[
  {
    "path": ".gitignore",
    "content": "*.log\n*.swp\n*.out\n*.dump\n*.log.*\n*.tmp\n*.rdb\n\n.DS_Store\n.htaccess\n\n/bin\n/tmp\n/pkg/utils/version.go\n\nmakefile\n"
  },
  {
    "path": ".travis.yml",
    "content": "language: go\n\nos:\n    - linux\n    - osx\n\ngo:\n    - 1.11.x\n    - 1.10.x\n    - 1.9.x\n    - 1.8.x\n\nscript:\n    - make\n    - make gotest\n\nbefore_deploy:\n    - export   DEPLOY_TARGET=codis${TRAVIS_TAG}-go${TRAVIS_GO_VERSION}-${TRAVIS_OS_NAME}\n    - mv bin ${DEPLOY_TARGET}\n    - zip -r ${DEPLOY_TARGET}.zip ${DEPLOY_TARGET} && tar -czvf ${DEPLOY_TARGET}.tar.gz ${DEPLOY_TARGET}\n\ndeploy:\n    provider: releases\n    overwrite: true\n    api_key:\n        secure: RKVkoCwNJej19d6KbgpxkwJ9H3bu0icS895G9BkaytUjRVO129S93L4xpHRfeIyySZNVrd4P/le01JIJ6/Fl89wKCc/5oX07aFo6l0w/+JKxSn33FsGh8pGTg5wt9Vm5aqccB6lbkylwKrvDUOwuJCbzMva8f1YrWv0a+3I6JKU=\n    file:\n        - ${DEPLOY_TARGET}.zip\n        - ${DEPLOY_TARGET}.tar.gz\n    skip_cleanup: true\n    on:\n        repo: CodisLabs/codis\n        tags: true\n        condition: $TRAVIS_GO_VERSION =~ ^1\\.(1[0-9]|[8-9])\\.[0-9]+$\n"
  },
  {
    "path": "Dockerfile",
    "content": "FROM golang:1.8\n\nRUN apt-get update\nRUN apt-get install -y autoconf\n\nENV GOPATH /gopath\nENV CODIS  ${GOPATH}/src/github.com/CodisLabs/codis\nENV PATH   ${GOPATH}/bin:${PATH}:${CODIS}/bin\nCOPY . ${CODIS}\n\nRUN make -C ${CODIS} distclean\nRUN make -C ${CODIS} build-all\n\nWORKDIR /codis\n"
  },
  {
    "path": "Godeps/Godeps.json",
    "content": "{\n\t\"ImportPath\": \"github.com/CodisLabs/codis\",\n\t\"GoVersion\": \"go1.8\",\n\t\"GodepVersion\": \"v79\",\n\t\"Packages\": [\n\t\t\"./...\"\n\t],\n\t\"Deps\": [\n\t\t{\n\t\t\t\"ImportPath\": \"github.com/BurntSushi/toml\",\n\t\t\t\"Comment\": \"v0.2.0-21-g9906417\",\n\t\t\t\"Rev\": \"99064174e013895bbd9b025c31100bd1d9b590ca\"\n\t\t},\n\t\t{\n\t\t\t\"ImportPath\": \"github.com/codegangsta/inject\",\n\t\t\t\"Comment\": \"v1.0-rc1-10-g33e0aa1\",\n\t\t\t\"Rev\": \"33e0aa1cb7c019ccc3fbe049a8262a6403d30504\"\n\t\t},\n\t\t{\n\t\t\t\"ImportPath\": \"github.com/coreos/etcd/client\",\n\t\t\t\"Comment\": \"v3.0.17\",\n\t\t\t\"Rev\": \"cc198e22d3b8fd7ec98304c95e68ee375be54589\"\n\t\t},\n\t\t{\n\t\t\t\"ImportPath\": \"github.com/coreos/etcd/pkg/pathutil\",\n\t\t\t\"Comment\": \"v3.0.17\",\n\t\t\t\"Rev\": \"cc198e22d3b8fd7ec98304c95e68ee375be54589\"\n\t\t},\n\t\t{\n\t\t\t\"ImportPath\": \"github.com/coreos/etcd/pkg/types\",\n\t\t\t\"Comment\": \"v3.0.17\",\n\t\t\t\"Rev\": \"cc198e22d3b8fd7ec98304c95e68ee375be54589\"\n\t\t},\n\t\t{\n\t\t\t\"ImportPath\": \"github.com/docopt/docopt-go\",\n\t\t\t\"Comment\": \"0.6.2\",\n\t\t\t\"Rev\": \"784ddc588536785e7299f7272f39101f7faccc3f\"\n\t\t},\n\t\t{\n\t\t\t\"ImportPath\": \"github.com/emirpasic/gods/containers\",\n\t\t\t\"Comment\": \"v1.9.0\",\n\t\t\t\"Rev\": \"f6c17b524822278a87e3b3bd809fec33b51f5b46\"\n\t\t},\n\t\t{\n\t\t\t\"ImportPath\": \"github.com/emirpasic/gods/trees\",\n\t\t\t\"Comment\": \"v1.9.0\",\n\t\t\t\"Rev\": \"f6c17b524822278a87e3b3bd809fec33b51f5b46\"\n\t\t},\n\t\t{\n\t\t\t\"ImportPath\": \"github.com/emirpasic/gods/trees/redblacktree\",\n\t\t\t\"Comment\": \"v1.9.0\",\n\t\t\t\"Rev\": \"f6c17b524822278a87e3b3bd809fec33b51f5b46\"\n\t\t},\n\t\t{\n\t\t\t\"ImportPath\": \"github.com/emirpasic/gods/utils\",\n\t\t\t\"Comment\": \"v1.9.0\",\n\t\t\t\"Rev\": \"f6c17b524822278a87e3b3bd809fec33b51f5b46\"\n\t\t},\n\t\t{\n\t\t\t\"ImportPath\": \"github.com/garyburd/redigo/internal\",\n\t\t\t\"Comment\": \"v1.0.0-20-g4854517\",\n\t\t\t\"Rev\": \"48545177e92ae3e7bcdbd50b42f7a139e6a268da\"\n\t\t},\n\t\t{\n\t\t\t\"ImportPath\": \"github.com/garyburd/redigo/redis\",\n\t\t\t\"Comment\": \"v1.0.0-20-g4854517\",\n\t\t\t\"Rev\": \"48545177e92ae3e7bcdbd50b42f7a139e6a268da\"\n\t\t},\n\t\t{\n\t\t\t\"ImportPath\": \"github.com/go-martini/martini\",\n\t\t\t\"Comment\": \"v1.0-186-gfe605b5\",\n\t\t\t\"Rev\": \"fe605b5cd210047ae3bb73d2b69a5b912a9b423d\"\n\t\t},\n\t\t{\n\t\t\t\"ImportPath\": \"github.com/influxdata/influxdb/client/v2\",\n\t\t\t\"Comment\": \"v1.1.0-223-g8c2cfd14a\",\n\t\t\t\"Rev\": \"8c2cfd14af2511580277ddfd7a834b6aaa5f19ab\"\n\t\t},\n\t\t{\n\t\t\t\"ImportPath\": \"github.com/influxdata/influxdb/models\",\n\t\t\t\"Comment\": \"v1.1.0-223-g8c2cfd14a\",\n\t\t\t\"Rev\": \"8c2cfd14af2511580277ddfd7a834b6aaa5f19ab\"\n\t\t},\n\t\t{\n\t\t\t\"ImportPath\": \"github.com/influxdata/influxdb/pkg/escape\",\n\t\t\t\"Comment\": \"v1.1.0-223-g8c2cfd14a\",\n\t\t\t\"Rev\": \"8c2cfd14af2511580277ddfd7a834b6aaa5f19ab\"\n\t\t},\n\t\t{\n\t\t\t\"ImportPath\": \"github.com/martini-contrib/binding\",\n\t\t\t\"Rev\": \"05d3e151b6cf34dacac6306226a33db68459a3b5\"\n\t\t},\n\t\t{\n\t\t\t\"ImportPath\": \"github.com/martini-contrib/gzip\",\n\t\t\t\"Rev\": \"6c035326b43f79aa18793d2f1db512d21253ea61\"\n\t\t},\n\t\t{\n\t\t\t\"ImportPath\": \"github.com/martini-contrib/render\",\n\t\t\t\"Rev\": \"ec18f8345a1181146728238980606fb1d6f40e8c\"\n\t\t},\n\t\t{\n\t\t\t\"ImportPath\": \"github.com/oxtoacart/bpool\",\n\t\t\t\"Rev\": \"4e1c5567d7c2dd59fa4c7c83d34c2f3528b025d6\"\n\t\t},\n\t\t{\n\t\t\t\"ImportPath\": \"github.com/samuel/go-zookeeper/zk\",\n\t\t\t\"Rev\": \"1d7be4effb13d2d908342d349d71a284a7542693\"\n\t\t},\n\t\t{\n\t\t\t\"ImportPath\": \"github.com/spinlock/jemalloc-go\",\n\t\t\t\"Rev\": \"26719b2ee6186ef794cd50b604f8d765d3be5a30\"\n\t\t},\n\t\t{\n\t\t\t\"ImportPath\": \"github.com/ugorji/go/codec\",\n\t\t\t\"Rev\": \"ded73eae5db7e7a0ef6f55aace87a2873c5d2b74\"\n\t\t},\n\t\t{\n\t\t\t\"ImportPath\": \"golang.org/x/net/context\",\n\t\t\t\"Rev\": \"242b6b35177ec3909636b6cf6a47e8c2c6324b5d\"\n\t\t},\n\t\t{\n\t\t\t\"ImportPath\": \"gopkg.in/alexcesaro/statsd.v2\",\n\t\t\t\"Comment\": \"v2.0.0\",\n\t\t\t\"Rev\": \"7fea3f0d2fab1ad973e641e51dba45443a311a90\"\n\t\t}\n\t]\n}\n"
  },
  {
    "path": "Godeps/Readme",
    "content": "This directory tree is generated automatically by godep.\n\nPlease do not edit.\n\nSee https://github.com/tools/godep for more information.\n"
  },
  {
    "path": "MIT-LICENSE.txt",
    "content": "The MIT License (MIT)\n\nCopyright (c) 2016 CodisLabs\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in\nall copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\nTHE SOFTWARE.\n"
  },
  {
    "path": "Makefile",
    "content": ".DEFAULT_GOAL := build-all\n\nexport GO15VENDOREXPERIMENT=1\n\nbuild-all: codis-server codis-dashboard codis-proxy codis-admin codis-ha codis-fe clean-gotest\n\ncodis-deps:\n\t@mkdir -p bin config && bash version\n\t@make --no-print-directory -C vendor/github.com/spinlock/jemalloc-go/\n\ncodis-dashboard: codis-deps\n\tgo build -i -o bin/codis-dashboard ./cmd/dashboard\n\t@./bin/codis-dashboard --default-config > config/dashboard.toml\n\ncodis-proxy: codis-deps\n\tgo build -i -tags \"cgo_jemalloc\" -o bin/codis-proxy ./cmd/proxy\n\t@./bin/codis-proxy --default-config > config/proxy.toml\n\ncodis-admin: codis-deps\n\tgo build -i -o bin/codis-admin ./cmd/admin\n\ncodis-ha: codis-deps\n\tgo build -i -o bin/codis-ha ./cmd/ha\n\ncodis-fe: codis-deps\n\tgo build -i -o bin/codis-fe ./cmd/fe\n\t@rm -rf bin/assets; cp -rf cmd/fe/assets bin/\n\ncodis-server:\n\t@mkdir -p bin\n\t@rm -f bin/codis-server*\n\tmake -j4 -C extern/redis-3.2.11/\n\t@cp -f extern/redis-3.2.11/src/redis-server  bin/codis-server\n\t@cp -f extern/redis-3.2.11/src/redis-benchmark bin/\n\t@cp -f extern/redis-3.2.11/src/redis-cli bin/\n\t@cp -f extern/redis-3.2.11/src/redis-sentinel bin/\n\t@cp -f extern/redis-3.2.11/redis.conf config/\n\t@sed -e \"s/^sentinel/# sentinel/g\" extern/redis-3.2.11/sentinel.conf > config/sentinel.conf\n\nclean-gotest:\n\t@rm -rf ./pkg/topom/gotest.tmp\n\nclean: clean-gotest\n\t@rm -rf bin\n\t@rm -rf scripts/tmp\n\ndistclean: clean\n\t@make --no-print-directory --quiet -C extern/redis-3.2.11 distclean\n\t@make --no-print-directory --quiet -C vendor/github.com/spinlock/jemalloc-go/ distclean\n\ngotest: codis-deps\n\tgo test ./cmd/... ./pkg/...\n\ngobench: codis-deps\n\tgo test -gcflags -l -bench=. -v ./pkg/...\n\ndocker:\n\tdocker build --force-rm -t codis-image .\n\ndemo:\n\tpushd example && make\n"
  },
  {
    "path": "README.md",
    "content": "<img src=\"doc/pictures/logo-3.png\" height=80></img>\n\n[![Gitter](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/CodisLabs/codis?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)\n[![Build Status](https://travis-ci.org/CodisLabs/codis.svg)](https://travis-ci.org/CodisLabs/codis)\n\nCodis is a proxy based high performance Redis cluster solution written in Go. It is production-ready and widely used at [wandoujia.com](http://wandoujia.com) and many companies. You can see [Codis Releases](https://github.com/CodisLabs/codis/releases) for latest and most stable realeases.\n\n## Donation\nDonate if you want to help us maintaining this project. Thank you!\n[See this issue for details](https://github.com/CodisLabs/codis/issues/976)\n\n## Compared with Twemproxy and Redis Cluster\n<table>\n<tr><th></th><th>Codis</th><th>Twemproxy</th><th>Redis Cluster</th></tr>\n<tr><td>resharding without restarting cluster</td><td>Yes</td><td>No</td><td>Yes</td></tr>\n<tr><td>pipeline</td><td>Yes</td><td>Yes</td><td>No</td></tr>\n<tr><td>hash tags for multi-key operations</td><td>Yes</td><td>Yes</td><td>Yes</td></tr>\n<tr><td>multi-key operations while resharding</td><td>Yes</td><td>-</td><td>No(<a href=\"http://redis.io/topics/cluster-spec#multiple-keys-operations\">details</a>)</td></tr>\n<tr><td>Redis clients supporting</td><td>Any clients</td><td>Any clients</td><td>Clients have to support cluster protocol</td></tr>\n</table>\n\"Resharding\" means migrating the data in one slot from one redis server to another, usually happens while increasing/decreasing the number of redis servers.\n\n## Other Features\n* GUI website dashboard & admin tools\n* Supports most of Redis commands, Fully compatible with Twemproxy(https://github.com/twitter/twemproxy)\n* Proxies can register on zk/etcd, clients can avoid dead proxies, see \"High Availability\" section.\n\n## Tutorial\n\n[简体中文](doc/tutorial_zh.md)\n[English (WIP) ](doc/tutorial_en.md)\n\n## FAQ\n\n[简体中文](doc/FAQ_zh.md)\n[English (WIP) ](FAQ_en.md)\n\n## High Availability\n\n[简体中文](doc/tutorial_zh.md#3-jodis-与-ha)\n[English (WIP) ](doc/tutorial_en.md#ha)\n\n## Architecture\n\n![architecture](doc/pictures/architecture.png)\n\n## Snapshots\n\nProxy\n![proxy](doc/pictures/snapshots1.png)\n\nSlots\n![slots](doc/pictures/snapshots2.png)\n\nGroup\n![group](doc/pictures/snapshots3.png)\n\nSentinel\n![sentinel](doc/pictures/snapshots4.png)\n\n## Benchmarks\n[See benchmark results](doc/benchmark.md)\n\n## Authors\n\nActive authors:\n* [@spinlock9](https://github.com/spinlock) [微博@斯宾洛克](http://weibo.com/spinlock9)\n* [@yangzhe1991](https://github.com/yangzhe1991) [微博@\\_杨肉\\_](http://weibo.com/yangzhe1991)\n\nEmeritus authors:\n* [@goroutine](https://github.com/ngaut) [微博@goroutine](http://weibo.com/u/1923497393)\n* [@c4pt0r](https://github.com/c4pt0r) [微博@Dongxu\\_Huang](http://weibo.com/c4pt0r)\n\nThanks:\n* [@ivanzhaowy](https://github.com/ivanzhaowy)\n* [@Apache9](https://github.com/apache9) [微博@Apache9](http://weibo.com/u/1876829375)\n\n## License\n\nCodis is licensed under MIT， see MIT-LICENSE.txt\n\n-------------\n*You are welcome to use Codis in your product, and feel free to let us know~ :)*\n"
  },
  {
    "path": "admin/codis-dashboard-admin.sh",
    "content": "#!/usr/bin/env bash\n\nCODIS_ADMIN=\"${BASH_SOURCE-$0}\"\nCODIS_ADMIN=\"$(dirname \"${CODIS_ADMIN}\")\"\nCODIS_ADMIN_DIR=\"$(cd \"${CODIS_ADMIN}\"; pwd)\"\n\nCODIS_BIN_DIR=$CODIS_ADMIN_DIR/../bin\nCODIS_LOG_DIR=$CODIS_ADMIN_DIR/../log\nCODIS_CONF_DIR=$CODIS_ADMIN_DIR/../config\n\nCODIS_DASHBOARD_BIN=$CODIS_BIN_DIR/codis-dashboard\nCODIS_ADMIN_TOOL_BIN=$CODIS_BIN_DIR/codis-admin\nCODIS_DASHBOARD_PID_FILE=$CODIS_BIN_DIR/codis-dashboard.pid\n\nCODIS_DASHBOARD_LOG_FILE=$CODIS_LOG_DIR/codis-dashboard.log\nCODIS_DASHBOARD_DAEMON_FILE=$CODIS_LOG_DIR/codis-dashboard.out\n\nCODIS_DASHBOARD_CONF_FILE=$CODIS_CONF_DIR/dashboard.toml\n\necho $CODIS_DASHBOARD_CONF_FILE\n\nif [ ! -d $CODIS_LOG_DIR ]; then\n    mkdir -p $CODIS_LOG_DIR\nfi\n\n\ncase $1 in\nstart)\n    echo  \"starting codis-dashboard ... \"\n    if [ -f \"$CODIS_DASHBOARD_PID_FILE\" ]; then\n      if kill -0 `cat \"$CODIS_DASHBOARD_PID_FILE\"` > /dev/null 2>&1; then\n         echo $command already running as process `cat \"$CODIS_DASHBOARD_PID_FILE\"`.\n         exit 0\n      fi\n    fi\n    nohup \"$CODIS_DASHBOARD_BIN\" \"--config=${CODIS_DASHBOARD_CONF_FILE}\" \\\n    \"--log=$CODIS_DASHBOARD_LOG_FILE\" \"--log-level=INFO\" \"--pidfile=$CODIS_DASHBOARD_PID_FILE\" > \"$CODIS_DASHBOARD_DAEMON_FILE\" 2>&1 < /dev/null &\n    ;;\nstart-foreground)\n    $CODIS_DASHBOARD_BIN \"--config=${CODIS_DASHBOARD_CONF_FILE}\" \\\n    \"--log-level=DEBUG\" \"--pidfile=$CODIS_DASHBOARD_PID_FILE\"\n    ;;\nstop)\n    echo \"stopping codis-dashboard ... \"\n    if [ ! -f \"$CODIS_DASHBOARD_PID_FILE\" ]\n    then\n      echo \"no codis-dashboard to stop (could not find file $CODIS_DASHBOARD_PID_FILE)\"\n    else\n      kill -2 $(cat \"$CODIS_DASHBOARD_PID_FILE\")\n      echo STOPPED\n    fi\n    exit 0\n    ;;\nstop-forced)\n    echo \"stopping codis-dashboard ... \"\n    if [ ! -f \"$CODIS_DASHBOARD_PID_FILE\" ]\n    then\n      echo \"no codis-dashboard to stop (could not find file $CODIS_DASHBOARD_PID_FILE)\"\n    else\n      kill -9 $(cat \"$CODIS_DASHBOARD_PID_FILE\")\n      rm \"$CODIS_DASHBOARD_PID_FILE\"\n      echo STOPPED\n    fi\n    exit 0\n    ;;\nrestart)\n    shift\n    \"$0\" stop\n    sleep 1\n    \"$0\" start\n    ;;\nremove-lock)\n    $CODIS_ADMIN_TOOL_BIN -v --remove-lock --product=codis-demo --zookeeper=127.0.0.1:2181\n    ;;\n*)\n    echo \"Usage: $0 {start|start-foreground|stop|stop-forced|restart|remove-lock}\" >&2\n\nesac\n"
  },
  {
    "path": "admin/codis-fe-admin.sh",
    "content": "#!/usr/bin/env bash\n\nCODIS_ADMIN=\"${BASH_SOURCE-$0}\"\nCODIS_ADMIN=\"$(dirname \"${CODIS_ADMIN}\")\"\nCODIS_ADMIN_DIR=\"$(cd \"${CODIS_ADMIN}\"; pwd)\"\n\nCODIS_BIN_DIR=$CODIS_ADMIN_DIR/../bin\nCODIS_LOG_DIR=$CODIS_ADMIN_DIR/../log\nCODIS_CONF_DIR=$CODIS_ADMIN_DIR/../config\n\nCODIS_FE_BIN=$CODIS_BIN_DIR/codis-fe\nCODIS_FE_PID_FILE=$CODIS_BIN_DIR/codis-fe.pid\nCODIS_FE_ASSETS_DIR=$CODIS_BIN_DIR/assets\n\nCODIS_FE_LOG_FILE=$CODIS_LOG_DIR/codis-fe.log\nCODIS_FE_DAEMON_FILE=$CODIS_LOG_DIR/codis-fe.out\n\nCOORDINATOR_NAME=\"filesystem\"\nCOORDINATOR_ADDR=\"/tmp/codis\"\nCODIS_FE_ADDR=\"0.0.0.0:9090\"\n\necho $CODIS_FE_CONF_FILE\n\nif [ ! -d $CODIS_LOG_DIR ]; then\n    mkdir -p $CODIS_LOG_DIR\nfi\n\n\ncase $1 in\nstart)\n    echo  \"starting codis-fe ... \"\n    if [ -f \"$CODIS_FE_PID_FILE\" ]; then\n      if kill -0 `cat \"$CODIS_FE_PID_FILE\"` > /dev/null 2>&1; then\n         echo $command already running as process `cat \"$CODIS_FE_PID_FILE\"`.\n         exit 0\n      fi\n    fi\n    nohup \"$CODIS_FE_BIN\" \"--assets-dir=${CODIS_FE_ASSETS_DIR}\" \"--$COORDINATOR_NAME=$COORDINATOR_ADDR\" \\\n    \"--log=$CODIS_FE_LOG_FILE\" \"--pidfile=$CODIS_FE_PID_FILE\" \"--log-level=INFO\" \"--listen=$CODIS_FE_ADDR\" > \"$CODIS_FE_DAEMON_FILE\" 2>&1 < /dev/null &\n    ;;\nstart-foreground)\n    $CODIS_FE_BIN \"--assets-dir=${CODIS_FE_ASSETS_DIR}\" \"--$COORDINATOR_NAME=$COORDINATOR_ADDR\" \\\n    \"--log-level=DEBUG\" \"--listen=$CODIS_FE_ADDR\"\n    ;;\nstop)\n    echo \"stopping codis-fe ... \"\n    if [ ! -f \"$CODIS_FE_PID_FILE\" ]\n    then\n      echo \"no codis-fe to stop (could not find file $CODIS_FE_PID_FILE)\"\n    else\n      kill -9 $(cat \"$CODIS_FE_PID_FILE\")\n      rm $CODIS_FE_PID_FILE\n      echo STOPPED\n    fi\n    exit 0\n    ;;\nrestart)\n    shift\n    \"$0\" stop\n    sleep 1\n    \"$0\" start\n    ;;\n*)\n    echo \"Usage: $0 {start|start-foreground|stop|restart}\" >&2\n\nesac\n"
  },
  {
    "path": "admin/codis-proxy-admin.sh",
    "content": "#!/usr/bin/env bash\n\nCODIS_ADMIN=\"${BASH_SOURCE-$0}\"\nCODIS_ADMIN=\"$(dirname \"${CODIS_ADMIN}\")\"\nCODIS_ADMIN_DIR=\"$(cd \"${CODIS_ADMIN}\"; pwd)\"\n\nCODIS_BIN_DIR=$CODIS_ADMIN_DIR/../bin\nCODIS_LOG_DIR=$CODIS_ADMIN_DIR/../log\nCODIS_CONF_DIR=$CODIS_ADMIN_DIR/../config\n\nCODIS_PROXY_BIN=$CODIS_BIN_DIR/codis-proxy\nCODIS_PROXY_PID_FILE=$CODIS_BIN_DIR/codis-proxy.pid\n\nCODIS_PROXY_LOG_FILE=$CODIS_LOG_DIR/codis-proxy.log\nCODIS_PROXY_DAEMON_FILE=$CODIS_LOG_DIR/codis-proxy.out\n\nCODIS_PROXY_CONF_FILE=$CODIS_CONF_DIR/proxy.toml\n\nCODIS_DASHBOARD_ADDR=\"127.0.0.1:18080\"\n\necho $CODIS_PROXY_CONF_FILE\n\nif [ ! -d $CODIS_LOG_DIR ]; then\n    mkdir -p $CODIS_LOG_DIR\nfi\n\n\ncase $1 in\nstart)\n    echo  \"starting codis-proxy ... \"\n    if [ -f \"$CODIS_PROXY_PID_FILE\" ]; then\n      if kill -0 `cat \"$CODIS_PROXY_PID_FILE\"` > /dev/null 2>&1; then\n         echo $command already running as process `cat \"$CODIS_PROXY_PID_FILE\"`.\n         exit 0\n      fi\n    fi\n    nohup \"$CODIS_PROXY_BIN\" \"--config=${CODIS_PROXY_CONF_FILE}\" \"--dashboard=${CODIS_DASHBOARD_ADDR}\" \\\n    \"--log=$CODIS_PROXY_LOG_FILE\" \"--log-level=INFO\" \"--ncpu=4\" \"--pidfile=$CODIS_PROXY_PID_FILE\" > \"$CODIS_PROXY_DAEMON_FILE\" 2>&1 < /dev/null &\n    ;;\nstart-foreground)\n    $CODIS_PROXY_BIN \"--config=${CODIS_PROXY_CONF_FILE}\" \"--dashboard=${CODIS_DASHBOARD_ADDR}\" \\\n    \"--log-level=DEBUG\" \"--pidfile=$CODIS_PROXY_PID_FILE\"\n    ;;\nstop)\n    echo \"stopping codis-proxy ... \"\n    if [ ! -f \"$CODIS_PROXY_PID_FILE\" ]\n    then\n      echo \"no codis-proxy to stop (could not find file $CODIS_PROXY_PID_FILE)\"\n    else\n      kill -2 $(cat \"$CODIS_PROXY_PID_FILE\")\n      echo STOPPED\n    fi\n    exit 0\n    ;;\nstop-forced)\n    echo \"stopping codis-proxy ... \"\n    if [ ! -f \"$CODIS_PROXY_PID_FILE\" ]\n    then\n      echo \"no codis-proxy to stop (could not find file $CODIS_PROXY_PID_FILE)\"\n    else\n      kill -9 $(cat \"$CODIS_PROXY_PID_FILE\")\n      rm \"$CODIS_PROXY_PID_FILE\"\n      echo STOPPED\n    fi\n    exit 0\n    ;;\nrestart)\n    shift\n    \"$0\" stop\n    sleep 1\n    \"$0\" start\n    ;;\n*)\n    echo \"Usage: $0 {start|start-foreground|stop|stop-forced|restart}\" >&2\n\nesac\n"
  },
  {
    "path": "admin/codis-server-admin.sh",
    "content": "#!/usr/bin/env bash\n\nCODIS_ADMIN=\"${BASH_SOURCE-$0}\"\nCODIS_ADMIN=\"$(dirname \"${CODIS_ADMIN}\")\"\nCODIS_ADMIN_DIR=\"$(cd \"${CODIS_ADMIN}\"; pwd)\"\n\nCODIS_BIN_DIR=$CODIS_ADMIN_DIR/../bin\nCODIS_LOG_DIR=$CODIS_ADMIN_DIR/../log\nCODIS_CONF_DIR=$CODIS_ADMIN_DIR/../config\n\nCODIS_SERVER_BIN=$CODIS_BIN_DIR/codis-server\nCODIS_SERVER_PID_FILE=/tmp/redis_6379.pid\n\nCODIS_SERVER_LOG_FILE=/tmp/redis_6379.log\nCODIS_SERVER_DAEMON_FILE=$CODIS_LOG_DIR/codis-server.out\n\nCODIS_SERVER_CONF_FILE=$CODIS_CONF_DIR/redis.conf\n\necho $CODIS_SERVER_CONF_FILE\n\nif [ ! -d $CODIS_LOG_DIR ]; then\n    mkdir -p $CODIS_LOG_DIR\nfi\n\n\ncase $1 in\nstart)\n    echo  \"starting codis-server ... \"\n    if [ -f \"$CODIS_SERVER_PID_FILE\" ]; then\n      if kill -0 `cat \"$CODIS_SERVER_PID_FILE\"` > /dev/null 2>&1; then\n         echo $command already running as process `cat \"$CODIS_SERVER_PID_FILE\"`.\n         exit 0\n      fi\n    fi\n    nohup \"$CODIS_SERVER_BIN\" \"${CODIS_SERVER_CONF_FILE}\" > \"$CODIS_SERVER_DAEMON_FILE\" 2>&1 < /dev/null &\n    ;;\nstop)\n    echo \"stopping codis-server ... \"\n    if [ ! -f \"$CODIS_SERVER_PID_FILE\" ]\n    then\n      echo \"no codis-server to stop (could not find file $CODIS_SERVER_PID_FILE)\"\n    else\n      kill -2 $(cat \"$CODIS_SERVER_PID_FILE\")\n      echo STOPPED\n    fi\n    exit 0\n    ;;\nstop-forced)\n    echo \"stopping codis-server ... \"\n    if [ ! -f \"$CODIS_SERVER_PID_FILE\" ]\n    then\n      echo \"no codis-server to stop (could not find file $CODIS_SERVER_PID_FILE)\"\n    else\n      kill -9 $(cat \"$CODIS_SERVER_PID_FILE\")\n      rm \"$CODIS_SERVER_PID_FILE\"\n      echo STOPPED\n    fi\n    exit 0\n    ;;\nrestart)\n    shift\n    \"$0\" stop\n    sleep 1\n    \"$0\" start\n    ;;\n*)\n    echo \"Usage: $0 {start|stop|stop-forced|restart}\" >&2\n\nesac\n"
  },
  {
    "path": "ansible/group_vars/all",
    "content": "---\ncodis_dir: /home/codis/codis\n\ncoordinator_name: filesystem\n\ncoordinator_addr: /tmp/codis\n\ncodis_install_dir: /data/codis-vip\n\nproduct_name: codis-demo\n\nproduct_auth: test\n\ndashboard_addr: 127.0.0.1:18080\n\nproxy_addr: 127.0.0.1:19000\n\nproxy_admin_addr: 127.0.0.1:11080\n\ncodis_server_workdir: /data/redis-6379\n\ncodis_server_port: 6379\n\nredis_sentinel_workdir: /data/sentinel-26379\n\nredis_sentinel_port: 26379\n"
  },
  {
    "path": "ansible/hosts",
    "content": "[codis-dashboard-servers]\n127.0.0.1\n[codis-proxy-servers]\n127.0.0.1\n[codis-servers]\n127.0.0.1\n[codis-fe-servers]\n127.0.0.1\n[redis-sentinel-servers]\n127.0.0.1\n"
  },
  {
    "path": "ansible/roles/codis-dashboard/tasks/main.yml",
    "content": "---\n- name: Copy codis-admin binary\n  copy: src={{ codis_dir }}/bin/codis-admin dest={{ codis_install_dir }}/bin/codis-admin mode=766\n\n- name: Copy codis-dashboard binary\n  copy: src={{ codis_dir }}/bin/codis-dashboard dest={{ codis_install_dir }}/bin/codis-dashboard mode=766\n\n- name: Copy codis-dashboard configuration\n  template: src=dashboard.toml dest={{ codis_install_dir }}/config/dashboard.toml\n\n- name: Copy codis-dashboard admin script\n  template: src=codis-dashboard-admin.sh dest={{ codis_install_dir }}/admin/codis-dashboard-admin.sh mode=766\n\n- name: Restart codis-dashboard service\n  command: \"{{ codis_install_dir }}/admin/codis-dashboard-admin.sh restart\"\n"
  },
  {
    "path": "ansible/roles/codis-dashboard/templates/codis-dashboard-admin.sh",
    "content": "#!/usr/bin/env bash\n\nCODIS_ADMIN=\"${BASH_SOURCE-$0}\"\nCODIS_ADMIN=\"$(dirname \"${CODIS_ADMIN}\")\"\nCODIS_ADMIN_DIR=\"$(cd \"${CODIS_ADMIN}\"; pwd)\"\n\nCODIS_BIN_DIR=$CODIS_ADMIN_DIR/../bin\nCODIS_LOG_DIR=$CODIS_ADMIN_DIR/../log\nCODIS_CONF_DIR=$CODIS_ADMIN_DIR/../config\n\nCODIS_DASHBOARD_BIN=$CODIS_BIN_DIR/codis-dashboard\nCODIS_ADMIN_TOOL_BIN=$CODIS_BIN_DIR/codis-admin\nCODIS_DASHBOARD_PID_FILE=$CODIS_BIN_DIR/codis-dashboard.pid\n\nCODIS_DASHBOARD_LOG_FILE=$CODIS_LOG_DIR/codis-dashboard.log\nCODIS_DASHBOARD_DAEMON_FILE=$CODIS_LOG_DIR/codis-dashboard.out\n\nCODIS_DASHBOARD_CONF_FILE=$CODIS_CONF_DIR/dashboard.toml\n\necho $CODIS_DASHBOARD_CONF_FILE\n\nif [ ! -d $CODIS_LOG_DIR ]; then\n    mkdir -p $CODIS_LOG_DIR\nfi\n\n\ncase $1 in\nstart)\n    echo  \"starting codis-dashboard ... \"\n    if [ -f \"$CODIS_DASHBOARD_PID_FILE\" ]; then\n      if kill -0 `cat \"$CODIS_DASHBOARD_PID_FILE\"` > /dev/null 2>&1; then\n         echo $command already running as process `cat \"$CODIS_DASHBOARD_PID_FILE\"`.\n         exit 0\n      fi\n    fi\n    nohup \"$CODIS_DASHBOARD_BIN\" \"--config=${CODIS_DASHBOARD_CONF_FILE}\" \\\n    \"--log=$CODIS_DASHBOARD_LOG_FILE\" \"--log-level=INFO\" \"--pidfile=$CODIS_DASHBOARD_PID_FILE\" > \"$CODIS_DASHBOARD_DAEMON_FILE\" 2>&1 < /dev/null &\n    ;;\nstart-foreground)\n    $CODIS_DASHBOARD_BIN \"--config=${CODIS_DASHBOARD_CONF_FILE}\" \\\n    \"--log-level=DEBUG\" \"--pidfile=$CODIS_DASHBOARD_PID_FILE\"\n    ;;\nstop)\n    echo \"stopping codis-dashboard ... \"\n    if [ ! -f \"$CODIS_DASHBOARD_PID_FILE\" ]\n    then\n      echo \"no codis-dashboard to stop (could not find file $CODIS_DASHBOARD_PID_FILE)\"\n    else\n      kill -2 $(cat \"$CODIS_DASHBOARD_PID_FILE\")\n      echo STOPPED\n    fi\n    exit 0\n    ;;\nstop-forced)\n    echo \"stopping codis-dashboard ... \"\n    if [ ! -f \"$CODIS_DASHBOARD_PID_FILE\" ]\n    then\n      echo \"no codis-dashboard to stop (could not find file $CODIS_DASHBOARD_PID_FILE)\"\n    else\n      kill -9 $(cat \"$CODIS_DASHBOARD_PID_FILE\")\n      rm \"$CODIS_DASHBOARD_PID_FILE\"\n      echo STOPPED\n    fi\n    exit 0\n    ;;\nrestart)\n    shift\n    \"$0\" stop\n    sleep 1\n    \"$0\" start\n    ;;\nremove-lock)\n    $CODIS_ADMIN_TOOL_BIN -v --remove-lock --product={{ product_name }} --{{ coordinator_name }}={{ coordinator_addr }}\n    ;;\n*)\n    echo \"Usage: $0 {start|start-foreground|stop|stop-forced|restart|remove-lock}\" >&2\n\nesac\n"
  },
  {
    "path": "ansible/roles/codis-dashboard/templates/dashboard.toml",
    "content": "\n##################################################\n#                                                #\n#                  Codis-Dashboard               #\n#                                                #\n##################################################\n\n# Set Coordinator, only accept \"zookeeper\" & \"etcd\" & \"filesystem\".\n# Quick Start\ncoordinator_name = \"{{ coordinator_name }}\"\ncoordinator_addr = \"{{ coordinator_addr }}\"\n#coordinator_name = \"zookeeper\"\n#coordinator_addr = \"127.0.0.1:2181\"\n\n# Set Codis Product Name/Auth.\nproduct_name = \"{{ product_name }}\"\nproduct_auth = \"{{ product_auth }}\"\n\n# Set bind address for admin(rpc), tcp only.\nadmin_addr = \"{{ dashboard_addr }}\"\n\n# Set arguments for data migration (only accept 'sync' & 'semi-async').\nmigration_method = \"semi-async\"\nmigration_parallel_slots = 100\nmigration_async_maxbulks = 200\nmigration_async_maxbytes = \"32mb\"\nmigration_async_numkeys = 500\nmigration_timeout = \"30s\"\n\n# Set configs for redis sentinel.\nsentinel_quorum = 2\nsentinel_parallel_syncs = 1\nsentinel_down_after = \"30s\"\nsentinel_failover_timeout = \"5m\"\nsentinel_notification_script = \"\"\nsentinel_client_reconfig_script = \"\"\n\n"
  },
  {
    "path": "ansible/roles/codis-fe/tasks/main.yml",
    "content": "---\n- name: Copy codis-fe binary\n  copy: src={{ codis_dir }}/bin/codis-fe dest={{ codis_install_dir }}/bin/codis-fe mode=766\n\n- name: Copy codis-fe assets\n  copy: src={{ codis_dir }}/bin/assets dest={{ codis_install_dir }}/bin\n\n- name: Copy codis-fe admin script\n  template: src=codis-fe-admin.sh dest={{ codis_install_dir }}/admin/codis-fe-admin.sh mode=766\n\n- name: Restart codis-fe service\n  command: \"{{ codis_install_dir }}/admin/codis-fe-admin.sh restart\"\n"
  },
  {
    "path": "ansible/roles/codis-fe/templates/codis-fe-admin.sh",
    "content": "#!/usr/bin/env bash\n\nCODIS_ADMIN=\"${BASH_SOURCE-$0}\"\nCODIS_ADMIN=\"$(dirname \"${CODIS_ADMIN}\")\"\nCODIS_ADMIN_DIR=\"$(cd \"${CODIS_ADMIN}\"; pwd)\"\n\nCODIS_BIN_DIR=$CODIS_ADMIN_DIR/../bin\nCODIS_LOG_DIR=$CODIS_ADMIN_DIR/../log\nCODIS_CONF_DIR=$CODIS_ADMIN_DIR/../config\n\nCODIS_FE_BIN=$CODIS_BIN_DIR/codis-fe\nCODIS_FE_PID_FILE=$CODIS_BIN_DIR/codis-fe.pid\nCODIS_FE_ASSETS_DIR=$CODIS_BIN_DIR/assets\n\nCODIS_FE_LOG_FILE=$CODIS_LOG_DIR/codis-fe.log\nCODIS_FE_DAEMON_FILE=$CODIS_LOG_DIR/codis-fe.out\n\nCOORDINATOR_NAME=\"{{ coordinator_name }}\"\nCOORDINATOR_ADDR=\"{{ coordinator_addr }}\"\nCODIS_FE_ADDR=\"0.0.0.0:9090\"\n\necho $CODIS_FE_CONF_FILE\n\nif [ ! -d $CODIS_LOG_DIR ]; then\n    mkdir -p $CODIS_LOG_DIR\nfi\n\n\ncase $1 in\nstart)\n    echo  \"starting codis-fe ... \"\n    if [ -f \"$CODIS_FE_PID_FILE\" ]; then\n      if kill -0 `cat \"$CODIS_FE_PID_FILE\"` > /dev/null 2>&1; then\n         echo $command already running as process `cat \"$CODIS_FE_PID_FILE\"`.\n         exit 0\n      fi\n    fi\n    nohup \"$CODIS_FE_BIN\" \"--assets-dir=${CODIS_FE_ASSETS_DIR}\" \"--$COORDINATOR_NAME=$COORDINATOR_ADDR\" \\\n    \"--log=$CODIS_FE_LOG_FILE\" \"--pidfile=$CODIS_FE_PID_FILE\" \"--log-level=INFO\" \"--listen=$CODIS_FE_ADDR\" > \"$CODIS_FE_DAEMON_FILE\" 2>&1 < /dev/null &\n    ;;\nstart-foreground)\n    $CODIS_FE_BIN \"--assets-dir=${CODIS_FE_ASSETS_DIR}\" \"--$COORDINATOR_NAME=$COORDINATOR_ADDR\" \\\n    \"--log-level=DEBUG\" \"--listen=$CODIS_FE_ADDR\"\n    ;;\nstop)\n    echo \"stopping codis-fe ... \"\n    if [ ! -f \"$CODIS_FE_PID_FILE\" ]\n    then\n      echo \"no codis-fe to stop (could not find file $CODIS_FE_PID_FILE)\"\n    else\n      kill -9 $(cat \"$CODIS_FE_PID_FILE\")\n      rm $CODIS_FE_PID_FILE\n      echo STOPPED\n    fi\n    exit 0\n    ;;\nrestart)\n    shift\n    \"$0\" stop\n    sleep 1\n    \"$0\" start\n    ;;\n*)\n    echo \"Usage: $0 {start|start-foreground|stop|restart}\" >&2\n\nesac\n"
  },
  {
    "path": "ansible/roles/codis-proxy/tasks/main.yml",
    "content": "---\n- name: Copy codis-proxy binary\n  copy: src={{ codis_dir }}/bin/codis-proxy dest={{ codis_install_dir }}/bin/codis-proxy mode=766\n\n- name: Copy codis-proxy configuration\n  template: src=proxy.toml dest={{ codis_install_dir }}/config/proxy.toml\n\n- name: Copy codis-proxy admin script\n  template: src=codis-proxy-admin.sh dest={{ codis_install_dir }}/admin/codis-proxy-admin.sh mode=766\n\n- name: Restart codis-proxy service\n  command: \"{{ codis_install_dir }}/admin/codis-proxy-admin.sh restart\"\n"
  },
  {
    "path": "ansible/roles/codis-proxy/templates/codis-proxy-admin.sh",
    "content": "#!/usr/bin/env bash\n\nCODIS_ADMIN=\"${BASH_SOURCE-$0}\"\nCODIS_ADMIN=\"$(dirname \"${CODIS_ADMIN}\")\"\nCODIS_ADMIN_DIR=\"$(cd \"${CODIS_ADMIN}\"; pwd)\"\n\nCODIS_BIN_DIR=$CODIS_ADMIN_DIR/../bin\nCODIS_LOG_DIR=$CODIS_ADMIN_DIR/../log\nCODIS_CONF_DIR=$CODIS_ADMIN_DIR/../config\n\nCODIS_PROXY_BIN=$CODIS_BIN_DIR/codis-proxy\nCODIS_PROXY_PID_FILE=$CODIS_BIN_DIR/codis-proxy.pid\n\nCODIS_PROXY_LOG_FILE=$CODIS_LOG_DIR/codis-proxy.log\nCODIS_PROXY_DAEMON_FILE=$CODIS_LOG_DIR/codis-proxy.out\n\nCODIS_PROXY_CONF_FILE=$CODIS_CONF_DIR/proxy.toml\n\nCODIS_DASHBOARD_ADDR=\"{{ dashboard_addr }}\"\n\necho $CODIS_PROXY_CONF_FILE\n\nif [ ! -d $CODIS_LOG_DIR ]; then\n    mkdir -p $CODIS_LOG_DIR\nfi\n\n\ncase $1 in\nstart)\n    echo  \"starting codis-proxy ... \"\n    if [ -f \"$CODIS_PROXY_PID_FILE\" ]; then\n      if kill -0 `cat \"$CODIS_PROXY_PID_FILE\"` > /dev/null 2>&1; then\n         echo $command already running as process `cat \"$CODIS_PROXY_PID_FILE\"`.\n         exit 0\n      fi\n    fi\n    nohup \"$CODIS_PROXY_BIN\" \"--config=${CODIS_PROXY_CONF_FILE}\" \"--dashboard=${CODIS_DASHBOARD_ADDR}\" \\\n    \"--log=$CODIS_PROXY_LOG_FILE\" \"--log-level=INFO\" \"--ncpu=4\" \"--pidfile=$CODIS_PROXY_PID_FILE\" > \"$CODIS_PROXY_DAEMON_FILE\" 2>&1 < /dev/null &\n    ;;\nstart-foreground)\n    $CODIS_PROXY_BIN \"--config=${CODIS_PROXY_CONF_FILE}\" \"--dashboard=${CODIS_DASHBOARD_ADDR}\" \\\n    \"--log-level=DEBUG\" \"--pidfile=$CODIS_PROXY_PID_FILE\"\n    ;;\nstop)\n    echo \"stopping codis-proxy ... \"\n    if [ ! -f \"$CODIS_PROXY_PID_FILE\" ]\n    then\n      echo \"no codis-proxy to stop (could not find file $CODIS_PROXY_PID_FILE)\"\n    else\n      kill -2 $(cat \"$CODIS_PROXY_PID_FILE\")\n      echo STOPPED\n    fi\n    exit 0\n    ;;\nstop-forced)\n    echo \"stopping codis-proxy ... \"\n    if [ ! -f \"$CODIS_PROXY_PID_FILE\" ]\n    then\n      echo \"no codis-proxy to stop (could not find file $CODIS_PROXY_PID_FILE)\"\n    else\n      kill -9 $(cat \"$CODIS_PROXY_PID_FILE\")\n      rm \"$CODIS_PROXY_PID_FILE\"\n      echo STOPPED\n    fi\n    exit 0\n    ;;\nrestart)\n    shift\n    \"$0\" stop\n    sleep 1\n    \"$0\" start\n    ;;\n*)\n    echo \"Usage: $0 {start|start-foreground|stop|stop-forced|restart}\" >&2\n\nesac\n"
  },
  {
    "path": "ansible/roles/codis-proxy/templates/proxy.toml",
    "content": "\n##################################################\n#                                                #\n#                  Codis-Proxy                   #\n#                                                #\n##################################################\n\n# Set Codis Product Name/Auth.\nproduct_name = \"{{ product_name }}\"\nproduct_auth = \"{{ product_auth }}\"\n\n# Set bind address for admin(rpc), tcp only.\nadmin_addr = \"{{ proxy_admin_addr }}\"\n\n# Set bind address for proxy, proto_type can be \"tcp\", \"tcp4\", \"tcp6\", \"unix\" or \"unixpacket\".\nproto_type = \"tcp4\"\nproxy_addr = \"{{ proxy_addr }}\"\n\n# Set jodis address & session timeout\n#   1. jodis_name is short for jodis_coordinator_name, only accept \"zookeeper\" & \"etcd\".\n#   2. jodis_addr is short for jodis_coordinator_addr\n#   3. proxy will be registered as node:\n#        if jodis_compatible = true (not suggested):\n#          /zk/codis/db_{PRODUCT_NAME}/proxy-{HASHID} (compatible with Codis2.0)\n#        or else\n#          /jodis/{PRODUCT_NAME}/proxy-{HASHID}\njodis_name = \"\"\njodis_addr = \"\"\njodis_timeout = \"20s\"\njodis_compatible = false\n\n# Set datacenter of proxy.\nproxy_datacenter = \"\"\n\n# Set max number of alive sessions.\nproxy_max_clients = 1000\n\n# Set max offheap memory size. (0 to disable)\nproxy_max_offheap_size = \"1024mb\"\n\n# Set heap placeholder to reduce GC frequency.\nproxy_heap_placeholder = \"256mb\"\n\n# Proxy will ping backend redis (and clear 'MASTERDOWN' state) in a predefined interval. (0 to disable)\nbackend_ping_period = \"5s\"\n\n# Set backend recv buffer size & timeout.\nbackend_recv_bufsize = \"128kb\"\nbackend_recv_timeout = \"30s\"\n\n# Set backend send buffer & timeout.\nbackend_send_bufsize = \"128kb\"\nbackend_send_timeout = \"30s\"\n\n# Set backend pipeline buffer size.\nbackend_max_pipeline = 1024\n\n# Set backend never read replica groups, default is false\nbackend_primary_only = false\n\n# Set backend parallel connections per server\nbackend_primary_parallel = 1\nbackend_replica_parallel = 1\n\n# Set backend tcp keepalive period. (0 to disable)\nbackend_keepalive_period = \"75s\"\n\n# Set number of databases of backend.\nbackend_number_databases = 16\n\n# If there is no request from client for a long time, the connection will be closed. (0 to disable)\n# Set session recv buffer size & timeout.\nsession_recv_bufsize = \"128kb\"\nsession_recv_timeout = \"30m\"\n\n# Set session send buffer size & timeout.\nsession_send_bufsize = \"64kb\"\nsession_send_timeout = \"30s\"\n\n# Make sure this is higher than the max number of requests for each pipeline request, or your client may be blocked.\n# Set session pipeline buffer size.\nsession_max_pipeline = 10000\n\n# Set session tcp keepalive period. (0 to disable)\nsession_keepalive_period = \"75s\"\n\n# Set session to be sensitive to failures. Default is false, instead of closing socket, proxy will send an error response to client.\nsession_break_on_failure = false\n\n# Set metrics server (such as http://localhost:28000), proxy will report json formatted metrics to specified server in a predefined period.\nmetrics_report_server = \"\"\nmetrics_report_period = \"1s\"\n\n# Set influxdb server (such as http://localhost:8086), proxy will report metrics to influxdb.\nmetrics_report_influxdb_server = \"\"\nmetrics_report_influxdb_period = \"1s\"\nmetrics_report_influxdb_username = \"\"\nmetrics_report_influxdb_password = \"\"\nmetrics_report_influxdb_database = \"\"\n\n# Set statsd server (such as localhost:8125), proxy will report metrics to statsd.\nmetrics_report_statsd_server = \"\"\nmetrics_report_statsd_period = \"1s\"\nmetrics_report_statsd_prefix = \"\"\n\n"
  },
  {
    "path": "ansible/roles/codis-server/tasks/main.yml",
    "content": "---\n- name: Create codis server work directory\n  file: path={{ codis_server_workdir }} state=directory owner=codis group=codis\n\n- name: Copy codis-server binary\n  copy: src={{ codis_dir }}/bin/codis-server dest={{ codis_install_dir }}/bin/codis-server mode=766\n\n- name: Copy codis-server configuration\n  template: src=redis.conf dest={{ codis_install_dir }}/config/redis.conf\n\n- name: Copy codis-server admin script\n  template: src=codis-server-admin.sh dest={{ codis_install_dir }}/admin/codis-server-admin.sh mode=766\n\n- name: Restart codis-server service\n  command: \"{{ codis_install_dir }}/admin/codis-server-admin.sh restart\"\n"
  },
  {
    "path": "ansible/roles/codis-server/templates/codis-server-admin.sh",
    "content": "#!/usr/bin/env bash\n\nCODIS_ADMIN=\"${BASH_SOURCE-$0}\"\nCODIS_ADMIN=\"$(dirname \"${CODIS_ADMIN}\")\"\nCODIS_ADMIN_DIR=\"$(cd \"${CODIS_ADMIN}\"; pwd)\"\n\nCODIS_BIN_DIR=$CODIS_ADMIN_DIR/../bin\nCODIS_LOG_DIR=$CODIS_ADMIN_DIR/../log\nCODIS_CONF_DIR=$CODIS_ADMIN_DIR/../config\n\nCODIS_SERVER_BIN=$CODIS_BIN_DIR/codis-server\nCODIS_SERVER_PID_FILE={{ codis_server_workdir }}/redis_{{ codis_server_port }}.pid\n\nCODIS_SERVER_LOG_FILE={{ codis_server_workdir }}/redis_{{ codis_server_port }}.log\nCODIS_SERVER_DAEMON_FILE=$CODIS_LOG_DIR/codis-server.out\n\nCODIS_SERVER_CONF_FILE=$CODIS_CONF_DIR/redis.conf\n\necho $CODIS_SERVER_CONF_FILE\n\nif [ ! -d $CODIS_LOG_DIR ]; then\n    mkdir -p $CODIS_LOG_DIR\nfi\n\n\ncase $1 in\nstart)\n    echo  \"starting codis-server ... \"\n    if [ -f \"$CODIS_SERVER_PID_FILE\" ]; then\n      if kill -0 `cat \"$CODIS_SERVER_PID_FILE\"` > /dev/null 2>&1; then\n         echo $command already running as process `cat \"$CODIS_SERVER_PID_FILE\"`.\n         exit 0\n      fi\n    fi\n    nohup \"$CODIS_SERVER_BIN\" \"${CODIS_SERVER_CONF_FILE}\" > \"$CODIS_SERVER_DAEMON_FILE\" 2>&1 < /dev/null &\n    ;;\nstop)\n    echo \"stopping codis-server ... \"\n    if [ ! -f \"$CODIS_SERVER_PID_FILE\" ]\n    then\n      echo \"no codis-server to stop (could not find file $CODIS_SERVER_PID_FILE)\"\n    else\n      kill -2 $(cat \"$CODIS_SERVER_PID_FILE\")\n      echo STOPPED\n    fi\n    exit 0\n    ;;\nstop-forced)\n    echo \"stopping codis-server ... \"\n    if [ ! -f \"$CODIS_SERVER_PID_FILE\" ]\n    then\n      echo \"no codis-server to stop (could not find file $CODIS_SERVER_PID_FILE)\"\n    else\n      kill -9 $(cat \"$CODIS_SERVER_PID_FILE\")\n      rm \"$CODIS_SERVER_PID_FILE\"\n      echo STOPPED\n    fi\n    exit 0\n    ;;\nrestart)\n    shift\n    \"$0\" stop\n    sleep 1\n    \"$0\" start\n    ;;\n*)\n    echo \"Usage: $0 {start|stop|stop-forced|restart}\" >&2\n\nesac\n"
  },
  {
    "path": "ansible/roles/codis-server/templates/redis.conf",
    "content": "# Redis configuration file example.\n#\n# Note that in order to read the configuration file, Redis must be\n# started with the file path as first argument:\n#\n# ./redis-server /path/to/redis.conf\n\n# Note on units: when memory size is needed, it is possible to specify\n# it in the usual form of 1k 5GB 4M and so forth:\n#\n# 1k => 1000 bytes\n# 1kb => 1024 bytes\n# 1m => 1000000 bytes\n# 1mb => 1024*1024 bytes\n# 1g => 1000000000 bytes\n# 1gb => 1024*1024*1024 bytes\n#\n# units are case insensitive so 1GB 1Gb 1gB are all the same.\n\n################################## INCLUDES ###################################\n\n# Include one or more other config files here.  This is useful if you\n# have a standard template that goes to all Redis servers but also need\n# to customize a few per-server settings.  Include files can include\n# other files, so use this wisely.\n#\n# Notice option \"include\" won't be rewritten by command \"CONFIG REWRITE\"\n# from admin or Redis Sentinel. Since Redis always uses the last processed\n# line as value of a configuration directive, you'd better put includes\n# at the beginning of this file to avoid overwriting config change at runtime.\n#\n# If instead you are interested in using includes to override configuration\n# options, it is better to use include as the last line.\n#\n# include /path/to/local.conf\n# include /path/to/other.conf\n\n################################## NETWORK #####################################\n\n# By default, if no \"bind\" configuration directive is specified, Redis listens\n# for connections from all the network interfaces available on the server.\n# It is possible to listen to just one or multiple selected interfaces using\n# the \"bind\" configuration directive, followed by one or more IP addresses.\n#\n# Examples:\n#\n# bind 192.168.1.100 10.0.0.1\n# bind 127.0.0.1 ::1\n#\n# ~~~ WARNING ~~~ If the computer running Redis is directly exposed to the\n# internet, binding to all the interfaces is dangerous and will expose the\n# instance to everybody on the internet. So by default we uncomment the\n# following bind directive, that will force Redis to listen only into\n# the IPv4 lookback interface address (this means Redis will be able to\n# accept connections only from clients running into the same computer it\n# is running).\n#\n# IF YOU ARE SURE YOU WANT YOUR INSTANCE TO LISTEN TO ALL THE INTERFACES\n# JUST COMMENT THE FOLLOWING LINE.\n# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\nbind 127.0.0.1\n\n# Protected mode is a layer of security protection, in order to avoid that\n# Redis instances left open on the internet are accessed and exploited.\n#\n# When protected mode is on and if:\n#\n# 1) The server is not binding explicitly to a set of addresses using the\n#    \"bind\" directive.\n# 2) No password is configured.\n#\n# The server only accepts connections from clients connecting from the\n# IPv4 and IPv6 loopback addresses 127.0.0.1 and ::1, and from Unix domain\n# sockets.\n#\n# By default protected mode is enabled. You should disable it only if\n# you are sure you want clients from other hosts to connect to Redis\n# even if no authentication is configured, nor a specific set of interfaces\n# are explicitly listed using the \"bind\" directive.\nprotected-mode yes\n\n# Accept connections on the specified port, default is 6379 (IANA #815344).\n# If port 0 is specified Redis will not listen on a TCP socket.\nport {{ codis_server_port }}\n\n# TCP listen() backlog.\n#\n# In high requests-per-second environments you need an high backlog in order\n# to avoid slow clients connections issues. Note that the Linux kernel\n# will silently truncate it to the value of /proc/sys/net/core/somaxconn so\n# make sure to raise both the value of somaxconn and tcp_max_syn_backlog\n# in order to get the desired effect.\ntcp-backlog 511\n\n# Unix socket.\n#\n# Specify the path for the Unix socket that will be used to listen for\n# incoming connections. There is no default, so Redis will not listen\n# on a unix socket when not specified.\n#\n# unixsocket /tmp/redis.sock\n# unixsocketperm 700\n\n# Close the connection after a client is idle for N seconds (0 to disable)\ntimeout 0\n\n# TCP keepalive.\n#\n# If non-zero, use SO_KEEPALIVE to send TCP ACKs to clients in absence\n# of communication. This is useful for two reasons:\n#\n# 1) Detect dead peers.\n# 2) Take the connection alive from the point of view of network\n#    equipment in the middle.\n#\n# On Linux, the specified value (in seconds) is the period used to send ACKs.\n# Note that to close the connection the double of the time is needed.\n# On other kernels the period depends on the kernel configuration.\n#\n# A reasonable value for this option is 300 seconds, which is the new\n# Redis default starting with Redis 3.2.1.\ntcp-keepalive 300\n\n################################# GENERAL #####################################\n\n# By default Redis does not run as a daemon. Use 'yes' if you need it.\n# Note that Redis will write a pid file in /var/run/redis.pid when daemonized.\ndaemonize yes\n\n# If you run Redis from upstart or systemd, Redis can interact with your\n# supervision tree. Options:\n#   supervised no      - no supervision interaction\n#   supervised upstart - signal upstart by putting Redis into SIGSTOP mode\n#   supervised systemd - signal systemd by writing READY=1 to $NOTIFY_SOCKET\n#   supervised auto    - detect upstart or systemd method based on\n#                        UPSTART_JOB or NOTIFY_SOCKET environment variables\n# Note: these supervision methods only signal \"process is ready.\"\n#       They do not enable continuous liveness pings back to your supervisor.\nsupervised no\n\n# If a pid file is specified, Redis writes it where specified at startup\n# and removes it at exit.\n#\n# When the server runs non daemonized, no pid file is created if none is\n# specified in the configuration. When the server is daemonized, the pid file\n# is used even if not specified, defaulting to \"/var/run/redis.pid\".\n#\n# Creating a pid file is best effort: if Redis is not able to create it\n# nothing bad happens, the server will start and run normally.\npidfile {{ codis_server_workdir }}/redis_{{ codis_server_port }}.pid\n\n# Specify the server verbosity level.\n# This can be one of:\n# debug (a lot of information, useful for development/testing)\n# verbose (many rarely useful info, but not a mess like the debug level)\n# notice (moderately verbose, what you want in production probably)\n# warning (only very important / critical messages are logged)\nloglevel notice\n\n# Specify the log file name. Also the empty string can be used to force\n# Redis to log on the standard output. Note that if you use standard\n# output for logging but daemonize, logs will be sent to /dev/null\nlogfile \"{{ codis_server_workdir }}/redis_{{ codis_server_port }}.log\"\n\n# To enable logging to the system logger, just set 'syslog-enabled' to yes,\n# and optionally update the other syslog parameters to suit your needs.\n# syslog-enabled no\n\n# Specify the syslog identity.\n# syslog-ident redis\n\n# Specify the syslog facility. Must be USER or between LOCAL0-LOCAL7.\n# syslog-facility local0\n\n# Set the number of databases. The default database is DB 0, you can select\n# a different one on a per-connection basis using SELECT <dbid> where\n# dbid is a number between 0 and 'databases'-1\ndatabases 16\n\n################################ SNAPSHOTTING  ################################\n#\n# Save the DB on disk:\n#\n#   save <seconds> <changes>\n#\n#   Will save the DB if both the given number of seconds and the given\n#   number of write operations against the DB occurred.\n#\n#   In the example below the behaviour will be to save:\n#   after 900 sec (15 min) if at least 1 key changed\n#   after 300 sec (5 min) if at least 10 keys changed\n#   after 60 sec if at least 10000 keys changed\n#\n#   Note: you can disable saving completely by commenting out all \"save\" lines.\n#\n#   It is also possible to remove all the previously configured save\n#   points by adding a save directive with a single empty string argument\n#   like in the following example:\n#\n#   save \"\"\n\nsave 900 1\nsave 300 10\nsave 60 10000\n\n# By default Redis will stop accepting writes if RDB snapshots are enabled\n# (at least one save point) and the latest background save failed.\n# This will make the user aware (in a hard way) that data is not persisting\n# on disk properly, otherwise chances are that no one will notice and some\n# disaster will happen.\n#\n# If the background saving process will start working again Redis will\n# automatically allow writes again.\n#\n# However if you have setup your proper monitoring of the Redis server\n# and persistence, you may want to disable this feature so that Redis will\n# continue to work as usual even if there are problems with disk,\n# permissions, and so forth.\nstop-writes-on-bgsave-error yes\n\n# Compress string objects using LZF when dump .rdb databases?\n# For default that's set to 'yes' as it's almost always a win.\n# If you want to save some CPU in the saving child set it to 'no' but\n# the dataset will likely be bigger if you have compressible values or keys.\nrdbcompression yes\n\n# Since version 5 of RDB a CRC64 checksum is placed at the end of the file.\n# This makes the format more resistant to corruption but there is a performance\n# hit to pay (around 10%) when saving and loading RDB files, so you can disable it\n# for maximum performances.\n#\n# RDB files created with checksum disabled have a checksum of zero that will\n# tell the loading code to skip the check.\nrdbchecksum yes\n\n# The filename where to dump the DB\ndbfilename dump.rdb\n\n# The working directory.\n#\n# The DB will be written inside this directory, with the filename specified\n# above using the 'dbfilename' configuration directive.\n#\n# The Append Only File will also be created inside this directory.\n#\n# Note that you must specify a directory here, not a file name.\ndir {{ codis_server_workdir }}\n\n################################# REPLICATION #################################\n\n# Master-Slave replication. Use slaveof to make a Redis instance a copy of\n# another Redis server. A few things to understand ASAP about Redis replication.\n#\n# 1) Redis replication is asynchronous, but you can configure a master to\n#    stop accepting writes if it appears to be not connected with at least\n#    a given number of slaves.\n# 2) Redis slaves are able to perform a partial resynchronization with the\n#    master if the replication link is lost for a relatively small amount of\n#    time. You may want to configure the replication backlog size (see the next\n#    sections of this file) with a sensible value depending on your needs.\n# 3) Replication is automatic and does not need user intervention. After a\n#    network partition slaves automatically try to reconnect to masters\n#    and resynchronize with them.\n#\n# slaveof <masterip> <masterport>\n\n# If the master is password protected (using the \"requirepass\" configuration\n# directive below) it is possible to tell the slave to authenticate before\n# starting the replication synchronization process, otherwise the master will\n# refuse the slave request.\n#\nmasterauth {{ product_auth }}\n\n# When a slave loses its connection with the master, or when the replication\n# is still in progress, the slave can act in two different ways:\n#\n# 1) if slave-serve-stale-data is set to 'yes' (the default) the slave will\n#    still reply to client requests, possibly with out of date data, or the\n#    data set may just be empty if this is the first synchronization.\n#\n# 2) if slave-serve-stale-data is set to 'no' the slave will reply with\n#    an error \"SYNC with master in progress\" to all the kind of commands\n#    but to INFO and SLAVEOF.\n#\nslave-serve-stale-data yes\n\n# You can configure a slave instance to accept writes or not. Writing against\n# a slave instance may be useful to store some ephemeral data (because data\n# written on a slave will be easily deleted after resync with the master) but\n# may also cause problems if clients are writing to it because of a\n# misconfiguration.\n#\n# Since Redis 2.6 by default slaves are read-only.\n#\n# Note: read only slaves are not designed to be exposed to untrusted clients\n# on the internet. It's just a protection layer against misuse of the instance.\n# Still a read only slave exports by default all the administrative commands\n# such as CONFIG, DEBUG, and so forth. To a limited extent you can improve\n# security of read only slaves using 'rename-command' to shadow all the\n# administrative / dangerous commands.\nslave-read-only yes\n\n# Replication SYNC strategy: disk or socket.\n#\n# -------------------------------------------------------\n# WARNING: DISKLESS REPLICATION IS EXPERIMENTAL CURRENTLY\n# -------------------------------------------------------\n#\n# New slaves and reconnecting slaves that are not able to continue the replication\n# process just receiving differences, need to do what is called a \"full\n# synchronization\". An RDB file is transmitted from the master to the slaves.\n# The transmission can happen in two different ways:\n#\n# 1) Disk-backed: The Redis master creates a new process that writes the RDB\n#                 file on disk. Later the file is transferred by the parent\n#                 process to the slaves incrementally.\n# 2) Diskless: The Redis master creates a new process that directly writes the\n#              RDB file to slave sockets, without touching the disk at all.\n#\n# With disk-backed replication, while the RDB file is generated, more slaves\n# can be queued and served with the RDB file as soon as the current child producing\n# the RDB file finishes its work. With diskless replication instead once\n# the transfer starts, new slaves arriving will be queued and a new transfer\n# will start when the current one terminates.\n#\n# When diskless replication is used, the master waits a configurable amount of\n# time (in seconds) before starting the transfer in the hope that multiple slaves\n# will arrive and the transfer can be parallelized.\n#\n# With slow disks and fast (large bandwidth) networks, diskless replication\n# works better.\nrepl-diskless-sync no\n\n# When diskless replication is enabled, it is possible to configure the delay\n# the server waits in order to spawn the child that transfers the RDB via socket\n# to the slaves.\n#\n# This is important since once the transfer starts, it is not possible to serve\n# new slaves arriving, that will be queued for the next RDB transfer, so the server\n# waits a delay in order to let more slaves arrive.\n#\n# The delay is specified in seconds, and by default is 5 seconds. To disable\n# it entirely just set it to 0 seconds and the transfer will start ASAP.\nrepl-diskless-sync-delay 5\n\n# Slaves send PINGs to server in a predefined interval. It's possible to change\n# this interval with the repl_ping_slave_period option. The default value is 10\n# seconds.\n#\n# repl-ping-slave-period 10\n\n# The following option sets the replication timeout for:\n#\n# 1) Bulk transfer I/O during SYNC, from the point of view of slave.\n# 2) Master timeout from the point of view of slaves (data, pings).\n# 3) Slave timeout from the point of view of masters (REPLCONF ACK pings).\n#\n# It is important to make sure that this value is greater than the value\n# specified for repl-ping-slave-period otherwise a timeout will be detected\n# every time there is low traffic between the master and the slave.\n#\n# repl-timeout 60\n\n# Disable TCP_NODELAY on the slave socket after SYNC?\n#\n# If you select \"yes\" Redis will use a smaller number of TCP packets and\n# less bandwidth to send data to slaves. But this can add a delay for\n# the data to appear on the slave side, up to 40 milliseconds with\n# Linux kernels using a default configuration.\n#\n# If you select \"no\" the delay for data to appear on the slave side will\n# be reduced but more bandwidth will be used for replication.\n#\n# By default we optimize for low latency, but in very high traffic conditions\n# or when the master and slaves are many hops away, turning this to \"yes\" may\n# be a good idea.\nrepl-disable-tcp-nodelay no\n\n# Set the replication backlog size. The backlog is a buffer that accumulates\n# slave data when slaves are disconnected for some time, so that when a slave\n# wants to reconnect again, often a full resync is not needed, but a partial\n# resync is enough, just passing the portion of data the slave missed while\n# disconnected.\n#\n# The bigger the replication backlog, the longer the time the slave can be\n# disconnected and later be able to perform a partial resynchronization.\n#\n# The backlog is only allocated once there is at least a slave connected.\n#\n# repl-backlog-size 1mb\n\n# After a master has no longer connected slaves for some time, the backlog\n# will be freed. The following option configures the amount of seconds that\n# need to elapse, starting from the time the last slave disconnected, for\n# the backlog buffer to be freed.\n#\n# A value of 0 means to never release the backlog.\n#\n# repl-backlog-ttl 3600\n\n# The slave priority is an integer number published by Redis in the INFO output.\n# It is used by Redis Sentinel in order to select a slave to promote into a\n# master if the master is no longer working correctly.\n#\n# A slave with a low priority number is considered better for promotion, so\n# for instance if there are three slaves with priority 10, 100, 25 Sentinel will\n# pick the one with priority 10, that is the lowest.\n#\n# However a special priority of 0 marks the slave as not able to perform the\n# role of master, so a slave with priority of 0 will never be selected by\n# Redis Sentinel for promotion.\n#\n# By default the priority is 100.\nslave-priority 100\n\n# It is possible for a master to stop accepting writes if there are less than\n# N slaves connected, having a lag less or equal than M seconds.\n#\n# The N slaves need to be in \"online\" state.\n#\n# The lag in seconds, that must be <= the specified value, is calculated from\n# the last ping received from the slave, that is usually sent every second.\n#\n# This option does not GUARANTEE that N replicas will accept the write, but\n# will limit the window of exposure for lost writes in case not enough slaves\n# are available, to the specified number of seconds.\n#\n# For example to require at least 3 slaves with a lag <= 10 seconds use:\n#\n# min-slaves-to-write 3\n# min-slaves-max-lag 10\n#\n# Setting one or the other to 0 disables the feature.\n#\n# By default min-slaves-to-write is set to 0 (feature disabled) and\n# min-slaves-max-lag is set to 10.\n\n# A Redis master is able to list the address and port of the attached\n# slaves in different ways. For example the \"INFO replication\" section\n# offers this information, which is used, among other tools, by\n# Redis Sentinel in order to discover slave instances.\n# Another place where this info is available is in the output of the\n# \"ROLE\" command of a masteer.\n#\n# The listed IP and address normally reported by a slave is obtained\n# in the following way:\n#\n#   IP: The address is auto detected by checking the peer address\n#   of the socket used by the slave to connect with the master.\n#\n#   Port: The port is communicated by the slave during the replication\n#   handshake, and is normally the port that the slave is using to\n#   list for connections.\n#\n# However when port forwarding or Network Address Translation (NAT) is\n# used, the slave may be actually reachable via different IP and port\n# pairs. The following two options can be used by a slave in order to\n# report to its master a specific set of IP and port, so that both INFO\n# and ROLE will report those values.\n#\n# There is no need to use both the options if you need to override just\n# the port or the IP address.\n#\n# slave-announce-ip 5.5.5.5\n# slave-announce-port 1234\n\n################################## SECURITY ###################################\n\n# Require clients to issue AUTH <PASSWORD> before processing any other\n# commands.  This might be useful in environments in which you do not trust\n# others with access to the host running redis-server.\n#\n# This should stay commented out for backward compatibility and because most\n# people do not need auth (e.g. they run their own servers).\n#\n# Warning: since Redis is pretty fast an outside user can try up to\n# 150k passwords per second against a good box. This means that you should\n# use a very strong password otherwise it will be very easy to break.\n#\nrequirepass {{ product_auth }}\n\n# Command renaming.\n#\n# It is possible to change the name of dangerous commands in a shared\n# environment. For instance the CONFIG command may be renamed into something\n# hard to guess so that it will still be available for internal-use tools\n# but not available for general clients.\n#\n# Example:\n#\n# rename-command CONFIG b840fc02d524045429941cc15f59e41cb7be6c52\n#\n# It is also possible to completely kill a command by renaming it into\n# an empty string:\n#\n# rename-command CONFIG \"\"\n#\n# Please note that changing the name of commands that are logged into the\n# AOF file or transmitted to slaves may cause problems.\n\n################################### LIMITS ####################################\n\n# Set the max number of connected clients at the same time. By default\n# this limit is set to 10000 clients, however if the Redis server is not\n# able to configure the process file limit to allow for the specified limit\n# the max number of allowed clients is set to the current file limit\n# minus 32 (as Redis reserves a few file descriptors for internal uses).\n#\n# Once the limit is reached Redis will close all the new connections sending\n# an error 'max number of clients reached'.\n#\n# maxclients 10000\n\n# Don't use more memory than the specified amount of bytes.\n# When the memory limit is reached Redis will try to remove keys\n# according to the eviction policy selected (see maxmemory-policy).\n#\n# If Redis can't remove keys according to the policy, or if the policy is\n# set to 'noeviction', Redis will start to reply with errors to commands\n# that would use more memory, like SET, LPUSH, and so on, and will continue\n# to reply to read-only commands like GET.\n#\n# This option is usually useful when using Redis as an LRU cache, or to set\n# a hard memory limit for an instance (using the 'noeviction' policy).\n#\n# WARNING: If you have slaves attached to an instance with maxmemory on,\n# the size of the output buffers needed to feed the slaves are subtracted\n# from the used memory count, so that network problems / resyncs will\n# not trigger a loop where keys are evicted, and in turn the output\n# buffer of slaves is full with DELs of keys evicted triggering the deletion\n# of more keys, and so forth until the database is completely emptied.\n#\n# In short... if you have slaves attached it is suggested that you set a lower\n# limit for maxmemory so that there is some free RAM on the system for slave\n# output buffers (but this is not needed if the policy is 'noeviction').\n#\n# maxmemory <bytes>\n\n# MAXMEMORY POLICY: how Redis will select what to remove when maxmemory\n# is reached. You can select among five behaviors:\n#\n# volatile-lru -> remove the key with an expire set using an LRU algorithm\n# allkeys-lru -> remove any key according to the LRU algorithm\n# volatile-random -> remove a random key with an expire set\n# allkeys-random -> remove a random key, any key\n# volatile-ttl -> remove the key with the nearest expire time (minor TTL)\n# noeviction -> don't expire at all, just return an error on write operations\n#\n# Note: with any of the above policies, Redis will return an error on write\n#       operations, when there are no suitable keys for eviction.\n#\n#       At the date of writing these commands are: set setnx setex append\n#       incr decr rpush lpush rpushx lpushx linsert lset rpoplpush sadd\n#       sinter sinterstore sunion sunionstore sdiff sdiffstore zadd zincrby\n#       zunionstore zinterstore hset hsetnx hmset hincrby incrby decrby\n#       getset mset msetnx exec sort\n#\n# The default is:\n#\n# maxmemory-policy noeviction\n\n# LRU and minimal TTL algorithms are not precise algorithms but approximated\n# algorithms (in order to save memory), so you can tune it for speed or\n# accuracy. For default Redis will check five keys and pick the one that was\n# used less recently, you can change the sample size using the following\n# configuration directive.\n#\n# The default of 5 produces good enough results. 10 Approximates very closely\n# true LRU but costs a bit more CPU. 3 is very fast but not very accurate.\n#\n# maxmemory-samples 5\n\n############################## APPEND ONLY MODE ###############################\n\n# By default Redis asynchronously dumps the dataset on disk. This mode is\n# good enough in many applications, but an issue with the Redis process or\n# a power outage may result into a few minutes of writes lost (depending on\n# the configured save points).\n#\n# The Append Only File is an alternative persistence mode that provides\n# much better durability. For instance using the default data fsync policy\n# (see later in the config file) Redis can lose just one second of writes in a\n# dramatic event like a server power outage, or a single write if something\n# wrong with the Redis process itself happens, but the operating system is\n# still running correctly.\n#\n# AOF and RDB persistence can be enabled at the same time without problems.\n# If the AOF is enabled on startup Redis will load the AOF, that is the file\n# with the better durability guarantees.\n#\n# Please check http://redis.io/topics/persistence for more information.\n\nappendonly no\n\n# The name of the append only file (default: \"appendonly.aof\")\n\nappendfilename \"appendonly.aof\"\n\n# The fsync() call tells the Operating System to actually write data on disk\n# instead of waiting for more data in the output buffer. Some OS will really flush\n# data on disk, some other OS will just try to do it ASAP.\n#\n# Redis supports three different modes:\n#\n# no: don't fsync, just let the OS flush the data when it wants. Faster.\n# always: fsync after every write to the append only log. Slow, Safest.\n# everysec: fsync only one time every second. Compromise.\n#\n# The default is \"everysec\", as that's usually the right compromise between\n# speed and data safety. It's up to you to understand if you can relax this to\n# \"no\" that will let the operating system flush the output buffer when\n# it wants, for better performances (but if you can live with the idea of\n# some data loss consider the default persistence mode that's snapshotting),\n# or on the contrary, use \"always\" that's very slow but a bit safer than\n# everysec.\n#\n# More details please check the following article:\n# http://antirez.com/post/redis-persistence-demystified.html\n#\n# If unsure, use \"everysec\".\n\n# appendfsync always\nappendfsync everysec\n# appendfsync no\n\n# When the AOF fsync policy is set to always or everysec, and a background\n# saving process (a background save or AOF log background rewriting) is\n# performing a lot of I/O against the disk, in some Linux configurations\n# Redis may block too long on the fsync() call. Note that there is no fix for\n# this currently, as even performing fsync in a different thread will block\n# our synchronous write(2) call.\n#\n# In order to mitigate this problem it's possible to use the following option\n# that will prevent fsync() from being called in the main process while a\n# BGSAVE or BGREWRITEAOF is in progress.\n#\n# This means that while another child is saving, the durability of Redis is\n# the same as \"appendfsync none\". In practical terms, this means that it is\n# possible to lose up to 30 seconds of log in the worst scenario (with the\n# default Linux settings).\n#\n# If you have latency problems turn this to \"yes\". Otherwise leave it as\n# \"no\" that is the safest pick from the point of view of durability.\n\nno-appendfsync-on-rewrite no\n\n# Automatic rewrite of the append only file.\n# Redis is able to automatically rewrite the log file implicitly calling\n# BGREWRITEAOF when the AOF log size grows by the specified percentage.\n#\n# This is how it works: Redis remembers the size of the AOF file after the\n# latest rewrite (if no rewrite has happened since the restart, the size of\n# the AOF at startup is used).\n#\n# This base size is compared to the current size. If the current size is\n# bigger than the specified percentage, the rewrite is triggered. Also\n# you need to specify a minimal size for the AOF file to be rewritten, this\n# is useful to avoid rewriting the AOF file even if the percentage increase\n# is reached but it is still pretty small.\n#\n# Specify a percentage of zero in order to disable the automatic AOF\n# rewrite feature.\n\nauto-aof-rewrite-percentage 100\nauto-aof-rewrite-min-size 64mb\n\n# An AOF file may be found to be truncated at the end during the Redis\n# startup process, when the AOF data gets loaded back into memory.\n# This may happen when the system where Redis is running\n# crashes, especially when an ext4 filesystem is mounted without the\n# data=ordered option (however this can't happen when Redis itself\n# crashes or aborts but the operating system still works correctly).\n#\n# Redis can either exit with an error when this happens, or load as much\n# data as possible (the default now) and start if the AOF file is found\n# to be truncated at the end. The following option controls this behavior.\n#\n# If aof-load-truncated is set to yes, a truncated AOF file is loaded and\n# the Redis server starts emitting a log to inform the user of the event.\n# Otherwise if the option is set to no, the server aborts with an error\n# and refuses to start. When the option is set to no, the user requires\n# to fix the AOF file using the \"redis-check-aof\" utility before to restart\n# the server.\n#\n# Note that if the AOF file will be found to be corrupted in the middle\n# the server will still exit with an error. This option only applies when\n# Redis will try to read more data from the AOF file but not enough bytes\n# will be found.\naof-load-truncated yes\n\n################################ LUA SCRIPTING  ###############################\n\n# Max execution time of a Lua script in milliseconds.\n#\n# If the maximum execution time is reached Redis will log that a script is\n# still in execution after the maximum allowed time and will start to\n# reply to queries with an error.\n#\n# When a long running script exceeds the maximum execution time only the\n# SCRIPT KILL and SHUTDOWN NOSAVE commands are available. The first can be\n# used to stop a script that did not yet called write commands. The second\n# is the only way to shut down the server in the case a write command was\n# already issued by the script but the user doesn't want to wait for the natural\n# termination of the script.\n#\n# Set it to 0 or a negative value for unlimited execution without warnings.\nlua-time-limit 5000\n\n################################ REDIS CLUSTER  ###############################\n#\n# ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++\n# WARNING EXPERIMENTAL: Redis Cluster is considered to be stable code, however\n# in order to mark it as \"mature\" we need to wait for a non trivial percentage\n# of users to deploy it in production.\n# ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++\n#\n# Normal Redis instances can't be part of a Redis Cluster; only nodes that are\n# started as cluster nodes can. In order to start a Redis instance as a\n# cluster node enable the cluster support uncommenting the following:\n#\n# cluster-enabled yes\n\n# Every cluster node has a cluster configuration file. This file is not\n# intended to be edited by hand. It is created and updated by Redis nodes.\n# Every Redis Cluster node requires a different cluster configuration file.\n# Make sure that instances running in the same system do not have\n# overlapping cluster configuration file names.\n#\n# cluster-config-file nodes-6379.conf\n\n# Cluster node timeout is the amount of milliseconds a node must be unreachable\n# for it to be considered in failure state.\n# Most other internal time limits are multiple of the node timeout.\n#\n# cluster-node-timeout 15000\n\n# A slave of a failing master will avoid to start a failover if its data\n# looks too old.\n#\n# There is no simple way for a slave to actually have a exact measure of\n# its \"data age\", so the following two checks are performed:\n#\n# 1) If there are multiple slaves able to failover, they exchange messages\n#    in order to try to give an advantage to the slave with the best\n#    replication offset (more data from the master processed).\n#    Slaves will try to get their rank by offset, and apply to the start\n#    of the failover a delay proportional to their rank.\n#\n# 2) Every single slave computes the time of the last interaction with\n#    its master. This can be the last ping or command received (if the master\n#    is still in the \"connected\" state), or the time that elapsed since the\n#    disconnection with the master (if the replication link is currently down).\n#    If the last interaction is too old, the slave will not try to failover\n#    at all.\n#\n# The point \"2\" can be tuned by user. Specifically a slave will not perform\n# the failover if, since the last interaction with the master, the time\n# elapsed is greater than:\n#\n#   (node-timeout * slave-validity-factor) + repl-ping-slave-period\n#\n# So for example if node-timeout is 30 seconds, and the slave-validity-factor\n# is 10, and assuming a default repl-ping-slave-period of 10 seconds, the\n# slave will not try to failover if it was not able to talk with the master\n# for longer than 310 seconds.\n#\n# A large slave-validity-factor may allow slaves with too old data to failover\n# a master, while a too small value may prevent the cluster from being able to\n# elect a slave at all.\n#\n# For maximum availability, it is possible to set the slave-validity-factor\n# to a value of 0, which means, that slaves will always try to failover the\n# master regardless of the last time they interacted with the master.\n# (However they'll always try to apply a delay proportional to their\n# offset rank).\n#\n# Zero is the only value able to guarantee that when all the partitions heal\n# the cluster will always be able to continue.\n#\n# cluster-slave-validity-factor 10\n\n# Cluster slaves are able to migrate to orphaned masters, that are masters\n# that are left without working slaves. This improves the cluster ability\n# to resist to failures as otherwise an orphaned master can't be failed over\n# in case of failure if it has no working slaves.\n#\n# Slaves migrate to orphaned masters only if there are still at least a\n# given number of other working slaves for their old master. This number\n# is the \"migration barrier\". A migration barrier of 1 means that a slave\n# will migrate only if there is at least 1 other working slave for its master\n# and so forth. It usually reflects the number of slaves you want for every\n# master in your cluster.\n#\n# Default is 1 (slaves migrate only if their masters remain with at least\n# one slave). To disable migration just set it to a very large value.\n# A value of 0 can be set but is useful only for debugging and dangerous\n# in production.\n#\n# cluster-migration-barrier 1\n\n# By default Redis Cluster nodes stop accepting queries if they detect there\n# is at least an hash slot uncovered (no available node is serving it).\n# This way if the cluster is partially down (for example a range of hash slots\n# are no longer covered) all the cluster becomes, eventually, unavailable.\n# It automatically returns available as soon as all the slots are covered again.\n#\n# However sometimes you want the subset of the cluster which is working,\n# to continue to accept queries for the part of the key space that is still\n# covered. In order to do so, just set the cluster-require-full-coverage\n# option to no.\n#\n# cluster-require-full-coverage yes\n\n# In order to setup your cluster make sure to read the documentation\n# available at http://redis.io web site.\n\n################################## SLOW LOG ###################################\n\n# The Redis Slow Log is a system to log queries that exceeded a specified\n# execution time. The execution time does not include the I/O operations\n# like talking with the client, sending the reply and so forth,\n# but just the time needed to actually execute the command (this is the only\n# stage of command execution where the thread is blocked and can not serve\n# other requests in the meantime).\n#\n# You can configure the slow log with two parameters: one tells Redis\n# what is the execution time, in microseconds, to exceed in order for the\n# command to get logged, and the other parameter is the length of the\n# slow log. When a new command is logged the oldest one is removed from the\n# queue of logged commands.\n\n# The following time is expressed in microseconds, so 1000000 is equivalent\n# to one second. Note that a negative number disables the slow log, while\n# a value of zero forces the logging of every command.\nslowlog-log-slower-than 10000\n\n# There is no limit to this length. Just be aware that it will consume memory.\n# You can reclaim memory used by the slow log with SLOWLOG RESET.\nslowlog-max-len 128\n\n################################ LATENCY MONITOR ##############################\n\n# The Redis latency monitoring subsystem samples different operations\n# at runtime in order to collect data related to possible sources of\n# latency of a Redis instance.\n#\n# Via the LATENCY command this information is available to the user that can\n# print graphs and obtain reports.\n#\n# The system only logs operations that were performed in a time equal or\n# greater than the amount of milliseconds specified via the\n# latency-monitor-threshold configuration directive. When its value is set\n# to zero, the latency monitor is turned off.\n#\n# By default latency monitoring is disabled since it is mostly not needed\n# if you don't have latency issues, and collecting data has a performance\n# impact, that while very small, can be measured under big load. Latency\n# monitoring can easily be enabled at runtime using the command\n# \"CONFIG SET latency-monitor-threshold <milliseconds>\" if needed.\nlatency-monitor-threshold 0\n\n############################# EVENT NOTIFICATION ##############################\n\n# Redis can notify Pub/Sub clients about events happening in the key space.\n# This feature is documented at http://redis.io/topics/notifications\n#\n# For instance if keyspace events notification is enabled, and a client\n# performs a DEL operation on key \"foo\" stored in the Database 0, two\n# messages will be published via Pub/Sub:\n#\n# PUBLISH __keyspace@0__:foo del\n# PUBLISH __keyevent@0__:del foo\n#\n# It is possible to select the events that Redis will notify among a set\n# of classes. Every class is identified by a single character:\n#\n#  K     Keyspace events, published with __keyspace@<db>__ prefix.\n#  E     Keyevent events, published with __keyevent@<db>__ prefix.\n#  g     Generic commands (non-type specific) like DEL, EXPIRE, RENAME, ...\n#  $     String commands\n#  l     List commands\n#  s     Set commands\n#  h     Hash commands\n#  z     Sorted set commands\n#  x     Expired events (events generated every time a key expires)\n#  e     Evicted events (events generated when a key is evicted for maxmemory)\n#  A     Alias for g$lshzxe, so that the \"AKE\" string means all the events.\n#\n#  The \"notify-keyspace-events\" takes as argument a string that is composed\n#  of zero or multiple characters. The empty string means that notifications\n#  are disabled.\n#\n#  Example: to enable list and generic events, from the point of view of the\n#           event name, use:\n#\n#  notify-keyspace-events Elg\n#\n#  Example 2: to get the stream of the expired keys subscribing to channel\n#             name __keyevent@0__:expired use:\n#\n#  notify-keyspace-events Ex\n#\n#  By default all notifications are disabled because most users don't need\n#  this feature and the feature has some overhead. Note that if you don't\n#  specify at least one of K or E, no events will be delivered.\nnotify-keyspace-events \"\"\n\n############################### ADVANCED CONFIG ###############################\n\n# Hashes are encoded using a memory efficient data structure when they have a\n# small number of entries, and the biggest entry does not exceed a given\n# threshold. These thresholds can be configured using the following directives.\nhash-max-ziplist-entries 512\nhash-max-ziplist-value 64\n\n# Lists are also encoded in a special way to save a lot of space.\n# The number of entries allowed per internal list node can be specified\n# as a fixed maximum size or a maximum number of elements.\n# For a fixed maximum size, use -5 through -1, meaning:\n# -5: max size: 64 Kb  <-- not recommended for normal workloads\n# -4: max size: 32 Kb  <-- not recommended\n# -3: max size: 16 Kb  <-- probably not recommended\n# -2: max size: 8 Kb   <-- good\n# -1: max size: 4 Kb   <-- good\n# Positive numbers mean store up to _exactly_ that number of elements\n# per list node.\n# The highest performing option is usually -2 (8 Kb size) or -1 (4 Kb size),\n# but if your use case is unique, adjust the settings as necessary.\nlist-max-ziplist-size -2\n\n# Lists may also be compressed.\n# Compress depth is the number of quicklist ziplist nodes from *each* side of\n# the list to *exclude* from compression.  The head and tail of the list\n# are always uncompressed for fast push/pop operations.  Settings are:\n# 0: disable all list compression\n# 1: depth 1 means \"don't start compressing until after 1 node into the list,\n#    going from either the head or tail\"\n#    So: [head]->node->node->...->node->[tail]\n#    [head], [tail] will always be uncompressed; inner nodes will compress.\n# 2: [head]->[next]->node->node->...->node->[prev]->[tail]\n#    2 here means: don't compress head or head->next or tail->prev or tail,\n#    but compress all nodes between them.\n# 3: [head]->[next]->[next]->node->node->...->node->[prev]->[prev]->[tail]\n# etc.\nlist-compress-depth 0\n\n# Sets have a special encoding in just one case: when a set is composed\n# of just strings that happen to be integers in radix 10 in the range\n# of 64 bit signed integers.\n# The following configuration setting sets the limit in the size of the\n# set in order to use this special memory saving encoding.\nset-max-intset-entries 512\n\n# Similarly to hashes and lists, sorted sets are also specially encoded in\n# order to save a lot of space. This encoding is only used when the length and\n# elements of a sorted set are below the following limits:\nzset-max-ziplist-entries 128\nzset-max-ziplist-value 64\n\n# HyperLogLog sparse representation bytes limit. The limit includes the\n# 16 bytes header. When an HyperLogLog using the sparse representation crosses\n# this limit, it is converted into the dense representation.\n#\n# A value greater than 16000 is totally useless, since at that point the\n# dense representation is more memory efficient.\n#\n# The suggested value is ~ 3000 in order to have the benefits of\n# the space efficient encoding without slowing down too much PFADD,\n# which is O(N) with the sparse encoding. The value can be raised to\n# ~ 10000 when CPU is not a concern, but space is, and the data set is\n# composed of many HyperLogLogs with cardinality in the 0 - 15000 range.\nhll-sparse-max-bytes 3000\n\n# Active rehashing uses 1 millisecond every 100 milliseconds of CPU time in\n# order to help rehashing the main Redis hash table (the one mapping top-level\n# keys to values). The hash table implementation Redis uses (see dict.c)\n# performs a lazy rehashing: the more operation you run into a hash table\n# that is rehashing, the more rehashing \"steps\" are performed, so if the\n# server is idle the rehashing is never complete and some more memory is used\n# by the hash table.\n#\n# The default is to use this millisecond 10 times every second in order to\n# actively rehash the main dictionaries, freeing memory when possible.\n#\n# If unsure:\n# use \"activerehashing no\" if you have hard latency requirements and it is\n# not a good thing in your environment that Redis can reply from time to time\n# to queries with 2 milliseconds delay.\n#\n# use \"activerehashing yes\" if you don't have such hard requirements but\n# want to free memory asap when possible.\nactiverehashing yes\n\n# The client output buffer limits can be used to force disconnection of clients\n# that are not reading data from the server fast enough for some reason (a\n# common reason is that a Pub/Sub client can't consume messages as fast as the\n# publisher can produce them).\n#\n# The limit can be set differently for the three different classes of clients:\n#\n# normal -> normal clients including MONITOR clients\n# slave  -> slave clients\n# pubsub -> clients subscribed to at least one pubsub channel or pattern\n#\n# The syntax of every client-output-buffer-limit directive is the following:\n#\n# client-output-buffer-limit <class> <hard limit> <soft limit> <soft seconds>\n#\n# A client is immediately disconnected once the hard limit is reached, or if\n# the soft limit is reached and remains reached for the specified number of\n# seconds (continuously).\n# So for instance if the hard limit is 32 megabytes and the soft limit is\n# 16 megabytes / 10 seconds, the client will get disconnected immediately\n# if the size of the output buffers reach 32 megabytes, but will also get\n# disconnected if the client reaches 16 megabytes and continuously overcomes\n# the limit for 10 seconds.\n#\n# By default normal clients are not limited because they don't receive data\n# without asking (in a push way), but just after a request, so only\n# asynchronous clients may create a scenario where data is requested faster\n# than it can read.\n#\n# Instead there is a default limit for pubsub and slave clients, since\n# subscribers and slaves receive data in a push fashion.\n#\n# Both the hard or the soft limit can be disabled by setting them to zero.\nclient-output-buffer-limit normal 0 0 0\nclient-output-buffer-limit slave 256mb 64mb 60\nclient-output-buffer-limit pubsub 32mb 8mb 60\n\n# Redis calls an internal function to perform many background tasks, like\n# closing connections of clients in timeout, purging expired keys that are\n# never requested, and so forth.\n#\n# Not all tasks are performed with the same frequency, but Redis checks for\n# tasks to perform according to the specified \"hz\" value.\n#\n# By default \"hz\" is set to 10. Raising the value will use more CPU when\n# Redis is idle, but at the same time will make Redis more responsive when\n# there are many keys expiring at the same time, and timeouts may be\n# handled with more precision.\n#\n# The range is between 1 and 500, however a value over 100 is usually not\n# a good idea. Most users should use the default of 10 and raise this up to\n# 100 only in environments where very low latency is required.\nhz 10\n\n# When a child rewrites the AOF file, if the following option is enabled\n# the file will be fsync-ed every 32 MB of data generated. This is useful\n# in order to commit the file to the disk more incrementally and avoid\n# big latency spikes.\naof-rewrite-incremental-fsync yes\n"
  },
  {
    "path": "ansible/roles/common/tasks/main.yml",
    "content": "---\n- name: Create codis install directory\n  file: path={{ codis_install_dir }} state=directory owner=codis group=codis\n\n- name: Create codis bin directory\n  file: path={{ codis_install_dir }}/bin state=directory owner=codis group=codis\n\n- name: Create codis conf directory\n  file: path={{ codis_install_dir }}/config state=directory owner=codis group=codis\n\n- name: Create codis admin directory\n  file: path={{ codis_install_dir }}/admin state=directory owner=codis group=codis\n"
  },
  {
    "path": "ansible/roles/redis-sentinel/tasks/main.yml",
    "content": "---\n- name: Create redis sentinel work directory\n  file: path={{ redis_sentinel_workdir }} state=directory owner=codis group=codis\n\n- name: Copy redis-sentinel binary\n  copy: src={{ codis_dir }}/bin/codis-server dest={{ codis_install_dir }}/bin/redis-sentinel mode=766\n\n- name: Copy redis-sentinel configuration\n  template: src=sentinel.conf dest={{ codis_install_dir }}/config/sentinel.conf\n\n- name: Copy redis-sentinel admin script\n  template: src=redis-sentinel-admin.sh dest={{ codis_install_dir }}/admin/redis-sentinel-admin.sh mode=766\n\n- name: Restart redis-sentinel service\n  command: \"{{ codis_install_dir }}/admin/redis-sentinel-admin.sh restart\"\n"
  },
  {
    "path": "ansible/roles/redis-sentinel/templates/redis-sentinel-admin.sh",
    "content": "#!/usr/bin/env bash\n\nCODIS_ADMIN=\"${BASH_SOURCE-$0}\"\nCODIS_ADMIN=\"$(dirname \"${CODIS_ADMIN}\")\"\nCODIS_ADMIN_DIR=\"$(cd \"${CODIS_ADMIN}\"; pwd)\"\n\nCODIS_BIN_DIR=$CODIS_ADMIN_DIR/../bin\nCODIS_LOG_DIR=$CODIS_ADMIN_DIR/../log\nCODIS_CONF_DIR=$CODIS_ADMIN_DIR/../config\n\nREDIS_SENTINEL_BIN=$CODIS_BIN_DIR/redis-sentinel\nREDIS_SENTINEL_PID_FILE={{ redis_sentinel_workdir }}/sentinel_{{ redis_sentinel_port }}.pid\n\nREDIS_SENTINEL_LOG_FILE={{ redis_sentinel_workdir }}/sentinel_{{ redis_sentinel_port }}.log\nREDIS_SENTINEL_DAEMON_FILE=$CODIS_LOG_DIR/redis-sentinel.out\n\nREDIS_SENTINEL_CONF_FILE=$CODIS_CONF_DIR/sentinel.conf\n\necho $REDIS_SENTINEL_CONF_FILE\n\nif [ ! -d $CODIS_LOG_DIR ]; then\n    mkdir -p $CODIS_LOG_DIR\nfi\n\n\ncase $1 in\nstart)\n    echo  \"starting redis-sentinel ... \"\n    if [ -f \"$REDIS_SENTINEL_PID_FILE\" ]; then\n      if kill -0 `cat \"$REDIS_SENTINEL_PID_FILE\"` > /dev/null 2>&1; then\n         echo $command already running as process `cat \"$REDIS_SENTINEL_PID_FILE\"`.\n         exit 0\n      fi\n    fi\n    nohup \"$REDIS_SENTINEL_BIN\" \"${REDIS_SENTINEL_CONF_FILE}\" > \"$REDIS_SENTINEL_DAEMON_FILE\" 2>&1 < /dev/null &\n    ;;\nstop)\n    echo \"stopping redis-sentinel ... \"\n    if [ ! -f \"$REDIS_SENTINEL_PID_FILE\" ]\n    then\n      echo \"no redis-sentinel to stop (could not find file $REDIS_SENTINEL_PID_FILE)\"\n    else\n      kill -2 $(cat \"$REDIS_SENTINEL_PID_FILE\")\n      echo STOPPED\n    fi\n    exit 0\n    ;;\nstop-forced)\n    echo \"stopping redis-sentinel ... \"\n    if [ ! -f \"$REDIS_SENTINEL_PID_FILE\" ]\n    then\n      echo \"no redis-sentinel to stop (could not find file $REDIS_SENTINEL_PID_FILE)\"\n    else\n      kill -9 $(cat \"$REDIS_SENTINEL_PID_FILE\")\n      rm \"$REDIS_SENTINEL_PID_FILE\"\n      echo STOPPED\n    fi\n    exit 0\n    ;;\nrestart)\n    shift\n    \"$0\" stop\n    sleep 1\n    \"$0\" start\n    ;;\n*)\n    echo \"Usage: $0 {start|stop|stop-forced|restart}\" >&2\n\nesac\n"
  },
  {
    "path": "ansible/roles/redis-sentinel/templates/sentinel.conf",
    "content": "# Example sentinel.conf\n\n# *** IMPORTANT ***\n#\n# By default Sentinel will not be reachable from interfaces different than\n# localhost, either use the 'bind' directive to bind to a list of network\n# interfaces, or disable protected mode with \"protected-mode no\" by\n# adding it to this configuration file.\n#\n# Before doing that MAKE SURE the instance is protected from the outside\n# world via firewalling or other means.\n#\n# For example you may use one of the following:\n#\n# bind 127.0.0.1 192.168.1.1\n#\n# protected-mode no\n\n# port <sentinel-port>\n# The port that this sentinel instance will run on\nport {{ redis_sentinel_port }}\n\ndaemonize yes\n\nlogfile \"{{ redis_sentinel_workdir }}/sentinel_{{ redis_sentinel_port }}.log\"\n\npidfile \"{{ redis_sentinel_workdir }}/sentinel_{{ redis_sentinel_port }}.pid\"\n# sentinel announce-ip <ip>\n# sentinel announce-port <port>\n#\n# The above two configuration directives are useful in environments where,\n# because of NAT, Sentinel is reachable from outside via a non-local address.\n#\n# When announce-ip is provided, the Sentinel will claim the specified IP address\n# in HELLO messages used to gossip its presence, instead of auto-detecting the\n# local address as it usually does.\n#\n# Similarly when announce-port is provided and is valid and non-zero, Sentinel\n# will announce the specified TCP port.\n#\n# The two options don't need to be used together, if only announce-ip is\n# provided, the Sentinel will announce the specified IP and the server port\n# as specified by the \"port\" option. If only announce-port is provided, the\n# Sentinel will announce the auto-detected local IP and the specified port.\n#\n# Example:\n#\n# sentinel announce-ip 1.2.3.4\n\n# dir <working-directory>\n# Every long running process should have a well-defined working directory.\n# For Redis Sentinel to chdir to /tmp at startup is the simplest thing\n# for the process to don't interfere with administrative tasks such as\n# unmounting filesystems.\ndir {{ redis_sentinel_workdir }}\n\n# sentinel monitor <master-name> <ip> <redis-port> <quorum>\n#\n# Tells Sentinel to monitor this master, and to consider it in O_DOWN\n# (Objectively Down) state only if at least <quorum> sentinels agree.\n#\n# Note that whatever is the ODOWN quorum, a Sentinel will require to\n# be elected by the majority of the known Sentinels in order to\n# start a failover, so no failover can be performed in minority.\n#\n# Slaves are auto-discovered, so you don't need to specify slaves in\n# any way. Sentinel itself will rewrite this configuration file adding\n# the slaves using additional configuration options.\n# Also note that the configuration file is rewritten when a\n# slave is promoted to master.\n#\n# Note: master name should not include special characters or spaces.\n# The valid charset is A-z 0-9 and the three characters \".-_\".\n# sentinel monitor mymaster 127.0.0.1 6379 2\n\n# sentinel auth-pass <master-name> <password>\n#\n# Set the password to use to authenticate with the master and slaves.\n# Useful if there is a password set in the Redis instances to monitor.\n#\n# Note that the master password is also used for slaves, so it is not\n# possible to set a different password in masters and slaves instances\n# if you want to be able to monitor these instances with Sentinel.\n#\n# However you can have Redis instances without the authentication enabled\n# mixed with Redis instances requiring the authentication (as long as the\n# password set is the same for all the instances requiring the password) as\n# the AUTH command will have no effect in Redis instances with authentication\n# switched off.\n#\n# Example:\n#\n# sentinel auth-pass mymaster MySUPER--secret-0123passw0rd\n\n# sentinel down-after-milliseconds <master-name> <milliseconds>\n#\n# Number of milliseconds the master (or any attached slave or sentinel) should\n# be unreachable (as in, not acceptable reply to PING, continuously, for the\n# specified period) in order to consider it in S_DOWN state (Subjectively\n# Down).\n#\n# Default is 30 seconds.\n# sentinel down-after-milliseconds mymaster 30000\n\n# sentinel parallel-syncs <master-name> <numslaves>\n#\n# How many slaves we can reconfigure to point to the new slave simultaneously\n# during the failover. Use a low number if you use the slaves to serve query\n# to avoid that all the slaves will be unreachable at about the same\n# time while performing the synchronization with the master.\n# sentinel parallel-syncs mymaster 1\n\n# sentinel failover-timeout <master-name> <milliseconds>\n#\n# Specifies the failover timeout in milliseconds. It is used in many ways:\n#\n# - The time needed to re-start a failover after a previous failover was\n#   already tried against the same master by a given Sentinel, is two\n#   times the failover timeout.\n#\n# - The time needed for a slave replicating to a wrong master according\n#   to a Sentinel current configuration, to be forced to replicate\n#   with the right master, is exactly the failover timeout (counting since\n#   the moment a Sentinel detected the misconfiguration).\n#\n# - The time needed to cancel a failover that is already in progress but\n#   did not produced any configuration change (SLAVEOF NO ONE yet not\n#   acknowledged by the promoted slave).\n#\n# - The maximum time a failover in progress waits for all the slaves to be\n#   reconfigured as slaves of the new master. However even after this time\n#   the slaves will be reconfigured by the Sentinels anyway, but not with\n#   the exact parallel-syncs progression as specified.\n#\n# Default is 3 minutes.\n# sentinel failover-timeout mymaster 180000\n\n# SCRIPTS EXECUTION\n#\n# sentinel notification-script and sentinel reconfig-script are used in order\n# to configure scripts that are called to notify the system administrator\n# or to reconfigure clients after a failover. The scripts are executed\n# with the following rules for error handling:\n#\n# If script exits with \"1\" the execution is retried later (up to a maximum\n# number of times currently set to 10).\n#\n# If script exits with \"2\" (or an higher value) the script execution is\n# not retried.\n#\n# If script terminates because it receives a signal the behavior is the same\n# as exit code 1.\n#\n# A script has a maximum running time of 60 seconds. After this limit is\n# reached the script is terminated with a SIGKILL and the execution retried.\n\n# NOTIFICATION SCRIPT\n#\n# sentinel notification-script <master-name> <script-path>\n#\n# Call the specified notification script for any sentinel event that is\n# generated in the WARNING level (for instance -sdown, -odown, and so forth).\n# This script should notify the system administrator via email, SMS, or any\n# other messaging system, that there is something wrong with the monitored\n# Redis systems.\n#\n# The script is called with just two arguments: the first is the event type\n# and the second the event description.\n#\n# The script must exist and be executable in order for sentinel to start if\n# this option is provided.\n#\n# Example:\n#\n# sentinel notification-script mymaster /var/redis/notify.sh\n\n# CLIENTS RECONFIGURATION SCRIPT\n#\n# sentinel client-reconfig-script <master-name> <script-path>\n#\n# When the master changed because of a failover a script can be called in\n# order to perform application-specific tasks to notify the clients that the\n# configuration has changed and the master is at a different address.\n#\n# The following arguments are passed to the script:\n#\n# <master-name> <role> <state> <from-ip> <from-port> <to-ip> <to-port>\n#\n# <state> is currently always \"failover\"\n# <role> is either \"leader\" or \"observer\"\n#\n# The arguments from-ip, from-port, to-ip, to-port are used to communicate\n# the old address of the master and the new address of the elected slave\n# (now a master).\n#\n# This script should be resistant to multiple invocations.\n#\n# Example:\n#\n# sentinel client-reconfig-script mymaster /var/redis/reconfig.sh\n\n"
  },
  {
    "path": "ansible/site.yml",
    "content": "---\n- name: codis environment init\n  hosts: all\n  remote_user: codis\n  roles:\n    - common\n\n- name: Install codis-dashboard\n  hosts: codis-dashboard-servers\n  remote_user: codis\n  roles:\n    - codis-dashboard\n\n- name: Install codis-proxy\n  hosts: codis-proxy-servers\n  remote_user: codis\n  roles:\n    - codis-proxy\n\n- name: Install codis-server\n  hosts: codis-servers\n  remote_user: codis\n  roles:\n    - codis-server\n\n- name: Install redis-sentinel\n  hosts: redis-sentinel-servers\n  remote_user: codis\n  roles:\n    - redis-sentinel\n\n- name: Install codis-fe\n  hosts: codis-fe-servers\n  remote_user: codis\n  roles:\n    - codis-fe\n"
  },
  {
    "path": "cmd/admin/admin.go",
    "content": "// Copyright 2016 CodisLabs. All Rights Reserved.\n// Licensed under the MIT (MIT-LICENSE.txt) license.\n\npackage main\n\nimport (\n\t\"encoding/json\"\n\t\"fmt\"\n\t\"io/ioutil\"\n\t\"path/filepath\"\n\t\"time\"\n\n\t\"github.com/CodisLabs/codis/pkg/models\"\n\t\"github.com/CodisLabs/codis/pkg/utils\"\n\t\"github.com/CodisLabs/codis/pkg/utils/log\"\n)\n\ntype cmdAdmin struct {\n\tproduct string\n}\n\nfunc (t *cmdAdmin) Main(d map[string]interface{}) {\n\tt.product, _ = d[\"--product\"].(string)\n\n\tswitch {\n\tcase d[\"--remove-lock\"].(bool):\n\t\tt.handleRemoveLock(d)\n\tcase d[\"--config-dump\"].(bool):\n\t\tt.handleConfigDump(d)\n\tcase d[\"--config-convert\"] != nil:\n\t\tt.handleConfigConvert(d)\n\tcase d[\"--config-restore\"] != nil:\n\t\tt.handleConfigRestore(d)\n\tcase d[\"--dashboard-list\"].(bool):\n\t\tt.handleDashboardList(d)\n\t}\n}\n\nfunc (t *cmdAdmin) newTopomClient(d map[string]interface{}) models.Client {\n\tvar coordinator struct {\n\t\tname string\n\t\taddr string\n\t\tauth string\n\t}\n\n\tswitch {\n\tcase d[\"--zookeeper\"] != nil:\n\t\tcoordinator.name = \"zookeeper\"\n\t\tcoordinator.addr = utils.ArgumentMust(d, \"--zookeeper\")\n\t\tif d[\"--zookeeper-auth\"] != nil {\n\t\t\tcoordinator.auth = utils.ArgumentMust(d, \"--zookeeper-auth\")\n\t\t}\n\n\tcase d[\"--etcd\"] != nil:\n\t\tcoordinator.name = \"etcd\"\n\t\tcoordinator.addr = utils.ArgumentMust(d, \"--etcd\")\n\t\tif d[\"--etcd-auth\"] != nil {\n\t\t\tcoordinator.auth = utils.ArgumentMust(d, \"--etcd-auth\")\n\t\t}\n\n\tcase d[\"--filesystem\"] != nil:\n\t\tcoordinator.name = \"filesystem\"\n\t\tcoordinator.addr = utils.ArgumentMust(d, \"--filesystem\")\n\n\tdefault:\n\t\tlog.Panicf(\"invalid coordinator\")\n\t}\n\n\tc, err := models.NewClient(coordinator.name, coordinator.addr, coordinator.auth, time.Minute)\n\tif err != nil {\n\t\tlog.PanicErrorf(err, \"create '%s' client to '%s' failed\", coordinator.name, coordinator.addr)\n\t}\n\treturn c\n}\n\nfunc (t *cmdAdmin) newTopomStore(d map[string]interface{}) *models.Store {\n\tif err := models.ValidateProduct(t.product); err != nil {\n\t\tlog.PanicErrorf(err, \"invalid product name\")\n\t}\n\tclient := t.newTopomClient(d)\n\treturn models.NewStore(client, t.product)\n}\n\nfunc (t *cmdAdmin) handleRemoveLock(d map[string]interface{}) {\n\tstore := t.newTopomStore(d)\n\tdefer store.Close()\n\n\tlog.Debugf(\"force remove-lock\")\n\tif err := store.Release(); err != nil {\n\t\tlog.PanicErrorf(err, \"force remove-lock failed\")\n\t}\n\tlog.Debugf(\"force remove-lock OK\")\n}\n\nfunc (t *cmdAdmin) handleConfigDump(d map[string]interface{}) {\n\tswitch {\n\tcase d[\"-1\"].(bool):\n\t\tt.dumpConfigV1(d)\n\tdefault:\n\t\tt.dumpConfigV3(d)\n\t}\n}\n\ntype ConfigV3 struct {\n\tSlots []*models.SlotMapping `json:\"slots,omitempty\"`\n\tGroup []*models.Group       `json:\"group,omitempty\"`\n\tProxy []*models.Proxy       `json:\"proxy,omitempty\"`\n}\n\nfunc (t *cmdAdmin) dumpConfigV1(d map[string]interface{}) {\n\tclient := t.newTopomClient(d)\n\tdefer client.Close()\n\n\tprefix := filepath.Join(\"/zk/codis\", fmt.Sprintf(\"db_%s\", t.product))\n\tconfig := t.dumpConfigV1Recursively(client, prefix)\n\tif m, ok := config.(map[string]interface{}); !ok || m == nil {\n\t\tlog.Panicf(\"cann't find product = %s [v1]\", t.product)\n\t}\n\tb, err := json.MarshalIndent(config, \"\", \"    \")\n\tif err != nil {\n\t\tlog.PanicErrorf(err, \"json marshal failed\")\n\t}\n\tfmt.Println(string(b))\n}\n\nfunc (t *cmdAdmin) dumpConfigV1Recursively(client models.Client, path string) interface{} {\n\tfiles, err := client.List(path, false)\n\tif err != nil {\n\t\tlog.PanicErrorf(err, \"list path = %s failed\", path)\n\t}\n\tif len(files) != 0 {\n\t\tvar m = make(map[string]interface{})\n\t\tfor _, path := range files {\n\t\t\tm[filepath.Base(path)] = t.dumpConfigV1Recursively(client, path)\n\t\t}\n\t\treturn m\n\t}\n\tb, err := client.Read(path, false)\n\tif err != nil {\n\t\tlog.PanicErrorf(err, \"read file = %s failed\", path)\n\t}\n\tif len(b) != 0 {\n\t\tvar v interface{}\n\t\tif err := json.Unmarshal(b, &v); err != nil {\n\t\t\tlog.PanicErrorf(err, \"json unmarshal failed\")\n\t\t}\n\t\treturn v\n\t}\n\treturn nil\n}\n\nfunc (t *cmdAdmin) dumpConfigV3(d map[string]interface{}) {\n\tstore := t.newTopomStore(d)\n\tdefer store.Close()\n\n\tgroup, err := store.ListGroup()\n\tif err != nil {\n\t\tlog.PanicErrorf(err, \"list group failed\")\n\t}\n\tproxy, err := store.ListProxy()\n\tif err != nil {\n\t\tlog.PanicErrorf(err, \"list proxy failed\")\n\t}\n\n\tif len(group) == 0 && len(proxy) == 0 {\n\t\tlog.Panicf(\"cann't find product = %s [v3]\", t.product)\n\t}\n\n\tslots, err := store.SlotMappings()\n\tif err != nil {\n\t\tlog.PanicErrorf(err, \"list slots failed\")\n\t}\n\n\tconfig := &ConfigV3{\n\t\tSlots: slots,\n\t\tGroup: models.SortGroup(group),\n\t\tProxy: models.SortProxy(proxy),\n\t}\n\n\tb, err := json.MarshalIndent(config, \"\", \"    \")\n\tif err != nil {\n\t\tlog.PanicErrorf(err, \"json marshal failed\")\n\t}\n\tfmt.Println(string(b))\n}\n\nfunc (t *cmdAdmin) loadJsonConfigV1(file string) map[string]interface{} {\n\tb, err := ioutil.ReadFile(file)\n\tif err != nil {\n\t\tlog.PanicErrorf(err, \"read file '%s' failed\", file)\n\t}\n\tvar v interface{}\n\tif err := json.Unmarshal(b, &v); err != nil {\n\t\tlog.PanicErrorf(err, \"json unmarshal failed\")\n\t}\n\treturn v.(map[string]interface{})\n}\n\nfunc (t *cmdAdmin) convertSlotsV1(slots map[int]*models.SlotMapping, v interface{}) {\n\tm := v.(map[string]interface{})\n\n\tvar sid = int(m[\"id\"].(float64))\n\tvar gid = int(m[\"group_id\"].(float64))\n\tvar status = m[\"state\"].(map[string]interface{})[\"status\"].(string)\n\n\tlog.Debugf(\"found slot-%04d status = %s\", sid, status)\n\n\tswitch status {\n\tcase \"online\":\n\tcase \"offline\":\n\t\treturn\n\tdefault:\n\t\tlog.Panicf(\"invalid slot status\")\n\t}\n\n\tif slots[sid] != nil {\n\t\tlog.Panicf(\"slot-%04d already exists\", sid)\n\t}\n\tslots[sid] = &models.SlotMapping{\n\t\tId: sid, GroupId: gid,\n\t}\n}\n\nfunc (t *cmdAdmin) convertGroupV1(group map[int]*models.Group, v interface{}) {\n\tm := v.(map[string]interface{})\n\n\tvar addr = m[\"addr\"].(string)\n\tvar gid = int(m[\"group_id\"].(float64))\n\tvar master = m[\"type\"].(string) == \"master\"\n\n\tlog.Debugf(\"found group-%04d %s is master = %t\", gid, addr, master)\n\n\tif gid <= 0 || gid > models.MaxGroupId {\n\t\tlog.Panicf(\"invalid group = %d\", gid)\n\t}\n\n\tif group[gid] == nil {\n\t\tgroup[gid] = &models.Group{Id: gid}\n\t}\n\tg := group[gid]\n\n\tservers := []*models.GroupServer{}\n\tif master {\n\t\tservers = append(servers, &models.GroupServer{Addr: addr})\n\t\tservers = append(servers, g.Servers...)\n\t} else {\n\t\tservers = append(servers, g.Servers...)\n\t\tservers = append(servers, &models.GroupServer{Addr: addr})\n\t}\n\tg.Servers = servers\n}\n\nfunc (t *cmdAdmin) handleConfigConvert(d map[string]interface{}) {\n\tdefer func() {\n\t\tif x := recover(); x != nil {\n\t\t\tlog.Panicf(\"convert config failed: %+v\", x)\n\t\t}\n\t}()\n\n\tcfg1 := t.loadJsonConfigV1(utils.ArgumentMust(d, \"--config-convert\"))\n\tcfg2 := &ConfigV3{}\n\n\tif slots := cfg1[\"slots\"]; slots != nil {\n\t\ttemp := make(map[int]*models.SlotMapping)\n\t\tfor _, v := range slots.(map[string]interface{}) {\n\t\t\tt.convertSlotsV1(temp, v)\n\t\t}\n\t\tfor i := 0; i < models.MaxSlotNum; i++ {\n\t\t\tif temp[i] == nil {\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tcfg2.Slots = append(cfg2.Slots, temp[i])\n\t\t}\n\t}\n\n\tif servers := cfg1[\"servers\"]; servers != nil {\n\t\tgroup := make(map[int]*models.Group)\n\t\tfor _, g := range servers.(map[string]interface{}) {\n\t\t\tfor _, v := range g.(map[string]interface{}) {\n\t\t\t\tt.convertGroupV1(group, v)\n\t\t\t}\n\t\t}\n\t\tcfg2.Group = models.SortGroup(group)\n\t}\n\n\tb, err := json.MarshalIndent(cfg2, \"\", \"    \")\n\tif err != nil {\n\t\tlog.PanicErrorf(err, \"json marshal failed\")\n\t}\n\tfmt.Println(string(b))\n}\n\nfunc (t *cmdAdmin) loadJsonConfigV3(file string) *ConfigV3 {\n\tb, err := ioutil.ReadFile(file)\n\tif err != nil {\n\t\tlog.PanicErrorf(err, \"read file '%s' failed\", file)\n\t}\n\n\tconfig := &ConfigV3{}\n\tif err := json.Unmarshal(b, config); err != nil {\n\t\tlog.PanicErrorf(err, \"json unmarshal failed\")\n\t}\n\n\tvar proxy = make(map[string]*models.Proxy)\n\tfor _, p := range config.Proxy {\n\t\tif proxy[p.Token] != nil {\n\t\t\tlog.Panicf(\"proxy-%s already exists\", p.Token)\n\t\t}\n\t\tproxy[p.Token] = p\n\t}\n\n\tvar group = make(map[int]*models.Group)\n\tvar maddr = make(map[string]bool)\n\tfor _, g := range config.Group {\n\t\tif g.Id <= 0 || g.Id > models.MaxGroupId {\n\t\t\tlog.Panicf(\"invalid group id = %d\", g.Id)\n\t\t}\n\t\tif group[g.Id] != nil {\n\t\t\tlog.Panicf(\"group-%04d already exists\", g.Id)\n\t\t}\n\t\tif g.Promoting.State != models.ActionNothing {\n\t\t\tlog.Panicf(\"gorup-%04d is promoting\", g.Id)\n\t\t}\n\t\tfor _, x := range g.Servers {\n\t\t\taddr := x.Addr\n\t\t\tif maddr[addr] {\n\t\t\t\tlog.Panicf(\"server %s already exists\", addr)\n\t\t\t}\n\t\t\tmaddr[addr] = true\n\t\t}\n\t\tgroup[g.Id] = g\n\t}\n\n\tvar slots = make(map[int]*models.SlotMapping)\n\tfor _, s := range config.Slots {\n\t\tif s.Id < 0 || s.Id >= models.MaxSlotNum {\n\t\t\tlog.Panicf(\"invalid slot id = %d\", s.Id)\n\t\t}\n\t\tif slots[s.Id] != nil {\n\t\t\tlog.Panicf(\"slot-%04d already exists\", s.Id)\n\t\t}\n\t\tif s.Action.State != models.ActionNothing {\n\t\t\tlog.Panicf(\"slot-%04d action is not empty\", s.Id)\n\t\t}\n\t\tif g := group[s.GroupId]; g == nil || len(g.Servers) == 0 {\n\t\t\tlog.Panicf(\"slot-%04d with group-%04d doesn't exist or empty\", s.Id, s.GroupId)\n\t\t}\n\t\tslots[s.Id] = s\n\t}\n\n\treturn config\n}\n\nfunc (t *cmdAdmin) handleConfigRestore(d map[string]interface{}) {\n\tstore := t.newTopomStore(d)\n\tdefer store.Close()\n\n\tconfig := t.loadJsonConfigV3(utils.ArgumentMust(d, \"--config-restore\"))\n\n\tif !d[\"--confirm\"].(bool) {\n\t\tb, err := json.MarshalIndent(config, \"\", \"    \")\n\t\tif err != nil {\n\t\t\tlog.PanicErrorf(err, \"json marshal failed\")\n\t\t}\n\t\tfmt.Println(string(b))\n\t\treturn\n\t}\n\n\tproxy, err := store.ListProxy()\n\tif err != nil {\n\t\tlog.PanicErrorf(err, \"list proxy failed\")\n\t}\n\tgroup, err := store.ListGroup()\n\tif err != nil {\n\t\tlog.PanicErrorf(err, \"list group failed\")\n\t}\n\n\tif len(group) != 0 || len(proxy) != 0 {\n\t\tlog.Panicf(\"product %s is not empty\", t.product)\n\t}\n\n\tfor _, s := range config.Slots {\n\t\tif err := store.UpdateSlotMapping(s); err != nil {\n\t\t\tlog.PanicErrorf(err, \"restore slot-%04d failed\", s.Id)\n\t\t}\n\t}\n\n\tfor _, g := range config.Group {\n\t\tif err := store.UpdateGroup(g); err != nil {\n\t\t\tlog.PanicErrorf(err, \"restore group-%04d failed\", g.Id)\n\t\t}\n\t}\n\n\tfor _, p := range config.Proxy {\n\t\tif err := store.UpdateProxy(p); err != nil {\n\t\t\tlog.PanicErrorf(err, \"restore proxy-%s failed\", p.Token)\n\t\t}\n\t}\n}\n\nfunc (t *cmdAdmin) handleDashboardList(d map[string]interface{}) {\n\tclient := t.newTopomClient(d)\n\tdefer client.Close()\n\n\tlist, err := client.List(models.CodisDir, false)\n\tif err != nil {\n\t\tlog.PanicErrorf(err, \"list products failed\")\n\t}\n\n\tnodes := []interface{}{}\n\n\tfor _, path := range list {\n\t\tvar elem = &struct {\n\t\t\tName      string `json:\"name\"`\n\t\t\tDashboard string `json:\"dashboard\"`\n\t\t}{filepath.Base(path), \"\"}\n\n\t\tif b, err := client.Read(models.LockPath(elem.Name), false); err != nil {\n\t\t\tlog.PanicErrorf(err, \"read topom of product %s failed\", elem.Name)\n\t\t} else if b != nil {\n\t\t\tvar t = &models.Topom{}\n\t\t\tif err := json.Unmarshal(b, t); err != nil {\n\t\t\t\tlog.PanicErrorf(err, \"decode json failed\")\n\t\t\t}\n\t\t\telem.Dashboard = t.AdminAddr\n\t\t}\n\n\t\tnodes = append(nodes, elem)\n\t}\n\n\tif b, err := json.MarshalIndent(nodes, \"\", \"    \"); err != nil {\n\t\tlog.PanicErrorf(err, \"json encode failed\")\n\t} else {\n\t\tfmt.Println(string(b))\n\t}\n}\n"
  },
  {
    "path": "cmd/admin/dashboard.go",
    "content": "// Copyright 2016 CodisLabs. All Rights Reserved.\n// Licensed under the MIT (MIT-LICENSE.txt) license.\n\npackage main\n\nimport (\n\t\"encoding/json\"\n\t\"fmt\"\n\t\"sort\"\n\t\"strconv\"\n\n\t\"github.com/CodisLabs/codis/pkg/models\"\n\t\"github.com/CodisLabs/codis/pkg/topom\"\n\t\"github.com/CodisLabs/codis/pkg/utils\"\n\t\"github.com/CodisLabs/codis/pkg/utils/log\"\n\t\"github.com/CodisLabs/codis/pkg/utils/math2\"\n)\n\ntype cmdDashboard struct {\n\taddr string\n}\n\nfunc (t *cmdDashboard) Main(d map[string]interface{}) {\n\tt.addr = utils.ArgumentMust(d, \"--dashboard\")\n\n\tswitch {\n\n\tdefault:\n\t\tt.handleOverview(d)\n\n\tcase d[\"--shutdown\"].(bool):\n\t\tt.handleShutdown(d)\n\tcase d[\"--reload\"].(bool):\n\t\tt.handleReload(d)\n\tcase d[\"--log-level\"] != nil:\n\t\tt.handleLogLevel(d)\n\n\tcase d[\"--slots-assign\"].(bool):\n\t\tfallthrough\n\tcase d[\"--slots-status\"].(bool):\n\t\tt.handleSlotsCommand(d)\n\n\tcase d[\"--create-proxy\"].(bool):\n\t\tfallthrough\n\tcase d[\"--online-proxy\"].(bool):\n\t\tfallthrough\n\tcase d[\"--remove-proxy\"].(bool):\n\t\tfallthrough\n\tcase d[\"--reinit-proxy\"].(bool):\n\t\tfallthrough\n\tcase d[\"--proxy-status\"].(bool):\n\t\tt.handleProxyCommand(d)\n\n\tcase d[\"--create-group\"].(bool):\n\t\tfallthrough\n\tcase d[\"--remove-group\"].(bool):\n\t\tfallthrough\n\tcase d[\"--resync-group\"].(bool):\n\t\tfallthrough\n\tcase d[\"--group-add\"].(bool):\n\t\tfallthrough\n\tcase d[\"--group-del\"].(bool):\n\t\tfallthrough\n\tcase d[\"--group-status\"].(bool):\n\t\tfallthrough\n\tcase d[\"--replica-groups\"].(bool):\n\t\tfallthrough\n\tcase d[\"--promote-server\"].(bool):\n\t\tt.handleGroupCommand(d)\n\n\tcase d[\"--sentinel-add\"].(bool):\n\t\tfallthrough\n\tcase d[\"--sentinel-del\"].(bool):\n\t\tfallthrough\n\tcase d[\"--sentinel-resync\"].(bool):\n\t\tt.handleSentinelCommand(d)\n\n\tcase d[\"--sync-action\"].(bool):\n\t\tt.handleSyncActionCommand(d)\n\n\tcase d[\"--slot-action\"].(bool):\n\t\tt.handleSlotActionCommand(d)\n\n\tcase d[\"--rebalance\"].(bool):\n\t\tt.handleSlotRebalance(d)\n\n\t}\n}\n\nfunc (t *cmdDashboard) newTopomClient() *topom.ApiClient {\n\tc := topom.NewApiClient(t.addr)\n\n\tlog.Debugf(\"call rpc model to dashboard %s\", t.addr)\n\tp, err := c.Model()\n\tif err != nil {\n\t\tlog.PanicErrorf(err, \"call rpc model to dashboard %s failed\", t.addr)\n\t}\n\tlog.Debugf(\"call rpc model OK\")\n\n\tc.SetXAuth(p.ProductName)\n\n\tlog.Debugf(\"call rpc xping to dashboard %s\", t.addr)\n\tif err := c.XPing(); err != nil {\n\t\tlog.PanicErrorf(err, \"call rpc xping to dashboard %s failed\", t.addr)\n\t}\n\tlog.Debugf(\"call rpc xping OK\")\n\n\treturn c\n}\n\nfunc (t *cmdDashboard) handleOverview(d map[string]interface{}) {\n\tc := t.newTopomClient()\n\n\tlog.Debugf(\"call rpc overview to dashboard %s\", t.addr)\n\to, err := c.Overview()\n\tif err != nil {\n\t\tlog.PanicErrorf(err, \"call rpc overview to dashboard %s failed\", t.addr)\n\t}\n\tlog.Debugf(\"call rpc overview OK\")\n\n\tvar cmd string\n\tfor _, s := range []string{\"config\", \"model\", \"slots\", \"stats\", \"group\", \"proxy\", \"--list-group\", \"--list-proxy\"} {\n\t\tif d[s].(bool) {\n\t\t\tcmd = s\n\t\t}\n\t}\n\n\tvar obj interface{}\n\tswitch cmd {\n\tdefault:\n\t\tobj = o\n\tcase \"config\":\n\t\tobj = o.Config\n\tcase \"model\":\n\t\tobj = o.Model\n\tcase \"stats\":\n\t\tobj = o.Stats\n\tcase \"slots\":\n\t\tif o.Stats != nil {\n\t\t\tobj = o.Stats.Slots\n\t\t}\n\tcase \"group\":\n\t\tif o.Stats != nil {\n\t\t\tobj = o.Stats.Group\n\t\t}\n\tcase \"--list-group\":\n\t\tif o.Stats != nil {\n\t\t\tobj = o.Stats.Group.Models\n\t\t}\n\tcase \"proxy\":\n\t\tif o.Stats != nil {\n\t\t\tobj = o.Stats.Proxy\n\t\t}\n\tcase \"--list-proxy\":\n\t\tif o.Stats != nil {\n\t\t\tobj = o.Stats.Proxy.Models\n\t\t}\n\t}\n\n\tb, err := json.MarshalIndent(obj, \"\", \"    \")\n\tif err != nil {\n\t\tlog.PanicErrorf(err, \"json marshal failed\")\n\t}\n\tfmt.Println(string(b))\n}\n\nfunc (t *cmdDashboard) handleLogLevel(d map[string]interface{}) {\n\tc := t.newTopomClient()\n\n\ts := utils.ArgumentMust(d, \"--log-level\")\n\n\tvar v log.LogLevel\n\tif !v.ParseFromString(s) {\n\t\tlog.Panicf(\"option --log-level = %s\", s)\n\t}\n\n\tlog.Debugf(\"call rpc loglevel to dashboard %s\", t.addr)\n\tif err := c.LogLevel(v); err != nil {\n\t\tlog.PanicErrorf(err, \"call rpc loglevel to dashboard %s failed\", t.addr)\n\t}\n\tlog.Debugf(\"call rpc loglevel OK\")\n}\n\nfunc (t *cmdDashboard) handleShutdown(d map[string]interface{}) {\n\tc := t.newTopomClient()\n\n\tlog.Debugf(\"call rpc shutdown to dashboard %s\", t.addr)\n\tif err := c.Shutdown(); err != nil {\n\t\tlog.PanicErrorf(err, \"call rpc shutdown to dashboard %s failed\", t.addr)\n\t}\n\tlog.Debugf(\"call rpc shutdown OK\")\n}\n\nfunc (t *cmdDashboard) handleReload(d map[string]interface{}) {\n\tc := t.newTopomClient()\n\n\tlog.Debugf(\"call rpc reload to dashboard %s\", t.addr)\n\tif err := c.Reload(); err != nil {\n\t\tlog.PanicErrorf(err, \"call rpc reload to dashboard %s failed\", t.addr)\n\t}\n\tlog.Debugf(\"call rpc reload OK\")\n}\n\nfunc (t *cmdDashboard) handleSlotsCommand(d map[string]interface{}) {\n\tc := t.newTopomClient()\n\n\tswitch {\n\n\tcase d[\"--slots-status\"].(bool):\n\n\t\tlog.Debugf(\"call rpc slots to dashboard %s\", t.addr)\n\t\to, err := c.Slots()\n\t\tif err != nil {\n\t\t\tlog.PanicErrorf(err, \"call rpc slots to dashboard %s failed\", t.addr)\n\t\t}\n\t\tlog.Debugf(\"call rpc slots OK\")\n\n\t\tb, err := json.MarshalIndent(o, \"\", \"    \")\n\t\tif err != nil {\n\t\t\tlog.PanicErrorf(err, \"json marshal failed\")\n\t\t}\n\t\tfmt.Println(string(b))\n\n\tcase d[\"--slots-assign\"].(bool) && d[\"--offline\"].(bool):\n\n\t\tbeg := utils.ArgumentIntegerMust(d, \"--beg\")\n\t\tend := utils.ArgumentIntegerMust(d, \"--end\")\n\n\t\tslots := []*models.SlotMapping{}\n\t\tfor i := beg; i <= end; i++ {\n\t\t\tslots = append(slots, &models.SlotMapping{\n\t\t\t\tId: i,\n\t\t\t})\n\t\t}\n\n\t\tif !d[\"--confirm\"].(bool) {\n\t\t\tb, err := json.MarshalIndent(slots, \"\", \"    \")\n\t\t\tif err != nil {\n\t\t\t\tlog.PanicErrorf(err, \"json marshal failed\")\n\t\t\t}\n\t\t\tfmt.Println(string(b))\n\t\t\treturn\n\t\t}\n\n\t\tlog.Debugf(\"call rpc slots-assign to dashboard %s\", t.addr)\n\t\tif err := c.SlotsAssignOffline(slots); err != nil {\n\t\t\tlog.PanicErrorf(err, \"call rpc slots-assign to dashboard %s failed\", t.addr)\n\t\t}\n\t\tlog.Debugf(\"call rpc slots-assign OK\")\n\n\tcase d[\"--slots-assign\"].(bool) && !d[\"--offline\"].(bool):\n\n\t\tbeg := utils.ArgumentIntegerMust(d, \"--beg\")\n\t\tend := utils.ArgumentIntegerMust(d, \"--end\")\n\t\tgid := utils.ArgumentIntegerMust(d, \"--gid\")\n\n\t\tslots := []*models.SlotMapping{}\n\t\tfor i := beg; i <= end; i++ {\n\t\t\tslots = append(slots, &models.SlotMapping{\n\t\t\t\tId: i, GroupId: gid,\n\t\t\t})\n\t\t}\n\n\t\tif !d[\"--confirm\"].(bool) {\n\t\t\tb, err := json.MarshalIndent(slots, \"\", \"    \")\n\t\t\tif err != nil {\n\t\t\t\tlog.PanicErrorf(err, \"json marshal failed\")\n\t\t\t}\n\t\t\tfmt.Println(string(b))\n\t\t\treturn\n\t\t}\n\n\t\tlog.Debugf(\"call rpc slots-assign to dashboard %s\", t.addr)\n\t\tif err := c.SlotsAssignGroup(slots); err != nil {\n\t\t\tlog.PanicErrorf(err, \"call rpc slots-assign to dashboard %s failed\", t.addr)\n\t\t}\n\t\tlog.Debugf(\"call rpc slots-assign OK\")\n\n\t}\n}\n\nfunc (t *cmdDashboard) parseProxyTokens(d map[string]interface{}) []string {\n\tswitch {\n\n\tdefault:\n\n\t\tlog.Panicf(\"can't find specific proxy\")\n\n\t\treturn nil\n\n\tcase d[\"--token\"] != nil:\n\n\t\treturn []string{utils.ArgumentMust(d, \"--token\")}\n\n\tcase d[\"--pid\"] != nil:\n\n\t\tpid := utils.ArgumentIntegerMust(d, \"--pid\")\n\n\t\tc := t.newTopomClient()\n\n\t\tlog.Debugf(\"call rpc stats to dashboard %s\", t.addr)\n\t\ts, err := c.Stats()\n\t\tif err != nil {\n\t\t\tlog.PanicErrorf(err, \"call rpc stats to dashboard %s failed\", t.addr)\n\t\t}\n\t\tlog.Debugf(\"call rpc stats OK\")\n\n\t\tvar tokens []string\n\n\t\tfor _, p := range s.Proxy.Models {\n\t\t\tif p.Id == pid {\n\t\t\t\ttokens = append(tokens, p.Token)\n\t\t\t}\n\t\t}\n\n\t\tif len(tokens) != 0 {\n\t\t\treturn tokens\n\t\t}\n\n\t\tif !d[\"--force\"].(bool) {\n\t\t\tlog.Panicf(\"can't find specific proxy with id = %d\", pid)\n\t\t}\n\t\treturn nil\n\n\tcase d[\"--addr\"] != nil:\n\n\t\taddr := utils.ArgumentMust(d, \"--addr\")\n\n\t\tc := t.newTopomClient()\n\n\t\tlog.Debugf(\"call rpc stats to dashboard %s\", t.addr)\n\t\ts, err := c.Stats()\n\t\tif err != nil {\n\t\t\tlog.PanicErrorf(err, \"call rpc stats to dashboard %s failed\", t.addr)\n\t\t}\n\t\tlog.Debugf(\"call rpc stats OK\")\n\n\t\tvar tokens []string\n\n\t\tfor _, p := range s.Proxy.Models {\n\t\t\tif p.AdminAddr == addr {\n\t\t\t\ttokens = append(tokens, p.Token)\n\t\t\t}\n\t\t}\n\n\t\tif len(tokens) != 0 {\n\t\t\treturn tokens\n\t\t}\n\n\t\tif !d[\"--force\"].(bool) {\n\t\t\tlog.Panicf(\"can't find specific proxy with addr = %s\", addr)\n\t\t}\n\t\treturn nil\n\n\t}\n}\n\nfunc (t *cmdDashboard) handleProxyCommand(d map[string]interface{}) {\n\tc := t.newTopomClient()\n\n\tswitch {\n\n\tcase d[\"--create-proxy\"].(bool):\n\n\t\taddr := utils.ArgumentMust(d, \"--addr\")\n\n\t\tlog.Debugf(\"call rpc create-proxy to dashboard %s\", t.addr)\n\t\tif err := c.CreateProxy(addr); err != nil {\n\t\t\tlog.PanicErrorf(err, \"call rpc create-proxy to dashboard %s failed\", t.addr)\n\t\t}\n\t\tlog.Debugf(\"call rpc create-proxy OK\")\n\n\tcase d[\"--online-proxy\"].(bool):\n\n\t\taddr := utils.ArgumentMust(d, \"--addr\")\n\n\t\tlog.Debugf(\"call rpc online-proxy to dashboard %s\", t.addr)\n\t\tif err := c.OnlineProxy(addr); err != nil {\n\t\t\tlog.PanicErrorf(err, \"call rpc online-proxy to dashboard %s failed\", t.addr)\n\t\t}\n\t\tlog.Debugf(\"call rpc online-proxy OK\")\n\n\tcase d[\"--remove-proxy\"].(bool):\n\n\t\tforce := d[\"--force\"].(bool)\n\n\t\tfor _, token := range t.parseProxyTokens(d) {\n\t\t\tlog.Debugf(\"call rpc remove-proxy to dashboard %s\", t.addr)\n\t\t\tif err := c.RemoveProxy(token, force); err != nil {\n\t\t\t\tlog.PanicErrorf(err, \"call rpc remove-proxy to dashboard %s failed\", t.addr)\n\t\t\t}\n\t\t\tlog.Debugf(\"call rpc remove-proxy OK\")\n\t\t}\n\n\tcase d[\"--reinit-proxy\"].(bool):\n\n\t\tswitch {\n\n\t\tdefault:\n\n\t\t\tfor _, token := range t.parseProxyTokens(d) {\n\t\t\t\tlog.Debugf(\"call rpc reinit-proxy to dashboard %s\", t.addr)\n\t\t\t\tif err := c.ReinitProxy(token); err != nil {\n\t\t\t\t\tlog.PanicErrorf(err, \"call rpc reinit-proxy to dashboard %s failed\", t.addr)\n\t\t\t\t}\n\t\t\t\tlog.Debugf(\"call rpc reinit-proxy OK\")\n\t\t\t}\n\n\t\tcase d[\"--all\"].(bool):\n\n\t\t\tlog.Debugf(\"call rpc stats to dashboard %s\", t.addr)\n\t\t\ts, err := c.Stats()\n\t\t\tif err != nil {\n\t\t\t\tlog.PanicErrorf(err, \"call rpc stats to dashboard %s failed\", t.addr)\n\t\t\t}\n\t\t\tlog.Debugf(\"call rpc stats OK\")\n\n\t\t\tfor _, p := range s.Proxy.Models {\n\t\t\t\tfmt.Printf(\"reinit proxy: %s\\n\", p.Encode())\n\t\t\t\tlog.Debugf(\"call rpc reinit-proxy to dashboard %s\", t.addr)\n\t\t\t\tif err := c.ReinitProxy(p.Token); err != nil {\n\t\t\t\t\tlog.PanicErrorf(err, \"call rpc reinit-proxy to dashboard %s failed\", t.addr)\n\t\t\t\t}\n\t\t\t\tlog.Debugf(\"call rpc reinit-proxy OK\")\n\t\t\t}\n\n\t\t}\n\n\tcase d[\"--proxy-status\"].(bool):\n\n\t\tlog.Debugf(\"call rpc stats to dashboard %s\", t.addr)\n\t\ts, err := c.Stats()\n\t\tif err != nil {\n\t\t\tlog.PanicErrorf(err, \"call rpc stats to dashboard %s failed\", t.addr)\n\t\t}\n\t\tlog.Debugf(\"call rpc stats OK\")\n\n\t\tvar format string\n\t\tvar wpid int\n\t\tfor _, p := range s.Proxy.Models {\n\t\t\twpid = math2.MaxInt(wpid, len(strconv.Itoa(p.Id)))\n\t\t}\n\t\tformat += fmt.Sprintf(\"proxy-%%0%dd [T] %%s\", wpid)\n\n\t\tvar waddr1, waddr2 int\n\t\tfor _, p := range s.Proxy.Models {\n\t\t\twaddr1 = math2.MaxInt(waddr1, len(p.AdminAddr))\n\t\t\twaddr2 = math2.MaxInt(waddr2, len(p.ProxyAddr))\n\t\t}\n\t\tformat += fmt.Sprintf(\" [A] %%-%ds\", waddr1)\n\t\tformat += fmt.Sprintf(\" [P] %%-%ds\", waddr2)\n\n\t\tfor _, p := range s.Proxy.Models {\n\t\t\tvar xfmt string\n\t\t\tswitch stats := s.Proxy.Stats[p.Token]; {\n\t\t\tcase stats == nil:\n\t\t\t\txfmt = \"[?] \" + format\n\t\t\tcase stats.Error != nil:\n\t\t\t\txfmt = \"[E] \" + format\n\t\t\tcase stats.Timeout || stats.Stats == nil:\n\t\t\t\txfmt = \"[T] \" + format\n\t\t\tdefault:\n\t\t\t\txfmt = \"[ ] \" + format\n\t\t\t}\n\t\t\tfmt.Printf(xfmt, p.Id, p.Token, p.AdminAddr, p.ProxyAddr)\n\t\t\tfmt.Println()\n\t\t}\n\t}\n}\n\nfunc (t *cmdDashboard) handleGroupCommand(d map[string]interface{}) {\n\tc := t.newTopomClient()\n\n\tswitch {\n\n\tcase d[\"--create-group\"].(bool):\n\n\t\tgid := utils.ArgumentIntegerMust(d, \"--gid\")\n\n\t\tlog.Debugf(\"call rpc create-group to dashboard %s\", t.addr)\n\t\tif err := c.CreateGroup(gid); err != nil {\n\t\t\tlog.PanicErrorf(err, \"call rpc create-group to dashboard %s failed\", t.addr)\n\t\t}\n\t\tlog.Debugf(\"call rpc create-group OK\")\n\n\tcase d[\"--remove-group\"].(bool):\n\n\t\tgid := utils.ArgumentIntegerMust(d, \"--gid\")\n\n\t\tlog.Debugf(\"call rpc remove-group to dashboard %s\", t.addr)\n\t\tif err := c.RemoveGroup(gid); err != nil {\n\t\t\tlog.PanicErrorf(err, \"call rpc remove-group to dashboard %s failed\", t.addr)\n\t\t}\n\t\tlog.Debugf(\"call rpc remove-group OK\")\n\n\tcase d[\"--resync-group\"].(bool):\n\n\t\tswitch {\n\n\t\tcase d[\"--all\"].(bool):\n\n\t\t\tstats, err := c.Stats()\n\t\t\tif err != nil {\n\t\t\t\tlog.PanicErrorf(err, \"call rpc stats to dashboard %s failed\", t.addr)\n\t\t\t}\n\t\t\tlog.Debugf(\"call rpc stats OK\")\n\n\t\t\tfor _, g := range stats.Group.Models {\n\t\t\t\tlog.Debugf(\"call rpc resync-group [%d] to dashboard %s\", g.Id, t.addr)\n\t\t\t\tif err := c.ResyncGroup(g.Id); err != nil {\n\t\t\t\t\tlog.PanicErrorf(err, \"call rpc resync-group to dashboard %s failed\", t.addr)\n\t\t\t\t}\n\t\t\t}\n\t\t\tlog.Debugf(\"call rpc resync-group OK\")\n\n\t\tdefault:\n\n\t\t\tgid := utils.ArgumentIntegerMust(d, \"--gid\")\n\n\t\t\tlog.Debugf(\"call rpc resync-group to dashboard %s\", t.addr)\n\t\t\tif err := c.ResyncGroup(gid); err != nil {\n\t\t\t\tlog.PanicErrorf(err, \"call rpc resync-group to dashboard %s failed\", t.addr)\n\t\t\t}\n\t\t\tlog.Debugf(\"call rpc resync-group OK\")\n\n\t\t}\n\n\tcase d[\"--group-add\"].(bool):\n\n\t\tgid, addr := utils.ArgumentIntegerMust(d, \"--gid\"), utils.ArgumentMust(d, \"--addr\")\n\t\tdc, _ := utils.Argument(d, \"--datacenter\")\n\n\t\tlog.Debugf(\"call rpc group-add-server to dashboard %s\", t.addr)\n\t\tif err := c.GroupAddServer(gid, dc, addr); err != nil {\n\t\t\tlog.PanicErrorf(err, \"call rpc group-add-server to dashboard %s failed\", t.addr)\n\t\t}\n\t\tlog.Debugf(\"call rpc group-add-server OK\")\n\n\tcase d[\"--group-del\"].(bool):\n\n\t\tgid, addr := utils.ArgumentIntegerMust(d, \"--gid\"), utils.ArgumentMust(d, \"--addr\")\n\n\t\tlog.Debugf(\"call rpc group-del-server to dashboard %s\", t.addr)\n\t\tif err := c.GroupDelServer(gid, addr); err != nil {\n\t\t\tlog.PanicErrorf(err, \"call rpc group-del-server to dashboard %s failed\", t.addr)\n\t\t}\n\t\tlog.Debugf(\"call rpc group-del-server OK\")\n\n\tcase d[\"--replica-groups\"].(bool):\n\n\t\tgid, addr := utils.ArgumentIntegerMust(d, \"--gid\"), utils.ArgumentMust(d, \"--addr\")\n\t\tvalue := d[\"--enable\"].(bool)\n\n\t\tlog.Debugf(\"call rpc replica-groups to dashboard %s\", t.addr)\n\t\tif err := c.EnableReplicaGroups(gid, addr, value); err != nil {\n\t\t\tlog.PanicErrorf(err, \"call rpc replica-groups to dashboard %s failed\", t.addr)\n\t\t}\n\t\tlog.Debugf(\"call rpc replica-groups to dashboard OK\")\n\n\tcase d[\"--promote-server\"].(bool):\n\n\t\tgid, addr := utils.ArgumentIntegerMust(d, \"--gid\"), utils.ArgumentMust(d, \"--addr\")\n\n\t\tlog.Debugf(\"call rpc group-promote-server to dashboard %s\", t.addr)\n\t\tif err := c.GroupPromoteServer(gid, addr); err != nil {\n\t\t\tlog.PanicErrorf(err, \"call rpc group-promote-server to dashboard %s failed\", t.addr)\n\t\t}\n\t\tlog.Debugf(\"call rpc group-promote-server OK\")\n\n\t\tfallthrough\n\n\tcase d[\"--group-status\"].(bool):\n\n\t\tlog.Debugf(\"call rpc stats to dashboard %s\", t.addr)\n\t\ts, err := c.Stats()\n\t\tif err != nil {\n\t\t\tlog.PanicErrorf(err, \"call rpc stats to dashboard %s failed\", t.addr)\n\t\t}\n\t\tlog.Debugf(\"call rpc stats OK\")\n\n\t\tvar format string\n\t\tvar wgid, widx int\n\t\tfor _, g := range s.Group.Models {\n\t\t\twgid = math2.MaxInt(wgid, len(strconv.Itoa(g.Id)))\n\t\t\tfor i, _ := range g.Servers {\n\t\t\t\twidx = math2.MaxInt(widx, len(strconv.Itoa(i)))\n\t\t\t}\n\t\t}\n\t\tformat += fmt.Sprintf(\"group-%%0%dd [%%0%dd]\", wgid, widx)\n\n\t\tvar waddr int\n\t\tfor _, g := range s.Group.Models {\n\t\t\tfor _, x := range g.Servers {\n\t\t\t\twaddr = math2.MaxInt(waddr, len(x.Addr))\n\t\t\t}\n\t\t}\n\t\tformat += fmt.Sprintf(\" %%-%ds\", waddr)\n\n\t\tfor _, g := range s.Group.Models {\n\t\t\tfor i, x := range g.Servers {\n\t\t\t\tvar addr = x.Addr\n\t\t\t\tswitch stats := s.Group.Stats[addr]; {\n\t\t\t\tcase stats == nil:\n\t\t\t\t\tfmt.Printf(\"[?] \"+format, g.Id, i, addr)\n\t\t\t\tcase stats.Error != nil:\n\t\t\t\t\tfmt.Printf(\"[E] \"+format, g.Id, i, addr)\n\t\t\t\tcase stats.Timeout || stats.Stats == nil:\n\t\t\t\t\tfmt.Printf(\"[T] \"+format, g.Id, i, addr)\n\t\t\t\tdefault:\n\t\t\t\t\tvar master string\n\t\t\t\t\tif s, ok := stats.Stats[\"master_addr\"]; ok {\n\t\t\t\t\t\tmaster = s + \":\" + stats.Stats[\"master_link_status\"]\n\t\t\t\t\t} else {\n\t\t\t\t\t\tmaster = \"NO:ONE\"\n\t\t\t\t\t}\n\t\t\t\t\tvar expect string\n\t\t\t\t\tif i == 0 {\n\t\t\t\t\t\texpect = \"NO:ONE\"\n\t\t\t\t\t} else {\n\t\t\t\t\t\texpect = g.Servers[0].Addr + \":up\"\n\t\t\t\t\t}\n\t\t\t\t\tif master == expect {\n\t\t\t\t\t\tfmt.Printf(\"[ ] \"+format, g.Id, i, addr)\n\t\t\t\t\t} else {\n\t\t\t\t\t\tfmt.Printf(\"[X] \"+format, g.Id, i, addr)\n\t\t\t\t\t}\n\t\t\t\t\tfmt.Printf(\"      ==> %s\", master)\n\t\t\t\t}\n\t\t\t\tfmt.Println()\n\t\t\t}\n\t\t}\n\t}\n}\n\nfunc (t *cmdDashboard) handleSentinelCommand(d map[string]interface{}) {\n\tc := t.newTopomClient()\n\n\tswitch {\n\n\tcase d[\"--sentinel-add\"].(bool):\n\n\t\taddr := utils.ArgumentMust(d, \"--addr\")\n\n\t\tlog.Debugf(\"call rpc add-sentinel to dashboard %s\", t.addr)\n\t\tif err := c.AddSentinel(addr); err != nil {\n\t\t\tlog.PanicErrorf(err, \"call rpc add-sentinel to dashboard %s failed\", t.addr)\n\t\t}\n\t\tlog.Debugf(\"call rpc add-sentinel OK\")\n\n\tcase d[\"--sentinel-del\"].(bool):\n\n\t\taddr := utils.ArgumentMust(d, \"--addr\")\n\n\t\tforce := d[\"--force\"].(bool)\n\n\t\tlog.Debugf(\"call rpc del-sentinel to dashboard %s\", t.addr)\n\t\tif err := c.DelSentinel(addr, force); err != nil {\n\t\t\tlog.PanicErrorf(err, \"call rpc del-sentinel to dashboard %s failed\", t.addr)\n\t\t}\n\t\tlog.Debugf(\"call rpc del-sentinel OK\")\n\n\tcase d[\"--sentinel-resync\"].(bool):\n\n\t\tlog.Debugf(\"call rpc resync-sentinels to dashboard %s\", t.addr)\n\t\tif err := c.ResyncSentinels(); err != nil {\n\t\t\tlog.PanicErrorf(err, \"call rpc resync-sentinels to dashboard %s failed\", t.addr)\n\t\t}\n\t\tlog.Debugf(\"call rpc resync-sentinels OK\")\n\n\t}\n}\n\nfunc (t *cmdDashboard) handleSyncActionCommand(d map[string]interface{}) {\n\tc := t.newTopomClient()\n\n\tswitch {\n\n\tcase d[\"--create\"].(bool):\n\n\t\taddr := utils.ArgumentMust(d, \"--addr\")\n\n\t\tlog.Debugf(\"call rpc create-sync-action to dashboard %s\", t.addr)\n\t\tif err := c.SyncCreateAction(addr); err != nil {\n\t\t\tlog.PanicErrorf(err, \"call rpc create-sync-action to dashboard %s failed\", t.addr)\n\t\t}\n\t\tlog.Debugf(\"call rpc create-sync-action OK\")\n\n\tcase d[\"--remove\"].(bool):\n\n\t\taddr := utils.ArgumentMust(d, \"--addr\")\n\n\t\tlog.Debugf(\"call rpc remove-sync-action to dashboard %s\", t.addr)\n\t\tif err := c.SyncRemoveAction(addr); err != nil {\n\t\t\tlog.PanicErrorf(err, \"call rpc remove-sync-action to dashboard %s failed\", t.addr)\n\t\t}\n\t\tlog.Debugf(\"call rpc remove-sync-action OK\")\n\n\t}\n\n}\n\nfunc (t *cmdDashboard) handleSlotActionCommand(d map[string]interface{}) {\n\tc := t.newTopomClient()\n\n\tswitch {\n\n\tcase d[\"--create\"].(bool):\n\n\t\tsid := utils.ArgumentIntegerMust(d, \"--sid\")\n\t\tgid := utils.ArgumentIntegerMust(d, \"--gid\")\n\n\t\tlog.Debugf(\"call rpc create-slot-action to dashboard %s\", t.addr)\n\t\tif err := c.SlotCreateAction(sid, gid); err != nil {\n\t\t\tlog.PanicErrorf(err, \"call rpc create-slot-action to dashboard %s failed\", t.addr)\n\t\t}\n\t\tlog.Debugf(\"call rpc create-slot-action OK\")\n\n\tcase d[\"--remove\"].(bool):\n\n\t\tsid := utils.ArgumentIntegerMust(d, \"--sid\")\n\n\t\tlog.Debugf(\"call rpc remove-slot-action to dashboard %s\", t.addr)\n\t\tif err := c.SlotRemoveAction(sid); err != nil {\n\t\t\tlog.PanicErrorf(err, \"call rpc remove-slot-action to dashboard %s failed\", t.addr)\n\t\t}\n\t\tlog.Debugf(\"call rpc remove-slot-action OK\")\n\n\tcase d[\"--create-some\"].(bool):\n\n\t\tsrc := utils.ArgumentIntegerMust(d, \"--gid-from\")\n\t\tdst := utils.ArgumentIntegerMust(d, \"--gid-to\")\n\t\tnum := utils.ArgumentIntegerMust(d, \"--num-slots\")\n\n\t\tlog.Debugf(\"call rpc create-slot-action-some to dashboard %s\", t.addr)\n\t\tif err := c.SlotCreateActionSome(src, dst, num); err != nil {\n\t\t\tlog.PanicErrorf(err, \"call rpc create-slot-action-some to dashboard %s failed\", t.addr)\n\t\t}\n\t\tlog.Debugf(\"call rpc create-slot-action-some OK\")\n\n\tcase d[\"--create-range\"].(bool):\n\n\t\tbeg := utils.ArgumentIntegerMust(d, \"--beg\")\n\t\tend := utils.ArgumentIntegerMust(d, \"--end\")\n\t\tgid := utils.ArgumentIntegerMust(d, \"--gid\")\n\n\t\tlog.Debugf(\"call rpc create-slot-action-range to dashboard %s\", t.addr)\n\t\tif err := c.SlotCreateActionRange(beg, end, gid); err != nil {\n\t\t\tlog.PanicErrorf(err, \"call rpc create-slot-action-range to dashboard %s failed\", t.addr)\n\t\t}\n\t\tlog.Debugf(\"call rpc create-slot-action-range OK\")\n\n\tcase d[\"--interval\"] != nil:\n\n\t\tvalue := utils.ArgumentIntegerMust(d, \"--interval\")\n\n\t\tlog.Debugf(\"call rpc slot-action-interval to dashboard %s\", t.addr)\n\t\tif err := c.SetSlotActionInterval(value); err != nil {\n\t\t\tlog.PanicErrorf(err, \"call rpc slot-action-interval to dashboard %s failed\", t.addr)\n\t\t}\n\t\tlog.Debugf(\"call rpc slot-action-interval OK\")\n\n\tcase d[\"--disabled\"] != nil:\n\n\t\tvalue := utils.ArgumentIntegerMust(d, \"--disabled\")\n\n\t\tlog.Debugf(\"call rpc slot-action-disabled to dashboard %s\", t.addr)\n\t\tif err := c.SetSlotActionDisabled(value != 0); err != nil {\n\t\t\tlog.PanicErrorf(err, \"call rpc slot-action-disabled to dashboard %s failed\", t.addr)\n\t\t}\n\t\tlog.Debugf(\"call rpc slot-action-disabled OK\")\n\n\t}\n}\n\nfunc (t *cmdDashboard) handleSlotRebalance(d map[string]interface{}) {\n\tc := t.newTopomClient()\n\n\tconfirm := d[\"--confirm\"].(bool)\n\n\tlog.Debugf(\"call rpc slot-rebalance to dashboard %s\", t.addr)\n\tplans, err := c.SlotsRebalance(confirm)\n\tif err != nil {\n\t\tlog.PanicErrorf(err, \"call rpc slot-rebalance to dashboard %s failed\", t.addr)\n\t}\n\tlog.Debugf(\"call rpc slot-rebalance OK\")\n\n\tif len(plans) == 0 {\n\t\tfmt.Println(\"nothing changes\")\n\t} else {\n\t\tvar slotIds = make([]int, 0, len(plans))\n\t\tfor sid := range plans {\n\t\t\tslotIds = append(slotIds, sid)\n\t\t}\n\t\tsort.Ints(slotIds)\n\n\t\tvar gid, beg, end = -1, 0, -1\n\t\tfor _, sid := range slotIds {\n\t\t\tif beg <= end {\n\t\t\t\tif sid == end+1 && plans[sid] == gid {\n\t\t\t\t\tend = sid\n\t\t\t\t\tcontinue\n\t\t\t\t}\n\t\t\t\tfmt.Printf(\"[%04d,%04d] => %d\\n\", beg, end, gid)\n\t\t\t}\n\t\t\tbeg, end, gid = sid, sid, plans[sid]\n\t\t}\n\t\tif beg <= end {\n\t\t\tfmt.Printf(\"[%04d,%04d] => %d\\n\", beg, end, gid)\n\t\t}\n\t\tfmt.Println(\"done\")\n\t}\n}\n"
  },
  {
    "path": "cmd/admin/main.go",
    "content": "// Copyright 2016 CodisLabs. All Rights Reserved.\n// Licensed under the MIT (MIT-LICENSE.txt) license.\n\npackage main\n\nimport (\n\t\"github.com/docopt/docopt-go\"\n\n\t\"github.com/CodisLabs/codis/pkg/utils/log\"\n)\n\nfunc main() {\n\tconst usage = `\nUsage:\n\tcodis-admin [-v] --proxy=ADDR [--auth=AUTH] [config|model|stats|slots]\n\tcodis-admin [-v] --proxy=ADDR [--auth=AUTH]  --start\n\tcodis-admin [-v] --proxy=ADDR [--auth=AUTH]  --shutdown\n\tcodis-admin [-v] --proxy=ADDR [--auth=AUTH]  --log-level=LEVEL\n\tcodis-admin [-v] --proxy=ADDR [--auth=AUTH]  --fillslots=FILE [--locked]\n\tcodis-admin [-v] --proxy=ADDR [--auth=AUTH]  --reset-stats\n\tcodis-admin [-v] --proxy=ADDR [--auth=AUTH]  --forcegc\n\tcodis-admin [-v] --dashboard=ADDR           [config|model|stats|slots|group|proxy]\n\tcodis-admin [-v] --dashboard=ADDR            --shutdown\n\tcodis-admin [-v] --dashboard=ADDR            --reload\n\tcodis-admin [-v] --dashboard=ADDR            --log-level=LEVEL\n\tcodis-admin [-v] --dashboard=ADDR            --slots-assign   --beg=ID --end=ID (--gid=ID|--offline) [--confirm]\n\tcodis-admin [-v] --dashboard=ADDR            --slots-status\n\tcodis-admin [-v] --dashboard=ADDR            --list-proxy\n\tcodis-admin [-v] --dashboard=ADDR            --create-proxy   --addr=ADDR\n\tcodis-admin [-v] --dashboard=ADDR            --online-proxy   --addr=ADDR\n\tcodis-admin [-v] --dashboard=ADDR            --remove-proxy  (--addr=ADDR|--token=TOKEN|--pid=ID)       [--force]\n\tcodis-admin [-v] --dashboard=ADDR            --reinit-proxy  (--addr=ADDR|--token=TOKEN|--pid=ID|--all) [--force]\n\tcodis-admin [-v] --dashboard=ADDR            --proxy-status\n\tcodis-admin [-v] --dashboard=ADDR            --list-group\n\tcodis-admin [-v] --dashboard=ADDR            --create-group   --gid=ID\n\tcodis-admin [-v] --dashboard=ADDR            --remove-group   --gid=ID\n\tcodis-admin [-v] --dashboard=ADDR            --resync-group  [--gid=ID | --all]\n\tcodis-admin [-v] --dashboard=ADDR            --group-add      --gid=ID --addr=ADDR [--datacenter=DATACENTER]\n\tcodis-admin [-v] --dashboard=ADDR            --group-del      --gid=ID --addr=ADDR\n\tcodis-admin [-v] --dashboard=ADDR            --group-status\n\tcodis-admin [-v] --dashboard=ADDR            --replica-groups --gid=ID --addr=ADDR (--enable|--disable)\n\tcodis-admin [-v] --dashboard=ADDR            --promote-server --gid=ID --addr=ADDR\n\tcodis-admin [-v] --dashboard=ADDR            --sync-action    --create --addr=ADDR\n\tcodis-admin [-v] --dashboard=ADDR            --sync-action    --remove --addr=ADDR\n\tcodis-admin [-v] --dashboard=ADDR            --slot-action    --create --sid=ID --gid=ID\n\tcodis-admin [-v] --dashboard=ADDR            --slot-action    --remove --sid=ID\n\tcodis-admin [-v] --dashboard=ADDR            --slot-action    --create-some  --gid-from=ID --gid-to=ID --num-slots=N\n\tcodis-admin [-v] --dashboard=ADDR            --slot-action    --create-range --beg=ID --end=ID --gid=ID\n\tcodis-admin [-v] --dashboard=ADDR            --slot-action    --interval=VALUE\n\tcodis-admin [-v] --dashboard=ADDR            --slot-action    --disabled=VALUE\n\tcodis-admin [-v] --dashboard=ADDR            --rebalance     [--confirm]\n\tcodis-admin [-v] --dashboard=ADDR            --sentinel-add   --addr=ADDR\n\tcodis-admin [-v] --dashboard=ADDR            --sentinel-del   --addr=ADDR [--force]\n\tcodis-admin [-v] --dashboard=ADDR            --sentinel-resync\n\tcodis-admin [-v] --remove-lock               --product=NAME (--zookeeper=ADDR [--zookeeper-auth=USR:PWD]|--etcd=ADDR [--etcd-auth=USR:PWD]|--filesystem=ROOT)\n\tcodis-admin [-v] --config-dump               --product=NAME (--zookeeper=ADDR [--zookeeper-auth=USR:PWD]|--etcd=ADDR [--etcd-auth=USR:PWD]|--filesystem=ROOT) [-1]\n\tcodis-admin [-v] --config-convert=FILE\n\tcodis-admin [-v] --config-restore=FILE       --product=NAME (--zookeeper=ADDR [--zookeeper-auth=USR:PWD]|--etcd=ADDR [--etcd-auth=USR:PWD]|--filesystem=ROOT) [--confirm]\n\tcodis-admin [-v] --dashboard-list                           (--zookeeper=ADDR [--zookeeper-auth=USR:PWD]|--etcd=ADDR [--etcd-auth=USR:PWD]|--filesystem=ROOT)\n\nOptions:\n\t-a AUTH, --auth=AUTH\n\t-x ADDR, --addr=ADDR\n\t-t TOKEN, --token=TOKEN\n\t-g ID, --gid=ID\n`\n\n\td, err := docopt.Parse(usage, nil, true, \"\", false)\n\tif err != nil {\n\t\tlog.PanicError(err, \"parse arguments failed\")\n\t}\n\tlog.SetLevel(log.LevelInfo)\n\n\tif d[\"-v\"].(bool) {\n\t\tlog.SetLevel(log.LevelDebug)\n\t}\n\n\tswitch {\n\tcase d[\"--proxy\"] != nil:\n\t\tnew(cmdProxy).Main(d)\n\tcase d[\"--dashboard\"] != nil:\n\t\tnew(cmdDashboard).Main(d)\n\tdefault:\n\t\tnew(cmdAdmin).Main(d)\n\t}\n}\n"
  },
  {
    "path": "cmd/admin/proxy.go",
    "content": "// Copyright 2016 CodisLabs. All Rights Reserved.\n// Licensed under the MIT (MIT-LICENSE.txt) license.\n\npackage main\n\nimport (\n\t\"encoding/json\"\n\t\"fmt\"\n\t\"io/ioutil\"\n\n\t\"github.com/CodisLabs/codis/pkg/models\"\n\t\"github.com/CodisLabs/codis/pkg/proxy\"\n\t\"github.com/CodisLabs/codis/pkg/utils\"\n\t\"github.com/CodisLabs/codis/pkg/utils/log\"\n)\n\ntype cmdProxy struct {\n\taddr string\n\tauth string\n}\n\nfunc (t *cmdProxy) Main(d map[string]interface{}) {\n\tt.addr = utils.ArgumentMust(d, \"--proxy\")\n\tt.auth, _ = d[\"--auth\"].(string)\n\n\tswitch {\n\tdefault:\n\t\tt.handleOverview(d)\n\tcase d[\"--start\"].(bool):\n\t\tt.handleStart(d)\n\tcase d[\"--shutdown\"].(bool):\n\t\tt.handleShutdown(d)\n\tcase d[\"--log-level\"] != nil:\n\t\tt.handleLogLevel(d)\n\tcase d[\"--fillslots\"] != nil:\n\t\tt.handleFillSlots(d)\n\tcase d[\"--reset-stats\"].(bool):\n\t\tt.handleResetStats(d)\n\tcase d[\"--forcegc\"].(bool):\n\t\tt.handleForceGC(d)\n\t}\n}\n\nfunc (t *cmdProxy) newProxyClient(xauth bool) *proxy.ApiClient {\n\tc := proxy.NewApiClient(t.addr)\n\n\tif !xauth {\n\t\treturn c\n\t}\n\n\tlog.Debugf(\"call rpc model to proxy %s\", t.addr)\n\tp, err := c.Model()\n\tif err != nil {\n\t\tlog.PanicErrorf(err, \"call rpc model to proxy %s failed\", t.addr)\n\t}\n\tlog.Debugf(\"call rpc model OK\")\n\n\tc.SetXAuth(p.ProductName, t.auth, p.Token)\n\n\tlog.Debugf(\"call rpc xping to proxy %s\", t.addr)\n\tif err := c.XPing(); err != nil {\n\t\tlog.PanicErrorf(err, \"call rpc xping failed\")\n\t}\n\tlog.Debugf(\"call rpc xping OK\")\n\n\treturn c\n}\n\nfunc (t *cmdProxy) handleOverview(d map[string]interface{}) {\n\tc := t.newProxyClient(false)\n\n\tlog.Debugf(\"call rpc overview to proxy %s\", t.addr)\n\to, err := c.Overview()\n\tif err != nil {\n\t\tlog.PanicErrorf(err, \"call rpc overview to proxy %s failed\", t.addr)\n\t}\n\tlog.Debugf(\"call rpc overview OK\")\n\n\tvar cmd string\n\tfor _, s := range []string{\"config\", \"model\", \"slots\", \"stats\"} {\n\t\tif d[s].(bool) {\n\t\t\tcmd = s\n\t\t}\n\t}\n\n\tvar obj interface{}\n\tswitch cmd {\n\tdefault:\n\t\tobj = o\n\tcase \"config\":\n\t\tobj = o.Config\n\tcase \"model\":\n\t\tobj = o.Model\n\tcase \"slots\":\n\t\tobj = o.Slots\n\tcase \"stats\":\n\t\tobj = o.Stats\n\t}\n\n\tb, err := json.MarshalIndent(obj, \"\", \"    \")\n\tif err != nil {\n\t\tlog.PanicErrorf(err, \"json marshal failed\")\n\t}\n\tfmt.Println(string(b))\n}\n\nfunc (t *cmdProxy) handleStart(d map[string]interface{}) {\n\tc := t.newProxyClient(true)\n\n\tlog.Debugf(\"call rpc start to proxy %s\", t.addr)\n\tif err := c.Start(); err != nil {\n\t\tlog.PanicErrorf(err, \"call rpc start to proxy %s failed\", t.addr)\n\t}\n\tlog.Debugf(\"call rpc start to proxy OK\")\n}\n\nfunc (t *cmdProxy) handleLogLevel(d map[string]interface{}) {\n\tc := t.newProxyClient(true)\n\n\ts := utils.ArgumentMust(d, \"--log-level\")\n\n\tvar v log.LogLevel\n\tif !v.ParseFromString(s) {\n\t\tlog.Panicf(\"option --log-level = %s\", s)\n\t}\n\n\tlog.Debugf(\"call rpc loglevel to proxy %s\", t.addr)\n\tif err := c.LogLevel(v); err != nil {\n\t\tlog.PanicErrorf(err, \"call rpc loglevel to proxy %s failed\", t.addr)\n\t}\n\tlog.Debugf(\"call rpc loglevel OK\")\n}\n\nfunc (t *cmdProxy) handleFillSlots(d map[string]interface{}) {\n\tc := t.newProxyClient(true)\n\n\tb, err := ioutil.ReadFile(utils.ArgumentMust(d, \"--fillslots\"))\n\tif err != nil {\n\t\tlog.PanicErrorf(err, \"load slots from file failed\")\n\t}\n\n\tvar slots []*models.Slot\n\tif err := json.Unmarshal(b, &slots); err != nil {\n\t\tlog.PanicErrorf(err, \"decode slots from json failed\")\n\t}\n\n\tfor _, m := range slots {\n\t\tif m.Id < 0 || m.Id >= models.MaxSlotNum {\n\t\t\tlog.Panicf(\"invalid slot id = %d\", m.Id)\n\t\t}\n\t}\n\n\tif d[\"--locked\"].(bool) {\n\t\tfor _, m := range slots {\n\t\t\tm.Locked = true\n\t\t}\n\t}\n\n\tlog.Debugf(\"call rpc fillslots to proxy %s\", t.addr)\n\tif err := c.FillSlots(slots...); err != nil {\n\t\tlog.PanicErrorf(err, \"call rpc fillslots to proxy %s failed\", t.addr)\n\t}\n\tlog.Debugf(\"call rpc fillslots OK\")\n}\n\nfunc (t *cmdProxy) handleResetStats(d map[string]interface{}) {\n\tc := t.newProxyClient(true)\n\n\tlog.Debugf(\"call rpc resetstats to proxy %s\", t.addr)\n\tif err := c.ResetStats(); err != nil {\n\t\tlog.PanicErrorf(err, \"call rpc resetstats to proxy %s failed\", t.addr)\n\t}\n\tlog.Debugf(\"call rpc resetstats OK\")\n}\n\nfunc (t *cmdProxy) handleForceGC(d map[string]interface{}) {\n\tc := t.newProxyClient(true)\n\n\tlog.Debugf(\"call rpc forcegc to proxy %s\", t.addr)\n\tif err := c.ForceGC(); err != nil {\n\t\tlog.PanicErrorf(err, \"call rpc forcegc to proxy %s failed\", t.addr)\n\t}\n\tlog.Debugf(\"call rpc forcegc OK\")\n}\n\nfunc (t *cmdProxy) handleShutdown(d map[string]interface{}) {\n\tc := t.newProxyClient(true)\n\n\tlog.Debugf(\"call rpc shutdown to proxy %s\", t.addr)\n\tif err := c.Shutdown(); err != nil {\n\t\tlog.PanicErrorf(err, \"call rpc shutdown to proxy %s failed\", t.addr)\n\t}\n\tlog.Debugf(\"call rpc shutdown OK\")\n}\n"
  },
  {
    "path": "cmd/dashboard/main.go",
    "content": "// Copyright 2016 CodisLabs. All Rights Reserved.\n// Licensed under the MIT (MIT-LICENSE.txt) license.\n\npackage main\n\nimport (\n\t\"fmt\"\n\t\"io/ioutil\"\n\t\"os\"\n\t\"os/signal\"\n\t\"path/filepath\"\n\t\"runtime\"\n\t\"strconv\"\n\t\"syscall\"\n\t\"time\"\n\n\t\"github.com/docopt/docopt-go\"\n\n\t\"github.com/CodisLabs/codis/pkg/models\"\n\t\"github.com/CodisLabs/codis/pkg/topom\"\n\t\"github.com/CodisLabs/codis/pkg/utils\"\n\t\"github.com/CodisLabs/codis/pkg/utils/log\"\n)\n\nfunc main() {\n\tconst usage = `\nUsage:\n\tcodis-dashboard [--ncpu=N] [--config=CONF] [--log=FILE] [--log-level=LEVEL] [--host-admin=ADDR] [--pidfile=FILE] [--zookeeper=ADDR|--etcd=ADDR|--filesystem=ROOT] [--product_name=NAME] [--product_auth=AUTH] [--remove-lock]\n\tcodis-dashboard  --default-config\n\tcodis-dashboard  --version\n\nOptions:\n\t--ncpu=N                    set runtime.GOMAXPROCS to N, default is runtime.NumCPU().\n\t-c CONF, --config=CONF      run with the specific configuration.\n\t-l FILE, --log=FILE         set path/name of daliy rotated log file.\n\t--log-level=LEVEL           set the log-level, should be INFO,WARN,DEBUG or ERROR, default is INFO.\n`\n\n\td, err := docopt.Parse(usage, nil, true, \"\", false)\n\tif err != nil {\n\t\tlog.PanicError(err, \"parse arguments failed\")\n\t}\n\n\tswitch {\n\n\tcase d[\"--default-config\"]:\n\t\tfmt.Println(topom.DefaultConfig)\n\t\treturn\n\n\tcase d[\"--version\"].(bool):\n\t\tfmt.Println(\"version:\", utils.Version)\n\t\tfmt.Println(\"compile:\", utils.Compile)\n\t\treturn\n\n\t}\n\n\tif s, ok := utils.Argument(d, \"--log\"); ok {\n\t\tw, err := log.NewRollingFile(s, log.DailyRolling)\n\t\tif err != nil {\n\t\t\tlog.PanicErrorf(err, \"open log file %s failed\", s)\n\t\t} else {\n\t\t\tlog.StdLog = log.New(w, \"\")\n\t\t}\n\t}\n\tlog.SetLevel(log.LevelInfo)\n\n\tif s, ok := utils.Argument(d, \"--log-level\"); ok {\n\t\tif !log.SetLevelString(s) {\n\t\t\tlog.Panicf(\"option --log-level = %s\", s)\n\t\t}\n\t}\n\n\tif n, ok := utils.ArgumentInteger(d, \"--ncpu\"); ok {\n\t\truntime.GOMAXPROCS(n)\n\t} else {\n\t\truntime.GOMAXPROCS(runtime.NumCPU())\n\t}\n\tlog.Warnf(\"set ncpu = %d\", runtime.GOMAXPROCS(0))\n\n\tconfig := topom.NewDefaultConfig()\n\tif s, ok := utils.Argument(d, \"--config\"); ok {\n\t\tif err := config.LoadFromFile(s); err != nil {\n\t\t\tlog.PanicErrorf(err, \"load config %s failed\", s)\n\t\t}\n\t}\n\tif s, ok := utils.Argument(d, \"--host-admin\"); ok {\n\t\tconfig.HostAdmin = s\n\t\tlog.Warnf(\"option --host-admin = %s\", s)\n\t}\n\n\tswitch {\n\tcase d[\"--zookeeper\"] != nil:\n\t\tconfig.CoordinatorName = \"zookeeper\"\n\t\tconfig.CoordinatorAddr = utils.ArgumentMust(d, \"--zookeeper\")\n\t\tlog.Warnf(\"option --zookeeper = %s\", config.CoordinatorAddr)\n\n\tcase d[\"--etcd\"] != nil:\n\t\tconfig.CoordinatorName = \"etcd\"\n\t\tconfig.CoordinatorAddr = utils.ArgumentMust(d, \"--etcd\")\n\t\tlog.Warnf(\"option --etcd = %s\", config.CoordinatorAddr)\n\n\tcase d[\"--filesystem\"] != nil:\n\t\tconfig.CoordinatorName = \"filesystem\"\n\t\tconfig.CoordinatorAddr = utils.ArgumentMust(d, \"--filesystem\")\n\t\tlog.Warnf(\"option --filesystem = %s\", config.CoordinatorAddr)\n\n\t}\n\n\tif s, ok := utils.Argument(d, \"--product_name\"); ok {\n\t\tconfig.ProductName = s\n\t\tlog.Warnf(\"option --product_name = %s\", s)\n\t}\n\tif s, ok := utils.Argument(d, \"--product_auth\"); ok {\n\t\tconfig.ProductAuth = s\n\t\tlog.Warnf(\"option --product_auth = %s\", s)\n\t}\n\n\tclient, err := models.NewClient(config.CoordinatorName, config.CoordinatorAddr, config.CoordinatorAuth, time.Minute)\n\tif err != nil {\n\t\tlog.PanicErrorf(err, \"create '%s' client to '%s' failed\", config.CoordinatorName, config.CoordinatorAddr)\n\t}\n\tdefer client.Close()\n\n\tif d[\"--remove-lock\"].(bool) {\n\t\tstore := models.NewStore(client, config.ProductName)\n\t\tdefer store.Close()\n\n\t\tlog.Warnf(\"force remove-lock\")\n\t\tif err := store.Release(); err != nil {\n\t\t\tlog.WarnErrorf(err, \"force remove-lock failed\")\n\t\t} else {\n\t\t\tlog.Warnf(\"force remove-lock OK\")\n\t\t}\n\t}\n\n\ts, err := topom.New(client, config)\n\tif err != nil {\n\t\tlog.PanicErrorf(err, \"create topom with config file failed\\n%s\", config)\n\t}\n\tdefer s.Close()\n\n\tlog.Warnf(\"create topom with config\\n%s\", config)\n\n\tif s, ok := utils.Argument(d, \"--pidfile\"); ok {\n\t\tif pidfile, err := filepath.Abs(s); err != nil {\n\t\t\tlog.WarnErrorf(err, \"parse pidfile = '%s' failed\", s)\n\t\t} else if err := ioutil.WriteFile(pidfile, []byte(strconv.Itoa(os.Getpid())), 0644); err != nil {\n\t\t\tlog.WarnErrorf(err, \"write pidfile = '%s' failed\", pidfile)\n\t\t} else {\n\t\t\tdefer func() {\n\t\t\t\tif err := os.Remove(pidfile); err != nil {\n\t\t\t\t\tlog.WarnErrorf(err, \"remove pidfile = '%s' failed\", pidfile)\n\t\t\t\t}\n\t\t\t}()\n\t\t\tlog.Warnf(\"option --pidfile = %s\", pidfile)\n\t\t}\n\t}\n\n\tgo func() {\n\t\tdefer s.Close()\n\t\tc := make(chan os.Signal, 1)\n\t\tsignal.Notify(c, syscall.SIGINT, syscall.SIGKILL, syscall.SIGTERM)\n\n\t\tsig := <-c\n\t\tlog.Warnf(\"[%p] dashboard receive signal = '%v'\", s, sig)\n\t}()\n\n\tfor i := 0; !s.IsClosed() && !s.IsOnline(); i++ {\n\t\tif err := s.Start(true); err != nil {\n\t\t\tif i <= 15 {\n\t\t\t\tlog.Warnf(\"[%p] dashboard online failed [%d]\", s, i)\n\t\t\t} else {\n\t\t\t\tlog.Panicf(\"dashboard online failed, give up & abort :'(\")\n\t\t\t}\n\t\t\ttime.Sleep(time.Second * 2)\n\t\t}\n\t}\n\n\tlog.Warnf(\"[%p] dashboard is working ...\", s)\n\n\tfor !s.IsClosed() {\n\t\ttime.Sleep(time.Second)\n\t}\n\n\tlog.Warnf(\"[%p] dashboard is exiting ...\", s)\n}\n"
  },
  {
    "path": "cmd/fe/assets/css/main.css",
    "content": "body {\n    min-height: 20000px;\n    min-width: 1000px;\n}\n\n[ng\\:cloak], [ng-cloak], [data-ng-cloak], [x-ng-cloak], .ng-cloak, .x-ng-cloak {\n    display: none !important;\n}\n\n#main {\n    margin-left: 100px;\n    margin-top: 0px;\n    position: relative;\n    height: 100%;\n}\n\n.container-full {\n    margin: 20px 60px 20px 60px;\n}\n\n#main > .container-full > .row {\n    margin-bottom: 40px;\n}\n\n.status_label_error {\n    background-color: red;\n    color: white;\n    font-weight: bold;\n    padding: 3px\n}\n\n.status_label_warning {\n    background-color: yellow;\n    font-weight: bold;\n    padding: 3px\n}\n\n.status_label_pending {\n    background-color: palevioletred;\n    font-weight: bold;\n    padding: 3px\n}\n\n.button_tight_column {\n    padding: 1px;\n    vertical-align: middle;\n}\n\n#sidebar {\n    position: fixed;\n    left: 0;\n    bottom: 0;\n    top: 0px;\n    width: 120px;\n    z-index: 8;\n    background-color: #fff;\n    -webkit-box-shadow: 0 0 10px 0 rgba(0, 0, 0, .2);\n    -moz-box-shadow: 0 0 10px 0 rgba(0, 0, 0, .2)\n}\n\n.sidebar-cover {\n    position: absolute;\n    left: 0;\n    right: 0;\n    top: 0;\n    bottom: 46px;\n    background: rgba(255, 255, 255, .5);\n    z-index: 11\n}\n\n.sidebar-cover:hover {\n    background: rgba(220, 220, 220, .5)\n}\n\n.sidebar-cover:hover::before {\n    width: 100%;\n    text-align: center;\n    content: \"Disabled\";\n    color: #888;\n    position: absolute;\n    top: 45%\n}\n\n#sidebar .title {\n    position: absolute;\n    left: 0;\n    right: 0;\n    top: 0;\n    font-size: 13px;\n    font-weight: 700;\n    border-bottom: 1px solid #ccc;\n    padding: 8px;\n    background: #DFF2FF\n}\n\n#sidebar .items {\n    margin: 0;\n    list-style: none;\n    position: absolute;\n    left: 0;\n    right: 0;\n    bottom: 0;\n    top: 36px;\n    overflow-y: auto\n}\n\n#sidebar > .selected-node,\n#sidebar > .selected-node > .info {\n    display: none\n}\n\n#sidebar > .tabs {\n    position: absolute;\n    left: 0;\n    right: 0;\n    bottom: 0;\n    height: 35px;\n    border-top: 1px solid #ddd;\n    margin: 0;\n    padding: 0;\n    background: #f9f9f9\n}\n\n#sidebar > .tabs > li {\n    display: inline-block\n}\n\n#sidebar > .tabs > li > a {\n    display: inline-block;\n    padding: 10px;\n    width: 60px;\n    font-size: 13px;\n    text-align: center;\n    border-right: 1px solid #ddd;\n    position: relative;\n    top: -1px\n}\n\n#sidebar > .tabs > li.active > a {\n    background: #fff\n}\n\n#sidebar > .content {\n    position: absolute;\n    left: 0;\n    right: 0;\n    top: 0;\n    bottom: 46px;\n    overflow-y: auto\n}\n\n#sidebar > .actions {\n    position: absolute;\n    left: 0;\n    right: 0;\n    bottom: 0;\n    height: 30px;\n    padding: 8px;\n    background: #f0f0f0\n}\n\n#sidebar > .actions > button {\n    width: 34px;\n    height: 30px;\n    padding: 0\n}\n\n#sidebar > .actions > .search {\n    display: inline-block;\n    border: 0;\n    background: #fff;\n    border-radius: 3px;\n    padding: 5px 6px;\n    height: 22px;\n    outline: 0;\n    width: 157px;\n    margin-right: 6px;\n    box-shadow: inset 0 0 2px 0 rgba(80, 80, 80, .5);\n    color: #333;\n    position: relative;\n    top: -1px\n}\n\n#sidebar > .actions > .fn-clear-search {\n    position: absolute;\n    top: 15px;\n    right: 65px;\n    font-weight: 100;\n    color: #888;\n    cursor: pointer\n}\n\n#sidebar > .actions > .fn-collapse {\n    float: right;\n    background-image: linear-gradient(transparent, rgba(0, 0, 0, .08) 40%, rgba(0, 0, 0, .1))\n}\n\n#sidebar > .actions > .fn-collapse:hover {\n    background-image: linear-gradient(rgba(0, 0, 0, .01), rgba(0, 0, 0, .14) 40%, rgba(0, 0, 0, .16))\n}\n\nbody.sidebar-collapsed #sidebar {\n    width: 50px;\n    background: #fff\n}\n\nbody.sidebar-collapsed #main {\n    margin-left: 50px\n}\n\nbody.sidebar-collapsed #sidebar .actions .search,\nbody.sidebar-collapsed #sidebar .content {\n    display: none\n}\n\nbody.sidebar-collapsed #sidebar > .selected-node {\n    display: block;\n    position: relative\n}\n\nbody.sidebar-collapsed #sidebar > .selected-node > .cube {\n    width: 50px;\n    background: #eee;\n    height: 45px;\n    line-height: 45px;\n    text-align: center;\n    font-size: 15px;\n    color: #2494F2;\n    cursor: pointer\n}\n\nbody.sidebar-collapsed #sidebar > .selected-node:hover > .info {\n    display: block;\n    position: absolute;\n    left: 50px;\n    top: 0;\n    padding-left: 10px;\n    width: 169px;\n    height: 45px;\n    line-height: 45px;\n    background: #fff;\n    border-right: 1px solid #2494F2;\n    border-bottom: 1px solid #2494F2;\n    font-size: 13px\n}\n\nbody.sidebar-collapsed #sidebar > .selected-node:hover > .cube {\n    border-bottom: 1px solid #2494F2\n}\n\n.ui-itemlist {\n    margin: 0;\n    padding: 0;\n    list-style: none\n}\n\n.ui-itemlist > li {\n    border-bottom: 1px solid #eee;\n    position: relative;\n    transition: all .2s ease\n}\n\n.ui-itemlist > li > i {\n    opacity: 0;\n    position: absolute;\n    left: 12px;\n    top: 9px;\n    transition: all .2s ease;\n    font-size: 13px;\n    z-index: 1\n}\n\n.ui-itemlist > li > a {\n    display: block;\n    position: relative;\n    padding: 8px 12px;\n    transition: all .2s ease;\n    font-size: 13px;\n    color: #2083D6\n}\n\n.ui-itemlist > li:hover {\n    background: #fafafa\n}\n\n.ui-itemlist > li.selected {\n    background: #eee\n}\n\n.ui-itemlist > li.selected:hover {\n    background: #f4f4f4\n}\n\n.ui-itemlist > li.selected > a,\n.ui-itemlist > li:hover > a {\n    margin-left: 12px\n}\n\n.ui-itemlist > li.selected > i,\n.ui-itemlist > li:hover > i {\n    opacity: 1\n}\n"
  },
  {
    "path": "cmd/fe/assets/dashboard-fe.js",
    "content": "'use strict';\n\nvar dashboard = angular.module('dashboard-fe', [\"highcharts-ng\", \"ui.bootstrap\"]);\n\nfunction genXAuth(name) {\n    return sha256(\"Codis-XAuth-[\" + name + \"]\").substring(0, 32);\n}\n\nfunction concatUrl(base, name) {\n    if (name) {\n        return encodeURI(base + \"?forward=\" + name);\n    } else {\n        return encodeURI(base);\n    }\n}\n\nfunction padInt2Str(num, size) {\n    var s = num + \"\";\n    while (s.length < size) s = \"0\" + s;\n    return s;\n}\n\nfunction toJsonHtml(obj) {\n    var json = angular.toJson(obj, 4);\n    json = json.replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;');\n    json = json.replace(/ /g, '&nbsp;');\n    json = json.replace(/(\"(\\\\u[a-zA-Z0-9]{4}|\\\\[^u]|[^\\\\\"])*\"(\\s*:)?|\\b(true|false|null)\\b|-?\\d+(?:\\.\\d*)?(?:[eE][+\\-]?\\d+)?)/g, function (match) {\n        var cls = 'number';\n        if (/^\"/.test(match)) {\n            if (/:$/.test(match)) {\n                cls = 'key';\n            } else {\n                cls = 'string';\n            }\n        } else if (/true|false/.test(match)) {\n            cls = 'boolean';\n        } else if (/null/.test(match)) {\n            cls = 'null';\n        }\n        return '<span class=\"' + cls + '\">' + match + '</span>';\n    });\n    return json;\n}\n\nfunction humanSize(size) {\n    if (size < 1024) {\n        return size + \" B\";\n    }\n    size /= 1024;\n    if (size < 1024) {\n        return size.toFixed(2) + \" KB\";\n    }\n    size /= 1024;\n    if (size < 1024) {\n        return size.toFixed(2) + \" MB\";\n    }\n    size /= 1024;\n    if (size < 1024) {\n        return size.toFixed(2) + \" GB\";\n    }\n    size /= 1024;\n    return size.toFixed(2) + \" TB\";\n}\n\nfunction newChatsOpsConfig() {\n    return {\n        options: {\n            chart: {\n                useUTC: false,\n                type: 'spline',\n            },\n        },\n        series: [{\n            color: '#d82b28',\n            lineWidth: 1.5,\n            states: {\n                hover: {\n                    enabled: false,\n                }\n            },\n            showInLegend: false,\n            marker: {\n                enabled: true,\n                symbol: 'circle',\n                radius: 2,\n            },\n            name: 'OP/s',\n            data: [],\n        }],\n        title: {\n            style: {\n                display: 'none',\n            }\n        },\n        xAxis: {\n            type: 'datetime',\n            title: {\n                style: {\n                    display: 'none',\n                }\n            },\n            labels: {\n                formatter: function () {\n                    var d = new Date(this.value);\n                    return padInt2Str(d.getHours(), 2) + \":\" + padInt2Str(d.getMinutes(), 2) + \":\" + padInt2Str(d.getSeconds(), 2);\n                }\n            },\n        },\n        yAxis: {\n            min: 0,\n            title: {\n                style: {\n                    display: 'none',\n                }\n            },\n        },\n    };\n}\n\nfunction renderSlotsCharts(slots_array) {\n    var groups = {};\n    var counts = {};\n    var n = slots_array.length;\n    for (var i = 0; i < n; i++) {\n        var slot = slots_array[i];\n        groups[slot.group_id] = true;\n        if (slot.action.target_id) {\n            groups[slot.action.target_id] = true;\n        }\n        if (counts[slot.group_id]) {\n            counts[slot.group_id]++;\n        } else {\n            counts[slot.group_id] = 1;\n        }\n    }\n    var series = [];\n    for (var g in groups) {\n        var xaxis = 2;\n        if (g == 0) {\n            xaxis = 0;\n        }\n        var s = {name: 'Group-' + g + ':' + (counts[g] == undefined ? 0 : counts[g]), data: [], group_id: g};\n        for (var beg = 0, end = 0; end <= n; end++) {\n            if (end == n || slots_array[end].group_id != g) {\n                if (beg < end) {\n                    s.data.push({x: xaxis, beg: beg, end: end - 1, low: beg, high: end, group_id: g});\n                }\n                beg = end + 1;\n            }\n        }\n        xaxis = 1;\n        for (var beg = 0, end = 0; end <= n; end++) {\n            if (end == n || !(slots_array[end].action.target_id && slots_array[end].action.target_id == g)) {\n                if (beg < end) {\n                    s.data.push({x: xaxis, beg: beg, end: end - 1, low: beg, high: end, group_id: g});\n                }\n                beg = end + 1;\n            }\n        }\n        s.data.sort(function (a, b) {\n            return a.x - b.x;\n        });\n        series.push(s);\n    }\n    series.sort(function (a, b) {\n        return a.group_id - b.group_id;\n    });\n    new Highcharts.Chart({\n        chart: {\n            renderTo: 'slots_charts',\n            type: 'columnrange',\n            inverted: true,\n        },\n        title: {\n            style: {\n                display: 'none',\n            }\n        },\n        xAxis: {\n            categories: ['Offline', 'Migrating', 'Default'],\n            min: 0,\n            max: 2,\n        },\n        yAxis: {\n            min: 0,\n            max: 1024,\n            tickInterval: 64,\n            title: {\n                style: {\n                    display: 'none',\n                }\n            },\n        },\n        legend: {\n            enabled: true,\n            itemWidth: 140,\n        },\n        plotOptions: {\n            columnrange: {\n                grouping: false\n            },\n            series: {\n                animation: false,\n                events: {\n                    legendItemClick: function () {\n                        return false;\n                    },\n                }\n            },\n        },\n        credits: {\n            enabled: false\n        },\n        tooltip: {\n            formatter: function () {\n                switch (this.point.x) {\n                case 0:\n                    return '<b>Slot-[' + this.point.beg + \",\" + this.point.end + \"]</b> are <b>Offline</b>\";\n                case 1:\n                    return '<b>Slot-[' + this.point.beg + \",\" + this.point.end + \"]</b> will be moved to <b>Group-[\" + this.point.group_id + \"]</b>\";\n                case 2:\n                    return '<b>Slot-[' + this.point.beg + \",\" + this.point.end + \"]</b> --> <b>Group-[\" + this.point.group_id + \"]</b>\";\n                }\n            }\n        },\n        series: series,\n    });\n}\n\nfunction processProxyStats(codis_stats) {\n    var proxy_array = codis_stats.proxy.models;\n    var proxy_stats = codis_stats.proxy.stats;\n    var qps = 0, sessions = 0;\n    for (var i = 0; i < proxy_array.length; i++) {\n        var p = proxy_array[i];\n        var s = proxy_stats[p.token];\n        p.sessions = \"NA\";\n        p.commands = \"NA\";\n        p.switched = false;\n        p.primary_only = false;\n        if (!s) {\n            p.status = \"PENDING\";\n        } else if (s.timeout) {\n            p.status = \"TIMEOUT\";\n        } else if (s.error) {\n            p.status = \"ERROR\";\n        } else {\n            if (s.stats.online) {\n                p.sessions = \"total=\" + s.stats.sessions.total + \",alive=\" + s.stats.sessions.alive;\n                p.commands = \"total=\" + s.stats.ops.total + \",fails=\" + s.stats.ops.fails;\n                if (s.stats.ops.redis != undefined) {\n                    p.commands += \",rsp.errs=\" + s.stats.ops.redis.errors;\n                }\n                p.commands += \",qps=\" + s.stats.ops.qps;\n                p.status = \"HEALTHY\";\n            } else {\n                p.status = \"PENDING\";\n            }\n            if (p.admin_addr) {\n                p.proxy_link = p.admin_addr + \"/proxy\"\n                p.stats_link = p.admin_addr + \"/proxy/stats\"\n            }\n            if (s.stats.sentinels != undefined) {\n                if (s.stats.sentinels.switched != undefined) {\n                    p.switched = s.stats.sentinels.switched;\n                }\n            }\n            if (s.stats.backend != undefined) {\n                if (s.stats.backend.primary_only != undefined) {\n                    p.primary_only = s.stats.backend.primary_only;\n                }\n            }\n            qps += s.stats.ops.qps;\n            sessions += s.stats.sessions.alive;\n        }\n    }\n    return {proxy_array: proxy_array, qps: qps, sessions: sessions};\n}\n\nfunction processSentinels(codis_stats, group_stats, codis_name) {\n    var ha = codis_stats.sentinels;\n    var out_of_sync = false;\n    var servers = [];\n    if (ha.model != undefined) {\n        if (ha.model.servers == undefined) {\n            ha.model.servers = []\n        }\n        for (var i = 0; i < ha.model.servers.length; i ++) {\n            var x = {server: ha.model.servers[i]};\n            var s = ha.stats[x.server];\n            x.runid_error = \"\";\n            if (!s) {\n                x.status = \"PENDING\";\n            } else if (s.timeout) {\n                x.status = \"TIMEOUT\";\n            } else if (s.error) {\n                x.status = \"ERROR\";\n            } else {\n                x.masters = 0;\n                x.masters_down = 0;\n                x.slaves = 0;\n                x.sentinels = 0;\n                var masters = s.stats[\"sentinel_masters\"];\n                if (masters != undefined) {\n                    for (var j = 0; j < masters; j ++) {\n                        var record = s.stats[\"master\" + j];\n                        if (record != undefined) {\n                            var pairs = record.split(\",\");\n                            var dict = {};\n                            for (var t = 0; t < pairs.length; t ++) {\n                                var ss = pairs[t].split(\"=\");\n                                if (ss.length == 2) {\n                                    dict[ss[0]] = ss[1];\n                                }\n                            }\n                            var name = dict[\"name\"];\n                            if (name == undefined) {\n                                continue;\n                            }\n                            if (name.lastIndexOf(codis_name) != 0) {\n                                continue;\n                            }\n                            if (name.lastIndexOf(\"-\") != codis_name.length) {\n                                continue;\n                            }\n                            x.masters ++;\n                            if (dict[\"status\"] != \"ok\") {\n                                x.masters_down ++;\n                            }\n                            x.slaves += parseInt(dict[\"slaves\"]);\n                            x.sentinels += parseInt(dict[\"sentinels\"]);\n                        }\n                    }\n                }\n                x.status_text = \"masters=\" + x.masters;\n                x.status_text += \",down=\" + x.masters_down;\n                var avg = 0;\n                if (x.slaves == 0) {\n                    avg = 0;\n                } else {\n                    avg = Number(x.slaves) / x.masters;\n                }\n                x.status_text += \",slaves=\" + avg.toFixed(2);\n                if (x.sentinels == 0) {\n                    avg = 0;\n                } else {\n                    avg = Number(x.sentinels) / x.masters;\n                }\n                x.status_text += \",sentinels=\" + avg.toFixed(2);\n\n                if (s.sentinel != undefined) {\n                    var group_array = group_stats.group_array;\n                    for (var t in group_array) {\n                        var g = group_array[t];\n                        var d = s.sentinel[codis_name + \"-\" + g.id];\n                        var runids = {};\n                        if (d != undefined) {\n                            if (d.master != undefined) {\n                                var o = d.master;\n                                runids[o[\"runid\"]] = o[\"ip\"] + \":\" + o[\"port\"];\n                            }\n                            if (d.slaves != undefined) {\n                                for (var j = 0; j < d.slaves.length; j ++) {\n                                    var o = d.slaves[j];\n                                    runids[o[\"runid\"]] = o[\"ip\"] + \":\" + o[\"port\"];\n                                }\n                            }\n                        }\n                        for (var runid in runids) {\n                            if (g.runids[runid] === undefined) {\n                                x.runid_error = \"[+]group=\" + g.id + \",server=\" + runids[runid] + \",runid=\"\n                                    + ((runid != \"\") ? runid : \"NA\");\n                            }\n                        }\n                        for (var runid in g.runids) {\n                            if (runids[runid] === undefined) {\n                                x.runid_error = \"[-]group=\" + g.id + \",server=\" + g.runids[runid] + \",runid=\" + runid;\n                            }\n                        }\n                    }\n                }\n            }\n            servers.push(x);\n        }\n        out_of_sync = ha.model.out_of_sync;\n    }\n    var masters = ha.masters;\n    if (masters == undefined) {\n        masters = {};\n    }\n    return {servers:servers, masters:masters, out_of_sync: out_of_sync}\n}\n\nfunction alertAction(text, callback) {\n    BootstrapDialog.show({\n        title: \"Warning !!\",\n        message: text,\n        closable: true,\n        buttons: [{\n            label: \"OK\",\n            cssClass: \"btn-primary\",\n            action: function (dialog) {\n                dialog.close();\n                callback();\n            },\n        }, {\n            label: \"CANCEL\",\n            action: function(dialogItself){\n                dialogItself.close();\n            }\n        }],\n    });\n}\n\nfunction alertAction2(text, callback) {\n    BootstrapDialog.show({\n        title: \"Warning !!\",\n        type: \"type-danger\",\n        message: text,\n        closable: true,\n        buttons: [{\n            label: \"JUST DO IT\",\n            cssClass: \"btn-danger\",\n            action: function (dialog) {\n                dialog.close();\n                callback();\n            },\n        }, {\n            label: \"CANCEL\",\n            action: function(dialogItself){\n                dialogItself.close();\n            }\n        }],\n    });\n}\n\nfunction alertErrorResp(failedResp) {\n    var text = \"error response\";\n    if (failedResp.status != 1500 && failedResp.status != 800) {\n        text = failedResp.data.toString();\n    } else {\n        text = toJsonHtml(failedResp.data);\n    }\n    BootstrapDialog.alert({\n        title: \"Error !!\",\n        type: \"type-danger\",\n        closable: true,\n        message: text,\n    });\n}\n\nfunction isValidInput(text) {\n    return text && text != \"\" && text != \"NA\";\n}\n\nfunction processGroupStats(codis_stats) {\n    var group_array = codis_stats.group.models;\n    var group_stats = codis_stats.group.stats;\n    var keys = 0, memory = 0;\n    var dbkeyRegexp = /db\\d+/\n    for (var i = 0; i < group_array.length; i++) {\n        var g = group_array[i];\n        if (g.promoting.state) {\n            g.ispromoting = g.promoting.state != \"\";\n            if (g.promoting.index) {\n                g.ispromoting_index = g.promoting.index;\n            } else {\n                g.ispromoting_index = 0;\n            }\n        } else {\n            g.ispromoting = false;\n            g.ispromoting_index = -1;\n        }\n        g.runids = {}\n        g.canremove = (g.servers.length == 0);\n        for (var j = 0; j < g.servers.length; j++) {\n            var x = g.servers[j];\n            var s = group_stats[x.server];\n            x.keys = [];\n            x.memory = \"NA\";\n            x.maxmem = \"NA\";\n            x.master = \"NA\";\n            if (j == 0) {\n                x.master_expect = \"NO:ONE\";\n            } else {\n                x.master_expect = g.servers[0].server;\n            }\n            if (!s) {\n                x.status = \"PENDING\";\n            } else if (s.timeout) {\n                x.status = \"TIMEOUT\";\n            } else if (s.error) {\n                x.status = \"ERROR\";\n            } else {\n                for (var field in s.stats) {\n                    if (dbkeyRegexp.test(field)) {\n                        var v = parseInt(s.stats[field].split(\",\")[0].split(\"=\")[1], 10);\n                        if (j == 0) {\n                            keys += v;\n                        }\n                        x.keys.push(field+ \":\" + s.stats[field]);\n                    }\n                }\n                if (s.stats[\"used_memory\"]) {\n                    var v = parseInt(s.stats[\"used_memory\"], 10);\n                    if (j == 0) {\n                        memory += v;\n                    }\n                    x.memory = humanSize(v);\n                }\n                if (s.stats[\"maxmemory\"]) {\n                    var v = parseInt(s.stats[\"maxmemory\"], 10);\n                    if (v == 0) {\n                        x.maxmem = \"INF.\"\n                    } else {\n                        x.maxmem = humanSize(v);\n                    }\n                }\n                if (s.stats[\"master_addr\"]) {\n                    x.master = s.stats[\"master_addr\"] + \":\" + s.stats[\"master_link_status\"];\n                } else {\n                    x.master = \"NO:ONE\";\n                }\n                if (j == 0) {\n                    x.master_status = (x.master == \"NO:ONE\");\n                } else {\n                    x.master_status = (x.master == g.servers[0].server + \":up\");\n                }\n                g.runids[s.stats[\"run_id\"]] = x.server;\n            }\n            if (g.ispromoting) {\n                x.canremove = false;\n                x.canpromote = false;\n                x.ispromoting = (j == g.ispromoting_index);\n            } else {\n                x.canremove = (j != 0 || g.servers.length <= 1);\n                x.canpromote = j != 0;\n                x.ispromoting = false;\n            }\n            if (x.action.state) {\n                if (x.action.state != \"pending\") {\n                    x.canslaveof = \"create\";\n                    x.actionstate = x.action.state;\n                } else {\n                    x.canslaveof = \"remove\";\n                    x.actionstate = x.action.state + \":\" + x.action.index;\n                }\n            } else {\n                x.canslaveof = \"create\";\n                x.actionstate = \"\";\n            }\n            x.server_text = x.server;\n        }\n    }\n    return {group_array: group_array, keys: keys, memory: memory};\n}\n\ndashboard.config(['$interpolateProvider',\n    function ($interpolateProvider) {\n        $interpolateProvider.startSymbol('[[');\n        $interpolateProvider.endSymbol(']]');\n    }\n]);\n\ndashboard.config(['$httpProvider', function ($httpProvider) {\n    $httpProvider.defaults.useXDomain = true;\n    delete $httpProvider.defaults.headers.common['X-Requested-With'];\n}]);\n\ndashboard.controller('MainCodisCtrl', ['$scope', '$http', '$uibModal', '$timeout',\n    function ($scope, $http, $uibModal, $timeout) {\n        Highcharts.setOptions({\n            global: {\n                useUTC: false,\n            },\n            exporting: {\n                enabled: false,\n            },\n        });\n        $scope.chart_ops = newChatsOpsConfig();\n\n        $scope.refresh_interval = 3;\n\n        $scope.resetOverview = function () {\n            $scope.codis_name = \"NA\";\n            $scope.codis_addr = \"NA\";\n            $scope.codis_coord_name = \"Coordinator\";\n            $scope.codis_coord_addr = \"NA\";\n            $scope.codis_qps = \"NA\";\n            $scope.codis_sessions = \"NA\";\n            $scope.redis_mem = \"NA\";\n            $scope.redis_keys = \"NA\";\n            $scope.slots_array = [];\n            $scope.proxy_array = [];\n            $scope.group_array = [];\n            $scope.slots_actions = [];\n            $scope.chart_ops.series[0].data = [];\n            $scope.slots_action_interval = \"NA\";\n            $scope.slots_action_disabled = \"NA\";\n            $scope.slots_action_failed = false;\n            $scope.slots_action_remain = 0;\n            $scope.sentinel_servers = [];\n            $scope.sentinel_out_of_sync = false;\n        }\n        $scope.resetOverview();\n\n        $http.get('/list').then(function (resp) {\n            $scope.codis_list = resp.data;\n        });\n\n        $scope.selectCodisInstance = function (selected) {\n            if ($scope.codis_name == selected) {\n                return;\n            }\n            $scope.resetOverview();\n            $scope.codis_name = selected;\n            var url = concatUrl(\"/topom\", selected);\n            $http.get(url).then(function (resp) {\n                if ($scope.codis_name != selected) {\n                    return;\n                }\n                var overview = resp.data;\n                $scope.codis_addr = overview.model.admin_addr;\n                $scope.codis_coord_name = \"[\" + overview.config.coordinator_name.charAt(0).toUpperCase() + overview.config.coordinator_name.slice(1) + \"]\";\n                $scope.codis_coord_addr = overview.config.coordinator_addr;\n                $scope.updateStats(overview.stats);\n            });\n        }\n\n        $scope.updateStats = function (codis_stats) {\n            var proxy_stats = processProxyStats(codis_stats);\n            var group_stats = processGroupStats(codis_stats);\n            var sentinel = processSentinels(codis_stats, group_stats, $scope.codis_name);\n\n            var merge = function(obj1, obj2) {\n                if (obj1 === null || obj2 === null) {\n                    return obj2;\n                }\n                if (Array.isArray(obj1)) {\n                    if (obj1.length != obj2.length) {\n                        return obj2;\n                    }\n                    for (var i = 0; i < obj1.length; i ++) {\n                        obj1[i] = merge(obj1[i], obj2[i]);\n                    }\n                    return obj1;\n                }\n                if (typeof obj1 === \"object\") {\n                    for (var k in obj1) {\n                        if (obj2[k] === undefined) {\n                            delete obj1[k];\n                        }\n                    }\n                    for (var k in obj2) {\n                        obj1[k] = merge(obj1[k], obj2[k]);\n                    }\n                    return obj1;\n                }\n                return obj2;\n            }\n\n            $scope.codis_qps = proxy_stats.qps;\n            $scope.codis_sessions = proxy_stats.sessions;\n            $scope.redis_mem = humanSize(group_stats.memory);\n            $scope.redis_keys = group_stats.keys.toString().replace(/\\B(?=(\\d{3})+(?!\\d))/g, \",\");\n            $scope.slots_array = merge($scope.slots_array, codis_stats.slots);\n            $scope.proxy_array = merge($scope.proxy_array, proxy_stats.proxy_array);\n            $scope.group_array = merge($scope.group_array, group_stats.group_array);\n            $scope.slots_actions = [];\n            $scope.slots_action_interval = codis_stats.slot_action.interval;\n            $scope.slots_action_disabled = codis_stats.slot_action.disabled;\n            $scope.slots_action_progress = codis_stats.slot_action.progress.status;\n            $scope.sentinel_servers = merge($scope.sentinel_servers, sentinel.servers);\n            $scope.sentinel_out_of_sync = sentinel.out_of_sync;\n\n            for (var i = 0; i < $scope.slots_array.length; i++) {\n                var slot = $scope.slots_array[i];\n                if (slot.action.state) {\n                    $scope.slots_actions.push(slot);\n                }\n            }\n\n            if ($scope.sentinel_servers.length != 0) {\n                for (var i = 0; i < $scope.group_array.length; i ++) {\n                    var g = $scope.group_array[i];\n                    var ha_master = sentinel.masters[g.id];\n                    var ha_master_ingroup = false;\n                    for (var j = 0; j < g.servers.length; j ++) {\n                        var x = g.servers[j];\n                        if (ha_master == undefined) {\n                            x.ha_status = \"ha_undefined\";\n                            continue;\n                        }\n                        if (j == 0) {\n                            if (x.server == ha_master) {\n                                x.ha_status = \"ha_master\";\n                            } else {\n                                x.ha_status = \"ha_not_master\";\n                            }\n                        } else {\n                            if (x.server == ha_master) {\n                                x.ha_status = \"ha_real_master\";\n                            } else {\n                                x.ha_status = \"ha_slave\";\n                            }\n                        }\n                        if (x.server == ha_master) {\n                            x.server_text = x.server + \" [HA]\";\n                            ha_master_ingroup = true;\n                        }\n                    }\n                    if (ha_master == undefined || ha_master_ingroup) {\n                        g.ha_warning = \"\";\n                    } else {\n                        g.ha_warning = \"[HA: \" + ha_master + \"]\";\n                    }\n                }\n            }\n\n            renderSlotsCharts($scope.slots_array);\n\n            var ops_array = $scope.chart_ops.series[0].data;\n            if (ops_array.length >= 10) {\n                ops_array.shift();\n            }\n            ops_array.push({x: new Date(), y: proxy_stats.qps});\n            $scope.chart_ops.series[0].data = ops_array;\n        }\n\n        $scope.refreshStats = function () {\n            var codis_name = $scope.codis_name;\n            var codis_addr = $scope.codis_addr;\n            if (isValidInput(codis_name) && isValidInput(codis_addr)) {\n                var xauth = genXAuth(codis_name);\n                var url = concatUrl(\"/api/topom/stats/\" + xauth, codis_name);\n                $http.get(url).then(function (resp) {\n                    if ($scope.codis_name != codis_name) {\n                        return;\n                    }\n                    $scope.updateStats(resp.data);\n                });\n            }\n        }\n\n        $scope.createProxy = function (proxy_addr) {\n            var codis_name = $scope.codis_name;\n            if (isValidInput(codis_name) && isValidInput(proxy_addr)) {\n                var xauth = genXAuth(codis_name);\n                var url = concatUrl(\"/api/topom/proxy/create/\" + xauth + \"/\" + proxy_addr, codis_name);\n                $http.put(url).then(function () {\n                    $scope.refreshStats();\n                }, function (failedResp) {\n                    alertErrorResp(failedResp);\n                });\n            }\n        }\n\n        $scope.removeProxy = function (proxy, force) {\n            var codis_name = $scope.codis_name;\n            if (isValidInput(codis_name)) {\n                var prefix = \"\";\n                if (force) {\n                    prefix = \"[FORCE] \";\n                }\n                alertAction(prefix + \"Remove and Shutdown proxy: \" + toJsonHtml(proxy), function () {\n                    var xauth = genXAuth(codis_name);\n                    var value = 0;\n                    if (force) {\n                        value = 1;\n                    }\n                    var url = concatUrl(\"/api/topom/proxy/remove/\" + xauth + \"/\" + proxy.token + \"/\" + value, codis_name);\n                    $http.put(url).then(function () {\n                        $scope.refreshStats();\n                    }, function (failedResp) {\n                        alertErrorResp(failedResp);\n                    });\n                });\n            }\n        }\n\n        $scope.reinitProxy = function (proxy) {\n            var codis_name = $scope.codis_name;\n            if (isValidInput(codis_name)) {\n                var confused = [];\n                for (var i = 0; i < $scope.group_array.length; i ++) {\n                    var group = $scope.group_array[i];\n                    var ha_real_master = -1;\n                    for (var j = 0; j < group.servers.length; j ++) {\n                        if (group.servers[j].ha_status == \"ha_real_master\") {\n                            ha_real_master = j;\n                        }\n                    }\n                    if (ha_real_master >= 0) {\n                        confused.push({group: group.id, logical_master: group.servers[0].server, ha_real_master: group.servers[ha_real_master].server});\n                    }\n                }\n                if (confused.length == 0) {\n                    alertAction(\"Reinit and Start proxy: \" + toJsonHtml(proxy), function () {\n                        var xauth = genXAuth(codis_name);\n                        var url = concatUrl(\"/api/topom/proxy/reinit/\" + xauth + \"/\" + proxy.token, codis_name);\n                        $http.put(url).then(function () {\n                            $scope.refreshStats();\n                        }, function (failedResp) {\n                            alertErrorResp(failedResp);\n                        });\n                    });\n                } else {\n                    var prompts = toJsonHtml(proxy);\n                    prompts += \"\\n\\n\";\n                    prompts += \"HA: real master & logical master area conflicting: \" + toJsonHtml(confused);\n                    prompts += \"\\n\\n\";\n                    prompts += \"Please fix these before resync proxy-[\" + proxy.token + \"].\";\n                    alertAction2(\"Reinit and Start proxy: \" + prompts, function () {\n                        var xauth = genXAuth(codis_name);\n                        var url = concatUrl(\"/api/topom/proxy/reinit/\" + xauth + \"/\" + proxy.token, codis_name);\n                        $http.put(url).then(function () {\n                            $scope.refreshStats();\n                        }, function (failedResp) {\n                            alertErrorResp(failedResp);\n                        });\n                    });\n                }\n            }\n        }\n\n        $scope.createGroup = function (group_id) {\n            var codis_name = $scope.codis_name;\n            if (isValidInput(codis_name) && isValidInput(group_id)) {\n                var xauth = genXAuth(codis_name);\n                var url = concatUrl(\"/api/topom/group/create/\" + xauth + \"/\" + group_id, codis_name);\n                $http.put(url).then(function () {\n                    $scope.refreshStats();\n                }, function (failedResp) {\n                    alertErrorResp(failedResp);\n                });\n            }\n        }\n\n        $scope.removeGroup = function (group_id) {\n            var codis_name = $scope.codis_name;\n            if (isValidInput(codis_name)) {\n                var xauth = genXAuth(codis_name);\n                var url = concatUrl(\"/api/topom/group/remove/\" + xauth + \"/\" + group_id, codis_name);\n                $http.put(url).then(function () {\n                    $scope.refreshStats();\n                }, function (failedResp) {\n                    alertErrorResp(failedResp);\n                });\n            }\n        }\n\n        $scope.resyncGroup = function (group) {\n            var codis_name = $scope.codis_name;\n            if (isValidInput(codis_name)) {\n                var o = {};\n                o.id = group.id;\n                o.servers = [];\n                var ha_real_master = -1;\n                for (var j = 0; j < group.servers.length; j++) {\n                    o.servers.push(group.servers[j].server);\n                    if (group.servers[j].ha_status == \"ha_real_master\") {\n                        ha_real_master = j;\n                    }\n                }\n                if (ha_real_master < 0) {\n                    alertAction(\"Resync Group-[\" + group.id + \"]: \" + toJsonHtml(o), function () {\n                        var xauth = genXAuth(codis_name);\n                        var url = concatUrl(\"/api/topom/group/resync/\" + xauth + \"/\" + group.id, codis_name);\n                        $http.put(url).then(function () {\n                            $scope.refreshStats();\n                        }, function (failedResp) {\n                            alertErrorResp(failedResp);\n                        });\n                    });\n                } else {\n                    var prompts = toJsonHtml(o);\n                    prompts += \"\\n\\n\";\n                    prompts += \"HA: server[\" + ha_real_master + \"]=\" + group.servers[ha_real_master].server + \" should be the real group master, do you really want to resync group-[\" + group.id + \"] ??\";\n                    alertAction2(\"Resync Group-[\" + group.id + \"]: \" + prompts, function () {\n                        var xauth = genXAuth(codis_name);\n                        var url = concatUrl(\"/api/topom/group/resync/\" + xauth + \"/\" + group.id, codis_name);\n                        $http.put(url).then(function () {\n                            $scope.refreshStats();\n                        }, function (failedResp) {\n                            alertErrorResp(failedResp);\n                        });\n                    });\n                }\n            }\n        }\n\n        $scope.resyncGroupAll = function() {\n            var codis_name = $scope.codis_name;\n            if (isValidInput(codis_name)) {\n                var ha_real_master = -1;\n                var gids = [];\n                for (var i = 0; i < $scope.group_array.length; i ++) {\n                    var group = $scope.group_array[i];\n                    for (var j = 0; j < group.servers.length; j++) {\n                        if (group.servers[j].ha_status == \"ha_real_master\") {\n                            ha_real_master = j;\n                        }\n                    }\n                    gids.push(group.id);\n                }\n                if (ha_real_master < 0) {\n                    alertAction(\"Resync All Groups: group-[\" + gids + \"]\", function () {\n                        var xauth = genXAuth(codis_name);\n                        var url = concatUrl(\"/api/topom/group/resync-all/\" + xauth, codis_name);\n                        $http.put(url).then(function () {\n                            $scope.refreshStats();\n                        }, function (failedResp) {\n                            alertErrorResp(failedResp);\n                        });\n                    });\n                } else {\n                    alertAction2(\"Resync All Groups: group-[\" + gids + \"] (in conflict with HA)\", function () {\n                        var xauth = genXAuth(codis_name);\n                        var url = concatUrl(\"/api/topom/group/resync-all/\" + xauth, codis_name);\n                        $http.put(url).then(function () {\n                            $scope.refreshStats();\n                        }, function (failedResp) {\n                            alertErrorResp(failedResp);\n                        });\n                    });\n                }\n            }\n        }\n\n        $scope.resyncSentinels = function () {\n            var codis_name = $scope.codis_name;\n            if (isValidInput(codis_name)) {\n                var servers = [];\n                for (var i = 0; i < $scope.sentinel_servers.length; i ++) {\n                    servers.push($scope.sentinel_servers[i].server);\n                }\n                var confused = [];\n                for (var i = 0; i < $scope.group_array.length; i ++) {\n                    var group = $scope.group_array[i];\n                    var ha_real_master = -1;\n                    for (var j = 0; j < group.servers.length; j ++) {\n                        if (group.servers[j].ha_status == \"ha_real_master\") {\n                            ha_real_master = j;\n                        }\n                    }\n                    if (ha_real_master >= 0) {\n                        confused.push({group: group.id, logical_master: group.servers[0].server, ha_real_master: group.servers[ha_real_master].server});\n                    }\n                }\n                if (confused.length == 0) {\n                    alertAction(\"Resync All Sentinels: \" + toJsonHtml(servers), function () {\n                        var xauth = genXAuth(codis_name);\n                        var url = concatUrl(\"/api/topom/sentinels/resync-all/\" + xauth, codis_name);\n                        $http.put(url).then(function () {\n                            $scope.refreshStats();\n                        }, function (failedResp) {\n                            alertErrorResp(failedResp);\n                        });\n                    });\n                } else {\n                    var prompts = toJsonHtml(servers);\n                    prompts += \"\\n\\n\";\n                    prompts += \"HA: real master & logical master area conflicting: \" + toJsonHtml(confused);\n                    prompts += \"\\n\\n\";\n                    prompts += \"Please fix these before resync sentinels.\";\n                    alertAction2(\"Resync All Sentinels: \" + prompts, function () {\n                        var xauth = genXAuth(codis_name);\n                        var url = concatUrl(\"/api/topom/sentinels/resync-all/\" + xauth, codis_name);\n                        $http.put(url).then(function () {\n                            $scope.refreshStats();\n                        }, function (failedResp) {\n                            alertErrorResp(failedResp);\n                        });\n                    });\n                }\n            }\n        }\n\n        $scope.addSentinel = function (server_addr) {\n            var codis_name = $scope.codis_name;\n            if (isValidInput(codis_name) && isValidInput(server_addr)) {\n                var xauth = genXAuth(codis_name);\n                var url = concatUrl(\"/api/topom/sentinels/add/\" + xauth + \"/\" + server_addr, codis_name);\n                $http.put(url).then(function () {\n                    $scope.refreshStats();\n                }, function (failedResp) {\n                    alertErrorResp(failedResp);\n                });\n            }\n        }\n\n        $scope.delSentinel = function (sentinel, force) {\n            var codis_name = $scope.codis_name;\n            if (isValidInput(codis_name)) {\n                var prefix = \"\";\n                if (force) {\n                    prefix = \"[FORCE] \";\n                }\n                alertAction(prefix + \"Remove sentinel \" + sentinel.server, function () {\n                    var xauth = genXAuth(codis_name);\n                    var value = 0;\n                    if (force) {\n                        value = 1;\n                    }\n                    var url = concatUrl(\"/api/topom/sentinels/del/\" + xauth + \"/\" + sentinel.server + \"/\" + value, codis_name);\n                    $http.put(url).then(function () {\n                        $scope.refreshStats();\n                    }, function (failedResp) {\n                        alertErrorResp(failedResp);\n                    });\n                });\n            }\n        }\n\n        $scope.addGroupServer = function (group_id, datacenter, server_addr) {\n            var codis_name = $scope.codis_name;\n            if (isValidInput(codis_name) && isValidInput(group_id) && isValidInput(server_addr)) {\n                var xauth = genXAuth(codis_name);\n                if (datacenter == undefined) {\n                    datacenter = \"\";\n                } else {\n                    datacenter = datacenter.trim();\n                }\n                var suffix = \"\";\n                if (datacenter != \"\") {\n                    suffix = \"/\" + datacenter;\n                }\n                var url = concatUrl(\"/api/topom/group/add/\" + xauth + \"/\" + group_id + \"/\" + server_addr + suffix, codis_name);\n                $http.put(url).then(function () {\n                    $scope.refreshStats();\n                }, function (failedResp) {\n                    alertErrorResp(failedResp);\n                });\n            }\n        }\n\n        $scope.delGroupServer = function (group, server_addr) {\n            var codis_name = $scope.codis_name;\n            if (isValidInput(codis_name) && isValidInput(server_addr)) {\n                var o = {};\n                o.id = group.id;\n                o.servers = [];\n                var ha_real_master = -1;\n                for (var j = 0; j < group.servers.length; j++) {\n                    o.servers.push(group.servers[j].server);\n                    if (group.servers[j].ha_status == \"ha_real_master\") {\n                        ha_real_master = j;\n                    }\n                }\n                if (ha_real_master < 0 || group.servers[ha_real_master].server != server_addr) {\n                    alertAction(\"Remove server \" + server_addr + \" from Group-[\" + group.id + \"]: \" + toJsonHtml(o), function () {\n                        var xauth = genXAuth(codis_name);\n                        var url = concatUrl(\"/api/topom/group/del/\" + xauth + \"/\" + group.id + \"/\" + server_addr, codis_name);\n                        $http.put(url).then(function () {\n                            $scope.refreshStats();\n                        }, function (failedResp) {\n                            alertErrorResp(failedResp);\n                        });\n                    });\n                } else {\n                    var prompts = toJsonHtml(o);\n                    prompts += \"\\n\\n\";\n                    prompts += \"HA: server[\" + ha_real_master + \"]=\" + server_addr + \" should be the real group master, do you really want to remove it ??\";\n                    alertAction2(\"Remove server \" + server_addr + \" from Group-[\" + group.id + \"]: \" + prompts, function () {\n                        var xauth = genXAuth(codis_name);\n                        var url = concatUrl(\"/api/topom/group/del/\" + xauth + \"/\" + group.id + \"/\" + server_addr, codis_name);\n                        $http.put(url).then(function () {\n                            $scope.refreshStats();\n                        }, function (failedResp) {\n                            alertErrorResp(failedResp);\n                        });\n                    });\n\n                }\n            }\n        }\n\n        $scope.promoteServer = function (group, server_addr) {\n            var codis_name = $scope.codis_name;\n            if (isValidInput(codis_name) && isValidInput(server_addr)) {\n                var o = {};\n                o.id = group.id;\n                o.servers = [];\n                var ha_real_master = -1;\n                for (var j = 0; j < group.servers.length; j++) {\n                    o.servers.push(group.servers[j].server);\n                    if (group.servers[j].ha_status == \"ha_real_master\") {\n                        ha_real_master = j;\n                    }\n                }\n                if (ha_real_master < 0 || group.servers[ha_real_master].server == server_addr) {\n                    alertAction(\"Promote server \" + server_addr + \" from Group-[\" + group.id + \"]: \" + toJsonHtml(o), function () {\n                        var xauth = genXAuth(codis_name);\n                        var url = concatUrl(\"/api/topom/group/promote/\" + xauth + \"/\" + group.id + \"/\" + server_addr, codis_name);\n                        $http.put(url).then(function () {\n                            $scope.refreshStats();\n                        }, function (failedResp) {\n                            alertErrorResp(failedResp);\n                        });\n                    });\n                } else {\n                    var prompts = toJsonHtml(o);\n                    prompts += \"\\n\\n\";\n                    prompts += \"HA: server[\" + ha_real_master + \"]=\" + group.servers[ha_real_master].server + \" should be the real group master, do you really want to promote \" + server_addr + \" ??\";\n                    alertAction2(\"Promote server \" + server_addr + \" from Group-[\" + group.id + \"]: \" + prompts, function () {\n                        var xauth = genXAuth(codis_name);\n                        var url = concatUrl(\"/api/topom/group/promote/\" + xauth + \"/\" + group.id + \"/\" + server_addr, codis_name);\n                        $http.put(url).then(function () {\n                            $scope.refreshStats();\n                        }, function (failedResp) {\n                            alertErrorResp(failedResp);\n                        });\n                    });\n                }\n            }\n        }\n\n        $scope.enableReplicaGroups = function (group_id, server_addr, replica_group) {\n            var codis_name = $scope.codis_name;\n            if (isValidInput(codis_name) && isValidInput(group_id) && isValidInput(server_addr)) {\n                var xauth = genXAuth(codis_name);\n                var value = 0;\n                if (replica_group) {\n                    value = 1;\n                }\n                var url = concatUrl(\"/api/topom/group/replica-groups/\" + xauth + \"/\" + group_id + \"/\" + server_addr + \"/\" + value, codis_name);\n                $http.put(url).then(function () {\n                    $scope.refreshStats();\n                }, function (failedResp) {\n                    alertErrorResp(failedResp);\n                });\n            }\n        }\n\n        $scope.enableReplicaGroupsAll = function (value) {\n            var codis_name = $scope.codis_name;\n            if (isValidInput(codis_name)) {\n                var xauth = genXAuth(codis_name);\n                var url = concatUrl(\"/api/topom/group/replica-groups-all/\" + xauth + \"/\" + value, codis_name);\n                $http.put(url).then(function () {\n                    $scope.refreshStats();\n                }, function (failedResp) {\n                    alertErrorResp(failedResp);\n                });\n            }\n        }\n\n        $scope.createSyncAction = function (server_addr) {\n            var codis_name = $scope.codis_name;\n            if (isValidInput(codis_name) && isValidInput(server_addr)) {\n                var xauth = genXAuth(codis_name);\n                var url = concatUrl(\"/api/topom/group/action/create/\" + xauth + \"/\" + server_addr, codis_name);\n                $http.put(url).then(function () {\n                    $scope.refreshStats();\n                }, function (failedResp) {\n                    alertErrorResp(failedResp);\n                });\n            }\n        }\n\n        $scope.removeSyncAction = function (server_addr) {\n            var codis_name = $scope.codis_name;\n            if (isValidInput(codis_name) && isValidInput(server_addr)) {\n                var xauth = genXAuth(codis_name);\n                var url = concatUrl(\"/api/topom/group/action/remove/\" + xauth + \"/\" + server_addr, codis_name);\n                $http.put(url).then(function () {\n                    $scope.refreshStats();\n                }, function (failedResp) {\n                    alertErrorResp(failedResp);\n                });\n            }\n        }\n\n        $scope.createSlotActionSome = function (slots_num, group_from, group_to) {\n            var codis_name = $scope.codis_name;\n            if (isValidInput(codis_name) && isValidInput(slots_num) && isValidInput(group_from) && isValidInput(group_to)) {\n                alertAction(\"Migrate \" + slots_num + \" Slots from Group-[\" + group_from + \"] to Group-[\" + group_to + \"]\", function () {\n                    var xauth = genXAuth(codis_name);\n                    var url = concatUrl(\"/api/topom/slots/action/create-some/\" + xauth + \"/\" + group_from + \"/\" + group_to + \"/\" + slots_num, codis_name);\n                    $http.put(url).then(function () {\n                        $scope.refreshStats();\n                    }, function (failedResp) {\n                        alertErrorResp(failedResp);\n                    });\n                });\n            }\n        }\n\n        $scope.createSlotActionRange = function (slot_beg, slot_end, group_id) {\n            var codis_name = $scope.codis_name;\n            if (isValidInput(codis_name) && isValidInput(slot_beg) && isValidInput(slot_end) && isValidInput(group_id)) {\n                alertAction(\"Migrate Slots-[\" + slot_beg + \",\" + slot_end + \"] to Group-[\" + group_id + \"]\", function () {\n                    var xauth = genXAuth(codis_name);\n                    var url = concatUrl(\"/api/topom/slots/action/create-range/\" + xauth + \"/\" + slot_beg + \"/\" + slot_end + \"/\" + group_id, codis_name);\n                    $http.put(url).then(function () {\n                        $scope.refreshStats();\n                    }, function (failedResp) {\n                        alertErrorResp(failedResp);\n                    });\n                });\n            }\n        }\n\n        $scope.removeSlotAction = function (slot_id) {\n            var codis_name = $scope.codis_name;\n            if (isValidInput(codis_name) && isValidInput(slot_id)) {\n                var xauth = genXAuth(codis_name);\n                var url = concatUrl(\"/api/topom/slots/action/remove/\" + xauth + \"/\" + slot_id, codis_name);\n                $http.put(url).then(function () {\n                    $scope.refreshStats();\n                }, function (failedResp) {\n                    alertErrorResp(failedResp);\n                });\n            }\n        }\n\n        $scope.updateSlotActionDisabled = function (value) {\n            var codis_name = $scope.codis_name;\n            if (isValidInput(codis_name)) {\n                var xauth = genXAuth(codis_name);\n                var url = concatUrl(\"/api/topom/slots/action/disabled/\" + xauth + \"/\" + value, codis_name);\n                $http.put(url).then(function () {\n                    $scope.refreshStats();\n                }, function (failedResp) {\n                    alertErrorResp(failedResp);\n                });\n            }\n        }\n\n        $scope.updateSlotActionInterval = function (value) {\n            var codis_name = $scope.codis_name;\n            if (isValidInput(codis_name)) {\n                var xauth = genXAuth(codis_name);\n                var url = concatUrl(\"/api/topom/slots/action/interval/\" + xauth + \"/\" + value, codis_name);\n                $http.put(url).then(function () {\n                    $scope.refreshStats();\n                }, function (failedResp) {\n                    alertErrorResp(failedResp);\n                });\n            }\n        }\n\n        $scope.rebalanceAllSlots = function() {\n            var codis_name = $scope.codis_name;\n            if (isValidInput(codis_name)) {\n                var xauth = genXAuth(codis_name);\n                var url = concatUrl(\"/api/topom/slots/rebalance/\" + xauth + \"/0\", codis_name);\n                $http.put(url).then(function (resp) {\n                    var actions = []\n                    for (var i = 0; i < $scope.group_array.length; i ++) {\n                        var g = $scope.group_array[i];\n                        var slots = [], beg = 0, end = -1;\n                        for (var sid = 0; sid < 1024; sid ++) {\n                            if (resp.data[sid] == g.id) {\n                                if (beg > end) {\n                                    beg = sid; end = sid;\n                                } else if (end == sid - 1) {\n                                    end = sid;\n                                } else {\n                                    slots.push(\"[\" + beg + \",\" + end + \"]\");\n                                    beg = sid; end = sid;\n                                }\n                            }\n                        }\n                        if (beg <= end) {\n                            slots.push(\"[\" + beg + \",\" + end + \"]\");\n                        }\n                        if (slots.length == 0) {\n                            continue;\n                        }\n                        actions.push(\"group-[\" + g.id + \"] <== \" + slots);\n                    }\n                    alertAction(\"Preview of Auto-Rebalance: \" + toJsonHtml(actions), function () {\n                        var xauth = genXAuth(codis_name);\n                        var url = concatUrl(\"/api/topom/slots/rebalance/\" + xauth + \"/1\", codis_name);\n                        $http.put(url).then(function () {\n                            $scope.refreshStats();\n                        }, function (failedResp) {\n                            alertErrorResp(failedResp);\n                        });\n                    });\n                }, function (failedResp) {\n                    alertErrorResp(failedResp);\n                });\n            }\n        }\n\n        if (window.location.hash) {\n            $scope.selectCodisInstance(window.location.hash.substring(1));\n        }\n\n        var ticker = 0;\n        (function autoRefreshStats() {\n            if (ticker >= $scope.refresh_interval) {\n                ticker = 0;\n                $scope.refreshStats();\n            }\n            ticker++;\n            $timeout(autoRefreshStats, 1000);\n        }());\n    }\n])\n;\n"
  },
  {
    "path": "cmd/fe/assets/index.html",
    "content": "<!doctype html>\n<html lang=\"en\" ng-app=\"dashboard-fe\" data-framework=\"angularjs\">\n<head>\n    <meta charset=\"utf-8\">\n    <meta name=\"description\" content=\"\">\n    <meta name=\"viewport\" content=\"width=device-width\">\n\n    <title>Codis • Dashboard</title>\n    <link rel=\"stylesheet\" href=\"node_modules/bootstrap-dialog/src/css/bootstrap-dialog.css\" media=\"all\">\n    <link rel=\"stylesheet\" href=\"node_modules/bootstrap/dist/css/bootstrap.css\" media=\"all\">\n    <link rel=\"stylesheet\" href=\"css/main.css\" media=\"all\">\n    <style>[ng-cloak] {\n        display: none;\n    }</style>\n    <style type=\"text/css\">\n        .bs-example {\n            margin: 20px;\n        }\n\n        @media screen and (min-width: 968px) {\n            .modal-dialog {\n                width: 900px; /* New width for default modal */\n            }\n        }\n    </style>\n</head>\n<body ng-controller=\"MainCodisCtrl\">\n<div class=\"body-container\" ng-cloak>\n    <div id=\"sidebar\">\n        <div class=\"content\">\n            <div class=\"title\" dis=\"1\"> Codis</div>\n            <div class=\"items\">\n                <ul class=\"ui-itemlist\" ng-repeat=\"cname in codis_list\">\n                    <li><a href=\"#[[cname]]\" ng-click=\"selectCodisInstance(cname)\">[[cname]]</a></li>\n                </ul>\n            </div>\n        </div>\n    </div>\n</div>\n\n<div id=\"main\">\n    <div class=\"container-full\">\n        <div class=\"row\" style=\"min-width: 400px\">\n            <div class=\"col-md-12\">\n                <h4 style=\"padding-left:20px;\"><b>Overview</b></h4>\n                <table class=\"table table-bordered\" style=\"font-weight: bold;\">\n                    <col width=\"200px\">\n                    <tbody>\n                    <tr>\n                        <td>Product Name</td>\n                        <td>[[codis_name]]</td>\n                    </tr>\n                    <tr>\n                        <td>[[codis_coord_name]]</td>\n                        <td>[[codis_coord_addr]]</td>\n                    </tr>\n                    <tr>\n                        <td>Codis QPS</td>\n                        <td>[[codis_qps]]</td>\n                    </tr>\n                    <tr>\n                        <td>Sessions</td>\n                        <td>[[codis_sessions]]</td>\n                    </tr>\n                    <tr>\n                        <td>Redis Memory</td>\n                        <td>[[redis_mem]]</td>\n                    </tr>\n                    <tr>\n                        <td>Redis Keys</td>\n                        <td>[[redis_keys]]</td>\n                    </tr>\n                    <tr>\n                        <td>Dashboard</td>\n                        <td ng-switch=\"codis_addr\">\n                            <span ng-switch-when=\"NA\">NA</span>\n                            <span ng-switch-default><a href=\"http://[[codis_addr]]/topom\" target=\"_blank\">[[codis_addr]]</a></span>\n                        </td>\n                    </tr>\n                    </tbody>\n                </table>\n                <div>\n                    <highchart config=\"chart_ops\" style=\"height:270px\"></highchart>\n                </div>\n                <table class=\"table\">\n                    <col width=\"200px\">\n                    <tr>\n                        <td style=\"border:none;\" ng-model=\"refresh_interval\">\n                            <b>Refresh: [[refresh_interval]]</b>\n                        </td>\n                        <td style=\"border:none;\">\n                            <input type=\"range\" min=\"1\" max=\"60\" step=\"1\" ng-model=\"refresh_interval\"\n                                   value=\"[[refresh_interval]]\">\n                        </td>\n                    </tr>\n                </table>\n            </div>\n        </div>\n\n        <div class=\"row\" style=\"min-width: 1200px\">\n            <div class=\"col-md-12\"\n                 style=\"margin-bottom: 10px; padding-bottom: 10px; border-bottom: solid 1px lightgray;\">\n                <form class=\"form-inline\">\n                    <h4 style=\"padding-left:30px; padding-right:20px; display: inline;\">Proxy</h4>\n                </form>\n            </div>\n            <div class=\"col-md-12\"\n                 style=\"padding-bottom: 10px;\">\n                <form class=\"form-inline\">\n                    <span ng-if=\"codis_addr != 'NA'\">\n                    <button class=\"btn btn-warning btn-sm active\" style=\"width: 120px; font-size: 14px; padding: 2px;\"\n                            ng-click=\"createProxy(new_proxy)\"\n                            ng-disabled=\"!new_proxy\">New Proxy\n                    </button>\n                    <input style=\"height: 28px; width: 250px;\" type=\"text\" class=\"form-control\" placeholder=\"Proxy Admin Address\"\n                           ng-model=\"new_proxy\">\n                    </span>\n                </form>\n            </div>\n            <div class=\"col-md-12\" ng-if=\"proxy_array.length != 0\">\n                <table class=\"table table-bordered table-striped table-hover table-condensed\" style=\"white-space: nowrap\">\n                    <thead>\n                    <tr>\n                        <th style=\"width: 35px; text-align: center\"/>ID</th>\n                        <th style=\"width: 50px; text-align: center\">Stats</th>\n                        <th style=\"min-width: 160px;\">Proxy</th>\n                        <th style=\"min-width: 160px;\">Admin</th>\n                        <th style=\"width: 60px;\"/>\n                        <th style=\"min-width: 100px;\">Data Center</th>\n                        <th style=\"width: 35px;\"/>\n                        <th style=\"min-width: 140px;\">Sessions</th>\n                        <th style=\"min-width: 200px;\">Commands</th>\n                        <th style=\"width: 35px;\"></th>\n                    </tr>\n                    </thead>\n                    <tr ng-repeat=\"proxy in proxy_array\">\n                        <td class=\"text-center\">[[proxy.id]]</td>\n                        <td>\n                            <a ng-href=\"http://[[proxy.proxy_link]]\" target=\"_blank\" class=\"btn btn-primary btn-xs active\" role=\"button\">F</a>\n                            <a ng-href=\"http://[[proxy.stats_link]]\" target=\"_blank\" class=\"btn btn-default btn-xs active\" role=\"button\">\n                                <span ng-if=\"proxy.primary_only\" style=\"color: DarkRed; font-weight: bold;\"\n                                    data-toggle=\"tooltip\" data-placement=\"right\" title=\"BACKEND: PRIMARY ONLY\">S</span>\n                                <span ng-if=\"!proxy.primary_only\">S</span>\n                            </a>\n                        </td>\n                        <td ng-switch=\"proxy.switched\">\n                            <span ng-switch-when=\"true\" style=\"color: white; background-color: red\"\n                                data-toggle=\"tooltip\" data-placement=\"right\" title=\"HA: MASTER SWITCHED\">\n                                [[proxy.proxy_addr]]\n                            </span>\n                            <span ng-switch-default>\n                                [[proxy.proxy_addr]]\n                            </span>\n                        </td>\n                        <td ng-switch=\"proxy.switched\">\n                            <span ng-switch-when=\"true\" style=\"color: white; background-color: red\"\n                                data-toggle=\"tooltip\" data-placement=\"right\" title=\"HA: MASTER SWITCHED\">\n                                [[proxy.admin_addr]]\n                            </span>\n                            <span ng-switch-default>\n                                [[proxy.admin_addr]]\n                            </span>\n                        </td>\n                        <td style=\"text-align: center\">\n                            <span ng-if=\"proxy.status == 'HEALTHY' && !proxy.switched\" class=\"btn btn-success btn-xs active\"\n                                data-toggle=\"tooltip\" data-placement=\"right\" title=\"RESYNC ALL SLOTS to [[proxy.proxy_addr]]\"\n                                ng-click=\"reinitProxy(proxy)\">\n                                SYNC\n                            </span>\n                            <span ng-if=\"proxy.status == 'PENDING' || proxy.switched\" class=\"btn btn-danger btn-xs active\"\n                                data-toggle=\"tooltip\" data-placement=\"right\" title=\"RESYNC ALL SLOTS to [[proxy.proxy_addr]]\"\n                                ng-click=\"reinitProxy(proxy)\">\n                                SYNC\n                            </span>\n                        </td>\n                        <td>[[proxy.datacenter]]</td>\n                        <td class=\"button_tight_column\" style=\"text-align: center\">\n                            <button class=\"btn btn-danger btn-xs active\" ng-if=\"proxy.status == 'ERROR'\"\n                                data-toggle=\"tooltip\" data-placement=\"right\" title=\"FORCE REMOVE PROXY [[proxy.proxy_addr]]\"\n                                ng-click=\"removeProxy(proxy, true)\">\n                                <span class=\"glyphicon glyphicon-remove\"></span>\n                            </button>\n                        </td>\n                        <td>[[proxy.sessions]]</td>\n                        <td ng-switch=\"proxy.status\">\n                            <span ng-switch-when=\"ERROR\" class=\"status_label_error\">[[proxy.status]]</span>\n                            <span ng-switch-when=\"TIMEOUT\" class=\"status_label_warning\">[[proxy.status]]</span>\n                            <span ng-switch-when=\"PENDING\" class=\"status_label_pending\">[[proxy.status]]</span>\n                            <span ng-switch-default>[[proxy.commands]]</span>\n                        </td>\n                        <td class=\"button_tight_column\" style=\"text-align: center\">\n                            <button class=\"btn btn-danger btn-xs active\"\n                                data-toggle=\"tooltip\" data-placement=\"right\" title=\"REMOVE PROXY [[proxy.proxy_addr]]\"\n                                ng-click=\"removeProxy(proxy, false)\">\n                                <span class=\"glyphicon glyphicon-minus\"></span>\n                            </button>\n                        </td>\n                    </tr>\n                    </tbody>\n                </table>\n            </div>\n        </div>\n\n        <div class=\"row\">\n            <div class=\"col-md-12\"\n                 style=\"margin-bottom: 10px; padding-bottom: 10px; border-bottom: solid 1px lightgray;\">\n                <form class=\"form-inline\">\n                    <h4 style=\"padding-left:30px; padding-right:20px; display: inline;\">Slots</h4>\n                </form>\n            </div>\n            <div class=\"col-md-12\"\n                 style=\"padding-bottom: 10px;\">\n                <form class=\"form-inline\">\n                    <span ng-if=\"codis_addr != 'NA'\">\n                        <button class=\"btn btn-warning btn-sm active\" style=\"width: 120px; font-size: 14px; padding: 2px;\"\n                                ng-click=\"createSlotActionRange(migrate_slot_id_beg, migrate_slot_id_end, migrate_range_to_group_id)\"\n                                ng-disabled=\"!migrate_slot_id_beg || !migrate_slot_id_end || !migrate_range_to_group_id\">\n                            Migrate Range\n                        </button>\n                        Slots-[\n                        <input style=\"height: 28px; width: 140px; \" type=\"text\"\n                               class=\"form-control\" placeholder=\"[0,1023]\"\n                               ng-model=\"migrate_slot_id_beg\">\n                        ~\n                        <input style=\"height: 28px; width: 140px; \" type=\"text\"\n                               class=\"form-control\" placeholder=\"[0,1023]\"\n                               ng-model=\"migrate_slot_id_end\">\n                        ] to Group\n                        <input style=\"height: 28px; width: 140px;\"\n                               pattern=\"^(?:[1-9][0-9]{1,3}|[1-9])$\"\n                               class=\"form-control\" placeholder=\"[1,9999]\"\n                               ng-model=\"migrate_range_to_group_id\">\n                    </span>\n                </form>\n            </div>\n\n            <div class=\"col-md-12\">\n                <div id=\"slots_charts\" style=\"min-width: 400px; height: 240px; margin: 0 auto\"></div>\n            </div>\n\n            <div class=\"col-md-12\"\n                 style=\"padding-bottom: 10px;\">\n                <form class=\"form-inline\">\n                    <span ng-if=\"codis_addr != 'NA'\">\n                        <button class=\"btn btn-warning btn-sm active\" style=\"width: 120px; font-size: 14px; padding: 2px;\"\n                                ng-click=\"createSlotActionSome(migrate_some_slots_num, migrate_some_group_from, migrate_some_group_to)\"\n                                ng-disabled=\"!migrate_some_slots_num || !migrate_some_group_from || !migrate_some_group_to\">\n                            Migrate Some\n                        </button>\n                        <input style=\"height: 28px; width: 130px; \" type=\"text\"\n                               class=\"form-control\" placeholder=\"Number of Slots\"\n                               ng-model=\"migrate_some_slots_num\">\n                        from Group\n                        <input style=\"height: 28px; width: 140px; \"\n                               class=\"form-control\" placeholder=\"[1,9999]\"\n                               ng-model=\"migrate_some_group_from\">\n                        to Group\n                        <input style=\"height: 28px; width: 140px;\"\n                               pattern=\"^(?:[1-9][0-9]{1,3}|[1-9])$\"\n                               class=\"form-control\" placeholder=\"[1,9999]\"\n                               ng-model=\"migrate_some_group_to\">\n                    </span>\n                </form>\n            </div>\n\n            <div>\n                <div class=\"row\">\n                    <div class=\"col-md-6\" style=\"min-width:450px;\">\n                        <table class=\"table table-bordered\" style=\"font-weight:bold;\">\n                            <col width=\"40%\">\n                            <col width=\"60%\">\n                            <tbody>\n                            <tr>\n                                <td ng-switch=\"slots_action_disabled\">\n                                    <span ng-switch-when=\"true\">\n                                        Action : Disabled\n                                    </span>\n                                    <span ng-switch-when=\"false\">\n                                        Action : Enabled\n                                    </span>\n                                </td>\n\n                                <td>\n                                    <span class=\"btn-group\">\n                                        <button class=\"btn btn-success btn-xs active\" style=\"width: 120px;\"\n                                                ng-disabled=\"!slots_action_disabled\"\n                                                ng-click=\"updateSlotActionDisabled(0)\">\n                                            Enable\n                                        </button>\n                                        <button class=\"btn btn-danger btn-xs active\" style=\"width: 120px;\"\n                                                ng-disabled=\"slots_action_disabled\"\n                                                ng-click=\"updateSlotActionDisabled(1)\">\n                                            Disable\n                                        </button>\n                                    </span>\n                                </td>\n                            </tr>\n                            <tr>\n                                <td>Action Interval (us)</td>\n                                <td>\n                                    <div class=\"input-group\">\n                                        <input type=\"text\" class=\"form-control\" style=\"height: 22px;\"\n                                               pattern=\"^(?:[1][0]{6}|[1-9][0-9]{1,5}|[0-9])$\"\n                                               placeholder=\"[[slots_action_interval]]\"\n                                               ng-model=\"updated_slots_action_interval\">\n                                            <span class=\"input-group-btn active\">\n                                                <button class=\"btn btn-primary btn-xs active\" type=\"button\"\n                                                        ng-click=\"updateSlotActionInterval(updated_slots_action_interval)\"\n                                                        ng-disabled=\"!updated_slots_action_interval\">\n                                                    Update\n                                                </button>\n                                            </span>\n                                    </div>\n                                </td>\n                            </tr>\n                            <tr>\n                                <td>Action Status</td>\n                                <td>\n                                    <span>\n                                        [[slots_action_progress]]\n                                    </span>\n                                </td>\n                            </tr>\n                            <tr>\n                                <td>Show Actions</td>\n                                <td>\n                                    <input type=\"checkbox\" ng-model=\"show_slots_actions\">\n                                </td>\n                            </tr>\n                            <tr>\n                                <td>Auto-Rebalance</td>\n                                <td>\n                                    <span>\n                                        <button class=\"btn btn-danger btn-xs active\" style=\"width: 240px;\"\n                                                ng-click=\"rebalanceAllSlots()\">\n                                            Rebalance All Slots\n                                        </button>\n                                    </span>\n                                </td>\n                            </tr>\n                            </tbody>\n                        </table>\n                    </div>\n                    <div class=\"col-md-6\" ng-if=\"show_slots_actions\">\n                        <table class=\"table table-bordered table-striped table-hover table-condensed\" style=\"white-space: nowrap\">\n                            <thead>\n                            <tr>\n                                <th style=\"min-width: 35px\">Slot</th>\n                                <th style=\"min-width: 35px\">Group</th>\n                                <th style=\"min-width: 35px\">Target</th>\n                                <th style=\"min-width: 35px\">Index</th>\n                                <th style=\"min-width: 120px;\">Status</th>\n                                <th style=\"width: 35px;\"></th>\n                            </tr>\n                            </thead>\n                            <tr ng-repeat=\"slot in slots_actions\">\n                                <td class=\"text-center\">[[slot.id]]</td>\n                                <td>[[slot.group_id]]</td>\n                                <td>[[slot.action.target_id]]</td>\n                                <td>[[slot.action.index]]</td>\n                                <td ng-switch=\"slot.action.state\">\n                                    <span ng-switch-when=\"pending\">\n                                        [[slot.action.state]]\n                                    </span>\n                                    <span ng-switch-default style=\"color: red; font-weight: bold;\">\n                                        [[slot.action.state]]\n                                    </span>\n                                </td>\n                                <td class=\"button_tight_column\" ng-switch=\"slot.action.state\">\n                                    <span ng-switch-when=\"pending\">\n                                        <button class=\"btn btn-danger btn-xs active\" ng-click=\"removeSlotAction(slot.id)\">\n                                            <span class=\"glyphicon glyphicon-minus\"></span>\n                                        </button>\n                                    </span>\n                                </td>\n                            </tr>\n                            </tbody>\n                        </table>\n                    </div>\n                </div>\n            </div>\n        </div>\n\n        <div class=\"row\" style=\"min-width: 1200px\">\n            <div class=\"col-md-12\"\n                 style=\"margin-bottom: 10px; padding-bottom: 10px; border-bottom: solid 1px lightgray;\">\n                <form class=\"form-inline\">\n                    <h4 style=\"padding-left:30px; padding-right:20px; display: inline;\">Group</h4>\n                </form>\n            </div>\n            <div class=\"col-md-12\"\n                 style=\"padding-bottom: 10px;\">\n                <form class=\"form-inline\" style=\"padding-bottom:5px\">\n                    <span ng-if=\"codis_addr != 'NA'\">\n                        <button class=\"btn btn-success btn-sm active\" style=\"width: 120px; font-size: 14px; padding: 2px;\"\n                                ng-click=\"createGroup(new_group)\"\n                                ng-disabled=\"!new_group\">New Group\n                        </button>\n                        <input style=\"height: 28px; width: 140px;\"\n                               pattern=\"^(?:[1-9][0-9]{1,3}|[1-9])$\"\n                               class=\"form-control\" placeholder=\"Group [1,9999]\"\n                               ng-model=\"new_group\">\n                    </span>\n                </form>\n                <form class=\"form-inline\" style=\"padding-bottom: 5px\">\n                    <span ng-if=\"codis_addr != 'NA'\">\n                        <button class=\"btn btn-warning btn-sm active\" style=\"width: 120px; font-size: 14px; padding: 2px;\"\n                                ng-click=\"addGroupServer(new_server_group, new_server_datacenter, new_server_addr)\"\n                                ng-disabled=\"!new_server_group || !new_server_addr\">Add Server\n                        </button>\n                        <input style=\"height: 28px; width: 140px; \" type=\"text\" class=\"form-control\"\n                               class=\"form-control\" placeholder=\"Data Center\"\n                               ng-model=\"new_server_datacenter\">\n                        <input style=\"height: 28px; width: 250px; \" type=\"text\" class=\"form-control\"\n                               placeholder=\"Codis Server Address\"\n                               ng-model=\"new_server_addr\">\n                        to\n                        <input style=\"height: 28px; width: 140px;\"\n                               pattern=\"^(?:[1-9][0-9]{1,3}|[1-9])$\"\n                               class=\"form-control\" placeholder=\"Group [1,9999]\"\n                               ng-model=\"new_server_group\">\n                    </span>\n                </form>\n                <form class=\"form-inline\">\n                    <span ng-if=\"group_array.length != 0\" class=\"btn-group\">\n                        <button class=\"btn btn-primary btn-xs active\" style=\"width: 160px; font-size: 14px; padding: 2px;\"\n                                ng-click=\"resyncGroupAll()\">GROUPS: SYNC ALL\n                        </button>\n                        <button class=\"btn btn-success btn-xs active\" style=\"width: 200px; font-size: 14px; padding: 2px;\"\n                                ng-click=\"enableReplicaGroupsAll(1)\">REPLICA(S): ENABLE ALL\n                        </button>\n                        <button class=\"btn btn-danger btn-xs active\" style=\"width: 200px; font-size: 14px; padding: 2px;\"\n                                ng-click=\"enableReplicaGroupsAll(0)\">REPLICA(S): DISABLE ALL\n                        </button>\n                    </span>\n                </form>\n            </div>\n\n            <div class=\"col-md-12\" ng-repeat=\"group in group_array\">\n                <table class=\"table table-bordered table-striped table-hover table-condensed\">\n                    <thead>\n                    <tr>\n                        <th style=\"width: 85px; text-align: center\" ng-switch=\"group.ispromoting\">\n                            <span ng-switch-when=\"true\" class=\"status_label_error\">\n                                [ [[group.id]] ]\n                            </span>\n                            <span ng-switch-default>\n                                [[group.id]]\n                            </span>\n                        </th>\n                        <th style=\"min-width: 190px;\"> Server\n                            <span ng-if=\"group.ha_warning != ''\" style=\"color: white; background-color: red\">\n                                    [[group.ha_warning]]\n                            </span>\n                        </th>\n                        <th style=\"min-width: 100px;\">Data Center</th>\n                        <th style=\"min-width: 180px;\">\n                            <span ng-switch=\"group.out_of_sync\">\n                                <span ng-switch-when=\"true\" style=\"color: white; background-color: red\">\n                                    (OUT OF SYNC)\n                                </span>\n                                <span ng-switch-default>\n                                    Master\n                                </span>\n                            </span>\n                        </th>\n                        <th style=\"width: 25px;\"/>\n                        <th style=\"width: 35px;\"/>\n                        <th style=\"min-width: 100px;\"/>\n                        <th style=\"min-width: 140px;\">Memory</th>\n                        <th style=\"min-width: 230px;\">Keys</th>\n                        <th style=\"width: 35px; text-align: center\">\n                            <span ng-if=\"!group.ispromoting\">\n                                <span ng-if=\"group.canremove\">\n                                    <button class=\"btn btn-primary btn-xs active\"\n                                            data-toggle=\"tooltip\" data-placement=\"right\" title=\"REMOVE GROUP-[[group.id]]\"\n                                            ng-click=\"removeGroup(group.id)\">\n                                        <span class=\"glyphicon glyphicon-trash\"></span>\n                                    </button>\n                                </span>\n                            </span>\n                        </th>\n                    </tr>\n                    </thead>\n                    <tr ng-repeat=\"server in group.servers\">\n                        <td class=\"button_tight_column\" style=\"text-align: center\">\n                            <span ng-if=\"!group.ispromoting\">\n                                <span ng-if=\"server.canpromote\">\n                                    <span ng-switch=\"server.ha_status\">\n                                        <span ng-switch-when=\"ha_real_master\">\n                                            <button class=\"btn btn-success btn-xs active\"\n                                                    style=\"width: 70px;\"\n                                                    data-toggle=\"tooltip\" data-placement=\"right\" title=\"PROMOTE SERVER [[server.server]]\"\n                                                    ng-click=\"promoteServer(group, server.server)\">\n                                                PROMOTE\n                                            </button>\n                                        </span>\n                                        <span ng-switch-default>\n                                            <button class=\"btn btn-warning btn-xs active\"\n                                                    style=\"width: 70px;\"\n                                                    data-toggle=\"tooltip\" data-placement=\"right\" title=\"PROMOTE SERVER [[server.server]]\"\n                                                    ng-click=\"promoteServer(group, server.server)\">\n                                                PROMOTE\n                                            </button>\n                                        </span>\n                                    </span>\n                                </span>\n                                <span ng-if=\"!server.canpromote\" ng-switch=\"group.out_of_sync\">\n                                    <span ng-switch-when=\"true\">\n                                        <button class=\"btn btn-danger btn-xs active\"\n                                                style=\"width: 70px;\"\n                                                data-toggle=\"tooltip\" data-placement=\"right\" title=\"RESYNC SLOTS of GROUP-[[group.id]]\"\n                                                ng-click=\"resyncGroup(group)\">\n                                            SYNC\n                                        </button>\n                                    </span>\n                                    <span ng-switch-default>\n                                        <button class=\"btn btn-primary btn-xs active\"\n                                                style=\"width: 70px;\"\n                                                data-toggle=\"tooltip\" data-placement=\"right\" title=\"RESYNC SLOTS of GROUP-[[group.id]]\"\n                                                ng-click=\"resyncGroup(group)\">\n                                            SYNC\n                                        </button>\n                                    </span>\n                                </span>\n                            </span>\n                            <span ng-if=\"group.ispromoting\">\n                                <span ng-if=\"server.ispromoting\">\n                                    <button class=\"btn btn-danger btn-xs active\"\n                                            style=\"width: 70px;\"\n                                            data-toggle=\"tooltip\" data-placement=\"right\" title=\"PROMOTE SERVER [[server.server]]\"\n                                            ng-click=\"promoteServer(group, server.server)\">\n                                        PROMOTE\n                                    </button>\n                                </span>\n                            </span>\n                        </td>\n                        <td>\n                            <a ng-href=\"http://[[codis_addr]]/api/topom/group/info/[[server.server]]\" target=\"_blank\" class=\"btn btn-default btn-xs active\" role=\"button\">S</a>\n                            <span ng-switch=\"server.ha_status\">\n                                <span ng-switch-when=\"ha_master\" style=\"color: darkgreen\"\n                                    data-toggle=\"tooltip\" data-placement=\"right\" title=\"HA: MASTER\">\n                                    [[server.server_text]]\n                                </span>\n                                <span ng-switch-when=\"ha_real_master\" style=\"color: white; background-color: darkgreen\"\n                                    data-toggle=\"tooltip\" data-placement=\"right\" title=\"HA: REAL MASTER\">\n                                    [[server.server_text]]\n                                </span>\n                                <span ng-switch-when=\"ha_not_master\" style=\"color: white; background-color: red\"\n                                    data-toggle=\"tooltip\" data-placement=\"right\" title=\"HA: NOT MASTER\">\n                                    [[server.server_text]]\n                                </span>\n                                <span ng-switch-when=\"ha_slave\"\n                                    data-toggle=\"tooltip\" data-placement=\"right\" title=\"HA: SLAVE\">\n                                    [[server.server_text]]\n                                </span>\n                                <span ng-switch-when=\"ha_undefined\" style=\"color: white; background-color: darkgray\"\n                                    data-toggle=\"tooltip\" data-placement=\"right\" title=\"HA: UNDEFINED\">\n                                    [[server.server_text]]\n                                </span>\n                                <span ng-switch-default>\n                                    [[server.server_text]]\n                                </span>\n                            </span>\n                        </td>\n                        <td>[[server.datacenter]]</td>\n                        <td ng-switch=\"server.master_status\">\n                            <span ng-switch-when=\"false\" class=\"status_label_error\">[[server.master]]</span>\n                            <span ng-switch-default>[[server.master]]</span>\n                        </td>\n                        <td ng-switch=\"group.ispromoting\" style=\"text-align: center\">\n                            <span ng-switch-when=\"true\">\n                                <input type=\"checkbox\" disabled=\"disabled\"\n                                    data-toggle=\"tooltip\" data-placement=\"right\" title=\"REPLICA_GROUP = [[server.replica_group]]\"\n                                    ng-model=\"server.replica_group\">\n                            </span>\n                            <span ng-switch-default>\n                                <input type=\"checkbox\"\n                                    data-toggle=\"tooltip\" data-placement=\"right\" title=\"REPLICA_GROUP = [[server.replica_group]]\"\n                                    ng-model=\"server.replica_group\" ng-click=\"enableReplicaGroups(group.id, server.server, server.replica_group)\">\n                            </span>\n                        </td>\n                        <td class=\"button_tight_column\" ng-switch=\"group.ispromoting\">\n                            <span ng-switch-when=\"true\" ng-switch=\"server.canslaveof\">\n                                <span ng-switch-when=\"create\">\n                                    <button class=\"btn btn-success btn-xs active disabled\"\n                                            data-toggle=\"tooltip\" data-placement=\"right\" title=\"SLAVEOF [[server.master_expect]]\">\n                                        <span class=\"glyphicon glyphicon-wrench\"></span>\n                                    </button>\n                                </span>\n                                <span ng-switch-when=\"remove\">\n                                    <button class=\"btn btn-danger btn-xs active disabled\"\n                                            data-toggle=\"tooltip\" data-placement=\"right\" title=\"CANCEL ACTION\">\n                                        <span class=\"glyphicon glyphicon-minus\"></span>\n                                    </button>\n                                </span>\n                            </span>\n                            <span ng-switch-default ng-switch=\"server.canslaveof\">\n                                <span ng-switch-when=\"create\">\n                                    <button class=\"btn btn-success btn-xs active\"\n                                            data-toggle=\"tooltip\" data-placement=\"right\" title=\"SLAVEOF [[server.master_expect]]\"\n                                            ng-click=\"createSyncAction(server.server)\">\n                                        <span class=\"glyphicon glyphicon-wrench\"></span>\n                                    </button>\n                                </span>\n                                <span ng-switch-when=\"remove\">\n                                    <button class=\"btn btn-danger btn-xs active\"\n                                            data-toggle=\"tooltip\" data-placement=\"right\" title=\"CANCEL ACTION\"\n                                            ng-click=\"removeSyncAction(server.server)\">\n                                        <span class=\"glyphicon glyphicon-minus\"></span>\n                                    </button>\n                                </span>\n                            </span>\n                        </td>\n                        <td>[[server.actionstate]]</td>\n                        <td>[[server.memory]] / [[server.maxmem]]</td>\n                        <td ng-switch=\"server.status\">\n                            <span ng-switch-when=\"ERROR\" class=\"status_label_error\">[[server.status]]</span>\n                            <span ng-switch-when=\"TIMEOUT\" class=\"status_label_warning\">[[server.status]]</span>\n                            <span ng-switch-when=\"PENDING\" class=\"status_label_pending\">[[server.status]]</span>\n                            <span ng-switch-default>\n                                <span ng-switch=\"server.keys.length\">\n                                    <span ng-switch-when=\"0\">NA</span>\n                                    <span ng-switch-default>\n                                        <span ng-repeat=\"keys in server.keys\">\n                                            <br ng-if=\"$index!=0\">\n                                            [[keys]]\n                                        </span>\n                                    </span>\n                                </span>\n                            </span>\n                        </td>\n                        <td class=\"button_tight_column\" ng-switch=\"group.ispromoting\" style=\"text-align: center\">\n                            <span ng-switch-when=\"true\" ng-switch=\"server.canremove\">\n                                <span ng-switch-when=\"true\">\n                                    <button class=\"btn btn-danger btn-xs active disabled\"\n                                            data-toggle=\"tooltip\" data-placement=\"right\" title=\"REMOVE SERVER [[server.server]]\">\n                                        <span class=\"glyphicon glyphicon-minus\"></span>\n                                    </button>\n                                </span>\n                            </span>\n                            <span ng-switch-default ng-switch=\"server.canremove\">\n                                <span ng-switch-when=\"true\">\n                                    <button class=\"btn btn-danger btn-xs active\"\n                                            data-toggle=\"tooltip\" data-placement=\"right\" title=\"REMOVE SERVER [[server.server]]\"\n                                            ng-click=\"delGroupServer(group, server.server)\">\n                                        <span class=\"glyphicon glyphicon-minus\"></span>\n                                    </button>\n                                </span>\n                            </span>\n                        </td>\n                    </tr>\n                    </tbody>\n                </table>\n            </div>\n        </div>\n\n        <div class=\"row\" style=\"min-width: 1200px\">\n            <div class=\"col-md-12\"\n                 style=\"margin-bottom: 10px; margin-top: 30px; padding-bottom: 10px; border-bottom: solid 1px lightgray;\">\n                <form class=\"form-inline\">\n                    <h4 style=\"padding-left:30px; padding-right:20px; display: inline;\">Sentinels</h4>\n                </form>\n            </div>\n            <div class=\"col-md-12\"\n                 style=\"padding-bottom: 10px\">\n                <form class=\"form-inline\">\n                    <span ng-if=\"codis_addr != 'NA'\">\n                        <button class=\"btn btn-warning btn-sm active\" style=\"width: 120px; font-size: 14px; padding: 2px;\"\n                                ng-click=\"addSentinel(new_sentinel_addr)\"\n                                ng-disabled=\"!new_sentinel_addr\">Add Sentinel\n                        </button>\n                        <input style=\"height: 28px; width: 250px; \" type=\"text\" class=\"form-control\"\n                               placeholder=\"Redis Sentinel Address\"\n                               ng-model=\"new_sentinel_addr\">\n                    </span>\n                </form>\n            </div>\n            <div class=\"col-md-4\"\n                 style=\"padding-bottom: 10px\">\n                <table class=\"table table-bordered table-striped table-hover table-condensed\" style=\"white-space: nowrap\">\n                    <thead>\n                    <tr>\n                        <th style=\"width: 85px; text-align: center\">\n                            <span ng-switch=\"sentinel_out_of_sync\">\n                                <span ng-switch-when=\"true\">\n                                    <button class=\"btn btn-danger btn-xs active\"\n                                            data-toggle=\"tooltip\" data-placement=\"right\" title=\"RESYNC ALL SENTINELS & PROXIES\"\n                                            style=\"width: 70px;\"\n                                            ng-click=\"resyncSentinels()\">\n                                        SYNC\n                                    </button>\n                                </span>\n                                <span ng-switch-default>\n                                    <button class=\"btn btn-primary btn-xs active\"\n                                            data-toggle=\"tooltip\" data-placement=\"right\" title=\"RESYNC ALL SENTINELS & PROXIES\"\n                                            style=\"width: 70px;\"\n                                            ng-click=\"resyncSentinels()\">\n                                        SYNC\n                                    </button>\n                                </span>\n                            </span>\n                        </th>\n                        <th style=\"min-width: 220px;\">\n                            Sentinels\n                            <span ng-if=\"sentinel_out_of_sync\" style=\"color: white; background-color: red\">\n                                (OUT OF SYNC)\n                            </span>\n                        </th>\n                        <th style=\"min-width: 35px;\"/>\n                        <th style=\"min-width: 350px;\">\n                            Status\n                        </th>\n                        <th style=\"min-width: 35px;\"/>\n                        <th style=\"min-width: 35px;\"/>\n                    </tr>\n                    </thead>\n                    <tr ng-repeat=\"sentinel in sentinel_servers\">\n                        <td style=\"text-align: center\">\n                            <a ng-href=\"http://[[codis_addr]]/api/topom/sentinels/info/[[sentinel.server]]/monitored\" style=\"width: 70px;\" target=\"_blank\" class=\"btn btn-default btn-xs active\" role=\"button\">WATCHED</a>\n                        </td>\n                        <td>\n                            <a ng-href=\"http://[[codis_addr]]/api/topom/sentinels/info/[[sentinel.server]]\" target=\"_blank\" class=\"btn btn-default btn-xs active\" role=\"button\">S</a>\n                            <span>\n                                [[sentinel.server]]\n                            </span>\n                        </td>\n                        <td class=\"button_tight_column\" style=\"text-align: center\">\n                            <button class=\"btn btn-danger btn-xs active\" ng-if=\"sentinel.status == 'ERROR'\"\n                                data-toggle=\"tooltip\" data-placement=\"right\" title=\"FORCE REMOVE SENTINEL [[sentinel.server]]\"\n                                ng-click=\"delSentinel(sentinel, true)\">\n                                <span class=\"glyphicon glyphicon-remove\"></span>\n                            </button>\n                        </td>\n                        <td ng-switch=\"sentinel.status\">\n                            <span ng-switch-when=\"ERROR\" class=\"status_label_error\">[[sentinel.status]]</span>\n                            <span ng-switch-when=\"TIMEOUT\" class=\"status_label_warning\">[[sentinel.status]]</span>\n                            <span ng-switch-when=\"PENDING\" class=\"status_label_pending\">[[sentinel.status]]</span>\n                            <span ng-switch-default>[[sentinel.status_text]]</span>\n                        </td>\n                        <td ng-switch=\"sentinel.runid_error != ''\">\n                            <span ng-switch-when=\"true\" style=\"color: red\">[[sentinel.runid_error]]</span>\n                            <span ng-switch-default/>\n                        </td>\n                        <td class=\"button_tight_column\">\n                            <button class=\"btn btn-danger btn-xs active\"\n                                data-toggle=\"tooltip\" data-placement=\"right\" title=\"REMOVE SENTINEL [[sentinel.server]]\"\n                                ng-click=\"delSentinel(sentinel, false)\">\n                                <span class=\"glyphicon glyphicon-minus\"></span>\n                            </button>\n                        </td>\n                    </tr>\n                    </tbody>\n                </table>\n            </div>\n\n        </div>\n    </div>\n</div>\n\n<script src=\"node_modules/jquery/dist/jquery.js\"></script>\n<script src=\"node_modules/angular/angular.js\"></script>\n<script src=\"node_modules/bootstrap/dist/js/bootstrap.js\"></script>\n<script src=\"node_modules/angular-ui-bootstrap/ui-bootstrap-tpls.js\"></script>\n<script src=\"node_modules/highcharts/lib/highcharts.js\"></script>\n<script src=\"node_modules/highcharts/lib/highcharts-more.js\"></script>\n<script src=\"node_modules/highcharts-ng/dist/highcharts-ng.js\"></script>\n<script src=\"node_modules/bootstrap-dialog/src/js/bootstrap-dialog.js\"></script>\n<script src=\"node_modules/convert-string/convert-string.js\"></script>\n<script src=\"node_modules/convert-hex/convert-hex.js\"></script>\n<script src=\"node_modules/sha256/lib/sha256.js\"></script>\n<script src=\"dashboard-fe.js\"></script>\n</body>\n</html>\n"
  },
  {
    "path": "cmd/fe/assets/package.json",
    "content": "{\n  \"dependencies\": {\n    \"angular\": \"^1.4.8\",\n    \"angular-ui-bootstrap\": \"^0.14.3\",\n    \"bootstrap\": \"^3.3.6\",\n    \"bootstrap-dialog\": \"^1.34.6\",\n    \"highcharts\": \"^4.1.10\",\n    \"highcharts-ng\": \"0.0.11\",\n    \"jquery\": \"^2.1.4\",\n    \"sha256\": \"^0.2.0\"\n  }\n}\n"
  },
  {
    "path": "cmd/fe/main.go",
    "content": "// Copyright 2016 CodisLabs. All Rights Reserved.\n// Licensed under the MIT (MIT-LICENSE.txt) license.\n\npackage main\n\nimport (\n\t\"encoding/json\"\n\t\"fmt\"\n\t\"io/ioutil\"\n\t\"net\"\n\t\"net/http\"\n\t\"net/http/httputil\"\n\t\"net/url\"\n\t\"os\"\n\t\"path/filepath\"\n\t\"runtime\"\n\t\"sort\"\n\t\"strconv\"\n\t\"sync\"\n\t\"time\"\n\n\t\"github.com/docopt/docopt-go\"\n\t\"github.com/go-martini/martini\"\n\t\"github.com/martini-contrib/render\"\n\n\t\"github.com/CodisLabs/codis/pkg/models\"\n\t\"github.com/CodisLabs/codis/pkg/utils\"\n\t\"github.com/CodisLabs/codis/pkg/utils/errors\"\n\t\"github.com/CodisLabs/codis/pkg/utils/log\"\n\t\"github.com/CodisLabs/codis/pkg/utils/rpc\"\n\t\"github.com/CodisLabs/codis/pkg/utils/sync2/atomic2\"\n)\n\nvar roundTripper http.RoundTripper\n\nfunc init() {\n\tvar dials atomic2.Int64\n\ttr := &http.Transport{}\n\ttr.Dial = func(network, addr string) (net.Conn, error) {\n\t\tc, err := net.DialTimeout(network, addr, time.Second*10)\n\t\tif err == nil {\n\t\t\tlog.Debugf(\"rpc: dial new connection to [%d] %s - %s\",\n\t\t\t\tdials.Incr()-1, network, addr)\n\t\t}\n\t\treturn c, err\n\t}\n\tgo func() {\n\t\tfor {\n\t\t\ttime.Sleep(time.Minute)\n\t\t\ttr.CloseIdleConnections()\n\t\t}\n\t}()\n\troundTripper = tr\n}\n\nfunc main() {\n\tconst usage = `\nUsage:\n\tcodis-fe [--ncpu=N] [--log=FILE] [--log-level=LEVEL] [--assets-dir=PATH] [--pidfile=FILE] (--dashboard-list=FILE|--zookeeper=ADDR [--zookeeper-auth=USR:PWD]|--etcd=ADDR [--etcd-auth=USR:PWD]|--filesystem=ROOT) --listen=ADDR\n\tcodis-fe  --version\n\nOptions:\n\t--ncpu=N                        set runtime.GOMAXPROCS to N, default is runtime.NumCPU().\n\t-d FILE, --dashboard-list=FILE  set list of dashboard, can be generated by codis-admin.\n\t-l FILE, --log=FILE             set path/name of daliy rotated log file.\n\t--log-level=LEVEL               set the log-level, should be INFO,WARN,DEBUG or ERROR, default is INFO.\n\t--listen=ADDR                   set the listen address.\n`\n\td, err := docopt.Parse(usage, nil, true, \"\", false)\n\tif err != nil {\n\t\tlog.PanicError(err, \"parse arguments failed\")\n\t}\n\n\tif d[\"--version\"].(bool) {\n\t\tfmt.Println(\"version:\", utils.Version)\n\t\tfmt.Println(\"compile:\", utils.Compile)\n\t\treturn\n\t}\n\n\tif s, ok := utils.Argument(d, \"--log\"); ok {\n\t\tw, err := log.NewRollingFile(s, log.DailyRolling)\n\t\tif err != nil {\n\t\t\tlog.PanicErrorf(err, \"open log file %s failed\", s)\n\t\t} else {\n\t\t\tlog.StdLog = log.New(w, \"\")\n\t\t}\n\t}\n\tlog.SetLevel(log.LevelInfo)\n\n\tif s, ok := utils.Argument(d, \"--log-level\"); ok {\n\t\tif !log.SetLevelString(s) {\n\t\t\tlog.Panicf(\"option --log-level = %s\", s)\n\t\t}\n\t}\n\n\tif n, ok := utils.ArgumentInteger(d, \"--ncpu\"); ok {\n\t\truntime.GOMAXPROCS(n)\n\t} else {\n\t\truntime.GOMAXPROCS(runtime.NumCPU())\n\t}\n\tlog.Warnf(\"set ncpu = %d\", runtime.GOMAXPROCS(0))\n\n\tlisten := utils.ArgumentMust(d, \"--listen\")\n\tlog.Warnf(\"set listen = %s\", listen)\n\n\tvar assets string\n\tif s, ok := utils.Argument(d, \"--assets-dir\"); ok {\n\t\tabspath, err := filepath.Abs(s)\n\t\tif err != nil {\n\t\t\tlog.PanicErrorf(err, \"get absolute path of %s failed\", s)\n\t\t}\n\t\tassets = abspath\n\t} else {\n\t\tbinpath, err := filepath.Abs(filepath.Dir(os.Args[0]))\n\t\tif err != nil {\n\t\t\tlog.PanicErrorf(err, \"get path of binary failed\")\n\t\t}\n\t\tassets = filepath.Join(binpath, \"assets\")\n\t}\n\tlog.Warnf(\"set assets = %s\", assets)\n\n\tindexFile := filepath.Join(assets, \"index.html\")\n\tif _, err := os.Stat(indexFile); err != nil {\n\t\tlog.PanicErrorf(err, \"get stat of %s failed\", indexFile)\n\t}\n\n\tvar loader ConfigLoader\n\tif d[\"--dashboard-list\"] != nil {\n\t\tfile := utils.ArgumentMust(d, \"--dashboard-list\")\n\t\tloader = &StaticLoader{file}\n\t\tlog.Warnf(\"set --dashboard-list = %s\", file)\n\t} else {\n\t\tvar coordinator struct {\n\t\t\tname string\n\t\t\taddr string\n\t\t\tauth string\n\t\t}\n\n\t\tswitch {\n\t\tcase d[\"--zookeeper\"] != nil:\n\t\t\tcoordinator.name = \"zookeeper\"\n\t\t\tcoordinator.addr = utils.ArgumentMust(d, \"--zookeeper\")\n\t\t\tif d[\"--zookeeper-auth\"] != nil {\n\t\t\t\tcoordinator.auth = utils.ArgumentMust(d, \"--zookeeper-auth\")\n\t\t\t}\n\n\t\tcase d[\"--etcd\"] != nil:\n\t\t\tcoordinator.name = \"etcd\"\n\t\t\tcoordinator.addr = utils.ArgumentMust(d, \"--etcd\")\n\t\t\tif d[\"--etcd-auth\"] != nil {\n\t\t\t\tcoordinator.auth = utils.ArgumentMust(d, \"--etcd-auth\")\n\t\t\t}\n\n\t\tcase d[\"--filesystem\"] != nil:\n\t\t\tcoordinator.name = \"filesystem\"\n\t\t\tcoordinator.addr = utils.ArgumentMust(d, \"--filesystem\")\n\n\t\tdefault:\n\t\t\tlog.Panicf(\"invalid coordinator\")\n\t\t}\n\n\t\tlog.Warnf(\"set --%s = %s\", coordinator.name, coordinator.addr)\n\n\t\tc, err := models.NewClient(coordinator.name, coordinator.addr, coordinator.auth, time.Minute)\n\t\tif err != nil {\n\t\t\tlog.PanicErrorf(err, \"create '%s' client to '%s' failed\", coordinator.name, coordinator.addr)\n\t\t}\n\t\tdefer c.Close()\n\n\t\tloader = &DynamicLoader{c}\n\t}\n\n\trouter := NewReverseProxy(loader)\n\n\tm := martini.New()\n\tm.Use(martini.Recovery())\n\tm.Use(render.Renderer())\n\tm.Use(martini.Static(assets, martini.StaticOptions{SkipLogging: true}))\n\n\tr := martini.NewRouter()\n\tr.Get(\"/list\", func() (int, string) {\n\t\tnames := router.GetNames()\n\t\tsort.Sort(sort.StringSlice(names))\n\t\treturn rpc.ApiResponseJson(names)\n\t})\n\n\tr.Any(\"/**\", func(w http.ResponseWriter, req *http.Request) {\n\t\tname := req.URL.Query().Get(\"forward\")\n\t\tif p := router.GetProxy(name); p != nil {\n\t\t\tp.ServeHTTP(w, req)\n\t\t} else {\n\t\t\tw.WriteHeader(http.StatusForbidden)\n\t\t}\n\t})\n\n\tm.MapTo(r, (*martini.Routes)(nil))\n\tm.Action(r.Handle)\n\n\tl, err := net.Listen(\"tcp\", listen)\n\tif err != nil {\n\t\tlog.PanicErrorf(err, \"listen %s failed\", listen)\n\t}\n\tdefer l.Close()\n\n\tif s, ok := utils.Argument(d, \"--pidfile\"); ok {\n\t\tif pidfile, err := filepath.Abs(s); err != nil {\n\t\t\tlog.WarnErrorf(err, \"parse pidfile = '%s' failed\", s)\n\t\t} else if err := ioutil.WriteFile(pidfile, []byte(strconv.Itoa(os.Getpid())), 0644); err != nil {\n\t\t\tlog.WarnErrorf(err, \"write pidfile = '%s' failed\", pidfile)\n\t\t} else {\n\t\t\tdefer func() {\n\t\t\t\tif err := os.Remove(pidfile); err != nil {\n\t\t\t\t\tlog.WarnErrorf(err, \"remove pidfile = '%s' failed\", pidfile)\n\t\t\t\t}\n\t\t\t}()\n\t\t\tlog.Warnf(\"option --pidfile = %s\", pidfile)\n\t\t}\n\t}\n\n\th := http.NewServeMux()\n\th.Handle(\"/\", m)\n\ths := &http.Server{Handler: h}\n\tif err := hs.Serve(l); err != nil {\n\t\tlog.PanicErrorf(err, \"serve %s failed\", listen)\n\t}\n}\n\ntype ConfigLoader interface {\n\tReload() (map[string]string, error)\n}\n\ntype StaticLoader struct {\n\tpath string\n}\n\nfunc (l *StaticLoader) Reload() (map[string]string, error) {\n\tb, err := ioutil.ReadFile(l.path)\n\tif err != nil {\n\t\treturn nil, errors.Trace(err)\n\t}\n\tvar list []*struct {\n\t\tName      string `json:\"name\"`\n\t\tDashboard string `json:\"dashboard\"`\n\t}\n\tif err := json.Unmarshal(b, &list); err != nil {\n\t\treturn nil, errors.Trace(err)\n\t}\n\tvar m = make(map[string]string)\n\tfor _, e := range list {\n\t\tm[e.Name] = e.Dashboard\n\t}\n\treturn m, nil\n}\n\ntype DynamicLoader struct {\n\tclient models.Client\n}\n\nfunc (l *DynamicLoader) Reload() (map[string]string, error) {\n\tvar m = make(map[string]string)\n\tlist, err := l.client.List(models.CodisDir, false)\n\tif err != nil {\n\t\treturn nil, errors.Trace(err)\n\t}\n\tfor _, path := range list {\n\t\tproduct := filepath.Base(path)\n\t\tif b, err := l.client.Read(models.LockPath(product), false); err != nil {\n\t\t\tlog.WarnErrorf(err, \"read topom of product %s failed\", product)\n\t\t} else if b != nil {\n\t\t\tvar t = &models.Topom{}\n\t\t\tif err := json.Unmarshal(b, t); err != nil {\n\t\t\t\tlog.WarnErrorf(err, \"decode json failed\")\n\t\t\t} else {\n\t\t\t\tm[product] = t.AdminAddr\n\t\t\t}\n\t\t}\n\t}\n\treturn m, nil\n}\n\ntype ReverseProxy struct {\n\tsync.Mutex\n\tloadAt time.Time\n\tloader ConfigLoader\n\troutes map[string]*httputil.ReverseProxy\n}\n\nfunc NewReverseProxy(loader ConfigLoader) *ReverseProxy {\n\tr := &ReverseProxy{}\n\tr.loader = loader\n\tr.routes = make(map[string]*httputil.ReverseProxy)\n\treturn r\n}\n\nfunc (r *ReverseProxy) reload(d time.Duration) {\n\tif time.Now().Sub(r.loadAt) < d {\n\t\treturn\n\t}\n\tr.routes = make(map[string]*httputil.ReverseProxy)\n\tif m, err := r.loader.Reload(); err != nil {\n\t\tlog.WarnErrorf(err, \"reload reverse proxy failed\")\n\t} else {\n\t\tfor name, host := range m {\n\t\t\tif name == \"\" || host == \"\" {\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tu := &url.URL{Scheme: \"http\", Host: host}\n\t\t\tp := httputil.NewSingleHostReverseProxy(u)\n\t\t\tp.Transport = roundTripper\n\t\t\tr.routes[name] = p\n\t\t}\n\t}\n\tr.loadAt = time.Now()\n}\n\nfunc (r *ReverseProxy) GetProxy(name string) *httputil.ReverseProxy {\n\tr.Lock()\n\tdefer r.Unlock()\n\treturn r.routes[name]\n}\n\nfunc (r *ReverseProxy) GetNames() []string {\n\tr.Lock()\n\tdefer r.Unlock()\n\tr.reload(time.Second * 5)\n\tvar names []string\n\tfor name, _ := range r.routes {\n\t\tnames = append(names, name)\n\t}\n\treturn names\n}\n"
  },
  {
    "path": "cmd/ha/main.go",
    "content": "// Copyright 2016 CodisLabs. All Rights Reserved.\n// Licensed under the MIT (MIT-LICENSE.txt) license.\n\npackage main\n\nimport (\n\t\"fmt\"\n\t\"strconv\"\n\t\"time\"\n\n\t\"github.com/docopt/docopt-go\"\n\n\t\"github.com/CodisLabs/codis/pkg/topom\"\n\t\"github.com/CodisLabs/codis/pkg/utils\"\n\t\"github.com/CodisLabs/codis/pkg/utils/log\"\n\t\"github.com/CodisLabs/codis/pkg/utils/math2\"\n\t\"github.com/CodisLabs/codis/pkg/utils/redis\"\n)\n\nfunc main() {\n\tconst usage = `\nUsage:\n\tcodis-ha [--log=FILE] [--log-level=LEVEL] [--interval=SECONDS] --dashboard=ADDR [--no-maintains]\n\tcodis-ha  --version\n\nOptions:\n\t-l FILE, --log=FILE         set path/name of daliy rotated log file.\n\t--log-level=LEVEL           set the log-level, should be INFO,WARN,DEBUG or ERROR, default is INFO.\n`\n\td, err := docopt.Parse(usage, nil, true, \"\", false)\n\tif err != nil {\n\t\tlog.PanicError(err, \"parse arguments failed\")\n\t}\n\n\tif d[\"--version\"].(bool) {\n\t\tfmt.Println(\"version:\", utils.Version)\n\t\tfmt.Println(\"compile:\", utils.Compile)\n\t\treturn\n\t}\n\n\tif s, ok := utils.Argument(d, \"--log\"); ok {\n\t\tw, err := log.NewRollingFile(s, log.DailyRolling)\n\t\tif err != nil {\n\t\t\tlog.PanicErrorf(err, \"open log file %s failed\", s)\n\t\t} else {\n\t\t\tlog.StdLog = log.New(w, \"\")\n\t\t}\n\t}\n\tlog.SetLevel(log.LevelInfo)\n\n\tif s, ok := utils.Argument(d, \"--log-level\"); ok {\n\t\tif !log.SetLevelString(s) {\n\t\t\tlog.Panicf(\"option --log-level = %s\", s)\n\t\t}\n\t}\n\n\tvar interval = 5\n\tif n, ok := utils.ArgumentInteger(d, \"--interval\"); ok {\n\t\tif n <= 0 {\n\t\t\tlog.Panicf(\"option --interval = %d\", n)\n\t\t}\n\t\tinterval = n\n\t}\n\n\tdashboard := utils.ArgumentMust(d, \"--dashboard\")\n\tlog.Warnf(\"set dashboard = %s\", dashboard)\n\tlog.Warnf(\"set interval = %d (seconds)\", interval)\n\n\tvar maintains = true\n\tif d[\"--no-maintains\"].(bool) {\n\t\tmaintains = false\n\t}\n\n\tclient := topom.NewApiClient(dashboard)\n\n\tt, err := client.Model()\n\tif err != nil {\n\t\tlog.PanicErrorf(err, \"rpc fetch model failed\")\n\t}\n\tlog.Warnf(\"topom =\\n%s\", t.Encode())\n\n\tclient.SetXAuth(t.ProductName)\n\n\toverview, err := client.Overview()\n\tif err != nil {\n\t\tlog.PanicErrorf(err, \"rpc fetch overview failed\")\n\t}\n\tprodcutAuth := overview.Config.ProductAuth\n\n\tfor {\n\t\thc := newHealthyChecker(client)\n\t\thc.LogProxyStats()\n\t\thc.LogGroupStats()\n\t\tif maintains {\n\t\t\thc.Maintains(client, interval*10, prodcutAuth)\n\t\t}\n\n\t\ttime.Sleep(time.Second * time.Duration(interval))\n\t}\n}\n\nconst (\n\tCodeAlive = iota + 100\n\tCodeError\n\tCodeMissing\n\tCodeTimeout\n)\n\nconst (\n\tCodeSyncReady = iota + 200\n\tCodeSyncError\n\tCodeSyncBroken\n)\n\ntype HealthyChecker struct {\n\t*topom.Stats\n\tpstatus map[string]int\n\tsstatus map[string]int\n}\n\nfunc newHealthyChecker(client *topom.ApiClient) *HealthyChecker {\n\tstats, err := client.Stats()\n\tif err != nil {\n\t\tlog.PanicErrorf(err, \"rpc stats failed\")\n\t}\n\n\thc := &HealthyChecker{Stats: stats}\n\n\thc.pstatus = make(map[string]int)\n\tfor _, p := range hc.Proxy.Models {\n\t\tswitch stats := hc.Proxy.Stats[p.Token]; {\n\t\tcase stats == nil:\n\t\t\thc.pstatus[p.Token] = CodeMissing\n\t\tcase stats.Error != nil:\n\t\t\thc.pstatus[p.Token] = CodeError\n\t\tcase stats.Timeout || stats.Stats == nil:\n\t\t\thc.pstatus[p.Token] = CodeTimeout\n\t\tdefault:\n\t\t\thc.pstatus[p.Token] = CodeAlive\n\t\t}\n\t}\n\n\thc.sstatus = make(map[string]int)\n\tfor _, g := range hc.Group.Models {\n\t\tfor i, x := range g.Servers {\n\t\t\tvar addr = x.Addr\n\t\t\tswitch stats := hc.Group.Stats[addr]; {\n\t\t\tcase stats == nil:\n\t\t\t\thc.sstatus[addr] = CodeMissing\n\t\t\tcase stats.Error != nil:\n\t\t\t\thc.sstatus[addr] = CodeError\n\t\t\tcase stats.Timeout || stats.Stats == nil:\n\t\t\t\thc.sstatus[addr] = CodeTimeout\n\t\t\tdefault:\n\t\t\t\tif i == 0 {\n\t\t\t\t\tif stats.Stats[\"master_addr\"] != \"\" {\n\t\t\t\t\t\thc.sstatus[addr] = CodeSyncError\n\t\t\t\t\t} else {\n\t\t\t\t\t\thc.sstatus[addr] = CodeSyncReady\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\tif stats.Stats[\"master_addr\"] != g.Servers[0].Addr {\n\t\t\t\t\t\thc.sstatus[addr] = CodeSyncError\n\t\t\t\t\t} else {\n\t\t\t\t\t\tswitch stats.Stats[\"master_link_status\"] {\n\t\t\t\t\t\tdefault:\n\t\t\t\t\t\t\thc.sstatus[addr] = CodeSyncError\n\t\t\t\t\t\tcase \"up\":\n\t\t\t\t\t\t\thc.sstatus[addr] = CodeSyncReady\n\t\t\t\t\t\tcase \"down\":\n\t\t\t\t\t\t\thc.sstatus[addr] = CodeSyncBroken\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\treturn hc\n}\n\nfunc (hc *HealthyChecker) LogProxyStats() {\n\tvar format string\n\tvar wpid int\n\tfor _, p := range hc.Proxy.Models {\n\t\twpid = math2.MaxInt(wpid, len(strconv.Itoa(p.Id)))\n\t}\n\tformat += fmt.Sprintf(\"proxy-%%0%dd [T] %%s\", wpid)\n\n\tvar waddr1, waddr2 int\n\tfor _, p := range hc.Proxy.Models {\n\t\twaddr1 = math2.MaxInt(waddr1, len(p.AdminAddr))\n\t\twaddr2 = math2.MaxInt(waddr2, len(p.ProxyAddr))\n\t}\n\tformat += fmt.Sprintf(\" [A] %%-%ds\", waddr1)\n\tformat += fmt.Sprintf(\" [P] %%-%ds\", waddr2)\n\n\tfor _, p := range hc.Proxy.Models {\n\t\tswitch hc.pstatus[p.Token] {\n\t\tcase CodeMissing:\n\t\t\tlog.Warnf(\"[?] \"+format, p.Id, p.Token, p.AdminAddr, p.ProxyAddr)\n\t\tcase CodeError:\n\t\t\tlog.Warnf(\"[E] \"+format, p.Id, p.Token, p.AdminAddr, p.ProxyAddr)\n\t\tcase CodeTimeout:\n\t\t\tlog.Warnf(\"[T] \"+format, p.Id, p.Token, p.AdminAddr, p.ProxyAddr)\n\t\tdefault:\n\t\t\tlog.Infof(\"[ ] \"+format, p.Id, p.Token, p.AdminAddr, p.ProxyAddr)\n\t\t}\n\t}\n}\n\nfunc (hc *HealthyChecker) LogGroupStats() {\n\tvar format string\n\tvar wgid, widx int\n\tfor _, g := range hc.Group.Models {\n\t\twgid = math2.MaxInt(wgid, len(strconv.Itoa(g.Id)))\n\t\tfor i, _ := range g.Servers {\n\t\t\twidx = math2.MaxInt(widx, len(strconv.Itoa(i)))\n\t\t}\n\t}\n\tformat += fmt.Sprintf(\"group-%%0%dd [%%0%dd]\", wgid, widx)\n\n\tvar waddr int\n\tfor _, g := range hc.Group.Models {\n\t\tfor _, x := range g.Servers {\n\t\t\twaddr = math2.MaxInt(waddr, len(x.Addr))\n\t\t}\n\t}\n\tformat += fmt.Sprintf(\" %%-%ds\", waddr)\n\n\tfor _, g := range hc.Group.Models {\n\t\tfor i, x := range g.Servers {\n\t\t\tswitch hc.sstatus[x.Addr] {\n\t\t\tcase CodeMissing:\n\t\t\t\tlog.Warnf(\"[?] \"+format, g.Id, i, x.Addr)\n\t\t\tcase CodeError:\n\t\t\t\tlog.Warnf(\"[E] \"+format, g.Id, i, x.Addr)\n\t\t\tcase CodeTimeout:\n\t\t\t\tlog.Warnf(\"[T] \"+format, g.Id, i, x.Addr)\n\t\t\tcase CodeSyncReady:\n\t\t\t\tlog.Infof(\"[ ] \"+format, g.Id, i, x.Addr)\n\t\t\tcase CodeSyncError, CodeSyncBroken:\n\t\t\t\tlog.Warnf(\"[X] \"+format, g.Id, i, x.Addr)\n\t\t\t}\n\t\t}\n\t}\n}\n\nfunc (hc *HealthyChecker) Maintains(client *topom.ApiClient, maxdown int, auth string) {\n\t// remove proxy at state error from codis\n\tfor _, p := range hc.Proxy.Models {\n\t\tswitch hc.pstatus[p.Token] {\n\t\tcase CodeError, CodeTimeout, CodeMissing:\n\t\t\tlog.Warnf(\"try to remove proxy-[%s]\", p.AdminAddr)\n\t\t\tif err := client.RemoveProxy(p.Token, true); err != nil {\n\t\t\t\tlog.ErrorErrorf(err, \"call rpc remove-proxy to dashboard %s failed\", p.AdminAddr)\n\t\t\t\treturn\n\t\t\t}\n\t\t\tlog.Warnf(\"try to remove proxy done.\")\n\t\t\treturn\n\t\tdefault:\n\t\t\tcontinue\n\t\t}\n\t}\n\n\t// remove server at state error from codis\nGroups:\n\tfor _, g := range hc.Group.Models {\n\t\tfor i, x := range g.Servers {\n\t\t\t// if master state is not right, promote slave to master first(if have slave)\n\t\t\tif i == 0 {\n\t\t\t\tif len(g.Servers) > 1 {\n\t\t\t\t\tswitch hc.sstatus[g.Servers[0].Addr] {\n\t\t\t\t\tcase CodeError, CodeMissing, CodeTimeout, CodeSyncError:\n\t\t\t\t\t\tlog.Warnf(\"codis-server (master) %s state error\", x.Addr)\n\t\t\t\t\t\tbreak Groups\n\t\t\t\t\tdefault:\n\t\t\t\t\t\tcontinue\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\tcontinue\n\t\t\t\t}\n\t\t\t}\n\t\t\t// remove codis server(slave and only one master) which state is not right\n\t\t\tswitch hc.sstatus[x.Addr] {\n\t\t\tcase CodeError, CodeMissing, CodeTimeout, CodeSyncError:\n\t\t\t\tlog.Warnf(\"try to group-del-server to dashboard %s\", x.Addr)\n\t\t\t\tif err := client.GroupDelServer(g.Id, x.Addr); err != nil {\n\t\t\t\t\tlog.ErrorErrorf(err, \"call rpc group-del-server to dashboard %s failed\", x.Addr)\n\t\t\t\t\treturn\n\t\t\t\t}\n\t\t\t\tlog.Debugf(\"call rpc group-del-server OK\")\n\n\t\t\t\t// trt to shutdown codis-server as slave in error state\n\t\t\t\tlog.Warnf(\"try to shutdown codis-server(slave) %s\", x.Addr)\n\t\t\t\tc, err := redis.NewClient(x.Addr, auth, time.Minute*30)\n\t\t\t\tif err != nil {\n\t\t\t\t\tlog.WarnErrorf(err, \"connect to codis-server(slave) %s failed\", x.Addr)\n\t\t\t\t\treturn\n\t\t\t\t}\n\t\t\t\tdefer c.Close()\n\t\t\t\tif err := c.Shutdown(); err != nil {\n\t\t\t\t\tlog.WarnErrorf(err, \"try to shutdown codis-server %s failed\", x.Addr)\n\t\t\t\t\treturn\n\t\t\t\t}\n\t\t\t\treturn\n\t\t\tcase CodeSyncBroken:\n\t\t\t\tlog.Warnf(\"slave %s master link down\", x.Addr)\n\t\t\tdefault:\n\t\t\t\tcontinue\n\t\t\t}\n\t\t}\n\t}\n\n\t// promote group server\n\tfor _, g := range hc.Group.Models {\n\t\tif len(g.Servers) != 0 {\n\t\t\tswitch hc.sstatus[g.Servers[0].Addr] {\n\t\t\tcase CodeMissing, CodeError, CodeTimeout:\n\t\t\t\tvar synced int\n\t\t\t\tvar picked, picked2 = 0, 0\n\t\t\t\tvar mindown, mindown2 = maxdown + 1, 65535\n\t\t\t\tfor i := 1; i < len(g.Servers); i++ {\n\t\t\t\t\tvar addr = g.Servers[i].Addr\n\t\t\t\t\tswitch hc.sstatus[addr] {\n\t\t\t\t\tcase CodeSyncReady:\n\t\t\t\t\t\tsynced++\n\t\t\t\t\tcase CodeSyncBroken:\n\t\t\t\t\t\tif stats := hc.Group.Stats[addr]; stats != nil && stats.Stats != nil {\n\t\t\t\t\t\t\tn, err := strconv.Atoi(stats.Stats[\"master_link_down_since_seconds\"])\n\t\t\t\t\t\t\tif err != nil {\n\t\t\t\t\t\t\t\tlog.WarnErrorf(err, \"try to get %s master_link_down_since_seconds failed\", addr)\n\t\t\t\t\t\t\t\tcontinue\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tif n >= 0 && n < mindown {\n\t\t\t\t\t\t\t\tpicked, mindown = i, n\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tif picked == 0 && n >= 0 && n < mindown2 {\n\t\t\t\t\t\t\t\tpicked2, mindown2 = i, n\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\tcase CodeSyncError:\n\t\t\t\t\t\tif picked == 0 && picked2 == 0 {\n\t\t\t\t\t\t\tpicked2 = i\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tswitch {\n\t\t\t\tcase picked == 0 && picked2 == 0:\n\t\t\t\t\tlog.Warnf(\"try to promote group-[%d], but synced = %d & picked = %d & picked2 = %d, giveup\", g.Id, synced, picked, picked2)\n\t\t\t\tcase g.Promoting.State != \"\":\n\t\t\t\t\tlog.Warnf(\"try to promote group-[%d], but group is promoting = %s, please fix it manually\", g.Id, g.Promoting.State)\n\t\t\t\tcase picked > 0 || picked2 > 0:\n\t\t\t\t\tvar pick int\n\t\t\t\t\tif picked > 0 {\n\t\t\t\t\t\tpick = picked\n\t\t\t\t\t} else {\n\t\t\t\t\t\tpick = picked2\n\t\t\t\t\t}\n\t\t\t\t\tvar slave = g.Servers[pick].Addr\n\t\t\t\t\tlog.Warnf(\"try to promote group-[%d] with slave %s\", g.Id, slave)\n\t\t\t\t\tif err := client.GroupPromoteServer(g.Id, slave); err != nil {\n\t\t\t\t\t\tlog.ErrorErrorf(err, \"rpc promote server failed\")\n\t\t\t\t\t}\n\t\t\t\t\tlog.Warnf(\"done.\")\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "cmd/proxy/main.go",
    "content": "// Copyright 2016 CodisLabs. All Rights Reserved.\n// Licensed under the MIT (MIT-LICENSE.txt) license.\n\npackage main\n\nimport (\n\t\"bytes\"\n\t\"encoding/json\"\n\t\"fmt\"\n\t\"io/ioutil\"\n\t\"os\"\n\t\"os/exec\"\n\t\"os/signal\"\n\t\"path/filepath\"\n\t\"runtime\"\n\t\"strconv\"\n\t\"strings\"\n\t\"syscall\"\n\t\"time\"\n\n\t\"github.com/docopt/docopt-go\"\n\n\t\"github.com/CodisLabs/codis/pkg/models\"\n\t\"github.com/CodisLabs/codis/pkg/proxy\"\n\t\"github.com/CodisLabs/codis/pkg/topom\"\n\t\"github.com/CodisLabs/codis/pkg/utils\"\n\t\"github.com/CodisLabs/codis/pkg/utils/log\"\n\t\"github.com/CodisLabs/codis/pkg/utils/math2\"\n)\n\nfunc main() {\n\tconst usage = `\nUsage:\n\tcodis-proxy [--ncpu=N [--max-ncpu=MAX]] [--config=CONF] [--log=FILE] [--log-level=LEVEL] [--host-admin=ADDR] [--host-proxy=ADDR] [--dashboard=ADDR|--zookeeper=ADDR [--zookeeper-auth=USR:PWD]|--etcd=ADDR [--etcd-auth=USR:PWD]|--filesystem=ROOT|--fillslots=FILE] [--ulimit=NLIMIT] [--pidfile=FILE] [--product_name=NAME] [--product_auth=AUTH] [--session_auth=AUTH]\n\tcodis-proxy  --default-config\n\tcodis-proxy  --version\n\nOptions:\n\t--ncpu=N                    set runtime.GOMAXPROCS to N, default is runtime.NumCPU().\n\t-c CONF, --config=CONF      run with the specific configuration.\n\t-l FILE, --log=FILE         set path/name of daliy rotated log file.\n\t--log-level=LEVEL           set the log-level, should be INFO,WARN,DEBUG or ERROR, default is INFO.\n\t--ulimit=NLIMIT             run 'ulimit -n' to check the maximum number of open file descriptors.\n`\n\n\td, err := docopt.Parse(usage, nil, true, \"\", false)\n\tif err != nil {\n\t\tlog.PanicError(err, \"parse arguments failed\")\n\t}\n\n\tswitch {\n\n\tcase d[\"--default-config\"]:\n\t\tfmt.Println(proxy.DefaultConfig)\n\t\treturn\n\n\tcase d[\"--version\"].(bool):\n\t\tfmt.Println(\"version:\", utils.Version)\n\t\tfmt.Println(\"compile:\", utils.Compile)\n\t\treturn\n\n\t}\n\n\tif s, ok := utils.Argument(d, \"--log\"); ok {\n\t\tw, err := log.NewRollingFile(s, log.DailyRolling)\n\t\tif err != nil {\n\t\t\tlog.PanicErrorf(err, \"open log file %s failed\", s)\n\t\t} else {\n\t\t\tlog.StdLog = log.New(w, \"\")\n\t\t}\n\t}\n\tlog.SetLevel(log.LevelInfo)\n\n\tif s, ok := utils.Argument(d, \"--log-level\"); ok {\n\t\tif !log.SetLevelString(s) {\n\t\t\tlog.Panicf(\"option --log-level = %s\", s)\n\t\t}\n\t}\n\n\tif n, ok := utils.ArgumentInteger(d, \"--ulimit\"); ok {\n\t\tb, err := exec.Command(\"/bin/sh\", \"-c\", \"ulimit -n\").Output()\n\t\tif err != nil {\n\t\t\tlog.PanicErrorf(err, \"run ulimit -n failed\")\n\t\t}\n\t\tif v, err := strconv.Atoi(strings.TrimSpace(string(b))); err != nil || v < n {\n\t\t\tlog.PanicErrorf(err, \"ulimit too small: %d, should be at least %d\", v, n)\n\t\t}\n\t}\n\n\tvar ncpu int\n\tif n, ok := utils.ArgumentInteger(d, \"--ncpu\"); ok {\n\t\tncpu = n\n\t} else {\n\t\tncpu = 4\n\t}\n\truntime.GOMAXPROCS(ncpu)\n\n\tvar maxncpu int\n\tif n, ok := utils.ArgumentInteger(d, \"--max-ncpu\"); ok {\n\t\tmaxncpu = math2.MaxInt(ncpu, n)\n\t} else {\n\t\tmaxncpu = math2.MaxInt(ncpu, runtime.NumCPU())\n\t}\n\tlog.Warnf(\"set ncpu = %d, max-ncpu = %d\", ncpu, maxncpu)\n\n\tif ncpu < maxncpu {\n\t\tgo AutoGOMAXPROCS(ncpu, maxncpu)\n\t}\n\n\tconfig := proxy.NewDefaultConfig()\n\tif s, ok := utils.Argument(d, \"--config\"); ok {\n\t\tif err := config.LoadFromFile(s); err != nil {\n\t\t\tlog.PanicErrorf(err, \"load config %s failed\", s)\n\t\t}\n\t}\n\tif s, ok := utils.Argument(d, \"--host-admin\"); ok {\n\t\tconfig.HostAdmin = s\n\t\tlog.Warnf(\"option --host-admin = %s\", s)\n\t}\n\tif s, ok := utils.Argument(d, \"--host-proxy\"); ok {\n\t\tconfig.HostProxy = s\n\t\tlog.Warnf(\"option --host-proxy = %s\", s)\n\t}\n\n\tvar dashboard string\n\tif s, ok := utils.Argument(d, \"--dashboard\"); ok {\n\t\tdashboard = s\n\t\tlog.Warnf(\"option --dashboard = %s\", s)\n\t}\n\n\tvar coordinator struct {\n\t\tname string\n\t\taddr string\n\t\tauth string\n\t}\n\n\tswitch {\n\n\tcase d[\"--zookeeper\"] != nil:\n\t\tcoordinator.name = \"zookeeper\"\n\t\tcoordinator.addr = utils.ArgumentMust(d, \"--zookeeper\")\n\t\tif d[\"--zookeeper-auth\"] != nil {\n\t\t\tcoordinator.auth = utils.ArgumentMust(d, \"--zookeeper-auth\")\n\t\t}\n\n\tcase d[\"--etcd\"] != nil:\n\t\tcoordinator.name = \"etcd\"\n\t\tcoordinator.addr = utils.ArgumentMust(d, \"--etcd\")\n\t\tif d[\"--etcd-auth\"] != nil {\n\t\t\tcoordinator.auth = utils.ArgumentMust(d, \"--etcd-auth\")\n\t\t}\n\n\tcase d[\"--filesystem\"] != nil:\n\t\tcoordinator.name = \"filesystem\"\n\t\tcoordinator.addr = utils.ArgumentMust(d, \"--filesystem\")\n\n\t}\n\n\tif coordinator.name != \"\" {\n\t\tlog.Warnf(\"option --%s = %s\", coordinator.name, coordinator.addr)\n\t}\n\n\tvar slots []*models.Slot\n\tif s, ok := utils.Argument(d, \"--fillslots\"); ok {\n\t\tb, err := ioutil.ReadFile(s)\n\t\tif err != nil {\n\t\t\tlog.PanicErrorf(err, \"load slots from file failed\")\n\t\t}\n\t\tif err := json.Unmarshal(b, &slots); err != nil {\n\t\t\tlog.PanicErrorf(err, \"decode slots from json failed\")\n\t\t}\n\t}\n\n\tif s, ok := utils.Argument(d, \"--product_name\"); ok {\n\t\tconfig.ProductName = s\n\t\tlog.Warnf(\"option --product_name = %s\", s)\n\t}\n\tif s, ok := utils.Argument(d, \"--product_auth\"); ok {\n\t\tconfig.ProductAuth = s\n\t\tlog.Warnf(\"option --product_auth = %s\", s)\n\t}\n\tif s, ok := utils.Argument(d, \"--session_auth\"); ok {\n\t\tconfig.SessionAuth = s\n\t\tlog.Warnf(\"option --session_auth = %s\", s)\n\t}\n\n\ts, err := proxy.New(config)\n\tif err != nil {\n\t\tlog.PanicErrorf(err, \"create proxy with config file failed\\n%s\", config)\n\t}\n\tdefer s.Close()\n\n\tlog.Warnf(\"create proxy with config\\n%s\", config)\n\n\tif s, ok := utils.Argument(d, \"--pidfile\"); ok {\n\t\tif pidfile, err := filepath.Abs(s); err != nil {\n\t\t\tlog.WarnErrorf(err, \"parse pidfile = '%s' failed\", s)\n\t\t} else if err := ioutil.WriteFile(pidfile, []byte(strconv.Itoa(os.Getpid())), 0644); err != nil {\n\t\t\tlog.WarnErrorf(err, \"write pidfile = '%s' failed\", pidfile)\n\t\t} else {\n\t\t\tdefer func() {\n\t\t\t\tif err := os.Remove(pidfile); err != nil {\n\t\t\t\t\tlog.WarnErrorf(err, \"remove pidfile = '%s' failed\", pidfile)\n\t\t\t\t}\n\t\t\t}()\n\t\t\tlog.Warnf(\"option --pidfile = %s\", pidfile)\n\t\t}\n\t}\n\n\tgo func() {\n\t\tdefer s.Close()\n\t\tc := make(chan os.Signal, 1)\n\t\tsignal.Notify(c, syscall.SIGINT, syscall.SIGKILL, syscall.SIGTERM)\n\n\t\tsig := <-c\n\t\tlog.Warnf(\"[%p] proxy receive signal = '%v'\", s, sig)\n\t}()\n\n\tswitch {\n\tcase dashboard != \"\":\n\t\tgo AutoOnlineWithDashboard(s, dashboard)\n\tcase coordinator.name != \"\":\n\t\tgo AutoOnlineWithCoordinator(s, coordinator.name, coordinator.addr, coordinator.auth)\n\tcase slots != nil:\n\t\tgo AutoOnlineWithFillSlots(s, slots)\n\t}\n\n\tfor !s.IsClosed() && !s.IsOnline() {\n\t\tlog.Warnf(\"[%p] proxy waiting online ...\", s)\n\t\ttime.Sleep(time.Second)\n\t}\n\n\tlog.Warnf(\"[%p] proxy is working ...\", s)\n\n\tfor !s.IsClosed() {\n\t\ttime.Sleep(time.Second)\n\t}\n\n\tlog.Warnf(\"[%p] proxy is exiting ...\", s)\n}\n\nfunc AutoGOMAXPROCS(min, max int) {\n\tfor {\n\t\tvar ncpu = runtime.GOMAXPROCS(0)\n\t\tvar less, more int\n\t\tvar usage [10]float64\n\t\tfor i := 0; i < len(usage) && more == 0; i++ {\n\t\t\tu, _, err := utils.CPUUsage(time.Second)\n\t\t\tif err != nil {\n\t\t\t\tlog.WarnErrorf(err, \"get cpu usage failed\")\n\t\t\t\ttime.Sleep(time.Second * 30)\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tu /= float64(ncpu)\n\t\t\tswitch {\n\t\t\tcase u < 0.30 && ncpu > min:\n\t\t\t\tless++\n\t\t\tcase u > 0.70 && ncpu < max:\n\t\t\t\tmore++\n\t\t\t}\n\t\t\tusage[i] = u\n\t\t}\n\t\tvar nn = ncpu\n\t\tswitch {\n\t\tcase more != 0:\n\t\t\tnn = ncpu + ((max - ncpu + 3) / 4)\n\t\tcase less == len(usage):\n\t\t\tnn = ncpu - 1\n\t\t}\n\t\tif nn != ncpu {\n\t\t\truntime.GOMAXPROCS(nn)\n\t\t\tvar b bytes.Buffer\n\t\t\tfor i, u := range usage {\n\t\t\t\tif i != 0 {\n\t\t\t\t\tfmt.Fprintf(&b, \", \")\n\t\t\t\t}\n\t\t\t\tfmt.Fprintf(&b, \"%.3f\", u)\n\t\t\t}\n\t\t\tlog.Warnf(\"ncpu = %d -> %d, usage = [%s]\", ncpu, nn, b.Bytes())\n\t\t}\n\t}\n}\n\nfunc AutoOnlineWithDashboard(p *proxy.Proxy, dashboard string) {\n\tfor i := 0; i < 10; i++ {\n\t\tif p.IsClosed() || p.IsOnline() {\n\t\t\treturn\n\t\t}\n\t\tif OnlineProxy(p, dashboard) {\n\t\t\treturn\n\t\t}\n\t\ttime.Sleep(time.Second * 3)\n\t}\n\tlog.Panicf(\"online proxy failed\")\n}\n\nfunc AutoOnlineWithCoordinator(p *proxy.Proxy, name, addr, auth string) {\n\tclient, err := models.NewClient(name, addr, auth, time.Minute)\n\tif err != nil {\n\t\tlog.PanicErrorf(err, \"create '%s' client to '%s' failed\", name, addr)\n\t}\n\tdefer client.Close()\n\tfor i := 0; i < 30; i++ {\n\t\tif p.IsClosed() || p.IsOnline() {\n\t\t\treturn\n\t\t}\n\t\tt, err := models.LoadTopom(client, p.Config().ProductName, false)\n\t\tif err != nil {\n\t\t\tlog.WarnErrorf(err, \"load & decode topom failed\")\n\t\t} else if t != nil && OnlineProxy(p, t.AdminAddr) {\n\t\t\treturn\n\t\t}\n\t\ttime.Sleep(time.Second * 3)\n\t}\n\tlog.Panicf(\"online proxy failed\")\n}\n\nfunc AutoOnlineWithFillSlots(p *proxy.Proxy, slots []*models.Slot) {\n\tif err := p.FillSlots(slots); err != nil {\n\t\tlog.PanicErrorf(err, \"fill slots failed\")\n\t}\n\tif err := p.Start(); err != nil {\n\t\tlog.PanicErrorf(err, \"start proxy failed\")\n\t}\n}\n\nfunc OnlineProxy(p *proxy.Proxy, dashboard string) bool {\n\tclient := topom.NewApiClient(dashboard)\n\tt, err := client.Model()\n\tif err != nil {\n\t\tlog.WarnErrorf(err, \"rpc fetch model failed\")\n\t\treturn false\n\t}\n\tif t.ProductName != p.Config().ProductName {\n\t\tlog.Panicf(\"unexcepted product name, got model =\\n%s\", t.Encode())\n\t}\n\tclient.SetXAuth(p.Config().ProductName)\n\n\tif err := client.OnlineProxy(p.Model().AdminAddr); err != nil {\n\t\tlog.WarnErrorf(err, \"rpc online proxy failed\")\n\t\treturn false\n\t} else {\n\t\tlog.Warnf(\"rpc online proxy seems OK\")\n\t\treturn true\n\t}\n}\n"
  },
  {
    "path": "config/dashboard.toml",
    "content": "\n##################################################\n#                                                #\n#                  Codis-Dashboard               #\n#                                                #\n##################################################\n\n# Set Coordinator, only accept \"zookeeper\" & \"etcd\" & \"filesystem\".\n# for zookeeper/etcd, coorinator_auth accept \"user:password\" \n# Quick Start\ncoordinator_name = \"filesystem\"\ncoordinator_addr = \"/tmp/codis\"\n#coordinator_name = \"zookeeper\"\n#coordinator_addr = \"127.0.0.1:2181\"\n#coordinator_auth = \"\"\n\n# Set Codis Product Name/Auth.\nproduct_name = \"codis-demo\"\nproduct_auth = \"\"\n\n# Set bind address for admin(rpc), tcp only.\nadmin_addr = \"0.0.0.0:18080\"\n\n# Set arguments for data migration (only accept 'sync' & 'semi-async').\nmigration_method = \"semi-async\"\nmigration_parallel_slots = 100\nmigration_async_maxbulks = 200\nmigration_async_maxbytes = \"32mb\"\nmigration_async_numkeys = 500\nmigration_timeout = \"30s\"\n\n# Set configs for redis sentinel.\nsentinel_client_timeout = \"10s\"\nsentinel_quorum = 2\nsentinel_parallel_syncs = 1\nsentinel_down_after = \"30s\"\nsentinel_failover_timeout = \"5m\"\nsentinel_notification_script = \"\"\nsentinel_client_reconfig_script = \"\"\n\n"
  },
  {
    "path": "config/proxy.toml",
    "content": "\n##################################################\n#                                                #\n#                  Codis-Proxy                   #\n#                                                #\n##################################################\n\n# Set Codis Product Name/Auth.\nproduct_name = \"codis-demo\"\nproduct_auth = \"\"\n\n# Set auth for client session\n#   1. product_auth is used for auth validation among codis-dashboard,\n#      codis-proxy and codis-server.\n#   2. session_auth is different from product_auth, it requires clients\n#      to issue AUTH <PASSWORD> before processing any other commands.\nsession_auth = \"\"\n\n# Set bind address for admin(rpc), tcp only.\nadmin_addr = \"0.0.0.0:11080\"\n\n# Set bind address for proxy, proto_type can be \"tcp\", \"tcp4\", \"tcp6\", \"unix\" or \"unixpacket\".\nproto_type = \"tcp4\"\nproxy_addr = \"0.0.0.0:19000\"\n\n# Set jodis address & session timeout\n#   1. jodis_name is short for jodis_coordinator_name, only accept \"zookeeper\" & \"etcd\".\n#   2. jodis_addr is short for jodis_coordinator_addr\n#   3. jodis_auth is short for jodis_coordinator_auth, for zookeeper/etcd, \"user:password\" is accepted.\n#   4. proxy will be registered as node:\n#        if jodis_compatible = true (not suggested):\n#          /zk/codis/db_{PRODUCT_NAME}/proxy-{HASHID} (compatible with Codis2.0)\n#        or else\n#          /jodis/{PRODUCT_NAME}/proxy-{HASHID}\njodis_name = \"\"\njodis_addr = \"\"\njodis_auth = \"\"\njodis_timeout = \"20s\"\njodis_compatible = false\n\n# Set datacenter of proxy.\nproxy_datacenter = \"\"\n\n# Set max number of alive sessions.\nproxy_max_clients = 1000\n\n# Set max offheap memory size. (0 to disable)\nproxy_max_offheap_size = \"1024mb\"\n\n# Set heap placeholder to reduce GC frequency.\nproxy_heap_placeholder = \"256mb\"\n\n# Proxy will ping backend redis (and clear 'MASTERDOWN' state) in a predefined interval. (0 to disable)\nbackend_ping_period = \"5s\"\n\n# Set backend recv buffer size & timeout.\nbackend_recv_bufsize = \"128kb\"\nbackend_recv_timeout = \"30s\"\n\n# Set backend send buffer & timeout.\nbackend_send_bufsize = \"128kb\"\nbackend_send_timeout = \"30s\"\n\n# Set backend pipeline buffer size.\nbackend_max_pipeline = 20480\n\n# Set backend never read replica groups, default is false\nbackend_primary_only = false\n\n# Set backend parallel connections per server\nbackend_primary_parallel = 1\nbackend_replica_parallel = 1\n\n# Set backend tcp keepalive period. (0 to disable)\nbackend_keepalive_period = \"75s\"\n\n# Set number of databases of backend.\nbackend_number_databases = 16\n\n# If there is no request from client for a long time, the connection will be closed. (0 to disable)\n# Set session recv buffer size & timeout.\nsession_recv_bufsize = \"128kb\"\nsession_recv_timeout = \"30m\"\n\n# Set session send buffer size & timeout.\nsession_send_bufsize = \"64kb\"\nsession_send_timeout = \"30s\"\n\n# Make sure this is higher than the max number of requests for each pipeline request, or your client may be blocked.\n# Set session pipeline buffer size.\nsession_max_pipeline = 10000\n\n# Set session tcp keepalive period. (0 to disable)\nsession_keepalive_period = \"75s\"\n\n# Set session to be sensitive to failures. Default is false, instead of closing socket, proxy will send an error response to client.\nsession_break_on_failure = false\n\n# Set metrics server (such as http://localhost:28000), proxy will report json formatted metrics to specified server in a predefined period.\nmetrics_report_server = \"\"\nmetrics_report_period = \"1s\"\n\n# Set influxdb server (such as http://localhost:8086), proxy will report metrics to influxdb.\nmetrics_report_influxdb_server = \"\"\nmetrics_report_influxdb_period = \"1s\"\nmetrics_report_influxdb_username = \"\"\nmetrics_report_influxdb_password = \"\"\nmetrics_report_influxdb_database = \"\"\n\n# Set statsd server (such as localhost:8125), proxy will report metrics to statsd.\nmetrics_report_statsd_server = \"\"\nmetrics_report_statsd_period = \"1s\"\nmetrics_report_statsd_prefix = \"\"\n\n"
  },
  {
    "path": "config/redis.conf",
    "content": "# Redis configuration file example.\n#\n# Note that in order to read the configuration file, Redis must be\n# started with the file path as first argument:\n#\n# ./redis-server /path/to/redis.conf\n\n# Note on units: when memory size is needed, it is possible to specify\n# it in the usual form of 1k 5GB 4M and so forth:\n#\n# 1k => 1000 bytes\n# 1kb => 1024 bytes\n# 1m => 1000000 bytes\n# 1mb => 1024*1024 bytes\n# 1g => 1000000000 bytes\n# 1gb => 1024*1024*1024 bytes\n#\n# units are case insensitive so 1GB 1Gb 1gB are all the same.\n\n################################## INCLUDES ###################################\n\n# Include one or more other config files here.  This is useful if you\n# have a standard template that goes to all Redis servers but also need\n# to customize a few per-server settings.  Include files can include\n# other files, so use this wisely.\n#\n# Notice option \"include\" won't be rewritten by command \"CONFIG REWRITE\"\n# from admin or Redis Sentinel. Since Redis always uses the last processed\n# line as value of a configuration directive, you'd better put includes\n# at the beginning of this file to avoid overwriting config change at runtime.\n#\n# If instead you are interested in using includes to override configuration\n# options, it is better to use include as the last line.\n#\n# include /path/to/local.conf\n# include /path/to/other.conf\n\n################################## NETWORK #####################################\n\n# By default, if no \"bind\" configuration directive is specified, Redis listens\n# for connections from all the network interfaces available on the server.\n# It is possible to listen to just one or multiple selected interfaces using\n# the \"bind\" configuration directive, followed by one or more IP addresses.\n#\n# Examples:\n#\n# bind 192.168.1.100 10.0.0.1\n# bind 127.0.0.1 ::1\n#\n# ~~~ WARNING ~~~ If the computer running Redis is directly exposed to the\n# internet, binding to all the interfaces is dangerous and will expose the\n# instance to everybody on the internet. So by default we uncomment the\n# following bind directive, that will force Redis to listen only into\n# the IPv4 lookback interface address (this means Redis will be able to\n# accept connections only from clients running into the same computer it\n# is running).\n#\n# IF YOU ARE SURE YOU WANT YOUR INSTANCE TO LISTEN TO ALL THE INTERFACES\n# JUST COMMENT THE FOLLOWING LINE.\n# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\nbind 127.0.0.1\n\n# Protected mode is a layer of security protection, in order to avoid that\n# Redis instances left open on the internet are accessed and exploited.\n#\n# When protected mode is on and if:\n#\n# 1) The server is not binding explicitly to a set of addresses using the\n#    \"bind\" directive.\n# 2) No password is configured.\n#\n# The server only accepts connections from clients connecting from the\n# IPv4 and IPv6 loopback addresses 127.0.0.1 and ::1, and from Unix domain\n# sockets.\n#\n# By default protected mode is enabled. You should disable it only if\n# you are sure you want clients from other hosts to connect to Redis\n# even if no authentication is configured, nor a specific set of interfaces\n# are explicitly listed using the \"bind\" directive.\nprotected-mode yes\n\n# Accept connections on the specified port, default is 6379 (IANA #815344).\n# If port 0 is specified Redis will not listen on a TCP socket.\nport 6379\n\n# TCP listen() backlog.\n#\n# In high requests-per-second environments you need an high backlog in order\n# to avoid slow clients connections issues. Note that the Linux kernel\n# will silently truncate it to the value of /proc/sys/net/core/somaxconn so\n# make sure to raise both the value of somaxconn and tcp_max_syn_backlog\n# in order to get the desired effect.\ntcp-backlog 511\n\n# Unix socket.\n#\n# Specify the path for the Unix socket that will be used to listen for\n# incoming connections. There is no default, so Redis will not listen\n# on a unix socket when not specified.\n#\n# unixsocket /tmp/redis.sock\n# unixsocketperm 700\n\n# Close the connection after a client is idle for N seconds (0 to disable)\ntimeout 0\n\n# TCP keepalive.\n#\n# If non-zero, use SO_KEEPALIVE to send TCP ACKs to clients in absence\n# of communication. This is useful for two reasons:\n#\n# 1) Detect dead peers.\n# 2) Take the connection alive from the point of view of network\n#    equipment in the middle.\n#\n# On Linux, the specified value (in seconds) is the period used to send ACKs.\n# Note that to close the connection the double of the time is needed.\n# On other kernels the period depends on the kernel configuration.\n#\n# A reasonable value for this option is 300 seconds, which is the new\n# Redis default starting with Redis 3.2.1.\ntcp-keepalive 300\n\n################################# GENERAL #####################################\n\n# By default Redis does not run as a daemon. Use 'yes' if you need it.\n# Note that Redis will write a pid file in /var/run/redis.pid when daemonized.\ndaemonize yes\n\n# If you run Redis from upstart or systemd, Redis can interact with your\n# supervision tree. Options:\n#   supervised no      - no supervision interaction\n#   supervised upstart - signal upstart by putting Redis into SIGSTOP mode\n#   supervised systemd - signal systemd by writing READY=1 to $NOTIFY_SOCKET\n#   supervised auto    - detect upstart or systemd method based on\n#                        UPSTART_JOB or NOTIFY_SOCKET environment variables\n# Note: these supervision methods only signal \"process is ready.\"\n#       They do not enable continuous liveness pings back to your supervisor.\nsupervised no\n\n# If a pid file is specified, Redis writes it where specified at startup\n# and removes it at exit.\n#\n# When the server runs non daemonized, no pid file is created if none is\n# specified in the configuration. When the server is daemonized, the pid file\n# is used even if not specified, defaulting to \"/var/run/redis.pid\".\n#\n# Creating a pid file is best effort: if Redis is not able to create it\n# nothing bad happens, the server will start and run normally.\npidfile /tmp/redis_6379.pid\n\n# Specify the server verbosity level.\n# This can be one of:\n# debug (a lot of information, useful for development/testing)\n# verbose (many rarely useful info, but not a mess like the debug level)\n# notice (moderately verbose, what you want in production probably)\n# warning (only very important / critical messages are logged)\nloglevel notice\n\n# Specify the log file name. Also the empty string can be used to force\n# Redis to log on the standard output. Note that if you use standard\n# output for logging but daemonize, logs will be sent to /dev/null\nlogfile \"/tmp/redis_6379.log\"\n\n# To enable logging to the system logger, just set 'syslog-enabled' to yes,\n# and optionally update the other syslog parameters to suit your needs.\n# syslog-enabled no\n\n# Specify the syslog identity.\n# syslog-ident redis\n\n# Specify the syslog facility. Must be USER or between LOCAL0-LOCAL7.\n# syslog-facility local0\n\n# Set the number of databases. The default database is DB 0, you can select\n# a different one on a per-connection basis using SELECT <dbid> where\n# dbid is a number between 0 and 'databases'-1\ndatabases 16\n\n################################ SNAPSHOTTING  ################################\n#\n# Save the DB on disk:\n#\n#   save <seconds> <changes>\n#\n#   Will save the DB if both the given number of seconds and the given\n#   number of write operations against the DB occurred.\n#\n#   In the example below the behaviour will be to save:\n#   after 900 sec (15 min) if at least 1 key changed\n#   after 300 sec (5 min) if at least 10 keys changed\n#   after 60 sec if at least 10000 keys changed\n#\n#   Note: you can disable saving completely by commenting out all \"save\" lines.\n#\n#   It is also possible to remove all the previously configured save\n#   points by adding a save directive with a single empty string argument\n#   like in the following example:\n#\n#   save \"\"\n\nsave 900 1\nsave 300 10\nsave 60 10000\n\n# By default Redis will stop accepting writes if RDB snapshots are enabled\n# (at least one save point) and the latest background save failed.\n# This will make the user aware (in a hard way) that data is not persisting\n# on disk properly, otherwise chances are that no one will notice and some\n# disaster will happen.\n#\n# If the background saving process will start working again Redis will\n# automatically allow writes again.\n#\n# However if you have setup your proper monitoring of the Redis server\n# and persistence, you may want to disable this feature so that Redis will\n# continue to work as usual even if there are problems with disk,\n# permissions, and so forth.\nstop-writes-on-bgsave-error yes\n\n# Compress string objects using LZF when dump .rdb databases?\n# For default that's set to 'yes' as it's almost always a win.\n# If you want to save some CPU in the saving child set it to 'no' but\n# the dataset will likely be bigger if you have compressible values or keys.\nrdbcompression yes\n\n# Since version 5 of RDB a CRC64 checksum is placed at the end of the file.\n# This makes the format more resistant to corruption but there is a performance\n# hit to pay (around 10%) when saving and loading RDB files, so you can disable it\n# for maximum performances.\n#\n# RDB files created with checksum disabled have a checksum of zero that will\n# tell the loading code to skip the check.\nrdbchecksum yes\n\n# The filename where to dump the DB\ndbfilename dump.rdb\n\n# The working directory.\n#\n# The DB will be written inside this directory, with the filename specified\n# above using the 'dbfilename' configuration directive.\n#\n# The Append Only File will also be created inside this directory.\n#\n# Note that you must specify a directory here, not a file name.\ndir ./\n\n################################# REPLICATION #################################\n\n# Master-Slave replication. Use slaveof to make a Redis instance a copy of\n# another Redis server. A few things to understand ASAP about Redis replication.\n#\n# 1) Redis replication is asynchronous, but you can configure a master to\n#    stop accepting writes if it appears to be not connected with at least\n#    a given number of slaves.\n# 2) Redis slaves are able to perform a partial resynchronization with the\n#    master if the replication link is lost for a relatively small amount of\n#    time. You may want to configure the replication backlog size (see the next\n#    sections of this file) with a sensible value depending on your needs.\n# 3) Replication is automatic and does not need user intervention. After a\n#    network partition slaves automatically try to reconnect to masters\n#    and resynchronize with them.\n#\n# slaveof <masterip> <masterport>\n\n# If the master is password protected (using the \"requirepass\" configuration\n# directive below) it is possible to tell the slave to authenticate before\n# starting the replication synchronization process, otherwise the master will\n# refuse the slave request.\n#\n# masterauth <master-password>\n\n# When a slave loses its connection with the master, or when the replication\n# is still in progress, the slave can act in two different ways:\n#\n# 1) if slave-serve-stale-data is set to 'yes' (the default) the slave will\n#    still reply to client requests, possibly with out of date data, or the\n#    data set may just be empty if this is the first synchronization.\n#\n# 2) if slave-serve-stale-data is set to 'no' the slave will reply with\n#    an error \"SYNC with master in progress\" to all the kind of commands\n#    but to INFO and SLAVEOF.\n#\nslave-serve-stale-data yes\n\n# You can configure a slave instance to accept writes or not. Writing against\n# a slave instance may be useful to store some ephemeral data (because data\n# written on a slave will be easily deleted after resync with the master) but\n# may also cause problems if clients are writing to it because of a\n# misconfiguration.\n#\n# Since Redis 2.6 by default slaves are read-only.\n#\n# Note: read only slaves are not designed to be exposed to untrusted clients\n# on the internet. It's just a protection layer against misuse of the instance.\n# Still a read only slave exports by default all the administrative commands\n# such as CONFIG, DEBUG, and so forth. To a limited extent you can improve\n# security of read only slaves using 'rename-command' to shadow all the\n# administrative / dangerous commands.\nslave-read-only yes\n\n# Replication SYNC strategy: disk or socket.\n#\n# -------------------------------------------------------\n# WARNING: DISKLESS REPLICATION IS EXPERIMENTAL CURRENTLY\n# -------------------------------------------------------\n#\n# New slaves and reconnecting slaves that are not able to continue the replication\n# process just receiving differences, need to do what is called a \"full\n# synchronization\". An RDB file is transmitted from the master to the slaves.\n# The transmission can happen in two different ways:\n#\n# 1) Disk-backed: The Redis master creates a new process that writes the RDB\n#                 file on disk. Later the file is transferred by the parent\n#                 process to the slaves incrementally.\n# 2) Diskless: The Redis master creates a new process that directly writes the\n#              RDB file to slave sockets, without touching the disk at all.\n#\n# With disk-backed replication, while the RDB file is generated, more slaves\n# can be queued and served with the RDB file as soon as the current child producing\n# the RDB file finishes its work. With diskless replication instead once\n# the transfer starts, new slaves arriving will be queued and a new transfer\n# will start when the current one terminates.\n#\n# When diskless replication is used, the master waits a configurable amount of\n# time (in seconds) before starting the transfer in the hope that multiple slaves\n# will arrive and the transfer can be parallelized.\n#\n# With slow disks and fast (large bandwidth) networks, diskless replication\n# works better.\nrepl-diskless-sync no\n\n# When diskless replication is enabled, it is possible to configure the delay\n# the server waits in order to spawn the child that transfers the RDB via socket\n# to the slaves.\n#\n# This is important since once the transfer starts, it is not possible to serve\n# new slaves arriving, that will be queued for the next RDB transfer, so the server\n# waits a delay in order to let more slaves arrive.\n#\n# The delay is specified in seconds, and by default is 5 seconds. To disable\n# it entirely just set it to 0 seconds and the transfer will start ASAP.\nrepl-diskless-sync-delay 5\n\n# Slaves send PINGs to server in a predefined interval. It's possible to change\n# this interval with the repl_ping_slave_period option. The default value is 10\n# seconds.\n#\n# repl-ping-slave-period 10\n\n# The following option sets the replication timeout for:\n#\n# 1) Bulk transfer I/O during SYNC, from the point of view of slave.\n# 2) Master timeout from the point of view of slaves (data, pings).\n# 3) Slave timeout from the point of view of masters (REPLCONF ACK pings).\n#\n# It is important to make sure that this value is greater than the value\n# specified for repl-ping-slave-period otherwise a timeout will be detected\n# every time there is low traffic between the master and the slave.\n#\n# repl-timeout 60\n\n# Disable TCP_NODELAY on the slave socket after SYNC?\n#\n# If you select \"yes\" Redis will use a smaller number of TCP packets and\n# less bandwidth to send data to slaves. But this can add a delay for\n# the data to appear on the slave side, up to 40 milliseconds with\n# Linux kernels using a default configuration.\n#\n# If you select \"no\" the delay for data to appear on the slave side will\n# be reduced but more bandwidth will be used for replication.\n#\n# By default we optimize for low latency, but in very high traffic conditions\n# or when the master and slaves are many hops away, turning this to \"yes\" may\n# be a good idea.\nrepl-disable-tcp-nodelay no\n\n# Set the replication backlog size. The backlog is a buffer that accumulates\n# slave data when slaves are disconnected for some time, so that when a slave\n# wants to reconnect again, often a full resync is not needed, but a partial\n# resync is enough, just passing the portion of data the slave missed while\n# disconnected.\n#\n# The bigger the replication backlog, the longer the time the slave can be\n# disconnected and later be able to perform a partial resynchronization.\n#\n# The backlog is only allocated once there is at least a slave connected.\n#\n# repl-backlog-size 1mb\n\n# After a master has no longer connected slaves for some time, the backlog\n# will be freed. The following option configures the amount of seconds that\n# need to elapse, starting from the time the last slave disconnected, for\n# the backlog buffer to be freed.\n#\n# A value of 0 means to never release the backlog.\n#\n# repl-backlog-ttl 3600\n\n# The slave priority is an integer number published by Redis in the INFO output.\n# It is used by Redis Sentinel in order to select a slave to promote into a\n# master if the master is no longer working correctly.\n#\n# A slave with a low priority number is considered better for promotion, so\n# for instance if there are three slaves with priority 10, 100, 25 Sentinel will\n# pick the one with priority 10, that is the lowest.\n#\n# However a special priority of 0 marks the slave as not able to perform the\n# role of master, so a slave with priority of 0 will never be selected by\n# Redis Sentinel for promotion.\n#\n# By default the priority is 100.\nslave-priority 100\n\n# It is possible for a master to stop accepting writes if there are less than\n# N slaves connected, having a lag less or equal than M seconds.\n#\n# The N slaves need to be in \"online\" state.\n#\n# The lag in seconds, that must be <= the specified value, is calculated from\n# the last ping received from the slave, that is usually sent every second.\n#\n# This option does not GUARANTEE that N replicas will accept the write, but\n# will limit the window of exposure for lost writes in case not enough slaves\n# are available, to the specified number of seconds.\n#\n# For example to require at least 3 slaves with a lag <= 10 seconds use:\n#\n# min-slaves-to-write 3\n# min-slaves-max-lag 10\n#\n# Setting one or the other to 0 disables the feature.\n#\n# By default min-slaves-to-write is set to 0 (feature disabled) and\n# min-slaves-max-lag is set to 10.\n\n# A Redis master is able to list the address and port of the attached\n# slaves in different ways. For example the \"INFO replication\" section\n# offers this information, which is used, among other tools, by\n# Redis Sentinel in order to discover slave instances.\n# Another place where this info is available is in the output of the\n# \"ROLE\" command of a masteer.\n#\n# The listed IP and address normally reported by a slave is obtained\n# in the following way:\n#\n#   IP: The address is auto detected by checking the peer address\n#   of the socket used by the slave to connect with the master.\n#\n#   Port: The port is communicated by the slave during the replication\n#   handshake, and is normally the port that the slave is using to\n#   list for connections.\n#\n# However when port forwarding or Network Address Translation (NAT) is\n# used, the slave may be actually reachable via different IP and port\n# pairs. The following two options can be used by a slave in order to\n# report to its master a specific set of IP and port, so that both INFO\n# and ROLE will report those values.\n#\n# There is no need to use both the options if you need to override just\n# the port or the IP address.\n#\n# slave-announce-ip 5.5.5.5\n# slave-announce-port 1234\n\n################################## SECURITY ###################################\n\n# Require clients to issue AUTH <PASSWORD> before processing any other\n# commands.  This might be useful in environments in which you do not trust\n# others with access to the host running redis-server.\n#\n# This should stay commented out for backward compatibility and because most\n# people do not need auth (e.g. they run their own servers).\n#\n# Warning: since Redis is pretty fast an outside user can try up to\n# 150k passwords per second against a good box. This means that you should\n# use a very strong password otherwise it will be very easy to break.\n#\n# requirepass foobared\n\n# Command renaming.\n#\n# It is possible to change the name of dangerous commands in a shared\n# environment. For instance the CONFIG command may be renamed into something\n# hard to guess so that it will still be available for internal-use tools\n# but not available for general clients.\n#\n# Example:\n#\n# rename-command CONFIG b840fc02d524045429941cc15f59e41cb7be6c52\n#\n# It is also possible to completely kill a command by renaming it into\n# an empty string:\n#\n# rename-command CONFIG \"\"\n#\n# Please note that changing the name of commands that are logged into the\n# AOF file or transmitted to slaves may cause problems.\n\n################################### LIMITS ####################################\n\n# Set the max number of connected clients at the same time. By default\n# this limit is set to 10000 clients, however if the Redis server is not\n# able to configure the process file limit to allow for the specified limit\n# the max number of allowed clients is set to the current file limit\n# minus 32 (as Redis reserves a few file descriptors for internal uses).\n#\n# Once the limit is reached Redis will close all the new connections sending\n# an error 'max number of clients reached'.\n#\n# maxclients 10000\n\n# Don't use more memory than the specified amount of bytes.\n# When the memory limit is reached Redis will try to remove keys\n# according to the eviction policy selected (see maxmemory-policy).\n#\n# If Redis can't remove keys according to the policy, or if the policy is\n# set to 'noeviction', Redis will start to reply with errors to commands\n# that would use more memory, like SET, LPUSH, and so on, and will continue\n# to reply to read-only commands like GET.\n#\n# This option is usually useful when using Redis as an LRU cache, or to set\n# a hard memory limit for an instance (using the 'noeviction' policy).\n#\n# WARNING: If you have slaves attached to an instance with maxmemory on,\n# the size of the output buffers needed to feed the slaves are subtracted\n# from the used memory count, so that network problems / resyncs will\n# not trigger a loop where keys are evicted, and in turn the output\n# buffer of slaves is full with DELs of keys evicted triggering the deletion\n# of more keys, and so forth until the database is completely emptied.\n#\n# In short... if you have slaves attached it is suggested that you set a lower\n# limit for maxmemory so that there is some free RAM on the system for slave\n# output buffers (but this is not needed if the policy is 'noeviction').\n#\n# maxmemory <bytes>\n\n# MAXMEMORY POLICY: how Redis will select what to remove when maxmemory\n# is reached. You can select among five behaviors:\n#\n# volatile-lru -> remove the key with an expire set using an LRU algorithm\n# allkeys-lru -> remove any key according to the LRU algorithm\n# volatile-random -> remove a random key with an expire set\n# allkeys-random -> remove a random key, any key\n# volatile-ttl -> remove the key with the nearest expire time (minor TTL)\n# noeviction -> don't expire at all, just return an error on write operations\n#\n# Note: with any of the above policies, Redis will return an error on write\n#       operations, when there are no suitable keys for eviction.\n#\n#       At the date of writing these commands are: set setnx setex append\n#       incr decr rpush lpush rpushx lpushx linsert lset rpoplpush sadd\n#       sinter sinterstore sunion sunionstore sdiff sdiffstore zadd zincrby\n#       zunionstore zinterstore hset hsetnx hmset hincrby incrby decrby\n#       getset mset msetnx exec sort\n#\n# The default is:\n#\n# maxmemory-policy noeviction\n\n# LRU and minimal TTL algorithms are not precise algorithms but approximated\n# algorithms (in order to save memory), so you can tune it for speed or\n# accuracy. For default Redis will check five keys and pick the one that was\n# used less recently, you can change the sample size using the following\n# configuration directive.\n#\n# The default of 5 produces good enough results. 10 Approximates very closely\n# true LRU but costs a bit more CPU. 3 is very fast but not very accurate.\n#\n# maxmemory-samples 5\n\n############################## APPEND ONLY MODE ###############################\n\n# By default Redis asynchronously dumps the dataset on disk. This mode is\n# good enough in many applications, but an issue with the Redis process or\n# a power outage may result into a few minutes of writes lost (depending on\n# the configured save points).\n#\n# The Append Only File is an alternative persistence mode that provides\n# much better durability. For instance using the default data fsync policy\n# (see later in the config file) Redis can lose just one second of writes in a\n# dramatic event like a server power outage, or a single write if something\n# wrong with the Redis process itself happens, but the operating system is\n# still running correctly.\n#\n# AOF and RDB persistence can be enabled at the same time without problems.\n# If the AOF is enabled on startup Redis will load the AOF, that is the file\n# with the better durability guarantees.\n#\n# Please check http://redis.io/topics/persistence for more information.\n\nappendonly no\n\n# The name of the append only file (default: \"appendonly.aof\")\n\nappendfilename \"appendonly.aof\"\n\n# The fsync() call tells the Operating System to actually write data on disk\n# instead of waiting for more data in the output buffer. Some OS will really flush\n# data on disk, some other OS will just try to do it ASAP.\n#\n# Redis supports three different modes:\n#\n# no: don't fsync, just let the OS flush the data when it wants. Faster.\n# always: fsync after every write to the append only log. Slow, Safest.\n# everysec: fsync only one time every second. Compromise.\n#\n# The default is \"everysec\", as that's usually the right compromise between\n# speed and data safety. It's up to you to understand if you can relax this to\n# \"no\" that will let the operating system flush the output buffer when\n# it wants, for better performances (but if you can live with the idea of\n# some data loss consider the default persistence mode that's snapshotting),\n# or on the contrary, use \"always\" that's very slow but a bit safer than\n# everysec.\n#\n# More details please check the following article:\n# http://antirez.com/post/redis-persistence-demystified.html\n#\n# If unsure, use \"everysec\".\n\n# appendfsync always\nappendfsync everysec\n# appendfsync no\n\n# When the AOF fsync policy is set to always or everysec, and a background\n# saving process (a background save or AOF log background rewriting) is\n# performing a lot of I/O against the disk, in some Linux configurations\n# Redis may block too long on the fsync() call. Note that there is no fix for\n# this currently, as even performing fsync in a different thread will block\n# our synchronous write(2) call.\n#\n# In order to mitigate this problem it's possible to use the following option\n# that will prevent fsync() from being called in the main process while a\n# BGSAVE or BGREWRITEAOF is in progress.\n#\n# This means that while another child is saving, the durability of Redis is\n# the same as \"appendfsync none\". In practical terms, this means that it is\n# possible to lose up to 30 seconds of log in the worst scenario (with the\n# default Linux settings).\n#\n# If you have latency problems turn this to \"yes\". Otherwise leave it as\n# \"no\" that is the safest pick from the point of view of durability.\n\nno-appendfsync-on-rewrite no\n\n# Automatic rewrite of the append only file.\n# Redis is able to automatically rewrite the log file implicitly calling\n# BGREWRITEAOF when the AOF log size grows by the specified percentage.\n#\n# This is how it works: Redis remembers the size of the AOF file after the\n# latest rewrite (if no rewrite has happened since the restart, the size of\n# the AOF at startup is used).\n#\n# This base size is compared to the current size. If the current size is\n# bigger than the specified percentage, the rewrite is triggered. Also\n# you need to specify a minimal size for the AOF file to be rewritten, this\n# is useful to avoid rewriting the AOF file even if the percentage increase\n# is reached but it is still pretty small.\n#\n# Specify a percentage of zero in order to disable the automatic AOF\n# rewrite feature.\n\nauto-aof-rewrite-percentage 100\nauto-aof-rewrite-min-size 64mb\n\n# An AOF file may be found to be truncated at the end during the Redis\n# startup process, when the AOF data gets loaded back into memory.\n# This may happen when the system where Redis is running\n# crashes, especially when an ext4 filesystem is mounted without the\n# data=ordered option (however this can't happen when Redis itself\n# crashes or aborts but the operating system still works correctly).\n#\n# Redis can either exit with an error when this happens, or load as much\n# data as possible (the default now) and start if the AOF file is found\n# to be truncated at the end. The following option controls this behavior.\n#\n# If aof-load-truncated is set to yes, a truncated AOF file is loaded and\n# the Redis server starts emitting a log to inform the user of the event.\n# Otherwise if the option is set to no, the server aborts with an error\n# and refuses to start. When the option is set to no, the user requires\n# to fix the AOF file using the \"redis-check-aof\" utility before to restart\n# the server.\n#\n# Note that if the AOF file will be found to be corrupted in the middle\n# the server will still exit with an error. This option only applies when\n# Redis will try to read more data from the AOF file but not enough bytes\n# will be found.\naof-load-truncated yes\n\n################################ LUA SCRIPTING  ###############################\n\n# Max execution time of a Lua script in milliseconds.\n#\n# If the maximum execution time is reached Redis will log that a script is\n# still in execution after the maximum allowed time and will start to\n# reply to queries with an error.\n#\n# When a long running script exceeds the maximum execution time only the\n# SCRIPT KILL and SHUTDOWN NOSAVE commands are available. The first can be\n# used to stop a script that did not yet called write commands. The second\n# is the only way to shut down the server in the case a write command was\n# already issued by the script but the user doesn't want to wait for the natural\n# termination of the script.\n#\n# Set it to 0 or a negative value for unlimited execution without warnings.\nlua-time-limit 5000\n\n################################ REDIS CLUSTER  ###############################\n#\n# ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++\n# WARNING EXPERIMENTAL: Redis Cluster is considered to be stable code, however\n# in order to mark it as \"mature\" we need to wait for a non trivial percentage\n# of users to deploy it in production.\n# ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++\n#\n# Normal Redis instances can't be part of a Redis Cluster; only nodes that are\n# started as cluster nodes can. In order to start a Redis instance as a\n# cluster node enable the cluster support uncommenting the following:\n#\n# cluster-enabled yes\n\n# Every cluster node has a cluster configuration file. This file is not\n# intended to be edited by hand. It is created and updated by Redis nodes.\n# Every Redis Cluster node requires a different cluster configuration file.\n# Make sure that instances running in the same system do not have\n# overlapping cluster configuration file names.\n#\n# cluster-config-file nodes-6379.conf\n\n# Cluster node timeout is the amount of milliseconds a node must be unreachable\n# for it to be considered in failure state.\n# Most other internal time limits are multiple of the node timeout.\n#\n# cluster-node-timeout 15000\n\n# A slave of a failing master will avoid to start a failover if its data\n# looks too old.\n#\n# There is no simple way for a slave to actually have a exact measure of\n# its \"data age\", so the following two checks are performed:\n#\n# 1) If there are multiple slaves able to failover, they exchange messages\n#    in order to try to give an advantage to the slave with the best\n#    replication offset (more data from the master processed).\n#    Slaves will try to get their rank by offset, and apply to the start\n#    of the failover a delay proportional to their rank.\n#\n# 2) Every single slave computes the time of the last interaction with\n#    its master. This can be the last ping or command received (if the master\n#    is still in the \"connected\" state), or the time that elapsed since the\n#    disconnection with the master (if the replication link is currently down).\n#    If the last interaction is too old, the slave will not try to failover\n#    at all.\n#\n# The point \"2\" can be tuned by user. Specifically a slave will not perform\n# the failover if, since the last interaction with the master, the time\n# elapsed is greater than:\n#\n#   (node-timeout * slave-validity-factor) + repl-ping-slave-period\n#\n# So for example if node-timeout is 30 seconds, and the slave-validity-factor\n# is 10, and assuming a default repl-ping-slave-period of 10 seconds, the\n# slave will not try to failover if it was not able to talk with the master\n# for longer than 310 seconds.\n#\n# A large slave-validity-factor may allow slaves with too old data to failover\n# a master, while a too small value may prevent the cluster from being able to\n# elect a slave at all.\n#\n# For maximum availability, it is possible to set the slave-validity-factor\n# to a value of 0, which means, that slaves will always try to failover the\n# master regardless of the last time they interacted with the master.\n# (However they'll always try to apply a delay proportional to their\n# offset rank).\n#\n# Zero is the only value able to guarantee that when all the partitions heal\n# the cluster will always be able to continue.\n#\n# cluster-slave-validity-factor 10\n\n# Cluster slaves are able to migrate to orphaned masters, that are masters\n# that are left without working slaves. This improves the cluster ability\n# to resist to failures as otherwise an orphaned master can't be failed over\n# in case of failure if it has no working slaves.\n#\n# Slaves migrate to orphaned masters only if there are still at least a\n# given number of other working slaves for their old master. This number\n# is the \"migration barrier\". A migration barrier of 1 means that a slave\n# will migrate only if there is at least 1 other working slave for its master\n# and so forth. It usually reflects the number of slaves you want for every\n# master in your cluster.\n#\n# Default is 1 (slaves migrate only if their masters remain with at least\n# one slave). To disable migration just set it to a very large value.\n# A value of 0 can be set but is useful only for debugging and dangerous\n# in production.\n#\n# cluster-migration-barrier 1\n\n# By default Redis Cluster nodes stop accepting queries if they detect there\n# is at least an hash slot uncovered (no available node is serving it).\n# This way if the cluster is partially down (for example a range of hash slots\n# are no longer covered) all the cluster becomes, eventually, unavailable.\n# It automatically returns available as soon as all the slots are covered again.\n#\n# However sometimes you want the subset of the cluster which is working,\n# to continue to accept queries for the part of the key space that is still\n# covered. In order to do so, just set the cluster-require-full-coverage\n# option to no.\n#\n# cluster-require-full-coverage yes\n\n# In order to setup your cluster make sure to read the documentation\n# available at http://redis.io web site.\n\n################################## SLOW LOG ###################################\n\n# The Redis Slow Log is a system to log queries that exceeded a specified\n# execution time. The execution time does not include the I/O operations\n# like talking with the client, sending the reply and so forth,\n# but just the time needed to actually execute the command (this is the only\n# stage of command execution where the thread is blocked and can not serve\n# other requests in the meantime).\n#\n# You can configure the slow log with two parameters: one tells Redis\n# what is the execution time, in microseconds, to exceed in order for the\n# command to get logged, and the other parameter is the length of the\n# slow log. When a new command is logged the oldest one is removed from the\n# queue of logged commands.\n\n# The following time is expressed in microseconds, so 1000000 is equivalent\n# to one second. Note that a negative number disables the slow log, while\n# a value of zero forces the logging of every command.\nslowlog-log-slower-than 10000\n\n# There is no limit to this length. Just be aware that it will consume memory.\n# You can reclaim memory used by the slow log with SLOWLOG RESET.\nslowlog-max-len 128\n\n################################ LATENCY MONITOR ##############################\n\n# The Redis latency monitoring subsystem samples different operations\n# at runtime in order to collect data related to possible sources of\n# latency of a Redis instance.\n#\n# Via the LATENCY command this information is available to the user that can\n# print graphs and obtain reports.\n#\n# The system only logs operations that were performed in a time equal or\n# greater than the amount of milliseconds specified via the\n# latency-monitor-threshold configuration directive. When its value is set\n# to zero, the latency monitor is turned off.\n#\n# By default latency monitoring is disabled since it is mostly not needed\n# if you don't have latency issues, and collecting data has a performance\n# impact, that while very small, can be measured under big load. Latency\n# monitoring can easily be enabled at runtime using the command\n# \"CONFIG SET latency-monitor-threshold <milliseconds>\" if needed.\nlatency-monitor-threshold 0\n\n############################# EVENT NOTIFICATION ##############################\n\n# Redis can notify Pub/Sub clients about events happening in the key space.\n# This feature is documented at http://redis.io/topics/notifications\n#\n# For instance if keyspace events notification is enabled, and a client\n# performs a DEL operation on key \"foo\" stored in the Database 0, two\n# messages will be published via Pub/Sub:\n#\n# PUBLISH __keyspace@0__:foo del\n# PUBLISH __keyevent@0__:del foo\n#\n# It is possible to select the events that Redis will notify among a set\n# of classes. Every class is identified by a single character:\n#\n#  K     Keyspace events, published with __keyspace@<db>__ prefix.\n#  E     Keyevent events, published with __keyevent@<db>__ prefix.\n#  g     Generic commands (non-type specific) like DEL, EXPIRE, RENAME, ...\n#  $     String commands\n#  l     List commands\n#  s     Set commands\n#  h     Hash commands\n#  z     Sorted set commands\n#  x     Expired events (events generated every time a key expires)\n#  e     Evicted events (events generated when a key is evicted for maxmemory)\n#  A     Alias for g$lshzxe, so that the \"AKE\" string means all the events.\n#\n#  The \"notify-keyspace-events\" takes as argument a string that is composed\n#  of zero or multiple characters. The empty string means that notifications\n#  are disabled.\n#\n#  Example: to enable list and generic events, from the point of view of the\n#           event name, use:\n#\n#  notify-keyspace-events Elg\n#\n#  Example 2: to get the stream of the expired keys subscribing to channel\n#             name __keyevent@0__:expired use:\n#\n#  notify-keyspace-events Ex\n#\n#  By default all notifications are disabled because most users don't need\n#  this feature and the feature has some overhead. Note that if you don't\n#  specify at least one of K or E, no events will be delivered.\nnotify-keyspace-events \"\"\n\n############################### ADVANCED CONFIG ###############################\n\n# Hashes are encoded using a memory efficient data structure when they have a\n# small number of entries, and the biggest entry does not exceed a given\n# threshold. These thresholds can be configured using the following directives.\nhash-max-ziplist-entries 512\nhash-max-ziplist-value 64\n\n# Lists are also encoded in a special way to save a lot of space.\n# The number of entries allowed per internal list node can be specified\n# as a fixed maximum size or a maximum number of elements.\n# For a fixed maximum size, use -5 through -1, meaning:\n# -5: max size: 64 Kb  <-- not recommended for normal workloads\n# -4: max size: 32 Kb  <-- not recommended\n# -3: max size: 16 Kb  <-- probably not recommended\n# -2: max size: 8 Kb   <-- good\n# -1: max size: 4 Kb   <-- good\n# Positive numbers mean store up to _exactly_ that number of elements\n# per list node.\n# The highest performing option is usually -2 (8 Kb size) or -1 (4 Kb size),\n# but if your use case is unique, adjust the settings as necessary.\nlist-max-ziplist-size -2\n\n# Lists may also be compressed.\n# Compress depth is the number of quicklist ziplist nodes from *each* side of\n# the list to *exclude* from compression.  The head and tail of the list\n# are always uncompressed for fast push/pop operations.  Settings are:\n# 0: disable all list compression\n# 1: depth 1 means \"don't start compressing until after 1 node into the list,\n#    going from either the head or tail\"\n#    So: [head]->node->node->...->node->[tail]\n#    [head], [tail] will always be uncompressed; inner nodes will compress.\n# 2: [head]->[next]->node->node->...->node->[prev]->[tail]\n#    2 here means: don't compress head or head->next or tail->prev or tail,\n#    but compress all nodes between them.\n# 3: [head]->[next]->[next]->node->node->...->node->[prev]->[prev]->[tail]\n# etc.\nlist-compress-depth 0\n\n# Sets have a special encoding in just one case: when a set is composed\n# of just strings that happen to be integers in radix 10 in the range\n# of 64 bit signed integers.\n# The following configuration setting sets the limit in the size of the\n# set in order to use this special memory saving encoding.\nset-max-intset-entries 512\n\n# Similarly to hashes and lists, sorted sets are also specially encoded in\n# order to save a lot of space. This encoding is only used when the length and\n# elements of a sorted set are below the following limits:\nzset-max-ziplist-entries 128\nzset-max-ziplist-value 64\n\n# HyperLogLog sparse representation bytes limit. The limit includes the\n# 16 bytes header. When an HyperLogLog using the sparse representation crosses\n# this limit, it is converted into the dense representation.\n#\n# A value greater than 16000 is totally useless, since at that point the\n# dense representation is more memory efficient.\n#\n# The suggested value is ~ 3000 in order to have the benefits of\n# the space efficient encoding without slowing down too much PFADD,\n# which is O(N) with the sparse encoding. The value can be raised to\n# ~ 10000 when CPU is not a concern, but space is, and the data set is\n# composed of many HyperLogLogs with cardinality in the 0 - 15000 range.\nhll-sparse-max-bytes 3000\n\n# Active rehashing uses 1 millisecond every 100 milliseconds of CPU time in\n# order to help rehashing the main Redis hash table (the one mapping top-level\n# keys to values). The hash table implementation Redis uses (see dict.c)\n# performs a lazy rehashing: the more operation you run into a hash table\n# that is rehashing, the more rehashing \"steps\" are performed, so if the\n# server is idle the rehashing is never complete and some more memory is used\n# by the hash table.\n#\n# The default is to use this millisecond 10 times every second in order to\n# actively rehash the main dictionaries, freeing memory when possible.\n#\n# If unsure:\n# use \"activerehashing no\" if you have hard latency requirements and it is\n# not a good thing in your environment that Redis can reply from time to time\n# to queries with 2 milliseconds delay.\n#\n# use \"activerehashing yes\" if you don't have such hard requirements but\n# want to free memory asap when possible.\nactiverehashing yes\n\n# The client output buffer limits can be used to force disconnection of clients\n# that are not reading data from the server fast enough for some reason (a\n# common reason is that a Pub/Sub client can't consume messages as fast as the\n# publisher can produce them).\n#\n# The limit can be set differently for the three different classes of clients:\n#\n# normal -> normal clients including MONITOR clients\n# slave  -> slave clients\n# pubsub -> clients subscribed to at least one pubsub channel or pattern\n#\n# The syntax of every client-output-buffer-limit directive is the following:\n#\n# client-output-buffer-limit <class> <hard limit> <soft limit> <soft seconds>\n#\n# A client is immediately disconnected once the hard limit is reached, or if\n# the soft limit is reached and remains reached for the specified number of\n# seconds (continuously).\n# So for instance if the hard limit is 32 megabytes and the soft limit is\n# 16 megabytes / 10 seconds, the client will get disconnected immediately\n# if the size of the output buffers reach 32 megabytes, but will also get\n# disconnected if the client reaches 16 megabytes and continuously overcomes\n# the limit for 10 seconds.\n#\n# By default normal clients are not limited because they don't receive data\n# without asking (in a push way), but just after a request, so only\n# asynchronous clients may create a scenario where data is requested faster\n# than it can read.\n#\n# Instead there is a default limit for pubsub and slave clients, since\n# subscribers and slaves receive data in a push fashion.\n#\n# Both the hard or the soft limit can be disabled by setting them to zero.\nclient-output-buffer-limit normal 0 0 0\nclient-output-buffer-limit slave 256mb 64mb 60\nclient-output-buffer-limit pubsub 32mb 8mb 60\n\n# Redis calls an internal function to perform many background tasks, like\n# closing connections of clients in timeout, purging expired keys that are\n# never requested, and so forth.\n#\n# Not all tasks are performed with the same frequency, but Redis checks for\n# tasks to perform according to the specified \"hz\" value.\n#\n# By default \"hz\" is set to 10. Raising the value will use more CPU when\n# Redis is idle, but at the same time will make Redis more responsive when\n# there are many keys expiring at the same time, and timeouts may be\n# handled with more precision.\n#\n# The range is between 1 and 500, however a value over 100 is usually not\n# a good idea. Most users should use the default of 10 and raise this up to\n# 100 only in environments where very low latency is required.\nhz 10\n\n# When a child rewrites the AOF file, if the following option is enabled\n# the file will be fsync-ed every 32 MB of data generated. This is useful\n# in order to commit the file to the disk more incrementally and avoid\n# big latency spikes.\naof-rewrite-incremental-fsync yes\n"
  },
  {
    "path": "config/sentinel.conf",
    "content": "# Example sentinel.conf\n\n# *** IMPORTANT ***\n#\n# By default Sentinel will not be reachable from interfaces different than\n# localhost, either use the 'bind' directive to bind to a list of network\n# interfaces, or disable protected mode with \"protected-mode no\" by\n# adding it to this configuration file.\n#\n# Before doing that MAKE SURE the instance is protected from the outside\n# world via firewalling or other means.\n#\n# For example you may use one of the following:\n#\n# bind 127.0.0.1 192.168.1.1\n#\n# protected-mode no\n\n# port <sentinel-port>\n# The port that this sentinel instance will run on\nport 26379\n\n# sentinel announce-ip <ip>\n# sentinel announce-port <port>\n#\n# The above two configuration directives are useful in environments where,\n# because of NAT, Sentinel is reachable from outside via a non-local address.\n#\n# When announce-ip is provided, the Sentinel will claim the specified IP address\n# in HELLO messages used to gossip its presence, instead of auto-detecting the\n# local address as it usually does.\n#\n# Similarly when announce-port is provided and is valid and non-zero, Sentinel\n# will announce the specified TCP port.\n#\n# The two options don't need to be used together, if only announce-ip is\n# provided, the Sentinel will announce the specified IP and the server port\n# as specified by the \"port\" option. If only announce-port is provided, the\n# Sentinel will announce the auto-detected local IP and the specified port.\n#\n# Example:\n#\n# sentinel announce-ip 1.2.3.4\n\n# dir <working-directory>\n# Every long running process should have a well-defined working directory.\n# For Redis Sentinel to chdir to /tmp at startup is the simplest thing\n# for the process to don't interfere with administrative tasks such as\n# unmounting filesystems.\ndir /tmp\n\n# sentinel monitor <master-name> <ip> <redis-port> <quorum>\n#\n# Tells Sentinel to monitor this master, and to consider it in O_DOWN\n# (Objectively Down) state only if at least <quorum> sentinels agree.\n#\n# Note that whatever is the ODOWN quorum, a Sentinel will require to\n# be elected by the majority of the known Sentinels in order to\n# start a failover, so no failover can be performed in minority.\n#\n# Slaves are auto-discovered, so you don't need to specify slaves in\n# any way. Sentinel itself will rewrite this configuration file adding\n# the slaves using additional configuration options.\n# Also note that the configuration file is rewritten when a\n# slave is promoted to master.\n#\n# Note: master name should not include special characters or spaces.\n# The valid charset is A-z 0-9 and the three characters \".-_\".\n# sentinel monitor mymaster 127.0.0.1 6379 2\n\n# sentinel auth-pass <master-name> <password>\n#\n# Set the password to use to authenticate with the master and slaves.\n# Useful if there is a password set in the Redis instances to monitor.\n#\n# Note that the master password is also used for slaves, so it is not\n# possible to set a different password in masters and slaves instances\n# if you want to be able to monitor these instances with Sentinel.\n#\n# However you can have Redis instances without the authentication enabled\n# mixed with Redis instances requiring the authentication (as long as the\n# password set is the same for all the instances requiring the password) as\n# the AUTH command will have no effect in Redis instances with authentication\n# switched off.\n#\n# Example:\n#\n# sentinel auth-pass mymaster MySUPER--secret-0123passw0rd\n\n# sentinel down-after-milliseconds <master-name> <milliseconds>\n#\n# Number of milliseconds the master (or any attached slave or sentinel) should\n# be unreachable (as in, not acceptable reply to PING, continuously, for the\n# specified period) in order to consider it in S_DOWN state (Subjectively\n# Down).\n#\n# Default is 30 seconds.\n# sentinel down-after-milliseconds mymaster 30000\n\n# sentinel parallel-syncs <master-name> <numslaves>\n#\n# How many slaves we can reconfigure to point to the new slave simultaneously\n# during the failover. Use a low number if you use the slaves to serve query\n# to avoid that all the slaves will be unreachable at about the same\n# time while performing the synchronization with the master.\n# sentinel parallel-syncs mymaster 1\n\n# sentinel failover-timeout <master-name> <milliseconds>\n#\n# Specifies the failover timeout in milliseconds. It is used in many ways:\n#\n# - The time needed to re-start a failover after a previous failover was\n#   already tried against the same master by a given Sentinel, is two\n#   times the failover timeout.\n#\n# - The time needed for a slave replicating to a wrong master according\n#   to a Sentinel current configuration, to be forced to replicate\n#   with the right master, is exactly the failover timeout (counting since\n#   the moment a Sentinel detected the misconfiguration).\n#\n# - The time needed to cancel a failover that is already in progress but\n#   did not produced any configuration change (SLAVEOF NO ONE yet not\n#   acknowledged by the promoted slave).\n#\n# - The maximum time a failover in progress waits for all the slaves to be\n#   reconfigured as slaves of the new master. However even after this time\n#   the slaves will be reconfigured by the Sentinels anyway, but not with\n#   the exact parallel-syncs progression as specified.\n#\n# Default is 3 minutes.\n# sentinel failover-timeout mymaster 180000\n\n# SCRIPTS EXECUTION\n#\n# sentinel notification-script and sentinel reconfig-script are used in order\n# to configure scripts that are called to notify the system administrator\n# or to reconfigure clients after a failover. The scripts are executed\n# with the following rules for error handling:\n#\n# If script exits with \"1\" the execution is retried later (up to a maximum\n# number of times currently set to 10).\n#\n# If script exits with \"2\" (or an higher value) the script execution is\n# not retried.\n#\n# If script terminates because it receives a signal the behavior is the same\n# as exit code 1.\n#\n# A script has a maximum running time of 60 seconds. After this limit is\n# reached the script is terminated with a SIGKILL and the execution retried.\n\n# NOTIFICATION SCRIPT\n#\n# sentinel notification-script <master-name> <script-path>\n# \n# Call the specified notification script for any sentinel event that is\n# generated in the WARNING level (for instance -sdown, -odown, and so forth).\n# This script should notify the system administrator via email, SMS, or any\n# other messaging system, that there is something wrong with the monitored\n# Redis systems.\n#\n# The script is called with just two arguments: the first is the event type\n# and the second the event description.\n#\n# The script must exist and be executable in order for sentinel to start if\n# this option is provided.\n#\n# Example:\n#\n# sentinel notification-script mymaster /var/redis/notify.sh\n\n# CLIENTS RECONFIGURATION SCRIPT\n#\n# sentinel client-reconfig-script <master-name> <script-path>\n#\n# When the master changed because of a failover a script can be called in\n# order to perform application-specific tasks to notify the clients that the\n# configuration has changed and the master is at a different address.\n# \n# The following arguments are passed to the script:\n#\n# <master-name> <role> <state> <from-ip> <from-port> <to-ip> <to-port>\n#\n# <state> is currently always \"failover\"\n# <role> is either \"leader\" or \"observer\"\n# \n# The arguments from-ip, from-port, to-ip, to-port are used to communicate\n# the old address of the master and the new address of the elected slave\n# (now a master).\n#\n# This script should be resistant to multiple invocations.\n#\n# Example:\n#\n# sentinel client-reconfig-script mymaster /var/redis/reconfig.sh\n\n"
  },
  {
    "path": "deploy/Makefile",
    "content": "all:\n\t@cd products && for d in `ls .`; do make -C $$d || exit 1; done\n"
  },
  {
    "path": "deploy/products/alpha/.gitignore",
    "content": "instance.json\n"
  },
  {
    "path": "deploy/products/alpha/Makefile",
    "content": "all:\n\t./gen.py && ./render.py\n"
  },
  {
    "path": "deploy/products/alpha/config.json",
    "content": "{\n    \"product_name\": \"demo-alpha\",\n    \"product_auth\": \"\",\n    \"dashboard\": {\n        \"admin_addr\": \"127.0.0.1:18080\",\n        \"coordinator\": {\n            \"name\": \"etcd\",\n            \"addr\": \"127.0.0.1:2379\"\n        },\n        \"sentinel_quorum\": 2,\n        \"sentinel_down_after\": \"10s\"\n    },\n    \"proxy\": {\n        \"min_cpu\": 4,\n        \"max_cpu\": 8,\n        \"max_clients\": 10000,\n        \"max_pipeline\": 1024\n    }\n}\n"
  },
  {
    "path": "deploy/products/alpha/gen.py",
    "content": "#!/usr/bin/env python3\n\nimport json\n\nproxy = {\n        \"\": [\n            \"127.0.0.1\",\n            ]\n        }\n\nproxy_list = []\n\nfor dc, ip_list in proxy.items():\n    for ip in ip_list:\n        for i in [0, 1, 2]:\n            proxy_list.append({\n                \"datacenter\": dc,\n                \"admin_addr\": \"{}:{}\".format(ip, 11080 + i),\n                \"proxy_addr\": \"{}:{}\".format(ip, 19000 + i),\n                })\n\nwith open(\"instance.json\", 'w+') as f:\n    f.write(json.dumps(proxy_list, indent=4))\n\nfor x in proxy:\n    print(\"[{}]:\".format(x))\n    proxy_addr = \"\"\n    for p in proxy_list:\n        if p[\"datacenter\"] == x:\n            if len(proxy_addr) != 0:\n                proxy_addr += \",\"\n            proxy_addr += p[\"proxy_addr\"]\n    print(proxy_addr)\n    print(\"\\n\")\n\n"
  },
  {
    "path": "deploy/products/alpha/render.py",
    "content": "#!/usr/bin/env python3\n\nimport os\nimport json\nimport stat\n\ntemplate_root = \"../../templates\"\ngenerate_root = \"../../root\"\n\ndef readfile(path, name):\n    file = os.path.join(path, name)\n    with open(file) as f:\n        return f.read()\n\n\ndef generate(path, name, content):\n    if path != \"\":\n        os.makedirs(path, exist_ok=True)\n    file = os.path.join(path, name)\n    print(\"Generate: {}\".format(os.path.abspath(file)))\n    with open(file, 'w+') as f:\n        f.write(content)\n\n\ndef generate_bash(path, name, content):\n    content = \"#!/usr/bin/env bash\\n\\nset -x\\nset -e\\n\\n\" + content + \"\\n\"\n    generate(path, name, content)\n    file = os.path.join(path, name)\n    os.chmod(file, os.stat(file).st_mode | stat.S_IEXEC)\n\n\ndef symlink(src, dst):\n    try:\n        os.remove(dst)\n    except OSError:\n        pass\n    os.symlink(src, dst)\n\n\nclass Coordinator:\n    def __init__(self, config):\n        self.name = config.get(\"name\", \"\")\n        self.addr = config.get(\"addr\", \"\")\n\n\nclass Dashboard():\n    def __init__(self, product, config):\n        self.product = product\n        self.env = product.env\n        self.admin_addr = config.get(\"admin_addr\", \"\")\n\n        self.sentinel_quorum = config.get(\"sentinel_quorum\", 2)\n        self.sentinel_down_after = config.get(\"sentinel_down_after\", \"30s\")\n        self.coordinator = Coordinator(config.get(\"coordinator\", {}))\n\n        if self.admin_addr == \"\":\n            raise Exception(\"dashboard.admin_addr not found\")\n        if self.coordinator.name == \"\":\n            raise Exception(\"coordinator.name not found\")\n        if self.coordinator.addr == \"\":\n            raise Exception(\"coordinator.addr not found or empty\")\n\n        self.admin_port = self.admin_addr.rsplit(':', 1)[1]\n\n    def render(self, proxylist):\n        kwargs = {\n            'PRODUCT_NAME': self.product.name,\n            'PRODUCT_AUTH': self.product.auth,\n            'COORDINATOR_NAME': self.coordinator.name,\n            'COORDINATOR_ADDR': self.coordinator.addr,\n            'ADMIN_ADDR': self.admin_addr,\n            'ADMIN_PORT': self.admin_port,\n            'SENTINEL_QUORUM': self.sentinel_quorum,\n            'SENTINEL_DOWN_AFTER': self.sentinel_down_after,\n            'BIN_PATH': self.env.bin_path,\n            'ETC_PATH': self.env.etc_path,\n            'LOG_PATH': self.env.log_path,\n        }\n        base = os.path.join(generate_root, self.env.etc_path.lstrip('/'), self.admin_addr.replace(':', '_'))\n\n        temp = readfile(template_root, \"dashboard.toml.template\")\n        generate(base, \"dashboard.toml\", temp.format(**kwargs))\n\n        temp = readfile(template_root, \"dashboard.service.template\")\n        generate(base, \"codis_dashboard_{}.service\".format(self.admin_port), temp.format(**kwargs))\n\n        admin = os.path.join(self.env.bin_path, \"codis-admin\")\n        generate_bash(base, \"dashboard_admin\", \"{} --dashboard={} $@\".format(admin, self.admin_addr))\n\n        scripts = 'd=1\\n'\n        for p in proxylist:\n            scripts += \"sleep $d; {} --dashboard={} --online-proxy --addr={}\".format(admin, self.admin_addr, p.admin_addr)\n            scripts += \"\\n\"\n        generate_bash(base, \"foreach_proxy_online\", scripts)\n\n        scripts = 'd=1\\n'\n        for p in proxylist:\n            scripts += \"sleep $d; {} --dashboard={} --reinit-proxy --addr={}\".format(admin, self.admin_addr, p.admin_addr)\n            scripts += \"\\n\"\n        generate_bash(base, \"foreach_proxy_reinit\", scripts)\n\n        scripts = 'd=1\\n'\n        for p in proxylist:\n            scripts += \"sleep $d; {} --proxy={} $@\".format(admin, p.admin_addr)\n            scripts += \"\\n\"\n        generate_bash(base, \"foreach_proxy\", scripts)\n\n        cwd = os.getcwd()\n        os.chdir(os.path.join(base, \"..\"))\n        symlink(self.admin_addr.replace(':', '_'), self.product.name)\n        os.chdir(cwd)\n\n\nclass Template:\n    def __init__(self, config):\n        self.min_cpu = config.get(\"min_cpu\", 4)\n        self.max_cpu = config.get(\"max_cpu\", 0)\n        self.max_clients = config.get(\"max_clients\", 10000)\n        self.max_pipeline = config.get(\"max_pipeline\", 1024)\n        self.log_level = config.get(\"log_level\", \"INFO\")\n        self.jodis_name = config.get(\"jodis_name\", \"\")\n        self.jodis_addr = config.get(\"jodis_addr\", \"\")\n\n\nclass Proxy():\n    def __init__(self, product, template, config):\n        self.product = product\n        self.env = product.env\n        self.template = template\n        self.datacenter = config.get(\"datacenter\", \"\")\n        self.admin_addr = config.get(\"admin_addr\", \"\")\n        self.proxy_addr = config.get(\"proxy_addr\", \"\")\n\n        if self.admin_addr == \"\":\n            raise Exception(\"proxy.admin_addr not found\")\n        if self.proxy_addr == \"\":\n            raise Exception(\"proxy.proxy_addr not found\")\n\n        self.proxy_port = self.proxy_addr.rsplit(':', 1)[1]\n\n    def render(self):\n        kwargs = {\n            'PRODUCT_NAME': self.product.name,\n            'PRODUCT_AUTH': self.product.auth,\n            'ADMIN_ADDR': self.admin_addr,\n            'PROXY_ADDR': self.proxy_addr,\n            'PROXY_PORT': self.proxy_port,\n            'DATACENTER': self.datacenter,\n            'MAX_CLIENTS': self.template.max_clients,\n            'MAX_PIPELINE': self.template.max_pipeline,\n            'JODIS_NAME': self.template.jodis_name,\n            'JODIS_ADDR': self.template.jodis_addr,\n            'MIN_CPU': self.template.min_cpu,\n            'MAX_CPU': self.template.max_cpu,\n            'LOG_LEVEL': self.template.log_level,\n            'BIN_PATH': self.env.bin_path,\n            'ETC_PATH': self.env.etc_path,\n            'LOG_PATH': self.env.log_path,\n        }\n        base = os.path.join(generate_root, self.env.etc_path.lstrip('/'), self.proxy_addr.replace(':', '_'))\n\n        temp = readfile(template_root, \"proxy.toml.template\")\n        generate(base, \"proxy.toml\", temp.format(**kwargs))\n\n        temp = readfile(template_root, \"proxy.service.template\")\n        generate(base, \"codis_proxy_{}.service\".format(self.proxy_port), temp.format(**kwargs))\n\n        admin = os.path.join(self.env.bin_path, \"codis-admin\")\n        generate_bash(base, \"proxy_admin\", \"{} --proxy={} $@\".format(admin, self.admin_addr))\n\n\nclass Env:\n    def __init__(self, config):\n        self.bin_path = os.path.abspath(config.get(\"bin_path\", \"/opt/codis/bin\"))\n        self.etc_path = os.path.abspath(config.get(\"etc_path\", \"/opt/codis/etc\"))\n        self.log_path = os.path.abspath(config.get(\"log_path\", \"/opt/codis/log\"))\n        self.log_level = config.get(\"log_level\", \"INFO\").upper()\n\n\nclass Product:\n    def __init__(self, config):\n        self.name = config.get(\"product_name\", \"\")\n        self.auth = config.get(\"product_auth\", \"\")\n\n        if self.name == \"\":\n            raise Exception(\"product_name not found\")\n\n        self.env = Env(config.get(\"env\", {}))\n        self.dashboard = Dashboard(self, config.get(\"dashboard\", {}))\n\n        self.proxylist = []\n        if \"proxy\" in config:\n            template = Template(config.get(\"proxy\", {}))\n            for p in config.get(\"instance\", []):\n                self.proxylist.append(Proxy(self, template, p))\n        self.proxylist.sort(key=lambda p: p.datacenter + \"|\" + p.proxy_addr)\n\n    def render(self):\n        self.dashboard.render(self.proxylist)\n        for p in self.proxylist:\n            p.render()\n\n\nconfig = {}\n\nwith open('config.json') as f:\n    config = json.loads(f.read())\n\nwith open('instance.json') as f:\n    config[\"instance\"] = json.loads(f.read())\n\nproduct = Product(config)\nproduct.render()\n"
  },
  {
    "path": "deploy/products/beta/.gitignore",
    "content": "instance.json\n"
  },
  {
    "path": "deploy/products/beta/Makefile",
    "content": "all:\n\t./gen.py && ./render.py\n"
  },
  {
    "path": "deploy/products/beta/config.json",
    "content": "{\n    \"env\": {\n        \"bin_path\": \"/opt/codis/bin\",\n        \"etc_path\": \"/opt/codis/etc\",\n        \"log_path\": \"/opt/codis/log\"\n    },\n    \"product_name\": \"demo-beta\",\n    \"product_auth\": \"\",\n    \"dashboard\": {\n        \"admin_addr\": \"10.4.10.100:18080\",\n        \"coordinator\": {\n            \"name\": \"zookeeper\",\n            \"addr\": \"10.4.10.101:2181,10.4.10.102:2181,10.4.10.103:2181,10.4.10.104:2181,10.4.10.105:2181\"\n        },\n        \"sentinel_quorum\": 2,\n        \"sentinel_down_after\": \"10s\"\n    },\n    \"proxy\": {\n        \"min_cpu\": 4,\n        \"max_cpu\": 8,\n        \"max_clients\": 2000,\n        \"max_pipeline\": 512,\n        \"log_level\": \"WARN\",\n        \"jodis_name\": \"zookeeper\",\n        \"jodis_addr\": \"10.4.10.101:2181,10.4.10.102:2181,10.4.10.103:2181,10.4.10.104:2181,10.4.10.105:2181\"\n    }\n}\n"
  },
  {
    "path": "deploy/products/beta/gen.py",
    "content": "#!/usr/bin/env python3\n\nimport json\n\nproxy = {\n        \"dc1\": [\n            \"10.4.10.200\",\n            \"10.4.10.201\",\n            ],\n        \"dc2\":[\n            \"10.2.16.200\",\n            \"10.2.16.201\",\n            \"10.2.16.202\",\n            ],\n        }\n\nproxy_list = []\n\nfor dc, ip_list in proxy.items():\n    for ip in ip_list:\n        for i in [0, 2]:\n            proxy_list.append({\n                \"datacenter\": dc,\n                \"admin_addr\": \"{}:{}\".format(ip, 11080 + i),\n                \"proxy_addr\": \"{}:{}\".format(ip, 19000 + i),\n                })\n\nwith open(\"instance.json\", 'w+') as f:\n    f.write(json.dumps(proxy_list, indent=4))\n\nfor x in proxy:\n    print(\"[{}]:\".format(x))\n    proxy_addr = \"\"\n    for p in proxy_list:\n        if p[\"datacenter\"] == x:\n            if len(proxy_addr) != 0:\n                proxy_addr += \",\"\n            proxy_addr += p[\"proxy_addr\"]\n    print(proxy_addr)\n    print(\"\\n\")\n\n"
  },
  {
    "path": "deploy/products/beta/render.py",
    "content": "#!/usr/bin/env python3\n\nimport os\nimport json\nimport stat\n\ntemplate_root = \"../../templates\"\ngenerate_root = \"../../root\"\n\ndef readfile(path, name):\n    file = os.path.join(path, name)\n    with open(file) as f:\n        return f.read()\n\n\ndef generate(path, name, content):\n    if path != \"\":\n        os.makedirs(path, exist_ok=True)\n    file = os.path.join(path, name)\n    print(\"Generate: {}\".format(os.path.abspath(file)))\n    with open(file, 'w+') as f:\n        f.write(content)\n\n\ndef generate_bash(path, name, content):\n    content = \"#!/usr/bin/env bash\\n\\nset -x\\nset -e\\n\\n\" + content + \"\\n\"\n    generate(path, name, content)\n    file = os.path.join(path, name)\n    os.chmod(file, os.stat(file).st_mode | stat.S_IEXEC)\n\n\ndef symlink(src, dst):\n    try:\n        os.remove(dst)\n    except OSError:\n        pass\n    os.symlink(src, dst)\n\n\nclass Coordinator:\n    def __init__(self, config):\n        self.name = config.get(\"name\", \"\")\n        self.addr = config.get(\"addr\", \"\")\n\n\nclass Dashboard():\n    def __init__(self, product, config):\n        self.product = product\n        self.env = product.env\n        self.admin_addr = config.get(\"admin_addr\", \"\")\n\n        self.sentinel_quorum = config.get(\"sentinel_quorum\", 2)\n        self.sentinel_down_after = config.get(\"sentinel_down_after\", \"30s\")\n        self.coordinator = Coordinator(config.get(\"coordinator\", {}))\n\n        if self.admin_addr == \"\":\n            raise Exception(\"dashboard.admin_addr not found\")\n        if self.coordinator.name == \"\":\n            raise Exception(\"coordinator.name not found\")\n        if self.coordinator.addr == \"\":\n            raise Exception(\"coordinator.addr not found or empty\")\n\n        self.admin_port = self.admin_addr.rsplit(':', 1)[1]\n\n    def render(self, proxylist):\n        kwargs = {\n            'PRODUCT_NAME': self.product.name,\n            'PRODUCT_AUTH': self.product.auth,\n            'COORDINATOR_NAME': self.coordinator.name,\n            'COORDINATOR_ADDR': self.coordinator.addr,\n            'ADMIN_ADDR': self.admin_addr,\n            'ADMIN_PORT': self.admin_port,\n            'SENTINEL_QUORUM': self.sentinel_quorum,\n            'SENTINEL_DOWN_AFTER': self.sentinel_down_after,\n            'BIN_PATH': self.env.bin_path,\n            'ETC_PATH': self.env.etc_path,\n            'LOG_PATH': self.env.log_path,\n        }\n        base = os.path.join(generate_root, self.env.etc_path.lstrip('/'), self.admin_addr.replace(':', '_'))\n\n        temp = readfile(template_root, \"dashboard.toml.template\")\n        generate(base, \"dashboard.toml\", temp.format(**kwargs))\n\n        temp = readfile(template_root, \"dashboard.service.template\")\n        generate(base, \"codis_dashboard_{}.service\".format(self.admin_port), temp.format(**kwargs))\n\n        admin = os.path.join(self.env.bin_path, \"codis-admin\")\n        generate_bash(base, \"dashboard_admin\", \"{} --dashboard={} $@\".format(admin, self.admin_addr))\n\n        scripts = 'd=1\\n'\n        for p in proxylist:\n            scripts += \"sleep $d; {} --dashboard={} --online-proxy --addr={}\".format(admin, self.admin_addr, p.admin_addr)\n            scripts += \"\\n\"\n        generate_bash(base, \"foreach_proxy_online\", scripts)\n\n        scripts = 'd=1\\n'\n        for p in proxylist:\n            scripts += \"sleep $d; {} --dashboard={} --reinit-proxy --addr={}\".format(admin, self.admin_addr, p.admin_addr)\n            scripts += \"\\n\"\n        generate_bash(base, \"foreach_proxy_reinit\", scripts)\n\n        scripts = 'd=1\\n'\n        for p in proxylist:\n            scripts += \"sleep $d; {} --proxy={} $@\".format(admin, p.admin_addr)\n            scripts += \"\\n\"\n        generate_bash(base, \"foreach_proxy\", scripts)\n\n        cwd = os.getcwd()\n        os.chdir(os.path.join(base, \"..\"))\n        symlink(self.admin_addr.replace(':', '_'), self.product.name)\n        os.chdir(cwd)\n\n\nclass Template:\n    def __init__(self, config):\n        self.min_cpu = config.get(\"min_cpu\", 4)\n        self.max_cpu = config.get(\"max_cpu\", 0)\n        self.max_clients = config.get(\"max_clients\", 10000)\n        self.max_pipeline = config.get(\"max_pipeline\", 1024)\n        self.log_level = config.get(\"log_level\", \"INFO\")\n        self.jodis_name = config.get(\"jodis_name\", \"\")\n        self.jodis_addr = config.get(\"jodis_addr\", \"\")\n\n\nclass Proxy():\n    def __init__(self, product, template, config):\n        self.product = product\n        self.env = product.env\n        self.template = template\n        self.datacenter = config.get(\"datacenter\", \"\")\n        self.admin_addr = config.get(\"admin_addr\", \"\")\n        self.proxy_addr = config.get(\"proxy_addr\", \"\")\n\n        if self.admin_addr == \"\":\n            raise Exception(\"proxy.admin_addr not found\")\n        if self.proxy_addr == \"\":\n            raise Exception(\"proxy.proxy_addr not found\")\n\n        self.proxy_port = self.proxy_addr.rsplit(':', 1)[1]\n\n    def render(self):\n        kwargs = {\n            'PRODUCT_NAME': self.product.name,\n            'PRODUCT_AUTH': self.product.auth,\n            'ADMIN_ADDR': self.admin_addr,\n            'PROXY_ADDR': self.proxy_addr,\n            'PROXY_PORT': self.proxy_port,\n            'DATACENTER': self.datacenter,\n            'MAX_CLIENTS': self.template.max_clients,\n            'MAX_PIPELINE': self.template.max_pipeline,\n            'JODIS_NAME': self.template.jodis_name,\n            'JODIS_ADDR': self.template.jodis_addr,\n            'MIN_CPU': self.template.min_cpu,\n            'MAX_CPU': self.template.max_cpu,\n            'LOG_LEVEL': self.template.log_level,\n            'BIN_PATH': self.env.bin_path,\n            'ETC_PATH': self.env.etc_path,\n            'LOG_PATH': self.env.log_path,\n        }\n        base = os.path.join(generate_root, self.env.etc_path.lstrip('/'), self.proxy_addr.replace(':', '_'))\n\n        temp = readfile(template_root, \"proxy.toml.template\")\n        generate(base, \"proxy.toml\", temp.format(**kwargs))\n\n        temp = readfile(template_root, \"proxy.service.template\")\n        generate(base, \"codis_proxy_{}.service\".format(self.proxy_port), temp.format(**kwargs))\n\n        admin = os.path.join(self.env.bin_path, \"codis-admin\")\n        generate_bash(base, \"proxy_admin\", \"{} --proxy={} $@\".format(admin, self.admin_addr))\n\n\nclass Env:\n    def __init__(self, config):\n        self.bin_path = os.path.abspath(config.get(\"bin_path\", \"/opt/codis/bin\"))\n        self.etc_path = os.path.abspath(config.get(\"etc_path\", \"/opt/codis/etc\"))\n        self.log_path = os.path.abspath(config.get(\"log_path\", \"/opt/codis/log\"))\n        self.log_level = config.get(\"log_level\", \"INFO\").upper()\n\n\nclass Product:\n    def __init__(self, config):\n        self.name = config.get(\"product_name\", \"\")\n        self.auth = config.get(\"product_auth\", \"\")\n\n        if self.name == \"\":\n            raise Exception(\"product_name not found\")\n\n        self.env = Env(config.get(\"env\", {}))\n        self.dashboard = Dashboard(self, config.get(\"dashboard\", {}))\n\n        self.proxylist = []\n        if \"proxy\" in config:\n            template = Template(config.get(\"proxy\", {}))\n            for p in config.get(\"instance\", []):\n                self.proxylist.append(Proxy(self, template, p))\n        self.proxylist.sort(key=lambda p: p.datacenter + \"|\" + p.proxy_addr)\n\n    def render(self):\n        self.dashboard.render(self.proxylist)\n        for p in self.proxylist:\n            p.render()\n\n\nconfig = {}\n\nwith open('config.json') as f:\n    config = json.loads(f.read())\n\nwith open('instance.json') as f:\n    config[\"instance\"] = json.loads(f.read())\n\nproduct = Product(config)\nproduct.render()\n"
  },
  {
    "path": "deploy/root/opt/codis/etc/10.2.16.200_19000/codis_proxy_19000.service",
    "content": "[Unit]\nDescription=Codis-[demo-beta]@19000\n[Service]\nExecStart=/opt/codis/bin/codis-proxy --ncpu=4 --max-ncpu=8 \\\n    --config=/opt/codis/etc/10.2.16.200:19000/proxy.toml --log=/opt/codis/log/10.2.16.200:19000/proxy.log --log-level=WARN\nRestart=always\n[Install]\nWantedBy=default.target\n\n"
  },
  {
    "path": "deploy/root/opt/codis/etc/10.2.16.200_19000/proxy.toml",
    "content": "##################################################\n#                                                #\n#                  Codis-Proxy                   #\n#                                                #\n##################################################\n\n# Set Codis Product Name/Auth.\nproduct_name = \"demo-beta\"\nproduct_auth = \"\"\n\n# Set bind address for admin(rpc), tcp only.\nadmin_addr = \"10.2.16.200:11080\"\n\n# Set bind address for proxy, proto_type can be \"tcp\", \"tcp4\", \"tcp6\", \"unix\" or \"unixpacket\".\nproto_type = \"tcp4\"\nproxy_addr = \"10.2.16.200:19000\"\n\n# Set jodis address & session timeout, only accept \"zookeeper\" & \"etcd\".\njodis_name = \"zookeeper\"\njodis_addr = \"10.4.10.101:2181,10.4.10.102:2181,10.4.10.103:2181,10.4.10.104:2181,10.4.10.105:2181\"\njodis_timeout = \"20s\"\njodis_compatible = false\n\n# Set datacenter of proxy.\nproxy_datacenter = \"dc2\"\n\n# Set max number of alive sessions.\nproxy_max_clients = 2000\n\n# Set max offheap memory size. (0 to disable)\nproxy_max_offheap_size = \"1024mb\"\n\n# Set heap placeholder to reduce GC frequency.\nproxy_heap_placeholder = \"256mb\"\n\n# Proxy will ping backend redis (and clear 'MASTERDOWN' state) in a predefined interval. (0 to disable)\nbackend_ping_period = \"5s\"\n\n# Set backend recv buffer size & timeout.\nbackend_recv_bufsize = \"128kb\"\nbackend_recv_timeout = \"30s\"\n\n# Set backend send buffer & timeout.\nbackend_send_bufsize = \"128kb\"\nbackend_send_timeout = \"30s\"\n\n# Set backend pipeline buffer size.\nbackend_max_pipeline = 1024\n\n# Set backend never read replica groups, default is false\nbackend_primary_only = false\n\n# Set backend parallel connections per server\nbackend_primary_parallel = 1\nbackend_replica_parallel = 1\n\n# Set backend tcp keepalive period. (0 to disable)\nbackend_keepalive_period = \"75s\"\n\n# Set number of databases of backend.\nbackend_number_databases = 16\n\n# If there is no request from client for a long time, the connection will be closed. (0 to disable)\n# Set session recv buffer size & timeout.\nsession_recv_bufsize = \"128kb\"\nsession_recv_timeout = \"30m\"\n\n# Set session send buffer size & timeout.\nsession_send_bufsize = \"64kb\"\nsession_send_timeout = \"30s\"\n\n# Make sure this is higher than the max number of requests for each pipeline request, or your client may be blocked.\n# Set session pipeline buffer size.\nsession_max_pipeline = 512\n\n# Set session tcp keepalive period. (0 to disable)\nsession_keepalive_period = \"75s\"\n\n# Set session to be sensitive to failures. Default is false, instead of closing socket, proxy will send an error response to client.\nsession_break_on_failure = false\n\n# Set metrics server (such as http://localhost:28000), proxy will report json formatted metrics to specified server in a predefined period.\nmetrics_report_server = \"\"\nmetrics_report_period = \"1s\"\n\n# Set influxdb server (such as http://localhost:8086), proxy will report metrics to influxdb.\nmetrics_report_influxdb_server = \"\"\nmetrics_report_influxdb_period = \"1s\"\nmetrics_report_influxdb_username = \"\"\nmetrics_report_influxdb_password = \"\"\nmetrics_report_influxdb_database = \"\"\n\n"
  },
  {
    "path": "deploy/root/opt/codis/etc/10.2.16.200_19000/proxy_admin",
    "content": "#!/usr/bin/env bash\n\nset -x\nset -e\n\n/opt/codis/bin/codis-admin --proxy=10.2.16.200:11080 $@\n"
  },
  {
    "path": "deploy/root/opt/codis/etc/10.2.16.200_19002/codis_proxy_19002.service",
    "content": "[Unit]\nDescription=Codis-[demo-beta]@19002\n[Service]\nExecStart=/opt/codis/bin/codis-proxy --ncpu=4 --max-ncpu=8 \\\n    --config=/opt/codis/etc/10.2.16.200:19002/proxy.toml --log=/opt/codis/log/10.2.16.200:19002/proxy.log --log-level=WARN\nRestart=always\n[Install]\nWantedBy=default.target\n\n"
  },
  {
    "path": "deploy/root/opt/codis/etc/10.2.16.200_19002/proxy.toml",
    "content": "##################################################\n#                                                #\n#                  Codis-Proxy                   #\n#                                                #\n##################################################\n\n# Set Codis Product Name/Auth.\nproduct_name = \"demo-beta\"\nproduct_auth = \"\"\n\n# Set bind address for admin(rpc), tcp only.\nadmin_addr = \"10.2.16.200:11082\"\n\n# Set bind address for proxy, proto_type can be \"tcp\", \"tcp4\", \"tcp6\", \"unix\" or \"unixpacket\".\nproto_type = \"tcp4\"\nproxy_addr = \"10.2.16.200:19002\"\n\n# Set jodis address & session timeout, only accept \"zookeeper\" & \"etcd\".\njodis_name = \"zookeeper\"\njodis_addr = \"10.4.10.101:2181,10.4.10.102:2181,10.4.10.103:2181,10.4.10.104:2181,10.4.10.105:2181\"\njodis_timeout = \"20s\"\njodis_compatible = false\n\n# Set datacenter of proxy.\nproxy_datacenter = \"dc2\"\n\n# Set max number of alive sessions.\nproxy_max_clients = 2000\n\n# Set max offheap memory size. (0 to disable)\nproxy_max_offheap_size = \"1024mb\"\n\n# Set heap placeholder to reduce GC frequency.\nproxy_heap_placeholder = \"256mb\"\n\n# Proxy will ping backend redis (and clear 'MASTERDOWN' state) in a predefined interval. (0 to disable)\nbackend_ping_period = \"5s\"\n\n# Set backend recv buffer size & timeout.\nbackend_recv_bufsize = \"128kb\"\nbackend_recv_timeout = \"30s\"\n\n# Set backend send buffer & timeout.\nbackend_send_bufsize = \"128kb\"\nbackend_send_timeout = \"30s\"\n\n# Set backend pipeline buffer size.\nbackend_max_pipeline = 1024\n\n# Set backend never read replica groups, default is false\nbackend_primary_only = false\n\n# Set backend parallel connections per server\nbackend_primary_parallel = 1\nbackend_replica_parallel = 1\n\n# Set backend tcp keepalive period. (0 to disable)\nbackend_keepalive_period = \"75s\"\n\n# Set number of databases of backend.\nbackend_number_databases = 16\n\n# If there is no request from client for a long time, the connection will be closed. (0 to disable)\n# Set session recv buffer size & timeout.\nsession_recv_bufsize = \"128kb\"\nsession_recv_timeout = \"30m\"\n\n# Set session send buffer size & timeout.\nsession_send_bufsize = \"64kb\"\nsession_send_timeout = \"30s\"\n\n# Make sure this is higher than the max number of requests for each pipeline request, or your client may be blocked.\n# Set session pipeline buffer size.\nsession_max_pipeline = 512\n\n# Set session tcp keepalive period. (0 to disable)\nsession_keepalive_period = \"75s\"\n\n# Set session to be sensitive to failures. Default is false, instead of closing socket, proxy will send an error response to client.\nsession_break_on_failure = false\n\n# Set metrics server (such as http://localhost:28000), proxy will report json formatted metrics to specified server in a predefined period.\nmetrics_report_server = \"\"\nmetrics_report_period = \"1s\"\n\n# Set influxdb server (such as http://localhost:8086), proxy will report metrics to influxdb.\nmetrics_report_influxdb_server = \"\"\nmetrics_report_influxdb_period = \"1s\"\nmetrics_report_influxdb_username = \"\"\nmetrics_report_influxdb_password = \"\"\nmetrics_report_influxdb_database = \"\"\n\n"
  },
  {
    "path": "deploy/root/opt/codis/etc/10.2.16.200_19002/proxy_admin",
    "content": "#!/usr/bin/env bash\n\nset -x\nset -e\n\n/opt/codis/bin/codis-admin --proxy=10.2.16.200:11082 $@\n"
  },
  {
    "path": "deploy/root/opt/codis/etc/10.2.16.201_19000/codis_proxy_19000.service",
    "content": "[Unit]\nDescription=Codis-[demo-beta]@19000\n[Service]\nExecStart=/opt/codis/bin/codis-proxy --ncpu=4 --max-ncpu=8 \\\n    --config=/opt/codis/etc/10.2.16.201:19000/proxy.toml --log=/opt/codis/log/10.2.16.201:19000/proxy.log --log-level=WARN\nRestart=always\n[Install]\nWantedBy=default.target\n\n"
  },
  {
    "path": "deploy/root/opt/codis/etc/10.2.16.201_19000/proxy.toml",
    "content": "##################################################\n#                                                #\n#                  Codis-Proxy                   #\n#                                                #\n##################################################\n\n# Set Codis Product Name/Auth.\nproduct_name = \"demo-beta\"\nproduct_auth = \"\"\n\n# Set bind address for admin(rpc), tcp only.\nadmin_addr = \"10.2.16.201:11080\"\n\n# Set bind address for proxy, proto_type can be \"tcp\", \"tcp4\", \"tcp6\", \"unix\" or \"unixpacket\".\nproto_type = \"tcp4\"\nproxy_addr = \"10.2.16.201:19000\"\n\n# Set jodis address & session timeout, only accept \"zookeeper\" & \"etcd\".\njodis_name = \"zookeeper\"\njodis_addr = \"10.4.10.101:2181,10.4.10.102:2181,10.4.10.103:2181,10.4.10.104:2181,10.4.10.105:2181\"\njodis_timeout = \"20s\"\njodis_compatible = false\n\n# Set datacenter of proxy.\nproxy_datacenter = \"dc2\"\n\n# Set max number of alive sessions.\nproxy_max_clients = 2000\n\n# Set max offheap memory size. (0 to disable)\nproxy_max_offheap_size = \"1024mb\"\n\n# Set heap placeholder to reduce GC frequency.\nproxy_heap_placeholder = \"256mb\"\n\n# Proxy will ping backend redis (and clear 'MASTERDOWN' state) in a predefined interval. (0 to disable)\nbackend_ping_period = \"5s\"\n\n# Set backend recv buffer size & timeout.\nbackend_recv_bufsize = \"128kb\"\nbackend_recv_timeout = \"30s\"\n\n# Set backend send buffer & timeout.\nbackend_send_bufsize = \"128kb\"\nbackend_send_timeout = \"30s\"\n\n# Set backend pipeline buffer size.\nbackend_max_pipeline = 1024\n\n# Set backend never read replica groups, default is false\nbackend_primary_only = false\n\n# Set backend parallel connections per server\nbackend_primary_parallel = 1\nbackend_replica_parallel = 1\n\n# Set backend tcp keepalive period. (0 to disable)\nbackend_keepalive_period = \"75s\"\n\n# Set number of databases of backend.\nbackend_number_databases = 16\n\n# If there is no request from client for a long time, the connection will be closed. (0 to disable)\n# Set session recv buffer size & timeout.\nsession_recv_bufsize = \"128kb\"\nsession_recv_timeout = \"30m\"\n\n# Set session send buffer size & timeout.\nsession_send_bufsize = \"64kb\"\nsession_send_timeout = \"30s\"\n\n# Make sure this is higher than the max number of requests for each pipeline request, or your client may be blocked.\n# Set session pipeline buffer size.\nsession_max_pipeline = 512\n\n# Set session tcp keepalive period. (0 to disable)\nsession_keepalive_period = \"75s\"\n\n# Set session to be sensitive to failures. Default is false, instead of closing socket, proxy will send an error response to client.\nsession_break_on_failure = false\n\n# Set metrics server (such as http://localhost:28000), proxy will report json formatted metrics to specified server in a predefined period.\nmetrics_report_server = \"\"\nmetrics_report_period = \"1s\"\n\n# Set influxdb server (such as http://localhost:8086), proxy will report metrics to influxdb.\nmetrics_report_influxdb_server = \"\"\nmetrics_report_influxdb_period = \"1s\"\nmetrics_report_influxdb_username = \"\"\nmetrics_report_influxdb_password = \"\"\nmetrics_report_influxdb_database = \"\"\n\n"
  },
  {
    "path": "deploy/root/opt/codis/etc/10.2.16.201_19000/proxy_admin",
    "content": "#!/usr/bin/env bash\n\nset -x\nset -e\n\n/opt/codis/bin/codis-admin --proxy=10.2.16.201:11080 $@\n"
  },
  {
    "path": "deploy/root/opt/codis/etc/10.2.16.201_19002/codis_proxy_19002.service",
    "content": "[Unit]\nDescription=Codis-[demo-beta]@19002\n[Service]\nExecStart=/opt/codis/bin/codis-proxy --ncpu=4 --max-ncpu=8 \\\n    --config=/opt/codis/etc/10.2.16.201:19002/proxy.toml --log=/opt/codis/log/10.2.16.201:19002/proxy.log --log-level=WARN\nRestart=always\n[Install]\nWantedBy=default.target\n\n"
  },
  {
    "path": "deploy/root/opt/codis/etc/10.2.16.201_19002/proxy.toml",
    "content": "##################################################\n#                                                #\n#                  Codis-Proxy                   #\n#                                                #\n##################################################\n\n# Set Codis Product Name/Auth.\nproduct_name = \"demo-beta\"\nproduct_auth = \"\"\n\n# Set bind address for admin(rpc), tcp only.\nadmin_addr = \"10.2.16.201:11082\"\n\n# Set bind address for proxy, proto_type can be \"tcp\", \"tcp4\", \"tcp6\", \"unix\" or \"unixpacket\".\nproto_type = \"tcp4\"\nproxy_addr = \"10.2.16.201:19002\"\n\n# Set jodis address & session timeout, only accept \"zookeeper\" & \"etcd\".\njodis_name = \"zookeeper\"\njodis_addr = \"10.4.10.101:2181,10.4.10.102:2181,10.4.10.103:2181,10.4.10.104:2181,10.4.10.105:2181\"\njodis_timeout = \"20s\"\njodis_compatible = false\n\n# Set datacenter of proxy.\nproxy_datacenter = \"dc2\"\n\n# Set max number of alive sessions.\nproxy_max_clients = 2000\n\n# Set max offheap memory size. (0 to disable)\nproxy_max_offheap_size = \"1024mb\"\n\n# Set heap placeholder to reduce GC frequency.\nproxy_heap_placeholder = \"256mb\"\n\n# Proxy will ping backend redis (and clear 'MASTERDOWN' state) in a predefined interval. (0 to disable)\nbackend_ping_period = \"5s\"\n\n# Set backend recv buffer size & timeout.\nbackend_recv_bufsize = \"128kb\"\nbackend_recv_timeout = \"30s\"\n\n# Set backend send buffer & timeout.\nbackend_send_bufsize = \"128kb\"\nbackend_send_timeout = \"30s\"\n\n# Set backend pipeline buffer size.\nbackend_max_pipeline = 1024\n\n# Set backend never read replica groups, default is false\nbackend_primary_only = false\n\n# Set backend parallel connections per server\nbackend_primary_parallel = 1\nbackend_replica_parallel = 1\n\n# Set backend tcp keepalive period. (0 to disable)\nbackend_keepalive_period = \"75s\"\n\n# Set number of databases of backend.\nbackend_number_databases = 16\n\n# If there is no request from client for a long time, the connection will be closed. (0 to disable)\n# Set session recv buffer size & timeout.\nsession_recv_bufsize = \"128kb\"\nsession_recv_timeout = \"30m\"\n\n# Set session send buffer size & timeout.\nsession_send_bufsize = \"64kb\"\nsession_send_timeout = \"30s\"\n\n# Make sure this is higher than the max number of requests for each pipeline request, or your client may be blocked.\n# Set session pipeline buffer size.\nsession_max_pipeline = 512\n\n# Set session tcp keepalive period. (0 to disable)\nsession_keepalive_period = \"75s\"\n\n# Set session to be sensitive to failures. Default is false, instead of closing socket, proxy will send an error response to client.\nsession_break_on_failure = false\n\n# Set metrics server (such as http://localhost:28000), proxy will report json formatted metrics to specified server in a predefined period.\nmetrics_report_server = \"\"\nmetrics_report_period = \"1s\"\n\n# Set influxdb server (such as http://localhost:8086), proxy will report metrics to influxdb.\nmetrics_report_influxdb_server = \"\"\nmetrics_report_influxdb_period = \"1s\"\nmetrics_report_influxdb_username = \"\"\nmetrics_report_influxdb_password = \"\"\nmetrics_report_influxdb_database = \"\"\n\n"
  },
  {
    "path": "deploy/root/opt/codis/etc/10.2.16.201_19002/proxy_admin",
    "content": "#!/usr/bin/env bash\n\nset -x\nset -e\n\n/opt/codis/bin/codis-admin --proxy=10.2.16.201:11082 $@\n"
  },
  {
    "path": "deploy/root/opt/codis/etc/10.2.16.202_19000/codis_proxy_19000.service",
    "content": "[Unit]\nDescription=Codis-[demo-beta]@19000\n[Service]\nExecStart=/opt/codis/bin/codis-proxy --ncpu=4 --max-ncpu=8 \\\n    --config=/opt/codis/etc/10.2.16.202:19000/proxy.toml --log=/opt/codis/log/10.2.16.202:19000/proxy.log --log-level=WARN\nRestart=always\n[Install]\nWantedBy=default.target\n\n"
  },
  {
    "path": "deploy/root/opt/codis/etc/10.2.16.202_19000/proxy.toml",
    "content": "##################################################\n#                                                #\n#                  Codis-Proxy                   #\n#                                                #\n##################################################\n\n# Set Codis Product Name/Auth.\nproduct_name = \"demo-beta\"\nproduct_auth = \"\"\n\n# Set bind address for admin(rpc), tcp only.\nadmin_addr = \"10.2.16.202:11080\"\n\n# Set bind address for proxy, proto_type can be \"tcp\", \"tcp4\", \"tcp6\", \"unix\" or \"unixpacket\".\nproto_type = \"tcp4\"\nproxy_addr = \"10.2.16.202:19000\"\n\n# Set jodis address & session timeout, only accept \"zookeeper\" & \"etcd\".\njodis_name = \"zookeeper\"\njodis_addr = \"10.4.10.101:2181,10.4.10.102:2181,10.4.10.103:2181,10.4.10.104:2181,10.4.10.105:2181\"\njodis_timeout = \"20s\"\njodis_compatible = false\n\n# Set datacenter of proxy.\nproxy_datacenter = \"dc2\"\n\n# Set max number of alive sessions.\nproxy_max_clients = 2000\n\n# Set max offheap memory size. (0 to disable)\nproxy_max_offheap_size = \"1024mb\"\n\n# Set heap placeholder to reduce GC frequency.\nproxy_heap_placeholder = \"256mb\"\n\n# Proxy will ping backend redis (and clear 'MASTERDOWN' state) in a predefined interval. (0 to disable)\nbackend_ping_period = \"5s\"\n\n# Set backend recv buffer size & timeout.\nbackend_recv_bufsize = \"128kb\"\nbackend_recv_timeout = \"30s\"\n\n# Set backend send buffer & timeout.\nbackend_send_bufsize = \"128kb\"\nbackend_send_timeout = \"30s\"\n\n# Set backend pipeline buffer size.\nbackend_max_pipeline = 1024\n\n# Set backend never read replica groups, default is false\nbackend_primary_only = false\n\n# Set backend parallel connections per server\nbackend_primary_parallel = 1\nbackend_replica_parallel = 1\n\n# Set backend tcp keepalive period. (0 to disable)\nbackend_keepalive_period = \"75s\"\n\n# Set number of databases of backend.\nbackend_number_databases = 16\n\n# If there is no request from client for a long time, the connection will be closed. (0 to disable)\n# Set session recv buffer size & timeout.\nsession_recv_bufsize = \"128kb\"\nsession_recv_timeout = \"30m\"\n\n# Set session send buffer size & timeout.\nsession_send_bufsize = \"64kb\"\nsession_send_timeout = \"30s\"\n\n# Make sure this is higher than the max number of requests for each pipeline request, or your client may be blocked.\n# Set session pipeline buffer size.\nsession_max_pipeline = 512\n\n# Set session tcp keepalive period. (0 to disable)\nsession_keepalive_period = \"75s\"\n\n# Set session to be sensitive to failures. Default is false, instead of closing socket, proxy will send an error response to client.\nsession_break_on_failure = false\n\n# Set metrics server (such as http://localhost:28000), proxy will report json formatted metrics to specified server in a predefined period.\nmetrics_report_server = \"\"\nmetrics_report_period = \"1s\"\n\n# Set influxdb server (such as http://localhost:8086), proxy will report metrics to influxdb.\nmetrics_report_influxdb_server = \"\"\nmetrics_report_influxdb_period = \"1s\"\nmetrics_report_influxdb_username = \"\"\nmetrics_report_influxdb_password = \"\"\nmetrics_report_influxdb_database = \"\"\n\n"
  },
  {
    "path": "deploy/root/opt/codis/etc/10.2.16.202_19000/proxy_admin",
    "content": "#!/usr/bin/env bash\n\nset -x\nset -e\n\n/opt/codis/bin/codis-admin --proxy=10.2.16.202:11080 $@\n"
  },
  {
    "path": "deploy/root/opt/codis/etc/10.2.16.202_19002/codis_proxy_19002.service",
    "content": "[Unit]\nDescription=Codis-[demo-beta]@19002\n[Service]\nExecStart=/opt/codis/bin/codis-proxy --ncpu=4 --max-ncpu=8 \\\n    --config=/opt/codis/etc/10.2.16.202:19002/proxy.toml --log=/opt/codis/log/10.2.16.202:19002/proxy.log --log-level=WARN\nRestart=always\n[Install]\nWantedBy=default.target\n\n"
  },
  {
    "path": "deploy/root/opt/codis/etc/10.2.16.202_19002/proxy.toml",
    "content": "##################################################\n#                                                #\n#                  Codis-Proxy                   #\n#                                                #\n##################################################\n\n# Set Codis Product Name/Auth.\nproduct_name = \"demo-beta\"\nproduct_auth = \"\"\n\n# Set bind address for admin(rpc), tcp only.\nadmin_addr = \"10.2.16.202:11082\"\n\n# Set bind address for proxy, proto_type can be \"tcp\", \"tcp4\", \"tcp6\", \"unix\" or \"unixpacket\".\nproto_type = \"tcp4\"\nproxy_addr = \"10.2.16.202:19002\"\n\n# Set jodis address & session timeout, only accept \"zookeeper\" & \"etcd\".\njodis_name = \"zookeeper\"\njodis_addr = \"10.4.10.101:2181,10.4.10.102:2181,10.4.10.103:2181,10.4.10.104:2181,10.4.10.105:2181\"\njodis_timeout = \"20s\"\njodis_compatible = false\n\n# Set datacenter of proxy.\nproxy_datacenter = \"dc2\"\n\n# Set max number of alive sessions.\nproxy_max_clients = 2000\n\n# Set max offheap memory size. (0 to disable)\nproxy_max_offheap_size = \"1024mb\"\n\n# Set heap placeholder to reduce GC frequency.\nproxy_heap_placeholder = \"256mb\"\n\n# Proxy will ping backend redis (and clear 'MASTERDOWN' state) in a predefined interval. (0 to disable)\nbackend_ping_period = \"5s\"\n\n# Set backend recv buffer size & timeout.\nbackend_recv_bufsize = \"128kb\"\nbackend_recv_timeout = \"30s\"\n\n# Set backend send buffer & timeout.\nbackend_send_bufsize = \"128kb\"\nbackend_send_timeout = \"30s\"\n\n# Set backend pipeline buffer size.\nbackend_max_pipeline = 1024\n\n# Set backend never read replica groups, default is false\nbackend_primary_only = false\n\n# Set backend parallel connections per server\nbackend_primary_parallel = 1\nbackend_replica_parallel = 1\n\n# Set backend tcp keepalive period. (0 to disable)\nbackend_keepalive_period = \"75s\"\n\n# Set number of databases of backend.\nbackend_number_databases = 16\n\n# If there is no request from client for a long time, the connection will be closed. (0 to disable)\n# Set session recv buffer size & timeout.\nsession_recv_bufsize = \"128kb\"\nsession_recv_timeout = \"30m\"\n\n# Set session send buffer size & timeout.\nsession_send_bufsize = \"64kb\"\nsession_send_timeout = \"30s\"\n\n# Make sure this is higher than the max number of requests for each pipeline request, or your client may be blocked.\n# Set session pipeline buffer size.\nsession_max_pipeline = 512\n\n# Set session tcp keepalive period. (0 to disable)\nsession_keepalive_period = \"75s\"\n\n# Set session to be sensitive to failures. Default is false, instead of closing socket, proxy will send an error response to client.\nsession_break_on_failure = false\n\n# Set metrics server (such as http://localhost:28000), proxy will report json formatted metrics to specified server in a predefined period.\nmetrics_report_server = \"\"\nmetrics_report_period = \"1s\"\n\n# Set influxdb server (such as http://localhost:8086), proxy will report metrics to influxdb.\nmetrics_report_influxdb_server = \"\"\nmetrics_report_influxdb_period = \"1s\"\nmetrics_report_influxdb_username = \"\"\nmetrics_report_influxdb_password = \"\"\nmetrics_report_influxdb_database = \"\"\n\n"
  },
  {
    "path": "deploy/root/opt/codis/etc/10.2.16.202_19002/proxy_admin",
    "content": "#!/usr/bin/env bash\n\nset -x\nset -e\n\n/opt/codis/bin/codis-admin --proxy=10.2.16.202:11082 $@\n"
  },
  {
    "path": "deploy/root/opt/codis/etc/10.4.10.100_18080/codis_dashboard_18080.service",
    "content": "[Unit]\nDescription=Codis-[demo-beta]@18080\n[Service]\nExecStart=/opt/codis/bin/codis-dashboard \\\n    --config=/opt/codis/etc/10.4.10.100:18080/dashboard.toml --log=/opt/codis/log/10.4.10.100:18080/dashboard.log\nRestart=always\n[Install]\nWantedBy=default.target\n\n"
  },
  {
    "path": "deploy/root/opt/codis/etc/10.4.10.100_18080/dashboard.toml",
    "content": "##################################################\n#                                                #\n#                  Codis-Dashboard               #\n#                                                #\n##################################################\n\n# Set Coordinator, only accept \"zookeeper\" & \"etcd\".\ncoordinator_name = \"zookeeper\"\ncoordinator_addr = \"10.4.10.101:2181,10.4.10.102:2181,10.4.10.103:2181,10.4.10.104:2181,10.4.10.105:2181\"\n\n# Set Codis Product Name/Auth.\nproduct_name = \"demo-beta\"\nproduct_auth = \"\"\n\n# Set bind address for admin(rpc), tcp only.\nadmin_addr = \"10.4.10.100:18080\"\n\n# Set arguments for data migration (only accept 'sync' & 'semi-async').\nmigration_method = \"semi-async\"\nmigration_async_maxbulks = 200\nmigration_async_maxbytes = \"32mb\"\nmigration_async_numkeys = 100\nmigration_timeout = \"30s\"\n\n# Set configs for redis sentinel.\nsentinel_quorum = 2\nsentinel_parallel_syncs = 1\nsentinel_down_after = \"10s\"\nsentinel_failover_timeout = \"5m\"\nsentinel_notification_script = \"\"\nsentinel_client_reconfig_script = \"\"\n\n"
  },
  {
    "path": "deploy/root/opt/codis/etc/10.4.10.100_18080/dashboard_admin",
    "content": "#!/usr/bin/env bash\n\nset -x\nset -e\n\n/opt/codis/bin/codis-admin --dashboard=10.4.10.100:18080 $@\n"
  },
  {
    "path": "deploy/root/opt/codis/etc/10.4.10.100_18080/foreach_proxy",
    "content": "#!/usr/bin/env bash\n\nset -x\nset -e\n\nd=1\nsleep $d; /opt/codis/bin/codis-admin --proxy=10.4.10.200:11080 $@\nsleep $d; /opt/codis/bin/codis-admin --proxy=10.4.10.200:11082 $@\nsleep $d; /opt/codis/bin/codis-admin --proxy=10.4.10.201:11080 $@\nsleep $d; /opt/codis/bin/codis-admin --proxy=10.4.10.201:11082 $@\nsleep $d; /opt/codis/bin/codis-admin --proxy=10.2.16.200:11080 $@\nsleep $d; /opt/codis/bin/codis-admin --proxy=10.2.16.200:11082 $@\nsleep $d; /opt/codis/bin/codis-admin --proxy=10.2.16.201:11080 $@\nsleep $d; /opt/codis/bin/codis-admin --proxy=10.2.16.201:11082 $@\nsleep $d; /opt/codis/bin/codis-admin --proxy=10.2.16.202:11080 $@\nsleep $d; /opt/codis/bin/codis-admin --proxy=10.2.16.202:11082 $@\n\n"
  },
  {
    "path": "deploy/root/opt/codis/etc/10.4.10.100_18080/foreach_proxy_online",
    "content": "#!/usr/bin/env bash\n\nset -x\nset -e\n\nd=1\nsleep $d; /opt/codis/bin/codis-admin --dashboard=10.4.10.100:18080 --online-proxy --addr=10.4.10.200:11080\nsleep $d; /opt/codis/bin/codis-admin --dashboard=10.4.10.100:18080 --online-proxy --addr=10.4.10.200:11082\nsleep $d; /opt/codis/bin/codis-admin --dashboard=10.4.10.100:18080 --online-proxy --addr=10.4.10.201:11080\nsleep $d; /opt/codis/bin/codis-admin --dashboard=10.4.10.100:18080 --online-proxy --addr=10.4.10.201:11082\nsleep $d; /opt/codis/bin/codis-admin --dashboard=10.4.10.100:18080 --online-proxy --addr=10.2.16.200:11080\nsleep $d; /opt/codis/bin/codis-admin --dashboard=10.4.10.100:18080 --online-proxy --addr=10.2.16.200:11082\nsleep $d; /opt/codis/bin/codis-admin --dashboard=10.4.10.100:18080 --online-proxy --addr=10.2.16.201:11080\nsleep $d; /opt/codis/bin/codis-admin --dashboard=10.4.10.100:18080 --online-proxy --addr=10.2.16.201:11082\nsleep $d; /opt/codis/bin/codis-admin --dashboard=10.4.10.100:18080 --online-proxy --addr=10.2.16.202:11080\nsleep $d; /opt/codis/bin/codis-admin --dashboard=10.4.10.100:18080 --online-proxy --addr=10.2.16.202:11082\n\n"
  },
  {
    "path": "deploy/root/opt/codis/etc/10.4.10.100_18080/foreach_proxy_reinit",
    "content": "#!/usr/bin/env bash\n\nset -x\nset -e\n\nd=1\nsleep $d; /opt/codis/bin/codis-admin --dashboard=10.4.10.100:18080 --reinit-proxy --addr=10.4.10.200:11080\nsleep $d; /opt/codis/bin/codis-admin --dashboard=10.4.10.100:18080 --reinit-proxy --addr=10.4.10.200:11082\nsleep $d; /opt/codis/bin/codis-admin --dashboard=10.4.10.100:18080 --reinit-proxy --addr=10.4.10.201:11080\nsleep $d; /opt/codis/bin/codis-admin --dashboard=10.4.10.100:18080 --reinit-proxy --addr=10.4.10.201:11082\nsleep $d; /opt/codis/bin/codis-admin --dashboard=10.4.10.100:18080 --reinit-proxy --addr=10.2.16.200:11080\nsleep $d; /opt/codis/bin/codis-admin --dashboard=10.4.10.100:18080 --reinit-proxy --addr=10.2.16.200:11082\nsleep $d; /opt/codis/bin/codis-admin --dashboard=10.4.10.100:18080 --reinit-proxy --addr=10.2.16.201:11080\nsleep $d; /opt/codis/bin/codis-admin --dashboard=10.4.10.100:18080 --reinit-proxy --addr=10.2.16.201:11082\nsleep $d; /opt/codis/bin/codis-admin --dashboard=10.4.10.100:18080 --reinit-proxy --addr=10.2.16.202:11080\nsleep $d; /opt/codis/bin/codis-admin --dashboard=10.4.10.100:18080 --reinit-proxy --addr=10.2.16.202:11082\n\n"
  },
  {
    "path": "deploy/root/opt/codis/etc/10.4.10.200_19000/codis_proxy_19000.service",
    "content": "[Unit]\nDescription=Codis-[demo-beta]@19000\n[Service]\nExecStart=/opt/codis/bin/codis-proxy --ncpu=4 --max-ncpu=8 \\\n    --config=/opt/codis/etc/10.4.10.200:19000/proxy.toml --log=/opt/codis/log/10.4.10.200:19000/proxy.log --log-level=WARN\nRestart=always\n[Install]\nWantedBy=default.target\n\n"
  },
  {
    "path": "deploy/root/opt/codis/etc/10.4.10.200_19000/proxy.toml",
    "content": "##################################################\n#                                                #\n#                  Codis-Proxy                   #\n#                                                #\n##################################################\n\n# Set Codis Product Name/Auth.\nproduct_name = \"demo-beta\"\nproduct_auth = \"\"\n\n# Set bind address for admin(rpc), tcp only.\nadmin_addr = \"10.4.10.200:11080\"\n\n# Set bind address for proxy, proto_type can be \"tcp\", \"tcp4\", \"tcp6\", \"unix\" or \"unixpacket\".\nproto_type = \"tcp4\"\nproxy_addr = \"10.4.10.200:19000\"\n\n# Set jodis address & session timeout, only accept \"zookeeper\" & \"etcd\".\njodis_name = \"zookeeper\"\njodis_addr = \"10.4.10.101:2181,10.4.10.102:2181,10.4.10.103:2181,10.4.10.104:2181,10.4.10.105:2181\"\njodis_timeout = \"20s\"\njodis_compatible = false\n\n# Set datacenter of proxy.\nproxy_datacenter = \"dc1\"\n\n# Set max number of alive sessions.\nproxy_max_clients = 2000\n\n# Set max offheap memory size. (0 to disable)\nproxy_max_offheap_size = \"1024mb\"\n\n# Set heap placeholder to reduce GC frequency.\nproxy_heap_placeholder = \"256mb\"\n\n# Proxy will ping backend redis (and clear 'MASTERDOWN' state) in a predefined interval. (0 to disable)\nbackend_ping_period = \"5s\"\n\n# Set backend recv buffer size & timeout.\nbackend_recv_bufsize = \"128kb\"\nbackend_recv_timeout = \"30s\"\n\n# Set backend send buffer & timeout.\nbackend_send_bufsize = \"128kb\"\nbackend_send_timeout = \"30s\"\n\n# Set backend pipeline buffer size.\nbackend_max_pipeline = 1024\n\n# Set backend never read replica groups, default is false\nbackend_primary_only = false\n\n# Set backend parallel connections per server\nbackend_primary_parallel = 1\nbackend_replica_parallel = 1\n\n# Set backend tcp keepalive period. (0 to disable)\nbackend_keepalive_period = \"75s\"\n\n# Set number of databases of backend.\nbackend_number_databases = 16\n\n# If there is no request from client for a long time, the connection will be closed. (0 to disable)\n# Set session recv buffer size & timeout.\nsession_recv_bufsize = \"128kb\"\nsession_recv_timeout = \"30m\"\n\n# Set session send buffer size & timeout.\nsession_send_bufsize = \"64kb\"\nsession_send_timeout = \"30s\"\n\n# Make sure this is higher than the max number of requests for each pipeline request, or your client may be blocked.\n# Set session pipeline buffer size.\nsession_max_pipeline = 512\n\n# Set session tcp keepalive period. (0 to disable)\nsession_keepalive_period = \"75s\"\n\n# Set session to be sensitive to failures. Default is false, instead of closing socket, proxy will send an error response to client.\nsession_break_on_failure = false\n\n# Set metrics server (such as http://localhost:28000), proxy will report json formatted metrics to specified server in a predefined period.\nmetrics_report_server = \"\"\nmetrics_report_period = \"1s\"\n\n# Set influxdb server (such as http://localhost:8086), proxy will report metrics to influxdb.\nmetrics_report_influxdb_server = \"\"\nmetrics_report_influxdb_period = \"1s\"\nmetrics_report_influxdb_username = \"\"\nmetrics_report_influxdb_password = \"\"\nmetrics_report_influxdb_database = \"\"\n\n"
  },
  {
    "path": "deploy/root/opt/codis/etc/10.4.10.200_19000/proxy_admin",
    "content": "#!/usr/bin/env bash\n\nset -x\nset -e\n\n/opt/codis/bin/codis-admin --proxy=10.4.10.200:11080 $@\n"
  },
  {
    "path": "deploy/root/opt/codis/etc/10.4.10.200_19002/codis_proxy_19002.service",
    "content": "[Unit]\nDescription=Codis-[demo-beta]@19002\n[Service]\nExecStart=/opt/codis/bin/codis-proxy --ncpu=4 --max-ncpu=8 \\\n    --config=/opt/codis/etc/10.4.10.200:19002/proxy.toml --log=/opt/codis/log/10.4.10.200:19002/proxy.log --log-level=WARN\nRestart=always\n[Install]\nWantedBy=default.target\n\n"
  },
  {
    "path": "deploy/root/opt/codis/etc/10.4.10.200_19002/proxy.toml",
    "content": "##################################################\n#                                                #\n#                  Codis-Proxy                   #\n#                                                #\n##################################################\n\n# Set Codis Product Name/Auth.\nproduct_name = \"demo-beta\"\nproduct_auth = \"\"\n\n# Set bind address for admin(rpc), tcp only.\nadmin_addr = \"10.4.10.200:11082\"\n\n# Set bind address for proxy, proto_type can be \"tcp\", \"tcp4\", \"tcp6\", \"unix\" or \"unixpacket\".\nproto_type = \"tcp4\"\nproxy_addr = \"10.4.10.200:19002\"\n\n# Set jodis address & session timeout, only accept \"zookeeper\" & \"etcd\".\njodis_name = \"zookeeper\"\njodis_addr = \"10.4.10.101:2181,10.4.10.102:2181,10.4.10.103:2181,10.4.10.104:2181,10.4.10.105:2181\"\njodis_timeout = \"20s\"\njodis_compatible = false\n\n# Set datacenter of proxy.\nproxy_datacenter = \"dc1\"\n\n# Set max number of alive sessions.\nproxy_max_clients = 2000\n\n# Set max offheap memory size. (0 to disable)\nproxy_max_offheap_size = \"1024mb\"\n\n# Set heap placeholder to reduce GC frequency.\nproxy_heap_placeholder = \"256mb\"\n\n# Proxy will ping backend redis (and clear 'MASTERDOWN' state) in a predefined interval. (0 to disable)\nbackend_ping_period = \"5s\"\n\n# Set backend recv buffer size & timeout.\nbackend_recv_bufsize = \"128kb\"\nbackend_recv_timeout = \"30s\"\n\n# Set backend send buffer & timeout.\nbackend_send_bufsize = \"128kb\"\nbackend_send_timeout = \"30s\"\n\n# Set backend pipeline buffer size.\nbackend_max_pipeline = 1024\n\n# Set backend never read replica groups, default is false\nbackend_primary_only = false\n\n# Set backend parallel connections per server\nbackend_primary_parallel = 1\nbackend_replica_parallel = 1\n\n# Set backend tcp keepalive period. (0 to disable)\nbackend_keepalive_period = \"75s\"\n\n# Set number of databases of backend.\nbackend_number_databases = 16\n\n# If there is no request from client for a long time, the connection will be closed. (0 to disable)\n# Set session recv buffer size & timeout.\nsession_recv_bufsize = \"128kb\"\nsession_recv_timeout = \"30m\"\n\n# Set session send buffer size & timeout.\nsession_send_bufsize = \"64kb\"\nsession_send_timeout = \"30s\"\n\n# Make sure this is higher than the max number of requests for each pipeline request, or your client may be blocked.\n# Set session pipeline buffer size.\nsession_max_pipeline = 512\n\n# Set session tcp keepalive period. (0 to disable)\nsession_keepalive_period = \"75s\"\n\n# Set session to be sensitive to failures. Default is false, instead of closing socket, proxy will send an error response to client.\nsession_break_on_failure = false\n\n# Set metrics server (such as http://localhost:28000), proxy will report json formatted metrics to specified server in a predefined period.\nmetrics_report_server = \"\"\nmetrics_report_period = \"1s\"\n\n# Set influxdb server (such as http://localhost:8086), proxy will report metrics to influxdb.\nmetrics_report_influxdb_server = \"\"\nmetrics_report_influxdb_period = \"1s\"\nmetrics_report_influxdb_username = \"\"\nmetrics_report_influxdb_password = \"\"\nmetrics_report_influxdb_database = \"\"\n\n"
  },
  {
    "path": "deploy/root/opt/codis/etc/10.4.10.200_19002/proxy_admin",
    "content": "#!/usr/bin/env bash\n\nset -x\nset -e\n\n/opt/codis/bin/codis-admin --proxy=10.4.10.200:11082 $@\n"
  },
  {
    "path": "deploy/root/opt/codis/etc/10.4.10.201_19000/codis_proxy_19000.service",
    "content": "[Unit]\nDescription=Codis-[demo-beta]@19000\n[Service]\nExecStart=/opt/codis/bin/codis-proxy --ncpu=4 --max-ncpu=8 \\\n    --config=/opt/codis/etc/10.4.10.201:19000/proxy.toml --log=/opt/codis/log/10.4.10.201:19000/proxy.log --log-level=WARN\nRestart=always\n[Install]\nWantedBy=default.target\n\n"
  },
  {
    "path": "deploy/root/opt/codis/etc/10.4.10.201_19000/proxy.toml",
    "content": "##################################################\n#                                                #\n#                  Codis-Proxy                   #\n#                                                #\n##################################################\n\n# Set Codis Product Name/Auth.\nproduct_name = \"demo-beta\"\nproduct_auth = \"\"\n\n# Set bind address for admin(rpc), tcp only.\nadmin_addr = \"10.4.10.201:11080\"\n\n# Set bind address for proxy, proto_type can be \"tcp\", \"tcp4\", \"tcp6\", \"unix\" or \"unixpacket\".\nproto_type = \"tcp4\"\nproxy_addr = \"10.4.10.201:19000\"\n\n# Set jodis address & session timeout, only accept \"zookeeper\" & \"etcd\".\njodis_name = \"zookeeper\"\njodis_addr = \"10.4.10.101:2181,10.4.10.102:2181,10.4.10.103:2181,10.4.10.104:2181,10.4.10.105:2181\"\njodis_timeout = \"20s\"\njodis_compatible = false\n\n# Set datacenter of proxy.\nproxy_datacenter = \"dc1\"\n\n# Set max number of alive sessions.\nproxy_max_clients = 2000\n\n# Set max offheap memory size. (0 to disable)\nproxy_max_offheap_size = \"1024mb\"\n\n# Set heap placeholder to reduce GC frequency.\nproxy_heap_placeholder = \"256mb\"\n\n# Proxy will ping backend redis (and clear 'MASTERDOWN' state) in a predefined interval. (0 to disable)\nbackend_ping_period = \"5s\"\n\n# Set backend recv buffer size & timeout.\nbackend_recv_bufsize = \"128kb\"\nbackend_recv_timeout = \"30s\"\n\n# Set backend send buffer & timeout.\nbackend_send_bufsize = \"128kb\"\nbackend_send_timeout = \"30s\"\n\n# Set backend pipeline buffer size.\nbackend_max_pipeline = 1024\n\n# Set backend never read replica groups, default is false\nbackend_primary_only = false\n\n# Set backend parallel connections per server\nbackend_primary_parallel = 1\nbackend_replica_parallel = 1\n\n# Set backend tcp keepalive period. (0 to disable)\nbackend_keepalive_period = \"75s\"\n\n# Set number of databases of backend.\nbackend_number_databases = 16\n\n# If there is no request from client for a long time, the connection will be closed. (0 to disable)\n# Set session recv buffer size & timeout.\nsession_recv_bufsize = \"128kb\"\nsession_recv_timeout = \"30m\"\n\n# Set session send buffer size & timeout.\nsession_send_bufsize = \"64kb\"\nsession_send_timeout = \"30s\"\n\n# Make sure this is higher than the max number of requests for each pipeline request, or your client may be blocked.\n# Set session pipeline buffer size.\nsession_max_pipeline = 512\n\n# Set session tcp keepalive period. (0 to disable)\nsession_keepalive_period = \"75s\"\n\n# Set session to be sensitive to failures. Default is false, instead of closing socket, proxy will send an error response to client.\nsession_break_on_failure = false\n\n# Set metrics server (such as http://localhost:28000), proxy will report json formatted metrics to specified server in a predefined period.\nmetrics_report_server = \"\"\nmetrics_report_period = \"1s\"\n\n# Set influxdb server (such as http://localhost:8086), proxy will report metrics to influxdb.\nmetrics_report_influxdb_server = \"\"\nmetrics_report_influxdb_period = \"1s\"\nmetrics_report_influxdb_username = \"\"\nmetrics_report_influxdb_password = \"\"\nmetrics_report_influxdb_database = \"\"\n\n"
  },
  {
    "path": "deploy/root/opt/codis/etc/10.4.10.201_19000/proxy_admin",
    "content": "#!/usr/bin/env bash\n\nset -x\nset -e\n\n/opt/codis/bin/codis-admin --proxy=10.4.10.201:11080 $@\n"
  },
  {
    "path": "deploy/root/opt/codis/etc/10.4.10.201_19002/codis_proxy_19002.service",
    "content": "[Unit]\nDescription=Codis-[demo-beta]@19002\n[Service]\nExecStart=/opt/codis/bin/codis-proxy --ncpu=4 --max-ncpu=8 \\\n    --config=/opt/codis/etc/10.4.10.201:19002/proxy.toml --log=/opt/codis/log/10.4.10.201:19002/proxy.log --log-level=WARN\nRestart=always\n[Install]\nWantedBy=default.target\n\n"
  },
  {
    "path": "deploy/root/opt/codis/etc/10.4.10.201_19002/proxy.toml",
    "content": "##################################################\n#                                                #\n#                  Codis-Proxy                   #\n#                                                #\n##################################################\n\n# Set Codis Product Name/Auth.\nproduct_name = \"demo-beta\"\nproduct_auth = \"\"\n\n# Set bind address for admin(rpc), tcp only.\nadmin_addr = \"10.4.10.201:11082\"\n\n# Set bind address for proxy, proto_type can be \"tcp\", \"tcp4\", \"tcp6\", \"unix\" or \"unixpacket\".\nproto_type = \"tcp4\"\nproxy_addr = \"10.4.10.201:19002\"\n\n# Set jodis address & session timeout, only accept \"zookeeper\" & \"etcd\".\njodis_name = \"zookeeper\"\njodis_addr = \"10.4.10.101:2181,10.4.10.102:2181,10.4.10.103:2181,10.4.10.104:2181,10.4.10.105:2181\"\njodis_timeout = \"20s\"\njodis_compatible = false\n\n# Set datacenter of proxy.\nproxy_datacenter = \"dc1\"\n\n# Set max number of alive sessions.\nproxy_max_clients = 2000\n\n# Set max offheap memory size. (0 to disable)\nproxy_max_offheap_size = \"1024mb\"\n\n# Set heap placeholder to reduce GC frequency.\nproxy_heap_placeholder = \"256mb\"\n\n# Proxy will ping backend redis (and clear 'MASTERDOWN' state) in a predefined interval. (0 to disable)\nbackend_ping_period = \"5s\"\n\n# Set backend recv buffer size & timeout.\nbackend_recv_bufsize = \"128kb\"\nbackend_recv_timeout = \"30s\"\n\n# Set backend send buffer & timeout.\nbackend_send_bufsize = \"128kb\"\nbackend_send_timeout = \"30s\"\n\n# Set backend pipeline buffer size.\nbackend_max_pipeline = 1024\n\n# Set backend never read replica groups, default is false\nbackend_primary_only = false\n\n# Set backend parallel connections per server\nbackend_primary_parallel = 1\nbackend_replica_parallel = 1\n\n# Set backend tcp keepalive period. (0 to disable)\nbackend_keepalive_period = \"75s\"\n\n# Set number of databases of backend.\nbackend_number_databases = 16\n\n# If there is no request from client for a long time, the connection will be closed. (0 to disable)\n# Set session recv buffer size & timeout.\nsession_recv_bufsize = \"128kb\"\nsession_recv_timeout = \"30m\"\n\n# Set session send buffer size & timeout.\nsession_send_bufsize = \"64kb\"\nsession_send_timeout = \"30s\"\n\n# Make sure this is higher than the max number of requests for each pipeline request, or your client may be blocked.\n# Set session pipeline buffer size.\nsession_max_pipeline = 512\n\n# Set session tcp keepalive period. (0 to disable)\nsession_keepalive_period = \"75s\"\n\n# Set session to be sensitive to failures. Default is false, instead of closing socket, proxy will send an error response to client.\nsession_break_on_failure = false\n\n# Set metrics server (such as http://localhost:28000), proxy will report json formatted metrics to specified server in a predefined period.\nmetrics_report_server = \"\"\nmetrics_report_period = \"1s\"\n\n# Set influxdb server (such as http://localhost:8086), proxy will report metrics to influxdb.\nmetrics_report_influxdb_server = \"\"\nmetrics_report_influxdb_period = \"1s\"\nmetrics_report_influxdb_username = \"\"\nmetrics_report_influxdb_password = \"\"\nmetrics_report_influxdb_database = \"\"\n\n"
  },
  {
    "path": "deploy/root/opt/codis/etc/10.4.10.201_19002/proxy_admin",
    "content": "#!/usr/bin/env bash\n\nset -x\nset -e\n\n/opt/codis/bin/codis-admin --proxy=10.4.10.201:11082 $@\n"
  },
  {
    "path": "deploy/root/opt/codis/etc/127.0.0.1_18080/codis_dashboard_18080.service",
    "content": "[Unit]\nDescription=Codis-[demo-alpha]@18080\n[Service]\nExecStart=/opt/codis/bin/codis-dashboard \\\n    --config=/opt/codis/etc/127.0.0.1:18080/dashboard.toml --log=/opt/codis/log/127.0.0.1:18080/dashboard.log\nRestart=always\n[Install]\nWantedBy=default.target\n\n"
  },
  {
    "path": "deploy/root/opt/codis/etc/127.0.0.1_18080/dashboard.toml",
    "content": "##################################################\n#                                                #\n#                  Codis-Dashboard               #\n#                                                #\n##################################################\n\n# Set Coordinator, only accept \"zookeeper\" & \"etcd\".\ncoordinator_name = \"etcd\"\ncoordinator_addr = \"127.0.0.1:2379\"\n\n# Set Codis Product Name/Auth.\nproduct_name = \"demo-alpha\"\nproduct_auth = \"\"\n\n# Set bind address for admin(rpc), tcp only.\nadmin_addr = \"127.0.0.1:18080\"\n\n# Set arguments for data migration (only accept 'sync' & 'semi-async').\nmigration_method = \"semi-async\"\nmigration_async_maxbulks = 200\nmigration_async_maxbytes = \"32mb\"\nmigration_async_numkeys = 100\nmigration_timeout = \"30s\"\n\n# Set configs for redis sentinel.\nsentinel_quorum = 2\nsentinel_parallel_syncs = 1\nsentinel_down_after = \"10s\"\nsentinel_failover_timeout = \"5m\"\nsentinel_notification_script = \"\"\nsentinel_client_reconfig_script = \"\"\n\n"
  },
  {
    "path": "deploy/root/opt/codis/etc/127.0.0.1_18080/dashboard_admin",
    "content": "#!/usr/bin/env bash\n\nset -x\nset -e\n\n/opt/codis/bin/codis-admin --dashboard=127.0.0.1:18080 $@\n"
  },
  {
    "path": "deploy/root/opt/codis/etc/127.0.0.1_18080/foreach_proxy",
    "content": "#!/usr/bin/env bash\n\nset -x\nset -e\n\nd=1\nsleep $d; /opt/codis/bin/codis-admin --proxy=127.0.0.1:11080 $@\nsleep $d; /opt/codis/bin/codis-admin --proxy=127.0.0.1:11081 $@\nsleep $d; /opt/codis/bin/codis-admin --proxy=127.0.0.1:11082 $@\n\n"
  },
  {
    "path": "deploy/root/opt/codis/etc/127.0.0.1_18080/foreach_proxy_online",
    "content": "#!/usr/bin/env bash\n\nset -x\nset -e\n\nd=1\nsleep $d; /opt/codis/bin/codis-admin --dashboard=127.0.0.1:18080 --online-proxy --addr=127.0.0.1:11080\nsleep $d; /opt/codis/bin/codis-admin --dashboard=127.0.0.1:18080 --online-proxy --addr=127.0.0.1:11081\nsleep $d; /opt/codis/bin/codis-admin --dashboard=127.0.0.1:18080 --online-proxy --addr=127.0.0.1:11082\n\n"
  },
  {
    "path": "deploy/root/opt/codis/etc/127.0.0.1_18080/foreach_proxy_reinit",
    "content": "#!/usr/bin/env bash\n\nset -x\nset -e\n\nd=1\nsleep $d; /opt/codis/bin/codis-admin --dashboard=127.0.0.1:18080 --reinit-proxy --addr=127.0.0.1:11080\nsleep $d; /opt/codis/bin/codis-admin --dashboard=127.0.0.1:18080 --reinit-proxy --addr=127.0.0.1:11081\nsleep $d; /opt/codis/bin/codis-admin --dashboard=127.0.0.1:18080 --reinit-proxy --addr=127.0.0.1:11082\n\n"
  },
  {
    "path": "deploy/root/opt/codis/etc/127.0.0.1_19000/codis_proxy_19000.service",
    "content": "[Unit]\nDescription=Codis-[demo-alpha]@19000\n[Service]\nExecStart=/opt/codis/bin/codis-proxy --ncpu=4 --max-ncpu=8 \\\n    --config=/opt/codis/etc/127.0.0.1:19000/proxy.toml --log=/opt/codis/log/127.0.0.1:19000/proxy.log --log-level=INFO\nRestart=always\n[Install]\nWantedBy=default.target\n\n"
  },
  {
    "path": "deploy/root/opt/codis/etc/127.0.0.1_19000/proxy.toml",
    "content": "##################################################\n#                                                #\n#                  Codis-Proxy                   #\n#                                                #\n##################################################\n\n# Set Codis Product Name/Auth.\nproduct_name = \"demo-alpha\"\nproduct_auth = \"\"\n\n# Set bind address for admin(rpc), tcp only.\nadmin_addr = \"127.0.0.1:11080\"\n\n# Set bind address for proxy, proto_type can be \"tcp\", \"tcp4\", \"tcp6\", \"unix\" or \"unixpacket\".\nproto_type = \"tcp4\"\nproxy_addr = \"127.0.0.1:19000\"\n\n# Set jodis address & session timeout, only accept \"zookeeper\" & \"etcd\".\njodis_name = \"\"\njodis_addr = \"\"\njodis_timeout = \"20s\"\njodis_compatible = false\n\n# Set datacenter of proxy.\nproxy_datacenter = \"\"\n\n# Set max number of alive sessions.\nproxy_max_clients = 10000\n\n# Set max offheap memory size. (0 to disable)\nproxy_max_offheap_size = \"1024mb\"\n\n# Set heap placeholder to reduce GC frequency.\nproxy_heap_placeholder = \"256mb\"\n\n# Proxy will ping backend redis (and clear 'MASTERDOWN' state) in a predefined interval. (0 to disable)\nbackend_ping_period = \"5s\"\n\n# Set backend recv buffer size & timeout.\nbackend_recv_bufsize = \"128kb\"\nbackend_recv_timeout = \"30s\"\n\n# Set backend send buffer & timeout.\nbackend_send_bufsize = \"128kb\"\nbackend_send_timeout = \"30s\"\n\n# Set backend pipeline buffer size.\nbackend_max_pipeline = 1024\n\n# Set backend never read replica groups, default is false\nbackend_primary_only = false\n\n# Set backend parallel connections per server\nbackend_primary_parallel = 1\nbackend_replica_parallel = 1\n\n# Set backend tcp keepalive period. (0 to disable)\nbackend_keepalive_period = \"75s\"\n\n# Set number of databases of backend.\nbackend_number_databases = 16\n\n# If there is no request from client for a long time, the connection will be closed. (0 to disable)\n# Set session recv buffer size & timeout.\nsession_recv_bufsize = \"128kb\"\nsession_recv_timeout = \"30m\"\n\n# Set session send buffer size & timeout.\nsession_send_bufsize = \"64kb\"\nsession_send_timeout = \"30s\"\n\n# Make sure this is higher than the max number of requests for each pipeline request, or your client may be blocked.\n# Set session pipeline buffer size.\nsession_max_pipeline = 1024\n\n# Set session tcp keepalive period. (0 to disable)\nsession_keepalive_period = \"75s\"\n\n# Set session to be sensitive to failures. Default is false, instead of closing socket, proxy will send an error response to client.\nsession_break_on_failure = false\n\n# Set metrics server (such as http://localhost:28000), proxy will report json formatted metrics to specified server in a predefined period.\nmetrics_report_server = \"\"\nmetrics_report_period = \"1s\"\n\n# Set influxdb server (such as http://localhost:8086), proxy will report metrics to influxdb.\nmetrics_report_influxdb_server = \"\"\nmetrics_report_influxdb_period = \"1s\"\nmetrics_report_influxdb_username = \"\"\nmetrics_report_influxdb_password = \"\"\nmetrics_report_influxdb_database = \"\"\n\n"
  },
  {
    "path": "deploy/root/opt/codis/etc/127.0.0.1_19000/proxy_admin",
    "content": "#!/usr/bin/env bash\n\nset -x\nset -e\n\n/opt/codis/bin/codis-admin --proxy=127.0.0.1:11080 $@\n"
  },
  {
    "path": "deploy/root/opt/codis/etc/127.0.0.1_19001/codis_proxy_19001.service",
    "content": "[Unit]\nDescription=Codis-[demo-alpha]@19001\n[Service]\nExecStart=/opt/codis/bin/codis-proxy --ncpu=4 --max-ncpu=8 \\\n    --config=/opt/codis/etc/127.0.0.1:19001/proxy.toml --log=/opt/codis/log/127.0.0.1:19001/proxy.log --log-level=INFO\nRestart=always\n[Install]\nWantedBy=default.target\n\n"
  },
  {
    "path": "deploy/root/opt/codis/etc/127.0.0.1_19001/proxy.toml",
    "content": "##################################################\n#                                                #\n#                  Codis-Proxy                   #\n#                                                #\n##################################################\n\n# Set Codis Product Name/Auth.\nproduct_name = \"demo-alpha\"\nproduct_auth = \"\"\n\n# Set bind address for admin(rpc), tcp only.\nadmin_addr = \"127.0.0.1:11081\"\n\n# Set bind address for proxy, proto_type can be \"tcp\", \"tcp4\", \"tcp6\", \"unix\" or \"unixpacket\".\nproto_type = \"tcp4\"\nproxy_addr = \"127.0.0.1:19001\"\n\n# Set jodis address & session timeout, only accept \"zookeeper\" & \"etcd\".\njodis_name = \"\"\njodis_addr = \"\"\njodis_timeout = \"20s\"\njodis_compatible = false\n\n# Set datacenter of proxy.\nproxy_datacenter = \"\"\n\n# Set max number of alive sessions.\nproxy_max_clients = 10000\n\n# Set max offheap memory size. (0 to disable)\nproxy_max_offheap_size = \"1024mb\"\n\n# Set heap placeholder to reduce GC frequency.\nproxy_heap_placeholder = \"256mb\"\n\n# Proxy will ping backend redis (and clear 'MASTERDOWN' state) in a predefined interval. (0 to disable)\nbackend_ping_period = \"5s\"\n\n# Set backend recv buffer size & timeout.\nbackend_recv_bufsize = \"128kb\"\nbackend_recv_timeout = \"30s\"\n\n# Set backend send buffer & timeout.\nbackend_send_bufsize = \"128kb\"\nbackend_send_timeout = \"30s\"\n\n# Set backend pipeline buffer size.\nbackend_max_pipeline = 1024\n\n# Set backend never read replica groups, default is false\nbackend_primary_only = false\n\n# Set backend parallel connections per server\nbackend_primary_parallel = 1\nbackend_replica_parallel = 1\n\n# Set backend tcp keepalive period. (0 to disable)\nbackend_keepalive_period = \"75s\"\n\n# Set number of databases of backend.\nbackend_number_databases = 16\n\n# If there is no request from client for a long time, the connection will be closed. (0 to disable)\n# Set session recv buffer size & timeout.\nsession_recv_bufsize = \"128kb\"\nsession_recv_timeout = \"30m\"\n\n# Set session send buffer size & timeout.\nsession_send_bufsize = \"64kb\"\nsession_send_timeout = \"30s\"\n\n# Make sure this is higher than the max number of requests for each pipeline request, or your client may be blocked.\n# Set session pipeline buffer size.\nsession_max_pipeline = 1024\n\n# Set session tcp keepalive period. (0 to disable)\nsession_keepalive_period = \"75s\"\n\n# Set session to be sensitive to failures. Default is false, instead of closing socket, proxy will send an error response to client.\nsession_break_on_failure = false\n\n# Set metrics server (such as http://localhost:28000), proxy will report json formatted metrics to specified server in a predefined period.\nmetrics_report_server = \"\"\nmetrics_report_period = \"1s\"\n\n# Set influxdb server (such as http://localhost:8086), proxy will report metrics to influxdb.\nmetrics_report_influxdb_server = \"\"\nmetrics_report_influxdb_period = \"1s\"\nmetrics_report_influxdb_username = \"\"\nmetrics_report_influxdb_password = \"\"\nmetrics_report_influxdb_database = \"\"\n\n"
  },
  {
    "path": "deploy/root/opt/codis/etc/127.0.0.1_19001/proxy_admin",
    "content": "#!/usr/bin/env bash\n\nset -x\nset -e\n\n/opt/codis/bin/codis-admin --proxy=127.0.0.1:11081 $@\n"
  },
  {
    "path": "deploy/root/opt/codis/etc/127.0.0.1_19002/codis_proxy_19002.service",
    "content": "[Unit]\nDescription=Codis-[demo-alpha]@19002\n[Service]\nExecStart=/opt/codis/bin/codis-proxy --ncpu=4 --max-ncpu=8 \\\n    --config=/opt/codis/etc/127.0.0.1:19002/proxy.toml --log=/opt/codis/log/127.0.0.1:19002/proxy.log --log-level=INFO\nRestart=always\n[Install]\nWantedBy=default.target\n\n"
  },
  {
    "path": "deploy/root/opt/codis/etc/127.0.0.1_19002/proxy.toml",
    "content": "##################################################\n#                                                #\n#                  Codis-Proxy                   #\n#                                                #\n##################################################\n\n# Set Codis Product Name/Auth.\nproduct_name = \"demo-alpha\"\nproduct_auth = \"\"\n\n# Set bind address for admin(rpc), tcp only.\nadmin_addr = \"127.0.0.1:11082\"\n\n# Set bind address for proxy, proto_type can be \"tcp\", \"tcp4\", \"tcp6\", \"unix\" or \"unixpacket\".\nproto_type = \"tcp4\"\nproxy_addr = \"127.0.0.1:19002\"\n\n# Set jodis address & session timeout, only accept \"zookeeper\" & \"etcd\".\njodis_name = \"\"\njodis_addr = \"\"\njodis_timeout = \"20s\"\njodis_compatible = false\n\n# Set datacenter of proxy.\nproxy_datacenter = \"\"\n\n# Set max number of alive sessions.\nproxy_max_clients = 10000\n\n# Set max offheap memory size. (0 to disable)\nproxy_max_offheap_size = \"1024mb\"\n\n# Set heap placeholder to reduce GC frequency.\nproxy_heap_placeholder = \"256mb\"\n\n# Proxy will ping backend redis (and clear 'MASTERDOWN' state) in a predefined interval. (0 to disable)\nbackend_ping_period = \"5s\"\n\n# Set backend recv buffer size & timeout.\nbackend_recv_bufsize = \"128kb\"\nbackend_recv_timeout = \"30s\"\n\n# Set backend send buffer & timeout.\nbackend_send_bufsize = \"128kb\"\nbackend_send_timeout = \"30s\"\n\n# Set backend pipeline buffer size.\nbackend_max_pipeline = 1024\n\n# Set backend never read replica groups, default is false\nbackend_primary_only = false\n\n# Set backend parallel connections per server\nbackend_primary_parallel = 1\nbackend_replica_parallel = 1\n\n# Set backend tcp keepalive period. (0 to disable)\nbackend_keepalive_period = \"75s\"\n\n# Set number of databases of backend.\nbackend_number_databases = 16\n\n# If there is no request from client for a long time, the connection will be closed. (0 to disable)\n# Set session recv buffer size & timeout.\nsession_recv_bufsize = \"128kb\"\nsession_recv_timeout = \"30m\"\n\n# Set session send buffer size & timeout.\nsession_send_bufsize = \"64kb\"\nsession_send_timeout = \"30s\"\n\n# Make sure this is higher than the max number of requests for each pipeline request, or your client may be blocked.\n# Set session pipeline buffer size.\nsession_max_pipeline = 1024\n\n# Set session tcp keepalive period. (0 to disable)\nsession_keepalive_period = \"75s\"\n\n# Set session to be sensitive to failures. Default is false, instead of closing socket, proxy will send an error response to client.\nsession_break_on_failure = false\n\n# Set metrics server (such as http://localhost:28000), proxy will report json formatted metrics to specified server in a predefined period.\nmetrics_report_server = \"\"\nmetrics_report_period = \"1s\"\n\n# Set influxdb server (such as http://localhost:8086), proxy will report metrics to influxdb.\nmetrics_report_influxdb_server = \"\"\nmetrics_report_influxdb_period = \"1s\"\nmetrics_report_influxdb_username = \"\"\nmetrics_report_influxdb_password = \"\"\nmetrics_report_influxdb_database = \"\"\n\n"
  },
  {
    "path": "deploy/root/opt/codis/etc/127.0.0.1_19002/proxy_admin",
    "content": "#!/usr/bin/env bash\n\nset -x\nset -e\n\n/opt/codis/bin/codis-admin --proxy=127.0.0.1:11082 $@\n"
  },
  {
    "path": "deploy/templates/dashboard.service.template",
    "content": "[Unit]\nDescription=Codis-[{PRODUCT_NAME}]@{ADMIN_PORT}\n[Service]\nExecStart={BIN_PATH}/codis-dashboard \\\n    --config={ETC_PATH}/{ADMIN_ADDR}/dashboard.toml --log={LOG_PATH}/{ADMIN_ADDR}/dashboard.log\nRestart=always\n[Install]\nWantedBy=default.target\n\n"
  },
  {
    "path": "deploy/templates/dashboard.toml.template",
    "content": "##################################################\n#                                                #\n#                  Codis-Dashboard               #\n#                                                #\n##################################################\n\n# Set Coordinator, only accept \"zookeeper\" & \"etcd\".\ncoordinator_name = \"{COORDINATOR_NAME}\"\ncoordinator_addr = \"{COORDINATOR_ADDR}\"\n\n# Set Codis Product Name/Auth.\nproduct_name = \"{PRODUCT_NAME}\"\nproduct_auth = \"{PRODUCT_AUTH}\"\n\n# Set bind address for admin(rpc), tcp only.\nadmin_addr = \"{ADMIN_ADDR}\"\n\n# Set arguments for data migration (only accept 'sync' & 'semi-async').\nmigration_method = \"semi-async\"\nmigration_async_maxbulks = 200\nmigration_async_maxbytes = \"32mb\"\nmigration_async_numkeys = 100\nmigration_timeout = \"30s\"\n\n# Set configs for redis sentinel.\nsentinel_quorum = {SENTINEL_QUORUM}\nsentinel_parallel_syncs = 1\nsentinel_down_after = \"{SENTINEL_DOWN_AFTER}\"\nsentinel_failover_timeout = \"5m\"\nsentinel_notification_script = \"\"\nsentinel_client_reconfig_script = \"\"\n\n"
  },
  {
    "path": "deploy/templates/proxy.service.template",
    "content": "[Unit]\nDescription=Codis-[{PRODUCT_NAME}]@{PROXY_PORT}\n[Service]\nExecStart={BIN_PATH}/codis-proxy --ncpu={MIN_CPU} --max-ncpu={MAX_CPU} \\\n    --config={ETC_PATH}/{PROXY_ADDR}/proxy.toml --log={LOG_PATH}/{PROXY_ADDR}/proxy.log --log-level={LOG_LEVEL}\nRestart=always\n[Install]\nWantedBy=default.target\n\n"
  },
  {
    "path": "deploy/templates/proxy.toml.template",
    "content": "##################################################\n#                                                #\n#                  Codis-Proxy                   #\n#                                                #\n##################################################\n\n# Set Codis Product Name/Auth.\nproduct_name = \"{PRODUCT_NAME}\"\nproduct_auth = \"{PRODUCT_AUTH}\"\n\n# Set bind address for admin(rpc), tcp only.\nadmin_addr = \"{ADMIN_ADDR}\"\n\n# Set bind address for proxy, proto_type can be \"tcp\", \"tcp4\", \"tcp6\", \"unix\" or \"unixpacket\".\nproto_type = \"tcp4\"\nproxy_addr = \"{PROXY_ADDR}\"\n\n# Set jodis address & session timeout, only accept \"zookeeper\" & \"etcd\".\njodis_name = \"{JODIS_NAME}\"\njodis_addr = \"{JODIS_ADDR}\"\njodis_timeout = \"20s\"\njodis_compatible = false\n\n# Set datacenter of proxy.\nproxy_datacenter = \"{DATACENTER}\"\n\n# Set max number of alive sessions.\nproxy_max_clients = {MAX_CLIENTS}\n\n# Set max offheap memory size. (0 to disable)\nproxy_max_offheap_size = \"1024mb\"\n\n# Set heap placeholder to reduce GC frequency.\nproxy_heap_placeholder = \"256mb\"\n\n# Proxy will ping backend redis (and clear 'MASTERDOWN' state) in a predefined interval. (0 to disable)\nbackend_ping_period = \"5s\"\n\n# Set backend recv buffer size & timeout.\nbackend_recv_bufsize = \"128kb\"\nbackend_recv_timeout = \"30s\"\n\n# Set backend send buffer & timeout.\nbackend_send_bufsize = \"128kb\"\nbackend_send_timeout = \"30s\"\n\n# Set backend pipeline buffer size.\nbackend_max_pipeline = 1024\n\n# Set backend never read replica groups, default is false\nbackend_primary_only = false\n\n# Set backend parallel connections per server\nbackend_primary_parallel = 1\nbackend_replica_parallel = 1\n\n# Set backend tcp keepalive period. (0 to disable)\nbackend_keepalive_period = \"75s\"\n\n# Set number of databases of backend.\nbackend_number_databases = 16\n\n# If there is no request from client for a long time, the connection will be closed. (0 to disable)\n# Set session recv buffer size & timeout.\nsession_recv_bufsize = \"128kb\"\nsession_recv_timeout = \"30m\"\n\n# Set session send buffer size & timeout.\nsession_send_bufsize = \"64kb\"\nsession_send_timeout = \"30s\"\n\n# Make sure this is higher than the max number of requests for each pipeline request, or your client may be blocked.\n# Set session pipeline buffer size.\nsession_max_pipeline = {MAX_PIPELINE}\n\n# Set session tcp keepalive period. (0 to disable)\nsession_keepalive_period = \"75s\"\n\n# Set session to be sensitive to failures. Default is false, instead of closing socket, proxy will send an error response to client.\nsession_break_on_failure = false\n\n# Set metrics server (such as http://localhost:28000), proxy will report json formatted metrics to specified server in a predefined period.\nmetrics_report_server = \"\"\nmetrics_report_period = \"1s\"\n\n# Set influxdb server (such as http://localhost:8086), proxy will report metrics to influxdb.\nmetrics_report_influxdb_server = \"\"\nmetrics_report_influxdb_period = \"1s\"\nmetrics_report_influxdb_username = \"\"\nmetrics_report_influxdb_password = \"\"\nmetrics_report_influxdb_database = \"\"\n\n"
  },
  {
    "path": "doc/FAQ_en.md",
    "content": "####What is Codis?\nCodis is a distributed redis service developed by wandoujia infrasstructure team, codis can be viewed as an redis server with infinite memory, have the ability of dynamically elastic scaling,  it's more fit for storage business, if you need SUBPUB-like command, Codis is not supported, always remember Codis is a distributed storage system.\n\n###Does Codis support etcd ? \n\nYes, please read the tutorial\n\n\n####Can I use Codis directly in my existing services?\n\nThat depends.  \nTwo cases:  \n1) Twemproxy users:  \nYes, codis fully support twemproxy commands, further more, using redis-port tool, you can synchronization the data on twemproxy onto your Codis cluster.\n\n2) Raw redis users:  \nThat depends, if you use the following commands:  \n\nBGREWRITEAOF, BGSAVE, BITOP, BLPOP, BRPOP, BRPOPLPUSH, CLIENT, CONFIG, DBSIZE, DEBUG, DISCARD, EXEC, FLUSHALL, FLUSHDB, KEYS, LASTSAVE, MIGRATE, MONITOR, MOVE, MSETNX, MULTI, OBJECT, PSUBSCRIBE, PUBLISH, PUNSUBSCRIBE, RANDOMKEY, RENAME, RENAMENX, RESTORE, SAVE, SCAN, SCRIPT, SHUTDOWN, SLAVEOF, SLOTSCHECK, SLOTSDEL, SLOTSINFO, SLOTSMGRTONE, SLOTSMGRTSLOT, SLOTSMGRTTAGONE, SLOTSMGRTTAGSLOT, SLOWLOG, SUBSCRIBE, SYNC, TIME, UNSUBSCRIBE, UNWATCH, WATCH\n\nyou should modify your code, because Codis does not support these commands.\n"
  },
  {
    "path": "doc/FAQ_zh.md",
    "content": "### Codis 是什么?\n\nCodis 是 Wandoujia Infrastructure Team 开发的一个分布式 Redis 服务, 用户可以看成是一个无限内存的 Redis 服务, 有动态扩/缩容的能力. 对偏存储型的业务更实用, 如果你需要 SUBPUB 之类的指令, Codis 是不支持的. 时刻记住 Codis 是一个分布式存储的项目. 对于海量的 key, value不太大( <= 1M ), 随着业务扩展缓存也要随之扩展的业务场景有特效.\n\n### 使用 Codis 有什么好处?\n\nRedis获得动态扩容/缩容的能力，增减redis实例对client完全透明、不需要重启服务，不需要业务方担心 Redis 内存爆掉的问题. 也不用担心申请太大, 造成浪费. 业务方也不需要自己维护 Redis.\n\nCodis支持水平扩容/缩容，扩容可以直接界面的 \"Auto Rebalance\" 按钮，缩容只需要将要下线的实例拥有的slot迁移到其它实例，然后在界面上删除下线的group即可。\n\n### 我的服务能直接迁移到 Codis 上吗?\n\n分两种情况: \n \n1) 原来使用 twemproxy 的用户:\n可以, 使用codis项目内的redis-port工具, 可以实时的同步 twemproxy 底下的 redis 数据到你的 codis 集群上. 搞定了以后, 只需要你修改一下你的配置, 将 twemproxy 的地址改成 codis 的地址就好了. 除此之外, 你什么事情都不用做.\n\n2) 原来使用 Redis 的用户:\n如果你使用了[doc/unsupported_cmds](https://github.com/CodisLabs/codis/blob/master/doc/unsupported_cmds.md)中提到的命令，是无法直接迁移到 Codis 上的. 你需要修改你的代码, 用其他的方式实现.\n\n### 相对于twemproxy的优劣？\ncodis和twemproxy最大的区别有两个：一个是codis支持动态水平扩展，对client完全透明不影响服务的情况下可以完成增减redis实例的操作；一个是codis是用go语言写的并支持多线程而twemproxy用C并只用单线程。\n后者又意味着：codis在多核机器上的性能会好于twemproxy；codis的最坏响应时间可能会因为GC的STW而变大，不过go1.5发布后会显著降低STW的时间；如果只用一个CPU的话go语言的性能不如C，因此在一些短连接而非长连接的场景中，整个系统的瓶颈可能变成accept新tcp连接的速度，这时codis的性能可能会差于twemproxy。\n\n### 相对于redis cluster的优劣？\nredis cluster基于smart client和无中心的设计，client必须按key的哈希将请求直接发送到对应的节点。这意味着：使用官方cluster必须要等对应语言的redis driver对cluster支持的开发和不断成熟；client不能直接像单机一样使用pipeline来提高效率，想同时执行多个请求来提速必须在client端自行实现异步逻辑。\n而codis因其有中心节点、基于proxy的设计，对client来说可以像对单机redis一样去操作proxy（除了一些命令不支持），还可以继续使用pipeline并且如果后台redis有多个的话速度会显著快于单redis的pipeline。同时codis使用zookeeper来作为辅助，这意味着单纯对于redis集群来说需要额外的机器搭zk，不过对于很多已经在其他服务上用了zk的公司来说这不是问题：）\n\n### Codis是如何分片的？\nCodis 采用 Pre-sharding 的技术来实现数据的分片, 默认分成 1024 个 slots (0-1023), 对于每个key来说, 通过以下公式确定所属的 Slot Id : SlotId = crc32(key) % 1024。\n\n每一个 slot 都会有一个且必须有一个特定的 server group id 来表示这个 slot 的数据由哪个 server group 来提供。数据的迁移也是以slot为单位的。\n\n### Codis 可以当队列使用吗?\n\n可以, Codis 还是支持 LPUSH LPOP这样的指令, 但是注意, 并不是说你用了 Codis 就有了一个分布式队列. 对于单个 key, 它的 value 还是会在一台机器上, 所以, 如果你的队列特别大, 而且整个业务就用了几个 key, 那么就几乎退化成了单个 redis 了, 所以, 如果你是希望有一个队列服务, 那么我建议你:\n\n1. List key 里存放的是任务id, 用另一个key-value pair来存放具体任务信息\n2. 使用 Pull 而不是 Push, 由消费者主动拉取数据, 而不是生产者推送数据.\n3. 监控好你的消费者, 当队列过长的时候, 及时报警. \n4. 可以将一个大队列拆分成多个小的队列, 放在不同的key中\n\n### Codis 支持 MSET, MGET吗?\n\n支持, 在比较早的版本中MSET/MGET的性能较差，甚至可能差过单机redis，但2.0开始会因为后台并发执行而比单机的mset/mget快很多。\n\n### Codis 是多线程的吗?\n\n虽然Redis是单线程的，但Codis proxy 是多线程的(严格来说是 goroutine), 启动的线程数是 CPU 的核数, 是可以充分利用起多核的性能的。\n\n### Codis 支持 CAS 吗? 支持 Lua 脚本吗?\n\nCAS 暂时不支持, 目前只支持eval的方式来跑lua脚本，需要配合TAG使用. \n\n### 有没有 zookeeper 的教程？\n\n[请参考这里](http://www.juvenxu.com/2015/03/20/experiences-on-zookeeper-ops/)\n\n### Codis的性能如何?\n\n见Readme中的[Benchmark一节](https://github.com/CodisLabs/codis#performance-benchmark)。\n\n### 我的数据在 Codis 上是安全的吗?\n\n首先, 安全的定义有很多个级别, Codis 并不是一个多副本的系统 (用纯内存来做多副本还是很贵的), 如果 Codis 底下的 redis 机器没有配从, 也没开 bgsave, 如果挂了, 那么最坏情况下会丢失这部分的数据, 但是集群的数据不会全失效 (即使这样的, 也比以前单点故障, 一下全丢的好...-_-|||). 如果上一种情况下配了从, 这种情况, 主挂了, 到从切上来这段时间, 客户端的部分写入会失败. 主从之前没来得及同步的小部分数据会丢失.\n第二种情况, 业务短时间内爆炸性增长, 内存短时间内不可预见的暴涨(就和你用数据库磁盘满了一样), Codis还没来得及扩容, 同时数据迁移的速度小于暴涨的速度, 此时会触发 Redis 的 LRU 策略, 会淘汰老的 Key. 这种情况也是无解...不过按照现在的运维经验, 我们会尽量预分配一些 buffer, 内存使用量大概 80% 的时候, 我们就会开始扩容.\n\n除此之外, 正常的数据迁移, 扩容缩容, 数据都是安全的. \n\n### 你们如何保证数据迁移的过程中多个 Proxy 不会读到老的数据 (迁移的原子性) ? \n\n见 [Codis 数据迁移流程](http://0xffff.me/blog/2014/11/11/codis-de-she-ji-yu-shi-xian-part-2/)\n\n### Codis支持etcd吗 ? \n\n支持，请参考使用教程，需要将配置文件中的coordinator=zookeeper改为etcd。\n\n但是需要注意：请使用codis2.0.10或更新的版本，旧版对etcd的支持有一些问题；由于etcd在2.2引入了一个与旧版不兼容的坑爹改动，导致如果使用etcd的版本>=2.2.0，暂时需要手动改一处代码，详情见[相关issue](https://github.com/CodisLabs/codis/issues/488)。\n\n### 现有redis集群上有上T的数据，如何迁移到Codis上来？\n\n为了提高 Codis 推广和部署上的效率，我们为数据迁移提供了一个叫做 [redis-port](https://github.com/CodisLabs/redis-port) 的命令行工具，它能够：\n\n+ 静态分析 RDB 文件，包括解析以及恢复 RDB 数据到 redis\n+ 从 redis 上 dump RDB 文件以及从 redis 和 codis 之间动态同步数据\n\n### 如果需要迁移现有 redis 数据到 codis，该如何操作？\n\n+ 先搭建好 codis 集群并让 codis-proxy 正确运行起来\n+ 对线上每一个 redis 实例运行一个 redis-port 来向 codis 导入数据，例如：\n\n\t\tfor port in {6379,6380,6479,6480}; do\n\t\t\tnohup redis-port sync --ncpu=4 --from=redis-server:${port} \\\n\t\t\t\t--target=codis-proxy:19000 > ${port}.log 2>&1 &\n\t\t\tsleep 5\n\t\tdone\n\t\ttail -f *.log\n\t\t\n\t- 每个 redis-port 负责将对应的 redis 数据导入到 codis\n\t- 多个 redis-port 之间不互相干扰，除非多个 redis 上的 key 本身出现冲突\n\t- 单个 redis-port 可以将负责的数据并行迁移以提高速度，通过 --ncpu 来指定并行数\n\t- 导入速度受带宽以及 codis-proxy 处理速度限制(本质是大量的 slotsrestore 操作)\n\t\n+ 完成数据迁移，在适当的时候将服务指向 Codis，并将原 redis 下线\n\n\t- 旧 redis 下线时，会导致 reids-port 链接断开，于是自动退出\n\t\t\n### redis-port 是如何在线迁移数据的？\n\n+ redis-port 本质是以 slave 的形式挂载到现有 redis 服务上去的\n\n\t1. redis 会生成 RDB DUMP 文件给作为 slave 的 redis-port\n\t2. redis-port 分析 RDB 文件，并拆分成 key-value 对，通过 [slotsrestore](https://github.com/CodisLabs/codis/blob/master/doc/redis_change_zh.md#slotsrestore-key1-ttl1-val1-key2-ttl2-val2-) 指令发给 codis\n\t3. 迁移过程中发生的修改，redis 会将这些指令在 RDB DUMP 发送完成后，再发给 redis-port，而 redis-port 收到这些指令后不作处理，而直接转发给 Codis\n\t\n+ redis-port 处理还是很快的，参考：\n\t- https://github.com/sripathikrishnan/redis-rdb-tools\n\t- https://github.com/cupcake/rdb\n\n### Dashboard 中 Ops 一直是 0？\n\n检查你的启动 dashboard 进程的机器，看是否可以访问proxy的地址，对应的地址是 proxy 启动参数中的 debug_var_addr 中填写的地址。\n\n###  zk: node already exists\n无论是proxy还是dashboard，都会在zk上注册自己的节点，同时在程序正常退出的时候会删掉对应的节点，但如果异常退出或试用`kill -9 {pid}`就会导致zk的节点无法删除，在下一次启动的时候会报“zk: node already exists”的错误。\n\n因此关闭服务的时候直接用`kill {pid}`不要-9，同时如果无法启动并且确认没有其他运行中的进程占用zk上的节点，可以在zk上手动删除/zk/codis/db_test/dashboard 或/zk/codis/db_test/fence/{host:port}.\n\n### 编译报错  undefined: utils.Version\n说明没有正确的设置go项目路径导致生成的文件找不到。见[安装教程](https://github.com/CodisLabs/codis/blob/master/doc/tutorial_zh.md#build-codis-proxy--codis-config)来正确配置环境变量并用正确的方式下载代码。\n\n### zk: session has been expired by the server\n因为使用的go-zookeeper库代码注释里写的session超时时间参数单位是秒，但实际上该参数的单位是毫秒，所以<=2.0.7的版本错误的将默认配置设成30。因此请将配置文件修改为30000。此外2.0.8起如果配置文件中的参数过小则自动将秒转化为毫秒。\n\nCodis的proxy会注册在zk上并监听新的zk事件。因为涉及到数据一致性的问题，所有proxy必须能尽快知道slot状态的改变，因此一旦和zk的连接出了问题就无法知道最新的slot信息从而可能不得不阻塞一些请求以防止数据错误或丢失。\n\nProxy会每几秒给zk发心跳，proxy的load太高可能导致timeout时间内（默认30秒，配置文件中可以修改）没有成功发心跳导致zk认为proxy已经挂了（当然也可能proxy确实挂了），\n这时如果client用了我们修改的Jedis, [Jodis](https://github.com/CodisLabs/jodis)，是会监控到zk节点上proxy少了一个从而自动避开请求这个proxy以保证客户端业务的可用性。如果用非Java语言可以根据Jodis代码DIY一个监听zk的客户端。\n另外，如果需要异步请求，可以使用我们基于Netty开发的[Nedis](https://github.com/CodisLabs/nedis)。\n\n当然，proxy收到session expired的错误也不意味着proxy一定要强制退出，但是这是最方便、安全的实现方式。而且实际使用中出现错误的情况通常是zk或proxy的load过高导致的，即使这时不退出可能业务的请求也会受影响，因此出现这个问题通常意味着需要加机器了。\n\n如果不依赖zk/Jodis来做proxy的高可用性（虽然我们建议这样做），可以适当延长配置文件中的超时时间以降低出这个错误的概率。\n\n### proxy异常退出\n目前proxy异常退出主要有两种可能，一种是zk的session expired错误，原因见前一节；另一种是从zk获取集群信息时超时或者报错。总体来说都是因为proxy和zk的连接不稳定导致的，而现在还没有加上重试等逻辑。\n\n不过，最新版的codis已经可以实现proxy自动启动、自动标记为online。因此可以外部通过脚本或supervisor等服务来监控proxy的进程，一旦进程退出可以直接自动重启。\n"
  },
  {
    "path": "doc/bench1/Makefile",
    "content": "all:\n\tgnuplot bench.plot\n\tconvert -density 300 bench.pdf -quality 90 -background white -alpha off bench.png\n"
  },
  {
    "path": "doc/bench1/bench.plot",
    "content": "set terminal pdfcairo enhanced color lw 1.2 size 20cm,34cm\nset output 'bench.pdf'\n\nset border 11 back\n\nset tics font \",14\"\nset key spacing 1.8 samplen 2 font \",15\" left Left reverse\nset key box opaque\n\nset grid y\nset xtics nomirror out\nset ytics nomirror out\nset y2tics nomirror out\nset mytics 5\nset my2tics 5\nset boxwidth 0.8 relative\n\nset pointsize 0.8\n\nset style line 1 lc rgb \"#4873EA\" lw 1.4 pt 7\nset style line 2 lc rgb \"#2FA75A\" lw 1.4 pt 7\nset style line 3 lc rgb \"#EB383E\" lw 1.4 pt 7\n\nset offset -0.3,-0.3,0,0\n\nset xtic add (\"\" 0, \"1\" 1, \"2\" 2, \"4\" 3, \"8\" 4, \"16\" 5, \"32\" 6, \"64\" 7, \"100\" 8, \"200\" 9, \"300\" 10, \"400\" 11, \"500\" 12, \"800\" 13, \"\" 14)\n\nset y2label \"99% Response Time (ms)\" offset 1,0 font \",16\"\n\nset lmargin at screen 0.10\nset rmargin at screen 0.90\n\nset multiplot layout 3,1\n\nset ylabel \"RPS_{avg}=(RPS_{set}+RPS_{get})/2, 1K=10^3\" offset 0.5,0 font \",16\"\nset xlabel \"Number of Clients\" offset 0,-0.5 font \",16\"\n\nset bmargin at screen 0.72\nset tmargin at screen 0.96\n\nset title \"RedisBenchmark(SET+GET): DataSize=256B, Pipeline=Disabled\" font \",20\"\nset ytics 50000\nset ytic add (\"50K\" 50000, \"100K\" 100000, \"150K\" 150000, \"200K\" 200000)\nset y2range[0:8]\n\nplot 'input1' \\\n              using 1:2 title \"1Core-Twemproxy \" with linespoints ls 1, \\\n           '' using 1:4 title \"4Core-Codis 2.0 \" with linespoints ls 3, \\\n           '' using 1:5 notitle with points ls 1 pt 1 ps 0.7 axes x1y2, \\\n           '' using 1:7 notitle with points ls 3 pt 1 ps 0.7 axes x1y2, \\\n           '' using 1:3 title \"4Core-Codis 1.9 \" with linespoints ls 2, \\\n           '' using 1:6 notitle with points ls 2 pt 1 ps 0.7 axes x1y2, \\\n\n\nset bmargin at screen 0.39\nset tmargin at screen 0.63\n\nset title \"RedisBenchmark(SET+GET): DataSize=256B, Pipeline=100\" font \",20\"\nset ytics 200000\nset ytic add (\"200K\" 200000, \"400K\" 400000, \"600K\" 600000, \"800K\" 800000, \"1000K\" 1000000)\nset yrange[0:1000000]\nset y2range[0:350]\n\nplot 'input2' \\\n              using 1:2 title \"1Core-Twemproxy \" with linespoints ls 1, \\\n           '' using 1:4 title \"4Core-Codis 2.0 \" with linespoints ls 3, \\\n           '' using 1:5 notitle with points ls 1 pt 1 ps 0.7 axes x1y2, \\\n           '' using 1:7 notitle with points ls 3 pt 1 ps 0.7 axes x1y2, \\\n           '' using 1:3 title \"4Core-Codis 1.9 \" with linespoints ls 2, \\\n           '' using 1:6 notitle with points ls 2 pt 1 ps 0.7 axes x1y2, \\\n\nset bmargin at screen 0.06\nset tmargin at screen 0.30\n\nset title \"RedisBenchmark(MSET): DataSize=256B, Pipeline=100\" font \",20\"\nset ytics 50000\nset ytic add (\"50K\" 50000, \"100K\" 100000, \"150K\" 150000, \"200K\" 200000)\nset yrange[0:150000]\nset y2range[0:2000]\n\nset ylabel \"RPS_{mset}, 1K=10^3\" offset 0.5,0 font \",16\"\n\nplot 'input3' \\\n              using 1:2 title \"1Core-Twemproxy \" with linespoints ls 1, \\\n           '' using 1:4 title \"4Core-Codis 2.0 \" with linespoints ls 3, \\\n           '' using 1:5 notitle with points ls 1 pt 1 ps 0.7 axes x1y2, \\\n           '' using 1:7 notitle with points ls 3 pt 1 ps 0.7 axes x1y2, \\\n           '' using 1:3 title \"4Core-Codis 1.9 \" with linespoints ls 2, \\\n           '' using 1:6 notitle with points ls 2 pt 1 ps 0.7 axes x1y2, \\\n\nunset multiplot\n"
  },
  {
    "path": "doc/bench1/input1",
    "content": "1   35275.01    17680.675   18808.07    1  1  1\n2   72842.26    30272.58    32675.88    1  1  1\n3   101501.92   61790.96    64895.435   1  1  1\n4   117578.445  103329.99   107440.265  1  1  1\n5   132894.23   131900.51   130211.785  1  1  1\n6   148646.965  155560.84   148929.79   1  1  1\n7   165562.53   175137.835  169754.88   1  1  1\n8   172019.39   179229.855  177277.595  1  2  2\n9   174394.525  181340.16   178518.415  2  2  3\n10  173001.76   169191.39   175404.105  3  3  4\n11  168563.395  154347.975  166161.24   3  3  5\n12  160042.105  141013.445  152576.875  4  4  5\n13  133816.15   115740.04   121767.62   7  7  7\n"
  },
  {
    "path": "doc/bench1/input2",
    "content": "1   456597.59   23740.63    323324.175  1    1   1\n2   446909.715  43555.16    489904.325  2    1   1\n3   449501.985  85470.705   576226.59   2    1   3\n4   437109.595  131071.2    706530.22   3    1   7\n5   361118.795  173250.195  769638.12   6    1   8\n6   329854.53   218659.425  819284.31   12   1   10\n7   310600.955  261996.235  836439.69   25   1   16\n8   296984.81   284925.065  871447.155  39   2   22\n9   287946.825  305086.485  860272.845  81   3   39\n10  279538.64   302252.78   864029.905  122  4   47\n11  275084.53   285676.625  830518.625  166  6   55\n12  273534.9    278811.89   822581.065  207  7   66\n13  271706.045  265871.79   816346.905  335  12  100\n"
  },
  {
    "path": "doc/bench1/input3",
    "content": "1   58505.19  1496.54   55020.63   2     1    7\n2   57595.39  3106.7    80176.39   5     1    8\n3   47003.52  6401.74   86095.57   11    1    10\n4   39108.33  9273.21   102040.81  24    2    16\n5   37611.66  10947.51  108401.09  50    3    26\n6   35810.21  12404.25  109739.37  104   5    42\n7   31829.39  13690.66  109619.08  216   8    53\n8   33129.04  13738.15  110895.48  309   11   59\n9   34004.93  13561.62  111919.42  762   22   75\n10  40489.93  13597.12  108137.34  1138  99   86\n11  53540.36  13626.76  108754.76  769   189  93\n12  47153.13  13540.96  104629.88  1198  256  103\n13  54429.18  13490.73  103119.36  1783  534  111\n"
  },
  {
    "path": "doc/bench2/Makefile",
    "content": "all:\n\tgnuplot bench.plot\n\tconvert -density 300 bench.pdf -quality 90 -background white -alpha off bench.png\n"
  },
  {
    "path": "doc/bench2/bench.plot",
    "content": "set terminal pdfcairo enhanced color lw 1.2 size 20cm,58cm\nset output 'bench.pdf'\n\nset border 11 back\n\nset tics font \",14\"\nset key spacing 1.8 samplen 2 font \",15\" left Left reverse\nset key box opaque\n\nset grid y\nset xtics nomirror out\nset ytics nomirror out\nset y2tics nomirror out\nset mytics 5\nset my2tics 5\nset boxwidth 0.8 relative\n\nset pointsize 0.8\n\nset style line 1 lc rgb \"#4873EA\" lw 1.4 pt 7\nset style line 2 lc rgb \"#2FA75A\" lw 1.4 pt 7\nset style line 3 lc rgb \"#EB383E\" lw 1.4 pt 7\nset style line 4 lc rgb \"#31EC73\" lw 1.4 pt 7\nset style line 5 lc rgb \"#FF9300\" lw 1.4 pt 7\n\nset offset -0.3,-0.3,0,0\n\nset xtic add (\"\" 0, \"1\" 1, \"2\" 2, \"4\" 3, \"8\" 4, \"16\" 5, \"32\" 6, \"64\" 7, \"100\" 8, \"200\" 9, \"300\" 10, \"400\" 11, \"500\" 12, \"800\" 13, \"\" 14)\n\nset y2label \"99% Response Time (ms)\" offset 1,0 font \",16\"\n\nset lmargin at screen 0.10\nset rmargin at screen 0.90\n\nset multiplot layout 3,1\n\nset ylabel \"RPS_{avg}=(RPS_{set}+RPS_{get})/2, 1K=10^3\" offset 0.5,0 font \",16\"\nset xlabel \"Number of Clients\" offset 0,-0.5 font \",16\"\n\nset bmargin at screen 0.83\nset tmargin at screen 0.98\n\nset title \"RedisBenchmark(SET+GET): DataSize=256B, Pipeline=Disabled\" font \",20\"\nset ytics 50000\nset ytic add (\"50K\" 50000, \"100K\" 100000, \"150K\" 150000, \"200K\" 200000)\nset y2range[0:14]\n\nplot 'input1' \\\n              using 1:2  title \"1Core-Twemproxy \" with linespoints ls 1, \\\n           '' using 1:4  title \"4Core-Codis 2.0 \" with linespoints ls 3, \\\n           '' using 1:6  title \"8Core-Codis 2.0 \" with linespoints ls 5, \\\n           '' using 1:7  notitle with points ls 1 pt 1 ps 0.7 axes x1y2, \\\n           '' using 1:9  notitle with points ls 3 pt 1 ps 0.7 axes x1y2, \\\n           '' using 1:11 notitle with points ls 5 pt 1 ps 0.7 axes x1y2, \\\n           '' using 1:3  title \"4Core-Codis 1.9 \" with linespoints ls 2, \\\n           '' using 1:5  title \"8Core-Codis 1.9 \" with linespoints ls 4, \\\n           '' using 1:8  notitle with points ls 2 pt 1 ps 0.7 axes x1y2, \\\n           '' using 1:10 notitle with points ls 4 pt 1 ps 0.7 axes x1y2, \\\n\n\nset bmargin at screen 0.63\nset tmargin at screen 0.78\n\nset title \"RedisBenchmark(SET+GET): DataSize=256B, Pipeline=100\" font \",20\"\nset ytics 200000\nset ytic add (\"200K\" 200000, \"400K\" 400000, \"600K\" 600000, \"800K\" 800000, \"1000K\" 1000000, \"1200K\" 1200000)\nset yrange[0:1200000]\nset y2range[0:1200]\n\nplot 'input2' \\\n              using 1:2  title \"1Core-Twemproxy \" with linespoints ls 1, \\\n           '' using 1:4  title \"4Core-Codis 2.0 \" with linespoints ls 3, \\\n           '' using 1:6  title \"8Core-Codis 2.0 \" with linespoints ls 5, \\\n           '' using 1:7  notitle with points ls 1 pt 1 ps 0.7 axes x1y2, \\\n           '' using 1:9  notitle with points ls 3 pt 1 ps 0.7 axes x1y2, \\\n           '' using 1:11 notitle with points ls 5 pt 1 ps 0.7 axes x1y2, \\\n           '' using 1:3  title \"4Core-Codis 1.9 \" with linespoints ls 2, \\\n           '' using 1:5  title \"8Core-Codis 1.9 \" with linespoints ls 4, \\\n           '' using 1:8  notitle with points ls 2 pt 1 ps 0.7 axes x1y2, \\\n           '' using 1:10 notitle with points ls 4 pt 1 ps 0.7 axes x1y2, \\\n\nset bmargin at screen 0.43\nset tmargin at screen 0.58\n\nset title \"RedisBenchmark(MSET): DataSize=256B, Pipeline=100\" font \",20\"\nset ytics 40000\nset ytic add (\"40K\" 40000, \"80K\" 80000, \"120K\" 120000, \"160K\" 160000, \"200K\" 200000)\nset yrange[0:160000]\nset y2range[0:6000]\n\nset ylabel \"RPS_{mset}, 1K=10^3\" offset 0.5,0 font \",16\"\n\nplot 'input3' \\\n              using 1:2  title \"1Core-Twemproxy \" with linespoints ls 1, \\\n           '' using 1:4  title \"4Core-Codis 2.0 \" with linespoints ls 3, \\\n           '' using 1:6  title \"8Core-Codis 2.0 \" with linespoints ls 5, \\\n           '' using 1:7  notitle with points ls 1 pt 1 ps 0.7 axes x1y2, \\\n           '' using 1:9  notitle with points ls 3 pt 1 ps 0.7 axes x1y2, \\\n           '' using 1:11 notitle with points ls 5 pt 1 ps 0.7 axes x1y2, \\\n           '' using 1:3  title \"4Core-Codis 1.9 \" with linespoints ls 2, \\\n           '' using 1:5  title \"8Core-Codis 1.9 \" with linespoints ls 4, \\\n           '' using 1:8  notitle with points ls 2 pt 1 ps 0.7 axes x1y2, \\\n           '' using 1:10 notitle with points ls 4 pt 1 ps 0.7 axes x1y2, \\\n\nset bmargin at screen 0.23\nset tmargin at screen 0.38\n\nset title \"MemtierBenchmark: DataSize=256B, Pipeline=Disabled\" font \",20\"\nset ytics 50000\nset ytic add (\"50K\" 50000, \"100K\" 100000, \"150K\" 150000, \"200K\" 200000)\nset yrange[0:200000]\nset y2range[0:20]\n\nset ylabel \"RPS_{set+get}, 1K=10^3\" offset 0.5,0 font \",16\"\n\nplot 'input4' \\\n              using 1:2  title \"1Core-Twemproxy \" with linespoints ls 1, \\\n           '' using 1:4  title \"4Core-Codis 2.0 \" with linespoints ls 3, \\\n           '' using 1:6  title \"8Core-Codis 2.0 \" with linespoints ls 5, \\\n           '' using 1:7  notitle with points ls 1 pt 1 ps 0.7 axes x1y2, \\\n           '' using 1:9  notitle with points ls 3 pt 1 ps 0.7 axes x1y2, \\\n           '' using 1:11 notitle with points ls 5 pt 1 ps 0.7 axes x1y2, \\\n           '' using 1:3  title \"4Core-Codis 1.9 \" with linespoints ls 2, \\\n           '' using 1:5  title \"8Core-Codis 1.9 \" with linespoints ls 4, \\\n           '' using 1:8  notitle with points ls 2 pt 1 ps 0.7 axes x1y2, \\\n           '' using 1:10 notitle with points ls 4 pt 1 ps 0.7 axes x1y2, \\\n\nset bmargin at screen 0.03\nset tmargin at screen 0.18\n\nset title \"MemtierBenchmark: DataSize=256B, Pipeline=100\" font \",20\"\nset ytics 400000\nset ytic add (\"400K\" 400000, \"800K\" 800000, \"1200K\" 1200000)\nset yrange[0:1200000]\nset y2range[0:1200]\n\nset ylabel \"RPS_{set+get}, 1K=10^3\" offset 0.5,0 font \",16\"\n\nplot 'input5' \\\n              using 1:2  title \"1Core-Twemproxy \" with linespoints ls 1, \\\n           '' using 1:4  title \"4Core-Codis 2.0 \" with linespoints ls 3, \\\n           '' using 1:6  title \"8Core-Codis 2.0 \" with linespoints ls 5, \\\n           '' using 1:7  notitle with points ls 1 pt 1 ps 0.7 axes x1y2, \\\n           '' using 1:9  notitle with points ls 3 pt 1 ps 0.7 axes x1y2, \\\n           '' using 1:11 notitle with points ls 5 pt 1 ps 0.7 axes x1y2, \\\n           '' using 1:3  title \"4Core-Codis 1.9 \" with linespoints ls 2, \\\n           '' using 1:5  title \"8Core-Codis 1.9 \" with linespoints ls 4, \\\n           '' using 1:8  notitle with points ls 2 pt 1 ps 0.7 axes x1y2, \\\n           '' using 1:10 notitle with points ls 4 pt 1 ps 0.7 axes x1y2, \\\n\nunset multiplot\n"
  },
  {
    "path": "doc/bench2/input1",
    "content": "1   18557.08  10126.97   10883.62   10796.98  11399.43  1   1   1  1  1\n2   37087.41  19901.09   22334.27   20070.87  22408.56  1   1   1  1  1\n3   52125.27  42667.45   46011.69   40016.45  43812.52  1   1   1  1  1\n4   52307.00  76266.47   80267.35   69981.97  71418.55  1   1   1  1  1\n5   54676.63  86677.25   92227.70   73426.84  90514.09  1   1   1  1  1\n6   71500.14  98354.54   97808.77   84222.51  83602.82  1   1   1  1  1\n7   62605.95  100078.19  86211.00   88522.30  87448.77  2   1   1  1  1\n8   63777.57  104774.60  107280.47  72165.25  79597.92  2   2   2  2  1\n9   86159.48  104064.73  98844.42   71535.88  72350.91  3   4   2  3  3\n10  89301.70  83330.30   87799.63   71192.47  83287.50  4   5   3  4  3\n11  90917.45  83030.51   86069.81   73734.88  79979.71  5   6   4  5  4\n12  92455.69  99800.77   85077.60   83511.26  75255.93  7   8   5  6  5\n13  86845.13  84382.34   83571.24   76398.26  73437.91  11  12  7  9  9\n"
  },
  {
    "path": "doc/bench2/input2",
    "content": "1   217536.05  13450.21   212852.50  14612.26   190323.13   1     2   1    1   1\n2   226996.26  27849.18   304040.84  27458.61   329400.00   1     1   1    1   1\n3   231413.04  58685.50   371179.80  55580.67   439968.55   3     1   5    1   1\n4   207892.34  94165.84   483756.61  101007.28  510752.24   5     1   8    1   6\n5   159301.84  114660.70  525299.72  161634.98  694435.41   14    1   12   1   9\n6   127820.05  138419.41  560700.35  209308.10  800491.85   32    1   20   1   13\n7   110602.24  167084.04  595707.75  251492.14  866241.69   68    2   30   3   22\n8   104896.98  179419.74  588179.63  280726.60  916997.87   110   3   43   3   29\n9   95638.43   199807.57  586615.81  311390.06  949709.60   257   6   62   6   43\n10  92993.80   215280.95  575916.60  323668.36  954504.63   394   7   85   9   57\n11  88639.33   213952.57  573628.66  328387.91  937307.81   537   9   100  13  54\n12  85187.05   215324.17  570163.94  330408.97  1003406.66  712   12  139  15  61\n13  98949.60   213544.82  533352.84  337346.11  886048.81   1062  22  180  23  117\n"
  },
  {
    "path": "doc/bench2/input3",
    "content": "1   32791.18  752.88   36521.68  818.00   30865.15   4     2     1    2    1\n2   31797.51  1592.48  57084.14  1608.30  57250.82   7     2     5    2    1\n3   30525.96  3471.98  61184.53  3124.32  83347.23   15    2     19   2    7\n4   23764.26  4806.31  76167.27  5775.51  94966.77   38    4     25   3    15\n5   19614.00  5089.84  79321.01  6550.50  111358.58  88    6     37   5    22\n6   16085.19  5437.29  75780.54  6682.26  113263.10  214   10    62   9    39\n7   15192.95  5796.43  76196.28  6620.32  118231.26  524   17    75   18   53\n8   16202.99  5949.90  75318.22  6658.23  115955.48  767   24    92   23   60\n9   21835.01  5791.06  72600.55  6625.59  115154.30  1177  48    110  75   71\n10  19363.33  5857.37  73730.00  6498.78  116009.28  1755  240   132  85   85\n11  20329.34  5842.49  72150.07  6587.40  114876.51  2313  403   155  134  107\n12  19555.69  5883.22  72139.66  6555.23  114116.18  3605  651   174  178  123\n13  20899.08  5745.48  68422.85  6012.51  109745.38  5012  1255  187  344  196\n"
  },
  {
    "path": "doc/bench2/input4",
    "content": "1   18213.37  8363.70    10106.52   9801.79    10729.49   0   0   0   0   0\n2   33021.27  15056.21   18510.74   16631.42   19124.33   0   0   0   0   0\n3   47109.41  32931.01   41944.46   36300.49   39016.04   0   0   0   0   0\n4   57288.84  57132.91   74675.84   63812.02   68685.35   0   0   0   0   0\n5   60981.01  79362.61   89707.47   108130.58  106533.88  0   0   0   0   0\n6   64579.85  98426.50   102812.05  138478.16  124839.63  0   0   0   0   0\n7   68559.04  118235.92  118499.18  150943.66  134676.47  1   1   1   0   1\n8   76015.01  132257.13  129295.00  133290.50  147886.57  1   1   1   1   1\n9   80378.23  142312.40  138818.15  139898.73  144979.13  2   3   2   2   2\n10  80651.44  150447.86  142520.34  142068.74  138247.05  4   5   4   3   4\n11  79152.14  148696.10  145735.55  135345.78  139994.88  6   7   5   4   5\n12  82153.48  150665.06  143447.49  135004.25  138176.31  7   8   7   7   6\n13  77017.30  144709.84  149897.36  136054.61  136588.44  12  14  10  11  9\n"
  },
  {
    "path": "doc/bench2/input5",
    "content": "1   5073.26    11934.46   226841.37  15205.84   214063.54  25    17   1    7    0\n2   9444.98    20950.69   299400.73  24875.48   368756.07  27    15   2    11   2\n3   16815.70   47909.52   397770.81  50147.71   568067.12  34    17   4    12   3\n4   29036.23   74688.73   458878.20  92498.53   645532.13  33    17   8    12   8\n5   42559.78   102813.97  488897.07  149738.27  734264.80  46    24   15   15   12\n6   58327.30   127382.00  523704.98  196562.63  791882.36  64    35   22   22   19\n7   69022.80   149836.07  536514.73  236464.70  838726.34  103   58   33   35   27\n8   63826.36   167621.65  569726.54  262442.22  870963.76  169   76   45   48   35\n9   70513.29   185076.56  552312.36  290947.95  918260.99  287   134  84   85   56\n10  75395.48   192887.77  544043.43  304980.93  919270.73  407   186  158  120  98\n11  77724.21   194410.52  544305.59  313683.72  899214.65  534   251  220  156  148\n12  82208.52   194951.36  541037.96  314984.15  871556.77  724   305  279  196  190\n13  109130.65  189885.50  529682.89  317095.60  870566.88  1051  484  422  299  279\n"
  },
  {
    "path": "doc/benchmark.md",
    "content": "\n## Performance (Benchmark)\n#### Intel(R) Core(TM) i7-4770 CPU @ 3.40GHz x 1 + 16G RAM\n+ Archlinux: 4.0.5-1-ARCH #1 SMP PREEMPT Sat Jun 6 18:37:49 CEST 2015 x86\\_64 GNU/Linux\n\n+ Go: go version go1.4.2 linux/amd64\n\n+ Redis x 4:\n\n```bash\n  for i in {6380..6383}; do\n    nohup codis-server ${i}.conf &\n  done\n```\n\n+ Twemproxy - 1CPU:\n  - nutcracker -c nutcracker.yml\n\n```yml\nalpha:\n  listen: 127.0.0.1:22120\n  hash: crc32a\n  hash_tag: \"{}\"\n  distribution: ketama\n  auto_eject_hosts: false\n  timeout: 400\n  redis: true\n  servers:\n   - 127.0.0.1:6380:1\n   - 127.0.0.1:6381:1\n   - 127.0.0.1:6382:1\n   - 127.0.0.1:6383:1\n```\n\n+ Codis - 4CPU:\n\n```bash\ncodis-proxy --ncpu=4 -c config.toml -L proxy.log \\\n  --host-proxy=0.0.0.0:19000 --host-admin=0.0.0.0:10000 &\n```\n\n+ RedisBenchmark - 1CPU:\n\n```bash\nfor clients in {1,2,4,8,16,32,64,100,200,300,500,800}; do\n  redis-benchmark -p $target -c $clients -n 5000000 -P 100 \\\n    -r 1048576 -d 256 -t get,set,mset\ndone\n```\n\n+ Benchmark Results:\n\n![main](bench1/bench.png)\n\n#### Intel(R) Xeon(R) CPU E5-2620 v2 @ 2.10GHz x 2 + 64G RAM\n+ CentOS: 2.6.32-279.el6.x86\\_64 #1 SMP Fri Jun 22 12:19:21 UTC 2012 x86\\_64 x86\\_64 x86\\_64 GNU/Linux\n\n+ Go: go version go1.3.3 linux/amd64\n\n+ Redis x 8:\n\n```bash\n  for i in {6380..6387}; do\n    nohup codis-server ${i}.conf &\n  done\n```\n\n+ Twemproxy - 1CPU:\n  - nutcracker -c nutcracker.yml\n\n```yml\nalpha:\n  listen: 127.0.0.1:22120\n  hash: crc32a\n  hash_tag: \"{}\"\n  distribution: ketama\n  auto_eject_hosts: false\n  timeout: 400\n  redis: true\n  servers:\n   - 127.0.0.1:6380:1\n   - 127.0.0.1:6381:1\n   - 127.0.0.1:6382:1\n   - 127.0.0.1:6383:1\n   - 127.0.0.1:6384:1\n   - 127.0.0.1:6385:1\n   - 127.0.0.1:6386:1\n   - 127.0.0.1:6387:1\n```\n\n+ Codis - 4CPU or 8CPU:\n\n```bash\ncodis-proxy --ncpu=4 -c config.toml -L proxy.log \\\n  --host-proxy=0.0.0.0:19000 --host-admin=0.0.0.0:10000 &\n```\n\n```bash\ncodis-proxy --ncpu=8 -c config.toml -L proxy.log \\\n  --host-proxy=0.0.0.0:19000 --host-admin=0.0.0.0:10000 &\n```\n\n+ RedisBenchmark - 1CPU:\n\n```bash\nfor clients in {1,2,4,8,16,32,64,100,200,300,500,800}; do\n  redis-benchmark -p $target -c $clients -n 5000000 -P 100 \\\n    -r 1048576 -d 256 -t get,set,mset\ndone\n```\n\n+ MemtierBenchmark - 4CPU:\n\n```bash\nfor i in {1,2,4,8,16,32,64,100,200,300,500,800}; do\n  nthread=4\n  if [ $i -lt 4 ]; then\n    nthread=1\n  fi\n  let nclient=\"$i/$nthread\"\n  memtier_benchmark -p $target -t $nthread -c $nclient \\\n    --ratio=1:1 --test-time 30 -d 256 --key-pattern=S:S --pipeline=100\ndone\n```\n\n+ Benchmark Results:\n\n![main](bench2/bench.png)\n"
  },
  {
    "path": "doc/pictures/.gitignore",
    "content": "tmp\n"
  },
  {
    "path": "doc/pictures/Makefile",
    "content": "all:\n\t@mkdir -p tmp\n\t@xelatex -output-directory tmp architecture.tex\n\t@convert -density 300 tmp/architecture.pdf -quality 90 -background white -alpha off architecture.png\n\n"
  },
  {
    "path": "doc/pictures/architecture.tex",
    "content": "\\documentclass{article}\n\\usepackage[letterpaper, landscape, margin=2in]{geometry}\n\\usepackage[active,tightpage]{preview}\n\\PreviewBorder=12pt\n\n\\usepackage{tikz}\n\\usetikzlibrary{positioning,shapes,arrows,decorations,decorations.pathreplacing}\n\n\\begin{document}\n\\begin{preview}\n\\begin{tikzpicture}[x=1pt,y=1pt,auto]\n    \\tikzstyle{every node}=[draw=black,fill=white,rectangle,minimum height=28,node distance=0,inner sep=0,rounded corners]\n    \\tikzstyle{note}=[draw=none,opaque,fill=none]\n    \\tikzstyle{proxy}=[minimum width=90]\n    \\tikzstyle{group}=[minimum width=70,minimum height=22]\n    \\tikzstyle{server}=[group,minimum width=80,minimum height=18]\n    \\tikzstyle{client}=[proxy,minimum width=58,rounded corners=0]\n    \\tikzstyle{dashboard}=[minimum width=100]\n    {\n        \\node[proxy] (p0) at (200,0) {codis-proxy};\n        \\node[proxy] (p1) at (340,0) {codis-proxy};\n        \\node[proxy] (p2) at (470,0) {codis-proxy};\n        \\node[note] at (270,0) {\\ldots};\n        \\node[dashboard] (d0) at (405,60) {codis-dashboard};\n\n        \\node[client] (c0) at (165, 120) {jodis-client};\n        \\node[client] (c1) at (235, 120) {redis-client};\n        \\draw[decorate,decoration={brace,amplitude=3}]\n                (235,105) -- (165,105) node[note] (cm) {};\n\n        \\node[dashboard,minimum width=70] (fe) at (405,120) {codis-fe};\n\n        \\path[->,>=stealth',shorten >=1pt,shorten <=1pt,auto]\n            (d0) edge (p0)\n            (d0) edge node[note,right,inner sep=20pt] {\\scriptsize{RESTful API}} (p1.north)\n            (d0) edge (p2.north)\n            (fe) edge (d0)\n            (200, 102) edge (p0);\n\n        \\newcount\\pos\n        \\foreach \\i in {0,1,2,3} {\n            \\pos=\\i\n            \\multiply\\pos by 90\n            \\node[group] (g\\i) at (\\pos+200,-60) {\\small{codis-group}};\n            \\foreach \\j in {0,1,2} {\n                \\path[->,>=stealth',shorten >=1pt,shorten <=1pt,auto]\n                    (p\\j.south) edge (g\\i.north);\n            }\n        }\n\n        \\node[draw=gray,minimum width=130,minimum height=70,rounded corners=0] (box) at (600, -120) {};\n        \\node[server] (s0) at (590, -100) {\\small{codis-server:0}};\n        \\node[server] (s1) at (590, -120) {\\small{codis-server:1}};\n        \\node[server] (s2) at (590, -140) {\\small{codis-server:2}};\n        \\node[note,right=of s0] {\\scriptsize{\\hspace{0.4em}master}};\n        \\node[note,right=of s1] {\\scriptsize{\\hspace{0.4em}slave}};\n        \\node[note,right=of s2] {\\scriptsize{\\hspace{0.4em}slave}};\n\n        \\path[shorten >=1pt,shorten <=1pt,auto,dotted]\n            (g3.east) edge (box.north east)\n            (g3.south) edge (box.south west);\n\n        \\node[draw,cloud,cloud puffs=9,minimum width=100pt,minimum height=60pt] (cloud1) at (600, 100) {};\n        \\node[note] at (600,100) {Storage};\n        \\path[->,>=stealth',shorten >=1pt,shorten <=1pt]\n            (d0) edge node[note,above,outer sep=-7pt,sloped,anchor=south,auto=false] {\\scriptsize{CRUD/List}} (cloud1);\n\n        \\node[draw,cloud,cloud puffs=12,minimum width=80pt,minimum height=40pt] (cloud2) at (100, 55) {};\n        \\node[note] at (100,55) {\\small{zookeeper}};\n        \\path[->,>=stealth',shorten >=2pt,shorten <=2pt,dashed]\n            (p0.west) edge[bend left=15] node[note,above,outer sep=-7pt,sloped,anchor=south,auto=false] {\\scriptsize{jodis}} (cloud2)\n            (cloud2) edge[bend left=15] node[note,above,outer sep=-7pt,sloped,anchor=south,auto=false] {} (c0);\n\n        \\node[draw,cloud,cloud puffs=12,minimum width=80pt,minimum height=40pt] (cloud3) at (600, 30) {};\n        \\node[note] at (600,30) {redis-sentinel};\n        \\path[->,>=stealth',shorten >=1pt,shorten <=1pt]\n            (p2.east) edge[bend right=15] node[note,above,outer sep=-7pt,sloped,anchor=south,auto=false] {\\scriptsize{subscribe}} (cloud3)\n            (cloud3.south) edge node[note,above,outer sep=-7pt,sloped,anchor=south,auto=false] {\\scriptsize{HA: ping}} (box)\n            (d0) edge node[note,above,outer sep=-7pt,sloped,anchor=south,auto=false] {\\scriptsize{monitor}} (cloud3);\n    }\n\\end{tikzpicture}\n\\end{preview}\n\\end{document}\n"
  },
  {
    "path": "doc/redis_change_zh.md",
    "content": "### redis 修改部分（增加若干指令） \n--------------------------------\n\n##### SLOTSINFO [start] [count] \n\n+ 命令说明：获取 redis 中 slot 的个数以及每个 slot 的大小\n\n+ 命令参数：缺省查询 [0, MAX\\_SLOT\\_NUM)\n\n  - start - 起始的 slot 序号\n\n    缺省 = 0\n\n  - count - 查询的区间的大小，即查询范围为 [start, start + count)\n\n    缺省 = MAX\\_SLOT\\_NUM\n\n+ 返回结果：返回结果是 slotinfo 的 array；slotinfo 本身也是一个 array。\n\n        response := []slotinfo{slot1, slot2, slot3, ...}\n        slotinfo := []int{slotnum, slotsize}\n\n        其中：\n            INT slotnum  : slot 序号\n            INT slotsize : slot 内数据个数\n\n+ 例如：\n\n        localhost:6379> slotsinfo 0 128\n            1) 1) (integer) 23\n               2) (integer) 2\n            2) 1) (integer) 29\n               2) (integer) 1\n\n##### SLOTSSCAN slotnum cursor [COUNT count]\n\n+ 命令说明：获取指定 slotnum 下的 key 列表\n\n+ 命令参数：参数说明类似 SCAN 命令\n\n    - slotnum - 查询的 slot 序号，[0, MAX\\_SLOT\\_NUM）\n\n    - cursor - 说明参考 SCAN 命令\n\n    - [COUNT count) - 说明参考 SCAN 命令\n\n        - 暂不支持 MATCH 查询\n\n+ 返回结果：参考 SCAN 命令\n\n    - 返回更新后的 cursor 以及一组 key 列表\n\n+ 例如:\n\n        localhost:6379> slotsscan 579 0 COUNT 10\n            1) \"10752\"\n            2)  1) \"{a}7836\"\n                2) \"{a}2167\"\n                3) \"{a}5332\"\n                4) \"{a}6292\"\n                5) \"{a}600\"\n                6) \"{a}6094\"\n                7) \"{a}7754\"\n                8) \"{a}4929\"\n                9) \"{a}9211\"\n               10) \"{a}6596\"\n\n##### SLOTSDEL slot1 [slot2 …]\n\n+ 命令说明：删除 redis 中若干 slot 下的全部 key-value\n\n+ 命令参数：接受至少 1 个 slotnum 作为参数\n\n+ 返回结果：格式参见 slotsinfo，不同的是：slotsize 表示删除后剩余大小，通常为 0。\n\n+ 例如：\n\n        localhost:6379> slotsdel 1013 990\n            1) 1) (integer) 1013\n               2) (integer) 0\n            2) 1) (integer) 990\n               2) (integer) 0\n\n#### 数据迁移\n---------------\n\n**以下4个命令是一族命令：**\n\n+ SLOTSMGRTSLOT - *O(1)*\n\n    随机在某个 slot 下迁移一个 key-value 到目标机器\n\n+ SLOTSMGRTONE - *O(1)*\n\n    将指定的 key-value 迁移到目标机\n\n+ SLOTSMGRTTAGSLOT - *O(log(n))*\n\n    随机在某个 slot 下选择一个 key，并将与之有相同 tag 的 key-value 对全部迁移到目标机\n\n+ SLOTSMGRTTAGONE - *O(log(n))*\n\n    将与指定 key 具有相同 tag 的所有 key-value 对迁移到目标机\n\n\n##### SLOTSMGRTSLOT host port timeout slot\n\n+ 命令说明：随机选择 slot 下的 1 个 key-value 到迁移到目标机（同步 IO 操作）\n\n    - 如果当前 slot 已经空了或者选择的 key 刚好过期，返回 0\n\n    - 如果当前 slot 下面还有 key 则选择一个进行迁移\n\n    - 同时返回当前 slot 剩余 key 的个数\n\n    - 迁移过程在目标机器调用 slotsrestore 命令，迁移会 **覆盖旧值**\n\n\n+ 命令参数：\n\n    - host:port - 目标机\n\n        redis 内部缓存到 host:port 的连接 30s，超时或错误则关闭\n\n    - timeout - 操作超时，单位 ms\n\n        过程需要 3 个同步操作：\n\n        1. 建立连接（可被缓存优化）\n\n        2. 发送 key-value 数据\n\n        3. 接受目标机返回\n\n        指令保证每个操作不超过 timeout\n\n    - slot - 指定迁移的 slot 序号\n\n+ 返回结果： 操作返回 int\n\n        response := []int{succ,size}\n\n        其中：\n            INT succ : 表示迁移是否成功。\n                0 表示当前 slot 已经空了（迁移成功个数=0）\n                1 表示迁移一个 key 成功，并从本地删除（迁移成功个数=1）\n            INT size : 表示 slot 下剩余 key 的个数\n\n+ 例如：\n\n        localhost:6379> set a 100            # set <a, 100>\n            OK\n        localhost:6379> slotsinfo            # slot 大小为 1\n            1) 1) (integer) 579\n               2) (integer) 1\n        localhost:6379> slotsmgrt 127.0.0.1 6380 100 579\n            (integer) 1                      # 成功迁移 value\n        localhost:6379> slotsinfo\n            (empty list or set)\n        localhost:6379> slotsmgrt 127.0.0.1 6380 100 579 1\n            (integer) 0                      # 成功成功个数为 0；当前 slot 已经空了\n\n\n##### SLOTSMGRTONE host port timeout key\n\n+ 命令说明：迁移 key 到目标机，与 slotsmgrtslot 相同\n\n+ 命令参数：参见 slotsmgrtslot\n\n+ 返回结果： 操作返回 整数 (int)\n\n        response := int(succ)\n\n        其中：\n            INT succ : 与 slotsmgrtslot 相似\n\n+ 例如：\n\n        localhost:6379> set a 100            # set <a, 100>\n            OK\n        localhost:6379> slotsinfo\n            1) 1) (integer) 579\n               2) (integer) 1\n        localhost:6379> slotsmgrtone 127.0.0.1 6380 100 a\n            (integer) 1                      # 迁移成功\n        localhost:6379> slotsmgrtone 127.0.0.1 6380 100 a\n            (integer) 0                      # 放弃迁移，本地已经不存在了\n\n##### SLOTSMGRTTAGONE host port timeout key\n\n+ 命令说明：迁移与 key 有相同的 tag 的所有 key 到目标机\n\n    - 当 key 中不包含合法 tag 时，命令退化为 slotsmgrtone，**复杂度为** ***O(1)***\n\n    - 当 key 中包含合法 tag 时，命令会计算 tag 的 hash 值，并在 skiplist 中找到所有具有相同 hash 值的 key-value 对，原子的迁移到目标机，**复杂度为** ***O(log(n))***\n\n    - **备注：修改的 redis 中，会将所有含有 tag 的 key，组织在 skiplist 中，并按照 tag 的 hash 值进行排序。当对按照某一 tag 进行迁移数据时，实际操作会将所有具有相同 hash 值的 tag 所涉及到的所有 key 一起迁移。也就是说，真正迁移的数据可能包含更多的 key，但是这么设计会减少 tag 迁移过程对字符串的比较次数，显著提升性能。**\n\n+ 命令参数：参见 slotsmgrtone\n\n+ 返回结果： 操作返回 整数 (int)\n\n        response := int(succ)\n\n        其中：\n            INT succ : 表示成功迁移的 key 的个数。\n\n+ 例如：\n\n        localhost:6379> set a{tag} 100        # set <a{tag}, 100>\n            OK\n        localhost:6379> set b{tag} 100        # set <b{tag}, 100>\n            OK\n        localhost:6379> slotsmgrttag 127.0.0.1 6380 1000 {tag}\n            (integer) 2\n        localhost:6379> scan 0                # 迁移成功，本地不存在了\n            1) \"0\"\n            2) (empty list or set)\n        localhost:6380> scan 0                # 数据一次成功迁移到目标机\n            1) \"0\"\n            2) 1) \"a{tag}\"\n               2) \"b{tag}\"\n\n##### SLOTSMGRTTAGSLOT host port timeout slot\n\n+ 命令说明：与 slotsmgrtslot 对应的迁移指令\n\n    - 其他说明参考 slotsmgrtslot 以及 slotsmgrttagone 的解释即可\n\n##### SLOTSRESTORE key1 ttl1 val1 [key2 ttl2 val2 …]\n\n+ 命令说明：该命令是对 redis-2.8 的 restore 命令的扩展\n\n    - 可以对 restore 多个 key-value\n\n    - 过程是原子的。\n\n+ **备注：与 restore 不同的是，slotsrestore 只支持 replace，即一定** ***覆盖旧值*** **。如果旧值已经存在，那么只可能是 redis-slots 或者 proxy 的实现 bug，程序会通过 redisLog 打印一条冲突记录。**\n\n#### 调试相关\n---------------\n\n##### SLOTSHASHKEY key1 [key2 …]\n\n+ 命令说明：计算并返回给定 key 的 slot 序号\n\n+ 命令参数：输入为 1 个或多个 key\n\n+ 返回结果： 操作返回 array\n\n        response := []int{slot1, slot2...}\n\n        其中：\n            INT slot : 表示对应 key 的 slot 序号，即 hash32(key) % NUM_OF_SLOTS\n\n+ 例如：\n\n        localhost:6379> slotshashkey a b c   # 计算 <a,b,c> 的 slot 序号\n            1) (integer) 579\n            2) (integer) 1017\n            3) (integer) 879\n\n##### SLOTSCHECK\n\n+ 命令说明：对 redis 内的 slots 进行一致性检查，即满足如下两条\n\n    - 每个 slot 中保存的 key 都能在 db 中找到对应的 val\n\n    - 每个 db 中的 key 都能在对应的 slot 中查找到\n\n+ 命令参数：0 参数\n\n+ 返回结果： 操作返回 字符串 OK（如果 check 失败，会返回 ERR 并包含对应出错的 key）\n\n+ 例如：\n\n        localhost:6379> set a 100            # set <a, 100>\n            OK\n        localhost:6379> slotscheck\n            OK                               # 检查通过\n        …\n        localhost:6379> slotscheck\n            OK                               # 检查通过，但是耗时 1.07s\n            (1.07s)\n\n+ **备注**：***该操作比较慢，仅仅作为 redis 开发的调试工具使用，不能在线上使用***\n"
  },
  {
    "path": "doc/tutorial_en.md",
    "content": "# Codis Tutorial\n\nCodis is a distributed Redis solution, there is no obvious difference between connecting to a Codis proxy and an original Redis server, top layer application can connect to Codis as normal standalone Redis, Codis will forward low layer requests. Hot data migration and all things in the shadow are transparent to client. Simply treat Codis as a Redis service with unlimited RAM. \n\n\nCodis 3.x consists of the following components:\n\n* **Codis Server**: based on redis-3.2.8 branch development. Added additional data structures to support slot-related operations and data migration instructions. Specific changes can refer to the document [redis changes](redis_change_zh.md).\n\n* **Codis Proxy**: is the proxy service of client connections. Codis Proxy Implements Redis Protocol. In addition to some commands do not support ([unsupported command list](unsupported_cmds.md)).\n\n    + For the same product cluster, you can deploy multiple codis-proxy instances at the same time;\n    + Different codis-proxy by codis-dashboard to ensure state synchronization.\n\n* **Codis Dashboard**: cluster management tools, support codis-proxy, codis-server add, delete, slot migrate(sync/async), and other operations. When a cluster state changes, the codis-dashboard maintains the consistency of all codis-proxy states under the cluster.\n\n    + For the same product cluster, the same time codis-dashboard can only have 0 or 1;\n    + All changes to the cluster must be done via codis-dashboard.\n\n* **Codis Admin**: Command-line tool for cluster management.\n\n    + Can be used to control the codis-proxy, codis-dashboard status, and access external storage.\n\n* **Codis FE**: cluster management Web Interface.\n\n    + Multiple cluster instances can share the same front-end display page;\n    + FE reads all cluster instances name from external storage.\n\n* **Storage**: Provides external storage for cluster status, and saves cluster metadata.\n\n    + Provide the concept of Namespace, different clusters will be organized according to different product name;\n    + Currently only provides Zookeeper, Etcd, Fs three implementations, but provides an abstract interface can be self-expansion.\n\n\n##  Getting Codis\n\n### Download Pre-built Release Binaries\n\nThe easiest way to get codis is to use one of the pre-built release binaries which are available for OSX, Linux. Instructions for using these binaries are on the [GitHub releases page][github-release].\n\n### Compile Source Code\n\nFor those wanting to try the very latest version, build the latest version of codis from the `master` branch. This first needs [*Go*](https://golang.org/) installed (version 1.7+ is required). All development occurs on `master`, including new features and bug fixes. Bug fixes are first targeted at `master` and subsequently ported to release branches.\n\n\n#### 1. Install Go Environment [reference](https://golang.org/doc/install)\n\nAfter the installation is complete, you can run the following command to detect：\n\n```bash\n$ go version\ngo version go1.7.3 linux/amd64\n```\n\n#### 2. Set the compilation environment\n\nAdd `$GOPATH/bin` To `$PATH`，For Example：`PATH=$PATH:$GOPATH/bin`。\n\n```bash\n$ go env GOPATH\n/home/codis/gopath\n```\n\n#### 3. Download Codis Source Code\n\nThe Codis source code needs to be downloaded to `$GOPATH/src/github.com/CodisLabs/codis`：\n\n```bash\n$ mkdir -p $GOPATH/src/github.com/CodisLabs\n$ cd $_ && git clone https://github.com/CodisLabs/codis.git -b release3.2\n```\n\n#### 4. Compile Codis Source Code\n\n* use make tool to compile：\n\n```bash\n$ cd $GOPATH/src/github.com/CodisLabs/codis\n$ make\nmake -j -C extern/redis-3.2.8/\n... ...\ngo build -i -o bin/codis-dashboard ./cmd/dashboard\ngo build -i -o bin/codis-proxy ./cmd/proxy\ngo build -i -o bin/codis-admin ./cmd/admin\ngo build -i -o bin/codis-fe ./cmd/fe\n\n$ ls bin/\ntotal 69124\ndrwxr-xr-x 4 codis codis     4096 Jan  4 14:55 assets\n-rwxr-xr-x 1 codis codis 17600752 Jan  4 14:55 codis-admin\n-rwxr-xr-x 1 codis codis 18416320 Jan  4 14:55 codis-dashboard\n-rwxr-xr-x 1 codis codis  9498040 Jan  4 14:55 codis-fe\n-rwxr-xr-x 1 codis codis 11057280 Jan  4 14:55 codis-proxy\n-rwxr-xr-x 1 codis codis  4234432 Jan  4 14:55 codis-server\n-rw-r--r-- 1 codis codis      148 Jan  4 14:55 version\n... ...\n\n$ cat bin/version\nversion = 2016-01-03 14:53:22 +0800 @51f06ae3b58a256a58f857f590430977638846a3\ncompile = 2016-01-04 15:00:17 +0800 by go version go1.5.2 linux/amd64\n```\n\n## Running Codis Cluster\n\nBuild a standalone codis cluster in 2 minutes,without any external component dependencies.\nThe admin folder in the source code provides a series of scripts to quickly start, stop the codis components, improve the efficiency of operation and maintenance.\n\n\n### Start codis-dashboard\nUse codis-dashboard-admin.sh script to start dashboard and check the dashboard log to confirm whether there is an exception.\n```\n./admin/codis-dashboard-admin.sh start\n tail -100 ./log/codis-dashboard.log.2017-04-08\n```\n```\n2017/04/08 15:16:57 fsclient.go:197: [INFO] fsclient - create /codis3/codis-demo/topom OK\n2017/04/08 15:16:57 main.go:140: [WARN] [0xc42025f7a0] dashboard is working ...\n2017/04/08 15:16:57 topom.go:424: [WARN] admin start service on [::]:18080\n\n```\n\nThe default external storage Uses filesystem, the default data path is saved in /tmp/codis. If the startup fails, please check whether the current user has read/write access to the path.\n\n\n### Start codis-proxy\nUse codis-proxy-admin.sh script to start codis-proxy and check the proxy log to confirm whether there is an exception.\n```\n./admin/codis-proxy-admin.sh start\ntail -100 ./log/codis-proxy.log.2017-04-08\n```\n\n```\n2017/04/08 15:39:37 proxy.go:293: [WARN] [0xc4200df760] set sentinels = []\n2017/04/08 15:39:37 main.go:320: [WARN] rpc online proxy seems OK\n2017/04/08 15:39:38 main.go:210: [WARN] [0xc4200df760] proxy is working ...\n```\n\n### Start codis-server\nUse codis-server-admin.sh script to start codis-server and check the redis log to confirm whether there is an exception.\n```\n./admin/codis-server-admin.sh start\ntail -100 /tmp/redis_6379.log \n```\n\n```\n5706:M 08 Apr 16:04:11.748 * DB loaded from disk: 0.000 seconds\n5706:M 08 Apr 16:04:11.748 * The server is now ready to accept connections on port 6379\n```\nredis.conf pidfile,logfile default saves in the /tmp directory. If the startup fails, please check whether the current user has read/write access to the path.\n\n### Start codis-fe\nUse codis-fe-admin.sh script to start codis-fe and check the redis log to confirm whether there is an exception.\n```\n./admin/codis-fe-admin.sh start\ntail -100 ./log/codis-fe.log.2017-04-08\n```\n```\n2017/04/08 16:12:13 main.go:100: [WARN] set ncpu = 1\n2017/04/08 16:12:13 main.go:103: [WARN] set listen = 0.0.0.0:9090\n2017/04/08 16:12:13 main.go:115: [WARN] set assets = /home/codis/go/src/github.com/CodisLabs/codis/admin/../bin/assets\n2017/04/08 16:12:13 main.go:153: [WARN] set --filesystem = /tmp/codis\n```\n\n### Add group by fe\n\nPlease visit the cluster management web page(fe url:127.0.0.1:9090)\nSelect the cluster(codis-demo) we have just built, in the Proxy column we can see that we have activated the Proxy,\nBut the Group column is empty, because codis-server is not joined the cluster.\n\nAdd NEW GROUP\nIn the `NEW GROUP` row, please input a number such as 1, and click NEWGROUP\n\nAdd Codis Server\n\nIn the `Add Server` row, please input the codis-server address we just started, add it to GROUP, and then click the Add Server button, as shown below\n\n![addgroup](pictures/addgroup.jpg)\n\n### Initialize slot by fe\n\nThe new cluster slot status is offline, so we need to initialize it (allocate 1024 slots to each group), and the fastest way to initialize a cluster is to click the `rebalance all slots` button provided by fe, as shown in the following figure.\n\n![rebalance_slots](pictures/rebalance_slots.jpg)\n\n\n## Quickly deploy the cluster by ansible\n\nUse ansible to quickly deploy multiple clusters in standalone and multi-machine environment.\nThe ansible folder contains the playbook for deploying the codis cluster, modifying the parameters in the groups_var / all file according to your own deployment environment, and modifying the hosts file to add the deployed environment IP.\n\nAnsible installation is simple.Once Ansible is installed, there will be no daemons to start or keep running. You only need to install it on one machine and it can manage an entire fleet of remote machines from that central point. \nAnsible by default manages machines over the SSH protocol.\n\n```\ngit clone https://github.com/ansible/ansible.git -b stable-2.3\ncd ./ansible\nsource ./hacking/env-setup\ncd $codis_dir/ansible\nansible-playbook -i hosts site.yml\n```\n\n\n## Codis HA\n\nCodis's proxy is stateless so you can run more than one proxies to get high availability and horizontal scalability.\n\nFor Java users, you can use a modified Jedis, [Jodis](https://github.com/CodisLabs/jodis). It will watch the ZooKeeper to get the real-time available proxies, then query via them using a round robin policy to balance load and detect proxy online and offline automatically.\nIf asynchronous request is required, you can use [Nedis](https://github.com/CodisLabs/nedis) which is implemented based on Netty.\n\nCodis-server is stateful.Redis Sentinel provides high availability for Codis-Server.Codis uses it to check master and slave instances are working as expected and start a failover process where a slave is promoted to master, the other additional slaves are reconfigured to use the new master.\n\n"
  },
  {
    "path": "doc/tutorial_zh.md",
    "content": "# Codis 使用文档\n\nCodis 是一个分布式 Redis 解决方案, 对于上层的应用来说, 连接到 Codis Proxy 和连接原生的 Redis Server 没有显著区别 ([不支持的命令列表](unsupported_cmds.md)), 上层应用可以像使用单机的 Redis 一样使用, Codis 底层会处理请求的转发, 不停机的数据迁移等工作, 所有后边的一切事情, 对于前面的客户端来说是透明的, 可以简单的认为后边连接的是一个内存无限大的 Redis 服务。\n\n## codis版本简介\ncodis目前主要release版本如下:\n### codis 1.9\n> * codis-server 基于 redis-2.8.13\n> * codis-proxy 对 pipeline 支持不友好\n> * codis-proxy 对 zk 强依赖\n> * 同步迁移性能差，不支持大 key 迁移\n### codis 2.0\n> * codis-server 基于 redis-2.8.21\n> * 重构了codis-proxy，性能大幅提升，对 pipeline 支持比较好\n> * codis-proxy 对 zk 强依赖\n> * 同步迁移性能差，不支持大key迁移\n### codis 3.x\n> * 最新 release 版本为 codis-3.2，codis-server 基于 redis-3.2.8\n> * 支持 slot 同步迁移、异步迁移和并发迁移，对 key 大小无任何限制，迁移性能大幅度提升\n> * 相比 2.0：重构了整个集群组件通信方式，codis-proxy 与 zookeeper 实现了解耦，废弃了codis-config 等\n> * 元数据存储支持 etcd/zookeeper/filesystem 等，可自行扩展支持新的存储，集群正常运行期间，即便元存储故障也不再影响 codis 集群，大大提升 codis-proxy 稳定性\n> * 对 codis-proxy 进行了大量性能优化,通过控制GC频率、减少对象创建、内存预分配、引入 `cgo`、`jemalloc` 等，使其吞吐还是延迟，都已达到 codis 项目中最佳\n> * proxy 实现 select 命令，支持多 DB\n> * proxy 支持读写分离、优先读同 IP/同 DC 下副本功能\n> * 基于 redis-sentinel 实现主备自动切换\n> * 实现动态 pipeline 缓存区（减少内存分配以及所引起的 GC 问题）\n> * proxy 支持通过 HTTP 请求实时获取 runtime metrics，便于监控、运维\n> * 支持通过 influxdb 和 statsd 采集 proxy metrics\n> * slot auto rebalance 算法从 2.0 的基于 max memory policy 变更成基于 group 下 slot 数量\n> * 提供了更加友好的 dashboard 和 fe 界面，新增了很多按钮、跳转链接、错误状态等，有利于快速发现、处理集群故障\n> * 新增 `SLOTSSCAN` 指令，便于获取集群各个 slot 下的所有 key\n> * codis-proxy 与 codis-dashbaord 支持 docker 部署\n\nCodis 3.x 由以下组件组成：\n\n* **Codis Server**：基于 redis-3.2.8 分支开发。增加了额外的数据结构，以支持 slot 有关的操作以及数据迁移指令。具体的修改可以参考文档 [redis 的修改](redis_change_zh.md)。\n\n* **Codis Proxy**：客户端连接的 Redis 代理服务, 实现了 Redis 协议。 除部分命令不支持以外([不支持的命令列表](unsupported_cmds.md))，表现的和原生的 Redis 没有区别（就像 Twemproxy）。\n\n    + 对于同一个业务集群而言，可以同时部署多个 codis-proxy 实例；\n    + 不同 codis-proxy 之间由 codis-dashboard 保证状态同步。\n\n* **Codis Dashboard**：集群管理工具，支持 codis-proxy、codis-server 的添加、删除，以及据迁移等操作。在集群状态发生改变时，codis-dashboard 维护集群下所有 codis-proxy 的状态的一致性。\n\n    + 对于同一个业务集群而言，同一个时刻 codis-dashboard 只能有 0个或者1个；\n    + 所有对集群的修改都必须通过 codis-dashboard 完成。\n\n* **Codis Admin**：集群管理的命令行工具。\n\n    + 可用于控制 codis-proxy、codis-dashboard 状态以及访问外部存储。\n\n* **Codis FE**：集群管理界面。\n\n    + 多个集群实例共享可以共享同一个前端展示页面；\n    + 通过配置文件管理后端 codis-dashboard 列表，配置文件可自动更新。\n\n* **Storage**：为集群状态提供外部存储。\n\n    + 提供 Namespace 概念，不同集群的会按照不同 product name 进行组织；\n    + 目前仅提供了 Zookeeper、Etcd、Fs 三种实现，但是提供了抽象的 interface 可自行扩展。\n\n## 0. 下载与编译\n\n### 下载[release binary](https://github.com/CodisLabs/codis/releases)文件安装\n如果是重要的生产环境使用，尽量不要选择alpha、rc版本。\n根据自己的部署平台，选择相应的文件下载即可。\n\n### 编译源码安装\n\n#### 1. 安装 Go 运行环境 [参考这里](https://golang.org/doc/install)\n\n安装完成后可以运行下列命令进行检测：\n\n```bash\n$ go version\ngo version go1.7.3 linux/amd64\n```\n\n#### 2. 设置编译环境\n\n**注意 `$GOPATH` 是本机所有第三方库 go 项目所在目录，Codis 仅是其中之一。**\n\n添加 `$GOPATH/bin` 到 `$PATH`，例如：`PATH=$PATH:$GOPATH/bin`。\n\n```bash\n$ go env GOPATH\n/home/codis/gopath\n```\n\n#### 3. 下载 Codis 源代码\n\nCodis 源代码需要下载到 `$GOPATH/src/github.com/CodisLabs/codis`：\n\n```bash\n$ mkdir -p $GOPATH/src/github.com/CodisLabs\n$ cd $_ && git clone https://github.com/CodisLabs/codis.git -b release3.2\n```\n\n#### 4. 编译 Codis 源代码\n\n* 直接通过 make 进行编译，会看到如下输出：\n\n```bash\n$ cd $GOPATH/src/github.com/CodisLabs/codis\n$ make\nmake -j -C extern/redis-3.2.8/\n... ...\ngo build -i -o bin/codis-dashboard ./cmd/dashboard\ngo build -i -o bin/codis-proxy ./cmd/proxy\ngo build -i -o bin/codis-admin ./cmd/admin\ngo build -i -o bin/codis-fe ./cmd/fe\n\n$ ls bin/\ntotal 69124\ndrwxr-xr-x 4 codis codis     4096 Jan  4 14:55 assets\n-rwxr-xr-x 1 codis codis 17600752 Jan  4 14:55 codis-admin\n-rwxr-xr-x 1 codis codis 18416320 Jan  4 14:55 codis-dashboard\n-rwxr-xr-x 1 codis codis  9498040 Jan  4 14:55 codis-fe\n-rwxr-xr-x 1 codis codis 11057280 Jan  4 14:55 codis-proxy\n-rwxr-xr-x 1 codis codis  4234432 Jan  4 14:55 codis-server\n-rw-r--r-- 1 codis codis      148 Jan  4 14:55 version\n... ...\n\n$ cat bin/version\nversion = 2016-01-03 14:53:22 +0800 @51f06ae3b58a256a58f857f590430977638846a3\ncompile = 2016-01-04 15:00:17 +0800 by go version go1.5.2 linux/amd64\n```\n\n## 1. 快速启动\n2分钟快速构建一个单机版测试 codis 集群，无任何外部组件依赖.\n\n源码中 admin 文件夹提供了一系列脚本以便快速启动、停止各个组件，提高运维效率。\n\n### 启动codis-dashboard\n使用 `codis-dashboard-admin.sh` 脚本启动 dashboard，并查看 dashboard 日志确认启动是否有异常。\n\n```\n./admin/codis-dashboard-admin.sh start\n tail -100 ./log/codis-dashboard.log.2017-04-08\n```\n```\n2017/04/08 15:16:57 fsclient.go:197: [INFO] fsclient - create /codis3/codis-demo/topom OK\n2017/04/08 15:16:57 main.go:140: [WARN] [0xc42025f7a0] dashboard is working ...\n2017/04/08 15:16:57 topom.go:424: [WARN] admin start service on [::]:18080\n```\n\n快速启动集群元数据存储使用 `filesystem`，默认数据路径保存在 `/tmp/codis`，若启动失败，请检查当前用户是否对该路径拥有读写权限。\n\n### 启动codis-proxy\n使用 `codis-proxy-admin.sh` 脚本启动 codis-proxy，并查看 proxy 日志确认启动是否有异常。\n\n```\n./admin/codis-proxy-admin.sh start\ntail -100 ./log/codis-proxy.log.2017-04-08\n```\n```\n2017/04/08 15:39:37 proxy.go:293: [WARN] [0xc4200df760] set sentinels = []\n2017/04/08 15:39:37 main.go:320: [WARN] rpc online proxy seems OK\n2017/04/08 15:39:38 main.go:210: [WARN] [0xc4200df760] proxy is working ...\n```\n\n### 启动codis-server\n使用 `codis-server-admin.sh` 脚本启动 codis-server，并查看 redis 日志确认启动是否有异常。\n\n```\n./admin/codis-server-admin.sh start\ntail -100 /tmp/redis_6379.log \n```\n```\n5706:M 08 Apr 16:04:11.748 * DB loaded from disk: 0.000 seconds\n5706:M 08 Apr 16:04:11.748 * The server is now ready to accept connections on port 6379\n```\nredis.conf 配置中 pidfile、logfile 默认保存在 `/tmp` 目录，若启动失败，请检查当前用户是否有该目录的读写权限。\n\n### 启动codis-fe\n使用 `codis-fe-admin.sh` 脚本启动 codis-fe，并查看 fe 日志确认启动是否有异常。\n\n```\n./admin/codis-fe-admin.sh start\ntail -100 ./log/codis-fe.log.2017-04-08\n```\n```\n2017/04/08 16:12:13 main.go:100: [WARN] set ncpu = 1\n2017/04/08 16:12:13 main.go:103: [WARN] set listen = 0.0.0.0:9090\n2017/04/08 16:12:13 main.go:115: [WARN] set assets = /home/codis/go/src/github.com/CodisLabs/codis/admin/../bin/assets\n2017/04/08 16:12:13 main.go:153: [WARN] set --filesystem = /tmp/codis\n```\n\n### 通过fe添加group\n通过web浏览器访问集群管理页面(fe地址:127.0.0.1:9090)\n选择我们刚搭建的集群 codis-demo，在 Proxy 栏可看到我们已经启动的 Proxy，\n但是 Group 栏为空，因为我们启动的 codis-server 并未加入到集群\n添加 `NEW GROUP`，`NEW GROUP` 行输入 1，再点击 `NEW GROUP` 即可\n添加 Codis Server，`Add Server` 行输入我们刚刚启动的 codis-server 地址，添加到我们刚新建的 Group，然后再点击 `Add Server` 按钮即可，如下图所示\n\n![addgroup](pictures/addgroup.jpg)\n\n### 通过fe初始化slot\n新增的集群 slot 状态是 offline，因此我们需要对它进行初始化（将 1024 个 slot 分配到各个 group），而初始化最快的方法可通过 fe 提供的 `rebalance all slots` 按钮来做，如下图所示，点击此按钮，我们即快速完成了一个集群的搭建。\n\n![rebalance_slots](pictures/rebalance_slots.jpg)\n\n\n## 通过 ansible 快速部署集群\n\n使用 ansible 可快速在单机、多机部署多套 codis 集群。\nansible 文件夹包含了部署 codis 集群的 playbook，根据自己部署环境修改 `groups_var/all` 文件里参数，修改 hosts 文件添加部署的环境 IP 即可。\nansible 安装也及其简单，各部署机器无需安装任何额外的 agent，彼此之间通过 ssh 通信。\n\n```\ngit clone https://github.com/ansible/ansible.git -b stable-2.3\ncd ./ansible\nsource ./hacking/env-setup\ncd $codis_dir/ansible\nansible-playbook -i hosts site.yml\n```\n\n\n## 2. 启动及参数\n\n**注意：请按照顺序逐步完成操作。生产环境建议修改dashboard coordinator_name配置，使用 `zookeeper` 或`etctd`作为外部存储。**\n\n**注意：Codis 3.x 支持 AUTH，但是要求所有组件使用的 AUTH 必须完全相同。**\n\n#### 2.1 Codis Dashboard\n\n##### 2.1.1 启动命令：\n\n```bash\n$ nohup ./bin/codis-dashboard --ncpu=4 --config=dashboard.toml \\\n    --log=dashboard.log --log-level=WARN &\n```\n\n默认配置文件 `dashboard.toml` 可由 codis-dashboard 生成。\n\n##### 2.1.2 详细说明：\n\n+ 启动参数说明：\n\n```bash\n$ ./bin/codis-dashboard -h\nUsage:\n    codis-dashboard [--ncpu=N] [--config=CONF] [--log=FILE] [--log-level=LEVEL] [--host-admin=ADDR]\n    codis-dashboard  --default-config\n    codis-dashboard  --version\n\nOptions:\n    --ncpu=N                    最大使用 CPU 个数\n    -c CONF, --config=CONF      指定启动配置文件\n    -l FILE, --log=FILE         设置 log 输出文件\n    --log-level=LEVEL           设置 log 输出等级：INFO,WARN,DEBUG,ERROR；默认INFO，推荐WARN\n```\n\n参数 `--host-admin` 请参见与 Docker 有关章节。\n\n+ 默认配置文件：\n\n```bash\n$ ./bin/codis-dashboard --default-config | tee dashboard.toml\n##################################################\n#                                                #\n#                  Codis-Dashboard               #\n#                                                #\n##################################################\n\n# Set Coordinator, only accept \"zookeeper\" & \"etcd\"\ncoordinator_name = \"zookeeper\"\ncoordinator_addr = \"127.0.0.1:2181\"\n\n# Set Codis Product {Name/Auth}.\nproduct_name = \"codis-demo\"\nproduct_auth = \"\"\n\n# Set bind address for admin(rpc), tcp only.\nadmin_addr = \"0.0.0.0:18080\"\n```\n\n| 参数              | 说明                               |\n|:----------------- |:---------------------------------- |\n| coordinator\\_name | 外部存储类型，接受 zookeeper/etcd  |\n| coordinator\\_addr | 外部存储地址                       |\n| product\\_name     | 集群名称，满足正则 `\\w[\\w\\.\\-]*`   |\n| product\\_auth     | 集群密码，默认为空                 |\n| admin\\_addr       | RESTful API 端口                   |\n\n#### 2.2 Codis Proxy\n\n##### 2.2.1 启动命令：\n\n```bash\n$ nohup ./bin/codis-proxy --ncpu=4 --config=proxy.toml \\\n    --log=proxy.log --log-level=WARN &\n```\n\n默认配置文件 `proxy.toml` 可由 codis-proxy 生成。\n\ncodis-proxy 启动后，处于 `waiting` 状态，监听 `proxy_addr` 地址，但是不会 `accept` 连接，添加到集群并完成集群状态的同步，才能改变状态为 `online`。添加的方法有以下两种：\n\n+ 通过 codis-fe 添加：通过 `Add Proxy` 按钮，将 `admin_addr` 加入到集群中；\n+ 通过 codis-admin 命令行工具添加，方法如下：\n\n```bash\n$ ./bin/codis-admin --dashboard=127.0.0.1:18080 --create-proxy -x 127.0.0.1:11080\n```\n\n其中 `127.0.0.1:18080` 以及 `127.0.0.1:11080` 分别为 dashboard 和 proxy 的 `admin_addr` 地址；\n\n添加过程中，dashboard 会完成如下一系列动作：\n\n+ 获取 proxy 信息，对集群 name 以及 auth 进行验证，并将其信息写入到外部存储中；\n+ 同步 slots 状态；\n+ 标记 proxy 状态为 `online`，此后 proxy 开始 `accept` 连接并开始提供服务；\n\n##### 2.2.2 详细说明：\n\n+ 启动参数说明：\n\n```bash\n$ ./bin/codis-proxy -h\nUsage:\n\tcodis-proxy [--ncpu=N] [--config=CONF] [--log=FILE] [--log-level=LEVEL] [--host-admin=ADDR] [--host-proxy=ADDR] [--ulimit=NLIMIT]\n\tcodis-proxy  --default-config\n\tcodis-proxy  --version\n\nOptions:\n\t--ncpu=N                    最大使用 CPU 个数\n\t-c CONF, --config=CONF      指定启动配置文件\n\t-l FILE, --log=FILE         设置 log 输出文件\n\t--log-level=LEVEL           设置 log 输出等级：INFO,WARN,DEBUG,ERROR；默认INFO，推荐WARN\n\t--ulimit=NLIMIT             检查 ulimit -n 的结果，确保运行时最大文件描述不少于 NLIMIT\n```\n\n参数 `--host-proxy` 以及 `--host-admin` 请参见与 Docker 有关章节。\n\n+ 默认配置文件：\n\n```bash\n$ ./bin/codis-proxy --default-config | tee proxy.toml\n##################################################\n#                                                #\n#                  Codis-Proxy                   #\n#                                                #\n##################################################\n\n# Set Codis Product {Name/Auth}.\nproduct_name = \"codis-demo\"\nproduct_auth = \"\"\n\n# Set bind address for admin(rpc), tcp only.\nadmin_addr = \"0.0.0.0:11080\"\n\n# Set bind address for proxy, proto_type can be \"tcp\", \"tcp4\", \"tcp6\", \"unix\" or \"unixpacket\".\nproto_type = \"tcp4\"\nproxy_addr = \"0.0.0.0:19000\"\n\n# Set jodis address & session timeout.\njodis_addr = \"\"\njodis_timeout = 10\njodis_compatible = false\n\n# Proxy will ping-pong backend redis periodly to keep-alive\nbackend_ping_period = 5\n\n# If there is no request from client for a long time, the connection will be droped. Set 0 to disable.\nsession_max_timeout = 1800\n\n# Buffer size for each client connection.\nsession_max_bufsize = 131072\n\n# Number of buffered requests for each client connection.\n# Make sure this is higher than the max number of requests for each pipeline request, or your client may be blocked.\nsession_max_pipeline = 1024\n\n# Set period between keep alives. Set 0 to disable.\nsession_keepalive_period = 60\n```\n\n| 参数                        | 说明                                                     |\n|:--------------------------- |:-------------------------------------------------------- |\n| product\\_name               | 集群名称，参考 dashboard 参数说明                        |\n| product\\_auth               | 集群密码，默认为空                                       |\n| admin\\_addr                 | RESTful API 端口                                         |\n| proto\\_type                 | Redis 端口类型，接受 tcp/tcp4/tcp6/unix/unixpacket       |\n| proxy\\_addr                 | Redis 端口地址或者路径                                   |\n| jodis\\_addr                 | Jodis 注册 zookeeper 地址                                |\n| jodis\\_timeout              | Jodis 注册 session timeout 时间，单位 second             |\n| jodis\\_compatible           | **Jodis 注册 zookeeper 的路径**                          |\n| backend\\_ping\\_period       | 与 codis-server 探活周期，单位 second，0 表示禁止        |\n| session\\_max\\_timeout       | 与 client 连接最大读超时，单位 second，0 表示禁止        |\n| session\\_max\\_bufsize       | 与 client 连接读写缓冲区大小，单位 byte                  |\n| session\\_max\\_pipeline      | 与 client 连接最大的 pipeline 大小                       |\n| session\\_keepalive\\_period  | 与 client 的 tcp keepalive 周期，仅 tcp 有效，0 表示禁止 |\n\n**注：Codis3 会将 jodis 节点注册在 `/jodis/{PRODUCT_NAME}` 下，这点与 Codis2 不太兼容，所以为了兼容性，可以考虑将 `jodis_compatible` 设置成 `true`。**\n\n#### 2.3 Codis Server\n\n+ 启动 ./bin/codis-server，与启动普通 redis 的方法一致。\n\n+ 启动完成后，可以通过 codis-fe 提供的界面或者 codis-admin 命令行工具添加到集群中。\n\n#### 2.4 Codis FE（可选组件）\n\n##### 2.4.1 启动命令：\n\n```bash\n$ nohup ./bin/codis-fe --ncpu=4 --log=fe.log --log-level=WARN \\\n    --zookeeper=127.0.0.1:2181 --listen=127.0.0.1:8080 &\n```\n\n##### 2.4.2 详细说明：\n\n+ 启动参数说明：\n\n```bash\n$ ./bin/codis-fe -h\nUsage:\n\tcodis-fe [--ncpu=N] [--log=FILE] [--log-level=LEVEL] [--assets-dir=PATH] (--dashboard-list=FILE|--zookeeper=ADDR|--etcd=ADDR|--filesystem=ROOT) --listen=ADDR\n\tcodis-fe  --version\n\nOptions:\n\t--ncpu=N                        最大使用 CPU 个数\n\t-d LIST, --dashboard-list=LIST  配置文件，能够自动刷新\n\t-l FILE, --log=FILE             设置 log 输出文件\n\t--log-level=LEVEL               设置 log 输出等级：INFO,WARN,DEBUG,ERROR；默认INFO，推荐WARN\n\t--listen=ADDR                   HTTP 服务端口\n```\n\n配置文件 codis.json 可以手动编辑，也可以通过 codis-admin 从外部存储中拉取，例如：\n\n```bash\n$ ./bin/codis-admin --dashboard-list --zookeeper=127.0.0.1:2181 | tee codis.json\n[\n    {\n        \"name\": \"codis-demo\",\n        \"dashboard\": \"127.0.0.1:18080\"\n    },\n    {\n        \"name\": \"codis-demo2\",\n        \"dashboard\": \"127.0.0.1:28080\"\n    }\n]\n```\n\n#### 2.5 Codis Admin（命令行工具）\n\n**注意：使用 codis-admin 是十分危险的。**\n\n##### 2.5.1 codis-dashboard 异常退出的修复\n\n当 codis-dashboard 启动时，会在外部存储上存放一条数据，用于存储 dashboard 信息，同时作为 LOCK 存在。当 codis-dashboard 安全退出时，会主动删除该数据。当 codis-dashboard 异常退出时，由于之前 LOCK 未安全删除，重启往往会失败。因此 codis-admin 提供了强制删除工具：\n\n1. 确认 codis-dashboard 进程已经退出（**很重要**）；\n2. 运行 codis-admin 删除 LOCK：\n\n```bash\n$ ./bin/codis-admin --remove-lock --product=codis-demo --zookeeper=127.0.0.1:2181\n```\n\n##### 2.5.2 codis-proxy 异常退出的修复\n\n通常 codis-proxy 都是通过 codis-dashboard 进行移除，移除过程中 codis-dashboard 为了安全会向 codis-proxy 发送 `offline` 指令，成功后才会将 proxy 信息从外部存储中移除。如果 codis-proxy 异常退出，该操作会失败。此时可以使用 codis-admin 工具进行移除：\n\n1. 确认 codis-proxy 进程已经退出（**很重要**）；\n2. 运行 codis-admin 删除 proxy：\n\n```bash\n$ ./bin/codis-admin --dashboard=127.0.0.1:18080 --remove-proxy --addr=127.0.0.1:11080 --force\n```\n\n选项 `--force` 表示，无论 `offline` 操作是否成功，都从外部存储中将该节点删除。所以操作前，一定要确认该 codis-proxy 进程已经退出。\n\n## 3. Jodis 与 HA\n\n因为 codis-proxy 是无状态的，可以比较容易的搭多个实例，达到高可用性和横向扩展。\n\n对 Java 用户来说，可以使用基于 Jedis 的实现 [Jodis](https://github.com/CodisLabs/jodis) ，来实现 proxy 层的 HA：\n    \n+ 它会通过监控 zookeeper 上的注册信息来实时获得当前可用的 proxy 列表，既可以保证高可用性；\n+ 也可以通过轮流请求所有的proxy实现负载均衡。\n\n如果需要异步请求，可以使用我们基于Netty开发的 [Nedis](https://github.com/CodisLabs/nedis)。\n\n对下层的 redis 实例来说，当一个 group 的 master 挂掉的时候，应该让管理员清楚，并手动的操作，因为这涉及到了数据一致性等问题（redis的主从同步是最终一致性的）。因此 codis 不会自动的将某个 slave 升级成 master。关于外部 codis-ha 工具（具体可以参考之前的章节），这是一个通过 codis-dashboard 开放的 RESTful API 实现自动切换主从的工具。该工具会在检测到 master 挂掉的时候主动应用主从切换策略，提升单个 slave 成为新的 master。\n\n需要注意，codis 将其中一个 slave 升级为 master 时，该组内其他 slave 实例是不会自动改变状态的，这些 slave 仍将试图从旧的 master 上同步数据，因而会导致组内新的 master 和其他 slave 之间的数据不一致。因此当出现主从切换时，需要管理员手动创建新的 sync action 来完成新 master 与 slave 之间的数据同步（codis-ha 不提供自动操作的工具，因为这样太不安全了）。\n\n## 4. Docker 部署\n\nCodis 3.x 起，开始正式支持 Docker 部署。这就需要 codis-dashboard 以及 codis-proxy 能够外部的 `listen` 地址暴露出来并保存在外部存储中。\n\n+ codis-proxy 增加了 `--host-admin` 以及 `--host-proxy` 参数；\n+ codis-dashboard 增加了 `--host-admin` 参数；\n\n以 codis-proxy 的 Docker 为例：\n\n```bash\n$ docker run --name \"Codis-Proxy\" -d -p 29000:19000 -p 21080:11080 codis-image \\\n    codis-proxy -c proxy.toml --host-admin 100.0.1.100:29000 --host-proxy 100.0.1.100:21080\n```\n\ncodis-proxy 在启动后，会使用 `--host-admin` 和 `--host-proxy` 参数所指定的实际地址替换 Docker 内监听的地址，向 codis-dashboard 注册。这样，例如使用 Jodis 的过程中，客户端就能够通过 `100.0.1.100:29000` 来访问 proxy 实例。\n\ncodis-dashboard 也是相同的道理，会使用 `--host-admin` 地址向外部存储注册，这样 codis-fe 也能通过该地址正确的对 codis-dashboard 进行操作。\n\n具体样例可以参考 `scripts/docker.sh`。\n\n## 5. 从Codis 2.x 升级\n\nCodis 3.x 修改了 codis-dashboard 与 codis-proxy 之间的通信方式，因此 Codis 2.x 并不兼容。但是我们提供了手动升级方案。\n\n**注意1：升级时，需要保证所有 slot 都处在 `online` 状态。即没有任何数据迁移操作正在进行。**\n\n**注意2：升级完成后，需要手动关闭 Codis 2.x 的所有 proxy 和 config 组件。**\n\n#### step 1. 导出配置文件\n\n```bash\n$ ./bin/codis-admin --config-dump --product=codis_v2.0 --zookeeper=127.0.0.1:2181 -1 | tee codis_v2.0.json\n```\n\n该命令会从 zookeeper 上拉取 `/zk/codis/db_codis_v2.0` 下全部的文件，并组织成 json 格式并输出。\n\n选项 `-1` 表示配置文件是 Codis 1.x 版本，缺省是 Codis 3.x 版本。\n\n#### step 2. 转换配置文件\n\n```bash\n$ ./bin/codis-admin --config-convert codis_v2.0.json | tee codis_v3.0.json\n```\n\n该命令会将 Codis 1.x 版本的配置文件中有效信息提取出来，并转成 Codis 3.x 版本的配置文件并输出。\n\n#### step 3. 更新配置文件\n\n**注意：更新配置文件时，请确保 Codis 3.x 中该集群不存在，否则可能导致更新失败或者集群状态异常。**\n\n```bash\n$ ./bin/codis-admin --config-restore=codis_v3.0.json --product=codis_v3.0 --zookeeper=127.0.0.1:2181 --confirm\n```\n\n该命令会将 Codis 3.x 版本的配置文件提交到 `/codis3/codis_v3.0` 目录下。\n\n选项 `--confirm` 选项表示确认提交，缺省时该命令仅仅打印配置文件作为调试。\n\n#### step 4. 启动 Codis 3.x dashboard 以及 proxy\n\n过程参考之前章节。因为集群信息已经存在，所以可以安全启动 codis-dashboard，并逐一添加 codis-proxy 到集群中。\n\n#### step 5. 关闭 Codis 2.x dashboard 以及 proxy\n\nCodis 3.x 的组件兼容 Jodis 协议。\n\n因为 Codis 2.x 与 Codis 3.x 在外部存储中的组织结构不同，所以可以安全的 `kill` 掉全部 Codis 2.x 组件。\n\n**注意：关闭过程请不要使用 `kill -9`，因为旧组件在退出时会自动清理部分注册信息。**\n"
  },
  {
    "path": "doc/unsupported_cmds.md",
    "content": "These commands are disallowed in codis proxy, if you use them, proxy will close the connection to warn you.\n\n|   Command Type   |   Command Name   |\n|:----------------:|:---------------- |\n|   Keys           | KEYS             |\n|                  | MIGRATE          |\n|                  | MOVE             |\n|                  | OBJECT           |\n|                  | RANDOMKEY        |\n|                  | RENAME           |\n|                  | RENAMENX         |\n|                  | SCAN             |\n|                  |                  |\n|   Strings        | BITOP            |\n|                  | MSETNX           |\n|                  |                  |\n|   Lists          | BLPOP            |\n|                  | BRPOP            |\n|                  | BRPOPLPUSH       |\n|                  |                  |\n|   Pub/Sub        | PSUBSCRIBE       |\n|                  | PUBLISH          |\n|                  | PUNSUBSCRIBE     |\n|                  | SUBSCRIBE        |\n|                  | UNSUBSCRIBE      |\n|                  |                  |\n|   Transactions   | DISCARD          |\n|                  | EXEC             |\n|                  | MULTI            |\n|                  | UNWATCH          |\n|                  | WATCH            |\n|                  |                  |\n|   Scripting      | SCRIPT           |\n|                  |                  |\n|   Server         | BGREWRITEAOF     |\n|                  | BGSAVE           |\n|                  | CLIENT           |\n|                  | CONFIG           |\n|                  | DBSIZE           |\n|                  | DEBUG            |\n|                  | FLUSHALL         |\n|                  | FLUSHDB          |\n|                  | LASTSAVE         |\n|                  | LATENCY          |\n|                  | MONITOR          |\n|                  | PSYNC            |\n|                  | REPLCONF         |\n|                  | RESTORE          |\n|                  | SAVE             |\n|                  | SHUTDOWN         |\n|                  | SLAVEOF          |\n|                  | SLOWLOG          |\n|                  | SYNC             |\n|                  | TIME             |\n|                  |                  |\n|   Codis Slot     | SLOTSCHECK       |\n|                  | SLOTSDEL         |\n|                  | SLOTSINFO        |\n|                  | SLOTSMGRTONE     |\n|                  | SLOTSMGRTSLOT    |\n|                  | SLOTSMGRTTAGONE  |\n|                  | SLOTSMGRTTAGSLOT |\n\n\nThese commands is \"half-supported\". Codis does not support cross-node operation, so you must use Hash Tags (See [this blog](http://oldblog.antirez.com/post/redis-presharding.html)'s \"Hash tags\" section) to put all the keys which may shown in one request into the same slot then you can use these commands. Codis does not check if the keys have same tag, so if you don't use tag, your program will get wrong response.\n\n|   Command Type   |   Command Name   |\n|:----------------:|:---------------- |\n|   Lists          | RPOPLPUSH        |\n|                  |                  |\n|   Sets           | SDIFF            |\n|                  | SINTER           |\n|                  | SINTERSTORE      |\n|                  | SMOVE            |\n|                  | SUNION           |\n|                  | SUNIONSTORE      |\n|                  |                  |\n|   Sorted Sets    | ZINTERSTORE      |\n|                  | ZUNIONSTORE      |\n|                  |                  |\n|   HyperLogLog    | PFMERGE          |\n|                  |                  |\n|   Scripting      | EVAL             |\n|                  | EVALSHA          |\n\n"
  },
  {
    "path": "example/.gitignore",
    "content": "*.conf\n*.toml\n*.pyc\n*.log\n*.rdb\n*.tmp\n*.swp\n\n.idea\n__pycache__\n\n/rootfs\n"
  },
  {
    "path": "example/Makefile",
    "content": "all: clean\n\t@python3 setup.py\n\nclean:\n\t@rm -f *.conf *.toml *.pyc *.log *.rdb\n\t@rm -rf rootfs\n"
  },
  {
    "path": "example/dashboard.py",
    "content": "#!/usr/bin/env python3\n\nfrom utils import *\n\nimport atexit\nimport json\nimport datetime\n\n\nclass CodisDashboard(Process):\n\n    def __init__(self, admin_port, product_name, product_auth=None):\n        self.config = self._open_config(admin_port, product_name, product_auth)\n        self.admin_port = admin_port\n        self.product_name = product_name\n        self.product_auth = product_auth\n\n        self.logfile = \"dashboard-{}.log\".format(admin_port)\n        self.command = \"codis-dashboard -c {}\".format(self.config)\n        Process.__init__(self, self.command, self.logfile)\n\n        dict = {\"admin_port\": admin_port, \"pid\": self.proc.pid}\n        print(\"    >> codis.dashboard = \" + json.dumps(dict, sort_keys=True))\n\n    @staticmethod\n    def _open_config(admin_port, product_name, product_auth=None):\n        config = 'dashboard-{}.toml'.format(admin_port)\n        with open(config, \"w+\") as f:\n            f.write('coordinator_name = \"filesystem\"\\n')\n            f.write('coordinator_addr = \"rootfs\"\\n')\n            f.write('product_name = \"{}\"\\n'.format(product_name))\n            if product_auth is not None:\n                f.write('product_auth = \"{}\"\\n'.format(product_auth))\n            f.write('admin_addr = \":{}\"\\n'.format(admin_port))\n            f.write('migration_method = \"semi-async\"\\n')\n            f.write('migration_async_maxbulks = 200\\n')\n            f.write('migration_async_maxbytes = \"32mb\"\\n')\n            f.write('migration_async_numkeys = 100\\n')\n            f.write('migration_timeout = \"30s\"\\n')\n            f.write('sentinel_quorum = 2\\n')\n            f.write('sentinel_parallel_syncs = 1\\n')\n            f.write('sentinel_down_after = \"5s\"\\n')\n            f.write('sentinel_failover_timeout = \"10m\"\\n')\n            path = os.getcwd()\n            f.write('sentinel_notification_script = \"{}\"\\n'.format(os.path.join(path, \"sentinel_notify.sh\")))\n            f.write('sentinel_client_reconfig_script = \"{}\"\\n'.format(os.path.join(path, \"sentinel_reconfig.sh\")))\n        return config\n\n\nif __name__ == \"__main__\":\n    children = []\n    atexit.register(kill_all, children)\n\n    product_name = \"demo-test\"\n    product_auth = None\n\n    children.append(CodisDashboard(18080, product_name, product_auth))\n\n    check_alive(children, 3)\n\n    while True:\n        print(datetime.datetime.now())\n        time.sleep(5)\n"
  },
  {
    "path": "example/fe.py",
    "content": "#!/usr/bin/env python3\n\nfrom utils import *\n\nimport atexit\nimport json\nimport datetime\n\n\nclass CodisFE(Process):\n\n    def __init__(self, port, assets):\n        self.port = port\n\n        self.logfile = \"fe-{}.log\".format(port)\n        self.command = \"codis-fe --filesystem rootfs --listen 0.0.0.0:{} --assets-dir={}\".format(self.port, assets)\n        Process.__init__(self, self.command, self.logfile)\n\n        dict = {\"pid\": self.proc.pid, \"assets\": assets}\n        print(\"    >> codis.fe = \" + json.dumps(dict, sort_keys=True))\n\n\nif __name__ == \"__main__\":\n    children = []\n    atexit.register(kill_all, children)\n\n    children.append(CodisFE(8080, \"../cmd/fe/assets\"))\n\n    check_alive(children, 3)\n\n    while True:\n        print(datetime.datetime.now())\n        time.sleep(5)\n"
  },
  {
    "path": "example/proxy.py",
    "content": "#!/usr/bin/env python3\n\nfrom utils import *\n\nimport atexit\nimport json\nimport datetime\n\n\nclass CodisProxy(Process):\n\n    def __init__(self, admin_port, proxy_port, product_name, product_auth=None):\n        self.config = self._open_config(admin_port, proxy_port, product_name, product_auth)\n        self.admin_port = admin_port\n        self.proxy_port = proxy_port\n        self.product_name = product_name\n        self.product_auth = product_auth\n\n        self.logfile = \"proxy-{}.log\".format(proxy_port)\n        self.command = \"codis-proxy -c {} --filesystem rootfs\".format(self.config)\n        Process.__init__(self, self.command, self.logfile)\n\n        dict = {\"admin_port\": admin_port, \"proxy_port\": proxy_port, \"pid\": self.proc.pid}\n        print(\"    >> codis.proxy = \" + json.dumps(dict, sort_keys=True))\n\n    @staticmethod\n    def _open_config(admin_port, proxy_port, product_name, product_auth=None):\n        config = 'proxy-{}.toml'.format(proxy_port)\n        with open(config, \"w+\") as f:\n            f.write('product_name = \"{}\"\\n'.format(product_name))\n            if product_auth is not None:\n                f.write('product_auth = \"{}\"\\n'.format(product_auth))\n            f.write('proto_type = \"tcp4\"\\n')\n            f.write('admin_addr = \":{}\"\\n'.format(admin_port))\n            f.write('proxy_addr = \":{}\"\\n'.format(proxy_port))\n            f.write('proxy_datacenter = \"localhost\"\\n')\n            f.write('proxy_heap_placeholder = \"0\"\\n')\n            f.write('proxy_max_offheap_size = \"0\"\\n')\n            f.write('backend_ping_period = \"5s\"\\n')\n            f.write('backend_recv_bufsize = \"128kb\"\\n')\n            f.write('backend_recv_timeout = \"30s\"\\n')\n            f.write('backend_send_bufsize = \"128kb\"\\n')\n            f.write('backend_send_timeout = \"30s\"\\n')\n            f.write('backend_max_pipeline = 1024\\n')\n            f.write('backend_primary_only = false\\n')\n            f.write('backend_keepalive_period = \"75s\"\\n')\n            f.write('session_recv_bufsize = \"128kb\"\\n')\n            f.write('session_recv_timeout = \"30m\"\\n')\n            f.write('session_send_bufsize = \"64kb\"\\n')\n            f.write('session_send_timeout = \"30s\"\\n')\n            f.write('session_max_pipeline = 1024\\n')\n            f.write('session_keepalive_period = \"75s\"\\n')\n            f.write('session_break_on_failure = false\\n')\n        return config\n\n\nif __name__ == \"__main__\":\n    children = []\n    atexit.register(kill_all, children)\n\n    product_name = \"demo-test\"\n    product_auth = None\n\n    for i in range(0, 4):\n        CodisProxy(11080+i, 19000+i, product_name, product_auth)\n\n    check_alive(children, 3)\n\n    while True:\n        print(datetime.datetime.now())\n        time.sleep(5)\n"
  },
  {
    "path": "example/sentinel.py",
    "content": "#!/usr/bin/env python3\n\nfrom utils import *\n\nimport atexit\nimport json\nimport datetime\n\n\nclass CodisSentinel(Process):\n\n    def __init__(self, port):\n        self.config = self._open_config(port)\n        self.port = port\n\n        self.logfile = \"sentinel-{}.log\".format(port)\n        self.command = \"codis-server {} --sentinel\".format(self.config)\n        Process.__init__(self, self.command, self.logfile)\n\n        dict = {\"port\": port, \"pid\": self.proc.pid}\n        print(\"    >> codis.sentinel = \" + json.dumps(dict, sort_keys=True))\n\n    @staticmethod\n    def _open_config(port):\n        config = 'sentinel-{}.conf'.format(port)\n        with open(config, \"w+\") as f:\n            f.write('port {}'.format(port))\n        return config\n\n\nif __name__ == \"__main__\":\n    children = []\n    atexit.register(kill_all, children)\n\n    for port in range(26380, 26385):\n        children.append(CodisSentinel(port))\n\n    check_alive(children, 3)\n\n    while True:\n        print(datetime.datetime.now())\n        time.sleep(5)\n"
  },
  {
    "path": "example/sentinel_notify.sh",
    "content": "#!/bin/bash\n\necho $@ >> sentinel_notify.log\n"
  },
  {
    "path": "example/sentinel_reconfig.sh",
    "content": "#!/bin/bash\n\necho $@ >> sentinel_reconfig.log\n"
  },
  {
    "path": "example/server.py",
    "content": "#!/usr/bin/env python3\n\nfrom utils import *\n\nimport atexit\nimport json\nimport datetime\n\n\nclass CodisServer(Process):\n\n    def __init__(self, port, master_port=None, requirepass=None):\n        self.config = self._open_config(port, master_port, requirepass)\n        self.port = port\n\n        self.logfile = \"redis-{}.log\".format(port)\n        self.command = \"codis-server {}\".format(self.config)\n        Process.__init__(self, self.command, self.logfile)\n\n        dict = {\"port\": port, \"pid\": self.proc.pid}\n        print(\"    >> codis.server = \" + json.dumps(dict, sort_keys=True))\n\n    @staticmethod\n    def _open_config(port, master_port=None, requirepass=None):\n        config = 'redis-{}.conf'.format(port)\n        with open(config, \"w+\") as f:\n            f.write('port {}\\n'.format(port))\n            f.write('save \"\"\\n')\n            f.write('dbfilename \"{}.rdb\"\\n'.format(port))\n            if master_port is not None:\n                f.write('slaveof 127.0.0.1 {}\\n'.format(master_port))\n            if requirepass is not None:\n                f.write('masterauth {}\\n'.format(requirepass))\n                f.write('requirepass {}\\n'.format(requirepass))\n            f.write('protected-mode no\\n')\n        return config\n\n\nif __name__ == \"__main__\":\n    children = []\n    atexit.register(kill_all, children)\n\n    passwd = None\n\n    for port in range(16380, 16384):\n        children.append(CodisServer(port, requirepass=passwd))\n        children.append(CodisServer(port + 1000, port, requirepass=passwd))\n\n    check_alive(children, 3)\n\n    while True:\n        print(datetime.datetime.now())\n        time.sleep(5)\n"
  },
  {
    "path": "example/setup.py",
    "content": "#!/usr/bin/env python3\n\nfrom server import *\nfrom sentinel import *\nfrom dashboard import *\nfrom proxy import *\nfrom fe import *\n\n\ndef codis_admin_dashboard(admin_port, args=None):\n    command = \"codis-admin --dashboard 127.0.0.1:{}\".format(admin_port)\n    if args is not None:\n        command += \" \" + args\n    return do_command(command)\n\n\ndef codis_admin_proxy(admin_port, args=None):\n    command = \"codis-admin --proxy 127.0.0.1:{}\".format(admin_port)\n    if args is not None:\n        command += \" \" + args\n    return do_command(command)\n\nif __name__ == \"__main__\":\n    children = []\n    atexit.register(kill_all, children)\n\n    product_name = \"demo-test\"\n    product_auth = None\n\n    # step 1. codis-server & codis-sentinel\n\n    # codis-server [master 2000+i <== following == 3000+i slave]\n    for i in range(0, 4):\n        children.append(CodisServer(2000 + i, requirepass=product_auth))\n        children.append(CodisServer(3000 + i, 2000 + i, requirepass=product_auth))\n\n    for i in range(0, 5):\n        children.append(CodisSentinel(20000 + i))\n\n    check_alive(children, 1)\n    print(\"[OK] setup codis-server & codis-sentinel\")\n\n    # step 2. setup codis-fe & codis-dashboard & codis-proxy\n\n    children.append(CodisFE(8080, \"../cmd/fe/assets\"))\n    children.append(CodisDashboard(18080, product_name, product_auth))\n\n    for i in range(0, 4):\n        children.append(CodisProxy(11080 + i, 19000 + i, product_name, product_auth))\n\n    check_alive(children, 3)\n    print(\"[OK] setup codis-fe & codis-dashboard & codis-proxy\")\n\n    # step3: init slot-mappings\n\n    for i in range(0, 4):\n        gid = i + 1\n        codis_admin_dashboard(18080, \"--create-group --gid={}\".format(gid))\n        codis_admin_dashboard(18080, \"--group-add --gid={} --addr=127.0.0.1:{} --datacenter=localhost\".format(gid, 2000+i))\n        codis_admin_dashboard(18080, \"--group-add --gid={} --addr=127.0.0.1:{} --datacenter=localhost\".format(gid, 3000+i))\n        beg, end = i * 256, (i + 1) * 256 - 1\n        codis_admin_dashboard(18080, \"--slots-assign --beg={} --end={} --gid={} --confirm\".format(beg, end, gid))\n        codis_admin_dashboard(18080, \"--resync-group --gid={}\".format(gid))\n\n    for i in range(0, 5):\n        codis_admin_dashboard(18080, \"--sentinel-add --addr=127.0.0.1:{}\".format(20000+i))\n\n    codis_admin_dashboard(18080, \"--slot-action --interval=0\")\n    codis_admin_dashboard(18080, \"--sentinel-resync\")\n\n    check_alive(children, 3)\n    print(\"[OK] done & have fun!!!\")\n\n    while True:\n        print(datetime.datetime.now())\n        time.sleep(5)\n"
  },
  {
    "path": "example/utils.py",
    "content": "#!/usr/bin/env python3\n\nimport subprocess\nimport time\nimport os\n\n\nclass Process:\n\n    def __init__(self, command, logfile=None):\n        self.command = command\n        if logfile is not None:\n            self.logfile = open(logfile, \"wb+\")\n        try:\n            self.proc = subprocess.Popen(self.command.split(), stderr=subprocess.STDOUT, stdout=self.logfile)\n        except Exception:\n            print(\"run command failed: {}\".format(self.command))\n            raise\n\n    def is_running(self):\n        try:\n            self.proc.wait(0)\n        except Exception:\n            pass\n        return self.proc.returncode is None\n\n    def kill(self):\n        if self.is_running():\n            self.proc.kill()\n        if self.logfile is not None:\n            self.logfile.close()\n\n    def wait(self):\n        self.proc.wait()\n\n    def get_pid(self):\n        return self.proc.pid\n\n\ndef kill_all(children=[]):\n    for p in children:\n        p.kill()\n\n\ndef check_alive(children=[], seconds=0):\n    if seconds != 0:\n        time.sleep(seconds)\n    for p in children:\n        if not p.is_running():\n            message = \"process lost - {}\".format(p.command)\n            raise Exception(message)\n\n\ndef do_command(command):\n    return subprocess.call(command.split())\n\n\nif __name__ != \"__main__\":\n    os.environ[\"PATH\"] += os.pathsep + os.getcwd()\n    os.environ[\"PATH\"] += os.pathsep + os.path.abspath(os.path.join(os.getcwd(), \"../bin\"))\n\n"
  },
  {
    "path": "extern/.gitignore",
    "content": "/Dockerfile\n"
  },
  {
    "path": "extern/README.md",
    "content": "codis's redis build & external librarys\n"
  },
  {
    "path": "extern/deprecated/redis-2.8.21/.gitignore",
    "content": ".*.swp\n*.o\n*.log\ndump.rdb\nredis-benchmark\nredis-check-aof\nredis-check-dump\nredis-cli\nredis-sentinel\nredis-server\ndoc-tools\nrelease\nmisc/*\nsrc/release.h\nappendonly.aof\nSHORT_TERM_TODO\nrelease.h\nsrc/transfer.sh\nsrc/configs\nredis.ds\nsrc/redis.conf\ndeps/lua/src/lua\ndeps/lua/src/luac\ndeps/lua/src/liblua.a\n.make-*\n.prerequisites\n*.dSYM\n"
  },
  {
    "path": "extern/deprecated/redis-2.8.21/00-RELEASENOTES",
    "content": "Redis 2.8 release notes\n=======================\n\n** IMPORTANT ** Check the 'Migrating from 2.6 to 2.8' section at the end of\n                this file for information about what changed between 2.6 and\n                2.8 and how this may affect your application.\n\n--------------------------------------------------------------------------------\nUpgrade urgency levels:\n\nLOW:      No need to upgrade unless there are new features you want to use.\nMODERATE: Program an upgrade of the server, but it's not urgent.\nHIGH:     There is a critical bug that may affect a subset of users. Upgrade!\nCRITICAL: There is a critical bug affecting MOST USERS. Upgrade ASAP.\n--------------------------------------------------------------------------------\n\n--[ Redis 2.8.21 ] Release date: 4 Jun 2015\n\nUpgrade urgency: HIGH for Redis because of a security issue.\n                 LOW for Sentinel.\n\n* [FIX] Critical security issue fix by Ben Murphy: http://t.co/LpGTyZmfS7\n* [FIX] SMOVE reply fixed when src and dst keys are the same. (Glenn Nethercutt)\n* [FIX] Lua cmsgpack lib updated to support str8 type. (Sebastian Waisbrot)\n\n* [NEW] Senitnel: CKQUORUM and FLUSHCONFIG commands back ported.\n        (Salvatore Sanfilippo)\n\n--[ Redis 2.8.20 ] Release date: 5 May 2015\n\nUpgrade urgency: LOW for Redis, MODERATE for Sentinel.\n\n* [FIX] Sentinel memory leak due to hiredis fixed. (Salvatore Sanfilippo)\n* [FIX] Sentinel memory leak on duplicated instance. (Charsyam)\n* [FIX] Redis crash on Lua reaching output buffer limits. (Yossi Gottlieb)\n* [FIX] Sentinel flushes config on +slave events. (Bill Anderson)\n* [FIX] Fixes to diskless replication. (Oran Agra)\n* [FIX] Redis (non clustered & clustered) replication bug involving blocking\n        operations: see issue #2473. (Salvatore Sanfilippo)\n* [FIX] Config: missing activerehashing option support in CONFIG SET added.\n        (Salvatore Sanfilippo, thx to Bill Anderson)\n* [FIX] AOF bug unlikely to happen in practice and mostly harmless: child\n        process segfaults when parent is not reachable via pipe. (Sun He)\n* [FIX] Scripting engine now reports an error when misused with Lua debug\n        hooks, instead of crashing. (Salvatore Sanfilippo)\n* [FIX] INFO loading stats: three fixes.\n* [FIX] Fixed memory leaks in rdbSaveToSlavesSockets(). (Alon Diamant)\n\n* [NEW] Redis-cli --latency-dist backported from unstable.\n        (Salvatore Sanfilippo)\n\n--[ Redis 2.8.19 ] Release date: 16 Dec 2014\n\n# UPGRADE URGENCY: LOW for both Redis and Sentinel. This release mostly\n                   fixes small issues.\n\n02d465c Don't log admin commands in MONITOR. (antirez)\n4d8f426 List of commands flagged as admin commands modified. (antirez)\ne47e460 Lua cmsgpack lib updated to latest version. (antirez)\n5509c14 Add symlink to redis-sentinel during make install (Rhommel Lamas)\n7de1ef7 SORT: Don't sort Set elements if not needed. (antirez)\ne945a54 Fix zero-ordering SORT when called against lists (Matt Stancliff)\nd81c383 Update redis_init_script.tpl (Ben Dowling)\ndba57ea FIXED redis-benchmark's idle mode.With idle mode shouldn't create write event (zhanghailei)\n888ea17 zipmap.c: update comments above (Sun He)\n86ebc13 replaced // comments  #2150 (Deepak Verma)\n3d73f08 redis-benchmark AUTH command to be discarded after the first send #2150 (azure provisioned user)\n76d53a6 sds.c: Correct two spelling mistakes in comments (Sun He)\n4848cf9 sds.c/sdscatvprintf: set va_end to finish va_list cpy (Sun He)\nd2f584f sds.c: Correct some comments (Sun He)\n2ed3f09 Update whatisdoing.sh (Serghei Iakovlev)\n77b997d Include stropts only if __sun is defined. (antirez)\nd409371 Fix implicit declaration of ioctl on Solaris (Jan-Erik Rediger)\n23b96c0 Silence _BSD_SOURCE warnings in glibc 2.20 and forward (Johan Bergström)\na47a042 Mark whatisdoing.sh as deprecated in top-comment. (antirez)\nb5737d2 getting pid fixes (Serghei Iakovlev)\na598e08 sparkline.c: AddSample skip Empty label (Sun He)\n7d480ab sparkline.c: mov label-ini into the AddSample Function (Sun He)\n2f3c860 Only ignore sigpipe in interactive mode (Jan-Erik Rediger)\n0c211a1 Simplify lua_cmsgpack macro and fix build on old Linux distros. (antirez)\n\n--[ Redis 2.8.18 ] Release date: 4 Dec 2014\n\n# UPGRADE URGENCY: LOW for both Redis and Sentinel. This release mostly\n                   adds new features to Redis, and contains non critical\n                   fixes.\n\n* [FIX] Linenoise updated to be more VT100 compatible. (Salvatore Sanfilippo)\n* [FIX] A number of typos fixed inside comments. (Various authors)\n* [FIX] redis-cli no longer quits after long timeouts. (Matt Stancliff)\n* [FIX] Test framework improved to detect never terminating scripts, cleanup\n        instances on crashes. (Salvatore Sanfilippo)\n* [FIX] PFCOUNT can be used on slaves now. (Salvatore Sanfilippo)\n* [FIX] ZSCAN no longer report very small scores as 0. (Matt Stancliff,\n        Michael Grunder, Salvatore Sanfilippo)\n* [FIX] Don't show the ASCII logo if syslog is enabled. Redis is now\n        an Enterprise Grade product. (Salvatore Sanfilippo)\n\n* [NEW] EXPERIMENTAL: Diskless replication, for more info check the doc at\n        http://redis.io/topics/replication. (Salvatore Sanfilippo).\n* [NEW] Transparent Huge Pages detection and reporting in logs and\n        LATENCY DOCTOR output. (Salvatore Sanfilippo)\n* [NEW] Many Lua scripting enhancements: Bitops API, cjson upgrade and tests,\n        cmsgpack upgrade. (Matt Stancliff)\n* [NEW] Total and instantaneous Network bandwidth tracking in INFO.\n* [NEW] DEBUG POPULATE two args form implemented (old form still works).\n        The second argument is the key prefix. Default is \"key:\" (Salvatore\n        Sanfilippo)\n* [NEW] Check that tcp-backlog is matched by /proc/sys/net/core/somaxconn, and\n        warn about it if not. (Salvatore Sanfilippo)\n\n--[ Redis 2.8.17 ] Release date: 19 Sep 2014\n\n# UPGRADE URGENCY: HIGH for Redis Sentinel.\n                   LOW for Redis Server (unmodified compared to 2.8.16).\n\n* [FIX] Resolved a memory leak in the hiredis library causing a memory leak\n        in Redis Sentinel when a monitored instance or another Sentinel is\n        unavailable. Every reconnection attempt will leak a small amount of\n        memory, but in the long run the process can reach a considerable size.\n\n--[ Redis 2.8.16 ] Release date: 16 Sep 2014\n\n# UPGRADE URGENCY: HIGH for Redis if you are using 2.8.15 + AOF.\n                   LOW for Sentinel.\n\n* [FIX] The ability to load truncated AOF files introduced with Redis 2.8.15\n        contains a bug fixed in this release: after loading the file was not\n        truncated to the last valid command, so the new commands are appended\n        after a non well formed command. This means that:\n\n        1) The first AOF rewrite triggered by the server will automatically\n           fix the problem.\n        2) However, if the server is restarted before the rewrite, Redis may\n           not be able to load the file and you need to manually fix it.\n\n        In order to fix a corrupted file you should start the redis-check-aof\n        utility WITHOUT the --fix option, just to check the offset where the\n        corruption is found. Around the offset reported by the check utility\n        you'll find, inside your AOF file, a command which is not complete\n        according to the Redis protocol. Just remove this incomplete command\n        leafing the file unaltered before and after the offending command,\n        and restart the server.\n\n        IMPORTANT #1: Redis 2.8.15 is the only stable version of Redis with\n        this bug so probably no actual real-world problem happened since the\n        problem is automatically fixed at the first automatic AOF rewrite.\n\n        IMPORTANT #2: Before upgrading to Redis 2.8.16, if you are using Redis\n        2.8.15 with AOF enabled, make sure to trigger a manual AOF rewrite\n        using the BGREWRITEAOF command.\n\n* [FIX] SAVE is no longer propagated to AOF / slaves.\n\n--[ Redis 2.8.15 ] Release date: 12 Sep 2014\n\n# UPGRADE URGENCY: LOW for Redis, HIGH for Sentinel.\n\n* [FIX] Sentinel critical bug fixed: the absolute majority was computed in a\n        wrong way because of a programming error. Now the implementation does\n        what the specification says and the majority to authorize a failover\n        (that should not be confused with the ODOWN quorum) is the majority of\n        *all* the Sentinels ever seen for a given master, regardless of their\n        current state.\n* [FIX] GETRANGE test no longer fails for 32 bit builds (Matt Stancliff).\n* [FIX] Limit SCAN latency when the hash table is in an odd state (very few\n        populted buckets because rehashing is in progress). (Xiaost and\n        Salvatore Sanfilippo)\n\n* [NEW] Redis is now able to load truncated AOF files without requiring a\n        redis-check-aof utility run. The default now is to load truncated\n        (but apparently not corrupted) AOFs, you can change this in redis.conf.\n        (Salvatore Sanfilippo).\n* [NEW] Sentinel: ability to announce itself with an arbitrary IP/port to work\n        in the context of natted networks. However this is probably still\n        not enough since there is no equivalent mechanism for slaves listed\n        in the master INFO output. (Dara Kong and Salvatore Sanfilippo)\n\n--[ Redis 2.8.14 ] Release date: 1 Sep 2014\n\n# UPGRADE URGENCY: HIGH for Lua scripting users, the server could crash because\n                   of a bug introduced in Redis 2.8.10, otherwise LOW.\n                   LOW for Redis Sentinel.\n\n* [FIX] Don't prevent use of shared integers if maxmemory policy is non-LRU.\n        (Salvatore Sanfilippo)\n* [FIX] Fail SYNC if background save child aborted due to a signal.\n        (Yossi Gottlieb)\n* [FIX] Different small redis-cli fixes. (Dov Murik, Charsyam, cubicdaiya,\n        Kashif Rasul, Jan-Erik Rediger, Matt Stancliff)\n* [FIX] AIX compilation fixes. (Siah Lyimo)\n* [FIX] A number of other smaller issues.\n* [FIX] Improved SIGINT handling (Matt Stancliff, Salvatore Sanfilippo)\n* [FIX] Use unsigned types in SDS header to raise limit to 4GB.\n        (Matt Stancliff, Salvatore Sanfilippo)\n* [FIX] Handle signed/unsigned comparisons with more care around the code.\n        (Salvatore Sanfilippo)\n* [FIX] Colorized test output fixed to don't change the background color.\n        (Mariano Pérez Rodríguez)\n* [FIX] More Sentinel IPv6 fixes. (Eiichi Sato)\n* [FIX] Deny CLIENT command in scripts. (Matt Stancliff)\n* [FIX] Allow datasets with more than 2 billion of keys, initial work.\n* [FIX] Fix a Lua scripting crash by storing the length of the static\n        argv when first allocated. (Paddy Byers)\n\n* [NEW] Pub/Sub PING. (Salvatore Sanfilippo)\n* [NEW] Much faster ZUNIONSTORE. (Kyle Hubert, Salvatore Sanfilippo)\n* [NEW] Faster ll2string() implementation. (Salvatore Sanfilippo)\n* [NEW] **WARNING, minor API change**: PUBSUB NUMSUB: return type modified\n        to integer. (Matt Stancliff)\n* [NEW] redis-benchmark support for AUTH. (CharSyam)\n\n--[ Redis 2.8.13 ] Release date: 14 Jul 2014\n\n# UPGRADE URGENCY: LOW for Redis and Sentinel, this is a features enhancement\n                   release mostly. Since this release introduces the latency\n                   monitoring feature, Redis 2.8 users experiencing latency\n                   issues are strongly encouraged to upgrade.\n\n* [FIX] CLIENT KILL minor backward compatibility fixes. (Salvatore Sanfilippo)\n* [FIX] Enable HAVE_ATOMIC for PowerPC. (Matt Stancliff)\n* [FIX] More robust PSYNC and AOF rewrites tests. (Salvatore Sanfilippo)\n* [FIX] Solaris build fixed. (Matt Stancliff, Salvatore Sanfilippo)\n\n* [NEW] The new latency monitoring feature, as documented at\n        http://redis.io/topics/latency-monitor (Salvatore Sanfilippo)\n* [NEW] The COMMAND command, exposing the Redis command table\n        as an API. (Matt Stancliff)\n* [NEW] Update used memory with C11 __atomic. (Matt Stancliff)\n\n--[ Redis 2.8.12 ] Release date: 23 Jun 2014\n\n# UPGRADE URGENCY: HIGH for Redis, CRITICAL for Sentinel.\n\n# WARNING: This release contains a non backward compatible semantical change\n           to Lua script that should affect an almost zero number of users.\n\n* [FIX / BREAKS BACKWARD COMPATIBILITY] Using SELECT inside Lua scripts no\n       longer makes the selected DB to be set in the calling client.\n       So Lua can still use SELECT, but the client calling the script will\n       remain set to the original DB. Thix fixes an issue with Redis\n       replication of Lua scripts that called SELECT without reverting the\n       selected DB to the original one. (Salvatore Sanfilippo)\n* [FIX] Sentinel failover was instalbe if the master was detected as available\n        during the failover (especially during manual failovers) because\n        of an implementation error (lack of checking of\n        SRI_PROMOTED flag). (Salvatore Sanfilippo)\n* [FIX] Cancel SHUTDOWN if initial AOF is being written. (Matt Stancliff)\n* [FIX] Sentinel: bind source address for outcoming connections. (Matt\n        Stancliff).\n* [FIX] Less timing sensitive Sentinel tests. (Salvatore Sanfilippo).\n\n* [NEW] redis-cli --intrinsic-latency stopped with SIGINT still reports\n        stats (Matt Stancliff)\n* [NEW] Sentinels broadcast an HELLO message ASAP after a failover in order to\n        reach a consistent state faster (before it relied for periodic HELLO\n        messages). (Salvatore Sanfilippo).\n* [NEW] Jemalloc updated to 3.6.0. (Salvatore Sanfilippo)\n* [NEW] CLIENT LIST speedup. (Salvatore Sanfilippo)\n* [NEW] CLIENT LIST new unique incremental ID to every client. (Salvatore\n        Sanfilippo)\n* [NEW] ROLE command added. (Salvatore Sanfilippo)\n* [NEW] CLIENT KILL new form to kill by client type and ID (see doc at\n        redis.io for more info). (Salvatore Sanfilippo)\n* [NEW] Sentinel now disconnects clients when instances are reconfigured\n        (see http://redis.io/topics/sentinel-clients). (Salvatore Sanfilippo)\n* [NEW] Hiredis update to latest version. (Matt Stancliff)\n\n--[ Redis 2.8.11 ] Release date: 11 Jun 2014\n\n# UPGRADE URGENCY: HIGH if you use Lua scripting, LOW otherwise.\n\n* [FIX] A previous fix for Lua -> Redis numerical precision enhancement\n        introduced a new problem. In Redis 2.8.10 commands called from Lua\n        passing a string that \"looks like\" a very large number, may actually\n        use as argument the string converted as a float. This bug is now\n        fixed.\n* [FIX] Now commands other than *PUSH* adding elements to a list will be able\n        to awake clients blocked in a blocking POP operation.\n* [FIX] Cygwin compilation fixes.\n\n--[ Redis 2.8.10 ] Release date: 5 Jun 2014\n\n# UPGRADE URGENCY: HIGH if you use min-slaves-to-write option.\n\n* [FIX] IMPORTANT! A min-slaves-to-write option active in a slave totally\n        prevented the slave from acception the master stream of commands.\n        This release includes testes for min-slaves-to-write, and a fix\n        for this issue.\n* [FIX] Sometimes DEL returned 1 for already expired keys. Fixed.\n* [FIX] Fix test false positive because new osx 'leaks' output.\n* [FIX] PFCOUNT HLL cache invalidation fixed: no wrong value was reported\n        but the cache was not used at all, leading to lower performances.\n* [FIX] Accept(2) multiple clients per readable-event invocation, and better\n        processing of I/O while loading or busy running a timedout script.\n        Basically now the LOADING / BUSY errors are reported at a decent\n        speed.\n* [FIX] A softwaer watchdog crash fixed.\n* [FIX] Fixed a Lua -> Redis numerical precision loss.\n\n* [NEW] Lua scripting engine speed improved.\n* [NEW] Sentinel generates one new event for humans to understand better\n        what is happening during a failover: +config-update-from.\n        Also the time at which a failover will be re-attempted is logged.\n\n--[ Redis 2.8.9 ] Release date: 22 Apr 2014\n\n# UPGRADE URGENCY: LOW, only new features introduced, no bugs fixed.\n\n* [NEW] The HyperLogLog data structure. You can read more about it\n        in this blog post. http://antirez.com/news/75\n* [NEW] The Sorted Set data type has now support for lexicographic range\n        queries, check the new commands ZRANGEBYLEX, ZLEXCOUNT and\n        ZREMRANGEBYLEX, which are documented at http://redis.io.\n\n--[ Redis 2.8.8 ] Release date: 25 Mar 2014\n\n# UPGRADE URGENCY: HIGH for Redis, LOW for Sentinel. There is a potentially\n                   critical bug fix causing data loss in Redis but it requires\n                   a combination of disk full and the use of the\n                   SHUTDOWN command.\n\n* [FIX] Fixed data loss when SHUTDOWN was used with a disk full condition.\n* [FIX] Fixed a memory leak in the SORT syntax error processing.\n* [FIX] When Sentinel down-after-milliseconds parameter is modified at runtime\n        now it gets propagated to all the slaves and sentinel instances\n        of the master.\n* [FIX] `install_server.sh` script finally fixed.\n* [FIX] Different fixes to maxclients handling.\n\n* [NEW] Sentinels are now able to send update messages in a peer-to-peer\n        fashion even if no Redis instances are available. Now the Sentinel\n        liveness property that the most updated configuration in a given\n        partition is propagated to all the Sentinels is extended to partitions\n        without reachable instances.\n* [NEW] Sentinel safety properties are now ensured in a crash-recovery system\n        model since some state is persisted on disk before replying to other\n        nodes, and reloaded at startup.\n* [NEW] Sentinel now uses CLIENT SETNAME so that it is easy to identify\n        Sentinels using CLIENT LIST among other clients.\n* [NEW] Sentinel failure detection and reconnection code improved.\n* [NEW] Use all 24 bits (instead of 22) for the Redis objects LRU field.\n        Note that the new LRU algorithm using eviction pools was not backported\n        from unstable for safery / code maturity concerns.\n* [NEW] Majory speedup for the INFO command (it is now 6 times faster).\n* [NEW] More Sentinel unit tests.\n* [NEW] New command DEBUG ERROR returns the specified error. Example:\n        DEBUG ERROR \"LOADING database\". This is handy to write Redis client\n        libraries unit tests.\n* [NEW] redis-cli now supports multi-line editing via updated linenoise lib.\n\nThanks to Matt Stancliff and Jan-Erik Rediger for the work done in the context\nof this release.\n\n--[ Redis 2.8.7 ] Release date: 5 Mar 2014\n\n# UPGRADE URGENCY: LOW for Redis, LOW for Sentinel. However this release adds\n                   new features so users may want to upgrade in order to\n                   exploit the new functionalities.\n\n* [FIX] Sometimes the absolute config file path was obtained in a wrong way.\n        This happened when there was a \"dir\" directive inside the config file\n        and at the same time the configuration file was given as a relative\n        path to redis-server or redis-sentinel executables.\n* [FIX] redis-cli: Automatically enter --slave mode when SYNC or PSYNC are\n        called during an interactive session.\n* [FIX] Sentinel \"IDONTKNOW\" error removed as it does not made sense with the\n        new Sentinel design. This error was actually a fix for a design error\n        in the first implementation of Sentinel.\n* [FIX] Sentinel: added a missing exit() call to abort after config file\n        checks at startup. This error was introduced with an improvement in\n        a previous 2.8 release.\n* [FIX] BITCOUNT: fixed unaligned access causing issues in sparc and other\n        archs not capable of dealing with unaligned accesses. This also makes\n        the code faster in archs where unaligned accesses are allowed.\n* [FIX] Sentinel: better nodes fail over start time desynchronization to avoid\n        split-brain during the voting process needed to get authorization to\n        fail over. This means the system is less likely to need to retry\n        and will fail over faster. No changes in behavior / correctness.\n* [FIX] Force INFO used_memory_peak to match peak memory. This generated some\n        confusion among users even if it was not an actual bug.\n\n* [NEW] Sentinel unit tests and framework. More tests needed and units must\n        be improved in order to have less false positives, but it is a start\n        and features a debugging console that is useful to fix tests or to\n        inspect bugs causing tests failures.\n* [NEW] New Sentinel events: +/-monitor and +set used to monitor when an\n        instance to monitor is added or removed, or when a configuration\n        is modified via SENTINEL SET.\n* [NEW] Redis-cli updated to use SCAN instead of random sampling via\n        RANDOMKEY in order to implement --bigkeys feature. Moreover the\n        implementation now supports pipelining and reports more information\n        at the end of the scan. Much faster, much better. A special thank\n        you to Michael Grunder for this improvement.\n* [NEW] redis-cli now supports a new --intrinsic-latency mode that is able\n        to meter the latency of a system due to kernel / hypervisor.\n        How to use it is explained at http://redis.io/topics/latency.\n* [NEW] New command BITPOS: find first bit set or clear in a bitmap.\n* [NEW] CONFIG REWRITE calls are now logged.\n\n--[ Redis 2.8.6 ] Release date: 13 Feb 2014\n\n# UPGRADE URGENCY: HIGH for Redis, LOW for Sentinel. Redis users using Lua\n                   scripts with EVALSHA and attached slaves and/or AOF\n                   persistence should consider upgrading ASAP.\n\n* [FIX] Fixed an critical EVALSHA script cache bug: scripts executed may not\n        propagate to AOF / Slaves correctly under certain conditions.\n        See issue #1549 at Github for more information.\n* [FIX] Fixed multiple bugs resulting into closing the link with master or slave\n        during replication without good reasons. This will result in useless\n        resynchronizations, or infinite loops where the replication link can't\n        be established.\n* [FIX] Don't count the time needed to populate the buffers of clients waiting\n        in MONITOR mode when populating the Slow Log entries.\n\n* [NEW] AOF write errors (like no space on device) no longer abort Redis if the\n        fsync policy is none or every second. The database enters a read-only\n        mode where every write is refused with an error. Normal operations are\n        restored as soon as Redis is able to append again data to the AOF file.\n* [NEW] Sentinel now accepts SHUTDOWN command.\n\n--[ Redis 2.8.5 ] Release date: 4 Feb 2014\n\n# UPGRADE URGENCY: HIGH for Redis, LOW for Sentinel. Redis users using Lua\n                   scripts with expires, and Redis users relying on the\n                   ability of Redis to block writes on RDB saving errors\n                   should plan to upgrade ASAP.\n\n* [FIX] Fixed a replication bug caused by Lua scripts + expired keys: keys could\n        expire in the middle of scripts causing non-deterministic behavior.\n* [FIX] MISCONFIG error if condition fixed, the server was no longer able\n        to stop writes on RDB misconfiguration after this error was introduced.\n* [FIX] REDIS_AOF_REWRITE_MIN_SIZE is now 64mb like example redis.conf default.\n* [FIX] Perform fflush() before fsync() in rio.c (bug without actual effects).\n* [FIX] Don't log MONITOR clients as disconnecting slaves.\n* [FIX] SENTINEL MASTER arity check fixed. Crashed the Sentinel instance when\n        the command was given without arguments.\n\n* [NEW] Allow CONFIG and SHUTDOWN while in stale-slave state.\n* [NEW] Support for configurable TCP listen(2) backlog size.\n* [NEW] redis-cli supports SCAN via the --scan and --pattern options.\n* [NEW] SENTINEL SET master quorum via runtime API implemented.\n\n--[ Redis 2.8.4 ] Release date: 13 Jan 2014\n\n# UPGRADE URGENCY: MODERATE for Redis and Sentinel.\n\n* [FIX] Makefile compatibility with non common make variants improved.\n* [FIX] SDIFF crash in very unlikely to trigger state fixed.\n* [FIX] Config rewriting fixed: don't wipe options unknown to the rewrite\n        process.\n* [FIX] Set TCP port to 0 works again to disable TCP networking.\n* [FIX] Fixed replication with old Redis instances as masters by not\n        sending REPLCONF ACK to them.\n* [FIX] Fix keyspace notifications rewrite and CONFIG GET output.\n* [FIX] Fix RESTORE TTL handling in 32 bit systems (32 bit overflow).\n\n* [NEW] Sentinel now has a run time configuration API.\n* [NEW] Log when we lost connection with master or slave.\n* [NEW] When instance is turned from slave to master now inherits the\n        old master replication offset when possible. This improves the\n        Sentinel failover procedure.\n\n--[ Redis 2.8.3 ] Release date: 11 Dec 2013\n\n# UPGRADE URGENCY: MODERATE for Redis, HIGH for Sentinel.\n\n* [FIX] Sentinel instance role sampling fixed, the system is now more\n        reliable during failover and when reconfiguring instances with\n        non matching configuration.\n* [FIX] Inline requests are now handled even when terminated with just LF.\n* [FIX] Replication timeout handling greatly improved, now the slave is able\n        to ping the master while removing the old data from memory, and while\n        loading the new RDB file. This avoid false timeouts sensed by\n        masters.\n* [FIX] Fixed a replication bug involving 32 bit instances and big datasets\n        hard to compress that resulted into more than 2GB of RDB file sent.\n* [FIX] Return error for inline requests with unbalanced quotes.\n* [FIX] Publish the slave replication offset even when disconnected from the\n        master if there is still a cached master instance.\n\n--[ Redis 2.8.2 ] Release date: 2 Dec 2013\n\n# UPGRADE URGENCY: MODERATE for both Redis and Sentinel.\n\n* [FIX] Sentinel better desynchronization to avoid split-brain elections\n        where no Sentinel managed to get elected.\n* [FIX] Stop accepting writes on \"MISCONF\" error only if master, not slave.\n* [FIX] Reply to PING with an error on \"MISCONF\" errors.\n\n--[ Redis 2.8.1 ] Release date: 25 Nov 2013\n\n# UPGRADE URGENCY: LOW for Redis, CRITICAL for Senitnel. You don't need to\n                   upgrade your Redis instances but it is highly recommended\n                   to upgrade and restart all the Sentinel processes.\n\n* [FIX] Fixed a bug in \"new Sentinel\" config propagation.\n* [FIX] Fixed a false positive in Redis tests.\n\n--[ Redis 2.8.0 ] Release date: 22 Nov 2013\n\n# UPGRADE URGENCY: LOW, unless you want to upgrade to new Sentinel code.\n\n* [FIX] Fixed an error in rdbWriteRaw() that should have no practical impact.\n* [NEW] Log the new master when SLAVEOF command is used.\n* [NEW] Sentinel code synchronized with the unstable branch, the new Sentinel\n        is a reimplementation that uses more reliable algorithms.\n\n--[ Redis 2.8 Release Candidate 6 (2.7.106) ] Release date: 6 Nov 2013\n\nThis is the 6th release candidate of Redis 2.8 (official version is 2.7.106).\n\n# UPGRADE URGENCY: LOW, only new features back ported, no fixes.\n\n* [NEW] SCAN, SSCAN, HSCAN, ZSCAN commands.\n\n--[ Redis 2.8 Release Candidate 5 (2.7.105) ] Release date: 9 Oct 2013\n\nThis is the 5th release candidate of Redis 2.8 (official version is 2.7.105).\nImportant bugs fixed inside.\n\n# UPGRADE URGENCY: HIGH because of many non critical replication bugs fixed.\n\n* [FIX] redis-cli: don't crash with --bigkeys when the key no longer exist.\n* [FIX] Allow AUTH / PING when disconnected from slave and serve-stale-data is no.\n* [FIX] PSYNC: safer handling of PSYNC requests with offsets in the future.\n* [FIX] Replication: Fix master timeout detection.\n* [FIX] Replication: Correctly install the write handler after successful PSYNC.\n\n--[ Redis 2.8 Release Candidate 4 (2.7.104) ] Release date: 30 Aug 2013\n\nThis is the fourth release candidate of Redis 2.8 (official version is 2.7.104).\nImportant bugs fixed inside.\n\n# UPGRADE URGENCY: HIGH because of the EVAL memory leak.\n\n* [FIX] Fixed a serious EVAL memory leak in the Lua stack.\n* [FIX] Fixed server startup when no IPv6 address exists in any interface.\n* [FIX] Send MISCONFIG error when BGSAVE fails because can't fork.\n* [FIX] Memory efficiency with large (> a few kbytes) values improved considerably.\n* [NEW] DEBUG SDSLEN for sds memory debugging.\n\n--[ Redis 2.8 Release Candidate 3 (2.7.103) ] Release date: 19 Aug 2013\n\nThis is the third release candidate of Redis 2.8 (official version is 2.7.103).\nImportant bugs fixed inside.\n\n# UPGRADE URGENCY: HIGH\n\n* [FIX] Improved expired keys collection algorithm. Even under heavy load keys\n        to be expired can't accumulate because of lack of CPU time.\n* [FIX] Replication speed regression fixed (issue #1238).\n* [FIX] Fixed an hard to trigger PSYNC bug.\n* [FIX] Fixed Issue #1240, ZUNIONSTORE could lead to wrong result.\n* [NEW] Add per-db average TTL information in INFO output.\n* [NEW] redis-benchmark improvements.\n* [NEW] dict.c API wrong usage detection.\n\n--[ Redis 2.8 Release Candidate 2 (2.7.102) ] Release date: 30 Jul 2013\n\nThis is the second release candidate of Redis 2.8 (official version is 2.7.102).\nImportant bugs fixed inside.\n\n# UPGRADE URGENCY: HIGH\n\n* [FIX] Fixed a critical replication bug, see issue #1221.\n* [NEW] The new inline protocol now accepts quoted strings like, for example\n        you can now type in a telnet session: set 'foo bar' \"hello world\\n\".\n\n--[ Redis 2.8 Release Candidate 1 (2.7.101) ] Release date: 18 Jul 2013\n\nThis is the first release candidate of Redis 2.8 (official version is 2.7.101).\n\nThe following is a list of improvements in Redis 2.8, compared to Redis 2.6.\n\n* [NEW] Slaves are now able to partially resynchronize with the master, so most\n        of the times a full resynchronization with the RDB creation in the master\n        side is not needed when the master-slave link is disconnected for a short\n        amount of time.\n* [NEW] Experimental IPv6 support.\n* [NEW] Slaves explicitly ping masters now, a master is able to detect a timed out\n        slave independently.\n* [NEW] Masters can stop accepting writes if not enough slaves with a given\n        maximum latency are connected.\n* [NEW] Keyspace changes notifications via Pub/Sub.\n* [NEW] CONFIG SET maxclients is now available.\n* [NEW] Ability to bind multiple IP addresses.\n* [NEW] Set process names so that you can recognize, in the \"ps\" command output,\n        the listening port of an instance, or if it is a saving child.\n* [NEW] Automatic memory check on crash.\n* [NEW] CONFIG REWRITE is able to materialize the changes in the configuration\n        operated using CONFIG SET into the redis.conf file.\n* [NEW] More NetBSD friendly code base.\n* [NEW] PUBSUB command for Pub/Sub introspection capabilities.\n* [NEW] EVALSHA can now be replicated as such, without requiring to be expanded\n        to a full EVAL for the replication link.\n* [NEW] Better Lua scripts error reporting.\n* [NEW] SDIFF performance improved.\n* [FIX] A number of bugfixes.\n\nMigrating from 2.6 to 2.8\n=========================\n\nRedis 2.6 is mostly a strict subset of 2.8. However there are a few things\nthat you should be aware of:\n\nThe following commands changed behavior:\n\n    * The TTL and PTTL commands now return -2 if the key does not exist and\n      -1 if it exists but has no associated expire. Redis 2.6 and previous\n      versions used to return -1 for both the conditions.\n    * SORT with ALPHA now sorts according to local collation locale if no STORE\n      option is used.\n    * ZADD/ZINCRBY are now able to accept a bigger range of values as valid\n      scores, that is, all the values you may end having as a result of\n      calling ZINCRBY multiple times.\n    * Many errors are now prefixed by a more specific error code instead of\n      the generic -ERR, for example -WRONGTYPE, -NOAUTH, ...\n    * PUBLISH called inside Lua scripts is now correctly propagated to slaves.\n\nThe following redis.conf and CONFIG GET / SET parameters changed:\n\n    * logfile now uses the empty string in order to log to standard output,\n      so 'logfile stdout' is now invalid, use 'logfile \"\"' instead.\n\nThe following INFO fields changed format in a non-backward compatible way:\n\n    * The list of slaves in INFO is now in field=value format.\n\nReplication:\n\n    Redis 2.8 can be used as slave for Redis 2.6, but doing this is only\n    a good idea for the short amount of time needed to upgrade your servers.\n    We suggest to update both master and slaves at about the same time.\n\n--------------------------------------------------------------------------------\n\nCredits: Where not specified the implementation and design is done by\nSalvatore Sanfilippo. Thanks to VMware and Pivotal for making all\nthis possible. Also many thanks to all the other contributors and the amazing\ncommunity we have.\n\nSee commit messages for more credits.\n\nCheers,\nSalvatore\n"
  },
  {
    "path": "extern/deprecated/redis-2.8.21/0000-redis.patch",
    "content": "diff --git a/extern/redis-2.8.21/redis.conf b/extern/redis-2.8.21/redis.conf\nindex 6c76569..0dadba0 100644\n--- a/extern/redis-2.8.21/redis.conf\n+++ b/extern/redis-2.8.21/redis.conf\n@@ -34,7 +34,7 @@\n \n # By default Redis does not run as a daemon. Use 'yes' if you need it.\n # Note that Redis will write a pid file in /var/run/redis.pid when daemonized.\n-daemonize no\n+daemonize yes\n \n # When running daemonized, Redis writes a pid file in /var/run/redis.pid by\n # default. You can specify a custom pid file location here.\ndiff --git a/extern/redis-2.8.21/src/Makefile b/extern/redis-2.8.21/src/Makefile\nindex a65e767..10ecfd9 100644\n--- a/extern/redis-2.8.21/src/Makefile\n+++ b/extern/redis-2.8.21/src/Makefile\n@@ -113,7 +113,7 @@ endif\n \n REDIS_SERVER_NAME=redis-server\n REDIS_SENTINEL_NAME=redis-sentinel\n-REDIS_SERVER_OBJ=adlist.o ae.o anet.o dict.o redis.o sds.o zmalloc.o lzf_c.o lzf_d.o pqsort.o zipmap.o sha1.o ziplist.o release.o networking.o util.o object.o db.o replication.o rdb.o t_string.o t_list.o t_set.o t_zset.o t_hash.o config.o aof.o pubsub.o multi.o debug.o sort.o intset.o syncio.o migrate.o endianconv.o slowlog.o scripting.o bio.o rio.o rand.o memtest.o crc64.o bitops.o sentinel.o notify.o setproctitle.o hyperloglog.o latency.o sparkline.o\n+REDIS_SERVER_OBJ=adlist.o ae.o anet.o dict.o redis.o sds.o zmalloc.o lzf_c.o lzf_d.o pqsort.o zipmap.o sha1.o ziplist.o release.o networking.o util.o object.o db.o replication.o rdb.o t_string.o t_list.o t_set.o t_zset.o t_hash.o config.o aof.o pubsub.o multi.o debug.o sort.o intset.o syncio.o migrate.o endianconv.o slowlog.o scripting.o bio.o rio.o rand.o memtest.o crc64.o crc32.o bitops.o sentinel.o notify.o setproctitle.o hyperloglog.o latency.o sparkline.o slots.o\n REDIS_CLI_NAME=redis-cli\n REDIS_CLI_OBJ=anet.o sds.o adlist.o redis-cli.o zmalloc.o release.o anet.o ae.o crc64.o\n REDIS_BENCHMARK_NAME=redis-benchmark\ndiff --git a/extern/redis-2.8.21/src/Makefile.dep b/extern/redis-2.8.21/src/Makefile.dep\nindex 1f24232..13a5ee9 100644\n--- a/extern/redis-2.8.21/src/Makefile.dep\n+++ b/extern/redis-2.8.21/src/Makefile.dep\n@@ -20,6 +20,7 @@ config.o: config.c redis.h fmacros.h config.h ../deps/lua/src/lua.h \\\n   ../deps/lua/src/luaconf.h ae.h sds.h dict.h adlist.h zmalloc.h anet.h \\\n   ziplist.h intset.h version.h util.h latency.h sparkline.h rdb.h rio.h\n crc64.o: crc64.c\n+crc32.o: crc32.c\n db.o: db.c redis.h fmacros.h config.h ../deps/lua/src/lua.h \\\n   ../deps/lua/src/luaconf.h ae.h sds.h dict.h adlist.h zmalloc.h anet.h \\\n   ziplist.h intset.h version.h util.h latency.h sparkline.h rdb.h rio.h\n@@ -40,6 +41,7 @@ latency.o: latency.c redis.h fmacros.h config.h ../deps/lua/src/lua.h \\\n lzf_c.o: lzf_c.c lzfP.h\n lzf_d.o: lzf_d.c lzfP.h\n memtest.o: memtest.c config.h\n+slots.o: slots.c redis.h\n migrate.o: migrate.c redis.h fmacros.h config.h ../deps/lua/src/lua.h \\\n   ../deps/lua/src/luaconf.h ae.h sds.h dict.h adlist.h zmalloc.h anet.h \\\n   ziplist.h intset.h version.h util.h latency.h sparkline.h rdb.h rio.h \\\ndiff --git a/extern/redis-2.8.21/src/crc32.c b/extern/redis-2.8.21/src/crc32.c\nnew file mode 100644\nindex 0000000..d6f54a6\n--- /dev/null\n+++ b/extern/redis-2.8.21/src/crc32.c\n@@ -0,0 +1,43 @@\n+#include <stdint.h>\n+\n+static const uint32_t IEEE_POLY = 0xedb88320;\n+static const uint32_t CAST_POLY = 0x82f63b78;\n+static const uint32_t KOOP_POLY = 0xeb31d82e;\n+\n+static uint32_t crc32tab[256];\n+\n+static void\n+crc32_tabinit(uint32_t poly) {\n+    int i, j;\n+    for (i = 0; i < 256; i ++) {\n+        uint32_t crc = i;\n+        for (j = 0; j < 8; j ++) {\n+            if (crc & 1) {\n+                crc = (crc >> 1) ^ poly;\n+            } else {\n+                crc = (crc >> 1);\n+            }\n+        }\n+        crc32tab[i] = crc;\n+    }\n+}\n+\n+void\n+crc32_init() {\n+    crc32_tabinit(IEEE_POLY);\n+}\n+\n+static uint32_t\n+crc32_update(uint32_t crc, const char *buf, int len) {\n+    int i;\n+    crc = ~crc;\n+    for (i = 0; i < len; i ++) {\n+        crc = crc32tab[(uint8_t)((char)crc ^ buf[i])] ^ (crc >> 8);\n+    }\n+    return ~crc;\n+}\n+\n+uint32_t\n+crc32_checksum(const char *buf, int len) {\n+    return crc32_update(0, buf, len);\n+}\ndiff --git a/extern/redis-2.8.21/src/db.c b/extern/redis-2.8.21/src/db.c\nindex dfec719..8bab0d3 100644\n--- a/extern/redis-2.8.21/src/db.c\n+++ b/extern/redis-2.8.21/src/db.c\n@@ -32,9 +32,6 @@\n #include <signal.h>\n #include <ctype.h>\n \n-void SlotToKeyAdd(robj *key);\n-void SlotToKeyDel(robj *key);\n-\n /*-----------------------------------------------------------------------------\n  * C-level DB API\n  *----------------------------------------------------------------------------*/\n@@ -90,11 +87,23 @@ robj *lookupKeyWriteOrReply(redisClient *c, robj *key, robj *reply) {\n  * The program is aborted if the key already exists. */\n void dbAdd(redisDb *db, robj *key, robj *val) {\n     sds copy = sdsdup(key->ptr);\n+\n     int retval = dictAdd(db->dict, copy, val);\n \n+    do {\n+        uint32_t crc;\n+        int hastag;\n+        int slot = slots_num(key->ptr, &crc, &hastag);\n+        dictAdd(db->hash_slots[slot], copy, (void *)(long)crc);\n+        if (hastag) {\n+            incrRefCount(key);\n+            zslInsert(db->tagged_keys, (double)crc, key);\n+        }\n+    } while (0);\n+\n     redisAssertWithInfo(NULL,key,retval == REDIS_OK);\n     if (val->type == REDIS_LIST) signalListAsReady(db, key);\n- }\n+}\n \n /* Overwrite an existing key with a new value. Incrementing the reference\n  * count of the new value is up to the caller.\n@@ -160,6 +169,18 @@ int dbDelete(redisDb *db, robj *key) {\n     /* Deleting an entry from the expires dict will not free the sds of\n      * the key, because it is shared with the main dictionary. */\n     if (dictSize(db->expires) > 0) dictDelete(db->expires,key->ptr);\n+\n+    do {\n+        uint32_t crc;\n+        int hastag;\n+        int slot = slots_num(key->ptr, &crc, &hastag);\n+        if (dictDelete(db->hash_slots[slot], key->ptr) == DICT_OK) {\n+            if (hastag) {\n+                zslDelete(db->tagged_keys, (double)crc, key);\n+            }\n+        }\n+    } while (0);\n+\n     if (dictDelete(db->dict,key->ptr) == DICT_OK) {\n         return 1;\n     } else {\n@@ -206,11 +227,18 @@ robj *dbUnshareStringValue(redisDb *db, robj *key, robj *o) {\n }\n \n long long emptyDb(void(callback)(void*)) {\n-    int j;\n+    int i, j;\n     long long removed = 0;\n-\n+    \n     for (j = 0; j < server.dbnum; j++) {\n         removed += dictSize(server.db[j].dict);\n+        for (i = 0; i < HASH_SLOTS_SIZE; i ++) {\n+            dictEmpty(server.db[j].hash_slots[i], NULL);\n+        }\n+        if (server.db[j].tagged_keys->length != 0) {\n+            zslFree(server.db[j].tagged_keys);\n+            server.db[j].tagged_keys = zslCreate();\n+        }\n         dictEmpty(server.db[j].dict,callback);\n         dictEmpty(server.db[j].expires,callback);\n     }\n@@ -246,8 +274,16 @@ void signalFlushedDb(int dbid) {\n  *----------------------------------------------------------------------------*/\n \n void flushdbCommand(redisClient *c) {\n+    int i;\n     server.dirty += dictSize(c->db->dict);\n     signalFlushedDb(c->db->id);\n+    for (i = 0; i < HASH_SLOTS_SIZE; i ++) {\n+        dictEmpty(c->db->hash_slots[i], NULL);\n+    }\n+    if (c->db->tagged_keys->length != 0) {\n+        zslFree(c->db->tagged_keys);\n+        c->db->tagged_keys = zslCreate();\n+    }\n     dictEmpty(c->db->dict,NULL);\n     dictEmpty(c->db->expires,NULL);\n     addReply(c,shared.ok);\n@@ -646,7 +682,15 @@ void shutdownCommand(redisClient *c) {\n      * Also when in Sentinel mode clear the SAVE flag and force NOSAVE. */\n     if (server.loading || server.sentinel_mode)\n         flags = (flags & ~REDIS_SHUTDOWN_SAVE) | REDIS_SHUTDOWN_NOSAVE;\n-    if (prepareForShutdown(flags) == REDIS_OK) exit(0);\n+    if (prepareForShutdown(flags) == REDIS_OK) {\n+        for (int j = 0; j < server.dbnum; j ++) {\n+            for (int i = 0; i < HASH_SLOTS_SIZE; i ++) {\n+                dictRelease(server.db[j].hash_slots[i]);\n+            }\n+            zslFree(server.db[j].tagged_keys);\n+        }\n+        exit(0);\n+    }\n     addReplyError(c,\"Errors trying to SHUTDOWN. Check logs.\");\n }\n \ndiff --git a/extern/redis-2.8.21/src/migrate.c b/extern/redis-2.8.21/src/migrate.c\nindex 543b00f..7a35a64 100644\n--- a/extern/redis-2.8.21/src/migrate.c\n+++ b/extern/redis-2.8.21/src/migrate.c\n@@ -140,7 +140,7 @@ void migrateCommand(redisClient *c) {\n         return;\n     if (getLongFromObjectOrReply(c,c->argv[4],&dbid,NULL) != REDIS_OK)\n         return;\n-    if (timeout <= 0) timeout = 1;\n+    if (timeout <= 0) timeout = 1000;\n \n     /* Check if the key is here. If not we reply with success as there is\n      * nothing to migrate (for instance the key expired in the meantime), but\n@@ -158,8 +158,11 @@ void migrateCommand(redisClient *c) {\n             server.neterr);\n         return;\n     }\n-    if ((aeWait(fd,AE_WRITABLE,timeout*1000) & AE_WRITABLE) == 0) {\n+    anetEnableTcpNoDelay(server.neterr,fd);\n+\n+    if ((aeWait(fd,AE_WRITABLE,timeout) & AE_WRITABLE) == 0) {\n         addReplySds(c,sdsnew(\"-IOERR error or timeout connecting to the client\\r\\n\"));\n+        close(fd);\n         return;\n     }\n \ndiff --git a/extern/redis-2.8.21/src/redis.c b/extern/redis-2.8.21/src/redis.c\nindex 3a9ab21..21e75d0 100644\n--- a/extern/redis-2.8.21/src/redis.c\n+++ b/extern/redis-2.8.21/src/redis.c\n@@ -274,7 +274,16 @@ struct redisCommand redisCommandTable[] = {\n     {\"pfcount\",pfcountCommand,-2,\"r\",0,NULL,1,1,1,0,0},\n     {\"pfmerge\",pfmergeCommand,-2,\"wm\",0,NULL,1,-1,1,0,0},\n     {\"pfdebug\",pfdebugCommand,-3,\"w\",0,NULL,0,0,0,0,0},\n-    {\"latency\",latencyCommand,-2,\"arslt\",0,NULL,0,0,0,0,0}\n+    {\"latency\",latencyCommand,-2,\"arslt\",0,NULL,0,0,0,0,0},\n+    {\"slotsinfo\",slotsinfoCommand,-1,\"rF\",0,NULL,0,0,0,0,0},\n+    {\"slotsdel\",slotsdelCommand,-2,\"w\",0,NULL,1,-1,1,0,0},\n+    {\"slotsmgrtslot\",slotsmgrtslotCommand,5,\"aw\",0,NULL,0,0,0,0,0},\n+    {\"slotsmgrtone\",slotsmgrtoneCommand,5,\"aw\",0,NULL,0,0,0,0,0},\n+    {\"slotsmgrttagslot\",slotsmgrttagslotCommand,5,\"aw\",0,NULL,0,0,0,0,0},\n+    {\"slotsmgrttagone\",slotsmgrttagoneCommand,5,\"aw\",0,NULL,0,0,0,0,0},\n+    {\"slotshashkey\",slotshashkeyCommand,-1,\"rF\",0,NULL,0,0,0,0,0},\n+    {\"slotscheck\",slotscheckCommand,0,\"r\",0,NULL,0,0,0,0,0},\n+    {\"slotsrestore\",slotsrestoreCommand,-4,\"awm\",0,NULL,1,1,1,0,0},\n };\n \n /*============================ Utility functions ============================ */\n@@ -531,6 +540,15 @@ dictType dbDictType = {\n     dictRedisObjectDestructor   /* val destructor */\n };\n \n+dictType hashSlotType = {\n+    dictSdsHash,                /* hash function */\n+    NULL,                       /* key dup */\n+    NULL,                       /* val dup */\n+    dictSdsKeyCompare,          /* key compare */\n+    NULL,                       /* key destructor */\n+    NULL                        /* val destructor */\n+};\n+\n /* server.lua_scripts sha (as sds string) -> scripts (as robj) cache. */\n dictType shaScriptObjectDictType = {\n     dictSdsCaseHash,            /* hash function */\n@@ -595,6 +613,15 @@ dictType replScriptCacheDictType = {\n     NULL                        /* val destructor */\n };\n \n+dictType migrateCacheDictType = {\n+    dictSdsHash,                /* hash function */\n+    NULL,                       /* key dup */\n+    NULL,                       /* val dup */\n+    dictSdsKeyCompare,          /* key compare */\n+    dictSdsDestructor,          /* key destructor */\n+    NULL                        /* val destructor */\n+};\n+\n int htNeedsResize(dict *dict) {\n     long long size, used;\n \n@@ -607,8 +634,15 @@ int htNeedsResize(dict *dict) {\n /* If the percentage of used slots in the HT reaches REDIS_HT_MINFILL\n  * we resize the hash table to save memory */\n void tryResizeHashTables(int dbid) {\n-    if (htNeedsResize(server.db[dbid].dict))\n+    if (htNeedsResize(server.db[dbid].dict)) {\n         dictResize(server.db[dbid].dict);\n+        for (int i = 0; i < HASH_SLOTS_SIZE; i ++) {\n+            dict *d = server.db[dbid].hash_slots[i];\n+            if (htNeedsResize(d)) {\n+                dictResize(d);\n+            }\n+        }\n+    }\n     if (htNeedsResize(server.db[dbid].expires))\n         dictResize(server.db[dbid].expires);\n }\n@@ -624,6 +658,12 @@ int incrementallyRehash(int dbid) {\n     /* Keys dictionary */\n     if (dictIsRehashing(server.db[dbid].dict)) {\n         dictRehashMilliseconds(server.db[dbid].dict,1);\n+        for (int i = 0; i < HASH_SLOTS_SIZE; i ++) {\n+            dict *d = server.db[dbid].hash_slots[i];\n+            if (dictIsRehashing(d)) {\n+                dictRehashMilliseconds(d, 1);\n+            }\n+        }\n         return 1; /* already used our millisecond for this loop... */\n     }\n     /* Expires */\n@@ -1179,6 +1219,10 @@ int serverCron(struct aeEventLoop *eventLoop, long long id, void *clientData) {\n         if (server.sentinel_mode) sentinelTimer();\n     }\n \n+    run_with_period(1000) {\n+        slotsmgrt_cleanup();\n+    }\n+\n     server.cronloops++;\n     return 1000/server.hz;\n }\n@@ -1385,6 +1429,8 @@ void initServerConfig(void) {\n     server.next_client_id = 1; /* Client IDs, start from 1 .*/\n     server.loading_process_events_interval_bytes = (1024*1024*2);\n \n+    server.slotsmgrt_cached_sockfds = dictCreate(&migrateCacheDictType, NULL);\n+\n     updateLRUClock();\n     resetServerSaveParams();\n \n@@ -1648,12 +1694,14 @@ void resetServerStats(void) {\n }\n \n void initServer(void) {\n-    int j;\n+    int i, j;\n \n     signal(SIGHUP, SIG_IGN);\n     signal(SIGPIPE, SIG_IGN);\n     setupSignalHandlers();\n \n+    crc32_init();\n+\n     if (server.syslog_enabled) {\n         openlog(server.syslog_ident, LOG_PID | LOG_NDELAY | LOG_NOWAIT,\n             server.syslog_facility);\n@@ -1705,6 +1753,10 @@ void initServer(void) {\n         server.db[j].watched_keys = dictCreate(&keylistDictType,NULL);\n         server.db[j].id = j;\n         server.db[j].avg_ttl = 0;\n+        for (i = 0; i < HASH_SLOTS_SIZE; i ++) {\n+            server.db[j].hash_slots[i] = dictCreate(&hashSlotType, NULL);\n+        }\n+        server.db[j].tagged_keys = zslCreate();\n     }\n     server.pubsub_channels = dictCreate(&keylistDictType,NULL);\n     server.pubsub_patterns = listCreate();\ndiff --git a/extern/redis-2.8.21/src/redis.h b/extern/redis-2.8.21/src/redis.h\nindex bd6e493..a15910a 100644\n--- a/extern/redis-2.8.21/src/redis.h\n+++ b/extern/redis-2.8.21/src/redis.h\n@@ -421,12 +421,22 @@ typedef struct redisObject {\n     _var.ptr = _ptr; \\\n } while(0);\n \n+void crc32_init();\n+uint32_t crc32_checksum(const char *buf, int len);\n+\n+#define HASH_SLOTS_MASK 0x000003ff\n+#define HASH_SLOTS_SIZE (HASH_SLOTS_MASK + 1)\n+\n+struct zskiplist;\n+\n typedef struct redisDb {\n     dict *dict;                 /* The keyspace for this DB */\n     dict *expires;              /* Timeout of keys with a timeout set */\n     dict *blocking_keys;        /* Keys with clients waiting for data (BLPOP) */\n     dict *ready_keys;           /* Blocked keys that received a PUSH */\n     dict *watched_keys;         /* WATCHED keys for MULTI/EXEC CAS */\n+    dict *hash_slots[HASH_SLOTS_SIZE];\n+    struct zskiplist *tagged_keys;\n     int id;\n     long long avg_ttl;          /* Average TTL, just for stats */\n } redisDb;\n@@ -634,6 +644,7 @@ struct redisServer {\n     list *slaves, *monitors;    /* List of slaves and MONITORs */\n     redisClient *current_client; /* Current client, only used on crash report */\n     char neterr[ANET_ERR_LEN];   /* Error buffer for anet.c */\n+    dict *slotsmgrt_cached_sockfds;\n     uint64_t next_client_id;    /* Next client unique ID. Incremental. */\n     /* RDB / AOF loading information */\n     int loading;                /* We are loading data from disk if true */\n@@ -1422,6 +1433,18 @@ void pfcountCommand(redisClient *c);\n void pfmergeCommand(redisClient *c);\n void pfdebugCommand(redisClient *c);\n void latencyCommand(redisClient *c);\n+void slotsinfoCommand(redisClient *c);\n+void slotsdelCommand(redisClient *c);\n+void slotsmgrtslotCommand(redisClient *c);\n+void slotsmgrtoneCommand(redisClient *c);\n+void slotsmgrttagslotCommand(redisClient *c);\n+void slotsmgrttagoneCommand(redisClient *c);\n+void slotshashkeyCommand(redisClient *c);\n+void slotscheckCommand(redisClient *c);\n+void slotsrestoreCommand(redisClient *c);\n+\n+void slotsmgrt_cleanup();\n+int slots_num(const sds s, uint32_t *pcrc, int *phastag);\n \n #if defined(__GNUC__)\n void *calloc(size_t count, size_t size) __attribute__ ((deprecated));\ndiff --git a/extern/redis-2.8.21/src/slots.c b/extern/redis-2.8.21/src/slots.c\nnew file mode 100644\nindex 0000000..24df9ae\n--- /dev/null\n+++ b/extern/redis-2.8.21/src/slots.c\n@@ -0,0 +1,817 @@\n+#include \"redis.h\"\n+\n+extern void createDumpPayload(rio *payload, robj *o);\n+extern int verifyDumpPayload(unsigned char *p, size_t len);\n+\n+static void *\n+slots_tag(const sds s, int *plen) {\n+    int i, j, n = sdslen(s);\n+    for (i = 0; i < n && s[i] != '{'; i ++) {}\n+    if (i == n) {\n+        return NULL;\n+    }\n+    i ++;\n+    for (j = i; j < n && s[j] != '}'; j ++) {}\n+    if (j == n) {\n+        return NULL;\n+    }\n+    if (plen != NULL) {\n+        *plen = j - i;\n+    }\n+    return s + i;\n+}\n+\n+int\n+slots_num(const sds s, uint32_t *pcrc, int *phastag) {\n+    int taglen;\n+    int hastag = 0;\n+    void *tag = slots_tag(s, &taglen);\n+    if (tag == NULL) {\n+        tag = s, taglen = sdslen(s);\n+    } else {\n+        hastag = 1;\n+    }\n+    uint32_t crc = crc32_checksum(tag, taglen);\n+    if (pcrc != NULL) {\n+        *pcrc = crc;\n+    }\n+    if (phastag != NULL) {\n+        *phastag = hastag;\n+    }\n+    return crc & HASH_SLOTS_MASK;\n+}\n+\n+static int\n+parse_int(redisClient *c, robj *obj, int *p) {\n+    long v;\n+    if (getLongFromObjectOrReply(c, obj, &v, NULL) != REDIS_OK) {\n+        return -1;\n+    }\n+    *p = v;\n+    return 0;\n+}\n+\n+static int\n+parse_timeout(redisClient *c, robj *obj, int *p) {\n+    int v;\n+    if (parse_int(c, obj, &v) != 0) {\n+        return -1;\n+    }\n+    if (v < 0) {\n+        addReplyErrorFormat(c, \"invalid timeout = %d\", v);\n+        return -1;\n+    }\n+    *p = (v == 0) ? 100 : v;\n+    return 0;\n+}\n+\n+static int\n+parse_slot(redisClient *c, robj *obj, int *p) {\n+    int v;\n+    if (parse_int(c, obj, &v) != 0) {\n+        return -1;\n+    }\n+    if (v < 0 || v >= HASH_SLOTS_SIZE) {\n+        addReplyErrorFormat(c, \"invalid slot number = %d\", v);\n+        return -1;\n+    }\n+    *p = v;\n+    return 0;\n+}\n+\n+/* *\n+ * slotshashkey [key1 key2...]\n+ * */\n+void\n+slotshashkeyCommand(redisClient *c) {\n+    int i;\n+    addReplyMultiBulkLen(c, c->argc - 1);\n+    for (i = 1; i < c->argc; i ++) {\n+        robj *key = c->argv[i];\n+        addReplyLongLong(c, slots_num(key->ptr, NULL, NULL));\n+    }\n+}\n+\n+/* *\n+ * slotsinfo [start] [count]\n+ * */\n+void\n+slotsinfoCommand(redisClient *c) {\n+    int slots_slot[HASH_SLOTS_SIZE];\n+    int slots_size[HASH_SLOTS_SIZE];\n+    int n = 0, beg = 0, end = HASH_SLOTS_SIZE;\n+    if (c->argc >= 2) {\n+        if (parse_slot(c, c->argv[1], &beg) != 0) {\n+            return;\n+        }\n+    }\n+    if (c->argc >= 3) {\n+        int v;\n+        if (parse_int(c, c->argv[2], &v) != 0) {\n+            return;\n+        }\n+        if (v < 0) {\n+            addReplyErrorFormat(c, \"invalid slot count = %d\", v);\n+            return;\n+        }\n+        if (beg + v < end) {\n+            end = beg + v;\n+        }\n+    }\n+    if (c->argc >= 4) {\n+        addReplyErrorFormat(c, \"wrong number of arguments for 'slotsinfo' command\");\n+        return;\n+    }\n+    int i;\n+    for (i = beg; i < end; i ++) {\n+        int s = dictSize(c->db->hash_slots[i]);\n+        if (s == 0) {\n+            continue;\n+        }\n+        slots_slot[n] = i;\n+        slots_size[n] = s;\n+        n ++;\n+    }\n+    addReplyMultiBulkLen(c, n);\n+    for (i = 0; i < n; i ++) {\n+        addReplyMultiBulkLen(c, 2);\n+        addReplyLongLong(c, slots_slot[i]);\n+        addReplyLongLong(c, slots_size[i]);\n+    }\n+}\n+\n+typedef struct {\n+    int fd;\n+    int db;\n+    int authorized;\n+    time_t lasttime;\n+} slotsmgrt_sockfd;\n+\n+static slotsmgrt_sockfd *\n+slotsmgrt_get_sockfd(redisClient *c, sds host, sds port, int timeout) {\n+    sds name = sdsempty();\n+    name = sdscatlen(name, host, sdslen(host));\n+    name = sdscatlen(name, \":\", 1);\n+    name = sdscatlen(name, port, sdslen(port));\n+\n+    slotsmgrt_sockfd *pfd = dictFetchValue(server.slotsmgrt_cached_sockfds, name);\n+    if (pfd != NULL) {\n+        sdsfree(name);\n+        pfd->lasttime = server.unixtime;\n+        return pfd;\n+    }\n+\n+    int fd = anetTcpNonBlockConnect(server.neterr, host, atoi(port));\n+    if (fd == -1) {\n+        redisLog(REDIS_WARNING, \"slotsmgrt: connect to target %s:%s, error = '%s'\",\n+                host, port, server.neterr);\n+        sdsfree(name);\n+        addReplyErrorFormat(c,\"Can't connect to target node: %s\", server.neterr);\n+        return NULL;\n+    }\n+    anetEnableTcpNoDelay(server.neterr, fd);\n+    if ((aeWait(fd, AE_WRITABLE, timeout) & AE_WRITABLE) == 0) {\n+        redisLog(REDIS_WARNING, \"slotsmgrt: connect to target %s:%s, aewait error = '%s'\",\n+                host, port, server.neterr);\n+        sdsfree(name);\n+        close(fd);\n+        addReplySds(c, sdsnew(\"-IOERR error or timeout connecting to the client\\r\\n\"));\n+        return NULL;\n+    }\n+    redisLog(REDIS_WARNING, \"slotsmgrt: connect to target %s:%s\", host, port);\n+\n+    pfd = zmalloc(sizeof(*pfd));\n+    pfd->fd = fd;\n+    pfd->db = -1;\n+    pfd->authorized = (server.requirepass == NULL) ? 1 : 0;\n+    pfd->lasttime = server.unixtime;\n+    dictAdd(server.slotsmgrt_cached_sockfds, name, pfd);\n+    return pfd;\n+}\n+\n+static void\n+slotsmgrt_close_socket(sds host, sds port) {\n+    sds name = sdsempty();\n+    name = sdscatlen(name, host, sdslen(host));\n+    name = sdscatlen(name, \":\", 1);\n+    name = sdscatlen(name, port, sdslen(port));\n+\n+    slotsmgrt_sockfd *pfd = dictFetchValue(server.slotsmgrt_cached_sockfds, name);\n+    if (pfd == NULL) {\n+        redisLog(REDIS_WARNING, \"slotsmgrt: close target %s:%s again\", host, port);\n+        sdsfree(name);\n+        return;\n+    } else {\n+        redisLog(REDIS_WARNING, \"slotsmgrt: close target %s:%s\", host, port);\n+    }\n+    dictDelete(server.slotsmgrt_cached_sockfds, name);\n+    close(pfd->fd);\n+    zfree(pfd);\n+    sdsfree(name);\n+}\n+\n+void\n+slotsmgrt_cleanup() {\n+    dictIterator *di = dictGetSafeIterator(server.slotsmgrt_cached_sockfds);\n+    dictEntry *de;\n+    while((de = dictNext(di)) != NULL) {\n+        slotsmgrt_sockfd *pfd = dictGetVal(de);\n+        if ((server.unixtime - pfd->lasttime) > 15) {\n+            redisLog(REDIS_WARNING, \"slotsmgrt: timeout target %s, lasttime = %ld, now = %ld\",\n+                   (char *)dictGetKey(de), pfd->lasttime, server.unixtime);\n+            dictDelete(server.slotsmgrt_cached_sockfds, dictGetKey(de));\n+            close(pfd->fd);\n+            zfree(pfd);\n+        }\n+    }\n+    dictReleaseIterator(di);\n+}\n+\n+static int\n+slotsmgrt(redisClient *c, sds host, sds port, slotsmgrt_sockfd *pfd, int db, int timeout, robj *keys[], robj *vals[], int n) {\n+    rio cmd;\n+    rioInitWithBuffer(&cmd, sdsempty());\n+\n+    int needauth = 0;\n+    if (pfd->authorized == 0 && server.requirepass != NULL) {\n+        needauth = 1;\n+        redisAssertWithInfo(c, NULL, rioWriteBulkCount(&cmd, '*', 2));\n+        redisAssertWithInfo(c, NULL, rioWriteBulkString(&cmd, \"AUTH\", 4));\n+        redisAssertWithInfo(c, NULL, rioWriteBulkString(&cmd, server.requirepass, strlen(server.requirepass)));\n+    }\n+\n+    int selectdb = 0;\n+    if (pfd->db != db) {\n+        selectdb = 1;\n+        redisAssertWithInfo(c, NULL, rioWriteBulkCount(&cmd, '*', 2));\n+        redisAssertWithInfo(c, NULL, rioWriteBulkString(&cmd, \"SELECT\", 6));\n+        redisAssertWithInfo(c, NULL, rioWriteBulkLongLong(&cmd, db));\n+    }\n+\n+    redisAssertWithInfo(c, NULL, rioWriteBulkCount(&cmd, '*', 1 + 3 * n));\n+    redisAssertWithInfo(c, NULL, rioWriteBulkString(&cmd, \"SLOTSRESTORE\", 12));\n+\n+    sds onekey = NULL;\n+    for (int i = 0; i < n; i ++) {\n+        robj *key = keys[i], *val = vals[i];\n+        long long ttl = 0, expireat = getExpire(c->db, key);\n+        if (expireat != -1) {\n+            ttl = expireat - mstime();\n+            if (ttl < 1) {\n+                ttl = 1;\n+            }\n+        }\n+        sds skey = key->ptr;\n+        redisAssertWithInfo(c, NULL, rioWriteBulkString(&cmd, skey, sdslen(skey)));\n+        redisAssertWithInfo(c, NULL, rioWriteBulkLongLong(&cmd, ttl));\n+        do {\n+            rio pld;\n+            createDumpPayload(&pld, val);\n+            sds buf = pld.io.buffer.ptr;\n+            redisAssertWithInfo(c, NULL, rioWriteBulkString(&cmd, buf, sdslen(buf)));\n+            sdsfree(buf);\n+        } while (0);\n+        if (onekey == NULL) {\n+            onekey = skey;\n+        }\n+    }\n+\n+    do {\n+        sds buf = cmd.io.buffer.ptr;\n+        size_t pos = 0, towrite;\n+        int nwritten = 0;\n+        while ((towrite = sdslen(buf) - pos) > 0) {\n+            towrite = (towrite > (64 * 1024) ? (64 * 1024) : towrite);\n+            nwritten = syncWrite(pfd->fd, buf + pos, towrite, timeout);\n+            if (nwritten != (signed)towrite) {\n+                redisLog(REDIS_WARNING, \"slotsmgrt: writing to target %s:%s, error '%s', \"\n+                        \"nkeys = %d, onekey = '%s', cmd.len = %ld, pos = %ld, towrite = %ld\",\n+                        host, port, server.neterr, n, onekey, sdslen(buf), pos, towrite);\n+                addReplySds(c, sdsnew(\"-IOERR error or timeout writing to target\\r\\n\"));\n+                sdsfree(buf);\n+                return -1;\n+            }\n+            pos += nwritten;\n+        }\n+        sdsfree(buf);\n+    } while (0);\n+\n+    do {\n+        char buf[1024];\n+        if (needauth) {\n+            if (syncReadLine(pfd->fd, buf, sizeof(buf), timeout) <= 0) {\n+                redisLog(REDIS_WARNING, \"slotsmgrt: auth failed, reading from target %s:%s: nkeys = %d, onekey = '%s', error = '%s'\",\n+                        host, port, n, onekey, server.neterr);\n+                addReplySds(c, sdsnew(\"-IOERR error or timeout reading from target\\r\\n\"));\n+                return -1;\n+            }\n+            if (buf[0] != '+') {\n+                redisLog(REDIS_WARNING, \"slotsmgrt: auth failed, reading from target %s:%s: nkeys = %d, onekey = '%s', response = '%s'\",\n+                        host, port, n, onekey, buf);\n+                addReplyError(c, \"error on slotsrestore, auth failed\");\n+                return -1;\n+            }\n+            pfd->authorized = 1;\n+        }\n+\n+        if (selectdb) {\n+            if (syncReadLine(pfd->fd, buf, sizeof(buf), timeout) <= 0) {\n+                redisLog(REDIS_WARNING, \"slotsmgrt: select failed, reading from target %s:%s: nkeys = %d, onekey = '%s', error = '%s'\",\n+                        host, port, n, onekey, server.neterr);\n+                addReplySds(c, sdsnew(\"-IOERR error or timeout reading from target\\r\\n\"));\n+                return -1;\n+            }\n+            if (buf[0] != '+') {\n+                redisLog(REDIS_WARNING, \"slotsmgrt: select failed, reading from target %s:%s: nkeys = %d, onekey = '%s', response = '%s'\",\n+                        host, port, n, onekey, buf);\n+                addReplyError(c, \"error on slotsrestore, select failed\");\n+                return -1;\n+            }\n+            pfd->db = db;\n+        }\n+\n+        if (syncReadLine(pfd->fd, buf, sizeof(buf), timeout) <= 0) {\n+            redisLog(REDIS_WARNING, \"slotsmgrt: migration failed, reading from target %s:%s: nkeys = %d, onekey = '%s', error = '%s'\",\n+                    host, port, n, onekey, server.neterr);\n+            addReplySds(c, sdsnew(\"-IOERR error or timeout reading from target\\r\\n\"));\n+            return -1;\n+        }\n+        if (buf[0] == '-') {\n+            redisLog(REDIS_WARNING, \"slotsmgrt: migration failed, reading from target %s:%s: nkeys = %d, onekey = '%s', response = '%s'\",\n+                    host, port, n, onekey, buf);\n+            addReplyError(c, \"error on slotsrestore, migration failed\");\n+            return -1;\n+        }\n+    } while (0);\n+\n+    pfd->lasttime = server.unixtime;\n+\n+    redisLog(REDIS_VERBOSE, \"slotsmgrt: migrate to %s:%s, nkeys = %d, onekey = '%s'\", host, port, n, onekey);\n+    return 0;\n+}\n+\n+static void\n+slotsremove(redisClient *c, robj **keys, int n, int rewrite) {\n+    for (int i = 0; i < n; i ++) {\n+        dbDelete(c->db, keys[i]);\n+        signalModifiedKey(c->db, keys[i]);\n+        server.dirty ++;\n+    }\n+    if (!rewrite) {\n+        return;\n+    }\n+    for (int i = 0; i < n; i ++) {\n+        incrRefCount(keys[i]);\n+    }\n+    for (int i = 0; i < c->argc; i ++) {\n+        decrRefCount(c->argv[i]);\n+    }\n+    zfree(c->argv);\n+    c->argc = n + 1;\n+    c->argv = zmalloc(sizeof(robj *) * c->argc);\n+    c->argv[0] = createStringObject(\"DEL\", 3);\n+    for (int i = 0; i < n; i ++) {\n+        c->argv[i + 1] = keys[i];\n+    }\n+    c->cmd = lookupCommandOrOriginal(c->argv[0]->ptr);\n+    redisAssertWithInfo(c, NULL, c->cmd != NULL);\n+}\n+\n+/* *\n+ * do migrate a key-value for slotsmgrt/slotsmgrtone commands\n+ * return value:\n+ *    -1 - error happens\n+ *   >=0 - # of success migration (0 or 1)\n+ * */\n+static int\n+slotsmgrtone_command(redisClient *c, sds host, sds port, int timeout, robj *key) {\n+    slotsmgrt_sockfd *pfd = slotsmgrt_get_sockfd(c, host, port, timeout);\n+    if (pfd == NULL) {\n+        return -1;\n+    }\n+\n+    robj *val = lookupKeyWrite(c->db, key);\n+    if (val == NULL) {\n+        return 0;\n+    }\n+    robj *keys[] = {key};\n+    robj *vals[] = {val};\n+    if (slotsmgrt(c, host, port, pfd, c->db->id, timeout, keys, vals, 1) != 0) {\n+        slotsmgrt_close_socket(host, port);\n+        return -1;\n+    }\n+    slotsremove(c, keys, 1, 1);\n+    return 1;\n+}\n+\n+/* *\n+ * slotsmgrtslot host port timeout slot\n+ * */\n+void\n+slotsmgrtslotCommand(redisClient *c) {\n+    sds host = c->argv[1]->ptr;\n+    sds port = c->argv[2]->ptr;\n+    int timeout, slot;\n+    if (parse_timeout(c, c->argv[3], &timeout) != 0) {\n+        return;\n+    }\n+    if (parse_slot(c, c->argv[4], &slot) != 0) {\n+        return;\n+    }\n+\n+    dict *d = c->db->hash_slots[slot];\n+    int succ = 0;\n+    do {\n+        const dictEntry *de = dictGetRandomKey(d);\n+        if (de == NULL) {\n+            break;\n+        }\n+        sds skey = dictGetKey(de);\n+        robj *key = createStringObject(skey, sdslen(skey));\n+        succ = slotsmgrtone_command(c, host, port, timeout, key);\n+        decrRefCount(key);\n+        if (succ < 0) {\n+            return;\n+        }\n+    } while (0);\n+    addReplyMultiBulkLen(c, 2);\n+    addReplyLongLong(c, succ);\n+    addReplyLongLong(c, dictSize(d));\n+}\n+\n+/* *\n+ * slotsmgrtone host port timeout key\n+ * */\n+void\n+slotsmgrtoneCommand(redisClient *c) {\n+    sds host = c->argv[1]->ptr;\n+    sds port = c->argv[2]->ptr;\n+    int timeout;\n+    if (parse_timeout(c, c->argv[3], &timeout) != 0) {\n+        return;\n+    }\n+\n+    robj *key = c->argv[4];\n+    int succ = slotsmgrtone_command(c, host, port, timeout, key);\n+    if (succ < 0) {\n+        return;\n+    }\n+    addReplyLongLong(c, succ);\n+}\n+\n+static void\n+slotsScanSdsKeyCallback(void *l, const dictEntry *de) {\n+    sds skey = dictGetKey(de);\n+    robj *key = createStringObject(skey, sdslen(skey));\n+    listAddNodeTail((list *)l, key);\n+}\n+\n+/* *\n+ * slotsdel slot1 [slot2 ...]\n+ * */\n+void\n+slotsdelCommand(redisClient *c) {\n+    int slots_slot[HASH_SLOTS_SIZE];\n+    int n = 0;\n+    if (c->argc <= 1) {\n+        addReplyErrorFormat(c, \"wrong number of arguments for 'slotsdel' command\");\n+        return;\n+    }\n+    int i;\n+    for (i = 1; i < c->argc; i ++) {\n+        int slot;\n+        if (parse_slot(c, c->argv[i], &slot) != 0) {\n+            return;\n+        }\n+        slots_slot[n] = slot;\n+        n ++;\n+    }\n+    for (i = 0; i < n; i ++) {\n+        dict *d = c->db->hash_slots[slots_slot[i]];\n+        int s = dictSize(d);\n+        if (s == 0) {\n+            continue;\n+        }\n+        list *l = listCreate();\n+        listSetFreeMethod(l, decrRefCountVoid);\n+        unsigned long cursor = 0;\n+        do {\n+            cursor = dictScan(d, cursor, slotsScanSdsKeyCallback, l);\n+        } while (cursor != 0);\n+        while (1) {\n+            listNode *head = listFirst(l);\n+            if (head == NULL) {\n+                break;\n+            }\n+            robj *key = listNodeValue(head);\n+            robj *keys[] = {key};\n+            slotsremove(c, keys, 1, 0);\n+            listDelNode(l, head);\n+        }\n+        listRelease(l);\n+    }\n+    addReplyMultiBulkLen(c, n);\n+    for (i = 0; i < n; i ++) {\n+        int n = slots_slot[i];\n+        int s = dictSize(c->db->hash_slots[n]);\n+        addReplyMultiBulkLen(c, 2);\n+        addReplyLongLong(c, n);\n+        addReplyLongLong(c, s);\n+    }\n+}\n+\n+/* *\n+ * slotscheck\n+ * */\n+void\n+slotscheckCommand(redisClient *c) {\n+    sds bug = NULL;\n+    int i;\n+    for (i = 0; i < HASH_SLOTS_SIZE && bug == NULL; i ++) {\n+        dict *d = c->db->hash_slots[i];\n+        if (dictSize(d) == 0) {\n+            continue;\n+        }\n+        list *l = listCreate();\n+        listSetFreeMethod(l, decrRefCountVoid);\n+        unsigned long cursor = 0;\n+        do {\n+            cursor = dictScan(d, cursor, slotsScanSdsKeyCallback, l);\n+            while (1) {\n+                listNode *head = listFirst(l);\n+                if (head == NULL) {\n+                    break;\n+                }\n+                robj *key = listNodeValue(head);\n+                if (lookupKey(c->db, key) == NULL) {\n+                    if (bug == NULL) {\n+                        bug = sdsdup(key->ptr);\n+                    }\n+                }\n+                listDelNode(l, head);\n+            }\n+        } while (cursor != 0 && bug == NULL);\n+        listRelease(l);\n+    }\n+    if (bug != NULL) {\n+        addReplyErrorFormat(c, \"step 1, miss = '%s'\", bug);\n+        sdsfree(bug);\n+        return;\n+    }\n+    do {\n+        dict *d = c->db->dict;\n+        if (dictSize(d) == 0) {\n+            break;\n+        }\n+        list *l = listCreate();\n+        listSetFreeMethod(l, decrRefCountVoid);\n+        unsigned long cursor = 0;\n+        do {\n+            cursor = dictScan(d, cursor, slotsScanSdsKeyCallback, l);\n+            while (1) {\n+                listNode *head = listFirst(l);\n+                if (head == NULL) {\n+                    break;\n+                }\n+                robj *key = listNodeValue(head);\n+                int slot = slots_num(key->ptr, NULL, NULL);\n+                if (dictFind(c->db->hash_slots[slot], key->ptr) == NULL) {\n+                    if (bug == NULL) {\n+                        bug = sdsdup(key->ptr);\n+                    }\n+                }\n+                listDelNode(l, head);\n+            }\n+        } while (cursor != 0 && bug == NULL);\n+        listRelease(l);\n+    } while (0);\n+    if (bug != NULL) {\n+        addReplyErrorFormat(c, \"step 2, miss = '%s'\", bug);\n+        sdsfree(bug);\n+        return;\n+    }\n+    zskiplistNode *node = c->db->tagged_keys->header->level[0].forward;\n+    while (node != NULL && bug == NULL) {\n+        if (lookupKey(c->db, node->obj) == NULL) {\n+            bug = sdsdup(node->obj->ptr);\n+        }\n+        node = node->level[0].forward;\n+    }\n+    if (bug != NULL) {\n+        addReplyErrorFormat(c, \"step 3, miss = '%s'\", bug);\n+        sdsfree(bug);\n+        return;\n+    }\n+    addReply(c, shared.ok);\n+}\n+\n+/* *\n+ * slotsrestore key ttl val [key ttl val ...]\n+ * */\n+void\n+slotsrestoreCommand(redisClient *c) {\n+    if (c->argc < 4 || (c->argc - 1) % 3 != 0) {\n+        addReplyErrorFormat(c, \"wrong number of arguments for 'slotsrestore' command\");\n+        return;\n+    }\n+    int n = (c->argc - 1) / 3;\n+\n+    long long *ttls = zmalloc(sizeof(long long) * n);\n+    robj **vals = zmalloc(sizeof(robj *) * n);\n+    for (int i = 0; i < n; i ++) {\n+        vals[i] = NULL;\n+    }\n+\n+    for (int i = 0; i < n; i ++) {\n+        robj *key = c->argv[i * 3 + 1];\n+        robj *ttl = c->argv[i * 3 + 2];\n+        robj *val = c->argv[i * 3 + 3];\n+        if (lookupKeyWrite(c->db, key) != NULL) {\n+            redisLog(REDIS_WARNING, \"slotsrestore: slot = %d, key = '%s' already exists\",\n+                    slots_num(key->ptr, NULL, NULL), (char *)key->ptr);\n+        }\n+        if (getLongLongFromObjectOrReply(c, ttl, &ttls[i], NULL) != REDIS_OK) {\n+            goto cleanup;\n+        } else if (ttls[i] < 0) {\n+            addReplyError(c, \"invalid ttl value, must be >= 0\");\n+            goto cleanup;\n+        }\n+        rio payload;\n+        int type;\n+        if (verifyDumpPayload(val->ptr, sdslen(val->ptr)) != REDIS_OK) {\n+            addReplyError(c, \"dump payload version or checksum are wrong\");\n+            goto cleanup;\n+        }\n+        rioInitWithBuffer(&payload, val->ptr);\n+        if (((type = rdbLoadObjectType(&payload)) == -1) ||\n+                ((vals[i] = rdbLoadObject(type, &payload)) == NULL)) {\n+            addReplyError(c, \"bad data format\");\n+            goto cleanup;\n+        }\n+    }\n+\n+    for (int i = 0; i < n; i ++) {\n+        robj *key = c->argv[i * 3 + 1];\n+        long long ttl = ttls[i];\n+        robj *val = vals[i];\n+        dbDelete(c->db, key);\n+        dbAdd(c->db, key, val);\n+        incrRefCount(val);\n+        if (ttl) {\n+            setExpire(c->db, key, mstime() + ttl);\n+        }\n+        signalModifiedKey(c->db, key);\n+        server.dirty ++;\n+    }\n+    addReply(c, shared.ok);\n+\n+cleanup:\n+    for (int i = 0; i < n; i ++) {\n+        if (vals[i] != NULL) {\n+            decrRefCount(vals[i]);\n+        }\n+    }\n+    zfree(vals);\n+    zfree(ttls);\n+}\n+\n+/* *\n+ * do migrate mutli key-value(s) for {slotsmgrt/slotsmgrtone}with tag commands\n+ * return value:\n+ *    -1 - error happens\n+ *   >=0 - # of success migration\n+ * */\n+static int\n+slotsmgrttag_command(redisClient *c, sds host, sds port, int timeout, robj *key) {\n+    uint32_t crc;\n+    int hastag;\n+    int slot = slots_num(key->ptr, &crc, &hastag);\n+    if (!hastag) {\n+        return slotsmgrtone_command(c, host, port, timeout, key);\n+    }\n+\n+    slotsmgrt_sockfd *pfd = slotsmgrt_get_sockfd(c, host, port, timeout);\n+    if (pfd == NULL) {\n+        return -1;\n+    }\n+\n+    dict *d = c->db->hash_slots[slot];\n+    if (dictSize(d) == 0) {\n+        return 0;\n+    }\n+\n+    zrangespec range;\n+    range.min = (double)crc;\n+    range.minex = 0;\n+    range.max = (double)crc;\n+    range.maxex = 0;\n+\n+    list *l = listCreate();\n+    listSetFreeMethod(l, decrRefCountVoid);\n+\n+    zskiplistNode *node = zslFirstInRange(c->db->tagged_keys, &range);\n+    while (node != NULL && node->score == (double)crc) {\n+        listAddNodeTail(l, node->obj);\n+        incrRefCount(node->obj);\n+        node = node->level[0].forward;\n+    }\n+\n+    int max = listLength(l);\n+    if (max == 0) {\n+        listRelease(l);\n+        return 0;\n+    }\n+\n+    robj **keys = zmalloc(sizeof(robj *) * max);\n+    robj **vals = zmalloc(sizeof(robj *) * max);\n+\n+    int n = 0;\n+    for (int i = 0; i < max; i ++) {\n+        listNode *head = listFirst(l);\n+        robj *key = listNodeValue(head);\n+        robj *val = lookupKeyWrite(c->db, key);\n+        if (val != NULL) {\n+            keys[n] = key;\n+            vals[n] = val;\n+            n ++;\n+            incrRefCount(key);\n+            incrRefCount(val);\n+        }\n+        listDelNode(l, head);\n+    }\n+\n+    int ret = 0;\n+    if (n != 0) {\n+        if (slotsmgrt(c, host, port, pfd, c->db->id, timeout, keys, vals, n) != 0) {\n+            slotsmgrt_close_socket(host, port);\n+            ret = -1;\n+        } else {\n+            slotsremove(c, keys, n, 1);\n+            ret = n;\n+        }\n+    }\n+\n+    listRelease(l);\n+    for (int i = 0; i < n; i ++) {\n+        decrRefCount(keys[i]);\n+        decrRefCount(vals[i]);\n+    }\n+    zfree(keys);\n+    zfree(vals);\n+    return ret;\n+}\n+\n+/* *\n+ * slotsmgrttagslot host port timeout slot\n+ * */\n+void\n+slotsmgrttagslotCommand(redisClient *c) {\n+    sds host = c->argv[1]->ptr;\n+    sds port = c->argv[2]->ptr;\n+    int timeout, slot;\n+    if (parse_timeout(c, c->argv[3], &timeout) != 0) {\n+        return;\n+    }\n+    if (parse_slot(c, c->argv[4], &slot) != 0) {\n+        return;\n+    }\n+\n+    dict *d = c->db->hash_slots[slot];\n+    int succ = 0;\n+    do {\n+        const dictEntry *de = dictGetRandomKey(d);\n+        if (de == NULL) {\n+            break;\n+        }\n+        sds skey = dictGetKey(de);\n+        robj *key = createStringObject(skey, sdslen(skey));\n+        succ = slotsmgrttag_command(c, host, port, timeout, key);\n+        decrRefCount(key);\n+        if (succ < 0) {\n+            return;\n+        }\n+    } while (0);\n+    addReplyMultiBulkLen(c, 2);\n+    addReplyLongLong(c, succ);\n+    addReplyLongLong(c, dictSize(d));\n+}\n+\n+/* *\n+ * slotsmgrttagone host port timeout key\n+ * */\n+void\n+slotsmgrttagoneCommand(redisClient *c) {\n+    sds host = c->argv[1]->ptr;\n+    sds port = c->argv[2]->ptr;\n+    int timeout;\n+    if (parse_timeout(c, c->argv[3], &timeout) != 0) {\n+        return;\n+    }\n+\n+    robj *key = c->argv[4];\n+    int succ = slotsmgrttag_command(c, host, port, timeout, key);\n+    if (succ < 0) {\n+        return;\n+    }\n+    addReplyLongLong(c, succ);\n+}\n"
  },
  {
    "path": "extern/deprecated/redis-2.8.21/0001-slotsscan.patch",
    "content": "diff --git a/extern/redis-2.8.21/src/redis.c b/extern/redis-2.8.21/src/redis.c\nindex 21e75d0..33ba3a3 100644\n--- a/extern/redis-2.8.21/src/redis.c\n+++ b/extern/redis-2.8.21/src/redis.c\n@@ -276,6 +276,7 @@ struct redisCommand redisCommandTable[] = {\n     {\"pfdebug\",pfdebugCommand,-3,\"w\",0,NULL,0,0,0,0,0},\n     {\"latency\",latencyCommand,-2,\"arslt\",0,NULL,0,0,0,0,0},\n     {\"slotsinfo\",slotsinfoCommand,-1,\"rF\",0,NULL,0,0,0,0,0},\n+    {\"slotsscan\",slotsscanCommand,-3,\"rR\",0,NULL,0,0,0,0,0},\n     {\"slotsdel\",slotsdelCommand,-2,\"w\",0,NULL,1,-1,1,0,0},\n     {\"slotsmgrtslot\",slotsmgrtslotCommand,5,\"aw\",0,NULL,0,0,0,0,0},\n     {\"slotsmgrtone\",slotsmgrtoneCommand,5,\"aw\",0,NULL,0,0,0,0,0},\ndiff --git a/extern/redis-2.8.21/src/redis.h b/extern/redis-2.8.21/src/redis.h\nindex a15910a..8a0c13d 100644\n--- a/extern/redis-2.8.21/src/redis.h\n+++ b/extern/redis-2.8.21/src/redis.h\n@@ -1434,6 +1434,7 @@ void pfmergeCommand(redisClient *c);\n void pfdebugCommand(redisClient *c);\n void latencyCommand(redisClient *c);\n void slotsinfoCommand(redisClient *c);\n+void slotsscanCommand(redisClient *c);\n void slotsdelCommand(redisClient *c);\n void slotsmgrtslotCommand(redisClient *c);\n void slotsmgrtoneCommand(redisClient *c);\ndiff --git a/extern/redis-2.8.21/src/slots.c b/extern/redis-2.8.21/src/slots.c\nindex 24df9ae..daa7be2 100644\n--- a/extern/redis-2.8.21/src/slots.c\n+++ b/extern/redis-2.8.21/src/slots.c\n@@ -47,8 +47,13 @@ parse_int(redisClient *c, robj *obj, int *p) {\n     if (getLongFromObjectOrReply(c, obj, &v, NULL) != REDIS_OK) {\n         return -1;\n     }\n-    *p = v;\n-    return 0;\n+    if (v < INT_MIN || v > INT_MAX) {\n+        addReplyError(c, \"value is out of range\");\n+        return -1;\n+    } else {\n+        *p = v;\n+        return 0;\n+    }\n }\n \n static int\n@@ -815,3 +820,63 @@ slotsmgrttagoneCommand(redisClient *c) {\n     }\n     addReplyLongLong(c, succ);\n }\n+\n+/* *\n+ * slotsscan slotnum cursor [COUNT count]\n+ * */\n+void\n+slotsscanCommand(redisClient *c) {\n+    int slot;\n+    if (parse_slot(c, c->argv[1], &slot) != 0) {\n+        return;\n+    }\n+    unsigned long cursor;\n+    if (parseScanCursorOrReply(c, c->argv[2], &cursor) == REDIS_ERR) {\n+        return;\n+    }\n+    unsigned long count = 10;\n+    if (c->argc != 3 && c->argc != 5) {\n+        addReplyErrorFormat(c, \"wrong number of arguments for 'slotsscan' command\");\n+        return;\n+    }\n+    if (c->argc == 5) {\n+        if (strcasecmp(c->argv[3]->ptr, \"count\") != 0) {\n+            addReply(c, shared.syntaxerr);\n+            return;\n+        }\n+        int v;\n+        if (parse_int(c, c->argv[4], &v) != 0) {\n+            return;\n+        }\n+        if (v < 1) {\n+            addReply(c, shared.syntaxerr);\n+            return;\n+        }\n+        count = v;\n+    }\n+    dict *d = c->db->hash_slots[slot];\n+    list *l = listCreate();\n+    listSetFreeMethod(l, decrRefCountVoid);\n+\n+    long loops = count * 10;\n+    do {\n+        cursor = dictScan(d, cursor, slotsScanSdsKeyCallback, l);\n+        loops --;\n+    } while (cursor != 0 && loops > 0 && listLength(l) < count);\n+\n+    addReplyMultiBulkLen(c, 2);\n+    addReplyBulkLongLong(c, cursor);\n+\n+    addReplyMultiBulkLen(c, listLength(l));\n+    while (1) {\n+        listNode *head = listFirst(l);\n+        if (head == NULL) {\n+            break;\n+        }\n+        robj *key = listNodeValue(head);\n+        addReplyBulk(c, key);\n+        listDelNode(l, head);\n+    }\n+\n+    listRelease(l);\n+}\n"
  },
  {
    "path": "extern/deprecated/redis-2.8.21/0002-rehash.patch",
    "content": "diff --git a/extern/redis-2.8.21/src/redis.c b/extern/redis-2.8.21/src/redis.c\nindex 33ba3a3..f035bb2 100644\n--- a/extern/redis-2.8.21/src/redis.c\n+++ b/extern/redis-2.8.21/src/redis.c\n@@ -659,10 +659,16 @@ int incrementallyRehash(int dbid) {\n     /* Keys dictionary */\n     if (dictIsRehashing(server.db[dbid].dict)) {\n         dictRehashMilliseconds(server.db[dbid].dict,1);\n+\n+        long long start = timeInMilliseconds();\n         for (int i = 0; i < HASH_SLOTS_SIZE; i ++) {\n-            dict *d = server.db[dbid].hash_slots[i];\n+            int idx = ((i + start) & HASH_SLOTS_MASK);\n+            dict *d = server.db[dbid].hash_slots[idx];\n             if (dictIsRehashing(d)) {\n                 dictRehashMilliseconds(d, 1);\n+                if (timeInMilliseconds() != start) {\n+                    break;\n+                }\n             }\n         }\n         return 1; /* already used our millisecond for this loop... */\ndiff --git a/extern/redis-2.8.21/src/redis.h b/extern/redis-2.8.21/src/redis.h\nindex 8a0c13d..8971143 100644\n--- a/extern/redis-2.8.21/src/redis.h\n+++ b/extern/redis-2.8.21/src/redis.h\n@@ -424,6 +424,8 @@ typedef struct redisObject {\n void crc32_init();\n uint32_t crc32_checksum(const char *buf, int len);\n \n+long long timeInMilliseconds(void);\n+\n #define HASH_SLOTS_MASK 0x000003ff\n #define HASH_SLOTS_SIZE (HASH_SLOTS_MASK + 1)\n \n"
  },
  {
    "path": "extern/deprecated/redis-2.8.21/BUGS",
    "content": "Please check https://github.com/antirez/redis/issues\n"
  },
  {
    "path": "extern/deprecated/redis-2.8.21/CONTRIBUTING",
    "content": "Note: by contributing code to the Redis project in any form, including sending\na pull request via Github, a code fragment or patch via private email or\npublic discussion groups, you agree to release your code under the terms\nof the BSD license that you can find in the COPYING file included in the Redis\nsource distribution. You will include BSD license in the COPYING file within\neach source file that you contribute.\n\n# IMPORTANT: HOW TO USE REDIS GITHUB ISSUES\n\n* Github issues SHOULD ONLY BE USED to report bugs, and for DETAILED feature\n  requests. Everything else belongs to the Redis Google Group.\n\n  PLEASE DO NOT POST GENERAL QUESTIONS that are not about bugs or suspected\n  bugs in the Github issues system. We'll be very happy to help you and provide\n  all the support in the Redis Google Group.\n\n  Redis Google Group address:\n  \n      https://groups.google.com/forum/?fromgroups#!forum/redis-db\n\n# How to provide a patch for a new feature\n\n1. Drop a message to the Redis Google Group with a proposal of semantics/API.\n\n2. If in step 1 you get an acknowledge from the project leaders, use the\n   following procedure to submit a patch:\n\n    a. Fork Redis on github ( http://help.github.com/fork-a-repo/ )\n    b. Create a topic branch (git checkout -b my_branch)\n    c. Push to your branch (git push origin my_branch)\n    d. Initiate a pull request on github ( http://help.github.com/send-pull-requests/ )\n    e. Done :)\n\nThanks!\n"
  },
  {
    "path": "extern/deprecated/redis-2.8.21/COPYING",
    "content": "Copyright (c) 2006-2015, Salvatore Sanfilippo\nAll rights reserved.\n\nRedistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:\n\n    * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.\n    * 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.\n    * Neither the name of Redis nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.\n\nTHIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT OWNER 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.\n"
  },
  {
    "path": "extern/deprecated/redis-2.8.21/INSTALL",
    "content": "See README\n"
  },
  {
    "path": "extern/deprecated/redis-2.8.21/MANIFESTO",
    "content": "[Note: this is the Redis manifesto, for general information about\n       installing and running Redis read the README file instead.]\n\nRedis Manifesto\n===============\n\n1 - A DSL for Abstract Data Types. Redis is a DSL (Domain Specific Language)\n    that manipulates abstract data types and implemented as a TCP daemon.\n    Commands manipulate a key space where keys are binary-safe strings and\n    values are different kinds of abstract data types. Every data type\n    represents an abstract version of a fundamental data structure. For instance\n    Redis Lists are an abstract representation of linked lists. In Redis, the\n    essence of a data type isn't just the kind of operations that the data types\n    support, but also the space and time complexity of the data type and the\n    operations performed upon it.\n\n2 - Memory storage is #1. The Redis data set, composed of defined key-value\n    pairs, is primarily stored in the computer's memory. The amount of memory in\n    all kinds of computers, including entry-level servers, is increasing\n    significantly each year. Memory is fast, and allows Redis to have very\n    predictable performance. Datasets composed of 10k or 40 millions keys will\n    perform similarly. Complex data types like Redis Sorted Sets are easy to\n    implement and manipulate in memory with good performance, making Redis very\n    simple. Redis will continue to explore alternative options (where data can\n    be optionally stored on disk, say) but the main goal of the project remains\n    the development of an in-memory database.\n\n3 - Fundamental data structures for a fundamental API. The Redis API is a direct\n    consequence of fundamental data structures. APIs can often be arbitrary but\n    not an API that resembles the nature of fundamental data structures. If we\n    ever meet intelligent life forms from another part of the universe, they'll\n    likely know, understand and recognize the same basic data structures we have\n    in our computer science books. Redis will avoid intermediate layers in API,\n    so that the complexity is obvious and more complex operations can be\n    performed as the sum of the basic operations.\n\n4 - Code is like a poem; it's not just something we write to reach some\n    practical result. Sometimes people that are far from the Redis philosophy\n    suggest using other code written by other authors (frequently in other\n    languages) in order to implement something Redis currently lacks. But to us\n    this is like if Shakespeare decided to end Enrico IV using the Paradiso from\n    the Divina Commedia. Is using any external code a bad idea? Not at all. Like\n    in \"One Thousand and One Nights\" smaller self contained stories are embedded\n    in a bigger story, we'll be happy to use beautiful self contained libraries\n    when needed. At the same time, when writing the Redis story we're trying to\n    write smaller stories that will fit in to other code.\n\n5 - We're against complexity. We believe designing systems is a fight against\n    complexity. We'll accept to fight the complexity when it's worthwhile but\n    we'll try hard to recognize when a small feature is not worth 1000s of lines\n    of code. Most of the time the best way to fight complexity is by not\n    creating it at all.\n\n6 - Two levels of API. The Redis API has two levels: 1) a subset of the API fits\n    naturally into a distributed version of Redis and 2) a more complex API that\n    supports multi-key operations. Both are useful if used judiciously but\n    there's no way to make the more complex multi-keys API distributed in an\n    opaque way without violating our other principles. We don't want to provide\n    the illusion of something that will work magically when actually it can't in\n    all cases. Instead we'll provide commands to quickly migrate keys from one\n    instance to another to perform multi-key operations and expose the tradeoffs\n    to the user.\n\n7 - We optimize for joy. We believe writing code is a lot of hard work, and the\n    only way it can be worth is by enjoying it. When there is no longer joy in\n    writing code, the best thing to do is stop. To prevent this, we'll avoid\n    taking paths that will make Redis less of a joy to develop.\n"
  },
  {
    "path": "extern/deprecated/redis-2.8.21/Makefile",
    "content": "# Top level makefile, the real shit is at src/Makefile\n\ndefault: all\n\n.DEFAULT:\n\tcd src && $(MAKE) $@\n\ninstall:\n\tcd src && $(MAKE) $@\n\n.PHONY: install\n"
  },
  {
    "path": "extern/deprecated/redis-2.8.21/README",
    "content": "Where to find complete Redis documentation?\n-------------------------------------------\n\nThis README is just a fast \"quick start\" document. You can find more detailed\ndocumentation at http://redis.io\n\nBuilding Redis\n--------------\n\nRedis can be compiled and used on Linux, OSX, OpenBSD, NetBSD, FreeBSD.\nWe support big endian and little endian architectures.\n\nIt may compile on Solaris derived systems (for instance SmartOS) but our\nsupport for this platform is \"best effort\" and Redis is not guaranteed to\nwork as well as in Linux, OSX, and *BSD there.\n\nIt is as simple as:\n\n    % make\n\nYou can run a 32 bit Redis binary using:\n\n    % make 32bit\n\nAfter building Redis is a good idea to test it, using:\n\n    % make test\n\nFixing build problems with dependencies or cached build options\n—--------\nRedis has some dependencies which are included into the \"deps\" directory.\n\"make\" does not rebuild dependencies automatically, even if something in the\nsource code of dependencies is changes.\n\nWhen you update the source code with `git pull` or when code inside the\ndependencies tree is modified in any other way, make sure to use the following\ncommand in order to really clean everything and rebuild from scratch:\n\n    make distclean\n\nThis will clean: jemalloc, lua, hiredis, linenoise.\n\nAlso if you force certain build options like 32bit target, no C compiler\noptimizations (for debugging purposes), and other similar build time options,\nthose options are cached indefinitely until you issue a \"make distclean\"\ncommand.\n\nFixing problems building 32 bit binaries\n---------\n\nIf after building Redis with a 32 bit target you need to rebuild it\nwith a 64 bit target, or the other way around, you need to perform a\n\"make distclean\" in the root directory of the Redis distribution.\n\nIn case of build errors when trying to build a 32 bit binary of Redis, try\nthe following steps:\n\n* Install the packages libc6-dev-i386 (also try g++-multilib).\n* Try using the following command line instead of \"make 32bit\":\n\n    make CFLAGS=\"-m32 -march=native\" LDFLAGS=\"-m32\"\n\nAllocator\n---------\n\nSelecting a non-default memory allocator when building Redis is done by setting\nthe `MALLOC` environment variable. Redis is compiled and linked against libc\nmalloc by default, with the exception of jemalloc being the default on Linux\nsystems. This default was picked because jemalloc has proven to have fewer\nfragmentation problems than libc malloc.\n\nTo force compiling against libc malloc, use:\n\n    % make MALLOC=libc\n\nTo compile against jemalloc on Mac OS X systems, use:\n\n    % make MALLOC=jemalloc\n\nVerbose build\n-------------\n\nRedis will build with a user friendly colorized output by default.\nIf you want to see a more verbose output use the following:\n\n    % make V=1\n\nRunning Redis\n-------------\n\nTo run Redis with the default configuration just type:\n\n    % cd src\n    % ./redis-server\n    \nIf you want to provide your redis.conf, you have to run it using an additional\nparameter (the path of the configuration file):\n\n    % cd src\n    % ./redis-server /path/to/redis.conf\n\nIt is possible to alter the Redis configuration passing parameters directly\nas options using the command line. Examples:\n\n    % ./redis-server --port 9999 --slaveof 127.0.0.1 6379\n    % ./redis-server /etc/redis/6379.conf --loglevel debug\n\nAll the options in redis.conf are also supported as options using the command\nline, with exactly the same name.\n\nPlaying with Redis\n------------------\n\nYou can use redis-cli to play with Redis. Start a redis-server instance,\nthen in another terminal try the following:\n\n    % cd src\n    % ./redis-cli\n    redis> ping\n    PONG\n    redis> set foo bar\n    OK\n    redis> get foo\n    \"bar\"\n    redis> incr mycounter\n    (integer) 1\n    redis> incr mycounter\n    (integer) 2\n    redis> \n\nYou can find the list of all the available commands here:\n\n    http://redis.io/commands\n\nInstalling Redis\n-----------------\n\nIn order to install Redis binaries into /usr/local/bin just use:\n\n    % make install\n\nYou can use \"make PREFIX=/some/other/directory install\" if you wish to use a\ndifferent destination.\n\nMake install will just install binaries in your system, but will not configure\ninit scripts and configuration files in the appropriate place. This is not\nneeded if you want just to play a bit with Redis, but if you are installing\nit the proper way for a production system, we have a script doing this\nfor Ubuntu and Debian systems:\n\n    % cd utils\n    % ./install_server.sh\n\nThe script will ask you a few questions and will setup everything you need\nto run Redis properly as a background daemon that will start again on\nsystem reboots.\n\nYou'll be able to stop and start Redis using the script named\n/etc/init.d/redis_<portnumber>, for instance /etc/init.d/redis_6379.\n\nCode contributions\n---\n\nNote: by contributing code to the Redis project in any form, including sending\na pull request via Github, a code fragment or patch via private email or\npublic discussion groups, you agree to release your code under the terms\nof the BSD license that you can find in the COPYING file included in the Redis\nsource distribution.\n\nPlease see the CONTRIBUTING file in this source distribution for more\ninformation.\n\nEnjoy!\n"
  },
  {
    "path": "extern/deprecated/redis-2.8.21/deps/Makefile",
    "content": "# Redis dependency Makefile\n\nuname_S:= $(shell sh -c 'uname -s 2>/dev/null || echo not')\n\nCCCOLOR=\"\\033[34m\"\nLINKCOLOR=\"\\033[34;1m\"\nSRCCOLOR=\"\\033[33m\"\nBINCOLOR=\"\\033[37;1m\"\nMAKECOLOR=\"\\033[32;1m\"\nENDCOLOR=\"\\033[0m\"\n\ndefault:\n\t@echo \"Explicit target required\"\n\n.PHONY: default\n\n# Prerequisites target\n.make-prerequisites:\n\t@touch $@\n\n# Clean everything when CFLAGS is different\nifneq ($(shell sh -c '[ -f .make-cflags ] && cat .make-cflags || echo none'), $(CFLAGS))\n.make-cflags: distclean\n\t-(echo \"$(CFLAGS)\" > .make-cflags)\n.make-prerequisites: .make-cflags\nendif\n\n# Clean everything when LDFLAGS is different\nifneq ($(shell sh -c '[ -f .make-ldflags ] && cat .make-ldflags || echo none'), $(LDFLAGS))\n.make-ldflags: distclean\n\t-(echo \"$(LDFLAGS)\" > .make-ldflags)\n.make-prerequisites: .make-ldflags\nendif\n\ndistclean:\n\t-(cd hiredis && $(MAKE) clean) > /dev/null || true\n\t-(cd linenoise && $(MAKE) clean) > /dev/null || true\n\t-(cd lua && $(MAKE) clean) > /dev/null || true\n\t-(cd jemalloc && [ -f Makefile ] && $(MAKE) distclean) > /dev/null || true\n\t-(rm -f .make-*)\n\n.PHONY: distclean\n\nhiredis: .make-prerequisites\n\t@printf '%b %b\\n' $(MAKECOLOR)MAKE$(ENDCOLOR) $(BINCOLOR)$@$(ENDCOLOR)\n\tcd hiredis && $(MAKE) static\n\n.PHONY: hiredis\n\nlinenoise: .make-prerequisites\n\t@printf '%b %b\\n' $(MAKECOLOR)MAKE$(ENDCOLOR) $(BINCOLOR)$@$(ENDCOLOR)\n\tcd linenoise && $(MAKE)\n\n.PHONY: linenoise\n\nifeq ($(uname_S),SunOS)\n\t# Make isinf() available\n\tLUA_CFLAGS= -D__C99FEATURES__=1\nendif\n\nLUA_CFLAGS+= -O2 -Wall -DLUA_ANSI -DENABLE_CJSON_GLOBAL $(CFLAGS)\nLUA_LDFLAGS+= $(LDFLAGS)\n# lua's Makefile defines AR=\"ar rcu\", which is unusual, and makes it more\n# challenging to cross-compile lua (and redis).  These defines make it easier\n# to fit redis into cross-compilation environments, which typically set AR.\nAR=ar\nARFLAGS=rcu\n\nlua: .make-prerequisites\n\t@printf '%b %b\\n' $(MAKECOLOR)MAKE$(ENDCOLOR) $(BINCOLOR)$@$(ENDCOLOR)\n\tcd lua/src && $(MAKE) all CFLAGS=\"$(LUA_CFLAGS)\" MYLDFLAGS=\"$(LUA_LDFLAGS)\" AR=\"$(AR) $(ARFLAGS)\"\n\n.PHONY: lua\n\nJEMALLOC_CFLAGS= -std=gnu99 -Wall -pipe -g3 -O3 -funroll-loops $(CFLAGS)\nJEMALLOC_LDFLAGS= $(LDFLAGS)\n\njemalloc: .make-prerequisites\n\t@printf '%b %b\\n' $(MAKECOLOR)MAKE$(ENDCOLOR) $(BINCOLOR)$@$(ENDCOLOR)\n\tcd jemalloc && ./configure --with-jemalloc-prefix=je_ --enable-cc-silence CFLAGS=\"$(JEMALLOC_CFLAGS)\" LDFLAGS=\"$(JEMALLOC_LDFLAGS)\"\n\tcd jemalloc && $(MAKE) CFLAGS=\"$(JEMALLOC_CFLAGS)\" LDFLAGS=\"$(JEMALLOC_LDFLAGS)\" lib/libjemalloc.a\n\n.PHONY: jemalloc\n"
  },
  {
    "path": "extern/deprecated/redis-2.8.21/deps/hiredis/.gitignore",
    "content": "/hiredis-test\n/examples/hiredis-example*\n/*.o\n/*.so\n/*.dylib\n/*.a\n"
  },
  {
    "path": "extern/deprecated/redis-2.8.21/deps/hiredis/.travis.yml",
    "content": "language: c\ncompiler:\n  - gcc\n  - clang\n\nscript: make && make check\n"
  },
  {
    "path": "extern/deprecated/redis-2.8.21/deps/hiredis/CHANGELOG.md",
    "content": "### 0.11.0\n\n* Increase the maximum multi-bulk reply depth to 7.\n\n* Increase the read buffer size from 2k to 16k.\n\n* Use poll(2) instead of select(2) to support large fds (>= 1024).\n\n### 0.10.1\n\n* Makefile overhaul. Important to check out if you override one or more\n  variables using environment variables or via arguments to the \"make\" tool.\n\n* Issue #45: Fix potential memory leak for a multi bulk reply with 0 elements\n  being created by the default reply object functions.\n\n* Issue #43: Don't crash in an asynchronous context when Redis returns an error\n  reply after the connection has been made (this happens when the maximum\n  number of connections is reached).\n\n### 0.10.0\n\n* See commit log.\n\n"
  },
  {
    "path": "extern/deprecated/redis-2.8.21/deps/hiredis/COPYING",
    "content": "Copyright (c) 2009-2011, Salvatore Sanfilippo <antirez at gmail dot com>\nCopyright (c) 2010-2011, Pieter Noordhuis <pcnoordhuis at gmail dot com>\n\nAll rights reserved.\n\nRedistribution and use in source and binary forms, with or without\nmodification, are permitted provided that the following conditions are met:\n\n* Redistributions of source code must retain the above copyright notice,\n  this list of conditions and the following disclaimer.\n\n* Redistributions in binary form must reproduce the above copyright notice,\n  this list of conditions and the following disclaimer in the documentation\n  and/or other materials provided with the distribution.\n\n* Neither the name of Redis nor the names of its contributors may be used\n  to endorse or promote products derived from this software without specific\n  prior written permission.\n\nTHIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND\nANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\nWARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\nDISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR\nANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\nLOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON\nANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\nSOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n"
  },
  {
    "path": "extern/deprecated/redis-2.8.21/deps/hiredis/Makefile",
    "content": "# Hiredis Makefile\n# Copyright (C) 2010-2011 Salvatore Sanfilippo <antirez at gmail dot com>\n# Copyright (C) 2010-2011 Pieter Noordhuis <pcnoordhuis at gmail dot com>\n# This file is released under the BSD license, see the COPYING file\n\nOBJ=net.o hiredis.o sds.o async.o\nEXAMPLES=hiredis-example hiredis-example-libevent hiredis-example-libev\nTESTS=hiredis-test\nLIBNAME=libhiredis\n\nHIREDIS_MAJOR=0\nHIREDIS_MINOR=11\n\n# redis-server configuration used for testing\nREDIS_PORT=56379\nREDIS_SERVER=redis-server\ndefine REDIS_TEST_CONFIG\n\tdaemonize yes\n\tpidfile /tmp/hiredis-test-redis.pid\n\tport $(REDIS_PORT)\n\tbind 127.0.0.1\n\tunixsocket /tmp/hiredis-test-redis.sock\nendef\nexport REDIS_TEST_CONFIG\n\n# Fallback to gcc when $CC is not in $PATH.\nCC:=$(shell sh -c 'type $(CC) >/dev/null 2>/dev/null && echo $(CC) || echo gcc')\nOPTIMIZATION?=-O3\nWARNINGS=-Wall -W -Wstrict-prototypes -Wwrite-strings\nDEBUG?= -g -ggdb\nREAL_CFLAGS=$(OPTIMIZATION) -fPIC $(CFLAGS) $(WARNINGS) $(DEBUG) $(ARCH)\nREAL_LDFLAGS=$(LDFLAGS) $(ARCH)\n\nDYLIBSUFFIX=so\nSTLIBSUFFIX=a\nDYLIB_MINOR_NAME=$(LIBNAME).$(DYLIBSUFFIX).$(HIREDIS_MAJOR).$(HIREDIS_MINOR)\nDYLIB_MAJOR_NAME=$(LIBNAME).$(DYLIBSUFFIX).$(HIREDIS_MAJOR)\nDYLIBNAME=$(LIBNAME).$(DYLIBSUFFIX)\nDYLIB_MAKE_CMD=$(CC) -shared -Wl,-soname,$(DYLIB_MINOR_NAME) -o $(DYLIBNAME) $(LDFLAGS)\nSTLIBNAME=$(LIBNAME).$(STLIBSUFFIX)\nSTLIB_MAKE_CMD=ar rcs $(STLIBNAME)\n\n# Platform-specific overrides\nuname_S := $(shell sh -c 'uname -s 2>/dev/null || echo not')\nifeq ($(uname_S),SunOS)\n  REAL_LDFLAGS+= -ldl -lnsl -lsocket\n  DYLIB_MAKE_CMD=$(CC) -G -o $(DYLIBNAME) -h $(DYLIB_MINOR_NAME) $(LDFLAGS)\n  INSTALL= cp -r\nendif\nifeq ($(uname_S),Darwin)\n  DYLIBSUFFIX=dylib\n  DYLIB_MINOR_NAME=$(LIBNAME).$(HIREDIS_MAJOR).$(HIREDIS_MINOR).$(DYLIBSUFFIX)\n  DYLIB_MAJOR_NAME=$(LIBNAME).$(HIREDIS_MAJOR).$(DYLIBSUFFIX)\n  DYLIB_MAKE_CMD=$(CC) -shared -Wl,-install_name,$(DYLIB_MINOR_NAME) -o $(DYLIBNAME) $(LDFLAGS)\nendif\n\nall: $(DYLIBNAME)\n\n# Deps (use make dep to generate this)\nnet.o: net.c fmacros.h net.h hiredis.h\nasync.o: async.c async.h hiredis.h sds.h dict.c dict.h\nhiredis.o: hiredis.c fmacros.h hiredis.h net.h sds.h\nsds.o: sds.c sds.h\ntest.o: test.c hiredis.h\n\n$(DYLIBNAME): $(OBJ)\n\t$(DYLIB_MAKE_CMD) $(OBJ)\n\n$(STLIBNAME): $(OBJ)\n\t$(STLIB_MAKE_CMD) $(OBJ)\n\ndynamic: $(DYLIBNAME)\nstatic: $(STLIBNAME)\n\n# Binaries:\nhiredis-example-libevent: examples/example-libevent.c adapters/libevent.h $(STLIBNAME)\n\t$(CC) -o examples/$@ $(REAL_CFLAGS) $(REAL_LDFLAGS) -I. $< -levent $(STLIBNAME)\n\nhiredis-example-libev: examples/example-libev.c adapters/libev.h $(STLIBNAME)\n\t$(CC) -o examples/$@ $(REAL_CFLAGS) $(REAL_LDFLAGS) -I. $< -lev $(STLIBNAME)\n\nifndef AE_DIR\nhiredis-example-ae:\n\t@echo \"Please specify AE_DIR (e.g. <redis repository>/src)\"\n\t@false\nelse\nhiredis-example-ae: examples/example-ae.c adapters/ae.h $(STLIBNAME)\n\t$(CC) -o examples/$@ $(REAL_CFLAGS) $(REAL_LDFLAGS) -I. -I$(AE_DIR) $< $(AE_DIR)/ae.o $(AE_DIR)/zmalloc.o $(AE_DIR)/../deps/jemalloc/lib/libjemalloc.a -pthread $(STLIBNAME)\nendif\n\nifndef LIBUV_DIR\nhiredis-example-libuv:\n\t@echo \"Please specify LIBUV_DIR (e.g. ../libuv/)\"\n\t@false\nelse\nhiredis-example-libuv: examples/example-libuv.c adapters/libuv.h $(STLIBNAME)\n\t$(CC) -o examples/$@ $(REAL_CFLAGS) $(REAL_LDFLAGS) -I. -I$(LIBUV_DIR)/include $< $(LIBUV_DIR)/.libs/libuv.a -lpthread $(STLIBNAME)\nendif\n\nhiredis-example: examples/example.c $(STLIBNAME)\n\t$(CC) -o examples/$@ $(REAL_CFLAGS) $(REAL_LDFLAGS) -I. $< $(STLIBNAME)\n\nexamples: $(EXAMPLES)\n\nhiredis-test: test.o $(STLIBNAME)\n\t$(CC) -o $@ $(REAL_LDFLAGS) $< $(STLIBNAME)\n\ntest: hiredis-test\n\t./hiredis-test\n\ncheck: hiredis-test\n\t@echo \"$$REDIS_TEST_CONFIG\" | $(REDIS_SERVER) -\n\t./hiredis-test -h 127.0.0.1 -p $(REDIS_PORT) -s /tmp/hiredis-test-redis.sock || \\\n\t\t\t( kill `cat /tmp/hiredis-test-redis.pid` && false )\n\tkill `cat /tmp/hiredis-test-redis.pid`\n\n.c.o:\n\t$(CC) -std=c99 -pedantic -c $(REAL_CFLAGS) $<\n\nclean:\n\trm -rf $(DYLIBNAME) $(STLIBNAME) $(TESTS) examples/hiredis-example* *.o *.gcda *.gcno *.gcov\n\ndep:\n\t$(CC) -MM *.c\n\n# Installation related variables and target\nPREFIX?=/usr/local\nINSTALL_INCLUDE_PATH= $(PREFIX)/include/hiredis\nINSTALL_LIBRARY_PATH= $(PREFIX)/lib\n\nifeq ($(uname_S),SunOS)\n  INSTALL?= cp -r\nendif\n\nINSTALL?= cp -a\n\ninstall: $(DYLIBNAME) $(STLIBNAME)\n\tmkdir -p $(INSTALL_INCLUDE_PATH) $(INSTALL_LIBRARY_PATH)\n\t$(INSTALL) hiredis.h async.h adapters $(INSTALL_INCLUDE_PATH)\n\t$(INSTALL) $(DYLIBNAME) $(INSTALL_LIBRARY_PATH)/$(DYLIB_MINOR_NAME)\n\tcd $(INSTALL_LIBRARY_PATH) && ln -sf $(DYLIB_MINOR_NAME) $(DYLIB_MAJOR_NAME)\n\tcd $(INSTALL_LIBRARY_PATH) && ln -sf $(DYLIB_MAJOR_NAME) $(DYLIBNAME)\n\t$(INSTALL) $(STLIBNAME) $(INSTALL_LIBRARY_PATH)\n\n32bit:\n\t@echo \"\"\n\t@echo \"WARNING: if this fails under Linux you probably need to install libc6-dev-i386\"\n\t@echo \"\"\n\t$(MAKE) CFLAGS=\"-m32\" LDFLAGS=\"-m32\"\n\ngprof:\n\t$(MAKE) CFLAGS=\"-pg\" LDFLAGS=\"-pg\"\n\ngcov:\n\t$(MAKE) CFLAGS=\"-fprofile-arcs -ftest-coverage\" LDFLAGS=\"-fprofile-arcs\"\n\ncoverage: gcov\n\tmake check\n\tmkdir -p tmp/lcov\n\tlcov -d . -c -o tmp/lcov/hiredis.info\n\tgenhtml --legend -o tmp/lcov/report tmp/lcov/hiredis.info\n\nnoopt:\n\t$(MAKE) OPTIMIZATION=\"\"\n\n.PHONY: all test check clean dep install 32bit gprof gcov noopt\n"
  },
  {
    "path": "extern/deprecated/redis-2.8.21/deps/hiredis/README.md",
    "content": "[![Build Status](https://travis-ci.org/redis/hiredis.png)](https://travis-ci.org/redis/hiredis)\n\n# HIREDIS\n\nHiredis is a minimalistic C client library for the [Redis](http://redis.io/) database.\n\nIt is minimalistic because it just adds minimal support for the protocol, but\nat the same time it uses an high level printf-alike API in order to make it\nmuch higher level than otherwise suggested by its minimal code base and the\nlack of explicit bindings for every Redis command.\n\nApart from supporting sending commands and receiving replies, it comes with\na reply parser that is decoupled from the I/O layer. It\nis a stream parser designed for easy reusability, which can for instance be used\nin higher level language bindings for efficient reply parsing.\n\nHiredis only supports the binary-safe Redis protocol, so you can use it with any\nRedis version >= 1.2.0.\n\nThe library comes with multiple APIs. There is the\n*synchronous API*, the *asynchronous API* and the *reply parsing API*.\n\n## UPGRADING\n\nVersion 0.9.0 is a major overhaul of hiredis in every aspect. However, upgrading existing\ncode using hiredis should not be a big pain. The key thing to keep in mind when\nupgrading is that hiredis >= 0.9.0 uses a `redisContext*` to keep state, in contrast to\nthe stateless 0.0.1 that only has a file descriptor to work with.\n\n## Synchronous API\n\nTo consume the synchronous API, there are only a few function calls that need to be introduced:\n\n    redisContext *redisConnect(const char *ip, int port);\n    void *redisCommand(redisContext *c, const char *format, ...);\n    void freeReplyObject(void *reply);\n\n### Connecting\n\nThe function `redisConnect` is used to create a so-called `redisContext`. The\ncontext is where Hiredis holds state for a connection. The `redisContext`\nstruct has an integer `err` field that is non-zero when an the connection is in\nan error state. The field `errstr` will contain a string with a description of\nthe error. More information on errors can be found in the **Errors** section.\nAfter trying to connect to Redis using `redisConnect` you should\ncheck the `err` field to see if establishing the connection was successful:\n\n    redisContext *c = redisConnect(\"127.0.0.1\", 6379);\n    if (c != NULL && c->err) {\n        printf(\"Error: %s\\n\", c->errstr);\n        // handle error\n    }\n\n### Sending commands\n\nThere are several ways to issue commands to Redis. The first that will be introduced is\n`redisCommand`. This function takes a format similar to printf. In the simplest form,\nit is used like this:\n\n    reply = redisCommand(context, \"SET foo bar\");\n\nThe specifier `%s` interpolates a string in the command, and uses `strlen` to\ndetermine the length of the string:\n\n    reply = redisCommand(context, \"SET foo %s\", value);\n\nWhen you need to pass binary safe strings in a command, the `%b` specifier can be\nused. Together with a pointer to the string, it requires a `size_t` length argument\nof the string:\n\n    reply = redisCommand(context, \"SET foo %b\", value, (size_t) valuelen);\n\nInternally, Hiredis splits the command in different arguments and will\nconvert it to the protocol used to communicate with Redis.\nOne or more spaces separates arguments, so you can use the specifiers\nanywhere in an argument:\n\n    reply = redisCommand(context, \"SET key:%s %s\", myid, value);\n\n### Using replies\n\nThe return value of `redisCommand` holds a reply when the command was\nsuccessfully executed. When an error occurs, the return value is `NULL` and\nthe `err` field in the context will be set (see section on **Errors**).\nOnce an error is returned the context cannot be reused and you should set up\na new connection.\n\nThe standard replies that `redisCommand` are of the type `redisReply`. The\n`type` field in the `redisReply` should be used to test what kind of reply\nwas received:\n\n* **`REDIS_REPLY_STATUS`**:\n    * The command replied with a status reply. The status string can be accessed using `reply->str`.\n      The length of this string can be accessed using `reply->len`.\n\n* **`REDIS_REPLY_ERROR`**:\n    *  The command replied with an error. The error string can be accessed identical to `REDIS_REPLY_STATUS`.\n\n* **`REDIS_REPLY_INTEGER`**:\n    * The command replied with an integer. The integer value can be accessed using the\n      `reply->integer` field of type `long long`.\n\n* **`REDIS_REPLY_NIL`**:\n    * The command replied with a **nil** object. There is no data to access.\n\n* **`REDIS_REPLY_STRING`**:\n    * A bulk (string) reply. The value of the reply can be accessed using `reply->str`.\n      The length of this string can be accessed using `reply->len`.\n\n* **`REDIS_REPLY_ARRAY`**:\n    * A multi bulk reply. The number of elements in the multi bulk reply is stored in\n      `reply->elements`. Every element in the multi bulk reply is a `redisReply` object as well\n      and can be accessed via `reply->element[..index..]`.\n      Redis may reply with nested arrays but this is fully supported.\n\nReplies should be freed using the `freeReplyObject()` function.\nNote that this function will take care of freeing sub-replies objects\ncontained in arrays and nested arrays, so there is no need for the user to\nfree the sub replies (it is actually harmful and will corrupt the memory).\n\n**Important:** the current version of hiredis (0.10.0) free's replies when the\nasynchronous API is used. This means you should not call `freeReplyObject` when\nyou use this API. The reply is cleaned up by hiredis _after_ the callback\nreturns. This behavior will probably change in future releases, so make sure to\nkeep an eye on the changelog when upgrading (see issue #39).\n\n### Cleaning up\n\nTo disconnect and free the context the following function can be used:\n\n    void redisFree(redisContext *c);\n\nThis function immediately closes the socket and then free's the allocations done in\ncreating the context.\n\n### Sending commands (cont'd)\n\nTogether with `redisCommand`, the function `redisCommandArgv` can be used to issue commands.\nIt has the following prototype:\n\n    void *redisCommandArgv(redisContext *c, int argc, const char **argv, const size_t *argvlen);\n\nIt takes the number of arguments `argc`, an array of strings `argv` and the lengths of the\narguments `argvlen`. For convenience, `argvlen` may be set to `NULL` and the function will\nuse `strlen(3)` on every argument to determine its length. Obviously, when any of the arguments\nneed to be binary safe, the entire array of lengths `argvlen` should be provided.\n\nThe return value has the same semantic as `redisCommand`.\n\n### Pipelining\n\nTo explain how Hiredis supports pipelining in a blocking connection, there needs to be\nunderstanding of the internal execution flow.\n\nWhen any of the functions in the `redisCommand` family is called, Hiredis first formats the\ncommand according to the Redis protocol. The formatted command is then put in the output buffer\nof the context. This output buffer is dynamic, so it can hold any number of commands.\nAfter the command is put in the output buffer, `redisGetReply` is called. This function has the\nfollowing two execution paths:\n\n1. The input buffer is non-empty:\n    * Try to parse a single reply from the input buffer and return it\n    * If no reply could be parsed, continue at *2*\n2. The input buffer is empty:\n    * Write the **entire** output buffer to the socket\n    * Read from the socket until a single reply could be parsed\n\nThe function `redisGetReply` is exported as part of the Hiredis API and can be used when a reply\nis expected on the socket. To pipeline commands, the only things that needs to be done is\nfilling up the output buffer. For this cause, two commands can be used that are identical\nto the `redisCommand` family, apart from not returning a reply:\n\n    void redisAppendCommand(redisContext *c, const char *format, ...);\n    void redisAppendCommandArgv(redisContext *c, int argc, const char **argv, const size_t *argvlen);\n\nAfter calling either function one or more times, `redisGetReply` can be used to receive the\nsubsequent replies. The return value for this function is either `REDIS_OK` or `REDIS_ERR`, where\nthe latter means an error occurred while reading a reply. Just as with the other commands,\nthe `err` field in the context can be used to find out what the cause of this error is.\n\nThe following examples shows a simple pipeline (resulting in only a single call to `write(2)` and\na single call to `read(2)`):\n\n    redisReply *reply;\n    redisAppendCommand(context,\"SET foo bar\");\n    redisAppendCommand(context,\"GET foo\");\n    redisGetReply(context,&reply); // reply for SET\n    freeReplyObject(reply);\n    redisGetReply(context,&reply); // reply for GET\n    freeReplyObject(reply);\n\nThis API can also be used to implement a blocking subscriber:\n\n    reply = redisCommand(context,\"SUBSCRIBE foo\");\n    freeReplyObject(reply);\n    while(redisGetReply(context,&reply) == REDIS_OK) {\n        // consume message\n        freeReplyObject(reply);\n    }\n\n### Errors\n\nWhen a function call is not successful, depending on the function either `NULL` or `REDIS_ERR` is\nreturned. The `err` field inside the context will be non-zero and set to one of the\nfollowing constants:\n\n* **`REDIS_ERR_IO`**:\n    There was an I/O error while creating the connection, trying to write\n    to the socket or read from the socket. If you included `errno.h` in your\n    application, you can use the global `errno` variable to find out what is\n    wrong.\n\n* **`REDIS_ERR_EOF`**:\n    The server closed the connection which resulted in an empty read.\n\n* **`REDIS_ERR_PROTOCOL`**:\n    There was an error while parsing the protocol.\n\n* **`REDIS_ERR_OTHER`**:\n    Any other error. Currently, it is only used when a specified hostname to connect\n    to cannot be resolved.\n\nIn every case, the `errstr` field in the context will be set to hold a string representation\nof the error.\n\n## Asynchronous API\n\nHiredis comes with an asynchronous API that works easily with any event library.\nExamples are bundled that show using Hiredis with [libev](http://software.schmorp.de/pkg/libev.html)\nand [libevent](http://monkey.org/~provos/libevent/).\n\n### Connecting\n\nThe function `redisAsyncConnect` can be used to establish a non-blocking connection to\nRedis. It returns a pointer to the newly created `redisAsyncContext` struct. The `err` field\nshould be checked after creation to see if there were errors creating the connection.\nBecause the connection that will be created is non-blocking, the kernel is not able to\ninstantly return if the specified host and port is able to accept a connection.\n\n    redisAsyncContext *c = redisAsyncConnect(\"127.0.0.1\", 6379);\n    if (c->err) {\n        printf(\"Error: %s\\n\", c->errstr);\n        // handle error\n    }\n\nThe asynchronous context can hold a disconnect callback function that is called when the\nconnection is disconnected (either because of an error or per user request). This function should\nhave the following prototype:\n\n    void(const redisAsyncContext *c, int status);\n\nOn a disconnect, the `status` argument is set to `REDIS_OK` when disconnection was initiated by the\nuser, or `REDIS_ERR` when the disconnection was caused by an error. When it is `REDIS_ERR`, the `err`\nfield in the context can be accessed to find out the cause of the error.\n\nThe context object is always free'd after the disconnect callback fired. When a reconnect is needed,\nthe disconnect callback is a good point to do so.\n\nSetting the disconnect callback can only be done once per context. For subsequent calls it will\nreturn `REDIS_ERR`. The function to set the disconnect callback has the following prototype:\n\n    int redisAsyncSetDisconnectCallback(redisAsyncContext *ac, redisDisconnectCallback *fn);\n\n### Sending commands and their callbacks\n\nIn an asynchronous context, commands are automatically pipelined due to the nature of an event loop.\nTherefore, unlike the synchronous API, there is only a single way to send commands.\nBecause commands are sent to Redis asynchronously, issuing a command requires a callback function\nthat is called when the reply is received. Reply callbacks should have the following prototype:\n\n    void(redisAsyncContext *c, void *reply, void *privdata);\n\nThe `privdata` argument can be used to curry arbitrary data to the callback from the point where\nthe command is initially queued for execution.\n\nThe functions that can be used to issue commands in an asynchronous context are:\n\n    int redisAsyncCommand(\n      redisAsyncContext *ac, redisCallbackFn *fn, void *privdata,\n      const char *format, ...);\n    int redisAsyncCommandArgv(\n      redisAsyncContext *ac, redisCallbackFn *fn, void *privdata,\n      int argc, const char **argv, const size_t *argvlen);\n\nBoth functions work like their blocking counterparts. The return value is `REDIS_OK` when the command\nwas successfully added to the output buffer and `REDIS_ERR` otherwise. Example: when the connection\nis being disconnected per user-request, no new commands may be added to the output buffer and `REDIS_ERR` is\nreturned on calls to the `redisAsyncCommand` family.\n\nIf the reply for a command with a `NULL` callback is read, it is immediately free'd. When the callback\nfor a command is non-`NULL`, the memory is free'd immediately following the callback: the reply is only\nvalid for the duration of the callback.\n\nAll pending callbacks are called with a `NULL` reply when the context encountered an error.\n\n### Disconnecting\n\nAn asynchronous connection can be terminated using:\n\n    void redisAsyncDisconnect(redisAsyncContext *ac);\n\nWhen this function is called, the connection is **not** immediately terminated. Instead, new\ncommands are no longer accepted and the connection is only terminated when all pending commands\nhave been written to the socket, their respective replies have been read and their respective\ncallbacks have been executed. After this, the disconnection callback is executed with the\n`REDIS_OK` status and the context object is free'd.\n\n### Hooking it up to event library *X*\n\nThere are a few hooks that need to be set on the context object after it is created.\nSee the `adapters/` directory for bindings to *libev* and *libevent*.\n\n## Reply parsing API\n\nHiredis comes with a reply parsing API that makes it easy for writing higher\nlevel language bindings.\n\nThe reply parsing API consists of the following functions:\n\n    redisReader *redisReaderCreate(void);\n    void redisReaderFree(redisReader *reader);\n    int redisReaderFeed(redisReader *reader, const char *buf, size_t len);\n    int redisReaderGetReply(redisReader *reader, void **reply);\n\nThe same set of functions are used internally by hiredis when creating a\nnormal Redis context, the above API just exposes it to the user for a direct\nusage.\n\n### Usage\n\nThe function `redisReaderCreate` creates a `redisReader` structure that holds a\nbuffer with unparsed data and state for the protocol parser.\n\nIncoming data -- most likely from a socket -- can be placed in the internal\nbuffer of the `redisReader` using `redisReaderFeed`. This function will make a\ncopy of the buffer pointed to by `buf` for `len` bytes. This data is parsed\nwhen `redisReaderGetReply` is called. This function returns an integer status\nand a reply object (as described above) via `void **reply`. The returned status\ncan be either `REDIS_OK` or `REDIS_ERR`, where the latter means something went\nwrong (either a protocol error, or an out of memory error).\n\nThe parser limits the level of nesting for multi bulk payloads to 7. If the\nmulti bulk nesting level is higher than this, the parser returns an error.\n\n### Customizing replies\n\nThe function `redisReaderGetReply` creates `redisReply` and makes the function\nargument `reply` point to the created `redisReply` variable. For instance, if\nthe response of type `REDIS_REPLY_STATUS` then the `str` field of `redisReply`\nwill hold the status as a vanilla C string. However, the functions that are\nresponsible for creating instances of the `redisReply` can be customized by\nsetting the `fn` field on the `redisReader` struct. This should be done\nimmediately after creating the `redisReader`.\n\nFor example, [hiredis-rb](https://github.com/pietern/hiredis-rb/blob/master/ext/hiredis_ext/reader.c)\nuses customized reply object functions to create Ruby objects.\n\n### Reader max buffer\n\nBoth when using the Reader API directly or when using it indirectly via a\nnormal Redis context, the redisReader structure uses a buffer in order to\naccumulate data from the server.\nUsually this buffer is destroyed when it is empty and is larger than 16\nkb in order to avoid wasting memory in unused buffers\n\nHowever when working with very big payloads destroying the buffer may slow\ndown performances considerably, so it is possible to modify the max size of\nan idle buffer changing the value of the `maxbuf` field of the reader structure\nto the desired value. The special value of 0 means that there is no maximum\nvalue for an idle buffer, so the buffer will never get freed.\n\nFor instance if you have a normal Redis context you can set the maximum idle\nbuffer to zero (unlimited) just with:\n\n    context->reader->maxbuf = 0;\n\nThis should be done only in order to maximize performances when working with\nlarge payloads. The context should be set back to `REDIS_READER_MAX_BUF` again\nas soon as possible in order to prevent allocation of useless memory.\n\n## AUTHORS\n\nHiredis was written by Salvatore Sanfilippo (antirez at gmail) and\nPieter Noordhuis (pcnoordhuis at gmail) and is released under the BSD license.\n"
  },
  {
    "path": "extern/deprecated/redis-2.8.21/deps/hiredis/adapters/ae.h",
    "content": "/*\n * Copyright (c) 2010-2011, Pieter Noordhuis <pcnoordhuis at gmail dot com>\n *\n * All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions are met:\n *\n *   * Redistributions of source code must retain the above copyright notice,\n *     this list of conditions and the following disclaimer.\n *   * Redistributions in binary form must reproduce the above copyright\n *     notice, this list of conditions and the following disclaimer in the\n *     documentation and/or other materials provided with the distribution.\n *   * Neither the name of Redis nor the names of its contributors may be used\n *     to endorse or promote products derived from this software without\n *     specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\"\n * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\n * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE\n * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR\n * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF\n * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS\n * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN\n * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)\n * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE\n * POSSIBILITY OF SUCH DAMAGE.\n */\n\n#ifndef __HIREDIS_AE_H__\n#define __HIREDIS_AE_H__\n#include <sys/types.h>\n#include <ae.h>\n#include \"../hiredis.h\"\n#include \"../async.h\"\n\ntypedef struct redisAeEvents {\n    redisAsyncContext *context;\n    aeEventLoop *loop;\n    int fd;\n    int reading, writing;\n} redisAeEvents;\n\nstatic void redisAeReadEvent(aeEventLoop *el, int fd, void *privdata, int mask) {\n    ((void)el); ((void)fd); ((void)mask);\n\n    redisAeEvents *e = (redisAeEvents*)privdata;\n    redisAsyncHandleRead(e->context);\n}\n\nstatic void redisAeWriteEvent(aeEventLoop *el, int fd, void *privdata, int mask) {\n    ((void)el); ((void)fd); ((void)mask);\n\n    redisAeEvents *e = (redisAeEvents*)privdata;\n    redisAsyncHandleWrite(e->context);\n}\n\nstatic void redisAeAddRead(void *privdata) {\n    redisAeEvents *e = (redisAeEvents*)privdata;\n    aeEventLoop *loop = e->loop;\n    if (!e->reading) {\n        e->reading = 1;\n        aeCreateFileEvent(loop,e->fd,AE_READABLE,redisAeReadEvent,e);\n    }\n}\n\nstatic void redisAeDelRead(void *privdata) {\n    redisAeEvents *e = (redisAeEvents*)privdata;\n    aeEventLoop *loop = e->loop;\n    if (e->reading) {\n        e->reading = 0;\n        aeDeleteFileEvent(loop,e->fd,AE_READABLE);\n    }\n}\n\nstatic void redisAeAddWrite(void *privdata) {\n    redisAeEvents *e = (redisAeEvents*)privdata;\n    aeEventLoop *loop = e->loop;\n    if (!e->writing) {\n        e->writing = 1;\n        aeCreateFileEvent(loop,e->fd,AE_WRITABLE,redisAeWriteEvent,e);\n    }\n}\n\nstatic void redisAeDelWrite(void *privdata) {\n    redisAeEvents *e = (redisAeEvents*)privdata;\n    aeEventLoop *loop = e->loop;\n    if (e->writing) {\n        e->writing = 0;\n        aeDeleteFileEvent(loop,e->fd,AE_WRITABLE);\n    }\n}\n\nstatic void redisAeCleanup(void *privdata) {\n    redisAeEvents *e = (redisAeEvents*)privdata;\n    redisAeDelRead(privdata);\n    redisAeDelWrite(privdata);\n    free(e);\n}\n\nstatic int redisAeAttach(aeEventLoop *loop, redisAsyncContext *ac) {\n    redisContext *c = &(ac->c);\n    redisAeEvents *e;\n\n    /* Nothing should be attached when something is already attached */\n    if (ac->ev.data != NULL)\n        return REDIS_ERR;\n\n    /* Create container for context and r/w events */\n    e = (redisAeEvents*)malloc(sizeof(*e));\n    e->context = ac;\n    e->loop = loop;\n    e->fd = c->fd;\n    e->reading = e->writing = 0;\n\n    /* Register functions to start/stop listening for events */\n    ac->ev.addRead = redisAeAddRead;\n    ac->ev.delRead = redisAeDelRead;\n    ac->ev.addWrite = redisAeAddWrite;\n    ac->ev.delWrite = redisAeDelWrite;\n    ac->ev.cleanup = redisAeCleanup;\n    ac->ev.data = e;\n\n    return REDIS_OK;\n}\n#endif\n"
  },
  {
    "path": "extern/deprecated/redis-2.8.21/deps/hiredis/adapters/libev.h",
    "content": "/*\n * Copyright (c) 2010-2011, Pieter Noordhuis <pcnoordhuis at gmail dot com>\n *\n * All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions are met:\n *\n *   * Redistributions of source code must retain the above copyright notice,\n *     this list of conditions and the following disclaimer.\n *   * Redistributions in binary form must reproduce the above copyright\n *     notice, this list of conditions and the following disclaimer in the\n *     documentation and/or other materials provided with the distribution.\n *   * Neither the name of Redis nor the names of its contributors may be used\n *     to endorse or promote products derived from this software without\n *     specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\"\n * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\n * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE\n * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR\n * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF\n * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS\n * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN\n * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)\n * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE\n * POSSIBILITY OF SUCH DAMAGE.\n */\n\n#ifndef __HIREDIS_LIBEV_H__\n#define __HIREDIS_LIBEV_H__\n#include <stdlib.h>\n#include <sys/types.h>\n#include <ev.h>\n#include \"../hiredis.h\"\n#include \"../async.h\"\n\ntypedef struct redisLibevEvents {\n    redisAsyncContext *context;\n    struct ev_loop *loop;\n    int reading, writing;\n    ev_io rev, wev;\n} redisLibevEvents;\n\nstatic void redisLibevReadEvent(EV_P_ ev_io *watcher, int revents) {\n#if EV_MULTIPLICITY\n    ((void)loop);\n#endif\n    ((void)revents);\n\n    redisLibevEvents *e = (redisLibevEvents*)watcher->data;\n    redisAsyncHandleRead(e->context);\n}\n\nstatic void redisLibevWriteEvent(EV_P_ ev_io *watcher, int revents) {\n#if EV_MULTIPLICITY\n    ((void)loop);\n#endif\n    ((void)revents);\n\n    redisLibevEvents *e = (redisLibevEvents*)watcher->data;\n    redisAsyncHandleWrite(e->context);\n}\n\nstatic void redisLibevAddRead(void *privdata) {\n    redisLibevEvents *e = (redisLibevEvents*)privdata;\n    struct ev_loop *loop = e->loop;\n    ((void)loop);\n    if (!e->reading) {\n        e->reading = 1;\n        ev_io_start(EV_A_ &e->rev);\n    }\n}\n\nstatic void redisLibevDelRead(void *privdata) {\n    redisLibevEvents *e = (redisLibevEvents*)privdata;\n    struct ev_loop *loop = e->loop;\n    ((void)loop);\n    if (e->reading) {\n        e->reading = 0;\n        ev_io_stop(EV_A_ &e->rev);\n    }\n}\n\nstatic void redisLibevAddWrite(void *privdata) {\n    redisLibevEvents *e = (redisLibevEvents*)privdata;\n    struct ev_loop *loop = e->loop;\n    ((void)loop);\n    if (!e->writing) {\n        e->writing = 1;\n        ev_io_start(EV_A_ &e->wev);\n    }\n}\n\nstatic void redisLibevDelWrite(void *privdata) {\n    redisLibevEvents *e = (redisLibevEvents*)privdata;\n    struct ev_loop *loop = e->loop;\n    ((void)loop);\n    if (e->writing) {\n        e->writing = 0;\n        ev_io_stop(EV_A_ &e->wev);\n    }\n}\n\nstatic void redisLibevCleanup(void *privdata) {\n    redisLibevEvents *e = (redisLibevEvents*)privdata;\n    redisLibevDelRead(privdata);\n    redisLibevDelWrite(privdata);\n    free(e);\n}\n\nstatic int redisLibevAttach(EV_P_ redisAsyncContext *ac) {\n    redisContext *c = &(ac->c);\n    redisLibevEvents *e;\n\n    /* Nothing should be attached when something is already attached */\n    if (ac->ev.data != NULL)\n        return REDIS_ERR;\n\n    /* Create container for context and r/w events */\n    e = (redisLibevEvents*)malloc(sizeof(*e));\n    e->context = ac;\n#if EV_MULTIPLICITY\n    e->loop = loop;\n#else\n    e->loop = NULL;\n#endif\n    e->reading = e->writing = 0;\n    e->rev.data = e;\n    e->wev.data = e;\n\n    /* Register functions to start/stop listening for events */\n    ac->ev.addRead = redisLibevAddRead;\n    ac->ev.delRead = redisLibevDelRead;\n    ac->ev.addWrite = redisLibevAddWrite;\n    ac->ev.delWrite = redisLibevDelWrite;\n    ac->ev.cleanup = redisLibevCleanup;\n    ac->ev.data = e;\n\n    /* Initialize read/write events */\n    ev_io_init(&e->rev,redisLibevReadEvent,c->fd,EV_READ);\n    ev_io_init(&e->wev,redisLibevWriteEvent,c->fd,EV_WRITE);\n    return REDIS_OK;\n}\n\n#endif\n"
  },
  {
    "path": "extern/deprecated/redis-2.8.21/deps/hiredis/adapters/libevent.h",
    "content": "/*\n * Copyright (c) 2010-2011, Pieter Noordhuis <pcnoordhuis at gmail dot com>\n *\n * All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions are met:\n *\n *   * Redistributions of source code must retain the above copyright notice,\n *     this list of conditions and the following disclaimer.\n *   * Redistributions in binary form must reproduce the above copyright\n *     notice, this list of conditions and the following disclaimer in the\n *     documentation and/or other materials provided with the distribution.\n *   * Neither the name of Redis nor the names of its contributors may be used\n *     to endorse or promote products derived from this software without\n *     specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\"\n * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\n * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE\n * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR\n * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF\n * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS\n * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN\n * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)\n * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE\n * POSSIBILITY OF SUCH DAMAGE.\n */\n\n#ifndef __HIREDIS_LIBEVENT_H__\n#define __HIREDIS_LIBEVENT_H__\n#include <event.h>\n#include \"../hiredis.h\"\n#include \"../async.h\"\n\ntypedef struct redisLibeventEvents {\n    redisAsyncContext *context;\n    struct event rev, wev;\n} redisLibeventEvents;\n\nstatic void redisLibeventReadEvent(int fd, short event, void *arg) {\n    ((void)fd); ((void)event);\n    redisLibeventEvents *e = (redisLibeventEvents*)arg;\n    redisAsyncHandleRead(e->context);\n}\n\nstatic void redisLibeventWriteEvent(int fd, short event, void *arg) {\n    ((void)fd); ((void)event);\n    redisLibeventEvents *e = (redisLibeventEvents*)arg;\n    redisAsyncHandleWrite(e->context);\n}\n\nstatic void redisLibeventAddRead(void *privdata) {\n    redisLibeventEvents *e = (redisLibeventEvents*)privdata;\n    event_add(&e->rev,NULL);\n}\n\nstatic void redisLibeventDelRead(void *privdata) {\n    redisLibeventEvents *e = (redisLibeventEvents*)privdata;\n    event_del(&e->rev);\n}\n\nstatic void redisLibeventAddWrite(void *privdata) {\n    redisLibeventEvents *e = (redisLibeventEvents*)privdata;\n    event_add(&e->wev,NULL);\n}\n\nstatic void redisLibeventDelWrite(void *privdata) {\n    redisLibeventEvents *e = (redisLibeventEvents*)privdata;\n    event_del(&e->wev);\n}\n\nstatic void redisLibeventCleanup(void *privdata) {\n    redisLibeventEvents *e = (redisLibeventEvents*)privdata;\n    event_del(&e->rev);\n    event_del(&e->wev);\n    free(e);\n}\n\nstatic int redisLibeventAttach(redisAsyncContext *ac, struct event_base *base) {\n    redisContext *c = &(ac->c);\n    redisLibeventEvents *e;\n\n    /* Nothing should be attached when something is already attached */\n    if (ac->ev.data != NULL)\n        return REDIS_ERR;\n\n    /* Create container for context and r/w events */\n    e = (redisLibeventEvents*)malloc(sizeof(*e));\n    e->context = ac;\n\n    /* Register functions to start/stop listening for events */\n    ac->ev.addRead = redisLibeventAddRead;\n    ac->ev.delRead = redisLibeventDelRead;\n    ac->ev.addWrite = redisLibeventAddWrite;\n    ac->ev.delWrite = redisLibeventDelWrite;\n    ac->ev.cleanup = redisLibeventCleanup;\n    ac->ev.data = e;\n\n    /* Initialize and install read/write events */\n    event_set(&e->rev,c->fd,EV_READ,redisLibeventReadEvent,e);\n    event_set(&e->wev,c->fd,EV_WRITE,redisLibeventWriteEvent,e);\n    event_base_set(base,&e->rev);\n    event_base_set(base,&e->wev);\n    return REDIS_OK;\n}\n#endif\n"
  },
  {
    "path": "extern/deprecated/redis-2.8.21/deps/hiredis/adapters/libuv.h",
    "content": "#ifndef __HIREDIS_LIBUV_H__\n#define __HIREDIS_LIBUV_H__\n#include <uv.h>\n#include \"../hiredis.h\"\n#include \"../async.h\"\n#include <string.h>\n\ntypedef struct redisLibuvEvents {\n  redisAsyncContext* context;\n  uv_poll_t          handle;\n  int                events;\n} redisLibuvEvents;\n\nint redisLibuvAttach(redisAsyncContext*, uv_loop_t*);\n\nstatic void redisLibuvPoll(uv_poll_t* handle, int status, int events) {\n  redisLibuvEvents* p = (redisLibuvEvents*)handle->data;\n\n  if (status != 0) {\n    return;\n  }\n\n  if (events & UV_READABLE) {\n    redisAsyncHandleRead(p->context);\n  }\n  if (events & UV_WRITABLE) {\n    redisAsyncHandleWrite(p->context);\n  }\n}\n\n\nstatic void redisLibuvAddRead(void *privdata) {\n  redisLibuvEvents* p = (redisLibuvEvents*)privdata;\n\n  p->events |= UV_READABLE;\n\n  uv_poll_start(&p->handle, p->events, redisLibuvPoll);\n}\n\n\nstatic void redisLibuvDelRead(void *privdata) {\n  redisLibuvEvents* p = (redisLibuvEvents*)privdata;\n\n  p->events &= ~UV_READABLE;\n\n  if (p->events) {\n    uv_poll_start(&p->handle, p->events, redisLibuvPoll);\n  } else {\n    uv_poll_stop(&p->handle);\n  }\n}\n\n\nstatic void redisLibuvAddWrite(void *privdata) {\n  redisLibuvEvents* p = (redisLibuvEvents*)privdata;\n\n  p->events |= UV_WRITABLE;\n\n  uv_poll_start(&p->handle, p->events, redisLibuvPoll);\n}\n\n\nstatic void redisLibuvDelWrite(void *privdata) {\n  redisLibuvEvents* p = (redisLibuvEvents*)privdata;\n\n  p->events &= ~UV_WRITABLE;\n\n  if (p->events) {\n    uv_poll_start(&p->handle, p->events, redisLibuvPoll);\n  } else {\n    uv_poll_stop(&p->handle);\n  }\n}\n\n\nstatic void on_close(uv_handle_t* handle) {\n  redisLibuvEvents* p = (redisLibuvEvents*)handle->data;\n\n  free(p);\n}\n\n\nstatic void redisLibuvCleanup(void *privdata) {\n  redisLibuvEvents* p = (redisLibuvEvents*)privdata;\n\n  uv_close((uv_handle_t*)&p->handle, on_close);\n}\n\n\nstatic int redisLibuvAttach(redisAsyncContext* ac, uv_loop_t* loop) {\n  redisContext *c = &(ac->c);\n\n  if (ac->ev.data != NULL) {\n    return REDIS_ERR;\n  }\n\n  ac->ev.addRead  = redisLibuvAddRead;\n  ac->ev.delRead  = redisLibuvDelRead;\n  ac->ev.addWrite = redisLibuvAddWrite;\n  ac->ev.delWrite = redisLibuvDelWrite;\n  ac->ev.cleanup  = redisLibuvCleanup;\n\n  redisLibuvEvents* p = (redisLibuvEvents*)malloc(sizeof(*p));\n\n  if (!p) {\n    return REDIS_ERR;\n  }\n\n  memset(p, 0, sizeof(*p));\n\n  if (uv_poll_init(loop, &p->handle, c->fd) != 0) {\n    return REDIS_ERR;\n  }\n\n  ac->ev.data    = p;\n  p->handle.data = p;\n  p->context     = ac;\n\n  return REDIS_OK;\n}\n#endif\n"
  },
  {
    "path": "extern/deprecated/redis-2.8.21/deps/hiredis/async.c",
    "content": "/*\n * Copyright (c) 2009-2011, Salvatore Sanfilippo <antirez at gmail dot com>\n * Copyright (c) 2010-2011, Pieter Noordhuis <pcnoordhuis at gmail dot com>\n *\n * All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions are met:\n *\n *   * Redistributions of source code must retain the above copyright notice,\n *     this list of conditions and the following disclaimer.\n *   * Redistributions in binary form must reproduce the above copyright\n *     notice, this list of conditions and the following disclaimer in the\n *     documentation and/or other materials provided with the distribution.\n *   * Neither the name of Redis nor the names of its contributors may be used\n *     to endorse or promote products derived from this software without\n *     specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\"\n * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\n * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE\n * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR\n * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF\n * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS\n * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN\n * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)\n * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE\n * POSSIBILITY OF SUCH DAMAGE.\n */\n\n#include \"fmacros.h\"\n#include <stdlib.h>\n#include <string.h>\n#include <strings.h>\n#include <assert.h>\n#include <ctype.h>\n#include <errno.h>\n#include \"async.h\"\n#include \"net.h\"\n#include \"dict.c\"\n#include \"sds.h\"\n\n#define _EL_ADD_READ(ctx) do { \\\n        if ((ctx)->ev.addRead) (ctx)->ev.addRead((ctx)->ev.data); \\\n    } while(0)\n#define _EL_DEL_READ(ctx) do { \\\n        if ((ctx)->ev.delRead) (ctx)->ev.delRead((ctx)->ev.data); \\\n    } while(0)\n#define _EL_ADD_WRITE(ctx) do { \\\n        if ((ctx)->ev.addWrite) (ctx)->ev.addWrite((ctx)->ev.data); \\\n    } while(0)\n#define _EL_DEL_WRITE(ctx) do { \\\n        if ((ctx)->ev.delWrite) (ctx)->ev.delWrite((ctx)->ev.data); \\\n    } while(0)\n#define _EL_CLEANUP(ctx) do { \\\n        if ((ctx)->ev.cleanup) (ctx)->ev.cleanup((ctx)->ev.data); \\\n    } while(0);\n\n/* Forward declaration of function in hiredis.c */\nvoid __redisAppendCommand(redisContext *c, char *cmd, size_t len);\n\n/* Functions managing dictionary of callbacks for pub/sub. */\nstatic unsigned int callbackHash(const void *key) {\n    return dictGenHashFunction((const unsigned char *)key,\n                               sdslen((const sds)key));\n}\n\nstatic void *callbackValDup(void *privdata, const void *src) {\n    ((void) privdata);\n    redisCallback *dup = malloc(sizeof(*dup));\n    memcpy(dup,src,sizeof(*dup));\n    return dup;\n}\n\nstatic int callbackKeyCompare(void *privdata, const void *key1, const void *key2) {\n    int l1, l2;\n    ((void) privdata);\n\n    l1 = sdslen((const sds)key1);\n    l2 = sdslen((const sds)key2);\n    if (l1 != l2) return 0;\n    return memcmp(key1,key2,l1) == 0;\n}\n\nstatic void callbackKeyDestructor(void *privdata, void *key) {\n    ((void) privdata);\n    sdsfree((sds)key);\n}\n\nstatic void callbackValDestructor(void *privdata, void *val) {\n    ((void) privdata);\n    free(val);\n}\n\nstatic dictType callbackDict = {\n    callbackHash,\n    NULL,\n    callbackValDup,\n    callbackKeyCompare,\n    callbackKeyDestructor,\n    callbackValDestructor\n};\n\nstatic redisAsyncContext *redisAsyncInitialize(redisContext *c) {\n    redisAsyncContext *ac;\n\n    ac = realloc(c,sizeof(redisAsyncContext));\n    if (ac == NULL)\n        return NULL;\n\n    c = &(ac->c);\n\n    /* The regular connect functions will always set the flag REDIS_CONNECTED.\n     * For the async API, we want to wait until the first write event is\n     * received up before setting this flag, so reset it here. */\n    c->flags &= ~REDIS_CONNECTED;\n\n    ac->err = 0;\n    ac->errstr = NULL;\n    ac->data = NULL;\n\n    ac->ev.data = NULL;\n    ac->ev.addRead = NULL;\n    ac->ev.delRead = NULL;\n    ac->ev.addWrite = NULL;\n    ac->ev.delWrite = NULL;\n    ac->ev.cleanup = NULL;\n\n    ac->onConnect = NULL;\n    ac->onDisconnect = NULL;\n\n    ac->replies.head = NULL;\n    ac->replies.tail = NULL;\n    ac->sub.invalid.head = NULL;\n    ac->sub.invalid.tail = NULL;\n    ac->sub.channels = dictCreate(&callbackDict,NULL);\n    ac->sub.patterns = dictCreate(&callbackDict,NULL);\n    return ac;\n}\n\n/* We want the error field to be accessible directly instead of requiring\n * an indirection to the redisContext struct. */\nstatic void __redisAsyncCopyError(redisAsyncContext *ac) {\n    redisContext *c = &(ac->c);\n    ac->err = c->err;\n    ac->errstr = c->errstr;\n}\n\nredisAsyncContext *redisAsyncConnect(const char *ip, int port) {\n    redisContext *c;\n    redisAsyncContext *ac;\n\n    c = redisConnectNonBlock(ip,port);\n    if (c == NULL)\n        return NULL;\n\n    ac = redisAsyncInitialize(c);\n    if (ac == NULL) {\n        redisFree(c);\n        return NULL;\n    }\n\n    __redisAsyncCopyError(ac);\n    return ac;\n}\n\nredisAsyncContext *redisAsyncConnectBind(const char *ip, int port,\n                                         const char *source_addr) {\n    redisContext *c = redisConnectBindNonBlock(ip,port,source_addr);\n    redisAsyncContext *ac = redisAsyncInitialize(c);\n    __redisAsyncCopyError(ac);\n    return ac;\n}\n\nredisAsyncContext *redisAsyncConnectUnix(const char *path) {\n    redisContext *c;\n    redisAsyncContext *ac;\n\n    c = redisConnectUnixNonBlock(path);\n    if (c == NULL)\n        return NULL;\n\n    ac = redisAsyncInitialize(c);\n    if (ac == NULL) {\n        redisFree(c);\n        return NULL;\n    }\n\n    __redisAsyncCopyError(ac);\n    return ac;\n}\n\nint redisAsyncSetConnectCallback(redisAsyncContext *ac, redisConnectCallback *fn) {\n    if (ac->onConnect == NULL) {\n        ac->onConnect = fn;\n\n        /* The common way to detect an established connection is to wait for\n         * the first write event to be fired. This assumes the related event\n         * library functions are already set. */\n        _EL_ADD_WRITE(ac);\n        return REDIS_OK;\n    }\n    return REDIS_ERR;\n}\n\nint redisAsyncSetDisconnectCallback(redisAsyncContext *ac, redisDisconnectCallback *fn) {\n    if (ac->onDisconnect == NULL) {\n        ac->onDisconnect = fn;\n        return REDIS_OK;\n    }\n    return REDIS_ERR;\n}\n\n/* Helper functions to push/shift callbacks */\nstatic int __redisPushCallback(redisCallbackList *list, redisCallback *source) {\n    redisCallback *cb;\n\n    /* Copy callback from stack to heap */\n    cb = malloc(sizeof(*cb));\n    if (cb == NULL)\n        return REDIS_ERR_OOM;\n\n    if (source != NULL) {\n        memcpy(cb,source,sizeof(*cb));\n        cb->next = NULL;\n    }\n\n    /* Store callback in list */\n    if (list->head == NULL)\n        list->head = cb;\n    if (list->tail != NULL)\n        list->tail->next = cb;\n    list->tail = cb;\n    return REDIS_OK;\n}\n\nstatic int __redisShiftCallback(redisCallbackList *list, redisCallback *target) {\n    redisCallback *cb = list->head;\n    if (cb != NULL) {\n        list->head = cb->next;\n        if (cb == list->tail)\n            list->tail = NULL;\n\n        /* Copy callback from heap to stack */\n        if (target != NULL)\n            memcpy(target,cb,sizeof(*cb));\n        free(cb);\n        return REDIS_OK;\n    }\n    return REDIS_ERR;\n}\n\nstatic void __redisRunCallback(redisAsyncContext *ac, redisCallback *cb, redisReply *reply) {\n    redisContext *c = &(ac->c);\n    if (cb->fn != NULL) {\n        c->flags |= REDIS_IN_CALLBACK;\n        cb->fn(ac,reply,cb->privdata);\n        c->flags &= ~REDIS_IN_CALLBACK;\n    }\n}\n\n/* Helper function to free the context. */\nstatic void __redisAsyncFree(redisAsyncContext *ac) {\n    redisContext *c = &(ac->c);\n    redisCallback cb;\n    dictIterator *it;\n    dictEntry *de;\n\n    /* Execute pending callbacks with NULL reply. */\n    while (__redisShiftCallback(&ac->replies,&cb) == REDIS_OK)\n        __redisRunCallback(ac,&cb,NULL);\n\n    /* Execute callbacks for invalid commands */\n    while (__redisShiftCallback(&ac->sub.invalid,&cb) == REDIS_OK)\n        __redisRunCallback(ac,&cb,NULL);\n\n    /* Run subscription callbacks callbacks with NULL reply */\n    it = dictGetIterator(ac->sub.channels);\n    while ((de = dictNext(it)) != NULL)\n        __redisRunCallback(ac,dictGetEntryVal(de),NULL);\n    dictReleaseIterator(it);\n    dictRelease(ac->sub.channels);\n\n    it = dictGetIterator(ac->sub.patterns);\n    while ((de = dictNext(it)) != NULL)\n        __redisRunCallback(ac,dictGetEntryVal(de),NULL);\n    dictReleaseIterator(it);\n    dictRelease(ac->sub.patterns);\n\n    /* Signal event lib to clean up */\n    _EL_CLEANUP(ac);\n\n    /* Execute disconnect callback. When redisAsyncFree() initiated destroying\n     * this context, the status will always be REDIS_OK. */\n    if (ac->onDisconnect && (c->flags & REDIS_CONNECTED)) {\n        if (c->flags & REDIS_FREEING) {\n            ac->onDisconnect(ac,REDIS_OK);\n        } else {\n            ac->onDisconnect(ac,(ac->err == 0) ? REDIS_OK : REDIS_ERR);\n        }\n    }\n\n    /* Cleanup self */\n    redisFree(c);\n}\n\n/* Free the async context. When this function is called from a callback,\n * control needs to be returned to redisProcessCallbacks() before actual\n * free'ing. To do so, a flag is set on the context which is picked up by\n * redisProcessCallbacks(). Otherwise, the context is immediately free'd. */\nvoid redisAsyncFree(redisAsyncContext *ac) {\n    redisContext *c = &(ac->c);\n    c->flags |= REDIS_FREEING;\n    if (!(c->flags & REDIS_IN_CALLBACK))\n        __redisAsyncFree(ac);\n}\n\n/* Helper function to make the disconnect happen and clean up. */\nstatic void __redisAsyncDisconnect(redisAsyncContext *ac) {\n    redisContext *c = &(ac->c);\n\n    /* Make sure error is accessible if there is any */\n    __redisAsyncCopyError(ac);\n\n    if (ac->err == 0) {\n        /* For clean disconnects, there should be no pending callbacks. */\n        assert(__redisShiftCallback(&ac->replies,NULL) == REDIS_ERR);\n    } else {\n        /* Disconnection is caused by an error, make sure that pending\n         * callbacks cannot call new commands. */\n        c->flags |= REDIS_DISCONNECTING;\n    }\n\n    /* For non-clean disconnects, __redisAsyncFree() will execute pending\n     * callbacks with a NULL-reply. */\n    __redisAsyncFree(ac);\n}\n\n/* Tries to do a clean disconnect from Redis, meaning it stops new commands\n * from being issued, but tries to flush the output buffer and execute\n * callbacks for all remaining replies. When this function is called from a\n * callback, there might be more replies and we can safely defer disconnecting\n * to redisProcessCallbacks(). Otherwise, we can only disconnect immediately\n * when there are no pending callbacks. */\nvoid redisAsyncDisconnect(redisAsyncContext *ac) {\n    redisContext *c = &(ac->c);\n    c->flags |= REDIS_DISCONNECTING;\n    if (!(c->flags & REDIS_IN_CALLBACK) && ac->replies.head == NULL)\n        __redisAsyncDisconnect(ac);\n}\n\nstatic int __redisGetSubscribeCallback(redisAsyncContext *ac, redisReply *reply, redisCallback *dstcb) {\n    redisContext *c = &(ac->c);\n    dict *callbacks;\n    dictEntry *de;\n    int pvariant;\n    char *stype;\n    sds sname;\n\n    /* Custom reply functions are not supported for pub/sub. This will fail\n     * very hard when they are used... */\n    if (reply->type == REDIS_REPLY_ARRAY) {\n        assert(reply->elements >= 2);\n        assert(reply->element[0]->type == REDIS_REPLY_STRING);\n        stype = reply->element[0]->str;\n        pvariant = (tolower(stype[0]) == 'p') ? 1 : 0;\n\n        if (pvariant)\n            callbacks = ac->sub.patterns;\n        else\n            callbacks = ac->sub.channels;\n\n        /* Locate the right callback */\n        assert(reply->element[1]->type == REDIS_REPLY_STRING);\n        sname = sdsnewlen(reply->element[1]->str,reply->element[1]->len);\n        de = dictFind(callbacks,sname);\n        if (de != NULL) {\n            memcpy(dstcb,dictGetEntryVal(de),sizeof(*dstcb));\n\n            /* If this is an unsubscribe message, remove it. */\n            if (strcasecmp(stype+pvariant,\"unsubscribe\") == 0) {\n                dictDelete(callbacks,sname);\n\n                /* If this was the last unsubscribe message, revert to\n                 * non-subscribe mode. */\n                assert(reply->element[2]->type == REDIS_REPLY_INTEGER);\n                if (reply->element[2]->integer == 0)\n                    c->flags &= ~REDIS_SUBSCRIBED;\n            }\n        }\n        sdsfree(sname);\n    } else {\n        /* Shift callback for invalid commands. */\n        __redisShiftCallback(&ac->sub.invalid,dstcb);\n    }\n    return REDIS_OK;\n}\n\nvoid redisProcessCallbacks(redisAsyncContext *ac) {\n    redisContext *c = &(ac->c);\n    redisCallback cb = {NULL, NULL, NULL};\n    void *reply = NULL;\n    int status;\n\n    while((status = redisGetReply(c,&reply)) == REDIS_OK) {\n        if (reply == NULL) {\n            /* When the connection is being disconnected and there are\n             * no more replies, this is the cue to really disconnect. */\n            if (c->flags & REDIS_DISCONNECTING && sdslen(c->obuf) == 0) {\n                __redisAsyncDisconnect(ac);\n                return;\n            }\n\n            /* If monitor mode, repush callback */\n            if(c->flags & REDIS_MONITORING) {\n                __redisPushCallback(&ac->replies,&cb);\n            }\n\n            /* When the connection is not being disconnected, simply stop\n             * trying to get replies and wait for the next loop tick. */\n            break;\n        }\n\n        /* Even if the context is subscribed, pending regular callbacks will\n         * get a reply before pub/sub messages arrive. */\n        if (__redisShiftCallback(&ac->replies,&cb) != REDIS_OK) {\n            /*\n             * A spontaneous reply in a not-subscribed context can be the error\n             * reply that is sent when a new connection exceeds the maximum\n             * number of allowed connections on the server side.\n             *\n             * This is seen as an error instead of a regular reply because the\n             * server closes the connection after sending it.\n             *\n             * To prevent the error from being overwritten by an EOF error the\n             * connection is closed here. See issue #43.\n             *\n             * Another possibility is that the server is loading its dataset.\n             * In this case we also want to close the connection, and have the\n             * user wait until the server is ready to take our request.\n             */\n            if (((redisReply*)reply)->type == REDIS_REPLY_ERROR) {\n                c->err = REDIS_ERR_OTHER;\n                snprintf(c->errstr,sizeof(c->errstr),\"%s\",((redisReply*)reply)->str);\n                c->reader->fn->freeObject(reply);\n                __redisAsyncDisconnect(ac);\n                return;\n            }\n            /* No more regular callbacks and no errors, the context *must* be subscribed or monitoring. */\n            assert((c->flags & REDIS_SUBSCRIBED || c->flags & REDIS_MONITORING));\n            if(c->flags & REDIS_SUBSCRIBED)\n                __redisGetSubscribeCallback(ac,reply,&cb);\n        }\n\n        if (cb.fn != NULL) {\n            __redisRunCallback(ac,&cb,reply);\n            c->reader->fn->freeObject(reply);\n\n            /* Proceed with free'ing when redisAsyncFree() was called. */\n            if (c->flags & REDIS_FREEING) {\n                __redisAsyncFree(ac);\n                return;\n            }\n        } else {\n            /* No callback for this reply. This can either be a NULL callback,\n             * or there were no callbacks to begin with. Either way, don't\n             * abort with an error, but simply ignore it because the client\n             * doesn't know what the server will spit out over the wire. */\n            c->reader->fn->freeObject(reply);\n        }\n    }\n\n    /* Disconnect when there was an error reading the reply */\n    if (status != REDIS_OK)\n        __redisAsyncDisconnect(ac);\n}\n\n/* Internal helper function to detect socket status the first time a read or\n * write event fires. When connecting was not succesful, the connect callback\n * is called with a REDIS_ERR status and the context is free'd. */\nstatic int __redisAsyncHandleConnect(redisAsyncContext *ac) {\n    redisContext *c = &(ac->c);\n\n    if (redisCheckSocketError(c) == REDIS_ERR) {\n        /* Try again later when connect(2) is still in progress. */\n        if (errno == EINPROGRESS)\n            return REDIS_OK;\n\n        if (ac->onConnect) ac->onConnect(ac,REDIS_ERR);\n        __redisAsyncDisconnect(ac);\n        return REDIS_ERR;\n    }\n\n    /* Mark context as connected. */\n    c->flags |= REDIS_CONNECTED;\n    if (ac->onConnect) ac->onConnect(ac,REDIS_OK);\n    return REDIS_OK;\n}\n\n/* This function should be called when the socket is readable.\n * It processes all replies that can be read and executes their callbacks.\n */\nvoid redisAsyncHandleRead(redisAsyncContext *ac) {\n    redisContext *c = &(ac->c);\n\n    if (!(c->flags & REDIS_CONNECTED)) {\n        /* Abort connect was not successful. */\n        if (__redisAsyncHandleConnect(ac) != REDIS_OK)\n            return;\n        /* Try again later when the context is still not connected. */\n        if (!(c->flags & REDIS_CONNECTED))\n            return;\n    }\n\n    if (redisBufferRead(c) == REDIS_ERR) {\n        __redisAsyncDisconnect(ac);\n    } else {\n        /* Always re-schedule reads */\n        _EL_ADD_READ(ac);\n        redisProcessCallbacks(ac);\n    }\n}\n\nvoid redisAsyncHandleWrite(redisAsyncContext *ac) {\n    redisContext *c = &(ac->c);\n    int done = 0;\n\n    if (!(c->flags & REDIS_CONNECTED)) {\n        /* Abort connect was not successful. */\n        if (__redisAsyncHandleConnect(ac) != REDIS_OK)\n            return;\n        /* Try again later when the context is still not connected. */\n        if (!(c->flags & REDIS_CONNECTED))\n            return;\n    }\n\n    if (redisBufferWrite(c,&done) == REDIS_ERR) {\n        __redisAsyncDisconnect(ac);\n    } else {\n        /* Continue writing when not done, stop writing otherwise */\n        if (!done)\n            _EL_ADD_WRITE(ac);\n        else\n            _EL_DEL_WRITE(ac);\n\n        /* Always schedule reads after writes */\n        _EL_ADD_READ(ac);\n    }\n}\n\n/* Sets a pointer to the first argument and its length starting at p. Returns\n * the number of bytes to skip to get to the following argument. */\nstatic char *nextArgument(char *start, char **str, size_t *len) {\n    char *p = start;\n    if (p[0] != '$') {\n        p = strchr(p,'$');\n        if (p == NULL) return NULL;\n    }\n\n    *len = (int)strtol(p+1,NULL,10);\n    p = strchr(p,'\\r');\n    assert(p);\n    *str = p+2;\n    return p+2+(*len)+2;\n}\n\n/* Helper function for the redisAsyncCommand* family of functions. Writes a\n * formatted command to the output buffer and registers the provided callback\n * function with the context. */\nstatic int __redisAsyncCommand(redisAsyncContext *ac, redisCallbackFn *fn, void *privdata, char *cmd, size_t len) {\n    redisContext *c = &(ac->c);\n    redisCallback cb;\n    int pvariant, hasnext;\n    char *cstr, *astr;\n    size_t clen, alen;\n    char *p;\n    sds sname;\n\n    /* Don't accept new commands when the connection is about to be closed. */\n    if (c->flags & (REDIS_DISCONNECTING | REDIS_FREEING)) return REDIS_ERR;\n\n    /* Setup callback */\n    cb.fn = fn;\n    cb.privdata = privdata;\n\n    /* Find out which command will be appended. */\n    p = nextArgument(cmd,&cstr,&clen);\n    assert(p != NULL);\n    hasnext = (p[0] == '$');\n    pvariant = (tolower(cstr[0]) == 'p') ? 1 : 0;\n    cstr += pvariant;\n    clen -= pvariant;\n\n    if (hasnext && strncasecmp(cstr,\"subscribe\\r\\n\",11) == 0) {\n        c->flags |= REDIS_SUBSCRIBED;\n\n        /* Add every channel/pattern to the list of subscription callbacks. */\n        while ((p = nextArgument(p,&astr,&alen)) != NULL) {\n            sname = sdsnewlen(astr,alen);\n            if (pvariant)\n                dictReplace(ac->sub.patterns,sname,&cb);\n            else\n                dictReplace(ac->sub.channels,sname,&cb);\n        }\n    } else if (strncasecmp(cstr,\"unsubscribe\\r\\n\",13) == 0) {\n        /* It is only useful to call (P)UNSUBSCRIBE when the context is\n         * subscribed to one or more channels or patterns. */\n        if (!(c->flags & REDIS_SUBSCRIBED)) return REDIS_ERR;\n\n        /* (P)UNSUBSCRIBE does not have its own response: every channel or\n         * pattern that is unsubscribed will receive a message. This means we\n         * should not append a callback function for this command. */\n     } else if(strncasecmp(cstr,\"monitor\\r\\n\",9) == 0) {\n         /* Set monitor flag and push callback */\n         c->flags |= REDIS_MONITORING;\n         __redisPushCallback(&ac->replies,&cb);\n    } else {\n        if (c->flags & REDIS_SUBSCRIBED)\n            /* This will likely result in an error reply, but it needs to be\n             * received and passed to the callback. */\n            __redisPushCallback(&ac->sub.invalid,&cb);\n        else\n            __redisPushCallback(&ac->replies,&cb);\n    }\n\n    __redisAppendCommand(c,cmd,len);\n\n    /* Always schedule a write when the write buffer is non-empty */\n    _EL_ADD_WRITE(ac);\n\n    return REDIS_OK;\n}\n\nint redisvAsyncCommand(redisAsyncContext *ac, redisCallbackFn *fn, void *privdata, const char *format, va_list ap) {\n    char *cmd;\n    int len;\n    int status;\n    len = redisvFormatCommand(&cmd,format,ap);\n    status = __redisAsyncCommand(ac,fn,privdata,cmd,len);\n    free(cmd);\n    return status;\n}\n\nint redisAsyncCommand(redisAsyncContext *ac, redisCallbackFn *fn, void *privdata, const char *format, ...) {\n    va_list ap;\n    int status;\n    va_start(ap,format);\n    status = redisvAsyncCommand(ac,fn,privdata,format,ap);\n    va_end(ap);\n    return status;\n}\n\nint redisAsyncCommandArgv(redisAsyncContext *ac, redisCallbackFn *fn, void *privdata, int argc, const char **argv, const size_t *argvlen) {\n    char *cmd;\n    int len;\n    int status;\n    len = redisFormatCommandArgv(&cmd,argc,argv,argvlen);\n    status = __redisAsyncCommand(ac,fn,privdata,cmd,len);\n    free(cmd);\n    return status;\n}\n"
  },
  {
    "path": "extern/deprecated/redis-2.8.21/deps/hiredis/async.h",
    "content": "/*\n * Copyright (c) 2009-2011, Salvatore Sanfilippo <antirez at gmail dot com>\n * Copyright (c) 2010-2011, Pieter Noordhuis <pcnoordhuis at gmail dot com>\n *\n * All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions are met:\n *\n *   * Redistributions of source code must retain the above copyright notice,\n *     this list of conditions and the following disclaimer.\n *   * Redistributions in binary form must reproduce the above copyright\n *     notice, this list of conditions and the following disclaimer in the\n *     documentation and/or other materials provided with the distribution.\n *   * Neither the name of Redis nor the names of its contributors may be used\n *     to endorse or promote products derived from this software without\n *     specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\"\n * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\n * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE\n * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR\n * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF\n * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS\n * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN\n * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)\n * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE\n * POSSIBILITY OF SUCH DAMAGE.\n */\n\n#ifndef __HIREDIS_ASYNC_H\n#define __HIREDIS_ASYNC_H\n#include \"hiredis.h\"\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\nstruct redisAsyncContext; /* need forward declaration of redisAsyncContext */\nstruct dict; /* dictionary header is included in async.c */\n\n/* Reply callback prototype and container */\ntypedef void (redisCallbackFn)(struct redisAsyncContext*, void*, void*);\ntypedef struct redisCallback {\n    struct redisCallback *next; /* simple singly linked list */\n    redisCallbackFn *fn;\n    void *privdata;\n} redisCallback;\n\n/* List of callbacks for either regular replies or pub/sub */\ntypedef struct redisCallbackList {\n    redisCallback *head, *tail;\n} redisCallbackList;\n\n/* Connection callback prototypes */\ntypedef void (redisDisconnectCallback)(const struct redisAsyncContext*, int status);\ntypedef void (redisConnectCallback)(const struct redisAsyncContext*, int status);\n\n/* Context for an async connection to Redis */\ntypedef struct redisAsyncContext {\n    /* Hold the regular context, so it can be realloc'ed. */\n    redisContext c;\n\n    /* Setup error flags so they can be used directly. */\n    int err;\n    char *errstr;\n\n    /* Not used by hiredis */\n    void *data;\n\n    /* Event library data and hooks */\n    struct {\n        void *data;\n\n        /* Hooks that are called when the library expects to start\n         * reading/writing. These functions should be idempotent. */\n        void (*addRead)(void *privdata);\n        void (*delRead)(void *privdata);\n        void (*addWrite)(void *privdata);\n        void (*delWrite)(void *privdata);\n        void (*cleanup)(void *privdata);\n    } ev;\n\n    /* Called when either the connection is terminated due to an error or per\n     * user request. The status is set accordingly (REDIS_OK, REDIS_ERR). */\n    redisDisconnectCallback *onDisconnect;\n\n    /* Called when the first write event was received. */\n    redisConnectCallback *onConnect;\n\n    /* Regular command callbacks */\n    redisCallbackList replies;\n\n    /* Subscription callbacks */\n    struct {\n        redisCallbackList invalid;\n        struct dict *channels;\n        struct dict *patterns;\n    } sub;\n} redisAsyncContext;\n\n/* Functions that proxy to hiredis */\nredisAsyncContext *redisAsyncConnect(const char *ip, int port);\nredisAsyncContext *redisAsyncConnectBind(const char *ip, int port, const char *source_addr);\nredisAsyncContext *redisAsyncConnectUnix(const char *path);\nint redisAsyncSetConnectCallback(redisAsyncContext *ac, redisConnectCallback *fn);\nint redisAsyncSetDisconnectCallback(redisAsyncContext *ac, redisDisconnectCallback *fn);\nvoid redisAsyncDisconnect(redisAsyncContext *ac);\nvoid redisAsyncFree(redisAsyncContext *ac);\n\n/* Handle read/write events */\nvoid redisAsyncHandleRead(redisAsyncContext *ac);\nvoid redisAsyncHandleWrite(redisAsyncContext *ac);\n\n/* Command functions for an async context. Write the command to the\n * output buffer and register the provided callback. */\nint redisvAsyncCommand(redisAsyncContext *ac, redisCallbackFn *fn, void *privdata, const char *format, va_list ap);\nint redisAsyncCommand(redisAsyncContext *ac, redisCallbackFn *fn, void *privdata, const char *format, ...);\nint redisAsyncCommandArgv(redisAsyncContext *ac, redisCallbackFn *fn, void *privdata, int argc, const char **argv, const size_t *argvlen);\n\n#ifdef __cplusplus\n}\n#endif\n\n#endif\n"
  },
  {
    "path": "extern/deprecated/redis-2.8.21/deps/hiredis/dict.c",
    "content": "/* Hash table implementation.\n *\n * This file implements in memory hash tables with insert/del/replace/find/\n * get-random-element operations. Hash tables will auto resize if needed\n * tables of power of two in size are used, collisions are handled by\n * chaining. See the source code for more information... :)\n *\n * Copyright (c) 2006-2010, Salvatore Sanfilippo <antirez at gmail dot com>\n * All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions are met:\n *\n *   * Redistributions of source code must retain the above copyright notice,\n *     this list of conditions and the following disclaimer.\n *   * Redistributions in binary form must reproduce the above copyright\n *     notice, this list of conditions and the following disclaimer in the\n *     documentation and/or other materials provided with the distribution.\n *   * Neither the name of Redis nor the names of its contributors may be used\n *     to endorse or promote products derived from this software without\n *     specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\"\n * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\n * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE\n * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR\n * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF\n * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS\n * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN\n * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)\n * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE\n * POSSIBILITY OF SUCH DAMAGE.\n */\n\n#include \"fmacros.h\"\n#include <stdlib.h>\n#include <assert.h>\n#include <limits.h>\n#include \"dict.h\"\n\n/* -------------------------- private prototypes ---------------------------- */\n\nstatic int _dictExpandIfNeeded(dict *ht);\nstatic unsigned long _dictNextPower(unsigned long size);\nstatic int _dictKeyIndex(dict *ht, const void *key);\nstatic int _dictInit(dict *ht, dictType *type, void *privDataPtr);\n\n/* -------------------------- hash functions -------------------------------- */\n\n/* Generic hash function (a popular one from Bernstein).\n * I tested a few and this was the best. */\nstatic unsigned int dictGenHashFunction(const unsigned char *buf, int len) {\n    unsigned int hash = 5381;\n\n    while (len--)\n        hash = ((hash << 5) + hash) + (*buf++); /* hash * 33 + c */\n    return hash;\n}\n\n/* ----------------------------- API implementation ------------------------- */\n\n/* Reset an hashtable already initialized with ht_init().\n * NOTE: This function should only called by ht_destroy(). */\nstatic void _dictReset(dict *ht) {\n    ht->table = NULL;\n    ht->size = 0;\n    ht->sizemask = 0;\n    ht->used = 0;\n}\n\n/* Create a new hash table */\nstatic dict *dictCreate(dictType *type, void *privDataPtr) {\n    dict *ht = malloc(sizeof(*ht));\n    _dictInit(ht,type,privDataPtr);\n    return ht;\n}\n\n/* Initialize the hash table */\nstatic int _dictInit(dict *ht, dictType *type, void *privDataPtr) {\n    _dictReset(ht);\n    ht->type = type;\n    ht->privdata = privDataPtr;\n    return DICT_OK;\n}\n\n/* Expand or create the hashtable */\nstatic int dictExpand(dict *ht, unsigned long size) {\n    dict n; /* the new hashtable */\n    unsigned long realsize = _dictNextPower(size), i;\n\n    /* the size is invalid if it is smaller than the number of\n     * elements already inside the hashtable */\n    if (ht->used > size)\n        return DICT_ERR;\n\n    _dictInit(&n, ht->type, ht->privdata);\n    n.size = realsize;\n    n.sizemask = realsize-1;\n    n.table = calloc(realsize,sizeof(dictEntry*));\n\n    /* Copy all the elements from the old to the new table:\n     * note that if the old hash table is empty ht->size is zero,\n     * so dictExpand just creates an hash table. */\n    n.used = ht->used;\n    for (i = 0; i < ht->size && ht->used > 0; i++) {\n        dictEntry *he, *nextHe;\n\n        if (ht->table[i] == NULL) continue;\n\n        /* For each hash entry on this slot... */\n        he = ht->table[i];\n        while(he) {\n            unsigned int h;\n\n            nextHe = he->next;\n            /* Get the new element index */\n            h = dictHashKey(ht, he->key) & n.sizemask;\n            he->next = n.table[h];\n            n.table[h] = he;\n            ht->used--;\n            /* Pass to the next element */\n            he = nextHe;\n        }\n    }\n    assert(ht->used == 0);\n    free(ht->table);\n\n    /* Remap the new hashtable in the old */\n    *ht = n;\n    return DICT_OK;\n}\n\n/* Add an element to the target hash table */\nstatic int dictAdd(dict *ht, void *key, void *val) {\n    int index;\n    dictEntry *entry;\n\n    /* Get the index of the new element, or -1 if\n     * the element already exists. */\n    if ((index = _dictKeyIndex(ht, key)) == -1)\n        return DICT_ERR;\n\n    /* Allocates the memory and stores key */\n    entry = malloc(sizeof(*entry));\n    entry->next = ht->table[index];\n    ht->table[index] = entry;\n\n    /* Set the hash entry fields. */\n    dictSetHashKey(ht, entry, key);\n    dictSetHashVal(ht, entry, val);\n    ht->used++;\n    return DICT_OK;\n}\n\n/* Add an element, discarding the old if the key already exists.\n * Return 1 if the key was added from scratch, 0 if there was already an\n * element with such key and dictReplace() just performed a value update\n * operation. */\nstatic int dictReplace(dict *ht, void *key, void *val) {\n    dictEntry *entry, auxentry;\n\n    /* Try to add the element. If the key\n     * does not exists dictAdd will suceed. */\n    if (dictAdd(ht, key, val) == DICT_OK)\n        return 1;\n    /* It already exists, get the entry */\n    entry = dictFind(ht, key);\n    /* Free the old value and set the new one */\n    /* Set the new value and free the old one. Note that it is important\n     * to do that in this order, as the value may just be exactly the same\n     * as the previous one. In this context, think to reference counting,\n     * you want to increment (set), and then decrement (free), and not the\n     * reverse. */\n    auxentry = *entry;\n    dictSetHashVal(ht, entry, val);\n    dictFreeEntryVal(ht, &auxentry);\n    return 0;\n}\n\n/* Search and remove an element */\nstatic int dictDelete(dict *ht, const void *key) {\n    unsigned int h;\n    dictEntry *de, *prevde;\n\n    if (ht->size == 0)\n        return DICT_ERR;\n    h = dictHashKey(ht, key) & ht->sizemask;\n    de = ht->table[h];\n\n    prevde = NULL;\n    while(de) {\n        if (dictCompareHashKeys(ht,key,de->key)) {\n            /* Unlink the element from the list */\n            if (prevde)\n                prevde->next = de->next;\n            else\n                ht->table[h] = de->next;\n\n            dictFreeEntryKey(ht,de);\n            dictFreeEntryVal(ht,de);\n            free(de);\n            ht->used--;\n            return DICT_OK;\n        }\n        prevde = de;\n        de = de->next;\n    }\n    return DICT_ERR; /* not found */\n}\n\n/* Destroy an entire hash table */\nstatic int _dictClear(dict *ht) {\n    unsigned long i;\n\n    /* Free all the elements */\n    for (i = 0; i < ht->size && ht->used > 0; i++) {\n        dictEntry *he, *nextHe;\n\n        if ((he = ht->table[i]) == NULL) continue;\n        while(he) {\n            nextHe = he->next;\n            dictFreeEntryKey(ht, he);\n            dictFreeEntryVal(ht, he);\n            free(he);\n            ht->used--;\n            he = nextHe;\n        }\n    }\n    /* Free the table and the allocated cache structure */\n    free(ht->table);\n    /* Re-initialize the table */\n    _dictReset(ht);\n    return DICT_OK; /* never fails */\n}\n\n/* Clear & Release the hash table */\nstatic void dictRelease(dict *ht) {\n    _dictClear(ht);\n    free(ht);\n}\n\nstatic dictEntry *dictFind(dict *ht, const void *key) {\n    dictEntry *he;\n    unsigned int h;\n\n    if (ht->size == 0) return NULL;\n    h = dictHashKey(ht, key) & ht->sizemask;\n    he = ht->table[h];\n    while(he) {\n        if (dictCompareHashKeys(ht, key, he->key))\n            return he;\n        he = he->next;\n    }\n    return NULL;\n}\n\nstatic dictIterator *dictGetIterator(dict *ht) {\n    dictIterator *iter = malloc(sizeof(*iter));\n\n    iter->ht = ht;\n    iter->index = -1;\n    iter->entry = NULL;\n    iter->nextEntry = NULL;\n    return iter;\n}\n\nstatic dictEntry *dictNext(dictIterator *iter) {\n    while (1) {\n        if (iter->entry == NULL) {\n            iter->index++;\n            if (iter->index >=\n                    (signed)iter->ht->size) break;\n            iter->entry = iter->ht->table[iter->index];\n        } else {\n            iter->entry = iter->nextEntry;\n        }\n        if (iter->entry) {\n            /* We need to save the 'next' here, the iterator user\n             * may delete the entry we are returning. */\n            iter->nextEntry = iter->entry->next;\n            return iter->entry;\n        }\n    }\n    return NULL;\n}\n\nstatic void dictReleaseIterator(dictIterator *iter) {\n    free(iter);\n}\n\n/* ------------------------- private functions ------------------------------ */\n\n/* Expand the hash table if needed */\nstatic int _dictExpandIfNeeded(dict *ht) {\n    /* If the hash table is empty expand it to the intial size,\n     * if the table is \"full\" dobule its size. */\n    if (ht->size == 0)\n        return dictExpand(ht, DICT_HT_INITIAL_SIZE);\n    if (ht->used == ht->size)\n        return dictExpand(ht, ht->size*2);\n    return DICT_OK;\n}\n\n/* Our hash table capability is a power of two */\nstatic unsigned long _dictNextPower(unsigned long size) {\n    unsigned long i = DICT_HT_INITIAL_SIZE;\n\n    if (size >= LONG_MAX) return LONG_MAX;\n    while(1) {\n        if (i >= size)\n            return i;\n        i *= 2;\n    }\n}\n\n/* Returns the index of a free slot that can be populated with\n * an hash entry for the given 'key'.\n * If the key already exists, -1 is returned. */\nstatic int _dictKeyIndex(dict *ht, const void *key) {\n    unsigned int h;\n    dictEntry *he;\n\n    /* Expand the hashtable if needed */\n    if (_dictExpandIfNeeded(ht) == DICT_ERR)\n        return -1;\n    /* Compute the key hash value */\n    h = dictHashKey(ht, key) & ht->sizemask;\n    /* Search if this slot does not already contain the given key */\n    he = ht->table[h];\n    while(he) {\n        if (dictCompareHashKeys(ht, key, he->key))\n            return -1;\n        he = he->next;\n    }\n    return h;\n}\n\n"
  },
  {
    "path": "extern/deprecated/redis-2.8.21/deps/hiredis/dict.h",
    "content": "/* Hash table implementation.\n *\n * This file implements in memory hash tables with insert/del/replace/find/\n * get-random-element operations. Hash tables will auto resize if needed\n * tables of power of two in size are used, collisions are handled by\n * chaining. See the source code for more information... :)\n *\n * Copyright (c) 2006-2010, Salvatore Sanfilippo <antirez at gmail dot com>\n * All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions are met:\n *\n *   * Redistributions of source code must retain the above copyright notice,\n *     this list of conditions and the following disclaimer.\n *   * Redistributions in binary form must reproduce the above copyright\n *     notice, this list of conditions and the following disclaimer in the\n *     documentation and/or other materials provided with the distribution.\n *   * Neither the name of Redis nor the names of its contributors may be used\n *     to endorse or promote products derived from this software without\n *     specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\"\n * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\n * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE\n * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR\n * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF\n * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS\n * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN\n * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)\n * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE\n * POSSIBILITY OF SUCH DAMAGE.\n */\n\n#ifndef __DICT_H\n#define __DICT_H\n\n#define DICT_OK 0\n#define DICT_ERR 1\n\n/* Unused arguments generate annoying warnings... */\n#define DICT_NOTUSED(V) ((void) V)\n\ntypedef struct dictEntry {\n    void *key;\n    void *val;\n    struct dictEntry *next;\n} dictEntry;\n\ntypedef struct dictType {\n    unsigned int (*hashFunction)(const void *key);\n    void *(*keyDup)(void *privdata, const void *key);\n    void *(*valDup)(void *privdata, const void *obj);\n    int (*keyCompare)(void *privdata, const void *key1, const void *key2);\n    void (*keyDestructor)(void *privdata, void *key);\n    void (*valDestructor)(void *privdata, void *obj);\n} dictType;\n\ntypedef struct dict {\n    dictEntry **table;\n    dictType *type;\n    unsigned long size;\n    unsigned long sizemask;\n    unsigned long used;\n    void *privdata;\n} dict;\n\ntypedef struct dictIterator {\n    dict *ht;\n    int index;\n    dictEntry *entry, *nextEntry;\n} dictIterator;\n\n/* This is the initial size of every hash table */\n#define DICT_HT_INITIAL_SIZE     4\n\n/* ------------------------------- Macros ------------------------------------*/\n#define dictFreeEntryVal(ht, entry) \\\n    if ((ht)->type->valDestructor) \\\n        (ht)->type->valDestructor((ht)->privdata, (entry)->val)\n\n#define dictSetHashVal(ht, entry, _val_) do { \\\n    if ((ht)->type->valDup) \\\n        entry->val = (ht)->type->valDup((ht)->privdata, _val_); \\\n    else \\\n        entry->val = (_val_); \\\n} while(0)\n\n#define dictFreeEntryKey(ht, entry) \\\n    if ((ht)->type->keyDestructor) \\\n        (ht)->type->keyDestructor((ht)->privdata, (entry)->key)\n\n#define dictSetHashKey(ht, entry, _key_) do { \\\n    if ((ht)->type->keyDup) \\\n        entry->key = (ht)->type->keyDup((ht)->privdata, _key_); \\\n    else \\\n        entry->key = (_key_); \\\n} while(0)\n\n#define dictCompareHashKeys(ht, key1, key2) \\\n    (((ht)->type->keyCompare) ? \\\n        (ht)->type->keyCompare((ht)->privdata, key1, key2) : \\\n        (key1) == (key2))\n\n#define dictHashKey(ht, key) (ht)->type->hashFunction(key)\n\n#define dictGetEntryKey(he) ((he)->key)\n#define dictGetEntryVal(he) ((he)->val)\n#define dictSlots(ht) ((ht)->size)\n#define dictSize(ht) ((ht)->used)\n\n/* API */\nstatic unsigned int dictGenHashFunction(const unsigned char *buf, int len);\nstatic dict *dictCreate(dictType *type, void *privDataPtr);\nstatic int dictExpand(dict *ht, unsigned long size);\nstatic int dictAdd(dict *ht, void *key, void *val);\nstatic int dictReplace(dict *ht, void *key, void *val);\nstatic int dictDelete(dict *ht, const void *key);\nstatic void dictRelease(dict *ht);\nstatic dictEntry * dictFind(dict *ht, const void *key);\nstatic dictIterator *dictGetIterator(dict *ht);\nstatic dictEntry *dictNext(dictIterator *iter);\nstatic void dictReleaseIterator(dictIterator *iter);\n\n#endif /* __DICT_H */\n"
  },
  {
    "path": "extern/deprecated/redis-2.8.21/deps/hiredis/examples/example-ae.c",
    "content": "#include <stdio.h>\n#include <stdlib.h>\n#include <string.h>\n#include <signal.h>\n\n#include <hiredis.h>\n#include <async.h>\n#include <adapters/ae.h>\n\n/* Put event loop in the global scope, so it can be explicitly stopped */\nstatic aeEventLoop *loop;\n\nvoid getCallback(redisAsyncContext *c, void *r, void *privdata) {\n    redisReply *reply = r;\n    if (reply == NULL) return;\n    printf(\"argv[%s]: %s\\n\", (char*)privdata, reply->str);\n\n    /* Disconnect after receiving the reply to GET */\n    redisAsyncDisconnect(c);\n}\n\nvoid connectCallback(const redisAsyncContext *c, int status) {\n    if (status != REDIS_OK) {\n        printf(\"Error: %s\\n\", c->errstr);\n        aeStop(loop);\n        return;\n    }\n\n    printf(\"Connected...\\n\");\n}\n\nvoid disconnectCallback(const redisAsyncContext *c, int status) {\n    if (status != REDIS_OK) {\n        printf(\"Error: %s\\n\", c->errstr);\n        aeStop(loop);\n        return;\n    }\n\n    printf(\"Disconnected...\\n\");\n    aeStop(loop);\n}\n\nint main (int argc, char **argv) {\n    signal(SIGPIPE, SIG_IGN);\n\n    redisAsyncContext *c = redisAsyncConnect(\"127.0.0.1\", 6379);\n    if (c->err) {\n        /* Let *c leak for now... */\n        printf(\"Error: %s\\n\", c->errstr);\n        return 1;\n    }\n\n    loop = aeCreateEventLoop(64);\n    redisAeAttach(loop, c);\n    redisAsyncSetConnectCallback(c,connectCallback);\n    redisAsyncSetDisconnectCallback(c,disconnectCallback);\n    redisAsyncCommand(c, NULL, NULL, \"SET key %b\", argv[argc-1], strlen(argv[argc-1]));\n    redisAsyncCommand(c, getCallback, (char*)\"end-1\", \"GET key\");\n    aeMain(loop);\n    return 0;\n}\n\n"
  },
  {
    "path": "extern/deprecated/redis-2.8.21/deps/hiredis/examples/example-libev.c",
    "content": "#include <stdio.h>\n#include <stdlib.h>\n#include <string.h>\n#include <signal.h>\n\n#include <hiredis.h>\n#include <async.h>\n#include <adapters/libev.h>\n\nvoid getCallback(redisAsyncContext *c, void *r, void *privdata) {\n    redisReply *reply = r;\n    if (reply == NULL) return;\n    printf(\"argv[%s]: %s\\n\", (char*)privdata, reply->str);\n\n    /* Disconnect after receiving the reply to GET */\n    redisAsyncDisconnect(c);\n}\n\nvoid connectCallback(const redisAsyncContext *c, int status) {\n    if (status != REDIS_OK) {\n        printf(\"Error: %s\\n\", c->errstr);\n        return;\n    }\n    printf(\"Connected...\\n\");\n}\n\nvoid disconnectCallback(const redisAsyncContext *c, int status) {\n    if (status != REDIS_OK) {\n        printf(\"Error: %s\\n\", c->errstr);\n        return;\n    }\n    printf(\"Disconnected...\\n\");\n}\n\nint main (int argc, char **argv) {\n    signal(SIGPIPE, SIG_IGN);\n\n    redisAsyncContext *c = redisAsyncConnect(\"127.0.0.1\", 6379);\n    if (c->err) {\n        /* Let *c leak for now... */\n        printf(\"Error: %s\\n\", c->errstr);\n        return 1;\n    }\n\n    redisLibevAttach(EV_DEFAULT_ c);\n    redisAsyncSetConnectCallback(c,connectCallback);\n    redisAsyncSetDisconnectCallback(c,disconnectCallback);\n    redisAsyncCommand(c, NULL, NULL, \"SET key %b\", argv[argc-1], strlen(argv[argc-1]));\n    redisAsyncCommand(c, getCallback, (char*)\"end-1\", \"GET key\");\n    ev_loop(EV_DEFAULT_ 0);\n    return 0;\n}\n"
  },
  {
    "path": "extern/deprecated/redis-2.8.21/deps/hiredis/examples/example-libevent.c",
    "content": "#include <stdio.h>\n#include <stdlib.h>\n#include <string.h>\n#include <signal.h>\n\n#include <hiredis.h>\n#include <async.h>\n#include <adapters/libevent.h>\n\nvoid getCallback(redisAsyncContext *c, void *r, void *privdata) {\n    redisReply *reply = r;\n    if (reply == NULL) return;\n    printf(\"argv[%s]: %s\\n\", (char*)privdata, reply->str);\n\n    /* Disconnect after receiving the reply to GET */\n    redisAsyncDisconnect(c);\n}\n\nvoid connectCallback(const redisAsyncContext *c, int status) {\n    if (status != REDIS_OK) {\n        printf(\"Error: %s\\n\", c->errstr);\n        return;\n    }\n    printf(\"Connected...\\n\");\n}\n\nvoid disconnectCallback(const redisAsyncContext *c, int status) {\n    if (status != REDIS_OK) {\n        printf(\"Error: %s\\n\", c->errstr);\n        return;\n    }\n    printf(\"Disconnected...\\n\");\n}\n\nint main (int argc, char **argv) {\n    signal(SIGPIPE, SIG_IGN);\n    struct event_base *base = event_base_new();\n\n    redisAsyncContext *c = redisAsyncConnect(\"127.0.0.1\", 6379);\n    if (c->err) {\n        /* Let *c leak for now... */\n        printf(\"Error: %s\\n\", c->errstr);\n        return 1;\n    }\n\n    redisLibeventAttach(c,base);\n    redisAsyncSetConnectCallback(c,connectCallback);\n    redisAsyncSetDisconnectCallback(c,disconnectCallback);\n    redisAsyncCommand(c, NULL, NULL, \"SET key %b\", argv[argc-1], strlen(argv[argc-1]));\n    redisAsyncCommand(c, getCallback, (char*)\"end-1\", \"GET key\");\n    event_base_dispatch(base);\n    return 0;\n}\n"
  },
  {
    "path": "extern/deprecated/redis-2.8.21/deps/hiredis/examples/example-libuv.c",
    "content": "#include <stdio.h>\n#include <stdlib.h>\n#include <string.h>\n#include <signal.h>\n\n#include <hiredis.h>\n#include <async.h>\n#include <adapters/libuv.h>\n\nvoid getCallback(redisAsyncContext *c, void *r, void *privdata) {\n    redisReply *reply = r;\n    if (reply == NULL) return;\n    printf(\"argv[%s]: %s\\n\", (char*)privdata, reply->str);\n\n    /* Disconnect after receiving the reply to GET */\n    redisAsyncDisconnect(c);\n}\n\nvoid connectCallback(const redisAsyncContext *c, int status) {\n    if (status != REDIS_OK) {\n        printf(\"Error: %s\\n\", c->errstr);\n        return;\n    }\n    printf(\"Connected...\\n\");\n}\n\nvoid disconnectCallback(const redisAsyncContext *c, int status) {\n    if (status != REDIS_OK) {\n        printf(\"Error: %s\\n\", c->errstr);\n        return;\n    }\n    printf(\"Disconnected...\\n\");\n}\n\nint main (int argc, char **argv) {\n    signal(SIGPIPE, SIG_IGN);\n    uv_loop_t* loop = uv_default_loop();\n\n    redisAsyncContext *c = redisAsyncConnect(\"127.0.0.1\", 6379);\n    if (c->err) {\n        /* Let *c leak for now... */\n        printf(\"Error: %s\\n\", c->errstr);\n        return 1;\n    }\n\n    redisLibuvAttach(c,loop);\n    redisAsyncSetConnectCallback(c,connectCallback);\n    redisAsyncSetDisconnectCallback(c,disconnectCallback);\n    redisAsyncCommand(c, NULL, NULL, \"SET key %b\", argv[argc-1], strlen(argv[argc-1]));\n    redisAsyncCommand(c, getCallback, (char*)\"end-1\", \"GET key\");\n    uv_run(loop, UV_RUN_DEFAULT);\n    return 0;\n}\n"
  },
  {
    "path": "extern/deprecated/redis-2.8.21/deps/hiredis/examples/example.c",
    "content": "#include <stdio.h>\n#include <stdlib.h>\n#include <string.h>\n\n#include <hiredis.h>\n\nint main(int argc, char **argv) {\n    unsigned int j;\n    redisContext *c;\n    redisReply *reply;\n    const char *hostname = (argc > 1) ? argv[1] : \"127.0.0.1\";\n    int port = (argc > 2) ? atoi(argv[2]) : 6379;\n\n    struct timeval timeout = { 1, 500000 }; // 1.5 seconds\n    c = redisConnectWithTimeout(hostname, port, timeout);\n    if (c == NULL || c->err) {\n        if (c) {\n            printf(\"Connection error: %s\\n\", c->errstr);\n            redisFree(c);\n        } else {\n            printf(\"Connection error: can't allocate redis context\\n\");\n        }\n        exit(1);\n    }\n\n    /* PING server */\n    reply = redisCommand(c,\"PING\");\n    printf(\"PING: %s\\n\", reply->str);\n    freeReplyObject(reply);\n\n    /* Set a key */\n    reply = redisCommand(c,\"SET %s %s\", \"foo\", \"hello world\");\n    printf(\"SET: %s\\n\", reply->str);\n    freeReplyObject(reply);\n\n    /* Set a key using binary safe API */\n    reply = redisCommand(c,\"SET %b %b\", \"bar\", (size_t) 3, \"hello\", (size_t) 5);\n    printf(\"SET (binary API): %s\\n\", reply->str);\n    freeReplyObject(reply);\n\n    /* Try a GET and two INCR */\n    reply = redisCommand(c,\"GET foo\");\n    printf(\"GET foo: %s\\n\", reply->str);\n    freeReplyObject(reply);\n\n    reply = redisCommand(c,\"INCR counter\");\n    printf(\"INCR counter: %lld\\n\", reply->integer);\n    freeReplyObject(reply);\n    /* again ... */\n    reply = redisCommand(c,\"INCR counter\");\n    printf(\"INCR counter: %lld\\n\", reply->integer);\n    freeReplyObject(reply);\n\n    /* Create a list of numbers, from 0 to 9 */\n    reply = redisCommand(c,\"DEL mylist\");\n    freeReplyObject(reply);\n    for (j = 0; j < 10; j++) {\n        char buf[64];\n\n        snprintf(buf,64,\"%d\",j);\n        reply = redisCommand(c,\"LPUSH mylist element-%s\", buf);\n        freeReplyObject(reply);\n    }\n\n    /* Let's check what we have inside the list */\n    reply = redisCommand(c,\"LRANGE mylist 0 -1\");\n    if (reply->type == REDIS_REPLY_ARRAY) {\n        for (j = 0; j < reply->elements; j++) {\n            printf(\"%u) %s\\n\", j, reply->element[j]->str);\n        }\n    }\n    freeReplyObject(reply);\n\n    /* Disconnects and frees the context */\n    redisFree(c);\n\n    return 0;\n}\n"
  },
  {
    "path": "extern/deprecated/redis-2.8.21/deps/hiredis/fmacros.h",
    "content": "#ifndef __HIREDIS_FMACRO_H\n#define __HIREDIS_FMACRO_H\n\n#if !defined(_BSD_SOURCE)\n#define _BSD_SOURCE\n#endif\n\n#if defined(_AIX)\n#define _ALL_SOURCE\n#endif\n\n#if defined(__sun__)\n#define _POSIX_C_SOURCE 200112L\n#elif defined(__linux__) || defined(__OpenBSD__) || defined(__NetBSD__)\n#define _XOPEN_SOURCE 600\n#else\n#define _XOPEN_SOURCE\n#endif\n\n#if __APPLE__ && __MACH__\n#define _OSX\n#endif\n\n#endif\n"
  },
  {
    "path": "extern/deprecated/redis-2.8.21/deps/hiredis/hiredis.c",
    "content": "/*\n * Copyright (c) 2009-2011, Salvatore Sanfilippo <antirez at gmail dot com>\n * Copyright (c) 2010-2011, Pieter Noordhuis <pcnoordhuis at gmail dot com>\n *\n * All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions are met:\n *\n *   * Redistributions of source code must retain the above copyright notice,\n *     this list of conditions and the following disclaimer.\n *   * Redistributions in binary form must reproduce the above copyright\n *     notice, this list of conditions and the following disclaimer in the\n *     documentation and/or other materials provided with the distribution.\n *   * Neither the name of Redis nor the names of its contributors may be used\n *     to endorse or promote products derived from this software without\n *     specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\"\n * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\n * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE\n * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR\n * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF\n * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS\n * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN\n * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)\n * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE\n * POSSIBILITY OF SUCH DAMAGE.\n */\n\n#include \"fmacros.h\"\n#include <string.h>\n#include <stdlib.h>\n#include <unistd.h>\n#include <assert.h>\n#include <errno.h>\n#include <ctype.h>\n\n#include \"hiredis.h\"\n#include \"net.h\"\n#include \"sds.h\"\n\nstatic redisReply *createReplyObject(int type);\nstatic void *createStringObject(const redisReadTask *task, char *str, size_t len);\nstatic void *createArrayObject(const redisReadTask *task, int elements);\nstatic void *createIntegerObject(const redisReadTask *task, long long value);\nstatic void *createNilObject(const redisReadTask *task);\n\n/* Default set of functions to build the reply. Keep in mind that such a\n * function returning NULL is interpreted as OOM. */\nstatic redisReplyObjectFunctions defaultFunctions = {\n    createStringObject,\n    createArrayObject,\n    createIntegerObject,\n    createNilObject,\n    freeReplyObject\n};\n\n/* Create a reply object */\nstatic redisReply *createReplyObject(int type) {\n    redisReply *r = calloc(1,sizeof(*r));\n\n    if (r == NULL)\n        return NULL;\n\n    r->type = type;\n    return r;\n}\n\n/* Free a reply object */\nvoid freeReplyObject(void *reply) {\n    redisReply *r = reply;\n    size_t j;\n\n    switch(r->type) {\n    case REDIS_REPLY_INTEGER:\n        break; /* Nothing to free */\n    case REDIS_REPLY_ARRAY:\n        if (r->element != NULL) {\n            for (j = 0; j < r->elements; j++)\n                if (r->element[j] != NULL)\n                    freeReplyObject(r->element[j]);\n            free(r->element);\n        }\n        break;\n    case REDIS_REPLY_ERROR:\n    case REDIS_REPLY_STATUS:\n    case REDIS_REPLY_STRING:\n        if (r->str != NULL)\n            free(r->str);\n        break;\n    }\n    free(r);\n}\n\nstatic void *createStringObject(const redisReadTask *task, char *str, size_t len) {\n    redisReply *r, *parent;\n    char *buf;\n\n    r = createReplyObject(task->type);\n    if (r == NULL)\n        return NULL;\n\n    buf = malloc(len+1);\n    if (buf == NULL) {\n        freeReplyObject(r);\n        return NULL;\n    }\n\n    assert(task->type == REDIS_REPLY_ERROR  ||\n           task->type == REDIS_REPLY_STATUS ||\n           task->type == REDIS_REPLY_STRING);\n\n    /* Copy string value */\n    memcpy(buf,str,len);\n    buf[len] = '\\0';\n    r->str = buf;\n    r->len = len;\n\n    if (task->parent) {\n        parent = task->parent->obj;\n        assert(parent->type == REDIS_REPLY_ARRAY);\n        parent->element[task->idx] = r;\n    }\n    return r;\n}\n\nstatic void *createArrayObject(const redisReadTask *task, int elements) {\n    redisReply *r, *parent;\n\n    r = createReplyObject(REDIS_REPLY_ARRAY);\n    if (r == NULL)\n        return NULL;\n\n    if (elements > 0) {\n        r->element = calloc(elements,sizeof(redisReply*));\n        if (r->element == NULL) {\n            freeReplyObject(r);\n            return NULL;\n        }\n    }\n\n    r->elements = elements;\n\n    if (task->parent) {\n        parent = task->parent->obj;\n        assert(parent->type == REDIS_REPLY_ARRAY);\n        parent->element[task->idx] = r;\n    }\n    return r;\n}\n\nstatic void *createIntegerObject(const redisReadTask *task, long long value) {\n    redisReply *r, *parent;\n\n    r = createReplyObject(REDIS_REPLY_INTEGER);\n    if (r == NULL)\n        return NULL;\n\n    r->integer = value;\n\n    if (task->parent) {\n        parent = task->parent->obj;\n        assert(parent->type == REDIS_REPLY_ARRAY);\n        parent->element[task->idx] = r;\n    }\n    return r;\n}\n\nstatic void *createNilObject(const redisReadTask *task) {\n    redisReply *r, *parent;\n\n    r = createReplyObject(REDIS_REPLY_NIL);\n    if (r == NULL)\n        return NULL;\n\n    if (task->parent) {\n        parent = task->parent->obj;\n        assert(parent->type == REDIS_REPLY_ARRAY);\n        parent->element[task->idx] = r;\n    }\n    return r;\n}\n\nstatic void __redisReaderSetError(redisReader *r, int type, const char *str) {\n    size_t len;\n\n    if (r->reply != NULL && r->fn && r->fn->freeObject) {\n        r->fn->freeObject(r->reply);\n        r->reply = NULL;\n    }\n\n    /* Clear input buffer on errors. */\n    if (r->buf != NULL) {\n        sdsfree(r->buf);\n        r->buf = NULL;\n        r->pos = r->len = 0;\n    }\n\n    /* Reset task stack. */\n    r->ridx = -1;\n\n    /* Set error. */\n    r->err = type;\n    len = strlen(str);\n    len = len < (sizeof(r->errstr)-1) ? len : (sizeof(r->errstr)-1);\n    memcpy(r->errstr,str,len);\n    r->errstr[len] = '\\0';\n}\n\nstatic size_t chrtos(char *buf, size_t size, char byte) {\n    size_t len = 0;\n\n    switch(byte) {\n    case '\\\\':\n    case '\"':\n        len = snprintf(buf,size,\"\\\"\\\\%c\\\"\",byte);\n        break;\n    case '\\n': len = snprintf(buf,size,\"\\\"\\\\n\\\"\"); break;\n    case '\\r': len = snprintf(buf,size,\"\\\"\\\\r\\\"\"); break;\n    case '\\t': len = snprintf(buf,size,\"\\\"\\\\t\\\"\"); break;\n    case '\\a': len = snprintf(buf,size,\"\\\"\\\\a\\\"\"); break;\n    case '\\b': len = snprintf(buf,size,\"\\\"\\\\b\\\"\"); break;\n    default:\n        if (isprint(byte))\n            len = snprintf(buf,size,\"\\\"%c\\\"\",byte);\n        else\n            len = snprintf(buf,size,\"\\\"\\\\x%02x\\\"\",(unsigned char)byte);\n        break;\n    }\n\n    return len;\n}\n\nstatic void __redisReaderSetErrorProtocolByte(redisReader *r, char byte) {\n    char cbuf[8], sbuf[128];\n\n    chrtos(cbuf,sizeof(cbuf),byte);\n    snprintf(sbuf,sizeof(sbuf),\n        \"Protocol error, got %s as reply type byte\", cbuf);\n    __redisReaderSetError(r,REDIS_ERR_PROTOCOL,sbuf);\n}\n\nstatic void __redisReaderSetErrorOOM(redisReader *r) {\n    __redisReaderSetError(r,REDIS_ERR_OOM,\"Out of memory\");\n}\n\nstatic char *readBytes(redisReader *r, unsigned int bytes) {\n    char *p;\n    if (r->len-r->pos >= bytes) {\n        p = r->buf+r->pos;\n        r->pos += bytes;\n        return p;\n    }\n    return NULL;\n}\n\n/* Find pointer to \\r\\n. */\nstatic char *seekNewline(char *s, size_t len) {\n    int pos = 0;\n    int _len = len-1;\n\n    /* Position should be < len-1 because the character at \"pos\" should be\n     * followed by a \\n. Note that strchr cannot be used because it doesn't\n     * allow to search a limited length and the buffer that is being searched\n     * might not have a trailing NULL character. */\n    while (pos < _len) {\n        while(pos < _len && s[pos] != '\\r') pos++;\n        if (s[pos] != '\\r') {\n            /* Not found. */\n            return NULL;\n        } else {\n            if (s[pos+1] == '\\n') {\n                /* Found. */\n                return s+pos;\n            } else {\n                /* Continue searching. */\n                pos++;\n            }\n        }\n    }\n    return NULL;\n}\n\n/* Read a long long value starting at *s, under the assumption that it will be\n * terminated by \\r\\n. Ambiguously returns -1 for unexpected input. */\nstatic long long readLongLong(char *s) {\n    long long v = 0;\n    int dec, mult = 1;\n    char c;\n\n    if (*s == '-') {\n        mult = -1;\n        s++;\n    } else if (*s == '+') {\n        mult = 1;\n        s++;\n    }\n\n    while ((c = *(s++)) != '\\r') {\n        dec = c - '0';\n        if (dec >= 0 && dec < 10) {\n            v *= 10;\n            v += dec;\n        } else {\n            /* Should not happen... */\n            return -1;\n        }\n    }\n\n    return mult*v;\n}\n\nstatic char *readLine(redisReader *r, int *_len) {\n    char *p, *s;\n    int len;\n\n    p = r->buf+r->pos;\n    s = seekNewline(p,(r->len-r->pos));\n    if (s != NULL) {\n        len = s-(r->buf+r->pos);\n        r->pos += len+2; /* skip \\r\\n */\n        if (_len) *_len = len;\n        return p;\n    }\n    return NULL;\n}\n\nstatic void moveToNextTask(redisReader *r) {\n    redisReadTask *cur, *prv;\n    while (r->ridx >= 0) {\n        /* Return a.s.a.p. when the stack is now empty. */\n        if (r->ridx == 0) {\n            r->ridx--;\n            return;\n        }\n\n        cur = &(r->rstack[r->ridx]);\n        prv = &(r->rstack[r->ridx-1]);\n        assert(prv->type == REDIS_REPLY_ARRAY);\n        if (cur->idx == prv->elements-1) {\n            r->ridx--;\n        } else {\n            /* Reset the type because the next item can be anything */\n            assert(cur->idx < prv->elements);\n            cur->type = -1;\n            cur->elements = -1;\n            cur->idx++;\n            return;\n        }\n    }\n}\n\nstatic int processLineItem(redisReader *r) {\n    redisReadTask *cur = &(r->rstack[r->ridx]);\n    void *obj;\n    char *p;\n    int len;\n\n    if ((p = readLine(r,&len)) != NULL) {\n        if (cur->type == REDIS_REPLY_INTEGER) {\n            if (r->fn && r->fn->createInteger)\n                obj = r->fn->createInteger(cur,readLongLong(p));\n            else\n                obj = (void*)REDIS_REPLY_INTEGER;\n        } else {\n            /* Type will be error or status. */\n            if (r->fn && r->fn->createString)\n                obj = r->fn->createString(cur,p,len);\n            else\n                obj = (void*)(size_t)(cur->type);\n        }\n\n        if (obj == NULL) {\n            __redisReaderSetErrorOOM(r);\n            return REDIS_ERR;\n        }\n\n        /* Set reply if this is the root object. */\n        if (r->ridx == 0) r->reply = obj;\n        moveToNextTask(r);\n        return REDIS_OK;\n    }\n\n    return REDIS_ERR;\n}\n\nstatic int processBulkItem(redisReader *r) {\n    redisReadTask *cur = &(r->rstack[r->ridx]);\n    void *obj = NULL;\n    char *p, *s;\n    long len;\n    unsigned long bytelen;\n    int success = 0;\n\n    p = r->buf+r->pos;\n    s = seekNewline(p,r->len-r->pos);\n    if (s != NULL) {\n        p = r->buf+r->pos;\n        bytelen = s-(r->buf+r->pos)+2; /* include \\r\\n */\n        len = readLongLong(p);\n\n        if (len < 0) {\n            /* The nil object can always be created. */\n            if (r->fn && r->fn->createNil)\n                obj = r->fn->createNil(cur);\n            else\n                obj = (void*)REDIS_REPLY_NIL;\n            success = 1;\n        } else {\n            /* Only continue when the buffer contains the entire bulk item. */\n            bytelen += len+2; /* include \\r\\n */\n            if (r->pos+bytelen <= r->len) {\n                if (r->fn && r->fn->createString)\n                    obj = r->fn->createString(cur,s+2,len);\n                else\n                    obj = (void*)REDIS_REPLY_STRING;\n                success = 1;\n            }\n        }\n\n        /* Proceed when obj was created. */\n        if (success) {\n            if (obj == NULL) {\n                __redisReaderSetErrorOOM(r);\n                return REDIS_ERR;\n            }\n\n            r->pos += bytelen;\n\n            /* Set reply if this is the root object. */\n            if (r->ridx == 0) r->reply = obj;\n            moveToNextTask(r);\n            return REDIS_OK;\n        }\n    }\n\n    return REDIS_ERR;\n}\n\nstatic int processMultiBulkItem(redisReader *r) {\n    redisReadTask *cur = &(r->rstack[r->ridx]);\n    void *obj;\n    char *p;\n    long elements;\n    int root = 0;\n\n    /* Set error for nested multi bulks with depth > 7 */\n    if (r->ridx == 8) {\n        __redisReaderSetError(r,REDIS_ERR_PROTOCOL,\n            \"No support for nested multi bulk replies with depth > 7\");\n        return REDIS_ERR;\n    }\n\n    if ((p = readLine(r,NULL)) != NULL) {\n        elements = readLongLong(p);\n        root = (r->ridx == 0);\n\n        if (elements == -1) {\n            if (r->fn && r->fn->createNil)\n                obj = r->fn->createNil(cur);\n            else\n                obj = (void*)REDIS_REPLY_NIL;\n\n            if (obj == NULL) {\n                __redisReaderSetErrorOOM(r);\n                return REDIS_ERR;\n            }\n\n            moveToNextTask(r);\n        } else {\n            if (r->fn && r->fn->createArray)\n                obj = r->fn->createArray(cur,elements);\n            else\n                obj = (void*)REDIS_REPLY_ARRAY;\n\n            if (obj == NULL) {\n                __redisReaderSetErrorOOM(r);\n                return REDIS_ERR;\n            }\n\n            /* Modify task stack when there are more than 0 elements. */\n            if (elements > 0) {\n                cur->elements = elements;\n                cur->obj = obj;\n                r->ridx++;\n                r->rstack[r->ridx].type = -1;\n                r->rstack[r->ridx].elements = -1;\n                r->rstack[r->ridx].idx = 0;\n                r->rstack[r->ridx].obj = NULL;\n                r->rstack[r->ridx].parent = cur;\n                r->rstack[r->ridx].privdata = r->privdata;\n            } else {\n                moveToNextTask(r);\n            }\n        }\n\n        /* Set reply if this is the root object. */\n        if (root) r->reply = obj;\n        return REDIS_OK;\n    }\n\n    return REDIS_ERR;\n}\n\nstatic int processItem(redisReader *r) {\n    redisReadTask *cur = &(r->rstack[r->ridx]);\n    char *p;\n\n    /* check if we need to read type */\n    if (cur->type < 0) {\n        if ((p = readBytes(r,1)) != NULL) {\n            switch (p[0]) {\n            case '-':\n                cur->type = REDIS_REPLY_ERROR;\n                break;\n            case '+':\n                cur->type = REDIS_REPLY_STATUS;\n                break;\n            case ':':\n                cur->type = REDIS_REPLY_INTEGER;\n                break;\n            case '$':\n                cur->type = REDIS_REPLY_STRING;\n                break;\n            case '*':\n                cur->type = REDIS_REPLY_ARRAY;\n                break;\n            default:\n                __redisReaderSetErrorProtocolByte(r,*p);\n                return REDIS_ERR;\n            }\n        } else {\n            /* could not consume 1 byte */\n            return REDIS_ERR;\n        }\n    }\n\n    /* process typed item */\n    switch(cur->type) {\n    case REDIS_REPLY_ERROR:\n    case REDIS_REPLY_STATUS:\n    case REDIS_REPLY_INTEGER:\n        return processLineItem(r);\n    case REDIS_REPLY_STRING:\n        return processBulkItem(r);\n    case REDIS_REPLY_ARRAY:\n        return processMultiBulkItem(r);\n    default:\n        assert(NULL);\n        return REDIS_ERR; /* Avoid warning. */\n    }\n}\n\nredisReader *redisReaderCreate(void) {\n    redisReader *r;\n\n    r = calloc(sizeof(redisReader),1);\n    if (r == NULL)\n        return NULL;\n\n    r->err = 0;\n    r->errstr[0] = '\\0';\n    r->fn = &defaultFunctions;\n    r->buf = sdsempty();\n    r->maxbuf = REDIS_READER_MAX_BUF;\n    if (r->buf == NULL) {\n        free(r);\n        return NULL;\n    }\n\n    r->ridx = -1;\n    return r;\n}\n\nvoid redisReaderFree(redisReader *r) {\n    if (r->reply != NULL && r->fn && r->fn->freeObject)\n        r->fn->freeObject(r->reply);\n    if (r->buf != NULL)\n        sdsfree(r->buf);\n    free(r);\n}\n\nint redisReaderFeed(redisReader *r, const char *buf, size_t len) {\n    sds newbuf;\n\n    /* Return early when this reader is in an erroneous state. */\n    if (r->err)\n        return REDIS_ERR;\n\n    /* Copy the provided buffer. */\n    if (buf != NULL && len >= 1) {\n        /* Destroy internal buffer when it is empty and is quite large. */\n        if (r->len == 0 && r->maxbuf != 0 && sdsavail(r->buf) > r->maxbuf) {\n            sdsfree(r->buf);\n            r->buf = sdsempty();\n            r->pos = 0;\n\n            /* r->buf should not be NULL since we just free'd a larger one. */\n            assert(r->buf != NULL);\n        }\n\n        newbuf = sdscatlen(r->buf,buf,len);\n        if (newbuf == NULL) {\n            __redisReaderSetErrorOOM(r);\n            return REDIS_ERR;\n        }\n\n        r->buf = newbuf;\n        r->len = sdslen(r->buf);\n    }\n\n    return REDIS_OK;\n}\n\nint redisReaderGetReply(redisReader *r, void **reply) {\n    /* Default target pointer to NULL. */\n    if (reply != NULL)\n        *reply = NULL;\n\n    /* Return early when this reader is in an erroneous state. */\n    if (r->err)\n        return REDIS_ERR;\n\n    /* When the buffer is empty, there will never be a reply. */\n    if (r->len == 0)\n        return REDIS_OK;\n\n    /* Set first item to process when the stack is empty. */\n    if (r->ridx == -1) {\n        r->rstack[0].type = -1;\n        r->rstack[0].elements = -1;\n        r->rstack[0].idx = -1;\n        r->rstack[0].obj = NULL;\n        r->rstack[0].parent = NULL;\n        r->rstack[0].privdata = r->privdata;\n        r->ridx = 0;\n    }\n\n    /* Process items in reply. */\n    while (r->ridx >= 0)\n        if (processItem(r) != REDIS_OK)\n            break;\n\n    /* Return ASAP when an error occurred. */\n    if (r->err)\n        return REDIS_ERR;\n\n    /* Discard part of the buffer when we've consumed at least 1k, to avoid\n     * doing unnecessary calls to memmove() in sds.c. */\n    if (r->pos >= 1024) {\n        sdsrange(r->buf,r->pos,-1);\n        r->pos = 0;\n        r->len = sdslen(r->buf);\n    }\n\n    /* Emit a reply when there is one. */\n    if (r->ridx == -1) {\n        if (reply != NULL)\n            *reply = r->reply;\n        r->reply = NULL;\n    }\n    return REDIS_OK;\n}\n\n/* Calculate the number of bytes needed to represent an integer as string. */\nstatic int intlen(int i) {\n    int len = 0;\n    if (i < 0) {\n        len++;\n        i = -i;\n    }\n    do {\n        len++;\n        i /= 10;\n    } while(i);\n    return len;\n}\n\n/* Helper that calculates the bulk length given a certain string length. */\nstatic size_t bulklen(size_t len) {\n    return 1+intlen(len)+2+len+2;\n}\n\nint redisvFormatCommand(char **target, const char *format, va_list ap) {\n    const char *c = format;\n    char *cmd = NULL; /* final command */\n    int pos; /* position in final command */\n    sds curarg, newarg; /* current argument */\n    int touched = 0; /* was the current argument touched? */\n    char **curargv = NULL, **newargv = NULL;\n    int argc = 0;\n    int totlen = 0;\n    int j;\n\n    /* Abort if there is not target to set */\n    if (target == NULL)\n        return -1;\n\n    /* Build the command string accordingly to protocol */\n    curarg = sdsempty();\n    if (curarg == NULL)\n        return -1;\n\n    while(*c != '\\0') {\n        if (*c != '%' || c[1] == '\\0') {\n            if (*c == ' ') {\n                if (touched) {\n                    newargv = realloc(curargv,sizeof(char*)*(argc+1));\n                    if (newargv == NULL) goto err;\n                    curargv = newargv;\n                    curargv[argc++] = curarg;\n                    totlen += bulklen(sdslen(curarg));\n\n                    /* curarg is put in argv so it can be overwritten. */\n                    curarg = sdsempty();\n                    if (curarg == NULL) goto err;\n                    touched = 0;\n                }\n            } else {\n                newarg = sdscatlen(curarg,c,1);\n                if (newarg == NULL) goto err;\n                curarg = newarg;\n                touched = 1;\n            }\n        } else {\n            char *arg;\n            size_t size;\n\n            /* Set newarg so it can be checked even if it is not touched. */\n            newarg = curarg;\n\n            switch(c[1]) {\n            case 's':\n                arg = va_arg(ap,char*);\n                size = strlen(arg);\n                if (size > 0)\n                    newarg = sdscatlen(curarg,arg,size);\n                break;\n            case 'b':\n                arg = va_arg(ap,char*);\n                size = va_arg(ap,size_t);\n                if (size > 0)\n                    newarg = sdscatlen(curarg,arg,size);\n                break;\n            case '%':\n                newarg = sdscat(curarg,\"%\");\n                break;\n            default:\n                /* Try to detect printf format */\n                {\n                    static const char intfmts[] = \"diouxX\";\n                    char _format[16];\n                    const char *_p = c+1;\n                    size_t _l = 0;\n                    va_list _cpy;\n\n                    /* Flags */\n                    if (*_p != '\\0' && *_p == '#') _p++;\n                    if (*_p != '\\0' && *_p == '0') _p++;\n                    if (*_p != '\\0' && *_p == '-') _p++;\n                    if (*_p != '\\0' && *_p == ' ') _p++;\n                    if (*_p != '\\0' && *_p == '+') _p++;\n\n                    /* Field width */\n                    while (*_p != '\\0' && isdigit(*_p)) _p++;\n\n                    /* Precision */\n                    if (*_p == '.') {\n                        _p++;\n                        while (*_p != '\\0' && isdigit(*_p)) _p++;\n                    }\n\n                    /* Copy va_list before consuming with va_arg */\n                    va_copy(_cpy,ap);\n\n                    /* Integer conversion (without modifiers) */\n                    if (strchr(intfmts,*_p) != NULL) {\n                        va_arg(ap,int);\n                        goto fmt_valid;\n                    }\n\n                    /* Double conversion (without modifiers) */\n                    if (strchr(\"eEfFgGaA\",*_p) != NULL) {\n                        va_arg(ap,double);\n                        goto fmt_valid;\n                    }\n\n                    /* Size: char */\n                    if (_p[0] == 'h' && _p[1] == 'h') {\n                        _p += 2;\n                        if (*_p != '\\0' && strchr(intfmts,*_p) != NULL) {\n                            va_arg(ap,int); /* char gets promoted to int */\n                            goto fmt_valid;\n                        }\n                        goto fmt_invalid;\n                    }\n\n                    /* Size: short */\n                    if (_p[0] == 'h') {\n                        _p += 1;\n                        if (*_p != '\\0' && strchr(intfmts,*_p) != NULL) {\n                            va_arg(ap,int); /* short gets promoted to int */\n                            goto fmt_valid;\n                        }\n                        goto fmt_invalid;\n                    }\n\n                    /* Size: long long */\n                    if (_p[0] == 'l' && _p[1] == 'l') {\n                        _p += 2;\n                        if (*_p != '\\0' && strchr(intfmts,*_p) != NULL) {\n                            va_arg(ap,long long);\n                            goto fmt_valid;\n                        }\n                        goto fmt_invalid;\n                    }\n\n                    /* Size: long */\n                    if (_p[0] == 'l') {\n                        _p += 1;\n                        if (*_p != '\\0' && strchr(intfmts,*_p) != NULL) {\n                            va_arg(ap,long);\n                            goto fmt_valid;\n                        }\n                        goto fmt_invalid;\n                    }\n\n                fmt_invalid:\n                    va_end(_cpy);\n                    goto err;\n\n                fmt_valid:\n                    _l = (_p+1)-c;\n                    if (_l < sizeof(_format)-2) {\n                        memcpy(_format,c,_l);\n                        _format[_l] = '\\0';\n                        newarg = sdscatvprintf(curarg,_format,_cpy);\n\n                        /* Update current position (note: outer blocks\n                         * increment c twice so compensate here) */\n                        c = _p-1;\n                    }\n\n                    va_end(_cpy);\n                    break;\n                }\n            }\n\n            if (newarg == NULL) goto err;\n            curarg = newarg;\n\n            touched = 1;\n            c++;\n        }\n        c++;\n    }\n\n    /* Add the last argument if needed */\n    if (touched) {\n        newargv = realloc(curargv,sizeof(char*)*(argc+1));\n        if (newargv == NULL) goto err;\n        curargv = newargv;\n        curargv[argc++] = curarg;\n        totlen += bulklen(sdslen(curarg));\n    } else {\n        sdsfree(curarg);\n    }\n\n    /* Clear curarg because it was put in curargv or was free'd. */\n    curarg = NULL;\n\n    /* Add bytes needed to hold multi bulk count */\n    totlen += 1+intlen(argc)+2;\n\n    /* Build the command at protocol level */\n    cmd = malloc(totlen+1);\n    if (cmd == NULL) goto err;\n\n    pos = sprintf(cmd,\"*%d\\r\\n\",argc);\n    for (j = 0; j < argc; j++) {\n        pos += sprintf(cmd+pos,\"$%zu\\r\\n\",sdslen(curargv[j]));\n        memcpy(cmd+pos,curargv[j],sdslen(curargv[j]));\n        pos += sdslen(curargv[j]);\n        sdsfree(curargv[j]);\n        cmd[pos++] = '\\r';\n        cmd[pos++] = '\\n';\n    }\n    assert(pos == totlen);\n    cmd[pos] = '\\0';\n\n    free(curargv);\n    *target = cmd;\n    return totlen;\n\nerr:\n    while(argc--)\n        sdsfree(curargv[argc]);\n    free(curargv);\n\n    if (curarg != NULL)\n        sdsfree(curarg);\n\n    /* No need to check cmd since it is the last statement that can fail,\n     * but do it anyway to be as defensive as possible. */\n    if (cmd != NULL)\n        free(cmd);\n\n    return -1;\n}\n\n/* Format a command according to the Redis protocol. This function\n * takes a format similar to printf:\n *\n * %s represents a C null terminated string you want to interpolate\n * %b represents a binary safe string\n *\n * When using %b you need to provide both the pointer to the string\n * and the length in bytes as a size_t. Examples:\n *\n * len = redisFormatCommand(target, \"GET %s\", mykey);\n * len = redisFormatCommand(target, \"SET %s %b\", mykey, myval, myvallen);\n */\nint redisFormatCommand(char **target, const char *format, ...) {\n    va_list ap;\n    int len;\n    va_start(ap,format);\n    len = redisvFormatCommand(target,format,ap);\n    va_end(ap);\n    return len;\n}\n\n/* Format a command according to the Redis protocol. This function takes the\n * number of arguments, an array with arguments and an array with their\n * lengths. If the latter is set to NULL, strlen will be used to compute the\n * argument lengths.\n */\nint redisFormatCommandArgv(char **target, int argc, const char **argv, const size_t *argvlen) {\n    char *cmd = NULL; /* final command */\n    int pos; /* position in final command */\n    size_t len;\n    int totlen, j;\n\n    /* Calculate number of bytes needed for the command */\n    totlen = 1+intlen(argc)+2;\n    for (j = 0; j < argc; j++) {\n        len = argvlen ? argvlen[j] : strlen(argv[j]);\n        totlen += bulklen(len);\n    }\n\n    /* Build the command at protocol level */\n    cmd = malloc(totlen+1);\n    if (cmd == NULL)\n        return -1;\n\n    pos = sprintf(cmd,\"*%d\\r\\n\",argc);\n    for (j = 0; j < argc; j++) {\n        len = argvlen ? argvlen[j] : strlen(argv[j]);\n        pos += sprintf(cmd+pos,\"$%zu\\r\\n\",len);\n        memcpy(cmd+pos,argv[j],len);\n        pos += len;\n        cmd[pos++] = '\\r';\n        cmd[pos++] = '\\n';\n    }\n    assert(pos == totlen);\n    cmd[pos] = '\\0';\n\n    *target = cmd;\n    return totlen;\n}\n\nvoid __redisSetError(redisContext *c, int type, const char *str) {\n    size_t len;\n\n    c->err = type;\n    if (str != NULL) {\n        len = strlen(str);\n        len = len < (sizeof(c->errstr)-1) ? len : (sizeof(c->errstr)-1);\n        memcpy(c->errstr,str,len);\n        c->errstr[len] = '\\0';\n    } else {\n        /* Only REDIS_ERR_IO may lack a description! */\n        assert(type == REDIS_ERR_IO);\n        strerror_r(errno,c->errstr,sizeof(c->errstr));\n    }\n}\n\nstatic redisContext *redisContextInit(void) {\n    redisContext *c;\n\n    c = calloc(1,sizeof(redisContext));\n    if (c == NULL)\n        return NULL;\n\n    c->err = 0;\n    c->errstr[0] = '\\0';\n    c->obuf = sdsempty();\n    c->reader = redisReaderCreate();\n    return c;\n}\n\nvoid redisFree(redisContext *c) {\n    if (c->fd > 0)\n        close(c->fd);\n    if (c->obuf != NULL)\n        sdsfree(c->obuf);\n    if (c->reader != NULL)\n        redisReaderFree(c->reader);\n    free(c);\n}\n\nint redisFreeKeepFd(redisContext *c) {\n\tint fd = c->fd;\n\tc->fd = -1;\n\tredisFree(c);\n\treturn fd;\n}\n\n/* Connect to a Redis instance. On error the field error in the returned\n * context will be set to the return value of the error function.\n * When no set of reply functions is given, the default set will be used. */\nredisContext *redisConnect(const char *ip, int port) {\n    redisContext *c;\n\n    c = redisContextInit();\n    if (c == NULL)\n        return NULL;\n\n    c->flags |= REDIS_BLOCK;\n    redisContextConnectTcp(c,ip,port,NULL);\n    return c;\n}\n\nredisContext *redisConnectWithTimeout(const char *ip, int port, const struct timeval tv) {\n    redisContext *c;\n\n    c = redisContextInit();\n    if (c == NULL)\n        return NULL;\n\n    c->flags |= REDIS_BLOCK;\n    redisContextConnectTcp(c,ip,port,&tv);\n    return c;\n}\n\nredisContext *redisConnectNonBlock(const char *ip, int port) {\n    redisContext *c;\n\n    c = redisContextInit();\n    if (c == NULL)\n        return NULL;\n\n    c->flags &= ~REDIS_BLOCK;\n    redisContextConnectTcp(c,ip,port,NULL);\n    return c;\n}\n\nredisContext *redisConnectBindNonBlock(const char *ip, int port,\n                                       const char *source_addr) {\n    redisContext *c = redisContextInit();\n    c->flags &= ~REDIS_BLOCK;\n    redisContextConnectBindTcp(c,ip,port,NULL,source_addr);\n    return c;\n}\n\nredisContext *redisConnectUnix(const char *path) {\n    redisContext *c;\n\n    c = redisContextInit();\n    if (c == NULL)\n        return NULL;\n\n    c->flags |= REDIS_BLOCK;\n    redisContextConnectUnix(c,path,NULL);\n    return c;\n}\n\nredisContext *redisConnectUnixWithTimeout(const char *path, const struct timeval tv) {\n    redisContext *c;\n\n    c = redisContextInit();\n    if (c == NULL)\n        return NULL;\n\n    c->flags |= REDIS_BLOCK;\n    redisContextConnectUnix(c,path,&tv);\n    return c;\n}\n\nredisContext *redisConnectUnixNonBlock(const char *path) {\n    redisContext *c;\n\n    c = redisContextInit();\n    if (c == NULL)\n        return NULL;\n\n    c->flags &= ~REDIS_BLOCK;\n    redisContextConnectUnix(c,path,NULL);\n    return c;\n}\n\nredisContext *redisConnectFd(int fd) {\n    redisContext *c;\n\n    c = redisContextInit();\n    if (c == NULL)\n        return NULL;\n\n    c->fd = fd;\n    c->flags |= REDIS_BLOCK | REDIS_CONNECTED;\n    return c;\n}\n\n/* Set read/write timeout on a blocking socket. */\nint redisSetTimeout(redisContext *c, const struct timeval tv) {\n    if (c->flags & REDIS_BLOCK)\n        return redisContextSetTimeout(c,tv);\n    return REDIS_ERR;\n}\n\n/* Enable connection KeepAlive. */\nint redisEnableKeepAlive(redisContext *c) {\n    if (redisKeepAlive(c, REDIS_KEEPALIVE_INTERVAL) != REDIS_OK)\n        return REDIS_ERR;\n    return REDIS_OK;\n}\n\n/* Use this function to handle a read event on the descriptor. It will try\n * and read some bytes from the socket and feed them to the reply parser.\n *\n * After this function is called, you may use redisContextReadReply to\n * see if there is a reply available. */\nint redisBufferRead(redisContext *c) {\n    char buf[1024*16];\n    int nread;\n\n    /* Return early when the context has seen an error. */\n    if (c->err)\n        return REDIS_ERR;\n\n    nread = read(c->fd,buf,sizeof(buf));\n    if (nread == -1) {\n        if ((errno == EAGAIN && !(c->flags & REDIS_BLOCK)) || (errno == EINTR)) {\n            /* Try again later */\n        } else {\n            __redisSetError(c,REDIS_ERR_IO,NULL);\n            return REDIS_ERR;\n        }\n    } else if (nread == 0) {\n        __redisSetError(c,REDIS_ERR_EOF,\"Server closed the connection\");\n        return REDIS_ERR;\n    } else {\n        if (redisReaderFeed(c->reader,buf,nread) != REDIS_OK) {\n            __redisSetError(c,c->reader->err,c->reader->errstr);\n            return REDIS_ERR;\n        }\n    }\n    return REDIS_OK;\n}\n\n/* Write the output buffer to the socket.\n *\n * Returns REDIS_OK when the buffer is empty, or (a part of) the buffer was\n * succesfully written to the socket. When the buffer is empty after the\n * write operation, \"done\" is set to 1 (if given).\n *\n * Returns REDIS_ERR if an error occured trying to write and sets\n * c->errstr to hold the appropriate error string.\n */\nint redisBufferWrite(redisContext *c, int *done) {\n    int nwritten;\n\n    /* Return early when the context has seen an error. */\n    if (c->err)\n        return REDIS_ERR;\n\n    if (sdslen(c->obuf) > 0) {\n        nwritten = write(c->fd,c->obuf,sdslen(c->obuf));\n        if (nwritten == -1) {\n            if ((errno == EAGAIN && !(c->flags & REDIS_BLOCK)) || (errno == EINTR)) {\n                /* Try again later */\n            } else {\n                __redisSetError(c,REDIS_ERR_IO,NULL);\n                return REDIS_ERR;\n            }\n        } else if (nwritten > 0) {\n            if (nwritten == (signed)sdslen(c->obuf)) {\n                sdsfree(c->obuf);\n                c->obuf = sdsempty();\n            } else {\n                sdsrange(c->obuf,nwritten,-1);\n            }\n        }\n    }\n    if (done != NULL) *done = (sdslen(c->obuf) == 0);\n    return REDIS_OK;\n}\n\n/* Internal helper function to try and get a reply from the reader,\n * or set an error in the context otherwise. */\nint redisGetReplyFromReader(redisContext *c, void **reply) {\n    if (redisReaderGetReply(c->reader,reply) == REDIS_ERR) {\n        __redisSetError(c,c->reader->err,c->reader->errstr);\n        return REDIS_ERR;\n    }\n    return REDIS_OK;\n}\n\nint redisGetReply(redisContext *c, void **reply) {\n    int wdone = 0;\n    void *aux = NULL;\n\n    /* Try to read pending replies */\n    if (redisGetReplyFromReader(c,&aux) == REDIS_ERR)\n        return REDIS_ERR;\n\n    /* For the blocking context, flush output buffer and read reply */\n    if (aux == NULL && c->flags & REDIS_BLOCK) {\n        /* Write until done */\n        do {\n            if (redisBufferWrite(c,&wdone) == REDIS_ERR)\n                return REDIS_ERR;\n        } while (!wdone);\n\n        /* Read until there is a reply */\n        do {\n            if (redisBufferRead(c) == REDIS_ERR)\n                return REDIS_ERR;\n            if (redisGetReplyFromReader(c,&aux) == REDIS_ERR)\n                return REDIS_ERR;\n        } while (aux == NULL);\n    }\n\n    /* Set reply object */\n    if (reply != NULL) *reply = aux;\n    return REDIS_OK;\n}\n\n\n/* Helper function for the redisAppendCommand* family of functions.\n *\n * Write a formatted command to the output buffer. When this family\n * is used, you need to call redisGetReply yourself to retrieve\n * the reply (or replies in pub/sub).\n */\nint __redisAppendCommand(redisContext *c, const char *cmd, size_t len) {\n    sds newbuf;\n\n    newbuf = sdscatlen(c->obuf,cmd,len);\n    if (newbuf == NULL) {\n        __redisSetError(c,REDIS_ERR_OOM,\"Out of memory\");\n        return REDIS_ERR;\n    }\n\n    c->obuf = newbuf;\n    return REDIS_OK;\n}\n\nint redisAppendFormattedCommand(redisContext *c, const char *cmd, size_t len) {\n\n    if (__redisAppendCommand(c, cmd, len) != REDIS_OK) {\n        return REDIS_ERR;\n    }\n\n    return REDIS_OK;\n}\n\nint redisvAppendCommand(redisContext *c, const char *format, va_list ap) {\n    char *cmd;\n    int len;\n\n    len = redisvFormatCommand(&cmd,format,ap);\n    if (len == -1) {\n        __redisSetError(c,REDIS_ERR_OOM,\"Out of memory\");\n        return REDIS_ERR;\n    }\n\n    if (__redisAppendCommand(c,cmd,len) != REDIS_OK) {\n        free(cmd);\n        return REDIS_ERR;\n    }\n\n    free(cmd);\n    return REDIS_OK;\n}\n\nint redisAppendCommand(redisContext *c, const char *format, ...) {\n    va_list ap;\n    int ret;\n\n    va_start(ap,format);\n    ret = redisvAppendCommand(c,format,ap);\n    va_end(ap);\n    return ret;\n}\n\nint redisAppendCommandArgv(redisContext *c, int argc, const char **argv, const size_t *argvlen) {\n    char *cmd;\n    int len;\n\n    len = redisFormatCommandArgv(&cmd,argc,argv,argvlen);\n    if (len == -1) {\n        __redisSetError(c,REDIS_ERR_OOM,\"Out of memory\");\n        return REDIS_ERR;\n    }\n\n    if (__redisAppendCommand(c,cmd,len) != REDIS_OK) {\n        free(cmd);\n        return REDIS_ERR;\n    }\n\n    free(cmd);\n    return REDIS_OK;\n}\n\n/* Helper function for the redisCommand* family of functions.\n *\n * Write a formatted command to the output buffer. If the given context is\n * blocking, immediately read the reply into the \"reply\" pointer. When the\n * context is non-blocking, the \"reply\" pointer will not be used and the\n * command is simply appended to the write buffer.\n *\n * Returns the reply when a reply was succesfully retrieved. Returns NULL\n * otherwise. When NULL is returned in a blocking context, the error field\n * in the context will be set.\n */\nstatic void *__redisBlockForReply(redisContext *c) {\n    void *reply;\n\n    if (c->flags & REDIS_BLOCK) {\n        if (redisGetReply(c,&reply) != REDIS_OK)\n            return NULL;\n        return reply;\n    }\n    return NULL;\n}\n\nvoid *redisvCommand(redisContext *c, const char *format, va_list ap) {\n    if (redisvAppendCommand(c,format,ap) != REDIS_OK)\n        return NULL;\n    return __redisBlockForReply(c);\n}\n\nvoid *redisCommand(redisContext *c, const char *format, ...) {\n    va_list ap;\n    void *reply = NULL;\n    va_start(ap,format);\n    reply = redisvCommand(c,format,ap);\n    va_end(ap);\n    return reply;\n}\n\nvoid *redisCommandArgv(redisContext *c, int argc, const char **argv, const size_t *argvlen) {\n    if (redisAppendCommandArgv(c,argc,argv,argvlen) != REDIS_OK)\n        return NULL;\n    return __redisBlockForReply(c);\n}\n"
  },
  {
    "path": "extern/deprecated/redis-2.8.21/deps/hiredis/hiredis.h",
    "content": "/*\n * Copyright (c) 2009-2011, Salvatore Sanfilippo <antirez at gmail dot com>\n * Copyright (c) 2010-2011, Pieter Noordhuis <pcnoordhuis at gmail dot com>\n *\n * All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions are met:\n *\n *   * Redistributions of source code must retain the above copyright notice,\n *     this list of conditions and the following disclaimer.\n *   * Redistributions in binary form must reproduce the above copyright\n *     notice, this list of conditions and the following disclaimer in the\n *     documentation and/or other materials provided with the distribution.\n *   * Neither the name of Redis nor the names of its contributors may be used\n *     to endorse or promote products derived from this software without\n *     specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\"\n * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\n * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE\n * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR\n * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF\n * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS\n * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN\n * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)\n * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE\n * POSSIBILITY OF SUCH DAMAGE.\n */\n\n#ifndef __HIREDIS_H\n#define __HIREDIS_H\n#include <stdio.h> /* for size_t */\n#include <stdarg.h> /* for va_list */\n#include <sys/time.h> /* for struct timeval */\n\n#define HIREDIS_MAJOR 0\n#define HIREDIS_MINOR 11\n#define HIREDIS_PATCH 0\n\n#define REDIS_ERR -1\n#define REDIS_OK 0\n\n/* When an error occurs, the err flag in a context is set to hold the type of\n * error that occured. REDIS_ERR_IO means there was an I/O error and you\n * should use the \"errno\" variable to find out what is wrong.\n * For other values, the \"errstr\" field will hold a description. */\n#define REDIS_ERR_IO 1 /* Error in read or write */\n#define REDIS_ERR_EOF 3 /* End of file */\n#define REDIS_ERR_PROTOCOL 4 /* Protocol error */\n#define REDIS_ERR_OOM 5 /* Out of memory */\n#define REDIS_ERR_OTHER 2 /* Everything else... */\n\n/* Connection type can be blocking or non-blocking and is set in the\n * least significant bit of the flags field in redisContext. */\n#define REDIS_BLOCK 0x1\n\n/* Connection may be disconnected before being free'd. The second bit\n * in the flags field is set when the context is connected. */\n#define REDIS_CONNECTED 0x2\n\n/* The async API might try to disconnect cleanly and flush the output\n * buffer and read all subsequent replies before disconnecting.\n * This flag means no new commands can come in and the connection\n * should be terminated once all replies have been read. */\n#define REDIS_DISCONNECTING 0x4\n\n/* Flag specific to the async API which means that the context should be clean\n * up as soon as possible. */\n#define REDIS_FREEING 0x8\n\n/* Flag that is set when an async callback is executed. */\n#define REDIS_IN_CALLBACK 0x10\n\n/* Flag that is set when the async context has one or more subscriptions. */\n#define REDIS_SUBSCRIBED 0x20\n\n/* Flag that is set when monitor mode is active */\n#define REDIS_MONITORING 0x40\n\n#define REDIS_REPLY_STRING 1\n#define REDIS_REPLY_ARRAY 2\n#define REDIS_REPLY_INTEGER 3\n#define REDIS_REPLY_NIL 4\n#define REDIS_REPLY_STATUS 5\n#define REDIS_REPLY_ERROR 6\n\n#define REDIS_READER_MAX_BUF (1024*16)  /* Default max unused reader buffer. */\n\n#define REDIS_KEEPALIVE_INTERVAL 15 /* seconds */\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n/* This is the reply object returned by redisCommand() */\ntypedef struct redisReply {\n    int type; /* REDIS_REPLY_* */\n    long long integer; /* The integer when type is REDIS_REPLY_INTEGER */\n    int len; /* Length of string */\n    char *str; /* Used for both REDIS_REPLY_ERROR and REDIS_REPLY_STRING */\n    size_t elements; /* number of elements, for REDIS_REPLY_ARRAY */\n    struct redisReply **element; /* elements vector for REDIS_REPLY_ARRAY */\n} redisReply;\n\ntypedef struct redisReadTask {\n    int type;\n    int elements; /* number of elements in multibulk container */\n    int idx; /* index in parent (array) object */\n    void *obj; /* holds user-generated value for a read task */\n    struct redisReadTask *parent; /* parent task */\n    void *privdata; /* user-settable arbitrary field */\n} redisReadTask;\n\ntypedef struct redisReplyObjectFunctions {\n    void *(*createString)(const redisReadTask*, char*, size_t);\n    void *(*createArray)(const redisReadTask*, int);\n    void *(*createInteger)(const redisReadTask*, long long);\n    void *(*createNil)(const redisReadTask*);\n    void (*freeObject)(void*);\n} redisReplyObjectFunctions;\n\n/* State for the protocol parser */\ntypedef struct redisReader {\n    int err; /* Error flags, 0 when there is no error */\n    char errstr[128]; /* String representation of error when applicable */\n\n    char *buf; /* Read buffer */\n    size_t pos; /* Buffer cursor */\n    size_t len; /* Buffer length */\n    size_t maxbuf; /* Max length of unused buffer */\n\n    redisReadTask rstack[9];\n    int ridx; /* Index of current read task */\n    void *reply; /* Temporary reply pointer */\n\n    redisReplyObjectFunctions *fn;\n    void *privdata;\n} redisReader;\n\n/* Public API for the protocol parser. */\nredisReader *redisReaderCreate(void);\nvoid redisReaderFree(redisReader *r);\nint redisReaderFeed(redisReader *r, const char *buf, size_t len);\nint redisReaderGetReply(redisReader *r, void **reply);\n\n/* Backwards compatibility, can be removed on big version bump. */\n#define redisReplyReaderCreate redisReaderCreate\n#define redisReplyReaderFree redisReaderFree\n#define redisReplyReaderFeed redisReaderFeed\n#define redisReplyReaderGetReply redisReaderGetReply\n#define redisReplyReaderSetPrivdata(_r, _p) (int)(((redisReader*)(_r))->privdata = (_p))\n#define redisReplyReaderGetObject(_r) (((redisReader*)(_r))->reply)\n#define redisReplyReaderGetError(_r) (((redisReader*)(_r))->errstr)\n\n/* Function to free the reply objects hiredis returns by default. */\nvoid freeReplyObject(void *reply);\n\n/* Functions to format a command according to the protocol. */\nint redisvFormatCommand(char **target, const char *format, va_list ap);\nint redisFormatCommand(char **target, const char *format, ...);\nint redisFormatCommandArgv(char **target, int argc, const char **argv, const size_t *argvlen);\n\n/* Context for a connection to Redis */\ntypedef struct redisContext {\n    int err; /* Error flags, 0 when there is no error */\n    char errstr[128]; /* String representation of error when applicable */\n    int fd;\n    int flags;\n    char *obuf; /* Write buffer */\n    redisReader *reader; /* Protocol reader */\n} redisContext;\n\nredisContext *redisConnect(const char *ip, int port);\nredisContext *redisConnectWithTimeout(const char *ip, int port, const struct timeval tv);\nredisContext *redisConnectNonBlock(const char *ip, int port);\nredisContext *redisConnectBindNonBlock(const char *ip, int port, const char *source_addr);\nredisContext *redisConnectUnix(const char *path);\nredisContext *redisConnectUnixWithTimeout(const char *path, const struct timeval tv);\nredisContext *redisConnectUnixNonBlock(const char *path);\nredisContext *redisConnectFd(int fd);\nint redisSetTimeout(redisContext *c, const struct timeval tv);\nint redisEnableKeepAlive(redisContext *c);\nvoid redisFree(redisContext *c);\nint redisFreeKeepFd(redisContext *c);\nint redisBufferRead(redisContext *c);\nint redisBufferWrite(redisContext *c, int *done);\n\n/* In a blocking context, this function first checks if there are unconsumed\n * replies to return and returns one if so. Otherwise, it flushes the output\n * buffer to the socket and reads until it has a reply. In a non-blocking\n * context, it will return unconsumed replies until there are no more. */\nint redisGetReply(redisContext *c, void **reply);\nint redisGetReplyFromReader(redisContext *c, void **reply);\n\n/* Write a formatted command to the output buffer. Use these functions in blocking mode\n * to get a pipeline of commands. */\nint redisAppendFormattedCommand(redisContext *c, const char *cmd, size_t len);\n\n/* Write a command to the output buffer. Use these functions in blocking mode\n * to get a pipeline of commands. */\nint redisvAppendCommand(redisContext *c, const char *format, va_list ap);\nint redisAppendCommand(redisContext *c, const char *format, ...);\nint redisAppendCommandArgv(redisContext *c, int argc, const char **argv, const size_t *argvlen);\n\n/* Issue a command to Redis. In a blocking context, it is identical to calling\n * redisAppendCommand, followed by redisGetReply. The function will return\n * NULL if there was an error in performing the request, otherwise it will\n * return the reply. In a non-blocking context, it is identical to calling\n * only redisAppendCommand and will always return NULL. */\nvoid *redisvCommand(redisContext *c, const char *format, va_list ap);\nvoid *redisCommand(redisContext *c, const char *format, ...);\nvoid *redisCommandArgv(redisContext *c, int argc, const char **argv, const size_t *argvlen);\n\n#ifdef __cplusplus\n}\n#endif\n\n#endif\n"
  },
  {
    "path": "extern/deprecated/redis-2.8.21/deps/hiredis/net.c",
    "content": "/* Extracted from anet.c to work properly with Hiredis error reporting.\n *\n * Copyright (c) 2006-2011, Salvatore Sanfilippo <antirez at gmail dot com>\n * Copyright (c) 2010-2011, Pieter Noordhuis <pcnoordhuis at gmail dot com>\n *\n * All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions are met:\n *\n *   * Redistributions of source code must retain the above copyright notice,\n *     this list of conditions and the following disclaimer.\n *   * Redistributions in binary form must reproduce the above copyright\n *     notice, this list of conditions and the following disclaimer in the\n *     documentation and/or other materials provided with the distribution.\n *   * Neither the name of Redis nor the names of its contributors may be used\n *     to endorse or promote products derived from this software without\n *     specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\"\n * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\n * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE\n * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR\n * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF\n * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS\n * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN\n * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)\n * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE\n * POSSIBILITY OF SUCH DAMAGE.\n */\n\n#include \"fmacros.h\"\n#include <sys/types.h>\n#include <sys/socket.h>\n#include <sys/select.h>\n#include <sys/un.h>\n#include <netinet/in.h>\n#include <netinet/tcp.h>\n#include <arpa/inet.h>\n#include <unistd.h>\n#include <fcntl.h>\n#include <string.h>\n#include <netdb.h>\n#include <errno.h>\n#include <stdarg.h>\n#include <stdio.h>\n#include <poll.h>\n#include <limits.h>\n\n#include \"net.h\"\n#include \"sds.h\"\n\n/* Defined in hiredis.c */\nvoid __redisSetError(redisContext *c, int type, const char *str);\n\nstatic void redisContextCloseFd(redisContext *c) {\n    if (c && c->fd >= 0) {\n        close(c->fd);\n        c->fd = -1;\n    }\n}\n\nstatic void __redisSetErrorFromErrno(redisContext *c, int type, const char *prefix) {\n    char buf[128] = { 0 };\n    size_t len = 0;\n\n    if (prefix != NULL)\n        len = snprintf(buf,sizeof(buf),\"%s: \",prefix);\n    strerror_r(errno,buf+len,sizeof(buf)-len);\n    __redisSetError(c,type,buf);\n}\n\nstatic int redisSetReuseAddr(redisContext *c) {\n    int on = 1;\n    if (setsockopt(c->fd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)) == -1) {\n        __redisSetErrorFromErrno(c,REDIS_ERR_IO,NULL);\n        redisContextCloseFd(c);\n        return REDIS_ERR;\n    }\n    return REDIS_OK;\n}\n\nstatic int redisCreateSocket(redisContext *c, int type) {\n    int s;\n    if ((s = socket(type, SOCK_STREAM, 0)) == -1) {\n        __redisSetErrorFromErrno(c,REDIS_ERR_IO,NULL);\n        return REDIS_ERR;\n    }\n    c->fd = s;\n    if (type == AF_INET) {\n        if (redisSetReuseAddr(c) == REDIS_ERR) {\n            return REDIS_ERR;\n        }\n    }\n    return REDIS_OK;\n}\n\nstatic int redisSetBlocking(redisContext *c, int blocking) {\n    int flags;\n\n    /* Set the socket nonblocking.\n     * Note that fcntl(2) for F_GETFL and F_SETFL can't be\n     * interrupted by a signal. */\n    if ((flags = fcntl(c->fd, F_GETFL)) == -1) {\n        __redisSetErrorFromErrno(c,REDIS_ERR_IO,\"fcntl(F_GETFL)\");\n        redisContextCloseFd(c);\n        return REDIS_ERR;\n    }\n\n    if (blocking)\n        flags &= ~O_NONBLOCK;\n    else\n        flags |= O_NONBLOCK;\n\n    if (fcntl(c->fd, F_SETFL, flags) == -1) {\n        __redisSetErrorFromErrno(c,REDIS_ERR_IO,\"fcntl(F_SETFL)\");\n        redisContextCloseFd(c);\n        return REDIS_ERR;\n    }\n    return REDIS_OK;\n}\n\nint redisKeepAlive(redisContext *c, int interval) {\n    int val = 1;\n    int fd = c->fd;\n\n    if (setsockopt(fd, SOL_SOCKET, SO_KEEPALIVE, &val, sizeof(val)) == -1){\n        __redisSetError(c,REDIS_ERR_OTHER,strerror(errno));\n        return REDIS_ERR;\n    }\n\n    val = interval;\n\n#ifdef _OSX\n    if (setsockopt(fd, IPPROTO_TCP, TCP_KEEPALIVE, &val, sizeof(val)) < 0) {\n        __redisSetError(c,REDIS_ERR_OTHER,strerror(errno));\n        return REDIS_ERR;\n    }\n#else\n#ifndef __sun\n    val = interval;\n    if (setsockopt(fd, IPPROTO_TCP, TCP_KEEPIDLE, &val, sizeof(val)) < 0) {\n        __redisSetError(c,REDIS_ERR_OTHER,strerror(errno));\n        return REDIS_ERR;\n    }\n\n    val = interval/3;\n    if (val == 0) val = 1;\n    if (setsockopt(fd, IPPROTO_TCP, TCP_KEEPINTVL, &val, sizeof(val)) < 0) {\n        __redisSetError(c,REDIS_ERR_OTHER,strerror(errno));\n        return REDIS_ERR;\n    }\n\n    val = 3;\n    if (setsockopt(fd, IPPROTO_TCP, TCP_KEEPCNT, &val, sizeof(val)) < 0) {\n        __redisSetError(c,REDIS_ERR_OTHER,strerror(errno));\n        return REDIS_ERR;\n    }\n#endif\n#endif\n\n    return REDIS_OK;\n}\n\nstatic int redisSetTcpNoDelay(redisContext *c) {\n    int yes = 1;\n    if (setsockopt(c->fd, IPPROTO_TCP, TCP_NODELAY, &yes, sizeof(yes)) == -1) {\n        __redisSetErrorFromErrno(c,REDIS_ERR_IO,\"setsockopt(TCP_NODELAY)\");\n        redisContextCloseFd(c);\n        return REDIS_ERR;\n    }\n    return REDIS_OK;\n}\n\n#define __MAX_MSEC (((LONG_MAX) - 999) / 1000)\n\nstatic int redisContextWaitReady(redisContext *c, const struct timeval *timeout) {\n    struct pollfd   wfd[1];\n    long msec;\n\n    msec          = -1;\n    wfd[0].fd     = c->fd;\n    wfd[0].events = POLLOUT;\n\n    /* Only use timeout when not NULL. */\n    if (timeout != NULL) {\n        if (timeout->tv_usec > 1000000 || timeout->tv_sec > __MAX_MSEC) {\n            __redisSetErrorFromErrno(c, REDIS_ERR_IO, NULL);\n            redisContextCloseFd(c);\n            return REDIS_ERR;\n        }\n\n        msec = (timeout->tv_sec * 1000) + ((timeout->tv_usec + 999) / 1000);\n\n        if (msec < 0 || msec > INT_MAX) {\n            msec = INT_MAX;\n        }\n    }\n\n    if (errno == EINPROGRESS) {\n        int res;\n\n        if ((res = poll(wfd, 1, msec)) == -1) {\n            __redisSetErrorFromErrno(c, REDIS_ERR_IO, \"poll(2)\");\n            redisContextCloseFd(c);\n            return REDIS_ERR;\n        } else if (res == 0) {\n            errno = ETIMEDOUT;\n            __redisSetErrorFromErrno(c,REDIS_ERR_IO,NULL);\n            redisContextCloseFd(c);\n            return REDIS_ERR;\n        }\n\n        if (redisCheckSocketError(c) != REDIS_OK)\n            return REDIS_ERR;\n\n        return REDIS_OK;\n    }\n\n    __redisSetErrorFromErrno(c,REDIS_ERR_IO,NULL);\n    redisContextCloseFd(c);\n    return REDIS_ERR;\n}\n\nint redisCheckSocketError(redisContext *c) {\n    int err = 0;\n    socklen_t errlen = sizeof(err);\n\n    if (getsockopt(c->fd, SOL_SOCKET, SO_ERROR, &err, &errlen) == -1) {\n        __redisSetErrorFromErrno(c,REDIS_ERR_IO,\"getsockopt(SO_ERROR)\");\n        return REDIS_ERR;\n    }\n\n    if (err) {\n        errno = err;\n        __redisSetErrorFromErrno(c,REDIS_ERR_IO,NULL);\n        return REDIS_ERR;\n    }\n\n    return REDIS_OK;\n}\n\nint redisContextSetTimeout(redisContext *c, const struct timeval tv) {\n    if (setsockopt(c->fd,SOL_SOCKET,SO_RCVTIMEO,&tv,sizeof(tv)) == -1) {\n        __redisSetErrorFromErrno(c,REDIS_ERR_IO,\"setsockopt(SO_RCVTIMEO)\");\n        return REDIS_ERR;\n    }\n    if (setsockopt(c->fd,SOL_SOCKET,SO_SNDTIMEO,&tv,sizeof(tv)) == -1) {\n        __redisSetErrorFromErrno(c,REDIS_ERR_IO,\"setsockopt(SO_SNDTIMEO)\");\n        return REDIS_ERR;\n    }\n    return REDIS_OK;\n}\n\nstatic int _redisContextConnectTcp(redisContext *c, const char *addr, int port,\n                                   const struct timeval *timeout,\n                                   const char *source_addr) {\n    int s, rv;\n    char _port[6];  /* strlen(\"65535\"); */\n    struct addrinfo hints, *servinfo, *bservinfo, *p, *b;\n    int blocking = (c->flags & REDIS_BLOCK);\n\n    snprintf(_port, 6, \"%d\", port);\n    memset(&hints,0,sizeof(hints));\n    hints.ai_family = AF_INET;\n    hints.ai_socktype = SOCK_STREAM;\n\n    /* Try with IPv6 if no IPv4 address was found. We do it in this order since\n     * in a Redis client you can't afford to test if you have IPv6 connectivity\n     * as this would add latency to every connect. Otherwise a more sensible\n     * route could be: Use IPv6 if both addresses are available and there is IPv6\n     * connectivity. */\n    if ((rv = getaddrinfo(addr,_port,&hints,&servinfo)) != 0) {\n         hints.ai_family = AF_INET6;\n         if ((rv = getaddrinfo(addr,_port,&hints,&servinfo)) != 0) {\n            __redisSetError(c,REDIS_ERR_OTHER,gai_strerror(rv));\n            return REDIS_ERR;\n        }\n    }\n    for (p = servinfo; p != NULL; p = p->ai_next) {\n        if ((s = socket(p->ai_family,p->ai_socktype,p->ai_protocol)) == -1)\n            continue;\n\n        c->fd = s;\n        if (redisSetBlocking(c,0) != REDIS_OK)\n            goto error;\n        if (source_addr) {\n            int bound = 0;\n            /* Using getaddrinfo saves us from self-determining IPv4 vs IPv6 */\n            if ((rv = getaddrinfo(source_addr, NULL, &hints, &bservinfo)) != 0) {\n                char buf[128];\n                snprintf(buf,sizeof(buf),\"Can't get addr: %s\",gai_strerror(rv));\n                __redisSetError(c,REDIS_ERR_OTHER,buf);\n                goto error;\n            }\n            for (b = bservinfo; b != NULL; b = b->ai_next) {\n                if (bind(s,b->ai_addr,b->ai_addrlen) != -1) {\n                    bound = 1;\n                    break;\n                }\n            }\n            freeaddrinfo(bservinfo);\n            if (!bound) {\n                char buf[128];\n                snprintf(buf,sizeof(buf),\"Can't bind socket: %s\",strerror(errno));\n                __redisSetError(c,REDIS_ERR_OTHER,buf);\n                goto error;\n            }\n        }\n        if (connect(s,p->ai_addr,p->ai_addrlen) == -1) {\n            if (errno == EHOSTUNREACH) {\n                redisContextCloseFd(c);\n                continue;\n            } else if (errno == EINPROGRESS && !blocking) {\n                /* This is ok. */\n            } else {\n                if (redisContextWaitReady(c,timeout) != REDIS_OK)\n                    goto error;\n            }\n        }\n        if (blocking && redisSetBlocking(c,1) != REDIS_OK)\n            goto error;\n        if (redisSetTcpNoDelay(c) != REDIS_OK)\n            goto error;\n\n        c->flags |= REDIS_CONNECTED;\n        rv = REDIS_OK;\n        goto end;\n    }\n    if (p == NULL) {\n        char buf[128];\n        snprintf(buf,sizeof(buf),\"Can't create socket: %s\",strerror(errno));\n        __redisSetError(c,REDIS_ERR_OTHER,buf);\n        goto error;\n    }\n\nerror:\n    rv = REDIS_ERR;\nend:\n    freeaddrinfo(servinfo);\n    return rv;  // Need to return REDIS_OK if alright\n}\n\nint redisContextConnectTcp(redisContext *c, const char *addr, int port,\n                           const struct timeval *timeout) {\n    return _redisContextConnectTcp(c, addr, port, timeout, NULL);\n}\n\nint redisContextConnectBindTcp(redisContext *c, const char *addr, int port,\n                               const struct timeval *timeout,\n                               const char *source_addr) {\n    return _redisContextConnectTcp(c, addr, port, timeout, source_addr);\n}\n\nint redisContextConnectUnix(redisContext *c, const char *path, const struct timeval *timeout) {\n    int blocking = (c->flags & REDIS_BLOCK);\n    struct sockaddr_un sa;\n\n    if (redisCreateSocket(c,AF_LOCAL) < 0)\n        return REDIS_ERR;\n    if (redisSetBlocking(c,0) != REDIS_OK)\n        return REDIS_ERR;\n\n    sa.sun_family = AF_LOCAL;\n    strncpy(sa.sun_path,path,sizeof(sa.sun_path)-1);\n    if (connect(c->fd, (struct sockaddr*)&sa, sizeof(sa)) == -1) {\n        if (errno == EINPROGRESS && !blocking) {\n            /* This is ok. */\n        } else {\n            if (redisContextWaitReady(c,timeout) != REDIS_OK)\n                return REDIS_ERR;\n        }\n    }\n\n    /* Reset socket to be blocking after connect(2). */\n    if (blocking && redisSetBlocking(c,1) != REDIS_OK)\n        return REDIS_ERR;\n\n    c->flags |= REDIS_CONNECTED;\n    return REDIS_OK;\n}\n"
  },
  {
    "path": "extern/deprecated/redis-2.8.21/deps/hiredis/net.h",
    "content": "/* Extracted from anet.c to work properly with Hiredis error reporting.\n *\n * Copyright (c) 2006-2011, Salvatore Sanfilippo <antirez at gmail dot com>\n * Copyright (c) 2010-2011, Pieter Noordhuis <pcnoordhuis at gmail dot com>\n *\n * All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions are met:\n *\n *   * Redistributions of source code must retain the above copyright notice,\n *     this list of conditions and the following disclaimer.\n *   * Redistributions in binary form must reproduce the above copyright\n *     notice, this list of conditions and the following disclaimer in the\n *     documentation and/or other materials provided with the distribution.\n *   * Neither the name of Redis nor the names of its contributors may be used\n *     to endorse or promote products derived from this software without\n *     specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\"\n * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\n * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE\n * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR\n * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF\n * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS\n * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN\n * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)\n * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE\n * POSSIBILITY OF SUCH DAMAGE.\n */\n\n#ifndef __NET_H\n#define __NET_H\n\n#include \"hiredis.h\"\n\n#if defined(__sun) || defined(_AIX)\n#define AF_LOCAL AF_UNIX\n#endif\n\nint redisCheckSocketError(redisContext *c);\nint redisContextSetTimeout(redisContext *c, const struct timeval tv);\nint redisContextConnectTcp(redisContext *c, const char *addr, int port, const struct timeval *timeout);\nint redisContextConnectBindTcp(redisContext *c, const char *addr, int port,\n                               const struct timeval *timeout,\n                               const char *source_addr);\nint redisContextConnectUnix(redisContext *c, const char *path, const struct timeval *timeout);\nint redisKeepAlive(redisContext *c, int interval);\n\n#endif\n"
  },
  {
    "path": "extern/deprecated/redis-2.8.21/deps/hiredis/sds.c",
    "content": "/* SDSLib, A C dynamic strings library\n *\n * Copyright (c) 2006-2012, Salvatore Sanfilippo <antirez at gmail dot com>\n * All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions are met:\n *\n *   * Redistributions of source code must retain the above copyright notice,\n *     this list of conditions and the following disclaimer.\n *   * Redistributions in binary form must reproduce the above copyright\n *     notice, this list of conditions and the following disclaimer in the\n *     documentation and/or other materials provided with the distribution.\n *   * Neither the name of Redis nor the names of its contributors may be used\n *     to endorse or promote products derived from this software without\n *     specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\"\n * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\n * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE\n * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR\n * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF\n * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS\n * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN\n * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)\n * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE\n * POSSIBILITY OF SUCH DAMAGE.\n */\n\n#include <stdio.h>\n#include <stdlib.h>\n#include <string.h>\n#include <ctype.h>\n#include <assert.h>\n#include \"sds.h\"\n#include \"zmalloc.h\"\n\n/* Create a new sds string with the content specified by the 'init' pointer\n * and 'initlen'.\n * If NULL is used for 'init' the string is initialized with zero bytes.\n *\n * The string is always null-termined (all the sds strings are, always) so\n * even if you create an sds string with:\n *\n * mystring = sdsnewlen(\"abc\",3\");\n *\n * You can print the string with printf() as there is an implicit \\0 at the\n * end of the string. However the string is binary safe and can contain\n * \\0 characters in the middle, as the length is stored in the sds header. */\nsds sdsnewlen(const void *init, size_t initlen) {\n    struct sdshdr *sh;\n\n    if (init) {\n        sh = zmalloc(sizeof(struct sdshdr)+initlen+1);\n    } else {\n        sh = zcalloc(sizeof(struct sdshdr)+initlen+1);\n    }\n    if (sh == NULL) return NULL;\n    sh->len = initlen;\n    sh->free = 0;\n    if (initlen && init)\n        memcpy(sh->buf, init, initlen);\n    sh->buf[initlen] = '\\0';\n    return (char*)sh->buf;\n}\n\n/* Create an empty (zero length) sds string. Even in this case the string\n * always has an implicit null term. */\nsds sdsempty(void) {\n    return sdsnewlen(\"\",0);\n}\n\n/* Create a new sds string starting from a null termined C string. */\nsds sdsnew(const char *init) {\n    size_t initlen = (init == NULL) ? 0 : strlen(init);\n    return sdsnewlen(init, initlen);\n}\n\n/* Duplicate an sds string. */\nsds sdsdup(const sds s) {\n    return sdsnewlen(s, sdslen(s));\n}\n\n/* Free an sds string. No operation is performed if 's' is NULL. */\nvoid sdsfree(sds s) {\n    if (s == NULL) return;\n    zfree(s-sizeof(struct sdshdr));\n}\n\n/* Set the sds string length to the length as obtained with strlen(), so\n * considering as content only up to the first null term character.\n *\n * This function is useful when the sds string is hacked manually in some\n * way, like in the following example:\n *\n * s = sdsnew(\"foobar\");\n * s[2] = '\\0';\n * sdsupdatelen(s);\n * printf(\"%d\\n\", sdslen(s));\n *\n * The output will be \"2\", but if we comment out the call to sdsupdatelen()\n * the output will be \"6\" as the string was modified but the logical length\n * remains 6 bytes. */\nvoid sdsupdatelen(sds s) {\n    struct sdshdr *sh = (void*) (s-(sizeof(struct sdshdr)));\n    int reallen = strlen(s);\n    sh->free += (sh->len-reallen);\n    sh->len = reallen;\n}\n\n/* Modify an sds string on-place to make it empty (zero length).\n * However all the existing buffer is not discarded but set as free space\n * so that next append operations will not require allocations up to the\n * number of bytes previously available. */\nvoid sdsclear(sds s) {\n    struct sdshdr *sh = (void*) (s-(sizeof(struct sdshdr)));\n    sh->free += sh->len;\n    sh->len = 0;\n    sh->buf[0] = '\\0';\n}\n\n/* Enlarge the free space at the end of the sds string so that the caller\n * is sure that after calling this function can overwrite up to addlen\n * bytes after the end of the string, plus one more byte for nul term.\n *\n * Note: this does not change the *length* of the sds string as returned\n * by sdslen(), but only the free buffer space we have. */\nsds sdsMakeRoomFor(sds s, size_t addlen) {\n    struct sdshdr *sh, *newsh;\n    size_t free = sdsavail(s);\n    size_t len, newlen;\n\n    if (free >= addlen) return s;\n    len = sdslen(s);\n    sh = (void*) (s-(sizeof(struct sdshdr)));\n    newlen = (len+addlen);\n    if (newlen < SDS_MAX_PREALLOC)\n        newlen *= 2;\n    else\n        newlen += SDS_MAX_PREALLOC;\n    newsh = zrealloc(sh, sizeof(struct sdshdr)+newlen+1);\n    if (newsh == NULL) return NULL;\n\n    newsh->free = newlen - len;\n    return newsh->buf;\n}\n\n/* Reallocate the sds string so that it has no free space at the end. The\n * contained string remains not altered, but next concatenation operations\n * will require a reallocation.\n *\n * After the call, the passed sds string is no longer valid and all the\n * references must be substituted with the new pointer returned by the call. */\nsds sdsRemoveFreeSpace(sds s) {\n    struct sdshdr *sh;\n\n    sh = (void*) (s-(sizeof(struct sdshdr)));\n    sh = zrealloc(sh, sizeof(struct sdshdr)+sh->len+1);\n    sh->free = 0;\n    return sh->buf;\n}\n\n/* Return the total size of the allocation of the specifed sds string,\n * including:\n * 1) The sds header before the pointer.\n * 2) The string.\n * 3) The free buffer at the end if any.\n * 4) The implicit null term.\n */\nsize_t sdsAllocSize(sds s) {\n    struct sdshdr *sh = (void*) (s-(sizeof(struct sdshdr)));\n\n    return sizeof(*sh)+sh->len+sh->free+1;\n}\n\n/* Increment the sds length and decrements the left free space at the\n * end of the string according to 'incr'. Also set the null term\n * in the new end of the string.\n *\n * This function is used in order to fix the string length after the\n * user calls sdsMakeRoomFor(), writes something after the end of\n * the current string, and finally needs to set the new length.\n *\n * Note: it is possible to use a negative increment in order to\n * right-trim the string.\n *\n * Usage example:\n *\n * Using sdsIncrLen() and sdsMakeRoomFor() it is possible to mount the\n * following schema, to cat bytes coming from the kernel to the end of an\n * sds string without copying into an intermediate buffer:\n *\n * oldlen = sdslen(s);\n * s = sdsMakeRoomFor(s, BUFFER_SIZE);\n * nread = read(fd, s+oldlen, BUFFER_SIZE);\n * ... check for nread <= 0 and handle it ...\n * sdsIncrLen(s, nread);\n */\nvoid sdsIncrLen(sds s, int incr) {\n    struct sdshdr *sh = (void*) (s-(sizeof(struct sdshdr)));\n\n    if (incr >= 0)\n        assert(sh->free >= (unsigned int)incr);\n    else\n        assert(sh->len >= (unsigned int)(-incr));\n    sh->len += incr;\n    sh->free -= incr;\n    s[sh->len] = '\\0';\n}\n\n/* Grow the sds to have the specified length. Bytes that were not part of\n * the original length of the sds will be set to zero.\n *\n * if the specified length is smaller than the current length, no operation\n * is performed. */\nsds sdsgrowzero(sds s, size_t len) {\n    struct sdshdr *sh = (void*)(s-(sizeof(struct sdshdr)));\n    size_t totlen, curlen = sh->len;\n\n    if (len <= curlen) return s;\n    s = sdsMakeRoomFor(s,len-curlen);\n    if (s == NULL) return NULL;\n\n    /* Make sure added region doesn't contain garbage */\n    sh = (void*)(s-(sizeof(struct sdshdr)));\n    memset(s+curlen,0,(len-curlen+1)); /* also set trailing \\0 byte */\n    totlen = sh->len+sh->free;\n    sh->len = len;\n    sh->free = totlen-sh->len;\n    return s;\n}\n\n/* Append the specified binary-safe string pointed by 't' of 'len' bytes to the\n * end of the specified sds string 's'.\n *\n * After the call, the passed sds string is no longer valid and all the\n * references must be substituted with the new pointer returned by the call. */\nsds sdscatlen(sds s, const void *t, size_t len) {\n    struct sdshdr *sh;\n    size_t curlen = sdslen(s);\n\n    s = sdsMakeRoomFor(s,len);\n    if (s == NULL) return NULL;\n    sh = (void*) (s-(sizeof(struct sdshdr)));\n    memcpy(s+curlen, t, len);\n    sh->len = curlen+len;\n    sh->free = sh->free-len;\n    s[curlen+len] = '\\0';\n    return s;\n}\n\n/* Append the specified null termianted C string to the sds string 's'.\n *\n * After the call, the passed sds string is no longer valid and all the\n * references must be substituted with the new pointer returned by the call. */\nsds sdscat(sds s, const char *t) {\n    return sdscatlen(s, t, strlen(t));\n}\n\n/* Append the specified sds 't' to the existing sds 's'.\n *\n * After the call, the modified sds string is no longer valid and all the\n * references must be substituted with the new pointer returned by the call. */\nsds sdscatsds(sds s, const sds t) {\n    return sdscatlen(s, t, sdslen(t));\n}\n\n/* Destructively modify the sds string 's' to hold the specified binary\n * safe string pointed by 't' of length 'len' bytes. */\nsds sdscpylen(sds s, const char *t, size_t len) {\n    struct sdshdr *sh = (void*) (s-(sizeof(struct sdshdr)));\n    size_t totlen = sh->free+sh->len;\n\n    if (totlen < len) {\n        s = sdsMakeRoomFor(s,len-sh->len);\n        if (s == NULL) return NULL;\n        sh = (void*) (s-(sizeof(struct sdshdr)));\n        totlen = sh->free+sh->len;\n    }\n    memcpy(s, t, len);\n    s[len] = '\\0';\n    sh->len = len;\n    sh->free = totlen-len;\n    return s;\n}\n\n/* Like sdscpylen() but 't' must be a null-termined string so that the length\n * of the string is obtained with strlen(). */\nsds sdscpy(sds s, const char *t) {\n    return sdscpylen(s, t, strlen(t));\n}\n\n/* Helper for sdscatlonglong() doing the actual number -> string\n * conversion. 's' must point to a string with room for at least\n * SDS_LLSTR_SIZE bytes.\n *\n * The function returns the lenght of the null-terminated string\n * representation stored at 's'. */\n#define SDS_LLSTR_SIZE 21\nint sdsll2str(char *s, long long value) {\n    char *p, aux;\n    unsigned long long v;\n    size_t l;\n\n    /* Generate the string representation, this method produces\n     * an reversed string. */\n    v = (value < 0) ? -value : value;\n    p = s;\n    do {\n        *p++ = '0'+(v%10);\n        v /= 10;\n    } while(v);\n    if (value < 0) *p++ = '-';\n\n    /* Compute length and add null term. */\n    l = p-s;\n    *p = '\\0';\n\n    /* Reverse the string. */\n    p--;\n    while(s < p) {\n        aux = *s;\n        *s = *p;\n        *p = aux;\n        s++;\n        p--;\n    }\n    return l;\n}\n\n/* Identical sdsll2str(), but for unsigned long long type. */\nint sdsull2str(char *s, unsigned long long v) {\n    char *p, aux;\n    size_t l;\n\n    /* Generate the string representation, this method produces\n     * an reversed string. */\n    p = s;\n    do {\n        *p++ = '0'+(v%10);\n        v /= 10;\n    } while(v);\n\n    /* Compute length and add null term. */\n    l = p-s;\n    *p = '\\0';\n\n    /* Reverse the string. */\n    p--;\n    while(s < p) {\n        aux = *s;\n        *s = *p;\n        *p = aux;\n        s++;\n        p--;\n    }\n    return l;\n}\n\n/* Create an sds string from a long long value. It is much faster than:\n *\n * sdscatprintf(sdsempty(),\"%lld\\n\", value);\n */\nsds sdsfromlonglong(long long value) {\n    char buf[SDS_LLSTR_SIZE];\n    int len = sdsll2str(buf,value);\n\n    return sdsnewlen(buf,len);\n}\n\n/* Like sdscatpritf() but gets va_list instead of being variadic. */\nsds sdscatvprintf(sds s, const char *fmt, va_list ap) {\n    va_list cpy;\n    char staticbuf[1024], *buf = staticbuf, *t;\n    size_t buflen = strlen(fmt)*2;\n\n    /* We try to start using a static buffer for speed.\n     * If not possible we revert to heap allocation. */\n    if (buflen > sizeof(staticbuf)) {\n        buf = zmalloc(buflen);\n        if (buf == NULL) return NULL;\n    } else {\n        buflen = sizeof(staticbuf);\n    }\n\n    /* Try with buffers two times bigger every time we fail to\n     * fit the string in the current buffer size. */\n    while(1) {\n        buf[buflen-2] = '\\0';\n        va_copy(cpy,ap);\n        vsnprintf(buf, buflen, fmt, cpy);\n        va_end(ap);\n        if (buf[buflen-2] != '\\0') {\n            if (buf != staticbuf) zfree(buf);\n            buflen *= 2;\n            buf = zmalloc(buflen);\n            if (buf == NULL) return NULL;\n            continue;\n        }\n        break;\n    }\n\n    /* Finally concat the obtained string to the SDS string and return it. */\n    t = sdscat(s, buf);\n    if (buf != staticbuf) zfree(buf);\n    return t;\n}\n\n/* Append to the sds string 's' a string obtained using printf-alike format\n * specifier.\n *\n * After the call, the modified sds string is no longer valid and all the\n * references must be substituted with the new pointer returned by the call.\n *\n * Example:\n *\n * s = sdsempty(\"Sum is: \");\n * s = sdscatprintf(s,\"%d+%d = %d\",a,b,a+b).\n *\n * Often you need to create a string from scratch with the printf-alike\n * format. When this is the need, just use sdsempty() as the target string:\n *\n * s = sdscatprintf(sdsempty(), \"... your format ...\", args);\n */\nsds sdscatprintf(sds s, const char *fmt, ...) {\n    va_list ap;\n    char *t;\n    va_start(ap, fmt);\n    t = sdscatvprintf(s,fmt,ap);\n    va_end(ap);\n    return t;\n}\n\n/* This function is similar to sdscatprintf, but much faster as it does\n * not rely on sprintf() family functions implemented by the libc that\n * are often very slow. Moreover directly handling the sds string as\n * new data is concatenated provides a performance improvement.\n *\n * However this function only handles an incompatible subset of printf-alike\n * format specifiers:\n *\n * %s - C String\n * %S - SDS string\n * %i - signed int\n * %I - 64 bit signed integer (long long, int64_t)\n * %u - unsigned int\n * %U - 64 bit unsigned integer (unsigned long long, uint64_t)\n * %% - Verbatim \"%\" character.\n */\nsds sdscatfmt(sds s, char const *fmt, ...) {\n    struct sdshdr *sh = (void*) (s-(sizeof(struct sdshdr)));\n    size_t initlen = sdslen(s);\n    const char *f = fmt;\n    int i;\n    va_list ap;\n\n    va_start(ap,fmt);\n    f = fmt;    /* Next format specifier byte to process. */\n    i = initlen; /* Position of the next byte to write to dest str. */\n    while(*f) {\n        char next, *str;\n        unsigned int l;\n        long long num;\n        unsigned long long unum;\n\n        /* Make sure there is always space for at least 1 char. */\n        if (sh->free == 0) {\n            s = sdsMakeRoomFor(s,1);\n            sh = (void*) (s-(sizeof(struct sdshdr)));\n        }\n\n        switch(*f) {\n        case '%':\n            next = *(f+1);\n            f++;\n            switch(next) {\n            case 's':\n            case 'S':\n                str = va_arg(ap,char*);\n                l = (next == 's') ? strlen(str) : sdslen(str);\n                if (sh->free < l) {\n                    s = sdsMakeRoomFor(s,l);\n                    sh = (void*) (s-(sizeof(struct sdshdr)));\n                }\n                memcpy(s+i,str,l);\n                sh->len += l;\n                sh->free -= l;\n                i += l;\n                break;\n            case 'i':\n            case 'I':\n                if (next == 'i')\n                    num = va_arg(ap,int);\n                else\n                    num = va_arg(ap,long long);\n                {\n                    char buf[SDS_LLSTR_SIZE];\n                    l = sdsll2str(buf,num);\n                    if (sh->free < l) {\n                        s = sdsMakeRoomFor(s,l);\n                        sh = (void*) (s-(sizeof(struct sdshdr)));\n                    }\n                    memcpy(s+i,buf,l);\n                    sh->len += l;\n                    sh->free -= l;\n                    i += l;\n                }\n                break;\n            case 'u':\n            case 'U':\n                if (next == 'u')\n                    unum = va_arg(ap,unsigned int);\n                else\n                    unum = va_arg(ap,unsigned long long);\n                {\n                    char buf[SDS_LLSTR_SIZE];\n                    l = sdsull2str(buf,unum);\n                    if (sh->free < l) {\n                        s = sdsMakeRoomFor(s,l);\n                        sh = (void*) (s-(sizeof(struct sdshdr)));\n                    }\n                    memcpy(s+i,buf,l);\n                    sh->len += l;\n                    sh->free -= l;\n                    i += l;\n                }\n                break;\n            default: /* Handle %% and generally %<unknown>. */\n                s[i++] = next;\n                sh->len += 1;\n                sh->free -= 1;\n                break;\n            }\n            break;\n        default:\n            s[i++] = *f;\n            sh->len += 1;\n            sh->free -= 1;\n            break;\n        }\n        f++;\n    }\n    va_end(ap);\n\n    /* Add null-term */\n    s[i] = '\\0';\n    return s;\n}\n\n/* Remove the part of the string from left and from right composed just of\n * contiguous characters found in 'cset', that is a null terminted C string.\n *\n * After the call, the modified sds string is no longer valid and all the\n * references must be substituted with the new pointer returned by the call.\n *\n * Example:\n *\n * s = sdsnew(\"AA...AA.a.aa.aHelloWorld     :::\");\n * s = sdstrim(s,\"A. :\");\n * printf(\"%s\\n\", s);\n *\n * Output will be just \"Hello World\".\n */\nsds sdstrim(sds s, const char *cset) {\n    struct sdshdr *sh = (void*) (s-(sizeof(struct sdshdr)));\n    char *start, *end, *sp, *ep;\n    size_t len;\n\n    sp = start = s;\n    ep = end = s+sdslen(s)-1;\n    while(sp <= end && strchr(cset, *sp)) sp++;\n    while(ep > start && strchr(cset, *ep)) ep--;\n    len = (sp > ep) ? 0 : ((ep-sp)+1);\n    if (sh->buf != sp) memmove(sh->buf, sp, len);\n    sh->buf[len] = '\\0';\n    sh->free = sh->free+(sh->len-len);\n    sh->len = len;\n    return s;\n}\n\n/* Turn the string into a smaller (or equal) string containing only the\n * substring specified by the 'start' and 'end' indexes.\n *\n * start and end can be negative, where -1 means the last character of the\n * string, -2 the penultimate character, and so forth.\n *\n * The interval is inclusive, so the start and end characters will be part\n * of the resulting string.\n *\n * The string is modified in-place.\n *\n * Example:\n *\n * s = sdsnew(\"Hello World\");\n * sdsrange(s,1,-1); => \"ello World\"\n */\nvoid sdsrange(sds s, int start, int end) {\n    struct sdshdr *sh = (void*) (s-(sizeof(struct sdshdr)));\n    size_t newlen, len = sdslen(s);\n\n    if (len == 0) return;\n    if (start < 0) {\n        start = len+start;\n        if (start < 0) start = 0;\n    }\n    if (end < 0) {\n        end = len+end;\n        if (end < 0) end = 0;\n    }\n    newlen = (start > end) ? 0 : (end-start)+1;\n    if (newlen != 0) {\n        if (start >= (signed)len) {\n            newlen = 0;\n        } else if (end >= (signed)len) {\n            end = len-1;\n            newlen = (start > end) ? 0 : (end-start)+1;\n        }\n    } else {\n        start = 0;\n    }\n    if (start && newlen) memmove(sh->buf, sh->buf+start, newlen);\n    sh->buf[newlen] = 0;\n    sh->free = sh->free+(sh->len-newlen);\n    sh->len = newlen;\n}\n\n/* Apply tolower() to every character of the sds string 's'. */\nvoid sdstolower(sds s) {\n    int len = sdslen(s), j;\n\n    for (j = 0; j < len; j++) s[j] = tolower(s[j]);\n}\n\n/* Apply toupper() to every character of the sds string 's'. */\nvoid sdstoupper(sds s) {\n    int len = sdslen(s), j;\n\n    for (j = 0; j < len; j++) s[j] = toupper(s[j]);\n}\n\n/* Compare two sds strings s1 and s2 with memcmp().\n *\n * Return value:\n *\n *     1 if s1 > s2.\n *    -1 if s1 < s2.\n *     0 if s1 and s2 are exactly the same binary string.\n *\n * If two strings share exactly the same prefix, but one of the two has\n * additional characters, the longer string is considered to be greater than\n * the smaller one. */\nint sdscmp(const sds s1, const sds s2) {\n    size_t l1, l2, minlen;\n    int cmp;\n\n    l1 = sdslen(s1);\n    l2 = sdslen(s2);\n    minlen = (l1 < l2) ? l1 : l2;\n    cmp = memcmp(s1,s2,minlen);\n    if (cmp == 0) return l1-l2;\n    return cmp;\n}\n\n/* Split 's' with separator in 'sep'. An array\n * of sds strings is returned. *count will be set\n * by reference to the number of tokens returned.\n *\n * On out of memory, zero length string, zero length\n * separator, NULL is returned.\n *\n * Note that 'sep' is able to split a string using\n * a multi-character separator. For example\n * sdssplit(\"foo_-_bar\",\"_-_\"); will return two\n * elements \"foo\" and \"bar\".\n *\n * This version of the function is binary-safe but\n * requires length arguments. sdssplit() is just the\n * same function but for zero-terminated strings.\n */\nsds *sdssplitlen(const char *s, int len, const char *sep, int seplen, int *count) {\n    int elements = 0, slots = 5, start = 0, j;\n    sds *tokens;\n\n    if (seplen < 1 || len < 0) return NULL;\n\n    tokens = zmalloc(sizeof(sds)*slots);\n    if (tokens == NULL) return NULL;\n\n    if (len == 0) {\n        *count = 0;\n        return tokens;\n    }\n    for (j = 0; j < (len-(seplen-1)); j++) {\n        /* make sure there is room for the next element and the final one */\n        if (slots < elements+2) {\n            sds *newtokens;\n\n            slots *= 2;\n            newtokens = zrealloc(tokens,sizeof(sds)*slots);\n            if (newtokens == NULL) goto cleanup;\n            tokens = newtokens;\n        }\n        /* search the separator */\n        if ((seplen == 1 && *(s+j) == sep[0]) || (memcmp(s+j,sep,seplen) == 0)) {\n            tokens[elements] = sdsnewlen(s+start,j-start);\n            if (tokens[elements] == NULL) goto cleanup;\n            elements++;\n            start = j+seplen;\n            j = j+seplen-1; /* skip the separator */\n        }\n    }\n    /* Add the final element. We are sure there is room in the tokens array. */\n    tokens[elements] = sdsnewlen(s+start,len-start);\n    if (tokens[elements] == NULL) goto cleanup;\n    elements++;\n    *count = elements;\n    return tokens;\n\ncleanup:\n    {\n        int i;\n        for (i = 0; i < elements; i++) sdsfree(tokens[i]);\n        zfree(tokens);\n        *count = 0;\n        return NULL;\n    }\n}\n\n/* Free the result returned by sdssplitlen(), or do nothing if 'tokens' is NULL. */\nvoid sdsfreesplitres(sds *tokens, int count) {\n    if (!tokens) return;\n    while(count--)\n        sdsfree(tokens[count]);\n    zfree(tokens);\n}\n\n/* Append to the sds string \"s\" an escaped string representation where\n * all the non-printable characters (tested with isprint()) are turned into\n * escapes in the form \"\\n\\r\\a....\" or \"\\x<hex-number>\".\n *\n * After the call, the modified sds string is no longer valid and all the\n * references must be substituted with the new pointer returned by the call. */\nsds sdscatrepr(sds s, const char *p, size_t len) {\n    s = sdscatlen(s,\"\\\"\",1);\n    while(len--) {\n        switch(*p) {\n        case '\\\\':\n        case '\"':\n            s = sdscatprintf(s,\"\\\\%c\",*p);\n            break;\n        case '\\n': s = sdscatlen(s,\"\\\\n\",2); break;\n        case '\\r': s = sdscatlen(s,\"\\\\r\",2); break;\n        case '\\t': s = sdscatlen(s,\"\\\\t\",2); break;\n        case '\\a': s = sdscatlen(s,\"\\\\a\",2); break;\n        case '\\b': s = sdscatlen(s,\"\\\\b\",2); break;\n        default:\n            if (isprint(*p))\n                s = sdscatprintf(s,\"%c\",*p);\n            else\n                s = sdscatprintf(s,\"\\\\x%02x\",(unsigned char)*p);\n            break;\n        }\n        p++;\n    }\n    return sdscatlen(s,\"\\\"\",1);\n}\n\n/* Helper function for sdssplitargs() that returns non zero if 'c'\n * is a valid hex digit. */\nint is_hex_digit(char c) {\n    return (c >= '0' && c <= '9') || (c >= 'a' && c <= 'f') ||\n           (c >= 'A' && c <= 'F');\n}\n\n/* Helper function for sdssplitargs() that converts a hex digit into an\n * integer from 0 to 15 */\nint hex_digit_to_int(char c) {\n    switch(c) {\n    case '0': return 0;\n    case '1': return 1;\n    case '2': return 2;\n    case '3': return 3;\n    case '4': return 4;\n    case '5': return 5;\n    case '6': return 6;\n    case '7': return 7;\n    case '8': return 8;\n    case '9': return 9;\n    case 'a': case 'A': return 10;\n    case 'b': case 'B': return 11;\n    case 'c': case 'C': return 12;\n    case 'd': case 'D': return 13;\n    case 'e': case 'E': return 14;\n    case 'f': case 'F': return 15;\n    default: return 0;\n    }\n}\n\n/* Split a line into arguments, where every argument can be in the\n * following programming-language REPL-alike form:\n *\n * foo bar \"newline are supported\\n\" and \"\\xff\\x00otherstuff\"\n *\n * The number of arguments is stored into *argc, and an array\n * of sds is returned.\n *\n * The caller should free the resulting array of sds strings with\n * sdsfreesplitres().\n *\n * Note that sdscatrepr() is able to convert back a string into\n * a quoted string in the same format sdssplitargs() is able to parse.\n *\n * The function returns the allocated tokens on success, even when the\n * input string is empty, or NULL if the input contains unbalanced\n * quotes or closed quotes followed by non space characters\n * as in: \"foo\"bar or \"foo'\n */\nsds *sdssplitargs(const char *line, int *argc) {\n    const char *p = line;\n    char *current = NULL;\n    char **vector = NULL;\n\n    *argc = 0;\n    while(1) {\n        /* skip blanks */\n        while(*p && isspace(*p)) p++;\n        if (*p) {\n            /* get a token */\n            int inq=0;  /* set to 1 if we are in \"quotes\" */\n            int insq=0; /* set to 1 if we are in 'single quotes' */\n            int done=0;\n\n            if (current == NULL) current = sdsempty();\n            while(!done) {\n                if (inq) {\n                    if (*p == '\\\\' && *(p+1) == 'x' &&\n                                             is_hex_digit(*(p+2)) &&\n                                             is_hex_digit(*(p+3)))\n                    {\n                        unsigned char byte;\n\n                        byte = (hex_digit_to_int(*(p+2))*16)+\n                                hex_digit_to_int(*(p+3));\n                        current = sdscatlen(current,(char*)&byte,1);\n                        p += 3;\n                    } else if (*p == '\\\\' && *(p+1)) {\n                        char c;\n\n                        p++;\n                        switch(*p) {\n                        case 'n': c = '\\n'; break;\n                        case 'r': c = '\\r'; break;\n                        case 't': c = '\\t'; break;\n                        case 'b': c = '\\b'; break;\n                        case 'a': c = '\\a'; break;\n                        default: c = *p; break;\n                        }\n                        current = sdscatlen(current,&c,1);\n                    } else if (*p == '\"') {\n                        /* closing quote must be followed by a space or\n                         * nothing at all. */\n                        if (*(p+1) && !isspace(*(p+1))) goto err;\n                        done=1;\n                    } else if (!*p) {\n                        /* unterminated quotes */\n                        goto err;\n                    } else {\n                        current = sdscatlen(current,p,1);\n                    }\n                } else if (insq) {\n                    if (*p == '\\\\' && *(p+1) == '\\'') {\n                        p++;\n                        current = sdscatlen(current,\"'\",1);\n                    } else if (*p == '\\'') {\n                        /* closing quote must be followed by a space or\n                         * nothing at all. */\n                        if (*(p+1) && !isspace(*(p+1))) goto err;\n                        done=1;\n                    } else if (!*p) {\n                        /* unterminated quotes */\n                        goto err;\n                    } else {\n                        current = sdscatlen(current,p,1);\n                    }\n                } else {\n                    switch(*p) {\n                    case ' ':\n                    case '\\n':\n                    case '\\r':\n                    case '\\t':\n                    case '\\0':\n                        done=1;\n                        break;\n                    case '\"':\n                        inq=1;\n                        break;\n                    case '\\'':\n                        insq=1;\n                        break;\n                    default:\n                        current = sdscatlen(current,p,1);\n                        break;\n                    }\n                }\n                if (*p) p++;\n            }\n            /* add the token to the vector */\n            vector = zrealloc(vector,((*argc)+1)*sizeof(char*));\n            vector[*argc] = current;\n            (*argc)++;\n            current = NULL;\n        } else {\n            /* Even on empty input string return something not NULL. */\n            if (vector == NULL) vector = zmalloc(sizeof(void*));\n            return vector;\n        }\n    }\n\nerr:\n    while((*argc)--)\n        sdsfree(vector[*argc]);\n    zfree(vector);\n    if (current) sdsfree(current);\n    *argc = 0;\n    return NULL;\n}\n\n/* Modify the string substituting all the occurrences of the set of\n * characters specified in the 'from' string to the corresponding character\n * in the 'to' array.\n *\n * For instance: sdsmapchars(mystring, \"ho\", \"01\", 2)\n * will have the effect of turning the string \"hello\" into \"0ell1\".\n *\n * The function returns the sds string pointer, that is always the same\n * as the input pointer since no resize is needed. */\nsds sdsmapchars(sds s, const char *from, const char *to, size_t setlen) {\n    size_t j, i, l = sdslen(s);\n\n    for (j = 0; j < l; j++) {\n        for (i = 0; i < setlen; i++) {\n            if (s[j] == from[i]) {\n                s[j] = to[i];\n                break;\n            }\n        }\n    }\n    return s;\n}\n\n/* Join an array of C strings using the specified separator (also a C string).\n * Returns the result as an sds string. */\nsds sdsjoin(char **argv, int argc, char *sep) {\n    sds join = sdsempty();\n    int j;\n\n    for (j = 0; j < argc; j++) {\n        join = sdscat(join, argv[j]);\n        if (j != argc-1) join = sdscat(join,sep);\n    }\n    return join;\n}\n\n#ifdef SDS_TEST_MAIN\n#include <stdio.h>\n#include \"testhelp.h\"\n#include \"limits.h\"\n\nint main(void) {\n    {\n        struct sdshdr *sh;\n        sds x = sdsnew(\"foo\"), y;\n\n        test_cond(\"Create a string and obtain the length\",\n            sdslen(x) == 3 && memcmp(x,\"foo\\0\",4) == 0)\n\n        sdsfree(x);\n        x = sdsnewlen(\"foo\",2);\n        test_cond(\"Create a string with specified length\",\n            sdslen(x) == 2 && memcmp(x,\"fo\\0\",3) == 0)\n\n        x = sdscat(x,\"bar\");\n        test_cond(\"Strings concatenation\",\n            sdslen(x) == 5 && memcmp(x,\"fobar\\0\",6) == 0);\n\n        x = sdscpy(x,\"a\");\n        test_cond(\"sdscpy() against an originally longer string\",\n            sdslen(x) == 1 && memcmp(x,\"a\\0\",2) == 0)\n\n        x = sdscpy(x,\"xyzxxxxxxxxxxyyyyyyyyyykkkkkkkkkk\");\n        test_cond(\"sdscpy() against an originally shorter string\",\n            sdslen(x) == 33 &&\n            memcmp(x,\"xyzxxxxxxxxxxyyyyyyyyyykkkkkkkkkk\\0\",33) == 0)\n\n        sdsfree(x);\n        x = sdscatprintf(sdsempty(),\"%d\",123);\n        test_cond(\"sdscatprintf() seems working in the base case\",\n            sdslen(x) == 3 && memcmp(x,\"123\\0\",4) == 0)\n\n        sdsfree(x);\n        x = sdsnew(\"--\");\n        x = sdscatfmt(x, \"Hello %s World %I,%I--\", \"Hi!\", LLONG_MIN,LLONG_MAX);\n        test_cond(\"sdscatfmt() seems working in the base case\",\n            sdslen(x) == 60 &&\n            memcmp(x,\"--Hello Hi! World -9223372036854775808,\"\n                     \"9223372036854775807--\",60) == 0)\n\n        sdsfree(x);\n        x = sdsnew(\"--\");\n        x = sdscatfmt(x, \"%u,%U--\", UINT_MAX, ULLONG_MAX);\n        test_cond(\"sdscatfmt() seems working with unsigned numbers\",\n            sdslen(x) == 35 &&\n            memcmp(x,\"--4294967295,18446744073709551615--\",35) == 0)\n\n        sdsfree(x);\n        x = sdsnew(\"xxciaoyyy\");\n        sdstrim(x,\"xy\");\n        test_cond(\"sdstrim() correctly trims characters\",\n            sdslen(x) == 4 && memcmp(x,\"ciao\\0\",5) == 0)\n\n        y = sdsdup(x);\n        sdsrange(y,1,1);\n        test_cond(\"sdsrange(...,1,1)\",\n            sdslen(y) == 1 && memcmp(y,\"i\\0\",2) == 0)\n\n        sdsfree(y);\n        y = sdsdup(x);\n        sdsrange(y,1,-1);\n        test_cond(\"sdsrange(...,1,-1)\",\n            sdslen(y) == 3 && memcmp(y,\"iao\\0\",4) == 0)\n\n        sdsfree(y);\n        y = sdsdup(x);\n        sdsrange(y,-2,-1);\n        test_cond(\"sdsrange(...,-2,-1)\",\n            sdslen(y) == 2 && memcmp(y,\"ao\\0\",3) == 0)\n\n        sdsfree(y);\n        y = sdsdup(x);\n        sdsrange(y,2,1);\n        test_cond(\"sdsrange(...,2,1)\",\n            sdslen(y) == 0 && memcmp(y,\"\\0\",1) == 0)\n\n        sdsfree(y);\n        y = sdsdup(x);\n        sdsrange(y,1,100);\n        test_cond(\"sdsrange(...,1,100)\",\n            sdslen(y) == 3 && memcmp(y,\"iao\\0\",4) == 0)\n\n        sdsfree(y);\n        y = sdsdup(x);\n        sdsrange(y,100,100);\n        test_cond(\"sdsrange(...,100,100)\",\n            sdslen(y) == 0 && memcmp(y,\"\\0\",1) == 0)\n\n        sdsfree(y);\n        sdsfree(x);\n        x = sdsnew(\"foo\");\n        y = sdsnew(\"foa\");\n        test_cond(\"sdscmp(foo,foa)\", sdscmp(x,y) > 0)\n\n        sdsfree(y);\n        sdsfree(x);\n        x = sdsnew(\"bar\");\n        y = sdsnew(\"bar\");\n        test_cond(\"sdscmp(bar,bar)\", sdscmp(x,y) == 0)\n\n        sdsfree(y);\n        sdsfree(x);\n        x = sdsnew(\"aar\");\n        y = sdsnew(\"bar\");\n        test_cond(\"sdscmp(bar,bar)\", sdscmp(x,y) < 0)\n\n        sdsfree(y);\n        sdsfree(x);\n        x = sdsnewlen(\"\\a\\n\\0foo\\r\",7);\n        y = sdscatrepr(sdsempty(),x,sdslen(x));\n        test_cond(\"sdscatrepr(...data...)\",\n            memcmp(y,\"\\\"\\\\a\\\\n\\\\x00foo\\\\r\\\"\",15) == 0)\n\n        {\n            int oldfree;\n\n            sdsfree(x);\n            x = sdsnew(\"0\");\n            sh = (void*) (x-(sizeof(struct sdshdr)));\n            test_cond(\"sdsnew() free/len buffers\", sh->len == 1 && sh->free == 0);\n            x = sdsMakeRoomFor(x,1);\n            sh = (void*) (x-(sizeof(struct sdshdr)));\n            test_cond(\"sdsMakeRoomFor()\", sh->len == 1 && sh->free > 0);\n            oldfree = sh->free;\n            x[1] = '1';\n            sdsIncrLen(x,1);\n            test_cond(\"sdsIncrLen() -- content\", x[0] == '0' && x[1] == '1');\n            test_cond(\"sdsIncrLen() -- len\", sh->len == 2);\n            test_cond(\"sdsIncrLen() -- free\", sh->free == oldfree-1);\n        }\n    }\n    test_report()\n    return 0;\n}\n#endif\n"
  },
  {
    "path": "extern/deprecated/redis-2.8.21/deps/hiredis/sds.h",
    "content": "/* SDSLib, A C dynamic strings library\n *\n * Copyright (c) 2006-2010, Salvatore Sanfilippo <antirez at gmail dot com>\n * All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions are met:\n *\n *   * Redistributions of source code must retain the above copyright notice,\n *     this list of conditions and the following disclaimer.\n *   * Redistributions in binary form must reproduce the above copyright\n *     notice, this list of conditions and the following disclaimer in the\n *     documentation and/or other materials provided with the distribution.\n *   * Neither the name of Redis nor the names of its contributors may be used\n *     to endorse or promote products derived from this software without\n *     specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\"\n * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\n * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE\n * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR\n * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF\n * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS\n * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN\n * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)\n * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE\n * POSSIBILITY OF SUCH DAMAGE.\n */\n\n#ifndef __SDS_H\n#define __SDS_H\n\n#define SDS_MAX_PREALLOC (1024*1024)\n\n#include <sys/types.h>\n#include <stdarg.h>\n\ntypedef char *sds;\n\nstruct sdshdr {\n    unsigned int len;\n    unsigned int free;\n    char buf[];\n};\n\nstatic inline size_t sdslen(const sds s) {\n    struct sdshdr *sh = (void*)(s-(sizeof(struct sdshdr)));\n    return sh->len;\n}\n\nstatic inline size_t sdsavail(const sds s) {\n    struct sdshdr *sh = (void*)(s-(sizeof(struct sdshdr)));\n    return sh->free;\n}\n\nsds sdsnewlen(const void *init, size_t initlen);\nsds sdsnew(const char *init);\nsds sdsempty(void);\nsize_t sdslen(const sds s);\nsds sdsdup(const sds s);\nvoid sdsfree(sds s);\nsize_t sdsavail(const sds s);\nsds sdsgrowzero(sds s, size_t len);\nsds sdscatlen(sds s, const void *t, size_t len);\nsds sdscat(sds s, const char *t);\nsds sdscatsds(sds s, const sds t);\nsds sdscpylen(sds s, const char *t, size_t len);\nsds sdscpy(sds s, const char *t);\n\nsds sdscatvprintf(sds s, const char *fmt, va_list ap);\n#ifdef __GNUC__\nsds sdscatprintf(sds s, const char *fmt, ...)\n    __attribute__((format(printf, 2, 3)));\n#else\nsds sdscatprintf(sds s, const char *fmt, ...);\n#endif\n\nsds sdscatfmt(sds s, char const *fmt, ...);\nsds sdstrim(sds s, const char *cset);\nvoid sdsrange(sds s, int start, int end);\nvoid sdsupdatelen(sds s);\nvoid sdsclear(sds s);\nint sdscmp(const sds s1, const sds s2);\nsds *sdssplitlen(const char *s, int len, const char *sep, int seplen, int *count);\nvoid sdsfreesplitres(sds *tokens, int count);\nvoid sdstolower(sds s);\nvoid sdstoupper(sds s);\nsds sdsfromlonglong(long long value);\nsds sdscatrepr(sds s, const char *p, size_t len);\nsds *sdssplitargs(const char *line, int *argc);\nsds sdsmapchars(sds s, const char *from, const char *to, size_t setlen);\nsds sdsjoin(char **argv, int argc, char *sep);\n\n/* Low level functions exposed to the user API */\nsds sdsMakeRoomFor(sds s, size_t addlen);\nvoid sdsIncrLen(sds s, int incr);\nsds sdsRemoveFreeSpace(sds s);\nsize_t sdsAllocSize(sds s);\n\n#endif\n"
  },
  {
    "path": "extern/deprecated/redis-2.8.21/deps/hiredis/test.c",
    "content": "#include \"fmacros.h\"\n#include <stdio.h>\n#include <stdlib.h>\n#include <string.h>\n#include <strings.h>\n#include <sys/time.h>\n#include <assert.h>\n#include <unistd.h>\n#include <signal.h>\n#include <errno.h>\n#include <limits.h>\n\n#include \"hiredis.h\"\n\nenum connection_type {\n    CONN_TCP,\n    CONN_UNIX,\n    CONN_FD\n};\n\nstruct config {\n    enum connection_type type;\n\n    struct {\n        const char *host;\n        int port;\n        struct timeval timeout;\n    } tcp;\n\n    struct {\n        const char *path;\n    } unix;\n};\n\n/* The following lines make up our testing \"framework\" :) */\nstatic int tests = 0, fails = 0;\n#define test(_s) { printf(\"#%02d \", ++tests); printf(_s); }\n#define test_cond(_c) if(_c) printf(\"\\033[0;32mPASSED\\033[0;0m\\n\"); else {printf(\"\\033[0;31mFAILED\\033[0;0m\\n\"); fails++;}\n\nstatic long long usec(void) {\n    struct timeval tv;\n    gettimeofday(&tv,NULL);\n    return (((long long)tv.tv_sec)*1000000)+tv.tv_usec;\n}\n\nstatic redisContext *select_database(redisContext *c) {\n    redisReply *reply;\n\n    /* Switch to DB 9 for testing, now that we know we can chat. */\n    reply = redisCommand(c,\"SELECT 9\");\n    assert(reply != NULL);\n    freeReplyObject(reply);\n\n    /* Make sure the DB is empty */\n    reply = redisCommand(c,\"DBSIZE\");\n    assert(reply != NULL);\n    if (reply->type == REDIS_REPLY_INTEGER && reply->integer == 0) {\n        /* Awesome, DB 9 is empty and we can continue. */\n        freeReplyObject(reply);\n    } else {\n        printf(\"Database #9 is not empty, test can not continue\\n\");\n        exit(1);\n    }\n\n    return c;\n}\n\nstatic int disconnect(redisContext *c, int keep_fd) {\n    redisReply *reply;\n\n    /* Make sure we're on DB 9. */\n    reply = redisCommand(c,\"SELECT 9\");\n    assert(reply != NULL);\n    freeReplyObject(reply);\n    reply = redisCommand(c,\"FLUSHDB\");\n    assert(reply != NULL);\n    freeReplyObject(reply);\n\n    /* Free the context as well, but keep the fd if requested. */\n    if (keep_fd)\n        return redisFreeKeepFd(c);\n    redisFree(c);\n    return -1;\n}\n\nstatic redisContext *connect(struct config config) {\n    redisContext *c = NULL;\n\n    if (config.type == CONN_TCP) {\n        c = redisConnect(config.tcp.host, config.tcp.port);\n    } else if (config.type == CONN_UNIX) {\n        c = redisConnectUnix(config.unix.path);\n    } else if (config.type == CONN_FD) {\n        /* Create a dummy connection just to get an fd to inherit */\n        redisContext *dummy_ctx = redisConnectUnix(config.unix.path);\n        if (dummy_ctx) {\n            int fd = disconnect(dummy_ctx, 1);\n            printf(\"Connecting to inherited fd %d\\n\", fd);\n            c = redisConnectFd(fd);\n        }\n    } else {\n        assert(NULL);\n    }\n\n    if (c == NULL) {\n        printf(\"Connection error: can't allocate redis context\\n\");\n        exit(1);\n    } else if (c->err) {\n        printf(\"Connection error: %s\\n\", c->errstr);\n        exit(1);\n    }\n\n    return select_database(c);\n}\n\nstatic void test_format_commands(void) {\n    char *cmd;\n    int len;\n\n    test(\"Format command without interpolation: \");\n    len = redisFormatCommand(&cmd,\"SET foo bar\");\n    test_cond(strncmp(cmd,\"*3\\r\\n$3\\r\\nSET\\r\\n$3\\r\\nfoo\\r\\n$3\\r\\nbar\\r\\n\",len) == 0 &&\n        len == 4+4+(3+2)+4+(3+2)+4+(3+2));\n    free(cmd);\n\n    test(\"Format command with %%s string interpolation: \");\n    len = redisFormatCommand(&cmd,\"SET %s %s\",\"foo\",\"bar\");\n    test_cond(strncmp(cmd,\"*3\\r\\n$3\\r\\nSET\\r\\n$3\\r\\nfoo\\r\\n$3\\r\\nbar\\r\\n\",len) == 0 &&\n        len == 4+4+(3+2)+4+(3+2)+4+(3+2));\n    free(cmd);\n\n    test(\"Format command with %%s and an empty string: \");\n    len = redisFormatCommand(&cmd,\"SET %s %s\",\"foo\",\"\");\n    test_cond(strncmp(cmd,\"*3\\r\\n$3\\r\\nSET\\r\\n$3\\r\\nfoo\\r\\n$0\\r\\n\\r\\n\",len) == 0 &&\n        len == 4+4+(3+2)+4+(3+2)+4+(0+2));\n    free(cmd);\n\n    test(\"Format command with an empty string in between proper interpolations: \");\n    len = redisFormatCommand(&cmd,\"SET %s %s\",\"\",\"foo\");\n    test_cond(strncmp(cmd,\"*3\\r\\n$3\\r\\nSET\\r\\n$0\\r\\n\\r\\n$3\\r\\nfoo\\r\\n\",len) == 0 &&\n        len == 4+4+(3+2)+4+(0+2)+4+(3+2));\n    free(cmd);\n\n    test(\"Format command with %%b string interpolation: \");\n    len = redisFormatCommand(&cmd,\"SET %b %b\",\"foo\",(size_t)3,\"b\\0r\",(size_t)3);\n    test_cond(strncmp(cmd,\"*3\\r\\n$3\\r\\nSET\\r\\n$3\\r\\nfoo\\r\\n$3\\r\\nb\\0r\\r\\n\",len) == 0 &&\n        len == 4+4+(3+2)+4+(3+2)+4+(3+2));\n    free(cmd);\n\n    test(\"Format command with %%b and an empty string: \");\n    len = redisFormatCommand(&cmd,\"SET %b %b\",\"foo\",(size_t)3,\"\",(size_t)0);\n    test_cond(strncmp(cmd,\"*3\\r\\n$3\\r\\nSET\\r\\n$3\\r\\nfoo\\r\\n$0\\r\\n\\r\\n\",len) == 0 &&\n        len == 4+4+(3+2)+4+(3+2)+4+(0+2));\n    free(cmd);\n\n    test(\"Format command with literal %%: \");\n    len = redisFormatCommand(&cmd,\"SET %% %%\");\n    test_cond(strncmp(cmd,\"*3\\r\\n$3\\r\\nSET\\r\\n$1\\r\\n%\\r\\n$1\\r\\n%\\r\\n\",len) == 0 &&\n        len == 4+4+(3+2)+4+(1+2)+4+(1+2));\n    free(cmd);\n\n    /* Vararg width depends on the type. These tests make sure that the\n     * width is correctly determined using the format and subsequent varargs\n     * can correctly be interpolated. */\n#define INTEGER_WIDTH_TEST(fmt, type) do {                                                \\\n    type value = 123;                                                                     \\\n    test(\"Format command with printf-delegation (\" #type \"): \");                          \\\n    len = redisFormatCommand(&cmd,\"key:%08\" fmt \" str:%s\", value, \"hello\");               \\\n    test_cond(strncmp(cmd,\"*2\\r\\n$12\\r\\nkey:00000123\\r\\n$9\\r\\nstr:hello\\r\\n\",len) == 0 && \\\n        len == 4+5+(12+2)+4+(9+2));                                                       \\\n    free(cmd);                                                                            \\\n} while(0)\n\n#define FLOAT_WIDTH_TEST(type) do {                                                       \\\n    type value = 123.0;                                                                   \\\n    test(\"Format command with printf-delegation (\" #type \"): \");                          \\\n    len = redisFormatCommand(&cmd,\"key:%08.3f str:%s\", value, \"hello\");                   \\\n    test_cond(strncmp(cmd,\"*2\\r\\n$12\\r\\nkey:0123.000\\r\\n$9\\r\\nstr:hello\\r\\n\",len) == 0 && \\\n        len == 4+5+(12+2)+4+(9+2));                                                       \\\n    free(cmd);                                                                            \\\n} while(0)\n\n    INTEGER_WIDTH_TEST(\"d\", int);\n    INTEGER_WIDTH_TEST(\"hhd\", char);\n    INTEGER_WIDTH_TEST(\"hd\", short);\n    INTEGER_WIDTH_TEST(\"ld\", long);\n    INTEGER_WIDTH_TEST(\"lld\", long long);\n    INTEGER_WIDTH_TEST(\"u\", unsigned int);\n    INTEGER_WIDTH_TEST(\"hhu\", unsigned char);\n    INTEGER_WIDTH_TEST(\"hu\", unsigned short);\n    INTEGER_WIDTH_TEST(\"lu\", unsigned long);\n    INTEGER_WIDTH_TEST(\"llu\", unsigned long long);\n    FLOAT_WIDTH_TEST(float);\n    FLOAT_WIDTH_TEST(double);\n\n    test(\"Format command with invalid printf format: \");\n    len = redisFormatCommand(&cmd,\"key:%08p %b\",(void*)1234,\"foo\",(size_t)3);\n    test_cond(len == -1);\n\n    const char *argv[3];\n    argv[0] = \"SET\";\n    argv[1] = \"foo\\0xxx\";\n    argv[2] = \"bar\";\n    size_t lens[3] = { 3, 7, 3 };\n    int argc = 3;\n\n    test(\"Format command by passing argc/argv without lengths: \");\n    len = redisFormatCommandArgv(&cmd,argc,argv,NULL);\n    test_cond(strncmp(cmd,\"*3\\r\\n$3\\r\\nSET\\r\\n$3\\r\\nfoo\\r\\n$3\\r\\nbar\\r\\n\",len) == 0 &&\n        len == 4+4+(3+2)+4+(3+2)+4+(3+2));\n    free(cmd);\n\n    test(\"Format command by passing argc/argv with lengths: \");\n    len = redisFormatCommandArgv(&cmd,argc,argv,lens);\n    test_cond(strncmp(cmd,\"*3\\r\\n$3\\r\\nSET\\r\\n$7\\r\\nfoo\\0xxx\\r\\n$3\\r\\nbar\\r\\n\",len) == 0 &&\n        len == 4+4+(3+2)+4+(7+2)+4+(3+2));\n    free(cmd);\n}\n\nstatic void test_append_formatted_commands(struct config config) {\n    redisContext *c;\n    redisReply *reply;\n    char *cmd;\n    int len;\n\n    c = connect(config);\n\n    test(\"Append format command: \");\n\n    len = redisFormatCommand(&cmd, \"SET foo bar\");\n\n    test_cond(redisAppendFormattedCommand(c, cmd, len) == REDIS_OK);\n\n    assert(redisGetReply(c, (void*)&reply) == REDIS_OK);\n\n    free(cmd);\n    freeReplyObject(reply);\n\n    disconnect(c, 0);\n}\n\nstatic void test_reply_reader(void) {\n    redisReader *reader;\n    void *reply;\n    int ret;\n    int i;\n\n    test(\"Error handling in reply parser: \");\n    reader = redisReaderCreate();\n    redisReaderFeed(reader,(char*)\"@foo\\r\\n\",6);\n    ret = redisReaderGetReply(reader,NULL);\n    test_cond(ret == REDIS_ERR &&\n              strcasecmp(reader->errstr,\"Protocol error, got \\\"@\\\" as reply type byte\") == 0);\n    redisReaderFree(reader);\n\n    /* when the reply already contains multiple items, they must be free'd\n     * on an error. valgrind will bark when this doesn't happen. */\n    test(\"Memory cleanup in reply parser: \");\n    reader = redisReaderCreate();\n    redisReaderFeed(reader,(char*)\"*2\\r\\n\",4);\n    redisReaderFeed(reader,(char*)\"$5\\r\\nhello\\r\\n\",11);\n    redisReaderFeed(reader,(char*)\"@foo\\r\\n\",6);\n    ret = redisReaderGetReply(reader,NULL);\n    test_cond(ret == REDIS_ERR &&\n              strcasecmp(reader->errstr,\"Protocol error, got \\\"@\\\" as reply type byte\") == 0);\n    redisReaderFree(reader);\n\n    test(\"Set error on nested multi bulks with depth > 7: \");\n    reader = redisReaderCreate();\n\n    for (i = 0; i < 9; i++) {\n        redisReaderFeed(reader,(char*)\"*1\\r\\n\",4);\n    }\n\n    ret = redisReaderGetReply(reader,NULL);\n    test_cond(ret == REDIS_ERR &&\n              strncasecmp(reader->errstr,\"No support for\",14) == 0);\n    redisReaderFree(reader);\n\n    test(\"Works with NULL functions for reply: \");\n    reader = redisReaderCreate();\n    reader->fn = NULL;\n    redisReaderFeed(reader,(char*)\"+OK\\r\\n\",5);\n    ret = redisReaderGetReply(reader,&reply);\n    test_cond(ret == REDIS_OK && reply == (void*)REDIS_REPLY_STATUS);\n    redisReaderFree(reader);\n\n    test(\"Works when a single newline (\\\\r\\\\n) covers two calls to feed: \");\n    reader = redisReaderCreate();\n    reader->fn = NULL;\n    redisReaderFeed(reader,(char*)\"+OK\\r\",4);\n    ret = redisReaderGetReply(reader,&reply);\n    assert(ret == REDIS_OK && reply == NULL);\n    redisReaderFeed(reader,(char*)\"\\n\",1);\n    ret = redisReaderGetReply(reader,&reply);\n    test_cond(ret == REDIS_OK && reply == (void*)REDIS_REPLY_STATUS);\n    redisReaderFree(reader);\n\n    test(\"Don't reset state after protocol error: \");\n    reader = redisReaderCreate();\n    reader->fn = NULL;\n    redisReaderFeed(reader,(char*)\"x\",1);\n    ret = redisReaderGetReply(reader,&reply);\n    assert(ret == REDIS_ERR);\n    ret = redisReaderGetReply(reader,&reply);\n    test_cond(ret == REDIS_ERR && reply == NULL);\n    redisReaderFree(reader);\n\n    /* Regression test for issue #45 on GitHub. */\n    test(\"Don't do empty allocation for empty multi bulk: \");\n    reader = redisReaderCreate();\n    redisReaderFeed(reader,(char*)\"*0\\r\\n\",4);\n    ret = redisReaderGetReply(reader,&reply);\n    test_cond(ret == REDIS_OK &&\n        ((redisReply*)reply)->type == REDIS_REPLY_ARRAY &&\n        ((redisReply*)reply)->elements == 0);\n    freeReplyObject(reply);\n    redisReaderFree(reader);\n}\n\nstatic void test_blocking_connection_errors(void) {\n    redisContext *c;\n\n    test(\"Returns error when host cannot be resolved: \");\n    c = redisConnect((char*)\"idontexist.local\", 6379);\n    test_cond(c->err == REDIS_ERR_OTHER &&\n        (strcmp(c->errstr,\"Name or service not known\") == 0 ||\n         strcmp(c->errstr,\"Can't resolve: idontexist.local\") == 0 ||\n         strcmp(c->errstr,\"nodename nor servname provided, or not known\") == 0 ||\n         strcmp(c->errstr,\"No address associated with hostname\") == 0 ||\n         strcmp(c->errstr,\"no address associated with name\") == 0));\n    redisFree(c);\n\n    test(\"Returns error when the port is not open: \");\n    c = redisConnect((char*)\"localhost\", 1);\n    test_cond(c->err == REDIS_ERR_IO &&\n        strcmp(c->errstr,\"Connection refused\") == 0);\n    redisFree(c);\n\n    test(\"Returns error when the unix socket path doesn't accept connections: \");\n    c = redisConnectUnix((char*)\"/tmp/idontexist.sock\");\n    test_cond(c->err == REDIS_ERR_IO); /* Don't care about the message... */\n    redisFree(c);\n}\n\nstatic void test_blocking_connection(struct config config) {\n    redisContext *c;\n    redisReply *reply;\n\n    c = connect(config);\n\n    test(\"Is able to deliver commands: \");\n    reply = redisCommand(c,\"PING\");\n    test_cond(reply->type == REDIS_REPLY_STATUS &&\n        strcasecmp(reply->str,\"pong\") == 0)\n    freeReplyObject(reply);\n\n    test(\"Is a able to send commands verbatim: \");\n    reply = redisCommand(c,\"SET foo bar\");\n    test_cond (reply->type == REDIS_REPLY_STATUS &&\n        strcasecmp(reply->str,\"ok\") == 0)\n    freeReplyObject(reply);\n\n    test(\"%%s String interpolation works: \");\n    reply = redisCommand(c,\"SET %s %s\",\"foo\",\"hello world\");\n    freeReplyObject(reply);\n    reply = redisCommand(c,\"GET foo\");\n    test_cond(reply->type == REDIS_REPLY_STRING &&\n        strcmp(reply->str,\"hello world\") == 0);\n    freeReplyObject(reply);\n\n    test(\"%%b String interpolation works: \");\n    reply = redisCommand(c,\"SET %b %b\",\"foo\",(size_t)3,\"hello\\x00world\",(size_t)11);\n    freeReplyObject(reply);\n    reply = redisCommand(c,\"GET foo\");\n    test_cond(reply->type == REDIS_REPLY_STRING &&\n        memcmp(reply->str,\"hello\\x00world\",11) == 0)\n\n    test(\"Binary reply length is correct: \");\n    test_cond(reply->len == 11)\n    freeReplyObject(reply);\n\n    test(\"Can parse nil replies: \");\n    reply = redisCommand(c,\"GET nokey\");\n    test_cond(reply->type == REDIS_REPLY_NIL)\n    freeReplyObject(reply);\n\n    /* test 7 */\n    test(\"Can parse integer replies: \");\n    reply = redisCommand(c,\"INCR mycounter\");\n    test_cond(reply->type == REDIS_REPLY_INTEGER && reply->integer == 1)\n    freeReplyObject(reply);\n\n    test(\"Can parse multi bulk replies: \");\n    freeReplyObject(redisCommand(c,\"LPUSH mylist foo\"));\n    freeReplyObject(redisCommand(c,\"LPUSH mylist bar\"));\n    reply = redisCommand(c,\"LRANGE mylist 0 -1\");\n    test_cond(reply->type == REDIS_REPLY_ARRAY &&\n              reply->elements == 2 &&\n              !memcmp(reply->element[0]->str,\"bar\",3) &&\n              !memcmp(reply->element[1]->str,\"foo\",3))\n    freeReplyObject(reply);\n\n    /* m/e with multi bulk reply *before* other reply.\n     * specifically test ordering of reply items to parse. */\n    test(\"Can handle nested multi bulk replies: \");\n    freeReplyObject(redisCommand(c,\"MULTI\"));\n    freeReplyObject(redisCommand(c,\"LRANGE mylist 0 -1\"));\n    freeReplyObject(redisCommand(c,\"PING\"));\n    reply = (redisCommand(c,\"EXEC\"));\n    test_cond(reply->type == REDIS_REPLY_ARRAY &&\n              reply->elements == 2 &&\n              reply->element[0]->type == REDIS_REPLY_ARRAY &&\n              reply->element[0]->elements == 2 &&\n              !memcmp(reply->element[0]->element[0]->str,\"bar\",3) &&\n              !memcmp(reply->element[0]->element[1]->str,\"foo\",3) &&\n              reply->element[1]->type == REDIS_REPLY_STATUS &&\n              strcasecmp(reply->element[1]->str,\"pong\") == 0);\n    freeReplyObject(reply);\n\n    disconnect(c, 0);\n}\n\nstatic void test_blocking_io_errors(struct config config) {\n    redisContext *c;\n    redisReply *reply;\n    void *_reply;\n    int major, minor;\n\n    /* Connect to target given by config. */\n    c = connect(config);\n    {\n        /* Find out Redis version to determine the path for the next test */\n        const char *field = \"redis_version:\";\n        char *p, *eptr;\n\n        reply = redisCommand(c,\"INFO\");\n        p = strstr(reply->str,field);\n        major = strtol(p+strlen(field),&eptr,10);\n        p = eptr+1; /* char next to the first \".\" */\n        minor = strtol(p,&eptr,10);\n        freeReplyObject(reply);\n    }\n\n    test(\"Returns I/O error when the connection is lost: \");\n    reply = redisCommand(c,\"QUIT\");\n    if (major >= 2 && minor > 0) {\n        /* > 2.0 returns OK on QUIT and read() should be issued once more\n         * to know the descriptor is at EOF. */\n        test_cond(strcasecmp(reply->str,\"OK\") == 0 &&\n            redisGetReply(c,&_reply) == REDIS_ERR);\n        freeReplyObject(reply);\n    } else {\n        test_cond(reply == NULL);\n    }\n\n    /* On 2.0, QUIT will cause the connection to be closed immediately and\n     * the read(2) for the reply on QUIT will set the error to EOF.\n     * On >2.0, QUIT will return with OK and another read(2) needed to be\n     * issued to find out the socket was closed by the server. In both\n     * conditions, the error will be set to EOF. */\n    assert(c->err == REDIS_ERR_EOF &&\n        strcmp(c->errstr,\"Server closed the connection\") == 0);\n    redisFree(c);\n\n    c = connect(config);\n    test(\"Returns I/O error on socket timeout: \");\n    struct timeval tv = { 0, 1000 };\n    assert(redisSetTimeout(c,tv) == REDIS_OK);\n    test_cond(redisGetReply(c,&_reply) == REDIS_ERR &&\n        c->err == REDIS_ERR_IO && errno == EAGAIN);\n    redisFree(c);\n}\n\nstatic void test_invalid_timeout_errors(struct config config) {\n    redisContext *c;\n\n    test(\"Set error when an invalid timeout usec value is given to redisConnectWithTimeout: \");\n\n    config.tcp.timeout.tv_sec = 0;\n    config.tcp.timeout.tv_usec = 10000001;\n\n    c = redisConnectWithTimeout(config.tcp.host, config.tcp.port, config.tcp.timeout);\n\n    test_cond(c->err == REDIS_ERR_IO);\n\n    test(\"Set error when an invalid timeout sec value is given to redisConnectWithTimeout: \");\n\n    config.tcp.timeout.tv_sec = (((LONG_MAX) - 999) / 1000) + 1;\n    config.tcp.timeout.tv_usec = 0;\n\n    c = redisConnectWithTimeout(config.tcp.host, config.tcp.port, config.tcp.timeout);\n\n    test_cond(c->err == REDIS_ERR_IO);\n\n    redisFree(c);\n}\n\nstatic void test_throughput(struct config config) {\n    redisContext *c = connect(config);\n    redisReply **replies;\n    int i, num;\n    long long t1, t2;\n\n    test(\"Throughput:\\n\");\n    for (i = 0; i < 500; i++)\n        freeReplyObject(redisCommand(c,\"LPUSH mylist foo\"));\n\n    num = 1000;\n    replies = malloc(sizeof(redisReply*)*num);\n    t1 = usec();\n    for (i = 0; i < num; i++) {\n        replies[i] = redisCommand(c,\"PING\");\n        assert(replies[i] != NULL && replies[i]->type == REDIS_REPLY_STATUS);\n    }\n    t2 = usec();\n    for (i = 0; i < num; i++) freeReplyObject(replies[i]);\n    free(replies);\n    printf(\"\\t(%dx PING: %.3fs)\\n\", num, (t2-t1)/1000000.0);\n\n    replies = malloc(sizeof(redisReply*)*num);\n    t1 = usec();\n    for (i = 0; i < num; i++) {\n        replies[i] = redisCommand(c,\"LRANGE mylist 0 499\");\n        assert(replies[i] != NULL && replies[i]->type == REDIS_REPLY_ARRAY);\n        assert(replies[i] != NULL && replies[i]->elements == 500);\n    }\n    t2 = usec();\n    for (i = 0; i < num; i++) freeReplyObject(replies[i]);\n    free(replies);\n    printf(\"\\t(%dx LRANGE with 500 elements: %.3fs)\\n\", num, (t2-t1)/1000000.0);\n\n    num = 10000;\n    replies = malloc(sizeof(redisReply*)*num);\n    for (i = 0; i < num; i++)\n        redisAppendCommand(c,\"PING\");\n    t1 = usec();\n    for (i = 0; i < num; i++) {\n        assert(redisGetReply(c, (void*)&replies[i]) == REDIS_OK);\n        assert(replies[i] != NULL && replies[i]->type == REDIS_REPLY_STATUS);\n    }\n    t2 = usec();\n    for (i = 0; i < num; i++) freeReplyObject(replies[i]);\n    free(replies);\n    printf(\"\\t(%dx PING (pipelined): %.3fs)\\n\", num, (t2-t1)/1000000.0);\n\n    replies = malloc(sizeof(redisReply*)*num);\n    for (i = 0; i < num; i++)\n        redisAppendCommand(c,\"LRANGE mylist 0 499\");\n    t1 = usec();\n    for (i = 0; i < num; i++) {\n        assert(redisGetReply(c, (void*)&replies[i]) == REDIS_OK);\n        assert(replies[i] != NULL && replies[i]->type == REDIS_REPLY_ARRAY);\n        assert(replies[i] != NULL && replies[i]->elements == 500);\n    }\n    t2 = usec();\n    for (i = 0; i < num; i++) freeReplyObject(replies[i]);\n    free(replies);\n    printf(\"\\t(%dx LRANGE with 500 elements (pipelined): %.3fs)\\n\", num, (t2-t1)/1000000.0);\n\n    disconnect(c, 0);\n}\n\n// static long __test_callback_flags = 0;\n// static void __test_callback(redisContext *c, void *privdata) {\n//     ((void)c);\n//     /* Shift to detect execution order */\n//     __test_callback_flags <<= 8;\n//     __test_callback_flags |= (long)privdata;\n// }\n//\n// static void __test_reply_callback(redisContext *c, redisReply *reply, void *privdata) {\n//     ((void)c);\n//     /* Shift to detect execution order */\n//     __test_callback_flags <<= 8;\n//     __test_callback_flags |= (long)privdata;\n//     if (reply) freeReplyObject(reply);\n// }\n//\n// static redisContext *__connect_nonblock() {\n//     /* Reset callback flags */\n//     __test_callback_flags = 0;\n//     return redisConnectNonBlock(\"127.0.0.1\", port, NULL);\n// }\n//\n// static void test_nonblocking_connection() {\n//     redisContext *c;\n//     int wdone = 0;\n//\n//     test(\"Calls command callback when command is issued: \");\n//     c = __connect_nonblock();\n//     redisSetCommandCallback(c,__test_callback,(void*)1);\n//     redisCommand(c,\"PING\");\n//     test_cond(__test_callback_flags == 1);\n//     redisFree(c);\n//\n//     test(\"Calls disconnect callback on redisDisconnect: \");\n//     c = __connect_nonblock();\n//     redisSetDisconnectCallback(c,__test_callback,(void*)2);\n//     redisDisconnect(c);\n//     test_cond(__test_callback_flags == 2);\n//     redisFree(c);\n//\n//     test(\"Calls disconnect callback and free callback on redisFree: \");\n//     c = __connect_nonblock();\n//     redisSetDisconnectCallback(c,__test_callback,(void*)2);\n//     redisSetFreeCallback(c,__test_callback,(void*)4);\n//     redisFree(c);\n//     test_cond(__test_callback_flags == ((2 << 8) | 4));\n//\n//     test(\"redisBufferWrite against empty write buffer: \");\n//     c = __connect_nonblock();\n//     test_cond(redisBufferWrite(c,&wdone) == REDIS_OK && wdone == 1);\n//     redisFree(c);\n//\n//     test(\"redisBufferWrite against not yet connected fd: \");\n//     c = __connect_nonblock();\n//     redisCommand(c,\"PING\");\n//     test_cond(redisBufferWrite(c,NULL) == REDIS_ERR &&\n//               strncmp(c->error,\"write:\",6) == 0);\n//     redisFree(c);\n//\n//     test(\"redisBufferWrite against closed fd: \");\n//     c = __connect_nonblock();\n//     redisCommand(c,\"PING\");\n//     redisDisconnect(c);\n//     test_cond(redisBufferWrite(c,NULL) == REDIS_ERR &&\n//               strncmp(c->error,\"write:\",6) == 0);\n//     redisFree(c);\n//\n//     test(\"Process callbacks in the right sequence: \");\n//     c = __connect_nonblock();\n//     redisCommandWithCallback(c,__test_reply_callback,(void*)1,\"PING\");\n//     redisCommandWithCallback(c,__test_reply_callback,(void*)2,\"PING\");\n//     redisCommandWithCallback(c,__test_reply_callback,(void*)3,\"PING\");\n//\n//     /* Write output buffer */\n//     wdone = 0;\n//     while(!wdone) {\n//         usleep(500);\n//         redisBufferWrite(c,&wdone);\n//     }\n//\n//     /* Read until at least one callback is executed (the 3 replies will\n//      * arrive in a single packet, causing all callbacks to be executed in\n//      * a single pass). */\n//     while(__test_callback_flags == 0) {\n//         assert(redisBufferRead(c) == REDIS_OK);\n//         redisProcessCallbacks(c);\n//     }\n//     test_cond(__test_callback_flags == 0x010203);\n//     redisFree(c);\n//\n//     test(\"redisDisconnect executes pending callbacks with NULL reply: \");\n//     c = __connect_nonblock();\n//     redisSetDisconnectCallback(c,__test_callback,(void*)1);\n//     redisCommandWithCallback(c,__test_reply_callback,(void*)2,\"PING\");\n//     redisDisconnect(c);\n//     test_cond(__test_callback_flags == 0x0201);\n//     redisFree(c);\n// }\n\nint main(int argc, char **argv) {\n    struct config cfg = {\n        .tcp = {\n            .host = \"127.0.0.1\",\n            .port = 6379\n        },\n        .unix = {\n            .path = \"/tmp/redis.sock\"\n        }\n    };\n    int throughput = 1;\n    int test_inherit_fd = 1;\n\n    /* Ignore broken pipe signal (for I/O error tests). */\n    signal(SIGPIPE, SIG_IGN);\n\n    /* Parse command line options. */\n    argv++; argc--;\n    while (argc) {\n        if (argc >= 2 && !strcmp(argv[0],\"-h\")) {\n            argv++; argc--;\n            cfg.tcp.host = argv[0];\n        } else if (argc >= 2 && !strcmp(argv[0],\"-p\")) {\n            argv++; argc--;\n            cfg.tcp.port = atoi(argv[0]);\n        } else if (argc >= 2 && !strcmp(argv[0],\"-s\")) {\n            argv++; argc--;\n            cfg.unix.path = argv[0];\n        } else if (argc >= 1 && !strcmp(argv[0],\"--skip-throughput\")) {\n            throughput = 0;\n        } else if (argc >= 1 && !strcmp(argv[0],\"--skip-inherit-fd\")) {\n            test_inherit_fd = 0;\n        } else {\n            fprintf(stderr, \"Invalid argument: %s\\n\", argv[0]);\n            exit(1);\n        }\n        argv++; argc--;\n    }\n\n    test_format_commands();\n    test_reply_reader();\n    test_blocking_connection_errors();\n\n    printf(\"\\nTesting against TCP connection (%s:%d):\\n\", cfg.tcp.host, cfg.tcp.port);\n    cfg.type = CONN_TCP;\n    test_blocking_connection(cfg);\n    test_blocking_io_errors(cfg);\n    test_invalid_timeout_errors(cfg);\n    test_append_formatted_commands(cfg);\n    if (throughput) test_throughput(cfg);\n\n    printf(\"\\nTesting against Unix socket connection (%s):\\n\", cfg.unix.path);\n    cfg.type = CONN_UNIX;\n    test_blocking_connection(cfg);\n    test_blocking_io_errors(cfg);\n    if (throughput) test_throughput(cfg);\n\n    if (test_inherit_fd) {\n        printf(\"\\nTesting against inherited fd (%s):\\n\", cfg.unix.path);\n        cfg.type = CONN_FD;\n        test_blocking_connection(cfg);\n    }\n\n    if (fails) {\n        printf(\"*** %d TESTS FAILED ***\\n\", fails);\n        return 1;\n    }\n\n    printf(\"ALL TESTS PASSED\\n\");\n    return 0;\n}\n"
  },
  {
    "path": "extern/deprecated/redis-2.8.21/deps/hiredis/zmalloc.h",
    "content": "/* Drop in replacement for zmalloc.h in order to just use libc malloc without\n * any wrappering. */\n\n#ifndef ZMALLOC_H\n#define ZMALLOC_H\n\n#define zmalloc malloc\n#define zrealloc realloc\n#define zcalloc(x) calloc(x,1)\n#define zfree free\n#define zstrdup strdup\n\n#endif\n"
  },
  {
    "path": "extern/deprecated/redis-2.8.21/deps/jemalloc/.gitignore",
    "content": "/*.gcov.*\n\n/autom4te.cache/\n\n/bin/jemalloc.sh\n\n/config.stamp\n/config.log\n/config.status\n/configure\n\n/doc/html.xsl\n/doc/manpages.xsl\n/doc/jemalloc.xml\n/doc/jemalloc.html\n/doc/jemalloc.3\n\n/lib/\n\n/Makefile\n\n/include/jemalloc/internal/jemalloc_internal.h\n/include/jemalloc/internal/jemalloc_internal_defs.h\n/include/jemalloc/internal/private_namespace.h\n/include/jemalloc/internal/private_unnamespace.h\n/include/jemalloc/internal/public_namespace.h\n/include/jemalloc/internal/public_symbols.txt\n/include/jemalloc/internal/public_unnamespace.h\n/include/jemalloc/internal/size_classes.h\n/include/jemalloc/jemalloc.h\n/include/jemalloc/jemalloc_defs.h\n/include/jemalloc/jemalloc_macros.h\n/include/jemalloc/jemalloc_mangle.h\n/include/jemalloc/jemalloc_mangle_jet.h\n/include/jemalloc/jemalloc_protos.h\n/include/jemalloc/jemalloc_protos_jet.h\n/include/jemalloc/jemalloc_rename.h\n\n/src/*.[od]\n/src/*.gcda\n/src/*.gcno\n\n/test/test.sh\ntest/include/test/jemalloc_test.h\ntest/include/test/jemalloc_test_defs.h\n\n/test/integration/[A-Za-z]*\n!/test/integration/[A-Za-z]*.*\n/test/integration/*.[od]\n/test/integration/*.gcda\n/test/integration/*.gcno\n/test/integration/*.out\n\n/test/src/*.[od]\n/test/src/*.gcda\n/test/src/*.gcno\n\n/test/stress/[A-Za-z]*\n!/test/stress/[A-Za-z]*.*\n/test/stress/*.[od]\n/test/stress/*.gcda\n/test/stress/*.gcno\n/test/stress/*.out\n\n/test/unit/[A-Za-z]*\n!/test/unit/[A-Za-z]*.*\n/test/unit/*.[od]\n/test/unit/*.gcda\n/test/unit/*.gcno\n/test/unit/*.out\n\n/VERSION\n"
  },
  {
    "path": "extern/deprecated/redis-2.8.21/deps/jemalloc/COPYING",
    "content": "Unless otherwise specified, files in the jemalloc source distribution are\nsubject to the following license:\n--------------------------------------------------------------------------------\nCopyright (C) 2002-2014 Jason Evans <jasone@canonware.com>.\nAll rights reserved.\nCopyright (C) 2007-2012 Mozilla Foundation.  All rights reserved.\nCopyright (C) 2009-2014 Facebook, Inc.  All rights reserved.\n\nRedistribution and use in source and binary forms, with or without\nmodification, are permitted provided that the following conditions are met:\n1. Redistributions of source code must retain the above copyright notice(s),\n   this list of conditions and the following disclaimer.\n2. Redistributions in binary form must reproduce the above copyright notice(s),\n   this list of conditions and the following disclaimer in the documentation\n   and/or other materials provided with the distribution.\n\nTHIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER(S) ``AS IS'' AND ANY EXPRESS\nOR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF\nMERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO\nEVENT SHALL THE COPYRIGHT HOLDER(S) BE LIABLE FOR ANY DIRECT, INDIRECT,\nINCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\nLIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR\nPROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF\nLIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE\nOR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF\nADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n--------------------------------------------------------------------------------\n"
  },
  {
    "path": "extern/deprecated/redis-2.8.21/deps/jemalloc/ChangeLog",
    "content": "Following are change highlights associated with official releases.  Important\nbug fixes are all mentioned, but internal enhancements are omitted here for\nbrevity (even though they are more fun to write about).  Much more detail can be\nfound in the git revision history:\n\n    https://github.com/jemalloc/jemalloc\n\n* 3.6.0 (March 31, 2014)\n\n  This version contains a critical bug fix for a regression present in 3.5.0 and\n  3.5.1.\n\n  Bug fixes:\n  - Fix a regression in arena_chunk_alloc() that caused crashes during\n    small/large allocation if chunk allocation failed.  In the absence of this\n    bug, chunk allocation failure would result in allocation failure, e.g.  NULL\n    return from malloc().  This regression was introduced in 3.5.0.\n  - Fix backtracing for gcc intrinsics-based backtracing by specifying\n    -fno-omit-frame-pointer to gcc.  Note that the application (and all the\n    libraries it links to) must also be compiled with this option for\n    backtracing to be reliable.\n  - Use dss allocation precedence for huge allocations as well as small/large\n    allocations.\n  - Fix test assertion failure message formatting.  This bug did not manifect on\n    x86_64 systems because of implementation subtleties in va_list.\n  - Fix inconsequential test failures for hash and SFMT code.\n\n  New features:\n  - Support heap profiling on FreeBSD.  This feature depends on the proc\n    filesystem being mounted during heap profile dumping.\n\n* 3.5.1 (February 25, 2014)\n\n  This version primarily addresses minor bugs in test code.\n\n  Bug fixes:\n  - Configure Solaris/Illumos to use MADV_FREE.\n  - Fix junk filling for mremap(2)-based huge reallocation.  This is only\n    relevant if configuring with the --enable-mremap option specified.\n  - Avoid compilation failure if 'restrict' C99 keyword is not supported by the\n    compiler.\n  - Add a configure test for SSE2 rather than assuming it is usable on i686\n    systems.  This fixes test compilation errors, especially on 32-bit Linux\n    systems.\n  - Fix mallctl argument size mismatches (size_t vs. uint64_t) in the stats unit\n    test.\n  - Fix/remove flawed alignment-related overflow tests.\n  - Prevent compiler optimizations that could change backtraces in the\n    prof_accum unit test.\n\n* 3.5.0 (January 22, 2014)\n\n  This version focuses on refactoring and automated testing, though it also\n  includes some non-trivial heap profiling optimizations not mentioned below.\n\n  New features:\n  - Add the *allocx() API, which is a successor to the experimental *allocm()\n    API.  The *allocx() functions are slightly simpler to use because they have\n    fewer parameters, they directly return the results of primary interest, and\n    mallocx()/rallocx() avoid the strict aliasing pitfall that\n    allocm()/rallocm() share with posix_memalign().  Note that *allocm() is\n    slated for removal in the next non-bugfix release.\n  - Add support for LinuxThreads.\n\n  Bug fixes:\n  - Unless heap profiling is enabled, disable floating point code and don't link\n    with libm.  This, in combination with e.g. EXTRA_CFLAGS=-mno-sse on x64\n    systems, makes it possible to completely disable floating point register\n    use.  Some versions of glibc neglect to save/restore caller-saved floating\n    point registers during dynamic lazy symbol loading, and the symbol loading\n    code uses whatever malloc the application happens to have linked/loaded\n    with, the result being potential floating point register corruption.\n  - Report ENOMEM rather than EINVAL if an OOM occurs during heap profiling\n    backtrace creation in imemalign().  This bug impacted posix_memalign() and\n    aligned_alloc().\n  - Fix a file descriptor leak in a prof_dump_maps() error path.\n  - Fix prof_dump() to close the dump file descriptor for all relevant error\n    paths.\n  - Fix rallocm() to use the arena specified by the ALLOCM_ARENA(s) flag for\n    allocation, not just deallocation.\n  - Fix a data race for large allocation stats counters.\n  - Fix a potential infinite loop during thread exit.  This bug occurred on\n    Solaris, and could affect other platforms with similar pthreads TSD\n    implementations.\n  - Don't junk-fill reallocations unless usable size changes.  This fixes a\n    violation of the *allocx()/*allocm() semantics.\n  - Fix growing large reallocation to junk fill new space.\n  - Fix huge deallocation to junk fill when munmap is disabled.\n  - Change the default private namespace prefix from empty to je_, and change\n    --with-private-namespace-prefix so that it prepends an additional prefix\n    rather than replacing je_.  This reduces the likelihood of applications\n    which statically link jemalloc experiencing symbol name collisions.\n  - Add missing private namespace mangling (relevant when\n    --with-private-namespace is specified).\n  - Add and use JEMALLOC_INLINE_C so that static inline functions are marked as\n    static even for debug builds.\n  - Add a missing mutex unlock in a malloc_init_hard() error path.  In practice\n    this error path is never executed.\n  - Fix numerous bugs in malloc_strotumax() error handling/reporting.  These\n    bugs had no impact except for malformed inputs.\n  - Fix numerous bugs in malloc_snprintf().  These bugs were not exercised by\n    existing calls, so they had no impact.\n\n* 3.4.1 (October 20, 2013)\n\n  Bug fixes:\n  - Fix a race in the \"arenas.extend\" mallctl that could cause memory corruption\n    of internal data structures and subsequent crashes.\n  - Fix Valgrind integration flaws that caused Valgrind warnings about reads of\n    uninitialized memory in:\n    + arena chunk headers\n    + internal zero-initialized data structures (relevant to tcache and prof\n      code)\n  - Preserve errno during the first allocation.  A readlink(2) call during\n    initialization fails unless /etc/malloc.conf exists, so errno was typically\n    set during the first allocation prior to this fix.\n  - Fix compilation warnings reported by gcc 4.8.1.\n\n* 3.4.0 (June 2, 2013)\n\n  This version is essentially a small bugfix release, but the addition of\n  aarch64 support requires that the minor version be incremented.\n\n  Bug fixes:\n  - Fix race-triggered deadlocks in chunk_record().  These deadlocks were\n    typically triggered by multiple threads concurrently deallocating huge\n    objects.\n\n  New features:\n  - Add support for the aarch64 architecture.\n\n* 3.3.1 (March 6, 2013)\n\n  This version fixes bugs that are typically encountered only when utilizing\n  custom run-time options.\n\n  Bug fixes:\n  - Fix a locking order bug that could cause deadlock during fork if heap\n    profiling were enabled.\n  - Fix a chunk recycling bug that could cause the allocator to lose track of\n    whether a chunk was zeroed.  On FreeBSD, NetBSD, and OS X, it could cause\n    corruption if allocating via sbrk(2) (unlikely unless running with the\n    \"dss:primary\" option specified).  This was completely harmless on Linux\n    unless using mlockall(2) (and unlikely even then, unless the\n    --disable-munmap configure option or the \"dss:primary\" option was\n    specified).  This regression was introduced in 3.1.0 by the\n    mlockall(2)/madvise(2) interaction fix.\n  - Fix TLS-related memory corruption that could occur during thread exit if the\n    thread never allocated memory.  Only the quarantine and prof facilities were\n    susceptible.\n  - Fix two quarantine bugs:\n    + Internal reallocation of the quarantined object array leaked the old\n      array.\n    + Reallocation failure for internal reallocation of the quarantined object\n      array (very unlikely) resulted in memory corruption.\n  - Fix Valgrind integration to annotate all internally allocated memory in a\n    way that keeps Valgrind happy about internal data structure access.\n  - Fix building for s390 systems.\n\n* 3.3.0 (January 23, 2013)\n\n  This version includes a few minor performance improvements in addition to the\n  listed new features and bug fixes.\n\n  New features:\n  - Add clipping support to lg_chunk option processing.\n  - Add the --enable-ivsalloc option.\n  - Add the --without-export option.\n  - Add the --disable-zone-allocator option.\n\n  Bug fixes:\n  - Fix \"arenas.extend\" mallctl to output the number of arenas.\n  - Fix chunk_recycle() to unconditionally inform Valgrind that returned memory\n    is undefined.\n  - Fix build break on FreeBSD related to alloca.h.\n\n* 3.2.0 (November 9, 2012)\n\n  In addition to a couple of bug fixes, this version modifies page run\n  allocation and dirty page purging algorithms in order to better control\n  page-level virtual memory fragmentation.\n\n  Incompatible changes:\n  - Change the \"opt.lg_dirty_mult\" default from 5 to 3 (32:1 to 8:1).\n\n  Bug fixes:\n  - Fix dss/mmap allocation precedence code to use recyclable mmap memory only\n    after primary dss allocation fails.\n  - Fix deadlock in the \"arenas.purge\" mallctl.  This regression was introduced\n    in 3.1.0 by the addition of the \"arena.<i>.purge\" mallctl.\n\n* 3.1.0 (October 16, 2012)\n\n  New features:\n  - Auto-detect whether running inside Valgrind, thus removing the need to\n    manually specify MALLOC_CONF=valgrind:true.\n  - Add the \"arenas.extend\" mallctl, which allows applications to create\n    manually managed arenas.\n  - Add the ALLOCM_ARENA() flag for {,r,d}allocm().\n  - Add the \"opt.dss\", \"arena.<i>.dss\", and \"stats.arenas.<i>.dss\" mallctls,\n    which provide control over dss/mmap precedence.\n  - Add the \"arena.<i>.purge\" mallctl, which obsoletes \"arenas.purge\".\n  - Define LG_QUANTUM for hppa.\n\n  Incompatible changes:\n  - Disable tcache by default if running inside Valgrind, in order to avoid\n    making unallocated objects appear reachable to Valgrind.\n  - Drop const from malloc_usable_size() argument on Linux.\n\n  Bug fixes:\n  - Fix heap profiling crash if sampled object is freed via realloc(p, 0).\n  - Remove const from __*_hook variable declarations, so that glibc can modify\n    them during process forking.\n  - Fix mlockall(2)/madvise(2) interaction.\n  - Fix fork(2)-related deadlocks.\n  - Fix error return value for \"thread.tcache.enabled\" mallctl.\n\n* 3.0.0 (May 11, 2012)\n\n  Although this version adds some major new features, the primary focus is on\n  internal code cleanup that facilitates maintainability and portability, most\n  of which is not reflected in the ChangeLog.  This is the first release to\n  incorporate substantial contributions from numerous other developers, and the\n  result is a more broadly useful allocator (see the git revision history for\n  contribution details).  Note that the license has been unified, thanks to\n  Facebook granting a license under the same terms as the other copyright\n  holders (see COPYING).\n\n  New features:\n  - Implement Valgrind support, redzones, and quarantine.\n  - Add support for additional platforms:\n    + FreeBSD\n    + Mac OS X Lion\n    + MinGW\n    + Windows (no support yet for replacing the system malloc)\n  - Add support for additional architectures:\n    + MIPS\n    + SH4\n    + Tilera\n  - Add support for cross compiling.\n  - Add nallocm(), which rounds a request size up to the nearest size class\n    without actually allocating.\n  - Implement aligned_alloc() (blame C11).\n  - Add the \"thread.tcache.enabled\" mallctl.\n  - Add the \"opt.prof_final\" mallctl.\n  - Update pprof (from gperftools 2.0).\n  - Add the --with-mangling option.\n  - Add the --disable-experimental option.\n  - Add the --disable-munmap option, and make it the default on Linux.\n  - Add the --enable-mremap option, which disables use of mremap(2) by default.\n\n  Incompatible changes:\n  - Enable stats by default.\n  - Enable fill by default.\n  - Disable lazy locking by default.\n  - Rename the \"tcache.flush\" mallctl to \"thread.tcache.flush\".\n  - Rename the \"arenas.pagesize\" mallctl to \"arenas.page\".\n  - Change the \"opt.lg_prof_sample\" default from 0 to 19 (1 B to 512 KiB).\n  - Change the \"opt.prof_accum\" default from true to false.\n\n  Removed features:\n  - Remove the swap feature, including the \"config.swap\", \"swap.avail\",\n    \"swap.prezeroed\", \"swap.nfds\", and \"swap.fds\" mallctls.\n  - Remove highruns statistics, including the\n    \"stats.arenas.<i>.bins.<j>.highruns\" and\n    \"stats.arenas.<i>.lruns.<j>.highruns\" mallctls.\n  - As part of small size class refactoring, remove the \"opt.lg_[qc]space_max\",\n    \"arenas.cacheline\", \"arenas.subpage\", \"arenas.[tqcs]space_{min,max}\", and\n    \"arenas.[tqcs]bins\" mallctls.\n  - Remove the \"arenas.chunksize\" mallctl.\n  - Remove the \"opt.lg_prof_tcmax\" option.\n  - Remove the \"opt.lg_prof_bt_max\" option.\n  - Remove the \"opt.lg_tcache_gc_sweep\" option.\n  - Remove the --disable-tiny option, including the \"config.tiny\" mallctl.\n  - Remove the --enable-dynamic-page-shift configure option.\n  - Remove the --enable-sysv configure option.\n\n  Bug fixes:\n  - Fix a statistics-related bug in the \"thread.arena\" mallctl that could cause\n    invalid statistics and crashes.\n  - Work around TLS deallocation via free() on Linux.  This bug could cause\n    write-after-free memory corruption.\n  - Fix a potential deadlock that could occur during interval- and\n    growth-triggered heap profile dumps.\n  - Fix large calloc() zeroing bugs due to dropping chunk map unzeroed flags.\n  - Fix chunk_alloc_dss() to stop claiming memory is zeroed.  This bug could\n    cause memory corruption and crashes with --enable-dss specified.\n  - Fix fork-related bugs that could cause deadlock in children between fork\n    and exec.\n  - Fix malloc_stats_print() to honor 'b' and 'l' in the opts parameter.\n  - Fix realloc(p, 0) to act like free(p).\n  - Do not enforce minimum alignment in memalign().\n  - Check for NULL pointer in malloc_usable_size().\n  - Fix an off-by-one heap profile statistics bug that could be observed in\n    interval- and growth-triggered heap profiles.\n  - Fix the \"epoch\" mallctl to update cached stats even if the passed in epoch\n    is 0.\n  - Fix bin->runcur management to fix a layout policy bug.  This bug did not\n    affect correctness.\n  - Fix a bug in choose_arena_hard() that potentially caused more arenas to be\n    initialized than necessary.\n  - Add missing \"opt.lg_tcache_max\" mallctl implementation.\n  - Use glibc allocator hooks to make mixed allocator usage less likely.\n  - Fix build issues for --disable-tcache.\n  - Don't mangle pthread_create() when --with-private-namespace is specified.\n\n* 2.2.5 (November 14, 2011)\n\n  Bug fixes:\n  - Fix huge_ralloc() race when using mremap(2).  This is a serious bug that\n    could cause memory corruption and/or crashes.\n  - Fix huge_ralloc() to maintain chunk statistics.\n  - Fix malloc_stats_print(..., \"a\") output.\n\n* 2.2.4 (November 5, 2011)\n\n  Bug fixes:\n  - Initialize arenas_tsd before using it.  This bug existed for 2.2.[0-3], as\n    well as for --disable-tls builds in earlier releases.\n  - Do not assume a 4 KiB page size in test/rallocm.c.\n\n* 2.2.3 (August 31, 2011)\n\n  This version fixes numerous bugs related to heap profiling.\n\n  Bug fixes:\n  - Fix a prof-related race condition.  This bug could cause memory corruption,\n    but only occurred in non-default configurations (prof_accum:false).\n  - Fix off-by-one backtracing issues (make sure that prof_alloc_prep() is\n    excluded from backtraces).\n  - Fix a prof-related bug in realloc() (only triggered by OOM errors).\n  - Fix prof-related bugs in allocm() and rallocm().\n  - Fix prof_tdata_cleanup() for --disable-tls builds.\n  - Fix a relative include path, to fix objdir builds.\n\n* 2.2.2 (July 30, 2011)\n\n  Bug fixes:\n  - Fix a build error for --disable-tcache.\n  - Fix assertions in arena_purge() (for real this time).\n  - Add the --with-private-namespace option.  This is a workaround for symbol\n    conflicts that can inadvertently arise when using static libraries.\n\n* 2.2.1 (March 30, 2011)\n\n  Bug fixes:\n  - Implement atomic operations for x86/x64.  This fixes compilation failures\n    for versions of gcc that are still in wide use.\n  - Fix an assertion in arena_purge().\n\n* 2.2.0 (March 22, 2011)\n\n  This version incorporates several improvements to algorithms and data\n  structures that tend to reduce fragmentation and increase speed.\n\n  New features:\n  - Add the \"stats.cactive\" mallctl.\n  - Update pprof (from google-perftools 1.7).\n  - Improve backtracing-related configuration logic, and add the\n    --disable-prof-libgcc option.\n\n  Bug fixes:\n  - Change default symbol visibility from \"internal\", to \"hidden\", which\n    decreases the overhead of library-internal function calls.\n  - Fix symbol visibility so that it is also set on OS X.\n  - Fix a build dependency regression caused by the introduction of the .pic.o\n    suffix for PIC object files.\n  - Add missing checks for mutex initialization failures.\n  - Don't use libgcc-based backtracing except on x64, where it is known to work.\n  - Fix deadlocks on OS X that were due to memory allocation in\n    pthread_mutex_lock().\n  - Heap profiling-specific fixes:\n    + Fix memory corruption due to integer overflow in small region index\n      computation, when using a small enough sample interval that profiling\n      context pointers are stored in small run headers.\n    + Fix a bootstrap ordering bug that only occurred with TLS disabled.\n    + Fix a rallocm() rsize bug.\n    + Fix error detection bugs for aligned memory allocation.\n\n* 2.1.3 (March 14, 2011)\n\n  Bug fixes:\n  - Fix a cpp logic regression (due to the \"thread.{de,}allocatedp\" mallctl fix\n    for OS X in 2.1.2).\n  - Fix a \"thread.arena\" mallctl bug.\n  - Fix a thread cache stats merging bug.\n\n* 2.1.2 (March 2, 2011)\n\n  Bug fixes:\n  - Fix \"thread.{de,}allocatedp\" mallctl for OS X.\n  - Add missing jemalloc.a to build system.\n\n* 2.1.1 (January 31, 2011)\n\n  Bug fixes:\n  - Fix aligned huge reallocation (affected allocm()).\n  - Fix the ALLOCM_LG_ALIGN macro definition.\n  - Fix a heap dumping deadlock.\n  - Fix a \"thread.arena\" mallctl bug.\n\n* 2.1.0 (December 3, 2010)\n\n  This version incorporates some optimizations that can't quite be considered\n  bug fixes.\n\n  New features:\n  - Use Linux's mremap(2) for huge object reallocation when possible.\n  - Avoid locking in mallctl*() when possible.\n  - Add the \"thread.[de]allocatedp\" mallctl's.\n  - Convert the manual page source from roff to DocBook, and generate both roff\n    and HTML manuals.\n\n  Bug fixes:\n  - Fix a crash due to incorrect bootstrap ordering.  This only impacted\n    --enable-debug --enable-dss configurations.\n  - Fix a minor statistics bug for mallctl(\"swap.avail\", ...).\n\n* 2.0.1 (October 29, 2010)\n\n  Bug fixes:\n  - Fix a race condition in heap profiling that could cause undefined behavior\n    if \"opt.prof_accum\" were disabled.\n  - Add missing mutex unlocks for some OOM error paths in the heap profiling\n    code.\n  - Fix a compilation error for non-C99 builds.\n\n* 2.0.0 (October 24, 2010)\n\n  This version focuses on the experimental *allocm() API, and on improved\n  run-time configuration/introspection.  Nonetheless, numerous performance\n  improvements are also included.\n\n  New features:\n  - Implement the experimental {,r,s,d}allocm() API, which provides a superset\n    of the functionality available via malloc(), calloc(), posix_memalign(),\n    realloc(), malloc_usable_size(), and free().  These functions can be used to\n    allocate/reallocate aligned zeroed memory, ask for optional extra memory\n    during reallocation, prevent object movement during reallocation, etc.\n  - Replace JEMALLOC_OPTIONS/JEMALLOC_PROF_PREFIX with MALLOC_CONF, which is\n    more human-readable, and more flexible.  For example:\n      JEMALLOC_OPTIONS=AJP\n    is now:\n      MALLOC_CONF=abort:true,fill:true,stats_print:true\n  - Port to Apple OS X.  Sponsored by Mozilla.\n  - Make it possible for the application to control thread-->arena mappings via\n    the \"thread.arena\" mallctl.\n  - Add compile-time support for all TLS-related functionality via pthreads TSD.\n    This is mainly of interest for OS X, which does not support TLS, but has a\n    TSD implementation with similar performance.\n  - Override memalign() and valloc() if they are provided by the system.\n  - Add the \"arenas.purge\" mallctl, which can be used to synchronously purge all\n    dirty unused pages.\n  - Make cumulative heap profiling data optional, so that it is possible to\n    limit the amount of memory consumed by heap profiling data structures.\n  - Add per thread allocation counters that can be accessed via the\n    \"thread.allocated\" and \"thread.deallocated\" mallctls.\n\n  Incompatible changes:\n  - Remove JEMALLOC_OPTIONS and malloc_options (see MALLOC_CONF above).\n  - Increase default backtrace depth from 4 to 128 for heap profiling.\n  - Disable interval-based profile dumps by default.\n\n  Bug fixes:\n  - Remove bad assertions in fork handler functions.  These assertions could\n    cause aborts for some combinations of configure settings.\n  - Fix strerror_r() usage to deal with non-standard semantics in GNU libc.\n  - Fix leak context reporting.  This bug tended to cause the number of contexts\n    to be underreported (though the reported number of objects and bytes were\n    correct).\n  - Fix a realloc() bug for large in-place growing reallocation.  This bug could\n    cause memory corruption, but it was hard to trigger.\n  - Fix an allocation bug for small allocations that could be triggered if\n    multiple threads raced to create a new run of backing pages.\n  - Enhance the heap profiler to trigger samples based on usable size, rather\n    than request size.\n  - Fix a heap profiling bug due to sometimes losing track of requested object\n    size for sampled objects.\n\n* 1.0.3 (August 12, 2010)\n\n  Bug fixes:\n  - Fix the libunwind-based implementation of stack backtracing (used for heap\n    profiling).  This bug could cause zero-length backtraces to be reported.\n  - Add a missing mutex unlock in library initialization code.  If multiple\n    threads raced to initialize malloc, some of them could end up permanently\n    blocked.\n\n* 1.0.2 (May 11, 2010)\n\n  Bug fixes:\n  - Fix junk filling of large objects, which could cause memory corruption.\n  - Add MAP_NORESERVE support for chunk mapping, because otherwise virtual\n    memory limits could cause swap file configuration to fail.  Contributed by\n    Jordan DeLong.\n\n* 1.0.1 (April 14, 2010)\n\n  Bug fixes:\n  - Fix compilation when --enable-fill is specified.\n  - Fix threads-related profiling bugs that affected accuracy and caused memory\n    to be leaked during thread exit.\n  - Fix dirty page purging race conditions that could cause crashes.\n  - Fix crash in tcache flushing code during thread destruction.\n\n* 1.0.0 (April 11, 2010)\n\n  This release focuses on speed and run-time introspection.  Numerous\n  algorithmic improvements make this release substantially faster than its\n  predecessors.\n\n  New features:\n  - Implement autoconf-based configuration system.\n  - Add mallctl*(), for the purposes of introspection and run-time\n    configuration.\n  - Make it possible for the application to manually flush a thread's cache, via\n    the \"tcache.flush\" mallctl.\n  - Base maximum dirty page count on proportion of active memory.\n  - Compute various addtional run-time statistics, including per size class\n    statistics for large objects.\n  - Expose malloc_stats_print(), which can be called repeatedly by the\n    application.\n  - Simplify the malloc_message() signature to only take one string argument,\n    and incorporate an opaque data pointer argument for use by the application\n    in combination with malloc_stats_print().\n  - Add support for allocation backed by one or more swap files, and allow the\n    application to disable over-commit if swap files are in use.\n  - Implement allocation profiling and leak checking.\n\n  Removed features:\n  - Remove the dynamic arena rebalancing code, since thread-specific caching\n    reduces its utility.\n\n  Bug fixes:\n  - Modify chunk allocation to work when address space layout randomization\n    (ASLR) is in use.\n  - Fix thread cleanup bugs related to TLS destruction.\n  - Handle 0-size allocation requests in posix_memalign().\n  - Fix a chunk leak.  The leaked chunks were never touched, so this impacted\n    virtual memory usage, but not physical memory usage.\n\n* linux_2008082[78]a (August 27/28, 2008)\n\n  These snapshot releases are the simple result of incorporating Linux-specific\n  support into the FreeBSD malloc sources.\n\n--------------------------------------------------------------------------------\nvim:filetype=text:textwidth=80\n"
  },
  {
    "path": "extern/deprecated/redis-2.8.21/deps/jemalloc/INSTALL",
    "content": "Building and installing jemalloc can be as simple as typing the following while\nin the root directory of the source tree:\n\n    ./configure\n    make\n    make install\n\n=== Advanced configuration =====================================================\n\nThe 'configure' script supports numerous options that allow control of which\nfunctionality is enabled, where jemalloc is installed, etc.  Optionally, pass\nany of the following arguments (not a definitive list) to 'configure':\n\n--help\n    Print a definitive list of options.\n\n--prefix=<install-root-dir>\n    Set the base directory in which to install.  For example:\n\n        ./configure --prefix=/usr/local\n\n    will cause files to be installed into /usr/local/include, /usr/local/lib,\n    and /usr/local/man.\n\n--with-rpath=<colon-separated-rpath>\n    Embed one or more library paths, so that libjemalloc can find the libraries\n    it is linked to.  This works only on ELF-based systems.\n\n--with-mangling=<map>\n    Mangle public symbols specified in <map> which is a comma-separated list of\n    name:mangled pairs.\n\n    For example, to use ld's --wrap option as an alternative method for\n    overriding libc's malloc implementation, specify something like:\n\n      --with-mangling=malloc:__wrap_malloc,free:__wrap_free[...]\n\n    Note that mangling happens prior to application of the prefix specified by\n    --with-jemalloc-prefix, and mangled symbols are then ignored when applying\n    the prefix.\n\n--with-jemalloc-prefix=<prefix>\n    Prefix all public APIs with <prefix>.  For example, if <prefix> is\n    \"prefix_\", API changes like the following occur:\n\n      malloc()         --> prefix_malloc()\n      malloc_conf      --> prefix_malloc_conf\n      /etc/malloc.conf --> /etc/prefix_malloc.conf\n      MALLOC_CONF      --> PREFIX_MALLOC_CONF\n\n    This makes it possible to use jemalloc at the same time as the system\n    allocator, or even to use multiple copies of jemalloc simultaneously.\n\n    By default, the prefix is \"\", except on OS X, where it is \"je_\".  On OS X,\n    jemalloc overlays the default malloc zone, but makes no attempt to actually\n    replace the \"malloc\", \"calloc\", etc. symbols.\n\n--without-export\n    Don't export public APIs. This can be useful when building jemalloc as a\n    static library, or to avoid exporting public APIs when using the zone\n    allocator on OSX.\n\n--with-private-namespace=<prefix>\n    Prefix all library-private APIs with <prefix>je_.  For shared libraries,\n    symbol visibility mechanisms prevent these symbols from being exported, but\n    for static libraries, naming collisions are a real possibility.  By\n    default, <prefix> is empty, which results in a symbol prefix of je_ .\n\n--with-install-suffix=<suffix>\n    Append <suffix> to the base name of all installed files, such that multiple\n    versions of jemalloc can coexist in the same installation directory.  For\n    example, libjemalloc.so.0 becomes libjemalloc<suffix>.so.0.\n\n--enable-cc-silence\n    Enable code that silences non-useful compiler warnings.  This is helpful\n    when trying to tell serious warnings from those due to compiler\n    limitations, but it potentially incurs a performance penalty.\n\n--enable-debug\n    Enable assertions and validation code.  This incurs a substantial\n    performance hit, but is very useful during application development.\n    Implies --enable-ivsalloc.\n\n--enable-code-coverage\n    Enable code coverage support, for use during jemalloc test development.\n    Additional testing targets are available if this option is enabled:\n\n      coverage\n      coverage_unit\n      coverage_integration\n      coverage_stress\n\n    These targets do not clear code coverage results from previous runs, and\n    there are interactions between the various coverage targets, so it is\n    usually advisable to run 'make clean' between repeated code coverage runs.\n\n--enable-ivsalloc\n    Enable validation code, which verifies that pointers reside within\n    jemalloc-owned chunks before dereferencing them. This incurs a substantial\n    performance hit.\n\n--disable-stats\n    Disable statistics gathering functionality.  See the \"opt.stats_print\"\n    option documentation for usage details.\n\n--enable-prof\n    Enable heap profiling and leak detection functionality.  See the \"opt.prof\"\n    option documentation for usage details.  When enabled, there are several\n    approaches to backtracing, and the configure script chooses the first one\n    in the following list that appears to function correctly:\n\n    + libunwind      (requires --enable-prof-libunwind)\n    + libgcc         (unless --disable-prof-libgcc)\n    + gcc intrinsics (unless --disable-prof-gcc)\n\n--enable-prof-libunwind\n    Use the libunwind library (http://www.nongnu.org/libunwind/) for stack\n    backtracing.\n\n--disable-prof-libgcc\n    Disable the use of libgcc's backtracing functionality.\n\n--disable-prof-gcc\n    Disable the use of gcc intrinsics for backtracing.\n\n--with-static-libunwind=<libunwind.a>\n    Statically link against the specified libunwind.a rather than dynamically\n    linking with -lunwind.\n\n--disable-tcache\n    Disable thread-specific caches for small objects.  Objects are cached and\n    released in bulk, thus reducing the total number of mutex operations.  See\n    the \"opt.tcache\" option for usage details.\n\n--enable-mremap\n    Enable huge realloc() via mremap(2).  mremap() is disabled by default\n    because the flavor used is specific to Linux, which has a quirk in its\n    virtual memory allocation algorithm that causes semi-permanent VM map holes\n    under normal jemalloc operation.\n\n--disable-munmap\n    Disable virtual memory deallocation via munmap(2); instead keep track of\n    the virtual memory for later use.  munmap() is disabled by default (i.e.\n    --disable-munmap is implied) on Linux, which has a quirk in its virtual\n    memory allocation algorithm that causes semi-permanent VM map holes under\n    normal jemalloc operation.\n\n--enable-dss\n    Enable support for page allocation/deallocation via sbrk(2), in addition to\n    mmap(2).\n\n--disable-fill\n    Disable support for junk/zero filling of memory, quarantine, and redzones.\n    See the \"opt.junk\", \"opt.zero\", \"opt.quarantine\", and \"opt.redzone\" option\n    documentation for usage details.\n\n--disable-valgrind\n    Disable support for Valgrind.\n\n--disable-experimental\n    Disable support for the experimental API (*allocm()).\n\n--disable-zone-allocator\n    Disable zone allocator for Darwin. This means jemalloc won't be hooked as\n    the default allocator on OSX/iOS.\n\n--enable-utrace\n    Enable utrace(2)-based allocation tracing.  This feature is not broadly\n    portable (FreeBSD has it, but Linux and OS X do not).\n\n--enable-xmalloc\n    Enable support for optional immediate termination due to out-of-memory\n    errors, as is commonly implemented by \"xmalloc\" wrapper function for malloc.\n    See the \"opt.xmalloc\" option documentation for usage details.\n\n--enable-lazy-lock\n    Enable code that wraps pthread_create() to detect when an application\n    switches from single-threaded to multi-threaded mode, so that it can avoid\n    mutex locking/unlocking operations while in single-threaded mode.  In\n    practice, this feature usually has little impact on performance unless\n    thread-specific caching is disabled.\n\n--disable-tls\n    Disable thread-local storage (TLS), which allows for fast access to\n    thread-local variables via the __thread keyword.  If TLS is available,\n    jemalloc uses it for several purposes.\n\n--with-xslroot=<path>\n    Specify where to find DocBook XSL stylesheets when building the\n    documentation.\n\nThe following environment variables (not a definitive list) impact configure's\nbehavior:\n\nCFLAGS=\"?\"\n    Pass these flags to the compiler.  You probably shouldn't define this unless\n    you know what you are doing.  (Use EXTRA_CFLAGS instead.)\n\nEXTRA_CFLAGS=\"?\"\n    Append these flags to CFLAGS.  This makes it possible to add flags such as\n    -Werror, while allowing the configure script to determine what other flags\n    are appropriate for the specified configuration.\n\n    The configure script specifically checks whether an optimization flag (-O*)\n    is specified in EXTRA_CFLAGS, and refrains from specifying an optimization\n    level if it finds that one has already been specified.\n\nCPPFLAGS=\"?\"\n    Pass these flags to the C preprocessor.  Note that CFLAGS is not passed to\n    'cpp' when 'configure' is looking for include files, so you must use\n    CPPFLAGS instead if you need to help 'configure' find header files.\n\nLD_LIBRARY_PATH=\"?\"\n    'ld' uses this colon-separated list to find libraries.\n\nLDFLAGS=\"?\"\n    Pass these flags when linking.\n\nPATH=\"?\"\n    'configure' uses this to find programs.\n\n=== Advanced compilation =======================================================\n\nTo build only parts of jemalloc, use the following targets:\n\n    build_lib_shared\n    build_lib_static\n    build_lib\n    build_doc_html\n    build_doc_man\n    build_doc\n\nTo install only parts of jemalloc, use the following targets:\n\n    install_bin\n    install_include\n    install_lib_shared\n    install_lib_static\n    install_lib\n    install_doc_html\n    install_doc_man\n    install_doc\n\nTo clean up build results to varying degrees, use the following make targets:\n\n    clean\n    distclean\n    relclean\n\n=== Advanced installation ======================================================\n\nOptionally, define make variables when invoking make, including (not\nexclusively):\n\nINCLUDEDIR=\"?\"\n    Use this as the installation prefix for header files.\n\nLIBDIR=\"?\"\n    Use this as the installation prefix for libraries.\n\nMANDIR=\"?\"\n    Use this as the installation prefix for man pages.\n\nDESTDIR=\"?\"\n    Prepend DESTDIR to INCLUDEDIR, LIBDIR, DATADIR, and MANDIR.  This is useful\n    when installing to a different path than was specified via --prefix.\n\nCC=\"?\"\n    Use this to invoke the C compiler.\n\nCFLAGS=\"?\"\n    Pass these flags to the compiler.\n\nCPPFLAGS=\"?\"\n    Pass these flags to the C preprocessor.\n\nLDFLAGS=\"?\"\n    Pass these flags when linking.\n\nPATH=\"?\"\n    Use this to search for programs used during configuration and building.\n\n=== Development ================================================================\n\nIf you intend to make non-trivial changes to jemalloc, use the 'autogen.sh'\nscript rather than 'configure'.  This re-generates 'configure', enables\nconfiguration dependency rules, and enables re-generation of automatically\ngenerated source files.\n\nThe build system supports using an object directory separate from the source\ntree.  For example, you can create an 'obj' directory, and from within that\ndirectory, issue configuration and build commands:\n\n    autoconf\n    mkdir obj\n    cd obj\n    ../configure --enable-autogen\n    make\n\n=== Documentation ==============================================================\n\nThe manual page is generated in both html and roff formats.  Any web browser\ncan be used to view the html manual.  The roff manual page can be formatted\nprior to installation via the following command:\n\n    nroff -man -t doc/jemalloc.3\n"
  },
  {
    "path": "extern/deprecated/redis-2.8.21/deps/jemalloc/Makefile.in",
    "content": "# Clear out all vpaths, then set just one (default vpath) for the main build\n# directory.\nvpath\nvpath % .\n\n# Clear the default suffixes, so that built-in rules are not used.\n.SUFFIXES :\n\nSHELL := /bin/sh\n\nCC := @CC@\n\n# Configuration parameters.\nDESTDIR =\nBINDIR := $(DESTDIR)@BINDIR@\nINCLUDEDIR := $(DESTDIR)@INCLUDEDIR@\nLIBDIR := $(DESTDIR)@LIBDIR@\nDATADIR := $(DESTDIR)@DATADIR@\nMANDIR := $(DESTDIR)@MANDIR@\nsrcroot := @srcroot@\nobjroot := @objroot@\nabs_srcroot := @abs_srcroot@\nabs_objroot := @abs_objroot@\n\n# Build parameters.\nCPPFLAGS := @CPPFLAGS@ -I$(srcroot)include -I$(objroot)include\nCFLAGS := @CFLAGS@\nLDFLAGS := @LDFLAGS@\nEXTRA_LDFLAGS := @EXTRA_LDFLAGS@\nLIBS := @LIBS@\nRPATH_EXTRA := @RPATH_EXTRA@\nSO := @so@\nIMPORTLIB := @importlib@\nO := @o@\nA := @a@\nEXE := @exe@\nLIBPREFIX := @libprefix@\nREV := @rev@\ninstall_suffix := @install_suffix@\nABI := @abi@\nXSLTPROC := @XSLTPROC@\nAUTOCONF := @AUTOCONF@\n_RPATH = @RPATH@\nRPATH = $(if $(1),$(call _RPATH,$(1)))\ncfghdrs_in := @cfghdrs_in@\ncfghdrs_out := @cfghdrs_out@\ncfgoutputs_in := @cfgoutputs_in@\ncfgoutputs_out := @cfgoutputs_out@\nenable_autogen := @enable_autogen@\nenable_code_coverage := @enable_code_coverage@\nenable_experimental := @enable_experimental@\nenable_zone_allocator := @enable_zone_allocator@\nDSO_LDFLAGS = @DSO_LDFLAGS@\nSOREV = @SOREV@\nPIC_CFLAGS = @PIC_CFLAGS@\nCTARGET = @CTARGET@\nLDTARGET = @LDTARGET@\nMKLIB = @MKLIB@\nAR = @AR@\nARFLAGS = @ARFLAGS@\nCC_MM = @CC_MM@\n\nifeq (macho, $(ABI))\nTEST_LIBRARY_PATH := DYLD_FALLBACK_LIBRARY_PATH=\"$(objroot)lib\"\nelse\nifeq (pecoff, $(ABI))\nTEST_LIBRARY_PATH := PATH=\"$(PATH):$(objroot)lib\"\nelse\nTEST_LIBRARY_PATH :=\nendif\nendif\n\nLIBJEMALLOC := $(LIBPREFIX)jemalloc$(install_suffix)\n\n# Lists of files.\nBINS := $(srcroot)bin/pprof $(objroot)bin/jemalloc.sh\nC_HDRS := $(objroot)include/jemalloc/jemalloc$(install_suffix).h\nC_SRCS := $(srcroot)src/jemalloc.c $(srcroot)src/arena.c \\\n\t$(srcroot)src/atomic.c $(srcroot)src/base.c $(srcroot)src/bitmap.c \\\n\t$(srcroot)src/chunk.c $(srcroot)src/chunk_dss.c \\\n\t$(srcroot)src/chunk_mmap.c $(srcroot)src/ckh.c $(srcroot)src/ctl.c \\\n\t$(srcroot)src/extent.c $(srcroot)src/hash.c $(srcroot)src/huge.c \\\n\t$(srcroot)src/mb.c $(srcroot)src/mutex.c $(srcroot)src/prof.c \\\n\t$(srcroot)src/quarantine.c $(srcroot)src/rtree.c $(srcroot)src/stats.c \\\n\t$(srcroot)src/tcache.c $(srcroot)src/util.c $(srcroot)src/tsd.c\nifeq ($(enable_zone_allocator), 1)\nC_SRCS += $(srcroot)src/zone.c\nendif\nifeq ($(IMPORTLIB),$(SO))\nSTATIC_LIBS := $(objroot)lib/$(LIBJEMALLOC).$(A)\nendif\nifdef PIC_CFLAGS\nSTATIC_LIBS += $(objroot)lib/$(LIBJEMALLOC)_pic.$(A)\nelse\nSTATIC_LIBS += $(objroot)lib/$(LIBJEMALLOC)_s.$(A)\nendif\nDSOS := $(objroot)lib/$(LIBJEMALLOC).$(SOREV)\nifneq ($(SOREV),$(SO))\nDSOS += $(objroot)lib/$(LIBJEMALLOC).$(SO)\nendif\nMAN3 := $(objroot)doc/jemalloc$(install_suffix).3\nDOCS_XML := $(objroot)doc/jemalloc$(install_suffix).xml\nDOCS_HTML := $(DOCS_XML:$(objroot)%.xml=$(srcroot)%.html)\nDOCS_MAN3 := $(DOCS_XML:$(objroot)%.xml=$(srcroot)%.3)\nDOCS := $(DOCS_HTML) $(DOCS_MAN3)\nC_TESTLIB_SRCS := $(srcroot)test/src/math.c $(srcroot)test/src/mtx.c \\\n\t$(srcroot)test/src/SFMT.c $(srcroot)test/src/test.c \\\n\t$(srcroot)test/src/thd.c\nC_UTIL_INTEGRATION_SRCS := $(srcroot)src/util.c\nTESTS_UNIT := $(srcroot)test/unit/bitmap.c \\\n\t$(srcroot)test/unit/ckh.c \\\n\t$(srcroot)test/unit/hash.c \\\n\t$(srcroot)test/unit/junk.c \\\n\t$(srcroot)test/unit/mallctl.c \\\n\t$(srcroot)test/unit/math.c \\\n\t$(srcroot)test/unit/mq.c \\\n\t$(srcroot)test/unit/mtx.c \\\n\t$(srcroot)test/unit/prof_accum.c \\\n\t$(srcroot)test/unit/prof_gdump.c \\\n\t$(srcroot)test/unit/prof_idump.c \\\n\t$(srcroot)test/unit/ql.c \\\n\t$(srcroot)test/unit/qr.c \\\n\t$(srcroot)test/unit/quarantine.c \\\n\t$(srcroot)test/unit/rb.c \\\n\t$(srcroot)test/unit/rtree.c \\\n\t$(srcroot)test/unit/SFMT.c \\\n\t$(srcroot)test/unit/stats.c \\\n\t$(srcroot)test/unit/tsd.c \\\n\t$(srcroot)test/unit/util.c \\\n\t$(srcroot)test/unit/zero.c\nTESTS_UNIT_AUX := $(srcroot)test/unit/prof_accum_a.c \\\n\t$(srcroot)test/unit/prof_accum_b.c\nTESTS_INTEGRATION := $(srcroot)test/integration/aligned_alloc.c \\\n\t$(srcroot)test/integration/allocated.c \\\n\t$(srcroot)test/integration/mallocx.c \\\n\t$(srcroot)test/integration/mremap.c \\\n\t$(srcroot)test/integration/posix_memalign.c \\\n\t$(srcroot)test/integration/rallocx.c \\\n\t$(srcroot)test/integration/thread_arena.c \\\n\t$(srcroot)test/integration/thread_tcache_enabled.c \\\n\t$(srcroot)test/integration/xallocx.c\nifeq ($(enable_experimental), 1)\nTESTS_INTEGRATION += $(srcroot)test/integration/allocm.c \\\n\t$(srcroot)test/integration/MALLOCX_ARENA.c \\\n\t$(srcroot)test/integration/rallocm.c\nendif\nTESTS_STRESS :=\nTESTS := $(TESTS_UNIT) $(TESTS_INTEGRATION) $(TESTS_STRESS)\n\nC_OBJS := $(C_SRCS:$(srcroot)%.c=$(objroot)%.$(O))\nC_PIC_OBJS := $(C_SRCS:$(srcroot)%.c=$(objroot)%.pic.$(O))\nC_JET_OBJS := $(C_SRCS:$(srcroot)%.c=$(objroot)%.jet.$(O))\nC_TESTLIB_UNIT_OBJS := $(C_TESTLIB_SRCS:$(srcroot)%.c=$(objroot)%.unit.$(O))\nC_TESTLIB_INTEGRATION_OBJS := $(C_TESTLIB_SRCS:$(srcroot)%.c=$(objroot)%.integration.$(O))\nC_UTIL_INTEGRATION_OBJS := $(C_UTIL_INTEGRATION_SRCS:$(srcroot)%.c=$(objroot)%.integration.$(O))\nC_TESTLIB_STRESS_OBJS := $(C_TESTLIB_SRCS:$(srcroot)%.c=$(objroot)%.stress.$(O))\nC_TESTLIB_OBJS := $(C_TESTLIB_UNIT_OBJS) $(C_TESTLIB_INTEGRATION_OBJS) $(C_UTIL_INTEGRATION_OBJS) $(C_TESTLIB_STRESS_OBJS)\n\nTESTS_UNIT_OBJS := $(TESTS_UNIT:$(srcroot)%.c=$(objroot)%.$(O))\nTESTS_UNIT_AUX_OBJS := $(TESTS_UNIT_AUX:$(srcroot)%.c=$(objroot)%.$(O))\nTESTS_INTEGRATION_OBJS := $(TESTS_INTEGRATION:$(srcroot)%.c=$(objroot)%.$(O))\nTESTS_STRESS_OBJS := $(TESTS_STRESS:$(srcroot)%.c=$(objroot)%.$(O))\nTESTS_OBJS := $(TESTS_UNIT_OBJS) $(TESTS_UNIT_AUX_OBJS) $(TESTS_INTEGRATION_OBJS) $(TESTS_STRESS_OBJS)\n\n.PHONY: all dist build_doc_html build_doc_man build_doc\n.PHONY: install_bin install_include install_lib\n.PHONY: install_doc_html install_doc_man install_doc install\n.PHONY: tests check clean distclean relclean\n\n.SECONDARY : $(TESTS_OBJS)\n\n# Default target.\nall: build_lib\n\ndist: build_doc\n\n$(srcroot)doc/%.html : $(objroot)doc/%.xml $(srcroot)doc/stylesheet.xsl $(objroot)doc/html.xsl\n\t$(XSLTPROC) -o $@ $(objroot)doc/html.xsl $<\n\n$(srcroot)doc/%.3 : $(objroot)doc/%.xml $(srcroot)doc/stylesheet.xsl $(objroot)doc/manpages.xsl\n\t$(XSLTPROC) -o $@ $(objroot)doc/manpages.xsl $<\n\nbuild_doc_html: $(DOCS_HTML)\nbuild_doc_man: $(DOCS_MAN3)\nbuild_doc: $(DOCS)\n\n#\n# Include generated dependency files.\n#\nifdef CC_MM\n-include $(C_OBJS:%.$(O)=%.d)\n-include $(C_PIC_OBJS:%.$(O)=%.d)\n-include $(C_JET_OBJS:%.$(O)=%.d)\n-include $(C_TESTLIB_OBJS:%.$(O)=%.d)\n-include $(TESTS_OBJS:%.$(O)=%.d)\nendif\n\n$(C_OBJS): $(objroot)src/%.$(O): $(srcroot)src/%.c\n$(C_PIC_OBJS): $(objroot)src/%.pic.$(O): $(srcroot)src/%.c\n$(C_PIC_OBJS): CFLAGS += $(PIC_CFLAGS)\n$(C_JET_OBJS): $(objroot)src/%.jet.$(O): $(srcroot)src/%.c\n$(C_JET_OBJS): CFLAGS += -DJEMALLOC_JET\n$(C_TESTLIB_UNIT_OBJS): $(objroot)test/src/%.unit.$(O): $(srcroot)test/src/%.c\n$(C_TESTLIB_UNIT_OBJS): CPPFLAGS += -DJEMALLOC_UNIT_TEST\n$(C_TESTLIB_INTEGRATION_OBJS): $(objroot)test/src/%.integration.$(O): $(srcroot)test/src/%.c\n$(C_TESTLIB_INTEGRATION_OBJS): CPPFLAGS += -DJEMALLOC_INTEGRATION_TEST\n$(C_UTIL_INTEGRATION_OBJS): $(objroot)src/%.integration.$(O): $(srcroot)src/%.c\n$(C_TESTLIB_STRESS_OBJS): $(objroot)test/src/%.stress.$(O): $(srcroot)test/src/%.c\n$(C_TESTLIB_STRESS_OBJS): CPPFLAGS += -DJEMALLOC_STRESS_TEST -DJEMALLOC_STRESS_TESTLIB\n$(C_TESTLIB_OBJS): CPPFLAGS += -I$(srcroot)test/include -I$(objroot)test/include\n$(TESTS_UNIT_OBJS): CPPFLAGS += -DJEMALLOC_UNIT_TEST\n$(TESTS_UNIT_AUX_OBJS): CPPFLAGS += -DJEMALLOC_UNIT_TEST\ndefine make-unit-link-dep\n$(1): TESTS_UNIT_LINK_OBJS += $(2)\n$(1): $(2)\nendef\n$(foreach test, $(TESTS_UNIT:$(srcroot)test/unit/%.c=$(objroot)test/unit/%$(EXE)), $(eval $(call make-unit-link-dep,$(test),$(filter $(test:%=%_a.$(O)) $(test:%=%_b.$(O)),$(TESTS_UNIT_AUX_OBJS)))))\n$(TESTS_INTEGRATION_OBJS): CPPFLAGS += -DJEMALLOC_INTEGRATION_TEST\n$(TESTS_STRESS_OBJS): CPPFLAGS += -DJEMALLOC_STRESS_TEST\n$(TESTS_OBJS): $(objroot)test/%.$(O): $(srcroot)test/%.c\n$(TESTS_OBJS): CPPFLAGS += -I$(srcroot)test/include -I$(objroot)test/include\nifneq ($(IMPORTLIB),$(SO))\n$(C_OBJS): CPPFLAGS += -DDLLEXPORT\nendif\n\nifndef CC_MM\n# Dependencies.\nHEADER_DIRS = $(srcroot)include/jemalloc/internal \\\n\t$(objroot)include/jemalloc $(objroot)include/jemalloc/internal\nHEADERS = $(wildcard $(foreach dir,$(HEADER_DIRS),$(dir)/*.h))\n$(C_OBJS) $(C_PIC_OBJS) $(C_JET_OBJS) $(C_TESTLIB_OBJS) $(TESTS_OBJS): $(HEADERS)\n$(TESTS_OBJS): $(objroot)test/unit/jemalloc_test.h\nendif\n\n$(C_OBJS) $(C_PIC_OBJS) $(C_JET_OBJS) $(C_TESTLIB_OBJS) $(TESTS_OBJS): %.$(O):\n\t@mkdir -p $(@D)\n\t$(CC) $(CFLAGS) -c $(CPPFLAGS) $(CTARGET) $<\nifdef CC_MM\n\t@$(CC) -MM $(CPPFLAGS) -MT $@ -o $(@:%.$(O)=%.d) $<\nendif\n\nifneq ($(SOREV),$(SO))\n%.$(SO) : %.$(SOREV)\n\t@mkdir -p $(@D)\n\tln -sf $(<F) $@\nendif\n\n$(objroot)lib/$(LIBJEMALLOC).$(SOREV) : $(if $(PIC_CFLAGS),$(C_PIC_OBJS),$(C_OBJS))\n\t@mkdir -p $(@D)\n\t$(CC) $(DSO_LDFLAGS) $(call RPATH,$(RPATH_EXTRA)) $(LDTARGET) $+ $(LDFLAGS) $(LIBS) $(EXTRA_LDFLAGS)\n\n$(objroot)lib/$(LIBJEMALLOC)_pic.$(A) : $(C_PIC_OBJS)\n$(objroot)lib/$(LIBJEMALLOC).$(A) : $(C_OBJS)\n$(objroot)lib/$(LIBJEMALLOC)_s.$(A) : $(C_OBJS)\n\n$(STATIC_LIBS):\n\t@mkdir -p $(@D)\n\t$(AR) $(ARFLAGS)@AROUT@ $+\n\n$(objroot)test/unit/%$(EXE): $(objroot)test/unit/%.$(O) $(TESTS_UNIT_LINK_OBJS) $(C_JET_OBJS) $(C_TESTLIB_UNIT_OBJS)\n\t@mkdir -p $(@D)\n\t$(CC) $(LDTARGET) $(filter %.$(O),$^) $(call RPATH,$(objroot)lib) $(LDFLAGS) $(filter-out -lm,$(LIBS)) -lm $(EXTRA_LDFLAGS)\n\n$(objroot)test/integration/%$(EXE): $(objroot)test/integration/%.$(O) $(C_TESTLIB_INTEGRATION_OBJS) $(C_UTIL_INTEGRATION_OBJS) $(objroot)lib/$(LIBJEMALLOC).$(IMPORTLIB)\n\t@mkdir -p $(@D)\n\t$(CC) $(LDTARGET) $(filter %.$(O),$^) $(call RPATH,$(objroot)lib) $(objroot)lib/$(LIBJEMALLOC).$(IMPORTLIB) $(LDFLAGS) $(filter-out -lm,$(filter -lpthread,$(LIBS))) -lm $(EXTRA_LDFLAGS)\n\n$(objroot)test/stress/%$(EXE): $(objroot)test/stress/%.$(O) $(C_JET_OBJS) $(C_TESTLIB_STRESS_OBJS) $(objroot)lib/$(LIBJEMALLOC).$(IMPORTLIB)\n\t@mkdir -p $(@D)\n\t$(CC) $(LDTARGET) $(filter %.$(O),$^) $(call RPATH,$(objroot)lib) $(objroot)lib/$(LIBJEMALLOC).$(IMPORTLIB) $(LDFLAGS) $(filter-out -lm,$(LIBS)) -lm $(EXTRA_LDFLAGS)\n\nbuild_lib_shared: $(DSOS)\nbuild_lib_static: $(STATIC_LIBS)\nbuild_lib: build_lib_shared build_lib_static\n\ninstall_bin:\n\tinstall -d $(BINDIR)\n\t@for b in $(BINS); do \\\n\techo \"install -m 755 $$b $(BINDIR)\"; \\\n\tinstall -m 755 $$b $(BINDIR); \\\ndone\n\ninstall_include:\n\tinstall -d $(INCLUDEDIR)/jemalloc\n\t@for h in $(C_HDRS); do \\\n\techo \"install -m 644 $$h $(INCLUDEDIR)/jemalloc\"; \\\n\tinstall -m 644 $$h $(INCLUDEDIR)/jemalloc; \\\ndone\n\ninstall_lib_shared: $(DSOS)\n\tinstall -d $(LIBDIR)\n\tinstall -m 755 $(objroot)lib/$(LIBJEMALLOC).$(SOREV) $(LIBDIR)\nifneq ($(SOREV),$(SO))\n\tln -sf $(LIBJEMALLOC).$(SOREV) $(LIBDIR)/$(LIBJEMALLOC).$(SO)\nendif\n\ninstall_lib_static: $(STATIC_LIBS)\n\tinstall -d $(LIBDIR)\n\t@for l in $(STATIC_LIBS); do \\\n\techo \"install -m 755 $$l $(LIBDIR)\"; \\\n\tinstall -m 755 $$l $(LIBDIR); \\\ndone\n\ninstall_lib: install_lib_shared install_lib_static\n\ninstall_doc_html:\n\tinstall -d $(DATADIR)/doc/jemalloc$(install_suffix)\n\t@for d in $(DOCS_HTML); do \\\n\techo \"install -m 644 $$d $(DATADIR)/doc/jemalloc$(install_suffix)\"; \\\n\tinstall -m 644 $$d $(DATADIR)/doc/jemalloc$(install_suffix); \\\ndone\n\ninstall_doc_man:\n\tinstall -d $(MANDIR)/man3\n\t@for d in $(DOCS_MAN3); do \\\n\techo \"install -m 644 $$d $(MANDIR)/man3\"; \\\n\tinstall -m 644 $$d $(MANDIR)/man3; \\\ndone\n\ninstall_doc: install_doc_html install_doc_man\n\ninstall: install_bin install_include install_lib install_doc\n\ntests_unit: $(TESTS_UNIT:$(srcroot)%.c=$(objroot)%$(EXE))\ntests_integration: $(TESTS_INTEGRATION:$(srcroot)%.c=$(objroot)%$(EXE))\ntests_stress: $(TESTS_STRESS:$(srcroot)%.c=$(objroot)%$(EXE))\ntests: tests_unit tests_integration tests_stress\n\ncheck_unit_dir:\n\t@mkdir -p $(objroot)test/unit\ncheck_integration_dir:\n\t@mkdir -p $(objroot)test/integration\ncheck_stress_dir:\n\t@mkdir -p $(objroot)test/stress\ncheck_dir: check_unit_dir check_integration_dir check_stress_dir\n\ncheck_unit: tests_unit check_unit_dir\n\t$(SHELL) $(objroot)test/test.sh $(TESTS_UNIT:$(srcroot)%.c=$(objroot)%)\ncheck_integration: tests_integration check_integration_dir\n\t$(SHELL) $(objroot)test/test.sh $(TESTS_INTEGRATION:$(srcroot)%.c=$(objroot)%)\ncheck_stress: tests_stress check_stress_dir\n\t$(SHELL) $(objroot)test/test.sh $(TESTS_STRESS:$(srcroot)%.c=$(objroot)%)\ncheck: tests check_dir\n\t$(SHELL) $(objroot)test/test.sh $(TESTS:$(srcroot)%.c=$(objroot)%)\n\nifeq ($(enable_code_coverage), 1)\ncoverage_unit: check_unit\n\t$(SHELL) $(srcroot)coverage.sh $(srcroot)src jet $(C_JET_OBJS)\n\t$(SHELL) $(srcroot)coverage.sh $(srcroot)test/src unit $(C_TESTLIB_UNIT_OBJS)\n\t$(SHELL) $(srcroot)coverage.sh $(srcroot)test/unit unit $(TESTS_UNIT_OBJS)\n\ncoverage_integration: check_integration\n\t$(SHELL) $(srcroot)coverage.sh $(srcroot)src pic $(C_PIC_OBJS)\n\t$(SHELL) $(srcroot)coverage.sh $(srcroot)src integration $(C_UTIL_INTEGRATION_OBJS)\n\t$(SHELL) $(srcroot)coverage.sh $(srcroot)test/src integration $(C_TESTLIB_INTEGRATION_OBJS)\n\t$(SHELL) $(srcroot)coverage.sh $(srcroot)test/integration integration $(TESTS_INTEGRATION_OBJS)\n\ncoverage_stress: check_stress\n\t$(SHELL) $(srcroot)coverage.sh $(srcroot)src pic $(C_PIC_OBJS)\n\t$(SHELL) $(srcroot)coverage.sh $(srcroot)src jet $(C_JET_OBJS)\n\t$(SHELL) $(srcroot)coverage.sh $(srcroot)test/src stress $(C_TESTLIB_STRESS_OBJS)\n\t$(SHELL) $(srcroot)coverage.sh $(srcroot)test/stress stress $(TESTS_STRESS_OBJS)\n\ncoverage: check\n\t$(SHELL) $(srcroot)coverage.sh $(srcroot)src pic $(C_PIC_OBJS)\n\t$(SHELL) $(srcroot)coverage.sh $(srcroot)src jet $(C_JET_OBJS)\n\t$(SHELL) $(srcroot)coverage.sh $(srcroot)src integration $(C_UTIL_INTEGRATION_OBJS)\n\t$(SHELL) $(srcroot)coverage.sh $(srcroot)test/src unit $(C_TESTLIB_UNIT_OBJS)\n\t$(SHELL) $(srcroot)coverage.sh $(srcroot)test/src integration $(C_TESTLIB_INTEGRATION_OBJS)\n\t$(SHELL) $(srcroot)coverage.sh $(srcroot)test/src stress $(C_TESTLIB_STRESS_OBJS)\n\t$(SHELL) $(srcroot)coverage.sh $(srcroot)test/unit unit $(TESTS_UNIT_OBJS) $(TESTS_UNIT_AUX_OBJS)\n\t$(SHELL) $(srcroot)coverage.sh $(srcroot)test/integration integration $(TESTS_INTEGRATION_OBJS)\n\t$(SHELL) $(srcroot)coverage.sh $(srcroot)test/stress integration $(TESTS_STRESS_OBJS)\nendif\n\nclean:\n\trm -f $(C_OBJS)\n\trm -f $(C_PIC_OBJS)\n\trm -f $(C_JET_OBJS)\n\trm -f $(C_TESTLIB_OBJS)\n\trm -f $(C_OBJS:%.$(O)=%.d)\n\trm -f $(C_OBJS:%.$(O)=%.gcda)\n\trm -f $(C_OBJS:%.$(O)=%.gcno)\n\trm -f $(C_PIC_OBJS:%.$(O)=%.d)\n\trm -f $(C_PIC_OBJS:%.$(O)=%.gcda)\n\trm -f $(C_PIC_OBJS:%.$(O)=%.gcno)\n\trm -f $(C_JET_OBJS:%.$(O)=%.d)\n\trm -f $(C_JET_OBJS:%.$(O)=%.gcda)\n\trm -f $(C_JET_OBJS:%.$(O)=%.gcno)\n\trm -f $(C_TESTLIB_OBJS:%.$(O)=%.d)\n\trm -f $(C_TESTLIB_OBJS:%.$(O)=%.gcda)\n\trm -f $(C_TESTLIB_OBJS:%.$(O)=%.gcno)\n\trm -f $(TESTS_OBJS:%.$(O)=%$(EXE))\n\trm -f $(TESTS_OBJS)\n\trm -f $(TESTS_OBJS:%.$(O)=%.d)\n\trm -f $(TESTS_OBJS:%.$(O)=%.gcda)\n\trm -f $(TESTS_OBJS:%.$(O)=%.gcno)\n\trm -f $(TESTS_OBJS:%.$(O)=%.out)\n\trm -f $(DSOS) $(STATIC_LIBS)\n\trm -f $(objroot)*.gcov.*\n\ndistclean: clean\n\trm -rf $(objroot)autom4te.cache\n\trm -f $(objroot)bin/jemalloc.sh\n\trm -f $(objroot)config.log\n\trm -f $(objroot)config.status\n\trm -f $(objroot)config.stamp\n\trm -f $(cfghdrs_out)\n\trm -f $(cfgoutputs_out)\n\nrelclean: distclean\n\trm -f $(objroot)configure\n\trm -f $(srcroot)VERSION\n\trm -f $(DOCS_HTML)\n\trm -f $(DOCS_MAN3)\n\n#===============================================================================\n# Re-configuration rules.\n\nifeq ($(enable_autogen), 1)\n$(srcroot)configure : $(srcroot)configure.ac\n\tcd ./$(srcroot) && $(AUTOCONF)\n\n$(objroot)config.status : $(srcroot)configure\n\t./$(objroot)config.status --recheck\n\n$(srcroot)config.stamp.in : $(srcroot)configure.ac\n\techo stamp > $(srcroot)config.stamp.in\n\n$(objroot)config.stamp : $(cfgoutputs_in) $(cfghdrs_in) $(srcroot)configure\n\t./$(objroot)config.status\n\t@touch $@\n\n# There must be some action in order for make to re-read Makefile when it is\n# out of date.\n$(cfgoutputs_out) $(cfghdrs_out) : $(objroot)config.stamp\n\t@true\nendif\n"
  },
  {
    "path": "extern/deprecated/redis-2.8.21/deps/jemalloc/README",
    "content": "jemalloc is a general purpose malloc(3) implementation that emphasizes\nfragmentation avoidance and scalable concurrency support.  jemalloc first came\ninto use as the FreeBSD libc allocator in 2005, and since then it has found its\nway into numerous applications that rely on its predictable behavior.  In 2010\njemalloc development efforts broadened to include developer support features\nsuch as heap profiling, Valgrind integration, and extensive monitoring/tuning\nhooks.  Modern jemalloc releases continue to be integrated back into FreeBSD,\nand therefore versatility remains critical.  Ongoing development efforts trend\ntoward making jemalloc among the best allocators for a broad range of demanding\napplications, and eliminating/mitigating weaknesses that have practical\nrepercussions for real world applications.\n\nThe COPYING file contains copyright and licensing information.\n\nThe INSTALL file contains information on how to configure, build, and install\njemalloc.\n\nThe ChangeLog file contains a brief summary of changes for each release.\n\nURL: http://www.canonware.com/jemalloc/\n"
  },
  {
    "path": "extern/deprecated/redis-2.8.21/deps/jemalloc/autogen.sh",
    "content": "#!/bin/sh\n\nfor i in autoconf; do\n    echo \"$i\"\n    $i\n    if [ $? -ne 0 ]; then\n\techo \"Error $? in $i\"\n\texit 1\n    fi\ndone\n\necho \"./configure --enable-autogen $@\"\n./configure --enable-autogen $@\nif [ $? -ne 0 ]; then\n    echo \"Error $? in ./configure\"\n    exit 1\nfi\n"
  },
  {
    "path": "extern/deprecated/redis-2.8.21/deps/jemalloc/bin/jemalloc.sh.in",
    "content": "#!/bin/sh\n\nprefix=@prefix@\nexec_prefix=@exec_prefix@\nlibdir=@libdir@\n\n@LD_PRELOAD_VAR@=${libdir}/libjemalloc.@SOREV@\nexport @LD_PRELOAD_VAR@\nexec \"$@\"\n"
  },
  {
    "path": "extern/deprecated/redis-2.8.21/deps/jemalloc/bin/pprof",
    "content": "#! /usr/bin/env perl\n\n# Copyright (c) 1998-2007, Google Inc.\n# All rights reserved.\n# \n# Redistribution and use in source and binary forms, with or without\n# modification, are permitted provided that the following conditions are\n# met:\n# \n#     * Redistributions of source code must retain the above copyright\n# notice, this list of conditions and the following disclaimer.\n#     * Redistributions in binary form must reproduce the above\n# copyright notice, this list of conditions and the following disclaimer\n# in the documentation and/or other materials provided with the\n# distribution.\n#     * Neither the name of Google Inc. nor the names of its\n# contributors may be used to endorse or promote products derived from\n# this software without specific prior written permission.\n# \n# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n# \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\n# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\n# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\n# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\n# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n\n# ---\n# Program for printing the profile generated by common/profiler.cc,\n# or by the heap profiler (common/debugallocation.cc)\n#\n# The profile contains a sequence of entries of the form:\n#       <count> <stack trace>\n# This program parses the profile, and generates user-readable\n# output.\n#\n# Examples:\n#\n# % tools/pprof \"program\" \"profile\"\n#   Enters \"interactive\" mode\n#\n# % tools/pprof --text \"program\" \"profile\"\n#   Generates one line per procedure\n#\n# % tools/pprof --gv \"program\" \"profile\"\n#   Generates annotated call-graph and displays via \"gv\"\n#\n# % tools/pprof --gv --focus=Mutex \"program\" \"profile\"\n#   Restrict to code paths that involve an entry that matches \"Mutex\"\n#\n# % tools/pprof --gv --focus=Mutex --ignore=string \"program\" \"profile\"\n#   Restrict to code paths that involve an entry that matches \"Mutex\"\n#   and does not match \"string\"\n#\n# % tools/pprof --list=IBF_CheckDocid \"program\" \"profile\"\n#   Generates disassembly listing of all routines with at least one\n#   sample that match the --list=<regexp> pattern.  The listing is\n#   annotated with the flat and cumulative sample counts at each line.\n#\n# % tools/pprof --disasm=IBF_CheckDocid \"program\" \"profile\"\n#   Generates disassembly listing of all routines with at least one\n#   sample that match the --disasm=<regexp> pattern.  The listing is\n#   annotated with the flat and cumulative sample counts at each PC value.\n#\n# TODO: Use color to indicate files?\n\nuse strict;\nuse warnings;\nuse Getopt::Long;\n\nmy $PPROF_VERSION = \"2.0\";\n\n# These are the object tools we use which can come from a\n# user-specified location using --tools, from the PPROF_TOOLS\n# environment variable, or from the environment.\nmy %obj_tool_map = (\n  \"objdump\" => \"objdump\",\n  \"nm\" => \"nm\",\n  \"addr2line\" => \"addr2line\",\n  \"c++filt\" => \"c++filt\",\n  ## ConfigureObjTools may add architecture-specific entries:\n  #\"nm_pdb\" => \"nm-pdb\",       # for reading windows (PDB-format) executables\n  #\"addr2line_pdb\" => \"addr2line-pdb\",                                # ditto\n  #\"otool\" => \"otool\",         # equivalent of objdump on OS X\n);\n# NOTE: these are lists, so you can put in commandline flags if you want.\nmy @DOT = (\"dot\");          # leave non-absolute, since it may be in /usr/local\nmy @GV = (\"gv\");\nmy @EVINCE = (\"evince\");    # could also be xpdf or perhaps acroread\nmy @KCACHEGRIND = (\"kcachegrind\");\nmy @PS2PDF = (\"ps2pdf\");\n# These are used for dynamic profiles\nmy @URL_FETCHER = (\"curl\", \"-s\");\n\n# These are the web pages that servers need to support for dynamic profiles\nmy $HEAP_PAGE = \"/pprof/heap\";\nmy $PROFILE_PAGE = \"/pprof/profile\";   # must support cgi-param \"?seconds=#\"\nmy $PMUPROFILE_PAGE = \"/pprof/pmuprofile(?:\\\\?.*)?\"; # must support cgi-param\n                                                # ?seconds=#&event=x&period=n\nmy $GROWTH_PAGE = \"/pprof/growth\";\nmy $CONTENTION_PAGE = \"/pprof/contention\";\nmy $WALL_PAGE = \"/pprof/wall(?:\\\\?.*)?\";  # accepts options like namefilter\nmy $FILTEREDPROFILE_PAGE = \"/pprof/filteredprofile(?:\\\\?.*)?\";\nmy $CENSUSPROFILE_PAGE = \"/pprof/censusprofile(?:\\\\?.*)?\"; # must support cgi-param\n                                                       # \"?seconds=#\",\n                                                       # \"?tags_regexp=#\" and\n                                                       # \"?type=#\".\nmy $SYMBOL_PAGE = \"/pprof/symbol\";     # must support symbol lookup via POST\nmy $PROGRAM_NAME_PAGE = \"/pprof/cmdline\";\n\n# These are the web pages that can be named on the command line.\n# All the alternatives must begin with /.\nmy $PROFILES = \"($HEAP_PAGE|$PROFILE_PAGE|$PMUPROFILE_PAGE|\" .\n               \"$GROWTH_PAGE|$CONTENTION_PAGE|$WALL_PAGE|\" .\n               \"$FILTEREDPROFILE_PAGE|$CENSUSPROFILE_PAGE)\";\n\n# default binary name\nmy $UNKNOWN_BINARY = \"(unknown)\";\n\n# There is a pervasive dependency on the length (in hex characters,\n# i.e., nibbles) of an address, distinguishing between 32-bit and\n# 64-bit profiles.  To err on the safe size, default to 64-bit here:\nmy $address_length = 16;\n\nmy $dev_null = \"/dev/null\";\nif (! -e $dev_null && $^O =~ /MSWin/) {    # $^O is the OS perl was built for\n  $dev_null = \"nul\";\n}\n\n# A list of paths to search for shared object files\nmy @prefix_list = ();\n\n# Special routine name that should not have any symbols.\n# Used as separator to parse \"addr2line -i\" output.\nmy $sep_symbol = '_fini';\nmy $sep_address = undef;\n\n##### Argument parsing #####\n\nsub usage_string {\n  return <<EOF;\nUsage:\npprof [options] <program> <profiles>\n   <profiles> is a space separated list of profile names.\npprof [options] <symbolized-profiles>\n   <symbolized-profiles> is a list of profile files where each file contains\n   the necessary symbol mappings  as well as profile data (likely generated\n   with --raw).\npprof [options] <profile>\n   <profile> is a remote form.  Symbols are obtained from host:port$SYMBOL_PAGE\n\n   Each name can be:\n   /path/to/profile        - a path to a profile file\n   host:port[/<service>]   - a location of a service to get profile from\n\n   The /<service> can be $HEAP_PAGE, $PROFILE_PAGE, /pprof/pmuprofile,\n                         $GROWTH_PAGE, $CONTENTION_PAGE, /pprof/wall,\n                         $CENSUSPROFILE_PAGE, or /pprof/filteredprofile.\n   For instance:\n     pprof http://myserver.com:80$HEAP_PAGE\n   If /<service> is omitted, the service defaults to $PROFILE_PAGE (cpu profiling).\npprof --symbols <program>\n   Maps addresses to symbol names.  In this mode, stdin should be a\n   list of library mappings, in the same format as is found in the heap-\n   and cpu-profile files (this loosely matches that of /proc/self/maps\n   on linux), followed by a list of hex addresses to map, one per line.\n\n   For more help with querying remote servers, including how to add the\n   necessary server-side support code, see this filename (or one like it):\n\n   /usr/doc/gperftools-$PPROF_VERSION/pprof_remote_servers.html\n\nOptions:\n   --cum               Sort by cumulative data\n   --base=<base>       Subtract <base> from <profile> before display\n   --interactive       Run in interactive mode (interactive \"help\" gives help) [default]\n   --seconds=<n>       Length of time for dynamic profiles [default=30 secs]\n   --add_lib=<file>    Read additional symbols and line info from the given library\n   --lib_prefix=<dir>  Comma separated list of library path prefixes\n\nReporting Granularity:\n   --addresses         Report at address level\n   --lines             Report at source line level\n   --functions         Report at function level [default]\n   --files             Report at source file level\n\nOutput type:\n   --text              Generate text report\n   --callgrind         Generate callgrind format to stdout\n   --gv                Generate Postscript and display\n   --evince            Generate PDF and display\n   --web               Generate SVG and display\n   --list=<regexp>     Generate source listing of matching routines\n   --disasm=<regexp>   Generate disassembly of matching routines\n   --symbols           Print demangled symbol names found at given addresses\n   --dot               Generate DOT file to stdout\n   --ps                Generate Postcript to stdout\n   --pdf               Generate PDF to stdout\n   --svg               Generate SVG to stdout\n   --gif               Generate GIF to stdout\n   --raw               Generate symbolized pprof data (useful with remote fetch)\n\nHeap-Profile Options:\n   --inuse_space       Display in-use (mega)bytes [default]\n   --inuse_objects     Display in-use objects\n   --alloc_space       Display allocated (mega)bytes\n   --alloc_objects     Display allocated objects\n   --show_bytes        Display space in bytes\n   --drop_negative     Ignore negative differences\n\nContention-profile options:\n   --total_delay       Display total delay at each region [default]\n   --contentions       Display number of delays at each region\n   --mean_delay        Display mean delay at each region\n\nCall-graph Options:\n   --nodecount=<n>     Show at most so many nodes [default=80]\n   --nodefraction=<f>  Hide nodes below <f>*total [default=.005]\n   --edgefraction=<f>  Hide edges below <f>*total [default=.001]\n   --maxdegree=<n>     Max incoming/outgoing edges per node [default=8]\n   --focus=<regexp>    Focus on nodes matching <regexp>\n   --ignore=<regexp>   Ignore nodes matching <regexp>\n   --scale=<n>         Set GV scaling [default=0]\n   --heapcheck         Make nodes with non-0 object counts\n                       (i.e. direct leak generators) more visible\n\nMiscellaneous:\n   --tools=<prefix or binary:fullpath>[,...]   \\$PATH for object tool pathnames\n   --test              Run unit tests\n   --help              This message\n   --version           Version information\n\nEnvironment Variables:\n   PPROF_TMPDIR        Profiles directory. Defaults to \\$HOME/pprof\n   PPROF_TOOLS         Prefix for object tools pathnames\n\nExamples:\n\npprof /bin/ls ls.prof\n                       Enters \"interactive\" mode\npprof --text /bin/ls ls.prof\n                       Outputs one line per procedure\npprof --web /bin/ls ls.prof\n                       Displays annotated call-graph in web browser\npprof --gv /bin/ls ls.prof\n                       Displays annotated call-graph via 'gv'\npprof --gv --focus=Mutex /bin/ls ls.prof\n                       Restricts to code paths including a .*Mutex.* entry\npprof --gv --focus=Mutex --ignore=string /bin/ls ls.prof\n                       Code paths including Mutex but not string\npprof --list=getdir /bin/ls ls.prof\n                       (Per-line) annotated source listing for getdir()\npprof --disasm=getdir /bin/ls ls.prof\n                       (Per-PC) annotated disassembly for getdir()\n\npprof http://localhost:1234/\n                       Enters \"interactive\" mode\npprof --text localhost:1234\n                       Outputs one line per procedure for localhost:1234\npprof --raw localhost:1234 > ./local.raw\npprof --text ./local.raw\n                       Fetches a remote profile for later analysis and then\n                       analyzes it in text mode.\nEOF\n}\n\nsub version_string {\n  return <<EOF\npprof (part of gperftools $PPROF_VERSION)\n\nCopyright 1998-2007 Google Inc.\n\nThis is BSD licensed software; see the source for copying conditions\nand license information.\nThere is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A\nPARTICULAR PURPOSE.\nEOF\n}\n\nsub usage {\n  my $msg = shift;\n  print STDERR \"$msg\\n\\n\";\n  print STDERR usage_string();\n  print STDERR \"\\nFATAL ERROR: $msg\\n\";    # just as a reminder\n  exit(1);\n}\n\nsub Init() {\n  # Setup tmp-file name and handler to clean it up.\n  # We do this in the very beginning so that we can use\n  # error() and cleanup() function anytime here after.\n  $main::tmpfile_sym = \"/tmp/pprof$$.sym\";\n  $main::tmpfile_ps = \"/tmp/pprof$$\";\n  $main::next_tmpfile = 0;\n  $SIG{'INT'} = \\&sighandler;\n\n  # Cache from filename/linenumber to source code\n  $main::source_cache = ();\n\n  $main::opt_help = 0;\n  $main::opt_version = 0;\n\n  $main::opt_cum = 0;\n  $main::opt_base = '';\n  $main::opt_addresses = 0;\n  $main::opt_lines = 0;\n  $main::opt_functions = 0;\n  $main::opt_files = 0;\n  $main::opt_lib_prefix = \"\";\n\n  $main::opt_text = 0;\n  $main::opt_callgrind = 0;\n  $main::opt_list = \"\";\n  $main::opt_disasm = \"\";\n  $main::opt_symbols = 0;\n  $main::opt_gv = 0;\n  $main::opt_evince = 0;\n  $main::opt_web = 0;\n  $main::opt_dot = 0;\n  $main::opt_ps = 0;\n  $main::opt_pdf = 0;\n  $main::opt_gif = 0;\n  $main::opt_svg = 0;\n  $main::opt_raw = 0;\n\n  $main::opt_nodecount = 80;\n  $main::opt_nodefraction = 0.005;\n  $main::opt_edgefraction = 0.001;\n  $main::opt_maxdegree = 8;\n  $main::opt_focus = '';\n  $main::opt_ignore = '';\n  $main::opt_scale = 0;\n  $main::opt_heapcheck = 0;\n  $main::opt_seconds = 30;\n  $main::opt_lib = \"\";\n\n  $main::opt_inuse_space   = 0;\n  $main::opt_inuse_objects = 0;\n  $main::opt_alloc_space   = 0;\n  $main::opt_alloc_objects = 0;\n  $main::opt_show_bytes    = 0;\n  $main::opt_drop_negative = 0;\n  $main::opt_interactive   = 0;\n\n  $main::opt_total_delay = 0;\n  $main::opt_contentions = 0;\n  $main::opt_mean_delay = 0;\n\n  $main::opt_tools   = \"\";\n  $main::opt_debug   = 0;\n  $main::opt_test    = 0;\n\n  # These are undocumented flags used only by unittests.\n  $main::opt_test_stride = 0;\n\n  # Are we using $SYMBOL_PAGE?\n  $main::use_symbol_page = 0;\n\n  # Files returned by TempName.\n  %main::tempnames = ();\n\n  # Type of profile we are dealing with\n  # Supported types:\n  #     cpu\n  #     heap\n  #     growth\n  #     contention\n  $main::profile_type = '';     # Empty type means \"unknown\"\n\n  GetOptions(\"help!\"          => \\$main::opt_help,\n             \"version!\"       => \\$main::opt_version,\n             \"cum!\"           => \\$main::opt_cum,\n             \"base=s\"         => \\$main::opt_base,\n             \"seconds=i\"      => \\$main::opt_seconds,\n             \"add_lib=s\"      => \\$main::opt_lib,\n             \"lib_prefix=s\"   => \\$main::opt_lib_prefix,\n             \"functions!\"     => \\$main::opt_functions,\n             \"lines!\"         => \\$main::opt_lines,\n             \"addresses!\"     => \\$main::opt_addresses,\n             \"files!\"         => \\$main::opt_files,\n             \"text!\"          => \\$main::opt_text,\n             \"callgrind!\"     => \\$main::opt_callgrind,\n             \"list=s\"         => \\$main::opt_list,\n             \"disasm=s\"       => \\$main::opt_disasm,\n             \"symbols!\"       => \\$main::opt_symbols,\n             \"gv!\"            => \\$main::opt_gv,\n             \"evince!\"        => \\$main::opt_evince,\n             \"web!\"           => \\$main::opt_web,\n             \"dot!\"           => \\$main::opt_dot,\n             \"ps!\"            => \\$main::opt_ps,\n             \"pdf!\"           => \\$main::opt_pdf,\n             \"svg!\"           => \\$main::opt_svg,\n             \"gif!\"           => \\$main::opt_gif,\n             \"raw!\"           => \\$main::opt_raw,\n             \"interactive!\"   => \\$main::opt_interactive,\n             \"nodecount=i\"    => \\$main::opt_nodecount,\n             \"nodefraction=f\" => \\$main::opt_nodefraction,\n             \"edgefraction=f\" => \\$main::opt_edgefraction,\n             \"maxdegree=i\"    => \\$main::opt_maxdegree,\n             \"focus=s\"        => \\$main::opt_focus,\n             \"ignore=s\"       => \\$main::opt_ignore,\n             \"scale=i\"        => \\$main::opt_scale,\n             \"heapcheck\"      => \\$main::opt_heapcheck,\n             \"inuse_space!\"   => \\$main::opt_inuse_space,\n             \"inuse_objects!\" => \\$main::opt_inuse_objects,\n             \"alloc_space!\"   => \\$main::opt_alloc_space,\n             \"alloc_objects!\" => \\$main::opt_alloc_objects,\n             \"show_bytes!\"    => \\$main::opt_show_bytes,\n             \"drop_negative!\" => \\$main::opt_drop_negative,\n             \"total_delay!\"   => \\$main::opt_total_delay,\n             \"contentions!\"   => \\$main::opt_contentions,\n             \"mean_delay!\"    => \\$main::opt_mean_delay,\n             \"tools=s\"        => \\$main::opt_tools,\n             \"test!\"          => \\$main::opt_test,\n             \"debug!\"         => \\$main::opt_debug,\n             # Undocumented flags used only by unittests:\n             \"test_stride=i\"  => \\$main::opt_test_stride,\n      ) || usage(\"Invalid option(s)\");\n\n  # Deal with the standard --help and --version\n  if ($main::opt_help) {\n    print usage_string();\n    exit(0);\n  }\n\n  if ($main::opt_version) {\n    print version_string();\n    exit(0);\n  }\n\n  # Disassembly/listing/symbols mode requires address-level info\n  if ($main::opt_disasm || $main::opt_list || $main::opt_symbols) {\n    $main::opt_functions = 0;\n    $main::opt_lines = 0;\n    $main::opt_addresses = 1;\n    $main::opt_files = 0;\n  }\n\n  # Check heap-profiling flags\n  if ($main::opt_inuse_space +\n      $main::opt_inuse_objects +\n      $main::opt_alloc_space +\n      $main::opt_alloc_objects > 1) {\n    usage(\"Specify at most on of --inuse/--alloc options\");\n  }\n\n  # Check output granularities\n  my $grains =\n      $main::opt_functions +\n      $main::opt_lines +\n      $main::opt_addresses +\n      $main::opt_files +\n      0;\n  if ($grains > 1) {\n    usage(\"Only specify one output granularity option\");\n  }\n  if ($grains == 0) {\n    $main::opt_functions = 1;\n  }\n\n  # Check output modes\n  my $modes =\n      $main::opt_text +\n      $main::opt_callgrind +\n      ($main::opt_list eq '' ? 0 : 1) +\n      ($main::opt_disasm eq '' ? 0 : 1) +\n      ($main::opt_symbols == 0 ? 0 : 1) +\n      $main::opt_gv +\n      $main::opt_evince +\n      $main::opt_web +\n      $main::opt_dot +\n      $main::opt_ps +\n      $main::opt_pdf +\n      $main::opt_svg +\n      $main::opt_gif +\n      $main::opt_raw +\n      $main::opt_interactive +\n      0;\n  if ($modes > 1) {\n    usage(\"Only specify one output mode\");\n  }\n  if ($modes == 0) {\n    if (-t STDOUT) {  # If STDOUT is a tty, activate interactive mode\n      $main::opt_interactive = 1;\n    } else {\n      $main::opt_text = 1;\n    }\n  }\n\n  if ($main::opt_test) {\n    RunUnitTests();\n    # Should not return\n    exit(1);\n  }\n\n  # Binary name and profile arguments list\n  $main::prog = \"\";\n  @main::pfile_args = ();\n\n  # Remote profiling without a binary (using $SYMBOL_PAGE instead)\n  if (@ARGV > 0) {\n    if (IsProfileURL($ARGV[0])) {\n      $main::use_symbol_page = 1;\n    } elsif (IsSymbolizedProfileFile($ARGV[0])) {\n      $main::use_symbolized_profile = 1;\n      $main::prog = $UNKNOWN_BINARY;  # will be set later from the profile file\n    }\n  }\n\n  if ($main::use_symbol_page || $main::use_symbolized_profile) {\n    # We don't need a binary!\n    my %disabled = ('--lines' => $main::opt_lines,\n                    '--disasm' => $main::opt_disasm);\n    for my $option (keys %disabled) {\n      usage(\"$option cannot be used without a binary\") if $disabled{$option};\n    }\n    # Set $main::prog later...\n    scalar(@ARGV) || usage(\"Did not specify profile file\");\n  } elsif ($main::opt_symbols) {\n    # --symbols needs a binary-name (to run nm on, etc) but not profiles\n    $main::prog = shift(@ARGV) || usage(\"Did not specify program\");\n  } else {\n    $main::prog = shift(@ARGV) || usage(\"Did not specify program\");\n    scalar(@ARGV) || usage(\"Did not specify profile file\");\n  }\n\n  # Parse profile file/location arguments\n  foreach my $farg (@ARGV) {\n    if ($farg =~ m/(.*)\\@([0-9]+)(|\\/.*)$/ ) {\n      my $machine = $1;\n      my $num_machines = $2;\n      my $path = $3;\n      for (my $i = 0; $i < $num_machines; $i++) {\n        unshift(@main::pfile_args, \"$i.$machine$path\");\n      }\n    } else {\n      unshift(@main::pfile_args, $farg);\n    }\n  }\n\n  if ($main::use_symbol_page) {\n    unless (IsProfileURL($main::pfile_args[0])) {\n      error(\"The first profile should be a remote form to use $SYMBOL_PAGE\\n\");\n    }\n    CheckSymbolPage();\n    $main::prog = FetchProgramName();\n  } elsif (!$main::use_symbolized_profile) {  # may not need objtools!\n    ConfigureObjTools($main::prog)\n  }\n\n  # Break the opt_lib_prefix into the prefix_list array\n  @prefix_list = split (',', $main::opt_lib_prefix);\n\n  # Remove trailing / from the prefixes, in the list to prevent\n  # searching things like /my/path//lib/mylib.so\n  foreach (@prefix_list) {\n    s|/+$||;\n  }\n}\n\nsub Main() {\n  Init();\n  $main::collected_profile = undef;\n  @main::profile_files = ();\n  $main::op_time = time();\n\n  # Printing symbols is special and requires a lot less info that most.\n  if ($main::opt_symbols) {\n    PrintSymbols(*STDIN);   # Get /proc/maps and symbols output from stdin\n    return;\n  }\n\n  # Fetch all profile data\n  FetchDynamicProfiles();\n\n  # this will hold symbols that we read from the profile files\n  my $symbol_map = {};\n\n  # Read one profile, pick the last item on the list\n  my $data = ReadProfile($main::prog, pop(@main::profile_files));\n  my $profile = $data->{profile};\n  my $pcs = $data->{pcs};\n  my $libs = $data->{libs};   # Info about main program and shared libraries\n  $symbol_map = MergeSymbols($symbol_map, $data->{symbols});\n\n  # Add additional profiles, if available.\n  if (scalar(@main::profile_files) > 0) {\n    foreach my $pname (@main::profile_files) {\n      my $data2 = ReadProfile($main::prog, $pname);\n      $profile = AddProfile($profile, $data2->{profile});\n      $pcs = AddPcs($pcs, $data2->{pcs});\n      $symbol_map = MergeSymbols($symbol_map, $data2->{symbols});\n    }\n  }\n\n  # Subtract base from profile, if specified\n  if ($main::opt_base ne '') {\n    my $base = ReadProfile($main::prog, $main::opt_base);\n    $profile = SubtractProfile($profile, $base->{profile});\n    $pcs = AddPcs($pcs, $base->{pcs});\n    $symbol_map = MergeSymbols($symbol_map, $base->{symbols});\n  }\n\n  # Get total data in profile\n  my $total = TotalProfile($profile);\n\n  # Collect symbols\n  my $symbols;\n  if ($main::use_symbolized_profile) {\n    $symbols = FetchSymbols($pcs, $symbol_map);\n  } elsif ($main::use_symbol_page) {\n    $symbols = FetchSymbols($pcs);\n  } else {\n    # TODO(csilvers): $libs uses the /proc/self/maps data from profile1,\n    # which may differ from the data from subsequent profiles, especially\n    # if they were run on different machines.  Use appropriate libs for\n    # each pc somehow.\n    $symbols = ExtractSymbols($libs, $pcs);\n  }\n\n  # Remove uniniteresting stack items\n  $profile = RemoveUninterestingFrames($symbols, $profile);\n\n  # Focus?\n  if ($main::opt_focus ne '') {\n    $profile = FocusProfile($symbols, $profile, $main::opt_focus);\n  }\n\n  # Ignore?\n  if ($main::opt_ignore ne '') {\n    $profile = IgnoreProfile($symbols, $profile, $main::opt_ignore);\n  }\n\n  my $calls = ExtractCalls($symbols, $profile);\n\n  # Reduce profiles to required output granularity, and also clean\n  # each stack trace so a given entry exists at most once.\n  my $reduced = ReduceProfile($symbols, $profile);\n\n  # Get derived profiles\n  my $flat = FlatProfile($reduced);\n  my $cumulative = CumulativeProfile($reduced);\n\n  # Print\n  if (!$main::opt_interactive) {\n    if ($main::opt_disasm) {\n      PrintDisassembly($libs, $flat, $cumulative, $main::opt_disasm);\n    } elsif ($main::opt_list) {\n      PrintListing($total, $libs, $flat, $cumulative, $main::opt_list, 0);\n    } elsif ($main::opt_text) {\n      # Make sure the output is empty when have nothing to report\n      # (only matters when --heapcheck is given but we must be\n      # compatible with old branches that did not pass --heapcheck always):\n      if ($total != 0) {\n        printf(\"Total: %s %s\\n\", Unparse($total), Units());\n      }\n      PrintText($symbols, $flat, $cumulative, -1);\n    } elsif ($main::opt_raw) {\n      PrintSymbolizedProfile($symbols, $profile, $main::prog);\n    } elsif ($main::opt_callgrind) {\n      PrintCallgrind($calls);\n    } else {\n      if (PrintDot($main::prog, $symbols, $profile, $flat, $cumulative, $total)) {\n        if ($main::opt_gv) {\n          RunGV(TempName($main::next_tmpfile, \"ps\"), \"\");\n        } elsif ($main::opt_evince) {\n          RunEvince(TempName($main::next_tmpfile, \"pdf\"), \"\");\n        } elsif ($main::opt_web) {\n          my $tmp = TempName($main::next_tmpfile, \"svg\");\n          RunWeb($tmp);\n          # The command we run might hand the file name off\n          # to an already running browser instance and then exit.\n          # Normally, we'd remove $tmp on exit (right now),\n          # but fork a child to remove $tmp a little later, so that the\n          # browser has time to load it first.\n          delete $main::tempnames{$tmp};\n          if (fork() == 0) {\n            sleep 5;\n            unlink($tmp);\n            exit(0);\n          }\n        }\n      } else {\n        cleanup();\n        exit(1);\n      }\n    }\n  } else {\n    InteractiveMode($profile, $symbols, $libs, $total);\n  }\n\n  cleanup();\n  exit(0);\n}\n\n##### Entry Point #####\n\nMain();\n\n# Temporary code to detect if we're running on a Goobuntu system.\n# These systems don't have the right stuff installed for the special\n# Readline libraries to work, so as a temporary workaround, we default\n# to using the normal stdio code, rather than the fancier readline-based\n# code\nsub ReadlineMightFail {\n  if (-e '/lib/libtermcap.so.2') {\n    return 0;  # libtermcap exists, so readline should be okay\n  } else {\n    return 1;\n  }\n}\n\nsub RunGV {\n  my $fname = shift;\n  my $bg = shift;       # \"\" or \" &\" if we should run in background\n  if (!system(ShellEscape(@GV, \"--version\") . \" >$dev_null 2>&1\")) {\n    # Options using double dash are supported by this gv version.\n    # Also, turn on noantialias to better handle bug in gv for\n    # postscript files with large dimensions.\n    # TODO: Maybe we should not pass the --noantialias flag\n    # if the gv version is known to work properly without the flag.\n    system(ShellEscape(@GV, \"--scale=$main::opt_scale\", \"--noantialias\", $fname)\n           . $bg);\n  } else {\n    # Old gv version - only supports options that use single dash.\n    print STDERR ShellEscape(@GV, \"-scale\", $main::opt_scale) . \"\\n\";\n    system(ShellEscape(@GV, \"-scale\", \"$main::opt_scale\", $fname) . $bg);\n  }\n}\n\nsub RunEvince {\n  my $fname = shift;\n  my $bg = shift;       # \"\" or \" &\" if we should run in background\n  system(ShellEscape(@EVINCE, $fname) . $bg);\n}\n\nsub RunWeb {\n  my $fname = shift;\n  print STDERR \"Loading web page file:///$fname\\n\";\n\n  if (`uname` =~ /Darwin/) {\n    # OS X: open will use standard preference for SVG files.\n    system(\"/usr/bin/open\", $fname);\n    return;\n  }\n\n  # Some kind of Unix; try generic symlinks, then specific browsers.\n  # (Stop once we find one.)\n  # Works best if the browser is already running.\n  my @alt = (\n    \"/etc/alternatives/gnome-www-browser\",\n    \"/etc/alternatives/x-www-browser\",\n    \"google-chrome\",\n    \"firefox\",\n  );\n  foreach my $b (@alt) {\n    if (system($b, $fname) == 0) {\n      return;\n    }\n  }\n\n  print STDERR \"Could not load web browser.\\n\";\n}\n\nsub RunKcachegrind {\n  my $fname = shift;\n  my $bg = shift;       # \"\" or \" &\" if we should run in background\n  print STDERR \"Starting '@KCACHEGRIND \" . $fname . $bg . \"'\\n\";\n  system(ShellEscape(@KCACHEGRIND, $fname) . $bg);\n}\n\n\n##### Interactive helper routines #####\n\nsub InteractiveMode {\n  $| = 1;  # Make output unbuffered for interactive mode\n  my ($orig_profile, $symbols, $libs, $total) = @_;\n\n  print STDERR \"Welcome to pprof!  For help, type 'help'.\\n\";\n\n  # Use ReadLine if it's installed and input comes from a console.\n  if ( -t STDIN &&\n       !ReadlineMightFail() &&\n       defined(eval {require Term::ReadLine}) ) {\n    my $term = new Term::ReadLine 'pprof';\n    while ( defined ($_ = $term->readline('(pprof) '))) {\n      $term->addhistory($_) if /\\S/;\n      if (!InteractiveCommand($orig_profile, $symbols, $libs, $total, $_)) {\n        last;    # exit when we get an interactive command to quit\n      }\n    }\n  } else {       # don't have readline\n    while (1) {\n      print STDERR \"(pprof) \";\n      $_ = <STDIN>;\n      last if ! defined $_ ;\n      s/\\r//g;         # turn windows-looking lines into unix-looking lines\n\n      # Save some flags that might be reset by InteractiveCommand()\n      my $save_opt_lines = $main::opt_lines;\n\n      if (!InteractiveCommand($orig_profile, $symbols, $libs, $total, $_)) {\n        last;    # exit when we get an interactive command to quit\n      }\n\n      # Restore flags\n      $main::opt_lines = $save_opt_lines;\n    }\n  }\n}\n\n# Takes two args: orig profile, and command to run.\n# Returns 1 if we should keep going, or 0 if we were asked to quit\nsub InteractiveCommand {\n  my($orig_profile, $symbols, $libs, $total, $command) = @_;\n  $_ = $command;                # just to make future m//'s easier\n  if (!defined($_)) {\n    print STDERR \"\\n\";\n    return 0;\n  }\n  if (m/^\\s*quit/) {\n    return 0;\n  }\n  if (m/^\\s*help/) {\n    InteractiveHelpMessage();\n    return 1;\n  }\n  # Clear all the mode options -- mode is controlled by \"$command\"\n  $main::opt_text = 0;\n  $main::opt_callgrind = 0;\n  $main::opt_disasm = 0;\n  $main::opt_list = 0;\n  $main::opt_gv = 0;\n  $main::opt_evince = 0;\n  $main::opt_cum = 0;\n\n  if (m/^\\s*(text|top)(\\d*)\\s*(.*)/) {\n    $main::opt_text = 1;\n\n    my $line_limit = ($2 ne \"\") ? int($2) : 10;\n\n    my $routine;\n    my $ignore;\n    ($routine, $ignore) = ParseInteractiveArgs($3);\n\n    my $profile = ProcessProfile($total, $orig_profile, $symbols, \"\", $ignore);\n    my $reduced = ReduceProfile($symbols, $profile);\n\n    # Get derived profiles\n    my $flat = FlatProfile($reduced);\n    my $cumulative = CumulativeProfile($reduced);\n\n    PrintText($symbols, $flat, $cumulative, $line_limit);\n    return 1;\n  }\n  if (m/^\\s*callgrind\\s*([^ \\n]*)/) {\n    $main::opt_callgrind = 1;\n\n    # Get derived profiles\n    my $calls = ExtractCalls($symbols, $orig_profile);\n    my $filename = $1;\n    if ( $1 eq '' ) {\n      $filename = TempName($main::next_tmpfile, \"callgrind\");\n    }\n    PrintCallgrind($calls, $filename);\n    if ( $1 eq '' ) {\n      RunKcachegrind($filename, \" & \");\n      $main::next_tmpfile++;\n    }\n\n    return 1;\n  }\n  if (m/^\\s*(web)?list\\s*(.+)/) {\n    my $html = (defined($1) && ($1 eq \"web\"));\n    $main::opt_list = 1;\n\n    my $routine;\n    my $ignore;\n    ($routine, $ignore) = ParseInteractiveArgs($2);\n\n    my $profile = ProcessProfile($total, $orig_profile, $symbols, \"\", $ignore);\n    my $reduced = ReduceProfile($symbols, $profile);\n\n    # Get derived profiles\n    my $flat = FlatProfile($reduced);\n    my $cumulative = CumulativeProfile($reduced);\n\n    PrintListing($total, $libs, $flat, $cumulative, $routine, $html);\n    return 1;\n  }\n  if (m/^\\s*disasm\\s*(.+)/) {\n    $main::opt_disasm = 1;\n\n    my $routine;\n    my $ignore;\n    ($routine, $ignore) = ParseInteractiveArgs($1);\n\n    # Process current profile to account for various settings\n    my $profile = ProcessProfile($total, $orig_profile, $symbols, \"\", $ignore);\n    my $reduced = ReduceProfile($symbols, $profile);\n\n    # Get derived profiles\n    my $flat = FlatProfile($reduced);\n    my $cumulative = CumulativeProfile($reduced);\n\n    PrintDisassembly($libs, $flat, $cumulative, $routine);\n    return 1;\n  }\n  if (m/^\\s*(gv|web|evince)\\s*(.*)/) {\n    $main::opt_gv = 0;\n    $main::opt_evince = 0;\n    $main::opt_web = 0;\n    if ($1 eq \"gv\") {\n      $main::opt_gv = 1;\n    } elsif ($1 eq \"evince\") {\n      $main::opt_evince = 1;\n    } elsif ($1 eq \"web\") {\n      $main::opt_web = 1;\n    }\n\n    my $focus;\n    my $ignore;\n    ($focus, $ignore) = ParseInteractiveArgs($2);\n\n    # Process current profile to account for various settings\n    my $profile = ProcessProfile($total, $orig_profile, $symbols,\n                                 $focus, $ignore);\n    my $reduced = ReduceProfile($symbols, $profile);\n\n    # Get derived profiles\n    my $flat = FlatProfile($reduced);\n    my $cumulative = CumulativeProfile($reduced);\n\n    if (PrintDot($main::prog, $symbols, $profile, $flat, $cumulative, $total)) {\n      if ($main::opt_gv) {\n        RunGV(TempName($main::next_tmpfile, \"ps\"), \" &\");\n      } elsif ($main::opt_evince) {\n        RunEvince(TempName($main::next_tmpfile, \"pdf\"), \" &\");\n      } elsif ($main::opt_web) {\n        RunWeb(TempName($main::next_tmpfile, \"svg\"));\n      }\n      $main::next_tmpfile++;\n    }\n    return 1;\n  }\n  if (m/^\\s*$/) {\n    return 1;\n  }\n  print STDERR \"Unknown command: try 'help'.\\n\";\n  return 1;\n}\n\n\nsub ProcessProfile {\n  my $total_count = shift;\n  my $orig_profile = shift;\n  my $symbols = shift;\n  my $focus = shift;\n  my $ignore = shift;\n\n  # Process current profile to account for various settings\n  my $profile = $orig_profile;\n  printf(\"Total: %s %s\\n\", Unparse($total_count), Units());\n  if ($focus ne '') {\n    $profile = FocusProfile($symbols, $profile, $focus);\n    my $focus_count = TotalProfile($profile);\n    printf(\"After focusing on '%s': %s %s of %s (%0.1f%%)\\n\",\n           $focus,\n           Unparse($focus_count), Units(),\n           Unparse($total_count), ($focus_count*100.0) / $total_count);\n  }\n  if ($ignore ne '') {\n    $profile = IgnoreProfile($symbols, $profile, $ignore);\n    my $ignore_count = TotalProfile($profile);\n    printf(\"After ignoring '%s': %s %s of %s (%0.1f%%)\\n\",\n           $ignore,\n           Unparse($ignore_count), Units(),\n           Unparse($total_count),\n           ($ignore_count*100.0) / $total_count);\n  }\n\n  return $profile;\n}\n\nsub InteractiveHelpMessage {\n  print STDERR <<ENDOFHELP;\nInteractive pprof mode\n\nCommands:\n  gv\n  gv [focus] [-ignore1] [-ignore2]\n      Show graphical hierarchical display of current profile.  Without\n      any arguments, shows all samples in the profile.  With the optional\n      \"focus\" argument, restricts the samples shown to just those where\n      the \"focus\" regular expression matches a routine name on the stack\n      trace.\n\n  web\n  web [focus] [-ignore1] [-ignore2]\n      Like GV, but displays profile in your web browser instead of using\n      Ghostview. Works best if your web browser is already running.\n      To change the browser that gets used:\n      On Linux, set the /etc/alternatives/gnome-www-browser symlink.\n      On OS X, change the Finder association for SVG files.\n\n  list [routine_regexp] [-ignore1] [-ignore2]\n      Show source listing of routines whose names match \"routine_regexp\"\n\n  weblist [routine_regexp] [-ignore1] [-ignore2]\n     Displays a source listing of routines whose names match \"routine_regexp\"\n     in a web browser.  You can click on source lines to view the\n     corresponding disassembly.\n\n  top [--cum] [-ignore1] [-ignore2]\n  top20 [--cum] [-ignore1] [-ignore2]\n  top37 [--cum] [-ignore1] [-ignore2]\n      Show top lines ordered by flat profile count, or cumulative count\n      if --cum is specified.  If a number is present after 'top', the\n      top K routines will be shown (defaults to showing the top 10)\n\n  disasm [routine_regexp] [-ignore1] [-ignore2]\n      Show disassembly of routines whose names match \"routine_regexp\",\n      annotated with sample counts.\n\n  callgrind\n  callgrind [filename]\n      Generates callgrind file. If no filename is given, kcachegrind is called.\n\n  help - This listing\n  quit or ^D - End pprof\n\nFor commands that accept optional -ignore tags, samples where any routine in\nthe stack trace matches the regular expression in any of the -ignore\nparameters will be ignored.\n\nFurther pprof details are available at this location (or one similar):\n\n /usr/doc/gperftools-$PPROF_VERSION/cpu_profiler.html\n /usr/doc/gperftools-$PPROF_VERSION/heap_profiler.html\n\nENDOFHELP\n}\nsub ParseInteractiveArgs {\n  my $args = shift;\n  my $focus = \"\";\n  my $ignore = \"\";\n  my @x = split(/ +/, $args);\n  foreach $a (@x) {\n    if ($a =~ m/^(--|-)lines$/) {\n      $main::opt_lines = 1;\n    } elsif ($a =~ m/^(--|-)cum$/) {\n      $main::opt_cum = 1;\n    } elsif ($a =~ m/^-(.*)/) {\n      $ignore .= (($ignore ne \"\") ? \"|\" : \"\" ) . $1;\n    } else {\n      $focus .= (($focus ne \"\") ? \"|\" : \"\" ) . $a;\n    }\n  }\n  if ($ignore ne \"\") {\n    print STDERR \"Ignoring samples in call stacks that match '$ignore'\\n\";\n  }\n  return ($focus, $ignore);\n}\n\n##### Output code #####\n\nsub TempName {\n  my $fnum = shift;\n  my $ext = shift;\n  my $file = \"$main::tmpfile_ps.$fnum.$ext\";\n  $main::tempnames{$file} = 1;\n  return $file;\n}\n\n# Print profile data in packed binary format (64-bit) to standard out\nsub PrintProfileData {\n  my $profile = shift;\n\n  # print header (64-bit style)\n  # (zero) (header-size) (version) (sample-period) (zero)\n  print pack('L*', 0, 0, 3, 0, 0, 0, 1, 0, 0, 0);\n\n  foreach my $k (keys(%{$profile})) {\n    my $count = $profile->{$k};\n    my @addrs = split(/\\n/, $k);\n    if ($#addrs >= 0) {\n      my $depth = $#addrs + 1;\n      # int(foo / 2**32) is the only reliable way to get rid of bottom\n      # 32 bits on both 32- and 64-bit systems.\n      print pack('L*', $count & 0xFFFFFFFF, int($count / 2**32));\n      print pack('L*', $depth & 0xFFFFFFFF, int($depth / 2**32));\n\n      foreach my $full_addr (@addrs) {\n        my $addr = $full_addr;\n        $addr =~ s/0x0*//;  # strip off leading 0x, zeroes\n        if (length($addr) > 16) {\n          print STDERR \"Invalid address in profile: $full_addr\\n\";\n          next;\n        }\n        my $low_addr = substr($addr, -8);       # get last 8 hex chars\n        my $high_addr = substr($addr, -16, 8);  # get up to 8 more hex chars\n        print pack('L*', hex('0x' . $low_addr), hex('0x' . $high_addr));\n      }\n    }\n  }\n}\n\n# Print symbols and profile data\nsub PrintSymbolizedProfile {\n  my $symbols = shift;\n  my $profile = shift;\n  my $prog = shift;\n\n  $SYMBOL_PAGE =~ m,[^/]+$,;    # matches everything after the last slash\n  my $symbol_marker = $&;\n\n  print '--- ', $symbol_marker, \"\\n\";\n  if (defined($prog)) {\n    print 'binary=', $prog, \"\\n\";\n  }\n  while (my ($pc, $name) = each(%{$symbols})) {\n    my $sep = ' ';\n    print '0x', $pc;\n    # We have a list of function names, which include the inlined\n    # calls.  They are separated (and terminated) by --, which is\n    # illegal in function names.\n    for (my $j = 2; $j <= $#{$name}; $j += 3) {\n      print $sep, $name->[$j];\n      $sep = '--';\n    }\n    print \"\\n\";\n  }\n  print '---', \"\\n\";\n\n  $PROFILE_PAGE =~ m,[^/]+$,;    # matches everything after the last slash\n  my $profile_marker = $&;\n  print '--- ', $profile_marker, \"\\n\";\n  if (defined($main::collected_profile)) {\n    # if used with remote fetch, simply dump the collected profile to output.\n    open(SRC, \"<$main::collected_profile\");\n    while (<SRC>) {\n      print $_;\n    }\n    close(SRC);\n  } else {\n    # dump a cpu-format profile to standard out\n    PrintProfileData($profile);\n  }\n}\n\n# Print text output\nsub PrintText {\n  my $symbols = shift;\n  my $flat = shift;\n  my $cumulative = shift;\n  my $line_limit = shift;\n\n  my $total = TotalProfile($flat);\n\n  # Which profile to sort by?\n  my $s = $main::opt_cum ? $cumulative : $flat;\n\n  my $running_sum = 0;\n  my $lines = 0;\n  foreach my $k (sort { GetEntry($s, $b) <=> GetEntry($s, $a) || $a cmp $b }\n                 keys(%{$cumulative})) {\n    my $f = GetEntry($flat, $k);\n    my $c = GetEntry($cumulative, $k);\n    $running_sum += $f;\n\n    my $sym = $k;\n    if (exists($symbols->{$k})) {\n      $sym = $symbols->{$k}->[0] . \" \" . $symbols->{$k}->[1];\n      if ($main::opt_addresses) {\n        $sym = $k . \" \" . $sym;\n      }\n    }\n\n    if ($f != 0 || $c != 0) {\n      printf(\"%8s %6s %6s %8s %6s %s\\n\",\n             Unparse($f),\n             Percent($f, $total),\n             Percent($running_sum, $total),\n             Unparse($c),\n             Percent($c, $total),\n             $sym);\n    }\n    $lines++;\n    last if ($line_limit >= 0 && $lines >= $line_limit);\n  }\n}\n\n# Callgrind format has a compression for repeated function and file\n# names.  You show the name the first time, and just use its number\n# subsequently.  This can cut down the file to about a third or a\n# quarter of its uncompressed size.  $key and $val are the key/value\n# pair that would normally be printed by callgrind; $map is a map from\n# value to number.\nsub CompressedCGName {\n  my($key, $val, $map) = @_;\n  my $idx = $map->{$val};\n  # For very short keys, providing an index hurts rather than helps.\n  if (length($val) <= 3) {\n    return \"$key=$val\\n\";\n  } elsif (defined($idx)) {\n    return \"$key=($idx)\\n\";\n  } else {\n    # scalar(keys $map) gives the number of items in the map.\n    $idx = scalar(keys(%{$map})) + 1;\n    $map->{$val} = $idx;\n    return \"$key=($idx) $val\\n\";\n  }\n}\n\n# Print the call graph in a way that's suiteable for callgrind.\nsub PrintCallgrind {\n  my $calls = shift;\n  my $filename;\n  my %filename_to_index_map;\n  my %fnname_to_index_map;\n\n  if ($main::opt_interactive) {\n    $filename = shift;\n    print STDERR \"Writing callgrind file to '$filename'.\\n\"\n  } else {\n    $filename = \"&STDOUT\";\n  }\n  open(CG, \">$filename\");\n  printf CG (\"events: Hits\\n\\n\");\n  foreach my $call ( map { $_->[0] }\n                     sort { $a->[1] cmp $b ->[1] ||\n                            $a->[2] <=> $b->[2] }\n                     map { /([^:]+):(\\d+):([^ ]+)( -> ([^:]+):(\\d+):(.+))?/;\n                           [$_, $1, $2] }\n                     keys %$calls ) {\n    my $count = int($calls->{$call});\n    $call =~ /([^:]+):(\\d+):([^ ]+)( -> ([^:]+):(\\d+):(.+))?/;\n    my ( $caller_file, $caller_line, $caller_function,\n         $callee_file, $callee_line, $callee_function ) =\n       ( $1, $2, $3, $5, $6, $7 );\n\n    # TODO(csilvers): for better compression, collect all the\n    # caller/callee_files and functions first, before printing\n    # anything, and only compress those referenced more than once.\n    printf CG CompressedCGName(\"fl\", $caller_file, \\%filename_to_index_map);\n    printf CG CompressedCGName(\"fn\", $caller_function, \\%fnname_to_index_map);\n    if (defined $6) {\n      printf CG CompressedCGName(\"cfl\", $callee_file, \\%filename_to_index_map);\n      printf CG CompressedCGName(\"cfn\", $callee_function, \\%fnname_to_index_map);\n      printf CG (\"calls=$count $callee_line\\n\");\n    }\n    printf CG (\"$caller_line $count\\n\\n\");\n  }\n}\n\n# Print disassembly for all all routines that match $main::opt_disasm\nsub PrintDisassembly {\n  my $libs = shift;\n  my $flat = shift;\n  my $cumulative = shift;\n  my $disasm_opts = shift;\n\n  my $total = TotalProfile($flat);\n\n  foreach my $lib (@{$libs}) {\n    my $symbol_table = GetProcedureBoundaries($lib->[0], $disasm_opts);\n    my $offset = AddressSub($lib->[1], $lib->[3]);\n    foreach my $routine (sort ByName keys(%{$symbol_table})) {\n      my $start_addr = $symbol_table->{$routine}->[0];\n      my $end_addr = $symbol_table->{$routine}->[1];\n      # See if there are any samples in this routine\n      my $length = hex(AddressSub($end_addr, $start_addr));\n      my $addr = AddressAdd($start_addr, $offset);\n      for (my $i = 0; $i < $length; $i++) {\n        if (defined($cumulative->{$addr})) {\n          PrintDisassembledFunction($lib->[0], $offset,\n                                    $routine, $flat, $cumulative,\n                                    $start_addr, $end_addr, $total);\n          last;\n        }\n        $addr = AddressInc($addr);\n      }\n    }\n  }\n}\n\n# Return reference to array of tuples of the form:\n#       [start_address, filename, linenumber, instruction, limit_address]\n# E.g.,\n#       [\"0x806c43d\", \"/foo/bar.cc\", 131, \"ret\", \"0x806c440\"]\nsub Disassemble {\n  my $prog = shift;\n  my $offset = shift;\n  my $start_addr = shift;\n  my $end_addr = shift;\n\n  my $objdump = $obj_tool_map{\"objdump\"};\n  my $cmd = ShellEscape($objdump, \"-C\", \"-d\", \"-l\", \"--no-show-raw-insn\",\n                        \"--start-address=0x$start_addr\",\n                        \"--stop-address=0x$end_addr\", $prog);\n  open(OBJDUMP, \"$cmd |\") || error(\"$cmd: $!\\n\");\n  my @result = ();\n  my $filename = \"\";\n  my $linenumber = -1;\n  my $last = [\"\", \"\", \"\", \"\"];\n  while (<OBJDUMP>) {\n    s/\\r//g;         # turn windows-looking lines into unix-looking lines\n    chop;\n    if (m|\\s*([^:\\s]+):(\\d+)\\s*$|) {\n      # Location line of the form:\n      #   <filename>:<linenumber>\n      $filename = $1;\n      $linenumber = $2;\n    } elsif (m/^ +([0-9a-f]+):\\s*(.*)/) {\n      # Disassembly line -- zero-extend address to full length\n      my $addr = HexExtend($1);\n      my $k = AddressAdd($addr, $offset);\n      $last->[4] = $k;   # Store ending address for previous instruction\n      $last = [$k, $filename, $linenumber, $2, $end_addr];\n      push(@result, $last);\n    }\n  }\n  close(OBJDUMP);\n  return @result;\n}\n\n# The input file should contain lines of the form /proc/maps-like\n# output (same format as expected from the profiles) or that looks\n# like hex addresses (like \"0xDEADBEEF\").  We will parse all\n# /proc/maps output, and for all the hex addresses, we will output\n# \"short\" symbol names, one per line, in the same order as the input.\nsub PrintSymbols {\n  my $maps_and_symbols_file = shift;\n\n  # ParseLibraries expects pcs to be in a set.  Fine by us...\n  my @pclist = ();   # pcs in sorted order\n  my $pcs = {};\n  my $map = \"\";\n  foreach my $line (<$maps_and_symbols_file>) {\n    $line =~ s/\\r//g;    # turn windows-looking lines into unix-looking lines\n    if ($line =~ /\\b(0x[0-9a-f]+)\\b/i) {\n      push(@pclist, HexExtend($1));\n      $pcs->{$pclist[-1]} = 1;\n    } else {\n      $map .= $line;\n    }\n  }\n\n  my $libs = ParseLibraries($main::prog, $map, $pcs);\n  my $symbols = ExtractSymbols($libs, $pcs);\n\n  foreach my $pc (@pclist) {\n    # ->[0] is the shortname, ->[2] is the full name\n    print(($symbols->{$pc}->[0] || \"??\") . \"\\n\");\n  }\n}\n\n\n# For sorting functions by name\nsub ByName {\n  return ShortFunctionName($a) cmp ShortFunctionName($b);\n}\n\n# Print source-listing for all all routines that match $list_opts\nsub PrintListing {\n  my $total = shift;\n  my $libs = shift;\n  my $flat = shift;\n  my $cumulative = shift;\n  my $list_opts = shift;\n  my $html = shift;\n\n  my $output = \\*STDOUT;\n  my $fname = \"\";\n\n  if ($html) {\n    # Arrange to write the output to a temporary file\n    $fname = TempName($main::next_tmpfile, \"html\");\n    $main::next_tmpfile++;\n    if (!open(TEMP, \">$fname\")) {\n      print STDERR \"$fname: $!\\n\";\n      return;\n    }\n    $output = \\*TEMP;\n    print $output HtmlListingHeader();\n    printf $output (\"<div class=\\\"legend\\\">%s<br>Total: %s %s</div>\\n\",\n                    $main::prog, Unparse($total), Units());\n  }\n\n  my $listed = 0;\n  foreach my $lib (@{$libs}) {\n    my $symbol_table = GetProcedureBoundaries($lib->[0], $list_opts);\n    my $offset = AddressSub($lib->[1], $lib->[3]);\n    foreach my $routine (sort ByName keys(%{$symbol_table})) {\n      # Print if there are any samples in this routine\n      my $start_addr = $symbol_table->{$routine}->[0];\n      my $end_addr = $symbol_table->{$routine}->[1];\n      my $length = hex(AddressSub($end_addr, $start_addr));\n      my $addr = AddressAdd($start_addr, $offset);\n      for (my $i = 0; $i < $length; $i++) {\n        if (defined($cumulative->{$addr})) {\n          $listed += PrintSource(\n            $lib->[0], $offset,\n            $routine, $flat, $cumulative,\n            $start_addr, $end_addr,\n            $html,\n            $output);\n          last;\n        }\n        $addr = AddressInc($addr);\n      }\n    }\n  }\n\n  if ($html) {\n    if ($listed > 0) {\n      print $output HtmlListingFooter();\n      close($output);\n      RunWeb($fname);\n    } else {\n      close($output);\n      unlink($fname);\n    }\n  }\n}\n\nsub HtmlListingHeader {\n  return <<'EOF';\n<DOCTYPE html>\n<html>\n<head>\n<title>Pprof listing</title>\n<style type=\"text/css\">\nbody {\n  font-family: sans-serif;\n}\nh1 {\n  font-size: 1.5em;\n  margin-bottom: 4px;\n}\n.legend {\n  font-size: 1.25em;\n}\n.line {\n  color: #aaaaaa;\n}\n.nop {\n  color: #aaaaaa;\n}\n.unimportant {\n  color: #cccccc;\n}\n.disasmloc {\n  color: #000000;\n}\n.deadsrc {\n  cursor: pointer;\n}\n.deadsrc:hover {\n  background-color: #eeeeee;\n}\n.livesrc {\n  color: #0000ff;\n  cursor: pointer;\n}\n.livesrc:hover {\n  background-color: #eeeeee;\n}\n.asm {\n  color: #008800;\n  display: none;\n}\n</style>\n<script type=\"text/javascript\">\nfunction pprof_toggle_asm(e) {\n  var target;\n  if (!e) e = window.event;\n  if (e.target) target = e.target;\n  else if (e.srcElement) target = e.srcElement;\n\n  if (target) {\n    var asm = target.nextSibling;\n    if (asm && asm.className == \"asm\") {\n      asm.style.display = (asm.style.display == \"block\" ? \"\" : \"block\");\n      e.preventDefault();\n      return false;\n    }\n  }\n}\n</script>\n</head>\n<body>\nEOF\n}\n\nsub HtmlListingFooter {\n  return <<'EOF';\n</body>\n</html>\nEOF\n}\n\nsub HtmlEscape {\n  my $text = shift;\n  $text =~ s/&/&amp;/g;\n  $text =~ s/</&lt;/g;\n  $text =~ s/>/&gt;/g;\n  return $text;\n}\n\n# Returns the indentation of the line, if it has any non-whitespace\n# characters.  Otherwise, returns -1.\nsub Indentation {\n  my $line = shift;\n  if (m/^(\\s*)\\S/) {\n    return length($1);\n  } else {\n    return -1;\n  }\n}\n\n# If the symbol table contains inlining info, Disassemble() may tag an\n# instruction with a location inside an inlined function.  But for\n# source listings, we prefer to use the location in the function we\n# are listing.  So use MapToSymbols() to fetch full location\n# information for each instruction and then pick out the first\n# location from a location list (location list contains callers before\n# callees in case of inlining).\n#\n# After this routine has run, each entry in $instructions contains:\n#   [0] start address\n#   [1] filename for function we are listing\n#   [2] line number for function we are listing\n#   [3] disassembly\n#   [4] limit address\n#   [5] most specific filename (may be different from [1] due to inlining)\n#   [6] most specific line number (may be different from [2] due to inlining)\nsub GetTopLevelLineNumbers {\n  my ($lib, $offset, $instructions) = @_;\n  my $pcs = [];\n  for (my $i = 0; $i <= $#{$instructions}; $i++) {\n    push(@{$pcs}, $instructions->[$i]->[0]);\n  }\n  my $symbols = {};\n  MapToSymbols($lib, $offset, $pcs, $symbols);\n  for (my $i = 0; $i <= $#{$instructions}; $i++) {\n    my $e = $instructions->[$i];\n    push(@{$e}, $e->[1]);\n    push(@{$e}, $e->[2]);\n    my $addr = $e->[0];\n    my $sym = $symbols->{$addr};\n    if (defined($sym)) {\n      if ($#{$sym} >= 2 && $sym->[1] =~ m/^(.*):(\\d+)$/) {\n        $e->[1] = $1;  # File name\n        $e->[2] = $2;  # Line number\n      }\n    }\n  }\n}\n\n# Print source-listing for one routine\nsub PrintSource {\n  my $prog = shift;\n  my $offset = shift;\n  my $routine = shift;\n  my $flat = shift;\n  my $cumulative = shift;\n  my $start_addr = shift;\n  my $end_addr = shift;\n  my $html = shift;\n  my $output = shift;\n\n  # Disassemble all instructions (just to get line numbers)\n  my @instructions = Disassemble($prog, $offset, $start_addr, $end_addr);\n  GetTopLevelLineNumbers($prog, $offset, \\@instructions);\n\n  # Hack 1: assume that the first source file encountered in the\n  # disassembly contains the routine\n  my $filename = undef;\n  for (my $i = 0; $i <= $#instructions; $i++) {\n    if ($instructions[$i]->[2] >= 0) {\n      $filename = $instructions[$i]->[1];\n      last;\n    }\n  }\n  if (!defined($filename)) {\n    print STDERR \"no filename found in $routine\\n\";\n    return 0;\n  }\n\n  # Hack 2: assume that the largest line number from $filename is the\n  # end of the procedure.  This is typically safe since if P1 contains\n  # an inlined call to P2, then P2 usually occurs earlier in the\n  # source file.  If this does not work, we might have to compute a\n  # density profile or just print all regions we find.\n  my $lastline = 0;\n  for (my $i = 0; $i <= $#instructions; $i++) {\n    my $f = $instructions[$i]->[1];\n    my $l = $instructions[$i]->[2];\n    if (($f eq $filename) && ($l > $lastline)) {\n      $lastline = $l;\n    }\n  }\n\n  # Hack 3: assume the first source location from \"filename\" is the start of\n  # the source code.\n  my $firstline = 1;\n  for (my $i = 0; $i <= $#instructions; $i++) {\n    if ($instructions[$i]->[1] eq $filename) {\n      $firstline = $instructions[$i]->[2];\n      last;\n    }\n  }\n\n  # Hack 4: Extend last line forward until its indentation is less than\n  # the indentation we saw on $firstline\n  my $oldlastline = $lastline;\n  {\n    if (!open(FILE, \"<$filename\")) {\n      print STDERR \"$filename: $!\\n\";\n      return 0;\n    }\n    my $l = 0;\n    my $first_indentation = -1;\n    while (<FILE>) {\n      s/\\r//g;         # turn windows-looking lines into unix-looking lines\n      $l++;\n      my $indent = Indentation($_);\n      if ($l >= $firstline) {\n        if ($first_indentation < 0 && $indent >= 0) {\n          $first_indentation = $indent;\n          last if ($first_indentation == 0);\n        }\n      }\n      if ($l >= $lastline && $indent >= 0) {\n        if ($indent >= $first_indentation) {\n          $lastline = $l+1;\n        } else {\n          last;\n        }\n      }\n    }\n    close(FILE);\n  }\n\n  # Assign all samples to the range $firstline,$lastline,\n  # Hack 4: If an instruction does not occur in the range, its samples\n  # are moved to the next instruction that occurs in the range.\n  my $samples1 = {};        # Map from line number to flat count\n  my $samples2 = {};        # Map from line number to cumulative count\n  my $running1 = 0;         # Unassigned flat counts\n  my $running2 = 0;         # Unassigned cumulative counts\n  my $total1 = 0;           # Total flat counts\n  my $total2 = 0;           # Total cumulative counts\n  my %disasm = ();          # Map from line number to disassembly\n  my $running_disasm = \"\";  # Unassigned disassembly\n  my $skip_marker = \"---\\n\";\n  if ($html) {\n    $skip_marker = \"\";\n    for (my $l = $firstline; $l <= $lastline; $l++) {\n      $disasm{$l} = \"\";\n    }\n  }\n  my $last_dis_filename = '';\n  my $last_dis_linenum = -1;\n  my $last_touched_line = -1;  # To detect gaps in disassembly for a line\n  foreach my $e (@instructions) {\n    # Add up counts for all address that fall inside this instruction\n    my $c1 = 0;\n    my $c2 = 0;\n    for (my $a = $e->[0]; $a lt $e->[4]; $a = AddressInc($a)) {\n      $c1 += GetEntry($flat, $a);\n      $c2 += GetEntry($cumulative, $a);\n    }\n\n    if ($html) {\n      my $dis = sprintf(\"      %6s %6s \\t\\t%8s: %s \",\n                        HtmlPrintNumber($c1),\n                        HtmlPrintNumber($c2),\n                        UnparseAddress($offset, $e->[0]),\n                        CleanDisassembly($e->[3]));\n      \n      # Append the most specific source line associated with this instruction\n      if (length($dis) < 80) { $dis .= (' ' x (80 - length($dis))) };\n      $dis = HtmlEscape($dis);\n      my $f = $e->[5];\n      my $l = $e->[6];\n      if ($f ne $last_dis_filename) {\n        $dis .= sprintf(\"<span class=disasmloc>%s:%d</span>\", \n                        HtmlEscape(CleanFileName($f)), $l);\n      } elsif ($l ne $last_dis_linenum) {\n        # De-emphasize the unchanged file name portion\n        $dis .= sprintf(\"<span class=unimportant>%s</span>\" .\n                        \"<span class=disasmloc>:%d</span>\", \n                        HtmlEscape(CleanFileName($f)), $l);\n      } else {\n        # De-emphasize the entire location\n        $dis .= sprintf(\"<span class=unimportant>%s:%d</span>\", \n                        HtmlEscape(CleanFileName($f)), $l);\n      }\n      $last_dis_filename = $f;\n      $last_dis_linenum = $l;\n      $running_disasm .= $dis;\n      $running_disasm .= \"\\n\";\n    }\n\n    $running1 += $c1;\n    $running2 += $c2;\n    $total1 += $c1;\n    $total2 += $c2;\n    my $file = $e->[1];\n    my $line = $e->[2];\n    if (($file eq $filename) &&\n        ($line >= $firstline) &&\n        ($line <= $lastline)) {\n      # Assign all accumulated samples to this line\n      AddEntry($samples1, $line, $running1);\n      AddEntry($samples2, $line, $running2);\n      $running1 = 0;\n      $running2 = 0;\n      if ($html) {\n        if ($line != $last_touched_line && $disasm{$line} ne '') {\n          $disasm{$line} .= \"\\n\";\n        }\n        $disasm{$line} .= $running_disasm;\n        $running_disasm = '';\n        $last_touched_line = $line;\n      }\n    }\n  }\n\n  # Assign any leftover samples to $lastline\n  AddEntry($samples1, $lastline, $running1);\n  AddEntry($samples2, $lastline, $running2);\n  if ($html) {\n    if ($lastline != $last_touched_line && $disasm{$lastline} ne '') {\n      $disasm{$lastline} .= \"\\n\";\n    }\n    $disasm{$lastline} .= $running_disasm;\n  }\n\n  if ($html) {\n    printf $output (\n      \"<h1>%s</h1>%s\\n<pre onClick=\\\"pprof_toggle_asm()\\\">\\n\" .\n      \"Total:%6s %6s (flat / cumulative %s)\\n\",\n      HtmlEscape(ShortFunctionName($routine)),\n      HtmlEscape(CleanFileName($filename)),\n      Unparse($total1),\n      Unparse($total2),\n      Units());\n  } else {\n    printf $output (\n      \"ROUTINE ====================== %s in %s\\n\" .\n      \"%6s %6s Total %s (flat / cumulative)\\n\",\n      ShortFunctionName($routine),\n      CleanFileName($filename),\n      Unparse($total1),\n      Unparse($total2),\n      Units());\n  }\n  if (!open(FILE, \"<$filename\")) {\n    print STDERR \"$filename: $!\\n\";\n    return 0;\n  }\n  my $l = 0;\n  while (<FILE>) {\n    s/\\r//g;         # turn windows-looking lines into unix-looking lines\n    $l++;\n    if ($l >= $firstline - 5 &&\n        (($l <= $oldlastline + 5) || ($l <= $lastline))) {\n      chop;\n      my $text = $_;\n      if ($l == $firstline) { print $output $skip_marker; }\n      my $n1 = GetEntry($samples1, $l);\n      my $n2 = GetEntry($samples2, $l);\n      if ($html) {\n        # Emit a span that has one of the following classes:\n        #    livesrc -- has samples\n        #    deadsrc -- has disassembly, but with no samples\n        #    nop     -- has no matching disasembly\n        # Also emit an optional span containing disassembly.\n        my $dis = $disasm{$l};\n        my $asm = \"\";\n        if (defined($dis) && $dis ne '') {\n          $asm = \"<span class=\\\"asm\\\">\" . $dis . \"</span>\";\n        }\n        my $source_class = (($n1 + $n2 > 0) \n                            ? \"livesrc\" \n                            : (($asm ne \"\") ? \"deadsrc\" : \"nop\"));\n        printf $output (\n          \"<span class=\\\"line\\\">%5d</span> \" .\n          \"<span class=\\\"%s\\\">%6s %6s %s</span>%s\\n\",\n          $l, $source_class,\n          HtmlPrintNumber($n1),\n          HtmlPrintNumber($n2),\n          HtmlEscape($text),\n          $asm);\n      } else {\n        printf $output(\n          \"%6s %6s %4d: %s\\n\",\n          UnparseAlt($n1),\n          UnparseAlt($n2),\n          $l,\n          $text);\n      }\n      if ($l == $lastline)  { print $output $skip_marker; }\n    };\n  }\n  close(FILE);\n  if ($html) {\n    print $output \"</pre>\\n\";\n  }\n  return 1;\n}\n\n# Return the source line for the specified file/linenumber.\n# Returns undef if not found.\nsub SourceLine {\n  my $file = shift;\n  my $line = shift;\n\n  # Look in cache\n  if (!defined($main::source_cache{$file})) {\n    if (100 < scalar keys(%main::source_cache)) {\n      # Clear the cache when it gets too big\n      $main::source_cache = ();\n    }\n\n    # Read all lines from the file\n    if (!open(FILE, \"<$file\")) {\n      print STDERR \"$file: $!\\n\";\n      $main::source_cache{$file} = [];  # Cache the negative result\n      return undef;\n    }\n    my $lines = [];\n    push(@{$lines}, \"\");        # So we can use 1-based line numbers as indices\n    while (<FILE>) {\n      push(@{$lines}, $_);\n    }\n    close(FILE);\n\n    # Save the lines in the cache\n    $main::source_cache{$file} = $lines;\n  }\n\n  my $lines = $main::source_cache{$file};\n  if (($line < 0) || ($line > $#{$lines})) {\n    return undef;\n  } else {\n    return $lines->[$line];\n  }\n}\n\n# Print disassembly for one routine with interspersed source if available\nsub PrintDisassembledFunction {\n  my $prog = shift;\n  my $offset = shift;\n  my $routine = shift;\n  my $flat = shift;\n  my $cumulative = shift;\n  my $start_addr = shift;\n  my $end_addr = shift;\n  my $total = shift;\n\n  # Disassemble all instructions\n  my @instructions = Disassemble($prog, $offset, $start_addr, $end_addr);\n\n  # Make array of counts per instruction\n  my @flat_count = ();\n  my @cum_count = ();\n  my $flat_total = 0;\n  my $cum_total = 0;\n  foreach my $e (@instructions) {\n    # Add up counts for all address that fall inside this instruction\n    my $c1 = 0;\n    my $c2 = 0;\n    for (my $a = $e->[0]; $a lt $e->[4]; $a = AddressInc($a)) {\n      $c1 += GetEntry($flat, $a);\n      $c2 += GetEntry($cumulative, $a);\n    }\n    push(@flat_count, $c1);\n    push(@cum_count, $c2);\n    $flat_total += $c1;\n    $cum_total += $c2;\n  }\n\n  # Print header with total counts\n  printf(\"ROUTINE ====================== %s\\n\" .\n         \"%6s %6s %s (flat, cumulative) %.1f%% of total\\n\",\n         ShortFunctionName($routine),\n         Unparse($flat_total),\n         Unparse($cum_total),\n         Units(),\n         ($cum_total * 100.0) / $total);\n\n  # Process instructions in order\n  my $current_file = \"\";\n  for (my $i = 0; $i <= $#instructions; ) {\n    my $e = $instructions[$i];\n\n    # Print the new file name whenever we switch files\n    if ($e->[1] ne $current_file) {\n      $current_file = $e->[1];\n      my $fname = $current_file;\n      $fname =~ s|^\\./||;   # Trim leading \"./\"\n\n      # Shorten long file names\n      if (length($fname) >= 58) {\n        $fname = \"...\" . substr($fname, -55);\n      }\n      printf(\"-------------------- %s\\n\", $fname);\n    }\n\n    # TODO: Compute range of lines to print together to deal with\n    # small reorderings.\n    my $first_line = $e->[2];\n    my $last_line = $first_line;\n    my %flat_sum = ();\n    my %cum_sum = ();\n    for (my $l = $first_line; $l <= $last_line; $l++) {\n      $flat_sum{$l} = 0;\n      $cum_sum{$l} = 0;\n    }\n\n    # Find run of instructions for this range of source lines\n    my $first_inst = $i;\n    while (($i <= $#instructions) &&\n           ($instructions[$i]->[2] >= $first_line) &&\n           ($instructions[$i]->[2] <= $last_line)) {\n      $e = $instructions[$i];\n      $flat_sum{$e->[2]} += $flat_count[$i];\n      $cum_sum{$e->[2]} += $cum_count[$i];\n      $i++;\n    }\n    my $last_inst = $i - 1;\n\n    # Print source lines\n    for (my $l = $first_line; $l <= $last_line; $l++) {\n      my $line = SourceLine($current_file, $l);\n      if (!defined($line)) {\n        $line = \"?\\n\";\n        next;\n      } else {\n        $line =~ s/^\\s+//;\n      }\n      printf(\"%6s %6s %5d: %s\",\n             UnparseAlt($flat_sum{$l}),\n             UnparseAlt($cum_sum{$l}),\n             $l,\n             $line);\n    }\n\n    # Print disassembly\n    for (my $x = $first_inst; $x <= $last_inst; $x++) {\n      my $e = $instructions[$x];\n      printf(\"%6s %6s    %8s: %6s\\n\",\n             UnparseAlt($flat_count[$x]),\n             UnparseAlt($cum_count[$x]),\n             UnparseAddress($offset, $e->[0]),\n             CleanDisassembly($e->[3]));\n    }\n  }\n}\n\n# Print DOT graph\nsub PrintDot {\n  my $prog = shift;\n  my $symbols = shift;\n  my $raw = shift;\n  my $flat = shift;\n  my $cumulative = shift;\n  my $overall_total = shift;\n\n  # Get total\n  my $local_total = TotalProfile($flat);\n  my $nodelimit = int($main::opt_nodefraction * $local_total);\n  my $edgelimit = int($main::opt_edgefraction * $local_total);\n  my $nodecount = $main::opt_nodecount;\n\n  # Find nodes to include\n  my @list = (sort { abs(GetEntry($cumulative, $b)) <=>\n                     abs(GetEntry($cumulative, $a))\n                     || $a cmp $b }\n              keys(%{$cumulative}));\n  my $last = $nodecount - 1;\n  if ($last > $#list) {\n    $last = $#list;\n  }\n  while (($last >= 0) &&\n         (abs(GetEntry($cumulative, $list[$last])) <= $nodelimit)) {\n    $last--;\n  }\n  if ($last < 0) {\n    print STDERR \"No nodes to print\\n\";\n    return 0;\n  }\n\n  if ($nodelimit > 0 || $edgelimit > 0) {\n    printf STDERR (\"Dropping nodes with <= %s %s; edges with <= %s abs(%s)\\n\",\n                   Unparse($nodelimit), Units(),\n                   Unparse($edgelimit), Units());\n  }\n\n  # Open DOT output file\n  my $output;\n  my $escaped_dot = ShellEscape(@DOT);\n  my $escaped_ps2pdf = ShellEscape(@PS2PDF);\n  if ($main::opt_gv) {\n    my $escaped_outfile = ShellEscape(TempName($main::next_tmpfile, \"ps\"));\n    $output = \"| $escaped_dot -Tps2 >$escaped_outfile\";\n  } elsif ($main::opt_evince) {\n    my $escaped_outfile = ShellEscape(TempName($main::next_tmpfile, \"pdf\"));\n    $output = \"| $escaped_dot -Tps2 | $escaped_ps2pdf - $escaped_outfile\";\n  } elsif ($main::opt_ps) {\n    $output = \"| $escaped_dot -Tps2\";\n  } elsif ($main::opt_pdf) {\n    $output = \"| $escaped_dot -Tps2 | $escaped_ps2pdf - -\";\n  } elsif ($main::opt_web || $main::opt_svg) {\n    # We need to post-process the SVG, so write to a temporary file always.\n    my $escaped_outfile = ShellEscape(TempName($main::next_tmpfile, \"svg\"));\n    $output = \"| $escaped_dot -Tsvg >$escaped_outfile\";\n  } elsif ($main::opt_gif) {\n    $output = \"| $escaped_dot -Tgif\";\n  } else {\n    $output = \">&STDOUT\";\n  }\n  open(DOT, $output) || error(\"$output: $!\\n\");\n\n  # Title\n  printf DOT (\"digraph \\\"%s; %s %s\\\" {\\n\",\n              $prog,\n              Unparse($overall_total),\n              Units());\n  if ($main::opt_pdf) {\n    # The output is more printable if we set the page size for dot.\n    printf DOT (\"size=\\\"8,11\\\"\\n\");\n  }\n  printf DOT (\"node [width=0.375,height=0.25];\\n\");\n\n  # Print legend\n  printf DOT (\"Legend [shape=box,fontsize=24,shape=plaintext,\" .\n              \"label=\\\"%s\\\\l%s\\\\l%s\\\\l%s\\\\l%s\\\\l\\\"];\\n\",\n              $prog,\n              sprintf(\"Total %s: %s\", Units(), Unparse($overall_total)),\n              sprintf(\"Focusing on: %s\", Unparse($local_total)),\n              sprintf(\"Dropped nodes with <= %s abs(%s)\",\n                      Unparse($nodelimit), Units()),\n              sprintf(\"Dropped edges with <= %s %s\",\n                      Unparse($edgelimit), Units())\n              );\n\n  # Print nodes\n  my %node = ();\n  my $nextnode = 1;\n  foreach my $a (@list[0..$last]) {\n    # Pick font size\n    my $f = GetEntry($flat, $a);\n    my $c = GetEntry($cumulative, $a);\n\n    my $fs = 8;\n    if ($local_total > 0) {\n      $fs = 8 + (50.0 * sqrt(abs($f * 1.0 / $local_total)));\n    }\n\n    $node{$a} = $nextnode++;\n    my $sym = $a;\n    $sym =~ s/\\s+/\\\\n/g;\n    $sym =~ s/::/\\\\n/g;\n\n    # Extra cumulative info to print for non-leaves\n    my $extra = \"\";\n    if ($f != $c) {\n      $extra = sprintf(\"\\\\rof %s (%s)\",\n                       Unparse($c),\n                       Percent($c, $local_total));\n    }\n    my $style = \"\";\n    if ($main::opt_heapcheck) {\n      if ($f > 0) {\n        # make leak-causing nodes more visible (add a background)\n        $style = \",style=filled,fillcolor=gray\"\n      } elsif ($f < 0) {\n        # make anti-leak-causing nodes (which almost never occur)\n        # stand out as well (triple border)\n        $style = \",peripheries=3\"\n      }\n    }\n\n    printf DOT (\"N%d [label=\\\"%s\\\\n%s (%s)%s\\\\r\" .\n                \"\\\",shape=box,fontsize=%.1f%s];\\n\",\n                $node{$a},\n                $sym,\n                Unparse($f),\n                Percent($f, $local_total),\n                $extra,\n                $fs,\n                $style,\n               );\n  }\n\n  # Get edges and counts per edge\n  my %edge = ();\n  my $n;\n  my $fullname_to_shortname_map = {};\n  FillFullnameToShortnameMap($symbols, $fullname_to_shortname_map);\n  foreach my $k (keys(%{$raw})) {\n    # TODO: omit low %age edges\n    $n = $raw->{$k};\n    my @translated = TranslateStack($symbols, $fullname_to_shortname_map, $k);\n    for (my $i = 1; $i <= $#translated; $i++) {\n      my $src = $translated[$i];\n      my $dst = $translated[$i-1];\n      #next if ($src eq $dst);  # Avoid self-edges?\n      if (exists($node{$src}) && exists($node{$dst})) {\n        my $edge_label = \"$src\\001$dst\";\n        if (!exists($edge{$edge_label})) {\n          $edge{$edge_label} = 0;\n        }\n        $edge{$edge_label} += $n;\n      }\n    }\n  }\n\n  # Print edges (process in order of decreasing counts)\n  my %indegree = ();   # Number of incoming edges added per node so far\n  my %outdegree = ();  # Number of outgoing edges added per node so far\n  foreach my $e (sort { $edge{$b} <=> $edge{$a} } keys(%edge)) {\n    my @x = split(/\\001/, $e);\n    $n = $edge{$e};\n\n    # Initialize degree of kept incoming and outgoing edges if necessary\n    my $src = $x[0];\n    my $dst = $x[1];\n    if (!exists($outdegree{$src})) { $outdegree{$src} = 0; }\n    if (!exists($indegree{$dst})) { $indegree{$dst} = 0; }\n\n    my $keep;\n    if ($indegree{$dst} == 0) {\n      # Keep edge if needed for reachability\n      $keep = 1;\n    } elsif (abs($n) <= $edgelimit) {\n      # Drop if we are below --edgefraction\n      $keep = 0;\n    } elsif ($outdegree{$src} >= $main::opt_maxdegree ||\n             $indegree{$dst} >= $main::opt_maxdegree) {\n      # Keep limited number of in/out edges per node\n      $keep = 0;\n    } else {\n      $keep = 1;\n    }\n\n    if ($keep) {\n      $outdegree{$src}++;\n      $indegree{$dst}++;\n\n      # Compute line width based on edge count\n      my $fraction = abs($local_total ? (3 * ($n / $local_total)) : 0);\n      if ($fraction > 1) { $fraction = 1; }\n      my $w = $fraction * 2;\n      if ($w < 1 && ($main::opt_web || $main::opt_svg)) {\n        # SVG output treats line widths < 1 poorly.\n        $w = 1;\n      }\n\n      # Dot sometimes segfaults if given edge weights that are too large, so\n      # we cap the weights at a large value\n      my $edgeweight = abs($n) ** 0.7;\n      if ($edgeweight > 100000) { $edgeweight = 100000; }\n      $edgeweight = int($edgeweight);\n\n      my $style = sprintf(\"setlinewidth(%f)\", $w);\n      if ($x[1] =~ m/\\(inline\\)/) {\n        $style .= \",dashed\";\n      }\n\n      # Use a slightly squashed function of the edge count as the weight\n      printf DOT (\"N%s -> N%s [label=%s, weight=%d, style=\\\"%s\\\"];\\n\",\n                  $node{$x[0]},\n                  $node{$x[1]},\n                  Unparse($n),\n                  $edgeweight,\n                  $style);\n    }\n  }\n\n  print DOT (\"}\\n\");\n  close(DOT);\n\n  if ($main::opt_web || $main::opt_svg) {\n    # Rewrite SVG to be more usable inside web browser.\n    RewriteSvg(TempName($main::next_tmpfile, \"svg\"));\n  }\n\n  return 1;\n}\n\nsub RewriteSvg {\n  my $svgfile = shift;\n\n  open(SVG, $svgfile) || die \"open temp svg: $!\";\n  my @svg = <SVG>;\n  close(SVG);\n  unlink $svgfile;\n  my $svg = join('', @svg);\n\n  # Dot's SVG output is\n  #\n  #    <svg width=\"___\" height=\"___\"\n  #     viewBox=\"___\" xmlns=...>\n  #    <g id=\"graph0\" transform=\"...\">\n  #    ...\n  #    </g>\n  #    </svg>\n  #\n  # Change it to\n  #\n  #    <svg width=\"100%\" height=\"100%\"\n  #     xmlns=...>\n  #    $svg_javascript\n  #    <g id=\"viewport\" transform=\"translate(0,0)\">\n  #    <g id=\"graph0\" transform=\"...\">\n  #    ...\n  #    </g>\n  #    </g>\n  #    </svg>\n\n  # Fix width, height; drop viewBox.\n  $svg =~ s/(?s)<svg width=\"[^\"]+\" height=\"[^\"]+\"(.*?)viewBox=\"[^\"]+\"/<svg width=\"100%\" height=\"100%\"$1/;\n\n  # Insert script, viewport <g> above first <g>\n  my $svg_javascript = SvgJavascript();\n  my $viewport = \"<g id=\\\"viewport\\\" transform=\\\"translate(0,0)\\\">\\n\";\n  $svg =~ s/<g id=\"graph\\d\"/$svg_javascript$viewport$&/;\n\n  # Insert final </g> above </svg>.\n  $svg =~ s/(.*)(<\\/svg>)/$1<\\/g>$2/;\n  $svg =~ s/<g id=\"graph\\d\"(.*?)/<g id=\"viewport\"$1/;\n\n  if ($main::opt_svg) {\n    # --svg: write to standard output.\n    print $svg;\n  } else {\n    # Write back to temporary file.\n    open(SVG, \">$svgfile\") || die \"open $svgfile: $!\";\n    print SVG $svg;\n    close(SVG);\n  }\n}\n\nsub SvgJavascript {\n  return <<'EOF';\n<script type=\"text/ecmascript\"><![CDATA[\n// SVGPan\n// http://www.cyberz.org/blog/2009/12/08/svgpan-a-javascript-svg-panzoomdrag-library/\n// Local modification: if(true || ...) below to force panning, never moving.\n\n/**\n *  SVGPan library 1.2\n * ====================\n *\n * Given an unique existing element with id \"viewport\", including the\n * the library into any SVG adds the following capabilities:\n *\n *  - Mouse panning\n *  - Mouse zooming (using the wheel)\n *  - Object dargging\n *\n * Known issues:\n *\n *  - Zooming (while panning) on Safari has still some issues\n *\n * Releases:\n *\n * 1.2, Sat Mar 20 08:42:50 GMT 2010, Zeng Xiaohui\n *\tFixed a bug with browser mouse handler interaction\n *\n * 1.1, Wed Feb  3 17:39:33 GMT 2010, Zeng Xiaohui\n *\tUpdated the zoom code to support the mouse wheel on Safari/Chrome\n *\n * 1.0, Andrea Leofreddi\n *\tFirst release\n *\n * This code is licensed under the following BSD license:\n *\n * Copyright 2009-2010 Andrea Leofreddi <a.leofreddi@itcharm.com>. All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without modification, are\n * permitted provided that the following conditions are met:\n *\n *    1. Redistributions of source code must retain the above copyright notice, this list of\n *       conditions and the following disclaimer.\n *\n *    2. Redistributions in binary form must reproduce the above copyright notice, this list\n *       of conditions and the following disclaimer in the documentation and/or other materials\n *       provided with the distribution.\n *\n * THIS SOFTWARE IS PROVIDED BY Andrea Leofreddi ``AS IS'' AND ANY EXPRESS OR IMPLIED\n * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND\n * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL Andrea Leofreddi OR\n * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR\n * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR\n * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON\n * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING\n * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF\n * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n *\n * The views and conclusions contained in the software and documentation are those of the\n * authors and should not be interpreted as representing official policies, either expressed\n * or implied, of Andrea Leofreddi.\n */\n\nvar root = document.documentElement;\n\nvar state = 'none', stateTarget, stateOrigin, stateTf;\n\nsetupHandlers(root);\n\n/**\n * Register handlers\n */\nfunction setupHandlers(root){\n\tsetAttributes(root, {\n\t\t\"onmouseup\" : \"add(evt)\",\n\t\t\"onmousedown\" : \"handleMouseDown(evt)\",\n\t\t\"onmousemove\" : \"handleMouseMove(evt)\",\n\t\t\"onmouseup\" : \"handleMouseUp(evt)\",\n\t\t//\"onmouseout\" : \"handleMouseUp(evt)\", // Decomment this to stop the pan functionality when dragging out of the SVG element\n\t});\n\n\tif(navigator.userAgent.toLowerCase().indexOf('webkit') >= 0)\n\t\twindow.addEventListener('mousewheel', handleMouseWheel, false); // Chrome/Safari\n\telse\n\t\twindow.addEventListener('DOMMouseScroll', handleMouseWheel, false); // Others\n\n\tvar g = svgDoc.getElementById(\"svg\");\n\tg.width = \"100%\";\n\tg.height = \"100%\";\n}\n\n/**\n * Instance an SVGPoint object with given event coordinates.\n */\nfunction getEventPoint(evt) {\n\tvar p = root.createSVGPoint();\n\n\tp.x = evt.clientX;\n\tp.y = evt.clientY;\n\n\treturn p;\n}\n\n/**\n * Sets the current transform matrix of an element.\n */\nfunction setCTM(element, matrix) {\n\tvar s = \"matrix(\" + matrix.a + \",\" + matrix.b + \",\" + matrix.c + \",\" + matrix.d + \",\" + matrix.e + \",\" + matrix.f + \")\";\n\n\telement.setAttribute(\"transform\", s);\n}\n\n/**\n * Dumps a matrix to a string (useful for debug).\n */\nfunction dumpMatrix(matrix) {\n\tvar s = \"[ \" + matrix.a + \", \" + matrix.c + \", \" + matrix.e + \"\\n  \" + matrix.b + \", \" + matrix.d + \", \" + matrix.f + \"\\n  0, 0, 1 ]\";\n\n\treturn s;\n}\n\n/**\n * Sets attributes of an element.\n */\nfunction setAttributes(element, attributes){\n\tfor (i in attributes)\n\t\telement.setAttributeNS(null, i, attributes[i]);\n}\n\n/**\n * Handle mouse move event.\n */\nfunction handleMouseWheel(evt) {\n\tif(evt.preventDefault)\n\t\tevt.preventDefault();\n\n\tevt.returnValue = false;\n\n\tvar svgDoc = evt.target.ownerDocument;\n\n\tvar delta;\n\n\tif(evt.wheelDelta)\n\t\tdelta = evt.wheelDelta / 3600; // Chrome/Safari\n\telse\n\t\tdelta = evt.detail / -90; // Mozilla\n\n\tvar z = 1 + delta; // Zoom factor: 0.9/1.1\n\n\tvar g = svgDoc.getElementById(\"viewport\");\n\n\tvar p = getEventPoint(evt);\n\n\tp = p.matrixTransform(g.getCTM().inverse());\n\n\t// Compute new scale matrix in current mouse position\n\tvar k = root.createSVGMatrix().translate(p.x, p.y).scale(z).translate(-p.x, -p.y);\n\n        setCTM(g, g.getCTM().multiply(k));\n\n\tstateTf = stateTf.multiply(k.inverse());\n}\n\n/**\n * Handle mouse move event.\n */\nfunction handleMouseMove(evt) {\n\tif(evt.preventDefault)\n\t\tevt.preventDefault();\n\n\tevt.returnValue = false;\n\n\tvar svgDoc = evt.target.ownerDocument;\n\n\tvar g = svgDoc.getElementById(\"viewport\");\n\n\tif(state == 'pan') {\n\t\t// Pan mode\n\t\tvar p = getEventPoint(evt).matrixTransform(stateTf);\n\n\t\tsetCTM(g, stateTf.inverse().translate(p.x - stateOrigin.x, p.y - stateOrigin.y));\n\t} else if(state == 'move') {\n\t\t// Move mode\n\t\tvar p = getEventPoint(evt).matrixTransform(g.getCTM().inverse());\n\n\t\tsetCTM(stateTarget, root.createSVGMatrix().translate(p.x - stateOrigin.x, p.y - stateOrigin.y).multiply(g.getCTM().inverse()).multiply(stateTarget.getCTM()));\n\n\t\tstateOrigin = p;\n\t}\n}\n\n/**\n * Handle click event.\n */\nfunction handleMouseDown(evt) {\n\tif(evt.preventDefault)\n\t\tevt.preventDefault();\n\n\tevt.returnValue = false;\n\n\tvar svgDoc = evt.target.ownerDocument;\n\n\tvar g = svgDoc.getElementById(\"viewport\");\n\n\tif(true || evt.target.tagName == \"svg\") {\n\t\t// Pan mode\n\t\tstate = 'pan';\n\n\t\tstateTf = g.getCTM().inverse();\n\n\t\tstateOrigin = getEventPoint(evt).matrixTransform(stateTf);\n\t} else {\n\t\t// Move mode\n\t\tstate = 'move';\n\n\t\tstateTarget = evt.target;\n\n\t\tstateTf = g.getCTM().inverse();\n\n\t\tstateOrigin = getEventPoint(evt).matrixTransform(stateTf);\n\t}\n}\n\n/**\n * Handle mouse button release event.\n */\nfunction handleMouseUp(evt) {\n\tif(evt.preventDefault)\n\t\tevt.preventDefault();\n\n\tevt.returnValue = false;\n\n\tvar svgDoc = evt.target.ownerDocument;\n\n\tif(state == 'pan' || state == 'move') {\n\t\t// Quit pan mode\n\t\tstate = '';\n\t}\n}\n\n]]></script>\nEOF\n}\n\n# Provides a map from fullname to shortname for cases where the\n# shortname is ambiguous.  The symlist has both the fullname and\n# shortname for all symbols, which is usually fine, but sometimes --\n# such as overloaded functions -- two different fullnames can map to\n# the same shortname.  In that case, we use the address of the\n# function to disambiguate the two.  This function fills in a map that\n# maps fullnames to modified shortnames in such cases.  If a fullname\n# is not present in the map, the 'normal' shortname provided by the\n# symlist is the appropriate one to use.\nsub FillFullnameToShortnameMap {\n  my $symbols = shift;\n  my $fullname_to_shortname_map = shift;\n  my $shortnames_seen_once = {};\n  my $shortnames_seen_more_than_once = {};\n\n  foreach my $symlist (values(%{$symbols})) {\n    # TODO(csilvers): deal with inlined symbols too.\n    my $shortname = $symlist->[0];\n    my $fullname = $symlist->[2];\n    if ($fullname !~ /<[0-9a-fA-F]+>$/) {  # fullname doesn't end in an address\n      next;       # the only collisions we care about are when addresses differ\n    }\n    if (defined($shortnames_seen_once->{$shortname}) &&\n        $shortnames_seen_once->{$shortname} ne $fullname) {\n      $shortnames_seen_more_than_once->{$shortname} = 1;\n    } else {\n      $shortnames_seen_once->{$shortname} = $fullname;\n    }\n  }\n\n  foreach my $symlist (values(%{$symbols})) {\n    my $shortname = $symlist->[0];\n    my $fullname = $symlist->[2];\n    # TODO(csilvers): take in a list of addresses we care about, and only\n    # store in the map if $symlist->[1] is in that list.  Saves space.\n    next if defined($fullname_to_shortname_map->{$fullname});\n    if (defined($shortnames_seen_more_than_once->{$shortname})) {\n      if ($fullname =~ /<0*([^>]*)>$/) {   # fullname has address at end of it\n        $fullname_to_shortname_map->{$fullname} = \"$shortname\\@$1\";\n      }\n    }\n  }\n}\n\n# Return a small number that identifies the argument.\n# Multiple calls with the same argument will return the same number.\n# Calls with different arguments will return different numbers.\nsub ShortIdFor {\n  my $key = shift;\n  my $id = $main::uniqueid{$key};\n  if (!defined($id)) {\n    $id = keys(%main::uniqueid) + 1;\n    $main::uniqueid{$key} = $id;\n  }\n  return $id;\n}\n\n# Translate a stack of addresses into a stack of symbols\nsub TranslateStack {\n  my $symbols = shift;\n  my $fullname_to_shortname_map = shift;\n  my $k = shift;\n\n  my @addrs = split(/\\n/, $k);\n  my @result = ();\n  for (my $i = 0; $i <= $#addrs; $i++) {\n    my $a = $addrs[$i];\n\n    # Skip large addresses since they sometimes show up as fake entries on RH9\n    if (length($a) > 8 && $a gt \"7fffffffffffffff\") {\n      next;\n    }\n\n    if ($main::opt_disasm || $main::opt_list) {\n      # We want just the address for the key\n      push(@result, $a);\n      next;\n    }\n\n    my $symlist = $symbols->{$a};\n    if (!defined($symlist)) {\n      $symlist = [$a, \"\", $a];\n    }\n\n    # We can have a sequence of symbols for a particular entry\n    # (more than one symbol in the case of inlining).  Callers\n    # come before callees in symlist, so walk backwards since\n    # the translated stack should contain callees before callers.\n    for (my $j = $#{$symlist}; $j >= 2; $j -= 3) {\n      my $func = $symlist->[$j-2];\n      my $fileline = $symlist->[$j-1];\n      my $fullfunc = $symlist->[$j];\n      if (defined($fullname_to_shortname_map->{$fullfunc})) {\n        $func = $fullname_to_shortname_map->{$fullfunc};\n      }\n      if ($j > 2) {\n        $func = \"$func (inline)\";\n      }\n\n      # Do not merge nodes corresponding to Callback::Run since that\n      # causes confusing cycles in dot display.  Instead, we synthesize\n      # a unique name for this frame per caller.\n      if ($func =~ m/Callback.*::Run$/) {\n        my $caller = ($i > 0) ? $addrs[$i-1] : 0;\n        $func = \"Run#\" . ShortIdFor($caller);\n      }\n\n      if ($main::opt_addresses) {\n        push(@result, \"$a $func $fileline\");\n      } elsif ($main::opt_lines) {\n        if ($func eq '??' && $fileline eq '??:0') {\n          push(@result, \"$a\");\n        } else {\n          push(@result, \"$func $fileline\");\n        }\n      } elsif ($main::opt_functions) {\n        if ($func eq '??') {\n          push(@result, \"$a\");\n        } else {\n          push(@result, $func);\n        }\n      } elsif ($main::opt_files) {\n        if ($fileline eq '??:0' || $fileline eq '') {\n          push(@result, \"$a\");\n        } else {\n          my $f = $fileline;\n          $f =~ s/:\\d+$//;\n          push(@result, $f);\n        }\n      } else {\n        push(@result, $a);\n        last;  # Do not print inlined info\n      }\n    }\n  }\n\n  # print join(\",\", @addrs), \" => \", join(\",\", @result), \"\\n\";\n  return @result;\n}\n\n# Generate percent string for a number and a total\nsub Percent {\n  my $num = shift;\n  my $tot = shift;\n  if ($tot != 0) {\n    return sprintf(\"%.1f%%\", $num * 100.0 / $tot);\n  } else {\n    return ($num == 0) ? \"nan\" : (($num > 0) ? \"+inf\" : \"-inf\");\n  }\n}\n\n# Generate pretty-printed form of number\nsub Unparse {\n  my $num = shift;\n  if ($main::profile_type eq 'heap' || $main::profile_type eq 'growth') {\n    if ($main::opt_inuse_objects || $main::opt_alloc_objects) {\n      return sprintf(\"%d\", $num);\n    } else {\n      if ($main::opt_show_bytes) {\n        return sprintf(\"%d\", $num);\n      } else {\n        return sprintf(\"%.1f\", $num / 1048576.0);\n      }\n    }\n  } elsif ($main::profile_type eq 'contention' && !$main::opt_contentions) {\n    return sprintf(\"%.3f\", $num / 1e9); # Convert nanoseconds to seconds\n  } else {\n    return sprintf(\"%d\", $num);\n  }\n}\n\n# Alternate pretty-printed form: 0 maps to \".\"\nsub UnparseAlt {\n  my $num = shift;\n  if ($num == 0) {\n    return \".\";\n  } else {\n    return Unparse($num);\n  }\n}\n\n# Alternate pretty-printed form: 0 maps to \"\"\nsub HtmlPrintNumber {\n  my $num = shift;\n  if ($num == 0) {\n    return \"\";\n  } else {\n    return Unparse($num);\n  }\n}\n\n# Return output units\nsub Units {\n  if ($main::profile_type eq 'heap' || $main::profile_type eq 'growth') {\n    if ($main::opt_inuse_objects || $main::opt_alloc_objects) {\n      return \"objects\";\n    } else {\n      if ($main::opt_show_bytes) {\n        return \"B\";\n      } else {\n        return \"MB\";\n      }\n    }\n  } elsif ($main::profile_type eq 'contention' && !$main::opt_contentions) {\n    return \"seconds\";\n  } else {\n    return \"samples\";\n  }\n}\n\n##### Profile manipulation code #####\n\n# Generate flattened profile:\n# If count is charged to stack [a,b,c,d], in generated profile,\n# it will be charged to [a]\nsub FlatProfile {\n  my $profile = shift;\n  my $result = {};\n  foreach my $k (keys(%{$profile})) {\n    my $count = $profile->{$k};\n    my @addrs = split(/\\n/, $k);\n    if ($#addrs >= 0) {\n      AddEntry($result, $addrs[0], $count);\n    }\n  }\n  return $result;\n}\n\n# Generate cumulative profile:\n# If count is charged to stack [a,b,c,d], in generated profile,\n# it will be charged to [a], [b], [c], [d]\nsub CumulativeProfile {\n  my $profile = shift;\n  my $result = {};\n  foreach my $k (keys(%{$profile})) {\n    my $count = $profile->{$k};\n    my @addrs = split(/\\n/, $k);\n    foreach my $a (@addrs) {\n      AddEntry($result, $a, $count);\n    }\n  }\n  return $result;\n}\n\n# If the second-youngest PC on the stack is always the same, returns\n# that pc.  Otherwise, returns undef.\nsub IsSecondPcAlwaysTheSame {\n  my $profile = shift;\n\n  my $second_pc = undef;\n  foreach my $k (keys(%{$profile})) {\n    my @addrs = split(/\\n/, $k);\n    if ($#addrs < 1) {\n      return undef;\n    }\n    if (not defined $second_pc) {\n      $second_pc = $addrs[1];\n    } else {\n      if ($second_pc ne $addrs[1]) {\n        return undef;\n      }\n    }\n  }\n  return $second_pc;\n}\n\nsub ExtractSymbolLocation {\n  my $symbols = shift;\n  my $address = shift;\n  # 'addr2line' outputs \"??:0\" for unknown locations; we do the\n  # same to be consistent.\n  my $location = \"??:0:unknown\";\n  if (exists $symbols->{$address}) {\n    my $file = $symbols->{$address}->[1];\n    if ($file eq \"?\") {\n      $file = \"??:0\"\n    }\n    $location = $file . \":\" . $symbols->{$address}->[0];\n  }\n  return $location;\n}\n\n# Extracts a graph of calls.\nsub ExtractCalls {\n  my $symbols = shift;\n  my $profile = shift;\n\n  my $calls = {};\n  while( my ($stack_trace, $count) = each %$profile ) {\n    my @address = split(/\\n/, $stack_trace);\n    my $destination = ExtractSymbolLocation($symbols, $address[0]);\n    AddEntry($calls, $destination, $count);\n    for (my $i = 1; $i <= $#address; $i++) {\n      my $source = ExtractSymbolLocation($symbols, $address[$i]);\n      my $call = \"$source -> $destination\";\n      AddEntry($calls, $call, $count);\n      $destination = $source;\n    }\n  }\n\n  return $calls;\n}\n\nsub RemoveUninterestingFrames {\n  my $symbols = shift;\n  my $profile = shift;\n\n  # List of function names to skip\n  my %skip = ();\n  my $skip_regexp = 'NOMATCH';\n  if ($main::profile_type eq 'heap' || $main::profile_type eq 'growth') {\n    foreach my $name ('calloc',\n                      'cfree',\n                      'malloc',\n                      'free',\n                      'memalign',\n                      'posix_memalign',\n                      'pvalloc',\n                      'valloc',\n                      'realloc',\n                      'tc_calloc',\n                      'tc_cfree',\n                      'tc_malloc',\n                      'tc_free',\n                      'tc_memalign',\n                      'tc_posix_memalign',\n                      'tc_pvalloc',\n                      'tc_valloc',\n                      'tc_realloc',\n                      'tc_new',\n                      'tc_delete',\n                      'tc_newarray',\n                      'tc_deletearray',\n                      'tc_new_nothrow',\n                      'tc_newarray_nothrow',\n                      'do_malloc',\n                      '::do_malloc',   # new name -- got moved to an unnamed ns\n                      '::do_malloc_or_cpp_alloc',\n                      'DoSampledAllocation',\n                      'simple_alloc::allocate',\n                      '__malloc_alloc_template::allocate',\n                      '__builtin_delete',\n                      '__builtin_new',\n                      '__builtin_vec_delete',\n                      '__builtin_vec_new',\n                      'operator new',\n                      'operator new[]',\n                      # The entry to our memory-allocation routines on OS X\n                      'malloc_zone_malloc',\n                      'malloc_zone_calloc',\n                      'malloc_zone_valloc',\n                      'malloc_zone_realloc',\n                      'malloc_zone_memalign',\n                      'malloc_zone_free',\n                      # These mark the beginning/end of our custom sections\n                      '__start_google_malloc',\n                      '__stop_google_malloc',\n                      '__start_malloc_hook',\n                      '__stop_malloc_hook') {\n      $skip{$name} = 1;\n      $skip{\"_\" . $name} = 1;   # Mach (OS X) adds a _ prefix to everything\n    }\n    # TODO: Remove TCMalloc once everything has been\n    # moved into the tcmalloc:: namespace and we have flushed\n    # old code out of the system.\n    $skip_regexp = \"TCMalloc|^tcmalloc::\";\n  } elsif ($main::profile_type eq 'contention') {\n    foreach my $vname ('base::RecordLockProfileData',\n                       'base::SubmitMutexProfileData',\n                       'base::SubmitSpinLockProfileData',\n                       'Mutex::Unlock',\n                       'Mutex::UnlockSlow',\n                       'Mutex::ReaderUnlock',\n                       'MutexLock::~MutexLock',\n                       'SpinLock::Unlock',\n                       'SpinLock::SlowUnlock',\n                       'SpinLockHolder::~SpinLockHolder') {\n      $skip{$vname} = 1;\n    }\n  } elsif ($main::profile_type eq 'cpu') {\n    # Drop signal handlers used for CPU profile collection\n    # TODO(dpeng): this should not be necessary; it's taken\n    # care of by the general 2nd-pc mechanism below.\n    foreach my $name ('ProfileData::Add',           # historical\n                      'ProfileData::prof_handler',  # historical\n                      'CpuProfiler::prof_handler',\n                      '__FRAME_END__',\n                      '__pthread_sighandler',\n                      '__restore') {\n      $skip{$name} = 1;\n    }\n  } else {\n    # Nothing skipped for unknown types\n  }\n\n  if ($main::profile_type eq 'cpu') {\n    # If all the second-youngest program counters are the same,\n    # this STRONGLY suggests that it is an artifact of measurement,\n    # i.e., stack frames pushed by the CPU profiler signal handler.\n    # Hence, we delete them.\n    # (The topmost PC is read from the signal structure, not from\n    # the stack, so it does not get involved.)\n    while (my $second_pc = IsSecondPcAlwaysTheSame($profile)) {\n      my $result = {};\n      my $func = '';\n      if (exists($symbols->{$second_pc})) {\n        $second_pc = $symbols->{$second_pc}->[0];\n      }\n      print STDERR \"Removing $second_pc from all stack traces.\\n\";\n      foreach my $k (keys(%{$profile})) {\n        my $count = $profile->{$k};\n        my @addrs = split(/\\n/, $k);\n        splice @addrs, 1, 1;\n        my $reduced_path = join(\"\\n\", @addrs);\n        AddEntry($result, $reduced_path, $count);\n      }\n      $profile = $result;\n    }\n  }\n\n  my $result = {};\n  foreach my $k (keys(%{$profile})) {\n    my $count = $profile->{$k};\n    my @addrs = split(/\\n/, $k);\n    my @path = ();\n    foreach my $a (@addrs) {\n      if (exists($symbols->{$a})) {\n        my $func = $symbols->{$a}->[0];\n        if ($skip{$func} || ($func =~ m/$skip_regexp/)) {\n          next;\n        }\n      }\n      push(@path, $a);\n    }\n    my $reduced_path = join(\"\\n\", @path);\n    AddEntry($result, $reduced_path, $count);\n  }\n  return $result;\n}\n\n# Reduce profile to granularity given by user\nsub ReduceProfile {\n  my $symbols = shift;\n  my $profile = shift;\n  my $result = {};\n  my $fullname_to_shortname_map = {};\n  FillFullnameToShortnameMap($symbols, $fullname_to_shortname_map);\n  foreach my $k (keys(%{$profile})) {\n    my $count = $profile->{$k};\n    my @translated = TranslateStack($symbols, $fullname_to_shortname_map, $k);\n    my @path = ();\n    my %seen = ();\n    $seen{''} = 1;      # So that empty keys are skipped\n    foreach my $e (@translated) {\n      # To avoid double-counting due to recursion, skip a stack-trace\n      # entry if it has already been seen\n      if (!$seen{$e}) {\n        $seen{$e} = 1;\n        push(@path, $e);\n      }\n    }\n    my $reduced_path = join(\"\\n\", @path);\n    AddEntry($result, $reduced_path, $count);\n  }\n  return $result;\n}\n\n# Does the specified symbol array match the regexp?\nsub SymbolMatches {\n  my $sym = shift;\n  my $re = shift;\n  if (defined($sym)) {\n    for (my $i = 0; $i < $#{$sym}; $i += 3) {\n      if ($sym->[$i] =~ m/$re/ || $sym->[$i+1] =~ m/$re/) {\n        return 1;\n      }\n    }\n  }\n  return 0;\n}\n\n# Focus only on paths involving specified regexps\nsub FocusProfile {\n  my $symbols = shift;\n  my $profile = shift;\n  my $focus = shift;\n  my $result = {};\n  foreach my $k (keys(%{$profile})) {\n    my $count = $profile->{$k};\n    my @addrs = split(/\\n/, $k);\n    foreach my $a (@addrs) {\n      # Reply if it matches either the address/shortname/fileline\n      if (($a =~ m/$focus/) || SymbolMatches($symbols->{$a}, $focus)) {\n        AddEntry($result, $k, $count);\n        last;\n      }\n    }\n  }\n  return $result;\n}\n\n# Focus only on paths not involving specified regexps\nsub IgnoreProfile {\n  my $symbols = shift;\n  my $profile = shift;\n  my $ignore = shift;\n  my $result = {};\n  foreach my $k (keys(%{$profile})) {\n    my $count = $profile->{$k};\n    my @addrs = split(/\\n/, $k);\n    my $matched = 0;\n    foreach my $a (@addrs) {\n      # Reply if it matches either the address/shortname/fileline\n      if (($a =~ m/$ignore/) || SymbolMatches($symbols->{$a}, $ignore)) {\n        $matched = 1;\n        last;\n      }\n    }\n    if (!$matched) {\n      AddEntry($result, $k, $count);\n    }\n  }\n  return $result;\n}\n\n# Get total count in profile\nsub TotalProfile {\n  my $profile = shift;\n  my $result = 0;\n  foreach my $k (keys(%{$profile})) {\n    $result += $profile->{$k};\n  }\n  return $result;\n}\n\n# Add A to B\nsub AddProfile {\n  my $A = shift;\n  my $B = shift;\n\n  my $R = {};\n  # add all keys in A\n  foreach my $k (keys(%{$A})) {\n    my $v = $A->{$k};\n    AddEntry($R, $k, $v);\n  }\n  # add all keys in B\n  foreach my $k (keys(%{$B})) {\n    my $v = $B->{$k};\n    AddEntry($R, $k, $v);\n  }\n  return $R;\n}\n\n# Merges symbol maps\nsub MergeSymbols {\n  my $A = shift;\n  my $B = shift;\n\n  my $R = {};\n  foreach my $k (keys(%{$A})) {\n    $R->{$k} = $A->{$k};\n  }\n  if (defined($B)) {\n    foreach my $k (keys(%{$B})) {\n      $R->{$k} = $B->{$k};\n    }\n  }\n  return $R;\n}\n\n\n# Add A to B\nsub AddPcs {\n  my $A = shift;\n  my $B = shift;\n\n  my $R = {};\n  # add all keys in A\n  foreach my $k (keys(%{$A})) {\n    $R->{$k} = 1\n  }\n  # add all keys in B\n  foreach my $k (keys(%{$B})) {\n    $R->{$k} = 1\n  }\n  return $R;\n}\n\n# Subtract B from A\nsub SubtractProfile {\n  my $A = shift;\n  my $B = shift;\n\n  my $R = {};\n  foreach my $k (keys(%{$A})) {\n    my $v = $A->{$k} - GetEntry($B, $k);\n    if ($v < 0 && $main::opt_drop_negative) {\n      $v = 0;\n    }\n    AddEntry($R, $k, $v);\n  }\n  if (!$main::opt_drop_negative) {\n    # Take care of when subtracted profile has more entries\n    foreach my $k (keys(%{$B})) {\n      if (!exists($A->{$k})) {\n        AddEntry($R, $k, 0 - $B->{$k});\n      }\n    }\n  }\n  return $R;\n}\n\n# Get entry from profile; zero if not present\nsub GetEntry {\n  my $profile = shift;\n  my $k = shift;\n  if (exists($profile->{$k})) {\n    return $profile->{$k};\n  } else {\n    return 0;\n  }\n}\n\n# Add entry to specified profile\nsub AddEntry {\n  my $profile = shift;\n  my $k = shift;\n  my $n = shift;\n  if (!exists($profile->{$k})) {\n    $profile->{$k} = 0;\n  }\n  $profile->{$k} += $n;\n}\n\n# Add a stack of entries to specified profile, and add them to the $pcs\n# list.\nsub AddEntries {\n  my $profile = shift;\n  my $pcs = shift;\n  my $stack = shift;\n  my $count = shift;\n  my @k = ();\n\n  foreach my $e (split(/\\s+/, $stack)) {\n    my $pc = HexExtend($e);\n    $pcs->{$pc} = 1;\n    push @k, $pc;\n  }\n  AddEntry($profile, (join \"\\n\", @k), $count);\n}\n\n##### Code to profile a server dynamically #####\n\nsub CheckSymbolPage {\n  my $url = SymbolPageURL();\n  my $command = ShellEscape(@URL_FETCHER, $url);\n  open(SYMBOL, \"$command |\") or error($command);\n  my $line = <SYMBOL>;\n  $line =~ s/\\r//g;         # turn windows-looking lines into unix-looking lines\n  close(SYMBOL);\n  unless (defined($line)) {\n    error(\"$url doesn't exist\\n\");\n  }\n\n  if ($line =~ /^num_symbols:\\s+(\\d+)$/) {\n    if ($1 == 0) {\n      error(\"Stripped binary. No symbols available.\\n\");\n    }\n  } else {\n    error(\"Failed to get the number of symbols from $url\\n\");\n  }\n}\n\nsub IsProfileURL {\n  my $profile_name = shift;\n  if (-f $profile_name) {\n    printf STDERR \"Using local file $profile_name.\\n\";\n    return 0;\n  }\n  return 1;\n}\n\nsub ParseProfileURL {\n  my $profile_name = shift;\n\n  if (!defined($profile_name) || $profile_name eq \"\") {\n    return ();\n  }\n\n  # Split profile URL - matches all non-empty strings, so no test.\n  $profile_name =~ m,^(https?://)?([^/]+)(.*?)(/|$PROFILES)?$,;\n\n  my $proto = $1 || \"http://\";\n  my $hostport = $2;\n  my $prefix = $3;\n  my $profile = $4 || \"/\";\n\n  my $host = $hostport;\n  $host =~ s/:.*//;\n\n  my $baseurl = \"$proto$hostport$prefix\";\n  return ($host, $baseurl, $profile);\n}\n\n# We fetch symbols from the first profile argument.\nsub SymbolPageURL {\n  my ($host, $baseURL, $path) = ParseProfileURL($main::pfile_args[0]);\n  return \"$baseURL$SYMBOL_PAGE\";\n}\n\nsub FetchProgramName() {\n  my ($host, $baseURL, $path) = ParseProfileURL($main::pfile_args[0]);\n  my $url = \"$baseURL$PROGRAM_NAME_PAGE\";\n  my $command_line = ShellEscape(@URL_FETCHER, $url);\n  open(CMDLINE, \"$command_line |\") or error($command_line);\n  my $cmdline = <CMDLINE>;\n  $cmdline =~ s/\\r//g;   # turn windows-looking lines into unix-looking lines\n  close(CMDLINE);\n  error(\"Failed to get program name from $url\\n\") unless defined($cmdline);\n  $cmdline =~ s/\\x00.+//;  # Remove argv[1] and latters.\n  $cmdline =~ s!\\n!!g;  # Remove LFs.\n  return $cmdline;\n}\n\n# Gee, curl's -L (--location) option isn't reliable at least\n# with its 7.12.3 version.  Curl will forget to post data if\n# there is a redirection.  This function is a workaround for\n# curl.  Redirection happens on borg hosts.\nsub ResolveRedirectionForCurl {\n  my $url = shift;\n  my $command_line = ShellEscape(@URL_FETCHER, \"--head\", $url);\n  open(CMDLINE, \"$command_line |\") or error($command_line);\n  while (<CMDLINE>) {\n    s/\\r//g;         # turn windows-looking lines into unix-looking lines\n    if (/^Location: (.*)/) {\n      $url = $1;\n    }\n  }\n  close(CMDLINE);\n  return $url;\n}\n\n# Add a timeout flat to URL_FETCHER.  Returns a new list.\nsub AddFetchTimeout {\n  my $timeout = shift;\n  my @fetcher = shift;\n  if (defined($timeout)) {\n    if (join(\" \", @fetcher) =~ m/\\bcurl -s/) {\n      push(@fetcher, \"--max-time\", sprintf(\"%d\", $timeout));\n    } elsif (join(\" \", @fetcher) =~ m/\\brpcget\\b/) {\n      push(@fetcher, sprintf(\"--deadline=%d\", $timeout));\n    }\n  }\n  return @fetcher;\n}\n\n# Reads a symbol map from the file handle name given as $1, returning\n# the resulting symbol map.  Also processes variables relating to symbols.\n# Currently, the only variable processed is 'binary=<value>' which updates\n# $main::prog to have the correct program name.\nsub ReadSymbols {\n  my $in = shift;\n  my $map = {};\n  while (<$in>) {\n    s/\\r//g;         # turn windows-looking lines into unix-looking lines\n    # Removes all the leading zeroes from the symbols, see comment below.\n    if (m/^0x0*([0-9a-f]+)\\s+(.+)/) {\n      $map->{$1} = $2;\n    } elsif (m/^---/) {\n      last;\n    } elsif (m/^([a-z][^=]*)=(.*)$/ ) {\n      my ($variable, $value) = ($1, $2);\n      for ($variable, $value) {\n        s/^\\s+//;\n        s/\\s+$//;\n      }\n      if ($variable eq \"binary\") {\n        if ($main::prog ne $UNKNOWN_BINARY && $main::prog ne $value) {\n          printf STDERR (\"Warning: Mismatched binary name '%s', using '%s'.\\n\",\n                         $main::prog, $value);\n        }\n        $main::prog = $value;\n      } else {\n        printf STDERR (\"Ignoring unknown variable in symbols list: \" .\n            \"'%s' = '%s'\\n\", $variable, $value);\n      }\n    }\n  }\n  return $map;\n}\n\n# Fetches and processes symbols to prepare them for use in the profile output\n# code.  If the optional 'symbol_map' arg is not given, fetches symbols from\n# $SYMBOL_PAGE for all PC values found in profile.  Otherwise, the raw symbols\n# are assumed to have already been fetched into 'symbol_map' and are simply\n# extracted and processed.\nsub FetchSymbols {\n  my $pcset = shift;\n  my $symbol_map = shift;\n\n  my %seen = ();\n  my @pcs = grep { !$seen{$_}++ } keys(%$pcset);  # uniq\n\n  if (!defined($symbol_map)) {\n    my $post_data = join(\"+\", sort((map {\"0x\" . \"$_\"} @pcs)));\n\n    open(POSTFILE, \">$main::tmpfile_sym\");\n    print POSTFILE $post_data;\n    close(POSTFILE);\n\n    my $url = SymbolPageURL();\n\n    my $command_line;\n    if (join(\" \", @URL_FETCHER) =~ m/\\bcurl -s/) {\n      $url = ResolveRedirectionForCurl($url);\n      $command_line = ShellEscape(@URL_FETCHER, \"-d\", \"\\@$main::tmpfile_sym\",\n                                  $url);\n    } else {\n      $command_line = (ShellEscape(@URL_FETCHER, \"--post\", $url)\n                       . \" < \" . ShellEscape($main::tmpfile_sym));\n    }\n    # We use c++filt in case $SYMBOL_PAGE gives us mangled symbols.\n    my $escaped_cppfilt = ShellEscape($obj_tool_map{\"c++filt\"});\n    open(SYMBOL, \"$command_line | $escaped_cppfilt |\") or error($command_line);\n    $symbol_map = ReadSymbols(*SYMBOL{IO});\n    close(SYMBOL);\n  }\n\n  my $symbols = {};\n  foreach my $pc (@pcs) {\n    my $fullname;\n    # For 64 bits binaries, symbols are extracted with 8 leading zeroes.\n    # Then /symbol reads the long symbols in as uint64, and outputs\n    # the result with a \"0x%08llx\" format which get rid of the zeroes.\n    # By removing all the leading zeroes in both $pc and the symbols from\n    # /symbol, the symbols match and are retrievable from the map.\n    my $shortpc = $pc;\n    $shortpc =~ s/^0*//;\n    # Each line may have a list of names, which includes the function\n    # and also other functions it has inlined.  They are separated (in\n    # PrintSymbolizedProfile), by --, which is illegal in function names.\n    my $fullnames;\n    if (defined($symbol_map->{$shortpc})) {\n      $fullnames = $symbol_map->{$shortpc};\n    } else {\n      $fullnames = \"0x\" . $pc;  # Just use addresses\n    }\n    my $sym = [];\n    $symbols->{$pc} = $sym;\n    foreach my $fullname (split(\"--\", $fullnames)) {\n      my $name = ShortFunctionName($fullname);\n      push(@{$sym}, $name, \"?\", $fullname);\n    }\n  }\n  return $symbols;\n}\n\nsub BaseName {\n  my $file_name = shift;\n  $file_name =~ s!^.*/!!;  # Remove directory name\n  return $file_name;\n}\n\nsub MakeProfileBaseName {\n  my ($binary_name, $profile_name) = @_;\n  my ($host, $baseURL, $path) = ParseProfileURL($profile_name);\n  my $binary_shortname = BaseName($binary_name);\n  return sprintf(\"%s.%s.%s\",\n                 $binary_shortname, $main::op_time, $host);\n}\n\nsub FetchDynamicProfile {\n  my $binary_name = shift;\n  my $profile_name = shift;\n  my $fetch_name_only = shift;\n  my $encourage_patience = shift;\n\n  if (!IsProfileURL($profile_name)) {\n    return $profile_name;\n  } else {\n    my ($host, $baseURL, $path) = ParseProfileURL($profile_name);\n    if ($path eq \"\" || $path eq \"/\") {\n      # Missing type specifier defaults to cpu-profile\n      $path = $PROFILE_PAGE;\n    }\n\n    my $profile_file = MakeProfileBaseName($binary_name, $profile_name);\n\n    my $url = \"$baseURL$path\";\n    my $fetch_timeout = undef;\n    if ($path =~ m/$PROFILE_PAGE|$PMUPROFILE_PAGE/) {\n      if ($path =~ m/[?]/) {\n        $url .= \"&\";\n      } else {\n        $url .= \"?\";\n      }\n      $url .= sprintf(\"seconds=%d\", $main::opt_seconds);\n      $fetch_timeout = $main::opt_seconds * 1.01 + 60;\n    } else {\n      # For non-CPU profiles, we add a type-extension to\n      # the target profile file name.\n      my $suffix = $path;\n      $suffix =~ s,/,.,g;\n      $profile_file .= $suffix;\n    }\n\n    my $profile_dir = $ENV{\"PPROF_TMPDIR\"} || ($ENV{HOME} . \"/pprof\");\n    if (! -d $profile_dir) {\n      mkdir($profile_dir)\n          || die(\"Unable to create profile directory $profile_dir: $!\\n\");\n    }\n    my $tmp_profile = \"$profile_dir/.tmp.$profile_file\";\n    my $real_profile = \"$profile_dir/$profile_file\";\n\n    if ($fetch_name_only > 0) {\n      return $real_profile;\n    }\n\n    my @fetcher = AddFetchTimeout($fetch_timeout, @URL_FETCHER);\n    my $cmd = ShellEscape(@fetcher, $url) . \" > \" . ShellEscape($tmp_profile);\n    if ($path =~ m/$PROFILE_PAGE|$PMUPROFILE_PAGE|$CENSUSPROFILE_PAGE/){\n      print STDERR \"Gathering CPU profile from $url for $main::opt_seconds seconds to\\n  ${real_profile}\\n\";\n      if ($encourage_patience) {\n        print STDERR \"Be patient...\\n\";\n      }\n    } else {\n      print STDERR \"Fetching $path profile from $url to\\n  ${real_profile}\\n\";\n    }\n\n    (system($cmd) == 0) || error(\"Failed to get profile: $cmd: $!\\n\");\n    (system(\"mv\", $tmp_profile, $real_profile) == 0) || error(\"Unable to rename profile\\n\");\n    print STDERR \"Wrote profile to $real_profile\\n\";\n    $main::collected_profile = $real_profile;\n    return $main::collected_profile;\n  }\n}\n\n# Collect profiles in parallel\nsub FetchDynamicProfiles {\n  my $items = scalar(@main::pfile_args);\n  my $levels = log($items) / log(2);\n\n  if ($items == 1) {\n    $main::profile_files[0] = FetchDynamicProfile($main::prog, $main::pfile_args[0], 0, 1);\n  } else {\n    # math rounding issues\n    if ((2 ** $levels) < $items) {\n     $levels++;\n    }\n    my $count = scalar(@main::pfile_args);\n    for (my $i = 0; $i < $count; $i++) {\n      $main::profile_files[$i] = FetchDynamicProfile($main::prog, $main::pfile_args[$i], 1, 0);\n    }\n    print STDERR \"Fetching $count profiles, Be patient...\\n\";\n    FetchDynamicProfilesRecurse($levels, 0, 0);\n    $main::collected_profile = join(\" \\\\\\n    \", @main::profile_files);\n  }\n}\n\n# Recursively fork a process to get enough processes\n# collecting profiles\nsub FetchDynamicProfilesRecurse {\n  my $maxlevel = shift;\n  my $level = shift;\n  my $position = shift;\n\n  if (my $pid = fork()) {\n    $position = 0 | ($position << 1);\n    TryCollectProfile($maxlevel, $level, $position);\n    wait;\n  } else {\n    $position = 1 | ($position << 1);\n    TryCollectProfile($maxlevel, $level, $position);\n    cleanup();\n    exit(0);\n  }\n}\n\n# Collect a single profile\nsub TryCollectProfile {\n  my $maxlevel = shift;\n  my $level = shift;\n  my $position = shift;\n\n  if ($level >= ($maxlevel - 1)) {\n    if ($position < scalar(@main::pfile_args)) {\n      FetchDynamicProfile($main::prog, $main::pfile_args[$position], 0, 0);\n    }\n  } else {\n    FetchDynamicProfilesRecurse($maxlevel, $level+1, $position);\n  }\n}\n\n##### Parsing code #####\n\n# Provide a small streaming-read module to handle very large\n# cpu-profile files.  Stream in chunks along a sliding window.\n# Provides an interface to get one 'slot', correctly handling\n# endian-ness differences.  A slot is one 32-bit or 64-bit word\n# (depending on the input profile).  We tell endianness and bit-size\n# for the profile by looking at the first 8 bytes: in cpu profiles,\n# the second slot is always 3 (we'll accept anything that's not 0).\nBEGIN {\n  package CpuProfileStream;\n\n  sub new {\n    my ($class, $file, $fname) = @_;\n    my $self = { file        => $file,\n                 base        => 0,\n                 stride      => 512 * 1024,   # must be a multiple of bitsize/8\n                 slots       => [],\n                 unpack_code => \"\",           # N for big-endian, V for little\n                 perl_is_64bit => 1,          # matters if profile is 64-bit\n    };\n    bless $self, $class;\n    # Let unittests adjust the stride\n    if ($main::opt_test_stride > 0) {\n      $self->{stride} = $main::opt_test_stride;\n    }\n    # Read the first two slots to figure out bitsize and endianness.\n    my $slots = $self->{slots};\n    my $str;\n    read($self->{file}, $str, 8);\n    # Set the global $address_length based on what we see here.\n    # 8 is 32-bit (8 hexadecimal chars); 16 is 64-bit (16 hexadecimal chars).\n    $address_length = ($str eq (chr(0)x8)) ? 16 : 8;\n    if ($address_length == 8) {\n      if (substr($str, 6, 2) eq chr(0)x2) {\n        $self->{unpack_code} = 'V';  # Little-endian.\n      } elsif (substr($str, 4, 2) eq chr(0)x2) {\n        $self->{unpack_code} = 'N';  # Big-endian\n      } else {\n        ::error(\"$fname: header size >= 2**16\\n\");\n      }\n      @$slots = unpack($self->{unpack_code} . \"*\", $str);\n    } else {\n      # If we're a 64-bit profile, check if we're a 64-bit-capable\n      # perl.  Otherwise, each slot will be represented as a float\n      # instead of an int64, losing precision and making all the\n      # 64-bit addresses wrong.  We won't complain yet, but will\n      # later if we ever see a value that doesn't fit in 32 bits.\n      my $has_q = 0;\n      eval { $has_q = pack(\"Q\", \"1\") ? 1 : 1; };\n      if (!$has_q) {\n        $self->{perl_is_64bit} = 0;\n      }\n      read($self->{file}, $str, 8);\n      if (substr($str, 4, 4) eq chr(0)x4) {\n        # We'd love to use 'Q', but it's a) not universal, b) not endian-proof.\n        $self->{unpack_code} = 'V';  # Little-endian.\n      } elsif (substr($str, 0, 4) eq chr(0)x4) {\n        $self->{unpack_code} = 'N';  # Big-endian\n      } else {\n        ::error(\"$fname: header size >= 2**32\\n\");\n      }\n      my @pair = unpack($self->{unpack_code} . \"*\", $str);\n      # Since we know one of the pair is 0, it's fine to just add them.\n      @$slots = (0, $pair[0] + $pair[1]);\n    }\n    return $self;\n  }\n\n  # Load more data when we access slots->get(X) which is not yet in memory.\n  sub overflow {\n    my ($self) = @_;\n    my $slots = $self->{slots};\n    $self->{base} += $#$slots + 1;   # skip over data we're replacing\n    my $str;\n    read($self->{file}, $str, $self->{stride});\n    if ($address_length == 8) {      # the 32-bit case\n      # This is the easy case: unpack provides 32-bit unpacking primitives.\n      @$slots = unpack($self->{unpack_code} . \"*\", $str);\n    } else {\n      # We need to unpack 32 bits at a time and combine.\n      my @b32_values = unpack($self->{unpack_code} . \"*\", $str);\n      my @b64_values = ();\n      for (my $i = 0; $i < $#b32_values; $i += 2) {\n        # TODO(csilvers): if this is a 32-bit perl, the math below\n        #    could end up in a too-large int, which perl will promote\n        #    to a double, losing necessary precision.  Deal with that.\n        #    Right now, we just die.\n        my ($lo, $hi) = ($b32_values[$i], $b32_values[$i+1]);\n        if ($self->{unpack_code} eq 'N') {    # big-endian\n          ($lo, $hi) = ($hi, $lo);\n        }\n        my $value = $lo + $hi * (2**32);\n        if (!$self->{perl_is_64bit} &&   # check value is exactly represented\n            (($value % (2**32)) != $lo || int($value / (2**32)) != $hi)) {\n          ::error(\"Need a 64-bit perl to process this 64-bit profile.\\n\");\n        }\n        push(@b64_values, $value);\n      }\n      @$slots = @b64_values;\n    }\n  }\n\n  # Access the i-th long in the file (logically), or -1 at EOF.\n  sub get {\n    my ($self, $idx) = @_;\n    my $slots = $self->{slots};\n    while ($#$slots >= 0) {\n      if ($idx < $self->{base}) {\n        # The only time we expect a reference to $slots[$i - something]\n        # after referencing $slots[$i] is reading the very first header.\n        # Since $stride > |header|, that shouldn't cause any lookback\n        # errors.  And everything after the header is sequential.\n        print STDERR \"Unexpected look-back reading CPU profile\";\n        return -1;   # shrug, don't know what better to return\n      } elsif ($idx > $self->{base} + $#$slots) {\n        $self->overflow();\n      } else {\n        return $slots->[$idx - $self->{base}];\n      }\n    }\n    # If we get here, $slots is [], which means we've reached EOF\n    return -1;  # unique since slots is supposed to hold unsigned numbers\n  }\n}\n\n# Reads the top, 'header' section of a profile, and returns the last\n# line of the header, commonly called a 'header line'.  The header\n# section of a profile consists of zero or more 'command' lines that\n# are instructions to pprof, which pprof executes when reading the\n# header.  All 'command' lines start with a %.  After the command\n# lines is the 'header line', which is a profile-specific line that\n# indicates what type of profile it is, and perhaps other global\n# information about the profile.  For instance, here's a header line\n# for a heap profile:\n#   heap profile:     53:    38236 [  5525:  1284029] @ heapprofile\n# For historical reasons, the CPU profile does not contain a text-\n# readable header line.  If the profile looks like a CPU profile,\n# this function returns \"\".  If no header line could be found, this\n# function returns undef.\n#\n# The following commands are recognized:\n#   %warn -- emit the rest of this line to stderr, prefixed by 'WARNING:'\n#\n# The input file should be in binmode.\nsub ReadProfileHeader {\n  local *PROFILE = shift;\n  my $firstchar = \"\";\n  my $line = \"\";\n  read(PROFILE, $firstchar, 1);\n  seek(PROFILE, -1, 1);                    # unread the firstchar\n  if ($firstchar !~ /[[:print:]]/) {       # is not a text character\n    return \"\";\n  }\n  while (defined($line = <PROFILE>)) {\n    $line =~ s/\\r//g;   # turn windows-looking lines into unix-looking lines\n    if ($line =~ /^%warn\\s+(.*)/) {        # 'warn' command\n      # Note this matches both '%warn blah\\n' and '%warn\\n'.\n      print STDERR \"WARNING: $1\\n\";        # print the rest of the line\n    } elsif ($line =~ /^%/) {\n      print STDERR \"Ignoring unknown command from profile header: $line\";\n    } else {\n      # End of commands, must be the header line.\n      return $line;\n    }\n  }\n  return undef;     # got to EOF without seeing a header line\n}\n\nsub IsSymbolizedProfileFile {\n  my $file_name = shift;\n  if (!(-e $file_name) || !(-r $file_name)) {\n    return 0;\n  }\n  # Check if the file contains a symbol-section marker.\n  open(TFILE, \"<$file_name\");\n  binmode TFILE;\n  my $firstline = ReadProfileHeader(*TFILE);\n  close(TFILE);\n  if (!$firstline) {\n    return 0;\n  }\n  $SYMBOL_PAGE =~ m,[^/]+$,;    # matches everything after the last slash\n  my $symbol_marker = $&;\n  return $firstline =~ /^--- *$symbol_marker/;\n}\n\n# Parse profile generated by common/profiler.cc and return a reference\n# to a map:\n#      $result->{version}     Version number of profile file\n#      $result->{period}      Sampling period (in microseconds)\n#      $result->{profile}     Profile object\n#      $result->{map}         Memory map info from profile\n#      $result->{pcs}         Hash of all PC values seen, key is hex address\nsub ReadProfile {\n  my $prog = shift;\n  my $fname = shift;\n  my $result;            # return value\n\n  $CONTENTION_PAGE =~ m,[^/]+$,;    # matches everything after the last slash\n  my $contention_marker = $&;\n  $GROWTH_PAGE  =~ m,[^/]+$,;    # matches everything after the last slash\n  my $growth_marker = $&;\n  $SYMBOL_PAGE =~ m,[^/]+$,;    # matches everything after the last slash\n  my $symbol_marker = $&;\n  $PROFILE_PAGE =~ m,[^/]+$,;    # matches everything after the last slash\n  my $profile_marker = $&;\n\n  # Look at first line to see if it is a heap or a CPU profile.\n  # CPU profile may start with no header at all, and just binary data\n  # (starting with \\0\\0\\0\\0) -- in that case, don't try to read the\n  # whole firstline, since it may be gigabytes(!) of data.\n  open(PROFILE, \"<$fname\") || error(\"$fname: $!\\n\");\n  binmode PROFILE;      # New perls do UTF-8 processing\n  my $header = ReadProfileHeader(*PROFILE);\n  if (!defined($header)) {   # means \"at EOF\"\n    error(\"Profile is empty.\\n\");\n  }\n\n  my $symbols;\n  if ($header =~ m/^--- *$symbol_marker/o) {\n    # Verify that the user asked for a symbolized profile\n    if (!$main::use_symbolized_profile) {\n      # we have both a binary and symbolized profiles, abort\n      error(\"FATAL ERROR: Symbolized profile\\n   $fname\\ncannot be used with \" .\n            \"a binary arg. Try again without passing\\n   $prog\\n\");\n    }\n    # Read the symbol section of the symbolized profile file.\n    $symbols = ReadSymbols(*PROFILE{IO});\n    # Read the next line to get the header for the remaining profile.\n    $header = ReadProfileHeader(*PROFILE) || \"\";\n  }\n\n  $main::profile_type = '';\n  if ($header =~ m/^heap profile:.*$growth_marker/o) {\n    $main::profile_type = 'growth';\n    $result =  ReadHeapProfile($prog, *PROFILE, $header);\n  } elsif ($header =~ m/^heap profile:/) {\n    $main::profile_type = 'heap';\n    $result =  ReadHeapProfile($prog, *PROFILE, $header);\n  } elsif ($header =~ m/^--- *$contention_marker/o) {\n    $main::profile_type = 'contention';\n    $result = ReadSynchProfile($prog, *PROFILE);\n  } elsif ($header =~ m/^--- *Stacks:/) {\n    print STDERR\n      \"Old format contention profile: mistakenly reports \" .\n      \"condition variable signals as lock contentions.\\n\";\n    $main::profile_type = 'contention';\n    $result = ReadSynchProfile($prog, *PROFILE);\n  } elsif ($header =~ m/^--- *$profile_marker/) {\n    # the binary cpu profile data starts immediately after this line\n    $main::profile_type = 'cpu';\n    $result = ReadCPUProfile($prog, $fname, *PROFILE);\n  } else {\n    if (defined($symbols)) {\n      # a symbolized profile contains a format we don't recognize, bail out\n      error(\"$fname: Cannot recognize profile section after symbols.\\n\");\n    }\n    # no ascii header present -- must be a CPU profile\n    $main::profile_type = 'cpu';\n    $result = ReadCPUProfile($prog, $fname, *PROFILE);\n  }\n\n  close(PROFILE);\n\n  # if we got symbols along with the profile, return those as well\n  if (defined($symbols)) {\n    $result->{symbols} = $symbols;\n  }\n\n  return $result;\n}\n\n# Subtract one from caller pc so we map back to call instr.\n# However, don't do this if we're reading a symbolized profile\n# file, in which case the subtract-one was done when the file\n# was written.\n#\n# We apply the same logic to all readers, though ReadCPUProfile uses an\n# independent implementation.\nsub FixCallerAddresses {\n  my $stack = shift;\n  if ($main::use_symbolized_profile) {\n    return $stack;\n  } else {\n    $stack =~ /(\\s)/;\n    my $delimiter = $1;\n    my @addrs = split(' ', $stack);\n    my @fixedaddrs;\n    $#fixedaddrs = $#addrs;\n    if ($#addrs >= 0) {\n      $fixedaddrs[0] = $addrs[0];\n    }\n    for (my $i = 1; $i <= $#addrs; $i++) {\n      $fixedaddrs[$i] = AddressSub($addrs[$i], \"0x1\");\n    }\n    return join $delimiter, @fixedaddrs;\n  }\n}\n\n# CPU profile reader\nsub ReadCPUProfile {\n  my $prog = shift;\n  my $fname = shift;       # just used for logging\n  local *PROFILE = shift;\n  my $version;\n  my $period;\n  my $i;\n  my $profile = {};\n  my $pcs = {};\n\n  # Parse string into array of slots.\n  my $slots = CpuProfileStream->new(*PROFILE, $fname);\n\n  # Read header.  The current header version is a 5-element structure\n  # containing:\n  #   0: header count (always 0)\n  #   1: header \"words\" (after this one: 3)\n  #   2: format version (0)\n  #   3: sampling period (usec)\n  #   4: unused padding (always 0)\n  if ($slots->get(0) != 0 ) {\n    error(\"$fname: not a profile file, or old format profile file\\n\");\n  }\n  $i = 2 + $slots->get(1);\n  $version = $slots->get(2);\n  $period = $slots->get(3);\n  # Do some sanity checking on these header values.\n  if ($version > (2**32) || $period > (2**32) || $i > (2**32) || $i < 5) {\n    error(\"$fname: not a profile file, or corrupted profile file\\n\");\n  }\n\n  # Parse profile\n  while ($slots->get($i) != -1) {\n    my $n = $slots->get($i++);\n    my $d = $slots->get($i++);\n    if ($d > (2**16)) {  # TODO(csilvers): what's a reasonable max-stack-depth?\n      my $addr = sprintf(\"0%o\", $i * ($address_length == 8 ? 4 : 8));\n      print STDERR \"At index $i (address $addr):\\n\";\n      error(\"$fname: stack trace depth >= 2**32\\n\");\n    }\n    if ($slots->get($i) == 0) {\n      # End of profile data marker\n      $i += $d;\n      last;\n    }\n\n    # Make key out of the stack entries\n    my @k = ();\n    for (my $j = 0; $j < $d; $j++) {\n      my $pc = $slots->get($i+$j);\n      # Subtract one from caller pc so we map back to call instr.\n      # However, don't do this if we're reading a symbolized profile\n      # file, in which case the subtract-one was done when the file\n      # was written.\n      if ($j > 0 && !$main::use_symbolized_profile) {\n        $pc--;\n      }\n      $pc = sprintf(\"%0*x\", $address_length, $pc);\n      $pcs->{$pc} = 1;\n      push @k, $pc;\n    }\n\n    AddEntry($profile, (join \"\\n\", @k), $n);\n    $i += $d;\n  }\n\n  # Parse map\n  my $map = '';\n  seek(PROFILE, $i * 4, 0);\n  read(PROFILE, $map, (stat PROFILE)[7]);\n\n  my $r = {};\n  $r->{version} = $version;\n  $r->{period} = $period;\n  $r->{profile} = $profile;\n  $r->{libs} = ParseLibraries($prog, $map, $pcs);\n  $r->{pcs} = $pcs;\n\n  return $r;\n}\n\nsub ReadHeapProfile {\n  my $prog = shift;\n  local *PROFILE = shift;\n  my $header = shift;\n\n  my $index = 1;\n  if ($main::opt_inuse_space) {\n    $index = 1;\n  } elsif ($main::opt_inuse_objects) {\n    $index = 0;\n  } elsif ($main::opt_alloc_space) {\n    $index = 3;\n  } elsif ($main::opt_alloc_objects) {\n    $index = 2;\n  }\n\n  # Find the type of this profile.  The header line looks like:\n  #    heap profile:   1246:  8800744 [  1246:  8800744] @ <heap-url>/266053\n  # There are two pairs <count: size>, the first inuse objects/space, and the\n  # second allocated objects/space.  This is followed optionally by a profile\n  # type, and if that is present, optionally by a sampling frequency.\n  # For remote heap profiles (v1):\n  # The interpretation of the sampling frequency is that the profiler, for\n  # each sample, calculates a uniformly distributed random integer less than\n  # the given value, and records the next sample after that many bytes have\n  # been allocated.  Therefore, the expected sample interval is half of the\n  # given frequency.  By default, if not specified, the expected sample\n  # interval is 128KB.  Only remote-heap-page profiles are adjusted for\n  # sample size.\n  # For remote heap profiles (v2):\n  # The sampling frequency is the rate of a Poisson process. This means that\n  # the probability of sampling an allocation of size X with sampling rate Y\n  # is 1 - exp(-X/Y)\n  # For version 2, a typical header line might look like this:\n  # heap profile:   1922: 127792360 [  1922: 127792360] @ <heap-url>_v2/524288\n  # the trailing number (524288) is the sampling rate. (Version 1 showed\n  # double the 'rate' here)\n  my $sampling_algorithm = 0;\n  my $sample_adjustment = 0;\n  chomp($header);\n  my $type = \"unknown\";\n  if ($header =~ m\"^heap profile:\\s*(\\d+):\\s+(\\d+)\\s+\\[\\s*(\\d+):\\s+(\\d+)\\](\\s*@\\s*([^/]*)(/(\\d+))?)?\") {\n    if (defined($6) && ($6 ne '')) {\n      $type = $6;\n      my $sample_period = $8;\n      # $type is \"heapprofile\" for profiles generated by the\n      # heap-profiler, and either \"heap\" or \"heap_v2\" for profiles\n      # generated by sampling directly within tcmalloc.  It can also\n      # be \"growth\" for heap-growth profiles.  The first is typically\n      # found for profiles generated locally, and the others for\n      # remote profiles.\n      if (($type eq \"heapprofile\") || ($type !~ /heap/) ) {\n        # No need to adjust for the sampling rate with heap-profiler-derived data\n        $sampling_algorithm = 0;\n      } elsif ($type =~ /_v2/) {\n        $sampling_algorithm = 2;     # version 2 sampling\n        if (defined($sample_period) && ($sample_period ne '')) {\n          $sample_adjustment = int($sample_period);\n        }\n      } else {\n        $sampling_algorithm = 1;     # version 1 sampling\n        if (defined($sample_period) && ($sample_period ne '')) {\n          $sample_adjustment = int($sample_period)/2;\n        }\n      }\n    } else {\n      # We detect whether or not this is a remote-heap profile by checking\n      # that the total-allocated stats ($n2,$s2) are exactly the\n      # same as the in-use stats ($n1,$s1).  It is remotely conceivable\n      # that a non-remote-heap profile may pass this check, but it is hard\n      # to imagine how that could happen.\n      # In this case it's so old it's guaranteed to be remote-heap version 1.\n      my ($n1, $s1, $n2, $s2) = ($1, $2, $3, $4);\n      if (($n1 == $n2) && ($s1 == $s2)) {\n        # This is likely to be a remote-heap based sample profile\n        $sampling_algorithm = 1;\n      }\n    }\n  }\n\n  if ($sampling_algorithm > 0) {\n    # For remote-heap generated profiles, adjust the counts and sizes to\n    # account for the sample rate (we sample once every 128KB by default).\n    if ($sample_adjustment == 0) {\n      # Turn on profile adjustment.\n      $sample_adjustment = 128*1024;\n      print STDERR \"Adjusting heap profiles for 1-in-128KB sampling rate\\n\";\n    } else {\n      printf STDERR (\"Adjusting heap profiles for 1-in-%d sampling rate\\n\",\n                     $sample_adjustment);\n    }\n    if ($sampling_algorithm > 1) {\n      # We don't bother printing anything for the original version (version 1)\n      printf STDERR \"Heap version $sampling_algorithm\\n\";\n    }\n  }\n\n  my $profile = {};\n  my $pcs = {};\n  my $map = \"\";\n\n  while (<PROFILE>) {\n    s/\\r//g;         # turn windows-looking lines into unix-looking lines\n    if (/^MAPPED_LIBRARIES:/) {\n      # Read the /proc/self/maps data\n      while (<PROFILE>) {\n        s/\\r//g;         # turn windows-looking lines into unix-looking lines\n        $map .= $_;\n      }\n      last;\n    }\n\n    if (/^--- Memory map:/) {\n      # Read /proc/self/maps data as formatted by DumpAddressMap()\n      my $buildvar = \"\";\n      while (<PROFILE>) {\n        s/\\r//g;         # turn windows-looking lines into unix-looking lines\n        # Parse \"build=<dir>\" specification if supplied\n        if (m/^\\s*build=(.*)\\n/) {\n          $buildvar = $1;\n        }\n\n        # Expand \"$build\" variable if available\n        $_ =~ s/\\$build\\b/$buildvar/g;\n\n        $map .= $_;\n      }\n      last;\n    }\n\n    # Read entry of the form:\n    #  <count1>: <bytes1> [<count2>: <bytes2>] @ a1 a2 a3 ... an\n    s/^\\s*//;\n    s/\\s*$//;\n    if (m/^\\s*(\\d+):\\s+(\\d+)\\s+\\[\\s*(\\d+):\\s+(\\d+)\\]\\s+@\\s+(.*)$/) {\n      my $stack = $5;\n      my ($n1, $s1, $n2, $s2) = ($1, $2, $3, $4);\n\n      if ($sample_adjustment) {\n        if ($sampling_algorithm == 2) {\n          # Remote-heap version 2\n          # The sampling frequency is the rate of a Poisson process.\n          # This means that the probability of sampling an allocation of\n          # size X with sampling rate Y is 1 - exp(-X/Y)\n          if ($n1 != 0) {\n            my $ratio = (($s1*1.0)/$n1)/($sample_adjustment);\n            my $scale_factor = 1/(1 - exp(-$ratio));\n            $n1 *= $scale_factor;\n            $s1 *= $scale_factor;\n          }\n          if ($n2 != 0) {\n            my $ratio = (($s2*1.0)/$n2)/($sample_adjustment);\n            my $scale_factor = 1/(1 - exp(-$ratio));\n            $n2 *= $scale_factor;\n            $s2 *= $scale_factor;\n          }\n        } else {\n          # Remote-heap version 1\n          my $ratio;\n          $ratio = (($s1*1.0)/$n1)/($sample_adjustment);\n          if ($ratio < 1) {\n            $n1 /= $ratio;\n            $s1 /= $ratio;\n          }\n          $ratio = (($s2*1.0)/$n2)/($sample_adjustment);\n          if ($ratio < 1) {\n            $n2 /= $ratio;\n            $s2 /= $ratio;\n          }\n        }\n      }\n\n      my @counts = ($n1, $s1, $n2, $s2);\n      AddEntries($profile, $pcs, FixCallerAddresses($stack), $counts[$index]);\n    }\n  }\n\n  my $r = {};\n  $r->{version} = \"heap\";\n  $r->{period} = 1;\n  $r->{profile} = $profile;\n  $r->{libs} = ParseLibraries($prog, $map, $pcs);\n  $r->{pcs} = $pcs;\n  return $r;\n}\n\nsub ReadSynchProfile {\n  my $prog = shift;\n  local *PROFILE = shift;\n  my $header = shift;\n\n  my $map = '';\n  my $profile = {};\n  my $pcs = {};\n  my $sampling_period = 1;\n  my $cyclespernanosec = 2.8;   # Default assumption for old binaries\n  my $seen_clockrate = 0;\n  my $line;\n\n  my $index = 0;\n  if ($main::opt_total_delay) {\n    $index = 0;\n  } elsif ($main::opt_contentions) {\n    $index = 1;\n  } elsif ($main::opt_mean_delay) {\n    $index = 2;\n  }\n\n  while ( $line = <PROFILE> ) {\n    $line =~ s/\\r//g;      # turn windows-looking lines into unix-looking lines\n    if ( $line =~ /^\\s*(\\d+)\\s+(\\d+) \\@\\s*(.*?)\\s*$/ ) {\n      my ($cycles, $count, $stack) = ($1, $2, $3);\n\n      # Convert cycles to nanoseconds\n      $cycles /= $cyclespernanosec;\n\n      # Adjust for sampling done by application\n      $cycles *= $sampling_period;\n      $count *= $sampling_period;\n\n      my @values = ($cycles, $count, $cycles / $count);\n      AddEntries($profile, $pcs, FixCallerAddresses($stack), $values[$index]);\n\n    } elsif ( $line =~ /^(slow release).*thread \\d+  \\@\\s*(.*?)\\s*$/ ||\n              $line =~ /^\\s*(\\d+) \\@\\s*(.*?)\\s*$/ ) {\n      my ($cycles, $stack) = ($1, $2);\n      if ($cycles !~ /^\\d+$/) {\n        next;\n      }\n\n      # Convert cycles to nanoseconds\n      $cycles /= $cyclespernanosec;\n\n      # Adjust for sampling done by application\n      $cycles *= $sampling_period;\n\n      AddEntries($profile, $pcs, FixCallerAddresses($stack), $cycles);\n\n    } elsif ( $line =~ m/^([a-z][^=]*)=(.*)$/ ) {\n      my ($variable, $value) = ($1,$2);\n      for ($variable, $value) {\n        s/^\\s+//;\n        s/\\s+$//;\n      }\n      if ($variable eq \"cycles/second\") {\n        $cyclespernanosec = $value / 1e9;\n        $seen_clockrate = 1;\n      } elsif ($variable eq \"sampling period\") {\n        $sampling_period = $value;\n      } elsif ($variable eq \"ms since reset\") {\n        # Currently nothing is done with this value in pprof\n        # So we just silently ignore it for now\n      } elsif ($variable eq \"discarded samples\") {\n        # Currently nothing is done with this value in pprof\n        # So we just silently ignore it for now\n      } else {\n        printf STDERR (\"Ignoring unnknown variable in /contention output: \" .\n                       \"'%s' = '%s'\\n\",$variable,$value);\n      }\n    } else {\n      # Memory map entry\n      $map .= $line;\n    }\n  }\n\n  if (!$seen_clockrate) {\n    printf STDERR (\"No cycles/second entry in profile; Guessing %.1f GHz\\n\",\n                   $cyclespernanosec);\n  }\n\n  my $r = {};\n  $r->{version} = 0;\n  $r->{period} = $sampling_period;\n  $r->{profile} = $profile;\n  $r->{libs} = ParseLibraries($prog, $map, $pcs);\n  $r->{pcs} = $pcs;\n  return $r;\n}\n\n# Given a hex value in the form \"0x1abcd\" or \"1abcd\", return either\n# \"0001abcd\" or \"000000000001abcd\", depending on the current (global)\n# address length.\nsub HexExtend {\n  my $addr = shift;\n\n  $addr =~ s/^(0x)?0*//;\n  my $zeros_needed = $address_length - length($addr);\n  if ($zeros_needed < 0) {\n    printf STDERR \"Warning: address $addr is longer than address length $address_length\\n\";\n    return $addr;\n  }\n  return (\"0\" x $zeros_needed) . $addr;\n}\n\n##### Symbol extraction #####\n\n# Aggressively search the lib_prefix values for the given library\n# If all else fails, just return the name of the library unmodified.\n# If the lib_prefix is \"/my/path,/other/path\" and $file is \"/lib/dir/mylib.so\"\n# it will search the following locations in this order, until it finds a file:\n#   /my/path/lib/dir/mylib.so\n#   /other/path/lib/dir/mylib.so\n#   /my/path/dir/mylib.so\n#   /other/path/dir/mylib.so\n#   /my/path/mylib.so\n#   /other/path/mylib.so\n#   /lib/dir/mylib.so              (returned as last resort)\nsub FindLibrary {\n  my $file = shift;\n  my $suffix = $file;\n\n  # Search for the library as described above\n  do {\n    foreach my $prefix (@prefix_list) {\n      my $fullpath = $prefix . $suffix;\n      if (-e $fullpath) {\n        return $fullpath;\n      }\n    }\n  } while ($suffix =~ s|^/[^/]+/|/|);\n  return $file;\n}\n\n# Return path to library with debugging symbols.\n# For libc libraries, the copy in /usr/lib/debug contains debugging symbols\nsub DebuggingLibrary {\n  my $file = shift;\n  if ($file =~ m|^/|) {\n      if (-f \"/usr/lib/debug$file\") {\n        return \"/usr/lib/debug$file\";\n      } elsif (-f \"/usr/lib/debug$file.debug\") {\n        return \"/usr/lib/debug$file.debug\";\n      }\n  }\n  return undef;\n}\n\n# Parse text section header of a library using objdump\nsub ParseTextSectionHeaderFromObjdump {\n  my $lib = shift;\n\n  my $size = undef;\n  my $vma;\n  my $file_offset;\n  # Get objdump output from the library file to figure out how to\n  # map between mapped addresses and addresses in the library.\n  my $cmd = ShellEscape($obj_tool_map{\"objdump\"}, \"-h\", $lib);\n  open(OBJDUMP, \"$cmd |\") || error(\"$cmd: $!\\n\");\n  while (<OBJDUMP>) {\n    s/\\r//g;         # turn windows-looking lines into unix-looking lines\n    # Idx Name          Size      VMA       LMA       File off  Algn\n    #  10 .text         00104b2c  420156f0  420156f0  000156f0  2**4\n    # For 64-bit objects, VMA and LMA will be 16 hex digits, size and file\n    # offset may still be 8.  But AddressSub below will still handle that.\n    my @x = split;\n    if (($#x >= 6) && ($x[1] eq '.text')) {\n      $size = $x[2];\n      $vma = $x[3];\n      $file_offset = $x[5];\n      last;\n    }\n  }\n  close(OBJDUMP);\n\n  if (!defined($size)) {\n    return undef;\n  }\n\n  my $r = {};\n  $r->{size} = $size;\n  $r->{vma} = $vma;\n  $r->{file_offset} = $file_offset;\n\n  return $r;\n}\n\n# Parse text section header of a library using otool (on OS X)\nsub ParseTextSectionHeaderFromOtool {\n  my $lib = shift;\n\n  my $size = undef;\n  my $vma = undef;\n  my $file_offset = undef;\n  # Get otool output from the library file to figure out how to\n  # map between mapped addresses and addresses in the library.\n  my $command = ShellEscape($obj_tool_map{\"otool\"}, \"-l\", $lib);\n  open(OTOOL, \"$command |\") || error(\"$command: $!\\n\");\n  my $cmd = \"\";\n  my $sectname = \"\";\n  my $segname = \"\";\n  foreach my $line (<OTOOL>) {\n    $line =~ s/\\r//g;      # turn windows-looking lines into unix-looking lines\n    # Load command <#>\n    #       cmd LC_SEGMENT\n    # [...]\n    # Section\n    #   sectname __text\n    #    segname __TEXT\n    #       addr 0x000009f8\n    #       size 0x00018b9e\n    #     offset 2552\n    #      align 2^2 (4)\n    # We will need to strip off the leading 0x from the hex addresses,\n    # and convert the offset into hex.\n    if ($line =~ /Load command/) {\n      $cmd = \"\";\n      $sectname = \"\";\n      $segname = \"\";\n    } elsif ($line =~ /Section/) {\n      $sectname = \"\";\n      $segname = \"\";\n    } elsif ($line =~ /cmd (\\w+)/) {\n      $cmd = $1;\n    } elsif ($line =~ /sectname (\\w+)/) {\n      $sectname = $1;\n    } elsif ($line =~ /segname (\\w+)/) {\n      $segname = $1;\n    } elsif (!(($cmd eq \"LC_SEGMENT\" || $cmd eq \"LC_SEGMENT_64\") &&\n               $sectname eq \"__text\" &&\n               $segname eq \"__TEXT\")) {\n      next;\n    } elsif ($line =~ /\\baddr 0x([0-9a-fA-F]+)/) {\n      $vma = $1;\n    } elsif ($line =~ /\\bsize 0x([0-9a-fA-F]+)/) {\n      $size = $1;\n    } elsif ($line =~ /\\boffset ([0-9]+)/) {\n      $file_offset = sprintf(\"%016x\", $1);\n    }\n    if (defined($vma) && defined($size) && defined($file_offset)) {\n      last;\n    }\n  }\n  close(OTOOL);\n\n  if (!defined($vma) || !defined($size) || !defined($file_offset)) {\n     return undef;\n  }\n\n  my $r = {};\n  $r->{size} = $size;\n  $r->{vma} = $vma;\n  $r->{file_offset} = $file_offset;\n\n  return $r;\n}\n\nsub ParseTextSectionHeader {\n  # obj_tool_map(\"otool\") is only defined if we're in a Mach-O environment\n  if (defined($obj_tool_map{\"otool\"})) {\n    my $r = ParseTextSectionHeaderFromOtool(@_);\n    if (defined($r)){\n      return $r;\n    }\n  }\n  # If otool doesn't work, or we don't have it, fall back to objdump\n  return ParseTextSectionHeaderFromObjdump(@_);\n}\n\n# Split /proc/pid/maps dump into a list of libraries\nsub ParseLibraries {\n  return if $main::use_symbol_page;  # We don't need libraries info.\n  my $prog = shift;\n  my $map = shift;\n  my $pcs = shift;\n\n  my $result = [];\n  my $h = \"[a-f0-9]+\";\n  my $zero_offset = HexExtend(\"0\");\n\n  my $buildvar = \"\";\n  foreach my $l (split(\"\\n\", $map)) {\n    if ($l =~ m/^\\s*build=(.*)$/) {\n      $buildvar = $1;\n    }\n\n    my $start;\n    my $finish;\n    my $offset;\n    my $lib;\n    if ($l =~ /^($h)-($h)\\s+..x.\\s+($h)\\s+\\S+:\\S+\\s+\\d+\\s+(\\S+\\.(so|dll|dylib|bundle)((\\.\\d+)+\\w*(\\.\\d+){0,3})?)$/i) {\n      # Full line from /proc/self/maps.  Example:\n      #   40000000-40015000 r-xp 00000000 03:01 12845071   /lib/ld-2.3.2.so\n      $start = HexExtend($1);\n      $finish = HexExtend($2);\n      $offset = HexExtend($3);\n      $lib = $4;\n      $lib =~ s|\\\\|/|g;     # turn windows-style paths into unix-style paths\n    } elsif ($l =~ /^\\s*($h)-($h):\\s*(\\S+\\.so(\\.\\d+)*)/) {\n      # Cooked line from DumpAddressMap.  Example:\n      #   40000000-40015000: /lib/ld-2.3.2.so\n      $start = HexExtend($1);\n      $finish = HexExtend($2);\n      $offset = $zero_offset;\n      $lib = $3;\n    }\n    # FreeBSD 10.0 virtual memory map /proc/curproc/map as defined in\n    # function procfs_doprocmap (sys/fs/procfs/procfs_map.c)\n    #\n    # Example:\n    # 0x800600000 0x80061a000 26 0 0xfffff800035a0000 r-x 75 33 0x1004 COW NC vnode /libexec/ld-elf.s\n    # o.1 NCH -1\n    elsif ($l =~ /^(0x$h)\\s(0x$h)\\s\\d+\\s\\d+\\s0x$h\\sr-x\\s\\d+\\s\\d+\\s0x\\d+\\s(COW|NCO)\\s(NC|NNC)\\svnode\\s(\\S+\\.so(\\.\\d+)*)/) {\n      $start = HexExtend($1);\n      $finish = HexExtend($2);\n      $offset = $zero_offset;\n      $lib = FindLibrary($5);\n\n    } else {\n      next;\n    }\n\n    # Expand \"$build\" variable if available\n    $lib =~ s/\\$build\\b/$buildvar/g;\n\n    $lib = FindLibrary($lib);\n\n    # Check for pre-relocated libraries, which use pre-relocated symbol tables\n    # and thus require adjusting the offset that we'll use to translate\n    # VM addresses into symbol table addresses.\n    # Only do this if we're not going to fetch the symbol table from a\n    # debugging copy of the library.\n    if (!DebuggingLibrary($lib)) {\n      my $text = ParseTextSectionHeader($lib);\n      if (defined($text)) {\n         my $vma_offset = AddressSub($text->{vma}, $text->{file_offset});\n         $offset = AddressAdd($offset, $vma_offset);\n      }\n    }\n\n    if($main::opt_debug) { printf STDERR \"$start:$finish ($offset) $lib\\n\"; }\n    push(@{$result}, [$lib, $start, $finish, $offset]);\n  }\n\n  # Append special entry for additional library (not relocated)\n  if ($main::opt_lib ne \"\") {\n    my $text = ParseTextSectionHeader($main::opt_lib);\n    if (defined($text)) {\n       my $start = $text->{vma};\n       my $finish = AddressAdd($start, $text->{size});\n\n       push(@{$result}, [$main::opt_lib, $start, $finish, $start]);\n    }\n  }\n\n  # Append special entry for the main program.  This covers\n  # 0..max_pc_value_seen, so that we assume pc values not found in one\n  # of the library ranges will be treated as coming from the main\n  # program binary.\n  my $min_pc = HexExtend(\"0\");\n  my $max_pc = $min_pc;          # find the maximal PC value in any sample\n  foreach my $pc (keys(%{$pcs})) {\n    if (HexExtend($pc) gt $max_pc) { $max_pc = HexExtend($pc); }\n  }\n  push(@{$result}, [$prog, $min_pc, $max_pc, $zero_offset]);\n\n  return $result;\n}\n\n# Add two hex addresses of length $address_length.\n# Run pprof --test for unit test if this is changed.\nsub AddressAdd {\n  my $addr1 = shift;\n  my $addr2 = shift;\n  my $sum;\n\n  if ($address_length == 8) {\n    # Perl doesn't cope with wraparound arithmetic, so do it explicitly:\n    $sum = (hex($addr1)+hex($addr2)) % (0x10000000 * 16);\n    return sprintf(\"%08x\", $sum);\n\n  } else {\n    # Do the addition in 7-nibble chunks to trivialize carry handling.\n\n    if ($main::opt_debug and $main::opt_test) {\n      print STDERR \"AddressAdd $addr1 + $addr2 = \";\n    }\n\n    my $a1 = substr($addr1,-7);\n    $addr1 = substr($addr1,0,-7);\n    my $a2 = substr($addr2,-7);\n    $addr2 = substr($addr2,0,-7);\n    $sum = hex($a1) + hex($a2);\n    my $c = 0;\n    if ($sum > 0xfffffff) {\n      $c = 1;\n      $sum -= 0x10000000;\n    }\n    my $r = sprintf(\"%07x\", $sum);\n\n    $a1 = substr($addr1,-7);\n    $addr1 = substr($addr1,0,-7);\n    $a2 = substr($addr2,-7);\n    $addr2 = substr($addr2,0,-7);\n    $sum = hex($a1) + hex($a2) + $c;\n    $c = 0;\n    if ($sum > 0xfffffff) {\n      $c = 1;\n      $sum -= 0x10000000;\n    }\n    $r = sprintf(\"%07x\", $sum) . $r;\n\n    $sum = hex($addr1) + hex($addr2) + $c;\n    if ($sum > 0xff) { $sum -= 0x100; }\n    $r = sprintf(\"%02x\", $sum) . $r;\n\n    if ($main::opt_debug and $main::opt_test) { print STDERR \"$r\\n\"; }\n\n    return $r;\n  }\n}\n\n\n# Subtract two hex addresses of length $address_length.\n# Run pprof --test for unit test if this is changed.\nsub AddressSub {\n  my $addr1 = shift;\n  my $addr2 = shift;\n  my $diff;\n\n  if ($address_length == 8) {\n    # Perl doesn't cope with wraparound arithmetic, so do it explicitly:\n    $diff = (hex($addr1)-hex($addr2)) % (0x10000000 * 16);\n    return sprintf(\"%08x\", $diff);\n\n  } else {\n    # Do the addition in 7-nibble chunks to trivialize borrow handling.\n    # if ($main::opt_debug) { print STDERR \"AddressSub $addr1 - $addr2 = \"; }\n\n    my $a1 = hex(substr($addr1,-7));\n    $addr1 = substr($addr1,0,-7);\n    my $a2 = hex(substr($addr2,-7));\n    $addr2 = substr($addr2,0,-7);\n    my $b = 0;\n    if ($a2 > $a1) {\n      $b = 1;\n      $a1 += 0x10000000;\n    }\n    $diff = $a1 - $a2;\n    my $r = sprintf(\"%07x\", $diff);\n\n    $a1 = hex(substr($addr1,-7));\n    $addr1 = substr($addr1,0,-7);\n    $a2 = hex(substr($addr2,-7)) + $b;\n    $addr2 = substr($addr2,0,-7);\n    $b = 0;\n    if ($a2 > $a1) {\n      $b = 1;\n      $a1 += 0x10000000;\n    }\n    $diff = $a1 - $a2;\n    $r = sprintf(\"%07x\", $diff) . $r;\n\n    $a1 = hex($addr1);\n    $a2 = hex($addr2) + $b;\n    if ($a2 > $a1) { $a1 += 0x100; }\n    $diff = $a1 - $a2;\n    $r = sprintf(\"%02x\", $diff) . $r;\n\n    # if ($main::opt_debug) { print STDERR \"$r\\n\"; }\n\n    return $r;\n  }\n}\n\n# Increment a hex addresses of length $address_length.\n# Run pprof --test for unit test if this is changed.\nsub AddressInc {\n  my $addr = shift;\n  my $sum;\n\n  if ($address_length == 8) {\n    # Perl doesn't cope with wraparound arithmetic, so do it explicitly:\n    $sum = (hex($addr)+1) % (0x10000000 * 16);\n    return sprintf(\"%08x\", $sum);\n\n  } else {\n    # Do the addition in 7-nibble chunks to trivialize carry handling.\n    # We are always doing this to step through the addresses in a function,\n    # and will almost never overflow the first chunk, so we check for this\n    # case and exit early.\n\n    # if ($main::opt_debug) { print STDERR \"AddressInc $addr1 = \"; }\n\n    my $a1 = substr($addr,-7);\n    $addr = substr($addr,0,-7);\n    $sum = hex($a1) + 1;\n    my $r = sprintf(\"%07x\", $sum);\n    if ($sum <= 0xfffffff) {\n      $r = $addr . $r;\n      # if ($main::opt_debug) { print STDERR \"$r\\n\"; }\n      return HexExtend($r);\n    } else {\n      $r = \"0000000\";\n    }\n\n    $a1 = substr($addr,-7);\n    $addr = substr($addr,0,-7);\n    $sum = hex($a1) + 1;\n    $r = sprintf(\"%07x\", $sum) . $r;\n    if ($sum <= 0xfffffff) {\n      $r = $addr . $r;\n      # if ($main::opt_debug) { print STDERR \"$r\\n\"; }\n      return HexExtend($r);\n    } else {\n      $r = \"00000000000000\";\n    }\n\n    $sum = hex($addr) + 1;\n    if ($sum > 0xff) { $sum -= 0x100; }\n    $r = sprintf(\"%02x\", $sum) . $r;\n\n    # if ($main::opt_debug) { print STDERR \"$r\\n\"; }\n    return $r;\n  }\n}\n\n# Extract symbols for all PC values found in profile\nsub ExtractSymbols {\n  my $libs = shift;\n  my $pcset = shift;\n\n  my $symbols = {};\n\n  # Map each PC value to the containing library.  To make this faster,\n  # we sort libraries by their starting pc value (highest first), and\n  # advance through the libraries as we advance the pc.  Sometimes the\n  # addresses of libraries may overlap with the addresses of the main\n  # binary, so to make sure the libraries 'win', we iterate over the\n  # libraries in reverse order (which assumes the binary doesn't start\n  # in the middle of a library, which seems a fair assumption).\n  my @pcs = (sort { $a cmp $b } keys(%{$pcset}));  # pcset is 0-extended strings\n  foreach my $lib (sort {$b->[1] cmp $a->[1]} @{$libs}) {\n    my $libname = $lib->[0];\n    my $start = $lib->[1];\n    my $finish = $lib->[2];\n    my $offset = $lib->[3];\n\n    # Use debug library if it exists\n    my $debug_libname = DebuggingLibrary($libname);\n    if ($debug_libname) {\n        $libname = $debug_libname;\n    }\n\n    # Get list of pcs that belong in this library.\n    my $contained = [];\n    my ($start_pc_index, $finish_pc_index);\n    # Find smallest finish_pc_index such that $finish < $pc[$finish_pc_index].\n    for ($finish_pc_index = $#pcs + 1; $finish_pc_index > 0;\n         $finish_pc_index--) {\n      last if $pcs[$finish_pc_index - 1] le $finish;\n    }\n    # Find smallest start_pc_index such that $start <= $pc[$start_pc_index].\n    for ($start_pc_index = $finish_pc_index; $start_pc_index > 0;\n         $start_pc_index--) {\n      last if $pcs[$start_pc_index - 1] lt $start;\n    }\n    # This keeps PC values higher than $pc[$finish_pc_index] in @pcs,\n    # in case there are overlaps in libraries and the main binary.\n    @{$contained} = splice(@pcs, $start_pc_index,\n                           $finish_pc_index - $start_pc_index);\n    # Map to symbols\n    MapToSymbols($libname, AddressSub($start, $offset), $contained, $symbols);\n  }\n\n  return $symbols;\n}\n\n# Map list of PC values to symbols for a given image\nsub MapToSymbols {\n  my $image = shift;\n  my $offset = shift;\n  my $pclist = shift;\n  my $symbols = shift;\n\n  my $debug = 0;\n\n  # Ignore empty binaries\n  if ($#{$pclist} < 0) { return; }\n\n  # Figure out the addr2line command to use\n  my $addr2line = $obj_tool_map{\"addr2line\"};\n  my $cmd = ShellEscape($addr2line, \"-f\", \"-C\", \"-e\", $image);\n  if (exists $obj_tool_map{\"addr2line_pdb\"}) {\n    $addr2line = $obj_tool_map{\"addr2line_pdb\"};\n    $cmd = ShellEscape($addr2line, \"--demangle\", \"-f\", \"-C\", \"-e\", $image);\n  }\n\n  # If \"addr2line\" isn't installed on the system at all, just use\n  # nm to get what info we can (function names, but not line numbers).\n  if (system(ShellEscape($addr2line, \"--help\") . \" >$dev_null 2>&1\") != 0) {\n    MapSymbolsWithNM($image, $offset, $pclist, $symbols);\n    return;\n  }\n\n  # \"addr2line -i\" can produce a variable number of lines per input\n  # address, with no separator that allows us to tell when data for\n  # the next address starts.  So we find the address for a special\n  # symbol (_fini) and interleave this address between all real\n  # addresses passed to addr2line.  The name of this special symbol\n  # can then be used as a separator.\n  $sep_address = undef;  # May be filled in by MapSymbolsWithNM()\n  my $nm_symbols = {};\n  MapSymbolsWithNM($image, $offset, $pclist, $nm_symbols);\n  if (defined($sep_address)) {\n    # Only add \" -i\" to addr2line if the binary supports it.\n    # addr2line --help returns 0, but not if it sees an unknown flag first.\n    if (system(\"$cmd -i --help >$dev_null 2>&1\") == 0) {\n      $cmd .= \" -i\";\n    } else {\n      $sep_address = undef;   # no need for sep_address if we don't support -i\n    }\n  }\n\n  # Make file with all PC values with intervening 'sep_address' so\n  # that we can reliably detect the end of inlined function list\n  open(ADDRESSES, \">$main::tmpfile_sym\") || error(\"$main::tmpfile_sym: $!\\n\");\n  if ($debug) { print(\"---- $image ---\\n\"); }\n  for (my $i = 0; $i <= $#{$pclist}; $i++) {\n    # addr2line always reads hex addresses, and does not need '0x' prefix.\n    if ($debug) { printf STDERR (\"%s\\n\", $pclist->[$i]); }\n    printf ADDRESSES (\"%s\\n\", AddressSub($pclist->[$i], $offset));\n    if (defined($sep_address)) {\n      printf ADDRESSES (\"%s\\n\", $sep_address);\n    }\n  }\n  close(ADDRESSES);\n  if ($debug) {\n    print(\"----\\n\");\n    system(\"cat\", $main::tmpfile_sym);\n    print(\"----\\n\");\n    system(\"$cmd < \" . ShellEscape($main::tmpfile_sym));\n    print(\"----\\n\");\n  }\n\n  open(SYMBOLS, \"$cmd <\" . ShellEscape($main::tmpfile_sym) . \" |\")\n      || error(\"$cmd: $!\\n\");\n  my $count = 0;   # Index in pclist\n  while (<SYMBOLS>) {\n    # Read fullfunction and filelineinfo from next pair of lines\n    s/\\r?\\n$//g;\n    my $fullfunction = $_;\n    $_ = <SYMBOLS>;\n    s/\\r?\\n$//g;\n    my $filelinenum = $_;\n\n    if (defined($sep_address) && $fullfunction eq $sep_symbol) {\n      # Terminating marker for data for this address\n      $count++;\n      next;\n    }\n\n    $filelinenum =~ s|\\\\|/|g; # turn windows-style paths into unix-style paths\n\n    my $pcstr = $pclist->[$count];\n    my $function = ShortFunctionName($fullfunction);\n    my $nms = $nm_symbols->{$pcstr};\n    if (defined($nms)) {\n      if ($fullfunction eq '??') {\n        # nm found a symbol for us.\n        $function = $nms->[0];\n        $fullfunction = $nms->[2];\n      } else {\n\t# MapSymbolsWithNM tags each routine with its starting address,\n\t# useful in case the image has multiple occurrences of this\n\t# routine.  (It uses a syntax that resembles template paramters,\n\t# that are automatically stripped out by ShortFunctionName().)\n\t# addr2line does not provide the same information.  So we check\n\t# if nm disambiguated our symbol, and if so take the annotated\n\t# (nm) version of the routine-name.  TODO(csilvers): this won't\n\t# catch overloaded, inlined symbols, which nm doesn't see.\n\t# Better would be to do a check similar to nm's, in this fn.\n\tif ($nms->[2] =~ m/^\\Q$function\\E/) {  # sanity check it's the right fn\n\t  $function = $nms->[0];\n\t  $fullfunction = $nms->[2];\n\t}\n      }\n    }\n    \n    # Prepend to accumulated symbols for pcstr\n    # (so that caller comes before callee)\n    my $sym = $symbols->{$pcstr};\n    if (!defined($sym)) {\n      $sym = [];\n      $symbols->{$pcstr} = $sym;\n    }\n    unshift(@{$sym}, $function, $filelinenum, $fullfunction);\n    if ($debug) { printf STDERR (\"%s => [%s]\\n\", $pcstr, join(\" \", @{$sym})); }\n    if (!defined($sep_address)) {\n      # Inlining is off, so this entry ends immediately\n      $count++;\n    }\n  }\n  close(SYMBOLS);\n}\n\n# Use nm to map the list of referenced PCs to symbols.  Return true iff we\n# are able to read procedure information via nm.\nsub MapSymbolsWithNM {\n  my $image = shift;\n  my $offset = shift;\n  my $pclist = shift;\n  my $symbols = shift;\n\n  # Get nm output sorted by increasing address\n  my $symbol_table = GetProcedureBoundaries($image, \".\");\n  if (!%{$symbol_table}) {\n    return 0;\n  }\n  # Start addresses are already the right length (8 or 16 hex digits).\n  my @names = sort { $symbol_table->{$a}->[0] cmp $symbol_table->{$b}->[0] }\n    keys(%{$symbol_table});\n\n  if ($#names < 0) {\n    # No symbols: just use addresses\n    foreach my $pc (@{$pclist}) {\n      my $pcstr = \"0x\" . $pc;\n      $symbols->{$pc} = [$pcstr, \"?\", $pcstr];\n    }\n    return 0;\n  }\n\n  # Sort addresses so we can do a join against nm output\n  my $index = 0;\n  my $fullname = $names[0];\n  my $name = ShortFunctionName($fullname);\n  foreach my $pc (sort { $a cmp $b } @{$pclist}) {\n    # Adjust for mapped offset\n    my $mpc = AddressSub($pc, $offset);\n    while (($index < $#names) && ($mpc ge $symbol_table->{$fullname}->[1])){\n      $index++;\n      $fullname = $names[$index];\n      $name = ShortFunctionName($fullname);\n    }\n    if ($mpc lt $symbol_table->{$fullname}->[1]) {\n      $symbols->{$pc} = [$name, \"?\", $fullname];\n    } else {\n      my $pcstr = \"0x\" . $pc;\n      $symbols->{$pc} = [$pcstr, \"?\", $pcstr];\n    }\n  }\n  return 1;\n}\n\nsub ShortFunctionName {\n  my $function = shift;\n  while ($function =~ s/\\([^()]*\\)(\\s*const)?//g) { }   # Argument types\n  while ($function =~ s/<[^<>]*>//g)  { }    # Remove template arguments\n  $function =~ s/^.*\\s+(\\w+::)/$1/;          # Remove leading type\n  return $function;\n}\n\n# Trim overly long symbols found in disassembler output\nsub CleanDisassembly {\n  my $d = shift;\n  while ($d =~ s/\\([^()%]*\\)(\\s*const)?//g) { } # Argument types, not (%rax)\n  while ($d =~ s/(\\w+)<[^<>]*>/$1/g)  { }       # Remove template arguments\n  return $d;\n}\n\n# Clean file name for display\nsub CleanFileName {\n  my ($f) = @_;\n  $f =~ s|^/proc/self/cwd/||;\n  $f =~ s|^\\./||;\n  return $f;\n}\n\n# Make address relative to section and clean up for display\nsub UnparseAddress {\n  my ($offset, $address) = @_;\n  $address = AddressSub($address, $offset);\n  $address =~ s/^0x//;\n  $address =~ s/^0*//;\n  return $address;\n}\n\n##### Miscellaneous #####\n\n# Find the right versions of the above object tools to use.  The\n# argument is the program file being analyzed, and should be an ELF\n# 32-bit or ELF 64-bit executable file.  The location of the tools\n# is determined by considering the following options in this order:\n#   1) --tools option, if set\n#   2) PPROF_TOOLS environment variable, if set\n#   3) the environment\nsub ConfigureObjTools {\n  my $prog_file = shift;\n\n  # Check for the existence of $prog_file because /usr/bin/file does not\n  # predictably return error status in prod.\n  (-e $prog_file)  || error(\"$prog_file does not exist.\\n\");\n\n  my $file_type = undef;\n  if (-e \"/usr/bin/file\") {\n    # Follow symlinks (at least for systems where \"file\" supports that).\n    my $escaped_prog_file = ShellEscape($prog_file);\n    $file_type = `/usr/bin/file -L $escaped_prog_file 2>$dev_null ||\n                  /usr/bin/file $escaped_prog_file`;\n  } elsif ($^O == \"MSWin32\") {\n    $file_type = \"MS Windows\";\n  } else {\n    print STDERR \"WARNING: Can't determine the file type of $prog_file\";\n  }\n\n  if ($file_type =~ /64-bit/) {\n    # Change $address_length to 16 if the program file is ELF 64-bit.\n    # We can't detect this from many (most?) heap or lock contention\n    # profiles, since the actual addresses referenced are generally in low\n    # memory even for 64-bit programs.\n    $address_length = 16;\n  }\n\n  if ($file_type =~ /MS Windows/) {\n    # For windows, we provide a version of nm and addr2line as part of\n    # the opensource release, which is capable of parsing\n    # Windows-style PDB executables.  It should live in the path, or\n    # in the same directory as pprof.\n    $obj_tool_map{\"nm_pdb\"} = \"nm-pdb\";\n    $obj_tool_map{\"addr2line_pdb\"} = \"addr2line-pdb\";\n  }\n\n  if ($file_type =~ /Mach-O/) {\n    # OS X uses otool to examine Mach-O files, rather than objdump.\n    $obj_tool_map{\"otool\"} = \"otool\";\n    $obj_tool_map{\"addr2line\"} = \"false\";  # no addr2line\n    $obj_tool_map{\"objdump\"} = \"false\";  # no objdump\n  }\n\n  # Go fill in %obj_tool_map with the pathnames to use:\n  foreach my $tool (keys %obj_tool_map) {\n    $obj_tool_map{$tool} = ConfigureTool($obj_tool_map{$tool});\n  }\n}\n\n# Returns the path of a caller-specified object tool.  If --tools or\n# PPROF_TOOLS are specified, then returns the full path to the tool\n# with that prefix.  Otherwise, returns the path unmodified (which\n# means we will look for it on PATH).\nsub ConfigureTool {\n  my $tool = shift;\n  my $path;\n\n  # --tools (or $PPROF_TOOLS) is a comma separated list, where each\n  # item is either a) a pathname prefix, or b) a map of the form\n  # <tool>:<path>.  First we look for an entry of type (b) for our\n  # tool.  If one is found, we use it.  Otherwise, we consider all the\n  # pathname prefixes in turn, until one yields an existing file.  If\n  # none does, we use a default path.\n  my $tools = $main::opt_tools || $ENV{\"PPROF_TOOLS\"} || \"\";\n  if ($tools =~ m/(,|^)\\Q$tool\\E:([^,]*)/) {\n    $path = $2;\n    # TODO(csilvers): sanity-check that $path exists?  Hard if it's relative.\n  } elsif ($tools ne '') {\n    foreach my $prefix (split(',', $tools)) {\n      next if ($prefix =~ /:/);    # ignore \"tool:fullpath\" entries in the list\n      if (-x $prefix . $tool) {\n        $path = $prefix . $tool;\n        last;\n      }\n    }\n    if (!$path) {\n      error(\"No '$tool' found with prefix specified by \" .\n            \"--tools (or \\$PPROF_TOOLS) '$tools'\\n\");\n    }\n  } else {\n    # ... otherwise use the version that exists in the same directory as\n    # pprof.  If there's nothing there, use $PATH.\n    $0 =~ m,[^/]*$,;     # this is everything after the last slash\n    my $dirname = $`;    # this is everything up to and including the last slash\n    if (-x \"$dirname$tool\") {\n      $path = \"$dirname$tool\";\n    } else { \n      $path = $tool;\n    }\n  }\n  if ($main::opt_debug) { print STDERR \"Using '$path' for '$tool'.\\n\"; }\n  return $path;\n}\n\nsub ShellEscape {\n  my @escaped_words = ();\n  foreach my $word (@_) {\n    my $escaped_word = $word;\n    if ($word =~ m![^a-zA-Z0-9/.,_=-]!) {  # check for anything not in whitelist\n      $escaped_word =~ s/'/'\\\\''/;\n      $escaped_word = \"'$escaped_word'\";\n    }\n    push(@escaped_words, $escaped_word);\n  }\n  return join(\" \", @escaped_words);\n}\n\nsub cleanup {\n  unlink($main::tmpfile_sym);\n  unlink(keys %main::tempnames);\n\n  # We leave any collected profiles in $HOME/pprof in case the user wants\n  # to look at them later.  We print a message informing them of this.\n  if ((scalar(@main::profile_files) > 0) &&\n      defined($main::collected_profile)) {\n    if (scalar(@main::profile_files) == 1) {\n      print STDERR \"Dynamically gathered profile is in $main::collected_profile\\n\";\n    }\n    print STDERR \"If you want to investigate this profile further, you can do:\\n\";\n    print STDERR \"\\n\";\n    print STDERR \"  pprof \\\\\\n\";\n    print STDERR \"    $main::prog \\\\\\n\";\n    print STDERR \"    $main::collected_profile\\n\";\n    print STDERR \"\\n\";\n  }\n}\n\nsub sighandler {\n  cleanup();\n  exit(1);\n}\n\nsub error {\n  my $msg = shift;\n  print STDERR $msg;\n  cleanup();\n  exit(1);\n}\n\n\n# Run $nm_command and get all the resulting procedure boundaries whose\n# names match \"$regexp\" and returns them in a hashtable mapping from\n# procedure name to a two-element vector of [start address, end address]\nsub GetProcedureBoundariesViaNm {\n  my $escaped_nm_command = shift;    # shell-escaped\n  my $regexp = shift;\n\n  my $symbol_table = {};\n  open(NM, \"$escaped_nm_command |\") || error(\"$escaped_nm_command: $!\\n\");\n  my $last_start = \"0\";\n  my $routine = \"\";\n  while (<NM>) {\n    s/\\r//g;         # turn windows-looking lines into unix-looking lines\n    if (m/^\\s*([0-9a-f]+) (.) (..*)/) {\n      my $start_val = $1;\n      my $type = $2;\n      my $this_routine = $3;\n\n      # It's possible for two symbols to share the same address, if\n      # one is a zero-length variable (like __start_google_malloc) or\n      # one symbol is a weak alias to another (like __libc_malloc).\n      # In such cases, we want to ignore all values except for the\n      # actual symbol, which in nm-speak has type \"T\".  The logic\n      # below does this, though it's a bit tricky: what happens when\n      # we have a series of lines with the same address, is the first\n      # one gets queued up to be processed.  However, it won't\n      # *actually* be processed until later, when we read a line with\n      # a different address.  That means that as long as we're reading\n      # lines with the same address, we have a chance to replace that\n      # item in the queue, which we do whenever we see a 'T' entry --\n      # that is, a line with type 'T'.  If we never see a 'T' entry,\n      # we'll just go ahead and process the first entry (which never\n      # got touched in the queue), and ignore the others.\n      if ($start_val eq $last_start && $type =~ /t/i) {\n        # We are the 'T' symbol at this address, replace previous symbol.\n        $routine = $this_routine;\n        next;\n      } elsif ($start_val eq $last_start) {\n        # We're not the 'T' symbol at this address, so ignore us.\n        next;\n      }\n\n      if ($this_routine eq $sep_symbol) {\n        $sep_address = HexExtend($start_val);\n      }\n\n      # Tag this routine with the starting address in case the image\n      # has multiple occurrences of this routine.  We use a syntax\n      # that resembles template parameters that are automatically\n      # stripped out by ShortFunctionName()\n      $this_routine .= \"<$start_val>\";\n\n      if (defined($routine) && $routine =~ m/$regexp/) {\n        $symbol_table->{$routine} = [HexExtend($last_start),\n                                     HexExtend($start_val)];\n      }\n      $last_start = $start_val;\n      $routine = $this_routine;\n    } elsif (m/^Loaded image name: (.+)/) {\n      # The win32 nm workalike emits information about the binary it is using.\n      if ($main::opt_debug) { print STDERR \"Using Image $1\\n\"; }\n    } elsif (m/^PDB file name: (.+)/) {\n      # The win32 nm workalike emits information about the pdb it is using.\n      if ($main::opt_debug) { print STDERR \"Using PDB $1\\n\"; }\n    }\n  }\n  close(NM);\n  # Handle the last line in the nm output.  Unfortunately, we don't know\n  # how big this last symbol is, because we don't know how big the file\n  # is.  For now, we just give it a size of 0.\n  # TODO(csilvers): do better here.\n  if (defined($routine) && $routine =~ m/$regexp/) {\n    $symbol_table->{$routine} = [HexExtend($last_start),\n                                 HexExtend($last_start)];\n  }\n  return $symbol_table;\n}\n\n# Gets the procedure boundaries for all routines in \"$image\" whose names\n# match \"$regexp\" and returns them in a hashtable mapping from procedure\n# name to a two-element vector of [start address, end address].\n# Will return an empty map if nm is not installed or not working properly.\nsub GetProcedureBoundaries {\n  my $image = shift;\n  my $regexp = shift;\n\n  # If $image doesn't start with /, then put ./ in front of it.  This works\n  # around an obnoxious bug in our probing of nm -f behavior.\n  # \"nm -f $image\" is supposed to fail on GNU nm, but if:\n  #\n  # a. $image starts with [BbSsPp] (for example, bin/foo/bar), AND\n  # b. you have a.out in your current directory (a not uncommon occurence)\n  #\n  # then \"nm -f $image\" succeeds because -f only looks at the first letter of\n  # the argument, which looks valid because it's [BbSsPp], and then since\n  # there's no image provided, it looks for a.out and finds it.\n  #\n  # This regex makes sure that $image starts with . or /, forcing the -f\n  # parsing to fail since . and / are not valid formats.\n  $image =~ s#^[^/]#./$&#;\n\n  # For libc libraries, the copy in /usr/lib/debug contains debugging symbols\n  my $debugging = DebuggingLibrary($image);\n  if ($debugging) {\n    $image = $debugging;\n  }\n\n  my $nm = $obj_tool_map{\"nm\"};\n  my $cppfilt = $obj_tool_map{\"c++filt\"};\n\n  # nm can fail for two reasons: 1) $image isn't a debug library; 2) nm\n  # binary doesn't support --demangle.  In addition, for OS X we need\n  # to use the -f flag to get 'flat' nm output (otherwise we don't sort\n  # properly and get incorrect results).  Unfortunately, GNU nm uses -f\n  # in an incompatible way.  So first we test whether our nm supports\n  # --demangle and -f.\n  my $demangle_flag = \"\";\n  my $cppfilt_flag = \"\";\n  my $to_devnull = \">$dev_null 2>&1\";\n  if (system(ShellEscape($nm, \"--demangle\", \"image\") . $to_devnull) == 0) {\n    # In this mode, we do \"nm --demangle <foo>\"\n    $demangle_flag = \"--demangle\";\n    $cppfilt_flag = \"\";\n  } elsif (system(ShellEscape($cppfilt, $image) . $to_devnull) == 0) {\n    # In this mode, we do \"nm <foo> | c++filt\"\n    $cppfilt_flag = \" | \" . ShellEscape($cppfilt);\n  };\n  my $flatten_flag = \"\";\n  if (system(ShellEscape($nm, \"-f\", $image) . $to_devnull) == 0) {\n    $flatten_flag = \"-f\";\n  }\n\n  # Finally, in the case $imagie isn't a debug library, we try again with\n  # -D to at least get *exported* symbols.  If we can't use --demangle,\n  # we use c++filt instead, if it exists on this system.\n  my @nm_commands = (ShellEscape($nm, \"-n\", $flatten_flag, $demangle_flag,\n                                 $image) . \" 2>$dev_null $cppfilt_flag\",\n                     ShellEscape($nm, \"-D\", \"-n\", $flatten_flag, $demangle_flag,\n                                 $image) . \" 2>$dev_null $cppfilt_flag\",\n                     # 6nm is for Go binaries\n                     ShellEscape(\"6nm\", \"$image\") . \" 2>$dev_null | sort\",\n                     );\n\n  # If the executable is an MS Windows PDB-format executable, we'll\n  # have set up obj_tool_map(\"nm_pdb\").  In this case, we actually\n  # want to use both unix nm and windows-specific nm_pdb, since\n  # PDB-format executables can apparently include dwarf .o files.\n  if (exists $obj_tool_map{\"nm_pdb\"}) {\n    push(@nm_commands,\n         ShellEscape($obj_tool_map{\"nm_pdb\"}, \"--demangle\", $image)\n         . \" 2>$dev_null\");\n  }\n\n  foreach my $nm_command (@nm_commands) {\n    my $symbol_table = GetProcedureBoundariesViaNm($nm_command, $regexp);\n    return $symbol_table if (%{$symbol_table});\n  }\n  my $symbol_table = {};\n  return $symbol_table;\n}\n\n\n# The test vectors for AddressAdd/Sub/Inc are 8-16-nibble hex strings.\n# To make them more readable, we add underscores at interesting places.\n# This routine removes the underscores, producing the canonical representation\n# used by pprof to represent addresses, particularly in the tested routines.\nsub CanonicalHex {\n  my $arg = shift;\n  return join '', (split '_',$arg);\n}\n\n\n# Unit test for AddressAdd:\nsub AddressAddUnitTest {\n  my $test_data_8 = shift;\n  my $test_data_16 = shift;\n  my $error_count = 0;\n  my $fail_count = 0;\n  my $pass_count = 0;\n  # print STDERR \"AddressAddUnitTest: \", 1+$#{$test_data_8}, \" tests\\n\";\n\n  # First a few 8-nibble addresses.  Note that this implementation uses\n  # plain old arithmetic, so a quick sanity check along with verifying what\n  # happens to overflow (we want it to wrap):\n  $address_length = 8;\n  foreach my $row (@{$test_data_8}) {\n    if ($main::opt_debug and $main::opt_test) { print STDERR \"@{$row}\\n\"; }\n    my $sum = AddressAdd ($row->[0], $row->[1]);\n    if ($sum ne $row->[2]) {\n      printf STDERR \"ERROR: %s != %s + %s = %s\\n\", $sum,\n             $row->[0], $row->[1], $row->[2];\n      ++$fail_count;\n    } else {\n      ++$pass_count;\n    }\n  }\n  printf STDERR \"AddressAdd 32-bit tests: %d passes, %d failures\\n\",\n         $pass_count, $fail_count;\n  $error_count = $fail_count;\n  $fail_count = 0;\n  $pass_count = 0;\n\n  # Now 16-nibble addresses.\n  $address_length = 16;\n  foreach my $row (@{$test_data_16}) {\n    if ($main::opt_debug and $main::opt_test) { print STDERR \"@{$row}\\n\"; }\n    my $sum = AddressAdd (CanonicalHex($row->[0]), CanonicalHex($row->[1]));\n    my $expected = join '', (split '_',$row->[2]);\n    if ($sum ne CanonicalHex($row->[2])) {\n      printf STDERR \"ERROR: %s != %s + %s = %s\\n\", $sum,\n             $row->[0], $row->[1], $row->[2];\n      ++$fail_count;\n    } else {\n      ++$pass_count;\n    }\n  }\n  printf STDERR \"AddressAdd 64-bit tests: %d passes, %d failures\\n\",\n         $pass_count, $fail_count;\n  $error_count += $fail_count;\n\n  return $error_count;\n}\n\n\n# Unit test for AddressSub:\nsub AddressSubUnitTest {\n  my $test_data_8 = shift;\n  my $test_data_16 = shift;\n  my $error_count = 0;\n  my $fail_count = 0;\n  my $pass_count = 0;\n  # print STDERR \"AddressSubUnitTest: \", 1+$#{$test_data_8}, \" tests\\n\";\n\n  # First a few 8-nibble addresses.  Note that this implementation uses\n  # plain old arithmetic, so a quick sanity check along with verifying what\n  # happens to overflow (we want it to wrap):\n  $address_length = 8;\n  foreach my $row (@{$test_data_8}) {\n    if ($main::opt_debug and $main::opt_test) { print STDERR \"@{$row}\\n\"; }\n    my $sum = AddressSub ($row->[0], $row->[1]);\n    if ($sum ne $row->[3]) {\n      printf STDERR \"ERROR: %s != %s - %s = %s\\n\", $sum,\n             $row->[0], $row->[1], $row->[3];\n      ++$fail_count;\n    } else {\n      ++$pass_count;\n    }\n  }\n  printf STDERR \"AddressSub 32-bit tests: %d passes, %d failures\\n\",\n         $pass_count, $fail_count;\n  $error_count = $fail_count;\n  $fail_count = 0;\n  $pass_count = 0;\n\n  # Now 16-nibble addresses.\n  $address_length = 16;\n  foreach my $row (@{$test_data_16}) {\n    if ($main::opt_debug and $main::opt_test) { print STDERR \"@{$row}\\n\"; }\n    my $sum = AddressSub (CanonicalHex($row->[0]), CanonicalHex($row->[1]));\n    if ($sum ne CanonicalHex($row->[3])) {\n      printf STDERR \"ERROR: %s != %s - %s = %s\\n\", $sum,\n             $row->[0], $row->[1], $row->[3];\n      ++$fail_count;\n    } else {\n      ++$pass_count;\n    }\n  }\n  printf STDERR \"AddressSub 64-bit tests: %d passes, %d failures\\n\",\n         $pass_count, $fail_count;\n  $error_count += $fail_count;\n\n  return $error_count;\n}\n\n\n# Unit test for AddressInc:\nsub AddressIncUnitTest {\n  my $test_data_8 = shift;\n  my $test_data_16 = shift;\n  my $error_count = 0;\n  my $fail_count = 0;\n  my $pass_count = 0;\n  # print STDERR \"AddressIncUnitTest: \", 1+$#{$test_data_8}, \" tests\\n\";\n\n  # First a few 8-nibble addresses.  Note that this implementation uses\n  # plain old arithmetic, so a quick sanity check along with verifying what\n  # happens to overflow (we want it to wrap):\n  $address_length = 8;\n  foreach my $row (@{$test_data_8}) {\n    if ($main::opt_debug and $main::opt_test) { print STDERR \"@{$row}\\n\"; }\n    my $sum = AddressInc ($row->[0]);\n    if ($sum ne $row->[4]) {\n      printf STDERR \"ERROR: %s != %s + 1 = %s\\n\", $sum,\n             $row->[0], $row->[4];\n      ++$fail_count;\n    } else {\n      ++$pass_count;\n    }\n  }\n  printf STDERR \"AddressInc 32-bit tests: %d passes, %d failures\\n\",\n         $pass_count, $fail_count;\n  $error_count = $fail_count;\n  $fail_count = 0;\n  $pass_count = 0;\n\n  # Now 16-nibble addresses.\n  $address_length = 16;\n  foreach my $row (@{$test_data_16}) {\n    if ($main::opt_debug and $main::opt_test) { print STDERR \"@{$row}\\n\"; }\n    my $sum = AddressInc (CanonicalHex($row->[0]));\n    if ($sum ne CanonicalHex($row->[4])) {\n      printf STDERR \"ERROR: %s != %s + 1 = %s\\n\", $sum,\n             $row->[0], $row->[4];\n      ++$fail_count;\n    } else {\n      ++$pass_count;\n    }\n  }\n  printf STDERR \"AddressInc 64-bit tests: %d passes, %d failures\\n\",\n         $pass_count, $fail_count;\n  $error_count += $fail_count;\n\n  return $error_count;\n}\n\n\n# Driver for unit tests.\n# Currently just the address add/subtract/increment routines for 64-bit.\nsub RunUnitTests {\n  my $error_count = 0;\n\n  # This is a list of tuples [a, b, a+b, a-b, a+1]\n  my $unit_test_data_8 = [\n    [qw(aaaaaaaa 50505050 fafafafa 5a5a5a5a aaaaaaab)],\n    [qw(50505050 aaaaaaaa fafafafa a5a5a5a6 50505051)],\n    [qw(ffffffff aaaaaaaa aaaaaaa9 55555555 00000000)],\n    [qw(00000001 ffffffff 00000000 00000002 00000002)],\n    [qw(00000001 fffffff0 fffffff1 00000011 00000002)],\n  ];\n  my $unit_test_data_16 = [\n    # The implementation handles data in 7-nibble chunks, so those are the\n    # interesting boundaries.\n    [qw(aaaaaaaa 50505050\n        00_000000f_afafafa 00_0000005_a5a5a5a 00_000000a_aaaaaab)],\n    [qw(50505050 aaaaaaaa\n        00_000000f_afafafa ff_ffffffa_5a5a5a6 00_0000005_0505051)],\n    [qw(ffffffff aaaaaaaa\n        00_000001a_aaaaaa9 00_0000005_5555555 00_0000010_0000000)],\n    [qw(00000001 ffffffff\n        00_0000010_0000000 ff_ffffff0_0000002 00_0000000_0000002)],\n    [qw(00000001 fffffff0\n        00_000000f_ffffff1 ff_ffffff0_0000011 00_0000000_0000002)],\n\n    [qw(00_a00000a_aaaaaaa 50505050\n        00_a00000f_afafafa 00_a000005_a5a5a5a 00_a00000a_aaaaaab)],\n    [qw(0f_fff0005_0505050 aaaaaaaa\n        0f_fff000f_afafafa 0f_ffefffa_5a5a5a6 0f_fff0005_0505051)],\n    [qw(00_000000f_fffffff 01_800000a_aaaaaaa\n        01_800001a_aaaaaa9 fe_8000005_5555555 00_0000010_0000000)],\n    [qw(00_0000000_0000001 ff_fffffff_fffffff\n        00_0000000_0000000 00_0000000_0000002 00_0000000_0000002)],\n    [qw(00_0000000_0000001 ff_fffffff_ffffff0\n        ff_fffffff_ffffff1 00_0000000_0000011 00_0000000_0000002)],\n  ];\n\n  $error_count += AddressAddUnitTest($unit_test_data_8, $unit_test_data_16);\n  $error_count += AddressSubUnitTest($unit_test_data_8, $unit_test_data_16);\n  $error_count += AddressIncUnitTest($unit_test_data_8, $unit_test_data_16);\n  if ($error_count > 0) {\n    print STDERR $error_count, \" errors: FAILED\\n\";\n  } else {\n    print STDERR \"PASS\\n\";\n  }\n  exit ($error_count);\n}\n"
  },
  {
    "path": "extern/deprecated/redis-2.8.21/deps/jemalloc/config.guess",
    "content": "#! /bin/sh\n# Attempt to guess a canonical system name.\n#   Copyright 1992-2013 Free Software Foundation, Inc.\n\ntimestamp='2013-06-10'\n\n# This file is free software; you can redistribute it and/or modify it\n# under the terms of the GNU General Public License as published by\n# the Free Software Foundation; either version 3 of the License, or\n# (at your option) any later version.\n#\n# This program is distributed in the hope that it will be useful, but\n# WITHOUT ANY WARRANTY; without even the implied warranty of\n# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n# General Public License for more details.\n#\n# You should have received a copy of the GNU General Public License\n# along with this program; if not, see <http://www.gnu.org/licenses/>.\n#\n# As a special exception to the GNU General Public License, if you\n# distribute this file as part of a program that contains a\n# configuration script generated by Autoconf, you may include it under\n# the same distribution terms that you use for the rest of that\n# program.  This Exception is an additional permission under section 7\n# of the GNU General Public License, version 3 (\"GPLv3\").\n#\n# Originally written by Per Bothner.\n#\n# You can get the latest version of this script from:\n# http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.guess;hb=HEAD\n#\n# Please send patches with a ChangeLog entry to config-patches@gnu.org.\n\n\nme=`echo \"$0\" | sed -e 's,.*/,,'`\n\nusage=\"\\\nUsage: $0 [OPTION]\n\nOutput the configuration name of the system \\`$me' is run on.\n\nOperation modes:\n  -h, --help         print this help, then exit\n  -t, --time-stamp   print date of last modification, then exit\n  -v, --version      print version number, then exit\n\nReport bugs and patches to <config-patches@gnu.org>.\"\n\nversion=\"\\\nGNU config.guess ($timestamp)\n\nOriginally written by Per Bothner.\nCopyright 1992-2013 Free Software Foundation, Inc.\n\nThis is free software; see the source for copying conditions.  There is NO\nwarranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\"\n\nhelp=\"\nTry \\`$me --help' for more information.\"\n\n# Parse command line\nwhile test $# -gt 0 ; do\n  case $1 in\n    --time-stamp | --time* | -t )\n       echo \"$timestamp\" ; exit ;;\n    --version | -v )\n       echo \"$version\" ; exit ;;\n    --help | --h* | -h )\n       echo \"$usage\"; exit ;;\n    -- )     # Stop option processing\n       shift; break ;;\n    - )\t# Use stdin as input.\n       break ;;\n    -* )\n       echo \"$me: invalid option $1$help\" >&2\n       exit 1 ;;\n    * )\n       break ;;\n  esac\ndone\n\nif test $# != 0; then\n  echo \"$me: too many arguments$help\" >&2\n  exit 1\nfi\n\ntrap 'exit 1' 1 2 15\n\n# CC_FOR_BUILD -- compiler used by this script. Note that the use of a\n# compiler to aid in system detection is discouraged as it requires\n# temporary files to be created and, as you can see below, it is a\n# headache to deal with in a portable fashion.\n\n# Historically, `CC_FOR_BUILD' used to be named `HOST_CC'. We still\n# use `HOST_CC' if defined, but it is deprecated.\n\n# Portable tmp directory creation inspired by the Autoconf team.\n\nset_cc_for_build='\ntrap \"exitcode=\\$?; (rm -f \\$tmpfiles 2>/dev/null; rmdir \\$tmp 2>/dev/null) && exit \\$exitcode\" 0 ;\ntrap \"rm -f \\$tmpfiles 2>/dev/null; rmdir \\$tmp 2>/dev/null; exit 1\" 1 2 13 15 ;\n: ${TMPDIR=/tmp} ;\n { tmp=`(umask 077 && mktemp -d \"$TMPDIR/cgXXXXXX\") 2>/dev/null` && test -n \"$tmp\" && test -d \"$tmp\" ; } ||\n { test -n \"$RANDOM\" && tmp=$TMPDIR/cg$$-$RANDOM && (umask 077 && mkdir $tmp) ; } ||\n { tmp=$TMPDIR/cg-$$ && (umask 077 && mkdir $tmp) && echo \"Warning: creating insecure temp directory\" >&2 ; } ||\n { echo \"$me: cannot create a temporary directory in $TMPDIR\" >&2 ; exit 1 ; } ;\ndummy=$tmp/dummy ;\ntmpfiles=\"$dummy.c $dummy.o $dummy.rel $dummy\" ;\ncase $CC_FOR_BUILD,$HOST_CC,$CC in\n ,,)    echo \"int x;\" > $dummy.c ;\n\tfor c in cc gcc c89 c99 ; do\n\t  if ($c -c -o $dummy.o $dummy.c) >/dev/null 2>&1 ; then\n\t     CC_FOR_BUILD=\"$c\"; break ;\n\t  fi ;\n\tdone ;\n\tif test x\"$CC_FOR_BUILD\" = x ; then\n\t  CC_FOR_BUILD=no_compiler_found ;\n\tfi\n\t;;\n ,,*)   CC_FOR_BUILD=$CC ;;\n ,*,*)  CC_FOR_BUILD=$HOST_CC ;;\nesac ; set_cc_for_build= ;'\n\n# This is needed to find uname on a Pyramid OSx when run in the BSD universe.\n# (ghazi@noc.rutgers.edu 1994-08-24)\nif (test -f /.attbin/uname) >/dev/null 2>&1 ; then\n\tPATH=$PATH:/.attbin ; export PATH\nfi\n\nUNAME_MACHINE=`(uname -m) 2>/dev/null` || UNAME_MACHINE=unknown\nUNAME_RELEASE=`(uname -r) 2>/dev/null` || UNAME_RELEASE=unknown\nUNAME_SYSTEM=`(uname -s) 2>/dev/null`  || UNAME_SYSTEM=unknown\nUNAME_VERSION=`(uname -v) 2>/dev/null` || UNAME_VERSION=unknown\n\ncase \"${UNAME_SYSTEM}\" in\nLinux|GNU|GNU/*)\n\t# If the system lacks a compiler, then just pick glibc.\n\t# We could probably try harder.\n\tLIBC=gnu\n\n\teval $set_cc_for_build\n\tcat <<-EOF > $dummy.c\n\t#include <features.h>\n\t#if defined(__UCLIBC__)\n\tLIBC=uclibc\n\t#elif defined(__dietlibc__)\n\tLIBC=dietlibc\n\t#else\n\tLIBC=gnu\n\t#endif\n\tEOF\n\teval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep '^LIBC'`\n\t;;\nesac\n\n# Note: order is significant - the case branches are not exclusive.\n\ncase \"${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}\" in\n    *:NetBSD:*:*)\n\t# NetBSD (nbsd) targets should (where applicable) match one or\n\t# more of the tuples: *-*-netbsdelf*, *-*-netbsdaout*,\n\t# *-*-netbsdecoff* and *-*-netbsd*.  For targets that recently\n\t# switched to ELF, *-*-netbsd* would select the old\n\t# object file format.  This provides both forward\n\t# compatibility and a consistent mechanism for selecting the\n\t# object file format.\n\t#\n\t# Note: NetBSD doesn't particularly care about the vendor\n\t# portion of the name.  We always set it to \"unknown\".\n\tsysctl=\"sysctl -n hw.machine_arch\"\n\tUNAME_MACHINE_ARCH=`(/sbin/$sysctl 2>/dev/null || \\\n\t    /usr/sbin/$sysctl 2>/dev/null || echo unknown)`\n\tcase \"${UNAME_MACHINE_ARCH}\" in\n\t    armeb) machine=armeb-unknown ;;\n\t    arm*) machine=arm-unknown ;;\n\t    sh3el) machine=shl-unknown ;;\n\t    sh3eb) machine=sh-unknown ;;\n\t    sh5el) machine=sh5le-unknown ;;\n\t    *) machine=${UNAME_MACHINE_ARCH}-unknown ;;\n\tesac\n\t# The Operating System including object format, if it has switched\n\t# to ELF recently, or will in the future.\n\tcase \"${UNAME_MACHINE_ARCH}\" in\n\t    arm*|i386|m68k|ns32k|sh3*|sparc|vax)\n\t\teval $set_cc_for_build\n\t\tif echo __ELF__ | $CC_FOR_BUILD -E - 2>/dev/null \\\n\t\t\t| grep -q __ELF__\n\t\tthen\n\t\t    # Once all utilities can be ECOFF (netbsdecoff) or a.out (netbsdaout).\n\t\t    # Return netbsd for either.  FIX?\n\t\t    os=netbsd\n\t\telse\n\t\t    os=netbsdelf\n\t\tfi\n\t\t;;\n\t    *)\n\t\tos=netbsd\n\t\t;;\n\tesac\n\t# The OS release\n\t# Debian GNU/NetBSD machines have a different userland, and\n\t# thus, need a distinct triplet. However, they do not need\n\t# kernel version information, so it can be replaced with a\n\t# suitable tag, in the style of linux-gnu.\n\tcase \"${UNAME_VERSION}\" in\n\t    Debian*)\n\t\trelease='-gnu'\n\t\t;;\n\t    *)\n\t\trelease=`echo ${UNAME_RELEASE}|sed -e 's/[-_].*/\\./'`\n\t\t;;\n\tesac\n\t# Since CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM:\n\t# contains redundant information, the shorter form:\n\t# CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM is used.\n\techo \"${machine}-${os}${release}\"\n\texit ;;\n    *:Bitrig:*:*)\n\tUNAME_MACHINE_ARCH=`arch | sed 's/Bitrig.//'`\n\techo ${UNAME_MACHINE_ARCH}-unknown-bitrig${UNAME_RELEASE}\n\texit ;;\n    *:OpenBSD:*:*)\n\tUNAME_MACHINE_ARCH=`arch | sed 's/OpenBSD.//'`\n\techo ${UNAME_MACHINE_ARCH}-unknown-openbsd${UNAME_RELEASE}\n\texit ;;\n    *:ekkoBSD:*:*)\n\techo ${UNAME_MACHINE}-unknown-ekkobsd${UNAME_RELEASE}\n\texit ;;\n    *:SolidBSD:*:*)\n\techo ${UNAME_MACHINE}-unknown-solidbsd${UNAME_RELEASE}\n\texit ;;\n    macppc:MirBSD:*:*)\n\techo powerpc-unknown-mirbsd${UNAME_RELEASE}\n\texit ;;\n    *:MirBSD:*:*)\n\techo ${UNAME_MACHINE}-unknown-mirbsd${UNAME_RELEASE}\n\texit ;;\n    alpha:OSF1:*:*)\n\tcase $UNAME_RELEASE in\n\t*4.0)\n\t\tUNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $3}'`\n\t\t;;\n\t*5.*)\n\t\tUNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $4}'`\n\t\t;;\n\tesac\n\t# According to Compaq, /usr/sbin/psrinfo has been available on\n\t# OSF/1 and Tru64 systems produced since 1995.  I hope that\n\t# covers most systems running today.  This code pipes the CPU\n\t# types through head -n 1, so we only detect the type of CPU 0.\n\tALPHA_CPU_TYPE=`/usr/sbin/psrinfo -v | sed -n -e 's/^  The alpha \\(.*\\) processor.*$/\\1/p' | head -n 1`\n\tcase \"$ALPHA_CPU_TYPE\" in\n\t    \"EV4 (21064)\")\n\t\tUNAME_MACHINE=\"alpha\" ;;\n\t    \"EV4.5 (21064)\")\n\t\tUNAME_MACHINE=\"alpha\" ;;\n\t    \"LCA4 (21066/21068)\")\n\t\tUNAME_MACHINE=\"alpha\" ;;\n\t    \"EV5 (21164)\")\n\t\tUNAME_MACHINE=\"alphaev5\" ;;\n\t    \"EV5.6 (21164A)\")\n\t\tUNAME_MACHINE=\"alphaev56\" ;;\n\t    \"EV5.6 (21164PC)\")\n\t\tUNAME_MACHINE=\"alphapca56\" ;;\n\t    \"EV5.7 (21164PC)\")\n\t\tUNAME_MACHINE=\"alphapca57\" ;;\n\t    \"EV6 (21264)\")\n\t\tUNAME_MACHINE=\"alphaev6\" ;;\n\t    \"EV6.7 (21264A)\")\n\t\tUNAME_MACHINE=\"alphaev67\" ;;\n\t    \"EV6.8CB (21264C)\")\n\t\tUNAME_MACHINE=\"alphaev68\" ;;\n\t    \"EV6.8AL (21264B)\")\n\t\tUNAME_MACHINE=\"alphaev68\" ;;\n\t    \"EV6.8CX (21264D)\")\n\t\tUNAME_MACHINE=\"alphaev68\" ;;\n\t    \"EV6.9A (21264/EV69A)\")\n\t\tUNAME_MACHINE=\"alphaev69\" ;;\n\t    \"EV7 (21364)\")\n\t\tUNAME_MACHINE=\"alphaev7\" ;;\n\t    \"EV7.9 (21364A)\")\n\t\tUNAME_MACHINE=\"alphaev79\" ;;\n\tesac\n\t# A Pn.n version is a patched version.\n\t# A Vn.n version is a released version.\n\t# A Tn.n version is a released field test version.\n\t# A Xn.n version is an unreleased experimental baselevel.\n\t# 1.2 uses \"1.2\" for uname -r.\n\techo ${UNAME_MACHINE}-dec-osf`echo ${UNAME_RELEASE} | sed -e 's/^[PVTX]//' | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'`\n\t# Reset EXIT trap before exiting to avoid spurious non-zero exit code.\n\texitcode=$?\n\ttrap '' 0\n\texit $exitcode ;;\n    Alpha\\ *:Windows_NT*:*)\n\t# How do we know it's Interix rather than the generic POSIX subsystem?\n\t# Should we change UNAME_MACHINE based on the output of uname instead\n\t# of the specific Alpha model?\n\techo alpha-pc-interix\n\texit ;;\n    21064:Windows_NT:50:3)\n\techo alpha-dec-winnt3.5\n\texit ;;\n    Amiga*:UNIX_System_V:4.0:*)\n\techo m68k-unknown-sysv4\n\texit ;;\n    *:[Aa]miga[Oo][Ss]:*:*)\n\techo ${UNAME_MACHINE}-unknown-amigaos\n\texit ;;\n    *:[Mm]orph[Oo][Ss]:*:*)\n\techo ${UNAME_MACHINE}-unknown-morphos\n\texit ;;\n    *:OS/390:*:*)\n\techo i370-ibm-openedition\n\texit ;;\n    *:z/VM:*:*)\n\techo s390-ibm-zvmoe\n\texit ;;\n    *:OS400:*:*)\n\techo powerpc-ibm-os400\n\texit ;;\n    arm:RISC*:1.[012]*:*|arm:riscix:1.[012]*:*)\n\techo arm-acorn-riscix${UNAME_RELEASE}\n\texit ;;\n    arm*:riscos:*:*|arm*:RISCOS:*:*)\n\techo arm-unknown-riscos\n\texit ;;\n    SR2?01:HI-UX/MPP:*:* | SR8000:HI-UX/MPP:*:*)\n\techo hppa1.1-hitachi-hiuxmpp\n\texit ;;\n    Pyramid*:OSx*:*:* | MIS*:OSx*:*:* | MIS*:SMP_DC-OSx*:*:*)\n\t# akee@wpdis03.wpafb.af.mil (Earle F. Ake) contributed MIS and NILE.\n\tif test \"`(/bin/universe) 2>/dev/null`\" = att ; then\n\t\techo pyramid-pyramid-sysv3\n\telse\n\t\techo pyramid-pyramid-bsd\n\tfi\n\texit ;;\n    NILE*:*:*:dcosx)\n\techo pyramid-pyramid-svr4\n\texit ;;\n    DRS?6000:unix:4.0:6*)\n\techo sparc-icl-nx6\n\texit ;;\n    DRS?6000:UNIX_SV:4.2*:7* | DRS?6000:isis:4.2*:7*)\n\tcase `/usr/bin/uname -p` in\n\t    sparc) echo sparc-icl-nx7; exit ;;\n\tesac ;;\n    s390x:SunOS:*:*)\n\techo ${UNAME_MACHINE}-ibm-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`\n\texit ;;\n    sun4H:SunOS:5.*:*)\n\techo sparc-hal-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`\n\texit ;;\n    sun4*:SunOS:5.*:* | tadpole*:SunOS:5.*:*)\n\techo sparc-sun-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`\n\texit ;;\n    i86pc:AuroraUX:5.*:* | i86xen:AuroraUX:5.*:*)\n\techo i386-pc-auroraux${UNAME_RELEASE}\n\texit ;;\n    i86pc:SunOS:5.*:* | i86xen:SunOS:5.*:*)\n\teval $set_cc_for_build\n\tSUN_ARCH=\"i386\"\n\t# If there is a compiler, see if it is configured for 64-bit objects.\n\t# Note that the Sun cc does not turn __LP64__ into 1 like gcc does.\n\t# This test works for both compilers.\n\tif [ \"$CC_FOR_BUILD\" != 'no_compiler_found' ]; then\n\t    if (echo '#ifdef __amd64'; echo IS_64BIT_ARCH; echo '#endif') | \\\n\t\t(CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) | \\\n\t\tgrep IS_64BIT_ARCH >/dev/null\n\t    then\n\t\tSUN_ARCH=\"x86_64\"\n\t    fi\n\tfi\n\techo ${SUN_ARCH}-pc-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`\n\texit ;;\n    sun4*:SunOS:6*:*)\n\t# According to config.sub, this is the proper way to canonicalize\n\t# SunOS6.  Hard to guess exactly what SunOS6 will be like, but\n\t# it's likely to be more like Solaris than SunOS4.\n\techo sparc-sun-solaris3`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`\n\texit ;;\n    sun4*:SunOS:*:*)\n\tcase \"`/usr/bin/arch -k`\" in\n\t    Series*|S4*)\n\t\tUNAME_RELEASE=`uname -v`\n\t\t;;\n\tesac\n\t# Japanese Language versions have a version number like `4.1.3-JL'.\n\techo sparc-sun-sunos`echo ${UNAME_RELEASE}|sed -e 's/-/_/'`\n\texit ;;\n    sun3*:SunOS:*:*)\n\techo m68k-sun-sunos${UNAME_RELEASE}\n\texit ;;\n    sun*:*:4.2BSD:*)\n\tUNAME_RELEASE=`(sed 1q /etc/motd | awk '{print substr($5,1,3)}') 2>/dev/null`\n\ttest \"x${UNAME_RELEASE}\" = \"x\" && UNAME_RELEASE=3\n\tcase \"`/bin/arch`\" in\n\t    sun3)\n\t\techo m68k-sun-sunos${UNAME_RELEASE}\n\t\t;;\n\t    sun4)\n\t\techo sparc-sun-sunos${UNAME_RELEASE}\n\t\t;;\n\tesac\n\texit ;;\n    aushp:SunOS:*:*)\n\techo sparc-auspex-sunos${UNAME_RELEASE}\n\texit ;;\n    # The situation for MiNT is a little confusing.  The machine name\n    # can be virtually everything (everything which is not\n    # \"atarist\" or \"atariste\" at least should have a processor\n    # > m68000).  The system name ranges from \"MiNT\" over \"FreeMiNT\"\n    # to the lowercase version \"mint\" (or \"freemint\").  Finally\n    # the system name \"TOS\" denotes a system which is actually not\n    # MiNT.  But MiNT is downward compatible to TOS, so this should\n    # be no problem.\n    atarist[e]:*MiNT:*:* | atarist[e]:*mint:*:* | atarist[e]:*TOS:*:*)\n\techo m68k-atari-mint${UNAME_RELEASE}\n\texit ;;\n    atari*:*MiNT:*:* | atari*:*mint:*:* | atarist[e]:*TOS:*:*)\n\techo m68k-atari-mint${UNAME_RELEASE}\n\texit ;;\n    *falcon*:*MiNT:*:* | *falcon*:*mint:*:* | *falcon*:*TOS:*:*)\n\techo m68k-atari-mint${UNAME_RELEASE}\n\texit ;;\n    milan*:*MiNT:*:* | milan*:*mint:*:* | *milan*:*TOS:*:*)\n\techo m68k-milan-mint${UNAME_RELEASE}\n\texit ;;\n    hades*:*MiNT:*:* | hades*:*mint:*:* | *hades*:*TOS:*:*)\n\techo m68k-hades-mint${UNAME_RELEASE}\n\texit ;;\n    *:*MiNT:*:* | *:*mint:*:* | *:*TOS:*:*)\n\techo m68k-unknown-mint${UNAME_RELEASE}\n\texit ;;\n    m68k:machten:*:*)\n\techo m68k-apple-machten${UNAME_RELEASE}\n\texit ;;\n    powerpc:machten:*:*)\n\techo powerpc-apple-machten${UNAME_RELEASE}\n\texit ;;\n    RISC*:Mach:*:*)\n\techo mips-dec-mach_bsd4.3\n\texit ;;\n    RISC*:ULTRIX:*:*)\n\techo mips-dec-ultrix${UNAME_RELEASE}\n\texit ;;\n    VAX*:ULTRIX*:*:*)\n\techo vax-dec-ultrix${UNAME_RELEASE}\n\texit ;;\n    2020:CLIX:*:* | 2430:CLIX:*:*)\n\techo clipper-intergraph-clix${UNAME_RELEASE}\n\texit ;;\n    mips:*:*:UMIPS | mips:*:*:RISCos)\n\teval $set_cc_for_build\n\tsed 's/^\t//' << EOF >$dummy.c\n#ifdef __cplusplus\n#include <stdio.h>  /* for printf() prototype */\n\tint main (int argc, char *argv[]) {\n#else\n\tint main (argc, argv) int argc; char *argv[]; {\n#endif\n\t#if defined (host_mips) && defined (MIPSEB)\n\t#if defined (SYSTYPE_SYSV)\n\t  printf (\"mips-mips-riscos%ssysv\\n\", argv[1]); exit (0);\n\t#endif\n\t#if defined (SYSTYPE_SVR4)\n\t  printf (\"mips-mips-riscos%ssvr4\\n\", argv[1]); exit (0);\n\t#endif\n\t#if defined (SYSTYPE_BSD43) || defined(SYSTYPE_BSD)\n\t  printf (\"mips-mips-riscos%sbsd\\n\", argv[1]); exit (0);\n\t#endif\n\t#endif\n\t  exit (-1);\n\t}\nEOF\n\t$CC_FOR_BUILD -o $dummy $dummy.c &&\n\t  dummyarg=`echo \"${UNAME_RELEASE}\" | sed -n 's/\\([0-9]*\\).*/\\1/p'` &&\n\t  SYSTEM_NAME=`$dummy $dummyarg` &&\n\t    { echo \"$SYSTEM_NAME\"; exit; }\n\techo mips-mips-riscos${UNAME_RELEASE}\n\texit ;;\n    Motorola:PowerMAX_OS:*:*)\n\techo powerpc-motorola-powermax\n\texit ;;\n    Motorola:*:4.3:PL8-*)\n\techo powerpc-harris-powermax\n\texit ;;\n    Night_Hawk:*:*:PowerMAX_OS | Synergy:PowerMAX_OS:*:*)\n\techo powerpc-harris-powermax\n\texit ;;\n    Night_Hawk:Power_UNIX:*:*)\n\techo powerpc-harris-powerunix\n\texit ;;\n    m88k:CX/UX:7*:*)\n\techo m88k-harris-cxux7\n\texit ;;\n    m88k:*:4*:R4*)\n\techo m88k-motorola-sysv4\n\texit ;;\n    m88k:*:3*:R3*)\n\techo m88k-motorola-sysv3\n\texit ;;\n    AViiON:dgux:*:*)\n\t# DG/UX returns AViiON for all architectures\n\tUNAME_PROCESSOR=`/usr/bin/uname -p`\n\tif [ $UNAME_PROCESSOR = mc88100 ] || [ $UNAME_PROCESSOR = mc88110 ]\n\tthen\n\t    if [ ${TARGET_BINARY_INTERFACE}x = m88kdguxelfx ] || \\\n\t       [ ${TARGET_BINARY_INTERFACE}x = x ]\n\t    then\n\t\techo m88k-dg-dgux${UNAME_RELEASE}\n\t    else\n\t\techo m88k-dg-dguxbcs${UNAME_RELEASE}\n\t    fi\n\telse\n\t    echo i586-dg-dgux${UNAME_RELEASE}\n\tfi\n\texit ;;\n    M88*:DolphinOS:*:*)\t# DolphinOS (SVR3)\n\techo m88k-dolphin-sysv3\n\texit ;;\n    M88*:*:R3*:*)\n\t# Delta 88k system running SVR3\n\techo m88k-motorola-sysv3\n\texit ;;\n    XD88*:*:*:*) # Tektronix XD88 system running UTekV (SVR3)\n\techo m88k-tektronix-sysv3\n\texit ;;\n    Tek43[0-9][0-9]:UTek:*:*) # Tektronix 4300 system running UTek (BSD)\n\techo m68k-tektronix-bsd\n\texit ;;\n    *:IRIX*:*:*)\n\techo mips-sgi-irix`echo ${UNAME_RELEASE}|sed -e 's/-/_/g'`\n\texit ;;\n    ????????:AIX?:[12].1:2)   # AIX 2.2.1 or AIX 2.1.1 is RT/PC AIX.\n\techo romp-ibm-aix     # uname -m gives an 8 hex-code CPU id\n\texit ;;               # Note that: echo \"'`uname -s`'\" gives 'AIX '\n    i*86:AIX:*:*)\n\techo i386-ibm-aix\n\texit ;;\n    ia64:AIX:*:*)\n\tif [ -x /usr/bin/oslevel ] ; then\n\t\tIBM_REV=`/usr/bin/oslevel`\n\telse\n\t\tIBM_REV=${UNAME_VERSION}.${UNAME_RELEASE}\n\tfi\n\techo ${UNAME_MACHINE}-ibm-aix${IBM_REV}\n\texit ;;\n    *:AIX:2:3)\n\tif grep bos325 /usr/include/stdio.h >/dev/null 2>&1; then\n\t\teval $set_cc_for_build\n\t\tsed 's/^\t\t//' << EOF >$dummy.c\n\t\t#include <sys/systemcfg.h>\n\n\t\tmain()\n\t\t\t{\n\t\t\tif (!__power_pc())\n\t\t\t\texit(1);\n\t\t\tputs(\"powerpc-ibm-aix3.2.5\");\n\t\t\texit(0);\n\t\t\t}\nEOF\n\t\tif $CC_FOR_BUILD -o $dummy $dummy.c && SYSTEM_NAME=`$dummy`\n\t\tthen\n\t\t\techo \"$SYSTEM_NAME\"\n\t\telse\n\t\t\techo rs6000-ibm-aix3.2.5\n\t\tfi\n\telif grep bos324 /usr/include/stdio.h >/dev/null 2>&1; then\n\t\techo rs6000-ibm-aix3.2.4\n\telse\n\t\techo rs6000-ibm-aix3.2\n\tfi\n\texit ;;\n    *:AIX:*:[4567])\n\tIBM_CPU_ID=`/usr/sbin/lsdev -C -c processor -S available | sed 1q | awk '{ print $1 }'`\n\tif /usr/sbin/lsattr -El ${IBM_CPU_ID} | grep ' POWER' >/dev/null 2>&1; then\n\t\tIBM_ARCH=rs6000\n\telse\n\t\tIBM_ARCH=powerpc\n\tfi\n\tif [ -x /usr/bin/oslevel ] ; then\n\t\tIBM_REV=`/usr/bin/oslevel`\n\telse\n\t\tIBM_REV=${UNAME_VERSION}.${UNAME_RELEASE}\n\tfi\n\techo ${IBM_ARCH}-ibm-aix${IBM_REV}\n\texit ;;\n    *:AIX:*:*)\n\techo rs6000-ibm-aix\n\texit ;;\n    ibmrt:4.4BSD:*|romp-ibm:BSD:*)\n\techo romp-ibm-bsd4.4\n\texit ;;\n    ibmrt:*BSD:*|romp-ibm:BSD:*)            # covers RT/PC BSD and\n\techo romp-ibm-bsd${UNAME_RELEASE}   # 4.3 with uname added to\n\texit ;;                             # report: romp-ibm BSD 4.3\n    *:BOSX:*:*)\n\techo rs6000-bull-bosx\n\texit ;;\n    DPX/2?00:B.O.S.:*:*)\n\techo m68k-bull-sysv3\n\texit ;;\n    9000/[34]??:4.3bsd:1.*:*)\n\techo m68k-hp-bsd\n\texit ;;\n    hp300:4.4BSD:*:* | 9000/[34]??:4.3bsd:2.*:*)\n\techo m68k-hp-bsd4.4\n\texit ;;\n    9000/[34678]??:HP-UX:*:*)\n\tHPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'`\n\tcase \"${UNAME_MACHINE}\" in\n\t    9000/31? )            HP_ARCH=m68000 ;;\n\t    9000/[34]?? )         HP_ARCH=m68k ;;\n\t    9000/[678][0-9][0-9])\n\t\tif [ -x /usr/bin/getconf ]; then\n\t\t    sc_cpu_version=`/usr/bin/getconf SC_CPU_VERSION 2>/dev/null`\n\t\t    sc_kernel_bits=`/usr/bin/getconf SC_KERNEL_BITS 2>/dev/null`\n\t\t    case \"${sc_cpu_version}\" in\n\t\t      523) HP_ARCH=\"hppa1.0\" ;; # CPU_PA_RISC1_0\n\t\t      528) HP_ARCH=\"hppa1.1\" ;; # CPU_PA_RISC1_1\n\t\t      532)                      # CPU_PA_RISC2_0\n\t\t\tcase \"${sc_kernel_bits}\" in\n\t\t\t  32) HP_ARCH=\"hppa2.0n\" ;;\n\t\t\t  64) HP_ARCH=\"hppa2.0w\" ;;\n\t\t\t  '') HP_ARCH=\"hppa2.0\" ;;   # HP-UX 10.20\n\t\t\tesac ;;\n\t\t    esac\n\t\tfi\n\t\tif [ \"${HP_ARCH}\" = \"\" ]; then\n\t\t    eval $set_cc_for_build\n\t\t    sed 's/^\t\t//' << EOF >$dummy.c\n\n\t\t#define _HPUX_SOURCE\n\t\t#include <stdlib.h>\n\t\t#include <unistd.h>\n\n\t\tint main ()\n\t\t{\n\t\t#if defined(_SC_KERNEL_BITS)\n\t\t    long bits = sysconf(_SC_KERNEL_BITS);\n\t\t#endif\n\t\t    long cpu  = sysconf (_SC_CPU_VERSION);\n\n\t\t    switch (cpu)\n\t\t\t{\n\t\t\tcase CPU_PA_RISC1_0: puts (\"hppa1.0\"); break;\n\t\t\tcase CPU_PA_RISC1_1: puts (\"hppa1.1\"); break;\n\t\t\tcase CPU_PA_RISC2_0:\n\t\t#if defined(_SC_KERNEL_BITS)\n\t\t\t    switch (bits)\n\t\t\t\t{\n\t\t\t\tcase 64: puts (\"hppa2.0w\"); break;\n\t\t\t\tcase 32: puts (\"hppa2.0n\"); break;\n\t\t\t\tdefault: puts (\"hppa2.0\"); break;\n\t\t\t\t} break;\n\t\t#else  /* !defined(_SC_KERNEL_BITS) */\n\t\t\t    puts (\"hppa2.0\"); break;\n\t\t#endif\n\t\t\tdefault: puts (\"hppa1.0\"); break;\n\t\t\t}\n\t\t    exit (0);\n\t\t}\nEOF\n\t\t    (CCOPTS= $CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null) && HP_ARCH=`$dummy`\n\t\t    test -z \"$HP_ARCH\" && HP_ARCH=hppa\n\t\tfi ;;\n\tesac\n\tif [ ${HP_ARCH} = \"hppa2.0w\" ]\n\tthen\n\t    eval $set_cc_for_build\n\n\t    # hppa2.0w-hp-hpux* has a 64-bit kernel and a compiler generating\n\t    # 32-bit code.  hppa64-hp-hpux* has the same kernel and a compiler\n\t    # generating 64-bit code.  GNU and HP use different nomenclature:\n\t    #\n\t    # $ CC_FOR_BUILD=cc ./config.guess\n\t    # => hppa2.0w-hp-hpux11.23\n\t    # $ CC_FOR_BUILD=\"cc +DA2.0w\" ./config.guess\n\t    # => hppa64-hp-hpux11.23\n\n\t    if echo __LP64__ | (CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) |\n\t\tgrep -q __LP64__\n\t    then\n\t\tHP_ARCH=\"hppa2.0w\"\n\t    else\n\t\tHP_ARCH=\"hppa64\"\n\t    fi\n\tfi\n\techo ${HP_ARCH}-hp-hpux${HPUX_REV}\n\texit ;;\n    ia64:HP-UX:*:*)\n\tHPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'`\n\techo ia64-hp-hpux${HPUX_REV}\n\texit ;;\n    3050*:HI-UX:*:*)\n\teval $set_cc_for_build\n\tsed 's/^\t//' << EOF >$dummy.c\n\t#include <unistd.h>\n\tint\n\tmain ()\n\t{\n\t  long cpu = sysconf (_SC_CPU_VERSION);\n\t  /* The order matters, because CPU_IS_HP_MC68K erroneously returns\n\t     true for CPU_PA_RISC1_0.  CPU_IS_PA_RISC returns correct\n\t     results, however.  */\n\t  if (CPU_IS_PA_RISC (cpu))\n\t    {\n\t      switch (cpu)\n\t\t{\n\t\t  case CPU_PA_RISC1_0: puts (\"hppa1.0-hitachi-hiuxwe2\"); break;\n\t\t  case CPU_PA_RISC1_1: puts (\"hppa1.1-hitachi-hiuxwe2\"); break;\n\t\t  case CPU_PA_RISC2_0: puts (\"hppa2.0-hitachi-hiuxwe2\"); break;\n\t\t  default: puts (\"hppa-hitachi-hiuxwe2\"); break;\n\t\t}\n\t    }\n\t  else if (CPU_IS_HP_MC68K (cpu))\n\t    puts (\"m68k-hitachi-hiuxwe2\");\n\t  else puts (\"unknown-hitachi-hiuxwe2\");\n\t  exit (0);\n\t}\nEOF\n\t$CC_FOR_BUILD -o $dummy $dummy.c && SYSTEM_NAME=`$dummy` &&\n\t\t{ echo \"$SYSTEM_NAME\"; exit; }\n\techo unknown-hitachi-hiuxwe2\n\texit ;;\n    9000/7??:4.3bsd:*:* | 9000/8?[79]:4.3bsd:*:* )\n\techo hppa1.1-hp-bsd\n\texit ;;\n    9000/8??:4.3bsd:*:*)\n\techo hppa1.0-hp-bsd\n\texit ;;\n    *9??*:MPE/iX:*:* | *3000*:MPE/iX:*:*)\n\techo hppa1.0-hp-mpeix\n\texit ;;\n    hp7??:OSF1:*:* | hp8?[79]:OSF1:*:* )\n\techo hppa1.1-hp-osf\n\texit ;;\n    hp8??:OSF1:*:*)\n\techo hppa1.0-hp-osf\n\texit ;;\n    i*86:OSF1:*:*)\n\tif [ -x /usr/sbin/sysversion ] ; then\n\t    echo ${UNAME_MACHINE}-unknown-osf1mk\n\telse\n\t    echo ${UNAME_MACHINE}-unknown-osf1\n\tfi\n\texit ;;\n    parisc*:Lites*:*:*)\n\techo hppa1.1-hp-lites\n\texit ;;\n    C1*:ConvexOS:*:* | convex:ConvexOS:C1*:*)\n\techo c1-convex-bsd\n\texit ;;\n    C2*:ConvexOS:*:* | convex:ConvexOS:C2*:*)\n\tif getsysinfo -f scalar_acc\n\tthen echo c32-convex-bsd\n\telse echo c2-convex-bsd\n\tfi\n\texit ;;\n    C34*:ConvexOS:*:* | convex:ConvexOS:C34*:*)\n\techo c34-convex-bsd\n\texit ;;\n    C38*:ConvexOS:*:* | convex:ConvexOS:C38*:*)\n\techo c38-convex-bsd\n\texit ;;\n    C4*:ConvexOS:*:* | convex:ConvexOS:C4*:*)\n\techo c4-convex-bsd\n\texit ;;\n    CRAY*Y-MP:*:*:*)\n\techo ymp-cray-unicos${UNAME_RELEASE} | sed -e 's/\\.[^.]*$/.X/'\n\texit ;;\n    CRAY*[A-Z]90:*:*:*)\n\techo ${UNAME_MACHINE}-cray-unicos${UNAME_RELEASE} \\\n\t| sed -e 's/CRAY.*\\([A-Z]90\\)/\\1/' \\\n\t      -e y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/ \\\n\t      -e 's/\\.[^.]*$/.X/'\n\texit ;;\n    CRAY*TS:*:*:*)\n\techo t90-cray-unicos${UNAME_RELEASE} | sed -e 's/\\.[^.]*$/.X/'\n\texit ;;\n    CRAY*T3E:*:*:*)\n\techo alphaev5-cray-unicosmk${UNAME_RELEASE} | sed -e 's/\\.[^.]*$/.X/'\n\texit ;;\n    CRAY*SV1:*:*:*)\n\techo sv1-cray-unicos${UNAME_RELEASE} | sed -e 's/\\.[^.]*$/.X/'\n\texit ;;\n    *:UNICOS/mp:*:*)\n\techo craynv-cray-unicosmp${UNAME_RELEASE} | sed -e 's/\\.[^.]*$/.X/'\n\texit ;;\n    F30[01]:UNIX_System_V:*:* | F700:UNIX_System_V:*:*)\n\tFUJITSU_PROC=`uname -m | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'`\n\tFUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\\///'`\n\tFUJITSU_REL=`echo ${UNAME_RELEASE} | sed -e 's/ /_/'`\n\techo \"${FUJITSU_PROC}-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}\"\n\texit ;;\n    5000:UNIX_System_V:4.*:*)\n\tFUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\\///'`\n\tFUJITSU_REL=`echo ${UNAME_RELEASE} | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/ /_/'`\n\techo \"sparc-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}\"\n\texit ;;\n    i*86:BSD/386:*:* | i*86:BSD/OS:*:* | *:Ascend\\ Embedded/OS:*:*)\n\techo ${UNAME_MACHINE}-pc-bsdi${UNAME_RELEASE}\n\texit ;;\n    sparc*:BSD/OS:*:*)\n\techo sparc-unknown-bsdi${UNAME_RELEASE}\n\texit ;;\n    *:BSD/OS:*:*)\n\techo ${UNAME_MACHINE}-unknown-bsdi${UNAME_RELEASE}\n\texit ;;\n    *:FreeBSD:*:*)\n\tUNAME_PROCESSOR=`/usr/bin/uname -p`\n\tcase ${UNAME_PROCESSOR} in\n\t    amd64)\n\t\techo x86_64-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;;\n\t    *)\n\t\techo ${UNAME_PROCESSOR}-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;;\n\tesac\n\texit ;;\n    i*:CYGWIN*:*)\n\techo ${UNAME_MACHINE}-pc-cygwin\n\texit ;;\n    *:MINGW64*:*)\n\techo ${UNAME_MACHINE}-pc-mingw64\n\texit ;;\n    *:MINGW*:*)\n\techo ${UNAME_MACHINE}-pc-mingw32\n\texit ;;\n    i*:MSYS*:*)\n\techo ${UNAME_MACHINE}-pc-msys\n\texit ;;\n    i*:windows32*:*)\n\t# uname -m includes \"-pc\" on this system.\n\techo ${UNAME_MACHINE}-mingw32\n\texit ;;\n    i*:PW*:*)\n\techo ${UNAME_MACHINE}-pc-pw32\n\texit ;;\n    *:Interix*:*)\n\tcase ${UNAME_MACHINE} in\n\t    x86)\n\t\techo i586-pc-interix${UNAME_RELEASE}\n\t\texit ;;\n\t    authenticamd | genuineintel | EM64T)\n\t\techo x86_64-unknown-interix${UNAME_RELEASE}\n\t\texit ;;\n\t    IA64)\n\t\techo ia64-unknown-interix${UNAME_RELEASE}\n\t\texit ;;\n\tesac ;;\n    [345]86:Windows_95:* | [345]86:Windows_98:* | [345]86:Windows_NT:*)\n\techo i${UNAME_MACHINE}-pc-mks\n\texit ;;\n    8664:Windows_NT:*)\n\techo x86_64-pc-mks\n\texit ;;\n    i*:Windows_NT*:* | Pentium*:Windows_NT*:*)\n\t# How do we know it's Interix rather than the generic POSIX subsystem?\n\t# It also conflicts with pre-2.0 versions of AT&T UWIN. Should we\n\t# UNAME_MACHINE based on the output of uname instead of i386?\n\techo i586-pc-interix\n\texit ;;\n    i*:UWIN*:*)\n\techo ${UNAME_MACHINE}-pc-uwin\n\texit ;;\n    amd64:CYGWIN*:*:* | x86_64:CYGWIN*:*:*)\n\techo x86_64-unknown-cygwin\n\texit ;;\n    p*:CYGWIN*:*)\n\techo powerpcle-unknown-cygwin\n\texit ;;\n    prep*:SunOS:5.*:*)\n\techo powerpcle-unknown-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`\n\texit ;;\n    *:GNU:*:*)\n\t# the GNU system\n\techo `echo ${UNAME_MACHINE}|sed -e 's,[-/].*$,,'`-unknown-${LIBC}`echo ${UNAME_RELEASE}|sed -e 's,/.*$,,'`\n\texit ;;\n    *:GNU/*:*:*)\n\t# other systems with GNU libc and userland\n\techo ${UNAME_MACHINE}-unknown-`echo ${UNAME_SYSTEM} | sed 's,^[^/]*/,,' | tr '[A-Z]' '[a-z]'``echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`-${LIBC}\n\texit ;;\n    i*86:Minix:*:*)\n\techo ${UNAME_MACHINE}-pc-minix\n\texit ;;\n    aarch64:Linux:*:*)\n\techo ${UNAME_MACHINE}-unknown-linux-${LIBC}\n\texit ;;\n    aarch64_be:Linux:*:*)\n\tUNAME_MACHINE=aarch64_be\n\techo ${UNAME_MACHINE}-unknown-linux-${LIBC}\n\texit ;;\n    alpha:Linux:*:*)\n\tcase `sed -n '/^cpu model/s/^.*: \\(.*\\)/\\1/p' < /proc/cpuinfo` in\n\t  EV5)   UNAME_MACHINE=alphaev5 ;;\n\t  EV56)  UNAME_MACHINE=alphaev56 ;;\n\t  PCA56) UNAME_MACHINE=alphapca56 ;;\n\t  PCA57) UNAME_MACHINE=alphapca56 ;;\n\t  EV6)   UNAME_MACHINE=alphaev6 ;;\n\t  EV67)  UNAME_MACHINE=alphaev67 ;;\n\t  EV68*) UNAME_MACHINE=alphaev68 ;;\n\tesac\n\tobjdump --private-headers /bin/sh | grep -q ld.so.1\n\tif test \"$?\" = 0 ; then LIBC=\"gnulibc1\" ; fi\n\techo ${UNAME_MACHINE}-unknown-linux-${LIBC}\n\texit ;;\n    arc:Linux:*:* | arceb:Linux:*:*)\n\techo ${UNAME_MACHINE}-unknown-linux-${LIBC}\n\texit ;;\n    arm*:Linux:*:*)\n\teval $set_cc_for_build\n\tif echo __ARM_EABI__ | $CC_FOR_BUILD -E - 2>/dev/null \\\n\t    | grep -q __ARM_EABI__\n\tthen\n\t    echo ${UNAME_MACHINE}-unknown-linux-${LIBC}\n\telse\n\t    if echo __ARM_PCS_VFP | $CC_FOR_BUILD -E - 2>/dev/null \\\n\t\t| grep -q __ARM_PCS_VFP\n\t    then\n\t\techo ${UNAME_MACHINE}-unknown-linux-${LIBC}eabi\n\t    else\n\t\techo ${UNAME_MACHINE}-unknown-linux-${LIBC}eabihf\n\t    fi\n\tfi\n\texit ;;\n    avr32*:Linux:*:*)\n\techo ${UNAME_MACHINE}-unknown-linux-${LIBC}\n\texit ;;\n    cris:Linux:*:*)\n\techo ${UNAME_MACHINE}-axis-linux-${LIBC}\n\texit ;;\n    crisv32:Linux:*:*)\n\techo ${UNAME_MACHINE}-axis-linux-${LIBC}\n\texit ;;\n    frv:Linux:*:*)\n\techo ${UNAME_MACHINE}-unknown-linux-${LIBC}\n\texit ;;\n    hexagon:Linux:*:*)\n\techo ${UNAME_MACHINE}-unknown-linux-${LIBC}\n\texit ;;\n    i*86:Linux:*:*)\n\techo ${UNAME_MACHINE}-pc-linux-${LIBC}\n\texit ;;\n    ia64:Linux:*:*)\n\techo ${UNAME_MACHINE}-unknown-linux-${LIBC}\n\texit ;;\n    m32r*:Linux:*:*)\n\techo ${UNAME_MACHINE}-unknown-linux-${LIBC}\n\texit ;;\n    m68*:Linux:*:*)\n\techo ${UNAME_MACHINE}-unknown-linux-${LIBC}\n\texit ;;\n    mips:Linux:*:* | mips64:Linux:*:*)\n\teval $set_cc_for_build\n\tsed 's/^\t//' << EOF >$dummy.c\n\t#undef CPU\n\t#undef ${UNAME_MACHINE}\n\t#undef ${UNAME_MACHINE}el\n\t#if defined(__MIPSEL__) || defined(__MIPSEL) || defined(_MIPSEL) || defined(MIPSEL)\n\tCPU=${UNAME_MACHINE}el\n\t#else\n\t#if defined(__MIPSEB__) || defined(__MIPSEB) || defined(_MIPSEB) || defined(MIPSEB)\n\tCPU=${UNAME_MACHINE}\n\t#else\n\tCPU=\n\t#endif\n\t#endif\nEOF\n\teval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep '^CPU'`\n\ttest x\"${CPU}\" != x && { echo \"${CPU}-unknown-linux-${LIBC}\"; exit; }\n\t;;\n    or1k:Linux:*:*)\n\techo ${UNAME_MACHINE}-unknown-linux-${LIBC}\n\texit ;;\n    or32:Linux:*:*)\n\techo ${UNAME_MACHINE}-unknown-linux-${LIBC}\n\texit ;;\n    padre:Linux:*:*)\n\techo sparc-unknown-linux-${LIBC}\n\texit ;;\n    parisc64:Linux:*:* | hppa64:Linux:*:*)\n\techo hppa64-unknown-linux-${LIBC}\n\texit ;;\n    parisc:Linux:*:* | hppa:Linux:*:*)\n\t# Look for CPU level\n\tcase `grep '^cpu[^a-z]*:' /proc/cpuinfo 2>/dev/null | cut -d' ' -f2` in\n\t  PA7*) echo hppa1.1-unknown-linux-${LIBC} ;;\n\t  PA8*) echo hppa2.0-unknown-linux-${LIBC} ;;\n\t  *)    echo hppa-unknown-linux-${LIBC} ;;\n\tesac\n\texit ;;\n    ppc64:Linux:*:*)\n\techo powerpc64-unknown-linux-${LIBC}\n\texit ;;\n    ppc:Linux:*:*)\n\techo powerpc-unknown-linux-${LIBC}\n\texit ;;\n    ppc64le:Linux:*:*)\n\techo powerpc64le-unknown-linux-${LIBC}\n\texit ;;\n    ppcle:Linux:*:*)\n\techo powerpcle-unknown-linux-${LIBC}\n\texit ;;\n    s390:Linux:*:* | s390x:Linux:*:*)\n\techo ${UNAME_MACHINE}-ibm-linux-${LIBC}\n\texit ;;\n    sh64*:Linux:*:*)\n\techo ${UNAME_MACHINE}-unknown-linux-${LIBC}\n\texit ;;\n    sh*:Linux:*:*)\n\techo ${UNAME_MACHINE}-unknown-linux-${LIBC}\n\texit ;;\n    sparc:Linux:*:* | sparc64:Linux:*:*)\n\techo ${UNAME_MACHINE}-unknown-linux-${LIBC}\n\texit ;;\n    tile*:Linux:*:*)\n\techo ${UNAME_MACHINE}-unknown-linux-${LIBC}\n\texit ;;\n    vax:Linux:*:*)\n\techo ${UNAME_MACHINE}-dec-linux-${LIBC}\n\texit ;;\n    x86_64:Linux:*:*)\n\techo ${UNAME_MACHINE}-unknown-linux-${LIBC}\n\texit ;;\n    xtensa*:Linux:*:*)\n\techo ${UNAME_MACHINE}-unknown-linux-${LIBC}\n\texit ;;\n    i*86:DYNIX/ptx:4*:*)\n\t# ptx 4.0 does uname -s correctly, with DYNIX/ptx in there.\n\t# earlier versions are messed up and put the nodename in both\n\t# sysname and nodename.\n\techo i386-sequent-sysv4\n\texit ;;\n    i*86:UNIX_SV:4.2MP:2.*)\n\t# Unixware is an offshoot of SVR4, but it has its own version\n\t# number series starting with 2...\n\t# I am not positive that other SVR4 systems won't match this,\n\t# I just have to hope.  -- rms.\n\t# Use sysv4.2uw... so that sysv4* matches it.\n\techo ${UNAME_MACHINE}-pc-sysv4.2uw${UNAME_VERSION}\n\texit ;;\n    i*86:OS/2:*:*)\n\t# If we were able to find `uname', then EMX Unix compatibility\n\t# is probably installed.\n\techo ${UNAME_MACHINE}-pc-os2-emx\n\texit ;;\n    i*86:XTS-300:*:STOP)\n\techo ${UNAME_MACHINE}-unknown-stop\n\texit ;;\n    i*86:atheos:*:*)\n\techo ${UNAME_MACHINE}-unknown-atheos\n\texit ;;\n    i*86:syllable:*:*)\n\techo ${UNAME_MACHINE}-pc-syllable\n\texit ;;\n    i*86:LynxOS:2.*:* | i*86:LynxOS:3.[01]*:* | i*86:LynxOS:4.[02]*:*)\n\techo i386-unknown-lynxos${UNAME_RELEASE}\n\texit ;;\n    i*86:*DOS:*:*)\n\techo ${UNAME_MACHINE}-pc-msdosdjgpp\n\texit ;;\n    i*86:*:4.*:* | i*86:SYSTEM_V:4.*:*)\n\tUNAME_REL=`echo ${UNAME_RELEASE} | sed 's/\\/MP$//'`\n\tif grep Novell /usr/include/link.h >/dev/null 2>/dev/null; then\n\t\techo ${UNAME_MACHINE}-univel-sysv${UNAME_REL}\n\telse\n\t\techo ${UNAME_MACHINE}-pc-sysv${UNAME_REL}\n\tfi\n\texit ;;\n    i*86:*:5:[678]*)\n\t# UnixWare 7.x, OpenUNIX and OpenServer 6.\n\tcase `/bin/uname -X | grep \"^Machine\"` in\n\t    *486*)\t     UNAME_MACHINE=i486 ;;\n\t    *Pentium)\t     UNAME_MACHINE=i586 ;;\n\t    *Pent*|*Celeron) UNAME_MACHINE=i686 ;;\n\tesac\n\techo ${UNAME_MACHINE}-unknown-sysv${UNAME_RELEASE}${UNAME_SYSTEM}${UNAME_VERSION}\n\texit ;;\n    i*86:*:3.2:*)\n\tif test -f /usr/options/cb.name; then\n\t\tUNAME_REL=`sed -n 's/.*Version //p' </usr/options/cb.name`\n\t\techo ${UNAME_MACHINE}-pc-isc$UNAME_REL\n\telif /bin/uname -X 2>/dev/null >/dev/null ; then\n\t\tUNAME_REL=`(/bin/uname -X|grep Release|sed -e 's/.*= //')`\n\t\t(/bin/uname -X|grep i80486 >/dev/null) && UNAME_MACHINE=i486\n\t\t(/bin/uname -X|grep '^Machine.*Pentium' >/dev/null) \\\n\t\t\t&& UNAME_MACHINE=i586\n\t\t(/bin/uname -X|grep '^Machine.*Pent *II' >/dev/null) \\\n\t\t\t&& UNAME_MACHINE=i686\n\t\t(/bin/uname -X|grep '^Machine.*Pentium Pro' >/dev/null) \\\n\t\t\t&& UNAME_MACHINE=i686\n\t\techo ${UNAME_MACHINE}-pc-sco$UNAME_REL\n\telse\n\t\techo ${UNAME_MACHINE}-pc-sysv32\n\tfi\n\texit ;;\n    pc:*:*:*)\n\t# Left here for compatibility:\n\t# uname -m prints for DJGPP always 'pc', but it prints nothing about\n\t# the processor, so we play safe by assuming i586.\n\t# Note: whatever this is, it MUST be the same as what config.sub\n\t# prints for the \"djgpp\" host, or else GDB configury will decide that\n\t# this is a cross-build.\n\techo i586-pc-msdosdjgpp\n\texit ;;\n    Intel:Mach:3*:*)\n\techo i386-pc-mach3\n\texit ;;\n    paragon:*:*:*)\n\techo i860-intel-osf1\n\texit ;;\n    i860:*:4.*:*) # i860-SVR4\n\tif grep Stardent /usr/include/sys/uadmin.h >/dev/null 2>&1 ; then\n\t  echo i860-stardent-sysv${UNAME_RELEASE} # Stardent Vistra i860-SVR4\n\telse # Add other i860-SVR4 vendors below as they are discovered.\n\t  echo i860-unknown-sysv${UNAME_RELEASE}  # Unknown i860-SVR4\n\tfi\n\texit ;;\n    mini*:CTIX:SYS*5:*)\n\t# \"miniframe\"\n\techo m68010-convergent-sysv\n\texit ;;\n    mc68k:UNIX:SYSTEM5:3.51m)\n\techo m68k-convergent-sysv\n\texit ;;\n    M680?0:D-NIX:5.3:*)\n\techo m68k-diab-dnix\n\texit ;;\n    M68*:*:R3V[5678]*:*)\n\ttest -r /sysV68 && { echo 'm68k-motorola-sysv'; exit; } ;;\n    3[345]??:*:4.0:3.0 | 3[34]??A:*:4.0:3.0 | 3[34]??,*:*:4.0:3.0 | 3[34]??/*:*:4.0:3.0 | 4400:*:4.0:3.0 | 4850:*:4.0:3.0 | SKA40:*:4.0:3.0 | SDS2:*:4.0:3.0 | SHG2:*:4.0:3.0 | S7501*:*:4.0:3.0)\n\tOS_REL=''\n\ttest -r /etc/.relid \\\n\t&& OS_REL=.`sed -n 's/[^ ]* [^ ]* \\([0-9][0-9]\\).*/\\1/p' < /etc/.relid`\n\t/bin/uname -p 2>/dev/null | grep 86 >/dev/null \\\n\t  && { echo i486-ncr-sysv4.3${OS_REL}; exit; }\n\t/bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \\\n\t  && { echo i586-ncr-sysv4.3${OS_REL}; exit; } ;;\n    3[34]??:*:4.0:* | 3[34]??,*:*:4.0:*)\n\t/bin/uname -p 2>/dev/null | grep 86 >/dev/null \\\n\t  && { echo i486-ncr-sysv4; exit; } ;;\n    NCR*:*:4.2:* | MPRAS*:*:4.2:*)\n\tOS_REL='.3'\n\ttest -r /etc/.relid \\\n\t    && OS_REL=.`sed -n 's/[^ ]* [^ ]* \\([0-9][0-9]\\).*/\\1/p' < /etc/.relid`\n\t/bin/uname -p 2>/dev/null | grep 86 >/dev/null \\\n\t    && { echo i486-ncr-sysv4.3${OS_REL}; exit; }\n\t/bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \\\n\t    && { echo i586-ncr-sysv4.3${OS_REL}; exit; }\n\t/bin/uname -p 2>/dev/null | /bin/grep pteron >/dev/null \\\n\t    && { echo i586-ncr-sysv4.3${OS_REL}; exit; } ;;\n    m68*:LynxOS:2.*:* | m68*:LynxOS:3.0*:*)\n\techo m68k-unknown-lynxos${UNAME_RELEASE}\n\texit ;;\n    mc68030:UNIX_System_V:4.*:*)\n\techo m68k-atari-sysv4\n\texit ;;\n    TSUNAMI:LynxOS:2.*:*)\n\techo sparc-unknown-lynxos${UNAME_RELEASE}\n\texit ;;\n    rs6000:LynxOS:2.*:*)\n\techo rs6000-unknown-lynxos${UNAME_RELEASE}\n\texit ;;\n    PowerPC:LynxOS:2.*:* | PowerPC:LynxOS:3.[01]*:* | PowerPC:LynxOS:4.[02]*:*)\n\techo powerpc-unknown-lynxos${UNAME_RELEASE}\n\texit ;;\n    SM[BE]S:UNIX_SV:*:*)\n\techo mips-dde-sysv${UNAME_RELEASE}\n\texit ;;\n    RM*:ReliantUNIX-*:*:*)\n\techo mips-sni-sysv4\n\texit ;;\n    RM*:SINIX-*:*:*)\n\techo mips-sni-sysv4\n\texit ;;\n    *:SINIX-*:*:*)\n\tif uname -p 2>/dev/null >/dev/null ; then\n\t\tUNAME_MACHINE=`(uname -p) 2>/dev/null`\n\t\techo ${UNAME_MACHINE}-sni-sysv4\n\telse\n\t\techo ns32k-sni-sysv\n\tfi\n\texit ;;\n    PENTIUM:*:4.0*:*)\t# Unisys `ClearPath HMP IX 4000' SVR4/MP effort\n\t\t\t# says <Richard.M.Bartel@ccMail.Census.GOV>\n\techo i586-unisys-sysv4\n\texit ;;\n    *:UNIX_System_V:4*:FTX*)\n\t# From Gerald Hewes <hewes@openmarket.com>.\n\t# How about differentiating between stratus architectures? -djm\n\techo hppa1.1-stratus-sysv4\n\texit ;;\n    *:*:*:FTX*)\n\t# From seanf@swdc.stratus.com.\n\techo i860-stratus-sysv4\n\texit ;;\n    i*86:VOS:*:*)\n\t# From Paul.Green@stratus.com.\n\techo ${UNAME_MACHINE}-stratus-vos\n\texit ;;\n    *:VOS:*:*)\n\t# From Paul.Green@stratus.com.\n\techo hppa1.1-stratus-vos\n\texit ;;\n    mc68*:A/UX:*:*)\n\techo m68k-apple-aux${UNAME_RELEASE}\n\texit ;;\n    news*:NEWS-OS:6*:*)\n\techo mips-sony-newsos6\n\texit ;;\n    R[34]000:*System_V*:*:* | R4000:UNIX_SYSV:*:* | R*000:UNIX_SV:*:*)\n\tif [ -d /usr/nec ]; then\n\t\techo mips-nec-sysv${UNAME_RELEASE}\n\telse\n\t\techo mips-unknown-sysv${UNAME_RELEASE}\n\tfi\n\texit ;;\n    BeBox:BeOS:*:*)\t# BeOS running on hardware made by Be, PPC only.\n\techo powerpc-be-beos\n\texit ;;\n    BeMac:BeOS:*:*)\t# BeOS running on Mac or Mac clone, PPC only.\n\techo powerpc-apple-beos\n\texit ;;\n    BePC:BeOS:*:*)\t# BeOS running on Intel PC compatible.\n\techo i586-pc-beos\n\texit ;;\n    BePC:Haiku:*:*)\t# Haiku running on Intel PC compatible.\n\techo i586-pc-haiku\n\texit ;;\n    x86_64:Haiku:*:*)\n\techo x86_64-unknown-haiku\n\texit ;;\n    SX-4:SUPER-UX:*:*)\n\techo sx4-nec-superux${UNAME_RELEASE}\n\texit ;;\n    SX-5:SUPER-UX:*:*)\n\techo sx5-nec-superux${UNAME_RELEASE}\n\texit ;;\n    SX-6:SUPER-UX:*:*)\n\techo sx6-nec-superux${UNAME_RELEASE}\n\texit ;;\n    SX-7:SUPER-UX:*:*)\n\techo sx7-nec-superux${UNAME_RELEASE}\n\texit ;;\n    SX-8:SUPER-UX:*:*)\n\techo sx8-nec-superux${UNAME_RELEASE}\n\texit ;;\n    SX-8R:SUPER-UX:*:*)\n\techo sx8r-nec-superux${UNAME_RELEASE}\n\texit ;;\n    Power*:Rhapsody:*:*)\n\techo powerpc-apple-rhapsody${UNAME_RELEASE}\n\texit ;;\n    *:Rhapsody:*:*)\n\techo ${UNAME_MACHINE}-apple-rhapsody${UNAME_RELEASE}\n\texit ;;\n    *:Darwin:*:*)\n\tUNAME_PROCESSOR=`uname -p` || UNAME_PROCESSOR=unknown\n\teval $set_cc_for_build\n\tif test \"$UNAME_PROCESSOR\" = unknown ; then\n\t    UNAME_PROCESSOR=powerpc\n\tfi\n\tif [ \"$CC_FOR_BUILD\" != 'no_compiler_found' ]; then\n\t    if (echo '#ifdef __LP64__'; echo IS_64BIT_ARCH; echo '#endif') | \\\n\t\t(CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) | \\\n\t\tgrep IS_64BIT_ARCH >/dev/null\n\t    then\n\t\tcase $UNAME_PROCESSOR in\n\t\t    i386) UNAME_PROCESSOR=x86_64 ;;\n\t\t    powerpc) UNAME_PROCESSOR=powerpc64 ;;\n\t\tesac\n\t    fi\n\tfi\n\techo ${UNAME_PROCESSOR}-apple-darwin${UNAME_RELEASE}\n\texit ;;\n    *:procnto*:*:* | *:QNX:[0123456789]*:*)\n\tUNAME_PROCESSOR=`uname -p`\n\tif test \"$UNAME_PROCESSOR\" = \"x86\"; then\n\t\tUNAME_PROCESSOR=i386\n\t\tUNAME_MACHINE=pc\n\tfi\n\techo ${UNAME_PROCESSOR}-${UNAME_MACHINE}-nto-qnx${UNAME_RELEASE}\n\texit ;;\n    *:QNX:*:4*)\n\techo i386-pc-qnx\n\texit ;;\n    NEO-?:NONSTOP_KERNEL:*:*)\n\techo neo-tandem-nsk${UNAME_RELEASE}\n\texit ;;\n    NSE-*:NONSTOP_KERNEL:*:*)\n\techo nse-tandem-nsk${UNAME_RELEASE}\n\texit ;;\n    NSR-?:NONSTOP_KERNEL:*:*)\n\techo nsr-tandem-nsk${UNAME_RELEASE}\n\texit ;;\n    *:NonStop-UX:*:*)\n\techo mips-compaq-nonstopux\n\texit ;;\n    BS2000:POSIX*:*:*)\n\techo bs2000-siemens-sysv\n\texit ;;\n    DS/*:UNIX_System_V:*:*)\n\techo ${UNAME_MACHINE}-${UNAME_SYSTEM}-${UNAME_RELEASE}\n\texit ;;\n    *:Plan9:*:*)\n\t# \"uname -m\" is not consistent, so use $cputype instead. 386\n\t# is converted to i386 for consistency with other x86\n\t# operating systems.\n\tif test \"$cputype\" = \"386\"; then\n\t    UNAME_MACHINE=i386\n\telse\n\t    UNAME_MACHINE=\"$cputype\"\n\tfi\n\techo ${UNAME_MACHINE}-unknown-plan9\n\texit ;;\n    *:TOPS-10:*:*)\n\techo pdp10-unknown-tops10\n\texit ;;\n    *:TENEX:*:*)\n\techo pdp10-unknown-tenex\n\texit ;;\n    KS10:TOPS-20:*:* | KL10:TOPS-20:*:* | TYPE4:TOPS-20:*:*)\n\techo pdp10-dec-tops20\n\texit ;;\n    XKL-1:TOPS-20:*:* | TYPE5:TOPS-20:*:*)\n\techo pdp10-xkl-tops20\n\texit ;;\n    *:TOPS-20:*:*)\n\techo pdp10-unknown-tops20\n\texit ;;\n    *:ITS:*:*)\n\techo pdp10-unknown-its\n\texit ;;\n    SEI:*:*:SEIUX)\n\techo mips-sei-seiux${UNAME_RELEASE}\n\texit ;;\n    *:DragonFly:*:*)\n\techo ${UNAME_MACHINE}-unknown-dragonfly`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`\n\texit ;;\n    *:*VMS:*:*)\n\tUNAME_MACHINE=`(uname -p) 2>/dev/null`\n\tcase \"${UNAME_MACHINE}\" in\n\t    A*) echo alpha-dec-vms ; exit ;;\n\t    I*) echo ia64-dec-vms ; exit ;;\n\t    V*) echo vax-dec-vms ; exit ;;\n\tesac ;;\n    *:XENIX:*:SysV)\n\techo i386-pc-xenix\n\texit ;;\n    i*86:skyos:*:*)\n\techo ${UNAME_MACHINE}-pc-skyos`echo ${UNAME_RELEASE}` | sed -e 's/ .*$//'\n\texit ;;\n    i*86:rdos:*:*)\n\techo ${UNAME_MACHINE}-pc-rdos\n\texit ;;\n    i*86:AROS:*:*)\n\techo ${UNAME_MACHINE}-pc-aros\n\texit ;;\n    x86_64:VMkernel:*:*)\n\techo ${UNAME_MACHINE}-unknown-esx\n\texit ;;\nesac\n\neval $set_cc_for_build\ncat >$dummy.c <<EOF\n#ifdef _SEQUENT_\n# include <sys/types.h>\n# include <sys/utsname.h>\n#endif\nmain ()\n{\n#if defined (sony)\n#if defined (MIPSEB)\n  /* BFD wants \"bsd\" instead of \"newsos\".  Perhaps BFD should be changed,\n     I don't know....  */\n  printf (\"mips-sony-bsd\\n\"); exit (0);\n#else\n#include <sys/param.h>\n  printf (\"m68k-sony-newsos%s\\n\",\n#ifdef NEWSOS4\n\t\"4\"\n#else\n\t\"\"\n#endif\n\t); exit (0);\n#endif\n#endif\n\n#if defined (__arm) && defined (__acorn) && defined (__unix)\n  printf (\"arm-acorn-riscix\\n\"); exit (0);\n#endif\n\n#if defined (hp300) && !defined (hpux)\n  printf (\"m68k-hp-bsd\\n\"); exit (0);\n#endif\n\n#if defined (NeXT)\n#if !defined (__ARCHITECTURE__)\n#define __ARCHITECTURE__ \"m68k\"\n#endif\n  int version;\n  version=`(hostinfo | sed -n 's/.*NeXT Mach \\([0-9]*\\).*/\\1/p') 2>/dev/null`;\n  if (version < 4)\n    printf (\"%s-next-nextstep%d\\n\", __ARCHITECTURE__, version);\n  else\n    printf (\"%s-next-openstep%d\\n\", __ARCHITECTURE__, version);\n  exit (0);\n#endif\n\n#if defined (MULTIMAX) || defined (n16)\n#if defined (UMAXV)\n  printf (\"ns32k-encore-sysv\\n\"); exit (0);\n#else\n#if defined (CMU)\n  printf (\"ns32k-encore-mach\\n\"); exit (0);\n#else\n  printf (\"ns32k-encore-bsd\\n\"); exit (0);\n#endif\n#endif\n#endif\n\n#if defined (__386BSD__)\n  printf (\"i386-pc-bsd\\n\"); exit (0);\n#endif\n\n#if defined (sequent)\n#if defined (i386)\n  printf (\"i386-sequent-dynix\\n\"); exit (0);\n#endif\n#if defined (ns32000)\n  printf (\"ns32k-sequent-dynix\\n\"); exit (0);\n#endif\n#endif\n\n#if defined (_SEQUENT_)\n    struct utsname un;\n\n    uname(&un);\n\n    if (strncmp(un.version, \"V2\", 2) == 0) {\n\tprintf (\"i386-sequent-ptx2\\n\"); exit (0);\n    }\n    if (strncmp(un.version, \"V1\", 2) == 0) { /* XXX is V1 correct? */\n\tprintf (\"i386-sequent-ptx1\\n\"); exit (0);\n    }\n    printf (\"i386-sequent-ptx\\n\"); exit (0);\n\n#endif\n\n#if defined (vax)\n# if !defined (ultrix)\n#  include <sys/param.h>\n#  if defined (BSD)\n#   if BSD == 43\n      printf (\"vax-dec-bsd4.3\\n\"); exit (0);\n#   else\n#    if BSD == 199006\n      printf (\"vax-dec-bsd4.3reno\\n\"); exit (0);\n#    else\n      printf (\"vax-dec-bsd\\n\"); exit (0);\n#    endif\n#   endif\n#  else\n    printf (\"vax-dec-bsd\\n\"); exit (0);\n#  endif\n# else\n    printf (\"vax-dec-ultrix\\n\"); exit (0);\n# endif\n#endif\n\n#if defined (alliant) && defined (i860)\n  printf (\"i860-alliant-bsd\\n\"); exit (0);\n#endif\n\n  exit (1);\n}\nEOF\n\n$CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null && SYSTEM_NAME=`$dummy` &&\n\t{ echo \"$SYSTEM_NAME\"; exit; }\n\n# Apollos put the system type in the environment.\n\ntest -d /usr/apollo && { echo ${ISP}-apollo-${SYSTYPE}; exit; }\n\n# Convex versions that predate uname can use getsysinfo(1)\n\nif [ -x /usr/convex/getsysinfo ]\nthen\n    case `getsysinfo -f cpu_type` in\n    c1*)\n\techo c1-convex-bsd\n\texit ;;\n    c2*)\n\tif getsysinfo -f scalar_acc\n\tthen echo c32-convex-bsd\n\telse echo c2-convex-bsd\n\tfi\n\texit ;;\n    c34*)\n\techo c34-convex-bsd\n\texit ;;\n    c38*)\n\techo c38-convex-bsd\n\texit ;;\n    c4*)\n\techo c4-convex-bsd\n\texit ;;\n    esac\nfi\n\ncat >&2 <<EOF\n$0: unable to guess system type\n\nThis script, last modified $timestamp, has failed to recognize\nthe operating system you are using. It is advised that you\ndownload the most up to date version of the config scripts from\n\n  http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.guess;hb=HEAD\nand\n  http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.sub;hb=HEAD\n\nIf the version you run ($0) is already up to date, please\nsend the following data and any information you think might be\npertinent to <config-patches@gnu.org> in order to provide the needed\ninformation to handle your system.\n\nconfig.guess timestamp = $timestamp\n\nuname -m = `(uname -m) 2>/dev/null || echo unknown`\nuname -r = `(uname -r) 2>/dev/null || echo unknown`\nuname -s = `(uname -s) 2>/dev/null || echo unknown`\nuname -v = `(uname -v) 2>/dev/null || echo unknown`\n\n/usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null`\n/bin/uname -X     = `(/bin/uname -X) 2>/dev/null`\n\nhostinfo               = `(hostinfo) 2>/dev/null`\n/bin/universe          = `(/bin/universe) 2>/dev/null`\n/usr/bin/arch -k       = `(/usr/bin/arch -k) 2>/dev/null`\n/bin/arch              = `(/bin/arch) 2>/dev/null`\n/usr/bin/oslevel       = `(/usr/bin/oslevel) 2>/dev/null`\n/usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null`\n\nUNAME_MACHINE = ${UNAME_MACHINE}\nUNAME_RELEASE = ${UNAME_RELEASE}\nUNAME_SYSTEM  = ${UNAME_SYSTEM}\nUNAME_VERSION = ${UNAME_VERSION}\nEOF\n\nexit 1\n\n# Local variables:\n# eval: (add-hook 'write-file-hooks 'time-stamp)\n# time-stamp-start: \"timestamp='\"\n# time-stamp-format: \"%:y-%02m-%02d\"\n# time-stamp-end: \"'\"\n# End:\n"
  },
  {
    "path": "extern/deprecated/redis-2.8.21/deps/jemalloc/config.stamp.in",
    "content": ""
  },
  {
    "path": "extern/deprecated/redis-2.8.21/deps/jemalloc/config.sub",
    "content": "#! /bin/sh\n# Configuration validation subroutine script.\n#   Copyright 1992-2013 Free Software Foundation, Inc.\n\ntimestamp='2013-10-01'\n\n# This file is free software; you can redistribute it and/or modify it\n# under the terms of the GNU General Public License as published by\n# the Free Software Foundation; either version 3 of the License, or\n# (at your option) any later version.\n#\n# This program is distributed in the hope that it will be useful, but\n# WITHOUT ANY WARRANTY; without even the implied warranty of\n# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n# General Public License for more details.\n#\n# You should have received a copy of the GNU General Public License\n# along with this program; if not, see <http://www.gnu.org/licenses/>.\n#\n# As a special exception to the GNU General Public License, if you\n# distribute this file as part of a program that contains a\n# configuration script generated by Autoconf, you may include it under\n# the same distribution terms that you use for the rest of that\n# program.  This Exception is an additional permission under section 7\n# of the GNU General Public License, version 3 (\"GPLv3\").\n\n\n# Please send patches with a ChangeLog entry to config-patches@gnu.org.\n#\n# Configuration subroutine to validate and canonicalize a configuration type.\n# Supply the specified configuration type as an argument.\n# If it is invalid, we print an error message on stderr and exit with code 1.\n# Otherwise, we print the canonical config type on stdout and succeed.\n\n# You can get the latest version of this script from:\n# http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.sub;hb=HEAD\n\n# This file is supposed to be the same for all GNU packages\n# and recognize all the CPU types, system types and aliases\n# that are meaningful with *any* GNU software.\n# Each package is responsible for reporting which valid configurations\n# it does not support.  The user should be able to distinguish\n# a failure to support a valid configuration from a meaningless\n# configuration.\n\n# The goal of this file is to map all the various variations of a given\n# machine specification into a single specification in the form:\n#\tCPU_TYPE-MANUFACTURER-OPERATING_SYSTEM\n# or in some cases, the newer four-part form:\n#\tCPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM\n# It is wrong to echo any other type of specification.\n\nme=`echo \"$0\" | sed -e 's,.*/,,'`\n\nusage=\"\\\nUsage: $0 [OPTION] CPU-MFR-OPSYS\n       $0 [OPTION] ALIAS\n\nCanonicalize a configuration name.\n\nOperation modes:\n  -h, --help         print this help, then exit\n  -t, --time-stamp   print date of last modification, then exit\n  -v, --version      print version number, then exit\n\nReport bugs and patches to <config-patches@gnu.org>.\"\n\nversion=\"\\\nGNU config.sub ($timestamp)\n\nCopyright 1992-2013 Free Software Foundation, Inc.\n\nThis is free software; see the source for copying conditions.  There is NO\nwarranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\"\n\nhelp=\"\nTry \\`$me --help' for more information.\"\n\n# Parse command line\nwhile test $# -gt 0 ; do\n  case $1 in\n    --time-stamp | --time* | -t )\n       echo \"$timestamp\" ; exit ;;\n    --version | -v )\n       echo \"$version\" ; exit ;;\n    --help | --h* | -h )\n       echo \"$usage\"; exit ;;\n    -- )     # Stop option processing\n       shift; break ;;\n    - )\t# Use stdin as input.\n       break ;;\n    -* )\n       echo \"$me: invalid option $1$help\"\n       exit 1 ;;\n\n    *local*)\n       # First pass through any local machine types.\n       echo $1\n       exit ;;\n\n    * )\n       break ;;\n  esac\ndone\n\ncase $# in\n 0) echo \"$me: missing argument$help\" >&2\n    exit 1;;\n 1) ;;\n *) echo \"$me: too many arguments$help\" >&2\n    exit 1;;\nesac\n\n# Separate what the user gave into CPU-COMPANY and OS or KERNEL-OS (if any).\n# Here we must recognize all the valid KERNEL-OS combinations.\nmaybe_os=`echo $1 | sed 's/^\\(.*\\)-\\([^-]*-[^-]*\\)$/\\2/'`\ncase $maybe_os in\n  nto-qnx* | linux-gnu* | linux-android* | linux-dietlibc | linux-newlib* | \\\n  linux-musl* | linux-uclibc* | uclinux-uclibc* | uclinux-gnu* | kfreebsd*-gnu* | \\\n  knetbsd*-gnu* | netbsd*-gnu* | \\\n  kopensolaris*-gnu* | \\\n  storm-chaos* | os2-emx* | rtmk-nova*)\n    os=-$maybe_os\n    basic_machine=`echo $1 | sed 's/^\\(.*\\)-\\([^-]*-[^-]*\\)$/\\1/'`\n    ;;\n  android-linux)\n    os=-linux-android\n    basic_machine=`echo $1 | sed 's/^\\(.*\\)-\\([^-]*-[^-]*\\)$/\\1/'`-unknown\n    ;;\n  *)\n    basic_machine=`echo $1 | sed 's/-[^-]*$//'`\n    if [ $basic_machine != $1 ]\n    then os=`echo $1 | sed 's/.*-/-/'`\n    else os=; fi\n    ;;\nesac\n\n### Let's recognize common machines as not being operating systems so\n### that things like config.sub decstation-3100 work.  We also\n### recognize some manufacturers as not being operating systems, so we\n### can provide default operating systems below.\ncase $os in\n\t-sun*os*)\n\t\t# Prevent following clause from handling this invalid input.\n\t\t;;\n\t-dec* | -mips* | -sequent* | -encore* | -pc532* | -sgi* | -sony* | \\\n\t-att* | -7300* | -3300* | -delta* | -motorola* | -sun[234]* | \\\n\t-unicom* | -ibm* | -next | -hp | -isi* | -apollo | -altos* | \\\n\t-convergent* | -ncr* | -news | -32* | -3600* | -3100* | -hitachi* |\\\n\t-c[123]* | -convex* | -sun | -crds | -omron* | -dg | -ultra | -tti* | \\\n\t-harris | -dolphin | -highlevel | -gould | -cbm | -ns | -masscomp | \\\n\t-apple | -axis | -knuth | -cray | -microblaze*)\n\t\tos=\n\t\tbasic_machine=$1\n\t\t;;\n\t-bluegene*)\n\t\tos=-cnk\n\t\t;;\n\t-sim | -cisco | -oki | -wec | -winbond)\n\t\tos=\n\t\tbasic_machine=$1\n\t\t;;\n\t-scout)\n\t\t;;\n\t-wrs)\n\t\tos=-vxworks\n\t\tbasic_machine=$1\n\t\t;;\n\t-chorusos*)\n\t\tos=-chorusos\n\t\tbasic_machine=$1\n\t\t;;\n\t-chorusrdb)\n\t\tos=-chorusrdb\n\t\tbasic_machine=$1\n\t\t;;\n\t-hiux*)\n\t\tos=-hiuxwe2\n\t\t;;\n\t-sco6)\n\t\tos=-sco5v6\n\t\tbasic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`\n\t\t;;\n\t-sco5)\n\t\tos=-sco3.2v5\n\t\tbasic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`\n\t\t;;\n\t-sco4)\n\t\tos=-sco3.2v4\n\t\tbasic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`\n\t\t;;\n\t-sco3.2.[4-9]*)\n\t\tos=`echo $os | sed -e 's/sco3.2./sco3.2v/'`\n\t\tbasic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`\n\t\t;;\n\t-sco3.2v[4-9]*)\n\t\t# Don't forget version if it is 3.2v4 or newer.\n\t\tbasic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`\n\t\t;;\n\t-sco5v6*)\n\t\t# Don't forget version if it is 3.2v4 or newer.\n\t\tbasic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`\n\t\t;;\n\t-sco*)\n\t\tos=-sco3.2v2\n\t\tbasic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`\n\t\t;;\n\t-udk*)\n\t\tbasic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`\n\t\t;;\n\t-isc)\n\t\tos=-isc2.2\n\t\tbasic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`\n\t\t;;\n\t-clix*)\n\t\tbasic_machine=clipper-intergraph\n\t\t;;\n\t-isc*)\n\t\tbasic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`\n\t\t;;\n\t-lynx*178)\n\t\tos=-lynxos178\n\t\t;;\n\t-lynx*5)\n\t\tos=-lynxos5\n\t\t;;\n\t-lynx*)\n\t\tos=-lynxos\n\t\t;;\n\t-ptx*)\n\t\tbasic_machine=`echo $1 | sed -e 's/86-.*/86-sequent/'`\n\t\t;;\n\t-windowsnt*)\n\t\tos=`echo $os | sed -e 's/windowsnt/winnt/'`\n\t\t;;\n\t-psos*)\n\t\tos=-psos\n\t\t;;\n\t-mint | -mint[0-9]*)\n\t\tbasic_machine=m68k-atari\n\t\tos=-mint\n\t\t;;\nesac\n\n# Decode aliases for certain CPU-COMPANY combinations.\ncase $basic_machine in\n\t# Recognize the basic CPU types without company name.\n\t# Some are omitted here because they have special meanings below.\n\t1750a | 580 \\\n\t| a29k \\\n\t| aarch64 | aarch64_be \\\n\t| alpha | alphaev[4-8] | alphaev56 | alphaev6[78] | alphapca5[67] \\\n\t| alpha64 | alpha64ev[4-8] | alpha64ev56 | alpha64ev6[78] | alpha64pca5[67] \\\n\t| am33_2.0 \\\n\t| arc | arceb \\\n\t| arm | arm[bl]e | arme[lb] | armv[2-8] | armv[3-8][lb] | armv7[arm] \\\n\t| avr | avr32 \\\n\t| be32 | be64 \\\n\t| bfin \\\n\t| c4x | c8051 | clipper \\\n\t| d10v | d30v | dlx | dsp16xx \\\n\t| epiphany \\\n\t| fido | fr30 | frv \\\n\t| h8300 | h8500 | hppa | hppa1.[01] | hppa2.0 | hppa2.0[nw] | hppa64 \\\n\t| hexagon \\\n\t| i370 | i860 | i960 | ia64 \\\n\t| ip2k | iq2000 \\\n\t| k1om \\\n\t| le32 | le64 \\\n\t| lm32 \\\n\t| m32c | m32r | m32rle | m68000 | m68k | m88k \\\n\t| maxq | mb | microblaze | microblazeel | mcore | mep | metag \\\n\t| mips | mipsbe | mipseb | mipsel | mipsle \\\n\t| mips16 \\\n\t| mips64 | mips64el \\\n\t| mips64octeon | mips64octeonel \\\n\t| mips64orion | mips64orionel \\\n\t| mips64r5900 | mips64r5900el \\\n\t| mips64vr | mips64vrel \\\n\t| mips64vr4100 | mips64vr4100el \\\n\t| mips64vr4300 | mips64vr4300el \\\n\t| mips64vr5000 | mips64vr5000el \\\n\t| mips64vr5900 | mips64vr5900el \\\n\t| mipsisa32 | mipsisa32el \\\n\t| mipsisa32r2 | mipsisa32r2el \\\n\t| mipsisa64 | mipsisa64el \\\n\t| mipsisa64r2 | mipsisa64r2el \\\n\t| mipsisa64sb1 | mipsisa64sb1el \\\n\t| mipsisa64sr71k | mipsisa64sr71kel \\\n\t| mipsr5900 | mipsr5900el \\\n\t| mipstx39 | mipstx39el \\\n\t| mn10200 | mn10300 \\\n\t| moxie \\\n\t| mt \\\n\t| msp430 \\\n\t| nds32 | nds32le | nds32be \\\n\t| nios | nios2 | nios2eb | nios2el \\\n\t| ns16k | ns32k \\\n\t| open8 \\\n\t| or1k | or32 \\\n\t| pdp10 | pdp11 | pj | pjl \\\n\t| powerpc | powerpc64 | powerpc64le | powerpcle \\\n\t| pyramid \\\n\t| rl78 | rx \\\n\t| score \\\n\t| sh | sh[1234] | sh[24]a | sh[24]aeb | sh[23]e | sh[34]eb | sheb | shbe | shle | sh[1234]le | sh3ele \\\n\t| sh64 | sh64le \\\n\t| sparc | sparc64 | sparc64b | sparc64v | sparc86x | sparclet | sparclite \\\n\t| sparcv8 | sparcv9 | sparcv9b | sparcv9v \\\n\t| spu \\\n\t| tahoe | tic4x | tic54x | tic55x | tic6x | tic80 | tron \\\n\t| ubicom32 \\\n\t| v850 | v850e | v850e1 | v850e2 | v850es | v850e2v3 \\\n\t| we32k \\\n\t| x86 | xc16x | xstormy16 | xtensa \\\n\t| z8k | z80)\n\t\tbasic_machine=$basic_machine-unknown\n\t\t;;\n\tc54x)\n\t\tbasic_machine=tic54x-unknown\n\t\t;;\n\tc55x)\n\t\tbasic_machine=tic55x-unknown\n\t\t;;\n\tc6x)\n\t\tbasic_machine=tic6x-unknown\n\t\t;;\n\tm6811 | m68hc11 | m6812 | m68hc12 | m68hcs12x | nvptx | picochip)\n\t\tbasic_machine=$basic_machine-unknown\n\t\tos=-none\n\t\t;;\n\tm88110 | m680[12346]0 | m683?2 | m68360 | m5200 | v70 | w65 | z8k)\n\t\t;;\n\tms1)\n\t\tbasic_machine=mt-unknown\n\t\t;;\n\n\tstrongarm | thumb | xscale)\n\t\tbasic_machine=arm-unknown\n\t\t;;\n\txgate)\n\t\tbasic_machine=$basic_machine-unknown\n\t\tos=-none\n\t\t;;\n\txscaleeb)\n\t\tbasic_machine=armeb-unknown\n\t\t;;\n\n\txscaleel)\n\t\tbasic_machine=armel-unknown\n\t\t;;\n\n\t# We use `pc' rather than `unknown'\n\t# because (1) that's what they normally are, and\n\t# (2) the word \"unknown\" tends to confuse beginning users.\n\ti*86 | x86_64)\n\t  basic_machine=$basic_machine-pc\n\t  ;;\n\t# Object if more than one company name word.\n\t*-*-*)\n\t\techo Invalid configuration \\`$1\\': machine \\`$basic_machine\\' not recognized 1>&2\n\t\texit 1\n\t\t;;\n\t# Recognize the basic CPU types with company name.\n\t580-* \\\n\t| a29k-* \\\n\t| aarch64-* | aarch64_be-* \\\n\t| alpha-* | alphaev[4-8]-* | alphaev56-* | alphaev6[78]-* \\\n\t| alpha64-* | alpha64ev[4-8]-* | alpha64ev56-* | alpha64ev6[78]-* \\\n\t| alphapca5[67]-* | alpha64pca5[67]-* | arc-* | arceb-* \\\n\t| arm-*  | armbe-* | armle-* | armeb-* | armv*-* \\\n\t| avr-* | avr32-* \\\n\t| be32-* | be64-* \\\n\t| bfin-* | bs2000-* \\\n\t| c[123]* | c30-* | [cjt]90-* | c4x-* \\\n\t| c8051-* | clipper-* | craynv-* | cydra-* \\\n\t| d10v-* | d30v-* | dlx-* \\\n\t| elxsi-* \\\n\t| f30[01]-* | f700-* | fido-* | fr30-* | frv-* | fx80-* \\\n\t| h8300-* | h8500-* \\\n\t| hppa-* | hppa1.[01]-* | hppa2.0-* | hppa2.0[nw]-* | hppa64-* \\\n\t| hexagon-* \\\n\t| i*86-* | i860-* | i960-* | ia64-* \\\n\t| ip2k-* | iq2000-* \\\n\t| k1om-* \\\n\t| le32-* | le64-* \\\n\t| lm32-* \\\n\t| m32c-* | m32r-* | m32rle-* \\\n\t| m68000-* | m680[012346]0-* | m68360-* | m683?2-* | m68k-* \\\n\t| m88110-* | m88k-* | maxq-* | mcore-* | metag-* \\\n\t| microblaze-* | microblazeel-* \\\n\t| mips-* | mipsbe-* | mipseb-* | mipsel-* | mipsle-* \\\n\t| mips16-* \\\n\t| mips64-* | mips64el-* \\\n\t| mips64octeon-* | mips64octeonel-* \\\n\t| mips64orion-* | mips64orionel-* \\\n\t| mips64r5900-* | mips64r5900el-* \\\n\t| mips64vr-* | mips64vrel-* \\\n\t| mips64vr4100-* | mips64vr4100el-* \\\n\t| mips64vr4300-* | mips64vr4300el-* \\\n\t| mips64vr5000-* | mips64vr5000el-* \\\n\t| mips64vr5900-* | mips64vr5900el-* \\\n\t| mipsisa32-* | mipsisa32el-* \\\n\t| mipsisa32r2-* | mipsisa32r2el-* \\\n\t| mipsisa64-* | mipsisa64el-* \\\n\t| mipsisa64r2-* | mipsisa64r2el-* \\\n\t| mipsisa64sb1-* | mipsisa64sb1el-* \\\n\t| mipsisa64sr71k-* | mipsisa64sr71kel-* \\\n\t| mipsr5900-* | mipsr5900el-* \\\n\t| mipstx39-* | mipstx39el-* \\\n\t| mmix-* \\\n\t| mt-* \\\n\t| msp430-* \\\n\t| nds32-* | nds32le-* | nds32be-* \\\n\t| nios-* | nios2-* | nios2eb-* | nios2el-* \\\n\t| none-* | np1-* | ns16k-* | ns32k-* \\\n\t| open8-* \\\n\t| orion-* \\\n\t| pdp10-* | pdp11-* | pj-* | pjl-* | pn-* | power-* \\\n\t| powerpc-* | powerpc64-* | powerpc64le-* | powerpcle-* \\\n\t| pyramid-* \\\n\t| rl78-* | romp-* | rs6000-* | rx-* \\\n\t| sh-* | sh[1234]-* | sh[24]a-* | sh[24]aeb-* | sh[23]e-* | sh[34]eb-* | sheb-* | shbe-* \\\n\t| shle-* | sh[1234]le-* | sh3ele-* | sh64-* | sh64le-* \\\n\t| sparc-* | sparc64-* | sparc64b-* | sparc64v-* | sparc86x-* | sparclet-* \\\n\t| sparclite-* \\\n\t| sparcv8-* | sparcv9-* | sparcv9b-* | sparcv9v-* | sv1-* | sx?-* \\\n\t| tahoe-* \\\n\t| tic30-* | tic4x-* | tic54x-* | tic55x-* | tic6x-* | tic80-* \\\n\t| tile*-* \\\n\t| tron-* \\\n\t| ubicom32-* \\\n\t| v850-* | v850e-* | v850e1-* | v850es-* | v850e2-* | v850e2v3-* \\\n\t| vax-* \\\n\t| we32k-* \\\n\t| x86-* | x86_64-* | xc16x-* | xps100-* \\\n\t| xstormy16-* | xtensa*-* \\\n\t| ymp-* \\\n\t| z8k-* | z80-*)\n\t\t;;\n\t# Recognize the basic CPU types without company name, with glob match.\n\txtensa*)\n\t\tbasic_machine=$basic_machine-unknown\n\t\t;;\n\t# Recognize the various machine names and aliases which stand\n\t# for a CPU type and a company and sometimes even an OS.\n\t386bsd)\n\t\tbasic_machine=i386-unknown\n\t\tos=-bsd\n\t\t;;\n\t3b1 | 7300 | 7300-att | att-7300 | pc7300 | safari | unixpc)\n\t\tbasic_machine=m68000-att\n\t\t;;\n\t3b*)\n\t\tbasic_machine=we32k-att\n\t\t;;\n\ta29khif)\n\t\tbasic_machine=a29k-amd\n\t\tos=-udi\n\t\t;;\n\tabacus)\n\t\tbasic_machine=abacus-unknown\n\t\t;;\n\tadobe68k)\n\t\tbasic_machine=m68010-adobe\n\t\tos=-scout\n\t\t;;\n\talliant | fx80)\n\t\tbasic_machine=fx80-alliant\n\t\t;;\n\taltos | altos3068)\n\t\tbasic_machine=m68k-altos\n\t\t;;\n\tam29k)\n\t\tbasic_machine=a29k-none\n\t\tos=-bsd\n\t\t;;\n\tamd64)\n\t\tbasic_machine=x86_64-pc\n\t\t;;\n\tamd64-*)\n\t\tbasic_machine=x86_64-`echo $basic_machine | sed 's/^[^-]*-//'`\n\t\t;;\n\tamdahl)\n\t\tbasic_machine=580-amdahl\n\t\tos=-sysv\n\t\t;;\n\tamiga | amiga-*)\n\t\tbasic_machine=m68k-unknown\n\t\t;;\n\tamigaos | amigados)\n\t\tbasic_machine=m68k-unknown\n\t\tos=-amigaos\n\t\t;;\n\tamigaunix | amix)\n\t\tbasic_machine=m68k-unknown\n\t\tos=-sysv4\n\t\t;;\n\tapollo68)\n\t\tbasic_machine=m68k-apollo\n\t\tos=-sysv\n\t\t;;\n\tapollo68bsd)\n\t\tbasic_machine=m68k-apollo\n\t\tos=-bsd\n\t\t;;\n\taros)\n\t\tbasic_machine=i386-pc\n\t\tos=-aros\n\t\t;;\n\taux)\n\t\tbasic_machine=m68k-apple\n\t\tos=-aux\n\t\t;;\n\tbalance)\n\t\tbasic_machine=ns32k-sequent\n\t\tos=-dynix\n\t\t;;\n\tblackfin)\n\t\tbasic_machine=bfin-unknown\n\t\tos=-linux\n\t\t;;\n\tblackfin-*)\n\t\tbasic_machine=bfin-`echo $basic_machine | sed 's/^[^-]*-//'`\n\t\tos=-linux\n\t\t;;\n\tbluegene*)\n\t\tbasic_machine=powerpc-ibm\n\t\tos=-cnk\n\t\t;;\n\tc54x-*)\n\t\tbasic_machine=tic54x-`echo $basic_machine | sed 's/^[^-]*-//'`\n\t\t;;\n\tc55x-*)\n\t\tbasic_machine=tic55x-`echo $basic_machine | sed 's/^[^-]*-//'`\n\t\t;;\n\tc6x-*)\n\t\tbasic_machine=tic6x-`echo $basic_machine | sed 's/^[^-]*-//'`\n\t\t;;\n\tc90)\n\t\tbasic_machine=c90-cray\n\t\tos=-unicos\n\t\t;;\n\tcegcc)\n\t\tbasic_machine=arm-unknown\n\t\tos=-cegcc\n\t\t;;\n\tconvex-c1)\n\t\tbasic_machine=c1-convex\n\t\tos=-bsd\n\t\t;;\n\tconvex-c2)\n\t\tbasic_machine=c2-convex\n\t\tos=-bsd\n\t\t;;\n\tconvex-c32)\n\t\tbasic_machine=c32-convex\n\t\tos=-bsd\n\t\t;;\n\tconvex-c34)\n\t\tbasic_machine=c34-convex\n\t\tos=-bsd\n\t\t;;\n\tconvex-c38)\n\t\tbasic_machine=c38-convex\n\t\tos=-bsd\n\t\t;;\n\tcray | j90)\n\t\tbasic_machine=j90-cray\n\t\tos=-unicos\n\t\t;;\n\tcraynv)\n\t\tbasic_machine=craynv-cray\n\t\tos=-unicosmp\n\t\t;;\n\tcr16 | cr16-*)\n\t\tbasic_machine=cr16-unknown\n\t\tos=-elf\n\t\t;;\n\tcrds | unos)\n\t\tbasic_machine=m68k-crds\n\t\t;;\n\tcrisv32 | crisv32-* | etraxfs*)\n\t\tbasic_machine=crisv32-axis\n\t\t;;\n\tcris | cris-* | etrax*)\n\t\tbasic_machine=cris-axis\n\t\t;;\n\tcrx)\n\t\tbasic_machine=crx-unknown\n\t\tos=-elf\n\t\t;;\n\tda30 | da30-*)\n\t\tbasic_machine=m68k-da30\n\t\t;;\n\tdecstation | decstation-3100 | pmax | pmax-* | pmin | dec3100 | decstatn)\n\t\tbasic_machine=mips-dec\n\t\t;;\n\tdecsystem10* | dec10*)\n\t\tbasic_machine=pdp10-dec\n\t\tos=-tops10\n\t\t;;\n\tdecsystem20* | dec20*)\n\t\tbasic_machine=pdp10-dec\n\t\tos=-tops20\n\t\t;;\n\tdelta | 3300 | motorola-3300 | motorola-delta \\\n\t      | 3300-motorola | delta-motorola)\n\t\tbasic_machine=m68k-motorola\n\t\t;;\n\tdelta88)\n\t\tbasic_machine=m88k-motorola\n\t\tos=-sysv3\n\t\t;;\n\tdicos)\n\t\tbasic_machine=i686-pc\n\t\tos=-dicos\n\t\t;;\n\tdjgpp)\n\t\tbasic_machine=i586-pc\n\t\tos=-msdosdjgpp\n\t\t;;\n\tdpx20 | dpx20-*)\n\t\tbasic_machine=rs6000-bull\n\t\tos=-bosx\n\t\t;;\n\tdpx2* | dpx2*-bull)\n\t\tbasic_machine=m68k-bull\n\t\tos=-sysv3\n\t\t;;\n\tebmon29k)\n\t\tbasic_machine=a29k-amd\n\t\tos=-ebmon\n\t\t;;\n\telxsi)\n\t\tbasic_machine=elxsi-elxsi\n\t\tos=-bsd\n\t\t;;\n\tencore | umax | mmax)\n\t\tbasic_machine=ns32k-encore\n\t\t;;\n\tes1800 | OSE68k | ose68k | ose | OSE)\n\t\tbasic_machine=m68k-ericsson\n\t\tos=-ose\n\t\t;;\n\tfx2800)\n\t\tbasic_machine=i860-alliant\n\t\t;;\n\tgenix)\n\t\tbasic_machine=ns32k-ns\n\t\t;;\n\tgmicro)\n\t\tbasic_machine=tron-gmicro\n\t\tos=-sysv\n\t\t;;\n\tgo32)\n\t\tbasic_machine=i386-pc\n\t\tos=-go32\n\t\t;;\n\th3050r* | hiux*)\n\t\tbasic_machine=hppa1.1-hitachi\n\t\tos=-hiuxwe2\n\t\t;;\n\th8300hms)\n\t\tbasic_machine=h8300-hitachi\n\t\tos=-hms\n\t\t;;\n\th8300xray)\n\t\tbasic_machine=h8300-hitachi\n\t\tos=-xray\n\t\t;;\n\th8500hms)\n\t\tbasic_machine=h8500-hitachi\n\t\tos=-hms\n\t\t;;\n\tharris)\n\t\tbasic_machine=m88k-harris\n\t\tos=-sysv3\n\t\t;;\n\thp300-*)\n\t\tbasic_machine=m68k-hp\n\t\t;;\n\thp300bsd)\n\t\tbasic_machine=m68k-hp\n\t\tos=-bsd\n\t\t;;\n\thp300hpux)\n\t\tbasic_machine=m68k-hp\n\t\tos=-hpux\n\t\t;;\n\thp3k9[0-9][0-9] | hp9[0-9][0-9])\n\t\tbasic_machine=hppa1.0-hp\n\t\t;;\n\thp9k2[0-9][0-9] | hp9k31[0-9])\n\t\tbasic_machine=m68000-hp\n\t\t;;\n\thp9k3[2-9][0-9])\n\t\tbasic_machine=m68k-hp\n\t\t;;\n\thp9k6[0-9][0-9] | hp6[0-9][0-9])\n\t\tbasic_machine=hppa1.0-hp\n\t\t;;\n\thp9k7[0-79][0-9] | hp7[0-79][0-9])\n\t\tbasic_machine=hppa1.1-hp\n\t\t;;\n\thp9k78[0-9] | hp78[0-9])\n\t\t# FIXME: really hppa2.0-hp\n\t\tbasic_machine=hppa1.1-hp\n\t\t;;\n\thp9k8[67]1 | hp8[67]1 | hp9k80[24] | hp80[24] | hp9k8[78]9 | hp8[78]9 | hp9k893 | hp893)\n\t\t# FIXME: really hppa2.0-hp\n\t\tbasic_machine=hppa1.1-hp\n\t\t;;\n\thp9k8[0-9][13679] | hp8[0-9][13679])\n\t\tbasic_machine=hppa1.1-hp\n\t\t;;\n\thp9k8[0-9][0-9] | hp8[0-9][0-9])\n\t\tbasic_machine=hppa1.0-hp\n\t\t;;\n\thppa-next)\n\t\tos=-nextstep3\n\t\t;;\n\thppaosf)\n\t\tbasic_machine=hppa1.1-hp\n\t\tos=-osf\n\t\t;;\n\thppro)\n\t\tbasic_machine=hppa1.1-hp\n\t\tos=-proelf\n\t\t;;\n\ti370-ibm* | ibm*)\n\t\tbasic_machine=i370-ibm\n\t\t;;\n\ti*86v32)\n\t\tbasic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`\n\t\tos=-sysv32\n\t\t;;\n\ti*86v4*)\n\t\tbasic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`\n\t\tos=-sysv4\n\t\t;;\n\ti*86v)\n\t\tbasic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`\n\t\tos=-sysv\n\t\t;;\n\ti*86sol2)\n\t\tbasic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`\n\t\tos=-solaris2\n\t\t;;\n\ti386mach)\n\t\tbasic_machine=i386-mach\n\t\tos=-mach\n\t\t;;\n\ti386-vsta | vsta)\n\t\tbasic_machine=i386-unknown\n\t\tos=-vsta\n\t\t;;\n\tiris | iris4d)\n\t\tbasic_machine=mips-sgi\n\t\tcase $os in\n\t\t    -irix*)\n\t\t\t;;\n\t\t    *)\n\t\t\tos=-irix4\n\t\t\t;;\n\t\tesac\n\t\t;;\n\tisi68 | isi)\n\t\tbasic_machine=m68k-isi\n\t\tos=-sysv\n\t\t;;\n\tm68knommu)\n\t\tbasic_machine=m68k-unknown\n\t\tos=-linux\n\t\t;;\n\tm68knommu-*)\n\t\tbasic_machine=m68k-`echo $basic_machine | sed 's/^[^-]*-//'`\n\t\tos=-linux\n\t\t;;\n\tm88k-omron*)\n\t\tbasic_machine=m88k-omron\n\t\t;;\n\tmagnum | m3230)\n\t\tbasic_machine=mips-mips\n\t\tos=-sysv\n\t\t;;\n\tmerlin)\n\t\tbasic_machine=ns32k-utek\n\t\tos=-sysv\n\t\t;;\n\tmicroblaze*)\n\t\tbasic_machine=microblaze-xilinx\n\t\t;;\n\tmingw64)\n\t\tbasic_machine=x86_64-pc\n\t\tos=-mingw64\n\t\t;;\n\tmingw32)\n\t\tbasic_machine=i686-pc\n\t\tos=-mingw32\n\t\t;;\n\tmingw32ce)\n\t\tbasic_machine=arm-unknown\n\t\tos=-mingw32ce\n\t\t;;\n\tminiframe)\n\t\tbasic_machine=m68000-convergent\n\t\t;;\n\t*mint | -mint[0-9]* | *MiNT | *MiNT[0-9]*)\n\t\tbasic_machine=m68k-atari\n\t\tos=-mint\n\t\t;;\n\tmips3*-*)\n\t\tbasic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'`\n\t\t;;\n\tmips3*)\n\t\tbasic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'`-unknown\n\t\t;;\n\tmonitor)\n\t\tbasic_machine=m68k-rom68k\n\t\tos=-coff\n\t\t;;\n\tmorphos)\n\t\tbasic_machine=powerpc-unknown\n\t\tos=-morphos\n\t\t;;\n\tmsdos)\n\t\tbasic_machine=i386-pc\n\t\tos=-msdos\n\t\t;;\n\tms1-*)\n\t\tbasic_machine=`echo $basic_machine | sed -e 's/ms1-/mt-/'`\n\t\t;;\n\tmsys)\n\t\tbasic_machine=i686-pc\n\t\tos=-msys\n\t\t;;\n\tmvs)\n\t\tbasic_machine=i370-ibm\n\t\tos=-mvs\n\t\t;;\n\tnacl)\n\t\tbasic_machine=le32-unknown\n\t\tos=-nacl\n\t\t;;\n\tncr3000)\n\t\tbasic_machine=i486-ncr\n\t\tos=-sysv4\n\t\t;;\n\tnetbsd386)\n\t\tbasic_machine=i386-unknown\n\t\tos=-netbsd\n\t\t;;\n\tnetwinder)\n\t\tbasic_machine=armv4l-rebel\n\t\tos=-linux\n\t\t;;\n\tnews | news700 | news800 | news900)\n\t\tbasic_machine=m68k-sony\n\t\tos=-newsos\n\t\t;;\n\tnews1000)\n\t\tbasic_machine=m68030-sony\n\t\tos=-newsos\n\t\t;;\n\tnews-3600 | risc-news)\n\t\tbasic_machine=mips-sony\n\t\tos=-newsos\n\t\t;;\n\tnecv70)\n\t\tbasic_machine=v70-nec\n\t\tos=-sysv\n\t\t;;\n\tnext | m*-next )\n\t\tbasic_machine=m68k-next\n\t\tcase $os in\n\t\t    -nextstep* )\n\t\t\t;;\n\t\t    -ns2*)\n\t\t      os=-nextstep2\n\t\t\t;;\n\t\t    *)\n\t\t      os=-nextstep3\n\t\t\t;;\n\t\tesac\n\t\t;;\n\tnh3000)\n\t\tbasic_machine=m68k-harris\n\t\tos=-cxux\n\t\t;;\n\tnh[45]000)\n\t\tbasic_machine=m88k-harris\n\t\tos=-cxux\n\t\t;;\n\tnindy960)\n\t\tbasic_machine=i960-intel\n\t\tos=-nindy\n\t\t;;\n\tmon960)\n\t\tbasic_machine=i960-intel\n\t\tos=-mon960\n\t\t;;\n\tnonstopux)\n\t\tbasic_machine=mips-compaq\n\t\tos=-nonstopux\n\t\t;;\n\tnp1)\n\t\tbasic_machine=np1-gould\n\t\t;;\n\tneo-tandem)\n\t\tbasic_machine=neo-tandem\n\t\t;;\n\tnse-tandem)\n\t\tbasic_machine=nse-tandem\n\t\t;;\n\tnsr-tandem)\n\t\tbasic_machine=nsr-tandem\n\t\t;;\n\top50n-* | op60c-*)\n\t\tbasic_machine=hppa1.1-oki\n\t\tos=-proelf\n\t\t;;\n\topenrisc | openrisc-*)\n\t\tbasic_machine=or32-unknown\n\t\t;;\n\tos400)\n\t\tbasic_machine=powerpc-ibm\n\t\tos=-os400\n\t\t;;\n\tOSE68000 | ose68000)\n\t\tbasic_machine=m68000-ericsson\n\t\tos=-ose\n\t\t;;\n\tos68k)\n\t\tbasic_machine=m68k-none\n\t\tos=-os68k\n\t\t;;\n\tpa-hitachi)\n\t\tbasic_machine=hppa1.1-hitachi\n\t\tos=-hiuxwe2\n\t\t;;\n\tparagon)\n\t\tbasic_machine=i860-intel\n\t\tos=-osf\n\t\t;;\n\tparisc)\n\t\tbasic_machine=hppa-unknown\n\t\tos=-linux\n\t\t;;\n\tparisc-*)\n\t\tbasic_machine=hppa-`echo $basic_machine | sed 's/^[^-]*-//'`\n\t\tos=-linux\n\t\t;;\n\tpbd)\n\t\tbasic_machine=sparc-tti\n\t\t;;\n\tpbb)\n\t\tbasic_machine=m68k-tti\n\t\t;;\n\tpc532 | pc532-*)\n\t\tbasic_machine=ns32k-pc532\n\t\t;;\n\tpc98)\n\t\tbasic_machine=i386-pc\n\t\t;;\n\tpc98-*)\n\t\tbasic_machine=i386-`echo $basic_machine | sed 's/^[^-]*-//'`\n\t\t;;\n\tpentium | p5 | k5 | k6 | nexgen | viac3)\n\t\tbasic_machine=i586-pc\n\t\t;;\n\tpentiumpro | p6 | 6x86 | athlon | athlon_*)\n\t\tbasic_machine=i686-pc\n\t\t;;\n\tpentiumii | pentium2 | pentiumiii | pentium3)\n\t\tbasic_machine=i686-pc\n\t\t;;\n\tpentium4)\n\t\tbasic_machine=i786-pc\n\t\t;;\n\tpentium-* | p5-* | k5-* | k6-* | nexgen-* | viac3-*)\n\t\tbasic_machine=i586-`echo $basic_machine | sed 's/^[^-]*-//'`\n\t\t;;\n\tpentiumpro-* | p6-* | 6x86-* | athlon-*)\n\t\tbasic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'`\n\t\t;;\n\tpentiumii-* | pentium2-* | pentiumiii-* | pentium3-*)\n\t\tbasic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'`\n\t\t;;\n\tpentium4-*)\n\t\tbasic_machine=i786-`echo $basic_machine | sed 's/^[^-]*-//'`\n\t\t;;\n\tpn)\n\t\tbasic_machine=pn-gould\n\t\t;;\n\tpower)\tbasic_machine=power-ibm\n\t\t;;\n\tppc | ppcbe)\tbasic_machine=powerpc-unknown\n\t\t;;\n\tppc-* | ppcbe-*)\n\t\tbasic_machine=powerpc-`echo $basic_machine | sed 's/^[^-]*-//'`\n\t\t;;\n\tppcle | powerpclittle | ppc-le | powerpc-little)\n\t\tbasic_machine=powerpcle-unknown\n\t\t;;\n\tppcle-* | powerpclittle-*)\n\t\tbasic_machine=powerpcle-`echo $basic_machine | sed 's/^[^-]*-//'`\n\t\t;;\n\tppc64)\tbasic_machine=powerpc64-unknown\n\t\t;;\n\tppc64-*) basic_machine=powerpc64-`echo $basic_machine | sed 's/^[^-]*-//'`\n\t\t;;\n\tppc64le | powerpc64little | ppc64-le | powerpc64-little)\n\t\tbasic_machine=powerpc64le-unknown\n\t\t;;\n\tppc64le-* | powerpc64little-*)\n\t\tbasic_machine=powerpc64le-`echo $basic_machine | sed 's/^[^-]*-//'`\n\t\t;;\n\tps2)\n\t\tbasic_machine=i386-ibm\n\t\t;;\n\tpw32)\n\t\tbasic_machine=i586-unknown\n\t\tos=-pw32\n\t\t;;\n\trdos | rdos64)\n\t\tbasic_machine=x86_64-pc\n\t\tos=-rdos\n\t\t;;\n\trdos32)\n\t\tbasic_machine=i386-pc\n\t\tos=-rdos\n\t\t;;\n\trom68k)\n\t\tbasic_machine=m68k-rom68k\n\t\tos=-coff\n\t\t;;\n\trm[46]00)\n\t\tbasic_machine=mips-siemens\n\t\t;;\n\trtpc | rtpc-*)\n\t\tbasic_machine=romp-ibm\n\t\t;;\n\ts390 | s390-*)\n\t\tbasic_machine=s390-ibm\n\t\t;;\n\ts390x | s390x-*)\n\t\tbasic_machine=s390x-ibm\n\t\t;;\n\tsa29200)\n\t\tbasic_machine=a29k-amd\n\t\tos=-udi\n\t\t;;\n\tsb1)\n\t\tbasic_machine=mipsisa64sb1-unknown\n\t\t;;\n\tsb1el)\n\t\tbasic_machine=mipsisa64sb1el-unknown\n\t\t;;\n\tsde)\n\t\tbasic_machine=mipsisa32-sde\n\t\tos=-elf\n\t\t;;\n\tsei)\n\t\tbasic_machine=mips-sei\n\t\tos=-seiux\n\t\t;;\n\tsequent)\n\t\tbasic_machine=i386-sequent\n\t\t;;\n\tsh)\n\t\tbasic_machine=sh-hitachi\n\t\tos=-hms\n\t\t;;\n\tsh5el)\n\t\tbasic_machine=sh5le-unknown\n\t\t;;\n\tsh64)\n\t\tbasic_machine=sh64-unknown\n\t\t;;\n\tsparclite-wrs | simso-wrs)\n\t\tbasic_machine=sparclite-wrs\n\t\tos=-vxworks\n\t\t;;\n\tsps7)\n\t\tbasic_machine=m68k-bull\n\t\tos=-sysv2\n\t\t;;\n\tspur)\n\t\tbasic_machine=spur-unknown\n\t\t;;\n\tst2000)\n\t\tbasic_machine=m68k-tandem\n\t\t;;\n\tstratus)\n\t\tbasic_machine=i860-stratus\n\t\tos=-sysv4\n\t\t;;\n\tstrongarm-* | thumb-*)\n\t\tbasic_machine=arm-`echo $basic_machine | sed 's/^[^-]*-//'`\n\t\t;;\n\tsun2)\n\t\tbasic_machine=m68000-sun\n\t\t;;\n\tsun2os3)\n\t\tbasic_machine=m68000-sun\n\t\tos=-sunos3\n\t\t;;\n\tsun2os4)\n\t\tbasic_machine=m68000-sun\n\t\tos=-sunos4\n\t\t;;\n\tsun3os3)\n\t\tbasic_machine=m68k-sun\n\t\tos=-sunos3\n\t\t;;\n\tsun3os4)\n\t\tbasic_machine=m68k-sun\n\t\tos=-sunos4\n\t\t;;\n\tsun4os3)\n\t\tbasic_machine=sparc-sun\n\t\tos=-sunos3\n\t\t;;\n\tsun4os4)\n\t\tbasic_machine=sparc-sun\n\t\tos=-sunos4\n\t\t;;\n\tsun4sol2)\n\t\tbasic_machine=sparc-sun\n\t\tos=-solaris2\n\t\t;;\n\tsun3 | sun3-*)\n\t\tbasic_machine=m68k-sun\n\t\t;;\n\tsun4)\n\t\tbasic_machine=sparc-sun\n\t\t;;\n\tsun386 | sun386i | roadrunner)\n\t\tbasic_machine=i386-sun\n\t\t;;\n\tsv1)\n\t\tbasic_machine=sv1-cray\n\t\tos=-unicos\n\t\t;;\n\tsymmetry)\n\t\tbasic_machine=i386-sequent\n\t\tos=-dynix\n\t\t;;\n\tt3e)\n\t\tbasic_machine=alphaev5-cray\n\t\tos=-unicos\n\t\t;;\n\tt90)\n\t\tbasic_machine=t90-cray\n\t\tos=-unicos\n\t\t;;\n\ttile*)\n\t\tbasic_machine=$basic_machine-unknown\n\t\tos=-linux-gnu\n\t\t;;\n\ttx39)\n\t\tbasic_machine=mipstx39-unknown\n\t\t;;\n\ttx39el)\n\t\tbasic_machine=mipstx39el-unknown\n\t\t;;\n\ttoad1)\n\t\tbasic_machine=pdp10-xkl\n\t\tos=-tops20\n\t\t;;\n\ttower | tower-32)\n\t\tbasic_machine=m68k-ncr\n\t\t;;\n\ttpf)\n\t\tbasic_machine=s390x-ibm\n\t\tos=-tpf\n\t\t;;\n\tudi29k)\n\t\tbasic_machine=a29k-amd\n\t\tos=-udi\n\t\t;;\n\tultra3)\n\t\tbasic_machine=a29k-nyu\n\t\tos=-sym1\n\t\t;;\n\tv810 | necv810)\n\t\tbasic_machine=v810-nec\n\t\tos=-none\n\t\t;;\n\tvaxv)\n\t\tbasic_machine=vax-dec\n\t\tos=-sysv\n\t\t;;\n\tvms)\n\t\tbasic_machine=vax-dec\n\t\tos=-vms\n\t\t;;\n\tvpp*|vx|vx-*)\n\t\tbasic_machine=f301-fujitsu\n\t\t;;\n\tvxworks960)\n\t\tbasic_machine=i960-wrs\n\t\tos=-vxworks\n\t\t;;\n\tvxworks68)\n\t\tbasic_machine=m68k-wrs\n\t\tos=-vxworks\n\t\t;;\n\tvxworks29k)\n\t\tbasic_machine=a29k-wrs\n\t\tos=-vxworks\n\t\t;;\n\tw65*)\n\t\tbasic_machine=w65-wdc\n\t\tos=-none\n\t\t;;\n\tw89k-*)\n\t\tbasic_machine=hppa1.1-winbond\n\t\tos=-proelf\n\t\t;;\n\txbox)\n\t\tbasic_machine=i686-pc\n\t\tos=-mingw32\n\t\t;;\n\txps | xps100)\n\t\tbasic_machine=xps100-honeywell\n\t\t;;\n\txscale-* | xscalee[bl]-*)\n\t\tbasic_machine=`echo $basic_machine | sed 's/^xscale/arm/'`\n\t\t;;\n\tymp)\n\t\tbasic_machine=ymp-cray\n\t\tos=-unicos\n\t\t;;\n\tz8k-*-coff)\n\t\tbasic_machine=z8k-unknown\n\t\tos=-sim\n\t\t;;\n\tz80-*-coff)\n\t\tbasic_machine=z80-unknown\n\t\tos=-sim\n\t\t;;\n\tnone)\n\t\tbasic_machine=none-none\n\t\tos=-none\n\t\t;;\n\n# Here we handle the default manufacturer of certain CPU types.  It is in\n# some cases the only manufacturer, in others, it is the most popular.\n\tw89k)\n\t\tbasic_machine=hppa1.1-winbond\n\t\t;;\n\top50n)\n\t\tbasic_machine=hppa1.1-oki\n\t\t;;\n\top60c)\n\t\tbasic_machine=hppa1.1-oki\n\t\t;;\n\tromp)\n\t\tbasic_machine=romp-ibm\n\t\t;;\n\tmmix)\n\t\tbasic_machine=mmix-knuth\n\t\t;;\n\trs6000)\n\t\tbasic_machine=rs6000-ibm\n\t\t;;\n\tvax)\n\t\tbasic_machine=vax-dec\n\t\t;;\n\tpdp10)\n\t\t# there are many clones, so DEC is not a safe bet\n\t\tbasic_machine=pdp10-unknown\n\t\t;;\n\tpdp11)\n\t\tbasic_machine=pdp11-dec\n\t\t;;\n\twe32k)\n\t\tbasic_machine=we32k-att\n\t\t;;\n\tsh[1234] | sh[24]a | sh[24]aeb | sh[34]eb | sh[1234]le | sh[23]ele)\n\t\tbasic_machine=sh-unknown\n\t\t;;\n\tsparc | sparcv8 | sparcv9 | sparcv9b | sparcv9v)\n\t\tbasic_machine=sparc-sun\n\t\t;;\n\tcydra)\n\t\tbasic_machine=cydra-cydrome\n\t\t;;\n\torion)\n\t\tbasic_machine=orion-highlevel\n\t\t;;\n\torion105)\n\t\tbasic_machine=clipper-highlevel\n\t\t;;\n\tmac | mpw | mac-mpw)\n\t\tbasic_machine=m68k-apple\n\t\t;;\n\tpmac | pmac-mpw)\n\t\tbasic_machine=powerpc-apple\n\t\t;;\n\t*-unknown)\n\t\t# Make sure to match an already-canonicalized machine name.\n\t\t;;\n\t*)\n\t\techo Invalid configuration \\`$1\\': machine \\`$basic_machine\\' not recognized 1>&2\n\t\texit 1\n\t\t;;\nesac\n\n# Here we canonicalize certain aliases for manufacturers.\ncase $basic_machine in\n\t*-digital*)\n\t\tbasic_machine=`echo $basic_machine | sed 's/digital.*/dec/'`\n\t\t;;\n\t*-commodore*)\n\t\tbasic_machine=`echo $basic_machine | sed 's/commodore.*/cbm/'`\n\t\t;;\n\t*)\n\t\t;;\nesac\n\n# Decode manufacturer-specific aliases for certain operating systems.\n\nif [ x\"$os\" != x\"\" ]\nthen\ncase $os in\n\t# First match some system type aliases\n\t# that might get confused with valid system types.\n\t# -solaris* is a basic system type, with this one exception.\n\t-auroraux)\n\t\tos=-auroraux\n\t\t;;\n\t-solaris1 | -solaris1.*)\n\t\tos=`echo $os | sed -e 's|solaris1|sunos4|'`\n\t\t;;\n\t-solaris)\n\t\tos=-solaris2\n\t\t;;\n\t-svr4*)\n\t\tos=-sysv4\n\t\t;;\n\t-unixware*)\n\t\tos=-sysv4.2uw\n\t\t;;\n\t-gnu/linux*)\n\t\tos=`echo $os | sed -e 's|gnu/linux|linux-gnu|'`\n\t\t;;\n\t# First accept the basic system types.\n\t# The portable systems comes first.\n\t# Each alternative MUST END IN A *, to match a version number.\n\t# -sysv* is not here because it comes later, after sysvr4.\n\t-gnu* | -bsd* | -mach* | -minix* | -genix* | -ultrix* | -irix* \\\n\t      | -*vms* | -sco* | -esix* | -isc* | -aix* | -cnk* | -sunos | -sunos[34]*\\\n\t      | -hpux* | -unos* | -osf* | -luna* | -dgux* | -auroraux* | -solaris* \\\n\t      | -sym* | -kopensolaris* | -plan9* \\\n\t      | -amigaos* | -amigados* | -msdos* | -newsos* | -unicos* | -aof* \\\n\t      | -aos* | -aros* \\\n\t      | -nindy* | -vxsim* | -vxworks* | -ebmon* | -hms* | -mvs* \\\n\t      | -clix* | -riscos* | -uniplus* | -iris* | -rtu* | -xenix* \\\n\t      | -hiux* | -386bsd* | -knetbsd* | -mirbsd* | -netbsd* \\\n\t      | -bitrig* | -openbsd* | -solidbsd* \\\n\t      | -ekkobsd* | -kfreebsd* | -freebsd* | -riscix* | -lynxos* \\\n\t      | -bosx* | -nextstep* | -cxux* | -aout* | -elf* | -oabi* \\\n\t      | -ptx* | -coff* | -ecoff* | -winnt* | -domain* | -vsta* \\\n\t      | -udi* | -eabi* | -lites* | -ieee* | -go32* | -aux* \\\n\t      | -chorusos* | -chorusrdb* | -cegcc* \\\n\t      | -cygwin* | -msys* | -pe* | -psos* | -moss* | -proelf* | -rtems* \\\n\t      | -mingw32* | -mingw64* | -linux-gnu* | -linux-android* \\\n\t      | -linux-newlib* | -linux-musl* | -linux-uclibc* \\\n\t      | -uxpv* | -beos* | -mpeix* | -udk* \\\n\t      | -interix* | -uwin* | -mks* | -rhapsody* | -darwin* | -opened* \\\n\t      | -openstep* | -oskit* | -conix* | -pw32* | -nonstopux* \\\n\t      | -storm-chaos* | -tops10* | -tenex* | -tops20* | -its* \\\n\t      | -os2* | -vos* | -palmos* | -uclinux* | -nucleus* \\\n\t      | -morphos* | -superux* | -rtmk* | -rtmk-nova* | -windiss* \\\n\t      | -powermax* | -dnix* | -nx6 | -nx7 | -sei* | -dragonfly* \\\n\t      | -skyos* | -haiku* | -rdos* | -toppers* | -drops* | -es*)\n\t# Remember, each alternative MUST END IN *, to match a version number.\n\t\t;;\n\t-qnx*)\n\t\tcase $basic_machine in\n\t\t    x86-* | i*86-*)\n\t\t\t;;\n\t\t    *)\n\t\t\tos=-nto$os\n\t\t\t;;\n\t\tesac\n\t\t;;\n\t-nto-qnx*)\n\t\t;;\n\t-nto*)\n\t\tos=`echo $os | sed -e 's|nto|nto-qnx|'`\n\t\t;;\n\t-sim | -es1800* | -hms* | -xray | -os68k* | -none* | -v88r* \\\n\t      | -windows* | -osx | -abug | -netware* | -os9* | -beos* | -haiku* \\\n\t      | -macos* | -mpw* | -magic* | -mmixware* | -mon960* | -lnews*)\n\t\t;;\n\t-mac*)\n\t\tos=`echo $os | sed -e 's|mac|macos|'`\n\t\t;;\n\t-linux-dietlibc)\n\t\tos=-linux-dietlibc\n\t\t;;\n\t-linux*)\n\t\tos=`echo $os | sed -e 's|linux|linux-gnu|'`\n\t\t;;\n\t-sunos5*)\n\t\tos=`echo $os | sed -e 's|sunos5|solaris2|'`\n\t\t;;\n\t-sunos6*)\n\t\tos=`echo $os | sed -e 's|sunos6|solaris3|'`\n\t\t;;\n\t-opened*)\n\t\tos=-openedition\n\t\t;;\n\t-os400*)\n\t\tos=-os400\n\t\t;;\n\t-wince*)\n\t\tos=-wince\n\t\t;;\n\t-osfrose*)\n\t\tos=-osfrose\n\t\t;;\n\t-osf*)\n\t\tos=-osf\n\t\t;;\n\t-utek*)\n\t\tos=-bsd\n\t\t;;\n\t-dynix*)\n\t\tos=-bsd\n\t\t;;\n\t-acis*)\n\t\tos=-aos\n\t\t;;\n\t-atheos*)\n\t\tos=-atheos\n\t\t;;\n\t-syllable*)\n\t\tos=-syllable\n\t\t;;\n\t-386bsd)\n\t\tos=-bsd\n\t\t;;\n\t-ctix* | -uts*)\n\t\tos=-sysv\n\t\t;;\n\t-nova*)\n\t\tos=-rtmk-nova\n\t\t;;\n\t-ns2 )\n\t\tos=-nextstep2\n\t\t;;\n\t-nsk*)\n\t\tos=-nsk\n\t\t;;\n\t# Preserve the version number of sinix5.\n\t-sinix5.*)\n\t\tos=`echo $os | sed -e 's|sinix|sysv|'`\n\t\t;;\n\t-sinix*)\n\t\tos=-sysv4\n\t\t;;\n\t-tpf*)\n\t\tos=-tpf\n\t\t;;\n\t-triton*)\n\t\tos=-sysv3\n\t\t;;\n\t-oss*)\n\t\tos=-sysv3\n\t\t;;\n\t-svr4)\n\t\tos=-sysv4\n\t\t;;\n\t-svr3)\n\t\tos=-sysv3\n\t\t;;\n\t-sysvr4)\n\t\tos=-sysv4\n\t\t;;\n\t# This must come after -sysvr4.\n\t-sysv*)\n\t\t;;\n\t-ose*)\n\t\tos=-ose\n\t\t;;\n\t-es1800*)\n\t\tos=-ose\n\t\t;;\n\t-xenix)\n\t\tos=-xenix\n\t\t;;\n\t-*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*)\n\t\tos=-mint\n\t\t;;\n\t-aros*)\n\t\tos=-aros\n\t\t;;\n\t-zvmoe)\n\t\tos=-zvmoe\n\t\t;;\n\t-dicos*)\n\t\tos=-dicos\n\t\t;;\n\t-nacl*)\n\t\t;;\n\t-none)\n\t\t;;\n\t*)\n\t\t# Get rid of the `-' at the beginning of $os.\n\t\tos=`echo $os | sed 's/[^-]*-//'`\n\t\techo Invalid configuration \\`$1\\': system \\`$os\\' not recognized 1>&2\n\t\texit 1\n\t\t;;\nesac\nelse\n\n# Here we handle the default operating systems that come with various machines.\n# The value should be what the vendor currently ships out the door with their\n# machine or put another way, the most popular os provided with the machine.\n\n# Note that if you're going to try to match \"-MANUFACTURER\" here (say,\n# \"-sun\"), then you have to tell the case statement up towards the top\n# that MANUFACTURER isn't an operating system.  Otherwise, code above\n# will signal an error saying that MANUFACTURER isn't an operating\n# system, and we'll never get to this point.\n\ncase $basic_machine in\n\tscore-*)\n\t\tos=-elf\n\t\t;;\n\tspu-*)\n\t\tos=-elf\n\t\t;;\n\t*-acorn)\n\t\tos=-riscix1.2\n\t\t;;\n\tarm*-rebel)\n\t\tos=-linux\n\t\t;;\n\tarm*-semi)\n\t\tos=-aout\n\t\t;;\n\tc4x-* | tic4x-*)\n\t\tos=-coff\n\t\t;;\n\tc8051-*)\n\t\tos=-elf\n\t\t;;\n\thexagon-*)\n\t\tos=-elf\n\t\t;;\n\ttic54x-*)\n\t\tos=-coff\n\t\t;;\n\ttic55x-*)\n\t\tos=-coff\n\t\t;;\n\ttic6x-*)\n\t\tos=-coff\n\t\t;;\n\t# This must come before the *-dec entry.\n\tpdp10-*)\n\t\tos=-tops20\n\t\t;;\n\tpdp11-*)\n\t\tos=-none\n\t\t;;\n\t*-dec | vax-*)\n\t\tos=-ultrix4.2\n\t\t;;\n\tm68*-apollo)\n\t\tos=-domain\n\t\t;;\n\ti386-sun)\n\t\tos=-sunos4.0.2\n\t\t;;\n\tm68000-sun)\n\t\tos=-sunos3\n\t\t;;\n\tm68*-cisco)\n\t\tos=-aout\n\t\t;;\n\tmep-*)\n\t\tos=-elf\n\t\t;;\n\tmips*-cisco)\n\t\tos=-elf\n\t\t;;\n\tmips*-*)\n\t\tos=-elf\n\t\t;;\n\tor1k-*)\n\t\tos=-elf\n\t\t;;\n\tor32-*)\n\t\tos=-coff\n\t\t;;\n\t*-tti)\t# must be before sparc entry or we get the wrong os.\n\t\tos=-sysv3\n\t\t;;\n\tsparc-* | *-sun)\n\t\tos=-sunos4.1.1\n\t\t;;\n\t*-be)\n\t\tos=-beos\n\t\t;;\n\t*-haiku)\n\t\tos=-haiku\n\t\t;;\n\t*-ibm)\n\t\tos=-aix\n\t\t;;\n\t*-knuth)\n\t\tos=-mmixware\n\t\t;;\n\t*-wec)\n\t\tos=-proelf\n\t\t;;\n\t*-winbond)\n\t\tos=-proelf\n\t\t;;\n\t*-oki)\n\t\tos=-proelf\n\t\t;;\n\t*-hp)\n\t\tos=-hpux\n\t\t;;\n\t*-hitachi)\n\t\tos=-hiux\n\t\t;;\n\ti860-* | *-att | *-ncr | *-altos | *-motorola | *-convergent)\n\t\tos=-sysv\n\t\t;;\n\t*-cbm)\n\t\tos=-amigaos\n\t\t;;\n\t*-dg)\n\t\tos=-dgux\n\t\t;;\n\t*-dolphin)\n\t\tos=-sysv3\n\t\t;;\n\tm68k-ccur)\n\t\tos=-rtu\n\t\t;;\n\tm88k-omron*)\n\t\tos=-luna\n\t\t;;\n\t*-next )\n\t\tos=-nextstep\n\t\t;;\n\t*-sequent)\n\t\tos=-ptx\n\t\t;;\n\t*-crds)\n\t\tos=-unos\n\t\t;;\n\t*-ns)\n\t\tos=-genix\n\t\t;;\n\ti370-*)\n\t\tos=-mvs\n\t\t;;\n\t*-next)\n\t\tos=-nextstep3\n\t\t;;\n\t*-gould)\n\t\tos=-sysv\n\t\t;;\n\t*-highlevel)\n\t\tos=-bsd\n\t\t;;\n\t*-encore)\n\t\tos=-bsd\n\t\t;;\n\t*-sgi)\n\t\tos=-irix\n\t\t;;\n\t*-siemens)\n\t\tos=-sysv4\n\t\t;;\n\t*-masscomp)\n\t\tos=-rtu\n\t\t;;\n\tf30[01]-fujitsu | f700-fujitsu)\n\t\tos=-uxpv\n\t\t;;\n\t*-rom68k)\n\t\tos=-coff\n\t\t;;\n\t*-*bug)\n\t\tos=-coff\n\t\t;;\n\t*-apple)\n\t\tos=-macos\n\t\t;;\n\t*-atari*)\n\t\tos=-mint\n\t\t;;\n\t*)\n\t\tos=-none\n\t\t;;\nesac\nfi\n\n# Here we handle the case where we know the os, and the CPU type, but not the\n# manufacturer.  We pick the logical manufacturer.\nvendor=unknown\ncase $basic_machine in\n\t*-unknown)\n\t\tcase $os in\n\t\t\t-riscix*)\n\t\t\t\tvendor=acorn\n\t\t\t\t;;\n\t\t\t-sunos*)\n\t\t\t\tvendor=sun\n\t\t\t\t;;\n\t\t\t-cnk*|-aix*)\n\t\t\t\tvendor=ibm\n\t\t\t\t;;\n\t\t\t-beos*)\n\t\t\t\tvendor=be\n\t\t\t\t;;\n\t\t\t-hpux*)\n\t\t\t\tvendor=hp\n\t\t\t\t;;\n\t\t\t-mpeix*)\n\t\t\t\tvendor=hp\n\t\t\t\t;;\n\t\t\t-hiux*)\n\t\t\t\tvendor=hitachi\n\t\t\t\t;;\n\t\t\t-unos*)\n\t\t\t\tvendor=crds\n\t\t\t\t;;\n\t\t\t-dgux*)\n\t\t\t\tvendor=dg\n\t\t\t\t;;\n\t\t\t-luna*)\n\t\t\t\tvendor=omron\n\t\t\t\t;;\n\t\t\t-genix*)\n\t\t\t\tvendor=ns\n\t\t\t\t;;\n\t\t\t-mvs* | -opened*)\n\t\t\t\tvendor=ibm\n\t\t\t\t;;\n\t\t\t-os400*)\n\t\t\t\tvendor=ibm\n\t\t\t\t;;\n\t\t\t-ptx*)\n\t\t\t\tvendor=sequent\n\t\t\t\t;;\n\t\t\t-tpf*)\n\t\t\t\tvendor=ibm\n\t\t\t\t;;\n\t\t\t-vxsim* | -vxworks* | -windiss*)\n\t\t\t\tvendor=wrs\n\t\t\t\t;;\n\t\t\t-aux*)\n\t\t\t\tvendor=apple\n\t\t\t\t;;\n\t\t\t-hms*)\n\t\t\t\tvendor=hitachi\n\t\t\t\t;;\n\t\t\t-mpw* | -macos*)\n\t\t\t\tvendor=apple\n\t\t\t\t;;\n\t\t\t-*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*)\n\t\t\t\tvendor=atari\n\t\t\t\t;;\n\t\t\t-vos*)\n\t\t\t\tvendor=stratus\n\t\t\t\t;;\n\t\tesac\n\t\tbasic_machine=`echo $basic_machine | sed \"s/unknown/$vendor/\"`\n\t\t;;\nesac\n\necho $basic_machine$os\nexit\n\n# Local variables:\n# eval: (add-hook 'write-file-hooks 'time-stamp)\n# time-stamp-start: \"timestamp='\"\n# time-stamp-format: \"%:y-%02m-%02d\"\n# time-stamp-end: \"'\"\n# End:\n"
  },
  {
    "path": "extern/deprecated/redis-2.8.21/deps/jemalloc/configure.ac",
    "content": "dnl Process this file with autoconf to produce a configure script.\nAC_INIT([Makefile.in])\n\ndnl ============================================================================\ndnl Custom macro definitions.\n\ndnl JE_CFLAGS_APPEND(cflag)\nAC_DEFUN([JE_CFLAGS_APPEND],\n[\nAC_MSG_CHECKING([whether compiler supports $1])\nTCFLAGS=\"${CFLAGS}\"\nif test \"x${CFLAGS}\" = \"x\" ; then\n  CFLAGS=\"$1\"\nelse\n  CFLAGS=\"${CFLAGS} $1\"\nfi\nAC_COMPILE_IFELSE([AC_LANG_PROGRAM(\n[[\n]], [[\n    return 0;\n]])],\n              [je_cv_cflags_appended=$1]\n              AC_MSG_RESULT([yes]),\n              [je_cv_cflags_appended=]\n              AC_MSG_RESULT([no])\n              [CFLAGS=\"${TCFLAGS}\"]\n)\n])\n\ndnl JE_COMPILABLE(label, hcode, mcode, rvar)\ndnl \ndnl Use AC_LINK_IFELSE() rather than AC_COMPILE_IFELSE() so that linker errors\ndnl cause failure.\nAC_DEFUN([JE_COMPILABLE],\n[\nAC_CACHE_CHECK([whether $1 is compilable],\n               [$4],\n               [AC_LINK_IFELSE([AC_LANG_PROGRAM([$2],\n                                                [$3])],\n                               [$4=yes],\n                               [$4=no])])\n])\n\ndnl ============================================================================\n\ndnl Library revision.\nrev=1\nAC_SUBST([rev])\n\nsrcroot=$srcdir\nif test \"x${srcroot}\" = \"x.\" ; then\n  srcroot=\"\"\nelse\n  srcroot=\"${srcroot}/\"\nfi\nAC_SUBST([srcroot])\nabs_srcroot=\"`cd \\\"${srcdir}\\\"; pwd`/\"\nAC_SUBST([abs_srcroot])\n\nobjroot=\"\"\nAC_SUBST([objroot])\nabs_objroot=\"`pwd`/\"\nAC_SUBST([abs_objroot])\n\ndnl Munge install path variables.\nif test \"x$prefix\" = \"xNONE\" ; then\n  prefix=\"/usr/local\"\nfi\nif test \"x$exec_prefix\" = \"xNONE\" ; then\n  exec_prefix=$prefix\nfi\nPREFIX=$prefix\nAC_SUBST([PREFIX])\nBINDIR=`eval echo $bindir`\nBINDIR=`eval echo $BINDIR`\nAC_SUBST([BINDIR])\nINCLUDEDIR=`eval echo $includedir`\nINCLUDEDIR=`eval echo $INCLUDEDIR`\nAC_SUBST([INCLUDEDIR])\nLIBDIR=`eval echo $libdir`\nLIBDIR=`eval echo $LIBDIR`\nAC_SUBST([LIBDIR])\nDATADIR=`eval echo $datadir`\nDATADIR=`eval echo $DATADIR`\nAC_SUBST([DATADIR])\nMANDIR=`eval echo $mandir`\nMANDIR=`eval echo $MANDIR`\nAC_SUBST([MANDIR])\n\ndnl Support for building documentation.\nAC_PATH_PROG([XSLTPROC], [xsltproc], [false], [$PATH])\nif test -d \"/usr/share/xml/docbook/stylesheet/docbook-xsl\" ; then\n  DEFAULT_XSLROOT=\"/usr/share/xml/docbook/stylesheet/docbook-xsl\"\nelif test -d \"/usr/share/sgml/docbook/xsl-stylesheets\" ; then\n  DEFAULT_XSLROOT=\"/usr/share/sgml/docbook/xsl-stylesheets\"\nelse\n  dnl Documentation building will fail if this default gets used.\n  DEFAULT_XSLROOT=\"\"\nfi\nAC_ARG_WITH([xslroot],\n  [AS_HELP_STRING([--with-xslroot=<path>], [XSL stylesheet root path])], [\nif test \"x$with_xslroot\" = \"xno\" ; then\n  XSLROOT=\"${DEFAULT_XSLROOT}\"\nelse\n  XSLROOT=\"${with_xslroot}\"\nfi\n],\n  XSLROOT=\"${DEFAULT_XSLROOT}\"\n)\nAC_SUBST([XSLROOT])\n\ndnl If CFLAGS isn't defined, set CFLAGS to something reasonable.  Otherwise,\ndnl just prevent autoconf from molesting CFLAGS.\nCFLAGS=$CFLAGS\nAC_PROG_CC\nif test \"x$GCC\" != \"xyes\" ; then\n  AC_CACHE_CHECK([whether compiler is MSVC],\n                 [je_cv_msvc],\n                 [AC_COMPILE_IFELSE([AC_LANG_PROGRAM([],\n                                                     [\n#ifndef _MSC_VER\n  int fail[-1];\n#endif\n])],\n                               [je_cv_msvc=yes],\n                               [je_cv_msvc=no])])\nfi\n\nif test \"x$CFLAGS\" = \"x\" ; then\n  no_CFLAGS=\"yes\"\n  if test \"x$GCC\" = \"xyes\" ; then\n    JE_CFLAGS_APPEND([-std=gnu99])\n    if test \"x$je_cv_cflags_appended\" = \"x-std=gnu99\" ; then\n      AC_DEFINE_UNQUOTED([JEMALLOC_HAS_RESTRICT])\n    fi\n    JE_CFLAGS_APPEND([-Wall])\n    JE_CFLAGS_APPEND([-pipe])\n    JE_CFLAGS_APPEND([-g3])\n  elif test \"x$je_cv_msvc\" = \"xyes\" ; then\n    CC=\"$CC -nologo\"\n    JE_CFLAGS_APPEND([-Zi])\n    JE_CFLAGS_APPEND([-MT])\n    JE_CFLAGS_APPEND([-W3])\n    CPPFLAGS=\"$CPPFLAGS -I${srcroot}/include/msvc_compat\"\n  fi\nfi\ndnl Append EXTRA_CFLAGS to CFLAGS, if defined.\nif test \"x$EXTRA_CFLAGS\" != \"x\" ; then\n  JE_CFLAGS_APPEND([$EXTRA_CFLAGS])\nfi\nAC_PROG_CPP\n\nAC_C_BIGENDIAN([ac_cv_big_endian=1], [ac_cv_big_endian=0])\nif test \"x${ac_cv_big_endian}\" = \"x1\" ; then\n  AC_DEFINE_UNQUOTED([JEMALLOC_BIG_ENDIAN], [ ])\nfi\n\nAC_CHECK_SIZEOF([void *])\nif test \"x${ac_cv_sizeof_void_p}\" = \"x8\" ; then\n  LG_SIZEOF_PTR=3\nelif test \"x${ac_cv_sizeof_void_p}\" = \"x4\" ; then\n  LG_SIZEOF_PTR=2\nelse\n  AC_MSG_ERROR([Unsupported pointer size: ${ac_cv_sizeof_void_p}])\nfi\nAC_DEFINE_UNQUOTED([LG_SIZEOF_PTR], [$LG_SIZEOF_PTR])\n\nAC_CHECK_SIZEOF([int])\nif test \"x${ac_cv_sizeof_int}\" = \"x8\" ; then\n  LG_SIZEOF_INT=3\nelif test \"x${ac_cv_sizeof_int}\" = \"x4\" ; then\n  LG_SIZEOF_INT=2\nelse\n  AC_MSG_ERROR([Unsupported int size: ${ac_cv_sizeof_int}])\nfi\nAC_DEFINE_UNQUOTED([LG_SIZEOF_INT], [$LG_SIZEOF_INT])\n\nAC_CHECK_SIZEOF([long])\nif test \"x${ac_cv_sizeof_long}\" = \"x8\" ; then\n  LG_SIZEOF_LONG=3\nelif test \"x${ac_cv_sizeof_long}\" = \"x4\" ; then\n  LG_SIZEOF_LONG=2\nelse\n  AC_MSG_ERROR([Unsupported long size: ${ac_cv_sizeof_long}])\nfi\nAC_DEFINE_UNQUOTED([LG_SIZEOF_LONG], [$LG_SIZEOF_LONG])\n\nAC_CHECK_SIZEOF([intmax_t])\nif test \"x${ac_cv_sizeof_intmax_t}\" = \"x16\" ; then\n  LG_SIZEOF_INTMAX_T=4\nelif test \"x${ac_cv_sizeof_intmax_t}\" = \"x8\" ; then\n  LG_SIZEOF_INTMAX_T=3\nelif test \"x${ac_cv_sizeof_intmax_t}\" = \"x4\" ; then\n  LG_SIZEOF_INTMAX_T=2\nelse\n  AC_MSG_ERROR([Unsupported intmax_t size: ${ac_cv_sizeof_intmax_t}])\nfi\nAC_DEFINE_UNQUOTED([LG_SIZEOF_INTMAX_T], [$LG_SIZEOF_INTMAX_T])\n\nAC_CANONICAL_HOST\ndnl CPU-specific settings.\nCPU_SPINWAIT=\"\"\ncase \"${host_cpu}\" in\n  i[[345]]86)\n\t;;\n  i686|x86_64)\n\tJE_COMPILABLE([pause instruction], [],\n\t              [[__asm__ volatile(\"pause\"); return 0;]],\n\t              [je_cv_pause])\n\tif test \"x${je_cv_pause}\" = \"xyes\" ; then\n\t    CPU_SPINWAIT='__asm__ volatile(\"pause\")'\n\tfi\n\tdnl emmintrin.h fails to compile unless MMX, SSE, and SSE2 are\n\tdnl supported.\n\tJE_COMPILABLE([SSE2 intrinsics], [\n#include <emmintrin.h>\n], [], [je_cv_sse2])\n\tif test \"x${je_cv_sse2}\" = \"xyes\" ; then\n\t  AC_DEFINE_UNQUOTED([HAVE_SSE2], [ ])\n\tfi\n\t;;\n  powerpc)\n\tAC_DEFINE_UNQUOTED([HAVE_ALTIVEC], [ ])\n\t;;\n  *)\n\t;;\nesac\nAC_DEFINE_UNQUOTED([CPU_SPINWAIT], [$CPU_SPINWAIT])\n\nLD_PRELOAD_VAR=\"LD_PRELOAD\"\nso=\"so\"\nimportlib=\"${so}\"\no=\"$ac_objext\"\na=\"a\"\nexe=\"$ac_exeext\"\nlibprefix=\"lib\"\nDSO_LDFLAGS='-shared -Wl,-soname,$(@F)'\nRPATH='-Wl,-rpath,$(1)'\nSOREV=\"${so}.${rev}\"\nPIC_CFLAGS='-fPIC -DPIC'\nCTARGET='-o $@'\nLDTARGET='-o $@'\nEXTRA_LDFLAGS=\nARFLAGS='crus'\nAROUT=' $@'\nCC_MM=1\n\nAN_MAKEVAR([AR], [AC_PROG_AR])\nAN_PROGRAM([ar], [AC_PROG_AR])\nAC_DEFUN([AC_PROG_AR], [AC_CHECK_TOOL(AR, ar, :)])\nAC_PROG_AR\n\ndnl Platform-specific settings.  abi and RPATH can probably be determined\ndnl programmatically, but doing so is error-prone, which makes it generally\ndnl not worth the trouble.\ndnl \ndnl Define cpp macros in CPPFLAGS, rather than doing AC_DEFINE(macro), since the\ndnl definitions need to be seen before any headers are included, which is a pain\ndnl to make happen otherwise.\ndefault_munmap=\"1\"\nJEMALLOC_USABLE_SIZE_CONST=\"const\"\ncase \"${host}\" in\n  *-*-darwin*)\n\tCFLAGS=\"$CFLAGS\"\n\tabi=\"macho\"\n\tAC_DEFINE([JEMALLOC_PURGE_MADVISE_FREE], [ ])\n\tRPATH=\"\"\n\tLD_PRELOAD_VAR=\"DYLD_INSERT_LIBRARIES\"\n\tso=\"dylib\"\n\timportlib=\"${so}\"\n\tforce_tls=\"0\"\n\tDSO_LDFLAGS='-shared -Wl,-dylib_install_name,$(@F)'\n\tSOREV=\"${rev}.${so}\"\n\tsbrk_deprecated=\"1\"\n\t;;\n  *-*-freebsd*)\n\tCFLAGS=\"$CFLAGS\"\n\tabi=\"elf\"\n\tAC_DEFINE([JEMALLOC_PURGE_MADVISE_FREE], [ ])\n\tforce_lazy_lock=\"1\"\n\t;;\n  *-*-linux*)\n\tCFLAGS=\"$CFLAGS\"\n\tCPPFLAGS=\"$CPPFLAGS -D_GNU_SOURCE\"\n\tabi=\"elf\"\n\tAC_DEFINE([JEMALLOC_HAS_ALLOCA_H])\n\tAC_DEFINE([JEMALLOC_PURGE_MADVISE_DONTNEED], [ ])\n\tAC_DEFINE([JEMALLOC_THREADED_INIT], [ ])\n\tJEMALLOC_USABLE_SIZE_CONST=\"\"\n\tdefault_munmap=\"0\"\n\t;;\n  *-*-netbsd*)\n\tAC_MSG_CHECKING([ABI])\n        AC_COMPILE_IFELSE([AC_LANG_PROGRAM(\n[[#ifdef __ELF__\n/* ELF */\n#else\n#error aout\n#endif\n]])],\n                          [CFLAGS=\"$CFLAGS\"; abi=\"elf\"],\n                          [abi=\"aout\"])\n\tAC_MSG_RESULT([$abi])\n\tAC_DEFINE([JEMALLOC_PURGE_MADVISE_FREE], [ ])\n\t;;\n  *-*-solaris2*)\n\tCFLAGS=\"$CFLAGS\"\n\tabi=\"elf\"\n\tAC_DEFINE([JEMALLOC_PURGE_MADVISE_FREE], [ ])\n\tRPATH='-Wl,-R,$(1)'\n\tdnl Solaris needs this for sigwait().\n\tCPPFLAGS=\"$CPPFLAGS -D_POSIX_PTHREAD_SEMANTICS\"\n\tLIBS=\"$LIBS -lposix4 -lsocket -lnsl\"\n\t;;\n  *-ibm-aix*)\n\tif \"$LG_SIZEOF_PTR\" = \"8\"; then\n\t  dnl 64bit AIX\n\t  LD_PRELOAD_VAR=\"LDR_PRELOAD64\"\n\telse\n\t  dnl 32bit AIX\n\t  LD_PRELOAD_VAR=\"LDR_PRELOAD\"\n\tfi\n\tabi=\"xcoff\"\n\t;;\n  *-*-mingw*)\n\tabi=\"pecoff\"\n\tforce_tls=\"0\"\n\tRPATH=\"\"\n\tso=\"dll\"\n\tif test \"x$je_cv_msvc\" = \"xyes\" ; then\n\t  importlib=\"lib\"\n\t  DSO_LDFLAGS=\"-LD\"\n\t  EXTRA_LDFLAGS=\"-link -DEBUG\"\n\t  CTARGET='-Fo$@'\n\t  LDTARGET='-Fe$@'\n\t  AR='lib'\n\t  ARFLAGS='-nologo -out:'\n\t  AROUT='$@'\n\t  CC_MM=\n        else\n\t  importlib=\"${so}\"\n\t  DSO_LDFLAGS=\"-shared\"\n\tfi\n\ta=\"lib\"\n\tlibprefix=\"\"\n\tSOREV=\"${so}\"\n\tPIC_CFLAGS=\"\"\n\t;;\n  *)\n\tAC_MSG_RESULT([Unsupported operating system: ${host}])\n\tabi=\"elf\"\n\t;;\nesac\nAC_DEFINE_UNQUOTED([JEMALLOC_USABLE_SIZE_CONST], [$JEMALLOC_USABLE_SIZE_CONST])\nAC_SUBST([abi])\nAC_SUBST([RPATH])\nAC_SUBST([LD_PRELOAD_VAR])\nAC_SUBST([so])\nAC_SUBST([importlib])\nAC_SUBST([o])\nAC_SUBST([a])\nAC_SUBST([exe])\nAC_SUBST([libprefix])\nAC_SUBST([DSO_LDFLAGS])\nAC_SUBST([EXTRA_LDFLAGS])\nAC_SUBST([SOREV])\nAC_SUBST([PIC_CFLAGS])\nAC_SUBST([CTARGET])\nAC_SUBST([LDTARGET])\nAC_SUBST([MKLIB])\nAC_SUBST([ARFLAGS])\nAC_SUBST([AROUT])\nAC_SUBST([CC_MM])\n\nJE_COMPILABLE([__attribute__ syntax],\n              [static __attribute__((unused)) void foo(void){}],\n              [],\n              [je_cv_attribute])\nif test \"x${je_cv_attribute}\" = \"xyes\" ; then\n  AC_DEFINE([JEMALLOC_HAVE_ATTR], [ ])\n  if test \"x${GCC}\" = \"xyes\" -a \"x${abi}\" = \"xelf\"; then\n    JE_CFLAGS_APPEND([-fvisibility=hidden])\n  fi\nfi\ndnl Check for tls_model attribute support (clang 3.0 still lacks support).\nSAVED_CFLAGS=\"${CFLAGS}\"\nJE_CFLAGS_APPEND([-Werror])\nJE_COMPILABLE([tls_model attribute], [],\n              [static __thread int\n               __attribute__((tls_model(\"initial-exec\"))) foo;\n               foo = 0;],\n              [je_cv_tls_model])\nCFLAGS=\"${SAVED_CFLAGS}\"\nif test \"x${je_cv_tls_model}\" = \"xyes\" ; then\n  AC_DEFINE([JEMALLOC_TLS_MODEL],\n            [__attribute__((tls_model(\"initial-exec\")))])\nelse\n  AC_DEFINE([JEMALLOC_TLS_MODEL], [ ])\nfi\n\ndnl Support optional additions to rpath.\nAC_ARG_WITH([rpath],\n  [AS_HELP_STRING([--with-rpath=<rpath>], [Colon-separated rpath (ELF systems only)])],\nif test \"x$with_rpath\" = \"xno\" ; then\n  RPATH_EXTRA=\nelse\n  RPATH_EXTRA=\"`echo $with_rpath | tr \\\":\\\" \\\" \\\"`\"\nfi,\n  RPATH_EXTRA=\n)\nAC_SUBST([RPATH_EXTRA])\n\ndnl Disable rules that do automatic regeneration of configure output by default.\nAC_ARG_ENABLE([autogen],\n  [AS_HELP_STRING([--enable-autogen], [Automatically regenerate configure output])],\nif test \"x$enable_autogen\" = \"xno\" ; then\n  enable_autogen=\"0\"\nelse\n  enable_autogen=\"1\"\nfi\n,\nenable_autogen=\"0\"\n)\nAC_SUBST([enable_autogen])\n\nAC_PROG_INSTALL\nAC_PROG_RANLIB\nAC_PATH_PROG([LD], [ld], [false], [$PATH])\nAC_PATH_PROG([AUTOCONF], [autoconf], [false], [$PATH])\n\npublic_syms=\"malloc_conf malloc_message malloc calloc posix_memalign aligned_alloc realloc free mallocx rallocx xallocx sallocx dallocx nallocx mallctl mallctlnametomib mallctlbymib malloc_stats_print malloc_usable_size\"\n\ndnl Check for allocator-related functions that should be wrapped.\nAC_CHECK_FUNC([memalign],\n\t      [AC_DEFINE([JEMALLOC_OVERRIDE_MEMALIGN], [ ])\n\t       public_syms=\"${public_syms} memalign\"])\nAC_CHECK_FUNC([valloc],\n\t      [AC_DEFINE([JEMALLOC_OVERRIDE_VALLOC], [ ])\n\t       public_syms=\"${public_syms} valloc\"])\n\ndnl Support the experimental API by default.\nAC_ARG_ENABLE([experimental],\n  [AS_HELP_STRING([--disable-experimental],\n   [Disable support for the experimental API])],\n[if test \"x$enable_experimental\" = \"xno\" ; then\n  enable_experimental=\"0\"\nelse\n  enable_experimental=\"1\"\nfi\n],\n[enable_experimental=\"1\"]\n)\nif test \"x$enable_experimental\" = \"x1\" ; then\n  AC_DEFINE([JEMALLOC_EXPERIMENTAL], [ ])\n  public_syms=\"${public_syms} allocm dallocm nallocm rallocm sallocm\"\nfi\nAC_SUBST([enable_experimental])\n\ndnl Do not compute test code coverage by default.\nGCOV_FLAGS=\nAC_ARG_ENABLE([code-coverage],\n  [AS_HELP_STRING([--enable-code-coverage],\n   [Enable code coverage])],\n[if test \"x$enable_code_coverage\" = \"xno\" ; then\n  enable_code_coverage=\"0\"\nelse\n  enable_code_coverage=\"1\"\nfi\n],\n[enable_code_coverage=\"0\"]\n)\nif test \"x$enable_code_coverage\" = \"x1\" ; then\n  deoptimize=\"no\"\n  echo \"$CFLAGS $EXTRA_CFLAGS\" | grep '\\-O' >/dev/null || deoptimize=\"yes\"\n  if test \"x${deoptimize}\" = \"xyes\" ; then\n    JE_CFLAGS_APPEND([-O0])\n  fi\n  JE_CFLAGS_APPEND([-fprofile-arcs -ftest-coverage])\n  EXTRA_LDFLAGS=\"$EXTRA_LDFLAGS -fprofile-arcs -ftest-coverage\"\n  AC_DEFINE([JEMALLOC_CODE_COVERAGE], [ ])\nfi\nAC_SUBST([enable_code_coverage])\n\ndnl Perform no name mangling by default.\nAC_ARG_WITH([mangling],\n  [AS_HELP_STRING([--with-mangling=<map>], [Mangle symbols in <map>])],\n  [mangling_map=\"$with_mangling\"], [mangling_map=\"\"])\n\ndnl Do not prefix public APIs by default.\nAC_ARG_WITH([jemalloc_prefix],\n  [AS_HELP_STRING([--with-jemalloc-prefix=<prefix>], [Prefix to prepend to all public APIs])],\n  [JEMALLOC_PREFIX=\"$with_jemalloc_prefix\"],\n  [if test \"x$abi\" != \"xmacho\" -a \"x$abi\" != \"xpecoff\"; then\n  JEMALLOC_PREFIX=\"\"\nelse\n  JEMALLOC_PREFIX=\"je_\"\nfi]\n)\nif test \"x$JEMALLOC_PREFIX\" != \"x\" ; then\n  JEMALLOC_CPREFIX=`echo ${JEMALLOC_PREFIX} | tr \"a-z\" \"A-Z\"`\n  AC_DEFINE_UNQUOTED([JEMALLOC_PREFIX], [\"$JEMALLOC_PREFIX\"])\n  AC_DEFINE_UNQUOTED([JEMALLOC_CPREFIX], [\"$JEMALLOC_CPREFIX\"])\nfi\n\nAC_ARG_WITH([export],\n  [AS_HELP_STRING([--without-export], [disable exporting jemalloc public APIs])],\n  [if test \"x$with_export\" = \"xno\"; then\n  AC_DEFINE([JEMALLOC_EXPORT],[])\nfi]\n)\n\ndnl Mangle library-private APIs.\nAC_ARG_WITH([private_namespace],\n  [AS_HELP_STRING([--with-private-namespace=<prefix>], [Prefix to prepend to all library-private APIs])],\n  [JEMALLOC_PRIVATE_NAMESPACE=\"${with_private_namespace}je_\"],\n  [JEMALLOC_PRIVATE_NAMESPACE=\"je_\"]\n)\nAC_DEFINE_UNQUOTED([JEMALLOC_PRIVATE_NAMESPACE], [$JEMALLOC_PRIVATE_NAMESPACE])\nprivate_namespace=\"$JEMALLOC_PRIVATE_NAMESPACE\"\nAC_SUBST([private_namespace])\n\ndnl Do not add suffix to installed files by default.\nAC_ARG_WITH([install_suffix],\n  [AS_HELP_STRING([--with-install-suffix=<suffix>], [Suffix to append to all installed files])],\n  [INSTALL_SUFFIX=\"$with_install_suffix\"],\n  [INSTALL_SUFFIX=]\n)\ninstall_suffix=\"$INSTALL_SUFFIX\"\nAC_SUBST([install_suffix])\n\ndnl Substitute @je_@ in jemalloc_protos.h.in, primarily to make generation of\ndnl jemalloc_protos_jet.h easy.\nje_=\"je_\"\nAC_SUBST([je_])\n\ncfgoutputs_in=\"${srcroot}Makefile.in\"\ncfgoutputs_in=\"${cfgoutputs_in} ${srcroot}doc/html.xsl.in\"\ncfgoutputs_in=\"${cfgoutputs_in} ${srcroot}doc/manpages.xsl.in\"\ncfgoutputs_in=\"${cfgoutputs_in} ${srcroot}doc/jemalloc.xml.in\"\ncfgoutputs_in=\"${cfgoutputs_in} ${srcroot}include/jemalloc/jemalloc_macros.h.in\"\ncfgoutputs_in=\"${cfgoutputs_in} ${srcroot}include/jemalloc/jemalloc_protos.h.in\"\ncfgoutputs_in=\"${cfgoutputs_in} ${srcroot}include/jemalloc/internal/jemalloc_internal.h.in\"\ncfgoutputs_in=\"${cfgoutputs_in} ${srcroot}test/test.sh.in\"\ncfgoutputs_in=\"${cfgoutputs_in} ${srcroot}test/include/test/jemalloc_test.h.in\"\n\ncfgoutputs_out=\"Makefile\"\ncfgoutputs_out=\"${cfgoutputs_out} doc/html.xsl\"\ncfgoutputs_out=\"${cfgoutputs_out} doc/manpages.xsl\"\ncfgoutputs_out=\"${cfgoutputs_out} doc/jemalloc.xml\"\ncfgoutputs_out=\"${cfgoutputs_out} include/jemalloc/jemalloc_macros.h\"\ncfgoutputs_out=\"${cfgoutputs_out} include/jemalloc/jemalloc_protos.h\"\ncfgoutputs_out=\"${cfgoutputs_out} include/jemalloc/internal/jemalloc_internal.h\"\ncfgoutputs_out=\"${cfgoutputs_out} test/test.sh\"\ncfgoutputs_out=\"${cfgoutputs_out} test/include/test/jemalloc_test.h\"\n\ncfgoutputs_tup=\"Makefile\"\ncfgoutputs_tup=\"${cfgoutputs_tup} doc/html.xsl:doc/html.xsl.in\"\ncfgoutputs_tup=\"${cfgoutputs_tup} doc/manpages.xsl:doc/manpages.xsl.in\"\ncfgoutputs_tup=\"${cfgoutputs_tup} doc/jemalloc.xml:doc/jemalloc.xml.in\"\ncfgoutputs_tup=\"${cfgoutputs_tup} include/jemalloc/jemalloc_macros.h:include/jemalloc/jemalloc_macros.h.in\"\ncfgoutputs_tup=\"${cfgoutputs_tup} include/jemalloc/jemalloc_protos.h:include/jemalloc/jemalloc_protos.h.in\"\ncfgoutputs_tup=\"${cfgoutputs_tup} include/jemalloc/internal/jemalloc_internal.h\"\ncfgoutputs_tup=\"${cfgoutputs_tup} test/test.sh:test/test.sh.in\"\ncfgoutputs_tup=\"${cfgoutputs_tup} test/include/test/jemalloc_test.h:test/include/test/jemalloc_test.h.in\"\n\ncfghdrs_in=\"${srcroot}include/jemalloc/jemalloc_defs.h.in\"\ncfghdrs_in=\"${cfghdrs_in} ${srcroot}include/jemalloc/internal/jemalloc_internal_defs.h.in\"\ncfghdrs_in=\"${cfghdrs_in} ${srcroot}include/jemalloc/internal/private_namespace.sh\"\ncfghdrs_in=\"${cfghdrs_in} ${srcroot}include/jemalloc/internal/private_unnamespace.sh\"\ncfghdrs_in=\"${cfghdrs_in} ${srcroot}include/jemalloc/internal/private_symbols.txt\"\ncfghdrs_in=\"${cfghdrs_in} ${srcroot}include/jemalloc/internal/public_namespace.sh\"\ncfghdrs_in=\"${cfghdrs_in} ${srcroot}include/jemalloc/internal/public_unnamespace.sh\"\ncfghdrs_in=\"${cfghdrs_in} ${srcroot}include/jemalloc/internal/size_classes.sh\"\ncfghdrs_in=\"${cfghdrs_in} ${srcroot}include/jemalloc/jemalloc_rename.sh\"\ncfghdrs_in=\"${cfghdrs_in} ${srcroot}include/jemalloc/jemalloc_mangle.sh\"\ncfghdrs_in=\"${cfghdrs_in} ${srcroot}include/jemalloc/jemalloc.sh\"\ncfghdrs_in=\"${cfghdrs_in} ${srcroot}test/include/test/jemalloc_test_defs.h.in\"\n\ncfghdrs_out=\"include/jemalloc/jemalloc_defs.h\"\ncfghdrs_out=\"${cfghdrs_out} include/jemalloc/jemalloc${install_suffix}.h\"\ncfghdrs_out=\"${cfghdrs_out} include/jemalloc/internal/private_namespace.h\"\ncfghdrs_out=\"${cfghdrs_out} include/jemalloc/internal/private_unnamespace.h\"\ncfghdrs_out=\"${cfghdrs_out} include/jemalloc/internal/public_symbols.txt\"\ncfghdrs_out=\"${cfghdrs_out} include/jemalloc/internal/public_namespace.h\"\ncfghdrs_out=\"${cfghdrs_out} include/jemalloc/internal/public_unnamespace.h\"\ncfghdrs_out=\"${cfghdrs_out} include/jemalloc/internal/size_classes.h\"\ncfghdrs_out=\"${cfghdrs_out} include/jemalloc/jemalloc_protos_jet.h\"\ncfghdrs_out=\"${cfghdrs_out} include/jemalloc/jemalloc_rename.h\"\ncfghdrs_out=\"${cfghdrs_out} include/jemalloc/jemalloc_mangle.h\"\ncfghdrs_out=\"${cfghdrs_out} include/jemalloc/jemalloc_mangle_jet.h\"\ncfghdrs_out=\"${cfghdrs_out} include/jemalloc/internal/jemalloc_internal_defs.h\"\ncfghdrs_out=\"${cfghdrs_out} test/include/test/jemalloc_test_defs.h\"\n\ncfghdrs_tup=\"include/jemalloc/jemalloc_defs.h:include/jemalloc/jemalloc_defs.h.in\"\ncfghdrs_tup=\"${cfghdrs_tup} include/jemalloc/internal/jemalloc_internal_defs.h:${srcroot}include/jemalloc/internal/jemalloc_internal_defs.h.in\"\ncfghdrs_tup=\"${cfghdrs_tup} test/include/test/jemalloc_test_defs.h:${srcroot}test/include/test/jemalloc_test_defs.h.in\"\n\ndnl Do not silence irrelevant compiler warnings by default, since enabling this\ndnl option incurs a performance penalty.\nAC_ARG_ENABLE([cc-silence],\n  [AS_HELP_STRING([--enable-cc-silence],\n                  [Silence irrelevant compiler warnings])],\n[if test \"x$enable_cc_silence\" = \"xno\" ; then\n  enable_cc_silence=\"0\"\nelse\n  enable_cc_silence=\"1\"\nfi\n],\n[enable_cc_silence=\"0\"]\n)\nif test \"x$enable_cc_silence\" = \"x1\" ; then\n  AC_DEFINE([JEMALLOC_CC_SILENCE], [ ])\nfi\n\ndnl Do not compile with debugging by default.\nAC_ARG_ENABLE([debug],\n  [AS_HELP_STRING([--enable-debug], [Build debugging code (implies --enable-ivsalloc)])],\n[if test \"x$enable_debug\" = \"xno\" ; then\n  enable_debug=\"0\"\nelse\n  enable_debug=\"1\"\nfi\n],\n[enable_debug=\"0\"]\n)\nif test \"x$enable_debug\" = \"x1\" ; then\n  AC_DEFINE([JEMALLOC_DEBUG], [ ])\n  enable_ivsalloc=\"1\"\nfi\nAC_SUBST([enable_debug])\n\ndnl Do not validate pointers by default.\nAC_ARG_ENABLE([ivsalloc],\n  [AS_HELP_STRING([--enable-ivsalloc], [Validate pointers passed through the public API])],\n[if test \"x$enable_ivsalloc\" = \"xno\" ; then\n  enable_ivsalloc=\"0\"\nelse\n  enable_ivsalloc=\"1\"\nfi\n],\n[enable_ivsalloc=\"0\"]\n)\nif test \"x$enable_ivsalloc\" = \"x1\" ; then\n  AC_DEFINE([JEMALLOC_IVSALLOC], [ ])\nfi\n\ndnl Only optimize if not debugging.\nif test \"x$enable_debug\" = \"x0\" -a \"x$no_CFLAGS\" = \"xyes\" ; then\n  dnl Make sure that an optimization flag was not specified in EXTRA_CFLAGS.\n  optimize=\"no\"\n  echo \"$CFLAGS $EXTRA_CFLAGS\" | grep '\\-O' >/dev/null || optimize=\"yes\"\n  if test \"x${optimize}\" = \"xyes\" ; then\n    if test \"x$GCC\" = \"xyes\" ; then\n      JE_CFLAGS_APPEND([-O3])\n      JE_CFLAGS_APPEND([-funroll-loops])\n    elif test \"x$je_cv_msvc\" = \"xyes\" ; then\n      JE_CFLAGS_APPEND([-O2])\n    else\n      JE_CFLAGS_APPEND([-O])\n    fi\n  fi\nfi\n\ndnl Enable statistics calculation by default.\nAC_ARG_ENABLE([stats],\n  [AS_HELP_STRING([--disable-stats],\n                  [Disable statistics calculation/reporting])],\n[if test \"x$enable_stats\" = \"xno\" ; then\n  enable_stats=\"0\"\nelse\n  enable_stats=\"1\"\nfi\n],\n[enable_stats=\"1\"]\n)\nif test \"x$enable_stats\" = \"x1\" ; then\n  AC_DEFINE([JEMALLOC_STATS], [ ])\nfi\nAC_SUBST([enable_stats])\n\ndnl Do not enable profiling by default.\nAC_ARG_ENABLE([prof],\n  [AS_HELP_STRING([--enable-prof], [Enable allocation profiling])],\n[if test \"x$enable_prof\" = \"xno\" ; then\n  enable_prof=\"0\"\nelse\n  enable_prof=\"1\"\nfi\n],\n[enable_prof=\"0\"]\n)\nif test \"x$enable_prof\" = \"x1\" ; then\n  backtrace_method=\"\"\nelse\n  backtrace_method=\"N/A\"\nfi\n\nAC_ARG_ENABLE([prof-libunwind],\n  [AS_HELP_STRING([--enable-prof-libunwind], [Use libunwind for backtracing])],\n[if test \"x$enable_prof_libunwind\" = \"xno\" ; then\n  enable_prof_libunwind=\"0\"\nelse\n  enable_prof_libunwind=\"1\"\nfi\n],\n[enable_prof_libunwind=\"0\"]\n)\nAC_ARG_WITH([static_libunwind],\n  [AS_HELP_STRING([--with-static-libunwind=<libunwind.a>],\n  [Path to static libunwind library; use rather than dynamically linking])],\nif test \"x$with_static_libunwind\" = \"xno\" ; then\n  LUNWIND=\"-lunwind\"\nelse\n  if test ! -f \"$with_static_libunwind\" ; then\n    AC_MSG_ERROR([Static libunwind not found: $with_static_libunwind])\n  fi\n  LUNWIND=\"$with_static_libunwind\"\nfi,\n  LUNWIND=\"-lunwind\"\n)\nif test \"x$backtrace_method\" = \"x\" -a \"x$enable_prof_libunwind\" = \"x1\" ; then\n  AC_CHECK_HEADERS([libunwind.h], , [enable_prof_libunwind=\"0\"])\n  if test \"x$LUNWIND\" = \"x-lunwind\" ; then\n    AC_CHECK_LIB([unwind], [backtrace], [LIBS=\"$LIBS $LUNWIND\"],\n                 [enable_prof_libunwind=\"0\"])\n  else\n    LIBS=\"$LIBS $LUNWIND\"\n  fi\n  if test \"x${enable_prof_libunwind}\" = \"x1\" ; then\n    backtrace_method=\"libunwind\"\n    AC_DEFINE([JEMALLOC_PROF_LIBUNWIND], [ ])\n  fi\nfi\n\nAC_ARG_ENABLE([prof-libgcc],\n  [AS_HELP_STRING([--disable-prof-libgcc],\n  [Do not use libgcc for backtracing])],\n[if test \"x$enable_prof_libgcc\" = \"xno\" ; then\n  enable_prof_libgcc=\"0\"\nelse\n  enable_prof_libgcc=\"1\"\nfi\n],\n[enable_prof_libgcc=\"1\"]\n)\nif test \"x$backtrace_method\" = \"x\" -a \"x$enable_prof_libgcc\" = \"x1\" \\\n     -a \"x$GCC\" = \"xyes\" ; then\n  AC_CHECK_HEADERS([unwind.h], , [enable_prof_libgcc=\"0\"])\n  AC_CHECK_LIB([gcc], [_Unwind_Backtrace], [LIBS=\"$LIBS -lgcc\"], [enable_prof_libgcc=\"0\"])\n  if test \"x${enable_prof_libgcc}\" = \"x1\" ; then\n    backtrace_method=\"libgcc\"\n    AC_DEFINE([JEMALLOC_PROF_LIBGCC], [ ])\n  fi\nelse\n  enable_prof_libgcc=\"0\"\nfi\n\nAC_ARG_ENABLE([prof-gcc],\n  [AS_HELP_STRING([--disable-prof-gcc],\n  [Do not use gcc intrinsics for backtracing])],\n[if test \"x$enable_prof_gcc\" = \"xno\" ; then\n  enable_prof_gcc=\"0\"\nelse\n  enable_prof_gcc=\"1\"\nfi\n],\n[enable_prof_gcc=\"1\"]\n)\nif test \"x$backtrace_method\" = \"x\" -a \"x$enable_prof_gcc\" = \"x1\" \\\n     -a \"x$GCC\" = \"xyes\" ; then\n  JE_CFLAGS_APPEND([-fno-omit-frame-pointer])\n  backtrace_method=\"gcc intrinsics\"\n  AC_DEFINE([JEMALLOC_PROF_GCC], [ ])\nelse\n  enable_prof_gcc=\"0\"\nfi\n\nif test \"x$backtrace_method\" = \"x\" ; then\n  backtrace_method=\"none (disabling profiling)\"\n  enable_prof=\"0\"\nfi\nAC_MSG_CHECKING([configured backtracing method])\nAC_MSG_RESULT([$backtrace_method])\nif test \"x$enable_prof\" = \"x1\" ; then\n  if test \"x${force_tls}\" = \"x0\" ; then\n    AC_MSG_ERROR([Heap profiling requires TLS]);\n  fi\n  force_tls=\"1\"\n\n  if test \"x$abi\" != \"xpecoff\"; then\n    dnl Heap profiling uses the log(3) function.\n    LIBS=\"$LIBS -lm\"\n  fi\n\n  AC_DEFINE([JEMALLOC_PROF], [ ])\nfi\nAC_SUBST([enable_prof])\n\ndnl Enable thread-specific caching by default.\nAC_ARG_ENABLE([tcache],\n  [AS_HELP_STRING([--disable-tcache], [Disable per thread caches])],\n[if test \"x$enable_tcache\" = \"xno\" ; then\n  enable_tcache=\"0\"\nelse\n  enable_tcache=\"1\"\nfi\n],\n[enable_tcache=\"1\"]\n)\nif test \"x$enable_tcache\" = \"x1\" ; then\n  AC_DEFINE([JEMALLOC_TCACHE], [ ])\nfi\nAC_SUBST([enable_tcache])\n\ndnl Disable mremap() for huge realloc() by default.\nAC_ARG_ENABLE([mremap],\n  [AS_HELP_STRING([--enable-mremap], [Enable mremap(2) for huge realloc()])],\n[if test \"x$enable_mremap\" = \"xno\" ; then\n  enable_mremap=\"0\"\nelse\n  enable_mremap=\"1\"\nfi\n],\n[enable_mremap=\"0\"]\n)\nif test \"x$enable_mremap\" = \"x1\" ; then\n  JE_COMPILABLE([mremap(...MREMAP_FIXED...)], [\n#define\t_GNU_SOURCE\n#include <sys/mman.h>\n], [\nvoid *p = mremap((void *)0, 0, 0, MREMAP_MAYMOVE|MREMAP_FIXED, (void *)0);\n], [je_cv_mremap_fixed])\n  if test \"x${je_cv_mremap_fixed}\" = \"xno\" ; then\n    enable_mremap=\"0\"\n  fi\nfi\nif test \"x$enable_mremap\" = \"x1\" ; then\n  AC_DEFINE([JEMALLOC_MREMAP], [ ])\nfi\nAC_SUBST([enable_mremap])\n\ndnl Enable VM deallocation via munmap() by default.\nAC_ARG_ENABLE([munmap],\n  [AS_HELP_STRING([--disable-munmap], [Disable VM deallocation via munmap(2)])],\n[if test \"x$enable_munmap\" = \"xno\" ; then\n  enable_munmap=\"0\"\nelse\n  enable_munmap=\"1\"\nfi\n],\n[enable_munmap=\"${default_munmap}\"]\n)\nif test \"x$enable_munmap\" = \"x1\" ; then\n  AC_DEFINE([JEMALLOC_MUNMAP], [ ])\nfi\nAC_SUBST([enable_munmap])\n\ndnl Do not enable allocation from DSS by default.\nAC_ARG_ENABLE([dss],\n  [AS_HELP_STRING([--enable-dss], [Enable allocation from DSS])],\n[if test \"x$enable_dss\" = \"xno\" ; then\n  enable_dss=\"0\"\nelse\n  enable_dss=\"1\"\nfi\n],\n[enable_dss=\"0\"]\n)\ndnl Check whether the BSD/SUSv1 sbrk() exists.  If not, disable DSS support.\nAC_CHECK_FUNC([sbrk], [have_sbrk=\"1\"], [have_sbrk=\"0\"])\nif test \"x$have_sbrk\" = \"x1\" ; then\n  if test \"x$sbrk_deprecated\" == \"x1\" ; then\n    AC_MSG_RESULT([Disabling dss allocation because sbrk is deprecated])\n    enable_dss=\"0\"\n  else\n    AC_DEFINE([JEMALLOC_HAVE_SBRK], [ ])\n  fi\nelse\n  enable_dss=\"0\"\nfi\n\nif test \"x$enable_dss\" = \"x1\" ; then\n  AC_DEFINE([JEMALLOC_DSS], [ ])\nfi\nAC_SUBST([enable_dss])\n\ndnl Support the junk/zero filling option by default.\nAC_ARG_ENABLE([fill],\n  [AS_HELP_STRING([--disable-fill],\n                  [Disable support for junk/zero filling, quarantine, and redzones])],\n[if test \"x$enable_fill\" = \"xno\" ; then\n  enable_fill=\"0\"\nelse\n  enable_fill=\"1\"\nfi\n],\n[enable_fill=\"1\"]\n)\nif test \"x$enable_fill\" = \"x1\" ; then\n  AC_DEFINE([JEMALLOC_FILL], [ ])\nfi\nAC_SUBST([enable_fill])\n\ndnl Disable utrace(2)-based tracing by default.\nAC_ARG_ENABLE([utrace],\n  [AS_HELP_STRING([--enable-utrace], [Enable utrace(2)-based tracing])],\n[if test \"x$enable_utrace\" = \"xno\" ; then\n  enable_utrace=\"0\"\nelse\n  enable_utrace=\"1\"\nfi\n],\n[enable_utrace=\"0\"]\n)\nJE_COMPILABLE([utrace(2)], [\n#include <sys/types.h>\n#include <sys/param.h>\n#include <sys/time.h>\n#include <sys/uio.h>\n#include <sys/ktrace.h>\n], [\n\tutrace((void *)0, 0);\n], [je_cv_utrace])\nif test \"x${je_cv_utrace}\" = \"xno\" ; then\n  enable_utrace=\"0\"\nfi\nif test \"x$enable_utrace\" = \"x1\" ; then\n  AC_DEFINE([JEMALLOC_UTRACE], [ ])\nfi\nAC_SUBST([enable_utrace])\n\ndnl Support Valgrind by default.\nAC_ARG_ENABLE([valgrind],\n  [AS_HELP_STRING([--disable-valgrind], [Disable support for Valgrind])],\n[if test \"x$enable_valgrind\" = \"xno\" ; then\n  enable_valgrind=\"0\"\nelse\n  enable_valgrind=\"1\"\nfi\n],\n[enable_valgrind=\"1\"]\n)\nif test \"x$enable_valgrind\" = \"x1\" ; then\n  JE_COMPILABLE([valgrind], [\n#include <valgrind/valgrind.h>\n#include <valgrind/memcheck.h>\n\n#if !defined(VALGRIND_RESIZEINPLACE_BLOCK)\n#  error \"Incompatible Valgrind version\"\n#endif\n], [], [je_cv_valgrind])\n  if test \"x${je_cv_valgrind}\" = \"xno\" ; then\n    enable_valgrind=\"0\"\n  fi\n  if test \"x$enable_valgrind\" = \"x1\" ; then\n    AC_DEFINE([JEMALLOC_VALGRIND], [ ])\n  fi\nfi\nAC_SUBST([enable_valgrind])\n\ndnl Do not support the xmalloc option by default.\nAC_ARG_ENABLE([xmalloc],\n  [AS_HELP_STRING([--enable-xmalloc], [Support xmalloc option])],\n[if test \"x$enable_xmalloc\" = \"xno\" ; then\n  enable_xmalloc=\"0\"\nelse\n  enable_xmalloc=\"1\"\nfi\n],\n[enable_xmalloc=\"0\"]\n)\nif test \"x$enable_xmalloc\" = \"x1\" ; then\n  AC_DEFINE([JEMALLOC_XMALLOC], [ ])\nfi\nAC_SUBST([enable_xmalloc])\n\nAC_CACHE_CHECK([STATIC_PAGE_SHIFT],\n               [je_cv_static_page_shift],\n               AC_RUN_IFELSE([AC_LANG_PROGRAM(\n[[\n#include <strings.h>\n#ifdef _WIN32\n#include <windows.h>\n#else\n#include <unistd.h>\n#endif\n#include <stdio.h>\n]],\n[[\n    int result;\n    FILE *f;\n\n#ifdef _WIN32\n    SYSTEM_INFO si;\n    GetSystemInfo(&si);\n    result = si.dwPageSize;\n#else\n    result = sysconf(_SC_PAGESIZE);\n#endif\n    if (result == -1) {\n\treturn 1;\n    }\n    result = ffsl(result) - 1;\n\n    f = fopen(\"conftest.out\", \"w\");\n    if (f == NULL) {\n\treturn 1;\n    }\n    fprintf(f, \"%d\\n\", result);\n    fclose(f);\n\n    return 0;\n]])],\n                             [je_cv_static_page_shift=`cat conftest.out`],\n                             [je_cv_static_page_shift=undefined]))\n\nif test \"x$je_cv_static_page_shift\" != \"xundefined\"; then\n   AC_DEFINE_UNQUOTED([STATIC_PAGE_SHIFT], [$je_cv_static_page_shift])\nelse\n   AC_MSG_ERROR([cannot determine value for STATIC_PAGE_SHIFT])\nfi\n\ndnl ============================================================================\ndnl jemalloc configuration.\ndnl \n\ndnl Set VERSION if source directory has an embedded git repository.\nif test -d \"${srcroot}.git\" ; then\n  git describe --long --abbrev=40 > ${srcroot}VERSION\nfi\njemalloc_version=`cat ${srcroot}VERSION`\njemalloc_version_major=`echo ${jemalloc_version} | tr \".g-\" \" \" | awk '{print [$]1}'`\njemalloc_version_minor=`echo ${jemalloc_version} | tr \".g-\" \" \" | awk '{print [$]2}'`\njemalloc_version_bugfix=`echo ${jemalloc_version} | tr \".g-\" \" \" | awk '{print [$]3}'`\njemalloc_version_nrev=`echo ${jemalloc_version} | tr \".g-\" \" \" | awk '{print [$]4}'`\njemalloc_version_gid=`echo ${jemalloc_version} | tr \".g-\" \" \" | awk '{print [$]5}'`\nAC_SUBST([jemalloc_version])\nAC_SUBST([jemalloc_version_major])\nAC_SUBST([jemalloc_version_minor])\nAC_SUBST([jemalloc_version_bugfix])\nAC_SUBST([jemalloc_version_nrev])\nAC_SUBST([jemalloc_version_gid])\n\ndnl ============================================================================\ndnl Configure pthreads.\n\nif test \"x$abi\" != \"xpecoff\" ; then\n  AC_CHECK_HEADERS([pthread.h], , [AC_MSG_ERROR([pthread.h is missing])])\n  dnl Some systems may embed pthreads functionality in libc; check for libpthread\n  dnl first, but try libc too before failing.\n  AC_CHECK_LIB([pthread], [pthread_create], [LIBS=\"$LIBS -lpthread\"],\n               [AC_SEARCH_LIBS([pthread_create], , ,\n                               AC_MSG_ERROR([libpthread is missing]))])\nfi\n\nCPPFLAGS=\"$CPPFLAGS -D_REENTRANT\"\n\ndnl Check whether the BSD-specific _malloc_thread_cleanup() exists.  If so, use\ndnl it rather than pthreads TSD cleanup functions to support cleanup during\ndnl thread exit, in order to avoid pthreads library recursion during\ndnl bootstrapping.\nAC_CHECK_FUNC([_malloc_thread_cleanup],\n              [have__malloc_thread_cleanup=\"1\"],\n              [have__malloc_thread_cleanup=\"0\"]\n             )\nif test \"x$have__malloc_thread_cleanup\" = \"x1\" ; then\n  AC_DEFINE([JEMALLOC_MALLOC_THREAD_CLEANUP], [ ])\n  force_tls=\"1\"\nfi\n\ndnl Check whether the BSD-specific _pthread_mutex_init_calloc_cb() exists.  If\ndnl so, mutex initialization causes allocation, and we need to implement this\ndnl callback function in order to prevent recursive allocation.\nAC_CHECK_FUNC([_pthread_mutex_init_calloc_cb],\n              [have__pthread_mutex_init_calloc_cb=\"1\"],\n              [have__pthread_mutex_init_calloc_cb=\"0\"]\n             )\nif test \"x$have__pthread_mutex_init_calloc_cb\" = \"x1\" ; then\n  AC_DEFINE([JEMALLOC_MUTEX_INIT_CB])\nfi\n\ndnl Disable lazy locking by default.\nAC_ARG_ENABLE([lazy_lock],\n  [AS_HELP_STRING([--enable-lazy-lock],\n  [Enable lazy locking (only lock when multi-threaded)])],\n[if test \"x$enable_lazy_lock\" = \"xno\" ; then\n  enable_lazy_lock=\"0\"\nelse\n  enable_lazy_lock=\"1\"\nfi\n],\n[enable_lazy_lock=\"0\"]\n)\nif test \"x$enable_lazy_lock\" = \"x0\" -a \"x${force_lazy_lock}\" = \"x1\" ; then\n  AC_MSG_RESULT([Forcing lazy-lock to avoid allocator/threading bootstrap issues])\n  enable_lazy_lock=\"1\"\nfi\nif test \"x$enable_lazy_lock\" = \"x1\" ; then\n  if test \"x$abi\" != \"xpecoff\" ; then\n    AC_CHECK_HEADERS([dlfcn.h], , [AC_MSG_ERROR([dlfcn.h is missing])])\n    AC_CHECK_FUNC([dlsym], [],\n      [AC_CHECK_LIB([dl], [dlsym], [LIBS=\"$LIBS -ldl\"],\n                    [AC_MSG_ERROR([libdl is missing])])\n      ])\n  fi\n  AC_DEFINE([JEMALLOC_LAZY_LOCK], [ ])\nfi\nAC_SUBST([enable_lazy_lock])\n\nAC_ARG_ENABLE([tls],\n  [AS_HELP_STRING([--disable-tls], [Disable thread-local storage (__thread keyword)])],\nif test \"x$enable_tls\" = \"xno\" ; then\n  enable_tls=\"0\"\nelse\n  enable_tls=\"1\"\nfi\n,\nenable_tls=\"1\"\n)\nif test \"x${enable_tls}\" = \"x0\" -a \"x${force_tls}\" = \"x1\" ; then\n  AC_MSG_RESULT([Forcing TLS to avoid allocator/threading bootstrap issues])\n  enable_tls=\"1\"\nfi\nif test \"x${enable_tls}\" = \"x1\" -a \"x${force_tls}\" = \"x0\" ; then\n  AC_MSG_RESULT([Forcing no TLS to avoid allocator/threading bootstrap issues])\n  enable_tls=\"0\"\nfi\nif test \"x${enable_tls}\" = \"x1\" ; then\nAC_MSG_CHECKING([for TLS])\nAC_COMPILE_IFELSE([AC_LANG_PROGRAM(\n[[\n    __thread int x;\n]], [[\n    x = 42;\n\n    return 0;\n]])],\n              AC_MSG_RESULT([yes]),\n              AC_MSG_RESULT([no])\n              enable_tls=\"0\")\nfi\nAC_SUBST([enable_tls])\nif test \"x${enable_tls}\" = \"x1\" ; then\n  AC_DEFINE_UNQUOTED([JEMALLOC_TLS], [ ])\nelif test \"x${force_tls}\" = \"x1\" ; then\n  AC_MSG_ERROR([Failed to configure TLS, which is mandatory for correct function])\nfi\n\ndnl ============================================================================\ndnl Check for ffsl(3), and fail if not found.  This function exists on all\ndnl platforms that jemalloc currently has a chance of functioning on without\ndnl modification.\nJE_COMPILABLE([a program using ffsl], [\n#include <stdio.h>\n#include <strings.h>\n#include <string.h>\n], [\n\t{\n\t\tint rv = ffsl(0x08);\n\t\tprintf(\"%d\\n\", rv);\n\t}\n], [je_cv_function_ffsl])\nif test \"x${je_cv_function_ffsl}\" != \"xyes\" ; then\n   AC_MSG_ERROR([Cannot build without ffsl(3)])\nfi\n\ndnl ============================================================================\ndnl Check for atomic(9) operations as provided on FreeBSD.\n\nJE_COMPILABLE([atomic(9)], [\n#include <sys/types.h>\n#include <machine/atomic.h>\n#include <inttypes.h>\n], [\n\t{\n\t\tuint32_t x32 = 0;\n\t\tvolatile uint32_t *x32p = &x32;\n\t\tatomic_fetchadd_32(x32p, 1);\n\t}\n\t{\n\t\tunsigned long xlong = 0;\n\t\tvolatile unsigned long *xlongp = &xlong;\n\t\tatomic_fetchadd_long(xlongp, 1);\n\t}\n], [je_cv_atomic9])\nif test \"x${je_cv_atomic9}\" = \"xyes\" ; then\n  AC_DEFINE([JEMALLOC_ATOMIC9])\nfi\n\ndnl ============================================================================\ndnl Check for atomic(3) operations as provided on Darwin.\n\nJE_COMPILABLE([Darwin OSAtomic*()], [\n#include <libkern/OSAtomic.h>\n#include <inttypes.h>\n], [\n\t{\n\t\tint32_t x32 = 0;\n\t\tvolatile int32_t *x32p = &x32;\n\t\tOSAtomicAdd32(1, x32p);\n\t}\n\t{\n\t\tint64_t x64 = 0;\n\t\tvolatile int64_t *x64p = &x64;\n\t\tOSAtomicAdd64(1, x64p);\n\t}\n], [je_cv_osatomic])\nif test \"x${je_cv_osatomic}\" = \"xyes\" ; then\n  AC_DEFINE([JEMALLOC_OSATOMIC], [ ])\nfi\n\ndnl ============================================================================\ndnl Check whether __sync_{add,sub}_and_fetch() are available despite\ndnl __GCC_HAVE_SYNC_COMPARE_AND_SWAP_n macros being undefined.\n\nAC_DEFUN([JE_SYNC_COMPARE_AND_SWAP_CHECK],[\n  AC_CACHE_CHECK([whether to force $1-bit __sync_{add,sub}_and_fetch()],\n               [je_cv_sync_compare_and_swap_$2],\n               [AC_LINK_IFELSE([AC_LANG_PROGRAM([\n                                                 #include <stdint.h>\n                                                ],\n                                                [\n                                                 #ifndef __GCC_HAVE_SYNC_COMPARE_AND_SWAP_$2\n                                                 {\n                                                    uint$1_t x$1 = 0;\n                                                    __sync_add_and_fetch(&x$1, 42);\n                                                    __sync_sub_and_fetch(&x$1, 1);\n                                                 }\n                                                 #else\n                                                 #error __GCC_HAVE_SYNC_COMPARE_AND_SWAP_$2 is defined, no need to force\n                                                 #endif\n                                                ])],\n                               [je_cv_sync_compare_and_swap_$2=yes],\n                               [je_cv_sync_compare_and_swap_$2=no])])\n\n  if test \"x${je_cv_sync_compare_and_swap_$2}\" = \"xyes\" ; then\n    AC_DEFINE([JE_FORCE_SYNC_COMPARE_AND_SWAP_$2], [ ])\n  fi\n])\n\nif test \"x${je_cv_atomic9}\" != \"xyes\" -a \"x${je_cv_osatomic}\" != \"xyes\" ; then\n  JE_SYNC_COMPARE_AND_SWAP_CHECK(32, 4)\n  JE_SYNC_COMPARE_AND_SWAP_CHECK(64, 8)\nfi\n\ndnl ============================================================================\ndnl Check for spinlock(3) operations as provided on Darwin.\n\nJE_COMPILABLE([Darwin OSSpin*()], [\n#include <libkern/OSAtomic.h>\n#include <inttypes.h>\n], [\n\tOSSpinLock lock = 0;\n\tOSSpinLockLock(&lock);\n\tOSSpinLockUnlock(&lock);\n], [je_cv_osspin])\nif test \"x${je_cv_osspin}\" = \"xyes\" ; then\n  AC_DEFINE([JEMALLOC_OSSPIN], [ ])\nfi\n\ndnl ============================================================================\ndnl Darwin-related configuration.\n\nAC_ARG_ENABLE([zone-allocator],\n  [AS_HELP_STRING([--disable-zone-allocator],\n                  [Disable zone allocator for Darwin])],\n[if test \"x$enable_zone_allocator\" = \"xno\" ; then\n  enable_zone_allocator=\"0\"\nelse\n  enable_zone_allocator=\"1\"\nfi\n],\n[if test \"x${abi}\" = \"xmacho\"; then\n  enable_zone_allocator=\"1\"\nfi\n]\n)\nAC_SUBST([enable_zone_allocator])\n\nif test \"x${enable_zone_allocator}\" = \"x1\" ; then\n  if test \"x${abi}\" != \"xmacho\"; then\n    AC_MSG_ERROR([--enable-zone-allocator is only supported on Darwin])\n  fi\n  AC_DEFINE([JEMALLOC_IVSALLOC], [ ])\n  AC_DEFINE([JEMALLOC_ZONE], [ ])\n\n  dnl The szone version jumped from 3 to 6 between the OS X 10.5.x and 10.6\n  dnl releases.  malloc_zone_t and malloc_introspection_t have new fields in\n  dnl 10.6, which is the only source-level indication of the change.\n  AC_MSG_CHECKING([malloc zone version])\n  AC_DEFUN([JE_ZONE_PROGRAM],\n    [AC_LANG_PROGRAM(\n      [#include <malloc/malloc.h>],\n      [static foo[[sizeof($1) $2 sizeof(void *) * $3 ? 1 : -1]]]\n    )])\n\n  AC_COMPILE_IFELSE([JE_ZONE_PROGRAM(malloc_zone_t,==,14)],[JEMALLOC_ZONE_VERSION=3],[\n  AC_COMPILE_IFELSE([JE_ZONE_PROGRAM(malloc_zone_t,==,15)],[JEMALLOC_ZONE_VERSION=5],[\n  AC_COMPILE_IFELSE([JE_ZONE_PROGRAM(malloc_zone_t,==,16)],[\n    AC_COMPILE_IFELSE([JE_ZONE_PROGRAM(malloc_introspection_t,==,9)],[JEMALLOC_ZONE_VERSION=6],[\n    AC_COMPILE_IFELSE([JE_ZONE_PROGRAM(malloc_introspection_t,==,13)],[JEMALLOC_ZONE_VERSION=7],[JEMALLOC_ZONE_VERSION=]\n  )])],[\n  AC_COMPILE_IFELSE([JE_ZONE_PROGRAM(malloc_zone_t,==,17)],[JEMALLOC_ZONE_VERSION=8],[\n  AC_COMPILE_IFELSE([JE_ZONE_PROGRAM(malloc_zone_t,>,17)],[JEMALLOC_ZONE_VERSION=9],[JEMALLOC_ZONE_VERSION=]\n  )])])])])\n  if test \"x${JEMALLOC_ZONE_VERSION}\" = \"x\"; then\n    AC_MSG_RESULT([unsupported])\n    AC_MSG_ERROR([Unsupported malloc zone version])\n  fi\n  if test \"${JEMALLOC_ZONE_VERSION}\" = 9; then\n    JEMALLOC_ZONE_VERSION=8\n    AC_MSG_RESULT([> 8])\n  else\n    AC_MSG_RESULT([$JEMALLOC_ZONE_VERSION])\n  fi\n  AC_DEFINE_UNQUOTED(JEMALLOC_ZONE_VERSION, [$JEMALLOC_ZONE_VERSION])\nfi\n\ndnl ============================================================================\ndnl Check for typedefs, structures, and compiler characteristics.\nAC_HEADER_STDBOOL\n\ndnl ============================================================================\ndnl Define commands that generate output files.\n\nAC_CONFIG_COMMANDS([include/jemalloc/internal/private_namespace.h], [\n  mkdir -p \"${objroot}include/jemalloc/internal\"\n  \"${srcdir}/include/jemalloc/internal/private_namespace.sh\" \"${srcdir}/include/jemalloc/internal/private_symbols.txt\" > \"${objroot}include/jemalloc/internal/private_namespace.h\"\n], [\n  srcdir=\"${srcdir}\"\n  objroot=\"${objroot}\"\n])\nAC_CONFIG_COMMANDS([include/jemalloc/internal/private_unnamespace.h], [\n  mkdir -p \"${objroot}include/jemalloc/internal\"\n  \"${srcdir}/include/jemalloc/internal/private_unnamespace.sh\" \"${srcdir}/include/jemalloc/internal/private_symbols.txt\" > \"${objroot}include/jemalloc/internal/private_unnamespace.h\"\n], [\n  srcdir=\"${srcdir}\"\n  objroot=\"${objroot}\"\n])\nAC_CONFIG_COMMANDS([include/jemalloc/internal/public_symbols.txt], [\n  f=\"${objroot}include/jemalloc/internal/public_symbols.txt\"\n  mkdir -p \"${objroot}include/jemalloc/internal\"\n  cp /dev/null \"${f}\"\n  for nm in `echo ${mangling_map} |tr ',' ' '` ; do\n    n=`echo ${nm} |tr ':' ' ' |awk '{print $[]1}'`\n    m=`echo ${nm} |tr ':' ' ' |awk '{print $[]2}'`\n    echo \"${n}:${m}\" >> \"${f}\"\n    dnl Remove name from public_syms so that it isn't redefined later.\n    public_syms=`for sym in ${public_syms}; do echo \"${sym}\"; done |grep -v \"^${n}\\$\" |tr '\\n' ' '`\n  done\n  for sym in ${public_syms} ; do\n    n=\"${sym}\"\n    m=\"${JEMALLOC_PREFIX}${sym}\"\n    echo \"${n}:${m}\" >> \"${f}\"\n  done\n], [\n  srcdir=\"${srcdir}\"\n  objroot=\"${objroot}\"\n  mangling_map=\"${mangling_map}\"\n  public_syms=\"${public_syms}\"\n  JEMALLOC_PREFIX=\"${JEMALLOC_PREFIX}\"\n])\nAC_CONFIG_COMMANDS([include/jemalloc/internal/public_namespace.h], [\n  mkdir -p \"${objroot}include/jemalloc/internal\"\n  \"${srcdir}/include/jemalloc/internal/public_namespace.sh\" \"${objroot}include/jemalloc/internal/public_symbols.txt\" > \"${objroot}include/jemalloc/internal/public_namespace.h\"\n], [\n  srcdir=\"${srcdir}\"\n  objroot=\"${objroot}\"\n])\nAC_CONFIG_COMMANDS([include/jemalloc/internal/public_unnamespace.h], [\n  mkdir -p \"${objroot}include/jemalloc/internal\"\n  \"${srcdir}/include/jemalloc/internal/public_unnamespace.sh\" \"${objroot}include/jemalloc/internal/public_symbols.txt\" > \"${objroot}include/jemalloc/internal/public_unnamespace.h\"\n], [\n  srcdir=\"${srcdir}\"\n  objroot=\"${objroot}\"\n])\nAC_CONFIG_COMMANDS([include/jemalloc/internal/size_classes.h], [\n  mkdir -p \"${objroot}include/jemalloc/internal\"\n  \"${srcdir}/include/jemalloc/internal/size_classes.sh\" > \"${objroot}include/jemalloc/internal/size_classes.h\"\n], [\n  srcdir=\"${srcdir}\"\n  objroot=\"${objroot}\"\n])\nAC_CONFIG_COMMANDS([include/jemalloc/jemalloc_protos_jet.h], [\n  mkdir -p \"${objroot}include/jemalloc\"\n  cat \"${srcdir}/include/jemalloc/jemalloc_protos.h.in\" | sed -e 's/@je_@/jet_/g' > \"${objroot}include/jemalloc/jemalloc_protos_jet.h\"\n], [\n  srcdir=\"${srcdir}\"\n  objroot=\"${objroot}\"\n])\nAC_CONFIG_COMMANDS([include/jemalloc/jemalloc_rename.h], [\n  mkdir -p \"${objroot}include/jemalloc\"\n  \"${srcdir}/include/jemalloc/jemalloc_rename.sh\" \"${objroot}include/jemalloc/internal/public_symbols.txt\" > \"${objroot}include/jemalloc/jemalloc_rename.h\"\n], [\n  srcdir=\"${srcdir}\"\n  objroot=\"${objroot}\"\n])\nAC_CONFIG_COMMANDS([include/jemalloc/jemalloc_mangle.h], [\n  mkdir -p \"${objroot}include/jemalloc\"\n  \"${srcdir}/include/jemalloc/jemalloc_mangle.sh\" \"${objroot}include/jemalloc/internal/public_symbols.txt\" je_ > \"${objroot}include/jemalloc/jemalloc_mangle.h\"\n], [\n  srcdir=\"${srcdir}\"\n  objroot=\"${objroot}\"\n])\nAC_CONFIG_COMMANDS([include/jemalloc/jemalloc_mangle_jet.h], [\n  mkdir -p \"${objroot}include/jemalloc\"\n  \"${srcdir}/include/jemalloc/jemalloc_mangle.sh\" \"${objroot}include/jemalloc/internal/public_symbols.txt\" jet_ > \"${objroot}include/jemalloc/jemalloc_mangle_jet.h\"\n], [\n  srcdir=\"${srcdir}\"\n  objroot=\"${objroot}\"\n])\nAC_CONFIG_COMMANDS([include/jemalloc/jemalloc.h], [\n  mkdir -p \"${objroot}include/jemalloc\"\n  \"${srcdir}/include/jemalloc/jemalloc.sh\" \"${objroot}\" > \"${objroot}include/jemalloc/jemalloc${install_suffix}.h\"\n], [\n  srcdir=\"${srcdir}\"\n  objroot=\"${objroot}\"\n  install_suffix=\"${install_suffix}\"\n])\n\ndnl Process .in files.\nAC_SUBST([cfghdrs_in])\nAC_SUBST([cfghdrs_out])\nAC_CONFIG_HEADERS([$cfghdrs_tup])\n\ndnl ============================================================================\ndnl Generate outputs.\n\nAC_CONFIG_FILES([$cfgoutputs_tup config.stamp bin/jemalloc.sh])\nAC_SUBST([cfgoutputs_in])\nAC_SUBST([cfgoutputs_out])\nAC_OUTPUT\n\ndnl ============================================================================\ndnl Print out the results of configuration.\nAC_MSG_RESULT([===============================================================================])\nAC_MSG_RESULT([jemalloc version   : ${jemalloc_version}])\nAC_MSG_RESULT([library revision   : ${rev}])\nAC_MSG_RESULT([])\nAC_MSG_RESULT([CC                 : ${CC}])\nAC_MSG_RESULT([CPPFLAGS           : ${CPPFLAGS}])\nAC_MSG_RESULT([CFLAGS             : ${CFLAGS}])\nAC_MSG_RESULT([LDFLAGS            : ${LDFLAGS}])\nAC_MSG_RESULT([EXTRA_LDFLAGS      : ${EXTRA_LDFLAGS}])\nAC_MSG_RESULT([LIBS               : ${LIBS}])\nAC_MSG_RESULT([RPATH_EXTRA        : ${RPATH_EXTRA}])\nAC_MSG_RESULT([])\nAC_MSG_RESULT([XSLTPROC           : ${XSLTPROC}])\nAC_MSG_RESULT([XSLROOT            : ${XSLROOT}])\nAC_MSG_RESULT([])\nAC_MSG_RESULT([PREFIX             : ${PREFIX}])\nAC_MSG_RESULT([BINDIR             : ${BINDIR}])\nAC_MSG_RESULT([INCLUDEDIR         : ${INCLUDEDIR}])\nAC_MSG_RESULT([LIBDIR             : ${LIBDIR}])\nAC_MSG_RESULT([DATADIR            : ${DATADIR}])\nAC_MSG_RESULT([MANDIR             : ${MANDIR}])\nAC_MSG_RESULT([])\nAC_MSG_RESULT([srcroot            : ${srcroot}])\nAC_MSG_RESULT([abs_srcroot        : ${abs_srcroot}])\nAC_MSG_RESULT([objroot            : ${objroot}])\nAC_MSG_RESULT([abs_objroot        : ${abs_objroot}])\nAC_MSG_RESULT([])\nAC_MSG_RESULT([JEMALLOC_PREFIX    : ${JEMALLOC_PREFIX}])\nAC_MSG_RESULT([JEMALLOC_PRIVATE_NAMESPACE])\nAC_MSG_RESULT([                   : ${JEMALLOC_PRIVATE_NAMESPACE}])\nAC_MSG_RESULT([install_suffix     : ${install_suffix}])\nAC_MSG_RESULT([autogen            : ${enable_autogen}])\nAC_MSG_RESULT([experimental       : ${enable_experimental}])\nAC_MSG_RESULT([cc-silence         : ${enable_cc_silence}])\nAC_MSG_RESULT([debug              : ${enable_debug}])\nAC_MSG_RESULT([code-coverage      : ${enable_code_coverage}])\nAC_MSG_RESULT([stats              : ${enable_stats}])\nAC_MSG_RESULT([prof               : ${enable_prof}])\nAC_MSG_RESULT([prof-libunwind     : ${enable_prof_libunwind}])\nAC_MSG_RESULT([prof-libgcc        : ${enable_prof_libgcc}])\nAC_MSG_RESULT([prof-gcc           : ${enable_prof_gcc}])\nAC_MSG_RESULT([tcache             : ${enable_tcache}])\nAC_MSG_RESULT([fill               : ${enable_fill}])\nAC_MSG_RESULT([utrace             : ${enable_utrace}])\nAC_MSG_RESULT([valgrind           : ${enable_valgrind}])\nAC_MSG_RESULT([xmalloc            : ${enable_xmalloc}])\nAC_MSG_RESULT([mremap             : ${enable_mremap}])\nAC_MSG_RESULT([munmap             : ${enable_munmap}])\nAC_MSG_RESULT([dss                : ${enable_dss}])\nAC_MSG_RESULT([lazy_lock          : ${enable_lazy_lock}])\nAC_MSG_RESULT([tls                : ${enable_tls}])\nAC_MSG_RESULT([===============================================================================])\n"
  },
  {
    "path": "extern/deprecated/redis-2.8.21/deps/jemalloc/coverage.sh",
    "content": "#!/bin/sh\n\nset -e\n\nobjdir=$1\nsuffix=$2\nshift 2\nobjs=$@\n\ngcov -b -p -f -o \"${objdir}\" ${objs}\n\n# Move gcov outputs so that subsequent gcov invocations won't clobber results\n# for the same sources with different compilation flags.\nfor f in `find . -maxdepth 1 -type f -name '*.gcov'` ; do\n  mv \"${f}\" \"${f}.${suffix}\"\ndone\n"
  },
  {
    "path": "extern/deprecated/redis-2.8.21/deps/jemalloc/doc/html.xsl.in",
    "content": "<xsl:stylesheet xmlns:xsl=\"http://www.w3.org/1999/XSL/Transform\" version=\"1.0\">\n  <xsl:import href=\"@XSLROOT@/html/docbook.xsl\"/>\n  <xsl:import href=\"@abs_srcroot@doc/stylesheet.xsl\"/>\n</xsl:stylesheet>\n"
  },
  {
    "path": "extern/deprecated/redis-2.8.21/deps/jemalloc/doc/jemalloc.xml.in",
    "content": "<?xml version='1.0' encoding='UTF-8'?>\n<?xml-stylesheet type=\"text/xsl\"\n        href=\"http://docbook.sourceforge.net/release/xsl/current/manpages/docbook.xsl\"?>\n<!DOCTYPE refentry PUBLIC \"-//OASIS//DTD DocBook XML V4.4//EN\"\n        \"http://www.oasis-open.org/docbook/xml/4.4/docbookx.dtd\" [\n]>\n\n<refentry>\n  <refentryinfo>\n    <title>User Manual</title>\n    <productname>jemalloc</productname>\n    <releaseinfo role=\"version\">@jemalloc_version@</releaseinfo>\n    <authorgroup>\n      <author>\n        <firstname>Jason</firstname>\n        <surname>Evans</surname>\n        <personblurb>Author</personblurb>\n      </author>\n    </authorgroup>\n  </refentryinfo>\n  <refmeta>\n    <refentrytitle>JEMALLOC</refentrytitle>\n    <manvolnum>3</manvolnum>\n  </refmeta>\n  <refnamediv>\n    <refdescriptor>jemalloc</refdescriptor>\n    <refname>jemalloc</refname>\n    <!-- Each refname causes a man page file to be created.  Only if this were\n         the system malloc(3) implementation would these files be appropriate.\n    <refname>malloc</refname>\n    <refname>calloc</refname>\n    <refname>posix_memalign</refname>\n    <refname>aligned_alloc</refname>\n    <refname>realloc</refname>\n    <refname>free</refname>\n    <refname>mallocx</refname>\n    <refname>rallocx</refname>\n    <refname>xallocx</refname>\n    <refname>sallocx</refname>\n    <refname>dallocx</refname>\n    <refname>nallocx</refname>\n    <refname>mallctl</refname>\n    <refname>mallctlnametomib</refname>\n    <refname>mallctlbymib</refname>\n    <refname>malloc_stats_print</refname>\n    <refname>malloc_usable_size</refname>\n    <refname>allocm</refname>\n    <refname>rallocm</refname>\n    <refname>sallocm</refname>\n    <refname>dallocm</refname>\n    <refname>nallocm</refname>\n    -->\n    <refpurpose>general purpose memory allocation functions</refpurpose>\n  </refnamediv>\n  <refsect1 id=\"library\">\n    <title>LIBRARY</title>\n    <para>This manual describes jemalloc @jemalloc_version@.  More information\n    can be found at the <ulink\n    url=\"http://www.canonware.com/jemalloc/\">jemalloc website</ulink>.</para>\n  </refsect1>\n  <refsynopsisdiv>\n    <title>SYNOPSIS</title>\n    <funcsynopsis>\n      <funcsynopsisinfo>#include &lt;<filename class=\"headerfile\">stdlib.h</filename>&gt;\n#include &lt;<filename class=\"headerfile\">jemalloc/jemalloc.h</filename>&gt;</funcsynopsisinfo>\n      <refsect2>\n        <title>Standard API</title>\n        <funcprototype>\n          <funcdef>void *<function>malloc</function></funcdef>\n          <paramdef>size_t <parameter>size</parameter></paramdef>\n        </funcprototype>\n        <funcprototype>\n          <funcdef>void *<function>calloc</function></funcdef>\n          <paramdef>size_t <parameter>number</parameter></paramdef>\n          <paramdef>size_t <parameter>size</parameter></paramdef>\n        </funcprototype>\n        <funcprototype>\n          <funcdef>int <function>posix_memalign</function></funcdef>\n          <paramdef>void **<parameter>ptr</parameter></paramdef>\n          <paramdef>size_t <parameter>alignment</parameter></paramdef>\n          <paramdef>size_t <parameter>size</parameter></paramdef>\n        </funcprototype>\n        <funcprototype>\n          <funcdef>void *<function>aligned_alloc</function></funcdef>\n          <paramdef>size_t <parameter>alignment</parameter></paramdef>\n          <paramdef>size_t <parameter>size</parameter></paramdef>\n        </funcprototype>\n        <funcprototype>\n          <funcdef>void *<function>realloc</function></funcdef>\n          <paramdef>void *<parameter>ptr</parameter></paramdef>\n          <paramdef>size_t <parameter>size</parameter></paramdef>\n        </funcprototype>\n        <funcprototype>\n          <funcdef>void <function>free</function></funcdef>\n          <paramdef>void *<parameter>ptr</parameter></paramdef>\n        </funcprototype>\n      </refsect2>\n      <refsect2>\n        <title>Non-standard API</title>\n        <funcprototype>\n          <funcdef>void *<function>mallocx</function></funcdef>\n          <paramdef>size_t <parameter>size</parameter></paramdef>\n          <paramdef>int <parameter>flags</parameter></paramdef>\n        </funcprototype>\n        <funcprototype>\n          <funcdef>void *<function>rallocx</function></funcdef>\n          <paramdef>void *<parameter>ptr</parameter></paramdef>\n          <paramdef>size_t <parameter>size</parameter></paramdef>\n          <paramdef>int <parameter>flags</parameter></paramdef>\n        </funcprototype>\n        <funcprototype>\n          <funcdef>size_t <function>xallocx</function></funcdef>\n          <paramdef>void *<parameter>ptr</parameter></paramdef>\n          <paramdef>size_t <parameter>size</parameter></paramdef>\n          <paramdef>size_t <parameter>extra</parameter></paramdef>\n          <paramdef>int <parameter>flags</parameter></paramdef>\n        </funcprototype>\n        <funcprototype>\n          <funcdef>size_t <function>sallocx</function></funcdef>\n          <paramdef>void *<parameter>ptr</parameter></paramdef>\n          <paramdef>int <parameter>flags</parameter></paramdef>\n        </funcprototype>\n        <funcprototype>\n          <funcdef>void <function>dallocx</function></funcdef>\n          <paramdef>void *<parameter>ptr</parameter></paramdef>\n          <paramdef>int <parameter>flags</parameter></paramdef>\n        </funcprototype>\n        <funcprototype>\n          <funcdef>size_t <function>nallocx</function></funcdef>\n          <paramdef>size_t <parameter>size</parameter></paramdef>\n          <paramdef>int <parameter>flags</parameter></paramdef>\n        </funcprototype>\n        <funcprototype>\n          <funcdef>int <function>mallctl</function></funcdef>\n          <paramdef>const char *<parameter>name</parameter></paramdef>\n          <paramdef>void *<parameter>oldp</parameter></paramdef>\n          <paramdef>size_t *<parameter>oldlenp</parameter></paramdef>\n          <paramdef>void *<parameter>newp</parameter></paramdef>\n          <paramdef>size_t <parameter>newlen</parameter></paramdef>\n        </funcprototype>\n        <funcprototype>\n          <funcdef>int <function>mallctlnametomib</function></funcdef>\n          <paramdef>const char *<parameter>name</parameter></paramdef>\n          <paramdef>size_t *<parameter>mibp</parameter></paramdef>\n          <paramdef>size_t *<parameter>miblenp</parameter></paramdef>\n        </funcprototype>\n        <funcprototype>\n          <funcdef>int <function>mallctlbymib</function></funcdef>\n          <paramdef>const size_t *<parameter>mib</parameter></paramdef>\n          <paramdef>size_t <parameter>miblen</parameter></paramdef>\n          <paramdef>void *<parameter>oldp</parameter></paramdef>\n          <paramdef>size_t *<parameter>oldlenp</parameter></paramdef>\n          <paramdef>void *<parameter>newp</parameter></paramdef>\n          <paramdef>size_t <parameter>newlen</parameter></paramdef>\n        </funcprototype>\n        <funcprototype>\n          <funcdef>void <function>malloc_stats_print</function></funcdef>\n          <paramdef>void <parameter>(*write_cb)</parameter>\n            <funcparams>void *, const char *</funcparams>\n          </paramdef>\n          <paramdef>void *<parameter>cbopaque</parameter></paramdef>\n          <paramdef>const char *<parameter>opts</parameter></paramdef>\n        </funcprototype>\n        <funcprototype>\n          <funcdef>size_t <function>malloc_usable_size</function></funcdef>\n          <paramdef>const void *<parameter>ptr</parameter></paramdef>\n        </funcprototype>\n        <funcprototype>\n          <funcdef>void <function>(*malloc_message)</function></funcdef>\n          <paramdef>void *<parameter>cbopaque</parameter></paramdef>\n          <paramdef>const char *<parameter>s</parameter></paramdef>\n        </funcprototype>\n        <para><type>const char *</type><varname>malloc_conf</varname>;</para>\n      </refsect2>\n      <refsect2>\n      <title>Experimental API</title>\n        <funcprototype>\n          <funcdef>int <function>allocm</function></funcdef>\n          <paramdef>void **<parameter>ptr</parameter></paramdef>\n          <paramdef>size_t *<parameter>rsize</parameter></paramdef>\n          <paramdef>size_t <parameter>size</parameter></paramdef>\n          <paramdef>int <parameter>flags</parameter></paramdef>\n        </funcprototype>\n        <funcprototype>\n          <funcdef>int <function>rallocm</function></funcdef>\n          <paramdef>void **<parameter>ptr</parameter></paramdef>\n          <paramdef>size_t *<parameter>rsize</parameter></paramdef>\n          <paramdef>size_t <parameter>size</parameter></paramdef>\n          <paramdef>size_t <parameter>extra</parameter></paramdef>\n          <paramdef>int <parameter>flags</parameter></paramdef>\n        </funcprototype>\n        <funcprototype>\n          <funcdef>int <function>sallocm</function></funcdef>\n          <paramdef>const void *<parameter>ptr</parameter></paramdef>\n          <paramdef>size_t *<parameter>rsize</parameter></paramdef>\n          <paramdef>int <parameter>flags</parameter></paramdef>\n        </funcprototype>\n        <funcprototype>\n          <funcdef>int <function>dallocm</function></funcdef>\n          <paramdef>void *<parameter>ptr</parameter></paramdef>\n          <paramdef>int <parameter>flags</parameter></paramdef>\n        </funcprototype>\n        <funcprototype>\n          <funcdef>int <function>nallocm</function></funcdef>\n          <paramdef>size_t *<parameter>rsize</parameter></paramdef>\n          <paramdef>size_t <parameter>size</parameter></paramdef>\n          <paramdef>int <parameter>flags</parameter></paramdef>\n        </funcprototype>\n      </refsect2>\n    </funcsynopsis>\n  </refsynopsisdiv>\n  <refsect1 id=\"description\">\n    <title>DESCRIPTION</title>\n    <refsect2>\n      <title>Standard API</title>\n\n      <para>The <function>malloc<parameter/></function> function allocates\n      <parameter>size</parameter> bytes of uninitialized memory.  The allocated\n      space is suitably aligned (after possible pointer coercion) for storage\n      of any type of object.</para>\n\n      <para>The <function>calloc<parameter/></function> function allocates\n      space for <parameter>number</parameter> objects, each\n      <parameter>size</parameter> bytes in length.  The result is identical to\n      calling <function>malloc<parameter/></function> with an argument of\n      <parameter>number</parameter> * <parameter>size</parameter>, with the\n      exception that the allocated memory is explicitly initialized to zero\n      bytes.</para>\n\n      <para>The <function>posix_memalign<parameter/></function> function\n      allocates <parameter>size</parameter> bytes of memory such that the\n      allocation's base address is an even multiple of\n      <parameter>alignment</parameter>, and returns the allocation in the value\n      pointed to by <parameter>ptr</parameter>.  The requested\n      <parameter>alignment</parameter> must be a power of 2 at least as large\n      as <code language=\"C\">sizeof(<type>void *</type>)</code>.</para>\n\n      <para>The <function>aligned_alloc<parameter/></function> function\n      allocates <parameter>size</parameter> bytes of memory such that the\n      allocation's base address is an even multiple of\n      <parameter>alignment</parameter>.  The requested\n      <parameter>alignment</parameter> must be a power of 2.  Behavior is\n      undefined if <parameter>size</parameter> is not an integral multiple of\n      <parameter>alignment</parameter>.</para>\n\n      <para>The <function>realloc<parameter/></function> function changes the\n      size of the previously allocated memory referenced by\n      <parameter>ptr</parameter> to <parameter>size</parameter> bytes.  The\n      contents of the memory are unchanged up to the lesser of the new and old\n      sizes.  If the new size is larger, the contents of the newly allocated\n      portion of the memory are undefined.  Upon success, the memory referenced\n      by <parameter>ptr</parameter> is freed and a pointer to the newly\n      allocated memory is returned.  Note that\n      <function>realloc<parameter/></function> may move the memory allocation,\n      resulting in a different return value than <parameter>ptr</parameter>.\n      If <parameter>ptr</parameter> is <constant>NULL</constant>, the\n      <function>realloc<parameter/></function> function behaves identically to\n      <function>malloc<parameter/></function> for the specified size.</para>\n\n      <para>The <function>free<parameter/></function> function causes the\n      allocated memory referenced by <parameter>ptr</parameter> to be made\n      available for future allocations.  If <parameter>ptr</parameter> is\n      <constant>NULL</constant>, no action occurs.</para>\n    </refsect2>\n    <refsect2>\n      <title>Non-standard API</title>\n      <para>The <function>mallocx<parameter/></function>,\n      <function>rallocx<parameter/></function>,\n      <function>xallocx<parameter/></function>,\n      <function>sallocx<parameter/></function>,\n      <function>dallocx<parameter/></function>, and\n      <function>nallocx<parameter/></function> functions all have a\n      <parameter>flags</parameter> argument that can be used to specify\n      options.  The functions only check the options that are contextually\n      relevant.  Use bitwise or (<code language=\"C\">|</code>) operations to\n      specify one or more of the following:\n        <variablelist>\n          <varlistentry>\n            <term><constant>MALLOCX_LG_ALIGN(<parameter>la</parameter>)\n            </constant></term>\n\n            <listitem><para>Align the memory allocation to start at an address\n            that is a multiple of <code language=\"C\">(1 &lt;&lt;\n            <parameter>la</parameter>)</code>.  This macro does not validate\n            that <parameter>la</parameter> is within the valid\n            range.</para></listitem>\n          </varlistentry>\n          <varlistentry>\n            <term><constant>MALLOCX_ALIGN(<parameter>a</parameter>)\n            </constant></term>\n\n            <listitem><para>Align the memory allocation to start at an address\n            that is a multiple of <parameter>a</parameter>, where\n            <parameter>a</parameter> is a power of two.  This macro does not\n            validate that <parameter>a</parameter> is a power of 2.\n            </para></listitem>\n          </varlistentry>\n          <varlistentry>\n            <term><constant>MALLOCX_ZERO</constant></term>\n\n            <listitem><para>Initialize newly allocated memory to contain zero\n            bytes.  In the growing reallocation case, the real size prior to\n            reallocation defines the boundary between untouched bytes and those\n            that are initialized to contain zero bytes.  If this macro is\n            absent, newly allocated memory is uninitialized.</para></listitem>\n          </varlistentry>\n          <varlistentry>\n            <term><constant>MALLOCX_ARENA(<parameter>a</parameter>)\n            </constant></term>\n\n            <listitem><para>Use the arena specified by the index\n            <parameter>a</parameter> (and by necessity bypass the thread\n            cache).  This macro has no effect for huge regions, nor for regions\n            that were allocated via an arena other than the one specified.\n            This macro does not validate that <parameter>a</parameter>\n            specifies an arena index in the valid range.</para></listitem>\n          </varlistentry>\n        </variablelist>\n      </para>\n\n      <para>The <function>mallocx<parameter/></function> function allocates at\n      least <parameter>size</parameter> bytes of memory, and returns a pointer\n      to the base address of the allocation.  Behavior is undefined if\n      <parameter>size</parameter> is <constant>0</constant>, or if request size\n      overflows due to size class and/or alignment constraints.</para>\n\n      <para>The <function>rallocx<parameter/></function> function resizes the\n      allocation at <parameter>ptr</parameter> to be at least\n      <parameter>size</parameter> bytes, and returns a pointer to the base\n      address of the resulting allocation, which may or may not have moved from\n      its original location.  Behavior is undefined if\n      <parameter>size</parameter> is <constant>0</constant>, or if request size\n      overflows due to size class and/or alignment constraints.</para>\n\n      <para>The <function>xallocx<parameter/></function> function resizes the\n      allocation at <parameter>ptr</parameter> in place to be at least\n      <parameter>size</parameter> bytes, and returns the real size of the\n      allocation.  If <parameter>extra</parameter> is non-zero, an attempt is\n      made to resize the allocation to be at least <code\n      language=\"C\">(<parameter>size</parameter> +\n      <parameter>extra</parameter>)</code> bytes, though inability to allocate\n      the extra byte(s) will not by itself result in failure to resize.\n      Behavior is undefined if <parameter>size</parameter> is\n      <constant>0</constant>, or if <code\n      language=\"C\">(<parameter>size</parameter> + <parameter>extra</parameter>\n      &gt; <constant>SIZE_T_MAX</constant>)</code>.</para>\n\n      <para>The <function>sallocx<parameter/></function> function returns the\n      real size of the allocation at <parameter>ptr</parameter>.</para>\n\n      <para>The <function>dallocx<parameter/></function> function causes the\n      memory referenced by <parameter>ptr</parameter> to be made available for\n      future allocations.</para>\n\n      <para>The <function>nallocx<parameter/></function> function allocates no\n      memory, but it performs the same size computation as the\n      <function>mallocx<parameter/></function> function, and returns the real\n      size of the allocation that would result from the equivalent\n      <function>mallocx<parameter/></function> function call.  Behavior is\n      undefined if <parameter>size</parameter> is <constant>0</constant>, or if\n      request size overflows due to size class and/or alignment\n      constraints.</para>\n\n      <para>The <function>mallctl<parameter/></function> function provides a\n      general interface for introspecting the memory allocator, as well as\n      setting modifiable parameters and triggering actions.  The\n      period-separated <parameter>name</parameter> argument specifies a\n      location in a tree-structured namespace; see the <xref\n      linkend=\"mallctl_namespace\" xrefstyle=\"template:%t\"/> section for\n      documentation on the tree contents.  To read a value, pass a pointer via\n      <parameter>oldp</parameter> to adequate space to contain the value, and a\n      pointer to its length via <parameter>oldlenp</parameter>; otherwise pass\n      <constant>NULL</constant> and <constant>NULL</constant>.  Similarly, to\n      write a value, pass a pointer to the value via\n      <parameter>newp</parameter>, and its length via\n      <parameter>newlen</parameter>; otherwise pass <constant>NULL</constant>\n      and <constant>0</constant>.</para>\n\n      <para>The <function>mallctlnametomib<parameter/></function> function\n      provides a way to avoid repeated name lookups for applications that\n      repeatedly query the same portion of the namespace, by translating a name\n      to a &ldquo;Management Information Base&rdquo; (MIB) that can be passed\n      repeatedly to <function>mallctlbymib<parameter/></function>.  Upon\n      successful return from <function>mallctlnametomib<parameter/></function>,\n      <parameter>mibp</parameter> contains an array of\n      <parameter>*miblenp</parameter> integers, where\n      <parameter>*miblenp</parameter> is the lesser of the number of components\n      in <parameter>name</parameter> and the input value of\n      <parameter>*miblenp</parameter>.  Thus it is possible to pass a\n      <parameter>*miblenp</parameter> that is smaller than the number of\n      period-separated name components, which results in a partial MIB that can\n      be used as the basis for constructing a complete MIB.  For name\n      components that are integers (e.g. the 2 in\n      <link\n      linkend=\"arenas.bin.i.size\"><mallctl>arenas.bin.2.size</mallctl></link>),\n      the corresponding MIB component will always be that integer.  Therefore,\n      it is legitimate to construct code like the following: <programlisting\n      language=\"C\"><![CDATA[\nunsigned nbins, i;\nsize_t mib[4];\nsize_t len, miblen;\n\nlen = sizeof(nbins);\nmallctl(\"arenas.nbins\", &nbins, &len, NULL, 0);\n\nmiblen = 4;\nmallctlnametomib(\"arenas.bin.0.size\", mib, &miblen);\nfor (i = 0; i < nbins; i++) {\n\tsize_t bin_size;\n\n\tmib[2] = i;\n\tlen = sizeof(bin_size);\n\tmallctlbymib(mib, miblen, &bin_size, &len, NULL, 0);\n\t/* Do something with bin_size... */\n}]]></programlisting></para>\n\n      <para>The <function>malloc_stats_print<parameter/></function> function\n      writes human-readable summary statistics via the\n      <parameter>write_cb</parameter> callback function pointer and\n      <parameter>cbopaque</parameter> data passed to\n      <parameter>write_cb</parameter>, or\n      <function>malloc_message<parameter/></function> if\n      <parameter>write_cb</parameter> is <constant>NULL</constant>.  This\n      function can be called repeatedly.  General information that never\n      changes during execution can be omitted by specifying \"g\" as a character\n      within the <parameter>opts</parameter> string.  Note that\n      <function>malloc_message<parameter/></function> uses the\n      <function>mallctl*<parameter/></function> functions internally, so\n      inconsistent statistics can be reported if multiple threads use these\n      functions simultaneously.  If <option>--enable-stats</option> is\n      specified during configuration, &ldquo;m&rdquo; and &ldquo;a&rdquo; can\n      be specified to omit merged arena and per arena statistics, respectively;\n      &ldquo;b&rdquo; and &ldquo;l&rdquo; can be specified to omit per size\n      class statistics for bins and large objects, respectively.  Unrecognized\n      characters are silently ignored.  Note that thread caching may prevent\n      some statistics from being completely up to date, since extra locking\n      would be required to merge counters that track thread cache operations.\n      </para>\n\n      <para>The <function>malloc_usable_size<parameter/></function> function\n      returns the usable size of the allocation pointed to by\n      <parameter>ptr</parameter>.  The return value may be larger than the size\n      that was requested during allocation.  The\n      <function>malloc_usable_size<parameter/></function> function is not a\n      mechanism for in-place <function>realloc<parameter/></function>; rather\n      it is provided solely as a tool for introspection purposes.  Any\n      discrepancy between the requested allocation size and the size reported\n      by <function>malloc_usable_size<parameter/></function> should not be\n      depended on, since such behavior is entirely implementation-dependent.\n      </para>\n    </refsect2>\n    <refsect2>\n      <title>Experimental API</title>\n      <para>The experimental API is subject to change or removal without regard\n      for backward compatibility.  If <option>--disable-experimental</option>\n      is specified during configuration, the experimental API is\n      omitted.</para>\n\n      <para>The <function>allocm<parameter/></function>,\n      <function>rallocm<parameter/></function>,\n      <function>sallocm<parameter/></function>,\n      <function>dallocm<parameter/></function>, and\n      <function>nallocm<parameter/></function> functions all have a\n      <parameter>flags</parameter> argument that can be used to specify\n      options.  The functions only check the options that are contextually\n      relevant.  Use bitwise or (<code language=\"C\">|</code>) operations to\n      specify one or more of the following:\n        <variablelist>\n          <varlistentry>\n            <term><constant>ALLOCM_LG_ALIGN(<parameter>la</parameter>)\n            </constant></term>\n\n            <listitem><para>Align the memory allocation to start at an address\n            that is a multiple of <code language=\"C\">(1 &lt;&lt;\n            <parameter>la</parameter>)</code>.  This macro does not validate\n            that <parameter>la</parameter> is within the valid\n            range.</para></listitem>\n          </varlistentry>\n          <varlistentry>\n            <term><constant>ALLOCM_ALIGN(<parameter>a</parameter>)\n            </constant></term>\n\n            <listitem><para>Align the memory allocation to start at an address\n            that is a multiple of <parameter>a</parameter>, where\n            <parameter>a</parameter> is a power of two.  This macro does not\n            validate that <parameter>a</parameter> is a power of 2.\n            </para></listitem>\n          </varlistentry>\n          <varlistentry>\n            <term><constant>ALLOCM_ZERO</constant></term>\n\n            <listitem><para>Initialize newly allocated memory to contain zero\n            bytes.  In the growing reallocation case, the real size prior to\n            reallocation defines the boundary between untouched bytes and those\n            that are initialized to contain zero bytes.  If this macro is\n            absent, newly allocated memory is uninitialized.</para></listitem>\n          </varlistentry>\n          <varlistentry>\n            <term><constant>ALLOCM_NO_MOVE</constant></term>\n\n            <listitem><para>For reallocation, fail rather than moving the\n            object.  This constraint can apply to both growth and\n            shrinkage.</para></listitem>\n          </varlistentry>\n          <varlistentry>\n            <term><constant>ALLOCM_ARENA(<parameter>a</parameter>)\n            </constant></term>\n\n            <listitem><para>Use the arena specified by the index\n            <parameter>a</parameter> (and by necessity bypass the thread\n            cache).  This macro has no effect for huge regions, nor for regions\n            that were allocated via an arena other than the one specified.\n            This macro does not validate that <parameter>a</parameter>\n            specifies an arena index in the valid range.</para></listitem>\n          </varlistentry>\n        </variablelist>\n      </para>\n\n      <para>The <function>allocm<parameter/></function> function allocates at\n      least <parameter>size</parameter> bytes of memory, sets\n      <parameter>*ptr</parameter> to the base address of the allocation, and\n      sets <parameter>*rsize</parameter> to the real size of the allocation if\n      <parameter>rsize</parameter> is not <constant>NULL</constant>.  Behavior\n      is undefined if <parameter>size</parameter> is <constant>0</constant>, or\n      if request size overflows due to size class and/or alignment\n      constraints.</para>\n\n      <para>The <function>rallocm<parameter/></function> function resizes the\n      allocation at <parameter>*ptr</parameter> to be at least\n      <parameter>size</parameter> bytes, sets <parameter>*ptr</parameter> to\n      the base address of the allocation if it moved, and sets\n      <parameter>*rsize</parameter> to the real size of the allocation if\n      <parameter>rsize</parameter> is not <constant>NULL</constant>.  If\n      <parameter>extra</parameter> is non-zero, an attempt is made to resize\n      the allocation to be at least <code\n      language=\"C\">(<parameter>size</parameter> +\n      <parameter>extra</parameter>)</code> bytes, though inability to allocate\n      the extra byte(s) will not by itself result in failure.  Behavior is\n      undefined if <parameter>size</parameter> is <constant>0</constant>, if\n      request size overflows due to size class and/or alignment constraints, or\n      if <code language=\"C\">(<parameter>size</parameter> +\n      <parameter>extra</parameter> &gt;\n      <constant>SIZE_T_MAX</constant>)</code>.</para>\n\n      <para>The <function>sallocm<parameter/></function> function sets\n      <parameter>*rsize</parameter> to the real size of the allocation.</para>\n\n      <para>The <function>dallocm<parameter/></function> function causes the\n      memory referenced by <parameter>ptr</parameter> to be made available for\n      future allocations.</para>\n\n      <para>The <function>nallocm<parameter/></function> function allocates no\n      memory, but it performs the same size computation as the\n      <function>allocm<parameter/></function> function, and if\n      <parameter>rsize</parameter> is not <constant>NULL</constant> it sets\n      <parameter>*rsize</parameter> to the real size of the allocation that\n      would result from the equivalent <function>allocm<parameter/></function>\n      function call.  Behavior is undefined if <parameter>size</parameter> is\n      <constant>0</constant>, or if request size overflows due to size class\n      and/or alignment constraints.</para>\n    </refsect2>\n  </refsect1>\n  <refsect1 id=\"tuning\">\n    <title>TUNING</title>\n    <para>Once, when the first call is made to one of the memory allocation\n    routines, the allocator initializes its internals based in part on various\n    options that can be specified at compile- or run-time.</para>\n\n    <para>The string pointed to by the global variable\n    <varname>malloc_conf</varname>, the &ldquo;name&rdquo; of the file\n    referenced by the symbolic link named <filename\n    class=\"symlink\">/etc/malloc.conf</filename>, and the value of the\n    environment variable <envar>MALLOC_CONF</envar>, will be interpreted, in\n    that order, from left to right as options.  Note that\n    <varname>malloc_conf</varname> may be read before\n    <function>main<parameter/></function> is entered, so the declaration of\n    <varname>malloc_conf</varname> should specify an initializer that contains\n    the final value to be read by jemalloc.  <varname>malloc_conf</varname> is\n    a compile-time setting, whereas <filename\n    class=\"symlink\">/etc/malloc.conf</filename> and <envar>MALLOC_CONF</envar>\n    can be safely set any time prior to program invocation.</para>\n\n    <para>An options string is a comma-separated list of option:value pairs.\n    There is one key corresponding to each <link\n    linkend=\"opt.abort\"><mallctl>opt.*</mallctl></link> mallctl (see the <xref\n    linkend=\"mallctl_namespace\" xrefstyle=\"template:%t\"/> section for options\n    documentation).  For example, <literal>abort:true,narenas:1</literal> sets\n    the <link linkend=\"opt.abort\"><mallctl>opt.abort</mallctl></link> and <link\n    linkend=\"opt.narenas\"><mallctl>opt.narenas</mallctl></link> options.  Some\n    options have boolean values (true/false), others have integer values (base\n    8, 10, or 16, depending on prefix), and yet others have raw string\n    values.</para>\n  </refsect1>\n  <refsect1 id=\"implementation_notes\">\n    <title>IMPLEMENTATION NOTES</title>\n    <para>Traditionally, allocators have used\n    <citerefentry><refentrytitle>sbrk</refentrytitle>\n    <manvolnum>2</manvolnum></citerefentry> to obtain memory, which is\n    suboptimal for several reasons, including race conditions, increased\n    fragmentation, and artificial limitations on maximum usable memory.  If\n    <option>--enable-dss</option> is specified during configuration, this\n    allocator uses both <citerefentry><refentrytitle>mmap</refentrytitle>\n    <manvolnum>2</manvolnum></citerefentry> and\n    <citerefentry><refentrytitle>sbrk</refentrytitle>\n    <manvolnum>2</manvolnum></citerefentry>, in that order of preference;\n    otherwise only <citerefentry><refentrytitle>mmap</refentrytitle>\n    <manvolnum>2</manvolnum></citerefentry> is used.</para>\n\n    <para>This allocator uses multiple arenas in order to reduce lock\n    contention for threaded programs on multi-processor systems.  This works\n    well with regard to threading scalability, but incurs some costs.  There is\n    a small fixed per-arena overhead, and additionally, arenas manage memory\n    completely independently of each other, which means a small fixed increase\n    in overall memory fragmentation.  These overheads are not generally an\n    issue, given the number of arenas normally used.  Note that using\n    substantially more arenas than the default is not likely to improve\n    performance, mainly due to reduced cache performance.  However, it may make\n    sense to reduce the number of arenas if an application does not make much\n    use of the allocation functions.</para>\n\n    <para>In addition to multiple arenas, unless\n    <option>--disable-tcache</option> is specified during configuration, this\n    allocator supports thread-specific caching for small and large objects, in\n    order to make it possible to completely avoid synchronization for most\n    allocation requests.  Such caching allows very fast allocation in the\n    common case, but it increases memory usage and fragmentation, since a\n    bounded number of objects can remain allocated in each thread cache.</para>\n\n    <para>Memory is conceptually broken into equal-sized chunks, where the\n    chunk size is a power of two that is greater than the page size.  Chunks\n    are always aligned to multiples of the chunk size.  This alignment makes it\n    possible to find metadata for user objects very quickly.</para>\n\n    <para>User objects are broken into three categories according to size:\n    small, large, and huge.  Small objects are smaller than one page.  Large\n    objects are smaller than the chunk size.  Huge objects are a multiple of\n    the chunk size.  Small and large objects are managed by arenas; huge\n    objects are managed separately in a single data structure that is shared by\n    all threads.  Huge objects are used by applications infrequently enough\n    that this single data structure is not a scalability issue.</para>\n\n    <para>Each chunk that is managed by an arena tracks its contents as runs of\n    contiguous pages (unused, backing a set of small objects, or backing one\n    large object).  The combination of chunk alignment and chunk page maps\n    makes it possible to determine all metadata regarding small and large\n    allocations in constant time.</para>\n\n    <para>Small objects are managed in groups by page runs.  Each run maintains\n    a frontier and free list to track which regions are in use.  Allocation\n    requests that are no more than half the quantum (8 or 16, depending on\n    architecture) are rounded up to the nearest power of two that is at least\n    <code language=\"C\">sizeof(<type>double</type>)</code>.  All other small\n    object size classes are multiples of the quantum, spaced such that internal\n    fragmentation is limited to approximately 25% for all but the smallest size\n    classes.  Allocation requests that are larger than the maximum small size\n    class, but small enough to fit in an arena-managed chunk (see the <link\n    linkend=\"opt.lg_chunk\"><mallctl>opt.lg_chunk</mallctl></link> option), are\n    rounded up to the nearest run size.  Allocation requests that are too large\n    to fit in an arena-managed chunk are rounded up to the nearest multiple of\n    the chunk size.</para>\n\n    <para>Allocations are packed tightly together, which can be an issue for\n    multi-threaded applications.  If you need to assure that allocations do not\n    suffer from cacheline sharing, round your allocation requests up to the\n    nearest multiple of the cacheline size, or specify cacheline alignment when\n    allocating.</para>\n\n    <para>Assuming 4 MiB chunks, 4 KiB pages, and a 16-byte quantum on a 64-bit\n    system, the size classes in each category are as shown in <xref\n    linkend=\"size_classes\" xrefstyle=\"template:Table %n\"/>.</para>\n\n    <table xml:id=\"size_classes\" frame=\"all\">\n      <title>Size classes</title>\n      <tgroup cols=\"3\" colsep=\"1\" rowsep=\"1\">\n      <colspec colname=\"c1\" align=\"left\"/>\n      <colspec colname=\"c2\" align=\"right\"/>\n      <colspec colname=\"c3\" align=\"left\"/>\n      <thead>\n        <row>\n          <entry>Category</entry>\n          <entry>Spacing</entry>\n          <entry>Size</entry>\n        </row>\n      </thead>\n      <tbody>\n        <row>\n          <entry morerows=\"6\">Small</entry>\n          <entry>lg</entry>\n          <entry>[8]</entry>\n        </row>\n        <row>\n          <entry>16</entry>\n          <entry>[16, 32, 48, ..., 128]</entry>\n        </row>\n        <row>\n          <entry>32</entry>\n          <entry>[160, 192, 224, 256]</entry>\n        </row>\n        <row>\n          <entry>64</entry>\n          <entry>[320, 384, 448, 512]</entry>\n        </row>\n        <row>\n          <entry>128</entry>\n          <entry>[640, 768, 896, 1024]</entry>\n        </row>\n        <row>\n          <entry>256</entry>\n          <entry>[1280, 1536, 1792, 2048]</entry>\n        </row>\n        <row>\n          <entry>512</entry>\n          <entry>[2560, 3072, 3584]</entry>\n        </row>\n        <row>\n          <entry>Large</entry>\n          <entry>4 KiB</entry>\n          <entry>[4 KiB, 8 KiB, 12 KiB, ..., 4072 KiB]</entry>\n        </row>\n        <row>\n          <entry>Huge</entry>\n          <entry>4 MiB</entry>\n          <entry>[4 MiB, 8 MiB, 12 MiB, ...]</entry>\n        </row>\n      </tbody>\n      </tgroup>\n    </table>\n  </refsect1>\n  <refsect1 id=\"mallctl_namespace\">\n    <title>MALLCTL NAMESPACE</title>\n    <para>The following names are defined in the namespace accessible via the\n    <function>mallctl*<parameter/></function> functions.  Value types are\n    specified in parentheses, their readable/writable statuses are encoded as\n    <literal>rw</literal>, <literal>r-</literal>, <literal>-w</literal>, or\n    <literal>--</literal>, and required build configuration flags follow, if\n    any.  A name element encoded as <literal>&lt;i&gt;</literal> or\n    <literal>&lt;j&gt;</literal> indicates an integer component, where the\n    integer varies from 0 to some upper value that must be determined via\n    introspection.  In the case of <mallctl>stats.arenas.&lt;i&gt;.*</mallctl>,\n    <literal>&lt;i&gt;</literal> equal to <link\n    linkend=\"arenas.narenas\"><mallctl>arenas.narenas</mallctl></link> can be\n    used to access the summation of statistics from all arenas.  Take special\n    note of the <link linkend=\"epoch\"><mallctl>epoch</mallctl></link> mallctl,\n    which controls refreshing of cached dynamic statistics.</para>\n\n    <variablelist>\n      <varlistentry id=\"version\">\n        <term>\n          <mallctl>version</mallctl>\n          (<type>const char *</type>)\n          <literal>r-</literal>\n        </term>\n        <listitem><para>Return the jemalloc version string.</para></listitem>\n      </varlistentry>\n\n      <varlistentry id=\"epoch\">\n        <term>\n          <mallctl>epoch</mallctl>\n          (<type>uint64_t</type>)\n          <literal>rw</literal>\n        </term>\n        <listitem><para>If a value is passed in, refresh the data from which\n        the <function>mallctl*<parameter/></function> functions report values,\n        and increment the epoch.  Return the current epoch.  This is useful for\n        detecting whether another thread caused a refresh.</para></listitem>\n      </varlistentry>\n\n      <varlistentry id=\"config.debug\">\n        <term>\n          <mallctl>config.debug</mallctl>\n          (<type>bool</type>)\n          <literal>r-</literal>\n        </term>\n        <listitem><para><option>--enable-debug</option> was specified during\n        build configuration.</para></listitem>\n      </varlistentry>\n\n      <varlistentry id=\"config.dss\">\n        <term>\n          <mallctl>config.dss</mallctl>\n          (<type>bool</type>)\n          <literal>r-</literal>\n        </term>\n        <listitem><para><option>--enable-dss</option> was specified during\n        build configuration.</para></listitem>\n      </varlistentry>\n\n      <varlistentry id=\"config.fill\">\n        <term>\n          <mallctl>config.fill</mallctl>\n          (<type>bool</type>)\n          <literal>r-</literal>\n        </term>\n        <listitem><para><option>--enable-fill</option> was specified during\n        build configuration.</para></listitem>\n      </varlistentry>\n\n      <varlistentry id=\"config.lazy_lock\">\n        <term>\n          <mallctl>config.lazy_lock</mallctl>\n          (<type>bool</type>)\n          <literal>r-</literal>\n        </term>\n        <listitem><para><option>--enable-lazy-lock</option> was specified\n        during build configuration.</para></listitem>\n      </varlistentry>\n\n      <varlistentry id=\"config.mremap\">\n        <term>\n          <mallctl>config.mremap</mallctl>\n          (<type>bool</type>)\n          <literal>r-</literal>\n        </term>\n        <listitem><para><option>--enable-mremap</option> was specified during\n        build configuration.</para></listitem>\n      </varlistentry>\n\n      <varlistentry id=\"config.munmap\">\n        <term>\n          <mallctl>config.munmap</mallctl>\n          (<type>bool</type>)\n          <literal>r-</literal>\n        </term>\n        <listitem><para><option>--enable-munmap</option> was specified during\n        build configuration.</para></listitem>\n      </varlistentry>\n\n      <varlistentry id=\"config.prof\">\n        <term>\n          <mallctl>config.prof</mallctl>\n          (<type>bool</type>)\n          <literal>r-</literal>\n        </term>\n        <listitem><para><option>--enable-prof</option> was specified during\n        build configuration.</para></listitem>\n      </varlistentry>\n\n      <varlistentry id=\"config.prof_libgcc\">\n        <term>\n          <mallctl>config.prof_libgcc</mallctl>\n          (<type>bool</type>)\n          <literal>r-</literal>\n        </term>\n        <listitem><para><option>--disable-prof-libgcc</option> was not\n        specified during build configuration.</para></listitem>\n      </varlistentry>\n\n      <varlistentry id=\"config.prof_libunwind\">\n        <term>\n          <mallctl>config.prof_libunwind</mallctl>\n          (<type>bool</type>)\n          <literal>r-</literal>\n        </term>\n        <listitem><para><option>--enable-prof-libunwind</option> was specified\n        during build configuration.</para></listitem>\n      </varlistentry>\n\n      <varlistentry id=\"config.stats\">\n        <term>\n          <mallctl>config.stats</mallctl>\n          (<type>bool</type>)\n          <literal>r-</literal>\n        </term>\n        <listitem><para><option>--enable-stats</option> was specified during\n        build configuration.</para></listitem>\n      </varlistentry>\n\n      <varlistentry id=\"config.tcache\">\n        <term>\n          <mallctl>config.tcache</mallctl>\n          (<type>bool</type>)\n          <literal>r-</literal>\n        </term>\n        <listitem><para><option>--disable-tcache</option> was not specified\n        during build configuration.</para></listitem>\n      </varlistentry>\n\n      <varlistentry id=\"config.tls\">\n        <term>\n          <mallctl>config.tls</mallctl>\n          (<type>bool</type>)\n          <literal>r-</literal>\n        </term>\n        <listitem><para><option>--disable-tls</option> was not specified during\n        build configuration.</para></listitem>\n      </varlistentry>\n\n      <varlistentry id=\"config.utrace\">\n        <term>\n          <mallctl>config.utrace</mallctl>\n          (<type>bool</type>)\n          <literal>r-</literal>\n        </term>\n        <listitem><para><option>--enable-utrace</option> was specified during\n        build configuration.</para></listitem>\n      </varlistentry>\n\n      <varlistentry id=\"config.valgrind\">\n        <term>\n          <mallctl>config.valgrind</mallctl>\n          (<type>bool</type>)\n          <literal>r-</literal>\n        </term>\n        <listitem><para><option>--enable-valgrind</option> was specified during\n        build configuration.</para></listitem>\n      </varlistentry>\n\n      <varlistentry id=\"config.xmalloc\">\n        <term>\n          <mallctl>config.xmalloc</mallctl>\n          (<type>bool</type>)\n          <literal>r-</literal>\n        </term>\n        <listitem><para><option>--enable-xmalloc</option> was specified during\n        build configuration.</para></listitem>\n      </varlistentry>\n\n      <varlistentry id=\"opt.abort\">\n        <term>\n          <mallctl>opt.abort</mallctl>\n          (<type>bool</type>)\n          <literal>r-</literal>\n        </term>\n        <listitem><para>Abort-on-warning enabled/disabled.  If true, most\n        warnings are fatal.  The process will call\n        <citerefentry><refentrytitle>abort</refentrytitle>\n        <manvolnum>3</manvolnum></citerefentry> in these cases.  This option is\n        disabled by default unless <option>--enable-debug</option> is\n        specified during configuration, in which case it is enabled by default.\n        </para></listitem>\n      </varlistentry>\n\n      <varlistentry id=\"opt.dss\">\n        <term>\n          <mallctl>opt.dss</mallctl>\n          (<type>const char *</type>)\n          <literal>r-</literal>\n        </term>\n        <listitem><para>dss (<citerefentry><refentrytitle>sbrk</refentrytitle>\n        <manvolnum>2</manvolnum></citerefentry>) allocation precedence as\n        related to <citerefentry><refentrytitle>mmap</refentrytitle>\n        <manvolnum>2</manvolnum></citerefentry> allocation.  The following\n        settings are supported: &ldquo;disabled&rdquo;, &ldquo;primary&rdquo;,\n        and &ldquo;secondary&rdquo;.  The default is &ldquo;secondary&rdquo; if\n        <link linkend=\"config.dss\"><mallctl>config.dss</mallctl></link> is\n        true, &ldquo;disabled&rdquo; otherwise.\n        </para></listitem>\n      </varlistentry>\n\n      <varlistentry id=\"opt.lg_chunk\">\n        <term>\n          <mallctl>opt.lg_chunk</mallctl>\n          (<type>size_t</type>)\n          <literal>r-</literal>\n        </term>\n        <listitem><para>Virtual memory chunk size (log base 2).  If a chunk\n        size outside the supported size range is specified, the size is\n        silently clipped to the minimum/maximum supported size.  The default\n        chunk size is 4 MiB (2^22).\n        </para></listitem>\n      </varlistentry>\n\n      <varlistentry id=\"opt.narenas\">\n        <term>\n          <mallctl>opt.narenas</mallctl>\n          (<type>size_t</type>)\n          <literal>r-</literal>\n        </term>\n        <listitem><para>Maximum number of arenas to use for automatic\n        multiplexing of threads and arenas.  The default is four times the\n        number of CPUs, or one if there is a single CPU.</para></listitem>\n      </varlistentry>\n\n      <varlistentry id=\"opt.lg_dirty_mult\">\n        <term>\n          <mallctl>opt.lg_dirty_mult</mallctl>\n          (<type>ssize_t</type>)\n          <literal>r-</literal>\n        </term>\n        <listitem><para>Per-arena minimum ratio (log base 2) of active to dirty\n        pages.  Some dirty unused pages may be allowed to accumulate, within\n        the limit set by the ratio (or one chunk worth of dirty pages,\n        whichever is greater), before informing the kernel about some of those\n        pages via <citerefentry><refentrytitle>madvise</refentrytitle>\n        <manvolnum>2</manvolnum></citerefentry> or a similar system call.  This\n        provides the kernel with sufficient information to recycle dirty pages\n        if physical memory becomes scarce and the pages remain unused.  The\n        default minimum ratio is 8:1 (2^3:1); an option value of -1 will\n        disable dirty page purging.</para></listitem>\n      </varlistentry>\n\n      <varlistentry id=\"opt.stats_print\">\n        <term>\n          <mallctl>opt.stats_print</mallctl>\n          (<type>bool</type>)\n          <literal>r-</literal>\n        </term>\n        <listitem><para>Enable/disable statistics printing at exit.  If\n        enabled, the <function>malloc_stats_print<parameter/></function>\n        function is called at program exit via an\n        <citerefentry><refentrytitle>atexit</refentrytitle>\n        <manvolnum>3</manvolnum></citerefentry> function.  If\n        <option>--enable-stats</option> is specified during configuration, this\n        has the potential to cause deadlock for a multi-threaded process that\n        exits while one or more threads are executing in the memory allocation\n        functions.  Therefore, this option should only be used with care; it is\n        primarily intended as a performance tuning aid during application\n        development.  This option is disabled by default.</para></listitem>\n      </varlistentry>\n\n      <varlistentry id=\"opt.junk\">\n        <term>\n          <mallctl>opt.junk</mallctl>\n          (<type>bool</type>)\n          <literal>r-</literal>\n          [<option>--enable-fill</option>]\n        </term>\n        <listitem><para>Junk filling enabled/disabled.  If enabled, each byte\n        of uninitialized allocated memory will be initialized to\n        <literal>0xa5</literal>.  All deallocated memory will be initialized to\n        <literal>0x5a</literal>.  This is intended for debugging and will\n        impact performance negatively.  This option is disabled by default\n        unless <option>--enable-debug</option> is specified during\n        configuration, in which case it is enabled by default unless running\n        inside <ulink\n        url=\"http://valgrind.org/\">Valgrind</ulink>.</para></listitem>\n      </varlistentry>\n\n      <varlistentry id=\"opt.quarantine\">\n        <term>\n          <mallctl>opt.quarantine</mallctl>\n          (<type>size_t</type>)\n          <literal>r-</literal>\n          [<option>--enable-fill</option>]\n        </term>\n        <listitem><para>Per thread quarantine size in bytes.  If non-zero, each\n        thread maintains a FIFO object quarantine that stores up to the\n        specified number of bytes of memory.  The quarantined memory is not\n        freed until it is released from quarantine, though it is immediately\n        junk-filled if the <link\n        linkend=\"opt.junk\"><mallctl>opt.junk</mallctl></link> option is\n        enabled.  This feature is of particular use in combination with <ulink\n        url=\"http://valgrind.org/\">Valgrind</ulink>, which can detect attempts\n        to access quarantined objects.  This is intended for debugging and will\n        impact performance negatively.  The default quarantine size is 0 unless\n        running inside Valgrind, in which case the default is 16\n        MiB.</para></listitem>\n      </varlistentry>\n\n      <varlistentry id=\"opt.redzone\">\n        <term>\n          <mallctl>opt.redzone</mallctl>\n          (<type>bool</type>)\n          <literal>r-</literal>\n          [<option>--enable-fill</option>]\n        </term>\n        <listitem><para>Redzones enabled/disabled.  If enabled, small\n        allocations have redzones before and after them.  Furthermore, if the\n        <link linkend=\"opt.junk\"><mallctl>opt.junk</mallctl></link> option is\n        enabled, the redzones are checked for corruption during deallocation.\n        However, the primary intended purpose of this feature is to be used in\n        combination with <ulink url=\"http://valgrind.org/\">Valgrind</ulink>,\n        which needs redzones in order to do effective buffer overflow/underflow\n        detection.  This option is intended for debugging and will impact\n        performance negatively.  This option is disabled by\n        default unless running inside Valgrind.</para></listitem>\n      </varlistentry>\n\n      <varlistentry id=\"opt.zero\">\n        <term>\n          <mallctl>opt.zero</mallctl>\n          (<type>bool</type>)\n          <literal>r-</literal>\n          [<option>--enable-fill</option>]\n        </term>\n        <listitem><para>Zero filling enabled/disabled.  If enabled, each byte\n        of uninitialized allocated memory will be initialized to 0.  Note that\n        this initialization only happens once for each byte, so\n        <function>realloc<parameter/></function>,\n        <function>rallocx<parameter/></function> and\n        <function>rallocm<parameter/></function> calls do not zero memory that\n        was previously allocated.  This is intended for debugging and will\n        impact performance negatively.  This option is disabled by default.\n        </para></listitem>\n      </varlistentry>\n\n      <varlistentry id=\"opt.utrace\">\n        <term>\n          <mallctl>opt.utrace</mallctl>\n          (<type>bool</type>)\n          <literal>r-</literal>\n          [<option>--enable-utrace</option>]\n        </term>\n        <listitem><para>Allocation tracing based on\n        <citerefentry><refentrytitle>utrace</refentrytitle>\n        <manvolnum>2</manvolnum></citerefentry> enabled/disabled.  This option\n        is disabled by default.</para></listitem>\n      </varlistentry>\n\n      <varlistentry id=\"opt.valgrind\">\n        <term>\n          <mallctl>opt.valgrind</mallctl>\n          (<type>bool</type>)\n          <literal>r-</literal>\n          [<option>--enable-valgrind</option>]\n        </term>\n        <listitem><para><ulink url=\"http://valgrind.org/\">Valgrind</ulink>\n        support enabled/disabled.  This option is vestigal because jemalloc\n        auto-detects whether it is running inside Valgrind.  This option is\n        disabled by default, unless running inside Valgrind.</para></listitem>\n      </varlistentry>\n\n      <varlistentry id=\"opt.xmalloc\">\n        <term>\n          <mallctl>opt.xmalloc</mallctl>\n          (<type>bool</type>)\n          <literal>r-</literal>\n          [<option>--enable-xmalloc</option>]\n        </term>\n        <listitem><para>Abort-on-out-of-memory enabled/disabled.  If enabled,\n        rather than returning failure for any allocation function, display a\n        diagnostic message on <constant>STDERR_FILENO</constant> and cause the\n        program to drop core (using\n        <citerefentry><refentrytitle>abort</refentrytitle>\n        <manvolnum>3</manvolnum></citerefentry>).  If an application is\n        designed to depend on this behavior, set the option at compile time by\n        including the following in the source code:\n        <programlisting language=\"C\"><![CDATA[\nmalloc_conf = \"xmalloc:true\";]]></programlisting>\n        This option is disabled by default.</para></listitem>\n      </varlistentry>\n\n      <varlistentry id=\"opt.tcache\">\n        <term>\n          <mallctl>opt.tcache</mallctl>\n          (<type>bool</type>)\n          <literal>r-</literal>\n          [<option>--enable-tcache</option>]\n        </term>\n        <listitem><para>Thread-specific caching enabled/disabled.  When there\n        are multiple threads, each thread uses a thread-specific cache for\n        objects up to a certain size.  Thread-specific caching allows many\n        allocations to be satisfied without performing any thread\n        synchronization, at the cost of increased memory use.  See the\n        <link\n        linkend=\"opt.lg_tcache_max\"><mallctl>opt.lg_tcache_max</mallctl></link>\n        option for related tuning information.  This option is enabled by\n        default unless running inside <ulink\n        url=\"http://valgrind.org/\">Valgrind</ulink>.</para></listitem>\n      </varlistentry>\n\n      <varlistentry id=\"opt.lg_tcache_max\">\n        <term>\n          <mallctl>opt.lg_tcache_max</mallctl>\n          (<type>size_t</type>)\n          <literal>r-</literal>\n          [<option>--enable-tcache</option>]\n        </term>\n        <listitem><para>Maximum size class (log base 2) to cache in the\n        thread-specific cache.  At a minimum, all small size classes are\n        cached, and at a maximum all large size classes are cached.  The\n        default maximum is 32 KiB (2^15).</para></listitem>\n      </varlistentry>\n\n      <varlistentry id=\"opt.prof\">\n        <term>\n          <mallctl>opt.prof</mallctl>\n          (<type>bool</type>)\n          <literal>r-</literal>\n          [<option>--enable-prof</option>]\n        </term>\n        <listitem><para>Memory profiling enabled/disabled.  If enabled, profile\n        memory allocation activity.  See the <link\n        linkend=\"opt.prof_active\"><mallctl>opt.prof_active</mallctl></link>\n        option for on-the-fly activation/deactivation.  See the <link\n        linkend=\"opt.lg_prof_sample\"><mallctl>opt.lg_prof_sample</mallctl></link>\n        option for probabilistic sampling control.  See the <link\n        linkend=\"opt.prof_accum\"><mallctl>opt.prof_accum</mallctl></link>\n        option for control of cumulative sample reporting.  See the <link\n        linkend=\"opt.lg_prof_interval\"><mallctl>opt.lg_prof_interval</mallctl></link>\n        option for information on interval-triggered profile dumping, the <link\n        linkend=\"opt.prof_gdump\"><mallctl>opt.prof_gdump</mallctl></link>\n        option for information on high-water-triggered profile dumping, and the\n        <link linkend=\"opt.prof_final\"><mallctl>opt.prof_final</mallctl></link>\n        option for final profile dumping.  Profile output is compatible with\n        the included <command>pprof</command> Perl script, which originates\n        from the <ulink url=\"http://code.google.com/p/gperftools/\">gperftools\n        package</ulink>.</para></listitem>\n      </varlistentry>\n\n      <varlistentry id=\"opt.prof_prefix\">\n        <term>\n          <mallctl>opt.prof_prefix</mallctl>\n          (<type>const char *</type>)\n          <literal>r-</literal>\n          [<option>--enable-prof</option>]\n        </term>\n        <listitem><para>Filename prefix for profile dumps.  If the prefix is\n        set to the empty string, no automatic dumps will occur; this is\n        primarily useful for disabling the automatic final heap dump (which\n        also disables leak reporting, if enabled).  The default prefix is\n        <filename>jeprof</filename>.</para></listitem>\n      </varlistentry>\n\n      <varlistentry id=\"opt.prof_active\">\n        <term>\n          <mallctl>opt.prof_active</mallctl>\n          (<type>bool</type>)\n          <literal>rw</literal>\n          [<option>--enable-prof</option>]\n        </term>\n        <listitem><para>Profiling activated/deactivated.  This is a secondary\n        control mechanism that makes it possible to start the application with\n        profiling enabled (see the <link\n        linkend=\"opt.prof\"><mallctl>opt.prof</mallctl></link> option) but\n        inactive, then toggle profiling at any time during program execution\n        with the <link\n        linkend=\"prof.active\"><mallctl>prof.active</mallctl></link> mallctl.\n        This option is enabled by default.</para></listitem>\n      </varlistentry>\n\n      <varlistentry id=\"opt.lg_prof_sample\">\n        <term>\n          <mallctl>opt.lg_prof_sample</mallctl>\n          (<type>ssize_t</type>)\n          <literal>r-</literal>\n          [<option>--enable-prof</option>]\n        </term>\n        <listitem><para>Average interval (log base 2) between allocation\n        samples, as measured in bytes of allocation activity.  Increasing the\n        sampling interval decreases profile fidelity, but also decreases the\n        computational overhead.  The default sample interval is 512 KiB (2^19\n        B).</para></listitem>\n      </varlistentry>\n\n      <varlistentry id=\"opt.prof_accum\">\n        <term>\n          <mallctl>opt.prof_accum</mallctl>\n          (<type>bool</type>)\n          <literal>r-</literal>\n          [<option>--enable-prof</option>]\n        </term>\n        <listitem><para>Reporting of cumulative object/byte counts in profile\n        dumps enabled/disabled.  If this option is enabled, every unique\n        backtrace must be stored for the duration of execution.  Depending on\n        the application, this can impose a large memory overhead, and the\n        cumulative counts are not always of interest.  This option is disabled\n        by default.</para></listitem>\n      </varlistentry>\n\n      <varlistentry id=\"opt.lg_prof_interval\">\n        <term>\n          <mallctl>opt.lg_prof_interval</mallctl>\n          (<type>ssize_t</type>)\n          <literal>r-</literal>\n          [<option>--enable-prof</option>]\n        </term>\n        <listitem><para>Average interval (log base 2) between memory profile\n        dumps, as measured in bytes of allocation activity.  The actual\n        interval between dumps may be sporadic because decentralized allocation\n        counters are used to avoid synchronization bottlenecks.  Profiles are\n        dumped to files named according to the pattern\n        <filename>&lt;prefix&gt;.&lt;pid&gt;.&lt;seq&gt;.i&lt;iseq&gt;.heap</filename>,\n        where <literal>&lt;prefix&gt;</literal> is controlled by the\n        <link\n        linkend=\"opt.prof_prefix\"><mallctl>opt.prof_prefix</mallctl></link>\n        option.  By default, interval-triggered profile dumping is disabled\n        (encoded as -1).\n        </para></listitem>\n      </varlistentry>\n\n      <varlistentry id=\"opt.prof_gdump\">\n        <term>\n          <mallctl>opt.prof_gdump</mallctl>\n          (<type>bool</type>)\n          <literal>r-</literal>\n          [<option>--enable-prof</option>]\n        </term>\n        <listitem><para>Trigger a memory profile dump every time the total\n        virtual memory exceeds the previous maximum.  Profiles are dumped to\n        files named according to the pattern\n        <filename>&lt;prefix&gt;.&lt;pid&gt;.&lt;seq&gt;.u&lt;useq&gt;.heap</filename>,\n        where <literal>&lt;prefix&gt;</literal> is controlled by the <link\n        linkend=\"opt.prof_prefix\"><mallctl>opt.prof_prefix</mallctl></link>\n        option.  This option is disabled by default.</para></listitem>\n      </varlistentry>\n\n      <varlistentry id=\"opt.prof_final\">\n        <term>\n          <mallctl>opt.prof_final</mallctl>\n          (<type>bool</type>)\n          <literal>r-</literal>\n          [<option>--enable-prof</option>]\n        </term>\n        <listitem><para>Use an\n        <citerefentry><refentrytitle>atexit</refentrytitle>\n        <manvolnum>3</manvolnum></citerefentry> function to dump final memory\n        usage to a file named according to the pattern\n        <filename>&lt;prefix&gt;.&lt;pid&gt;.&lt;seq&gt;.f.heap</filename>,\n        where <literal>&lt;prefix&gt;</literal> is controlled by the <link\n        linkend=\"opt.prof_prefix\"><mallctl>opt.prof_prefix</mallctl></link>\n        option.  This option is enabled by default.</para></listitem>\n      </varlistentry>\n\n      <varlistentry id=\"opt.prof_leak\">\n        <term>\n          <mallctl>opt.prof_leak</mallctl>\n          (<type>bool</type>)\n          <literal>r-</literal>\n          [<option>--enable-prof</option>]\n        </term>\n        <listitem><para>Leak reporting enabled/disabled.  If enabled, use an\n        <citerefentry><refentrytitle>atexit</refentrytitle>\n        <manvolnum>3</manvolnum></citerefentry> function to report memory leaks\n        detected by allocation sampling.  See the\n        <link linkend=\"opt.prof\"><mallctl>opt.prof</mallctl></link> option for\n        information on analyzing heap profile output.  This option is disabled\n        by default.</para></listitem>\n      </varlistentry>\n\n      <varlistentry id=\"thread.arena\">\n        <term>\n          <mallctl>thread.arena</mallctl>\n          (<type>unsigned</type>)\n          <literal>rw</literal>\n        </term>\n        <listitem><para>Get or set the arena associated with the calling\n        thread.  If the specified arena was not initialized beforehand (see the\n        <link\n        linkend=\"arenas.initialized\"><mallctl>arenas.initialized</mallctl></link>\n        mallctl), it will be automatically initialized as a side effect of\n        calling this interface.</para></listitem>\n      </varlistentry>\n\n      <varlistentry id=\"thread.allocated\">\n        <term>\n          <mallctl>thread.allocated</mallctl>\n          (<type>uint64_t</type>)\n          <literal>r-</literal>\n          [<option>--enable-stats</option>]\n        </term>\n        <listitem><para>Get the total number of bytes ever allocated by the\n        calling thread.  This counter has the potential to wrap around; it is\n        up to the application to appropriately interpret the counter in such\n        cases.</para></listitem>\n      </varlistentry>\n\n      <varlistentry id=\"thread.allocatedp\">\n        <term>\n          <mallctl>thread.allocatedp</mallctl>\n          (<type>uint64_t *</type>)\n          <literal>r-</literal>\n          [<option>--enable-stats</option>]\n        </term>\n        <listitem><para>Get a pointer to the the value that is returned by the\n        <link\n        linkend=\"thread.allocated\"><mallctl>thread.allocated</mallctl></link>\n        mallctl.  This is useful for avoiding the overhead of repeated\n        <function>mallctl*<parameter/></function> calls.</para></listitem>\n      </varlistentry>\n\n      <varlistentry id=\"thread.deallocated\">\n        <term>\n          <mallctl>thread.deallocated</mallctl>\n          (<type>uint64_t</type>)\n          <literal>r-</literal>\n          [<option>--enable-stats</option>]\n        </term>\n        <listitem><para>Get the total number of bytes ever deallocated by the\n        calling thread.  This counter has the potential to wrap around; it is\n        up to the application to appropriately interpret the counter in such\n        cases.</para></listitem>\n      </varlistentry>\n\n      <varlistentry id=\"thread.deallocatedp\">\n        <term>\n          <mallctl>thread.deallocatedp</mallctl>\n          (<type>uint64_t *</type>)\n          <literal>r-</literal>\n          [<option>--enable-stats</option>]\n        </term>\n        <listitem><para>Get a pointer to the the value that is returned by the\n        <link\n        linkend=\"thread.deallocated\"><mallctl>thread.deallocated</mallctl></link>\n        mallctl.  This is useful for avoiding the overhead of repeated\n        <function>mallctl*<parameter/></function> calls.</para></listitem>\n      </varlistentry>\n\n      <varlistentry id=\"thread.tcache.enabled\">\n        <term>\n          <mallctl>thread.tcache.enabled</mallctl>\n          (<type>bool</type>)\n          <literal>rw</literal>\n          [<option>--enable-tcache</option>]\n        </term>\n        <listitem><para>Enable/disable calling thread's tcache.  The tcache is\n        implicitly flushed as a side effect of becoming\n        disabled (see <link\n        lenkend=\"thread.tcache.flush\"><mallctl>thread.tcache.flush</mallctl></link>).\n        </para></listitem>\n      </varlistentry>\n\n      <varlistentry id=\"thread.tcache.flush\">\n        <term>\n          <mallctl>thread.tcache.flush</mallctl>\n          (<type>void</type>)\n          <literal>--</literal>\n          [<option>--enable-tcache</option>]\n        </term>\n        <listitem><para>Flush calling thread's tcache.  This interface releases\n        all cached objects and internal data structures associated with the\n        calling thread's thread-specific cache.  Ordinarily, this interface\n        need not be called, since automatic periodic incremental garbage\n        collection occurs, and the thread cache is automatically discarded when\n        a thread exits.  However, garbage collection is triggered by allocation\n        activity, so it is possible for a thread that stops\n        allocating/deallocating to retain its cache indefinitely, in which case\n        the developer may find manual flushing useful.</para></listitem>\n      </varlistentry>\n\n      <varlistentry id=\"arena.i.purge\">\n        <term>\n          <mallctl>arena.&lt;i&gt;.purge</mallctl>\n          (<type>unsigned</type>)\n          <literal>--</literal>\n        </term>\n        <listitem><para>Purge unused dirty pages for arena &lt;i&gt;, or for\n        all arenas if &lt;i&gt; equals <link\n        linkend=\"arenas.narenas\"><mallctl>arenas.narenas</mallctl></link>.\n        </para></listitem>\n      </varlistentry>\n\n      <varlistentry id=\"arena.i.dss\">\n        <term>\n          <mallctl>arena.&lt;i&gt;.dss</mallctl>\n          (<type>const char *</type>)\n          <literal>rw</literal>\n        </term>\n        <listitem><para>Set the precedence of dss allocation as related to mmap\n        allocation for arena &lt;i&gt;, or for all arenas if &lt;i&gt; equals\n        <link\n        linkend=\"arenas.narenas\"><mallctl>arenas.narenas</mallctl></link>.  Note\n        that even during huge allocation this setting is read from the arena\n        that would be chosen for small or large allocation so that applications\n        can depend on consistent dss versus mmap allocation regardless of\n        allocation size.  See <link\n        linkend=\"opt.dss\"><mallctl>opt.dss</mallctl></link> for supported\n        settings.\n        </para></listitem>\n      </varlistentry>\n\n      <varlistentry id=\"arenas.narenas\">\n        <term>\n          <mallctl>arenas.narenas</mallctl>\n          (<type>unsigned</type>)\n          <literal>r-</literal>\n        </term>\n        <listitem><para>Current limit on number of arenas.</para></listitem>\n      </varlistentry>\n\n      <varlistentry id=\"arenas.initialized\">\n        <term>\n          <mallctl>arenas.initialized</mallctl>\n          (<type>bool *</type>)\n          <literal>r-</literal>\n        </term>\n        <listitem><para>An array of <link\n        linkend=\"arenas.narenas\"><mallctl>arenas.narenas</mallctl></link>\n        booleans.  Each boolean indicates whether the corresponding arena is\n        initialized.</para></listitem>\n      </varlistentry>\n\n      <varlistentry id=\"arenas.quantum\">\n        <term>\n          <mallctl>arenas.quantum</mallctl>\n          (<type>size_t</type>)\n          <literal>r-</literal>\n        </term>\n        <listitem><para>Quantum size.</para></listitem>\n      </varlistentry>\n\n      <varlistentry id=\"arenas.page\">\n        <term>\n          <mallctl>arenas.page</mallctl>\n          (<type>size_t</type>)\n          <literal>r-</literal>\n        </term>\n        <listitem><para>Page size.</para></listitem>\n      </varlistentry>\n\n      <varlistentry id=\"arenas.tcache_max\">\n        <term>\n          <mallctl>arenas.tcache_max</mallctl>\n          (<type>size_t</type>)\n          <literal>r-</literal>\n          [<option>--enable-tcache</option>]\n        </term>\n        <listitem><para>Maximum thread-cached size class.</para></listitem>\n      </varlistentry>\n\n      <varlistentry id=\"arenas.nbins\">\n        <term>\n          <mallctl>arenas.nbins</mallctl>\n          (<type>unsigned</type>)\n          <literal>r-</literal>\n        </term>\n        <listitem><para>Number of bin size classes.</para></listitem>\n      </varlistentry>\n\n      <varlistentry id=\"arenas.nhbins\">\n        <term>\n          <mallctl>arenas.nhbins</mallctl>\n          (<type>unsigned</type>)\n          <literal>r-</literal>\n          [<option>--enable-tcache</option>]\n        </term>\n        <listitem><para>Total number of thread cache bin size\n        classes.</para></listitem>\n      </varlistentry>\n\n      <varlistentry id=\"arenas.bin.i.size\">\n        <term>\n          <mallctl>arenas.bin.&lt;i&gt;.size</mallctl>\n          (<type>size_t</type>)\n          <literal>r-</literal>\n        </term>\n        <listitem><para>Maximum size supported by size class.</para></listitem>\n      </varlistentry>\n\n      <varlistentry id=\"arenas.bin.i.nregs\">\n        <term>\n          <mallctl>arenas.bin.&lt;i&gt;.nregs</mallctl>\n          (<type>uint32_t</type>)\n          <literal>r-</literal>\n        </term>\n        <listitem><para>Number of regions per page run.</para></listitem>\n      </varlistentry>\n\n      <varlistentry id=\"arenas.bin.i.run_size\">\n        <term>\n          <mallctl>arenas.bin.&lt;i&gt;.run_size</mallctl>\n          (<type>size_t</type>)\n          <literal>r-</literal>\n        </term>\n        <listitem><para>Number of bytes per page run.</para></listitem>\n      </varlistentry>\n\n      <varlistentry id=\"arenas.nlruns\">\n        <term>\n          <mallctl>arenas.nlruns</mallctl>\n          (<type>size_t</type>)\n          <literal>r-</literal>\n        </term>\n        <listitem><para>Total number of large size classes.</para></listitem>\n      </varlistentry>\n\n      <varlistentry id=\"arenas.lrun.i.size\">\n        <term>\n          <mallctl>arenas.lrun.&lt;i&gt;.size</mallctl>\n          (<type>size_t</type>)\n          <literal>r-</literal>\n        </term>\n        <listitem><para>Maximum size supported by this large size\n        class.</para></listitem>\n      </varlistentry>\n\n      <varlistentry id=\"arenas.purge\">\n        <term>\n          <mallctl>arenas.purge</mallctl>\n          (<type>unsigned</type>)\n          <literal>-w</literal>\n        </term>\n        <listitem><para>Purge unused dirty pages for the specified arena, or\n        for all arenas if none is specified.</para></listitem>\n      </varlistentry>\n\n      <varlistentry id=\"arenas.extend\">\n        <term>\n          <mallctl>arenas.extend</mallctl>\n          (<type>unsigned</type>)\n          <literal>r-</literal>\n        </term>\n        <listitem><para>Extend the array of arenas by appending a new arena,\n        and returning the new arena index.</para></listitem>\n      </varlistentry>\n\n      <varlistentry id=\"prof.active\">\n        <term>\n          <mallctl>prof.active</mallctl>\n          (<type>bool</type>)\n          <literal>rw</literal>\n          [<option>--enable-prof</option>]\n        </term>\n        <listitem><para>Control whether sampling is currently active.  See the\n        <link\n        linkend=\"opt.prof_active\"><mallctl>opt.prof_active</mallctl></link>\n        option for additional information.\n        </para></listitem>\n      </varlistentry>\n\n      <varlistentry id=\"prof.dump\">\n        <term>\n          <mallctl>prof.dump</mallctl>\n          (<type>const char *</type>)\n          <literal>-w</literal>\n          [<option>--enable-prof</option>]\n        </term>\n        <listitem><para>Dump a memory profile to the specified file, or if NULL\n        is specified, to a file according to the pattern\n        <filename>&lt;prefix&gt;.&lt;pid&gt;.&lt;seq&gt;.m&lt;mseq&gt;.heap</filename>,\n        where <literal>&lt;prefix&gt;</literal> is controlled by the\n        <link\n        linkend=\"opt.prof_prefix\"><mallctl>opt.prof_prefix</mallctl></link>\n        option.</para></listitem>\n      </varlistentry>\n\n      <varlistentry id=\"prof.interval\">\n        <term>\n          <mallctl>prof.interval</mallctl>\n          (<type>uint64_t</type>)\n          <literal>r-</literal>\n          [<option>--enable-prof</option>]\n        </term>\n        <listitem><para>Average number of bytes allocated between\n        inverval-based profile dumps.  See the\n        <link\n        linkend=\"opt.lg_prof_interval\"><mallctl>opt.lg_prof_interval</mallctl></link>\n        option for additional information.</para></listitem>\n      </varlistentry>\n\n      <varlistentry id=\"stats.cactive\">\n        <term>\n          <mallctl>stats.cactive</mallctl>\n          (<type>size_t *</type>)\n          <literal>r-</literal>\n          [<option>--enable-stats</option>]\n        </term>\n        <listitem><para>Pointer to a counter that contains an approximate count\n        of the current number of bytes in active pages.  The estimate may be\n        high, but never low, because each arena rounds up to the nearest\n        multiple of the chunk size when computing its contribution to the\n        counter.  Note that the <link\n        linkend=\"epoch\"><mallctl>epoch</mallctl></link> mallctl has no bearing\n        on this counter.  Furthermore, counter consistency is maintained via\n        atomic operations, so it is necessary to use an atomic operation in\n        order to guarantee a consistent read when dereferencing the pointer.\n        </para></listitem>\n      </varlistentry>\n\n      <varlistentry id=\"stats.allocated\">\n        <term>\n          <mallctl>stats.allocated</mallctl>\n          (<type>size_t</type>)\n          <literal>r-</literal>\n          [<option>--enable-stats</option>]\n        </term>\n        <listitem><para>Total number of bytes allocated by the\n        application.</para></listitem>\n      </varlistentry>\n\n      <varlistentry id=\"stats.active\">\n        <term>\n          <mallctl>stats.active</mallctl>\n          (<type>size_t</type>)\n          <literal>r-</literal>\n          [<option>--enable-stats</option>]\n        </term>\n        <listitem><para>Total number of bytes in active pages allocated by the\n        application.  This is a multiple of the page size, and greater than or\n        equal to <link\n        linkend=\"stats.allocated\"><mallctl>stats.allocated</mallctl></link>.\n        This does not include <link linkend=\"stats.arenas.i.pdirty\">\n        <mallctl>stats.arenas.&lt;i&gt;.pdirty</mallctl></link> and pages\n        entirely devoted to allocator metadata.</para></listitem>\n      </varlistentry>\n\n      <varlistentry id=\"stats.mapped\">\n        <term>\n          <mallctl>stats.mapped</mallctl>\n          (<type>size_t</type>)\n          <literal>r-</literal>\n          [<option>--enable-stats</option>]\n        </term>\n        <listitem><para>Total number of bytes in chunks mapped on behalf of the\n        application.  This is a multiple of the chunk size, and is at least as\n        large as <link\n        linkend=\"stats.active\"><mallctl>stats.active</mallctl></link>.  This\n        does not include inactive chunks.</para></listitem>\n      </varlistentry>\n\n      <varlistentry id=\"stats.chunks.current\">\n        <term>\n          <mallctl>stats.chunks.current</mallctl>\n          (<type>size_t</type>)\n          <literal>r-</literal>\n          [<option>--enable-stats</option>]\n        </term>\n        <listitem><para>Total number of chunks actively mapped on behalf of the\n        application.  This does not include inactive chunks.\n        </para></listitem>\n      </varlistentry>\n\n      <varlistentry id=\"stats.chunks.total\">\n        <term>\n          <mallctl>stats.chunks.total</mallctl>\n          (<type>uint64_t</type>)\n          <literal>r-</literal>\n          [<option>--enable-stats</option>]\n        </term>\n        <listitem><para>Cumulative number of chunks allocated.</para></listitem>\n      </varlistentry>\n\n      <varlistentry id=\"stats.chunks.high\">\n        <term>\n          <mallctl>stats.chunks.high</mallctl>\n          (<type>size_t</type>)\n          <literal>r-</literal>\n          [<option>--enable-stats</option>]\n        </term>\n        <listitem><para>Maximum number of active chunks at any time thus far.\n        </para></listitem>\n      </varlistentry>\n\n      <varlistentry id=\"stats.huge.allocated\">\n        <term>\n          <mallctl>stats.huge.allocated</mallctl>\n          (<type>size_t</type>)\n          <literal>r-</literal>\n          [<option>--enable-stats</option>]\n        </term>\n        <listitem><para>Number of bytes currently allocated by huge objects.\n        </para></listitem>\n      </varlistentry>\n\n      <varlistentry id=\"stats.huge.nmalloc\">\n        <term>\n          <mallctl>stats.huge.nmalloc</mallctl>\n          (<type>uint64_t</type>)\n          <literal>r-</literal>\n          [<option>--enable-stats</option>]\n        </term>\n        <listitem><para>Cumulative number of huge allocation requests.\n        </para></listitem>\n      </varlistentry>\n\n      <varlistentry id=\"stats.huge.ndalloc\">\n        <term>\n          <mallctl>stats.huge.ndalloc</mallctl>\n          (<type>uint64_t</type>)\n          <literal>r-</literal>\n          [<option>--enable-stats</option>]\n        </term>\n        <listitem><para>Cumulative number of huge deallocation requests.\n        </para></listitem>\n      </varlistentry>\n\n      <varlistentry id=\"stats.arenas.i.dss\">\n        <term>\n          <mallctl>stats.arenas.&lt;i&gt;.dss</mallctl>\n          (<type>const char *</type>)\n          <literal>r-</literal>\n        </term>\n        <listitem><para>dss (<citerefentry><refentrytitle>sbrk</refentrytitle>\n        <manvolnum>2</manvolnum></citerefentry>) allocation precedence as\n        related to <citerefentry><refentrytitle>mmap</refentrytitle>\n        <manvolnum>2</manvolnum></citerefentry> allocation.  See <link\n        linkend=\"opt.dss\"><mallctl>opt.dss</mallctl></link> for details.\n        </para></listitem>\n      </varlistentry>\n\n      <varlistentry id=\"stats.arenas.i.nthreads\">\n        <term>\n          <mallctl>stats.arenas.&lt;i&gt;.nthreads</mallctl>\n          (<type>unsigned</type>)\n          <literal>r-</literal>\n        </term>\n        <listitem><para>Number of threads currently assigned to\n        arena.</para></listitem>\n      </varlistentry>\n\n      <varlistentry id=\"stats.arenas.i.pactive\">\n        <term>\n          <mallctl>stats.arenas.&lt;i&gt;.pactive</mallctl>\n          (<type>size_t</type>)\n          <literal>r-</literal>\n        </term>\n        <listitem><para>Number of pages in active runs.</para></listitem>\n      </varlistentry>\n\n      <varlistentry id=\"stats.arenas.i.pdirty\">\n        <term>\n          <mallctl>stats.arenas.&lt;i&gt;.pdirty</mallctl>\n          (<type>size_t</type>)\n          <literal>r-</literal>\n        </term>\n        <listitem><para>Number of pages within unused runs that are potentially\n        dirty, and for which <function>madvise<parameter>...</parameter>\n        <parameter><constant>MADV_DONTNEED</constant></parameter></function> or\n        similar has not been called.</para></listitem>\n      </varlistentry>\n\n      <varlistentry id=\"stats.arenas.i.mapped\">\n        <term>\n          <mallctl>stats.arenas.&lt;i&gt;.mapped</mallctl>\n          (<type>size_t</type>)\n          <literal>r-</literal>\n          [<option>--enable-stats</option>]\n        </term>\n        <listitem><para>Number of mapped bytes.</para></listitem>\n      </varlistentry>\n\n      <varlistentry id=\"stats.arenas.i.npurge\">\n        <term>\n          <mallctl>stats.arenas.&lt;i&gt;.npurge</mallctl>\n          (<type>uint64_t</type>)\n          <literal>r-</literal>\n          [<option>--enable-stats</option>]\n        </term>\n        <listitem><para>Number of dirty page purge sweeps performed.\n        </para></listitem>\n      </varlistentry>\n\n      <varlistentry id=\"stats.arenas.i.nmadvise\">\n        <term>\n          <mallctl>stats.arenas.&lt;i&gt;.nmadvise</mallctl>\n          (<type>uint64_t</type>)\n          <literal>r-</literal>\n          [<option>--enable-stats</option>]\n        </term>\n        <listitem><para>Number of <function>madvise<parameter>...</parameter>\n        <parameter><constant>MADV_DONTNEED</constant></parameter></function> or\n        similar calls made to purge dirty pages.</para></listitem>\n      </varlistentry>\n\n      <varlistentry id=\"stats.arenas.i.purged\">\n        <term>\n          <mallctl>stats.arenas.&lt;i&gt;.purged</mallctl>\n          (<type>uint64_t</type>)\n          <literal>r-</literal>\n          [<option>--enable-stats</option>]\n        </term>\n        <listitem><para>Number of pages purged.</para></listitem>\n      </varlistentry>\n\n      <varlistentry id=\"stats.arenas.i.small.allocated\">\n        <term>\n          <mallctl>stats.arenas.&lt;i&gt;.small.allocated</mallctl>\n          (<type>size_t</type>)\n          <literal>r-</literal>\n          [<option>--enable-stats</option>]\n        </term>\n        <listitem><para>Number of bytes currently allocated by small objects.\n        </para></listitem>\n      </varlistentry>\n\n      <varlistentry id=\"stats.arenas.i.small.nmalloc\">\n        <term>\n          <mallctl>stats.arenas.&lt;i&gt;.small.nmalloc</mallctl>\n          (<type>uint64_t</type>)\n          <literal>r-</literal>\n          [<option>--enable-stats</option>]\n        </term>\n        <listitem><para>Cumulative number of allocation requests served by\n        small bins.</para></listitem>\n      </varlistentry>\n\n      <varlistentry id=\"stats.arenas.i.small.ndalloc\">\n        <term>\n          <mallctl>stats.arenas.&lt;i&gt;.small.ndalloc</mallctl>\n          (<type>uint64_t</type>)\n          <literal>r-</literal>\n          [<option>--enable-stats</option>]\n        </term>\n        <listitem><para>Cumulative number of small objects returned to bins.\n        </para></listitem>\n      </varlistentry>\n\n      <varlistentry id=\"stats.arenas.i.small.nrequests\">\n        <term>\n          <mallctl>stats.arenas.&lt;i&gt;.small.nrequests</mallctl>\n          (<type>uint64_t</type>)\n          <literal>r-</literal>\n          [<option>--enable-stats</option>]\n        </term>\n        <listitem><para>Cumulative number of small allocation requests.\n        </para></listitem>\n      </varlistentry>\n\n      <varlistentry id=\"stats.arenas.i.large.allocated\">\n        <term>\n          <mallctl>stats.arenas.&lt;i&gt;.large.allocated</mallctl>\n          (<type>size_t</type>)\n          <literal>r-</literal>\n          [<option>--enable-stats</option>]\n        </term>\n        <listitem><para>Number of bytes currently allocated by large objects.\n        </para></listitem>\n      </varlistentry>\n\n      <varlistentry id=\"stats.arenas.i.large.nmalloc\">\n        <term>\n          <mallctl>stats.arenas.&lt;i&gt;.large.nmalloc</mallctl>\n          (<type>uint64_t</type>)\n          <literal>r-</literal>\n          [<option>--enable-stats</option>]\n        </term>\n        <listitem><para>Cumulative number of large allocation requests served\n        directly by the arena.</para></listitem>\n      </varlistentry>\n\n      <varlistentry id=\"stats.arenas.i.large.ndalloc\">\n        <term>\n          <mallctl>stats.arenas.&lt;i&gt;.large.ndalloc</mallctl>\n          (<type>uint64_t</type>)\n          <literal>r-</literal>\n          [<option>--enable-stats</option>]\n        </term>\n        <listitem><para>Cumulative number of large deallocation requests served\n        directly by the arena.</para></listitem>\n      </varlistentry>\n\n      <varlistentry id=\"stats.arenas.i.large.nrequests\">\n        <term>\n          <mallctl>stats.arenas.&lt;i&gt;.large.nrequests</mallctl>\n          (<type>uint64_t</type>)\n          <literal>r-</literal>\n          [<option>--enable-stats</option>]\n        </term>\n        <listitem><para>Cumulative number of large allocation requests.\n        </para></listitem>\n      </varlistentry>\n\n      <varlistentry id=\"stats.arenas.i.bins.j.allocated\">\n        <term>\n          <mallctl>stats.arenas.&lt;i&gt;.bins.&lt;j&gt;.allocated</mallctl>\n          (<type>size_t</type>)\n          <literal>r-</literal>\n          [<option>--enable-stats</option>]\n        </term>\n        <listitem><para>Current number of bytes allocated by\n        bin.</para></listitem>\n      </varlistentry>\n\n      <varlistentry id=\"stats.arenas.i.bins.j.nmalloc\">\n        <term>\n          <mallctl>stats.arenas.&lt;i&gt;.bins.&lt;j&gt;.nmalloc</mallctl>\n          (<type>uint64_t</type>)\n          <literal>r-</literal>\n          [<option>--enable-stats</option>]\n        </term>\n        <listitem><para>Cumulative number of allocations served by bin.\n        </para></listitem>\n      </varlistentry>\n\n      <varlistentry id=\"stats.arenas.i.bins.j.ndalloc\">\n        <term>\n          <mallctl>stats.arenas.&lt;i&gt;.bins.&lt;j&gt;.ndalloc</mallctl>\n          (<type>uint64_t</type>)\n          <literal>r-</literal>\n          [<option>--enable-stats</option>]\n        </term>\n        <listitem><para>Cumulative number of allocations returned to bin.\n        </para></listitem>\n      </varlistentry>\n\n      <varlistentry id=\"stats.arenas.i.bins.j.nrequests\">\n        <term>\n          <mallctl>stats.arenas.&lt;i&gt;.bins.&lt;j&gt;.nrequests</mallctl>\n          (<type>uint64_t</type>)\n          <literal>r-</literal>\n          [<option>--enable-stats</option>]\n        </term>\n        <listitem><para>Cumulative number of allocation\n        requests.</para></listitem>\n      </varlistentry>\n\n      <varlistentry id=\"stats.arenas.i.bins.j.nfills\">\n        <term>\n          <mallctl>stats.arenas.&lt;i&gt;.bins.&lt;j&gt;.nfills</mallctl>\n          (<type>uint64_t</type>)\n          <literal>r-</literal>\n          [<option>--enable-stats</option> <option>--enable-tcache</option>]\n        </term>\n        <listitem><para>Cumulative number of tcache fills.</para></listitem>\n      </varlistentry>\n\n      <varlistentry id=\"stats.arenas.i.bins.j.nflushes\">\n        <term>\n          <mallctl>stats.arenas.&lt;i&gt;.bins.&lt;j&gt;.nflushes</mallctl>\n          (<type>uint64_t</type>)\n          <literal>r-</literal>\n          [<option>--enable-stats</option> <option>--enable-tcache</option>]\n        </term>\n        <listitem><para>Cumulative number of tcache flushes.</para></listitem>\n      </varlistentry>\n\n      <varlistentry id=\"stats.arenas.i.bins.j.nruns\">\n        <term>\n          <mallctl>stats.arenas.&lt;i&gt;.bins.&lt;j&gt;.nruns</mallctl>\n          (<type>uint64_t</type>)\n          <literal>r-</literal>\n          [<option>--enable-stats</option>]\n        </term>\n        <listitem><para>Cumulative number of runs created.</para></listitem>\n      </varlistentry>\n\n      <varlistentry id=\"stats.arenas.i.bins.j.nreruns\">\n        <term>\n          <mallctl>stats.arenas.&lt;i&gt;.bins.&lt;j&gt;.nreruns</mallctl>\n          (<type>uint64_t</type>)\n          <literal>r-</literal>\n          [<option>--enable-stats</option>]\n        </term>\n        <listitem><para>Cumulative number of times the current run from which\n        to allocate changed.</para></listitem>\n      </varlistentry>\n\n      <varlistentry id=\"stats.arenas.i.bins.j.curruns\">\n        <term>\n          <mallctl>stats.arenas.&lt;i&gt;.bins.&lt;j&gt;.curruns</mallctl>\n          (<type>size_t</type>)\n          <literal>r-</literal>\n          [<option>--enable-stats</option>]\n        </term>\n        <listitem><para>Current number of runs.</para></listitem>\n      </varlistentry>\n\n      <varlistentry id=\"stats.arenas.i.lruns.j.nmalloc\">\n        <term>\n          <mallctl>stats.arenas.&lt;i&gt;.lruns.&lt;j&gt;.nmalloc</mallctl>\n          (<type>uint64_t</type>)\n          <literal>r-</literal>\n          [<option>--enable-stats</option>]\n        </term>\n        <listitem><para>Cumulative number of allocation requests for this size\n        class served directly by the arena.</para></listitem>\n      </varlistentry>\n\n      <varlistentry id=\"stats.arenas.i.lruns.j.ndalloc\">\n        <term>\n          <mallctl>stats.arenas.&lt;i&gt;.lruns.&lt;j&gt;.ndalloc</mallctl>\n          (<type>uint64_t</type>)\n          <literal>r-</literal>\n          [<option>--enable-stats</option>]\n        </term>\n        <listitem><para>Cumulative number of deallocation requests for this\n        size class served directly by the arena.</para></listitem>\n      </varlistentry>\n\n      <varlistentry id=\"stats.arenas.i.lruns.j.nrequests\">\n        <term>\n          <mallctl>stats.arenas.&lt;i&gt;.lruns.&lt;j&gt;.nrequests</mallctl>\n          (<type>uint64_t</type>)\n          <literal>r-</literal>\n          [<option>--enable-stats</option>]\n        </term>\n        <listitem><para>Cumulative number of allocation requests for this size\n        class.</para></listitem>\n      </varlistentry>\n\n      <varlistentry id=\"stats.arenas.i.lruns.j.curruns\">\n        <term>\n          <mallctl>stats.arenas.&lt;i&gt;.lruns.&lt;j&gt;.curruns</mallctl>\n          (<type>size_t</type>)\n          <literal>r-</literal>\n          [<option>--enable-stats</option>]\n        </term>\n        <listitem><para>Current number of runs for this size class.\n        </para></listitem>\n      </varlistentry>\n    </variablelist>\n  </refsect1>\n  <refsect1 id=\"debugging_malloc_problems\">\n    <title>DEBUGGING MALLOC PROBLEMS</title>\n    <para>When debugging, it is a good idea to configure/build jemalloc with\n    the <option>--enable-debug</option> and <option>--enable-fill</option>\n    options, and recompile the program with suitable options and symbols for\n    debugger support.  When so configured, jemalloc incorporates a wide variety\n    of run-time assertions that catch application errors such as double-free,\n    write-after-free, etc.</para>\n\n    <para>Programs often accidentally depend on &ldquo;uninitialized&rdquo;\n    memory actually being filled with zero bytes.  Junk filling\n    (see the <link linkend=\"opt.junk\"><mallctl>opt.junk</mallctl></link>\n    option) tends to expose such bugs in the form of obviously incorrect\n    results and/or coredumps.  Conversely, zero\n    filling (see the <link\n    linkend=\"opt.zero\"><mallctl>opt.zero</mallctl></link> option) eliminates\n    the symptoms of such bugs.  Between these two options, it is usually\n    possible to quickly detect, diagnose, and eliminate such bugs.</para>\n\n    <para>This implementation does not provide much detail about the problems\n    it detects, because the performance impact for storing such information\n    would be prohibitive.  However, jemalloc does integrate with the most\n    excellent <ulink url=\"http://valgrind.org/\">Valgrind</ulink> tool if the\n    <option>--enable-valgrind</option> configuration option is enabled.</para>\n  </refsect1>\n  <refsect1 id=\"diagnostic_messages\">\n    <title>DIAGNOSTIC MESSAGES</title>\n    <para>If any of the memory allocation/deallocation functions detect an\n    error or warning condition, a message will be printed to file descriptor\n    <constant>STDERR_FILENO</constant>.  Errors will result in the process\n    dumping core.  If the <link\n    linkend=\"opt.abort\"><mallctl>opt.abort</mallctl></link> option is set, most\n    warnings are treated as errors.</para>\n\n    <para>The <varname>malloc_message</varname> variable allows the programmer\n    to override the function which emits the text strings forming the errors\n    and warnings if for some reason the <constant>STDERR_FILENO</constant> file\n    descriptor is not suitable for this.\n    <function>malloc_message<parameter/></function> takes the\n    <parameter>cbopaque</parameter> pointer argument that is\n    <constant>NULL</constant> unless overridden by the arguments in a call to\n    <function>malloc_stats_print<parameter/></function>, followed by a string\n    pointer.  Please note that doing anything which tries to allocate memory in\n    this function is likely to result in a crash or deadlock.</para>\n\n    <para>All messages are prefixed by\n    &ldquo;<computeroutput>&lt;jemalloc&gt;: </computeroutput>&rdquo;.</para>\n  </refsect1>\n  <refsect1 id=\"return_values\">\n    <title>RETURN VALUES</title>\n    <refsect2>\n      <title>Standard API</title>\n      <para>The <function>malloc<parameter/></function> and\n      <function>calloc<parameter/></function> functions return a pointer to the\n      allocated memory if successful; otherwise a <constant>NULL</constant>\n      pointer is returned and <varname>errno</varname> is set to\n      <errorname>ENOMEM</errorname>.</para>\n\n      <para>The <function>posix_memalign<parameter/></function> function\n      returns the value 0 if successful; otherwise it returns an error value.\n      The <function>posix_memalign<parameter/></function> function will fail\n      if:\n        <variablelist>\n          <varlistentry>\n            <term><errorname>EINVAL</errorname></term>\n\n            <listitem><para>The <parameter>alignment</parameter> parameter is\n            not a power of 2 at least as large as\n            <code language=\"C\">sizeof(<type>void *</type>)</code>.\n            </para></listitem>\n          </varlistentry>\n          <varlistentry>\n            <term><errorname>ENOMEM</errorname></term>\n\n            <listitem><para>Memory allocation error.</para></listitem>\n          </varlistentry>\n        </variablelist>\n      </para>\n\n      <para>The <function>aligned_alloc<parameter/></function> function returns\n      a pointer to the allocated memory if successful; otherwise a\n      <constant>NULL</constant> pointer is returned and\n      <varname>errno</varname> is set.  The\n      <function>aligned_alloc<parameter/></function> function will fail if:\n        <variablelist>\n          <varlistentry>\n            <term><errorname>EINVAL</errorname></term>\n\n            <listitem><para>The <parameter>alignment</parameter> parameter is\n            not a power of 2.\n            </para></listitem>\n          </varlistentry>\n          <varlistentry>\n            <term><errorname>ENOMEM</errorname></term>\n\n            <listitem><para>Memory allocation error.</para></listitem>\n          </varlistentry>\n        </variablelist>\n      </para>\n\n      <para>The <function>realloc<parameter/></function> function returns a\n      pointer, possibly identical to <parameter>ptr</parameter>, to the\n      allocated memory if successful; otherwise a <constant>NULL</constant>\n      pointer is returned, and <varname>errno</varname> is set to\n      <errorname>ENOMEM</errorname> if the error was the result of an\n      allocation failure.  The <function>realloc<parameter/></function>\n      function always leaves the original buffer intact when an error occurs.\n      </para>\n\n      <para>The <function>free<parameter/></function> function returns no\n      value.</para>\n    </refsect2>\n    <refsect2>\n      <title>Non-standard API</title>\n      <para>The <function>mallocx<parameter/></function> and\n      <function>rallocx<parameter/></function> functions return a pointer to\n      the allocated memory if successful; otherwise a <constant>NULL</constant>\n      pointer is returned to indicate insufficient contiguous memory was\n      available to service the allocation request.  </para>\n\n      <para>The <function>xallocx<parameter/></function> function returns the\n      real size of the resulting resized allocation pointed to by\n      <parameter>ptr</parameter>, which is a value less than\n      <parameter>size</parameter> if the allocation could not be adequately\n      grown in place.  </para>\n\n      <para>The <function>sallocx<parameter/></function> function returns the\n      real size of the allocation pointed to by <parameter>ptr</parameter>.\n      </para>\n\n      <para>The <function>nallocx<parameter/></function> returns the real size\n      that would result from a successful equivalent\n      <function>mallocx<parameter/></function> function call, or zero if\n      insufficient memory is available to perform the size computation.  </para>\n\n      <para>The <function>mallctl<parameter/></function>,\n      <function>mallctlnametomib<parameter/></function>, and\n      <function>mallctlbymib<parameter/></function> functions return 0 on\n      success; otherwise they return an error value.  The functions will fail\n      if:\n        <variablelist>\n          <varlistentry>\n            <term><errorname>EINVAL</errorname></term>\n\n            <listitem><para><parameter>newp</parameter> is not\n            <constant>NULL</constant>, and <parameter>newlen</parameter> is too\n            large or too small.  Alternatively, <parameter>*oldlenp</parameter>\n            is too large or too small; in this case as much data as possible\n            are read despite the error.</para></listitem>\n          </varlistentry>\n          <varlistentry>\n            <term><errorname>ENOENT</errorname></term>\n\n            <listitem><para><parameter>name</parameter> or\n            <parameter>mib</parameter> specifies an unknown/invalid\n            value.</para></listitem>\n          </varlistentry>\n          <varlistentry>\n            <term><errorname>EPERM</errorname></term>\n\n            <listitem><para>Attempt to read or write void value, or attempt to\n            write read-only value.</para></listitem>\n          </varlistentry>\n          <varlistentry>\n            <term><errorname>EAGAIN</errorname></term>\n\n            <listitem><para>A memory allocation failure\n            occurred.</para></listitem>\n          </varlistentry>\n          <varlistentry>\n            <term><errorname>EFAULT</errorname></term>\n\n            <listitem><para>An interface with side effects failed in some way\n            not directly related to <function>mallctl*<parameter/></function>\n            read/write processing.</para></listitem>\n          </varlistentry>\n        </variablelist>\n      </para>\n\n      <para>The <function>malloc_usable_size<parameter/></function> function\n      returns the usable size of the allocation pointed to by\n      <parameter>ptr</parameter>.  </para>\n    </refsect2>\n    <refsect2>\n      <title>Experimental API</title>\n      <para>The <function>allocm<parameter/></function>,\n      <function>rallocm<parameter/></function>,\n      <function>sallocm<parameter/></function>,\n      <function>dallocm<parameter/></function>, and\n      <function>nallocm<parameter/></function> functions return\n      <constant>ALLOCM_SUCCESS</constant> on success; otherwise they return an\n      error value.  The <function>allocm<parameter/></function>,\n      <function>rallocm<parameter/></function>, and\n      <function>nallocm<parameter/></function> functions will fail if:\n        <variablelist>\n          <varlistentry>\n            <term><errorname>ALLOCM_ERR_OOM</errorname></term>\n\n            <listitem><para>Out of memory.  Insufficient contiguous memory was\n            available to service the allocation request.  The\n            <function>allocm<parameter/></function> function additionally sets\n            <parameter>*ptr</parameter> to <constant>NULL</constant>, whereas\n            the <function>rallocm<parameter/></function> function leaves\n            <constant>*ptr</constant> unmodified.</para></listitem>\n          </varlistentry>\n        </variablelist>\n      The <function>rallocm<parameter/></function> function will also\n      fail if:\n        <variablelist>\n          <varlistentry>\n            <term><errorname>ALLOCM_ERR_NOT_MOVED</errorname></term>\n\n            <listitem><para><constant>ALLOCM_NO_MOVE</constant> was specified,\n            but the reallocation request could not be serviced without moving\n            the object.</para></listitem>\n          </varlistentry>\n        </variablelist>\n      </para>\n    </refsect2>\n  </refsect1>\n  <refsect1 id=\"environment\">\n    <title>ENVIRONMENT</title>\n    <para>The following environment variable affects the execution of the\n    allocation functions:\n      <variablelist>\n        <varlistentry>\n          <term><envar>MALLOC_CONF</envar></term>\n\n          <listitem><para>If the environment variable\n          <envar>MALLOC_CONF</envar> is set, the characters it contains\n          will be interpreted as options.</para></listitem>\n        </varlistentry>\n      </variablelist>\n    </para>\n  </refsect1>\n  <refsect1 id=\"examples\">\n    <title>EXAMPLES</title>\n    <para>To dump core whenever a problem occurs:\n      <screen>ln -s 'abort:true' /etc/malloc.conf</screen>\n    </para>\n    <para>To specify in the source a chunk size that is 16 MiB:\n      <programlisting language=\"C\"><![CDATA[\nmalloc_conf = \"lg_chunk:24\";]]></programlisting></para>\n  </refsect1>\n  <refsect1 id=\"see_also\">\n    <title>SEE ALSO</title>\n    <para><citerefentry><refentrytitle>madvise</refentrytitle>\n    <manvolnum>2</manvolnum></citerefentry>,\n    <citerefentry><refentrytitle>mmap</refentrytitle>\n    <manvolnum>2</manvolnum></citerefentry>,\n    <citerefentry><refentrytitle>sbrk</refentrytitle>\n    <manvolnum>2</manvolnum></citerefentry>,\n    <citerefentry><refentrytitle>utrace</refentrytitle>\n    <manvolnum>2</manvolnum></citerefentry>,\n    <citerefentry><refentrytitle>alloca</refentrytitle>\n    <manvolnum>3</manvolnum></citerefentry>,\n    <citerefentry><refentrytitle>atexit</refentrytitle>\n    <manvolnum>3</manvolnum></citerefentry>,\n    <citerefentry><refentrytitle>getpagesize</refentrytitle>\n    <manvolnum>3</manvolnum></citerefentry></para>\n  </refsect1>\n  <refsect1 id=\"standards\">\n    <title>STANDARDS</title>\n    <para>The <function>malloc<parameter/></function>,\n    <function>calloc<parameter/></function>,\n    <function>realloc<parameter/></function>, and\n    <function>free<parameter/></function> functions conform to ISO/IEC\n    9899:1990 (&ldquo;ISO C90&rdquo;).</para>\n\n    <para>The <function>posix_memalign<parameter/></function> function conforms\n    to IEEE Std 1003.1-2001 (&ldquo;POSIX.1&rdquo;).</para>\n  </refsect1>\n</refentry>\n"
  },
  {
    "path": "extern/deprecated/redis-2.8.21/deps/jemalloc/doc/manpages.xsl.in",
    "content": "<xsl:stylesheet xmlns:xsl=\"http://www.w3.org/1999/XSL/Transform\" version=\"1.0\">\n  <xsl:import href=\"@XSLROOT@/manpages/docbook.xsl\"/>\n  <xsl:import href=\"@abs_srcroot@doc/stylesheet.xsl\"/>\n</xsl:stylesheet>\n"
  },
  {
    "path": "extern/deprecated/redis-2.8.21/deps/jemalloc/doc/stylesheet.xsl",
    "content": "<xsl:stylesheet xmlns:xsl=\"http://www.w3.org/1999/XSL/Transform\" version=\"1.0\">\n  <xsl:param name=\"funcsynopsis.style\">ansi</xsl:param>\n  <xsl:param name=\"function.parens\" select=\"1\"/>\n  <xsl:template match=\"mallctl\">\n    \"<xsl:call-template name=\"inline.monoseq\"/>\"\n  </xsl:template>\n</xsl:stylesheet>\n"
  },
  {
    "path": "extern/deprecated/redis-2.8.21/deps/jemalloc/include/jemalloc/internal/arena.h",
    "content": "/******************************************************************************/\n#ifdef JEMALLOC_H_TYPES\n\n/*\n * RUN_MAX_OVRHD indicates maximum desired run header overhead.  Runs are sized\n * as small as possible such that this setting is still honored, without\n * violating other constraints.  The goal is to make runs as small as possible\n * without exceeding a per run external fragmentation threshold.\n *\n * We use binary fixed point math for overhead computations, where the binary\n * point is implicitly RUN_BFP bits to the left.\n *\n * Note that it is possible to set RUN_MAX_OVRHD low enough that it cannot be\n * honored for some/all object sizes, since when heap profiling is enabled\n * there is one pointer of header overhead per object (plus a constant).  This\n * constraint is relaxed (ignored) for runs that are so small that the\n * per-region overhead is greater than:\n *\n *   (RUN_MAX_OVRHD / (reg_interval << (3+RUN_BFP))\n */\n#define\tRUN_BFP\t\t\t12\n/*                                    \\/   Implicit binary fixed point. */\n#define\tRUN_MAX_OVRHD\t\t0x0000003dU\n#define\tRUN_MAX_OVRHD_RELAX\t0x00001800U\n\n/* Maximum number of regions in one run. */\n#define\tLG_RUN_MAXREGS\t\t11\n#define\tRUN_MAXREGS\t\t(1U << LG_RUN_MAXREGS)\n\n/*\n * Minimum redzone size.  Redzones may be larger than this if necessary to\n * preserve region alignment.\n */\n#define\tREDZONE_MINSIZE\t\t16\n\n/*\n * The minimum ratio of active:dirty pages per arena is computed as:\n *\n *   (nactive >> opt_lg_dirty_mult) >= ndirty\n *\n * So, supposing that opt_lg_dirty_mult is 3, there can be no less than 8 times\n * as many active pages as dirty pages.\n */\n#define\tLG_DIRTY_MULT_DEFAULT\t3\n\ntypedef struct arena_chunk_map_s arena_chunk_map_t;\ntypedef struct arena_chunk_s arena_chunk_t;\ntypedef struct arena_run_s arena_run_t;\ntypedef struct arena_bin_info_s arena_bin_info_t;\ntypedef struct arena_bin_s arena_bin_t;\ntypedef struct arena_s arena_t;\n\n#endif /* JEMALLOC_H_TYPES */\n/******************************************************************************/\n#ifdef JEMALLOC_H_STRUCTS\n\n/* Each element of the chunk map corresponds to one page within the chunk. */\nstruct arena_chunk_map_s {\n#ifndef JEMALLOC_PROF\n\t/*\n\t * Overlay prof_ctx in order to allow it to be referenced by dead code.\n\t * Such antics aren't warranted for per arena data structures, but\n\t * chunk map overhead accounts for a percentage of memory, rather than\n\t * being just a fixed cost.\n\t */\n\tunion {\n#endif\n\tunion {\n\t\t/*\n\t\t * Linkage for run trees.  There are two disjoint uses:\n\t\t *\n\t\t * 1) arena_t's runs_avail tree.\n\t\t * 2) arena_run_t conceptually uses this linkage for in-use\n\t\t *    non-full runs, rather than directly embedding linkage.\n\t\t */\n\t\trb_node(arena_chunk_map_t)\trb_link;\n\t\t/*\n\t\t * List of runs currently in purgatory.  arena_chunk_purge()\n\t\t * temporarily allocates runs that contain dirty pages while\n\t\t * purging, so that other threads cannot use the runs while the\n\t\t * purging thread is operating without the arena lock held.\n\t\t */\n\t\tql_elm(arena_chunk_map_t)\tql_link;\n\t}\t\t\t\tu;\n\n\t/* Profile counters, used for large object runs. */\n\tprof_ctx_t\t\t\t*prof_ctx;\n#ifndef JEMALLOC_PROF\n\t}; /* union { ... }; */\n#endif\n\n\t/*\n\t * Run address (or size) and various flags are stored together.  The bit\n\t * layout looks like (assuming 32-bit system):\n\t *\n\t *   ???????? ???????? ????nnnn nnnndula\n\t *\n\t * ? : Unallocated: Run address for first/last pages, unset for internal\n\t *                  pages.\n\t *     Small: Run page offset.\n\t *     Large: Run size for first page, unset for trailing pages.\n\t * n : binind for small size class, BININD_INVALID for large size class.\n\t * d : dirty?\n\t * u : unzeroed?\n\t * l : large?\n\t * a : allocated?\n\t *\n\t * Following are example bit patterns for the three types of runs.\n\t *\n\t * p : run page offset\n\t * s : run size\n\t * n : binind for size class; large objects set these to BININD_INVALID\n\t *     except for promoted allocations (see prof_promote)\n\t * x : don't care\n\t * - : 0\n\t * + : 1\n\t * [DULA] : bit set\n\t * [dula] : bit unset\n\t *\n\t *   Unallocated (clean):\n\t *     ssssssss ssssssss ssss++++ ++++du-a\n\t *     xxxxxxxx xxxxxxxx xxxxxxxx xxxx-Uxx\n\t *     ssssssss ssssssss ssss++++ ++++dU-a\n\t *\n\t *   Unallocated (dirty):\n\t *     ssssssss ssssssss ssss++++ ++++D--a\n\t *     xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx\n\t *     ssssssss ssssssss ssss++++ ++++D--a\n\t *\n\t *   Small:\n\t *     pppppppp pppppppp ppppnnnn nnnnd--A\n\t *     pppppppp pppppppp ppppnnnn nnnn---A\n\t *     pppppppp pppppppp ppppnnnn nnnnd--A\n\t *\n\t *   Large:\n\t *     ssssssss ssssssss ssss++++ ++++D-LA\n\t *     xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx\n\t *     -------- -------- ----++++ ++++D-LA\n\t *\n\t *   Large (sampled, size <= PAGE):\n\t *     ssssssss ssssssss ssssnnnn nnnnD-LA\n\t *\n\t *   Large (not sampled, size == PAGE):\n\t *     ssssssss ssssssss ssss++++ ++++D-LA\n\t */\n\tsize_t\t\t\t\tbits;\n#define\tCHUNK_MAP_BININD_SHIFT\t4\n#define\tBININD_INVALID\t\t((size_t)0xffU)\n/*     CHUNK_MAP_BININD_MASK == (BININD_INVALID << CHUNK_MAP_BININD_SHIFT) */\n#define\tCHUNK_MAP_BININD_MASK\t((size_t)0xff0U)\n#define\tCHUNK_MAP_BININD_INVALID CHUNK_MAP_BININD_MASK\n#define\tCHUNK_MAP_FLAGS_MASK\t((size_t)0xcU)\n#define\tCHUNK_MAP_DIRTY\t\t((size_t)0x8U)\n#define\tCHUNK_MAP_UNZEROED\t((size_t)0x4U)\n#define\tCHUNK_MAP_LARGE\t\t((size_t)0x2U)\n#define\tCHUNK_MAP_ALLOCATED\t((size_t)0x1U)\n#define\tCHUNK_MAP_KEY\t\tCHUNK_MAP_ALLOCATED\n};\ntypedef rb_tree(arena_chunk_map_t) arena_avail_tree_t;\ntypedef rb_tree(arena_chunk_map_t) arena_run_tree_t;\ntypedef ql_head(arena_chunk_map_t) arena_chunk_mapelms_t;\n\n/* Arena chunk header. */\nstruct arena_chunk_s {\n\t/* Arena that owns the chunk. */\n\tarena_t\t\t\t*arena;\n\n\t/* Linkage for tree of arena chunks that contain dirty runs. */\n\trb_node(arena_chunk_t)\tdirty_link;\n\n\t/* Number of dirty pages. */\n\tsize_t\t\t\tndirty;\n\n\t/* Number of available runs. */\n\tsize_t\t\t\tnruns_avail;\n\n\t/*\n\t * Number of available run adjacencies that purging could coalesce.\n\t * Clean and dirty available runs are not coalesced, which causes\n\t * virtual memory fragmentation.  The ratio of\n\t * (nruns_avail-nruns_adjac):nruns_adjac is used for tracking this\n\t * fragmentation.\n\t */\n\tsize_t\t\t\tnruns_adjac;\n\n\t/*\n\t * Map of pages within chunk that keeps track of free/large/small.  The\n\t * first map_bias entries are omitted, since the chunk header does not\n\t * need to be tracked in the map.  This omission saves a header page\n\t * for common chunk sizes (e.g. 4 MiB).\n\t */\n\tarena_chunk_map_t\tmap[1]; /* Dynamically sized. */\n};\ntypedef rb_tree(arena_chunk_t) arena_chunk_tree_t;\n\nstruct arena_run_s {\n\t/* Bin this run is associated with. */\n\tarena_bin_t\t*bin;\n\n\t/* Index of next region that has never been allocated, or nregs. */\n\tuint32_t\tnextind;\n\n\t/* Number of free regions in run. */\n\tunsigned\tnfree;\n};\n\n/*\n * Read-only information associated with each element of arena_t's bins array\n * is stored separately, partly to reduce memory usage (only one copy, rather\n * than one per arena), but mainly to avoid false cacheline sharing.\n *\n * Each run has the following layout:\n *\n *               /--------------------\\\n *               | arena_run_t header |\n *               | ...                |\n * bitmap_offset | bitmap             |\n *               | ...                |\n *   ctx0_offset | ctx map            |\n *               | ...                |\n *               |--------------------|\n *               | redzone            |\n *   reg0_offset | region 0           |\n *               | redzone            |\n *               |--------------------| \\\n *               | redzone            | |\n *               | region 1           |  > reg_interval\n *               | redzone            | /\n *               |--------------------|\n *               | ...                |\n *               | ...                |\n *               | ...                |\n *               |--------------------|\n *               | redzone            |\n *               | region nregs-1     |\n *               | redzone            |\n *               |--------------------|\n *               | alignment pad?     |\n *               \\--------------------/\n *\n * reg_interval has at least the same minimum alignment as reg_size; this\n * preserves the alignment constraint that sa2u() depends on.  Alignment pad is\n * either 0 or redzone_size; it is present only if needed to align reg0_offset.\n */\nstruct arena_bin_info_s {\n\t/* Size of regions in a run for this bin's size class. */\n\tsize_t\t\treg_size;\n\n\t/* Redzone size. */\n\tsize_t\t\tredzone_size;\n\n\t/* Interval between regions (reg_size + (redzone_size << 1)). */\n\tsize_t\t\treg_interval;\n\n\t/* Total size of a run for this bin's size class. */\n\tsize_t\t\trun_size;\n\n\t/* Total number of regions in a run for this bin's size class. */\n\tuint32_t\tnregs;\n\n\t/*\n\t * Offset of first bitmap_t element in a run header for this bin's size\n\t * class.\n\t */\n\tuint32_t\tbitmap_offset;\n\n\t/*\n\t * Metadata used to manipulate bitmaps for runs associated with this\n\t * bin.\n\t */\n\tbitmap_info_t\tbitmap_info;\n\n\t/*\n\t * Offset of first (prof_ctx_t *) in a run header for this bin's size\n\t * class, or 0 if (config_prof == false || opt_prof == false).\n\t */\n\tuint32_t\tctx0_offset;\n\n\t/* Offset of first region in a run for this bin's size class. */\n\tuint32_t\treg0_offset;\n};\n\nstruct arena_bin_s {\n\t/*\n\t * All operations on runcur, runs, and stats require that lock be\n\t * locked.  Run allocation/deallocation are protected by the arena lock,\n\t * which may be acquired while holding one or more bin locks, but not\n\t * vise versa.\n\t */\n\tmalloc_mutex_t\tlock;\n\n\t/*\n\t * Current run being used to service allocations of this bin's size\n\t * class.\n\t */\n\tarena_run_t\t*runcur;\n\n\t/*\n\t * Tree of non-full runs.  This tree is used when looking for an\n\t * existing run when runcur is no longer usable.  We choose the\n\t * non-full run that is lowest in memory; this policy tends to keep\n\t * objects packed well, and it can also help reduce the number of\n\t * almost-empty chunks.\n\t */\n\tarena_run_tree_t runs;\n\n\t/* Bin statistics. */\n\tmalloc_bin_stats_t stats;\n};\n\nstruct arena_s {\n\t/* This arena's index within the arenas array. */\n\tunsigned\t\tind;\n\n\t/*\n\t * Number of threads currently assigned to this arena.  This field is\n\t * protected by arenas_lock.\n\t */\n\tunsigned\t\tnthreads;\n\n\t/*\n\t * There are three classes of arena operations from a locking\n\t * perspective:\n\t * 1) Thread asssignment (modifies nthreads) is protected by\n\t *    arenas_lock.\n\t * 2) Bin-related operations are protected by bin locks.\n\t * 3) Chunk- and run-related operations are protected by this mutex.\n\t */\n\tmalloc_mutex_t\t\tlock;\n\n\tarena_stats_t\t\tstats;\n\t/*\n\t * List of tcaches for extant threads associated with this arena.\n\t * Stats from these are merged incrementally, and at exit.\n\t */\n\tql_head(tcache_t)\ttcache_ql;\n\n\tuint64_t\t\tprof_accumbytes;\n\n\tdss_prec_t\t\tdss_prec;\n\n\t/* Tree of dirty-page-containing chunks this arena manages. */\n\tarena_chunk_tree_t\tchunks_dirty;\n\n\t/*\n\t * In order to avoid rapid chunk allocation/deallocation when an arena\n\t * oscillates right on the cusp of needing a new chunk, cache the most\n\t * recently freed chunk.  The spare is left in the arena's chunk trees\n\t * until it is deleted.\n\t *\n\t * There is one spare chunk per arena, rather than one spare total, in\n\t * order to avoid interactions between multiple threads that could make\n\t * a single spare inadequate.\n\t */\n\tarena_chunk_t\t\t*spare;\n\n\t/* Number of pages in active runs. */\n\tsize_t\t\t\tnactive;\n\n\t/*\n\t * Current count of pages within unused runs that are potentially\n\t * dirty, and for which madvise(... MADV_DONTNEED) has not been called.\n\t * By tracking this, we can institute a limit on how much dirty unused\n\t * memory is mapped for each arena.\n\t */\n\tsize_t\t\t\tndirty;\n\n\t/*\n\t * Approximate number of pages being purged.  It is possible for\n\t * multiple threads to purge dirty pages concurrently, and they use\n\t * npurgatory to indicate the total number of pages all threads are\n\t * attempting to purge.\n\t */\n\tsize_t\t\t\tnpurgatory;\n\n\t/*\n\t * Size/address-ordered trees of this arena's available runs.  The trees\n\t * are used for first-best-fit run allocation.\n\t */\n\tarena_avail_tree_t\truns_avail;\n\n\t/* bins is used to store trees of free regions. */\n\tarena_bin_t\t\tbins[NBINS];\n};\n\n#endif /* JEMALLOC_H_STRUCTS */\n/******************************************************************************/\n#ifdef JEMALLOC_H_EXTERNS\n\nextern ssize_t\topt_lg_dirty_mult;\n/*\n * small_size2bin is a compact lookup table that rounds request sizes up to\n * size classes.  In order to reduce cache footprint, the table is compressed,\n * and all accesses are via the SMALL_SIZE2BIN macro.\n */\nextern uint8_t const\tsmall_size2bin[];\n#define\tSMALL_SIZE2BIN(s)\t(small_size2bin[(s-1) >> LG_TINY_MIN])\n\nextern arena_bin_info_t\tarena_bin_info[NBINS];\n\n/* Number of large size classes. */\n#define\t\t\tnlclasses (chunk_npages - map_bias)\n\nvoid\tarena_purge_all(arena_t *arena);\nvoid\tarena_tcache_fill_small(arena_t *arena, tcache_bin_t *tbin,\n    size_t binind, uint64_t prof_accumbytes);\nvoid\tarena_alloc_junk_small(void *ptr, arena_bin_info_t *bin_info,\n    bool zero);\n#ifdef JEMALLOC_JET\ntypedef void (arena_redzone_corruption_t)(void *, size_t, bool, size_t,\n    uint8_t);\nextern arena_redzone_corruption_t *arena_redzone_corruption;\ntypedef void (arena_dalloc_junk_small_t)(void *, arena_bin_info_t *);\nextern arena_dalloc_junk_small_t *arena_dalloc_junk_small;\n#else\nvoid\tarena_dalloc_junk_small(void *ptr, arena_bin_info_t *bin_info);\n#endif\nvoid\tarena_quarantine_junk_small(void *ptr, size_t usize);\nvoid\t*arena_malloc_small(arena_t *arena, size_t size, bool zero);\nvoid\t*arena_malloc_large(arena_t *arena, size_t size, bool zero);\nvoid\t*arena_palloc(arena_t *arena, size_t size, size_t alignment, bool zero);\nvoid\tarena_prof_promoted(const void *ptr, size_t size);\nvoid\tarena_dalloc_bin_locked(arena_t *arena, arena_chunk_t *chunk, void *ptr,\n    arena_chunk_map_t *mapelm);\nvoid\tarena_dalloc_bin(arena_t *arena, arena_chunk_t *chunk, void *ptr,\n    size_t pageind, arena_chunk_map_t *mapelm);\nvoid\tarena_dalloc_small(arena_t *arena, arena_chunk_t *chunk, void *ptr,\n    size_t pageind);\n#ifdef JEMALLOC_JET\ntypedef void (arena_dalloc_junk_large_t)(void *, size_t);\nextern arena_dalloc_junk_large_t *arena_dalloc_junk_large;\n#endif\nvoid\tarena_dalloc_large_locked(arena_t *arena, arena_chunk_t *chunk,\n    void *ptr);\nvoid\tarena_dalloc_large(arena_t *arena, arena_chunk_t *chunk, void *ptr);\n#ifdef JEMALLOC_JET\ntypedef void (arena_ralloc_junk_large_t)(void *, size_t, size_t);\nextern arena_ralloc_junk_large_t *arena_ralloc_junk_large;\n#endif\nbool\tarena_ralloc_no_move(void *ptr, size_t oldsize, size_t size,\n    size_t extra, bool zero);\nvoid\t*arena_ralloc(arena_t *arena, void *ptr, size_t oldsize, size_t size,\n    size_t extra, size_t alignment, bool zero, bool try_tcache_alloc,\n    bool try_tcache_dalloc);\ndss_prec_t\tarena_dss_prec_get(arena_t *arena);\nvoid\tarena_dss_prec_set(arena_t *arena, dss_prec_t dss_prec);\nvoid\tarena_stats_merge(arena_t *arena, const char **dss, size_t *nactive,\n    size_t *ndirty, arena_stats_t *astats, malloc_bin_stats_t *bstats,\n    malloc_large_stats_t *lstats);\nbool\tarena_new(arena_t *arena, unsigned ind);\nvoid\tarena_boot(void);\nvoid\tarena_prefork(arena_t *arena);\nvoid\tarena_postfork_parent(arena_t *arena);\nvoid\tarena_postfork_child(arena_t *arena);\n\n#endif /* JEMALLOC_H_EXTERNS */\n/******************************************************************************/\n#ifdef JEMALLOC_H_INLINES\n\n#ifndef JEMALLOC_ENABLE_INLINE\narena_chunk_map_t\t*arena_mapp_get(arena_chunk_t *chunk, size_t pageind);\nsize_t\t*arena_mapbitsp_get(arena_chunk_t *chunk, size_t pageind);\nsize_t\tarena_mapbitsp_read(size_t *mapbitsp);\nsize_t\tarena_mapbits_get(arena_chunk_t *chunk, size_t pageind);\nsize_t\tarena_mapbits_unallocated_size_get(arena_chunk_t *chunk,\n    size_t pageind);\nsize_t\tarena_mapbits_large_size_get(arena_chunk_t *chunk, size_t pageind);\nsize_t\tarena_mapbits_small_runind_get(arena_chunk_t *chunk, size_t pageind);\nsize_t\tarena_mapbits_binind_get(arena_chunk_t *chunk, size_t pageind);\nsize_t\tarena_mapbits_dirty_get(arena_chunk_t *chunk, size_t pageind);\nsize_t\tarena_mapbits_unzeroed_get(arena_chunk_t *chunk, size_t pageind);\nsize_t\tarena_mapbits_large_get(arena_chunk_t *chunk, size_t pageind);\nsize_t\tarena_mapbits_allocated_get(arena_chunk_t *chunk, size_t pageind);\nvoid\tarena_mapbitsp_write(size_t *mapbitsp, size_t mapbits);\nvoid\tarena_mapbits_unallocated_set(arena_chunk_t *chunk, size_t pageind,\n    size_t size, size_t flags);\nvoid\tarena_mapbits_unallocated_size_set(arena_chunk_t *chunk, size_t pageind,\n    size_t size);\nvoid\tarena_mapbits_large_set(arena_chunk_t *chunk, size_t pageind,\n    size_t size, size_t flags);\nvoid\tarena_mapbits_large_binind_set(arena_chunk_t *chunk, size_t pageind,\n    size_t binind);\nvoid\tarena_mapbits_small_set(arena_chunk_t *chunk, size_t pageind,\n    size_t runind, size_t binind, size_t flags);\nvoid\tarena_mapbits_unzeroed_set(arena_chunk_t *chunk, size_t pageind,\n    size_t unzeroed);\nbool\tarena_prof_accum_impl(arena_t *arena, uint64_t accumbytes);\nbool\tarena_prof_accum_locked(arena_t *arena, uint64_t accumbytes);\nbool\tarena_prof_accum(arena_t *arena, uint64_t accumbytes);\nsize_t\tarena_ptr_small_binind_get(const void *ptr, size_t mapbits);\nsize_t\tarena_bin_index(arena_t *arena, arena_bin_t *bin);\nunsigned\tarena_run_regind(arena_run_t *run, arena_bin_info_t *bin_info,\n    const void *ptr);\nprof_ctx_t\t*arena_prof_ctx_get(const void *ptr);\nvoid\tarena_prof_ctx_set(const void *ptr, size_t usize, prof_ctx_t *ctx);\nvoid\t*arena_malloc(arena_t *arena, size_t size, bool zero, bool try_tcache);\nsize_t\tarena_salloc(const void *ptr, bool demote);\nvoid\tarena_dalloc(arena_t *arena, arena_chunk_t *chunk, void *ptr,\n    bool try_tcache);\n#endif\n\n#if (defined(JEMALLOC_ENABLE_INLINE) || defined(JEMALLOC_ARENA_C_))\n#  ifdef JEMALLOC_ARENA_INLINE_A\nJEMALLOC_ALWAYS_INLINE arena_chunk_map_t *\narena_mapp_get(arena_chunk_t *chunk, size_t pageind)\n{\n\n\tassert(pageind >= map_bias);\n\tassert(pageind < chunk_npages);\n\n\treturn (&chunk->map[pageind-map_bias]);\n}\n\nJEMALLOC_ALWAYS_INLINE size_t *\narena_mapbitsp_get(arena_chunk_t *chunk, size_t pageind)\n{\n\n\treturn (&arena_mapp_get(chunk, pageind)->bits);\n}\n\nJEMALLOC_ALWAYS_INLINE size_t\narena_mapbitsp_read(size_t *mapbitsp)\n{\n\n\treturn (*mapbitsp);\n}\n\nJEMALLOC_ALWAYS_INLINE size_t\narena_mapbits_get(arena_chunk_t *chunk, size_t pageind)\n{\n\n\treturn (arena_mapbitsp_read(arena_mapbitsp_get(chunk, pageind)));\n}\n\nJEMALLOC_ALWAYS_INLINE size_t\narena_mapbits_unallocated_size_get(arena_chunk_t *chunk, size_t pageind)\n{\n\tsize_t mapbits;\n\n\tmapbits = arena_mapbits_get(chunk, pageind);\n\tassert((mapbits & (CHUNK_MAP_LARGE|CHUNK_MAP_ALLOCATED)) == 0);\n\treturn (mapbits & ~PAGE_MASK);\n}\n\nJEMALLOC_ALWAYS_INLINE size_t\narena_mapbits_large_size_get(arena_chunk_t *chunk, size_t pageind)\n{\n\tsize_t mapbits;\n\n\tmapbits = arena_mapbits_get(chunk, pageind);\n\tassert((mapbits & (CHUNK_MAP_LARGE|CHUNK_MAP_ALLOCATED)) ==\n\t    (CHUNK_MAP_LARGE|CHUNK_MAP_ALLOCATED));\n\treturn (mapbits & ~PAGE_MASK);\n}\n\nJEMALLOC_ALWAYS_INLINE size_t\narena_mapbits_small_runind_get(arena_chunk_t *chunk, size_t pageind)\n{\n\tsize_t mapbits;\n\n\tmapbits = arena_mapbits_get(chunk, pageind);\n\tassert((mapbits & (CHUNK_MAP_LARGE|CHUNK_MAP_ALLOCATED)) ==\n\t    CHUNK_MAP_ALLOCATED);\n\treturn (mapbits >> LG_PAGE);\n}\n\nJEMALLOC_ALWAYS_INLINE size_t\narena_mapbits_binind_get(arena_chunk_t *chunk, size_t pageind)\n{\n\tsize_t mapbits;\n\tsize_t binind;\n\n\tmapbits = arena_mapbits_get(chunk, pageind);\n\tbinind = (mapbits & CHUNK_MAP_BININD_MASK) >> CHUNK_MAP_BININD_SHIFT;\n\tassert(binind < NBINS || binind == BININD_INVALID);\n\treturn (binind);\n}\n\nJEMALLOC_ALWAYS_INLINE size_t\narena_mapbits_dirty_get(arena_chunk_t *chunk, size_t pageind)\n{\n\tsize_t mapbits;\n\n\tmapbits = arena_mapbits_get(chunk, pageind);\n\treturn (mapbits & CHUNK_MAP_DIRTY);\n}\n\nJEMALLOC_ALWAYS_INLINE size_t\narena_mapbits_unzeroed_get(arena_chunk_t *chunk, size_t pageind)\n{\n\tsize_t mapbits;\n\n\tmapbits = arena_mapbits_get(chunk, pageind);\n\treturn (mapbits & CHUNK_MAP_UNZEROED);\n}\n\nJEMALLOC_ALWAYS_INLINE size_t\narena_mapbits_large_get(arena_chunk_t *chunk, size_t pageind)\n{\n\tsize_t mapbits;\n\n\tmapbits = arena_mapbits_get(chunk, pageind);\n\treturn (mapbits & CHUNK_MAP_LARGE);\n}\n\nJEMALLOC_ALWAYS_INLINE size_t\narena_mapbits_allocated_get(arena_chunk_t *chunk, size_t pageind)\n{\n\tsize_t mapbits;\n\n\tmapbits = arena_mapbits_get(chunk, pageind);\n\treturn (mapbits & CHUNK_MAP_ALLOCATED);\n}\n\nJEMALLOC_ALWAYS_INLINE void\narena_mapbitsp_write(size_t *mapbitsp, size_t mapbits)\n{\n\n\t*mapbitsp = mapbits;\n}\n\nJEMALLOC_ALWAYS_INLINE void\narena_mapbits_unallocated_set(arena_chunk_t *chunk, size_t pageind, size_t size,\n    size_t flags)\n{\n\tsize_t *mapbitsp = arena_mapbitsp_get(chunk, pageind);\n\n\tassert((size & PAGE_MASK) == 0);\n\tassert((flags & ~CHUNK_MAP_FLAGS_MASK) == 0);\n\tassert((flags & (CHUNK_MAP_DIRTY|CHUNK_MAP_UNZEROED)) == flags);\n\tarena_mapbitsp_write(mapbitsp, size | CHUNK_MAP_BININD_INVALID | flags);\n}\n\nJEMALLOC_ALWAYS_INLINE void\narena_mapbits_unallocated_size_set(arena_chunk_t *chunk, size_t pageind,\n    size_t size)\n{\n\tsize_t *mapbitsp = arena_mapbitsp_get(chunk, pageind);\n\tsize_t mapbits = arena_mapbitsp_read(mapbitsp);\n\n\tassert((size & PAGE_MASK) == 0);\n\tassert((mapbits & (CHUNK_MAP_LARGE|CHUNK_MAP_ALLOCATED)) == 0);\n\tarena_mapbitsp_write(mapbitsp, size | (mapbits & PAGE_MASK));\n}\n\nJEMALLOC_ALWAYS_INLINE void\narena_mapbits_large_set(arena_chunk_t *chunk, size_t pageind, size_t size,\n    size_t flags)\n{\n\tsize_t *mapbitsp = arena_mapbitsp_get(chunk, pageind);\n\tsize_t mapbits = arena_mapbitsp_read(mapbitsp);\n\tsize_t unzeroed;\n\n\tassert((size & PAGE_MASK) == 0);\n\tassert((flags & CHUNK_MAP_DIRTY) == flags);\n\tunzeroed = mapbits & CHUNK_MAP_UNZEROED; /* Preserve unzeroed. */\n\tarena_mapbitsp_write(mapbitsp, size | CHUNK_MAP_BININD_INVALID | flags\n\t    | unzeroed | CHUNK_MAP_LARGE | CHUNK_MAP_ALLOCATED);\n}\n\nJEMALLOC_ALWAYS_INLINE void\narena_mapbits_large_binind_set(arena_chunk_t *chunk, size_t pageind,\n    size_t binind)\n{\n\tsize_t *mapbitsp = arena_mapbitsp_get(chunk, pageind);\n\tsize_t mapbits = arena_mapbitsp_read(mapbitsp);\n\n\tassert(binind <= BININD_INVALID);\n\tassert(arena_mapbits_large_size_get(chunk, pageind) == PAGE);\n\tarena_mapbitsp_write(mapbitsp, (mapbits & ~CHUNK_MAP_BININD_MASK) |\n\t    (binind << CHUNK_MAP_BININD_SHIFT));\n}\n\nJEMALLOC_ALWAYS_INLINE void\narena_mapbits_small_set(arena_chunk_t *chunk, size_t pageind, size_t runind,\n    size_t binind, size_t flags)\n{\n\tsize_t *mapbitsp = arena_mapbitsp_get(chunk, pageind);\n\tsize_t mapbits = arena_mapbitsp_read(mapbitsp);\n\tsize_t unzeroed;\n\n\tassert(binind < BININD_INVALID);\n\tassert(pageind - runind >= map_bias);\n\tassert((flags & CHUNK_MAP_DIRTY) == flags);\n\tunzeroed = mapbits & CHUNK_MAP_UNZEROED; /* Preserve unzeroed. */\n\tarena_mapbitsp_write(mapbitsp, (runind << LG_PAGE) | (binind <<\n\t    CHUNK_MAP_BININD_SHIFT) | flags | unzeroed | CHUNK_MAP_ALLOCATED);\n}\n\nJEMALLOC_ALWAYS_INLINE void\narena_mapbits_unzeroed_set(arena_chunk_t *chunk, size_t pageind,\n    size_t unzeroed)\n{\n\tsize_t *mapbitsp = arena_mapbitsp_get(chunk, pageind);\n\tsize_t mapbits = arena_mapbitsp_read(mapbitsp);\n\n\tarena_mapbitsp_write(mapbitsp, (mapbits & ~CHUNK_MAP_UNZEROED) |\n\t    unzeroed);\n}\n\nJEMALLOC_INLINE bool\narena_prof_accum_impl(arena_t *arena, uint64_t accumbytes)\n{\n\n\tcassert(config_prof);\n\tassert(prof_interval != 0);\n\n\tarena->prof_accumbytes += accumbytes;\n\tif (arena->prof_accumbytes >= prof_interval) {\n\t\tarena->prof_accumbytes -= prof_interval;\n\t\treturn (true);\n\t}\n\treturn (false);\n}\n\nJEMALLOC_INLINE bool\narena_prof_accum_locked(arena_t *arena, uint64_t accumbytes)\n{\n\n\tcassert(config_prof);\n\n\tif (prof_interval == 0)\n\t\treturn (false);\n\treturn (arena_prof_accum_impl(arena, accumbytes));\n}\n\nJEMALLOC_INLINE bool\narena_prof_accum(arena_t *arena, uint64_t accumbytes)\n{\n\n\tcassert(config_prof);\n\n\tif (prof_interval == 0)\n\t\treturn (false);\n\n\t{\n\t\tbool ret;\n\n\t\tmalloc_mutex_lock(&arena->lock);\n\t\tret = arena_prof_accum_impl(arena, accumbytes);\n\t\tmalloc_mutex_unlock(&arena->lock);\n\t\treturn (ret);\n\t}\n}\n\nJEMALLOC_ALWAYS_INLINE size_t\narena_ptr_small_binind_get(const void *ptr, size_t mapbits)\n{\n\tsize_t binind;\n\n\tbinind = (mapbits & CHUNK_MAP_BININD_MASK) >> CHUNK_MAP_BININD_SHIFT;\n\n\tif (config_debug) {\n\t\tarena_chunk_t *chunk;\n\t\tarena_t *arena;\n\t\tsize_t pageind;\n\t\tsize_t actual_mapbits;\n\t\tarena_run_t *run;\n\t\tarena_bin_t *bin;\n\t\tsize_t actual_binind;\n\t\tarena_bin_info_t *bin_info;\n\n\t\tassert(binind != BININD_INVALID);\n\t\tassert(binind < NBINS);\n\t\tchunk = (arena_chunk_t *)CHUNK_ADDR2BASE(ptr);\n\t\tarena = chunk->arena;\n\t\tpageind = ((uintptr_t)ptr - (uintptr_t)chunk) >> LG_PAGE;\n\t\tactual_mapbits = arena_mapbits_get(chunk, pageind);\n\t\tassert(mapbits == actual_mapbits);\n\t\tassert(arena_mapbits_large_get(chunk, pageind) == 0);\n\t\tassert(arena_mapbits_allocated_get(chunk, pageind) != 0);\n\t\trun = (arena_run_t *)((uintptr_t)chunk + (uintptr_t)((pageind -\n\t\t    (actual_mapbits >> LG_PAGE)) << LG_PAGE));\n\t\tbin = run->bin;\n\t\tactual_binind = bin - arena->bins;\n\t\tassert(binind == actual_binind);\n\t\tbin_info = &arena_bin_info[actual_binind];\n\t\tassert(((uintptr_t)ptr - ((uintptr_t)run +\n\t\t    (uintptr_t)bin_info->reg0_offset)) % bin_info->reg_interval\n\t\t    == 0);\n\t}\n\n\treturn (binind);\n}\n#  endif /* JEMALLOC_ARENA_INLINE_A */\n\n#  ifdef JEMALLOC_ARENA_INLINE_B\nJEMALLOC_INLINE size_t\narena_bin_index(arena_t *arena, arena_bin_t *bin)\n{\n\tsize_t binind = bin - arena->bins;\n\tassert(binind < NBINS);\n\treturn (binind);\n}\n\nJEMALLOC_INLINE unsigned\narena_run_regind(arena_run_t *run, arena_bin_info_t *bin_info, const void *ptr)\n{\n\tunsigned shift, diff, regind;\n\tsize_t interval;\n\n\t/*\n\t * Freeing a pointer lower than region zero can cause assertion\n\t * failure.\n\t */\n\tassert((uintptr_t)ptr >= (uintptr_t)run +\n\t    (uintptr_t)bin_info->reg0_offset);\n\n\t/*\n\t * Avoid doing division with a variable divisor if possible.  Using\n\t * actual division here can reduce allocator throughput by over 20%!\n\t */\n\tdiff = (unsigned)((uintptr_t)ptr - (uintptr_t)run -\n\t    bin_info->reg0_offset);\n\n\t/* Rescale (factor powers of 2 out of the numerator and denominator). */\n\tinterval = bin_info->reg_interval;\n\tshift = ffs(interval) - 1;\n\tdiff >>= shift;\n\tinterval >>= shift;\n\n\tif (interval == 1) {\n\t\t/* The divisor was a power of 2. */\n\t\tregind = diff;\n\t} else {\n\t\t/*\n\t\t * To divide by a number D that is not a power of two we\n\t\t * multiply by (2^21 / D) and then right shift by 21 positions.\n\t\t *\n\t\t *   X / D\n\t\t *\n\t\t * becomes\n\t\t *\n\t\t *   (X * interval_invs[D - 3]) >> SIZE_INV_SHIFT\n\t\t *\n\t\t * We can omit the first three elements, because we never\n\t\t * divide by 0, and 1 and 2 are both powers of two, which are\n\t\t * handled above.\n\t\t */\n#define\tSIZE_INV_SHIFT\t((sizeof(unsigned) << 3) - LG_RUN_MAXREGS)\n#define\tSIZE_INV(s)\t(((1U << SIZE_INV_SHIFT) / (s)) + 1)\n\t\tstatic const unsigned interval_invs[] = {\n\t\t    SIZE_INV(3),\n\t\t    SIZE_INV(4), SIZE_INV(5), SIZE_INV(6), SIZE_INV(7),\n\t\t    SIZE_INV(8), SIZE_INV(9), SIZE_INV(10), SIZE_INV(11),\n\t\t    SIZE_INV(12), SIZE_INV(13), SIZE_INV(14), SIZE_INV(15),\n\t\t    SIZE_INV(16), SIZE_INV(17), SIZE_INV(18), SIZE_INV(19),\n\t\t    SIZE_INV(20), SIZE_INV(21), SIZE_INV(22), SIZE_INV(23),\n\t\t    SIZE_INV(24), SIZE_INV(25), SIZE_INV(26), SIZE_INV(27),\n\t\t    SIZE_INV(28), SIZE_INV(29), SIZE_INV(30), SIZE_INV(31)\n\t\t};\n\n\t\tif (interval <= ((sizeof(interval_invs) / sizeof(unsigned)) +\n\t\t    2)) {\n\t\t\tregind = (diff * interval_invs[interval - 3]) >>\n\t\t\t    SIZE_INV_SHIFT;\n\t\t} else\n\t\t\tregind = diff / interval;\n#undef SIZE_INV\n#undef SIZE_INV_SHIFT\n\t}\n\tassert(diff == regind * interval);\n\tassert(regind < bin_info->nregs);\n\n\treturn (regind);\n}\n\nJEMALLOC_INLINE prof_ctx_t *\narena_prof_ctx_get(const void *ptr)\n{\n\tprof_ctx_t *ret;\n\tarena_chunk_t *chunk;\n\tsize_t pageind, mapbits;\n\n\tcassert(config_prof);\n\tassert(ptr != NULL);\n\tassert(CHUNK_ADDR2BASE(ptr) != ptr);\n\n\tchunk = (arena_chunk_t *)CHUNK_ADDR2BASE(ptr);\n\tpageind = ((uintptr_t)ptr - (uintptr_t)chunk) >> LG_PAGE;\n\tmapbits = arena_mapbits_get(chunk, pageind);\n\tassert((mapbits & CHUNK_MAP_ALLOCATED) != 0);\n\tif ((mapbits & CHUNK_MAP_LARGE) == 0) {\n\t\tif (prof_promote)\n\t\t\tret = (prof_ctx_t *)(uintptr_t)1U;\n\t\telse {\n\t\t\tarena_run_t *run = (arena_run_t *)((uintptr_t)chunk +\n\t\t\t    (uintptr_t)((pageind - (mapbits >> LG_PAGE)) <<\n\t\t\t    LG_PAGE));\n\t\t\tsize_t binind = arena_ptr_small_binind_get(ptr,\n\t\t\t    mapbits);\n\t\t\tarena_bin_info_t *bin_info = &arena_bin_info[binind];\n\t\t\tunsigned regind;\n\n\t\t\tregind = arena_run_regind(run, bin_info, ptr);\n\t\t\tret = *(prof_ctx_t **)((uintptr_t)run +\n\t\t\t    bin_info->ctx0_offset + (regind *\n\t\t\t    sizeof(prof_ctx_t *)));\n\t\t}\n\t} else\n\t\tret = arena_mapp_get(chunk, pageind)->prof_ctx;\n\n\treturn (ret);\n}\n\nJEMALLOC_INLINE void\narena_prof_ctx_set(const void *ptr, size_t usize, prof_ctx_t *ctx)\n{\n\tarena_chunk_t *chunk;\n\tsize_t pageind;\n\n\tcassert(config_prof);\n\tassert(ptr != NULL);\n\tassert(CHUNK_ADDR2BASE(ptr) != ptr);\n\n\tchunk = (arena_chunk_t *)CHUNK_ADDR2BASE(ptr);\n\tpageind = ((uintptr_t)ptr - (uintptr_t)chunk) >> LG_PAGE;\n\tassert(arena_mapbits_allocated_get(chunk, pageind) != 0);\n\n\tif (usize > SMALL_MAXCLASS || (prof_promote &&\n\t    ((uintptr_t)ctx != (uintptr_t)1U || arena_mapbits_large_get(chunk,\n\t    pageind) != 0))) {\n\t\tassert(arena_mapbits_large_get(chunk, pageind) != 0);\n\t\tarena_mapp_get(chunk, pageind)->prof_ctx = ctx;\n\t} else {\n\t\tassert(arena_mapbits_large_get(chunk, pageind) == 0);\n\t\tif (prof_promote == false) {\n\t\t\tsize_t mapbits = arena_mapbits_get(chunk, pageind);\n\t\t\tarena_run_t *run = (arena_run_t *)((uintptr_t)chunk +\n\t\t\t    (uintptr_t)((pageind - (mapbits >> LG_PAGE)) <<\n\t\t\t    LG_PAGE));\n\t\t\tsize_t binind;\n\t\t\tarena_bin_info_t *bin_info;\n\t\t\tunsigned regind;\n\n\t\t\tbinind = arena_ptr_small_binind_get(ptr, mapbits);\n\t\t\tbin_info = &arena_bin_info[binind];\n\t\t\tregind = arena_run_regind(run, bin_info, ptr);\n\n\t\t\t*((prof_ctx_t **)((uintptr_t)run +\n\t\t\t    bin_info->ctx0_offset + (regind * sizeof(prof_ctx_t\n\t\t\t    *)))) = ctx;\n\t\t}\n\t}\n}\n\nJEMALLOC_ALWAYS_INLINE void *\narena_malloc(arena_t *arena, size_t size, bool zero, bool try_tcache)\n{\n\ttcache_t *tcache;\n\n\tassert(size != 0);\n\tassert(size <= arena_maxclass);\n\n\tif (size <= SMALL_MAXCLASS) {\n\t\tif (try_tcache && (tcache = tcache_get(true)) != NULL)\n\t\t\treturn (tcache_alloc_small(tcache, size, zero));\n\t\telse {\n\t\t\treturn (arena_malloc_small(choose_arena(arena), size,\n\t\t\t    zero));\n\t\t}\n\t} else {\n\t\t/*\n\t\t * Initialize tcache after checking size in order to avoid\n\t\t * infinite recursion during tcache initialization.\n\t\t */\n\t\tif (try_tcache && size <= tcache_maxclass && (tcache =\n\t\t    tcache_get(true)) != NULL)\n\t\t\treturn (tcache_alloc_large(tcache, size, zero));\n\t\telse {\n\t\t\treturn (arena_malloc_large(choose_arena(arena), size,\n\t\t\t    zero));\n\t\t}\n\t}\n}\n\n/* Return the size of the allocation pointed to by ptr. */\nJEMALLOC_ALWAYS_INLINE size_t\narena_salloc(const void *ptr, bool demote)\n{\n\tsize_t ret;\n\tarena_chunk_t *chunk;\n\tsize_t pageind, binind;\n\n\tassert(ptr != NULL);\n\tassert(CHUNK_ADDR2BASE(ptr) != ptr);\n\n\tchunk = (arena_chunk_t *)CHUNK_ADDR2BASE(ptr);\n\tpageind = ((uintptr_t)ptr - (uintptr_t)chunk) >> LG_PAGE;\n\tassert(arena_mapbits_allocated_get(chunk, pageind) != 0);\n\tbinind = arena_mapbits_binind_get(chunk, pageind);\n\tif (binind == BININD_INVALID || (config_prof && demote == false &&\n\t    prof_promote && arena_mapbits_large_get(chunk, pageind) != 0)) {\n\t\t/*\n\t\t * Large allocation.  In the common case (demote == true), and\n\t\t * as this is an inline function, most callers will only end up\n\t\t * looking at binind to determine that ptr is a small\n\t\t * allocation.\n\t\t */\n\t\tassert(((uintptr_t)ptr & PAGE_MASK) == 0);\n\t\tret = arena_mapbits_large_size_get(chunk, pageind);\n\t\tassert(ret != 0);\n\t\tassert(pageind + (ret>>LG_PAGE) <= chunk_npages);\n\t\tassert(ret == PAGE || arena_mapbits_large_size_get(chunk,\n\t\t    pageind+(ret>>LG_PAGE)-1) == 0);\n\t\tassert(binind == arena_mapbits_binind_get(chunk,\n\t\t    pageind+(ret>>LG_PAGE)-1));\n\t\tassert(arena_mapbits_dirty_get(chunk, pageind) ==\n\t\t    arena_mapbits_dirty_get(chunk, pageind+(ret>>LG_PAGE)-1));\n\t} else {\n\t\t/*\n\t\t * Small allocation (possibly promoted to a large object due to\n\t\t * prof_promote).\n\t\t */\n\t\tassert(arena_mapbits_large_get(chunk, pageind) != 0 ||\n\t\t    arena_ptr_small_binind_get(ptr, arena_mapbits_get(chunk,\n\t\t    pageind)) == binind);\n\t\tret = arena_bin_info[binind].reg_size;\n\t}\n\n\treturn (ret);\n}\n\nJEMALLOC_ALWAYS_INLINE void\narena_dalloc(arena_t *arena, arena_chunk_t *chunk, void *ptr, bool try_tcache)\n{\n\tsize_t pageind, mapbits;\n\ttcache_t *tcache;\n\n\tassert(arena != NULL);\n\tassert(chunk->arena == arena);\n\tassert(ptr != NULL);\n\tassert(CHUNK_ADDR2BASE(ptr) != ptr);\n\n\tpageind = ((uintptr_t)ptr - (uintptr_t)chunk) >> LG_PAGE;\n\tmapbits = arena_mapbits_get(chunk, pageind);\n\tassert(arena_mapbits_allocated_get(chunk, pageind) != 0);\n\tif ((mapbits & CHUNK_MAP_LARGE) == 0) {\n\t\t/* Small allocation. */\n\t\tif (try_tcache && (tcache = tcache_get(false)) != NULL) {\n\t\t\tsize_t binind;\n\n\t\t\tbinind = arena_ptr_small_binind_get(ptr, mapbits);\n\t\t\ttcache_dalloc_small(tcache, ptr, binind);\n\t\t} else\n\t\t\tarena_dalloc_small(arena, chunk, ptr, pageind);\n\t} else {\n\t\tsize_t size = arena_mapbits_large_size_get(chunk, pageind);\n\n\t\tassert(((uintptr_t)ptr & PAGE_MASK) == 0);\n\n\t\tif (try_tcache && size <= tcache_maxclass && (tcache =\n\t\t    tcache_get(false)) != NULL) {\n\t\t\ttcache_dalloc_large(tcache, ptr, size);\n\t\t} else\n\t\t\tarena_dalloc_large(arena, chunk, ptr);\n\t}\n}\n#  endif /* JEMALLOC_ARENA_INLINE_B */\n#endif\n\n#endif /* JEMALLOC_H_INLINES */\n/******************************************************************************/\n"
  },
  {
    "path": "extern/deprecated/redis-2.8.21/deps/jemalloc/include/jemalloc/internal/atomic.h",
    "content": "/******************************************************************************/\n#ifdef JEMALLOC_H_TYPES\n\n#endif /* JEMALLOC_H_TYPES */\n/******************************************************************************/\n#ifdef JEMALLOC_H_STRUCTS\n\n#endif /* JEMALLOC_H_STRUCTS */\n/******************************************************************************/\n#ifdef JEMALLOC_H_EXTERNS\n\n#define\tatomic_read_uint64(p)\tatomic_add_uint64(p, 0)\n#define\tatomic_read_uint32(p)\tatomic_add_uint32(p, 0)\n#define\tatomic_read_z(p)\tatomic_add_z(p, 0)\n#define\tatomic_read_u(p)\tatomic_add_u(p, 0)\n\n#endif /* JEMALLOC_H_EXTERNS */\n/******************************************************************************/\n#ifdef JEMALLOC_H_INLINES\n\n#ifndef JEMALLOC_ENABLE_INLINE\nuint64_t\tatomic_add_uint64(uint64_t *p, uint64_t x);\nuint64_t\tatomic_sub_uint64(uint64_t *p, uint64_t x);\nuint32_t\tatomic_add_uint32(uint32_t *p, uint32_t x);\nuint32_t\tatomic_sub_uint32(uint32_t *p, uint32_t x);\nsize_t\tatomic_add_z(size_t *p, size_t x);\nsize_t\tatomic_sub_z(size_t *p, size_t x);\nunsigned\tatomic_add_u(unsigned *p, unsigned x);\nunsigned\tatomic_sub_u(unsigned *p, unsigned x);\n#endif\n\n#if (defined(JEMALLOC_ENABLE_INLINE) || defined(JEMALLOC_ATOMIC_C_))\n/******************************************************************************/\n/* 64-bit operations. */\n#if (LG_SIZEOF_PTR == 3 || LG_SIZEOF_INT == 3)\n#  ifdef __GCC_HAVE_SYNC_COMPARE_AND_SWAP_8\nJEMALLOC_INLINE uint64_t\natomic_add_uint64(uint64_t *p, uint64_t x)\n{\n\n\treturn (__sync_add_and_fetch(p, x));\n}\n\nJEMALLOC_INLINE uint64_t\natomic_sub_uint64(uint64_t *p, uint64_t x)\n{\n\n\treturn (__sync_sub_and_fetch(p, x));\n}\n#elif (defined(_MSC_VER))\nJEMALLOC_INLINE uint64_t\natomic_add_uint64(uint64_t *p, uint64_t x)\n{\n\n\treturn (InterlockedExchangeAdd64(p, x));\n}\n\nJEMALLOC_INLINE uint64_t\natomic_sub_uint64(uint64_t *p, uint64_t x)\n{\n\n\treturn (InterlockedExchangeAdd64(p, -((int64_t)x)));\n}\n#elif (defined(JEMALLOC_OSATOMIC))\nJEMALLOC_INLINE uint64_t\natomic_add_uint64(uint64_t *p, uint64_t x)\n{\n\n\treturn (OSAtomicAdd64((int64_t)x, (int64_t *)p));\n}\n\nJEMALLOC_INLINE uint64_t\natomic_sub_uint64(uint64_t *p, uint64_t x)\n{\n\n\treturn (OSAtomicAdd64(-((int64_t)x), (int64_t *)p));\n}\n#  elif (defined(__amd64__) || defined(__x86_64__))\nJEMALLOC_INLINE uint64_t\natomic_add_uint64(uint64_t *p, uint64_t x)\n{\n\n\tasm volatile (\n\t    \"lock; xaddq %0, %1;\"\n\t    : \"+r\" (x), \"=m\" (*p) /* Outputs. */\n\t    : \"m\" (*p) /* Inputs. */\n\t    );\n\n\treturn (x);\n}\n\nJEMALLOC_INLINE uint64_t\natomic_sub_uint64(uint64_t *p, uint64_t x)\n{\n\n\tx = (uint64_t)(-(int64_t)x);\n\tasm volatile (\n\t    \"lock; xaddq %0, %1;\"\n\t    : \"+r\" (x), \"=m\" (*p) /* Outputs. */\n\t    : \"m\" (*p) /* Inputs. */\n\t    );\n\n\treturn (x);\n}\n#  elif (defined(JEMALLOC_ATOMIC9))\nJEMALLOC_INLINE uint64_t\natomic_add_uint64(uint64_t *p, uint64_t x)\n{\n\n\t/*\n\t * atomic_fetchadd_64() doesn't exist, but we only ever use this\n\t * function on LP64 systems, so atomic_fetchadd_long() will do.\n\t */\n\tassert(sizeof(uint64_t) == sizeof(unsigned long));\n\n\treturn (atomic_fetchadd_long(p, (unsigned long)x) + x);\n}\n\nJEMALLOC_INLINE uint64_t\natomic_sub_uint64(uint64_t *p, uint64_t x)\n{\n\n\tassert(sizeof(uint64_t) == sizeof(unsigned long));\n\n\treturn (atomic_fetchadd_long(p, (unsigned long)(-(long)x)) - x);\n}\n#  elif (defined(JE_FORCE_SYNC_COMPARE_AND_SWAP_8))\nJEMALLOC_INLINE uint64_t\natomic_add_uint64(uint64_t *p, uint64_t x)\n{\n\n\treturn (__sync_add_and_fetch(p, x));\n}\n\nJEMALLOC_INLINE uint64_t\natomic_sub_uint64(uint64_t *p, uint64_t x)\n{\n\n\treturn (__sync_sub_and_fetch(p, x));\n}\n#  else\n#    error \"Missing implementation for 64-bit atomic operations\"\n#  endif\n#endif\n\n/******************************************************************************/\n/* 32-bit operations. */\n#ifdef __GCC_HAVE_SYNC_COMPARE_AND_SWAP_4\nJEMALLOC_INLINE uint32_t\natomic_add_uint32(uint32_t *p, uint32_t x)\n{\n\n\treturn (__sync_add_and_fetch(p, x));\n}\n\nJEMALLOC_INLINE uint32_t\natomic_sub_uint32(uint32_t *p, uint32_t x)\n{\n\n\treturn (__sync_sub_and_fetch(p, x));\n}\n#elif (defined(_MSC_VER))\nJEMALLOC_INLINE uint32_t\natomic_add_uint32(uint32_t *p, uint32_t x)\n{\n\n\treturn (InterlockedExchangeAdd(p, x));\n}\n\nJEMALLOC_INLINE uint32_t\natomic_sub_uint32(uint32_t *p, uint32_t x)\n{\n\n\treturn (InterlockedExchangeAdd(p, -((int32_t)x)));\n}\n#elif (defined(JEMALLOC_OSATOMIC))\nJEMALLOC_INLINE uint32_t\natomic_add_uint32(uint32_t *p, uint32_t x)\n{\n\n\treturn (OSAtomicAdd32((int32_t)x, (int32_t *)p));\n}\n\nJEMALLOC_INLINE uint32_t\natomic_sub_uint32(uint32_t *p, uint32_t x)\n{\n\n\treturn (OSAtomicAdd32(-((int32_t)x), (int32_t *)p));\n}\n#elif (defined(__i386__) || defined(__amd64__) || defined(__x86_64__))\nJEMALLOC_INLINE uint32_t\natomic_add_uint32(uint32_t *p, uint32_t x)\n{\n\n\tasm volatile (\n\t    \"lock; xaddl %0, %1;\"\n\t    : \"+r\" (x), \"=m\" (*p) /* Outputs. */\n\t    : \"m\" (*p) /* Inputs. */\n\t    );\n\n\treturn (x);\n}\n\nJEMALLOC_INLINE uint32_t\natomic_sub_uint32(uint32_t *p, uint32_t x)\n{\n\n\tx = (uint32_t)(-(int32_t)x);\n\tasm volatile (\n\t    \"lock; xaddl %0, %1;\"\n\t    : \"+r\" (x), \"=m\" (*p) /* Outputs. */\n\t    : \"m\" (*p) /* Inputs. */\n\t    );\n\n\treturn (x);\n}\n#elif (defined(JEMALLOC_ATOMIC9))\nJEMALLOC_INLINE uint32_t\natomic_add_uint32(uint32_t *p, uint32_t x)\n{\n\n\treturn (atomic_fetchadd_32(p, x) + x);\n}\n\nJEMALLOC_INLINE uint32_t\natomic_sub_uint32(uint32_t *p, uint32_t x)\n{\n\n\treturn (atomic_fetchadd_32(p, (uint32_t)(-(int32_t)x)) - x);\n}\n#elif (defined(JE_FORCE_SYNC_COMPARE_AND_SWAP_4))\nJEMALLOC_INLINE uint32_t\natomic_add_uint32(uint32_t *p, uint32_t x)\n{\n\n\treturn (__sync_add_and_fetch(p, x));\n}\n\nJEMALLOC_INLINE uint32_t\natomic_sub_uint32(uint32_t *p, uint32_t x)\n{\n\n\treturn (__sync_sub_and_fetch(p, x));\n}\n#else\n#  error \"Missing implementation for 32-bit atomic operations\"\n#endif\n\n/******************************************************************************/\n/* size_t operations. */\nJEMALLOC_INLINE size_t\natomic_add_z(size_t *p, size_t x)\n{\n\n#if (LG_SIZEOF_PTR == 3)\n\treturn ((size_t)atomic_add_uint64((uint64_t *)p, (uint64_t)x));\n#elif (LG_SIZEOF_PTR == 2)\n\treturn ((size_t)atomic_add_uint32((uint32_t *)p, (uint32_t)x));\n#endif\n}\n\nJEMALLOC_INLINE size_t\natomic_sub_z(size_t *p, size_t x)\n{\n\n#if (LG_SIZEOF_PTR == 3)\n\treturn ((size_t)atomic_add_uint64((uint64_t *)p,\n\t    (uint64_t)-((int64_t)x)));\n#elif (LG_SIZEOF_PTR == 2)\n\treturn ((size_t)atomic_add_uint32((uint32_t *)p,\n\t    (uint32_t)-((int32_t)x)));\n#endif\n}\n\n/******************************************************************************/\n/* unsigned operations. */\nJEMALLOC_INLINE unsigned\natomic_add_u(unsigned *p, unsigned x)\n{\n\n#if (LG_SIZEOF_INT == 3)\n\treturn ((unsigned)atomic_add_uint64((uint64_t *)p, (uint64_t)x));\n#elif (LG_SIZEOF_INT == 2)\n\treturn ((unsigned)atomic_add_uint32((uint32_t *)p, (uint32_t)x));\n#endif\n}\n\nJEMALLOC_INLINE unsigned\natomic_sub_u(unsigned *p, unsigned x)\n{\n\n#if (LG_SIZEOF_INT == 3)\n\treturn ((unsigned)atomic_add_uint64((uint64_t *)p,\n\t    (uint64_t)-((int64_t)x)));\n#elif (LG_SIZEOF_INT == 2)\n\treturn ((unsigned)atomic_add_uint32((uint32_t *)p,\n\t    (uint32_t)-((int32_t)x)));\n#endif\n}\n/******************************************************************************/\n#endif\n\n#endif /* JEMALLOC_H_INLINES */\n/******************************************************************************/\n"
  },
  {
    "path": "extern/deprecated/redis-2.8.21/deps/jemalloc/include/jemalloc/internal/base.h",
    "content": "/******************************************************************************/\n#ifdef JEMALLOC_H_TYPES\n\n#endif /* JEMALLOC_H_TYPES */\n/******************************************************************************/\n#ifdef JEMALLOC_H_STRUCTS\n\n#endif /* JEMALLOC_H_STRUCTS */\n/******************************************************************************/\n#ifdef JEMALLOC_H_EXTERNS\n\nvoid\t*base_alloc(size_t size);\nvoid\t*base_calloc(size_t number, size_t size);\nextent_node_t *base_node_alloc(void);\nvoid\tbase_node_dealloc(extent_node_t *node);\nbool\tbase_boot(void);\nvoid\tbase_prefork(void);\nvoid\tbase_postfork_parent(void);\nvoid\tbase_postfork_child(void);\n\n#endif /* JEMALLOC_H_EXTERNS */\n/******************************************************************************/\n#ifdef JEMALLOC_H_INLINES\n\n#endif /* JEMALLOC_H_INLINES */\n/******************************************************************************/\n"
  },
  {
    "path": "extern/deprecated/redis-2.8.21/deps/jemalloc/include/jemalloc/internal/bitmap.h",
    "content": "/******************************************************************************/\n#ifdef JEMALLOC_H_TYPES\n\n/* Maximum bitmap bit count is 2^LG_BITMAP_MAXBITS. */\n#define\tLG_BITMAP_MAXBITS\tLG_RUN_MAXREGS\n\ntypedef struct bitmap_level_s bitmap_level_t;\ntypedef struct bitmap_info_s bitmap_info_t;\ntypedef unsigned long bitmap_t;\n#define\tLG_SIZEOF_BITMAP\tLG_SIZEOF_LONG\n\n/* Number of bits per group. */\n#define\tLG_BITMAP_GROUP_NBITS\t\t(LG_SIZEOF_BITMAP + 3)\n#define\tBITMAP_GROUP_NBITS\t\t(ZU(1) << LG_BITMAP_GROUP_NBITS)\n#define\tBITMAP_GROUP_NBITS_MASK\t\t(BITMAP_GROUP_NBITS-1)\n\n/* Maximum number of levels possible. */\n#define\tBITMAP_MAX_LEVELS\t\t\t\t\t\t\\\n    (LG_BITMAP_MAXBITS / LG_SIZEOF_BITMAP)\t\t\t\t\\\n    + !!(LG_BITMAP_MAXBITS % LG_SIZEOF_BITMAP)\n\n#endif /* JEMALLOC_H_TYPES */\n/******************************************************************************/\n#ifdef JEMALLOC_H_STRUCTS\n\nstruct bitmap_level_s {\n\t/* Offset of this level's groups within the array of groups. */\n\tsize_t group_offset;\n};\n\nstruct bitmap_info_s {\n\t/* Logical number of bits in bitmap (stored at bottom level). */\n\tsize_t nbits;\n\n\t/* Number of levels necessary for nbits. */\n\tunsigned nlevels;\n\n\t/*\n\t * Only the first (nlevels+1) elements are used, and levels are ordered\n\t * bottom to top (e.g. the bottom level is stored in levels[0]).\n\t */\n\tbitmap_level_t levels[BITMAP_MAX_LEVELS+1];\n};\n\n#endif /* JEMALLOC_H_STRUCTS */\n/******************************************************************************/\n#ifdef JEMALLOC_H_EXTERNS\n\nvoid\tbitmap_info_init(bitmap_info_t *binfo, size_t nbits);\nsize_t\tbitmap_info_ngroups(const bitmap_info_t *binfo);\nsize_t\tbitmap_size(size_t nbits);\nvoid\tbitmap_init(bitmap_t *bitmap, const bitmap_info_t *binfo);\n\n#endif /* JEMALLOC_H_EXTERNS */\n/******************************************************************************/\n#ifdef JEMALLOC_H_INLINES\n\n#ifndef JEMALLOC_ENABLE_INLINE\nbool\tbitmap_full(bitmap_t *bitmap, const bitmap_info_t *binfo);\nbool\tbitmap_get(bitmap_t *bitmap, const bitmap_info_t *binfo, size_t bit);\nvoid\tbitmap_set(bitmap_t *bitmap, const bitmap_info_t *binfo, size_t bit);\nsize_t\tbitmap_sfu(bitmap_t *bitmap, const bitmap_info_t *binfo);\nvoid\tbitmap_unset(bitmap_t *bitmap, const bitmap_info_t *binfo, size_t bit);\n#endif\n\n#if (defined(JEMALLOC_ENABLE_INLINE) || defined(JEMALLOC_BITMAP_C_))\nJEMALLOC_INLINE bool\nbitmap_full(bitmap_t *bitmap, const bitmap_info_t *binfo)\n{\n\tunsigned rgoff = binfo->levels[binfo->nlevels].group_offset - 1;\n\tbitmap_t rg = bitmap[rgoff];\n\t/* The bitmap is full iff the root group is 0. */\n\treturn (rg == 0);\n}\n\nJEMALLOC_INLINE bool\nbitmap_get(bitmap_t *bitmap, const bitmap_info_t *binfo, size_t bit)\n{\n\tsize_t goff;\n\tbitmap_t g;\n\n\tassert(bit < binfo->nbits);\n\tgoff = bit >> LG_BITMAP_GROUP_NBITS;\n\tg = bitmap[goff];\n\treturn (!(g & (1LU << (bit & BITMAP_GROUP_NBITS_MASK))));\n}\n\nJEMALLOC_INLINE void\nbitmap_set(bitmap_t *bitmap, const bitmap_info_t *binfo, size_t bit)\n{\n\tsize_t goff;\n\tbitmap_t *gp;\n\tbitmap_t g;\n\n\tassert(bit < binfo->nbits);\n\tassert(bitmap_get(bitmap, binfo, bit) == false);\n\tgoff = bit >> LG_BITMAP_GROUP_NBITS;\n\tgp = &bitmap[goff];\n\tg = *gp;\n\tassert(g & (1LU << (bit & BITMAP_GROUP_NBITS_MASK)));\n\tg ^= 1LU << (bit & BITMAP_GROUP_NBITS_MASK);\n\t*gp = g;\n\tassert(bitmap_get(bitmap, binfo, bit));\n\t/* Propagate group state transitions up the tree. */\n\tif (g == 0) {\n\t\tunsigned i;\n\t\tfor (i = 1; i < binfo->nlevels; i++) {\n\t\t\tbit = goff;\n\t\t\tgoff = bit >> LG_BITMAP_GROUP_NBITS;\n\t\t\tgp = &bitmap[binfo->levels[i].group_offset + goff];\n\t\t\tg = *gp;\n\t\t\tassert(g & (1LU << (bit & BITMAP_GROUP_NBITS_MASK)));\n\t\t\tg ^= 1LU << (bit & BITMAP_GROUP_NBITS_MASK);\n\t\t\t*gp = g;\n\t\t\tif (g != 0)\n\t\t\t\tbreak;\n\t\t}\n\t}\n}\n\n/* sfu: set first unset. */\nJEMALLOC_INLINE size_t\nbitmap_sfu(bitmap_t *bitmap, const bitmap_info_t *binfo)\n{\n\tsize_t bit;\n\tbitmap_t g;\n\tunsigned i;\n\n\tassert(bitmap_full(bitmap, binfo) == false);\n\n\ti = binfo->nlevels - 1;\n\tg = bitmap[binfo->levels[i].group_offset];\n\tbit = ffsl(g) - 1;\n\twhile (i > 0) {\n\t\ti--;\n\t\tg = bitmap[binfo->levels[i].group_offset + bit];\n\t\tbit = (bit << LG_BITMAP_GROUP_NBITS) + (ffsl(g) - 1);\n\t}\n\n\tbitmap_set(bitmap, binfo, bit);\n\treturn (bit);\n}\n\nJEMALLOC_INLINE void\nbitmap_unset(bitmap_t *bitmap, const bitmap_info_t *binfo, size_t bit)\n{\n\tsize_t goff;\n\tbitmap_t *gp;\n\tbitmap_t g;\n\tbool propagate;\n\n\tassert(bit < binfo->nbits);\n\tassert(bitmap_get(bitmap, binfo, bit));\n\tgoff = bit >> LG_BITMAP_GROUP_NBITS;\n\tgp = &bitmap[goff];\n\tg = *gp;\n\tpropagate = (g == 0);\n\tassert((g & (1LU << (bit & BITMAP_GROUP_NBITS_MASK))) == 0);\n\tg ^= 1LU << (bit & BITMAP_GROUP_NBITS_MASK);\n\t*gp = g;\n\tassert(bitmap_get(bitmap, binfo, bit) == false);\n\t/* Propagate group state transitions up the tree. */\n\tif (propagate) {\n\t\tunsigned i;\n\t\tfor (i = 1; i < binfo->nlevels; i++) {\n\t\t\tbit = goff;\n\t\t\tgoff = bit >> LG_BITMAP_GROUP_NBITS;\n\t\t\tgp = &bitmap[binfo->levels[i].group_offset + goff];\n\t\t\tg = *gp;\n\t\t\tpropagate = (g == 0);\n\t\t\tassert((g & (1LU << (bit & BITMAP_GROUP_NBITS_MASK)))\n\t\t\t    == 0);\n\t\t\tg ^= 1LU << (bit & BITMAP_GROUP_NBITS_MASK);\n\t\t\t*gp = g;\n\t\t\tif (propagate == false)\n\t\t\t\tbreak;\n\t\t}\n\t}\n}\n\n#endif\n\n#endif /* JEMALLOC_H_INLINES */\n/******************************************************************************/\n"
  },
  {
    "path": "extern/deprecated/redis-2.8.21/deps/jemalloc/include/jemalloc/internal/chunk.h",
    "content": "/******************************************************************************/\n#ifdef JEMALLOC_H_TYPES\n\n/*\n * Size and alignment of memory chunks that are allocated by the OS's virtual\n * memory system.\n */\n#define\tLG_CHUNK_DEFAULT\t22\n\n/* Return the chunk address for allocation address a. */\n#define\tCHUNK_ADDR2BASE(a)\t\t\t\t\t\t\\\n\t((void *)((uintptr_t)(a) & ~chunksize_mask))\n\n/* Return the chunk offset of address a. */\n#define\tCHUNK_ADDR2OFFSET(a)\t\t\t\t\t\t\\\n\t((size_t)((uintptr_t)(a) & chunksize_mask))\n\n/* Return the smallest chunk multiple that is >= s. */\n#define\tCHUNK_CEILING(s)\t\t\t\t\t\t\\\n\t(((s) + chunksize_mask) & ~chunksize_mask)\n\n#endif /* JEMALLOC_H_TYPES */\n/******************************************************************************/\n#ifdef JEMALLOC_H_STRUCTS\n\n#endif /* JEMALLOC_H_STRUCTS */\n/******************************************************************************/\n#ifdef JEMALLOC_H_EXTERNS\n\nextern size_t\t\topt_lg_chunk;\nextern const char\t*opt_dss;\n\n/* Protects stats_chunks; currently not used for any other purpose. */\nextern malloc_mutex_t\tchunks_mtx;\n/* Chunk statistics. */\nextern chunk_stats_t\tstats_chunks;\n\nextern rtree_t\t\t*chunks_rtree;\n\nextern size_t\t\tchunksize;\nextern size_t\t\tchunksize_mask; /* (chunksize - 1). */\nextern size_t\t\tchunk_npages;\nextern size_t\t\tmap_bias; /* Number of arena chunk header pages. */\nextern size_t\t\tarena_maxclass; /* Max size class for arenas. */\n\nvoid\t*chunk_alloc(size_t size, size_t alignment, bool base, bool *zero,\n    dss_prec_t dss_prec);\nvoid\tchunk_unmap(void *chunk, size_t size);\nvoid\tchunk_dealloc(void *chunk, size_t size, bool unmap);\nbool\tchunk_boot(void);\nvoid\tchunk_prefork(void);\nvoid\tchunk_postfork_parent(void);\nvoid\tchunk_postfork_child(void);\n\n#endif /* JEMALLOC_H_EXTERNS */\n/******************************************************************************/\n#ifdef JEMALLOC_H_INLINES\n\n#endif /* JEMALLOC_H_INLINES */\n/******************************************************************************/\n\n#include \"jemalloc/internal/chunk_dss.h\"\n#include \"jemalloc/internal/chunk_mmap.h\"\n"
  },
  {
    "path": "extern/deprecated/redis-2.8.21/deps/jemalloc/include/jemalloc/internal/chunk_dss.h",
    "content": "/******************************************************************************/\n#ifdef JEMALLOC_H_TYPES\n\ntypedef enum {\n\tdss_prec_disabled  = 0,\n\tdss_prec_primary   = 1,\n\tdss_prec_secondary = 2,\n\n\tdss_prec_limit     = 3\n} dss_prec_t;\n#define\tDSS_PREC_DEFAULT\tdss_prec_secondary\n#define\tDSS_DEFAULT\t\t\"secondary\"\n\n#endif /* JEMALLOC_H_TYPES */\n/******************************************************************************/\n#ifdef JEMALLOC_H_STRUCTS\n\nextern const char *dss_prec_names[];\n\n#endif /* JEMALLOC_H_STRUCTS */\n/******************************************************************************/\n#ifdef JEMALLOC_H_EXTERNS\n\ndss_prec_t\tchunk_dss_prec_get(void);\nbool\tchunk_dss_prec_set(dss_prec_t dss_prec);\nvoid\t*chunk_alloc_dss(size_t size, size_t alignment, bool *zero);\nbool\tchunk_in_dss(void *chunk);\nbool\tchunk_dss_boot(void);\nvoid\tchunk_dss_prefork(void);\nvoid\tchunk_dss_postfork_parent(void);\nvoid\tchunk_dss_postfork_child(void);\n\n#endif /* JEMALLOC_H_EXTERNS */\n/******************************************************************************/\n#ifdef JEMALLOC_H_INLINES\n\n#endif /* JEMALLOC_H_INLINES */\n/******************************************************************************/\n"
  },
  {
    "path": "extern/deprecated/redis-2.8.21/deps/jemalloc/include/jemalloc/internal/chunk_mmap.h",
    "content": "/******************************************************************************/\n#ifdef JEMALLOC_H_TYPES\n\n#endif /* JEMALLOC_H_TYPES */\n/******************************************************************************/\n#ifdef JEMALLOC_H_STRUCTS\n\n#endif /* JEMALLOC_H_STRUCTS */\n/******************************************************************************/\n#ifdef JEMALLOC_H_EXTERNS\n\nbool\tpages_purge(void *addr, size_t length);\n\nvoid\t*chunk_alloc_mmap(size_t size, size_t alignment, bool *zero);\nbool\tchunk_dealloc_mmap(void *chunk, size_t size);\n\n#endif /* JEMALLOC_H_EXTERNS */\n/******************************************************************************/\n#ifdef JEMALLOC_H_INLINES\n\n#endif /* JEMALLOC_H_INLINES */\n/******************************************************************************/\n"
  },
  {
    "path": "extern/deprecated/redis-2.8.21/deps/jemalloc/include/jemalloc/internal/ckh.h",
    "content": "/******************************************************************************/\n#ifdef JEMALLOC_H_TYPES\n\ntypedef struct ckh_s ckh_t;\ntypedef struct ckhc_s ckhc_t;\n\n/* Typedefs to allow easy function pointer passing. */\ntypedef void ckh_hash_t (const void *, size_t[2]);\ntypedef bool ckh_keycomp_t (const void *, const void *);\n\n/* Maintain counters used to get an idea of performance. */\n/* #define\tCKH_COUNT */\n/* Print counter values in ckh_delete() (requires CKH_COUNT). */\n/* #define\tCKH_VERBOSE */\n\n/*\n * There are 2^LG_CKH_BUCKET_CELLS cells in each hash table bucket.  Try to fit\n * one bucket per L1 cache line.\n */\n#define\tLG_CKH_BUCKET_CELLS (LG_CACHELINE - LG_SIZEOF_PTR - 1)\n\n#endif /* JEMALLOC_H_TYPES */\n/******************************************************************************/\n#ifdef JEMALLOC_H_STRUCTS\n\n/* Hash table cell. */\nstruct ckhc_s {\n\tconst void\t*key;\n\tconst void\t*data;\n};\n\nstruct ckh_s {\n#ifdef CKH_COUNT\n\t/* Counters used to get an idea of performance. */\n\tuint64_t\tngrows;\n\tuint64_t\tnshrinks;\n\tuint64_t\tnshrinkfails;\n\tuint64_t\tninserts;\n\tuint64_t\tnrelocs;\n#endif\n\n\t/* Used for pseudo-random number generation. */\n#define\tCKH_A\t\t1103515241\n#define\tCKH_C\t\t12347\n\tuint32_t\tprng_state;\n\n\t/* Total number of items. */\n\tsize_t\t\tcount;\n\n\t/*\n\t * Minimum and current number of hash table buckets.  There are\n\t * 2^LG_CKH_BUCKET_CELLS cells per bucket.\n\t */\n\tunsigned\tlg_minbuckets;\n\tunsigned\tlg_curbuckets;\n\n\t/* Hash and comparison functions. */\n\tckh_hash_t\t*hash;\n\tckh_keycomp_t\t*keycomp;\n\n\t/* Hash table with 2^lg_curbuckets buckets. */\n\tckhc_t\t\t*tab;\n};\n\n#endif /* JEMALLOC_H_STRUCTS */\n/******************************************************************************/\n#ifdef JEMALLOC_H_EXTERNS\n\nbool\tckh_new(ckh_t *ckh, size_t minitems, ckh_hash_t *hash,\n    ckh_keycomp_t *keycomp);\nvoid\tckh_delete(ckh_t *ckh);\nsize_t\tckh_count(ckh_t *ckh);\nbool\tckh_iter(ckh_t *ckh, size_t *tabind, void **key, void **data);\nbool\tckh_insert(ckh_t *ckh, const void *key, const void *data);\nbool\tckh_remove(ckh_t *ckh, const void *searchkey, void **key,\n    void **data);\nbool\tckh_search(ckh_t *ckh, const void *seachkey, void **key, void **data);\nvoid\tckh_string_hash(const void *key, size_t r_hash[2]);\nbool\tckh_string_keycomp(const void *k1, const void *k2);\nvoid\tckh_pointer_hash(const void *key, size_t r_hash[2]);\nbool\tckh_pointer_keycomp(const void *k1, const void *k2);\n\n#endif /* JEMALLOC_H_EXTERNS */\n/******************************************************************************/\n#ifdef JEMALLOC_H_INLINES\n\n#endif /* JEMALLOC_H_INLINES */\n/******************************************************************************/\n"
  },
  {
    "path": "extern/deprecated/redis-2.8.21/deps/jemalloc/include/jemalloc/internal/ctl.h",
    "content": "/******************************************************************************/\n#ifdef JEMALLOC_H_TYPES\n\ntypedef struct ctl_node_s ctl_node_t;\ntypedef struct ctl_named_node_s ctl_named_node_t;\ntypedef struct ctl_indexed_node_s ctl_indexed_node_t;\ntypedef struct ctl_arena_stats_s ctl_arena_stats_t;\ntypedef struct ctl_stats_s ctl_stats_t;\n\n#endif /* JEMALLOC_H_TYPES */\n/******************************************************************************/\n#ifdef JEMALLOC_H_STRUCTS\n\nstruct ctl_node_s {\n\tbool\t\t\tnamed;\n};\n\nstruct ctl_named_node_s {\n\tstruct ctl_node_s\tnode;\n\tconst char\t\t*name;\n\t/* If (nchildren == 0), this is a terminal node. */\n\tunsigned\t\tnchildren;\n\tconst\t\t\tctl_node_t *children;\n\tint\t\t\t(*ctl)(const size_t *, size_t, void *, size_t *,\n\t    void *, size_t);\n};\n\nstruct ctl_indexed_node_s {\n\tstruct ctl_node_s\tnode;\n\tconst ctl_named_node_t\t*(*index)(const size_t *, size_t, size_t);\n};\n\nstruct ctl_arena_stats_s {\n\tbool\t\t\tinitialized;\n\tunsigned\t\tnthreads;\n\tconst char\t\t*dss;\n\tsize_t\t\t\tpactive;\n\tsize_t\t\t\tpdirty;\n\tarena_stats_t\t\tastats;\n\n\t/* Aggregate stats for small size classes, based on bin stats. */\n\tsize_t\t\t\tallocated_small;\n\tuint64_t\t\tnmalloc_small;\n\tuint64_t\t\tndalloc_small;\n\tuint64_t\t\tnrequests_small;\n\n\tmalloc_bin_stats_t\tbstats[NBINS];\n\tmalloc_large_stats_t\t*lstats;\t/* nlclasses elements. */\n};\n\nstruct ctl_stats_s {\n\tsize_t\t\t\tallocated;\n\tsize_t\t\t\tactive;\n\tsize_t\t\t\tmapped;\n\tstruct {\n\t\tsize_t\t\tcurrent;\t/* stats_chunks.curchunks */\n\t\tuint64_t\ttotal;\t\t/* stats_chunks.nchunks */\n\t\tsize_t\t\thigh;\t\t/* stats_chunks.highchunks */\n\t} chunks;\n\tstruct {\n\t\tsize_t\t\tallocated;\t/* huge_allocated */\n\t\tuint64_t\tnmalloc;\t/* huge_nmalloc */\n\t\tuint64_t\tndalloc;\t/* huge_ndalloc */\n\t} huge;\n\tunsigned\t\tnarenas;\n\tctl_arena_stats_t\t*arenas;\t/* (narenas + 1) elements. */\n};\n\n#endif /* JEMALLOC_H_STRUCTS */\n/******************************************************************************/\n#ifdef JEMALLOC_H_EXTERNS\n\nint\tctl_byname(const char *name, void *oldp, size_t *oldlenp, void *newp,\n    size_t newlen);\nint\tctl_nametomib(const char *name, size_t *mibp, size_t *miblenp);\n\nint\tctl_bymib(const size_t *mib, size_t miblen, void *oldp, size_t *oldlenp,\n    void *newp, size_t newlen);\nbool\tctl_boot(void);\nvoid\tctl_prefork(void);\nvoid\tctl_postfork_parent(void);\nvoid\tctl_postfork_child(void);\n\n#define\txmallctl(name, oldp, oldlenp, newp, newlen) do {\t\t\\\n\tif (je_mallctl(name, oldp, oldlenp, newp, newlen)\t\t\\\n\t    != 0) {\t\t\t\t\t\t\t\\\n\t\tmalloc_printf(\t\t\t\t\t\t\\\n\t\t    \"<jemalloc>: Failure in xmallctl(\\\"%s\\\", ...)\\n\",\t\\\n\t\t    name);\t\t\t\t\t\t\\\n\t\tabort();\t\t\t\t\t\t\\\n\t}\t\t\t\t\t\t\t\t\\\n} while (0)\n\n#define\txmallctlnametomib(name, mibp, miblenp) do {\t\t\t\\\n\tif (je_mallctlnametomib(name, mibp, miblenp) != 0) {\t\t\\\n\t\tmalloc_printf(\"<jemalloc>: Failure in \"\t\t\t\\\n\t\t    \"xmallctlnametomib(\\\"%s\\\", ...)\\n\", name);\t\t\\\n\t\tabort();\t\t\t\t\t\t\\\n\t}\t\t\t\t\t\t\t\t\\\n} while (0)\n\n#define\txmallctlbymib(mib, miblen, oldp, oldlenp, newp, newlen) do {\t\\\n\tif (je_mallctlbymib(mib, miblen, oldp, oldlenp, newp,\t\t\\\n\t    newlen) != 0) {\t\t\t\t\t\t\\\n\t\tmalloc_write(\t\t\t\t\t\t\\\n\t\t    \"<jemalloc>: Failure in xmallctlbymib()\\n\");\t\\\n\t\tabort();\t\t\t\t\t\t\\\n\t}\t\t\t\t\t\t\t\t\\\n} while (0)\n\n#endif /* JEMALLOC_H_EXTERNS */\n/******************************************************************************/\n#ifdef JEMALLOC_H_INLINES\n\n#endif /* JEMALLOC_H_INLINES */\n/******************************************************************************/\n\n"
  },
  {
    "path": "extern/deprecated/redis-2.8.21/deps/jemalloc/include/jemalloc/internal/extent.h",
    "content": "/******************************************************************************/\n#ifdef JEMALLOC_H_TYPES\n\ntypedef struct extent_node_s extent_node_t;\n\n#endif /* JEMALLOC_H_TYPES */\n/******************************************************************************/\n#ifdef JEMALLOC_H_STRUCTS\n\n/* Tree of extents. */\nstruct extent_node_s {\n\t/* Linkage for the size/address-ordered tree. */\n\trb_node(extent_node_t)\tlink_szad;\n\n\t/* Linkage for the address-ordered tree. */\n\trb_node(extent_node_t)\tlink_ad;\n\n\t/* Profile counters, used for huge objects. */\n\tprof_ctx_t\t\t*prof_ctx;\n\n\t/* Pointer to the extent that this tree node is responsible for. */\n\tvoid\t\t\t*addr;\n\n\t/* Total region size. */\n\tsize_t\t\t\tsize;\n\n\t/* True if zero-filled; used by chunk recycling code. */\n\tbool\t\t\tzeroed;\n};\ntypedef rb_tree(extent_node_t) extent_tree_t;\n\n#endif /* JEMALLOC_H_STRUCTS */\n/******************************************************************************/\n#ifdef JEMALLOC_H_EXTERNS\n\nrb_proto(, extent_tree_szad_, extent_tree_t, extent_node_t)\n\nrb_proto(, extent_tree_ad_, extent_tree_t, extent_node_t)\n\n#endif /* JEMALLOC_H_EXTERNS */\n/******************************************************************************/\n#ifdef JEMALLOC_H_INLINES\n\n#endif /* JEMALLOC_H_INLINES */\n/******************************************************************************/\n\n"
  },
  {
    "path": "extern/deprecated/redis-2.8.21/deps/jemalloc/include/jemalloc/internal/hash.h",
    "content": "/*\n * The following hash function is based on MurmurHash3, placed into the public\n * domain by Austin Appleby.  See http://code.google.com/p/smhasher/ for\n * details.\n */\n/******************************************************************************/\n#ifdef JEMALLOC_H_TYPES\n\n#endif /* JEMALLOC_H_TYPES */\n/******************************************************************************/\n#ifdef JEMALLOC_H_STRUCTS\n\n#endif /* JEMALLOC_H_STRUCTS */\n/******************************************************************************/\n#ifdef JEMALLOC_H_EXTERNS\n\n#endif /* JEMALLOC_H_EXTERNS */\n/******************************************************************************/\n#ifdef JEMALLOC_H_INLINES\n\n#ifndef JEMALLOC_ENABLE_INLINE\nuint32_t\thash_x86_32(const void *key, int len, uint32_t seed);\nvoid\thash_x86_128(const void *key, const int len, uint32_t seed,\n    uint64_t r_out[2]);\nvoid\thash_x64_128(const void *key, const int len, const uint32_t seed,\n    uint64_t r_out[2]);\nvoid\thash(const void *key, size_t len, const uint32_t seed,\n    size_t r_hash[2]);\n#endif\n\n#if (defined(JEMALLOC_ENABLE_INLINE) || defined(JEMALLOC_HASH_C_))\n/******************************************************************************/\n/* Internal implementation. */\nJEMALLOC_INLINE uint32_t\nhash_rotl_32(uint32_t x, int8_t r)\n{\n\n\treturn (x << r) | (x >> (32 - r));\n}\n\nJEMALLOC_INLINE uint64_t\nhash_rotl_64(uint64_t x, int8_t r)\n{\n\treturn (x << r) | (x >> (64 - r));\n}\n\nJEMALLOC_INLINE uint32_t\nhash_get_block_32(const uint32_t *p, int i)\n{\n\n\treturn (p[i]);\n}\n\nJEMALLOC_INLINE uint64_t\nhash_get_block_64(const uint64_t *p, int i)\n{\n\n\treturn (p[i]);\n}\n\nJEMALLOC_INLINE uint32_t\nhash_fmix_32(uint32_t h)\n{\n\n\th ^= h >> 16;\n\th *= 0x85ebca6b;\n\th ^= h >> 13;\n\th *= 0xc2b2ae35;\n\th ^= h >> 16;\n\n\treturn (h);\n}\n\nJEMALLOC_INLINE uint64_t\nhash_fmix_64(uint64_t k)\n{\n\n\tk ^= k >> 33;\n\tk *= QU(0xff51afd7ed558ccdLLU);\n\tk ^= k >> 33;\n\tk *= QU(0xc4ceb9fe1a85ec53LLU);\n\tk ^= k >> 33;\n\n\treturn (k);\n}\n\nJEMALLOC_INLINE uint32_t\nhash_x86_32(const void *key, int len, uint32_t seed)\n{\n\tconst uint8_t *data = (const uint8_t *) key;\n\tconst int nblocks = len / 4;\n\n\tuint32_t h1 = seed;\n\n\tconst uint32_t c1 = 0xcc9e2d51;\n\tconst uint32_t c2 = 0x1b873593;\n\n\t/* body */\n\t{\n\t\tconst uint32_t *blocks = (const uint32_t *) (data + nblocks*4);\n\t\tint i;\n\n\t\tfor (i = -nblocks; i; i++) {\n\t\t\tuint32_t k1 = hash_get_block_32(blocks, i);\n\n\t\t\tk1 *= c1;\n\t\t\tk1 = hash_rotl_32(k1, 15);\n\t\t\tk1 *= c2;\n\n\t\t\th1 ^= k1;\n\t\t\th1 = hash_rotl_32(h1, 13);\n\t\t\th1 = h1*5 + 0xe6546b64;\n\t\t}\n\t}\n\n\t/* tail */\n\t{\n\t\tconst uint8_t *tail = (const uint8_t *) (data + nblocks*4);\n\n\t\tuint32_t k1 = 0;\n\n\t\tswitch (len & 3) {\n\t\tcase 3: k1 ^= tail[2] << 16;\n\t\tcase 2: k1 ^= tail[1] << 8;\n\t\tcase 1: k1 ^= tail[0]; k1 *= c1; k1 = hash_rotl_32(k1, 15);\n\t\t\tk1 *= c2; h1 ^= k1;\n\t\t}\n\t}\n\n\t/* finalization */\n\th1 ^= len;\n\n\th1 = hash_fmix_32(h1);\n\n\treturn (h1);\n}\n\nUNUSED JEMALLOC_INLINE void\nhash_x86_128(const void *key, const int len, uint32_t seed,\n    uint64_t r_out[2])\n{\n\tconst uint8_t * data = (const uint8_t *) key;\n\tconst int nblocks = len / 16;\n\n\tuint32_t h1 = seed;\n\tuint32_t h2 = seed;\n\tuint32_t h3 = seed;\n\tuint32_t h4 = seed;\n\n\tconst uint32_t c1 = 0x239b961b;\n\tconst uint32_t c2 = 0xab0e9789;\n\tconst uint32_t c3 = 0x38b34ae5;\n\tconst uint32_t c4 = 0xa1e38b93;\n\n\t/* body */\n\t{\n\t\tconst uint32_t *blocks = (const uint32_t *) (data + nblocks*16);\n\t\tint i;\n\n\t\tfor (i = -nblocks; i; i++) {\n\t\t\tuint32_t k1 = hash_get_block_32(blocks, i*4 + 0);\n\t\t\tuint32_t k2 = hash_get_block_32(blocks, i*4 + 1);\n\t\t\tuint32_t k3 = hash_get_block_32(blocks, i*4 + 2);\n\t\t\tuint32_t k4 = hash_get_block_32(blocks, i*4 + 3);\n\n\t\t\tk1 *= c1; k1 = hash_rotl_32(k1, 15); k1 *= c2; h1 ^= k1;\n\n\t\t\th1 = hash_rotl_32(h1, 19); h1 += h2;\n\t\t\th1 = h1*5 + 0x561ccd1b;\n\n\t\t\tk2 *= c2; k2 = hash_rotl_32(k2, 16); k2 *= c3; h2 ^= k2;\n\n\t\t\th2 = hash_rotl_32(h2, 17); h2 += h3;\n\t\t\th2 = h2*5 + 0x0bcaa747;\n\n\t\t\tk3 *= c3; k3 = hash_rotl_32(k3, 17); k3 *= c4; h3 ^= k3;\n\n\t\t\th3 = hash_rotl_32(h3, 15); h3 += h4;\n\t\t\th3 = h3*5 + 0x96cd1c35;\n\n\t\t\tk4 *= c4; k4 = hash_rotl_32(k4, 18); k4 *= c1; h4 ^= k4;\n\n\t\t\th4 = hash_rotl_32(h4, 13); h4 += h1;\n\t\t\th4 = h4*5 + 0x32ac3b17;\n\t\t}\n\t}\n\n\t/* tail */\n\t{\n\t\tconst uint8_t *tail = (const uint8_t *) (data + nblocks*16);\n\t\tuint32_t k1 = 0;\n\t\tuint32_t k2 = 0;\n\t\tuint32_t k3 = 0;\n\t\tuint32_t k4 = 0;\n\n\t\tswitch (len & 15) {\n\t\tcase 15: k4 ^= tail[14] << 16;\n\t\tcase 14: k4 ^= tail[13] << 8;\n\t\tcase 13: k4 ^= tail[12] << 0;\n\t\t\tk4 *= c4; k4 = hash_rotl_32(k4, 18); k4 *= c1; h4 ^= k4;\n\n\t\tcase 12: k3 ^= tail[11] << 24;\n\t\tcase 11: k3 ^= tail[10] << 16;\n\t\tcase 10: k3 ^= tail[ 9] << 8;\n\t\tcase  9: k3 ^= tail[ 8] << 0;\n\t\t     k3 *= c3; k3 = hash_rotl_32(k3, 17); k3 *= c4; h3 ^= k3;\n\n\t\tcase  8: k2 ^= tail[ 7] << 24;\n\t\tcase  7: k2 ^= tail[ 6] << 16;\n\t\tcase  6: k2 ^= tail[ 5] << 8;\n\t\tcase  5: k2 ^= tail[ 4] << 0;\n\t\t\tk2 *= c2; k2 = hash_rotl_32(k2, 16); k2 *= c3; h2 ^= k2;\n\n\t\tcase  4: k1 ^= tail[ 3] << 24;\n\t\tcase  3: k1 ^= tail[ 2] << 16;\n\t\tcase  2: k1 ^= tail[ 1] << 8;\n\t\tcase  1: k1 ^= tail[ 0] << 0;\n\t\t\tk1 *= c1; k1 = hash_rotl_32(k1, 15); k1 *= c2; h1 ^= k1;\n\t\t}\n\t}\n\n\t/* finalization */\n\th1 ^= len; h2 ^= len; h3 ^= len; h4 ^= len;\n\n\th1 += h2; h1 += h3; h1 += h4;\n\th2 += h1; h3 += h1; h4 += h1;\n\n\th1 = hash_fmix_32(h1);\n\th2 = hash_fmix_32(h2);\n\th3 = hash_fmix_32(h3);\n\th4 = hash_fmix_32(h4);\n\n\th1 += h2; h1 += h3; h1 += h4;\n\th2 += h1; h3 += h1; h4 += h1;\n\n\tr_out[0] = (((uint64_t) h2) << 32) | h1;\n\tr_out[1] = (((uint64_t) h4) << 32) | h3;\n}\n\nUNUSED JEMALLOC_INLINE void\nhash_x64_128(const void *key, const int len, const uint32_t seed,\n    uint64_t r_out[2])\n{\n\tconst uint8_t *data = (const uint8_t *) key;\n\tconst int nblocks = len / 16;\n\n\tuint64_t h1 = seed;\n\tuint64_t h2 = seed;\n\n\tconst uint64_t c1 = QU(0x87c37b91114253d5LLU);\n\tconst uint64_t c2 = QU(0x4cf5ad432745937fLLU);\n\n\t/* body */\n\t{\n\t\tconst uint64_t *blocks = (const uint64_t *) (data);\n\t\tint i;\n\n\t\tfor (i = 0; i < nblocks; i++) {\n\t\t\tuint64_t k1 = hash_get_block_64(blocks, i*2 + 0);\n\t\t\tuint64_t k2 = hash_get_block_64(blocks, i*2 + 1);\n\n\t\t\tk1 *= c1; k1 = hash_rotl_64(k1, 31); k1 *= c2; h1 ^= k1;\n\n\t\t\th1 = hash_rotl_64(h1, 27); h1 += h2;\n\t\t\th1 = h1*5 + 0x52dce729;\n\n\t\t\tk2 *= c2; k2 = hash_rotl_64(k2, 33); k2 *= c1; h2 ^= k2;\n\n\t\t\th2 = hash_rotl_64(h2, 31); h2 += h1;\n\t\t\th2 = h2*5 + 0x38495ab5;\n\t\t}\n\t}\n\n\t/* tail */\n\t{\n\t\tconst uint8_t *tail = (const uint8_t*)(data + nblocks*16);\n\t\tuint64_t k1 = 0;\n\t\tuint64_t k2 = 0;\n\n\t\tswitch (len & 15) {\n\t\tcase 15: k2 ^= ((uint64_t)(tail[14])) << 48;\n\t\tcase 14: k2 ^= ((uint64_t)(tail[13])) << 40;\n\t\tcase 13: k2 ^= ((uint64_t)(tail[12])) << 32;\n\t\tcase 12: k2 ^= ((uint64_t)(tail[11])) << 24;\n\t\tcase 11: k2 ^= ((uint64_t)(tail[10])) << 16;\n\t\tcase 10: k2 ^= ((uint64_t)(tail[ 9])) << 8;\n\t\tcase  9: k2 ^= ((uint64_t)(tail[ 8])) << 0;\n\t\t\tk2 *= c2; k2 = hash_rotl_64(k2, 33); k2 *= c1; h2 ^= k2;\n\n\t\tcase  8: k1 ^= ((uint64_t)(tail[ 7])) << 56;\n\t\tcase  7: k1 ^= ((uint64_t)(tail[ 6])) << 48;\n\t\tcase  6: k1 ^= ((uint64_t)(tail[ 5])) << 40;\n\t\tcase  5: k1 ^= ((uint64_t)(tail[ 4])) << 32;\n\t\tcase  4: k1 ^= ((uint64_t)(tail[ 3])) << 24;\n\t\tcase  3: k1 ^= ((uint64_t)(tail[ 2])) << 16;\n\t\tcase  2: k1 ^= ((uint64_t)(tail[ 1])) << 8;\n\t\tcase  1: k1 ^= ((uint64_t)(tail[ 0])) << 0;\n\t\t\tk1 *= c1; k1 = hash_rotl_64(k1, 31); k1 *= c2; h1 ^= k1;\n\t\t}\n\t}\n\n\t/* finalization */\n\th1 ^= len; h2 ^= len;\n\n\th1 += h2;\n\th2 += h1;\n\n\th1 = hash_fmix_64(h1);\n\th2 = hash_fmix_64(h2);\n\n\th1 += h2;\n\th2 += h1;\n\n\tr_out[0] = h1;\n\tr_out[1] = h2;\n}\n\n/******************************************************************************/\n/* API. */\nJEMALLOC_INLINE void\nhash(const void *key, size_t len, const uint32_t seed, size_t r_hash[2])\n{\n#if (LG_SIZEOF_PTR == 3 && !defined(JEMALLOC_BIG_ENDIAN))\n\thash_x64_128(key, len, seed, (uint64_t *)r_hash);\n#else\n\tuint64_t hashes[2];\n\thash_x86_128(key, len, seed, hashes);\n\tr_hash[0] = (size_t)hashes[0];\n\tr_hash[1] = (size_t)hashes[1];\n#endif\n}\n#endif\n\n#endif /* JEMALLOC_H_INLINES */\n/******************************************************************************/\n"
  },
  {
    "path": "extern/deprecated/redis-2.8.21/deps/jemalloc/include/jemalloc/internal/huge.h",
    "content": "/******************************************************************************/\n#ifdef JEMALLOC_H_TYPES\n\n#endif /* JEMALLOC_H_TYPES */\n/******************************************************************************/\n#ifdef JEMALLOC_H_STRUCTS\n\n#endif /* JEMALLOC_H_STRUCTS */\n/******************************************************************************/\n#ifdef JEMALLOC_H_EXTERNS\n\n/* Huge allocation statistics. */\nextern uint64_t\t\thuge_nmalloc;\nextern uint64_t\t\thuge_ndalloc;\nextern size_t\t\thuge_allocated;\n\n/* Protects chunk-related data structures. */\nextern malloc_mutex_t\thuge_mtx;\n\nvoid\t*huge_malloc(size_t size, bool zero, dss_prec_t dss_prec);\nvoid\t*huge_palloc(size_t size, size_t alignment, bool zero,\n    dss_prec_t dss_prec);\nbool\thuge_ralloc_no_move(void *ptr, size_t oldsize, size_t size,\n    size_t extra);\nvoid\t*huge_ralloc(void *ptr, size_t oldsize, size_t size, size_t extra,\n    size_t alignment, bool zero, bool try_tcache_dalloc, dss_prec_t dss_prec);\n#ifdef JEMALLOC_JET\ntypedef void (huge_dalloc_junk_t)(void *, size_t);\nextern huge_dalloc_junk_t *huge_dalloc_junk;\n#endif\nvoid\thuge_dalloc(void *ptr, bool unmap);\nsize_t\thuge_salloc(const void *ptr);\ndss_prec_t\thuge_dss_prec_get(arena_t *arena);\nprof_ctx_t\t*huge_prof_ctx_get(const void *ptr);\nvoid\thuge_prof_ctx_set(const void *ptr, prof_ctx_t *ctx);\nbool\thuge_boot(void);\nvoid\thuge_prefork(void);\nvoid\thuge_postfork_parent(void);\nvoid\thuge_postfork_child(void);\n\n#endif /* JEMALLOC_H_EXTERNS */\n/******************************************************************************/\n#ifdef JEMALLOC_H_INLINES\n\n#endif /* JEMALLOC_H_INLINES */\n/******************************************************************************/\n"
  },
  {
    "path": "extern/deprecated/redis-2.8.21/deps/jemalloc/include/jemalloc/internal/jemalloc_internal.h.in",
    "content": "#ifndef JEMALLOC_INTERNAL_H\n#define\tJEMALLOC_INTERNAL_H\n#include <math.h>\n#ifdef _WIN32\n#  include <windows.h>\n#  define ENOENT ERROR_PATH_NOT_FOUND\n#  define EINVAL ERROR_BAD_ARGUMENTS\n#  define EAGAIN ERROR_OUTOFMEMORY\n#  define EPERM  ERROR_WRITE_FAULT\n#  define EFAULT ERROR_INVALID_ADDRESS\n#  define ENOMEM ERROR_NOT_ENOUGH_MEMORY\n#  undef ERANGE\n#  define ERANGE ERROR_INVALID_DATA\n#else\n#  include <sys/param.h>\n#  include <sys/mman.h>\n#  include <sys/syscall.h>\n#  if !defined(SYS_write) && defined(__NR_write)\n#    define SYS_write __NR_write\n#  endif\n#  include <sys/uio.h>\n#  include <pthread.h>\n#  include <errno.h>\n#endif\n#include <sys/types.h>\n\n#include <limits.h>\n#ifndef SIZE_T_MAX\n#  define SIZE_T_MAX\tSIZE_MAX\n#endif\n#include <stdarg.h>\n#include <stdbool.h>\n#include <stdio.h>\n#include <stdlib.h>\n#include <stdint.h>\n#include <stddef.h>\n#ifndef offsetof\n#  define offsetof(type, member)\t((size_t)&(((type *)NULL)->member))\n#endif\n#include <inttypes.h>\n#include <string.h>\n#include <strings.h>\n#include <ctype.h>\n#ifdef _MSC_VER\n#  include <io.h>\ntypedef intptr_t ssize_t;\n#  define PATH_MAX 1024\n#  define STDERR_FILENO 2\n#  define __func__ __FUNCTION__\n/* Disable warnings about deprecated system functions */\n#  pragma warning(disable: 4996)\n#else\n#  include <unistd.h>\n#endif\n#include <fcntl.h>\n\n#include \"jemalloc_internal_defs.h\"\n\n#ifdef JEMALLOC_UTRACE\n#include <sys/ktrace.h>\n#endif\n\n#ifdef JEMALLOC_VALGRIND\n#include <valgrind/valgrind.h>\n#include <valgrind/memcheck.h>\n#endif\n\n#define\tJEMALLOC_NO_DEMANGLE\n#ifdef JEMALLOC_JET\n#  define JEMALLOC_N(n) jet_##n\n#  include \"jemalloc/internal/public_namespace.h\"\n#  define JEMALLOC_NO_RENAME\n#  include \"../jemalloc@install_suffix@.h\"\n#  undef JEMALLOC_NO_RENAME\n#else\n#  define JEMALLOC_N(n) @private_namespace@##n\n#  include \"../jemalloc@install_suffix@.h\"\n#endif\n#include \"jemalloc/internal/private_namespace.h\"\n\nstatic const bool config_debug =\n#ifdef JEMALLOC_DEBUG\n    true\n#else\n    false\n#endif\n    ;\nstatic const bool config_dss =\n#ifdef JEMALLOC_DSS\n    true\n#else\n    false\n#endif\n    ;\nstatic const bool config_fill =\n#ifdef JEMALLOC_FILL\n    true\n#else\n    false\n#endif\n    ;\nstatic const bool config_lazy_lock =\n#ifdef JEMALLOC_LAZY_LOCK\n    true\n#else\n    false\n#endif\n    ;\nstatic const bool config_prof =\n#ifdef JEMALLOC_PROF\n    true\n#else\n    false\n#endif\n    ;\nstatic const bool config_prof_libgcc =\n#ifdef JEMALLOC_PROF_LIBGCC\n    true\n#else\n    false\n#endif\n    ;\nstatic const bool config_prof_libunwind =\n#ifdef JEMALLOC_PROF_LIBUNWIND\n    true\n#else\n    false\n#endif\n    ;\nstatic const bool config_mremap =\n#ifdef JEMALLOC_MREMAP\n    true\n#else\n    false\n#endif\n    ;\nstatic const bool config_munmap =\n#ifdef JEMALLOC_MUNMAP\n    true\n#else\n    false\n#endif\n    ;\nstatic const bool config_stats =\n#ifdef JEMALLOC_STATS\n    true\n#else\n    false\n#endif\n    ;\nstatic const bool config_tcache =\n#ifdef JEMALLOC_TCACHE\n    true\n#else\n    false\n#endif\n    ;\nstatic const bool config_tls =\n#ifdef JEMALLOC_TLS\n    true\n#else\n    false\n#endif\n    ;\nstatic const bool config_utrace =\n#ifdef JEMALLOC_UTRACE\n    true\n#else\n    false\n#endif\n    ;\nstatic const bool config_valgrind =\n#ifdef JEMALLOC_VALGRIND\n    true\n#else\n    false\n#endif\n    ;\nstatic const bool config_xmalloc =\n#ifdef JEMALLOC_XMALLOC\n    true\n#else\n    false\n#endif\n    ;\nstatic const bool config_ivsalloc =\n#ifdef JEMALLOC_IVSALLOC\n    true\n#else\n    false\n#endif\n    ;\n\n#ifdef JEMALLOC_ATOMIC9\n#include <machine/atomic.h>\n#endif\n\n#if (defined(JEMALLOC_OSATOMIC) || defined(JEMALLOC_OSSPIN))\n#include <libkern/OSAtomic.h>\n#endif\n\n#ifdef JEMALLOC_ZONE\n#include <mach/mach_error.h>\n#include <mach/mach_init.h>\n#include <mach/vm_map.h>\n#include <malloc/malloc.h>\n#endif\n\n#define\tRB_COMPACT\n#include \"jemalloc/internal/rb.h\"\n#include \"jemalloc/internal/qr.h\"\n#include \"jemalloc/internal/ql.h\"\n\n/*\n * jemalloc can conceptually be broken into components (arena, tcache, etc.),\n * but there are circular dependencies that cannot be broken without\n * substantial performance degradation.  In order to reduce the effect on\n * visual code flow, read the header files in multiple passes, with one of the\n * following cpp variables defined during each pass:\n *\n *   JEMALLOC_H_TYPES   : Preprocessor-defined constants and psuedo-opaque data\n *                        types.\n *   JEMALLOC_H_STRUCTS : Data structures.\n *   JEMALLOC_H_EXTERNS : Extern data declarations and function prototypes.\n *   JEMALLOC_H_INLINES : Inline functions.\n */\n/******************************************************************************/\n#define\tJEMALLOC_H_TYPES\n\n#include \"jemalloc/internal/jemalloc_internal_macros.h\"\n\n#define\tMALLOCX_LG_ALIGN_MASK\t((int)0x3f)\n#define\tALLOCM_LG_ALIGN_MASK\t((int)0x3f)\n\n/* Smallest size class to support. */\n#define\tLG_TINY_MIN\t\t3\n#define\tTINY_MIN\t\t(1U << LG_TINY_MIN)\n\n/*\n * Minimum alignment of allocations is 2^LG_QUANTUM bytes (ignoring tiny size\n * classes).\n */\n#ifndef LG_QUANTUM\n#  if (defined(__i386__) || defined(_M_IX86))\n#    define LG_QUANTUM\t\t4\n#  endif\n#  ifdef __ia64__\n#    define LG_QUANTUM\t\t4\n#  endif\n#  ifdef __alpha__\n#    define LG_QUANTUM\t\t4\n#  endif\n#  ifdef __sparc64__\n#    define LG_QUANTUM\t\t4\n#  endif\n#  if (defined(__amd64__) || defined(__x86_64__) || defined(_M_X64))\n#    define LG_QUANTUM\t\t4\n#  endif\n#  ifdef __arm__\n#    define LG_QUANTUM\t\t3\n#  endif\n#  ifdef __aarch64__\n#    define LG_QUANTUM\t\t4\n#  endif\n#  ifdef __hppa__\n#    define LG_QUANTUM\t\t4\n#  endif\n#  ifdef __mips__\n#    define LG_QUANTUM\t\t3\n#  endif\n#  ifdef __powerpc__\n#    define LG_QUANTUM\t\t4\n#  endif\n#  ifdef __s390__\n#    define LG_QUANTUM\t\t4\n#  endif\n#  ifdef __SH4__\n#    define LG_QUANTUM\t\t4\n#  endif\n#  ifdef __tile__\n#    define LG_QUANTUM\t\t4\n#  endif\n#  ifndef LG_QUANTUM\n#    error \"No LG_QUANTUM definition for architecture; specify via CPPFLAGS\"\n#  endif\n#endif\n\n#define\tQUANTUM\t\t\t((size_t)(1U << LG_QUANTUM))\n#define\tQUANTUM_MASK\t\t(QUANTUM - 1)\n\n/* Return the smallest quantum multiple that is >= a. */\n#define\tQUANTUM_CEILING(a)\t\t\t\t\t\t\\\n\t(((a) + QUANTUM_MASK) & ~QUANTUM_MASK)\n\n#define\tLONG\t\t\t((size_t)(1U << LG_SIZEOF_LONG))\n#define\tLONG_MASK\t\t(LONG - 1)\n\n/* Return the smallest long multiple that is >= a. */\n#define\tLONG_CEILING(a)\t\t\t\t\t\t\t\\\n\t(((a) + LONG_MASK) & ~LONG_MASK)\n\n#define\tSIZEOF_PTR\t\t(1U << LG_SIZEOF_PTR)\n#define\tPTR_MASK\t\t(SIZEOF_PTR - 1)\n\n/* Return the smallest (void *) multiple that is >= a. */\n#define\tPTR_CEILING(a)\t\t\t\t\t\t\t\\\n\t(((a) + PTR_MASK) & ~PTR_MASK)\n\n/*\n * Maximum size of L1 cache line.  This is used to avoid cache line aliasing.\n * In addition, this controls the spacing of cacheline-spaced size classes.\n *\n * CACHELINE cannot be based on LG_CACHELINE because __declspec(align()) can\n * only handle raw constants.\n */\n#define\tLG_CACHELINE\t\t6\n#define\tCACHELINE\t\t64\n#define\tCACHELINE_MASK\t\t(CACHELINE - 1)\n\n/* Return the smallest cacheline multiple that is >= s. */\n#define\tCACHELINE_CEILING(s)\t\t\t\t\t\t\\\n\t(((s) + CACHELINE_MASK) & ~CACHELINE_MASK)\n\n/* Page size.  STATIC_PAGE_SHIFT is determined by the configure script. */\n#ifdef PAGE_MASK\n#  undef PAGE_MASK\n#endif\n#define\tLG_PAGE\t\tSTATIC_PAGE_SHIFT\n#define\tPAGE\t\t((size_t)(1U << STATIC_PAGE_SHIFT))\n#define\tPAGE_MASK\t((size_t)(PAGE - 1))\n\n/* Return the smallest pagesize multiple that is >= s. */\n#define\tPAGE_CEILING(s)\t\t\t\t\t\t\t\\\n\t(((s) + PAGE_MASK) & ~PAGE_MASK)\n\n/* Return the nearest aligned address at or below a. */\n#define\tALIGNMENT_ADDR2BASE(a, alignment)\t\t\t\t\\\n\t((void *)((uintptr_t)(a) & (-(alignment))))\n\n/* Return the offset between a and the nearest aligned address at or below a. */\n#define\tALIGNMENT_ADDR2OFFSET(a, alignment)\t\t\t\t\\\n\t((size_t)((uintptr_t)(a) & (alignment - 1)))\n\n/* Return the smallest alignment multiple that is >= s. */\n#define\tALIGNMENT_CEILING(s, alignment)\t\t\t\t\t\\\n\t(((s) + (alignment - 1)) & (-(alignment)))\n\n/* Declare a variable length array */\n#if __STDC_VERSION__ < 199901L\n#  ifdef _MSC_VER\n#    include <malloc.h>\n#    define alloca _alloca\n#  else\n#    ifdef JEMALLOC_HAS_ALLOCA_H\n#      include <alloca.h>\n#    else\n#      include <stdlib.h>\n#    endif\n#  endif\n#  define VARIABLE_ARRAY(type, name, count) \\\n\ttype *name = alloca(sizeof(type) * count)\n#else\n#  define VARIABLE_ARRAY(type, name, count) type name[count]\n#endif\n\n#ifdef JEMALLOC_VALGRIND\n/*\n * The JEMALLOC_VALGRIND_*() macros must be macros rather than functions\n * so that when Valgrind reports errors, there are no extra stack frames\n * in the backtraces.\n *\n * The size that is reported to valgrind must be consistent through a chain of\n * malloc..realloc..realloc calls.  Request size isn't recorded anywhere in\n * jemalloc, so it is critical that all callers of these macros provide usize\n * rather than request size.  As a result, buffer overflow detection is\n * technically weakened for the standard API, though it is generally accepted\n * practice to consider any extra bytes reported by malloc_usable_size() as\n * usable space.\n */\n#define\tJEMALLOC_VALGRIND_MALLOC(cond, ptr, usize, zero) do {\t\t\\\n\tif (config_valgrind && opt_valgrind && cond)\t\t\t\\\n\t\tVALGRIND_MALLOCLIKE_BLOCK(ptr, usize, p2rz(ptr), zero);\t\\\n} while (0)\n#define\tJEMALLOC_VALGRIND_REALLOC(ptr, usize, old_ptr, old_usize,\t\\\n    old_rzsize, zero)  do {\t\t\t\t\t\t\\\n\tif (config_valgrind && opt_valgrind) {\t\t\t\t\\\n\t\tsize_t rzsize = p2rz(ptr);\t\t\t\t\\\n\t\t\t\t\t\t\t\t\t\\\n\t\tif (ptr == old_ptr) {\t\t\t\t\t\\\n\t\t\tVALGRIND_RESIZEINPLACE_BLOCK(ptr, old_usize,\t\\\n\t\t\t    usize, rzsize);\t\t\t\t\\\n\t\t\tif (zero && old_usize < usize) {\t\t\\\n\t\t\t\tVALGRIND_MAKE_MEM_DEFINED(\t\t\\\n\t\t\t\t    (void *)((uintptr_t)ptr +\t\t\\\n\t\t\t\t    old_usize), usize - old_usize);\t\\\n\t\t\t}\t\t\t\t\t\t\\\n\t\t} else {\t\t\t\t\t\t\\\n\t\t\tif (old_ptr != NULL) {\t\t\t\t\\\n\t\t\t\tVALGRIND_FREELIKE_BLOCK(old_ptr,\t\\\n\t\t\t\t    old_rzsize);\t\t\t\\\n\t\t\t}\t\t\t\t\t\t\\\n\t\t\tif (ptr != NULL) {\t\t\t\t\\\n\t\t\t\tsize_t copy_size = (old_usize < usize)\t\\\n\t\t\t\t    ?  old_usize : usize;\t\t\\\n\t\t\t\tsize_t tail_size = usize - copy_size;\t\\\n\t\t\t\tVALGRIND_MALLOCLIKE_BLOCK(ptr, usize,\t\\\n\t\t\t\t    rzsize, false);\t\t\t\\\n\t\t\t\tif (copy_size > 0) {\t\t\t\\\n\t\t\t\t\tVALGRIND_MAKE_MEM_DEFINED(ptr,\t\\\n\t\t\t\t\t    copy_size);\t\t\t\\\n\t\t\t\t}\t\t\t\t\t\\\n\t\t\t\tif (zero && tail_size > 0) {\t\t\\\n\t\t\t\t\tVALGRIND_MAKE_MEM_DEFINED(\t\\\n\t\t\t\t\t    (void *)((uintptr_t)ptr +\t\\\n\t\t\t\t\t    copy_size), tail_size);\t\\\n\t\t\t\t}\t\t\t\t\t\\\n\t\t\t}\t\t\t\t\t\t\\\n\t\t}\t\t\t\t\t\t\t\\\n\t}\t\t\t\t\t\t\t\t\\\n} while (0)\n#define\tJEMALLOC_VALGRIND_FREE(ptr, rzsize) do {\t\t\t\\\n\tif (config_valgrind && opt_valgrind)\t\t\t\t\\\n\t\tVALGRIND_FREELIKE_BLOCK(ptr, rzsize);\t\t\t\\\n} while (0)\n#else\n#define\tRUNNING_ON_VALGRIND\t((unsigned)0)\n#define\tVALGRIND_MALLOCLIKE_BLOCK(addr, sizeB, rzB, is_zeroed) \\\n    do {} while (0)\n#define\tVALGRIND_RESIZEINPLACE_BLOCK(addr, oldSizeB, newSizeB, rzB) \\\n    do {} while (0)\n#define\tVALGRIND_FREELIKE_BLOCK(addr, rzB) do {} while (0)\n#define\tVALGRIND_MAKE_MEM_NOACCESS(_qzz_addr, _qzz_len) do {} while (0)\n#define\tVALGRIND_MAKE_MEM_UNDEFINED(_qzz_addr, _qzz_len) do {} while (0)\n#define\tVALGRIND_MAKE_MEM_DEFINED(_qzz_addr, _qzz_len) do {} while (0)\n#define\tJEMALLOC_VALGRIND_MALLOC(cond, ptr, usize, zero) do {} while (0)\n#define\tJEMALLOC_VALGRIND_REALLOC(ptr, usize, old_ptr, old_usize,\t\\\n    old_rzsize, zero) do {} while (0)\n#define\tJEMALLOC_VALGRIND_FREE(ptr, rzsize) do {} while (0)\n#endif\n\n#include \"jemalloc/internal/util.h\"\n#include \"jemalloc/internal/atomic.h\"\n#include \"jemalloc/internal/prng.h\"\n#include \"jemalloc/internal/ckh.h\"\n#include \"jemalloc/internal/size_classes.h\"\n#include \"jemalloc/internal/stats.h\"\n#include \"jemalloc/internal/ctl.h\"\n#include \"jemalloc/internal/mutex.h\"\n#include \"jemalloc/internal/tsd.h\"\n#include \"jemalloc/internal/mb.h\"\n#include \"jemalloc/internal/extent.h\"\n#include \"jemalloc/internal/arena.h\"\n#include \"jemalloc/internal/bitmap.h\"\n#include \"jemalloc/internal/base.h\"\n#include \"jemalloc/internal/chunk.h\"\n#include \"jemalloc/internal/huge.h\"\n#include \"jemalloc/internal/rtree.h\"\n#include \"jemalloc/internal/tcache.h\"\n#include \"jemalloc/internal/hash.h\"\n#include \"jemalloc/internal/quarantine.h\"\n#include \"jemalloc/internal/prof.h\"\n\n#undef JEMALLOC_H_TYPES\n/******************************************************************************/\n#define\tJEMALLOC_H_STRUCTS\n\n#include \"jemalloc/internal/util.h\"\n#include \"jemalloc/internal/atomic.h\"\n#include \"jemalloc/internal/prng.h\"\n#include \"jemalloc/internal/ckh.h\"\n#include \"jemalloc/internal/size_classes.h\"\n#include \"jemalloc/internal/stats.h\"\n#include \"jemalloc/internal/ctl.h\"\n#include \"jemalloc/internal/mutex.h\"\n#include \"jemalloc/internal/tsd.h\"\n#include \"jemalloc/internal/mb.h\"\n#include \"jemalloc/internal/bitmap.h\"\n#include \"jemalloc/internal/extent.h\"\n#include \"jemalloc/internal/arena.h\"\n#include \"jemalloc/internal/base.h\"\n#include \"jemalloc/internal/chunk.h\"\n#include \"jemalloc/internal/huge.h\"\n#include \"jemalloc/internal/rtree.h\"\n#include \"jemalloc/internal/tcache.h\"\n#include \"jemalloc/internal/hash.h\"\n#include \"jemalloc/internal/quarantine.h\"\n#include \"jemalloc/internal/prof.h\"\n\ntypedef struct {\n\tuint64_t\tallocated;\n\tuint64_t\tdeallocated;\n} thread_allocated_t;\n/*\n * The JEMALLOC_ARG_CONCAT() wrapper is necessary to pass {0, 0} via a cpp macro\n * argument.\n */\n#define\tTHREAD_ALLOCATED_INITIALIZER\tJEMALLOC_ARG_CONCAT({0, 0})\n\n#undef JEMALLOC_H_STRUCTS\n/******************************************************************************/\n#define\tJEMALLOC_H_EXTERNS\n\nextern bool\topt_abort;\nextern bool\topt_junk;\nextern size_t\topt_quarantine;\nextern bool\topt_redzone;\nextern bool\topt_utrace;\nextern bool\topt_valgrind;\nextern bool\topt_xmalloc;\nextern bool\topt_zero;\nextern size_t\topt_narenas;\n\n/* Number of CPUs. */\nextern unsigned\t\tncpus;\n\n/* Protects arenas initialization (arenas, arenas_total). */\nextern malloc_mutex_t\tarenas_lock;\n/*\n * Arenas that are used to service external requests.  Not all elements of the\n * arenas array are necessarily used; arenas are created lazily as needed.\n *\n * arenas[0..narenas_auto) are used for automatic multiplexing of threads and\n * arenas.  arenas[narenas_auto..narenas_total) are only used if the application\n * takes some action to create them and allocate from them.\n */\nextern arena_t\t\t**arenas;\nextern unsigned\t\tnarenas_total;\nextern unsigned\t\tnarenas_auto; /* Read-only after initialization. */\n\narena_t\t*arenas_extend(unsigned ind);\nvoid\tarenas_cleanup(void *arg);\narena_t\t*choose_arena_hard(void);\nvoid\tjemalloc_prefork(void);\nvoid\tjemalloc_postfork_parent(void);\nvoid\tjemalloc_postfork_child(void);\n\n#include \"jemalloc/internal/util.h\"\n#include \"jemalloc/internal/atomic.h\"\n#include \"jemalloc/internal/prng.h\"\n#include \"jemalloc/internal/ckh.h\"\n#include \"jemalloc/internal/size_classes.h\"\n#include \"jemalloc/internal/stats.h\"\n#include \"jemalloc/internal/ctl.h\"\n#include \"jemalloc/internal/mutex.h\"\n#include \"jemalloc/internal/tsd.h\"\n#include \"jemalloc/internal/mb.h\"\n#include \"jemalloc/internal/bitmap.h\"\n#include \"jemalloc/internal/extent.h\"\n#include \"jemalloc/internal/arena.h\"\n#include \"jemalloc/internal/base.h\"\n#include \"jemalloc/internal/chunk.h\"\n#include \"jemalloc/internal/huge.h\"\n#include \"jemalloc/internal/rtree.h\"\n#include \"jemalloc/internal/tcache.h\"\n#include \"jemalloc/internal/hash.h\"\n#include \"jemalloc/internal/quarantine.h\"\n#include \"jemalloc/internal/prof.h\"\n\n#undef JEMALLOC_H_EXTERNS\n/******************************************************************************/\n#define\tJEMALLOC_H_INLINES\n\n#include \"jemalloc/internal/util.h\"\n#include \"jemalloc/internal/atomic.h\"\n#include \"jemalloc/internal/prng.h\"\n#include \"jemalloc/internal/ckh.h\"\n#include \"jemalloc/internal/size_classes.h\"\n#include \"jemalloc/internal/stats.h\"\n#include \"jemalloc/internal/ctl.h\"\n#include \"jemalloc/internal/mutex.h\"\n#include \"jemalloc/internal/tsd.h\"\n#include \"jemalloc/internal/mb.h\"\n#include \"jemalloc/internal/extent.h\"\n#include \"jemalloc/internal/base.h\"\n#include \"jemalloc/internal/chunk.h\"\n#include \"jemalloc/internal/huge.h\"\n\n#ifndef JEMALLOC_ENABLE_INLINE\nmalloc_tsd_protos(JEMALLOC_ATTR(unused), arenas, arena_t *)\n\nsize_t\ts2u(size_t size);\nsize_t\tsa2u(size_t size, size_t alignment);\nunsigned\tnarenas_total_get(void);\narena_t\t*choose_arena(arena_t *arena);\n#endif\n\n#if (defined(JEMALLOC_ENABLE_INLINE) || defined(JEMALLOC_C_))\n/*\n * Map of pthread_self() --> arenas[???], used for selecting an arena to use\n * for allocations.\n */\nmalloc_tsd_externs(arenas, arena_t *)\nmalloc_tsd_funcs(JEMALLOC_ALWAYS_INLINE, arenas, arena_t *, NULL,\n    arenas_cleanup)\n\n/*\n * Compute usable size that would result from allocating an object with the\n * specified size.\n */\nJEMALLOC_ALWAYS_INLINE size_t\ns2u(size_t size)\n{\n\n\tif (size <= SMALL_MAXCLASS)\n\t\treturn (arena_bin_info[SMALL_SIZE2BIN(size)].reg_size);\n\tif (size <= arena_maxclass)\n\t\treturn (PAGE_CEILING(size));\n\treturn (CHUNK_CEILING(size));\n}\n\n/*\n * Compute usable size that would result from allocating an object with the\n * specified size and alignment.\n */\nJEMALLOC_ALWAYS_INLINE size_t\nsa2u(size_t size, size_t alignment)\n{\n\tsize_t usize;\n\n\tassert(alignment != 0 && ((alignment - 1) & alignment) == 0);\n\n\t/*\n\t * Round size up to the nearest multiple of alignment.\n\t *\n\t * This done, we can take advantage of the fact that for each small\n\t * size class, every object is aligned at the smallest power of two\n\t * that is non-zero in the base two representation of the size.  For\n\t * example:\n\t *\n\t *   Size |   Base 2 | Minimum alignment\n\t *   -----+----------+------------------\n\t *     96 |  1100000 |  32\n\t *    144 | 10100000 |  32\n\t *    192 | 11000000 |  64\n\t */\n\tusize = ALIGNMENT_CEILING(size, alignment);\n\t/*\n\t * (usize < size) protects against the combination of maximal\n\t * alignment and size greater than maximal alignment.\n\t */\n\tif (usize < size) {\n\t\t/* size_t overflow. */\n\t\treturn (0);\n\t}\n\n\tif (usize <= arena_maxclass && alignment <= PAGE) {\n\t\tif (usize <= SMALL_MAXCLASS)\n\t\t\treturn (arena_bin_info[SMALL_SIZE2BIN(usize)].reg_size);\n\t\treturn (PAGE_CEILING(usize));\n\t} else {\n\t\tsize_t run_size;\n\n\t\t/*\n\t\t * We can't achieve subpage alignment, so round up alignment\n\t\t * permanently; it makes later calculations simpler.\n\t\t */\n\t\talignment = PAGE_CEILING(alignment);\n\t\tusize = PAGE_CEILING(size);\n\t\t/*\n\t\t * (usize < size) protects against very large sizes within\n\t\t * PAGE of SIZE_T_MAX.\n\t\t *\n\t\t * (usize + alignment < usize) protects against the\n\t\t * combination of maximal alignment and usize large enough\n\t\t * to cause overflow.  This is similar to the first overflow\n\t\t * check above, but it needs to be repeated due to the new\n\t\t * usize value, which may now be *equal* to maximal\n\t\t * alignment, whereas before we only detected overflow if the\n\t\t * original size was *greater* than maximal alignment.\n\t\t */\n\t\tif (usize < size || usize + alignment < usize) {\n\t\t\t/* size_t overflow. */\n\t\t\treturn (0);\n\t\t}\n\n\t\t/*\n\t\t * Calculate the size of the over-size run that arena_palloc()\n\t\t * would need to allocate in order to guarantee the alignment.\n\t\t * If the run wouldn't fit within a chunk, round up to a huge\n\t\t * allocation size.\n\t\t */\n\t\trun_size = usize + alignment - PAGE;\n\t\tif (run_size <= arena_maxclass)\n\t\t\treturn (PAGE_CEILING(usize));\n\t\treturn (CHUNK_CEILING(usize));\n\t}\n}\n\nJEMALLOC_INLINE unsigned\nnarenas_total_get(void)\n{\n\tunsigned narenas;\n\n\tmalloc_mutex_lock(&arenas_lock);\n\tnarenas = narenas_total;\n\tmalloc_mutex_unlock(&arenas_lock);\n\n\treturn (narenas);\n}\n\n/* Choose an arena based on a per-thread value. */\nJEMALLOC_INLINE arena_t *\nchoose_arena(arena_t *arena)\n{\n\tarena_t *ret;\n\n\tif (arena != NULL)\n\t\treturn (arena);\n\n\tif ((ret = *arenas_tsd_get()) == NULL) {\n\t\tret = choose_arena_hard();\n\t\tassert(ret != NULL);\n\t}\n\n\treturn (ret);\n}\n#endif\n\n#include \"jemalloc/internal/bitmap.h\"\n#include \"jemalloc/internal/rtree.h\"\n/*\n * Include arena.h twice in order to resolve circular dependencies with\n * tcache.h.\n */\n#define\tJEMALLOC_ARENA_INLINE_A\n#include \"jemalloc/internal/arena.h\"\n#undef JEMALLOC_ARENA_INLINE_A\n#include \"jemalloc/internal/tcache.h\"\n#define\tJEMALLOC_ARENA_INLINE_B\n#include \"jemalloc/internal/arena.h\"\n#undef JEMALLOC_ARENA_INLINE_B\n#include \"jemalloc/internal/hash.h\"\n#include \"jemalloc/internal/quarantine.h\"\n\n#ifndef JEMALLOC_ENABLE_INLINE\nvoid\t*imalloct(size_t size, bool try_tcache, arena_t *arena);\nvoid\t*imalloc(size_t size);\nvoid\t*icalloct(size_t size, bool try_tcache, arena_t *arena);\nvoid\t*icalloc(size_t size);\nvoid\t*ipalloct(size_t usize, size_t alignment, bool zero, bool try_tcache,\n    arena_t *arena);\nvoid\t*ipalloc(size_t usize, size_t alignment, bool zero);\nsize_t\tisalloc(const void *ptr, bool demote);\nsize_t\tivsalloc(const void *ptr, bool demote);\nsize_t\tu2rz(size_t usize);\nsize_t\tp2rz(const void *ptr);\nvoid\tidalloct(void *ptr, bool try_tcache);\nvoid\tidalloc(void *ptr);\nvoid\tiqalloct(void *ptr, bool try_tcache);\nvoid\tiqalloc(void *ptr);\nvoid\t*iralloct_realign(void *ptr, size_t oldsize, size_t size, size_t extra,\n    size_t alignment, bool zero, bool try_tcache_alloc, bool try_tcache_dalloc,\n    arena_t *arena);\nvoid\t*iralloct(void *ptr, size_t size, size_t extra, size_t alignment,\n    bool zero, bool try_tcache_alloc, bool try_tcache_dalloc, arena_t *arena);\nvoid\t*iralloc(void *ptr, size_t size, size_t extra, size_t alignment,\n    bool zero);\nbool\tixalloc(void *ptr, size_t size, size_t extra, size_t alignment,\n    bool zero);\nmalloc_tsd_protos(JEMALLOC_ATTR(unused), thread_allocated, thread_allocated_t)\n#endif\n\n#if (defined(JEMALLOC_ENABLE_INLINE) || defined(JEMALLOC_C_))\nJEMALLOC_ALWAYS_INLINE void *\nimalloct(size_t size, bool try_tcache, arena_t *arena)\n{\n\n\tassert(size != 0);\n\n\tif (size <= arena_maxclass)\n\t\treturn (arena_malloc(arena, size, false, try_tcache));\n\telse\n\t\treturn (huge_malloc(size, false, huge_dss_prec_get(arena)));\n}\n\nJEMALLOC_ALWAYS_INLINE void *\nimalloc(size_t size)\n{\n\n\treturn (imalloct(size, true, NULL));\n}\n\nJEMALLOC_ALWAYS_INLINE void *\nicalloct(size_t size, bool try_tcache, arena_t *arena)\n{\n\n\tif (size <= arena_maxclass)\n\t\treturn (arena_malloc(arena, size, true, try_tcache));\n\telse\n\t\treturn (huge_malloc(size, true, huge_dss_prec_get(arena)));\n}\n\nJEMALLOC_ALWAYS_INLINE void *\nicalloc(size_t size)\n{\n\n\treturn (icalloct(size, true, NULL));\n}\n\nJEMALLOC_ALWAYS_INLINE void *\nipalloct(size_t usize, size_t alignment, bool zero, bool try_tcache,\n    arena_t *arena)\n{\n\tvoid *ret;\n\n\tassert(usize != 0);\n\tassert(usize == sa2u(usize, alignment));\n\n\tif (usize <= arena_maxclass && alignment <= PAGE)\n\t\tret = arena_malloc(arena, usize, zero, try_tcache);\n\telse {\n\t\tif (usize <= arena_maxclass) {\n\t\t\tret = arena_palloc(choose_arena(arena), usize,\n\t\t\t    alignment, zero);\n\t\t} else if (alignment <= chunksize)\n\t\t\tret = huge_malloc(usize, zero, huge_dss_prec_get(arena));\n\t\telse\n\t\t\tret = huge_palloc(usize, alignment, zero, huge_dss_prec_get(arena));\n\t}\n\n\tassert(ALIGNMENT_ADDR2BASE(ret, alignment) == ret);\n\treturn (ret);\n}\n\nJEMALLOC_ALWAYS_INLINE void *\nipalloc(size_t usize, size_t alignment, bool zero)\n{\n\n\treturn (ipalloct(usize, alignment, zero, true, NULL));\n}\n\n/*\n * Typical usage:\n *   void *ptr = [...]\n *   size_t sz = isalloc(ptr, config_prof);\n */\nJEMALLOC_ALWAYS_INLINE size_t\nisalloc(const void *ptr, bool demote)\n{\n\tsize_t ret;\n\tarena_chunk_t *chunk;\n\n\tassert(ptr != NULL);\n\t/* Demotion only makes sense if config_prof is true. */\n\tassert(config_prof || demote == false);\n\n\tchunk = (arena_chunk_t *)CHUNK_ADDR2BASE(ptr);\n\tif (chunk != ptr)\n\t\tret = arena_salloc(ptr, demote);\n\telse\n\t\tret = huge_salloc(ptr);\n\n\treturn (ret);\n}\n\nJEMALLOC_ALWAYS_INLINE size_t\nivsalloc(const void *ptr, bool demote)\n{\n\n\t/* Return 0 if ptr is not within a chunk managed by jemalloc. */\n\tif (rtree_get(chunks_rtree, (uintptr_t)CHUNK_ADDR2BASE(ptr)) == 0)\n\t\treturn (0);\n\n\treturn (isalloc(ptr, demote));\n}\n\nJEMALLOC_INLINE size_t\nu2rz(size_t usize)\n{\n\tsize_t ret;\n\n\tif (usize <= SMALL_MAXCLASS) {\n\t\tsize_t binind = SMALL_SIZE2BIN(usize);\n\t\tret = arena_bin_info[binind].redzone_size;\n\t} else\n\t\tret = 0;\n\n\treturn (ret);\n}\n\nJEMALLOC_INLINE size_t\np2rz(const void *ptr)\n{\n\tsize_t usize = isalloc(ptr, false);\n\n\treturn (u2rz(usize));\n}\n\nJEMALLOC_ALWAYS_INLINE void\nidalloct(void *ptr, bool try_tcache)\n{\n\tarena_chunk_t *chunk;\n\n\tassert(ptr != NULL);\n\n\tchunk = (arena_chunk_t *)CHUNK_ADDR2BASE(ptr);\n\tif (chunk != ptr)\n\t\tarena_dalloc(chunk->arena, chunk, ptr, try_tcache);\n\telse\n\t\thuge_dalloc(ptr, true);\n}\n\nJEMALLOC_ALWAYS_INLINE void\nidalloc(void *ptr)\n{\n\n\tidalloct(ptr, true);\n}\n\nJEMALLOC_ALWAYS_INLINE void\niqalloct(void *ptr, bool try_tcache)\n{\n\n\tif (config_fill && opt_quarantine)\n\t\tquarantine(ptr);\n\telse\n\t\tidalloct(ptr, try_tcache);\n}\n\nJEMALLOC_ALWAYS_INLINE void\niqalloc(void *ptr)\n{\n\n\tiqalloct(ptr, true);\n}\n\nJEMALLOC_ALWAYS_INLINE void *\niralloct_realign(void *ptr, size_t oldsize, size_t size, size_t extra,\n    size_t alignment, bool zero, bool try_tcache_alloc, bool try_tcache_dalloc,\n    arena_t *arena)\n{\n\tvoid *p;\n\tsize_t usize, copysize;\n\n\tusize = sa2u(size + extra, alignment);\n\tif (usize == 0)\n\t\treturn (NULL);\n\tp = ipalloct(usize, alignment, zero, try_tcache_alloc, arena);\n\tif (p == NULL) {\n\t\tif (extra == 0)\n\t\t\treturn (NULL);\n\t\t/* Try again, without extra this time. */\n\t\tusize = sa2u(size, alignment);\n\t\tif (usize == 0)\n\t\t\treturn (NULL);\n\t\tp = ipalloct(usize, alignment, zero, try_tcache_alloc, arena);\n\t\tif (p == NULL)\n\t\t\treturn (NULL);\n\t}\n\t/*\n\t * Copy at most size bytes (not size+extra), since the caller has no\n\t * expectation that the extra bytes will be reliably preserved.\n\t */\n\tcopysize = (size < oldsize) ? size : oldsize;\n\tmemcpy(p, ptr, copysize);\n\tiqalloct(ptr, try_tcache_dalloc);\n\treturn (p);\n}\n\nJEMALLOC_ALWAYS_INLINE void *\niralloct(void *ptr, size_t size, size_t extra, size_t alignment, bool zero,\n    bool try_tcache_alloc, bool try_tcache_dalloc, arena_t *arena)\n{\n\tsize_t oldsize;\n\n\tassert(ptr != NULL);\n\tassert(size != 0);\n\n\toldsize = isalloc(ptr, config_prof);\n\n\tif (alignment != 0 && ((uintptr_t)ptr & ((uintptr_t)alignment-1))\n\t    != 0) {\n\t\t/*\n\t\t * Existing object alignment is inadequate; allocate new space\n\t\t * and copy.\n\t\t */\n\t\treturn (iralloct_realign(ptr, oldsize, size, extra, alignment,\n\t\t    zero, try_tcache_alloc, try_tcache_dalloc, arena));\n\t}\n\n\tif (size + extra <= arena_maxclass) {\n\t\treturn (arena_ralloc(arena, ptr, oldsize, size, extra,\n\t\t    alignment, zero, try_tcache_alloc,\n\t\t    try_tcache_dalloc));\n\t} else {\n\t\treturn (huge_ralloc(ptr, oldsize, size, extra,\n\t\t    alignment, zero, try_tcache_dalloc, huge_dss_prec_get(arena)));\n\t}\n}\n\nJEMALLOC_ALWAYS_INLINE void *\niralloc(void *ptr, size_t size, size_t extra, size_t alignment, bool zero)\n{\n\n\treturn (iralloct(ptr, size, extra, alignment, zero, true, true, NULL));\n}\n\nJEMALLOC_ALWAYS_INLINE bool\nixalloc(void *ptr, size_t size, size_t extra, size_t alignment, bool zero)\n{\n\tsize_t oldsize;\n\n\tassert(ptr != NULL);\n\tassert(size != 0);\n\n\toldsize = isalloc(ptr, config_prof);\n\tif (alignment != 0 && ((uintptr_t)ptr & ((uintptr_t)alignment-1))\n\t    != 0) {\n\t\t/* Existing object alignment is inadequate. */\n\t\treturn (true);\n\t}\n\n\tif (size <= arena_maxclass)\n\t\treturn (arena_ralloc_no_move(ptr, oldsize, size, extra, zero));\n\telse\n\t\treturn (huge_ralloc_no_move(ptr, oldsize, size, extra));\n}\n\nmalloc_tsd_externs(thread_allocated, thread_allocated_t)\nmalloc_tsd_funcs(JEMALLOC_ALWAYS_INLINE, thread_allocated, thread_allocated_t,\n    THREAD_ALLOCATED_INITIALIZER, malloc_tsd_no_cleanup)\n#endif\n\n#include \"jemalloc/internal/prof.h\"\n\n#undef JEMALLOC_H_INLINES\n/******************************************************************************/\n#endif /* JEMALLOC_INTERNAL_H */\n"
  },
  {
    "path": "extern/deprecated/redis-2.8.21/deps/jemalloc/include/jemalloc/internal/jemalloc_internal_defs.h.in",
    "content": "#ifndef JEMALLOC_INTERNAL_DEFS_H_\n#define\tJEMALLOC_INTERNAL_DEFS_H_\n/*\n * If JEMALLOC_PREFIX is defined via --with-jemalloc-prefix, it will cause all\n * public APIs to be prefixed.  This makes it possible, with some care, to use\n * multiple allocators simultaneously.\n */\n#undef JEMALLOC_PREFIX\n#undef JEMALLOC_CPREFIX\n\n/*\n * JEMALLOC_PRIVATE_NAMESPACE is used as a prefix for all library-private APIs.\n * For shared libraries, symbol visibility mechanisms prevent these symbols\n * from being exported, but for static libraries, naming collisions are a real\n * possibility.\n */\n#undef JEMALLOC_PRIVATE_NAMESPACE\n\n/*\n * Hyper-threaded CPUs may need a special instruction inside spin loops in\n * order to yield to another virtual CPU.\n */\n#undef CPU_SPINWAIT\n\n/* Defined if the equivalent of FreeBSD's atomic(9) functions are available. */\n#undef JEMALLOC_ATOMIC9\n\n/*\n * Defined if OSAtomic*() functions are available, as provided by Darwin, and\n * documented in the atomic(3) manual page.\n */\n#undef JEMALLOC_OSATOMIC\n\n/*\n * Defined if __sync_add_and_fetch(uint32_t *, uint32_t) and\n * __sync_sub_and_fetch(uint32_t *, uint32_t) are available, despite\n * __GCC_HAVE_SYNC_COMPARE_AND_SWAP_4 not being defined (which means the\n * functions are defined in libgcc instead of being inlines)\n */\n#undef JE_FORCE_SYNC_COMPARE_AND_SWAP_4\n\n/*\n * Defined if __sync_add_and_fetch(uint64_t *, uint64_t) and\n * __sync_sub_and_fetch(uint64_t *, uint64_t) are available, despite\n * __GCC_HAVE_SYNC_COMPARE_AND_SWAP_8 not being defined (which means the\n * functions are defined in libgcc instead of being inlines)\n */\n#undef JE_FORCE_SYNC_COMPARE_AND_SWAP_8\n\n/*\n * Defined if OSSpin*() functions are available, as provided by Darwin, and\n * documented in the spinlock(3) manual page.\n */\n#undef JEMALLOC_OSSPIN\n\n/*\n * Defined if _malloc_thread_cleanup() exists.  At least in the case of\n * FreeBSD, pthread_key_create() allocates, which if used during malloc\n * bootstrapping will cause recursion into the pthreads library.  Therefore, if\n * _malloc_thread_cleanup() exists, use it as the basis for thread cleanup in\n * malloc_tsd.\n */\n#undef JEMALLOC_MALLOC_THREAD_CLEANUP\n\n/*\n * Defined if threaded initialization is known to be safe on this platform.\n * Among other things, it must be possible to initialize a mutex without\n * triggering allocation in order for threaded allocation to be safe.\n */\n#undef JEMALLOC_THREADED_INIT\n\n/*\n * Defined if the pthreads implementation defines\n * _pthread_mutex_init_calloc_cb(), in which case the function is used in order\n * to avoid recursive allocation during mutex initialization.\n */\n#undef JEMALLOC_MUTEX_INIT_CB\n\n/* Defined if sbrk() is supported. */\n#undef JEMALLOC_HAVE_SBRK\n\n/* Non-empty if the tls_model attribute is supported. */\n#undef JEMALLOC_TLS_MODEL\n\n/* JEMALLOC_CC_SILENCE enables code that silences unuseful compiler warnings. */\n#undef JEMALLOC_CC_SILENCE\n\n/* JEMALLOC_CODE_COVERAGE enables test code coverage analysis. */\n#undef JEMALLOC_CODE_COVERAGE\n\n/*\n * JEMALLOC_DEBUG enables assertions and other sanity checks, and disables\n * inline functions.\n */\n#undef JEMALLOC_DEBUG\n\n/* JEMALLOC_STATS enables statistics calculation. */\n#undef JEMALLOC_STATS\n\n/* JEMALLOC_PROF enables allocation profiling. */\n#undef JEMALLOC_PROF\n\n/* Use libunwind for profile backtracing if defined. */\n#undef JEMALLOC_PROF_LIBUNWIND\n\n/* Use libgcc for profile backtracing if defined. */\n#undef JEMALLOC_PROF_LIBGCC\n\n/* Use gcc intrinsics for profile backtracing if defined. */\n#undef JEMALLOC_PROF_GCC\n\n/*\n * JEMALLOC_TCACHE enables a thread-specific caching layer for small objects.\n * This makes it possible to allocate/deallocate objects without any locking\n * when the cache is in the steady state.\n */\n#undef JEMALLOC_TCACHE\n\n/*\n * JEMALLOC_DSS enables use of sbrk(2) to allocate chunks from the data storage\n * segment (DSS).\n */\n#undef JEMALLOC_DSS\n\n/* Support memory filling (junk/zero/quarantine/redzone). */\n#undef JEMALLOC_FILL\n\n/* Support utrace(2)-based tracing. */\n#undef JEMALLOC_UTRACE\n\n/* Support Valgrind. */\n#undef JEMALLOC_VALGRIND\n\n/* Support optional abort() on OOM. */\n#undef JEMALLOC_XMALLOC\n\n/* Support lazy locking (avoid locking unless a second thread is launched). */\n#undef JEMALLOC_LAZY_LOCK\n\n/* One page is 2^STATIC_PAGE_SHIFT bytes. */\n#undef STATIC_PAGE_SHIFT\n\n/*\n * If defined, use munmap() to unmap freed chunks, rather than storing them for\n * later reuse.  This is disabled by default on Linux because common sequences\n * of mmap()/munmap() calls will cause virtual memory map holes.\n */\n#undef JEMALLOC_MUNMAP\n\n/*\n * If defined, use mremap(...MREMAP_FIXED...) for huge realloc().  This is\n * disabled by default because it is Linux-specific and it will cause virtual\n * memory map holes, much like munmap(2) does.\n */\n#undef JEMALLOC_MREMAP\n\n/* TLS is used to map arenas and magazine caches to threads. */\n#undef JEMALLOC_TLS\n\n/*\n * JEMALLOC_IVSALLOC enables ivsalloc(), which verifies that pointers reside\n * within jemalloc-owned chunks before dereferencing them.\n */\n#undef JEMALLOC_IVSALLOC\n\n/*\n * Darwin (OS X) uses zones to work around Mach-O symbol override shortcomings.\n */\n#undef JEMALLOC_ZONE\n#undef JEMALLOC_ZONE_VERSION\n\n/*\n * Methods for purging unused pages differ between operating systems.\n *\n *   madvise(..., MADV_DONTNEED) : On Linux, this immediately discards pages,\n *                                 such that new pages will be demand-zeroed if\n *                                 the address region is later touched.\n *   madvise(..., MADV_FREE) : On FreeBSD and Darwin, this marks pages as being\n *                             unused, such that they will be discarded rather\n *                             than swapped out.\n */\n#undef JEMALLOC_PURGE_MADVISE_DONTNEED\n#undef JEMALLOC_PURGE_MADVISE_FREE\n\n/*\n * Define if operating system has alloca.h header.\n */\n#undef JEMALLOC_HAS_ALLOCA_H\n\n/* C99 restrict keyword supported. */\n#undef JEMALLOC_HAS_RESTRICT\n\n/* For use by hash code. */\n#undef JEMALLOC_BIG_ENDIAN\n\n/* sizeof(int) == 2^LG_SIZEOF_INT. */\n#undef LG_SIZEOF_INT\n\n/* sizeof(long) == 2^LG_SIZEOF_LONG. */\n#undef LG_SIZEOF_LONG\n\n/* sizeof(intmax_t) == 2^LG_SIZEOF_INTMAX_T. */\n#undef LG_SIZEOF_INTMAX_T\n\n#endif /* JEMALLOC_INTERNAL_DEFS_H_ */\n"
  },
  {
    "path": "extern/deprecated/redis-2.8.21/deps/jemalloc/include/jemalloc/internal/jemalloc_internal_macros.h",
    "content": "/*\n * JEMALLOC_ALWAYS_INLINE and JEMALLOC_INLINE are used within header files for\n * functions that are static inline functions if inlining is enabled, and\n * single-definition library-private functions if inlining is disabled.\n *\n * JEMALLOC_ALWAYS_INLINE_C and JEMALLOC_INLINE_C are for use in .c files, in\n * which case the denoted functions are always static, regardless of whether\n * inlining is enabled.\n */\n#if defined(JEMALLOC_DEBUG) || defined(JEMALLOC_CODE_COVERAGE)\n   /* Disable inlining to make debugging/profiling easier. */\n#  define JEMALLOC_ALWAYS_INLINE\n#  define JEMALLOC_ALWAYS_INLINE_C static\n#  define JEMALLOC_INLINE\n#  define JEMALLOC_INLINE_C static\n#  define inline\n#else\n#  define JEMALLOC_ENABLE_INLINE\n#  ifdef JEMALLOC_HAVE_ATTR\n#    define JEMALLOC_ALWAYS_INLINE \\\n\t static inline JEMALLOC_ATTR(unused) JEMALLOC_ATTR(always_inline)\n#    define JEMALLOC_ALWAYS_INLINE_C \\\n\t static inline JEMALLOC_ATTR(always_inline)\n#  else\n#    define JEMALLOC_ALWAYS_INLINE static inline\n#    define JEMALLOC_ALWAYS_INLINE_C static inline\n#  endif\n#  define JEMALLOC_INLINE static inline\n#  define JEMALLOC_INLINE_C static inline\n#  ifdef _MSC_VER\n#    define inline _inline\n#  endif\n#endif\n\n#ifdef JEMALLOC_CC_SILENCE\n#  define UNUSED JEMALLOC_ATTR(unused)\n#else\n#  define UNUSED\n#endif\n\n#define\tZU(z)\t((size_t)z)\n#define\tQU(q)\t((uint64_t)q)\n#define\tQI(q)\t((int64_t)q)\n\n#ifndef __DECONST\n#  define\t__DECONST(type, var)\t((type)(uintptr_t)(const void *)(var))\n#endif\n\n#ifndef JEMALLOC_HAS_RESTRICT\n#  define restrict\n#endif\n"
  },
  {
    "path": "extern/deprecated/redis-2.8.21/deps/jemalloc/include/jemalloc/internal/mb.h",
    "content": "/******************************************************************************/\n#ifdef JEMALLOC_H_TYPES\n\n#endif /* JEMALLOC_H_TYPES */\n/******************************************************************************/\n#ifdef JEMALLOC_H_STRUCTS\n\n#endif /* JEMALLOC_H_STRUCTS */\n/******************************************************************************/\n#ifdef JEMALLOC_H_EXTERNS\n\n#endif /* JEMALLOC_H_EXTERNS */\n/******************************************************************************/\n#ifdef JEMALLOC_H_INLINES\n\n#ifndef JEMALLOC_ENABLE_INLINE\nvoid\tmb_write(void);\n#endif\n\n#if (defined(JEMALLOC_ENABLE_INLINE) || defined(JEMALLOC_MB_C_))\n#ifdef __i386__\n/*\n * According to the Intel Architecture Software Developer's Manual, current\n * processors execute instructions in order from the perspective of other\n * processors in a multiprocessor system, but 1) Intel reserves the right to\n * change that, and 2) the compiler's optimizer could re-order instructions if\n * there weren't some form of barrier.  Therefore, even if running on an\n * architecture that does not need memory barriers (everything through at least\n * i686), an \"optimizer barrier\" is necessary.\n */\nJEMALLOC_INLINE void\nmb_write(void)\n{\n\n#  if 0\n\t/* This is a true memory barrier. */\n\tasm volatile (\"pusha;\"\n\t    \"xor  %%eax,%%eax;\"\n\t    \"cpuid;\"\n\t    \"popa;\"\n\t    : /* Outputs. */\n\t    : /* Inputs. */\n\t    : \"memory\" /* Clobbers. */\n\t    );\n#else\n\t/*\n\t * This is hopefully enough to keep the compiler from reordering\n\t * instructions around this one.\n\t */\n\tasm volatile (\"nop;\"\n\t    : /* Outputs. */\n\t    : /* Inputs. */\n\t    : \"memory\" /* Clobbers. */\n\t    );\n#endif\n}\n#elif (defined(__amd64__) || defined(__x86_64__))\nJEMALLOC_INLINE void\nmb_write(void)\n{\n\n\tasm volatile (\"sfence\"\n\t    : /* Outputs. */\n\t    : /* Inputs. */\n\t    : \"memory\" /* Clobbers. */\n\t    );\n}\n#elif defined(__powerpc__)\nJEMALLOC_INLINE void\nmb_write(void)\n{\n\n\tasm volatile (\"eieio\"\n\t    : /* Outputs. */\n\t    : /* Inputs. */\n\t    : \"memory\" /* Clobbers. */\n\t    );\n}\n#elif defined(__sparc64__)\nJEMALLOC_INLINE void\nmb_write(void)\n{\n\n\tasm volatile (\"membar #StoreStore\"\n\t    : /* Outputs. */\n\t    : /* Inputs. */\n\t    : \"memory\" /* Clobbers. */\n\t    );\n}\n#elif defined(__tile__)\nJEMALLOC_INLINE void\nmb_write(void)\n{\n\n\t__sync_synchronize();\n}\n#else\n/*\n * This is much slower than a simple memory barrier, but the semantics of mutex\n * unlock make this work.\n */\nJEMALLOC_INLINE void\nmb_write(void)\n{\n\tmalloc_mutex_t mtx;\n\n\tmalloc_mutex_init(&mtx);\n\tmalloc_mutex_lock(&mtx);\n\tmalloc_mutex_unlock(&mtx);\n}\n#endif\n#endif\n\n#endif /* JEMALLOC_H_INLINES */\n/******************************************************************************/\n"
  },
  {
    "path": "extern/deprecated/redis-2.8.21/deps/jemalloc/include/jemalloc/internal/mutex.h",
    "content": "/******************************************************************************/\n#ifdef JEMALLOC_H_TYPES\n\ntypedef struct malloc_mutex_s malloc_mutex_t;\n\n#ifdef _WIN32\n#  define MALLOC_MUTEX_INITIALIZER\n#elif (defined(JEMALLOC_OSSPIN))\n#  define MALLOC_MUTEX_INITIALIZER {0}\n#elif (defined(JEMALLOC_MUTEX_INIT_CB))\n#  define MALLOC_MUTEX_INITIALIZER {PTHREAD_MUTEX_INITIALIZER, NULL}\n#else\n#  if (defined(PTHREAD_MUTEX_ADAPTIVE_NP) &&\t\t\t\t\\\n       defined(PTHREAD_ADAPTIVE_MUTEX_INITIALIZER_NP))\n#    define MALLOC_MUTEX_TYPE PTHREAD_MUTEX_ADAPTIVE_NP\n#    define MALLOC_MUTEX_INITIALIZER {PTHREAD_ADAPTIVE_MUTEX_INITIALIZER_NP}\n#  else\n#    define MALLOC_MUTEX_TYPE PTHREAD_MUTEX_DEFAULT\n#    define MALLOC_MUTEX_INITIALIZER {PTHREAD_MUTEX_INITIALIZER}\n#  endif\n#endif\n\n#endif /* JEMALLOC_H_TYPES */\n/******************************************************************************/\n#ifdef JEMALLOC_H_STRUCTS\n\nstruct malloc_mutex_s {\n#ifdef _WIN32\n\tCRITICAL_SECTION\tlock;\n#elif (defined(JEMALLOC_OSSPIN))\n\tOSSpinLock\t\tlock;\n#elif (defined(JEMALLOC_MUTEX_INIT_CB))\n\tpthread_mutex_t\t\tlock;\n\tmalloc_mutex_t\t\t*postponed_next;\n#else\n\tpthread_mutex_t\t\tlock;\n#endif\n};\n\n#endif /* JEMALLOC_H_STRUCTS */\n/******************************************************************************/\n#ifdef JEMALLOC_H_EXTERNS\n\n#ifdef JEMALLOC_LAZY_LOCK\nextern bool isthreaded;\n#else\n#  undef isthreaded /* Undo private_namespace.h definition. */\n#  define isthreaded true\n#endif\n\nbool\tmalloc_mutex_init(malloc_mutex_t *mutex);\nvoid\tmalloc_mutex_prefork(malloc_mutex_t *mutex);\nvoid\tmalloc_mutex_postfork_parent(malloc_mutex_t *mutex);\nvoid\tmalloc_mutex_postfork_child(malloc_mutex_t *mutex);\nbool\tmutex_boot(void);\n\n#endif /* JEMALLOC_H_EXTERNS */\n/******************************************************************************/\n#ifdef JEMALLOC_H_INLINES\n\n#ifndef JEMALLOC_ENABLE_INLINE\nvoid\tmalloc_mutex_lock(malloc_mutex_t *mutex);\nvoid\tmalloc_mutex_unlock(malloc_mutex_t *mutex);\n#endif\n\n#if (defined(JEMALLOC_ENABLE_INLINE) || defined(JEMALLOC_MUTEX_C_))\nJEMALLOC_INLINE void\nmalloc_mutex_lock(malloc_mutex_t *mutex)\n{\n\n\tif (isthreaded) {\n#ifdef _WIN32\n\t\tEnterCriticalSection(&mutex->lock);\n#elif (defined(JEMALLOC_OSSPIN))\n\t\tOSSpinLockLock(&mutex->lock);\n#else\n\t\tpthread_mutex_lock(&mutex->lock);\n#endif\n\t}\n}\n\nJEMALLOC_INLINE void\nmalloc_mutex_unlock(malloc_mutex_t *mutex)\n{\n\n\tif (isthreaded) {\n#ifdef _WIN32\n\t\tLeaveCriticalSection(&mutex->lock);\n#elif (defined(JEMALLOC_OSSPIN))\n\t\tOSSpinLockUnlock(&mutex->lock);\n#else\n\t\tpthread_mutex_unlock(&mutex->lock);\n#endif\n\t}\n}\n#endif\n\n#endif /* JEMALLOC_H_INLINES */\n/******************************************************************************/\n"
  },
  {
    "path": "extern/deprecated/redis-2.8.21/deps/jemalloc/include/jemalloc/internal/private_namespace.sh",
    "content": "#!/bin/sh\n\nfor symbol in `cat $1` ; do\n  echo \"#define\t${symbol} JEMALLOC_N(${symbol})\"\ndone\n"
  },
  {
    "path": "extern/deprecated/redis-2.8.21/deps/jemalloc/include/jemalloc/internal/private_symbols.txt",
    "content": "a0calloc\na0free\na0malloc\narena_alloc_junk_small\narena_bin_index\narena_bin_info\narena_boot\narena_dalloc\narena_dalloc_bin\narena_dalloc_bin_locked\narena_dalloc_junk_large\narena_dalloc_junk_small\narena_dalloc_large\narena_dalloc_large_locked\narena_dalloc_small\narena_dss_prec_get\narena_dss_prec_set\narena_malloc\narena_malloc_large\narena_malloc_small\narena_mapbits_allocated_get\narena_mapbits_binind_get\narena_mapbits_dirty_get\narena_mapbits_get\narena_mapbits_large_binind_set\narena_mapbits_large_get\narena_mapbits_large_set\narena_mapbits_large_size_get\narena_mapbits_small_runind_get\narena_mapbits_small_set\narena_mapbits_unallocated_set\narena_mapbits_unallocated_size_get\narena_mapbits_unallocated_size_set\narena_mapbits_unzeroed_get\narena_mapbits_unzeroed_set\narena_mapbitsp_get\narena_mapbitsp_read\narena_mapbitsp_write\narena_mapp_get\narena_maxclass\narena_new\narena_palloc\narena_postfork_child\narena_postfork_parent\narena_prefork\narena_prof_accum\narena_prof_accum_impl\narena_prof_accum_locked\narena_prof_ctx_get\narena_prof_ctx_set\narena_prof_promoted\narena_ptr_small_binind_get\narena_purge_all\narena_quarantine_junk_small\narena_ralloc\narena_ralloc_junk_large\narena_ralloc_no_move\narena_redzone_corruption\narena_run_regind\narena_salloc\narena_stats_merge\narena_tcache_fill_small\narenas\narenas_booted\narenas_cleanup\narenas_extend\narenas_initialized\narenas_lock\narenas_tls\narenas_tsd\narenas_tsd_boot\narenas_tsd_cleanup_wrapper\narenas_tsd_get\narenas_tsd_get_wrapper\narenas_tsd_init_head\narenas_tsd_set\natomic_add_u\natomic_add_uint32\natomic_add_uint64\natomic_add_z\natomic_sub_u\natomic_sub_uint32\natomic_sub_uint64\natomic_sub_z\nbase_alloc\nbase_boot\nbase_calloc\nbase_node_alloc\nbase_node_dealloc\nbase_postfork_child\nbase_postfork_parent\nbase_prefork\nbitmap_full\nbitmap_get\nbitmap_info_init\nbitmap_info_ngroups\nbitmap_init\nbitmap_set\nbitmap_sfu\nbitmap_size\nbitmap_unset\nbt_init\nbuferror\nchoose_arena\nchoose_arena_hard\nchunk_alloc\nchunk_alloc_dss\nchunk_alloc_mmap\nchunk_boot\nchunk_dealloc\nchunk_dealloc_mmap\nchunk_dss_boot\nchunk_dss_postfork_child\nchunk_dss_postfork_parent\nchunk_dss_prec_get\nchunk_dss_prec_set\nchunk_dss_prefork\nchunk_in_dss\nchunk_npages\nchunk_postfork_child\nchunk_postfork_parent\nchunk_prefork\nchunk_unmap\nchunks_mtx\nchunks_rtree\nchunksize\nchunksize_mask\nckh_bucket_search\nckh_count\nckh_delete\nckh_evict_reloc_insert\nckh_insert\nckh_isearch\nckh_iter\nckh_new\nckh_pointer_hash\nckh_pointer_keycomp\nckh_rebuild\nckh_remove\nckh_search\nckh_string_hash\nckh_string_keycomp\nckh_try_bucket_insert\nckh_try_insert\nctl_boot\nctl_bymib\nctl_byname\nctl_nametomib\nctl_postfork_child\nctl_postfork_parent\nctl_prefork\ndss_prec_names\nextent_tree_ad_first\nextent_tree_ad_insert\nextent_tree_ad_iter\nextent_tree_ad_iter_recurse\nextent_tree_ad_iter_start\nextent_tree_ad_last\nextent_tree_ad_new\nextent_tree_ad_next\nextent_tree_ad_nsearch\nextent_tree_ad_prev\nextent_tree_ad_psearch\nextent_tree_ad_remove\nextent_tree_ad_reverse_iter\nextent_tree_ad_reverse_iter_recurse\nextent_tree_ad_reverse_iter_start\nextent_tree_ad_search\nextent_tree_szad_first\nextent_tree_szad_insert\nextent_tree_szad_iter\nextent_tree_szad_iter_recurse\nextent_tree_szad_iter_start\nextent_tree_szad_last\nextent_tree_szad_new\nextent_tree_szad_next\nextent_tree_szad_nsearch\nextent_tree_szad_prev\nextent_tree_szad_psearch\nextent_tree_szad_remove\nextent_tree_szad_reverse_iter\nextent_tree_szad_reverse_iter_recurse\nextent_tree_szad_reverse_iter_start\nextent_tree_szad_search\nget_errno\nhash\nhash_fmix_32\nhash_fmix_64\nhash_get_block_32\nhash_get_block_64\nhash_rotl_32\nhash_rotl_64\nhash_x64_128\nhash_x86_128\nhash_x86_32\nhuge_allocated\nhuge_boot\nhuge_dalloc\nhuge_dalloc_junk\nhuge_dss_prec_get\nhuge_malloc\nhuge_mtx\nhuge_ndalloc\nhuge_nmalloc\nhuge_palloc\nhuge_postfork_child\nhuge_postfork_parent\nhuge_prefork\nhuge_prof_ctx_get\nhuge_prof_ctx_set\nhuge_ralloc\nhuge_ralloc_no_move\nhuge_salloc\niallocm\nicalloc\nicalloct\nidalloc\nidalloct\nimalloc\nimalloct\nipalloc\nipalloct\niqalloc\niqalloct\niralloc\niralloct\niralloct_realign\nisalloc\nisthreaded\nivsalloc\nixalloc\njemalloc_postfork_child\njemalloc_postfork_parent\njemalloc_prefork\nmalloc_cprintf\nmalloc_mutex_init\nmalloc_mutex_lock\nmalloc_mutex_postfork_child\nmalloc_mutex_postfork_parent\nmalloc_mutex_prefork\nmalloc_mutex_unlock\nmalloc_printf\nmalloc_snprintf\nmalloc_strtoumax\nmalloc_tsd_boot\nmalloc_tsd_cleanup_register\nmalloc_tsd_dalloc\nmalloc_tsd_malloc\nmalloc_tsd_no_cleanup\nmalloc_vcprintf\nmalloc_vsnprintf\nmalloc_write\nmap_bias\nmb_write\nmutex_boot\nnarenas_auto\nnarenas_total\nnarenas_total_get\nncpus\nnhbins\nopt_abort\nopt_dss\nopt_junk\nopt_lg_chunk\nopt_lg_dirty_mult\nopt_lg_prof_interval\nopt_lg_prof_sample\nopt_lg_tcache_max\nopt_narenas\nopt_prof\nopt_prof_accum\nopt_prof_active\nopt_prof_final\nopt_prof_gdump\nopt_prof_leak\nopt_prof_prefix\nopt_quarantine\nopt_redzone\nopt_stats_print\nopt_tcache\nopt_utrace\nopt_valgrind\nopt_xmalloc\nopt_zero\np2rz\npages_purge\npow2_ceil\nprof_backtrace\nprof_boot0\nprof_boot1\nprof_boot2\nprof_bt_count\nprof_ctx_get\nprof_ctx_set\nprof_dump_open\nprof_free\nprof_gdump\nprof_idump\nprof_interval\nprof_lookup\nprof_malloc\nprof_mdump\nprof_postfork_child\nprof_postfork_parent\nprof_prefork\nprof_promote\nprof_realloc\nprof_sample_accum_update\nprof_sample_threshold_update\nprof_tdata_booted\nprof_tdata_cleanup\nprof_tdata_get\nprof_tdata_init\nprof_tdata_initialized\nprof_tdata_tls\nprof_tdata_tsd\nprof_tdata_tsd_boot\nprof_tdata_tsd_cleanup_wrapper\nprof_tdata_tsd_get\nprof_tdata_tsd_get_wrapper\nprof_tdata_tsd_init_head\nprof_tdata_tsd_set\nquarantine\nquarantine_alloc_hook\nquarantine_boot\nquarantine_booted\nquarantine_cleanup\nquarantine_init\nquarantine_tls\nquarantine_tsd\nquarantine_tsd_boot\nquarantine_tsd_cleanup_wrapper\nquarantine_tsd_get\nquarantine_tsd_get_wrapper\nquarantine_tsd_init_head\nquarantine_tsd_set\nregister_zone\nrtree_delete\nrtree_get\nrtree_get_locked\nrtree_new\nrtree_postfork_child\nrtree_postfork_parent\nrtree_prefork\nrtree_set\ns2u\nsa2u\nset_errno\nsmall_size2bin\nstats_cactive\nstats_cactive_add\nstats_cactive_get\nstats_cactive_sub\nstats_chunks\nstats_print\ntcache_alloc_easy\ntcache_alloc_large\ntcache_alloc_small\ntcache_alloc_small_hard\ntcache_arena_associate\ntcache_arena_dissociate\ntcache_bin_flush_large\ntcache_bin_flush_small\ntcache_bin_info\ntcache_boot0\ntcache_boot1\ntcache_booted\ntcache_create\ntcache_dalloc_large\ntcache_dalloc_small\ntcache_destroy\ntcache_enabled_booted\ntcache_enabled_get\ntcache_enabled_initialized\ntcache_enabled_set\ntcache_enabled_tls\ntcache_enabled_tsd\ntcache_enabled_tsd_boot\ntcache_enabled_tsd_cleanup_wrapper\ntcache_enabled_tsd_get\ntcache_enabled_tsd_get_wrapper\ntcache_enabled_tsd_init_head\ntcache_enabled_tsd_set\ntcache_event\ntcache_event_hard\ntcache_flush\ntcache_get\ntcache_initialized\ntcache_maxclass\ntcache_salloc\ntcache_stats_merge\ntcache_thread_cleanup\ntcache_tls\ntcache_tsd\ntcache_tsd_boot\ntcache_tsd_cleanup_wrapper\ntcache_tsd_get\ntcache_tsd_get_wrapper\ntcache_tsd_init_head\ntcache_tsd_set\nthread_allocated_booted\nthread_allocated_initialized\nthread_allocated_tls\nthread_allocated_tsd\nthread_allocated_tsd_boot\nthread_allocated_tsd_cleanup_wrapper\nthread_allocated_tsd_get\nthread_allocated_tsd_get_wrapper\nthread_allocated_tsd_init_head\nthread_allocated_tsd_set\ntsd_init_check_recursion\ntsd_init_finish\nu2rz\n"
  },
  {
    "path": "extern/deprecated/redis-2.8.21/deps/jemalloc/include/jemalloc/internal/private_unnamespace.sh",
    "content": "#!/bin/sh\n\nfor symbol in `cat $1` ; do\n  echo \"#undef ${symbol}\"\ndone\n"
  },
  {
    "path": "extern/deprecated/redis-2.8.21/deps/jemalloc/include/jemalloc/internal/prng.h",
    "content": "/******************************************************************************/\n#ifdef JEMALLOC_H_TYPES\n\n/*\n * Simple linear congruential pseudo-random number generator:\n *\n *   prng(y) = (a*x + c) % m\n *\n * where the following constants ensure maximal period:\n *\n *   a == Odd number (relatively prime to 2^n), and (a-1) is a multiple of 4.\n *   c == Odd number (relatively prime to 2^n).\n *   m == 2^32\n *\n * See Knuth's TAOCP 3rd Ed., Vol. 2, pg. 17 for details on these constraints.\n *\n * This choice of m has the disadvantage that the quality of the bits is\n * proportional to bit position.  For example. the lowest bit has a cycle of 2,\n * the next has a cycle of 4, etc.  For this reason, we prefer to use the upper\n * bits.\n *\n * Macro parameters:\n *   uint32_t r          : Result.\n *   unsigned lg_range   : (0..32], number of least significant bits to return.\n *   uint32_t state      : Seed value.\n *   const uint32_t a, c : See above discussion.\n */\n#define\tprng32(r, lg_range, state, a, c) do {\t\t\t\t\\\n\tassert(lg_range > 0);\t\t\t\t\t\t\\\n\tassert(lg_range <= 32);\t\t\t\t\t\t\\\n\t\t\t\t\t\t\t\t\t\\\n\tr = (state * (a)) + (c);\t\t\t\t\t\\\n\tstate = r;\t\t\t\t\t\t\t\\\n\tr >>= (32 - lg_range);\t\t\t\t\t\t\\\n} while (false)\n\n/* Same as prng32(), but 64 bits of pseudo-randomness, using uint64_t. */\n#define\tprng64(r, lg_range, state, a, c) do {\t\t\t\t\\\n\tassert(lg_range > 0);\t\t\t\t\t\t\\\n\tassert(lg_range <= 64);\t\t\t\t\t\t\\\n\t\t\t\t\t\t\t\t\t\\\n\tr = (state * (a)) + (c);\t\t\t\t\t\\\n\tstate = r;\t\t\t\t\t\t\t\\\n\tr >>= (64 - lg_range);\t\t\t\t\t\t\\\n} while (false)\n\n#endif /* JEMALLOC_H_TYPES */\n/******************************************************************************/\n#ifdef JEMALLOC_H_STRUCTS\n\n#endif /* JEMALLOC_H_STRUCTS */\n/******************************************************************************/\n#ifdef JEMALLOC_H_EXTERNS\n\n#endif /* JEMALLOC_H_EXTERNS */\n/******************************************************************************/\n#ifdef JEMALLOC_H_INLINES\n\n#endif /* JEMALLOC_H_INLINES */\n/******************************************************************************/\n"
  },
  {
    "path": "extern/deprecated/redis-2.8.21/deps/jemalloc/include/jemalloc/internal/prof.h",
    "content": "/******************************************************************************/\n#ifdef JEMALLOC_H_TYPES\n\ntypedef struct prof_bt_s prof_bt_t;\ntypedef struct prof_cnt_s prof_cnt_t;\ntypedef struct prof_thr_cnt_s prof_thr_cnt_t;\ntypedef struct prof_ctx_s prof_ctx_t;\ntypedef struct prof_tdata_s prof_tdata_t;\n\n/* Option defaults. */\n#ifdef JEMALLOC_PROF\n#  define PROF_PREFIX_DEFAULT\t\t\"jeprof\"\n#else\n#  define PROF_PREFIX_DEFAULT\t\t\"\"\n#endif\n#define\tLG_PROF_SAMPLE_DEFAULT\t\t19\n#define\tLG_PROF_INTERVAL_DEFAULT\t-1\n\n/*\n * Hard limit on stack backtrace depth.  The version of prof_backtrace() that\n * is based on __builtin_return_address() necessarily has a hard-coded number\n * of backtrace frame handlers, and should be kept in sync with this setting.\n */\n#define\tPROF_BT_MAX\t\t\t128\n\n/* Maximum number of backtraces to store in each per thread LRU cache. */\n#define\tPROF_TCMAX\t\t\t1024\n\n/* Initial hash table size. */\n#define\tPROF_CKH_MINITEMS\t\t64\n\n/* Size of memory buffer to use when writing dump files. */\n#define\tPROF_DUMP_BUFSIZE\t\t65536\n\n/* Size of stack-allocated buffer used by prof_printf(). */\n#define\tPROF_PRINTF_BUFSIZE\t\t128\n\n/*\n * Number of mutexes shared among all ctx's.  No space is allocated for these\n * unless profiling is enabled, so it's okay to over-provision.\n */\n#define\tPROF_NCTX_LOCKS\t\t\t1024\n\n/*\n * prof_tdata pointers close to NULL are used to encode state information that\n * is used for cleaning up during thread shutdown.\n */\n#define\tPROF_TDATA_STATE_REINCARNATED\t((prof_tdata_t *)(uintptr_t)1)\n#define\tPROF_TDATA_STATE_PURGATORY\t((prof_tdata_t *)(uintptr_t)2)\n#define\tPROF_TDATA_STATE_MAX\t\tPROF_TDATA_STATE_PURGATORY\n\n#endif /* JEMALLOC_H_TYPES */\n/******************************************************************************/\n#ifdef JEMALLOC_H_STRUCTS\n\nstruct prof_bt_s {\n\t/* Backtrace, stored as len program counters. */\n\tvoid\t\t**vec;\n\tunsigned\tlen;\n};\n\n#ifdef JEMALLOC_PROF_LIBGCC\n/* Data structure passed to libgcc _Unwind_Backtrace() callback functions. */\ntypedef struct {\n\tprof_bt_t\t*bt;\n\tunsigned\tnignore;\n\tunsigned\tmax;\n} prof_unwind_data_t;\n#endif\n\nstruct prof_cnt_s {\n\t/*\n\t * Profiling counters.  An allocation/deallocation pair can operate on\n\t * different prof_thr_cnt_t objects that are linked into the same\n\t * prof_ctx_t cnts_ql, so it is possible for the cur* counters to go\n\t * negative.  In principle it is possible for the *bytes counters to\n\t * overflow/underflow, but a general solution would require something\n\t * like 128-bit counters; this implementation doesn't bother to solve\n\t * that problem.\n\t */\n\tint64_t\t\tcurobjs;\n\tint64_t\t\tcurbytes;\n\tuint64_t\taccumobjs;\n\tuint64_t\taccumbytes;\n};\n\nstruct prof_thr_cnt_s {\n\t/* Linkage into prof_ctx_t's cnts_ql. */\n\tql_elm(prof_thr_cnt_t)\tcnts_link;\n\n\t/* Linkage into thread's LRU. */\n\tql_elm(prof_thr_cnt_t)\tlru_link;\n\n\t/*\n\t * Associated context.  If a thread frees an object that it did not\n\t * allocate, it is possible that the context is not cached in the\n\t * thread's hash table, in which case it must be able to look up the\n\t * context, insert a new prof_thr_cnt_t into the thread's hash table,\n\t * and link it into the prof_ctx_t's cnts_ql.\n\t */\n\tprof_ctx_t\t\t*ctx;\n\n\t/*\n\t * Threads use memory barriers to update the counters.  Since there is\n\t * only ever one writer, the only challenge is for the reader to get a\n\t * consistent read of the counters.\n\t *\n\t * The writer uses this series of operations:\n\t *\n\t * 1) Increment epoch to an odd number.\n\t * 2) Update counters.\n\t * 3) Increment epoch to an even number.\n\t *\n\t * The reader must assure 1) that the epoch is even while it reads the\n\t * counters, and 2) that the epoch doesn't change between the time it\n\t * starts and finishes reading the counters.\n\t */\n\tunsigned\t\tepoch;\n\n\t/* Profiling counters. */\n\tprof_cnt_t\t\tcnts;\n};\n\nstruct prof_ctx_s {\n\t/* Associated backtrace. */\n\tprof_bt_t\t\t*bt;\n\n\t/* Protects nlimbo, cnt_merged, and cnts_ql. */\n\tmalloc_mutex_t\t\t*lock;\n\n\t/*\n\t * Number of threads that currently cause this ctx to be in a state of\n\t * limbo due to one of:\n\t *   - Initializing per thread counters associated with this ctx.\n\t *   - Preparing to destroy this ctx.\n\t *   - Dumping a heap profile that includes this ctx.\n\t * nlimbo must be 1 (single destroyer) in order to safely destroy the\n\t * ctx.\n\t */\n\tunsigned\t\tnlimbo;\n\n\t/* Temporary storage for summation during dump. */\n\tprof_cnt_t\t\tcnt_summed;\n\n\t/* When threads exit, they merge their stats into cnt_merged. */\n\tprof_cnt_t\t\tcnt_merged;\n\n\t/*\n\t * List of profile counters, one for each thread that has allocated in\n\t * this context.\n\t */\n\tql_head(prof_thr_cnt_t)\tcnts_ql;\n\n\t/* Linkage for list of contexts to be dumped. */\n\tql_elm(prof_ctx_t)\tdump_link;\n};\ntypedef ql_head(prof_ctx_t) prof_ctx_list_t;\n\nstruct prof_tdata_s {\n\t/*\n\t * Hash of (prof_bt_t *)-->(prof_thr_cnt_t *).  Each thread keeps a\n\t * cache of backtraces, with associated thread-specific prof_thr_cnt_t\n\t * objects.  Other threads may read the prof_thr_cnt_t contents, but no\n\t * others will ever write them.\n\t *\n\t * Upon thread exit, the thread must merge all the prof_thr_cnt_t\n\t * counter data into the associated prof_ctx_t objects, and unlink/free\n\t * the prof_thr_cnt_t objects.\n\t */\n\tckh_t\t\t\tbt2cnt;\n\n\t/* LRU for contents of bt2cnt. */\n\tql_head(prof_thr_cnt_t)\tlru_ql;\n\n\t/* Backtrace vector, used for calls to prof_backtrace(). */\n\tvoid\t\t\t**vec;\n\n\t/* Sampling state. */\n\tuint64_t\t\tprng_state;\n\tuint64_t\t\tthreshold;\n\tuint64_t\t\taccum;\n\n\t/* State used to avoid dumping while operating on prof internals. */\n\tbool\t\t\tenq;\n\tbool\t\t\tenq_idump;\n\tbool\t\t\tenq_gdump;\n};\n\n#endif /* JEMALLOC_H_STRUCTS */\n/******************************************************************************/\n#ifdef JEMALLOC_H_EXTERNS\n\nextern bool\topt_prof;\n/*\n * Even if opt_prof is true, sampling can be temporarily disabled by setting\n * opt_prof_active to false.  No locking is used when updating opt_prof_active,\n * so there are no guarantees regarding how long it will take for all threads\n * to notice state changes.\n */\nextern bool\topt_prof_active;\nextern size_t\topt_lg_prof_sample;   /* Mean bytes between samples. */\nextern ssize_t\topt_lg_prof_interval; /* lg(prof_interval). */\nextern bool\topt_prof_gdump;       /* High-water memory dumping. */\nextern bool\topt_prof_final;       /* Final profile dumping. */\nextern bool\topt_prof_leak;        /* Dump leak summary at exit. */\nextern bool\topt_prof_accum;       /* Report cumulative bytes. */\nextern char\topt_prof_prefix[\n    /* Minimize memory bloat for non-prof builds. */\n#ifdef JEMALLOC_PROF\n    PATH_MAX +\n#endif\n    1];\n\n/*\n * Profile dump interval, measured in bytes allocated.  Each arena triggers a\n * profile dump when it reaches this threshold.  The effect is that the\n * interval between profile dumps averages prof_interval, though the actual\n * interval between dumps will tend to be sporadic, and the interval will be a\n * maximum of approximately (prof_interval * narenas).\n */\nextern uint64_t\tprof_interval;\n\n/*\n * If true, promote small sampled objects to large objects, since small run\n * headers do not have embedded profile context pointers.\n */\nextern bool\tprof_promote;\n\nvoid\tbt_init(prof_bt_t *bt, void **vec);\nvoid\tprof_backtrace(prof_bt_t *bt, unsigned nignore);\nprof_thr_cnt_t\t*prof_lookup(prof_bt_t *bt);\n#ifdef JEMALLOC_JET\nsize_t\tprof_bt_count(void);\ntypedef int (prof_dump_open_t)(bool, const char *);\nextern prof_dump_open_t *prof_dump_open;\n#endif\nvoid\tprof_idump(void);\nbool\tprof_mdump(const char *filename);\nvoid\tprof_gdump(void);\nprof_tdata_t\t*prof_tdata_init(void);\nvoid\tprof_tdata_cleanup(void *arg);\nvoid\tprof_boot0(void);\nvoid\tprof_boot1(void);\nbool\tprof_boot2(void);\nvoid\tprof_prefork(void);\nvoid\tprof_postfork_parent(void);\nvoid\tprof_postfork_child(void);\n\n#endif /* JEMALLOC_H_EXTERNS */\n/******************************************************************************/\n#ifdef JEMALLOC_H_INLINES\n\n#define\tPROF_ALLOC_PREP(nignore, size, ret) do {\t\t\t\\\n\tprof_tdata_t *prof_tdata;\t\t\t\t\t\\\n\tprof_bt_t bt;\t\t\t\t\t\t\t\\\n\t\t\t\t\t\t\t\t\t\\\n\tassert(size == s2u(size));\t\t\t\t\t\\\n\t\t\t\t\t\t\t\t\t\\\n\tprof_tdata = prof_tdata_get(true);\t\t\t\t\\\n\tif ((uintptr_t)prof_tdata <= (uintptr_t)PROF_TDATA_STATE_MAX) {\t\\\n\t\tif (prof_tdata != NULL)\t\t\t\t\t\\\n\t\t\tret = (prof_thr_cnt_t *)(uintptr_t)1U;\t\t\\\n\t\telse\t\t\t\t\t\t\t\\\n\t\t\tret = NULL;\t\t\t\t\t\\\n\t\tbreak;\t\t\t\t\t\t\t\\\n\t}\t\t\t\t\t\t\t\t\\\n\t\t\t\t\t\t\t\t\t\\\n\tif (opt_prof_active == false) {\t\t\t\t\t\\\n\t\t/* Sampling is currently inactive, so avoid sampling. */\\\n\t\tret = (prof_thr_cnt_t *)(uintptr_t)1U;\t\t\t\\\n\t} else if (opt_lg_prof_sample == 0) {\t\t\t\t\\\n\t\t/* Don't bother with sampling logic, since sampling   */\\\n\t\t/* interval is 1.                                     */\\\n\t\tbt_init(&bt, prof_tdata->vec);\t\t\t\t\\\n\t\tprof_backtrace(&bt, nignore);\t\t\t\t\\\n\t\tret = prof_lookup(&bt);\t\t\t\t\t\\\n\t} else {\t\t\t\t\t\t\t\\\n\t\tif (prof_tdata->threshold == 0) {\t\t\t\\\n\t\t\t/* Initialize.  Seed the prng differently for */\\\n\t\t\t/* each thread.                               */\\\n\t\t\tprof_tdata->prng_state =\t\t\t\\\n\t\t\t    (uint64_t)(uintptr_t)&size;\t\t\t\\\n\t\t\tprof_sample_threshold_update(prof_tdata);\t\\\n\t\t}\t\t\t\t\t\t\t\\\n\t\t\t\t\t\t\t\t\t\\\n\t\t/* Determine whether to capture a backtrace based on  */\\\n\t\t/* whether size is enough for prof_accum to reach     */\\\n\t\t/* prof_tdata->threshold.  However, delay updating    */\\\n\t\t/* these variables until prof_{m,re}alloc(), because  */\\\n\t\t/* we don't know for sure that the allocation will    */\\\n\t\t/* succeed.                                           */\\\n\t\t/*                                                    */\\\n\t\t/* Use subtraction rather than addition to avoid      */\\\n\t\t/* potential integer overflow.                        */\\\n\t\tif (size >= prof_tdata->threshold -\t\t\t\\\n\t\t    prof_tdata->accum) {\t\t\t\t\\\n\t\t\tbt_init(&bt, prof_tdata->vec);\t\t\t\\\n\t\t\tprof_backtrace(&bt, nignore);\t\t\t\\\n\t\t\tret = prof_lookup(&bt);\t\t\t\t\\\n\t\t} else\t\t\t\t\t\t\t\\\n\t\t\tret = (prof_thr_cnt_t *)(uintptr_t)1U;\t\t\\\n\t}\t\t\t\t\t\t\t\t\\\n} while (0)\n\n#ifndef JEMALLOC_ENABLE_INLINE\nmalloc_tsd_protos(JEMALLOC_ATTR(unused), prof_tdata, prof_tdata_t *)\n\nprof_tdata_t\t*prof_tdata_get(bool create);\nvoid\tprof_sample_threshold_update(prof_tdata_t *prof_tdata);\nprof_ctx_t\t*prof_ctx_get(const void *ptr);\nvoid\tprof_ctx_set(const void *ptr, size_t usize, prof_ctx_t *ctx);\nbool\tprof_sample_accum_update(size_t size);\nvoid\tprof_malloc(const void *ptr, size_t usize, prof_thr_cnt_t *cnt);\nvoid\tprof_realloc(const void *ptr, size_t usize, prof_thr_cnt_t *cnt,\n    size_t old_usize, prof_ctx_t *old_ctx);\nvoid\tprof_free(const void *ptr, size_t size);\n#endif\n\n#if (defined(JEMALLOC_ENABLE_INLINE) || defined(JEMALLOC_PROF_C_))\n/* Thread-specific backtrace cache, used to reduce bt2ctx contention. */\nmalloc_tsd_externs(prof_tdata, prof_tdata_t *)\nmalloc_tsd_funcs(JEMALLOC_INLINE, prof_tdata, prof_tdata_t *, NULL,\n    prof_tdata_cleanup)\n\nJEMALLOC_INLINE prof_tdata_t *\nprof_tdata_get(bool create)\n{\n\tprof_tdata_t *prof_tdata;\n\n\tcassert(config_prof);\n\n\tprof_tdata = *prof_tdata_tsd_get();\n\tif (create && prof_tdata == NULL)\n\t\tprof_tdata = prof_tdata_init();\n\n\treturn (prof_tdata);\n}\n\nJEMALLOC_INLINE void\nprof_sample_threshold_update(prof_tdata_t *prof_tdata)\n{\n\t/*\n\t * The body of this function is compiled out unless heap profiling is\n\t * enabled, so that it is possible to compile jemalloc with floating\n\t * point support completely disabled.  Avoiding floating point code is\n\t * important on memory-constrained systems, but it also enables a\n\t * workaround for versions of glibc that don't properly save/restore\n\t * floating point registers during dynamic lazy symbol loading (which\n\t * internally calls into whatever malloc implementation happens to be\n\t * integrated into the application).  Note that some compilers (e.g.\n\t * gcc 4.8) may use floating point registers for fast memory moves, so\n\t * jemalloc must be compiled with such optimizations disabled (e.g.\n\t * -mno-sse) in order for the workaround to be complete.\n\t */\n#ifdef JEMALLOC_PROF\n\tuint64_t r;\n\tdouble u;\n\n\tcassert(config_prof);\n\n\t/*\n\t * Compute sample threshold as a geometrically distributed random\n\t * variable with mean (2^opt_lg_prof_sample).\n\t *\n\t *                         __        __\n\t *                         |  log(u)  |                     1\n\t * prof_tdata->threshold = | -------- |, where p = -------------------\n\t *                         | log(1-p) |             opt_lg_prof_sample\n\t *                                                 2\n\t *\n\t * For more information on the math, see:\n\t *\n\t *   Non-Uniform Random Variate Generation\n\t *   Luc Devroye\n\t *   Springer-Verlag, New York, 1986\n\t *   pp 500\n\t *   (http://luc.devroye.org/rnbookindex.html)\n\t */\n\tprng64(r, 53, prof_tdata->prng_state,\n\t    UINT64_C(6364136223846793005), UINT64_C(1442695040888963407));\n\tu = (double)r * (1.0/9007199254740992.0L);\n\tprof_tdata->threshold = (uint64_t)(log(u) /\n\t    log(1.0 - (1.0 / (double)((uint64_t)1U << opt_lg_prof_sample))))\n\t    + (uint64_t)1U;\n#endif\n}\n\nJEMALLOC_INLINE prof_ctx_t *\nprof_ctx_get(const void *ptr)\n{\n\tprof_ctx_t *ret;\n\tarena_chunk_t *chunk;\n\n\tcassert(config_prof);\n\tassert(ptr != NULL);\n\n\tchunk = (arena_chunk_t *)CHUNK_ADDR2BASE(ptr);\n\tif (chunk != ptr) {\n\t\t/* Region. */\n\t\tret = arena_prof_ctx_get(ptr);\n\t} else\n\t\tret = huge_prof_ctx_get(ptr);\n\n\treturn (ret);\n}\n\nJEMALLOC_INLINE void\nprof_ctx_set(const void *ptr, size_t usize, prof_ctx_t *ctx)\n{\n\tarena_chunk_t *chunk;\n\n\tcassert(config_prof);\n\tassert(ptr != NULL);\n\n\tchunk = (arena_chunk_t *)CHUNK_ADDR2BASE(ptr);\n\tif (chunk != ptr) {\n\t\t/* Region. */\n\t\tarena_prof_ctx_set(ptr, usize, ctx);\n\t} else\n\t\thuge_prof_ctx_set(ptr, ctx);\n}\n\nJEMALLOC_INLINE bool\nprof_sample_accum_update(size_t size)\n{\n\tprof_tdata_t *prof_tdata;\n\n\tcassert(config_prof);\n\t/* Sampling logic is unnecessary if the interval is 1. */\n\tassert(opt_lg_prof_sample != 0);\n\n\tprof_tdata = prof_tdata_get(false);\n\tif ((uintptr_t)prof_tdata <= (uintptr_t)PROF_TDATA_STATE_MAX)\n\t\treturn (true);\n\n\t/* Take care to avoid integer overflow. */\n\tif (size >= prof_tdata->threshold - prof_tdata->accum) {\n\t\tprof_tdata->accum -= (prof_tdata->threshold - size);\n\t\t/* Compute new sample threshold. */\n\t\tprof_sample_threshold_update(prof_tdata);\n\t\twhile (prof_tdata->accum >= prof_tdata->threshold) {\n\t\t\tprof_tdata->accum -= prof_tdata->threshold;\n\t\t\tprof_sample_threshold_update(prof_tdata);\n\t\t}\n\t\treturn (false);\n\t} else {\n\t\tprof_tdata->accum += size;\n\t\treturn (true);\n\t}\n}\n\nJEMALLOC_INLINE void\nprof_malloc(const void *ptr, size_t usize, prof_thr_cnt_t *cnt)\n{\n\n\tcassert(config_prof);\n\tassert(ptr != NULL);\n\tassert(usize == isalloc(ptr, true));\n\n\tif (opt_lg_prof_sample != 0) {\n\t\tif (prof_sample_accum_update(usize)) {\n\t\t\t/*\n\t\t\t * Don't sample.  For malloc()-like allocation, it is\n\t\t\t * always possible to tell in advance how large an\n\t\t\t * object's usable size will be, so there should never\n\t\t\t * be a difference between the usize passed to\n\t\t\t * PROF_ALLOC_PREP() and prof_malloc().\n\t\t\t */\n\t\t\tassert((uintptr_t)cnt == (uintptr_t)1U);\n\t\t}\n\t}\n\n\tif ((uintptr_t)cnt > (uintptr_t)1U) {\n\t\tprof_ctx_set(ptr, usize, cnt->ctx);\n\n\t\tcnt->epoch++;\n\t\t/*********/\n\t\tmb_write();\n\t\t/*********/\n\t\tcnt->cnts.curobjs++;\n\t\tcnt->cnts.curbytes += usize;\n\t\tif (opt_prof_accum) {\n\t\t\tcnt->cnts.accumobjs++;\n\t\t\tcnt->cnts.accumbytes += usize;\n\t\t}\n\t\t/*********/\n\t\tmb_write();\n\t\t/*********/\n\t\tcnt->epoch++;\n\t\t/*********/\n\t\tmb_write();\n\t\t/*********/\n\t} else\n\t\tprof_ctx_set(ptr, usize, (prof_ctx_t *)(uintptr_t)1U);\n}\n\nJEMALLOC_INLINE void\nprof_realloc(const void *ptr, size_t usize, prof_thr_cnt_t *cnt,\n    size_t old_usize, prof_ctx_t *old_ctx)\n{\n\tprof_thr_cnt_t *told_cnt;\n\n\tcassert(config_prof);\n\tassert(ptr != NULL || (uintptr_t)cnt <= (uintptr_t)1U);\n\n\tif (ptr != NULL) {\n\t\tassert(usize == isalloc(ptr, true));\n\t\tif (opt_lg_prof_sample != 0) {\n\t\t\tif (prof_sample_accum_update(usize)) {\n\t\t\t\t/*\n\t\t\t\t * Don't sample.  The usize passed to\n\t\t\t\t * PROF_ALLOC_PREP() was larger than what\n\t\t\t\t * actually got allocated, so a backtrace was\n\t\t\t\t * captured for this allocation, even though\n\t\t\t\t * its actual usize was insufficient to cross\n\t\t\t\t * the sample threshold.\n\t\t\t\t */\n\t\t\t\tcnt = (prof_thr_cnt_t *)(uintptr_t)1U;\n\t\t\t}\n\t\t}\n\t}\n\n\tif ((uintptr_t)old_ctx > (uintptr_t)1U) {\n\t\ttold_cnt = prof_lookup(old_ctx->bt);\n\t\tif (told_cnt == NULL) {\n\t\t\t/*\n\t\t\t * It's too late to propagate OOM for this realloc(),\n\t\t\t * so operate directly on old_cnt->ctx->cnt_merged.\n\t\t\t */\n\t\t\tmalloc_mutex_lock(old_ctx->lock);\n\t\t\told_ctx->cnt_merged.curobjs--;\n\t\t\told_ctx->cnt_merged.curbytes -= old_usize;\n\t\t\tmalloc_mutex_unlock(old_ctx->lock);\n\t\t\ttold_cnt = (prof_thr_cnt_t *)(uintptr_t)1U;\n\t\t}\n\t} else\n\t\ttold_cnt = (prof_thr_cnt_t *)(uintptr_t)1U;\n\n\tif ((uintptr_t)told_cnt > (uintptr_t)1U)\n\t\ttold_cnt->epoch++;\n\tif ((uintptr_t)cnt > (uintptr_t)1U) {\n\t\tprof_ctx_set(ptr, usize, cnt->ctx);\n\t\tcnt->epoch++;\n\t} else if (ptr != NULL)\n\t\tprof_ctx_set(ptr, usize, (prof_ctx_t *)(uintptr_t)1U);\n\t/*********/\n\tmb_write();\n\t/*********/\n\tif ((uintptr_t)told_cnt > (uintptr_t)1U) {\n\t\ttold_cnt->cnts.curobjs--;\n\t\ttold_cnt->cnts.curbytes -= old_usize;\n\t}\n\tif ((uintptr_t)cnt > (uintptr_t)1U) {\n\t\tcnt->cnts.curobjs++;\n\t\tcnt->cnts.curbytes += usize;\n\t\tif (opt_prof_accum) {\n\t\t\tcnt->cnts.accumobjs++;\n\t\t\tcnt->cnts.accumbytes += usize;\n\t\t}\n\t}\n\t/*********/\n\tmb_write();\n\t/*********/\n\tif ((uintptr_t)told_cnt > (uintptr_t)1U)\n\t\ttold_cnt->epoch++;\n\tif ((uintptr_t)cnt > (uintptr_t)1U)\n\t\tcnt->epoch++;\n\t/*********/\n\tmb_write(); /* Not strictly necessary. */\n}\n\nJEMALLOC_INLINE void\nprof_free(const void *ptr, size_t size)\n{\n\tprof_ctx_t *ctx = prof_ctx_get(ptr);\n\n\tcassert(config_prof);\n\n\tif ((uintptr_t)ctx > (uintptr_t)1) {\n\t\tprof_thr_cnt_t *tcnt;\n\t\tassert(size == isalloc(ptr, true));\n\t\ttcnt = prof_lookup(ctx->bt);\n\n\t\tif (tcnt != NULL) {\n\t\t\ttcnt->epoch++;\n\t\t\t/*********/\n\t\t\tmb_write();\n\t\t\t/*********/\n\t\t\ttcnt->cnts.curobjs--;\n\t\t\ttcnt->cnts.curbytes -= size;\n\t\t\t/*********/\n\t\t\tmb_write();\n\t\t\t/*********/\n\t\t\ttcnt->epoch++;\n\t\t\t/*********/\n\t\t\tmb_write();\n\t\t\t/*********/\n\t\t} else {\n\t\t\t/*\n\t\t\t * OOM during free() cannot be propagated, so operate\n\t\t\t * directly on cnt->ctx->cnt_merged.\n\t\t\t */\n\t\t\tmalloc_mutex_lock(ctx->lock);\n\t\t\tctx->cnt_merged.curobjs--;\n\t\t\tctx->cnt_merged.curbytes -= size;\n\t\t\tmalloc_mutex_unlock(ctx->lock);\n\t\t}\n\t}\n}\n#endif\n\n#endif /* JEMALLOC_H_INLINES */\n/******************************************************************************/\n"
  },
  {
    "path": "extern/deprecated/redis-2.8.21/deps/jemalloc/include/jemalloc/internal/public_namespace.sh",
    "content": "#!/bin/sh\n\nfor nm in `cat $1` ; do\n  n=`echo ${nm} |tr ':' ' ' |awk '{print $1}'`\n  echo \"#define\tje_${n} JEMALLOC_N(${n})\"\ndone\n"
  },
  {
    "path": "extern/deprecated/redis-2.8.21/deps/jemalloc/include/jemalloc/internal/public_unnamespace.sh",
    "content": "#!/bin/sh\n\nfor nm in `cat $1` ; do\n  n=`echo ${nm} |tr ':' ' ' |awk '{print $1}'`\n  echo \"#undef je_${n}\"\ndone\n"
  },
  {
    "path": "extern/deprecated/redis-2.8.21/deps/jemalloc/include/jemalloc/internal/ql.h",
    "content": "/*\n * List definitions.\n */\n#define\tql_head(a_type)\t\t\t\t\t\t\t\\\nstruct {\t\t\t\t\t\t\t\t\\\n\ta_type *qlh_first;\t\t\t\t\t\t\\\n}\n\n#define\tql_head_initializer(a_head) {NULL}\n\n#define\tql_elm(a_type)\tqr(a_type)\n\n/* List functions. */\n#define\tql_new(a_head) do {\t\t\t\t\t\t\\\n\t(a_head)->qlh_first = NULL;\t\t\t\t\t\\\n} while (0)\n\n#define\tql_elm_new(a_elm, a_field) qr_new((a_elm), a_field)\n\n#define\tql_first(a_head) ((a_head)->qlh_first)\n\n#define\tql_last(a_head, a_field)\t\t\t\t\t\\\n\t((ql_first(a_head) != NULL)\t\t\t\t\t\\\n\t    ? qr_prev(ql_first(a_head), a_field) : NULL)\n\n#define\tql_next(a_head, a_elm, a_field)\t\t\t\t\t\\\n\t((ql_last(a_head, a_field) != (a_elm))\t\t\t\t\\\n\t    ? qr_next((a_elm), a_field)\t: NULL)\n\n#define\tql_prev(a_head, a_elm, a_field)\t\t\t\t\t\\\n\t((ql_first(a_head) != (a_elm)) ? qr_prev((a_elm), a_field)\t\\\n\t\t\t\t       : NULL)\n\n#define\tql_before_insert(a_head, a_qlelm, a_elm, a_field) do {\t\t\\\n\tqr_before_insert((a_qlelm), (a_elm), a_field);\t\t\t\\\n\tif (ql_first(a_head) == (a_qlelm)) {\t\t\t\t\\\n\t\tql_first(a_head) = (a_elm);\t\t\t\t\\\n\t}\t\t\t\t\t\t\t\t\\\n} while (0)\n\n#define\tql_after_insert(a_qlelm, a_elm, a_field)\t\t\t\\\n\tqr_after_insert((a_qlelm), (a_elm), a_field)\n\n#define\tql_head_insert(a_head, a_elm, a_field) do {\t\t\t\\\n\tif (ql_first(a_head) != NULL) {\t\t\t\t\t\\\n\t\tqr_before_insert(ql_first(a_head), (a_elm), a_field);\t\\\n\t}\t\t\t\t\t\t\t\t\\\n\tql_first(a_head) = (a_elm);\t\t\t\t\t\\\n} while (0)\n\n#define\tql_tail_insert(a_head, a_elm, a_field) do {\t\t\t\\\n\tif (ql_first(a_head) != NULL) {\t\t\t\t\t\\\n\t\tqr_before_insert(ql_first(a_head), (a_elm), a_field);\t\\\n\t}\t\t\t\t\t\t\t\t\\\n\tql_first(a_head) = qr_next((a_elm), a_field);\t\t\t\\\n} while (0)\n\n#define\tql_remove(a_head, a_elm, a_field) do {\t\t\t\t\\\n\tif (ql_first(a_head) == (a_elm)) {\t\t\t\t\\\n\t\tql_first(a_head) = qr_next(ql_first(a_head), a_field);\t\\\n\t}\t\t\t\t\t\t\t\t\\\n\tif (ql_first(a_head) != (a_elm)) {\t\t\t\t\\\n\t\tqr_remove((a_elm), a_field);\t\t\t\t\\\n\t} else {\t\t\t\t\t\t\t\\\n\t\tql_first(a_head) = NULL;\t\t\t\t\\\n\t}\t\t\t\t\t\t\t\t\\\n} while (0)\n\n#define\tql_head_remove(a_head, a_type, a_field) do {\t\t\t\\\n\ta_type *t = ql_first(a_head);\t\t\t\t\t\\\n\tql_remove((a_head), t, a_field);\t\t\t\t\\\n} while (0)\n\n#define\tql_tail_remove(a_head, a_type, a_field) do {\t\t\t\\\n\ta_type *t = ql_last(a_head, a_field);\t\t\t\t\\\n\tql_remove((a_head), t, a_field);\t\t\t\t\\\n} while (0)\n\n#define\tql_foreach(a_var, a_head, a_field)\t\t\t\t\\\n\tqr_foreach((a_var), ql_first(a_head), a_field)\n\n#define\tql_reverse_foreach(a_var, a_head, a_field)\t\t\t\\\n\tqr_reverse_foreach((a_var), ql_first(a_head), a_field)\n"
  },
  {
    "path": "extern/deprecated/redis-2.8.21/deps/jemalloc/include/jemalloc/internal/qr.h",
    "content": "/* Ring definitions. */\n#define\tqr(a_type)\t\t\t\t\t\t\t\\\nstruct {\t\t\t\t\t\t\t\t\\\n\ta_type\t*qre_next;\t\t\t\t\t\t\\\n\ta_type\t*qre_prev;\t\t\t\t\t\t\\\n}\n\n/* Ring functions. */\n#define\tqr_new(a_qr, a_field) do {\t\t\t\t\t\\\n\t(a_qr)->a_field.qre_next = (a_qr);\t\t\t\t\\\n\t(a_qr)->a_field.qre_prev = (a_qr);\t\t\t\t\\\n} while (0)\n\n#define\tqr_next(a_qr, a_field) ((a_qr)->a_field.qre_next)\n\n#define\tqr_prev(a_qr, a_field) ((a_qr)->a_field.qre_prev)\n\n#define\tqr_before_insert(a_qrelm, a_qr, a_field) do {\t\t\t\\\n\t(a_qr)->a_field.qre_prev = (a_qrelm)->a_field.qre_prev;\t\t\\\n\t(a_qr)->a_field.qre_next = (a_qrelm);\t\t\t\t\\\n\t(a_qr)->a_field.qre_prev->a_field.qre_next = (a_qr);\t\t\\\n\t(a_qrelm)->a_field.qre_prev = (a_qr);\t\t\t\t\\\n} while (0)\n\n#define\tqr_after_insert(a_qrelm, a_qr, a_field)\t\t\t\t\\\n    do\t\t\t\t\t\t\t\t\t\\\n    {\t\t\t\t\t\t\t\t\t\\\n\t(a_qr)->a_field.qre_next = (a_qrelm)->a_field.qre_next;\t\t\\\n\t(a_qr)->a_field.qre_prev = (a_qrelm);\t\t\t\t\\\n\t(a_qr)->a_field.qre_next->a_field.qre_prev = (a_qr);\t\t\\\n\t(a_qrelm)->a_field.qre_next = (a_qr);\t\t\t\t\\\n    } while (0)\n\n#define\tqr_meld(a_qr_a, a_qr_b, a_field) do {\t\t\t\t\\\n\tvoid *t;\t\t\t\t\t\t\t\\\n\t(a_qr_a)->a_field.qre_prev->a_field.qre_next = (a_qr_b);\t\\\n\t(a_qr_b)->a_field.qre_prev->a_field.qre_next = (a_qr_a);\t\\\n\tt = (a_qr_a)->a_field.qre_prev;\t\t\t\t\t\\\n\t(a_qr_a)->a_field.qre_prev = (a_qr_b)->a_field.qre_prev;\t\\\n\t(a_qr_b)->a_field.qre_prev = t;\t\t\t\t\t\\\n} while (0)\n\n/* qr_meld() and qr_split() are functionally equivalent, so there's no need to\n * have two copies of the code. */\n#define\tqr_split(a_qr_a, a_qr_b, a_field)\t\t\t\t\\\n\tqr_meld((a_qr_a), (a_qr_b), a_field)\n\n#define\tqr_remove(a_qr, a_field) do {\t\t\t\t\t\\\n\t(a_qr)->a_field.qre_prev->a_field.qre_next\t\t\t\\\n\t    = (a_qr)->a_field.qre_next;\t\t\t\t\t\\\n\t(a_qr)->a_field.qre_next->a_field.qre_prev\t\t\t\\\n\t    = (a_qr)->a_field.qre_prev;\t\t\t\t\t\\\n\t(a_qr)->a_field.qre_next = (a_qr);\t\t\t\t\\\n\t(a_qr)->a_field.qre_prev = (a_qr);\t\t\t\t\\\n} while (0)\n\n#define\tqr_foreach(var, a_qr, a_field)\t\t\t\t\t\\\n\tfor ((var) = (a_qr);\t\t\t\t\t\t\\\n\t    (var) != NULL;\t\t\t\t\t\t\\\n\t    (var) = (((var)->a_field.qre_next != (a_qr))\t\t\\\n\t    ? (var)->a_field.qre_next : NULL))\n\n#define\tqr_reverse_foreach(var, a_qr, a_field)\t\t\t\t\\\n\tfor ((var) = ((a_qr) != NULL) ? qr_prev(a_qr, a_field) : NULL;\t\\\n\t    (var) != NULL;\t\t\t\t\t\t\\\n\t    (var) = (((var) != (a_qr))\t\t\t\t\t\\\n\t    ? (var)->a_field.qre_prev : NULL))\n"
  },
  {
    "path": "extern/deprecated/redis-2.8.21/deps/jemalloc/include/jemalloc/internal/quarantine.h",
    "content": "/******************************************************************************/\n#ifdef JEMALLOC_H_TYPES\n\ntypedef struct quarantine_obj_s quarantine_obj_t;\ntypedef struct quarantine_s quarantine_t;\n\n/* Default per thread quarantine size if valgrind is enabled. */\n#define\tJEMALLOC_VALGRIND_QUARANTINE_DEFAULT\t(ZU(1) << 24)\n\n#endif /* JEMALLOC_H_TYPES */\n/******************************************************************************/\n#ifdef JEMALLOC_H_STRUCTS\n\nstruct quarantine_obj_s {\n\tvoid\t*ptr;\n\tsize_t\tusize;\n};\n\nstruct quarantine_s {\n\tsize_t\t\t\tcurbytes;\n\tsize_t\t\t\tcurobjs;\n\tsize_t\t\t\tfirst;\n#define\tLG_MAXOBJS_INIT 10\n\tsize_t\t\t\tlg_maxobjs;\n\tquarantine_obj_t\tobjs[1]; /* Dynamically sized ring buffer. */\n};\n\n#endif /* JEMALLOC_H_STRUCTS */\n/******************************************************************************/\n#ifdef JEMALLOC_H_EXTERNS\n\nquarantine_t\t*quarantine_init(size_t lg_maxobjs);\nvoid\tquarantine(void *ptr);\nvoid\tquarantine_cleanup(void *arg);\nbool\tquarantine_boot(void);\n\n#endif /* JEMALLOC_H_EXTERNS */\n/******************************************************************************/\n#ifdef JEMALLOC_H_INLINES\n\n#ifndef JEMALLOC_ENABLE_INLINE\nmalloc_tsd_protos(JEMALLOC_ATTR(unused), quarantine, quarantine_t *)\n\nvoid\tquarantine_alloc_hook(void);\n#endif\n\n#if (defined(JEMALLOC_ENABLE_INLINE) || defined(JEMALLOC_QUARANTINE_C_))\nmalloc_tsd_externs(quarantine, quarantine_t *)\nmalloc_tsd_funcs(JEMALLOC_ALWAYS_INLINE, quarantine, quarantine_t *, NULL,\n    quarantine_cleanup)\n\nJEMALLOC_ALWAYS_INLINE void\nquarantine_alloc_hook(void)\n{\n\tquarantine_t *quarantine;\n\n\tassert(config_fill && opt_quarantine);\n\n\tquarantine = *quarantine_tsd_get();\n\tif (quarantine == NULL)\n\t\tquarantine_init(LG_MAXOBJS_INIT);\n}\n#endif\n\n#endif /* JEMALLOC_H_INLINES */\n/******************************************************************************/\n\n"
  },
  {
    "path": "extern/deprecated/redis-2.8.21/deps/jemalloc/include/jemalloc/internal/rb.h",
    "content": "/*-\n *******************************************************************************\n *\n * cpp macro implementation of left-leaning 2-3 red-black trees.  Parent\n * pointers are not used, and color bits are stored in the least significant\n * bit of right-child pointers (if RB_COMPACT is defined), thus making node\n * linkage as compact as is possible for red-black trees.\n *\n * Usage:\n *\n *   #include <stdint.h>\n *   #include <stdbool.h>\n *   #define NDEBUG // (Optional, see assert(3).)\n *   #include <assert.h>\n *   #define RB_COMPACT // (Optional, embed color bits in right-child pointers.)\n *   #include <rb.h>\n *   ...\n *\n *******************************************************************************\n */\n\n#ifndef RB_H_\n#define\tRB_H_\n\n#ifdef RB_COMPACT\n/* Node structure. */\n#define\trb_node(a_type)\t\t\t\t\t\t\t\\\nstruct {\t\t\t\t\t\t\t\t\\\n    a_type *rbn_left;\t\t\t\t\t\t\t\\\n    a_type *rbn_right_red;\t\t\t\t\t\t\\\n}\n#else\n#define\trb_node(a_type)\t\t\t\t\t\t\t\\\nstruct {\t\t\t\t\t\t\t\t\\\n    a_type *rbn_left;\t\t\t\t\t\t\t\\\n    a_type *rbn_right;\t\t\t\t\t\t\t\\\n    bool rbn_red;\t\t\t\t\t\t\t\\\n}\n#endif\n\n/* Root structure. */\n#define\trb_tree(a_type)\t\t\t\t\t\t\t\\\nstruct {\t\t\t\t\t\t\t\t\\\n    a_type *rbt_root;\t\t\t\t\t\t\t\\\n    a_type rbt_nil;\t\t\t\t\t\t\t\\\n}\n\n/* Left accessors. */\n#define\trbtn_left_get(a_type, a_field, a_node)\t\t\t\t\\\n    ((a_node)->a_field.rbn_left)\n#define\trbtn_left_set(a_type, a_field, a_node, a_left) do {\t\t\\\n    (a_node)->a_field.rbn_left = a_left;\t\t\t\t\\\n} while (0)\n\n#ifdef RB_COMPACT\n/* Right accessors. */\n#define\trbtn_right_get(a_type, a_field, a_node)\t\t\t\t\\\n    ((a_type *) (((intptr_t) (a_node)->a_field.rbn_right_red)\t\t\\\n      & ((ssize_t)-2)))\n#define\trbtn_right_set(a_type, a_field, a_node, a_right) do {\t\t\\\n    (a_node)->a_field.rbn_right_red = (a_type *) (((uintptr_t) a_right)\t\\\n      | (((uintptr_t) (a_node)->a_field.rbn_right_red) & ((size_t)1)));\t\\\n} while (0)\n\n/* Color accessors. */\n#define\trbtn_red_get(a_type, a_field, a_node)\t\t\t\t\\\n    ((bool) (((uintptr_t) (a_node)->a_field.rbn_right_red)\t\t\\\n      & ((size_t)1)))\n#define\trbtn_color_set(a_type, a_field, a_node, a_red) do {\t\t\\\n    (a_node)->a_field.rbn_right_red = (a_type *) ((((intptr_t)\t\t\\\n      (a_node)->a_field.rbn_right_red) & ((ssize_t)-2))\t\t\t\\\n      | ((ssize_t)a_red));\t\t\t\t\t\t\\\n} while (0)\n#define\trbtn_red_set(a_type, a_field, a_node) do {\t\t\t\\\n    (a_node)->a_field.rbn_right_red = (a_type *) (((uintptr_t)\t\t\\\n      (a_node)->a_field.rbn_right_red) | ((size_t)1));\t\t\t\\\n} while (0)\n#define\trbtn_black_set(a_type, a_field, a_node) do {\t\t\t\\\n    (a_node)->a_field.rbn_right_red = (a_type *) (((intptr_t)\t\t\\\n      (a_node)->a_field.rbn_right_red) & ((ssize_t)-2));\t\t\\\n} while (0)\n#else\n/* Right accessors. */\n#define\trbtn_right_get(a_type, a_field, a_node)\t\t\t\t\\\n    ((a_node)->a_field.rbn_right)\n#define\trbtn_right_set(a_type, a_field, a_node, a_right) do {\t\t\\\n    (a_node)->a_field.rbn_right = a_right;\t\t\t\t\\\n} while (0)\n\n/* Color accessors. */\n#define\trbtn_red_get(a_type, a_field, a_node)\t\t\t\t\\\n    ((a_node)->a_field.rbn_red)\n#define\trbtn_color_set(a_type, a_field, a_node, a_red) do {\t\t\\\n    (a_node)->a_field.rbn_red = (a_red);\t\t\t\t\\\n} while (0)\n#define\trbtn_red_set(a_type, a_field, a_node) do {\t\t\t\\\n    (a_node)->a_field.rbn_red = true;\t\t\t\t\t\\\n} while (0)\n#define\trbtn_black_set(a_type, a_field, a_node) do {\t\t\t\\\n    (a_node)->a_field.rbn_red = false;\t\t\t\t\t\\\n} while (0)\n#endif\n\n/* Node initializer. */\n#define\trbt_node_new(a_type, a_field, a_rbt, a_node) do {\t\t\\\n    rbtn_left_set(a_type, a_field, (a_node), &(a_rbt)->rbt_nil);\t\\\n    rbtn_right_set(a_type, a_field, (a_node), &(a_rbt)->rbt_nil);\t\\\n    rbtn_red_set(a_type, a_field, (a_node));\t\t\t\t\\\n} while (0)\n\n/* Tree initializer. */\n#define\trb_new(a_type, a_field, a_rbt) do {\t\t\t\t\\\n    (a_rbt)->rbt_root = &(a_rbt)->rbt_nil;\t\t\t\t\\\n    rbt_node_new(a_type, a_field, a_rbt, &(a_rbt)->rbt_nil);\t\t\\\n    rbtn_black_set(a_type, a_field, &(a_rbt)->rbt_nil);\t\t\t\\\n} while (0)\n\n/* Internal utility macros. */\n#define\trbtn_first(a_type, a_field, a_rbt, a_root, r_node) do {\t\t\\\n    (r_node) = (a_root);\t\t\t\t\t\t\\\n    if ((r_node) != &(a_rbt)->rbt_nil) {\t\t\t\t\\\n\tfor (;\t\t\t\t\t\t\t\t\\\n\t  rbtn_left_get(a_type, a_field, (r_node)) != &(a_rbt)->rbt_nil;\\\n\t  (r_node) = rbtn_left_get(a_type, a_field, (r_node))) {\t\\\n\t}\t\t\t\t\t\t\t\t\\\n    }\t\t\t\t\t\t\t\t\t\\\n} while (0)\n\n#define\trbtn_last(a_type, a_field, a_rbt, a_root, r_node) do {\t\t\\\n    (r_node) = (a_root);\t\t\t\t\t\t\\\n    if ((r_node) != &(a_rbt)->rbt_nil) {\t\t\t\t\\\n\tfor (; rbtn_right_get(a_type, a_field, (r_node)) !=\t\t\\\n\t  &(a_rbt)->rbt_nil; (r_node) = rbtn_right_get(a_type, a_field,\t\\\n\t  (r_node))) {\t\t\t\t\t\t\t\\\n\t}\t\t\t\t\t\t\t\t\\\n    }\t\t\t\t\t\t\t\t\t\\\n} while (0)\n\n#define\trbtn_rotate_left(a_type, a_field, a_node, r_node) do {\t\t\\\n    (r_node) = rbtn_right_get(a_type, a_field, (a_node));\t\t\\\n    rbtn_right_set(a_type, a_field, (a_node),\t\t\t\t\\\n      rbtn_left_get(a_type, a_field, (r_node)));\t\t\t\\\n    rbtn_left_set(a_type, a_field, (r_node), (a_node));\t\t\t\\\n} while (0)\n\n#define\trbtn_rotate_right(a_type, a_field, a_node, r_node) do {\t\t\\\n    (r_node) = rbtn_left_get(a_type, a_field, (a_node));\t\t\\\n    rbtn_left_set(a_type, a_field, (a_node),\t\t\t\t\\\n      rbtn_right_get(a_type, a_field, (r_node)));\t\t\t\\\n    rbtn_right_set(a_type, a_field, (r_node), (a_node));\t\t\\\n} while (0)\n\n/*\n * The rb_proto() macro generates function prototypes that correspond to the\n * functions generated by an equivalently parameterized call to rb_gen().\n */\n\n#define\trb_proto(a_attr, a_prefix, a_rbt_type, a_type)\t\t\t\\\na_attr void\t\t\t\t\t\t\t\t\\\na_prefix##new(a_rbt_type *rbtree);\t\t\t\t\t\\\na_attr a_type *\t\t\t\t\t\t\t\t\\\na_prefix##first(a_rbt_type *rbtree);\t\t\t\t\t\\\na_attr a_type *\t\t\t\t\t\t\t\t\\\na_prefix##last(a_rbt_type *rbtree);\t\t\t\t\t\\\na_attr a_type *\t\t\t\t\t\t\t\t\\\na_prefix##next(a_rbt_type *rbtree, a_type *node);\t\t\t\\\na_attr a_type *\t\t\t\t\t\t\t\t\\\na_prefix##prev(a_rbt_type *rbtree, a_type *node);\t\t\t\\\na_attr a_type *\t\t\t\t\t\t\t\t\\\na_prefix##search(a_rbt_type *rbtree, a_type *key);\t\t\t\\\na_attr a_type *\t\t\t\t\t\t\t\t\\\na_prefix##nsearch(a_rbt_type *rbtree, a_type *key);\t\t\t\\\na_attr a_type *\t\t\t\t\t\t\t\t\\\na_prefix##psearch(a_rbt_type *rbtree, a_type *key);\t\t\t\\\na_attr void\t\t\t\t\t\t\t\t\\\na_prefix##insert(a_rbt_type *rbtree, a_type *node);\t\t\t\\\na_attr void\t\t\t\t\t\t\t\t\\\na_prefix##remove(a_rbt_type *rbtree, a_type *node);\t\t\t\\\na_attr a_type *\t\t\t\t\t\t\t\t\\\na_prefix##iter(a_rbt_type *rbtree, a_type *start, a_type *(*cb)(\t\\\n  a_rbt_type *, a_type *, void *), void *arg);\t\t\t\t\\\na_attr a_type *\t\t\t\t\t\t\t\t\\\na_prefix##reverse_iter(a_rbt_type *rbtree, a_type *start,\t\t\\\n  a_type *(*cb)(a_rbt_type *, a_type *, void *), void *arg);\n\n/*\n * The rb_gen() macro generates a type-specific red-black tree implementation,\n * based on the above cpp macros.\n *\n * Arguments:\n *\n *   a_attr    : Function attribute for generated functions (ex: static).\n *   a_prefix  : Prefix for generated functions (ex: ex_).\n *   a_rb_type : Type for red-black tree data structure (ex: ex_t).\n *   a_type    : Type for red-black tree node data structure (ex: ex_node_t).\n *   a_field   : Name of red-black tree node linkage (ex: ex_link).\n *   a_cmp     : Node comparison function name, with the following prototype:\n *                 int (a_cmp *)(a_type *a_node, a_type *a_other);\n *                                       ^^^^^^\n *                                    or a_key\n *               Interpretation of comparision function return values:\n *                 -1 : a_node <  a_other\n *                  0 : a_node == a_other\n *                  1 : a_node >  a_other\n *               In all cases, the a_node or a_key macro argument is the first\n *               argument to the comparison function, which makes it possible\n *               to write comparison functions that treat the first argument\n *               specially.\n *\n * Assuming the following setup:\n *\n *   typedef struct ex_node_s ex_node_t;\n *   struct ex_node_s {\n *       rb_node(ex_node_t) ex_link;\n *   };\n *   typedef rb_tree(ex_node_t) ex_t;\n *   rb_gen(static, ex_, ex_t, ex_node_t, ex_link, ex_cmp)\n *\n * The following API is generated:\n *\n *   static void\n *   ex_new(ex_t *tree);\n *       Description: Initialize a red-black tree structure.\n *       Args:\n *         tree: Pointer to an uninitialized red-black tree object.\n *\n *   static ex_node_t *\n *   ex_first(ex_t *tree);\n *   static ex_node_t *\n *   ex_last(ex_t *tree);\n *       Description: Get the first/last node in tree.\n *       Args:\n *         tree: Pointer to an initialized red-black tree object.\n *       Ret: First/last node in tree, or NULL if tree is empty.\n *\n *   static ex_node_t *\n *   ex_next(ex_t *tree, ex_node_t *node);\n *   static ex_node_t *\n *   ex_prev(ex_t *tree, ex_node_t *node);\n *       Description: Get node's successor/predecessor.\n *       Args:\n *         tree: Pointer to an initialized red-black tree object.\n *         node: A node in tree.\n *       Ret: node's successor/predecessor in tree, or NULL if node is\n *            last/first.\n *\n *   static ex_node_t *\n *   ex_search(ex_t *tree, ex_node_t *key);\n *       Description: Search for node that matches key.\n *       Args:\n *         tree: Pointer to an initialized red-black tree object.\n *         key : Search key.\n *       Ret: Node in tree that matches key, or NULL if no match.\n *\n *   static ex_node_t *\n *   ex_nsearch(ex_t *tree, ex_node_t *key);\n *   static ex_node_t *\n *   ex_psearch(ex_t *tree, ex_node_t *key);\n *       Description: Search for node that matches key.  If no match is found,\n *                    return what would be key's successor/predecessor, were\n *                    key in tree.\n *       Args:\n *         tree: Pointer to an initialized red-black tree object.\n *         key : Search key.\n *       Ret: Node in tree that matches key, or if no match, hypothetical node's\n *            successor/predecessor (NULL if no successor/predecessor).\n *\n *   static void\n *   ex_insert(ex_t *tree, ex_node_t *node);\n *       Description: Insert node into tree.\n *       Args:\n *         tree: Pointer to an initialized red-black tree object.\n *         node: Node to be inserted into tree.\n *\n *   static void\n *   ex_remove(ex_t *tree, ex_node_t *node);\n *       Description: Remove node from tree.\n *       Args:\n *         tree: Pointer to an initialized red-black tree object.\n *         node: Node in tree to be removed.\n *\n *   static ex_node_t *\n *   ex_iter(ex_t *tree, ex_node_t *start, ex_node_t *(*cb)(ex_t *,\n *     ex_node_t *, void *), void *arg);\n *   static ex_node_t *\n *   ex_reverse_iter(ex_t *tree, ex_node_t *start, ex_node *(*cb)(ex_t *,\n *     ex_node_t *, void *), void *arg);\n *       Description: Iterate forward/backward over tree, starting at node.  If\n *                    tree is modified, iteration must be immediately\n *                    terminated by the callback function that causes the\n *                    modification.\n *       Args:\n *         tree : Pointer to an initialized red-black tree object.\n *         start: Node at which to start iteration, or NULL to start at\n *                first/last node.\n *         cb   : Callback function, which is called for each node during\n *                iteration.  Under normal circumstances the callback function\n *                should return NULL, which causes iteration to continue.  If a\n *                callback function returns non-NULL, iteration is immediately\n *                terminated and the non-NULL return value is returned by the\n *                iterator.  This is useful for re-starting iteration after\n *                modifying tree.\n *         arg  : Opaque pointer passed to cb().\n *       Ret: NULL if iteration completed, or the non-NULL callback return value\n *            that caused termination of the iteration.\n */\n#define\trb_gen(a_attr, a_prefix, a_rbt_type, a_type, a_field, a_cmp)\t\\\na_attr void\t\t\t\t\t\t\t\t\\\na_prefix##new(a_rbt_type *rbtree) {\t\t\t\t\t\\\n    rb_new(a_type, a_field, rbtree);\t\t\t\t\t\\\n}\t\t\t\t\t\t\t\t\t\\\na_attr a_type *\t\t\t\t\t\t\t\t\\\na_prefix##first(a_rbt_type *rbtree) {\t\t\t\t\t\\\n    a_type *ret;\t\t\t\t\t\t\t\\\n    rbtn_first(a_type, a_field, rbtree, rbtree->rbt_root, ret);\t\t\\\n    if (ret == &rbtree->rbt_nil) {\t\t\t\t\t\\\n\tret = NULL;\t\t\t\t\t\t\t\\\n    }\t\t\t\t\t\t\t\t\t\\\n    return (ret);\t\t\t\t\t\t\t\\\n}\t\t\t\t\t\t\t\t\t\\\na_attr a_type *\t\t\t\t\t\t\t\t\\\na_prefix##last(a_rbt_type *rbtree) {\t\t\t\t\t\\\n    a_type *ret;\t\t\t\t\t\t\t\\\n    rbtn_last(a_type, a_field, rbtree, rbtree->rbt_root, ret);\t\t\\\n    if (ret == &rbtree->rbt_nil) {\t\t\t\t\t\\\n\tret = NULL;\t\t\t\t\t\t\t\\\n    }\t\t\t\t\t\t\t\t\t\\\n    return (ret);\t\t\t\t\t\t\t\\\n}\t\t\t\t\t\t\t\t\t\\\na_attr a_type *\t\t\t\t\t\t\t\t\\\na_prefix##next(a_rbt_type *rbtree, a_type *node) {\t\t\t\\\n    a_type *ret;\t\t\t\t\t\t\t\\\n    if (rbtn_right_get(a_type, a_field, node) != &rbtree->rbt_nil) {\t\\\n\trbtn_first(a_type, a_field, rbtree, rbtn_right_get(a_type,\t\\\n\t  a_field, node), ret);\t\t\t\t\t\t\\\n    } else {\t\t\t\t\t\t\t\t\\\n\ta_type *tnode = rbtree->rbt_root;\t\t\t\t\\\n\tassert(tnode != &rbtree->rbt_nil);\t\t\t\t\\\n\tret = &rbtree->rbt_nil;\t\t\t\t\t\t\\\n\twhile (true) {\t\t\t\t\t\t\t\\\n\t    int cmp = (a_cmp)(node, tnode);\t\t\t\t\\\n\t    if (cmp < 0) {\t\t\t\t\t\t\\\n\t\tret = tnode;\t\t\t\t\t\t\\\n\t\ttnode = rbtn_left_get(a_type, a_field, tnode);\t\t\\\n\t    } else if (cmp > 0) {\t\t\t\t\t\\\n\t\ttnode = rbtn_right_get(a_type, a_field, tnode);\t\t\\\n\t    } else {\t\t\t\t\t\t\t\\\n\t\tbreak;\t\t\t\t\t\t\t\\\n\t    }\t\t\t\t\t\t\t\t\\\n\t    assert(tnode != &rbtree->rbt_nil);\t\t\t\t\\\n\t}\t\t\t\t\t\t\t\t\\\n    }\t\t\t\t\t\t\t\t\t\\\n    if (ret == &rbtree->rbt_nil) {\t\t\t\t\t\\\n\tret = (NULL);\t\t\t\t\t\t\t\\\n    }\t\t\t\t\t\t\t\t\t\\\n    return (ret);\t\t\t\t\t\t\t\\\n}\t\t\t\t\t\t\t\t\t\\\na_attr a_type *\t\t\t\t\t\t\t\t\\\na_prefix##prev(a_rbt_type *rbtree, a_type *node) {\t\t\t\\\n    a_type *ret;\t\t\t\t\t\t\t\\\n    if (rbtn_left_get(a_type, a_field, node) != &rbtree->rbt_nil) {\t\\\n\trbtn_last(a_type, a_field, rbtree, rbtn_left_get(a_type,\t\\\n\t  a_field, node), ret);\t\t\t\t\t\t\\\n    } else {\t\t\t\t\t\t\t\t\\\n\ta_type *tnode = rbtree->rbt_root;\t\t\t\t\\\n\tassert(tnode != &rbtree->rbt_nil);\t\t\t\t\\\n\tret = &rbtree->rbt_nil;\t\t\t\t\t\t\\\n\twhile (true) {\t\t\t\t\t\t\t\\\n\t    int cmp = (a_cmp)(node, tnode);\t\t\t\t\\\n\t    if (cmp < 0) {\t\t\t\t\t\t\\\n\t\ttnode = rbtn_left_get(a_type, a_field, tnode);\t\t\\\n\t    } else if (cmp > 0) {\t\t\t\t\t\\\n\t\tret = tnode;\t\t\t\t\t\t\\\n\t\ttnode = rbtn_right_get(a_type, a_field, tnode);\t\t\\\n\t    } else {\t\t\t\t\t\t\t\\\n\t\tbreak;\t\t\t\t\t\t\t\\\n\t    }\t\t\t\t\t\t\t\t\\\n\t    assert(tnode != &rbtree->rbt_nil);\t\t\t\t\\\n\t}\t\t\t\t\t\t\t\t\\\n    }\t\t\t\t\t\t\t\t\t\\\n    if (ret == &rbtree->rbt_nil) {\t\t\t\t\t\\\n\tret = (NULL);\t\t\t\t\t\t\t\\\n    }\t\t\t\t\t\t\t\t\t\\\n    return (ret);\t\t\t\t\t\t\t\\\n}\t\t\t\t\t\t\t\t\t\\\na_attr a_type *\t\t\t\t\t\t\t\t\\\na_prefix##search(a_rbt_type *rbtree, a_type *key) {\t\t\t\\\n    a_type *ret;\t\t\t\t\t\t\t\\\n    int cmp;\t\t\t\t\t\t\t\t\\\n    ret = rbtree->rbt_root;\t\t\t\t\t\t\\\n    while (ret != &rbtree->rbt_nil\t\t\t\t\t\\\n      && (cmp = (a_cmp)(key, ret)) != 0) {\t\t\t\t\\\n\tif (cmp < 0) {\t\t\t\t\t\t\t\\\n\t    ret = rbtn_left_get(a_type, a_field, ret);\t\t\t\\\n\t} else {\t\t\t\t\t\t\t\\\n\t    ret = rbtn_right_get(a_type, a_field, ret);\t\t\t\\\n\t}\t\t\t\t\t\t\t\t\\\n    }\t\t\t\t\t\t\t\t\t\\\n    if (ret == &rbtree->rbt_nil) {\t\t\t\t\t\\\n\tret = (NULL);\t\t\t\t\t\t\t\\\n    }\t\t\t\t\t\t\t\t\t\\\n    return (ret);\t\t\t\t\t\t\t\\\n}\t\t\t\t\t\t\t\t\t\\\na_attr a_type *\t\t\t\t\t\t\t\t\\\na_prefix##nsearch(a_rbt_type *rbtree, a_type *key) {\t\t\t\\\n    a_type *ret;\t\t\t\t\t\t\t\\\n    a_type *tnode = rbtree->rbt_root;\t\t\t\t\t\\\n    ret = &rbtree->rbt_nil;\t\t\t\t\t\t\\\n    while (tnode != &rbtree->rbt_nil) {\t\t\t\t\t\\\n\tint cmp = (a_cmp)(key, tnode);\t\t\t\t\t\\\n\tif (cmp < 0) {\t\t\t\t\t\t\t\\\n\t    ret = tnode;\t\t\t\t\t\t\\\n\t    tnode = rbtn_left_get(a_type, a_field, tnode);\t\t\\\n\t} else if (cmp > 0) {\t\t\t\t\t\t\\\n\t    tnode = rbtn_right_get(a_type, a_field, tnode);\t\t\\\n\t} else {\t\t\t\t\t\t\t\\\n\t    ret = tnode;\t\t\t\t\t\t\\\n\t    break;\t\t\t\t\t\t\t\\\n\t}\t\t\t\t\t\t\t\t\\\n    }\t\t\t\t\t\t\t\t\t\\\n    if (ret == &rbtree->rbt_nil) {\t\t\t\t\t\\\n\tret = (NULL);\t\t\t\t\t\t\t\\\n    }\t\t\t\t\t\t\t\t\t\\\n    return (ret);\t\t\t\t\t\t\t\\\n}\t\t\t\t\t\t\t\t\t\\\na_attr a_type *\t\t\t\t\t\t\t\t\\\na_prefix##psearch(a_rbt_type *rbtree, a_type *key) {\t\t\t\\\n    a_type *ret;\t\t\t\t\t\t\t\\\n    a_type *tnode = rbtree->rbt_root;\t\t\t\t\t\\\n    ret = &rbtree->rbt_nil;\t\t\t\t\t\t\\\n    while (tnode != &rbtree->rbt_nil) {\t\t\t\t\t\\\n\tint cmp = (a_cmp)(key, tnode);\t\t\t\t\t\\\n\tif (cmp < 0) {\t\t\t\t\t\t\t\\\n\t    tnode = rbtn_left_get(a_type, a_field, tnode);\t\t\\\n\t} else if (cmp > 0) {\t\t\t\t\t\t\\\n\t    ret = tnode;\t\t\t\t\t\t\\\n\t    tnode = rbtn_right_get(a_type, a_field, tnode);\t\t\\\n\t} else {\t\t\t\t\t\t\t\\\n\t    ret = tnode;\t\t\t\t\t\t\\\n\t    break;\t\t\t\t\t\t\t\\\n\t}\t\t\t\t\t\t\t\t\\\n    }\t\t\t\t\t\t\t\t\t\\\n    if (ret == &rbtree->rbt_nil) {\t\t\t\t\t\\\n\tret = (NULL);\t\t\t\t\t\t\t\\\n    }\t\t\t\t\t\t\t\t\t\\\n    return (ret);\t\t\t\t\t\t\t\\\n}\t\t\t\t\t\t\t\t\t\\\na_attr void\t\t\t\t\t\t\t\t\\\na_prefix##insert(a_rbt_type *rbtree, a_type *node) {\t\t\t\\\n    struct {\t\t\t\t\t\t\t\t\\\n\ta_type *node;\t\t\t\t\t\t\t\\\n\tint cmp;\t\t\t\t\t\t\t\\\n    } path[sizeof(void *) << 4], *pathp;\t\t\t\t\\\n    rbt_node_new(a_type, a_field, rbtree, node);\t\t\t\\\n    /* Wind. */\t\t\t\t\t\t\t\t\\\n    path->node = rbtree->rbt_root;\t\t\t\t\t\\\n    for (pathp = path; pathp->node != &rbtree->rbt_nil; pathp++) {\t\\\n\tint cmp = pathp->cmp = a_cmp(node, pathp->node);\t\t\\\n\tassert(cmp != 0);\t\t\t\t\t\t\\\n\tif (cmp < 0) {\t\t\t\t\t\t\t\\\n\t    pathp[1].node = rbtn_left_get(a_type, a_field,\t\t\\\n\t      pathp->node);\t\t\t\t\t\t\\\n\t} else {\t\t\t\t\t\t\t\\\n\t    pathp[1].node = rbtn_right_get(a_type, a_field,\t\t\\\n\t      pathp->node);\t\t\t\t\t\t\\\n\t}\t\t\t\t\t\t\t\t\\\n    }\t\t\t\t\t\t\t\t\t\\\n    pathp->node = node;\t\t\t\t\t\t\t\\\n    /* Unwind. */\t\t\t\t\t\t\t\\\n    for (pathp--; (uintptr_t)pathp >= (uintptr_t)path; pathp--) {\t\\\n\ta_type *cnode = pathp->node;\t\t\t\t\t\\\n\tif (pathp->cmp < 0) {\t\t\t\t\t\t\\\n\t    a_type *left = pathp[1].node;\t\t\t\t\\\n\t    rbtn_left_set(a_type, a_field, cnode, left);\t\t\\\n\t    if (rbtn_red_get(a_type, a_field, left)) {\t\t\t\\\n\t\ta_type *leftleft = rbtn_left_get(a_type, a_field, left);\\\n\t\tif (rbtn_red_get(a_type, a_field, leftleft)) {\t\t\\\n\t\t    /* Fix up 4-node. */\t\t\t\t\\\n\t\t    a_type *tnode;\t\t\t\t\t\\\n\t\t    rbtn_black_set(a_type, a_field, leftleft);\t\t\\\n\t\t    rbtn_rotate_right(a_type, a_field, cnode, tnode);\t\\\n\t\t    cnode = tnode;\t\t\t\t\t\\\n\t\t}\t\t\t\t\t\t\t\\\n\t    } else {\t\t\t\t\t\t\t\\\n\t\treturn;\t\t\t\t\t\t\t\\\n\t    }\t\t\t\t\t\t\t\t\\\n\t} else {\t\t\t\t\t\t\t\\\n\t    a_type *right = pathp[1].node;\t\t\t\t\\\n\t    rbtn_right_set(a_type, a_field, cnode, right);\t\t\\\n\t    if (rbtn_red_get(a_type, a_field, right)) {\t\t\t\\\n\t\ta_type *left = rbtn_left_get(a_type, a_field, cnode);\t\\\n\t\tif (rbtn_red_get(a_type, a_field, left)) {\t\t\\\n\t\t    /* Split 4-node. */\t\t\t\t\t\\\n\t\t    rbtn_black_set(a_type, a_field, left);\t\t\\\n\t\t    rbtn_black_set(a_type, a_field, right);\t\t\\\n\t\t    rbtn_red_set(a_type, a_field, cnode);\t\t\\\n\t\t} else {\t\t\t\t\t\t\\\n\t\t    /* Lean left. */\t\t\t\t\t\\\n\t\t    a_type *tnode;\t\t\t\t\t\\\n\t\t    bool tred = rbtn_red_get(a_type, a_field, cnode);\t\\\n\t\t    rbtn_rotate_left(a_type, a_field, cnode, tnode);\t\\\n\t\t    rbtn_color_set(a_type, a_field, tnode, tred);\t\\\n\t\t    rbtn_red_set(a_type, a_field, cnode);\t\t\\\n\t\t    cnode = tnode;\t\t\t\t\t\\\n\t\t}\t\t\t\t\t\t\t\\\n\t    } else {\t\t\t\t\t\t\t\\\n\t\treturn;\t\t\t\t\t\t\t\\\n\t    }\t\t\t\t\t\t\t\t\\\n\t}\t\t\t\t\t\t\t\t\\\n\tpathp->node = cnode;\t\t\t\t\t\t\\\n    }\t\t\t\t\t\t\t\t\t\\\n    /* Set root, and make it black. */\t\t\t\t\t\\\n    rbtree->rbt_root = path->node;\t\t\t\t\t\\\n    rbtn_black_set(a_type, a_field, rbtree->rbt_root);\t\t\t\\\n}\t\t\t\t\t\t\t\t\t\\\na_attr void\t\t\t\t\t\t\t\t\\\na_prefix##remove(a_rbt_type *rbtree, a_type *node) {\t\t\t\\\n    struct {\t\t\t\t\t\t\t\t\\\n\ta_type *node;\t\t\t\t\t\t\t\\\n\tint cmp;\t\t\t\t\t\t\t\\\n    } *pathp, *nodep, path[sizeof(void *) << 4];\t\t\t\\\n    /* Wind. */\t\t\t\t\t\t\t\t\\\n    nodep = NULL; /* Silence compiler warning. */\t\t\t\\\n    path->node = rbtree->rbt_root;\t\t\t\t\t\\\n    for (pathp = path; pathp->node != &rbtree->rbt_nil; pathp++) {\t\\\n\tint cmp = pathp->cmp = a_cmp(node, pathp->node);\t\t\\\n\tif (cmp < 0) {\t\t\t\t\t\t\t\\\n\t    pathp[1].node = rbtn_left_get(a_type, a_field,\t\t\\\n\t      pathp->node);\t\t\t\t\t\t\\\n\t} else {\t\t\t\t\t\t\t\\\n\t    pathp[1].node = rbtn_right_get(a_type, a_field,\t\t\\\n\t      pathp->node);\t\t\t\t\t\t\\\n\t    if (cmp == 0) {\t\t\t\t\t\t\\\n\t        /* Find node's successor, in preparation for swap. */\t\\\n\t\tpathp->cmp = 1;\t\t\t\t\t\t\\\n\t\tnodep = pathp;\t\t\t\t\t\t\\\n\t\tfor (pathp++; pathp->node != &rbtree->rbt_nil;\t\t\\\n\t\t  pathp++) {\t\t\t\t\t\t\\\n\t\t    pathp->cmp = -1;\t\t\t\t\t\\\n\t\t    pathp[1].node = rbtn_left_get(a_type, a_field,\t\\\n\t\t      pathp->node);\t\t\t\t\t\\\n\t\t}\t\t\t\t\t\t\t\\\n\t\tbreak;\t\t\t\t\t\t\t\\\n\t    }\t\t\t\t\t\t\t\t\\\n\t}\t\t\t\t\t\t\t\t\\\n    }\t\t\t\t\t\t\t\t\t\\\n    assert(nodep->node == node);\t\t\t\t\t\\\n    pathp--;\t\t\t\t\t\t\t\t\\\n    if (pathp->node != node) {\t\t\t\t\t\t\\\n\t/* Swap node with its successor. */\t\t\t\t\\\n\tbool tred = rbtn_red_get(a_type, a_field, pathp->node);\t\t\\\n\trbtn_color_set(a_type, a_field, pathp->node,\t\t\t\\\n\t  rbtn_red_get(a_type, a_field, node));\t\t\t\t\\\n\trbtn_left_set(a_type, a_field, pathp->node,\t\t\t\\\n\t  rbtn_left_get(a_type, a_field, node));\t\t\t\\\n\t/* If node's successor is its right child, the following code */\\\n\t/* will do the wrong thing for the right child pointer.       */\\\n\t/* However, it doesn't matter, because the pointer will be    */\\\n\t/* properly set when the successor is pruned.                 */\\\n\trbtn_right_set(a_type, a_field, pathp->node,\t\t\t\\\n\t  rbtn_right_get(a_type, a_field, node));\t\t\t\\\n\trbtn_color_set(a_type, a_field, node, tred);\t\t\t\\\n\t/* The pruned leaf node's child pointers are never accessed   */\\\n\t/* again, so don't bother setting them to nil.                */\\\n\tnodep->node = pathp->node;\t\t\t\t\t\\\n\tpathp->node = node;\t\t\t\t\t\t\\\n\tif (nodep == path) {\t\t\t\t\t\t\\\n\t    rbtree->rbt_root = nodep->node;\t\t\t\t\\\n\t} else {\t\t\t\t\t\t\t\\\n\t    if (nodep[-1].cmp < 0) {\t\t\t\t\t\\\n\t\trbtn_left_set(a_type, a_field, nodep[-1].node,\t\t\\\n\t\t  nodep->node);\t\t\t\t\t\t\\\n\t    } else {\t\t\t\t\t\t\t\\\n\t\trbtn_right_set(a_type, a_field, nodep[-1].node,\t\t\\\n\t\t  nodep->node);\t\t\t\t\t\t\\\n\t    }\t\t\t\t\t\t\t\t\\\n\t}\t\t\t\t\t\t\t\t\\\n    } else {\t\t\t\t\t\t\t\t\\\n\ta_type *left = rbtn_left_get(a_type, a_field, node);\t\t\\\n\tif (left != &rbtree->rbt_nil) {\t\t\t\t\t\\\n\t    /* node has no successor, but it has a left child.        */\\\n\t    /* Splice node out, without losing the left child.        */\\\n\t    assert(rbtn_red_get(a_type, a_field, node) == false);\t\\\n\t    assert(rbtn_red_get(a_type, a_field, left));\t\t\\\n\t    rbtn_black_set(a_type, a_field, left);\t\t\t\\\n\t    if (pathp == path) {\t\t\t\t\t\\\n\t\trbtree->rbt_root = left;\t\t\t\t\\\n\t    } else {\t\t\t\t\t\t\t\\\n\t\tif (pathp[-1].cmp < 0) {\t\t\t\t\\\n\t\t    rbtn_left_set(a_type, a_field, pathp[-1].node,\t\\\n\t\t      left);\t\t\t\t\t\t\\\n\t\t} else {\t\t\t\t\t\t\\\n\t\t    rbtn_right_set(a_type, a_field, pathp[-1].node,\t\\\n\t\t      left);\t\t\t\t\t\t\\\n\t\t}\t\t\t\t\t\t\t\\\n\t    }\t\t\t\t\t\t\t\t\\\n\t    return;\t\t\t\t\t\t\t\\\n\t} else if (pathp == path) {\t\t\t\t\t\\\n\t    /* The tree only contained one node. */\t\t\t\\\n\t    rbtree->rbt_root = &rbtree->rbt_nil;\t\t\t\\\n\t    return;\t\t\t\t\t\t\t\\\n\t}\t\t\t\t\t\t\t\t\\\n    }\t\t\t\t\t\t\t\t\t\\\n    if (rbtn_red_get(a_type, a_field, pathp->node)) {\t\t\t\\\n\t/* Prune red node, which requires no fixup. */\t\t\t\\\n\tassert(pathp[-1].cmp < 0);\t\t\t\t\t\\\n\trbtn_left_set(a_type, a_field, pathp[-1].node,\t\t\t\\\n\t  &rbtree->rbt_nil);\t\t\t\t\t\t\\\n\treturn;\t\t\t\t\t\t\t\t\\\n    }\t\t\t\t\t\t\t\t\t\\\n    /* The node to be pruned is black, so unwind until balance is     */\\\n    /* restored.                                                      */\\\n    pathp->node = &rbtree->rbt_nil;\t\t\t\t\t\\\n    for (pathp--; (uintptr_t)pathp >= (uintptr_t)path; pathp--) {\t\\\n\tassert(pathp->cmp != 0);\t\t\t\t\t\\\n\tif (pathp->cmp < 0) {\t\t\t\t\t\t\\\n\t    rbtn_left_set(a_type, a_field, pathp->node,\t\t\t\\\n\t      pathp[1].node);\t\t\t\t\t\t\\\n\t    assert(rbtn_red_get(a_type, a_field, pathp[1].node)\t\t\\\n\t      == false);\t\t\t\t\t\t\\\n\t    if (rbtn_red_get(a_type, a_field, pathp->node)) {\t\t\\\n\t\ta_type *right = rbtn_right_get(a_type, a_field,\t\t\\\n\t\t  pathp->node);\t\t\t\t\t\t\\\n\t\ta_type *rightleft = rbtn_left_get(a_type, a_field,\t\\\n\t\t  right);\t\t\t\t\t\t\\\n\t\ta_type *tnode;\t\t\t\t\t\t\\\n\t\tif (rbtn_red_get(a_type, a_field, rightleft)) {\t\t\\\n\t\t    /* In the following diagrams, ||, //, and \\\\      */\\\n\t\t    /* indicate the path to the removed node.         */\\\n\t\t    /*                                                */\\\n\t\t    /*      ||                                        */\\\n\t\t    /*    pathp(r)                                    */\\\n\t\t    /*  //        \\                                   */\\\n\t\t    /* (b)        (b)                                 */\\\n\t\t    /*           /                                    */\\\n\t\t    /*          (r)                                   */\\\n\t\t    /*                                                */\\\n\t\t    rbtn_black_set(a_type, a_field, pathp->node);\t\\\n\t\t    rbtn_rotate_right(a_type, a_field, right, tnode);\t\\\n\t\t    rbtn_right_set(a_type, a_field, pathp->node, tnode);\\\n\t\t    rbtn_rotate_left(a_type, a_field, pathp->node,\t\\\n\t\t      tnode);\t\t\t\t\t\t\\\n\t\t} else {\t\t\t\t\t\t\\\n\t\t    /*      ||                                        */\\\n\t\t    /*    pathp(r)                                    */\\\n\t\t    /*  //        \\                                   */\\\n\t\t    /* (b)        (b)                                 */\\\n\t\t    /*           /                                    */\\\n\t\t    /*          (b)                                   */\\\n\t\t    /*                                                */\\\n\t\t    rbtn_rotate_left(a_type, a_field, pathp->node,\t\\\n\t\t      tnode);\t\t\t\t\t\t\\\n\t\t}\t\t\t\t\t\t\t\\\n\t\t/* Balance restored, but rotation modified subtree    */\\\n\t\t/* root.                                              */\\\n\t\tassert((uintptr_t)pathp > (uintptr_t)path);\t\t\\\n\t\tif (pathp[-1].cmp < 0) {\t\t\t\t\\\n\t\t    rbtn_left_set(a_type, a_field, pathp[-1].node,\t\\\n\t\t      tnode);\t\t\t\t\t\t\\\n\t\t} else {\t\t\t\t\t\t\\\n\t\t    rbtn_right_set(a_type, a_field, pathp[-1].node,\t\\\n\t\t      tnode);\t\t\t\t\t\t\\\n\t\t}\t\t\t\t\t\t\t\\\n\t\treturn;\t\t\t\t\t\t\t\\\n\t    } else {\t\t\t\t\t\t\t\\\n\t\ta_type *right = rbtn_right_get(a_type, a_field,\t\t\\\n\t\t  pathp->node);\t\t\t\t\t\t\\\n\t\ta_type *rightleft = rbtn_left_get(a_type, a_field,\t\\\n\t\t  right);\t\t\t\t\t\t\\\n\t\tif (rbtn_red_get(a_type, a_field, rightleft)) {\t\t\\\n\t\t    /*      ||                                        */\\\n\t\t    /*    pathp(b)                                    */\\\n\t\t    /*  //        \\                                   */\\\n\t\t    /* (b)        (b)                                 */\\\n\t\t    /*           /                                    */\\\n\t\t    /*          (r)                                   */\\\n\t\t    a_type *tnode;\t\t\t\t\t\\\n\t\t    rbtn_black_set(a_type, a_field, rightleft);\t\t\\\n\t\t    rbtn_rotate_right(a_type, a_field, right, tnode);\t\\\n\t\t    rbtn_right_set(a_type, a_field, pathp->node, tnode);\\\n\t\t    rbtn_rotate_left(a_type, a_field, pathp->node,\t\\\n\t\t      tnode);\t\t\t\t\t\t\\\n\t\t    /* Balance restored, but rotation modified        */\\\n\t\t    /* subree root, which may actually be the tree    */\\\n\t\t    /* root.                                          */\\\n\t\t    if (pathp == path) {\t\t\t\t\\\n\t\t\t/* Set root. */\t\t\t\t\t\\\n\t\t\trbtree->rbt_root = tnode;\t\t\t\\\n\t\t    } else {\t\t\t\t\t\t\\\n\t\t\tif (pathp[-1].cmp < 0) {\t\t\t\\\n\t\t\t    rbtn_left_set(a_type, a_field,\t\t\\\n\t\t\t      pathp[-1].node, tnode);\t\t\t\\\n\t\t\t} else {\t\t\t\t\t\\\n\t\t\t    rbtn_right_set(a_type, a_field,\t\t\\\n\t\t\t      pathp[-1].node, tnode);\t\t\t\\\n\t\t\t}\t\t\t\t\t\t\\\n\t\t    }\t\t\t\t\t\t\t\\\n\t\t    return;\t\t\t\t\t\t\\\n\t\t} else {\t\t\t\t\t\t\\\n\t\t    /*      ||                                        */\\\n\t\t    /*    pathp(b)                                    */\\\n\t\t    /*  //        \\                                   */\\\n\t\t    /* (b)        (b)                                 */\\\n\t\t    /*           /                                    */\\\n\t\t    /*          (b)                                   */\\\n\t\t    a_type *tnode;\t\t\t\t\t\\\n\t\t    rbtn_red_set(a_type, a_field, pathp->node);\t\t\\\n\t\t    rbtn_rotate_left(a_type, a_field, pathp->node,\t\\\n\t\t      tnode);\t\t\t\t\t\t\\\n\t\t    pathp->node = tnode;\t\t\t\t\\\n\t\t}\t\t\t\t\t\t\t\\\n\t    }\t\t\t\t\t\t\t\t\\\n\t} else {\t\t\t\t\t\t\t\\\n\t    a_type *left;\t\t\t\t\t\t\\\n\t    rbtn_right_set(a_type, a_field, pathp->node,\t\t\\\n\t      pathp[1].node);\t\t\t\t\t\t\\\n\t    left = rbtn_left_get(a_type, a_field, pathp->node);\t\t\\\n\t    if (rbtn_red_get(a_type, a_field, left)) {\t\t\t\\\n\t\ta_type *tnode;\t\t\t\t\t\t\\\n\t\ta_type *leftright = rbtn_right_get(a_type, a_field,\t\\\n\t\t  left);\t\t\t\t\t\t\\\n\t\ta_type *leftrightleft = rbtn_left_get(a_type, a_field,\t\\\n\t\t  leftright);\t\t\t\t\t\t\\\n\t\tif (rbtn_red_get(a_type, a_field, leftrightleft)) {\t\\\n\t\t    /*      ||                                        */\\\n\t\t    /*    pathp(b)                                    */\\\n\t\t    /*   /        \\\\                                  */\\\n\t\t    /* (r)        (b)                                 */\\\n\t\t    /*   \\                                            */\\\n\t\t    /*   (b)                                          */\\\n\t\t    /*   /                                            */\\\n\t\t    /* (r)                                            */\\\n\t\t    a_type *unode;\t\t\t\t\t\\\n\t\t    rbtn_black_set(a_type, a_field, leftrightleft);\t\\\n\t\t    rbtn_rotate_right(a_type, a_field, pathp->node,\t\\\n\t\t      unode);\t\t\t\t\t\t\\\n\t\t    rbtn_rotate_right(a_type, a_field, pathp->node,\t\\\n\t\t      tnode);\t\t\t\t\t\t\\\n\t\t    rbtn_right_set(a_type, a_field, unode, tnode);\t\\\n\t\t    rbtn_rotate_left(a_type, a_field, unode, tnode);\t\\\n\t\t} else {\t\t\t\t\t\t\\\n\t\t    /*      ||                                        */\\\n\t\t    /*    pathp(b)                                    */\\\n\t\t    /*   /        \\\\                                  */\\\n\t\t    /* (r)        (b)                                 */\\\n\t\t    /*   \\                                            */\\\n\t\t    /*   (b)                                          */\\\n\t\t    /*   /                                            */\\\n\t\t    /* (b)                                            */\\\n\t\t    assert(leftright != &rbtree->rbt_nil);\t\t\\\n\t\t    rbtn_red_set(a_type, a_field, leftright);\t\t\\\n\t\t    rbtn_rotate_right(a_type, a_field, pathp->node,\t\\\n\t\t      tnode);\t\t\t\t\t\t\\\n\t\t    rbtn_black_set(a_type, a_field, tnode);\t\t\\\n\t\t}\t\t\t\t\t\t\t\\\n\t\t/* Balance restored, but rotation modified subtree    */\\\n\t\t/* root, which may actually be the tree root.         */\\\n\t\tif (pathp == path) {\t\t\t\t\t\\\n\t\t    /* Set root. */\t\t\t\t\t\\\n\t\t    rbtree->rbt_root = tnode;\t\t\t\t\\\n\t\t} else {\t\t\t\t\t\t\\\n\t\t    if (pathp[-1].cmp < 0) {\t\t\t\t\\\n\t\t\trbtn_left_set(a_type, a_field, pathp[-1].node,\t\\\n\t\t\t  tnode);\t\t\t\t\t\\\n\t\t    } else {\t\t\t\t\t\t\\\n\t\t\trbtn_right_set(a_type, a_field, pathp[-1].node,\t\\\n\t\t\t  tnode);\t\t\t\t\t\\\n\t\t    }\t\t\t\t\t\t\t\\\n\t\t}\t\t\t\t\t\t\t\\\n\t\treturn;\t\t\t\t\t\t\t\\\n\t    } else if (rbtn_red_get(a_type, a_field, pathp->node)) {\t\\\n\t\ta_type *leftleft = rbtn_left_get(a_type, a_field, left);\\\n\t\tif (rbtn_red_get(a_type, a_field, leftleft)) {\t\t\\\n\t\t    /*        ||                                      */\\\n\t\t    /*      pathp(r)                                  */\\\n\t\t    /*     /        \\\\                                */\\\n\t\t    /*   (b)        (b)                               */\\\n\t\t    /*   /                                            */\\\n\t\t    /* (r)                                            */\\\n\t\t    a_type *tnode;\t\t\t\t\t\\\n\t\t    rbtn_black_set(a_type, a_field, pathp->node);\t\\\n\t\t    rbtn_red_set(a_type, a_field, left);\t\t\\\n\t\t    rbtn_black_set(a_type, a_field, leftleft);\t\t\\\n\t\t    rbtn_rotate_right(a_type, a_field, pathp->node,\t\\\n\t\t      tnode);\t\t\t\t\t\t\\\n\t\t    /* Balance restored, but rotation modified        */\\\n\t\t    /* subtree root.                                  */\\\n\t\t    assert((uintptr_t)pathp > (uintptr_t)path);\t\t\\\n\t\t    if (pathp[-1].cmp < 0) {\t\t\t\t\\\n\t\t\trbtn_left_set(a_type, a_field, pathp[-1].node,\t\\\n\t\t\t  tnode);\t\t\t\t\t\\\n\t\t    } else {\t\t\t\t\t\t\\\n\t\t\trbtn_right_set(a_type, a_field, pathp[-1].node,\t\\\n\t\t\t  tnode);\t\t\t\t\t\\\n\t\t    }\t\t\t\t\t\t\t\\\n\t\t    return;\t\t\t\t\t\t\\\n\t\t} else {\t\t\t\t\t\t\\\n\t\t    /*        ||                                      */\\\n\t\t    /*      pathp(r)                                  */\\\n\t\t    /*     /        \\\\                                */\\\n\t\t    /*   (b)        (b)                               */\\\n\t\t    /*   /                                            */\\\n\t\t    /* (b)                                            */\\\n\t\t    rbtn_red_set(a_type, a_field, left);\t\t\\\n\t\t    rbtn_black_set(a_type, a_field, pathp->node);\t\\\n\t\t    /* Balance restored. */\t\t\t\t\\\n\t\t    return;\t\t\t\t\t\t\\\n\t\t}\t\t\t\t\t\t\t\\\n\t    } else {\t\t\t\t\t\t\t\\\n\t\ta_type *leftleft = rbtn_left_get(a_type, a_field, left);\\\n\t\tif (rbtn_red_get(a_type, a_field, leftleft)) {\t\t\\\n\t\t    /*               ||                               */\\\n\t\t    /*             pathp(b)                           */\\\n\t\t    /*            /        \\\\                         */\\\n\t\t    /*          (b)        (b)                        */\\\n\t\t    /*          /                                     */\\\n\t\t    /*        (r)                                     */\\\n\t\t    a_type *tnode;\t\t\t\t\t\\\n\t\t    rbtn_black_set(a_type, a_field, leftleft);\t\t\\\n\t\t    rbtn_rotate_right(a_type, a_field, pathp->node,\t\\\n\t\t      tnode);\t\t\t\t\t\t\\\n\t\t    /* Balance restored, but rotation modified        */\\\n\t\t    /* subtree root, which may actually be the tree   */\\\n\t\t    /* root.                                          */\\\n\t\t    if (pathp == path) {\t\t\t\t\\\n\t\t\t/* Set root. */\t\t\t\t\t\\\n\t\t\trbtree->rbt_root = tnode;\t\t\t\\\n\t\t    } else {\t\t\t\t\t\t\\\n\t\t\tif (pathp[-1].cmp < 0) {\t\t\t\\\n\t\t\t    rbtn_left_set(a_type, a_field,\t\t\\\n\t\t\t      pathp[-1].node, tnode);\t\t\t\\\n\t\t\t} else {\t\t\t\t\t\\\n\t\t\t    rbtn_right_set(a_type, a_field,\t\t\\\n\t\t\t      pathp[-1].node, tnode);\t\t\t\\\n\t\t\t}\t\t\t\t\t\t\\\n\t\t    }\t\t\t\t\t\t\t\\\n\t\t    return;\t\t\t\t\t\t\\\n\t\t} else {\t\t\t\t\t\t\\\n\t\t    /*               ||                               */\\\n\t\t    /*             pathp(b)                           */\\\n\t\t    /*            /        \\\\                         */\\\n\t\t    /*          (b)        (b)                        */\\\n\t\t    /*          /                                     */\\\n\t\t    /*        (b)                                     */\\\n\t\t    rbtn_red_set(a_type, a_field, left);\t\t\\\n\t\t}\t\t\t\t\t\t\t\\\n\t    }\t\t\t\t\t\t\t\t\\\n\t}\t\t\t\t\t\t\t\t\\\n    }\t\t\t\t\t\t\t\t\t\\\n    /* Set root. */\t\t\t\t\t\t\t\\\n    rbtree->rbt_root = path->node;\t\t\t\t\t\\\n    assert(rbtn_red_get(a_type, a_field, rbtree->rbt_root) == false);\t\\\n}\t\t\t\t\t\t\t\t\t\\\na_attr a_type *\t\t\t\t\t\t\t\t\\\na_prefix##iter_recurse(a_rbt_type *rbtree, a_type *node,\t\t\\\n  a_type *(*cb)(a_rbt_type *, a_type *, void *), void *arg) {\t\t\\\n    if (node == &rbtree->rbt_nil) {\t\t\t\t\t\\\n\treturn (&rbtree->rbt_nil);\t\t\t\t\t\\\n    } else {\t\t\t\t\t\t\t\t\\\n\ta_type *ret;\t\t\t\t\t\t\t\\\n\tif ((ret = a_prefix##iter_recurse(rbtree, rbtn_left_get(a_type,\t\\\n\t  a_field, node), cb, arg)) != &rbtree->rbt_nil\t\t\t\\\n\t  || (ret = cb(rbtree, node, arg)) != NULL) {\t\t\t\\\n\t    return (ret);\t\t\t\t\t\t\\\n\t}\t\t\t\t\t\t\t\t\\\n\treturn (a_prefix##iter_recurse(rbtree, rbtn_right_get(a_type,\t\\\n\t  a_field, node), cb, arg));\t\t\t\t\t\\\n    }\t\t\t\t\t\t\t\t\t\\\n}\t\t\t\t\t\t\t\t\t\\\na_attr a_type *\t\t\t\t\t\t\t\t\\\na_prefix##iter_start(a_rbt_type *rbtree, a_type *start, a_type *node,\t\\\n  a_type *(*cb)(a_rbt_type *, a_type *, void *), void *arg) {\t\t\\\n    int cmp = a_cmp(start, node);\t\t\t\t\t\\\n    if (cmp < 0) {\t\t\t\t\t\t\t\\\n\ta_type *ret;\t\t\t\t\t\t\t\\\n\tif ((ret = a_prefix##iter_start(rbtree, start,\t\t\t\\\n\t  rbtn_left_get(a_type, a_field, node), cb, arg)) !=\t\t\\\n\t  &rbtree->rbt_nil || (ret = cb(rbtree, node, arg)) != NULL) {\t\\\n\t    return (ret);\t\t\t\t\t\t\\\n\t}\t\t\t\t\t\t\t\t\\\n\treturn (a_prefix##iter_recurse(rbtree, rbtn_right_get(a_type,\t\\\n\t  a_field, node), cb, arg));\t\t\t\t\t\\\n    } else if (cmp > 0) {\t\t\t\t\t\t\\\n\treturn (a_prefix##iter_start(rbtree, start,\t\t\t\\\n\t  rbtn_right_get(a_type, a_field, node), cb, arg));\t\t\\\n    } else {\t\t\t\t\t\t\t\t\\\n\ta_type *ret;\t\t\t\t\t\t\t\\\n\tif ((ret = cb(rbtree, node, arg)) != NULL) {\t\t\t\\\n\t    return (ret);\t\t\t\t\t\t\\\n\t}\t\t\t\t\t\t\t\t\\\n\treturn (a_prefix##iter_recurse(rbtree, rbtn_right_get(a_type,\t\\\n\t  a_field, node), cb, arg));\t\t\t\t\t\\\n    }\t\t\t\t\t\t\t\t\t\\\n}\t\t\t\t\t\t\t\t\t\\\na_attr a_type *\t\t\t\t\t\t\t\t\\\na_prefix##iter(a_rbt_type *rbtree, a_type *start, a_type *(*cb)(\t\\\n  a_rbt_type *, a_type *, void *), void *arg) {\t\t\t\t\\\n    a_type *ret;\t\t\t\t\t\t\t\\\n    if (start != NULL) {\t\t\t\t\t\t\\\n\tret = a_prefix##iter_start(rbtree, start, rbtree->rbt_root,\t\\\n\t  cb, arg);\t\t\t\t\t\t\t\\\n    } else {\t\t\t\t\t\t\t\t\\\n\tret = a_prefix##iter_recurse(rbtree, rbtree->rbt_root, cb, arg);\\\n    }\t\t\t\t\t\t\t\t\t\\\n    if (ret == &rbtree->rbt_nil) {\t\t\t\t\t\\\n\tret = NULL;\t\t\t\t\t\t\t\\\n    }\t\t\t\t\t\t\t\t\t\\\n    return (ret);\t\t\t\t\t\t\t\\\n}\t\t\t\t\t\t\t\t\t\\\na_attr a_type *\t\t\t\t\t\t\t\t\\\na_prefix##reverse_iter_recurse(a_rbt_type *rbtree, a_type *node,\t\\\n  a_type *(*cb)(a_rbt_type *, a_type *, void *), void *arg) {\t\t\\\n    if (node == &rbtree->rbt_nil) {\t\t\t\t\t\\\n\treturn (&rbtree->rbt_nil);\t\t\t\t\t\\\n    } else {\t\t\t\t\t\t\t\t\\\n\ta_type *ret;\t\t\t\t\t\t\t\\\n\tif ((ret = a_prefix##reverse_iter_recurse(rbtree,\t\t\\\n\t  rbtn_right_get(a_type, a_field, node), cb, arg)) !=\t\t\\\n\t  &rbtree->rbt_nil || (ret = cb(rbtree, node, arg)) != NULL) {\t\\\n\t    return (ret);\t\t\t\t\t\t\\\n\t}\t\t\t\t\t\t\t\t\\\n\treturn (a_prefix##reverse_iter_recurse(rbtree,\t\t\t\\\n\t  rbtn_left_get(a_type, a_field, node), cb, arg));\t\t\\\n    }\t\t\t\t\t\t\t\t\t\\\n}\t\t\t\t\t\t\t\t\t\\\na_attr a_type *\t\t\t\t\t\t\t\t\\\na_prefix##reverse_iter_start(a_rbt_type *rbtree, a_type *start,\t\t\\\n  a_type *node, a_type *(*cb)(a_rbt_type *, a_type *, void *),\t\t\\\n  void *arg) {\t\t\t\t\t\t\t\t\\\n    int cmp = a_cmp(start, node);\t\t\t\t\t\\\n    if (cmp > 0) {\t\t\t\t\t\t\t\\\n\ta_type *ret;\t\t\t\t\t\t\t\\\n\tif ((ret = a_prefix##reverse_iter_start(rbtree, start,\t\t\\\n\t  rbtn_right_get(a_type, a_field, node), cb, arg)) !=\t\t\\\n\t  &rbtree->rbt_nil || (ret = cb(rbtree, node, arg)) != NULL) {\t\\\n\t    return (ret);\t\t\t\t\t\t\\\n\t}\t\t\t\t\t\t\t\t\\\n\treturn (a_prefix##reverse_iter_recurse(rbtree,\t\t\t\\\n\t  rbtn_left_get(a_type, a_field, node), cb, arg));\t\t\\\n    } else if (cmp < 0) {\t\t\t\t\t\t\\\n\treturn (a_prefix##reverse_iter_start(rbtree, start,\t\t\\\n\t  rbtn_left_get(a_type, a_field, node), cb, arg));\t\t\\\n    } else {\t\t\t\t\t\t\t\t\\\n\ta_type *ret;\t\t\t\t\t\t\t\\\n\tif ((ret = cb(rbtree, node, arg)) != NULL) {\t\t\t\\\n\t    return (ret);\t\t\t\t\t\t\\\n\t}\t\t\t\t\t\t\t\t\\\n\treturn (a_prefix##reverse_iter_recurse(rbtree,\t\t\t\\\n\t  rbtn_left_get(a_type, a_field, node), cb, arg));\t\t\\\n    }\t\t\t\t\t\t\t\t\t\\\n}\t\t\t\t\t\t\t\t\t\\\na_attr a_type *\t\t\t\t\t\t\t\t\\\na_prefix##reverse_iter(a_rbt_type *rbtree, a_type *start,\t\t\\\n  a_type *(*cb)(a_rbt_type *, a_type *, void *), void *arg) {\t\t\\\n    a_type *ret;\t\t\t\t\t\t\t\\\n    if (start != NULL) {\t\t\t\t\t\t\\\n\tret = a_prefix##reverse_iter_start(rbtree, start,\t\t\\\n\t  rbtree->rbt_root, cb, arg);\t\t\t\t\t\\\n    } else {\t\t\t\t\t\t\t\t\\\n\tret = a_prefix##reverse_iter_recurse(rbtree, rbtree->rbt_root,\t\\\n\t  cb, arg);\t\t\t\t\t\t\t\\\n    }\t\t\t\t\t\t\t\t\t\\\n    if (ret == &rbtree->rbt_nil) {\t\t\t\t\t\\\n\tret = NULL;\t\t\t\t\t\t\t\\\n    }\t\t\t\t\t\t\t\t\t\\\n    return (ret);\t\t\t\t\t\t\t\\\n}\n\n#endif /* RB_H_ */\n"
  },
  {
    "path": "extern/deprecated/redis-2.8.21/deps/jemalloc/include/jemalloc/internal/rtree.h",
    "content": "/*\n * This radix tree implementation is tailored to the singular purpose of\n * tracking which chunks are currently owned by jemalloc.  This functionality\n * is mandatory for OS X, where jemalloc must be able to respond to object\n * ownership queries.\n *\n *******************************************************************************\n */\n#ifdef JEMALLOC_H_TYPES\n\ntypedef struct rtree_s rtree_t;\n\n/*\n * Size of each radix tree node (must be a power of 2).  This impacts tree\n * depth.\n */\n#define\tRTREE_NODESIZE (1U << 16)\n\ntypedef void *(rtree_alloc_t)(size_t);\ntypedef void (rtree_dalloc_t)(void *);\n\n#endif /* JEMALLOC_H_TYPES */\n/******************************************************************************/\n#ifdef JEMALLOC_H_STRUCTS\n\nstruct rtree_s {\n\trtree_alloc_t\t*alloc;\n\trtree_dalloc_t\t*dalloc;\n\tmalloc_mutex_t\tmutex;\n\tvoid\t\t**root;\n\tunsigned\theight;\n\tunsigned\tlevel2bits[1]; /* Dynamically sized. */\n};\n\n#endif /* JEMALLOC_H_STRUCTS */\n/******************************************************************************/\n#ifdef JEMALLOC_H_EXTERNS\n\nrtree_t\t*rtree_new(unsigned bits, rtree_alloc_t *alloc, rtree_dalloc_t *dalloc);\nvoid\trtree_delete(rtree_t *rtree);\nvoid\trtree_prefork(rtree_t *rtree);\nvoid\trtree_postfork_parent(rtree_t *rtree);\nvoid\trtree_postfork_child(rtree_t *rtree);\n\n#endif /* JEMALLOC_H_EXTERNS */\n/******************************************************************************/\n#ifdef JEMALLOC_H_INLINES\n\n#ifndef JEMALLOC_ENABLE_INLINE\n#ifdef JEMALLOC_DEBUG\nuint8_t rtree_get_locked(rtree_t *rtree, uintptr_t key);\n#endif\nuint8_t\trtree_get(rtree_t *rtree, uintptr_t key);\nbool\trtree_set(rtree_t *rtree, uintptr_t key, uint8_t val);\n#endif\n\n#if (defined(JEMALLOC_ENABLE_INLINE) || defined(JEMALLOC_RTREE_C_))\n#define\tRTREE_GET_GENERATE(f)\t\t\t\t\t\t\\\n/* The least significant bits of the key are ignored. */\t\t\\\nJEMALLOC_INLINE uint8_t\t\t\t\t\t\t\t\\\nf(rtree_t *rtree, uintptr_t key)\t\t\t\t\t\\\n{\t\t\t\t\t\t\t\t\t\\\n\tuint8_t ret;\t\t\t\t\t\t\t\\\n\tuintptr_t subkey;\t\t\t\t\t\t\\\n\tunsigned i, lshift, height, bits;\t\t\t\t\\\n\tvoid **node, **child;\t\t\t\t\t\t\\\n\t\t\t\t\t\t\t\t\t\\\n\tRTREE_LOCK(&rtree->mutex);\t\t\t\t\t\\\n\tfor (i = lshift = 0, height = rtree->height, node = rtree->root;\\\n\t    i < height - 1;\t\t\t\t\t\t\\\n\t    i++, lshift += bits, node = child) {\t\t\t\\\n\t\tbits = rtree->level2bits[i];\t\t\t\t\\\n\t\tsubkey = (key << lshift) >> ((ZU(1) << (LG_SIZEOF_PTR +\t\\\n\t\t    3)) - bits);\t\t\t\t\t\\\n\t\tchild = (void**)node[subkey];\t\t\t\t\\\n\t\tif (child == NULL) {\t\t\t\t\t\\\n\t\t\tRTREE_UNLOCK(&rtree->mutex);\t\t\t\\\n\t\t\treturn (0);\t\t\t\t\t\\\n\t\t}\t\t\t\t\t\t\t\\\n\t}\t\t\t\t\t\t\t\t\\\n\t\t\t\t\t\t\t\t\t\\\n\t/*\t\t\t\t\t\t\t\t\\\n\t * node is a leaf, so it contains values rather than node\t\\\n\t * pointers.\t\t\t\t\t\t\t\\\n\t */\t\t\t\t\t\t\t\t\\\n\tbits = rtree->level2bits[i];\t\t\t\t\t\\\n\tsubkey = (key << lshift) >> ((ZU(1) << (LG_SIZEOF_PTR+3)) -\t\\\n\t    bits);\t\t\t\t\t\t\t\\\n\t{\t\t\t\t\t\t\t\t\\\n\t\tuint8_t *leaf = (uint8_t *)node;\t\t\t\\\n\t\tret = leaf[subkey];\t\t\t\t\t\\\n\t}\t\t\t\t\t\t\t\t\\\n\tRTREE_UNLOCK(&rtree->mutex);\t\t\t\t\t\\\n\t\t\t\t\t\t\t\t\t\\\n\tRTREE_GET_VALIDATE\t\t\t\t\t\t\\\n\treturn (ret);\t\t\t\t\t\t\t\\\n}\n\n#ifdef JEMALLOC_DEBUG\n#  define RTREE_LOCK(l)\t\tmalloc_mutex_lock(l)\n#  define RTREE_UNLOCK(l)\tmalloc_mutex_unlock(l)\n#  define RTREE_GET_VALIDATE\nRTREE_GET_GENERATE(rtree_get_locked)\n#  undef RTREE_LOCK\n#  undef RTREE_UNLOCK\n#  undef RTREE_GET_VALIDATE\n#endif\n\n#define\tRTREE_LOCK(l)\n#define\tRTREE_UNLOCK(l)\n#ifdef JEMALLOC_DEBUG\n   /*\n    * Suppose that it were possible for a jemalloc-allocated chunk to be\n    * munmap()ped, followed by a different allocator in another thread re-using\n    * overlapping virtual memory, all without invalidating the cached rtree\n    * value.  The result would be a false positive (the rtree would claim that\n    * jemalloc owns memory that it had actually discarded).  This scenario\n    * seems impossible, but the following assertion is a prudent sanity check.\n    */\n#  define RTREE_GET_VALIDATE\t\t\t\t\t\t\\\n\tassert(rtree_get_locked(rtree, key) == ret);\n#else\n#  define RTREE_GET_VALIDATE\n#endif\nRTREE_GET_GENERATE(rtree_get)\n#undef RTREE_LOCK\n#undef RTREE_UNLOCK\n#undef RTREE_GET_VALIDATE\n\nJEMALLOC_INLINE bool\nrtree_set(rtree_t *rtree, uintptr_t key, uint8_t val)\n{\n\tuintptr_t subkey;\n\tunsigned i, lshift, height, bits;\n\tvoid **node, **child;\n\n\tmalloc_mutex_lock(&rtree->mutex);\n\tfor (i = lshift = 0, height = rtree->height, node = rtree->root;\n\t    i < height - 1;\n\t    i++, lshift += bits, node = child) {\n\t\tbits = rtree->level2bits[i];\n\t\tsubkey = (key << lshift) >> ((ZU(1) << (LG_SIZEOF_PTR+3)) -\n\t\t    bits);\n\t\tchild = (void**)node[subkey];\n\t\tif (child == NULL) {\n\t\t\tsize_t size = ((i + 1 < height - 1) ? sizeof(void *)\n\t\t\t    : (sizeof(uint8_t))) << rtree->level2bits[i+1];\n\t\t\tchild = (void**)rtree->alloc(size);\n\t\t\tif (child == NULL) {\n\t\t\t\tmalloc_mutex_unlock(&rtree->mutex);\n\t\t\t\treturn (true);\n\t\t\t}\n\t\t\tmemset(child, 0, size);\n\t\t\tnode[subkey] = child;\n\t\t}\n\t}\n\n\t/* node is a leaf, so it contains values rather than node pointers. */\n\tbits = rtree->level2bits[i];\n\tsubkey = (key << lshift) >> ((ZU(1) << (LG_SIZEOF_PTR+3)) - bits);\n\t{\n\t\tuint8_t *leaf = (uint8_t *)node;\n\t\tleaf[subkey] = val;\n\t}\n\tmalloc_mutex_unlock(&rtree->mutex);\n\n\treturn (false);\n}\n#endif\n\n#endif /* JEMALLOC_H_INLINES */\n/******************************************************************************/\n"
  },
  {
    "path": "extern/deprecated/redis-2.8.21/deps/jemalloc/include/jemalloc/internal/size_classes.sh",
    "content": "#!/bin/sh\n\n# The following limits are chosen such that they cover all supported platforms.\n\n# Range of quanta.\nlg_qmin=3\nlg_qmax=4\n\n# The range of tiny size classes is [2^lg_tmin..2^(lg_q-1)].\nlg_tmin=3\n\n# Range of page sizes.\nlg_pmin=12\nlg_pmax=16\n\npow2() {\n  e=$1\n  pow2_result=1\n  while [ ${e} -gt 0 ] ; do\n    pow2_result=$((${pow2_result} + ${pow2_result}))\n    e=$((${e} - 1))\n  done\n}\n\ncat <<EOF\n/* This file was automatically generated by size_classes.sh. */\n/******************************************************************************/\n#ifdef JEMALLOC_H_TYPES\n\nEOF\n\nlg_q=${lg_qmin}\nwhile [ ${lg_q} -le ${lg_qmax} ] ; do\n  lg_t=${lg_tmin}\n  while [ ${lg_t} -le ${lg_q} ] ; do\n    lg_p=${lg_pmin}\n    while [ ${lg_p} -le ${lg_pmax} ] ; do\n      echo \"#if (LG_TINY_MIN == ${lg_t} && LG_QUANTUM == ${lg_q} && LG_PAGE == ${lg_p})\"\n      echo \"#define\tSIZE_CLASSES_DEFINED\"\n      pow2 ${lg_q}; q=${pow2_result}\n      pow2 ${lg_t}; t=${pow2_result}\n      pow2 ${lg_p}; p=${pow2_result}\n      bin=0\n      psz=0\n      sz=${t}\n      delta=$((${sz} - ${psz}))\n      echo \"/*  SIZE_CLASS(bin,\tdelta,\tsz) */\"\n      echo \"#define\tSIZE_CLASSES\t\t\t\t\t\t\t\\\\\"\n\n      # Tiny size classes.\n      while [ ${sz} -lt ${q} ] ; do\n        echo \"    SIZE_CLASS(${bin},\t${delta},\t${sz})\t\t\t\t\t\\\\\"\n        bin=$((${bin} + 1))\n        psz=${sz}\n        sz=$((${sz} + ${sz}))\n        delta=$((${sz} - ${psz}))\n      done\n      # Quantum-multiple size classes.  For each doubling of sz, as many as 4\n      # size classes exist.  Their spacing is the greater of:\n      # - q\n      # - sz/4, where sz is a power of 2\n      while [ ${sz} -lt ${p} ] ; do\n        if [ ${sz} -ge $((${q} * 4)) ] ; then\n          i=$((${sz} / 4))\n        else\n          i=${q}\n        fi\n        next_2pow=$((${sz} * 2))\n        while [ ${sz} -lt $next_2pow ] ; do\n          echo \"    SIZE_CLASS(${bin},\t${delta},\t${sz})\t\t\t\t\t\\\\\"\n          bin=$((${bin} + 1))\n          psz=${sz}\n          sz=$((${sz} + ${i}))\n          delta=$((${sz} - ${psz}))\n        done\n      done\n      echo\n      echo \"#define\tNBINS\t\t${bin}\"\n      echo \"#define\tSMALL_MAXCLASS\t${psz}\"\n      echo \"#endif\"\n      echo\n      lg_p=$((${lg_p} + 1))\n    done\n    lg_t=$((${lg_t} + 1))\n  done\n  lg_q=$((${lg_q} + 1))\ndone\n\ncat <<EOF\n#ifndef SIZE_CLASSES_DEFINED\n#  error \"No size class definitions match configuration\"\n#endif\n#undef SIZE_CLASSES_DEFINED\n/*\n * The small_size2bin lookup table uses uint8_t to encode each bin index, so we\n * cannot support more than 256 small size classes.  Further constrain NBINS to\n * 255 to support prof_promote, since all small size classes, plus a \"not\n * small\" size class must be stored in 8 bits of arena_chunk_map_t's bits\n * field.\n */\n#if (NBINS > 255)\n#  error \"Too many small size classes\"\n#endif\n\n#endif /* JEMALLOC_H_TYPES */\n/******************************************************************************/\n#ifdef JEMALLOC_H_STRUCTS\n\n\n#endif /* JEMALLOC_H_STRUCTS */\n/******************************************************************************/\n#ifdef JEMALLOC_H_EXTERNS\n\n\n#endif /* JEMALLOC_H_EXTERNS */\n/******************************************************************************/\n#ifdef JEMALLOC_H_INLINES\n\n\n#endif /* JEMALLOC_H_INLINES */\n/******************************************************************************/\nEOF\n"
  },
  {
    "path": "extern/deprecated/redis-2.8.21/deps/jemalloc/include/jemalloc/internal/stats.h",
    "content": "/******************************************************************************/\n#ifdef JEMALLOC_H_TYPES\n\ntypedef struct tcache_bin_stats_s tcache_bin_stats_t;\ntypedef struct malloc_bin_stats_s malloc_bin_stats_t;\ntypedef struct malloc_large_stats_s malloc_large_stats_t;\ntypedef struct arena_stats_s arena_stats_t;\ntypedef struct chunk_stats_s chunk_stats_t;\n\n#endif /* JEMALLOC_H_TYPES */\n/******************************************************************************/\n#ifdef JEMALLOC_H_STRUCTS\n\nstruct tcache_bin_stats_s {\n\t/*\n\t * Number of allocation requests that corresponded to the size of this\n\t * bin.\n\t */\n\tuint64_t\tnrequests;\n};\n\nstruct malloc_bin_stats_s {\n\t/*\n\t * Current number of bytes allocated, including objects currently\n\t * cached by tcache.\n\t */\n\tsize_t\t\tallocated;\n\n\t/*\n\t * Total number of allocation/deallocation requests served directly by\n\t * the bin.  Note that tcache may allocate an object, then recycle it\n\t * many times, resulting many increments to nrequests, but only one\n\t * each to nmalloc and ndalloc.\n\t */\n\tuint64_t\tnmalloc;\n\tuint64_t\tndalloc;\n\n\t/*\n\t * Number of allocation requests that correspond to the size of this\n\t * bin.  This includes requests served by tcache, though tcache only\n\t * periodically merges into this counter.\n\t */\n\tuint64_t\tnrequests;\n\n\t/* Number of tcache fills from this bin. */\n\tuint64_t\tnfills;\n\n\t/* Number of tcache flushes to this bin. */\n\tuint64_t\tnflushes;\n\n\t/* Total number of runs created for this bin's size class. */\n\tuint64_t\tnruns;\n\n\t/*\n\t * Total number of runs reused by extracting them from the runs tree for\n\t * this bin's size class.\n\t */\n\tuint64_t\treruns;\n\n\t/* Current number of runs in this bin. */\n\tsize_t\t\tcurruns;\n};\n\nstruct malloc_large_stats_s {\n\t/*\n\t * Total number of allocation/deallocation requests served directly by\n\t * the arena.  Note that tcache may allocate an object, then recycle it\n\t * many times, resulting many increments to nrequests, but only one\n\t * each to nmalloc and ndalloc.\n\t */\n\tuint64_t\tnmalloc;\n\tuint64_t\tndalloc;\n\n\t/*\n\t * Number of allocation requests that correspond to this size class.\n\t * This includes requests served by tcache, though tcache only\n\t * periodically merges into this counter.\n\t */\n\tuint64_t\tnrequests;\n\n\t/* Current number of runs of this size class. */\n\tsize_t\t\tcurruns;\n};\n\nstruct arena_stats_s {\n\t/* Number of bytes currently mapped. */\n\tsize_t\t\tmapped;\n\n\t/*\n\t * Total number of purge sweeps, total number of madvise calls made,\n\t * and total pages purged in order to keep dirty unused memory under\n\t * control.\n\t */\n\tuint64_t\tnpurge;\n\tuint64_t\tnmadvise;\n\tuint64_t\tpurged;\n\n\t/* Per-size-category statistics. */\n\tsize_t\t\tallocated_large;\n\tuint64_t\tnmalloc_large;\n\tuint64_t\tndalloc_large;\n\tuint64_t\tnrequests_large;\n\n\t/*\n\t * One element for each possible size class, including sizes that\n\t * overlap with bin size classes.  This is necessary because ipalloc()\n\t * sometimes has to use such large objects in order to assure proper\n\t * alignment.\n\t */\n\tmalloc_large_stats_t\t*lstats;\n};\n\nstruct chunk_stats_s {\n\t/* Number of chunks that were allocated. */\n\tuint64_t\tnchunks;\n\n\t/* High-water mark for number of chunks allocated. */\n\tsize_t\t\thighchunks;\n\n\t/*\n\t * Current number of chunks allocated.  This value isn't maintained for\n\t * any other purpose, so keep track of it in order to be able to set\n\t * highchunks.\n\t */\n\tsize_t\t\tcurchunks;\n};\n\n#endif /* JEMALLOC_H_STRUCTS */\n/******************************************************************************/\n#ifdef JEMALLOC_H_EXTERNS\n\nextern bool\topt_stats_print;\n\nextern size_t\tstats_cactive;\n\nvoid\tstats_print(void (*write)(void *, const char *), void *cbopaque,\n    const char *opts);\n\n#endif /* JEMALLOC_H_EXTERNS */\n/******************************************************************************/\n#ifdef JEMALLOC_H_INLINES\n\n#ifndef JEMALLOC_ENABLE_INLINE\nsize_t\tstats_cactive_get(void);\nvoid\tstats_cactive_add(size_t size);\nvoid\tstats_cactive_sub(size_t size);\n#endif\n\n#if (defined(JEMALLOC_ENABLE_INLINE) || defined(JEMALLOC_STATS_C_))\nJEMALLOC_INLINE size_t\nstats_cactive_get(void)\n{\n\n\treturn (atomic_read_z(&stats_cactive));\n}\n\nJEMALLOC_INLINE void\nstats_cactive_add(size_t size)\n{\n\n\tatomic_add_z(&stats_cactive, size);\n}\n\nJEMALLOC_INLINE void\nstats_cactive_sub(size_t size)\n{\n\n\tatomic_sub_z(&stats_cactive, size);\n}\n#endif\n\n#endif /* JEMALLOC_H_INLINES */\n/******************************************************************************/\n"
  },
  {
    "path": "extern/deprecated/redis-2.8.21/deps/jemalloc/include/jemalloc/internal/tcache.h",
    "content": "/******************************************************************************/\n#ifdef JEMALLOC_H_TYPES\n\ntypedef struct tcache_bin_info_s tcache_bin_info_t;\ntypedef struct tcache_bin_s tcache_bin_t;\ntypedef struct tcache_s tcache_t;\n\n/*\n * tcache pointers close to NULL are used to encode state information that is\n * used for two purposes: preventing thread caching on a per thread basis and\n * cleaning up during thread shutdown.\n */\n#define\tTCACHE_STATE_DISABLED\t\t((tcache_t *)(uintptr_t)1)\n#define\tTCACHE_STATE_REINCARNATED\t((tcache_t *)(uintptr_t)2)\n#define\tTCACHE_STATE_PURGATORY\t\t((tcache_t *)(uintptr_t)3)\n#define\tTCACHE_STATE_MAX\t\tTCACHE_STATE_PURGATORY\n\n/*\n * Absolute maximum number of cache slots for each small bin in the thread\n * cache.  This is an additional constraint beyond that imposed as: twice the\n * number of regions per run for this size class.\n *\n * This constant must be an even number.\n */\n#define\tTCACHE_NSLOTS_SMALL_MAX\t\t200\n\n/* Number of cache slots for large size classes. */\n#define\tTCACHE_NSLOTS_LARGE\t\t20\n\n/* (1U << opt_lg_tcache_max) is used to compute tcache_maxclass. */\n#define\tLG_TCACHE_MAXCLASS_DEFAULT\t15\n\n/*\n * TCACHE_GC_SWEEP is the approximate number of allocation events between\n * full GC sweeps.  Integer rounding may cause the actual number to be\n * slightly higher, since GC is performed incrementally.\n */\n#define\tTCACHE_GC_SWEEP\t\t\t8192\n\n/* Number of tcache allocation/deallocation events between incremental GCs. */\n#define\tTCACHE_GC_INCR\t\t\t\t\t\t\t\\\n    ((TCACHE_GC_SWEEP / NBINS) + ((TCACHE_GC_SWEEP / NBINS == 0) ? 0 : 1))\n\n#endif /* JEMALLOC_H_TYPES */\n/******************************************************************************/\n#ifdef JEMALLOC_H_STRUCTS\n\ntypedef enum {\n\ttcache_enabled_false   = 0, /* Enable cast to/from bool. */\n\ttcache_enabled_true    = 1,\n\ttcache_enabled_default = 2\n} tcache_enabled_t;\n\n/*\n * Read-only information associated with each element of tcache_t's tbins array\n * is stored separately, mainly to reduce memory usage.\n */\nstruct tcache_bin_info_s {\n\tunsigned\tncached_max;\t/* Upper limit on ncached. */\n};\n\nstruct tcache_bin_s {\n\ttcache_bin_stats_t tstats;\n\tint\t\tlow_water;\t/* Min # cached since last GC. */\n\tunsigned\tlg_fill_div;\t/* Fill (ncached_max >> lg_fill_div). */\n\tunsigned\tncached;\t/* # of cached objects. */\n\tvoid\t\t**avail;\t/* Stack of available objects. */\n};\n\nstruct tcache_s {\n\tql_elm(tcache_t) link;\t\t/* Used for aggregating stats. */\n\tuint64_t\tprof_accumbytes;/* Cleared after arena_prof_accum() */\n\tarena_t\t\t*arena;\t\t/* This thread's arena. */\n\tunsigned\tev_cnt;\t\t/* Event count since incremental GC. */\n\tunsigned\tnext_gc_bin;\t/* Next bin to GC. */\n\ttcache_bin_t\ttbins[1];\t/* Dynamically sized. */\n\t/*\n\t * The pointer stacks associated with tbins follow as a contiguous\n\t * array.  During tcache initialization, the avail pointer in each\n\t * element of tbins is initialized to point to the proper offset within\n\t * this array.\n\t */\n};\n\n#endif /* JEMALLOC_H_STRUCTS */\n/******************************************************************************/\n#ifdef JEMALLOC_H_EXTERNS\n\nextern bool\topt_tcache;\nextern ssize_t\topt_lg_tcache_max;\n\nextern tcache_bin_info_t\t*tcache_bin_info;\n\n/*\n * Number of tcache bins.  There are NBINS small-object bins, plus 0 or more\n * large-object bins.\n */\nextern size_t\t\t\tnhbins;\n\n/* Maximum cached size class. */\nextern size_t\t\t\ttcache_maxclass;\n\nsize_t\ttcache_salloc(const void *ptr);\nvoid\ttcache_event_hard(tcache_t *tcache);\nvoid\t*tcache_alloc_small_hard(tcache_t *tcache, tcache_bin_t *tbin,\n    size_t binind);\nvoid\ttcache_bin_flush_small(tcache_bin_t *tbin, size_t binind, unsigned rem,\n    tcache_t *tcache);\nvoid\ttcache_bin_flush_large(tcache_bin_t *tbin, size_t binind, unsigned rem,\n    tcache_t *tcache);\nvoid\ttcache_arena_associate(tcache_t *tcache, arena_t *arena);\nvoid\ttcache_arena_dissociate(tcache_t *tcache);\ntcache_t *tcache_create(arena_t *arena);\nvoid\ttcache_destroy(tcache_t *tcache);\nvoid\ttcache_thread_cleanup(void *arg);\nvoid\ttcache_stats_merge(tcache_t *tcache, arena_t *arena);\nbool\ttcache_boot0(void);\nbool\ttcache_boot1(void);\n\n#endif /* JEMALLOC_H_EXTERNS */\n/******************************************************************************/\n#ifdef JEMALLOC_H_INLINES\n\n#ifndef JEMALLOC_ENABLE_INLINE\nmalloc_tsd_protos(JEMALLOC_ATTR(unused), tcache, tcache_t *)\nmalloc_tsd_protos(JEMALLOC_ATTR(unused), tcache_enabled, tcache_enabled_t)\n\nvoid\ttcache_event(tcache_t *tcache);\nvoid\ttcache_flush(void);\nbool\ttcache_enabled_get(void);\ntcache_t *tcache_get(bool create);\nvoid\ttcache_enabled_set(bool enabled);\nvoid\t*tcache_alloc_easy(tcache_bin_t *tbin);\nvoid\t*tcache_alloc_small(tcache_t *tcache, size_t size, bool zero);\nvoid\t*tcache_alloc_large(tcache_t *tcache, size_t size, bool zero);\nvoid\ttcache_dalloc_small(tcache_t *tcache, void *ptr, size_t binind);\nvoid\ttcache_dalloc_large(tcache_t *tcache, void *ptr, size_t size);\n#endif\n\n#if (defined(JEMALLOC_ENABLE_INLINE) || defined(JEMALLOC_TCACHE_C_))\n/* Map of thread-specific caches. */\nmalloc_tsd_externs(tcache, tcache_t *)\nmalloc_tsd_funcs(JEMALLOC_ALWAYS_INLINE, tcache, tcache_t *, NULL,\n    tcache_thread_cleanup)\n/* Per thread flag that allows thread caches to be disabled. */\nmalloc_tsd_externs(tcache_enabled, tcache_enabled_t)\nmalloc_tsd_funcs(JEMALLOC_ALWAYS_INLINE, tcache_enabled, tcache_enabled_t,\n    tcache_enabled_default, malloc_tsd_no_cleanup)\n\nJEMALLOC_INLINE void\ntcache_flush(void)\n{\n\ttcache_t *tcache;\n\n\tcassert(config_tcache);\n\n\ttcache = *tcache_tsd_get();\n\tif ((uintptr_t)tcache <= (uintptr_t)TCACHE_STATE_MAX)\n\t\treturn;\n\ttcache_destroy(tcache);\n\ttcache = NULL;\n\ttcache_tsd_set(&tcache);\n}\n\nJEMALLOC_INLINE bool\ntcache_enabled_get(void)\n{\n\ttcache_enabled_t tcache_enabled;\n\n\tcassert(config_tcache);\n\n\ttcache_enabled = *tcache_enabled_tsd_get();\n\tif (tcache_enabled == tcache_enabled_default) {\n\t\ttcache_enabled = (tcache_enabled_t)opt_tcache;\n\t\ttcache_enabled_tsd_set(&tcache_enabled);\n\t}\n\n\treturn ((bool)tcache_enabled);\n}\n\nJEMALLOC_INLINE void\ntcache_enabled_set(bool enabled)\n{\n\ttcache_enabled_t tcache_enabled;\n\ttcache_t *tcache;\n\n\tcassert(config_tcache);\n\n\ttcache_enabled = (tcache_enabled_t)enabled;\n\ttcache_enabled_tsd_set(&tcache_enabled);\n\ttcache = *tcache_tsd_get();\n\tif (enabled) {\n\t\tif (tcache == TCACHE_STATE_DISABLED) {\n\t\t\ttcache = NULL;\n\t\t\ttcache_tsd_set(&tcache);\n\t\t}\n\t} else /* disabled */ {\n\t\tif (tcache > TCACHE_STATE_MAX) {\n\t\t\ttcache_destroy(tcache);\n\t\t\ttcache = NULL;\n\t\t}\n\t\tif (tcache == NULL) {\n\t\t\ttcache = TCACHE_STATE_DISABLED;\n\t\t\ttcache_tsd_set(&tcache);\n\t\t}\n\t}\n}\n\nJEMALLOC_ALWAYS_INLINE tcache_t *\ntcache_get(bool create)\n{\n\ttcache_t *tcache;\n\n\tif (config_tcache == false)\n\t\treturn (NULL);\n\tif (config_lazy_lock && isthreaded == false)\n\t\treturn (NULL);\n\n\ttcache = *tcache_tsd_get();\n\tif ((uintptr_t)tcache <= (uintptr_t)TCACHE_STATE_MAX) {\n\t\tif (tcache == TCACHE_STATE_DISABLED)\n\t\t\treturn (NULL);\n\t\tif (tcache == NULL) {\n\t\t\tif (create == false) {\n\t\t\t\t/*\n\t\t\t\t * Creating a tcache here would cause\n\t\t\t\t * allocation as a side effect of free().\n\t\t\t\t * Ordinarily that would be okay since\n\t\t\t\t * tcache_create() failure is a soft failure\n\t\t\t\t * that doesn't propagate.  However, if TLS\n\t\t\t\t * data are freed via free() as in glibc,\n\t\t\t\t * subtle corruption could result from setting\n\t\t\t\t * a TLS variable after its backing memory is\n\t\t\t\t * freed.\n\t\t\t\t */\n\t\t\t\treturn (NULL);\n\t\t\t}\n\t\t\tif (tcache_enabled_get() == false) {\n\t\t\t\ttcache_enabled_set(false); /* Memoize. */\n\t\t\t\treturn (NULL);\n\t\t\t}\n\t\t\treturn (tcache_create(choose_arena(NULL)));\n\t\t}\n\t\tif (tcache == TCACHE_STATE_PURGATORY) {\n\t\t\t/*\n\t\t\t * Make a note that an allocator function was called\n\t\t\t * after tcache_thread_cleanup() was called.\n\t\t\t */\n\t\t\ttcache = TCACHE_STATE_REINCARNATED;\n\t\t\ttcache_tsd_set(&tcache);\n\t\t\treturn (NULL);\n\t\t}\n\t\tif (tcache == TCACHE_STATE_REINCARNATED)\n\t\t\treturn (NULL);\n\t\tnot_reached();\n\t}\n\n\treturn (tcache);\n}\n\nJEMALLOC_ALWAYS_INLINE void\ntcache_event(tcache_t *tcache)\n{\n\n\tif (TCACHE_GC_INCR == 0)\n\t\treturn;\n\n\ttcache->ev_cnt++;\n\tassert(tcache->ev_cnt <= TCACHE_GC_INCR);\n\tif (tcache->ev_cnt == TCACHE_GC_INCR)\n\t\ttcache_event_hard(tcache);\n}\n\nJEMALLOC_ALWAYS_INLINE void *\ntcache_alloc_easy(tcache_bin_t *tbin)\n{\n\tvoid *ret;\n\n\tif (tbin->ncached == 0) {\n\t\ttbin->low_water = -1;\n\t\treturn (NULL);\n\t}\n\ttbin->ncached--;\n\tif ((int)tbin->ncached < tbin->low_water)\n\t\ttbin->low_water = tbin->ncached;\n\tret = tbin->avail[tbin->ncached];\n\treturn (ret);\n}\n\nJEMALLOC_ALWAYS_INLINE void *\ntcache_alloc_small(tcache_t *tcache, size_t size, bool zero)\n{\n\tvoid *ret;\n\tsize_t binind;\n\ttcache_bin_t *tbin;\n\n\tbinind = SMALL_SIZE2BIN(size);\n\tassert(binind < NBINS);\n\ttbin = &tcache->tbins[binind];\n\tsize = arena_bin_info[binind].reg_size;\n\tret = tcache_alloc_easy(tbin);\n\tif (ret == NULL) {\n\t\tret = tcache_alloc_small_hard(tcache, tbin, binind);\n\t\tif (ret == NULL)\n\t\t\treturn (NULL);\n\t}\n\tassert(tcache_salloc(ret) == arena_bin_info[binind].reg_size);\n\n\tif (zero == false) {\n\t\tif (config_fill) {\n\t\t\tif (opt_junk) {\n\t\t\t\tarena_alloc_junk_small(ret,\n\t\t\t\t    &arena_bin_info[binind], false);\n\t\t\t} else if (opt_zero)\n\t\t\t\tmemset(ret, 0, size);\n\t\t}\n\t\tVALGRIND_MAKE_MEM_UNDEFINED(ret, size);\n\t} else {\n\t\tif (config_fill && opt_junk) {\n\t\t\tarena_alloc_junk_small(ret, &arena_bin_info[binind],\n\t\t\t    true);\n\t\t}\n\t\tVALGRIND_MAKE_MEM_UNDEFINED(ret, size);\n\t\tmemset(ret, 0, size);\n\t}\n\n\tif (config_stats)\n\t\ttbin->tstats.nrequests++;\n\tif (config_prof)\n\t\ttcache->prof_accumbytes += arena_bin_info[binind].reg_size;\n\ttcache_event(tcache);\n\treturn (ret);\n}\n\nJEMALLOC_ALWAYS_INLINE void *\ntcache_alloc_large(tcache_t *tcache, size_t size, bool zero)\n{\n\tvoid *ret;\n\tsize_t binind;\n\ttcache_bin_t *tbin;\n\n\tsize = PAGE_CEILING(size);\n\tassert(size <= tcache_maxclass);\n\tbinind = NBINS + (size >> LG_PAGE) - 1;\n\tassert(binind < nhbins);\n\ttbin = &tcache->tbins[binind];\n\tret = tcache_alloc_easy(tbin);\n\tif (ret == NULL) {\n\t\t/*\n\t\t * Only allocate one large object at a time, because it's quite\n\t\t * expensive to create one and not use it.\n\t\t */\n\t\tret = arena_malloc_large(tcache->arena, size, zero);\n\t\tif (ret == NULL)\n\t\t\treturn (NULL);\n\t} else {\n\t\tif (config_prof && prof_promote && size == PAGE) {\n\t\t\tarena_chunk_t *chunk =\n\t\t\t    (arena_chunk_t *)CHUNK_ADDR2BASE(ret);\n\t\t\tsize_t pageind = (((uintptr_t)ret - (uintptr_t)chunk) >>\n\t\t\t    LG_PAGE);\n\t\t\tarena_mapbits_large_binind_set(chunk, pageind,\n\t\t\t    BININD_INVALID);\n\t\t}\n\t\tif (zero == false) {\n\t\t\tif (config_fill) {\n\t\t\t\tif (opt_junk)\n\t\t\t\t\tmemset(ret, 0xa5, size);\n\t\t\t\telse if (opt_zero)\n\t\t\t\t\tmemset(ret, 0, size);\n\t\t\t}\n\t\t\tVALGRIND_MAKE_MEM_UNDEFINED(ret, size);\n\t\t} else {\n\t\t\tVALGRIND_MAKE_MEM_UNDEFINED(ret, size);\n\t\t\tmemset(ret, 0, size);\n\t\t}\n\n\t\tif (config_stats)\n\t\t\ttbin->tstats.nrequests++;\n\t\tif (config_prof)\n\t\t\ttcache->prof_accumbytes += size;\n\t}\n\n\ttcache_event(tcache);\n\treturn (ret);\n}\n\nJEMALLOC_ALWAYS_INLINE void\ntcache_dalloc_small(tcache_t *tcache, void *ptr, size_t binind)\n{\n\ttcache_bin_t *tbin;\n\ttcache_bin_info_t *tbin_info;\n\n\tassert(tcache_salloc(ptr) <= SMALL_MAXCLASS);\n\n\tif (config_fill && opt_junk)\n\t\tarena_dalloc_junk_small(ptr, &arena_bin_info[binind]);\n\n\ttbin = &tcache->tbins[binind];\n\ttbin_info = &tcache_bin_info[binind];\n\tif (tbin->ncached == tbin_info->ncached_max) {\n\t\ttcache_bin_flush_small(tbin, binind, (tbin_info->ncached_max >>\n\t\t    1), tcache);\n\t}\n\tassert(tbin->ncached < tbin_info->ncached_max);\n\ttbin->avail[tbin->ncached] = ptr;\n\ttbin->ncached++;\n\n\ttcache_event(tcache);\n}\n\nJEMALLOC_ALWAYS_INLINE void\ntcache_dalloc_large(tcache_t *tcache, void *ptr, size_t size)\n{\n\tsize_t binind;\n\ttcache_bin_t *tbin;\n\ttcache_bin_info_t *tbin_info;\n\n\tassert((size & PAGE_MASK) == 0);\n\tassert(tcache_salloc(ptr) > SMALL_MAXCLASS);\n\tassert(tcache_salloc(ptr) <= tcache_maxclass);\n\n\tbinind = NBINS + (size >> LG_PAGE) - 1;\n\n\tif (config_fill && opt_junk)\n\t\tmemset(ptr, 0x5a, size);\n\n\ttbin = &tcache->tbins[binind];\n\ttbin_info = &tcache_bin_info[binind];\n\tif (tbin->ncached == tbin_info->ncached_max) {\n\t\ttcache_bin_flush_large(tbin, binind, (tbin_info->ncached_max >>\n\t\t    1), tcache);\n\t}\n\tassert(tbin->ncached < tbin_info->ncached_max);\n\ttbin->avail[tbin->ncached] = ptr;\n\ttbin->ncached++;\n\n\ttcache_event(tcache);\n}\n#endif\n\n#endif /* JEMALLOC_H_INLINES */\n/******************************************************************************/\n"
  },
  {
    "path": "extern/deprecated/redis-2.8.21/deps/jemalloc/include/jemalloc/internal/tsd.h",
    "content": "/******************************************************************************/\n#ifdef JEMALLOC_H_TYPES\n\n/* Maximum number of malloc_tsd users with cleanup functions. */\n#define\tMALLOC_TSD_CLEANUPS_MAX\t8\n\ntypedef bool (*malloc_tsd_cleanup_t)(void);\n\n#if (!defined(JEMALLOC_MALLOC_THREAD_CLEANUP) && !defined(JEMALLOC_TLS) && \\\n    !defined(_WIN32))\ntypedef struct tsd_init_block_s tsd_init_block_t;\ntypedef struct tsd_init_head_s tsd_init_head_t;\n#endif\n\n/*\n * TLS/TSD-agnostic macro-based implementation of thread-specific data.  There\n * are four macros that support (at least) three use cases: file-private,\n * library-private, and library-private inlined.  Following is an example\n * library-private tsd variable:\n *\n * In example.h:\n *   typedef struct {\n *           int x;\n *           int y;\n *   } example_t;\n *   #define EX_INITIALIZER JEMALLOC_CONCAT({0, 0})\n *   malloc_tsd_protos(, example, example_t *)\n *   malloc_tsd_externs(example, example_t *)\n * In example.c:\n *   malloc_tsd_data(, example, example_t *, EX_INITIALIZER)\n *   malloc_tsd_funcs(, example, example_t *, EX_INITIALIZER,\n *       example_tsd_cleanup)\n *\n * The result is a set of generated functions, e.g.:\n *\n *   bool example_tsd_boot(void) {...}\n *   example_t **example_tsd_get() {...}\n *   void example_tsd_set(example_t **val) {...}\n *\n * Note that all of the functions deal in terms of (a_type *) rather than\n * (a_type)  so that it is possible to support non-pointer types (unlike\n * pthreads TSD).  example_tsd_cleanup() is passed an (a_type *) pointer that is\n * cast to (void *).  This means that the cleanup function needs to cast *and*\n * dereference the function argument, e.g.:\n *\n *   void\n *   example_tsd_cleanup(void *arg)\n *   {\n *           example_t *example = *(example_t **)arg;\n *\n *           [...]\n *           if ([want the cleanup function to be called again]) {\n *                   example_tsd_set(&example);\n *           }\n *   }\n *\n * If example_tsd_set() is called within example_tsd_cleanup(), it will be\n * called again.  This is similar to how pthreads TSD destruction works, except\n * that pthreads only calls the cleanup function again if the value was set to\n * non-NULL.\n */\n\n/* malloc_tsd_protos(). */\n#define\tmalloc_tsd_protos(a_attr, a_name, a_type)\t\t\t\\\na_attr bool\t\t\t\t\t\t\t\t\\\na_name##_tsd_boot(void);\t\t\t\t\t\t\\\na_attr a_type *\t\t\t\t\t\t\t\t\\\na_name##_tsd_get(void);\t\t\t\t\t\t\t\\\na_attr void\t\t\t\t\t\t\t\t\\\na_name##_tsd_set(a_type *val);\n\n/* malloc_tsd_externs(). */\n#ifdef JEMALLOC_MALLOC_THREAD_CLEANUP\n#define\tmalloc_tsd_externs(a_name, a_type)\t\t\t\t\\\nextern __thread a_type\ta_name##_tls;\t\t\t\t\t\\\nextern __thread bool\ta_name##_initialized;\t\t\t\t\\\nextern bool\t\ta_name##_booted;\n#elif (defined(JEMALLOC_TLS))\n#define\tmalloc_tsd_externs(a_name, a_type)\t\t\t\t\\\nextern __thread a_type\ta_name##_tls;\t\t\t\t\t\\\nextern pthread_key_t\ta_name##_tsd;\t\t\t\t\t\\\nextern bool\t\ta_name##_booted;\n#elif (defined(_WIN32))\n#define\tmalloc_tsd_externs(a_name, a_type)\t\t\t\t\\\nextern DWORD\t\ta_name##_tsd;\t\t\t\t\t\\\nextern bool\t\ta_name##_booted;\n#else\n#define\tmalloc_tsd_externs(a_name, a_type)\t\t\t\t\\\nextern pthread_key_t\ta_name##_tsd;\t\t\t\t\t\\\nextern tsd_init_head_t\ta_name##_tsd_init_head;\t\t\t\t\\\nextern bool\t\ta_name##_booted;\n#endif\n\n/* malloc_tsd_data(). */\n#ifdef JEMALLOC_MALLOC_THREAD_CLEANUP\n#define\tmalloc_tsd_data(a_attr, a_name, a_type, a_initializer)\t\t\\\na_attr __thread a_type JEMALLOC_TLS_MODEL\t\t\t\t\\\n    a_name##_tls = a_initializer;\t\t\t\t\t\\\na_attr __thread bool JEMALLOC_TLS_MODEL\t\t\t\t\t\\\n    a_name##_initialized = false;\t\t\t\t\t\\\na_attr bool\t\ta_name##_booted = false;\n#elif (defined(JEMALLOC_TLS))\n#define\tmalloc_tsd_data(a_attr, a_name, a_type, a_initializer)\t\t\\\na_attr __thread a_type JEMALLOC_TLS_MODEL\t\t\t\t\\\n    a_name##_tls = a_initializer;\t\t\t\t\t\\\na_attr pthread_key_t\ta_name##_tsd;\t\t\t\t\t\\\na_attr bool\t\ta_name##_booted = false;\n#elif (defined(_WIN32))\n#define\tmalloc_tsd_data(a_attr, a_name, a_type, a_initializer)\t\t\\\na_attr DWORD\t\ta_name##_tsd;\t\t\t\t\t\\\na_attr bool\t\ta_name##_booted = false;\n#else\n#define\tmalloc_tsd_data(a_attr, a_name, a_type, a_initializer)\t\t\\\na_attr pthread_key_t\ta_name##_tsd;\t\t\t\t\t\\\na_attr tsd_init_head_t\ta_name##_tsd_init_head = {\t\t\t\\\n\tql_head_initializer(blocks),\t\t\t\t\t\\\n\tMALLOC_MUTEX_INITIALIZER\t\t\t\t\t\\\n};\t\t\t\t\t\t\t\t\t\\\na_attr bool\t\ta_name##_booted = false;\n#endif\n\n/* malloc_tsd_funcs(). */\n#ifdef JEMALLOC_MALLOC_THREAD_CLEANUP\n#define\tmalloc_tsd_funcs(a_attr, a_name, a_type, a_initializer,\t\t\\\n    a_cleanup)\t\t\t\t\t\t\t\t\\\n/* Initialization/cleanup. */\t\t\t\t\t\t\\\na_attr bool\t\t\t\t\t\t\t\t\\\na_name##_tsd_cleanup_wrapper(void)\t\t\t\t\t\\\n{\t\t\t\t\t\t\t\t\t\\\n\t\t\t\t\t\t\t\t\t\\\n\tif (a_name##_initialized) {\t\t\t\t\t\\\n\t\ta_name##_initialized = false;\t\t\t\t\\\n\t\ta_cleanup(&a_name##_tls);\t\t\t\t\\\n\t}\t\t\t\t\t\t\t\t\\\n\treturn (a_name##_initialized);\t\t\t\t\t\\\n}\t\t\t\t\t\t\t\t\t\\\na_attr bool\t\t\t\t\t\t\t\t\\\na_name##_tsd_boot(void)\t\t\t\t\t\t\t\\\n{\t\t\t\t\t\t\t\t\t\\\n\t\t\t\t\t\t\t\t\t\\\n\tif (a_cleanup != malloc_tsd_no_cleanup) {\t\t\t\\\n\t\tmalloc_tsd_cleanup_register(\t\t\t\t\\\n\t\t    &a_name##_tsd_cleanup_wrapper);\t\t\t\\\n\t}\t\t\t\t\t\t\t\t\\\n\ta_name##_booted = true;\t\t\t\t\t\t\\\n\treturn (false);\t\t\t\t\t\t\t\\\n}\t\t\t\t\t\t\t\t\t\\\n/* Get/set. */\t\t\t\t\t\t\t\t\\\na_attr a_type *\t\t\t\t\t\t\t\t\\\na_name##_tsd_get(void)\t\t\t\t\t\t\t\\\n{\t\t\t\t\t\t\t\t\t\\\n\t\t\t\t\t\t\t\t\t\\\n\tassert(a_name##_booted);\t\t\t\t\t\\\n\treturn (&a_name##_tls);\t\t\t\t\t\t\\\n}\t\t\t\t\t\t\t\t\t\\\na_attr void\t\t\t\t\t\t\t\t\\\na_name##_tsd_set(a_type *val)\t\t\t\t\t\t\\\n{\t\t\t\t\t\t\t\t\t\\\n\t\t\t\t\t\t\t\t\t\\\n\tassert(a_name##_booted);\t\t\t\t\t\\\n\ta_name##_tls = (*val);\t\t\t\t\t\t\\\n\tif (a_cleanup != malloc_tsd_no_cleanup)\t\t\t\t\\\n\t\ta_name##_initialized = true;\t\t\t\t\\\n}\n#elif (defined(JEMALLOC_TLS))\n#define\tmalloc_tsd_funcs(a_attr, a_name, a_type, a_initializer,\t\t\\\n    a_cleanup)\t\t\t\t\t\t\t\t\\\n/* Initialization/cleanup. */\t\t\t\t\t\t\\\na_attr bool\t\t\t\t\t\t\t\t\\\na_name##_tsd_boot(void)\t\t\t\t\t\t\t\\\n{\t\t\t\t\t\t\t\t\t\\\n\t\t\t\t\t\t\t\t\t\\\n\tif (a_cleanup != malloc_tsd_no_cleanup) {\t\t\t\\\n\t\tif (pthread_key_create(&a_name##_tsd, a_cleanup) != 0)\t\\\n\t\t\treturn (true);\t\t\t\t\t\\\n\t}\t\t\t\t\t\t\t\t\\\n\ta_name##_booted = true;\t\t\t\t\t\t\\\n\treturn (false);\t\t\t\t\t\t\t\\\n}\t\t\t\t\t\t\t\t\t\\\n/* Get/set. */\t\t\t\t\t\t\t\t\\\na_attr a_type *\t\t\t\t\t\t\t\t\\\na_name##_tsd_get(void)\t\t\t\t\t\t\t\\\n{\t\t\t\t\t\t\t\t\t\\\n\t\t\t\t\t\t\t\t\t\\\n\tassert(a_name##_booted);\t\t\t\t\t\\\n\treturn (&a_name##_tls);\t\t\t\t\t\t\\\n}\t\t\t\t\t\t\t\t\t\\\na_attr void\t\t\t\t\t\t\t\t\\\na_name##_tsd_set(a_type *val)\t\t\t\t\t\t\\\n{\t\t\t\t\t\t\t\t\t\\\n\t\t\t\t\t\t\t\t\t\\\n\tassert(a_name##_booted);\t\t\t\t\t\\\n\ta_name##_tls = (*val);\t\t\t\t\t\t\\\n\tif (a_cleanup != malloc_tsd_no_cleanup) {\t\t\t\\\n\t\tif (pthread_setspecific(a_name##_tsd,\t\t\t\\\n\t\t    (void *)(&a_name##_tls))) {\t\t\t\t\\\n\t\t\tmalloc_write(\"<jemalloc>: Error\"\t\t\\\n\t\t\t    \" setting TSD for \"#a_name\"\\n\");\t\t\\\n\t\t\tif (opt_abort)\t\t\t\t\t\\\n\t\t\t\tabort();\t\t\t\t\\\n\t\t}\t\t\t\t\t\t\t\\\n\t}\t\t\t\t\t\t\t\t\\\n}\n#elif (defined(_WIN32))\n#define\tmalloc_tsd_funcs(a_attr, a_name, a_type, a_initializer,\t\t\\\n    a_cleanup)\t\t\t\t\t\t\t\t\\\n/* Data structure. */\t\t\t\t\t\t\t\\\ntypedef struct {\t\t\t\t\t\t\t\\\n\tbool\tinitialized;\t\t\t\t\t\t\\\n\ta_type\tval;\t\t\t\t\t\t\t\\\n} a_name##_tsd_wrapper_t;\t\t\t\t\t\t\\\n/* Initialization/cleanup. */\t\t\t\t\t\t\\\na_attr bool\t\t\t\t\t\t\t\t\\\na_name##_tsd_cleanup_wrapper(void)\t\t\t\t\t\\\n{\t\t\t\t\t\t\t\t\t\\\n\ta_name##_tsd_wrapper_t *wrapper;\t\t\t\t\\\n\t\t\t\t\t\t\t\t\t\\\n\twrapper = (a_name##_tsd_wrapper_t *) TlsGetValue(a_name##_tsd);\t\\\n\tif (wrapper == NULL)\t\t\t\t\t\t\\\n\t\treturn (false);\t\t\t\t\t\t\\\n\tif (a_cleanup != malloc_tsd_no_cleanup &&\t\t\t\\\n\t    wrapper->initialized) {\t\t\t\t\t\\\n\t\ta_type val = wrapper->val;\t\t\t\t\\\n\t\ta_type tsd_static_data = a_initializer;\t\t\t\\\n\t\twrapper->initialized = false;\t\t\t\t\\\n\t\twrapper->val = tsd_static_data;\t\t\t\t\\\n\t\ta_cleanup(&val);\t\t\t\t\t\\\n\t\tif (wrapper->initialized) {\t\t\t\t\\\n\t\t\t/* Trigger another cleanup round. */\t\t\\\n\t\t\treturn (true);\t\t\t\t\t\\\n\t\t}\t\t\t\t\t\t\t\\\n\t}\t\t\t\t\t\t\t\t\\\n\tmalloc_tsd_dalloc(wrapper);\t\t\t\t\t\\\n\treturn (false);\t\t\t\t\t\t\t\\\n}\t\t\t\t\t\t\t\t\t\\\na_attr bool\t\t\t\t\t\t\t\t\\\na_name##_tsd_boot(void)\t\t\t\t\t\t\t\\\n{\t\t\t\t\t\t\t\t\t\\\n\t\t\t\t\t\t\t\t\t\\\n\ta_name##_tsd = TlsAlloc();\t\t\t\t\t\\\n\tif (a_name##_tsd == TLS_OUT_OF_INDEXES)\t\t\t\t\\\n\t\treturn (true);\t\t\t\t\t\t\\\n\tif (a_cleanup != malloc_tsd_no_cleanup) {\t\t\t\\\n\t\tmalloc_tsd_cleanup_register(\t\t\t\t\\\n\t\t    &a_name##_tsd_cleanup_wrapper);\t\t\t\\\n\t}\t\t\t\t\t\t\t\t\\\n\ta_name##_booted = true;\t\t\t\t\t\t\\\n\treturn (false);\t\t\t\t\t\t\t\\\n}\t\t\t\t\t\t\t\t\t\\\n/* Get/set. */\t\t\t\t\t\t\t\t\\\na_attr a_name##_tsd_wrapper_t *\t\t\t\t\t\t\\\na_name##_tsd_get_wrapper(void)\t\t\t\t\t\t\\\n{\t\t\t\t\t\t\t\t\t\\\n\ta_name##_tsd_wrapper_t *wrapper = (a_name##_tsd_wrapper_t *)\t\\\n\t    TlsGetValue(a_name##_tsd);\t\t\t\t\t\\\n\t\t\t\t\t\t\t\t\t\\\n\tif (wrapper == NULL) {\t\t\t\t\t\t\\\n\t\twrapper = (a_name##_tsd_wrapper_t *)\t\t\t\\\n\t\t    malloc_tsd_malloc(sizeof(a_name##_tsd_wrapper_t));\t\\\n\t\tif (wrapper == NULL) {\t\t\t\t\t\\\n\t\t\tmalloc_write(\"<jemalloc>: Error allocating\"\t\\\n\t\t\t    \" TSD for \"#a_name\"\\n\");\t\t\t\\\n\t\t\tabort();\t\t\t\t\t\\\n\t\t} else {\t\t\t\t\t\t\\\n\t\t\tstatic a_type tsd_static_data = a_initializer;\t\\\n\t\t\twrapper->initialized = false;\t\t\t\\\n\t\t\twrapper->val = tsd_static_data;\t\t\t\\\n\t\t}\t\t\t\t\t\t\t\\\n\t\tif (!TlsSetValue(a_name##_tsd, (void *)wrapper)) {\t\\\n\t\t\tmalloc_write(\"<jemalloc>: Error setting\"\t\\\n\t\t\t    \" TSD for \"#a_name\"\\n\");\t\t\t\\\n\t\t\tabort();\t\t\t\t\t\\\n\t\t}\t\t\t\t\t\t\t\\\n\t}\t\t\t\t\t\t\t\t\\\n\treturn (wrapper);\t\t\t\t\t\t\\\n}\t\t\t\t\t\t\t\t\t\\\na_attr a_type *\t\t\t\t\t\t\t\t\\\na_name##_tsd_get(void)\t\t\t\t\t\t\t\\\n{\t\t\t\t\t\t\t\t\t\\\n\ta_name##_tsd_wrapper_t *wrapper;\t\t\t\t\\\n\t\t\t\t\t\t\t\t\t\\\n\tassert(a_name##_booted);\t\t\t\t\t\\\n\twrapper = a_name##_tsd_get_wrapper();\t\t\t\t\\\n\treturn (&wrapper->val);\t\t\t\t\t\t\\\n}\t\t\t\t\t\t\t\t\t\\\na_attr void\t\t\t\t\t\t\t\t\\\na_name##_tsd_set(a_type *val)\t\t\t\t\t\t\\\n{\t\t\t\t\t\t\t\t\t\\\n\ta_name##_tsd_wrapper_t *wrapper;\t\t\t\t\\\n\t\t\t\t\t\t\t\t\t\\\n\tassert(a_name##_booted);\t\t\t\t\t\\\n\twrapper = a_name##_tsd_get_wrapper();\t\t\t\t\\\n\twrapper->val = *(val);\t\t\t\t\t\t\\\n\tif (a_cleanup != malloc_tsd_no_cleanup)\t\t\t\t\\\n\t\twrapper->initialized = true;\t\t\t\t\\\n}\n#else\n#define\tmalloc_tsd_funcs(a_attr, a_name, a_type, a_initializer,\t\t\\\n    a_cleanup)\t\t\t\t\t\t\t\t\\\n/* Data structure. */\t\t\t\t\t\t\t\\\ntypedef struct {\t\t\t\t\t\t\t\\\n\tbool\tinitialized;\t\t\t\t\t\t\\\n\ta_type\tval;\t\t\t\t\t\t\t\\\n} a_name##_tsd_wrapper_t;\t\t\t\t\t\t\\\n/* Initialization/cleanup. */\t\t\t\t\t\t\\\na_attr void\t\t\t\t\t\t\t\t\\\na_name##_tsd_cleanup_wrapper(void *arg)\t\t\t\t\t\\\n{\t\t\t\t\t\t\t\t\t\\\n\ta_name##_tsd_wrapper_t *wrapper = (a_name##_tsd_wrapper_t *)arg;\\\n\t\t\t\t\t\t\t\t\t\\\n\tif (a_cleanup != malloc_tsd_no_cleanup &&\t\t\t\\\n\t    wrapper->initialized) {\t\t\t\t\t\\\n\t\twrapper->initialized = false;\t\t\t\t\\\n\t\ta_cleanup(&wrapper->val);\t\t\t\t\\\n\t\tif (wrapper->initialized) {\t\t\t\t\\\n\t\t\t/* Trigger another cleanup round. */\t\t\\\n\t\t\tif (pthread_setspecific(a_name##_tsd,\t\t\\\n\t\t\t    (void *)wrapper)) {\t\t\t\t\\\n\t\t\t\tmalloc_write(\"<jemalloc>: Error\"\t\\\n\t\t\t\t    \" setting TSD for \"#a_name\"\\n\");\t\\\n\t\t\t\tif (opt_abort)\t\t\t\t\\\n\t\t\t\t\tabort();\t\t\t\\\n\t\t\t}\t\t\t\t\t\t\\\n\t\t\treturn;\t\t\t\t\t\t\\\n\t\t}\t\t\t\t\t\t\t\\\n\t}\t\t\t\t\t\t\t\t\\\n\tmalloc_tsd_dalloc(wrapper);\t\t\t\t\t\\\n}\t\t\t\t\t\t\t\t\t\\\na_attr bool\t\t\t\t\t\t\t\t\\\na_name##_tsd_boot(void)\t\t\t\t\t\t\t\\\n{\t\t\t\t\t\t\t\t\t\\\n\t\t\t\t\t\t\t\t\t\\\n\tif (pthread_key_create(&a_name##_tsd,\t\t\t\t\\\n\t    a_name##_tsd_cleanup_wrapper) != 0)\t\t\t\t\\\n\t\treturn (true);\t\t\t\t\t\t\\\n\ta_name##_booted = true;\t\t\t\t\t\t\\\n\treturn (false);\t\t\t\t\t\t\t\\\n}\t\t\t\t\t\t\t\t\t\\\n/* Get/set. */\t\t\t\t\t\t\t\t\\\na_attr a_name##_tsd_wrapper_t *\t\t\t\t\t\t\\\na_name##_tsd_get_wrapper(void)\t\t\t\t\t\t\\\n{\t\t\t\t\t\t\t\t\t\\\n\ta_name##_tsd_wrapper_t *wrapper = (a_name##_tsd_wrapper_t *)\t\\\n\t    pthread_getspecific(a_name##_tsd);\t\t\t\t\\\n\t\t\t\t\t\t\t\t\t\\\n\tif (wrapper == NULL) {\t\t\t\t\t\t\\\n\t\ttsd_init_block_t block;\t\t\t\t\t\\\n\t\twrapper = tsd_init_check_recursion(\t\t\t\\\n\t\t    &a_name##_tsd_init_head, &block);\t\t\t\\\n\t\tif (wrapper)\t\t\t\t\t\t\\\n\t\t    return (wrapper);\t\t\t\t\t\\\n\t\twrapper = (a_name##_tsd_wrapper_t *)\t\t\t\\\n\t\t    malloc_tsd_malloc(sizeof(a_name##_tsd_wrapper_t));\t\\\n\t\tblock.data = wrapper;\t\t\t\t\t\\\n\t\tif (wrapper == NULL) {\t\t\t\t\t\\\n\t\t\tmalloc_write(\"<jemalloc>: Error allocating\"\t\\\n\t\t\t    \" TSD for \"#a_name\"\\n\");\t\t\t\\\n\t\t\tabort();\t\t\t\t\t\\\n\t\t} else {\t\t\t\t\t\t\\\n\t\t\tstatic a_type tsd_static_data = a_initializer;\t\\\n\t\t\twrapper->initialized = false;\t\t\t\\\n\t\t\twrapper->val = tsd_static_data;\t\t\t\\\n\t\t}\t\t\t\t\t\t\t\\\n\t\tif (pthread_setspecific(a_name##_tsd,\t\t\t\\\n\t\t    (void *)wrapper)) {\t\t\t\t\t\\\n\t\t\tmalloc_write(\"<jemalloc>: Error setting\"\t\\\n\t\t\t    \" TSD for \"#a_name\"\\n\");\t\t\t\\\n\t\t\tabort();\t\t\t\t\t\\\n\t\t}\t\t\t\t\t\t\t\\\n\t\ttsd_init_finish(&a_name##_tsd_init_head, &block);\t\\\n\t}\t\t\t\t\t\t\t\t\\\n\treturn (wrapper);\t\t\t\t\t\t\\\n}\t\t\t\t\t\t\t\t\t\\\na_attr a_type *\t\t\t\t\t\t\t\t\\\na_name##_tsd_get(void)\t\t\t\t\t\t\t\\\n{\t\t\t\t\t\t\t\t\t\\\n\ta_name##_tsd_wrapper_t *wrapper;\t\t\t\t\\\n\t\t\t\t\t\t\t\t\t\\\n\tassert(a_name##_booted);\t\t\t\t\t\\\n\twrapper = a_name##_tsd_get_wrapper();\t\t\t\t\\\n\treturn (&wrapper->val);\t\t\t\t\t\t\\\n}\t\t\t\t\t\t\t\t\t\\\na_attr void\t\t\t\t\t\t\t\t\\\na_name##_tsd_set(a_type *val)\t\t\t\t\t\t\\\n{\t\t\t\t\t\t\t\t\t\\\n\ta_name##_tsd_wrapper_t *wrapper;\t\t\t\t\\\n\t\t\t\t\t\t\t\t\t\\\n\tassert(a_name##_booted);\t\t\t\t\t\\\n\twrapper = a_name##_tsd_get_wrapper();\t\t\t\t\\\n\twrapper->val = *(val);\t\t\t\t\t\t\\\n\tif (a_cleanup != malloc_tsd_no_cleanup)\t\t\t\t\\\n\t\twrapper->initialized = true;\t\t\t\t\\\n}\n#endif\n\n#endif /* JEMALLOC_H_TYPES */\n/******************************************************************************/\n#ifdef JEMALLOC_H_STRUCTS\n\n#if (!defined(JEMALLOC_MALLOC_THREAD_CLEANUP) && !defined(JEMALLOC_TLS) && \\\n    !defined(_WIN32))\nstruct tsd_init_block_s {\n\tql_elm(tsd_init_block_t)\tlink;\n\tpthread_t\t\t\tthread;\n\tvoid\t\t\t\t*data;\n};\nstruct tsd_init_head_s {\n\tql_head(tsd_init_block_t)\tblocks;\n\tmalloc_mutex_t\t\t\tlock;\n};\n#endif\n\n#endif /* JEMALLOC_H_STRUCTS */\n/******************************************************************************/\n#ifdef JEMALLOC_H_EXTERNS\n\nvoid\t*malloc_tsd_malloc(size_t size);\nvoid\tmalloc_tsd_dalloc(void *wrapper);\nvoid\tmalloc_tsd_no_cleanup(void *);\nvoid\tmalloc_tsd_cleanup_register(bool (*f)(void));\nvoid\tmalloc_tsd_boot(void);\n#if (!defined(JEMALLOC_MALLOC_THREAD_CLEANUP) && !defined(JEMALLOC_TLS) && \\\n    !defined(_WIN32))\nvoid\t*tsd_init_check_recursion(tsd_init_head_t *head,\n    tsd_init_block_t *block);\nvoid\ttsd_init_finish(tsd_init_head_t *head, tsd_init_block_t *block);\n#endif\n\n#endif /* JEMALLOC_H_EXTERNS */\n/******************************************************************************/\n#ifdef JEMALLOC_H_INLINES\n\n#endif /* JEMALLOC_H_INLINES */\n/******************************************************************************/\n"
  },
  {
    "path": "extern/deprecated/redis-2.8.21/deps/jemalloc/include/jemalloc/internal/util.h",
    "content": "/******************************************************************************/\n#ifdef JEMALLOC_H_TYPES\n\n/* Size of stack-allocated buffer passed to buferror(). */\n#define\tBUFERROR_BUF\t\t64\n\n/*\n * Size of stack-allocated buffer used by malloc_{,v,vc}printf().  This must be\n * large enough for all possible uses within jemalloc.\n */\n#define\tMALLOC_PRINTF_BUFSIZE\t4096\n\n/*\n * Wrap a cpp argument that contains commas such that it isn't broken up into\n * multiple arguments.\n */\n#define\tJEMALLOC_ARG_CONCAT(...) __VA_ARGS__\n\n/*\n * Silence compiler warnings due to uninitialized values.  This is used\n * wherever the compiler fails to recognize that the variable is never used\n * uninitialized.\n */\n#ifdef JEMALLOC_CC_SILENCE\n#  define JEMALLOC_CC_SILENCE_INIT(v) = v\n#else\n#  define JEMALLOC_CC_SILENCE_INIT(v)\n#endif\n\n/*\n * Define a custom assert() in order to reduce the chances of deadlock during\n * assertion failure.\n */\n#ifndef assert\n#define\tassert(e) do {\t\t\t\t\t\t\t\\\n\tif (config_debug && !(e)) {\t\t\t\t\t\\\n\t\tmalloc_printf(\t\t\t\t\t\t\\\n\t\t    \"<jemalloc>: %s:%d: Failed assertion: \\\"%s\\\"\\n\",\t\\\n\t\t    __FILE__, __LINE__, #e);\t\t\t\t\\\n\t\tabort();\t\t\t\t\t\t\\\n\t}\t\t\t\t\t\t\t\t\\\n} while (0)\n#endif\n\n#ifndef not_reached\n#define\tnot_reached() do {\t\t\t\t\t\t\\\n\tif (config_debug) {\t\t\t\t\t\t\\\n\t\tmalloc_printf(\t\t\t\t\t\t\\\n\t\t    \"<jemalloc>: %s:%d: Unreachable code reached\\n\",\t\\\n\t\t    __FILE__, __LINE__);\t\t\t\t\\\n\t\tabort();\t\t\t\t\t\t\\\n\t}\t\t\t\t\t\t\t\t\\\n} while (0)\n#endif\n\n#ifndef not_implemented\n#define\tnot_implemented() do {\t\t\t\t\t\t\\\n\tif (config_debug) {\t\t\t\t\t\t\\\n\t\tmalloc_printf(\"<jemalloc>: %s:%d: Not implemented\\n\",\t\\\n\t\t    __FILE__, __LINE__);\t\t\t\t\\\n\t\tabort();\t\t\t\t\t\t\\\n\t}\t\t\t\t\t\t\t\t\\\n} while (0)\n#endif\n\n#ifndef assert_not_implemented\n#define\tassert_not_implemented(e) do {\t\t\t\t\t\\\n\tif (config_debug && !(e))\t\t\t\t\t\\\n\t\tnot_implemented();\t\t\t\t\t\\\n} while (0)\n#endif\n\n/* Use to assert a particular configuration, e.g., cassert(config_debug). */\n#define\tcassert(c) do {\t\t\t\t\t\t\t\\\n\tif ((c) == false)\t\t\t\t\t\t\\\n\t\tnot_reached();\t\t\t\t\t\t\\\n} while (0)\n\n#endif /* JEMALLOC_H_TYPES */\n/******************************************************************************/\n#ifdef JEMALLOC_H_STRUCTS\n\n#endif /* JEMALLOC_H_STRUCTS */\n/******************************************************************************/\n#ifdef JEMALLOC_H_EXTERNS\n\nint\tbuferror(int err, char *buf, size_t buflen);\nuintmax_t\tmalloc_strtoumax(const char *restrict nptr,\n    char **restrict endptr, int base);\nvoid\tmalloc_write(const char *s);\n\n/*\n * malloc_vsnprintf() supports a subset of snprintf(3) that avoids floating\n * point math.\n */\nint\tmalloc_vsnprintf(char *str, size_t size, const char *format,\n    va_list ap);\nint\tmalloc_snprintf(char *str, size_t size, const char *format, ...)\n    JEMALLOC_ATTR(format(printf, 3, 4));\nvoid\tmalloc_vcprintf(void (*write_cb)(void *, const char *), void *cbopaque,\n    const char *format, va_list ap);\nvoid malloc_cprintf(void (*write)(void *, const char *), void *cbopaque,\n    const char *format, ...) JEMALLOC_ATTR(format(printf, 3, 4));\nvoid\tmalloc_printf(const char *format, ...)\n    JEMALLOC_ATTR(format(printf, 1, 2));\n\n#endif /* JEMALLOC_H_EXTERNS */\n/******************************************************************************/\n#ifdef JEMALLOC_H_INLINES\n\n#ifndef JEMALLOC_ENABLE_INLINE\nsize_t\tpow2_ceil(size_t x);\nvoid\tset_errno(int errnum);\nint\tget_errno(void);\n#endif\n\n#if (defined(JEMALLOC_ENABLE_INLINE) || defined(JEMALLOC_UTIL_C_))\n/* Compute the smallest power of 2 that is >= x. */\nJEMALLOC_INLINE size_t\npow2_ceil(size_t x)\n{\n\n\tx--;\n\tx |= x >> 1;\n\tx |= x >> 2;\n\tx |= x >> 4;\n\tx |= x >> 8;\n\tx |= x >> 16;\n#if (LG_SIZEOF_PTR == 3)\n\tx |= x >> 32;\n#endif\n\tx++;\n\treturn (x);\n}\n\n/* Sets error code */\nJEMALLOC_INLINE void\nset_errno(int errnum)\n{\n\n#ifdef _WIN32\n\tSetLastError(errnum);\n#else\n\terrno = errnum;\n#endif\n}\n\n/* Get last error code */\nJEMALLOC_INLINE int\nget_errno(void)\n{\n\n#ifdef _WIN32\n\treturn (GetLastError());\n#else\n\treturn (errno);\n#endif\n}\n#endif\n\n#endif /* JEMALLOC_H_INLINES */\n/******************************************************************************/\n"
  },
  {
    "path": "extern/deprecated/redis-2.8.21/deps/jemalloc/include/jemalloc/jemalloc.sh",
    "content": "#!/bin/sh\n\nobjroot=$1\n\ncat <<EOF\n#ifndef JEMALLOC_H_\n#define\tJEMALLOC_H_\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\nEOF\n\nfor hdr in jemalloc_defs.h jemalloc_rename.h jemalloc_macros.h \\\n           jemalloc_protos.h jemalloc_mangle.h ; do\n  cat \"${objroot}include/jemalloc/${hdr}\" \\\n      | grep -v 'Generated from .* by configure\\.' \\\n      | sed -e 's/^#define /#define\t/g' \\\n      | sed -e 's/ $//g'\n  echo\ndone\n\ncat <<EOF\n#ifdef __cplusplus\n};\n#endif\n#endif /* JEMALLOC_H_ */\nEOF\n"
  },
  {
    "path": "extern/deprecated/redis-2.8.21/deps/jemalloc/include/jemalloc/jemalloc_defs.h.in",
    "content": "/* Defined if __attribute__((...)) syntax is supported. */\n#undef JEMALLOC_HAVE_ATTR\n\n/* Support the experimental API. */\n#undef JEMALLOC_EXPERIMENTAL\n\n/*\n * Define overrides for non-standard allocator-related functions if they are\n * present on the system.\n */\n#undef JEMALLOC_OVERRIDE_MEMALIGN\n#undef JEMALLOC_OVERRIDE_VALLOC\n\n/*\n * At least Linux omits the \"const\" in:\n *\n *   size_t malloc_usable_size(const void *ptr);\n *\n * Match the operating system's prototype.\n */\n#undef JEMALLOC_USABLE_SIZE_CONST\n\n/* sizeof(void *) == 2^LG_SIZEOF_PTR. */\n#undef LG_SIZEOF_PTR\n"
  },
  {
    "path": "extern/deprecated/redis-2.8.21/deps/jemalloc/include/jemalloc/jemalloc_macros.h.in",
    "content": "#include <limits.h>\n#include <strings.h>\n\n#define\tJEMALLOC_VERSION \"@jemalloc_version@\"\n#define\tJEMALLOC_VERSION_MAJOR @jemalloc_version_major@\n#define\tJEMALLOC_VERSION_MINOR @jemalloc_version_minor@\n#define\tJEMALLOC_VERSION_BUGFIX @jemalloc_version_bugfix@\n#define\tJEMALLOC_VERSION_NREV @jemalloc_version_nrev@\n#define\tJEMALLOC_VERSION_GID \"@jemalloc_version_gid@\"\n\n#  define MALLOCX_LG_ALIGN(la)\t(la)\n#  if LG_SIZEOF_PTR == 2\n#    define MALLOCX_ALIGN(a)\t(ffs(a)-1)\n#  else\n#    define MALLOCX_ALIGN(a)\t\t\t\t\t\t\\\n\t ((a < (size_t)INT_MAX) ? ffs(a)-1 : ffs(a>>32)+31)\n#  endif\n#  define MALLOCX_ZERO\t((int)0x40)\n/* Bias arena index bits so that 0 encodes \"MALLOCX_ARENA() unspecified\". */\n#  define MALLOCX_ARENA(a)\t((int)(((a)+1) << 8))\n\n#ifdef JEMALLOC_EXPERIMENTAL\n#  define ALLOCM_LG_ALIGN(la)\t(la)\n#  if LG_SIZEOF_PTR == 2\n#    define ALLOCM_ALIGN(a)\t(ffs(a)-1)\n#  else\n#    define ALLOCM_ALIGN(a)\t\t\t\t\t\t\\\n\t ((a < (size_t)INT_MAX) ? ffs(a)-1 : ffs(a>>32)+31)\n#  endif\n#  define ALLOCM_ZERO\t((int)0x40)\n#  define ALLOCM_NO_MOVE\t((int)0x80)\n/* Bias arena index bits so that 0 encodes \"ALLOCM_ARENA() unspecified\". */\n#  define ALLOCM_ARENA(a)\t((int)(((a)+1) << 8))\n#  define ALLOCM_SUCCESS\t0\n#  define ALLOCM_ERR_OOM\t1\n#  define ALLOCM_ERR_NOT_MOVED\t2\n#endif\n\n#ifdef JEMALLOC_HAVE_ATTR\n#  define JEMALLOC_ATTR(s) __attribute__((s))\n#  define JEMALLOC_EXPORT JEMALLOC_ATTR(visibility(\"default\"))\n#  define JEMALLOC_ALIGNED(s) JEMALLOC_ATTR(aligned(s))\n#  define JEMALLOC_SECTION(s) JEMALLOC_ATTR(section(s))\n#  define JEMALLOC_NOINLINE JEMALLOC_ATTR(noinline)\n#elif _MSC_VER\n#  define JEMALLOC_ATTR(s)\n#  ifdef DLLEXPORT\n#    define JEMALLOC_EXPORT __declspec(dllexport)\n#  else\n#    define JEMALLOC_EXPORT __declspec(dllimport)\n#  endif\n#  define JEMALLOC_ALIGNED(s) __declspec(align(s))\n#  define JEMALLOC_SECTION(s) __declspec(allocate(s))\n#  define JEMALLOC_NOINLINE __declspec(noinline)\n#else\n#  define JEMALLOC_ATTR(s)\n#  define JEMALLOC_EXPORT\n#  define JEMALLOC_ALIGNED(s)\n#  define JEMALLOC_SECTION(s)\n#  define JEMALLOC_NOINLINE\n#endif\n"
  },
  {
    "path": "extern/deprecated/redis-2.8.21/deps/jemalloc/include/jemalloc/jemalloc_mangle.sh",
    "content": "#!/bin/sh\n\npublic_symbols_txt=$1\nsymbol_prefix=$2\n\ncat <<EOF\n/*\n * By default application code must explicitly refer to mangled symbol names,\n * so that it is possible to use jemalloc in conjunction with another allocator\n * in the same application.  Define JEMALLOC_MANGLE in order to cause automatic\n * name mangling that matches the API prefixing that happened as a result of\n * --with-mangling and/or --with-jemalloc-prefix configuration settings.\n */\n#ifdef JEMALLOC_MANGLE\n#  ifndef JEMALLOC_NO_DEMANGLE\n#    define JEMALLOC_NO_DEMANGLE\n#  endif\nEOF\n\nfor nm in `cat ${public_symbols_txt}` ; do\n  n=`echo ${nm} |tr ':' ' ' |awk '{print $1}'`\n  echo \"#  define ${n} ${symbol_prefix}${n}\"\ndone\n\ncat <<EOF\n#endif\n\n/*\n * The ${symbol_prefix}* macros can be used as stable alternative names for the\n * public jemalloc API if JEMALLOC_NO_DEMANGLE is defined.  This is primarily\n * meant for use in jemalloc itself, but it can be used by application code to\n * provide isolation from the name mangling specified via --with-mangling\n * and/or --with-jemalloc-prefix.\n */\n#ifndef JEMALLOC_NO_DEMANGLE\nEOF\n\nfor nm in `cat ${public_symbols_txt}` ; do\n  n=`echo ${nm} |tr ':' ' ' |awk '{print $1}'`\n  echo \"#  undef ${symbol_prefix}${n}\"\ndone\n\ncat <<EOF\n#endif\nEOF\n"
  },
  {
    "path": "extern/deprecated/redis-2.8.21/deps/jemalloc/include/jemalloc/jemalloc_protos.h.in",
    "content": "/*\n * The @je_@ prefix on the following public symbol declarations is an artifact\n * of namespace management, and should be omitted in application code unless\n * JEMALLOC_NO_DEMANGLE is defined (see jemalloc_mangle@install_suffix@.h).\n */\nextern JEMALLOC_EXPORT const char\t*@je_@malloc_conf;\nextern JEMALLOC_EXPORT void\t\t(*@je_@malloc_message)(void *cbopaque,\n    const char *s);\n\nJEMALLOC_EXPORT void\t*@je_@malloc(size_t size) JEMALLOC_ATTR(malloc);\nJEMALLOC_EXPORT void\t*@je_@calloc(size_t num, size_t size)\n    JEMALLOC_ATTR(malloc);\nJEMALLOC_EXPORT int\t@je_@posix_memalign(void **memptr, size_t alignment,\n    size_t size) JEMALLOC_ATTR(nonnull(1));\nJEMALLOC_EXPORT void\t*@je_@aligned_alloc(size_t alignment, size_t size)\n    JEMALLOC_ATTR(malloc);\nJEMALLOC_EXPORT void\t*@je_@realloc(void *ptr, size_t size);\nJEMALLOC_EXPORT void\t@je_@free(void *ptr);\n\nJEMALLOC_EXPORT void\t*@je_@mallocx(size_t size, int flags);\nJEMALLOC_EXPORT void\t*@je_@rallocx(void *ptr, size_t size, int flags);\nJEMALLOC_EXPORT size_t\t@je_@xallocx(void *ptr, size_t size, size_t extra,\n    int flags);\nJEMALLOC_EXPORT size_t\t@je_@sallocx(const void *ptr, int flags);\nJEMALLOC_EXPORT void\t@je_@dallocx(void *ptr, int flags);\nJEMALLOC_EXPORT size_t\t@je_@nallocx(size_t size, int flags);\n\nJEMALLOC_EXPORT int\t@je_@mallctl(const char *name, void *oldp,\n    size_t *oldlenp, void *newp, size_t newlen);\nJEMALLOC_EXPORT int\t@je_@mallctlnametomib(const char *name, size_t *mibp,\n    size_t *miblenp);\nJEMALLOC_EXPORT int\t@je_@mallctlbymib(const size_t *mib, size_t miblen,\n    void *oldp, size_t *oldlenp, void *newp, size_t newlen);\nJEMALLOC_EXPORT void\t@je_@malloc_stats_print(void (*write_cb)(void *,\n    const char *), void *@je_@cbopaque, const char *opts);\nJEMALLOC_EXPORT size_t\t@je_@malloc_usable_size(\n    JEMALLOC_USABLE_SIZE_CONST void *ptr);\n\n#ifdef JEMALLOC_OVERRIDE_MEMALIGN\nJEMALLOC_EXPORT void *\t@je_@memalign(size_t alignment, size_t size)\n    JEMALLOC_ATTR(malloc);\n#endif\n\n#ifdef JEMALLOC_OVERRIDE_VALLOC\nJEMALLOC_EXPORT void *\t@je_@valloc(size_t size) JEMALLOC_ATTR(malloc);\n#endif\n\n#ifdef JEMALLOC_EXPERIMENTAL\nJEMALLOC_EXPORT int\t@je_@allocm(void **ptr, size_t *rsize, size_t size,\n    int flags) JEMALLOC_ATTR(nonnull(1));\nJEMALLOC_EXPORT int\t@je_@rallocm(void **ptr, size_t *rsize, size_t size,\n    size_t extra, int flags) JEMALLOC_ATTR(nonnull(1));\nJEMALLOC_EXPORT int\t@je_@sallocm(const void *ptr, size_t *rsize, int flags)\n    JEMALLOC_ATTR(nonnull(1));\nJEMALLOC_EXPORT int\t@je_@dallocm(void *ptr, int flags)\n    JEMALLOC_ATTR(nonnull(1));\nJEMALLOC_EXPORT int\t@je_@nallocm(size_t *rsize, size_t size, int flags);\n#endif\n"
  },
  {
    "path": "extern/deprecated/redis-2.8.21/deps/jemalloc/include/jemalloc/jemalloc_rename.sh",
    "content": "#!/bin/sh\n\npublic_symbols_txt=$1\n\ncat <<EOF\n/*\n * Name mangling for public symbols is controlled by --with-mangling and\n * --with-jemalloc-prefix.  With default settings the je_ prefix is stripped by\n * these macro definitions.\n */\n#ifndef JEMALLOC_NO_RENAME\nEOF\n\nfor nm in `cat ${public_symbols_txt}` ; do\n  n=`echo ${nm} |tr ':' ' ' |awk '{print $1}'`\n  m=`echo ${nm} |tr ':' ' ' |awk '{print $2}'`\n  echo \"#  define je_${n} ${m}\"\ndone\n\ncat <<EOF\n#endif\nEOF\n"
  },
  {
    "path": "extern/deprecated/redis-2.8.21/deps/jemalloc/include/msvc_compat/inttypes.h",
    "content": "// ISO C9x  compliant inttypes.h for Microsoft Visual Studio\n// Based on ISO/IEC 9899:TC2 Committee draft (May 6, 2005) WG14/N1124 \n// \n//  Copyright (c) 2006 Alexander Chemeris\n// \n// Redistribution and use in source and binary forms, with or without\n// modification, are permitted provided that the following conditions are met:\n// \n//   1. Redistributions of source code must retain the above copyright notice,\n//      this list of conditions and the following disclaimer.\n// \n//   2. Redistributions in binary form must reproduce the above copyright\n//      notice, this list of conditions and the following disclaimer in the\n//      documentation and/or other materials provided with the distribution.\n// \n//   3. The name of the author may be used to endorse or promote products\n//      derived from this software without specific prior written permission.\n// \n// THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED\n// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF\n// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO\n// EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,\n// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;\n// OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, \n// WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR\n// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF\n// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n// \n///////////////////////////////////////////////////////////////////////////////\n\n#ifndef _MSC_VER // [\n#error \"Use this header only with Microsoft Visual C++ compilers!\"\n#endif // _MSC_VER ]\n\n#ifndef _MSC_INTTYPES_H_ // [\n#define _MSC_INTTYPES_H_\n\n#if _MSC_VER > 1000\n#pragma once\n#endif\n\n#include \"stdint.h\"\n\n// 7.8 Format conversion of integer types\n\ntypedef struct {\n   intmax_t quot;\n   intmax_t rem;\n} imaxdiv_t;\n\n// 7.8.1 Macros for format specifiers\n\n#if !defined(__cplusplus) || defined(__STDC_FORMAT_MACROS) // [   See footnote 185 at page 198\n\n#ifdef _WIN64\n#  define __PRI64_PREFIX        \"l\"\n#  define __PRIPTR_PREFIX       \"l\"\n#else\n#  define __PRI64_PREFIX        \"ll\"\n#  define __PRIPTR_PREFIX\n#endif\n\n// The fprintf macros for signed integers are:\n#define PRId8       \"d\"\n#define PRIi8       \"i\"\n#define PRIdLEAST8  \"d\"\n#define PRIiLEAST8  \"i\"\n#define PRIdFAST8   \"d\"\n#define PRIiFAST8   \"i\"\n\n#define PRId16       \"hd\"\n#define PRIi16       \"hi\"\n#define PRIdLEAST16  \"hd\"\n#define PRIiLEAST16  \"hi\"\n#define PRIdFAST16   \"hd\"\n#define PRIiFAST16   \"hi\"\n\n#define PRId32       \"d\"\n#define PRIi32       \"i\"\n#define PRIdLEAST32  \"d\"\n#define PRIiLEAST32  \"i\"\n#define PRIdFAST32   \"d\"\n#define PRIiFAST32   \"i\"\n\n#define PRId64       __PRI64_PREFIX \"d\"\n#define PRIi64       __PRI64_PREFIX \"i\"\n#define PRIdLEAST64  __PRI64_PREFIX \"d\"\n#define PRIiLEAST64  __PRI64_PREFIX \"i\"\n#define PRIdFAST64   __PRI64_PREFIX \"d\"\n#define PRIiFAST64   __PRI64_PREFIX \"i\"\n\n#define PRIdMAX     __PRI64_PREFIX \"d\"\n#define PRIiMAX     __PRI64_PREFIX \"i\"\n\n#define PRIdPTR     __PRIPTR_PREFIX \"d\"\n#define PRIiPTR     __PRIPTR_PREFIX \"i\"\n\n// The fprintf macros for unsigned integers are:\n#define PRIo8       \"o\"\n#define PRIu8       \"u\"\n#define PRIx8       \"x\"\n#define PRIX8       \"X\"\n#define PRIoLEAST8  \"o\"\n#define PRIuLEAST8  \"u\"\n#define PRIxLEAST8  \"x\"\n#define PRIXLEAST8  \"X\"\n#define PRIoFAST8   \"o\"\n#define PRIuFAST8   \"u\"\n#define PRIxFAST8   \"x\"\n#define PRIXFAST8   \"X\"\n\n#define PRIo16       \"ho\"\n#define PRIu16       \"hu\"\n#define PRIx16       \"hx\"\n#define PRIX16       \"hX\"\n#define PRIoLEAST16  \"ho\"\n#define PRIuLEAST16  \"hu\"\n#define PRIxLEAST16  \"hx\"\n#define PRIXLEAST16  \"hX\"\n#define PRIoFAST16   \"ho\"\n#define PRIuFAST16   \"hu\"\n#define PRIxFAST16   \"hx\"\n#define PRIXFAST16   \"hX\"\n\n#define PRIo32       \"o\"\n#define PRIu32       \"u\"\n#define PRIx32       \"x\"\n#define PRIX32       \"X\"\n#define PRIoLEAST32  \"o\"\n#define PRIuLEAST32  \"u\"\n#define PRIxLEAST32  \"x\"\n#define PRIXLEAST32  \"X\"\n#define PRIoFAST32   \"o\"\n#define PRIuFAST32   \"u\"\n#define PRIxFAST32   \"x\"\n#define PRIXFAST32   \"X\"\n\n#define PRIo64       __PRI64_PREFIX \"o\"\n#define PRIu64       __PRI64_PREFIX \"u\"\n#define PRIx64       __PRI64_PREFIX \"x\"\n#define PRIX64       __PRI64_PREFIX \"X\"\n#define PRIoLEAST64  __PRI64_PREFIX \"o\"\n#define PRIuLEAST64  __PRI64_PREFIX \"u\"\n#define PRIxLEAST64  __PRI64_PREFIX \"x\"\n#define PRIXLEAST64  __PRI64_PREFIX \"X\"\n#define PRIoFAST64   __PRI64_PREFIX \"o\"\n#define PRIuFAST64   __PRI64_PREFIX \"u\"\n#define PRIxFAST64   __PRI64_PREFIX \"x\"\n#define PRIXFAST64   __PRI64_PREFIX \"X\"\n\n#define PRIoMAX     __PRI64_PREFIX \"o\"\n#define PRIuMAX     __PRI64_PREFIX \"u\"\n#define PRIxMAX     __PRI64_PREFIX \"x\"\n#define PRIXMAX     __PRI64_PREFIX \"X\"\n\n#define PRIoPTR     __PRIPTR_PREFIX \"o\"\n#define PRIuPTR     __PRIPTR_PREFIX \"u\"\n#define PRIxPTR     __PRIPTR_PREFIX \"x\"\n#define PRIXPTR     __PRIPTR_PREFIX \"X\"\n\n// The fscanf macros for signed integers are:\n#define SCNd8       \"d\"\n#define SCNi8       \"i\"\n#define SCNdLEAST8  \"d\"\n#define SCNiLEAST8  \"i\"\n#define SCNdFAST8   \"d\"\n#define SCNiFAST8   \"i\"\n\n#define SCNd16       \"hd\"\n#define SCNi16       \"hi\"\n#define SCNdLEAST16  \"hd\"\n#define SCNiLEAST16  \"hi\"\n#define SCNdFAST16   \"hd\"\n#define SCNiFAST16   \"hi\"\n\n#define SCNd32       \"ld\"\n#define SCNi32       \"li\"\n#define SCNdLEAST32  \"ld\"\n#define SCNiLEAST32  \"li\"\n#define SCNdFAST32   \"ld\"\n#define SCNiFAST32   \"li\"\n\n#define SCNd64       \"I64d\"\n#define SCNi64       \"I64i\"\n#define SCNdLEAST64  \"I64d\"\n#define SCNiLEAST64  \"I64i\"\n#define SCNdFAST64   \"I64d\"\n#define SCNiFAST64   \"I64i\"\n\n#define SCNdMAX     \"I64d\"\n#define SCNiMAX     \"I64i\"\n\n#ifdef _WIN64 // [\n#  define SCNdPTR     \"I64d\"\n#  define SCNiPTR     \"I64i\"\n#else  // _WIN64 ][\n#  define SCNdPTR     \"ld\"\n#  define SCNiPTR     \"li\"\n#endif  // _WIN64 ]\n\n// The fscanf macros for unsigned integers are:\n#define SCNo8       \"o\"\n#define SCNu8       \"u\"\n#define SCNx8       \"x\"\n#define SCNX8       \"X\"\n#define SCNoLEAST8  \"o\"\n#define SCNuLEAST8  \"u\"\n#define SCNxLEAST8  \"x\"\n#define SCNXLEAST8  \"X\"\n#define SCNoFAST8   \"o\"\n#define SCNuFAST8   \"u\"\n#define SCNxFAST8   \"x\"\n#define SCNXFAST8   \"X\"\n\n#define SCNo16       \"ho\"\n#define SCNu16       \"hu\"\n#define SCNx16       \"hx\"\n#define SCNX16       \"hX\"\n#define SCNoLEAST16  \"ho\"\n#define SCNuLEAST16  \"hu\"\n#define SCNxLEAST16  \"hx\"\n#define SCNXLEAST16  \"hX\"\n#define SCNoFAST16   \"ho\"\n#define SCNuFAST16   \"hu\"\n#define SCNxFAST16   \"hx\"\n#define SCNXFAST16   \"hX\"\n\n#define SCNo32       \"lo\"\n#define SCNu32       \"lu\"\n#define SCNx32       \"lx\"\n#define SCNX32       \"lX\"\n#define SCNoLEAST32  \"lo\"\n#define SCNuLEAST32  \"lu\"\n#define SCNxLEAST32  \"lx\"\n#define SCNXLEAST32  \"lX\"\n#define SCNoFAST32   \"lo\"\n#define SCNuFAST32   \"lu\"\n#define SCNxFAST32   \"lx\"\n#define SCNXFAST32   \"lX\"\n\n#define SCNo64       \"I64o\"\n#define SCNu64       \"I64u\"\n#define SCNx64       \"I64x\"\n#define SCNX64       \"I64X\"\n#define SCNoLEAST64  \"I64o\"\n#define SCNuLEAST64  \"I64u\"\n#define SCNxLEAST64  \"I64x\"\n#define SCNXLEAST64  \"I64X\"\n#define SCNoFAST64   \"I64o\"\n#define SCNuFAST64   \"I64u\"\n#define SCNxFAST64   \"I64x\"\n#define SCNXFAST64   \"I64X\"\n\n#define SCNoMAX     \"I64o\"\n#define SCNuMAX     \"I64u\"\n#define SCNxMAX     \"I64x\"\n#define SCNXMAX     \"I64X\"\n\n#ifdef _WIN64 // [\n#  define SCNoPTR     \"I64o\"\n#  define SCNuPTR     \"I64u\"\n#  define SCNxPTR     \"I64x\"\n#  define SCNXPTR     \"I64X\"\n#else  // _WIN64 ][\n#  define SCNoPTR     \"lo\"\n#  define SCNuPTR     \"lu\"\n#  define SCNxPTR     \"lx\"\n#  define SCNXPTR     \"lX\"\n#endif  // _WIN64 ]\n\n#endif // __STDC_FORMAT_MACROS ]\n\n// 7.8.2 Functions for greatest-width integer types\n\n// 7.8.2.1 The imaxabs function\n#define imaxabs _abs64\n\n// 7.8.2.2 The imaxdiv function\n\n// This is modified version of div() function from Microsoft's div.c found\n// in %MSVC.NET%\\crt\\src\\div.c\n#ifdef STATIC_IMAXDIV // [\nstatic\n#else // STATIC_IMAXDIV ][\n_inline\n#endif // STATIC_IMAXDIV ]\nimaxdiv_t __cdecl imaxdiv(intmax_t numer, intmax_t denom)\n{\n   imaxdiv_t result;\n\n   result.quot = numer / denom;\n   result.rem = numer % denom;\n\n   if (numer < 0 && result.rem > 0) {\n      // did division wrong; must fix up\n      ++result.quot;\n      result.rem -= denom;\n   }\n\n   return result;\n}\n\n// 7.8.2.3 The strtoimax and strtoumax functions\n#define strtoimax _strtoi64\n#define strtoumax _strtoui64\n\n// 7.8.2.4 The wcstoimax and wcstoumax functions\n#define wcstoimax _wcstoi64\n#define wcstoumax _wcstoui64\n\n\n#endif // _MSC_INTTYPES_H_ ]\n"
  },
  {
    "path": "extern/deprecated/redis-2.8.21/deps/jemalloc/include/msvc_compat/stdbool.h",
    "content": "#ifndef stdbool_h\n#define stdbool_h\n\n#include <wtypes.h>\n\n/* MSVC doesn't define _Bool or bool in C, but does have BOOL */\n/* Note this doesn't pass autoconf's test because (bool) 0.5 != true */\ntypedef BOOL _Bool;\n\n#define bool _Bool\n#define true 1\n#define false 0\n\n#define __bool_true_false_are_defined 1\n\n#endif /* stdbool_h */\n"
  },
  {
    "path": "extern/deprecated/redis-2.8.21/deps/jemalloc/include/msvc_compat/stdint.h",
    "content": "// ISO C9x  compliant stdint.h for Microsoft Visual Studio\n// Based on ISO/IEC 9899:TC2 Committee draft (May 6, 2005) WG14/N1124 \n// \n//  Copyright (c) 2006-2008 Alexander Chemeris\n// \n// Redistribution and use in source and binary forms, with or without\n// modification, are permitted provided that the following conditions are met:\n// \n//   1. Redistributions of source code must retain the above copyright notice,\n//      this list of conditions and the following disclaimer.\n// \n//   2. Redistributions in binary form must reproduce the above copyright\n//      notice, this list of conditions and the following disclaimer in the\n//      documentation and/or other materials provided with the distribution.\n// \n//   3. The name of the author may be used to endorse or promote products\n//      derived from this software without specific prior written permission.\n// \n// THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED\n// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF\n// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO\n// EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,\n// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;\n// OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, \n// WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR\n// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF\n// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n// \n///////////////////////////////////////////////////////////////////////////////\n\n#ifndef _MSC_VER // [\n#error \"Use this header only with Microsoft Visual C++ compilers!\"\n#endif // _MSC_VER ]\n\n#ifndef _MSC_STDINT_H_ // [\n#define _MSC_STDINT_H_\n\n#if _MSC_VER > 1000\n#pragma once\n#endif\n\n#include <limits.h>\n\n// For Visual Studio 6 in C++ mode and for many Visual Studio versions when\n// compiling for ARM we should wrap <wchar.h> include with 'extern \"C++\" {}'\n// or compiler give many errors like this:\n//   error C2733: second C linkage of overloaded function 'wmemchr' not allowed\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n#  include <wchar.h>\n#ifdef __cplusplus\n}\n#endif\n\n// Define _W64 macros to mark types changing their size, like intptr_t.\n#ifndef _W64\n#  if !defined(__midl) && (defined(_X86_) || defined(_M_IX86)) && _MSC_VER >= 1300\n#     define _W64 __w64\n#  else\n#     define _W64\n#  endif\n#endif\n\n\n// 7.18.1 Integer types\n\n// 7.18.1.1 Exact-width integer types\n\n// Visual Studio 6 and Embedded Visual C++ 4 doesn't\n// realize that, e.g. char has the same size as __int8\n// so we give up on __intX for them.\n#if (_MSC_VER < 1300)\n   typedef signed char       int8_t;\n   typedef signed short      int16_t;\n   typedef signed int        int32_t;\n   typedef unsigned char     uint8_t;\n   typedef unsigned short    uint16_t;\n   typedef unsigned int      uint32_t;\n#else\n   typedef signed __int8     int8_t;\n   typedef signed __int16    int16_t;\n   typedef signed __int32    int32_t;\n   typedef unsigned __int8   uint8_t;\n   typedef unsigned __int16  uint16_t;\n   typedef unsigned __int32  uint32_t;\n#endif\ntypedef signed __int64       int64_t;\ntypedef unsigned __int64     uint64_t;\n\n\n// 7.18.1.2 Minimum-width integer types\ntypedef int8_t    int_least8_t;\ntypedef int16_t   int_least16_t;\ntypedef int32_t   int_least32_t;\ntypedef int64_t   int_least64_t;\ntypedef uint8_t   uint_least8_t;\ntypedef uint16_t  uint_least16_t;\ntypedef uint32_t  uint_least32_t;\ntypedef uint64_t  uint_least64_t;\n\n// 7.18.1.3 Fastest minimum-width integer types\ntypedef int8_t    int_fast8_t;\ntypedef int16_t   int_fast16_t;\ntypedef int32_t   int_fast32_t;\ntypedef int64_t   int_fast64_t;\ntypedef uint8_t   uint_fast8_t;\ntypedef uint16_t  uint_fast16_t;\ntypedef uint32_t  uint_fast32_t;\ntypedef uint64_t  uint_fast64_t;\n\n// 7.18.1.4 Integer types capable of holding object pointers\n#ifdef _WIN64 // [\n   typedef signed __int64    intptr_t;\n   typedef unsigned __int64  uintptr_t;\n#else // _WIN64 ][\n   typedef _W64 signed int   intptr_t;\n   typedef _W64 unsigned int uintptr_t;\n#endif // _WIN64 ]\n\n// 7.18.1.5 Greatest-width integer types\ntypedef int64_t   intmax_t;\ntypedef uint64_t  uintmax_t;\n\n\n// 7.18.2 Limits of specified-width integer types\n\n#if !defined(__cplusplus) || defined(__STDC_LIMIT_MACROS) // [   See footnote 220 at page 257 and footnote 221 at page 259\n\n// 7.18.2.1 Limits of exact-width integer types\n#define INT8_MIN     ((int8_t)_I8_MIN)\n#define INT8_MAX     _I8_MAX\n#define INT16_MIN    ((int16_t)_I16_MIN)\n#define INT16_MAX    _I16_MAX\n#define INT32_MIN    ((int32_t)_I32_MIN)\n#define INT32_MAX    _I32_MAX\n#define INT64_MIN    ((int64_t)_I64_MIN)\n#define INT64_MAX    _I64_MAX\n#define UINT8_MAX    _UI8_MAX\n#define UINT16_MAX   _UI16_MAX\n#define UINT32_MAX   _UI32_MAX\n#define UINT64_MAX   _UI64_MAX\n\n// 7.18.2.2 Limits of minimum-width integer types\n#define INT_LEAST8_MIN    INT8_MIN\n#define INT_LEAST8_MAX    INT8_MAX\n#define INT_LEAST16_MIN   INT16_MIN\n#define INT_LEAST16_MAX   INT16_MAX\n#define INT_LEAST32_MIN   INT32_MIN\n#define INT_LEAST32_MAX   INT32_MAX\n#define INT_LEAST64_MIN   INT64_MIN\n#define INT_LEAST64_MAX   INT64_MAX\n#define UINT_LEAST8_MAX   UINT8_MAX\n#define UINT_LEAST16_MAX  UINT16_MAX\n#define UINT_LEAST32_MAX  UINT32_MAX\n#define UINT_LEAST64_MAX  UINT64_MAX\n\n// 7.18.2.3 Limits of fastest minimum-width integer types\n#define INT_FAST8_MIN    INT8_MIN\n#define INT_FAST8_MAX    INT8_MAX\n#define INT_FAST16_MIN   INT16_MIN\n#define INT_FAST16_MAX   INT16_MAX\n#define INT_FAST32_MIN   INT32_MIN\n#define INT_FAST32_MAX   INT32_MAX\n#define INT_FAST64_MIN   INT64_MIN\n#define INT_FAST64_MAX   INT64_MAX\n#define UINT_FAST8_MAX   UINT8_MAX\n#define UINT_FAST16_MAX  UINT16_MAX\n#define UINT_FAST32_MAX  UINT32_MAX\n#define UINT_FAST64_MAX  UINT64_MAX\n\n// 7.18.2.4 Limits of integer types capable of holding object pointers\n#ifdef _WIN64 // [\n#  define INTPTR_MIN   INT64_MIN\n#  define INTPTR_MAX   INT64_MAX\n#  define UINTPTR_MAX  UINT64_MAX\n#else // _WIN64 ][\n#  define INTPTR_MIN   INT32_MIN\n#  define INTPTR_MAX   INT32_MAX\n#  define UINTPTR_MAX  UINT32_MAX\n#endif // _WIN64 ]\n\n// 7.18.2.5 Limits of greatest-width integer types\n#define INTMAX_MIN   INT64_MIN\n#define INTMAX_MAX   INT64_MAX\n#define UINTMAX_MAX  UINT64_MAX\n\n// 7.18.3 Limits of other integer types\n\n#ifdef _WIN64 // [\n#  define PTRDIFF_MIN  _I64_MIN\n#  define PTRDIFF_MAX  _I64_MAX\n#else  // _WIN64 ][\n#  define PTRDIFF_MIN  _I32_MIN\n#  define PTRDIFF_MAX  _I32_MAX\n#endif  // _WIN64 ]\n\n#define SIG_ATOMIC_MIN  INT_MIN\n#define SIG_ATOMIC_MAX  INT_MAX\n\n#ifndef SIZE_MAX // [\n#  ifdef _WIN64 // [\n#     define SIZE_MAX  _UI64_MAX\n#  else // _WIN64 ][\n#     define SIZE_MAX  _UI32_MAX\n#  endif // _WIN64 ]\n#endif // SIZE_MAX ]\n\n// WCHAR_MIN and WCHAR_MAX are also defined in <wchar.h>\n#ifndef WCHAR_MIN // [\n#  define WCHAR_MIN  0\n#endif  // WCHAR_MIN ]\n#ifndef WCHAR_MAX // [\n#  define WCHAR_MAX  _UI16_MAX\n#endif  // WCHAR_MAX ]\n\n#define WINT_MIN  0\n#define WINT_MAX  _UI16_MAX\n\n#endif // __STDC_LIMIT_MACROS ]\n\n\n// 7.18.4 Limits of other integer types\n\n#if !defined(__cplusplus) || defined(__STDC_CONSTANT_MACROS) // [   See footnote 224 at page 260\n\n// 7.18.4.1 Macros for minimum-width integer constants\n\n#define INT8_C(val)  val##i8\n#define INT16_C(val) val##i16\n#define INT32_C(val) val##i32\n#define INT64_C(val) val##i64\n\n#define UINT8_C(val)  val##ui8\n#define UINT16_C(val) val##ui16\n#define UINT32_C(val) val##ui32\n#define UINT64_C(val) val##ui64\n\n// 7.18.4.2 Macros for greatest-width integer constants\n#define INTMAX_C   INT64_C\n#define UINTMAX_C  UINT64_C\n\n#endif // __STDC_CONSTANT_MACROS ]\n\n\n#endif // _MSC_STDINT_H_ ]\n"
  },
  {
    "path": "extern/deprecated/redis-2.8.21/deps/jemalloc/include/msvc_compat/strings.h",
    "content": "#ifndef strings_h\n#define strings_h\n\n/* MSVC doesn't define ffs/ffsl. This dummy strings.h header is provided\n * for both */\n#include <intrin.h>\n#pragma intrinsic(_BitScanForward)\nstatic __forceinline int ffsl(long x)\n{\n\tunsigned long i;\n\n\tif (_BitScanForward(&i, x))\n\t\treturn (i + 1);\n\treturn (0);\n}\n\nstatic __forceinline int ffs(int x)\n{\n\n\treturn (ffsl(x));\n}\n\n#endif\n"
  },
  {
    "path": "extern/deprecated/redis-2.8.21/deps/jemalloc/install-sh",
    "content": "#! /bin/sh\n#\n# install - install a program, script, or datafile\n# This comes from X11R5 (mit/util/scripts/install.sh).\n#\n# Copyright 1991 by the Massachusetts Institute of Technology\n#\n# Permission to use, copy, modify, distribute, and sell this software and its\n# documentation for any purpose is hereby granted without fee, provided that\n# the above copyright notice appear in all copies and that both that\n# copyright notice and this permission notice appear in supporting\n# documentation, and that the name of M.I.T. not be used in advertising or\n# publicity pertaining to distribution of the software without specific,\n# written prior permission.  M.I.T. makes no representations about the\n# suitability of this software for any purpose.  It is provided \"as is\"\n# without express or implied warranty.\n#\n# Calling this script install-sh is preferred over install.sh, to prevent\n# `make' implicit rules from creating a file called install from it\n# when there is no Makefile.\n#\n# This script is compatible with the BSD install script, but was written\n# from scratch.  It can only install one file at a time, a restriction\n# shared with many OS's install programs.\n\n\n# set DOITPROG to echo to test this script\n\n# Don't use :- since 4.3BSD and earlier shells don't like it.\ndoit=\"${DOITPROG-}\"\n\n\n# put in absolute paths if you don't have them in your path; or use env. vars.\n\nmvprog=\"${MVPROG-mv}\"\ncpprog=\"${CPPROG-cp}\"\nchmodprog=\"${CHMODPROG-chmod}\"\nchownprog=\"${CHOWNPROG-chown}\"\nchgrpprog=\"${CHGRPPROG-chgrp}\"\nstripprog=\"${STRIPPROG-strip}\"\nrmprog=\"${RMPROG-rm}\"\nmkdirprog=\"${MKDIRPROG-mkdir}\"\n\ntransformbasename=\"\"\ntransform_arg=\"\"\ninstcmd=\"$mvprog\"\nchmodcmd=\"$chmodprog 0755\"\nchowncmd=\"\"\nchgrpcmd=\"\"\nstripcmd=\"\"\nrmcmd=\"$rmprog -f\"\nmvcmd=\"$mvprog\"\nsrc=\"\"\ndst=\"\"\ndir_arg=\"\"\n\nwhile [ x\"$1\" != x ]; do\n    case $1 in\n\t-c) instcmd=\"$cpprog\"\n\t    shift\n\t    continue;;\n\n\t-d) dir_arg=true\n\t    shift\n\t    continue;;\n\n\t-m) chmodcmd=\"$chmodprog $2\"\n\t    shift\n\t    shift\n\t    continue;;\n\n\t-o) chowncmd=\"$chownprog $2\"\n\t    shift\n\t    shift\n\t    continue;;\n\n\t-g) chgrpcmd=\"$chgrpprog $2\"\n\t    shift\n\t    shift\n\t    continue;;\n\n\t-s) stripcmd=\"$stripprog\"\n\t    shift\n\t    continue;;\n\n\t-t=*) transformarg=`echo $1 | sed 's/-t=//'`\n\t    shift\n\t    continue;;\n\n\t-b=*) transformbasename=`echo $1 | sed 's/-b=//'`\n\t    shift\n\t    continue;;\n\n\t*)  if [ x\"$src\" = x ]\n\t    then\n\t\tsrc=$1\n\t    else\n\t\t# this colon is to work around a 386BSD /bin/sh bug\n\t\t:\n\t\tdst=$1\n\t    fi\n\t    shift\n\t    continue;;\n    esac\ndone\n\nif [ x\"$src\" = x ]\nthen\n\techo \"install:\tno input file specified\"\n\texit 1\nelse\n\ttrue\nfi\n\nif [ x\"$dir_arg\" != x ]; then\n\tdst=$src\n\tsrc=\"\"\n\t\n\tif [ -d $dst ]; then\n\t\tinstcmd=:\n\telse\n\t\tinstcmd=mkdir\n\tfi\nelse\n\n# Waiting for this to be detected by the \"$instcmd $src $dsttmp\" command\n# might cause directories to be created, which would be especially bad \n# if $src (and thus $dsttmp) contains '*'.\n\n\tif [ -f $src -o -d $src ]\n\tthen\n\t\ttrue\n\telse\n\t\techo \"install:  $src does not exist\"\n\t\texit 1\n\tfi\n\t\n\tif [ x\"$dst\" = x ]\n\tthen\n\t\techo \"install:\tno destination specified\"\n\t\texit 1\n\telse\n\t\ttrue\n\tfi\n\n# If destination is a directory, append the input filename; if your system\n# does not like double slashes in filenames, you may need to add some logic\n\n\tif [ -d $dst ]\n\tthen\n\t\tdst=\"$dst\"/`basename $src`\n\telse\n\t\ttrue\n\tfi\nfi\n\n## this sed command emulates the dirname command\ndstdir=`echo $dst | sed -e 's,[^/]*$,,;s,/$,,;s,^$,.,'`\n\n# Make sure that the destination directory exists.\n#  this part is taken from Noah Friedman's mkinstalldirs script\n\n# Skip lots of stat calls in the usual case.\nif [ ! -d \"$dstdir\" ]; then\ndefaultIFS='\t\n'\nIFS=\"${IFS-${defaultIFS}}\"\n\noIFS=\"${IFS}\"\n# Some sh's can't handle IFS=/ for some reason.\nIFS='%'\nset - `echo ${dstdir} | sed -e 's@/@%@g' -e 's@^%@/@'`\nIFS=\"${oIFS}\"\n\npathcomp=''\n\nwhile [ $# -ne 0 ] ; do\n\tpathcomp=\"${pathcomp}${1}\"\n\tshift\n\n\tif [ ! -d \"${pathcomp}\" ] ;\n        then\n\t\t$mkdirprog \"${pathcomp}\"\n\telse\n\t\ttrue\n\tfi\n\n\tpathcomp=\"${pathcomp}/\"\ndone\nfi\n\nif [ x\"$dir_arg\" != x ]\nthen\n\t$doit $instcmd $dst &&\n\n\tif [ x\"$chowncmd\" != x ]; then $doit $chowncmd $dst; else true ; fi &&\n\tif [ x\"$chgrpcmd\" != x ]; then $doit $chgrpcmd $dst; else true ; fi &&\n\tif [ x\"$stripcmd\" != x ]; then $doit $stripcmd $dst; else true ; fi &&\n\tif [ x\"$chmodcmd\" != x ]; then $doit $chmodcmd $dst; else true ; fi\nelse\n\n# If we're going to rename the final executable, determine the name now.\n\n\tif [ x\"$transformarg\" = x ] \n\tthen\n\t\tdstfile=`basename $dst`\n\telse\n\t\tdstfile=`basename $dst $transformbasename | \n\t\t\tsed $transformarg`$transformbasename\n\tfi\n\n# don't allow the sed command to completely eliminate the filename\n\n\tif [ x\"$dstfile\" = x ] \n\tthen\n\t\tdstfile=`basename $dst`\n\telse\n\t\ttrue\n\tfi\n\n# Make a temp file name in the proper directory.\n\n\tdsttmp=$dstdir/#inst.$$#\n\n# Move or copy the file name to the temp name\n\n\t$doit $instcmd $src $dsttmp &&\n\n\ttrap \"rm -f ${dsttmp}\" 0 &&\n\n# and set any options; do chmod last to preserve setuid bits\n\n# If any of these fail, we abort the whole thing.  If we want to\n# ignore errors from any of these, just make sure not to ignore\n# errors from the above \"$doit $instcmd $src $dsttmp\" command.\n\n\tif [ x\"$chowncmd\" != x ]; then $doit $chowncmd $dsttmp; else true;fi &&\n\tif [ x\"$chgrpcmd\" != x ]; then $doit $chgrpcmd $dsttmp; else true;fi &&\n\tif [ x\"$stripcmd\" != x ]; then $doit $stripcmd $dsttmp; else true;fi &&\n\tif [ x\"$chmodcmd\" != x ]; then $doit $chmodcmd $dsttmp; else true;fi &&\n\n# Now rename the file to the real destination.\n\n\t$doit $rmcmd -f $dstdir/$dstfile &&\n\t$doit $mvcmd $dsttmp $dstdir/$dstfile \n\nfi &&\n\n\nexit 0\n"
  },
  {
    "path": "extern/deprecated/redis-2.8.21/deps/jemalloc/src/arena.c",
    "content": "#define\tJEMALLOC_ARENA_C_\n#include \"jemalloc/internal/jemalloc_internal.h\"\n\n/******************************************************************************/\n/* Data. */\n\nssize_t\t\topt_lg_dirty_mult = LG_DIRTY_MULT_DEFAULT;\narena_bin_info_t\tarena_bin_info[NBINS];\n\nJEMALLOC_ALIGNED(CACHELINE)\nconst uint8_t\tsmall_size2bin[] = {\n#define\tS2B_8(i)\ti,\n#define\tS2B_16(i)\tS2B_8(i) S2B_8(i)\n#define\tS2B_32(i)\tS2B_16(i) S2B_16(i)\n#define\tS2B_64(i)\tS2B_32(i) S2B_32(i)\n#define\tS2B_128(i)\tS2B_64(i) S2B_64(i)\n#define\tS2B_256(i)\tS2B_128(i) S2B_128(i)\n#define\tS2B_512(i)\tS2B_256(i) S2B_256(i)\n#define\tS2B_1024(i)\tS2B_512(i) S2B_512(i)\n#define\tS2B_2048(i)\tS2B_1024(i) S2B_1024(i)\n#define\tS2B_4096(i)\tS2B_2048(i) S2B_2048(i)\n#define\tS2B_8192(i)\tS2B_4096(i) S2B_4096(i)\n#define\tSIZE_CLASS(bin, delta, size)\t\t\t\t\t\\\n\tS2B_##delta(bin)\n\tSIZE_CLASSES\n#undef S2B_8\n#undef S2B_16\n#undef S2B_32\n#undef S2B_64\n#undef S2B_128\n#undef S2B_256\n#undef S2B_512\n#undef S2B_1024\n#undef S2B_2048\n#undef S2B_4096\n#undef S2B_8192\n#undef SIZE_CLASS\n};\n\n/******************************************************************************/\n/*\n * Function prototypes for static functions that are referenced prior to\n * definition.\n */\n\nstatic void\tarena_purge(arena_t *arena, bool all);\nstatic void\tarena_run_dalloc(arena_t *arena, arena_run_t *run, bool dirty,\n    bool cleaned);\nstatic void\tarena_dalloc_bin_run(arena_t *arena, arena_chunk_t *chunk,\n    arena_run_t *run, arena_bin_t *bin);\nstatic void\tarena_bin_lower_run(arena_t *arena, arena_chunk_t *chunk,\n    arena_run_t *run, arena_bin_t *bin);\n\n/******************************************************************************/\n\nstatic inline int\narena_run_comp(arena_chunk_map_t *a, arena_chunk_map_t *b)\n{\n\tuintptr_t a_mapelm = (uintptr_t)a;\n\tuintptr_t b_mapelm = (uintptr_t)b;\n\n\tassert(a != NULL);\n\tassert(b != NULL);\n\n\treturn ((a_mapelm > b_mapelm) - (a_mapelm < b_mapelm));\n}\n\n/* Generate red-black tree functions. */\nrb_gen(static UNUSED, arena_run_tree_, arena_run_tree_t, arena_chunk_map_t,\n    u.rb_link, arena_run_comp)\n\nstatic inline int\narena_avail_comp(arena_chunk_map_t *a, arena_chunk_map_t *b)\n{\n\tint ret;\n\tsize_t a_size = a->bits & ~PAGE_MASK;\n\tsize_t b_size = b->bits & ~PAGE_MASK;\n\n\tret = (a_size > b_size) - (a_size < b_size);\n\tif (ret == 0) {\n\t\tuintptr_t a_mapelm, b_mapelm;\n\n\t\tif ((a->bits & CHUNK_MAP_KEY) != CHUNK_MAP_KEY)\n\t\t\ta_mapelm = (uintptr_t)a;\n\t\telse {\n\t\t\t/*\n\t\t\t * Treat keys as though they are lower than anything\n\t\t\t * else.\n\t\t\t */\n\t\t\ta_mapelm = 0;\n\t\t}\n\t\tb_mapelm = (uintptr_t)b;\n\n\t\tret = (a_mapelm > b_mapelm) - (a_mapelm < b_mapelm);\n\t}\n\n\treturn (ret);\n}\n\n/* Generate red-black tree functions. */\nrb_gen(static UNUSED, arena_avail_tree_, arena_avail_tree_t, arena_chunk_map_t,\n    u.rb_link, arena_avail_comp)\n\nstatic inline int\narena_chunk_dirty_comp(arena_chunk_t *a, arena_chunk_t *b)\n{\n\n\tassert(a != NULL);\n\tassert(b != NULL);\n\n\t/*\n\t * Short-circuit for self comparison.  The following comparison code\n\t * would come to the same result, but at the cost of executing the slow\n\t * path.\n\t */\n\tif (a == b)\n\t\treturn (0);\n\n\t/*\n\t * Order such that chunks with higher fragmentation are \"less than\"\n\t * those with lower fragmentation -- purging order is from \"least\" to\n\t * \"greatest\".  Fragmentation is measured as:\n\t *\n\t *     mean current avail run size\n\t *   --------------------------------\n\t *   mean defragmented avail run size\n\t *\n\t *            navail\n\t *         -----------\n\t *         nruns_avail           nruns_avail-nruns_adjac\n\t * = ========================= = -----------------------\n\t *            navail                  nruns_avail\n\t *    -----------------------\n\t *    nruns_avail-nruns_adjac\n\t *\n\t * The following code multiplies away the denominator prior to\n\t * comparison, in order to avoid division.\n\t *\n\t */\n\t{\n\t\tsize_t a_val = (a->nruns_avail - a->nruns_adjac) *\n\t\t    b->nruns_avail;\n\t\tsize_t b_val = (b->nruns_avail - b->nruns_adjac) *\n\t\t    a->nruns_avail;\n\n\t\tif (a_val < b_val)\n\t\t\treturn (1);\n\t\tif (a_val > b_val)\n\t\t\treturn (-1);\n\t}\n\t/*\n\t * Break ties by chunk address.  For fragmented chunks, report lower\n\t * addresses as \"lower\", so that fragmentation reduction happens first\n\t * at lower addresses.  However, use the opposite ordering for\n\t * unfragmented chunks, in order to increase the chances of\n\t * re-allocating dirty runs.\n\t */\n\t{\n\t\tuintptr_t a_chunk = (uintptr_t)a;\n\t\tuintptr_t b_chunk = (uintptr_t)b;\n\t\tint ret = ((a_chunk > b_chunk) - (a_chunk < b_chunk));\n\t\tif (a->nruns_adjac == 0) {\n\t\t\tassert(b->nruns_adjac == 0);\n\t\t\tret = -ret;\n\t\t}\n\t\treturn (ret);\n\t}\n}\n\n/* Generate red-black tree functions. */\nrb_gen(static UNUSED, arena_chunk_dirty_, arena_chunk_tree_t, arena_chunk_t,\n    dirty_link, arena_chunk_dirty_comp)\n\nstatic inline bool\narena_avail_adjac_pred(arena_chunk_t *chunk, size_t pageind)\n{\n\tbool ret;\n\n\tif (pageind-1 < map_bias)\n\t\tret = false;\n\telse {\n\t\tret = (arena_mapbits_allocated_get(chunk, pageind-1) == 0);\n\t\tassert(ret == false || arena_mapbits_dirty_get(chunk,\n\t\t    pageind-1) != arena_mapbits_dirty_get(chunk, pageind));\n\t}\n\treturn (ret);\n}\n\nstatic inline bool\narena_avail_adjac_succ(arena_chunk_t *chunk, size_t pageind, size_t npages)\n{\n\tbool ret;\n\n\tif (pageind+npages == chunk_npages)\n\t\tret = false;\n\telse {\n\t\tassert(pageind+npages < chunk_npages);\n\t\tret = (arena_mapbits_allocated_get(chunk, pageind+npages) == 0);\n\t\tassert(ret == false || arena_mapbits_dirty_get(chunk, pageind)\n\t\t    != arena_mapbits_dirty_get(chunk, pageind+npages));\n\t}\n\treturn (ret);\n}\n\nstatic inline bool\narena_avail_adjac(arena_chunk_t *chunk, size_t pageind, size_t npages)\n{\n\n\treturn (arena_avail_adjac_pred(chunk, pageind) ||\n\t    arena_avail_adjac_succ(chunk, pageind, npages));\n}\n\nstatic void\narena_avail_insert(arena_t *arena, arena_chunk_t *chunk, size_t pageind,\n    size_t npages, bool maybe_adjac_pred, bool maybe_adjac_succ)\n{\n\n\tassert(npages == (arena_mapbits_unallocated_size_get(chunk, pageind) >>\n\t    LG_PAGE));\n\n\t/*\n\t * chunks_dirty is keyed by nruns_{avail,adjac}, so the chunk must be\n\t * removed and reinserted even if the run to be inserted is clean.\n\t */\n\tif (chunk->ndirty != 0)\n\t\tarena_chunk_dirty_remove(&arena->chunks_dirty, chunk);\n\n\tif (maybe_adjac_pred && arena_avail_adjac_pred(chunk, pageind))\n\t\tchunk->nruns_adjac++;\n\tif (maybe_adjac_succ && arena_avail_adjac_succ(chunk, pageind, npages))\n\t\tchunk->nruns_adjac++;\n\tchunk->nruns_avail++;\n\tassert(chunk->nruns_avail > chunk->nruns_adjac);\n\n\tif (arena_mapbits_dirty_get(chunk, pageind) != 0) {\n\t\tarena->ndirty += npages;\n\t\tchunk->ndirty += npages;\n\t}\n\tif (chunk->ndirty != 0)\n\t\tarena_chunk_dirty_insert(&arena->chunks_dirty, chunk);\n\n\tarena_avail_tree_insert(&arena->runs_avail, arena_mapp_get(chunk,\n\t    pageind));\n}\n\nstatic void\narena_avail_remove(arena_t *arena, arena_chunk_t *chunk, size_t pageind,\n    size_t npages, bool maybe_adjac_pred, bool maybe_adjac_succ)\n{\n\n\tassert(npages == (arena_mapbits_unallocated_size_get(chunk, pageind) >>\n\t    LG_PAGE));\n\n\t/*\n\t * chunks_dirty is keyed by nruns_{avail,adjac}, so the chunk must be\n\t * removed and reinserted even if the run to be removed is clean.\n\t */\n\tif (chunk->ndirty != 0)\n\t\tarena_chunk_dirty_remove(&arena->chunks_dirty, chunk);\n\n\tif (maybe_adjac_pred && arena_avail_adjac_pred(chunk, pageind))\n\t\tchunk->nruns_adjac--;\n\tif (maybe_adjac_succ && arena_avail_adjac_succ(chunk, pageind, npages))\n\t\tchunk->nruns_adjac--;\n\tchunk->nruns_avail--;\n\tassert(chunk->nruns_avail > chunk->nruns_adjac || (chunk->nruns_avail\n\t    == 0 && chunk->nruns_adjac == 0));\n\n\tif (arena_mapbits_dirty_get(chunk, pageind) != 0) {\n\t\tarena->ndirty -= npages;\n\t\tchunk->ndirty -= npages;\n\t}\n\tif (chunk->ndirty != 0)\n\t\tarena_chunk_dirty_insert(&arena->chunks_dirty, chunk);\n\n\tarena_avail_tree_remove(&arena->runs_avail, arena_mapp_get(chunk,\n\t    pageind));\n}\n\nstatic inline void *\narena_run_reg_alloc(arena_run_t *run, arena_bin_info_t *bin_info)\n{\n\tvoid *ret;\n\tunsigned regind;\n\tbitmap_t *bitmap = (bitmap_t *)((uintptr_t)run +\n\t    (uintptr_t)bin_info->bitmap_offset);\n\n\tassert(run->nfree > 0);\n\tassert(bitmap_full(bitmap, &bin_info->bitmap_info) == false);\n\n\tregind = bitmap_sfu(bitmap, &bin_info->bitmap_info);\n\tret = (void *)((uintptr_t)run + (uintptr_t)bin_info->reg0_offset +\n\t    (uintptr_t)(bin_info->reg_interval * regind));\n\trun->nfree--;\n\tif (regind == run->nextind)\n\t\trun->nextind++;\n\tassert(regind < run->nextind);\n\treturn (ret);\n}\n\nstatic inline void\narena_run_reg_dalloc(arena_run_t *run, void *ptr)\n{\n\tarena_chunk_t *chunk = (arena_chunk_t *)CHUNK_ADDR2BASE(run);\n\tsize_t pageind = ((uintptr_t)ptr - (uintptr_t)chunk) >> LG_PAGE;\n\tsize_t mapbits = arena_mapbits_get(chunk, pageind);\n\tsize_t binind = arena_ptr_small_binind_get(ptr, mapbits);\n\tarena_bin_info_t *bin_info = &arena_bin_info[binind];\n\tunsigned regind = arena_run_regind(run, bin_info, ptr);\n\tbitmap_t *bitmap = (bitmap_t *)((uintptr_t)run +\n\t    (uintptr_t)bin_info->bitmap_offset);\n\n\tassert(run->nfree < bin_info->nregs);\n\t/* Freeing an interior pointer can cause assertion failure. */\n\tassert(((uintptr_t)ptr - ((uintptr_t)run +\n\t    (uintptr_t)bin_info->reg0_offset)) %\n\t    (uintptr_t)bin_info->reg_interval == 0);\n\tassert((uintptr_t)ptr >= (uintptr_t)run +\n\t    (uintptr_t)bin_info->reg0_offset);\n\t/* Freeing an unallocated pointer can cause assertion failure. */\n\tassert(bitmap_get(bitmap, &bin_info->bitmap_info, regind));\n\n\tbitmap_unset(bitmap, &bin_info->bitmap_info, regind);\n\trun->nfree++;\n}\n\nstatic inline void\narena_run_zero(arena_chunk_t *chunk, size_t run_ind, size_t npages)\n{\n\n\tVALGRIND_MAKE_MEM_UNDEFINED((void *)((uintptr_t)chunk + (run_ind <<\n\t    LG_PAGE)), (npages << LG_PAGE));\n\tmemset((void *)((uintptr_t)chunk + (run_ind << LG_PAGE)), 0,\n\t    (npages << LG_PAGE));\n}\n\nstatic inline void\narena_run_page_mark_zeroed(arena_chunk_t *chunk, size_t run_ind)\n{\n\n\tVALGRIND_MAKE_MEM_DEFINED((void *)((uintptr_t)chunk + (run_ind <<\n\t    LG_PAGE)), PAGE);\n}\n\nstatic inline void\narena_run_page_validate_zeroed(arena_chunk_t *chunk, size_t run_ind)\n{\n\tsize_t i;\n\tUNUSED size_t *p = (size_t *)((uintptr_t)chunk + (run_ind << LG_PAGE));\n\n\tarena_run_page_mark_zeroed(chunk, run_ind);\n\tfor (i = 0; i < PAGE / sizeof(size_t); i++)\n\t\tassert(p[i] == 0);\n}\n\nstatic void\narena_cactive_update(arena_t *arena, size_t add_pages, size_t sub_pages)\n{\n\n\tif (config_stats) {\n\t\tssize_t cactive_diff = CHUNK_CEILING((arena->nactive +\n\t\t    add_pages) << LG_PAGE) - CHUNK_CEILING((arena->nactive -\n\t\t    sub_pages) << LG_PAGE);\n\t\tif (cactive_diff != 0)\n\t\t\tstats_cactive_add(cactive_diff);\n\t}\n}\n\nstatic void\narena_run_split_remove(arena_t *arena, arena_chunk_t *chunk, size_t run_ind,\n    size_t flag_dirty, size_t need_pages)\n{\n\tsize_t total_pages, rem_pages;\n\n\ttotal_pages = arena_mapbits_unallocated_size_get(chunk, run_ind) >>\n\t    LG_PAGE;\n\tassert(arena_mapbits_dirty_get(chunk, run_ind+total_pages-1) ==\n\t    flag_dirty);\n\tassert(need_pages <= total_pages);\n\trem_pages = total_pages - need_pages;\n\n\tarena_avail_remove(arena, chunk, run_ind, total_pages, true, true);\n\tarena_cactive_update(arena, need_pages, 0);\n\tarena->nactive += need_pages;\n\n\t/* Keep track of trailing unused pages for later use. */\n\tif (rem_pages > 0) {\n\t\tif (flag_dirty != 0) {\n\t\t\tarena_mapbits_unallocated_set(chunk,\n\t\t\t    run_ind+need_pages, (rem_pages << LG_PAGE),\n\t\t\t    flag_dirty);\n\t\t\tarena_mapbits_unallocated_set(chunk,\n\t\t\t    run_ind+total_pages-1, (rem_pages << LG_PAGE),\n\t\t\t    flag_dirty);\n\t\t} else {\n\t\t\tarena_mapbits_unallocated_set(chunk, run_ind+need_pages,\n\t\t\t    (rem_pages << LG_PAGE),\n\t\t\t    arena_mapbits_unzeroed_get(chunk,\n\t\t\t    run_ind+need_pages));\n\t\t\tarena_mapbits_unallocated_set(chunk,\n\t\t\t    run_ind+total_pages-1, (rem_pages << LG_PAGE),\n\t\t\t    arena_mapbits_unzeroed_get(chunk,\n\t\t\t    run_ind+total_pages-1));\n\t\t}\n\t\tarena_avail_insert(arena, chunk, run_ind+need_pages, rem_pages,\n\t\t    false, true);\n\t}\n}\n\nstatic void\narena_run_split_large_helper(arena_t *arena, arena_run_t *run, size_t size,\n    bool remove, bool zero)\n{\n\tarena_chunk_t *chunk;\n\tsize_t flag_dirty, run_ind, need_pages, i;\n\n\tchunk = (arena_chunk_t *)CHUNK_ADDR2BASE(run);\n\trun_ind = (unsigned)(((uintptr_t)run - (uintptr_t)chunk) >> LG_PAGE);\n\tflag_dirty = arena_mapbits_dirty_get(chunk, run_ind);\n\tneed_pages = (size >> LG_PAGE);\n\tassert(need_pages > 0);\n\n\tif (remove) {\n\t\tarena_run_split_remove(arena, chunk, run_ind, flag_dirty,\n\t\t    need_pages);\n\t}\n\n\tif (zero) {\n\t\tif (flag_dirty == 0) {\n\t\t\t/*\n\t\t\t * The run is clean, so some pages may be zeroed (i.e.\n\t\t\t * never before touched).\n\t\t\t */\n\t\t\tfor (i = 0; i < need_pages; i++) {\n\t\t\t\tif (arena_mapbits_unzeroed_get(chunk, run_ind+i)\n\t\t\t\t    != 0)\n\t\t\t\t\tarena_run_zero(chunk, run_ind+i, 1);\n\t\t\t\telse if (config_debug) {\n\t\t\t\t\tarena_run_page_validate_zeroed(chunk,\n\t\t\t\t\t    run_ind+i);\n\t\t\t\t} else {\n\t\t\t\t\tarena_run_page_mark_zeroed(chunk,\n\t\t\t\t\t    run_ind+i);\n\t\t\t\t}\n\t\t\t}\n\t\t} else {\n\t\t\t/* The run is dirty, so all pages must be zeroed. */\n\t\t\tarena_run_zero(chunk, run_ind, need_pages);\n\t\t}\n\t} else {\n\t\tVALGRIND_MAKE_MEM_UNDEFINED((void *)((uintptr_t)chunk +\n\t\t    (run_ind << LG_PAGE)), (need_pages << LG_PAGE));\n\t}\n\n\t/*\n\t * Set the last element first, in case the run only contains one page\n\t * (i.e. both statements set the same element).\n\t */\n\tarena_mapbits_large_set(chunk, run_ind+need_pages-1, 0, flag_dirty);\n\tarena_mapbits_large_set(chunk, run_ind, size, flag_dirty);\n}\n\nstatic void\narena_run_split_large(arena_t *arena, arena_run_t *run, size_t size, bool zero)\n{\n\n\tarena_run_split_large_helper(arena, run, size, true, zero);\n}\n\nstatic void\narena_run_init_large(arena_t *arena, arena_run_t *run, size_t size, bool zero)\n{\n\n\tarena_run_split_large_helper(arena, run, size, false, zero);\n}\n\nstatic void\narena_run_split_small(arena_t *arena, arena_run_t *run, size_t size,\n    size_t binind)\n{\n\tarena_chunk_t *chunk;\n\tsize_t flag_dirty, run_ind, need_pages, i;\n\n\tassert(binind != BININD_INVALID);\n\n\tchunk = (arena_chunk_t *)CHUNK_ADDR2BASE(run);\n\trun_ind = (unsigned)(((uintptr_t)run - (uintptr_t)chunk) >> LG_PAGE);\n\tflag_dirty = arena_mapbits_dirty_get(chunk, run_ind);\n\tneed_pages = (size >> LG_PAGE);\n\tassert(need_pages > 0);\n\n\tarena_run_split_remove(arena, chunk, run_ind, flag_dirty, need_pages);\n\n\t/*\n\t * Propagate the dirty and unzeroed flags to the allocated small run,\n\t * so that arena_dalloc_bin_run() has the ability to conditionally trim\n\t * clean pages.\n\t */\n\tarena_mapbits_small_set(chunk, run_ind, 0, binind, flag_dirty);\n\t/*\n\t * The first page will always be dirtied during small run\n\t * initialization, so a validation failure here would not actually\n\t * cause an observable failure.\n\t */\n\tif (config_debug && flag_dirty == 0 && arena_mapbits_unzeroed_get(chunk,\n\t    run_ind) == 0)\n\t\tarena_run_page_validate_zeroed(chunk, run_ind);\n\tfor (i = 1; i < need_pages - 1; i++) {\n\t\tarena_mapbits_small_set(chunk, run_ind+i, i, binind, 0);\n\t\tif (config_debug && flag_dirty == 0 &&\n\t\t    arena_mapbits_unzeroed_get(chunk, run_ind+i) == 0)\n\t\t\tarena_run_page_validate_zeroed(chunk, run_ind+i);\n\t}\n\tarena_mapbits_small_set(chunk, run_ind+need_pages-1, need_pages-1,\n\t    binind, flag_dirty);\n\tif (config_debug && flag_dirty == 0 && arena_mapbits_unzeroed_get(chunk,\n\t    run_ind+need_pages-1) == 0)\n\t\tarena_run_page_validate_zeroed(chunk, run_ind+need_pages-1);\n\tVALGRIND_MAKE_MEM_UNDEFINED((void *)((uintptr_t)chunk +\n\t    (run_ind << LG_PAGE)), (need_pages << LG_PAGE));\n}\n\nstatic arena_chunk_t *\narena_chunk_init_spare(arena_t *arena)\n{\n\tarena_chunk_t *chunk;\n\n\tassert(arena->spare != NULL);\n\n\tchunk = arena->spare;\n\tarena->spare = NULL;\n\n\tassert(arena_mapbits_allocated_get(chunk, map_bias) == 0);\n\tassert(arena_mapbits_allocated_get(chunk, chunk_npages-1) == 0);\n\tassert(arena_mapbits_unallocated_size_get(chunk, map_bias) ==\n\t    arena_maxclass);\n\tassert(arena_mapbits_unallocated_size_get(chunk, chunk_npages-1) ==\n\t    arena_maxclass);\n\tassert(arena_mapbits_dirty_get(chunk, map_bias) ==\n\t    arena_mapbits_dirty_get(chunk, chunk_npages-1));\n\n\treturn (chunk);\n}\n\nstatic arena_chunk_t *\narena_chunk_init_hard(arena_t *arena)\n{\n\tarena_chunk_t *chunk;\n\tbool zero;\n\tsize_t unzeroed, i;\n\n\tassert(arena->spare == NULL);\n\n\tzero = false;\n\tmalloc_mutex_unlock(&arena->lock);\n\tchunk = (arena_chunk_t *)chunk_alloc(chunksize, chunksize, false,\n\t    &zero, arena->dss_prec);\n\tmalloc_mutex_lock(&arena->lock);\n\tif (chunk == NULL)\n\t\treturn (NULL);\n\tif (config_stats)\n\t\tarena->stats.mapped += chunksize;\n\n\tchunk->arena = arena;\n\n\t/*\n\t * Claim that no pages are in use, since the header is merely overhead.\n\t */\n\tchunk->ndirty = 0;\n\n\tchunk->nruns_avail = 0;\n\tchunk->nruns_adjac = 0;\n\n\t/*\n\t * Initialize the map to contain one maximal free untouched run.  Mark\n\t * the pages as zeroed iff chunk_alloc() returned a zeroed chunk.\n\t */\n\tunzeroed = zero ? 0 : CHUNK_MAP_UNZEROED;\n\tarena_mapbits_unallocated_set(chunk, map_bias, arena_maxclass,\n\t    unzeroed);\n\t/*\n\t * There is no need to initialize the internal page map entries unless\n\t * the chunk is not zeroed.\n\t */\n\tif (zero == false) {\n\t\tVALGRIND_MAKE_MEM_UNDEFINED((void *)arena_mapp_get(chunk,\n\t\t    map_bias+1), (size_t)((uintptr_t) arena_mapp_get(chunk,\n\t\t    chunk_npages-1) - (uintptr_t)arena_mapp_get(chunk,\n\t\t    map_bias+1)));\n\t\tfor (i = map_bias+1; i < chunk_npages-1; i++)\n\t\t\tarena_mapbits_unzeroed_set(chunk, i, unzeroed);\n\t} else {\n\t\tVALGRIND_MAKE_MEM_DEFINED((void *)arena_mapp_get(chunk,\n\t\t    map_bias+1), (size_t)((uintptr_t) arena_mapp_get(chunk,\n\t\t    chunk_npages-1) - (uintptr_t)arena_mapp_get(chunk,\n\t\t    map_bias+1)));\n\t\tif (config_debug) {\n\t\t\tfor (i = map_bias+1; i < chunk_npages-1; i++) {\n\t\t\t\tassert(arena_mapbits_unzeroed_get(chunk, i) ==\n\t\t\t\t    unzeroed);\n\t\t\t}\n\t\t}\n\t}\n\tarena_mapbits_unallocated_set(chunk, chunk_npages-1, arena_maxclass,\n\t    unzeroed);\n\n\treturn (chunk);\n}\n\nstatic arena_chunk_t *\narena_chunk_alloc(arena_t *arena)\n{\n\tarena_chunk_t *chunk;\n\n\tif (arena->spare != NULL)\n\t\tchunk = arena_chunk_init_spare(arena);\n\telse {\n\t\tchunk = arena_chunk_init_hard(arena);\n\t\tif (chunk == NULL)\n\t\t\treturn (NULL);\n\t}\n\n\t/* Insert the run into the runs_avail tree. */\n\tarena_avail_insert(arena, chunk, map_bias, chunk_npages-map_bias,\n\t    false, false);\n\n\treturn (chunk);\n}\n\nstatic void\narena_chunk_dealloc(arena_t *arena, arena_chunk_t *chunk)\n{\n\tassert(arena_mapbits_allocated_get(chunk, map_bias) == 0);\n\tassert(arena_mapbits_allocated_get(chunk, chunk_npages-1) == 0);\n\tassert(arena_mapbits_unallocated_size_get(chunk, map_bias) ==\n\t    arena_maxclass);\n\tassert(arena_mapbits_unallocated_size_get(chunk, chunk_npages-1) ==\n\t    arena_maxclass);\n\tassert(arena_mapbits_dirty_get(chunk, map_bias) ==\n\t    arena_mapbits_dirty_get(chunk, chunk_npages-1));\n\n\t/*\n\t * Remove run from the runs_avail tree, so that the arena does not use\n\t * it.\n\t */\n\tarena_avail_remove(arena, chunk, map_bias, chunk_npages-map_bias,\n\t    false, false);\n\n\tif (arena->spare != NULL) {\n\t\tarena_chunk_t *spare = arena->spare;\n\n\t\tarena->spare = chunk;\n\t\tmalloc_mutex_unlock(&arena->lock);\n\t\tchunk_dealloc((void *)spare, chunksize, true);\n\t\tmalloc_mutex_lock(&arena->lock);\n\t\tif (config_stats)\n\t\t\tarena->stats.mapped -= chunksize;\n\t} else\n\t\tarena->spare = chunk;\n}\n\nstatic arena_run_t *\narena_run_alloc_large_helper(arena_t *arena, size_t size, bool zero)\n{\n\tarena_run_t *run;\n\tarena_chunk_map_t *mapelm, key;\n\n\tkey.bits = size | CHUNK_MAP_KEY;\n\tmapelm = arena_avail_tree_nsearch(&arena->runs_avail, &key);\n\tif (mapelm != NULL) {\n\t\tarena_chunk_t *run_chunk = CHUNK_ADDR2BASE(mapelm);\n\t\tsize_t pageind = (((uintptr_t)mapelm -\n\t\t    (uintptr_t)run_chunk->map) / sizeof(arena_chunk_map_t))\n\t\t    + map_bias;\n\n\t\trun = (arena_run_t *)((uintptr_t)run_chunk + (pageind <<\n\t\t    LG_PAGE));\n\t\tarena_run_split_large(arena, run, size, zero);\n\t\treturn (run);\n\t}\n\n\treturn (NULL);\n}\n\nstatic arena_run_t *\narena_run_alloc_large(arena_t *arena, size_t size, bool zero)\n{\n\tarena_chunk_t *chunk;\n\tarena_run_t *run;\n\n\tassert(size <= arena_maxclass);\n\tassert((size & PAGE_MASK) == 0);\n\n\t/* Search the arena's chunks for the lowest best fit. */\n\trun = arena_run_alloc_large_helper(arena, size, zero);\n\tif (run != NULL)\n\t\treturn (run);\n\n\t/*\n\t * No usable runs.  Create a new chunk from which to allocate the run.\n\t */\n\tchunk = arena_chunk_alloc(arena);\n\tif (chunk != NULL) {\n\t\trun = (arena_run_t *)((uintptr_t)chunk + (map_bias << LG_PAGE));\n\t\tarena_run_split_large(arena, run, size, zero);\n\t\treturn (run);\n\t}\n\n\t/*\n\t * arena_chunk_alloc() failed, but another thread may have made\n\t * sufficient memory available while this one dropped arena->lock in\n\t * arena_chunk_alloc(), so search one more time.\n\t */\n\treturn (arena_run_alloc_large_helper(arena, size, zero));\n}\n\nstatic arena_run_t *\narena_run_alloc_small_helper(arena_t *arena, size_t size, size_t binind)\n{\n\tarena_run_t *run;\n\tarena_chunk_map_t *mapelm, key;\n\n\tkey.bits = size | CHUNK_MAP_KEY;\n\tmapelm = arena_avail_tree_nsearch(&arena->runs_avail, &key);\n\tif (mapelm != NULL) {\n\t\tarena_chunk_t *run_chunk = CHUNK_ADDR2BASE(mapelm);\n\t\tsize_t pageind = (((uintptr_t)mapelm -\n\t\t    (uintptr_t)run_chunk->map) / sizeof(arena_chunk_map_t))\n\t\t    + map_bias;\n\n\t\trun = (arena_run_t *)((uintptr_t)run_chunk + (pageind <<\n\t\t    LG_PAGE));\n\t\tarena_run_split_small(arena, run, size, binind);\n\t\treturn (run);\n\t}\n\n\treturn (NULL);\n}\n\nstatic arena_run_t *\narena_run_alloc_small(arena_t *arena, size_t size, size_t binind)\n{\n\tarena_chunk_t *chunk;\n\tarena_run_t *run;\n\n\tassert(size <= arena_maxclass);\n\tassert((size & PAGE_MASK) == 0);\n\tassert(binind != BININD_INVALID);\n\n\t/* Search the arena's chunks for the lowest best fit. */\n\trun = arena_run_alloc_small_helper(arena, size, binind);\n\tif (run != NULL)\n\t\treturn (run);\n\n\t/*\n\t * No usable runs.  Create a new chunk from which to allocate the run.\n\t */\n\tchunk = arena_chunk_alloc(arena);\n\tif (chunk != NULL) {\n\t\trun = (arena_run_t *)((uintptr_t)chunk + (map_bias << LG_PAGE));\n\t\tarena_run_split_small(arena, run, size, binind);\n\t\treturn (run);\n\t}\n\n\t/*\n\t * arena_chunk_alloc() failed, but another thread may have made\n\t * sufficient memory available while this one dropped arena->lock in\n\t * arena_chunk_alloc(), so search one more time.\n\t */\n\treturn (arena_run_alloc_small_helper(arena, size, binind));\n}\n\nstatic inline void\narena_maybe_purge(arena_t *arena)\n{\n\tsize_t npurgeable, threshold;\n\n\t/* Don't purge if the option is disabled. */\n\tif (opt_lg_dirty_mult < 0)\n\t\treturn;\n\t/* Don't purge if all dirty pages are already being purged. */\n\tif (arena->ndirty <= arena->npurgatory)\n\t\treturn;\n\tnpurgeable = arena->ndirty - arena->npurgatory;\n\tthreshold = (arena->nactive >> opt_lg_dirty_mult);\n\t/*\n\t * Don't purge unless the number of purgeable pages exceeds the\n\t * threshold.\n\t */\n\tif (npurgeable <= threshold)\n\t\treturn;\n\n\tarena_purge(arena, false);\n}\n\nstatic arena_chunk_t *\nchunks_dirty_iter_cb(arena_chunk_tree_t *tree, arena_chunk_t *chunk, void *arg)\n{\n       size_t *ndirty = (size_t *)arg;\n\n       assert(chunk->ndirty != 0);\n       *ndirty += chunk->ndirty;\n       return (NULL);\n}\n\nstatic size_t\narena_compute_npurgatory(arena_t *arena, bool all)\n{\n\tsize_t npurgatory, npurgeable;\n\n\t/*\n\t * Compute the minimum number of pages that this thread should try to\n\t * purge.\n\t */\n\tnpurgeable = arena->ndirty - arena->npurgatory;\n\n\tif (all == false) {\n\t\tsize_t threshold = (arena->nactive >> opt_lg_dirty_mult);\n\n\t\tnpurgatory = npurgeable - threshold;\n\t} else\n\t\tnpurgatory = npurgeable;\n\n\treturn (npurgatory);\n}\n\nstatic void\narena_chunk_stash_dirty(arena_t *arena, arena_chunk_t *chunk, bool all,\n    arena_chunk_mapelms_t *mapelms)\n{\n\tsize_t pageind, npages;\n\n\t/*\n\t * Temporarily allocate free dirty runs within chunk.  If all is false,\n\t * only operate on dirty runs that are fragments; otherwise operate on\n\t * all dirty runs.\n\t */\n\tfor (pageind = map_bias; pageind < chunk_npages; pageind += npages) {\n\t\tarena_chunk_map_t *mapelm = arena_mapp_get(chunk, pageind);\n\t\tif (arena_mapbits_allocated_get(chunk, pageind) == 0) {\n\t\t\tsize_t run_size =\n\t\t\t    arena_mapbits_unallocated_size_get(chunk, pageind);\n\n\t\t\tnpages = run_size >> LG_PAGE;\n\t\t\tassert(pageind + npages <= chunk_npages);\n\t\t\tassert(arena_mapbits_dirty_get(chunk, pageind) ==\n\t\t\t    arena_mapbits_dirty_get(chunk, pageind+npages-1));\n\n\t\t\tif (arena_mapbits_dirty_get(chunk, pageind) != 0 &&\n\t\t\t    (all || arena_avail_adjac(chunk, pageind,\n\t\t\t    npages))) {\n\t\t\t\tarena_run_t *run = (arena_run_t *)((uintptr_t)\n\t\t\t\t    chunk + (uintptr_t)(pageind << LG_PAGE));\n\n\t\t\t\tarena_run_split_large(arena, run, run_size,\n\t\t\t\t    false);\n\t\t\t\t/* Append to list for later processing. */\n\t\t\t\tql_elm_new(mapelm, u.ql_link);\n\t\t\t\tql_tail_insert(mapelms, mapelm, u.ql_link);\n\t\t\t}\n\t\t} else {\n\t\t\t/* Skip run. */\n\t\t\tif (arena_mapbits_large_get(chunk, pageind) != 0) {\n\t\t\t\tnpages = arena_mapbits_large_size_get(chunk,\n\t\t\t\t    pageind) >> LG_PAGE;\n\t\t\t} else {\n\t\t\t\tsize_t binind;\n\t\t\t\tarena_bin_info_t *bin_info;\n\t\t\t\tarena_run_t *run = (arena_run_t *)((uintptr_t)\n\t\t\t\t    chunk + (uintptr_t)(pageind << LG_PAGE));\n\n\t\t\t\tassert(arena_mapbits_small_runind_get(chunk,\n\t\t\t\t    pageind) == 0);\n\t\t\t\tbinind = arena_bin_index(arena, run->bin);\n\t\t\t\tbin_info = &arena_bin_info[binind];\n\t\t\t\tnpages = bin_info->run_size >> LG_PAGE;\n\t\t\t}\n\t\t}\n\t}\n\tassert(pageind == chunk_npages);\n\tassert(chunk->ndirty == 0 || all == false);\n\tassert(chunk->nruns_adjac == 0);\n}\n\nstatic size_t\narena_chunk_purge_stashed(arena_t *arena, arena_chunk_t *chunk,\n    arena_chunk_mapelms_t *mapelms)\n{\n\tsize_t npurged, pageind, npages, nmadvise;\n\tarena_chunk_map_t *mapelm;\n\n\tmalloc_mutex_unlock(&arena->lock);\n\tif (config_stats)\n\t\tnmadvise = 0;\n\tnpurged = 0;\n\tql_foreach(mapelm, mapelms, u.ql_link) {\n\t\tbool unzeroed;\n\t\tsize_t flag_unzeroed, i;\n\n\t\tpageind = (((uintptr_t)mapelm - (uintptr_t)chunk->map) /\n\t\t    sizeof(arena_chunk_map_t)) + map_bias;\n\t\tnpages = arena_mapbits_large_size_get(chunk, pageind) >>\n\t\t    LG_PAGE;\n\t\tassert(pageind + npages <= chunk_npages);\n\t\tunzeroed = pages_purge((void *)((uintptr_t)chunk + (pageind <<\n\t\t    LG_PAGE)), (npages << LG_PAGE));\n\t\tflag_unzeroed = unzeroed ? CHUNK_MAP_UNZEROED : 0;\n\t\t/*\n\t\t * Set the unzeroed flag for all pages, now that pages_purge()\n\t\t * has returned whether the pages were zeroed as a side effect\n\t\t * of purging.  This chunk map modification is safe even though\n\t\t * the arena mutex isn't currently owned by this thread,\n\t\t * because the run is marked as allocated, thus protecting it\n\t\t * from being modified by any other thread.  As long as these\n\t\t * writes don't perturb the first and last elements'\n\t\t * CHUNK_MAP_ALLOCATED bits, behavior is well defined.\n\t\t */\n\t\tfor (i = 0; i < npages; i++) {\n\t\t\tarena_mapbits_unzeroed_set(chunk, pageind+i,\n\t\t\t    flag_unzeroed);\n\t\t}\n\t\tnpurged += npages;\n\t\tif (config_stats)\n\t\t\tnmadvise++;\n\t}\n\tmalloc_mutex_lock(&arena->lock);\n\tif (config_stats)\n\t\tarena->stats.nmadvise += nmadvise;\n\n\treturn (npurged);\n}\n\nstatic void\narena_chunk_unstash_purged(arena_t *arena, arena_chunk_t *chunk,\n    arena_chunk_mapelms_t *mapelms)\n{\n\tarena_chunk_map_t *mapelm;\n\tsize_t pageind;\n\n\t/* Deallocate runs. */\n\tfor (mapelm = ql_first(mapelms); mapelm != NULL;\n\t    mapelm = ql_first(mapelms)) {\n\t\tarena_run_t *run;\n\n\t\tpageind = (((uintptr_t)mapelm - (uintptr_t)chunk->map) /\n\t\t    sizeof(arena_chunk_map_t)) + map_bias;\n\t\trun = (arena_run_t *)((uintptr_t)chunk + (uintptr_t)(pageind <<\n\t\t    LG_PAGE));\n\t\tql_remove(mapelms, mapelm, u.ql_link);\n\t\tarena_run_dalloc(arena, run, false, true);\n\t}\n}\n\nstatic inline size_t\narena_chunk_purge(arena_t *arena, arena_chunk_t *chunk, bool all)\n{\n\tsize_t npurged;\n\tarena_chunk_mapelms_t mapelms;\n\n\tql_new(&mapelms);\n\n\t/*\n\t * If chunk is the spare, temporarily re-allocate it, 1) so that its\n\t * run is reinserted into runs_avail, and 2) so that it cannot be\n\t * completely discarded by another thread while arena->lock is dropped\n\t * by this thread.  Note that the arena_run_dalloc() call will\n\t * implicitly deallocate the chunk, so no explicit action is required\n\t * in this function to deallocate the chunk.\n\t *\n\t * Note that once a chunk contains dirty pages, it cannot again contain\n\t * a single run unless 1) it is a dirty run, or 2) this function purges\n\t * dirty pages and causes the transition to a single clean run.  Thus\n\t * (chunk == arena->spare) is possible, but it is not possible for\n\t * this function to be called on the spare unless it contains a dirty\n\t * run.\n\t */\n\tif (chunk == arena->spare) {\n\t\tassert(arena_mapbits_dirty_get(chunk, map_bias) != 0);\n\t\tassert(arena_mapbits_dirty_get(chunk, chunk_npages-1) != 0);\n\n\t\tarena_chunk_alloc(arena);\n\t}\n\n\tif (config_stats)\n\t\tarena->stats.purged += chunk->ndirty;\n\n\t/*\n\t * Operate on all dirty runs if there is no clean/dirty run\n\t * fragmentation.\n\t */\n\tif (chunk->nruns_adjac == 0)\n\t\tall = true;\n\n\tarena_chunk_stash_dirty(arena, chunk, all, &mapelms);\n\tnpurged = arena_chunk_purge_stashed(arena, chunk, &mapelms);\n\tarena_chunk_unstash_purged(arena, chunk, &mapelms);\n\n\treturn (npurged);\n}\n\nstatic void\narena_purge(arena_t *arena, bool all)\n{\n\tarena_chunk_t *chunk;\n\tsize_t npurgatory;\n\tif (config_debug) {\n\t\tsize_t ndirty = 0;\n\n\t\tarena_chunk_dirty_iter(&arena->chunks_dirty, NULL,\n\t\t    chunks_dirty_iter_cb, (void *)&ndirty);\n\t\tassert(ndirty == arena->ndirty);\n\t}\n\tassert(arena->ndirty > arena->npurgatory || all);\n\tassert((arena->nactive >> opt_lg_dirty_mult) < (arena->ndirty -\n\t    arena->npurgatory) || all);\n\n\tif (config_stats)\n\t\tarena->stats.npurge++;\n\n\t/*\n\t * Add the minimum number of pages this thread should try to purge to\n\t * arena->npurgatory.  This will keep multiple threads from racing to\n\t * reduce ndirty below the threshold.\n\t */\n\tnpurgatory = arena_compute_npurgatory(arena, all);\n\tarena->npurgatory += npurgatory;\n\n\twhile (npurgatory > 0) {\n\t\tsize_t npurgeable, npurged, nunpurged;\n\n\t\t/* Get next chunk with dirty pages. */\n\t\tchunk = arena_chunk_dirty_first(&arena->chunks_dirty);\n\t\tif (chunk == NULL) {\n\t\t\t/*\n\t\t\t * This thread was unable to purge as many pages as\n\t\t\t * originally intended, due to races with other threads\n\t\t\t * that either did some of the purging work, or re-used\n\t\t\t * dirty pages.\n\t\t\t */\n\t\t\tarena->npurgatory -= npurgatory;\n\t\t\treturn;\n\t\t}\n\t\tnpurgeable = chunk->ndirty;\n\t\tassert(npurgeable != 0);\n\n\t\tif (npurgeable > npurgatory && chunk->nruns_adjac == 0) {\n\t\t\t/*\n\t\t\t * This thread will purge all the dirty pages in chunk,\n\t\t\t * so set npurgatory to reflect this thread's intent to\n\t\t\t * purge the pages.  This tends to reduce the chances\n\t\t\t * of the following scenario:\n\t\t\t *\n\t\t\t * 1) This thread sets arena->npurgatory such that\n\t\t\t *    (arena->ndirty - arena->npurgatory) is at the\n\t\t\t *    threshold.\n\t\t\t * 2) This thread drops arena->lock.\n\t\t\t * 3) Another thread causes one or more pages to be\n\t\t\t *    dirtied, and immediately determines that it must\n\t\t\t *    purge dirty pages.\n\t\t\t *\n\t\t\t * If this scenario *does* play out, that's okay,\n\t\t\t * because all of the purging work being done really\n\t\t\t * needs to happen.\n\t\t\t */\n\t\t\tarena->npurgatory += npurgeable - npurgatory;\n\t\t\tnpurgatory = npurgeable;\n\t\t}\n\n\t\t/*\n\t\t * Keep track of how many pages are purgeable, versus how many\n\t\t * actually get purged, and adjust counters accordingly.\n\t\t */\n\t\tarena->npurgatory -= npurgeable;\n\t\tnpurgatory -= npurgeable;\n\t\tnpurged = arena_chunk_purge(arena, chunk, all);\n\t\tnunpurged = npurgeable - npurged;\n\t\tarena->npurgatory += nunpurged;\n\t\tnpurgatory += nunpurged;\n\t}\n}\n\nvoid\narena_purge_all(arena_t *arena)\n{\n\n\tmalloc_mutex_lock(&arena->lock);\n\tarena_purge(arena, true);\n\tmalloc_mutex_unlock(&arena->lock);\n}\n\nstatic void\narena_run_coalesce(arena_t *arena, arena_chunk_t *chunk, size_t *p_size,\n    size_t *p_run_ind, size_t *p_run_pages, size_t flag_dirty)\n{\n\tsize_t size = *p_size;\n\tsize_t run_ind = *p_run_ind;\n\tsize_t run_pages = *p_run_pages;\n\n\t/* Try to coalesce forward. */\n\tif (run_ind + run_pages < chunk_npages &&\n\t    arena_mapbits_allocated_get(chunk, run_ind+run_pages) == 0 &&\n\t    arena_mapbits_dirty_get(chunk, run_ind+run_pages) == flag_dirty) {\n\t\tsize_t nrun_size = arena_mapbits_unallocated_size_get(chunk,\n\t\t    run_ind+run_pages);\n\t\tsize_t nrun_pages = nrun_size >> LG_PAGE;\n\n\t\t/*\n\t\t * Remove successor from runs_avail; the coalesced run is\n\t\t * inserted later.\n\t\t */\n\t\tassert(arena_mapbits_unallocated_size_get(chunk,\n\t\t    run_ind+run_pages+nrun_pages-1) == nrun_size);\n\t\tassert(arena_mapbits_dirty_get(chunk,\n\t\t    run_ind+run_pages+nrun_pages-1) == flag_dirty);\n\t\tarena_avail_remove(arena, chunk, run_ind+run_pages, nrun_pages,\n\t\t    false, true);\n\n\t\tsize += nrun_size;\n\t\trun_pages += nrun_pages;\n\n\t\tarena_mapbits_unallocated_size_set(chunk, run_ind, size);\n\t\tarena_mapbits_unallocated_size_set(chunk, run_ind+run_pages-1,\n\t\t    size);\n\t}\n\n\t/* Try to coalesce backward. */\n\tif (run_ind > map_bias && arena_mapbits_allocated_get(chunk,\n\t    run_ind-1) == 0 && arena_mapbits_dirty_get(chunk, run_ind-1) ==\n\t    flag_dirty) {\n\t\tsize_t prun_size = arena_mapbits_unallocated_size_get(chunk,\n\t\t    run_ind-1);\n\t\tsize_t prun_pages = prun_size >> LG_PAGE;\n\n\t\trun_ind -= prun_pages;\n\n\t\t/*\n\t\t * Remove predecessor from runs_avail; the coalesced run is\n\t\t * inserted later.\n\t\t */\n\t\tassert(arena_mapbits_unallocated_size_get(chunk, run_ind) ==\n\t\t    prun_size);\n\t\tassert(arena_mapbits_dirty_get(chunk, run_ind) == flag_dirty);\n\t\tarena_avail_remove(arena, chunk, run_ind, prun_pages, true,\n\t\t    false);\n\n\t\tsize += prun_size;\n\t\trun_pages += prun_pages;\n\n\t\tarena_mapbits_unallocated_size_set(chunk, run_ind, size);\n\t\tarena_mapbits_unallocated_size_set(chunk, run_ind+run_pages-1,\n\t\t    size);\n\t}\n\n\t*p_size = size;\n\t*p_run_ind = run_ind;\n\t*p_run_pages = run_pages;\n}\n\nstatic void\narena_run_dalloc(arena_t *arena, arena_run_t *run, bool dirty, bool cleaned)\n{\n\tarena_chunk_t *chunk;\n\tsize_t size, run_ind, run_pages, flag_dirty;\n\n\tchunk = (arena_chunk_t *)CHUNK_ADDR2BASE(run);\n\trun_ind = (size_t)(((uintptr_t)run - (uintptr_t)chunk) >> LG_PAGE);\n\tassert(run_ind >= map_bias);\n\tassert(run_ind < chunk_npages);\n\tif (arena_mapbits_large_get(chunk, run_ind) != 0) {\n\t\tsize = arena_mapbits_large_size_get(chunk, run_ind);\n\t\tassert(size == PAGE ||\n\t\t    arena_mapbits_large_size_get(chunk,\n\t\t    run_ind+(size>>LG_PAGE)-1) == 0);\n\t} else {\n\t\tsize_t binind = arena_bin_index(arena, run->bin);\n\t\tarena_bin_info_t *bin_info = &arena_bin_info[binind];\n\t\tsize = bin_info->run_size;\n\t}\n\trun_pages = (size >> LG_PAGE);\n\tarena_cactive_update(arena, 0, run_pages);\n\tarena->nactive -= run_pages;\n\n\t/*\n\t * The run is dirty if the caller claims to have dirtied it, as well as\n\t * if it was already dirty before being allocated and the caller\n\t * doesn't claim to have cleaned it.\n\t */\n\tassert(arena_mapbits_dirty_get(chunk, run_ind) ==\n\t    arena_mapbits_dirty_get(chunk, run_ind+run_pages-1));\n\tif (cleaned == false && arena_mapbits_dirty_get(chunk, run_ind) != 0)\n\t\tdirty = true;\n\tflag_dirty = dirty ? CHUNK_MAP_DIRTY : 0;\n\n\t/* Mark pages as unallocated in the chunk map. */\n\tif (dirty) {\n\t\tarena_mapbits_unallocated_set(chunk, run_ind, size,\n\t\t    CHUNK_MAP_DIRTY);\n\t\tarena_mapbits_unallocated_set(chunk, run_ind+run_pages-1, size,\n\t\t    CHUNK_MAP_DIRTY);\n\t} else {\n\t\tarena_mapbits_unallocated_set(chunk, run_ind, size,\n\t\t    arena_mapbits_unzeroed_get(chunk, run_ind));\n\t\tarena_mapbits_unallocated_set(chunk, run_ind+run_pages-1, size,\n\t\t    arena_mapbits_unzeroed_get(chunk, run_ind+run_pages-1));\n\t}\n\n\tarena_run_coalesce(arena, chunk, &size, &run_ind, &run_pages,\n\t    flag_dirty);\n\n\t/* Insert into runs_avail, now that coalescing is complete. */\n\tassert(arena_mapbits_unallocated_size_get(chunk, run_ind) ==\n\t    arena_mapbits_unallocated_size_get(chunk, run_ind+run_pages-1));\n\tassert(arena_mapbits_dirty_get(chunk, run_ind) ==\n\t    arena_mapbits_dirty_get(chunk, run_ind+run_pages-1));\n\tarena_avail_insert(arena, chunk, run_ind, run_pages, true, true);\n\n\t/* Deallocate chunk if it is now completely unused. */\n\tif (size == arena_maxclass) {\n\t\tassert(run_ind == map_bias);\n\t\tassert(run_pages == (arena_maxclass >> LG_PAGE));\n\t\tarena_chunk_dealloc(arena, chunk);\n\t}\n\n\t/*\n\t * It is okay to do dirty page processing here even if the chunk was\n\t * deallocated above, since in that case it is the spare.  Waiting\n\t * until after possible chunk deallocation to do dirty processing\n\t * allows for an old spare to be fully deallocated, thus decreasing the\n\t * chances of spuriously crossing the dirty page purging threshold.\n\t */\n\tif (dirty)\n\t\tarena_maybe_purge(arena);\n}\n\nstatic void\narena_run_trim_head(arena_t *arena, arena_chunk_t *chunk, arena_run_t *run,\n    size_t oldsize, size_t newsize)\n{\n\tsize_t pageind = ((uintptr_t)run - (uintptr_t)chunk) >> LG_PAGE;\n\tsize_t head_npages = (oldsize - newsize) >> LG_PAGE;\n\tsize_t flag_dirty = arena_mapbits_dirty_get(chunk, pageind);\n\n\tassert(oldsize > newsize);\n\n\t/*\n\t * Update the chunk map so that arena_run_dalloc() can treat the\n\t * leading run as separately allocated.  Set the last element of each\n\t * run first, in case of single-page runs.\n\t */\n\tassert(arena_mapbits_large_size_get(chunk, pageind) == oldsize);\n\tarena_mapbits_large_set(chunk, pageind+head_npages-1, 0, flag_dirty);\n\tarena_mapbits_large_set(chunk, pageind, oldsize-newsize, flag_dirty);\n\n\tif (config_debug) {\n\t\tUNUSED size_t tail_npages = newsize >> LG_PAGE;\n\t\tassert(arena_mapbits_large_size_get(chunk,\n\t\t    pageind+head_npages+tail_npages-1) == 0);\n\t\tassert(arena_mapbits_dirty_get(chunk,\n\t\t    pageind+head_npages+tail_npages-1) == flag_dirty);\n\t}\n\tarena_mapbits_large_set(chunk, pageind+head_npages, newsize,\n\t    flag_dirty);\n\n\tarena_run_dalloc(arena, run, false, false);\n}\n\nstatic void\narena_run_trim_tail(arena_t *arena, arena_chunk_t *chunk, arena_run_t *run,\n    size_t oldsize, size_t newsize, bool dirty)\n{\n\tsize_t pageind = ((uintptr_t)run - (uintptr_t)chunk) >> LG_PAGE;\n\tsize_t head_npages = newsize >> LG_PAGE;\n\tsize_t flag_dirty = arena_mapbits_dirty_get(chunk, pageind);\n\n\tassert(oldsize > newsize);\n\n\t/*\n\t * Update the chunk map so that arena_run_dalloc() can treat the\n\t * trailing run as separately allocated.  Set the last element of each\n\t * run first, in case of single-page runs.\n\t */\n\tassert(arena_mapbits_large_size_get(chunk, pageind) == oldsize);\n\tarena_mapbits_large_set(chunk, pageind+head_npages-1, 0, flag_dirty);\n\tarena_mapbits_large_set(chunk, pageind, newsize, flag_dirty);\n\n\tif (config_debug) {\n\t\tUNUSED size_t tail_npages = (oldsize - newsize) >> LG_PAGE;\n\t\tassert(arena_mapbits_large_size_get(chunk,\n\t\t    pageind+head_npages+tail_npages-1) == 0);\n\t\tassert(arena_mapbits_dirty_get(chunk,\n\t\t    pageind+head_npages+tail_npages-1) == flag_dirty);\n\t}\n\tarena_mapbits_large_set(chunk, pageind+head_npages, oldsize-newsize,\n\t    flag_dirty);\n\n\tarena_run_dalloc(arena, (arena_run_t *)((uintptr_t)run + newsize),\n\t    dirty, false);\n}\n\nstatic arena_run_t *\narena_bin_runs_first(arena_bin_t *bin)\n{\n\tarena_chunk_map_t *mapelm = arena_run_tree_first(&bin->runs);\n\tif (mapelm != NULL) {\n\t\tarena_chunk_t *chunk;\n\t\tsize_t pageind;\n\t\tarena_run_t *run;\n\n\t\tchunk = (arena_chunk_t *)CHUNK_ADDR2BASE(mapelm);\n\t\tpageind = ((((uintptr_t)mapelm - (uintptr_t)chunk->map) /\n\t\t    sizeof(arena_chunk_map_t))) + map_bias;\n\t\trun = (arena_run_t *)((uintptr_t)chunk + (uintptr_t)((pageind -\n\t\t    arena_mapbits_small_runind_get(chunk, pageind)) <<\n\t\t    LG_PAGE));\n\t\treturn (run);\n\t}\n\n\treturn (NULL);\n}\n\nstatic void\narena_bin_runs_insert(arena_bin_t *bin, arena_run_t *run)\n{\n\tarena_chunk_t *chunk = CHUNK_ADDR2BASE(run);\n\tsize_t pageind = ((uintptr_t)run - (uintptr_t)chunk) >> LG_PAGE;\n\tarena_chunk_map_t *mapelm = arena_mapp_get(chunk, pageind);\n\n\tassert(arena_run_tree_search(&bin->runs, mapelm) == NULL);\n\n\tarena_run_tree_insert(&bin->runs, mapelm);\n}\n\nstatic void\narena_bin_runs_remove(arena_bin_t *bin, arena_run_t *run)\n{\n\tarena_chunk_t *chunk = (arena_chunk_t *)CHUNK_ADDR2BASE(run);\n\tsize_t pageind = ((uintptr_t)run - (uintptr_t)chunk) >> LG_PAGE;\n\tarena_chunk_map_t *mapelm = arena_mapp_get(chunk, pageind);\n\n\tassert(arena_run_tree_search(&bin->runs, mapelm) != NULL);\n\n\tarena_run_tree_remove(&bin->runs, mapelm);\n}\n\nstatic arena_run_t *\narena_bin_nonfull_run_tryget(arena_bin_t *bin)\n{\n\tarena_run_t *run = arena_bin_runs_first(bin);\n\tif (run != NULL) {\n\t\tarena_bin_runs_remove(bin, run);\n\t\tif (config_stats)\n\t\t\tbin->stats.reruns++;\n\t}\n\treturn (run);\n}\n\nstatic arena_run_t *\narena_bin_nonfull_run_get(arena_t *arena, arena_bin_t *bin)\n{\n\tarena_run_t *run;\n\tsize_t binind;\n\tarena_bin_info_t *bin_info;\n\n\t/* Look for a usable run. */\n\trun = arena_bin_nonfull_run_tryget(bin);\n\tif (run != NULL)\n\t\treturn (run);\n\t/* No existing runs have any space available. */\n\n\tbinind = arena_bin_index(arena, bin);\n\tbin_info = &arena_bin_info[binind];\n\n\t/* Allocate a new run. */\n\tmalloc_mutex_unlock(&bin->lock);\n\t/******************************/\n\tmalloc_mutex_lock(&arena->lock);\n\trun = arena_run_alloc_small(arena, bin_info->run_size, binind);\n\tif (run != NULL) {\n\t\tbitmap_t *bitmap = (bitmap_t *)((uintptr_t)run +\n\t\t    (uintptr_t)bin_info->bitmap_offset);\n\n\t\t/* Initialize run internals. */\n\t\trun->bin = bin;\n\t\trun->nextind = 0;\n\t\trun->nfree = bin_info->nregs;\n\t\tbitmap_init(bitmap, &bin_info->bitmap_info);\n\t}\n\tmalloc_mutex_unlock(&arena->lock);\n\t/********************************/\n\tmalloc_mutex_lock(&bin->lock);\n\tif (run != NULL) {\n\t\tif (config_stats) {\n\t\t\tbin->stats.nruns++;\n\t\t\tbin->stats.curruns++;\n\t\t}\n\t\treturn (run);\n\t}\n\n\t/*\n\t * arena_run_alloc_small() failed, but another thread may have made\n\t * sufficient memory available while this one dropped bin->lock above,\n\t * so search one more time.\n\t */\n\trun = arena_bin_nonfull_run_tryget(bin);\n\tif (run != NULL)\n\t\treturn (run);\n\n\treturn (NULL);\n}\n\n/* Re-fill bin->runcur, then call arena_run_reg_alloc(). */\nstatic void *\narena_bin_malloc_hard(arena_t *arena, arena_bin_t *bin)\n{\n\tvoid *ret;\n\tsize_t binind;\n\tarena_bin_info_t *bin_info;\n\tarena_run_t *run;\n\n\tbinind = arena_bin_index(arena, bin);\n\tbin_info = &arena_bin_info[binind];\n\tbin->runcur = NULL;\n\trun = arena_bin_nonfull_run_get(arena, bin);\n\tif (bin->runcur != NULL && bin->runcur->nfree > 0) {\n\t\t/*\n\t\t * Another thread updated runcur while this one ran without the\n\t\t * bin lock in arena_bin_nonfull_run_get().\n\t\t */\n\t\tassert(bin->runcur->nfree > 0);\n\t\tret = arena_run_reg_alloc(bin->runcur, bin_info);\n\t\tif (run != NULL) {\n\t\t\tarena_chunk_t *chunk;\n\n\t\t\t/*\n\t\t\t * arena_run_alloc_small() may have allocated run, or\n\t\t\t * it may have pulled run from the bin's run tree.\n\t\t\t * Therefore it is unsafe to make any assumptions about\n\t\t\t * how run has previously been used, and\n\t\t\t * arena_bin_lower_run() must be called, as if a region\n\t\t\t * were just deallocated from the run.\n\t\t\t */\n\t\t\tchunk = (arena_chunk_t *)CHUNK_ADDR2BASE(run);\n\t\t\tif (run->nfree == bin_info->nregs)\n\t\t\t\tarena_dalloc_bin_run(arena, chunk, run, bin);\n\t\t\telse\n\t\t\t\tarena_bin_lower_run(arena, chunk, run, bin);\n\t\t}\n\t\treturn (ret);\n\t}\n\n\tif (run == NULL)\n\t\treturn (NULL);\n\n\tbin->runcur = run;\n\n\tassert(bin->runcur->nfree > 0);\n\n\treturn (arena_run_reg_alloc(bin->runcur, bin_info));\n}\n\nvoid\narena_tcache_fill_small(arena_t *arena, tcache_bin_t *tbin, size_t binind,\n    uint64_t prof_accumbytes)\n{\n\tunsigned i, nfill;\n\tarena_bin_t *bin;\n\tarena_run_t *run;\n\tvoid *ptr;\n\n\tassert(tbin->ncached == 0);\n\n\tif (config_prof && arena_prof_accum(arena, prof_accumbytes))\n\t\tprof_idump();\n\tbin = &arena->bins[binind];\n\tmalloc_mutex_lock(&bin->lock);\n\tfor (i = 0, nfill = (tcache_bin_info[binind].ncached_max >>\n\t    tbin->lg_fill_div); i < nfill; i++) {\n\t\tif ((run = bin->runcur) != NULL && run->nfree > 0)\n\t\t\tptr = arena_run_reg_alloc(run, &arena_bin_info[binind]);\n\t\telse\n\t\t\tptr = arena_bin_malloc_hard(arena, bin);\n\t\tif (ptr == NULL)\n\t\t\tbreak;\n\t\tif (config_fill && opt_junk) {\n\t\t\tarena_alloc_junk_small(ptr, &arena_bin_info[binind],\n\t\t\t    true);\n\t\t}\n\t\t/* Insert such that low regions get used first. */\n\t\ttbin->avail[nfill - 1 - i] = ptr;\n\t}\n\tif (config_stats) {\n\t\tbin->stats.allocated += i * arena_bin_info[binind].reg_size;\n\t\tbin->stats.nmalloc += i;\n\t\tbin->stats.nrequests += tbin->tstats.nrequests;\n\t\tbin->stats.nfills++;\n\t\ttbin->tstats.nrequests = 0;\n\t}\n\tmalloc_mutex_unlock(&bin->lock);\n\ttbin->ncached = i;\n}\n\nvoid\narena_alloc_junk_small(void *ptr, arena_bin_info_t *bin_info, bool zero)\n{\n\n\tif (zero) {\n\t\tsize_t redzone_size = bin_info->redzone_size;\n\t\tmemset((void *)((uintptr_t)ptr - redzone_size), 0xa5,\n\t\t    redzone_size);\n\t\tmemset((void *)((uintptr_t)ptr + bin_info->reg_size), 0xa5,\n\t\t    redzone_size);\n\t} else {\n\t\tmemset((void *)((uintptr_t)ptr - bin_info->redzone_size), 0xa5,\n\t\t    bin_info->reg_interval);\n\t}\n}\n\n#ifdef JEMALLOC_JET\n#undef arena_redzone_corruption\n#define\tarena_redzone_corruption JEMALLOC_N(arena_redzone_corruption_impl)\n#endif\nstatic void\narena_redzone_corruption(void *ptr, size_t usize, bool after,\n    size_t offset, uint8_t byte)\n{\n\n\tmalloc_printf(\"<jemalloc>: Corrupt redzone %zu byte%s %s %p \"\n\t    \"(size %zu), byte=%#x\\n\", offset, (offset == 1) ? \"\" : \"s\",\n\t    after ? \"after\" : \"before\", ptr, usize, byte);\n}\n#ifdef JEMALLOC_JET\n#undef arena_redzone_corruption\n#define\tarena_redzone_corruption JEMALLOC_N(arena_redzone_corruption)\narena_redzone_corruption_t *arena_redzone_corruption =\n    JEMALLOC_N(arena_redzone_corruption_impl);\n#endif\n\nstatic void\narena_redzones_validate(void *ptr, arena_bin_info_t *bin_info, bool reset)\n{\n\tsize_t size = bin_info->reg_size;\n\tsize_t redzone_size = bin_info->redzone_size;\n\tsize_t i;\n\tbool error = false;\n\n\tfor (i = 1; i <= redzone_size; i++) {\n\t\tuint8_t *byte = (uint8_t *)((uintptr_t)ptr - i);\n\t\tif (*byte != 0xa5) {\n\t\t\terror = true;\n\t\t\tarena_redzone_corruption(ptr, size, false, i, *byte);\n\t\t\tif (reset)\n\t\t\t\t*byte = 0xa5;\n\t\t}\n\t}\n\tfor (i = 0; i < redzone_size; i++) {\n\t\tuint8_t *byte = (uint8_t *)((uintptr_t)ptr + size + i);\n\t\tif (*byte != 0xa5) {\n\t\t\terror = true;\n\t\t\tarena_redzone_corruption(ptr, size, true, i, *byte);\n\t\t\tif (reset)\n\t\t\t\t*byte = 0xa5;\n\t\t}\n\t}\n\tif (opt_abort && error)\n\t\tabort();\n}\n\n#ifdef JEMALLOC_JET\n#undef arena_dalloc_junk_small\n#define\tarena_dalloc_junk_small JEMALLOC_N(arena_dalloc_junk_small_impl)\n#endif\nvoid\narena_dalloc_junk_small(void *ptr, arena_bin_info_t *bin_info)\n{\n\tsize_t redzone_size = bin_info->redzone_size;\n\n\tarena_redzones_validate(ptr, bin_info, false);\n\tmemset((void *)((uintptr_t)ptr - redzone_size), 0x5a,\n\t    bin_info->reg_interval);\n}\n#ifdef JEMALLOC_JET\n#undef arena_dalloc_junk_small\n#define\tarena_dalloc_junk_small JEMALLOC_N(arena_dalloc_junk_small)\narena_dalloc_junk_small_t *arena_dalloc_junk_small =\n    JEMALLOC_N(arena_dalloc_junk_small_impl);\n#endif\n\nvoid\narena_quarantine_junk_small(void *ptr, size_t usize)\n{\n\tsize_t binind;\n\tarena_bin_info_t *bin_info;\n\tcassert(config_fill);\n\tassert(opt_junk);\n\tassert(opt_quarantine);\n\tassert(usize <= SMALL_MAXCLASS);\n\n\tbinind = SMALL_SIZE2BIN(usize);\n\tbin_info = &arena_bin_info[binind];\n\tarena_redzones_validate(ptr, bin_info, true);\n}\n\nvoid *\narena_malloc_small(arena_t *arena, size_t size, bool zero)\n{\n\tvoid *ret;\n\tarena_bin_t *bin;\n\tarena_run_t *run;\n\tsize_t binind;\n\n\tbinind = SMALL_SIZE2BIN(size);\n\tassert(binind < NBINS);\n\tbin = &arena->bins[binind];\n\tsize = arena_bin_info[binind].reg_size;\n\n\tmalloc_mutex_lock(&bin->lock);\n\tif ((run = bin->runcur) != NULL && run->nfree > 0)\n\t\tret = arena_run_reg_alloc(run, &arena_bin_info[binind]);\n\telse\n\t\tret = arena_bin_malloc_hard(arena, bin);\n\n\tif (ret == NULL) {\n\t\tmalloc_mutex_unlock(&bin->lock);\n\t\treturn (NULL);\n\t}\n\n\tif (config_stats) {\n\t\tbin->stats.allocated += size;\n\t\tbin->stats.nmalloc++;\n\t\tbin->stats.nrequests++;\n\t}\n\tmalloc_mutex_unlock(&bin->lock);\n\tif (config_prof && isthreaded == false && arena_prof_accum(arena, size))\n\t\tprof_idump();\n\n\tif (zero == false) {\n\t\tif (config_fill) {\n\t\t\tif (opt_junk) {\n\t\t\t\tarena_alloc_junk_small(ret,\n\t\t\t\t    &arena_bin_info[binind], false);\n\t\t\t} else if (opt_zero)\n\t\t\t\tmemset(ret, 0, size);\n\t\t}\n\t\tVALGRIND_MAKE_MEM_UNDEFINED(ret, size);\n\t} else {\n\t\tif (config_fill && opt_junk) {\n\t\t\tarena_alloc_junk_small(ret, &arena_bin_info[binind],\n\t\t\t    true);\n\t\t}\n\t\tVALGRIND_MAKE_MEM_UNDEFINED(ret, size);\n\t\tmemset(ret, 0, size);\n\t}\n\n\treturn (ret);\n}\n\nvoid *\narena_malloc_large(arena_t *arena, size_t size, bool zero)\n{\n\tvoid *ret;\n\tUNUSED bool idump;\n\n\t/* Large allocation. */\n\tsize = PAGE_CEILING(size);\n\tmalloc_mutex_lock(&arena->lock);\n\tret = (void *)arena_run_alloc_large(arena, size, zero);\n\tif (ret == NULL) {\n\t\tmalloc_mutex_unlock(&arena->lock);\n\t\treturn (NULL);\n\t}\n\tif (config_stats) {\n\t\tarena->stats.nmalloc_large++;\n\t\tarena->stats.nrequests_large++;\n\t\tarena->stats.allocated_large += size;\n\t\tarena->stats.lstats[(size >> LG_PAGE) - 1].nmalloc++;\n\t\tarena->stats.lstats[(size >> LG_PAGE) - 1].nrequests++;\n\t\tarena->stats.lstats[(size >> LG_PAGE) - 1].curruns++;\n\t}\n\tif (config_prof)\n\t\tidump = arena_prof_accum_locked(arena, size);\n\tmalloc_mutex_unlock(&arena->lock);\n\tif (config_prof && idump)\n\t\tprof_idump();\n\n\tif (zero == false) {\n\t\tif (config_fill) {\n\t\t\tif (opt_junk)\n\t\t\t\tmemset(ret, 0xa5, size);\n\t\t\telse if (opt_zero)\n\t\t\t\tmemset(ret, 0, size);\n\t\t}\n\t}\n\n\treturn (ret);\n}\n\n/* Only handles large allocations that require more than page alignment. */\nvoid *\narena_palloc(arena_t *arena, size_t size, size_t alignment, bool zero)\n{\n\tvoid *ret;\n\tsize_t alloc_size, leadsize, trailsize;\n\tarena_run_t *run;\n\tarena_chunk_t *chunk;\n\n\tassert((size & PAGE_MASK) == 0);\n\n\talignment = PAGE_CEILING(alignment);\n\talloc_size = size + alignment - PAGE;\n\n\tmalloc_mutex_lock(&arena->lock);\n\trun = arena_run_alloc_large(arena, alloc_size, false);\n\tif (run == NULL) {\n\t\tmalloc_mutex_unlock(&arena->lock);\n\t\treturn (NULL);\n\t}\n\tchunk = (arena_chunk_t *)CHUNK_ADDR2BASE(run);\n\n\tleadsize = ALIGNMENT_CEILING((uintptr_t)run, alignment) -\n\t    (uintptr_t)run;\n\tassert(alloc_size >= leadsize + size);\n\ttrailsize = alloc_size - leadsize - size;\n\tret = (void *)((uintptr_t)run + leadsize);\n\tif (leadsize != 0) {\n\t\tarena_run_trim_head(arena, chunk, run, alloc_size, alloc_size -\n\t\t    leadsize);\n\t}\n\tif (trailsize != 0) {\n\t\tarena_run_trim_tail(arena, chunk, ret, size + trailsize, size,\n\t\t    false);\n\t}\n\tarena_run_init_large(arena, (arena_run_t *)ret, size, zero);\n\n\tif (config_stats) {\n\t\tarena->stats.nmalloc_large++;\n\t\tarena->stats.nrequests_large++;\n\t\tarena->stats.allocated_large += size;\n\t\tarena->stats.lstats[(size >> LG_PAGE) - 1].nmalloc++;\n\t\tarena->stats.lstats[(size >> LG_PAGE) - 1].nrequests++;\n\t\tarena->stats.lstats[(size >> LG_PAGE) - 1].curruns++;\n\t}\n\tmalloc_mutex_unlock(&arena->lock);\n\n\tif (config_fill && zero == false) {\n\t\tif (opt_junk)\n\t\t\tmemset(ret, 0xa5, size);\n\t\telse if (opt_zero)\n\t\t\tmemset(ret, 0, size);\n\t}\n\treturn (ret);\n}\n\nvoid\narena_prof_promoted(const void *ptr, size_t size)\n{\n\tarena_chunk_t *chunk;\n\tsize_t pageind, binind;\n\n\tcassert(config_prof);\n\tassert(ptr != NULL);\n\tassert(CHUNK_ADDR2BASE(ptr) != ptr);\n\tassert(isalloc(ptr, false) == PAGE);\n\tassert(isalloc(ptr, true) == PAGE);\n\tassert(size <= SMALL_MAXCLASS);\n\n\tchunk = (arena_chunk_t *)CHUNK_ADDR2BASE(ptr);\n\tpageind = ((uintptr_t)ptr - (uintptr_t)chunk) >> LG_PAGE;\n\tbinind = SMALL_SIZE2BIN(size);\n\tassert(binind < NBINS);\n\tarena_mapbits_large_binind_set(chunk, pageind, binind);\n\n\tassert(isalloc(ptr, false) == PAGE);\n\tassert(isalloc(ptr, true) == size);\n}\n\nstatic void\narena_dissociate_bin_run(arena_chunk_t *chunk, arena_run_t *run,\n    arena_bin_t *bin)\n{\n\n\t/* Dissociate run from bin. */\n\tif (run == bin->runcur)\n\t\tbin->runcur = NULL;\n\telse {\n\t\tsize_t binind = arena_bin_index(chunk->arena, bin);\n\t\tarena_bin_info_t *bin_info = &arena_bin_info[binind];\n\n\t\tif (bin_info->nregs != 1) {\n\t\t\t/*\n\t\t\t * This block's conditional is necessary because if the\n\t\t\t * run only contains one region, then it never gets\n\t\t\t * inserted into the non-full runs tree.\n\t\t\t */\n\t\t\tarena_bin_runs_remove(bin, run);\n\t\t}\n\t}\n}\n\nstatic void\narena_dalloc_bin_run(arena_t *arena, arena_chunk_t *chunk, arena_run_t *run,\n    arena_bin_t *bin)\n{\n\tsize_t binind;\n\tarena_bin_info_t *bin_info;\n\tsize_t npages, run_ind, past;\n\n\tassert(run != bin->runcur);\n\tassert(arena_run_tree_search(&bin->runs,\n\t    arena_mapp_get(chunk, ((uintptr_t)run-(uintptr_t)chunk)>>LG_PAGE))\n\t    == NULL);\n\n\tbinind = arena_bin_index(chunk->arena, run->bin);\n\tbin_info = &arena_bin_info[binind];\n\n\tmalloc_mutex_unlock(&bin->lock);\n\t/******************************/\n\tnpages = bin_info->run_size >> LG_PAGE;\n\trun_ind = (size_t)(((uintptr_t)run - (uintptr_t)chunk) >> LG_PAGE);\n\tpast = (size_t)(PAGE_CEILING((uintptr_t)run +\n\t    (uintptr_t)bin_info->reg0_offset + (uintptr_t)(run->nextind *\n\t    bin_info->reg_interval - bin_info->redzone_size) -\n\t    (uintptr_t)chunk) >> LG_PAGE);\n\tmalloc_mutex_lock(&arena->lock);\n\n\t/*\n\t * If the run was originally clean, and some pages were never touched,\n\t * trim the clean pages before deallocating the dirty portion of the\n\t * run.\n\t */\n\tassert(arena_mapbits_dirty_get(chunk, run_ind) ==\n\t    arena_mapbits_dirty_get(chunk, run_ind+npages-1));\n\tif (arena_mapbits_dirty_get(chunk, run_ind) == 0 && past - run_ind <\n\t    npages) {\n\t\t/* Trim clean pages.  Convert to large run beforehand. */\n\t\tassert(npages > 0);\n\t\tarena_mapbits_large_set(chunk, run_ind, bin_info->run_size, 0);\n\t\tarena_mapbits_large_set(chunk, run_ind+npages-1, 0, 0);\n\t\tarena_run_trim_tail(arena, chunk, run, (npages << LG_PAGE),\n\t\t    ((past - run_ind) << LG_PAGE), false);\n\t\t/* npages = past - run_ind; */\n\t}\n\tarena_run_dalloc(arena, run, true, false);\n\tmalloc_mutex_unlock(&arena->lock);\n\t/****************************/\n\tmalloc_mutex_lock(&bin->lock);\n\tif (config_stats)\n\t\tbin->stats.curruns--;\n}\n\nstatic void\narena_bin_lower_run(arena_t *arena, arena_chunk_t *chunk, arena_run_t *run,\n    arena_bin_t *bin)\n{\n\n\t/*\n\t * Make sure that if bin->runcur is non-NULL, it refers to the lowest\n\t * non-full run.  It is okay to NULL runcur out rather than proactively\n\t * keeping it pointing at the lowest non-full run.\n\t */\n\tif ((uintptr_t)run < (uintptr_t)bin->runcur) {\n\t\t/* Switch runcur. */\n\t\tif (bin->runcur->nfree > 0)\n\t\t\tarena_bin_runs_insert(bin, bin->runcur);\n\t\tbin->runcur = run;\n\t\tif (config_stats)\n\t\t\tbin->stats.reruns++;\n\t} else\n\t\tarena_bin_runs_insert(bin, run);\n}\n\nvoid\narena_dalloc_bin_locked(arena_t *arena, arena_chunk_t *chunk, void *ptr,\n    arena_chunk_map_t *mapelm)\n{\n\tsize_t pageind;\n\tarena_run_t *run;\n\tarena_bin_t *bin;\n\tarena_bin_info_t *bin_info;\n\tsize_t size, binind;\n\n\tpageind = ((uintptr_t)ptr - (uintptr_t)chunk) >> LG_PAGE;\n\trun = (arena_run_t *)((uintptr_t)chunk + (uintptr_t)((pageind -\n\t    arena_mapbits_small_runind_get(chunk, pageind)) << LG_PAGE));\n\tbin = run->bin;\n\tbinind = arena_ptr_small_binind_get(ptr, mapelm->bits);\n\tbin_info = &arena_bin_info[binind];\n\tif (config_fill || config_stats)\n\t\tsize = bin_info->reg_size;\n\n\tif (config_fill && opt_junk)\n\t\tarena_dalloc_junk_small(ptr, bin_info);\n\n\tarena_run_reg_dalloc(run, ptr);\n\tif (run->nfree == bin_info->nregs) {\n\t\tarena_dissociate_bin_run(chunk, run, bin);\n\t\tarena_dalloc_bin_run(arena, chunk, run, bin);\n\t} else if (run->nfree == 1 && run != bin->runcur)\n\t\tarena_bin_lower_run(arena, chunk, run, bin);\n\n\tif (config_stats) {\n\t\tbin->stats.allocated -= size;\n\t\tbin->stats.ndalloc++;\n\t}\n}\n\nvoid\narena_dalloc_bin(arena_t *arena, arena_chunk_t *chunk, void *ptr,\n    size_t pageind, arena_chunk_map_t *mapelm)\n{\n\tarena_run_t *run;\n\tarena_bin_t *bin;\n\n\trun = (arena_run_t *)((uintptr_t)chunk + (uintptr_t)((pageind -\n\t    arena_mapbits_small_runind_get(chunk, pageind)) << LG_PAGE));\n\tbin = run->bin;\n\tmalloc_mutex_lock(&bin->lock);\n\tarena_dalloc_bin_locked(arena, chunk, ptr, mapelm);\n\tmalloc_mutex_unlock(&bin->lock);\n}\n\nvoid\narena_dalloc_small(arena_t *arena, arena_chunk_t *chunk, void *ptr,\n    size_t pageind)\n{\n\tarena_chunk_map_t *mapelm;\n\n\tif (config_debug) {\n\t\t/* arena_ptr_small_binind_get() does extra sanity checking. */\n\t\tassert(arena_ptr_small_binind_get(ptr, arena_mapbits_get(chunk,\n\t\t    pageind)) != BININD_INVALID);\n\t}\n\tmapelm = arena_mapp_get(chunk, pageind);\n\tarena_dalloc_bin(arena, chunk, ptr, pageind, mapelm);\n}\n\n#ifdef JEMALLOC_JET\n#undef arena_dalloc_junk_large\n#define\tarena_dalloc_junk_large JEMALLOC_N(arena_dalloc_junk_large_impl)\n#endif\nstatic void\narena_dalloc_junk_large(void *ptr, size_t usize)\n{\n\n\tif (config_fill && opt_junk)\n\t\tmemset(ptr, 0x5a, usize);\n}\n#ifdef JEMALLOC_JET\n#undef arena_dalloc_junk_large\n#define\tarena_dalloc_junk_large JEMALLOC_N(arena_dalloc_junk_large)\narena_dalloc_junk_large_t *arena_dalloc_junk_large =\n    JEMALLOC_N(arena_dalloc_junk_large_impl);\n#endif\n\nvoid\narena_dalloc_large_locked(arena_t *arena, arena_chunk_t *chunk, void *ptr)\n{\n\n\tif (config_fill || config_stats) {\n\t\tsize_t pageind = ((uintptr_t)ptr - (uintptr_t)chunk) >> LG_PAGE;\n\t\tsize_t usize = arena_mapbits_large_size_get(chunk, pageind);\n\n\t\tarena_dalloc_junk_large(ptr, usize);\n\t\tif (config_stats) {\n\t\t\tarena->stats.ndalloc_large++;\n\t\t\tarena->stats.allocated_large -= usize;\n\t\t\tarena->stats.lstats[(usize >> LG_PAGE) - 1].ndalloc++;\n\t\t\tarena->stats.lstats[(usize >> LG_PAGE) - 1].curruns--;\n\t\t}\n\t}\n\n\tarena_run_dalloc(arena, (arena_run_t *)ptr, true, false);\n}\n\nvoid\narena_dalloc_large(arena_t *arena, arena_chunk_t *chunk, void *ptr)\n{\n\n\tmalloc_mutex_lock(&arena->lock);\n\tarena_dalloc_large_locked(arena, chunk, ptr);\n\tmalloc_mutex_unlock(&arena->lock);\n}\n\nstatic void\narena_ralloc_large_shrink(arena_t *arena, arena_chunk_t *chunk, void *ptr,\n    size_t oldsize, size_t size)\n{\n\n\tassert(size < oldsize);\n\n\t/*\n\t * Shrink the run, and make trailing pages available for other\n\t * allocations.\n\t */\n\tmalloc_mutex_lock(&arena->lock);\n\tarena_run_trim_tail(arena, chunk, (arena_run_t *)ptr, oldsize, size,\n\t    true);\n\tif (config_stats) {\n\t\tarena->stats.ndalloc_large++;\n\t\tarena->stats.allocated_large -= oldsize;\n\t\tarena->stats.lstats[(oldsize >> LG_PAGE) - 1].ndalloc++;\n\t\tarena->stats.lstats[(oldsize >> LG_PAGE) - 1].curruns--;\n\n\t\tarena->stats.nmalloc_large++;\n\t\tarena->stats.nrequests_large++;\n\t\tarena->stats.allocated_large += size;\n\t\tarena->stats.lstats[(size >> LG_PAGE) - 1].nmalloc++;\n\t\tarena->stats.lstats[(size >> LG_PAGE) - 1].nrequests++;\n\t\tarena->stats.lstats[(size >> LG_PAGE) - 1].curruns++;\n\t}\n\tmalloc_mutex_unlock(&arena->lock);\n}\n\nstatic bool\narena_ralloc_large_grow(arena_t *arena, arena_chunk_t *chunk, void *ptr,\n    size_t oldsize, size_t size, size_t extra, bool zero)\n{\n\tsize_t pageind = ((uintptr_t)ptr - (uintptr_t)chunk) >> LG_PAGE;\n\tsize_t npages = oldsize >> LG_PAGE;\n\tsize_t followsize;\n\n\tassert(oldsize == arena_mapbits_large_size_get(chunk, pageind));\n\n\t/* Try to extend the run. */\n\tassert(size + extra > oldsize);\n\tmalloc_mutex_lock(&arena->lock);\n\tif (pageind + npages < chunk_npages &&\n\t    arena_mapbits_allocated_get(chunk, pageind+npages) == 0 &&\n\t    (followsize = arena_mapbits_unallocated_size_get(chunk,\n\t    pageind+npages)) >= size - oldsize) {\n\t\t/*\n\t\t * The next run is available and sufficiently large.  Split the\n\t\t * following run, then merge the first part with the existing\n\t\t * allocation.\n\t\t */\n\t\tsize_t flag_dirty;\n\t\tsize_t splitsize = (oldsize + followsize <= size + extra)\n\t\t    ? followsize : size + extra - oldsize;\n\t\tarena_run_split_large(arena, (arena_run_t *)((uintptr_t)chunk +\n\t\t    ((pageind+npages) << LG_PAGE)), splitsize, zero);\n\n\t\tsize = oldsize + splitsize;\n\t\tnpages = size >> LG_PAGE;\n\n\t\t/*\n\t\t * Mark the extended run as dirty if either portion of the run\n\t\t * was dirty before allocation.  This is rather pedantic,\n\t\t * because there's not actually any sequence of events that\n\t\t * could cause the resulting run to be passed to\n\t\t * arena_run_dalloc() with the dirty argument set to false\n\t\t * (which is when dirty flag consistency would really matter).\n\t\t */\n\t\tflag_dirty = arena_mapbits_dirty_get(chunk, pageind) |\n\t\t    arena_mapbits_dirty_get(chunk, pageind+npages-1);\n\t\tarena_mapbits_large_set(chunk, pageind, size, flag_dirty);\n\t\tarena_mapbits_large_set(chunk, pageind+npages-1, 0, flag_dirty);\n\n\t\tif (config_stats) {\n\t\t\tarena->stats.ndalloc_large++;\n\t\t\tarena->stats.allocated_large -= oldsize;\n\t\t\tarena->stats.lstats[(oldsize >> LG_PAGE) - 1].ndalloc++;\n\t\t\tarena->stats.lstats[(oldsize >> LG_PAGE) - 1].curruns--;\n\n\t\t\tarena->stats.nmalloc_large++;\n\t\t\tarena->stats.nrequests_large++;\n\t\t\tarena->stats.allocated_large += size;\n\t\t\tarena->stats.lstats[(size >> LG_PAGE) - 1].nmalloc++;\n\t\t\tarena->stats.lstats[(size >> LG_PAGE) - 1].nrequests++;\n\t\t\tarena->stats.lstats[(size >> LG_PAGE) - 1].curruns++;\n\t\t}\n\t\tmalloc_mutex_unlock(&arena->lock);\n\t\treturn (false);\n\t}\n\tmalloc_mutex_unlock(&arena->lock);\n\n\treturn (true);\n}\n\n#ifdef JEMALLOC_JET\n#undef arena_ralloc_junk_large\n#define\tarena_ralloc_junk_large JEMALLOC_N(arena_ralloc_junk_large_impl)\n#endif\nstatic void\narena_ralloc_junk_large(void *ptr, size_t old_usize, size_t usize)\n{\n\n\tif (config_fill && opt_junk) {\n\t\tmemset((void *)((uintptr_t)ptr + usize), 0x5a,\n\t\t    old_usize - usize);\n\t}\n}\n#ifdef JEMALLOC_JET\n#undef arena_ralloc_junk_large\n#define\tarena_ralloc_junk_large JEMALLOC_N(arena_ralloc_junk_large)\narena_ralloc_junk_large_t *arena_ralloc_junk_large =\n    JEMALLOC_N(arena_ralloc_junk_large_impl);\n#endif\n\n/*\n * Try to resize a large allocation, in order to avoid copying.  This will\n * always fail if growing an object, and the following run is already in use.\n */\nstatic bool\narena_ralloc_large(void *ptr, size_t oldsize, size_t size, size_t extra,\n    bool zero)\n{\n\tsize_t psize;\n\n\tpsize = PAGE_CEILING(size + extra);\n\tif (psize == oldsize) {\n\t\t/* Same size class. */\n\t\treturn (false);\n\t} else {\n\t\tarena_chunk_t *chunk;\n\t\tarena_t *arena;\n\n\t\tchunk = (arena_chunk_t *)CHUNK_ADDR2BASE(ptr);\n\t\tarena = chunk->arena;\n\n\t\tif (psize < oldsize) {\n\t\t\t/* Fill before shrinking in order avoid a race. */\n\t\t\tarena_ralloc_junk_large(ptr, oldsize, psize);\n\t\t\tarena_ralloc_large_shrink(arena, chunk, ptr, oldsize,\n\t\t\t    psize);\n\t\t\treturn (false);\n\t\t} else {\n\t\t\tbool ret = arena_ralloc_large_grow(arena, chunk, ptr,\n\t\t\t    oldsize, PAGE_CEILING(size),\n\t\t\t    psize - PAGE_CEILING(size), zero);\n\t\t\tif (config_fill && ret == false && zero == false) {\n\t\t\t\tif (opt_junk) {\n\t\t\t\t\tmemset((void *)((uintptr_t)ptr +\n\t\t\t\t\t    oldsize), 0xa5, isalloc(ptr,\n\t\t\t\t\t    config_prof) - oldsize);\n\t\t\t\t} else if (opt_zero) {\n\t\t\t\t\tmemset((void *)((uintptr_t)ptr +\n\t\t\t\t\t    oldsize), 0, isalloc(ptr,\n\t\t\t\t\t    config_prof) - oldsize);\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn (ret);\n\t\t}\n\t}\n}\n\nbool\narena_ralloc_no_move(void *ptr, size_t oldsize, size_t size, size_t extra,\n    bool zero)\n{\n\n\t/*\n\t * Avoid moving the allocation if the size class can be left the same.\n\t */\n\tif (oldsize <= arena_maxclass) {\n\t\tif (oldsize <= SMALL_MAXCLASS) {\n\t\t\tassert(arena_bin_info[SMALL_SIZE2BIN(oldsize)].reg_size\n\t\t\t    == oldsize);\n\t\t\tif ((size + extra <= SMALL_MAXCLASS &&\n\t\t\t    SMALL_SIZE2BIN(size + extra) ==\n\t\t\t    SMALL_SIZE2BIN(oldsize)) || (size <= oldsize &&\n\t\t\t    size + extra >= oldsize))\n\t\t\t\treturn (false);\n\t\t} else {\n\t\t\tassert(size <= arena_maxclass);\n\t\t\tif (size + extra > SMALL_MAXCLASS) {\n\t\t\t\tif (arena_ralloc_large(ptr, oldsize, size,\n\t\t\t\t    extra, zero) == false)\n\t\t\t\t\treturn (false);\n\t\t\t}\n\t\t}\n\t}\n\n\t/* Reallocation would require a move. */\n\treturn (true);\n}\n\nvoid *\narena_ralloc(arena_t *arena, void *ptr, size_t oldsize, size_t size,\n    size_t extra, size_t alignment, bool zero, bool try_tcache_alloc,\n    bool try_tcache_dalloc)\n{\n\tvoid *ret;\n\tsize_t copysize;\n\n\t/* Try to avoid moving the allocation. */\n\tif (arena_ralloc_no_move(ptr, oldsize, size, extra, zero) == false)\n\t\treturn (ptr);\n\n\t/*\n\t * size and oldsize are different enough that we need to move the\n\t * object.  In that case, fall back to allocating new space and\n\t * copying.\n\t */\n\tif (alignment != 0) {\n\t\tsize_t usize = sa2u(size + extra, alignment);\n\t\tif (usize == 0)\n\t\t\treturn (NULL);\n\t\tret = ipalloct(usize, alignment, zero, try_tcache_alloc, arena);\n\t} else\n\t\tret = arena_malloc(arena, size + extra, zero, try_tcache_alloc);\n\n\tif (ret == NULL) {\n\t\tif (extra == 0)\n\t\t\treturn (NULL);\n\t\t/* Try again, this time without extra. */\n\t\tif (alignment != 0) {\n\t\t\tsize_t usize = sa2u(size, alignment);\n\t\t\tif (usize == 0)\n\t\t\t\treturn (NULL);\n\t\t\tret = ipalloct(usize, alignment, zero, try_tcache_alloc,\n\t\t\t    arena);\n\t\t} else\n\t\t\tret = arena_malloc(arena, size, zero, try_tcache_alloc);\n\n\t\tif (ret == NULL)\n\t\t\treturn (NULL);\n\t}\n\n\t/* Junk/zero-filling were already done by ipalloc()/arena_malloc(). */\n\n\t/*\n\t * Copy at most size bytes (not size+extra), since the caller has no\n\t * expectation that the extra bytes will be reliably preserved.\n\t */\n\tcopysize = (size < oldsize) ? size : oldsize;\n\tVALGRIND_MAKE_MEM_UNDEFINED(ret, copysize);\n\tmemcpy(ret, ptr, copysize);\n\tiqalloct(ptr, try_tcache_dalloc);\n\treturn (ret);\n}\n\ndss_prec_t\narena_dss_prec_get(arena_t *arena)\n{\n\tdss_prec_t ret;\n\n\tmalloc_mutex_lock(&arena->lock);\n\tret = arena->dss_prec;\n\tmalloc_mutex_unlock(&arena->lock);\n\treturn (ret);\n}\n\nvoid\narena_dss_prec_set(arena_t *arena, dss_prec_t dss_prec)\n{\n\n\tmalloc_mutex_lock(&arena->lock);\n\tarena->dss_prec = dss_prec;\n\tmalloc_mutex_unlock(&arena->lock);\n}\n\nvoid\narena_stats_merge(arena_t *arena, const char **dss, size_t *nactive,\n    size_t *ndirty, arena_stats_t *astats, malloc_bin_stats_t *bstats,\n    malloc_large_stats_t *lstats)\n{\n\tunsigned i;\n\n\tmalloc_mutex_lock(&arena->lock);\n\t*dss = dss_prec_names[arena->dss_prec];\n\t*nactive += arena->nactive;\n\t*ndirty += arena->ndirty;\n\n\tastats->mapped += arena->stats.mapped;\n\tastats->npurge += arena->stats.npurge;\n\tastats->nmadvise += arena->stats.nmadvise;\n\tastats->purged += arena->stats.purged;\n\tastats->allocated_large += arena->stats.allocated_large;\n\tastats->nmalloc_large += arena->stats.nmalloc_large;\n\tastats->ndalloc_large += arena->stats.ndalloc_large;\n\tastats->nrequests_large += arena->stats.nrequests_large;\n\n\tfor (i = 0; i < nlclasses; i++) {\n\t\tlstats[i].nmalloc += arena->stats.lstats[i].nmalloc;\n\t\tlstats[i].ndalloc += arena->stats.lstats[i].ndalloc;\n\t\tlstats[i].nrequests += arena->stats.lstats[i].nrequests;\n\t\tlstats[i].curruns += arena->stats.lstats[i].curruns;\n\t}\n\tmalloc_mutex_unlock(&arena->lock);\n\n\tfor (i = 0; i < NBINS; i++) {\n\t\tarena_bin_t *bin = &arena->bins[i];\n\n\t\tmalloc_mutex_lock(&bin->lock);\n\t\tbstats[i].allocated += bin->stats.allocated;\n\t\tbstats[i].nmalloc += bin->stats.nmalloc;\n\t\tbstats[i].ndalloc += bin->stats.ndalloc;\n\t\tbstats[i].nrequests += bin->stats.nrequests;\n\t\tif (config_tcache) {\n\t\t\tbstats[i].nfills += bin->stats.nfills;\n\t\t\tbstats[i].nflushes += bin->stats.nflushes;\n\t\t}\n\t\tbstats[i].nruns += bin->stats.nruns;\n\t\tbstats[i].reruns += bin->stats.reruns;\n\t\tbstats[i].curruns += bin->stats.curruns;\n\t\tmalloc_mutex_unlock(&bin->lock);\n\t}\n}\n\nbool\narena_new(arena_t *arena, unsigned ind)\n{\n\tunsigned i;\n\tarena_bin_t *bin;\n\n\tarena->ind = ind;\n\tarena->nthreads = 0;\n\n\tif (malloc_mutex_init(&arena->lock))\n\t\treturn (true);\n\n\tif (config_stats) {\n\t\tmemset(&arena->stats, 0, sizeof(arena_stats_t));\n\t\tarena->stats.lstats =\n\t\t    (malloc_large_stats_t *)base_alloc(nlclasses *\n\t\t    sizeof(malloc_large_stats_t));\n\t\tif (arena->stats.lstats == NULL)\n\t\t\treturn (true);\n\t\tmemset(arena->stats.lstats, 0, nlclasses *\n\t\t    sizeof(malloc_large_stats_t));\n\t\tif (config_tcache)\n\t\t\tql_new(&arena->tcache_ql);\n\t}\n\n\tif (config_prof)\n\t\tarena->prof_accumbytes = 0;\n\n\tarena->dss_prec = chunk_dss_prec_get();\n\n\t/* Initialize chunks. */\n\tarena_chunk_dirty_new(&arena->chunks_dirty);\n\tarena->spare = NULL;\n\n\tarena->nactive = 0;\n\tarena->ndirty = 0;\n\tarena->npurgatory = 0;\n\n\tarena_avail_tree_new(&arena->runs_avail);\n\n\t/* Initialize bins. */\n\tfor (i = 0; i < NBINS; i++) {\n\t\tbin = &arena->bins[i];\n\t\tif (malloc_mutex_init(&bin->lock))\n\t\t\treturn (true);\n\t\tbin->runcur = NULL;\n\t\tarena_run_tree_new(&bin->runs);\n\t\tif (config_stats)\n\t\t\tmemset(&bin->stats, 0, sizeof(malloc_bin_stats_t));\n\t}\n\n\treturn (false);\n}\n\n/*\n * Calculate bin_info->run_size such that it meets the following constraints:\n *\n *   *) bin_info->run_size >= min_run_size\n *   *) bin_info->run_size <= arena_maxclass\n *   *) run header overhead <= RUN_MAX_OVRHD (or header overhead relaxed).\n *   *) bin_info->nregs <= RUN_MAXREGS\n *\n * bin_info->nregs, bin_info->bitmap_offset, and bin_info->reg0_offset are also\n * calculated here, since these settings are all interdependent.\n */\nstatic size_t\nbin_info_run_size_calc(arena_bin_info_t *bin_info, size_t min_run_size)\n{\n\tsize_t pad_size;\n\tsize_t try_run_size, good_run_size;\n\tuint32_t try_nregs, good_nregs;\n\tuint32_t try_hdr_size, good_hdr_size;\n\tuint32_t try_bitmap_offset, good_bitmap_offset;\n\tuint32_t try_ctx0_offset, good_ctx0_offset;\n\tuint32_t try_redzone0_offset, good_redzone0_offset;\n\n\tassert(min_run_size >= PAGE);\n\tassert(min_run_size <= arena_maxclass);\n\n\t/*\n\t * Determine redzone size based on minimum alignment and minimum\n\t * redzone size.  Add padding to the end of the run if it is needed to\n\t * align the regions.  The padding allows each redzone to be half the\n\t * minimum alignment; without the padding, each redzone would have to\n\t * be twice as large in order to maintain alignment.\n\t */\n\tif (config_fill && opt_redzone) {\n\t\tsize_t align_min = ZU(1) << (ffs(bin_info->reg_size) - 1);\n\t\tif (align_min <= REDZONE_MINSIZE) {\n\t\t\tbin_info->redzone_size = REDZONE_MINSIZE;\n\t\t\tpad_size = 0;\n\t\t} else {\n\t\t\tbin_info->redzone_size = align_min >> 1;\n\t\t\tpad_size = bin_info->redzone_size;\n\t\t}\n\t} else {\n\t\tbin_info->redzone_size = 0;\n\t\tpad_size = 0;\n\t}\n\tbin_info->reg_interval = bin_info->reg_size +\n\t    (bin_info->redzone_size << 1);\n\n\t/*\n\t * Calculate known-valid settings before entering the run_size\n\t * expansion loop, so that the first part of the loop always copies\n\t * valid settings.\n\t *\n\t * The do..while loop iteratively reduces the number of regions until\n\t * the run header and the regions no longer overlap.  A closed formula\n\t * would be quite messy, since there is an interdependency between the\n\t * header's mask length and the number of regions.\n\t */\n\ttry_run_size = min_run_size;\n\ttry_nregs = ((try_run_size - sizeof(arena_run_t)) /\n\t    bin_info->reg_interval)\n\t    + 1; /* Counter-act try_nregs-- in loop. */\n\tif (try_nregs > RUN_MAXREGS) {\n\t\ttry_nregs = RUN_MAXREGS\n\t\t    + 1; /* Counter-act try_nregs-- in loop. */\n\t}\n\tdo {\n\t\ttry_nregs--;\n\t\ttry_hdr_size = sizeof(arena_run_t);\n\t\t/* Pad to a long boundary. */\n\t\ttry_hdr_size = LONG_CEILING(try_hdr_size);\n\t\ttry_bitmap_offset = try_hdr_size;\n\t\t/* Add space for bitmap. */\n\t\ttry_hdr_size += bitmap_size(try_nregs);\n\t\tif (config_prof && opt_prof && prof_promote == false) {\n\t\t\t/* Pad to a quantum boundary. */\n\t\t\ttry_hdr_size = QUANTUM_CEILING(try_hdr_size);\n\t\t\ttry_ctx0_offset = try_hdr_size;\n\t\t\t/* Add space for one (prof_ctx_t *) per region. */\n\t\t\ttry_hdr_size += try_nregs * sizeof(prof_ctx_t *);\n\t\t} else\n\t\t\ttry_ctx0_offset = 0;\n\t\ttry_redzone0_offset = try_run_size - (try_nregs *\n\t\t    bin_info->reg_interval) - pad_size;\n\t} while (try_hdr_size > try_redzone0_offset);\n\n\t/* run_size expansion loop. */\n\tdo {\n\t\t/*\n\t\t * Copy valid settings before trying more aggressive settings.\n\t\t */\n\t\tgood_run_size = try_run_size;\n\t\tgood_nregs = try_nregs;\n\t\tgood_hdr_size = try_hdr_size;\n\t\tgood_bitmap_offset = try_bitmap_offset;\n\t\tgood_ctx0_offset = try_ctx0_offset;\n\t\tgood_redzone0_offset = try_redzone0_offset;\n\n\t\t/* Try more aggressive settings. */\n\t\ttry_run_size += PAGE;\n\t\ttry_nregs = ((try_run_size - sizeof(arena_run_t) - pad_size) /\n\t\t    bin_info->reg_interval)\n\t\t    + 1; /* Counter-act try_nregs-- in loop. */\n\t\tif (try_nregs > RUN_MAXREGS) {\n\t\t\ttry_nregs = RUN_MAXREGS\n\t\t\t    + 1; /* Counter-act try_nregs-- in loop. */\n\t\t}\n\t\tdo {\n\t\t\ttry_nregs--;\n\t\t\ttry_hdr_size = sizeof(arena_run_t);\n\t\t\t/* Pad to a long boundary. */\n\t\t\ttry_hdr_size = LONG_CEILING(try_hdr_size);\n\t\t\ttry_bitmap_offset = try_hdr_size;\n\t\t\t/* Add space for bitmap. */\n\t\t\ttry_hdr_size += bitmap_size(try_nregs);\n\t\t\tif (config_prof && opt_prof && prof_promote == false) {\n\t\t\t\t/* Pad to a quantum boundary. */\n\t\t\t\ttry_hdr_size = QUANTUM_CEILING(try_hdr_size);\n\t\t\t\ttry_ctx0_offset = try_hdr_size;\n\t\t\t\t/*\n\t\t\t\t * Add space for one (prof_ctx_t *) per region.\n\t\t\t\t */\n\t\t\t\ttry_hdr_size += try_nregs *\n\t\t\t\t    sizeof(prof_ctx_t *);\n\t\t\t}\n\t\t\ttry_redzone0_offset = try_run_size - (try_nregs *\n\t\t\t    bin_info->reg_interval) - pad_size;\n\t\t} while (try_hdr_size > try_redzone0_offset);\n\t} while (try_run_size <= arena_maxclass\n\t    && RUN_MAX_OVRHD * (bin_info->reg_interval << 3) >\n\t    RUN_MAX_OVRHD_RELAX\n\t    && (try_redzone0_offset << RUN_BFP) > RUN_MAX_OVRHD * try_run_size\n\t    && try_nregs < RUN_MAXREGS);\n\n\tassert(good_hdr_size <= good_redzone0_offset);\n\n\t/* Copy final settings. */\n\tbin_info->run_size = good_run_size;\n\tbin_info->nregs = good_nregs;\n\tbin_info->bitmap_offset = good_bitmap_offset;\n\tbin_info->ctx0_offset = good_ctx0_offset;\n\tbin_info->reg0_offset = good_redzone0_offset + bin_info->redzone_size;\n\n\tassert(bin_info->reg0_offset - bin_info->redzone_size + (bin_info->nregs\n\t    * bin_info->reg_interval) + pad_size == bin_info->run_size);\n\n\treturn (good_run_size);\n}\n\nstatic void\nbin_info_init(void)\n{\n\tarena_bin_info_t *bin_info;\n\tsize_t prev_run_size = PAGE;\n\n#define\tSIZE_CLASS(bin, delta, size)\t\t\t\t\t\\\n\tbin_info = &arena_bin_info[bin];\t\t\t\t\\\n\tbin_info->reg_size = size;\t\t\t\t\t\\\n\tprev_run_size = bin_info_run_size_calc(bin_info, prev_run_size);\\\n\tbitmap_info_init(&bin_info->bitmap_info, bin_info->nregs);\n\tSIZE_CLASSES\n#undef SIZE_CLASS\n}\n\nvoid\narena_boot(void)\n{\n\tsize_t header_size;\n\tunsigned i;\n\n\t/*\n\t * Compute the header size such that it is large enough to contain the\n\t * page map.  The page map is biased to omit entries for the header\n\t * itself, so some iteration is necessary to compute the map bias.\n\t *\n\t * 1) Compute safe header_size and map_bias values that include enough\n\t *    space for an unbiased page map.\n\t * 2) Refine map_bias based on (1) to omit the header pages in the page\n\t *    map.  The resulting map_bias may be one too small.\n\t * 3) Refine map_bias based on (2).  The result will be >= the result\n\t *    from (2), and will always be correct.\n\t */\n\tmap_bias = 0;\n\tfor (i = 0; i < 3; i++) {\n\t\theader_size = offsetof(arena_chunk_t, map) +\n\t\t    (sizeof(arena_chunk_map_t) * (chunk_npages-map_bias));\n\t\tmap_bias = (header_size >> LG_PAGE) + ((header_size & PAGE_MASK)\n\t\t    != 0);\n\t}\n\tassert(map_bias > 0);\n\n\tarena_maxclass = chunksize - (map_bias << LG_PAGE);\n\n\tbin_info_init();\n}\n\nvoid\narena_prefork(arena_t *arena)\n{\n\tunsigned i;\n\n\tmalloc_mutex_prefork(&arena->lock);\n\tfor (i = 0; i < NBINS; i++)\n\t\tmalloc_mutex_prefork(&arena->bins[i].lock);\n}\n\nvoid\narena_postfork_parent(arena_t *arena)\n{\n\tunsigned i;\n\n\tfor (i = 0; i < NBINS; i++)\n\t\tmalloc_mutex_postfork_parent(&arena->bins[i].lock);\n\tmalloc_mutex_postfork_parent(&arena->lock);\n}\n\nvoid\narena_postfork_child(arena_t *arena)\n{\n\tunsigned i;\n\n\tfor (i = 0; i < NBINS; i++)\n\t\tmalloc_mutex_postfork_child(&arena->bins[i].lock);\n\tmalloc_mutex_postfork_child(&arena->lock);\n}\n"
  },
  {
    "path": "extern/deprecated/redis-2.8.21/deps/jemalloc/src/atomic.c",
    "content": "#define\tJEMALLOC_ATOMIC_C_\n#include \"jemalloc/internal/jemalloc_internal.h\"\n"
  },
  {
    "path": "extern/deprecated/redis-2.8.21/deps/jemalloc/src/base.c",
    "content": "#define\tJEMALLOC_BASE_C_\n#include \"jemalloc/internal/jemalloc_internal.h\"\n\n/******************************************************************************/\n/* Data. */\n\nstatic malloc_mutex_t\tbase_mtx;\n\n/*\n * Current pages that are being used for internal memory allocations.  These\n * pages are carved up in cacheline-size quanta, so that there is no chance of\n * false cache line sharing.\n */\nstatic void\t\t*base_pages;\nstatic void\t\t*base_next_addr;\nstatic void\t\t*base_past_addr; /* Addr immediately past base_pages. */\nstatic extent_node_t\t*base_nodes;\n\n/******************************************************************************/\n/* Function prototypes for non-inline static functions. */\n\nstatic bool\tbase_pages_alloc(size_t minsize);\n\n/******************************************************************************/\n\nstatic bool\nbase_pages_alloc(size_t minsize)\n{\n\tsize_t csize;\n\tbool zero;\n\n\tassert(minsize != 0);\n\tcsize = CHUNK_CEILING(minsize);\n\tzero = false;\n\tbase_pages = chunk_alloc(csize, chunksize, true, &zero,\n\t    chunk_dss_prec_get());\n\tif (base_pages == NULL)\n\t\treturn (true);\n\tbase_next_addr = base_pages;\n\tbase_past_addr = (void *)((uintptr_t)base_pages + csize);\n\n\treturn (false);\n}\n\nvoid *\nbase_alloc(size_t size)\n{\n\tvoid *ret;\n\tsize_t csize;\n\n\t/* Round size up to nearest multiple of the cacheline size. */\n\tcsize = CACHELINE_CEILING(size);\n\n\tmalloc_mutex_lock(&base_mtx);\n\t/* Make sure there's enough space for the allocation. */\n\tif ((uintptr_t)base_next_addr + csize > (uintptr_t)base_past_addr) {\n\t\tif (base_pages_alloc(csize)) {\n\t\t\tmalloc_mutex_unlock(&base_mtx);\n\t\t\treturn (NULL);\n\t\t}\n\t}\n\t/* Allocate. */\n\tret = base_next_addr;\n\tbase_next_addr = (void *)((uintptr_t)base_next_addr + csize);\n\tmalloc_mutex_unlock(&base_mtx);\n\tVALGRIND_MAKE_MEM_UNDEFINED(ret, csize);\n\n\treturn (ret);\n}\n\nvoid *\nbase_calloc(size_t number, size_t size)\n{\n\tvoid *ret = base_alloc(number * size);\n\n\tif (ret != NULL)\n\t\tmemset(ret, 0, number * size);\n\n\treturn (ret);\n}\n\nextent_node_t *\nbase_node_alloc(void)\n{\n\textent_node_t *ret;\n\n\tmalloc_mutex_lock(&base_mtx);\n\tif (base_nodes != NULL) {\n\t\tret = base_nodes;\n\t\tbase_nodes = *(extent_node_t **)ret;\n\t\tmalloc_mutex_unlock(&base_mtx);\n\t\tVALGRIND_MAKE_MEM_UNDEFINED(ret, sizeof(extent_node_t));\n\t} else {\n\t\tmalloc_mutex_unlock(&base_mtx);\n\t\tret = (extent_node_t *)base_alloc(sizeof(extent_node_t));\n\t}\n\n\treturn (ret);\n}\n\nvoid\nbase_node_dealloc(extent_node_t *node)\n{\n\n\tVALGRIND_MAKE_MEM_UNDEFINED(node, sizeof(extent_node_t));\n\tmalloc_mutex_lock(&base_mtx);\n\t*(extent_node_t **)node = base_nodes;\n\tbase_nodes = node;\n\tmalloc_mutex_unlock(&base_mtx);\n}\n\nbool\nbase_boot(void)\n{\n\n\tbase_nodes = NULL;\n\tif (malloc_mutex_init(&base_mtx))\n\t\treturn (true);\n\n\treturn (false);\n}\n\nvoid\nbase_prefork(void)\n{\n\n\tmalloc_mutex_prefork(&base_mtx);\n}\n\nvoid\nbase_postfork_parent(void)\n{\n\n\tmalloc_mutex_postfork_parent(&base_mtx);\n}\n\nvoid\nbase_postfork_child(void)\n{\n\n\tmalloc_mutex_postfork_child(&base_mtx);\n}\n"
  },
  {
    "path": "extern/deprecated/redis-2.8.21/deps/jemalloc/src/bitmap.c",
    "content": "#define\tJEMALLOC_BITMAP_C_\n#include \"jemalloc/internal/jemalloc_internal.h\"\n\n/******************************************************************************/\n/* Function prototypes for non-inline static functions. */\n\nstatic size_t\tbits2groups(size_t nbits);\n\n/******************************************************************************/\n\nstatic size_t\nbits2groups(size_t nbits)\n{\n\n\treturn ((nbits >> LG_BITMAP_GROUP_NBITS) +\n\t    !!(nbits & BITMAP_GROUP_NBITS_MASK));\n}\n\nvoid\nbitmap_info_init(bitmap_info_t *binfo, size_t nbits)\n{\n\tunsigned i;\n\tsize_t group_count;\n\n\tassert(nbits > 0);\n\tassert(nbits <= (ZU(1) << LG_BITMAP_MAXBITS));\n\n\t/*\n\t * Compute the number of groups necessary to store nbits bits, and\n\t * progressively work upward through the levels until reaching a level\n\t * that requires only one group.\n\t */\n\tbinfo->levels[0].group_offset = 0;\n\tgroup_count = bits2groups(nbits);\n\tfor (i = 1; group_count > 1; i++) {\n\t\tassert(i < BITMAP_MAX_LEVELS);\n\t\tbinfo->levels[i].group_offset = binfo->levels[i-1].group_offset\n\t\t    + group_count;\n\t\tgroup_count = bits2groups(group_count);\n\t}\n\tbinfo->levels[i].group_offset = binfo->levels[i-1].group_offset\n\t    + group_count;\n\tbinfo->nlevels = i;\n\tbinfo->nbits = nbits;\n}\n\nsize_t\nbitmap_info_ngroups(const bitmap_info_t *binfo)\n{\n\n\treturn (binfo->levels[binfo->nlevels].group_offset << LG_SIZEOF_BITMAP);\n}\n\nsize_t\nbitmap_size(size_t nbits)\n{\n\tbitmap_info_t binfo;\n\n\tbitmap_info_init(&binfo, nbits);\n\treturn (bitmap_info_ngroups(&binfo));\n}\n\nvoid\nbitmap_init(bitmap_t *bitmap, const bitmap_info_t *binfo)\n{\n\tsize_t extra;\n\tunsigned i;\n\n\t/*\n\t * Bits are actually inverted with regard to the external bitmap\n\t * interface, so the bitmap starts out with all 1 bits, except for\n\t * trailing unused bits (if any).  Note that each group uses bit 0 to\n\t * correspond to the first logical bit in the group, so extra bits\n\t * are the most significant bits of the last group.\n\t */\n\tmemset(bitmap, 0xffU, binfo->levels[binfo->nlevels].group_offset <<\n\t    LG_SIZEOF_BITMAP);\n\textra = (BITMAP_GROUP_NBITS - (binfo->nbits & BITMAP_GROUP_NBITS_MASK))\n\t    & BITMAP_GROUP_NBITS_MASK;\n\tif (extra != 0)\n\t\tbitmap[binfo->levels[1].group_offset - 1] >>= extra;\n\tfor (i = 1; i < binfo->nlevels; i++) {\n\t\tsize_t group_count = binfo->levels[i].group_offset -\n\t\t    binfo->levels[i-1].group_offset;\n\t\textra = (BITMAP_GROUP_NBITS - (group_count &\n\t\t    BITMAP_GROUP_NBITS_MASK)) & BITMAP_GROUP_NBITS_MASK;\n\t\tif (extra != 0)\n\t\t\tbitmap[binfo->levels[i+1].group_offset - 1] >>= extra;\n\t}\n}\n"
  },
  {
    "path": "extern/deprecated/redis-2.8.21/deps/jemalloc/src/chunk.c",
    "content": "#define\tJEMALLOC_CHUNK_C_\n#include \"jemalloc/internal/jemalloc_internal.h\"\n\n/******************************************************************************/\n/* Data. */\n\nconst char\t*opt_dss = DSS_DEFAULT;\nsize_t\t\topt_lg_chunk = LG_CHUNK_DEFAULT;\n\nmalloc_mutex_t\tchunks_mtx;\nchunk_stats_t\tstats_chunks;\n\n/*\n * Trees of chunks that were previously allocated (trees differ only in node\n * ordering).  These are used when allocating chunks, in an attempt to re-use\n * address space.  Depending on function, different tree orderings are needed,\n * which is why there are two trees with the same contents.\n */\nstatic extent_tree_t\tchunks_szad_mmap;\nstatic extent_tree_t\tchunks_ad_mmap;\nstatic extent_tree_t\tchunks_szad_dss;\nstatic extent_tree_t\tchunks_ad_dss;\n\nrtree_t\t\t*chunks_rtree;\n\n/* Various chunk-related settings. */\nsize_t\t\tchunksize;\nsize_t\t\tchunksize_mask; /* (chunksize - 1). */\nsize_t\t\tchunk_npages;\nsize_t\t\tmap_bias;\nsize_t\t\tarena_maxclass; /* Max size class for arenas. */\n\n/******************************************************************************/\n/* Function prototypes for non-inline static functions. */\n\nstatic void\t*chunk_recycle(extent_tree_t *chunks_szad,\n    extent_tree_t *chunks_ad, size_t size, size_t alignment, bool base,\n    bool *zero);\nstatic void\tchunk_record(extent_tree_t *chunks_szad,\n    extent_tree_t *chunks_ad, void *chunk, size_t size);\n\n/******************************************************************************/\n\nstatic void *\nchunk_recycle(extent_tree_t *chunks_szad, extent_tree_t *chunks_ad, size_t size,\n    size_t alignment, bool base, bool *zero)\n{\n\tvoid *ret;\n\textent_node_t *node;\n\textent_node_t key;\n\tsize_t alloc_size, leadsize, trailsize;\n\tbool zeroed;\n\n\tif (base) {\n\t\t/*\n\t\t * This function may need to call base_node_{,de}alloc(), but\n\t\t * the current chunk allocation request is on behalf of the\n\t\t * base allocator.  Avoid deadlock (and if that weren't an\n\t\t * issue, potential for infinite recursion) by returning NULL.\n\t\t */\n\t\treturn (NULL);\n\t}\n\n\talloc_size = size + alignment - chunksize;\n\t/* Beware size_t wrap-around. */\n\tif (alloc_size < size)\n\t\treturn (NULL);\n\tkey.addr = NULL;\n\tkey.size = alloc_size;\n\tmalloc_mutex_lock(&chunks_mtx);\n\tnode = extent_tree_szad_nsearch(chunks_szad, &key);\n\tif (node == NULL) {\n\t\tmalloc_mutex_unlock(&chunks_mtx);\n\t\treturn (NULL);\n\t}\n\tleadsize = ALIGNMENT_CEILING((uintptr_t)node->addr, alignment) -\n\t    (uintptr_t)node->addr;\n\tassert(node->size >= leadsize + size);\n\ttrailsize = node->size - leadsize - size;\n\tret = (void *)((uintptr_t)node->addr + leadsize);\n\tzeroed = node->zeroed;\n\tif (zeroed)\n\t    *zero = true;\n\t/* Remove node from the tree. */\n\textent_tree_szad_remove(chunks_szad, node);\n\textent_tree_ad_remove(chunks_ad, node);\n\tif (leadsize != 0) {\n\t\t/* Insert the leading space as a smaller chunk. */\n\t\tnode->size = leadsize;\n\t\textent_tree_szad_insert(chunks_szad, node);\n\t\textent_tree_ad_insert(chunks_ad, node);\n\t\tnode = NULL;\n\t}\n\tif (trailsize != 0) {\n\t\t/* Insert the trailing space as a smaller chunk. */\n\t\tif (node == NULL) {\n\t\t\t/*\n\t\t\t * An additional node is required, but\n\t\t\t * base_node_alloc() can cause a new base chunk to be\n\t\t\t * allocated.  Drop chunks_mtx in order to avoid\n\t\t\t * deadlock, and if node allocation fails, deallocate\n\t\t\t * the result before returning an error.\n\t\t\t */\n\t\t\tmalloc_mutex_unlock(&chunks_mtx);\n\t\t\tnode = base_node_alloc();\n\t\t\tif (node == NULL) {\n\t\t\t\tchunk_dealloc(ret, size, true);\n\t\t\t\treturn (NULL);\n\t\t\t}\n\t\t\tmalloc_mutex_lock(&chunks_mtx);\n\t\t}\n\t\tnode->addr = (void *)((uintptr_t)(ret) + size);\n\t\tnode->size = trailsize;\n\t\tnode->zeroed = zeroed;\n\t\textent_tree_szad_insert(chunks_szad, node);\n\t\textent_tree_ad_insert(chunks_ad, node);\n\t\tnode = NULL;\n\t}\n\tmalloc_mutex_unlock(&chunks_mtx);\n\n\tif (node != NULL)\n\t\tbase_node_dealloc(node);\n\tif (*zero) {\n\t\tif (zeroed == false)\n\t\t\tmemset(ret, 0, size);\n\t\telse if (config_debug) {\n\t\t\tsize_t i;\n\t\t\tsize_t *p = (size_t *)(uintptr_t)ret;\n\n\t\t\tVALGRIND_MAKE_MEM_DEFINED(ret, size);\n\t\t\tfor (i = 0; i < size / sizeof(size_t); i++)\n\t\t\t\tassert(p[i] == 0);\n\t\t}\n\t}\n\treturn (ret);\n}\n\n/*\n * If the caller specifies (*zero == false), it is still possible to receive\n * zeroed memory, in which case *zero is toggled to true.  arena_chunk_alloc()\n * takes advantage of this to avoid demanding zeroed chunks, but taking\n * advantage of them if they are returned.\n */\nvoid *\nchunk_alloc(size_t size, size_t alignment, bool base, bool *zero,\n    dss_prec_t dss_prec)\n{\n\tvoid *ret;\n\n\tassert(size != 0);\n\tassert((size & chunksize_mask) == 0);\n\tassert(alignment != 0);\n\tassert((alignment & chunksize_mask) == 0);\n\n\t/* \"primary\" dss. */\n\tif (config_dss && dss_prec == dss_prec_primary) {\n\t\tif ((ret = chunk_recycle(&chunks_szad_dss, &chunks_ad_dss, size,\n\t\t    alignment, base, zero)) != NULL)\n\t\t\tgoto label_return;\n\t\tif ((ret = chunk_alloc_dss(size, alignment, zero)) != NULL)\n\t\t\tgoto label_return;\n\t}\n\t/* mmap. */\n\tif ((ret = chunk_recycle(&chunks_szad_mmap, &chunks_ad_mmap, size,\n\t    alignment, base, zero)) != NULL)\n\t\tgoto label_return;\n\tif ((ret = chunk_alloc_mmap(size, alignment, zero)) != NULL)\n\t\tgoto label_return;\n\t/* \"secondary\" dss. */\n\tif (config_dss && dss_prec == dss_prec_secondary) {\n\t\tif ((ret = chunk_recycle(&chunks_szad_dss, &chunks_ad_dss, size,\n\t\t    alignment, base, zero)) != NULL)\n\t\t\tgoto label_return;\n\t\tif ((ret = chunk_alloc_dss(size, alignment, zero)) != NULL)\n\t\t\tgoto label_return;\n\t}\n\n\t/* All strategies for allocation failed. */\n\tret = NULL;\nlabel_return:\n\tif (ret != NULL) {\n\t\tif (config_ivsalloc && base == false) {\n\t\t\tif (rtree_set(chunks_rtree, (uintptr_t)ret, 1)) {\n\t\t\t\tchunk_dealloc(ret, size, true);\n\t\t\t\treturn (NULL);\n\t\t\t}\n\t\t}\n\t\tif (config_stats || config_prof) {\n\t\t\tbool gdump;\n\t\t\tmalloc_mutex_lock(&chunks_mtx);\n\t\t\tif (config_stats)\n\t\t\t\tstats_chunks.nchunks += (size / chunksize);\n\t\t\tstats_chunks.curchunks += (size / chunksize);\n\t\t\tif (stats_chunks.curchunks > stats_chunks.highchunks) {\n\t\t\t\tstats_chunks.highchunks =\n\t\t\t\t    stats_chunks.curchunks;\n\t\t\t\tif (config_prof)\n\t\t\t\t\tgdump = true;\n\t\t\t} else if (config_prof)\n\t\t\t\tgdump = false;\n\t\t\tmalloc_mutex_unlock(&chunks_mtx);\n\t\t\tif (config_prof && opt_prof && opt_prof_gdump && gdump)\n\t\t\t\tprof_gdump();\n\t\t}\n\t\tif (config_valgrind)\n\t\t\tVALGRIND_MAKE_MEM_UNDEFINED(ret, size);\n\t}\n\tassert(CHUNK_ADDR2BASE(ret) == ret);\n\treturn (ret);\n}\n\nstatic void\nchunk_record(extent_tree_t *chunks_szad, extent_tree_t *chunks_ad, void *chunk,\n    size_t size)\n{\n\tbool unzeroed;\n\textent_node_t *xnode, *node, *prev, *xprev, key;\n\n\tunzeroed = pages_purge(chunk, size);\n\tVALGRIND_MAKE_MEM_NOACCESS(chunk, size);\n\n\t/*\n\t * Allocate a node before acquiring chunks_mtx even though it might not\n\t * be needed, because base_node_alloc() may cause a new base chunk to\n\t * be allocated, which could cause deadlock if chunks_mtx were already\n\t * held.\n\t */\n\txnode = base_node_alloc();\n\t/* Use xprev to implement conditional deferred deallocation of prev. */\n\txprev = NULL;\n\n\tmalloc_mutex_lock(&chunks_mtx);\n\tkey.addr = (void *)((uintptr_t)chunk + size);\n\tnode = extent_tree_ad_nsearch(chunks_ad, &key);\n\t/* Try to coalesce forward. */\n\tif (node != NULL && node->addr == key.addr) {\n\t\t/*\n\t\t * Coalesce chunk with the following address range.  This does\n\t\t * not change the position within chunks_ad, so only\n\t\t * remove/insert from/into chunks_szad.\n\t\t */\n\t\textent_tree_szad_remove(chunks_szad, node);\n\t\tnode->addr = chunk;\n\t\tnode->size += size;\n\t\tnode->zeroed = (node->zeroed && (unzeroed == false));\n\t\textent_tree_szad_insert(chunks_szad, node);\n\t} else {\n\t\t/* Coalescing forward failed, so insert a new node. */\n\t\tif (xnode == NULL) {\n\t\t\t/*\n\t\t\t * base_node_alloc() failed, which is an exceedingly\n\t\t\t * unlikely failure.  Leak chunk; its pages have\n\t\t\t * already been purged, so this is only a virtual\n\t\t\t * memory leak.\n\t\t\t */\n\t\t\tgoto label_return;\n\t\t}\n\t\tnode = xnode;\n\t\txnode = NULL; /* Prevent deallocation below. */\n\t\tnode->addr = chunk;\n\t\tnode->size = size;\n\t\tnode->zeroed = (unzeroed == false);\n\t\textent_tree_ad_insert(chunks_ad, node);\n\t\textent_tree_szad_insert(chunks_szad, node);\n\t}\n\n\t/* Try to coalesce backward. */\n\tprev = extent_tree_ad_prev(chunks_ad, node);\n\tif (prev != NULL && (void *)((uintptr_t)prev->addr + prev->size) ==\n\t    chunk) {\n\t\t/*\n\t\t * Coalesce chunk with the previous address range.  This does\n\t\t * not change the position within chunks_ad, so only\n\t\t * remove/insert node from/into chunks_szad.\n\t\t */\n\t\textent_tree_szad_remove(chunks_szad, prev);\n\t\textent_tree_ad_remove(chunks_ad, prev);\n\n\t\textent_tree_szad_remove(chunks_szad, node);\n\t\tnode->addr = prev->addr;\n\t\tnode->size += prev->size;\n\t\tnode->zeroed = (node->zeroed && prev->zeroed);\n\t\textent_tree_szad_insert(chunks_szad, node);\n\n\t\txprev = prev;\n\t}\n\nlabel_return:\n\tmalloc_mutex_unlock(&chunks_mtx);\n\t/*\n\t * Deallocate xnode and/or xprev after unlocking chunks_mtx in order to\n\t * avoid potential deadlock.\n\t */\n\tif (xnode != NULL)\n\t\tbase_node_dealloc(xnode);\n\tif (xprev != NULL)\n\t\tbase_node_dealloc(xprev);\n}\n\nvoid\nchunk_unmap(void *chunk, size_t size)\n{\n\tassert(chunk != NULL);\n\tassert(CHUNK_ADDR2BASE(chunk) == chunk);\n\tassert(size != 0);\n\tassert((size & chunksize_mask) == 0);\n\n\tif (config_dss && chunk_in_dss(chunk))\n\t\tchunk_record(&chunks_szad_dss, &chunks_ad_dss, chunk, size);\n\telse if (chunk_dealloc_mmap(chunk, size))\n\t\tchunk_record(&chunks_szad_mmap, &chunks_ad_mmap, chunk, size);\n}\n\nvoid\nchunk_dealloc(void *chunk, size_t size, bool unmap)\n{\n\n\tassert(chunk != NULL);\n\tassert(CHUNK_ADDR2BASE(chunk) == chunk);\n\tassert(size != 0);\n\tassert((size & chunksize_mask) == 0);\n\n\tif (config_ivsalloc)\n\t\trtree_set(chunks_rtree, (uintptr_t)chunk, 0);\n\tif (config_stats || config_prof) {\n\t\tmalloc_mutex_lock(&chunks_mtx);\n\t\tassert(stats_chunks.curchunks >= (size / chunksize));\n\t\tstats_chunks.curchunks -= (size / chunksize);\n\t\tmalloc_mutex_unlock(&chunks_mtx);\n\t}\n\n\tif (unmap)\n\t\tchunk_unmap(chunk, size);\n}\n\nbool\nchunk_boot(void)\n{\n\n\t/* Set variables according to the value of opt_lg_chunk. */\n\tchunksize = (ZU(1) << opt_lg_chunk);\n\tassert(chunksize >= PAGE);\n\tchunksize_mask = chunksize - 1;\n\tchunk_npages = (chunksize >> LG_PAGE);\n\n\tif (config_stats || config_prof) {\n\t\tif (malloc_mutex_init(&chunks_mtx))\n\t\t\treturn (true);\n\t\tmemset(&stats_chunks, 0, sizeof(chunk_stats_t));\n\t}\n\tif (config_dss && chunk_dss_boot())\n\t\treturn (true);\n\textent_tree_szad_new(&chunks_szad_mmap);\n\textent_tree_ad_new(&chunks_ad_mmap);\n\textent_tree_szad_new(&chunks_szad_dss);\n\textent_tree_ad_new(&chunks_ad_dss);\n\tif (config_ivsalloc) {\n\t\tchunks_rtree = rtree_new((ZU(1) << (LG_SIZEOF_PTR+3)) -\n\t\t    opt_lg_chunk, base_alloc, NULL);\n\t\tif (chunks_rtree == NULL)\n\t\t\treturn (true);\n\t}\n\n\treturn (false);\n}\n\nvoid\nchunk_prefork(void)\n{\n\n\tmalloc_mutex_prefork(&chunks_mtx);\n\tif (config_ivsalloc)\n\t\trtree_prefork(chunks_rtree);\n\tchunk_dss_prefork();\n}\n\nvoid\nchunk_postfork_parent(void)\n{\n\n\tchunk_dss_postfork_parent();\n\tif (config_ivsalloc)\n\t\trtree_postfork_parent(chunks_rtree);\n\tmalloc_mutex_postfork_parent(&chunks_mtx);\n}\n\nvoid\nchunk_postfork_child(void)\n{\n\n\tchunk_dss_postfork_child();\n\tif (config_ivsalloc)\n\t\trtree_postfork_child(chunks_rtree);\n\tmalloc_mutex_postfork_child(&chunks_mtx);\n}\n"
  },
  {
    "path": "extern/deprecated/redis-2.8.21/deps/jemalloc/src/chunk_dss.c",
    "content": "#define\tJEMALLOC_CHUNK_DSS_C_\n#include \"jemalloc/internal/jemalloc_internal.h\"\n/******************************************************************************/\n/* Data. */\n\nconst char\t*dss_prec_names[] = {\n\t\"disabled\",\n\t\"primary\",\n\t\"secondary\",\n\t\"N/A\"\n};\n\n/* Current dss precedence default, used when creating new arenas. */\nstatic dss_prec_t\tdss_prec_default = DSS_PREC_DEFAULT;\n\n/*\n * Protects sbrk() calls.  This avoids malloc races among threads, though it\n * does not protect against races with threads that call sbrk() directly.\n */\nstatic malloc_mutex_t\tdss_mtx;\n\n/* Base address of the DSS. */\nstatic void\t\t*dss_base;\n/* Current end of the DSS, or ((void *)-1) if the DSS is exhausted. */\nstatic void\t\t*dss_prev;\n/* Current upper limit on DSS addresses. */\nstatic void\t\t*dss_max;\n\n/******************************************************************************/\n\nstatic void *\nchunk_dss_sbrk(intptr_t increment)\n{\n\n#ifdef JEMALLOC_HAVE_SBRK\n\treturn (sbrk(increment));\n#else\n\tnot_implemented();\n\treturn (NULL);\n#endif\n}\n\ndss_prec_t\nchunk_dss_prec_get(void)\n{\n\tdss_prec_t ret;\n\n\tif (config_dss == false)\n\t\treturn (dss_prec_disabled);\n\tmalloc_mutex_lock(&dss_mtx);\n\tret = dss_prec_default;\n\tmalloc_mutex_unlock(&dss_mtx);\n\treturn (ret);\n}\n\nbool\nchunk_dss_prec_set(dss_prec_t dss_prec)\n{\n\n\tif (config_dss == false)\n\t\treturn (true);\n\tmalloc_mutex_lock(&dss_mtx);\n\tdss_prec_default = dss_prec;\n\tmalloc_mutex_unlock(&dss_mtx);\n\treturn (false);\n}\n\nvoid *\nchunk_alloc_dss(size_t size, size_t alignment, bool *zero)\n{\n\tvoid *ret;\n\n\tcassert(config_dss);\n\tassert(size > 0 && (size & chunksize_mask) == 0);\n\tassert(alignment > 0 && (alignment & chunksize_mask) == 0);\n\n\t/*\n\t * sbrk() uses a signed increment argument, so take care not to\n\t * interpret a huge allocation request as a negative increment.\n\t */\n\tif ((intptr_t)size < 0)\n\t\treturn (NULL);\n\n\tmalloc_mutex_lock(&dss_mtx);\n\tif (dss_prev != (void *)-1) {\n\t\tsize_t gap_size, cpad_size;\n\t\tvoid *cpad, *dss_next;\n\t\tintptr_t incr;\n\n\t\t/*\n\t\t * The loop is necessary to recover from races with other\n\t\t * threads that are using the DSS for something other than\n\t\t * malloc.\n\t\t */\n\t\tdo {\n\t\t\t/* Get the current end of the DSS. */\n\t\t\tdss_max = chunk_dss_sbrk(0);\n\t\t\t/*\n\t\t\t * Calculate how much padding is necessary to\n\t\t\t * chunk-align the end of the DSS.\n\t\t\t */\n\t\t\tgap_size = (chunksize - CHUNK_ADDR2OFFSET(dss_max)) &\n\t\t\t    chunksize_mask;\n\t\t\t/*\n\t\t\t * Compute how much chunk-aligned pad space (if any) is\n\t\t\t * necessary to satisfy alignment.  This space can be\n\t\t\t * recycled for later use.\n\t\t\t */\n\t\t\tcpad = (void *)((uintptr_t)dss_max + gap_size);\n\t\t\tret = (void *)ALIGNMENT_CEILING((uintptr_t)dss_max,\n\t\t\t    alignment);\n\t\t\tcpad_size = (uintptr_t)ret - (uintptr_t)cpad;\n\t\t\tdss_next = (void *)((uintptr_t)ret + size);\n\t\t\tif ((uintptr_t)ret < (uintptr_t)dss_max ||\n\t\t\t    (uintptr_t)dss_next < (uintptr_t)dss_max) {\n\t\t\t\t/* Wrap-around. */\n\t\t\t\tmalloc_mutex_unlock(&dss_mtx);\n\t\t\t\treturn (NULL);\n\t\t\t}\n\t\t\tincr = gap_size + cpad_size + size;\n\t\t\tdss_prev = chunk_dss_sbrk(incr);\n\t\t\tif (dss_prev == dss_max) {\n\t\t\t\t/* Success. */\n\t\t\t\tdss_max = dss_next;\n\t\t\t\tmalloc_mutex_unlock(&dss_mtx);\n\t\t\t\tif (cpad_size != 0)\n\t\t\t\t\tchunk_unmap(cpad, cpad_size);\n\t\t\t\tif (*zero) {\n\t\t\t\t\tVALGRIND_MAKE_MEM_UNDEFINED(ret, size);\n\t\t\t\t\tmemset(ret, 0, size);\n\t\t\t\t}\n\t\t\t\treturn (ret);\n\t\t\t}\n\t\t} while (dss_prev != (void *)-1);\n\t}\n\tmalloc_mutex_unlock(&dss_mtx);\n\n\treturn (NULL);\n}\n\nbool\nchunk_in_dss(void *chunk)\n{\n\tbool ret;\n\n\tcassert(config_dss);\n\n\tmalloc_mutex_lock(&dss_mtx);\n\tif ((uintptr_t)chunk >= (uintptr_t)dss_base\n\t    && (uintptr_t)chunk < (uintptr_t)dss_max)\n\t\tret = true;\n\telse\n\t\tret = false;\n\tmalloc_mutex_unlock(&dss_mtx);\n\n\treturn (ret);\n}\n\nbool\nchunk_dss_boot(void)\n{\n\n\tcassert(config_dss);\n\n\tif (malloc_mutex_init(&dss_mtx))\n\t\treturn (true);\n\tdss_base = chunk_dss_sbrk(0);\n\tdss_prev = dss_base;\n\tdss_max = dss_base;\n\n\treturn (false);\n}\n\nvoid\nchunk_dss_prefork(void)\n{\n\n\tif (config_dss)\n\t\tmalloc_mutex_prefork(&dss_mtx);\n}\n\nvoid\nchunk_dss_postfork_parent(void)\n{\n\n\tif (config_dss)\n\t\tmalloc_mutex_postfork_parent(&dss_mtx);\n}\n\nvoid\nchunk_dss_postfork_child(void)\n{\n\n\tif (config_dss)\n\t\tmalloc_mutex_postfork_child(&dss_mtx);\n}\n\n/******************************************************************************/\n"
  },
  {
    "path": "extern/deprecated/redis-2.8.21/deps/jemalloc/src/chunk_mmap.c",
    "content": "#define\tJEMALLOC_CHUNK_MMAP_C_\n#include \"jemalloc/internal/jemalloc_internal.h\"\n\n/******************************************************************************/\n/* Function prototypes for non-inline static functions. */\n\nstatic void\t*pages_map(void *addr, size_t size);\nstatic void\tpages_unmap(void *addr, size_t size);\nstatic void\t*chunk_alloc_mmap_slow(size_t size, size_t alignment,\n    bool *zero);\n\n/******************************************************************************/\n\nstatic void *\npages_map(void *addr, size_t size)\n{\n\tvoid *ret;\n\n\tassert(size != 0);\n\n#ifdef _WIN32\n\t/*\n\t * If VirtualAlloc can't allocate at the given address when one is\n\t * given, it fails and returns NULL.\n\t */\n\tret = VirtualAlloc(addr, size, MEM_COMMIT | MEM_RESERVE,\n\t    PAGE_READWRITE);\n#else\n\t/*\n\t * We don't use MAP_FIXED here, because it can cause the *replacement*\n\t * of existing mappings, and we only want to create new mappings.\n\t */\n\tret = mmap(addr, size, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANON,\n\t    -1, 0);\n\tassert(ret != NULL);\n\n\tif (ret == MAP_FAILED)\n\t\tret = NULL;\n\telse if (addr != NULL && ret != addr) {\n\t\t/*\n\t\t * We succeeded in mapping memory, but not in the right place.\n\t\t */\n\t\tif (munmap(ret, size) == -1) {\n\t\t\tchar buf[BUFERROR_BUF];\n\n\t\t\tbuferror(get_errno(), buf, sizeof(buf));\n\t\t\tmalloc_printf(\"<jemalloc: Error in munmap(): %s\\n\",\n\t\t\t    buf);\n\t\t\tif (opt_abort)\n\t\t\t\tabort();\n\t\t}\n\t\tret = NULL;\n\t}\n#endif\n\tassert(ret == NULL || (addr == NULL && ret != addr)\n\t    || (addr != NULL && ret == addr));\n\treturn (ret);\n}\n\nstatic void\npages_unmap(void *addr, size_t size)\n{\n\n#ifdef _WIN32\n\tif (VirtualFree(addr, 0, MEM_RELEASE) == 0)\n#else\n\tif (munmap(addr, size) == -1)\n#endif\n\t{\n\t\tchar buf[BUFERROR_BUF];\n\n\t\tbuferror(get_errno(), buf, sizeof(buf));\n\t\tmalloc_printf(\"<jemalloc>: Error in \"\n#ifdef _WIN32\n\t\t              \"VirtualFree\"\n#else\n\t\t              \"munmap\"\n#endif\n\t\t              \"(): %s\\n\", buf);\n\t\tif (opt_abort)\n\t\t\tabort();\n\t}\n}\n\nstatic void *\npages_trim(void *addr, size_t alloc_size, size_t leadsize, size_t size)\n{\n\tvoid *ret = (void *)((uintptr_t)addr + leadsize);\n\n\tassert(alloc_size >= leadsize + size);\n#ifdef _WIN32\n\t{\n\t\tvoid *new_addr;\n\n\t\tpages_unmap(addr, alloc_size);\n\t\tnew_addr = pages_map(ret, size);\n\t\tif (new_addr == ret)\n\t\t\treturn (ret);\n\t\tif (new_addr)\n\t\t\tpages_unmap(new_addr, size);\n\t\treturn (NULL);\n\t}\n#else\n\t{\n\t\tsize_t trailsize = alloc_size - leadsize - size;\n\n\t\tif (leadsize != 0)\n\t\t\tpages_unmap(addr, leadsize);\n\t\tif (trailsize != 0)\n\t\t\tpages_unmap((void *)((uintptr_t)ret + size), trailsize);\n\t\treturn (ret);\n\t}\n#endif\n}\n\nbool\npages_purge(void *addr, size_t length)\n{\n\tbool unzeroed;\n\n#ifdef _WIN32\n\tVirtualAlloc(addr, length, MEM_RESET, PAGE_READWRITE);\n\tunzeroed = true;\n#else\n#  ifdef JEMALLOC_PURGE_MADVISE_DONTNEED\n#    define JEMALLOC_MADV_PURGE MADV_DONTNEED\n#    define JEMALLOC_MADV_ZEROS true\n#  elif defined(JEMALLOC_PURGE_MADVISE_FREE)\n#    define JEMALLOC_MADV_PURGE MADV_FREE\n#    define JEMALLOC_MADV_ZEROS false\n#  else\n#    error \"No method defined for purging unused dirty pages.\"\n#  endif\n\tint err = madvise(addr, length, JEMALLOC_MADV_PURGE);\n\tunzeroed = (JEMALLOC_MADV_ZEROS == false || err != 0);\n#  undef JEMALLOC_MADV_PURGE\n#  undef JEMALLOC_MADV_ZEROS\n#endif\n\treturn (unzeroed);\n}\n\nstatic void *\nchunk_alloc_mmap_slow(size_t size, size_t alignment, bool *zero)\n{\n\tvoid *ret, *pages;\n\tsize_t alloc_size, leadsize;\n\n\talloc_size = size + alignment - PAGE;\n\t/* Beware size_t wrap-around. */\n\tif (alloc_size < size)\n\t\treturn (NULL);\n\tdo {\n\t\tpages = pages_map(NULL, alloc_size);\n\t\tif (pages == NULL)\n\t\t\treturn (NULL);\n\t\tleadsize = ALIGNMENT_CEILING((uintptr_t)pages, alignment) -\n\t\t    (uintptr_t)pages;\n\t\tret = pages_trim(pages, alloc_size, leadsize, size);\n\t} while (ret == NULL);\n\n\tassert(ret != NULL);\n\t*zero = true;\n\treturn (ret);\n}\n\nvoid *\nchunk_alloc_mmap(size_t size, size_t alignment, bool *zero)\n{\n\tvoid *ret;\n\tsize_t offset;\n\n\t/*\n\t * Ideally, there would be a way to specify alignment to mmap() (like\n\t * NetBSD has), but in the absence of such a feature, we have to work\n\t * hard to efficiently create aligned mappings.  The reliable, but\n\t * slow method is to create a mapping that is over-sized, then trim the\n\t * excess.  However, that always results in one or two calls to\n\t * pages_unmap().\n\t *\n\t * Optimistically try mapping precisely the right amount before falling\n\t * back to the slow method, with the expectation that the optimistic\n\t * approach works most of the time.\n\t */\n\n\tassert(alignment != 0);\n\tassert((alignment & chunksize_mask) == 0);\n\n\tret = pages_map(NULL, size);\n\tif (ret == NULL)\n\t\treturn (NULL);\n\toffset = ALIGNMENT_ADDR2OFFSET(ret, alignment);\n\tif (offset != 0) {\n\t\tpages_unmap(ret, size);\n\t\treturn (chunk_alloc_mmap_slow(size, alignment, zero));\n\t}\n\n\tassert(ret != NULL);\n\t*zero = true;\n\treturn (ret);\n}\n\nbool\nchunk_dealloc_mmap(void *chunk, size_t size)\n{\n\n\tif (config_munmap)\n\t\tpages_unmap(chunk, size);\n\n\treturn (config_munmap == false);\n}\n"
  },
  {
    "path": "extern/deprecated/redis-2.8.21/deps/jemalloc/src/ckh.c",
    "content": "/*\n *******************************************************************************\n * Implementation of (2^1+,2) cuckoo hashing, where 2^1+ indicates that each\n * hash bucket contains 2^n cells, for n >= 1, and 2 indicates that two hash\n * functions are employed.  The original cuckoo hashing algorithm was described\n * in:\n *\n *   Pagh, R., F.F. Rodler (2004) Cuckoo Hashing.  Journal of Algorithms\n *     51(2):122-144.\n *\n * Generalization of cuckoo hashing was discussed in:\n *\n *   Erlingsson, U., M. Manasse, F. McSherry (2006) A cool and practical\n *     alternative to traditional hash tables.  In Proceedings of the 7th\n *     Workshop on Distributed Data and Structures (WDAS'06), Santa Clara, CA,\n *     January 2006.\n *\n * This implementation uses precisely two hash functions because that is the\n * fewest that can work, and supporting multiple hashes is an implementation\n * burden.  Here is a reproduction of Figure 1 from Erlingsson et al. (2006)\n * that shows approximate expected maximum load factors for various\n * configurations:\n *\n *           |         #cells/bucket         |\n *   #hashes |   1   |   2   |   4   |   8   |\n *   --------+-------+-------+-------+-------+\n *         1 | 0.006 | 0.006 | 0.03  | 0.12  |\n *         2 | 0.49  | 0.86  |>0.93< |>0.96< |\n *         3 | 0.91  | 0.97  | 0.98  | 0.999 |\n *         4 | 0.97  | 0.99  | 0.999 |       |\n *\n * The number of cells per bucket is chosen such that a bucket fits in one cache\n * line.  So, on 32- and 64-bit systems, we use (8,2) and (4,2) cuckoo hashing,\n * respectively.\n *\n ******************************************************************************/\n#define\tJEMALLOC_CKH_C_\n#include \"jemalloc/internal/jemalloc_internal.h\"\n\n/******************************************************************************/\n/* Function prototypes for non-inline static functions. */\n\nstatic bool\tckh_grow(ckh_t *ckh);\nstatic void\tckh_shrink(ckh_t *ckh);\n\n/******************************************************************************/\n\n/*\n * Search bucket for key and return the cell number if found; SIZE_T_MAX\n * otherwise.\n */\nJEMALLOC_INLINE_C size_t\nckh_bucket_search(ckh_t *ckh, size_t bucket, const void *key)\n{\n\tckhc_t *cell;\n\tunsigned i;\n\n\tfor (i = 0; i < (ZU(1) << LG_CKH_BUCKET_CELLS); i++) {\n\t\tcell = &ckh->tab[(bucket << LG_CKH_BUCKET_CELLS) + i];\n\t\tif (cell->key != NULL && ckh->keycomp(key, cell->key))\n\t\t\treturn ((bucket << LG_CKH_BUCKET_CELLS) + i);\n\t}\n\n\treturn (SIZE_T_MAX);\n}\n\n/*\n * Search table for key and return cell number if found; SIZE_T_MAX otherwise.\n */\nJEMALLOC_INLINE_C size_t\nckh_isearch(ckh_t *ckh, const void *key)\n{\n\tsize_t hashes[2], bucket, cell;\n\n\tassert(ckh != NULL);\n\n\tckh->hash(key, hashes);\n\n\t/* Search primary bucket. */\n\tbucket = hashes[0] & ((ZU(1) << ckh->lg_curbuckets) - 1);\n\tcell = ckh_bucket_search(ckh, bucket, key);\n\tif (cell != SIZE_T_MAX)\n\t\treturn (cell);\n\n\t/* Search secondary bucket. */\n\tbucket = hashes[1] & ((ZU(1) << ckh->lg_curbuckets) - 1);\n\tcell = ckh_bucket_search(ckh, bucket, key);\n\treturn (cell);\n}\n\nJEMALLOC_INLINE_C bool\nckh_try_bucket_insert(ckh_t *ckh, size_t bucket, const void *key,\n    const void *data)\n{\n\tckhc_t *cell;\n\tunsigned offset, i;\n\n\t/*\n\t * Cycle through the cells in the bucket, starting at a random position.\n\t * The randomness avoids worst-case search overhead as buckets fill up.\n\t */\n\tprng32(offset, LG_CKH_BUCKET_CELLS, ckh->prng_state, CKH_A, CKH_C);\n\tfor (i = 0; i < (ZU(1) << LG_CKH_BUCKET_CELLS); i++) {\n\t\tcell = &ckh->tab[(bucket << LG_CKH_BUCKET_CELLS) +\n\t\t    ((i + offset) & ((ZU(1) << LG_CKH_BUCKET_CELLS) - 1))];\n\t\tif (cell->key == NULL) {\n\t\t\tcell->key = key;\n\t\t\tcell->data = data;\n\t\t\tckh->count++;\n\t\t\treturn (false);\n\t\t}\n\t}\n\n\treturn (true);\n}\n\n/*\n * No space is available in bucket.  Randomly evict an item, then try to find an\n * alternate location for that item.  Iteratively repeat this\n * eviction/relocation procedure until either success or detection of an\n * eviction/relocation bucket cycle.\n */\nJEMALLOC_INLINE_C bool\nckh_evict_reloc_insert(ckh_t *ckh, size_t argbucket, void const **argkey,\n    void const **argdata)\n{\n\tconst void *key, *data, *tkey, *tdata;\n\tckhc_t *cell;\n\tsize_t hashes[2], bucket, tbucket;\n\tunsigned i;\n\n\tbucket = argbucket;\n\tkey = *argkey;\n\tdata = *argdata;\n\twhile (true) {\n\t\t/*\n\t\t * Choose a random item within the bucket to evict.  This is\n\t\t * critical to correct function, because without (eventually)\n\t\t * evicting all items within a bucket during iteration, it\n\t\t * would be possible to get stuck in an infinite loop if there\n\t\t * were an item for which both hashes indicated the same\n\t\t * bucket.\n\t\t */\n\t\tprng32(i, LG_CKH_BUCKET_CELLS, ckh->prng_state, CKH_A, CKH_C);\n\t\tcell = &ckh->tab[(bucket << LG_CKH_BUCKET_CELLS) + i];\n\t\tassert(cell->key != NULL);\n\n\t\t/* Swap cell->{key,data} and {key,data} (evict). */\n\t\ttkey = cell->key; tdata = cell->data;\n\t\tcell->key = key; cell->data = data;\n\t\tkey = tkey; data = tdata;\n\n#ifdef CKH_COUNT\n\t\tckh->nrelocs++;\n#endif\n\n\t\t/* Find the alternate bucket for the evicted item. */\n\t\tckh->hash(key, hashes);\n\t\ttbucket = hashes[1] & ((ZU(1) << ckh->lg_curbuckets) - 1);\n\t\tif (tbucket == bucket) {\n\t\t\ttbucket = hashes[0] & ((ZU(1) << ckh->lg_curbuckets)\n\t\t\t    - 1);\n\t\t\t/*\n\t\t\t * It may be that (tbucket == bucket) still, if the\n\t\t\t * item's hashes both indicate this bucket.  However,\n\t\t\t * we are guaranteed to eventually escape this bucket\n\t\t\t * during iteration, assuming pseudo-random item\n\t\t\t * selection (true randomness would make infinite\n\t\t\t * looping a remote possibility).  The reason we can\n\t\t\t * never get trapped forever is that there are two\n\t\t\t * cases:\n\t\t\t *\n\t\t\t * 1) This bucket == argbucket, so we will quickly\n\t\t\t *    detect an eviction cycle and terminate.\n\t\t\t * 2) An item was evicted to this bucket from another,\n\t\t\t *    which means that at least one item in this bucket\n\t\t\t *    has hashes that indicate distinct buckets.\n\t\t\t */\n\t\t}\n\t\t/* Check for a cycle. */\n\t\tif (tbucket == argbucket) {\n\t\t\t*argkey = key;\n\t\t\t*argdata = data;\n\t\t\treturn (true);\n\t\t}\n\n\t\tbucket = tbucket;\n\t\tif (ckh_try_bucket_insert(ckh, bucket, key, data) == false)\n\t\t\treturn (false);\n\t}\n}\n\nJEMALLOC_INLINE_C bool\nckh_try_insert(ckh_t *ckh, void const**argkey, void const**argdata)\n{\n\tsize_t hashes[2], bucket;\n\tconst void *key = *argkey;\n\tconst void *data = *argdata;\n\n\tckh->hash(key, hashes);\n\n\t/* Try to insert in primary bucket. */\n\tbucket = hashes[0] & ((ZU(1) << ckh->lg_curbuckets) - 1);\n\tif (ckh_try_bucket_insert(ckh, bucket, key, data) == false)\n\t\treturn (false);\n\n\t/* Try to insert in secondary bucket. */\n\tbucket = hashes[1] & ((ZU(1) << ckh->lg_curbuckets) - 1);\n\tif (ckh_try_bucket_insert(ckh, bucket, key, data) == false)\n\t\treturn (false);\n\n\t/*\n\t * Try to find a place for this item via iterative eviction/relocation.\n\t */\n\treturn (ckh_evict_reloc_insert(ckh, bucket, argkey, argdata));\n}\n\n/*\n * Try to rebuild the hash table from scratch by inserting all items from the\n * old table into the new.\n */\nJEMALLOC_INLINE_C bool\nckh_rebuild(ckh_t *ckh, ckhc_t *aTab)\n{\n\tsize_t count, i, nins;\n\tconst void *key, *data;\n\n\tcount = ckh->count;\n\tckh->count = 0;\n\tfor (i = nins = 0; nins < count; i++) {\n\t\tif (aTab[i].key != NULL) {\n\t\t\tkey = aTab[i].key;\n\t\t\tdata = aTab[i].data;\n\t\t\tif (ckh_try_insert(ckh, &key, &data)) {\n\t\t\t\tckh->count = count;\n\t\t\t\treturn (true);\n\t\t\t}\n\t\t\tnins++;\n\t\t}\n\t}\n\n\treturn (false);\n}\n\nstatic bool\nckh_grow(ckh_t *ckh)\n{\n\tbool ret;\n\tckhc_t *tab, *ttab;\n\tsize_t lg_curcells;\n\tunsigned lg_prevbuckets;\n\n#ifdef CKH_COUNT\n\tckh->ngrows++;\n#endif\n\n\t/*\n\t * It is possible (though unlikely, given well behaved hashes) that the\n\t * table will have to be doubled more than once in order to create a\n\t * usable table.\n\t */\n\tlg_prevbuckets = ckh->lg_curbuckets;\n\tlg_curcells = ckh->lg_curbuckets + LG_CKH_BUCKET_CELLS;\n\twhile (true) {\n\t\tsize_t usize;\n\n\t\tlg_curcells++;\n\t\tusize = sa2u(sizeof(ckhc_t) << lg_curcells, CACHELINE);\n\t\tif (usize == 0) {\n\t\t\tret = true;\n\t\t\tgoto label_return;\n\t\t}\n\t\ttab = (ckhc_t *)ipalloc(usize, CACHELINE, true);\n\t\tif (tab == NULL) {\n\t\t\tret = true;\n\t\t\tgoto label_return;\n\t\t}\n\t\t/* Swap in new table. */\n\t\tttab = ckh->tab;\n\t\tckh->tab = tab;\n\t\ttab = ttab;\n\t\tckh->lg_curbuckets = lg_curcells - LG_CKH_BUCKET_CELLS;\n\n\t\tif (ckh_rebuild(ckh, tab) == false) {\n\t\t\tidalloc(tab);\n\t\t\tbreak;\n\t\t}\n\n\t\t/* Rebuilding failed, so back out partially rebuilt table. */\n\t\tidalloc(ckh->tab);\n\t\tckh->tab = tab;\n\t\tckh->lg_curbuckets = lg_prevbuckets;\n\t}\n\n\tret = false;\nlabel_return:\n\treturn (ret);\n}\n\nstatic void\nckh_shrink(ckh_t *ckh)\n{\n\tckhc_t *tab, *ttab;\n\tsize_t lg_curcells, usize;\n\tunsigned lg_prevbuckets;\n\n\t/*\n\t * It is possible (though unlikely, given well behaved hashes) that the\n\t * table rebuild will fail.\n\t */\n\tlg_prevbuckets = ckh->lg_curbuckets;\n\tlg_curcells = ckh->lg_curbuckets + LG_CKH_BUCKET_CELLS - 1;\n\tusize = sa2u(sizeof(ckhc_t) << lg_curcells, CACHELINE);\n\tif (usize == 0)\n\t\treturn;\n\ttab = (ckhc_t *)ipalloc(usize, CACHELINE, true);\n\tif (tab == NULL) {\n\t\t/*\n\t\t * An OOM error isn't worth propagating, since it doesn't\n\t\t * prevent this or future operations from proceeding.\n\t\t */\n\t\treturn;\n\t}\n\t/* Swap in new table. */\n\tttab = ckh->tab;\n\tckh->tab = tab;\n\ttab = ttab;\n\tckh->lg_curbuckets = lg_curcells - LG_CKH_BUCKET_CELLS;\n\n\tif (ckh_rebuild(ckh, tab) == false) {\n\t\tidalloc(tab);\n#ifdef CKH_COUNT\n\t\tckh->nshrinks++;\n#endif\n\t\treturn;\n\t}\n\n\t/* Rebuilding failed, so back out partially rebuilt table. */\n\tidalloc(ckh->tab);\n\tckh->tab = tab;\n\tckh->lg_curbuckets = lg_prevbuckets;\n#ifdef CKH_COUNT\n\tckh->nshrinkfails++;\n#endif\n}\n\nbool\nckh_new(ckh_t *ckh, size_t minitems, ckh_hash_t *hash, ckh_keycomp_t *keycomp)\n{\n\tbool ret;\n\tsize_t mincells, usize;\n\tunsigned lg_mincells;\n\n\tassert(minitems > 0);\n\tassert(hash != NULL);\n\tassert(keycomp != NULL);\n\n#ifdef CKH_COUNT\n\tckh->ngrows = 0;\n\tckh->nshrinks = 0;\n\tckh->nshrinkfails = 0;\n\tckh->ninserts = 0;\n\tckh->nrelocs = 0;\n#endif\n\tckh->prng_state = 42; /* Value doesn't really matter. */\n\tckh->count = 0;\n\n\t/*\n\t * Find the minimum power of 2 that is large enough to fit aBaseCount\n\t * entries.  We are using (2+,2) cuckoo hashing, which has an expected\n\t * maximum load factor of at least ~0.86, so 0.75 is a conservative load\n\t * factor that will typically allow 2^aLgMinItems to fit without ever\n\t * growing the table.\n\t */\n\tassert(LG_CKH_BUCKET_CELLS > 0);\n\tmincells = ((minitems + (3 - (minitems % 3))) / 3) << 2;\n\tfor (lg_mincells = LG_CKH_BUCKET_CELLS;\n\t    (ZU(1) << lg_mincells) < mincells;\n\t    lg_mincells++)\n\t\t; /* Do nothing. */\n\tckh->lg_minbuckets = lg_mincells - LG_CKH_BUCKET_CELLS;\n\tckh->lg_curbuckets = lg_mincells - LG_CKH_BUCKET_CELLS;\n\tckh->hash = hash;\n\tckh->keycomp = keycomp;\n\n\tusize = sa2u(sizeof(ckhc_t) << lg_mincells, CACHELINE);\n\tif (usize == 0) {\n\t\tret = true;\n\t\tgoto label_return;\n\t}\n\tckh->tab = (ckhc_t *)ipalloc(usize, CACHELINE, true);\n\tif (ckh->tab == NULL) {\n\t\tret = true;\n\t\tgoto label_return;\n\t}\n\n\tret = false;\nlabel_return:\n\treturn (ret);\n}\n\nvoid\nckh_delete(ckh_t *ckh)\n{\n\n\tassert(ckh != NULL);\n\n#ifdef CKH_VERBOSE\n\tmalloc_printf(\n\t    \"%s(%p): ngrows: %\"PRIu64\", nshrinks: %\"PRIu64\",\"\n\t    \" nshrinkfails: %\"PRIu64\", ninserts: %\"PRIu64\",\"\n\t    \" nrelocs: %\"PRIu64\"\\n\", __func__, ckh,\n\t    (unsigned long long)ckh->ngrows,\n\t    (unsigned long long)ckh->nshrinks,\n\t    (unsigned long long)ckh->nshrinkfails,\n\t    (unsigned long long)ckh->ninserts,\n\t    (unsigned long long)ckh->nrelocs);\n#endif\n\n\tidalloc(ckh->tab);\n\tif (config_debug)\n\t\tmemset(ckh, 0x5a, sizeof(ckh_t));\n}\n\nsize_t\nckh_count(ckh_t *ckh)\n{\n\n\tassert(ckh != NULL);\n\n\treturn (ckh->count);\n}\n\nbool\nckh_iter(ckh_t *ckh, size_t *tabind, void **key, void **data)\n{\n\tsize_t i, ncells;\n\n\tfor (i = *tabind, ncells = (ZU(1) << (ckh->lg_curbuckets +\n\t    LG_CKH_BUCKET_CELLS)); i < ncells; i++) {\n\t\tif (ckh->tab[i].key != NULL) {\n\t\t\tif (key != NULL)\n\t\t\t\t*key = (void *)ckh->tab[i].key;\n\t\t\tif (data != NULL)\n\t\t\t\t*data = (void *)ckh->tab[i].data;\n\t\t\t*tabind = i + 1;\n\t\t\treturn (false);\n\t\t}\n\t}\n\n\treturn (true);\n}\n\nbool\nckh_insert(ckh_t *ckh, const void *key, const void *data)\n{\n\tbool ret;\n\n\tassert(ckh != NULL);\n\tassert(ckh_search(ckh, key, NULL, NULL));\n\n#ifdef CKH_COUNT\n\tckh->ninserts++;\n#endif\n\n\twhile (ckh_try_insert(ckh, &key, &data)) {\n\t\tif (ckh_grow(ckh)) {\n\t\t\tret = true;\n\t\t\tgoto label_return;\n\t\t}\n\t}\n\n\tret = false;\nlabel_return:\n\treturn (ret);\n}\n\nbool\nckh_remove(ckh_t *ckh, const void *searchkey, void **key, void **data)\n{\n\tsize_t cell;\n\n\tassert(ckh != NULL);\n\n\tcell = ckh_isearch(ckh, searchkey);\n\tif (cell != SIZE_T_MAX) {\n\t\tif (key != NULL)\n\t\t\t*key = (void *)ckh->tab[cell].key;\n\t\tif (data != NULL)\n\t\t\t*data = (void *)ckh->tab[cell].data;\n\t\tckh->tab[cell].key = NULL;\n\t\tckh->tab[cell].data = NULL; /* Not necessary. */\n\n\t\tckh->count--;\n\t\t/* Try to halve the table if it is less than 1/4 full. */\n\t\tif (ckh->count < (ZU(1) << (ckh->lg_curbuckets\n\t\t    + LG_CKH_BUCKET_CELLS - 2)) && ckh->lg_curbuckets\n\t\t    > ckh->lg_minbuckets) {\n\t\t\t/* Ignore error due to OOM. */\n\t\t\tckh_shrink(ckh);\n\t\t}\n\n\t\treturn (false);\n\t}\n\n\treturn (true);\n}\n\nbool\nckh_search(ckh_t *ckh, const void *searchkey, void **key, void **data)\n{\n\tsize_t cell;\n\n\tassert(ckh != NULL);\n\n\tcell = ckh_isearch(ckh, searchkey);\n\tif (cell != SIZE_T_MAX) {\n\t\tif (key != NULL)\n\t\t\t*key = (void *)ckh->tab[cell].key;\n\t\tif (data != NULL)\n\t\t\t*data = (void *)ckh->tab[cell].data;\n\t\treturn (false);\n\t}\n\n\treturn (true);\n}\n\nvoid\nckh_string_hash(const void *key, size_t r_hash[2])\n{\n\n\thash(key, strlen((const char *)key), 0x94122f33U, r_hash);\n}\n\nbool\nckh_string_keycomp(const void *k1, const void *k2)\n{\n\n    assert(k1 != NULL);\n    assert(k2 != NULL);\n\n    return (strcmp((char *)k1, (char *)k2) ? false : true);\n}\n\nvoid\nckh_pointer_hash(const void *key, size_t r_hash[2])\n{\n\tunion {\n\t\tconst void\t*v;\n\t\tsize_t\t\ti;\n\t} u;\n\n\tassert(sizeof(u.v) == sizeof(u.i));\n\tu.v = key;\n\thash(&u.i, sizeof(u.i), 0xd983396eU, r_hash);\n}\n\nbool\nckh_pointer_keycomp(const void *k1, const void *k2)\n{\n\n\treturn ((k1 == k2) ? true : false);\n}\n"
  },
  {
    "path": "extern/deprecated/redis-2.8.21/deps/jemalloc/src/ctl.c",
    "content": "#define\tJEMALLOC_CTL_C_\n#include \"jemalloc/internal/jemalloc_internal.h\"\n\n/******************************************************************************/\n/* Data. */\n\n/*\n * ctl_mtx protects the following:\n * - ctl_stats.*\n * - opt_prof_active\n */\nstatic malloc_mutex_t\tctl_mtx;\nstatic bool\t\tctl_initialized;\nstatic uint64_t\t\tctl_epoch;\nstatic ctl_stats_t\tctl_stats;\n\n/******************************************************************************/\n/* Helpers for named and indexed nodes. */\n\nstatic inline const ctl_named_node_t *\nctl_named_node(const ctl_node_t *node)\n{\n\n\treturn ((node->named) ? (const ctl_named_node_t *)node : NULL);\n}\n\nstatic inline const ctl_named_node_t *\nctl_named_children(const ctl_named_node_t *node, int index)\n{\n\tconst ctl_named_node_t *children = ctl_named_node(node->children);\n\n\treturn (children ? &children[index] : NULL);\n}\n\nstatic inline const ctl_indexed_node_t *\nctl_indexed_node(const ctl_node_t *node)\n{\n\n\treturn ((node->named == false) ? (const ctl_indexed_node_t *)node :\n\t    NULL);\n}\n\n/******************************************************************************/\n/* Function prototypes for non-inline static functions. */\n\n#define\tCTL_PROTO(n)\t\t\t\t\t\t\t\\\nstatic int\tn##_ctl(const size_t *mib, size_t miblen, void *oldp,\t\\\n    size_t *oldlenp, void *newp, size_t newlen);\n\n#define\tINDEX_PROTO(n)\t\t\t\t\t\t\t\\\nstatic const ctl_named_node_t\t*n##_index(const size_t *mib,\t\t\\\n    size_t miblen, size_t i);\n\nstatic bool\tctl_arena_init(ctl_arena_stats_t *astats);\nstatic void\tctl_arena_clear(ctl_arena_stats_t *astats);\nstatic void\tctl_arena_stats_amerge(ctl_arena_stats_t *cstats,\n    arena_t *arena);\nstatic void\tctl_arena_stats_smerge(ctl_arena_stats_t *sstats,\n    ctl_arena_stats_t *astats);\nstatic void\tctl_arena_refresh(arena_t *arena, unsigned i);\nstatic bool\tctl_grow(void);\nstatic void\tctl_refresh(void);\nstatic bool\tctl_init(void);\nstatic int\tctl_lookup(const char *name, ctl_node_t const **nodesp,\n    size_t *mibp, size_t *depthp);\n\nCTL_PROTO(version)\nCTL_PROTO(epoch)\nCTL_PROTO(thread_tcache_enabled)\nCTL_PROTO(thread_tcache_flush)\nCTL_PROTO(thread_arena)\nCTL_PROTO(thread_allocated)\nCTL_PROTO(thread_allocatedp)\nCTL_PROTO(thread_deallocated)\nCTL_PROTO(thread_deallocatedp)\nCTL_PROTO(config_debug)\nCTL_PROTO(config_dss)\nCTL_PROTO(config_fill)\nCTL_PROTO(config_lazy_lock)\nCTL_PROTO(config_mremap)\nCTL_PROTO(config_munmap)\nCTL_PROTO(config_prof)\nCTL_PROTO(config_prof_libgcc)\nCTL_PROTO(config_prof_libunwind)\nCTL_PROTO(config_stats)\nCTL_PROTO(config_tcache)\nCTL_PROTO(config_tls)\nCTL_PROTO(config_utrace)\nCTL_PROTO(config_valgrind)\nCTL_PROTO(config_xmalloc)\nCTL_PROTO(opt_abort)\nCTL_PROTO(opt_dss)\nCTL_PROTO(opt_lg_chunk)\nCTL_PROTO(opt_narenas)\nCTL_PROTO(opt_lg_dirty_mult)\nCTL_PROTO(opt_stats_print)\nCTL_PROTO(opt_junk)\nCTL_PROTO(opt_zero)\nCTL_PROTO(opt_quarantine)\nCTL_PROTO(opt_redzone)\nCTL_PROTO(opt_utrace)\nCTL_PROTO(opt_valgrind)\nCTL_PROTO(opt_xmalloc)\nCTL_PROTO(opt_tcache)\nCTL_PROTO(opt_lg_tcache_max)\nCTL_PROTO(opt_prof)\nCTL_PROTO(opt_prof_prefix)\nCTL_PROTO(opt_prof_active)\nCTL_PROTO(opt_lg_prof_sample)\nCTL_PROTO(opt_lg_prof_interval)\nCTL_PROTO(opt_prof_gdump)\nCTL_PROTO(opt_prof_final)\nCTL_PROTO(opt_prof_leak)\nCTL_PROTO(opt_prof_accum)\nCTL_PROTO(arena_i_purge)\nstatic void\tarena_purge(unsigned arena_ind);\nCTL_PROTO(arena_i_dss)\nINDEX_PROTO(arena_i)\nCTL_PROTO(arenas_bin_i_size)\nCTL_PROTO(arenas_bin_i_nregs)\nCTL_PROTO(arenas_bin_i_run_size)\nINDEX_PROTO(arenas_bin_i)\nCTL_PROTO(arenas_lrun_i_size)\nINDEX_PROTO(arenas_lrun_i)\nCTL_PROTO(arenas_narenas)\nCTL_PROTO(arenas_initialized)\nCTL_PROTO(arenas_quantum)\nCTL_PROTO(arenas_page)\nCTL_PROTO(arenas_tcache_max)\nCTL_PROTO(arenas_nbins)\nCTL_PROTO(arenas_nhbins)\nCTL_PROTO(arenas_nlruns)\nCTL_PROTO(arenas_purge)\nCTL_PROTO(arenas_extend)\nCTL_PROTO(prof_active)\nCTL_PROTO(prof_dump)\nCTL_PROTO(prof_interval)\nCTL_PROTO(stats_chunks_current)\nCTL_PROTO(stats_chunks_total)\nCTL_PROTO(stats_chunks_high)\nCTL_PROTO(stats_huge_allocated)\nCTL_PROTO(stats_huge_nmalloc)\nCTL_PROTO(stats_huge_ndalloc)\nCTL_PROTO(stats_arenas_i_small_allocated)\nCTL_PROTO(stats_arenas_i_small_nmalloc)\nCTL_PROTO(stats_arenas_i_small_ndalloc)\nCTL_PROTO(stats_arenas_i_small_nrequests)\nCTL_PROTO(stats_arenas_i_large_allocated)\nCTL_PROTO(stats_arenas_i_large_nmalloc)\nCTL_PROTO(stats_arenas_i_large_ndalloc)\nCTL_PROTO(stats_arenas_i_large_nrequests)\nCTL_PROTO(stats_arenas_i_bins_j_allocated)\nCTL_PROTO(stats_arenas_i_bins_j_nmalloc)\nCTL_PROTO(stats_arenas_i_bins_j_ndalloc)\nCTL_PROTO(stats_arenas_i_bins_j_nrequests)\nCTL_PROTO(stats_arenas_i_bins_j_nfills)\nCTL_PROTO(stats_arenas_i_bins_j_nflushes)\nCTL_PROTO(stats_arenas_i_bins_j_nruns)\nCTL_PROTO(stats_arenas_i_bins_j_nreruns)\nCTL_PROTO(stats_arenas_i_bins_j_curruns)\nINDEX_PROTO(stats_arenas_i_bins_j)\nCTL_PROTO(stats_arenas_i_lruns_j_nmalloc)\nCTL_PROTO(stats_arenas_i_lruns_j_ndalloc)\nCTL_PROTO(stats_arenas_i_lruns_j_nrequests)\nCTL_PROTO(stats_arenas_i_lruns_j_curruns)\nINDEX_PROTO(stats_arenas_i_lruns_j)\nCTL_PROTO(stats_arenas_i_nthreads)\nCTL_PROTO(stats_arenas_i_dss)\nCTL_PROTO(stats_arenas_i_pactive)\nCTL_PROTO(stats_arenas_i_pdirty)\nCTL_PROTO(stats_arenas_i_mapped)\nCTL_PROTO(stats_arenas_i_npurge)\nCTL_PROTO(stats_arenas_i_nmadvise)\nCTL_PROTO(stats_arenas_i_purged)\nINDEX_PROTO(stats_arenas_i)\nCTL_PROTO(stats_cactive)\nCTL_PROTO(stats_allocated)\nCTL_PROTO(stats_active)\nCTL_PROTO(stats_mapped)\n\n/******************************************************************************/\n/* mallctl tree. */\n\n/* Maximum tree depth. */\n#define\tCTL_MAX_DEPTH\t6\n\n#define\tNAME(n)\t{true},\tn\n#define\tCHILD(t, c)\t\t\t\t\t\t\t\\\n\tsizeof(c##_node) / sizeof(ctl_##t##_node_t),\t\t\t\\\n\t(ctl_node_t *)c##_node,\t\t\t\t\t\t\\\n\tNULL\n#define\tCTL(c)\t0, NULL, c##_ctl\n\n/*\n * Only handles internal indexed nodes, since there are currently no external\n * ones.\n */\n#define\tINDEX(i)\t{false},\ti##_index\n\nstatic const ctl_named_node_t\ttcache_node[] = {\n\t{NAME(\"enabled\"),\tCTL(thread_tcache_enabled)},\n\t{NAME(\"flush\"),\t\tCTL(thread_tcache_flush)}\n};\n\nstatic const ctl_named_node_t\tthread_node[] = {\n\t{NAME(\"arena\"),\t\tCTL(thread_arena)},\n\t{NAME(\"allocated\"),\tCTL(thread_allocated)},\n\t{NAME(\"allocatedp\"),\tCTL(thread_allocatedp)},\n\t{NAME(\"deallocated\"),\tCTL(thread_deallocated)},\n\t{NAME(\"deallocatedp\"),\tCTL(thread_deallocatedp)},\n\t{NAME(\"tcache\"),\tCHILD(named, tcache)}\n};\n\nstatic const ctl_named_node_t\tconfig_node[] = {\n\t{NAME(\"debug\"),\t\t\tCTL(config_debug)},\n\t{NAME(\"dss\"),\t\t\tCTL(config_dss)},\n\t{NAME(\"fill\"),\t\t\tCTL(config_fill)},\n\t{NAME(\"lazy_lock\"),\t\tCTL(config_lazy_lock)},\n\t{NAME(\"mremap\"),\t\tCTL(config_mremap)},\n\t{NAME(\"munmap\"),\t\tCTL(config_munmap)},\n\t{NAME(\"prof\"),\t\t\tCTL(config_prof)},\n\t{NAME(\"prof_libgcc\"),\t\tCTL(config_prof_libgcc)},\n\t{NAME(\"prof_libunwind\"),\tCTL(config_prof_libunwind)},\n\t{NAME(\"stats\"),\t\t\tCTL(config_stats)},\n\t{NAME(\"tcache\"),\t\tCTL(config_tcache)},\n\t{NAME(\"tls\"),\t\t\tCTL(config_tls)},\n\t{NAME(\"utrace\"),\t\tCTL(config_utrace)},\n\t{NAME(\"valgrind\"),\t\tCTL(config_valgrind)},\n\t{NAME(\"xmalloc\"),\t\tCTL(config_xmalloc)}\n};\n\nstatic const ctl_named_node_t opt_node[] = {\n\t{NAME(\"abort\"),\t\t\tCTL(opt_abort)},\n\t{NAME(\"dss\"),\t\t\tCTL(opt_dss)},\n\t{NAME(\"lg_chunk\"),\t\tCTL(opt_lg_chunk)},\n\t{NAME(\"narenas\"),\t\tCTL(opt_narenas)},\n\t{NAME(\"lg_dirty_mult\"),\t\tCTL(opt_lg_dirty_mult)},\n\t{NAME(\"stats_print\"),\t\tCTL(opt_stats_print)},\n\t{NAME(\"junk\"),\t\t\tCTL(opt_junk)},\n\t{NAME(\"zero\"),\t\t\tCTL(opt_zero)},\n\t{NAME(\"quarantine\"),\t\tCTL(opt_quarantine)},\n\t{NAME(\"redzone\"),\t\tCTL(opt_redzone)},\n\t{NAME(\"utrace\"),\t\tCTL(opt_utrace)},\n\t{NAME(\"valgrind\"),\t\tCTL(opt_valgrind)},\n\t{NAME(\"xmalloc\"),\t\tCTL(opt_xmalloc)},\n\t{NAME(\"tcache\"),\t\tCTL(opt_tcache)},\n\t{NAME(\"lg_tcache_max\"),\t\tCTL(opt_lg_tcache_max)},\n\t{NAME(\"prof\"),\t\t\tCTL(opt_prof)},\n\t{NAME(\"prof_prefix\"),\t\tCTL(opt_prof_prefix)},\n\t{NAME(\"prof_active\"),\t\tCTL(opt_prof_active)},\n\t{NAME(\"lg_prof_sample\"),\tCTL(opt_lg_prof_sample)},\n\t{NAME(\"lg_prof_interval\"),\tCTL(opt_lg_prof_interval)},\n\t{NAME(\"prof_gdump\"),\t\tCTL(opt_prof_gdump)},\n\t{NAME(\"prof_final\"),\t\tCTL(opt_prof_final)},\n\t{NAME(\"prof_leak\"),\t\tCTL(opt_prof_leak)},\n\t{NAME(\"prof_accum\"),\t\tCTL(opt_prof_accum)}\n};\n\nstatic const ctl_named_node_t arena_i_node[] = {\n\t{NAME(\"purge\"),\t\t\tCTL(arena_i_purge)},\n\t{NAME(\"dss\"),\t\t\tCTL(arena_i_dss)}\n};\nstatic const ctl_named_node_t super_arena_i_node[] = {\n\t{NAME(\"\"),\t\t\tCHILD(named, arena_i)}\n};\n\nstatic const ctl_indexed_node_t arena_node[] = {\n\t{INDEX(arena_i)}\n};\n\nstatic const ctl_named_node_t arenas_bin_i_node[] = {\n\t{NAME(\"size\"),\t\t\tCTL(arenas_bin_i_size)},\n\t{NAME(\"nregs\"),\t\t\tCTL(arenas_bin_i_nregs)},\n\t{NAME(\"run_size\"),\t\tCTL(arenas_bin_i_run_size)}\n};\nstatic const ctl_named_node_t super_arenas_bin_i_node[] = {\n\t{NAME(\"\"),\t\t\tCHILD(named, arenas_bin_i)}\n};\n\nstatic const ctl_indexed_node_t arenas_bin_node[] = {\n\t{INDEX(arenas_bin_i)}\n};\n\nstatic const ctl_named_node_t arenas_lrun_i_node[] = {\n\t{NAME(\"size\"),\t\t\tCTL(arenas_lrun_i_size)}\n};\nstatic const ctl_named_node_t super_arenas_lrun_i_node[] = {\n\t{NAME(\"\"),\t\t\tCHILD(named, arenas_lrun_i)}\n};\n\nstatic const ctl_indexed_node_t arenas_lrun_node[] = {\n\t{INDEX(arenas_lrun_i)}\n};\n\nstatic const ctl_named_node_t arenas_node[] = {\n\t{NAME(\"narenas\"),\t\tCTL(arenas_narenas)},\n\t{NAME(\"initialized\"),\t\tCTL(arenas_initialized)},\n\t{NAME(\"quantum\"),\t\tCTL(arenas_quantum)},\n\t{NAME(\"page\"),\t\t\tCTL(arenas_page)},\n\t{NAME(\"tcache_max\"),\t\tCTL(arenas_tcache_max)},\n\t{NAME(\"nbins\"),\t\t\tCTL(arenas_nbins)},\n\t{NAME(\"nhbins\"),\t\tCTL(arenas_nhbins)},\n\t{NAME(\"bin\"),\t\t\tCHILD(indexed, arenas_bin)},\n\t{NAME(\"nlruns\"),\t\tCTL(arenas_nlruns)},\n\t{NAME(\"lrun\"),\t\t\tCHILD(indexed, arenas_lrun)},\n\t{NAME(\"purge\"),\t\t\tCTL(arenas_purge)},\n\t{NAME(\"extend\"),\t\tCTL(arenas_extend)}\n};\n\nstatic const ctl_named_node_t\tprof_node[] = {\n\t{NAME(\"active\"),\tCTL(prof_active)},\n\t{NAME(\"dump\"),\t\tCTL(prof_dump)},\n\t{NAME(\"interval\"),\tCTL(prof_interval)}\n};\n\nstatic const ctl_named_node_t stats_chunks_node[] = {\n\t{NAME(\"current\"),\t\tCTL(stats_chunks_current)},\n\t{NAME(\"total\"),\t\t\tCTL(stats_chunks_total)},\n\t{NAME(\"high\"),\t\t\tCTL(stats_chunks_high)}\n};\n\nstatic const ctl_named_node_t stats_huge_node[] = {\n\t{NAME(\"allocated\"),\t\tCTL(stats_huge_allocated)},\n\t{NAME(\"nmalloc\"),\t\tCTL(stats_huge_nmalloc)},\n\t{NAME(\"ndalloc\"),\t\tCTL(stats_huge_ndalloc)}\n};\n\nstatic const ctl_named_node_t stats_arenas_i_small_node[] = {\n\t{NAME(\"allocated\"),\t\tCTL(stats_arenas_i_small_allocated)},\n\t{NAME(\"nmalloc\"),\t\tCTL(stats_arenas_i_small_nmalloc)},\n\t{NAME(\"ndalloc\"),\t\tCTL(stats_arenas_i_small_ndalloc)},\n\t{NAME(\"nrequests\"),\t\tCTL(stats_arenas_i_small_nrequests)}\n};\n\nstatic const ctl_named_node_t stats_arenas_i_large_node[] = {\n\t{NAME(\"allocated\"),\t\tCTL(stats_arenas_i_large_allocated)},\n\t{NAME(\"nmalloc\"),\t\tCTL(stats_arenas_i_large_nmalloc)},\n\t{NAME(\"ndalloc\"),\t\tCTL(stats_arenas_i_large_ndalloc)},\n\t{NAME(\"nrequests\"),\t\tCTL(stats_arenas_i_large_nrequests)}\n};\n\nstatic const ctl_named_node_t stats_arenas_i_bins_j_node[] = {\n\t{NAME(\"allocated\"),\t\tCTL(stats_arenas_i_bins_j_allocated)},\n\t{NAME(\"nmalloc\"),\t\tCTL(stats_arenas_i_bins_j_nmalloc)},\n\t{NAME(\"ndalloc\"),\t\tCTL(stats_arenas_i_bins_j_ndalloc)},\n\t{NAME(\"nrequests\"),\t\tCTL(stats_arenas_i_bins_j_nrequests)},\n\t{NAME(\"nfills\"),\t\tCTL(stats_arenas_i_bins_j_nfills)},\n\t{NAME(\"nflushes\"),\t\tCTL(stats_arenas_i_bins_j_nflushes)},\n\t{NAME(\"nruns\"),\t\t\tCTL(stats_arenas_i_bins_j_nruns)},\n\t{NAME(\"nreruns\"),\t\tCTL(stats_arenas_i_bins_j_nreruns)},\n\t{NAME(\"curruns\"),\t\tCTL(stats_arenas_i_bins_j_curruns)}\n};\nstatic const ctl_named_node_t super_stats_arenas_i_bins_j_node[] = {\n\t{NAME(\"\"),\t\t\tCHILD(named, stats_arenas_i_bins_j)}\n};\n\nstatic const ctl_indexed_node_t stats_arenas_i_bins_node[] = {\n\t{INDEX(stats_arenas_i_bins_j)}\n};\n\nstatic const ctl_named_node_t stats_arenas_i_lruns_j_node[] = {\n\t{NAME(\"nmalloc\"),\t\tCTL(stats_arenas_i_lruns_j_nmalloc)},\n\t{NAME(\"ndalloc\"),\t\tCTL(stats_arenas_i_lruns_j_ndalloc)},\n\t{NAME(\"nrequests\"),\t\tCTL(stats_arenas_i_lruns_j_nrequests)},\n\t{NAME(\"curruns\"),\t\tCTL(stats_arenas_i_lruns_j_curruns)}\n};\nstatic const ctl_named_node_t super_stats_arenas_i_lruns_j_node[] = {\n\t{NAME(\"\"),\t\t\tCHILD(named, stats_arenas_i_lruns_j)}\n};\n\nstatic const ctl_indexed_node_t stats_arenas_i_lruns_node[] = {\n\t{INDEX(stats_arenas_i_lruns_j)}\n};\n\nstatic const ctl_named_node_t stats_arenas_i_node[] = {\n\t{NAME(\"nthreads\"),\t\tCTL(stats_arenas_i_nthreads)},\n\t{NAME(\"dss\"),\t\t\tCTL(stats_arenas_i_dss)},\n\t{NAME(\"pactive\"),\t\tCTL(stats_arenas_i_pactive)},\n\t{NAME(\"pdirty\"),\t\tCTL(stats_arenas_i_pdirty)},\n\t{NAME(\"mapped\"),\t\tCTL(stats_arenas_i_mapped)},\n\t{NAME(\"npurge\"),\t\tCTL(stats_arenas_i_npurge)},\n\t{NAME(\"nmadvise\"),\t\tCTL(stats_arenas_i_nmadvise)},\n\t{NAME(\"purged\"),\t\tCTL(stats_arenas_i_purged)},\n\t{NAME(\"small\"),\t\t\tCHILD(named, stats_arenas_i_small)},\n\t{NAME(\"large\"),\t\t\tCHILD(named, stats_arenas_i_large)},\n\t{NAME(\"bins\"),\t\t\tCHILD(indexed, stats_arenas_i_bins)},\n\t{NAME(\"lruns\"),\t\t\tCHILD(indexed, stats_arenas_i_lruns)}\n};\nstatic const ctl_named_node_t super_stats_arenas_i_node[] = {\n\t{NAME(\"\"),\t\t\tCHILD(named, stats_arenas_i)}\n};\n\nstatic const ctl_indexed_node_t stats_arenas_node[] = {\n\t{INDEX(stats_arenas_i)}\n};\n\nstatic const ctl_named_node_t stats_node[] = {\n\t{NAME(\"cactive\"),\t\tCTL(stats_cactive)},\n\t{NAME(\"allocated\"),\t\tCTL(stats_allocated)},\n\t{NAME(\"active\"),\t\tCTL(stats_active)},\n\t{NAME(\"mapped\"),\t\tCTL(stats_mapped)},\n\t{NAME(\"chunks\"),\t\tCHILD(named, stats_chunks)},\n\t{NAME(\"huge\"),\t\t\tCHILD(named, stats_huge)},\n\t{NAME(\"arenas\"),\t\tCHILD(indexed, stats_arenas)}\n};\n\nstatic const ctl_named_node_t\troot_node[] = {\n\t{NAME(\"version\"),\tCTL(version)},\n\t{NAME(\"epoch\"),\t\tCTL(epoch)},\n\t{NAME(\"thread\"),\tCHILD(named, thread)},\n\t{NAME(\"config\"),\tCHILD(named, config)},\n\t{NAME(\"opt\"),\t\tCHILD(named, opt)},\n\t{NAME(\"arena\"),\t\tCHILD(indexed, arena)},\n\t{NAME(\"arenas\"),\tCHILD(named, arenas)},\n\t{NAME(\"prof\"),\t\tCHILD(named, prof)},\n\t{NAME(\"stats\"),\t\tCHILD(named, stats)}\n};\nstatic const ctl_named_node_t super_root_node[] = {\n\t{NAME(\"\"),\t\tCHILD(named, root)}\n};\n\n#undef NAME\n#undef CHILD\n#undef CTL\n#undef INDEX\n\n/******************************************************************************/\n\nstatic bool\nctl_arena_init(ctl_arena_stats_t *astats)\n{\n\n\tif (astats->lstats == NULL) {\n\t\tastats->lstats = (malloc_large_stats_t *)base_alloc(nlclasses *\n\t\t    sizeof(malloc_large_stats_t));\n\t\tif (astats->lstats == NULL)\n\t\t\treturn (true);\n\t}\n\n\treturn (false);\n}\n\nstatic void\nctl_arena_clear(ctl_arena_stats_t *astats)\n{\n\n\tastats->dss = dss_prec_names[dss_prec_limit];\n\tastats->pactive = 0;\n\tastats->pdirty = 0;\n\tif (config_stats) {\n\t\tmemset(&astats->astats, 0, sizeof(arena_stats_t));\n\t\tastats->allocated_small = 0;\n\t\tastats->nmalloc_small = 0;\n\t\tastats->ndalloc_small = 0;\n\t\tastats->nrequests_small = 0;\n\t\tmemset(astats->bstats, 0, NBINS * sizeof(malloc_bin_stats_t));\n\t\tmemset(astats->lstats, 0, nlclasses *\n\t\t    sizeof(malloc_large_stats_t));\n\t}\n}\n\nstatic void\nctl_arena_stats_amerge(ctl_arena_stats_t *cstats, arena_t *arena)\n{\n\tunsigned i;\n\n\tarena_stats_merge(arena, &cstats->dss, &cstats->pactive,\n\t    &cstats->pdirty, &cstats->astats, cstats->bstats, cstats->lstats);\n\n\tfor (i = 0; i < NBINS; i++) {\n\t\tcstats->allocated_small += cstats->bstats[i].allocated;\n\t\tcstats->nmalloc_small += cstats->bstats[i].nmalloc;\n\t\tcstats->ndalloc_small += cstats->bstats[i].ndalloc;\n\t\tcstats->nrequests_small += cstats->bstats[i].nrequests;\n\t}\n}\n\nstatic void\nctl_arena_stats_smerge(ctl_arena_stats_t *sstats, ctl_arena_stats_t *astats)\n{\n\tunsigned i;\n\n\tsstats->pactive += astats->pactive;\n\tsstats->pdirty += astats->pdirty;\n\n\tsstats->astats.mapped += astats->astats.mapped;\n\tsstats->astats.npurge += astats->astats.npurge;\n\tsstats->astats.nmadvise += astats->astats.nmadvise;\n\tsstats->astats.purged += astats->astats.purged;\n\n\tsstats->allocated_small += astats->allocated_small;\n\tsstats->nmalloc_small += astats->nmalloc_small;\n\tsstats->ndalloc_small += astats->ndalloc_small;\n\tsstats->nrequests_small += astats->nrequests_small;\n\n\tsstats->astats.allocated_large += astats->astats.allocated_large;\n\tsstats->astats.nmalloc_large += astats->astats.nmalloc_large;\n\tsstats->astats.ndalloc_large += astats->astats.ndalloc_large;\n\tsstats->astats.nrequests_large += astats->astats.nrequests_large;\n\n\tfor (i = 0; i < nlclasses; i++) {\n\t\tsstats->lstats[i].nmalloc += astats->lstats[i].nmalloc;\n\t\tsstats->lstats[i].ndalloc += astats->lstats[i].ndalloc;\n\t\tsstats->lstats[i].nrequests += astats->lstats[i].nrequests;\n\t\tsstats->lstats[i].curruns += astats->lstats[i].curruns;\n\t}\n\n\tfor (i = 0; i < NBINS; i++) {\n\t\tsstats->bstats[i].allocated += astats->bstats[i].allocated;\n\t\tsstats->bstats[i].nmalloc += astats->bstats[i].nmalloc;\n\t\tsstats->bstats[i].ndalloc += astats->bstats[i].ndalloc;\n\t\tsstats->bstats[i].nrequests += astats->bstats[i].nrequests;\n\t\tif (config_tcache) {\n\t\t\tsstats->bstats[i].nfills += astats->bstats[i].nfills;\n\t\t\tsstats->bstats[i].nflushes +=\n\t\t\t    astats->bstats[i].nflushes;\n\t\t}\n\t\tsstats->bstats[i].nruns += astats->bstats[i].nruns;\n\t\tsstats->bstats[i].reruns += astats->bstats[i].reruns;\n\t\tsstats->bstats[i].curruns += astats->bstats[i].curruns;\n\t}\n}\n\nstatic void\nctl_arena_refresh(arena_t *arena, unsigned i)\n{\n\tctl_arena_stats_t *astats = &ctl_stats.arenas[i];\n\tctl_arena_stats_t *sstats = &ctl_stats.arenas[ctl_stats.narenas];\n\n\tctl_arena_clear(astats);\n\n\tsstats->nthreads += astats->nthreads;\n\tif (config_stats) {\n\t\tctl_arena_stats_amerge(astats, arena);\n\t\t/* Merge into sum stats as well. */\n\t\tctl_arena_stats_smerge(sstats, astats);\n\t} else {\n\t\tastats->pactive += arena->nactive;\n\t\tastats->pdirty += arena->ndirty;\n\t\t/* Merge into sum stats as well. */\n\t\tsstats->pactive += arena->nactive;\n\t\tsstats->pdirty += arena->ndirty;\n\t}\n}\n\nstatic bool\nctl_grow(void)\n{\n\tctl_arena_stats_t *astats;\n\tarena_t **tarenas;\n\n\t/* Allocate extended arena stats and arenas arrays. */\n\tastats = (ctl_arena_stats_t *)imalloc((ctl_stats.narenas + 2) *\n\t    sizeof(ctl_arena_stats_t));\n\tif (astats == NULL)\n\t\treturn (true);\n\ttarenas = (arena_t **)imalloc((ctl_stats.narenas + 1) *\n\t    sizeof(arena_t *));\n\tif (tarenas == NULL) {\n\t\tidalloc(astats);\n\t\treturn (true);\n\t}\n\n\t/* Initialize the new astats element. */\n\tmemcpy(astats, ctl_stats.arenas, (ctl_stats.narenas + 1) *\n\t    sizeof(ctl_arena_stats_t));\n\tmemset(&astats[ctl_stats.narenas + 1], 0, sizeof(ctl_arena_stats_t));\n\tif (ctl_arena_init(&astats[ctl_stats.narenas + 1])) {\n\t\tidalloc(tarenas);\n\t\tidalloc(astats);\n\t\treturn (true);\n\t}\n\t/* Swap merged stats to their new location. */\n\t{\n\t\tctl_arena_stats_t tstats;\n\t\tmemcpy(&tstats, &astats[ctl_stats.narenas],\n\t\t    sizeof(ctl_arena_stats_t));\n\t\tmemcpy(&astats[ctl_stats.narenas],\n\t\t    &astats[ctl_stats.narenas + 1], sizeof(ctl_arena_stats_t));\n\t\tmemcpy(&astats[ctl_stats.narenas + 1], &tstats,\n\t\t    sizeof(ctl_arena_stats_t));\n\t}\n\t/* Initialize the new arenas element. */\n\ttarenas[ctl_stats.narenas] = NULL;\n\t{\n\t\tarena_t **arenas_old = arenas;\n\t\t/*\n\t\t * Swap extended arenas array into place.  Although ctl_mtx\n\t\t * protects this function from other threads extending the\n\t\t * array, it does not protect from other threads mutating it\n\t\t * (i.e. initializing arenas and setting array elements to\n\t\t * point to them).  Therefore, array copying must happen under\n\t\t * the protection of arenas_lock.\n\t\t */\n\t\tmalloc_mutex_lock(&arenas_lock);\n\t\tarenas = tarenas;\n\t\tmemcpy(arenas, arenas_old, ctl_stats.narenas *\n\t\t    sizeof(arena_t *));\n\t\tnarenas_total++;\n\t\tarenas_extend(narenas_total - 1);\n\t\tmalloc_mutex_unlock(&arenas_lock);\n\t\t/*\n\t\t * Deallocate arenas_old only if it came from imalloc() (not\n\t\t * base_alloc()).\n\t\t */\n\t\tif (ctl_stats.narenas != narenas_auto)\n\t\t\tidalloc(arenas_old);\n\t}\n\tctl_stats.arenas = astats;\n\tctl_stats.narenas++;\n\n\treturn (false);\n}\n\nstatic void\nctl_refresh(void)\n{\n\tunsigned i;\n\tVARIABLE_ARRAY(arena_t *, tarenas, ctl_stats.narenas);\n\n\tif (config_stats) {\n\t\tmalloc_mutex_lock(&chunks_mtx);\n\t\tctl_stats.chunks.current = stats_chunks.curchunks;\n\t\tctl_stats.chunks.total = stats_chunks.nchunks;\n\t\tctl_stats.chunks.high = stats_chunks.highchunks;\n\t\tmalloc_mutex_unlock(&chunks_mtx);\n\n\t\tmalloc_mutex_lock(&huge_mtx);\n\t\tctl_stats.huge.allocated = huge_allocated;\n\t\tctl_stats.huge.nmalloc = huge_nmalloc;\n\t\tctl_stats.huge.ndalloc = huge_ndalloc;\n\t\tmalloc_mutex_unlock(&huge_mtx);\n\t}\n\n\t/*\n\t * Clear sum stats, since they will be merged into by\n\t * ctl_arena_refresh().\n\t */\n\tctl_stats.arenas[ctl_stats.narenas].nthreads = 0;\n\tctl_arena_clear(&ctl_stats.arenas[ctl_stats.narenas]);\n\n\tmalloc_mutex_lock(&arenas_lock);\n\tmemcpy(tarenas, arenas, sizeof(arena_t *) * ctl_stats.narenas);\n\tfor (i = 0; i < ctl_stats.narenas; i++) {\n\t\tif (arenas[i] != NULL)\n\t\t\tctl_stats.arenas[i].nthreads = arenas[i]->nthreads;\n\t\telse\n\t\t\tctl_stats.arenas[i].nthreads = 0;\n\t}\n\tmalloc_mutex_unlock(&arenas_lock);\n\tfor (i = 0; i < ctl_stats.narenas; i++) {\n\t\tbool initialized = (tarenas[i] != NULL);\n\n\t\tctl_stats.arenas[i].initialized = initialized;\n\t\tif (initialized)\n\t\t\tctl_arena_refresh(tarenas[i], i);\n\t}\n\n\tif (config_stats) {\n\t\tctl_stats.allocated =\n\t\t    ctl_stats.arenas[ctl_stats.narenas].allocated_small\n\t\t    + ctl_stats.arenas[ctl_stats.narenas].astats.allocated_large\n\t\t    + ctl_stats.huge.allocated;\n\t\tctl_stats.active =\n\t\t    (ctl_stats.arenas[ctl_stats.narenas].pactive << LG_PAGE)\n\t\t    + ctl_stats.huge.allocated;\n\t\tctl_stats.mapped = (ctl_stats.chunks.current << opt_lg_chunk);\n\t}\n\n\tctl_epoch++;\n}\n\nstatic bool\nctl_init(void)\n{\n\tbool ret;\n\n\tmalloc_mutex_lock(&ctl_mtx);\n\tif (ctl_initialized == false) {\n\t\t/*\n\t\t * Allocate space for one extra arena stats element, which\n\t\t * contains summed stats across all arenas.\n\t\t */\n\t\tassert(narenas_auto == narenas_total_get());\n\t\tctl_stats.narenas = narenas_auto;\n\t\tctl_stats.arenas = (ctl_arena_stats_t *)base_alloc(\n\t\t    (ctl_stats.narenas + 1) * sizeof(ctl_arena_stats_t));\n\t\tif (ctl_stats.arenas == NULL) {\n\t\t\tret = true;\n\t\t\tgoto label_return;\n\t\t}\n\t\tmemset(ctl_stats.arenas, 0, (ctl_stats.narenas + 1) *\n\t\t    sizeof(ctl_arena_stats_t));\n\n\t\t/*\n\t\t * Initialize all stats structures, regardless of whether they\n\t\t * ever get used.  Lazy initialization would allow errors to\n\t\t * cause inconsistent state to be viewable by the application.\n\t\t */\n\t\tif (config_stats) {\n\t\t\tunsigned i;\n\t\t\tfor (i = 0; i <= ctl_stats.narenas; i++) {\n\t\t\t\tif (ctl_arena_init(&ctl_stats.arenas[i])) {\n\t\t\t\t\tret = true;\n\t\t\t\t\tgoto label_return;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tctl_stats.arenas[ctl_stats.narenas].initialized = true;\n\n\t\tctl_epoch = 0;\n\t\tctl_refresh();\n\t\tctl_initialized = true;\n\t}\n\n\tret = false;\nlabel_return:\n\tmalloc_mutex_unlock(&ctl_mtx);\n\treturn (ret);\n}\n\nstatic int\nctl_lookup(const char *name, ctl_node_t const **nodesp, size_t *mibp,\n    size_t *depthp)\n{\n\tint ret;\n\tconst char *elm, *tdot, *dot;\n\tsize_t elen, i, j;\n\tconst ctl_named_node_t *node;\n\n\telm = name;\n\t/* Equivalent to strchrnul(). */\n\tdot = ((tdot = strchr(elm, '.')) != NULL) ? tdot : strchr(elm, '\\0');\n\telen = (size_t)((uintptr_t)dot - (uintptr_t)elm);\n\tif (elen == 0) {\n\t\tret = ENOENT;\n\t\tgoto label_return;\n\t}\n\tnode = super_root_node;\n\tfor (i = 0; i < *depthp; i++) {\n\t\tassert(node);\n\t\tassert(node->nchildren > 0);\n\t\tif (ctl_named_node(node->children) != NULL) {\n\t\t\tconst ctl_named_node_t *pnode = node;\n\n\t\t\t/* Children are named. */\n\t\t\tfor (j = 0; j < node->nchildren; j++) {\n\t\t\t\tconst ctl_named_node_t *child =\n\t\t\t\t    ctl_named_children(node, j);\n\t\t\t\tif (strlen(child->name) == elen &&\n\t\t\t\t    strncmp(elm, child->name, elen) == 0) {\n\t\t\t\t\tnode = child;\n\t\t\t\t\tif (nodesp != NULL)\n\t\t\t\t\t\tnodesp[i] =\n\t\t\t\t\t\t    (const ctl_node_t *)node;\n\t\t\t\t\tmibp[i] = j;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (node == pnode) {\n\t\t\t\tret = ENOENT;\n\t\t\t\tgoto label_return;\n\t\t\t}\n\t\t} else {\n\t\t\tuintmax_t index;\n\t\t\tconst ctl_indexed_node_t *inode;\n\n\t\t\t/* Children are indexed. */\n\t\t\tindex = malloc_strtoumax(elm, NULL, 10);\n\t\t\tif (index == UINTMAX_MAX || index > SIZE_T_MAX) {\n\t\t\t\tret = ENOENT;\n\t\t\t\tgoto label_return;\n\t\t\t}\n\n\t\t\tinode = ctl_indexed_node(node->children);\n\t\t\tnode = inode->index(mibp, *depthp, (size_t)index);\n\t\t\tif (node == NULL) {\n\t\t\t\tret = ENOENT;\n\t\t\t\tgoto label_return;\n\t\t\t}\n\n\t\t\tif (nodesp != NULL)\n\t\t\t\tnodesp[i] = (const ctl_node_t *)node;\n\t\t\tmibp[i] = (size_t)index;\n\t\t}\n\n\t\tif (node->ctl != NULL) {\n\t\t\t/* Terminal node. */\n\t\t\tif (*dot != '\\0') {\n\t\t\t\t/*\n\t\t\t\t * The name contains more elements than are\n\t\t\t\t * in this path through the tree.\n\t\t\t\t */\n\t\t\t\tret = ENOENT;\n\t\t\t\tgoto label_return;\n\t\t\t}\n\t\t\t/* Complete lookup successful. */\n\t\t\t*depthp = i + 1;\n\t\t\tbreak;\n\t\t}\n\n\t\t/* Update elm. */\n\t\tif (*dot == '\\0') {\n\t\t\t/* No more elements. */\n\t\t\tret = ENOENT;\n\t\t\tgoto label_return;\n\t\t}\n\t\telm = &dot[1];\n\t\tdot = ((tdot = strchr(elm, '.')) != NULL) ? tdot :\n\t\t    strchr(elm, '\\0');\n\t\telen = (size_t)((uintptr_t)dot - (uintptr_t)elm);\n\t}\n\n\tret = 0;\nlabel_return:\n\treturn (ret);\n}\n\nint\nctl_byname(const char *name, void *oldp, size_t *oldlenp, void *newp,\n    size_t newlen)\n{\n\tint ret;\n\tsize_t depth;\n\tctl_node_t const *nodes[CTL_MAX_DEPTH];\n\tsize_t mib[CTL_MAX_DEPTH];\n\tconst ctl_named_node_t *node;\n\n\tif (ctl_initialized == false && ctl_init()) {\n\t\tret = EAGAIN;\n\t\tgoto label_return;\n\t}\n\n\tdepth = CTL_MAX_DEPTH;\n\tret = ctl_lookup(name, nodes, mib, &depth);\n\tif (ret != 0)\n\t\tgoto label_return;\n\n\tnode = ctl_named_node(nodes[depth-1]);\n\tif (node != NULL && node->ctl)\n\t\tret = node->ctl(mib, depth, oldp, oldlenp, newp, newlen);\n\telse {\n\t\t/* The name refers to a partial path through the ctl tree. */\n\t\tret = ENOENT;\n\t}\n\nlabel_return:\n\treturn(ret);\n}\n\nint\nctl_nametomib(const char *name, size_t *mibp, size_t *miblenp)\n{\n\tint ret;\n\n\tif (ctl_initialized == false && ctl_init()) {\n\t\tret = EAGAIN;\n\t\tgoto label_return;\n\t}\n\n\tret = ctl_lookup(name, NULL, mibp, miblenp);\nlabel_return:\n\treturn(ret);\n}\n\nint\nctl_bymib(const size_t *mib, size_t miblen, void *oldp, size_t *oldlenp,\n    void *newp, size_t newlen)\n{\n\tint ret;\n\tconst ctl_named_node_t *node;\n\tsize_t i;\n\n\tif (ctl_initialized == false && ctl_init()) {\n\t\tret = EAGAIN;\n\t\tgoto label_return;\n\t}\n\n\t/* Iterate down the tree. */\n\tnode = super_root_node;\n\tfor (i = 0; i < miblen; i++) {\n\t\tassert(node);\n\t\tassert(node->nchildren > 0);\n\t\tif (ctl_named_node(node->children) != NULL) {\n\t\t\t/* Children are named. */\n\t\t\tif (node->nchildren <= mib[i]) {\n\t\t\t\tret = ENOENT;\n\t\t\t\tgoto label_return;\n\t\t\t}\n\t\t\tnode = ctl_named_children(node, mib[i]);\n\t\t} else {\n\t\t\tconst ctl_indexed_node_t *inode;\n\n\t\t\t/* Indexed element. */\n\t\t\tinode = ctl_indexed_node(node->children);\n\t\t\tnode = inode->index(mib, miblen, mib[i]);\n\t\t\tif (node == NULL) {\n\t\t\t\tret = ENOENT;\n\t\t\t\tgoto label_return;\n\t\t\t}\n\t\t}\n\t}\n\n\t/* Call the ctl function. */\n\tif (node && node->ctl)\n\t\tret = node->ctl(mib, miblen, oldp, oldlenp, newp, newlen);\n\telse {\n\t\t/* Partial MIB. */\n\t\tret = ENOENT;\n\t}\n\nlabel_return:\n\treturn(ret);\n}\n\nbool\nctl_boot(void)\n{\n\n\tif (malloc_mutex_init(&ctl_mtx))\n\t\treturn (true);\n\n\tctl_initialized = false;\n\n\treturn (false);\n}\n\nvoid\nctl_prefork(void)\n{\n\n\tmalloc_mutex_prefork(&ctl_mtx);\n}\n\nvoid\nctl_postfork_parent(void)\n{\n\n\tmalloc_mutex_postfork_parent(&ctl_mtx);\n}\n\nvoid\nctl_postfork_child(void)\n{\n\n\tmalloc_mutex_postfork_child(&ctl_mtx);\n}\n\n/******************************************************************************/\n/* *_ctl() functions. */\n\n#define\tREADONLY()\tdo {\t\t\t\t\t\t\\\n\tif (newp != NULL || newlen != 0) {\t\t\t\t\\\n\t\tret = EPERM;\t\t\t\t\t\t\\\n\t\tgoto label_return;\t\t\t\t\t\\\n\t}\t\t\t\t\t\t\t\t\\\n} while (0)\n\n#define\tWRITEONLY()\tdo {\t\t\t\t\t\t\\\n\tif (oldp != NULL || oldlenp != NULL) {\t\t\t\t\\\n\t\tret = EPERM;\t\t\t\t\t\t\\\n\t\tgoto label_return;\t\t\t\t\t\\\n\t}\t\t\t\t\t\t\t\t\\\n} while (0)\n\n#define\tREAD(v, t)\tdo {\t\t\t\t\t\t\\\n\tif (oldp != NULL && oldlenp != NULL) {\t\t\t\t\\\n\t\tif (*oldlenp != sizeof(t)) {\t\t\t\t\\\n\t\t\tsize_t\tcopylen = (sizeof(t) <= *oldlenp)\t\\\n\t\t\t    ? sizeof(t) : *oldlenp;\t\t\t\\\n\t\t\tmemcpy(oldp, (void *)&(v), copylen);\t\t\\\n\t\t\tret = EINVAL;\t\t\t\t\t\\\n\t\t\tgoto label_return;\t\t\t\t\\\n\t\t} else\t\t\t\t\t\t\t\\\n\t\t\t*(t *)oldp = (v);\t\t\t\t\\\n\t}\t\t\t\t\t\t\t\t\\\n} while (0)\n\n#define\tWRITE(v, t)\tdo {\t\t\t\t\t\t\\\n\tif (newp != NULL) {\t\t\t\t\t\t\\\n\t\tif (newlen != sizeof(t)) {\t\t\t\t\\\n\t\t\tret = EINVAL;\t\t\t\t\t\\\n\t\t\tgoto label_return;\t\t\t\t\\\n\t\t}\t\t\t\t\t\t\t\\\n\t\t(v) = *(t *)newp;\t\t\t\t\t\\\n\t}\t\t\t\t\t\t\t\t\\\n} while (0)\n\n/*\n * There's a lot of code duplication in the following macros due to limitations\n * in how nested cpp macros are expanded.\n */\n#define\tCTL_RO_CLGEN(c, l, n, v, t)\t\t\t\t\t\\\nstatic int\t\t\t\t\t\t\t\t\\\nn##_ctl(const size_t *mib, size_t miblen, void *oldp, size_t *oldlenp,\t\\\n    void *newp, size_t newlen)\t\t\t\t\t\t\\\n{\t\t\t\t\t\t\t\t\t\\\n\tint ret;\t\t\t\t\t\t\t\\\n\tt oldval;\t\t\t\t\t\t\t\\\n\t\t\t\t\t\t\t\t\t\\\n\tif ((c) == false)\t\t\t\t\t\t\\\n\t\treturn (ENOENT);\t\t\t\t\t\\\n\tif (l)\t\t\t\t\t\t\t\t\\\n\t\tmalloc_mutex_lock(&ctl_mtx);\t\t\t\t\\\n\tREADONLY();\t\t\t\t\t\t\t\\\n\toldval = (v);\t\t\t\t\t\t\t\\\n\tREAD(oldval, t);\t\t\t\t\t\t\\\n\t\t\t\t\t\t\t\t\t\\\n\tret = 0;\t\t\t\t\t\t\t\\\nlabel_return:\t\t\t\t\t\t\t\t\\\n\tif (l)\t\t\t\t\t\t\t\t\\\n\t\tmalloc_mutex_unlock(&ctl_mtx);\t\t\t\t\\\n\treturn (ret);\t\t\t\t\t\t\t\\\n}\n\n#define\tCTL_RO_CGEN(c, n, v, t)\t\t\t\t\t\t\\\nstatic int\t\t\t\t\t\t\t\t\\\nn##_ctl(const size_t *mib, size_t miblen, void *oldp, size_t *oldlenp,\t\\\n    void *newp, size_t newlen)\t\t\t\t\t\t\\\n{\t\t\t\t\t\t\t\t\t\\\n\tint ret;\t\t\t\t\t\t\t\\\n\tt oldval;\t\t\t\t\t\t\t\\\n\t\t\t\t\t\t\t\t\t\\\n\tif ((c) == false)\t\t\t\t\t\t\\\n\t\treturn (ENOENT);\t\t\t\t\t\\\n\tmalloc_mutex_lock(&ctl_mtx);\t\t\t\t\t\\\n\tREADONLY();\t\t\t\t\t\t\t\\\n\toldval = (v);\t\t\t\t\t\t\t\\\n\tREAD(oldval, t);\t\t\t\t\t\t\\\n\t\t\t\t\t\t\t\t\t\\\n\tret = 0;\t\t\t\t\t\t\t\\\nlabel_return:\t\t\t\t\t\t\t\t\\\n\tmalloc_mutex_unlock(&ctl_mtx);\t\t\t\t\t\\\n\treturn (ret);\t\t\t\t\t\t\t\\\n}\n\n#define\tCTL_RO_GEN(n, v, t)\t\t\t\t\t\t\\\nstatic int\t\t\t\t\t\t\t\t\\\nn##_ctl(const size_t *mib, size_t miblen, void *oldp, size_t *oldlenp,\t\\\n    void *newp, size_t newlen)\t\t\t\t\t\t\\\n{\t\t\t\t\t\t\t\t\t\\\n\tint ret;\t\t\t\t\t\t\t\\\n\tt oldval;\t\t\t\t\t\t\t\\\n\t\t\t\t\t\t\t\t\t\\\n\tmalloc_mutex_lock(&ctl_mtx);\t\t\t\t\t\\\n\tREADONLY();\t\t\t\t\t\t\t\\\n\toldval = (v);\t\t\t\t\t\t\t\\\n\tREAD(oldval, t);\t\t\t\t\t\t\\\n\t\t\t\t\t\t\t\t\t\\\n\tret = 0;\t\t\t\t\t\t\t\\\nlabel_return:\t\t\t\t\t\t\t\t\\\n\tmalloc_mutex_unlock(&ctl_mtx);\t\t\t\t\t\\\n\treturn (ret);\t\t\t\t\t\t\t\\\n}\n\n/*\n * ctl_mtx is not acquired, under the assumption that no pertinent data will\n * mutate during the call.\n */\n#define\tCTL_RO_NL_CGEN(c, n, v, t)\t\t\t\t\t\\\nstatic int\t\t\t\t\t\t\t\t\\\nn##_ctl(const size_t *mib, size_t miblen, void *oldp, size_t *oldlenp,\t\\\n    void *newp, size_t newlen)\t\t\t\t\t\t\\\n{\t\t\t\t\t\t\t\t\t\\\n\tint ret;\t\t\t\t\t\t\t\\\n\tt oldval;\t\t\t\t\t\t\t\\\n\t\t\t\t\t\t\t\t\t\\\n\tif ((c) == false)\t\t\t\t\t\t\\\n\t\treturn (ENOENT);\t\t\t\t\t\\\n\tREADONLY();\t\t\t\t\t\t\t\\\n\toldval = (v);\t\t\t\t\t\t\t\\\n\tREAD(oldval, t);\t\t\t\t\t\t\\\n\t\t\t\t\t\t\t\t\t\\\n\tret = 0;\t\t\t\t\t\t\t\\\nlabel_return:\t\t\t\t\t\t\t\t\\\n\treturn (ret);\t\t\t\t\t\t\t\\\n}\n\n#define\tCTL_RO_NL_GEN(n, v, t)\t\t\t\t\t\t\\\nstatic int\t\t\t\t\t\t\t\t\\\nn##_ctl(const size_t *mib, size_t miblen, void *oldp, size_t *oldlenp,\t\\\n    void *newp, size_t newlen)\t\t\t\t\t\t\\\n{\t\t\t\t\t\t\t\t\t\\\n\tint ret;\t\t\t\t\t\t\t\\\n\tt oldval;\t\t\t\t\t\t\t\\\n\t\t\t\t\t\t\t\t\t\\\n\tREADONLY();\t\t\t\t\t\t\t\\\n\toldval = (v);\t\t\t\t\t\t\t\\\n\tREAD(oldval, t);\t\t\t\t\t\t\\\n\t\t\t\t\t\t\t\t\t\\\n\tret = 0;\t\t\t\t\t\t\t\\\nlabel_return:\t\t\t\t\t\t\t\t\\\n\treturn (ret);\t\t\t\t\t\t\t\\\n}\n\n#define\tCTL_RO_BOOL_CONFIG_GEN(n)\t\t\t\t\t\\\nstatic int\t\t\t\t\t\t\t\t\\\nn##_ctl(const size_t *mib, size_t miblen, void *oldp, size_t *oldlenp,\t\\\n    void *newp, size_t newlen)\t\t\t\t\t\t\\\n{\t\t\t\t\t\t\t\t\t\\\n\tint ret;\t\t\t\t\t\t\t\\\n\tbool oldval;\t\t\t\t\t\t\t\\\n\t\t\t\t\t\t\t\t\t\\\n\tREADONLY();\t\t\t\t\t\t\t\\\n\toldval = n;\t\t\t\t\t\t\t\\\n\tREAD(oldval, bool);\t\t\t\t\t\t\\\n\t\t\t\t\t\t\t\t\t\\\n\tret = 0;\t\t\t\t\t\t\t\\\nlabel_return:\t\t\t\t\t\t\t\t\\\n\treturn (ret);\t\t\t\t\t\t\t\\\n}\n\n/******************************************************************************/\n\nCTL_RO_NL_GEN(version, JEMALLOC_VERSION, const char *)\n\nstatic int\nepoch_ctl(const size_t *mib, size_t miblen, void *oldp, size_t *oldlenp,\n    void *newp, size_t newlen)\n{\n\tint ret;\n\tUNUSED uint64_t newval;\n\n\tmalloc_mutex_lock(&ctl_mtx);\n\tWRITE(newval, uint64_t);\n\tif (newp != NULL)\n\t\tctl_refresh();\n\tREAD(ctl_epoch, uint64_t);\n\n\tret = 0;\nlabel_return:\n\tmalloc_mutex_unlock(&ctl_mtx);\n\treturn (ret);\n}\n\n/******************************************************************************/\n\nCTL_RO_BOOL_CONFIG_GEN(config_debug)\nCTL_RO_BOOL_CONFIG_GEN(config_dss)\nCTL_RO_BOOL_CONFIG_GEN(config_fill)\nCTL_RO_BOOL_CONFIG_GEN(config_lazy_lock)\nCTL_RO_BOOL_CONFIG_GEN(config_mremap)\nCTL_RO_BOOL_CONFIG_GEN(config_munmap)\nCTL_RO_BOOL_CONFIG_GEN(config_prof)\nCTL_RO_BOOL_CONFIG_GEN(config_prof_libgcc)\nCTL_RO_BOOL_CONFIG_GEN(config_prof_libunwind)\nCTL_RO_BOOL_CONFIG_GEN(config_stats)\nCTL_RO_BOOL_CONFIG_GEN(config_tcache)\nCTL_RO_BOOL_CONFIG_GEN(config_tls)\nCTL_RO_BOOL_CONFIG_GEN(config_utrace)\nCTL_RO_BOOL_CONFIG_GEN(config_valgrind)\nCTL_RO_BOOL_CONFIG_GEN(config_xmalloc)\n\n/******************************************************************************/\n\nCTL_RO_NL_GEN(opt_abort, opt_abort, bool)\nCTL_RO_NL_GEN(opt_dss, opt_dss, const char *)\nCTL_RO_NL_GEN(opt_lg_chunk, opt_lg_chunk, size_t)\nCTL_RO_NL_GEN(opt_narenas, opt_narenas, size_t)\nCTL_RO_NL_GEN(opt_lg_dirty_mult, opt_lg_dirty_mult, ssize_t)\nCTL_RO_NL_GEN(opt_stats_print, opt_stats_print, bool)\nCTL_RO_NL_CGEN(config_fill, opt_junk, opt_junk, bool)\nCTL_RO_NL_CGEN(config_fill, opt_quarantine, opt_quarantine, size_t)\nCTL_RO_NL_CGEN(config_fill, opt_redzone, opt_redzone, bool)\nCTL_RO_NL_CGEN(config_fill, opt_zero, opt_zero, bool)\nCTL_RO_NL_CGEN(config_utrace, opt_utrace, opt_utrace, bool)\nCTL_RO_NL_CGEN(config_valgrind, opt_valgrind, opt_valgrind, bool)\nCTL_RO_NL_CGEN(config_xmalloc, opt_xmalloc, opt_xmalloc, bool)\nCTL_RO_NL_CGEN(config_tcache, opt_tcache, opt_tcache, bool)\nCTL_RO_NL_CGEN(config_tcache, opt_lg_tcache_max, opt_lg_tcache_max, ssize_t)\nCTL_RO_NL_CGEN(config_prof, opt_prof, opt_prof, bool)\nCTL_RO_NL_CGEN(config_prof, opt_prof_prefix, opt_prof_prefix, const char *)\nCTL_RO_CGEN(config_prof, opt_prof_active, opt_prof_active, bool) /* Mutable. */\nCTL_RO_NL_CGEN(config_prof, opt_lg_prof_sample, opt_lg_prof_sample, size_t)\nCTL_RO_NL_CGEN(config_prof, opt_prof_accum, opt_prof_accum, bool)\nCTL_RO_NL_CGEN(config_prof, opt_lg_prof_interval, opt_lg_prof_interval, ssize_t)\nCTL_RO_NL_CGEN(config_prof, opt_prof_gdump, opt_prof_gdump, bool)\nCTL_RO_NL_CGEN(config_prof, opt_prof_final, opt_prof_final, bool)\nCTL_RO_NL_CGEN(config_prof, opt_prof_leak, opt_prof_leak, bool)\n\n/******************************************************************************/\n\nstatic int\nthread_arena_ctl(const size_t *mib, size_t miblen, void *oldp, size_t *oldlenp,\n    void *newp, size_t newlen)\n{\n\tint ret;\n\tunsigned newind, oldind;\n\n\tmalloc_mutex_lock(&ctl_mtx);\n\tnewind = oldind = choose_arena(NULL)->ind;\n\tWRITE(newind, unsigned);\n\tREAD(oldind, unsigned);\n\tif (newind != oldind) {\n\t\tarena_t *arena;\n\n\t\tif (newind >= ctl_stats.narenas) {\n\t\t\t/* New arena index is out of range. */\n\t\t\tret = EFAULT;\n\t\t\tgoto label_return;\n\t\t}\n\n\t\t/* Initialize arena if necessary. */\n\t\tmalloc_mutex_lock(&arenas_lock);\n\t\tif ((arena = arenas[newind]) == NULL && (arena =\n\t\t    arenas_extend(newind)) == NULL) {\n\t\t\tmalloc_mutex_unlock(&arenas_lock);\n\t\t\tret = EAGAIN;\n\t\t\tgoto label_return;\n\t\t}\n\t\tassert(arena == arenas[newind]);\n\t\tarenas[oldind]->nthreads--;\n\t\tarenas[newind]->nthreads++;\n\t\tmalloc_mutex_unlock(&arenas_lock);\n\n\t\t/* Set new arena association. */\n\t\tif (config_tcache) {\n\t\t\ttcache_t *tcache;\n\t\t\tif ((uintptr_t)(tcache = *tcache_tsd_get()) >\n\t\t\t    (uintptr_t)TCACHE_STATE_MAX) {\n\t\t\t\ttcache_arena_dissociate(tcache);\n\t\t\t\ttcache_arena_associate(tcache, arena);\n\t\t\t}\n\t\t}\n\t\tarenas_tsd_set(&arena);\n\t}\n\n\tret = 0;\nlabel_return:\n\tmalloc_mutex_unlock(&ctl_mtx);\n\treturn (ret);\n}\n\nCTL_RO_NL_CGEN(config_stats, thread_allocated,\n    thread_allocated_tsd_get()->allocated, uint64_t)\nCTL_RO_NL_CGEN(config_stats, thread_allocatedp,\n    &thread_allocated_tsd_get()->allocated, uint64_t *)\nCTL_RO_NL_CGEN(config_stats, thread_deallocated,\n    thread_allocated_tsd_get()->deallocated, uint64_t)\nCTL_RO_NL_CGEN(config_stats, thread_deallocatedp,\n    &thread_allocated_tsd_get()->deallocated, uint64_t *)\n\nstatic int\nthread_tcache_enabled_ctl(const size_t *mib, size_t miblen, void *oldp,\n    size_t *oldlenp, void *newp, size_t newlen)\n{\n\tint ret;\n\tbool oldval;\n\n\tif (config_tcache == false)\n\t\treturn (ENOENT);\n\n\toldval = tcache_enabled_get();\n\tif (newp != NULL) {\n\t\tif (newlen != sizeof(bool)) {\n\t\t\tret = EINVAL;\n\t\t\tgoto label_return;\n\t\t}\n\t\ttcache_enabled_set(*(bool *)newp);\n\t}\n\tREAD(oldval, bool);\n\n\tret = 0;\nlabel_return:\n\treturn (ret);\n}\n\nstatic int\nthread_tcache_flush_ctl(const size_t *mib, size_t miblen, void *oldp,\n    size_t *oldlenp, void *newp, size_t newlen)\n{\n\tint ret;\n\n\tif (config_tcache == false)\n\t\treturn (ENOENT);\n\n\tREADONLY();\n\tWRITEONLY();\n\n\ttcache_flush();\n\n\tret = 0;\nlabel_return:\n\treturn (ret);\n}\n\n/******************************************************************************/\n\n/* ctl_mutex must be held during execution of this function. */\nstatic void\narena_purge(unsigned arena_ind)\n{\n\tVARIABLE_ARRAY(arena_t *, tarenas, ctl_stats.narenas);\n\n\tmalloc_mutex_lock(&arenas_lock);\n\tmemcpy(tarenas, arenas, sizeof(arena_t *) * ctl_stats.narenas);\n\tmalloc_mutex_unlock(&arenas_lock);\n\n\tif (arena_ind == ctl_stats.narenas) {\n\t\tunsigned i;\n\t\tfor (i = 0; i < ctl_stats.narenas; i++) {\n\t\t\tif (tarenas[i] != NULL)\n\t\t\t\tarena_purge_all(tarenas[i]);\n\t\t}\n\t} else {\n\t\tassert(arena_ind < ctl_stats.narenas);\n\t\tif (tarenas[arena_ind] != NULL)\n\t\t\tarena_purge_all(tarenas[arena_ind]);\n\t}\n}\n\nstatic int\narena_i_purge_ctl(const size_t *mib, size_t miblen, void *oldp, size_t *oldlenp,\n    void *newp, size_t newlen)\n{\n\tint ret;\n\n\tREADONLY();\n\tWRITEONLY();\n\tmalloc_mutex_lock(&ctl_mtx);\n\tarena_purge(mib[1]);\n\tmalloc_mutex_unlock(&ctl_mtx);\n\n\tret = 0;\nlabel_return:\n\treturn (ret);\n}\n\nstatic int\narena_i_dss_ctl(const size_t *mib, size_t miblen, void *oldp, size_t *oldlenp,\n    void *newp, size_t newlen)\n{\n\tint ret, i;\n\tbool match, err;\n\tconst char *dss;\n\tunsigned arena_ind = mib[1];\n\tdss_prec_t dss_prec_old = dss_prec_limit;\n\tdss_prec_t dss_prec = dss_prec_limit;\n\n\tmalloc_mutex_lock(&ctl_mtx);\n\tWRITE(dss, const char *);\n\tmatch = false;\n\tfor (i = 0; i < dss_prec_limit; i++) {\n\t\tif (strcmp(dss_prec_names[i], dss) == 0) {\n\t\t\tdss_prec = i;\n\t\t\tmatch = true;\n\t\t\tbreak;\n\t\t}\n\t}\n\tif (match == false) {\n\t\tret = EINVAL;\n\t\tgoto label_return;\n\t}\n\n\tif (arena_ind < ctl_stats.narenas) {\n\t\tarena_t *arena = arenas[arena_ind];\n\t\tif (arena != NULL) {\n\t\t\tdss_prec_old = arena_dss_prec_get(arena);\n\t\t\tarena_dss_prec_set(arena, dss_prec);\n\t\t\terr = false;\n\t\t} else\n\t\t\terr = true;\n\t} else {\n\t\tdss_prec_old = chunk_dss_prec_get();\n\t\terr = chunk_dss_prec_set(dss_prec);\n\t}\n\tdss = dss_prec_names[dss_prec_old];\n\tREAD(dss, const char *);\n\tif (err) {\n\t\tret = EFAULT;\n\t\tgoto label_return;\n\t}\n\n\tret = 0;\nlabel_return:\n\tmalloc_mutex_unlock(&ctl_mtx);\n\treturn (ret);\n}\n\nstatic const ctl_named_node_t *\narena_i_index(const size_t *mib, size_t miblen, size_t i)\n{\n\tconst ctl_named_node_t * ret;\n\n\tmalloc_mutex_lock(&ctl_mtx);\n\tif (i > ctl_stats.narenas) {\n\t\tret = NULL;\n\t\tgoto label_return;\n\t}\n\n\tret = super_arena_i_node;\nlabel_return:\n\tmalloc_mutex_unlock(&ctl_mtx);\n\treturn (ret);\n}\n\n/******************************************************************************/\n\nstatic int\narenas_narenas_ctl(const size_t *mib, size_t miblen, void *oldp,\n    size_t *oldlenp, void *newp, size_t newlen)\n{\n\tint ret;\n\tunsigned narenas;\n\n\tmalloc_mutex_lock(&ctl_mtx);\n\tREADONLY();\n\tif (*oldlenp != sizeof(unsigned)) {\n\t\tret = EINVAL;\n\t\tgoto label_return;\n\t}\n\tnarenas = ctl_stats.narenas;\n\tREAD(narenas, unsigned);\n\n\tret = 0;\nlabel_return:\n\tmalloc_mutex_unlock(&ctl_mtx);\n\treturn (ret);\n}\n\nstatic int\narenas_initialized_ctl(const size_t *mib, size_t miblen, void *oldp,\n    size_t *oldlenp, void *newp, size_t newlen)\n{\n\tint ret;\n\tunsigned nread, i;\n\n\tmalloc_mutex_lock(&ctl_mtx);\n\tREADONLY();\n\tif (*oldlenp != ctl_stats.narenas * sizeof(bool)) {\n\t\tret = EINVAL;\n\t\tnread = (*oldlenp < ctl_stats.narenas * sizeof(bool))\n\t\t    ? (*oldlenp / sizeof(bool)) : ctl_stats.narenas;\n\t} else {\n\t\tret = 0;\n\t\tnread = ctl_stats.narenas;\n\t}\n\n\tfor (i = 0; i < nread; i++)\n\t\t((bool *)oldp)[i] = ctl_stats.arenas[i].initialized;\n\nlabel_return:\n\tmalloc_mutex_unlock(&ctl_mtx);\n\treturn (ret);\n}\n\nCTL_RO_NL_GEN(arenas_quantum, QUANTUM, size_t)\nCTL_RO_NL_GEN(arenas_page, PAGE, size_t)\nCTL_RO_NL_CGEN(config_tcache, arenas_tcache_max, tcache_maxclass, size_t)\nCTL_RO_NL_GEN(arenas_nbins, NBINS, unsigned)\nCTL_RO_NL_CGEN(config_tcache, arenas_nhbins, nhbins, unsigned)\nCTL_RO_NL_GEN(arenas_bin_i_size, arena_bin_info[mib[2]].reg_size, size_t)\nCTL_RO_NL_GEN(arenas_bin_i_nregs, arena_bin_info[mib[2]].nregs, uint32_t)\nCTL_RO_NL_GEN(arenas_bin_i_run_size, arena_bin_info[mib[2]].run_size, size_t)\nstatic const ctl_named_node_t *\narenas_bin_i_index(const size_t *mib, size_t miblen, size_t i)\n{\n\n\tif (i > NBINS)\n\t\treturn (NULL);\n\treturn (super_arenas_bin_i_node);\n}\n\nCTL_RO_NL_GEN(arenas_nlruns, nlclasses, size_t)\nCTL_RO_NL_GEN(arenas_lrun_i_size, ((mib[2]+1) << LG_PAGE), size_t)\nstatic const ctl_named_node_t *\narenas_lrun_i_index(const size_t *mib, size_t miblen, size_t i)\n{\n\n\tif (i > nlclasses)\n\t\treturn (NULL);\n\treturn (super_arenas_lrun_i_node);\n}\n\nstatic int\narenas_purge_ctl(const size_t *mib, size_t miblen, void *oldp, size_t *oldlenp,\n    void *newp, size_t newlen)\n{\n\tint ret;\n\tunsigned arena_ind;\n\n\tmalloc_mutex_lock(&ctl_mtx);\n\tWRITEONLY();\n\tarena_ind = UINT_MAX;\n\tWRITE(arena_ind, unsigned);\n\tif (newp != NULL && arena_ind >= ctl_stats.narenas)\n\t\tret = EFAULT;\n\telse {\n\t\tif (arena_ind == UINT_MAX)\n\t\t\tarena_ind = ctl_stats.narenas;\n\t\tarena_purge(arena_ind);\n\t\tret = 0;\n\t}\n\nlabel_return:\n\tmalloc_mutex_unlock(&ctl_mtx);\n\treturn (ret);\n}\n\nstatic int\narenas_extend_ctl(const size_t *mib, size_t miblen, void *oldp, size_t *oldlenp,\n    void *newp, size_t newlen)\n{\n\tint ret;\n\tunsigned narenas;\n\n\tmalloc_mutex_lock(&ctl_mtx);\n\tREADONLY();\n\tif (ctl_grow()) {\n\t\tret = EAGAIN;\n\t\tgoto label_return;\n\t}\n\tnarenas = ctl_stats.narenas - 1;\n\tREAD(narenas, unsigned);\n\n\tret = 0;\nlabel_return:\n\tmalloc_mutex_unlock(&ctl_mtx);\n\treturn (ret);\n}\n\n/******************************************************************************/\n\nstatic int\nprof_active_ctl(const size_t *mib, size_t miblen, void *oldp, size_t *oldlenp,\n    void *newp, size_t newlen)\n{\n\tint ret;\n\tbool oldval;\n\n\tif (config_prof == false)\n\t\treturn (ENOENT);\n\n\tmalloc_mutex_lock(&ctl_mtx); /* Protect opt_prof_active. */\n\toldval = opt_prof_active;\n\tif (newp != NULL) {\n\t\t/*\n\t\t * The memory barriers will tend to make opt_prof_active\n\t\t * propagate faster on systems with weak memory ordering.\n\t\t */\n\t\tmb_write();\n\t\tWRITE(opt_prof_active, bool);\n\t\tmb_write();\n\t}\n\tREAD(oldval, bool);\n\n\tret = 0;\nlabel_return:\n\tmalloc_mutex_unlock(&ctl_mtx);\n\treturn (ret);\n}\n\nstatic int\nprof_dump_ctl(const size_t *mib, size_t miblen, void *oldp, size_t *oldlenp,\n    void *newp, size_t newlen)\n{\n\tint ret;\n\tconst char *filename = NULL;\n\n\tif (config_prof == false)\n\t\treturn (ENOENT);\n\n\tWRITEONLY();\n\tWRITE(filename, const char *);\n\n\tif (prof_mdump(filename)) {\n\t\tret = EFAULT;\n\t\tgoto label_return;\n\t}\n\n\tret = 0;\nlabel_return:\n\treturn (ret);\n}\n\nCTL_RO_NL_CGEN(config_prof, prof_interval, prof_interval, uint64_t)\n\n/******************************************************************************/\n\nCTL_RO_CGEN(config_stats, stats_cactive, &stats_cactive, size_t *)\nCTL_RO_CGEN(config_stats, stats_allocated, ctl_stats.allocated, size_t)\nCTL_RO_CGEN(config_stats, stats_active, ctl_stats.active, size_t)\nCTL_RO_CGEN(config_stats, stats_mapped, ctl_stats.mapped, size_t)\n\nCTL_RO_CGEN(config_stats, stats_chunks_current, ctl_stats.chunks.current,\n    size_t)\nCTL_RO_CGEN(config_stats, stats_chunks_total, ctl_stats.chunks.total, uint64_t)\nCTL_RO_CGEN(config_stats, stats_chunks_high, ctl_stats.chunks.high, size_t)\nCTL_RO_CGEN(config_stats, stats_huge_allocated, huge_allocated, size_t)\nCTL_RO_CGEN(config_stats, stats_huge_nmalloc, huge_nmalloc, uint64_t)\nCTL_RO_CGEN(config_stats, stats_huge_ndalloc, huge_ndalloc, uint64_t)\n\nCTL_RO_GEN(stats_arenas_i_dss, ctl_stats.arenas[mib[2]].dss, const char *)\nCTL_RO_GEN(stats_arenas_i_nthreads, ctl_stats.arenas[mib[2]].nthreads, unsigned)\nCTL_RO_GEN(stats_arenas_i_pactive, ctl_stats.arenas[mib[2]].pactive, size_t)\nCTL_RO_GEN(stats_arenas_i_pdirty, ctl_stats.arenas[mib[2]].pdirty, size_t)\nCTL_RO_CGEN(config_stats, stats_arenas_i_mapped,\n    ctl_stats.arenas[mib[2]].astats.mapped, size_t)\nCTL_RO_CGEN(config_stats, stats_arenas_i_npurge,\n    ctl_stats.arenas[mib[2]].astats.npurge, uint64_t)\nCTL_RO_CGEN(config_stats, stats_arenas_i_nmadvise,\n    ctl_stats.arenas[mib[2]].astats.nmadvise, uint64_t)\nCTL_RO_CGEN(config_stats, stats_arenas_i_purged,\n    ctl_stats.arenas[mib[2]].astats.purged, uint64_t)\n\nCTL_RO_CGEN(config_stats, stats_arenas_i_small_allocated,\n    ctl_stats.arenas[mib[2]].allocated_small, size_t)\nCTL_RO_CGEN(config_stats, stats_arenas_i_small_nmalloc,\n    ctl_stats.arenas[mib[2]].nmalloc_small, uint64_t)\nCTL_RO_CGEN(config_stats, stats_arenas_i_small_ndalloc,\n    ctl_stats.arenas[mib[2]].ndalloc_small, uint64_t)\nCTL_RO_CGEN(config_stats, stats_arenas_i_small_nrequests,\n    ctl_stats.arenas[mib[2]].nrequests_small, uint64_t)\nCTL_RO_CGEN(config_stats, stats_arenas_i_large_allocated,\n    ctl_stats.arenas[mib[2]].astats.allocated_large, size_t)\nCTL_RO_CGEN(config_stats, stats_arenas_i_large_nmalloc,\n    ctl_stats.arenas[mib[2]].astats.nmalloc_large, uint64_t)\nCTL_RO_CGEN(config_stats, stats_arenas_i_large_ndalloc,\n    ctl_stats.arenas[mib[2]].astats.ndalloc_large, uint64_t)\nCTL_RO_CGEN(config_stats, stats_arenas_i_large_nrequests,\n    ctl_stats.arenas[mib[2]].astats.nrequests_large, uint64_t)\n\nCTL_RO_CGEN(config_stats, stats_arenas_i_bins_j_allocated,\n    ctl_stats.arenas[mib[2]].bstats[mib[4]].allocated, size_t)\nCTL_RO_CGEN(config_stats, stats_arenas_i_bins_j_nmalloc,\n    ctl_stats.arenas[mib[2]].bstats[mib[4]].nmalloc, uint64_t)\nCTL_RO_CGEN(config_stats, stats_arenas_i_bins_j_ndalloc,\n    ctl_stats.arenas[mib[2]].bstats[mib[4]].ndalloc, uint64_t)\nCTL_RO_CGEN(config_stats, stats_arenas_i_bins_j_nrequests,\n    ctl_stats.arenas[mib[2]].bstats[mib[4]].nrequests, uint64_t)\nCTL_RO_CGEN(config_stats && config_tcache, stats_arenas_i_bins_j_nfills,\n    ctl_stats.arenas[mib[2]].bstats[mib[4]].nfills, uint64_t)\nCTL_RO_CGEN(config_stats && config_tcache, stats_arenas_i_bins_j_nflushes,\n    ctl_stats.arenas[mib[2]].bstats[mib[4]].nflushes, uint64_t)\nCTL_RO_CGEN(config_stats, stats_arenas_i_bins_j_nruns,\n    ctl_stats.arenas[mib[2]].bstats[mib[4]].nruns, uint64_t)\nCTL_RO_CGEN(config_stats, stats_arenas_i_bins_j_nreruns,\n    ctl_stats.arenas[mib[2]].bstats[mib[4]].reruns, uint64_t)\nCTL_RO_CGEN(config_stats, stats_arenas_i_bins_j_curruns,\n    ctl_stats.arenas[mib[2]].bstats[mib[4]].curruns, size_t)\n\nstatic const ctl_named_node_t *\nstats_arenas_i_bins_j_index(const size_t *mib, size_t miblen, size_t j)\n{\n\n\tif (j > NBINS)\n\t\treturn (NULL);\n\treturn (super_stats_arenas_i_bins_j_node);\n}\n\nCTL_RO_CGEN(config_stats, stats_arenas_i_lruns_j_nmalloc,\n    ctl_stats.arenas[mib[2]].lstats[mib[4]].nmalloc, uint64_t)\nCTL_RO_CGEN(config_stats, stats_arenas_i_lruns_j_ndalloc,\n    ctl_stats.arenas[mib[2]].lstats[mib[4]].ndalloc, uint64_t)\nCTL_RO_CGEN(config_stats, stats_arenas_i_lruns_j_nrequests,\n    ctl_stats.arenas[mib[2]].lstats[mib[4]].nrequests, uint64_t)\nCTL_RO_CGEN(config_stats, stats_arenas_i_lruns_j_curruns,\n    ctl_stats.arenas[mib[2]].lstats[mib[4]].curruns, size_t)\n\nstatic const ctl_named_node_t *\nstats_arenas_i_lruns_j_index(const size_t *mib, size_t miblen, size_t j)\n{\n\n\tif (j > nlclasses)\n\t\treturn (NULL);\n\treturn (super_stats_arenas_i_lruns_j_node);\n}\n\nstatic const ctl_named_node_t *\nstats_arenas_i_index(const size_t *mib, size_t miblen, size_t i)\n{\n\tconst ctl_named_node_t * ret;\n\n\tmalloc_mutex_lock(&ctl_mtx);\n\tif (i > ctl_stats.narenas || ctl_stats.arenas[i].initialized == false) {\n\t\tret = NULL;\n\t\tgoto label_return;\n\t}\n\n\tret = super_stats_arenas_i_node;\nlabel_return:\n\tmalloc_mutex_unlock(&ctl_mtx);\n\treturn (ret);\n}\n"
  },
  {
    "path": "extern/deprecated/redis-2.8.21/deps/jemalloc/src/extent.c",
    "content": "#define\tJEMALLOC_EXTENT_C_\n#include \"jemalloc/internal/jemalloc_internal.h\"\n\n/******************************************************************************/\n\nstatic inline int\nextent_szad_comp(extent_node_t *a, extent_node_t *b)\n{\n\tint ret;\n\tsize_t a_size = a->size;\n\tsize_t b_size = b->size;\n\n\tret = (a_size > b_size) - (a_size < b_size);\n\tif (ret == 0) {\n\t\tuintptr_t a_addr = (uintptr_t)a->addr;\n\t\tuintptr_t b_addr = (uintptr_t)b->addr;\n\n\t\tret = (a_addr > b_addr) - (a_addr < b_addr);\n\t}\n\n\treturn (ret);\n}\n\n/* Generate red-black tree functions. */\nrb_gen(, extent_tree_szad_, extent_tree_t, extent_node_t, link_szad,\n    extent_szad_comp)\n\nstatic inline int\nextent_ad_comp(extent_node_t *a, extent_node_t *b)\n{\n\tuintptr_t a_addr = (uintptr_t)a->addr;\n\tuintptr_t b_addr = (uintptr_t)b->addr;\n\n\treturn ((a_addr > b_addr) - (a_addr < b_addr));\n}\n\n/* Generate red-black tree functions. */\nrb_gen(, extent_tree_ad_, extent_tree_t, extent_node_t, link_ad,\n    extent_ad_comp)\n"
  },
  {
    "path": "extern/deprecated/redis-2.8.21/deps/jemalloc/src/hash.c",
    "content": "#define\tJEMALLOC_HASH_C_\n#include \"jemalloc/internal/jemalloc_internal.h\"\n"
  },
  {
    "path": "extern/deprecated/redis-2.8.21/deps/jemalloc/src/huge.c",
    "content": "#define\tJEMALLOC_HUGE_C_\n#include \"jemalloc/internal/jemalloc_internal.h\"\n\n/******************************************************************************/\n/* Data. */\n\nuint64_t\thuge_nmalloc;\nuint64_t\thuge_ndalloc;\nsize_t\t\thuge_allocated;\n\nmalloc_mutex_t\thuge_mtx;\n\n/******************************************************************************/\n\n/* Tree of chunks that are stand-alone huge allocations. */\nstatic extent_tree_t\thuge;\n\nvoid *\nhuge_malloc(size_t size, bool zero, dss_prec_t dss_prec)\n{\n\n\treturn (huge_palloc(size, chunksize, zero, dss_prec));\n}\n\nvoid *\nhuge_palloc(size_t size, size_t alignment, bool zero, dss_prec_t dss_prec)\n{\n\tvoid *ret;\n\tsize_t csize;\n\textent_node_t *node;\n\tbool is_zeroed;\n\n\t/* Allocate one or more contiguous chunks for this request. */\n\n\tcsize = CHUNK_CEILING(size);\n\tif (csize == 0) {\n\t\t/* size is large enough to cause size_t wrap-around. */\n\t\treturn (NULL);\n\t}\n\n\t/* Allocate an extent node with which to track the chunk. */\n\tnode = base_node_alloc();\n\tif (node == NULL)\n\t\treturn (NULL);\n\n\t/*\n\t * Copy zero into is_zeroed and pass the copy to chunk_alloc(), so that\n\t * it is possible to make correct junk/zero fill decisions below.\n\t */\n\tis_zeroed = zero;\n\tret = chunk_alloc(csize, alignment, false, &is_zeroed, dss_prec);\n\tif (ret == NULL) {\n\t\tbase_node_dealloc(node);\n\t\treturn (NULL);\n\t}\n\n\t/* Insert node into huge. */\n\tnode->addr = ret;\n\tnode->size = csize;\n\n\tmalloc_mutex_lock(&huge_mtx);\n\textent_tree_ad_insert(&huge, node);\n\tif (config_stats) {\n\t\tstats_cactive_add(csize);\n\t\thuge_nmalloc++;\n\t\thuge_allocated += csize;\n\t}\n\tmalloc_mutex_unlock(&huge_mtx);\n\n\tif (config_fill && zero == false) {\n\t\tif (opt_junk)\n\t\t\tmemset(ret, 0xa5, csize);\n\t\telse if (opt_zero && is_zeroed == false)\n\t\t\tmemset(ret, 0, csize);\n\t}\n\n\treturn (ret);\n}\n\nbool\nhuge_ralloc_no_move(void *ptr, size_t oldsize, size_t size, size_t extra)\n{\n\n\t/*\n\t * Avoid moving the allocation if the size class can be left the same.\n\t */\n\tif (oldsize > arena_maxclass\n\t    && CHUNK_CEILING(oldsize) >= CHUNK_CEILING(size)\n\t    && CHUNK_CEILING(oldsize) <= CHUNK_CEILING(size+extra)) {\n\t\tassert(CHUNK_CEILING(oldsize) == oldsize);\n\t\treturn (false);\n\t}\n\n\t/* Reallocation would require a move. */\n\treturn (true);\n}\n\nvoid *\nhuge_ralloc(void *ptr, size_t oldsize, size_t size, size_t extra,\n    size_t alignment, bool zero, bool try_tcache_dalloc, dss_prec_t dss_prec)\n{\n\tvoid *ret;\n\tsize_t copysize;\n\n\t/* Try to avoid moving the allocation. */\n\tif (huge_ralloc_no_move(ptr, oldsize, size, extra) == false)\n\t\treturn (ptr);\n\n\t/*\n\t * size and oldsize are different enough that we need to use a\n\t * different size class.  In that case, fall back to allocating new\n\t * space and copying.\n\t */\n\tif (alignment > chunksize)\n\t\tret = huge_palloc(size + extra, alignment, zero, dss_prec);\n\telse\n\t\tret = huge_malloc(size + extra, zero, dss_prec);\n\n\tif (ret == NULL) {\n\t\tif (extra == 0)\n\t\t\treturn (NULL);\n\t\t/* Try again, this time without extra. */\n\t\tif (alignment > chunksize)\n\t\t\tret = huge_palloc(size, alignment, zero, dss_prec);\n\t\telse\n\t\t\tret = huge_malloc(size, zero, dss_prec);\n\n\t\tif (ret == NULL)\n\t\t\treturn (NULL);\n\t}\n\n\t/*\n\t * Copy at most size bytes (not size+extra), since the caller has no\n\t * expectation that the extra bytes will be reliably preserved.\n\t */\n\tcopysize = (size < oldsize) ? size : oldsize;\n\n#ifdef JEMALLOC_MREMAP\n\t/*\n\t * Use mremap(2) if this is a huge-->huge reallocation, and neither the\n\t * source nor the destination are in dss.\n\t */\n\tif (oldsize >= chunksize && (config_dss == false || (chunk_in_dss(ptr)\n\t    == false && chunk_in_dss(ret) == false))) {\n\t\tsize_t newsize = huge_salloc(ret);\n\n\t\t/*\n\t\t * Remove ptr from the tree of huge allocations before\n\t\t * performing the remap operation, in order to avoid the\n\t\t * possibility of another thread acquiring that mapping before\n\t\t * this one removes it from the tree.\n\t\t */\n\t\thuge_dalloc(ptr, false);\n\t\tif (mremap(ptr, oldsize, newsize, MREMAP_MAYMOVE|MREMAP_FIXED,\n\t\t    ret) == MAP_FAILED) {\n\t\t\t/*\n\t\t\t * Assuming no chunk management bugs in the allocator,\n\t\t\t * the only documented way an error can occur here is\n\t\t\t * if the application changed the map type for a\n\t\t\t * portion of the old allocation.  This is firmly in\n\t\t\t * undefined behavior territory, so write a diagnostic\n\t\t\t * message, and optionally abort.\n\t\t\t */\n\t\t\tchar buf[BUFERROR_BUF];\n\n\t\t\tbuferror(get_errno(), buf, sizeof(buf));\n\t\t\tmalloc_printf(\"<jemalloc>: Error in mremap(): %s\\n\",\n\t\t\t    buf);\n\t\t\tif (opt_abort)\n\t\t\t\tabort();\n\t\t\tmemcpy(ret, ptr, copysize);\n\t\t\tchunk_dealloc_mmap(ptr, oldsize);\n\t\t} else if (config_fill && zero == false && opt_junk && oldsize\n\t\t    < newsize) {\n\t\t\t/*\n\t\t\t * mremap(2) clobbers the original mapping, so\n\t\t\t * junk/zero filling is not preserved.  There is no\n\t\t\t * need to zero fill here, since any trailing\n\t\t\t * uninititialized memory is demand-zeroed by the\n\t\t\t * kernel, but junk filling must be redone.\n\t\t\t */\n\t\t\tmemset(ret + oldsize, 0xa5, newsize - oldsize);\n\t\t}\n\t} else\n#endif\n\t{\n\t\tmemcpy(ret, ptr, copysize);\n\t\tiqalloct(ptr, try_tcache_dalloc);\n\t}\n\treturn (ret);\n}\n\n#ifdef JEMALLOC_JET\n#undef huge_dalloc_junk\n#define\thuge_dalloc_junk JEMALLOC_N(huge_dalloc_junk_impl)\n#endif\nstatic void\nhuge_dalloc_junk(void *ptr, size_t usize)\n{\n\n\tif (config_fill && config_dss && opt_junk) {\n\t\t/*\n\t\t * Only bother junk filling if the chunk isn't about to be\n\t\t * unmapped.\n\t\t */\n\t\tif (config_munmap == false || (config_dss && chunk_in_dss(ptr)))\n\t\t\tmemset(ptr, 0x5a, usize);\n\t}\n}\n#ifdef JEMALLOC_JET\n#undef huge_dalloc_junk\n#define\thuge_dalloc_junk JEMALLOC_N(huge_dalloc_junk)\nhuge_dalloc_junk_t *huge_dalloc_junk = JEMALLOC_N(huge_dalloc_junk_impl);\n#endif\n\nvoid\nhuge_dalloc(void *ptr, bool unmap)\n{\n\textent_node_t *node, key;\n\n\tmalloc_mutex_lock(&huge_mtx);\n\n\t/* Extract from tree of huge allocations. */\n\tkey.addr = ptr;\n\tnode = extent_tree_ad_search(&huge, &key);\n\tassert(node != NULL);\n\tassert(node->addr == ptr);\n\textent_tree_ad_remove(&huge, node);\n\n\tif (config_stats) {\n\t\tstats_cactive_sub(node->size);\n\t\thuge_ndalloc++;\n\t\thuge_allocated -= node->size;\n\t}\n\n\tmalloc_mutex_unlock(&huge_mtx);\n\n\tif (unmap)\n\t\thuge_dalloc_junk(node->addr, node->size);\n\n\tchunk_dealloc(node->addr, node->size, unmap);\n\n\tbase_node_dealloc(node);\n}\n\nsize_t\nhuge_salloc(const void *ptr)\n{\n\tsize_t ret;\n\textent_node_t *node, key;\n\n\tmalloc_mutex_lock(&huge_mtx);\n\n\t/* Extract from tree of huge allocations. */\n\tkey.addr = __DECONST(void *, ptr);\n\tnode = extent_tree_ad_search(&huge, &key);\n\tassert(node != NULL);\n\n\tret = node->size;\n\n\tmalloc_mutex_unlock(&huge_mtx);\n\n\treturn (ret);\n}\n\ndss_prec_t\nhuge_dss_prec_get(arena_t *arena)\n{\n\n\treturn (arena_dss_prec_get(choose_arena(arena)));\n}\n\nprof_ctx_t *\nhuge_prof_ctx_get(const void *ptr)\n{\n\tprof_ctx_t *ret;\n\textent_node_t *node, key;\n\n\tmalloc_mutex_lock(&huge_mtx);\n\n\t/* Extract from tree of huge allocations. */\n\tkey.addr = __DECONST(void *, ptr);\n\tnode = extent_tree_ad_search(&huge, &key);\n\tassert(node != NULL);\n\n\tret = node->prof_ctx;\n\n\tmalloc_mutex_unlock(&huge_mtx);\n\n\treturn (ret);\n}\n\nvoid\nhuge_prof_ctx_set(const void *ptr, prof_ctx_t *ctx)\n{\n\textent_node_t *node, key;\n\n\tmalloc_mutex_lock(&huge_mtx);\n\n\t/* Extract from tree of huge allocations. */\n\tkey.addr = __DECONST(void *, ptr);\n\tnode = extent_tree_ad_search(&huge, &key);\n\tassert(node != NULL);\n\n\tnode->prof_ctx = ctx;\n\n\tmalloc_mutex_unlock(&huge_mtx);\n}\n\nbool\nhuge_boot(void)\n{\n\n\t/* Initialize chunks data. */\n\tif (malloc_mutex_init(&huge_mtx))\n\t\treturn (true);\n\textent_tree_ad_new(&huge);\n\n\tif (config_stats) {\n\t\thuge_nmalloc = 0;\n\t\thuge_ndalloc = 0;\n\t\thuge_allocated = 0;\n\t}\n\n\treturn (false);\n}\n\nvoid\nhuge_prefork(void)\n{\n\n\tmalloc_mutex_prefork(&huge_mtx);\n}\n\nvoid\nhuge_postfork_parent(void)\n{\n\n\tmalloc_mutex_postfork_parent(&huge_mtx);\n}\n\nvoid\nhuge_postfork_child(void)\n{\n\n\tmalloc_mutex_postfork_child(&huge_mtx);\n}\n"
  },
  {
    "path": "extern/deprecated/redis-2.8.21/deps/jemalloc/src/jemalloc.c",
    "content": "#define\tJEMALLOC_C_\n#include \"jemalloc/internal/jemalloc_internal.h\"\n\n/******************************************************************************/\n/* Data. */\n\nmalloc_tsd_data(, arenas, arena_t *, NULL)\nmalloc_tsd_data(, thread_allocated, thread_allocated_t,\n    THREAD_ALLOCATED_INITIALIZER)\n\n/* Runtime configuration options. */\nconst char\t*je_malloc_conf;\nbool\topt_abort =\n#ifdef JEMALLOC_DEBUG\n    true\n#else\n    false\n#endif\n    ;\nbool\topt_junk =\n#if (defined(JEMALLOC_DEBUG) && defined(JEMALLOC_FILL))\n    true\n#else\n    false\n#endif\n    ;\nsize_t\topt_quarantine = ZU(0);\nbool\topt_redzone = false;\nbool\topt_utrace = false;\nbool\topt_valgrind = false;\nbool\topt_xmalloc = false;\nbool\topt_zero = false;\nsize_t\topt_narenas = 0;\n\nunsigned\tncpus;\n\nmalloc_mutex_t\t\tarenas_lock;\narena_t\t\t\t**arenas;\nunsigned\t\tnarenas_total;\nunsigned\t\tnarenas_auto;\n\n/* Set to true once the allocator has been initialized. */\nstatic bool\t\tmalloc_initialized = false;\n\n#ifdef JEMALLOC_THREADED_INIT\n/* Used to let the initializing thread recursively allocate. */\n#  define NO_INITIALIZER\t((unsigned long)0)\n#  define INITIALIZER\t\tpthread_self()\n#  define IS_INITIALIZER\t(malloc_initializer == pthread_self())\nstatic pthread_t\t\tmalloc_initializer = NO_INITIALIZER;\n#else\n#  define NO_INITIALIZER\tfalse\n#  define INITIALIZER\t\ttrue\n#  define IS_INITIALIZER\tmalloc_initializer\nstatic bool\t\t\tmalloc_initializer = NO_INITIALIZER;\n#endif\n\n/* Used to avoid initialization races. */\n#ifdef _WIN32\nstatic malloc_mutex_t\tinit_lock;\n\nJEMALLOC_ATTR(constructor)\nstatic void WINAPI\n_init_init_lock(void)\n{\n\n\tmalloc_mutex_init(&init_lock);\n}\n\n#ifdef _MSC_VER\n#  pragma section(\".CRT$XCU\", read)\nJEMALLOC_SECTION(\".CRT$XCU\") JEMALLOC_ATTR(used)\nstatic const void (WINAPI *init_init_lock)(void) = _init_init_lock;\n#endif\n\n#else\nstatic malloc_mutex_t\tinit_lock = MALLOC_MUTEX_INITIALIZER;\n#endif\n\ntypedef struct {\n\tvoid\t*p;\t/* Input pointer (as in realloc(p, s)). */\n\tsize_t\ts;\t/* Request size. */\n\tvoid\t*r;\t/* Result pointer. */\n} malloc_utrace_t;\n\n#ifdef JEMALLOC_UTRACE\n#  define UTRACE(a, b, c) do {\t\t\t\t\t\t\\\n\tif (opt_utrace) {\t\t\t\t\t\t\\\n\t\tint utrace_serrno = errno;\t\t\t\t\\\n\t\tmalloc_utrace_t ut;\t\t\t\t\t\\\n\t\tut.p = (a);\t\t\t\t\t\t\\\n\t\tut.s = (b);\t\t\t\t\t\t\\\n\t\tut.r = (c);\t\t\t\t\t\t\\\n\t\tutrace(&ut, sizeof(ut));\t\t\t\t\\\n\t\terrno = utrace_serrno;\t\t\t\t\t\\\n\t}\t\t\t\t\t\t\t\t\\\n} while (0)\n#else\n#  define UTRACE(a, b, c)\n#endif\n\n/******************************************************************************/\n/*\n * Function prototypes for static functions that are referenced prior to\n * definition.\n */\n\nstatic bool\tmalloc_init_hard(void);\n\n/******************************************************************************/\n/*\n * Begin miscellaneous support functions.\n */\n\n/* Create a new arena and insert it into the arenas array at index ind. */\narena_t *\narenas_extend(unsigned ind)\n{\n\tarena_t *ret;\n\n\tret = (arena_t *)base_alloc(sizeof(arena_t));\n\tif (ret != NULL && arena_new(ret, ind) == false) {\n\t\tarenas[ind] = ret;\n\t\treturn (ret);\n\t}\n\t/* Only reached if there is an OOM error. */\n\n\t/*\n\t * OOM here is quite inconvenient to propagate, since dealing with it\n\t * would require a check for failure in the fast path.  Instead, punt\n\t * by using arenas[0].  In practice, this is an extremely unlikely\n\t * failure.\n\t */\n\tmalloc_write(\"<jemalloc>: Error initializing arena\\n\");\n\tif (opt_abort)\n\t\tabort();\n\n\treturn (arenas[0]);\n}\n\n/* Slow path, called only by choose_arena(). */\narena_t *\nchoose_arena_hard(void)\n{\n\tarena_t *ret;\n\n\tif (narenas_auto > 1) {\n\t\tunsigned i, choose, first_null;\n\n\t\tchoose = 0;\n\t\tfirst_null = narenas_auto;\n\t\tmalloc_mutex_lock(&arenas_lock);\n\t\tassert(arenas[0] != NULL);\n\t\tfor (i = 1; i < narenas_auto; i++) {\n\t\t\tif (arenas[i] != NULL) {\n\t\t\t\t/*\n\t\t\t\t * Choose the first arena that has the lowest\n\t\t\t\t * number of threads assigned to it.\n\t\t\t\t */\n\t\t\t\tif (arenas[i]->nthreads <\n\t\t\t\t    arenas[choose]->nthreads)\n\t\t\t\t\tchoose = i;\n\t\t\t} else if (first_null == narenas_auto) {\n\t\t\t\t/*\n\t\t\t\t * Record the index of the first uninitialized\n\t\t\t\t * arena, in case all extant arenas are in use.\n\t\t\t\t *\n\t\t\t\t * NB: It is possible for there to be\n\t\t\t\t * discontinuities in terms of initialized\n\t\t\t\t * versus uninitialized arenas, due to the\n\t\t\t\t * \"thread.arena\" mallctl.\n\t\t\t\t */\n\t\t\t\tfirst_null = i;\n\t\t\t}\n\t\t}\n\n\t\tif (arenas[choose]->nthreads == 0\n\t\t    || first_null == narenas_auto) {\n\t\t\t/*\n\t\t\t * Use an unloaded arena, or the least loaded arena if\n\t\t\t * all arenas are already initialized.\n\t\t\t */\n\t\t\tret = arenas[choose];\n\t\t} else {\n\t\t\t/* Initialize a new arena. */\n\t\t\tret = arenas_extend(first_null);\n\t\t}\n\t\tret->nthreads++;\n\t\tmalloc_mutex_unlock(&arenas_lock);\n\t} else {\n\t\tret = arenas[0];\n\t\tmalloc_mutex_lock(&arenas_lock);\n\t\tret->nthreads++;\n\t\tmalloc_mutex_unlock(&arenas_lock);\n\t}\n\n\tarenas_tsd_set(&ret);\n\n\treturn (ret);\n}\n\nstatic void\nstats_print_atexit(void)\n{\n\n\tif (config_tcache && config_stats) {\n\t\tunsigned narenas, i;\n\n\t\t/*\n\t\t * Merge stats from extant threads.  This is racy, since\n\t\t * individual threads do not lock when recording tcache stats\n\t\t * events.  As a consequence, the final stats may be slightly\n\t\t * out of date by the time they are reported, if other threads\n\t\t * continue to allocate.\n\t\t */\n\t\tfor (i = 0, narenas = narenas_total_get(); i < narenas; i++) {\n\t\t\tarena_t *arena = arenas[i];\n\t\t\tif (arena != NULL) {\n\t\t\t\ttcache_t *tcache;\n\n\t\t\t\t/*\n\t\t\t\t * tcache_stats_merge() locks bins, so if any\n\t\t\t\t * code is introduced that acquires both arena\n\t\t\t\t * and bin locks in the opposite order,\n\t\t\t\t * deadlocks may result.\n\t\t\t\t */\n\t\t\t\tmalloc_mutex_lock(&arena->lock);\n\t\t\t\tql_foreach(tcache, &arena->tcache_ql, link) {\n\t\t\t\t\ttcache_stats_merge(tcache, arena);\n\t\t\t\t}\n\t\t\t\tmalloc_mutex_unlock(&arena->lock);\n\t\t\t}\n\t\t}\n\t}\n\tje_malloc_stats_print(NULL, NULL, NULL);\n}\n\n/*\n * End miscellaneous support functions.\n */\n/******************************************************************************/\n/*\n * Begin initialization functions.\n */\n\nstatic unsigned\nmalloc_ncpus(void)\n{\n\tlong result;\n\n#ifdef _WIN32\n\tSYSTEM_INFO si;\n\tGetSystemInfo(&si);\n\tresult = si.dwNumberOfProcessors;\n#else\n\tresult = sysconf(_SC_NPROCESSORS_ONLN);\n#endif\n\treturn ((result == -1) ? 1 : (unsigned)result);\n}\n\nvoid\narenas_cleanup(void *arg)\n{\n\tarena_t *arena = *(arena_t **)arg;\n\n\tmalloc_mutex_lock(&arenas_lock);\n\tarena->nthreads--;\n\tmalloc_mutex_unlock(&arenas_lock);\n}\n\nJEMALLOC_ALWAYS_INLINE_C void\nmalloc_thread_init(void)\n{\n\n\t/*\n\t * TSD initialization can't be safely done as a side effect of\n\t * deallocation, because it is possible for a thread to do nothing but\n\t * deallocate its TLS data via free(), in which case writing to TLS\n\t * would cause write-after-free memory corruption.  The quarantine\n\t * facility *only* gets used as a side effect of deallocation, so make\n\t * a best effort attempt at initializing its TSD by hooking all\n\t * allocation events.\n\t */\n\tif (config_fill && opt_quarantine)\n\t\tquarantine_alloc_hook();\n}\n\nJEMALLOC_ALWAYS_INLINE_C bool\nmalloc_init(void)\n{\n\n\tif (malloc_initialized == false && malloc_init_hard())\n\t\treturn (true);\n\tmalloc_thread_init();\n\n\treturn (false);\n}\n\nstatic bool\nmalloc_conf_next(char const **opts_p, char const **k_p, size_t *klen_p,\n    char const **v_p, size_t *vlen_p)\n{\n\tbool accept;\n\tconst char *opts = *opts_p;\n\n\t*k_p = opts;\n\n\tfor (accept = false; accept == false;) {\n\t\tswitch (*opts) {\n\t\tcase 'A': case 'B': case 'C': case 'D': case 'E': case 'F':\n\t\tcase 'G': case 'H': case 'I': case 'J': case 'K': case 'L':\n\t\tcase 'M': case 'N': case 'O': case 'P': case 'Q': case 'R':\n\t\tcase 'S': case 'T': case 'U': case 'V': case 'W': case 'X':\n\t\tcase 'Y': case 'Z':\n\t\tcase 'a': case 'b': case 'c': case 'd': case 'e': case 'f':\n\t\tcase 'g': case 'h': case 'i': case 'j': case 'k': case 'l':\n\t\tcase 'm': case 'n': case 'o': case 'p': case 'q': case 'r':\n\t\tcase 's': case 't': case 'u': case 'v': case 'w': case 'x':\n\t\tcase 'y': case 'z':\n\t\tcase '0': case '1': case '2': case '3': case '4': case '5':\n\t\tcase '6': case '7': case '8': case '9':\n\t\tcase '_':\n\t\t\topts++;\n\t\t\tbreak;\n\t\tcase ':':\n\t\t\topts++;\n\t\t\t*klen_p = (uintptr_t)opts - 1 - (uintptr_t)*k_p;\n\t\t\t*v_p = opts;\n\t\t\taccept = true;\n\t\t\tbreak;\n\t\tcase '\\0':\n\t\t\tif (opts != *opts_p) {\n\t\t\t\tmalloc_write(\"<jemalloc>: Conf string ends \"\n\t\t\t\t    \"with key\\n\");\n\t\t\t}\n\t\t\treturn (true);\n\t\tdefault:\n\t\t\tmalloc_write(\"<jemalloc>: Malformed conf string\\n\");\n\t\t\treturn (true);\n\t\t}\n\t}\n\n\tfor (accept = false; accept == false;) {\n\t\tswitch (*opts) {\n\t\tcase ',':\n\t\t\topts++;\n\t\t\t/*\n\t\t\t * Look ahead one character here, because the next time\n\t\t\t * this function is called, it will assume that end of\n\t\t\t * input has been cleanly reached if no input remains,\n\t\t\t * but we have optimistically already consumed the\n\t\t\t * comma if one exists.\n\t\t\t */\n\t\t\tif (*opts == '\\0') {\n\t\t\t\tmalloc_write(\"<jemalloc>: Conf string ends \"\n\t\t\t\t    \"with comma\\n\");\n\t\t\t}\n\t\t\t*vlen_p = (uintptr_t)opts - 1 - (uintptr_t)*v_p;\n\t\t\taccept = true;\n\t\t\tbreak;\n\t\tcase '\\0':\n\t\t\t*vlen_p = (uintptr_t)opts - (uintptr_t)*v_p;\n\t\t\taccept = true;\n\t\t\tbreak;\n\t\tdefault:\n\t\t\topts++;\n\t\t\tbreak;\n\t\t}\n\t}\n\n\t*opts_p = opts;\n\treturn (false);\n}\n\nstatic void\nmalloc_conf_error(const char *msg, const char *k, size_t klen, const char *v,\n    size_t vlen)\n{\n\n\tmalloc_printf(\"<jemalloc>: %s: %.*s:%.*s\\n\", msg, (int)klen, k,\n\t    (int)vlen, v);\n}\n\nstatic void\nmalloc_conf_init(void)\n{\n\tunsigned i;\n\tchar buf[PATH_MAX + 1];\n\tconst char *opts, *k, *v;\n\tsize_t klen, vlen;\n\n\t/*\n\t * Automatically configure valgrind before processing options.  The\n\t * valgrind option remains in jemalloc 3.x for compatibility reasons.\n\t */\n\tif (config_valgrind) {\n\t\topt_valgrind = (RUNNING_ON_VALGRIND != 0) ? true : false;\n\t\tif (config_fill && opt_valgrind) {\n\t\t\topt_junk = false;\n\t\t\tassert(opt_zero == false);\n\t\t\topt_quarantine = JEMALLOC_VALGRIND_QUARANTINE_DEFAULT;\n\t\t\topt_redzone = true;\n\t\t}\n\t\tif (config_tcache && opt_valgrind)\n\t\t\topt_tcache = false;\n\t}\n\n\tfor (i = 0; i < 3; i++) {\n\t\t/* Get runtime configuration. */\n\t\tswitch (i) {\n\t\tcase 0:\n\t\t\tif (je_malloc_conf != NULL) {\n\t\t\t\t/*\n\t\t\t\t * Use options that were compiled into the\n\t\t\t\t * program.\n\t\t\t\t */\n\t\t\t\topts = je_malloc_conf;\n\t\t\t} else {\n\t\t\t\t/* No configuration specified. */\n\t\t\t\tbuf[0] = '\\0';\n\t\t\t\topts = buf;\n\t\t\t}\n\t\t\tbreak;\n\t\tcase 1: {\n\t\t\tint linklen = 0;\n#ifndef _WIN32\n\t\t\tint saved_errno = errno;\n\t\t\tconst char *linkname =\n#  ifdef JEMALLOC_PREFIX\n\t\t\t    \"/etc/\"JEMALLOC_PREFIX\"malloc.conf\"\n#  else\n\t\t\t    \"/etc/malloc.conf\"\n#  endif\n\t\t\t    ;\n\n\t\t\t/*\n\t\t\t * Try to use the contents of the \"/etc/malloc.conf\"\n\t\t\t * symbolic link's name.\n\t\t\t */\n\t\t\tlinklen = readlink(linkname, buf, sizeof(buf) - 1);\n\t\t\tif (linklen == -1) {\n\t\t\t\t/* No configuration specified. */\n\t\t\t\tlinklen = 0;\n\t\t\t\t/* restore errno */\n\t\t\t\tset_errno(saved_errno);\n\t\t\t}\n#endif\n\t\t\tbuf[linklen] = '\\0';\n\t\t\topts = buf;\n\t\t\tbreak;\n\t\t} case 2: {\n\t\t\tconst char *envname =\n#ifdef JEMALLOC_PREFIX\n\t\t\t    JEMALLOC_CPREFIX\"MALLOC_CONF\"\n#else\n\t\t\t    \"MALLOC_CONF\"\n#endif\n\t\t\t    ;\n\n\t\t\tif ((opts = getenv(envname)) != NULL) {\n\t\t\t\t/*\n\t\t\t\t * Do nothing; opts is already initialized to\n\t\t\t\t * the value of the MALLOC_CONF environment\n\t\t\t\t * variable.\n\t\t\t\t */\n\t\t\t} else {\n\t\t\t\t/* No configuration specified. */\n\t\t\t\tbuf[0] = '\\0';\n\t\t\t\topts = buf;\n\t\t\t}\n\t\t\tbreak;\n\t\t} default:\n\t\t\tnot_reached();\n\t\t\tbuf[0] = '\\0';\n\t\t\topts = buf;\n\t\t}\n\n\t\twhile (*opts != '\\0' && malloc_conf_next(&opts, &k, &klen, &v,\n\t\t    &vlen) == false) {\n#define\tCONF_HANDLE_BOOL(o, n)\t\t\t\t\t\t\\\n\t\t\tif (sizeof(n)-1 == klen && strncmp(n, k,\t\\\n\t\t\t    klen) == 0) {\t\t\t\t\\\n\t\t\t\tif (strncmp(\"true\", v, vlen) == 0 &&\t\\\n\t\t\t\t    vlen == sizeof(\"true\")-1)\t\t\\\n\t\t\t\t\to = true;\t\t\t\\\n\t\t\t\telse if (strncmp(\"false\", v, vlen) ==\t\\\n\t\t\t\t    0 && vlen == sizeof(\"false\")-1)\t\\\n\t\t\t\t\to = false;\t\t\t\\\n\t\t\t\telse {\t\t\t\t\t\\\n\t\t\t\t\tmalloc_conf_error(\t\t\\\n\t\t\t\t\t    \"Invalid conf value\",\t\\\n\t\t\t\t\t    k, klen, v, vlen);\t\t\\\n\t\t\t\t}\t\t\t\t\t\\\n\t\t\t\tcontinue;\t\t\t\t\\\n\t\t\t}\n#define\tCONF_HANDLE_SIZE_T(o, n, min, max, clip)\t\t\t\\\n\t\t\tif (sizeof(n)-1 == klen && strncmp(n, k,\t\\\n\t\t\t    klen) == 0) {\t\t\t\t\\\n\t\t\t\tuintmax_t um;\t\t\t\t\\\n\t\t\t\tchar *end;\t\t\t\t\\\n\t\t\t\t\t\t\t\t\t\\\n\t\t\t\tset_errno(0);\t\t\t\t\\\n\t\t\t\tum = malloc_strtoumax(v, &end, 0);\t\\\n\t\t\t\tif (get_errno() != 0 || (uintptr_t)end -\\\n\t\t\t\t    (uintptr_t)v != vlen) {\t\t\\\n\t\t\t\t\tmalloc_conf_error(\t\t\\\n\t\t\t\t\t    \"Invalid conf value\",\t\\\n\t\t\t\t\t    k, klen, v, vlen);\t\t\\\n\t\t\t\t} else if (clip) {\t\t\t\\\n\t\t\t\t\tif (min != 0 && um < min)\t\\\n\t\t\t\t\t\to = min;\t\t\\\n\t\t\t\t\telse if (um > max)\t\t\\\n\t\t\t\t\t\to = max;\t\t\\\n\t\t\t\t\telse\t\t\t\t\\\n\t\t\t\t\t\to = um;\t\t\t\\\n\t\t\t\t} else {\t\t\t\t\\\n\t\t\t\t\tif ((min != 0 && um < min) ||\t\\\n\t\t\t\t\t    um > max) {\t\t\t\\\n\t\t\t\t\t\tmalloc_conf_error(\t\\\n\t\t\t\t\t\t    \"Out-of-range \"\t\\\n\t\t\t\t\t\t    \"conf value\",\t\\\n\t\t\t\t\t\t    k, klen, v, vlen);\t\\\n\t\t\t\t\t} else\t\t\t\t\\\n\t\t\t\t\t\to = um;\t\t\t\\\n\t\t\t\t}\t\t\t\t\t\\\n\t\t\t\tcontinue;\t\t\t\t\\\n\t\t\t}\n#define\tCONF_HANDLE_SSIZE_T(o, n, min, max)\t\t\t\t\\\n\t\t\tif (sizeof(n)-1 == klen && strncmp(n, k,\t\\\n\t\t\t    klen) == 0) {\t\t\t\t\\\n\t\t\t\tlong l;\t\t\t\t\t\\\n\t\t\t\tchar *end;\t\t\t\t\\\n\t\t\t\t\t\t\t\t\t\\\n\t\t\t\tset_errno(0);\t\t\t\t\\\n\t\t\t\tl = strtol(v, &end, 0);\t\t\t\\\n\t\t\t\tif (get_errno() != 0 || (uintptr_t)end -\\\n\t\t\t\t    (uintptr_t)v != vlen) {\t\t\\\n\t\t\t\t\tmalloc_conf_error(\t\t\\\n\t\t\t\t\t    \"Invalid conf value\",\t\\\n\t\t\t\t\t    k, klen, v, vlen);\t\t\\\n\t\t\t\t} else if (l < (ssize_t)min || l >\t\\\n\t\t\t\t    (ssize_t)max) {\t\t\t\\\n\t\t\t\t\tmalloc_conf_error(\t\t\\\n\t\t\t\t\t    \"Out-of-range conf value\",\t\\\n\t\t\t\t\t    k, klen, v, vlen);\t\t\\\n\t\t\t\t} else\t\t\t\t\t\\\n\t\t\t\t\to = l;\t\t\t\t\\\n\t\t\t\tcontinue;\t\t\t\t\\\n\t\t\t}\n#define\tCONF_HANDLE_CHAR_P(o, n, d)\t\t\t\t\t\\\n\t\t\tif (sizeof(n)-1 == klen && strncmp(n, k,\t\\\n\t\t\t    klen) == 0) {\t\t\t\t\\\n\t\t\t\tsize_t cpylen = (vlen <=\t\t\\\n\t\t\t\t    sizeof(o)-1) ? vlen :\t\t\\\n\t\t\t\t    sizeof(o)-1;\t\t\t\\\n\t\t\t\tstrncpy(o, v, cpylen);\t\t\t\\\n\t\t\t\to[cpylen] = '\\0';\t\t\t\\\n\t\t\t\tcontinue;\t\t\t\t\\\n\t\t\t}\n\n\t\t\tCONF_HANDLE_BOOL(opt_abort, \"abort\")\n\t\t\t/*\n\t\t\t * Chunks always require at least one header page, plus\n\t\t\t * one data page in the absence of redzones, or three\n\t\t\t * pages in the presence of redzones.  In order to\n\t\t\t * simplify options processing, fix the limit based on\n\t\t\t * config_fill.\n\t\t\t */\n\t\t\tCONF_HANDLE_SIZE_T(opt_lg_chunk, \"lg_chunk\", LG_PAGE +\n\t\t\t    (config_fill ? 2 : 1), (sizeof(size_t) << 3) - 1,\n\t\t\t    true)\n\t\t\tif (strncmp(\"dss\", k, klen) == 0) {\n\t\t\t\tint i;\n\t\t\t\tbool match = false;\n\t\t\t\tfor (i = 0; i < dss_prec_limit; i++) {\n\t\t\t\t\tif (strncmp(dss_prec_names[i], v, vlen)\n\t\t\t\t\t    == 0) {\n\t\t\t\t\t\tif (chunk_dss_prec_set(i)) {\n\t\t\t\t\t\t\tmalloc_conf_error(\n\t\t\t\t\t\t\t    \"Error setting dss\",\n\t\t\t\t\t\t\t    k, klen, v, vlen);\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\topt_dss =\n\t\t\t\t\t\t\t    dss_prec_names[i];\n\t\t\t\t\t\t\tmatch = true;\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tif (match == false) {\n\t\t\t\t\tmalloc_conf_error(\"Invalid conf value\",\n\t\t\t\t\t    k, klen, v, vlen);\n\t\t\t\t}\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tCONF_HANDLE_SIZE_T(opt_narenas, \"narenas\", 1,\n\t\t\t    SIZE_T_MAX, false)\n\t\t\tCONF_HANDLE_SSIZE_T(opt_lg_dirty_mult, \"lg_dirty_mult\",\n\t\t\t    -1, (sizeof(size_t) << 3) - 1)\n\t\t\tCONF_HANDLE_BOOL(opt_stats_print, \"stats_print\")\n\t\t\tif (config_fill) {\n\t\t\t\tCONF_HANDLE_BOOL(opt_junk, \"junk\")\n\t\t\t\tCONF_HANDLE_SIZE_T(opt_quarantine, \"quarantine\",\n\t\t\t\t    0, SIZE_T_MAX, false)\n\t\t\t\tCONF_HANDLE_BOOL(opt_redzone, \"redzone\")\n\t\t\t\tCONF_HANDLE_BOOL(opt_zero, \"zero\")\n\t\t\t}\n\t\t\tif (config_utrace) {\n\t\t\t\tCONF_HANDLE_BOOL(opt_utrace, \"utrace\")\n\t\t\t}\n\t\t\tif (config_valgrind) {\n\t\t\t\tCONF_HANDLE_BOOL(opt_valgrind, \"valgrind\")\n\t\t\t}\n\t\t\tif (config_xmalloc) {\n\t\t\t\tCONF_HANDLE_BOOL(opt_xmalloc, \"xmalloc\")\n\t\t\t}\n\t\t\tif (config_tcache) {\n\t\t\t\tCONF_HANDLE_BOOL(opt_tcache, \"tcache\")\n\t\t\t\tCONF_HANDLE_SSIZE_T(opt_lg_tcache_max,\n\t\t\t\t    \"lg_tcache_max\", -1,\n\t\t\t\t    (sizeof(size_t) << 3) - 1)\n\t\t\t}\n\t\t\tif (config_prof) {\n\t\t\t\tCONF_HANDLE_BOOL(opt_prof, \"prof\")\n\t\t\t\tCONF_HANDLE_CHAR_P(opt_prof_prefix,\n\t\t\t\t    \"prof_prefix\", \"jeprof\")\n\t\t\t\tCONF_HANDLE_BOOL(opt_prof_active, \"prof_active\")\n\t\t\t\tCONF_HANDLE_SSIZE_T(opt_lg_prof_sample,\n\t\t\t\t    \"lg_prof_sample\", 0,\n\t\t\t\t    (sizeof(uint64_t) << 3) - 1)\n\t\t\t\tCONF_HANDLE_BOOL(opt_prof_accum, \"prof_accum\")\n\t\t\t\tCONF_HANDLE_SSIZE_T(opt_lg_prof_interval,\n\t\t\t\t    \"lg_prof_interval\", -1,\n\t\t\t\t    (sizeof(uint64_t) << 3) - 1)\n\t\t\t\tCONF_HANDLE_BOOL(opt_prof_gdump, \"prof_gdump\")\n\t\t\t\tCONF_HANDLE_BOOL(opt_prof_final, \"prof_final\")\n\t\t\t\tCONF_HANDLE_BOOL(opt_prof_leak, \"prof_leak\")\n\t\t\t}\n\t\t\tmalloc_conf_error(\"Invalid conf pair\", k, klen, v,\n\t\t\t    vlen);\n#undef CONF_HANDLE_BOOL\n#undef CONF_HANDLE_SIZE_T\n#undef CONF_HANDLE_SSIZE_T\n#undef CONF_HANDLE_CHAR_P\n\t\t}\n\t}\n}\n\nstatic bool\nmalloc_init_hard(void)\n{\n\tarena_t *init_arenas[1];\n\n\tmalloc_mutex_lock(&init_lock);\n\tif (malloc_initialized || IS_INITIALIZER) {\n\t\t/*\n\t\t * Another thread initialized the allocator before this one\n\t\t * acquired init_lock, or this thread is the initializing\n\t\t * thread, and it is recursively allocating.\n\t\t */\n\t\tmalloc_mutex_unlock(&init_lock);\n\t\treturn (false);\n\t}\n#ifdef JEMALLOC_THREADED_INIT\n\tif (malloc_initializer != NO_INITIALIZER && IS_INITIALIZER == false) {\n\t\t/* Busy-wait until the initializing thread completes. */\n\t\tdo {\n\t\t\tmalloc_mutex_unlock(&init_lock);\n\t\t\tCPU_SPINWAIT;\n\t\t\tmalloc_mutex_lock(&init_lock);\n\t\t} while (malloc_initialized == false);\n\t\tmalloc_mutex_unlock(&init_lock);\n\t\treturn (false);\n\t}\n#endif\n\tmalloc_initializer = INITIALIZER;\n\n\tmalloc_tsd_boot();\n\tif (config_prof)\n\t\tprof_boot0();\n\n\tmalloc_conf_init();\n\n\tif (opt_stats_print) {\n\t\t/* Print statistics at exit. */\n\t\tif (atexit(stats_print_atexit) != 0) {\n\t\t\tmalloc_write(\"<jemalloc>: Error in atexit()\\n\");\n\t\t\tif (opt_abort)\n\t\t\t\tabort();\n\t\t}\n\t}\n\n\tif (base_boot()) {\n\t\tmalloc_mutex_unlock(&init_lock);\n\t\treturn (true);\n\t}\n\n\tif (chunk_boot()) {\n\t\tmalloc_mutex_unlock(&init_lock);\n\t\treturn (true);\n\t}\n\n\tif (ctl_boot()) {\n\t\tmalloc_mutex_unlock(&init_lock);\n\t\treturn (true);\n\t}\n\n\tif (config_prof)\n\t\tprof_boot1();\n\n\tarena_boot();\n\n\tif (config_tcache && tcache_boot0()) {\n\t\tmalloc_mutex_unlock(&init_lock);\n\t\treturn (true);\n\t}\n\n\tif (huge_boot()) {\n\t\tmalloc_mutex_unlock(&init_lock);\n\t\treturn (true);\n\t}\n\n\tif (malloc_mutex_init(&arenas_lock)) {\n\t\tmalloc_mutex_unlock(&init_lock);\n\t\treturn (true);\n\t}\n\n\t/*\n\t * Create enough scaffolding to allow recursive allocation in\n\t * malloc_ncpus().\n\t */\n\tnarenas_total = narenas_auto = 1;\n\tarenas = init_arenas;\n\tmemset(arenas, 0, sizeof(arena_t *) * narenas_auto);\n\n\t/*\n\t * Initialize one arena here.  The rest are lazily created in\n\t * choose_arena_hard().\n\t */\n\tarenas_extend(0);\n\tif (arenas[0] == NULL) {\n\t\tmalloc_mutex_unlock(&init_lock);\n\t\treturn (true);\n\t}\n\n\t/* Initialize allocation counters before any allocations can occur. */\n\tif (config_stats && thread_allocated_tsd_boot()) {\n\t\tmalloc_mutex_unlock(&init_lock);\n\t\treturn (true);\n\t}\n\n\tif (arenas_tsd_boot()) {\n\t\tmalloc_mutex_unlock(&init_lock);\n\t\treturn (true);\n\t}\n\n\tif (config_tcache && tcache_boot1()) {\n\t\tmalloc_mutex_unlock(&init_lock);\n\t\treturn (true);\n\t}\n\n\tif (config_fill && quarantine_boot()) {\n\t\tmalloc_mutex_unlock(&init_lock);\n\t\treturn (true);\n\t}\n\n\tif (config_prof && prof_boot2()) {\n\t\tmalloc_mutex_unlock(&init_lock);\n\t\treturn (true);\n\t}\n\n\tmalloc_mutex_unlock(&init_lock);\n\t/**********************************************************************/\n\t/* Recursive allocation may follow. */\n\n\tncpus = malloc_ncpus();\n\n#if (!defined(JEMALLOC_MUTEX_INIT_CB) && !defined(JEMALLOC_ZONE) \\\n    && !defined(_WIN32))\n\t/* LinuxThreads's pthread_atfork() allocates. */\n\tif (pthread_atfork(jemalloc_prefork, jemalloc_postfork_parent,\n\t    jemalloc_postfork_child) != 0) {\n\t\tmalloc_write(\"<jemalloc>: Error in pthread_atfork()\\n\");\n\t\tif (opt_abort)\n\t\t\tabort();\n\t}\n#endif\n\n\t/* Done recursively allocating. */\n\t/**********************************************************************/\n\tmalloc_mutex_lock(&init_lock);\n\n\tif (mutex_boot()) {\n\t\tmalloc_mutex_unlock(&init_lock);\n\t\treturn (true);\n\t}\n\n\tif (opt_narenas == 0) {\n\t\t/*\n\t\t * For SMP systems, create more than one arena per CPU by\n\t\t * default.\n\t\t */\n\t\tif (ncpus > 1)\n\t\t\topt_narenas = ncpus << 2;\n\t\telse\n\t\t\topt_narenas = 1;\n\t}\n\tnarenas_auto = opt_narenas;\n\t/*\n\t * Make sure that the arenas array can be allocated.  In practice, this\n\t * limit is enough to allow the allocator to function, but the ctl\n\t * machinery will fail to allocate memory at far lower limits.\n\t */\n\tif (narenas_auto > chunksize / sizeof(arena_t *)) {\n\t\tnarenas_auto = chunksize / sizeof(arena_t *);\n\t\tmalloc_printf(\"<jemalloc>: Reducing narenas to limit (%d)\\n\",\n\t\t    narenas_auto);\n\t}\n\tnarenas_total = narenas_auto;\n\n\t/* Allocate and initialize arenas. */\n\tarenas = (arena_t **)base_alloc(sizeof(arena_t *) * narenas_total);\n\tif (arenas == NULL) {\n\t\tmalloc_mutex_unlock(&init_lock);\n\t\treturn (true);\n\t}\n\t/*\n\t * Zero the array.  In practice, this should always be pre-zeroed,\n\t * since it was just mmap()ed, but let's be sure.\n\t */\n\tmemset(arenas, 0, sizeof(arena_t *) * narenas_total);\n\t/* Copy the pointer to the one arena that was already initialized. */\n\tarenas[0] = init_arenas[0];\n\n\tmalloc_initialized = true;\n\tmalloc_mutex_unlock(&init_lock);\n\n\treturn (false);\n}\n\n/*\n * End initialization functions.\n */\n/******************************************************************************/\n/*\n * Begin malloc(3)-compatible functions.\n */\n\nstatic void *\nimalloc_prof_sample(size_t usize, prof_thr_cnt_t *cnt)\n{\n\tvoid *p;\n\n\tif (cnt == NULL)\n\t\treturn (NULL);\n\tif (prof_promote && usize <= SMALL_MAXCLASS) {\n\t\tp = imalloc(SMALL_MAXCLASS+1);\n\t\tif (p == NULL)\n\t\t\treturn (NULL);\n\t\tarena_prof_promoted(p, usize);\n\t} else\n\t\tp = imalloc(usize);\n\n\treturn (p);\n}\n\nJEMALLOC_ALWAYS_INLINE_C void *\nimalloc_prof(size_t usize, prof_thr_cnt_t *cnt)\n{\n\tvoid *p;\n\n\tif ((uintptr_t)cnt != (uintptr_t)1U)\n\t\tp = imalloc_prof_sample(usize, cnt);\n\telse\n\t\tp = imalloc(usize);\n\tif (p == NULL)\n\t\treturn (NULL);\n\tprof_malloc(p, usize, cnt);\n\n\treturn (p);\n}\n\n/*\n * MALLOC_BODY() is a macro rather than a function because its contents are in\n * the fast path, but inlining would cause reliability issues when determining\n * how many frames to discard from heap profiling backtraces.\n */\n#define\tMALLOC_BODY(ret, size, usize) do {\t\t\t\t\\\n\tif (malloc_init())\t\t\t\t\t\t\\\n\t\tret = NULL;\t\t\t\t\t\t\\\n\telse {\t\t\t\t\t\t\t\t\\\n\t\tif (config_prof && opt_prof) {\t\t\t\t\\\n\t\t\tprof_thr_cnt_t *cnt;\t\t\t\t\\\n\t\t\t\t\t\t\t\t\t\\\n\t\t\tusize = s2u(size);\t\t\t\t\\\n\t\t\t/*\t\t\t\t\t\t\\\n\t\t\t * Call PROF_ALLOC_PREP() here rather than in\t\\\n\t\t\t * imalloc_prof() so that imalloc_prof() can be\t\\\n\t\t\t * inlined without introducing uncertainty\t\\\n\t\t\t * about the number of backtrace frames to\t\\\n\t\t\t * ignore.  imalloc_prof() is in the fast path\t\\\n\t\t\t * when heap profiling is enabled, so inlining\t\\\n\t\t\t * is critical to performance.  (For\t\t\\\n\t\t\t * consistency all callers of PROF_ALLOC_PREP()\t\\\n\t\t\t * are structured similarly, even though e.g.\t\\\n\t\t\t * realloc() isn't called enough for inlining\t\\\n\t\t\t * to be critical.)\t\t\t\t\\\n\t\t\t */\t\t\t\t\t\t\\\n\t\t\tPROF_ALLOC_PREP(1, usize, cnt);\t\t\t\\\n\t\t\tret = imalloc_prof(usize, cnt);\t\t\t\\\n\t\t} else {\t\t\t\t\t\t\\\n\t\t\tif (config_stats || (config_valgrind &&\t\t\\\n\t\t\t    opt_valgrind))\t\t\t\t\\\n\t\t\t\tusize = s2u(size);\t\t\t\\\n\t\t\tret = imalloc(size);\t\t\t\t\\\n\t\t}\t\t\t\t\t\t\t\\\n\t}\t\t\t\t\t\t\t\t\\\n} while (0)\n\nvoid *\nje_malloc(size_t size)\n{\n\tvoid *ret;\n\tsize_t usize JEMALLOC_CC_SILENCE_INIT(0);\n\n\tif (size == 0)\n\t\tsize = 1;\n\n\tMALLOC_BODY(ret, size, usize);\n\n\tif (ret == NULL) {\n\t\tif (config_xmalloc && opt_xmalloc) {\n\t\t\tmalloc_write(\"<jemalloc>: Error in malloc(): \"\n\t\t\t    \"out of memory\\n\");\n\t\t\tabort();\n\t\t}\n\t\tset_errno(ENOMEM);\n\t}\n\tif (config_stats && ret != NULL) {\n\t\tassert(usize == isalloc(ret, config_prof));\n\t\tthread_allocated_tsd_get()->allocated += usize;\n\t}\n\tUTRACE(0, size, ret);\n\tJEMALLOC_VALGRIND_MALLOC(ret != NULL, ret, usize, false);\n\treturn (ret);\n}\n\nstatic void *\nimemalign_prof_sample(size_t alignment, size_t usize, prof_thr_cnt_t *cnt)\n{\n\tvoid *p;\n\n\tif (cnt == NULL)\n\t\treturn (NULL);\n\tif (prof_promote && usize <= SMALL_MAXCLASS) {\n\t\tassert(sa2u(SMALL_MAXCLASS+1, alignment) != 0);\n\t\tp = ipalloc(sa2u(SMALL_MAXCLASS+1, alignment), alignment,\n\t\t    false);\n\t\tif (p == NULL)\n\t\t\treturn (NULL);\n\t\tarena_prof_promoted(p, usize);\n\t} else\n\t\tp = ipalloc(usize, alignment, false);\n\n\treturn (p);\n}\n\nJEMALLOC_ALWAYS_INLINE_C void *\nimemalign_prof(size_t alignment, size_t usize, prof_thr_cnt_t *cnt)\n{\n\tvoid *p;\n\n\tif ((uintptr_t)cnt != (uintptr_t)1U)\n\t\tp = imemalign_prof_sample(alignment, usize, cnt);\n\telse\n\t\tp = ipalloc(usize, alignment, false);\n\tif (p == NULL)\n\t\treturn (NULL);\n\tprof_malloc(p, usize, cnt);\n\n\treturn (p);\n}\n\nJEMALLOC_ATTR(nonnull(1))\n#ifdef JEMALLOC_PROF\n/*\n * Avoid any uncertainty as to how many backtrace frames to ignore in\n * PROF_ALLOC_PREP().\n */\nJEMALLOC_NOINLINE\n#endif\nstatic int\nimemalign(void **memptr, size_t alignment, size_t size, size_t min_alignment)\n{\n\tint ret;\n\tsize_t usize;\n\tvoid *result;\n\n\tassert(min_alignment != 0);\n\n\tif (malloc_init()) {\n\t\tresult = NULL;\n\t\tgoto label_oom;\n\t} else {\n\t\tif (size == 0)\n\t\t\tsize = 1;\n\n\t\t/* Make sure that alignment is a large enough power of 2. */\n\t\tif (((alignment - 1) & alignment) != 0\n\t\t    || (alignment < min_alignment)) {\n\t\t\tif (config_xmalloc && opt_xmalloc) {\n\t\t\t\tmalloc_write(\"<jemalloc>: Error allocating \"\n\t\t\t\t    \"aligned memory: invalid alignment\\n\");\n\t\t\t\tabort();\n\t\t\t}\n\t\t\tresult = NULL;\n\t\t\tret = EINVAL;\n\t\t\tgoto label_return;\n\t\t}\n\n\t\tusize = sa2u(size, alignment);\n\t\tif (usize == 0) {\n\t\t\tresult = NULL;\n\t\t\tgoto label_oom;\n\t\t}\n\n\t\tif (config_prof && opt_prof) {\n\t\t\tprof_thr_cnt_t *cnt;\n\n\t\t\tPROF_ALLOC_PREP(2, usize, cnt);\n\t\t\tresult = imemalign_prof(alignment, usize, cnt);\n\t\t} else\n\t\t\tresult = ipalloc(usize, alignment, false);\n\t\tif (result == NULL)\n\t\t\tgoto label_oom;\n\t}\n\n\t*memptr = result;\n\tret = 0;\nlabel_return:\n\tif (config_stats && result != NULL) {\n\t\tassert(usize == isalloc(result, config_prof));\n\t\tthread_allocated_tsd_get()->allocated += usize;\n\t}\n\tUTRACE(0, size, result);\n\treturn (ret);\nlabel_oom:\n\tassert(result == NULL);\n\tif (config_xmalloc && opt_xmalloc) {\n\t\tmalloc_write(\"<jemalloc>: Error allocating aligned memory: \"\n\t\t    \"out of memory\\n\");\n\t\tabort();\n\t}\n\tret = ENOMEM;\n\tgoto label_return;\n}\n\nint\nje_posix_memalign(void **memptr, size_t alignment, size_t size)\n{\n\tint ret = imemalign(memptr, alignment, size, sizeof(void *));\n\tJEMALLOC_VALGRIND_MALLOC(ret == 0, *memptr, isalloc(*memptr,\n\t    config_prof), false);\n\treturn (ret);\n}\n\nvoid *\nje_aligned_alloc(size_t alignment, size_t size)\n{\n\tvoid *ret;\n\tint err;\n\n\tif ((err = imemalign(&ret, alignment, size, 1)) != 0) {\n\t\tret = NULL;\n\t\tset_errno(err);\n\t}\n\tJEMALLOC_VALGRIND_MALLOC(err == 0, ret, isalloc(ret, config_prof),\n\t    false);\n\treturn (ret);\n}\n\nstatic void *\nicalloc_prof_sample(size_t usize, prof_thr_cnt_t *cnt)\n{\n\tvoid *p;\n\n\tif (cnt == NULL)\n\t\treturn (NULL);\n\tif (prof_promote && usize <= SMALL_MAXCLASS) {\n\t\tp = icalloc(SMALL_MAXCLASS+1);\n\t\tif (p == NULL)\n\t\t\treturn (NULL);\n\t\tarena_prof_promoted(p, usize);\n\t} else\n\t\tp = icalloc(usize);\n\n\treturn (p);\n}\n\nJEMALLOC_ALWAYS_INLINE_C void *\nicalloc_prof(size_t usize, prof_thr_cnt_t *cnt)\n{\n\tvoid *p;\n\n\tif ((uintptr_t)cnt != (uintptr_t)1U)\n\t\tp = icalloc_prof_sample(usize, cnt);\n\telse\n\t\tp = icalloc(usize);\n\tif (p == NULL)\n\t\treturn (NULL);\n\tprof_malloc(p, usize, cnt);\n\n\treturn (p);\n}\n\nvoid *\nje_calloc(size_t num, size_t size)\n{\n\tvoid *ret;\n\tsize_t num_size;\n\tsize_t usize JEMALLOC_CC_SILENCE_INIT(0);\n\n\tif (malloc_init()) {\n\t\tnum_size = 0;\n\t\tret = NULL;\n\t\tgoto label_return;\n\t}\n\n\tnum_size = num * size;\n\tif (num_size == 0) {\n\t\tif (num == 0 || size == 0)\n\t\t\tnum_size = 1;\n\t\telse {\n\t\t\tret = NULL;\n\t\t\tgoto label_return;\n\t\t}\n\t/*\n\t * Try to avoid division here.  We know that it isn't possible to\n\t * overflow during multiplication if neither operand uses any of the\n\t * most significant half of the bits in a size_t.\n\t */\n\t} else if (((num | size) & (SIZE_T_MAX << (sizeof(size_t) << 2)))\n\t    && (num_size / size != num)) {\n\t\t/* size_t overflow. */\n\t\tret = NULL;\n\t\tgoto label_return;\n\t}\n\n\tif (config_prof && opt_prof) {\n\t\tprof_thr_cnt_t *cnt;\n\n\t\tusize = s2u(num_size);\n\t\tPROF_ALLOC_PREP(1, usize, cnt);\n\t\tret = icalloc_prof(usize, cnt);\n\t} else {\n\t\tif (config_stats || (config_valgrind && opt_valgrind))\n\t\t\tusize = s2u(num_size);\n\t\tret = icalloc(num_size);\n\t}\n\nlabel_return:\n\tif (ret == NULL) {\n\t\tif (config_xmalloc && opt_xmalloc) {\n\t\t\tmalloc_write(\"<jemalloc>: Error in calloc(): out of \"\n\t\t\t    \"memory\\n\");\n\t\t\tabort();\n\t\t}\n\t\tset_errno(ENOMEM);\n\t}\n\tif (config_stats && ret != NULL) {\n\t\tassert(usize == isalloc(ret, config_prof));\n\t\tthread_allocated_tsd_get()->allocated += usize;\n\t}\n\tUTRACE(0, num_size, ret);\n\tJEMALLOC_VALGRIND_MALLOC(ret != NULL, ret, usize, true);\n\treturn (ret);\n}\n\nstatic void *\nirealloc_prof_sample(void *oldptr, size_t usize, prof_thr_cnt_t *cnt)\n{\n\tvoid *p;\n\n\tif (cnt == NULL)\n\t\treturn (NULL);\n\tif (prof_promote && usize <= SMALL_MAXCLASS) {\n\t\tp = iralloc(oldptr, SMALL_MAXCLASS+1, 0, 0, false);\n\t\tif (p == NULL)\n\t\t\treturn (NULL);\n\t\tarena_prof_promoted(p, usize);\n\t} else\n\t\tp = iralloc(oldptr, usize, 0, 0, false);\n\n\treturn (p);\n}\n\nJEMALLOC_ALWAYS_INLINE_C void *\nirealloc_prof(void *oldptr, size_t old_usize, size_t usize, prof_thr_cnt_t *cnt)\n{\n\tvoid *p;\n\tprof_ctx_t *old_ctx;\n\n\told_ctx = prof_ctx_get(oldptr);\n\tif ((uintptr_t)cnt != (uintptr_t)1U)\n\t\tp = irealloc_prof_sample(oldptr, usize, cnt);\n\telse\n\t\tp = iralloc(oldptr, usize, 0, 0, false);\n\tif (p == NULL)\n\t\treturn (NULL);\n\tprof_realloc(p, usize, cnt, old_usize, old_ctx);\n\n\treturn (p);\n}\n\nJEMALLOC_INLINE_C void\nifree(void *ptr)\n{\n\tsize_t usize;\n\tUNUSED size_t rzsize JEMALLOC_CC_SILENCE_INIT(0);\n\n\tassert(ptr != NULL);\n\tassert(malloc_initialized || IS_INITIALIZER);\n\n\tif (config_prof && opt_prof) {\n\t\tusize = isalloc(ptr, config_prof);\n\t\tprof_free(ptr, usize);\n\t} else if (config_stats || config_valgrind)\n\t\tusize = isalloc(ptr, config_prof);\n\tif (config_stats)\n\t\tthread_allocated_tsd_get()->deallocated += usize;\n\tif (config_valgrind && opt_valgrind)\n\t\trzsize = p2rz(ptr);\n\tiqalloc(ptr);\n\tJEMALLOC_VALGRIND_FREE(ptr, rzsize);\n}\n\nvoid *\nje_realloc(void *ptr, size_t size)\n{\n\tvoid *ret;\n\tsize_t usize JEMALLOC_CC_SILENCE_INIT(0);\n\tsize_t old_usize = 0;\n\tUNUSED size_t old_rzsize JEMALLOC_CC_SILENCE_INIT(0);\n\n\tif (size == 0) {\n\t\tif (ptr != NULL) {\n\t\t\t/* realloc(ptr, 0) is equivalent to free(ptr). */\n\t\t\tUTRACE(ptr, 0, 0);\n\t\t\tifree(ptr);\n\t\t\treturn (NULL);\n\t\t}\n\t\tsize = 1;\n\t}\n\n\tif (ptr != NULL) {\n\t\tassert(malloc_initialized || IS_INITIALIZER);\n\t\tmalloc_thread_init();\n\n\t\tif ((config_prof && opt_prof) || config_stats ||\n\t\t    (config_valgrind && opt_valgrind))\n\t\t\told_usize = isalloc(ptr, config_prof);\n\t\tif (config_valgrind && opt_valgrind)\n\t\t\told_rzsize = config_prof ? p2rz(ptr) : u2rz(old_usize);\n\n\t\tif (config_prof && opt_prof) {\n\t\t\tprof_thr_cnt_t *cnt;\n\n\t\t\tusize = s2u(size);\n\t\t\tPROF_ALLOC_PREP(1, usize, cnt);\n\t\t\tret = irealloc_prof(ptr, old_usize, usize, cnt);\n\t\t} else {\n\t\t\tif (config_stats || (config_valgrind && opt_valgrind))\n\t\t\t\tusize = s2u(size);\n\t\t\tret = iralloc(ptr, size, 0, 0, false);\n\t\t}\n\t} else {\n\t\t/* realloc(NULL, size) is equivalent to malloc(size). */\n\t\tMALLOC_BODY(ret, size, usize);\n\t}\n\n\tif (ret == NULL) {\n\t\tif (config_xmalloc && opt_xmalloc) {\n\t\t\tmalloc_write(\"<jemalloc>: Error in realloc(): \"\n\t\t\t    \"out of memory\\n\");\n\t\t\tabort();\n\t\t}\n\t\tset_errno(ENOMEM);\n\t}\n\tif (config_stats && ret != NULL) {\n\t\tthread_allocated_t *ta;\n\t\tassert(usize == isalloc(ret, config_prof));\n\t\tta = thread_allocated_tsd_get();\n\t\tta->allocated += usize;\n\t\tta->deallocated += old_usize;\n\t}\n\tUTRACE(ptr, size, ret);\n\tJEMALLOC_VALGRIND_REALLOC(ret, usize, ptr, old_usize, old_rzsize,\n\t    false);\n\treturn (ret);\n}\n\nvoid\nje_free(void *ptr)\n{\n\n\tUTRACE(ptr, 0, 0);\n\tif (ptr != NULL)\n\t\tifree(ptr);\n}\n\n/*\n * End malloc(3)-compatible functions.\n */\n/******************************************************************************/\n/*\n * Begin non-standard override functions.\n */\n\n#ifdef JEMALLOC_OVERRIDE_MEMALIGN\nvoid *\nje_memalign(size_t alignment, size_t size)\n{\n\tvoid *ret JEMALLOC_CC_SILENCE_INIT(NULL);\n\timemalign(&ret, alignment, size, 1);\n\tJEMALLOC_VALGRIND_MALLOC(ret != NULL, ret, size, false);\n\treturn (ret);\n}\n#endif\n\n#ifdef JEMALLOC_OVERRIDE_VALLOC\nvoid *\nje_valloc(size_t size)\n{\n\tvoid *ret JEMALLOC_CC_SILENCE_INIT(NULL);\n\timemalign(&ret, PAGE, size, 1);\n\tJEMALLOC_VALGRIND_MALLOC(ret != NULL, ret, size, false);\n\treturn (ret);\n}\n#endif\n\n/*\n * is_malloc(je_malloc) is some macro magic to detect if jemalloc_defs.h has\n * #define je_malloc malloc\n */\n#define\tmalloc_is_malloc 1\n#define\tis_malloc_(a) malloc_is_ ## a\n#define\tis_malloc(a) is_malloc_(a)\n\n#if ((is_malloc(je_malloc) == 1) && defined(__GLIBC__) && !defined(__UCLIBC__))\n/*\n * glibc provides the RTLD_DEEPBIND flag for dlopen which can make it possible\n * to inconsistently reference libc's malloc(3)-compatible functions\n * (https://bugzilla.mozilla.org/show_bug.cgi?id=493541).\n *\n * These definitions interpose hooks in glibc.  The functions are actually\n * passed an extra argument for the caller return address, which will be\n * ignored.\n */\nJEMALLOC_EXPORT void (* __free_hook)(void *ptr) = je_free;\nJEMALLOC_EXPORT void *(* __malloc_hook)(size_t size) = je_malloc;\nJEMALLOC_EXPORT void *(* __realloc_hook)(void *ptr, size_t size) = je_realloc;\nJEMALLOC_EXPORT void *(* __memalign_hook)(size_t alignment, size_t size) =\n    je_memalign;\n#endif\n\n/*\n * End non-standard override functions.\n */\n/******************************************************************************/\n/*\n * Begin non-standard functions.\n */\n\nJEMALLOC_ALWAYS_INLINE_C void *\nimallocx(size_t usize, size_t alignment, bool zero, bool try_tcache,\n    arena_t *arena)\n{\n\n\tassert(usize == ((alignment == 0) ? s2u(usize) : sa2u(usize,\n\t    alignment)));\n\n\tif (alignment != 0)\n\t\treturn (ipalloct(usize, alignment, zero, try_tcache, arena));\n\telse if (zero)\n\t\treturn (icalloct(usize, try_tcache, arena));\n\telse\n\t\treturn (imalloct(usize, try_tcache, arena));\n}\n\nstatic void *\nimallocx_prof_sample(size_t usize, size_t alignment, bool zero, bool try_tcache,\n    arena_t *arena, prof_thr_cnt_t *cnt)\n{\n\tvoid *p;\n\n\tif (cnt == NULL)\n\t\treturn (NULL);\n\tif (prof_promote && usize <= SMALL_MAXCLASS) {\n\t\tsize_t usize_promoted = (alignment == 0) ?\n\t\t    s2u(SMALL_MAXCLASS+1) : sa2u(SMALL_MAXCLASS+1, alignment);\n\t\tassert(usize_promoted != 0);\n\t\tp = imallocx(usize_promoted, alignment, zero, try_tcache,\n\t\t    arena);\n\t\tif (p == NULL)\n\t\t\treturn (NULL);\n\t\tarena_prof_promoted(p, usize);\n\t} else\n\t\tp = imallocx(usize, alignment, zero, try_tcache, arena);\n\n\treturn (p);\n}\n\nJEMALLOC_ALWAYS_INLINE_C void *\nimallocx_prof(size_t usize, size_t alignment, bool zero, bool try_tcache,\n    arena_t *arena, prof_thr_cnt_t *cnt)\n{\n\tvoid *p;\n\n\tif ((uintptr_t)cnt != (uintptr_t)1U) {\n\t\tp = imallocx_prof_sample(usize, alignment, zero, try_tcache,\n\t\t    arena, cnt);\n\t} else\n\t\tp = imallocx(usize, alignment, zero, try_tcache, arena);\n\tif (p == NULL)\n\t\treturn (NULL);\n\tprof_malloc(p, usize, cnt);\n\n\treturn (p);\n}\n\nvoid *\nje_mallocx(size_t size, int flags)\n{\n\tvoid *p;\n\tsize_t usize;\n\tsize_t alignment = (ZU(1) << (flags & MALLOCX_LG_ALIGN_MASK)\n\t    & (SIZE_T_MAX-1));\n\tbool zero = flags & MALLOCX_ZERO;\n\tunsigned arena_ind = ((unsigned)(flags >> 8)) - 1;\n\tarena_t *arena;\n\tbool try_tcache;\n\n\tassert(size != 0);\n\n\tif (malloc_init())\n\t\tgoto label_oom;\n\n\tif (arena_ind != UINT_MAX) {\n\t\tarena = arenas[arena_ind];\n\t\ttry_tcache = false;\n\t} else {\n\t\tarena = NULL;\n\t\ttry_tcache = true;\n\t}\n\n\tusize = (alignment == 0) ? s2u(size) : sa2u(size, alignment);\n\tassert(usize != 0);\n\n\tif (config_prof && opt_prof) {\n\t\tprof_thr_cnt_t *cnt;\n\n\t\tPROF_ALLOC_PREP(1, usize, cnt);\n\t\tp = imallocx_prof(usize, alignment, zero, try_tcache, arena,\n\t\t    cnt);\n\t} else\n\t\tp = imallocx(usize, alignment, zero, try_tcache, arena);\n\tif (p == NULL)\n\t\tgoto label_oom;\n\n\tif (config_stats) {\n\t\tassert(usize == isalloc(p, config_prof));\n\t\tthread_allocated_tsd_get()->allocated += usize;\n\t}\n\tUTRACE(0, size, p);\n\tJEMALLOC_VALGRIND_MALLOC(true, p, usize, zero);\n\treturn (p);\nlabel_oom:\n\tif (config_xmalloc && opt_xmalloc) {\n\t\tmalloc_write(\"<jemalloc>: Error in mallocx(): out of memory\\n\");\n\t\tabort();\n\t}\n\tUTRACE(0, size, 0);\n\treturn (NULL);\n}\n\nstatic void *\nirallocx_prof_sample(void *oldptr, size_t size, size_t alignment, size_t usize,\n    bool zero, bool try_tcache_alloc, bool try_tcache_dalloc, arena_t *arena,\n    prof_thr_cnt_t *cnt)\n{\n\tvoid *p;\n\n\tif (cnt == NULL)\n\t\treturn (NULL);\n\tif (prof_promote && usize <= SMALL_MAXCLASS) {\n\t\tp = iralloct(oldptr, SMALL_MAXCLASS+1, (SMALL_MAXCLASS+1 >=\n\t\t    size) ? 0 : size - (SMALL_MAXCLASS+1), alignment, zero,\n\t\t    try_tcache_alloc, try_tcache_dalloc, arena);\n\t\tif (p == NULL)\n\t\t\treturn (NULL);\n\t\tarena_prof_promoted(p, usize);\n\t} else {\n\t\tp = iralloct(oldptr, size, 0, alignment, zero,\n\t\t    try_tcache_alloc, try_tcache_dalloc, arena);\n\t}\n\n\treturn (p);\n}\n\nJEMALLOC_ALWAYS_INLINE_C void *\nirallocx_prof(void *oldptr, size_t old_usize, size_t size, size_t alignment,\n    size_t *usize, bool zero, bool try_tcache_alloc, bool try_tcache_dalloc,\n    arena_t *arena, prof_thr_cnt_t *cnt)\n{\n\tvoid *p;\n\tprof_ctx_t *old_ctx;\n\n\told_ctx = prof_ctx_get(oldptr);\n\tif ((uintptr_t)cnt != (uintptr_t)1U)\n\t\tp = irallocx_prof_sample(oldptr, size, alignment, *usize, zero,\n\t\t    try_tcache_alloc, try_tcache_dalloc, arena, cnt);\n\telse {\n\t\tp = iralloct(oldptr, size, 0, alignment, zero,\n\t\t    try_tcache_alloc, try_tcache_dalloc, arena);\n\t}\n\tif (p == NULL)\n\t\treturn (NULL);\n\n\tif (p == oldptr && alignment != 0) {\n\t\t/*\n\t\t * The allocation did not move, so it is possible that the size\n\t\t * class is smaller than would guarantee the requested\n\t\t * alignment, and that the alignment constraint was\n\t\t * serendipitously satisfied.  Additionally, old_usize may not\n\t\t * be the same as the current usize because of in-place large\n\t\t * reallocation.  Therefore, query the actual value of usize.\n\t\t */\n\t\t*usize = isalloc(p, config_prof);\n\t}\n\tprof_realloc(p, *usize, cnt, old_usize, old_ctx);\n\n\treturn (p);\n}\n\nvoid *\nje_rallocx(void *ptr, size_t size, int flags)\n{\n\tvoid *p;\n\tsize_t usize, old_usize;\n\tUNUSED size_t old_rzsize JEMALLOC_CC_SILENCE_INIT(0);\n\tsize_t alignment = (ZU(1) << (flags & MALLOCX_LG_ALIGN_MASK)\n\t    & (SIZE_T_MAX-1));\n\tbool zero = flags & MALLOCX_ZERO;\n\tunsigned arena_ind = ((unsigned)(flags >> 8)) - 1;\n\tbool try_tcache_alloc, try_tcache_dalloc;\n\tarena_t *arena;\n\n\tassert(ptr != NULL);\n\tassert(size != 0);\n\tassert(malloc_initialized || IS_INITIALIZER);\n\tmalloc_thread_init();\n\n\tif (arena_ind != UINT_MAX) {\n\t\tarena_chunk_t *chunk;\n\t\ttry_tcache_alloc = false;\n\t\tchunk = (arena_chunk_t *)CHUNK_ADDR2BASE(ptr);\n\t\ttry_tcache_dalloc = (chunk == ptr || chunk->arena !=\n\t\t    arenas[arena_ind]);\n\t\tarena = arenas[arena_ind];\n\t} else {\n\t\ttry_tcache_alloc = true;\n\t\ttry_tcache_dalloc = true;\n\t\tarena = NULL;\n\t}\n\n\tif ((config_prof && opt_prof) || config_stats ||\n\t    (config_valgrind && opt_valgrind))\n\t\told_usize = isalloc(ptr, config_prof);\n\tif (config_valgrind && opt_valgrind)\n\t\told_rzsize = u2rz(old_usize);\n\n\tif (config_prof && opt_prof) {\n\t\tprof_thr_cnt_t *cnt;\n\n\t\tusize = (alignment == 0) ? s2u(size) : sa2u(size, alignment);\n\t\tassert(usize != 0);\n\t\tPROF_ALLOC_PREP(1, usize, cnt);\n\t\tp = irallocx_prof(ptr, old_usize, size, alignment, &usize, zero,\n\t\t    try_tcache_alloc, try_tcache_dalloc, arena, cnt);\n\t\tif (p == NULL)\n\t\t\tgoto label_oom;\n\t} else {\n\t\tp = iralloct(ptr, size, 0, alignment, zero, try_tcache_alloc,\n\t\t    try_tcache_dalloc, arena);\n\t\tif (p == NULL)\n\t\t\tgoto label_oom;\n\t\tif (config_stats || (config_valgrind && opt_valgrind))\n\t\t\tusize = isalloc(p, config_prof);\n\t}\n\n\tif (config_stats) {\n\t\tthread_allocated_t *ta;\n\t\tta = thread_allocated_tsd_get();\n\t\tta->allocated += usize;\n\t\tta->deallocated += old_usize;\n\t}\n\tUTRACE(ptr, size, p);\n\tJEMALLOC_VALGRIND_REALLOC(p, usize, ptr, old_usize, old_rzsize, zero);\n\treturn (p);\nlabel_oom:\n\tif (config_xmalloc && opt_xmalloc) {\n\t\tmalloc_write(\"<jemalloc>: Error in rallocx(): out of memory\\n\");\n\t\tabort();\n\t}\n\tUTRACE(ptr, size, 0);\n\treturn (NULL);\n}\n\nJEMALLOC_ALWAYS_INLINE_C size_t\nixallocx_helper(void *ptr, size_t old_usize, size_t size, size_t extra,\n    size_t alignment, bool zero, arena_t *arena)\n{\n\tsize_t usize;\n\n\tif (ixalloc(ptr, size, extra, alignment, zero))\n\t\treturn (old_usize);\n\tusize = isalloc(ptr, config_prof);\n\n\treturn (usize);\n}\n\nstatic size_t\nixallocx_prof_sample(void *ptr, size_t old_usize, size_t size, size_t extra,\n    size_t alignment, size_t max_usize, bool zero, arena_t *arena,\n    prof_thr_cnt_t *cnt)\n{\n\tsize_t usize;\n\n\tif (cnt == NULL)\n\t\treturn (old_usize);\n\t/* Use minimum usize to determine whether promotion may happen. */\n\tif (prof_promote && ((alignment == 0) ? s2u(size) : sa2u(size,\n\t    alignment)) <= SMALL_MAXCLASS) {\n\t\tif (ixalloc(ptr, SMALL_MAXCLASS+1, (SMALL_MAXCLASS+1 >=\n\t\t    size+extra) ? 0 : size+extra - (SMALL_MAXCLASS+1),\n\t\t    alignment, zero))\n\t\t\treturn (old_usize);\n\t\tusize = isalloc(ptr, config_prof);\n\t\tif (max_usize < PAGE)\n\t\t\tarena_prof_promoted(ptr, usize);\n\t} else {\n\t\tusize = ixallocx_helper(ptr, old_usize, size, extra, alignment,\n\t\t    zero, arena);\n\t}\n\n\treturn (usize);\n}\n\nJEMALLOC_ALWAYS_INLINE_C size_t\nixallocx_prof(void *ptr, size_t old_usize, size_t size, size_t extra,\n    size_t alignment, size_t max_usize, bool zero, arena_t *arena,\n    prof_thr_cnt_t *cnt)\n{\n\tsize_t usize;\n\tprof_ctx_t *old_ctx;\n\n\told_ctx = prof_ctx_get(ptr);\n\tif ((uintptr_t)cnt != (uintptr_t)1U) {\n\t\tusize = ixallocx_prof_sample(ptr, old_usize, size, extra,\n\t\t    alignment, zero, max_usize, arena, cnt);\n\t} else {\n\t\tusize = ixallocx_helper(ptr, old_usize, size, extra, alignment,\n\t\t    zero, arena);\n\t}\n\tif (usize == old_usize)\n\t\treturn (usize);\n\tprof_realloc(ptr, usize, cnt, old_usize, old_ctx);\n\n\treturn (usize);\n}\n\nsize_t\nje_xallocx(void *ptr, size_t size, size_t extra, int flags)\n{\n\tsize_t usize, old_usize;\n\tUNUSED size_t old_rzsize JEMALLOC_CC_SILENCE_INIT(0);\n\tsize_t alignment = (ZU(1) << (flags & MALLOCX_LG_ALIGN_MASK)\n\t    & (SIZE_T_MAX-1));\n\tbool zero = flags & MALLOCX_ZERO;\n\tunsigned arena_ind = ((unsigned)(flags >> 8)) - 1;\n\tarena_t *arena;\n\n\tassert(ptr != NULL);\n\tassert(size != 0);\n\tassert(SIZE_T_MAX - size >= extra);\n\tassert(malloc_initialized || IS_INITIALIZER);\n\tmalloc_thread_init();\n\n\tif (arena_ind != UINT_MAX)\n\t\tarena = arenas[arena_ind];\n\telse\n\t\tarena = NULL;\n\n\told_usize = isalloc(ptr, config_prof);\n\tif (config_valgrind && opt_valgrind)\n\t\told_rzsize = u2rz(old_usize);\n\n\tif (config_prof && opt_prof) {\n\t\tprof_thr_cnt_t *cnt;\n\t\t/*\n\t\t * usize isn't knowable before ixalloc() returns when extra is\n\t\t * non-zero.  Therefore, compute its maximum possible value and\n\t\t * use that in PROF_ALLOC_PREP() to decide whether to capture a\n\t\t * backtrace.  prof_realloc() will use the actual usize to\n\t\t * decide whether to sample.\n\t\t */\n\t\tsize_t max_usize = (alignment == 0) ? s2u(size+extra) :\n\t\t    sa2u(size+extra, alignment);\n\t\tPROF_ALLOC_PREP(1, max_usize, cnt);\n\t\tusize = ixallocx_prof(ptr, old_usize, size, extra, alignment,\n\t\t    max_usize, zero, arena, cnt);\n\t} else {\n\t\tusize = ixallocx_helper(ptr, old_usize, size, extra, alignment,\n\t\t    zero, arena);\n\t}\n\tif (usize == old_usize)\n\t\tgoto label_not_resized;\n\n\tif (config_stats) {\n\t\tthread_allocated_t *ta;\n\t\tta = thread_allocated_tsd_get();\n\t\tta->allocated += usize;\n\t\tta->deallocated += old_usize;\n\t}\n\tJEMALLOC_VALGRIND_REALLOC(ptr, usize, ptr, old_usize, old_rzsize, zero);\nlabel_not_resized:\n\tUTRACE(ptr, size, ptr);\n\treturn (usize);\n}\n\nsize_t\nje_sallocx(const void *ptr, int flags)\n{\n\tsize_t usize;\n\n\tassert(malloc_initialized || IS_INITIALIZER);\n\tmalloc_thread_init();\n\n\tif (config_ivsalloc)\n\t\tusize = ivsalloc(ptr, config_prof);\n\telse {\n\t\tassert(ptr != NULL);\n\t\tusize = isalloc(ptr, config_prof);\n\t}\n\n\treturn (usize);\n}\n\nvoid\nje_dallocx(void *ptr, int flags)\n{\n\tsize_t usize;\n\tUNUSED size_t rzsize JEMALLOC_CC_SILENCE_INIT(0);\n\tunsigned arena_ind = ((unsigned)(flags >> 8)) - 1;\n\tbool try_tcache;\n\n\tassert(ptr != NULL);\n\tassert(malloc_initialized || IS_INITIALIZER);\n\n\tif (arena_ind != UINT_MAX) {\n\t\tarena_chunk_t *chunk = (arena_chunk_t *)CHUNK_ADDR2BASE(ptr);\n\t\ttry_tcache = (chunk == ptr || chunk->arena !=\n\t\t    arenas[arena_ind]);\n\t} else\n\t\ttry_tcache = true;\n\n\tUTRACE(ptr, 0, 0);\n\tif (config_stats || config_valgrind)\n\t\tusize = isalloc(ptr, config_prof);\n\tif (config_prof && opt_prof) {\n\t\tif (config_stats == false && config_valgrind == false)\n\t\t\tusize = isalloc(ptr, config_prof);\n\t\tprof_free(ptr, usize);\n\t}\n\tif (config_stats)\n\t\tthread_allocated_tsd_get()->deallocated += usize;\n\tif (config_valgrind && opt_valgrind)\n\t\trzsize = p2rz(ptr);\n\tiqalloct(ptr, try_tcache);\n\tJEMALLOC_VALGRIND_FREE(ptr, rzsize);\n}\n\nsize_t\nje_nallocx(size_t size, int flags)\n{\n\tsize_t usize;\n\tsize_t alignment = (ZU(1) << (flags & MALLOCX_LG_ALIGN_MASK)\n\t    & (SIZE_T_MAX-1));\n\n\tassert(size != 0);\n\n\tif (malloc_init())\n\t\treturn (0);\n\n\tusize = (alignment == 0) ? s2u(size) : sa2u(size, alignment);\n\tassert(usize != 0);\n\treturn (usize);\n}\n\nint\nje_mallctl(const char *name, void *oldp, size_t *oldlenp, void *newp,\n    size_t newlen)\n{\n\n\tif (malloc_init())\n\t\treturn (EAGAIN);\n\n\treturn (ctl_byname(name, oldp, oldlenp, newp, newlen));\n}\n\nint\nje_mallctlnametomib(const char *name, size_t *mibp, size_t *miblenp)\n{\n\n\tif (malloc_init())\n\t\treturn (EAGAIN);\n\n\treturn (ctl_nametomib(name, mibp, miblenp));\n}\n\nint\nje_mallctlbymib(const size_t *mib, size_t miblen, void *oldp, size_t *oldlenp,\n  void *newp, size_t newlen)\n{\n\n\tif (malloc_init())\n\t\treturn (EAGAIN);\n\n\treturn (ctl_bymib(mib, miblen, oldp, oldlenp, newp, newlen));\n}\n\nvoid\nje_malloc_stats_print(void (*write_cb)(void *, const char *), void *cbopaque,\n    const char *opts)\n{\n\n\tstats_print(write_cb, cbopaque, opts);\n}\n\nsize_t\nje_malloc_usable_size(JEMALLOC_USABLE_SIZE_CONST void *ptr)\n{\n\tsize_t ret;\n\n\tassert(malloc_initialized || IS_INITIALIZER);\n\tmalloc_thread_init();\n\n\tif (config_ivsalloc)\n\t\tret = ivsalloc(ptr, config_prof);\n\telse\n\t\tret = (ptr != NULL) ? isalloc(ptr, config_prof) : 0;\n\n\treturn (ret);\n}\n\n/*\n * End non-standard functions.\n */\n/******************************************************************************/\n/*\n * Begin experimental functions.\n */\n#ifdef JEMALLOC_EXPERIMENTAL\n\nint\nje_allocm(void **ptr, size_t *rsize, size_t size, int flags)\n{\n\tvoid *p;\n\n\tassert(ptr != NULL);\n\n\tp = je_mallocx(size, flags);\n\tif (p == NULL)\n\t\treturn (ALLOCM_ERR_OOM);\n\tif (rsize != NULL)\n\t\t*rsize = isalloc(p, config_prof);\n\t*ptr = p;\n\treturn (ALLOCM_SUCCESS);\n}\n\nint\nje_rallocm(void **ptr, size_t *rsize, size_t size, size_t extra, int flags)\n{\n\tint ret;\n\tbool no_move = flags & ALLOCM_NO_MOVE;\n\n\tassert(ptr != NULL);\n\tassert(*ptr != NULL);\n\tassert(size != 0);\n\tassert(SIZE_T_MAX - size >= extra);\n\n\tif (no_move) {\n\t\tsize_t usize = je_xallocx(*ptr, size, extra, flags);\n\t\tret = (usize >= size) ? ALLOCM_SUCCESS : ALLOCM_ERR_NOT_MOVED;\n\t\tif (rsize != NULL)\n\t\t\t*rsize = usize;\n\t} else {\n\t\tvoid *p = je_rallocx(*ptr, size+extra, flags);\n\t\tif (p != NULL) {\n\t\t\t*ptr = p;\n\t\t\tret = ALLOCM_SUCCESS;\n\t\t} else\n\t\t\tret = ALLOCM_ERR_OOM;\n\t\tif (rsize != NULL)\n\t\t\t*rsize = isalloc(*ptr, config_prof);\n\t}\n\treturn (ret);\n}\n\nint\nje_sallocm(const void *ptr, size_t *rsize, int flags)\n{\n\n\tassert(rsize != NULL);\n\t*rsize = je_sallocx(ptr, flags);\n\treturn (ALLOCM_SUCCESS);\n}\n\nint\nje_dallocm(void *ptr, int flags)\n{\n\n\tje_dallocx(ptr, flags);\n\treturn (ALLOCM_SUCCESS);\n}\n\nint\nje_nallocm(size_t *rsize, size_t size, int flags)\n{\n\tsize_t usize;\n\n\tusize = je_nallocx(size, flags);\n\tif (usize == 0)\n\t\treturn (ALLOCM_ERR_OOM);\n\tif (rsize != NULL)\n\t\t*rsize = usize;\n\treturn (ALLOCM_SUCCESS);\n}\n\n#endif\n/*\n * End experimental functions.\n */\n/******************************************************************************/\n/*\n * The following functions are used by threading libraries for protection of\n * malloc during fork().\n */\n\n/*\n * If an application creates a thread before doing any allocation in the main\n * thread, then calls fork(2) in the main thread followed by memory allocation\n * in the child process, a race can occur that results in deadlock within the\n * child: the main thread may have forked while the created thread had\n * partially initialized the allocator.  Ordinarily jemalloc prevents\n * fork/malloc races via the following functions it registers during\n * initialization using pthread_atfork(), but of course that does no good if\n * the allocator isn't fully initialized at fork time.  The following library\n * constructor is a partial solution to this problem.  It may still possible to\n * trigger the deadlock described above, but doing so would involve forking via\n * a library constructor that runs before jemalloc's runs.\n */\nJEMALLOC_ATTR(constructor)\nstatic void\njemalloc_constructor(void)\n{\n\n\tmalloc_init();\n}\n\n#ifndef JEMALLOC_MUTEX_INIT_CB\nvoid\njemalloc_prefork(void)\n#else\nJEMALLOC_EXPORT void\n_malloc_prefork(void)\n#endif\n{\n\tunsigned i;\n\n#ifdef JEMALLOC_MUTEX_INIT_CB\n\tif (malloc_initialized == false)\n\t\treturn;\n#endif\n\tassert(malloc_initialized);\n\n\t/* Acquire all mutexes in a safe order. */\n\tctl_prefork();\n\tprof_prefork();\n\tmalloc_mutex_prefork(&arenas_lock);\n\tfor (i = 0; i < narenas_total; i++) {\n\t\tif (arenas[i] != NULL)\n\t\t\tarena_prefork(arenas[i]);\n\t}\n\tchunk_prefork();\n\tbase_prefork();\n\thuge_prefork();\n}\n\n#ifndef JEMALLOC_MUTEX_INIT_CB\nvoid\njemalloc_postfork_parent(void)\n#else\nJEMALLOC_EXPORT void\n_malloc_postfork(void)\n#endif\n{\n\tunsigned i;\n\n#ifdef JEMALLOC_MUTEX_INIT_CB\n\tif (malloc_initialized == false)\n\t\treturn;\n#endif\n\tassert(malloc_initialized);\n\n\t/* Release all mutexes, now that fork() has completed. */\n\thuge_postfork_parent();\n\tbase_postfork_parent();\n\tchunk_postfork_parent();\n\tfor (i = 0; i < narenas_total; i++) {\n\t\tif (arenas[i] != NULL)\n\t\t\tarena_postfork_parent(arenas[i]);\n\t}\n\tmalloc_mutex_postfork_parent(&arenas_lock);\n\tprof_postfork_parent();\n\tctl_postfork_parent();\n}\n\nvoid\njemalloc_postfork_child(void)\n{\n\tunsigned i;\n\n\tassert(malloc_initialized);\n\n\t/* Release all mutexes, now that fork() has completed. */\n\thuge_postfork_child();\n\tbase_postfork_child();\n\tchunk_postfork_child();\n\tfor (i = 0; i < narenas_total; i++) {\n\t\tif (arenas[i] != NULL)\n\t\t\tarena_postfork_child(arenas[i]);\n\t}\n\tmalloc_mutex_postfork_child(&arenas_lock);\n\tprof_postfork_child();\n\tctl_postfork_child();\n}\n\n/******************************************************************************/\n/*\n * The following functions are used for TLS allocation/deallocation in static\n * binaries on FreeBSD.  The primary difference between these and i[mcd]alloc()\n * is that these avoid accessing TLS variables.\n */\n\nstatic void *\na0alloc(size_t size, bool zero)\n{\n\n\tif (malloc_init())\n\t\treturn (NULL);\n\n\tif (size == 0)\n\t\tsize = 1;\n\n\tif (size <= arena_maxclass)\n\t\treturn (arena_malloc(arenas[0], size, zero, false));\n\telse\n\t\treturn (huge_malloc(size, zero, huge_dss_prec_get(arenas[0])));\n}\n\nvoid *\na0malloc(size_t size)\n{\n\n\treturn (a0alloc(size, false));\n}\n\nvoid *\na0calloc(size_t num, size_t size)\n{\n\n\treturn (a0alloc(num * size, true));\n}\n\nvoid\na0free(void *ptr)\n{\n\tarena_chunk_t *chunk;\n\n\tif (ptr == NULL)\n\t\treturn;\n\n\tchunk = (arena_chunk_t *)CHUNK_ADDR2BASE(ptr);\n\tif (chunk != ptr)\n\t\tarena_dalloc(chunk->arena, chunk, ptr, false);\n\telse\n\t\thuge_dalloc(ptr, true);\n}\n\n/******************************************************************************/\n"
  },
  {
    "path": "extern/deprecated/redis-2.8.21/deps/jemalloc/src/mb.c",
    "content": "#define\tJEMALLOC_MB_C_\n#include \"jemalloc/internal/jemalloc_internal.h\"\n"
  },
  {
    "path": "extern/deprecated/redis-2.8.21/deps/jemalloc/src/mutex.c",
    "content": "#define\tJEMALLOC_MUTEX_C_\n#include \"jemalloc/internal/jemalloc_internal.h\"\n\n#if defined(JEMALLOC_LAZY_LOCK) && !defined(_WIN32)\n#include <dlfcn.h>\n#endif\n\n#ifndef _CRT_SPINCOUNT\n#define\t_CRT_SPINCOUNT 4000\n#endif\n\n/******************************************************************************/\n/* Data. */\n\n#ifdef JEMALLOC_LAZY_LOCK\nbool isthreaded = false;\n#endif\n#ifdef JEMALLOC_MUTEX_INIT_CB\nstatic bool\t\tpostpone_init = true;\nstatic malloc_mutex_t\t*postponed_mutexes = NULL;\n#endif\n\n#if defined(JEMALLOC_LAZY_LOCK) && !defined(_WIN32)\nstatic void\tpthread_create_once(void);\n#endif\n\n/******************************************************************************/\n/*\n * We intercept pthread_create() calls in order to toggle isthreaded if the\n * process goes multi-threaded.\n */\n\n#if defined(JEMALLOC_LAZY_LOCK) && !defined(_WIN32)\nstatic int (*pthread_create_fptr)(pthread_t *__restrict, const pthread_attr_t *,\n    void *(*)(void *), void *__restrict);\n\nstatic void\npthread_create_once(void)\n{\n\n\tpthread_create_fptr = dlsym(RTLD_NEXT, \"pthread_create\");\n\tif (pthread_create_fptr == NULL) {\n\t\tmalloc_write(\"<jemalloc>: Error in dlsym(RTLD_NEXT, \"\n\t\t    \"\\\"pthread_create\\\")\\n\");\n\t\tabort();\n\t}\n\n\tisthreaded = true;\n}\n\nJEMALLOC_EXPORT int\npthread_create(pthread_t *__restrict thread,\n    const pthread_attr_t *__restrict attr, void *(*start_routine)(void *),\n    void *__restrict arg)\n{\n\tstatic pthread_once_t once_control = PTHREAD_ONCE_INIT;\n\n\tpthread_once(&once_control, pthread_create_once);\n\n\treturn (pthread_create_fptr(thread, attr, start_routine, arg));\n}\n#endif\n\n/******************************************************************************/\n\n#ifdef JEMALLOC_MUTEX_INIT_CB\nJEMALLOC_EXPORT int\t_pthread_mutex_init_calloc_cb(pthread_mutex_t *mutex,\n    void *(calloc_cb)(size_t, size_t));\n#endif\n\nbool\nmalloc_mutex_init(malloc_mutex_t *mutex)\n{\n\n#ifdef _WIN32\n\tif (!InitializeCriticalSectionAndSpinCount(&mutex->lock,\n\t    _CRT_SPINCOUNT))\n\t\treturn (true);\n#elif (defined(JEMALLOC_OSSPIN))\n\tmutex->lock = 0;\n#elif (defined(JEMALLOC_MUTEX_INIT_CB))\n\tif (postpone_init) {\n\t\tmutex->postponed_next = postponed_mutexes;\n\t\tpostponed_mutexes = mutex;\n\t} else {\n\t\tif (_pthread_mutex_init_calloc_cb(&mutex->lock, base_calloc) !=\n\t\t    0)\n\t\t\treturn (true);\n\t}\n#else\n\tpthread_mutexattr_t attr;\n\n\tif (pthread_mutexattr_init(&attr) != 0)\n\t\treturn (true);\n\tpthread_mutexattr_settype(&attr, MALLOC_MUTEX_TYPE);\n\tif (pthread_mutex_init(&mutex->lock, &attr) != 0) {\n\t\tpthread_mutexattr_destroy(&attr);\n\t\treturn (true);\n\t}\n\tpthread_mutexattr_destroy(&attr);\n#endif\n\treturn (false);\n}\n\nvoid\nmalloc_mutex_prefork(malloc_mutex_t *mutex)\n{\n\n\tmalloc_mutex_lock(mutex);\n}\n\nvoid\nmalloc_mutex_postfork_parent(malloc_mutex_t *mutex)\n{\n\n\tmalloc_mutex_unlock(mutex);\n}\n\nvoid\nmalloc_mutex_postfork_child(malloc_mutex_t *mutex)\n{\n\n#ifdef JEMALLOC_MUTEX_INIT_CB\n\tmalloc_mutex_unlock(mutex);\n#else\n\tif (malloc_mutex_init(mutex)) {\n\t\tmalloc_printf(\"<jemalloc>: Error re-initializing mutex in \"\n\t\t    \"child\\n\");\n\t\tif (opt_abort)\n\t\t\tabort();\n\t}\n#endif\n}\n\nbool\nmutex_boot(void)\n{\n\n#ifdef JEMALLOC_MUTEX_INIT_CB\n\tpostpone_init = false;\n\twhile (postponed_mutexes != NULL) {\n\t\tif (_pthread_mutex_init_calloc_cb(&postponed_mutexes->lock,\n\t\t    base_calloc) != 0)\n\t\t\treturn (true);\n\t\tpostponed_mutexes = postponed_mutexes->postponed_next;\n\t}\n#endif\n\treturn (false);\n}\n"
  },
  {
    "path": "extern/deprecated/redis-2.8.21/deps/jemalloc/src/prof.c",
    "content": "#define\tJEMALLOC_PROF_C_\n#include \"jemalloc/internal/jemalloc_internal.h\"\n/******************************************************************************/\n\n#ifdef JEMALLOC_PROF_LIBUNWIND\n#define\tUNW_LOCAL_ONLY\n#include <libunwind.h>\n#endif\n\n#ifdef JEMALLOC_PROF_LIBGCC\n#include <unwind.h>\n#endif\n\n/******************************************************************************/\n/* Data. */\n\nmalloc_tsd_data(, prof_tdata, prof_tdata_t *, NULL)\n\nbool\t\topt_prof = false;\nbool\t\topt_prof_active = true;\nsize_t\t\topt_lg_prof_sample = LG_PROF_SAMPLE_DEFAULT;\nssize_t\t\topt_lg_prof_interval = LG_PROF_INTERVAL_DEFAULT;\nbool\t\topt_prof_gdump = false;\nbool\t\topt_prof_final = true;\nbool\t\topt_prof_leak = false;\nbool\t\topt_prof_accum = false;\nchar\t\topt_prof_prefix[\n    /* Minimize memory bloat for non-prof builds. */\n#ifdef JEMALLOC_PROF\n    PATH_MAX +\n#endif\n    1];\n\nuint64_t\tprof_interval = 0;\nbool\t\tprof_promote;\n\n/*\n * Table of mutexes that are shared among ctx's.  These are leaf locks, so\n * there is no problem with using them for more than one ctx at the same time.\n * The primary motivation for this sharing though is that ctx's are ephemeral,\n * and destroying mutexes causes complications for systems that allocate when\n * creating/destroying mutexes.\n */\nstatic malloc_mutex_t\t*ctx_locks;\nstatic unsigned\t\tcum_ctxs; /* Atomic counter. */\n\n/*\n * Global hash of (prof_bt_t *)-->(prof_ctx_t *).  This is the master data\n * structure that knows about all backtraces currently captured.\n */\nstatic ckh_t\t\tbt2ctx;\nstatic malloc_mutex_t\tbt2ctx_mtx;\n\nstatic malloc_mutex_t\tprof_dump_seq_mtx;\nstatic uint64_t\t\tprof_dump_seq;\nstatic uint64_t\t\tprof_dump_iseq;\nstatic uint64_t\t\tprof_dump_mseq;\nstatic uint64_t\t\tprof_dump_useq;\n\n/*\n * This buffer is rather large for stack allocation, so use a single buffer for\n * all profile dumps.\n */\nstatic malloc_mutex_t\tprof_dump_mtx;\nstatic char\t\tprof_dump_buf[\n    /* Minimize memory bloat for non-prof builds. */\n#ifdef JEMALLOC_PROF\n    PROF_DUMP_BUFSIZE\n#else\n    1\n#endif\n];\nstatic unsigned\t\tprof_dump_buf_end;\nstatic int\t\tprof_dump_fd;\n\n/* Do not dump any profiles until bootstrapping is complete. */\nstatic bool\t\tprof_booted = false;\n\n/******************************************************************************/\n\nvoid\nbt_init(prof_bt_t *bt, void **vec)\n{\n\n\tcassert(config_prof);\n\n\tbt->vec = vec;\n\tbt->len = 0;\n}\n\nstatic void\nbt_destroy(prof_bt_t *bt)\n{\n\n\tcassert(config_prof);\n\n\tidalloc(bt);\n}\n\nstatic prof_bt_t *\nbt_dup(prof_bt_t *bt)\n{\n\tprof_bt_t *ret;\n\n\tcassert(config_prof);\n\n\t/*\n\t * Create a single allocation that has space for vec immediately\n\t * following the prof_bt_t structure.  The backtraces that get\n\t * stored in the backtrace caches are copied from stack-allocated\n\t * temporary variables, so size is known at creation time.  Making this\n\t * a contiguous object improves cache locality.\n\t */\n\tret = (prof_bt_t *)imalloc(QUANTUM_CEILING(sizeof(prof_bt_t)) +\n\t    (bt->len * sizeof(void *)));\n\tif (ret == NULL)\n\t\treturn (NULL);\n\tret->vec = (void **)((uintptr_t)ret +\n\t    QUANTUM_CEILING(sizeof(prof_bt_t)));\n\tmemcpy(ret->vec, bt->vec, bt->len * sizeof(void *));\n\tret->len = bt->len;\n\n\treturn (ret);\n}\n\nstatic inline void\nprof_enter(prof_tdata_t *prof_tdata)\n{\n\n\tcassert(config_prof);\n\n\tassert(prof_tdata->enq == false);\n\tprof_tdata->enq = true;\n\n\tmalloc_mutex_lock(&bt2ctx_mtx);\n}\n\nstatic inline void\nprof_leave(prof_tdata_t *prof_tdata)\n{\n\tbool idump, gdump;\n\n\tcassert(config_prof);\n\n\tmalloc_mutex_unlock(&bt2ctx_mtx);\n\n\tassert(prof_tdata->enq);\n\tprof_tdata->enq = false;\n\tidump = prof_tdata->enq_idump;\n\tprof_tdata->enq_idump = false;\n\tgdump = prof_tdata->enq_gdump;\n\tprof_tdata->enq_gdump = false;\n\n\tif (idump)\n\t\tprof_idump();\n\tif (gdump)\n\t\tprof_gdump();\n}\n\n#ifdef JEMALLOC_PROF_LIBUNWIND\nvoid\nprof_backtrace(prof_bt_t *bt, unsigned nignore)\n{\n\tunw_context_t uc;\n\tunw_cursor_t cursor;\n\tunsigned i;\n\tint err;\n\n\tcassert(config_prof);\n\tassert(bt->len == 0);\n\tassert(bt->vec != NULL);\n\n\tunw_getcontext(&uc);\n\tunw_init_local(&cursor, &uc);\n\n\t/* Throw away (nignore+1) stack frames, if that many exist. */\n\tfor (i = 0; i < nignore + 1; i++) {\n\t\terr = unw_step(&cursor);\n\t\tif (err <= 0)\n\t\t\treturn;\n\t}\n\n\t/*\n\t * Iterate over stack frames until there are no more, or until no space\n\t * remains in bt.\n\t */\n\tfor (i = 0; i < PROF_BT_MAX; i++) {\n\t\tunw_get_reg(&cursor, UNW_REG_IP, (unw_word_t *)&bt->vec[i]);\n\t\tbt->len++;\n\t\terr = unw_step(&cursor);\n\t\tif (err <= 0)\n\t\t\tbreak;\n\t}\n}\n#elif (defined(JEMALLOC_PROF_LIBGCC))\nstatic _Unwind_Reason_Code\nprof_unwind_init_callback(struct _Unwind_Context *context, void *arg)\n{\n\n\tcassert(config_prof);\n\n\treturn (_URC_NO_REASON);\n}\n\nstatic _Unwind_Reason_Code\nprof_unwind_callback(struct _Unwind_Context *context, void *arg)\n{\n\tprof_unwind_data_t *data = (prof_unwind_data_t *)arg;\n\n\tcassert(config_prof);\n\n\tif (data->nignore > 0)\n\t\tdata->nignore--;\n\telse {\n\t\tdata->bt->vec[data->bt->len] = (void *)_Unwind_GetIP(context);\n\t\tdata->bt->len++;\n\t\tif (data->bt->len == data->max)\n\t\t\treturn (_URC_END_OF_STACK);\n\t}\n\n\treturn (_URC_NO_REASON);\n}\n\nvoid\nprof_backtrace(prof_bt_t *bt, unsigned nignore)\n{\n\tprof_unwind_data_t data = {bt, nignore, PROF_BT_MAX};\n\n\tcassert(config_prof);\n\n\t_Unwind_Backtrace(prof_unwind_callback, &data);\n}\n#elif (defined(JEMALLOC_PROF_GCC))\nvoid\nprof_backtrace(prof_bt_t *bt, unsigned nignore)\n{\n#define\tBT_FRAME(i)\t\t\t\t\t\t\t\\\n\tif ((i) < nignore + PROF_BT_MAX) {\t\t\t\t\\\n\t\tvoid *p;\t\t\t\t\t\t\\\n\t\tif (__builtin_frame_address(i) == 0)\t\t\t\\\n\t\t\treturn;\t\t\t\t\t\t\\\n\t\tp = __builtin_return_address(i);\t\t\t\\\n\t\tif (p == NULL)\t\t\t\t\t\t\\\n\t\t\treturn;\t\t\t\t\t\t\\\n\t\tif (i >= nignore) {\t\t\t\t\t\\\n\t\t\tbt->vec[(i) - nignore] = p;\t\t\t\\\n\t\t\tbt->len = (i) - nignore + 1;\t\t\t\\\n\t\t}\t\t\t\t\t\t\t\\\n\t} else\t\t\t\t\t\t\t\t\\\n\t\treturn;\n\n\tcassert(config_prof);\n\tassert(nignore <= 3);\n\n\tBT_FRAME(0)\n\tBT_FRAME(1)\n\tBT_FRAME(2)\n\tBT_FRAME(3)\n\tBT_FRAME(4)\n\tBT_FRAME(5)\n\tBT_FRAME(6)\n\tBT_FRAME(7)\n\tBT_FRAME(8)\n\tBT_FRAME(9)\n\n\tBT_FRAME(10)\n\tBT_FRAME(11)\n\tBT_FRAME(12)\n\tBT_FRAME(13)\n\tBT_FRAME(14)\n\tBT_FRAME(15)\n\tBT_FRAME(16)\n\tBT_FRAME(17)\n\tBT_FRAME(18)\n\tBT_FRAME(19)\n\n\tBT_FRAME(20)\n\tBT_FRAME(21)\n\tBT_FRAME(22)\n\tBT_FRAME(23)\n\tBT_FRAME(24)\n\tBT_FRAME(25)\n\tBT_FRAME(26)\n\tBT_FRAME(27)\n\tBT_FRAME(28)\n\tBT_FRAME(29)\n\n\tBT_FRAME(30)\n\tBT_FRAME(31)\n\tBT_FRAME(32)\n\tBT_FRAME(33)\n\tBT_FRAME(34)\n\tBT_FRAME(35)\n\tBT_FRAME(36)\n\tBT_FRAME(37)\n\tBT_FRAME(38)\n\tBT_FRAME(39)\n\n\tBT_FRAME(40)\n\tBT_FRAME(41)\n\tBT_FRAME(42)\n\tBT_FRAME(43)\n\tBT_FRAME(44)\n\tBT_FRAME(45)\n\tBT_FRAME(46)\n\tBT_FRAME(47)\n\tBT_FRAME(48)\n\tBT_FRAME(49)\n\n\tBT_FRAME(50)\n\tBT_FRAME(51)\n\tBT_FRAME(52)\n\tBT_FRAME(53)\n\tBT_FRAME(54)\n\tBT_FRAME(55)\n\tBT_FRAME(56)\n\tBT_FRAME(57)\n\tBT_FRAME(58)\n\tBT_FRAME(59)\n\n\tBT_FRAME(60)\n\tBT_FRAME(61)\n\tBT_FRAME(62)\n\tBT_FRAME(63)\n\tBT_FRAME(64)\n\tBT_FRAME(65)\n\tBT_FRAME(66)\n\tBT_FRAME(67)\n\tBT_FRAME(68)\n\tBT_FRAME(69)\n\n\tBT_FRAME(70)\n\tBT_FRAME(71)\n\tBT_FRAME(72)\n\tBT_FRAME(73)\n\tBT_FRAME(74)\n\tBT_FRAME(75)\n\tBT_FRAME(76)\n\tBT_FRAME(77)\n\tBT_FRAME(78)\n\tBT_FRAME(79)\n\n\tBT_FRAME(80)\n\tBT_FRAME(81)\n\tBT_FRAME(82)\n\tBT_FRAME(83)\n\tBT_FRAME(84)\n\tBT_FRAME(85)\n\tBT_FRAME(86)\n\tBT_FRAME(87)\n\tBT_FRAME(88)\n\tBT_FRAME(89)\n\n\tBT_FRAME(90)\n\tBT_FRAME(91)\n\tBT_FRAME(92)\n\tBT_FRAME(93)\n\tBT_FRAME(94)\n\tBT_FRAME(95)\n\tBT_FRAME(96)\n\tBT_FRAME(97)\n\tBT_FRAME(98)\n\tBT_FRAME(99)\n\n\tBT_FRAME(100)\n\tBT_FRAME(101)\n\tBT_FRAME(102)\n\tBT_FRAME(103)\n\tBT_FRAME(104)\n\tBT_FRAME(105)\n\tBT_FRAME(106)\n\tBT_FRAME(107)\n\tBT_FRAME(108)\n\tBT_FRAME(109)\n\n\tBT_FRAME(110)\n\tBT_FRAME(111)\n\tBT_FRAME(112)\n\tBT_FRAME(113)\n\tBT_FRAME(114)\n\tBT_FRAME(115)\n\tBT_FRAME(116)\n\tBT_FRAME(117)\n\tBT_FRAME(118)\n\tBT_FRAME(119)\n\n\tBT_FRAME(120)\n\tBT_FRAME(121)\n\tBT_FRAME(122)\n\tBT_FRAME(123)\n\tBT_FRAME(124)\n\tBT_FRAME(125)\n\tBT_FRAME(126)\n\tBT_FRAME(127)\n\n\t/* Extras to compensate for nignore. */\n\tBT_FRAME(128)\n\tBT_FRAME(129)\n\tBT_FRAME(130)\n#undef BT_FRAME\n}\n#else\nvoid\nprof_backtrace(prof_bt_t *bt, unsigned nignore)\n{\n\n\tcassert(config_prof);\n\tnot_reached();\n}\n#endif\n\nstatic malloc_mutex_t *\nprof_ctx_mutex_choose(void)\n{\n\tunsigned nctxs = atomic_add_u(&cum_ctxs, 1);\n\n\treturn (&ctx_locks[(nctxs - 1) % PROF_NCTX_LOCKS]);\n}\n\nstatic void\nprof_ctx_init(prof_ctx_t *ctx, prof_bt_t *bt)\n{\n\n\tctx->bt = bt;\n\tctx->lock = prof_ctx_mutex_choose();\n\t/*\n\t * Set nlimbo to 1, in order to avoid a race condition with\n\t * prof_ctx_merge()/prof_ctx_destroy().\n\t */\n\tctx->nlimbo = 1;\n\tql_elm_new(ctx, dump_link);\n\tmemset(&ctx->cnt_merged, 0, sizeof(prof_cnt_t));\n\tql_new(&ctx->cnts_ql);\n}\n\nstatic void\nprof_ctx_destroy(prof_ctx_t *ctx)\n{\n\tprof_tdata_t *prof_tdata;\n\n\tcassert(config_prof);\n\n\t/*\n\t * Check that ctx is still unused by any thread cache before destroying\n\t * it.  prof_lookup() increments ctx->nlimbo in order to avoid a race\n\t * condition with this function, as does prof_ctx_merge() in order to\n\t * avoid a race between the main body of prof_ctx_merge() and entry\n\t * into this function.\n\t */\n\tprof_tdata = prof_tdata_get(false);\n\tassert((uintptr_t)prof_tdata > (uintptr_t)PROF_TDATA_STATE_MAX);\n\tprof_enter(prof_tdata);\n\tmalloc_mutex_lock(ctx->lock);\n\tif (ql_first(&ctx->cnts_ql) == NULL && ctx->cnt_merged.curobjs == 0 &&\n\t    ctx->nlimbo == 1) {\n\t\tassert(ctx->cnt_merged.curbytes == 0);\n\t\tassert(ctx->cnt_merged.accumobjs == 0);\n\t\tassert(ctx->cnt_merged.accumbytes == 0);\n\t\t/* Remove ctx from bt2ctx. */\n\t\tif (ckh_remove(&bt2ctx, ctx->bt, NULL, NULL))\n\t\t\tnot_reached();\n\t\tprof_leave(prof_tdata);\n\t\t/* Destroy ctx. */\n\t\tmalloc_mutex_unlock(ctx->lock);\n\t\tbt_destroy(ctx->bt);\n\t\tidalloc(ctx);\n\t} else {\n\t\t/*\n\t\t * Compensate for increment in prof_ctx_merge() or\n\t\t * prof_lookup().\n\t\t */\n\t\tctx->nlimbo--;\n\t\tmalloc_mutex_unlock(ctx->lock);\n\t\tprof_leave(prof_tdata);\n\t}\n}\n\nstatic void\nprof_ctx_merge(prof_ctx_t *ctx, prof_thr_cnt_t *cnt)\n{\n\tbool destroy;\n\n\tcassert(config_prof);\n\n\t/* Merge cnt stats and detach from ctx. */\n\tmalloc_mutex_lock(ctx->lock);\n\tctx->cnt_merged.curobjs += cnt->cnts.curobjs;\n\tctx->cnt_merged.curbytes += cnt->cnts.curbytes;\n\tctx->cnt_merged.accumobjs += cnt->cnts.accumobjs;\n\tctx->cnt_merged.accumbytes += cnt->cnts.accumbytes;\n\tql_remove(&ctx->cnts_ql, cnt, cnts_link);\n\tif (opt_prof_accum == false && ql_first(&ctx->cnts_ql) == NULL &&\n\t    ctx->cnt_merged.curobjs == 0 && ctx->nlimbo == 0) {\n\t\t/*\n\t\t * Increment ctx->nlimbo in order to keep another thread from\n\t\t * winning the race to destroy ctx while this one has ctx->lock\n\t\t * dropped.  Without this, it would be possible for another\n\t\t * thread to:\n\t\t *\n\t\t * 1) Sample an allocation associated with ctx.\n\t\t * 2) Deallocate the sampled object.\n\t\t * 3) Successfully prof_ctx_destroy(ctx).\n\t\t *\n\t\t * The result would be that ctx no longer exists by the time\n\t\t * this thread accesses it in prof_ctx_destroy().\n\t\t */\n\t\tctx->nlimbo++;\n\t\tdestroy = true;\n\t} else\n\t\tdestroy = false;\n\tmalloc_mutex_unlock(ctx->lock);\n\tif (destroy)\n\t\tprof_ctx_destroy(ctx);\n}\n\nstatic bool\nprof_lookup_global(prof_bt_t *bt, prof_tdata_t *prof_tdata, void **p_btkey,\n    prof_ctx_t **p_ctx, bool *p_new_ctx)\n{\n\tunion {\n\t\tprof_ctx_t\t*p;\n\t\tvoid\t\t*v;\n\t} ctx;\n\tunion {\n\t\tprof_bt_t\t*p;\n\t\tvoid\t\t*v;\n\t} btkey;\n\tbool new_ctx;\n\n\tprof_enter(prof_tdata);\n\tif (ckh_search(&bt2ctx, bt, &btkey.v, &ctx.v)) {\n\t\t/* bt has never been seen before.  Insert it. */\n\t\tctx.v = imalloc(sizeof(prof_ctx_t));\n\t\tif (ctx.v == NULL) {\n\t\t\tprof_leave(prof_tdata);\n\t\t\treturn (true);\n\t\t}\n\t\tbtkey.p = bt_dup(bt);\n\t\tif (btkey.v == NULL) {\n\t\t\tprof_leave(prof_tdata);\n\t\t\tidalloc(ctx.v);\n\t\t\treturn (true);\n\t\t}\n\t\tprof_ctx_init(ctx.p, btkey.p);\n\t\tif (ckh_insert(&bt2ctx, btkey.v, ctx.v)) {\n\t\t\t/* OOM. */\n\t\t\tprof_leave(prof_tdata);\n\t\t\tidalloc(btkey.v);\n\t\t\tidalloc(ctx.v);\n\t\t\treturn (true);\n\t\t}\n\t\tnew_ctx = true;\n\t} else {\n\t\t/*\n\t\t * Increment nlimbo, in order to avoid a race condition with\n\t\t * prof_ctx_merge()/prof_ctx_destroy().\n\t\t */\n\t\tmalloc_mutex_lock(ctx.p->lock);\n\t\tctx.p->nlimbo++;\n\t\tmalloc_mutex_unlock(ctx.p->lock);\n\t\tnew_ctx = false;\n\t}\n\tprof_leave(prof_tdata);\n\n\t*p_btkey = btkey.v;\n\t*p_ctx = ctx.p;\n\t*p_new_ctx = new_ctx;\n\treturn (false);\n}\n\nprof_thr_cnt_t *\nprof_lookup(prof_bt_t *bt)\n{\n\tunion {\n\t\tprof_thr_cnt_t\t*p;\n\t\tvoid\t\t*v;\n\t} ret;\n\tprof_tdata_t *prof_tdata;\n\n\tcassert(config_prof);\n\n\tprof_tdata = prof_tdata_get(false);\n\tif ((uintptr_t)prof_tdata <= (uintptr_t)PROF_TDATA_STATE_MAX)\n\t\treturn (NULL);\n\n\tif (ckh_search(&prof_tdata->bt2cnt, bt, NULL, &ret.v)) {\n\t\tvoid *btkey;\n\t\tprof_ctx_t *ctx;\n\t\tbool new_ctx;\n\n\t\t/*\n\t\t * This thread's cache lacks bt.  Look for it in the global\n\t\t * cache.\n\t\t */\n\t\tif (prof_lookup_global(bt, prof_tdata, &btkey, &ctx, &new_ctx))\n\t\t\treturn (NULL);\n\n\t\t/* Link a prof_thd_cnt_t into ctx for this thread. */\n\t\tif (ckh_count(&prof_tdata->bt2cnt) == PROF_TCMAX) {\n\t\t\tassert(ckh_count(&prof_tdata->bt2cnt) > 0);\n\t\t\t/*\n\t\t\t * Flush the least recently used cnt in order to keep\n\t\t\t * bt2cnt from becoming too large.\n\t\t\t */\n\t\t\tret.p = ql_last(&prof_tdata->lru_ql, lru_link);\n\t\t\tassert(ret.v != NULL);\n\t\t\tif (ckh_remove(&prof_tdata->bt2cnt, ret.p->ctx->bt,\n\t\t\t    NULL, NULL))\n\t\t\t\tnot_reached();\n\t\t\tql_remove(&prof_tdata->lru_ql, ret.p, lru_link);\n\t\t\tprof_ctx_merge(ret.p->ctx, ret.p);\n\t\t\t/* ret can now be re-used. */\n\t\t} else {\n\t\t\tassert(ckh_count(&prof_tdata->bt2cnt) < PROF_TCMAX);\n\t\t\t/* Allocate and partially initialize a new cnt. */\n\t\t\tret.v = imalloc(sizeof(prof_thr_cnt_t));\n\t\t\tif (ret.p == NULL) {\n\t\t\t\tif (new_ctx)\n\t\t\t\t\tprof_ctx_destroy(ctx);\n\t\t\t\treturn (NULL);\n\t\t\t}\n\t\t\tql_elm_new(ret.p, cnts_link);\n\t\t\tql_elm_new(ret.p, lru_link);\n\t\t}\n\t\t/* Finish initializing ret. */\n\t\tret.p->ctx = ctx;\n\t\tret.p->epoch = 0;\n\t\tmemset(&ret.p->cnts, 0, sizeof(prof_cnt_t));\n\t\tif (ckh_insert(&prof_tdata->bt2cnt, btkey, ret.v)) {\n\t\t\tif (new_ctx)\n\t\t\t\tprof_ctx_destroy(ctx);\n\t\t\tidalloc(ret.v);\n\t\t\treturn (NULL);\n\t\t}\n\t\tql_head_insert(&prof_tdata->lru_ql, ret.p, lru_link);\n\t\tmalloc_mutex_lock(ctx->lock);\n\t\tql_tail_insert(&ctx->cnts_ql, ret.p, cnts_link);\n\t\tctx->nlimbo--;\n\t\tmalloc_mutex_unlock(ctx->lock);\n\t} else {\n\t\t/* Move ret to the front of the LRU. */\n\t\tql_remove(&prof_tdata->lru_ql, ret.p, lru_link);\n\t\tql_head_insert(&prof_tdata->lru_ql, ret.p, lru_link);\n\t}\n\n\treturn (ret.p);\n}\n\n#ifdef JEMALLOC_JET\nsize_t\nprof_bt_count(void)\n{\n\tsize_t bt_count;\n\tprof_tdata_t *prof_tdata;\n\n\tprof_tdata = prof_tdata_get(false);\n\tif ((uintptr_t)prof_tdata <= (uintptr_t)PROF_TDATA_STATE_MAX)\n\t\treturn (0);\n\n\tprof_enter(prof_tdata);\n\tbt_count = ckh_count(&bt2ctx);\n\tprof_leave(prof_tdata);\n\n\treturn (bt_count);\n}\n#endif\n\n#ifdef JEMALLOC_JET\n#undef prof_dump_open\n#define\tprof_dump_open JEMALLOC_N(prof_dump_open_impl)\n#endif\nstatic int\nprof_dump_open(bool propagate_err, const char *filename)\n{\n\tint fd;\n\n\tfd = creat(filename, 0644);\n\tif (fd == -1 && propagate_err == false) {\n\t\tmalloc_printf(\"<jemalloc>: creat(\\\"%s\\\"), 0644) failed\\n\",\n\t\t    filename);\n\t\tif (opt_abort)\n\t\t\tabort();\n\t}\n\n\treturn (fd);\n}\n#ifdef JEMALLOC_JET\n#undef prof_dump_open\n#define\tprof_dump_open JEMALLOC_N(prof_dump_open)\nprof_dump_open_t *prof_dump_open = JEMALLOC_N(prof_dump_open_impl);\n#endif\n\nstatic bool\nprof_dump_flush(bool propagate_err)\n{\n\tbool ret = false;\n\tssize_t err;\n\n\tcassert(config_prof);\n\n\terr = write(prof_dump_fd, prof_dump_buf, prof_dump_buf_end);\n\tif (err == -1) {\n\t\tif (propagate_err == false) {\n\t\t\tmalloc_write(\"<jemalloc>: write() failed during heap \"\n\t\t\t    \"profile flush\\n\");\n\t\t\tif (opt_abort)\n\t\t\t\tabort();\n\t\t}\n\t\tret = true;\n\t}\n\tprof_dump_buf_end = 0;\n\n\treturn (ret);\n}\n\nstatic bool\nprof_dump_close(bool propagate_err)\n{\n\tbool ret;\n\n\tassert(prof_dump_fd != -1);\n\tret = prof_dump_flush(propagate_err);\n\tclose(prof_dump_fd);\n\tprof_dump_fd = -1;\n\n\treturn (ret);\n}\n\nstatic bool\nprof_dump_write(bool propagate_err, const char *s)\n{\n\tunsigned i, slen, n;\n\n\tcassert(config_prof);\n\n\ti = 0;\n\tslen = strlen(s);\n\twhile (i < slen) {\n\t\t/* Flush the buffer if it is full. */\n\t\tif (prof_dump_buf_end == PROF_DUMP_BUFSIZE)\n\t\t\tif (prof_dump_flush(propagate_err) && propagate_err)\n\t\t\t\treturn (true);\n\n\t\tif (prof_dump_buf_end + slen <= PROF_DUMP_BUFSIZE) {\n\t\t\t/* Finish writing. */\n\t\t\tn = slen - i;\n\t\t} else {\n\t\t\t/* Write as much of s as will fit. */\n\t\t\tn = PROF_DUMP_BUFSIZE - prof_dump_buf_end;\n\t\t}\n\t\tmemcpy(&prof_dump_buf[prof_dump_buf_end], &s[i], n);\n\t\tprof_dump_buf_end += n;\n\t\ti += n;\n\t}\n\n\treturn (false);\n}\n\nJEMALLOC_ATTR(format(printf, 2, 3))\nstatic bool\nprof_dump_printf(bool propagate_err, const char *format, ...)\n{\n\tbool ret;\n\tva_list ap;\n\tchar buf[PROF_PRINTF_BUFSIZE];\n\n\tva_start(ap, format);\n\tmalloc_vsnprintf(buf, sizeof(buf), format, ap);\n\tva_end(ap);\n\tret = prof_dump_write(propagate_err, buf);\n\n\treturn (ret);\n}\n\nstatic void\nprof_dump_ctx_prep(prof_ctx_t *ctx, prof_cnt_t *cnt_all, size_t *leak_nctx,\n    prof_ctx_list_t *ctx_ql)\n{\n\tprof_thr_cnt_t *thr_cnt;\n\tprof_cnt_t tcnt;\n\n\tcassert(config_prof);\n\n\tmalloc_mutex_lock(ctx->lock);\n\n\t/*\n\t * Increment nlimbo so that ctx won't go away before dump.\n\t * Additionally, link ctx into the dump list so that it is included in\n\t * prof_dump()'s second pass.\n\t */\n\tctx->nlimbo++;\n\tql_tail_insert(ctx_ql, ctx, dump_link);\n\n\tmemcpy(&ctx->cnt_summed, &ctx->cnt_merged, sizeof(prof_cnt_t));\n\tql_foreach(thr_cnt, &ctx->cnts_ql, cnts_link) {\n\t\tvolatile unsigned *epoch = &thr_cnt->epoch;\n\n\t\twhile (true) {\n\t\t\tunsigned epoch0 = *epoch;\n\n\t\t\t/* Make sure epoch is even. */\n\t\t\tif (epoch0 & 1U)\n\t\t\t\tcontinue;\n\n\t\t\tmemcpy(&tcnt, &thr_cnt->cnts, sizeof(prof_cnt_t));\n\n\t\t\t/* Terminate if epoch didn't change while reading. */\n\t\t\tif (*epoch == epoch0)\n\t\t\t\tbreak;\n\t\t}\n\n\t\tctx->cnt_summed.curobjs += tcnt.curobjs;\n\t\tctx->cnt_summed.curbytes += tcnt.curbytes;\n\t\tif (opt_prof_accum) {\n\t\t\tctx->cnt_summed.accumobjs += tcnt.accumobjs;\n\t\t\tctx->cnt_summed.accumbytes += tcnt.accumbytes;\n\t\t}\n\t}\n\n\tif (ctx->cnt_summed.curobjs != 0)\n\t\t(*leak_nctx)++;\n\n\t/* Add to cnt_all. */\n\tcnt_all->curobjs += ctx->cnt_summed.curobjs;\n\tcnt_all->curbytes += ctx->cnt_summed.curbytes;\n\tif (opt_prof_accum) {\n\t\tcnt_all->accumobjs += ctx->cnt_summed.accumobjs;\n\t\tcnt_all->accumbytes += ctx->cnt_summed.accumbytes;\n\t}\n\n\tmalloc_mutex_unlock(ctx->lock);\n}\n\nstatic bool\nprof_dump_header(bool propagate_err, const prof_cnt_t *cnt_all)\n{\n\n\tif (opt_lg_prof_sample == 0) {\n\t\tif (prof_dump_printf(propagate_err,\n\t\t    \"heap profile: %\"PRId64\": %\"PRId64\n\t\t    \" [%\"PRIu64\": %\"PRIu64\"] @ heapprofile\\n\",\n\t\t    cnt_all->curobjs, cnt_all->curbytes,\n\t\t    cnt_all->accumobjs, cnt_all->accumbytes))\n\t\t\treturn (true);\n\t} else {\n\t\tif (prof_dump_printf(propagate_err,\n\t\t    \"heap profile: %\"PRId64\": %\"PRId64\n\t\t    \" [%\"PRIu64\": %\"PRIu64\"] @ heap_v2/%\"PRIu64\"\\n\",\n\t\t    cnt_all->curobjs, cnt_all->curbytes,\n\t\t    cnt_all->accumobjs, cnt_all->accumbytes,\n\t\t    ((uint64_t)1U << opt_lg_prof_sample)))\n\t\t\treturn (true);\n\t}\n\n\treturn (false);\n}\n\nstatic void\nprof_dump_ctx_cleanup_locked(prof_ctx_t *ctx, prof_ctx_list_t *ctx_ql)\n{\n\n\tctx->nlimbo--;\n\tql_remove(ctx_ql, ctx, dump_link);\n}\n\nstatic void\nprof_dump_ctx_cleanup(prof_ctx_t *ctx, prof_ctx_list_t *ctx_ql)\n{\n\n\tmalloc_mutex_lock(ctx->lock);\n\tprof_dump_ctx_cleanup_locked(ctx, ctx_ql);\n\tmalloc_mutex_unlock(ctx->lock);\n}\n\nstatic bool\nprof_dump_ctx(bool propagate_err, prof_ctx_t *ctx, const prof_bt_t *bt,\n    prof_ctx_list_t *ctx_ql)\n{\n\tbool ret;\n\tunsigned i;\n\n\tcassert(config_prof);\n\n\t/*\n\t * Current statistics can sum to 0 as a result of unmerged per thread\n\t * statistics.  Additionally, interval- and growth-triggered dumps can\n\t * occur between the time a ctx is created and when its statistics are\n\t * filled in.  Avoid dumping any ctx that is an artifact of either\n\t * implementation detail.\n\t */\n\tmalloc_mutex_lock(ctx->lock);\n\tif ((opt_prof_accum == false && ctx->cnt_summed.curobjs == 0) ||\n\t    (opt_prof_accum && ctx->cnt_summed.accumobjs == 0)) {\n\t\tassert(ctx->cnt_summed.curobjs == 0);\n\t\tassert(ctx->cnt_summed.curbytes == 0);\n\t\tassert(ctx->cnt_summed.accumobjs == 0);\n\t\tassert(ctx->cnt_summed.accumbytes == 0);\n\t\tret = false;\n\t\tgoto label_return;\n\t}\n\n\tif (prof_dump_printf(propagate_err, \"%\"PRId64\": %\"PRId64\n\t    \" [%\"PRIu64\": %\"PRIu64\"] @\",\n\t    ctx->cnt_summed.curobjs, ctx->cnt_summed.curbytes,\n\t    ctx->cnt_summed.accumobjs, ctx->cnt_summed.accumbytes)) {\n\t\tret = true;\n\t\tgoto label_return;\n\t}\n\n\tfor (i = 0; i < bt->len; i++) {\n\t\tif (prof_dump_printf(propagate_err, \" %#\"PRIxPTR,\n\t\t    (uintptr_t)bt->vec[i])) {\n\t\t\tret = true;\n\t\t\tgoto label_return;\n\t\t}\n\t}\n\n\tif (prof_dump_write(propagate_err, \"\\n\")) {\n\t\tret = true;\n\t\tgoto label_return;\n\t}\n\n\tret = false;\nlabel_return:\n\tprof_dump_ctx_cleanup_locked(ctx, ctx_ql);\n\tmalloc_mutex_unlock(ctx->lock);\n\treturn (ret);\n}\n\nstatic bool\nprof_dump_maps(bool propagate_err)\n{\n\tbool ret;\n\tint mfd;\n\tchar filename[PATH_MAX + 1];\n\n\tcassert(config_prof);\n#ifdef __FreeBSD__\n\tmalloc_snprintf(filename, sizeof(filename), \"/proc/curproc/map\");\n#else\n\tmalloc_snprintf(filename, sizeof(filename), \"/proc/%d/maps\",\n\t    (int)getpid());\n#endif\n\tmfd = open(filename, O_RDONLY);\n\tif (mfd != -1) {\n\t\tssize_t nread;\n\n\t\tif (prof_dump_write(propagate_err, \"\\nMAPPED_LIBRARIES:\\n\") &&\n\t\t    propagate_err) {\n\t\t\tret = true;\n\t\t\tgoto label_return;\n\t\t}\n\t\tnread = 0;\n\t\tdo {\n\t\t\tprof_dump_buf_end += nread;\n\t\t\tif (prof_dump_buf_end == PROF_DUMP_BUFSIZE) {\n\t\t\t\t/* Make space in prof_dump_buf before read(). */\n\t\t\t\tif (prof_dump_flush(propagate_err) &&\n\t\t\t\t    propagate_err) {\n\t\t\t\t\tret = true;\n\t\t\t\t\tgoto label_return;\n\t\t\t\t}\n\t\t\t}\n\t\t\tnread = read(mfd, &prof_dump_buf[prof_dump_buf_end],\n\t\t\t    PROF_DUMP_BUFSIZE - prof_dump_buf_end);\n\t\t} while (nread > 0);\n\t} else {\n\t\tret = true;\n\t\tgoto label_return;\n\t}\n\n\tret = false;\nlabel_return:\n\tif (mfd != -1)\n\t\tclose(mfd);\n\treturn (ret);\n}\n\nstatic void\nprof_leakcheck(const prof_cnt_t *cnt_all, size_t leak_nctx,\n    const char *filename)\n{\n\n\tif (cnt_all->curbytes != 0) {\n\t\tmalloc_printf(\"<jemalloc>: Leak summary: %\"PRId64\" byte%s, %\"\n\t\t    PRId64\" object%s, %zu context%s\\n\",\n\t\t    cnt_all->curbytes, (cnt_all->curbytes != 1) ? \"s\" : \"\",\n\t\t    cnt_all->curobjs, (cnt_all->curobjs != 1) ? \"s\" : \"\",\n\t\t    leak_nctx, (leak_nctx != 1) ? \"s\" : \"\");\n\t\tmalloc_printf(\n\t\t    \"<jemalloc>: Run pprof on \\\"%s\\\" for leak detail\\n\",\n\t\t    filename);\n\t}\n}\n\nstatic bool\nprof_dump(bool propagate_err, const char *filename, bool leakcheck)\n{\n\tprof_tdata_t *prof_tdata;\n\tprof_cnt_t cnt_all;\n\tsize_t tabind;\n\tunion {\n\t\tprof_ctx_t\t*p;\n\t\tvoid\t\t*v;\n\t} ctx;\n\tsize_t leak_nctx;\n\tprof_ctx_list_t ctx_ql;\n\n\tcassert(config_prof);\n\n\tprof_tdata = prof_tdata_get(false);\n\tif ((uintptr_t)prof_tdata <= (uintptr_t)PROF_TDATA_STATE_MAX)\n\t\treturn (true);\n\n\tmalloc_mutex_lock(&prof_dump_mtx);\n\n\t/* Merge per thread profile stats, and sum them in cnt_all. */\n\tmemset(&cnt_all, 0, sizeof(prof_cnt_t));\n\tleak_nctx = 0;\n\tql_new(&ctx_ql);\n\tprof_enter(prof_tdata);\n\tfor (tabind = 0; ckh_iter(&bt2ctx, &tabind, NULL, &ctx.v) == false;)\n\t\tprof_dump_ctx_prep(ctx.p, &cnt_all, &leak_nctx, &ctx_ql);\n\tprof_leave(prof_tdata);\n\n\t/* Create dump file. */\n\tif ((prof_dump_fd = prof_dump_open(propagate_err, filename)) == -1)\n\t\tgoto label_open_close_error;\n\n\t/* Dump profile header. */\n\tif (prof_dump_header(propagate_err, &cnt_all))\n\t\tgoto label_write_error;\n\n\t/* Dump per ctx profile stats. */\n\twhile ((ctx.p = ql_first(&ctx_ql)) != NULL) {\n\t\tif (prof_dump_ctx(propagate_err, ctx.p, ctx.p->bt, &ctx_ql))\n\t\t\tgoto label_write_error;\n\t}\n\n\t/* Dump /proc/<pid>/maps if possible. */\n\tif (prof_dump_maps(propagate_err))\n\t\tgoto label_write_error;\n\n\tif (prof_dump_close(propagate_err))\n\t\tgoto label_open_close_error;\n\n\tmalloc_mutex_unlock(&prof_dump_mtx);\n\n\tif (leakcheck)\n\t\tprof_leakcheck(&cnt_all, leak_nctx, filename);\n\n\treturn (false);\nlabel_write_error:\n\tprof_dump_close(propagate_err);\nlabel_open_close_error:\n\twhile ((ctx.p = ql_first(&ctx_ql)) != NULL)\n\t\tprof_dump_ctx_cleanup(ctx.p, &ctx_ql);\n\tmalloc_mutex_unlock(&prof_dump_mtx);\n\treturn (true);\n}\n\n#define\tDUMP_FILENAME_BUFSIZE\t(PATH_MAX + 1)\n#define\tVSEQ_INVALID\t\tUINT64_C(0xffffffffffffffff)\nstatic void\nprof_dump_filename(char *filename, char v, int64_t vseq)\n{\n\n\tcassert(config_prof);\n\n\tif (vseq != VSEQ_INVALID) {\n\t        /* \"<prefix>.<pid>.<seq>.v<vseq>.heap\" */\n\t\tmalloc_snprintf(filename, DUMP_FILENAME_BUFSIZE,\n\t\t    \"%s.%d.%\"PRIu64\".%c%\"PRId64\".heap\",\n\t\t    opt_prof_prefix, (int)getpid(), prof_dump_seq, v, vseq);\n\t} else {\n\t        /* \"<prefix>.<pid>.<seq>.<v>.heap\" */\n\t\tmalloc_snprintf(filename, DUMP_FILENAME_BUFSIZE,\n\t\t    \"%s.%d.%\"PRIu64\".%c.heap\",\n\t\t    opt_prof_prefix, (int)getpid(), prof_dump_seq, v);\n\t}\n\tprof_dump_seq++;\n}\n\nstatic void\nprof_fdump(void)\n{\n\tchar filename[DUMP_FILENAME_BUFSIZE];\n\n\tcassert(config_prof);\n\n\tif (prof_booted == false)\n\t\treturn;\n\n\tif (opt_prof_final && opt_prof_prefix[0] != '\\0') {\n\t\tmalloc_mutex_lock(&prof_dump_seq_mtx);\n\t\tprof_dump_filename(filename, 'f', VSEQ_INVALID);\n\t\tmalloc_mutex_unlock(&prof_dump_seq_mtx);\n\t\tprof_dump(false, filename, opt_prof_leak);\n\t}\n}\n\nvoid\nprof_idump(void)\n{\n\tprof_tdata_t *prof_tdata;\n\tchar filename[PATH_MAX + 1];\n\n\tcassert(config_prof);\n\n\tif (prof_booted == false)\n\t\treturn;\n\tprof_tdata = prof_tdata_get(false);\n\tif ((uintptr_t)prof_tdata <= (uintptr_t)PROF_TDATA_STATE_MAX)\n\t\treturn;\n\tif (prof_tdata->enq) {\n\t\tprof_tdata->enq_idump = true;\n\t\treturn;\n\t}\n\n\tif (opt_prof_prefix[0] != '\\0') {\n\t\tmalloc_mutex_lock(&prof_dump_seq_mtx);\n\t\tprof_dump_filename(filename, 'i', prof_dump_iseq);\n\t\tprof_dump_iseq++;\n\t\tmalloc_mutex_unlock(&prof_dump_seq_mtx);\n\t\tprof_dump(false, filename, false);\n\t}\n}\n\nbool\nprof_mdump(const char *filename)\n{\n\tchar filename_buf[DUMP_FILENAME_BUFSIZE];\n\n\tcassert(config_prof);\n\n\tif (opt_prof == false || prof_booted == false)\n\t\treturn (true);\n\n\tif (filename == NULL) {\n\t\t/* No filename specified, so automatically generate one. */\n\t\tif (opt_prof_prefix[0] == '\\0')\n\t\t\treturn (true);\n\t\tmalloc_mutex_lock(&prof_dump_seq_mtx);\n\t\tprof_dump_filename(filename_buf, 'm', prof_dump_mseq);\n\t\tprof_dump_mseq++;\n\t\tmalloc_mutex_unlock(&prof_dump_seq_mtx);\n\t\tfilename = filename_buf;\n\t}\n\treturn (prof_dump(true, filename, false));\n}\n\nvoid\nprof_gdump(void)\n{\n\tprof_tdata_t *prof_tdata;\n\tchar filename[DUMP_FILENAME_BUFSIZE];\n\n\tcassert(config_prof);\n\n\tif (prof_booted == false)\n\t\treturn;\n\tprof_tdata = prof_tdata_get(false);\n\tif ((uintptr_t)prof_tdata <= (uintptr_t)PROF_TDATA_STATE_MAX)\n\t\treturn;\n\tif (prof_tdata->enq) {\n\t\tprof_tdata->enq_gdump = true;\n\t\treturn;\n\t}\n\n\tif (opt_prof_prefix[0] != '\\0') {\n\t\tmalloc_mutex_lock(&prof_dump_seq_mtx);\n\t\tprof_dump_filename(filename, 'u', prof_dump_useq);\n\t\tprof_dump_useq++;\n\t\tmalloc_mutex_unlock(&prof_dump_seq_mtx);\n\t\tprof_dump(false, filename, false);\n\t}\n}\n\nstatic void\nprof_bt_hash(const void *key, size_t r_hash[2])\n{\n\tprof_bt_t *bt = (prof_bt_t *)key;\n\n\tcassert(config_prof);\n\n\thash(bt->vec, bt->len * sizeof(void *), 0x94122f33U, r_hash);\n}\n\nstatic bool\nprof_bt_keycomp(const void *k1, const void *k2)\n{\n\tconst prof_bt_t *bt1 = (prof_bt_t *)k1;\n\tconst prof_bt_t *bt2 = (prof_bt_t *)k2;\n\n\tcassert(config_prof);\n\n\tif (bt1->len != bt2->len)\n\t\treturn (false);\n\treturn (memcmp(bt1->vec, bt2->vec, bt1->len * sizeof(void *)) == 0);\n}\n\nprof_tdata_t *\nprof_tdata_init(void)\n{\n\tprof_tdata_t *prof_tdata;\n\n\tcassert(config_prof);\n\n\t/* Initialize an empty cache for this thread. */\n\tprof_tdata = (prof_tdata_t *)imalloc(sizeof(prof_tdata_t));\n\tif (prof_tdata == NULL)\n\t\treturn (NULL);\n\n\tif (ckh_new(&prof_tdata->bt2cnt, PROF_CKH_MINITEMS,\n\t    prof_bt_hash, prof_bt_keycomp)) {\n\t\tidalloc(prof_tdata);\n\t\treturn (NULL);\n\t}\n\tql_new(&prof_tdata->lru_ql);\n\n\tprof_tdata->vec = imalloc(sizeof(void *) * PROF_BT_MAX);\n\tif (prof_tdata->vec == NULL) {\n\t\tckh_delete(&prof_tdata->bt2cnt);\n\t\tidalloc(prof_tdata);\n\t\treturn (NULL);\n\t}\n\n\tprof_tdata->prng_state = 0;\n\tprof_tdata->threshold = 0;\n\tprof_tdata->accum = 0;\n\n\tprof_tdata->enq = false;\n\tprof_tdata->enq_idump = false;\n\tprof_tdata->enq_gdump = false;\n\n\tprof_tdata_tsd_set(&prof_tdata);\n\n\treturn (prof_tdata);\n}\n\nvoid\nprof_tdata_cleanup(void *arg)\n{\n\tprof_thr_cnt_t *cnt;\n\tprof_tdata_t *prof_tdata = *(prof_tdata_t **)arg;\n\n\tcassert(config_prof);\n\n\tif (prof_tdata == PROF_TDATA_STATE_REINCARNATED) {\n\t\t/*\n\t\t * Another destructor deallocated memory after this destructor\n\t\t * was called.  Reset prof_tdata to PROF_TDATA_STATE_PURGATORY\n\t\t * in order to receive another callback.\n\t\t */\n\t\tprof_tdata = PROF_TDATA_STATE_PURGATORY;\n\t\tprof_tdata_tsd_set(&prof_tdata);\n\t} else if (prof_tdata == PROF_TDATA_STATE_PURGATORY) {\n\t\t/*\n\t\t * The previous time this destructor was called, we set the key\n\t\t * to PROF_TDATA_STATE_PURGATORY so that other destructors\n\t\t * wouldn't cause re-creation of the prof_tdata.  This time, do\n\t\t * nothing, so that the destructor will not be called again.\n\t\t */\n\t} else if (prof_tdata != NULL) {\n\t\t/*\n\t\t * Delete the hash table.  All of its contents can still be\n\t\t * iterated over via the LRU.\n\t\t */\n\t\tckh_delete(&prof_tdata->bt2cnt);\n\t\t/*\n\t\t * Iteratively merge cnt's into the global stats and delete\n\t\t * them.\n\t\t */\n\t\twhile ((cnt = ql_last(&prof_tdata->lru_ql, lru_link)) != NULL) {\n\t\t\tql_remove(&prof_tdata->lru_ql, cnt, lru_link);\n\t\t\tprof_ctx_merge(cnt->ctx, cnt);\n\t\t\tidalloc(cnt);\n\t\t}\n\t\tidalloc(prof_tdata->vec);\n\t\tidalloc(prof_tdata);\n\t\tprof_tdata = PROF_TDATA_STATE_PURGATORY;\n\t\tprof_tdata_tsd_set(&prof_tdata);\n\t}\n}\n\nvoid\nprof_boot0(void)\n{\n\n\tcassert(config_prof);\n\n\tmemcpy(opt_prof_prefix, PROF_PREFIX_DEFAULT,\n\t    sizeof(PROF_PREFIX_DEFAULT));\n}\n\nvoid\nprof_boot1(void)\n{\n\n\tcassert(config_prof);\n\n\t/*\n\t * opt_prof and prof_promote must be in their final state before any\n\t * arenas are initialized, so this function must be executed early.\n\t */\n\n\tif (opt_prof_leak && opt_prof == false) {\n\t\t/*\n\t\t * Enable opt_prof, but in such a way that profiles are never\n\t\t * automatically dumped.\n\t\t */\n\t\topt_prof = true;\n\t\topt_prof_gdump = false;\n\t} else if (opt_prof) {\n\t\tif (opt_lg_prof_interval >= 0) {\n\t\t\tprof_interval = (((uint64_t)1U) <<\n\t\t\t    opt_lg_prof_interval);\n\t\t}\n\t}\n\n\tprof_promote = (opt_prof && opt_lg_prof_sample > LG_PAGE);\n}\n\nbool\nprof_boot2(void)\n{\n\n\tcassert(config_prof);\n\n\tif (opt_prof) {\n\t\tunsigned i;\n\n\t\tif (ckh_new(&bt2ctx, PROF_CKH_MINITEMS, prof_bt_hash,\n\t\t    prof_bt_keycomp))\n\t\t\treturn (true);\n\t\tif (malloc_mutex_init(&bt2ctx_mtx))\n\t\t\treturn (true);\n\t\tif (prof_tdata_tsd_boot()) {\n\t\t\tmalloc_write(\n\t\t\t    \"<jemalloc>: Error in pthread_key_create()\\n\");\n\t\t\tabort();\n\t\t}\n\n\t\tif (malloc_mutex_init(&prof_dump_seq_mtx))\n\t\t\treturn (true);\n\t\tif (malloc_mutex_init(&prof_dump_mtx))\n\t\t\treturn (true);\n\n\t\tif (atexit(prof_fdump) != 0) {\n\t\t\tmalloc_write(\"<jemalloc>: Error in atexit()\\n\");\n\t\t\tif (opt_abort)\n\t\t\t\tabort();\n\t\t}\n\n\t\tctx_locks = (malloc_mutex_t *)base_alloc(PROF_NCTX_LOCKS *\n\t\t    sizeof(malloc_mutex_t));\n\t\tif (ctx_locks == NULL)\n\t\t\treturn (true);\n\t\tfor (i = 0; i < PROF_NCTX_LOCKS; i++) {\n\t\t\tif (malloc_mutex_init(&ctx_locks[i]))\n\t\t\t\treturn (true);\n\t\t}\n\t}\n\n#ifdef JEMALLOC_PROF_LIBGCC\n\t/*\n\t * Cause the backtracing machinery to allocate its internal state\n\t * before enabling profiling.\n\t */\n\t_Unwind_Backtrace(prof_unwind_init_callback, NULL);\n#endif\n\n\tprof_booted = true;\n\n\treturn (false);\n}\n\nvoid\nprof_prefork(void)\n{\n\n\tif (opt_prof) {\n\t\tunsigned i;\n\n\t\tmalloc_mutex_prefork(&bt2ctx_mtx);\n\t\tmalloc_mutex_prefork(&prof_dump_seq_mtx);\n\t\tfor (i = 0; i < PROF_NCTX_LOCKS; i++)\n\t\t\tmalloc_mutex_prefork(&ctx_locks[i]);\n\t}\n}\n\nvoid\nprof_postfork_parent(void)\n{\n\n\tif (opt_prof) {\n\t\tunsigned i;\n\n\t\tfor (i = 0; i < PROF_NCTX_LOCKS; i++)\n\t\t\tmalloc_mutex_postfork_parent(&ctx_locks[i]);\n\t\tmalloc_mutex_postfork_parent(&prof_dump_seq_mtx);\n\t\tmalloc_mutex_postfork_parent(&bt2ctx_mtx);\n\t}\n}\n\nvoid\nprof_postfork_child(void)\n{\n\n\tif (opt_prof) {\n\t\tunsigned i;\n\n\t\tfor (i = 0; i < PROF_NCTX_LOCKS; i++)\n\t\t\tmalloc_mutex_postfork_child(&ctx_locks[i]);\n\t\tmalloc_mutex_postfork_child(&prof_dump_seq_mtx);\n\t\tmalloc_mutex_postfork_child(&bt2ctx_mtx);\n\t}\n}\n\n/******************************************************************************/\n"
  },
  {
    "path": "extern/deprecated/redis-2.8.21/deps/jemalloc/src/quarantine.c",
    "content": "#define\tJEMALLOC_QUARANTINE_C_\n#include \"jemalloc/internal/jemalloc_internal.h\"\n\n/*\n * quarantine pointers close to NULL are used to encode state information that\n * is used for cleaning up during thread shutdown.\n */\n#define\tQUARANTINE_STATE_REINCARNATED\t((quarantine_t *)(uintptr_t)1)\n#define\tQUARANTINE_STATE_PURGATORY\t((quarantine_t *)(uintptr_t)2)\n#define\tQUARANTINE_STATE_MAX\t\tQUARANTINE_STATE_PURGATORY\n\n/******************************************************************************/\n/* Data. */\n\nmalloc_tsd_data(, quarantine, quarantine_t *, NULL)\n\n/******************************************************************************/\n/* Function prototypes for non-inline static functions. */\n\nstatic quarantine_t\t*quarantine_grow(quarantine_t *quarantine);\nstatic void\tquarantine_drain_one(quarantine_t *quarantine);\nstatic void\tquarantine_drain(quarantine_t *quarantine, size_t upper_bound);\n\n/******************************************************************************/\n\nquarantine_t *\nquarantine_init(size_t lg_maxobjs)\n{\n\tquarantine_t *quarantine;\n\n\tquarantine = (quarantine_t *)imalloc(offsetof(quarantine_t, objs) +\n\t    ((ZU(1) << lg_maxobjs) * sizeof(quarantine_obj_t)));\n\tif (quarantine == NULL)\n\t\treturn (NULL);\n\tquarantine->curbytes = 0;\n\tquarantine->curobjs = 0;\n\tquarantine->first = 0;\n\tquarantine->lg_maxobjs = lg_maxobjs;\n\n\tquarantine_tsd_set(&quarantine);\n\n\treturn (quarantine);\n}\n\nstatic quarantine_t *\nquarantine_grow(quarantine_t *quarantine)\n{\n\tquarantine_t *ret;\n\n\tret = quarantine_init(quarantine->lg_maxobjs + 1);\n\tif (ret == NULL) {\n\t\tquarantine_drain_one(quarantine);\n\t\treturn (quarantine);\n\t}\n\n\tret->curbytes = quarantine->curbytes;\n\tret->curobjs = quarantine->curobjs;\n\tif (quarantine->first + quarantine->curobjs <= (ZU(1) <<\n\t    quarantine->lg_maxobjs)) {\n\t\t/* objs ring buffer data are contiguous. */\n\t\tmemcpy(ret->objs, &quarantine->objs[quarantine->first],\n\t\t    quarantine->curobjs * sizeof(quarantine_obj_t));\n\t} else {\n\t\t/* objs ring buffer data wrap around. */\n\t\tsize_t ncopy_a = (ZU(1) << quarantine->lg_maxobjs) -\n\t\t    quarantine->first;\n\t\tsize_t ncopy_b = quarantine->curobjs - ncopy_a;\n\n\t\tmemcpy(ret->objs, &quarantine->objs[quarantine->first], ncopy_a\n\t\t    * sizeof(quarantine_obj_t));\n\t\tmemcpy(&ret->objs[ncopy_a], quarantine->objs, ncopy_b *\n\t\t    sizeof(quarantine_obj_t));\n\t}\n\tidalloc(quarantine);\n\n\treturn (ret);\n}\n\nstatic void\nquarantine_drain_one(quarantine_t *quarantine)\n{\n\tquarantine_obj_t *obj = &quarantine->objs[quarantine->first];\n\tassert(obj->usize == isalloc(obj->ptr, config_prof));\n\tidalloc(obj->ptr);\n\tquarantine->curbytes -= obj->usize;\n\tquarantine->curobjs--;\n\tquarantine->first = (quarantine->first + 1) & ((ZU(1) <<\n\t    quarantine->lg_maxobjs) - 1);\n}\n\nstatic void\nquarantine_drain(quarantine_t *quarantine, size_t upper_bound)\n{\n\n\twhile (quarantine->curbytes > upper_bound && quarantine->curobjs > 0)\n\t\tquarantine_drain_one(quarantine);\n}\n\nvoid\nquarantine(void *ptr)\n{\n\tquarantine_t *quarantine;\n\tsize_t usize = isalloc(ptr, config_prof);\n\n\tcassert(config_fill);\n\tassert(opt_quarantine);\n\n\tquarantine = *quarantine_tsd_get();\n\tif ((uintptr_t)quarantine <= (uintptr_t)QUARANTINE_STATE_MAX) {\n\t\tif (quarantine == QUARANTINE_STATE_PURGATORY) {\n\t\t\t/*\n\t\t\t * Make a note that quarantine() was called after\n\t\t\t * quarantine_cleanup() was called.\n\t\t\t */\n\t\t\tquarantine = QUARANTINE_STATE_REINCARNATED;\n\t\t\tquarantine_tsd_set(&quarantine);\n\t\t}\n\t\tidalloc(ptr);\n\t\treturn;\n\t}\n\t/*\n\t * Drain one or more objects if the quarantine size limit would be\n\t * exceeded by appending ptr.\n\t */\n\tif (quarantine->curbytes + usize > opt_quarantine) {\n\t\tsize_t upper_bound = (opt_quarantine >= usize) ? opt_quarantine\n\t\t    - usize : 0;\n\t\tquarantine_drain(quarantine, upper_bound);\n\t}\n\t/* Grow the quarantine ring buffer if it's full. */\n\tif (quarantine->curobjs == (ZU(1) << quarantine->lg_maxobjs))\n\t\tquarantine = quarantine_grow(quarantine);\n\t/* quarantine_grow() must free a slot if it fails to grow. */\n\tassert(quarantine->curobjs < (ZU(1) << quarantine->lg_maxobjs));\n\t/* Append ptr if its size doesn't exceed the quarantine size. */\n\tif (quarantine->curbytes + usize <= opt_quarantine) {\n\t\tsize_t offset = (quarantine->first + quarantine->curobjs) &\n\t\t    ((ZU(1) << quarantine->lg_maxobjs) - 1);\n\t\tquarantine_obj_t *obj = &quarantine->objs[offset];\n\t\tobj->ptr = ptr;\n\t\tobj->usize = usize;\n\t\tquarantine->curbytes += usize;\n\t\tquarantine->curobjs++;\n\t\tif (config_fill && opt_junk) {\n\t\t\t/*\n\t\t\t * Only do redzone validation if Valgrind isn't in\n\t\t\t * operation.\n\t\t\t */\n\t\t\tif ((config_valgrind == false || opt_valgrind == false)\n\t\t\t    && usize <= SMALL_MAXCLASS)\n\t\t\t\tarena_quarantine_junk_small(ptr, usize);\n\t\t\telse\n\t\t\t\tmemset(ptr, 0x5a, usize);\n\t\t}\n\t} else {\n\t\tassert(quarantine->curbytes == 0);\n\t\tidalloc(ptr);\n\t}\n}\n\nvoid\nquarantine_cleanup(void *arg)\n{\n\tquarantine_t *quarantine = *(quarantine_t **)arg;\n\n\tif (quarantine == QUARANTINE_STATE_REINCARNATED) {\n\t\t/*\n\t\t * Another destructor deallocated memory after this destructor\n\t\t * was called.  Reset quarantine to QUARANTINE_STATE_PURGATORY\n\t\t * in order to receive another callback.\n\t\t */\n\t\tquarantine = QUARANTINE_STATE_PURGATORY;\n\t\tquarantine_tsd_set(&quarantine);\n\t} else if (quarantine == QUARANTINE_STATE_PURGATORY) {\n\t\t/*\n\t\t * The previous time this destructor was called, we set the key\n\t\t * to QUARANTINE_STATE_PURGATORY so that other destructors\n\t\t * wouldn't cause re-creation of the quarantine.  This time, do\n\t\t * nothing, so that the destructor will not be called again.\n\t\t */\n\t} else if (quarantine != NULL) {\n\t\tquarantine_drain(quarantine, 0);\n\t\tidalloc(quarantine);\n\t\tquarantine = QUARANTINE_STATE_PURGATORY;\n\t\tquarantine_tsd_set(&quarantine);\n\t}\n}\n\nbool\nquarantine_boot(void)\n{\n\n\tcassert(config_fill);\n\n\tif (quarantine_tsd_boot())\n\t\treturn (true);\n\n\treturn (false);\n}\n"
  },
  {
    "path": "extern/deprecated/redis-2.8.21/deps/jemalloc/src/rtree.c",
    "content": "#define\tJEMALLOC_RTREE_C_\n#include \"jemalloc/internal/jemalloc_internal.h\"\n\nrtree_t *\nrtree_new(unsigned bits, rtree_alloc_t *alloc, rtree_dalloc_t *dalloc)\n{\n\trtree_t *ret;\n\tunsigned bits_per_level, bits_in_leaf, height, i;\n\n\tassert(bits > 0 && bits <= (sizeof(uintptr_t) << 3));\n\n\tbits_per_level = ffs(pow2_ceil((RTREE_NODESIZE / sizeof(void *)))) - 1;\n\tbits_in_leaf = ffs(pow2_ceil((RTREE_NODESIZE / sizeof(uint8_t)))) - 1;\n\tif (bits > bits_in_leaf) {\n\t\theight = 1 + (bits - bits_in_leaf) / bits_per_level;\n\t\tif ((height-1) * bits_per_level + bits_in_leaf != bits)\n\t\t\theight++;\n\t} else {\n\t\theight = 1;\n\t}\n\tassert((height-1) * bits_per_level + bits_in_leaf >= bits);\n\n\tret = (rtree_t*)alloc(offsetof(rtree_t, level2bits) +\n\t    (sizeof(unsigned) * height));\n\tif (ret == NULL)\n\t\treturn (NULL);\n\tmemset(ret, 0, offsetof(rtree_t, level2bits) + (sizeof(unsigned) *\n\t    height));\n\n\tret->alloc = alloc;\n\tret->dalloc = dalloc;\n\tif (malloc_mutex_init(&ret->mutex)) {\n\t\tif (dalloc != NULL)\n\t\t\tdalloc(ret);\n\t\treturn (NULL);\n\t}\n\tret->height = height;\n\tif (height > 1) {\n\t\tif ((height-1) * bits_per_level + bits_in_leaf > bits) {\n\t\t\tret->level2bits[0] = (bits - bits_in_leaf) %\n\t\t\t    bits_per_level;\n\t\t} else\n\t\t\tret->level2bits[0] = bits_per_level;\n\t\tfor (i = 1; i < height-1; i++)\n\t\t\tret->level2bits[i] = bits_per_level;\n\t\tret->level2bits[height-1] = bits_in_leaf;\n\t} else\n\t\tret->level2bits[0] = bits;\n\n\tret->root = (void**)alloc(sizeof(void *) << ret->level2bits[0]);\n\tif (ret->root == NULL) {\n\t\tif (dalloc != NULL)\n\t\t\tdalloc(ret);\n\t\treturn (NULL);\n\t}\n\tmemset(ret->root, 0, sizeof(void *) << ret->level2bits[0]);\n\n\treturn (ret);\n}\n\nstatic void\nrtree_delete_subtree(rtree_t *rtree, void **node, unsigned level)\n{\n\n\tif (level < rtree->height - 1) {\n\t\tsize_t nchildren, i;\n\n\t\tnchildren = ZU(1) << rtree->level2bits[level];\n\t\tfor (i = 0; i < nchildren; i++) {\n\t\t\tvoid **child = (void **)node[i];\n\t\t\tif (child != NULL)\n\t\t\t\trtree_delete_subtree(rtree, child, level + 1);\n\t\t}\n\t}\n\trtree->dalloc(node);\n}\n\nvoid\nrtree_delete(rtree_t *rtree)\n{\n\n\trtree_delete_subtree(rtree, rtree->root, 0);\n\trtree->dalloc(rtree);\n}\n\nvoid\nrtree_prefork(rtree_t *rtree)\n{\n\n\tmalloc_mutex_prefork(&rtree->mutex);\n}\n\nvoid\nrtree_postfork_parent(rtree_t *rtree)\n{\n\n\tmalloc_mutex_postfork_parent(&rtree->mutex);\n}\n\nvoid\nrtree_postfork_child(rtree_t *rtree)\n{\n\n\tmalloc_mutex_postfork_child(&rtree->mutex);\n}\n"
  },
  {
    "path": "extern/deprecated/redis-2.8.21/deps/jemalloc/src/stats.c",
    "content": "#define\tJEMALLOC_STATS_C_\n#include \"jemalloc/internal/jemalloc_internal.h\"\n\n#define\tCTL_GET(n, v, t) do {\t\t\t\t\t\t\\\n\tsize_t sz = sizeof(t);\t\t\t\t\t\t\\\n\txmallctl(n, v, &sz, NULL, 0);\t\t\t\t\t\\\n} while (0)\n\n#define\tCTL_I_GET(n, v, t) do {\t\t\t\t\t\t\\\n\tsize_t mib[6];\t\t\t\t\t\t\t\\\n\tsize_t miblen = sizeof(mib) / sizeof(size_t);\t\t\t\\\n\tsize_t sz = sizeof(t);\t\t\t\t\t\t\\\n\txmallctlnametomib(n, mib, &miblen);\t\t\t\t\\\n\tmib[2] = i;\t\t\t\t\t\t\t\\\n\txmallctlbymib(mib, miblen, v, &sz, NULL, 0);\t\t\t\\\n} while (0)\n\n#define\tCTL_J_GET(n, v, t) do {\t\t\t\t\t\t\\\n\tsize_t mib[6];\t\t\t\t\t\t\t\\\n\tsize_t miblen = sizeof(mib) / sizeof(size_t);\t\t\t\\\n\tsize_t sz = sizeof(t);\t\t\t\t\t\t\\\n\txmallctlnametomib(n, mib, &miblen);\t\t\t\t\\\n\tmib[2] = j;\t\t\t\t\t\t\t\\\n\txmallctlbymib(mib, miblen, v, &sz, NULL, 0);\t\t\t\\\n} while (0)\n\n#define\tCTL_IJ_GET(n, v, t) do {\t\t\t\t\t\\\n\tsize_t mib[6];\t\t\t\t\t\t\t\\\n\tsize_t miblen = sizeof(mib) / sizeof(size_t);\t\t\t\\\n\tsize_t sz = sizeof(t);\t\t\t\t\t\t\\\n\txmallctlnametomib(n, mib, &miblen);\t\t\t\t\\\n\tmib[2] = i;\t\t\t\t\t\t\t\\\n\tmib[4] = j;\t\t\t\t\t\t\t\\\n\txmallctlbymib(mib, miblen, v, &sz, NULL, 0);\t\t\t\\\n} while (0)\n\n/******************************************************************************/\n/* Data. */\n\nbool\topt_stats_print = false;\n\nsize_t\tstats_cactive = 0;\n\n/******************************************************************************/\n/* Function prototypes for non-inline static functions. */\n\nstatic void\tstats_arena_bins_print(void (*write_cb)(void *, const char *),\n    void *cbopaque, unsigned i);\nstatic void\tstats_arena_lruns_print(void (*write_cb)(void *, const char *),\n    void *cbopaque, unsigned i);\nstatic void\tstats_arena_print(void (*write_cb)(void *, const char *),\n    void *cbopaque, unsigned i, bool bins, bool large);\n\n/******************************************************************************/\n\nstatic void\nstats_arena_bins_print(void (*write_cb)(void *, const char *), void *cbopaque,\n    unsigned i)\n{\n\tsize_t page;\n\tbool config_tcache;\n\tunsigned nbins, j, gap_start;\n\n\tCTL_GET(\"arenas.page\", &page, size_t);\n\n\tCTL_GET(\"config.tcache\", &config_tcache, bool);\n\tif (config_tcache) {\n\t\tmalloc_cprintf(write_cb, cbopaque,\n\t\t    \"bins:     bin  size regs pgs    allocated      nmalloc\"\n\t\t    \"      ndalloc    nrequests       nfills     nflushes\"\n\t\t    \"      newruns       reruns      curruns\\n\");\n\t} else {\n\t\tmalloc_cprintf(write_cb, cbopaque,\n\t\t    \"bins:     bin  size regs pgs    allocated      nmalloc\"\n\t\t    \"      ndalloc      newruns       reruns      curruns\\n\");\n\t}\n\tCTL_GET(\"arenas.nbins\", &nbins, unsigned);\n\tfor (j = 0, gap_start = UINT_MAX; j < nbins; j++) {\n\t\tuint64_t nruns;\n\n\t\tCTL_IJ_GET(\"stats.arenas.0.bins.0.nruns\", &nruns, uint64_t);\n\t\tif (nruns == 0) {\n\t\t\tif (gap_start == UINT_MAX)\n\t\t\t\tgap_start = j;\n\t\t} else {\n\t\t\tsize_t reg_size, run_size, allocated;\n\t\t\tuint32_t nregs;\n\t\t\tuint64_t nmalloc, ndalloc, nrequests, nfills, nflushes;\n\t\t\tuint64_t reruns;\n\t\t\tsize_t curruns;\n\n\t\t\tif (gap_start != UINT_MAX) {\n\t\t\t\tif (j > gap_start + 1) {\n\t\t\t\t\t/* Gap of more than one size class. */\n\t\t\t\t\tmalloc_cprintf(write_cb, cbopaque,\n\t\t\t\t\t    \"[%u..%u]\\n\", gap_start,\n\t\t\t\t\t    j - 1);\n\t\t\t\t} else {\n\t\t\t\t\t/* Gap of one size class. */\n\t\t\t\t\tmalloc_cprintf(write_cb, cbopaque,\n\t\t\t\t\t    \"[%u]\\n\", gap_start);\n\t\t\t\t}\n\t\t\t\tgap_start = UINT_MAX;\n\t\t\t}\n\t\t\tCTL_J_GET(\"arenas.bin.0.size\", &reg_size, size_t);\n\t\t\tCTL_J_GET(\"arenas.bin.0.nregs\", &nregs, uint32_t);\n\t\t\tCTL_J_GET(\"arenas.bin.0.run_size\", &run_size, size_t);\n\t\t\tCTL_IJ_GET(\"stats.arenas.0.bins.0.allocated\",\n\t\t\t    &allocated, size_t);\n\t\t\tCTL_IJ_GET(\"stats.arenas.0.bins.0.nmalloc\",\n\t\t\t    &nmalloc, uint64_t);\n\t\t\tCTL_IJ_GET(\"stats.arenas.0.bins.0.ndalloc\",\n\t\t\t    &ndalloc, uint64_t);\n\t\t\tif (config_tcache) {\n\t\t\t\tCTL_IJ_GET(\"stats.arenas.0.bins.0.nrequests\",\n\t\t\t\t    &nrequests, uint64_t);\n\t\t\t\tCTL_IJ_GET(\"stats.arenas.0.bins.0.nfills\",\n\t\t\t\t    &nfills, uint64_t);\n\t\t\t\tCTL_IJ_GET(\"stats.arenas.0.bins.0.nflushes\",\n\t\t\t\t    &nflushes, uint64_t);\n\t\t\t}\n\t\t\tCTL_IJ_GET(\"stats.arenas.0.bins.0.nreruns\", &reruns,\n\t\t\t    uint64_t);\n\t\t\tCTL_IJ_GET(\"stats.arenas.0.bins.0.curruns\", &curruns,\n\t\t\t    size_t);\n\t\t\tif (config_tcache) {\n\t\t\t\tmalloc_cprintf(write_cb, cbopaque,\n\t\t\t\t    \"%13u %5zu %4u %3zu %12zu %12\"PRIu64\n\t\t\t\t    \" %12\"PRIu64\" %12\"PRIu64\" %12\"PRIu64\n\t\t\t\t    \" %12\"PRIu64\" %12\"PRIu64\" %12\"PRIu64\n\t\t\t\t    \" %12zu\\n\",\n\t\t\t\t    j, reg_size, nregs, run_size / page,\n\t\t\t\t    allocated, nmalloc, ndalloc, nrequests,\n\t\t\t\t    nfills, nflushes, nruns, reruns, curruns);\n\t\t\t} else {\n\t\t\t\tmalloc_cprintf(write_cb, cbopaque,\n\t\t\t\t    \"%13u %5zu %4u %3zu %12zu %12\"PRIu64\n\t\t\t\t    \" %12\"PRIu64\" %12\"PRIu64\" %12\"PRIu64\n\t\t\t\t    \" %12zu\\n\",\n\t\t\t\t    j, reg_size, nregs, run_size / page,\n\t\t\t\t    allocated, nmalloc, ndalloc, nruns, reruns,\n\t\t\t\t    curruns);\n\t\t\t}\n\t\t}\n\t}\n\tif (gap_start != UINT_MAX) {\n\t\tif (j > gap_start + 1) {\n\t\t\t/* Gap of more than one size class. */\n\t\t\tmalloc_cprintf(write_cb, cbopaque, \"[%u..%u]\\n\",\n\t\t\t    gap_start, j - 1);\n\t\t} else {\n\t\t\t/* Gap of one size class. */\n\t\t\tmalloc_cprintf(write_cb, cbopaque, \"[%u]\\n\", gap_start);\n\t\t}\n\t}\n}\n\nstatic void\nstats_arena_lruns_print(void (*write_cb)(void *, const char *), void *cbopaque,\n    unsigned i)\n{\n\tsize_t page, nlruns, j;\n\tssize_t gap_start;\n\n\tCTL_GET(\"arenas.page\", &page, size_t);\n\n\tmalloc_cprintf(write_cb, cbopaque,\n\t    \"large:   size pages      nmalloc      ndalloc    nrequests\"\n\t    \"      curruns\\n\");\n\tCTL_GET(\"arenas.nlruns\", &nlruns, size_t);\n\tfor (j = 0, gap_start = -1; j < nlruns; j++) {\n\t\tuint64_t nmalloc, ndalloc, nrequests;\n\t\tsize_t run_size, curruns;\n\n\t\tCTL_IJ_GET(\"stats.arenas.0.lruns.0.nmalloc\", &nmalloc,\n\t\t    uint64_t);\n\t\tCTL_IJ_GET(\"stats.arenas.0.lruns.0.ndalloc\", &ndalloc,\n\t\t    uint64_t);\n\t\tCTL_IJ_GET(\"stats.arenas.0.lruns.0.nrequests\", &nrequests,\n\t\t    uint64_t);\n\t\tif (nrequests == 0) {\n\t\t\tif (gap_start == -1)\n\t\t\t\tgap_start = j;\n\t\t} else {\n\t\t\tCTL_J_GET(\"arenas.lrun.0.size\", &run_size, size_t);\n\t\t\tCTL_IJ_GET(\"stats.arenas.0.lruns.0.curruns\", &curruns,\n\t\t\t    size_t);\n\t\t\tif (gap_start != -1) {\n\t\t\t\tmalloc_cprintf(write_cb, cbopaque, \"[%zu]\\n\",\n\t\t\t\t    j - gap_start);\n\t\t\t\tgap_start = -1;\n\t\t\t}\n\t\t\tmalloc_cprintf(write_cb, cbopaque,\n\t\t\t    \"%13zu %5zu %12\"PRIu64\" %12\"PRIu64\" %12\"PRIu64\n\t\t\t    \" %12zu\\n\",\n\t\t\t    run_size, run_size / page, nmalloc, ndalloc,\n\t\t\t    nrequests, curruns);\n\t\t}\n\t}\n\tif (gap_start != -1)\n\t\tmalloc_cprintf(write_cb, cbopaque, \"[%zu]\\n\", j - gap_start);\n}\n\nstatic void\nstats_arena_print(void (*write_cb)(void *, const char *), void *cbopaque,\n    unsigned i, bool bins, bool large)\n{\n\tunsigned nthreads;\n\tconst char *dss;\n\tsize_t page, pactive, pdirty, mapped;\n\tuint64_t npurge, nmadvise, purged;\n\tsize_t small_allocated;\n\tuint64_t small_nmalloc, small_ndalloc, small_nrequests;\n\tsize_t large_allocated;\n\tuint64_t large_nmalloc, large_ndalloc, large_nrequests;\n\n\tCTL_GET(\"arenas.page\", &page, size_t);\n\n\tCTL_I_GET(\"stats.arenas.0.nthreads\", &nthreads, unsigned);\n\tmalloc_cprintf(write_cb, cbopaque,\n\t    \"assigned threads: %u\\n\", nthreads);\n\tCTL_I_GET(\"stats.arenas.0.dss\", &dss, const char *);\n\tmalloc_cprintf(write_cb, cbopaque, \"dss allocation precedence: %s\\n\",\n\t    dss);\n\tCTL_I_GET(\"stats.arenas.0.pactive\", &pactive, size_t);\n\tCTL_I_GET(\"stats.arenas.0.pdirty\", &pdirty, size_t);\n\tCTL_I_GET(\"stats.arenas.0.npurge\", &npurge, uint64_t);\n\tCTL_I_GET(\"stats.arenas.0.nmadvise\", &nmadvise, uint64_t);\n\tCTL_I_GET(\"stats.arenas.0.purged\", &purged, uint64_t);\n\tmalloc_cprintf(write_cb, cbopaque,\n\t    \"dirty pages: %zu:%zu active:dirty, %\"PRIu64\" sweep%s,\"\n\t    \" %\"PRIu64\" madvise%s, %\"PRIu64\" purged\\n\",\n\t    pactive, pdirty, npurge, npurge == 1 ? \"\" : \"s\",\n\t    nmadvise, nmadvise == 1 ? \"\" : \"s\", purged);\n\n\tmalloc_cprintf(write_cb, cbopaque,\n\t    \"            allocated      nmalloc      ndalloc    nrequests\\n\");\n\tCTL_I_GET(\"stats.arenas.0.small.allocated\", &small_allocated, size_t);\n\tCTL_I_GET(\"stats.arenas.0.small.nmalloc\", &small_nmalloc, uint64_t);\n\tCTL_I_GET(\"stats.arenas.0.small.ndalloc\", &small_ndalloc, uint64_t);\n\tCTL_I_GET(\"stats.arenas.0.small.nrequests\", &small_nrequests, uint64_t);\n\tmalloc_cprintf(write_cb, cbopaque,\n\t    \"small:   %12zu %12\"PRIu64\" %12\"PRIu64\" %12\"PRIu64\"\\n\",\n\t    small_allocated, small_nmalloc, small_ndalloc, small_nrequests);\n\tCTL_I_GET(\"stats.arenas.0.large.allocated\", &large_allocated, size_t);\n\tCTL_I_GET(\"stats.arenas.0.large.nmalloc\", &large_nmalloc, uint64_t);\n\tCTL_I_GET(\"stats.arenas.0.large.ndalloc\", &large_ndalloc, uint64_t);\n\tCTL_I_GET(\"stats.arenas.0.large.nrequests\", &large_nrequests, uint64_t);\n\tmalloc_cprintf(write_cb, cbopaque,\n\t    \"large:   %12zu %12\"PRIu64\" %12\"PRIu64\" %12\"PRIu64\"\\n\",\n\t    large_allocated, large_nmalloc, large_ndalloc, large_nrequests);\n\tmalloc_cprintf(write_cb, cbopaque,\n\t    \"total:   %12zu %12\"PRIu64\" %12\"PRIu64\" %12\"PRIu64\"\\n\",\n\t    small_allocated + large_allocated,\n\t    small_nmalloc + large_nmalloc,\n\t    small_ndalloc + large_ndalloc,\n\t    small_nrequests + large_nrequests);\n\tmalloc_cprintf(write_cb, cbopaque, \"active:  %12zu\\n\", pactive * page);\n\tCTL_I_GET(\"stats.arenas.0.mapped\", &mapped, size_t);\n\tmalloc_cprintf(write_cb, cbopaque, \"mapped:  %12zu\\n\", mapped);\n\n\tif (bins)\n\t\tstats_arena_bins_print(write_cb, cbopaque, i);\n\tif (large)\n\t\tstats_arena_lruns_print(write_cb, cbopaque, i);\n}\n\nvoid\nstats_print(void (*write_cb)(void *, const char *), void *cbopaque,\n    const char *opts)\n{\n\tint err;\n\tuint64_t epoch;\n\tsize_t u64sz;\n\tbool general = true;\n\tbool merged = true;\n\tbool unmerged = true;\n\tbool bins = true;\n\tbool large = true;\n\n\t/*\n\t * Refresh stats, in case mallctl() was called by the application.\n\t *\n\t * Check for OOM here, since refreshing the ctl cache can trigger\n\t * allocation.  In practice, none of the subsequent mallctl()-related\n\t * calls in this function will cause OOM if this one succeeds.\n\t * */\n\tepoch = 1;\n\tu64sz = sizeof(uint64_t);\n\terr = je_mallctl(\"epoch\", &epoch, &u64sz, &epoch, sizeof(uint64_t));\n\tif (err != 0) {\n\t\tif (err == EAGAIN) {\n\t\t\tmalloc_write(\"<jemalloc>: Memory allocation failure in \"\n\t\t\t    \"mallctl(\\\"epoch\\\", ...)\\n\");\n\t\t\treturn;\n\t\t}\n\t\tmalloc_write(\"<jemalloc>: Failure in mallctl(\\\"epoch\\\", \"\n\t\t    \"...)\\n\");\n\t\tabort();\n\t}\n\n\tif (opts != NULL) {\n\t\tunsigned i;\n\n\t\tfor (i = 0; opts[i] != '\\0'; i++) {\n\t\t\tswitch (opts[i]) {\n\t\t\tcase 'g':\n\t\t\t\tgeneral = false;\n\t\t\t\tbreak;\n\t\t\tcase 'm':\n\t\t\t\tmerged = false;\n\t\t\t\tbreak;\n\t\t\tcase 'a':\n\t\t\t\tunmerged = false;\n\t\t\t\tbreak;\n\t\t\tcase 'b':\n\t\t\t\tbins = false;\n\t\t\t\tbreak;\n\t\t\tcase 'l':\n\t\t\t\tlarge = false;\n\t\t\t\tbreak;\n\t\t\tdefault:;\n\t\t\t}\n\t\t}\n\t}\n\n\tmalloc_cprintf(write_cb, cbopaque,\n\t    \"___ Begin jemalloc statistics ___\\n\");\n\tif (general) {\n\t\tint err;\n\t\tconst char *cpv;\n\t\tbool bv;\n\t\tunsigned uv;\n\t\tssize_t ssv;\n\t\tsize_t sv, bsz, ssz, sssz, cpsz;\n\n\t\tbsz = sizeof(bool);\n\t\tssz = sizeof(size_t);\n\t\tsssz = sizeof(ssize_t);\n\t\tcpsz = sizeof(const char *);\n\n\t\tCTL_GET(\"version\", &cpv, const char *);\n\t\tmalloc_cprintf(write_cb, cbopaque, \"Version: %s\\n\", cpv);\n\t\tCTL_GET(\"config.debug\", &bv, bool);\n\t\tmalloc_cprintf(write_cb, cbopaque, \"Assertions %s\\n\",\n\t\t    bv ? \"enabled\" : \"disabled\");\n\n#define\tOPT_WRITE_BOOL(n)\t\t\t\t\t\t\\\n\t\tif ((err = je_mallctl(\"opt.\"#n, &bv, &bsz, NULL, 0))\t\\\n\t\t    == 0) {\t\t\t\t\t\t\\\n\t\t\tmalloc_cprintf(write_cb, cbopaque,\t\t\\\n\t\t\t    \"  opt.\"#n\": %s\\n\", bv ? \"true\" : \"false\");\t\\\n\t\t}\n#define\tOPT_WRITE_SIZE_T(n)\t\t\t\t\t\t\\\n\t\tif ((err = je_mallctl(\"opt.\"#n, &sv, &ssz, NULL, 0))\t\\\n\t\t    == 0) {\t\t\t\t\t\t\\\n\t\t\tmalloc_cprintf(write_cb, cbopaque,\t\t\\\n\t\t\t\"  opt.\"#n\": %zu\\n\", sv);\t\t\t\\\n\t\t}\n#define\tOPT_WRITE_SSIZE_T(n)\t\t\t\t\t\t\\\n\t\tif ((err = je_mallctl(\"opt.\"#n, &ssv, &sssz, NULL, 0))\t\\\n\t\t    == 0) {\t\t\t\t\t\t\\\n\t\t\tmalloc_cprintf(write_cb, cbopaque,\t\t\\\n\t\t\t    \"  opt.\"#n\": %zd\\n\", ssv);\t\t\t\\\n\t\t}\n#define\tOPT_WRITE_CHAR_P(n)\t\t\t\t\t\t\\\n\t\tif ((err = je_mallctl(\"opt.\"#n, &cpv, &cpsz, NULL, 0))\t\\\n\t\t    == 0) {\t\t\t\t\t\t\\\n\t\t\tmalloc_cprintf(write_cb, cbopaque,\t\t\\\n\t\t\t    \"  opt.\"#n\": \\\"%s\\\"\\n\", cpv);\t\t\\\n\t\t}\n\n\t\tmalloc_cprintf(write_cb, cbopaque,\n\t\t    \"Run-time option settings:\\n\");\n\t\tOPT_WRITE_BOOL(abort)\n\t\tOPT_WRITE_SIZE_T(lg_chunk)\n\t\tOPT_WRITE_CHAR_P(dss)\n\t\tOPT_WRITE_SIZE_T(narenas)\n\t\tOPT_WRITE_SSIZE_T(lg_dirty_mult)\n\t\tOPT_WRITE_BOOL(stats_print)\n\t\tOPT_WRITE_BOOL(junk)\n\t\tOPT_WRITE_SIZE_T(quarantine)\n\t\tOPT_WRITE_BOOL(redzone)\n\t\tOPT_WRITE_BOOL(zero)\n\t\tOPT_WRITE_BOOL(utrace)\n\t\tOPT_WRITE_BOOL(valgrind)\n\t\tOPT_WRITE_BOOL(xmalloc)\n\t\tOPT_WRITE_BOOL(tcache)\n\t\tOPT_WRITE_SSIZE_T(lg_tcache_max)\n\t\tOPT_WRITE_BOOL(prof)\n\t\tOPT_WRITE_CHAR_P(prof_prefix)\n\t\tOPT_WRITE_BOOL(prof_active)\n\t\tOPT_WRITE_SSIZE_T(lg_prof_sample)\n\t\tOPT_WRITE_BOOL(prof_accum)\n\t\tOPT_WRITE_SSIZE_T(lg_prof_interval)\n\t\tOPT_WRITE_BOOL(prof_gdump)\n\t\tOPT_WRITE_BOOL(prof_final)\n\t\tOPT_WRITE_BOOL(prof_leak)\n\n#undef OPT_WRITE_BOOL\n#undef OPT_WRITE_SIZE_T\n#undef OPT_WRITE_SSIZE_T\n#undef OPT_WRITE_CHAR_P\n\n\t\tmalloc_cprintf(write_cb, cbopaque, \"CPUs: %u\\n\", ncpus);\n\n\t\tCTL_GET(\"arenas.narenas\", &uv, unsigned);\n\t\tmalloc_cprintf(write_cb, cbopaque, \"Arenas: %u\\n\", uv);\n\n\t\tmalloc_cprintf(write_cb, cbopaque, \"Pointer size: %zu\\n\",\n\t\t    sizeof(void *));\n\n\t\tCTL_GET(\"arenas.quantum\", &sv, size_t);\n\t\tmalloc_cprintf(write_cb, cbopaque, \"Quantum size: %zu\\n\", sv);\n\n\t\tCTL_GET(\"arenas.page\", &sv, size_t);\n\t\tmalloc_cprintf(write_cb, cbopaque, \"Page size: %zu\\n\", sv);\n\n\t\tCTL_GET(\"opt.lg_dirty_mult\", &ssv, ssize_t);\n\t\tif (ssv >= 0) {\n\t\t\tmalloc_cprintf(write_cb, cbopaque,\n\t\t\t    \"Min active:dirty page ratio per arena: %u:1\\n\",\n\t\t\t    (1U << ssv));\n\t\t} else {\n\t\t\tmalloc_cprintf(write_cb, cbopaque,\n\t\t\t    \"Min active:dirty page ratio per arena: N/A\\n\");\n\t\t}\n\t\tif ((err = je_mallctl(\"arenas.tcache_max\", &sv, &ssz, NULL, 0))\n\t\t    == 0) {\n\t\t\tmalloc_cprintf(write_cb, cbopaque,\n\t\t\t    \"Maximum thread-cached size class: %zu\\n\", sv);\n\t\t}\n\t\tif ((err = je_mallctl(\"opt.prof\", &bv, &bsz, NULL, 0)) == 0 &&\n\t\t    bv) {\n\t\t\tCTL_GET(\"opt.lg_prof_sample\", &sv, size_t);\n\t\t\tmalloc_cprintf(write_cb, cbopaque,\n\t\t\t    \"Average profile sample interval: %\"PRIu64\n\t\t\t    \" (2^%zu)\\n\", (((uint64_t)1U) << sv), sv);\n\n\t\t\tCTL_GET(\"opt.lg_prof_interval\", &ssv, ssize_t);\n\t\t\tif (ssv >= 0) {\n\t\t\t\tmalloc_cprintf(write_cb, cbopaque,\n\t\t\t\t    \"Average profile dump interval: %\"PRIu64\n\t\t\t\t    \" (2^%zd)\\n\",\n\t\t\t\t    (((uint64_t)1U) << ssv), ssv);\n\t\t\t} else {\n\t\t\t\tmalloc_cprintf(write_cb, cbopaque,\n\t\t\t\t    \"Average profile dump interval: N/A\\n\");\n\t\t\t}\n\t\t}\n\t\tCTL_GET(\"opt.lg_chunk\", &sv, size_t);\n\t\tmalloc_cprintf(write_cb, cbopaque, \"Chunk size: %zu (2^%zu)\\n\",\n\t\t    (ZU(1) << sv), sv);\n\t}\n\n\tif (config_stats) {\n\t\tsize_t *cactive;\n\t\tsize_t allocated, active, mapped;\n\t\tsize_t chunks_current, chunks_high;\n\t\tuint64_t chunks_total;\n\t\tsize_t huge_allocated;\n\t\tuint64_t huge_nmalloc, huge_ndalloc;\n\n\t\tCTL_GET(\"stats.cactive\", &cactive, size_t *);\n\t\tCTL_GET(\"stats.allocated\", &allocated, size_t);\n\t\tCTL_GET(\"stats.active\", &active, size_t);\n\t\tCTL_GET(\"stats.mapped\", &mapped, size_t);\n\t\tmalloc_cprintf(write_cb, cbopaque,\n\t\t    \"Allocated: %zu, active: %zu, mapped: %zu\\n\",\n\t\t    allocated, active, mapped);\n\t\tmalloc_cprintf(write_cb, cbopaque,\n\t\t    \"Current active ceiling: %zu\\n\", atomic_read_z(cactive));\n\n\t\t/* Print chunk stats. */\n\t\tCTL_GET(\"stats.chunks.total\", &chunks_total, uint64_t);\n\t\tCTL_GET(\"stats.chunks.high\", &chunks_high, size_t);\n\t\tCTL_GET(\"stats.chunks.current\", &chunks_current, size_t);\n\t\tmalloc_cprintf(write_cb, cbopaque, \"chunks: nchunks   \"\n\t\t    \"highchunks    curchunks\\n\");\n\t\tmalloc_cprintf(write_cb, cbopaque,\n\t\t    \"  %13\"PRIu64\" %12zu %12zu\\n\",\n\t\t    chunks_total, chunks_high, chunks_current);\n\n\t\t/* Print huge stats. */\n\t\tCTL_GET(\"stats.huge.nmalloc\", &huge_nmalloc, uint64_t);\n\t\tCTL_GET(\"stats.huge.ndalloc\", &huge_ndalloc, uint64_t);\n\t\tCTL_GET(\"stats.huge.allocated\", &huge_allocated, size_t);\n\t\tmalloc_cprintf(write_cb, cbopaque,\n\t\t    \"huge: nmalloc      ndalloc    allocated\\n\");\n\t\tmalloc_cprintf(write_cb, cbopaque,\n\t\t    \" %12\"PRIu64\" %12\"PRIu64\" %12zu\\n\",\n\t\t    huge_nmalloc, huge_ndalloc, huge_allocated);\n\n\t\tif (merged) {\n\t\t\tunsigned narenas;\n\n\t\t\tCTL_GET(\"arenas.narenas\", &narenas, unsigned);\n\t\t\t{\n\t\t\t\tVARIABLE_ARRAY(bool, initialized, narenas);\n\t\t\t\tsize_t isz;\n\t\t\t\tunsigned i, ninitialized;\n\n\t\t\t\tisz = sizeof(bool) * narenas;\n\t\t\t\txmallctl(\"arenas.initialized\", initialized,\n\t\t\t\t    &isz, NULL, 0);\n\t\t\t\tfor (i = ninitialized = 0; i < narenas; i++) {\n\t\t\t\t\tif (initialized[i])\n\t\t\t\t\t\tninitialized++;\n\t\t\t\t}\n\n\t\t\t\tif (ninitialized > 1 || unmerged == false) {\n\t\t\t\t\t/* Print merged arena stats. */\n\t\t\t\t\tmalloc_cprintf(write_cb, cbopaque,\n\t\t\t\t\t    \"\\nMerged arenas stats:\\n\");\n\t\t\t\t\tstats_arena_print(write_cb, cbopaque,\n\t\t\t\t\t    narenas, bins, large);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tif (unmerged) {\n\t\t\tunsigned narenas;\n\n\t\t\t/* Print stats for each arena. */\n\n\t\t\tCTL_GET(\"arenas.narenas\", &narenas, unsigned);\n\t\t\t{\n\t\t\t\tVARIABLE_ARRAY(bool, initialized, narenas);\n\t\t\t\tsize_t isz;\n\t\t\t\tunsigned i;\n\n\t\t\t\tisz = sizeof(bool) * narenas;\n\t\t\t\txmallctl(\"arenas.initialized\", initialized,\n\t\t\t\t    &isz, NULL, 0);\n\n\t\t\t\tfor (i = 0; i < narenas; i++) {\n\t\t\t\t\tif (initialized[i]) {\n\t\t\t\t\t\tmalloc_cprintf(write_cb,\n\t\t\t\t\t\t    cbopaque,\n\t\t\t\t\t\t    \"\\narenas[%u]:\\n\", i);\n\t\t\t\t\t\tstats_arena_print(write_cb,\n\t\t\t\t\t\t    cbopaque, i, bins, large);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\tmalloc_cprintf(write_cb, cbopaque, \"--- End jemalloc statistics ---\\n\");\n}\n"
  },
  {
    "path": "extern/deprecated/redis-2.8.21/deps/jemalloc/src/tcache.c",
    "content": "#define\tJEMALLOC_TCACHE_C_\n#include \"jemalloc/internal/jemalloc_internal.h\"\n\n/******************************************************************************/\n/* Data. */\n\nmalloc_tsd_data(, tcache, tcache_t *, NULL)\nmalloc_tsd_data(, tcache_enabled, tcache_enabled_t, tcache_enabled_default)\n\nbool\topt_tcache = true;\nssize_t\topt_lg_tcache_max = LG_TCACHE_MAXCLASS_DEFAULT;\n\ntcache_bin_info_t\t*tcache_bin_info;\nstatic unsigned\t\tstack_nelms; /* Total stack elms per tcache. */\n\nsize_t\t\t\tnhbins;\nsize_t\t\t\ttcache_maxclass;\n\n/******************************************************************************/\n\nsize_t\ttcache_salloc(const void *ptr)\n{\n\n\treturn (arena_salloc(ptr, false));\n}\n\nvoid\ntcache_event_hard(tcache_t *tcache)\n{\n\tsize_t binind = tcache->next_gc_bin;\n\ttcache_bin_t *tbin = &tcache->tbins[binind];\n\ttcache_bin_info_t *tbin_info = &tcache_bin_info[binind];\n\n\tif (tbin->low_water > 0) {\n\t\t/*\n\t\t * Flush (ceiling) 3/4 of the objects below the low water mark.\n\t\t */\n\t\tif (binind < NBINS) {\n\t\t\ttcache_bin_flush_small(tbin, binind, tbin->ncached -\n\t\t\t    tbin->low_water + (tbin->low_water >> 2), tcache);\n\t\t} else {\n\t\t\ttcache_bin_flush_large(tbin, binind, tbin->ncached -\n\t\t\t    tbin->low_water + (tbin->low_water >> 2), tcache);\n\t\t}\n\t\t/*\n\t\t * Reduce fill count by 2X.  Limit lg_fill_div such that the\n\t\t * fill count is always at least 1.\n\t\t */\n\t\tif ((tbin_info->ncached_max >> (tbin->lg_fill_div+1)) >= 1)\n\t\t\ttbin->lg_fill_div++;\n\t} else if (tbin->low_water < 0) {\n\t\t/*\n\t\t * Increase fill count by 2X.  Make sure lg_fill_div stays\n\t\t * greater than 0.\n\t\t */\n\t\tif (tbin->lg_fill_div > 1)\n\t\t\ttbin->lg_fill_div--;\n\t}\n\ttbin->low_water = tbin->ncached;\n\n\ttcache->next_gc_bin++;\n\tif (tcache->next_gc_bin == nhbins)\n\t\ttcache->next_gc_bin = 0;\n\ttcache->ev_cnt = 0;\n}\n\nvoid *\ntcache_alloc_small_hard(tcache_t *tcache, tcache_bin_t *tbin, size_t binind)\n{\n\tvoid *ret;\n\n\tarena_tcache_fill_small(tcache->arena, tbin, binind,\n\t    config_prof ? tcache->prof_accumbytes : 0);\n\tif (config_prof)\n\t\ttcache->prof_accumbytes = 0;\n\tret = tcache_alloc_easy(tbin);\n\n\treturn (ret);\n}\n\nvoid\ntcache_bin_flush_small(tcache_bin_t *tbin, size_t binind, unsigned rem,\n    tcache_t *tcache)\n{\n\tvoid *ptr;\n\tunsigned i, nflush, ndeferred;\n\tbool merged_stats = false;\n\n\tassert(binind < NBINS);\n\tassert(rem <= tbin->ncached);\n\n\tfor (nflush = tbin->ncached - rem; nflush > 0; nflush = ndeferred) {\n\t\t/* Lock the arena bin associated with the first object. */\n\t\tarena_chunk_t *chunk = (arena_chunk_t *)CHUNK_ADDR2BASE(\n\t\t    tbin->avail[0]);\n\t\tarena_t *arena = chunk->arena;\n\t\tarena_bin_t *bin = &arena->bins[binind];\n\n\t\tif (config_prof && arena == tcache->arena) {\n\t\t\tif (arena_prof_accum(arena, tcache->prof_accumbytes))\n\t\t\t\tprof_idump();\n\t\t\ttcache->prof_accumbytes = 0;\n\t\t}\n\n\t\tmalloc_mutex_lock(&bin->lock);\n\t\tif (config_stats && arena == tcache->arena) {\n\t\t\tassert(merged_stats == false);\n\t\t\tmerged_stats = true;\n\t\t\tbin->stats.nflushes++;\n\t\t\tbin->stats.nrequests += tbin->tstats.nrequests;\n\t\t\ttbin->tstats.nrequests = 0;\n\t\t}\n\t\tndeferred = 0;\n\t\tfor (i = 0; i < nflush; i++) {\n\t\t\tptr = tbin->avail[i];\n\t\t\tassert(ptr != NULL);\n\t\t\tchunk = (arena_chunk_t *)CHUNK_ADDR2BASE(ptr);\n\t\t\tif (chunk->arena == arena) {\n\t\t\t\tsize_t pageind = ((uintptr_t)ptr -\n\t\t\t\t    (uintptr_t)chunk) >> LG_PAGE;\n\t\t\t\tarena_chunk_map_t *mapelm =\n\t\t\t\t    arena_mapp_get(chunk, pageind);\n\t\t\t\tif (config_fill && opt_junk) {\n\t\t\t\t\tarena_alloc_junk_small(ptr,\n\t\t\t\t\t    &arena_bin_info[binind], true);\n\t\t\t\t}\n\t\t\t\tarena_dalloc_bin_locked(arena, chunk, ptr,\n\t\t\t\t    mapelm);\n\t\t\t} else {\n\t\t\t\t/*\n\t\t\t\t * This object was allocated via a different\n\t\t\t\t * arena bin than the one that is currently\n\t\t\t\t * locked.  Stash the object, so that it can be\n\t\t\t\t * handled in a future pass.\n\t\t\t\t */\n\t\t\t\ttbin->avail[ndeferred] = ptr;\n\t\t\t\tndeferred++;\n\t\t\t}\n\t\t}\n\t\tmalloc_mutex_unlock(&bin->lock);\n\t}\n\tif (config_stats && merged_stats == false) {\n\t\t/*\n\t\t * The flush loop didn't happen to flush to this thread's\n\t\t * arena, so the stats didn't get merged.  Manually do so now.\n\t\t */\n\t\tarena_bin_t *bin = &tcache->arena->bins[binind];\n\t\tmalloc_mutex_lock(&bin->lock);\n\t\tbin->stats.nflushes++;\n\t\tbin->stats.nrequests += tbin->tstats.nrequests;\n\t\ttbin->tstats.nrequests = 0;\n\t\tmalloc_mutex_unlock(&bin->lock);\n\t}\n\n\tmemmove(tbin->avail, &tbin->avail[tbin->ncached - rem],\n\t    rem * sizeof(void *));\n\ttbin->ncached = rem;\n\tif ((int)tbin->ncached < tbin->low_water)\n\t\ttbin->low_water = tbin->ncached;\n}\n\nvoid\ntcache_bin_flush_large(tcache_bin_t *tbin, size_t binind, unsigned rem,\n    tcache_t *tcache)\n{\n\tvoid *ptr;\n\tunsigned i, nflush, ndeferred;\n\tbool merged_stats = false;\n\n\tassert(binind < nhbins);\n\tassert(rem <= tbin->ncached);\n\n\tfor (nflush = tbin->ncached - rem; nflush > 0; nflush = ndeferred) {\n\t\t/* Lock the arena associated with the first object. */\n\t\tarena_chunk_t *chunk = (arena_chunk_t *)CHUNK_ADDR2BASE(\n\t\t    tbin->avail[0]);\n\t\tarena_t *arena = chunk->arena;\n\t\tUNUSED bool idump;\n\n\t\tif (config_prof)\n\t\t\tidump = false;\n\t\tmalloc_mutex_lock(&arena->lock);\n\t\tif ((config_prof || config_stats) && arena == tcache->arena) {\n\t\t\tif (config_prof) {\n\t\t\t\tidump = arena_prof_accum_locked(arena,\n\t\t\t\t    tcache->prof_accumbytes);\n\t\t\t\ttcache->prof_accumbytes = 0;\n\t\t\t}\n\t\t\tif (config_stats) {\n\t\t\t\tmerged_stats = true;\n\t\t\t\tarena->stats.nrequests_large +=\n\t\t\t\t    tbin->tstats.nrequests;\n\t\t\t\tarena->stats.lstats[binind - NBINS].nrequests +=\n\t\t\t\t    tbin->tstats.nrequests;\n\t\t\t\ttbin->tstats.nrequests = 0;\n\t\t\t}\n\t\t}\n\t\tndeferred = 0;\n\t\tfor (i = 0; i < nflush; i++) {\n\t\t\tptr = tbin->avail[i];\n\t\t\tassert(ptr != NULL);\n\t\t\tchunk = (arena_chunk_t *)CHUNK_ADDR2BASE(ptr);\n\t\t\tif (chunk->arena == arena)\n\t\t\t\tarena_dalloc_large_locked(arena, chunk, ptr);\n\t\t\telse {\n\t\t\t\t/*\n\t\t\t\t * This object was allocated via a different\n\t\t\t\t * arena than the one that is currently locked.\n\t\t\t\t * Stash the object, so that it can be handled\n\t\t\t\t * in a future pass.\n\t\t\t\t */\n\t\t\t\ttbin->avail[ndeferred] = ptr;\n\t\t\t\tndeferred++;\n\t\t\t}\n\t\t}\n\t\tmalloc_mutex_unlock(&arena->lock);\n\t\tif (config_prof && idump)\n\t\t\tprof_idump();\n\t}\n\tif (config_stats && merged_stats == false) {\n\t\t/*\n\t\t * The flush loop didn't happen to flush to this thread's\n\t\t * arena, so the stats didn't get merged.  Manually do so now.\n\t\t */\n\t\tarena_t *arena = tcache->arena;\n\t\tmalloc_mutex_lock(&arena->lock);\n\t\tarena->stats.nrequests_large += tbin->tstats.nrequests;\n\t\tarena->stats.lstats[binind - NBINS].nrequests +=\n\t\t    tbin->tstats.nrequests;\n\t\ttbin->tstats.nrequests = 0;\n\t\tmalloc_mutex_unlock(&arena->lock);\n\t}\n\n\tmemmove(tbin->avail, &tbin->avail[tbin->ncached - rem],\n\t    rem * sizeof(void *));\n\ttbin->ncached = rem;\n\tif ((int)tbin->ncached < tbin->low_water)\n\t\ttbin->low_water = tbin->ncached;\n}\n\nvoid\ntcache_arena_associate(tcache_t *tcache, arena_t *arena)\n{\n\n\tif (config_stats) {\n\t\t/* Link into list of extant tcaches. */\n\t\tmalloc_mutex_lock(&arena->lock);\n\t\tql_elm_new(tcache, link);\n\t\tql_tail_insert(&arena->tcache_ql, tcache, link);\n\t\tmalloc_mutex_unlock(&arena->lock);\n\t}\n\ttcache->arena = arena;\n}\n\nvoid\ntcache_arena_dissociate(tcache_t *tcache)\n{\n\n\tif (config_stats) {\n\t\t/* Unlink from list of extant tcaches. */\n\t\tmalloc_mutex_lock(&tcache->arena->lock);\n\t\tql_remove(&tcache->arena->tcache_ql, tcache, link);\n\t\ttcache_stats_merge(tcache, tcache->arena);\n\t\tmalloc_mutex_unlock(&tcache->arena->lock);\n\t}\n}\n\ntcache_t *\ntcache_create(arena_t *arena)\n{\n\ttcache_t *tcache;\n\tsize_t size, stack_offset;\n\tunsigned i;\n\n\tsize = offsetof(tcache_t, tbins) + (sizeof(tcache_bin_t) * nhbins);\n\t/* Naturally align the pointer stacks. */\n\tsize = PTR_CEILING(size);\n\tstack_offset = size;\n\tsize += stack_nelms * sizeof(void *);\n\t/*\n\t * Round up to the nearest multiple of the cacheline size, in order to\n\t * avoid the possibility of false cacheline sharing.\n\t *\n\t * That this works relies on the same logic as in ipalloc(), but we\n\t * cannot directly call ipalloc() here due to tcache bootstrapping\n\t * issues.\n\t */\n\tsize = (size + CACHELINE_MASK) & (-CACHELINE);\n\n\tif (size <= SMALL_MAXCLASS)\n\t\ttcache = (tcache_t *)arena_malloc_small(arena, size, true);\n\telse if (size <= tcache_maxclass)\n\t\ttcache = (tcache_t *)arena_malloc_large(arena, size, true);\n\telse\n\t\ttcache = (tcache_t *)icalloct(size, false, arena);\n\n\tif (tcache == NULL)\n\t\treturn (NULL);\n\n\ttcache_arena_associate(tcache, arena);\n\n\tassert((TCACHE_NSLOTS_SMALL_MAX & 1U) == 0);\n\tfor (i = 0; i < nhbins; i++) {\n\t\ttcache->tbins[i].lg_fill_div = 1;\n\t\ttcache->tbins[i].avail = (void **)((uintptr_t)tcache +\n\t\t    (uintptr_t)stack_offset);\n\t\tstack_offset += tcache_bin_info[i].ncached_max * sizeof(void *);\n\t}\n\n\ttcache_tsd_set(&tcache);\n\n\treturn (tcache);\n}\n\nvoid\ntcache_destroy(tcache_t *tcache)\n{\n\tunsigned i;\n\tsize_t tcache_size;\n\n\ttcache_arena_dissociate(tcache);\n\n\tfor (i = 0; i < NBINS; i++) {\n\t\ttcache_bin_t *tbin = &tcache->tbins[i];\n\t\ttcache_bin_flush_small(tbin, i, 0, tcache);\n\n\t\tif (config_stats && tbin->tstats.nrequests != 0) {\n\t\t\tarena_t *arena = tcache->arena;\n\t\t\tarena_bin_t *bin = &arena->bins[i];\n\t\t\tmalloc_mutex_lock(&bin->lock);\n\t\t\tbin->stats.nrequests += tbin->tstats.nrequests;\n\t\t\tmalloc_mutex_unlock(&bin->lock);\n\t\t}\n\t}\n\n\tfor (; i < nhbins; i++) {\n\t\ttcache_bin_t *tbin = &tcache->tbins[i];\n\t\ttcache_bin_flush_large(tbin, i, 0, tcache);\n\n\t\tif (config_stats && tbin->tstats.nrequests != 0) {\n\t\t\tarena_t *arena = tcache->arena;\n\t\t\tmalloc_mutex_lock(&arena->lock);\n\t\t\tarena->stats.nrequests_large += tbin->tstats.nrequests;\n\t\t\tarena->stats.lstats[i - NBINS].nrequests +=\n\t\t\t    tbin->tstats.nrequests;\n\t\t\tmalloc_mutex_unlock(&arena->lock);\n\t\t}\n\t}\n\n\tif (config_prof && tcache->prof_accumbytes > 0 &&\n\t    arena_prof_accum(tcache->arena, tcache->prof_accumbytes))\n\t\tprof_idump();\n\n\ttcache_size = arena_salloc(tcache, false);\n\tif (tcache_size <= SMALL_MAXCLASS) {\n\t\tarena_chunk_t *chunk = CHUNK_ADDR2BASE(tcache);\n\t\tarena_t *arena = chunk->arena;\n\t\tsize_t pageind = ((uintptr_t)tcache - (uintptr_t)chunk) >>\n\t\t    LG_PAGE;\n\t\tarena_chunk_map_t *mapelm = arena_mapp_get(chunk, pageind);\n\n\t\tarena_dalloc_bin(arena, chunk, tcache, pageind, mapelm);\n\t} else if (tcache_size <= tcache_maxclass) {\n\t\tarena_chunk_t *chunk = CHUNK_ADDR2BASE(tcache);\n\t\tarena_t *arena = chunk->arena;\n\n\t\tarena_dalloc_large(arena, chunk, tcache);\n\t} else\n\t\tidalloct(tcache, false);\n}\n\nvoid\ntcache_thread_cleanup(void *arg)\n{\n\ttcache_t *tcache = *(tcache_t **)arg;\n\n\tif (tcache == TCACHE_STATE_DISABLED) {\n\t\t/* Do nothing. */\n\t} else if (tcache == TCACHE_STATE_REINCARNATED) {\n\t\t/*\n\t\t * Another destructor called an allocator function after this\n\t\t * destructor was called.  Reset tcache to\n\t\t * TCACHE_STATE_PURGATORY in order to receive another callback.\n\t\t */\n\t\ttcache = TCACHE_STATE_PURGATORY;\n\t\ttcache_tsd_set(&tcache);\n\t} else if (tcache == TCACHE_STATE_PURGATORY) {\n\t\t/*\n\t\t * The previous time this destructor was called, we set the key\n\t\t * to TCACHE_STATE_PURGATORY so that other destructors wouldn't\n\t\t * cause re-creation of the tcache.  This time, do nothing, so\n\t\t * that the destructor will not be called again.\n\t\t */\n\t} else if (tcache != NULL) {\n\t\tassert(tcache != TCACHE_STATE_PURGATORY);\n\t\ttcache_destroy(tcache);\n\t\ttcache = TCACHE_STATE_PURGATORY;\n\t\ttcache_tsd_set(&tcache);\n\t}\n}\n\n/* Caller must own arena->lock. */\nvoid\ntcache_stats_merge(tcache_t *tcache, arena_t *arena)\n{\n\tunsigned i;\n\n\tcassert(config_stats);\n\n\t/* Merge and reset tcache stats. */\n\tfor (i = 0; i < NBINS; i++) {\n\t\tarena_bin_t *bin = &arena->bins[i];\n\t\ttcache_bin_t *tbin = &tcache->tbins[i];\n\t\tmalloc_mutex_lock(&bin->lock);\n\t\tbin->stats.nrequests += tbin->tstats.nrequests;\n\t\tmalloc_mutex_unlock(&bin->lock);\n\t\ttbin->tstats.nrequests = 0;\n\t}\n\n\tfor (; i < nhbins; i++) {\n\t\tmalloc_large_stats_t *lstats = &arena->stats.lstats[i - NBINS];\n\t\ttcache_bin_t *tbin = &tcache->tbins[i];\n\t\tarena->stats.nrequests_large += tbin->tstats.nrequests;\n\t\tlstats->nrequests += tbin->tstats.nrequests;\n\t\ttbin->tstats.nrequests = 0;\n\t}\n}\n\nbool\ntcache_boot0(void)\n{\n\tunsigned i;\n\n\t/*\n\t * If necessary, clamp opt_lg_tcache_max, now that arena_maxclass is\n\t * known.\n\t */\n\tif (opt_lg_tcache_max < 0 || (1U << opt_lg_tcache_max) < SMALL_MAXCLASS)\n\t\ttcache_maxclass = SMALL_MAXCLASS;\n\telse if ((1U << opt_lg_tcache_max) > arena_maxclass)\n\t\ttcache_maxclass = arena_maxclass;\n\telse\n\t\ttcache_maxclass = (1U << opt_lg_tcache_max);\n\n\tnhbins = NBINS + (tcache_maxclass >> LG_PAGE);\n\n\t/* Initialize tcache_bin_info. */\n\ttcache_bin_info = (tcache_bin_info_t *)base_alloc(nhbins *\n\t    sizeof(tcache_bin_info_t));\n\tif (tcache_bin_info == NULL)\n\t\treturn (true);\n\tstack_nelms = 0;\n\tfor (i = 0; i < NBINS; i++) {\n\t\tif ((arena_bin_info[i].nregs << 1) <= TCACHE_NSLOTS_SMALL_MAX) {\n\t\t\ttcache_bin_info[i].ncached_max =\n\t\t\t    (arena_bin_info[i].nregs << 1);\n\t\t} else {\n\t\t\ttcache_bin_info[i].ncached_max =\n\t\t\t    TCACHE_NSLOTS_SMALL_MAX;\n\t\t}\n\t\tstack_nelms += tcache_bin_info[i].ncached_max;\n\t}\n\tfor (; i < nhbins; i++) {\n\t\ttcache_bin_info[i].ncached_max = TCACHE_NSLOTS_LARGE;\n\t\tstack_nelms += tcache_bin_info[i].ncached_max;\n\t}\n\n\treturn (false);\n}\n\nbool\ntcache_boot1(void)\n{\n\n\tif (tcache_tsd_boot() || tcache_enabled_tsd_boot())\n\t\treturn (true);\n\n\treturn (false);\n}\n"
  },
  {
    "path": "extern/deprecated/redis-2.8.21/deps/jemalloc/src/tsd.c",
    "content": "#define\tJEMALLOC_TSD_C_\n#include \"jemalloc/internal/jemalloc_internal.h\"\n\n/******************************************************************************/\n/* Data. */\n\nstatic unsigned ncleanups;\nstatic malloc_tsd_cleanup_t cleanups[MALLOC_TSD_CLEANUPS_MAX];\n\n/******************************************************************************/\n\nvoid *\nmalloc_tsd_malloc(size_t size)\n{\n\n\t/* Avoid choose_arena() in order to dodge bootstrapping issues. */\n\treturn (arena_malloc(arenas[0], size, false, false));\n}\n\nvoid\nmalloc_tsd_dalloc(void *wrapper)\n{\n\n\tidalloct(wrapper, false);\n}\n\nvoid\nmalloc_tsd_no_cleanup(void *arg)\n{\n\n\tnot_reached();\n}\n\n#if defined(JEMALLOC_MALLOC_THREAD_CLEANUP) || defined(_WIN32)\n#ifndef _WIN32\nJEMALLOC_EXPORT\n#endif\nvoid\n_malloc_thread_cleanup(void)\n{\n\tbool pending[MALLOC_TSD_CLEANUPS_MAX], again;\n\tunsigned i;\n\n\tfor (i = 0; i < ncleanups; i++)\n\t\tpending[i] = true;\n\n\tdo {\n\t\tagain = false;\n\t\tfor (i = 0; i < ncleanups; i++) {\n\t\t\tif (pending[i]) {\n\t\t\t\tpending[i] = cleanups[i]();\n\t\t\t\tif (pending[i])\n\t\t\t\t\tagain = true;\n\t\t\t}\n\t\t}\n\t} while (again);\n}\n#endif\n\nvoid\nmalloc_tsd_cleanup_register(bool (*f)(void))\n{\n\n\tassert(ncleanups < MALLOC_TSD_CLEANUPS_MAX);\n\tcleanups[ncleanups] = f;\n\tncleanups++;\n}\n\nvoid\nmalloc_tsd_boot(void)\n{\n\n\tncleanups = 0;\n}\n\n#ifdef _WIN32\nstatic BOOL WINAPI\n_tls_callback(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)\n{\n\n\tswitch (fdwReason) {\n#ifdef JEMALLOC_LAZY_LOCK\n\tcase DLL_THREAD_ATTACH:\n\t\tisthreaded = true;\n\t\tbreak;\n#endif\n\tcase DLL_THREAD_DETACH:\n\t\t_malloc_thread_cleanup();\n\t\tbreak;\n\tdefault:\n\t\tbreak;\n\t}\n\treturn (true);\n}\n\n#ifdef _MSC_VER\n#  ifdef _M_IX86\n#    pragma comment(linker, \"/INCLUDE:__tls_used\")\n#  else\n#    pragma comment(linker, \"/INCLUDE:_tls_used\")\n#  endif\n#  pragma section(\".CRT$XLY\",long,read)\n#endif\nJEMALLOC_SECTION(\".CRT$XLY\") JEMALLOC_ATTR(used)\nstatic const BOOL\t(WINAPI *tls_callback)(HINSTANCE hinstDLL,\n    DWORD fdwReason, LPVOID lpvReserved) = _tls_callback;\n#endif\n\n#if (!defined(JEMALLOC_MALLOC_THREAD_CLEANUP) && !defined(JEMALLOC_TLS) && \\\n    !defined(_WIN32))\nvoid *\ntsd_init_check_recursion(tsd_init_head_t *head, tsd_init_block_t *block)\n{\n\tpthread_t self = pthread_self();\n\ttsd_init_block_t *iter;\n\n\t/* Check whether this thread has already inserted into the list. */\n\tmalloc_mutex_lock(&head->lock);\n\tql_foreach(iter, &head->blocks, link) {\n\t\tif (iter->thread == self) {\n\t\t\tmalloc_mutex_unlock(&head->lock);\n\t\t\treturn (iter->data);\n\t\t}\n\t}\n\t/* Insert block into list. */\n\tql_elm_new(block, link);\n\tblock->thread = self;\n\tql_tail_insert(&head->blocks, block, link);\n\tmalloc_mutex_unlock(&head->lock);\n\treturn (NULL);\n}\n\nvoid\ntsd_init_finish(tsd_init_head_t *head, tsd_init_block_t *block)\n{\n\n\tmalloc_mutex_lock(&head->lock);\n\tql_remove(&head->blocks, block, link);\n\tmalloc_mutex_unlock(&head->lock);\n}\n#endif\n"
  },
  {
    "path": "extern/deprecated/redis-2.8.21/deps/jemalloc/src/util.c",
    "content": "#define\tassert(e) do {\t\t\t\t\t\t\t\\\n\tif (config_debug && !(e)) {\t\t\t\t\t\\\n\t\tmalloc_write(\"<jemalloc>: Failed assertion\\n\");\t\t\\\n\t\tabort();\t\t\t\t\t\t\\\n\t}\t\t\t\t\t\t\t\t\\\n} while (0)\n\n#define\tnot_reached() do {\t\t\t\t\t\t\\\n\tif (config_debug) {\t\t\t\t\t\t\\\n\t\tmalloc_write(\"<jemalloc>: Unreachable code reached\\n\");\t\\\n\t\tabort();\t\t\t\t\t\t\\\n\t}\t\t\t\t\t\t\t\t\\\n} while (0)\n\n#define\tnot_implemented() do {\t\t\t\t\t\t\\\n\tif (config_debug) {\t\t\t\t\t\t\\\n\t\tmalloc_write(\"<jemalloc>: Not implemented\\n\");\t\t\\\n\t\tabort();\t\t\t\t\t\t\\\n\t}\t\t\t\t\t\t\t\t\\\n} while (0)\n\n#define\tJEMALLOC_UTIL_C_\n#include \"jemalloc/internal/jemalloc_internal.h\"\n\n/******************************************************************************/\n/* Function prototypes for non-inline static functions. */\n\nstatic void\twrtmessage(void *cbopaque, const char *s);\n#define\tU2S_BUFSIZE\t((1U << (LG_SIZEOF_INTMAX_T + 3)) + 1)\nstatic char\t*u2s(uintmax_t x, unsigned base, bool uppercase, char *s,\n    size_t *slen_p);\n#define\tD2S_BUFSIZE\t(1 + U2S_BUFSIZE)\nstatic char\t*d2s(intmax_t x, char sign, char *s, size_t *slen_p);\n#define\tO2S_BUFSIZE\t(1 + U2S_BUFSIZE)\nstatic char\t*o2s(uintmax_t x, bool alt_form, char *s, size_t *slen_p);\n#define\tX2S_BUFSIZE\t(2 + U2S_BUFSIZE)\nstatic char\t*x2s(uintmax_t x, bool alt_form, bool uppercase, char *s,\n    size_t *slen_p);\n\n/******************************************************************************/\n\n/* malloc_message() setup. */\nstatic void\nwrtmessage(void *cbopaque, const char *s)\n{\n\n#ifdef SYS_write\n\t/*\n\t * Use syscall(2) rather than write(2) when possible in order to avoid\n\t * the possibility of memory allocation within libc.  This is necessary\n\t * on FreeBSD; most operating systems do not have this problem though.\n\t */\n\tUNUSED int result = syscall(SYS_write, STDERR_FILENO, s, strlen(s));\n#else\n\tUNUSED int result = write(STDERR_FILENO, s, strlen(s));\n#endif\n}\n\nJEMALLOC_EXPORT void\t(*je_malloc_message)(void *, const char *s);\n\n/*\n * Wrapper around malloc_message() that avoids the need for\n * je_malloc_message(...) throughout the code.\n */\nvoid\nmalloc_write(const char *s)\n{\n\n\tif (je_malloc_message != NULL)\n\t\tje_malloc_message(NULL, s);\n\telse\n\t\twrtmessage(NULL, s);\n}\n\n/*\n * glibc provides a non-standard strerror_r() when _GNU_SOURCE is defined, so\n * provide a wrapper.\n */\nint\nbuferror(int err, char *buf, size_t buflen)\n{\n\n#ifdef _WIN32\n\tFormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM, NULL, GetLastError(), 0,\n\t    (LPSTR)buf, buflen, NULL);\n\treturn (0);\n#elif defined(_GNU_SOURCE)\n\tchar *b = strerror_r(err, buf, buflen);\n\tif (b != buf) {\n\t\tstrncpy(buf, b, buflen);\n\t\tbuf[buflen-1] = '\\0';\n\t}\n\treturn (0);\n#else\n\treturn (strerror_r(err, buf, buflen));\n#endif\n}\n\nuintmax_t\nmalloc_strtoumax(const char *restrict nptr, char **restrict endptr, int base)\n{\n\tuintmax_t ret, digit;\n\tint b;\n\tbool neg;\n\tconst char *p, *ns;\n\n\tp = nptr;\n\tif (base < 0 || base == 1 || base > 36) {\n\t\tns = p;\n\t\tset_errno(EINVAL);\n\t\tret = UINTMAX_MAX;\n\t\tgoto label_return;\n\t}\n\tb = base;\n\n\t/* Swallow leading whitespace and get sign, if any. */\n\tneg = false;\n\twhile (true) {\n\t\tswitch (*p) {\n\t\tcase '\\t': case '\\n': case '\\v': case '\\f': case '\\r': case ' ':\n\t\t\tp++;\n\t\t\tbreak;\n\t\tcase '-':\n\t\t\tneg = true;\n\t\t\t/* Fall through. */\n\t\tcase '+':\n\t\t\tp++;\n\t\t\t/* Fall through. */\n\t\tdefault:\n\t\t\tgoto label_prefix;\n\t\t}\n\t}\n\n\t/* Get prefix, if any. */\n\tlabel_prefix:\n\t/*\n\t * Note where the first non-whitespace/sign character is so that it is\n\t * possible to tell whether any digits are consumed (e.g., \"  0\" vs.\n\t * \"  -x\").\n\t */\n\tns = p;\n\tif (*p == '0') {\n\t\tswitch (p[1]) {\n\t\tcase '0': case '1': case '2': case '3': case '4': case '5':\n\t\tcase '6': case '7':\n\t\t\tif (b == 0)\n\t\t\t\tb = 8;\n\t\t\tif (b == 8)\n\t\t\t\tp++;\n\t\t\tbreak;\n\t\tcase 'X': case 'x':\n\t\t\tswitch (p[2]) {\n\t\t\tcase '0': case '1': case '2': case '3': case '4':\n\t\t\tcase '5': case '6': case '7': case '8': case '9':\n\t\t\tcase 'A': case 'B': case 'C': case 'D': case 'E':\n\t\t\tcase 'F':\n\t\t\tcase 'a': case 'b': case 'c': case 'd': case 'e':\n\t\t\tcase 'f':\n\t\t\t\tif (b == 0)\n\t\t\t\t\tb = 16;\n\t\t\t\tif (b == 16)\n\t\t\t\t\tp += 2;\n\t\t\t\tbreak;\n\t\t\tdefault:\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tbreak;\n\t\tdefault:\n\t\t\tp++;\n\t\t\tret = 0;\n\t\t\tgoto label_return;\n\t\t}\n\t}\n\tif (b == 0)\n\t\tb = 10;\n\n\t/* Convert. */\n\tret = 0;\n\twhile ((*p >= '0' && *p <= '9' && (digit = *p - '0') < b)\n\t    || (*p >= 'A' && *p <= 'Z' && (digit = 10 + *p - 'A') < b)\n\t    || (*p >= 'a' && *p <= 'z' && (digit = 10 + *p - 'a') < b)) {\n\t\tuintmax_t pret = ret;\n\t\tret *= b;\n\t\tret += digit;\n\t\tif (ret < pret) {\n\t\t\t/* Overflow. */\n\t\t\tset_errno(ERANGE);\n\t\t\tret = UINTMAX_MAX;\n\t\t\tgoto label_return;\n\t\t}\n\t\tp++;\n\t}\n\tif (neg)\n\t\tret = -ret;\n\n\tif (p == ns) {\n\t\t/* No conversion performed. */\n\t\tset_errno(EINVAL);\n\t\tret = UINTMAX_MAX;\n\t\tgoto label_return;\n\t}\n\nlabel_return:\n\tif (endptr != NULL) {\n\t\tif (p == ns) {\n\t\t\t/* No characters were converted. */\n\t\t\t*endptr = (char *)nptr;\n\t\t} else\n\t\t\t*endptr = (char *)p;\n\t}\n\treturn (ret);\n}\n\nstatic char *\nu2s(uintmax_t x, unsigned base, bool uppercase, char *s, size_t *slen_p)\n{\n\tunsigned i;\n\n\ti = U2S_BUFSIZE - 1;\n\ts[i] = '\\0';\n\tswitch (base) {\n\tcase 10:\n\t\tdo {\n\t\t\ti--;\n\t\t\ts[i] = \"0123456789\"[x % (uint64_t)10];\n\t\t\tx /= (uint64_t)10;\n\t\t} while (x > 0);\n\t\tbreak;\n\tcase 16: {\n\t\tconst char *digits = (uppercase)\n\t\t    ? \"0123456789ABCDEF\"\n\t\t    : \"0123456789abcdef\";\n\n\t\tdo {\n\t\t\ti--;\n\t\t\ts[i] = digits[x & 0xf];\n\t\t\tx >>= 4;\n\t\t} while (x > 0);\n\t\tbreak;\n\t} default: {\n\t\tconst char *digits = (uppercase)\n\t\t    ? \"0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ\"\n\t\t    : \"0123456789abcdefghijklmnopqrstuvwxyz\";\n\n\t\tassert(base >= 2 && base <= 36);\n\t\tdo {\n\t\t\ti--;\n\t\t\ts[i] = digits[x % (uint64_t)base];\n\t\t\tx /= (uint64_t)base;\n\t\t} while (x > 0);\n\t}}\n\n\t*slen_p = U2S_BUFSIZE - 1 - i;\n\treturn (&s[i]);\n}\n\nstatic char *\nd2s(intmax_t x, char sign, char *s, size_t *slen_p)\n{\n\tbool neg;\n\n\tif ((neg = (x < 0)))\n\t\tx = -x;\n\ts = u2s(x, 10, false, s, slen_p);\n\tif (neg)\n\t\tsign = '-';\n\tswitch (sign) {\n\tcase '-':\n\t\tif (neg == false)\n\t\t\tbreak;\n\t\t/* Fall through. */\n\tcase ' ':\n\tcase '+':\n\t\ts--;\n\t\t(*slen_p)++;\n\t\t*s = sign;\n\t\tbreak;\n\tdefault: not_reached();\n\t}\n\treturn (s);\n}\n\nstatic char *\no2s(uintmax_t x, bool alt_form, char *s, size_t *slen_p)\n{\n\n\ts = u2s(x, 8, false, s, slen_p);\n\tif (alt_form && *s != '0') {\n\t\ts--;\n\t\t(*slen_p)++;\n\t\t*s = '0';\n\t}\n\treturn (s);\n}\n\nstatic char *\nx2s(uintmax_t x, bool alt_form, bool uppercase, char *s, size_t *slen_p)\n{\n\n\ts = u2s(x, 16, uppercase, s, slen_p);\n\tif (alt_form) {\n\t\ts -= 2;\n\t\t(*slen_p) += 2;\n\t\tmemcpy(s, uppercase ? \"0X\" : \"0x\", 2);\n\t}\n\treturn (s);\n}\n\nint\nmalloc_vsnprintf(char *str, size_t size, const char *format, va_list ap)\n{\n\tint ret;\n\tsize_t i;\n\tconst char *f;\n\n#define\tAPPEND_C(c) do {\t\t\t\t\t\t\\\n\tif (i < size)\t\t\t\t\t\t\t\\\n\t\tstr[i] = (c);\t\t\t\t\t\t\\\n\ti++;\t\t\t\t\t\t\t\t\\\n} while (0)\n#define\tAPPEND_S(s, slen) do {\t\t\t\t\t\t\\\n\tif (i < size) {\t\t\t\t\t\t\t\\\n\t\tsize_t cpylen = (slen <= size - i) ? slen : size - i;\t\\\n\t\tmemcpy(&str[i], s, cpylen);\t\t\t\t\\\n\t}\t\t\t\t\t\t\t\t\\\n\ti += slen;\t\t\t\t\t\t\t\\\n} while (0)\n#define\tAPPEND_PADDED_S(s, slen, width, left_justify) do {\t\t\\\n\t/* Left padding. */\t\t\t\t\t\t\\\n\tsize_t pad_len = (width == -1) ? 0 : ((slen < (size_t)width) ?\t\\\n\t    (size_t)width - slen : 0);\t\t\t\t\t\\\n\tif (left_justify == false && pad_len != 0) {\t\t\t\\\n\t\tsize_t j;\t\t\t\t\t\t\\\n\t\tfor (j = 0; j < pad_len; j++)\t\t\t\t\\\n\t\t\tAPPEND_C(' ');\t\t\t\t\t\\\n\t}\t\t\t\t\t\t\t\t\\\n\t/* Value. */\t\t\t\t\t\t\t\\\n\tAPPEND_S(s, slen);\t\t\t\t\t\t\\\n\t/* Right padding. */\t\t\t\t\t\t\\\n\tif (left_justify && pad_len != 0) {\t\t\t\t\\\n\t\tsize_t j;\t\t\t\t\t\t\\\n\t\tfor (j = 0; j < pad_len; j++)\t\t\t\t\\\n\t\t\tAPPEND_C(' ');\t\t\t\t\t\\\n\t}\t\t\t\t\t\t\t\t\\\n} while (0)\n#define\tGET_ARG_NUMERIC(val, len) do {\t\t\t\t\t\\\n\tswitch (len) {\t\t\t\t\t\t\t\\\n\tcase '?':\t\t\t\t\t\t\t\\\n\t\tval = va_arg(ap, int);\t\t\t\t\t\\\n\t\tbreak;\t\t\t\t\t\t\t\\\n\tcase '?' | 0x80:\t\t\t\t\t\t\\\n\t\tval = va_arg(ap, unsigned int);\t\t\t\t\\\n\t\tbreak;\t\t\t\t\t\t\t\\\n\tcase 'l':\t\t\t\t\t\t\t\\\n\t\tval = va_arg(ap, long);\t\t\t\t\t\\\n\t\tbreak;\t\t\t\t\t\t\t\\\n\tcase 'l' | 0x80:\t\t\t\t\t\t\\\n\t\tval = va_arg(ap, unsigned long);\t\t\t\\\n\t\tbreak;\t\t\t\t\t\t\t\\\n\tcase 'q':\t\t\t\t\t\t\t\\\n\t\tval = va_arg(ap, long long);\t\t\t\t\\\n\t\tbreak;\t\t\t\t\t\t\t\\\n\tcase 'q' | 0x80:\t\t\t\t\t\t\\\n\t\tval = va_arg(ap, unsigned long long);\t\t\t\\\n\t\tbreak;\t\t\t\t\t\t\t\\\n\tcase 'j':\t\t\t\t\t\t\t\\\n\t\tval = va_arg(ap, intmax_t);\t\t\t\t\\\n\t\tbreak;\t\t\t\t\t\t\t\\\n\tcase 'j' | 0x80:\t\t\t\t\t\t\\\n\t\tval = va_arg(ap, uintmax_t);\t\t\t\t\\\n\t\tbreak;\t\t\t\t\t\t\t\\\n\tcase 't':\t\t\t\t\t\t\t\\\n\t\tval = va_arg(ap, ptrdiff_t);\t\t\t\t\\\n\t\tbreak;\t\t\t\t\t\t\t\\\n\tcase 'z':\t\t\t\t\t\t\t\\\n\t\tval = va_arg(ap, ssize_t);\t\t\t\t\\\n\t\tbreak;\t\t\t\t\t\t\t\\\n\tcase 'z' | 0x80:\t\t\t\t\t\t\\\n\t\tval = va_arg(ap, size_t);\t\t\t\t\\\n\t\tbreak;\t\t\t\t\t\t\t\\\n\tcase 'p': /* Synthetic; used for %p. */\t\t\t\t\\\n\t\tval = va_arg(ap, uintptr_t);\t\t\t\t\\\n\t\tbreak;\t\t\t\t\t\t\t\\\n\tdefault: not_reached();\t\t\t\t\t\t\\\n\t}\t\t\t\t\t\t\t\t\\\n} while (0)\n\n\ti = 0;\n\tf = format;\n\twhile (true) {\n\t\tswitch (*f) {\n\t\tcase '\\0': goto label_out;\n\t\tcase '%': {\n\t\t\tbool alt_form = false;\n\t\t\tbool left_justify = false;\n\t\t\tbool plus_space = false;\n\t\t\tbool plus_plus = false;\n\t\t\tint prec = -1;\n\t\t\tint width = -1;\n\t\t\tunsigned char len = '?';\n\n\t\t\tf++;\n\t\t\t/* Flags. */\n\t\t\twhile (true) {\n\t\t\t\tswitch (*f) {\n\t\t\t\tcase '#':\n\t\t\t\t\tassert(alt_form == false);\n\t\t\t\t\talt_form = true;\n\t\t\t\t\tbreak;\n\t\t\t\tcase '-':\n\t\t\t\t\tassert(left_justify == false);\n\t\t\t\t\tleft_justify = true;\n\t\t\t\t\tbreak;\n\t\t\t\tcase ' ':\n\t\t\t\t\tassert(plus_space == false);\n\t\t\t\t\tplus_space = true;\n\t\t\t\t\tbreak;\n\t\t\t\tcase '+':\n\t\t\t\t\tassert(plus_plus == false);\n\t\t\t\t\tplus_plus = true;\n\t\t\t\t\tbreak;\n\t\t\t\tdefault: goto label_width;\n\t\t\t\t}\n\t\t\t\tf++;\n\t\t\t}\n\t\t\t/* Width. */\n\t\t\tlabel_width:\n\t\t\tswitch (*f) {\n\t\t\tcase '*':\n\t\t\t\twidth = va_arg(ap, int);\n\t\t\t\tf++;\n\t\t\t\tif (width < 0) {\n\t\t\t\t\tleft_justify = true;\n\t\t\t\t\twidth = -width;\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\tcase '0': case '1': case '2': case '3': case '4':\n\t\t\tcase '5': case '6': case '7': case '8': case '9': {\n\t\t\t\tuintmax_t uwidth;\n\t\t\t\tset_errno(0);\n\t\t\t\tuwidth = malloc_strtoumax(f, (char **)&f, 10);\n\t\t\t\tassert(uwidth != UINTMAX_MAX || get_errno() !=\n\t\t\t\t    ERANGE);\n\t\t\t\twidth = (int)uwidth;\n\t\t\t\tbreak;\n\t\t\t} default:\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\t/* Width/precision separator. */\n\t\t\tif (*f == '.')\n\t\t\t\tf++;\n\t\t\telse\n\t\t\t\tgoto label_length;\n\t\t\t/* Precision. */\n\t\t\tswitch (*f) {\n\t\t\tcase '*':\n\t\t\t\tprec = va_arg(ap, int);\n\t\t\t\tf++;\n\t\t\t\tbreak;\n\t\t\tcase '0': case '1': case '2': case '3': case '4':\n\t\t\tcase '5': case '6': case '7': case '8': case '9': {\n\t\t\t\tuintmax_t uprec;\n\t\t\t\tset_errno(0);\n\t\t\t\tuprec = malloc_strtoumax(f, (char **)&f, 10);\n\t\t\t\tassert(uprec != UINTMAX_MAX || get_errno() !=\n\t\t\t\t    ERANGE);\n\t\t\t\tprec = (int)uprec;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tdefault: break;\n\t\t\t}\n\t\t\t/* Length. */\n\t\t\tlabel_length:\n\t\t\tswitch (*f) {\n\t\t\tcase 'l':\n\t\t\t\tf++;\n\t\t\t\tif (*f == 'l') {\n\t\t\t\t\tlen = 'q';\n\t\t\t\t\tf++;\n\t\t\t\t} else\n\t\t\t\t\tlen = 'l';\n\t\t\t\tbreak;\n\t\t\tcase 'q': case 'j': case 't': case 'z':\n\t\t\t\tlen = *f;\n\t\t\t\tf++;\n\t\t\t\tbreak;\n\t\t\tdefault: break;\n\t\t\t}\n\t\t\t/* Conversion specifier. */\n\t\t\tswitch (*f) {\n\t\t\t\tchar *s;\n\t\t\t\tsize_t slen;\n\t\t\tcase '%':\n\t\t\t\t/* %% */\n\t\t\t\tAPPEND_C(*f);\n\t\t\t\tf++;\n\t\t\t\tbreak;\n\t\t\tcase 'd': case 'i': {\n\t\t\t\tintmax_t val JEMALLOC_CC_SILENCE_INIT(0);\n\t\t\t\tchar buf[D2S_BUFSIZE];\n\n\t\t\t\tGET_ARG_NUMERIC(val, len);\n\t\t\t\ts = d2s(val, (plus_plus ? '+' : (plus_space ?\n\t\t\t\t    ' ' : '-')), buf, &slen);\n\t\t\t\tAPPEND_PADDED_S(s, slen, width, left_justify);\n\t\t\t\tf++;\n\t\t\t\tbreak;\n\t\t\t} case 'o': {\n\t\t\t\tuintmax_t val JEMALLOC_CC_SILENCE_INIT(0);\n\t\t\t\tchar buf[O2S_BUFSIZE];\n\n\t\t\t\tGET_ARG_NUMERIC(val, len | 0x80);\n\t\t\t\ts = o2s(val, alt_form, buf, &slen);\n\t\t\t\tAPPEND_PADDED_S(s, slen, width, left_justify);\n\t\t\t\tf++;\n\t\t\t\tbreak;\n\t\t\t} case 'u': {\n\t\t\t\tuintmax_t val JEMALLOC_CC_SILENCE_INIT(0);\n\t\t\t\tchar buf[U2S_BUFSIZE];\n\n\t\t\t\tGET_ARG_NUMERIC(val, len | 0x80);\n\t\t\t\ts = u2s(val, 10, false, buf, &slen);\n\t\t\t\tAPPEND_PADDED_S(s, slen, width, left_justify);\n\t\t\t\tf++;\n\t\t\t\tbreak;\n\t\t\t} case 'x': case 'X': {\n\t\t\t\tuintmax_t val JEMALLOC_CC_SILENCE_INIT(0);\n\t\t\t\tchar buf[X2S_BUFSIZE];\n\n\t\t\t\tGET_ARG_NUMERIC(val, len | 0x80);\n\t\t\t\ts = x2s(val, alt_form, *f == 'X', buf, &slen);\n\t\t\t\tAPPEND_PADDED_S(s, slen, width, left_justify);\n\t\t\t\tf++;\n\t\t\t\tbreak;\n\t\t\t} case 'c': {\n\t\t\t\tunsigned char val;\n\t\t\t\tchar buf[2];\n\n\t\t\t\tassert(len == '?' || len == 'l');\n\t\t\t\tassert_not_implemented(len != 'l');\n\t\t\t\tval = va_arg(ap, int);\n\t\t\t\tbuf[0] = val;\n\t\t\t\tbuf[1] = '\\0';\n\t\t\t\tAPPEND_PADDED_S(buf, 1, width, left_justify);\n\t\t\t\tf++;\n\t\t\t\tbreak;\n\t\t\t} case 's':\n\t\t\t\tassert(len == '?' || len == 'l');\n\t\t\t\tassert_not_implemented(len != 'l');\n\t\t\t\ts = va_arg(ap, char *);\n\t\t\t\tslen = (prec < 0) ? strlen(s) : prec;\n\t\t\t\tAPPEND_PADDED_S(s, slen, width, left_justify);\n\t\t\t\tf++;\n\t\t\t\tbreak;\n\t\t\tcase 'p': {\n\t\t\t\tuintmax_t val;\n\t\t\t\tchar buf[X2S_BUFSIZE];\n\n\t\t\t\tGET_ARG_NUMERIC(val, 'p');\n\t\t\t\ts = x2s(val, true, false, buf, &slen);\n\t\t\t\tAPPEND_PADDED_S(s, slen, width, left_justify);\n\t\t\t\tf++;\n\t\t\t\tbreak;\n\t\t\t} default: not_reached();\n\t\t\t}\n\t\t\tbreak;\n\t\t} default: {\n\t\t\tAPPEND_C(*f);\n\t\t\tf++;\n\t\t\tbreak;\n\t\t}}\n\t}\n\tlabel_out:\n\tif (i < size)\n\t\tstr[i] = '\\0';\n\telse\n\t\tstr[size - 1] = '\\0';\n\tret = i;\n\n#undef APPEND_C\n#undef APPEND_S\n#undef APPEND_PADDED_S\n#undef GET_ARG_NUMERIC\n\treturn (ret);\n}\n\nJEMALLOC_ATTR(format(printf, 3, 4))\nint\nmalloc_snprintf(char *str, size_t size, const char *format, ...)\n{\n\tint ret;\n\tva_list ap;\n\n\tva_start(ap, format);\n\tret = malloc_vsnprintf(str, size, format, ap);\n\tva_end(ap);\n\n\treturn (ret);\n}\n\nvoid\nmalloc_vcprintf(void (*write_cb)(void *, const char *), void *cbopaque,\n    const char *format, va_list ap)\n{\n\tchar buf[MALLOC_PRINTF_BUFSIZE];\n\n\tif (write_cb == NULL) {\n\t\t/*\n\t\t * The caller did not provide an alternate write_cb callback\n\t\t * function, so use the default one.  malloc_write() is an\n\t\t * inline function, so use malloc_message() directly here.\n\t\t */\n\t\twrite_cb = (je_malloc_message != NULL) ? je_malloc_message :\n\t\t    wrtmessage;\n\t\tcbopaque = NULL;\n\t}\n\n\tmalloc_vsnprintf(buf, sizeof(buf), format, ap);\n\twrite_cb(cbopaque, buf);\n}\n\n/*\n * Print to a callback function in such a way as to (hopefully) avoid memory\n * allocation.\n */\nJEMALLOC_ATTR(format(printf, 3, 4))\nvoid\nmalloc_cprintf(void (*write_cb)(void *, const char *), void *cbopaque,\n    const char *format, ...)\n{\n\tva_list ap;\n\n\tva_start(ap, format);\n\tmalloc_vcprintf(write_cb, cbopaque, format, ap);\n\tva_end(ap);\n}\n\n/* Print to stderr in such a way as to avoid memory allocation. */\nJEMALLOC_ATTR(format(printf, 1, 2))\nvoid\nmalloc_printf(const char *format, ...)\n{\n\tva_list ap;\n\n\tva_start(ap, format);\n\tmalloc_vcprintf(NULL, NULL, format, ap);\n\tva_end(ap);\n}\n"
  },
  {
    "path": "extern/deprecated/redis-2.8.21/deps/jemalloc/src/zone.c",
    "content": "#include \"jemalloc/internal/jemalloc_internal.h\"\n#ifndef JEMALLOC_ZONE\n#  error \"This source file is for zones on Darwin (OS X).\"\n#endif\n\n/*\n * The malloc_default_purgeable_zone function is only available on >= 10.6.\n * We need to check whether it is present at runtime, thus the weak_import.\n */\nextern malloc_zone_t *malloc_default_purgeable_zone(void)\nJEMALLOC_ATTR(weak_import);\n\n/******************************************************************************/\n/* Data. */\n\nstatic malloc_zone_t zone;\nstatic struct malloc_introspection_t zone_introspect;\n\n/******************************************************************************/\n/* Function prototypes for non-inline static functions. */\n\nstatic size_t\tzone_size(malloc_zone_t *zone, void *ptr);\nstatic void\t*zone_malloc(malloc_zone_t *zone, size_t size);\nstatic void\t*zone_calloc(malloc_zone_t *zone, size_t num, size_t size);\nstatic void\t*zone_valloc(malloc_zone_t *zone, size_t size);\nstatic void\tzone_free(malloc_zone_t *zone, void *ptr);\nstatic void\t*zone_realloc(malloc_zone_t *zone, void *ptr, size_t size);\n#if (JEMALLOC_ZONE_VERSION >= 5)\nstatic void\t*zone_memalign(malloc_zone_t *zone, size_t alignment,\n#endif\n#if (JEMALLOC_ZONE_VERSION >= 6)\n    size_t size);\nstatic void\tzone_free_definite_size(malloc_zone_t *zone, void *ptr,\n    size_t size);\n#endif\nstatic void\t*zone_destroy(malloc_zone_t *zone);\nstatic size_t\tzone_good_size(malloc_zone_t *zone, size_t size);\nstatic void\tzone_force_lock(malloc_zone_t *zone);\nstatic void\tzone_force_unlock(malloc_zone_t *zone);\n\n/******************************************************************************/\n/*\n * Functions.\n */\n\nstatic size_t\nzone_size(malloc_zone_t *zone, void *ptr)\n{\n\n\t/*\n\t * There appear to be places within Darwin (such as setenv(3)) that\n\t * cause calls to this function with pointers that *no* zone owns.  If\n\t * we knew that all pointers were owned by *some* zone, we could split\n\t * our zone into two parts, and use one as the default allocator and\n\t * the other as the default deallocator/reallocator.  Since that will\n\t * not work in practice, we must check all pointers to assure that they\n\t * reside within a mapped chunk before determining size.\n\t */\n\treturn (ivsalloc(ptr, config_prof));\n}\n\nstatic void *\nzone_malloc(malloc_zone_t *zone, size_t size)\n{\n\n\treturn (je_malloc(size));\n}\n\nstatic void *\nzone_calloc(malloc_zone_t *zone, size_t num, size_t size)\n{\n\n\treturn (je_calloc(num, size));\n}\n\nstatic void *\nzone_valloc(malloc_zone_t *zone, size_t size)\n{\n\tvoid *ret = NULL; /* Assignment avoids useless compiler warning. */\n\n\tje_posix_memalign(&ret, PAGE, size);\n\n\treturn (ret);\n}\n\nstatic void\nzone_free(malloc_zone_t *zone, void *ptr)\n{\n\n\tif (ivsalloc(ptr, config_prof) != 0) {\n\t\tje_free(ptr);\n\t\treturn;\n\t}\n\n\tfree(ptr);\n}\n\nstatic void *\nzone_realloc(malloc_zone_t *zone, void *ptr, size_t size)\n{\n\n\tif (ivsalloc(ptr, config_prof) != 0)\n\t\treturn (je_realloc(ptr, size));\n\n\treturn (realloc(ptr, size));\n}\n\n#if (JEMALLOC_ZONE_VERSION >= 5)\nstatic void *\nzone_memalign(malloc_zone_t *zone, size_t alignment, size_t size)\n{\n\tvoid *ret = NULL; /* Assignment avoids useless compiler warning. */\n\n\tje_posix_memalign(&ret, alignment, size);\n\n\treturn (ret);\n}\n#endif\n\n#if (JEMALLOC_ZONE_VERSION >= 6)\nstatic void\nzone_free_definite_size(malloc_zone_t *zone, void *ptr, size_t size)\n{\n\n\tif (ivsalloc(ptr, config_prof) != 0) {\n\t\tassert(ivsalloc(ptr, config_prof) == size);\n\t\tje_free(ptr);\n\t\treturn;\n\t}\n\n\tfree(ptr);\n}\n#endif\n\nstatic void *\nzone_destroy(malloc_zone_t *zone)\n{\n\n\t/* This function should never be called. */\n\tnot_reached();\n\treturn (NULL);\n}\n\nstatic size_t\nzone_good_size(malloc_zone_t *zone, size_t size)\n{\n\n\tif (size == 0)\n\t\tsize = 1;\n\treturn (s2u(size));\n}\n\nstatic void\nzone_force_lock(malloc_zone_t *zone)\n{\n\n\tif (isthreaded)\n\t\tjemalloc_prefork();\n}\n\nstatic void\nzone_force_unlock(malloc_zone_t *zone)\n{\n\n\tif (isthreaded)\n\t\tjemalloc_postfork_parent();\n}\n\nJEMALLOC_ATTR(constructor)\nvoid\nregister_zone(void)\n{\n\n\t/*\n\t * If something else replaced the system default zone allocator, don't\n\t * register jemalloc's.\n\t */\n\tmalloc_zone_t *default_zone = malloc_default_zone();\n\tif (!default_zone->zone_name ||\n\t    strcmp(default_zone->zone_name, \"DefaultMallocZone\") != 0) {\n\t\treturn;\n\t}\n\n\tzone.size = (void *)zone_size;\n\tzone.malloc = (void *)zone_malloc;\n\tzone.calloc = (void *)zone_calloc;\n\tzone.valloc = (void *)zone_valloc;\n\tzone.free = (void *)zone_free;\n\tzone.realloc = (void *)zone_realloc;\n\tzone.destroy = (void *)zone_destroy;\n\tzone.zone_name = \"jemalloc_zone\";\n\tzone.batch_malloc = NULL;\n\tzone.batch_free = NULL;\n\tzone.introspect = &zone_introspect;\n\tzone.version = JEMALLOC_ZONE_VERSION;\n#if (JEMALLOC_ZONE_VERSION >= 5)\n\tzone.memalign = zone_memalign;\n#endif\n#if (JEMALLOC_ZONE_VERSION >= 6)\n\tzone.free_definite_size = zone_free_definite_size;\n#endif\n#if (JEMALLOC_ZONE_VERSION >= 8)\n\tzone.pressure_relief = NULL;\n#endif\n\n\tzone_introspect.enumerator = NULL;\n\tzone_introspect.good_size = (void *)zone_good_size;\n\tzone_introspect.check = NULL;\n\tzone_introspect.print = NULL;\n\tzone_introspect.log = NULL;\n\tzone_introspect.force_lock = (void *)zone_force_lock;\n\tzone_introspect.force_unlock = (void *)zone_force_unlock;\n\tzone_introspect.statistics = NULL;\n#if (JEMALLOC_ZONE_VERSION >= 6)\n\tzone_introspect.zone_locked = NULL;\n#endif\n#if (JEMALLOC_ZONE_VERSION >= 7)\n\tzone_introspect.enable_discharge_checking = NULL;\n\tzone_introspect.disable_discharge_checking = NULL;\n\tzone_introspect.discharge = NULL;\n#ifdef __BLOCKS__\n\tzone_introspect.enumerate_discharged_pointers = NULL;\n#else\n\tzone_introspect.enumerate_unavailable_without_blocks = NULL;\n#endif\n#endif\n\n\t/*\n\t * The default purgeable zone is created lazily by OSX's libc.  It uses\n\t * the default zone when it is created for \"small\" allocations\n\t * (< 15 KiB), but assumes the default zone is a scalable_zone.  This\n\t * obviously fails when the default zone is the jemalloc zone, so\n\t * malloc_default_purgeable_zone is called beforehand so that the\n\t * default purgeable zone is created when the default zone is still\n\t * a scalable_zone.  As purgeable zones only exist on >= 10.6, we need\n\t * to check for the existence of malloc_default_purgeable_zone() at\n\t * run time.\n\t */\n\tif (malloc_default_purgeable_zone != NULL)\n\t\tmalloc_default_purgeable_zone();\n\n\t/* Register the custom zone.  At this point it won't be the default. */\n\tmalloc_zone_register(&zone);\n\n\t/*\n\t * Unregister and reregister the default zone.  On OSX >= 10.6,\n\t * unregistering takes the last registered zone and places it at the\n\t * location of the specified zone.  Unregistering the default zone thus\n\t * makes the last registered one the default.  On OSX < 10.6,\n\t * unregistering shifts all registered zones.  The first registered zone\n\t * then becomes the default.\n\t */\n\tdo {\n\t\tdefault_zone = malloc_default_zone();\n\t\tmalloc_zone_unregister(default_zone);\n\t\tmalloc_zone_register(default_zone);\n\t} while (malloc_default_zone() != &zone);\n}\n"
  },
  {
    "path": "extern/deprecated/redis-2.8.21/deps/jemalloc/test/include/test/SFMT-alti.h",
    "content": "/*\n * This file derives from SFMT 1.3.3\n * (http://www.math.sci.hiroshima-u.ac.jp/~m-mat/MT/SFMT/index.html), which was\n * released under the terms of the following license:\n *\n *   Copyright (c) 2006,2007 Mutsuo Saito, Makoto Matsumoto and Hiroshima\n *   University. All rights reserved.\n *\n *   Redistribution and use in source and binary forms, with or without\n *   modification, are permitted provided that the following conditions are\n *   met:\n *\n *       * Redistributions of source code must retain the above copyright\n *         notice, this list of conditions and the following disclaimer.\n *       * Redistributions in binary form must reproduce the above\n *         copyright notice, this list of conditions and the following\n *         disclaimer in the documentation and/or other materials provided\n *         with the distribution.\n *       * Neither the name of the Hiroshima University nor the names of\n *         its contributors may be used to endorse or promote products\n *         derived from this software without specific prior written\n *         permission.\n *\n *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n *   \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\n *   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\n *   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\n *   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n *   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\n *   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n *   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n *   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n *   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n *   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n/** \n * @file SFMT-alti.h \n *\n * @brief SIMD oriented Fast Mersenne Twister(SFMT)\n * pseudorandom number generator\n *\n * @author Mutsuo Saito (Hiroshima University)\n * @author Makoto Matsumoto (Hiroshima University)\n *\n * Copyright (C) 2007 Mutsuo Saito, Makoto Matsumoto and Hiroshima\n * University. All rights reserved.\n *\n * The new BSD License is applied to this software.\n * see LICENSE.txt\n */\n\n#ifndef SFMT_ALTI_H\n#define SFMT_ALTI_H\n\n/**\n * This function represents the recursion formula in AltiVec and BIG ENDIAN.\n * @param a a 128-bit part of the interal state array\n * @param b a 128-bit part of the interal state array\n * @param c a 128-bit part of the interal state array\n * @param d a 128-bit part of the interal state array\n * @return output\n */\nJEMALLOC_ALWAYS_INLINE\nvector unsigned int vec_recursion(vector unsigned int a,\n\t\t\t\t\t\tvector unsigned int b,\n\t\t\t\t\t\tvector unsigned int c,\n\t\t\t\t\t\tvector unsigned int d) {\n\n    const vector unsigned int sl1 = ALTI_SL1;\n    const vector unsigned int sr1 = ALTI_SR1;\n#ifdef ONLY64\n    const vector unsigned int mask = ALTI_MSK64;\n    const vector unsigned char perm_sl = ALTI_SL2_PERM64;\n    const vector unsigned char perm_sr = ALTI_SR2_PERM64;\n#else\n    const vector unsigned int mask = ALTI_MSK;\n    const vector unsigned char perm_sl = ALTI_SL2_PERM;\n    const vector unsigned char perm_sr = ALTI_SR2_PERM;\n#endif\n    vector unsigned int v, w, x, y, z;\n    x = vec_perm(a, (vector unsigned int)perm_sl, perm_sl);\n    v = a;\n    y = vec_sr(b, sr1);\n    z = vec_perm(c, (vector unsigned int)perm_sr, perm_sr);\n    w = vec_sl(d, sl1);\n    z = vec_xor(z, w);\n    y = vec_and(y, mask);\n    v = vec_xor(v, x);\n    z = vec_xor(z, y);\n    z = vec_xor(z, v);\n    return z;\n}\n\n/**\n * This function fills the internal state array with pseudorandom\n * integers.\n */\nJEMALLOC_INLINE void gen_rand_all(sfmt_t *ctx) {\n    int i;\n    vector unsigned int r, r1, r2;\n\n    r1 = ctx->sfmt[N - 2].s;\n    r2 = ctx->sfmt[N - 1].s;\n    for (i = 0; i < N - POS1; i++) {\n\tr = vec_recursion(ctx->sfmt[i].s, ctx->sfmt[i + POS1].s, r1, r2);\n\tctx->sfmt[i].s = r;\n\tr1 = r2;\n\tr2 = r;\n    }\n    for (; i < N; i++) {\n\tr = vec_recursion(ctx->sfmt[i].s, ctx->sfmt[i + POS1 - N].s, r1, r2);\n\tctx->sfmt[i].s = r;\n\tr1 = r2;\n\tr2 = r;\n    }\n}\n\n/**\n * This function fills the user-specified array with pseudorandom\n * integers.\n *\n * @param array an 128-bit array to be filled by pseudorandom numbers.  \n * @param size number of 128-bit pesudorandom numbers to be generated.\n */\nJEMALLOC_INLINE void gen_rand_array(sfmt_t *ctx, w128_t *array, int size) {\n    int i, j;\n    vector unsigned int r, r1, r2;\n\n    r1 = ctx->sfmt[N - 2].s;\n    r2 = ctx->sfmt[N - 1].s;\n    for (i = 0; i < N - POS1; i++) {\n\tr = vec_recursion(ctx->sfmt[i].s, ctx->sfmt[i + POS1].s, r1, r2);\n\tarray[i].s = r;\n\tr1 = r2;\n\tr2 = r;\n    }\n    for (; i < N; i++) {\n\tr = vec_recursion(ctx->sfmt[i].s, array[i + POS1 - N].s, r1, r2);\n\tarray[i].s = r;\n\tr1 = r2;\n\tr2 = r;\n    }\n    /* main loop */\n    for (; i < size - N; i++) {\n\tr = vec_recursion(array[i - N].s, array[i + POS1 - N].s, r1, r2);\n\tarray[i].s = r;\n\tr1 = r2;\n\tr2 = r;\n    }\n    for (j = 0; j < 2 * N - size; j++) {\n\tctx->sfmt[j].s = array[j + size - N].s;\n    }\n    for (; i < size; i++) {\n\tr = vec_recursion(array[i - N].s, array[i + POS1 - N].s, r1, r2);\n\tarray[i].s = r;\n\tctx->sfmt[j++].s = r;\n\tr1 = r2;\n\tr2 = r;\n    }\n}\n\n#ifndef ONLY64\n#if defined(__APPLE__)\n#define ALTI_SWAP (vector unsigned char) \\\n\t(4, 5, 6, 7, 0, 1, 2, 3, 12, 13, 14, 15, 8, 9, 10, 11)\n#else\n#define ALTI_SWAP {4, 5, 6, 7, 0, 1, 2, 3, 12, 13, 14, 15, 8, 9, 10, 11}\n#endif\n/**\n * This function swaps high and low 32-bit of 64-bit integers in user\n * specified array.\n *\n * @param array an 128-bit array to be swaped.\n * @param size size of 128-bit array.\n */\nJEMALLOC_INLINE void swap(w128_t *array, int size) {\n    int i;\n    const vector unsigned char perm = ALTI_SWAP;\n\n    for (i = 0; i < size; i++) {\n\tarray[i].s = vec_perm(array[i].s, (vector unsigned int)perm, perm);\n    }\n}\n#endif\n\n#endif\n"
  },
  {
    "path": "extern/deprecated/redis-2.8.21/deps/jemalloc/test/include/test/SFMT-params.h",
    "content": "/*\n * This file derives from SFMT 1.3.3\n * (http://www.math.sci.hiroshima-u.ac.jp/~m-mat/MT/SFMT/index.html), which was\n * released under the terms of the following license:\n *\n *   Copyright (c) 2006,2007 Mutsuo Saito, Makoto Matsumoto and Hiroshima\n *   University. All rights reserved.\n *\n *   Redistribution and use in source and binary forms, with or without\n *   modification, are permitted provided that the following conditions are\n *   met:\n *\n *       * Redistributions of source code must retain the above copyright\n *         notice, this list of conditions and the following disclaimer.\n *       * Redistributions in binary form must reproduce the above\n *         copyright notice, this list of conditions and the following\n *         disclaimer in the documentation and/or other materials provided\n *         with the distribution.\n *       * Neither the name of the Hiroshima University nor the names of\n *         its contributors may be used to endorse or promote products\n *         derived from this software without specific prior written\n *         permission.\n *\n *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n *   \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\n *   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\n *   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\n *   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n *   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\n *   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n *   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n *   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n *   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n *   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n#ifndef SFMT_PARAMS_H\n#define SFMT_PARAMS_H\n\n#if !defined(MEXP)\n#ifdef __GNUC__\n  #warning \"MEXP is not defined. I assume MEXP is 19937.\"\n#endif\n  #define MEXP 19937\n#endif\n/*-----------------\n  BASIC DEFINITIONS\n  -----------------*/\n/** Mersenne Exponent. The period of the sequence \n *  is a multiple of 2^MEXP-1.\n * #define MEXP 19937 */\n/** SFMT generator has an internal state array of 128-bit integers,\n * and N is its size. */\n#define N (MEXP / 128 + 1)\n/** N32 is the size of internal state array when regarded as an array\n * of 32-bit integers.*/\n#define N32 (N * 4)\n/** N64 is the size of internal state array when regarded as an array\n * of 64-bit integers.*/\n#define N64 (N * 2)\n\n/*----------------------\n  the parameters of SFMT\n  following definitions are in paramsXXXX.h file.\n  ----------------------*/\n/** the pick up position of the array.\n#define POS1 122 \n*/\n\n/** the parameter of shift left as four 32-bit registers.\n#define SL1 18\n */\n\n/** the parameter of shift left as one 128-bit register. \n * The 128-bit integer is shifted by (SL2 * 8) bits. \n#define SL2 1 \n*/\n\n/** the parameter of shift right as four 32-bit registers.\n#define SR1 11\n*/\n\n/** the parameter of shift right as one 128-bit register. \n * The 128-bit integer is shifted by (SL2 * 8) bits. \n#define SR2 1 \n*/\n\n/** A bitmask, used in the recursion.  These parameters are introduced\n * to break symmetry of SIMD.\n#define MSK1 0xdfffffefU\n#define MSK2 0xddfecb7fU\n#define MSK3 0xbffaffffU\n#define MSK4 0xbffffff6U \n*/\n\n/** These definitions are part of a 128-bit period certification vector.\n#define PARITY1\t0x00000001U\n#define PARITY2\t0x00000000U\n#define PARITY3\t0x00000000U\n#define PARITY4\t0xc98e126aU\n*/\n\n#if MEXP == 607\n  #include \"test/SFMT-params607.h\"\n#elif MEXP == 1279\n  #include \"test/SFMT-params1279.h\"\n#elif MEXP == 2281\n  #include \"test/SFMT-params2281.h\"\n#elif MEXP == 4253\n  #include \"test/SFMT-params4253.h\"\n#elif MEXP == 11213\n  #include \"test/SFMT-params11213.h\"\n#elif MEXP == 19937\n  #include \"test/SFMT-params19937.h\"\n#elif MEXP == 44497\n  #include \"test/SFMT-params44497.h\"\n#elif MEXP == 86243\n  #include \"test/SFMT-params86243.h\"\n#elif MEXP == 132049\n  #include \"test/SFMT-params132049.h\"\n#elif MEXP == 216091\n  #include \"test/SFMT-params216091.h\"\n#else\n#ifdef __GNUC__\n  #error \"MEXP is not valid.\"\n  #undef MEXP\n#else\n  #undef MEXP\n#endif\n\n#endif\n\n#endif /* SFMT_PARAMS_H */\n"
  },
  {
    "path": "extern/deprecated/redis-2.8.21/deps/jemalloc/test/include/test/SFMT-params11213.h",
    "content": "/*\n * This file derives from SFMT 1.3.3\n * (http://www.math.sci.hiroshima-u.ac.jp/~m-mat/MT/SFMT/index.html), which was\n * released under the terms of the following license:\n *\n *   Copyright (c) 2006,2007 Mutsuo Saito, Makoto Matsumoto and Hiroshima\n *   University. All rights reserved.\n *\n *   Redistribution and use in source and binary forms, with or without\n *   modification, are permitted provided that the following conditions are\n *   met:\n *\n *       * Redistributions of source code must retain the above copyright\n *         notice, this list of conditions and the following disclaimer.\n *       * Redistributions in binary form must reproduce the above\n *         copyright notice, this list of conditions and the following\n *         disclaimer in the documentation and/or other materials provided\n *         with the distribution.\n *       * Neither the name of the Hiroshima University nor the names of\n *         its contributors may be used to endorse or promote products\n *         derived from this software without specific prior written\n *         permission.\n *\n *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n *   \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\n *   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\n *   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\n *   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n *   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\n *   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n *   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n *   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n *   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n *   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n#ifndef SFMT_PARAMS11213_H\n#define SFMT_PARAMS11213_H\n\n#define POS1\t68\n#define SL1\t14\n#define SL2\t3\n#define SR1\t7\n#define SR2\t3\n#define MSK1\t0xeffff7fbU\n#define MSK2\t0xffffffefU\n#define MSK3\t0xdfdfbfffU\n#define MSK4\t0x7fffdbfdU\n#define PARITY1\t0x00000001U\n#define PARITY2\t0x00000000U\n#define PARITY3\t0xe8148000U\n#define PARITY4\t0xd0c7afa3U\n\n\n/* PARAMETERS FOR ALTIVEC */\n#if defined(__APPLE__)\t/* For OSX */\n    #define ALTI_SL1\t(vector unsigned int)(SL1, SL1, SL1, SL1)\n    #define ALTI_SR1\t(vector unsigned int)(SR1, SR1, SR1, SR1)\n    #define ALTI_MSK\t(vector unsigned int)(MSK1, MSK2, MSK3, MSK4)\n    #define ALTI_MSK64 \\\n\t(vector unsigned int)(MSK2, MSK1, MSK4, MSK3)\n    #define ALTI_SL2_PERM \\\n\t(vector unsigned char)(3,21,21,21,7,0,1,2,11,4,5,6,15,8,9,10)\n    #define ALTI_SL2_PERM64 \\\n\t(vector unsigned char)(3,4,5,6,7,29,29,29,11,12,13,14,15,0,1,2)\n    #define ALTI_SR2_PERM \\\n\t(vector unsigned char)(5,6,7,0,9,10,11,4,13,14,15,8,19,19,19,12)\n    #define ALTI_SR2_PERM64 \\\n\t(vector unsigned char)(13,14,15,0,1,2,3,4,19,19,19,8,9,10,11,12)\n#else\t/* For OTHER OSs(Linux?) */\n    #define ALTI_SL1\t{SL1, SL1, SL1, SL1}\n    #define ALTI_SR1\t{SR1, SR1, SR1, SR1}\n    #define ALTI_MSK\t{MSK1, MSK2, MSK3, MSK4}\n    #define ALTI_MSK64\t{MSK2, MSK1, MSK4, MSK3}\n    #define ALTI_SL2_PERM\t{3,21,21,21,7,0,1,2,11,4,5,6,15,8,9,10}\n    #define ALTI_SL2_PERM64\t{3,4,5,6,7,29,29,29,11,12,13,14,15,0,1,2}\n    #define ALTI_SR2_PERM\t{5,6,7,0,9,10,11,4,13,14,15,8,19,19,19,12}\n    #define ALTI_SR2_PERM64\t{13,14,15,0,1,2,3,4,19,19,19,8,9,10,11,12}\n#endif\t/* For OSX */\n#define IDSTR\t\"SFMT-11213:68-14-3-7-3:effff7fb-ffffffef-dfdfbfff-7fffdbfd\"\n\n#endif /* SFMT_PARAMS11213_H */\n"
  },
  {
    "path": "extern/deprecated/redis-2.8.21/deps/jemalloc/test/include/test/SFMT-params1279.h",
    "content": "/*\n * This file derives from SFMT 1.3.3\n * (http://www.math.sci.hiroshima-u.ac.jp/~m-mat/MT/SFMT/index.html), which was\n * released under the terms of the following license:\n *\n *   Copyright (c) 2006,2007 Mutsuo Saito, Makoto Matsumoto and Hiroshima\n *   University. All rights reserved.\n *\n *   Redistribution and use in source and binary forms, with or without\n *   modification, are permitted provided that the following conditions are\n *   met:\n *\n *       * Redistributions of source code must retain the above copyright\n *         notice, this list of conditions and the following disclaimer.\n *       * Redistributions in binary form must reproduce the above\n *         copyright notice, this list of conditions and the following\n *         disclaimer in the documentation and/or other materials provided\n *         with the distribution.\n *       * Neither the name of the Hiroshima University nor the names of\n *         its contributors may be used to endorse or promote products\n *         derived from this software without specific prior written\n *         permission.\n *\n *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n *   \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\n *   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\n *   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\n *   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n *   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\n *   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n *   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n *   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n *   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n *   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n#ifndef SFMT_PARAMS1279_H\n#define SFMT_PARAMS1279_H\n\n#define POS1\t7\n#define SL1\t14\n#define SL2\t3\n#define SR1\t5\n#define SR2\t1\n#define MSK1\t0xf7fefffdU\n#define MSK2\t0x7fefcfffU\n#define MSK3\t0xaff3ef3fU\n#define MSK4\t0xb5ffff7fU\n#define PARITY1\t0x00000001U\n#define PARITY2\t0x00000000U\n#define PARITY3\t0x00000000U\n#define PARITY4\t0x20000000U\n\n\n/* PARAMETERS FOR ALTIVEC */\n#if defined(__APPLE__)\t/* For OSX */\n    #define ALTI_SL1\t(vector unsigned int)(SL1, SL1, SL1, SL1)\n    #define ALTI_SR1\t(vector unsigned int)(SR1, SR1, SR1, SR1)\n    #define ALTI_MSK\t(vector unsigned int)(MSK1, MSK2, MSK3, MSK4)\n    #define ALTI_MSK64 \\\n\t(vector unsigned int)(MSK2, MSK1, MSK4, MSK3)\n    #define ALTI_SL2_PERM \\\n\t(vector unsigned char)(3,21,21,21,7,0,1,2,11,4,5,6,15,8,9,10)\n    #define ALTI_SL2_PERM64 \\\n\t(vector unsigned char)(3,4,5,6,7,29,29,29,11,12,13,14,15,0,1,2)\n    #define ALTI_SR2_PERM \\\n\t(vector unsigned char)(7,0,1,2,11,4,5,6,15,8,9,10,17,12,13,14)\n    #define ALTI_SR2_PERM64 \\\n\t(vector unsigned char)(15,0,1,2,3,4,5,6,17,8,9,10,11,12,13,14)\n#else\t/* For OTHER OSs(Linux?) */\n    #define ALTI_SL1\t{SL1, SL1, SL1, SL1}\n    #define ALTI_SR1\t{SR1, SR1, SR1, SR1}\n    #define ALTI_MSK\t{MSK1, MSK2, MSK3, MSK4}\n    #define ALTI_MSK64\t{MSK2, MSK1, MSK4, MSK3}\n    #define ALTI_SL2_PERM\t{3,21,21,21,7,0,1,2,11,4,5,6,15,8,9,10}\n    #define ALTI_SL2_PERM64\t{3,4,5,6,7,29,29,29,11,12,13,14,15,0,1,2}\n    #define ALTI_SR2_PERM\t{7,0,1,2,11,4,5,6,15,8,9,10,17,12,13,14}\n    #define ALTI_SR2_PERM64\t{15,0,1,2,3,4,5,6,17,8,9,10,11,12,13,14}\n#endif\t/* For OSX */\n#define IDSTR\t\"SFMT-1279:7-14-3-5-1:f7fefffd-7fefcfff-aff3ef3f-b5ffff7f\"\n\n#endif /* SFMT_PARAMS1279_H */\n"
  },
  {
    "path": "extern/deprecated/redis-2.8.21/deps/jemalloc/test/include/test/SFMT-params132049.h",
    "content": "/*\n * This file derives from SFMT 1.3.3\n * (http://www.math.sci.hiroshima-u.ac.jp/~m-mat/MT/SFMT/index.html), which was\n * released under the terms of the following license:\n *\n *   Copyright (c) 2006,2007 Mutsuo Saito, Makoto Matsumoto and Hiroshima\n *   University. All rights reserved.\n *\n *   Redistribution and use in source and binary forms, with or without\n *   modification, are permitted provided that the following conditions are\n *   met:\n *\n *       * Redistributions of source code must retain the above copyright\n *         notice, this list of conditions and the following disclaimer.\n *       * Redistributions in binary form must reproduce the above\n *         copyright notice, this list of conditions and the following\n *         disclaimer in the documentation and/or other materials provided\n *         with the distribution.\n *       * Neither the name of the Hiroshima University nor the names of\n *         its contributors may be used to endorse or promote products\n *         derived from this software without specific prior written\n *         permission.\n *\n *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n *   \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\n *   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\n *   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\n *   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n *   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\n *   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n *   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n *   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n *   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n *   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n#ifndef SFMT_PARAMS132049_H\n#define SFMT_PARAMS132049_H\n\n#define POS1\t110\n#define SL1\t19\n#define SL2\t1\n#define SR1\t21\n#define SR2\t1\n#define MSK1\t0xffffbb5fU\n#define MSK2\t0xfb6ebf95U\n#define MSK3\t0xfffefffaU\n#define MSK4\t0xcff77fffU\n#define PARITY1\t0x00000001U\n#define PARITY2\t0x00000000U\n#define PARITY3\t0xcb520000U\n#define PARITY4\t0xc7e91c7dU\n\n\n/* PARAMETERS FOR ALTIVEC */\n#if defined(__APPLE__)\t/* For OSX */\n    #define ALTI_SL1\t(vector unsigned int)(SL1, SL1, SL1, SL1)\n    #define ALTI_SR1\t(vector unsigned int)(SR1, SR1, SR1, SR1)\n    #define ALTI_MSK\t(vector unsigned int)(MSK1, MSK2, MSK3, MSK4)\n    #define ALTI_MSK64 \\\n\t(vector unsigned int)(MSK2, MSK1, MSK4, MSK3)\n    #define ALTI_SL2_PERM \\\n\t(vector unsigned char)(1,2,3,23,5,6,7,0,9,10,11,4,13,14,15,8)\n    #define ALTI_SL2_PERM64 \\\n\t(vector unsigned char)(1,2,3,4,5,6,7,31,9,10,11,12,13,14,15,0)\n    #define ALTI_SR2_PERM \\\n\t(vector unsigned char)(7,0,1,2,11,4,5,6,15,8,9,10,17,12,13,14)\n    #define ALTI_SR2_PERM64 \\\n\t(vector unsigned char)(15,0,1,2,3,4,5,6,17,8,9,10,11,12,13,14)\n#else\t/* For OTHER OSs(Linux?) */\n    #define ALTI_SL1\t{SL1, SL1, SL1, SL1}\n    #define ALTI_SR1\t{SR1, SR1, SR1, SR1}\n    #define ALTI_MSK\t{MSK1, MSK2, MSK3, MSK4}\n    #define ALTI_MSK64\t{MSK2, MSK1, MSK4, MSK3}\n    #define ALTI_SL2_PERM\t{1,2,3,23,5,6,7,0,9,10,11,4,13,14,15,8}\n    #define ALTI_SL2_PERM64\t{1,2,3,4,5,6,7,31,9,10,11,12,13,14,15,0}\n    #define ALTI_SR2_PERM\t{7,0,1,2,11,4,5,6,15,8,9,10,17,12,13,14}\n    #define ALTI_SR2_PERM64\t{15,0,1,2,3,4,5,6,17,8,9,10,11,12,13,14}\n#endif\t/* For OSX */\n#define IDSTR\t\"SFMT-132049:110-19-1-21-1:ffffbb5f-fb6ebf95-fffefffa-cff77fff\"\n\n#endif /* SFMT_PARAMS132049_H */\n"
  },
  {
    "path": "extern/deprecated/redis-2.8.21/deps/jemalloc/test/include/test/SFMT-params19937.h",
    "content": "/*\n * This file derives from SFMT 1.3.3\n * (http://www.math.sci.hiroshima-u.ac.jp/~m-mat/MT/SFMT/index.html), which was\n * released under the terms of the following license:\n *\n *   Copyright (c) 2006,2007 Mutsuo Saito, Makoto Matsumoto and Hiroshima\n *   University. All rights reserved.\n *\n *   Redistribution and use in source and binary forms, with or without\n *   modification, are permitted provided that the following conditions are\n *   met:\n *\n *       * Redistributions of source code must retain the above copyright\n *         notice, this list of conditions and the following disclaimer.\n *       * Redistributions in binary form must reproduce the above\n *         copyright notice, this list of conditions and the following\n *         disclaimer in the documentation and/or other materials provided\n *         with the distribution.\n *       * Neither the name of the Hiroshima University nor the names of\n *         its contributors may be used to endorse or promote products\n *         derived from this software without specific prior written\n *         permission.\n *\n *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n *   \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\n *   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\n *   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\n *   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n *   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\n *   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n *   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n *   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n *   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n *   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n#ifndef SFMT_PARAMS19937_H\n#define SFMT_PARAMS19937_H\n\n#define POS1\t122\n#define SL1\t18\n#define SL2\t1\n#define SR1\t11\n#define SR2\t1\n#define MSK1\t0xdfffffefU\n#define MSK2\t0xddfecb7fU\n#define MSK3\t0xbffaffffU\n#define MSK4\t0xbffffff6U\n#define PARITY1\t0x00000001U\n#define PARITY2\t0x00000000U\n#define PARITY3\t0x00000000U\n#define PARITY4\t0x13c9e684U\n\n\n/* PARAMETERS FOR ALTIVEC */\n#if defined(__APPLE__)\t/* For OSX */\n    #define ALTI_SL1\t(vector unsigned int)(SL1, SL1, SL1, SL1)\n    #define ALTI_SR1\t(vector unsigned int)(SR1, SR1, SR1, SR1)\n    #define ALTI_MSK\t(vector unsigned int)(MSK1, MSK2, MSK3, MSK4)\n    #define ALTI_MSK64 \\\n\t(vector unsigned int)(MSK2, MSK1, MSK4, MSK3)\n    #define ALTI_SL2_PERM \\\n\t(vector unsigned char)(1,2,3,23,5,6,7,0,9,10,11,4,13,14,15,8)\n    #define ALTI_SL2_PERM64 \\\n\t(vector unsigned char)(1,2,3,4,5,6,7,31,9,10,11,12,13,14,15,0)\n    #define ALTI_SR2_PERM \\\n\t(vector unsigned char)(7,0,1,2,11,4,5,6,15,8,9,10,17,12,13,14)\n    #define ALTI_SR2_PERM64 \\\n\t(vector unsigned char)(15,0,1,2,3,4,5,6,17,8,9,10,11,12,13,14)\n#else\t/* For OTHER OSs(Linux?) */\n    #define ALTI_SL1\t{SL1, SL1, SL1, SL1}\n    #define ALTI_SR1\t{SR1, SR1, SR1, SR1}\n    #define ALTI_MSK\t{MSK1, MSK2, MSK3, MSK4}\n    #define ALTI_MSK64\t{MSK2, MSK1, MSK4, MSK3}\n    #define ALTI_SL2_PERM\t{1,2,3,23,5,6,7,0,9,10,11,4,13,14,15,8}\n    #define ALTI_SL2_PERM64\t{1,2,3,4,5,6,7,31,9,10,11,12,13,14,15,0}\n    #define ALTI_SR2_PERM\t{7,0,1,2,11,4,5,6,15,8,9,10,17,12,13,14}\n    #define ALTI_SR2_PERM64\t{15,0,1,2,3,4,5,6,17,8,9,10,11,12,13,14}\n#endif\t/* For OSX */\n#define IDSTR\t\"SFMT-19937:122-18-1-11-1:dfffffef-ddfecb7f-bffaffff-bffffff6\"\n\n#endif /* SFMT_PARAMS19937_H */\n"
  },
  {
    "path": "extern/deprecated/redis-2.8.21/deps/jemalloc/test/include/test/SFMT-params216091.h",
    "content": "/*\n * This file derives from SFMT 1.3.3\n * (http://www.math.sci.hiroshima-u.ac.jp/~m-mat/MT/SFMT/index.html), which was\n * released under the terms of the following license:\n *\n *   Copyright (c) 2006,2007 Mutsuo Saito, Makoto Matsumoto and Hiroshima\n *   University. All rights reserved.\n *\n *   Redistribution and use in source and binary forms, with or without\n *   modification, are permitted provided that the following conditions are\n *   met:\n *\n *       * Redistributions of source code must retain the above copyright\n *         notice, this list of conditions and the following disclaimer.\n *       * Redistributions in binary form must reproduce the above\n *         copyright notice, this list of conditions and the following\n *         disclaimer in the documentation and/or other materials provided\n *         with the distribution.\n *       * Neither the name of the Hiroshima University nor the names of\n *         its contributors may be used to endorse or promote products\n *         derived from this software without specific prior written\n *         permission.\n *\n *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n *   \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\n *   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\n *   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\n *   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n *   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\n *   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n *   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n *   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n *   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n *   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n#ifndef SFMT_PARAMS216091_H\n#define SFMT_PARAMS216091_H\n\n#define POS1\t627\n#define SL1\t11\n#define SL2\t3\n#define SR1\t10\n#define SR2\t1\n#define MSK1\t0xbff7bff7U\n#define MSK2\t0xbfffffffU\n#define MSK3\t0xbffffa7fU\n#define MSK4\t0xffddfbfbU\n#define PARITY1\t0xf8000001U\n#define PARITY2\t0x89e80709U\n#define PARITY3\t0x3bd2b64bU\n#define PARITY4\t0x0c64b1e4U\n\n\n/* PARAMETERS FOR ALTIVEC */\n#if defined(__APPLE__)\t/* For OSX */\n    #define ALTI_SL1\t(vector unsigned int)(SL1, SL1, SL1, SL1)\n    #define ALTI_SR1\t(vector unsigned int)(SR1, SR1, SR1, SR1)\n    #define ALTI_MSK\t(vector unsigned int)(MSK1, MSK2, MSK3, MSK4)\n    #define ALTI_MSK64 \\\n\t(vector unsigned int)(MSK2, MSK1, MSK4, MSK3)\n    #define ALTI_SL2_PERM \\\n\t(vector unsigned char)(3,21,21,21,7,0,1,2,11,4,5,6,15,8,9,10)\n    #define ALTI_SL2_PERM64 \\\n\t(vector unsigned char)(3,4,5,6,7,29,29,29,11,12,13,14,15,0,1,2)\n    #define ALTI_SR2_PERM \\\n\t(vector unsigned char)(7,0,1,2,11,4,5,6,15,8,9,10,17,12,13,14)\n    #define ALTI_SR2_PERM64 \\\n\t(vector unsigned char)(15,0,1,2,3,4,5,6,17,8,9,10,11,12,13,14)\n#else\t/* For OTHER OSs(Linux?) */\n    #define ALTI_SL1\t{SL1, SL1, SL1, SL1}\n    #define ALTI_SR1\t{SR1, SR1, SR1, SR1}\n    #define ALTI_MSK\t{MSK1, MSK2, MSK3, MSK4}\n    #define ALTI_MSK64\t{MSK2, MSK1, MSK4, MSK3}\n    #define ALTI_SL2_PERM\t{3,21,21,21,7,0,1,2,11,4,5,6,15,8,9,10}\n    #define ALTI_SL2_PERM64\t{3,4,5,6,7,29,29,29,11,12,13,14,15,0,1,2}\n    #define ALTI_SR2_PERM\t{7,0,1,2,11,4,5,6,15,8,9,10,17,12,13,14}\n    #define ALTI_SR2_PERM64\t{15,0,1,2,3,4,5,6,17,8,9,10,11,12,13,14}\n#endif\t/* For OSX */\n#define IDSTR\t\"SFMT-216091:627-11-3-10-1:bff7bff7-bfffffff-bffffa7f-ffddfbfb\"\n\n#endif /* SFMT_PARAMS216091_H */\n"
  },
  {
    "path": "extern/deprecated/redis-2.8.21/deps/jemalloc/test/include/test/SFMT-params2281.h",
    "content": "/*\n * This file derives from SFMT 1.3.3\n * (http://www.math.sci.hiroshima-u.ac.jp/~m-mat/MT/SFMT/index.html), which was\n * released under the terms of the following license:\n *\n *   Copyright (c) 2006,2007 Mutsuo Saito, Makoto Matsumoto and Hiroshima\n *   University. All rights reserved.\n *\n *   Redistribution and use in source and binary forms, with or without\n *   modification, are permitted provided that the following conditions are\n *   met:\n *\n *       * Redistributions of source code must retain the above copyright\n *         notice, this list of conditions and the following disclaimer.\n *       * Redistributions in binary form must reproduce the above\n *         copyright notice, this list of conditions and the following\n *         disclaimer in the documentation and/or other materials provided\n *         with the distribution.\n *       * Neither the name of the Hiroshima University nor the names of\n *         its contributors may be used to endorse or promote products\n *         derived from this software without specific prior written\n *         permission.\n *\n *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n *   \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\n *   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\n *   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\n *   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n *   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\n *   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n *   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n *   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n *   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n *   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n#ifndef SFMT_PARAMS2281_H\n#define SFMT_PARAMS2281_H\n\n#define POS1\t12\n#define SL1\t19\n#define SL2\t1\n#define SR1\t5\n#define SR2\t1\n#define MSK1\t0xbff7ffbfU\n#define MSK2\t0xfdfffffeU\n#define MSK3\t0xf7ffef7fU\n#define MSK4\t0xf2f7cbbfU\n#define PARITY1\t0x00000001U\n#define PARITY2\t0x00000000U\n#define PARITY3\t0x00000000U\n#define PARITY4\t0x41dfa600U\n\n\n/* PARAMETERS FOR ALTIVEC */\n#if defined(__APPLE__)\t/* For OSX */\n    #define ALTI_SL1\t(vector unsigned int)(SL1, SL1, SL1, SL1)\n    #define ALTI_SR1\t(vector unsigned int)(SR1, SR1, SR1, SR1)\n    #define ALTI_MSK\t(vector unsigned int)(MSK1, MSK2, MSK3, MSK4)\n    #define ALTI_MSK64 \\\n\t(vector unsigned int)(MSK2, MSK1, MSK4, MSK3)\n    #define ALTI_SL2_PERM \\\n\t(vector unsigned char)(1,2,3,23,5,6,7,0,9,10,11,4,13,14,15,8)\n    #define ALTI_SL2_PERM64 \\\n\t(vector unsigned char)(1,2,3,4,5,6,7,31,9,10,11,12,13,14,15,0)\n    #define ALTI_SR2_PERM \\\n\t(vector unsigned char)(7,0,1,2,11,4,5,6,15,8,9,10,17,12,13,14)\n    #define ALTI_SR2_PERM64 \\\n\t(vector unsigned char)(15,0,1,2,3,4,5,6,17,8,9,10,11,12,13,14)\n#else\t/* For OTHER OSs(Linux?) */\n    #define ALTI_SL1\t{SL1, SL1, SL1, SL1}\n    #define ALTI_SR1\t{SR1, SR1, SR1, SR1}\n    #define ALTI_MSK\t{MSK1, MSK2, MSK3, MSK4}\n    #define ALTI_MSK64\t{MSK2, MSK1, MSK4, MSK3}\n    #define ALTI_SL2_PERM\t{1,2,3,23,5,6,7,0,9,10,11,4,13,14,15,8}\n    #define ALTI_SL2_PERM64\t{1,2,3,4,5,6,7,31,9,10,11,12,13,14,15,0}\n    #define ALTI_SR2_PERM\t{7,0,1,2,11,4,5,6,15,8,9,10,17,12,13,14}\n    #define ALTI_SR2_PERM64\t{15,0,1,2,3,4,5,6,17,8,9,10,11,12,13,14}\n#endif\t/* For OSX */\n#define IDSTR\t\"SFMT-2281:12-19-1-5-1:bff7ffbf-fdfffffe-f7ffef7f-f2f7cbbf\"\n\n#endif /* SFMT_PARAMS2281_H */\n"
  },
  {
    "path": "extern/deprecated/redis-2.8.21/deps/jemalloc/test/include/test/SFMT-params4253.h",
    "content": "/*\n * This file derives from SFMT 1.3.3\n * (http://www.math.sci.hiroshima-u.ac.jp/~m-mat/MT/SFMT/index.html), which was\n * released under the terms of the following license:\n *\n *   Copyright (c) 2006,2007 Mutsuo Saito, Makoto Matsumoto and Hiroshima\n *   University. All rights reserved.\n *\n *   Redistribution and use in source and binary forms, with or without\n *   modification, are permitted provided that the following conditions are\n *   met:\n *\n *       * Redistributions of source code must retain the above copyright\n *         notice, this list of conditions and the following disclaimer.\n *       * Redistributions in binary form must reproduce the above\n *         copyright notice, this list of conditions and the following\n *         disclaimer in the documentation and/or other materials provided\n *         with the distribution.\n *       * Neither the name of the Hiroshima University nor the names of\n *         its contributors may be used to endorse or promote products\n *         derived from this software without specific prior written\n *         permission.\n *\n *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n *   \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\n *   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\n *   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\n *   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n *   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\n *   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n *   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n *   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n *   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n *   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n#ifndef SFMT_PARAMS4253_H\n#define SFMT_PARAMS4253_H\n\n#define POS1\t17\n#define SL1\t20\n#define SL2\t1\n#define SR1\t7\n#define SR2\t1\n#define MSK1\t0x9f7bffffU\n#define MSK2\t0x9fffff5fU\n#define MSK3\t0x3efffffbU\n#define MSK4\t0xfffff7bbU\n#define PARITY1\t0xa8000001U\n#define PARITY2\t0xaf5390a3U\n#define PARITY3\t0xb740b3f8U\n#define PARITY4\t0x6c11486dU\n\n\n/* PARAMETERS FOR ALTIVEC */\n#if defined(__APPLE__)\t/* For OSX */\n    #define ALTI_SL1\t(vector unsigned int)(SL1, SL1, SL1, SL1)\n    #define ALTI_SR1\t(vector unsigned int)(SR1, SR1, SR1, SR1)\n    #define ALTI_MSK\t(vector unsigned int)(MSK1, MSK2, MSK3, MSK4)\n    #define ALTI_MSK64 \\\n\t(vector unsigned int)(MSK2, MSK1, MSK4, MSK3)\n    #define ALTI_SL2_PERM \\\n\t(vector unsigned char)(1,2,3,23,5,6,7,0,9,10,11,4,13,14,15,8)\n    #define ALTI_SL2_PERM64 \\\n\t(vector unsigned char)(1,2,3,4,5,6,7,31,9,10,11,12,13,14,15,0)\n    #define ALTI_SR2_PERM \\\n\t(vector unsigned char)(7,0,1,2,11,4,5,6,15,8,9,10,17,12,13,14)\n    #define ALTI_SR2_PERM64 \\\n\t(vector unsigned char)(15,0,1,2,3,4,5,6,17,8,9,10,11,12,13,14)\n#else\t/* For OTHER OSs(Linux?) */\n    #define ALTI_SL1\t{SL1, SL1, SL1, SL1}\n    #define ALTI_SR1\t{SR1, SR1, SR1, SR1}\n    #define ALTI_MSK\t{MSK1, MSK2, MSK3, MSK4}\n    #define ALTI_MSK64\t{MSK2, MSK1, MSK4, MSK3}\n    #define ALTI_SL2_PERM\t{1,2,3,23,5,6,7,0,9,10,11,4,13,14,15,8}\n    #define ALTI_SL2_PERM64\t{1,2,3,4,5,6,7,31,9,10,11,12,13,14,15,0}\n    #define ALTI_SR2_PERM\t{7,0,1,2,11,4,5,6,15,8,9,10,17,12,13,14}\n    #define ALTI_SR2_PERM64\t{15,0,1,2,3,4,5,6,17,8,9,10,11,12,13,14}\n#endif\t/* For OSX */\n#define IDSTR\t\"SFMT-4253:17-20-1-7-1:9f7bffff-9fffff5f-3efffffb-fffff7bb\"\n\n#endif /* SFMT_PARAMS4253_H */\n"
  },
  {
    "path": "extern/deprecated/redis-2.8.21/deps/jemalloc/test/include/test/SFMT-params44497.h",
    "content": "/*\n * This file derives from SFMT 1.3.3\n * (http://www.math.sci.hiroshima-u.ac.jp/~m-mat/MT/SFMT/index.html), which was\n * released under the terms of the following license:\n *\n *   Copyright (c) 2006,2007 Mutsuo Saito, Makoto Matsumoto and Hiroshima\n *   University. All rights reserved.\n *\n *   Redistribution and use in source and binary forms, with or without\n *   modification, are permitted provided that the following conditions are\n *   met:\n *\n *       * Redistributions of source code must retain the above copyright\n *         notice, this list of conditions and the following disclaimer.\n *       * Redistributions in binary form must reproduce the above\n *         copyright notice, this list of conditions and the following\n *         disclaimer in the documentation and/or other materials provided\n *         with the distribution.\n *       * Neither the name of the Hiroshima University nor the names of\n *         its contributors may be used to endorse or promote products\n *         derived from this software without specific prior written\n *         permission.\n *\n *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n *   \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\n *   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\n *   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\n *   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n *   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\n *   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n *   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n *   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n *   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n *   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n#ifndef SFMT_PARAMS44497_H\n#define SFMT_PARAMS44497_H\n\n#define POS1\t330\n#define SL1\t5\n#define SL2\t3\n#define SR1\t9\n#define SR2\t3\n#define MSK1\t0xeffffffbU\n#define MSK2\t0xdfbebfffU\n#define MSK3\t0xbfbf7befU\n#define MSK4\t0x9ffd7bffU\n#define PARITY1\t0x00000001U\n#define PARITY2\t0x00000000U\n#define PARITY3\t0xa3ac4000U\n#define PARITY4\t0xecc1327aU\n\n\n/* PARAMETERS FOR ALTIVEC */\n#if defined(__APPLE__)\t/* For OSX */\n    #define ALTI_SL1\t(vector unsigned int)(SL1, SL1, SL1, SL1)\n    #define ALTI_SR1\t(vector unsigned int)(SR1, SR1, SR1, SR1)\n    #define ALTI_MSK\t(vector unsigned int)(MSK1, MSK2, MSK3, MSK4)\n    #define ALTI_MSK64 \\\n\t(vector unsigned int)(MSK2, MSK1, MSK4, MSK3)\n    #define ALTI_SL2_PERM \\\n\t(vector unsigned char)(3,21,21,21,7,0,1,2,11,4,5,6,15,8,9,10)\n    #define ALTI_SL2_PERM64 \\\n\t(vector unsigned char)(3,4,5,6,7,29,29,29,11,12,13,14,15,0,1,2)\n    #define ALTI_SR2_PERM \\\n\t(vector unsigned char)(5,6,7,0,9,10,11,4,13,14,15,8,19,19,19,12)\n    #define ALTI_SR2_PERM64 \\\n\t(vector unsigned char)(13,14,15,0,1,2,3,4,19,19,19,8,9,10,11,12)\n#else\t/* For OTHER OSs(Linux?) */\n    #define ALTI_SL1\t{SL1, SL1, SL1, SL1}\n    #define ALTI_SR1\t{SR1, SR1, SR1, SR1}\n    #define ALTI_MSK\t{MSK1, MSK2, MSK3, MSK4}\n    #define ALTI_MSK64\t{MSK2, MSK1, MSK4, MSK3}\n    #define ALTI_SL2_PERM\t{3,21,21,21,7,0,1,2,11,4,5,6,15,8,9,10}\n    #define ALTI_SL2_PERM64\t{3,4,5,6,7,29,29,29,11,12,13,14,15,0,1,2}\n    #define ALTI_SR2_PERM\t{5,6,7,0,9,10,11,4,13,14,15,8,19,19,19,12}\n    #define ALTI_SR2_PERM64\t{13,14,15,0,1,2,3,4,19,19,19,8,9,10,11,12}\n#endif\t/* For OSX */\n#define IDSTR\t\"SFMT-44497:330-5-3-9-3:effffffb-dfbebfff-bfbf7bef-9ffd7bff\"\n\n#endif /* SFMT_PARAMS44497_H */\n"
  },
  {
    "path": "extern/deprecated/redis-2.8.21/deps/jemalloc/test/include/test/SFMT-params607.h",
    "content": "/*\n * This file derives from SFMT 1.3.3\n * (http://www.math.sci.hiroshima-u.ac.jp/~m-mat/MT/SFMT/index.html), which was\n * released under the terms of the following license:\n *\n *   Copyright (c) 2006,2007 Mutsuo Saito, Makoto Matsumoto and Hiroshima\n *   University. All rights reserved.\n *\n *   Redistribution and use in source and binary forms, with or without\n *   modification, are permitted provided that the following conditions are\n *   met:\n *\n *       * Redistributions of source code must retain the above copyright\n *         notice, this list of conditions and the following disclaimer.\n *       * Redistributions in binary form must reproduce the above\n *         copyright notice, this list of conditions and the following\n *         disclaimer in the documentation and/or other materials provided\n *         with the distribution.\n *       * Neither the name of the Hiroshima University nor the names of\n *         its contributors may be used to endorse or promote products\n *         derived from this software without specific prior written\n *         permission.\n *\n *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n *   \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\n *   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\n *   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\n *   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n *   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\n *   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n *   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n *   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n *   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n *   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n#ifndef SFMT_PARAMS607_H\n#define SFMT_PARAMS607_H\n\n#define POS1\t2\n#define SL1\t15\n#define SL2\t3\n#define SR1\t13\n#define SR2\t3\n#define MSK1\t0xfdff37ffU\n#define MSK2\t0xef7f3f7dU\n#define MSK3\t0xff777b7dU\n#define MSK4\t0x7ff7fb2fU\n#define PARITY1\t0x00000001U\n#define PARITY2\t0x00000000U\n#define PARITY3\t0x00000000U\n#define PARITY4\t0x5986f054U\n\n\n/* PARAMETERS FOR ALTIVEC */\n#if defined(__APPLE__)\t/* For OSX */\n    #define ALTI_SL1\t(vector unsigned int)(SL1, SL1, SL1, SL1)\n    #define ALTI_SR1\t(vector unsigned int)(SR1, SR1, SR1, SR1)\n    #define ALTI_MSK\t(vector unsigned int)(MSK1, MSK2, MSK3, MSK4)\n    #define ALTI_MSK64 \\\n\t(vector unsigned int)(MSK2, MSK1, MSK4, MSK3)\n    #define ALTI_SL2_PERM \\\n\t(vector unsigned char)(3,21,21,21,7,0,1,2,11,4,5,6,15,8,9,10)\n    #define ALTI_SL2_PERM64 \\\n\t(vector unsigned char)(3,4,5,6,7,29,29,29,11,12,13,14,15,0,1,2)\n    #define ALTI_SR2_PERM \\\n\t(vector unsigned char)(5,6,7,0,9,10,11,4,13,14,15,8,19,19,19,12)\n    #define ALTI_SR2_PERM64 \\\n\t(vector unsigned char)(13,14,15,0,1,2,3,4,19,19,19,8,9,10,11,12)\n#else\t/* For OTHER OSs(Linux?) */\n    #define ALTI_SL1\t{SL1, SL1, SL1, SL1}\n    #define ALTI_SR1\t{SR1, SR1, SR1, SR1}\n    #define ALTI_MSK\t{MSK1, MSK2, MSK3, MSK4}\n    #define ALTI_MSK64\t{MSK2, MSK1, MSK4, MSK3}\n    #define ALTI_SL2_PERM\t{3,21,21,21,7,0,1,2,11,4,5,6,15,8,9,10}\n    #define ALTI_SL2_PERM64\t{3,4,5,6,7,29,29,29,11,12,13,14,15,0,1,2}\n    #define ALTI_SR2_PERM\t{5,6,7,0,9,10,11,4,13,14,15,8,19,19,19,12}\n    #define ALTI_SR2_PERM64\t{13,14,15,0,1,2,3,4,19,19,19,8,9,10,11,12}\n#endif\t/* For OSX */\n#define IDSTR\t\"SFMT-607:2-15-3-13-3:fdff37ff-ef7f3f7d-ff777b7d-7ff7fb2f\"\n\n#endif /* SFMT_PARAMS607_H */\n"
  },
  {
    "path": "extern/deprecated/redis-2.8.21/deps/jemalloc/test/include/test/SFMT-params86243.h",
    "content": "/*\n * This file derives from SFMT 1.3.3\n * (http://www.math.sci.hiroshima-u.ac.jp/~m-mat/MT/SFMT/index.html), which was\n * released under the terms of the following license:\n *\n *   Copyright (c) 2006,2007 Mutsuo Saito, Makoto Matsumoto and Hiroshima\n *   University. All rights reserved.\n *\n *   Redistribution and use in source and binary forms, with or without\n *   modification, are permitted provided that the following conditions are\n *   met:\n *\n *       * Redistributions of source code must retain the above copyright\n *         notice, this list of conditions and the following disclaimer.\n *       * Redistributions in binary form must reproduce the above\n *         copyright notice, this list of conditions and the following\n *         disclaimer in the documentation and/or other materials provided\n *         with the distribution.\n *       * Neither the name of the Hiroshima University nor the names of\n *         its contributors may be used to endorse or promote products\n *         derived from this software without specific prior written\n *         permission.\n *\n *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n *   \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\n *   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\n *   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\n *   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n *   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\n *   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n *   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n *   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n *   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n *   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n#ifndef SFMT_PARAMS86243_H\n#define SFMT_PARAMS86243_H\n\n#define POS1\t366\n#define SL1\t6\n#define SL2\t7\n#define SR1\t19\n#define SR2\t1\n#define MSK1\t0xfdbffbffU\n#define MSK2\t0xbff7ff3fU\n#define MSK3\t0xfd77efffU\n#define MSK4\t0xbf9ff3ffU\n#define PARITY1\t0x00000001U\n#define PARITY2\t0x00000000U\n#define PARITY3\t0x00000000U\n#define PARITY4\t0xe9528d85U\n\n\n/* PARAMETERS FOR ALTIVEC */\n#if defined(__APPLE__)\t/* For OSX */\n    #define ALTI_SL1\t(vector unsigned int)(SL1, SL1, SL1, SL1)\n    #define ALTI_SR1\t(vector unsigned int)(SR1, SR1, SR1, SR1)\n    #define ALTI_MSK\t(vector unsigned int)(MSK1, MSK2, MSK3, MSK4)\n    #define ALTI_MSK64 \\\n\t(vector unsigned int)(MSK2, MSK1, MSK4, MSK3)\n    #define ALTI_SL2_PERM \\\n\t(vector unsigned char)(25,25,25,25,3,25,25,25,7,0,1,2,11,4,5,6)\n    #define ALTI_SL2_PERM64 \\\n\t(vector unsigned char)(7,25,25,25,25,25,25,25,15,0,1,2,3,4,5,6)\n    #define ALTI_SR2_PERM \\\n\t(vector unsigned char)(7,0,1,2,11,4,5,6,15,8,9,10,17,12,13,14)\n    #define ALTI_SR2_PERM64 \\\n\t(vector unsigned char)(15,0,1,2,3,4,5,6,17,8,9,10,11,12,13,14)\n#else\t/* For OTHER OSs(Linux?) */\n    #define ALTI_SL1\t{SL1, SL1, SL1, SL1}\n    #define ALTI_SR1\t{SR1, SR1, SR1, SR1}\n    #define ALTI_MSK\t{MSK1, MSK2, MSK3, MSK4}\n    #define ALTI_MSK64\t{MSK2, MSK1, MSK4, MSK3}\n    #define ALTI_SL2_PERM\t{25,25,25,25,3,25,25,25,7,0,1,2,11,4,5,6}\n    #define ALTI_SL2_PERM64\t{7,25,25,25,25,25,25,25,15,0,1,2,3,4,5,6}\n    #define ALTI_SR2_PERM\t{7,0,1,2,11,4,5,6,15,8,9,10,17,12,13,14}\n    #define ALTI_SR2_PERM64\t{15,0,1,2,3,4,5,6,17,8,9,10,11,12,13,14}\n#endif\t/* For OSX */\n#define IDSTR\t\"SFMT-86243:366-6-7-19-1:fdbffbff-bff7ff3f-fd77efff-bf9ff3ff\"\n\n#endif /* SFMT_PARAMS86243_H */\n"
  },
  {
    "path": "extern/deprecated/redis-2.8.21/deps/jemalloc/test/include/test/SFMT-sse2.h",
    "content": "/*\n * This file derives from SFMT 1.3.3\n * (http://www.math.sci.hiroshima-u.ac.jp/~m-mat/MT/SFMT/index.html), which was\n * released under the terms of the following license:\n *\n *   Copyright (c) 2006,2007 Mutsuo Saito, Makoto Matsumoto and Hiroshima\n *   University. All rights reserved.\n *\n *   Redistribution and use in source and binary forms, with or without\n *   modification, are permitted provided that the following conditions are\n *   met:\n *\n *       * Redistributions of source code must retain the above copyright\n *         notice, this list of conditions and the following disclaimer.\n *       * Redistributions in binary form must reproduce the above\n *         copyright notice, this list of conditions and the following\n *         disclaimer in the documentation and/or other materials provided\n *         with the distribution.\n *       * Neither the name of the Hiroshima University nor the names of\n *         its contributors may be used to endorse or promote products\n *         derived from this software without specific prior written\n *         permission.\n *\n *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n *   \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\n *   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\n *   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\n *   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n *   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\n *   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n *   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n *   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n *   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n *   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n/** \n * @file  SFMT-sse2.h\n * @brief SIMD oriented Fast Mersenne Twister(SFMT) for Intel SSE2\n *\n * @author Mutsuo Saito (Hiroshima University)\n * @author Makoto Matsumoto (Hiroshima University)\n *\n * @note We assume LITTLE ENDIAN in this file\n *\n * Copyright (C) 2006, 2007 Mutsuo Saito, Makoto Matsumoto and Hiroshima\n * University. All rights reserved.\n *\n * The new BSD License is applied to this software, see LICENSE.txt\n */\n\n#ifndef SFMT_SSE2_H\n#define SFMT_SSE2_H\n\n/**\n * This function represents the recursion formula.\n * @param a a 128-bit part of the interal state array\n * @param b a 128-bit part of the interal state array\n * @param c a 128-bit part of the interal state array\n * @param d a 128-bit part of the interal state array\n * @param mask 128-bit mask\n * @return output\n */\nJEMALLOC_ALWAYS_INLINE __m128i mm_recursion(__m128i *a, __m128i *b, \n\t\t\t\t   __m128i c, __m128i d, __m128i mask) {\n    __m128i v, x, y, z;\n    \n    x = _mm_load_si128(a);\n    y = _mm_srli_epi32(*b, SR1);\n    z = _mm_srli_si128(c, SR2);\n    v = _mm_slli_epi32(d, SL1);\n    z = _mm_xor_si128(z, x);\n    z = _mm_xor_si128(z, v);\n    x = _mm_slli_si128(x, SL2);\n    y = _mm_and_si128(y, mask);\n    z = _mm_xor_si128(z, x);\n    z = _mm_xor_si128(z, y);\n    return z;\n}\n\n/**\n * This function fills the internal state array with pseudorandom\n * integers.\n */\nJEMALLOC_INLINE void gen_rand_all(sfmt_t *ctx) {\n    int i;\n    __m128i r, r1, r2, mask;\n    mask = _mm_set_epi32(MSK4, MSK3, MSK2, MSK1);\n\n    r1 = _mm_load_si128(&ctx->sfmt[N - 2].si);\n    r2 = _mm_load_si128(&ctx->sfmt[N - 1].si);\n    for (i = 0; i < N - POS1; i++) {\n\tr = mm_recursion(&ctx->sfmt[i].si, &ctx->sfmt[i + POS1].si, r1, r2,\n\t  mask);\n\t_mm_store_si128(&ctx->sfmt[i].si, r);\n\tr1 = r2;\n\tr2 = r;\n    }\n    for (; i < N; i++) {\n\tr = mm_recursion(&ctx->sfmt[i].si, &ctx->sfmt[i + POS1 - N].si, r1, r2,\n\t  mask);\n\t_mm_store_si128(&ctx->sfmt[i].si, r);\n\tr1 = r2;\n\tr2 = r;\n    }\n}\n\n/**\n * This function fills the user-specified array with pseudorandom\n * integers.\n *\n * @param array an 128-bit array to be filled by pseudorandom numbers.  \n * @param size number of 128-bit pesudorandom numbers to be generated.\n */\nJEMALLOC_INLINE void gen_rand_array(sfmt_t *ctx, w128_t *array, int size) {\n    int i, j;\n    __m128i r, r1, r2, mask;\n    mask = _mm_set_epi32(MSK4, MSK3, MSK2, MSK1);\n\n    r1 = _mm_load_si128(&ctx->sfmt[N - 2].si);\n    r2 = _mm_load_si128(&ctx->sfmt[N - 1].si);\n    for (i = 0; i < N - POS1; i++) {\n\tr = mm_recursion(&ctx->sfmt[i].si, &ctx->sfmt[i + POS1].si, r1, r2,\n\t  mask);\n\t_mm_store_si128(&array[i].si, r);\n\tr1 = r2;\n\tr2 = r;\n    }\n    for (; i < N; i++) {\n\tr = mm_recursion(&ctx->sfmt[i].si, &array[i + POS1 - N].si, r1, r2,\n\t  mask);\n\t_mm_store_si128(&array[i].si, r);\n\tr1 = r2;\n\tr2 = r;\n    }\n    /* main loop */\n    for (; i < size - N; i++) {\n\tr = mm_recursion(&array[i - N].si, &array[i + POS1 - N].si, r1, r2,\n\t\t\t mask);\n\t_mm_store_si128(&array[i].si, r);\n\tr1 = r2;\n\tr2 = r;\n    }\n    for (j = 0; j < 2 * N - size; j++) {\n\tr = _mm_load_si128(&array[j + size - N].si);\n\t_mm_store_si128(&ctx->sfmt[j].si, r);\n    }\n    for (; i < size; i++) {\n\tr = mm_recursion(&array[i - N].si, &array[i + POS1 - N].si, r1, r2,\n\t\t\t mask);\n\t_mm_store_si128(&array[i].si, r);\n\t_mm_store_si128(&ctx->sfmt[j++].si, r);\n\tr1 = r2;\n\tr2 = r;\n    }\n}\n\n#endif\n"
  },
  {
    "path": "extern/deprecated/redis-2.8.21/deps/jemalloc/test/include/test/SFMT.h",
    "content": "/*\n * This file derives from SFMT 1.3.3\n * (http://www.math.sci.hiroshima-u.ac.jp/~m-mat/MT/SFMT/index.html), which was\n * released under the terms of the following license:\n *\n *   Copyright (c) 2006,2007 Mutsuo Saito, Makoto Matsumoto and Hiroshima\n *   University. All rights reserved.\n *\n *   Redistribution and use in source and binary forms, with or without\n *   modification, are permitted provided that the following conditions are\n *   met:\n *\n *       * Redistributions of source code must retain the above copyright\n *         notice, this list of conditions and the following disclaimer.\n *       * Redistributions in binary form must reproduce the above\n *         copyright notice, this list of conditions and the following\n *         disclaimer in the documentation and/or other materials provided\n *         with the distribution.\n *       * Neither the name of the Hiroshima University nor the names of\n *         its contributors may be used to endorse or promote products\n *         derived from this software without specific prior written\n *         permission.\n *\n *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n *   \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\n *   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\n *   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\n *   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n *   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\n *   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n *   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n *   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n *   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n *   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n/** \n * @file SFMT.h \n *\n * @brief SIMD oriented Fast Mersenne Twister(SFMT) pseudorandom\n * number generator\n *\n * @author Mutsuo Saito (Hiroshima University)\n * @author Makoto Matsumoto (Hiroshima University)\n *\n * Copyright (C) 2006, 2007 Mutsuo Saito, Makoto Matsumoto and Hiroshima\n * University. All rights reserved.\n *\n * The new BSD License is applied to this software.\n * see LICENSE.txt\n *\n * @note We assume that your system has inttypes.h.  If your system\n * doesn't have inttypes.h, you have to typedef uint32_t and uint64_t,\n * and you have to define PRIu64 and PRIx64 in this file as follows:\n * @verbatim\n typedef unsigned int uint32_t\n typedef unsigned long long uint64_t  \n #define PRIu64 \"llu\"\n #define PRIx64 \"llx\"\n@endverbatim\n * uint32_t must be exactly 32-bit unsigned integer type (no more, no\n * less), and uint64_t must be exactly 64-bit unsigned integer type.\n * PRIu64 and PRIx64 are used for printf function to print 64-bit\n * unsigned int and 64-bit unsigned int in hexadecimal format.\n */\n\n#ifndef SFMT_H\n#define SFMT_H\n\ntypedef struct sfmt_s sfmt_t;\n\nuint32_t gen_rand32(sfmt_t *ctx);\nuint32_t gen_rand32_range(sfmt_t *ctx, uint32_t limit);\nuint64_t gen_rand64(sfmt_t *ctx);\nuint64_t gen_rand64_range(sfmt_t *ctx, uint64_t limit);\nvoid fill_array32(sfmt_t *ctx, uint32_t *array, int size);\nvoid fill_array64(sfmt_t *ctx, uint64_t *array, int size);\nsfmt_t *init_gen_rand(uint32_t seed);\nsfmt_t *init_by_array(uint32_t *init_key, int key_length);\nvoid fini_gen_rand(sfmt_t *ctx);\nconst char *get_idstring(void);\nint get_min_array_size32(void);\nint get_min_array_size64(void);\n\n#ifndef JEMALLOC_ENABLE_INLINE\ndouble to_real1(uint32_t v);\ndouble genrand_real1(sfmt_t *ctx);\ndouble to_real2(uint32_t v);\ndouble genrand_real2(sfmt_t *ctx);\ndouble to_real3(uint32_t v);\ndouble genrand_real3(sfmt_t *ctx);\ndouble to_res53(uint64_t v);\ndouble to_res53_mix(uint32_t x, uint32_t y);\ndouble genrand_res53(sfmt_t *ctx);\ndouble genrand_res53_mix(sfmt_t *ctx);\n#endif\n\n#if (defined(JEMALLOC_ENABLE_INLINE) || defined(SFMT_C_))\n/* These real versions are due to Isaku Wada */\n/** generates a random number on [0,1]-real-interval */\nJEMALLOC_INLINE double to_real1(uint32_t v)\n{\n    return v * (1.0/4294967295.0); \n    /* divided by 2^32-1 */ \n}\n\n/** generates a random number on [0,1]-real-interval */\nJEMALLOC_INLINE double genrand_real1(sfmt_t *ctx)\n{\n    return to_real1(gen_rand32(ctx));\n}\n\n/** generates a random number on [0,1)-real-interval */\nJEMALLOC_INLINE double to_real2(uint32_t v)\n{\n    return v * (1.0/4294967296.0); \n    /* divided by 2^32 */\n}\n\n/** generates a random number on [0,1)-real-interval */\nJEMALLOC_INLINE double genrand_real2(sfmt_t *ctx)\n{\n    return to_real2(gen_rand32(ctx));\n}\n\n/** generates a random number on (0,1)-real-interval */\nJEMALLOC_INLINE double to_real3(uint32_t v)\n{\n    return (((double)v) + 0.5)*(1.0/4294967296.0); \n    /* divided by 2^32 */\n}\n\n/** generates a random number on (0,1)-real-interval */\nJEMALLOC_INLINE double genrand_real3(sfmt_t *ctx)\n{\n    return to_real3(gen_rand32(ctx));\n}\n/** These real versions are due to Isaku Wada */\n\n/** generates a random number on [0,1) with 53-bit resolution*/\nJEMALLOC_INLINE double to_res53(uint64_t v) \n{ \n    return v * (1.0/18446744073709551616.0L);\n}\n\n/** generates a random number on [0,1) with 53-bit resolution from two\n * 32 bit integers */\nJEMALLOC_INLINE double to_res53_mix(uint32_t x, uint32_t y) \n{ \n    return to_res53(x | ((uint64_t)y << 32));\n}\n\n/** generates a random number on [0,1) with 53-bit resolution\n */\nJEMALLOC_INLINE double genrand_res53(sfmt_t *ctx) \n{ \n    return to_res53(gen_rand64(ctx));\n} \n\n/** generates a random number on [0,1) with 53-bit resolution\n    using 32bit integer.\n */\nJEMALLOC_INLINE double genrand_res53_mix(sfmt_t *ctx) \n{ \n    uint32_t x, y;\n\n    x = gen_rand32(ctx);\n    y = gen_rand32(ctx);\n    return to_res53_mix(x, y);\n} \n#endif\n#endif\n"
  },
  {
    "path": "extern/deprecated/redis-2.8.21/deps/jemalloc/test/include/test/jemalloc_test.h.in",
    "content": "#include <stdlib.h>\n#include <stdarg.h>\n#include <stdbool.h>\n#include <errno.h>\n#include <inttypes.h>\n#include <math.h>\n#include <string.h>\n\n#ifdef _WIN32\n#  include <windows.h>\n#else\n#  include <pthread.h>\n#endif\n\n/******************************************************************************/\n/*\n * Define always-enabled assertion macros, so that test assertions execute even\n * if assertions are disabled in the library code.  These definitions must\n * exist prior to including \"jemalloc/internal/util.h\".\n */\n#define\tassert(e) do {\t\t\t\t\t\t\t\\\n\tif (!(e)) {\t\t\t\t\t\t\t\\\n\t\tmalloc_printf(\t\t\t\t\t\t\\\n\t\t    \"<jemalloc>: %s:%d: Failed assertion: \\\"%s\\\"\\n\",\t\\\n\t\t    __FILE__, __LINE__, #e);\t\t\t\t\\\n\t\tabort();\t\t\t\t\t\t\\\n\t}\t\t\t\t\t\t\t\t\\\n} while (0)\n\n#define\tnot_reached() do {\t\t\t\t\t\t\\\n\tmalloc_printf(\t\t\t\t\t\t\t\\\n\t    \"<jemalloc>: %s:%d: Unreachable code reached\\n\",\t\t\\\n\t    __FILE__, __LINE__);\t\t\t\t\t\\\n\tabort();\t\t\t\t\t\t\t\\\n} while (0)\n\n#define\tnot_implemented() do {\t\t\t\t\t\t\\\n\tmalloc_printf(\"<jemalloc>: %s:%d: Not implemented\\n\",\t\t\\\n\t    __FILE__, __LINE__);\t\t\t\t\t\\\n\tabort();\t\t\t\t\t\t\t\\\n} while (0)\n\n#define\tassert_not_implemented(e) do {\t\t\t\t\t\\\n\tif (!(e))\t\t\t\t\t\t\t\\\n\t\tnot_implemented();\t\t\t\t\t\\\n} while (0)\n\n#include \"test/jemalloc_test_defs.h\"\n\n#ifdef JEMALLOC_OSSPIN\n#  include <libkern/OSAtomic.h>\n#endif\n\n#if defined(HAVE_ALTIVEC) && !defined(__APPLE__)\n#  include <altivec.h>\n#endif\n#ifdef HAVE_SSE2\n#  include <emmintrin.h>\n#endif\n\n/******************************************************************************/\n/*\n * For unit tests, expose all public and private interfaces.\n */\n#ifdef JEMALLOC_UNIT_TEST\n#  define JEMALLOC_JET\n#  define JEMALLOC_MANGLE\n#  include \"jemalloc/internal/jemalloc_internal.h\"\n\n/******************************************************************************/\n/*\n * For integration tests, expose the public jemalloc interfaces, but only\n * expose the minimum necessary internal utility code (to avoid re-implementing\n * essentially identical code within the test infrastructure).\n */\n#elif defined(JEMALLOC_INTEGRATION_TEST)\n#  define JEMALLOC_MANGLE\n#  include \"jemalloc/jemalloc@install_suffix@.h\"\n#  include \"jemalloc/internal/jemalloc_internal_defs.h\"\n#  include \"jemalloc/internal/jemalloc_internal_macros.h\"\n\n#  define JEMALLOC_N(n) @private_namespace@##n\n#  include \"jemalloc/internal/private_namespace.h\"\n\n#  define JEMALLOC_H_TYPES\n#  define JEMALLOC_H_STRUCTS\n#  define JEMALLOC_H_EXTERNS\n#  define JEMALLOC_H_INLINES\n#  include \"jemalloc/internal/util.h\"\n#  include \"jemalloc/internal/qr.h\"\n#  include \"jemalloc/internal/ql.h\"\n#  undef JEMALLOC_H_TYPES\n#  undef JEMALLOC_H_STRUCTS\n#  undef JEMALLOC_H_EXTERNS\n#  undef JEMALLOC_H_INLINES\n\n/******************************************************************************/\n/*\n * For stress tests, expose the public jemalloc interfaces with name mangling\n * so that they can be tested as e.g. malloc() and free().  Also expose the\n * public jemalloc interfaces with jet_ prefixes, so that stress tests can use\n * a separate allocator for their internal data structures.\n */\n#elif defined(JEMALLOC_STRESS_TEST)\n#  include \"jemalloc/jemalloc@install_suffix@.h\"\n\n#  include \"jemalloc/jemalloc_protos_jet.h\"\n\n#  define JEMALLOC_JET\n#  include \"jemalloc/internal/jemalloc_internal.h\"\n#  include \"jemalloc/internal/public_unnamespace.h\"\n#  undef JEMALLOC_JET\n\n#  include \"jemalloc/jemalloc_rename.h\"\n#  define JEMALLOC_MANGLE\n#  ifdef JEMALLOC_STRESS_TESTLIB\n#    include \"jemalloc/jemalloc_mangle_jet.h\"\n#  else\n#    include \"jemalloc/jemalloc_mangle.h\"\n#  endif\n\n/******************************************************************************/\n/*\n * This header does dangerous things, the effects of which only test code\n * should be subject to.\n */\n#else\n#  error \"This header cannot be included outside a testing context\"\n#endif\n\n/******************************************************************************/\n/*\n * Common test utilities.\n */\n#include \"test/math.h\"\n#include \"test/mtx.h\"\n#include \"test/mq.h\"\n#include \"test/test.h\"\n#include \"test/thd.h\"\n#define\tMEXP 19937\n#include \"test/SFMT.h\"\n"
  },
  {
    "path": "extern/deprecated/redis-2.8.21/deps/jemalloc/test/include/test/jemalloc_test_defs.h.in",
    "content": "#include \"jemalloc/internal/jemalloc_internal_defs.h\"\n\n/* For use by SFMT. */\n#undef HAVE_SSE2\n#undef HAVE_ALTIVEC\n"
  },
  {
    "path": "extern/deprecated/redis-2.8.21/deps/jemalloc/test/include/test/math.h",
    "content": "#ifndef JEMALLOC_ENABLE_INLINE\ndouble\tln_gamma(double x);\ndouble\ti_gamma(double x, double p, double ln_gamma_p);\ndouble\tpt_norm(double p);\ndouble\tpt_chi2(double p, double df, double ln_gamma_df_2);\ndouble\tpt_gamma(double p, double shape, double scale, double ln_gamma_shape);\n#endif\n\n#if (defined(JEMALLOC_ENABLE_INLINE) || defined(MATH_C_))\n/*\n * Compute the natural log of Gamma(x), accurate to 10 decimal places.\n *\n * This implementation is based on:\n *\n *   Pike, M.C., I.D. Hill (1966) Algorithm 291: Logarithm of Gamma function\n *   [S14].  Communications of the ACM 9(9):684.\n */\nJEMALLOC_INLINE double\nln_gamma(double x)\n{\n\tdouble f, z;\n\n\tassert(x > 0.0);\n\n\tif (x < 7.0) {\n\t\tf = 1.0;\n\t\tz = x;\n\t\twhile (z < 7.0) {\n\t\t\tf *= z;\n\t\t\tz += 1.0;\n\t\t}\n\t\tx = z;\n\t\tf = -log(f);\n\t} else\n\t\tf = 0.0;\n\n\tz = 1.0 / (x * x);\n\n\treturn (f + (x-0.5) * log(x) - x + 0.918938533204673 +\n\t    (((-0.000595238095238 * z + 0.000793650793651) * z -\n\t    0.002777777777778) * z + 0.083333333333333) / x);\n}\n\n/*\n * Compute the incomplete Gamma ratio for [0..x], where p is the shape\n * parameter, and ln_gamma_p is ln_gamma(p).\n *\n * This implementation is based on:\n *\n *   Bhattacharjee, G.P. (1970) Algorithm AS 32: The incomplete Gamma integral.\n *   Applied Statistics 19:285-287.\n */\nJEMALLOC_INLINE double\ni_gamma(double x, double p, double ln_gamma_p)\n{\n\tdouble acu, factor, oflo, gin, term, rn, a, b, an, dif;\n\tdouble pn[6];\n\tunsigned i;\n\n\tassert(p > 0.0);\n\tassert(x >= 0.0);\n\n\tif (x == 0.0)\n\t\treturn (0.0);\n\n\tacu = 1.0e-10;\n\toflo = 1.0e30;\n\tgin = 0.0;\n\tfactor = exp(p * log(x) - x - ln_gamma_p);\n\n\tif (x <= 1.0 || x < p) {\n\t\t/* Calculation by series expansion. */\n\t\tgin = 1.0;\n\t\tterm = 1.0;\n\t\trn = p;\n\n\t\twhile (true) {\n\t\t\trn += 1.0;\n\t\t\tterm *= x / rn;\n\t\t\tgin += term;\n\t\t\tif (term <= acu) {\n\t\t\t\tgin *= factor / p;\n\t\t\t\treturn (gin);\n\t\t\t}\n\t\t}\n\t} else {\n\t\t/* Calculation by continued fraction. */\n\t\ta = 1.0 - p;\n\t\tb = a + x + 1.0;\n\t\tterm = 0.0;\n\t\tpn[0] = 1.0;\n\t\tpn[1] = x;\n\t\tpn[2] = x + 1.0;\n\t\tpn[3] = x * b;\n\t\tgin = pn[2] / pn[3];\n\n\t\twhile (true) {\n\t\t\ta += 1.0;\n\t\t\tb += 2.0;\n\t\t\tterm += 1.0;\n\t\t\tan = a * term;\n\t\t\tfor (i = 0; i < 2; i++)\n\t\t\t\tpn[i+4] = b * pn[i+2] - an * pn[i];\n\t\t\tif (pn[5] != 0.0) {\n\t\t\t\trn = pn[4] / pn[5];\n\t\t\t\tdif = fabs(gin - rn);\n\t\t\t\tif (dif <= acu && dif <= acu * rn) {\n\t\t\t\t\tgin = 1.0 - factor * gin;\n\t\t\t\t\treturn (gin);\n\t\t\t\t}\n\t\t\t\tgin = rn;\n\t\t\t}\n\t\t\tfor (i = 0; i < 4; i++)\n\t\t\t\tpn[i] = pn[i+2];\n\n\t\t\tif (fabs(pn[4]) >= oflo) {\n\t\t\t\tfor (i = 0; i < 4; i++)\n\t\t\t\t\tpn[i] /= oflo;\n\t\t\t}\n\t\t}\n\t}\n}\n\n/*\n * Given a value p in [0..1] of the lower tail area of the normal distribution,\n * compute the limit on the definite integral from [-inf..z] that satisfies p,\n * accurate to 16 decimal places.\n *\n * This implementation is based on:\n *\n *   Wichura, M.J. (1988) Algorithm AS 241: The percentage points of the normal\n *   distribution.  Applied Statistics 37(3):477-484.\n */\nJEMALLOC_INLINE double\npt_norm(double p)\n{\n\tdouble q, r, ret;\n\n\tassert(p > 0.0 && p < 1.0);\n\n\tq = p - 0.5;\n\tif (fabs(q) <= 0.425) {\n\t\t/* p close to 1/2. */\n\t\tr = 0.180625 - q * q;\n\t\treturn (q * (((((((2.5090809287301226727e3 * r +\n\t\t    3.3430575583588128105e4) * r + 6.7265770927008700853e4) * r\n\t\t    + 4.5921953931549871457e4) * r + 1.3731693765509461125e4) *\n\t\t    r + 1.9715909503065514427e3) * r + 1.3314166789178437745e2)\n\t\t    * r + 3.3871328727963666080e0) /\n\t\t    (((((((5.2264952788528545610e3 * r +\n\t\t    2.8729085735721942674e4) * r + 3.9307895800092710610e4) * r\n\t\t    + 2.1213794301586595867e4) * r + 5.3941960214247511077e3) *\n\t\t    r + 6.8718700749205790830e2) * r + 4.2313330701600911252e1)\n\t\t    * r + 1.0));\n\t} else {\n\t\tif (q < 0.0)\n\t\t\tr = p;\n\t\telse\n\t\t\tr = 1.0 - p;\n\t\tassert(r > 0.0);\n\n\t\tr = sqrt(-log(r));\n\t\tif (r <= 5.0) {\n\t\t\t/* p neither close to 1/2 nor 0 or 1. */\n\t\t\tr -= 1.6;\n\t\t\tret = ((((((((7.74545014278341407640e-4 * r +\n\t\t\t    2.27238449892691845833e-2) * r +\n\t\t\t    2.41780725177450611770e-1) * r +\n\t\t\t    1.27045825245236838258e0) * r +\n\t\t\t    3.64784832476320460504e0) * r +\n\t\t\t    5.76949722146069140550e0) * r +\n\t\t\t    4.63033784615654529590e0) * r +\n\t\t\t    1.42343711074968357734e0) /\n\t\t\t    (((((((1.05075007164441684324e-9 * r +\n\t\t\t    5.47593808499534494600e-4) * r +\n\t\t\t    1.51986665636164571966e-2)\n\t\t\t    * r + 1.48103976427480074590e-1) * r +\n\t\t\t    6.89767334985100004550e-1) * r +\n\t\t\t    1.67638483018380384940e0) * r +\n\t\t\t    2.05319162663775882187e0) * r + 1.0));\n\t\t} else {\n\t\t\t/* p near 0 or 1. */\n\t\t\tr -= 5.0;\n\t\t\tret = ((((((((2.01033439929228813265e-7 * r +\n\t\t\t    2.71155556874348757815e-5) * r +\n\t\t\t    1.24266094738807843860e-3) * r +\n\t\t\t    2.65321895265761230930e-2) * r +\n\t\t\t    2.96560571828504891230e-1) * r +\n\t\t\t    1.78482653991729133580e0) * r +\n\t\t\t    5.46378491116411436990e0) * r +\n\t\t\t    6.65790464350110377720e0) /\n\t\t\t    (((((((2.04426310338993978564e-15 * r +\n\t\t\t    1.42151175831644588870e-7) * r +\n\t\t\t    1.84631831751005468180e-5) * r +\n\t\t\t    7.86869131145613259100e-4) * r +\n\t\t\t    1.48753612908506148525e-2) * r +\n\t\t\t    1.36929880922735805310e-1) * r +\n\t\t\t    5.99832206555887937690e-1)\n\t\t\t    * r + 1.0));\n\t\t}\n\t\tif (q < 0.0)\n\t\t\tret = -ret;\n\t\treturn (ret);\n\t}\n}\n\n/*\n * Given a value p in [0..1] of the lower tail area of the Chi^2 distribution\n * with df degrees of freedom, where ln_gamma_df_2 is ln_gamma(df/2.0), compute\n * the upper limit on the definite integral from [0..z] that satisfies p,\n * accurate to 12 decimal places.\n *\n * This implementation is based on:\n *\n *   Best, D.J., D.E. Roberts (1975) Algorithm AS 91: The percentage points of\n *   the Chi^2 distribution.  Applied Statistics 24(3):385-388.\n *\n *   Shea, B.L. (1991) Algorithm AS R85: A remark on AS 91: The percentage\n *   points of the Chi^2 distribution.  Applied Statistics 40(1):233-235.\n */\nJEMALLOC_INLINE double\npt_chi2(double p, double df, double ln_gamma_df_2)\n{\n\tdouble e, aa, xx, c, ch, a, q, p1, p2, t, x, b, s1, s2, s3, s4, s5, s6;\n\tunsigned i;\n\n\tassert(p >= 0.0 && p < 1.0);\n\tassert(df > 0.0);\n\n\te = 5.0e-7;\n\taa = 0.6931471805;\n\n\txx = 0.5 * df;\n\tc = xx - 1.0;\n\n\tif (df < -1.24 * log(p)) {\n\t\t/* Starting approximation for small Chi^2. */\n\t\tch = pow(p * xx * exp(ln_gamma_df_2 + xx * aa), 1.0 / xx);\n\t\tif (ch - e < 0.0)\n\t\t\treturn (ch);\n\t} else {\n\t\tif (df > 0.32) {\n\t\t\tx = pt_norm(p);\n\t\t\t/*\n\t\t\t * Starting approximation using Wilson and Hilferty\n\t\t\t * estimate.\n\t\t\t */\n\t\t\tp1 = 0.222222 / df;\n\t\t\tch = df * pow(x * sqrt(p1) + 1.0 - p1, 3.0);\n\t\t\t/* Starting approximation for p tending to 1. */\n\t\t\tif (ch > 2.2 * df + 6.0) {\n\t\t\t\tch = -2.0 * (log(1.0 - p) - c * log(0.5 * ch) +\n\t\t\t\t    ln_gamma_df_2);\n\t\t\t}\n\t\t} else {\n\t\t\tch = 0.4;\n\t\t\ta = log(1.0 - p);\n\t\t\twhile (true) {\n\t\t\t\tq = ch;\n\t\t\t\tp1 = 1.0 + ch * (4.67 + ch);\n\t\t\t\tp2 = ch * (6.73 + ch * (6.66 + ch));\n\t\t\t\tt = -0.5 + (4.67 + 2.0 * ch) / p1 - (6.73 + ch\n\t\t\t\t    * (13.32 + 3.0 * ch)) / p2;\n\t\t\t\tch -= (1.0 - exp(a + ln_gamma_df_2 + 0.5 * ch +\n\t\t\t\t    c * aa) * p2 / p1) / t;\n\t\t\t\tif (fabs(q / ch - 1.0) - 0.01 <= 0.0)\n\t\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t}\n\n\tfor (i = 0; i < 20; i++) {\n\t\t/* Calculation of seven-term Taylor series. */\n\t\tq = ch;\n\t\tp1 = 0.5 * ch;\n\t\tif (p1 < 0.0)\n\t\t\treturn (-1.0);\n\t\tp2 = p - i_gamma(p1, xx, ln_gamma_df_2);\n\t\tt = p2 * exp(xx * aa + ln_gamma_df_2 + p1 - c * log(ch));\n\t\tb = t / ch;\n\t\ta = 0.5 * t - b * c;\n\t\ts1 = (210.0 + a * (140.0 + a * (105.0 + a * (84.0 + a * (70.0 +\n\t\t    60.0 * a))))) / 420.0;\n\t\ts2 = (420.0 + a * (735.0 + a * (966.0 + a * (1141.0 + 1278.0 *\n\t\t    a)))) / 2520.0;\n\t\ts3 = (210.0 + a * (462.0 + a * (707.0 + 932.0 * a))) / 2520.0;\n\t\ts4 = (252.0 + a * (672.0 + 1182.0 * a) + c * (294.0 + a *\n\t\t    (889.0 + 1740.0 * a))) / 5040.0;\n\t\ts5 = (84.0 + 264.0 * a + c * (175.0 + 606.0 * a)) / 2520.0;\n\t\ts6 = (120.0 + c * (346.0 + 127.0 * c)) / 5040.0;\n\t\tch += t * (1.0 + 0.5 * t * s1 - b * c * (s1 - b * (s2 - b * (s3\n\t\t    - b * (s4 - b * (s5 - b * s6))))));\n\t\tif (fabs(q / ch - 1.0) <= e)\n\t\t\tbreak;\n\t}\n\n\treturn (ch);\n}\n\n/*\n * Given a value p in [0..1] and Gamma distribution shape and scale parameters,\n * compute the upper limit on the definite integeral from [0..z] that satisfies\n * p.\n */\nJEMALLOC_INLINE double\npt_gamma(double p, double shape, double scale, double ln_gamma_shape)\n{\n\n\treturn (pt_chi2(p, shape * 2.0, ln_gamma_shape) * 0.5 * scale);\n}\n#endif\n"
  },
  {
    "path": "extern/deprecated/redis-2.8.21/deps/jemalloc/test/include/test/mq.h",
    "content": "/*\n * Simple templated message queue implementation that relies on only mutexes for\n * synchronization (which reduces portability issues).  Given the following\n * setup:\n *\n *   typedef struct mq_msg_s mq_msg_t;\n *   struct mq_msg_s {\n *           mq_msg(mq_msg_t) link;\n *           [message data]\n *   };\n *   mq_gen(, mq_, mq_t, mq_msg_t, link)\n *\n * The API is as follows:\n *\n *   bool mq_init(mq_t *mq);\n *   void mq_fini(mq_t *mq);\n *   unsigned mq_count(mq_t *mq);\n *   mq_msg_t *mq_tryget(mq_t *mq);\n *   mq_msg_t *mq_get(mq_t *mq);\n *   void mq_put(mq_t *mq, mq_msg_t *msg);\n *\n * The message queue linkage embedded in each message is to be treated as\n * externally opaque (no need to initialize or clean up externally).  mq_fini()\n * does not perform any cleanup of messages, since it knows nothing of their\n * payloads.\n */\n#define\tmq_msg(a_mq_msg_type)\tql_elm(a_mq_msg_type)\n\n#define\tmq_gen(a_attr, a_prefix, a_mq_type, a_mq_msg_type, a_field)\t\\\ntypedef struct {\t\t\t\t\t\t\t\\\n\tmtx_t\t\t\tlock;\t\t\t\t\t\\\n\tql_head(a_mq_msg_type)\tmsgs;\t\t\t\t\t\\\n\tunsigned\t\tcount;\t\t\t\t\t\\\n} a_mq_type;\t\t\t\t\t\t\t\t\\\na_attr bool\t\t\t\t\t\t\t\t\\\na_prefix##init(a_mq_type *mq) {\t\t\t\t\t\t\\\n\t\t\t\t\t\t\t\t\t\\\n\tif (mtx_init(&mq->lock))\t\t\t\t\t\\\n\t\treturn (true);\t\t\t\t\t\t\\\n\tql_new(&mq->msgs);\t\t\t\t\t\t\\\n\tmq->count = 0;\t\t\t\t\t\t\t\\\n\treturn (false);\t\t\t\t\t\t\t\\\n}\t\t\t\t\t\t\t\t\t\\\na_attr void\t\t\t\t\t\t\t\t\\\na_prefix##fini(a_mq_type *mq)\t\t\t\t\t\t\\\n{\t\t\t\t\t\t\t\t\t\\\n\t\t\t\t\t\t\t\t\t\\\n\tmtx_fini(&mq->lock);\t\t\t\t\t\t\\\n}\t\t\t\t\t\t\t\t\t\\\na_attr unsigned\t\t\t\t\t\t\t\t\\\na_prefix##count(a_mq_type *mq)\t\t\t\t\t\t\\\n{\t\t\t\t\t\t\t\t\t\\\n\tunsigned count;\t\t\t\t\t\t\t\\\n\t\t\t\t\t\t\t\t\t\\\n\tmtx_lock(&mq->lock);\t\t\t\t\t\t\\\n\tcount = mq->count;\t\t\t\t\t\t\\\n\tmtx_unlock(&mq->lock);\t\t\t\t\t\t\\\n\treturn (count);\t\t\t\t\t\t\t\\\n}\t\t\t\t\t\t\t\t\t\\\na_attr a_mq_msg_type *\t\t\t\t\t\t\t\\\na_prefix##tryget(a_mq_type *mq)\t\t\t\t\t\t\\\n{\t\t\t\t\t\t\t\t\t\\\n\ta_mq_msg_type *msg;\t\t\t\t\t\t\\\n\t\t\t\t\t\t\t\t\t\\\n\tmtx_lock(&mq->lock);\t\t\t\t\t\t\\\n\tmsg = ql_first(&mq->msgs);\t\t\t\t\t\\\n\tif (msg != NULL) {\t\t\t\t\t\t\\\n\t\tql_head_remove(&mq->msgs, a_mq_msg_type, a_field);\t\\\n\t\tmq->count--;\t\t\t\t\t\t\\\n\t}\t\t\t\t\t\t\t\t\\\n\tmtx_unlock(&mq->lock);\t\t\t\t\t\t\\\n\treturn (msg);\t\t\t\t\t\t\t\\\n}\t\t\t\t\t\t\t\t\t\\\na_attr a_mq_msg_type *\t\t\t\t\t\t\t\\\na_prefix##get(a_mq_type *mq)\t\t\t\t\t\t\\\n{\t\t\t\t\t\t\t\t\t\\\n\ta_mq_msg_type *msg;\t\t\t\t\t\t\\\n\tstruct timespec timeout;\t\t\t\t\t\\\n\t\t\t\t\t\t\t\t\t\\\n\tmsg = a_prefix##tryget(mq);\t\t\t\t\t\\\n\tif (msg != NULL)\t\t\t\t\t\t\\\n\t\treturn (msg);\t\t\t\t\t\t\\\n\t\t\t\t\t\t\t\t\t\\\n\ttimeout.tv_sec = 0;\t\t\t\t\t\t\\\n\ttimeout.tv_nsec = 1;\t\t\t\t\t\t\\\n\twhile (true) {\t\t\t\t\t\t\t\\\n\t\tnanosleep(&timeout, NULL);\t\t\t\t\\\n\t\tmsg = a_prefix##tryget(mq);\t\t\t\t\\\n\t\tif (msg != NULL)\t\t\t\t\t\\\n\t\t\treturn (msg);\t\t\t\t\t\\\n\t\tif (timeout.tv_sec == 0) {\t\t\t\t\\\n\t\t\t/* Double sleep time, up to max 1 second. */\t\\\n\t\t\ttimeout.tv_nsec <<= 1;\t\t\t\t\\\n\t\t\tif (timeout.tv_nsec >= 1000*1000*1000) {\t\\\n\t\t\t\ttimeout.tv_sec = 1;\t\t\t\\\n\t\t\t\ttimeout.tv_nsec = 0;\t\t\t\\\n\t\t\t}\t\t\t\t\t\t\\\n\t\t}\t\t\t\t\t\t\t\\\n\t}\t\t\t\t\t\t\t\t\\\n}\t\t\t\t\t\t\t\t\t\\\na_attr void\t\t\t\t\t\t\t\t\\\na_prefix##put(a_mq_type *mq, a_mq_msg_type *msg)\t\t\t\\\n{\t\t\t\t\t\t\t\t\t\\\n\t\t\t\t\t\t\t\t\t\\\n\tmtx_lock(&mq->lock);\t\t\t\t\t\t\\\n\tql_elm_new(msg, a_field);\t\t\t\t\t\\\n\tql_tail_insert(&mq->msgs, msg, a_field);\t\t\t\\\n\tmq->count++;\t\t\t\t\t\t\t\\\n\tmtx_unlock(&mq->lock);\t\t\t\t\t\t\\\n}\n"
  },
  {
    "path": "extern/deprecated/redis-2.8.21/deps/jemalloc/test/include/test/mtx.h",
    "content": "/*\n * mtx is a slightly simplified version of malloc_mutex.  This code duplication\n * is unfortunate, but there are allocator bootstrapping considerations that\n * would leak into the test infrastructure if malloc_mutex were used directly\n * in tests.\n */\n\ntypedef struct {\n#ifdef _WIN32\n\tCRITICAL_SECTION\tlock;\n#elif (defined(JEMALLOC_OSSPIN))\n\tOSSpinLock\t\tlock;\n#else\n\tpthread_mutex_t\t\tlock;\n#endif\n} mtx_t;\n\nbool\tmtx_init(mtx_t *mtx);\nvoid\tmtx_fini(mtx_t *mtx);\nvoid\tmtx_lock(mtx_t *mtx);\nvoid\tmtx_unlock(mtx_t *mtx);\n"
  },
  {
    "path": "extern/deprecated/redis-2.8.21/deps/jemalloc/test/include/test/test.h",
    "content": "#define\tASSERT_BUFSIZE\t256\n\n#define\tassert_cmp(t, a, b, cmp, neg_cmp, pri, fmt...) do {\t\t\\\n\tt a_ = (a);\t\t\t\t\t\t\t\\\n\tt b_ = (b);\t\t\t\t\t\t\t\\\n\tif (!(a_ cmp b_)) {\t\t\t\t\t\t\\\n\t\tchar prefix[ASSERT_BUFSIZE];\t\t\t\t\\\n\t\tchar message[ASSERT_BUFSIZE];\t\t\t\t\\\n\t\tmalloc_snprintf(prefix, sizeof(prefix),\t\t\t\\\n\t\t    \"%s:%s:%d: Failed assertion: \"\t\t\t\\\n\t\t    \"(%s) \"#cmp\" (%s) --> \"\t\t\t\t\\\n\t\t    \"%\"pri\" \"#neg_cmp\" %\"pri\": \",\t\t\t\\\n\t\t    __func__, __FILE__, __LINE__,\t\t\t\\\n\t\t    #a, #b, a_, b_);\t\t\t\t\t\\\n\t\tmalloc_snprintf(message, sizeof(message), fmt);\t\t\\\n\t\tp_test_fail(prefix, message);\t\t\t\t\\\n\t}\t\t\t\t\t\t\t\t\\\n} while (0)\n\n#define\tassert_ptr_eq(a, b, fmt...)\tassert_cmp(void *, a, b, ==,\t\\\n    !=, \"p\", fmt)\n#define\tassert_ptr_ne(a, b, fmt...)\tassert_cmp(void *, a, b, !=,\t\\\n    ==, \"p\", fmt)\n#define\tassert_ptr_null(a, fmt...)\tassert_cmp(void *, a, NULL, ==,\t\\\n    !=, \"p\", fmt)\n#define\tassert_ptr_not_null(a, fmt...)\tassert_cmp(void *, a, NULL, !=,\t\\\n    ==, \"p\", fmt)\n\n#define\tassert_c_eq(a, b, fmt...)\tassert_cmp(char, a, b, ==, !=, \"c\", fmt)\n#define\tassert_c_ne(a, b, fmt...)\tassert_cmp(char, a, b, !=, ==, \"c\", fmt)\n#define\tassert_c_lt(a, b, fmt...)\tassert_cmp(char, a, b, <, >=, \"c\", fmt)\n#define\tassert_c_le(a, b, fmt...)\tassert_cmp(char, a, b, <=, >, \"c\", fmt)\n#define\tassert_c_ge(a, b, fmt...)\tassert_cmp(char, a, b, >=, <, \"c\", fmt)\n#define\tassert_c_gt(a, b, fmt...)\tassert_cmp(char, a, b, >, <=, \"c\", fmt)\n\n#define\tassert_x_eq(a, b, fmt...)\tassert_cmp(int, a, b, ==, !=, \"#x\", fmt)\n#define\tassert_x_ne(a, b, fmt...)\tassert_cmp(int, a, b, !=, ==, \"#x\", fmt)\n#define\tassert_x_lt(a, b, fmt...)\tassert_cmp(int, a, b, <, >=, \"#x\", fmt)\n#define\tassert_x_le(a, b, fmt...)\tassert_cmp(int, a, b, <=, >, \"#x\", fmt)\n#define\tassert_x_ge(a, b, fmt...)\tassert_cmp(int, a, b, >=, <, \"#x\", fmt)\n#define\tassert_x_gt(a, b, fmt...)\tassert_cmp(int, a, b, >, <=, \"#x\", fmt)\n\n#define\tassert_d_eq(a, b, fmt...)\tassert_cmp(int, a, b, ==, !=, \"d\", fmt)\n#define\tassert_d_ne(a, b, fmt...)\tassert_cmp(int, a, b, !=, ==, \"d\", fmt)\n#define\tassert_d_lt(a, b, fmt...)\tassert_cmp(int, a, b, <, >=, \"d\", fmt)\n#define\tassert_d_le(a, b, fmt...)\tassert_cmp(int, a, b, <=, >, \"d\", fmt)\n#define\tassert_d_ge(a, b, fmt...)\tassert_cmp(int, a, b, >=, <, \"d\", fmt)\n#define\tassert_d_gt(a, b, fmt...)\tassert_cmp(int, a, b, >, <=, \"d\", fmt)\n\n#define\tassert_u_eq(a, b, fmt...)\tassert_cmp(int, a, b, ==, !=, \"u\", fmt)\n#define\tassert_u_ne(a, b, fmt...)\tassert_cmp(int, a, b, !=, ==, \"u\", fmt)\n#define\tassert_u_lt(a, b, fmt...)\tassert_cmp(int, a, b, <, >=, \"u\", fmt)\n#define\tassert_u_le(a, b, fmt...)\tassert_cmp(int, a, b, <=, >, \"u\", fmt)\n#define\tassert_u_ge(a, b, fmt...)\tassert_cmp(int, a, b, >=, <, \"u\", fmt)\n#define\tassert_u_gt(a, b, fmt...)\tassert_cmp(int, a, b, >, <=, \"u\", fmt)\n\n#define\tassert_ld_eq(a, b, fmt...)\tassert_cmp(long, a, b, ==,\t\\\n    !=, \"ld\", fmt)\n#define\tassert_ld_ne(a, b, fmt...)\tassert_cmp(long, a, b, !=,\t\\\n    ==, \"ld\", fmt)\n#define\tassert_ld_lt(a, b, fmt...)\tassert_cmp(long, a, b, <,\t\\\n    >=, \"ld\", fmt)\n#define\tassert_ld_le(a, b, fmt...)\tassert_cmp(long, a, b, <=,\t\\\n    >, \"ld\", fmt)\n#define\tassert_ld_ge(a, b, fmt...)\tassert_cmp(long, a, b, >=,\t\\\n    <, \"ld\", fmt)\n#define\tassert_ld_gt(a, b, fmt...)\tassert_cmp(long, a, b, >,\t\\\n    <=, \"ld\", fmt)\n\n#define\tassert_lu_eq(a, b, fmt...)\tassert_cmp(unsigned long,\t\\\n    a, b, ==, !=, \"lu\", fmt)\n#define\tassert_lu_ne(a, b, fmt...)\tassert_cmp(unsigned long,\t\\\n    a, b, !=, ==, \"lu\", fmt)\n#define\tassert_lu_lt(a, b, fmt...)\tassert_cmp(unsigned long,\t\\\n    a, b, <, >=, \"lu\", fmt)\n#define\tassert_lu_le(a, b, fmt...)\tassert_cmp(unsigned long,\t\\\n    a, b, <=, >, \"lu\", fmt)\n#define\tassert_lu_ge(a, b, fmt...)\tassert_cmp(unsigned long,\t\\\n    a, b, >=, <, \"lu\", fmt)\n#define\tassert_lu_gt(a, b, fmt...)\tassert_cmp(unsigned long,\t\\\n    a, b, >, <=, \"lu\", fmt)\n\n#define\tassert_qd_eq(a, b, fmt...)\tassert_cmp(long long, a, b, ==,\t\\\n    !=, \"qd\", fmt)\n#define\tassert_qd_ne(a, b, fmt...)\tassert_cmp(long long, a, b, !=,\t\\\n    ==, \"qd\", fmt)\n#define\tassert_qd_lt(a, b, fmt...)\tassert_cmp(long long, a, b, <,\t\\\n    >=, \"qd\", fmt)\n#define\tassert_qd_le(a, b, fmt...)\tassert_cmp(long long, a, b, <=,\t\\\n    >, \"qd\", fmt)\n#define\tassert_qd_ge(a, b, fmt...)\tassert_cmp(long long, a, b, >=,\t\\\n    <, \"qd\", fmt)\n#define\tassert_qd_gt(a, b, fmt...)\tassert_cmp(long long, a, b, >,\t\\\n    <=, \"qd\", fmt)\n\n#define\tassert_qu_eq(a, b, fmt...)\tassert_cmp(unsigned long long,\t\\\n    a, b, ==, !=, \"qu\", fmt)\n#define\tassert_qu_ne(a, b, fmt...)\tassert_cmp(unsigned long long,\t\\\n    a, b, !=, ==, \"qu\", fmt)\n#define\tassert_qu_lt(a, b, fmt...)\tassert_cmp(unsigned long long,\t\\\n    a, b, <, >=, \"qu\", fmt)\n#define\tassert_qu_le(a, b, fmt...)\tassert_cmp(unsigned long long,\t\\\n    a, b, <=, >, \"qu\", fmt)\n#define\tassert_qu_ge(a, b, fmt...)\tassert_cmp(unsigned long long,\t\\\n    a, b, >=, <, \"qu\", fmt)\n#define\tassert_qu_gt(a, b, fmt...)\tassert_cmp(unsigned long long,\t\\\n    a, b, >, <=, \"qu\", fmt)\n\n#define\tassert_jd_eq(a, b, fmt...)\tassert_cmp(intmax_t, a, b, ==,\t\\\n    !=, \"jd\", fmt)\n#define\tassert_jd_ne(a, b, fmt...)\tassert_cmp(intmax_t, a, b, !=,\t\\\n    ==, \"jd\", fmt)\n#define\tassert_jd_lt(a, b, fmt...)\tassert_cmp(intmax_t, a, b, <,\t\\\n    >=, \"jd\", fmt)\n#define\tassert_jd_le(a, b, fmt...)\tassert_cmp(intmax_t, a, b, <=,\t\\\n    >, \"jd\", fmt)\n#define\tassert_jd_ge(a, b, fmt...)\tassert_cmp(intmax_t, a, b, >=,\t\\\n    <, \"jd\", fmt)\n#define\tassert_jd_gt(a, b, fmt...)\tassert_cmp(intmax_t, a, b, >,\t\\\n    <=, \"jd\", fmt)\n\n#define\tassert_ju_eq(a, b, fmt...)\tassert_cmp(uintmax_t, a, b, ==,\t\\\n    !=, \"ju\", fmt)\n#define\tassert_ju_ne(a, b, fmt...)\tassert_cmp(uintmax_t, a, b, !=,\t\\\n    ==, \"ju\", fmt)\n#define\tassert_ju_lt(a, b, fmt...)\tassert_cmp(uintmax_t, a, b, <,\t\\\n    >=, \"ju\", fmt)\n#define\tassert_ju_le(a, b, fmt...)\tassert_cmp(uintmax_t, a, b, <=,\t\\\n    >, \"ju\", fmt)\n#define\tassert_ju_ge(a, b, fmt...)\tassert_cmp(uintmax_t, a, b, >=,\t\\\n    <, \"ju\", fmt)\n#define\tassert_ju_gt(a, b, fmt...)\tassert_cmp(uintmax_t, a, b, >,\t\\\n    <=, \"ju\", fmt)\n\n#define\tassert_zd_eq(a, b, fmt...)\tassert_cmp(ssize_t, a, b, ==,\t\\\n    !=, \"zd\", fmt)\n#define\tassert_zd_ne(a, b, fmt...)\tassert_cmp(ssize_t, a, b, !=,\t\\\n    ==, \"zd\", fmt)\n#define\tassert_zd_lt(a, b, fmt...)\tassert_cmp(ssize_t, a, b, <,\t\\\n    >=, \"zd\", fmt)\n#define\tassert_zd_le(a, b, fmt...)\tassert_cmp(ssize_t, a, b, <=,\t\\\n    >, \"zd\", fmt)\n#define\tassert_zd_ge(a, b, fmt...)\tassert_cmp(ssize_t, a, b, >=,\t\\\n    <, \"zd\", fmt)\n#define\tassert_zd_gt(a, b, fmt...)\tassert_cmp(ssize_t, a, b, >,\t\\\n    <=, \"zd\", fmt)\n\n#define\tassert_zu_eq(a, b, fmt...)\tassert_cmp(size_t, a, b, ==,\t\\\n    !=, \"zu\", fmt)\n#define\tassert_zu_ne(a, b, fmt...)\tassert_cmp(size_t, a, b, !=,\t\\\n    ==, \"zu\", fmt)\n#define\tassert_zu_lt(a, b, fmt...)\tassert_cmp(size_t, a, b, <,\t\\\n    >=, \"zu\", fmt)\n#define\tassert_zu_le(a, b, fmt...)\tassert_cmp(size_t, a, b, <=,\t\\\n    >, \"zu\", fmt)\n#define\tassert_zu_ge(a, b, fmt...)\tassert_cmp(size_t, a, b, >=,\t\\\n    <, \"zu\", fmt)\n#define\tassert_zu_gt(a, b, fmt...)\tassert_cmp(size_t, a, b, >,\t\\\n    <=, \"zu\", fmt)\n\n#define\tassert_d32_eq(a, b, fmt...)\tassert_cmp(int32_t, a, b, ==,\t\\\n    !=, PRId32, fmt)\n#define\tassert_d32_ne(a, b, fmt...)\tassert_cmp(int32_t, a, b, !=,\t\\\n    ==, PRId32, fmt)\n#define\tassert_d32_lt(a, b, fmt...)\tassert_cmp(int32_t, a, b, <,\t\\\n    >=, PRId32, fmt)\n#define\tassert_d32_le(a, b, fmt...)\tassert_cmp(int32_t, a, b, <=,\t\\\n    >, PRId32, fmt)\n#define\tassert_d32_ge(a, b, fmt...)\tassert_cmp(int32_t, a, b, >=,\t\\\n    <, PRId32, fmt)\n#define\tassert_d32_gt(a, b, fmt...)\tassert_cmp(int32_t, a, b, >,\t\\\n    <=, PRId32, fmt)\n\n#define\tassert_u32_eq(a, b, fmt...)\tassert_cmp(uint32_t, a, b, ==,\t\\\n    !=, PRIu32, fmt)\n#define\tassert_u32_ne(a, b, fmt...)\tassert_cmp(uint32_t, a, b, !=,\t\\\n    ==, PRIu32, fmt)\n#define\tassert_u32_lt(a, b, fmt...)\tassert_cmp(uint32_t, a, b, <,\t\\\n    >=, PRIu32, fmt)\n#define\tassert_u32_le(a, b, fmt...)\tassert_cmp(uint32_t, a, b, <=,\t\\\n    >, PRIu32, fmt)\n#define\tassert_u32_ge(a, b, fmt...)\tassert_cmp(uint32_t, a, b, >=,\t\\\n    <, PRIu32, fmt)\n#define\tassert_u32_gt(a, b, fmt...)\tassert_cmp(uint32_t, a, b, >,\t\\\n    <=, PRIu32, fmt)\n\n#define\tassert_d64_eq(a, b, fmt...)\tassert_cmp(int64_t, a, b, ==,\t\\\n    !=, PRId64, fmt)\n#define\tassert_d64_ne(a, b, fmt...)\tassert_cmp(int64_t, a, b, !=,\t\\\n    ==, PRId64, fmt)\n#define\tassert_d64_lt(a, b, fmt...)\tassert_cmp(int64_t, a, b, <,\t\\\n    >=, PRId64, fmt)\n#define\tassert_d64_le(a, b, fmt...)\tassert_cmp(int64_t, a, b, <=,\t\\\n    >, PRId64, fmt)\n#define\tassert_d64_ge(a, b, fmt...)\tassert_cmp(int64_t, a, b, >=,\t\\\n    <, PRId64, fmt)\n#define\tassert_d64_gt(a, b, fmt...)\tassert_cmp(int64_t, a, b, >,\t\\\n    <=, PRId64, fmt)\n\n#define\tassert_u64_eq(a, b, fmt...)\tassert_cmp(uint64_t, a, b, ==,\t\\\n    !=, PRIu64, fmt)\n#define\tassert_u64_ne(a, b, fmt...)\tassert_cmp(uint64_t, a, b, !=,\t\\\n    ==, PRIu64, fmt)\n#define\tassert_u64_lt(a, b, fmt...)\tassert_cmp(uint64_t, a, b, <,\t\\\n    >=, PRIu64, fmt)\n#define\tassert_u64_le(a, b, fmt...)\tassert_cmp(uint64_t, a, b, <=,\t\\\n    >, PRIu64, fmt)\n#define\tassert_u64_ge(a, b, fmt...)\tassert_cmp(uint64_t, a, b, >=,\t\\\n    <, PRIu64, fmt)\n#define\tassert_u64_gt(a, b, fmt...)\tassert_cmp(uint64_t, a, b, >,\t\\\n    <=, PRIu64, fmt)\n\n#define\tassert_b_eq(a, b, fmt...) do {\t\t\t\t\t\\\n\tbool a_ = (a);\t\t\t\t\t\t\t\\\n\tbool b_ = (b);\t\t\t\t\t\t\t\\\n\tif (!(a_ == b_)) {\t\t\t\t\t\t\\\n\t\tchar prefix[ASSERT_BUFSIZE];\t\t\t\t\\\n\t\tchar message[ASSERT_BUFSIZE];\t\t\t\t\\\n\t\tmalloc_snprintf(prefix, sizeof(prefix),\t\t\t\\\n\t\t    \"%s:%s:%d: Failed assertion: \"\t\t\t\\\n\t\t    \"(%s) == (%s) --> %s != %s: \",\t\t\t\\\n\t\t    __func__, __FILE__, __LINE__,\t\t\t\\\n\t\t    #a, #b, a_ ? \"true\" : \"false\",\t\t\t\\\n\t\t    b_ ? \"true\" : \"false\");\t\t\t\t\\\n\t\tmalloc_snprintf(message, sizeof(message), fmt);\t\t\\\n\t\tp_test_fail(prefix, message);\t\t\t\t\\\n\t}\t\t\t\t\t\t\t\t\\\n} while (0)\n#define\tassert_b_ne(a, b, fmt...) do {\t\t\t\t\t\\\n\tbool a_ = (a);\t\t\t\t\t\t\t\\\n\tbool b_ = (b);\t\t\t\t\t\t\t\\\n\tif (!(a_ != b_)) {\t\t\t\t\t\t\\\n\t\tchar prefix[ASSERT_BUFSIZE];\t\t\t\t\\\n\t\tchar message[ASSERT_BUFSIZE];\t\t\t\t\\\n\t\tmalloc_snprintf(prefix, sizeof(prefix),\t\t\t\\\n\t\t    \"%s:%s:%d: Failed assertion: \"\t\t\t\\\n\t\t    \"(%s) != (%s) --> %s == %s: \",\t\t\t\\\n\t\t    __func__, __FILE__, __LINE__,\t\t\t\\\n\t\t    #a, #b, a_ ? \"true\" : \"false\",\t\t\t\\\n\t\t    b_ ? \"true\" : \"false\");\t\t\t\t\\\n\t\tmalloc_snprintf(message, sizeof(message), fmt);\t\t\\\n\t\tp_test_fail(prefix, message);\t\t\t\t\\\n\t}\t\t\t\t\t\t\t\t\\\n} while (0)\n#define\tassert_true(a, fmt...)\tassert_b_eq(a, true, fmt)\n#define\tassert_false(a, fmt...)\tassert_b_eq(a, false, fmt)\n\n#define\tassert_str_eq(a, b, fmt...) do {\t\t\t\t\\\n\tif (strcmp((a), (b))) {\t\t\t\t\t\t\\\n\t\tchar prefix[ASSERT_BUFSIZE];\t\t\t\t\\\n\t\tchar message[ASSERT_BUFSIZE];\t\t\t\t\\\n\t\tmalloc_snprintf(prefix, sizeof(prefix),\t\t\t\\\n\t\t    \"%s:%s:%d: Failed assertion: \"\t\t\t\\\n\t\t    \"(%s) same as (%s) --> \"\t\t\t\t\\\n\t\t    \"\\\"%s\\\" differs from \\\"%s\\\": \",\t\t\t\\\n\t\t    __func__, __FILE__, __LINE__, #a, #b, a, b);\t\\\n\t\tmalloc_snprintf(message, sizeof(message), fmt);\t\t\\\n\t\tp_test_fail(prefix, message);\t\t\t\t\\\n\t}\t\t\t\t\t\t\t\t\\\n} while (0)\n#define\tassert_str_ne(a, b, fmt...) do {\t\t\t\t\\\n\tif (!strcmp((a), (b))) {\t\t\t\t\t\\\n\t\tchar prefix[ASSERT_BUFSIZE];\t\t\t\t\\\n\t\tchar message[ASSERT_BUFSIZE];\t\t\t\t\\\n\t\tmalloc_snprintf(prefix, sizeof(prefix),\t\t\t\\\n\t\t    \"%s:%s:%d: Failed assertion: \"\t\t\t\\\n\t\t    \"(%s) differs from (%s) --> \"\t\t\t\\\n\t\t    \"\\\"%s\\\" same as \\\"%s\\\": \",\t\t\t\t\\\n\t\t    __func__, __FILE__, __LINE__, #a, #b, a, b);\t\\\n\t\tmalloc_snprintf(message, sizeof(message), fmt);\t\t\\\n\t\tp_test_fail(prefix, message);\t\t\t\t\\\n\t}\t\t\t\t\t\t\t\t\\\n} while (0)\n\n#define\tassert_not_reached(fmt...) do {\t\t\t\t\t\\\n\tchar prefix[ASSERT_BUFSIZE];\t\t\t\t\t\\\n\tchar message[ASSERT_BUFSIZE];\t\t\t\t\t\\\n\tmalloc_snprintf(prefix, sizeof(prefix),\t\t\t\t\\\n\t    \"%s:%s:%d: Unreachable code reached: \",\t\t\t\\\n\t    __func__, __FILE__, __LINE__);\t\t\t\t\\\n\tmalloc_snprintf(message, sizeof(message), fmt);\t\t\t\\\n\tp_test_fail(prefix, message);\t\t\t\t\t\\\n} while (0)\n\n/*\n * If this enum changes, corresponding changes in test/test.sh.in are also\n * necessary.\n */\ntypedef enum {\n\ttest_status_pass = 0,\n\ttest_status_skip = 1,\n\ttest_status_fail = 2,\n\n\ttest_status_count = 3\n} test_status_t;\n\ntypedef void (test_t)(void);\n\n#define\tTEST_BEGIN(f)\t\t\t\t\t\t\t\\\nstatic void\t\t\t\t\t\t\t\t\\\nf(void)\t\t\t\t\t\t\t\t\t\\\n{\t\t\t\t\t\t\t\t\t\\\n\tp_test_init(#f);\n\n#define\tTEST_END\t\t\t\t\t\t\t\\\n\tgoto label_test_end;\t\t\t\t\t\t\\\nlabel_test_end:\t\t\t\t\t\t\t\t\\\n\tp_test_fini();\t\t\t\t\t\t\t\\\n}\n\n#define\ttest(tests...)\t\t\t\t\t\t\t\\\n\tp_test(tests, NULL)\n\n#define\ttest_skip_if(e) do {\t\t\t\t\t\t\\\n\tif (e) {\t\t\t\t\t\t\t\\\n\t\ttest_skip(\"%s:%s:%d: Test skipped: (%s)\",\t\t\\\n\t\t    __func__, __FILE__, __LINE__, #e);\t\t\t\\\n\t\tgoto label_test_end;\t\t\t\t\t\\\n\t}\t\t\t\t\t\t\t\t\\\n} while (0)\n\nvoid\ttest_skip(const char *format, ...) JEMALLOC_ATTR(format(printf, 1, 2));\nvoid\ttest_fail(const char *format, ...) JEMALLOC_ATTR(format(printf, 1, 2));\n\n/* For private use by macros. */\ntest_status_t\tp_test(test_t* t, ...);\nvoid\tp_test_init(const char *name);\nvoid\tp_test_fini(void);\nvoid\tp_test_fail(const char *prefix, const char *message);\n"
  },
  {
    "path": "extern/deprecated/redis-2.8.21/deps/jemalloc/test/include/test/thd.h",
    "content": "/* Abstraction layer for threading in tests */\n#ifdef _WIN32\ntypedef HANDLE thd_t;\n#else\ntypedef pthread_t thd_t;\n#endif\n\nvoid\tthd_create(thd_t *thd, void *(*proc)(void *), void *arg);\nvoid\tthd_join(thd_t thd, void **ret);\n"
  },
  {
    "path": "extern/deprecated/redis-2.8.21/deps/jemalloc/test/integration/MALLOCX_ARENA.c",
    "content": "#include \"test/jemalloc_test.h\"\n\n#define\tNTHREADS 10\n\nvoid *\nthd_start(void *arg)\n{\n\tunsigned thread_ind = (unsigned)(uintptr_t)arg;\n\tunsigned arena_ind;\n\tvoid *p;\n\tsize_t sz;\n\n\tsz = sizeof(arena_ind);\n\tassert_d_eq(mallctl(\"arenas.extend\", &arena_ind, &sz, NULL, 0), 0,\n\t    \"Error in arenas.extend\");\n\n\tif (thread_ind % 4 != 3) {\n\t\tsize_t mib[3];\n\t\tsize_t miblen = sizeof(mib) / sizeof(size_t);\n\t\tconst char *dss_precs[] = {\"disabled\", \"primary\", \"secondary\"};\n\t\tconst char *dss = dss_precs[thread_ind %\n\t\t    (sizeof(dss_precs)/sizeof(char*))];\n\t\tassert_d_eq(mallctlnametomib(\"arena.0.dss\", mib, &miblen), 0,\n\t\t    \"Error in mallctlnametomib()\");\n\t\tmib[1] = arena_ind;\n\t\tassert_d_eq(mallctlbymib(mib, miblen, NULL, NULL, (void *)&dss,\n\t\t    sizeof(const char *)), 0, \"Error in mallctlbymib()\");\n\t}\n\n\tp = mallocx(1, MALLOCX_ARENA(arena_ind));\n\tassert_ptr_not_null(p, \"Unexpected mallocx() error\");\n\tdallocx(p, 0);\n\n\treturn (NULL);\n}\n\nTEST_BEGIN(test_ALLOCM_ARENA)\n{\n\tthd_t thds[NTHREADS];\n\tunsigned i;\n\n\tfor (i = 0; i < NTHREADS; i++) {\n\t\tthd_create(&thds[i], thd_start,\n\t\t    (void *)(uintptr_t)i);\n\t}\n\n\tfor (i = 0; i < NTHREADS; i++)\n\t\tthd_join(thds[i], NULL);\n}\nTEST_END\n\nint\nmain(void)\n{\n\n\treturn (test(\n\t    test_ALLOCM_ARENA));\n}\n"
  },
  {
    "path": "extern/deprecated/redis-2.8.21/deps/jemalloc/test/integration/aligned_alloc.c",
    "content": "#include \"test/jemalloc_test.h\"\n\n#define\tCHUNK 0x400000\n/* #define MAXALIGN ((size_t)UINT64_C(0x80000000000)) */\n#define\tMAXALIGN ((size_t)0x2000000LU)\n#define\tNITER 4\n\nTEST_BEGIN(test_alignment_errors)\n{\n\tsize_t alignment;\n\tvoid *p;\n\n\talignment = 0;\n\tset_errno(0);\n\tp = aligned_alloc(alignment, 1);\n\tassert_false(p != NULL || get_errno() != EINVAL,\n\t    \"Expected error for invalid alignment %zu\", alignment);\n\n\tfor (alignment = sizeof(size_t); alignment < MAXALIGN;\n\t    alignment <<= 1) {\n\t\tset_errno(0);\n\t\tp = aligned_alloc(alignment + 1, 1);\n\t\tassert_false(p != NULL || get_errno() != EINVAL,\n\t\t    \"Expected error for invalid alignment %zu\",\n\t\t    alignment + 1);\n\t}\n}\nTEST_END\n\nTEST_BEGIN(test_oom_errors)\n{\n\tsize_t alignment, size;\n\tvoid *p;\n\n#if LG_SIZEOF_PTR == 3\n\talignment = UINT64_C(0x8000000000000000);\n\tsize      = UINT64_C(0x8000000000000000);\n#else\n\talignment = 0x80000000LU;\n\tsize      = 0x80000000LU;\n#endif\n\tset_errno(0);\n\tp = aligned_alloc(alignment, size);\n\tassert_false(p != NULL || get_errno() != ENOMEM,\n\t    \"Expected error for aligned_alloc(%zu, %zu)\",\n\t    alignment, size);\n\n#if LG_SIZEOF_PTR == 3\n\talignment = UINT64_C(0x4000000000000000);\n\tsize      = UINT64_C(0xc000000000000001);\n#else\n\talignment = 0x40000000LU;\n\tsize      = 0xc0000001LU;\n#endif\n\tset_errno(0);\n\tp = aligned_alloc(alignment, size);\n\tassert_false(p != NULL || get_errno() != ENOMEM,\n\t    \"Expected error for aligned_alloc(%zu, %zu)\",\n\t    alignment, size);\n\n\talignment = 0x10LU;\n#if LG_SIZEOF_PTR == 3\n\tsize = UINT64_C(0xfffffffffffffff0);\n#else\n\tsize = 0xfffffff0LU;\n#endif\n\tset_errno(0);\n\tp = aligned_alloc(alignment, size);\n\tassert_false(p != NULL || get_errno() != ENOMEM,\n\t    \"Expected error for aligned_alloc(&p, %zu, %zu)\",\n\t    alignment, size);\n}\nTEST_END\n\nTEST_BEGIN(test_alignment_and_size)\n{\n\tsize_t alignment, size, total;\n\tunsigned i;\n\tvoid *ps[NITER];\n\n\tfor (i = 0; i < NITER; i++)\n\t\tps[i] = NULL;\n\n\tfor (alignment = 8;\n\t    alignment <= MAXALIGN;\n\t    alignment <<= 1) {\n\t\ttotal = 0;\n\t\tfor (size = 1;\n\t\t    size < 3 * alignment && size < (1U << 31);\n\t\t    size += (alignment >> (LG_SIZEOF_PTR-1)) - 1) {\n\t\t\tfor (i = 0; i < NITER; i++) {\n\t\t\t\tps[i] = aligned_alloc(alignment, size);\n\t\t\t\tif (ps[i] == NULL) {\n\t\t\t\t\tchar buf[BUFERROR_BUF];\n\n\t\t\t\t\tbuferror(get_errno(), buf, sizeof(buf));\n\t\t\t\t\ttest_fail(\n\t\t\t\t\t    \"Error for alignment=%zu, \"\n\t\t\t\t\t    \"size=%zu (%#zx): %s\",\n\t\t\t\t\t    alignment, size, size, buf);\n\t\t\t\t}\n\t\t\t\ttotal += malloc_usable_size(ps[i]);\n\t\t\t\tif (total >= (MAXALIGN << 1))\n\t\t\t\t\tbreak;\n\t\t\t}\n\t\t\tfor (i = 0; i < NITER; i++) {\n\t\t\t\tif (ps[i] != NULL) {\n\t\t\t\t\tfree(ps[i]);\n\t\t\t\t\tps[i] = NULL;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}\nTEST_END\n\nint\nmain(void)\n{\n\n\treturn (test(\n\t    test_alignment_errors,\n\t    test_oom_errors,\n\t    test_alignment_and_size));\n}\n"
  },
  {
    "path": "extern/deprecated/redis-2.8.21/deps/jemalloc/test/integration/allocated.c",
    "content": "#include \"test/jemalloc_test.h\"\n\nstatic const bool config_stats =\n#ifdef JEMALLOC_STATS\n    true\n#else\n    false\n#endif\n    ;\n\nvoid *\nthd_start(void *arg)\n{\n\tint err;\n\tvoid *p;\n\tuint64_t a0, a1, d0, d1;\n\tuint64_t *ap0, *ap1, *dp0, *dp1;\n\tsize_t sz, usize;\n\n\tsz = sizeof(a0);\n\tif ((err = mallctl(\"thread.allocated\", &a0, &sz, NULL, 0))) {\n\t\tif (err == ENOENT)\n\t\t\tgoto label_ENOENT;\n\t\ttest_fail(\"%s(): Error in mallctl(): %s\", __func__,\n\t\t    strerror(err));\n\t}\n\tsz = sizeof(ap0);\n\tif ((err = mallctl(\"thread.allocatedp\", &ap0, &sz, NULL, 0))) {\n\t\tif (err == ENOENT)\n\t\t\tgoto label_ENOENT;\n\t\ttest_fail(\"%s(): Error in mallctl(): %s\", __func__,\n\t\t    strerror(err));\n\t}\n\tassert_u64_eq(*ap0, a0,\n\t    \"\\\"thread.allocatedp\\\" should provide a pointer to internal \"\n\t    \"storage\");\n\n\tsz = sizeof(d0);\n\tif ((err = mallctl(\"thread.deallocated\", &d0, &sz, NULL, 0))) {\n\t\tif (err == ENOENT)\n\t\t\tgoto label_ENOENT;\n\t\ttest_fail(\"%s(): Error in mallctl(): %s\", __func__,\n\t\t    strerror(err));\n\t}\n\tsz = sizeof(dp0);\n\tif ((err = mallctl(\"thread.deallocatedp\", &dp0, &sz, NULL, 0))) {\n\t\tif (err == ENOENT)\n\t\t\tgoto label_ENOENT;\n\t\ttest_fail(\"%s(): Error in mallctl(): %s\", __func__,\n\t\t    strerror(err));\n\t}\n\tassert_u64_eq(*dp0, d0,\n\t    \"\\\"thread.deallocatedp\\\" should provide a pointer to internal \"\n\t    \"storage\");\n\n\tp = malloc(1);\n\tassert_ptr_not_null(p, \"Unexpected malloc() error\");\n\n\tsz = sizeof(a1);\n\tmallctl(\"thread.allocated\", &a1, &sz, NULL, 0);\n\tsz = sizeof(ap1);\n\tmallctl(\"thread.allocatedp\", &ap1, &sz, NULL, 0);\n\tassert_u64_eq(*ap1, a1,\n\t    \"Dereferenced \\\"thread.allocatedp\\\" value should equal \"\n\t    \"\\\"thread.allocated\\\" value\");\n\tassert_ptr_eq(ap0, ap1,\n\t    \"Pointer returned by \\\"thread.allocatedp\\\" should not change\");\n\n\tusize = malloc_usable_size(p);\n\tassert_u64_le(a0 + usize, a1,\n\t    \"Allocated memory counter should increase by at least the amount \"\n\t    \"explicitly allocated\");\n\n\tfree(p);\n\n\tsz = sizeof(d1);\n\tmallctl(\"thread.deallocated\", &d1, &sz, NULL, 0);\n\tsz = sizeof(dp1);\n\tmallctl(\"thread.deallocatedp\", &dp1, &sz, NULL, 0);\n\tassert_u64_eq(*dp1, d1,\n\t    \"Dereferenced \\\"thread.deallocatedp\\\" value should equal \"\n\t    \"\\\"thread.deallocated\\\" value\");\n\tassert_ptr_eq(dp0, dp1,\n\t    \"Pointer returned by \\\"thread.deallocatedp\\\" should not change\");\n\n\tassert_u64_le(d0 + usize, d1,\n\t    \"Deallocated memory counter should increase by at least the amount \"\n\t    \"explicitly deallocated\");\n\n\treturn (NULL);\nlabel_ENOENT:\n\tassert_false(config_stats,\n\t    \"ENOENT should only be returned if stats are disabled\");\n\ttest_skip(\"\\\"thread.allocated\\\" mallctl not available\");\n\treturn (NULL);\n}\n\nTEST_BEGIN(test_main_thread)\n{\n\n\tthd_start(NULL);\n}\nTEST_END\n\nTEST_BEGIN(test_subthread)\n{\n\tthd_t thd;\n\n\tthd_create(&thd, thd_start, NULL);\n\tthd_join(thd, NULL);\n}\nTEST_END\n\nint\nmain(void)\n{\n\n\t/* Run tests multiple times to check for bad interactions. */\n\treturn (test(\n\t    test_main_thread,\n\t    test_subthread,\n\t    test_main_thread,\n\t    test_subthread,\n\t    test_main_thread));\n}\n"
  },
  {
    "path": "extern/deprecated/redis-2.8.21/deps/jemalloc/test/integration/allocm.c",
    "content": "#include \"test/jemalloc_test.h\"\n\n#define\tCHUNK 0x400000\n#define\tMAXALIGN (((size_t)1) << 25)\n#define\tNITER 4\n\nTEST_BEGIN(test_basic)\n{\n\tsize_t nsz, rsz, sz;\n\tvoid *p;\n\n\tsz = 42;\n\tnsz = 0;\n\tassert_d_eq(nallocm(&nsz, sz, 0), ALLOCM_SUCCESS,\n\t    \"Unexpected nallocm() error\");\n\trsz = 0;\n\tassert_d_eq(allocm(&p, &rsz, sz, 0), ALLOCM_SUCCESS,\n\t    \"Unexpected allocm() error\");\n\tassert_zu_ge(rsz, sz, \"Real size smaller than expected\");\n\tassert_zu_eq(nsz, rsz, \"nallocm()/allocm() rsize mismatch\");\n\tassert_d_eq(dallocm(p, 0), ALLOCM_SUCCESS,\n\t    \"Unexpected dallocm() error\");\n\n\tassert_d_eq(allocm(&p, NULL, sz, 0), ALLOCM_SUCCESS,\n\t    \"Unexpected allocm() error\");\n\tassert_d_eq(dallocm(p, 0), ALLOCM_SUCCESS,\n\t    \"Unexpected dallocm() error\");\n\n\tnsz = 0;\n\tassert_d_eq(nallocm(&nsz, sz, ALLOCM_ZERO), ALLOCM_SUCCESS,\n\t    \"Unexpected nallocm() error\");\n\trsz = 0;\n\tassert_d_eq(allocm(&p, &rsz, sz, ALLOCM_ZERO), ALLOCM_SUCCESS,\n\t    \"Unexpected allocm() error\");\n\tassert_zu_eq(nsz, rsz, \"nallocm()/allocm() rsize mismatch\");\n\tassert_d_eq(dallocm(p, 0), ALLOCM_SUCCESS,\n\t    \"Unexpected dallocm() error\");\n}\nTEST_END\n\nTEST_BEGIN(test_alignment_and_size)\n{\n\tint r;\n\tsize_t nsz, rsz, sz, alignment, total;\n\tunsigned i;\n\tvoid *ps[NITER];\n\n\tfor (i = 0; i < NITER; i++)\n\t\tps[i] = NULL;\n\n\tfor (alignment = 8;\n\t    alignment <= MAXALIGN;\n\t    alignment <<= 1) {\n\t\ttotal = 0;\n\t\tfor (sz = 1;\n\t\t    sz < 3 * alignment && sz < (1U << 31);\n\t\t    sz += (alignment >> (LG_SIZEOF_PTR-1)) - 1) {\n\t\t\tfor (i = 0; i < NITER; i++) {\n\t\t\t\tnsz = 0;\n\t\t\t\tr = nallocm(&nsz, sz, ALLOCM_ALIGN(alignment) |\n\t\t\t\t    ALLOCM_ZERO);\n\t\t\t\tassert_d_eq(r, ALLOCM_SUCCESS,\n\t\t\t\t    \"nallocm() error for alignment=%zu, \"\n\t\t\t\t    \"size=%zu (%#zx): %d\",\n\t\t\t\t    alignment, sz, sz, r);\n\t\t\t\trsz = 0;\n\t\t\t\tr = allocm(&ps[i], &rsz, sz,\n\t\t\t\t    ALLOCM_ALIGN(alignment) | ALLOCM_ZERO);\n\t\t\t\tassert_d_eq(r, ALLOCM_SUCCESS,\n\t\t\t\t    \"allocm() error for alignment=%zu, \"\n\t\t\t\t    \"size=%zu (%#zx): %d\",\n\t\t\t\t    alignment, sz, sz, r);\n\t\t\t\tassert_zu_ge(rsz, sz,\n\t\t\t\t    \"Real size smaller than expected for \"\n\t\t\t\t    \"alignment=%zu, size=%zu\", alignment, sz);\n\t\t\t\tassert_zu_eq(nsz, rsz,\n\t\t\t\t    \"nallocm()/allocm() rsize mismatch for \"\n\t\t\t\t    \"alignment=%zu, size=%zu\", alignment, sz);\n\t\t\t\tassert_ptr_null(\n\t\t\t\t    (void *)((uintptr_t)ps[i] & (alignment-1)),\n\t\t\t\t    \"%p inadequately aligned for\"\n\t\t\t\t    \" alignment=%zu, size=%zu\", ps[i],\n\t\t\t\t    alignment, sz);\n\t\t\t\tsallocm(ps[i], &rsz, 0);\n\t\t\t\ttotal += rsz;\n\t\t\t\tif (total >= (MAXALIGN << 1))\n\t\t\t\t\tbreak;\n\t\t\t}\n\t\t\tfor (i = 0; i < NITER; i++) {\n\t\t\t\tif (ps[i] != NULL) {\n\t\t\t\t\tdallocm(ps[i], 0);\n\t\t\t\t\tps[i] = NULL;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}\nTEST_END\n\nint\nmain(void)\n{\n\n\treturn (test(\n\t    test_basic,\n\t    test_alignment_and_size));\n}\n"
  },
  {
    "path": "extern/deprecated/redis-2.8.21/deps/jemalloc/test/integration/mallocx.c",
    "content": "#include \"test/jemalloc_test.h\"\n\n#define\tCHUNK 0x400000\n#define\tMAXALIGN (((size_t)1) << 25)\n#define\tNITER 4\n\nTEST_BEGIN(test_basic)\n{\n\tsize_t nsz, rsz, sz;\n\tvoid *p;\n\n\tsz = 42;\n\tnsz = nallocx(sz, 0);\n\tassert_zu_ne(nsz, 0, \"Unexpected nallocx() error\");\n\tp = mallocx(sz, 0);\n\tassert_ptr_not_null(p, \"Unexpected mallocx() error\");\n\trsz = sallocx(p, 0);\n\tassert_zu_ge(rsz, sz, \"Real size smaller than expected\");\n\tassert_zu_eq(nsz, rsz, \"nallocx()/sallocx() size mismatch\");\n\tdallocx(p, 0);\n\n\tp = mallocx(sz, 0);\n\tassert_ptr_not_null(p, \"Unexpected mallocx() error\");\n\tdallocx(p, 0);\n\n\tnsz = nallocx(sz, MALLOCX_ZERO);\n\tassert_zu_ne(nsz, 0, \"Unexpected nallocx() error\");\n\tp = mallocx(sz, MALLOCX_ZERO);\n\tassert_ptr_not_null(p, \"Unexpected mallocx() error\");\n\trsz = sallocx(p, 0);\n\tassert_zu_eq(nsz, rsz, \"nallocx()/sallocx() rsize mismatch\");\n\tdallocx(p, 0);\n}\nTEST_END\n\nTEST_BEGIN(test_alignment_and_size)\n{\n\tsize_t nsz, rsz, sz, alignment, total;\n\tunsigned i;\n\tvoid *ps[NITER];\n\n\tfor (i = 0; i < NITER; i++)\n\t\tps[i] = NULL;\n\n\tfor (alignment = 8;\n\t    alignment <= MAXALIGN;\n\t    alignment <<= 1) {\n\t\ttotal = 0;\n\t\tfor (sz = 1;\n\t\t    sz < 3 * alignment && sz < (1U << 31);\n\t\t    sz += (alignment >> (LG_SIZEOF_PTR-1)) - 1) {\n\t\t\tfor (i = 0; i < NITER; i++) {\n\t\t\t\tnsz = nallocx(sz, MALLOCX_ALIGN(alignment) |\n\t\t\t\t    MALLOCX_ZERO);\n\t\t\t\tassert_zu_ne(nsz, 0,\n\t\t\t\t    \"nallocx() error for alignment=%zu, \"\n\t\t\t\t    \"size=%zu (%#zx)\", alignment, sz, sz);\n\t\t\t\tps[i] = mallocx(sz, MALLOCX_ALIGN(alignment) |\n\t\t\t\t    MALLOCX_ZERO);\n\t\t\t\tassert_ptr_not_null(ps[i],\n\t\t\t\t    \"mallocx() error for alignment=%zu, \"\n\t\t\t\t    \"size=%zu (%#zx)\", alignment, sz, sz);\n\t\t\t\trsz = sallocx(ps[i], 0);\n\t\t\t\tassert_zu_ge(rsz, sz,\n\t\t\t\t    \"Real size smaller than expected for \"\n\t\t\t\t    \"alignment=%zu, size=%zu\", alignment, sz);\n\t\t\t\tassert_zu_eq(nsz, rsz,\n\t\t\t\t    \"nallocx()/sallocx() size mismatch for \"\n\t\t\t\t    \"alignment=%zu, size=%zu\", alignment, sz);\n\t\t\t\tassert_ptr_null(\n\t\t\t\t    (void *)((uintptr_t)ps[i] & (alignment-1)),\n\t\t\t\t    \"%p inadequately aligned for\"\n\t\t\t\t    \" alignment=%zu, size=%zu\", ps[i],\n\t\t\t\t    alignment, sz);\n\t\t\t\ttotal += rsz;\n\t\t\t\tif (total >= (MAXALIGN << 1))\n\t\t\t\t\tbreak;\n\t\t\t}\n\t\t\tfor (i = 0; i < NITER; i++) {\n\t\t\t\tif (ps[i] != NULL) {\n\t\t\t\t\tdallocx(ps[i], 0);\n\t\t\t\t\tps[i] = NULL;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}\nTEST_END\n\nint\nmain(void)\n{\n\n\treturn (test(\n\t    test_basic,\n\t    test_alignment_and_size));\n}\n"
  },
  {
    "path": "extern/deprecated/redis-2.8.21/deps/jemalloc/test/integration/mremap.c",
    "content": "#include \"test/jemalloc_test.h\"\n\nTEST_BEGIN(test_mremap)\n{\n\tint err;\n\tsize_t sz, lg_chunk, chunksize, i;\n\tchar *p, *q;\n\n\tsz = sizeof(lg_chunk);\n\terr = mallctl(\"opt.lg_chunk\", &lg_chunk, &sz, NULL, 0);\n\tassert_d_eq(err, 0, \"Error in mallctl(): %s\", strerror(err));\n\tchunksize = ((size_t)1U) << lg_chunk;\n\n\tp = (char *)malloc(chunksize);\n\tassert_ptr_not_null(p, \"malloc(%zu) --> %p\", chunksize, p);\n\tmemset(p, 'a', chunksize);\n\n\tq = (char *)realloc(p, chunksize * 2);\n\tassert_ptr_not_null(q, \"realloc(%p, %zu) --> %p\", p, chunksize * 2,\n\t    q);\n\tfor (i = 0; i < chunksize; i++) {\n\t\tassert_c_eq(q[i], 'a',\n\t\t    \"realloc() should preserve existing bytes across copies\");\n\t}\n\n\tp = q;\n\n\tq = (char *)realloc(p, chunksize);\n\tassert_ptr_not_null(q, \"realloc(%p, %zu) --> %p\", p, chunksize, q);\n\tfor (i = 0; i < chunksize; i++) {\n\t\tassert_c_eq(q[i], 'a',\n\t\t    \"realloc() should preserve existing bytes across copies\");\n\t}\n\n\tfree(q);\n}\nTEST_END\n\nint\nmain(void)\n{\n\n\treturn (test(\n\t    test_mremap));\n}\n"
  },
  {
    "path": "extern/deprecated/redis-2.8.21/deps/jemalloc/test/integration/posix_memalign.c",
    "content": "#include \"test/jemalloc_test.h\"\n\n#define\tCHUNK 0x400000\n/* #define MAXALIGN ((size_t)UINT64_C(0x80000000000)) */\n#define\tMAXALIGN ((size_t)0x2000000LU)\n#define\tNITER 4\n\nTEST_BEGIN(test_alignment_errors)\n{\n\tsize_t alignment;\n\tvoid *p;\n\n\tfor (alignment = 0; alignment < sizeof(void *); alignment++) {\n\t\tassert_d_eq(posix_memalign(&p, alignment, 1), EINVAL,\n\t\t    \"Expected error for invalid alignment %zu\",\n\t\t    alignment);\n\t}\n\n\tfor (alignment = sizeof(size_t); alignment < MAXALIGN;\n\t    alignment <<= 1) {\n\t\tassert_d_ne(posix_memalign(&p, alignment + 1, 1), 0,\n\t\t    \"Expected error for invalid alignment %zu\",\n\t\t    alignment + 1);\n\t}\n}\nTEST_END\n\nTEST_BEGIN(test_oom_errors)\n{\n\tsize_t alignment, size;\n\tvoid *p;\n\n#if LG_SIZEOF_PTR == 3\n\talignment = UINT64_C(0x8000000000000000);\n\tsize      = UINT64_C(0x8000000000000000);\n#else\n\talignment = 0x80000000LU;\n\tsize      = 0x80000000LU;\n#endif\n\tassert_d_ne(posix_memalign(&p, alignment, size), 0,\n\t    \"Expected error for posix_memalign(&p, %zu, %zu)\",\n\t    alignment, size);\n\n#if LG_SIZEOF_PTR == 3\n\talignment = UINT64_C(0x4000000000000000);\n\tsize      = UINT64_C(0xc000000000000001);\n#else\n\talignment = 0x40000000LU;\n\tsize      = 0xc0000001LU;\n#endif\n\tassert_d_ne(posix_memalign(&p, alignment, size), 0,\n\t    \"Expected error for posix_memalign(&p, %zu, %zu)\",\n\t    alignment, size);\n\n\talignment = 0x10LU;\n#if LG_SIZEOF_PTR == 3\n\tsize = UINT64_C(0xfffffffffffffff0);\n#else\n\tsize = 0xfffffff0LU;\n#endif\n\tassert_d_ne(posix_memalign(&p, alignment, size), 0,\n\t    \"Expected error for posix_memalign(&p, %zu, %zu)\",\n\t    alignment, size);\n}\nTEST_END\n\nTEST_BEGIN(test_alignment_and_size)\n{\n\tsize_t alignment, size, total;\n\tunsigned i;\n\tint err;\n\tvoid *ps[NITER];\n\n\tfor (i = 0; i < NITER; i++)\n\t\tps[i] = NULL;\n\n\tfor (alignment = 8;\n\t    alignment <= MAXALIGN;\n\t    alignment <<= 1) {\n\t\ttotal = 0;\n\t\tfor (size = 1;\n\t\t    size < 3 * alignment && size < (1U << 31);\n\t\t    size += (alignment >> (LG_SIZEOF_PTR-1)) - 1) {\n\t\t\tfor (i = 0; i < NITER; i++) {\n\t\t\t\terr = posix_memalign(&ps[i],\n\t\t\t\t    alignment, size);\n\t\t\t\tif (err) {\n\t\t\t\t\tchar buf[BUFERROR_BUF];\n\n\t\t\t\t\tbuferror(get_errno(), buf, sizeof(buf));\n\t\t\t\t\ttest_fail(\n\t\t\t\t\t    \"Error for alignment=%zu, \"\n\t\t\t\t\t    \"size=%zu (%#zx): %s\",\n\t\t\t\t\t    alignment, size, size, buf);\n\t\t\t\t}\n\t\t\t\ttotal += malloc_usable_size(ps[i]);\n\t\t\t\tif (total >= (MAXALIGN << 1))\n\t\t\t\t\tbreak;\n\t\t\t}\n\t\t\tfor (i = 0; i < NITER; i++) {\n\t\t\t\tif (ps[i] != NULL) {\n\t\t\t\t\tfree(ps[i]);\n\t\t\t\t\tps[i] = NULL;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}\nTEST_END\n\nint\nmain(void)\n{\n\n\treturn (test(\n\t    test_alignment_errors,\n\t    test_oom_errors,\n\t    test_alignment_and_size));\n}\n"
  },
  {
    "path": "extern/deprecated/redis-2.8.21/deps/jemalloc/test/integration/rallocm.c",
    "content": "#include \"test/jemalloc_test.h\"\n\nTEST_BEGIN(test_same_size)\n{\n\tvoid *p, *q;\n\tsize_t sz, tsz;\n\n\tassert_d_eq(allocm(&p, &sz, 42, 0), ALLOCM_SUCCESS,\n\t    \"Unexpected allocm() error\");\n\n\tq = p;\n\tassert_d_eq(rallocm(&q, &tsz, sz, 0, ALLOCM_NO_MOVE), ALLOCM_SUCCESS,\n\t    \"Unexpected rallocm() error\");\n\tassert_ptr_eq(q, p, \"Unexpected object move\");\n\tassert_zu_eq(tsz, sz, \"Unexpected size change: %zu --> %zu\", sz, tsz);\n\n\tassert_d_eq(dallocm(p, 0), ALLOCM_SUCCESS,\n\t    \"Unexpected dallocm() error\");\n}\nTEST_END\n\nTEST_BEGIN(test_extra_no_move)\n{\n\tvoid *p, *q;\n\tsize_t sz, tsz;\n\n\tassert_d_eq(allocm(&p, &sz, 42, 0), ALLOCM_SUCCESS,\n\t    \"Unexpected allocm() error\");\n\n\tq = p;\n\tassert_d_eq(rallocm(&q, &tsz, sz, sz-42, ALLOCM_NO_MOVE),\n\t    ALLOCM_SUCCESS, \"Unexpected rallocm() error\");\n\tassert_ptr_eq(q, p, \"Unexpected object move\");\n\tassert_zu_eq(tsz, sz, \"Unexpected size change: %zu --> %zu\", sz, tsz);\n\n\tassert_d_eq(dallocm(p, 0), ALLOCM_SUCCESS,\n\t    \"Unexpected dallocm() error\");\n}\nTEST_END\n\nTEST_BEGIN(test_no_move_fail)\n{\n\tvoid *p, *q;\n\tsize_t sz, tsz;\n\n\tassert_d_eq(allocm(&p, &sz, 42, 0), ALLOCM_SUCCESS,\n\t    \"Unexpected allocm() error\");\n\n\tq = p;\n\tassert_d_eq(rallocm(&q, &tsz, sz + 5, 0, ALLOCM_NO_MOVE),\n\t    ALLOCM_ERR_NOT_MOVED, \"Unexpected rallocm() result\");\n\tassert_ptr_eq(q, p, \"Unexpected object move\");\n\tassert_zu_eq(tsz, sz, \"Unexpected size change: %zu --> %zu\", sz, tsz);\n\n\tassert_d_eq(dallocm(p, 0), ALLOCM_SUCCESS,\n\t    \"Unexpected dallocm() error\");\n}\nTEST_END\n\nTEST_BEGIN(test_grow_and_shrink)\n{\n\tvoid *p, *q;\n\tsize_t tsz;\n#define\tNCYCLES 3\n\tunsigned i, j;\n#define\tNSZS 2500\n\tsize_t szs[NSZS];\n#define\tMAXSZ ZU(12 * 1024 * 1024)\n\n\tassert_d_eq(allocm(&p, &szs[0], 1, 0), ALLOCM_SUCCESS,\n\t    \"Unexpected allocm() error\");\n\n\tfor (i = 0; i < NCYCLES; i++) {\n\t\tfor (j = 1; j < NSZS && szs[j-1] < MAXSZ; j++) {\n\t\t\tq = p;\n\t\t\tassert_d_eq(rallocm(&q, &szs[j], szs[j-1]+1, 0, 0),\n\t\t\t    ALLOCM_SUCCESS,\n\t\t\t    \"Unexpected rallocm() error for size=%zu-->%zu\",\n\t\t\t    szs[j-1], szs[j-1]+1);\n\t\t\tassert_zu_ne(szs[j], szs[j-1]+1,\n\t\t\t    \"Expected size to at least: %zu\", szs[j-1]+1);\n\t\t\tp = q;\n\t\t}\n\n\t\tfor (j--; j > 0; j--) {\n\t\t\tq = p;\n\t\t\tassert_d_eq(rallocm(&q, &tsz, szs[j-1], 0, 0),\n\t\t\t    ALLOCM_SUCCESS,\n\t\t\t    \"Unexpected rallocm() error for size=%zu-->%zu\",\n\t\t\t    szs[j], szs[j-1]);\n\t\t\tassert_zu_eq(tsz, szs[j-1],\n\t\t\t    \"Expected size=%zu, got size=%zu\", szs[j-1], tsz);\n\t\t\tp = q;\n\t\t}\n\t}\n\n\tassert_d_eq(dallocm(p, 0), ALLOCM_SUCCESS,\n\t    \"Unexpected dallocm() error\");\n}\nTEST_END\n\nint\nmain(void)\n{\n\n\treturn (test(\n\t    test_same_size,\n\t    test_extra_no_move,\n\t    test_no_move_fail,\n\t    test_grow_and_shrink));\n}\n"
  },
  {
    "path": "extern/deprecated/redis-2.8.21/deps/jemalloc/test/integration/rallocx.c",
    "content": "#include \"test/jemalloc_test.h\"\n\nTEST_BEGIN(test_grow_and_shrink)\n{\n\tvoid *p, *q;\n\tsize_t tsz;\n#define\tNCYCLES 3\n\tunsigned i, j;\n#define\tNSZS 2500\n\tsize_t szs[NSZS];\n#define\tMAXSZ ZU(12 * 1024 * 1024)\n\n\tp = mallocx(1, 0);\n\tassert_ptr_not_null(p, \"Unexpected mallocx() error\");\n\tszs[0] = sallocx(p, 0);\n\n\tfor (i = 0; i < NCYCLES; i++) {\n\t\tfor (j = 1; j < NSZS && szs[j-1] < MAXSZ; j++) {\n\t\t\tq = rallocx(p, szs[j-1]+1, 0);\n\t\t\tassert_ptr_not_null(q,\n\t\t\t    \"Unexpected rallocx() error for size=%zu-->%zu\",\n\t\t\t    szs[j-1], szs[j-1]+1);\n\t\t\tszs[j] = sallocx(q, 0);\n\t\t\tassert_zu_ne(szs[j], szs[j-1]+1,\n\t\t\t    \"Expected size to at least: %zu\", szs[j-1]+1);\n\t\t\tp = q;\n\t\t}\n\n\t\tfor (j--; j > 0; j--) {\n\t\t\tq = rallocx(p, szs[j-1], 0);\n\t\t\tassert_ptr_not_null(q,\n\t\t\t    \"Unexpected rallocx() error for size=%zu-->%zu\",\n\t\t\t    szs[j], szs[j-1]);\n\t\t\ttsz = sallocx(q, 0);\n\t\t\tassert_zu_eq(tsz, szs[j-1],\n\t\t\t    \"Expected size=%zu, got size=%zu\", szs[j-1], tsz);\n\t\t\tp = q;\n\t\t}\n\t}\n\n\tdallocx(p, 0);\n#undef MAXSZ\n#undef NSZS\n#undef NCYCLES\n}\nTEST_END\n\nstatic bool\nvalidate_fill(const void *p, uint8_t c, size_t offset, size_t len)\n{\n\tbool ret = false;\n\tconst uint8_t *buf = (const uint8_t *)p;\n\tsize_t i;\n\n\tfor (i = 0; i < len; i++) {\n\t\tuint8_t b = buf[offset+i];\n\t\tif (b != c) {\n\t\t\ttest_fail(\"Allocation at %p contains %#x rather than \"\n\t\t\t    \"%#x at offset %zu\", p, b, c, offset+i);\n\t\t\tret = true;\n\t\t}\n\t}\n\n\treturn (ret);\n}\n\nTEST_BEGIN(test_zero)\n{\n\tvoid *p, *q;\n\tsize_t psz, qsz, i, j;\n\tsize_t start_sizes[] = {1, 3*1024, 63*1024, 4095*1024};\n#define\tFILL_BYTE 0xaaU\n#define\tRANGE 2048\n\n\tfor (i = 0; i < sizeof(start_sizes)/sizeof(size_t); i++) {\n\t\tsize_t start_size = start_sizes[i];\n\t\tp = mallocx(start_size, MALLOCX_ZERO);\n\t\tassert_ptr_not_null(p, \"Unexpected mallocx() error\");\n\t\tpsz = sallocx(p, 0);\n\n\t\tassert_false(validate_fill(p, 0, 0, psz),\n\t\t    \"Expected zeroed memory\");\n\t\tmemset(p, FILL_BYTE, psz);\n\t\tassert_false(validate_fill(p, FILL_BYTE, 0, psz),\n\t\t    \"Expected filled memory\");\n\n\t\tfor (j = 1; j < RANGE; j++) {\n\t\t\tq = rallocx(p, start_size+j, MALLOCX_ZERO);\n\t\t\tassert_ptr_not_null(q, \"Unexpected rallocx() error\");\n\t\t\tqsz = sallocx(q, 0);\n\t\t\tif (q != p || qsz != psz) {\n\t\t\t\tassert_false(validate_fill(q, FILL_BYTE, 0,\n\t\t\t\t    psz), \"Expected filled memory\");\n\t\t\t\tassert_false(validate_fill(q, 0, psz, qsz-psz),\n\t\t\t\t    \"Expected zeroed memory\");\n\t\t\t}\n\t\t\tif (psz != qsz) {\n\t\t\t\tmemset(q+psz, FILL_BYTE, qsz-psz);\n\t\t\t\tpsz = qsz;\n\t\t\t}\n\t\t\tp = q;\n\t\t}\n\t\tassert_false(validate_fill(p, FILL_BYTE, 0, psz),\n\t\t    \"Expected filled memory\");\n\t\tdallocx(p, 0);\n\t}\n#undef FILL_BYTE\n}\nTEST_END\n\nTEST_BEGIN(test_align)\n{\n\tvoid *p, *q;\n\tsize_t align;\n#define\tMAX_ALIGN (ZU(1) << 25)\n\n\talign = ZU(1);\n\tp = mallocx(1, MALLOCX_ALIGN(align));\n\tassert_ptr_not_null(p, \"Unexpected mallocx() error\");\n\n\tfor (align <<= 1; align <= MAX_ALIGN; align <<= 1) {\n\t\tq = rallocx(p, 1, MALLOCX_ALIGN(align));\n\t\tassert_ptr_not_null(q,\n\t\t    \"Unexpected rallocx() error for align=%zu\", align);\n\t\tassert_ptr_null(\n\t\t    (void *)((uintptr_t)q & (align-1)),\n\t\t    \"%p inadequately aligned for align=%zu\",\n\t\t    q, align);\n\t\tp = q;\n\t}\n\tdallocx(p, 0);\n#undef MAX_ALIGN\n}\nTEST_END\n\nTEST_BEGIN(test_lg_align_and_zero)\n{\n\tvoid *p, *q;\n\tsize_t lg_align, sz;\n#define\tMAX_LG_ALIGN 25\n#define\tMAX_VALIDATE (ZU(1) << 22)\n\n\tlg_align = ZU(0);\n\tp = mallocx(1, MALLOCX_LG_ALIGN(lg_align)|MALLOCX_ZERO);\n\tassert_ptr_not_null(p, \"Unexpected mallocx() error\");\n\n\tfor (lg_align++; lg_align <= MAX_LG_ALIGN; lg_align++) {\n\t\tq = rallocx(p, 1, MALLOCX_LG_ALIGN(lg_align)|MALLOCX_ZERO);\n\t\tassert_ptr_not_null(q,\n\t\t    \"Unexpected rallocx() error for lg_align=%zu\", lg_align);\n\t\tassert_ptr_null(\n\t\t    (void *)((uintptr_t)q & ((ZU(1) << lg_align)-1)),\n\t\t    \"%p inadequately aligned for lg_align=%zu\",\n\t\t    q, lg_align);\n\t\tsz = sallocx(q, 0);\n\t\tif ((sz << 1) <= MAX_VALIDATE) {\n\t\t\tassert_false(validate_fill(q, 0, 0, sz),\n\t\t\t    \"Expected zeroed memory\");\n\t\t} else {\n\t\t\tassert_false(validate_fill(q, 0, 0, MAX_VALIDATE),\n\t\t\t    \"Expected zeroed memory\");\n\t\t\tassert_false(validate_fill(q+sz-MAX_VALIDATE, 0, 0,\n\t\t\t    MAX_VALIDATE), \"Expected zeroed memory\");\n\t\t}\n\t\tp = q;\n\t}\n\tdallocx(p, 0);\n#undef MAX_VALIDATE\n#undef MAX_LG_ALIGN\n}\nTEST_END\n\nint\nmain(void)\n{\n\n\treturn (test(\n\t    test_grow_and_shrink,\n\t    test_zero,\n\t    test_align,\n\t    test_lg_align_and_zero));\n}\n"
  },
  {
    "path": "extern/deprecated/redis-2.8.21/deps/jemalloc/test/integration/thread_arena.c",
    "content": "#include \"test/jemalloc_test.h\"\n\n#define\tNTHREADS 10\n\nvoid *\nthd_start(void *arg)\n{\n\tunsigned main_arena_ind = *(unsigned *)arg;\n\tvoid *p;\n\tunsigned arena_ind;\n\tsize_t size;\n\tint err;\n\n\tp = malloc(1);\n\tassert_ptr_not_null(p, \"Error in malloc()\");\n\tfree(p);\n\n\tsize = sizeof(arena_ind);\n\tif ((err = mallctl(\"thread.arena\", &arena_ind, &size, &main_arena_ind,\n\t    sizeof(main_arena_ind)))) {\n\t\tchar buf[BUFERROR_BUF];\n\n\t\tbuferror(err, buf, sizeof(buf));\n\t\ttest_fail(\"Error in mallctl(): %s\", buf);\n\t}\n\n\tsize = sizeof(arena_ind);\n\tif ((err = mallctl(\"thread.arena\", &arena_ind, &size, NULL, 0))) {\n\t\tchar buf[BUFERROR_BUF];\n\n\t\tbuferror(err, buf, sizeof(buf));\n\t\ttest_fail(\"Error in mallctl(): %s\", buf);\n\t}\n\tassert_u_eq(arena_ind, main_arena_ind,\n\t    \"Arena index should be same as for main thread\");\n\n\treturn (NULL);\n}\n\nTEST_BEGIN(test_thread_arena)\n{\n\tvoid *p;\n\tunsigned arena_ind;\n\tsize_t size;\n\tint err;\n\tthd_t thds[NTHREADS];\n\tunsigned i;\n\n\tp = malloc(1);\n\tassert_ptr_not_null(p, \"Error in malloc()\");\n\n\tsize = sizeof(arena_ind);\n\tif ((err = mallctl(\"thread.arena\", &arena_ind, &size, NULL, 0))) {\n\t\tchar buf[BUFERROR_BUF];\n\n\t\tbuferror(err, buf, sizeof(buf));\n\t\ttest_fail(\"Error in mallctl(): %s\", buf);\n\t}\n\n\tfor (i = 0; i < NTHREADS; i++) {\n\t\tthd_create(&thds[i], thd_start,\n\t\t    (void *)&arena_ind);\n\t}\n\n\tfor (i = 0; i < NTHREADS; i++) {\n\t\tintptr_t join_ret;\n\t\tthd_join(thds[i], (void *)&join_ret);\n\t\tassert_zd_eq(join_ret, 0, \"Unexpected thread join error\");\n\t}\n}\nTEST_END\n\nint\nmain(void)\n{\n\n\treturn (test(\n\t    test_thread_arena));\n}\n"
  },
  {
    "path": "extern/deprecated/redis-2.8.21/deps/jemalloc/test/integration/thread_tcache_enabled.c",
    "content": "#include \"test/jemalloc_test.h\"\n\nstatic const bool config_tcache =\n#ifdef JEMALLOC_TCACHE\n    true\n#else\n    false\n#endif\n    ;\n\nvoid *\nthd_start(void *arg)\n{\n\tint err;\n\tsize_t sz;\n\tbool e0, e1;\n\n\tsz = sizeof(bool);\n\tif ((err = mallctl(\"thread.tcache.enabled\", &e0, &sz, NULL, 0))) {\n\t\tif (err == ENOENT) {\n\t\t\tassert_false(config_tcache,\n\t\t\t    \"ENOENT should only be returned if tcache is \"\n\t\t\t    \"disabled\");\n\t\t}\n\t\tgoto label_ENOENT;\n\t}\n\n\tif (e0) {\n\t\te1 = false;\n\t\tassert_d_eq(mallctl(\"thread.tcache.enabled\", &e0, &sz, &e1, sz),\n\t\t    0, \"Unexpected mallctl() error\");\n\t\tassert_true(e0, \"tcache should be enabled\");\n\t}\n\n\te1 = true;\n\tassert_d_eq(mallctl(\"thread.tcache.enabled\", &e0, &sz, &e1, sz), 0,\n\t    \"Unexpected mallctl() error\");\n\tassert_false(e0, \"tcache should be disabled\");\n\n\te1 = true;\n\tassert_d_eq(mallctl(\"thread.tcache.enabled\", &e0, &sz, &e1, sz), 0,\n\t    \"Unexpected mallctl() error\");\n\tassert_true(e0, \"tcache should be enabled\");\n\n\te1 = false;\n\tassert_d_eq(mallctl(\"thread.tcache.enabled\", &e0, &sz, &e1, sz), 0,\n\t    \"Unexpected mallctl() error\");\n\tassert_true(e0, \"tcache should be enabled\");\n\n\te1 = false;\n\tassert_d_eq(mallctl(\"thread.tcache.enabled\", &e0, &sz, &e1, sz), 0,\n\t    \"Unexpected mallctl() error\");\n\tassert_false(e0, \"tcache should be disabled\");\n\n\tfree(malloc(1));\n\te1 = true;\n\tassert_d_eq(mallctl(\"thread.tcache.enabled\", &e0, &sz, &e1, sz), 0,\n\t    \"Unexpected mallctl() error\");\n\tassert_false(e0, \"tcache should be disabled\");\n\n\tfree(malloc(1));\n\te1 = true;\n\tassert_d_eq(mallctl(\"thread.tcache.enabled\", &e0, &sz, &e1, sz), 0,\n\t    \"Unexpected mallctl() error\");\n\tassert_true(e0, \"tcache should be enabled\");\n\n\tfree(malloc(1));\n\te1 = false;\n\tassert_d_eq(mallctl(\"thread.tcache.enabled\", &e0, &sz, &e1, sz), 0,\n\t    \"Unexpected mallctl() error\");\n\tassert_true(e0, \"tcache should be enabled\");\n\n\tfree(malloc(1));\n\te1 = false;\n\tassert_d_eq(mallctl(\"thread.tcache.enabled\", &e0, &sz, &e1, sz), 0,\n\t    \"Unexpected mallctl() error\");\n\tassert_false(e0, \"tcache should be disabled\");\n\n\tfree(malloc(1));\n\treturn (NULL);\nlabel_ENOENT:\n\ttest_skip(\"\\\"thread.tcache.enabled\\\" mallctl not available\");\n\treturn (NULL);\n}\n\nTEST_BEGIN(test_main_thread)\n{\n\n\tthd_start(NULL);\n}\nTEST_END\n\nTEST_BEGIN(test_subthread)\n{\n\tthd_t thd;\n\n\tthd_create(&thd, thd_start, NULL);\n\tthd_join(thd, NULL);\n}\nTEST_END\n\nint\nmain(void)\n{\n\n\t/* Run tests multiple times to check for bad interactions. */\n\treturn (test(\n\t    test_main_thread,\n\t    test_subthread,\n\t    test_main_thread,\n\t    test_subthread,\n\t    test_main_thread));\n}\n"
  },
  {
    "path": "extern/deprecated/redis-2.8.21/deps/jemalloc/test/integration/xallocx.c",
    "content": "#include \"test/jemalloc_test.h\"\n\nTEST_BEGIN(test_same_size)\n{\n\tvoid *p;\n\tsize_t sz, tsz;\n\n\tp = mallocx(42, 0);\n\tassert_ptr_not_null(p, \"Unexpected mallocx() error\");\n\tsz = sallocx(p, 0);\n\n\ttsz = xallocx(p, sz, 0, 0);\n\tassert_zu_eq(tsz, sz, \"Unexpected size change: %zu --> %zu\", sz, tsz);\n\n\tdallocx(p, 0);\n}\nTEST_END\n\nTEST_BEGIN(test_extra_no_move)\n{\n\tvoid *p;\n\tsize_t sz, tsz;\n\n\tp = mallocx(42, 0);\n\tassert_ptr_not_null(p, \"Unexpected mallocx() error\");\n\tsz = sallocx(p, 0);\n\n\ttsz = xallocx(p, sz, sz-42, 0);\n\tassert_zu_eq(tsz, sz, \"Unexpected size change: %zu --> %zu\", sz, tsz);\n\n\tdallocx(p, 0);\n}\nTEST_END\n\nTEST_BEGIN(test_no_move_fail)\n{\n\tvoid *p;\n\tsize_t sz, tsz;\n\n\tp = mallocx(42, 0);\n\tassert_ptr_not_null(p, \"Unexpected mallocx() error\");\n\tsz = sallocx(p, 0);\n\n\ttsz = xallocx(p, sz + 5, 0, 0);\n\tassert_zu_eq(tsz, sz, \"Unexpected size change: %zu --> %zu\", sz, tsz);\n\n\tdallocx(p, 0);\n}\nTEST_END\n\nint\nmain(void)\n{\n\n\treturn (test(\n\t    test_same_size,\n\t    test_extra_no_move,\n\t    test_no_move_fail));\n}\n"
  },
  {
    "path": "extern/deprecated/redis-2.8.21/deps/jemalloc/test/src/SFMT.c",
    "content": "/*\n * This file derives from SFMT 1.3.3\n * (http://www.math.sci.hiroshima-u.ac.jp/~m-mat/MT/SFMT/index.html), which was\n * released under the terms of the following license:\n *\n *   Copyright (c) 2006,2007 Mutsuo Saito, Makoto Matsumoto and Hiroshima\n *   University. All rights reserved.\n *\n *   Redistribution and use in source and binary forms, with or without\n *   modification, are permitted provided that the following conditions are\n *   met:\n *\n *       * Redistributions of source code must retain the above copyright\n *         notice, this list of conditions and the following disclaimer.\n *       * Redistributions in binary form must reproduce the above\n *         copyright notice, this list of conditions and the following\n *         disclaimer in the documentation and/or other materials provided\n *         with the distribution.\n *       * Neither the name of the Hiroshima University nor the names of\n *         its contributors may be used to endorse or promote products\n *         derived from this software without specific prior written\n *         permission.\n *\n *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n *   \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\n *   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\n *   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\n *   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n *   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\n *   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n *   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n *   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n *   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n *   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n/** \n * @file  SFMT.c\n * @brief SIMD oriented Fast Mersenne Twister(SFMT)\n *\n * @author Mutsuo Saito (Hiroshima University)\n * @author Makoto Matsumoto (Hiroshima University)\n *\n * Copyright (C) 2006,2007 Mutsuo Saito, Makoto Matsumoto and Hiroshima\n * University. All rights reserved.\n *\n * The new BSD License is applied to this software, see LICENSE.txt\n */\n#define\tSFMT_C_\n#include \"test/jemalloc_test.h\"\n#include \"test/SFMT-params.h\"\n\n#if defined(JEMALLOC_BIG_ENDIAN) && !defined(BIG_ENDIAN64)\n#define BIG_ENDIAN64 1\n#endif\n#if defined(__BIG_ENDIAN__) && !defined(__amd64) && !defined(BIG_ENDIAN64)\n#define BIG_ENDIAN64 1\n#endif\n#if defined(HAVE_ALTIVEC) && !defined(BIG_ENDIAN64)\n#define BIG_ENDIAN64 1\n#endif\n#if defined(ONLY64) && !defined(BIG_ENDIAN64)\n  #if defined(__GNUC__)\n    #error \"-DONLY64 must be specified with -DBIG_ENDIAN64\"\n  #endif\n#undef ONLY64\n#endif\n/*------------------------------------------------------\n  128-bit SIMD data type for Altivec, SSE2 or standard C\n  ------------------------------------------------------*/\n#if defined(HAVE_ALTIVEC)\n/** 128-bit data structure */\nunion W128_T {\n    vector unsigned int s;\n    uint32_t u[4];\n};\n/** 128-bit data type */\ntypedef union W128_T w128_t;\n\n#elif defined(HAVE_SSE2)\n/** 128-bit data structure */\nunion W128_T {\n    __m128i si;\n    uint32_t u[4];\n};\n/** 128-bit data type */\ntypedef union W128_T w128_t;\n\n#else\n\n/** 128-bit data structure */\nstruct W128_T {\n    uint32_t u[4];\n};\n/** 128-bit data type */\ntypedef struct W128_T w128_t;\n\n#endif\n\nstruct sfmt_s {\n    /** the 128-bit internal state array */\n    w128_t sfmt[N];\n    /** index counter to the 32-bit internal state array */\n    int idx;\n    /** a flag: it is 0 if and only if the internal state is not yet\n     * initialized. */\n    int initialized;\n};\n\n/*--------------------------------------\n  FILE GLOBAL VARIABLES\n  internal state, index counter and flag \n  --------------------------------------*/\n\n/** a parity check vector which certificate the period of 2^{MEXP} */\nstatic uint32_t parity[4] = {PARITY1, PARITY2, PARITY3, PARITY4};\n\n/*----------------\n  STATIC FUNCTIONS\n  ----------------*/\nJEMALLOC_INLINE_C int idxof(int i);\n#if (!defined(HAVE_ALTIVEC)) && (!defined(HAVE_SSE2))\nJEMALLOC_INLINE_C void rshift128(w128_t *out,  w128_t const *in, int shift);\nJEMALLOC_INLINE_C void lshift128(w128_t *out,  w128_t const *in, int shift);\n#endif\nJEMALLOC_INLINE_C void gen_rand_all(sfmt_t *ctx);\nJEMALLOC_INLINE_C void gen_rand_array(sfmt_t *ctx, w128_t *array, int size);\nJEMALLOC_INLINE_C uint32_t func1(uint32_t x);\nJEMALLOC_INLINE_C uint32_t func2(uint32_t x);\nstatic void period_certification(sfmt_t *ctx);\n#if defined(BIG_ENDIAN64) && !defined(ONLY64)\nJEMALLOC_INLINE_C void swap(w128_t *array, int size);\n#endif\n\n#if defined(HAVE_ALTIVEC)\n  #include \"test/SFMT-alti.h\"\n#elif defined(HAVE_SSE2)\n  #include \"test/SFMT-sse2.h\"\n#endif\n\n/**\n * This function simulate a 64-bit index of LITTLE ENDIAN \n * in BIG ENDIAN machine.\n */\n#ifdef ONLY64\nJEMALLOC_INLINE_C int idxof(int i) {\n    return i ^ 1;\n}\n#else\nJEMALLOC_INLINE_C int idxof(int i) {\n    return i;\n}\n#endif\n/**\n * This function simulates SIMD 128-bit right shift by the standard C.\n * The 128-bit integer given in in is shifted by (shift * 8) bits.\n * This function simulates the LITTLE ENDIAN SIMD.\n * @param out the output of this function\n * @param in the 128-bit data to be shifted\n * @param shift the shift value\n */\n#if (!defined(HAVE_ALTIVEC)) && (!defined(HAVE_SSE2))\n#ifdef ONLY64\nJEMALLOC_INLINE_C void rshift128(w128_t *out, w128_t const *in, int shift) {\n    uint64_t th, tl, oh, ol;\n\n    th = ((uint64_t)in->u[2] << 32) | ((uint64_t)in->u[3]);\n    tl = ((uint64_t)in->u[0] << 32) | ((uint64_t)in->u[1]);\n\n    oh = th >> (shift * 8);\n    ol = tl >> (shift * 8);\n    ol |= th << (64 - shift * 8);\n    out->u[0] = (uint32_t)(ol >> 32);\n    out->u[1] = (uint32_t)ol;\n    out->u[2] = (uint32_t)(oh >> 32);\n    out->u[3] = (uint32_t)oh;\n}\n#else\nJEMALLOC_INLINE_C void rshift128(w128_t *out, w128_t const *in, int shift) {\n    uint64_t th, tl, oh, ol;\n\n    th = ((uint64_t)in->u[3] << 32) | ((uint64_t)in->u[2]);\n    tl = ((uint64_t)in->u[1] << 32) | ((uint64_t)in->u[0]);\n\n    oh = th >> (shift * 8);\n    ol = tl >> (shift * 8);\n    ol |= th << (64 - shift * 8);\n    out->u[1] = (uint32_t)(ol >> 32);\n    out->u[0] = (uint32_t)ol;\n    out->u[3] = (uint32_t)(oh >> 32);\n    out->u[2] = (uint32_t)oh;\n}\n#endif\n/**\n * This function simulates SIMD 128-bit left shift by the standard C.\n * The 128-bit integer given in in is shifted by (shift * 8) bits.\n * This function simulates the LITTLE ENDIAN SIMD.\n * @param out the output of this function\n * @param in the 128-bit data to be shifted\n * @param shift the shift value\n */\n#ifdef ONLY64\nJEMALLOC_INLINE_C void lshift128(w128_t *out, w128_t const *in, int shift) {\n    uint64_t th, tl, oh, ol;\n\n    th = ((uint64_t)in->u[2] << 32) | ((uint64_t)in->u[3]);\n    tl = ((uint64_t)in->u[0] << 32) | ((uint64_t)in->u[1]);\n\n    oh = th << (shift * 8);\n    ol = tl << (shift * 8);\n    oh |= tl >> (64 - shift * 8);\n    out->u[0] = (uint32_t)(ol >> 32);\n    out->u[1] = (uint32_t)ol;\n    out->u[2] = (uint32_t)(oh >> 32);\n    out->u[3] = (uint32_t)oh;\n}\n#else\nJEMALLOC_INLINE_C void lshift128(w128_t *out, w128_t const *in, int shift) {\n    uint64_t th, tl, oh, ol;\n\n    th = ((uint64_t)in->u[3] << 32) | ((uint64_t)in->u[2]);\n    tl = ((uint64_t)in->u[1] << 32) | ((uint64_t)in->u[0]);\n\n    oh = th << (shift * 8);\n    ol = tl << (shift * 8);\n    oh |= tl >> (64 - shift * 8);\n    out->u[1] = (uint32_t)(ol >> 32);\n    out->u[0] = (uint32_t)ol;\n    out->u[3] = (uint32_t)(oh >> 32);\n    out->u[2] = (uint32_t)oh;\n}\n#endif\n#endif\n\n/**\n * This function represents the recursion formula.\n * @param r output\n * @param a a 128-bit part of the internal state array\n * @param b a 128-bit part of the internal state array\n * @param c a 128-bit part of the internal state array\n * @param d a 128-bit part of the internal state array\n */\n#if (!defined(HAVE_ALTIVEC)) && (!defined(HAVE_SSE2))\n#ifdef ONLY64\nJEMALLOC_INLINE_C void do_recursion(w128_t *r, w128_t *a, w128_t *b, w128_t *c,\n\t\t\t\tw128_t *d) {\n    w128_t x;\n    w128_t y;\n\n    lshift128(&x, a, SL2);\n    rshift128(&y, c, SR2);\n    r->u[0] = a->u[0] ^ x.u[0] ^ ((b->u[0] >> SR1) & MSK2) ^ y.u[0] \n\t^ (d->u[0] << SL1);\n    r->u[1] = a->u[1] ^ x.u[1] ^ ((b->u[1] >> SR1) & MSK1) ^ y.u[1] \n\t^ (d->u[1] << SL1);\n    r->u[2] = a->u[2] ^ x.u[2] ^ ((b->u[2] >> SR1) & MSK4) ^ y.u[2] \n\t^ (d->u[2] << SL1);\n    r->u[3] = a->u[3] ^ x.u[3] ^ ((b->u[3] >> SR1) & MSK3) ^ y.u[3] \n\t^ (d->u[3] << SL1);\n}\n#else\nJEMALLOC_INLINE_C void do_recursion(w128_t *r, w128_t *a, w128_t *b, w128_t *c,\n\t\t\t\tw128_t *d) {\n    w128_t x;\n    w128_t y;\n\n    lshift128(&x, a, SL2);\n    rshift128(&y, c, SR2);\n    r->u[0] = a->u[0] ^ x.u[0] ^ ((b->u[0] >> SR1) & MSK1) ^ y.u[0] \n\t^ (d->u[0] << SL1);\n    r->u[1] = a->u[1] ^ x.u[1] ^ ((b->u[1] >> SR1) & MSK2) ^ y.u[1] \n\t^ (d->u[1] << SL1);\n    r->u[2] = a->u[2] ^ x.u[2] ^ ((b->u[2] >> SR1) & MSK3) ^ y.u[2] \n\t^ (d->u[2] << SL1);\n    r->u[3] = a->u[3] ^ x.u[3] ^ ((b->u[3] >> SR1) & MSK4) ^ y.u[3] \n\t^ (d->u[3] << SL1);\n}\n#endif\n#endif\n\n#if (!defined(HAVE_ALTIVEC)) && (!defined(HAVE_SSE2))\n/**\n * This function fills the internal state array with pseudorandom\n * integers.\n */\nJEMALLOC_INLINE_C void gen_rand_all(sfmt_t *ctx) {\n    int i;\n    w128_t *r1, *r2;\n\n    r1 = &ctx->sfmt[N - 2];\n    r2 = &ctx->sfmt[N - 1];\n    for (i = 0; i < N - POS1; i++) {\n\tdo_recursion(&ctx->sfmt[i], &ctx->sfmt[i], &ctx->sfmt[i + POS1], r1,\n\t  r2);\n\tr1 = r2;\n\tr2 = &ctx->sfmt[i];\n    }\n    for (; i < N; i++) {\n\tdo_recursion(&ctx->sfmt[i], &ctx->sfmt[i], &ctx->sfmt[i + POS1 - N], r1,\n\t  r2);\n\tr1 = r2;\n\tr2 = &ctx->sfmt[i];\n    }\n}\n\n/**\n * This function fills the user-specified array with pseudorandom\n * integers.\n *\n * @param array an 128-bit array to be filled by pseudorandom numbers.  \n * @param size number of 128-bit pseudorandom numbers to be generated.\n */\nJEMALLOC_INLINE_C void gen_rand_array(sfmt_t *ctx, w128_t *array, int size) {\n    int i, j;\n    w128_t *r1, *r2;\n\n    r1 = &ctx->sfmt[N - 2];\n    r2 = &ctx->sfmt[N - 1];\n    for (i = 0; i < N - POS1; i++) {\n\tdo_recursion(&array[i], &ctx->sfmt[i], &ctx->sfmt[i + POS1], r1, r2);\n\tr1 = r2;\n\tr2 = &array[i];\n    }\n    for (; i < N; i++) {\n\tdo_recursion(&array[i], &ctx->sfmt[i], &array[i + POS1 - N], r1, r2);\n\tr1 = r2;\n\tr2 = &array[i];\n    }\n    for (; i < size - N; i++) {\n\tdo_recursion(&array[i], &array[i - N], &array[i + POS1 - N], r1, r2);\n\tr1 = r2;\n\tr2 = &array[i];\n    }\n    for (j = 0; j < 2 * N - size; j++) {\n\tctx->sfmt[j] = array[j + size - N];\n    }\n    for (; i < size; i++, j++) {\n\tdo_recursion(&array[i], &array[i - N], &array[i + POS1 - N], r1, r2);\n\tr1 = r2;\n\tr2 = &array[i];\n\tctx->sfmt[j] = array[i];\n    }\n}\n#endif\n\n#if defined(BIG_ENDIAN64) && !defined(ONLY64) && !defined(HAVE_ALTIVEC)\nJEMALLOC_INLINE_C void swap(w128_t *array, int size) {\n    int i;\n    uint32_t x, y;\n\n    for (i = 0; i < size; i++) {\n\tx = array[i].u[0];\n\ty = array[i].u[2];\n\tarray[i].u[0] = array[i].u[1];\n\tarray[i].u[2] = array[i].u[3];\n\tarray[i].u[1] = x;\n\tarray[i].u[3] = y;\n    }\n}\n#endif\n/**\n * This function represents a function used in the initialization\n * by init_by_array\n * @param x 32-bit integer\n * @return 32-bit integer\n */\nstatic uint32_t func1(uint32_t x) {\n    return (x ^ (x >> 27)) * (uint32_t)1664525UL;\n}\n\n/**\n * This function represents a function used in the initialization\n * by init_by_array\n * @param x 32-bit integer\n * @return 32-bit integer\n */\nstatic uint32_t func2(uint32_t x) {\n    return (x ^ (x >> 27)) * (uint32_t)1566083941UL;\n}\n\n/**\n * This function certificate the period of 2^{MEXP}\n */\nstatic void period_certification(sfmt_t *ctx) {\n    int inner = 0;\n    int i, j;\n    uint32_t work;\n    uint32_t *psfmt32 = &ctx->sfmt[0].u[0];\n\n    for (i = 0; i < 4; i++)\n\tinner ^= psfmt32[idxof(i)] & parity[i];\n    for (i = 16; i > 0; i >>= 1)\n\tinner ^= inner >> i;\n    inner &= 1;\n    /* check OK */\n    if (inner == 1) {\n\treturn;\n    }\n    /* check NG, and modification */\n    for (i = 0; i < 4; i++) {\n\twork = 1;\n\tfor (j = 0; j < 32; j++) {\n\t    if ((work & parity[i]) != 0) {\n\t\tpsfmt32[idxof(i)] ^= work;\n\t\treturn;\n\t    }\n\t    work = work << 1;\n\t}\n    }\n}\n\n/*----------------\n  PUBLIC FUNCTIONS\n  ----------------*/\n/**\n * This function returns the identification string.\n * The string shows the word size, the Mersenne exponent,\n * and all parameters of this generator.\n */\nconst char *get_idstring(void) {\n    return IDSTR;\n}\n\n/**\n * This function returns the minimum size of array used for \\b\n * fill_array32() function.\n * @return minimum size of array used for fill_array32() function.\n */\nint get_min_array_size32(void) {\n    return N32;\n}\n\n/**\n * This function returns the minimum size of array used for \\b\n * fill_array64() function.\n * @return minimum size of array used for fill_array64() function.\n */\nint get_min_array_size64(void) {\n    return N64;\n}\n\n#ifndef ONLY64\n/**\n * This function generates and returns 32-bit pseudorandom number.\n * init_gen_rand or init_by_array must be called before this function.\n * @return 32-bit pseudorandom number\n */\nuint32_t gen_rand32(sfmt_t *ctx) {\n    uint32_t r;\n    uint32_t *psfmt32 = &ctx->sfmt[0].u[0];\n\n    assert(ctx->initialized);\n    if (ctx->idx >= N32) {\n\tgen_rand_all(ctx);\n\tctx->idx = 0;\n    }\n    r = psfmt32[ctx->idx++];\n    return r;\n}\n\n/* Generate a random integer in [0..limit). */\nuint32_t gen_rand32_range(sfmt_t *ctx, uint32_t limit) {\n    uint32_t ret, above;\n\n    above = 0xffffffffU - (0xffffffffU % limit);\n    while (1) {\n        ret = gen_rand32(ctx);\n        if (ret < above) {\n            ret %= limit;\n            break;\n        }\n    }\n    return ret;\n}\n#endif\n/**\n * This function generates and returns 64-bit pseudorandom number.\n * init_gen_rand or init_by_array must be called before this function.\n * The function gen_rand64 should not be called after gen_rand32,\n * unless an initialization is again executed. \n * @return 64-bit pseudorandom number\n */\nuint64_t gen_rand64(sfmt_t *ctx) {\n#if defined(BIG_ENDIAN64) && !defined(ONLY64)\n    uint32_t r1, r2;\n    uint32_t *psfmt32 = &ctx->sfmt[0].u[0];\n#else\n    uint64_t r;\n    uint64_t *psfmt64 = (uint64_t *)&ctx->sfmt[0].u[0];\n#endif\n\n    assert(ctx->initialized);\n    assert(ctx->idx % 2 == 0);\n\n    if (ctx->idx >= N32) {\n\tgen_rand_all(ctx);\n\tctx->idx = 0;\n    }\n#if defined(BIG_ENDIAN64) && !defined(ONLY64)\n    r1 = psfmt32[ctx->idx];\n    r2 = psfmt32[ctx->idx + 1];\n    ctx->idx += 2;\n    return ((uint64_t)r2 << 32) | r1;\n#else\n    r = psfmt64[ctx->idx / 2];\n    ctx->idx += 2;\n    return r;\n#endif\n}\n\n/* Generate a random integer in [0..limit). */\nuint64_t gen_rand64_range(sfmt_t *ctx, uint64_t limit) {\n    uint64_t ret, above;\n\n    above = 0xffffffffffffffffLLU - (0xffffffffffffffffLLU  % limit);\n    while (1) {\n        ret = gen_rand64(ctx);\n        if (ret < above) {\n            ret %= limit;\n            break;\n        }\n    }\n    return ret;\n}\n\n#ifndef ONLY64\n/**\n * This function generates pseudorandom 32-bit integers in the\n * specified array[] by one call. The number of pseudorandom integers\n * is specified by the argument size, which must be at least 624 and a\n * multiple of four.  The generation by this function is much faster\n * than the following gen_rand function.\n *\n * For initialization, init_gen_rand or init_by_array must be called\n * before the first call of this function. This function can not be\n * used after calling gen_rand function, without initialization.\n *\n * @param array an array where pseudorandom 32-bit integers are filled\n * by this function.  The pointer to the array must be \\b \"aligned\"\n * (namely, must be a multiple of 16) in the SIMD version, since it\n * refers to the address of a 128-bit integer.  In the standard C\n * version, the pointer is arbitrary.\n *\n * @param size the number of 32-bit pseudorandom integers to be\n * generated.  size must be a multiple of 4, and greater than or equal\n * to (MEXP / 128 + 1) * 4.\n *\n * @note \\b memalign or \\b posix_memalign is available to get aligned\n * memory. Mac OSX doesn't have these functions, but \\b malloc of OSX\n * returns the pointer to the aligned memory block.\n */\nvoid fill_array32(sfmt_t *ctx, uint32_t *array, int size) {\n    assert(ctx->initialized);\n    assert(ctx->idx == N32);\n    assert(size % 4 == 0);\n    assert(size >= N32);\n\n    gen_rand_array(ctx, (w128_t *)array, size / 4);\n    ctx->idx = N32;\n}\n#endif\n\n/**\n * This function generates pseudorandom 64-bit integers in the\n * specified array[] by one call. The number of pseudorandom integers\n * is specified by the argument size, which must be at least 312 and a\n * multiple of two.  The generation by this function is much faster\n * than the following gen_rand function.\n *\n * For initialization, init_gen_rand or init_by_array must be called\n * before the first call of this function. This function can not be\n * used after calling gen_rand function, without initialization.\n *\n * @param array an array where pseudorandom 64-bit integers are filled\n * by this function.  The pointer to the array must be \"aligned\"\n * (namely, must be a multiple of 16) in the SIMD version, since it\n * refers to the address of a 128-bit integer.  In the standard C\n * version, the pointer is arbitrary.\n *\n * @param size the number of 64-bit pseudorandom integers to be\n * generated.  size must be a multiple of 2, and greater than or equal\n * to (MEXP / 128 + 1) * 2\n *\n * @note \\b memalign or \\b posix_memalign is available to get aligned\n * memory. Mac OSX doesn't have these functions, but \\b malloc of OSX\n * returns the pointer to the aligned memory block.\n */\nvoid fill_array64(sfmt_t *ctx, uint64_t *array, int size) {\n    assert(ctx->initialized);\n    assert(ctx->idx == N32);\n    assert(size % 2 == 0);\n    assert(size >= N64);\n\n    gen_rand_array(ctx, (w128_t *)array, size / 2);\n    ctx->idx = N32;\n\n#if defined(BIG_ENDIAN64) && !defined(ONLY64)\n    swap((w128_t *)array, size /2);\n#endif\n}\n\n/**\n * This function initializes the internal state array with a 32-bit\n * integer seed.\n *\n * @param seed a 32-bit integer used as the seed.\n */\nsfmt_t *init_gen_rand(uint32_t seed) {\n    void *p;\n    sfmt_t *ctx;\n    int i;\n    uint32_t *psfmt32;\n\n    if (posix_memalign(&p, sizeof(w128_t), sizeof(sfmt_t)) != 0) {\n\treturn NULL;\n    }\n    ctx = (sfmt_t *)p;\n    psfmt32 = &ctx->sfmt[0].u[0];\n\n    psfmt32[idxof(0)] = seed;\n    for (i = 1; i < N32; i++) {\n\tpsfmt32[idxof(i)] = 1812433253UL * (psfmt32[idxof(i - 1)] \n\t\t\t\t\t    ^ (psfmt32[idxof(i - 1)] >> 30))\n\t    + i;\n    }\n    ctx->idx = N32;\n    period_certification(ctx);\n    ctx->initialized = 1;\n\n    return ctx;\n}\n\n/**\n * This function initializes the internal state array,\n * with an array of 32-bit integers used as the seeds\n * @param init_key the array of 32-bit integers, used as a seed.\n * @param key_length the length of init_key.\n */\nsfmt_t *init_by_array(uint32_t *init_key, int key_length) {\n    void *p;\n    sfmt_t *ctx;\n    int i, j, count;\n    uint32_t r;\n    int lag;\n    int mid;\n    int size = N * 4;\n    uint32_t *psfmt32;\n\n    if (posix_memalign(&p, sizeof(w128_t), sizeof(sfmt_t)) != 0) {\n\treturn NULL;\n    }\n    ctx = (sfmt_t *)p;\n    psfmt32 = &ctx->sfmt[0].u[0];\n\n    if (size >= 623) {\n\tlag = 11;\n    } else if (size >= 68) {\n\tlag = 7;\n    } else if (size >= 39) {\n\tlag = 5;\n    } else {\n\tlag = 3;\n    }\n    mid = (size - lag) / 2;\n\n    memset(ctx->sfmt, 0x8b, sizeof(ctx->sfmt));\n    if (key_length + 1 > N32) {\n\tcount = key_length + 1;\n    } else {\n\tcount = N32;\n    }\n    r = func1(psfmt32[idxof(0)] ^ psfmt32[idxof(mid)] \n\t      ^ psfmt32[idxof(N32 - 1)]);\n    psfmt32[idxof(mid)] += r;\n    r += key_length;\n    psfmt32[idxof(mid + lag)] += r;\n    psfmt32[idxof(0)] = r;\n\n    count--;\n    for (i = 1, j = 0; (j < count) && (j < key_length); j++) {\n\tr = func1(psfmt32[idxof(i)] ^ psfmt32[idxof((i + mid) % N32)] \n\t\t  ^ psfmt32[idxof((i + N32 - 1) % N32)]);\n\tpsfmt32[idxof((i + mid) % N32)] += r;\n\tr += init_key[j] + i;\n\tpsfmt32[idxof((i + mid + lag) % N32)] += r;\n\tpsfmt32[idxof(i)] = r;\n\ti = (i + 1) % N32;\n    }\n    for (; j < count; j++) {\n\tr = func1(psfmt32[idxof(i)] ^ psfmt32[idxof((i + mid) % N32)] \n\t\t  ^ psfmt32[idxof((i + N32 - 1) % N32)]);\n\tpsfmt32[idxof((i + mid) % N32)] += r;\n\tr += i;\n\tpsfmt32[idxof((i + mid + lag) % N32)] += r;\n\tpsfmt32[idxof(i)] = r;\n\ti = (i + 1) % N32;\n    }\n    for (j = 0; j < N32; j++) {\n\tr = func2(psfmt32[idxof(i)] + psfmt32[idxof((i + mid) % N32)] \n\t\t  + psfmt32[idxof((i + N32 - 1) % N32)]);\n\tpsfmt32[idxof((i + mid) % N32)] ^= r;\n\tr -= i;\n\tpsfmt32[idxof((i + mid + lag) % N32)] ^= r;\n\tpsfmt32[idxof(i)] = r;\n\ti = (i + 1) % N32;\n    }\n\n    ctx->idx = N32;\n    period_certification(ctx);\n    ctx->initialized = 1;\n\n    return ctx;\n}\n\nvoid fini_gen_rand(sfmt_t *ctx) {\n    assert(ctx != NULL);\n\n    ctx->initialized = 0;\n    free(ctx);\n}\n"
  },
  {
    "path": "extern/deprecated/redis-2.8.21/deps/jemalloc/test/src/math.c",
    "content": "#define\tMATH_C_\n#include \"test/jemalloc_test.h\"\n"
  },
  {
    "path": "extern/deprecated/redis-2.8.21/deps/jemalloc/test/src/mtx.c",
    "content": "#include \"test/jemalloc_test.h\"\n\nbool\nmtx_init(mtx_t *mtx)\n{\n\n#ifdef _WIN32\n\tif (!InitializeCriticalSectionAndSpinCount(&mtx->lock, _CRT_SPINCOUNT))\n\t\treturn (true);\n#elif (defined(JEMALLOC_OSSPIN))\n\tmtx->lock = 0;\n#else\n\tpthread_mutexattr_t attr;\n\n\tif (pthread_mutexattr_init(&attr) != 0)\n\t\treturn (true);\n\tpthread_mutexattr_settype(&attr, PTHREAD_MUTEX_DEFAULT);\n\tif (pthread_mutex_init(&mtx->lock, &attr) != 0) {\n\t\tpthread_mutexattr_destroy(&attr);\n\t\treturn (true);\n\t}\n\tpthread_mutexattr_destroy(&attr);\n#endif\n\treturn (false);\n}\n\nvoid\nmtx_fini(mtx_t *mtx)\n{\n\n#ifdef _WIN32\n#elif (defined(JEMALLOC_OSSPIN))\n#else\n\tpthread_mutex_destroy(&mtx->lock);\n#endif\n}\n\nvoid\nmtx_lock(mtx_t *mtx)\n{\n\n#ifdef _WIN32\n\tEnterCriticalSection(&mtx->lock);\n#elif (defined(JEMALLOC_OSSPIN))\n\tOSSpinLockLock(&mtx->lock);\n#else\n\tpthread_mutex_lock(&mtx->lock);\n#endif\n}\n\nvoid\nmtx_unlock(mtx_t *mtx)\n{\n\n#ifdef _WIN32\n\tLeaveCriticalSection(&mtx->lock);\n#elif (defined(JEMALLOC_OSSPIN))\n\tOSSpinLockUnlock(&mtx->lock);\n#else\n\tpthread_mutex_unlock(&mtx->lock);\n#endif\n}\n"
  },
  {
    "path": "extern/deprecated/redis-2.8.21/deps/jemalloc/test/src/test.c",
    "content": "#include \"test/jemalloc_test.h\"\n\nstatic unsigned\t\ttest_count = 0;\nstatic test_status_t\ttest_counts[test_status_count] = {0, 0, 0};\nstatic test_status_t\ttest_status = test_status_pass;\nstatic const char *\ttest_name = \"\";\n\nJEMALLOC_ATTR(format(printf, 1, 2))\nvoid\ntest_skip(const char *format, ...)\n{\n\tva_list ap;\n\n\tva_start(ap, format);\n\tmalloc_vcprintf(NULL, NULL, format, ap);\n\tva_end(ap);\n\tmalloc_printf(\"\\n\");\n\ttest_status = test_status_skip;\n}\n\nJEMALLOC_ATTR(format(printf, 1, 2))\nvoid\ntest_fail(const char *format, ...)\n{\n\tva_list ap;\n\n\tva_start(ap, format);\n\tmalloc_vcprintf(NULL, NULL, format, ap);\n\tva_end(ap);\n\tmalloc_printf(\"\\n\");\n\ttest_status = test_status_fail;\n}\n\nstatic const char *\ntest_status_string(test_status_t test_status)\n{\n\n\tswitch (test_status) {\n\tcase test_status_pass: return \"pass\";\n\tcase test_status_skip: return \"skip\";\n\tcase test_status_fail: return \"fail\";\n\tdefault: not_reached();\n\t}\n}\n\nvoid\np_test_init(const char *name)\n{\n\n\ttest_count++;\n\ttest_status = test_status_pass;\n\ttest_name = name;\n}\n\nvoid\np_test_fini(void)\n{\n\n\ttest_counts[test_status]++;\n\tmalloc_printf(\"%s: %s\\n\", test_name, test_status_string(test_status));\n}\n\ntest_status_t\np_test(test_t* t, ...)\n{\n\ttest_status_t ret = test_status_pass;\n\tva_list ap;\n\n\tva_start(ap, t);\n\tfor (; t != NULL; t = va_arg(ap, test_t*)) {\n\t\tt();\n\t\tif (test_status > ret)\n\t\t\tret = test_status;\n\t}\n\tva_end(ap);\n\n\tmalloc_printf(\"--- %s: %u/%u, %s: %u/%u, %s: %u/%u ---\\n\",\n\t    test_status_string(test_status_pass),\n\t    test_counts[test_status_pass], test_count,\n\t    test_status_string(test_status_skip),\n\t    test_counts[test_status_skip], test_count,\n\t    test_status_string(test_status_fail),\n\t    test_counts[test_status_fail], test_count);\n\n\treturn (ret);\n}\n\nvoid\np_test_fail(const char *prefix, const char *message)\n{\n\n\tmalloc_cprintf(NULL, NULL, \"%s%s\\n\", prefix, message);\n\ttest_status = test_status_fail;\n}\n"
  },
  {
    "path": "extern/deprecated/redis-2.8.21/deps/jemalloc/test/src/thd.c",
    "content": "#include \"test/jemalloc_test.h\"\n\n#ifdef _WIN32\nvoid\nthd_create(thd_t *thd, void *(*proc)(void *), void *arg)\n{\n\tLPTHREAD_START_ROUTINE routine = (LPTHREAD_START_ROUTINE)proc;\n\t*thd = CreateThread(NULL, 0, routine, arg, 0, NULL);\n\tif (*thd == NULL)\n\t\ttest_fail(\"Error in CreateThread()\\n\");\n}\n\nvoid\nthd_join(thd_t thd, void **ret)\n{\n\n\tWaitForSingleObject(thd, INFINITE);\n}\n\n#else\nvoid\nthd_create(thd_t *thd, void *(*proc)(void *), void *arg)\n{\n\n\tif (pthread_create(thd, NULL, proc, arg) != 0)\n\t\ttest_fail(\"Error in pthread_create()\\n\");\n}\n\nvoid\nthd_join(thd_t thd, void **ret)\n{\n\n\tpthread_join(thd, ret);\n}\n#endif\n"
  },
  {
    "path": "extern/deprecated/redis-2.8.21/deps/jemalloc/test/test.sh.in",
    "content": "#!/bin/sh\n\ncase @abi@ in\n  macho)\n    export DYLD_FALLBACK_LIBRARY_PATH=\"@objroot@lib\"\n    ;;\n  pecoff)\n    export PATH=\"${PATH}:@objroot@lib\"\n    ;;\n  *)\n    ;;\nesac\n\n# Corresponds to test_status_t.\npass_code=0\nskip_code=1\nfail_code=2\n\npass_count=0\nskip_count=0\nfail_count=0\nfor t in $@; do\n  if [ $pass_count -ne 0 -o $skip_count -ne 0 -o $fail_count != 0 ] ; then\n    echo\n  fi\n  echo \"=== ${t} ===\"\n  ${t}@exe@ @abs_srcroot@ @abs_objroot@\n  result_code=$?\n  case ${result_code} in\n    ${pass_code})\n      pass_count=$((pass_count+1))\n      ;;\n    ${skip_code})\n      skip_count=$((skip_count+1))\n      ;;\n    ${fail_code})\n      fail_count=$((fail_count+1))\n      ;;\n    *)\n      echo \"Test harness error\" 1>&2\n      exit 1\n  esac\ndone\n\ntotal_count=`expr ${pass_count} + ${skip_count} + ${fail_count}`\necho\necho \"Test suite summary: pass: ${pass_count}/${total_count}, skip: ${skip_count}/${total_count}, fail: ${fail_count}/${total_count}\"\n\nif [ ${fail_count} -eq 0 ] ; then\n  exit 0\nelse\n  exit 1\nfi\n"
  },
  {
    "path": "extern/deprecated/redis-2.8.21/deps/jemalloc/test/unit/SFMT.c",
    "content": "/*\n * This file derives from SFMT 1.3.3\n * (http://www.math.sci.hiroshima-u.ac.jp/~m-mat/MT/SFMT/index.html), which was\n * released under the terms of the following license:\n *\n *   Copyright (c) 2006,2007 Mutsuo Saito, Makoto Matsumoto and Hiroshima\n *   University. All rights reserved.\n *\n *   Redistribution and use in source and binary forms, with or without\n *   modification, are permitted provided that the following conditions are\n *   met:\n *\n *       * Redistributions of source code must retain the above copyright\n *         notice, this list of conditions and the following disclaimer.\n *       * Redistributions in binary form must reproduce the above\n *         copyright notice, this list of conditions and the following\n *         disclaimer in the documentation and/or other materials provided\n *         with the distribution.\n *       * Neither the name of the Hiroshima University nor the names of\n *         its contributors may be used to endorse or promote products\n *         derived from this software without specific prior written\n *         permission.\n *\n *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n *   \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\n *   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\n *   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\n *   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n *   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\n *   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n *   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n *   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n *   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n *   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n#include \"test/jemalloc_test.h\"\n\n#define\tBLOCK_SIZE 10000\n#define\tBLOCK_SIZE64 (BLOCK_SIZE / 2)\n#define\tCOUNT_1 1000\n#define\tCOUNT_2 700\n\nstatic const uint32_t init_gen_rand_32_expected[] = {\n\t3440181298U, 1564997079U, 1510669302U, 2930277156U, 1452439940U,\n\t3796268453U,  423124208U, 2143818589U, 3827219408U, 2987036003U,\n\t2674978610U, 1536842514U, 2027035537U, 2534897563U, 1686527725U,\n\t 545368292U, 1489013321U, 1370534252U, 4231012796U, 3994803019U,\n\t1764869045U,  824597505U,  862581900U, 2469764249U,  812862514U,\n\t 359318673U,  116957936U, 3367389672U, 2327178354U, 1898245200U,\n\t3206507879U, 2378925033U, 1040214787U, 2524778605U, 3088428700U,\n\t1417665896U,  964324147U, 2282797708U, 2456269299U,  313400376U,\n\t2245093271U, 1015729427U, 2694465011U, 3246975184U, 1992793635U,\n\t 463679346U, 3721104591U, 3475064196U,  856141236U, 1499559719U,\n\t3522818941U, 3721533109U, 1954826617U, 1282044024U, 1543279136U,\n\t1301863085U, 2669145051U, 4221477354U, 3896016841U, 3392740262U,\n\t 462466863U, 1037679449U, 1228140306U,  922298197U, 1205109853U,\n\t1872938061U, 3102547608U, 2742766808U, 1888626088U, 4028039414U,\n\t 157593879U, 1136901695U, 4038377686U, 3572517236U, 4231706728U,\n\t2997311961U, 1189931652U, 3981543765U, 2826166703U,   87159245U,\n\t1721379072U, 3897926942U, 1790395498U, 2569178939U, 1047368729U,\n\t2340259131U, 3144212906U, 2301169789U, 2442885464U, 3034046771U,\n\t3667880593U, 3935928400U, 2372805237U, 1666397115U, 2460584504U,\n\t 513866770U, 3810869743U, 2147400037U, 2792078025U, 2941761810U,\n\t3212265810U,  984692259U,  346590253U, 1804179199U, 3298543443U,\n\t 750108141U, 2880257022U,  243310542U, 1869036465U, 1588062513U,\n\t2983949551U, 1931450364U, 4034505847U, 2735030199U, 1628461061U,\n\t2539522841U,  127965585U, 3992448871U,  913388237U,  559130076U,\n\t1202933193U, 4087643167U, 2590021067U, 2256240196U, 1746697293U,\n\t1013913783U, 1155864921U, 2715773730U,  915061862U, 1948766573U,\n\t2322882854U, 3761119102U, 1343405684U, 3078711943U, 3067431651U,\n\t3245156316U, 3588354584U, 3484623306U, 3899621563U, 4156689741U,\n\t3237090058U, 3880063844U,  862416318U, 4039923869U, 2303788317U,\n\t3073590536U,  701653667U, 2131530884U, 3169309950U, 2028486980U,\n\t 747196777U, 3620218225U,  432016035U, 1449580595U, 2772266392U,\n\t 444224948U, 1662832057U, 3184055582U, 3028331792U, 1861686254U,\n\t1104864179U,  342430307U, 1350510923U, 3024656237U, 1028417492U,\n\t2870772950U,  290847558U, 3675663500U,  508431529U, 4264340390U,\n\t2263569913U, 1669302976U,  519511383U, 2706411211U, 3764615828U,\n\t3883162495U, 4051445305U, 2412729798U, 3299405164U, 3991911166U,\n\t2348767304U, 2664054906U, 3763609282U,  593943581U, 3757090046U,\n\t2075338894U, 2020550814U, 4287452920U, 4290140003U, 1422957317U,\n\t2512716667U, 2003485045U, 2307520103U, 2288472169U, 3940751663U,\n\t4204638664U, 2892583423U, 1710068300U, 3904755993U, 2363243951U,\n\t3038334120U,  547099465U,  771105860U, 3199983734U, 4282046461U,\n\t2298388363U,  934810218U, 2837827901U, 3952500708U, 2095130248U,\n\t3083335297U,   26885281U, 3932155283U, 1531751116U, 1425227133U,\n\t 495654159U, 3279634176U, 3855562207U, 3957195338U, 4159985527U,\n\t 893375062U, 1875515536U, 1327247422U, 3754140693U, 1028923197U,\n\t1729880440U,  805571298U,  448971099U, 2726757106U, 2749436461U,\n\t2485987104U,  175337042U, 3235477922U, 3882114302U, 2020970972U,\n\t 943926109U, 2762587195U, 1904195558U, 3452650564U,  108432281U,\n\t3893463573U, 3977583081U, 2636504348U, 1110673525U, 3548479841U,\n\t4258854744U,  980047703U, 4057175418U, 3890008292U,  145653646U,\n\t3141868989U, 3293216228U, 1194331837U, 1254570642U, 3049934521U,\n\t2868313360U, 2886032750U, 1110873820U,  279553524U, 3007258565U,\n\t1104807822U, 3186961098U,  315764646U, 2163680838U, 3574508994U,\n\t3099755655U,  191957684U, 3642656737U, 3317946149U, 3522087636U,\n\t 444526410U,  779157624U, 1088229627U, 1092460223U, 1856013765U,\n\t3659877367U,  368270451U,  503570716U, 3000984671U, 2742789647U,\n\t 928097709U, 2914109539U,  308843566U, 2816161253U, 3667192079U,\n\t2762679057U, 3395240989U, 2928925038U, 1491465914U, 3458702834U,\n\t3787782576U, 2894104823U, 1296880455U, 1253636503U,  989959407U,\n\t2291560361U, 2776790436U, 1913178042U, 1584677829U,  689637520U,\n\t1898406878U,  688391508U, 3385234998U,  845493284U, 1943591856U,\n\t2720472050U,  222695101U, 1653320868U, 2904632120U, 4084936008U,\n\t1080720688U, 3938032556U,  387896427U, 2650839632U,   99042991U,\n\t1720913794U, 1047186003U, 1877048040U, 2090457659U,  517087501U,\n\t4172014665U, 2129713163U, 2413533132U, 2760285054U, 4129272496U,\n\t1317737175U, 2309566414U, 2228873332U, 3889671280U, 1110864630U,\n\t3576797776U, 2074552772U,  832002644U, 3097122623U, 2464859298U,\n\t2679603822U, 1667489885U, 3237652716U, 1478413938U, 1719340335U,\n\t2306631119U,  639727358U, 3369698270U,  226902796U, 2099920751U,\n\t1892289957U, 2201594097U, 3508197013U, 3495811856U, 3900381493U,\n\t 841660320U, 3974501451U, 3360949056U, 1676829340U,  728899254U,\n\t2047809627U, 2390948962U,  670165943U, 3412951831U, 4189320049U,\n\t1911595255U, 2055363086U,  507170575U,  418219594U, 4141495280U,\n\t2692088692U, 4203630654U, 3540093932U,  791986533U, 2237921051U,\n\t2526864324U, 2956616642U, 1394958700U, 1983768223U, 1893373266U,\n\t 591653646U,  228432437U, 1611046598U, 3007736357U, 1040040725U,\n\t2726180733U, 2789804360U, 4263568405U,  829098158U, 3847722805U,\n\t1123578029U, 1804276347U,  997971319U, 4203797076U, 4185199713U,\n\t2811733626U, 2343642194U, 2985262313U, 1417930827U, 3759587724U,\n\t1967077982U, 1585223204U, 1097475516U, 1903944948U,  740382444U,\n\t1114142065U, 1541796065U, 1718384172U, 1544076191U, 1134682254U,\n\t3519754455U, 2866243923U,  341865437U,  645498576U, 2690735853U,\n\t1046963033U, 2493178460U, 1187604696U, 1619577821U,  488503634U,\n\t3255768161U, 2306666149U, 1630514044U, 2377698367U, 2751503746U,\n\t3794467088U, 1796415981U, 3657173746U,  409136296U, 1387122342U,\n\t1297726519U,  219544855U, 4270285558U,  437578827U, 1444698679U,\n\t2258519491U,  963109892U, 3982244073U, 3351535275U,  385328496U,\n\t1804784013U,  698059346U, 3920535147U,  708331212U,  784338163U,\n\t 785678147U, 1238376158U, 1557298846U, 2037809321U,  271576218U,\n\t4145155269U, 1913481602U, 2763691931U,  588981080U, 1201098051U,\n\t3717640232U, 1509206239U,  662536967U, 3180523616U, 1133105435U,\n\t2963500837U, 2253971215U, 3153642623U, 1066925709U, 2582781958U,\n\t3034720222U, 1090798544U, 2942170004U, 4036187520U,  686972531U,\n\t2610990302U, 2641437026U, 1837562420U,  722096247U, 1315333033U,\n\t2102231203U, 3402389208U, 3403698140U, 1312402831U, 2898426558U,\n\t 814384596U,  385649582U, 1916643285U, 1924625106U, 2512905582U,\n\t2501170304U, 4275223366U, 2841225246U, 1467663688U, 3563567847U,\n\t2969208552U,  884750901U,  102992576U,  227844301U, 3681442994U,\n\t3502881894U, 4034693299U, 1166727018U, 1697460687U, 1737778332U,\n\t1787161139U, 1053003655U, 1215024478U, 2791616766U, 2525841204U,\n\t1629323443U,    3233815U, 2003823032U, 3083834263U, 2379264872U,\n\t3752392312U, 1287475550U, 3770904171U, 3004244617U, 1502117784U,\n\t 918698423U, 2419857538U, 3864502062U, 1751322107U, 2188775056U,\n\t4018728324U,  983712955U,  440071928U, 3710838677U, 2001027698U,\n\t3994702151U,   22493119U, 3584400918U, 3446253670U, 4254789085U,\n\t1405447860U, 1240245579U, 1800644159U, 1661363424U, 3278326132U,\n\t3403623451U,   67092802U, 2609352193U, 3914150340U, 1814842761U,\n\t3610830847U,  591531412U, 3880232807U, 1673505890U, 2585326991U,\n\t1678544474U, 3148435887U, 3457217359U, 1193226330U, 2816576908U,\n\t 154025329U,  121678860U, 1164915738U,  973873761U,  269116100U,\n\t  52087970U,  744015362U,  498556057U,   94298882U, 1563271621U,\n\t2383059628U, 4197367290U, 3958472990U, 2592083636U, 2906408439U,\n\t1097742433U, 3924840517U,  264557272U, 2292287003U, 3203307984U,\n\t4047038857U, 3820609705U, 2333416067U, 1839206046U, 3600944252U,\n\t3412254904U,  583538222U, 2390557166U, 4140459427U, 2810357445U,\n\t 226777499U, 2496151295U, 2207301712U, 3283683112U,  611630281U,\n\t1933218215U, 3315610954U, 3889441987U, 3719454256U, 3957190521U,\n\t1313998161U, 2365383016U, 3146941060U, 1801206260U,  796124080U,\n\t2076248581U, 1747472464U, 3254365145U,  595543130U, 3573909503U,\n\t3758250204U, 2020768540U, 2439254210U,   93368951U, 3155792250U,\n\t2600232980U, 3709198295U, 3894900440U, 2971850836U, 1578909644U,\n\t1443493395U, 2581621665U, 3086506297U, 2443465861U,  558107211U,\n\t1519367835U,  249149686U,  908102264U, 2588765675U, 1232743965U,\n\t1001330373U, 3561331654U, 2259301289U, 1564977624U, 3835077093U,\n\t 727244906U, 4255738067U, 1214133513U, 2570786021U, 3899704621U,\n\t1633861986U, 1636979509U, 1438500431U,   58463278U, 2823485629U,\n\t2297430187U, 2926781924U, 3371352948U, 1864009023U, 2722267973U,\n\t1444292075U,  437703973U, 1060414512U,  189705863U,  910018135U,\n\t4077357964U,  884213423U, 2644986052U, 3973488374U, 1187906116U,\n\t2331207875U,  780463700U, 3713351662U, 3854611290U,  412805574U,\n\t2978462572U, 2176222820U,  829424696U, 2790788332U, 2750819108U,\n\t1594611657U, 3899878394U, 3032870364U, 1702887682U, 1948167778U,\n\t  14130042U,  192292500U,  947227076U,   90719497U, 3854230320U,\n\t 784028434U, 2142399787U, 1563449646U, 2844400217U,  819143172U,\n\t2883302356U, 2328055304U, 1328532246U, 2603885363U, 3375188924U,\n\t 933941291U, 3627039714U, 2129697284U, 2167253953U, 2506905438U,\n\t1412424497U, 2981395985U, 1418359660U, 2925902456U,   52752784U,\n\t3713667988U, 3924669405U,  648975707U, 1145520213U, 4018650664U,\n\t3805915440U, 2380542088U, 2013260958U, 3262572197U, 2465078101U,\n\t1114540067U, 3728768081U, 2396958768U,  590672271U,  904818725U,\n\t4263660715U,  700754408U, 1042601829U, 4094111823U, 4274838909U,\n\t2512692617U, 2774300207U, 2057306915U, 3470942453U,   99333088U,\n\t1142661026U, 2889931380U,   14316674U, 2201179167U,  415289459U,\n\t 448265759U, 3515142743U, 3254903683U,  246633281U, 1184307224U,\n\t2418347830U, 2092967314U, 2682072314U, 2558750234U, 2000352263U,\n\t1544150531U,  399010405U, 1513946097U,  499682937U,  461167460U,\n\t3045570638U, 1633669705U,  851492362U, 4052801922U, 2055266765U,\n\t 635556996U,  368266356U, 2385737383U, 3218202352U, 2603772408U,\n\t 349178792U,  226482567U, 3102426060U, 3575998268U, 2103001871U,\n\t3243137071U,  225500688U, 1634718593U, 4283311431U, 4292122923U,\n\t3842802787U,  811735523U,  105712518U,  663434053U, 1855889273U,\n\t2847972595U, 1196355421U, 2552150115U, 4254510614U, 3752181265U,\n\t3430721819U, 3828705396U, 3436287905U, 3441964937U, 4123670631U,\n\t 353001539U,  459496439U, 3799690868U, 1293777660U, 2761079737U,\n\t 498096339U, 3398433374U, 4080378380U, 2304691596U, 2995729055U,\n\t4134660419U, 3903444024U, 3576494993U,  203682175U, 3321164857U,\n\t2747963611U,   79749085U, 2992890370U, 1240278549U, 1772175713U,\n\t2111331972U, 2655023449U, 1683896345U, 2836027212U, 3482868021U,\n\t2489884874U,  756853961U, 2298874501U, 4013448667U, 4143996022U,\n\t2948306858U, 4132920035U, 1283299272U,  995592228U, 3450508595U,\n\t1027845759U, 1766942720U, 3861411826U, 1446861231U,   95974993U,\n\t3502263554U, 1487532194U,  601502472U, 4129619129U,  250131773U,\n\t2050079547U, 3198903947U, 3105589778U, 4066481316U, 3026383978U,\n\t2276901713U,  365637751U, 2260718426U, 1394775634U, 1791172338U,\n\t2690503163U, 2952737846U, 1568710462U,  732623190U, 2980358000U,\n\t1053631832U, 1432426951U, 3229149635U, 1854113985U, 3719733532U,\n\t3204031934U,  735775531U,  107468620U, 3734611984U,  631009402U,\n\t3083622457U, 4109580626U,  159373458U, 1301970201U, 4132389302U,\n\t1293255004U,  847182752U, 4170022737U,   96712900U, 2641406755U,\n\t1381727755U,  405608287U, 4287919625U, 1703554290U, 3589580244U,\n\t2911403488U,    2166565U, 2647306451U, 2330535117U, 1200815358U,\n\t1165916754U,  245060911U, 4040679071U, 3684908771U, 2452834126U,\n\t2486872773U, 2318678365U, 2940627908U, 1837837240U, 3447897409U,\n\t4270484676U, 1495388728U, 3754288477U, 4204167884U, 1386977705U,\n\t2692224733U, 3076249689U, 4109568048U, 4170955115U, 4167531356U,\n\t4020189950U, 4261855038U, 3036907575U, 3410399885U, 3076395737U,\n\t1046178638U,  144496770U,  230725846U, 3349637149U,   17065717U,\n\t2809932048U, 2054581785U, 3608424964U, 3259628808U,  134897388U,\n\t3743067463U,  257685904U, 3795656590U, 1562468719U, 3589103904U,\n\t3120404710U,  254684547U, 2653661580U, 3663904795U, 2631942758U,\n\t1063234347U, 2609732900U, 2332080715U, 3521125233U, 1180599599U,\n\t1935868586U, 4110970440U,  296706371U, 2128666368U, 1319875791U,\n\t1570900197U, 3096025483U, 1799882517U, 1928302007U, 1163707758U,\n\t1244491489U, 3533770203U,  567496053U, 2757924305U, 2781639343U,\n\t2818420107U,  560404889U, 2619609724U, 4176035430U, 2511289753U,\n\t2521842019U, 3910553502U, 2926149387U, 3302078172U, 4237118867U,\n\t 330725126U,  367400677U,  888239854U,  545570454U, 4259590525U,\n\t 134343617U, 1102169784U, 1647463719U, 3260979784U, 1518840883U,\n\t3631537963U, 3342671457U, 1301549147U, 2083739356U,  146593792U,\n\t3217959080U,  652755743U, 2032187193U, 3898758414U, 1021358093U,\n\t4037409230U, 2176407931U, 3427391950U, 2883553603U,  985613827U,\n\t3105265092U, 3423168427U, 3387507672U,  467170288U, 2141266163U,\n\t3723870208U,  916410914U, 1293987799U, 2652584950U,  769160137U,\n\t3205292896U, 1561287359U, 1684510084U, 3136055621U, 3765171391U,\n\t 639683232U, 2639569327U, 1218546948U, 4263586685U, 3058215773U,\n\t2352279820U,  401870217U, 2625822463U, 1529125296U, 2981801895U,\n\t1191285226U, 4027725437U, 3432700217U, 4098835661U,  971182783U,\n\t2443861173U, 3881457123U, 3874386651U,  457276199U, 2638294160U,\n\t4002809368U,  421169044U, 1112642589U, 3076213779U, 3387033971U,\n\t2499610950U, 3057240914U, 1662679783U,  461224431U, 1168395933U\n};\nstatic const uint32_t init_by_array_32_expected[] = {\n\t2920711183U, 3885745737U, 3501893680U,  856470934U, 1421864068U,\n\t 277361036U, 1518638004U, 2328404353U, 3355513634U,   64329189U,\n\t1624587673U, 3508467182U, 2481792141U, 3706480799U, 1925859037U,\n\t2913275699U,  882658412U,  384641219U,  422202002U, 1873384891U,\n\t2006084383U, 3924929912U, 1636718106U, 3108838742U, 1245465724U,\n\t4195470535U,  779207191U, 1577721373U, 1390469554U, 2928648150U,\n\t 121399709U, 3170839019U, 4044347501U,  953953814U, 3821710850U,\n\t3085591323U, 3666535579U, 3577837737U, 2012008410U, 3565417471U,\n\t4044408017U,  433600965U, 1637785608U, 1798509764U,  860770589U,\n\t3081466273U, 3982393409U, 2451928325U, 3437124742U, 4093828739U,\n\t3357389386U, 2154596123U,  496568176U, 2650035164U, 2472361850U,\n\t   3438299U, 2150366101U, 1577256676U, 3802546413U, 1787774626U,\n\t4078331588U, 3706103141U,  170391138U, 3806085154U, 1680970100U,\n\t1961637521U, 3316029766U,  890610272U, 1453751581U, 1430283664U,\n\t3051057411U, 3597003186U,  542563954U, 3796490244U, 1690016688U,\n\t3448752238U,  440702173U,  347290497U, 1121336647U, 2540588620U,\n\t 280881896U, 2495136428U,  213707396U,   15104824U, 2946180358U,\n\t 659000016U,  566379385U, 2614030979U, 2855760170U,  334526548U,\n\t2315569495U, 2729518615U,  564745877U, 1263517638U, 3157185798U,\n\t1604852056U, 1011639885U, 2950579535U, 2524219188U,  312951012U,\n\t1528896652U, 1327861054U, 2846910138U, 3966855905U, 2536721582U,\n\t 855353911U, 1685434729U, 3303978929U, 1624872055U, 4020329649U,\n\t3164802143U, 1642802700U, 1957727869U, 1792352426U, 3334618929U,\n\t2631577923U, 3027156164U,  842334259U, 3353446843U, 1226432104U,\n\t1742801369U, 3552852535U, 3471698828U, 1653910186U, 3380330939U,\n\t2313782701U, 3351007196U, 2129839995U, 1800682418U, 4085884420U,\n\t1625156629U, 3669701987U,  615211810U, 3294791649U, 4131143784U,\n\t2590843588U, 3207422808U, 3275066464U,  561592872U, 3957205738U,\n\t3396578098U,   48410678U, 3505556445U, 1005764855U, 3920606528U,\n\t2936980473U, 2378918600U, 2404449845U, 1649515163U,  701203563U,\n\t3705256349U,   83714199U, 3586854132U,  922978446U, 2863406304U,\n\t3523398907U, 2606864832U, 2385399361U, 3171757816U, 4262841009U,\n\t3645837721U, 1169579486U, 3666433897U, 3174689479U, 1457866976U,\n\t3803895110U, 3346639145U, 1907224409U, 1978473712U, 1036712794U,\n\t 980754888U, 1302782359U, 1765252468U,  459245755U, 3728923860U,\n\t1512894209U, 2046491914U,  207860527U,  514188684U, 2288713615U,\n\t1597354672U, 3349636117U, 2357291114U, 3995796221U,  945364213U,\n\t1893326518U, 3770814016U, 1691552714U, 2397527410U,  967486361U,\n\t 776416472U, 4197661421U,  951150819U, 1852770983U, 4044624181U,\n\t1399439738U, 4194455275U, 2284037669U, 1550734958U, 3321078108U,\n\t1865235926U, 2912129961U, 2664980877U, 1357572033U, 2600196436U,\n\t2486728200U, 2372668724U, 1567316966U, 2374111491U, 1839843570U,\n\t  20815612U, 3727008608U, 3871996229U,  824061249U, 1932503978U,\n\t3404541726U,  758428924U, 2609331364U, 1223966026U, 1299179808U,\n\t 648499352U, 2180134401U,  880821170U, 3781130950U,  113491270U,\n\t1032413764U, 4185884695U, 2490396037U, 1201932817U, 4060951446U,\n\t4165586898U, 1629813212U, 2887821158U,  415045333U,  628926856U,\n\t2193466079U, 3391843445U, 2227540681U, 1907099846U, 2848448395U,\n\t1717828221U, 1372704537U, 1707549841U, 2294058813U, 2101214437U,\n\t2052479531U, 1695809164U, 3176587306U, 2632770465U,   81634404U,\n\t1603220563U,  644238487U,  302857763U,  897352968U, 2613146653U,\n\t1391730149U, 4245717312U, 4191828749U, 1948492526U, 2618174230U,\n\t3992984522U, 2178852787U, 3596044509U, 3445573503U, 2026614616U,\n\t 915763564U, 3415689334U, 2532153403U, 3879661562U, 2215027417U,\n\t3111154986U, 2929478371U,  668346391U, 1152241381U, 2632029711U,\n\t3004150659U, 2135025926U,  948690501U, 2799119116U, 4228829406U,\n\t1981197489U, 4209064138U,  684318751U, 3459397845U,  201790843U,\n\t4022541136U, 3043635877U,  492509624U, 3263466772U, 1509148086U,\n\t 921459029U, 3198857146U,  705479721U, 3835966910U, 3603356465U,\n\t 576159741U, 1742849431U,  594214882U, 2055294343U, 3634861861U,\n\t 449571793U, 3246390646U, 3868232151U, 1479156585U, 2900125656U,\n\t2464815318U, 3960178104U, 1784261920U,   18311476U, 3627135050U,\n\t 644609697U,  424968996U,  919890700U, 2986824110U,  816423214U,\n\t4003562844U, 1392714305U, 1757384428U, 2569030598U,  995949559U,\n\t3875659880U, 2933807823U, 2752536860U, 2993858466U, 4030558899U,\n\t2770783427U, 2775406005U, 2777781742U, 1931292655U,  472147933U,\n\t3865853827U, 2726470545U, 2668412860U, 2887008249U,  408979190U,\n\t3578063323U, 3242082049U, 1778193530U,   27981909U, 2362826515U,\n\t 389875677U, 1043878156U,  581653903U, 3830568952U,  389535942U,\n\t3713523185U, 2768373359U, 2526101582U, 1998618197U, 1160859704U,\n\t3951172488U, 1098005003U,  906275699U, 3446228002U, 2220677963U,\n\t2059306445U,  132199571U,  476838790U, 1868039399U, 3097344807U,\n\t 857300945U,  396345050U, 2835919916U, 1782168828U, 1419519470U,\n\t4288137521U,  819087232U,  596301494U,  872823172U, 1526888217U,\n\t 805161465U, 1116186205U, 2829002754U, 2352620120U,  620121516U,\n\t 354159268U, 3601949785U,  209568138U, 1352371732U, 2145977349U,\n\t4236871834U, 1539414078U, 3558126206U, 3224857093U, 4164166682U,\n\t3817553440U, 3301780278U, 2682696837U, 3734994768U, 1370950260U,\n\t1477421202U, 2521315749U, 1330148125U, 1261554731U, 2769143688U,\n\t3554756293U, 4235882678U, 3254686059U, 3530579953U, 1215452615U,\n\t3574970923U, 4057131421U,  589224178U, 1000098193U,  171190718U,\n\t2521852045U, 2351447494U, 2284441580U, 2646685513U, 3486933563U,\n\t3789864960U, 1190528160U, 1702536782U, 1534105589U, 4262946827U,\n\t2726686826U, 3584544841U, 2348270128U, 2145092281U, 2502718509U,\n\t1027832411U, 3571171153U, 1287361161U, 4011474411U, 3241215351U,\n\t2419700818U,  971242709U, 1361975763U, 1096842482U, 3271045537U,\n\t  81165449U,  612438025U, 3912966678U, 1356929810U,  733545735U,\n\t 537003843U, 1282953084U,  884458241U,  588930090U, 3930269801U,\n\t2961472450U, 1219535534U, 3632251943U,  268183903U, 1441240533U,\n\t3653903360U, 3854473319U, 2259087390U, 2548293048U, 2022641195U,\n\t2105543911U, 1764085217U, 3246183186U,  482438805U,  888317895U,\n\t2628314765U, 2466219854U,  717546004U, 2322237039U,  416725234U,\n\t1544049923U, 1797944973U, 3398652364U, 3111909456U,  485742908U,\n\t2277491072U, 1056355088U, 3181001278U,  129695079U, 2693624550U,\n\t1764438564U, 3797785470U,  195503713U, 3266519725U, 2053389444U,\n\t1961527818U, 3400226523U, 3777903038U, 2597274307U, 4235851091U,\n\t4094406648U, 2171410785U, 1781151386U, 1378577117U,  654643266U,\n\t3424024173U, 3385813322U,  679385799U,  479380913U,  681715441U,\n\t3096225905U,  276813409U, 3854398070U, 2721105350U,  831263315U,\n\t3276280337U, 2628301522U, 3984868494U, 1466099834U, 2104922114U,\n\t1412672743U,  820330404U, 3491501010U,  942735832U,  710652807U,\n\t3972652090U,  679881088U,   40577009U, 3705286397U, 2815423480U,\n\t3566262429U,  663396513U, 3777887429U, 4016670678U,  404539370U,\n\t1142712925U, 1140173408U, 2913248352U, 2872321286U,  263751841U,\n\t3175196073U, 3162557581U, 2878996619U,   75498548U, 3836833140U,\n\t3284664959U, 1157523805U,  112847376U,  207855609U, 1337979698U,\n\t1222578451U,  157107174U,  901174378U, 3883717063U, 1618632639U,\n\t1767889440U, 4264698824U, 1582999313U,  884471997U, 2508825098U,\n\t3756370771U, 2457213553U, 3565776881U, 3709583214U,  915609601U,\n\t 460833524U, 1091049576U,   85522880U,    2553251U,  132102809U,\n\t2429882442U, 2562084610U, 1386507633U, 4112471229U,   21965213U,\n\t1981516006U, 2418435617U, 3054872091U, 4251511224U, 2025783543U,\n\t1916911512U, 2454491136U, 3938440891U, 3825869115U, 1121698605U,\n\t3463052265U,  802340101U, 1912886800U, 4031997367U, 3550640406U,\n\t1596096923U,  610150600U,  431464457U, 2541325046U,  486478003U,\n\t 739704936U, 2862696430U, 3037903166U, 1129749694U, 2611481261U,\n\t1228993498U,  510075548U, 3424962587U, 2458689681U,  818934833U,\n\t4233309125U, 1608196251U, 3419476016U, 1858543939U, 2682166524U,\n\t3317854285U,  631986188U, 3008214764U,  613826412U, 3567358221U,\n\t3512343882U, 1552467474U, 3316162670U, 1275841024U, 4142173454U,\n\t 565267881U,  768644821U,  198310105U, 2396688616U, 1837659011U,\n\t 203429334U,  854539004U, 4235811518U, 3338304926U, 3730418692U,\n\t3852254981U, 3032046452U, 2329811860U, 2303590566U, 2696092212U,\n\t3894665932U,  145835667U,  249563655U, 1932210840U, 2431696407U,\n\t3312636759U,  214962629U, 2092026914U, 3020145527U, 4073039873U,\n\t2739105705U, 1308336752U,  855104522U, 2391715321U,   67448785U,\n\t 547989482U,  854411802U, 3608633740U,  431731530U,  537375589U,\n\t3888005760U,  696099141U,  397343236U, 1864511780U,   44029739U,\n\t1729526891U, 1993398655U, 2010173426U, 2591546756U,  275223291U,\n\t1503900299U, 4217765081U, 2185635252U, 1122436015U, 3550155364U,\n\t 681707194U, 3260479338U,  933579397U, 2983029282U, 2505504587U,\n\t2667410393U, 2962684490U, 4139721708U, 2658172284U, 2452602383U,\n\t2607631612U, 1344296217U, 3075398709U, 2949785295U, 1049956168U,\n\t3917185129U, 2155660174U, 3280524475U, 1503827867U,  674380765U,\n\t1918468193U, 3843983676U,  634358221U, 2538335643U, 1873351298U,\n\t3368723763U, 2129144130U, 3203528633U, 3087174986U, 2691698871U,\n\t2516284287U,   24437745U, 1118381474U, 2816314867U, 2448576035U,\n\t4281989654U,  217287825U,  165872888U, 2628995722U, 3533525116U,\n\t2721669106U,  872340568U, 3429930655U, 3309047304U, 3916704967U,\n\t3270160355U, 1348884255U, 1634797670U,  881214967U, 4259633554U,\n\t 174613027U, 1103974314U, 1625224232U, 2678368291U, 1133866707U,\n\t3853082619U, 4073196549U, 1189620777U,  637238656U,  930241537U,\n\t4042750792U, 3842136042U, 2417007212U, 2524907510U, 1243036827U,\n\t1282059441U, 3764588774U, 1394459615U, 2323620015U, 1166152231U,\n\t3307479609U, 3849322257U, 3507445699U, 4247696636U,  758393720U,\n\t 967665141U, 1095244571U, 1319812152U,  407678762U, 2640605208U,\n\t2170766134U, 3663594275U, 4039329364U, 2512175520U,  725523154U,\n\t2249807004U, 3312617979U, 2414634172U, 1278482215U,  349206484U,\n\t1573063308U, 1196429124U, 3873264116U, 2400067801U,  268795167U,\n\t 226175489U, 2961367263U, 1968719665U,   42656370U, 1010790699U,\n\t 561600615U, 2422453992U, 3082197735U, 1636700484U, 3977715296U,\n\t3125350482U, 3478021514U, 2227819446U, 1540868045U, 3061908980U,\n\t1087362407U, 3625200291U,  361937537U,  580441897U, 1520043666U,\n\t2270875402U, 1009161260U, 2502355842U, 4278769785U,  473902412U,\n\t1057239083U, 1905829039U, 1483781177U, 2080011417U, 1207494246U,\n\t1806991954U, 2194674403U, 3455972205U,  807207678U, 3655655687U,\n\t 674112918U,  195425752U, 3917890095U, 1874364234U, 1837892715U,\n\t3663478166U, 1548892014U, 2570748714U, 2049929836U, 2167029704U,\n\t 697543767U, 3499545023U, 3342496315U, 1725251190U, 3561387469U,\n\t2905606616U, 1580182447U, 3934525927U, 4103172792U, 1365672522U,\n\t1534795737U, 3308667416U, 2841911405U, 3943182730U, 4072020313U,\n\t3494770452U, 3332626671U,   55327267U,  478030603U,  411080625U,\n\t3419529010U, 1604767823U, 3513468014U,  570668510U,  913790824U,\n\t2283967995U,  695159462U, 3825542932U, 4150698144U, 1829758699U,\n\t 202895590U, 1609122645U, 1267651008U, 2910315509U, 2511475445U,\n\t2477423819U, 3932081579U,  900879979U, 2145588390U, 2670007504U,\n\t 580819444U, 1864996828U, 2526325979U, 1019124258U,  815508628U,\n\t2765933989U, 1277301341U, 3006021786U,  855540956U,  288025710U,\n\t1919594237U, 2331223864U,  177452412U, 2475870369U, 2689291749U,\n\t 865194284U,  253432152U, 2628531804U, 2861208555U, 2361597573U,\n\t1653952120U, 1039661024U, 2159959078U, 3709040440U, 3564718533U,\n\t2596878672U, 2041442161U,   31164696U, 2662962485U, 3665637339U,\n\t1678115244U, 2699839832U, 3651968520U, 3521595541U,  458433303U,\n\t2423096824U,   21831741U,  380011703U, 2498168716U,  861806087U,\n\t1673574843U, 4188794405U, 2520563651U, 2632279153U, 2170465525U,\n\t4171949898U, 3886039621U, 1661344005U, 3424285243U,  992588372U,\n\t2500984144U, 2993248497U, 3590193895U, 1535327365U,  515645636U,\n\t 131633450U, 3729760261U, 1613045101U, 3254194278U,   15889678U,\n\t1493590689U,  244148718U, 2991472662U, 1401629333U,  777349878U,\n\t2501401703U, 4285518317U, 3794656178U,  955526526U, 3442142820U,\n\t3970298374U,  736025417U, 2737370764U, 1271509744U,  440570731U,\n\t 136141826U, 1596189518U,  923399175U,  257541519U, 3505774281U,\n\t2194358432U, 2518162991U, 1379893637U, 2667767062U, 3748146247U,\n\t1821712620U, 3923161384U, 1947811444U, 2392527197U, 4127419685U,\n\t1423694998U, 4156576871U, 1382885582U, 3420127279U, 3617499534U,\n\t2994377493U, 4038063986U, 1918458672U, 2983166794U, 4200449033U,\n\t 353294540U, 1609232588U,  243926648U, 2332803291U,  507996832U,\n\t2392838793U, 4075145196U, 2060984340U, 4287475136U,   88232602U,\n\t2491531140U, 4159725633U, 2272075455U,  759298618U,  201384554U,\n\t 838356250U, 1416268324U,  674476934U,   90795364U,  141672229U,\n\t3660399588U, 4196417251U, 3249270244U, 3774530247U,   59587265U,\n\t3683164208U,   19392575U, 1463123697U, 1882205379U,  293780489U,\n\t2553160622U, 2933904694U,  675638239U, 2851336944U, 1435238743U,\n\t2448730183U,  804436302U, 2119845972U,  322560608U, 4097732704U,\n\t2987802540U,  641492617U, 2575442710U, 4217822703U, 3271835300U,\n\t2836418300U, 3739921620U, 2138378768U, 2879771855U, 4294903423U,\n\t3121097946U, 2603440486U, 2560820391U, 1012930944U, 2313499967U,\n\t 584489368U, 3431165766U,  897384869U, 2062537737U, 2847889234U,\n\t3742362450U, 2951174585U, 4204621084U, 1109373893U, 3668075775U,\n\t2750138839U, 3518055702U,  733072558U, 4169325400U,  788493625U\n};\nstatic const uint64_t init_gen_rand_64_expected[] = {\n\tQU(16924766246869039260LLU), QU( 8201438687333352714LLU),\n\tQU( 2265290287015001750LLU), QU(18397264611805473832LLU),\n\tQU( 3375255223302384358LLU), QU( 6345559975416828796LLU),\n\tQU(18229739242790328073LLU), QU( 7596792742098800905LLU),\n\tQU(  255338647169685981LLU), QU( 2052747240048610300LLU),\n\tQU(18328151576097299343LLU), QU(12472905421133796567LLU),\n\tQU(11315245349717600863LLU), QU(16594110197775871209LLU),\n\tQU(15708751964632456450LLU), QU(10452031272054632535LLU),\n\tQU(11097646720811454386LLU), QU( 4556090668445745441LLU),\n\tQU(17116187693090663106LLU), QU(14931526836144510645LLU),\n\tQU( 9190752218020552591LLU), QU( 9625800285771901401LLU),\n\tQU(13995141077659972832LLU), QU( 5194209094927829625LLU),\n\tQU( 4156788379151063303LLU), QU( 8523452593770139494LLU),\n\tQU(14082382103049296727LLU), QU( 2462601863986088483LLU),\n\tQU( 3030583461592840678LLU), QU( 5221622077872827681LLU),\n\tQU( 3084210671228981236LLU), QU(13956758381389953823LLU),\n\tQU(13503889856213423831LLU), QU(15696904024189836170LLU),\n\tQU( 4612584152877036206LLU), QU( 6231135538447867881LLU),\n\tQU(10172457294158869468LLU), QU( 6452258628466708150LLU),\n\tQU(14044432824917330221LLU), QU(  370168364480044279LLU),\n\tQU(10102144686427193359LLU), QU(  667870489994776076LLU),\n\tQU( 2732271956925885858LLU), QU(18027788905977284151LLU),\n\tQU(15009842788582923859LLU), QU( 7136357960180199542LLU),\n\tQU(15901736243475578127LLU), QU(16951293785352615701LLU),\n\tQU(10551492125243691632LLU), QU(17668869969146434804LLU),\n\tQU(13646002971174390445LLU), QU( 9804471050759613248LLU),\n\tQU( 5511670439655935493LLU), QU(18103342091070400926LLU),\n\tQU(17224512747665137533LLU), QU(15534627482992618168LLU),\n\tQU( 1423813266186582647LLU), QU(15821176807932930024LLU),\n\tQU(   30323369733607156LLU), QU(11599382494723479403LLU),\n\tQU(  653856076586810062LLU), QU( 3176437395144899659LLU),\n\tQU(14028076268147963917LLU), QU(16156398271809666195LLU),\n\tQU( 3166955484848201676LLU), QU( 5746805620136919390LLU),\n\tQU(17297845208891256593LLU), QU(11691653183226428483LLU),\n\tQU(17900026146506981577LLU), QU(15387382115755971042LLU),\n\tQU(16923567681040845943LLU), QU( 8039057517199388606LLU),\n\tQU(11748409241468629263LLU), QU(  794358245539076095LLU),\n\tQU(13438501964693401242LLU), QU(14036803236515618962LLU),\n\tQU( 5252311215205424721LLU), QU(17806589612915509081LLU),\n\tQU( 6802767092397596006LLU), QU(14212120431184557140LLU),\n\tQU( 1072951366761385712LLU), QU(13098491780722836296LLU),\n\tQU( 9466676828710797353LLU), QU(12673056849042830081LLU),\n\tQU(12763726623645357580LLU), QU(16468961652999309493LLU),\n\tQU(15305979875636438926LLU), QU(17444713151223449734LLU),\n\tQU( 5692214267627883674LLU), QU(13049589139196151505LLU),\n\tQU(  880115207831670745LLU), QU( 1776529075789695498LLU),\n\tQU(16695225897801466485LLU), QU(10666901778795346845LLU),\n\tQU( 6164389346722833869LLU), QU( 2863817793264300475LLU),\n\tQU( 9464049921886304754LLU), QU( 3993566636740015468LLU),\n\tQU( 9983749692528514136LLU), QU(16375286075057755211LLU),\n\tQU(16042643417005440820LLU), QU(11445419662923489877LLU),\n\tQU( 7999038846885158836LLU), QU( 6721913661721511535LLU),\n\tQU( 5363052654139357320LLU), QU( 1817788761173584205LLU),\n\tQU(13290974386445856444LLU), QU( 4650350818937984680LLU),\n\tQU( 8219183528102484836LLU), QU( 1569862923500819899LLU),\n\tQU( 4189359732136641860LLU), QU(14202822961683148583LLU),\n\tQU( 4457498315309429058LLU), QU(13089067387019074834LLU),\n\tQU(11075517153328927293LLU), QU(10277016248336668389LLU),\n\tQU( 7070509725324401122LLU), QU(17808892017780289380LLU),\n\tQU(13143367339909287349LLU), QU( 1377743745360085151LLU),\n\tQU( 5749341807421286485LLU), QU(14832814616770931325LLU),\n\tQU( 7688820635324359492LLU), QU(10960474011539770045LLU),\n\tQU(   81970066653179790LLU), QU(12619476072607878022LLU),\n\tQU( 4419566616271201744LLU), QU(15147917311750568503LLU),\n\tQU( 5549739182852706345LLU), QU( 7308198397975204770LLU),\n\tQU(13580425496671289278LLU), QU(17070764785210130301LLU),\n\tQU( 8202832846285604405LLU), QU( 6873046287640887249LLU),\n\tQU( 6927424434308206114LLU), QU( 6139014645937224874LLU),\n\tQU(10290373645978487639LLU), QU(15904261291701523804LLU),\n\tQU( 9628743442057826883LLU), QU(18383429096255546714LLU),\n\tQU( 4977413265753686967LLU), QU( 7714317492425012869LLU),\n\tQU( 9025232586309926193LLU), QU(14627338359776709107LLU),\n\tQU(14759849896467790763LLU), QU(10931129435864423252LLU),\n\tQU( 4588456988775014359LLU), QU(10699388531797056724LLU),\n\tQU(  468652268869238792LLU), QU( 5755943035328078086LLU),\n\tQU( 2102437379988580216LLU), QU( 9986312786506674028LLU),\n\tQU( 2654207180040945604LLU), QU( 8726634790559960062LLU),\n\tQU(  100497234871808137LLU), QU( 2800137176951425819LLU),\n\tQU( 6076627612918553487LLU), QU( 5780186919186152796LLU),\n\tQU( 8179183595769929098LLU), QU( 6009426283716221169LLU),\n\tQU( 2796662551397449358LLU), QU( 1756961367041986764LLU),\n\tQU( 6972897917355606205LLU), QU(14524774345368968243LLU),\n\tQU( 2773529684745706940LLU), QU( 4853632376213075959LLU),\n\tQU( 4198177923731358102LLU), QU( 8271224913084139776LLU),\n\tQU( 2741753121611092226LLU), QU(16782366145996731181LLU),\n\tQU(15426125238972640790LLU), QU(13595497100671260342LLU),\n\tQU( 3173531022836259898LLU), QU( 6573264560319511662LLU),\n\tQU(18041111951511157441LLU), QU( 2351433581833135952LLU),\n\tQU( 3113255578908173487LLU), QU( 1739371330877858784LLU),\n\tQU(16046126562789165480LLU), QU( 8072101652214192925LLU),\n\tQU(15267091584090664910LLU), QU( 9309579200403648940LLU),\n\tQU( 5218892439752408722LLU), QU(14492477246004337115LLU),\n\tQU(17431037586679770619LLU), QU( 7385248135963250480LLU),\n\tQU( 9580144956565560660LLU), QU( 4919546228040008720LLU),\n\tQU(15261542469145035584LLU), QU(18233297270822253102LLU),\n\tQU( 5453248417992302857LLU), QU( 9309519155931460285LLU),\n\tQU(10342813012345291756LLU), QU(15676085186784762381LLU),\n\tQU(15912092950691300645LLU), QU( 9371053121499003195LLU),\n\tQU( 9897186478226866746LLU), QU(14061858287188196327LLU),\n\tQU(  122575971620788119LLU), QU(12146750969116317754LLU),\n\tQU( 4438317272813245201LLU), QU( 8332576791009527119LLU),\n\tQU(13907785691786542057LLU), QU(10374194887283287467LLU),\n\tQU( 2098798755649059566LLU), QU( 3416235197748288894LLU),\n\tQU( 8688269957320773484LLU), QU( 7503964602397371571LLU),\n\tQU(16724977015147478236LLU), QU( 9461512855439858184LLU),\n\tQU(13259049744534534727LLU), QU( 3583094952542899294LLU),\n\tQU( 8764245731305528292LLU), QU(13240823595462088985LLU),\n\tQU(13716141617617910448LLU), QU(18114969519935960955LLU),\n\tQU( 2297553615798302206LLU), QU( 4585521442944663362LLU),\n\tQU(17776858680630198686LLU), QU( 4685873229192163363LLU),\n\tQU(  152558080671135627LLU), QU(15424900540842670088LLU),\n\tQU(13229630297130024108LLU), QU(17530268788245718717LLU),\n\tQU(16675633913065714144LLU), QU( 3158912717897568068LLU),\n\tQU(15399132185380087288LLU), QU( 7401418744515677872LLU),\n\tQU(13135412922344398535LLU), QU( 6385314346100509511LLU),\n\tQU(13962867001134161139LLU), QU(10272780155442671999LLU),\n\tQU(12894856086597769142LLU), QU(13340877795287554994LLU),\n\tQU(12913630602094607396LLU), QU(12543167911119793857LLU),\n\tQU(17343570372251873096LLU), QU(10959487764494150545LLU),\n\tQU( 6966737953093821128LLU), QU(13780699135496988601LLU),\n\tQU( 4405070719380142046LLU), QU(14923788365607284982LLU),\n\tQU( 2869487678905148380LLU), QU( 6416272754197188403LLU),\n\tQU(15017380475943612591LLU), QU( 1995636220918429487LLU),\n\tQU( 3402016804620122716LLU), QU(15800188663407057080LLU),\n\tQU(11362369990390932882LLU), QU(15262183501637986147LLU),\n\tQU(10239175385387371494LLU), QU( 9352042420365748334LLU),\n\tQU( 1682457034285119875LLU), QU( 1724710651376289644LLU),\n\tQU( 2038157098893817966LLU), QU( 9897825558324608773LLU),\n\tQU( 1477666236519164736LLU), QU(16835397314511233640LLU),\n\tQU(10370866327005346508LLU), QU(10157504370660621982LLU),\n\tQU(12113904045335882069LLU), QU(13326444439742783008LLU),\n\tQU(11302769043000765804LLU), QU(13594979923955228484LLU),\n\tQU(11779351762613475968LLU), QU( 3786101619539298383LLU),\n\tQU( 8021122969180846063LLU), QU(15745904401162500495LLU),\n\tQU(10762168465993897267LLU), QU(13552058957896319026LLU),\n\tQU(11200228655252462013LLU), QU( 5035370357337441226LLU),\n\tQU( 7593918984545500013LLU), QU( 5418554918361528700LLU),\n\tQU( 4858270799405446371LLU), QU( 9974659566876282544LLU),\n\tQU(18227595922273957859LLU), QU( 2772778443635656220LLU),\n\tQU(14285143053182085385LLU), QU( 9939700992429600469LLU),\n\tQU(12756185904545598068LLU), QU( 2020783375367345262LLU),\n\tQU(   57026775058331227LLU), QU(  950827867930065454LLU),\n\tQU( 6602279670145371217LLU), QU( 2291171535443566929LLU),\n\tQU( 5832380724425010313LLU), QU( 1220343904715982285LLU),\n\tQU(17045542598598037633LLU), QU(15460481779702820971LLU),\n\tQU(13948388779949365130LLU), QU(13975040175430829518LLU),\n\tQU(17477538238425541763LLU), QU(11104663041851745725LLU),\n\tQU(15860992957141157587LLU), QU(14529434633012950138LLU),\n\tQU( 2504838019075394203LLU), QU( 7512113882611121886LLU),\n\tQU( 4859973559980886617LLU), QU( 1258601555703250219LLU),\n\tQU(15594548157514316394LLU), QU( 4516730171963773048LLU),\n\tQU(11380103193905031983LLU), QU( 6809282239982353344LLU),\n\tQU(18045256930420065002LLU), QU( 2453702683108791859LLU),\n\tQU(  977214582986981460LLU), QU( 2006410402232713466LLU),\n\tQU( 6192236267216378358LLU), QU( 3429468402195675253LLU),\n\tQU(18146933153017348921LLU), QU(17369978576367231139LLU),\n\tQU( 1246940717230386603LLU), QU(11335758870083327110LLU),\n\tQU(14166488801730353682LLU), QU( 9008573127269635732LLU),\n\tQU(10776025389820643815LLU), QU(15087605441903942962LLU),\n\tQU( 1359542462712147922LLU), QU(13898874411226454206LLU),\n\tQU(17911176066536804411LLU), QU( 9435590428600085274LLU),\n\tQU(  294488509967864007LLU), QU( 8890111397567922046LLU),\n\tQU( 7987823476034328778LLU), QU(13263827582440967651LLU),\n\tQU( 7503774813106751573LLU), QU(14974747296185646837LLU),\n\tQU( 8504765037032103375LLU), QU(17340303357444536213LLU),\n\tQU( 7704610912964485743LLU), QU( 8107533670327205061LLU),\n\tQU( 9062969835083315985LLU), QU(16968963142126734184LLU),\n\tQU(12958041214190810180LLU), QU( 2720170147759570200LLU),\n\tQU( 2986358963942189566LLU), QU(14884226322219356580LLU),\n\tQU(  286224325144368520LLU), QU(11313800433154279797LLU),\n\tQU(18366849528439673248LLU), QU(17899725929482368789LLU),\n\tQU( 3730004284609106799LLU), QU( 1654474302052767205LLU),\n\tQU( 5006698007047077032LLU), QU( 8196893913601182838LLU),\n\tQU(15214541774425211640LLU), QU(17391346045606626073LLU),\n\tQU( 8369003584076969089LLU), QU( 3939046733368550293LLU),\n\tQU(10178639720308707785LLU), QU( 2180248669304388697LLU),\n\tQU(   62894391300126322LLU), QU( 9205708961736223191LLU),\n\tQU( 6837431058165360438LLU), QU( 3150743890848308214LLU),\n\tQU(17849330658111464583LLU), QU(12214815643135450865LLU),\n\tQU(13410713840519603402LLU), QU( 3200778126692046802LLU),\n\tQU(13354780043041779313LLU), QU(  800850022756886036LLU),\n\tQU(15660052933953067433LLU), QU( 6572823544154375676LLU),\n\tQU(11030281857015819266LLU), QU(12682241941471433835LLU),\n\tQU(11654136407300274693LLU), QU( 4517795492388641109LLU),\n\tQU( 9757017371504524244LLU), QU(17833043400781889277LLU),\n\tQU(12685085201747792227LLU), QU(10408057728835019573LLU),\n\tQU(   98370418513455221LLU), QU( 6732663555696848598LLU),\n\tQU(13248530959948529780LLU), QU( 3530441401230622826LLU),\n\tQU(18188251992895660615LLU), QU( 1847918354186383756LLU),\n\tQU( 1127392190402660921LLU), QU(11293734643143819463LLU),\n\tQU( 3015506344578682982LLU), QU(13852645444071153329LLU),\n\tQU( 2121359659091349142LLU), QU( 1294604376116677694LLU),\n\tQU( 5616576231286352318LLU), QU( 7112502442954235625LLU),\n\tQU(11676228199551561689LLU), QU(12925182803007305359LLU),\n\tQU( 7852375518160493082LLU), QU( 1136513130539296154LLU),\n\tQU( 5636923900916593195LLU), QU( 3221077517612607747LLU),\n\tQU(17784790465798152513LLU), QU( 3554210049056995938LLU),\n\tQU(17476839685878225874LLU), QU( 3206836372585575732LLU),\n\tQU( 2765333945644823430LLU), QU(10080070903718799528LLU),\n\tQU( 5412370818878286353LLU), QU( 9689685887726257728LLU),\n\tQU( 8236117509123533998LLU), QU( 1951139137165040214LLU),\n\tQU( 4492205209227980349LLU), QU(16541291230861602967LLU),\n\tQU( 1424371548301437940LLU), QU( 9117562079669206794LLU),\n\tQU(14374681563251691625LLU), QU(13873164030199921303LLU),\n\tQU( 6680317946770936731LLU), QU(15586334026918276214LLU),\n\tQU(10896213950976109802LLU), QU( 9506261949596413689LLU),\n\tQU( 9903949574308040616LLU), QU( 6038397344557204470LLU),\n\tQU(  174601465422373648LLU), QU(15946141191338238030LLU),\n\tQU(17142225620992044937LLU), QU( 7552030283784477064LLU),\n\tQU( 2947372384532947997LLU), QU(  510797021688197711LLU),\n\tQU( 4962499439249363461LLU), QU(   23770320158385357LLU),\n\tQU(  959774499105138124LLU), QU( 1468396011518788276LLU),\n\tQU( 2015698006852312308LLU), QU( 4149400718489980136LLU),\n\tQU( 5992916099522371188LLU), QU(10819182935265531076LLU),\n\tQU(16189787999192351131LLU), QU(  342833961790261950LLU),\n\tQU(12470830319550495336LLU), QU(18128495041912812501LLU),\n\tQU( 1193600899723524337LLU), QU( 9056793666590079770LLU),\n\tQU( 2154021227041669041LLU), QU( 4963570213951235735LLU),\n\tQU( 4865075960209211409LLU), QU( 2097724599039942963LLU),\n\tQU( 2024080278583179845LLU), QU(11527054549196576736LLU),\n\tQU(10650256084182390252LLU), QU( 4808408648695766755LLU),\n\tQU( 1642839215013788844LLU), QU(10607187948250398390LLU),\n\tQU( 7076868166085913508LLU), QU(  730522571106887032LLU),\n\tQU(12500579240208524895LLU), QU( 4484390097311355324LLU),\n\tQU(15145801330700623870LLU), QU( 8055827661392944028LLU),\n\tQU( 5865092976832712268LLU), QU(15159212508053625143LLU),\n\tQU( 3560964582876483341LLU), QU( 4070052741344438280LLU),\n\tQU( 6032585709886855634LLU), QU(15643262320904604873LLU),\n\tQU( 2565119772293371111LLU), QU(  318314293065348260LLU),\n\tQU(15047458749141511872LLU), QU( 7772788389811528730LLU),\n\tQU( 7081187494343801976LLU), QU( 6465136009467253947LLU),\n\tQU(10425940692543362069LLU), QU(  554608190318339115LLU),\n\tQU(14796699860302125214LLU), QU( 1638153134431111443LLU),\n\tQU(10336967447052276248LLU), QU( 8412308070396592958LLU),\n\tQU( 4004557277152051226LLU), QU( 8143598997278774834LLU),\n\tQU(16413323996508783221LLU), QU(13139418758033994949LLU),\n\tQU( 9772709138335006667LLU), QU( 2818167159287157659LLU),\n\tQU(17091740573832523669LLU), QU(14629199013130751608LLU),\n\tQU(18268322711500338185LLU), QU( 8290963415675493063LLU),\n\tQU( 8830864907452542588LLU), QU( 1614839084637494849LLU),\n\tQU(14855358500870422231LLU), QU( 3472996748392519937LLU),\n\tQU(15317151166268877716LLU), QU( 5825895018698400362LLU),\n\tQU(16730208429367544129LLU), QU(10481156578141202800LLU),\n\tQU( 4746166512382823750LLU), QU(12720876014472464998LLU),\n\tQU( 8825177124486735972LLU), QU(13733447296837467838LLU),\n\tQU( 6412293741681359625LLU), QU( 8313213138756135033LLU),\n\tQU(11421481194803712517LLU), QU( 7997007691544174032LLU),\n\tQU( 6812963847917605930LLU), QU( 9683091901227558641LLU),\n\tQU(14703594165860324713LLU), QU( 1775476144519618309LLU),\n\tQU( 2724283288516469519LLU), QU(  717642555185856868LLU),\n\tQU( 8736402192215092346LLU), QU(11878800336431381021LLU),\n\tQU( 4348816066017061293LLU), QU( 6115112756583631307LLU),\n\tQU( 9176597239667142976LLU), QU(12615622714894259204LLU),\n\tQU(10283406711301385987LLU), QU( 5111762509485379420LLU),\n\tQU( 3118290051198688449LLU), QU( 7345123071632232145LLU),\n\tQU( 9176423451688682359LLU), QU( 4843865456157868971LLU),\n\tQU(12008036363752566088LLU), QU(12058837181919397720LLU),\n\tQU( 2145073958457347366LLU), QU( 1526504881672818067LLU),\n\tQU( 3488830105567134848LLU), QU(13208362960674805143LLU),\n\tQU( 4077549672899572192LLU), QU( 7770995684693818365LLU),\n\tQU( 1398532341546313593LLU), QU(12711859908703927840LLU),\n\tQU( 1417561172594446813LLU), QU(17045191024194170604LLU),\n\tQU( 4101933177604931713LLU), QU(14708428834203480320LLU),\n\tQU(17447509264469407724LLU), QU(14314821973983434255LLU),\n\tQU(17990472271061617265LLU), QU( 5087756685841673942LLU),\n\tQU(12797820586893859939LLU), QU( 1778128952671092879LLU),\n\tQU( 3535918530508665898LLU), QU( 9035729701042481301LLU),\n\tQU(14808661568277079962LLU), QU(14587345077537747914LLU),\n\tQU(11920080002323122708LLU), QU( 6426515805197278753LLU),\n\tQU( 3295612216725984831LLU), QU(11040722532100876120LLU),\n\tQU(12305952936387598754LLU), QU(16097391899742004253LLU),\n\tQU( 4908537335606182208LLU), QU(12446674552196795504LLU),\n\tQU(16010497855816895177LLU), QU( 9194378874788615551LLU),\n\tQU( 3382957529567613384LLU), QU( 5154647600754974077LLU),\n\tQU( 9801822865328396141LLU), QU( 9023662173919288143LLU),\n\tQU(17623115353825147868LLU), QU( 8238115767443015816LLU),\n\tQU(15811444159859002560LLU), QU( 9085612528904059661LLU),\n\tQU( 6888601089398614254LLU), QU(  258252992894160189LLU),\n\tQU( 6704363880792428622LLU), QU( 6114966032147235763LLU),\n\tQU(11075393882690261875LLU), QU( 8797664238933620407LLU),\n\tQU( 5901892006476726920LLU), QU( 5309780159285518958LLU),\n\tQU(14940808387240817367LLU), QU(14642032021449656698LLU),\n\tQU( 9808256672068504139LLU), QU( 3670135111380607658LLU),\n\tQU(11211211097845960152LLU), QU( 1474304506716695808LLU),\n\tQU(15843166204506876239LLU), QU( 7661051252471780561LLU),\n\tQU(10170905502249418476LLU), QU( 7801416045582028589LLU),\n\tQU( 2763981484737053050LLU), QU( 9491377905499253054LLU),\n\tQU(16201395896336915095LLU), QU( 9256513756442782198LLU),\n\tQU( 5411283157972456034LLU), QU( 5059433122288321676LLU),\n\tQU( 4327408006721123357LLU), QU( 9278544078834433377LLU),\n\tQU( 7601527110882281612LLU), QU(11848295896975505251LLU),\n\tQU(12096998801094735560LLU), QU(14773480339823506413LLU),\n\tQU(15586227433895802149LLU), QU(12786541257830242872LLU),\n\tQU( 6904692985140503067LLU), QU( 5309011515263103959LLU),\n\tQU(12105257191179371066LLU), QU(14654380212442225037LLU),\n\tQU( 2556774974190695009LLU), QU( 4461297399927600261LLU),\n\tQU(14888225660915118646LLU), QU(14915459341148291824LLU),\n\tQU( 2738802166252327631LLU), QU( 6047155789239131512LLU),\n\tQU(12920545353217010338LLU), QU(10697617257007840205LLU),\n\tQU( 2751585253158203504LLU), QU(13252729159780047496LLU),\n\tQU(14700326134672815469LLU), QU(14082527904374600529LLU),\n\tQU(16852962273496542070LLU), QU(17446675504235853907LLU),\n\tQU(15019600398527572311LLU), QU(12312781346344081551LLU),\n\tQU(14524667935039810450LLU), QU( 5634005663377195738LLU),\n\tQU(11375574739525000569LLU), QU( 2423665396433260040LLU),\n\tQU( 5222836914796015410LLU), QU( 4397666386492647387LLU),\n\tQU( 4619294441691707638LLU), QU(  665088602354770716LLU),\n\tQU(13246495665281593610LLU), QU( 6564144270549729409LLU),\n\tQU(10223216188145661688LLU), QU( 3961556907299230585LLU),\n\tQU(11543262515492439914LLU), QU(16118031437285993790LLU),\n\tQU( 7143417964520166465LLU), QU(13295053515909486772LLU),\n\tQU(   40434666004899675LLU), QU(17127804194038347164LLU),\n\tQU( 8599165966560586269LLU), QU( 8214016749011284903LLU),\n\tQU(13725130352140465239LLU), QU( 5467254474431726291LLU),\n\tQU( 7748584297438219877LLU), QU(16933551114829772472LLU),\n\tQU( 2169618439506799400LLU), QU( 2169787627665113463LLU),\n\tQU(17314493571267943764LLU), QU(18053575102911354912LLU),\n\tQU(11928303275378476973LLU), QU(11593850925061715550LLU),\n\tQU(17782269923473589362LLU), QU( 3280235307704747039LLU),\n\tQU( 6145343578598685149LLU), QU(17080117031114086090LLU),\n\tQU(18066839902983594755LLU), QU( 6517508430331020706LLU),\n\tQU( 8092908893950411541LLU), QU(12558378233386153732LLU),\n\tQU( 4476532167973132976LLU), QU(16081642430367025016LLU),\n\tQU( 4233154094369139361LLU), QU( 8693630486693161027LLU),\n\tQU(11244959343027742285LLU), QU(12273503967768513508LLU),\n\tQU(14108978636385284876LLU), QU( 7242414665378826984LLU),\n\tQU( 6561316938846562432LLU), QU( 8601038474994665795LLU),\n\tQU(17532942353612365904LLU), QU(17940076637020912186LLU),\n\tQU( 7340260368823171304LLU), QU( 7061807613916067905LLU),\n\tQU(10561734935039519326LLU), QU(17990796503724650862LLU),\n\tQU( 6208732943911827159LLU), QU(  359077562804090617LLU),\n\tQU(14177751537784403113LLU), QU(10659599444915362902LLU),\n\tQU(15081727220615085833LLU), QU(13417573895659757486LLU),\n\tQU(15513842342017811524LLU), QU(11814141516204288231LLU),\n\tQU( 1827312513875101814LLU), QU( 2804611699894603103LLU),\n\tQU(17116500469975602763LLU), QU(12270191815211952087LLU),\n\tQU(12256358467786024988LLU), QU(18435021722453971267LLU),\n\tQU(  671330264390865618LLU), QU(  476504300460286050LLU),\n\tQU(16465470901027093441LLU), QU( 4047724406247136402LLU),\n\tQU( 1322305451411883346LLU), QU( 1388308688834322280LLU),\n\tQU( 7303989085269758176LLU), QU( 9323792664765233642LLU),\n\tQU( 4542762575316368936LLU), QU(17342696132794337618LLU),\n\tQU( 4588025054768498379LLU), QU(13415475057390330804LLU),\n\tQU(17880279491733405570LLU), QU(10610553400618620353LLU),\n\tQU( 3180842072658960139LLU), QU(13002966655454270120LLU),\n\tQU( 1665301181064982826LLU), QU( 7083673946791258979LLU),\n\tQU(  190522247122496820LLU), QU(17388280237250677740LLU),\n\tQU( 8430770379923642945LLU), QU(12987180971921668584LLU),\n\tQU( 2311086108365390642LLU), QU( 2870984383579822345LLU),\n\tQU(14014682609164653318LLU), QU(14467187293062251484LLU),\n\tQU(  192186361147413298LLU), QU(15171951713531796524LLU),\n\tQU( 9900305495015948728LLU), QU(17958004775615466344LLU),\n\tQU(14346380954498606514LLU), QU(18040047357617407096LLU),\n\tQU( 5035237584833424532LLU), QU(15089555460613972287LLU),\n\tQU( 4131411873749729831LLU), QU( 1329013581168250330LLU),\n\tQU(10095353333051193949LLU), QU(10749518561022462716LLU),\n\tQU( 9050611429810755847LLU), QU(15022028840236655649LLU),\n\tQU( 8775554279239748298LLU), QU(13105754025489230502LLU),\n\tQU(15471300118574167585LLU), QU(   89864764002355628LLU),\n\tQU( 8776416323420466637LLU), QU( 5280258630612040891LLU),\n\tQU( 2719174488591862912LLU), QU( 7599309137399661994LLU),\n\tQU(15012887256778039979LLU), QU(14062981725630928925LLU),\n\tQU(12038536286991689603LLU), QU( 7089756544681775245LLU),\n\tQU(10376661532744718039LLU), QU( 1265198725901533130LLU),\n\tQU(13807996727081142408LLU), QU( 2935019626765036403LLU),\n\tQU( 7651672460680700141LLU), QU( 3644093016200370795LLU),\n\tQU( 2840982578090080674LLU), QU(17956262740157449201LLU),\n\tQU(18267979450492880548LLU), QU(11799503659796848070LLU),\n\tQU( 9942537025669672388LLU), QU(11886606816406990297LLU),\n\tQU( 5488594946437447576LLU), QU( 7226714353282744302LLU),\n\tQU( 3784851653123877043LLU), QU(  878018453244803041LLU),\n\tQU(12110022586268616085LLU), QU(  734072179404675123LLU),\n\tQU(11869573627998248542LLU), QU(  469150421297783998LLU),\n\tQU(  260151124912803804LLU), QU(11639179410120968649LLU),\n\tQU( 9318165193840846253LLU), QU(12795671722734758075LLU),\n\tQU(15318410297267253933LLU), QU(  691524703570062620LLU),\n\tQU( 5837129010576994601LLU), QU(15045963859726941052LLU),\n\tQU( 5850056944932238169LLU), QU(12017434144750943807LLU),\n\tQU( 7447139064928956574LLU), QU( 3101711812658245019LLU),\n\tQU(16052940704474982954LLU), QU(18195745945986994042LLU),\n\tQU( 8932252132785575659LLU), QU(13390817488106794834LLU),\n\tQU(11582771836502517453LLU), QU( 4964411326683611686LLU),\n\tQU( 2195093981702694011LLU), QU(14145229538389675669LLU),\n\tQU(16459605532062271798LLU), QU(  866316924816482864LLU),\n\tQU( 4593041209937286377LLU), QU( 8415491391910972138LLU),\n\tQU( 4171236715600528969LLU), QU(16637569303336782889LLU),\n\tQU( 2002011073439212680LLU), QU(17695124661097601411LLU),\n\tQU( 4627687053598611702LLU), QU( 7895831936020190403LLU),\n\tQU( 8455951300917267802LLU), QU( 2923861649108534854LLU),\n\tQU( 8344557563927786255LLU), QU( 6408671940373352556LLU),\n\tQU(12210227354536675772LLU), QU(14294804157294222295LLU),\n\tQU(10103022425071085127LLU), QU(10092959489504123771LLU),\n\tQU( 6554774405376736268LLU), QU(12629917718410641774LLU),\n\tQU( 6260933257596067126LLU), QU( 2460827021439369673LLU),\n\tQU( 2541962996717103668LLU), QU(  597377203127351475LLU),\n\tQU( 5316984203117315309LLU), QU( 4811211393563241961LLU),\n\tQU(13119698597255811641LLU), QU( 8048691512862388981LLU),\n\tQU(10216818971194073842LLU), QU( 4612229970165291764LLU),\n\tQU(10000980798419974770LLU), QU( 6877640812402540687LLU),\n\tQU( 1488727563290436992LLU), QU( 2227774069895697318LLU),\n\tQU(11237754507523316593LLU), QU(13478948605382290972LLU),\n\tQU( 1963583846976858124LLU), QU( 5512309205269276457LLU),\n\tQU( 3972770164717652347LLU), QU( 3841751276198975037LLU),\n\tQU(10283343042181903117LLU), QU( 8564001259792872199LLU),\n\tQU(16472187244722489221LLU), QU( 8953493499268945921LLU),\n\tQU( 3518747340357279580LLU), QU( 4003157546223963073LLU),\n\tQU( 3270305958289814590LLU), QU( 3966704458129482496LLU),\n\tQU( 8122141865926661939LLU), QU(14627734748099506653LLU),\n\tQU(13064426990862560568LLU), QU( 2414079187889870829LLU),\n\tQU( 5378461209354225306LLU), QU(10841985740128255566LLU),\n\tQU(  538582442885401738LLU), QU( 7535089183482905946LLU),\n\tQU(16117559957598879095LLU), QU( 8477890721414539741LLU),\n\tQU( 1459127491209533386LLU), QU(17035126360733620462LLU),\n\tQU( 8517668552872379126LLU), QU(10292151468337355014LLU),\n\tQU(17081267732745344157LLU), QU(13751455337946087178LLU),\n\tQU(14026945459523832966LLU), QU( 6653278775061723516LLU),\n\tQU(10619085543856390441LLU), QU( 2196343631481122885LLU),\n\tQU(10045966074702826136LLU), QU(10082317330452718282LLU),\n\tQU( 5920859259504831242LLU), QU( 9951879073426540617LLU),\n\tQU( 7074696649151414158LLU), QU(15808193543879464318LLU),\n\tQU( 7385247772746953374LLU), QU( 3192003544283864292LLU),\n\tQU(18153684490917593847LLU), QU(12423498260668568905LLU),\n\tQU(10957758099756378169LLU), QU(11488762179911016040LLU),\n\tQU( 2099931186465333782LLU), QU(11180979581250294432LLU),\n\tQU( 8098916250668367933LLU), QU( 3529200436790763465LLU),\n\tQU(12988418908674681745LLU), QU( 6147567275954808580LLU),\n\tQU( 3207503344604030989LLU), QU(10761592604898615360LLU),\n\tQU(  229854861031893504LLU), QU( 8809853962667144291LLU),\n\tQU(13957364469005693860LLU), QU( 7634287665224495886LLU),\n\tQU(12353487366976556874LLU), QU( 1134423796317152034LLU),\n\tQU( 2088992471334107068LLU), QU( 7393372127190799698LLU),\n\tQU( 1845367839871058391LLU), QU(  207922563987322884LLU),\n\tQU(11960870813159944976LLU), QU(12182120053317317363LLU),\n\tQU(17307358132571709283LLU), QU(13871081155552824936LLU),\n\tQU(18304446751741566262LLU), QU( 7178705220184302849LLU),\n\tQU(10929605677758824425LLU), QU(16446976977835806844LLU),\n\tQU(13723874412159769044LLU), QU( 6942854352100915216LLU),\n\tQU( 1726308474365729390LLU), QU( 2150078766445323155LLU),\n\tQU(15345558947919656626LLU), QU(12145453828874527201LLU),\n\tQU( 2054448620739726849LLU), QU( 2740102003352628137LLU),\n\tQU(11294462163577610655LLU), QU(  756164283387413743LLU),\n\tQU(17841144758438810880LLU), QU(10802406021185415861LLU),\n\tQU( 8716455530476737846LLU), QU( 6321788834517649606LLU),\n\tQU(14681322910577468426LLU), QU(17330043563884336387LLU),\n\tQU(12701802180050071614LLU), QU(14695105111079727151LLU),\n\tQU( 5112098511654172830LLU), QU( 4957505496794139973LLU),\n\tQU( 8270979451952045982LLU), QU(12307685939199120969LLU),\n\tQU(12425799408953443032LLU), QU( 8376410143634796588LLU),\n\tQU(16621778679680060464LLU), QU( 3580497854566660073LLU),\n\tQU( 1122515747803382416LLU), QU(  857664980960597599LLU),\n\tQU( 6343640119895925918LLU), QU(12878473260854462891LLU),\n\tQU(10036813920765722626LLU), QU(14451335468363173812LLU),\n\tQU( 5476809692401102807LLU), QU(16442255173514366342LLU),\n\tQU(13060203194757167104LLU), QU(14354124071243177715LLU),\n\tQU(15961249405696125227LLU), QU(13703893649690872584LLU),\n\tQU(  363907326340340064LLU), QU( 6247455540491754842LLU),\n\tQU(12242249332757832361LLU), QU(  156065475679796717LLU),\n\tQU( 9351116235749732355LLU), QU( 4590350628677701405LLU),\n\tQU( 1671195940982350389LLU), QU(13501398458898451905LLU),\n\tQU( 6526341991225002255LLU), QU( 1689782913778157592LLU),\n\tQU( 7439222350869010334LLU), QU(13975150263226478308LLU),\n\tQU(11411961169932682710LLU), QU(17204271834833847277LLU),\n\tQU(  541534742544435367LLU), QU( 6591191931218949684LLU),\n\tQU( 2645454775478232486LLU), QU( 4322857481256485321LLU),\n\tQU( 8477416487553065110LLU), QU(12902505428548435048LLU),\n\tQU(  971445777981341415LLU), QU(14995104682744976712LLU),\n\tQU( 4243341648807158063LLU), QU( 8695061252721927661LLU),\n\tQU( 5028202003270177222LLU), QU( 2289257340915567840LLU),\n\tQU(13870416345121866007LLU), QU(13994481698072092233LLU),\n\tQU( 6912785400753196481LLU), QU( 2278309315841980139LLU),\n\tQU( 4329765449648304839LLU), QU( 5963108095785485298LLU),\n\tQU( 4880024847478722478LLU), QU(16015608779890240947LLU),\n\tQU( 1866679034261393544LLU), QU(  914821179919731519LLU),\n\tQU( 9643404035648760131LLU), QU( 2418114953615593915LLU),\n\tQU(  944756836073702374LLU), QU(15186388048737296834LLU),\n\tQU( 7723355336128442206LLU), QU( 7500747479679599691LLU),\n\tQU(18013961306453293634LLU), QU( 2315274808095756456LLU),\n\tQU(13655308255424029566LLU), QU(17203800273561677098LLU),\n\tQU( 1382158694422087756LLU), QU( 5090390250309588976LLU),\n\tQU(  517170818384213989LLU), QU( 1612709252627729621LLU),\n\tQU( 1330118955572449606LLU), QU(  300922478056709885LLU),\n\tQU(18115693291289091987LLU), QU(13491407109725238321LLU),\n\tQU(15293714633593827320LLU), QU( 5151539373053314504LLU),\n\tQU( 5951523243743139207LLU), QU(14459112015249527975LLU),\n\tQU( 5456113959000700739LLU), QU( 3877918438464873016LLU),\n\tQU(12534071654260163555LLU), QU(15871678376893555041LLU),\n\tQU(11005484805712025549LLU), QU(16353066973143374252LLU),\n\tQU( 4358331472063256685LLU), QU( 8268349332210859288LLU),\n\tQU(12485161590939658075LLU), QU(13955993592854471343LLU),\n\tQU( 5911446886848367039LLU), QU(14925834086813706974LLU),\n\tQU( 6590362597857994805LLU), QU( 1280544923533661875LLU),\n\tQU( 1637756018947988164LLU), QU( 4734090064512686329LLU),\n\tQU(16693705263131485912LLU), QU( 6834882340494360958LLU),\n\tQU( 8120732176159658505LLU), QU( 2244371958905329346LLU),\n\tQU(10447499707729734021LLU), QU( 7318742361446942194LLU),\n\tQU( 8032857516355555296LLU), QU(14023605983059313116LLU),\n\tQU( 1032336061815461376LLU), QU( 9840995337876562612LLU),\n\tQU( 9869256223029203587LLU), QU(12227975697177267636LLU),\n\tQU(12728115115844186033LLU), QU( 7752058479783205470LLU),\n\tQU(  729733219713393087LLU), QU(12954017801239007622LLU)\n};\nstatic const uint64_t init_by_array_64_expected[] = {\n\tQU( 2100341266307895239LLU), QU( 8344256300489757943LLU),\n\tQU(15687933285484243894LLU), QU( 8268620370277076319LLU),\n\tQU(12371852309826545459LLU), QU( 8800491541730110238LLU),\n\tQU(18113268950100835773LLU), QU( 2886823658884438119LLU),\n\tQU( 3293667307248180724LLU), QU( 9307928143300172731LLU),\n\tQU( 7688082017574293629LLU), QU(  900986224735166665LLU),\n\tQU( 9977972710722265039LLU), QU( 6008205004994830552LLU),\n\tQU(  546909104521689292LLU), QU( 7428471521869107594LLU),\n\tQU(14777563419314721179LLU), QU(16116143076567350053LLU),\n\tQU( 5322685342003142329LLU), QU( 4200427048445863473LLU),\n\tQU( 4693092150132559146LLU), QU(13671425863759338582LLU),\n\tQU( 6747117460737639916LLU), QU( 4732666080236551150LLU),\n\tQU( 5912839950611941263LLU), QU( 3903717554504704909LLU),\n\tQU( 2615667650256786818LLU), QU(10844129913887006352LLU),\n\tQU(13786467861810997820LLU), QU(14267853002994021570LLU),\n\tQU(13767807302847237439LLU), QU(16407963253707224617LLU),\n\tQU( 4802498363698583497LLU), QU( 2523802839317209764LLU),\n\tQU( 3822579397797475589LLU), QU( 8950320572212130610LLU),\n\tQU( 3745623504978342534LLU), QU(16092609066068482806LLU),\n\tQU( 9817016950274642398LLU), QU(10591660660323829098LLU),\n\tQU(11751606650792815920LLU), QU( 5122873818577122211LLU),\n\tQU(17209553764913936624LLU), QU( 6249057709284380343LLU),\n\tQU(15088791264695071830LLU), QU(15344673071709851930LLU),\n\tQU( 4345751415293646084LLU), QU( 2542865750703067928LLU),\n\tQU(13520525127852368784LLU), QU(18294188662880997241LLU),\n\tQU( 3871781938044881523LLU), QU( 2873487268122812184LLU),\n\tQU(15099676759482679005LLU), QU(15442599127239350490LLU),\n\tQU( 6311893274367710888LLU), QU( 3286118760484672933LLU),\n\tQU( 4146067961333542189LLU), QU(13303942567897208770LLU),\n\tQU( 8196013722255630418LLU), QU( 4437815439340979989LLU),\n\tQU(15433791533450605135LLU), QU( 4254828956815687049LLU),\n\tQU( 1310903207708286015LLU), QU(10529182764462398549LLU),\n\tQU(14900231311660638810LLU), QU( 9727017277104609793LLU),\n\tQU( 1821308310948199033LLU), QU(11628861435066772084LLU),\n\tQU( 9469019138491546924LLU), QU( 3145812670532604988LLU),\n\tQU( 9938468915045491919LLU), QU( 1562447430672662142LLU),\n\tQU(13963995266697989134LLU), QU( 3356884357625028695LLU),\n\tQU( 4499850304584309747LLU), QU( 8456825817023658122LLU),\n\tQU(10859039922814285279LLU), QU( 8099512337972526555LLU),\n\tQU(  348006375109672149LLU), QU(11919893998241688603LLU),\n\tQU( 1104199577402948826LLU), QU(16689191854356060289LLU),\n\tQU(10992552041730168078LLU), QU( 7243733172705465836LLU),\n\tQU( 5668075606180319560LLU), QU(18182847037333286970LLU),\n\tQU( 4290215357664631322LLU), QU( 4061414220791828613LLU),\n\tQU(13006291061652989604LLU), QU( 7140491178917128798LLU),\n\tQU(12703446217663283481LLU), QU( 5500220597564558267LLU),\n\tQU(10330551509971296358LLU), QU(15958554768648714492LLU),\n\tQU( 5174555954515360045LLU), QU( 1731318837687577735LLU),\n\tQU( 3557700801048354857LLU), QU(13764012341928616198LLU),\n\tQU(13115166194379119043LLU), QU( 7989321021560255519LLU),\n\tQU( 2103584280905877040LLU), QU( 9230788662155228488LLU),\n\tQU(16396629323325547654LLU), QU(  657926409811318051LLU),\n\tQU(15046700264391400727LLU), QU( 5120132858771880830LLU),\n\tQU( 7934160097989028561LLU), QU( 6963121488531976245LLU),\n\tQU(17412329602621742089LLU), QU(15144843053931774092LLU),\n\tQU(17204176651763054532LLU), QU(13166595387554065870LLU),\n\tQU( 8590377810513960213LLU), QU( 5834365135373991938LLU),\n\tQU( 7640913007182226243LLU), QU( 3479394703859418425LLU),\n\tQU(16402784452644521040LLU), QU( 4993979809687083980LLU),\n\tQU(13254522168097688865LLU), QU(15643659095244365219LLU),\n\tQU( 5881437660538424982LLU), QU(11174892200618987379LLU),\n\tQU(  254409966159711077LLU), QU(17158413043140549909LLU),\n\tQU( 3638048789290376272LLU), QU( 1376816930299489190LLU),\n\tQU( 4622462095217761923LLU), QU(15086407973010263515LLU),\n\tQU(13253971772784692238LLU), QU( 5270549043541649236LLU),\n\tQU(11182714186805411604LLU), QU(12283846437495577140LLU),\n\tQU( 5297647149908953219LLU), QU(10047451738316836654LLU),\n\tQU( 4938228100367874746LLU), QU(12328523025304077923LLU),\n\tQU( 3601049438595312361LLU), QU( 9313624118352733770LLU),\n\tQU(13322966086117661798LLU), QU(16660005705644029394LLU),\n\tQU(11337677526988872373LLU), QU(13869299102574417795LLU),\n\tQU(15642043183045645437LLU), QU( 3021755569085880019LLU),\n\tQU( 4979741767761188161LLU), QU(13679979092079279587LLU),\n\tQU( 3344685842861071743LLU), QU(13947960059899588104LLU),\n\tQU(  305806934293368007LLU), QU( 5749173929201650029LLU),\n\tQU(11123724852118844098LLU), QU(15128987688788879802LLU),\n\tQU(15251651211024665009LLU), QU( 7689925933816577776LLU),\n\tQU(16732804392695859449LLU), QU(17087345401014078468LLU),\n\tQU(14315108589159048871LLU), QU( 4820700266619778917LLU),\n\tQU(16709637539357958441LLU), QU( 4936227875177351374LLU),\n\tQU( 2137907697912987247LLU), QU(11628565601408395420LLU),\n\tQU( 2333250549241556786LLU), QU( 5711200379577778637LLU),\n\tQU( 5170680131529031729LLU), QU(12620392043061335164LLU),\n\tQU(   95363390101096078LLU), QU( 5487981914081709462LLU),\n\tQU( 1763109823981838620LLU), QU( 3395861271473224396LLU),\n\tQU( 1300496844282213595LLU), QU( 6894316212820232902LLU),\n\tQU(10673859651135576674LLU), QU( 5911839658857903252LLU),\n\tQU(17407110743387299102LLU), QU( 8257427154623140385LLU),\n\tQU(11389003026741800267LLU), QU( 4070043211095013717LLU),\n\tQU(11663806997145259025LLU), QU(15265598950648798210LLU),\n\tQU(  630585789434030934LLU), QU( 3524446529213587334LLU),\n\tQU( 7186424168495184211LLU), QU(10806585451386379021LLU),\n\tQU(11120017753500499273LLU), QU( 1586837651387701301LLU),\n\tQU(17530454400954415544LLU), QU( 9991670045077880430LLU),\n\tQU( 7550997268990730180LLU), QU( 8640249196597379304LLU),\n\tQU( 3522203892786893823LLU), QU(10401116549878854788LLU),\n\tQU(13690285544733124852LLU), QU( 8295785675455774586LLU),\n\tQU(15535716172155117603LLU), QU( 3112108583723722511LLU),\n\tQU(17633179955339271113LLU), QU(18154208056063759375LLU),\n\tQU( 1866409236285815666LLU), QU(13326075895396412882LLU),\n\tQU( 8756261842948020025LLU), QU( 6281852999868439131LLU),\n\tQU(15087653361275292858LLU), QU(10333923911152949397LLU),\n\tQU( 5265567645757408500LLU), QU(12728041843210352184LLU),\n\tQU( 6347959327507828759LLU), QU(  154112802625564758LLU),\n\tQU(18235228308679780218LLU), QU( 3253805274673352418LLU),\n\tQU( 4849171610689031197LLU), QU(17948529398340432518LLU),\n\tQU(13803510475637409167LLU), QU(13506570190409883095LLU),\n\tQU(15870801273282960805LLU), QU( 8451286481299170773LLU),\n\tQU( 9562190620034457541LLU), QU( 8518905387449138364LLU),\n\tQU(12681306401363385655LLU), QU( 3788073690559762558LLU),\n\tQU( 5256820289573487769LLU), QU( 2752021372314875467LLU),\n\tQU( 6354035166862520716LLU), QU( 4328956378309739069LLU),\n\tQU(  449087441228269600LLU), QU( 5533508742653090868LLU),\n\tQU( 1260389420404746988LLU), QU(18175394473289055097LLU),\n\tQU( 1535467109660399420LLU), QU( 8818894282874061442LLU),\n\tQU(12140873243824811213LLU), QU(15031386653823014946LLU),\n\tQU( 1286028221456149232LLU), QU( 6329608889367858784LLU),\n\tQU( 9419654354945132725LLU), QU( 6094576547061672379LLU),\n\tQU(17706217251847450255LLU), QU( 1733495073065878126LLU),\n\tQU(16918923754607552663LLU), QU( 8881949849954945044LLU),\n\tQU(12938977706896313891LLU), QU(14043628638299793407LLU),\n\tQU(18393874581723718233LLU), QU( 6886318534846892044LLU),\n\tQU(14577870878038334081LLU), QU(13541558383439414119LLU),\n\tQU(13570472158807588273LLU), QU(18300760537910283361LLU),\n\tQU(  818368572800609205LLU), QU( 1417000585112573219LLU),\n\tQU(12337533143867683655LLU), QU(12433180994702314480LLU),\n\tQU(  778190005829189083LLU), QU(13667356216206524711LLU),\n\tQU( 9866149895295225230LLU), QU(11043240490417111999LLU),\n\tQU( 1123933826541378598LLU), QU( 6469631933605123610LLU),\n\tQU(14508554074431980040LLU), QU(13918931242962026714LLU),\n\tQU( 2870785929342348285LLU), QU(14786362626740736974LLU),\n\tQU(13176680060902695786LLU), QU( 9591778613541679456LLU),\n\tQU( 9097662885117436706LLU), QU(  749262234240924947LLU),\n\tQU( 1944844067793307093LLU), QU( 4339214904577487742LLU),\n\tQU( 8009584152961946551LLU), QU(16073159501225501777LLU),\n\tQU( 3335870590499306217LLU), QU(17088312653151202847LLU),\n\tQU( 3108893142681931848LLU), QU(16636841767202792021LLU),\n\tQU(10423316431118400637LLU), QU( 8008357368674443506LLU),\n\tQU(11340015231914677875LLU), QU(17687896501594936090LLU),\n\tQU(15173627921763199958LLU), QU(  542569482243721959LLU),\n\tQU(15071714982769812975LLU), QU( 4466624872151386956LLU),\n\tQU( 1901780715602332461LLU), QU( 9822227742154351098LLU),\n\tQU( 1479332892928648780LLU), QU( 6981611948382474400LLU),\n\tQU( 7620824924456077376LLU), QU(14095973329429406782LLU),\n\tQU( 7902744005696185404LLU), QU(15830577219375036920LLU),\n\tQU(10287076667317764416LLU), QU(12334872764071724025LLU),\n\tQU( 4419302088133544331LLU), QU(14455842851266090520LLU),\n\tQU(12488077416504654222LLU), QU( 7953892017701886766LLU),\n\tQU( 6331484925529519007LLU), QU( 4902145853785030022LLU),\n\tQU(17010159216096443073LLU), QU(11945354668653886087LLU),\n\tQU(15112022728645230829LLU), QU(17363484484522986742LLU),\n\tQU( 4423497825896692887LLU), QU( 8155489510809067471LLU),\n\tQU(  258966605622576285LLU), QU( 5462958075742020534LLU),\n\tQU( 6763710214913276228LLU), QU( 2368935183451109054LLU),\n\tQU(14209506165246453811LLU), QU( 2646257040978514881LLU),\n\tQU( 3776001911922207672LLU), QU( 1419304601390147631LLU),\n\tQU(14987366598022458284LLU), QU( 3977770701065815721LLU),\n\tQU(  730820417451838898LLU), QU( 3982991703612885327LLU),\n\tQU( 2803544519671388477LLU), QU(17067667221114424649LLU),\n\tQU( 2922555119737867166LLU), QU( 1989477584121460932LLU),\n\tQU(15020387605892337354LLU), QU( 9293277796427533547LLU),\n\tQU(10722181424063557247LLU), QU(16704542332047511651LLU),\n\tQU( 5008286236142089514LLU), QU(16174732308747382540LLU),\n\tQU(17597019485798338402LLU), QU(13081745199110622093LLU),\n\tQU( 8850305883842258115LLU), QU(12723629125624589005LLU),\n\tQU( 8140566453402805978LLU), QU(15356684607680935061LLU),\n\tQU(14222190387342648650LLU), QU(11134610460665975178LLU),\n\tQU( 1259799058620984266LLU), QU(13281656268025610041LLU),\n\tQU(  298262561068153992LLU), QU(12277871700239212922LLU),\n\tQU(13911297774719779438LLU), QU(16556727962761474934LLU),\n\tQU(17903010316654728010LLU), QU( 9682617699648434744LLU),\n\tQU(14757681836838592850LLU), QU( 1327242446558524473LLU),\n\tQU(11126645098780572792LLU), QU( 1883602329313221774LLU),\n\tQU( 2543897783922776873LLU), QU(15029168513767772842LLU),\n\tQU(12710270651039129878LLU), QU(16118202956069604504LLU),\n\tQU(15010759372168680524LLU), QU( 2296827082251923948LLU),\n\tQU(10793729742623518101LLU), QU(13829764151845413046LLU),\n\tQU(17769301223184451213LLU), QU( 3118268169210783372LLU),\n\tQU(17626204544105123127LLU), QU( 7416718488974352644LLU),\n\tQU(10450751996212925994LLU), QU( 9352529519128770586LLU),\n\tQU(  259347569641110140LLU), QU( 8048588892269692697LLU),\n\tQU( 1774414152306494058LLU), QU(10669548347214355622LLU),\n\tQU(13061992253816795081LLU), QU(18432677803063861659LLU),\n\tQU( 8879191055593984333LLU), QU(12433753195199268041LLU),\n\tQU(14919392415439730602LLU), QU( 6612848378595332963LLU),\n\tQU( 6320986812036143628LLU), QU(10465592420226092859LLU),\n\tQU( 4196009278962570808LLU), QU( 3747816564473572224LLU),\n\tQU(17941203486133732898LLU), QU( 2350310037040505198LLU),\n\tQU( 5811779859134370113LLU), QU(10492109599506195126LLU),\n\tQU( 7699650690179541274LLU), QU( 1954338494306022961LLU),\n\tQU(14095816969027231152LLU), QU( 5841346919964852061LLU),\n\tQU(14945969510148214735LLU), QU( 3680200305887550992LLU),\n\tQU( 6218047466131695792LLU), QU( 8242165745175775096LLU),\n\tQU(11021371934053307357LLU), QU( 1265099502753169797LLU),\n\tQU( 4644347436111321718LLU), QU( 3609296916782832859LLU),\n\tQU( 8109807992218521571LLU), QU(18387884215648662020LLU),\n\tQU(14656324896296392902LLU), QU(17386819091238216751LLU),\n\tQU(17788300878582317152LLU), QU( 7919446259742399591LLU),\n\tQU( 4466613134576358004LLU), QU(12928181023667938509LLU),\n\tQU(13147446154454932030LLU), QU(16552129038252734620LLU),\n\tQU( 8395299403738822450LLU), QU(11313817655275361164LLU),\n\tQU(  434258809499511718LLU), QU( 2074882104954788676LLU),\n\tQU( 7929892178759395518LLU), QU( 9006461629105745388LLU),\n\tQU( 5176475650000323086LLU), QU(11128357033468341069LLU),\n\tQU(12026158851559118955LLU), QU(14699716249471156500LLU),\n\tQU(  448982497120206757LLU), QU( 4156475356685519900LLU),\n\tQU( 6063816103417215727LLU), QU(10073289387954971479LLU),\n\tQU( 8174466846138590962LLU), QU( 2675777452363449006LLU),\n\tQU( 9090685420572474281LLU), QU( 6659652652765562060LLU),\n\tQU(12923120304018106621LLU), QU(11117480560334526775LLU),\n\tQU(  937910473424587511LLU), QU( 1838692113502346645LLU),\n\tQU(11133914074648726180LLU), QU( 7922600945143884053LLU),\n\tQU(13435287702700959550LLU), QU( 5287964921251123332LLU),\n\tQU(11354875374575318947LLU), QU(17955724760748238133LLU),\n\tQU(13728617396297106512LLU), QU( 4107449660118101255LLU),\n\tQU( 1210269794886589623LLU), QU(11408687205733456282LLU),\n\tQU( 4538354710392677887LLU), QU(13566803319341319267LLU),\n\tQU(17870798107734050771LLU), QU( 3354318982568089135LLU),\n\tQU( 9034450839405133651LLU), QU(13087431795753424314LLU),\n\tQU(  950333102820688239LLU), QU( 1968360654535604116LLU),\n\tQU(16840551645563314995LLU), QU( 8867501803892924995LLU),\n\tQU(11395388644490626845LLU), QU( 1529815836300732204LLU),\n\tQU(13330848522996608842LLU), QU( 1813432878817504265LLU),\n\tQU( 2336867432693429560LLU), QU(15192805445973385902LLU),\n\tQU( 2528593071076407877LLU), QU(  128459777936689248LLU),\n\tQU( 9976345382867214866LLU), QU( 6208885766767996043LLU),\n\tQU(14982349522273141706LLU), QU( 3099654362410737822LLU),\n\tQU(13776700761947297661LLU), QU( 8806185470684925550LLU),\n\tQU( 8151717890410585321LLU), QU(  640860591588072925LLU),\n\tQU(14592096303937307465LLU), QU( 9056472419613564846LLU),\n\tQU(14861544647742266352LLU), QU(12703771500398470216LLU),\n\tQU( 3142372800384138465LLU), QU( 6201105606917248196LLU),\n\tQU(18337516409359270184LLU), QU(15042268695665115339LLU),\n\tQU(15188246541383283846LLU), QU(12800028693090114519LLU),\n\tQU( 5992859621101493472LLU), QU(18278043971816803521LLU),\n\tQU( 9002773075219424560LLU), QU( 7325707116943598353LLU),\n\tQU( 7930571931248040822LLU), QU( 5645275869617023448LLU),\n\tQU( 7266107455295958487LLU), QU( 4363664528273524411LLU),\n\tQU(14313875763787479809LLU), QU(17059695613553486802LLU),\n\tQU( 9247761425889940932LLU), QU(13704726459237593128LLU),\n\tQU( 2701312427328909832LLU), QU(17235532008287243115LLU),\n\tQU(14093147761491729538LLU), QU( 6247352273768386516LLU),\n\tQU( 8268710048153268415LLU), QU( 7985295214477182083LLU),\n\tQU(15624495190888896807LLU), QU( 3772753430045262788LLU),\n\tQU( 9133991620474991698LLU), QU( 5665791943316256028LLU),\n\tQU( 7551996832462193473LLU), QU(13163729206798953877LLU),\n\tQU( 9263532074153846374LLU), QU( 1015460703698618353LLU),\n\tQU(17929874696989519390LLU), QU(18257884721466153847LLU),\n\tQU(16271867543011222991LLU), QU( 3905971519021791941LLU),\n\tQU(16814488397137052085LLU), QU( 1321197685504621613LLU),\n\tQU( 2870359191894002181LLU), QU(14317282970323395450LLU),\n\tQU(13663920845511074366LLU), QU( 2052463995796539594LLU),\n\tQU(14126345686431444337LLU), QU( 1727572121947022534LLU),\n\tQU(17793552254485594241LLU), QU( 6738857418849205750LLU),\n\tQU( 1282987123157442952LLU), QU(16655480021581159251LLU),\n\tQU( 6784587032080183866LLU), QU(14726758805359965162LLU),\n\tQU( 7577995933961987349LLU), QU(12539609320311114036LLU),\n\tQU(10789773033385439494LLU), QU( 8517001497411158227LLU),\n\tQU(10075543932136339710LLU), QU(14838152340938811081LLU),\n\tQU( 9560840631794044194LLU), QU(17445736541454117475LLU),\n\tQU(10633026464336393186LLU), QU(15705729708242246293LLU),\n\tQU( 1117517596891411098LLU), QU( 4305657943415886942LLU),\n\tQU( 4948856840533979263LLU), QU(16071681989041789593LLU),\n\tQU(13723031429272486527LLU), QU( 7639567622306509462LLU),\n\tQU(12670424537483090390LLU), QU( 9715223453097197134LLU),\n\tQU( 5457173389992686394LLU), QU(  289857129276135145LLU),\n\tQU(17048610270521972512LLU), QU(  692768013309835485LLU),\n\tQU(14823232360546632057LLU), QU(18218002361317895936LLU),\n\tQU( 3281724260212650204LLU), QU(16453957266549513795LLU),\n\tQU( 8592711109774511881LLU), QU(  929825123473369579LLU),\n\tQU(15966784769764367791LLU), QU( 9627344291450607588LLU),\n\tQU(10849555504977813287LLU), QU( 9234566913936339275LLU),\n\tQU( 6413807690366911210LLU), QU(10862389016184219267LLU),\n\tQU(13842504799335374048LLU), QU( 1531994113376881174LLU),\n\tQU( 2081314867544364459LLU), QU(16430628791616959932LLU),\n\tQU( 8314714038654394368LLU), QU( 9155473892098431813LLU),\n\tQU(12577843786670475704LLU), QU( 4399161106452401017LLU),\n\tQU( 1668083091682623186LLU), QU( 1741383777203714216LLU),\n\tQU( 2162597285417794374LLU), QU(15841980159165218736LLU),\n\tQU( 1971354603551467079LLU), QU( 1206714764913205968LLU),\n\tQU( 4790860439591272330LLU), QU(14699375615594055799LLU),\n\tQU( 8374423871657449988LLU), QU(10950685736472937738LLU),\n\tQU(  697344331343267176LLU), QU(10084998763118059810LLU),\n\tQU(12897369539795983124LLU), QU(12351260292144383605LLU),\n\tQU( 1268810970176811234LLU), QU( 7406287800414582768LLU),\n\tQU(  516169557043807831LLU), QU( 5077568278710520380LLU),\n\tQU( 3828791738309039304LLU), QU( 7721974069946943610LLU),\n\tQU( 3534670260981096460LLU), QU( 4865792189600584891LLU),\n\tQU(16892578493734337298LLU), QU( 9161499464278042590LLU),\n\tQU(11976149624067055931LLU), QU(13219479887277343990LLU),\n\tQU(14161556738111500680LLU), QU(14670715255011223056LLU),\n\tQU( 4671205678403576558LLU), QU(12633022931454259781LLU),\n\tQU(14821376219869187646LLU), QU(  751181776484317028LLU),\n\tQU( 2192211308839047070LLU), QU(11787306362361245189LLU),\n\tQU(10672375120744095707LLU), QU( 4601972328345244467LLU),\n\tQU(15457217788831125879LLU), QU( 8464345256775460809LLU),\n\tQU(10191938789487159478LLU), QU( 6184348739615197613LLU),\n\tQU(11425436778806882100LLU), QU( 2739227089124319793LLU),\n\tQU(  461464518456000551LLU), QU( 4689850170029177442LLU),\n\tQU( 6120307814374078625LLU), QU(11153579230681708671LLU),\n\tQU( 7891721473905347926LLU), QU(10281646937824872400LLU),\n\tQU( 3026099648191332248LLU), QU( 8666750296953273818LLU),\n\tQU(14978499698844363232LLU), QU(13303395102890132065LLU),\n\tQU( 8182358205292864080LLU), QU(10560547713972971291LLU),\n\tQU(11981635489418959093LLU), QU( 3134621354935288409LLU),\n\tQU(11580681977404383968LLU), QU(14205530317404088650LLU),\n\tQU( 5997789011854923157LLU), QU(13659151593432238041LLU),\n\tQU(11664332114338865086LLU), QU( 7490351383220929386LLU),\n\tQU( 7189290499881530378LLU), QU(15039262734271020220LLU),\n\tQU( 2057217285976980055LLU), QU(  555570804905355739LLU),\n\tQU(11235311968348555110LLU), QU(13824557146269603217LLU),\n\tQU(16906788840653099693LLU), QU( 7222878245455661677LLU),\n\tQU( 5245139444332423756LLU), QU( 4723748462805674292LLU),\n\tQU(12216509815698568612LLU), QU(17402362976648951187LLU),\n\tQU(17389614836810366768LLU), QU( 4880936484146667711LLU),\n\tQU( 9085007839292639880LLU), QU(13837353458498535449LLU),\n\tQU(11914419854360366677LLU), QU(16595890135313864103LLU),\n\tQU( 6313969847197627222LLU), QU(18296909792163910431LLU),\n\tQU(10041780113382084042LLU), QU( 2499478551172884794LLU),\n\tQU(11057894246241189489LLU), QU( 9742243032389068555LLU),\n\tQU(12838934582673196228LLU), QU(13437023235248490367LLU),\n\tQU(13372420669446163240LLU), QU( 6752564244716909224LLU),\n\tQU( 7157333073400313737LLU), QU(12230281516370654308LLU),\n\tQU( 1182884552219419117LLU), QU( 2955125381312499218LLU),\n\tQU(10308827097079443249LLU), QU( 1337648572986534958LLU),\n\tQU(16378788590020343939LLU), QU(  108619126514420935LLU),\n\tQU( 3990981009621629188LLU), QU( 5460953070230946410LLU),\n\tQU( 9703328329366531883LLU), QU(13166631489188077236LLU),\n\tQU( 1104768831213675170LLU), QU( 3447930458553877908LLU),\n\tQU( 8067172487769945676LLU), QU( 5445802098190775347LLU),\n\tQU( 3244840981648973873LLU), QU(17314668322981950060LLU),\n\tQU( 5006812527827763807LLU), QU(18158695070225526260LLU),\n\tQU( 2824536478852417853LLU), QU(13974775809127519886LLU),\n\tQU( 9814362769074067392LLU), QU(17276205156374862128LLU),\n\tQU(11361680725379306967LLU), QU( 3422581970382012542LLU),\n\tQU(11003189603753241266LLU), QU(11194292945277862261LLU),\n\tQU( 6839623313908521348LLU), QU(11935326462707324634LLU),\n\tQU( 1611456788685878444LLU), QU(13112620989475558907LLU),\n\tQU(  517659108904450427LLU), QU(13558114318574407624LLU),\n\tQU(15699089742731633077LLU), QU( 4988979278862685458LLU),\n\tQU( 8111373583056521297LLU), QU( 3891258746615399627LLU),\n\tQU( 8137298251469718086LLU), QU(12748663295624701649LLU),\n\tQU( 4389835683495292062LLU), QU( 5775217872128831729LLU),\n\tQU( 9462091896405534927LLU), QU( 8498124108820263989LLU),\n\tQU( 8059131278842839525LLU), QU(10503167994254090892LLU),\n\tQU(11613153541070396656LLU), QU(18069248738504647790LLU),\n\tQU(  570657419109768508LLU), QU( 3950574167771159665LLU),\n\tQU( 5514655599604313077LLU), QU( 2908460854428484165LLU),\n\tQU(10777722615935663114LLU), QU(12007363304839279486LLU),\n\tQU( 9800646187569484767LLU), QU( 8795423564889864287LLU),\n\tQU(14257396680131028419LLU), QU( 6405465117315096498LLU),\n\tQU( 7939411072208774878LLU), QU(17577572378528990006LLU),\n\tQU(14785873806715994850LLU), QU(16770572680854747390LLU),\n\tQU(18127549474419396481LLU), QU(11637013449455757750LLU),\n\tQU(14371851933996761086LLU), QU( 3601181063650110280LLU),\n\tQU( 4126442845019316144LLU), QU(10198287239244320669LLU),\n\tQU(18000169628555379659LLU), QU(18392482400739978269LLU),\n\tQU( 6219919037686919957LLU), QU( 3610085377719446052LLU),\n\tQU( 2513925039981776336LLU), QU(16679413537926716955LLU),\n\tQU(12903302131714909434LLU), QU( 5581145789762985009LLU),\n\tQU(12325955044293303233LLU), QU(17216111180742141204LLU),\n\tQU( 6321919595276545740LLU), QU( 3507521147216174501LLU),\n\tQU( 9659194593319481840LLU), QU(11473976005975358326LLU),\n\tQU(14742730101435987026LLU), QU(  492845897709954780LLU),\n\tQU(16976371186162599676LLU), QU(17712703422837648655LLU),\n\tQU( 9881254778587061697LLU), QU( 8413223156302299551LLU),\n\tQU( 1563841828254089168LLU), QU( 9996032758786671975LLU),\n\tQU(  138877700583772667LLU), QU(13003043368574995989LLU),\n\tQU( 4390573668650456587LLU), QU( 8610287390568126755LLU),\n\tQU(15126904974266642199LLU), QU( 6703637238986057662LLU),\n\tQU( 2873075592956810157LLU), QU( 6035080933946049418LLU),\n\tQU(13382846581202353014LLU), QU( 7303971031814642463LLU),\n\tQU(18418024405307444267LLU), QU( 5847096731675404647LLU),\n\tQU( 4035880699639842500LLU), QU(11525348625112218478LLU),\n\tQU( 3041162365459574102LLU), QU( 2604734487727986558LLU),\n\tQU(15526341771636983145LLU), QU(14556052310697370254LLU),\n\tQU(12997787077930808155LLU), QU( 9601806501755554499LLU),\n\tQU(11349677952521423389LLU), QU(14956777807644899350LLU),\n\tQU(16559736957742852721LLU), QU(12360828274778140726LLU),\n\tQU( 6685373272009662513LLU), QU(16932258748055324130LLU),\n\tQU(15918051131954158508LLU), QU( 1692312913140790144LLU),\n\tQU(  546653826801637367LLU), QU( 5341587076045986652LLU),\n\tQU(14975057236342585662LLU), QU(12374976357340622412LLU),\n\tQU(10328833995181940552LLU), QU(12831807101710443149LLU),\n\tQU(10548514914382545716LLU), QU( 2217806727199715993LLU),\n\tQU(12627067369242845138LLU), QU( 4598965364035438158LLU),\n\tQU(  150923352751318171LLU), QU(14274109544442257283LLU),\n\tQU( 4696661475093863031LLU), QU( 1505764114384654516LLU),\n\tQU(10699185831891495147LLU), QU( 2392353847713620519LLU),\n\tQU( 3652870166711788383LLU), QU( 8640653276221911108LLU),\n\tQU( 3894077592275889704LLU), QU( 4918592872135964845LLU),\n\tQU(16379121273281400789LLU), QU(12058465483591683656LLU),\n\tQU(11250106829302924945LLU), QU( 1147537556296983005LLU),\n\tQU( 6376342756004613268LLU), QU(14967128191709280506LLU),\n\tQU(18007449949790627628LLU), QU( 9497178279316537841LLU),\n\tQU( 7920174844809394893LLU), QU(10037752595255719907LLU),\n\tQU(15875342784985217697LLU), QU(15311615921712850696LLU),\n\tQU( 9552902652110992950LLU), QU(14054979450099721140LLU),\n\tQU( 5998709773566417349LLU), QU(18027910339276320187LLU),\n\tQU( 8223099053868585554LLU), QU( 7842270354824999767LLU),\n\tQU( 4896315688770080292LLU), QU(12969320296569787895LLU),\n\tQU( 2674321489185759961LLU), QU( 4053615936864718439LLU),\n\tQU(11349775270588617578LLU), QU( 4743019256284553975LLU),\n\tQU( 5602100217469723769LLU), QU(14398995691411527813LLU),\n\tQU( 7412170493796825470LLU), QU(  836262406131744846LLU),\n\tQU( 8231086633845153022LLU), QU( 5161377920438552287LLU),\n\tQU( 8828731196169924949LLU), QU(16211142246465502680LLU),\n\tQU( 3307990879253687818LLU), QU( 5193405406899782022LLU),\n\tQU( 8510842117467566693LLU), QU( 6070955181022405365LLU),\n\tQU(14482950231361409799LLU), QU(12585159371331138077LLU),\n\tQU( 3511537678933588148LLU), QU( 2041849474531116417LLU),\n\tQU(10944936685095345792LLU), QU(18303116923079107729LLU),\n\tQU( 2720566371239725320LLU), QU( 4958672473562397622LLU),\n\tQU( 3032326668253243412LLU), QU(13689418691726908338LLU),\n\tQU( 1895205511728843996LLU), QU( 8146303515271990527LLU),\n\tQU(16507343500056113480LLU), QU(  473996939105902919LLU),\n\tQU( 9897686885246881481LLU), QU(14606433762712790575LLU),\n\tQU( 6732796251605566368LLU), QU( 1399778120855368916LLU),\n\tQU(  935023885182833777LLU), QU(16066282816186753477LLU),\n\tQU( 7291270991820612055LLU), QU(17530230393129853844LLU),\n\tQU(10223493623477451366LLU), QU(15841725630495676683LLU),\n\tQU(17379567246435515824LLU), QU( 8588251429375561971LLU),\n\tQU(18339511210887206423LLU), QU(17349587430725976100LLU),\n\tQU(12244876521394838088LLU), QU( 6382187714147161259LLU),\n\tQU(12335807181848950831LLU), QU(16948885622305460665LLU),\n\tQU(13755097796371520506LLU), QU(14806740373324947801LLU),\n\tQU( 4828699633859287703LLU), QU( 8209879281452301604LLU),\n\tQU(12435716669553736437LLU), QU(13970976859588452131LLU),\n\tQU( 6233960842566773148LLU), QU(12507096267900505759LLU),\n\tQU( 1198713114381279421LLU), QU(14989862731124149015LLU),\n\tQU(15932189508707978949LLU), QU( 2526406641432708722LLU),\n\tQU(   29187427817271982LLU), QU( 1499802773054556353LLU),\n\tQU(10816638187021897173LLU), QU( 5436139270839738132LLU),\n\tQU( 6659882287036010082LLU), QU( 2154048955317173697LLU),\n\tQU(10887317019333757642LLU), QU(16281091802634424955LLU),\n\tQU(10754549879915384901LLU), QU(10760611745769249815LLU),\n\tQU( 2161505946972504002LLU), QU( 5243132808986265107LLU),\n\tQU(10129852179873415416LLU), QU(  710339480008649081LLU),\n\tQU( 7802129453068808528LLU), QU(17967213567178907213LLU),\n\tQU(15730859124668605599LLU), QU(13058356168962376502LLU),\n\tQU( 3701224985413645909LLU), QU(14464065869149109264LLU),\n\tQU( 9959272418844311646LLU), QU(10157426099515958752LLU),\n\tQU(14013736814538268528LLU), QU(17797456992065653951LLU),\n\tQU(17418878140257344806LLU), QU(15457429073540561521LLU),\n\tQU( 2184426881360949378LLU), QU( 2062193041154712416LLU),\n\tQU( 8553463347406931661LLU), QU( 4913057625202871854LLU),\n\tQU( 2668943682126618425LLU), QU(17064444737891172288LLU),\n\tQU( 4997115903913298637LLU), QU(12019402608892327416LLU),\n\tQU(17603584559765897352LLU), QU(11367529582073647975LLU),\n\tQU( 8211476043518436050LLU), QU( 8676849804070323674LLU),\n\tQU(18431829230394475730LLU), QU(10490177861361247904LLU),\n\tQU( 9508720602025651349LLU), QU( 7409627448555722700LLU),\n\tQU( 5804047018862729008LLU), QU(11943858176893142594LLU),\n\tQU(11908095418933847092LLU), QU( 5415449345715887652LLU),\n\tQU( 1554022699166156407LLU), QU( 9073322106406017161LLU),\n\tQU( 7080630967969047082LLU), QU(18049736940860732943LLU),\n\tQU(12748714242594196794LLU), QU( 1226992415735156741LLU),\n\tQU(17900981019609531193LLU), QU(11720739744008710999LLU),\n\tQU( 3006400683394775434LLU), QU(11347974011751996028LLU),\n\tQU( 3316999628257954608LLU), QU( 8384484563557639101LLU),\n\tQU(18117794685961729767LLU), QU( 1900145025596618194LLU),\n\tQU(17459527840632892676LLU), QU( 5634784101865710994LLU),\n\tQU( 7918619300292897158LLU), QU( 3146577625026301350LLU),\n\tQU( 9955212856499068767LLU), QU( 1873995843681746975LLU),\n\tQU( 1561487759967972194LLU), QU( 8322718804375878474LLU),\n\tQU(11300284215327028366LLU), QU( 4667391032508998982LLU),\n\tQU( 9820104494306625580LLU), QU(17922397968599970610LLU),\n\tQU( 1784690461886786712LLU), QU(14940365084341346821LLU),\n\tQU( 5348719575594186181LLU), QU(10720419084507855261LLU),\n\tQU(14210394354145143274LLU), QU( 2426468692164000131LLU),\n\tQU(16271062114607059202LLU), QU(14851904092357070247LLU),\n\tQU( 6524493015693121897LLU), QU( 9825473835127138531LLU),\n\tQU(14222500616268569578LLU), QU(15521484052007487468LLU),\n\tQU(14462579404124614699LLU), QU(11012375590820665520LLU),\n\tQU(11625327350536084927LLU), QU(14452017765243785417LLU),\n\tQU( 9989342263518766305LLU), QU( 3640105471101803790LLU),\n\tQU( 4749866455897513242LLU), QU(13963064946736312044LLU),\n\tQU(10007416591973223791LLU), QU(18314132234717431115LLU),\n\tQU( 3286596588617483450LLU), QU( 7726163455370818765LLU),\n\tQU( 7575454721115379328LLU), QU( 5308331576437663422LLU),\n\tQU(18288821894903530934LLU), QU( 8028405805410554106LLU),\n\tQU(15744019832103296628LLU), QU(  149765559630932100LLU),\n\tQU( 6137705557200071977LLU), QU(14513416315434803615LLU),\n\tQU(11665702820128984473LLU), QU(  218926670505601386LLU),\n\tQU( 6868675028717769519LLU), QU(15282016569441512302LLU),\n\tQU( 5707000497782960236LLU), QU( 6671120586555079567LLU),\n\tQU( 2194098052618985448LLU), QU(16849577895477330978LLU),\n\tQU(12957148471017466283LLU), QU( 1997805535404859393LLU),\n\tQU( 1180721060263860490LLU), QU(13206391310193756958LLU),\n\tQU(12980208674461861797LLU), QU( 3825967775058875366LLU),\n\tQU(17543433670782042631LLU), QU( 1518339070120322730LLU),\n\tQU(16344584340890991669LLU), QU( 2611327165318529819LLU),\n\tQU(11265022723283422529LLU), QU( 4001552800373196817LLU),\n\tQU(14509595890079346161LLU), QU( 3528717165416234562LLU),\n\tQU(18153222571501914072LLU), QU( 9387182977209744425LLU),\n\tQU(10064342315985580021LLU), QU(11373678413215253977LLU),\n\tQU( 2308457853228798099LLU), QU( 9729042942839545302LLU),\n\tQU( 7833785471140127746LLU), QU( 6351049900319844436LLU),\n\tQU(14454610627133496067LLU), QU(12533175683634819111LLU),\n\tQU(15570163926716513029LLU), QU(13356980519185762498LLU)\n};\n\nTEST_BEGIN(test_gen_rand_32)\n{\n\tuint32_t array32[BLOCK_SIZE] JEMALLOC_ATTR(aligned(16));\n\tuint32_t array32_2[BLOCK_SIZE] JEMALLOC_ATTR(aligned(16));\n\tint i;\n\tuint32_t r32;\n\tsfmt_t *ctx;\n\n\tassert_d_le(get_min_array_size32(), BLOCK_SIZE,\n\t    \"Array size too small\");\n\tctx = init_gen_rand(1234);\n\tfill_array32(ctx, array32, BLOCK_SIZE);\n\tfill_array32(ctx, array32_2, BLOCK_SIZE);\n\tfini_gen_rand(ctx);\n\n\tctx = init_gen_rand(1234);\n\tfor (i = 0; i < BLOCK_SIZE; i++) {\n\t\tif (i < COUNT_1) {\n\t\t\tassert_u32_eq(array32[i], init_gen_rand_32_expected[i],\n\t\t\t    \"Output mismatch for i=%d\", i);\n\t\t}\n\t\tr32 = gen_rand32(ctx);\n\t\tassert_u32_eq(r32, array32[i],\n\t\t    \"Mismatch at array32[%d]=%x, gen=%x\", i, array32[i], r32);\n\t}\n\tfor (i = 0; i < COUNT_2; i++) {\n\t\tr32 = gen_rand32(ctx);\n\t\tassert_u32_eq(r32, array32_2[i],\n\t\t    \"Mismatch at array32_2[%d]=%x, gen=%x\", i, array32_2[i],\n\t\t    r32);\n\t}\n\tfini_gen_rand(ctx);\n}\nTEST_END\n\nTEST_BEGIN(test_by_array_32)\n{\n\tuint32_t array32[BLOCK_SIZE] JEMALLOC_ATTR(aligned(16));\n\tuint32_t array32_2[BLOCK_SIZE] JEMALLOC_ATTR(aligned(16));\n\tint i;\n\tuint32_t ini[4] = {0x1234, 0x5678, 0x9abc, 0xdef0};\n\tuint32_t r32;\n\tsfmt_t *ctx;\n\n\tassert_d_le(get_min_array_size32(), BLOCK_SIZE,\n\t    \"Array size too small\");\n\tctx = init_by_array(ini, 4);\n\tfill_array32(ctx, array32, BLOCK_SIZE);\n\tfill_array32(ctx, array32_2, BLOCK_SIZE);\n\tfini_gen_rand(ctx);\n\n\tctx = init_by_array(ini, 4);\n\tfor (i = 0; i < BLOCK_SIZE; i++) {\n\t\tif (i < COUNT_1) {\n\t\t\tassert_u32_eq(array32[i], init_by_array_32_expected[i],\n\t\t\t    \"Output mismatch for i=%d\", i);\n\t\t}\n\t\tr32 = gen_rand32(ctx);\n\t\tassert_u32_eq(r32, array32[i],\n\t\t    \"Mismatch at array32[%d]=%x, gen=%x\", i, array32[i], r32);\n\t}\n\tfor (i = 0; i < COUNT_2; i++) {\n\t\tr32 = gen_rand32(ctx);\n\t\tassert_u32_eq(r32, array32_2[i],\n\t\t    \"Mismatch at array32_2[%d]=%x, gen=%x\", i, array32_2[i],\n\t\t    r32);\n\t}\n\tfini_gen_rand(ctx);\n}\nTEST_END\n\nTEST_BEGIN(test_gen_rand_64)\n{\n\tuint64_t array64[BLOCK_SIZE64] JEMALLOC_ATTR(aligned(16));\n\tuint64_t array64_2[BLOCK_SIZE64] JEMALLOC_ATTR(aligned(16));\n\tint i;\n\tuint64_t r;\n\tsfmt_t *ctx;\n\n\tassert_d_le(get_min_array_size64(), BLOCK_SIZE64,\n\t    \"Array size too small\");\n\tctx = init_gen_rand(4321);\n\tfill_array64(ctx, array64, BLOCK_SIZE64);\n\tfill_array64(ctx, array64_2, BLOCK_SIZE64);\n\tfini_gen_rand(ctx);\n\n\tctx = init_gen_rand(4321);\n\tfor (i = 0; i < BLOCK_SIZE64; i++) {\n\t\tif (i < COUNT_1) {\n\t\t\tassert_u64_eq(array64[i], init_gen_rand_64_expected[i],\n\t\t\t    \"Output mismatch for i=%d\", i);\n\t\t}\n\t\tr = gen_rand64(ctx);\n\t\tassert_u64_eq(r, array64[i],\n\t\t    \"Mismatch at array64[%d]=%\"PRIx64\", gen=%\"PRIx64, i,\n\t\t    array64[i], r);\n\t}\n\tfor (i = 0; i < COUNT_2; i++) {\n\t\tr = gen_rand64(ctx);\n\t\tassert_u64_eq(r, array64_2[i],\n\t\t    \"Mismatch at array64_2[%d]=%\"PRIx64\" gen=%\"PRIx64\"\", i,\n\t\t    array64_2[i], r);\n\t}\n\tfini_gen_rand(ctx);\n}\nTEST_END\n\nTEST_BEGIN(test_by_array_64)\n{\n\tuint64_t array64[BLOCK_SIZE64] JEMALLOC_ATTR(aligned(16));\n\tuint64_t array64_2[BLOCK_SIZE64] JEMALLOC_ATTR(aligned(16));\n\tint i;\n\tuint64_t r;\n\tuint32_t ini[] = {5, 4, 3, 2, 1};\n\tsfmt_t *ctx;\n\n\tassert_d_le(get_min_array_size64(), BLOCK_SIZE64,\n\t    \"Array size too small\");\n\tctx = init_by_array(ini, 5);\n\tfill_array64(ctx, array64, BLOCK_SIZE64);\n\tfill_array64(ctx, array64_2, BLOCK_SIZE64);\n\tfini_gen_rand(ctx);\n\n\tctx = init_by_array(ini, 5);\n\tfor (i = 0; i < BLOCK_SIZE64; i++) {\n\t\tif (i < COUNT_1) {\n\t\t\tassert_u64_eq(array64[i], init_by_array_64_expected[i],\n\t\t\t    \"Output mismatch for i=%d\", i);\n\t\t}\n\t\tr = gen_rand64(ctx);\n\t\tassert_u64_eq(r, array64[i],\n\t\t    \"Mismatch at array64[%d]=%\"PRIx64\" gen=%\"PRIx64, i,\n\t\t    array64[i], r);\n\t}\n\tfor (i = 0; i < COUNT_2; i++) {\n\t\tr = gen_rand64(ctx);\n\t\tassert_u64_eq(r, array64_2[i],\n\t\t    \"Mismatch at array64_2[%d]=%\"PRIx64\" gen=%\"PRIx64, i,\n\t\t    array64_2[i], r);\n\t}\n\tfini_gen_rand(ctx);\n}\nTEST_END\n\nint\nmain(void)\n{\n\n\treturn (test(\n\t    test_gen_rand_32,\n\t    test_by_array_32,\n\t    test_gen_rand_64,\n\t    test_by_array_64));\n}\n"
  },
  {
    "path": "extern/deprecated/redis-2.8.21/deps/jemalloc/test/unit/bitmap.c",
    "content": "#include \"test/jemalloc_test.h\"\n\n#if (LG_BITMAP_MAXBITS > 12)\n#  define MAXBITS\t4500\n#else\n#  define MAXBITS\t(1U << LG_BITMAP_MAXBITS)\n#endif\n\nTEST_BEGIN(test_bitmap_size)\n{\n\tsize_t i, prev_size;\n\n\tprev_size = 0;\n\tfor (i = 1; i <= MAXBITS; i++) {\n\t\tsize_t size = bitmap_size(i);\n\t\tassert_true(size >= prev_size,\n\t\t    \"Bitmap size is smaller than expected\");\n\t\tprev_size = size;\n\t}\n}\nTEST_END\n\nTEST_BEGIN(test_bitmap_init)\n{\n\tsize_t i;\n\n\tfor (i = 1; i <= MAXBITS; i++) {\n\t\tbitmap_info_t binfo;\n\t\tbitmap_info_init(&binfo, i);\n\t\t{\n\t\t\tsize_t j;\n\t\t\tbitmap_t *bitmap = malloc(sizeof(bitmap_t) *\n\t\t\t\tbitmap_info_ngroups(&binfo));\n\t\t\tbitmap_init(bitmap, &binfo);\n\n\t\t\tfor (j = 0; j < i; j++) {\n\t\t\t\tassert_false(bitmap_get(bitmap, &binfo, j),\n\t\t\t\t    \"Bit should be unset\");\n\t\t\t}\n\t\t\tfree(bitmap);\n\t\t}\n\t}\n}\nTEST_END\n\nTEST_BEGIN(test_bitmap_set)\n{\n\tsize_t i;\n\n\tfor (i = 1; i <= MAXBITS; i++) {\n\t\tbitmap_info_t binfo;\n\t\tbitmap_info_init(&binfo, i);\n\t\t{\n\t\t\tsize_t j;\n\t\t\tbitmap_t *bitmap = malloc(sizeof(bitmap_t) *\n\t\t\t\tbitmap_info_ngroups(&binfo));\n\t\t\tbitmap_init(bitmap, &binfo);\n\n\t\t\tfor (j = 0; j < i; j++)\n\t\t\t\tbitmap_set(bitmap, &binfo, j);\n\t\t\tassert_true(bitmap_full(bitmap, &binfo),\n\t\t\t    \"All bits should be set\");\n\t\t\tfree(bitmap);\n\t\t}\n\t}\n}\nTEST_END\n\nTEST_BEGIN(test_bitmap_unset)\n{\n\tsize_t i;\n\n\tfor (i = 1; i <= MAXBITS; i++) {\n\t\tbitmap_info_t binfo;\n\t\tbitmap_info_init(&binfo, i);\n\t\t{\n\t\t\tsize_t j;\n\t\t\tbitmap_t *bitmap = malloc(sizeof(bitmap_t) *\n\t\t\t\tbitmap_info_ngroups(&binfo));\n\t\t\tbitmap_init(bitmap, &binfo);\n\n\t\t\tfor (j = 0; j < i; j++)\n\t\t\t\tbitmap_set(bitmap, &binfo, j);\n\t\t\tassert_true(bitmap_full(bitmap, &binfo),\n\t\t\t    \"All bits should be set\");\n\t\t\tfor (j = 0; j < i; j++)\n\t\t\t\tbitmap_unset(bitmap, &binfo, j);\n\t\t\tfor (j = 0; j < i; j++)\n\t\t\t\tbitmap_set(bitmap, &binfo, j);\n\t\t\tassert_true(bitmap_full(bitmap, &binfo),\n\t\t\t    \"All bits should be set\");\n\t\t\tfree(bitmap);\n\t\t}\n\t}\n}\nTEST_END\n\nTEST_BEGIN(test_bitmap_sfu)\n{\n\tsize_t i;\n\n\tfor (i = 1; i <= MAXBITS; i++) {\n\t\tbitmap_info_t binfo;\n\t\tbitmap_info_init(&binfo, i);\n\t\t{\n\t\t\tssize_t j;\n\t\t\tbitmap_t *bitmap = malloc(sizeof(bitmap_t) *\n\t\t\t\tbitmap_info_ngroups(&binfo));\n\t\t\tbitmap_init(bitmap, &binfo);\n\n\t\t\t/* Iteratively set bits starting at the beginning. */\n\t\t\tfor (j = 0; j < i; j++) {\n\t\t\t\tassert_zd_eq(bitmap_sfu(bitmap, &binfo), j,\n\t\t\t\t    \"First unset bit should be just after \"\n\t\t\t\t    \"previous first unset bit\");\n\t\t\t}\n\t\t\tassert_true(bitmap_full(bitmap, &binfo),\n\t\t\t    \"All bits should be set\");\n\n\t\t\t/*\n\t\t\t * Iteratively unset bits starting at the end, and\n\t\t\t * verify that bitmap_sfu() reaches the unset bits.\n\t\t\t */\n\t\t\tfor (j = i - 1; j >= 0; j--) {\n\t\t\t\tbitmap_unset(bitmap, &binfo, j);\n\t\t\t\tassert_zd_eq(bitmap_sfu(bitmap, &binfo), j,\n\t\t\t\t    \"First unset bit should the bit previously \"\n\t\t\t\t    \"unset\");\n\t\t\t\tbitmap_unset(bitmap, &binfo, j);\n\t\t\t}\n\t\t\tassert_false(bitmap_get(bitmap, &binfo, 0),\n\t\t\t    \"Bit should be unset\");\n\n\t\t\t/*\n\t\t\t * Iteratively set bits starting at the beginning, and\n\t\t\t * verify that bitmap_sfu() looks past them.\n\t\t\t */\n\t\t\tfor (j = 1; j < i; j++) {\n\t\t\t\tbitmap_set(bitmap, &binfo, j - 1);\n\t\t\t\tassert_zd_eq(bitmap_sfu(bitmap, &binfo), j,\n\t\t\t\t    \"First unset bit should be just after the \"\n\t\t\t\t    \"bit previously set\");\n\t\t\t\tbitmap_unset(bitmap, &binfo, j);\n\t\t\t}\n\t\t\tassert_zd_eq(bitmap_sfu(bitmap, &binfo), i - 1,\n\t\t\t    \"First unset bit should be the last bit\");\n\t\t\tassert_true(bitmap_full(bitmap, &binfo),\n\t\t\t    \"All bits should be set\");\n\t\t\tfree(bitmap);\n\t\t}\n\t}\n}\nTEST_END\n\nint\nmain(void)\n{\n\n\treturn (test(\n\t    test_bitmap_size,\n\t    test_bitmap_init,\n\t    test_bitmap_set,\n\t    test_bitmap_unset,\n\t    test_bitmap_sfu));\n}\n"
  },
  {
    "path": "extern/deprecated/redis-2.8.21/deps/jemalloc/test/unit/ckh.c",
    "content": "#include \"test/jemalloc_test.h\"\n\nTEST_BEGIN(test_new_delete)\n{\n\tckh_t ckh;\n\n\tassert_false(ckh_new(&ckh, 2, ckh_string_hash, ckh_string_keycomp),\n\t    \"Unexpected ckh_new() error\");\n\tckh_delete(&ckh);\n\n\tassert_false(ckh_new(&ckh, 3, ckh_pointer_hash, ckh_pointer_keycomp),\n\t    \"Unexpected ckh_new() error\");\n\tckh_delete(&ckh);\n}\nTEST_END\n\nTEST_BEGIN(test_count_insert_search_remove)\n{\n\tckh_t ckh;\n\tconst char *strs[] = {\n\t    \"a string\",\n\t    \"A string\",\n\t    \"a string.\",\n\t    \"A string.\"\n\t};\n\tconst char *missing = \"A string not in the hash table.\";\n\tsize_t i;\n\n\tassert_false(ckh_new(&ckh, 2, ckh_string_hash, ckh_string_keycomp),\n\t    \"Unexpected ckh_new() error\");\n\tassert_zu_eq(ckh_count(&ckh), 0,\n\t    \"ckh_count() should return %zu, but it returned %zu\", ZU(0),\n\t    ckh_count(&ckh));\n\n\t/* Insert. */\n\tfor (i = 0; i < sizeof(strs)/sizeof(const char *); i++) {\n\t\tckh_insert(&ckh, strs[i], strs[i]);\n\t\tassert_zu_eq(ckh_count(&ckh), i+1,\n\t\t    \"ckh_count() should return %zu, but it returned %zu\", i+1,\n\t\t    ckh_count(&ckh));\n\t}\n\n\t/* Search. */\n\tfor (i = 0; i < sizeof(strs)/sizeof(const char *); i++) {\n\t\tunion {\n\t\t\tvoid *p;\n\t\t\tconst char *s;\n\t\t} k, v;\n\t\tvoid **kp, **vp;\n\t\tconst char *ks, *vs;\n\n\t\tkp = (i & 1) ? &k.p : NULL;\n\t\tvp = (i & 2) ? &v.p : NULL;\n\t\tk.p = NULL;\n\t\tv.p = NULL;\n\t\tassert_false(ckh_search(&ckh, strs[i], kp, vp),\n\t\t    \"Unexpected ckh_search() error\");\n\n\t\tks = (i & 1) ? strs[i] : (const char *)NULL;\n\t\tvs = (i & 2) ? strs[i] : (const char *)NULL;\n\t\tassert_ptr_eq((void *)ks, (void *)k.s,\n\t\t    \"Key mismatch, i=%zu\", i);\n\t\tassert_ptr_eq((void *)vs, (void *)v.s,\n\t\t    \"Value mismatch, i=%zu\", i);\n\t}\n\tassert_true(ckh_search(&ckh, missing, NULL, NULL),\n\t    \"Unexpected ckh_search() success\");\n\n\t/* Remove. */\n\tfor (i = 0; i < sizeof(strs)/sizeof(const char *); i++) {\n\t\tunion {\n\t\t\tvoid *p;\n\t\t\tconst char *s;\n\t\t} k, v;\n\t\tvoid **kp, **vp;\n\t\tconst char *ks, *vs;\n\n\t\tkp = (i & 1) ? &k.p : NULL;\n\t\tvp = (i & 2) ? &v.p : NULL;\n\t\tk.p = NULL;\n\t\tv.p = NULL;\n\t\tassert_false(ckh_remove(&ckh, strs[i], kp, vp),\n\t\t    \"Unexpected ckh_remove() error\");\n\n\t\tks = (i & 1) ? strs[i] : (const char *)NULL;\n\t\tvs = (i & 2) ? strs[i] : (const char *)NULL;\n\t\tassert_ptr_eq((void *)ks, (void *)k.s,\n\t\t    \"Key mismatch, i=%zu\", i);\n\t\tassert_ptr_eq((void *)vs, (void *)v.s,\n\t\t    \"Value mismatch, i=%zu\", i);\n\t\tassert_zu_eq(ckh_count(&ckh),\n\t\t    sizeof(strs)/sizeof(const char *) - i - 1,\n\t\t    \"ckh_count() should return %zu, but it returned %zu\",\n\t\t    sizeof(strs)/sizeof(const char *) - i - 1,\n\t\t    ckh_count(&ckh));\n\t}\n\n\tckh_delete(&ckh);\n}\nTEST_END\n\nTEST_BEGIN(test_insert_iter_remove)\n{\n#define\tNITEMS ZU(1000)\n\tckh_t ckh;\n\tvoid **p[NITEMS];\n\tvoid *q, *r;\n\tsize_t i;\n\n\tassert_false(ckh_new(&ckh, 2, ckh_pointer_hash, ckh_pointer_keycomp),\n\t    \"Unexpected ckh_new() error\");\n\n\tfor (i = 0; i < NITEMS; i++) {\n\t\tp[i] = mallocx(i+1, 0);\n\t\tassert_ptr_not_null(p[i], \"Unexpected mallocx() failure\");\n\t}\n\n\tfor (i = 0; i < NITEMS; i++) {\n\t\tsize_t j;\n\n\t\tfor (j = i; j < NITEMS; j++) {\n\t\t\tassert_false(ckh_insert(&ckh, p[j], p[j]),\n\t\t\t    \"Unexpected ckh_insert() failure\");\n\t\t\tassert_false(ckh_search(&ckh, p[j], &q, &r),\n\t\t\t    \"Unexpected ckh_search() failure\");\n\t\t\tassert_ptr_eq(p[j], q, \"Key pointer mismatch\");\n\t\t\tassert_ptr_eq(p[j], r, \"Value pointer mismatch\");\n\t\t}\n\n\t\tassert_zu_eq(ckh_count(&ckh), NITEMS,\n\t\t    \"ckh_count() should return %zu, but it returned %zu\",\n\t\t    NITEMS, ckh_count(&ckh));\n\n\t\tfor (j = i + 1; j < NITEMS; j++) {\n\t\t\tassert_false(ckh_search(&ckh, p[j], NULL, NULL),\n\t\t\t    \"Unexpected ckh_search() failure\");\n\t\t\tassert_false(ckh_remove(&ckh, p[j], &q, &r),\n\t\t\t    \"Unexpected ckh_remove() failure\");\n\t\t\tassert_ptr_eq(p[j], q, \"Key pointer mismatch\");\n\t\t\tassert_ptr_eq(p[j], r, \"Value pointer mismatch\");\n\t\t\tassert_true(ckh_search(&ckh, p[j], NULL, NULL),\n\t\t\t    \"Unexpected ckh_search() success\");\n\t\t\tassert_true(ckh_remove(&ckh, p[j], &q, &r),\n\t\t\t    \"Unexpected ckh_remove() success\");\n\t\t}\n\n\t\t{\n\t\t\tbool seen[NITEMS];\n\t\t\tsize_t tabind;\n\n\t\t\tmemset(seen, 0, sizeof(seen));\n\n\t\t\tfor (tabind = 0; ckh_iter(&ckh, &tabind, &q, &r) ==\n\t\t\t    false;) {\n\t\t\t\tsize_t k;\n\n\t\t\t\tassert_ptr_eq(q, r, \"Key and val not equal\");\n\n\t\t\t\tfor (k = 0; k < NITEMS; k++) {\n\t\t\t\t\tif (p[k] == q) {\n\t\t\t\t\t\tassert_false(seen[k],\n\t\t\t\t\t\t    \"Item %zu already seen\", k);\n\t\t\t\t\t\tseen[k] = true;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tfor (j = 0; j < i + 1; j++)\n\t\t\t\tassert_true(seen[j], \"Item %zu not seen\", j);\n\t\t\tfor (; j < NITEMS; j++)\n\t\t\t\tassert_false(seen[j], \"Item %zu seen\", j);\n\t\t}\n\t}\n\n\tfor (i = 0; i < NITEMS; i++) {\n\t\tassert_false(ckh_search(&ckh, p[i], NULL, NULL),\n\t\t    \"Unexpected ckh_search() failure\");\n\t\tassert_false(ckh_remove(&ckh, p[i], &q, &r),\n\t\t    \"Unexpected ckh_remove() failure\");\n\t\tassert_ptr_eq(p[i], q, \"Key pointer mismatch\");\n\t\tassert_ptr_eq(p[i], r, \"Value pointer mismatch\");\n\t\tassert_true(ckh_search(&ckh, p[i], NULL, NULL),\n\t\t    \"Unexpected ckh_search() success\");\n\t\tassert_true(ckh_remove(&ckh, p[i], &q, &r),\n\t\t    \"Unexpected ckh_remove() success\");\n\t\tdallocx(p[i], 0);\n\t}\n\n\tassert_zu_eq(ckh_count(&ckh), 0,\n\t    \"ckh_count() should return %zu, but it returned %zu\", ZU(0),\n\t    ckh_count(&ckh));\n\tckh_delete(&ckh);\n#undef NITEMS\n}\nTEST_END\n\nint\nmain(void)\n{\n\n\treturn (test(\n\t    test_new_delete,\n\t    test_count_insert_search_remove,\n\t    test_insert_iter_remove));\n}\n"
  },
  {
    "path": "extern/deprecated/redis-2.8.21/deps/jemalloc/test/unit/hash.c",
    "content": "/*\n * This file is based on code that is part of SMHasher\n * (https://code.google.com/p/smhasher/), and is subject to the MIT license\n * (http://www.opensource.org/licenses/mit-license.php).  Both email addresses\n * associated with the source code's revision history belong to Austin Appleby,\n * and the revision history ranges from 2010 to 2012.  Therefore the copyright\n * and license are here taken to be:\n *\n * Copyright (c) 2010-2012 Austin Appleby\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n\n#include \"test/jemalloc_test.h\"\n\ntypedef enum {\n\thash_variant_x86_32,\n\thash_variant_x86_128,\n\thash_variant_x64_128\n} hash_variant_t;\n\nstatic size_t\nhash_variant_bits(hash_variant_t variant)\n{\n\n\tswitch (variant) {\n\tcase hash_variant_x86_32: return (32);\n\tcase hash_variant_x86_128: return (128);\n\tcase hash_variant_x64_128: return (128);\n\tdefault: not_reached();\n\t}\n}\n\nstatic const char *\nhash_variant_string(hash_variant_t variant)\n{\n\n\tswitch (variant) {\n\tcase hash_variant_x86_32: return (\"hash_x86_32\");\n\tcase hash_variant_x86_128: return (\"hash_x86_128\");\n\tcase hash_variant_x64_128: return (\"hash_x64_128\");\n\tdefault: not_reached();\n\t}\n}\n\nstatic void\nhash_variant_verify(hash_variant_t variant)\n{\n\tconst size_t hashbytes = hash_variant_bits(variant) / 8;\n\tuint8_t key[256];\n\tuint8_t hashes[hashbytes * 256];\n\tuint8_t final[hashbytes];\n\tunsigned i;\n\tuint32_t computed, expected;\n\n\tmemset(key, 0, sizeof(key));\n\tmemset(hashes, 0, sizeof(hashes));\n\tmemset(final, 0, sizeof(final));\n\n\t/*\n\t * Hash keys of the form {0}, {0,1}, {0,1,2}, ..., {0,1,...,255} as the\n\t * seed.\n\t */\n\tfor (i = 0; i < 256; i++) {\n\t\tkey[i] = (uint8_t)i;\n\t\tswitch (variant) {\n\t\tcase hash_variant_x86_32: {\n\t\t\tuint32_t out;\n\t\t\tout = hash_x86_32(key, i, 256-i);\n\t\t\tmemcpy(&hashes[i*hashbytes], &out, hashbytes);\n\t\t\tbreak;\n\t\t} case hash_variant_x86_128: {\n\t\t\tuint64_t out[2];\n\t\t\thash_x86_128(key, i, 256-i, out);\n\t\t\tmemcpy(&hashes[i*hashbytes], out, hashbytes);\n\t\t\tbreak;\n\t\t} case hash_variant_x64_128: {\n\t\t\tuint64_t out[2];\n\t\t\thash_x64_128(key, i, 256-i, out);\n\t\t\tmemcpy(&hashes[i*hashbytes], out, hashbytes);\n\t\t\tbreak;\n\t\t} default: not_reached();\n\t\t}\n\t}\n\n\t/* Hash the result array. */\n\tswitch (variant) {\n\tcase hash_variant_x86_32: {\n\t\tuint32_t out = hash_x86_32(hashes, hashbytes*256, 0);\n\t\tmemcpy(final, &out, sizeof(out));\n\t\tbreak;\n\t} case hash_variant_x86_128: {\n\t\tuint64_t out[2];\n\t\thash_x86_128(hashes, hashbytes*256, 0, out);\n\t\tmemcpy(final, out, sizeof(out));\n\t\tbreak;\n\t} case hash_variant_x64_128: {\n\t\tuint64_t out[2];\n\t\thash_x64_128(hashes, hashbytes*256, 0, out);\n\t\tmemcpy(final, out, sizeof(out));\n\t\tbreak;\n\t} default: not_reached();\n\t}\n\n\tcomputed = (final[0] << 0) | (final[1] << 8) | (final[2] << 16) |\n\t    (final[3] << 24);\n\n\tswitch (variant) {\n#ifdef JEMALLOC_BIG_ENDIAN\n\tcase hash_variant_x86_32: expected = 0x6213303eU; break;\n\tcase hash_variant_x86_128: expected = 0x266820caU; break;\n\tcase hash_variant_x64_128: expected = 0xcc622b6fU; break;\n#else\n\tcase hash_variant_x86_32: expected = 0xb0f57ee3U; break;\n\tcase hash_variant_x86_128: expected = 0xb3ece62aU; break;\n\tcase hash_variant_x64_128: expected = 0x6384ba69U; break;\n#endif\n\tdefault: not_reached();\n\t}\n\n\tassert_u32_eq(computed, expected,\n\t    \"Hash mismatch for %s(): expected %#x but got %#x\",\n\t    hash_variant_string(variant), expected, computed);\n}\n\nTEST_BEGIN(test_hash_x86_32)\n{\n\n\thash_variant_verify(hash_variant_x86_32);\n}\nTEST_END\n\nTEST_BEGIN(test_hash_x86_128)\n{\n\n\thash_variant_verify(hash_variant_x86_128);\n}\nTEST_END\n\nTEST_BEGIN(test_hash_x64_128)\n{\n\n\thash_variant_verify(hash_variant_x64_128);\n}\nTEST_END\n\nint\nmain(void)\n{\n\n\treturn (test(\n\t    test_hash_x86_32,\n\t    test_hash_x86_128,\n\t    test_hash_x64_128));\n}\n"
  },
  {
    "path": "extern/deprecated/redis-2.8.21/deps/jemalloc/test/unit/junk.c",
    "content": "#include \"test/jemalloc_test.h\"\n\n#ifdef JEMALLOC_FILL\nconst char *malloc_conf =\n    \"abort:false,junk:true,zero:false,redzone:true,quarantine:0\";\n#endif\n\nstatic arena_dalloc_junk_small_t *arena_dalloc_junk_small_orig;\nstatic arena_dalloc_junk_large_t *arena_dalloc_junk_large_orig;\nstatic huge_dalloc_junk_t *huge_dalloc_junk_orig;\nstatic void *most_recently_junked;\n\nstatic void\narena_dalloc_junk_small_intercept(void *ptr, arena_bin_info_t *bin_info)\n{\n\tsize_t i;\n\n\tarena_dalloc_junk_small_orig(ptr, bin_info);\n\tfor (i = 0; i < bin_info->reg_size; i++) {\n\t\tassert_c_eq(((char *)ptr)[i], 0x5a,\n\t\t    \"Missing junk fill for byte %zu/%zu of deallocated region\",\n\t\t    i, bin_info->reg_size);\n\t}\n\tmost_recently_junked = ptr;\n}\n\nstatic void\narena_dalloc_junk_large_intercept(void *ptr, size_t usize)\n{\n\tsize_t i;\n\n\tarena_dalloc_junk_large_orig(ptr, usize);\n\tfor (i = 0; i < usize; i++) {\n\t\tassert_c_eq(((char *)ptr)[i], 0x5a,\n\t\t    \"Missing junk fill for byte %zu/%zu of deallocated region\",\n\t\t    i, usize);\n\t}\n\tmost_recently_junked = ptr;\n}\n\nstatic void\nhuge_dalloc_junk_intercept(void *ptr, size_t usize)\n{\n\n\thuge_dalloc_junk_orig(ptr, usize);\n\t/*\n\t * The conditions under which junk filling actually occurs are nuanced\n\t * enough that it doesn't make sense to duplicate the decision logic in\n\t * test code, so don't actually check that the region is junk-filled.\n\t */\n\tmost_recently_junked = ptr;\n}\n\nstatic void\ntest_junk(size_t sz_min, size_t sz_max)\n{\n\tchar *s;\n\tsize_t sz_prev, sz, i;\n\n\tarena_dalloc_junk_small_orig = arena_dalloc_junk_small;\n\tarena_dalloc_junk_small = arena_dalloc_junk_small_intercept;\n\tarena_dalloc_junk_large_orig = arena_dalloc_junk_large;\n\tarena_dalloc_junk_large = arena_dalloc_junk_large_intercept;\n\thuge_dalloc_junk_orig = huge_dalloc_junk;\n\thuge_dalloc_junk = huge_dalloc_junk_intercept;\n\n\tsz_prev = 0;\n\ts = (char *)mallocx(sz_min, 0);\n\tassert_ptr_not_null((void *)s, \"Unexpected mallocx() failure\");\n\n\tfor (sz = sallocx(s, 0); sz <= sz_max;\n\t    sz_prev = sz, sz = sallocx(s, 0)) {\n\t\tif (sz_prev > 0) {\n\t\t\tassert_c_eq(s[0], 'a',\n\t\t\t    \"Previously allocated byte %zu/%zu is corrupted\",\n\t\t\t    ZU(0), sz_prev);\n\t\t\tassert_c_eq(s[sz_prev-1], 'a',\n\t\t\t    \"Previously allocated byte %zu/%zu is corrupted\",\n\t\t\t    sz_prev-1, sz_prev);\n\t\t}\n\n\t\tfor (i = sz_prev; i < sz; i++) {\n\t\t\tassert_c_eq(s[i], 0xa5,\n\t\t\t    \"Newly allocated byte %zu/%zu isn't junk-filled\",\n\t\t\t    i, sz);\n\t\t\ts[i] = 'a';\n\t\t}\n\n\t\tif (xallocx(s, sz+1, 0, 0) == sz) {\n\t\t\tvoid *junked = (void *)s;\n\n\t\t\ts = (char *)rallocx(s, sz+1, 0);\n\t\t\tassert_ptr_not_null((void *)s,\n\t\t\t    \"Unexpected rallocx() failure\");\n\t\t\tif (!config_mremap || sz+1 <= arena_maxclass) {\n\t\t\t\tassert_ptr_eq(most_recently_junked, junked,\n\t\t\t\t    \"Expected region of size %zu to be \"\n\t\t\t\t    \"junk-filled\",\n\t\t\t\t    sz);\n\t\t\t}\n\t\t}\n\t}\n\n\tdallocx(s, 0);\n\tassert_ptr_eq(most_recently_junked, (void *)s,\n\t    \"Expected region of size %zu to be junk-filled\", sz);\n\n\tarena_dalloc_junk_small = arena_dalloc_junk_small_orig;\n\tarena_dalloc_junk_large = arena_dalloc_junk_large_orig;\n\thuge_dalloc_junk = huge_dalloc_junk_orig;\n}\n\nTEST_BEGIN(test_junk_small)\n{\n\n\ttest_skip_if(!config_fill);\n\ttest_junk(1, SMALL_MAXCLASS-1);\n}\nTEST_END\n\nTEST_BEGIN(test_junk_large)\n{\n\n\ttest_skip_if(!config_fill);\n\ttest_junk(SMALL_MAXCLASS+1, arena_maxclass);\n}\nTEST_END\n\nTEST_BEGIN(test_junk_huge)\n{\n\n\ttest_skip_if(!config_fill);\n\ttest_junk(arena_maxclass+1, chunksize*2);\n}\nTEST_END\n\narena_ralloc_junk_large_t *arena_ralloc_junk_large_orig;\nstatic void *most_recently_trimmed;\n\nstatic void\narena_ralloc_junk_large_intercept(void *ptr, size_t old_usize, size_t usize)\n{\n\n\tarena_ralloc_junk_large_orig(ptr, old_usize, usize);\n\tassert_zu_eq(old_usize, arena_maxclass, \"Unexpected old_usize\");\n\tassert_zu_eq(usize, arena_maxclass-PAGE, \"Unexpected usize\");\n\tmost_recently_trimmed = ptr;\n}\n\nTEST_BEGIN(test_junk_large_ralloc_shrink)\n{\n\tvoid *p1, *p2;\n\n\tp1 = mallocx(arena_maxclass, 0);\n\tassert_ptr_not_null(p1, \"Unexpected mallocx() failure\");\n\n\tarena_ralloc_junk_large_orig = arena_ralloc_junk_large;\n\tarena_ralloc_junk_large = arena_ralloc_junk_large_intercept;\n\n\tp2 = rallocx(p1, arena_maxclass-PAGE, 0);\n\tassert_ptr_eq(p1, p2, \"Unexpected move during shrink\");\n\n\tarena_ralloc_junk_large = arena_ralloc_junk_large_orig;\n\n\tassert_ptr_eq(most_recently_trimmed, p1,\n\t    \"Expected trimmed portion of region to be junk-filled\");\n}\nTEST_END\n\nstatic bool detected_redzone_corruption;\n\nstatic void\narena_redzone_corruption_replacement(void *ptr, size_t usize, bool after,\n    size_t offset, uint8_t byte)\n{\n\n\tdetected_redzone_corruption = true;\n}\n\nTEST_BEGIN(test_junk_redzone)\n{\n\tchar *s;\n\tarena_redzone_corruption_t *arena_redzone_corruption_orig;\n\n\ttest_skip_if(!config_fill);\n\n\tarena_redzone_corruption_orig = arena_redzone_corruption;\n\tarena_redzone_corruption = arena_redzone_corruption_replacement;\n\n\t/* Test underflow. */\n\tdetected_redzone_corruption = false;\n\ts = (char *)mallocx(1, 0);\n\tassert_ptr_not_null((void *)s, \"Unexpected mallocx() failure\");\n\ts[-1] = 0xbb;\n\tdallocx(s, 0);\n\tassert_true(detected_redzone_corruption,\n\t    \"Did not detect redzone corruption\");\n\n\t/* Test overflow. */\n\tdetected_redzone_corruption = false;\n\ts = (char *)mallocx(1, 0);\n\tassert_ptr_not_null((void *)s, \"Unexpected mallocx() failure\");\n\ts[sallocx(s, 0)] = 0xbb;\n\tdallocx(s, 0);\n\tassert_true(detected_redzone_corruption,\n\t    \"Did not detect redzone corruption\");\n\n\tarena_redzone_corruption = arena_redzone_corruption_orig;\n}\nTEST_END\n\nint\nmain(void)\n{\n\n\treturn (test(\n\t    test_junk_small,\n\t    test_junk_large,\n\t    test_junk_huge,\n\t    test_junk_large_ralloc_shrink,\n\t    test_junk_redzone));\n}\n"
  },
  {
    "path": "extern/deprecated/redis-2.8.21/deps/jemalloc/test/unit/mallctl.c",
    "content": "#include \"test/jemalloc_test.h\"\n\nTEST_BEGIN(test_mallctl_errors)\n{\n\tuint64_t epoch;\n\tsize_t sz;\n\n\tassert_d_eq(mallctl(\"no_such_name\", NULL, NULL, NULL, 0), ENOENT,\n\t    \"mallctl() should return ENOENT for non-existent names\");\n\n\tassert_d_eq(mallctl(\"version\", NULL, NULL, \"0.0.0\", strlen(\"0.0.0\")),\n\t    EPERM, \"mallctl() should return EPERM on attempt to write \"\n\t    \"read-only value\");\n\n\tassert_d_eq(mallctl(\"epoch\", NULL, NULL, &epoch, sizeof(epoch)-1),\n\t    EINVAL, \"mallctl() should return EINVAL for input size mismatch\");\n\tassert_d_eq(mallctl(\"epoch\", NULL, NULL, &epoch, sizeof(epoch)+1),\n\t    EINVAL, \"mallctl() should return EINVAL for input size mismatch\");\n\n\tsz = sizeof(epoch)-1;\n\tassert_d_eq(mallctl(\"epoch\", &epoch, &sz, NULL, 0), EINVAL,\n\t    \"mallctl() should return EINVAL for output size mismatch\");\n\tsz = sizeof(epoch)+1;\n\tassert_d_eq(mallctl(\"epoch\", &epoch, &sz, NULL, 0), EINVAL,\n\t    \"mallctl() should return EINVAL for output size mismatch\");\n}\nTEST_END\n\nTEST_BEGIN(test_mallctlnametomib_errors)\n{\n\tsize_t mib[1];\n\tsize_t miblen;\n\n\tmiblen = sizeof(mib)/sizeof(size_t);\n\tassert_d_eq(mallctlnametomib(\"no_such_name\", mib, &miblen), ENOENT,\n\t    \"mallctlnametomib() should return ENOENT for non-existent names\");\n}\nTEST_END\n\nTEST_BEGIN(test_mallctlbymib_errors)\n{\n\tuint64_t epoch;\n\tsize_t sz;\n\tsize_t mib[1];\n\tsize_t miblen;\n\n\tmiblen = sizeof(mib)/sizeof(size_t);\n\tassert_d_eq(mallctlnametomib(\"version\", mib, &miblen), 0,\n\t    \"Unexpected mallctlnametomib() failure\");\n\n\tassert_d_eq(mallctlbymib(mib, miblen, NULL, NULL, \"0.0.0\",\n\t    strlen(\"0.0.0\")), EPERM, \"mallctl() should return EPERM on \"\n\t    \"attempt to write read-only value\");\n\n\tmiblen = sizeof(mib)/sizeof(size_t);\n\tassert_d_eq(mallctlnametomib(\"epoch\", mib, &miblen), 0,\n\t    \"Unexpected mallctlnametomib() failure\");\n\n\tassert_d_eq(mallctlbymib(mib, miblen, NULL, NULL, &epoch,\n\t    sizeof(epoch)-1), EINVAL,\n\t    \"mallctlbymib() should return EINVAL for input size mismatch\");\n\tassert_d_eq(mallctlbymib(mib, miblen, NULL, NULL, &epoch,\n\t    sizeof(epoch)+1), EINVAL,\n\t    \"mallctlbymib() should return EINVAL for input size mismatch\");\n\n\tsz = sizeof(epoch)-1;\n\tassert_d_eq(mallctlbymib(mib, miblen, &epoch, &sz, NULL, 0), EINVAL,\n\t    \"mallctlbymib() should return EINVAL for output size mismatch\");\n\tsz = sizeof(epoch)+1;\n\tassert_d_eq(mallctlbymib(mib, miblen, &epoch, &sz, NULL, 0), EINVAL,\n\t    \"mallctlbymib() should return EINVAL for output size mismatch\");\n}\nTEST_END\n\nTEST_BEGIN(test_mallctl_read_write)\n{\n\tuint64_t old_epoch, new_epoch;\n\tsize_t sz = sizeof(old_epoch);\n\n\t/* Blind. */\n\tassert_d_eq(mallctl(\"epoch\", NULL, NULL, NULL, 0), 0,\n\t    \"Unexpected mallctl() failure\");\n\tassert_zu_eq(sz, sizeof(old_epoch), \"Unexpected output size\");\n\n\t/* Read. */\n\tassert_d_eq(mallctl(\"epoch\", &old_epoch, &sz, NULL, 0), 0,\n\t    \"Unexpected mallctl() failure\");\n\tassert_zu_eq(sz, sizeof(old_epoch), \"Unexpected output size\");\n\n\t/* Write. */\n\tassert_d_eq(mallctl(\"epoch\", NULL, NULL, &new_epoch, sizeof(new_epoch)),\n\t    0, \"Unexpected mallctl() failure\");\n\tassert_zu_eq(sz, sizeof(old_epoch), \"Unexpected output size\");\n\n\t/* Read+write. */\n\tassert_d_eq(mallctl(\"epoch\", &old_epoch, &sz, &new_epoch,\n\t    sizeof(new_epoch)), 0, \"Unexpected mallctl() failure\");\n\tassert_zu_eq(sz, sizeof(old_epoch), \"Unexpected output size\");\n}\nTEST_END\n\nTEST_BEGIN(test_mallctlnametomib_short_mib)\n{\n\tsize_t mib[4];\n\tsize_t miblen;\n\n\tmiblen = 3;\n\tmib[3] = 42;\n\tassert_d_eq(mallctlnametomib(\"arenas.bin.0.nregs\", mib, &miblen), 0,\n\t    \"Unexpected mallctlnametomib() failure\");\n\tassert_zu_eq(miblen, 3, \"Unexpected mib output length\");\n\tassert_zu_eq(mib[3], 42,\n\t    \"mallctlnametomib() wrote past the end of the input mib\");\n}\nTEST_END\n\nTEST_BEGIN(test_mallctl_config)\n{\n\n#define\tTEST_MALLCTL_CONFIG(config) do {\t\t\t\t\\\n\tbool oldval;\t\t\t\t\t\t\t\\\n\tsize_t sz = sizeof(oldval);\t\t\t\t\t\\\n\tassert_d_eq(mallctl(\"config.\"#config, &oldval, &sz, NULL, 0),\t\\\n\t    0, \"Unexpected mallctl() failure\");\t\t\t\t\\\n\tassert_b_eq(oldval, config_##config, \"Incorrect config value\");\t\\\n\tassert_zu_eq(sz, sizeof(oldval), \"Unexpected output size\");\t\\\n} while (0)\n\n\tTEST_MALLCTL_CONFIG(debug);\n\tTEST_MALLCTL_CONFIG(dss);\n\tTEST_MALLCTL_CONFIG(fill);\n\tTEST_MALLCTL_CONFIG(lazy_lock);\n\tTEST_MALLCTL_CONFIG(mremap);\n\tTEST_MALLCTL_CONFIG(munmap);\n\tTEST_MALLCTL_CONFIG(prof);\n\tTEST_MALLCTL_CONFIG(prof_libgcc);\n\tTEST_MALLCTL_CONFIG(prof_libunwind);\n\tTEST_MALLCTL_CONFIG(stats);\n\tTEST_MALLCTL_CONFIG(tcache);\n\tTEST_MALLCTL_CONFIG(tls);\n\tTEST_MALLCTL_CONFIG(utrace);\n\tTEST_MALLCTL_CONFIG(valgrind);\n\tTEST_MALLCTL_CONFIG(xmalloc);\n\n#undef TEST_MALLCTL_CONFIG\n}\nTEST_END\n\nTEST_BEGIN(test_mallctl_opt)\n{\n\tbool config_always = true;\n\n#define\tTEST_MALLCTL_OPT(t, opt, config) do {\t\t\t\t\\\n\tt oldval;\t\t\t\t\t\t\t\\\n\tsize_t sz = sizeof(oldval);\t\t\t\t\t\\\n\tint expected = config_##config ? 0 : ENOENT;\t\t\t\\\n\tint result = mallctl(\"opt.\"#opt, &oldval, &sz, NULL, 0);\t\\\n\tassert_d_eq(result, expected,\t\t\t\t\t\\\n\t    \"Unexpected mallctl() result for opt.\"#opt);\t\t\\\n\tassert_zu_eq(sz, sizeof(oldval), \"Unexpected output size\");\t\\\n} while (0)\n\n\tTEST_MALLCTL_OPT(bool, abort, always);\n\tTEST_MALLCTL_OPT(size_t, lg_chunk, always);\n\tTEST_MALLCTL_OPT(const char *, dss, always);\n\tTEST_MALLCTL_OPT(size_t, narenas, always);\n\tTEST_MALLCTL_OPT(ssize_t, lg_dirty_mult, always);\n\tTEST_MALLCTL_OPT(bool, stats_print, always);\n\tTEST_MALLCTL_OPT(bool, junk, fill);\n\tTEST_MALLCTL_OPT(size_t, quarantine, fill);\n\tTEST_MALLCTL_OPT(bool, redzone, fill);\n\tTEST_MALLCTL_OPT(bool, zero, fill);\n\tTEST_MALLCTL_OPT(bool, utrace, utrace);\n\tTEST_MALLCTL_OPT(bool, valgrind, valgrind);\n\tTEST_MALLCTL_OPT(bool, xmalloc, xmalloc);\n\tTEST_MALLCTL_OPT(bool, tcache, tcache);\n\tTEST_MALLCTL_OPT(size_t, lg_tcache_max, tcache);\n\tTEST_MALLCTL_OPT(bool, prof, prof);\n\tTEST_MALLCTL_OPT(const char *, prof_prefix, prof);\n\tTEST_MALLCTL_OPT(bool, prof_active, prof);\n\tTEST_MALLCTL_OPT(ssize_t, lg_prof_sample, prof);\n\tTEST_MALLCTL_OPT(bool, prof_accum, prof);\n\tTEST_MALLCTL_OPT(ssize_t, lg_prof_interval, prof);\n\tTEST_MALLCTL_OPT(bool, prof_gdump, prof);\n\tTEST_MALLCTL_OPT(bool, prof_final, prof);\n\tTEST_MALLCTL_OPT(bool, prof_leak, prof);\n\n#undef TEST_MALLCTL_OPT\n}\nTEST_END\n\nTEST_BEGIN(test_manpage_example)\n{\n\tunsigned nbins, i;\n\tsize_t mib[4];\n\tsize_t len, miblen;\n\n\tlen = sizeof(nbins);\n\tassert_d_eq(mallctl(\"arenas.nbins\", &nbins, &len, NULL, 0), 0,\n\t    \"Unexpected mallctl() failure\");\n\n\tmiblen = 4;\n\tassert_d_eq(mallctlnametomib(\"arenas.bin.0.size\", mib, &miblen), 0,\n\t    \"Unexpected mallctlnametomib() failure\");\n\tfor (i = 0; i < nbins; i++) {\n\t\tsize_t bin_size;\n\n\t\tmib[2] = i;\n\t\tlen = sizeof(bin_size);\n\t\tassert_d_eq(mallctlbymib(mib, miblen, &bin_size, &len, NULL, 0),\n\t\t    0, \"Unexpected mallctlbymib() failure\");\n\t\t/* Do something with bin_size... */\n\t}\n}\nTEST_END\n\nTEST_BEGIN(test_thread_arena)\n{\n\tunsigned arena_old, arena_new, narenas;\n\tsize_t sz = sizeof(unsigned);\n\n\tassert_d_eq(mallctl(\"arenas.narenas\", &narenas, &sz, NULL, 0), 0,\n\t    \"Unexpected mallctl() failure\");\n\tassert_u_eq(narenas, opt_narenas, \"Number of arenas incorrect\");\n\tarena_new = narenas - 1;\n\tassert_d_eq(mallctl(\"thread.arena\", &arena_old, &sz, &arena_new,\n\t    sizeof(unsigned)), 0, \"Unexpected mallctl() failure\");\n\tarena_new = 0;\n\tassert_d_eq(mallctl(\"thread.arena\", &arena_old, &sz, &arena_new,\n\t    sizeof(unsigned)), 0, \"Unexpected mallctl() failure\");\n}\nTEST_END\n\nTEST_BEGIN(test_arena_i_purge)\n{\n\tunsigned narenas;\n\tsize_t sz = sizeof(unsigned);\n\tsize_t mib[3];\n\tsize_t miblen = 3;\n\n\tassert_d_eq(mallctl(\"arena.0.purge\", NULL, NULL, NULL, 0), 0,\n\t    \"Unexpected mallctl() failure\");\n\n\tassert_d_eq(mallctl(\"arenas.narenas\", &narenas, &sz, NULL, 0), 0,\n\t    \"Unexpected mallctl() failure\");\n\tassert_d_eq(mallctlnametomib(\"arena.0.purge\", mib, &miblen), 0,\n\t    \"Unexpected mallctlnametomib() failure\");\n\tmib[1] = narenas;\n\tassert_d_eq(mallctlbymib(mib, miblen, NULL, NULL, NULL, 0), 0,\n\t    \"Unexpected mallctlbymib() failure\");\n}\nTEST_END\n\nTEST_BEGIN(test_arena_i_dss)\n{\n\tconst char *dss_prec_old, *dss_prec_new;\n\tsize_t sz = sizeof(dss_prec_old);\n\n\tdss_prec_new = \"primary\";\n\tassert_d_eq(mallctl(\"arena.0.dss\", &dss_prec_old, &sz, &dss_prec_new,\n\t    sizeof(dss_prec_new)), 0, \"Unexpected mallctl() failure\");\n\tassert_str_ne(dss_prec_old, \"primary\",\n\t    \"Unexpected default for dss precedence\");\n\n\tassert_d_eq(mallctl(\"arena.0.dss\", &dss_prec_new, &sz, &dss_prec_old,\n\t    sizeof(dss_prec_old)), 0, \"Unexpected mallctl() failure\");\n}\nTEST_END\n\nTEST_BEGIN(test_arenas_purge)\n{\n\tunsigned arena = 0;\n\n\tassert_d_eq(mallctl(\"arenas.purge\", NULL, NULL, &arena, sizeof(arena)),\n\t    0, \"Unexpected mallctl() failure\");\n\n\tassert_d_eq(mallctl(\"arenas.purge\", NULL, NULL, NULL, 0), 0,\n\t    \"Unexpected mallctl() failure\");\n}\nTEST_END\n\nTEST_BEGIN(test_arenas_initialized)\n{\n\tunsigned narenas;\n\tsize_t sz = sizeof(narenas);\n\n\tassert_d_eq(mallctl(\"arenas.narenas\", &narenas, &sz, NULL, 0), 0,\n\t    \"Unexpected mallctl() failure\");\n\t{\n\t\tbool initialized[narenas];\n\n\t\tsz = narenas * sizeof(bool);\n\t\tassert_d_eq(mallctl(\"arenas.initialized\", initialized, &sz,\n\t\t    NULL, 0), 0, \"Unexpected mallctl() failure\");\n\t}\n}\nTEST_END\n\nTEST_BEGIN(test_arenas_constants)\n{\n\n#define\tTEST_ARENAS_CONSTANT(t, name, expected) do {\t\t\t\\\n\tt name;\t\t\t\t\t\t\t\t\\\n\tsize_t sz = sizeof(t);\t\t\t\t\t\t\\\n\tassert_d_eq(mallctl(\"arenas.\"#name, &name, &sz, NULL, 0), 0,\t\\\n\t    \"Unexpected mallctl() failure\");\t\t\t\t\\\n\tassert_zu_eq(name, expected, \"Incorrect \"#name\" size\");\t\t\\\n} while (0)\n\n\tTEST_ARENAS_CONSTANT(size_t, quantum, QUANTUM);\n\tTEST_ARENAS_CONSTANT(size_t, page, PAGE);\n\tTEST_ARENAS_CONSTANT(unsigned, nbins, NBINS);\n\tTEST_ARENAS_CONSTANT(size_t, nlruns, nlclasses);\n\n#undef TEST_ARENAS_CONSTANT\n}\nTEST_END\n\nTEST_BEGIN(test_arenas_bin_constants)\n{\n\n#define\tTEST_ARENAS_BIN_CONSTANT(t, name, expected) do {\t\t\\\n\tt name;\t\t\t\t\t\t\t\t\\\n\tsize_t sz = sizeof(t);\t\t\t\t\t\t\\\n\tassert_d_eq(mallctl(\"arenas.bin.0.\"#name, &name, &sz, NULL, 0),\t\\\n\t    0, \"Unexpected mallctl() failure\");\t\t\t\t\\\n\tassert_zu_eq(name, expected, \"Incorrect \"#name\" size\");\t\t\\\n} while (0)\n\n\tTEST_ARENAS_BIN_CONSTANT(size_t, size, arena_bin_info[0].reg_size);\n\tTEST_ARENAS_BIN_CONSTANT(uint32_t, nregs, arena_bin_info[0].nregs);\n\tTEST_ARENAS_BIN_CONSTANT(size_t, run_size, arena_bin_info[0].run_size);\n\n#undef TEST_ARENAS_BIN_CONSTANT\n}\nTEST_END\n\nTEST_BEGIN(test_arenas_lrun_constants)\n{\n\n#define\tTEST_ARENAS_LRUN_CONSTANT(t, name, expected) do {\t\t\\\n\tt name;\t\t\t\t\t\t\t\t\\\n\tsize_t sz = sizeof(t);\t\t\t\t\t\t\\\n\tassert_d_eq(mallctl(\"arenas.lrun.0.\"#name, &name, &sz, NULL,\t\\\n\t    0), 0, \"Unexpected mallctl() failure\");\t\t\t\\\n\tassert_zu_eq(name, expected, \"Incorrect \"#name\" size\");\t\t\\\n} while (0)\n\n\tTEST_ARENAS_LRUN_CONSTANT(size_t, size, (1 << LG_PAGE));\n\n#undef TEST_ARENAS_LRUN_CONSTANT\n}\nTEST_END\n\nTEST_BEGIN(test_arenas_extend)\n{\n\tunsigned narenas_before, arena, narenas_after;\n\tsize_t sz = sizeof(unsigned);\n\n\tassert_d_eq(mallctl(\"arenas.narenas\", &narenas_before, &sz, NULL, 0), 0,\n\t    \"Unexpected mallctl() failure\");\n\tassert_d_eq(mallctl(\"arenas.extend\", &arena, &sz, NULL, 0), 0,\n\t    \"Unexpected mallctl() failure\");\n\tassert_d_eq(mallctl(\"arenas.narenas\", &narenas_after, &sz, NULL, 0), 0,\n\t    \"Unexpected mallctl() failure\");\n\n\tassert_u_eq(narenas_before+1, narenas_after,\n\t    \"Unexpected number of arenas before versus after extension\");\n\tassert_u_eq(arena, narenas_after-1, \"Unexpected arena index\");\n}\nTEST_END\n\nTEST_BEGIN(test_stats_arenas)\n{\n\n#define\tTEST_STATS_ARENAS(t, name) do {\t\t\t\t\t\\\n\tt name;\t\t\t\t\t\t\t\t\\\n\tsize_t sz = sizeof(t);\t\t\t\t\t\t\\\n\tassert_d_eq(mallctl(\"stats.arenas.0.\"#name, &name, &sz, NULL,\t\\\n\t    0), 0, \"Unexpected mallctl() failure\");\t\t\t\\\n} while (0)\n\n\tTEST_STATS_ARENAS(const char *, dss);\n\tTEST_STATS_ARENAS(unsigned, nthreads);\n\tTEST_STATS_ARENAS(size_t, pactive);\n\tTEST_STATS_ARENAS(size_t, pdirty);\n\n#undef TEST_STATS_ARENAS\n}\nTEST_END\n\nint\nmain(void)\n{\n\n\treturn (test(\n\t    test_mallctl_errors,\n\t    test_mallctlnametomib_errors,\n\t    test_mallctlbymib_errors,\n\t    test_mallctl_read_write,\n\t    test_mallctlnametomib_short_mib,\n\t    test_mallctl_config,\n\t    test_mallctl_opt,\n\t    test_manpage_example,\n\t    test_thread_arena,\n\t    test_arena_i_purge,\n\t    test_arena_i_dss,\n\t    test_arenas_purge,\n\t    test_arenas_initialized,\n\t    test_arenas_constants,\n\t    test_arenas_bin_constants,\n\t    test_arenas_lrun_constants,\n\t    test_arenas_extend,\n\t    test_stats_arenas));\n}\n"
  },
  {
    "path": "extern/deprecated/redis-2.8.21/deps/jemalloc/test/unit/math.c",
    "content": "#include \"test/jemalloc_test.h\"\n\n#define\tMAX_REL_ERR 1.0e-9\n#define\tMAX_ABS_ERR 1.0e-9\n\nstatic bool\ndouble_eq_rel(double a, double b, double max_rel_err, double max_abs_err)\n{\n\tdouble rel_err;\n\n\tif (fabs(a - b) < max_abs_err)\n\t\treturn (true);\n\trel_err = (fabs(b) > fabs(a)) ? fabs((a-b)/b) : fabs((a-b)/a);\n\treturn (rel_err < max_rel_err);\n}\n\nstatic uint64_t\nfactorial(unsigned x)\n{\n\tuint64_t ret = 1;\n\tunsigned i;\n\n\tfor (i = 2; i <= x; i++)\n\t\tret *= (uint64_t)i;\n\n\treturn (ret);\n}\n\nTEST_BEGIN(test_ln_gamma_factorial)\n{\n\tunsigned x;\n\n\t/* exp(ln_gamma(x)) == (x-1)! for integer x. */\n\tfor (x = 1; x <= 21; x++) {\n\t\tassert_true(double_eq_rel(exp(ln_gamma(x)),\n\t\t    (double)factorial(x-1), MAX_REL_ERR, MAX_ABS_ERR),\n\t\t    \"Incorrect factorial result for x=%u\", x);\n\t}\n}\nTEST_END\n\n/* Expected ln_gamma([0.0..100.0] increment=0.25). */\nstatic const double ln_gamma_misc_expected[] = {\n\tINFINITY,\n\t1.28802252469807743, 0.57236494292470008, 0.20328095143129538,\n\t0.00000000000000000, -0.09827183642181320, -0.12078223763524518,\n\t-0.08440112102048555, 0.00000000000000000, 0.12487171489239651,\n\t0.28468287047291918, 0.47521466691493719, 0.69314718055994529,\n\t0.93580193110872523, 1.20097360234707429, 1.48681557859341718,\n\t1.79175946922805496, 2.11445692745037128, 2.45373657084244234,\n\t2.80857141857573644, 3.17805383034794575, 3.56137591038669710,\n\t3.95781396761871651, 4.36671603662228680, 4.78749174278204581,\n\t5.21960398699022932, 5.66256205985714178, 6.11591589143154568,\n\t6.57925121201010121, 7.05218545073853953, 7.53436423675873268,\n\t8.02545839631598312, 8.52516136106541467, 9.03318691960512332,\n\t9.54926725730099690, 10.07315123968123949, 10.60460290274525086,\n\t11.14340011995171231, 11.68933342079726856, 12.24220494005076176,\n\t12.80182748008146909, 13.36802367147604720, 13.94062521940376342,\n\t14.51947222506051816, 15.10441257307551943, 15.69530137706046524,\n\t16.29200047656724237, 16.89437797963419285, 17.50230784587389010,\n\t18.11566950571089407, 18.73434751193644843, 19.35823122022435427,\n\t19.98721449566188468, 20.62119544270163018, 21.26007615624470048,\n\t21.90376249182879320, 22.55216385312342098, 23.20519299513386002,\n\t23.86276584168908954, 24.52480131594137802, 25.19122118273868338,\n\t25.86194990184851861, 26.53691449111561340, 27.21604439872720604,\n\t27.89927138384089389, 28.58652940490193828, 29.27775451504081516,\n\t29.97288476399884871, 30.67186010608067548, 31.37462231367769050,\n\t32.08111489594735843, 32.79128302226991565, 33.50507345013689076,\n\t34.22243445715505317, 34.94331577687681545, 35.66766853819134298,\n\t36.39544520803305261, 37.12659953718355865, 37.86108650896109395,\n\t38.59886229060776230, 39.33988418719949465, 40.08411059791735198,\n\t40.83150097453079752, 41.58201578195490100, 42.33561646075348506,\n\t43.09226539146988699, 43.85192586067515208, 44.61456202863158893,\n\t45.38013889847690052, 46.14862228684032885, 46.91997879580877395,\n\t47.69417578616628361, 48.47118135183522014, 49.25096429545256882,\n\t50.03349410501914463, 50.81874093156324790, 51.60667556776436982,\n\t52.39726942748592364, 53.19049452616926743, 53.98632346204390586,\n\t54.78472939811231157, 55.58568604486942633, 56.38916764371992940,\n\t57.19514895105859864, 58.00360522298051080, 58.81451220059079787,\n\t59.62784609588432261, 60.44358357816834371, 61.26170176100199427,\n\t62.08217818962842927, 62.90499082887649962, 63.73011805151035958,\n\t64.55753862700632340, 65.38723171073768015, 66.21917683354901385,\n\t67.05335389170279825, 67.88974313718154008, 68.72832516833013017,\n\t69.56908092082363737, 70.41199165894616385, 71.25703896716800045,\n\t72.10420474200799390, 72.95347118416940191, 73.80482079093779646,\n\t74.65823634883015814, 75.51370092648485866, 76.37119786778275454,\n\t77.23071078519033961, 78.09222355331530707, 78.95572030266725960,\n\t79.82118541361435859, 80.68860351052903468, 81.55795945611502873,\n\t82.42923834590904164, 83.30242550295004378, 84.17750647261028973,\n\t85.05446701758152983, 85.93329311301090456, 86.81397094178107920,\n\t87.69648688992882057, 88.58082754219766741, 89.46697967771913795,\n\t90.35493026581838194, 91.24466646193963015, 92.13617560368709292,\n\t93.02944520697742803, 93.92446296229978486, 94.82121673107967297,\n\t95.71969454214321615, 96.61988458827809723, 97.52177522288820910,\n\t98.42535495673848800, 99.33061245478741341, 100.23753653310367895,\n\t101.14611615586458981, 102.05634043243354370, 102.96819861451382394,\n\t103.88168009337621811, 104.79677439715833032, 105.71347118823287303,\n\t106.63176026064346047, 107.55163153760463501, 108.47307506906540198,\n\t109.39608102933323153, 110.32063971475740516, 111.24674154146920557,\n\t112.17437704317786995, 113.10353686902013237, 114.03421178146170689,\n\t114.96639265424990128, 115.90007047041454769, 116.83523632031698014,\n\t117.77188139974506953, 118.70999700805310795, 119.64957454634490830,\n\t120.59060551569974962, 121.53308151543865279, 122.47699424143097247,\n\t123.42233548443955726, 124.36909712850338394, 125.31727114935689826,\n\t126.26684961288492559, 127.21782467361175861, 128.17018857322420899,\n\t129.12393363912724453, 130.07905228303084755, 131.03553699956862033,\n\t131.99338036494577864, 132.95257503561629164, 133.91311374698926784,\n\t134.87498931216194364, 135.83819462068046846, 136.80272263732638294,\n\t137.76856640092901785, 138.73571902320256299, 139.70417368760718091,\n\t140.67392364823425055, 141.64496222871400732, 142.61728282114600574,\n\t143.59087888505104047, 144.56574394634486680, 145.54187159633210058,\n\t146.51925549072063859, 147.49788934865566148, 148.47776695177302031,\n\t149.45888214327129617, 150.44122882700193600, 151.42480096657754984,\n\t152.40959258449737490, 153.39559776128982094, 154.38281063467164245,\n\t155.37122539872302696, 156.36083630307879844, 157.35163765213474107,\n\t158.34362380426921391, 159.33678917107920370, 160.33112821663092973,\n\t161.32663545672428995, 162.32330545817117695, 163.32113283808695314,\n\t164.32011226319519892, 165.32023844914485267, 166.32150615984036790,\n\t167.32391020678358018, 168.32744544842768164, 169.33210678954270634,\n\t170.33788918059275375, 171.34478761712384198, 172.35279713916281707,\n\t173.36191283062726143, 174.37212981874515094, 175.38344327348534080,\n\t176.39584840699734514, 177.40934047306160437, 178.42391476654847793,\n\t179.43956662288721304, 180.45629141754378111, 181.47408456550741107,\n\t182.49294152078630304, 183.51285777591152737, 184.53382886144947861,\n\t185.55585034552262869, 186.57891783333786861, 187.60302696672312095,\n\t188.62817342367162610, 189.65435291789341932, 190.68156119837468054,\n\t191.70979404894376330, 192.73904728784492590, 193.76931676731820176,\n\t194.80059837318714244, 195.83288802445184729, 196.86618167288995096,\n\t197.90047530266301123, 198.93576492992946214, 199.97204660246373464,\n\t201.00931639928148797, 202.04757043027063901, 203.08680483582807597,\n\t204.12701578650228385, 205.16819948264117102, 206.21035215404597807,\n\t207.25347005962987623, 208.29754948708190909, 209.34258675253678916,\n\t210.38857820024875878, 211.43552020227099320, 212.48340915813977858,\n\t213.53224149456323744, 214.58201366511514152, 215.63272214993284592,\n\t216.68436345542014010, 217.73693411395422004, 218.79043068359703739,\n\t219.84484974781133815, 220.90018791517996988, 221.95644181913033322,\n\t223.01360811766215875, 224.07168349307951871, 225.13066465172661879,\n\t226.19054832372759734, 227.25133126272962159, 228.31301024565024704,\n\t229.37558207242807384, 230.43904356577689896, 231.50339157094342113,\n\t232.56862295546847008, 233.63473460895144740, 234.70172344281823484,\n\t235.76958639009222907, 236.83832040516844586, 237.90792246359117712,\n\t238.97838956183431947, 240.04971871708477238, 241.12190696702904802,\n\t242.19495136964280846, 243.26884900298270509, 244.34359696498191283,\n\t245.41919237324782443, 246.49563236486270057, 247.57291409618682110,\n\t248.65103474266476269, 249.72999149863338175, 250.80978157713354904,\n\t251.89040220972316320, 252.97185064629374551, 254.05412415488834199,\n\t255.13722002152300661, 256.22113555000953511, 257.30586806178126835,\n\t258.39141489572085675, 259.47777340799029844, 260.56494097186322279,\n\t261.65291497755913497, 262.74169283208021852, 263.83127195904967266,\n\t264.92164979855277807, 266.01282380697938379, 267.10479145686849733,\n\t268.19755023675537586, 269.29109765101975427, 270.38543121973674488,\n\t271.48054847852881721, 272.57644697842033565, 273.67312428569374561,\n\t274.77057798174683967, 275.86880566295326389, 276.96780494052313770,\n\t278.06757344036617496, 279.16810880295668085, 280.26940868320008349,\n\t281.37147075030043197, 282.47429268763045229, 283.57787219260217171,\n\t284.68220697654078322, 285.78729476455760050, 286.89313329542699194,\n\t287.99972032146268930, 289.10705360839756395, 290.21513093526289140,\n\t291.32395009427028754, 292.43350889069523646, 293.54380514276073200,\n\t294.65483668152336350, 295.76660135076059532, 296.87909700685889902,\n\t297.99232151870342022, 299.10627276756946458, 300.22094864701409733,\n\t301.33634706277030091, 302.45246593264130297, 303.56930318639643929,\n\t304.68685676566872189, 305.80512462385280514, 306.92410472600477078,\n\t308.04379504874236773, 309.16419358014690033, 310.28529831966631036,\n\t311.40710727801865687, 312.52961847709792664, 313.65282994987899201,\n\t314.77673974032603610, 315.90134590329950015, 317.02664650446632777,\n\t318.15263962020929966, 319.27932333753892635, 320.40669575400545455,\n\t321.53475497761127144, 322.66349912672620803, 323.79292633000159185,\n\t324.92303472628691452, 326.05382246454587403, 327.18528770377525916,\n\t328.31742861292224234, 329.45024337080525356, 330.58373016603343331,\n\t331.71788719692847280, 332.85271267144611329, 333.98820480709991898,\n\t335.12436183088397001, 336.26118197919845443, 337.39866349777429377,\n\t338.53680464159958774, 339.67560367484657036, 340.81505887079896411,\n\t341.95516851178109619, 343.09593088908627578, 344.23734430290727460,\n\t345.37940706226686416, 346.52211748494903532, 347.66547389743118401,\n\t348.80947463481720661, 349.95411804077025408, 351.09940246744753267,\n\t352.24532627543504759, 353.39188783368263103, 354.53908551944078908,\n\t355.68691771819692349, 356.83538282361303118, 357.98447923746385868,\n\t359.13420536957539753\n};\n\nTEST_BEGIN(test_ln_gamma_misc)\n{\n\tunsigned i;\n\n\tfor (i = 1; i < sizeof(ln_gamma_misc_expected)/sizeof(double); i++) {\n\t\tdouble x = (double)i * 0.25;\n\t\tassert_true(double_eq_rel(ln_gamma(x),\n\t\t    ln_gamma_misc_expected[i], MAX_REL_ERR, MAX_ABS_ERR),\n\t\t    \"Incorrect ln_gamma result for i=%u\", i);\n\t}\n}\nTEST_END\n\n/* Expected pt_norm([0.01..0.99] increment=0.01). */\nstatic const double pt_norm_expected[] = {\n\t-INFINITY,\n\t-2.32634787404084076, -2.05374891063182252, -1.88079360815125085,\n\t-1.75068607125216946, -1.64485362695147264, -1.55477359459685305,\n\t-1.47579102817917063, -1.40507156030963221, -1.34075503369021654,\n\t-1.28155156554460081, -1.22652812003661049, -1.17498679206608991,\n\t-1.12639112903880045, -1.08031934081495606, -1.03643338949378938,\n\t-0.99445788320975281, -0.95416525314619416, -0.91536508784281390,\n\t-0.87789629505122846, -0.84162123357291418, -0.80642124701824025,\n\t-0.77219321418868492, -0.73884684918521371, -0.70630256284008752,\n\t-0.67448975019608171, -0.64334540539291685, -0.61281299101662701,\n\t-0.58284150727121620, -0.55338471955567281, -0.52440051270804067,\n\t-0.49585034734745320, -0.46769879911450812, -0.43991316567323380,\n\t-0.41246312944140462, -0.38532046640756751, -0.35845879325119373,\n\t-0.33185334643681652, -0.30548078809939738, -0.27931903444745404,\n\t-0.25334710313579978, -0.22754497664114931, -0.20189347914185077,\n\t-0.17637416478086135, -0.15096921549677725, -0.12566134685507399,\n\t-0.10043372051146975, -0.07526986209982976, -0.05015358346473352,\n\t-0.02506890825871106, 0.00000000000000000, 0.02506890825871106,\n\t0.05015358346473366, 0.07526986209982990, 0.10043372051146990,\n\t0.12566134685507413, 0.15096921549677739, 0.17637416478086146,\n\t0.20189347914185105, 0.22754497664114931, 0.25334710313579978,\n\t0.27931903444745404, 0.30548078809939738, 0.33185334643681652,\n\t0.35845879325119373, 0.38532046640756762, 0.41246312944140484,\n\t0.43991316567323391, 0.46769879911450835, 0.49585034734745348,\n\t0.52440051270804111, 0.55338471955567303, 0.58284150727121620,\n\t0.61281299101662701, 0.64334540539291685, 0.67448975019608171,\n\t0.70630256284008752, 0.73884684918521371, 0.77219321418868492,\n\t0.80642124701824036, 0.84162123357291441, 0.87789629505122879,\n\t0.91536508784281423, 0.95416525314619460, 0.99445788320975348,\n\t1.03643338949378938, 1.08031934081495606, 1.12639112903880045,\n\t1.17498679206608991, 1.22652812003661049, 1.28155156554460081,\n\t1.34075503369021654, 1.40507156030963265, 1.47579102817917085,\n\t1.55477359459685394, 1.64485362695147308, 1.75068607125217102,\n\t1.88079360815125041, 2.05374891063182208, 2.32634787404084076\n};\n\nTEST_BEGIN(test_pt_norm)\n{\n\tunsigned i;\n\n\tfor (i = 1; i < sizeof(pt_norm_expected)/sizeof(double); i++) {\n\t\tdouble p = (double)i * 0.01;\n\t\tassert_true(double_eq_rel(pt_norm(p), pt_norm_expected[i],\n\t\t    MAX_REL_ERR, MAX_ABS_ERR),\n\t\t    \"Incorrect pt_norm result for i=%u\", i);\n\t}\n}\nTEST_END\n\n/*\n * Expected pt_chi2(p=[0.01..0.99] increment=0.07,\n *                  df={0.1, 1.1, 10.1, 100.1, 1000.1}).\n */\nstatic const double pt_chi2_df[] = {0.1, 1.1, 10.1, 100.1, 1000.1};\nstatic const double pt_chi2_expected[] = {\n\t1.168926411457320e-40, 1.347680397072034e-22, 3.886980416666260e-17,\n\t8.245951724356564e-14, 2.068936347497604e-11, 1.562561743309233e-09,\n\t5.459543043426564e-08, 1.114775688149252e-06, 1.532101202364371e-05,\n\t1.553884683726585e-04, 1.239396954915939e-03, 8.153872320255721e-03,\n\t4.631183739647523e-02, 2.473187311701327e-01, 2.175254800183617e+00,\n\n\t0.0003729887888876379, 0.0164409238228929513, 0.0521523015190650113,\n\t0.1064701372271216612, 0.1800913735793082115, 0.2748704281195626931,\n\t0.3939246282787986497, 0.5420727552260817816, 0.7267265822221973259,\n\t0.9596554296000253670, 1.2607440376386165326, 1.6671185084541604304,\n\t2.2604828984738705167, 3.2868613342148607082, 6.9298574921692139839,\n\n\t2.606673548632508, 4.602913725294877, 5.646152813924212,\n\t6.488971315540869, 7.249823275816285, 7.977314231410841,\n\t8.700354939944047, 9.441728024225892, 10.224338321374127,\n\t11.076435368801061, 12.039320937038386, 13.183878752697167,\n\t14.657791935084575, 16.885728216339373, 23.361991680031817,\n\n\t70.14844087392152, 80.92379498849355, 85.53325420085891,\n\t88.94433120715347, 91.83732712857017, 94.46719943606301,\n\t96.96896479994635, 99.43412843510363, 101.94074719829733,\n\t104.57228644307247, 107.43900093448734, 110.71844673417287,\n\t114.76616819871325, 120.57422505959563, 135.92318818757556,\n\n\t899.0072447849649, 937.9271278858220, 953.8117189560207,\n\t965.3079371501154, 974.8974061207954, 983.4936235182347,\n\t991.5691170518946, 999.4334123954690, 1007.3391826856553,\n\t1015.5445154999951, 1024.3777075619569, 1034.3538789836223,\n\t1046.4872561869577, 1063.5717461999654, 1107.0741966053859\n};\n\nTEST_BEGIN(test_pt_chi2)\n{\n\tunsigned i, j;\n\tunsigned e = 0;\n\n\tfor (i = 0; i < sizeof(pt_chi2_df)/sizeof(double); i++) {\n\t\tdouble df = pt_chi2_df[i];\n\t\tdouble ln_gamma_df = ln_gamma(df * 0.5);\n\t\tfor (j = 1; j < 100; j += 7) {\n\t\t\tdouble p = (double)j * 0.01;\n\t\t\tassert_true(double_eq_rel(pt_chi2(p, df, ln_gamma_df),\n\t\t\t    pt_chi2_expected[e], MAX_REL_ERR, MAX_ABS_ERR),\n\t\t\t    \"Incorrect pt_chi2 result for i=%u, j=%u\", i, j);\n\t\t\te++;\n\t\t}\n\t}\n}\nTEST_END\n\n/*\n * Expected pt_gamma(p=[0.1..0.99] increment=0.07,\n *                   shape=[0.5..3.0] increment=0.5).\n */\nstatic const double pt_gamma_shape[] = {0.5, 1.0, 1.5, 2.0, 2.5, 3.0};\nstatic const double pt_gamma_expected[] = {\n\t7.854392895485103e-05, 5.043466107888016e-03, 1.788288957794883e-02,\n\t3.900956150232906e-02, 6.913847560638034e-02, 1.093710833465766e-01,\n\t1.613412523825817e-01, 2.274682115597864e-01, 3.114117323127083e-01,\n\t4.189466220207417e-01, 5.598106789059246e-01, 7.521856146202706e-01,\n\t1.036125427911119e+00, 1.532450860038180e+00, 3.317448300510606e+00,\n\n\t0.01005033585350144, 0.08338160893905107, 0.16251892949777497,\n\t0.24846135929849966, 0.34249030894677596, 0.44628710262841947,\n\t0.56211891815354142, 0.69314718055994529, 0.84397007029452920,\n\t1.02165124753198167, 1.23787435600161766, 1.51412773262977574,\n\t1.89711998488588196, 2.52572864430825783, 4.60517018598809091,\n\n\t0.05741590094955853, 0.24747378084860744, 0.39888572212236084,\n\t0.54394139997444901, 0.69048812513915159, 0.84311389861296104,\n\t1.00580622221479898, 1.18298694218766931, 1.38038096305861213,\n\t1.60627736383027453, 1.87396970522337947, 2.20749220408081070,\n\t2.65852391865854942, 3.37934630984842244, 5.67243336507218476,\n\n\t0.1485547402532659, 0.4657458011640391, 0.6832386130709406,\n\t0.8794297834672100, 1.0700752852474524, 1.2629614217350744,\n\t1.4638400448580779, 1.6783469900166610, 1.9132338090606940,\n\t2.1778589228618777, 2.4868823970010991, 2.8664695666264195,\n\t3.3724415436062114, 4.1682658512758071, 6.6383520679938108,\n\n\t0.2771490383641385, 0.7195001279643727, 0.9969081732265243,\n\t1.2383497880608061, 1.4675206597269927, 1.6953064251816552,\n\t1.9291243435606809, 2.1757300955477641, 2.4428032131216391,\n\t2.7406534569230616, 3.0851445039665513, 3.5043101122033367,\n\t4.0575997065264637, 4.9182956424675286, 7.5431362346944937,\n\n\t0.4360451650782932, 0.9983600902486267, 1.3306365880734528,\n\t1.6129750834753802, 1.8767241606994294, 2.1357032436097660,\n\t2.3988853336865565, 2.6740603137235603, 2.9697561737517959,\n\t3.2971457713883265, 3.6731795898504660, 4.1275751617770631,\n\t4.7230515633946677, 5.6417477865306020, 8.4059469148854635\n};\n\nTEST_BEGIN(test_pt_gamma_shape)\n{\n\tunsigned i, j;\n\tunsigned e = 0;\n\n\tfor (i = 0; i < sizeof(pt_gamma_shape)/sizeof(double); i++) {\n\t\tdouble shape = pt_gamma_shape[i];\n\t\tdouble ln_gamma_shape = ln_gamma(shape);\n\t\tfor (j = 1; j < 100; j += 7) {\n\t\t\tdouble p = (double)j * 0.01;\n\t\t\tassert_true(double_eq_rel(pt_gamma(p, shape, 1.0,\n\t\t\t    ln_gamma_shape), pt_gamma_expected[e], MAX_REL_ERR,\n\t\t\t    MAX_ABS_ERR),\n\t\t\t    \"Incorrect pt_gamma result for i=%u, j=%u\", i, j);\n\t\t\te++;\n\t\t}\n\t}\n}\nTEST_END\n\nTEST_BEGIN(test_pt_gamma_scale)\n{\n\tdouble shape = 1.0;\n\tdouble ln_gamma_shape = ln_gamma(shape);\n\n\tassert_true(double_eq_rel(\n\t    pt_gamma(0.5, shape, 1.0, ln_gamma_shape) * 10.0,\n\t    pt_gamma(0.5, shape, 10.0, ln_gamma_shape), MAX_REL_ERR,\n\t    MAX_ABS_ERR),\n\t    \"Scale should be trivially equivalent to external multiplication\");\n}\nTEST_END\n\nint\nmain(void)\n{\n\n\treturn (test(\n\t    test_ln_gamma_factorial,\n\t    test_ln_gamma_misc,\n\t    test_pt_norm,\n\t    test_pt_chi2,\n\t    test_pt_gamma_shape,\n\t    test_pt_gamma_scale));\n}\n"
  },
  {
    "path": "extern/deprecated/redis-2.8.21/deps/jemalloc/test/unit/mq.c",
    "content": "#include \"test/jemalloc_test.h\"\n\n#define\tNSENDERS\t3\n#define\tNMSGS\t\t100000\n\ntypedef struct mq_msg_s mq_msg_t;\nstruct mq_msg_s {\n\tmq_msg(mq_msg_t)\tlink;\n};\nmq_gen(static, mq_, mq_t, mq_msg_t, link)\n\nTEST_BEGIN(test_mq_basic)\n{\n\tmq_t mq;\n\tmq_msg_t msg;\n\n\tassert_false(mq_init(&mq), \"Unexpected mq_init() failure\");\n\tassert_u_eq(mq_count(&mq), 0, \"mq should be empty\");\n\tassert_ptr_null(mq_tryget(&mq),\n\t    \"mq_tryget() should fail when the queue is empty\");\n\n\tmq_put(&mq, &msg);\n\tassert_u_eq(mq_count(&mq), 1, \"mq should contain one message\");\n\tassert_ptr_eq(mq_tryget(&mq), &msg, \"mq_tryget() should return msg\");\n\n\tmq_put(&mq, &msg);\n\tassert_ptr_eq(mq_get(&mq), &msg, \"mq_get() should return msg\");\n\n\tmq_fini(&mq);\n}\nTEST_END\n\nstatic void *\nthd_receiver_start(void *arg)\n{\n\tmq_t *mq = (mq_t *)arg;\n\tunsigned i;\n\n\tfor (i = 0; i < (NSENDERS * NMSGS); i++) {\n\t\tmq_msg_t *msg = mq_get(mq);\n\t\tassert_ptr_not_null(msg, \"mq_get() should never return NULL\");\n\t\tdallocx(msg, 0);\n\t}\n\treturn (NULL);\n}\n\nstatic void *\nthd_sender_start(void *arg)\n{\n\tmq_t *mq = (mq_t *)arg;\n\tunsigned i;\n\n\tfor (i = 0; i < NMSGS; i++) {\n\t\tmq_msg_t *msg;\n\t\tvoid *p;\n\t\tp = mallocx(sizeof(mq_msg_t), 0);\n\t\tassert_ptr_not_null(p, \"Unexpected allocm() failure\");\n\t\tmsg = (mq_msg_t *)p;\n\t\tmq_put(mq, msg);\n\t}\n\treturn (NULL);\n}\n\nTEST_BEGIN(test_mq_threaded)\n{\n\tmq_t mq;\n\tthd_t receiver;\n\tthd_t senders[NSENDERS];\n\tunsigned i;\n\n\tassert_false(mq_init(&mq), \"Unexpected mq_init() failure\");\n\n\tthd_create(&receiver, thd_receiver_start, (void *)&mq);\n\tfor (i = 0; i < NSENDERS; i++)\n\t\tthd_create(&senders[i], thd_sender_start, (void *)&mq);\n\n\tthd_join(receiver, NULL);\n\tfor (i = 0; i < NSENDERS; i++)\n\t\tthd_join(senders[i], NULL);\n\n\tmq_fini(&mq);\n}\nTEST_END\n\nint\nmain(void)\n{\n\treturn (test(\n\t    test_mq_basic,\n\t    test_mq_threaded));\n}\n\n"
  },
  {
    "path": "extern/deprecated/redis-2.8.21/deps/jemalloc/test/unit/mtx.c",
    "content": "#include \"test/jemalloc_test.h\"\n\n#define\tNTHREADS\t2\n#define\tNINCRS\t\t2000000\n\nTEST_BEGIN(test_mtx_basic)\n{\n\tmtx_t mtx;\n\n\tassert_false(mtx_init(&mtx), \"Unexpected mtx_init() failure\");\n\tmtx_lock(&mtx);\n\tmtx_unlock(&mtx);\n\tmtx_fini(&mtx);\n}\nTEST_END\n\ntypedef struct {\n\tmtx_t\t\tmtx;\n\tunsigned\tx;\n} thd_start_arg_t;\n\nstatic void *\nthd_start(void *varg)\n{\n\tthd_start_arg_t *arg = (thd_start_arg_t *)varg;\n\tunsigned i;\n\n\tfor (i = 0; i < NINCRS; i++) {\n\t\tmtx_lock(&arg->mtx);\n\t\targ->x++;\n\t\tmtx_unlock(&arg->mtx);\n\t}\n\treturn (NULL);\n}\n\nTEST_BEGIN(test_mtx_race)\n{\n\tthd_start_arg_t arg;\n\tthd_t thds[NTHREADS];\n\tunsigned i;\n\n\tassert_false(mtx_init(&arg.mtx), \"Unexpected mtx_init() failure\");\n\targ.x = 0;\n\tfor (i = 0; i < NTHREADS; i++)\n\t\tthd_create(&thds[i], thd_start, (void *)&arg);\n\tfor (i = 0; i < NTHREADS; i++)\n\t\tthd_join(thds[i], NULL);\n\tassert_u_eq(arg.x, NTHREADS * NINCRS,\n\t    \"Race-related counter corruption\");\n}\nTEST_END\n\nint\nmain(void)\n{\n\n\treturn (test(\n\t    test_mtx_basic,\n\t    test_mtx_race));\n}\n"
  },
  {
    "path": "extern/deprecated/redis-2.8.21/deps/jemalloc/test/unit/prof_accum.c",
    "content": "#include \"prof_accum.h\"\n\n#ifdef JEMALLOC_PROF\nconst char *malloc_conf =\n    \"prof:true,prof_accum:true,prof_active:false,lg_prof_sample:0\";\n#endif\n\nstatic int\nprof_dump_open_intercept(bool propagate_err, const char *filename)\n{\n\tint fd;\n\n\tfd = open(\"/dev/null\", O_WRONLY);\n\tassert_d_ne(fd, -1, \"Unexpected open() failure\");\n\n\treturn (fd);\n}\n\nstatic void *\nalloc_from_permuted_backtrace(unsigned thd_ind, unsigned iteration)\n{\n\n\treturn (alloc_0(thd_ind*NALLOCS_PER_THREAD + iteration));\n}\n\nstatic void *\nthd_start(void *varg)\n{\n\tunsigned thd_ind = *(unsigned *)varg;\n\tsize_t bt_count_prev, bt_count;\n\tunsigned i_prev, i;\n\n\ti_prev = 0;\n\tbt_count_prev = 0;\n\tfor (i = 0; i < NALLOCS_PER_THREAD; i++) {\n\t\tvoid *p = alloc_from_permuted_backtrace(thd_ind, i);\n\t\tdallocx(p, 0);\n\t\tif (i % DUMP_INTERVAL == 0) {\n\t\t\tassert_d_eq(mallctl(\"prof.dump\", NULL, NULL, NULL, 0),\n\t\t\t    0, \"Unexpected error while dumping heap profile\");\n\t\t}\n\n\t\tif (i % BT_COUNT_CHECK_INTERVAL == 0 ||\n\t\t    i+1 == NALLOCS_PER_THREAD) {\n\t\t\tbt_count = prof_bt_count();\n\t\t\tassert_zu_le(bt_count_prev+(i-i_prev), bt_count,\n\t\t\t    \"Expected larger backtrace count increase\");\n\t\t\ti_prev = i;\n\t\t\tbt_count_prev = bt_count;\n\t\t}\n\t}\n\n\treturn (NULL);\n}\n\nTEST_BEGIN(test_idump)\n{\n\tbool active;\n\tthd_t thds[NTHREADS];\n\tunsigned thd_args[NTHREADS];\n\tunsigned i;\n\n\ttest_skip_if(!config_prof);\n\n\tactive = true;\n\tassert_d_eq(mallctl(\"prof.active\", NULL, NULL, &active, sizeof(active)),\n\t    0, \"Unexpected mallctl failure while activating profiling\");\n\n\tprof_dump_open = prof_dump_open_intercept;\n\n\tfor (i = 0; i < NTHREADS; i++) {\n\t\tthd_args[i] = i;\n\t\tthd_create(&thds[i], thd_start, (void *)&thd_args[i]);\n\t}\n\tfor (i = 0; i < NTHREADS; i++)\n\t\tthd_join(thds[i], NULL);\n}\nTEST_END\n\nint\nmain(void)\n{\n\n\treturn (test(\n\t    test_idump));\n}\n"
  },
  {
    "path": "extern/deprecated/redis-2.8.21/deps/jemalloc/test/unit/prof_accum.h",
    "content": "#include \"test/jemalloc_test.h\"\n\n#define\tNTHREADS\t\t4\n#define\tNALLOCS_PER_THREAD\t50\n#define\tDUMP_INTERVAL\t\t1\n#define\tBT_COUNT_CHECK_INTERVAL\t5\n\n#define\talloc_n_proto(n)\t\t\t\t\t\t\\\nvoid\t*alloc_##n(unsigned bits);\nalloc_n_proto(0)\nalloc_n_proto(1)\n\n#define\talloc_n_gen(n)\t\t\t\t\t\t\t\\\nvoid *\t\t\t\t\t\t\t\t\t\\\nalloc_##n(unsigned bits)\t\t\t\t\t\t\\\n{\t\t\t\t\t\t\t\t\t\\\n\tvoid *p;\t\t\t\t\t\t\t\\\n\t\t\t\t\t\t\t\t\t\\\n\tif (bits == 0)\t\t\t\t\t\t\t\\\n\t\tp = mallocx(1, 0);\t\t\t\t\t\\\n\telse {\t\t\t\t\t\t\t\t\\\n\t\tswitch (bits & 0x1U) {\t\t\t\t\t\\\n\t\tcase 0:\t\t\t\t\t\t\t\\\n\t\t\tp = (alloc_0(bits >> 1));\t\t\t\\\n\t\t\tbreak;\t\t\t\t\t\t\\\n\t\tcase 1:\t\t\t\t\t\t\t\\\n\t\t\tp = (alloc_1(bits >> 1));\t\t\t\\\n\t\t\tbreak;\t\t\t\t\t\t\\\n\t\tdefault: not_reached();\t\t\t\t\t\\\n\t\t}\t\t\t\t\t\t\t\\\n\t}\t\t\t\t\t\t\t\t\\\n\t/* Intentionally sabotage tail call optimization. */\t\t\\\n\tassert_ptr_not_null(p, \"Unexpected mallocx() failure\");\t\t\\\n\treturn (p);\t\t\t\t\t\t\t\\\n}\n"
  },
  {
    "path": "extern/deprecated/redis-2.8.21/deps/jemalloc/test/unit/prof_accum_a.c",
    "content": "#include \"prof_accum.h\"\n\nalloc_n_gen(0)\n"
  },
  {
    "path": "extern/deprecated/redis-2.8.21/deps/jemalloc/test/unit/prof_accum_b.c",
    "content": "#include \"prof_accum.h\"\n\nalloc_n_gen(1)\n"
  },
  {
    "path": "extern/deprecated/redis-2.8.21/deps/jemalloc/test/unit/prof_gdump.c",
    "content": "#include \"test/jemalloc_test.h\"\n\n#ifdef JEMALLOC_PROF\nconst char *malloc_conf = \"prof:true,prof_active:false,prof_gdump:true\";\n#endif\n\nstatic bool did_prof_dump_open;\n\nstatic int\nprof_dump_open_intercept(bool propagate_err, const char *filename)\n{\n\tint fd;\n\n\tdid_prof_dump_open = true;\n\n\tfd = open(\"/dev/null\", O_WRONLY);\n\tassert_d_ne(fd, -1, \"Unexpected open() failure\");\n\n\treturn (fd);\n}\n\nTEST_BEGIN(test_gdump)\n{\n\tbool active;\n\tvoid *p, *q;\n\n\ttest_skip_if(!config_prof);\n\n\tactive = true;\n\tassert_d_eq(mallctl(\"prof.active\", NULL, NULL, &active, sizeof(active)),\n\t    0, \"Unexpected mallctl failure while activating profiling\");\n\n\tprof_dump_open = prof_dump_open_intercept;\n\n\tdid_prof_dump_open = false;\n\tp = mallocx(chunksize, 0);\n\tassert_ptr_not_null(p, \"Unexpected mallocx() failure\");\n\tassert_true(did_prof_dump_open, \"Expected a profile dump\");\n\n\tdid_prof_dump_open = false;\n\tq = mallocx(chunksize, 0);\n\tassert_ptr_not_null(q, \"Unexpected mallocx() failure\");\n\tassert_true(did_prof_dump_open, \"Expected a profile dump\");\n\n\tdallocx(p, 0);\n\tdallocx(q, 0);\n}\nTEST_END\n\nint\nmain(void)\n{\n\n\treturn (test(\n\t    test_gdump));\n}\n"
  },
  {
    "path": "extern/deprecated/redis-2.8.21/deps/jemalloc/test/unit/prof_idump.c",
    "content": "#include \"test/jemalloc_test.h\"\n\n#ifdef JEMALLOC_PROF\nconst char *malloc_conf =\n    \"prof:true,prof_accum:true,prof_active:false,lg_prof_sample:0,\"\n    \"lg_prof_interval:0\";\n#endif\n\nstatic bool did_prof_dump_open;\n\nstatic int\nprof_dump_open_intercept(bool propagate_err, const char *filename)\n{\n\tint fd;\n\n\tdid_prof_dump_open = true;\n\n\tfd = open(\"/dev/null\", O_WRONLY);\n\tassert_d_ne(fd, -1, \"Unexpected open() failure\");\n\n\treturn (fd);\n}\n\nTEST_BEGIN(test_idump)\n{\n\tbool active;\n\tvoid *p;\n\n\ttest_skip_if(!config_prof);\n\n\tactive = true;\n\tassert_d_eq(mallctl(\"prof.active\", NULL, NULL, &active, sizeof(active)),\n\t    0, \"Unexpected mallctl failure while activating profiling\");\n\n\tprof_dump_open = prof_dump_open_intercept;\n\n\tdid_prof_dump_open = false;\n\tp = mallocx(1, 0);\n\tassert_ptr_not_null(p, \"Unexpected mallocx() failure\");\n\tdallocx(p, 0);\n\tassert_true(did_prof_dump_open, \"Expected a profile dump\");\n}\nTEST_END\n\nint\nmain(void)\n{\n\n\treturn (test(\n\t    test_idump));\n}\n"
  },
  {
    "path": "extern/deprecated/redis-2.8.21/deps/jemalloc/test/unit/ql.c",
    "content": "#include \"test/jemalloc_test.h\"\n\n/* Number of ring entries, in [2..26]. */\n#define\tNENTRIES 9\n\ntypedef struct list_s list_t;\ntypedef ql_head(list_t) list_head_t;\n\nstruct list_s {\n\tql_elm(list_t) link;\n\tchar id;\n};\n\nstatic void\ntest_empty_list(list_head_t *head)\n{\n\tlist_t *t;\n\tunsigned i;\n\n\tassert_ptr_null(ql_first(head), \"Unexpected element for empty list\");\n\tassert_ptr_null(ql_last(head, link),\n\t    \"Unexpected element for empty list\");\n\n\ti = 0;\n\tql_foreach(t, head, link) {\n\t\ti++;\n\t}\n\tassert_u_eq(i, 0, \"Unexpected element for empty list\");\n\n\ti = 0;\n\tql_reverse_foreach(t, head, link) {\n\t\ti++;\n\t}\n\tassert_u_eq(i, 0, \"Unexpected element for empty list\");\n}\n\nTEST_BEGIN(test_ql_empty)\n{\n\tlist_head_t head;\n\n\tql_new(&head);\n\ttest_empty_list(&head);\n}\nTEST_END\n\nstatic void\ninit_entries(list_t *entries, unsigned nentries)\n{\n\tunsigned i;\n\n\tfor (i = 0; i < nentries; i++) {\n\t\tentries[i].id = 'a' + i;\n\t\tql_elm_new(&entries[i], link);\n\t}\n}\n\nstatic void\ntest_entries_list(list_head_t *head, list_t *entries, unsigned nentries)\n{\n\tlist_t *t;\n\tunsigned i;\n\n\tassert_c_eq(ql_first(head)->id, entries[0].id, \"Element id mismatch\");\n\tassert_c_eq(ql_last(head, link)->id, entries[nentries-1].id,\n\t    \"Element id mismatch\");\n\n\ti = 0;\n\tql_foreach(t, head, link) {\n\t\tassert_c_eq(t->id, entries[i].id, \"Element id mismatch\");\n\t\ti++;\n\t}\n\n\ti = 0;\n\tql_reverse_foreach(t, head, link) {\n\t\tassert_c_eq(t->id, entries[nentries-i-1].id,\n\t\t    \"Element id mismatch\");\n\t\ti++;\n\t}\n\n\tfor (i = 0; i < nentries-1; i++) {\n\t\tt = ql_next(head, &entries[i], link);\n\t\tassert_c_eq(t->id, entries[i+1].id, \"Element id mismatch\");\n\t}\n\tassert_ptr_null(ql_next(head, &entries[nentries-1], link),\n\t    \"Unexpected element\");\n\n\tassert_ptr_null(ql_prev(head, &entries[0], link), \"Unexpected element\");\n\tfor (i = 1; i < nentries; i++) {\n\t\tt = ql_prev(head, &entries[i], link);\n\t\tassert_c_eq(t->id, entries[i-1].id, \"Element id mismatch\");\n\t}\n}\n\nTEST_BEGIN(test_ql_tail_insert)\n{\n\tlist_head_t head;\n\tlist_t entries[NENTRIES];\n\tunsigned i;\n\n\tql_new(&head);\n\tinit_entries(entries, sizeof(entries)/sizeof(list_t));\n\tfor (i = 0; i < NENTRIES; i++)\n\t\tql_tail_insert(&head, &entries[i], link);\n\n\ttest_entries_list(&head, entries, NENTRIES);\n}\nTEST_END\n\nTEST_BEGIN(test_ql_tail_remove)\n{\n\tlist_head_t head;\n\tlist_t entries[NENTRIES];\n\tunsigned i;\n\n\tql_new(&head);\n\tinit_entries(entries, sizeof(entries)/sizeof(list_t));\n\tfor (i = 0; i < NENTRIES; i++)\n\t\tql_tail_insert(&head, &entries[i], link);\n\n\tfor (i = 0; i < NENTRIES; i++) {\n\t\ttest_entries_list(&head, entries, NENTRIES-i);\n\t\tql_tail_remove(&head, list_t, link);\n\t}\n\ttest_empty_list(&head);\n}\nTEST_END\n\nTEST_BEGIN(test_ql_head_insert)\n{\n\tlist_head_t head;\n\tlist_t entries[NENTRIES];\n\tunsigned i;\n\n\tql_new(&head);\n\tinit_entries(entries, sizeof(entries)/sizeof(list_t));\n\tfor (i = 0; i < NENTRIES; i++)\n\t\tql_head_insert(&head, &entries[NENTRIES-i-1], link);\n\n\ttest_entries_list(&head, entries, NENTRIES);\n}\nTEST_END\n\nTEST_BEGIN(test_ql_head_remove)\n{\n\tlist_head_t head;\n\tlist_t entries[NENTRIES];\n\tunsigned i;\n\n\tql_new(&head);\n\tinit_entries(entries, sizeof(entries)/sizeof(list_t));\n\tfor (i = 0; i < NENTRIES; i++)\n\t\tql_head_insert(&head, &entries[NENTRIES-i-1], link);\n\n\tfor (i = 0; i < NENTRIES; i++) {\n\t\ttest_entries_list(&head, &entries[i], NENTRIES-i);\n\t\tql_head_remove(&head, list_t, link);\n\t}\n\ttest_empty_list(&head);\n}\nTEST_END\n\nTEST_BEGIN(test_ql_insert)\n{\n\tlist_head_t head;\n\tlist_t entries[8];\n\tlist_t *a, *b, *c, *d, *e, *f, *g, *h;\n\n\tql_new(&head);\n\tinit_entries(entries, sizeof(entries)/sizeof(list_t));\n\ta = &entries[0];\n\tb = &entries[1];\n\tc = &entries[2];\n\td = &entries[3];\n\te = &entries[4];\n\tf = &entries[5];\n\tg = &entries[6];\n\th = &entries[7];\n\n\t/*\n\t * ql_remove(), ql_before_insert(), and ql_after_insert() are used\n\t * internally by other macros that are already tested, so there's no\n\t * need to test them completely.  However, insertion/deletion from the\n\t * middle of lists is not otherwise tested; do so here.\n\t */\n\tql_tail_insert(&head, f, link);\n\tql_before_insert(&head, f, b, link);\n\tql_before_insert(&head, f, c, link);\n\tql_after_insert(f, h, link);\n\tql_after_insert(f, g, link);\n\tql_before_insert(&head, b, a, link);\n\tql_after_insert(c, d, link);\n\tql_before_insert(&head, f, e, link);\n\n\ttest_entries_list(&head, entries, sizeof(entries)/sizeof(list_t));\n}\nTEST_END\n\nint\nmain(void)\n{\n\n\treturn (test(\n\t    test_ql_empty,\n\t    test_ql_tail_insert,\n\t    test_ql_tail_remove,\n\t    test_ql_head_insert,\n\t    test_ql_head_remove,\n\t    test_ql_insert));\n}\n"
  },
  {
    "path": "extern/deprecated/redis-2.8.21/deps/jemalloc/test/unit/qr.c",
    "content": "#include \"test/jemalloc_test.h\"\n\n/* Number of ring entries, in [2..26]. */\n#define\tNENTRIES 9\n/* Split index, in [1..NENTRIES). */\n#define\tSPLIT_INDEX 5\n\ntypedef struct ring_s ring_t;\n\nstruct ring_s {\n\tqr(ring_t) link;\n\tchar id;\n};\n\nstatic void\ninit_entries(ring_t *entries)\n{\n\tunsigned i;\n\n\tfor (i = 0; i < NENTRIES; i++) {\n\t\tqr_new(&entries[i], link);\n\t\tentries[i].id = 'a' + i;\n\t}\n}\n\nstatic void\ntest_independent_entries(ring_t *entries)\n{\n\tring_t *t;\n\tunsigned i, j;\n\n\tfor (i = 0; i < NENTRIES; i++) {\n\t\tj = 0;\n\t\tqr_foreach(t, &entries[i], link) {\n\t\t\tj++;\n\t\t}\n\t\tassert_u_eq(j, 1,\n\t\t    \"Iteration over single-element ring should visit precisely \"\n\t\t    \"one element\");\n\t}\n\tfor (i = 0; i < NENTRIES; i++) {\n\t\tj = 0;\n\t\tqr_reverse_foreach(t, &entries[i], link) {\n\t\t\tj++;\n\t\t}\n\t\tassert_u_eq(j, 1,\n\t\t    \"Iteration over single-element ring should visit precisely \"\n\t\t    \"one element\");\n\t}\n\tfor (i = 0; i < NENTRIES; i++) {\n\t\tt = qr_next(&entries[i], link);\n\t\tassert_ptr_eq(t, &entries[i],\n\t\t    \"Next element in single-element ring should be same as \"\n\t\t    \"current element\");\n\t}\n\tfor (i = 0; i < NENTRIES; i++) {\n\t\tt = qr_prev(&entries[i], link);\n\t\tassert_ptr_eq(t, &entries[i],\n\t\t    \"Previous element in single-element ring should be same as \"\n\t\t    \"current element\");\n\t}\n}\n\nTEST_BEGIN(test_qr_one)\n{\n\tring_t entries[NENTRIES];\n\n\tinit_entries(entries);\n\ttest_independent_entries(entries);\n}\nTEST_END\n\nstatic void\ntest_entries_ring(ring_t *entries)\n{\n\tring_t *t;\n\tunsigned i, j;\n\n\tfor (i = 0; i < NENTRIES; i++) {\n\t\tj = 0;\n\t\tqr_foreach(t, &entries[i], link) {\n\t\t\tassert_c_eq(t->id, entries[(i+j) % NENTRIES].id,\n\t\t\t    \"Element id mismatch\");\n\t\t\tj++;\n\t\t}\n\t}\n\tfor (i = 0; i < NENTRIES; i++) {\n\t\tj = 0;\n\t\tqr_reverse_foreach(t, &entries[i], link) {\n\t\t\tassert_c_eq(t->id, entries[(NENTRIES+i-j-1) %\n\t\t\t    NENTRIES].id, \"Element id mismatch\");\n\t\t\tj++;\n\t\t}\n\t}\n\tfor (i = 0; i < NENTRIES; i++) {\n\t\tt = qr_next(&entries[i], link);\n\t\tassert_c_eq(t->id, entries[(i+1) % NENTRIES].id,\n\t\t    \"Element id mismatch\");\n\t}\n\tfor (i = 0; i < NENTRIES; i++) {\n\t\tt = qr_prev(&entries[i], link);\n\t\tassert_c_eq(t->id, entries[(NENTRIES+i-1) % NENTRIES].id,\n\t\t    \"Element id mismatch\");\n\t}\n}\n\nTEST_BEGIN(test_qr_after_insert)\n{\n\tring_t entries[NENTRIES];\n\tunsigned i;\n\n\tinit_entries(entries);\n\tfor (i = 1; i < NENTRIES; i++)\n\t\tqr_after_insert(&entries[i - 1], &entries[i], link);\n\ttest_entries_ring(entries);\n}\nTEST_END\n\nTEST_BEGIN(test_qr_remove)\n{\n\tring_t entries[NENTRIES];\n\tring_t *t;\n\tunsigned i, j;\n\n\tinit_entries(entries);\n\tfor (i = 1; i < NENTRIES; i++)\n\t\tqr_after_insert(&entries[i - 1], &entries[i], link);\n\n\tfor (i = 0; i < NENTRIES; i++) {\n\t\tj = 0;\n\t\tqr_foreach(t, &entries[i], link) {\n\t\t\tassert_c_eq(t->id, entries[i+j].id,\n\t\t\t    \"Element id mismatch\");\n\t\t\tj++;\n\t\t}\n\t\tj = 0;\n\t\tqr_reverse_foreach(t, &entries[i], link) {\n\t\t\tassert_c_eq(t->id, entries[NENTRIES - 1 - j].id,\n\t\t\t\"Element id mismatch\");\n\t\t\tj++;\n\t\t}\n\t\tqr_remove(&entries[i], link);\n\t}\n\ttest_independent_entries(entries);\n}\nTEST_END\n\nTEST_BEGIN(test_qr_before_insert)\n{\n\tring_t entries[NENTRIES];\n\tring_t *t;\n\tunsigned i, j;\n\n\tinit_entries(entries);\n\tfor (i = 1; i < NENTRIES; i++)\n\t\tqr_before_insert(&entries[i - 1], &entries[i], link);\n\tfor (i = 0; i < NENTRIES; i++) {\n\t\tj = 0;\n\t\tqr_foreach(t, &entries[i], link) {\n\t\t\tassert_c_eq(t->id, entries[(NENTRIES+i-j) %\n\t\t\t    NENTRIES].id, \"Element id mismatch\");\n\t\t\tj++;\n\t\t}\n\t}\n\tfor (i = 0; i < NENTRIES; i++) {\n\t\tj = 0;\n\t\tqr_reverse_foreach(t, &entries[i], link) {\n\t\t\tassert_c_eq(t->id, entries[(i+j+1) % NENTRIES].id,\n\t\t\t    \"Element id mismatch\");\n\t\t\tj++;\n\t\t}\n\t}\n\tfor (i = 0; i < NENTRIES; i++) {\n\t\tt = qr_next(&entries[i], link);\n\t\tassert_c_eq(t->id, entries[(NENTRIES+i-1) % NENTRIES].id,\n\t\t    \"Element id mismatch\");\n\t}\n\tfor (i = 0; i < NENTRIES; i++) {\n\t\tt = qr_prev(&entries[i], link);\n\t\tassert_c_eq(t->id, entries[(i+1) % NENTRIES].id,\n\t\t    \"Element id mismatch\");\n\t}\n}\nTEST_END\n\nstatic void\ntest_split_entries(ring_t *entries)\n{\n\tring_t *t;\n\tunsigned i, j;\n\n\tfor (i = 0; i < NENTRIES; i++) {\n\t\tj = 0;\n\t\tqr_foreach(t, &entries[i], link) {\n\t\t\tif (i < SPLIT_INDEX) {\n\t\t\t\tassert_c_eq(t->id,\n\t\t\t\t    entries[(i+j) % SPLIT_INDEX].id,\n\t\t\t\t    \"Element id mismatch\");\n\t\t\t} else {\n\t\t\t\tassert_c_eq(t->id, entries[(i+j-SPLIT_INDEX) %\n\t\t\t\t    (NENTRIES-SPLIT_INDEX) + SPLIT_INDEX].id,\n\t\t\t\t    \"Element id mismatch\");\n\t\t\t}\n\t\t\tj++;\n\t\t}\n\t}\n}\n\nTEST_BEGIN(test_qr_meld_split)\n{\n\tring_t entries[NENTRIES];\n\tunsigned i;\n\n\tinit_entries(entries);\n\tfor (i = 1; i < NENTRIES; i++)\n\t\tqr_after_insert(&entries[i - 1], &entries[i], link);\n\n\tqr_split(&entries[0], &entries[SPLIT_INDEX], link);\n\ttest_split_entries(entries);\n\n\tqr_meld(&entries[0], &entries[SPLIT_INDEX], link);\n\ttest_entries_ring(entries);\n\n\tqr_meld(&entries[0], &entries[SPLIT_INDEX], link);\n\ttest_split_entries(entries);\n\n\tqr_split(&entries[0], &entries[SPLIT_INDEX], link);\n\ttest_entries_ring(entries);\n\n\tqr_split(&entries[0], &entries[0], link);\n\ttest_entries_ring(entries);\n\n\tqr_meld(&entries[0], &entries[0], link);\n\ttest_entries_ring(entries);\n}\nTEST_END\n\nint\nmain(void)\n{\n\n\treturn (test(\n\t    test_qr_one,\n\t    test_qr_after_insert,\n\t    test_qr_remove,\n\t    test_qr_before_insert,\n\t    test_qr_meld_split));\n}\n"
  },
  {
    "path": "extern/deprecated/redis-2.8.21/deps/jemalloc/test/unit/quarantine.c",
    "content": "#include \"test/jemalloc_test.h\"\n\n#define\tQUARANTINE_SIZE\t\t8192\n#define\tSTRINGIFY_HELPER(x)\t#x\n#define\tSTRINGIFY(x)\t\tSTRINGIFY_HELPER(x)\n\n#ifdef JEMALLOC_FILL\nconst char *malloc_conf = \"abort:false,junk:true,redzone:true,quarantine:\"\n    STRINGIFY(QUARANTINE_SIZE);\n#endif\n\nvoid\nquarantine_clear(void)\n{\n\tvoid *p;\n\n\tp = mallocx(QUARANTINE_SIZE*2, 0);\n\tassert_ptr_not_null(p, \"Unexpected mallocx() failure\");\n\tdallocx(p, 0);\n}\n\nTEST_BEGIN(test_quarantine)\n{\n#define\tSZ\t\tZU(256)\n#define\tNQUARANTINED\t(QUARANTINE_SIZE/SZ)\n\tvoid *quarantined[NQUARANTINED+1];\n\tsize_t i, j;\n\n\ttest_skip_if(!config_fill);\n\n\tassert_zu_eq(nallocx(SZ, 0), SZ,\n\t    \"SZ=%zu does not precisely equal a size class\", SZ);\n\n\tquarantine_clear();\n\n\t/*\n\t * Allocate enough regions to completely fill the quarantine, plus one\n\t * more.  The last iteration occurs with a completely full quarantine,\n\t * but no regions should be drained from the quarantine until the last\n\t * deallocation occurs.  Therefore no region recycling should occur\n\t * until after this loop completes.\n\t */\n\tfor (i = 0; i < NQUARANTINED+1; i++) {\n\t\tvoid *p = mallocx(SZ, 0);\n\t\tassert_ptr_not_null(p, \"Unexpected mallocx() failure\");\n\t\tquarantined[i] = p;\n\t\tdallocx(p, 0);\n\t\tfor (j = 0; j < i; j++) {\n\t\t\tassert_ptr_ne(p, quarantined[j],\n\t\t\t    \"Quarantined region recycled too early; \"\n\t\t\t    \"i=%zu, j=%zu\", i, j);\n\t\t}\n\t}\n#undef NQUARANTINED\n#undef SZ\n}\nTEST_END\n\nstatic bool detected_redzone_corruption;\n\nstatic void\narena_redzone_corruption_replacement(void *ptr, size_t usize, bool after,\n    size_t offset, uint8_t byte)\n{\n\n\tdetected_redzone_corruption = true;\n}\n\nTEST_BEGIN(test_quarantine_redzone)\n{\n\tchar *s;\n\tarena_redzone_corruption_t *arena_redzone_corruption_orig;\n\n\ttest_skip_if(!config_fill);\n\n\tarena_redzone_corruption_orig = arena_redzone_corruption;\n\tarena_redzone_corruption = arena_redzone_corruption_replacement;\n\n\t/* Test underflow. */\n\tdetected_redzone_corruption = false;\n\ts = (char *)mallocx(1, 0);\n\tassert_ptr_not_null((void *)s, \"Unexpected mallocx() failure\");\n\ts[-1] = 0xbb;\n\tdallocx(s, 0);\n\tassert_true(detected_redzone_corruption,\n\t    \"Did not detect redzone corruption\");\n\n\t/* Test overflow. */\n\tdetected_redzone_corruption = false;\n\ts = (char *)mallocx(1, 0);\n\tassert_ptr_not_null((void *)s, \"Unexpected mallocx() failure\");\n\ts[sallocx(s, 0)] = 0xbb;\n\tdallocx(s, 0);\n\tassert_true(detected_redzone_corruption,\n\t    \"Did not detect redzone corruption\");\n\n\tarena_redzone_corruption = arena_redzone_corruption_orig;\n}\nTEST_END\n\nint\nmain(void)\n{\n\n\treturn (test(\n\t    test_quarantine,\n\t    test_quarantine_redzone));\n}\n"
  },
  {
    "path": "extern/deprecated/redis-2.8.21/deps/jemalloc/test/unit/rb.c",
    "content": "#include \"test/jemalloc_test.h\"\n\n#define\trbtn_black_height(a_type, a_field, a_rbt, r_height) do {\t\\\n    a_type *rbp_bh_t;\t\t\t\t\t\t\t\\\n    for (rbp_bh_t = (a_rbt)->rbt_root, (r_height) = 0;\t\t\t\\\n      rbp_bh_t != &(a_rbt)->rbt_nil;\t\t\t\t\t\\\n      rbp_bh_t = rbtn_left_get(a_type, a_field, rbp_bh_t)) {\t\t\\\n\tif (rbtn_red_get(a_type, a_field, rbp_bh_t) == false) {\t\t\\\n\t    (r_height)++;\t\t\t\t\t\t\\\n\t}\t\t\t\t\t\t\t\t\\\n    }\t\t\t\t\t\t\t\t\t\\\n} while (0)\n\ntypedef struct node_s node_t;\n\nstruct node_s {\n#define\tNODE_MAGIC 0x9823af7e\n\tuint32_t magic;\n\trb_node(node_t) link;\n\tuint64_t key;\n};\n\nstatic int\nnode_cmp(node_t *a, node_t *b) {\n\tint ret;\n\n\tassert_u32_eq(a->magic, NODE_MAGIC, \"Bad magic\");\n\tassert_u32_eq(b->magic, NODE_MAGIC, \"Bad magic\");\n\n\tret = (a->key > b->key) - (a->key < b->key);\n\tif (ret == 0) {\n\t\t/*\n\t\t * Duplicates are not allowed in the tree, so force an\n\t\t * arbitrary ordering for non-identical items with equal keys.\n\t\t */\n\t\tret = (((uintptr_t)a) > ((uintptr_t)b))\n\t\t    - (((uintptr_t)a) < ((uintptr_t)b));\n\t}\n\treturn (ret);\n}\n\ntypedef rb_tree(node_t) tree_t;\nrb_gen(static, tree_, tree_t, node_t, link, node_cmp);\n\nTEST_BEGIN(test_rb_empty)\n{\n\ttree_t tree;\n\tnode_t key;\n\n\ttree_new(&tree);\n\n\tassert_ptr_null(tree_first(&tree), \"Unexpected node\");\n\tassert_ptr_null(tree_last(&tree), \"Unexpected node\");\n\n\tkey.key = 0;\n\tkey.magic = NODE_MAGIC;\n\tassert_ptr_null(tree_search(&tree, &key), \"Unexpected node\");\n\n\tkey.key = 0;\n\tkey.magic = NODE_MAGIC;\n\tassert_ptr_null(tree_nsearch(&tree, &key), \"Unexpected node\");\n\n\tkey.key = 0;\n\tkey.magic = NODE_MAGIC;\n\tassert_ptr_null(tree_psearch(&tree, &key), \"Unexpected node\");\n}\nTEST_END\n\nstatic unsigned\ntree_recurse(node_t *node, unsigned black_height, unsigned black_depth,\n    node_t *nil)\n{\n\tunsigned ret = 0;\n\tnode_t *left_node = rbtn_left_get(node_t, link, node);\n\tnode_t *right_node = rbtn_right_get(node_t, link, node);\n\n\tif (rbtn_red_get(node_t, link, node) == false)\n\t\tblack_depth++;\n\n\t/* Red nodes must be interleaved with black nodes. */\n\tif (rbtn_red_get(node_t, link, node)) {\n\t\tassert_false(rbtn_red_get(node_t, link, left_node),\n\t\t    \"Node should be black\");\n\t\tassert_false(rbtn_red_get(node_t, link, right_node),\n\t\t    \"Node should be black\");\n\t}\n\n\tif (node == nil)\n\t\treturn (ret);\n\t/* Self. */\n\tassert_u32_eq(node->magic, NODE_MAGIC, \"Bad magic\");\n\n\t/* Left subtree. */\n\tif (left_node != nil)\n\t\tret += tree_recurse(left_node, black_height, black_depth, nil);\n\telse\n\t\tret += (black_depth != black_height);\n\n\t/* Right subtree. */\n\tif (right_node != nil)\n\t\tret += tree_recurse(right_node, black_height, black_depth, nil);\n\telse\n\t\tret += (black_depth != black_height);\n\n\treturn (ret);\n}\n\nstatic node_t *\ntree_iterate_cb(tree_t *tree, node_t *node, void *data)\n{\n\tunsigned *i = (unsigned *)data;\n\tnode_t *search_node;\n\n\tassert_u32_eq(node->magic, NODE_MAGIC, \"Bad magic\");\n\n\t/* Test rb_search(). */\n\tsearch_node = tree_search(tree, node);\n\tassert_ptr_eq(search_node, node,\n\t    \"tree_search() returned unexpected node\");\n\n\t/* Test rb_nsearch(). */\n\tsearch_node = tree_nsearch(tree, node);\n\tassert_ptr_eq(search_node, node,\n\t    \"tree_nsearch() returned unexpected node\");\n\n\t/* Test rb_psearch(). */\n\tsearch_node = tree_psearch(tree, node);\n\tassert_ptr_eq(search_node, node,\n\t    \"tree_psearch() returned unexpected node\");\n\n\t(*i)++;\n\n\treturn (NULL);\n}\n\nstatic unsigned\ntree_iterate(tree_t *tree)\n{\n\tunsigned i;\n\n\ti = 0;\n\ttree_iter(tree, NULL, tree_iterate_cb, (void *)&i);\n\n\treturn (i);\n}\n\nstatic unsigned\ntree_iterate_reverse(tree_t *tree)\n{\n\tunsigned i;\n\n\ti = 0;\n\ttree_reverse_iter(tree, NULL, tree_iterate_cb, (void *)&i);\n\n\treturn (i);\n}\n\nstatic void\nnode_remove(tree_t *tree, node_t *node, unsigned nnodes)\n{\n\tnode_t *search_node;\n\tunsigned black_height, imbalances;\n\n\ttree_remove(tree, node);\n\n\t/* Test rb_nsearch(). */\n\tsearch_node = tree_nsearch(tree, node);\n\tif (search_node != NULL) {\n\t\tassert_u64_ge(search_node->key, node->key,\n\t\t    \"Key ordering error\");\n\t}\n\n\t/* Test rb_psearch(). */\n\tsearch_node = tree_psearch(tree, node);\n\tif (search_node != NULL) {\n\t\tassert_u64_le(search_node->key, node->key,\n\t\t    \"Key ordering error\");\n\t}\n\n\tnode->magic = 0;\n\n\trbtn_black_height(node_t, link, tree, black_height);\n\timbalances = tree_recurse(tree->rbt_root, black_height, 0,\n\t    &(tree->rbt_nil));\n\tassert_u_eq(imbalances, 0, \"Tree is unbalanced\");\n\tassert_u_eq(tree_iterate(tree), nnodes-1,\n\t    \"Unexpected node iteration count\");\n\tassert_u_eq(tree_iterate_reverse(tree), nnodes-1,\n\t    \"Unexpected node iteration count\");\n}\n\nstatic node_t *\nremove_iterate_cb(tree_t *tree, node_t *node, void *data)\n{\n\tunsigned *nnodes = (unsigned *)data;\n\tnode_t *ret = tree_next(tree, node);\n\n\tnode_remove(tree, node, *nnodes);\n\n\treturn (ret);\n}\n\nstatic node_t *\nremove_reverse_iterate_cb(tree_t *tree, node_t *node, void *data)\n{\n\tunsigned *nnodes = (unsigned *)data;\n\tnode_t *ret = tree_prev(tree, node);\n\n\tnode_remove(tree, node, *nnodes);\n\n\treturn (ret);\n}\n\nTEST_BEGIN(test_rb_random)\n{\n#define\tNNODES 25\n#define\tNBAGS 250\n#define\tSEED 42\n\tsfmt_t *sfmt;\n\tuint64_t bag[NNODES];\n\ttree_t tree;\n\tnode_t nodes[NNODES];\n\tunsigned i, j, k, black_height, imbalances;\n\n\tsfmt = init_gen_rand(SEED);\n\tfor (i = 0; i < NBAGS; i++) {\n\t\tswitch (i) {\n\t\tcase 0:\n\t\t\t/* Insert in order. */\n\t\t\tfor (j = 0; j < NNODES; j++)\n\t\t\t\tbag[j] = j;\n\t\t\tbreak;\n\t\tcase 1:\n\t\t\t/* Insert in reverse order. */\n\t\t\tfor (j = 0; j < NNODES; j++)\n\t\t\t\tbag[j] = NNODES - j - 1;\n\t\t\tbreak;\n\t\tdefault:\n\t\t\tfor (j = 0; j < NNODES; j++)\n\t\t\t\tbag[j] = gen_rand64_range(sfmt, NNODES);\n\t\t}\n\n\t\tfor (j = 1; j <= NNODES; j++) {\n\t\t\t/* Initialize tree and nodes. */\n\t\t\ttree_new(&tree);\n\t\t\ttree.rbt_nil.magic = 0;\n\t\t\tfor (k = 0; k < j; k++) {\n\t\t\t\tnodes[k].magic = NODE_MAGIC;\n\t\t\t\tnodes[k].key = bag[k];\n\t\t\t}\n\n\t\t\t/* Insert nodes. */\n\t\t\tfor (k = 0; k < j; k++) {\n\t\t\t\ttree_insert(&tree, &nodes[k]);\n\n\t\t\t\trbtn_black_height(node_t, link, &tree,\n\t\t\t\t    black_height);\n\t\t\t\timbalances = tree_recurse(tree.rbt_root,\n\t\t\t\t    black_height, 0, &(tree.rbt_nil));\n\t\t\t\tassert_u_eq(imbalances, 0,\n\t\t\t\t    \"Tree is unbalanced\");\n\n\t\t\t\tassert_u_eq(tree_iterate(&tree), k+1,\n\t\t\t\t    \"Unexpected node iteration count\");\n\t\t\t\tassert_u_eq(tree_iterate_reverse(&tree), k+1,\n\t\t\t\t    \"Unexpected node iteration count\");\n\n\t\t\t\tassert_ptr_not_null(tree_first(&tree),\n\t\t\t\t    \"Tree should not be empty\");\n\t\t\t\tassert_ptr_not_null(tree_last(&tree),\n\t\t\t\t    \"Tree should not be empty\");\n\n\t\t\t\ttree_next(&tree, &nodes[k]);\n\t\t\t\ttree_prev(&tree, &nodes[k]);\n\t\t\t}\n\n\t\t\t/* Remove nodes. */\n\t\t\tswitch (i % 4) {\n\t\t\tcase 0:\n\t\t\t\tfor (k = 0; k < j; k++)\n\t\t\t\t\tnode_remove(&tree, &nodes[k], j - k);\n\t\t\t\tbreak;\n\t\t\tcase 1:\n\t\t\t\tfor (k = j; k > 0; k--)\n\t\t\t\t\tnode_remove(&tree, &nodes[k-1], k);\n\t\t\t\tbreak;\n\t\t\tcase 2: {\n\t\t\t\tnode_t *start;\n\t\t\t\tunsigned nnodes = j;\n\n\t\t\t\tstart = NULL;\n\t\t\t\tdo {\n\t\t\t\t\tstart = tree_iter(&tree, start,\n\t\t\t\t\t    remove_iterate_cb, (void *)&nnodes);\n\t\t\t\t\tnnodes--;\n\t\t\t\t} while (start != NULL);\n\t\t\t\tassert_u_eq(nnodes, 0,\n\t\t\t\t    \"Removal terminated early\");\n\t\t\t\tbreak;\n\t\t\t} case 3: {\n\t\t\t\tnode_t *start;\n\t\t\t\tunsigned nnodes = j;\n\n\t\t\t\tstart = NULL;\n\t\t\t\tdo {\n\t\t\t\t\tstart = tree_reverse_iter(&tree, start,\n\t\t\t\t\t    remove_reverse_iterate_cb,\n\t\t\t\t\t    (void *)&nnodes);\n\t\t\t\t\tnnodes--;\n\t\t\t\t} while (start != NULL);\n\t\t\t\tassert_u_eq(nnodes, 0,\n\t\t\t\t    \"Removal terminated early\");\n\t\t\t\tbreak;\n\t\t\t} default:\n\t\t\t\tnot_reached();\n\t\t\t}\n\t\t}\n\t}\n\tfini_gen_rand(sfmt);\n#undef NNODES\n#undef NBAGS\n#undef SEED\n}\nTEST_END\n\nint\nmain(void)\n{\n\n\treturn (test(\n\t    test_rb_empty,\n\t    test_rb_random));\n}\n"
  },
  {
    "path": "extern/deprecated/redis-2.8.21/deps/jemalloc/test/unit/rtree.c",
    "content": "#include \"test/jemalloc_test.h\"\n\nTEST_BEGIN(test_rtree_get_empty)\n{\n\tunsigned i;\n\n\tfor (i = 1; i <= (sizeof(uintptr_t) << 3); i++) {\n\t\trtree_t *rtree = rtree_new(i, imalloc, idalloc);\n\t\tassert_u_eq(rtree_get(rtree, 0), 0,\n\t\t    \"rtree_get() should return NULL for empty tree\");\n\t\trtree_delete(rtree);\n\t}\n}\nTEST_END\n\nTEST_BEGIN(test_rtree_extrema)\n{\n\tunsigned i;\n\n\tfor (i = 1; i <= (sizeof(uintptr_t) << 3); i++) {\n\t\trtree_t *rtree = rtree_new(i, imalloc, idalloc);\n\n\t\trtree_set(rtree, 0, 1);\n\t\tassert_u_eq(rtree_get(rtree, 0), 1,\n\t\t    \"rtree_get() should return previously set value\");\n\n\t\trtree_set(rtree, ~((uintptr_t)0), 1);\n\t\tassert_u_eq(rtree_get(rtree, ~((uintptr_t)0)), 1,\n\t\t    \"rtree_get() should return previously set value\");\n\n\t\trtree_delete(rtree);\n\t}\n}\nTEST_END\n\nTEST_BEGIN(test_rtree_bits)\n{\n\tunsigned i, j, k;\n\n\tfor (i = 1; i < (sizeof(uintptr_t) << 3); i++) {\n\t\tuintptr_t keys[] = {0, 1,\n\t\t    (((uintptr_t)1) << (sizeof(uintptr_t)*8-i)) - 1};\n\t\trtree_t *rtree = rtree_new(i, imalloc, idalloc);\n\n\t\tfor (j = 0; j < sizeof(keys)/sizeof(uintptr_t); j++) {\n\t\t\trtree_set(rtree, keys[j], 1);\n\t\t\tfor (k = 0; k < sizeof(keys)/sizeof(uintptr_t); k++) {\n\t\t\t\tassert_u_eq(rtree_get(rtree, keys[k]), 1,\n\t\t\t\t    \"rtree_get() should return previously set \"\n\t\t\t\t    \"value and ignore insignificant key bits; \"\n\t\t\t\t    \"i=%u, j=%u, k=%u, set key=%#\"PRIxPTR\", \"\n\t\t\t\t    \"get key=%#\"PRIxPTR, i, j, k, keys[j],\n\t\t\t\t    keys[k]);\n\t\t\t}\n\t\t\tassert_u_eq(rtree_get(rtree,\n\t\t\t    (((uintptr_t)1) << (sizeof(uintptr_t)*8-i))), 0,\n\t\t\t    \"Only leftmost rtree leaf should be set; \"\n\t\t\t    \"i=%u, j=%u\", i, j);\n\t\t\trtree_set(rtree, keys[j], 0);\n\t\t}\n\n\t\trtree_delete(rtree);\n\t}\n}\nTEST_END\n\nTEST_BEGIN(test_rtree_random)\n{\n\tunsigned i;\n\tsfmt_t *sfmt;\n#define\tNSET 100\n#define\tSEED 42\n\n\tsfmt = init_gen_rand(SEED);\n\tfor (i = 1; i <= (sizeof(uintptr_t) << 3); i++) {\n\t\trtree_t *rtree = rtree_new(i, imalloc, idalloc);\n\t\tuintptr_t keys[NSET];\n\t\tunsigned j;\n\n\t\tfor (j = 0; j < NSET; j++) {\n\t\t\tkeys[j] = (uintptr_t)gen_rand64(sfmt);\n\t\t\trtree_set(rtree, keys[j], 1);\n\t\t\tassert_u_eq(rtree_get(rtree, keys[j]), 1,\n\t\t\t    \"rtree_get() should return previously set value\");\n\t\t}\n\t\tfor (j = 0; j < NSET; j++) {\n\t\t\tassert_u_eq(rtree_get(rtree, keys[j]), 1,\n\t\t\t    \"rtree_get() should return previously set value\");\n\t\t}\n\n\t\tfor (j = 0; j < NSET; j++) {\n\t\t\trtree_set(rtree, keys[j], 0);\n\t\t\tassert_u_eq(rtree_get(rtree, keys[j]), 0,\n\t\t\t    \"rtree_get() should return previously set value\");\n\t\t}\n\t\tfor (j = 0; j < NSET; j++) {\n\t\t\tassert_u_eq(rtree_get(rtree, keys[j]), 0,\n\t\t\t    \"rtree_get() should return previously set value\");\n\t\t}\n\n\t\trtree_delete(rtree);\n\t}\n\tfini_gen_rand(sfmt);\n#undef NSET\n#undef SEED\n}\nTEST_END\n\nint\nmain(void)\n{\n\n\treturn (test(\n\t    test_rtree_get_empty,\n\t    test_rtree_extrema,\n\t    test_rtree_bits,\n\t    test_rtree_random));\n}\n"
  },
  {
    "path": "extern/deprecated/redis-2.8.21/deps/jemalloc/test/unit/stats.c",
    "content": "#include \"test/jemalloc_test.h\"\n\nTEST_BEGIN(test_stats_summary)\n{\n\tsize_t *cactive;\n\tsize_t sz, allocated, active, mapped;\n\tint expected = config_stats ? 0 : ENOENT;\n\n\tsz = sizeof(cactive);\n\tassert_d_eq(mallctl(\"stats.cactive\", &cactive, &sz, NULL, 0), expected,\n\t    \"Unexpected mallctl() result\");\n\n\tsz = sizeof(size_t);\n\tassert_d_eq(mallctl(\"stats.allocated\", &allocated, &sz, NULL, 0),\n\t    expected, \"Unexpected mallctl() result\");\n\tassert_d_eq(mallctl(\"stats.active\", &active, &sz, NULL, 0), expected,\n\t    \"Unexpected mallctl() result\");\n\tassert_d_eq(mallctl(\"stats.mapped\", &mapped, &sz, NULL, 0), expected,\n\t    \"Unexpected mallctl() result\");\n\n\tif (config_stats) {\n\t\tassert_zu_le(active, *cactive,\n\t\t    \"active should be no larger than cactive\");\n\t\tassert_zu_le(allocated, active,\n\t\t    \"allocated should be no larger than active\");\n\t\tassert_zu_le(active, mapped,\n\t\t    \"active should be no larger than mapped\");\n\t}\n}\nTEST_END\n\nTEST_BEGIN(test_stats_chunks)\n{\n\tsize_t current, high;\n\tuint64_t total;\n\tsize_t sz;\n\tint expected = config_stats ? 0 : ENOENT;\n\n\tsz = sizeof(size_t);\n\tassert_d_eq(mallctl(\"stats.chunks.current\", &current, &sz, NULL, 0),\n\t    expected, \"Unexpected mallctl() result\");\n\tsz = sizeof(uint64_t);\n\tassert_d_eq(mallctl(\"stats.chunks.total\", &total, &sz, NULL, 0),\n\t    expected, \"Unexpected mallctl() result\");\n\tsz = sizeof(size_t);\n\tassert_d_eq(mallctl(\"stats.chunks.high\", &high, &sz, NULL, 0), expected,\n\t    \"Unexpected mallctl() result\");\n\n\tif (config_stats) {\n\t\tassert_zu_le(current, high,\n\t\t    \"current should be no larger than high\");\n\t\tassert_u64_le((uint64_t)high, total,\n\t\t    \"high should be no larger than total\");\n\t}\n}\nTEST_END\n\nTEST_BEGIN(test_stats_huge)\n{\n\tvoid *p;\n\tuint64_t epoch;\n\tsize_t allocated;\n\tuint64_t nmalloc, ndalloc;\n\tsize_t sz;\n\tint expected = config_stats ? 0 : ENOENT;\n\n\tp = mallocx(arena_maxclass+1, 0);\n\tassert_ptr_not_null(p, \"Unexpected mallocx() failure\");\n\n\tassert_d_eq(mallctl(\"epoch\", NULL, NULL, &epoch, sizeof(epoch)), 0,\n\t    \"Unexpected mallctl() failure\");\n\n\tsz = sizeof(size_t);\n\tassert_d_eq(mallctl(\"stats.huge.allocated\", &allocated, &sz, NULL, 0),\n\t    expected, \"Unexpected mallctl() result\");\n\tsz = sizeof(uint64_t);\n\tassert_d_eq(mallctl(\"stats.huge.nmalloc\", &nmalloc, &sz, NULL, 0),\n\t    expected, \"Unexpected mallctl() result\");\n\tassert_d_eq(mallctl(\"stats.huge.ndalloc\", &ndalloc, &sz, NULL, 0),\n\t    expected, \"Unexpected mallctl() result\");\n\n\tif (config_stats) {\n\t\tassert_zu_gt(allocated, 0,\n\t\t    \"allocated should be greater than zero\");\n\t\tassert_u64_ge(nmalloc, ndalloc,\n\t\t    \"nmalloc should be at least as large as ndalloc\");\n\t}\n\n\tdallocx(p, 0);\n}\nTEST_END\n\nTEST_BEGIN(test_stats_arenas_summary)\n{\n\tunsigned arena;\n\tvoid *small, *large;\n\tuint64_t epoch;\n\tsize_t sz;\n\tint expected = config_stats ? 0 : ENOENT;\n\tsize_t mapped;\n\tuint64_t npurge, nmadvise, purged;\n\n\tarena = 0;\n\tassert_d_eq(mallctl(\"thread.arena\", NULL, NULL, &arena, sizeof(arena)),\n\t    0, \"Unexpected mallctl() failure\");\n\n\tsmall = mallocx(SMALL_MAXCLASS, 0);\n\tassert_ptr_not_null(small, \"Unexpected mallocx() failure\");\n\tlarge = mallocx(arena_maxclass, 0);\n\tassert_ptr_not_null(large, \"Unexpected mallocx() failure\");\n\n\tassert_d_eq(mallctl(\"arena.0.purge\", NULL, NULL, NULL, 0), 0,\n\t    \"Unexpected mallctl() failure\");\n\n\tassert_d_eq(mallctl(\"epoch\", NULL, NULL, &epoch, sizeof(epoch)), 0,\n\t    \"Unexpected mallctl() failure\");\n\n\tsz = sizeof(size_t);\n\tassert_d_eq(mallctl(\"stats.arenas.0.mapped\", &mapped, &sz, NULL, 0),\n\t    expected, \"Unexepected mallctl() result\");\n\tsz = sizeof(uint64_t);\n\tassert_d_eq(mallctl(\"stats.arenas.0.npurge\", &npurge, &sz, NULL, 0),\n\t    expected, \"Unexepected mallctl() result\");\n\tassert_d_eq(mallctl(\"stats.arenas.0.nmadvise\", &nmadvise, &sz, NULL, 0),\n\t    expected, \"Unexepected mallctl() result\");\n\tassert_d_eq(mallctl(\"stats.arenas.0.purged\", &purged, &sz, NULL, 0),\n\t    expected, \"Unexepected mallctl() result\");\n\n\tif (config_stats) {\n\t\tassert_u64_gt(npurge, 0,\n\t\t    \"At least one purge should have occurred\");\n\t\tassert_u64_le(nmadvise, purged,\n\t\t    \"nmadvise should be no greater than purged\");\n\t}\n\n\tdallocx(small, 0);\n\tdallocx(large, 0);\n}\nTEST_END\n\nvoid *\nthd_start(void *arg)\n{\n\n\treturn (NULL);\n}\n\nstatic void\nno_lazy_lock(void)\n{\n\tthd_t thd;\n\n\tthd_create(&thd, thd_start, NULL);\n\tthd_join(thd, NULL);\n}\n\nTEST_BEGIN(test_stats_arenas_small)\n{\n\tunsigned arena;\n\tvoid *p;\n\tsize_t sz, allocated;\n\tuint64_t epoch, nmalloc, ndalloc, nrequests;\n\tint expected = config_stats ? 0 : ENOENT;\n\n\tno_lazy_lock(); /* Lazy locking would dodge tcache testing. */\n\n\tarena = 0;\n\tassert_d_eq(mallctl(\"thread.arena\", NULL, NULL, &arena, sizeof(arena)),\n\t    0, \"Unexpected mallctl() failure\");\n\n\tp = mallocx(SMALL_MAXCLASS, 0);\n\tassert_ptr_not_null(p, \"Unexpected mallocx() failure\");\n\n\tassert_d_eq(mallctl(\"thread.tcache.flush\", NULL, NULL, NULL, 0),\n\t    config_tcache ? 0 : ENOENT, \"Unexpected mallctl() result\");\n\n\tassert_d_eq(mallctl(\"epoch\", NULL, NULL, &epoch, sizeof(epoch)), 0,\n\t    \"Unexpected mallctl() failure\");\n\n\tsz = sizeof(size_t);\n\tassert_d_eq(mallctl(\"stats.arenas.0.small.allocated\", &allocated, &sz,\n\t    NULL, 0), expected, \"Unexpected mallctl() result\");\n\tsz = sizeof(uint64_t);\n\tassert_d_eq(mallctl(\"stats.arenas.0.small.nmalloc\", &nmalloc, &sz,\n\t    NULL, 0), expected, \"Unexpected mallctl() result\");\n\tassert_d_eq(mallctl(\"stats.arenas.0.small.ndalloc\", &ndalloc, &sz,\n\t    NULL, 0), expected, \"Unexpected mallctl() result\");\n\tassert_d_eq(mallctl(\"stats.arenas.0.small.nrequests\", &nrequests, &sz,\n\t    NULL, 0), expected, \"Unexpected mallctl() result\");\n\n\tif (config_stats) {\n\t\tassert_zu_gt(allocated, 0,\n\t\t    \"allocated should be greater than zero\");\n\t\tassert_u64_gt(nmalloc, 0,\n\t\t    \"nmalloc should be no greater than zero\");\n\t\tassert_u64_ge(nmalloc, ndalloc,\n\t\t    \"nmalloc should be at least as large as ndalloc\");\n\t\tassert_u64_gt(nrequests, 0,\n\t\t    \"nrequests should be greater than zero\");\n\t}\n\n\tdallocx(p, 0);\n}\nTEST_END\n\nTEST_BEGIN(test_stats_arenas_large)\n{\n\tunsigned arena;\n\tvoid *p;\n\tsize_t sz, allocated;\n\tuint64_t epoch, nmalloc, ndalloc, nrequests;\n\tint expected = config_stats ? 0 : ENOENT;\n\n\tarena = 0;\n\tassert_d_eq(mallctl(\"thread.arena\", NULL, NULL, &arena, sizeof(arena)),\n\t    0, \"Unexpected mallctl() failure\");\n\n\tp = mallocx(arena_maxclass, 0);\n\tassert_ptr_not_null(p, \"Unexpected mallocx() failure\");\n\n\tassert_d_eq(mallctl(\"epoch\", NULL, NULL, &epoch, sizeof(epoch)), 0,\n\t    \"Unexpected mallctl() failure\");\n\n\tsz = sizeof(size_t);\n\tassert_d_eq(mallctl(\"stats.arenas.0.large.allocated\", &allocated, &sz,\n\t    NULL, 0), expected, \"Unexpected mallctl() result\");\n\tsz = sizeof(uint64_t);\n\tassert_d_eq(mallctl(\"stats.arenas.0.large.nmalloc\", &nmalloc, &sz,\n\t    NULL, 0), expected, \"Unexpected mallctl() result\");\n\tassert_d_eq(mallctl(\"stats.arenas.0.large.ndalloc\", &ndalloc, &sz,\n\t    NULL, 0), expected, \"Unexpected mallctl() result\");\n\tassert_d_eq(mallctl(\"stats.arenas.0.large.nrequests\", &nrequests, &sz,\n\t    NULL, 0), expected, \"Unexpected mallctl() result\");\n\n\tif (config_stats) {\n\t\tassert_zu_gt(allocated, 0,\n\t\t    \"allocated should be greater than zero\");\n\t\tassert_zu_gt(nmalloc, 0,\n\t\t    \"nmalloc should be greater than zero\");\n\t\tassert_zu_ge(nmalloc, ndalloc,\n\t\t    \"nmalloc should be at least as large as ndalloc\");\n\t\tassert_zu_gt(nrequests, 0,\n\t\t    \"nrequests should be greater than zero\");\n\t}\n\n\tdallocx(p, 0);\n}\nTEST_END\n\nTEST_BEGIN(test_stats_arenas_bins)\n{\n\tunsigned arena;\n\tvoid *p;\n\tsize_t sz, allocated, curruns;\n\tuint64_t epoch, nmalloc, ndalloc, nrequests, nfills, nflushes;\n\tuint64_t nruns, nreruns;\n\tint expected = config_stats ? 0 : ENOENT;\n\n\tarena = 0;\n\tassert_d_eq(mallctl(\"thread.arena\", NULL, NULL, &arena, sizeof(arena)),\n\t    0, \"Unexpected mallctl() failure\");\n\n\tp = mallocx(arena_bin_info[0].reg_size, 0);\n\tassert_ptr_not_null(p, \"Unexpected mallocx() failure\");\n\n\tassert_d_eq(mallctl(\"thread.tcache.flush\", NULL, NULL, NULL, 0),\n\t    config_tcache ? 0 : ENOENT, \"Unexpected mallctl() result\");\n\n\tassert_d_eq(mallctl(\"epoch\", NULL, NULL, &epoch, sizeof(epoch)), 0,\n\t    \"Unexpected mallctl() failure\");\n\n\tsz = sizeof(size_t);\n\tassert_d_eq(mallctl(\"stats.arenas.0.bins.0.allocated\", &allocated, &sz,\n\t    NULL, 0), expected, \"Unexpected mallctl() result\");\n\tsz = sizeof(uint64_t);\n\tassert_d_eq(mallctl(\"stats.arenas.0.bins.0.nmalloc\", &nmalloc, &sz,\n\t    NULL, 0), expected, \"Unexpected mallctl() result\");\n\tassert_d_eq(mallctl(\"stats.arenas.0.bins.0.ndalloc\", &ndalloc, &sz,\n\t    NULL, 0), expected, \"Unexpected mallctl() result\");\n\tassert_d_eq(mallctl(\"stats.arenas.0.bins.0.nrequests\", &nrequests, &sz,\n\t    NULL, 0), expected, \"Unexpected mallctl() result\");\n\n\tassert_d_eq(mallctl(\"stats.arenas.0.bins.0.nfills\", &nfills, &sz,\n\t    NULL, 0), config_tcache ? expected : ENOENT,\n\t    \"Unexpected mallctl() result\");\n\tassert_d_eq(mallctl(\"stats.arenas.0.bins.0.nflushes\", &nflushes, &sz,\n\t    NULL, 0), config_tcache ? expected : ENOENT,\n\t    \"Unexpected mallctl() result\");\n\n\tassert_d_eq(mallctl(\"stats.arenas.0.bins.0.nruns\", &nruns, &sz,\n\t    NULL, 0), expected, \"Unexpected mallctl() result\");\n\tassert_d_eq(mallctl(\"stats.arenas.0.bins.0.nreruns\", &nreruns, &sz,\n\t    NULL, 0), expected, \"Unexpected mallctl() result\");\n\tsz = sizeof(size_t);\n\tassert_d_eq(mallctl(\"stats.arenas.0.bins.0.curruns\", &curruns, &sz,\n\t    NULL, 0), expected, \"Unexpected mallctl() result\");\n\n\tif (config_stats) {\n\t\tassert_zu_gt(allocated, 0,\n\t\t    \"allocated should be greater than zero\");\n\t\tassert_u64_gt(nmalloc, 0,\n\t\t    \"nmalloc should be greater than zero\");\n\t\tassert_u64_ge(nmalloc, ndalloc,\n\t\t    \"nmalloc should be at least as large as ndalloc\");\n\t\tassert_u64_gt(nrequests, 0,\n\t\t    \"nrequests should be greater than zero\");\n\t\tif (config_tcache) {\n\t\t\tassert_u64_gt(nfills, 0,\n\t\t\t    \"At least one fill should have occurred\");\n\t\t\tassert_u64_gt(nflushes, 0,\n\t\t\t    \"At least one flush should have occurred\");\n\t\t}\n\t\tassert_u64_gt(nruns, 0,\n\t\t    \"At least one run should have been allocated\");\n\t\tassert_zu_gt(curruns, 0,\n\t\t    \"At least one run should be currently allocated\");\n\t}\n\n\tdallocx(p, 0);\n}\nTEST_END\n\nTEST_BEGIN(test_stats_arenas_lruns)\n{\n\tunsigned arena;\n\tvoid *p;\n\tuint64_t epoch, nmalloc, ndalloc, nrequests;\n\tsize_t curruns, sz;\n\tint expected = config_stats ? 0 : ENOENT;\n\n\tarena = 0;\n\tassert_d_eq(mallctl(\"thread.arena\", NULL, NULL, &arena, sizeof(arena)),\n\t    0, \"Unexpected mallctl() failure\");\n\n\tp = mallocx(SMALL_MAXCLASS+1, 0);\n\tassert_ptr_not_null(p, \"Unexpected mallocx() failure\");\n\n\tassert_d_eq(mallctl(\"epoch\", NULL, NULL, &epoch, sizeof(epoch)), 0,\n\t    \"Unexpected mallctl() failure\");\n\n\tsz = sizeof(uint64_t);\n\tassert_d_eq(mallctl(\"stats.arenas.0.lruns.0.nmalloc\", &nmalloc, &sz,\n\t    NULL, 0), expected, \"Unexpected mallctl() result\");\n\tassert_d_eq(mallctl(\"stats.arenas.0.lruns.0.ndalloc\", &ndalloc, &sz,\n\t    NULL, 0), expected, \"Unexpected mallctl() result\");\n\tassert_d_eq(mallctl(\"stats.arenas.0.lruns.0.nrequests\", &nrequests, &sz,\n\t    NULL, 0), expected, \"Unexpected mallctl() result\");\n\tsz = sizeof(size_t);\n\tassert_d_eq(mallctl(\"stats.arenas.0.lruns.0.curruns\", &curruns, &sz,\n\t    NULL, 0), expected, \"Unexpected mallctl() result\");\n\n\tif (config_stats) {\n\t\tassert_u64_gt(nmalloc, 0,\n\t\t    \"nmalloc should be greater than zero\");\n\t\tassert_u64_ge(nmalloc, ndalloc,\n\t\t    \"nmalloc should be at least as large as ndalloc\");\n\t\tassert_u64_gt(nrequests, 0,\n\t\t    \"nrequests should be greater than zero\");\n\t\tassert_u64_gt(curruns, 0,\n\t\t    \"At least one run should be currently allocated\");\n\t}\n\n\tdallocx(p, 0);\n}\nTEST_END\n\nint\nmain(void)\n{\n\n\treturn (test(\n\t    test_stats_summary,\n\t    test_stats_chunks,\n\t    test_stats_huge,\n\t    test_stats_arenas_summary,\n\t    test_stats_arenas_small,\n\t    test_stats_arenas_large,\n\t    test_stats_arenas_bins,\n\t    test_stats_arenas_lruns));\n}\n"
  },
  {
    "path": "extern/deprecated/redis-2.8.21/deps/jemalloc/test/unit/tsd.c",
    "content": "#include \"test/jemalloc_test.h\"\n\n#define\tTHREAD_DATA 0x72b65c10\n\ntypedef unsigned int data_t;\n\nstatic bool data_cleanup_executed;\n\nvoid\ndata_cleanup(void *arg)\n{\n\tdata_t *data = (data_t *)arg;\n\n\tassert_x_eq(*data, THREAD_DATA,\n\t    \"Argument passed into cleanup function should match tsd value\");\n\tdata_cleanup_executed = true;\n}\n\nmalloc_tsd_protos(, data, data_t)\nmalloc_tsd_externs(data, data_t)\n#define\tDATA_INIT 0x12345678\nmalloc_tsd_data(, data, data_t, DATA_INIT)\nmalloc_tsd_funcs(, data, data_t, DATA_INIT, data_cleanup)\n\nstatic void *\nthd_start(void *arg)\n{\n\tdata_t d = (data_t)(uintptr_t)arg;\n\tassert_x_eq(*data_tsd_get(), DATA_INIT,\n\t    \"Initial tsd get should return initialization value\");\n\n\tdata_tsd_set(&d);\n\tassert_x_eq(*data_tsd_get(), d,\n\t    \"After tsd set, tsd get should return value that was set\");\n\n\td = 0;\n\tassert_x_eq(*data_tsd_get(), (data_t)(uintptr_t)arg,\n\t    \"Resetting local data should have no effect on tsd\");\n\n\treturn (NULL);\n}\n\nTEST_BEGIN(test_tsd_main_thread)\n{\n\n\tthd_start((void *) 0xa5f3e329);\n}\nTEST_END\n\nTEST_BEGIN(test_tsd_sub_thread)\n{\n\tthd_t thd;\n\n\tdata_cleanup_executed = false;\n\tthd_create(&thd, thd_start, (void *)THREAD_DATA);\n\tthd_join(thd, NULL);\n\tassert_true(data_cleanup_executed,\n\t    \"Cleanup function should have executed\");\n}\nTEST_END\n\nint\nmain(void)\n{\n\n\tdata_tsd_boot();\n\n\treturn (test(\n\t    test_tsd_main_thread,\n\t    test_tsd_sub_thread));\n}\n"
  },
  {
    "path": "extern/deprecated/redis-2.8.21/deps/jemalloc/test/unit/util.c",
    "content": "#include \"test/jemalloc_test.h\"\n\nTEST_BEGIN(test_pow2_ceil)\n{\n\tunsigned i, pow2;\n\tsize_t x;\n\n\tassert_zu_eq(pow2_ceil(0), 0, \"Unexpected result\");\n\n\tfor (i = 0; i < sizeof(size_t) * 8; i++) {\n\t\tassert_zu_eq(pow2_ceil(ZU(1) << i), ZU(1) << i,\n\t\t    \"Unexpected result\");\n\t}\n\n\tfor (i = 2; i < sizeof(size_t) * 8; i++) {\n\t\tassert_zu_eq(pow2_ceil((ZU(1) << i) - 1), ZU(1) << i,\n\t\t    \"Unexpected result\");\n\t}\n\n\tfor (i = 0; i < sizeof(size_t) * 8 - 1; i++) {\n\t\tassert_zu_eq(pow2_ceil((ZU(1) << i) + 1), ZU(1) << (i+1),\n\t\t    \"Unexpected result\");\n\t}\n\n\tfor (pow2 = 1; pow2 < 25; pow2++) {\n\t\tfor (x = (ZU(1) << (pow2-1)) + 1; x <= ZU(1) << pow2; x++) {\n\t\t\tassert_zu_eq(pow2_ceil(x), ZU(1) << pow2,\n\t\t\t    \"Unexpected result, x=%zu\", x);\n\t\t}\n\t}\n}\nTEST_END\n\nTEST_BEGIN(test_malloc_strtoumax_no_endptr)\n{\n\tint err;\n\n\tset_errno(0);\n\tassert_ju_eq(malloc_strtoumax(\"0\", NULL, 0), 0, \"Unexpected result\");\n\terr = get_errno();\n\tassert_d_eq(err, 0, \"Unexpected failure\");\n}\nTEST_END\n\nTEST_BEGIN(test_malloc_strtoumax)\n{\n\tstruct test_s {\n\t\tconst char *input;\n\t\tconst char *expected_remainder;\n\t\tint base;\n\t\tint expected_errno;\n\t\tconst char *expected_errno_name;\n\t\tuintmax_t expected_x;\n\t};\n#define\tERR(e)\te, #e\n#define\tUMAX(x)\t((uintmax_t)x##ULL)\n\tstruct test_s tests[] = {\n\t\t{\"0\",\t\t\"0\",\t-1,\tERR(EINVAL),\tUINTMAX_MAX},\n\t\t{\"0\",\t\t\"0\",\t1,\tERR(EINVAL),\tUINTMAX_MAX},\n\t\t{\"0\",\t\t\"0\",\t37,\tERR(EINVAL),\tUINTMAX_MAX},\n\n\t\t{\"\",\t\t\"\",\t0,\tERR(EINVAL),\tUINTMAX_MAX},\n\t\t{\"+\",\t\t\"+\",\t0,\tERR(EINVAL),\tUINTMAX_MAX},\n\t\t{\"++3\",\t\t\"++3\",\t0,\tERR(EINVAL),\tUINTMAX_MAX},\n\t\t{\"-\",\t\t\"-\",\t0,\tERR(EINVAL),\tUINTMAX_MAX},\n\n\t\t{\"42\",\t\t\"\",\t0,\tERR(0),\t\tUMAX(42)},\n\t\t{\"+42\",\t\t\"\",\t0,\tERR(0),\t\tUMAX(42)},\n\t\t{\"-42\",\t\t\"\",\t0,\tERR(0),\t\tUMAX(-42)},\n\t\t{\"042\",\t\t\"\",\t0,\tERR(0),\t\tUMAX(042)},\n\t\t{\"+042\",\t\"\",\t0,\tERR(0),\t\tUMAX(042)},\n\t\t{\"-042\",\t\"\",\t0,\tERR(0),\t\tUMAX(-042)},\n\t\t{\"0x42\",\t\"\",\t0,\tERR(0),\t\tUMAX(0x42)},\n\t\t{\"+0x42\",\t\"\",\t0,\tERR(0),\t\tUMAX(0x42)},\n\t\t{\"-0x42\",\t\"\",\t0,\tERR(0),\t\tUMAX(-0x42)},\n\n\t\t{\"0\",\t\t\"\",\t0,\tERR(0),\t\tUMAX(0)},\n\t\t{\"1\",\t\t\"\",\t0,\tERR(0),\t\tUMAX(1)},\n\n\t\t{\"42\",\t\t\"\",\t0,\tERR(0),\t\tUMAX(42)},\n\t\t{\" 42\",\t\t\"\",\t0,\tERR(0),\t\tUMAX(42)},\n\t\t{\"42 \",\t\t\" \",\t0,\tERR(0),\t\tUMAX(42)},\n\t\t{\"0x\",\t\t\"x\",\t0,\tERR(0),\t\tUMAX(0)},\n\t\t{\"42x\",\t\t\"x\",\t0,\tERR(0),\t\tUMAX(42)},\n\n\t\t{\"07\",\t\t\"\",\t0,\tERR(0),\t\tUMAX(7)},\n\t\t{\"010\",\t\t\"\",\t0,\tERR(0),\t\tUMAX(8)},\n\t\t{\"08\",\t\t\"8\",\t0,\tERR(0),\t\tUMAX(0)},\n\t\t{\"0_\",\t\t\"_\",\t0,\tERR(0),\t\tUMAX(0)},\n\n\t\t{\"0x\",\t\t\"x\",\t0,\tERR(0),\t\tUMAX(0)},\n\t\t{\"0X\",\t\t\"X\",\t0,\tERR(0),\t\tUMAX(0)},\n\t\t{\"0xg\",\t\t\"xg\",\t0,\tERR(0),\t\tUMAX(0)},\n\t\t{\"0XA\",\t\t\"\",\t0,\tERR(0),\t\tUMAX(10)},\n\n\t\t{\"010\",\t\t\"\",\t10,\tERR(0),\t\tUMAX(10)},\n\t\t{\"0x3\",\t\t\"x3\",\t10,\tERR(0),\t\tUMAX(0)},\n\n\t\t{\"12\",\t\t\"2\",\t2,\tERR(0),\t\tUMAX(1)},\n\t\t{\"78\",\t\t\"8\",\t8,\tERR(0),\t\tUMAX(7)},\n\t\t{\"9a\",\t\t\"a\",\t10,\tERR(0),\t\tUMAX(9)},\n\t\t{\"9A\",\t\t\"A\",\t10,\tERR(0),\t\tUMAX(9)},\n\t\t{\"fg\",\t\t\"g\",\t16,\tERR(0),\t\tUMAX(15)},\n\t\t{\"FG\",\t\t\"G\",\t16,\tERR(0),\t\tUMAX(15)},\n\t\t{\"0xfg\",\t\"g\",\t16,\tERR(0),\t\tUMAX(15)},\n\t\t{\"0XFG\",\t\"G\",\t16,\tERR(0),\t\tUMAX(15)},\n\t\t{\"z_\",\t\t\"_\",\t36,\tERR(0),\t\tUMAX(35)},\n\t\t{\"Z_\",\t\t\"_\",\t36,\tERR(0),\t\tUMAX(35)}\n\t};\n#undef ERR\n#undef UMAX\n\tunsigned i;\n\n\tfor (i = 0; i < sizeof(tests)/sizeof(struct test_s); i++) {\n\t\tstruct test_s *test = &tests[i];\n\t\tint err;\n\t\tuintmax_t result;\n\t\tchar *remainder;\n\n\t\tset_errno(0);\n\t\tresult = malloc_strtoumax(test->input, &remainder, test->base);\n\t\terr = get_errno();\n\t\tassert_d_eq(err, test->expected_errno,\n\t\t    \"Expected errno %s for \\\"%s\\\", base %d\",\n\t\t    test->expected_errno_name, test->input, test->base);\n\t\tassert_str_eq(remainder, test->expected_remainder,\n\t\t    \"Unexpected remainder for \\\"%s\\\", base %d\",\n\t\t    test->input, test->base);\n\t\tif (err == 0) {\n\t\t\tassert_ju_eq(result, test->expected_x,\n\t\t\t    \"Unexpected result for \\\"%s\\\", base %d\",\n\t\t\t    test->input, test->base);\n\t\t}\n\t}\n}\nTEST_END\n\nTEST_BEGIN(test_malloc_snprintf_truncated)\n{\n#define\tBUFLEN\t15\n\tchar buf[BUFLEN];\n\tint result;\n\tsize_t len;\n#define TEST(expected_str_untruncated, fmt...) do {\t\t\t\\\n\tresult = malloc_snprintf(buf, len, fmt);\t\t\t\\\n\tassert_d_eq(strncmp(buf, expected_str_untruncated, len-1), 0,\t\\\n\t    \"Unexpected string inequality (\\\"%s\\\" vs \\\"%s\\\")\",\t\t\\\n\t    buf, expected_str_untruncated);\t\t\\\n\tassert_d_eq(result, strlen(expected_str_untruncated),\t\t\\\n\t    \"Unexpected result\");\t\t\t\t\t\\\n} while (0)\n\n\tfor (len = 1; len < BUFLEN; len++) {\n\t\tTEST(\"012346789\",\t\"012346789\");\n\t\tTEST(\"a0123b\",\t\t\"a%sb\", \"0123\");\n\t\tTEST(\"a01234567\",\t\"a%s%s\", \"0123\", \"4567\");\n\t\tTEST(\"a0123  \",\t\t\"a%-6s\", \"0123\");\n\t\tTEST(\"a  0123\",\t\t\"a%6s\", \"0123\");\n\t\tTEST(\"a   012\",\t\t\"a%6.3s\", \"0123\");\n\t\tTEST(\"a   012\",\t\t\"a%*.*s\", 6, 3, \"0123\");\n\t\tTEST(\"a 123b\",\t\t\"a% db\", 123);\n\t\tTEST(\"a123b\",\t\t\"a%-db\", 123);\n\t\tTEST(\"a-123b\",\t\t\"a%-db\", -123);\n\t\tTEST(\"a+123b\",\t\t\"a%+db\", 123);\n\t}\n#undef BUFLEN\n#undef TEST\n}\nTEST_END\n\nTEST_BEGIN(test_malloc_snprintf)\n{\n#define\tBUFLEN\t128\n\tchar buf[BUFLEN];\n\tint result;\n#define\tTEST(expected_str, fmt...) do {\t\t\t\t\t\\\n\tresult = malloc_snprintf(buf, sizeof(buf), fmt);\t\t\\\n\tassert_str_eq(buf, expected_str, \"Unexpected output\");\t\t\\\n\tassert_d_eq(result, strlen(expected_str), \"Unexpected result\");\t\\\n} while (0)\n\n\tTEST(\"hello\", \"hello\");\n\n\tTEST(\"50%, 100%\", \"50%%, %d%%\", 100);\n\n\tTEST(\"a0123b\", \"a%sb\", \"0123\");\n\n\tTEST(\"a 0123b\", \"a%5sb\", \"0123\");\n\tTEST(\"a 0123b\", \"a%*sb\", 5, \"0123\");\n\n\tTEST(\"a0123 b\", \"a%-5sb\", \"0123\");\n\tTEST(\"a0123b\", \"a%*sb\", -1, \"0123\");\n\tTEST(\"a0123 b\", \"a%*sb\", -5, \"0123\");\n\tTEST(\"a0123 b\", \"a%-*sb\", -5, \"0123\");\n\n\tTEST(\"a012b\", \"a%.3sb\", \"0123\");\n\tTEST(\"a012b\", \"a%.*sb\", 3, \"0123\");\n\tTEST(\"a0123b\", \"a%.*sb\", -3, \"0123\");\n\n\tTEST(\"a  012b\", \"a%5.3sb\", \"0123\");\n\tTEST(\"a  012b\", \"a%5.*sb\", 3, \"0123\");\n\tTEST(\"a  012b\", \"a%*.3sb\", 5, \"0123\");\n\tTEST(\"a  012b\", \"a%*.*sb\", 5, 3, \"0123\");\n\tTEST(\"a 0123b\", \"a%*.*sb\", 5, -3, \"0123\");\n\n\tTEST(\"_abcd_\", \"_%x_\", 0xabcd);\n\tTEST(\"_0xabcd_\", \"_%#x_\", 0xabcd);\n\tTEST(\"_1234_\", \"_%o_\", 01234);\n\tTEST(\"_01234_\", \"_%#o_\", 01234);\n\tTEST(\"_1234_\", \"_%u_\", 1234);\n\n\tTEST(\"_1234_\", \"_%d_\", 1234);\n\tTEST(\"_ 1234_\", \"_% d_\", 1234);\n\tTEST(\"_+1234_\", \"_%+d_\", 1234);\n\tTEST(\"_-1234_\", \"_%d_\", -1234);\n\tTEST(\"_-1234_\", \"_% d_\", -1234);\n\tTEST(\"_-1234_\", \"_%+d_\", -1234);\n\n\tTEST(\"_-1234_\", \"_%d_\", -1234);\n\tTEST(\"_1234_\", \"_%d_\", 1234);\n\tTEST(\"_-1234_\", \"_%i_\", -1234);\n\tTEST(\"_1234_\", \"_%i_\", 1234);\n\tTEST(\"_01234_\", \"_%#o_\", 01234);\n\tTEST(\"_1234_\", \"_%u_\", 1234);\n\tTEST(\"_0x1234abc_\", \"_%#x_\", 0x1234abc);\n\tTEST(\"_0X1234ABC_\", \"_%#X_\", 0x1234abc);\n\tTEST(\"_c_\", \"_%c_\", 'c');\n\tTEST(\"_string_\", \"_%s_\", \"string\");\n\tTEST(\"_0x42_\", \"_%p_\", ((void *)0x42));\n\n\tTEST(\"_-1234_\", \"_%ld_\", ((long)-1234));\n\tTEST(\"_1234_\", \"_%ld_\", ((long)1234));\n\tTEST(\"_-1234_\", \"_%li_\", ((long)-1234));\n\tTEST(\"_1234_\", \"_%li_\", ((long)1234));\n\tTEST(\"_01234_\", \"_%#lo_\", ((long)01234));\n\tTEST(\"_1234_\", \"_%lu_\", ((long)1234));\n\tTEST(\"_0x1234abc_\", \"_%#lx_\", ((long)0x1234abc));\n\tTEST(\"_0X1234ABC_\", \"_%#lX_\", ((long)0x1234ABC));\n\n\tTEST(\"_-1234_\", \"_%lld_\", ((long long)-1234));\n\tTEST(\"_1234_\", \"_%lld_\", ((long long)1234));\n\tTEST(\"_-1234_\", \"_%lli_\", ((long long)-1234));\n\tTEST(\"_1234_\", \"_%lli_\", ((long long)1234));\n\tTEST(\"_01234_\", \"_%#llo_\", ((long long)01234));\n\tTEST(\"_1234_\", \"_%llu_\", ((long long)1234));\n\tTEST(\"_0x1234abc_\", \"_%#llx_\", ((long long)0x1234abc));\n\tTEST(\"_0X1234ABC_\", \"_%#llX_\", ((long long)0x1234ABC));\n\n\tTEST(\"_-1234_\", \"_%qd_\", ((long long)-1234));\n\tTEST(\"_1234_\", \"_%qd_\", ((long long)1234));\n\tTEST(\"_-1234_\", \"_%qi_\", ((long long)-1234));\n\tTEST(\"_1234_\", \"_%qi_\", ((long long)1234));\n\tTEST(\"_01234_\", \"_%#qo_\", ((long long)01234));\n\tTEST(\"_1234_\", \"_%qu_\", ((long long)1234));\n\tTEST(\"_0x1234abc_\", \"_%#qx_\", ((long long)0x1234abc));\n\tTEST(\"_0X1234ABC_\", \"_%#qX_\", ((long long)0x1234ABC));\n\n\tTEST(\"_-1234_\", \"_%jd_\", ((intmax_t)-1234));\n\tTEST(\"_1234_\", \"_%jd_\", ((intmax_t)1234));\n\tTEST(\"_-1234_\", \"_%ji_\", ((intmax_t)-1234));\n\tTEST(\"_1234_\", \"_%ji_\", ((intmax_t)1234));\n\tTEST(\"_01234_\", \"_%#jo_\", ((intmax_t)01234));\n\tTEST(\"_1234_\", \"_%ju_\", ((intmax_t)1234));\n\tTEST(\"_0x1234abc_\", \"_%#jx_\", ((intmax_t)0x1234abc));\n\tTEST(\"_0X1234ABC_\", \"_%#jX_\", ((intmax_t)0x1234ABC));\n\n\tTEST(\"_1234_\", \"_%td_\", ((ptrdiff_t)1234));\n\tTEST(\"_-1234_\", \"_%td_\", ((ptrdiff_t)-1234));\n\tTEST(\"_1234_\", \"_%ti_\", ((ptrdiff_t)1234));\n\tTEST(\"_-1234_\", \"_%ti_\", ((ptrdiff_t)-1234));\n\n\tTEST(\"_-1234_\", \"_%zd_\", ((ssize_t)-1234));\n\tTEST(\"_1234_\", \"_%zd_\", ((ssize_t)1234));\n\tTEST(\"_-1234_\", \"_%zi_\", ((ssize_t)-1234));\n\tTEST(\"_1234_\", \"_%zi_\", ((ssize_t)1234));\n\tTEST(\"_01234_\", \"_%#zo_\", ((ssize_t)01234));\n\tTEST(\"_1234_\", \"_%zu_\", ((ssize_t)1234));\n\tTEST(\"_0x1234abc_\", \"_%#zx_\", ((ssize_t)0x1234abc));\n\tTEST(\"_0X1234ABC_\", \"_%#zX_\", ((ssize_t)0x1234ABC));\n#undef BUFLEN\n}\nTEST_END\n\nint\nmain(void)\n{\n\n\treturn (test(\n\t    test_pow2_ceil,\n\t    test_malloc_strtoumax_no_endptr,\n\t    test_malloc_strtoumax,\n\t    test_malloc_snprintf_truncated,\n\t    test_malloc_snprintf));\n}\n"
  },
  {
    "path": "extern/deprecated/redis-2.8.21/deps/jemalloc/test/unit/zero.c",
    "content": "#include \"test/jemalloc_test.h\"\n\n#ifdef JEMALLOC_FILL\nconst char *malloc_conf =\n    \"abort:false,junk:false,zero:true,redzone:false,quarantine:0\";\n#endif\n\nstatic void\ntest_zero(size_t sz_min, size_t sz_max)\n{\n\tchar *s;\n\tsize_t sz_prev, sz, i;\n\n\tsz_prev = 0;\n\ts = (char *)mallocx(sz_min, 0);\n\tassert_ptr_not_null((void *)s, \"Unexpected mallocx() failure\");\n\n\tfor (sz = sallocx(s, 0); sz <= sz_max;\n\t    sz_prev = sz, sz = sallocx(s, 0)) {\n\t\tif (sz_prev > 0) {\n\t\t\tassert_c_eq(s[0], 'a',\n\t\t\t    \"Previously allocated byte %zu/%zu is corrupted\",\n\t\t\t    ZU(0), sz_prev);\n\t\t\tassert_c_eq(s[sz_prev-1], 'a',\n\t\t\t    \"Previously allocated byte %zu/%zu is corrupted\",\n\t\t\t    sz_prev-1, sz_prev);\n\t\t}\n\n\t\tfor (i = sz_prev; i < sz; i++) {\n\t\t\tassert_c_eq(s[i], 0x0,\n\t\t\t    \"Newly allocated byte %zu/%zu isn't zero-filled\",\n\t\t\t    i, sz);\n\t\t\ts[i] = 'a';\n\t\t}\n\n\t\tif (xallocx(s, sz+1, 0, 0) == sz) {\n\t\t\ts = (char *)rallocx(s, sz+1, 0);\n\t\t\tassert_ptr_not_null((void *)s,\n\t\t\t    \"Unexpected rallocx() failure\");\n\t\t}\n\t}\n\n\tdallocx(s, 0);\n}\n\nTEST_BEGIN(test_zero_small)\n{\n\n\ttest_skip_if(!config_fill);\n\ttest_zero(1, SMALL_MAXCLASS-1);\n}\nTEST_END\n\nTEST_BEGIN(test_zero_large)\n{\n\n\ttest_skip_if(!config_fill);\n\ttest_zero(SMALL_MAXCLASS+1, arena_maxclass);\n}\nTEST_END\n\nTEST_BEGIN(test_zero_huge)\n{\n\n\ttest_skip_if(!config_fill);\n\ttest_zero(arena_maxclass+1, chunksize*2);\n}\nTEST_END\n\nint\nmain(void)\n{\n\n\treturn (test(\n\t    test_zero_small,\n\t    test_zero_large,\n\t    test_zero_huge));\n}\n"
  },
  {
    "path": "extern/deprecated/redis-2.8.21/deps/linenoise/.gitignore",
    "content": "linenoise_example\n*.dSYM\nhistory.txt\n"
  },
  {
    "path": "extern/deprecated/redis-2.8.21/deps/linenoise/Makefile",
    "content": "STD=\nWARN= -Wall\nOPT= -Os\n\nR_CFLAGS= $(STD) $(WARN) $(OPT) $(DEBUG) $(CFLAGS)\nR_LDFLAGS= $(LDFLAGS)\nDEBUG= -g\n\nR_CC=$(CC) $(R_CFLAGS)\nR_LD=$(CC) $(R_LDFLAGS)\n\nlinenoise.o: linenoise.h linenoise.c\n\nlinenoise_example: linenoise.o example.o\n\t$(R_LD) -o $@ $^\n\n.c.o:\n\t$(R_CC) -c $<\n\nclean:\n\trm -f linenoise_example *.o\n"
  },
  {
    "path": "extern/deprecated/redis-2.8.21/deps/linenoise/README.markdown",
    "content": "# Linenoise\n\nA minimal, zero-config, BSD licensed, readline replacement used in Redis,\nMongoDB, and Android.\n\n* Single and multi line editing mode with the usual key bindings implemented.\n* History handling.\n* Completion.\n* About 1,100 lines of BSD license source code.\n* Only uses a subset of VT100 escapes (ANSI.SYS compatible).\n\n## Can a line editing library be 20k lines of code?\n\nLine editing with some support for history is a really important feature for command line utilities. Instead of retyping almost the same stuff again and again it's just much better to hit the up arrow and edit on syntax errors, or in order to try a slightly different command. But apparently code dealing with terminals is some sort of Black Magic: readline is 30k lines of code, libedit 20k. Is it reasonable to link small utilities to huge libraries just to get a minimal support for line editing?\n\nSo what usually happens is either:\n\n * Large programs with configure scripts disabling line editing if readline is not present in the system, or not supporting it at all since readline is GPL licensed and libedit (the BSD clone) is not as known and available as readline is (Real world example of this problem: Tclsh).\n * Smaller programs not using a configure script not supporting line editing at all (A problem we had with Redis-cli for instance).\n \nThe result is a pollution of binaries without line editing support.\n\nSo I spent more or less two hours doing a reality check resulting in this little library: is it *really* needed for a line editing library to be 20k lines of code? Apparently not, it is possibe to get a very small, zero configuration, trivial to embed library, that solves the problem. Smaller programs will just include this, supporing line editing out of the box. Larger programs may use this little library or just checking with configure if readline/libedit is available and resorting to linenoise if not.\n\n## Terminals, in 2010.\n\nApparently almost every terminal you can happen to use today has some kind of support for basic VT100 escape sequences. So I tried to write a lib using just very basic VT100 features. The resulting library appears to work everywhere I tried to use it, and now can work even on ANSI.SYS compatible terminals, since no\nVT220 specific sequences are used anymore.\n\nThe library is currently about 1100 lines of code. In order to use it in your project just look at the *example.c* file in the source distribution, it is trivial. Linenoise is BSD code, so you can use both in free software and commercial software.\n\n## Tested with...\n\n * Linux text only console ($TERM = linux)\n * Linux KDE terminal application ($TERM = xterm)\n * Linux xterm ($TERM = xterm)\n * Linux Buildroot ($TERM = vt100)\n * Mac OS X iTerm ($TERM = xterm)\n * Mac OS X default Terminal.app ($TERM = xterm)\n * OpenBSD 4.5 through an OSX Terminal.app ($TERM = screen)\n * IBM AIX 6.1\n * FreeBSD xterm ($TERM = xterm)\n * ANSI.SYS\n\nPlease test it everywhere you can and report back!\n\n## Let's push this forward!\n\nPatches should be provided in the respect of linenoise sensibility for small\neasy to understand code.\n\nSend feedbacks to antirez at gmail\n"
  },
  {
    "path": "extern/deprecated/redis-2.8.21/deps/linenoise/example.c",
    "content": "#include <stdio.h>\n#include <stdlib.h>\n#include <string.h>\n#include \"linenoise.h\"\n\n\nvoid completion(const char *buf, linenoiseCompletions *lc) {\n    if (buf[0] == 'h') {\n        linenoiseAddCompletion(lc,\"hello\");\n        linenoiseAddCompletion(lc,\"hello there\");\n    }\n}\n\nint main(int argc, char **argv) {\n    char *line;\n    char *prgname = argv[0];\n\n    /* Parse options, with --multiline we enable multi line editing. */\n    while(argc > 1) {\n        argc--;\n        argv++;\n        if (!strcmp(*argv,\"--multiline\")) {\n            linenoiseSetMultiLine(1);\n            printf(\"Multi-line mode enabled.\\n\");\n        } else if (!strcmp(*argv,\"--keycodes\")) {\n            linenoisePrintKeyCodes();\n            exit(0);\n        } else {\n            fprintf(stderr, \"Usage: %s [--multiline] [--keycodes]\\n\", prgname);\n            exit(1);\n        }\n    }\n\n    /* Set the completion callback. This will be called every time the\n     * user uses the <tab> key. */\n    linenoiseSetCompletionCallback(completion);\n\n    /* Load history from file. The history file is just a plain text file\n     * where entries are separated by newlines. */\n    linenoiseHistoryLoad(\"history.txt\"); /* Load the history at startup */\n\n    /* Now this is the main loop of the typical linenoise-based application.\n     * The call to linenoise() will block as long as the user types something\n     * and presses enter.\n     *\n     * The typed string is returned as a malloc() allocated string by\n     * linenoise, so the user needs to free() it. */\n    while((line = linenoise(\"hello> \")) != NULL) {\n        /* Do something with the string. */\n        if (line[0] != '\\0' && line[0] != '/') {\n            printf(\"echo: '%s'\\n\", line);\n            linenoiseHistoryAdd(line); /* Add to the history. */\n            linenoiseHistorySave(\"history.txt\"); /* Save the history on disk. */\n        } else if (!strncmp(line,\"/historylen\",11)) {\n            /* The \"/historylen\" command will change the history len. */\n            int len = atoi(line+11);\n            linenoiseHistorySetMaxLen(len);\n        } else if (line[0] == '/') {\n            printf(\"Unreconized command: %s\\n\", line);\n        }\n        free(line);\n    }\n    return 0;\n}\n"
  },
  {
    "path": "extern/deprecated/redis-2.8.21/deps/linenoise/linenoise.c",
    "content": "/* linenoise.c -- guerrilla line editing library against the idea that a\n * line editing lib needs to be 20,000 lines of C code.\n *\n * You can find the latest source code at:\n *\n *   http://github.com/antirez/linenoise\n *\n * Does a number of crazy assumptions that happen to be true in 99.9999% of\n * the 2010 UNIX computers around.\n *\n * ------------------------------------------------------------------------\n *\n * Copyright (c) 2010-2013, Salvatore Sanfilippo <antirez at gmail dot com>\n * Copyright (c) 2010-2013, Pieter Noordhuis <pcnoordhuis at gmail dot com>\n *\n * All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions are\n * met:\n *\n *  *  Redistributions of source code must retain the above copyright\n *     notice, this list of conditions and the following disclaimer.\n *\n *  *  Redistributions in binary form must reproduce the above copyright\n *     notice, this list of conditions and the following disclaimer in the\n *     documentation and/or other materials provided with the distribution.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n * \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\n * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\n * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\n * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\n * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n *\n * ------------------------------------------------------------------------\n *\n * References:\n * - http://invisible-island.net/xterm/ctlseqs/ctlseqs.html\n * - http://www.3waylabs.com/nw/WWW/products/wizcon/vt220.html\n *\n * Todo list:\n * - Filter bogus Ctrl+<char> combinations.\n * - Win32 support\n *\n * Bloat:\n * - History search like Ctrl+r in readline?\n *\n * List of escape sequences used by this program, we do everything just\n * with three sequences. In order to be so cheap we may have some\n * flickering effect with some slow terminal, but the lesser sequences\n * the more compatible.\n *\n * EL (Erase Line)\n *    Sequence: ESC [ n K\n *    Effect: if n is 0 or missing, clear from cursor to end of line\n *    Effect: if n is 1, clear from beginning of line to cursor\n *    Effect: if n is 2, clear entire line\n *\n * CUF (CUrsor Forward)\n *    Sequence: ESC [ n C\n *    Effect: moves cursor forward n chars\n *\n * CUB (CUrsor Backward)\n *    Sequence: ESC [ n D\n *    Effect: moves cursor backward n chars\n *\n * The following is used to get the terminal width if getting\n * the width with the TIOCGWINSZ ioctl fails\n *\n * DSR (Device Status Report)\n *    Sequence: ESC [ 6 n\n *    Effect: reports the current cusor position as ESC [ n ; m R\n *            where n is the row and m is the column\n *\n * When multi line mode is enabled, we also use an additional escape\n * sequence. However multi line editing is disabled by default.\n *\n * CUU (Cursor Up)\n *    Sequence: ESC [ n A\n *    Effect: moves cursor up of n chars.\n *\n * CUD (Cursor Down)\n *    Sequence: ESC [ n B\n *    Effect: moves cursor down of n chars.\n *\n * When linenoiseClearScreen() is called, two additional escape sequences\n * are used in order to clear the screen and position the cursor at home\n * position.\n *\n * CUP (Cursor position)\n *    Sequence: ESC [ H\n *    Effect: moves the cursor to upper left corner\n *\n * ED (Erase display)\n *    Sequence: ESC [ 2 J\n *    Effect: clear the whole screen\n *\n */\n\n#include <termios.h>\n#include <unistd.h>\n#include <stdlib.h>\n#include <stdio.h>\n#include <errno.h>\n#include <string.h>\n#include <stdlib.h>\n#include <ctype.h>\n#include <sys/types.h>\n#include <sys/ioctl.h>\n#include <unistd.h>\n#include \"linenoise.h\"\n\n#define LINENOISE_DEFAULT_HISTORY_MAX_LEN 100\n#define LINENOISE_MAX_LINE 4096\nstatic char *unsupported_term[] = {\"dumb\",\"cons25\",\"emacs\",NULL};\nstatic linenoiseCompletionCallback *completionCallback = NULL;\n\nstatic struct termios orig_termios; /* In order to restore at exit.*/\nstatic int rawmode = 0; /* For atexit() function to check if restore is needed*/\nstatic int mlmode = 0;  /* Multi line mode. Default is single line. */\nstatic int atexit_registered = 0; /* Register atexit just 1 time. */\nstatic int history_max_len = LINENOISE_DEFAULT_HISTORY_MAX_LEN;\nstatic int history_len = 0;\nstatic char **history = NULL;\n\n/* The linenoiseState structure represents the state during line editing.\n * We pass this state to functions implementing specific editing\n * functionalities. */\nstruct linenoiseState {\n    int ifd;            /* Terminal stdin file descriptor. */\n    int ofd;            /* Terminal stdout file descriptor. */\n    char *buf;          /* Edited line buffer. */\n    size_t buflen;      /* Edited line buffer size. */\n    const char *prompt; /* Prompt to display. */\n    size_t plen;        /* Prompt length. */\n    size_t pos;         /* Current cursor position. */\n    size_t oldpos;      /* Previous refresh cursor position. */\n    size_t len;         /* Current edited line length. */\n    size_t cols;        /* Number of columns in terminal. */\n    size_t maxrows;     /* Maximum num of rows used so far (multiline mode) */\n    int history_index;  /* The history index we are currently editing. */\n};\n\nenum KEY_ACTION{\n\tKEY_NULL = 0,\t    /* NULL */\n\tCTRL_A = 1,         /* Ctrl+a */\n\tCTRL_B = 2,         /* Ctrl-b */\n\tCTRL_C = 3,         /* Ctrl-c */\n\tCTRL_D = 4,         /* Ctrl-d */\n\tCTRL_E = 5,         /* Ctrl-e */\n\tCTRL_F = 6,         /* Ctrl-f */\n\tCTRL_H = 8,         /* Ctrl-h */\n\tTAB = 9,            /* Tab */\n\tCTRL_K = 11,        /* Ctrl+k */\n\tCTRL_L = 12,        /* Ctrl+l */\n\tENTER = 13,         /* Enter */\n\tCTRL_N = 14,        /* Ctrl-n */\n\tCTRL_P = 16,        /* Ctrl-p */\n\tCTRL_T = 20,        /* Ctrl-t */\n\tCTRL_U = 21,        /* Ctrl+u */\n\tCTRL_W = 23,        /* Ctrl+w */\n\tESC = 27,           /* Escape */\n\tBACKSPACE =  127    /* Backspace */\n};\n\nstatic void linenoiseAtExit(void);\nint linenoiseHistoryAdd(const char *line);\nstatic void refreshLine(struct linenoiseState *l);\n\n/* Debugging macro. */\n#if 0\nFILE *lndebug_fp = NULL;\n#define lndebug(...) \\\n    do { \\\n        if (lndebug_fp == NULL) { \\\n            lndebug_fp = fopen(\"/tmp/lndebug.txt\",\"a\"); \\\n            fprintf(lndebug_fp, \\\n            \"[%d %d %d] p: %d, rows: %d, rpos: %d, max: %d, oldmax: %d\\n\", \\\n            (int)l->len,(int)l->pos,(int)l->oldpos,plen,rows,rpos, \\\n            (int)l->maxrows,old_rows); \\\n        } \\\n        fprintf(lndebug_fp, \", \" __VA_ARGS__); \\\n        fflush(lndebug_fp); \\\n    } while (0)\n#else\n#define lndebug(fmt, ...)\n#endif\n\n/* ======================= Low level terminal handling ====================== */\n\n/* Set if to use or not the multi line mode. */\nvoid linenoiseSetMultiLine(int ml) {\n    mlmode = ml;\n}\n\n/* Return true if the terminal name is in the list of terminals we know are\n * not able to understand basic escape sequences. */\nstatic int isUnsupportedTerm(void) {\n    char *term = getenv(\"TERM\");\n    int j;\n\n    if (term == NULL) return 0;\n    for (j = 0; unsupported_term[j]; j++)\n        if (!strcasecmp(term,unsupported_term[j])) return 1;\n    return 0;\n}\n\n/* Raw mode: 1960 magic shit. */\nstatic int enableRawMode(int fd) {\n    struct termios raw;\n\n    if (!isatty(STDIN_FILENO)) goto fatal;\n    if (!atexit_registered) {\n        atexit(linenoiseAtExit);\n        atexit_registered = 1;\n    }\n    if (tcgetattr(fd,&orig_termios) == -1) goto fatal;\n\n    raw = orig_termios;  /* modify the original mode */\n    /* input modes: no break, no CR to NL, no parity check, no strip char,\n     * no start/stop output control. */\n    raw.c_iflag &= ~(BRKINT | ICRNL | INPCK | ISTRIP | IXON);\n    /* output modes - disable post processing */\n    raw.c_oflag &= ~(OPOST);\n    /* control modes - set 8 bit chars */\n    raw.c_cflag |= (CS8);\n    /* local modes - choing off, canonical off, no extended functions,\n     * no signal chars (^Z,^C) */\n    raw.c_lflag &= ~(ECHO | ICANON | IEXTEN | ISIG);\n    /* control chars - set return condition: min number of bytes and timer.\n     * We want read to return every single byte, without timeout. */\n    raw.c_cc[VMIN] = 1; raw.c_cc[VTIME] = 0; /* 1 byte, no timer */\n\n    /* put terminal in raw mode after flushing */\n    if (tcsetattr(fd,TCSAFLUSH,&raw) < 0) goto fatal;\n    rawmode = 1;\n    return 0;\n\nfatal:\n    errno = ENOTTY;\n    return -1;\n}\n\nstatic void disableRawMode(int fd) {\n    /* Don't even check the return value as it's too late. */\n    if (rawmode && tcsetattr(fd,TCSAFLUSH,&orig_termios) != -1)\n        rawmode = 0;\n}\n\n/* Use the ESC [6n escape sequence to query the horizontal cursor position\n * and return it. On error -1 is returned, on success the position of the\n * cursor. */\nstatic int getCursorPosition(int ifd, int ofd) {\n    char buf[32];\n    int cols, rows;\n    unsigned int i = 0;\n\n    /* Report cursor location */\n    if (write(ofd, \"\\x1b[6n\", 4) != 4) return -1;\n\n    /* Read the response: ESC [ rows ; cols R */\n    while (i < sizeof(buf)-1) {\n        if (read(ifd,buf+i,1) != 1) break;\n        if (buf[i] == 'R') break;\n        i++;\n    }\n    buf[i] = '\\0';\n\n    /* Parse it. */\n    if (buf[0] != ESC || buf[1] != '[') return -1;\n    if (sscanf(buf+2,\"%d;%d\",&rows,&cols) != 2) return -1;\n    return cols;\n}\n\n/* Try to get the number of columns in the current terminal, or assume 80\n * if it fails. */\nstatic int getColumns(int ifd, int ofd) {\n    struct winsize ws;\n\n    if (ioctl(1, TIOCGWINSZ, &ws) == -1 || ws.ws_col == 0) {\n        /* ioctl() failed. Try to query the terminal itself. */\n        int start, cols;\n\n        /* Get the initial position so we can restore it later. */\n        start = getCursorPosition(ifd,ofd);\n        if (start == -1) goto failed;\n\n        /* Go to right margin and get position. */\n        if (write(ofd,\"\\x1b[999C\",6) != 6) goto failed;\n        cols = getCursorPosition(ifd,ofd);\n        if (cols == -1) goto failed;\n\n        /* Restore position. */\n        if (cols > start) {\n            char seq[32];\n            snprintf(seq,32,\"\\x1b[%dD\",cols-start);\n            if (write(ofd,seq,strlen(seq)) == -1) {\n                /* Can't recover... */\n            }\n        }\n        return cols;\n    } else {\n        return ws.ws_col;\n    }\n\nfailed:\n    return 80;\n}\n\n/* Clear the screen. Used to handle ctrl+l */\nvoid linenoiseClearScreen(void) {\n    if (write(STDOUT_FILENO,\"\\x1b[H\\x1b[2J\",7) <= 0) {\n        /* nothing to do, just to avoid warning. */\n    }\n}\n\n/* Beep, used for completion when there is nothing to complete or when all\n * the choices were already shown. */\nstatic void linenoiseBeep(void) {\n    fprintf(stderr, \"\\x7\");\n    fflush(stderr);\n}\n\n/* ============================== Completion ================================ */\n\n/* Free a list of completion option populated by linenoiseAddCompletion(). */\nstatic void freeCompletions(linenoiseCompletions *lc) {\n    size_t i;\n    for (i = 0; i < lc->len; i++)\n        free(lc->cvec[i]);\n    if (lc->cvec != NULL)\n        free(lc->cvec);\n}\n\n/* This is an helper function for linenoiseEdit() and is called when the\n * user types the <tab> key in order to complete the string currently in the\n * input.\n *\n * The state of the editing is encapsulated into the pointed linenoiseState\n * structure as described in the structure definition. */\nstatic int completeLine(struct linenoiseState *ls) {\n    linenoiseCompletions lc = { 0, NULL };\n    int nread, nwritten;\n    char c = 0;\n\n    completionCallback(ls->buf,&lc);\n    if (lc.len == 0) {\n        linenoiseBeep();\n    } else {\n        size_t stop = 0, i = 0;\n\n        while(!stop) {\n            /* Show completion or original buffer */\n            if (i < lc.len) {\n                struct linenoiseState saved = *ls;\n\n                ls->len = ls->pos = strlen(lc.cvec[i]);\n                ls->buf = lc.cvec[i];\n                refreshLine(ls);\n                ls->len = saved.len;\n                ls->pos = saved.pos;\n                ls->buf = saved.buf;\n            } else {\n                refreshLine(ls);\n            }\n\n            nread = read(ls->ifd,&c,1);\n            if (nread <= 0) {\n                freeCompletions(&lc);\n                return -1;\n            }\n\n            switch(c) {\n                case 9: /* tab */\n                    i = (i+1) % (lc.len+1);\n                    if (i == lc.len) linenoiseBeep();\n                    break;\n                case 27: /* escape */\n                    /* Re-show original buffer */\n                    if (i < lc.len) refreshLine(ls);\n                    stop = 1;\n                    break;\n                default:\n                    /* Update buffer and return */\n                    if (i < lc.len) {\n                        nwritten = snprintf(ls->buf,ls->buflen,\"%s\",lc.cvec[i]);\n                        ls->len = ls->pos = nwritten;\n                    }\n                    stop = 1;\n                    break;\n            }\n        }\n    }\n\n    freeCompletions(&lc);\n    return c; /* Return last read character */\n}\n\n/* Register a callback function to be called for tab-completion. */\nvoid linenoiseSetCompletionCallback(linenoiseCompletionCallback *fn) {\n    completionCallback = fn;\n}\n\n/* This function is used by the callback function registered by the user\n * in order to add completion options given the input string when the\n * user typed <tab>. See the example.c source code for a very easy to\n * understand example. */\nvoid linenoiseAddCompletion(linenoiseCompletions *lc, const char *str) {\n    size_t len = strlen(str);\n    char *copy, **cvec;\n\n    copy = malloc(len+1);\n    if (copy == NULL) return;\n    memcpy(copy,str,len+1);\n    cvec = realloc(lc->cvec,sizeof(char*)*(lc->len+1));\n    if (cvec == NULL) {\n        free(copy);\n        return;\n    }\n    lc->cvec = cvec;\n    lc->cvec[lc->len++] = copy;\n}\n\n/* =========================== Line editing ================================= */\n\n/* We define a very simple \"append buffer\" structure, that is an heap\n * allocated string where we can append to. This is useful in order to\n * write all the escape sequences in a buffer and flush them to the standard\n * output in a single call, to avoid flickering effects. */\nstruct abuf {\n    char *b;\n    int len;\n};\n\nstatic void abInit(struct abuf *ab) {\n    ab->b = NULL;\n    ab->len = 0;\n}\n\nstatic void abAppend(struct abuf *ab, const char *s, int len) {\n    char *new = realloc(ab->b,ab->len+len);\n\n    if (new == NULL) return;\n    memcpy(new+ab->len,s,len);\n    ab->b = new;\n    ab->len += len;\n}\n\nstatic void abFree(struct abuf *ab) {\n    free(ab->b);\n}\n\n/* Single line low level line refresh.\n *\n * Rewrite the currently edited line accordingly to the buffer content,\n * cursor position, and number of columns of the terminal. */\nstatic void refreshSingleLine(struct linenoiseState *l) {\n    char seq[64];\n    size_t plen = strlen(l->prompt);\n    int fd = l->ofd;\n    char *buf = l->buf;\n    size_t len = l->len;\n    size_t pos = l->pos;\n    struct abuf ab;\n\n    while((plen+pos) >= l->cols) {\n        buf++;\n        len--;\n        pos--;\n    }\n    while (plen+len > l->cols) {\n        len--;\n    }\n\n    abInit(&ab);\n    /* Cursor to left edge */\n    snprintf(seq,64,\"\\r\");\n    abAppend(&ab,seq,strlen(seq));\n    /* Write the prompt and the current buffer content */\n    abAppend(&ab,l->prompt,strlen(l->prompt));\n    abAppend(&ab,buf,len);\n    /* Erase to right */\n    snprintf(seq,64,\"\\x1b[0K\");\n    abAppend(&ab,seq,strlen(seq));\n    /* Move cursor to original position. */\n    snprintf(seq,64,\"\\r\\x1b[%dC\", (int)(pos+plen));\n    abAppend(&ab,seq,strlen(seq));\n    if (write(fd,ab.b,ab.len) == -1) {} /* Can't recover from write error. */\n    abFree(&ab);\n}\n\n/* Multi line low level line refresh.\n *\n * Rewrite the currently edited line accordingly to the buffer content,\n * cursor position, and number of columns of the terminal. */\nstatic void refreshMultiLine(struct linenoiseState *l) {\n    char seq[64];\n    int plen = strlen(l->prompt);\n    int rows = (plen+l->len+l->cols-1)/l->cols; /* rows used by current buf. */\n    int rpos = (plen+l->oldpos+l->cols)/l->cols; /* cursor relative row. */\n    int rpos2; /* rpos after refresh. */\n    int col; /* colum position, zero-based. */\n    int old_rows = l->maxrows;\n    int fd = l->ofd, j;\n    struct abuf ab;\n\n    /* Update maxrows if needed. */\n    if (rows > (int)l->maxrows) l->maxrows = rows;\n\n    /* First step: clear all the lines used before. To do so start by\n     * going to the last row. */\n    abInit(&ab);\n    if (old_rows-rpos > 0) {\n        lndebug(\"go down %d\", old_rows-rpos);\n        snprintf(seq,64,\"\\x1b[%dB\", old_rows-rpos);\n        abAppend(&ab,seq,strlen(seq));\n    }\n\n    /* Now for every row clear it, go up. */\n    for (j = 0; j < old_rows-1; j++) {\n        lndebug(\"clear+up\");\n        snprintf(seq,64,\"\\r\\x1b[0K\\x1b[1A\");\n        abAppend(&ab,seq,strlen(seq));\n    }\n\n    /* Clean the top line. */\n    lndebug(\"clear\");\n    snprintf(seq,64,\"\\r\\x1b[0K\");\n    abAppend(&ab,seq,strlen(seq));\n\n    /* Write the prompt and the current buffer content */\n    abAppend(&ab,l->prompt,strlen(l->prompt));\n    abAppend(&ab,l->buf,l->len);\n\n    /* If we are at the very end of the screen with our prompt, we need to\n     * emit a newline and move the prompt to the first column. */\n    if (l->pos &&\n        l->pos == l->len &&\n        (l->pos+plen) % l->cols == 0)\n    {\n        lndebug(\"<newline>\");\n        abAppend(&ab,\"\\n\",1);\n        snprintf(seq,64,\"\\r\");\n        abAppend(&ab,seq,strlen(seq));\n        rows++;\n        if (rows > (int)l->maxrows) l->maxrows = rows;\n    }\n\n    /* Move cursor to right position. */\n    rpos2 = (plen+l->pos+l->cols)/l->cols; /* current cursor relative row. */\n    lndebug(\"rpos2 %d\", rpos2);\n\n    /* Go up till we reach the expected positon. */\n    if (rows-rpos2 > 0) {\n        lndebug(\"go-up %d\", rows-rpos2);\n        snprintf(seq,64,\"\\x1b[%dA\", rows-rpos2);\n        abAppend(&ab,seq,strlen(seq));\n    }\n\n    /* Set column. */\n    col = (plen+(int)l->pos) % (int)l->cols;\n    lndebug(\"set col %d\", 1+col);\n    if (col)\n        snprintf(seq,64,\"\\r\\x1b[%dC\", col);\n    else\n        snprintf(seq,64,\"\\r\");\n    abAppend(&ab,seq,strlen(seq));\n\n    lndebug(\"\\n\");\n    l->oldpos = l->pos;\n\n    if (write(fd,ab.b,ab.len) == -1) {} /* Can't recover from write error. */\n    abFree(&ab);\n}\n\n/* Calls the two low level functions refreshSingleLine() or\n * refreshMultiLine() according to the selected mode. */\nstatic void refreshLine(struct linenoiseState *l) {\n    if (mlmode)\n        refreshMultiLine(l);\n    else\n        refreshSingleLine(l);\n}\n\n/* Insert the character 'c' at cursor current position.\n *\n * On error writing to the terminal -1 is returned, otherwise 0. */\nint linenoiseEditInsert(struct linenoiseState *l, char c) {\n    if (l->len < l->buflen) {\n        if (l->len == l->pos) {\n            l->buf[l->pos] = c;\n            l->pos++;\n            l->len++;\n            l->buf[l->len] = '\\0';\n            if ((!mlmode && l->plen+l->len < l->cols) /* || mlmode */) {\n                /* Avoid a full update of the line in the\n                 * trivial case. */\n                if (write(l->ofd,&c,1) == -1) return -1;\n            } else {\n                refreshLine(l);\n            }\n        } else {\n            memmove(l->buf+l->pos+1,l->buf+l->pos,l->len-l->pos);\n            l->buf[l->pos] = c;\n            l->len++;\n            l->pos++;\n            l->buf[l->len] = '\\0';\n            refreshLine(l);\n        }\n    }\n    return 0;\n}\n\n/* Move cursor on the left. */\nvoid linenoiseEditMoveLeft(struct linenoiseState *l) {\n    if (l->pos > 0) {\n        l->pos--;\n        refreshLine(l);\n    }\n}\n\n/* Move cursor on the right. */\nvoid linenoiseEditMoveRight(struct linenoiseState *l) {\n    if (l->pos != l->len) {\n        l->pos++;\n        refreshLine(l);\n    }\n}\n\n/* Move cursor to the start of the line. */\nvoid linenoiseEditMoveHome(struct linenoiseState *l) {\n    if (l->pos != 0) {\n        l->pos = 0;\n        refreshLine(l);\n    }\n}\n\n/* Move cursor to the end of the line. */\nvoid linenoiseEditMoveEnd(struct linenoiseState *l) {\n    if (l->pos != l->len) {\n        l->pos = l->len;\n        refreshLine(l);\n    }\n}\n\n/* Substitute the currently edited line with the next or previous history\n * entry as specified by 'dir'. */\n#define LINENOISE_HISTORY_NEXT 0\n#define LINENOISE_HISTORY_PREV 1\nvoid linenoiseEditHistoryNext(struct linenoiseState *l, int dir) {\n    if (history_len > 1) {\n        /* Update the current history entry before to\n         * overwrite it with the next one. */\n        free(history[history_len - 1 - l->history_index]);\n        history[history_len - 1 - l->history_index] = strdup(l->buf);\n        /* Show the new entry */\n        l->history_index += (dir == LINENOISE_HISTORY_PREV) ? 1 : -1;\n        if (l->history_index < 0) {\n            l->history_index = 0;\n            return;\n        } else if (l->history_index >= history_len) {\n            l->history_index = history_len-1;\n            return;\n        }\n        strncpy(l->buf,history[history_len - 1 - l->history_index],l->buflen);\n        l->buf[l->buflen-1] = '\\0';\n        l->len = l->pos = strlen(l->buf);\n        refreshLine(l);\n    }\n}\n\n/* Delete the character at the right of the cursor without altering the cursor\n * position. Basically this is what happens with the \"Delete\" keyboard key. */\nvoid linenoiseEditDelete(struct linenoiseState *l) {\n    if (l->len > 0 && l->pos < l->len) {\n        memmove(l->buf+l->pos,l->buf+l->pos+1,l->len-l->pos-1);\n        l->len--;\n        l->buf[l->len] = '\\0';\n        refreshLine(l);\n    }\n}\n\n/* Backspace implementation. */\nvoid linenoiseEditBackspace(struct linenoiseState *l) {\n    if (l->pos > 0 && l->len > 0) {\n        memmove(l->buf+l->pos-1,l->buf+l->pos,l->len-l->pos);\n        l->pos--;\n        l->len--;\n        l->buf[l->len] = '\\0';\n        refreshLine(l);\n    }\n}\n\n/* Delete the previosu word, maintaining the cursor at the start of the\n * current word. */\nvoid linenoiseEditDeletePrevWord(struct linenoiseState *l) {\n    size_t old_pos = l->pos;\n    size_t diff;\n\n    while (l->pos > 0 && l->buf[l->pos-1] == ' ')\n        l->pos--;\n    while (l->pos > 0 && l->buf[l->pos-1] != ' ')\n        l->pos--;\n    diff = old_pos - l->pos;\n    memmove(l->buf+l->pos,l->buf+old_pos,l->len-old_pos+1);\n    l->len -= diff;\n    refreshLine(l);\n}\n\n/* This function is the core of the line editing capability of linenoise.\n * It expects 'fd' to be already in \"raw mode\" so that every key pressed\n * will be returned ASAP to read().\n *\n * The resulting string is put into 'buf' when the user type enter, or\n * when ctrl+d is typed.\n *\n * The function returns the length of the current buffer. */\nstatic int linenoiseEdit(int stdin_fd, int stdout_fd, char *buf, size_t buflen, const char *prompt)\n{\n    struct linenoiseState l;\n\n    /* Populate the linenoise state that we pass to functions implementing\n     * specific editing functionalities. */\n    l.ifd = stdin_fd;\n    l.ofd = stdout_fd;\n    l.buf = buf;\n    l.buflen = buflen;\n    l.prompt = prompt;\n    l.plen = strlen(prompt);\n    l.oldpos = l.pos = 0;\n    l.len = 0;\n    l.cols = getColumns(stdin_fd, stdout_fd);\n    l.maxrows = 0;\n    l.history_index = 0;\n\n    /* Buffer starts empty. */\n    l.buf[0] = '\\0';\n    l.buflen--; /* Make sure there is always space for the nulterm */\n\n    /* The latest history entry is always our current buffer, that\n     * initially is just an empty string. */\n    linenoiseHistoryAdd(\"\");\n\n    if (write(l.ofd,prompt,l.plen) == -1) return -1;\n    while(1) {\n        char c;\n        int nread;\n        char seq[3];\n\n        nread = read(l.ifd,&c,1);\n        if (nread <= 0) return l.len;\n\n        /* Only autocomplete when the callback is set. It returns < 0 when\n         * there was an error reading from fd. Otherwise it will return the\n         * character that should be handled next. */\n        if (c == 9 && completionCallback != NULL) {\n            c = completeLine(&l);\n            /* Return on errors */\n            if (c < 0) return l.len;\n            /* Read next character when 0 */\n            if (c == 0) continue;\n        }\n\n        switch(c) {\n        case ENTER:    /* enter */\n            history_len--;\n            free(history[history_len]);\n            if (mlmode) linenoiseEditMoveEnd(&l);\n            return (int)l.len;\n        case CTRL_C:     /* ctrl-c */\n            errno = EAGAIN;\n            return -1;\n        case BACKSPACE:   /* backspace */\n        case 8:     /* ctrl-h */\n            linenoiseEditBackspace(&l);\n            break;\n        case CTRL_D:     /* ctrl-d, remove char at right of cursor, or if the\n                            line is empty, act as end-of-file. */\n            if (l.len > 0) {\n                linenoiseEditDelete(&l);\n            } else {\n                history_len--;\n                free(history[history_len]);\n                return -1;\n            }\n            break;\n        case CTRL_T:    /* ctrl-t, swaps current character with previous. */\n            if (l.pos > 0 && l.pos < l.len) {\n                int aux = buf[l.pos-1];\n                buf[l.pos-1] = buf[l.pos];\n                buf[l.pos] = aux;\n                if (l.pos != l.len-1) l.pos++;\n                refreshLine(&l);\n            }\n            break;\n        case CTRL_B:     /* ctrl-b */\n            linenoiseEditMoveLeft(&l);\n            break;\n        case CTRL_F:     /* ctrl-f */\n            linenoiseEditMoveRight(&l);\n            break;\n        case CTRL_P:    /* ctrl-p */\n            linenoiseEditHistoryNext(&l, LINENOISE_HISTORY_PREV);\n            break;\n        case CTRL_N:    /* ctrl-n */\n            linenoiseEditHistoryNext(&l, LINENOISE_HISTORY_NEXT);\n            break;\n        case ESC:    /* escape sequence */\n            /* Read the next two bytes representing the escape sequence.\n             * Use two calls to handle slow terminals returning the two\n             * chars at different times. */\n            if (read(l.ifd,seq,1) == -1) break;\n            if (read(l.ifd,seq+1,1) == -1) break;\n\n            /* ESC [ sequences. */\n            if (seq[0] == '[') {\n                if (seq[1] >= '0' && seq[1] <= '9') {\n                    /* Extended escape, read additional byte. */\n                    if (read(l.ifd,seq+2,1) == -1) break;\n                    if (seq[2] == '~') {\n                        switch(seq[1]) {\n                        case '3': /* Delete key. */\n                            linenoiseEditDelete(&l);\n                            break;\n                        }\n                    }\n                } else {\n                    switch(seq[1]) {\n                    case 'A': /* Up */\n                        linenoiseEditHistoryNext(&l, LINENOISE_HISTORY_PREV);\n                        break;\n                    case 'B': /* Down */\n                        linenoiseEditHistoryNext(&l, LINENOISE_HISTORY_NEXT);\n                        break;\n                    case 'C': /* Right */\n                        linenoiseEditMoveRight(&l);\n                        break;\n                    case 'D': /* Left */\n                        linenoiseEditMoveLeft(&l);\n                        break;\n                    case 'H': /* Home */\n                        linenoiseEditMoveHome(&l);\n                        break;\n                    case 'F': /* End*/\n                        linenoiseEditMoveEnd(&l);\n                        break;\n                    }\n                }\n            }\n\n            /* ESC O sequences. */\n            else if (seq[0] == 'O') {\n                switch(seq[1]) {\n                case 'H': /* Home */\n                    linenoiseEditMoveHome(&l);\n                    break;\n                case 'F': /* End*/\n                    linenoiseEditMoveEnd(&l);\n                    break;\n                }\n            }\n            break;\n        default:\n            if (linenoiseEditInsert(&l,c)) return -1;\n            break;\n        case CTRL_U: /* Ctrl+u, delete the whole line. */\n            buf[0] = '\\0';\n            l.pos = l.len = 0;\n            refreshLine(&l);\n            break;\n        case CTRL_K: /* Ctrl+k, delete from current to end of line. */\n            buf[l.pos] = '\\0';\n            l.len = l.pos;\n            refreshLine(&l);\n            break;\n        case CTRL_A: /* Ctrl+a, go to the start of the line */\n            linenoiseEditMoveHome(&l);\n            break;\n        case CTRL_E: /* ctrl+e, go to the end of the line */\n            linenoiseEditMoveEnd(&l);\n            break;\n        case CTRL_L: /* ctrl+l, clear screen */\n            linenoiseClearScreen();\n            refreshLine(&l);\n            break;\n        case CTRL_W: /* ctrl+w, delete previous word */\n            linenoiseEditDeletePrevWord(&l);\n            break;\n        }\n    }\n    return l.len;\n}\n\n/* This special mode is used by linenoise in order to print scan codes\n * on screen for debugging / development purposes. It is implemented\n * by the linenoise_example program using the --keycodes option. */\nvoid linenoisePrintKeyCodes(void) {\n    char quit[4];\n\n    printf(\"Linenoise key codes debugging mode.\\n\"\n            \"Press keys to see scan codes. Type 'quit' at any time to exit.\\n\");\n    if (enableRawMode(STDIN_FILENO) == -1) return;\n    memset(quit,' ',4);\n    while(1) {\n        char c;\n        int nread;\n\n        nread = read(STDIN_FILENO,&c,1);\n        if (nread <= 0) continue;\n        memmove(quit,quit+1,sizeof(quit)-1); /* shift string to left. */\n        quit[sizeof(quit)-1] = c; /* Insert current char on the right. */\n        if (memcmp(quit,\"quit\",sizeof(quit)) == 0) break;\n\n        printf(\"'%c' %02x (%d) (type quit to exit)\\n\",\n            isprint(c) ? c : '?', (int)c, (int)c);\n        printf(\"\\r\"); /* Go left edge manually, we are in raw mode. */\n        fflush(stdout);\n    }\n    disableRawMode(STDIN_FILENO);\n}\n\n/* This function calls the line editing function linenoiseEdit() using\n * the STDIN file descriptor set in raw mode. */\nstatic int linenoiseRaw(char *buf, size_t buflen, const char *prompt) {\n    int count;\n\n    if (buflen == 0) {\n        errno = EINVAL;\n        return -1;\n    }\n    if (!isatty(STDIN_FILENO)) {\n        /* Not a tty: read from file / pipe. */\n        if (fgets(buf, buflen, stdin) == NULL) return -1;\n        count = strlen(buf);\n        if (count && buf[count-1] == '\\n') {\n            count--;\n            buf[count] = '\\0';\n        }\n    } else {\n        /* Interactive editing. */\n        if (enableRawMode(STDIN_FILENO) == -1) return -1;\n        count = linenoiseEdit(STDIN_FILENO, STDOUT_FILENO, buf, buflen, prompt);\n        disableRawMode(STDIN_FILENO);\n        printf(\"\\n\");\n    }\n    return count;\n}\n\n/* The high level function that is the main API of the linenoise library.\n * This function checks if the terminal has basic capabilities, just checking\n * for a blacklist of stupid terminals, and later either calls the line\n * editing function or uses dummy fgets() so that you will be able to type\n * something even in the most desperate of the conditions. */\nchar *linenoise(const char *prompt) {\n    char buf[LINENOISE_MAX_LINE];\n    int count;\n\n    if (isUnsupportedTerm()) {\n        size_t len;\n\n        printf(\"%s\",prompt);\n        fflush(stdout);\n        if (fgets(buf,LINENOISE_MAX_LINE,stdin) == NULL) return NULL;\n        len = strlen(buf);\n        while(len && (buf[len-1] == '\\n' || buf[len-1] == '\\r')) {\n            len--;\n            buf[len] = '\\0';\n        }\n        return strdup(buf);\n    } else {\n        count = linenoiseRaw(buf,LINENOISE_MAX_LINE,prompt);\n        if (count == -1) return NULL;\n        return strdup(buf);\n    }\n}\n\n/* ================================ History ================================= */\n\n/* Free the history, but does not reset it. Only used when we have to\n * exit() to avoid memory leaks are reported by valgrind & co. */\nstatic void freeHistory(void) {\n    if (history) {\n        int j;\n\n        for (j = 0; j < history_len; j++)\n            free(history[j]);\n        free(history);\n    }\n}\n\n/* At exit we'll try to fix the terminal to the initial conditions. */\nstatic void linenoiseAtExit(void) {\n    disableRawMode(STDIN_FILENO);\n    freeHistory();\n}\n\n/* This is the API call to add a new entry in the linenoise history.\n * It uses a fixed array of char pointers that are shifted (memmoved)\n * when the history max length is reached in order to remove the older\n * entry and make room for the new one, so it is not exactly suitable for huge\n * histories, but will work well for a few hundred of entries.\n *\n * Using a circular buffer is smarter, but a bit more complex to handle. */\nint linenoiseHistoryAdd(const char *line) {\n    char *linecopy;\n\n    if (history_max_len == 0) return 0;\n\n    /* Initialization on first call. */\n    if (history == NULL) {\n        history = malloc(sizeof(char*)*history_max_len);\n        if (history == NULL) return 0;\n        memset(history,0,(sizeof(char*)*history_max_len));\n    }\n\n    /* Don't add duplicated lines. */\n    if (history_len && !strcmp(history[history_len-1], line)) return 0;\n\n    /* Add an heap allocated copy of the line in the history.\n     * If we reached the max length, remove the older line. */\n    linecopy = strdup(line);\n    if (!linecopy) return 0;\n    if (history_len == history_max_len) {\n        free(history[0]);\n        memmove(history,history+1,sizeof(char*)*(history_max_len-1));\n        history_len--;\n    }\n    history[history_len] = linecopy;\n    history_len++;\n    return 1;\n}\n\n/* Set the maximum length for the history. This function can be called even\n * if there is already some history, the function will make sure to retain\n * just the latest 'len' elements if the new history length value is smaller\n * than the amount of items already inside the history. */\nint linenoiseHistorySetMaxLen(int len) {\n    char **new;\n\n    if (len < 1) return 0;\n    if (history) {\n        int tocopy = history_len;\n\n        new = malloc(sizeof(char*)*len);\n        if (new == NULL) return 0;\n\n        /* If we can't copy everything, free the elements we'll not use. */\n        if (len < tocopy) {\n            int j;\n\n            for (j = 0; j < tocopy-len; j++) free(history[j]);\n            tocopy = len;\n        }\n        memset(new,0,sizeof(char*)*len);\n        memcpy(new,history+(history_len-tocopy), sizeof(char*)*tocopy);\n        free(history);\n        history = new;\n    }\n    history_max_len = len;\n    if (history_len > history_max_len)\n        history_len = history_max_len;\n    return 1;\n}\n\n/* Save the history in the specified file. On success 0 is returned\n * otherwise -1 is returned. */\nint linenoiseHistorySave(const char *filename) {\n    FILE *fp = fopen(filename,\"w\");\n    int j;\n\n    if (fp == NULL) return -1;\n    for (j = 0; j < history_len; j++)\n        fprintf(fp,\"%s\\n\",history[j]);\n    fclose(fp);\n    return 0;\n}\n\n/* Load the history from the specified file. If the file does not exist\n * zero is returned and no operation is performed.\n *\n * If the file exists and the operation succeeded 0 is returned, otherwise\n * on error -1 is returned. */\nint linenoiseHistoryLoad(const char *filename) {\n    FILE *fp = fopen(filename,\"r\");\n    char buf[LINENOISE_MAX_LINE];\n\n    if (fp == NULL) return -1;\n\n    while (fgets(buf,LINENOISE_MAX_LINE,fp) != NULL) {\n        char *p;\n\n        p = strchr(buf,'\\r');\n        if (!p) p = strchr(buf,'\\n');\n        if (p) *p = '\\0';\n        linenoiseHistoryAdd(buf);\n    }\n    fclose(fp);\n    return 0;\n}\n"
  },
  {
    "path": "extern/deprecated/redis-2.8.21/deps/linenoise/linenoise.h",
    "content": "/* linenoise.h -- guerrilla line editing library against the idea that a\n * line editing lib needs to be 20,000 lines of C code.\n *\n * See linenoise.c for more information.\n *\n * ------------------------------------------------------------------------\n *\n * Copyright (c) 2010, Salvatore Sanfilippo <antirez at gmail dot com>\n * Copyright (c) 2010, Pieter Noordhuis <pcnoordhuis at gmail dot com>\n *\n * All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions are\n * met:\n *\n *  *  Redistributions of source code must retain the above copyright\n *     notice, this list of conditions and the following disclaimer.\n *\n *  *  Redistributions in binary form must reproduce the above copyright\n *     notice, this list of conditions and the following disclaimer in the\n *     documentation and/or other materials provided with the distribution.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n * \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\n * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\n * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\n * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\n * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n\n#ifndef __LINENOISE_H\n#define __LINENOISE_H\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\ntypedef struct linenoiseCompletions {\n  size_t len;\n  char **cvec;\n} linenoiseCompletions;\n\ntypedef void(linenoiseCompletionCallback)(const char *, linenoiseCompletions *);\nvoid linenoiseSetCompletionCallback(linenoiseCompletionCallback *);\nvoid linenoiseAddCompletion(linenoiseCompletions *, const char *);\n\nchar *linenoise(const char *prompt);\nint linenoiseHistoryAdd(const char *line);\nint linenoiseHistorySetMaxLen(int len);\nint linenoiseHistorySave(const char *filename);\nint linenoiseHistoryLoad(const char *filename);\nvoid linenoiseClearScreen(void);\nvoid linenoiseSetMultiLine(int ml);\nvoid linenoisePrintKeyCodes(void);\n\n#ifdef __cplusplus\n}\n#endif\n\n#endif /* __LINENOISE_H */\n"
  },
  {
    "path": "extern/deprecated/redis-2.8.21/deps/lua/COPYRIGHT",
    "content": "Lua License\n-----------\n\nLua is licensed under the terms of the MIT license reproduced below.\nThis means that Lua is free software and can be used for both academic\nand commercial purposes at absolutely no cost.\n\nFor details and rationale, see http://www.lua.org/license.html .\n\n===============================================================================\n\nCopyright (C) 1994-2012 Lua.org, PUC-Rio.\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in\nall copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\nTHE SOFTWARE.\n\n===============================================================================\n\n(end of COPYRIGHT)\n"
  },
  {
    "path": "extern/deprecated/redis-2.8.21/deps/lua/HISTORY",
    "content": "HISTORY for Lua 5.1\n\n* Changes from version 5.0 to 5.1\n  -------------------------------\n  Language:\n  + new module system.\n  + new semantics for control variables of fors.\n  + new semantics for setn/getn.\n  + new syntax/semantics for varargs.\n  + new long strings and comments.\n  + new `mod' operator (`%')\n  + new length operator #t\n  + metatables for all types\n  API:\n  + new functions: lua_createtable, lua_get(set)field, lua_push(to)integer.\n  + user supplies memory allocator (lua_open becomes lua_newstate).\n  + luaopen_* functions must be called through Lua.\n  Implementation:\n  + new configuration scheme via luaconf.h.\n  + incremental garbage collection.\n  + better handling of end-of-line in the lexer.\n  + fully reentrant parser (new Lua function `load')\n  + better support for 64-bit machines.\n  + native loadlib support for Mac OS X.\n  + standard distribution in only one library (lualib.a merged into lua.a)\n\n* Changes from version 4.0 to 5.0\n  -------------------------------\n  Language:\n  + lexical scoping.\n  + Lua coroutines.\n  + standard libraries now packaged in tables.\n  + tags replaced by metatables and tag methods replaced by metamethods,\n    stored in metatables.\n  + proper tail calls.\n  + each function can have its own global table, which can be shared.\n  + new __newindex metamethod, called when we insert a new key into a table.\n  + new block comments: --[[ ... ]].\n  + new generic for.\n  + new weak tables.\n  + new boolean type.\n  + new syntax \"local function\".\n  + (f()) returns the first value returned by f.\n  + {f()} fills a table with all values returned by f.\n  + \\n ignored in [[\\n .\n  + fixed and-or priorities.\n  + more general syntax for function definition (e.g. function a.x.y:f()...end).\n  + more general syntax for function calls (e.g. (print or write)(9)).\n  + new functions (time/date, tmpfile, unpack, require, load*, etc.).\n  API:\n  + chunks are loaded by using lua_load; new luaL_loadfile and luaL_loadbuffer.\n  + introduced lightweight userdata, a simple \"void*\" without a metatable.\n  + new error handling protocol: the core no longer prints error messages;\n    all errors are reported to the caller on the stack.\n  + new lua_atpanic for host cleanup.\n  + new, signal-safe, hook scheme.\n  Implementation:\n  + new license: MIT.\n  + new, faster, register-based virtual machine.\n  + support for external multithreading and coroutines.\n  + new and consistent error message format.\n  + the core no longer needs \"stdio.h\" for anything (except for a single\n    use of sprintf to convert numbers to strings).\n  + lua.c now runs the environment variable LUA_INIT, if present. It can\n    be \"@filename\", to run a file, or the chunk itself.\n  + support for user extensions in lua.c.\n    sample implementation given for command line editing.\n  + new dynamic loading library, active by default on several platforms.\n  + safe garbage-collector metamethods.\n  + precompiled bytecodes checked for integrity (secure binary dostring).\n  + strings are fully aligned.\n  + position capture in string.find.\n  + read('*l') can read lines with embedded zeros.\n\n* Changes from version 3.2 to 4.0\n  -------------------------------\n  Language:\n  + new \"break\" and \"for\" statements (both numerical and for tables).\n  + uniform treatment of globals: globals are now stored in a Lua table.\n  + improved error messages.\n  + no more '$debug': full speed *and* full debug information.\n  + new read form: read(N) for next N bytes.\n  + general read patterns now deprecated.\n    (still available with -DCOMPAT_READPATTERNS.)\n  + all return values are passed as arguments for the last function\n    (old semantics still available with -DLUA_COMPAT_ARGRET)\n  + garbage collection tag methods for tables now deprecated.\n  + there is now only one tag method for order.\n  API:\n  + New API: fully re-entrant, simpler, and more efficient.\n  + New debug API.\n  Implementation:\n  + faster than ever: cleaner virtual machine and new hashing algorithm.\n  + non-recursive garbage-collector algorithm.\n  + reduced memory usage for programs with many strings.\n  + improved treatment for memory allocation errors.\n  + improved support for 16-bit machines (we hope).\n  + code now compiles unmodified as both ANSI C and C++.\n  + numbers in bases other than 10 are converted using strtoul.\n  + new -f option in Lua to support #! scripts.\n  + luac can now combine text and binaries.\n\n* Changes from version 3.1 to 3.2\n  -------------------------------\n  + redirected all output in Lua's core to _ERRORMESSAGE and _ALERT.\n  + increased limit on the number of constants and globals per function\n    (from 2^16 to 2^24).\n  + debugging info (lua_debug and hooks) moved into lua_state and new API\n    functions provided to get and set this info.\n  + new debug lib gives full debugging access within Lua.\n  + new table functions \"foreachi\", \"sort\", \"tinsert\", \"tremove\", \"getn\".\n  + new io functions \"flush\", \"seek\".\n\n* Changes from version 3.0 to 3.1\n  -------------------------------\n  + NEW FEATURE: anonymous functions with closures (via \"upvalues\").\n  + new syntax:\n    - local variables in chunks.\n    - better scope control with DO block END.\n    - constructors can now be also written: { record-part; list-part }.\n    - more general syntax for function calls and lvalues, e.g.:\n      f(x).y=1\n      o:f(x,y):g(z)\n      f\"string\" is sugar for f(\"string\")\n  + strings may now contain arbitrary binary data (e.g., embedded zeros).\n  + major code re-organization and clean-up; reduced module interdependecies.\n  + no arbitrary limits on the total number of constants and globals.\n  + support for multiple global contexts.\n  + better syntax error messages.\n  + new traversal functions \"foreach\" and \"foreachvar\".\n  + the default for numbers is now double.\n    changing it to use floats or longs is easy.\n  + complete debug information stored in pre-compiled chunks.\n  + sample interpreter now prompts user when run interactively, and also\n    handles control-C interruptions gracefully.\n\n* Changes from version 2.5 to 3.0\n  -------------------------------\n  + NEW CONCEPT: \"tag methods\".\n    Tag methods replace fallbacks as the meta-mechanism for extending the\n    semantics of Lua. Whereas fallbacks had a global nature, tag methods\n    work on objects having the same tag (e.g., groups of tables).\n    Existing code that uses fallbacks should work without change.\n  + new, general syntax for constructors {[exp] = exp, ... }.\n  + support for handling variable number of arguments in functions (varargs).\n  + support for conditional compilation ($if ... $else ... $end).\n  + cleaner semantics in API simplifies host code.\n  + better support for writing libraries (auxlib.h).\n  + better type checking and error messages in the standard library.\n  + luac can now also undump.\n\n* Changes from version 2.4 to 2.5\n  -------------------------------\n  + io and string libraries are now based on pattern matching;\n    the old libraries are still available for compatibility\n  + dofile and dostring can now return values (via return statement)\n  + better support for 16- and 64-bit machines\n  + expanded documentation, with more examples\n\n* Changes from version 2.2 to 2.4\n  -------------------------------\n  + external compiler creates portable binary files that can be loaded faster\n  + interface for debugging and profiling\n  + new \"getglobal\" fallback\n  + new functions for handling references to Lua objects\n  + new functions in standard lib\n  + only one copy of each string is stored\n  + expanded documentation, with more examples\n\n* Changes from version 2.1 to 2.2\n  -------------------------------\n  + functions now may be declared with any \"lvalue\" as a name\n  + garbage collection of functions\n  + support for pipes\n\n* Changes from version 1.1 to 2.1\n  -------------------------------\n  + object-oriented support\n  + fallbacks\n  + simplified syntax for tables\n  + many internal improvements\n\n(end of HISTORY)\n"
  },
  {
    "path": "extern/deprecated/redis-2.8.21/deps/lua/INSTALL",
    "content": "INSTALL for Lua 5.1\n\n* Building Lua\n  ------------\n  Lua is built in the src directory, but the build process can be\n  controlled from the top-level Makefile.\n\n  Building Lua on Unix systems should be very easy. First do \"make\" and\n  see if your platform is listed. If so, just do \"make xxx\", where xxx\n  is your platform name. The platforms currently supported are:\n    aix ansi bsd freebsd generic linux macosx mingw posix solaris\n\n  If your platform is not listed, try the closest one or posix, generic,\n  ansi, in this order.\n\n  See below for customization instructions and for instructions on how\n  to build with other Windows compilers.\n\n  If you want to check that Lua has been built correctly, do \"make test\"\n  after building Lua. Also, have a look at the example programs in test.\n\n* Installing Lua\n  --------------\n  Once you have built Lua, you may want to install it in an official\n  place in your system. In this case, do \"make install\". The official\n  place and the way to install files are defined in Makefile. You must\n  have the right permissions to install files.\n\n  If you want to build and install Lua in one step, do \"make xxx install\",\n  where xxx is your platform name.\n\n  If you want to install Lua locally, then do \"make local\". This will\n  create directories bin, include, lib, man, and install Lua there as\n  follows:\n\n    bin:\tlua luac\n    include:\tlua.h luaconf.h lualib.h lauxlib.h lua.hpp\n    lib:\tliblua.a\n    man/man1:\tlua.1 luac.1\n\n  These are the only directories you need for development.\n\n  There are man pages for lua and luac, in both nroff and html, and a\n  reference manual in html in doc, some sample code in test, and some\n  useful stuff in etc. You don't need these directories for development.\n\n  If you want to install Lua locally, but in some other directory, do\n  \"make install INSTALL_TOP=xxx\", where xxx is your chosen directory.\n\n  See below for instructions for Windows and other systems.\n\n* Customization\n  -------------\n  Three things can be customized by editing a file:\n    - Where and how to install Lua -- edit Makefile.\n    - How to build Lua -- edit src/Makefile.\n    - Lua features -- edit src/luaconf.h.\n\n  You don't actually need to edit the Makefiles because you may set the\n  relevant variables when invoking make.\n\n  On the other hand, if you need to select some Lua features, you'll need\n  to edit src/luaconf.h. The edited file will be the one installed, and\n  it will be used by any Lua clients that you build, to ensure consistency.\n\n  We strongly recommend that you enable dynamic loading. This is done\n  automatically for all platforms listed above that have this feature\n  (and also Windows). See src/luaconf.h and also src/Makefile.\n\n* Building Lua on Windows and other systems\n  -----------------------------------------\n  If you're not using the usual Unix tools, then the instructions for\n  building Lua depend on the compiler you use. You'll need to create\n  projects (or whatever your compiler uses) for building the library,\n  the interpreter, and the compiler, as follows:\n\n  library:\tlapi.c lcode.c ldebug.c ldo.c ldump.c lfunc.c lgc.c llex.c\n\t\tlmem.c lobject.c lopcodes.c lparser.c lstate.c lstring.c\n\t\tltable.c ltm.c lundump.c lvm.c lzio.c\n\t\tlauxlib.c lbaselib.c ldblib.c liolib.c lmathlib.c loslib.c\n\t\tltablib.c lstrlib.c loadlib.c linit.c\n\n  interpreter:\tlibrary, lua.c\n\n  compiler:\tlibrary, luac.c print.c\n\n  If you use Visual Studio .NET, you can use etc/luavs.bat in its\n  \"Command Prompt\".\n\n  If all you want is to build the Lua interpreter, you may put all .c files\n  in a single project, except for luac.c and print.c. Or just use etc/all.c.\n\n  To use Lua as a library in your own programs, you'll need to know how to\n  create and use libraries with your compiler.\n\n  As mentioned above, you may edit luaconf.h to select some features before\n  building Lua.\n\n(end of INSTALL)\n"
  },
  {
    "path": "extern/deprecated/redis-2.8.21/deps/lua/Makefile",
    "content": "# makefile for installing Lua\n# see INSTALL for installation instructions\n# see src/Makefile and src/luaconf.h for further customization\n\n# == CHANGE THE SETTINGS BELOW TO SUIT YOUR ENVIRONMENT =======================\n\n# Your platform. See PLATS for possible values.\nPLAT= none\n\n# Where to install. The installation starts in the src and doc directories,\n# so take care if INSTALL_TOP is not an absolute path.\nINSTALL_TOP= /usr/local\nINSTALL_BIN= $(INSTALL_TOP)/bin\nINSTALL_INC= $(INSTALL_TOP)/include\nINSTALL_LIB= $(INSTALL_TOP)/lib\nINSTALL_MAN= $(INSTALL_TOP)/man/man1\n#\n# You probably want to make INSTALL_LMOD and INSTALL_CMOD consistent with\n# LUA_ROOT, LUA_LDIR, and LUA_CDIR in luaconf.h (and also with etc/lua.pc).\nINSTALL_LMOD= $(INSTALL_TOP)/share/lua/$V\nINSTALL_CMOD= $(INSTALL_TOP)/lib/lua/$V\n\n# How to install. If your install program does not support \"-p\", then you\n# may have to run ranlib on the installed liblua.a (do \"make ranlib\").\nINSTALL= install -p\nINSTALL_EXEC= $(INSTALL) -m 0755\nINSTALL_DATA= $(INSTALL) -m 0644\n#\n# If you don't have install you can use cp instead.\n# INSTALL= cp -p\n# INSTALL_EXEC= $(INSTALL)\n# INSTALL_DATA= $(INSTALL)\n\n# Utilities.\nMKDIR= mkdir -p\nRANLIB= ranlib\n\n# == END OF USER SETTINGS. NO NEED TO CHANGE ANYTHING BELOW THIS LINE =========\n\n# Convenience platforms targets.\nPLATS= aix ansi bsd freebsd generic linux macosx mingw posix solaris\n\n# What to install.\nTO_BIN= lua luac\nTO_INC= lua.h luaconf.h lualib.h lauxlib.h ../etc/lua.hpp\nTO_LIB= liblua.a\nTO_MAN= lua.1 luac.1\n\n# Lua version and release.\nV= 5.1\nR= 5.1.5\n\nall:\t$(PLAT)\n\n$(PLATS) clean:\n\tcd src && $(MAKE) $@\n\ntest:\tdummy\n\tsrc/lua test/hello.lua\n\ninstall: dummy\n\tcd src && $(MKDIR) $(INSTALL_BIN) $(INSTALL_INC) $(INSTALL_LIB) $(INSTALL_MAN) $(INSTALL_LMOD) $(INSTALL_CMOD)\n\tcd src && $(INSTALL_EXEC) $(TO_BIN) $(INSTALL_BIN)\n\tcd src && $(INSTALL_DATA) $(TO_INC) $(INSTALL_INC)\n\tcd src && $(INSTALL_DATA) $(TO_LIB) $(INSTALL_LIB)\n\tcd doc && $(INSTALL_DATA) $(TO_MAN) $(INSTALL_MAN)\n\nranlib:\n\tcd src && cd $(INSTALL_LIB) && $(RANLIB) $(TO_LIB)\n\nlocal:\n\t$(MAKE) install INSTALL_TOP=..\n\nnone:\n\t@echo \"Please do\"\n\t@echo \"   make PLATFORM\"\n\t@echo \"where PLATFORM is one of these:\"\n\t@echo \"   $(PLATS)\"\n\t@echo \"See INSTALL for complete instructions.\"\n\n# make may get confused with test/ and INSTALL in a case-insensitive OS\ndummy:\n\n# echo config parameters\necho:\n\t@echo \"\"\n\t@echo \"These are the parameters currently set in src/Makefile to build Lua $R:\"\n\t@echo \"\"\n\t@cd src && $(MAKE) -s echo\n\t@echo \"\"\n\t@echo \"These are the parameters currently set in Makefile to install Lua $R:\"\n\t@echo \"\"\n\t@echo \"PLAT = $(PLAT)\"\n\t@echo \"INSTALL_TOP = $(INSTALL_TOP)\"\n\t@echo \"INSTALL_BIN = $(INSTALL_BIN)\"\n\t@echo \"INSTALL_INC = $(INSTALL_INC)\"\n\t@echo \"INSTALL_LIB = $(INSTALL_LIB)\"\n\t@echo \"INSTALL_MAN = $(INSTALL_MAN)\"\n\t@echo \"INSTALL_LMOD = $(INSTALL_LMOD)\"\n\t@echo \"INSTALL_CMOD = $(INSTALL_CMOD)\"\n\t@echo \"INSTALL_EXEC = $(INSTALL_EXEC)\"\n\t@echo \"INSTALL_DATA = $(INSTALL_DATA)\"\n\t@echo \"\"\n\t@echo \"See also src/luaconf.h .\"\n\t@echo \"\"\n\n# echo private config parameters\npecho:\n\t@echo \"V = $(V)\"\n\t@echo \"R = $(R)\"\n\t@echo \"TO_BIN = $(TO_BIN)\"\n\t@echo \"TO_INC = $(TO_INC)\"\n\t@echo \"TO_LIB = $(TO_LIB)\"\n\t@echo \"TO_MAN = $(TO_MAN)\"\n\n# echo config parameters as Lua code\n# uncomment the last sed expression if you want nil instead of empty strings\nlecho:\n\t@echo \"-- installation parameters for Lua $R\"\n\t@echo \"VERSION = '$V'\"\n\t@echo \"RELEASE = '$R'\"\n\t@$(MAKE) echo | grep = | sed -e 's/= /= \"/' -e 's/$$/\"/' #-e 's/\"\"/nil/'\n\t@echo \"-- EOF\"\n\n# list targets that do not create files (but not all makes understand .PHONY)\n.PHONY: all $(PLATS) clean test install local none dummy echo pecho lecho\n\n# (end of Makefile)\n"
  },
  {
    "path": "extern/deprecated/redis-2.8.21/deps/lua/README",
    "content": "README for Lua 5.1\n\nSee INSTALL for installation instructions.\nSee HISTORY for a summary of changes since the last released version.\n\n* What is Lua?\n  ------------\n  Lua is a powerful, light-weight programming language designed for extending\n  applications. Lua is also frequently used as a general-purpose, stand-alone\n  language. Lua is free software.\n\n  For complete information, visit Lua's web site at http://www.lua.org/ .\n  For an executive summary, see http://www.lua.org/about.html .\n\n  Lua has been used in many different projects around the world.\n  For a short list, see http://www.lua.org/uses.html .\n\n* Availability\n  ------------\n  Lua is freely available for both academic and commercial purposes.\n  See COPYRIGHT and http://www.lua.org/license.html for details.\n  Lua can be downloaded at http://www.lua.org/download.html .\n\n* Installation\n  ------------\n  Lua is implemented in pure ANSI C, and compiles unmodified in all known\n  platforms that have an ANSI C compiler. In most Unix-like platforms, simply\n  do \"make\" with a suitable target. See INSTALL for detailed instructions.\n\n* Origin\n  ------\n  Lua is developed at Lua.org, a laboratory of the Department of Computer\n  Science of PUC-Rio (the Pontifical Catholic University of Rio de Janeiro\n  in Brazil).\n  For more information about the authors, see http://www.lua.org/authors.html .\n\n(end of README)\n"
  },
  {
    "path": "extern/deprecated/redis-2.8.21/deps/lua/doc/contents.html",
    "content": "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\">\n<HTML>\n<HEAD>\n<TITLE>Lua 5.1 Reference Manual - contents</TITLE>\n<LINK REL=\"stylesheet\" TYPE=\"text/css\" HREF=\"lua.css\">\n<META HTTP-EQUIV=\"content-type\" CONTENT=\"text/html; charset=utf-8\">\n<STYLE TYPE=\"text/css\">\nul {\n\tlist-style-type: none ;\n}\n</STYLE>\n</HEAD>\n\n<BODY>\n\n<HR>\n<H1>\n<A HREF=\"http://www.lua.org/\"><IMG SRC=\"logo.gif\" ALT=\"\" BORDER=0></A>\nLua 5.1 Reference Manual\n</H1>\n\n<P>\nThe reference manual is the official definition of the Lua language.\nFor a complete introduction to Lua programming, see the book\n<A HREF=\"http://www.lua.org/docs.html#pil\">Programming in Lua</A>.\n\n<P>\nThis manual is also available as a book:\n<BLOCKQUOTE>\n<A HREF=\"http://www.amazon.com/exec/obidos/ASIN/8590379833/lua-indexmanual-20\">\n<IMG SRC=\"cover.png\" ALT=\"\" TITLE=\"buy from Amazon\" BORDER=1 ALIGN=\"left\" HSPACE=12>\n</A>\n<B>Lua 5.1 Reference Manual</B>\n<BR>by R. Ierusalimschy, L. H. de Figueiredo, W. Celes\n<BR>Lua.org, August 2006\n<BR>ISBN 85-903798-3-3\n<BR CLEAR=\"all\">\n</BLOCKQUOTE>\n\n<P>\n<A HREF=\"http://www.amazon.com/exec/obidos/ASIN/8590379833/lua-indexmanual-20\">Buy a copy</A>\nof this book and\n<A HREF=\"http://www.lua.org/donations.html\">help to support</A>\nthe Lua project.\n\n<P>\n<A HREF=\"manual.html\">start</A>\n&middot;\n<A HREF=\"#contents\">contents</A>\n&middot;\n<A HREF=\"#index\">index</A>\n&middot;\n<A HREF=\"http://www.lua.org/manual/\">other versions</A>\n<HR>\n<SMALL>\nCopyright &copy; 2006&ndash;2012 Lua.org, PUC-Rio.\nFreely available under the terms of the\n<A HREF=\"http://www.lua.org/license.html\">Lua license</A>.\n</SMALL>\n\n<H2><A NAME=\"contents\">Contents</A></H2>\n<UL style=\"padding: 0\">\n<LI><A HREF=\"manual.html\">1 &ndash; Introduction</A>\n<P>\n<LI><A HREF=\"manual.html#2\">2 &ndash; The Language</A>\n<UL>\n<LI><A HREF=\"manual.html#2.1\">2.1 &ndash; Lexical Conventions</A>\n<LI><A HREF=\"manual.html#2.2\">2.2 &ndash; Values and Types</A>\n<UL>\n<LI><A HREF=\"manual.html#2.2.1\">2.2.1 &ndash; Coercion</A>\n</UL>\n<LI><A HREF=\"manual.html#2.3\">2.3 &ndash; Variables</A>\n<LI><A HREF=\"manual.html#2.4\">2.4 &ndash; Statements</A>\n<UL>\n<LI><A HREF=\"manual.html#2.4.1\">2.4.1 &ndash; Chunks</A>\n<LI><A HREF=\"manual.html#2.4.2\">2.4.2 &ndash; Blocks</A>\n<LI><A HREF=\"manual.html#2.4.3\">2.4.3 &ndash; Assignment</A>\n<LI><A HREF=\"manual.html#2.4.4\">2.4.4 &ndash; Control Structures</A>\n<LI><A HREF=\"manual.html#2.4.5\">2.4.5 &ndash; For Statement</A>\n<LI><A HREF=\"manual.html#2.4.6\">2.4.6 &ndash; Function Calls as Statements</A>\n<LI><A HREF=\"manual.html#2.4.7\">2.4.7 &ndash; Local Declarations</A>\n</UL>\n<LI><A HREF=\"manual.html#2.5\">2.5 &ndash; Expressions</A>\n<UL>\n<LI><A HREF=\"manual.html#2.5.1\">2.5.1 &ndash; Arithmetic Operators</A>\n<LI><A HREF=\"manual.html#2.5.2\">2.5.2 &ndash; Relational Operators</A>\n<LI><A HREF=\"manual.html#2.5.3\">2.5.3 &ndash; Logical Operators</A>\n<LI><A HREF=\"manual.html#2.5.4\">2.5.4 &ndash; Concatenation</A>\n<LI><A HREF=\"manual.html#2.5.5\">2.5.5 &ndash; The Length Operator</A>\n<LI><A HREF=\"manual.html#2.5.6\">2.5.6 &ndash; Precedence</A>\n<LI><A HREF=\"manual.html#2.5.7\">2.5.7 &ndash; Table Constructors</A>\n<LI><A HREF=\"manual.html#2.5.8\">2.5.8 &ndash; Function Calls</A>\n<LI><A HREF=\"manual.html#2.5.9\">2.5.9 &ndash; Function Definitions</A>\n</UL>\n<LI><A HREF=\"manual.html#2.6\">2.6 &ndash; Visibility Rules</A>\n<LI><A HREF=\"manual.html#2.7\">2.7 &ndash; Error Handling</A>\n<LI><A HREF=\"manual.html#2.8\">2.8 &ndash; Metatables</A>\n<LI><A HREF=\"manual.html#2.9\">2.9 &ndash; Environments</A>\n<LI><A HREF=\"manual.html#2.10\">2.10 &ndash; Garbage Collection</A>\n<UL>\n<LI><A HREF=\"manual.html#2.10.1\">2.10.1 &ndash; Garbage-Collection Metamethods</A>\n<LI><A HREF=\"manual.html#2.10.2\">2.10.2 &ndash; Weak Tables</A>\n</UL>\n<LI><A HREF=\"manual.html#2.11\">2.11 &ndash; Coroutines</A>\n</UL>\n<P>\n<LI><A HREF=\"manual.html#3\">3 &ndash; The Application Program Interface</A>\n<UL>\n<LI><A HREF=\"manual.html#3.1\">3.1 &ndash; The Stack</A>\n<LI><A HREF=\"manual.html#3.2\">3.2 &ndash; Stack Size</A>\n<LI><A HREF=\"manual.html#3.3\">3.3 &ndash; Pseudo-Indices</A>\n<LI><A HREF=\"manual.html#3.4\">3.4 &ndash; C Closures</A>\n<LI><A HREF=\"manual.html#3.5\">3.5 &ndash; Registry</A>\n<LI><A HREF=\"manual.html#3.6\">3.6 &ndash; Error Handling in C</A>\n<LI><A HREF=\"manual.html#3.7\">3.7 &ndash; Functions and Types</A>\n<LI><A HREF=\"manual.html#3.8\">3.8 &ndash; The Debug Interface</A>\n</UL>\n<P>\n<LI><A HREF=\"manual.html#4\">4 &ndash; The Auxiliary Library</A>\n<UL>\n<LI><A HREF=\"manual.html#4.1\">4.1 &ndash; Functions and Types</A>\n</UL>\n<P>\n<LI><A HREF=\"manual.html#5\">5 &ndash; Standard Libraries</A>\n<UL>\n<LI><A HREF=\"manual.html#5.1\">5.1 &ndash; Basic Functions</A>\n<LI><A HREF=\"manual.html#5.2\">5.2 &ndash; Coroutine Manipulation</A>\n<LI><A HREF=\"manual.html#5.3\">5.3 &ndash; Modules</A>\n<LI><A HREF=\"manual.html#5.4\">5.4 &ndash; String Manipulation</A>\n<UL>\n<LI><A HREF=\"manual.html#5.4.1\">5.4.1 &ndash; Patterns</A>\n</UL>\n<LI><A HREF=\"manual.html#5.5\">5.5 &ndash; Table Manipulation</A>\n<LI><A HREF=\"manual.html#5.6\">5.6 &ndash; Mathematical Functions</A>\n<LI><A HREF=\"manual.html#5.7\">5.7 &ndash; Input and Output Facilities</A>\n<LI><A HREF=\"manual.html#5.8\">5.8 &ndash; Operating System Facilities</A>\n<LI><A HREF=\"manual.html#5.9\">5.9 &ndash; The Debug Library</A>\n</UL>\n<P>\n<LI><A HREF=\"manual.html#6\">6 &ndash; Lua Stand-alone</A>\n<P>\n<LI><A HREF=\"manual.html#7\">7 &ndash; Incompatibilities with the Previous Version</A>\n<UL>\n<LI><A HREF=\"manual.html#7.1\">7.1 &ndash; Changes in the Language</A>\n<LI><A HREF=\"manual.html#7.2\">7.2 &ndash; Changes in the Libraries</A>\n<LI><A HREF=\"manual.html#7.3\">7.3 &ndash; Changes in the API</A>\n</UL>\n<P>\n<LI><A HREF=\"manual.html#8\">8 &ndash; The Complete Syntax of Lua</A>\n</UL>\n\n<H2><A NAME=\"index\">Index</A></H2>\n<TABLE WIDTH=\"100%\">\n<TR VALIGN=\"top\">\n<TD>\n<H3><A NAME=\"functions\">Lua functions</A></H3>\n<A HREF=\"manual.html#pdf-_G\">_G</A><BR>\n<A HREF=\"manual.html#pdf-_VERSION\">_VERSION</A><BR>\n<P>\n\n<A HREF=\"manual.html#pdf-assert\">assert</A><BR>\n<A HREF=\"manual.html#pdf-collectgarbage\">collectgarbage</A><BR>\n<A HREF=\"manual.html#pdf-dofile\">dofile</A><BR>\n<A HREF=\"manual.html#pdf-error\">error</A><BR>\n<A HREF=\"manual.html#pdf-getfenv\">getfenv</A><BR>\n<A HREF=\"manual.html#pdf-getmetatable\">getmetatable</A><BR>\n<A HREF=\"manual.html#pdf-ipairs\">ipairs</A><BR>\n<A HREF=\"manual.html#pdf-load\">load</A><BR>\n<A HREF=\"manual.html#pdf-loadfile\">loadfile</A><BR>\n<A HREF=\"manual.html#pdf-loadstring\">loadstring</A><BR>\n<A HREF=\"manual.html#pdf-module\">module</A><BR>\n<A HREF=\"manual.html#pdf-next\">next</A><BR>\n<A HREF=\"manual.html#pdf-pairs\">pairs</A><BR>\n<A HREF=\"manual.html#pdf-pcall\">pcall</A><BR>\n<A HREF=\"manual.html#pdf-print\">print</A><BR>\n<A HREF=\"manual.html#pdf-rawequal\">rawequal</A><BR>\n<A HREF=\"manual.html#pdf-rawget\">rawget</A><BR>\n<A HREF=\"manual.html#pdf-rawset\">rawset</A><BR>\n<A HREF=\"manual.html#pdf-require\">require</A><BR>\n<A HREF=\"manual.html#pdf-select\">select</A><BR>\n<A HREF=\"manual.html#pdf-setfenv\">setfenv</A><BR>\n<A HREF=\"manual.html#pdf-setmetatable\">setmetatable</A><BR>\n<A HREF=\"manual.html#pdf-tonumber\">tonumber</A><BR>\n<A HREF=\"manual.html#pdf-tostring\">tostring</A><BR>\n<A HREF=\"manual.html#pdf-type\">type</A><BR>\n<A HREF=\"manual.html#pdf-unpack\">unpack</A><BR>\n<A HREF=\"manual.html#pdf-xpcall\">xpcall</A><BR>\n<P>\n\n<A HREF=\"manual.html#pdf-coroutine.create\">coroutine.create</A><BR>\n<A HREF=\"manual.html#pdf-coroutine.resume\">coroutine.resume</A><BR>\n<A HREF=\"manual.html#pdf-coroutine.running\">coroutine.running</A><BR>\n<A HREF=\"manual.html#pdf-coroutine.status\">coroutine.status</A><BR>\n<A HREF=\"manual.html#pdf-coroutine.wrap\">coroutine.wrap</A><BR>\n<A HREF=\"manual.html#pdf-coroutine.yield\">coroutine.yield</A><BR>\n<P>\n\n<A HREF=\"manual.html#pdf-debug.debug\">debug.debug</A><BR>\n<A HREF=\"manual.html#pdf-debug.getfenv\">debug.getfenv</A><BR>\n<A HREF=\"manual.html#pdf-debug.gethook\">debug.gethook</A><BR>\n<A HREF=\"manual.html#pdf-debug.getinfo\">debug.getinfo</A><BR>\n<A HREF=\"manual.html#pdf-debug.getlocal\">debug.getlocal</A><BR>\n<A HREF=\"manual.html#pdf-debug.getmetatable\">debug.getmetatable</A><BR>\n<A HREF=\"manual.html#pdf-debug.getregistry\">debug.getregistry</A><BR>\n<A HREF=\"manual.html#pdf-debug.getupvalue\">debug.getupvalue</A><BR>\n<A HREF=\"manual.html#pdf-debug.setfenv\">debug.setfenv</A><BR>\n<A HREF=\"manual.html#pdf-debug.sethook\">debug.sethook</A><BR>\n<A HREF=\"manual.html#pdf-debug.setlocal\">debug.setlocal</A><BR>\n<A HREF=\"manual.html#pdf-debug.setmetatable\">debug.setmetatable</A><BR>\n<A HREF=\"manual.html#pdf-debug.setupvalue\">debug.setupvalue</A><BR>\n<A HREF=\"manual.html#pdf-debug.traceback\">debug.traceback</A><BR>\n\n</TD>\n<TD>\n<H3>&nbsp;</H3>\n<A HREF=\"manual.html#pdf-file:close\">file:close</A><BR>\n<A HREF=\"manual.html#pdf-file:flush\">file:flush</A><BR>\n<A HREF=\"manual.html#pdf-file:lines\">file:lines</A><BR>\n<A HREF=\"manual.html#pdf-file:read\">file:read</A><BR>\n<A HREF=\"manual.html#pdf-file:seek\">file:seek</A><BR>\n<A HREF=\"manual.html#pdf-file:setvbuf\">file:setvbuf</A><BR>\n<A HREF=\"manual.html#pdf-file:write\">file:write</A><BR>\n<P>\n\n<A HREF=\"manual.html#pdf-io.close\">io.close</A><BR>\n<A HREF=\"manual.html#pdf-io.flush\">io.flush</A><BR>\n<A HREF=\"manual.html#pdf-io.input\">io.input</A><BR>\n<A HREF=\"manual.html#pdf-io.lines\">io.lines</A><BR>\n<A HREF=\"manual.html#pdf-io.open\">io.open</A><BR>\n<A HREF=\"manual.html#pdf-io.output\">io.output</A><BR>\n<A HREF=\"manual.html#pdf-io.popen\">io.popen</A><BR>\n<A HREF=\"manual.html#pdf-io.read\">io.read</A><BR>\n<A HREF=\"manual.html#pdf-io.stderr\">io.stderr</A><BR>\n<A HREF=\"manual.html#pdf-io.stdin\">io.stdin</A><BR>\n<A HREF=\"manual.html#pdf-io.stdout\">io.stdout</A><BR>\n<A HREF=\"manual.html#pdf-io.tmpfile\">io.tmpfile</A><BR>\n<A HREF=\"manual.html#pdf-io.type\">io.type</A><BR>\n<A HREF=\"manual.html#pdf-io.write\">io.write</A><BR>\n<P>\n\n<A HREF=\"manual.html#pdf-math.abs\">math.abs</A><BR>\n<A HREF=\"manual.html#pdf-math.acos\">math.acos</A><BR>\n<A HREF=\"manual.html#pdf-math.asin\">math.asin</A><BR>\n<A HREF=\"manual.html#pdf-math.atan\">math.atan</A><BR>\n<A HREF=\"manual.html#pdf-math.atan2\">math.atan2</A><BR>\n<A HREF=\"manual.html#pdf-math.ceil\">math.ceil</A><BR>\n<A HREF=\"manual.html#pdf-math.cos\">math.cos</A><BR>\n<A HREF=\"manual.html#pdf-math.cosh\">math.cosh</A><BR>\n<A HREF=\"manual.html#pdf-math.deg\">math.deg</A><BR>\n<A HREF=\"manual.html#pdf-math.exp\">math.exp</A><BR>\n<A HREF=\"manual.html#pdf-math.floor\">math.floor</A><BR>\n<A HREF=\"manual.html#pdf-math.fmod\">math.fmod</A><BR>\n<A HREF=\"manual.html#pdf-math.frexp\">math.frexp</A><BR>\n<A HREF=\"manual.html#pdf-math.huge\">math.huge</A><BR>\n<A HREF=\"manual.html#pdf-math.ldexp\">math.ldexp</A><BR>\n<A HREF=\"manual.html#pdf-math.log\">math.log</A><BR>\n<A HREF=\"manual.html#pdf-math.log10\">math.log10</A><BR>\n<A HREF=\"manual.html#pdf-math.max\">math.max</A><BR>\n<A HREF=\"manual.html#pdf-math.min\">math.min</A><BR>\n<A HREF=\"manual.html#pdf-math.modf\">math.modf</A><BR>\n<A HREF=\"manual.html#pdf-math.pi\">math.pi</A><BR>\n<A HREF=\"manual.html#pdf-math.pow\">math.pow</A><BR>\n<A HREF=\"manual.html#pdf-math.rad\">math.rad</A><BR>\n<A HREF=\"manual.html#pdf-math.random\">math.random</A><BR>\n<A HREF=\"manual.html#pdf-math.randomseed\">math.randomseed</A><BR>\n<A HREF=\"manual.html#pdf-math.sin\">math.sin</A><BR>\n<A HREF=\"manual.html#pdf-math.sinh\">math.sinh</A><BR>\n<A HREF=\"manual.html#pdf-math.sqrt\">math.sqrt</A><BR>\n<A HREF=\"manual.html#pdf-math.tan\">math.tan</A><BR>\n<A HREF=\"manual.html#pdf-math.tanh\">math.tanh</A><BR>\n<P>\n\n<A HREF=\"manual.html#pdf-os.clock\">os.clock</A><BR>\n<A HREF=\"manual.html#pdf-os.date\">os.date</A><BR>\n<A HREF=\"manual.html#pdf-os.difftime\">os.difftime</A><BR>\n<A HREF=\"manual.html#pdf-os.execute\">os.execute</A><BR>\n<A HREF=\"manual.html#pdf-os.exit\">os.exit</A><BR>\n<A HREF=\"manual.html#pdf-os.getenv\">os.getenv</A><BR>\n<A HREF=\"manual.html#pdf-os.remove\">os.remove</A><BR>\n<A HREF=\"manual.html#pdf-os.rename\">os.rename</A><BR>\n<A HREF=\"manual.html#pdf-os.setlocale\">os.setlocale</A><BR>\n<A HREF=\"manual.html#pdf-os.time\">os.time</A><BR>\n<A HREF=\"manual.html#pdf-os.tmpname\">os.tmpname</A><BR>\n<P>\n\n<A HREF=\"manual.html#pdf-package.cpath\">package.cpath</A><BR>\n<A HREF=\"manual.html#pdf-package.loaded\">package.loaded</A><BR>\n<A HREF=\"manual.html#pdf-package.loaders\">package.loaders</A><BR>\n<A HREF=\"manual.html#pdf-package.loadlib\">package.loadlib</A><BR>\n<A HREF=\"manual.html#pdf-package.path\">package.path</A><BR>\n<A HREF=\"manual.html#pdf-package.preload\">package.preload</A><BR>\n<A HREF=\"manual.html#pdf-package.seeall\">package.seeall</A><BR>\n<P>\n\n<A HREF=\"manual.html#pdf-string.byte\">string.byte</A><BR>\n<A HREF=\"manual.html#pdf-string.char\">string.char</A><BR>\n<A HREF=\"manual.html#pdf-string.dump\">string.dump</A><BR>\n<A HREF=\"manual.html#pdf-string.find\">string.find</A><BR>\n<A HREF=\"manual.html#pdf-string.format\">string.format</A><BR>\n<A HREF=\"manual.html#pdf-string.gmatch\">string.gmatch</A><BR>\n<A HREF=\"manual.html#pdf-string.gsub\">string.gsub</A><BR>\n<A HREF=\"manual.html#pdf-string.len\">string.len</A><BR>\n<A HREF=\"manual.html#pdf-string.lower\">string.lower</A><BR>\n<A HREF=\"manual.html#pdf-string.match\">string.match</A><BR>\n<A HREF=\"manual.html#pdf-string.rep\">string.rep</A><BR>\n<A HREF=\"manual.html#pdf-string.reverse\">string.reverse</A><BR>\n<A HREF=\"manual.html#pdf-string.sub\">string.sub</A><BR>\n<A HREF=\"manual.html#pdf-string.upper\">string.upper</A><BR>\n<P>\n\n<A HREF=\"manual.html#pdf-table.concat\">table.concat</A><BR>\n<A HREF=\"manual.html#pdf-table.insert\">table.insert</A><BR>\n<A HREF=\"manual.html#pdf-table.maxn\">table.maxn</A><BR>\n<A HREF=\"manual.html#pdf-table.remove\">table.remove</A><BR>\n<A HREF=\"manual.html#pdf-table.sort\">table.sort</A><BR>\n\n</TD>\n<TD>\n<H3>C API</H3>\n<A HREF=\"manual.html#lua_Alloc\">lua_Alloc</A><BR>\n<A HREF=\"manual.html#lua_CFunction\">lua_CFunction</A><BR>\n<A HREF=\"manual.html#lua_Debug\">lua_Debug</A><BR>\n<A HREF=\"manual.html#lua_Hook\">lua_Hook</A><BR>\n<A HREF=\"manual.html#lua_Integer\">lua_Integer</A><BR>\n<A HREF=\"manual.html#lua_Number\">lua_Number</A><BR>\n<A HREF=\"manual.html#lua_Reader\">lua_Reader</A><BR>\n<A HREF=\"manual.html#lua_State\">lua_State</A><BR>\n<A HREF=\"manual.html#lua_Writer\">lua_Writer</A><BR>\n<P>\n\n<A HREF=\"manual.html#lua_atpanic\">lua_atpanic</A><BR>\n<A HREF=\"manual.html#lua_call\">lua_call</A><BR>\n<A HREF=\"manual.html#lua_checkstack\">lua_checkstack</A><BR>\n<A HREF=\"manual.html#lua_close\">lua_close</A><BR>\n<A HREF=\"manual.html#lua_concat\">lua_concat</A><BR>\n<A HREF=\"manual.html#lua_cpcall\">lua_cpcall</A><BR>\n<A HREF=\"manual.html#lua_createtable\">lua_createtable</A><BR>\n<A HREF=\"manual.html#lua_dump\">lua_dump</A><BR>\n<A HREF=\"manual.html#lua_equal\">lua_equal</A><BR>\n<A HREF=\"manual.html#lua_error\">lua_error</A><BR>\n<A HREF=\"manual.html#lua_gc\">lua_gc</A><BR>\n<A HREF=\"manual.html#lua_getallocf\">lua_getallocf</A><BR>\n<A HREF=\"manual.html#lua_getfenv\">lua_getfenv</A><BR>\n<A HREF=\"manual.html#lua_getfield\">lua_getfield</A><BR>\n<A HREF=\"manual.html#lua_getglobal\">lua_getglobal</A><BR>\n<A HREF=\"manual.html#lua_gethook\">lua_gethook</A><BR>\n<A HREF=\"manual.html#lua_gethookcount\">lua_gethookcount</A><BR>\n<A HREF=\"manual.html#lua_gethookmask\">lua_gethookmask</A><BR>\n<A HREF=\"manual.html#lua_getinfo\">lua_getinfo</A><BR>\n<A HREF=\"manual.html#lua_getlocal\">lua_getlocal</A><BR>\n<A HREF=\"manual.html#lua_getmetatable\">lua_getmetatable</A><BR>\n<A HREF=\"manual.html#lua_getstack\">lua_getstack</A><BR>\n<A HREF=\"manual.html#lua_gettable\">lua_gettable</A><BR>\n<A HREF=\"manual.html#lua_gettop\">lua_gettop</A><BR>\n<A HREF=\"manual.html#lua_getupvalue\">lua_getupvalue</A><BR>\n<A HREF=\"manual.html#lua_insert\">lua_insert</A><BR>\n<A HREF=\"manual.html#lua_isboolean\">lua_isboolean</A><BR>\n<A HREF=\"manual.html#lua_iscfunction\">lua_iscfunction</A><BR>\n<A HREF=\"manual.html#lua_isfunction\">lua_isfunction</A><BR>\n<A HREF=\"manual.html#lua_islightuserdata\">lua_islightuserdata</A><BR>\n<A HREF=\"manual.html#lua_isnil\">lua_isnil</A><BR>\n<A HREF=\"manual.html#lua_isnone\">lua_isnone</A><BR>\n<A HREF=\"manual.html#lua_isnoneornil\">lua_isnoneornil</A><BR>\n<A HREF=\"manual.html#lua_isnumber\">lua_isnumber</A><BR>\n<A HREF=\"manual.html#lua_isstring\">lua_isstring</A><BR>\n<A HREF=\"manual.html#lua_istable\">lua_istable</A><BR>\n<A HREF=\"manual.html#lua_isthread\">lua_isthread</A><BR>\n<A HREF=\"manual.html#lua_isuserdata\">lua_isuserdata</A><BR>\n<A HREF=\"manual.html#lua_lessthan\">lua_lessthan</A><BR>\n<A HREF=\"manual.html#lua_load\">lua_load</A><BR>\n<A HREF=\"manual.html#lua_newstate\">lua_newstate</A><BR>\n<A HREF=\"manual.html#lua_newtable\">lua_newtable</A><BR>\n<A HREF=\"manual.html#lua_newthread\">lua_newthread</A><BR>\n<A HREF=\"manual.html#lua_newuserdata\">lua_newuserdata</A><BR>\n<A HREF=\"manual.html#lua_next\">lua_next</A><BR>\n<A HREF=\"manual.html#lua_objlen\">lua_objlen</A><BR>\n<A HREF=\"manual.html#lua_pcall\">lua_pcall</A><BR>\n<A HREF=\"manual.html#lua_pop\">lua_pop</A><BR>\n<A HREF=\"manual.html#lua_pushboolean\">lua_pushboolean</A><BR>\n<A HREF=\"manual.html#lua_pushcclosure\">lua_pushcclosure</A><BR>\n<A HREF=\"manual.html#lua_pushcfunction\">lua_pushcfunction</A><BR>\n<A HREF=\"manual.html#lua_pushfstring\">lua_pushfstring</A><BR>\n<A HREF=\"manual.html#lua_pushinteger\">lua_pushinteger</A><BR>\n<A HREF=\"manual.html#lua_pushlightuserdata\">lua_pushlightuserdata</A><BR>\n<A HREF=\"manual.html#lua_pushliteral\">lua_pushliteral</A><BR>\n<A HREF=\"manual.html#lua_pushlstring\">lua_pushlstring</A><BR>\n<A HREF=\"manual.html#lua_pushnil\">lua_pushnil</A><BR>\n<A HREF=\"manual.html#lua_pushnumber\">lua_pushnumber</A><BR>\n<A HREF=\"manual.html#lua_pushstring\">lua_pushstring</A><BR>\n<A HREF=\"manual.html#lua_pushthread\">lua_pushthread</A><BR>\n<A HREF=\"manual.html#lua_pushvalue\">lua_pushvalue</A><BR>\n<A HREF=\"manual.html#lua_pushvfstring\">lua_pushvfstring</A><BR>\n<A HREF=\"manual.html#lua_rawequal\">lua_rawequal</A><BR>\n<A HREF=\"manual.html#lua_rawget\">lua_rawget</A><BR>\n<A HREF=\"manual.html#lua_rawgeti\">lua_rawgeti</A><BR>\n<A HREF=\"manual.html#lua_rawset\">lua_rawset</A><BR>\n<A HREF=\"manual.html#lua_rawseti\">lua_rawseti</A><BR>\n<A HREF=\"manual.html#lua_register\">lua_register</A><BR>\n<A HREF=\"manual.html#lua_remove\">lua_remove</A><BR>\n<A HREF=\"manual.html#lua_replace\">lua_replace</A><BR>\n<A HREF=\"manual.html#lua_resume\">lua_resume</A><BR>\n<A HREF=\"manual.html#lua_setallocf\">lua_setallocf</A><BR>\n<A HREF=\"manual.html#lua_setfenv\">lua_setfenv</A><BR>\n<A HREF=\"manual.html#lua_setfield\">lua_setfield</A><BR>\n<A HREF=\"manual.html#lua_setglobal\">lua_setglobal</A><BR>\n<A HREF=\"manual.html#lua_sethook\">lua_sethook</A><BR>\n<A HREF=\"manual.html#lua_setlocal\">lua_setlocal</A><BR>\n<A HREF=\"manual.html#lua_setmetatable\">lua_setmetatable</A><BR>\n<A HREF=\"manual.html#lua_settable\">lua_settable</A><BR>\n<A HREF=\"manual.html#lua_settop\">lua_settop</A><BR>\n<A HREF=\"manual.html#lua_setupvalue\">lua_setupvalue</A><BR>\n<A HREF=\"manual.html#lua_status\">lua_status</A><BR>\n<A HREF=\"manual.html#lua_toboolean\">lua_toboolean</A><BR>\n<A HREF=\"manual.html#lua_tocfunction\">lua_tocfunction</A><BR>\n<A HREF=\"manual.html#lua_tointeger\">lua_tointeger</A><BR>\n<A HREF=\"manual.html#lua_tolstring\">lua_tolstring</A><BR>\n<A HREF=\"manual.html#lua_tonumber\">lua_tonumber</A><BR>\n<A HREF=\"manual.html#lua_topointer\">lua_topointer</A><BR>\n<A HREF=\"manual.html#lua_tostring\">lua_tostring</A><BR>\n<A HREF=\"manual.html#lua_tothread\">lua_tothread</A><BR>\n<A HREF=\"manual.html#lua_touserdata\">lua_touserdata</A><BR>\n<A HREF=\"manual.html#lua_type\">lua_type</A><BR>\n<A HREF=\"manual.html#lua_typename\">lua_typename</A><BR>\n<A HREF=\"manual.html#lua_upvalueindex\">lua_upvalueindex</A><BR>\n<A HREF=\"manual.html#lua_xmove\">lua_xmove</A><BR>\n<A HREF=\"manual.html#lua_yield\">lua_yield</A><BR>\n\n</TD>\n<TD>\n<H3>auxiliary library</H3>\n<A HREF=\"manual.html#luaL_Buffer\">luaL_Buffer</A><BR>\n<A HREF=\"manual.html#luaL_Reg\">luaL_Reg</A><BR>\n<P>\n\n<A HREF=\"manual.html#luaL_addchar\">luaL_addchar</A><BR>\n<A HREF=\"manual.html#luaL_addlstring\">luaL_addlstring</A><BR>\n<A HREF=\"manual.html#luaL_addsize\">luaL_addsize</A><BR>\n<A HREF=\"manual.html#luaL_addstring\">luaL_addstring</A><BR>\n<A HREF=\"manual.html#luaL_addvalue\">luaL_addvalue</A><BR>\n<A HREF=\"manual.html#luaL_argcheck\">luaL_argcheck</A><BR>\n<A HREF=\"manual.html#luaL_argerror\">luaL_argerror</A><BR>\n<A HREF=\"manual.html#luaL_buffinit\">luaL_buffinit</A><BR>\n<A HREF=\"manual.html#luaL_callmeta\">luaL_callmeta</A><BR>\n<A HREF=\"manual.html#luaL_checkany\">luaL_checkany</A><BR>\n<A HREF=\"manual.html#luaL_checkint\">luaL_checkint</A><BR>\n<A HREF=\"manual.html#luaL_checkinteger\">luaL_checkinteger</A><BR>\n<A HREF=\"manual.html#luaL_checklong\">luaL_checklong</A><BR>\n<A HREF=\"manual.html#luaL_checklstring\">luaL_checklstring</A><BR>\n<A HREF=\"manual.html#luaL_checknumber\">luaL_checknumber</A><BR>\n<A HREF=\"manual.html#luaL_checkoption\">luaL_checkoption</A><BR>\n<A HREF=\"manual.html#luaL_checkstack\">luaL_checkstack</A><BR>\n<A HREF=\"manual.html#luaL_checkstring\">luaL_checkstring</A><BR>\n<A HREF=\"manual.html#luaL_checktype\">luaL_checktype</A><BR>\n<A HREF=\"manual.html#luaL_checkudata\">luaL_checkudata</A><BR>\n<A HREF=\"manual.html#luaL_dofile\">luaL_dofile</A><BR>\n<A HREF=\"manual.html#luaL_dostring\">luaL_dostring</A><BR>\n<A HREF=\"manual.html#luaL_error\">luaL_error</A><BR>\n<A HREF=\"manual.html#luaL_getmetafield\">luaL_getmetafield</A><BR>\n<A HREF=\"manual.html#luaL_getmetatable\">luaL_getmetatable</A><BR>\n<A HREF=\"manual.html#luaL_gsub\">luaL_gsub</A><BR>\n<A HREF=\"manual.html#luaL_loadbuffer\">luaL_loadbuffer</A><BR>\n<A HREF=\"manual.html#luaL_loadfile\">luaL_loadfile</A><BR>\n<A HREF=\"manual.html#luaL_loadstring\">luaL_loadstring</A><BR>\n<A HREF=\"manual.html#luaL_newmetatable\">luaL_newmetatable</A><BR>\n<A HREF=\"manual.html#luaL_newstate\">luaL_newstate</A><BR>\n<A HREF=\"manual.html#luaL_openlibs\">luaL_openlibs</A><BR>\n<A HREF=\"manual.html#luaL_optint\">luaL_optint</A><BR>\n<A HREF=\"manual.html#luaL_optinteger\">luaL_optinteger</A><BR>\n<A HREF=\"manual.html#luaL_optlong\">luaL_optlong</A><BR>\n<A HREF=\"manual.html#luaL_optlstring\">luaL_optlstring</A><BR>\n<A HREF=\"manual.html#luaL_optnumber\">luaL_optnumber</A><BR>\n<A HREF=\"manual.html#luaL_optstring\">luaL_optstring</A><BR>\n<A HREF=\"manual.html#luaL_prepbuffer\">luaL_prepbuffer</A><BR>\n<A HREF=\"manual.html#luaL_pushresult\">luaL_pushresult</A><BR>\n<A HREF=\"manual.html#luaL_ref\">luaL_ref</A><BR>\n<A HREF=\"manual.html#luaL_register\">luaL_register</A><BR>\n<A HREF=\"manual.html#luaL_typename\">luaL_typename</A><BR>\n<A HREF=\"manual.html#luaL_typerror\">luaL_typerror</A><BR>\n<A HREF=\"manual.html#luaL_unref\">luaL_unref</A><BR>\n<A HREF=\"manual.html#luaL_where\">luaL_where</A><BR>\n\n</TD>\n</TR>\n</TABLE>\n<P>\n\n<HR>\n<SMALL CLASS=\"footer\">\nLast update:\nMon Feb 13 18:53:32 BRST 2012\n</SMALL>\n<!--\nLast change: revised for Lua 5.1.5\n-->\n\n</BODY>\n</HTML>\n"
  },
  {
    "path": "extern/deprecated/redis-2.8.21/deps/lua/doc/lua.1",
    "content": ".\\\" $Id: lua.man,v 1.11 2006/01/06 16:03:34 lhf Exp $\n.TH LUA 1 \"$Date: 2006/01/06 16:03:34 $\"\n.SH NAME\nlua \\- Lua interpreter\n.SH SYNOPSIS\n.B lua\n[\n.I options\n]\n[\n.I script\n[\n.I args\n]\n]\n.SH DESCRIPTION\n.B lua\nis the stand-alone Lua interpreter.\nIt loads and executes Lua programs,\neither in textual source form or\nin precompiled binary form.\n(Precompiled binaries are output by\n.BR luac ,\nthe Lua compiler.)\n.B lua\ncan be used as a batch interpreter and also interactively.\n.LP\nThe given\n.I options\n(see below)\nare executed and then\nthe Lua program in file\n.I script\nis loaded and executed.\nThe given\n.I args\nare available to\n.I script\nas strings in a global table named\n.BR arg .\nIf these arguments contain spaces or other characters special to the shell,\nthen they should be quoted\n(but note that the quotes will be removed by the shell).\nThe arguments in\n.B arg\nstart at 0,\nwhich contains the string\n.RI ' script '.\nThe index of the last argument is stored in\n.BR arg.n .\nThe arguments given in the command line before\n.IR script ,\nincluding the name of the interpreter,\nare available in negative indices in\n.BR arg .\n.LP\nAt the very start,\nbefore even handling the command line,\n.B lua\nexecutes the contents of the environment variable\n.BR LUA_INIT ,\nif it is defined.\nIf the value of\n.B LUA_INIT\nis of the form\n.RI '@ filename ',\nthen\n.I filename\nis executed.\nOtherwise, the string is assumed to be a Lua statement and is executed.\n.LP\nOptions start with\n.B '\\-'\nand are described below.\nYou can use\n.B \"'\\--'\"\nto signal the end of options.\n.LP\nIf no arguments are given,\nthen\n.B \"\\-v \\-i\"\nis assumed when the standard input is a terminal;\notherwise,\n.B \"\\-\"\nis assumed.\n.LP\nIn interactive mode,\n.B lua\nprompts the user,\nreads lines from the standard input,\nand executes them as they are read.\nIf a line does not contain a complete statement,\nthen a secondary prompt is displayed and\nlines are read until a complete statement is formed or\na syntax error is found.\nSo, one way to interrupt the reading of an incomplete statement is\nto force a syntax error:\nadding a\n.B ';' \nin the middle of a statement is a sure way of forcing a syntax error\n(except inside multiline strings and comments; these must be closed explicitly).\nIf a line starts with\n.BR '=' ,\nthen\n.B lua\ndisplays the values of all the expressions in the remainder of the\nline. The expressions must be separated by commas.\nThe primary prompt is the value of the global variable\n.BR _PROMPT ,\nif this value is a string;\notherwise, the default prompt is used.\nSimilarly, the secondary prompt is the value of the global variable\n.BR _PROMPT2 .\nSo,\nto change the prompts,\nset the corresponding variable to a string of your choice.\nYou can do that after calling the interpreter\nor on the command line\n(but in this case you have to be careful with quotes\nif the prompt string contains a space; otherwise you may confuse the shell.)\nThe default prompts are \"> \" and \">> \".\n.SH OPTIONS\n.TP\n.B \\-\nload and execute the standard input as a file,\nthat is,\nnot interactively,\neven when the standard input is a terminal.\n.TP\n.BI \\-e \" stat\"\nexecute statement\n.IR stat .\nYou need to quote\n.I stat \nif it contains spaces, quotes,\nor other characters special to the shell.\n.TP\n.B \\-i\nenter interactive mode after\n.I script\nis executed.\n.TP\n.BI \\-l \" name\"\ncall\n.BI require(' name ')\nbefore executing\n.IR script .\nTypically used to load libraries.\n.TP\n.B \\-v\nshow version information.\n.SH \"SEE ALSO\"\n.BR luac (1)\n.br\nhttp://www.lua.org/\n.SH DIAGNOSTICS\nError messages should be self explanatory.\n.SH AUTHORS\nR. Ierusalimschy,\nL. H. de Figueiredo,\nand\nW. Celes\n.\\\" EOF\n"
  },
  {
    "path": "extern/deprecated/redis-2.8.21/deps/lua/doc/lua.css",
    "content": "body {\n\tcolor: #000000 ;\n\tbackground-color: #FFFFFF ;\n\tfont-family: Helvetica, Arial, sans-serif ;\n\ttext-align: justify ;\n\tmargin-right: 30px ;\n\tmargin-left: 30px ;\n}\n\nh1, h2, h3, h4 {\n\tfont-family: Verdana, Geneva, sans-serif ;\n\tfont-weight: normal ;\n\tfont-style: italic ;\n}\n\nh2 {\n\tpadding-top: 0.4em ;\n\tpadding-bottom: 0.4em ;\n\tpadding-left: 30px ;\n\tpadding-right: 30px ;\n\tmargin-left: -30px ;\n\tbackground-color: #E0E0FF ;\n}\n\nh3 {\n\tpadding-left: 0.5em ;\n\tborder-left: solid #E0E0FF 1em ;\n}\n\ntable h3 {\n\tpadding-left: 0px ;\n\tborder-left: none ;\n}\n\na:link {\n\tcolor: #000080 ;\n\tbackground-color: inherit ;\n\ttext-decoration: none ;\n}\n\na:visited {\n\tbackground-color: inherit ;\n\ttext-decoration: none ;\n}\n\na:link:hover, a:visited:hover {\n\tcolor: #000080 ;\n\tbackground-color: #E0E0FF ;\n}\n\na:link:active, a:visited:active {\n\tcolor: #FF0000 ;\n}\n\nhr {\n\tborder: 0 ;\n\theight: 1px ;\n\tcolor: #a0a0a0 ;\n\tbackground-color: #a0a0a0 ;\n}\n\n:target {\n\tbackground-color: #F8F8F8 ;\n\tpadding: 8px ;\n\tborder: solid #a0a0a0 2px ;\n}\n\n.footer {\n\tcolor: gray ;\n\tfont-size: small ;\n}\n\ninput[type=text] {\n\tborder: solid #a0a0a0 2px ;\n\tborder-radius: 2em ;\n\t-moz-border-radius: 2em ;\n\tbackground-image: url('images/search.png') ;\n\tbackground-repeat: no-repeat;\n\tbackground-position: 4px center ;\n\tpadding-left: 20px ;\n\theight: 2em ;\n}\n\n"
  },
  {
    "path": "extern/deprecated/redis-2.8.21/deps/lua/doc/lua.html",
    "content": "<!-- $Id: lua.man,v 1.11 2006/01/06 16:03:34 lhf Exp $ -->\n<HTML>\n<HEAD>\n<TITLE>LUA man page</TITLE>\n<LINK REL=\"stylesheet\" TYPE=\"text/css\" HREF=\"lua.css\">\n</HEAD>\n\n<BODY BGCOLOR=\"#FFFFFF\">\n\n<H2>NAME</H2>\nlua - Lua interpreter\n<H2>SYNOPSIS</H2>\n<B>lua</B>\n[\n<I>options</I>\n]\n[\n<I>script</I>\n[\n<I>args</I>\n]\n]\n<H2>DESCRIPTION</H2>\n<B>lua</B>\nis the stand-alone Lua interpreter.\nIt loads and executes Lua programs,\neither in textual source form or\nin precompiled binary form.\n(Precompiled binaries are output by\n<B>luac</B>,\nthe Lua compiler.)\n<B>lua</B>\ncan be used as a batch interpreter and also interactively.\n<P>\nThe given\n<I>options</I>\n(see below)\nare executed and then\nthe Lua program in file\n<I>script</I>\nis loaded and executed.\nThe given\n<I>args</I>\nare available to\n<I>script</I>\nas strings in a global table named\n<B>arg</B>.\nIf these arguments contain spaces or other characters special to the shell,\nthen they should be quoted\n(but note that the quotes will be removed by the shell).\nThe arguments in\n<B>arg</B>\nstart at 0,\nwhich contains the string\n'<I>script</I>'.\nThe index of the last argument is stored in\n<B>arg.n</B>.\nThe arguments given in the command line before\n<I>script</I>,\nincluding the name of the interpreter,\nare available in negative indices in\n<B>arg</B>.\n<P>\nAt the very start,\nbefore even handling the command line,\n<B>lua</B>\nexecutes the contents of the environment variable\n<B>LUA_INIT</B>,\nif it is defined.\nIf the value of\n<B>LUA_INIT</B>\nis of the form\n'@<I>filename</I>',\nthen\n<I>filename</I>\nis executed.\nOtherwise, the string is assumed to be a Lua statement and is executed.\n<P>\nOptions start with\n<B>'-'</B>\nand are described below.\nYou can use\n<B>'--'</B>\nto signal the end of options.\n<P>\nIf no arguments are given,\nthen\n<B>\"-v -i\"</B>\nis assumed when the standard input is a terminal;\notherwise,\n<B>\"-\"</B>\nis assumed.\n<P>\nIn interactive mode,\n<B>lua</B>\nprompts the user,\nreads lines from the standard input,\nand executes them as they are read.\nIf a line does not contain a complete statement,\nthen a secondary prompt is displayed and\nlines are read until a complete statement is formed or\na syntax error is found.\nSo, one way to interrupt the reading of an incomplete statement is\nto force a syntax error:\nadding a\n<B>';'</B>\nin the middle of a statement is a sure way of forcing a syntax error\n(except inside multiline strings and comments; these must be closed explicitly).\nIf a line starts with\n<B>'='</B>,\nthen\n<B>lua</B>\ndisplays the values of all the expressions in the remainder of the\nline. The expressions must be separated by commas.\nThe primary prompt is the value of the global variable\n<B>_PROMPT</B>,\nif this value is a string;\notherwise, the default prompt is used.\nSimilarly, the secondary prompt is the value of the global variable\n<B>_PROMPT2</B>.\nSo,\nto change the prompts,\nset the corresponding variable to a string of your choice.\nYou can do that after calling the interpreter\nor on the command line\n(but in this case you have to be careful with quotes\nif the prompt string contains a space; otherwise you may confuse the shell.)\nThe default prompts are \"&gt; \" and \"&gt;&gt; \".\n<H2>OPTIONS</H2>\n<P>\n<B>-</B>\nload and execute the standard input as a file,\nthat is,\nnot interactively,\neven when the standard input is a terminal.\n<P>\n<B>-e </B><I>stat</I>\nexecute statement\n<I>stat</I>.\nYou need to quote\n<I>stat </I>\nif it contains spaces, quotes,\nor other characters special to the shell.\n<P>\n<B>-i</B>\nenter interactive mode after\n<I>script</I>\nis executed.\n<P>\n<B>-l </B><I>name</I>\ncall\n<B>require</B>('<I>name</I>')\nbefore executing\n<I>script</I>.\nTypically used to load libraries.\n<P>\n<B>-v</B>\nshow version information.\n<H2>SEE ALSO</H2>\n<B>luac</B>(1)\n<BR>\n<A HREF=\"http://www.lua.org/\">http://www.lua.org/</A>\n<H2>DIAGNOSTICS</H2>\nError messages should be self explanatory.\n<H2>AUTHORS</H2>\nR. Ierusalimschy,\nL. H. de Figueiredo,\nand\nW. Celes\n<!-- EOF -->\n</BODY>\n</HTML>\n"
  },
  {
    "path": "extern/deprecated/redis-2.8.21/deps/lua/doc/luac.1",
    "content": ".\\\" $Id: luac.man,v 1.28 2006/01/06 16:03:34 lhf Exp $\n.TH LUAC 1 \"$Date: 2006/01/06 16:03:34 $\"\n.SH NAME\nluac \\- Lua compiler\n.SH SYNOPSIS\n.B luac\n[\n.I options\n] [\n.I filenames\n]\n.SH DESCRIPTION\n.B luac\nis the Lua compiler.\nIt translates programs written in the Lua programming language\ninto binary files that can be later loaded and executed.\n.LP\nThe main advantages of precompiling chunks are:\nfaster loading,\nprotecting source code from accidental user changes,\nand\noff-line syntax checking.\n.LP\nPre-compiling does not imply faster execution\nbecause in Lua chunks are always compiled into bytecodes before being executed.\n.B luac\nsimply allows those bytecodes to be saved in a file for later execution.\n.LP\nPre-compiled chunks are not necessarily smaller than the corresponding source.\nThe main goal in pre-compiling is faster loading.\n.LP\nThe binary files created by\n.B luac\nare portable only among architectures with the same word size and byte order.\n.LP\n.B luac\nproduces a single output file containing the bytecodes\nfor all source files given.\nBy default,\nthe output file is named\n.BR luac.out ,\nbut you can change this with the\n.B \\-o\noption.\n.LP\nIn the command line,\nyou can mix\ntext files containing Lua source and\nbinary files containing precompiled chunks.\nThis is useful to combine several precompiled chunks,\neven from different (but compatible) platforms,\ninto a single precompiled chunk.\n.LP\nYou can use\n.B \"'\\-'\"\nto indicate the standard input as a source file\nand\n.B \"'\\--'\"\nto signal the end of options\n(that is,\nall remaining arguments will be treated as files even if they start with\n.BR \"'\\-'\" ).\n.LP\nThe internal format of the binary files produced by\n.B luac\nis likely to change when a new version of Lua is released.\nSo,\nsave the source files of all Lua programs that you precompile.\n.LP\n.SH OPTIONS\nOptions must be separate.\n.TP\n.B \\-l\nproduce a listing of the compiled bytecode for Lua's virtual machine.\nListing bytecodes is useful to learn about Lua's virtual machine.\nIf no files are given, then\n.B luac\nloads\n.B luac.out\nand lists its contents.\n.TP\n.BI \\-o \" file\"\noutput to\n.IR file ,\ninstead of the default\n.BR luac.out .\n(You can use\n.B \"'\\-'\"\nfor standard output,\nbut not on platforms that open standard output in text mode.)\nThe output file may be a source file because\nall files are loaded before the output file is written.\nBe careful not to overwrite precious files.\n.TP\n.B \\-p\nload files but do not generate any output file.\nUsed mainly for syntax checking and for testing precompiled chunks:\ncorrupted files will probably generate errors when loaded.\nLua always performs a thorough integrity test on precompiled chunks.\nBytecode that passes this test is completely safe,\nin the sense that it will not break the interpreter.\nHowever,\nthere is no guarantee that such code does anything sensible.\n(None can be given, because the halting problem is unsolvable.)\nIf no files are given, then\n.B luac\nloads\n.B luac.out\nand tests its contents.\nNo messages are displayed if the file passes the integrity test.\n.TP\n.B \\-s\nstrip debug information before writing the output file.\nThis saves some space in very large chunks,\nbut if errors occur when running a stripped chunk,\nthen the error messages may not contain the full information they usually do.\nFor instance,\nline numbers and names of local variables are lost.\n.TP\n.B \\-v\nshow version information.\n.SH FILES\n.TP 15\n.B luac.out\ndefault output file\n.SH \"SEE ALSO\"\n.BR lua (1)\n.br\nhttp://www.lua.org/\n.SH DIAGNOSTICS\nError messages should be self explanatory.\n.SH AUTHORS\nL. H. de Figueiredo,\nR. Ierusalimschy and\nW. Celes\n.\\\" EOF\n"
  },
  {
    "path": "extern/deprecated/redis-2.8.21/deps/lua/doc/luac.html",
    "content": "<!-- $Id: luac.man,v 1.28 2006/01/06 16:03:34 lhf Exp $ -->\n<HTML>\n<HEAD>\n<TITLE>LUAC man page</TITLE>\n<LINK REL=\"stylesheet\" TYPE=\"text/css\" HREF=\"lua.css\">\n</HEAD>\n\n<BODY BGCOLOR=\"#FFFFFF\">\n\n<H2>NAME</H2>\nluac - Lua compiler\n<H2>SYNOPSIS</H2>\n<B>luac</B>\n[\n<I>options</I>\n] [\n<I>filenames</I>\n]\n<H2>DESCRIPTION</H2>\n<B>luac</B>\nis the Lua compiler.\nIt translates programs written in the Lua programming language\ninto binary files that can be later loaded and executed.\n<P>\nThe main advantages of precompiling chunks are:\nfaster loading,\nprotecting source code from accidental user changes,\nand\noff-line syntax checking.\n<P>\nPrecompiling does not imply faster execution\nbecause in Lua chunks are always compiled into bytecodes before being executed.\n<B>luac</B>\nsimply allows those bytecodes to be saved in a file for later execution.\n<P>\nPrecompiled chunks are not necessarily smaller than the corresponding source.\nThe main goal in precompiling is faster loading.\n<P>\nThe binary files created by\n<B>luac</B>\nare portable only among architectures with the same word size and byte order.\n<P>\n<B>luac</B>\nproduces a single output file containing the bytecodes\nfor all source files given.\nBy default,\nthe output file is named\n<B>luac.out</B>,\nbut you can change this with the\n<B>-o</B>\noption.\n<P>\nIn the command line,\nyou can mix\ntext files containing Lua source and\nbinary files containing precompiled chunks.\nThis is useful because several precompiled chunks,\neven from different (but compatible) platforms,\ncan be combined into a single precompiled chunk.\n<P>\nYou can use\n<B>'-'</B>\nto indicate the standard input as a source file\nand\n<B>'--'</B>\nto signal the end of options\n(that is,\nall remaining arguments will be treated as files even if they start with\n<B>'-'</B>).\n<P>\nThe internal format of the binary files produced by\n<B>luac</B>\nis likely to change when a new version of Lua is released.\nSo,\nsave the source files of all Lua programs that you precompile.\n<P>\n<H2>OPTIONS</H2>\nOptions must be separate.\n<P>\n<B>-l</B>\nproduce a listing of the compiled bytecode for Lua's virtual machine.\nListing bytecodes is useful to learn about Lua's virtual machine.\nIf no files are given, then\n<B>luac</B>\nloads\n<B>luac.out</B>\nand lists its contents.\n<P>\n<B>-o </B><I>file</I>\noutput to\n<I>file</I>,\ninstead of the default\n<B>luac.out</B>.\n(You can use\n<B>'-'</B>\nfor standard output,\nbut not on platforms that open standard output in text mode.)\nThe output file may be a source file because\nall files are loaded before the output file is written.\nBe careful not to overwrite precious files.\n<P>\n<B>-p</B>\nload files but do not generate any output file.\nUsed mainly for syntax checking and for testing precompiled chunks:\ncorrupted files will probably generate errors when loaded.\nLua always performs a thorough integrity test on precompiled chunks.\nBytecode that passes this test is completely safe,\nin the sense that it will not break the interpreter.\nHowever,\nthere is no guarantee that such code does anything sensible.\n(None can be given, because the halting problem is unsolvable.)\nIf no files are given, then\n<B>luac</B>\nloads\n<B>luac.out</B>\nand tests its contents.\nNo messages are displayed if the file passes the integrity test.\n<P>\n<B>-s</B>\nstrip debug information before writing the output file.\nThis saves some space in very large chunks,\nbut if errors occur when running a stripped chunk,\nthen the error messages may not contain the full information they usually do.\nFor instance,\nline numbers and names of local variables are lost.\n<P>\n<B>-v</B>\nshow version information.\n<H2>FILES</H2>\n<P>\n<B>luac.out</B>\ndefault output file\n<H2>SEE ALSO</H2>\n<B>lua</B>(1)\n<BR>\n<A HREF=\"http://www.lua.org/\">http://www.lua.org/</A>\n<H2>DIAGNOSTICS</H2>\nError messages should be self explanatory.\n<H2>AUTHORS</H2>\nL. H. de Figueiredo,\nR. Ierusalimschy and\nW. Celes\n<!-- EOF -->\n</BODY>\n</HTML>\n"
  },
  {
    "path": "extern/deprecated/redis-2.8.21/deps/lua/doc/manual.css",
    "content": "h3 code {\n\tfont-family: inherit ;\n\tfont-size: inherit ;\n}\n\npre, code {\n\tfont-size: 12pt ;\n}\n\nspan.apii {\n\tfloat: right ;\n\tfont-family: inherit ;\n\tfont-style: normal ;\n\tfont-size: small ;\n\tcolor: gray ;\n}\n\np+h1, ul+h1 {\n\tpadding-top: 0.4em ;\n\tpadding-bottom: 0.4em ;\n\tpadding-left: 30px ;\n\tmargin-left: -30px ;\n\tbackground-color: #E0E0FF ;\n}\n"
  },
  {
    "path": "extern/deprecated/redis-2.8.21/deps/lua/doc/manual.html",
    "content": "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\">\n<html>\n\n<head>\n<title>Lua 5.1 Reference Manual</title>\n<link rel=\"stylesheet\" type=\"text/css\" href=\"lua.css\">\n<link rel=\"stylesheet\" type=\"text/css\" href=\"manual.css\">\n<META HTTP-EQUIV=\"content-type\" CONTENT=\"text/html; charset=iso-8859-1\">\n</head>\n\n<body>\n\n<hr>\n<h1>\n<a href=\"http://www.lua.org/\"><img src=\"logo.gif\" alt=\"\" border=\"0\"></a>\nLua 5.1 Reference Manual\n</h1>\n\nby Roberto Ierusalimschy, Luiz Henrique de Figueiredo, Waldemar Celes\n<p>\n<small>\nCopyright &copy; 2006&ndash;2012 Lua.org, PUC-Rio.\nFreely available under the terms of the\n<a href=\"http://www.lua.org/license.html\">Lua license</a>.\n</small>\n<hr>\n<p>\n\n<a href=\"contents.html#contents\">contents</A>\n&middot;\n<a href=\"contents.html#index\">index</A>\n&middot;\n<A HREF=\"http://www.lua.org/manual/\">other versions</A>\n\n<!-- ====================================================================== -->\n<p>\n\n<!-- $Id: manual.of,v 1.49.1.2 2012/01/13 20:23:26 roberto Exp $ -->\n\n\n\n\n<h1>1 - <a name=\"1\">Introduction</a></h1>\n\n<p>\nLua is an extension programming language designed to support\ngeneral procedural programming with data description\nfacilities.\nIt also offers good support for object-oriented programming,\nfunctional programming, and data-driven programming.\nLua is intended to be used as a powerful, light-weight\nscripting language for any program that needs one.\nLua is implemented as a library, written in <em>clean</em> C\n(that is, in the common subset of ANSI&nbsp;C and C++).\n\n\n<p>\nBeing an extension language, Lua has no notion of a \"main\" program:\nit only works <em>embedded</em> in a host client,\ncalled the <em>embedding program</em> or simply the <em>host</em>.\nThis host program can invoke functions to execute a piece of Lua code,\ncan write and read Lua variables,\nand can register C&nbsp;functions to be called by Lua code.\nThrough the use of C&nbsp;functions, Lua can be augmented to cope with\na wide range of different domains,\nthus creating customized programming languages sharing a syntactical framework.\nThe Lua distribution includes a sample host program called <code>lua</code>,\nwhich uses the Lua library to offer a complete, stand-alone Lua interpreter.\n\n\n<p>\nLua is free software,\nand is provided as usual with no guarantees,\nas stated in its license.\nThe implementation described in this manual is available\nat Lua's official web site, <code>www.lua.org</code>.\n\n\n<p>\nLike any other reference manual,\nthis document is dry in places.\nFor a discussion of the decisions behind the design of Lua,\nsee the technical papers available at Lua's web site.\nFor a detailed introduction to programming in Lua,\nsee Roberto's book, <em>Programming in Lua (Second Edition)</em>.\n\n\n\n<h1>2 - <a name=\"2\">The Language</a></h1>\n\n<p>\nThis section describes the lexis, the syntax, and the semantics of Lua.\nIn other words,\nthis section describes\nwhich tokens are valid,\nhow they can be combined,\nand what their combinations mean.\n\n\n<p>\nThe language constructs will be explained using the usual extended BNF notation,\nin which\n{<em>a</em>}&nbsp;means&nbsp;0 or more <em>a</em>'s, and\n[<em>a</em>]&nbsp;means an optional <em>a</em>.\nNon-terminals are shown like non-terminal,\nkeywords are shown like <b>kword</b>,\nand other terminal symbols are shown like `<b>=</b>&acute;.\nThe complete syntax of Lua can be found in <a href=\"#8\">&sect;8</a>\nat the end of this manual.\n\n\n\n<h2>2.1 - <a name=\"2.1\">Lexical Conventions</a></h2>\n\n<p>\n<em>Names</em>\n(also called <em>identifiers</em>)\nin Lua can be any string of letters,\ndigits, and underscores,\nnot beginning with a digit.\nThis coincides with the definition of names in most languages.\n(The definition of letter depends on the current locale:\nany character considered alphabetic by the current locale\ncan be used in an identifier.)\nIdentifiers are used to name variables and table fields.\n\n\n<p>\nThe following <em>keywords</em> are reserved\nand cannot be used as names:\n\n\n<pre>\n     and       break     do        else      elseif\n     end       false     for       function  if\n     in        local     nil       not       or\n     repeat    return    then      true      until     while\n</pre>\n\n<p>\nLua is a case-sensitive language:\n<code>and</code> is a reserved word, but <code>And</code> and <code>AND</code>\nare two different, valid names.\nAs a convention, names starting with an underscore followed by\nuppercase letters (such as <a href=\"#pdf-_VERSION\"><code>_VERSION</code></a>)\nare reserved for internal global variables used by Lua.\n\n\n<p>\nThe following strings denote other tokens:\n\n<pre>\n     +     -     *     /     %     ^     #\n     ==    ~=    &lt;=    &gt;=    &lt;     &gt;     =\n     (     )     {     }     [     ]\n     ;     :     ,     .     ..    ...\n</pre>\n\n<p>\n<em>Literal strings</em>\ncan be delimited by matching single or double quotes,\nand can contain the following C-like escape sequences:\n'<code>\\a</code>' (bell),\n'<code>\\b</code>' (backspace),\n'<code>\\f</code>' (form feed),\n'<code>\\n</code>' (newline),\n'<code>\\r</code>' (carriage return),\n'<code>\\t</code>' (horizontal tab),\n'<code>\\v</code>' (vertical tab),\n'<code>\\\\</code>' (backslash),\n'<code>\\\"</code>' (quotation mark [double quote]),\nand '<code>\\'</code>' (apostrophe [single quote]).\nMoreover, a backslash followed by a real newline\nresults in a newline in the string.\nA character in a string can also be specified by its numerical value\nusing the escape sequence <code>\\<em>ddd</em></code>,\nwhere <em>ddd</em> is a sequence of up to three decimal digits.\n(Note that if a numerical escape is to be followed by a digit,\nit must be expressed using exactly three digits.)\nStrings in Lua can contain any 8-bit value, including embedded zeros,\nwhich can be specified as '<code>\\0</code>'.\n\n\n<p>\nLiteral strings can also be defined using a long format\nenclosed by <em>long brackets</em>.\nWe define an <em>opening long bracket of level <em>n</em></em> as an opening\nsquare bracket followed by <em>n</em> equal signs followed by another\nopening square bracket.\nSo, an opening long bracket of level&nbsp;0 is written as <code>[[</code>,\nan opening long bracket of level&nbsp;1 is written as <code>[=[</code>,\nand so on.\nA <em>closing long bracket</em> is defined similarly;\nfor instance, a closing long bracket of level&nbsp;4 is written as <code>]====]</code>.\nA long string starts with an opening long bracket of any level and\nends at the first closing long bracket of the same level.\nLiterals in this bracketed form can run for several lines,\ndo not interpret any escape sequences,\nand ignore long brackets of any other level.\nThey can contain anything except a closing bracket of the proper level.\n\n\n<p>\nFor convenience,\nwhen the opening long bracket is immediately followed by a newline,\nthe newline is not included in the string.\nAs an example, in a system using ASCII\n(in which '<code>a</code>' is coded as&nbsp;97,\nnewline is coded as&nbsp;10, and '<code>1</code>' is coded as&nbsp;49),\nthe five literal strings below denote the same string:\n\n<pre>\n     a = 'alo\\n123\"'\n     a = \"alo\\n123\\\"\"\n     a = '\\97lo\\10\\04923\"'\n     a = [[alo\n     123\"]]\n     a = [==[\n     alo\n     123\"]==]\n</pre>\n\n<p>\nA <em>numerical constant</em> can be written with an optional decimal part\nand an optional decimal exponent.\nLua also accepts integer hexadecimal constants,\nby prefixing them with <code>0x</code>.\nExamples of valid numerical constants are\n\n<pre>\n     3   3.0   3.1416   314.16e-2   0.31416E1   0xff   0x56\n</pre>\n\n<p>\nA <em>comment</em> starts with a double hyphen (<code>--</code>)\nanywhere outside a string.\nIf the text immediately after <code>--</code> is not an opening long bracket,\nthe comment is a <em>short comment</em>,\nwhich runs until the end of the line.\nOtherwise, it is a <em>long comment</em>,\nwhich runs until the corresponding closing long bracket.\nLong comments are frequently used to disable code temporarily.\n\n\n\n\n\n<h2>2.2 - <a name=\"2.2\">Values and Types</a></h2>\n\n<p>\nLua is a <em>dynamically typed language</em>.\nThis means that\nvariables do not have types; only values do.\nThere are no type definitions in the language.\nAll values carry their own type.\n\n\n<p>\nAll values in Lua are <em>first-class values</em>.\nThis means that all values can be stored in variables,\npassed as arguments to other functions, and returned as results.\n\n\n<p>\nThere are eight basic types in Lua:\n<em>nil</em>, <em>boolean</em>, <em>number</em>,\n<em>string</em>, <em>function</em>, <em>userdata</em>,\n<em>thread</em>, and <em>table</em>.\n<em>Nil</em> is the type of the value <b>nil</b>,\nwhose main property is to be different from any other value;\nit usually represents the absence of a useful value.\n<em>Boolean</em> is the type of the values <b>false</b> and <b>true</b>.\nBoth <b>nil</b> and <b>false</b> make a condition false;\nany other value makes it true.\n<em>Number</em> represents real (double-precision floating-point) numbers.\n(It is easy to build Lua interpreters that use other\ninternal representations for numbers,\nsuch as single-precision float or long integers;\nsee file <code>luaconf.h</code>.)\n<em>String</em> represents arrays of characters.\n\nLua is 8-bit clean:\nstrings can contain any 8-bit character,\nincluding embedded zeros ('<code>\\0</code>') (see <a href=\"#2.1\">&sect;2.1</a>).\n\n\n<p>\nLua can call (and manipulate) functions written in Lua and\nfunctions written in C\n(see <a href=\"#2.5.8\">&sect;2.5.8</a>).\n\n\n<p>\nThe type <em>userdata</em> is provided to allow arbitrary C&nbsp;data to\nbe stored in Lua variables.\nThis type corresponds to a block of raw memory\nand has no pre-defined operations in Lua,\nexcept assignment and identity test.\nHowever, by using <em>metatables</em>,\nthe programmer can define operations for userdata values\n(see <a href=\"#2.8\">&sect;2.8</a>).\nUserdata values cannot be created or modified in Lua,\nonly through the C&nbsp;API.\nThis guarantees the integrity of data owned by the host program.\n\n\n<p>\nThe type <em>thread</em> represents independent threads of execution\nand it is used to implement coroutines (see <a href=\"#2.11\">&sect;2.11</a>).\nDo not confuse Lua threads with operating-system threads.\nLua supports coroutines on all systems,\neven those that do not support threads.\n\n\n<p>\nThe type <em>table</em> implements associative arrays,\nthat is, arrays that can be indexed not only with numbers,\nbut with any value (except <b>nil</b>).\nTables can be <em>heterogeneous</em>;\nthat is, they can contain values of all types (except <b>nil</b>).\nTables are the sole data structuring mechanism in Lua;\nthey can be used to represent ordinary arrays,\nsymbol tables, sets, records, graphs, trees, etc.\nTo represent records, Lua uses the field name as an index.\nThe language supports this representation by\nproviding <code>a.name</code> as syntactic sugar for <code>a[\"name\"]</code>.\nThere are several convenient ways to create tables in Lua\n(see <a href=\"#2.5.7\">&sect;2.5.7</a>).\n\n\n<p>\nLike indices,\nthe value of a table field can be of any type (except <b>nil</b>).\nIn particular,\nbecause functions are first-class values,\ntable fields can contain functions.\nThus tables can also carry <em>methods</em> (see <a href=\"#2.5.9\">&sect;2.5.9</a>).\n\n\n<p>\nTables, functions, threads, and (full) userdata values are <em>objects</em>:\nvariables do not actually <em>contain</em> these values,\nonly <em>references</em> to them.\nAssignment, parameter passing, and function returns\nalways manipulate references to such values;\nthese operations do not imply any kind of copy.\n\n\n<p>\nThe library function <a href=\"#pdf-type\"><code>type</code></a> returns a string describing the type\nof a given value.\n\n\n\n<h3>2.2.1 - <a name=\"2.2.1\">Coercion</a></h3>\n\n<p>\nLua provides automatic conversion between\nstring and number values at run time.\nAny arithmetic operation applied to a string tries to convert\nthis string to a number, following the usual conversion rules.\nConversely, whenever a number is used where a string is expected,\nthe number is converted to a string, in a reasonable format.\nFor complete control over how numbers are converted to strings,\nuse the <code>format</code> function from the string library\n(see <a href=\"#pdf-string.format\"><code>string.format</code></a>).\n\n\n\n\n\n\n\n<h2>2.3 - <a name=\"2.3\">Variables</a></h2>\n\n<p>\nVariables are places that store values.\n\nThere are three kinds of variables in Lua:\nglobal variables, local variables, and table fields.\n\n\n<p>\nA single name can denote a global variable or a local variable\n(or a function's formal parameter,\nwhich is a particular kind of local variable):\n\n<pre>\n\tvar ::= Name\n</pre><p>\nName denotes identifiers, as defined in <a href=\"#2.1\">&sect;2.1</a>.\n\n\n<p>\nAny variable is assumed to be global unless explicitly declared\nas a local (see <a href=\"#2.4.7\">&sect;2.4.7</a>).\nLocal variables are <em>lexically scoped</em>:\nlocal variables can be freely accessed by functions\ndefined inside their scope (see <a href=\"#2.6\">&sect;2.6</a>).\n\n\n<p>\nBefore the first assignment to a variable, its value is <b>nil</b>.\n\n\n<p>\nSquare brackets are used to index a table:\n\n<pre>\n\tvar ::= prefixexp `<b>[</b>&acute; exp `<b>]</b>&acute;\n</pre><p>\nThe meaning of accesses to global variables \nand table fields can be changed via metatables.\nAn access to an indexed variable <code>t[i]</code> is equivalent to\na call <code>gettable_event(t,i)</code>.\n(See <a href=\"#2.8\">&sect;2.8</a> for a complete description of the\n<code>gettable_event</code> function.\nThis function is not defined or callable in Lua.\nWe use it here only for explanatory purposes.)\n\n\n<p>\nThe syntax <code>var.Name</code> is just syntactic sugar for\n<code>var[\"Name\"]</code>:\n\n<pre>\n\tvar ::= prefixexp `<b>.</b>&acute; Name\n</pre>\n\n<p>\nAll global variables live as fields in ordinary Lua tables,\ncalled <em>environment tables</em> or simply\n<em>environments</em> (see <a href=\"#2.9\">&sect;2.9</a>).\nEach function has its own reference to an environment,\nso that all global variables in this function\nwill refer to this environment table.\nWhen a function is created,\nit inherits the environment from the function that created it.\nTo get the environment table of a Lua function,\nyou call <a href=\"#pdf-getfenv\"><code>getfenv</code></a>.\nTo replace it,\nyou call <a href=\"#pdf-setfenv\"><code>setfenv</code></a>.\n(You can only manipulate the environment of C&nbsp;functions\nthrough the debug library; (see <a href=\"#5.9\">&sect;5.9</a>).)\n\n\n<p>\nAn access to a global variable <code>x</code>\nis equivalent to <code>_env.x</code>,\nwhich in turn is equivalent to\n\n<pre>\n     gettable_event(_env, \"x\")\n</pre><p>\nwhere <code>_env</code> is the environment of the running function.\n(See <a href=\"#2.8\">&sect;2.8</a> for a complete description of the\n<code>gettable_event</code> function.\nThis function is not defined or callable in Lua.\nSimilarly, the <code>_env</code> variable is not defined in Lua.\nWe use them here only for explanatory purposes.)\n\n\n\n\n\n<h2>2.4 - <a name=\"2.4\">Statements</a></h2>\n\n<p>\nLua supports an almost conventional set of statements,\nsimilar to those in Pascal or C.\nThis set includes\nassignments, control structures, function calls,\nand variable declarations.\n\n\n\n<h3>2.4.1 - <a name=\"2.4.1\">Chunks</a></h3>\n\n<p>\nThe unit of execution of Lua is called a <em>chunk</em>.\nA chunk is simply a sequence of statements,\nwhich are executed sequentially.\nEach statement can be optionally followed by a semicolon:\n\n<pre>\n\tchunk ::= {stat [`<b>;</b>&acute;]}\n</pre><p>\nThere are no empty statements and thus '<code>;;</code>' is not legal.\n\n\n<p>\nLua handles a chunk as the body of an anonymous function \nwith a variable number of arguments\n(see <a href=\"#2.5.9\">&sect;2.5.9</a>).\nAs such, chunks can define local variables,\nreceive arguments, and return values.\n\n\n<p>\nA chunk can be stored in a file or in a string inside the host program.\nTo execute a chunk,\nLua first pre-compiles the chunk into instructions for a virtual machine,\nand then it executes the compiled code\nwith an interpreter for the virtual machine.\n\n\n<p>\nChunks can also be pre-compiled into binary form;\nsee program <code>luac</code> for details.\nPrograms in source and compiled forms are interchangeable;\nLua automatically detects the file type and acts accordingly.\n\n\n\n\n\n\n<h3>2.4.2 - <a name=\"2.4.2\">Blocks</a></h3><p>\nA block is a list of statements;\nsyntactically, a block is the same as a chunk:\n\n<pre>\n\tblock ::= chunk\n</pre>\n\n<p>\nA block can be explicitly delimited to produce a single statement:\n\n<pre>\n\tstat ::= <b>do</b> block <b>end</b>\n</pre><p>\nExplicit blocks are useful\nto control the scope of variable declarations.\nExplicit blocks are also sometimes used to\nadd a <b>return</b> or <b>break</b> statement in the middle\nof another block (see <a href=\"#2.4.4\">&sect;2.4.4</a>).\n\n\n\n\n\n<h3>2.4.3 - <a name=\"2.4.3\">Assignment</a></h3>\n\n<p>\nLua allows multiple assignments.\nTherefore, the syntax for assignment\ndefines a list of variables on the left side\nand a list of expressions on the right side.\nThe elements in both lists are separated by commas:\n\n<pre>\n\tstat ::= varlist `<b>=</b>&acute; explist\n\tvarlist ::= var {`<b>,</b>&acute; var}\n\texplist ::= exp {`<b>,</b>&acute; exp}\n</pre><p>\nExpressions are discussed in <a href=\"#2.5\">&sect;2.5</a>.\n\n\n<p>\nBefore the assignment,\nthe list of values is <em>adjusted</em> to the length of\nthe list of variables.\nIf there are more values than needed,\nthe excess values are thrown away.\nIf there are fewer values than needed,\nthe list is extended with as many  <b>nil</b>'s as needed.\nIf the list of expressions ends with a function call,\nthen all values returned by that call enter the list of values,\nbefore the adjustment\n(except when the call is enclosed in parentheses; see <a href=\"#2.5\">&sect;2.5</a>).\n\n\n<p>\nThe assignment statement first evaluates all its expressions\nand only then are the assignments performed.\nThus the code\n\n<pre>\n     i = 3\n     i, a[i] = i+1, 20\n</pre><p>\nsets <code>a[3]</code> to 20, without affecting <code>a[4]</code>\nbecause the <code>i</code> in <code>a[i]</code> is evaluated (to 3)\nbefore it is assigned&nbsp;4.\nSimilarly, the line\n\n<pre>\n     x, y = y, x\n</pre><p>\nexchanges the values of <code>x</code> and <code>y</code>,\nand\n\n<pre>\n     x, y, z = y, z, x\n</pre><p>\ncyclically permutes the values of <code>x</code>, <code>y</code>, and <code>z</code>.\n\n\n<p>\nThe meaning of assignments to global variables\nand table fields can be changed via metatables.\nAn assignment to an indexed variable <code>t[i] = val</code> is equivalent to\n<code>settable_event(t,i,val)</code>.\n(See <a href=\"#2.8\">&sect;2.8</a> for a complete description of the\n<code>settable_event</code> function.\nThis function is not defined or callable in Lua.\nWe use it here only for explanatory purposes.)\n\n\n<p>\nAn assignment to a global variable <code>x = val</code>\nis equivalent to the assignment\n<code>_env.x = val</code>,\nwhich in turn is equivalent to\n\n<pre>\n     settable_event(_env, \"x\", val)\n</pre><p>\nwhere <code>_env</code> is the environment of the running function.\n(The <code>_env</code> variable is not defined in Lua.\nWe use it here only for explanatory purposes.)\n\n\n\n\n\n<h3>2.4.4 - <a name=\"2.4.4\">Control Structures</a></h3><p>\nThe control structures\n<b>if</b>, <b>while</b>, and <b>repeat</b> have the usual meaning and\nfamiliar syntax:\n\n\n\n\n<pre>\n\tstat ::= <b>while</b> exp <b>do</b> block <b>end</b>\n\tstat ::= <b>repeat</b> block <b>until</b> exp\n\tstat ::= <b>if</b> exp <b>then</b> block {<b>elseif</b> exp <b>then</b> block} [<b>else</b> block] <b>end</b>\n</pre><p>\nLua also has a <b>for</b> statement, in two flavors (see <a href=\"#2.4.5\">&sect;2.4.5</a>).\n\n\n<p>\nThe condition expression of a\ncontrol structure can return any value.\nBoth <b>false</b> and <b>nil</b> are considered false.\nAll values different from <b>nil</b> and <b>false</b> are considered true\n(in particular, the number 0 and the empty string are also true).\n\n\n<p>\nIn the <b>repeat</b>&ndash;<b>until</b> loop,\nthe inner block does not end at the <b>until</b> keyword,\nbut only after the condition.\nSo, the condition can refer to local variables\ndeclared inside the loop block.\n\n\n<p>\nThe <b>return</b> statement is used to return values\nfrom a function or a chunk (which is just a function).\n\nFunctions and chunks can return more than one value,\nand so the syntax for the <b>return</b> statement is\n\n<pre>\n\tstat ::= <b>return</b> [explist]\n</pre>\n\n<p>\nThe <b>break</b> statement is used to terminate the execution of a\n<b>while</b>, <b>repeat</b>, or <b>for</b> loop,\nskipping to the next statement after the loop:\n\n\n<pre>\n\tstat ::= <b>break</b>\n</pre><p>\nA <b>break</b> ends the innermost enclosing loop.\n\n\n<p>\nThe <b>return</b> and <b>break</b>\nstatements can only be written as the <em>last</em> statement of a block.\nIf it is really necessary to <b>return</b> or <b>break</b> in the\nmiddle of a block,\nthen an explicit inner block can be used,\nas in the idioms\n<code>do return end</code> and <code>do break end</code>,\nbecause now <b>return</b> and <b>break</b> are the last statements in\ntheir (inner) blocks.\n\n\n\n\n\n<h3>2.4.5 - <a name=\"2.4.5\">For Statement</a></h3>\n\n<p>\n\nThe <b>for</b> statement has two forms:\none numeric and one generic.\n\n\n<p>\nThe numeric <b>for</b> loop repeats a block of code while a\ncontrol variable runs through an arithmetic progression.\nIt has the following syntax:\n\n<pre>\n\tstat ::= <b>for</b> Name `<b>=</b>&acute; exp `<b>,</b>&acute; exp [`<b>,</b>&acute; exp] <b>do</b> block <b>end</b>\n</pre><p>\nThe <em>block</em> is repeated for <em>name</em> starting at the value of\nthe first <em>exp</em>, until it passes the second <em>exp</em> by steps of the\nthird <em>exp</em>.\nMore precisely, a <b>for</b> statement like\n\n<pre>\n     for v = <em>e1</em>, <em>e2</em>, <em>e3</em> do <em>block</em> end\n</pre><p>\nis equivalent to the code:\n\n<pre>\n     do\n       local <em>var</em>, <em>limit</em>, <em>step</em> = tonumber(<em>e1</em>), tonumber(<em>e2</em>), tonumber(<em>e3</em>)\n       if not (<em>var</em> and <em>limit</em> and <em>step</em>) then error() end\n       while (<em>step</em> &gt; 0 and <em>var</em> &lt;= <em>limit</em>) or (<em>step</em> &lt;= 0 and <em>var</em> &gt;= <em>limit</em>) do\n         local v = <em>var</em>\n         <em>block</em>\n         <em>var</em> = <em>var</em> + <em>step</em>\n       end\n     end\n</pre><p>\nNote the following:\n\n<ul>\n\n<li>\nAll three control expressions are evaluated only once,\nbefore the loop starts.\nThey must all result in numbers.\n</li>\n\n<li>\n<code><em>var</em></code>, <code><em>limit</em></code>, and <code><em>step</em></code> are invisible variables.\nThe names shown here are for explanatory purposes only.\n</li>\n\n<li>\nIf the third expression (the step) is absent,\nthen a step of&nbsp;1 is used.\n</li>\n\n<li>\nYou can use <b>break</b> to exit a <b>for</b> loop.\n</li>\n\n<li>\nThe loop variable <code>v</code> is local to the loop;\nyou cannot use its value after the <b>for</b> ends or is broken.\nIf you need this value,\nassign it to another variable before breaking or exiting the loop.\n</li>\n\n</ul>\n\n<p>\nThe generic <b>for</b> statement works over functions,\ncalled <em>iterators</em>.\nOn each iteration, the iterator function is called to produce a new value,\nstopping when this new value is <b>nil</b>.\nThe generic <b>for</b> loop has the following syntax:\n\n<pre>\n\tstat ::= <b>for</b> namelist <b>in</b> explist <b>do</b> block <b>end</b>\n\tnamelist ::= Name {`<b>,</b>&acute; Name}\n</pre><p>\nA <b>for</b> statement like\n\n<pre>\n     for <em>var_1</em>, &middot;&middot;&middot;, <em>var_n</em> in <em>explist</em> do <em>block</em> end\n</pre><p>\nis equivalent to the code:\n\n<pre>\n     do\n       local <em>f</em>, <em>s</em>, <em>var</em> = <em>explist</em>\n       while true do\n         local <em>var_1</em>, &middot;&middot;&middot;, <em>var_n</em> = <em>f</em>(<em>s</em>, <em>var</em>)\n         <em>var</em> = <em>var_1</em>\n         if <em>var</em> == nil then break end\n         <em>block</em>\n       end\n     end\n</pre><p>\nNote the following:\n\n<ul>\n\n<li>\n<code><em>explist</em></code> is evaluated only once.\nIts results are an <em>iterator</em> function,\na <em>state</em>,\nand an initial value for the first <em>iterator variable</em>.\n</li>\n\n<li>\n<code><em>f</em></code>, <code><em>s</em></code>, and <code><em>var</em></code> are invisible variables.\nThe names are here for explanatory purposes only.\n</li>\n\n<li>\nYou can use <b>break</b> to exit a <b>for</b> loop.\n</li>\n\n<li>\nThe loop variables <code><em>var_i</em></code> are local to the loop;\nyou cannot use their values after the <b>for</b> ends.\nIf you need these values,\nthen assign them to other variables before breaking or exiting the loop.\n</li>\n\n</ul>\n\n\n\n\n<h3>2.4.6 - <a name=\"2.4.6\">Function Calls as Statements</a></h3><p>\nTo allow possible side-effects,\nfunction calls can be executed as statements:\n\n<pre>\n\tstat ::= functioncall\n</pre><p>\nIn this case, all returned values are thrown away.\nFunction calls are explained in <a href=\"#2.5.8\">&sect;2.5.8</a>.\n\n\n\n\n\n<h3>2.4.7 - <a name=\"2.4.7\">Local Declarations</a></h3><p>\nLocal variables can be declared anywhere inside a block.\nThe declaration can include an initial assignment:\n\n<pre>\n\tstat ::= <b>local</b> namelist [`<b>=</b>&acute; explist]\n</pre><p>\nIf present, an initial assignment has the same semantics\nof a multiple assignment (see <a href=\"#2.4.3\">&sect;2.4.3</a>).\nOtherwise, all variables are initialized with <b>nil</b>.\n\n\n<p>\nA chunk is also a block (see <a href=\"#2.4.1\">&sect;2.4.1</a>),\nand so local variables can be declared in a chunk outside any explicit block.\nThe scope of such local variables extends until the end of the chunk.\n\n\n<p>\nThe visibility rules for local variables are explained in <a href=\"#2.6\">&sect;2.6</a>.\n\n\n\n\n\n\n\n<h2>2.5 - <a name=\"2.5\">Expressions</a></h2>\n\n<p>\nThe basic expressions in Lua are the following:\n\n<pre>\n\texp ::= prefixexp\n\texp ::= <b>nil</b> | <b>false</b> | <b>true</b>\n\texp ::= Number\n\texp ::= String\n\texp ::= function\n\texp ::= tableconstructor\n\texp ::= `<b>...</b>&acute;\n\texp ::= exp binop exp\n\texp ::= unop exp\n\tprefixexp ::= var | functioncall | `<b>(</b>&acute; exp `<b>)</b>&acute;\n</pre>\n\n<p>\nNumbers and literal strings are explained in <a href=\"#2.1\">&sect;2.1</a>;\nvariables are explained in <a href=\"#2.3\">&sect;2.3</a>;\nfunction definitions are explained in <a href=\"#2.5.9\">&sect;2.5.9</a>;\nfunction calls are explained in <a href=\"#2.5.8\">&sect;2.5.8</a>;\ntable constructors are explained in <a href=\"#2.5.7\">&sect;2.5.7</a>.\nVararg expressions,\ndenoted by three dots ('<code>...</code>'), can only be used when\ndirectly inside a vararg function;\nthey are explained in <a href=\"#2.5.9\">&sect;2.5.9</a>.\n\n\n<p>\nBinary operators comprise arithmetic operators (see <a href=\"#2.5.1\">&sect;2.5.1</a>),\nrelational operators (see <a href=\"#2.5.2\">&sect;2.5.2</a>), logical operators (see <a href=\"#2.5.3\">&sect;2.5.3</a>),\nand the concatenation operator (see <a href=\"#2.5.4\">&sect;2.5.4</a>).\nUnary operators comprise the unary minus (see <a href=\"#2.5.1\">&sect;2.5.1</a>),\nthe unary <b>not</b> (see <a href=\"#2.5.3\">&sect;2.5.3</a>),\nand the unary <em>length operator</em> (see <a href=\"#2.5.5\">&sect;2.5.5</a>).\n\n\n<p>\nBoth function calls and vararg expressions can result in multiple values.\nIf an expression is used as a statement\n(only possible for function calls (see <a href=\"#2.4.6\">&sect;2.4.6</a>)),\nthen its return list is adjusted to zero elements,\nthus discarding all returned values.\nIf an expression is used as the last (or the only) element\nof a list of expressions,\nthen no adjustment is made\n(unless the call is enclosed in parentheses).\nIn all other contexts,\nLua adjusts the result list to one element,\ndiscarding all values except the first one.\n\n\n<p>\nHere are some examples:\n\n<pre>\n     f()                -- adjusted to 0 results\n     g(f(), x)          -- f() is adjusted to 1 result\n     g(x, f())          -- g gets x plus all results from f()\n     a,b,c = f(), x     -- f() is adjusted to 1 result (c gets nil)\n     a,b = ...          -- a gets the first vararg parameter, b gets\n                        -- the second (both a and b can get nil if there\n                        -- is no corresponding vararg parameter)\n     \n     a,b,c = x, f()     -- f() is adjusted to 2 results\n     a,b,c = f()        -- f() is adjusted to 3 results\n     return f()         -- returns all results from f()\n     return ...         -- returns all received vararg parameters\n     return x,y,f()     -- returns x, y, and all results from f()\n     {f()}              -- creates a list with all results from f()\n     {...}              -- creates a list with all vararg parameters\n     {f(), nil}         -- f() is adjusted to 1 result\n</pre>\n\n<p>\nAny expression enclosed in parentheses always results in only one value.\nThus,\n<code>(f(x,y,z))</code> is always a single value,\neven if <code>f</code> returns several values.\n(The value of <code>(f(x,y,z))</code> is the first value returned by <code>f</code>\nor <b>nil</b> if <code>f</code> does not return any values.)\n\n\n\n<h3>2.5.1 - <a name=\"2.5.1\">Arithmetic Operators</a></h3><p>\nLua supports the usual arithmetic operators:\nthe binary <code>+</code> (addition),\n<code>-</code> (subtraction), <code>*</code> (multiplication),\n<code>/</code> (division), <code>%</code> (modulo), and <code>^</code> (exponentiation);\nand unary <code>-</code> (negation).\nIf the operands are numbers, or strings that can be converted to\nnumbers (see <a href=\"#2.2.1\">&sect;2.2.1</a>),\nthen all operations have the usual meaning.\nExponentiation works for any exponent.\nFor instance, <code>x^(-0.5)</code> computes the inverse of the square root of <code>x</code>.\nModulo is defined as\n\n<pre>\n     a % b == a - math.floor(a/b)*b\n</pre><p>\nThat is, it is the remainder of a division that rounds\nthe quotient towards minus infinity.\n\n\n\n\n\n<h3>2.5.2 - <a name=\"2.5.2\">Relational Operators</a></h3><p>\nThe relational operators in Lua are\n\n<pre>\n     ==    ~=    &lt;     &gt;     &lt;=    &gt;=\n</pre><p>\nThese operators always result in <b>false</b> or <b>true</b>.\n\n\n<p>\nEquality (<code>==</code>) first compares the type of its operands.\nIf the types are different, then the result is <b>false</b>.\nOtherwise, the values of the operands are compared.\nNumbers and strings are compared in the usual way.\nObjects (tables, userdata, threads, and functions)\nare compared by <em>reference</em>:\ntwo objects are considered equal only if they are the <em>same</em> object.\nEvery time you create a new object\n(a table, userdata, thread, or function),\nthis new object is different from any previously existing object.\n\n\n<p>\nYou can change the way that Lua compares tables and userdata \nby using the \"eq\" metamethod (see <a href=\"#2.8\">&sect;2.8</a>).\n\n\n<p>\nThe conversion rules of <a href=\"#2.2.1\">&sect;2.2.1</a>\n<em>do not</em> apply to equality comparisons.\nThus, <code>\"0\"==0</code> evaluates to <b>false</b>,\nand <code>t[0]</code> and <code>t[\"0\"]</code> denote different\nentries in a table.\n\n\n<p>\nThe operator <code>~=</code> is exactly the negation of equality (<code>==</code>).\n\n\n<p>\nThe order operators work as follows.\nIf both arguments are numbers, then they are compared as such.\nOtherwise, if both arguments are strings,\nthen their values are compared according to the current locale.\nOtherwise, Lua tries to call the \"lt\" or the \"le\"\nmetamethod (see <a href=\"#2.8\">&sect;2.8</a>).\nA comparison <code>a &gt; b</code> is translated to <code>b &lt; a</code>\nand <code>a &gt;= b</code> is translated to <code>b &lt;= a</code>.\n\n\n\n\n\n<h3>2.5.3 - <a name=\"2.5.3\">Logical Operators</a></h3><p>\nThe logical operators in Lua are\n<b>and</b>, <b>or</b>, and <b>not</b>.\nLike the control structures (see <a href=\"#2.4.4\">&sect;2.4.4</a>),\nall logical operators consider both <b>false</b> and <b>nil</b> as false\nand anything else as true.\n\n\n<p>\nThe negation operator <b>not</b> always returns <b>false</b> or <b>true</b>.\nThe conjunction operator <b>and</b> returns its first argument\nif this value is <b>false</b> or <b>nil</b>;\notherwise, <b>and</b> returns its second argument.\nThe disjunction operator <b>or</b> returns its first argument\nif this value is different from <b>nil</b> and <b>false</b>;\notherwise, <b>or</b> returns its second argument.\nBoth <b>and</b> and <b>or</b> use short-cut evaluation;\nthat is,\nthe second operand is evaluated only if necessary.\nHere are some examples:\n\n<pre>\n     10 or 20            --&gt; 10\n     10 or error()       --&gt; 10\n     nil or \"a\"          --&gt; \"a\"\n     nil and 10          --&gt; nil\n     false and error()   --&gt; false\n     false and nil       --&gt; false\n     false or nil        --&gt; nil\n     10 and 20           --&gt; 20\n</pre><p>\n(In this manual,\n<code>--&gt;</code> indicates the result of the preceding expression.)\n\n\n\n\n\n<h3>2.5.4 - <a name=\"2.5.4\">Concatenation</a></h3><p>\nThe string concatenation operator in Lua is\ndenoted by two dots ('<code>..</code>').\nIf both operands are strings or numbers, then they are converted to\nstrings according to the rules mentioned in <a href=\"#2.2.1\">&sect;2.2.1</a>.\nOtherwise, the \"concat\" metamethod is called (see <a href=\"#2.8\">&sect;2.8</a>).\n\n\n\n\n\n<h3>2.5.5 - <a name=\"2.5.5\">The Length Operator</a></h3>\n\n<p>\nThe length operator is denoted by the unary operator <code>#</code>.\nThe length of a string is its number of bytes\n(that is, the usual meaning of string length when each\ncharacter is one byte).\n\n\n<p>\nThe length of a table <code>t</code> is defined to be any\ninteger index <code>n</code>\nsuch that <code>t[n]</code> is not <b>nil</b> and <code>t[n+1]</code> is <b>nil</b>;\nmoreover, if <code>t[1]</code> is <b>nil</b>, <code>n</code> can be zero.\nFor a regular array, with non-nil values from 1 to a given <code>n</code>,\nits length is exactly that <code>n</code>,\nthe index of its last value.\nIf the array has \"holes\"\n(that is, <b>nil</b> values between other non-nil values),\nthen <code>#t</code> can be any of the indices that\ndirectly precedes a <b>nil</b> value\n(that is, it may consider any such <b>nil</b> value as the end of\nthe array). \n\n\n\n\n\n<h3>2.5.6 - <a name=\"2.5.6\">Precedence</a></h3><p>\nOperator precedence in Lua follows the table below,\nfrom lower to higher priority:\n\n<pre>\n     or\n     and\n     &lt;     &gt;     &lt;=    &gt;=    ~=    ==\n     ..\n     +     -\n     *     /     %\n     not   #     - (unary)\n     ^\n</pre><p>\nAs usual,\nyou can use parentheses to change the precedences of an expression.\nThe concatenation ('<code>..</code>') and exponentiation ('<code>^</code>')\noperators are right associative.\nAll other binary operators are left associative.\n\n\n\n\n\n<h3>2.5.7 - <a name=\"2.5.7\">Table Constructors</a></h3><p>\nTable constructors are expressions that create tables.\nEvery time a constructor is evaluated, a new table is created.\nA constructor can be used to create an empty table\nor to create a table and initialize some of its fields.\nThe general syntax for constructors is\n\n<pre>\n\ttableconstructor ::= `<b>{</b>&acute; [fieldlist] `<b>}</b>&acute;\n\tfieldlist ::= field {fieldsep field} [fieldsep]\n\tfield ::= `<b>[</b>&acute; exp `<b>]</b>&acute; `<b>=</b>&acute; exp | Name `<b>=</b>&acute; exp | exp\n\tfieldsep ::= `<b>,</b>&acute; | `<b>;</b>&acute;\n</pre>\n\n<p>\nEach field of the form <code>[exp1] = exp2</code> adds to the new table an entry\nwith key <code>exp1</code> and value <code>exp2</code>.\nA field of the form <code>name = exp</code> is equivalent to\n<code>[\"name\"] = exp</code>.\nFinally, fields of the form <code>exp</code> are equivalent to\n<code>[i] = exp</code>, where <code>i</code> are consecutive numerical integers,\nstarting with 1.\nFields in the other formats do not affect this counting.\nFor example,\n\n<pre>\n     a = { [f(1)] = g; \"x\", \"y\"; x = 1, f(x), [30] = 23; 45 }\n</pre><p>\nis equivalent to\n\n<pre>\n     do\n       local t = {}\n       t[f(1)] = g\n       t[1] = \"x\"         -- 1st exp\n       t[2] = \"y\"         -- 2nd exp\n       t.x = 1            -- t[\"x\"] = 1\n       t[3] = f(x)        -- 3rd exp\n       t[30] = 23\n       t[4] = 45          -- 4th exp\n       a = t\n     end\n</pre>\n\n<p>\nIf the last field in the list has the form <code>exp</code>\nand the expression is a function call or a vararg expression,\nthen all values returned by this expression enter the list consecutively\n(see <a href=\"#2.5.8\">&sect;2.5.8</a>).\nTo avoid this,\nenclose the function call or the vararg expression\nin parentheses (see <a href=\"#2.5\">&sect;2.5</a>).\n\n\n<p>\nThe field list can have an optional trailing separator,\nas a convenience for machine-generated code.\n\n\n\n\n\n<h3>2.5.8 - <a name=\"2.5.8\">Function Calls</a></h3><p>\nA function call in Lua has the following syntax:\n\n<pre>\n\tfunctioncall ::= prefixexp args\n</pre><p>\nIn a function call,\nfirst prefixexp and args are evaluated.\nIf the value of prefixexp has type <em>function</em>,\nthen this function is called\nwith the given arguments.\nOtherwise, the prefixexp \"call\" metamethod is called,\nhaving as first parameter the value of prefixexp,\nfollowed by the original call arguments\n(see <a href=\"#2.8\">&sect;2.8</a>).\n\n\n<p>\nThe form\n\n<pre>\n\tfunctioncall ::= prefixexp `<b>:</b>&acute; Name args\n</pre><p>\ncan be used to call \"methods\".\nA call <code>v:name(<em>args</em>)</code>\nis syntactic sugar for <code>v.name(v,<em>args</em>)</code>,\nexcept that <code>v</code> is evaluated only once.\n\n\n<p>\nArguments have the following syntax:\n\n<pre>\n\targs ::= `<b>(</b>&acute; [explist] `<b>)</b>&acute;\n\targs ::= tableconstructor\n\targs ::= String\n</pre><p>\nAll argument expressions are evaluated before the call.\nA call of the form <code>f{<em>fields</em>}</code> is\nsyntactic sugar for <code>f({<em>fields</em>})</code>;\nthat is, the argument list is a single new table.\nA call of the form <code>f'<em>string</em>'</code>\n(or <code>f\"<em>string</em>\"</code> or <code>f[[<em>string</em>]]</code>)\nis syntactic sugar for <code>f('<em>string</em>')</code>;\nthat is, the argument list is a single literal string.\n\n\n<p>\nAs an exception to the free-format syntax of Lua,\nyou cannot put a line break before the '<code>(</code>' in a function call.\nThis restriction avoids some ambiguities in the language.\nIf you write\n\n<pre>\n     a = f\n     (g).x(a)\n</pre><p>\nLua would see that as a single statement, <code>a = f(g).x(a)</code>.\nSo, if you want two statements, you must add a semi-colon between them.\nIf you actually want to call <code>f</code>,\nyou must remove the line break before <code>(g)</code>.\n\n\n<p>\nA call of the form <code>return</code> <em>functioncall</em> is called\na <em>tail call</em>.\nLua implements <em>proper tail calls</em>\n(or <em>proper tail recursion</em>):\nin a tail call,\nthe called function reuses the stack entry of the calling function.\nTherefore, there is no limit on the number of nested tail calls that\na program can execute.\nHowever, a tail call erases any debug information about the\ncalling function.\nNote that a tail call only happens with a particular syntax,\nwhere the <b>return</b> has one single function call as argument;\nthis syntax makes the calling function return exactly\nthe returns of the called function.\nSo, none of the following examples are tail calls:\n\n<pre>\n     return (f(x))        -- results adjusted to 1\n     return 2 * f(x)\n     return x, f(x)       -- additional results\n     f(x); return         -- results discarded\n     return x or f(x)     -- results adjusted to 1\n</pre>\n\n\n\n\n<h3>2.5.9 - <a name=\"2.5.9\">Function Definitions</a></h3>\n\n<p>\nThe syntax for function definition is\n\n<pre>\n\tfunction ::= <b>function</b> funcbody\n\tfuncbody ::= `<b>(</b>&acute; [parlist] `<b>)</b>&acute; block <b>end</b>\n</pre>\n\n<p>\nThe following syntactic sugar simplifies function definitions:\n\n<pre>\n\tstat ::= <b>function</b> funcname funcbody\n\tstat ::= <b>local</b> <b>function</b> Name funcbody\n\tfuncname ::= Name {`<b>.</b>&acute; Name} [`<b>:</b>&acute; Name]\n</pre><p>\nThe statement\n\n<pre>\n     function f () <em>body</em> end\n</pre><p>\ntranslates to\n\n<pre>\n     f = function () <em>body</em> end\n</pre><p>\nThe statement\n\n<pre>\n     function t.a.b.c.f () <em>body</em> end\n</pre><p>\ntranslates to\n\n<pre>\n     t.a.b.c.f = function () <em>body</em> end\n</pre><p>\nThe statement\n\n<pre>\n     local function f () <em>body</em> end\n</pre><p>\ntranslates to\n\n<pre>\n     local f; f = function () <em>body</em> end\n</pre><p>\n<em>not</em> to\n\n<pre>\n     local f = function () <em>body</em> end\n</pre><p>\n(This only makes a difference when the body of the function\ncontains references to <code>f</code>.)\n\n\n<p>\nA function definition is an executable expression,\nwhose value has type <em>function</em>.\nWhen Lua pre-compiles a chunk,\nall its function bodies are pre-compiled too.\nThen, whenever Lua executes the function definition,\nthe function is <em>instantiated</em> (or <em>closed</em>).\nThis function instance (or <em>closure</em>)\nis the final value of the expression.\nDifferent instances of the same function\ncan refer to different  external local variables\nand can have different environment tables.\n\n\n<p>\nParameters act as local variables that are\ninitialized with the argument values:\n\n<pre>\n\tparlist ::= namelist [`<b>,</b>&acute; `<b>...</b>&acute;] | `<b>...</b>&acute;\n</pre><p>\nWhen a function is called,\nthe list of arguments is adjusted to\nthe length of the list of parameters,\nunless the function is a variadic or <em>vararg function</em>,\nwhich is\nindicated by three dots ('<code>...</code>') at the end of its parameter list.\nA vararg function does not adjust its argument list;\ninstead, it collects all extra arguments and supplies them\nto the function through a <em>vararg expression</em>,\nwhich is also written as three dots.\nThe value of this expression is a list of all actual extra arguments,\nsimilar to a function with multiple results.\nIf a vararg expression is used inside another expression\nor in the middle of a list of expressions,\nthen its return list is adjusted to one element.\nIf the expression is used as the last element of a list of expressions,\nthen no adjustment is made\n(unless that last expression is enclosed in parentheses).\n\n\n<p>\nAs an example, consider the following definitions:\n\n<pre>\n     function f(a, b) end\n     function g(a, b, ...) end\n     function r() return 1,2,3 end\n</pre><p>\nThen, we have the following mapping from arguments to parameters and\nto the vararg expression:\n\n<pre>\n     CALL            PARAMETERS\n     \n     f(3)             a=3, b=nil\n     f(3, 4)          a=3, b=4\n     f(3, 4, 5)       a=3, b=4\n     f(r(), 10)       a=1, b=10\n     f(r())           a=1, b=2\n     \n     g(3)             a=3, b=nil, ... --&gt;  (nothing)\n     g(3, 4)          a=3, b=4,   ... --&gt;  (nothing)\n     g(3, 4, 5, 8)    a=3, b=4,   ... --&gt;  5  8\n     g(5, r())        a=5, b=1,   ... --&gt;  2  3\n</pre>\n\n<p>\nResults are returned using the <b>return</b> statement (see <a href=\"#2.4.4\">&sect;2.4.4</a>).\nIf control reaches the end of a function\nwithout encountering a <b>return</b> statement,\nthen the function returns with no results.\n\n\n<p>\nThe <em>colon</em> syntax\nis used for defining <em>methods</em>,\nthat is, functions that have an implicit extra parameter <code>self</code>.\nThus, the statement\n\n<pre>\n     function t.a.b.c:f (<em>params</em>) <em>body</em> end\n</pre><p>\nis syntactic sugar for\n\n<pre>\n     t.a.b.c.f = function (self, <em>params</em>) <em>body</em> end\n</pre>\n\n\n\n\n\n\n<h2>2.6 - <a name=\"2.6\">Visibility Rules</a></h2>\n\n<p>\n\nLua is a lexically scoped language.\nThe scope of variables begins at the first statement <em>after</em>\ntheir declaration and lasts until the end of the innermost block that\nincludes the declaration.\nConsider the following example:\n\n<pre>\n     x = 10                -- global variable\n     do                    -- new block\n       local x = x         -- new 'x', with value 10\n       print(x)            --&gt; 10\n       x = x+1\n       do                  -- another block\n         local x = x+1     -- another 'x'\n         print(x)          --&gt; 12\n       end\n       print(x)            --&gt; 11\n     end\n     print(x)              --&gt; 10  (the global one)\n</pre>\n\n<p>\nNotice that, in a declaration like <code>local x = x</code>,\nthe new <code>x</code> being declared is not in scope yet,\nand so the second <code>x</code> refers to the outside variable.\n\n\n<p>\nBecause of the lexical scoping rules,\nlocal variables can be freely accessed by functions\ndefined inside their scope.\nA local variable used by an inner function is called\nan <em>upvalue</em>, or <em>external local variable</em>,\ninside the inner function.\n\n\n<p>\nNotice that each execution of a <b>local</b> statement\ndefines new local variables.\nConsider the following example:\n\n<pre>\n     a = {}\n     local x = 20\n     for i=1,10 do\n       local y = 0\n       a[i] = function () y=y+1; return x+y end\n     end\n</pre><p>\nThe loop creates ten closures\n(that is, ten instances of the anonymous function).\nEach of these closures uses a different <code>y</code> variable,\nwhile all of them share the same <code>x</code>.\n\n\n\n\n\n<h2>2.7 - <a name=\"2.7\">Error Handling</a></h2>\n\n<p>\nBecause Lua is an embedded extension language,\nall Lua actions start from C&nbsp;code in the host program\ncalling a function from the Lua library (see <a href=\"#lua_pcall\"><code>lua_pcall</code></a>).\nWhenever an error occurs during Lua compilation or execution,\ncontrol returns to C,\nwhich can take appropriate measures\n(such as printing an error message).\n\n\n<p>\nLua code can explicitly generate an error by calling the\n<a href=\"#pdf-error\"><code>error</code></a> function.\nIf you need to catch errors in Lua,\nyou can use the <a href=\"#pdf-pcall\"><code>pcall</code></a> function.\n\n\n\n\n\n<h2>2.8 - <a name=\"2.8\">Metatables</a></h2>\n\n<p>\nEvery value in Lua can have a <em>metatable</em>.\nThis <em>metatable</em> is an ordinary Lua table\nthat defines the behavior of the original value\nunder certain special operations.\nYou can change several aspects of the behavior\nof operations over a value by setting specific fields in its metatable.\nFor instance, when a non-numeric value is the operand of an addition,\nLua checks for a function in the field <code>\"__add\"</code> in its metatable.\nIf it finds one,\nLua calls this function to perform the addition.\n\n\n<p>\nWe call the keys in a metatable <em>events</em>\nand the values <em>metamethods</em>.\nIn the previous example, the event is <code>\"add\"</code> \nand the metamethod is the function that performs the addition.\n\n\n<p>\nYou can query the metatable of any value\nthrough the <a href=\"#pdf-getmetatable\"><code>getmetatable</code></a> function.\n\n\n<p>\nYou can replace the metatable of tables\nthrough the <a href=\"#pdf-setmetatable\"><code>setmetatable</code></a>\nfunction.\nYou cannot change the metatable of other types from Lua\n(except by using the debug library);\nyou must use the C&nbsp;API for that.\n\n\n<p>\nTables and full userdata have individual metatables\n(although multiple tables and userdata can share their metatables).\nValues of all other types share one single metatable per type;\nthat is, there is one single metatable for all numbers,\none for all strings, etc.\n\n\n<p>\nA metatable controls how an object behaves in arithmetic operations,\norder comparisons, concatenation, length operation, and indexing.\nA metatable also can define a function to be called when a userdata\nis garbage collected.\nFor each of these operations Lua associates a specific key\ncalled an <em>event</em>.\nWhen Lua performs one of these operations over a value,\nit checks whether this value has a metatable with the corresponding event.\nIf so, the value associated with that key (the metamethod)\ncontrols how Lua will perform the operation.\n\n\n<p>\nMetatables control the operations listed next.\nEach operation is identified by its corresponding name.\nThe key for each operation is a string with its name prefixed by\ntwo underscores, '<code>__</code>';\nfor instance, the key for operation \"add\" is the\nstring <code>\"__add\"</code>.\nThe semantics of these operations is better explained by a Lua function\ndescribing how the interpreter executes the operation.\n\n\n<p>\nThe code shown here in Lua is only illustrative;\nthe real behavior is hard coded in the interpreter\nand it is much more efficient than this simulation.\nAll functions used in these descriptions\n(<a href=\"#pdf-rawget\"><code>rawget</code></a>, <a href=\"#pdf-tonumber\"><code>tonumber</code></a>, etc.)\nare described in <a href=\"#5.1\">&sect;5.1</a>.\nIn particular, to retrieve the metamethod of a given object,\nwe use the expression\n\n<pre>\n     metatable(obj)[event]\n</pre><p>\nThis should be read as\n\n<pre>\n     rawget(getmetatable(obj) or {}, event)\n</pre><p>\n\nThat is, the access to a metamethod does not invoke other metamethods,\nand the access to objects with no metatables does not fail\n(it simply results in <b>nil</b>).\n\n\n\n<ul>\n\n<li><b>\"add\":</b>\nthe <code>+</code> operation.\n\n\n\n<p>\nThe function <code>getbinhandler</code> below defines how Lua chooses a handler\nfor a binary operation.\nFirst, Lua tries the first operand.\nIf its type does not define a handler for the operation,\nthen Lua tries the second operand.\n\n<pre>\n     function getbinhandler (op1, op2, event)\n       return metatable(op1)[event] or metatable(op2)[event]\n     end\n</pre><p>\nBy using this function,\nthe behavior of the <code>op1 + op2</code> is\n\n<pre>\n     function add_event (op1, op2)\n       local o1, o2 = tonumber(op1), tonumber(op2)\n       if o1 and o2 then  -- both operands are numeric?\n         return o1 + o2   -- '+' here is the primitive 'add'\n       else  -- at least one of the operands is not numeric\n         local h = getbinhandler(op1, op2, \"__add\")\n         if h then\n           -- call the handler with both operands\n           return (h(op1, op2))\n         else  -- no handler available: default behavior\n           error(&middot;&middot;&middot;)\n         end\n       end\n     end\n</pre><p>\n</li>\n\n<li><b>\"sub\":</b>\nthe <code>-</code> operation.\n\nBehavior similar to the \"add\" operation.\n</li>\n\n<li><b>\"mul\":</b>\nthe <code>*</code> operation.\n\nBehavior similar to the \"add\" operation.\n</li>\n\n<li><b>\"div\":</b>\nthe <code>/</code> operation.\n\nBehavior similar to the \"add\" operation.\n</li>\n\n<li><b>\"mod\":</b>\nthe <code>%</code> operation.\n\nBehavior similar to the \"add\" operation,\nwith the operation\n<code>o1 - floor(o1/o2)*o2</code> as the primitive operation.\n</li>\n\n<li><b>\"pow\":</b>\nthe <code>^</code> (exponentiation) operation.\n\nBehavior similar to the \"add\" operation,\nwith the function <code>pow</code> (from the C&nbsp;math library)\nas the primitive operation.\n</li>\n\n<li><b>\"unm\":</b>\nthe unary <code>-</code> operation.\n\n\n<pre>\n     function unm_event (op)\n       local o = tonumber(op)\n       if o then  -- operand is numeric?\n         return -o  -- '-' here is the primitive 'unm'\n       else  -- the operand is not numeric.\n         -- Try to get a handler from the operand\n         local h = metatable(op).__unm\n         if h then\n           -- call the handler with the operand\n           return (h(op))\n         else  -- no handler available: default behavior\n           error(&middot;&middot;&middot;)\n         end\n       end\n     end\n</pre><p>\n</li>\n\n<li><b>\"concat\":</b>\nthe <code>..</code> (concatenation) operation.\n\n\n<pre>\n     function concat_event (op1, op2)\n       if (type(op1) == \"string\" or type(op1) == \"number\") and\n          (type(op2) == \"string\" or type(op2) == \"number\") then\n         return op1 .. op2  -- primitive string concatenation\n       else\n         local h = getbinhandler(op1, op2, \"__concat\")\n         if h then\n           return (h(op1, op2))\n         else\n           error(&middot;&middot;&middot;)\n         end\n       end\n     end\n</pre><p>\n</li>\n\n<li><b>\"len\":</b>\nthe <code>#</code> operation.\n\n\n<pre>\n     function len_event (op)\n       if type(op) == \"string\" then\n         return strlen(op)         -- primitive string length\n       elseif type(op) == \"table\" then\n         return #op                -- primitive table length\n       else\n         local h = metatable(op).__len\n         if h then\n           -- call the handler with the operand\n           return (h(op))\n         else  -- no handler available: default behavior\n           error(&middot;&middot;&middot;)\n         end\n       end\n     end\n</pre><p>\nSee <a href=\"#2.5.5\">&sect;2.5.5</a> for a description of the length of a table.\n</li>\n\n<li><b>\"eq\":</b>\nthe <code>==</code> operation.\n\nThe function <code>getcomphandler</code> defines how Lua chooses a metamethod\nfor comparison operators.\nA metamethod only is selected when both objects\nbeing compared have the same type\nand the same metamethod for the selected operation.\n\n<pre>\n     function getcomphandler (op1, op2, event)\n       if type(op1) ~= type(op2) then return nil end\n       local mm1 = metatable(op1)[event]\n       local mm2 = metatable(op2)[event]\n       if mm1 == mm2 then return mm1 else return nil end\n     end\n</pre><p>\nThe \"eq\" event is defined as follows:\n\n<pre>\n     function eq_event (op1, op2)\n       if type(op1) ~= type(op2) then  -- different types?\n         return false   -- different objects\n       end\n       if op1 == op2 then   -- primitive equal?\n         return true   -- objects are equal\n       end\n       -- try metamethod\n       local h = getcomphandler(op1, op2, \"__eq\")\n       if h then\n         return (h(op1, op2))\n       else\n         return false\n       end\n     end\n</pre><p>\n<code>a ~= b</code> is equivalent to <code>not (a == b)</code>.\n</li>\n\n<li><b>\"lt\":</b>\nthe <code>&lt;</code> operation.\n\n\n<pre>\n     function lt_event (op1, op2)\n       if type(op1) == \"number\" and type(op2) == \"number\" then\n         return op1 &lt; op2   -- numeric comparison\n       elseif type(op1) == \"string\" and type(op2) == \"string\" then\n         return op1 &lt; op2   -- lexicographic comparison\n       else\n         local h = getcomphandler(op1, op2, \"__lt\")\n         if h then\n           return (h(op1, op2))\n         else\n           error(&middot;&middot;&middot;)\n         end\n       end\n     end\n</pre><p>\n<code>a &gt; b</code> is equivalent to <code>b &lt; a</code>.\n</li>\n\n<li><b>\"le\":</b>\nthe <code>&lt;=</code> operation.\n\n\n<pre>\n     function le_event (op1, op2)\n       if type(op1) == \"number\" and type(op2) == \"number\" then\n         return op1 &lt;= op2   -- numeric comparison\n       elseif type(op1) == \"string\" and type(op2) == \"string\" then\n         return op1 &lt;= op2   -- lexicographic comparison\n       else\n         local h = getcomphandler(op1, op2, \"__le\")\n         if h then\n           return (h(op1, op2))\n         else\n           h = getcomphandler(op1, op2, \"__lt\")\n           if h then\n             return not h(op2, op1)\n           else\n             error(&middot;&middot;&middot;)\n           end\n         end\n       end\n     end\n</pre><p>\n<code>a &gt;= b</code> is equivalent to <code>b &lt;= a</code>.\nNote that, in the absence of a \"le\" metamethod,\nLua tries the \"lt\", assuming that <code>a &lt;= b</code> is\nequivalent to <code>not (b &lt; a)</code>.\n</li>\n\n<li><b>\"index\":</b>\nThe indexing access <code>table[key]</code>.\n\n\n<pre>\n     function gettable_event (table, key)\n       local h\n       if type(table) == \"table\" then\n         local v = rawget(table, key)\n         if v ~= nil then return v end\n         h = metatable(table).__index\n         if h == nil then return nil end\n       else\n         h = metatable(table).__index\n         if h == nil then\n           error(&middot;&middot;&middot;)\n         end\n       end\n       if type(h) == \"function\" then\n         return (h(table, key))     -- call the handler\n       else return h[key]           -- or repeat operation on it\n       end\n     end\n</pre><p>\n</li>\n\n<li><b>\"newindex\":</b>\nThe indexing assignment <code>table[key] = value</code>.\n\n\n<pre>\n     function settable_event (table, key, value)\n       local h\n       if type(table) == \"table\" then\n         local v = rawget(table, key)\n         if v ~= nil then rawset(table, key, value); return end\n         h = metatable(table).__newindex\n         if h == nil then rawset(table, key, value); return end\n       else\n         h = metatable(table).__newindex\n         if h == nil then\n           error(&middot;&middot;&middot;)\n         end\n       end\n       if type(h) == \"function\" then\n         h(table, key,value)           -- call the handler\n       else h[key] = value             -- or repeat operation on it\n       end\n     end\n</pre><p>\n</li>\n\n<li><b>\"call\":</b>\ncalled when Lua calls a value.\n\n\n<pre>\n     function function_event (func, ...)\n       if type(func) == \"function\" then\n         return func(...)   -- primitive call\n       else\n         local h = metatable(func).__call\n         if h then\n           return h(func, ...)\n         else\n           error(&middot;&middot;&middot;)\n         end\n       end\n     end\n</pre><p>\n</li>\n\n</ul>\n\n\n\n\n<h2>2.9 - <a name=\"2.9\">Environments</a></h2>\n\n<p>\nBesides metatables,\nobjects of types thread, function, and userdata\nhave another table associated with them,\ncalled their <em>environment</em>.\nLike metatables, environments are regular tables and\nmultiple objects can share the same environment.\n\n\n<p>\nThreads are created sharing the environment of the creating thread.\nUserdata and C&nbsp;functions are created sharing the environment\nof the creating C&nbsp;function.\nNon-nested Lua functions\n(created by <a href=\"#pdf-loadfile\"><code>loadfile</code></a>, <a href=\"#pdf-loadstring\"><code>loadstring</code></a> or <a href=\"#pdf-load\"><code>load</code></a>)\nare created sharing the environment of the creating thread.\nNested Lua functions are created sharing the environment of\nthe creating Lua function.\n\n\n<p>\nEnvironments associated with userdata have no meaning for Lua.\nIt is only a convenience feature for programmers to associate a table to\na userdata.\n\n\n<p>\nEnvironments associated with threads are called\n<em>global environments</em>.\nThey are used as the default environment for threads and\nnon-nested Lua functions created by the thread\nand can be directly accessed by C&nbsp;code (see <a href=\"#3.3\">&sect;3.3</a>).\n\n\n<p>\nThe environment associated with a C&nbsp;function can be directly\naccessed by C&nbsp;code (see <a href=\"#3.3\">&sect;3.3</a>).\nIt is used as the default environment for other C&nbsp;functions\nand userdata created by the function.\n\n\n<p>\nEnvironments associated with Lua functions are used to resolve\nall accesses to global variables within the function (see <a href=\"#2.3\">&sect;2.3</a>).\nThey are used as the default environment for nested Lua functions\ncreated by the function.\n\n\n<p>\nYou can change the environment of a Lua function or the\nrunning thread by calling <a href=\"#pdf-setfenv\"><code>setfenv</code></a>.\nYou can get the environment of a Lua function or the running thread\nby calling <a href=\"#pdf-getfenv\"><code>getfenv</code></a>.\nTo manipulate the environment of other objects\n(userdata, C&nbsp;functions, other threads) you must\nuse the C&nbsp;API.\n\n\n\n\n\n<h2>2.10 - <a name=\"2.10\">Garbage Collection</a></h2>\n\n<p>\nLua performs automatic memory management.\nThis means that\nyou have to worry neither about allocating memory for new objects\nnor about freeing it when the objects are no longer needed.\nLua manages memory automatically by running\na <em>garbage collector</em> from time to time\nto collect all <em>dead objects</em>\n(that is, objects that are no longer accessible from Lua).\nAll memory used by Lua is subject to automatic management:\ntables, userdata, functions, threads, strings, etc.\n\n\n<p>\nLua implements an incremental mark-and-sweep collector.\nIt uses two numbers to control its garbage-collection cycles:\nthe <em>garbage-collector pause</em> and\nthe <em>garbage-collector step multiplier</em>.\nBoth use percentage points as units\n(so that a value of 100 means an internal value of 1).\n\n\n<p>\nThe garbage-collector pause\ncontrols how long the collector waits before starting a new cycle.\nLarger values make the collector less aggressive.\nValues smaller than 100 mean the collector will not wait to\nstart a new cycle.\nA value of 200 means that the collector waits for the total memory in use\nto double before starting a new cycle.\n\n\n<p>\nThe step multiplier\ncontrols the relative speed of the collector relative to\nmemory allocation.\nLarger values make the collector more aggressive but also increase\nthe size of each incremental step.\nValues smaller than 100 make the collector too slow and\ncan result in the collector never finishing a cycle.\nThe default, 200, means that the collector runs at \"twice\"\nthe speed of memory allocation.\n\n\n<p>\nYou can change these numbers by calling <a href=\"#lua_gc\"><code>lua_gc</code></a> in C\nor <a href=\"#pdf-collectgarbage\"><code>collectgarbage</code></a> in Lua.\nWith these functions you can also control \nthe collector directly (e.g., stop and restart it).\n\n\n\n<h3>2.10.1 - <a name=\"2.10.1\">Garbage-Collection Metamethods</a></h3>\n\n<p>\nUsing the C&nbsp;API,\nyou can set garbage-collector metamethods for userdata (see <a href=\"#2.8\">&sect;2.8</a>).\nThese metamethods are also called <em>finalizers</em>.\nFinalizers allow you to coordinate Lua's garbage collection\nwith external resource management\n(such as closing files, network or database connections,\nor freeing your own memory).\n\n\n<p>\nGarbage userdata with a field <code>__gc</code> in their metatables are not\ncollected immediately by the garbage collector.\nInstead, Lua puts them in a list.\nAfter the collection,\nLua does the equivalent of the following function\nfor each userdata in that list:\n\n<pre>\n     function gc_event (udata)\n       local h = metatable(udata).__gc\n       if h then\n         h(udata)\n       end\n     end\n</pre>\n\n<p>\nAt the end of each garbage-collection cycle,\nthe finalizers for userdata are called in <em>reverse</em>\norder of their creation,\namong those collected in that cycle.\nThat is, the first finalizer to be called is the one associated\nwith the userdata created last in the program.\nThe userdata itself is freed only in the next garbage-collection cycle.\n\n\n\n\n\n<h3>2.10.2 - <a name=\"2.10.2\">Weak Tables</a></h3>\n\n<p>\nA <em>weak table</em> is a table whose elements are\n<em>weak references</em>.\nA weak reference is ignored by the garbage collector.\nIn other words,\nif the only references to an object are weak references,\nthen the garbage collector will collect this object.\n\n\n<p>\nA weak table can have weak keys, weak values, or both.\nA table with weak keys allows the collection of its keys,\nbut prevents the collection of its values.\nA table with both weak keys and weak values allows the collection of\nboth keys and values.\nIn any case, if either the key or the value is collected,\nthe whole pair is removed from the table.\nThe weakness of a table is controlled by the\n<code>__mode</code> field of its metatable.\nIf the <code>__mode</code> field is a string containing the character&nbsp;'<code>k</code>',\nthe keys in the table are weak.\nIf <code>__mode</code> contains '<code>v</code>',\nthe values in the table are weak.\n\n\n<p>\nAfter you use a table as a metatable,\nyou should not change the value of its <code>__mode</code> field.\nOtherwise, the weak behavior of the tables controlled by this\nmetatable is undefined.\n\n\n\n\n\n\n\n<h2>2.11 - <a name=\"2.11\">Coroutines</a></h2>\n\n<p>\nLua supports coroutines,\nalso called <em>collaborative multithreading</em>.\nA coroutine in Lua represents an independent thread of execution.\nUnlike threads in multithread systems, however,\na coroutine only suspends its execution by explicitly calling\na yield function.\n\n\n<p>\nYou create a coroutine with a call to <a href=\"#pdf-coroutine.create\"><code>coroutine.create</code></a>.\nIts sole argument is a function\nthat is the main function of the coroutine.\nThe <code>create</code> function only creates a new coroutine and\nreturns a handle to it (an object of type <em>thread</em>);\nit does not start the coroutine execution.\n\n\n<p>\nWhen you first call <a href=\"#pdf-coroutine.resume\"><code>coroutine.resume</code></a>,\npassing as its first argument\na thread returned by <a href=\"#pdf-coroutine.create\"><code>coroutine.create</code></a>,\nthe coroutine starts its execution,\nat the first line of its main function.\nExtra arguments passed to <a href=\"#pdf-coroutine.resume\"><code>coroutine.resume</code></a> are passed on\nto the coroutine main function.\nAfter the coroutine starts running,\nit runs until it terminates or <em>yields</em>.\n\n\n<p>\nA coroutine can terminate its execution in two ways:\nnormally, when its main function returns\n(explicitly or implicitly, after the last instruction);\nand abnormally, if there is an unprotected error.\nIn the first case, <a href=\"#pdf-coroutine.resume\"><code>coroutine.resume</code></a> returns <b>true</b>,\nplus any values returned by the coroutine main function.\nIn case of errors, <a href=\"#pdf-coroutine.resume\"><code>coroutine.resume</code></a> returns <b>false</b>\nplus an error message.\n\n\n<p>\nA coroutine yields by calling <a href=\"#pdf-coroutine.yield\"><code>coroutine.yield</code></a>.\nWhen a coroutine yields,\nthe corresponding <a href=\"#pdf-coroutine.resume\"><code>coroutine.resume</code></a> returns immediately,\neven if the yield happens inside nested function calls\n(that is, not in the main function,\nbut in a function directly or indirectly called by the main function).\nIn the case of a yield, <a href=\"#pdf-coroutine.resume\"><code>coroutine.resume</code></a> also returns <b>true</b>,\nplus any values passed to <a href=\"#pdf-coroutine.yield\"><code>coroutine.yield</code></a>.\nThe next time you resume the same coroutine,\nit continues its execution from the point where it yielded,\nwith the call to <a href=\"#pdf-coroutine.yield\"><code>coroutine.yield</code></a> returning any extra\narguments passed to <a href=\"#pdf-coroutine.resume\"><code>coroutine.resume</code></a>.\n\n\n<p>\nLike <a href=\"#pdf-coroutine.create\"><code>coroutine.create</code></a>,\nthe <a href=\"#pdf-coroutine.wrap\"><code>coroutine.wrap</code></a> function also creates a coroutine,\nbut instead of returning the coroutine itself,\nit returns a function that, when called, resumes the coroutine.\nAny arguments passed to this function\ngo as extra arguments to <a href=\"#pdf-coroutine.resume\"><code>coroutine.resume</code></a>.\n<a href=\"#pdf-coroutine.wrap\"><code>coroutine.wrap</code></a> returns all the values returned by <a href=\"#pdf-coroutine.resume\"><code>coroutine.resume</code></a>,\nexcept the first one (the boolean error code).\nUnlike <a href=\"#pdf-coroutine.resume\"><code>coroutine.resume</code></a>,\n<a href=\"#pdf-coroutine.wrap\"><code>coroutine.wrap</code></a> does not catch errors;\nany error is propagated to the caller.\n\n\n<p>\nAs an example,\nconsider the following code:\n\n<pre>\n     function foo (a)\n       print(\"foo\", a)\n       return coroutine.yield(2*a)\n     end\n     \n     co = coroutine.create(function (a,b)\n           print(\"co-body\", a, b)\n           local r = foo(a+1)\n           print(\"co-body\", r)\n           local r, s = coroutine.yield(a+b, a-b)\n           print(\"co-body\", r, s)\n           return b, \"end\"\n     end)\n            \n     print(\"main\", coroutine.resume(co, 1, 10))\n     print(\"main\", coroutine.resume(co, \"r\"))\n     print(\"main\", coroutine.resume(co, \"x\", \"y\"))\n     print(\"main\", coroutine.resume(co, \"x\", \"y\"))\n</pre><p>\nWhen you run it, it produces the following output:\n\n<pre>\n     co-body 1       10\n     foo     2\n     \n     main    true    4\n     co-body r\n     main    true    11      -9\n     co-body x       y\n     main    true    10      end\n     main    false   cannot resume dead coroutine\n</pre>\n\n\n\n\n<h1>3 - <a name=\"3\">The Application Program Interface</a></h1>\n\n<p>\n\nThis section describes the C&nbsp;API for Lua, that is,\nthe set of C&nbsp;functions available to the host program to communicate\nwith Lua.\nAll API functions and related types and constants\nare declared in the header file <a name=\"pdf-lua.h\"><code>lua.h</code></a>.\n\n\n<p>\nEven when we use the term \"function\",\nany facility in the API may be provided as a macro instead.\nAll such macros use each of their arguments exactly once\n(except for the first argument, which is always a Lua state),\nand so do not generate any hidden side-effects.\n\n\n<p>\nAs in most C&nbsp;libraries,\nthe Lua API functions do not check their arguments for validity or consistency.\nHowever, you can change this behavior by compiling Lua\nwith a proper definition for the macro <a name=\"pdf-luai_apicheck\"><code>luai_apicheck</code></a>,\nin file <code>luaconf.h</code>.\n\n\n\n<h2>3.1 - <a name=\"3.1\">The Stack</a></h2>\n\n<p>\nLua uses a <em>virtual stack</em> to pass values to and from C.\nEach element in this stack represents a Lua value\n(<b>nil</b>, number, string, etc.).\n\n\n<p>\nWhenever Lua calls C, the called function gets a new stack,\nwhich is independent of previous stacks and of stacks of\nC&nbsp;functions that are still active.\nThis stack initially contains any arguments to the C&nbsp;function\nand it is where the C&nbsp;function pushes its results\nto be returned to the caller (see <a href=\"#lua_CFunction\"><code>lua_CFunction</code></a>).\n\n\n<p>\nFor convenience,\nmost query operations in the API do not follow a strict stack discipline.\nInstead, they can refer to any element in the stack\nby using an <em>index</em>:\nA positive index represents an <em>absolute</em> stack position\n(starting at&nbsp;1);\na negative index represents an <em>offset</em> relative to the top of the stack.\nMore specifically, if the stack has <em>n</em> elements,\nthen index&nbsp;1 represents the first element\n(that is, the element that was pushed onto the stack first)\nand\nindex&nbsp;<em>n</em> represents the last element;\nindex&nbsp;-1 also represents the last element\n(that is, the element at the&nbsp;top)\nand index <em>-n</em> represents the first element.\nWe say that an index is <em>valid</em>\nif it lies between&nbsp;1 and the stack top\n(that is, if <code>1 &le; abs(index) &le; top</code>).\n \n\n\n\n\n\n<h2>3.2 - <a name=\"3.2\">Stack Size</a></h2>\n\n<p>\nWhen you interact with Lua API,\nyou are responsible for ensuring consistency.\nIn particular,\n<em>you are responsible for controlling stack overflow</em>.\nYou can use the function <a href=\"#lua_checkstack\"><code>lua_checkstack</code></a>\nto grow the stack size.\n\n\n<p>\nWhenever Lua calls C,\nit ensures that at least <a name=\"pdf-LUA_MINSTACK\"><code>LUA_MINSTACK</code></a> stack positions are available.\n<code>LUA_MINSTACK</code> is defined as 20,\nso that usually you do not have to worry about stack space\nunless your code has loops pushing elements onto the stack.\n\n\n<p>\nMost query functions accept as indices any value inside the\navailable stack space, that is, indices up to the maximum stack size\nyou have set through <a href=\"#lua_checkstack\"><code>lua_checkstack</code></a>.\nSuch indices are called <em>acceptable indices</em>.\nMore formally, we define an <em>acceptable index</em>\nas follows:\n\n<pre>\n     (index &lt; 0 &amp;&amp; abs(index) &lt;= top) ||\n     (index &gt; 0 &amp;&amp; index &lt;= stackspace)\n</pre><p>\nNote that 0 is never an acceptable index.\n\n\n\n\n\n<h2>3.3 - <a name=\"3.3\">Pseudo-Indices</a></h2>\n\n<p>\nUnless otherwise noted,\nany function that accepts valid indices can also be called with\n<em>pseudo-indices</em>,\nwhich represent some Lua values that are accessible to C&nbsp;code\nbut which are not in the stack.\nPseudo-indices are used to access the thread environment,\nthe function environment,\nthe registry,\nand the upvalues of a C&nbsp;function (see <a href=\"#3.4\">&sect;3.4</a>).\n\n\n<p>\nThe thread environment (where global variables live) is\nalways at pseudo-index <a name=\"pdf-LUA_GLOBALSINDEX\"><code>LUA_GLOBALSINDEX</code></a>.\nThe environment of the running C&nbsp;function is always\nat pseudo-index <a name=\"pdf-LUA_ENVIRONINDEX\"><code>LUA_ENVIRONINDEX</code></a>.\n\n\n<p>\nTo access and change the value of global variables,\nyou can use regular table operations over an environment table.\nFor instance, to access the value of a global variable, do\n\n<pre>\n     lua_getfield(L, LUA_GLOBALSINDEX, varname);\n</pre>\n\n\n\n\n<h2>3.4 - <a name=\"3.4\">C Closures</a></h2>\n\n<p>\nWhen a C&nbsp;function is created,\nit is possible to associate some values with it,\nthus creating a <em>C&nbsp;closure</em>;\nthese values are called <em>upvalues</em> and are\naccessible to the function whenever it is called\n(see <a href=\"#lua_pushcclosure\"><code>lua_pushcclosure</code></a>).\n\n\n<p>\nWhenever a C&nbsp;function is called,\nits upvalues are located at specific pseudo-indices.\nThese pseudo-indices are produced by the macro\n<a name=\"lua_upvalueindex\"><code>lua_upvalueindex</code></a>.\nThe first value associated with a function is at position\n<code>lua_upvalueindex(1)</code>, and so on.\nAny access to <code>lua_upvalueindex(<em>n</em>)</code>,\nwhere <em>n</em> is greater than the number of upvalues of the\ncurrent function (but not greater than 256),\nproduces an acceptable (but invalid) index.\n\n\n\n\n\n<h2>3.5 - <a name=\"3.5\">Registry</a></h2>\n\n<p>\nLua provides a <em>registry</em>,\na pre-defined table that can be used by any C&nbsp;code to\nstore whatever Lua value it needs to store.\nThis table is always located at pseudo-index\n<a name=\"pdf-LUA_REGISTRYINDEX\"><code>LUA_REGISTRYINDEX</code></a>.\nAny C&nbsp;library can store data into this table,\nbut it should take care to choose keys different from those used\nby other libraries, to avoid collisions.\nTypically, you should use as key a string containing your library name\nor a light userdata with the address of a C&nbsp;object in your code.\n\n\n<p>\nThe integer keys in the registry are used by the reference mechanism,\nimplemented by the auxiliary library,\nand therefore should not be used for other purposes.\n\n\n\n\n\n<h2>3.6 - <a name=\"3.6\">Error Handling in C</a></h2>\n\n<p>\nInternally, Lua uses the C <code>longjmp</code> facility to handle errors.\n(You can also choose to use exceptions if you use C++;\nsee file <code>luaconf.h</code>.)\nWhen Lua faces any error\n(such as memory allocation errors, type errors, syntax errors,\nand runtime errors)\nit <em>raises</em> an error;\nthat is, it does a long jump.\nA <em>protected environment</em> uses <code>setjmp</code>\nto set a recover point;\nany error jumps to the most recent active recover point.\n\n\n<p>\nMost functions in the API can throw an error,\nfor instance due to a memory allocation error.\nThe documentation for each function indicates whether\nit can throw errors.\n\n\n<p>\nInside a C&nbsp;function you can throw an error by calling <a href=\"#lua_error\"><code>lua_error</code></a>.\n\n\n\n\n\n<h2>3.7 - <a name=\"3.7\">Functions and Types</a></h2>\n\n<p>\nHere we list all functions and types from the C&nbsp;API in\nalphabetical order.\nEach function has an indicator like this:\n<span class=\"apii\">[-o, +p, <em>x</em>]</span>\n\n\n<p>\nThe first field, <code>o</code>,\nis how many elements the function pops from the stack.\nThe second field, <code>p</code>,\nis how many elements the function pushes onto the stack.\n(Any function always pushes its results after popping its arguments.)\nA field in the form <code>x|y</code> means the function can push (or pop)\n<code>x</code> or <code>y</code> elements,\ndepending on the situation;\nan interrogation mark '<code>?</code>' means that\nwe cannot know how many elements the function pops/pushes\nby looking only at its arguments\n(e.g., they may depend on what is on the stack).\nThe third field, <code>x</code>,\ntells whether the function may throw errors:\n'<code>-</code>' means the function never throws any error;\n'<code>m</code>' means the function may throw an error\nonly due to not enough memory;\n'<code>e</code>' means the function may throw other kinds of errors;\n'<code>v</code>' means the function may throw an error on purpose.\n\n\n\n<hr><h3><a name=\"lua_Alloc\"><code>lua_Alloc</code></a></h3>\n<pre>typedef void * (*lua_Alloc) (void *ud,\n                             void *ptr,\n                             size_t osize,\n                             size_t nsize);</pre>\n\n<p>\nThe type of the memory-allocation function used by Lua states.\nThe allocator function must provide a\nfunctionality similar to <code>realloc</code>,\nbut not exactly the same.\nIts arguments are\n<code>ud</code>, an opaque pointer passed to <a href=\"#lua_newstate\"><code>lua_newstate</code></a>;\n<code>ptr</code>, a pointer to the block being allocated/reallocated/freed;\n<code>osize</code>, the original size of the block;\n<code>nsize</code>, the new size of the block.\n<code>ptr</code> is <code>NULL</code> if and only if <code>osize</code> is zero.\nWhen <code>nsize</code> is zero, the allocator must return <code>NULL</code>;\nif <code>osize</code> is not zero,\nit should free the block pointed to by <code>ptr</code>.\nWhen <code>nsize</code> is not zero, the allocator returns <code>NULL</code>\nif and only if it cannot fill the request.\nWhen <code>nsize</code> is not zero and <code>osize</code> is zero,\nthe allocator should behave like <code>malloc</code>.\nWhen <code>nsize</code> and <code>osize</code> are not zero,\nthe allocator behaves like <code>realloc</code>.\nLua assumes that the allocator never fails when\n<code>osize &gt;= nsize</code>.\n\n\n<p>\nHere is a simple implementation for the allocator function.\nIt is used in the auxiliary library by <a href=\"#luaL_newstate\"><code>luaL_newstate</code></a>.\n\n<pre>\n     static void *l_alloc (void *ud, void *ptr, size_t osize,\n                                                size_t nsize) {\n       (void)ud;  (void)osize;  /* not used */\n       if (nsize == 0) {\n         free(ptr);\n         return NULL;\n       }\n       else\n         return realloc(ptr, nsize);\n     }\n</pre><p>\nThis code assumes\nthat <code>free(NULL)</code> has no effect and that\n<code>realloc(NULL, size)</code> is equivalent to <code>malloc(size)</code>.\nANSI&nbsp;C ensures both behaviors.\n\n\n\n\n\n<hr><h3><a name=\"lua_atpanic\"><code>lua_atpanic</code></a></h3><p>\n<span class=\"apii\">[-0, +0, <em>-</em>]</span>\n<pre>lua_CFunction lua_atpanic (lua_State *L, lua_CFunction panicf);</pre>\n\n<p>\nSets a new panic function and returns the old one.\n\n\n<p>\nIf an error happens outside any protected environment,\nLua calls a <em>panic function</em>\nand then calls <code>exit(EXIT_FAILURE)</code>,\nthus exiting the host application.\nYour panic function can avoid this exit by\nnever returning (e.g., doing a long jump).\n\n\n<p>\nThe panic function can access the error message at the top of the stack.\n\n\n\n\n\n<hr><h3><a name=\"lua_call\"><code>lua_call</code></a></h3><p>\n<span class=\"apii\">[-(nargs + 1), +nresults, <em>e</em>]</span>\n<pre>void lua_call (lua_State *L, int nargs, int nresults);</pre>\n\n<p>\nCalls a function.\n\n\n<p>\nTo call a function you must use the following protocol:\nfirst, the function to be called is pushed onto the stack;\nthen, the arguments to the function are pushed\nin direct order;\nthat is, the first argument is pushed first.\nFinally you call <a href=\"#lua_call\"><code>lua_call</code></a>;\n<code>nargs</code> is the number of arguments that you pushed onto the stack.\nAll arguments and the function value are popped from the stack\nwhen the function is called.\nThe function results are pushed onto the stack when the function returns.\nThe number of results is adjusted to <code>nresults</code>,\nunless <code>nresults</code> is <a name=\"pdf-LUA_MULTRET\"><code>LUA_MULTRET</code></a>.\nIn this case, <em>all</em> results from the function are pushed.\nLua takes care that the returned values fit into the stack space.\nThe function results are pushed onto the stack in direct order\n(the first result is pushed first),\nso that after the call the last result is on the top of the stack.\n\n\n<p>\nAny error inside the called function is propagated upwards\n(with a <code>longjmp</code>).\n\n\n<p>\nThe following example shows how the host program can do the\nequivalent to this Lua code:\n\n<pre>\n     a = f(\"how\", t.x, 14)\n</pre><p>\nHere it is in&nbsp;C:\n\n<pre>\n     lua_getfield(L, LUA_GLOBALSINDEX, \"f\"); /* function to be called */\n     lua_pushstring(L, \"how\");                        /* 1st argument */\n     lua_getfield(L, LUA_GLOBALSINDEX, \"t\");   /* table to be indexed */\n     lua_getfield(L, -1, \"x\");        /* push result of t.x (2nd arg) */\n     lua_remove(L, -2);                  /* remove 't' from the stack */\n     lua_pushinteger(L, 14);                          /* 3rd argument */\n     lua_call(L, 3, 1);     /* call 'f' with 3 arguments and 1 result */\n     lua_setfield(L, LUA_GLOBALSINDEX, \"a\");        /* set global 'a' */\n</pre><p>\nNote that the code above is \"balanced\":\nat its end, the stack is back to its original configuration.\nThis is considered good programming practice.\n\n\n\n\n\n<hr><h3><a name=\"lua_CFunction\"><code>lua_CFunction</code></a></h3>\n<pre>typedef int (*lua_CFunction) (lua_State *L);</pre>\n\n<p>\nType for C&nbsp;functions.\n\n\n<p>\nIn order to communicate properly with Lua,\na C&nbsp;function must use the following protocol,\nwhich defines the way parameters and results are passed:\na C&nbsp;function receives its arguments from Lua in its stack\nin direct order (the first argument is pushed first).\nSo, when the function starts,\n<code>lua_gettop(L)</code> returns the number of arguments received by the function.\nThe first argument (if any) is at index 1\nand its last argument is at index <code>lua_gettop(L)</code>.\nTo return values to Lua, a C&nbsp;function just pushes them onto the stack,\nin direct order (the first result is pushed first),\nand returns the number of results.\nAny other value in the stack below the results will be properly\ndiscarded by Lua.\nLike a Lua function, a C&nbsp;function called by Lua can also return\nmany results.\n\n\n<p>\nAs an example, the following function receives a variable number\nof numerical arguments and returns their average and sum:\n\n<pre>\n     static int foo (lua_State *L) {\n       int n = lua_gettop(L);    /* number of arguments */\n       lua_Number sum = 0;\n       int i;\n       for (i = 1; i &lt;= n; i++) {\n         if (!lua_isnumber(L, i)) {\n           lua_pushstring(L, \"incorrect argument\");\n           lua_error(L);\n         }\n         sum += lua_tonumber(L, i);\n       }\n       lua_pushnumber(L, sum/n);        /* first result */\n       lua_pushnumber(L, sum);         /* second result */\n       return 2;                   /* number of results */\n     }\n</pre>\n\n\n\n\n<hr><h3><a name=\"lua_checkstack\"><code>lua_checkstack</code></a></h3><p>\n<span class=\"apii\">[-0, +0, <em>m</em>]</span>\n<pre>int lua_checkstack (lua_State *L, int extra);</pre>\n\n<p>\nEnsures that there are at least <code>extra</code> free stack slots in the stack.\nIt returns false if it cannot grow the stack to that size.\nThis function never shrinks the stack;\nif the stack is already larger than the new size,\nit is left unchanged.\n\n\n\n\n\n<hr><h3><a name=\"lua_close\"><code>lua_close</code></a></h3><p>\n<span class=\"apii\">[-0, +0, <em>-</em>]</span>\n<pre>void lua_close (lua_State *L);</pre>\n\n<p>\nDestroys all objects in the given Lua state\n(calling the corresponding garbage-collection metamethods, if any)\nand frees all dynamic memory used by this state.\nOn several platforms, you may not need to call this function,\nbecause all resources are naturally released when the host program ends.\nOn the other hand, long-running programs,\nsuch as a daemon or a web server,\nmight need to release states as soon as they are not needed,\nto avoid growing too large.\n\n\n\n\n\n<hr><h3><a name=\"lua_concat\"><code>lua_concat</code></a></h3><p>\n<span class=\"apii\">[-n, +1, <em>e</em>]</span>\n<pre>void lua_concat (lua_State *L, int n);</pre>\n\n<p>\nConcatenates the <code>n</code> values at the top of the stack,\npops them, and leaves the result at the top.\nIf <code>n</code>&nbsp;is&nbsp;1, the result is the single value on the stack\n(that is, the function does nothing);\nif <code>n</code> is 0, the result is the empty string.\nConcatenation is performed following the usual semantics of Lua\n(see <a href=\"#2.5.4\">&sect;2.5.4</a>).\n\n\n\n\n\n<hr><h3><a name=\"lua_cpcall\"><code>lua_cpcall</code></a></h3><p>\n<span class=\"apii\">[-0, +(0|1), <em>-</em>]</span>\n<pre>int lua_cpcall (lua_State *L, lua_CFunction func, void *ud);</pre>\n\n<p>\nCalls the C&nbsp;function <code>func</code> in protected mode.\n<code>func</code> starts with only one element in its stack,\na light userdata containing <code>ud</code>.\nIn case of errors,\n<a href=\"#lua_cpcall\"><code>lua_cpcall</code></a> returns the same error codes as <a href=\"#lua_pcall\"><code>lua_pcall</code></a>,\nplus the error object on the top of the stack;\notherwise, it returns zero, and does not change the stack.\nAll values returned by <code>func</code> are discarded.\n\n\n\n\n\n<hr><h3><a name=\"lua_createtable\"><code>lua_createtable</code></a></h3><p>\n<span class=\"apii\">[-0, +1, <em>m</em>]</span>\n<pre>void lua_createtable (lua_State *L, int narr, int nrec);</pre>\n\n<p>\nCreates a new empty table and pushes it onto the stack.\nThe new table has space pre-allocated\nfor <code>narr</code> array elements and <code>nrec</code> non-array elements.\nThis pre-allocation is useful when you know exactly how many elements\nthe table will have.\nOtherwise you can use the function <a href=\"#lua_newtable\"><code>lua_newtable</code></a>.\n\n\n\n\n\n<hr><h3><a name=\"lua_dump\"><code>lua_dump</code></a></h3><p>\n<span class=\"apii\">[-0, +0, <em>m</em>]</span>\n<pre>int lua_dump (lua_State *L, lua_Writer writer, void *data);</pre>\n\n<p>\nDumps a function as a binary chunk.\nReceives a Lua function on the top of the stack\nand produces a binary chunk that,\nif loaded again,\nresults in a function equivalent to the one dumped.\nAs it produces parts of the chunk,\n<a href=\"#lua_dump\"><code>lua_dump</code></a> calls function <code>writer</code> (see <a href=\"#lua_Writer\"><code>lua_Writer</code></a>)\nwith the given <code>data</code>\nto write them.\n\n\n<p>\nThe value returned is the error code returned by the last\ncall to the writer;\n0&nbsp;means no errors.\n\n\n<p>\nThis function does not pop the Lua function from the stack.\n\n\n\n\n\n<hr><h3><a name=\"lua_equal\"><code>lua_equal</code></a></h3><p>\n<span class=\"apii\">[-0, +0, <em>e</em>]</span>\n<pre>int lua_equal (lua_State *L, int index1, int index2);</pre>\n\n<p>\nReturns 1 if the two values in acceptable indices <code>index1</code> and\n<code>index2</code> are equal,\nfollowing the semantics of the Lua <code>==</code> operator\n(that is, may call metamethods).\nOtherwise returns&nbsp;0.\nAlso returns&nbsp;0 if any of the indices is non valid.\n\n\n\n\n\n<hr><h3><a name=\"lua_error\"><code>lua_error</code></a></h3><p>\n<span class=\"apii\">[-1, +0, <em>v</em>]</span>\n<pre>int lua_error (lua_State *L);</pre>\n\n<p>\nGenerates a Lua error.\nThe error message (which can actually be a Lua value of any type)\nmust be on the stack top.\nThis function does a long jump,\nand therefore never returns.\n(see <a href=\"#luaL_error\"><code>luaL_error</code></a>).\n\n\n\n\n\n<hr><h3><a name=\"lua_gc\"><code>lua_gc</code></a></h3><p>\n<span class=\"apii\">[-0, +0, <em>e</em>]</span>\n<pre>int lua_gc (lua_State *L, int what, int data);</pre>\n\n<p>\nControls the garbage collector.\n\n\n<p>\nThis function performs several tasks,\naccording to the value of the parameter <code>what</code>:\n\n<ul>\n\n<li><b><code>LUA_GCSTOP</code>:</b>\nstops the garbage collector.\n</li>\n\n<li><b><code>LUA_GCRESTART</code>:</b>\nrestarts the garbage collector.\n</li>\n\n<li><b><code>LUA_GCCOLLECT</code>:</b>\nperforms a full garbage-collection cycle.\n</li>\n\n<li><b><code>LUA_GCCOUNT</code>:</b>\nreturns the current amount of memory (in Kbytes) in use by Lua.\n</li>\n\n<li><b><code>LUA_GCCOUNTB</code>:</b>\nreturns the remainder of dividing the current amount of bytes of\nmemory in use by Lua by 1024.\n</li>\n\n<li><b><code>LUA_GCSTEP</code>:</b>\nperforms an incremental step of garbage collection.\nThe step \"size\" is controlled by <code>data</code>\n(larger values mean more steps) in a non-specified way.\nIf you want to control the step size\nyou must experimentally tune the value of <code>data</code>.\nThe function returns 1 if the step finished a\ngarbage-collection cycle.\n</li>\n\n<li><b><code>LUA_GCSETPAUSE</code>:</b>\nsets <code>data</code> as the new value\nfor the <em>pause</em> of the collector (see <a href=\"#2.10\">&sect;2.10</a>).\nThe function returns the previous value of the pause.\n</li>\n\n<li><b><code>LUA_GCSETSTEPMUL</code>:</b>\nsets <code>data</code> as the new value for the <em>step multiplier</em> of\nthe collector (see <a href=\"#2.10\">&sect;2.10</a>).\nThe function returns the previous value of the step multiplier.\n</li>\n\n</ul>\n\n\n\n\n<hr><h3><a name=\"lua_getallocf\"><code>lua_getallocf</code></a></h3><p>\n<span class=\"apii\">[-0, +0, <em>-</em>]</span>\n<pre>lua_Alloc lua_getallocf (lua_State *L, void **ud);</pre>\n\n<p>\nReturns the memory-allocation function of a given state.\nIf <code>ud</code> is not <code>NULL</code>, Lua stores in <code>*ud</code> the\nopaque pointer passed to <a href=\"#lua_newstate\"><code>lua_newstate</code></a>.\n\n\n\n\n\n<hr><h3><a name=\"lua_getfenv\"><code>lua_getfenv</code></a></h3><p>\n<span class=\"apii\">[-0, +1, <em>-</em>]</span>\n<pre>void lua_getfenv (lua_State *L, int index);</pre>\n\n<p>\nPushes onto the stack the environment table of\nthe value at the given index.\n\n\n\n\n\n<hr><h3><a name=\"lua_getfield\"><code>lua_getfield</code></a></h3><p>\n<span class=\"apii\">[-0, +1, <em>e</em>]</span>\n<pre>void lua_getfield (lua_State *L, int index, const char *k);</pre>\n\n<p>\nPushes onto the stack the value <code>t[k]</code>,\nwhere <code>t</code> is the value at the given valid index.\nAs in Lua, this function may trigger a metamethod\nfor the \"index\" event (see <a href=\"#2.8\">&sect;2.8</a>).\n\n\n\n\n\n<hr><h3><a name=\"lua_getglobal\"><code>lua_getglobal</code></a></h3><p>\n<span class=\"apii\">[-0, +1, <em>e</em>]</span>\n<pre>void lua_getglobal (lua_State *L, const char *name);</pre>\n\n<p>\nPushes onto the stack the value of the global <code>name</code>.\nIt is defined as a macro:\n\n<pre>\n     #define lua_getglobal(L,s)  lua_getfield(L, LUA_GLOBALSINDEX, s)\n</pre>\n\n\n\n\n<hr><h3><a name=\"lua_getmetatable\"><code>lua_getmetatable</code></a></h3><p>\n<span class=\"apii\">[-0, +(0|1), <em>-</em>]</span>\n<pre>int lua_getmetatable (lua_State *L, int index);</pre>\n\n<p>\nPushes onto the stack the metatable of the value at the given\nacceptable index.\nIf the index is not valid,\nor if the value does not have a metatable,\nthe function returns&nbsp;0 and pushes nothing on the stack.\n\n\n\n\n\n<hr><h3><a name=\"lua_gettable\"><code>lua_gettable</code></a></h3><p>\n<span class=\"apii\">[-1, +1, <em>e</em>]</span>\n<pre>void lua_gettable (lua_State *L, int index);</pre>\n\n<p>\nPushes onto the stack the value <code>t[k]</code>,\nwhere <code>t</code> is the value at the given valid index\nand <code>k</code> is the value at the top of the stack.\n\n\n<p>\nThis function pops the key from the stack\n(putting the resulting value in its place).\nAs in Lua, this function may trigger a metamethod\nfor the \"index\" event (see <a href=\"#2.8\">&sect;2.8</a>).\n\n\n\n\n\n<hr><h3><a name=\"lua_gettop\"><code>lua_gettop</code></a></h3><p>\n<span class=\"apii\">[-0, +0, <em>-</em>]</span>\n<pre>int lua_gettop (lua_State *L);</pre>\n\n<p>\nReturns the index of the top element in the stack.\nBecause indices start at&nbsp;1,\nthis result is equal to the number of elements in the stack\n(and so 0&nbsp;means an empty stack).\n\n\n\n\n\n<hr><h3><a name=\"lua_insert\"><code>lua_insert</code></a></h3><p>\n<span class=\"apii\">[-1, +1, <em>-</em>]</span>\n<pre>void lua_insert (lua_State *L, int index);</pre>\n\n<p>\nMoves the top element into the given valid index,\nshifting up the elements above this index to open space.\nCannot be called with a pseudo-index,\nbecause a pseudo-index is not an actual stack position.\n\n\n\n\n\n<hr><h3><a name=\"lua_Integer\"><code>lua_Integer</code></a></h3>\n<pre>typedef ptrdiff_t lua_Integer;</pre>\n\n<p>\nThe type used by the Lua API to represent integral values.\n\n\n<p>\nBy default it is a <code>ptrdiff_t</code>,\nwhich is usually the largest signed integral type the machine handles\n\"comfortably\".\n\n\n\n\n\n<hr><h3><a name=\"lua_isboolean\"><code>lua_isboolean</code></a></h3><p>\n<span class=\"apii\">[-0, +0, <em>-</em>]</span>\n<pre>int lua_isboolean (lua_State *L, int index);</pre>\n\n<p>\nReturns 1 if the value at the given acceptable index has type boolean,\nand 0&nbsp;otherwise.\n\n\n\n\n\n<hr><h3><a name=\"lua_iscfunction\"><code>lua_iscfunction</code></a></h3><p>\n<span class=\"apii\">[-0, +0, <em>-</em>]</span>\n<pre>int lua_iscfunction (lua_State *L, int index);</pre>\n\n<p>\nReturns 1 if the value at the given acceptable index is a C&nbsp;function,\nand 0&nbsp;otherwise.\n\n\n\n\n\n<hr><h3><a name=\"lua_isfunction\"><code>lua_isfunction</code></a></h3><p>\n<span class=\"apii\">[-0, +0, <em>-</em>]</span>\n<pre>int lua_isfunction (lua_State *L, int index);</pre>\n\n<p>\nReturns 1 if the value at the given acceptable index is a function\n(either C or Lua), and 0&nbsp;otherwise.\n\n\n\n\n\n<hr><h3><a name=\"lua_islightuserdata\"><code>lua_islightuserdata</code></a></h3><p>\n<span class=\"apii\">[-0, +0, <em>-</em>]</span>\n<pre>int lua_islightuserdata (lua_State *L, int index);</pre>\n\n<p>\nReturns 1 if the value at the given acceptable index is a light userdata,\nand 0&nbsp;otherwise.\n\n\n\n\n\n<hr><h3><a name=\"lua_isnil\"><code>lua_isnil</code></a></h3><p>\n<span class=\"apii\">[-0, +0, <em>-</em>]</span>\n<pre>int lua_isnil (lua_State *L, int index);</pre>\n\n<p>\nReturns 1 if the value at the given acceptable index is <b>nil</b>,\nand 0&nbsp;otherwise.\n\n\n\n\n\n<hr><h3><a name=\"lua_isnone\"><code>lua_isnone</code></a></h3><p>\n<span class=\"apii\">[-0, +0, <em>-</em>]</span>\n<pre>int lua_isnone (lua_State *L, int index);</pre>\n\n<p>\nReturns 1 if the given acceptable index is not valid\n(that is, it refers to an element outside the current stack),\nand 0&nbsp;otherwise.\n\n\n\n\n\n<hr><h3><a name=\"lua_isnoneornil\"><code>lua_isnoneornil</code></a></h3><p>\n<span class=\"apii\">[-0, +0, <em>-</em>]</span>\n<pre>int lua_isnoneornil (lua_State *L, int index);</pre>\n\n<p>\nReturns 1 if the given acceptable index is not valid\n(that is, it refers to an element outside the current stack)\nor if the value at this index is <b>nil</b>,\nand 0&nbsp;otherwise.\n\n\n\n\n\n<hr><h3><a name=\"lua_isnumber\"><code>lua_isnumber</code></a></h3><p>\n<span class=\"apii\">[-0, +0, <em>-</em>]</span>\n<pre>int lua_isnumber (lua_State *L, int index);</pre>\n\n<p>\nReturns 1 if the value at the given acceptable index is a number\nor a string convertible to a number,\nand 0&nbsp;otherwise.\n\n\n\n\n\n<hr><h3><a name=\"lua_isstring\"><code>lua_isstring</code></a></h3><p>\n<span class=\"apii\">[-0, +0, <em>-</em>]</span>\n<pre>int lua_isstring (lua_State *L, int index);</pre>\n\n<p>\nReturns 1 if the value at the given acceptable index is a string\nor a number (which is always convertible to a string),\nand 0&nbsp;otherwise.\n\n\n\n\n\n<hr><h3><a name=\"lua_istable\"><code>lua_istable</code></a></h3><p>\n<span class=\"apii\">[-0, +0, <em>-</em>]</span>\n<pre>int lua_istable (lua_State *L, int index);</pre>\n\n<p>\nReturns 1 if the value at the given acceptable index is a table,\nand 0&nbsp;otherwise.\n\n\n\n\n\n<hr><h3><a name=\"lua_isthread\"><code>lua_isthread</code></a></h3><p>\n<span class=\"apii\">[-0, +0, <em>-</em>]</span>\n<pre>int lua_isthread (lua_State *L, int index);</pre>\n\n<p>\nReturns 1 if the value at the given acceptable index is a thread,\nand 0&nbsp;otherwise.\n\n\n\n\n\n<hr><h3><a name=\"lua_isuserdata\"><code>lua_isuserdata</code></a></h3><p>\n<span class=\"apii\">[-0, +0, <em>-</em>]</span>\n<pre>int lua_isuserdata (lua_State *L, int index);</pre>\n\n<p>\nReturns 1 if the value at the given acceptable index is a userdata\n(either full or light), and 0&nbsp;otherwise.\n\n\n\n\n\n<hr><h3><a name=\"lua_lessthan\"><code>lua_lessthan</code></a></h3><p>\n<span class=\"apii\">[-0, +0, <em>e</em>]</span>\n<pre>int lua_lessthan (lua_State *L, int index1, int index2);</pre>\n\n<p>\nReturns 1 if the value at acceptable index <code>index1</code> is smaller\nthan the value at acceptable index <code>index2</code>,\nfollowing the semantics of the Lua <code>&lt;</code> operator\n(that is, may call metamethods).\nOtherwise returns&nbsp;0.\nAlso returns&nbsp;0 if any of the indices is non valid.\n\n\n\n\n\n<hr><h3><a name=\"lua_load\"><code>lua_load</code></a></h3><p>\n<span class=\"apii\">[-0, +1, <em>-</em>]</span>\n<pre>int lua_load (lua_State *L,\n              lua_Reader reader,\n              void *data,\n              const char *chunkname);</pre>\n\n<p>\nLoads a Lua chunk.\nIf there are no errors,\n<a href=\"#lua_load\"><code>lua_load</code></a> pushes the compiled chunk as a Lua\nfunction on top of the stack.\nOtherwise, it pushes an error message.\nThe return values of <a href=\"#lua_load\"><code>lua_load</code></a> are:\n\n<ul>\n\n<li><b>0:</b> no errors;</li>\n\n<li><b><a name=\"pdf-LUA_ERRSYNTAX\"><code>LUA_ERRSYNTAX</code></a>:</b>\nsyntax error during pre-compilation;</li>\n\n<li><b><a href=\"#pdf-LUA_ERRMEM\"><code>LUA_ERRMEM</code></a>:</b>\nmemory allocation error.</li>\n\n</ul>\n\n<p>\nThis function only loads a chunk;\nit does not run it.\n\n\n<p>\n<a href=\"#lua_load\"><code>lua_load</code></a> automatically detects whether the chunk is text or binary,\nand loads it accordingly (see program <code>luac</code>).\n\n\n<p>\nThe <a href=\"#lua_load\"><code>lua_load</code></a> function uses a user-supplied <code>reader</code> function\nto read the chunk (see <a href=\"#lua_Reader\"><code>lua_Reader</code></a>).\nThe <code>data</code> argument is an opaque value passed to the reader function.\n\n\n<p>\nThe <code>chunkname</code> argument gives a name to the chunk,\nwhich is used for error messages and in debug information (see <a href=\"#3.8\">&sect;3.8</a>).\n\n\n\n\n\n<hr><h3><a name=\"lua_newstate\"><code>lua_newstate</code></a></h3><p>\n<span class=\"apii\">[-0, +0, <em>-</em>]</span>\n<pre>lua_State *lua_newstate (lua_Alloc f, void *ud);</pre>\n\n<p>\nCreates a new, independent state.\nReturns <code>NULL</code> if cannot create the state\n(due to lack of memory).\nThe argument <code>f</code> is the allocator function;\nLua does all memory allocation for this state through this function.\nThe second argument, <code>ud</code>, is an opaque pointer that Lua\nsimply passes to the allocator in every call.\n\n\n\n\n\n<hr><h3><a name=\"lua_newtable\"><code>lua_newtable</code></a></h3><p>\n<span class=\"apii\">[-0, +1, <em>m</em>]</span>\n<pre>void lua_newtable (lua_State *L);</pre>\n\n<p>\nCreates a new empty table and pushes it onto the stack.\nIt is equivalent to <code>lua_createtable(L, 0, 0)</code>.\n\n\n\n\n\n<hr><h3><a name=\"lua_newthread\"><code>lua_newthread</code></a></h3><p>\n<span class=\"apii\">[-0, +1, <em>m</em>]</span>\n<pre>lua_State *lua_newthread (lua_State *L);</pre>\n\n<p>\nCreates a new thread, pushes it on the stack,\nand returns a pointer to a <a href=\"#lua_State\"><code>lua_State</code></a> that represents this new thread.\nThe new state returned by this function shares with the original state\nall global objects (such as tables),\nbut has an independent execution stack.\n\n\n<p>\nThere is no explicit function to close or to destroy a thread.\nThreads are subject to garbage collection,\nlike any Lua object.\n\n\n\n\n\n<hr><h3><a name=\"lua_newuserdata\"><code>lua_newuserdata</code></a></h3><p>\n<span class=\"apii\">[-0, +1, <em>m</em>]</span>\n<pre>void *lua_newuserdata (lua_State *L, size_t size);</pre>\n\n<p>\nThis function allocates a new block of memory with the given size,\npushes onto the stack a new full userdata with the block address,\nand returns this address.\n\n\n<p>\nUserdata represent C&nbsp;values in Lua.\nA <em>full userdata</em> represents a block of memory.\nIt is an object (like a table):\nyou must create it, it can have its own metatable,\nand you can detect when it is being collected.\nA full userdata is only equal to itself (under raw equality).\n\n\n<p>\nWhen Lua collects a full userdata with a <code>gc</code> metamethod,\nLua calls the metamethod and marks the userdata as finalized.\nWhen this userdata is collected again then\nLua frees its corresponding memory.\n\n\n\n\n\n<hr><h3><a name=\"lua_next\"><code>lua_next</code></a></h3><p>\n<span class=\"apii\">[-1, +(2|0), <em>e</em>]</span>\n<pre>int lua_next (lua_State *L, int index);</pre>\n\n<p>\nPops a key from the stack,\nand pushes a key-value pair from the table at the given index\n(the \"next\" pair after the given key).\nIf there are no more elements in the table,\nthen <a href=\"#lua_next\"><code>lua_next</code></a> returns 0 (and pushes nothing).\n\n\n<p>\nA typical traversal looks like this:\n\n<pre>\n     /* table is in the stack at index 't' */\n     lua_pushnil(L);  /* first key */\n     while (lua_next(L, t) != 0) {\n       /* uses 'key' (at index -2) and 'value' (at index -1) */\n       printf(\"%s - %s\\n\",\n              lua_typename(L, lua_type(L, -2)),\n              lua_typename(L, lua_type(L, -1)));\n       /* removes 'value'; keeps 'key' for next iteration */\n       lua_pop(L, 1);\n     }\n</pre>\n\n<p>\nWhile traversing a table,\ndo not call <a href=\"#lua_tolstring\"><code>lua_tolstring</code></a> directly on a key,\nunless you know that the key is actually a string.\nRecall that <a href=\"#lua_tolstring\"><code>lua_tolstring</code></a> <em>changes</em>\nthe value at the given index;\nthis confuses the next call to <a href=\"#lua_next\"><code>lua_next</code></a>.\n\n\n\n\n\n<hr><h3><a name=\"lua_Number\"><code>lua_Number</code></a></h3>\n<pre>typedef double lua_Number;</pre>\n\n<p>\nThe type of numbers in Lua.\nBy default, it is double, but that can be changed in <code>luaconf.h</code>.\n\n\n<p>\nThrough the configuration file you can change\nLua to operate with another type for numbers (e.g., float or long).\n\n\n\n\n\n<hr><h3><a name=\"lua_objlen\"><code>lua_objlen</code></a></h3><p>\n<span class=\"apii\">[-0, +0, <em>-</em>]</span>\n<pre>size_t lua_objlen (lua_State *L, int index);</pre>\n\n<p>\nReturns the \"length\" of the value at the given acceptable index:\nfor strings, this is the string length;\nfor tables, this is the result of the length operator ('<code>#</code>');\nfor userdata, this is the size of the block of memory allocated\nfor the userdata;\nfor other values, it is&nbsp;0.\n\n\n\n\n\n<hr><h3><a name=\"lua_pcall\"><code>lua_pcall</code></a></h3><p>\n<span class=\"apii\">[-(nargs + 1), +(nresults|1), <em>-</em>]</span>\n<pre>int lua_pcall (lua_State *L, int nargs, int nresults, int errfunc);</pre>\n\n<p>\nCalls a function in protected mode.\n\n\n<p>\nBoth <code>nargs</code> and <code>nresults</code> have the same meaning as\nin <a href=\"#lua_call\"><code>lua_call</code></a>.\nIf there are no errors during the call,\n<a href=\"#lua_pcall\"><code>lua_pcall</code></a> behaves exactly like <a href=\"#lua_call\"><code>lua_call</code></a>.\nHowever, if there is any error,\n<a href=\"#lua_pcall\"><code>lua_pcall</code></a> catches it,\npushes a single value on the stack (the error message),\nand returns an error code.\nLike <a href=\"#lua_call\"><code>lua_call</code></a>,\n<a href=\"#lua_pcall\"><code>lua_pcall</code></a> always removes the function\nand its arguments from the stack.\n\n\n<p>\nIf <code>errfunc</code> is 0,\nthen the error message returned on the stack\nis exactly the original error message.\nOtherwise, <code>errfunc</code> is the stack index of an\n<em>error handler function</em>.\n(In the current implementation, this index cannot be a pseudo-index.)\nIn case of runtime errors,\nthis function will be called with the error message\nand its return value will be the message returned on the stack by <a href=\"#lua_pcall\"><code>lua_pcall</code></a>.\n\n\n<p>\nTypically, the error handler function is used to add more debug\ninformation to the error message, such as a stack traceback.\nSuch information cannot be gathered after the return of <a href=\"#lua_pcall\"><code>lua_pcall</code></a>,\nsince by then the stack has unwound.\n\n\n<p>\nThe <a href=\"#lua_pcall\"><code>lua_pcall</code></a> function returns 0 in case of success\nor one of the following error codes\n(defined in <code>lua.h</code>):\n\n<ul>\n\n<li><b><a name=\"pdf-LUA_ERRRUN\"><code>LUA_ERRRUN</code></a>:</b>\na runtime error.\n</li>\n\n<li><b><a name=\"pdf-LUA_ERRMEM\"><code>LUA_ERRMEM</code></a>:</b>\nmemory allocation error.\nFor such errors, Lua does not call the error handler function.\n</li>\n\n<li><b><a name=\"pdf-LUA_ERRERR\"><code>LUA_ERRERR</code></a>:</b>\nerror while running the error handler function.\n</li>\n\n</ul>\n\n\n\n\n<hr><h3><a name=\"lua_pop\"><code>lua_pop</code></a></h3><p>\n<span class=\"apii\">[-n, +0, <em>-</em>]</span>\n<pre>void lua_pop (lua_State *L, int n);</pre>\n\n<p>\nPops <code>n</code> elements from the stack.\n\n\n\n\n\n<hr><h3><a name=\"lua_pushboolean\"><code>lua_pushboolean</code></a></h3><p>\n<span class=\"apii\">[-0, +1, <em>-</em>]</span>\n<pre>void lua_pushboolean (lua_State *L, int b);</pre>\n\n<p>\nPushes a boolean value with value <code>b</code> onto the stack.\n\n\n\n\n\n<hr><h3><a name=\"lua_pushcclosure\"><code>lua_pushcclosure</code></a></h3><p>\n<span class=\"apii\">[-n, +1, <em>m</em>]</span>\n<pre>void lua_pushcclosure (lua_State *L, lua_CFunction fn, int n);</pre>\n\n<p>\nPushes a new C&nbsp;closure onto the stack.\n\n\n<p>\nWhen a C&nbsp;function is created,\nit is possible to associate some values with it,\nthus creating a C&nbsp;closure (see <a href=\"#3.4\">&sect;3.4</a>);\nthese values are then accessible to the function whenever it is called.\nTo associate values with a C&nbsp;function,\nfirst these values should be pushed onto the stack\n(when there are multiple values, the first value is pushed first).\nThen <a href=\"#lua_pushcclosure\"><code>lua_pushcclosure</code></a>\nis called to create and push the C&nbsp;function onto the stack,\nwith the argument <code>n</code> telling how many values should be\nassociated with the function.\n<a href=\"#lua_pushcclosure\"><code>lua_pushcclosure</code></a> also pops these values from the stack.\n\n\n<p>\nThe maximum value for <code>n</code> is 255.\n\n\n\n\n\n<hr><h3><a name=\"lua_pushcfunction\"><code>lua_pushcfunction</code></a></h3><p>\n<span class=\"apii\">[-0, +1, <em>m</em>]</span>\n<pre>void lua_pushcfunction (lua_State *L, lua_CFunction f);</pre>\n\n<p>\nPushes a C&nbsp;function onto the stack.\nThis function receives a pointer to a C function\nand pushes onto the stack a Lua value of type <code>function</code> that,\nwhen called, invokes the corresponding C&nbsp;function.\n\n\n<p>\nAny function to be registered in Lua must\nfollow the correct protocol to receive its parameters\nand return its results (see <a href=\"#lua_CFunction\"><code>lua_CFunction</code></a>).\n\n\n<p>\n<code>lua_pushcfunction</code> is defined as a macro:\n\n<pre>\n     #define lua_pushcfunction(L,f)  lua_pushcclosure(L,f,0)\n</pre>\n\n\n\n\n<hr><h3><a name=\"lua_pushfstring\"><code>lua_pushfstring</code></a></h3><p>\n<span class=\"apii\">[-0, +1, <em>m</em>]</span>\n<pre>const char *lua_pushfstring (lua_State *L, const char *fmt, ...);</pre>\n\n<p>\nPushes onto the stack a formatted string\nand returns a pointer to this string.\nIt is similar to the C&nbsp;function <code>sprintf</code>,\nbut has some important differences:\n\n<ul>\n\n<li>\nYou do not have to allocate space for the result:\nthe result is a Lua string and Lua takes care of memory allocation\n(and deallocation, through garbage collection).\n</li>\n\n<li>\nThe conversion specifiers are quite restricted.\nThere are no flags, widths, or precisions.\nThe conversion specifiers can only be\n'<code>%%</code>' (inserts a '<code>%</code>' in the string),\n'<code>%s</code>' (inserts a zero-terminated string, with no size restrictions),\n'<code>%f</code>' (inserts a <a href=\"#lua_Number\"><code>lua_Number</code></a>),\n'<code>%p</code>' (inserts a pointer as a hexadecimal numeral),\n'<code>%d</code>' (inserts an <code>int</code>), and\n'<code>%c</code>' (inserts an <code>int</code> as a character).\n</li>\n\n</ul>\n\n\n\n\n<hr><h3><a name=\"lua_pushinteger\"><code>lua_pushinteger</code></a></h3><p>\n<span class=\"apii\">[-0, +1, <em>-</em>]</span>\n<pre>void lua_pushinteger (lua_State *L, lua_Integer n);</pre>\n\n<p>\nPushes a number with value <code>n</code> onto the stack.\n\n\n\n\n\n<hr><h3><a name=\"lua_pushlightuserdata\"><code>lua_pushlightuserdata</code></a></h3><p>\n<span class=\"apii\">[-0, +1, <em>-</em>]</span>\n<pre>void lua_pushlightuserdata (lua_State *L, void *p);</pre>\n\n<p>\nPushes a light userdata onto the stack.\n\n\n<p>\nUserdata represent C&nbsp;values in Lua.\nA <em>light userdata</em> represents a pointer.\nIt is a value (like a number):\nyou do not create it, it has no individual metatable,\nand it is not collected (as it was never created).\nA light userdata is equal to \"any\"\nlight userdata with the same C&nbsp;address.\n\n\n\n\n\n<hr><h3><a name=\"lua_pushliteral\"><code>lua_pushliteral</code></a></h3><p>\n<span class=\"apii\">[-0, +1, <em>m</em>]</span>\n<pre>void lua_pushliteral (lua_State *L, const char *s);</pre>\n\n<p>\nThis macro is equivalent to <a href=\"#lua_pushlstring\"><code>lua_pushlstring</code></a>,\nbut can be used only when <code>s</code> is a literal string.\nIn these cases, it automatically provides the string length.\n\n\n\n\n\n<hr><h3><a name=\"lua_pushlstring\"><code>lua_pushlstring</code></a></h3><p>\n<span class=\"apii\">[-0, +1, <em>m</em>]</span>\n<pre>void lua_pushlstring (lua_State *L, const char *s, size_t len);</pre>\n\n<p>\nPushes the string pointed to by <code>s</code> with size <code>len</code>\nonto the stack.\nLua makes (or reuses) an internal copy of the given string,\nso the memory at <code>s</code> can be freed or reused immediately after\nthe function returns.\nThe string can contain embedded zeros.\n\n\n\n\n\n<hr><h3><a name=\"lua_pushnil\"><code>lua_pushnil</code></a></h3><p>\n<span class=\"apii\">[-0, +1, <em>-</em>]</span>\n<pre>void lua_pushnil (lua_State *L);</pre>\n\n<p>\nPushes a nil value onto the stack.\n\n\n\n\n\n<hr><h3><a name=\"lua_pushnumber\"><code>lua_pushnumber</code></a></h3><p>\n<span class=\"apii\">[-0, +1, <em>-</em>]</span>\n<pre>void lua_pushnumber (lua_State *L, lua_Number n);</pre>\n\n<p>\nPushes a number with value <code>n</code> onto the stack.\n\n\n\n\n\n<hr><h3><a name=\"lua_pushstring\"><code>lua_pushstring</code></a></h3><p>\n<span class=\"apii\">[-0, +1, <em>m</em>]</span>\n<pre>void lua_pushstring (lua_State *L, const char *s);</pre>\n\n<p>\nPushes the zero-terminated string pointed to by <code>s</code>\nonto the stack.\nLua makes (or reuses) an internal copy of the given string,\nso the memory at <code>s</code> can be freed or reused immediately after\nthe function returns.\nThe string cannot contain embedded zeros;\nit is assumed to end at the first zero.\n\n\n\n\n\n<hr><h3><a name=\"lua_pushthread\"><code>lua_pushthread</code></a></h3><p>\n<span class=\"apii\">[-0, +1, <em>-</em>]</span>\n<pre>int lua_pushthread (lua_State *L);</pre>\n\n<p>\nPushes the thread represented by <code>L</code> onto the stack.\nReturns 1 if this thread is the main thread of its state.\n\n\n\n\n\n<hr><h3><a name=\"lua_pushvalue\"><code>lua_pushvalue</code></a></h3><p>\n<span class=\"apii\">[-0, +1, <em>-</em>]</span>\n<pre>void lua_pushvalue (lua_State *L, int index);</pre>\n\n<p>\nPushes a copy of the element at the given valid index\nonto the stack.\n\n\n\n\n\n<hr><h3><a name=\"lua_pushvfstring\"><code>lua_pushvfstring</code></a></h3><p>\n<span class=\"apii\">[-0, +1, <em>m</em>]</span>\n<pre>const char *lua_pushvfstring (lua_State *L,\n                              const char *fmt,\n                              va_list argp);</pre>\n\n<p>\nEquivalent to <a href=\"#lua_pushfstring\"><code>lua_pushfstring</code></a>, except that it receives a <code>va_list</code>\ninstead of a variable number of arguments.\n\n\n\n\n\n<hr><h3><a name=\"lua_rawequal\"><code>lua_rawequal</code></a></h3><p>\n<span class=\"apii\">[-0, +0, <em>-</em>]</span>\n<pre>int lua_rawequal (lua_State *L, int index1, int index2);</pre>\n\n<p>\nReturns 1 if the two values in acceptable indices <code>index1</code> and\n<code>index2</code> are primitively equal\n(that is, without calling metamethods).\nOtherwise returns&nbsp;0.\nAlso returns&nbsp;0 if any of the indices are non valid.\n\n\n\n\n\n<hr><h3><a name=\"lua_rawget\"><code>lua_rawget</code></a></h3><p>\n<span class=\"apii\">[-1, +1, <em>-</em>]</span>\n<pre>void lua_rawget (lua_State *L, int index);</pre>\n\n<p>\nSimilar to <a href=\"#lua_gettable\"><code>lua_gettable</code></a>, but does a raw access\n(i.e., without metamethods).\n\n\n\n\n\n<hr><h3><a name=\"lua_rawgeti\"><code>lua_rawgeti</code></a></h3><p>\n<span class=\"apii\">[-0, +1, <em>-</em>]</span>\n<pre>void lua_rawgeti (lua_State *L, int index, int n);</pre>\n\n<p>\nPushes onto the stack the value <code>t[n]</code>,\nwhere <code>t</code> is the value at the given valid index.\nThe access is raw;\nthat is, it does not invoke metamethods.\n\n\n\n\n\n<hr><h3><a name=\"lua_rawset\"><code>lua_rawset</code></a></h3><p>\n<span class=\"apii\">[-2, +0, <em>m</em>]</span>\n<pre>void lua_rawset (lua_State *L, int index);</pre>\n\n<p>\nSimilar to <a href=\"#lua_settable\"><code>lua_settable</code></a>, but does a raw assignment\n(i.e., without metamethods).\n\n\n\n\n\n<hr><h3><a name=\"lua_rawseti\"><code>lua_rawseti</code></a></h3><p>\n<span class=\"apii\">[-1, +0, <em>m</em>]</span>\n<pre>void lua_rawseti (lua_State *L, int index, int n);</pre>\n\n<p>\nDoes the equivalent of <code>t[n] = v</code>,\nwhere <code>t</code> is the value at the given valid index\nand <code>v</code> is the value at the top of the stack.\n\n\n<p>\nThis function pops the value from the stack.\nThe assignment is raw;\nthat is, it does not invoke metamethods.\n\n\n\n\n\n<hr><h3><a name=\"lua_Reader\"><code>lua_Reader</code></a></h3>\n<pre>typedef const char * (*lua_Reader) (lua_State *L,\n                                    void *data,\n                                    size_t *size);</pre>\n\n<p>\nThe reader function used by <a href=\"#lua_load\"><code>lua_load</code></a>.\nEvery time it needs another piece of the chunk,\n<a href=\"#lua_load\"><code>lua_load</code></a> calls the reader,\npassing along its <code>data</code> parameter.\nThe reader must return a pointer to a block of memory\nwith a new piece of the chunk\nand set <code>size</code> to the block size.\nThe block must exist until the reader function is called again.\nTo signal the end of the chunk,\nthe reader must return <code>NULL</code> or set <code>size</code> to zero.\nThe reader function may return pieces of any size greater than zero.\n\n\n\n\n\n<hr><h3><a name=\"lua_register\"><code>lua_register</code></a></h3><p>\n<span class=\"apii\">[-0, +0, <em>e</em>]</span>\n<pre>void lua_register (lua_State *L,\n                   const char *name,\n                   lua_CFunction f);</pre>\n\n<p>\nSets the C function <code>f</code> as the new value of global <code>name</code>.\nIt is defined as a macro:\n\n<pre>\n     #define lua_register(L,n,f) \\\n            (lua_pushcfunction(L, f), lua_setglobal(L, n))\n</pre>\n\n\n\n\n<hr><h3><a name=\"lua_remove\"><code>lua_remove</code></a></h3><p>\n<span class=\"apii\">[-1, +0, <em>-</em>]</span>\n<pre>void lua_remove (lua_State *L, int index);</pre>\n\n<p>\nRemoves the element at the given valid index,\nshifting down the elements above this index to fill the gap.\nCannot be called with a pseudo-index,\nbecause a pseudo-index is not an actual stack position.\n\n\n\n\n\n<hr><h3><a name=\"lua_replace\"><code>lua_replace</code></a></h3><p>\n<span class=\"apii\">[-1, +0, <em>-</em>]</span>\n<pre>void lua_replace (lua_State *L, int index);</pre>\n\n<p>\nMoves the top element into the given position (and pops it),\nwithout shifting any element\n(therefore replacing the value at the given position).\n\n\n\n\n\n<hr><h3><a name=\"lua_resume\"><code>lua_resume</code></a></h3><p>\n<span class=\"apii\">[-?, +?, <em>-</em>]</span>\n<pre>int lua_resume (lua_State *L, int narg);</pre>\n\n<p>\nStarts and resumes a coroutine in a given thread.\n\n\n<p>\nTo start a coroutine, you first create a new thread\n(see <a href=\"#lua_newthread\"><code>lua_newthread</code></a>);\nthen you push onto its stack the main function plus any arguments;\nthen you call <a href=\"#lua_resume\"><code>lua_resume</code></a>,\nwith <code>narg</code> being the number of arguments.\nThis call returns when the coroutine suspends or finishes its execution.\nWhen it returns, the stack contains all values passed to <a href=\"#lua_yield\"><code>lua_yield</code></a>,\nor all values returned by the body function.\n<a href=\"#lua_resume\"><code>lua_resume</code></a> returns\n<a href=\"#pdf-LUA_YIELD\"><code>LUA_YIELD</code></a> if the coroutine yields,\n0 if the coroutine finishes its execution\nwithout errors,\nor an error code in case of errors (see <a href=\"#lua_pcall\"><code>lua_pcall</code></a>).\nIn case of errors,\nthe stack is not unwound,\nso you can use the debug API over it.\nThe error message is on the top of the stack.\nTo restart a coroutine, you put on its stack only the values to\nbe passed as results from <code>yield</code>,\nand then call <a href=\"#lua_resume\"><code>lua_resume</code></a>.\n\n\n\n\n\n<hr><h3><a name=\"lua_setallocf\"><code>lua_setallocf</code></a></h3><p>\n<span class=\"apii\">[-0, +0, <em>-</em>]</span>\n<pre>void lua_setallocf (lua_State *L, lua_Alloc f, void *ud);</pre>\n\n<p>\nChanges the allocator function of a given state to <code>f</code>\nwith user data <code>ud</code>.\n\n\n\n\n\n<hr><h3><a name=\"lua_setfenv\"><code>lua_setfenv</code></a></h3><p>\n<span class=\"apii\">[-1, +0, <em>-</em>]</span>\n<pre>int lua_setfenv (lua_State *L, int index);</pre>\n\n<p>\nPops a table from the stack and sets it as\nthe new environment for the value at the given index.\nIf the value at the given index is\nneither a function nor a thread nor a userdata,\n<a href=\"#lua_setfenv\"><code>lua_setfenv</code></a> returns 0.\nOtherwise it returns 1.\n\n\n\n\n\n<hr><h3><a name=\"lua_setfield\"><code>lua_setfield</code></a></h3><p>\n<span class=\"apii\">[-1, +0, <em>e</em>]</span>\n<pre>void lua_setfield (lua_State *L, int index, const char *k);</pre>\n\n<p>\nDoes the equivalent to <code>t[k] = v</code>,\nwhere <code>t</code> is the value at the given valid index\nand <code>v</code> is the value at the top of the stack.\n\n\n<p>\nThis function pops the value from the stack.\nAs in Lua, this function may trigger a metamethod\nfor the \"newindex\" event (see <a href=\"#2.8\">&sect;2.8</a>).\n\n\n\n\n\n<hr><h3><a name=\"lua_setglobal\"><code>lua_setglobal</code></a></h3><p>\n<span class=\"apii\">[-1, +0, <em>e</em>]</span>\n<pre>void lua_setglobal (lua_State *L, const char *name);</pre>\n\n<p>\nPops a value from the stack and\nsets it as the new value of global <code>name</code>.\nIt is defined as a macro:\n\n<pre>\n     #define lua_setglobal(L,s)   lua_setfield(L, LUA_GLOBALSINDEX, s)\n</pre>\n\n\n\n\n<hr><h3><a name=\"lua_setmetatable\"><code>lua_setmetatable</code></a></h3><p>\n<span class=\"apii\">[-1, +0, <em>-</em>]</span>\n<pre>int lua_setmetatable (lua_State *L, int index);</pre>\n\n<p>\nPops a table from the stack and\nsets it as the new metatable for the value at the given\nacceptable index.\n\n\n\n\n\n<hr><h3><a name=\"lua_settable\"><code>lua_settable</code></a></h3><p>\n<span class=\"apii\">[-2, +0, <em>e</em>]</span>\n<pre>void lua_settable (lua_State *L, int index);</pre>\n\n<p>\nDoes the equivalent to <code>t[k] = v</code>,\nwhere <code>t</code> is the value at the given valid index,\n<code>v</code> is the value at the top of the stack,\nand <code>k</code> is the value just below the top.\n\n\n<p>\nThis function pops both the key and the value from the stack.\nAs in Lua, this function may trigger a metamethod\nfor the \"newindex\" event (see <a href=\"#2.8\">&sect;2.8</a>).\n\n\n\n\n\n<hr><h3><a name=\"lua_settop\"><code>lua_settop</code></a></h3><p>\n<span class=\"apii\">[-?, +?, <em>-</em>]</span>\n<pre>void lua_settop (lua_State *L, int index);</pre>\n\n<p>\nAccepts any acceptable index, or&nbsp;0,\nand sets the stack top to this index.\nIf the new top is larger than the old one,\nthen the new elements are filled with <b>nil</b>.\nIf <code>index</code> is&nbsp;0, then all stack elements are removed.\n\n\n\n\n\n<hr><h3><a name=\"lua_State\"><code>lua_State</code></a></h3>\n<pre>typedef struct lua_State lua_State;</pre>\n\n<p>\nOpaque structure that keeps the whole state of a Lua interpreter.\nThe Lua library is fully reentrant:\nit has no global variables.\nAll information about a state is kept in this structure.\n\n\n<p>\nA pointer to this state must be passed as the first argument to\nevery function in the library, except to <a href=\"#lua_newstate\"><code>lua_newstate</code></a>,\nwhich creates a Lua state from scratch.\n\n\n\n\n\n<hr><h3><a name=\"lua_status\"><code>lua_status</code></a></h3><p>\n<span class=\"apii\">[-0, +0, <em>-</em>]</span>\n<pre>int lua_status (lua_State *L);</pre>\n\n<p>\nReturns the status of the thread <code>L</code>.\n\n\n<p>\nThe status can be 0 for a normal thread,\nan error code if the thread finished its execution with an error,\nor <a name=\"pdf-LUA_YIELD\"><code>LUA_YIELD</code></a> if the thread is suspended.\n\n\n\n\n\n<hr><h3><a name=\"lua_toboolean\"><code>lua_toboolean</code></a></h3><p>\n<span class=\"apii\">[-0, +0, <em>-</em>]</span>\n<pre>int lua_toboolean (lua_State *L, int index);</pre>\n\n<p>\nConverts the Lua value at the given acceptable index to a C&nbsp;boolean\nvalue (0&nbsp;or&nbsp;1).\nLike all tests in Lua,\n<a href=\"#lua_toboolean\"><code>lua_toboolean</code></a> returns 1 for any Lua value\ndifferent from <b>false</b> and <b>nil</b>;\notherwise it returns 0.\nIt also returns 0 when called with a non-valid index.\n(If you want to accept only actual boolean values,\nuse <a href=\"#lua_isboolean\"><code>lua_isboolean</code></a> to test the value's type.)\n\n\n\n\n\n<hr><h3><a name=\"lua_tocfunction\"><code>lua_tocfunction</code></a></h3><p>\n<span class=\"apii\">[-0, +0, <em>-</em>]</span>\n<pre>lua_CFunction lua_tocfunction (lua_State *L, int index);</pre>\n\n<p>\nConverts a value at the given acceptable index to a C&nbsp;function.\nThat value must be a C&nbsp;function;\notherwise, returns <code>NULL</code>.\n\n\n\n\n\n<hr><h3><a name=\"lua_tointeger\"><code>lua_tointeger</code></a></h3><p>\n<span class=\"apii\">[-0, +0, <em>-</em>]</span>\n<pre>lua_Integer lua_tointeger (lua_State *L, int index);</pre>\n\n<p>\nConverts the Lua value at the given acceptable index\nto the signed integral type <a href=\"#lua_Integer\"><code>lua_Integer</code></a>.\nThe Lua value must be a number or a string convertible to a number\n(see <a href=\"#2.2.1\">&sect;2.2.1</a>);\notherwise, <a href=\"#lua_tointeger\"><code>lua_tointeger</code></a> returns&nbsp;0.\n\n\n<p>\nIf the number is not an integer,\nit is truncated in some non-specified way.\n\n\n\n\n\n<hr><h3><a name=\"lua_tolstring\"><code>lua_tolstring</code></a></h3><p>\n<span class=\"apii\">[-0, +0, <em>m</em>]</span>\n<pre>const char *lua_tolstring (lua_State *L, int index, size_t *len);</pre>\n\n<p>\nConverts the Lua value at the given acceptable index to a C&nbsp;string.\nIf <code>len</code> is not <code>NULL</code>,\nit also sets <code>*len</code> with the string length.\nThe Lua value must be a string or a number;\notherwise, the function returns <code>NULL</code>.\nIf the value is a number,\nthen <a href=\"#lua_tolstring\"><code>lua_tolstring</code></a> also\n<em>changes the actual value in the stack to a string</em>.\n(This change confuses <a href=\"#lua_next\"><code>lua_next</code></a>\nwhen <a href=\"#lua_tolstring\"><code>lua_tolstring</code></a> is applied to keys during a table traversal.)\n\n\n<p>\n<a href=\"#lua_tolstring\"><code>lua_tolstring</code></a> returns a fully aligned pointer\nto a string inside the Lua state.\nThis string always has a zero ('<code>\\0</code>')\nafter its last character (as in&nbsp;C),\nbut can contain other zeros in its body.\nBecause Lua has garbage collection,\nthere is no guarantee that the pointer returned by <a href=\"#lua_tolstring\"><code>lua_tolstring</code></a>\nwill be valid after the corresponding value is removed from the stack.\n\n\n\n\n\n<hr><h3><a name=\"lua_tonumber\"><code>lua_tonumber</code></a></h3><p>\n<span class=\"apii\">[-0, +0, <em>-</em>]</span>\n<pre>lua_Number lua_tonumber (lua_State *L, int index);</pre>\n\n<p>\nConverts the Lua value at the given acceptable index\nto the C&nbsp;type <a href=\"#lua_Number\"><code>lua_Number</code></a> (see <a href=\"#lua_Number\"><code>lua_Number</code></a>).\nThe Lua value must be a number or a string convertible to a number\n(see <a href=\"#2.2.1\">&sect;2.2.1</a>);\notherwise, <a href=\"#lua_tonumber\"><code>lua_tonumber</code></a> returns&nbsp;0.\n\n\n\n\n\n<hr><h3><a name=\"lua_topointer\"><code>lua_topointer</code></a></h3><p>\n<span class=\"apii\">[-0, +0, <em>-</em>]</span>\n<pre>const void *lua_topointer (lua_State *L, int index);</pre>\n\n<p>\nConverts the value at the given acceptable index to a generic\nC&nbsp;pointer (<code>void*</code>).\nThe value can be a userdata, a table, a thread, or a function;\notherwise, <a href=\"#lua_topointer\"><code>lua_topointer</code></a> returns <code>NULL</code>.\nDifferent objects will give different pointers.\nThere is no way to convert the pointer back to its original value.\n\n\n<p>\nTypically this function is used only for debug information.\n\n\n\n\n\n<hr><h3><a name=\"lua_tostring\"><code>lua_tostring</code></a></h3><p>\n<span class=\"apii\">[-0, +0, <em>m</em>]</span>\n<pre>const char *lua_tostring (lua_State *L, int index);</pre>\n\n<p>\nEquivalent to <a href=\"#lua_tolstring\"><code>lua_tolstring</code></a> with <code>len</code> equal to <code>NULL</code>.\n\n\n\n\n\n<hr><h3><a name=\"lua_tothread\"><code>lua_tothread</code></a></h3><p>\n<span class=\"apii\">[-0, +0, <em>-</em>]</span>\n<pre>lua_State *lua_tothread (lua_State *L, int index);</pre>\n\n<p>\nConverts the value at the given acceptable index to a Lua thread\n(represented as <code>lua_State*</code>).\nThis value must be a thread;\notherwise, the function returns <code>NULL</code>.\n\n\n\n\n\n<hr><h3><a name=\"lua_touserdata\"><code>lua_touserdata</code></a></h3><p>\n<span class=\"apii\">[-0, +0, <em>-</em>]</span>\n<pre>void *lua_touserdata (lua_State *L, int index);</pre>\n\n<p>\nIf the value at the given acceptable index is a full userdata,\nreturns its block address.\nIf the value is a light userdata,\nreturns its pointer.\nOtherwise, returns <code>NULL</code>.\n\n\n\n\n\n<hr><h3><a name=\"lua_type\"><code>lua_type</code></a></h3><p>\n<span class=\"apii\">[-0, +0, <em>-</em>]</span>\n<pre>int lua_type (lua_State *L, int index);</pre>\n\n<p>\nReturns the type of the value in the given acceptable index,\nor <code>LUA_TNONE</code> for a non-valid index\n(that is, an index to an \"empty\" stack position).\nThe types returned by <a href=\"#lua_type\"><code>lua_type</code></a> are coded by the following constants\ndefined in <code>lua.h</code>:\n<code>LUA_TNIL</code>,\n<code>LUA_TNUMBER</code>,\n<code>LUA_TBOOLEAN</code>,\n<code>LUA_TSTRING</code>,\n<code>LUA_TTABLE</code>,\n<code>LUA_TFUNCTION</code>,\n<code>LUA_TUSERDATA</code>,\n<code>LUA_TTHREAD</code>,\nand\n<code>LUA_TLIGHTUSERDATA</code>.\n\n\n\n\n\n<hr><h3><a name=\"lua_typename\"><code>lua_typename</code></a></h3><p>\n<span class=\"apii\">[-0, +0, <em>-</em>]</span>\n<pre>const char *lua_typename  (lua_State *L, int tp);</pre>\n\n<p>\nReturns the name of the type encoded by the value <code>tp</code>,\nwhich must be one the values returned by <a href=\"#lua_type\"><code>lua_type</code></a>.\n\n\n\n\n\n<hr><h3><a name=\"lua_Writer\"><code>lua_Writer</code></a></h3>\n<pre>typedef int (*lua_Writer) (lua_State *L,\n                           const void* p,\n                           size_t sz,\n                           void* ud);</pre>\n\n<p>\nThe type of the writer function used by <a href=\"#lua_dump\"><code>lua_dump</code></a>.\nEvery time it produces another piece of chunk,\n<a href=\"#lua_dump\"><code>lua_dump</code></a> calls the writer,\npassing along the buffer to be written (<code>p</code>),\nits size (<code>sz</code>),\nand the <code>data</code> parameter supplied to <a href=\"#lua_dump\"><code>lua_dump</code></a>.\n\n\n<p>\nThe writer returns an error code:\n0&nbsp;means no errors;\nany other value means an error and stops <a href=\"#lua_dump\"><code>lua_dump</code></a> from\ncalling the writer again.\n\n\n\n\n\n<hr><h3><a name=\"lua_xmove\"><code>lua_xmove</code></a></h3><p>\n<span class=\"apii\">[-?, +?, <em>-</em>]</span>\n<pre>void lua_xmove (lua_State *from, lua_State *to, int n);</pre>\n\n<p>\nExchange values between different threads of the <em>same</em> global state.\n\n\n<p>\nThis function pops <code>n</code> values from the stack <code>from</code>,\nand pushes them onto the stack <code>to</code>.\n\n\n\n\n\n<hr><h3><a name=\"lua_yield\"><code>lua_yield</code></a></h3><p>\n<span class=\"apii\">[-?, +?, <em>-</em>]</span>\n<pre>int lua_yield  (lua_State *L, int nresults);</pre>\n\n<p>\nYields a coroutine.\n\n\n<p>\nThis function should only be called as the\nreturn expression of a C&nbsp;function, as follows:\n\n<pre>\n     return lua_yield (L, nresults);\n</pre><p>\nWhen a C&nbsp;function calls <a href=\"#lua_yield\"><code>lua_yield</code></a> in that way,\nthe running coroutine suspends its execution,\nand the call to <a href=\"#lua_resume\"><code>lua_resume</code></a> that started this coroutine returns.\nThe parameter <code>nresults</code> is the number of values from the stack\nthat are passed as results to <a href=\"#lua_resume\"><code>lua_resume</code></a>.\n\n\n\n\n\n\n\n<h2>3.8 - <a name=\"3.8\">The Debug Interface</a></h2>\n\n<p>\nLua has no built-in debugging facilities.\nInstead, it offers a special interface\nby means of functions and <em>hooks</em>.\nThis interface allows the construction of different\nkinds of debuggers, profilers, and other tools\nthat need \"inside information\" from the interpreter.\n\n\n\n<hr><h3><a name=\"lua_Debug\"><code>lua_Debug</code></a></h3>\n<pre>typedef struct lua_Debug {\n  int event;\n  const char *name;           /* (n) */\n  const char *namewhat;       /* (n) */\n  const char *what;           /* (S) */\n  const char *source;         /* (S) */\n  int currentline;            /* (l) */\n  int nups;                   /* (u) number of upvalues */\n  int linedefined;            /* (S) */\n  int lastlinedefined;        /* (S) */\n  char short_src[LUA_IDSIZE]; /* (S) */\n  /* private part */\n  <em>other fields</em>\n} lua_Debug;</pre>\n\n<p>\nA structure used to carry different pieces of\ninformation about an active function.\n<a href=\"#lua_getstack\"><code>lua_getstack</code></a> fills only the private part\nof this structure, for later use.\nTo fill the other fields of <a href=\"#lua_Debug\"><code>lua_Debug</code></a> with useful information,\ncall <a href=\"#lua_getinfo\"><code>lua_getinfo</code></a>.\n\n\n<p>\nThe fields of <a href=\"#lua_Debug\"><code>lua_Debug</code></a> have the following meaning:\n\n<ul>\n\n<li><b><code>source</code>:</b>\nIf the function was defined in a string,\nthen <code>source</code> is that string.\nIf the function was defined in a file,\nthen <code>source</code> starts with a '<code>@</code>' followed by the file name.\n</li>\n\n<li><b><code>short_src</code>:</b>\na \"printable\" version of <code>source</code>, to be used in error messages.\n</li>\n\n<li><b><code>linedefined</code>:</b>\nthe line number where the definition of the function starts.\n</li>\n\n<li><b><code>lastlinedefined</code>:</b>\nthe line number where the definition of the function ends.\n</li>\n\n<li><b><code>what</code>:</b>\nthe string <code>\"Lua\"</code> if the function is a Lua function,\n<code>\"C\"</code> if it is a C&nbsp;function,\n<code>\"main\"</code> if it is the main part of a chunk,\nand <code>\"tail\"</code> if it was a function that did a tail call.\nIn the latter case,\nLua has no other information about the function.\n</li>\n\n<li><b><code>currentline</code>:</b>\nthe current line where the given function is executing.\nWhen no line information is available,\n<code>currentline</code> is set to -1.\n</li>\n\n<li><b><code>name</code>:</b>\na reasonable name for the given function.\nBecause functions in Lua are first-class values,\nthey do not have a fixed name:\nsome functions can be the value of multiple global variables,\nwhile others can be stored only in a table field.\nThe <code>lua_getinfo</code> function checks how the function was\ncalled to find a suitable name.\nIf it cannot find a name,\nthen <code>name</code> is set to <code>NULL</code>.\n</li>\n\n<li><b><code>namewhat</code>:</b>\nexplains the <code>name</code> field.\nThe value of <code>namewhat</code> can be\n<code>\"global\"</code>, <code>\"local\"</code>, <code>\"method\"</code>,\n<code>\"field\"</code>, <code>\"upvalue\"</code>, or <code>\"\"</code> (the empty string),\naccording to how the function was called.\n(Lua uses the empty string when no other option seems to apply.)\n</li>\n\n<li><b><code>nups</code>:</b>\nthe number of upvalues of the function.\n</li>\n\n</ul>\n\n\n\n\n<hr><h3><a name=\"lua_gethook\"><code>lua_gethook</code></a></h3><p>\n<span class=\"apii\">[-0, +0, <em>-</em>]</span>\n<pre>lua_Hook lua_gethook (lua_State *L);</pre>\n\n<p>\nReturns the current hook function.\n\n\n\n\n\n<hr><h3><a name=\"lua_gethookcount\"><code>lua_gethookcount</code></a></h3><p>\n<span class=\"apii\">[-0, +0, <em>-</em>]</span>\n<pre>int lua_gethookcount (lua_State *L);</pre>\n\n<p>\nReturns the current hook count.\n\n\n\n\n\n<hr><h3><a name=\"lua_gethookmask\"><code>lua_gethookmask</code></a></h3><p>\n<span class=\"apii\">[-0, +0, <em>-</em>]</span>\n<pre>int lua_gethookmask (lua_State *L);</pre>\n\n<p>\nReturns the current hook mask.\n\n\n\n\n\n<hr><h3><a name=\"lua_getinfo\"><code>lua_getinfo</code></a></h3><p>\n<span class=\"apii\">[-(0|1), +(0|1|2), <em>m</em>]</span>\n<pre>int lua_getinfo (lua_State *L, const char *what, lua_Debug *ar);</pre>\n\n<p>\nReturns information about a specific function or function invocation.\n\n\n<p>\nTo get information about a function invocation,\nthe parameter <code>ar</code> must be a valid activation record that was\nfilled by a previous call to <a href=\"#lua_getstack\"><code>lua_getstack</code></a> or\ngiven as argument to a hook (see <a href=\"#lua_Hook\"><code>lua_Hook</code></a>).\n\n\n<p>\nTo get information about a function you push it onto the stack\nand start the <code>what</code> string with the character '<code>&gt;</code>'.\n(In that case,\n<code>lua_getinfo</code> pops the function in the top of the stack.)\nFor instance, to know in which line a function <code>f</code> was defined,\nyou can write the following code:\n\n<pre>\n     lua_Debug ar;\n     lua_getfield(L, LUA_GLOBALSINDEX, \"f\");  /* get global 'f' */\n     lua_getinfo(L, \"&gt;S\", &amp;ar);\n     printf(\"%d\\n\", ar.linedefined);\n</pre>\n\n<p>\nEach character in the string <code>what</code>\nselects some fields of the structure <code>ar</code> to be filled or\na value to be pushed on the stack:\n\n<ul>\n\n<li><b>'<code>n</code>':</b> fills in the field <code>name</code> and <code>namewhat</code>;\n</li>\n\n<li><b>'<code>S</code>':</b>\nfills in the fields <code>source</code>, <code>short_src</code>,\n<code>linedefined</code>, <code>lastlinedefined</code>, and <code>what</code>;\n</li>\n\n<li><b>'<code>l</code>':</b> fills in the field <code>currentline</code>;\n</li>\n\n<li><b>'<code>u</code>':</b> fills in the field <code>nups</code>;\n</li>\n\n<li><b>'<code>f</code>':</b>\npushes onto the stack the function that is\nrunning at the given level;\n</li>\n\n<li><b>'<code>L</code>':</b>\npushes onto the stack a table whose indices are the\nnumbers of the lines that are valid on the function.\n(A <em>valid line</em> is a line with some associated code,\nthat is, a line where you can put a break point.\nNon-valid lines include empty lines and comments.)\n</li>\n\n</ul>\n\n<p>\nThis function returns 0 on error\n(for instance, an invalid option in <code>what</code>).\n\n\n\n\n\n<hr><h3><a name=\"lua_getlocal\"><code>lua_getlocal</code></a></h3><p>\n<span class=\"apii\">[-0, +(0|1), <em>-</em>]</span>\n<pre>const char *lua_getlocal (lua_State *L, lua_Debug *ar, int n);</pre>\n\n<p>\nGets information about a local variable of a given activation record.\nThe parameter <code>ar</code> must be a valid activation record that was\nfilled by a previous call to <a href=\"#lua_getstack\"><code>lua_getstack</code></a> or\ngiven as argument to a hook (see <a href=\"#lua_Hook\"><code>lua_Hook</code></a>).\nThe index <code>n</code> selects which local variable to inspect\n(1 is the first parameter or active local variable, and so on,\nuntil the last active local variable).\n<a href=\"#lua_getlocal\"><code>lua_getlocal</code></a> pushes the variable's value onto the stack\nand returns its name.\n\n\n<p>\nVariable names starting with '<code>(</code>' (open parentheses)\nrepresent internal variables\n(loop control variables, temporaries, and C&nbsp;function locals).\n\n\n<p>\nReturns <code>NULL</code> (and pushes nothing)\nwhen the index is greater than\nthe number of active local variables.\n\n\n\n\n\n<hr><h3><a name=\"lua_getstack\"><code>lua_getstack</code></a></h3><p>\n<span class=\"apii\">[-0, +0, <em>-</em>]</span>\n<pre>int lua_getstack (lua_State *L, int level, lua_Debug *ar);</pre>\n\n<p>\nGet information about the interpreter runtime stack.\n\n\n<p>\nThis function fills parts of a <a href=\"#lua_Debug\"><code>lua_Debug</code></a> structure with\nan identification of the <em>activation record</em>\nof the function executing at a given level.\nLevel&nbsp;0 is the current running function,\nwhereas level <em>n+1</em> is the function that has called level <em>n</em>.\nWhen there are no errors, <a href=\"#lua_getstack\"><code>lua_getstack</code></a> returns 1;\nwhen called with a level greater than the stack depth,\nit returns 0.\n\n\n\n\n\n<hr><h3><a name=\"lua_getupvalue\"><code>lua_getupvalue</code></a></h3><p>\n<span class=\"apii\">[-0, +(0|1), <em>-</em>]</span>\n<pre>const char *lua_getupvalue (lua_State *L, int funcindex, int n);</pre>\n\n<p>\nGets information about a closure's upvalue.\n(For Lua functions,\nupvalues are the external local variables that the function uses,\nand that are consequently included in its closure.)\n<a href=\"#lua_getupvalue\"><code>lua_getupvalue</code></a> gets the index <code>n</code> of an upvalue,\npushes the upvalue's value onto the stack,\nand returns its name.\n<code>funcindex</code> points to the closure in the stack.\n(Upvalues have no particular order,\nas they are active through the whole function.\nSo, they are numbered in an arbitrary order.)\n\n\n<p>\nReturns <code>NULL</code> (and pushes nothing)\nwhen the index is greater than the number of upvalues.\nFor C&nbsp;functions, this function uses the empty string <code>\"\"</code>\nas a name for all upvalues.\n\n\n\n\n\n<hr><h3><a name=\"lua_Hook\"><code>lua_Hook</code></a></h3>\n<pre>typedef void (*lua_Hook) (lua_State *L, lua_Debug *ar);</pre>\n\n<p>\nType for debugging hook functions.\n\n\n<p>\nWhenever a hook is called, its <code>ar</code> argument has its field\n<code>event</code> set to the specific event that triggered the hook.\nLua identifies these events with the following constants:\n<a name=\"pdf-LUA_HOOKCALL\"><code>LUA_HOOKCALL</code></a>, <a name=\"pdf-LUA_HOOKRET\"><code>LUA_HOOKRET</code></a>,\n<a name=\"pdf-LUA_HOOKTAILRET\"><code>LUA_HOOKTAILRET</code></a>, <a name=\"pdf-LUA_HOOKLINE\"><code>LUA_HOOKLINE</code></a>,\nand <a name=\"pdf-LUA_HOOKCOUNT\"><code>LUA_HOOKCOUNT</code></a>.\nMoreover, for line events, the field <code>currentline</code> is also set.\nTo get the value of any other field in <code>ar</code>,\nthe hook must call <a href=\"#lua_getinfo\"><code>lua_getinfo</code></a>.\nFor return events, <code>event</code> can be <code>LUA_HOOKRET</code>,\nthe normal value, or <code>LUA_HOOKTAILRET</code>.\nIn the latter case, Lua is simulating a return from\na function that did a tail call;\nin this case, it is useless to call <a href=\"#lua_getinfo\"><code>lua_getinfo</code></a>.\n\n\n<p>\nWhile Lua is running a hook, it disables other calls to hooks.\nTherefore, if a hook calls back Lua to execute a function or a chunk,\nthis execution occurs without any calls to hooks.\n\n\n\n\n\n<hr><h3><a name=\"lua_sethook\"><code>lua_sethook</code></a></h3><p>\n<span class=\"apii\">[-0, +0, <em>-</em>]</span>\n<pre>int lua_sethook (lua_State *L, lua_Hook f, int mask, int count);</pre>\n\n<p>\nSets the debugging hook function.\n\n\n<p>\nArgument <code>f</code> is the hook function.\n<code>mask</code> specifies on which events the hook will be called:\nit is formed by a bitwise or of the constants\n<a name=\"pdf-LUA_MASKCALL\"><code>LUA_MASKCALL</code></a>,\n<a name=\"pdf-LUA_MASKRET\"><code>LUA_MASKRET</code></a>,\n<a name=\"pdf-LUA_MASKLINE\"><code>LUA_MASKLINE</code></a>,\nand <a name=\"pdf-LUA_MASKCOUNT\"><code>LUA_MASKCOUNT</code></a>.\nThe <code>count</code> argument is only meaningful when the mask\nincludes <code>LUA_MASKCOUNT</code>.\nFor each event, the hook is called as explained below:\n\n<ul>\n\n<li><b>The call hook:</b> is called when the interpreter calls a function.\nThe hook is called just after Lua enters the new function,\nbefore the function gets its arguments.\n</li>\n\n<li><b>The return hook:</b> is called when the interpreter returns from a function.\nThe hook is called just before Lua leaves the function.\nYou have no access to the values to be returned by the function.\n</li>\n\n<li><b>The line hook:</b> is called when the interpreter is about to\nstart the execution of a new line of code,\nor when it jumps back in the code (even to the same line).\n(This event only happens while Lua is executing a Lua function.)\n</li>\n\n<li><b>The count hook:</b> is called after the interpreter executes every\n<code>count</code> instructions.\n(This event only happens while Lua is executing a Lua function.)\n</li>\n\n</ul>\n\n<p>\nA hook is disabled by setting <code>mask</code> to zero.\n\n\n\n\n\n<hr><h3><a name=\"lua_setlocal\"><code>lua_setlocal</code></a></h3><p>\n<span class=\"apii\">[-(0|1), +0, <em>-</em>]</span>\n<pre>const char *lua_setlocal (lua_State *L, lua_Debug *ar, int n);</pre>\n\n<p>\nSets the value of a local variable of a given activation record.\nParameters <code>ar</code> and <code>n</code> are as in <a href=\"#lua_getlocal\"><code>lua_getlocal</code></a>\n(see <a href=\"#lua_getlocal\"><code>lua_getlocal</code></a>).\n<a href=\"#lua_setlocal\"><code>lua_setlocal</code></a> assigns the value at the top of the stack\nto the variable and returns its name.\nIt also pops the value from the stack.\n\n\n<p>\nReturns <code>NULL</code> (and pops nothing)\nwhen the index is greater than\nthe number of active local variables.\n\n\n\n\n\n<hr><h3><a name=\"lua_setupvalue\"><code>lua_setupvalue</code></a></h3><p>\n<span class=\"apii\">[-(0|1), +0, <em>-</em>]</span>\n<pre>const char *lua_setupvalue (lua_State *L, int funcindex, int n);</pre>\n\n<p>\nSets the value of a closure's upvalue.\nIt assigns the value at the top of the stack\nto the upvalue and returns its name.\nIt also pops the value from the stack.\nParameters <code>funcindex</code> and <code>n</code> are as in the <a href=\"#lua_getupvalue\"><code>lua_getupvalue</code></a>\n(see <a href=\"#lua_getupvalue\"><code>lua_getupvalue</code></a>).\n\n\n<p>\nReturns <code>NULL</code> (and pops nothing)\nwhen the index is greater than the number of upvalues.\n\n\n\n\n\n\n\n<h1>4 - <a name=\"4\">The Auxiliary Library</a></h1>\n\n<p>\n\nThe <em>auxiliary library</em> provides several convenient functions\nto interface C with Lua.\nWhile the basic API provides the primitive functions for all \ninteractions between C and Lua,\nthe auxiliary library provides higher-level functions for some\ncommon tasks.\n\n\n<p>\nAll functions from the auxiliary library\nare defined in header file <code>lauxlib.h</code> and\nhave a prefix <code>luaL_</code>.\n\n\n<p>\nAll functions in the auxiliary library are built on\ntop of the basic API,\nand so they provide nothing that cannot be done with this API.\n\n\n<p>\nSeveral functions in the auxiliary library are used to\ncheck C&nbsp;function arguments.\nTheir names are always <code>luaL_check*</code> or <code>luaL_opt*</code>.\nAll of these functions throw an error if the check is not satisfied.\nBecause the error message is formatted for arguments\n(e.g., \"<code>bad argument #1</code>\"),\nyou should not use these functions for other stack values.\n\n\n\n<h2>4.1 - <a name=\"4.1\">Functions and Types</a></h2>\n\n<p>\nHere we list all functions and types from the auxiliary library\nin alphabetical order.\n\n\n\n<hr><h3><a name=\"luaL_addchar\"><code>luaL_addchar</code></a></h3><p>\n<span class=\"apii\">[-0, +0, <em>m</em>]</span>\n<pre>void luaL_addchar (luaL_Buffer *B, char c);</pre>\n\n<p>\nAdds the character <code>c</code> to the buffer <code>B</code>\n(see <a href=\"#luaL_Buffer\"><code>luaL_Buffer</code></a>).\n\n\n\n\n\n<hr><h3><a name=\"luaL_addlstring\"><code>luaL_addlstring</code></a></h3><p>\n<span class=\"apii\">[-0, +0, <em>m</em>]</span>\n<pre>void luaL_addlstring (luaL_Buffer *B, const char *s, size_t l);</pre>\n\n<p>\nAdds the string pointed to by <code>s</code> with length <code>l</code> to\nthe buffer <code>B</code>\n(see <a href=\"#luaL_Buffer\"><code>luaL_Buffer</code></a>).\nThe string may contain embedded zeros.\n\n\n\n\n\n<hr><h3><a name=\"luaL_addsize\"><code>luaL_addsize</code></a></h3><p>\n<span class=\"apii\">[-0, +0, <em>m</em>]</span>\n<pre>void luaL_addsize (luaL_Buffer *B, size_t n);</pre>\n\n<p>\nAdds to the buffer <code>B</code> (see <a href=\"#luaL_Buffer\"><code>luaL_Buffer</code></a>)\na string of length <code>n</code> previously copied to the\nbuffer area (see <a href=\"#luaL_prepbuffer\"><code>luaL_prepbuffer</code></a>).\n\n\n\n\n\n<hr><h3><a name=\"luaL_addstring\"><code>luaL_addstring</code></a></h3><p>\n<span class=\"apii\">[-0, +0, <em>m</em>]</span>\n<pre>void luaL_addstring (luaL_Buffer *B, const char *s);</pre>\n\n<p>\nAdds the zero-terminated string pointed to by <code>s</code>\nto the buffer <code>B</code>\n(see <a href=\"#luaL_Buffer\"><code>luaL_Buffer</code></a>).\nThe string may not contain embedded zeros.\n\n\n\n\n\n<hr><h3><a name=\"luaL_addvalue\"><code>luaL_addvalue</code></a></h3><p>\n<span class=\"apii\">[-1, +0, <em>m</em>]</span>\n<pre>void luaL_addvalue (luaL_Buffer *B);</pre>\n\n<p>\nAdds the value at the top of the stack\nto the buffer <code>B</code>\n(see <a href=\"#luaL_Buffer\"><code>luaL_Buffer</code></a>).\nPops the value.\n\n\n<p>\nThis is the only function on string buffers that can (and must)\nbe called with an extra element on the stack,\nwhich is the value to be added to the buffer.\n\n\n\n\n\n<hr><h3><a name=\"luaL_argcheck\"><code>luaL_argcheck</code></a></h3><p>\n<span class=\"apii\">[-0, +0, <em>v</em>]</span>\n<pre>void luaL_argcheck (lua_State *L,\n                    int cond,\n                    int narg,\n                    const char *extramsg);</pre>\n\n<p>\nChecks whether <code>cond</code> is true.\nIf not, raises an error with the following message,\nwhere <code>func</code> is retrieved from the call stack:\n\n<pre>\n     bad argument #&lt;narg&gt; to &lt;func&gt; (&lt;extramsg&gt;)\n</pre>\n\n\n\n\n<hr><h3><a name=\"luaL_argerror\"><code>luaL_argerror</code></a></h3><p>\n<span class=\"apii\">[-0, +0, <em>v</em>]</span>\n<pre>int luaL_argerror (lua_State *L, int narg, const char *extramsg);</pre>\n\n<p>\nRaises an error with the following message,\nwhere <code>func</code> is retrieved from the call stack:\n\n<pre>\n     bad argument #&lt;narg&gt; to &lt;func&gt; (&lt;extramsg&gt;)\n</pre>\n\n<p>\nThis function never returns,\nbut it is an idiom to use it in C&nbsp;functions\nas <code>return luaL_argerror(<em>args</em>)</code>.\n\n\n\n\n\n<hr><h3><a name=\"luaL_Buffer\"><code>luaL_Buffer</code></a></h3>\n<pre>typedef struct luaL_Buffer luaL_Buffer;</pre>\n\n<p>\nType for a <em>string buffer</em>.\n\n\n<p>\nA string buffer allows C&nbsp;code to build Lua strings piecemeal.\nIts pattern of use is as follows:\n\n<ul>\n\n<li>First you declare a variable <code>b</code> of type <a href=\"#luaL_Buffer\"><code>luaL_Buffer</code></a>.</li>\n\n<li>Then you initialize it with a call <code>luaL_buffinit(L, &amp;b)</code>.</li>\n\n<li>\nThen you add string pieces to the buffer calling any of\nthe <code>luaL_add*</code> functions.\n</li>\n\n<li>\nYou finish by calling <code>luaL_pushresult(&amp;b)</code>.\nThis call leaves the final string on the top of the stack.\n</li>\n\n</ul>\n\n<p>\nDuring its normal operation,\na string buffer uses a variable number of stack slots.\nSo, while using a buffer, you cannot assume that you know where\nthe top of the stack is.\nYou can use the stack between successive calls to buffer operations\nas long as that use is balanced;\nthat is,\nwhen you call a buffer operation,\nthe stack is at the same level\nit was immediately after the previous buffer operation.\n(The only exception to this rule is <a href=\"#luaL_addvalue\"><code>luaL_addvalue</code></a>.)\nAfter calling <a href=\"#luaL_pushresult\"><code>luaL_pushresult</code></a> the stack is back to its\nlevel when the buffer was initialized,\nplus the final string on its top.\n\n\n\n\n\n<hr><h3><a name=\"luaL_buffinit\"><code>luaL_buffinit</code></a></h3><p>\n<span class=\"apii\">[-0, +0, <em>-</em>]</span>\n<pre>void luaL_buffinit (lua_State *L, luaL_Buffer *B);</pre>\n\n<p>\nInitializes a buffer <code>B</code>.\nThis function does not allocate any space;\nthe buffer must be declared as a variable\n(see <a href=\"#luaL_Buffer\"><code>luaL_Buffer</code></a>).\n\n\n\n\n\n<hr><h3><a name=\"luaL_callmeta\"><code>luaL_callmeta</code></a></h3><p>\n<span class=\"apii\">[-0, +(0|1), <em>e</em>]</span>\n<pre>int luaL_callmeta (lua_State *L, int obj, const char *e);</pre>\n\n<p>\nCalls a metamethod.\n\n\n<p>\nIf the object at index <code>obj</code> has a metatable and this\nmetatable has a field <code>e</code>,\nthis function calls this field and passes the object as its only argument.\nIn this case this function returns 1 and pushes onto the\nstack the value returned by the call.\nIf there is no metatable or no metamethod,\nthis function returns 0 (without pushing any value on the stack).\n\n\n\n\n\n<hr><h3><a name=\"luaL_checkany\"><code>luaL_checkany</code></a></h3><p>\n<span class=\"apii\">[-0, +0, <em>v</em>]</span>\n<pre>void luaL_checkany (lua_State *L, int narg);</pre>\n\n<p>\nChecks whether the function has an argument\nof any type (including <b>nil</b>) at position <code>narg</code>.\n\n\n\n\n\n<hr><h3><a name=\"luaL_checkint\"><code>luaL_checkint</code></a></h3><p>\n<span class=\"apii\">[-0, +0, <em>v</em>]</span>\n<pre>int luaL_checkint (lua_State *L, int narg);</pre>\n\n<p>\nChecks whether the function argument <code>narg</code> is a number\nand returns this number cast to an <code>int</code>.\n\n\n\n\n\n<hr><h3><a name=\"luaL_checkinteger\"><code>luaL_checkinteger</code></a></h3><p>\n<span class=\"apii\">[-0, +0, <em>v</em>]</span>\n<pre>lua_Integer luaL_checkinteger (lua_State *L, int narg);</pre>\n\n<p>\nChecks whether the function argument <code>narg</code> is a number\nand returns this number cast to a <a href=\"#lua_Integer\"><code>lua_Integer</code></a>.\n\n\n\n\n\n<hr><h3><a name=\"luaL_checklong\"><code>luaL_checklong</code></a></h3><p>\n<span class=\"apii\">[-0, +0, <em>v</em>]</span>\n<pre>long luaL_checklong (lua_State *L, int narg);</pre>\n\n<p>\nChecks whether the function argument <code>narg</code> is a number\nand returns this number cast to a <code>long</code>.\n\n\n\n\n\n<hr><h3><a name=\"luaL_checklstring\"><code>luaL_checklstring</code></a></h3><p>\n<span class=\"apii\">[-0, +0, <em>v</em>]</span>\n<pre>const char *luaL_checklstring (lua_State *L, int narg, size_t *l);</pre>\n\n<p>\nChecks whether the function argument <code>narg</code> is a string\nand returns this string;\nif <code>l</code> is not <code>NULL</code> fills <code>*l</code>\nwith the string's length.\n\n\n<p>\nThis function uses <a href=\"#lua_tolstring\"><code>lua_tolstring</code></a> to get its result,\nso all conversions and caveats of that function apply here.\n\n\n\n\n\n<hr><h3><a name=\"luaL_checknumber\"><code>luaL_checknumber</code></a></h3><p>\n<span class=\"apii\">[-0, +0, <em>v</em>]</span>\n<pre>lua_Number luaL_checknumber (lua_State *L, int narg);</pre>\n\n<p>\nChecks whether the function argument <code>narg</code> is a number\nand returns this number.\n\n\n\n\n\n<hr><h3><a name=\"luaL_checkoption\"><code>luaL_checkoption</code></a></h3><p>\n<span class=\"apii\">[-0, +0, <em>v</em>]</span>\n<pre>int luaL_checkoption (lua_State *L,\n                      int narg,\n                      const char *def,\n                      const char *const lst[]);</pre>\n\n<p>\nChecks whether the function argument <code>narg</code> is a string and\nsearches for this string in the array <code>lst</code>\n(which must be NULL-terminated).\nReturns the index in the array where the string was found.\nRaises an error if the argument is not a string or\nif the string cannot be found.\n\n\n<p>\nIf <code>def</code> is not <code>NULL</code>,\nthe function uses <code>def</code> as a default value when\nthere is no argument <code>narg</code> or if this argument is <b>nil</b>.\n\n\n<p>\nThis is a useful function for mapping strings to C&nbsp;enums.\n(The usual convention in Lua libraries is\nto use strings instead of numbers to select options.)\n\n\n\n\n\n<hr><h3><a name=\"luaL_checkstack\"><code>luaL_checkstack</code></a></h3><p>\n<span class=\"apii\">[-0, +0, <em>v</em>]</span>\n<pre>void luaL_checkstack (lua_State *L, int sz, const char *msg);</pre>\n\n<p>\nGrows the stack size to <code>top + sz</code> elements,\nraising an error if the stack cannot grow to that size.\n<code>msg</code> is an additional text to go into the error message.\n\n\n\n\n\n<hr><h3><a name=\"luaL_checkstring\"><code>luaL_checkstring</code></a></h3><p>\n<span class=\"apii\">[-0, +0, <em>v</em>]</span>\n<pre>const char *luaL_checkstring (lua_State *L, int narg);</pre>\n\n<p>\nChecks whether the function argument <code>narg</code> is a string\nand returns this string.\n\n\n<p>\nThis function uses <a href=\"#lua_tolstring\"><code>lua_tolstring</code></a> to get its result,\nso all conversions and caveats of that function apply here.\n\n\n\n\n\n<hr><h3><a name=\"luaL_checktype\"><code>luaL_checktype</code></a></h3><p>\n<span class=\"apii\">[-0, +0, <em>v</em>]</span>\n<pre>void luaL_checktype (lua_State *L, int narg, int t);</pre>\n\n<p>\nChecks whether the function argument <code>narg</code> has type <code>t</code>.\nSee <a href=\"#lua_type\"><code>lua_type</code></a> for the encoding of types for <code>t</code>.\n\n\n\n\n\n<hr><h3><a name=\"luaL_checkudata\"><code>luaL_checkudata</code></a></h3><p>\n<span class=\"apii\">[-0, +0, <em>v</em>]</span>\n<pre>void *luaL_checkudata (lua_State *L, int narg, const char *tname);</pre>\n\n<p>\nChecks whether the function argument <code>narg</code> is a userdata\nof the type <code>tname</code> (see <a href=\"#luaL_newmetatable\"><code>luaL_newmetatable</code></a>).\n\n\n\n\n\n<hr><h3><a name=\"luaL_dofile\"><code>luaL_dofile</code></a></h3><p>\n<span class=\"apii\">[-0, +?, <em>m</em>]</span>\n<pre>int luaL_dofile (lua_State *L, const char *filename);</pre>\n\n<p>\nLoads and runs the given file.\nIt is defined as the following macro:\n\n<pre>\n     (luaL_loadfile(L, filename) || lua_pcall(L, 0, LUA_MULTRET, 0))\n</pre><p>\nIt returns 0 if there are no errors\nor 1 in case of errors.\n\n\n\n\n\n<hr><h3><a name=\"luaL_dostring\"><code>luaL_dostring</code></a></h3><p>\n<span class=\"apii\">[-0, +?, <em>m</em>]</span>\n<pre>int luaL_dostring (lua_State *L, const char *str);</pre>\n\n<p>\nLoads and runs the given string.\nIt is defined as the following macro:\n\n<pre>\n     (luaL_loadstring(L, str) || lua_pcall(L, 0, LUA_MULTRET, 0))\n</pre><p>\nIt returns 0 if there are no errors\nor 1 in case of errors.\n\n\n\n\n\n<hr><h3><a name=\"luaL_error\"><code>luaL_error</code></a></h3><p>\n<span class=\"apii\">[-0, +0, <em>v</em>]</span>\n<pre>int luaL_error (lua_State *L, const char *fmt, ...);</pre>\n\n<p>\nRaises an error.\nThe error message format is given by <code>fmt</code>\nplus any extra arguments,\nfollowing the same rules of <a href=\"#lua_pushfstring\"><code>lua_pushfstring</code></a>.\nIt also adds at the beginning of the message the file name and\nthe line number where the error occurred,\nif this information is available.\n\n\n<p>\nThis function never returns,\nbut it is an idiom to use it in C&nbsp;functions\nas <code>return luaL_error(<em>args</em>)</code>.\n\n\n\n\n\n<hr><h3><a name=\"luaL_getmetafield\"><code>luaL_getmetafield</code></a></h3><p>\n<span class=\"apii\">[-0, +(0|1), <em>m</em>]</span>\n<pre>int luaL_getmetafield (lua_State *L, int obj, const char *e);</pre>\n\n<p>\nPushes onto the stack the field <code>e</code> from the metatable\nof the object at index <code>obj</code>.\nIf the object does not have a metatable,\nor if the metatable does not have this field,\nreturns 0 and pushes nothing.\n\n\n\n\n\n<hr><h3><a name=\"luaL_getmetatable\"><code>luaL_getmetatable</code></a></h3><p>\n<span class=\"apii\">[-0, +1, <em>-</em>]</span>\n<pre>void luaL_getmetatable (lua_State *L, const char *tname);</pre>\n\n<p>\nPushes onto the stack the metatable associated with name <code>tname</code>\nin the registry (see <a href=\"#luaL_newmetatable\"><code>luaL_newmetatable</code></a>).\n\n\n\n\n\n<hr><h3><a name=\"luaL_gsub\"><code>luaL_gsub</code></a></h3><p>\n<span class=\"apii\">[-0, +1, <em>m</em>]</span>\n<pre>const char *luaL_gsub (lua_State *L,\n                       const char *s,\n                       const char *p,\n                       const char *r);</pre>\n\n<p>\nCreates a copy of string <code>s</code> by replacing\nany occurrence of the string <code>p</code>\nwith the string <code>r</code>.\nPushes the resulting string on the stack and returns it.\n\n\n\n\n\n<hr><h3><a name=\"luaL_loadbuffer\"><code>luaL_loadbuffer</code></a></h3><p>\n<span class=\"apii\">[-0, +1, <em>m</em>]</span>\n<pre>int luaL_loadbuffer (lua_State *L,\n                     const char *buff,\n                     size_t sz,\n                     const char *name);</pre>\n\n<p>\nLoads a buffer as a Lua chunk.\nThis function uses <a href=\"#lua_load\"><code>lua_load</code></a> to load the chunk in the\nbuffer pointed to by <code>buff</code> with size <code>sz</code>.\n\n\n<p>\nThis function returns the same results as <a href=\"#lua_load\"><code>lua_load</code></a>.\n<code>name</code> is the chunk name,\nused for debug information and error messages.\n\n\n\n\n\n<hr><h3><a name=\"luaL_loadfile\"><code>luaL_loadfile</code></a></h3><p>\n<span class=\"apii\">[-0, +1, <em>m</em>]</span>\n<pre>int luaL_loadfile (lua_State *L, const char *filename);</pre>\n\n<p>\nLoads a file as a Lua chunk.\nThis function uses <a href=\"#lua_load\"><code>lua_load</code></a> to load the chunk in the file\nnamed <code>filename</code>.\nIf <code>filename</code> is <code>NULL</code>,\nthen it loads from the standard input.\nThe first line in the file is ignored if it starts with a <code>#</code>.\n\n\n<p>\nThis function returns the same results as <a href=\"#lua_load\"><code>lua_load</code></a>,\nbut it has an extra error code <a name=\"pdf-LUA_ERRFILE\"><code>LUA_ERRFILE</code></a>\nif it cannot open/read the file.\n\n\n<p>\nAs <a href=\"#lua_load\"><code>lua_load</code></a>, this function only loads the chunk;\nit does not run it.\n\n\n\n\n\n<hr><h3><a name=\"luaL_loadstring\"><code>luaL_loadstring</code></a></h3><p>\n<span class=\"apii\">[-0, +1, <em>m</em>]</span>\n<pre>int luaL_loadstring (lua_State *L, const char *s);</pre>\n\n<p>\nLoads a string as a Lua chunk.\nThis function uses <a href=\"#lua_load\"><code>lua_load</code></a> to load the chunk in\nthe zero-terminated string <code>s</code>.\n\n\n<p>\nThis function returns the same results as <a href=\"#lua_load\"><code>lua_load</code></a>.\n\n\n<p>\nAlso as <a href=\"#lua_load\"><code>lua_load</code></a>, this function only loads the chunk;\nit does not run it.\n\n\n\n\n\n<hr><h3><a name=\"luaL_newmetatable\"><code>luaL_newmetatable</code></a></h3><p>\n<span class=\"apii\">[-0, +1, <em>m</em>]</span>\n<pre>int luaL_newmetatable (lua_State *L, const char *tname);</pre>\n\n<p>\nIf the registry already has the key <code>tname</code>,\nreturns 0.\nOtherwise,\ncreates a new table to be used as a metatable for userdata,\nadds it to the registry with key <code>tname</code>,\nand returns 1.\n\n\n<p>\nIn both cases pushes onto the stack the final value associated\nwith <code>tname</code> in the registry.\n\n\n\n\n\n<hr><h3><a name=\"luaL_newstate\"><code>luaL_newstate</code></a></h3><p>\n<span class=\"apii\">[-0, +0, <em>-</em>]</span>\n<pre>lua_State *luaL_newstate (void);</pre>\n\n<p>\nCreates a new Lua state.\nIt calls <a href=\"#lua_newstate\"><code>lua_newstate</code></a> with an\nallocator based on the standard&nbsp;C <code>realloc</code> function\nand then sets a panic function (see <a href=\"#lua_atpanic\"><code>lua_atpanic</code></a>) that prints\nan error message to the standard error output in case of fatal\nerrors.\n\n\n<p>\nReturns the new state,\nor <code>NULL</code> if there is a memory allocation error.\n\n\n\n\n\n<hr><h3><a name=\"luaL_openlibs\"><code>luaL_openlibs</code></a></h3><p>\n<span class=\"apii\">[-0, +0, <em>m</em>]</span>\n<pre>void luaL_openlibs (lua_State *L);</pre>\n\n<p>\nOpens all standard Lua libraries into the given state.\n\n\n\n\n\n<hr><h3><a name=\"luaL_optint\"><code>luaL_optint</code></a></h3><p>\n<span class=\"apii\">[-0, +0, <em>v</em>]</span>\n<pre>int luaL_optint (lua_State *L, int narg, int d);</pre>\n\n<p>\nIf the function argument <code>narg</code> is a number,\nreturns this number cast to an <code>int</code>.\nIf this argument is absent or is <b>nil</b>,\nreturns <code>d</code>.\nOtherwise, raises an error.\n\n\n\n\n\n<hr><h3><a name=\"luaL_optinteger\"><code>luaL_optinteger</code></a></h3><p>\n<span class=\"apii\">[-0, +0, <em>v</em>]</span>\n<pre>lua_Integer luaL_optinteger (lua_State *L,\n                             int narg,\n                             lua_Integer d);</pre>\n\n<p>\nIf the function argument <code>narg</code> is a number,\nreturns this number cast to a <a href=\"#lua_Integer\"><code>lua_Integer</code></a>.\nIf this argument is absent or is <b>nil</b>,\nreturns <code>d</code>.\nOtherwise, raises an error.\n\n\n\n\n\n<hr><h3><a name=\"luaL_optlong\"><code>luaL_optlong</code></a></h3><p>\n<span class=\"apii\">[-0, +0, <em>v</em>]</span>\n<pre>long luaL_optlong (lua_State *L, int narg, long d);</pre>\n\n<p>\nIf the function argument <code>narg</code> is a number,\nreturns this number cast to a <code>long</code>.\nIf this argument is absent or is <b>nil</b>,\nreturns <code>d</code>.\nOtherwise, raises an error.\n\n\n\n\n\n<hr><h3><a name=\"luaL_optlstring\"><code>luaL_optlstring</code></a></h3><p>\n<span class=\"apii\">[-0, +0, <em>v</em>]</span>\n<pre>const char *luaL_optlstring (lua_State *L,\n                             int narg,\n                             const char *d,\n                             size_t *l);</pre>\n\n<p>\nIf the function argument <code>narg</code> is a string,\nreturns this string.\nIf this argument is absent or is <b>nil</b>,\nreturns <code>d</code>.\nOtherwise, raises an error.\n\n\n<p>\nIf <code>l</code> is not <code>NULL</code>,\nfills the position <code>*l</code> with the results's length.\n\n\n\n\n\n<hr><h3><a name=\"luaL_optnumber\"><code>luaL_optnumber</code></a></h3><p>\n<span class=\"apii\">[-0, +0, <em>v</em>]</span>\n<pre>lua_Number luaL_optnumber (lua_State *L, int narg, lua_Number d);</pre>\n\n<p>\nIf the function argument <code>narg</code> is a number,\nreturns this number.\nIf this argument is absent or is <b>nil</b>,\nreturns <code>d</code>.\nOtherwise, raises an error.\n\n\n\n\n\n<hr><h3><a name=\"luaL_optstring\"><code>luaL_optstring</code></a></h3><p>\n<span class=\"apii\">[-0, +0, <em>v</em>]</span>\n<pre>const char *luaL_optstring (lua_State *L,\n                            int narg,\n                            const char *d);</pre>\n\n<p>\nIf the function argument <code>narg</code> is a string,\nreturns this string.\nIf this argument is absent or is <b>nil</b>,\nreturns <code>d</code>.\nOtherwise, raises an error.\n\n\n\n\n\n<hr><h3><a name=\"luaL_prepbuffer\"><code>luaL_prepbuffer</code></a></h3><p>\n<span class=\"apii\">[-0, +0, <em>-</em>]</span>\n<pre>char *luaL_prepbuffer (luaL_Buffer *B);</pre>\n\n<p>\nReturns an address to a space of size <a name=\"pdf-LUAL_BUFFERSIZE\"><code>LUAL_BUFFERSIZE</code></a>\nwhere you can copy a string to be added to buffer <code>B</code>\n(see <a href=\"#luaL_Buffer\"><code>luaL_Buffer</code></a>).\nAfter copying the string into this space you must call\n<a href=\"#luaL_addsize\"><code>luaL_addsize</code></a> with the size of the string to actually add \nit to the buffer.\n\n\n\n\n\n<hr><h3><a name=\"luaL_pushresult\"><code>luaL_pushresult</code></a></h3><p>\n<span class=\"apii\">[-?, +1, <em>m</em>]</span>\n<pre>void luaL_pushresult (luaL_Buffer *B);</pre>\n\n<p>\nFinishes the use of buffer <code>B</code> leaving the final string on\nthe top of the stack.\n\n\n\n\n\n<hr><h3><a name=\"luaL_ref\"><code>luaL_ref</code></a></h3><p>\n<span class=\"apii\">[-1, +0, <em>m</em>]</span>\n<pre>int luaL_ref (lua_State *L, int t);</pre>\n\n<p>\nCreates and returns a <em>reference</em>,\nin the table at index <code>t</code>,\nfor the object at the top of the stack (and pops the object).\n\n\n<p>\nA reference is a unique integer key.\nAs long as you do not manually add integer keys into table <code>t</code>,\n<a href=\"#luaL_ref\"><code>luaL_ref</code></a> ensures the uniqueness of the key it returns.\nYou can retrieve an object referred by reference <code>r</code>\nby calling <code>lua_rawgeti(L, t, r)</code>.\nFunction <a href=\"#luaL_unref\"><code>luaL_unref</code></a> frees a reference and its associated object.\n\n\n<p>\nIf the object at the top of the stack is <b>nil</b>,\n<a href=\"#luaL_ref\"><code>luaL_ref</code></a> returns the constant <a name=\"pdf-LUA_REFNIL\"><code>LUA_REFNIL</code></a>.\nThe constant <a name=\"pdf-LUA_NOREF\"><code>LUA_NOREF</code></a> is guaranteed to be different\nfrom any reference returned by <a href=\"#luaL_ref\"><code>luaL_ref</code></a>.\n\n\n\n\n\n<hr><h3><a name=\"luaL_Reg\"><code>luaL_Reg</code></a></h3>\n<pre>typedef struct luaL_Reg {\n  const char *name;\n  lua_CFunction func;\n} luaL_Reg;</pre>\n\n<p>\nType for arrays of functions to be registered by\n<a href=\"#luaL_register\"><code>luaL_register</code></a>.\n<code>name</code> is the function name and <code>func</code> is a pointer to\nthe function.\nAny array of <a href=\"#luaL_Reg\"><code>luaL_Reg</code></a> must end with an sentinel entry\nin which both <code>name</code> and <code>func</code> are <code>NULL</code>.\n\n\n\n\n\n<hr><h3><a name=\"luaL_register\"><code>luaL_register</code></a></h3><p>\n<span class=\"apii\">[-(0|1), +1, <em>m</em>]</span>\n<pre>void luaL_register (lua_State *L,\n                    const char *libname,\n                    const luaL_Reg *l);</pre>\n\n<p>\nOpens a library.\n\n\n<p>\nWhen called with <code>libname</code> equal to <code>NULL</code>,\nit simply registers all functions in the list <code>l</code>\n(see <a href=\"#luaL_Reg\"><code>luaL_Reg</code></a>) into the table on the top of the stack.\n\n\n<p>\nWhen called with a non-null <code>libname</code>,\n<code>luaL_register</code> creates a new table <code>t</code>,\nsets it as the value of the global variable <code>libname</code>,\nsets it as the value of <code>package.loaded[libname]</code>,\nand registers on it all functions in the list <code>l</code>.\nIf there is a table in <code>package.loaded[libname]</code> or in\nvariable <code>libname</code>,\nreuses this table instead of creating a new one.\n\n\n<p>\nIn any case the function leaves the table\non the top of the stack.\n\n\n\n\n\n<hr><h3><a name=\"luaL_typename\"><code>luaL_typename</code></a></h3><p>\n<span class=\"apii\">[-0, +0, <em>-</em>]</span>\n<pre>const char *luaL_typename (lua_State *L, int index);</pre>\n\n<p>\nReturns the name of the type of the value at the given index.\n\n\n\n\n\n<hr><h3><a name=\"luaL_typerror\"><code>luaL_typerror</code></a></h3><p>\n<span class=\"apii\">[-0, +0, <em>v</em>]</span>\n<pre>int luaL_typerror (lua_State *L, int narg, const char *tname);</pre>\n\n<p>\nGenerates an error with a message like the following:\n\n<pre>\n     <em>location</em>: bad argument <em>narg</em> to '<em>func</em>' (<em>tname</em> expected, got <em>rt</em>)\n</pre><p>\nwhere <code><em>location</em></code> is produced by <a href=\"#luaL_where\"><code>luaL_where</code></a>,\n<code><em>func</em></code> is the name of the current function,\nand <code><em>rt</em></code> is the type name of the actual argument.\n\n\n\n\n\n<hr><h3><a name=\"luaL_unref\"><code>luaL_unref</code></a></h3><p>\n<span class=\"apii\">[-0, +0, <em>-</em>]</span>\n<pre>void luaL_unref (lua_State *L, int t, int ref);</pre>\n\n<p>\nReleases reference <code>ref</code> from the table at index <code>t</code>\n(see <a href=\"#luaL_ref\"><code>luaL_ref</code></a>).\nThe entry is removed from the table,\nso that the referred object can be collected.\nThe reference <code>ref</code> is also freed to be used again.\n\n\n<p>\nIf <code>ref</code> is <a href=\"#pdf-LUA_NOREF\"><code>LUA_NOREF</code></a> or <a href=\"#pdf-LUA_REFNIL\"><code>LUA_REFNIL</code></a>,\n<a href=\"#luaL_unref\"><code>luaL_unref</code></a> does nothing.\n\n\n\n\n\n<hr><h3><a name=\"luaL_where\"><code>luaL_where</code></a></h3><p>\n<span class=\"apii\">[-0, +1, <em>m</em>]</span>\n<pre>void luaL_where (lua_State *L, int lvl);</pre>\n\n<p>\nPushes onto the stack a string identifying the current position\nof the control at level <code>lvl</code> in the call stack.\nTypically this string has the following format:\n\n<pre>\n     <em>chunkname</em>:<em>currentline</em>:\n</pre><p>\nLevel&nbsp;0 is the running function,\nlevel&nbsp;1 is the function that called the running function,\netc.\n\n\n<p>\nThis function is used to build a prefix for error messages.\n\n\n\n\n\n\n\n<h1>5 - <a name=\"5\">Standard Libraries</a></h1>\n\n<p>\nThe standard Lua libraries provide useful functions\nthat are implemented directly through the C&nbsp;API.\nSome of these functions provide essential services to the language\n(e.g., <a href=\"#pdf-type\"><code>type</code></a> and <a href=\"#pdf-getmetatable\"><code>getmetatable</code></a>);\nothers provide access to \"outside\" services (e.g., I/O);\nand others could be implemented in Lua itself,\nbut are quite useful or have critical performance requirements that\ndeserve an implementation in C (e.g., <a href=\"#pdf-table.sort\"><code>table.sort</code></a>).\n\n\n<p>\nAll libraries are implemented through the official C&nbsp;API\nand are provided as separate C&nbsp;modules.\nCurrently, Lua has the following standard libraries:\n\n<ul>\n\n<li>basic library, which includes the coroutine sub-library;</li>\n\n<li>package library;</li>\n\n<li>string manipulation;</li>\n\n<li>table manipulation;</li>\n\n<li>mathematical functions (sin, log, etc.);</li>\n\n<li>input and output;</li>\n\n<li>operating system facilities;</li>\n\n<li>debug facilities.</li>\n\n</ul><p>\nExcept for the basic and package libraries,\neach library provides all its functions as fields of a global table\nor as methods of its objects.\n\n\n<p>\nTo have access to these libraries,\nthe C&nbsp;host program should call the <a href=\"#luaL_openlibs\"><code>luaL_openlibs</code></a> function,\nwhich opens all standard libraries.\nAlternatively,\nit can open them individually by calling\n<a name=\"pdf-luaopen_base\"><code>luaopen_base</code></a> (for the basic library),\n<a name=\"pdf-luaopen_package\"><code>luaopen_package</code></a> (for the package library),\n<a name=\"pdf-luaopen_string\"><code>luaopen_string</code></a> (for the string library),\n<a name=\"pdf-luaopen_table\"><code>luaopen_table</code></a> (for the table library),\n<a name=\"pdf-luaopen_math\"><code>luaopen_math</code></a> (for the mathematical library),\n<a name=\"pdf-luaopen_io\"><code>luaopen_io</code></a> (for the I/O library),\n<a name=\"pdf-luaopen_os\"><code>luaopen_os</code></a> (for the Operating System library),\nand <a name=\"pdf-luaopen_debug\"><code>luaopen_debug</code></a> (for the debug library).\nThese functions are declared in <a name=\"pdf-lualib.h\"><code>lualib.h</code></a>\nand should not be called directly:\nyou must call them like any other Lua C&nbsp;function,\ne.g., by using <a href=\"#lua_call\"><code>lua_call</code></a>.\n\n\n\n<h2>5.1 - <a name=\"5.1\">Basic Functions</a></h2>\n\n<p>\nThe basic library provides some core functions to Lua.\nIf you do not include this library in your application,\nyou should check carefully whether you need to provide \nimplementations for some of its facilities.\n\n\n<p>\n<hr><h3><a name=\"pdf-assert\"><code>assert (v [, message])</code></a></h3>\nIssues an  error when\nthe value of its argument <code>v</code> is false (i.e., <b>nil</b> or <b>false</b>);\notherwise, returns all its arguments.\n<code>message</code> is an error message;\nwhen absent, it defaults to \"assertion failed!\"\n\n\n\n\n<p>\n<hr><h3><a name=\"pdf-collectgarbage\"><code>collectgarbage ([opt [, arg]])</code></a></h3>\n\n\n<p>\nThis function is a generic interface to the garbage collector.\nIt performs different functions according to its first argument, <code>opt</code>:\n\n<ul>\n\n<li><b>\"collect\":</b>\nperforms a full garbage-collection cycle.\nThis is the default option.\n</li>\n\n<li><b>\"stop\":</b>\nstops the garbage collector.\n</li>\n\n<li><b>\"restart\":</b>\nrestarts the garbage collector.\n</li>\n\n<li><b>\"count\":</b>\nreturns the total memory in use by Lua (in Kbytes).\n</li>\n\n<li><b>\"step\":</b>\nperforms a garbage-collection step.\nThe step \"size\" is controlled by <code>arg</code>\n(larger values mean more steps) in a non-specified way.\nIf you want to control the step size\nyou must experimentally tune the value of <code>arg</code>.\nReturns <b>true</b> if the step finished a collection cycle.\n</li>\n\n<li><b>\"setpause\":</b>\nsets <code>arg</code> as the new value for the <em>pause</em> of\nthe collector (see <a href=\"#2.10\">&sect;2.10</a>).\nReturns the previous value for <em>pause</em>.\n</li>\n\n<li><b>\"setstepmul\":</b>\nsets <code>arg</code> as the new value for the <em>step multiplier</em> of\nthe collector (see <a href=\"#2.10\">&sect;2.10</a>).\nReturns the previous value for <em>step</em>.\n</li>\n\n</ul>\n\n\n\n<p>\n<hr><h3><a name=\"pdf-dofile\"><code>dofile ([filename])</code></a></h3>\nOpens the named file and executes its contents as a Lua chunk.\nWhen called without arguments,\n<code>dofile</code> executes the contents of the standard input (<code>stdin</code>).\nReturns all values returned by the chunk.\nIn case of errors, <code>dofile</code> propagates the error\nto its caller (that is, <code>dofile</code> does not run in protected mode).\n\n\n\n\n<p>\n<hr><h3><a name=\"pdf-error\"><code>error (message [, level])</code></a></h3>\nTerminates the last protected function called\nand returns <code>message</code> as the error message.\nFunction <code>error</code> never returns.\n\n\n<p>\nUsually, <code>error</code> adds some information about the error position\nat the beginning of the message.\nThe <code>level</code> argument specifies how to get the error position.\nWith level&nbsp;1 (the default), the error position is where the\n<code>error</code> function was called.\nLevel&nbsp;2 points the error to where the function\nthat called <code>error</code> was called; and so on.\nPassing a level&nbsp;0 avoids the addition of error position information\nto the message.\n\n\n\n\n<p>\n<hr><h3><a name=\"pdf-_G\"><code>_G</code></a></h3>\nA global variable (not a function) that\nholds the global environment (that is, <code>_G._G = _G</code>).\nLua itself does not use this variable;\nchanging its value does not affect any environment,\nnor vice-versa.\n(Use <a href=\"#pdf-setfenv\"><code>setfenv</code></a> to change environments.)\n\n\n\n\n<p>\n<hr><h3><a name=\"pdf-getfenv\"><code>getfenv ([f])</code></a></h3>\nReturns the current environment in use by the function.\n<code>f</code> can be a Lua function or a number\nthat specifies the function at that stack level:\nLevel&nbsp;1 is the function calling <code>getfenv</code>.\nIf the given function is not a Lua function,\nor if <code>f</code> is 0,\n<code>getfenv</code> returns the global environment.\nThe default for <code>f</code> is 1.\n\n\n\n\n<p>\n<hr><h3><a name=\"pdf-getmetatable\"><code>getmetatable (object)</code></a></h3>\n\n\n<p>\nIf <code>object</code> does not have a metatable, returns <b>nil</b>.\nOtherwise,\nif the object's metatable has a <code>\"__metatable\"</code> field,\nreturns the associated value.\nOtherwise, returns the metatable of the given object.\n\n\n\n\n<p>\n<hr><h3><a name=\"pdf-ipairs\"><code>ipairs (t)</code></a></h3>\n\n\n<p>\nReturns three values: an iterator function, the table <code>t</code>, and 0,\nso that the construction\n\n<pre>\n     for i,v in ipairs(t) do <em>body</em> end\n</pre><p>\nwill iterate over the pairs (<code>1,t[1]</code>), (<code>2,t[2]</code>), &middot;&middot;&middot;,\nup to the first integer key absent from the table.\n\n\n\n\n<p>\n<hr><h3><a name=\"pdf-load\"><code>load (func [, chunkname])</code></a></h3>\n\n\n<p>\nLoads a chunk using function <code>func</code> to get its pieces.\nEach call to <code>func</code> must return a string that concatenates\nwith previous results.\nA return of an empty string, <b>nil</b>, or no value signals the end of the chunk.\n\n\n<p>\nIf there are no errors, \nreturns the compiled chunk as a function;\notherwise, returns <b>nil</b> plus the error message.\nThe environment of the returned function is the global environment.\n\n\n<p>\n<code>chunkname</code> is used as the chunk name for error messages\nand debug information.\nWhen absent,\nit defaults to \"<code>=(load)</code>\".\n\n\n\n\n<p>\n<hr><h3><a name=\"pdf-loadfile\"><code>loadfile ([filename])</code></a></h3>\n\n\n<p>\nSimilar to <a href=\"#pdf-load\"><code>load</code></a>,\nbut gets the chunk from file <code>filename</code>\nor from the standard input,\nif no file name is given.\n\n\n\n\n<p>\n<hr><h3><a name=\"pdf-loadstring\"><code>loadstring (string [, chunkname])</code></a></h3>\n\n\n<p>\nSimilar to <a href=\"#pdf-load\"><code>load</code></a>,\nbut gets the chunk from the given string.\n\n\n<p>\nTo load and run a given string, use the idiom\n\n<pre>\n     assert(loadstring(s))()\n</pre>\n\n<p>\nWhen absent,\n<code>chunkname</code> defaults to the given string.\n\n\n\n\n<p>\n<hr><h3><a name=\"pdf-next\"><code>next (table [, index])</code></a></h3>\n\n\n<p>\nAllows a program to traverse all fields of a table.\nIts first argument is a table and its second argument\nis an index in this table.\n<code>next</code> returns the next index of the table\nand its associated value.\nWhen called with <b>nil</b> as its second argument,\n<code>next</code> returns an initial index\nand its associated value.\nWhen called with the last index,\nor with <b>nil</b> in an empty table,\n<code>next</code> returns <b>nil</b>.\nIf the second argument is absent, then it is interpreted as <b>nil</b>.\nIn particular,\nyou can use <code>next(t)</code> to check whether a table is empty.\n\n\n<p>\nThe order in which the indices are enumerated is not specified,\n<em>even for numeric indices</em>.\n(To traverse a table in numeric order,\nuse a numerical <b>for</b> or the <a href=\"#pdf-ipairs\"><code>ipairs</code></a> function.)\n\n\n<p>\nThe behavior of <code>next</code> is <em>undefined</em> if,\nduring the traversal,\nyou assign any value to a non-existent field in the table.\nYou may however modify existing fields.\nIn particular, you may clear existing fields.\n\n\n\n\n<p>\n<hr><h3><a name=\"pdf-pairs\"><code>pairs (t)</code></a></h3>\n\n\n<p>\nReturns three values: the <a href=\"#pdf-next\"><code>next</code></a> function, the table <code>t</code>, and <b>nil</b>,\nso that the construction\n\n<pre>\n     for k,v in pairs(t) do <em>body</em> end\n</pre><p>\nwill iterate over all key&ndash;value pairs of table <code>t</code>.\n\n\n<p>\nSee function <a href=\"#pdf-next\"><code>next</code></a> for the caveats of modifying\nthe table during its traversal.\n\n\n\n\n<p>\n<hr><h3><a name=\"pdf-pcall\"><code>pcall (f, arg1, &middot;&middot;&middot;)</code></a></h3>\n\n\n<p>\nCalls function <code>f</code> with\nthe given arguments in <em>protected mode</em>.\nThis means that any error inside&nbsp;<code>f</code> is not propagated;\ninstead, <code>pcall</code> catches the error\nand returns a status code.\nIts first result is the status code (a boolean),\nwhich is true if the call succeeds without errors.\nIn such case, <code>pcall</code> also returns all results from the call,\nafter this first result.\nIn case of any error, <code>pcall</code> returns <b>false</b> plus the error message.\n\n\n\n\n<p>\n<hr><h3><a name=\"pdf-print\"><code>print (&middot;&middot;&middot;)</code></a></h3>\nReceives any number of arguments,\nand prints their values to <code>stdout</code>,\nusing the <a href=\"#pdf-tostring\"><code>tostring</code></a> function to convert them to strings.\n<code>print</code> is not intended for formatted output,\nbut only as a quick way to show a value,\ntypically for debugging.\nFor formatted output, use <a href=\"#pdf-string.format\"><code>string.format</code></a>.\n\n\n\n\n<p>\n<hr><h3><a name=\"pdf-rawequal\"><code>rawequal (v1, v2)</code></a></h3>\nChecks whether <code>v1</code> is equal to <code>v2</code>,\nwithout invoking any metamethod.\nReturns a boolean.\n\n\n\n\n<p>\n<hr><h3><a name=\"pdf-rawget\"><code>rawget (table, index)</code></a></h3>\nGets the real value of <code>table[index]</code>,\nwithout invoking any metamethod.\n<code>table</code> must be a table;\n<code>index</code> may be any value.\n\n\n\n\n<p>\n<hr><h3><a name=\"pdf-rawset\"><code>rawset (table, index, value)</code></a></h3>\nSets the real value of <code>table[index]</code> to <code>value</code>,\nwithout invoking any metamethod.\n<code>table</code> must be a table,\n<code>index</code> any value different from <b>nil</b>,\nand <code>value</code> any Lua value.\n\n\n<p>\nThis function returns <code>table</code>.\n\n\n\n\n<p>\n<hr><h3><a name=\"pdf-select\"><code>select (index, &middot;&middot;&middot;)</code></a></h3>\n\n\n<p>\nIf <code>index</code> is a number,\nreturns all arguments after argument number <code>index</code>.\nOtherwise, <code>index</code> must be the string <code>\"#\"</code>,\nand <code>select</code> returns the total number of extra arguments it received.\n\n\n\n\n<p>\n<hr><h3><a name=\"pdf-setfenv\"><code>setfenv (f, table)</code></a></h3>\n\n\n<p>\nSets the environment to be used by the given function.\n<code>f</code> can be a Lua function or a number\nthat specifies the function at that stack level:\nLevel&nbsp;1 is the function calling <code>setfenv</code>.\n<code>setfenv</code> returns the given function.\n\n\n<p>\nAs a special case, when <code>f</code> is 0 <code>setfenv</code> changes\nthe environment of the running thread.\nIn this case, <code>setfenv</code> returns no values.\n\n\n\n\n<p>\n<hr><h3><a name=\"pdf-setmetatable\"><code>setmetatable (table, metatable)</code></a></h3>\n\n\n<p>\nSets the metatable for the given table.\n(You cannot change the metatable of other types from Lua, only from&nbsp;C.)\nIf <code>metatable</code> is <b>nil</b>,\nremoves the metatable of the given table.\nIf the original metatable has a <code>\"__metatable\"</code> field,\nraises an error.\n\n\n<p>\nThis function returns <code>table</code>.\n\n\n\n\n<p>\n<hr><h3><a name=\"pdf-tonumber\"><code>tonumber (e [, base])</code></a></h3>\nTries to convert its argument to a number.\nIf the argument is already a number or a string convertible\nto a number, then <code>tonumber</code> returns this number;\notherwise, it returns <b>nil</b>.\n\n\n<p>\nAn optional argument specifies the base to interpret the numeral.\nThe base may be any integer between 2 and 36, inclusive.\nIn bases above&nbsp;10, the letter '<code>A</code>' (in either upper or lower case)\nrepresents&nbsp;10, '<code>B</code>' represents&nbsp;11, and so forth,\nwith '<code>Z</code>' representing 35.\nIn base 10 (the default), the number can have a decimal part,\nas well as an optional exponent part (see <a href=\"#2.1\">&sect;2.1</a>).\nIn other bases, only unsigned integers are accepted.\n\n\n\n\n<p>\n<hr><h3><a name=\"pdf-tostring\"><code>tostring (e)</code></a></h3>\nReceives an argument of any type and\nconverts it to a string in a reasonable format.\nFor complete control of how numbers are converted,\nuse <a href=\"#pdf-string.format\"><code>string.format</code></a>.\n\n\n<p>\nIf the metatable of <code>e</code> has a <code>\"__tostring\"</code> field,\nthen <code>tostring</code> calls the corresponding value\nwith <code>e</code> as argument,\nand uses the result of the call as its result.\n\n\n\n\n<p>\n<hr><h3><a name=\"pdf-type\"><code>type (v)</code></a></h3>\nReturns the type of its only argument, coded as a string.\nThe possible results of this function are\n\"<code>nil</code>\" (a string, not the value <b>nil</b>),\n\"<code>number</code>\",\n\"<code>string</code>\",\n\"<code>boolean</code>\",\n\"<code>table</code>\",\n\"<code>function</code>\",\n\"<code>thread</code>\",\nand \"<code>userdata</code>\".\n\n\n\n\n<p>\n<hr><h3><a name=\"pdf-unpack\"><code>unpack (list [, i [, j]])</code></a></h3>\nReturns the elements from the given table.\nThis function is equivalent to\n\n<pre>\n     return list[i], list[i+1], &middot;&middot;&middot;, list[j]\n</pre><p>\nexcept that the above code can be written only for a fixed number\nof elements.\nBy default, <code>i</code> is&nbsp;1 and <code>j</code> is the length of the list,\nas defined by the length operator (see <a href=\"#2.5.5\">&sect;2.5.5</a>).\n\n\n\n\n<p>\n<hr><h3><a name=\"pdf-_VERSION\"><code>_VERSION</code></a></h3>\nA global variable (not a function) that\nholds a string containing the current interpreter version.\nThe current contents of this variable is \"<code>Lua 5.1</code>\".\n\n\n\n\n<p>\n<hr><h3><a name=\"pdf-xpcall\"><code>xpcall (f, err)</code></a></h3>\n\n\n<p>\nThis function is similar to <a href=\"#pdf-pcall\"><code>pcall</code></a>,\nexcept that you can set a new error handler.\n\n\n<p>\n<code>xpcall</code> calls function <code>f</code> in protected mode,\nusing <code>err</code> as the error handler.\nAny error inside <code>f</code> is not propagated;\ninstead, <code>xpcall</code> catches the error,\ncalls the <code>err</code> function with the original error object,\nand returns a status code.\nIts first result is the status code (a boolean),\nwhich is true if the call succeeds without errors.\nIn this case, <code>xpcall</code> also returns all results from the call,\nafter this first result.\nIn case of any error,\n<code>xpcall</code> returns <b>false</b> plus the result from <code>err</code>.\n\n\n\n\n\n\n\n<h2>5.2 - <a name=\"5.2\">Coroutine Manipulation</a></h2>\n\n<p>\nThe operations related to coroutines comprise a sub-library of\nthe basic library and come inside the table <a name=\"pdf-coroutine\"><code>coroutine</code></a>.\nSee <a href=\"#2.11\">&sect;2.11</a> for a general description of coroutines.\n\n\n<p>\n<hr><h3><a name=\"pdf-coroutine.create\"><code>coroutine.create (f)</code></a></h3>\n\n\n<p>\nCreates a new coroutine, with body <code>f</code>.\n<code>f</code> must be a Lua function.\nReturns this new coroutine,\nan object with type <code>\"thread\"</code>.\n\n\n\n\n<p>\n<hr><h3><a name=\"pdf-coroutine.resume\"><code>coroutine.resume (co [, val1, &middot;&middot;&middot;])</code></a></h3>\n\n\n<p>\nStarts or continues the execution of coroutine <code>co</code>.\nThe first time you resume a coroutine,\nit starts running its body.\nThe values <code>val1</code>, &middot;&middot;&middot; are passed\nas the arguments to the body function.\nIf the coroutine has yielded,\n<code>resume</code> restarts it;\nthe values <code>val1</code>, &middot;&middot;&middot; are passed\nas the results from the yield.\n\n\n<p>\nIf the coroutine runs without any errors,\n<code>resume</code> returns <b>true</b> plus any values passed to <code>yield</code>\n(if the coroutine yields) or any values returned by the body function\n(if the coroutine terminates).\nIf there is any error,\n<code>resume</code> returns <b>false</b> plus the error message.\n\n\n\n\n<p>\n<hr><h3><a name=\"pdf-coroutine.running\"><code>coroutine.running ()</code></a></h3>\n\n\n<p>\nReturns the running coroutine,\nor <b>nil</b> when called by the main thread.\n\n\n\n\n<p>\n<hr><h3><a name=\"pdf-coroutine.status\"><code>coroutine.status (co)</code></a></h3>\n\n\n<p>\nReturns the status of coroutine <code>co</code>, as a string:\n<code>\"running\"</code>,\nif the coroutine is running (that is, it called <code>status</code>);\n<code>\"suspended\"</code>, if the coroutine is suspended in a call to <code>yield</code>,\nor if it has not started running yet;\n<code>\"normal\"</code> if the coroutine is active but not running\n(that is, it has resumed another coroutine);\nand <code>\"dead\"</code> if the coroutine has finished its body function,\nor if it has stopped with an error.\n\n\n\n\n<p>\n<hr><h3><a name=\"pdf-coroutine.wrap\"><code>coroutine.wrap (f)</code></a></h3>\n\n\n<p>\nCreates a new coroutine, with body <code>f</code>.\n<code>f</code> must be a Lua function.\nReturns a function that resumes the coroutine each time it is called.\nAny arguments passed to the function behave as the\nextra arguments to <code>resume</code>.\nReturns the same values returned by <code>resume</code>,\nexcept the first boolean.\nIn case of error, propagates the error.\n\n\n\n\n<p>\n<hr><h3><a name=\"pdf-coroutine.yield\"><code>coroutine.yield (&middot;&middot;&middot;)</code></a></h3>\n\n\n<p>\nSuspends the execution of the calling coroutine.\nThe coroutine cannot be running a C&nbsp;function,\na metamethod, or an iterator.\nAny arguments to <code>yield</code> are passed as extra results to <code>resume</code>.\n\n\n\n\n\n\n\n<h2>5.3 - <a name=\"5.3\">Modules</a></h2>\n\n<p>\nThe package library provides basic\nfacilities for loading and building modules in Lua.\nIt exports two of its functions directly in the global environment:\n<a href=\"#pdf-require\"><code>require</code></a> and <a href=\"#pdf-module\"><code>module</code></a>.\nEverything else is exported in a table <a name=\"pdf-package\"><code>package</code></a>.\n\n\n<p>\n<hr><h3><a name=\"pdf-module\"><code>module (name [, &middot;&middot;&middot;])</code></a></h3>\n\n\n<p>\nCreates a module.\nIf there is a table in <code>package.loaded[name]</code>,\nthis table is the module.\nOtherwise, if there is a global table <code>t</code> with the given name,\nthis table is the module.\nOtherwise creates a new table <code>t</code> and\nsets it as the value of the global <code>name</code> and\nthe value of <code>package.loaded[name]</code>.\nThis function also initializes <code>t._NAME</code> with the given name,\n<code>t._M</code> with the module (<code>t</code> itself),\nand <code>t._PACKAGE</code> with the package name\n(the full module name minus last component; see below).\nFinally, <code>module</code> sets <code>t</code> as the new environment\nof the current function and the new value of <code>package.loaded[name]</code>,\nso that <a href=\"#pdf-require\"><code>require</code></a> returns <code>t</code>.\n\n\n<p>\nIf <code>name</code> is a compound name\n(that is, one with components separated by dots),\n<code>module</code> creates (or reuses, if they already exist)\ntables for each component.\nFor instance, if <code>name</code> is <code>a.b.c</code>,\nthen <code>module</code> stores the module table in field <code>c</code> of\nfield <code>b</code> of global <code>a</code>.\n\n\n<p>\nThis function can receive optional <em>options</em> after\nthe module name,\nwhere each option is a function to be applied over the module.\n\n\n\n\n<p>\n<hr><h3><a name=\"pdf-require\"><code>require (modname)</code></a></h3>\n\n\n<p>\nLoads the given module.\nThe function starts by looking into the <a href=\"#pdf-package.loaded\"><code>package.loaded</code></a> table\nto determine whether <code>modname</code> is already loaded.\nIf it is, then <code>require</code> returns the value stored\nat <code>package.loaded[modname]</code>.\nOtherwise, it tries to find a <em>loader</em> for the module.\n\n\n<p>\nTo find a loader,\n<code>require</code> is guided by the <a href=\"#pdf-package.loaders\"><code>package.loaders</code></a> array.\nBy changing this array,\nwe can change how <code>require</code> looks for a module.\nThe following explanation is based on the default configuration\nfor <a href=\"#pdf-package.loaders\"><code>package.loaders</code></a>.\n\n\n<p>\nFirst <code>require</code> queries <code>package.preload[modname]</code>.\nIf it has a value,\nthis value (which should be a function) is the loader.\nOtherwise <code>require</code> searches for a Lua loader using the\npath stored in <a href=\"#pdf-package.path\"><code>package.path</code></a>.\nIf that also fails, it searches for a C&nbsp;loader using the\npath stored in <a href=\"#pdf-package.cpath\"><code>package.cpath</code></a>.\nIf that also fails,\nit tries an <em>all-in-one</em> loader (see <a href=\"#pdf-package.loaders\"><code>package.loaders</code></a>).\n\n\n<p>\nOnce a loader is found,\n<code>require</code> calls the loader with a single argument, <code>modname</code>.\nIf the loader returns any value,\n<code>require</code> assigns the returned value to <code>package.loaded[modname]</code>.\nIf the loader returns no value and\nhas not assigned any value to <code>package.loaded[modname]</code>,\nthen <code>require</code> assigns <b>true</b> to this entry.\nIn any case, <code>require</code> returns the\nfinal value of <code>package.loaded[modname]</code>.\n\n\n<p>\nIf there is any error loading or running the module,\nor if it cannot find any loader for the module,\nthen <code>require</code> signals an error. \n\n\n\n\n<p>\n<hr><h3><a name=\"pdf-package.cpath\"><code>package.cpath</code></a></h3>\n\n\n<p>\nThe path used by <a href=\"#pdf-require\"><code>require</code></a> to search for a C&nbsp;loader.\n\n\n<p>\nLua initializes the C&nbsp;path <a href=\"#pdf-package.cpath\"><code>package.cpath</code></a> in the same way\nit initializes the Lua path <a href=\"#pdf-package.path\"><code>package.path</code></a>,\nusing the environment variable <a name=\"pdf-LUA_CPATH\"><code>LUA_CPATH</code></a>\nor a default path defined in <code>luaconf.h</code>.\n\n\n\n\n<p>\n\n<hr><h3><a name=\"pdf-package.loaded\"><code>package.loaded</code></a></h3>\n\n\n<p>\nA table used by <a href=\"#pdf-require\"><code>require</code></a> to control which\nmodules are already loaded.\nWhen you require a module <code>modname</code> and\n<code>package.loaded[modname]</code> is not false,\n<a href=\"#pdf-require\"><code>require</code></a> simply returns the value stored there.\n\n\n\n\n<p>\n<hr><h3><a name=\"pdf-package.loaders\"><code>package.loaders</code></a></h3>\n\n\n<p>\nA table used by <a href=\"#pdf-require\"><code>require</code></a> to control how to load modules.\n\n\n<p>\nEach entry in this table is a <em>searcher function</em>.\nWhen looking for a module,\n<a href=\"#pdf-require\"><code>require</code></a> calls each of these searchers in ascending order,\nwith the module name (the argument given to <a href=\"#pdf-require\"><code>require</code></a>) as its\nsole parameter.\nThe function can return another function (the module <em>loader</em>)\nor a string explaining why it did not find that module\n(or <b>nil</b> if it has nothing to say).\nLua initializes this table with four functions.\n\n\n<p>\nThe first searcher simply looks for a loader in the\n<a href=\"#pdf-package.preload\"><code>package.preload</code></a> table.\n\n\n<p>\nThe second searcher looks for a loader as a Lua library,\nusing the path stored at <a href=\"#pdf-package.path\"><code>package.path</code></a>.\nA path is a sequence of <em>templates</em> separated by semicolons.\nFor each template,\nthe searcher will change each interrogation\nmark in the template by <code>filename</code>,\nwhich is the module name with each dot replaced by a\n\"directory separator\" (such as \"<code>/</code>\" in Unix);\nthen it will try to open the resulting file name.\nSo, for instance, if the Lua path is the string\n\n<pre>\n     \"./?.lua;./?.lc;/usr/local/?/init.lua\"\n</pre><p>\nthe search for a Lua file for module <code>foo</code>\nwill try to open the files\n<code>./foo.lua</code>, <code>./foo.lc</code>, and\n<code>/usr/local/foo/init.lua</code>, in that order.\n\n\n<p>\nThe third searcher looks for a loader as a C&nbsp;library,\nusing the path given by the variable <a href=\"#pdf-package.cpath\"><code>package.cpath</code></a>.\nFor instance,\nif the C&nbsp;path is the string\n\n<pre>\n     \"./?.so;./?.dll;/usr/local/?/init.so\"\n</pre><p>\nthe searcher for module <code>foo</code>\nwill try to open the files <code>./foo.so</code>, <code>./foo.dll</code>,\nand <code>/usr/local/foo/init.so</code>, in that order.\nOnce it finds a C&nbsp;library,\nthis searcher first uses a dynamic link facility to link the\napplication with the library.\nThen it tries to find a C&nbsp;function inside the library to\nbe used as the loader.\nThe name of this C&nbsp;function is the string \"<code>luaopen_</code>\"\nconcatenated with a copy of the module name where each dot\nis replaced by an underscore.\nMoreover, if the module name has a hyphen,\nits prefix up to (and including) the first hyphen is removed.\nFor instance, if the module name is <code>a.v1-b.c</code>,\nthe function name will be <code>luaopen_b_c</code>.\n\n\n<p>\nThe fourth searcher tries an <em>all-in-one loader</em>.\nIt searches the C&nbsp;path for a library for\nthe root name of the given module.\nFor instance, when requiring <code>a.b.c</code>,\nit will search for a C&nbsp;library for <code>a</code>.\nIf found, it looks into it for an open function for\nthe submodule;\nin our example, that would be <code>luaopen_a_b_c</code>.\nWith this facility, a package can pack several C&nbsp;submodules\ninto one single library,\nwith each submodule keeping its original open function.\n\n\n\n\n<p>\n<hr><h3><a name=\"pdf-package.loadlib\"><code>package.loadlib (libname, funcname)</code></a></h3>\n\n\n<p>\nDynamically links the host program with the C&nbsp;library <code>libname</code>.\nInside this library, looks for a function <code>funcname</code>\nand returns this function as a C&nbsp;function.\n(So, <code>funcname</code> must follow the protocol (see <a href=\"#lua_CFunction\"><code>lua_CFunction</code></a>)).\n\n\n<p>\nThis is a low-level function.\nIt completely bypasses the package and module system.\nUnlike <a href=\"#pdf-require\"><code>require</code></a>,\nit does not perform any path searching and\ndoes not automatically adds extensions.\n<code>libname</code> must be the complete file name of the C&nbsp;library,\nincluding if necessary a path and extension.\n<code>funcname</code> must be the exact name exported by the C&nbsp;library\n(which may depend on the C&nbsp;compiler and linker used).\n\n\n<p>\nThis function is not supported by ANSI C.\nAs such, it is only available on some platforms\n(Windows, Linux, Mac OS X, Solaris, BSD,\nplus other Unix systems that support the <code>dlfcn</code> standard).\n\n\n\n\n<p>\n<hr><h3><a name=\"pdf-package.path\"><code>package.path</code></a></h3>\n\n\n<p>\nThe path used by <a href=\"#pdf-require\"><code>require</code></a> to search for a Lua loader.\n\n\n<p>\nAt start-up, Lua initializes this variable with\nthe value of the environment variable <a name=\"pdf-LUA_PATH\"><code>LUA_PATH</code></a> or\nwith a default path defined in <code>luaconf.h</code>,\nif the environment variable is not defined.\nAny \"<code>;;</code>\" in the value of the environment variable\nis replaced by the default path.\n\n\n\n\n<p>\n<hr><h3><a name=\"pdf-package.preload\"><code>package.preload</code></a></h3>\n\n\n<p>\nA table to store loaders for specific modules\n(see <a href=\"#pdf-require\"><code>require</code></a>).\n\n\n\n\n<p>\n<hr><h3><a name=\"pdf-package.seeall\"><code>package.seeall (module)</code></a></h3>\n\n\n<p>\nSets a metatable for <code>module</code> with\nits <code>__index</code> field referring to the global environment,\nso that this module inherits values\nfrom the global environment.\nTo be used as an option to function <a href=\"#pdf-module\"><code>module</code></a>.\n\n\n\n\n\n\n\n<h2>5.4 - <a name=\"5.4\">String Manipulation</a></h2>\n\n<p>\nThis library provides generic functions for string manipulation,\nsuch as finding and extracting substrings, and pattern matching.\nWhen indexing a string in Lua, the first character is at position&nbsp;1\n(not at&nbsp;0, as in C).\nIndices are allowed to be negative and are interpreted as indexing backwards,\nfrom the end of the string.\nThus, the last character is at position -1, and so on.\n\n\n<p>\nThe string library provides all its functions inside the table\n<a name=\"pdf-string\"><code>string</code></a>.\nIt also sets a metatable for strings\nwhere the <code>__index</code> field points to the <code>string</code> table.\nTherefore, you can use the string functions in object-oriented style.\nFor instance, <code>string.byte(s, i)</code>\ncan be written as <code>s:byte(i)</code>.\n\n\n<p>\nThe string library assumes one-byte character encodings.\n\n\n<p>\n<hr><h3><a name=\"pdf-string.byte\"><code>string.byte (s [, i [, j]])</code></a></h3>\nReturns the internal numerical codes of the characters <code>s[i]</code>,\n<code>s[i+1]</code>, &middot;&middot;&middot;, <code>s[j]</code>.\nThe default value for <code>i</code> is&nbsp;1;\nthe default value for <code>j</code> is&nbsp;<code>i</code>.\n\n\n<p>\nNote that numerical codes are not necessarily portable across platforms.\n\n\n\n\n<p>\n<hr><h3><a name=\"pdf-string.char\"><code>string.char (&middot;&middot;&middot;)</code></a></h3>\nReceives zero or more integers.\nReturns a string with length equal to the number of arguments,\nin which each character has the internal numerical code equal\nto its corresponding argument.\n\n\n<p>\nNote that numerical codes are not necessarily portable across platforms.\n\n\n\n\n<p>\n<hr><h3><a name=\"pdf-string.dump\"><code>string.dump (function)</code></a></h3>\n\n\n<p>\nReturns a string containing a binary representation of the given function,\nso that a later <a href=\"#pdf-loadstring\"><code>loadstring</code></a> on this string returns\na copy of the function.\n<code>function</code> must be a Lua function without upvalues.\n\n\n\n\n<p>\n<hr><h3><a name=\"pdf-string.find\"><code>string.find (s, pattern [, init [, plain]])</code></a></h3>\nLooks for the first match of\n<code>pattern</code> in the string <code>s</code>.\nIf it finds a match, then <code>find</code> returns the indices of&nbsp;<code>s</code>\nwhere this occurrence starts and ends;\notherwise, it returns <b>nil</b>.\nA third, optional numerical argument <code>init</code> specifies\nwhere to start the search;\nits default value is&nbsp;1 and can be negative.\nA value of <b>true</b> as a fourth, optional argument <code>plain</code>\nturns off the pattern matching facilities,\nso the function does a plain \"find substring\" operation,\nwith no characters in <code>pattern</code> being considered \"magic\".\nNote that if <code>plain</code> is given, then <code>init</code> must be given as well.\n\n\n<p>\nIf the pattern has captures,\nthen in a successful match\nthe captured values are also returned,\nafter the two indices.\n\n\n\n\n<p>\n<hr><h3><a name=\"pdf-string.format\"><code>string.format (formatstring, &middot;&middot;&middot;)</code></a></h3>\nReturns a formatted version of its variable number of arguments\nfollowing the description given in its first argument (which must be a string).\nThe format string follows the same rules as the <code>printf</code> family of\nstandard C&nbsp;functions.\nThe only differences are that the options/modifiers\n<code>*</code>, <code>l</code>, <code>L</code>, <code>n</code>, <code>p</code>,\nand <code>h</code> are not supported\nand that there is an extra option, <code>q</code>.\nThe <code>q</code> option formats a string in a form suitable to be safely read\nback by the Lua interpreter:\nthe string is written between double quotes,\nand all double quotes, newlines, embedded zeros,\nand backslashes in the string\nare correctly escaped when written.\nFor instance, the call\n\n<pre>\n     string.format('%q', 'a string with \"quotes\" and \\n new line')\n</pre><p>\nwill produce the string:\n\n<pre>\n     \"a string with \\\"quotes\\\" and \\\n      new line\"\n</pre>\n\n<p>\nThe options <code>c</code>, <code>d</code>, <code>E</code>, <code>e</code>, <code>f</code>,\n<code>g</code>, <code>G</code>, <code>i</code>, <code>o</code>, <code>u</code>, <code>X</code>, and <code>x</code> all\nexpect a number as argument,\nwhereas <code>q</code> and <code>s</code> expect a string.\n\n\n<p>\nThis function does not accept string values\ncontaining embedded zeros,\nexcept as arguments to the <code>q</code> option.\n\n\n\n\n<p>\n<hr><h3><a name=\"pdf-string.gmatch\"><code>string.gmatch (s, pattern)</code></a></h3>\nReturns an iterator function that,\neach time it is called,\nreturns the next captures from <code>pattern</code> over string <code>s</code>.\nIf <code>pattern</code> specifies no captures,\nthen the whole match is produced in each call.\n\n\n<p>\nAs an example, the following loop\n\n<pre>\n     s = \"hello world from Lua\"\n     for w in string.gmatch(s, \"%a+\") do\n       print(w)\n     end\n</pre><p>\nwill iterate over all the words from string <code>s</code>,\nprinting one per line.\nThe next example collects all pairs <code>key=value</code> from the\ngiven string into a table:\n\n<pre>\n     t = {}\n     s = \"from=world, to=Lua\"\n     for k, v in string.gmatch(s, \"(%w+)=(%w+)\") do\n       t[k] = v\n     end\n</pre>\n\n<p>\nFor this function, a '<code>^</code>' at the start of a pattern does not\nwork as an anchor, as this would prevent the iteration.\n\n\n\n\n<p>\n<hr><h3><a name=\"pdf-string.gsub\"><code>string.gsub (s, pattern, repl [, n])</code></a></h3>\nReturns a copy of <code>s</code>\nin which all (or the first <code>n</code>, if given)\noccurrences of the <code>pattern</code> have been\nreplaced by a replacement string specified by <code>repl</code>,\nwhich can be a string, a table, or a function.\n<code>gsub</code> also returns, as its second value,\nthe total number of matches that occurred.\n\n\n<p>\nIf <code>repl</code> is a string, then its value is used for replacement.\nThe character&nbsp;<code>%</code> works as an escape character:\nany sequence in <code>repl</code> of the form <code>%<em>n</em></code>,\nwith <em>n</em> between 1 and 9,\nstands for the value of the <em>n</em>-th captured substring (see below).\nThe sequence <code>%0</code> stands for the whole match.\nThe sequence <code>%%</code> stands for a single&nbsp;<code>%</code>.\n\n\n<p>\nIf <code>repl</code> is a table, then the table is queried for every match,\nusing the first capture as the key;\nif the pattern specifies no captures,\nthen the whole match is used as the key.\n\n\n<p>\nIf <code>repl</code> is a function, then this function is called every time a\nmatch occurs, with all captured substrings passed as arguments,\nin order;\nif the pattern specifies no captures,\nthen the whole match is passed as a sole argument.\n\n\n<p>\nIf the value returned by the table query or by the function call\nis a string or a number,\nthen it is used as the replacement string;\notherwise, if it is <b>false</b> or <b>nil</b>,\nthen there is no replacement\n(that is, the original match is kept in the string).\n\n\n<p>\nHere are some examples:\n\n<pre>\n     x = string.gsub(\"hello world\", \"(%w+)\", \"%1 %1\")\n     --&gt; x=\"hello hello world world\"\n     \n     x = string.gsub(\"hello world\", \"%w+\", \"%0 %0\", 1)\n     --&gt; x=\"hello hello world\"\n     \n     x = string.gsub(\"hello world from Lua\", \"(%w+)%s*(%w+)\", \"%2 %1\")\n     --&gt; x=\"world hello Lua from\"\n     \n     x = string.gsub(\"home = $HOME, user = $USER\", \"%$(%w+)\", os.getenv)\n     --&gt; x=\"home = /home/roberto, user = roberto\"\n     \n     x = string.gsub(\"4+5 = $return 4+5$\", \"%$(.-)%$\", function (s)\n           return loadstring(s)()\n         end)\n     --&gt; x=\"4+5 = 9\"\n     \n     local t = {name=\"lua\", version=\"5.1\"}\n     x = string.gsub(\"$name-$version.tar.gz\", \"%$(%w+)\", t)\n     --&gt; x=\"lua-5.1.tar.gz\"\n</pre>\n\n\n\n<p>\n<hr><h3><a name=\"pdf-string.len\"><code>string.len (s)</code></a></h3>\nReceives a string and returns its length.\nThe empty string <code>\"\"</code> has length 0.\nEmbedded zeros are counted,\nso <code>\"a\\000bc\\000\"</code> has length 5.\n\n\n\n\n<p>\n<hr><h3><a name=\"pdf-string.lower\"><code>string.lower (s)</code></a></h3>\nReceives a string and returns a copy of this string with all\nuppercase letters changed to lowercase.\nAll other characters are left unchanged.\nThe definition of what an uppercase letter is depends on the current locale.\n\n\n\n\n<p>\n<hr><h3><a name=\"pdf-string.match\"><code>string.match (s, pattern [, init])</code></a></h3>\nLooks for the first <em>match</em> of\n<code>pattern</code> in the string <code>s</code>.\nIf it finds one, then <code>match</code> returns\nthe captures from the pattern;\notherwise it returns <b>nil</b>.\nIf <code>pattern</code> specifies no captures,\nthen the whole match is returned.\nA third, optional numerical argument <code>init</code> specifies\nwhere to start the search;\nits default value is&nbsp;1 and can be negative.\n\n\n\n\n<p>\n<hr><h3><a name=\"pdf-string.rep\"><code>string.rep (s, n)</code></a></h3>\nReturns a string that is the concatenation of <code>n</code> copies of\nthe string <code>s</code>.\n\n\n\n\n<p>\n<hr><h3><a name=\"pdf-string.reverse\"><code>string.reverse (s)</code></a></h3>\nReturns a string that is the string <code>s</code> reversed.\n\n\n\n\n<p>\n<hr><h3><a name=\"pdf-string.sub\"><code>string.sub (s, i [, j])</code></a></h3>\nReturns the substring of <code>s</code> that\nstarts at <code>i</code>  and continues until <code>j</code>;\n<code>i</code> and <code>j</code> can be negative.\nIf <code>j</code> is absent, then it is assumed to be equal to -1\n(which is the same as the string length).\nIn particular,\nthe call <code>string.sub(s,1,j)</code> returns a prefix of <code>s</code>\nwith length <code>j</code>,\nand <code>string.sub(s, -i)</code> returns a suffix of <code>s</code>\nwith length <code>i</code>.\n\n\n\n\n<p>\n<hr><h3><a name=\"pdf-string.upper\"><code>string.upper (s)</code></a></h3>\nReceives a string and returns a copy of this string with all\nlowercase letters changed to uppercase.\nAll other characters are left unchanged.\nThe definition of what a lowercase letter is depends on the current locale.\n\n\n\n<h3>5.4.1 - <a name=\"5.4.1\">Patterns</a></h3>\n\n\n<h4>Character Class:</h4><p>\nA <em>character class</em> is used to represent a set of characters.\nThe following combinations are allowed in describing a character class:\n\n<ul>\n\n<li><b><em>x</em>:</b>\n(where <em>x</em> is not one of the <em>magic characters</em>\n<code>^$()%.[]*+-?</code>)\nrepresents the character <em>x</em> itself.\n</li>\n\n<li><b><code>.</code>:</b> (a dot) represents all characters.</li>\n\n<li><b><code>%a</code>:</b> represents all letters.</li>\n\n<li><b><code>%c</code>:</b> represents all control characters.</li>\n\n<li><b><code>%d</code>:</b> represents all digits.</li>\n\n<li><b><code>%l</code>:</b> represents all lowercase letters.</li>\n\n<li><b><code>%p</code>:</b> represents all punctuation characters.</li>\n\n<li><b><code>%s</code>:</b> represents all space characters.</li>\n\n<li><b><code>%u</code>:</b> represents all uppercase letters.</li>\n\n<li><b><code>%w</code>:</b> represents all alphanumeric characters.</li>\n\n<li><b><code>%x</code>:</b> represents all hexadecimal digits.</li>\n\n<li><b><code>%z</code>:</b> represents the character with representation 0.</li>\n\n<li><b><code>%<em>x</em></code>:</b> (where <em>x</em> is any non-alphanumeric character)\nrepresents the character <em>x</em>.\nThis is the standard way to escape the magic characters.\nAny punctuation character (even the non magic)\ncan be preceded by a '<code>%</code>'\nwhen used to represent itself in a pattern.\n</li>\n\n<li><b><code>[<em>set</em>]</code>:</b>\nrepresents the class which is the union of all\ncharacters in <em>set</em>.\nA range of characters can be specified by\nseparating the end characters of the range with a '<code>-</code>'.\nAll classes <code>%</code><em>x</em> described above can also be used as\ncomponents in <em>set</em>.\nAll other characters in <em>set</em> represent themselves.\nFor example, <code>[%w_]</code> (or <code>[_%w]</code>)\nrepresents all alphanumeric characters plus the underscore,\n<code>[0-7]</code> represents the octal digits,\nand <code>[0-7%l%-]</code> represents the octal digits plus\nthe lowercase letters plus the '<code>-</code>' character.\n\n\n<p>\nThe interaction between ranges and classes is not defined.\nTherefore, patterns like <code>[%a-z]</code> or <code>[a-%%]</code>\nhave no meaning.\n</li>\n\n<li><b><code>[^<em>set</em>]</code>:</b>\nrepresents the complement of <em>set</em>,\nwhere <em>set</em> is interpreted as above.\n</li>\n\n</ul><p>\nFor all classes represented by single letters (<code>%a</code>, <code>%c</code>, etc.),\nthe corresponding uppercase letter represents the complement of the class.\nFor instance, <code>%S</code> represents all non-space characters.\n\n\n<p>\nThe definitions of letter, space, and other character groups\ndepend on the current locale.\nIn particular, the class <code>[a-z]</code> may not be equivalent to <code>%l</code>.\n\n\n\n\n\n<h4>Pattern Item:</h4><p>\nA <em>pattern item</em> can be\n\n<ul>\n\n<li>\na single character class,\nwhich matches any single character in the class;\n</li>\n\n<li>\na single character class followed by '<code>*</code>',\nwhich matches 0 or more repetitions of characters in the class.\nThese repetition items will always match the longest possible sequence;\n</li>\n\n<li>\na single character class followed by '<code>+</code>',\nwhich matches 1 or more repetitions of characters in the class.\nThese repetition items will always match the longest possible sequence;\n</li>\n\n<li>\na single character class followed by '<code>-</code>',\nwhich also matches 0 or more repetitions of characters in the class.\nUnlike '<code>*</code>',\nthese repetition items will always match the <em>shortest</em> possible sequence;\n</li>\n\n<li>\na single character class followed by '<code>?</code>',\nwhich matches 0 or 1 occurrence of a character in the class;\n</li>\n\n<li>\n<code>%<em>n</em></code>, for <em>n</em> between 1 and 9;\nsuch item matches a substring equal to the <em>n</em>-th captured string\n(see below);\n</li>\n\n<li>\n<code>%b<em>xy</em></code>, where <em>x</em> and <em>y</em> are two distinct characters;\nsuch item matches strings that start with&nbsp;<em>x</em>, end with&nbsp;<em>y</em>,\nand where the <em>x</em> and <em>y</em> are <em>balanced</em>.\nThis means that, if one reads the string from left to right,\ncounting <em>+1</em> for an <em>x</em> and <em>-1</em> for a <em>y</em>,\nthe ending <em>y</em> is the first <em>y</em> where the count reaches 0.\nFor instance, the item <code>%b()</code> matches expressions with\nbalanced parentheses.\n</li>\n\n</ul>\n\n\n\n\n<h4>Pattern:</h4><p>\nA <em>pattern</em> is a sequence of pattern items.\nA '<code>^</code>' at the beginning of a pattern anchors the match at the\nbeginning of the subject string.\nA '<code>$</code>' at the end of a pattern anchors the match at the\nend of the subject string.\nAt other positions,\n'<code>^</code>' and '<code>$</code>' have no special meaning and represent themselves.\n\n\n\n\n\n<h4>Captures:</h4><p>\nA pattern can contain sub-patterns enclosed in parentheses;\nthey describe <em>captures</em>.\nWhen a match succeeds, the substrings of the subject string\nthat match captures are stored (<em>captured</em>) for future use.\nCaptures are numbered according to their left parentheses.\nFor instance, in the pattern <code>\"(a*(.)%w(%s*))\"</code>,\nthe part of the string matching <code>\"a*(.)%w(%s*)\"</code> is\nstored as the first capture (and therefore has number&nbsp;1);\nthe character matching \"<code>.</code>\" is captured with number&nbsp;2,\nand the part matching \"<code>%s*</code>\" has number&nbsp;3.\n\n\n<p>\nAs a special case, the empty capture <code>()</code> captures\nthe current string position (a number).\nFor instance, if we apply the pattern <code>\"()aa()\"</code> on the\nstring <code>\"flaaap\"</code>, there will be two captures: 3&nbsp;and&nbsp;5.\n\n\n<p>\nA pattern cannot contain embedded zeros.  Use <code>%z</code> instead.\n\n\n\n\n\n\n\n\n\n\n\n<h2>5.5 - <a name=\"5.5\">Table Manipulation</a></h2><p>\nThis library provides generic functions for table manipulation.\nIt provides all its functions inside the table <a name=\"pdf-table\"><code>table</code></a>.\n\n\n<p>\nMost functions in the table library assume that the table\nrepresents an array or a list.\nFor these functions, when we talk about the \"length\" of a table\nwe mean the result of the length operator.\n\n\n<p>\n<hr><h3><a name=\"pdf-table.concat\"><code>table.concat (table [, sep [, i [, j]]])</code></a></h3>\nGiven an array where all elements are strings or numbers,\nreturns <code>table[i]..sep..table[i+1] &middot;&middot;&middot; sep..table[j]</code>.\nThe default value for <code>sep</code> is the empty string,\nthe default for <code>i</code> is 1,\nand the default for <code>j</code> is the length of the table.\nIf <code>i</code> is greater than <code>j</code>, returns the empty string.\n\n\n\n\n<p>\n<hr><h3><a name=\"pdf-table.insert\"><code>table.insert (table, [pos,] value)</code></a></h3>\n\n\n<p>\nInserts element <code>value</code> at position <code>pos</code> in <code>table</code>,\nshifting up other elements to open space, if necessary.\nThe default value for <code>pos</code> is <code>n+1</code>,\nwhere <code>n</code> is the length of the table (see <a href=\"#2.5.5\">&sect;2.5.5</a>),\nso that a call <code>table.insert(t,x)</code> inserts <code>x</code> at the end\nof table <code>t</code>.\n\n\n\n\n<p>\n<hr><h3><a name=\"pdf-table.maxn\"><code>table.maxn (table)</code></a></h3>\n\n\n<p>\nReturns the largest positive numerical index of the given table,\nor zero if the table has no positive numerical indices.\n(To do its job this function does a linear traversal of\nthe whole table.) \n\n\n\n\n<p>\n<hr><h3><a name=\"pdf-table.remove\"><code>table.remove (table [, pos])</code></a></h3>\n\n\n<p>\nRemoves from <code>table</code> the element at position <code>pos</code>,\nshifting down other elements to close the space, if necessary.\nReturns the value of the removed element.\nThe default value for <code>pos</code> is <code>n</code>,\nwhere <code>n</code> is the length of the table,\nso that a call <code>table.remove(t)</code> removes the last element\nof table <code>t</code>.\n\n\n\n\n<p>\n<hr><h3><a name=\"pdf-table.sort\"><code>table.sort (table [, comp])</code></a></h3>\nSorts table elements in a given order, <em>in-place</em>,\nfrom <code>table[1]</code> to <code>table[n]</code>,\nwhere <code>n</code> is the length of the table.\nIf <code>comp</code> is given,\nthen it must be a function that receives two table elements,\nand returns true\nwhen the first is less than the second\n(so that <code>not comp(a[i+1],a[i])</code> will be true after the sort).\nIf <code>comp</code> is not given,\nthen the standard Lua operator <code>&lt;</code> is used instead.\n\n\n<p>\nThe sort algorithm is not stable;\nthat is, elements considered equal by the given order\nmay have their relative positions changed by the sort.\n\n\n\n\n\n\n\n<h2>5.6 - <a name=\"5.6\">Mathematical Functions</a></h2>\n\n<p>\nThis library is an interface to the standard C&nbsp;math library.\nIt provides all its functions inside the table <a name=\"pdf-math\"><code>math</code></a>.\n\n\n<p>\n<hr><h3><a name=\"pdf-math.abs\"><code>math.abs (x)</code></a></h3>\n\n\n<p>\nReturns the absolute value of <code>x</code>.\n\n\n\n\n<p>\n<hr><h3><a name=\"pdf-math.acos\"><code>math.acos (x)</code></a></h3>\n\n\n<p>\nReturns the arc cosine of <code>x</code> (in radians).\n\n\n\n\n<p>\n<hr><h3><a name=\"pdf-math.asin\"><code>math.asin (x)</code></a></h3>\n\n\n<p>\nReturns the arc sine of <code>x</code> (in radians).\n\n\n\n\n<p>\n<hr><h3><a name=\"pdf-math.atan\"><code>math.atan (x)</code></a></h3>\n\n\n<p>\nReturns the arc tangent of <code>x</code> (in radians).\n\n\n\n\n<p>\n<hr><h3><a name=\"pdf-math.atan2\"><code>math.atan2 (y, x)</code></a></h3>\n\n\n<p>\nReturns the arc tangent of <code>y/x</code> (in radians),\nbut uses the signs of both parameters to find the\nquadrant of the result.\n(It also handles correctly the case of <code>x</code> being zero.)\n\n\n\n\n<p>\n<hr><h3><a name=\"pdf-math.ceil\"><code>math.ceil (x)</code></a></h3>\n\n\n<p>\nReturns the smallest integer larger than or equal to <code>x</code>.\n\n\n\n\n<p>\n<hr><h3><a name=\"pdf-math.cos\"><code>math.cos (x)</code></a></h3>\n\n\n<p>\nReturns the cosine of <code>x</code> (assumed to be in radians).\n\n\n\n\n<p>\n<hr><h3><a name=\"pdf-math.cosh\"><code>math.cosh (x)</code></a></h3>\n\n\n<p>\nReturns the hyperbolic cosine of <code>x</code>.\n\n\n\n\n<p>\n<hr><h3><a name=\"pdf-math.deg\"><code>math.deg (x)</code></a></h3>\n\n\n<p>\nReturns the angle <code>x</code> (given in radians) in degrees.\n\n\n\n\n<p>\n<hr><h3><a name=\"pdf-math.exp\"><code>math.exp (x)</code></a></h3>\n\n\n<p>\nReturns the value <em>e<sup>x</sup></em>.\n\n\n\n\n<p>\n<hr><h3><a name=\"pdf-math.floor\"><code>math.floor (x)</code></a></h3>\n\n\n<p>\nReturns the largest integer smaller than or equal to <code>x</code>.\n\n\n\n\n<p>\n<hr><h3><a name=\"pdf-math.fmod\"><code>math.fmod (x, y)</code></a></h3>\n\n\n<p>\nReturns the remainder of the division of <code>x</code> by <code>y</code>\nthat rounds the quotient towards zero.\n\n\n\n\n<p>\n<hr><h3><a name=\"pdf-math.frexp\"><code>math.frexp (x)</code></a></h3>\n\n\n<p>\nReturns <code>m</code> and <code>e</code> such that <em>x = m2<sup>e</sup></em>,\n<code>e</code> is an integer and the absolute value of <code>m</code> is\nin the range <em>[0.5, 1)</em>\n(or zero when <code>x</code> is zero).\n\n\n\n\n<p>\n<hr><h3><a name=\"pdf-math.huge\"><code>math.huge</code></a></h3>\n\n\n<p>\nThe value <code>HUGE_VAL</code>,\na value larger than or equal to any other numerical value.\n\n\n\n\n<p>\n<hr><h3><a name=\"pdf-math.ldexp\"><code>math.ldexp (m, e)</code></a></h3>\n\n\n<p>\nReturns <em>m2<sup>e</sup></em> (<code>e</code> should be an integer).\n\n\n\n\n<p>\n<hr><h3><a name=\"pdf-math.log\"><code>math.log (x)</code></a></h3>\n\n\n<p>\nReturns the natural logarithm of <code>x</code>.\n\n\n\n\n<p>\n<hr><h3><a name=\"pdf-math.log10\"><code>math.log10 (x)</code></a></h3>\n\n\n<p>\nReturns the base-10 logarithm of <code>x</code>.\n\n\n\n\n<p>\n<hr><h3><a name=\"pdf-math.max\"><code>math.max (x, &middot;&middot;&middot;)</code></a></h3>\n\n\n<p>\nReturns the maximum value among its arguments.\n\n\n\n\n<p>\n<hr><h3><a name=\"pdf-math.min\"><code>math.min (x, &middot;&middot;&middot;)</code></a></h3>\n\n\n<p>\nReturns the minimum value among its arguments.\n\n\n\n\n<p>\n<hr><h3><a name=\"pdf-math.modf\"><code>math.modf (x)</code></a></h3>\n\n\n<p>\nReturns two numbers,\nthe integral part of <code>x</code> and the fractional part of <code>x</code>.\n\n\n\n\n<p>\n<hr><h3><a name=\"pdf-math.pi\"><code>math.pi</code></a></h3>\n\n\n<p>\nThe value of <em>pi</em>.\n\n\n\n\n<p>\n<hr><h3><a name=\"pdf-math.pow\"><code>math.pow (x, y)</code></a></h3>\n\n\n<p>\nReturns <em>x<sup>y</sup></em>.\n(You can also use the expression <code>x^y</code> to compute this value.)\n\n\n\n\n<p>\n<hr><h3><a name=\"pdf-math.rad\"><code>math.rad (x)</code></a></h3>\n\n\n<p>\nReturns the angle <code>x</code> (given in degrees) in radians.\n\n\n\n\n<p>\n<hr><h3><a name=\"pdf-math.random\"><code>math.random ([m [, n]])</code></a></h3>\n\n\n<p>\nThis function is an interface to the simple\npseudo-random generator function <code>rand</code> provided by ANSI&nbsp;C.\n(No guarantees can be given for its statistical properties.)\n\n\n<p>\nWhen called without arguments,\nreturns a uniform pseudo-random real number\nin the range <em>[0,1)</em>.  \nWhen called with an integer number <code>m</code>,\n<code>math.random</code> returns\na uniform pseudo-random integer in the range <em>[1, m]</em>.\nWhen called with two integer numbers <code>m</code> and <code>n</code>,\n<code>math.random</code> returns a uniform pseudo-random\ninteger in the range <em>[m, n]</em>.\n\n\n\n\n<p>\n<hr><h3><a name=\"pdf-math.randomseed\"><code>math.randomseed (x)</code></a></h3>\n\n\n<p>\nSets <code>x</code> as the \"seed\"\nfor the pseudo-random generator:\nequal seeds produce equal sequences of numbers.\n\n\n\n\n<p>\n<hr><h3><a name=\"pdf-math.sin\"><code>math.sin (x)</code></a></h3>\n\n\n<p>\nReturns the sine of <code>x</code> (assumed to be in radians).\n\n\n\n\n<p>\n<hr><h3><a name=\"pdf-math.sinh\"><code>math.sinh (x)</code></a></h3>\n\n\n<p>\nReturns the hyperbolic sine of <code>x</code>.\n\n\n\n\n<p>\n<hr><h3><a name=\"pdf-math.sqrt\"><code>math.sqrt (x)</code></a></h3>\n\n\n<p>\nReturns the square root of <code>x</code>.\n(You can also use the expression <code>x^0.5</code> to compute this value.)\n\n\n\n\n<p>\n<hr><h3><a name=\"pdf-math.tan\"><code>math.tan (x)</code></a></h3>\n\n\n<p>\nReturns the tangent of <code>x</code> (assumed to be in radians).\n\n\n\n\n<p>\n<hr><h3><a name=\"pdf-math.tanh\"><code>math.tanh (x)</code></a></h3>\n\n\n<p>\nReturns the hyperbolic tangent of <code>x</code>.\n\n\n\n\n\n\n\n<h2>5.7 - <a name=\"5.7\">Input and Output Facilities</a></h2>\n\n<p>\nThe I/O library provides two different styles for file manipulation.\nThe first one uses implicit file descriptors;\nthat is, there are operations to set a default input file and a\ndefault output file,\nand all input/output operations are over these default files.\nThe second style uses explicit file descriptors.\n\n\n<p>\nWhen using implicit file descriptors,\nall operations are supplied by table <a name=\"pdf-io\"><code>io</code></a>.\nWhen using explicit file descriptors,\nthe operation <a href=\"#pdf-io.open\"><code>io.open</code></a> returns a file descriptor\nand then all operations are supplied as methods of the file descriptor.\n\n\n<p>\nThe table <code>io</code> also provides\nthree predefined file descriptors with their usual meanings from C:\n<a name=\"pdf-io.stdin\"><code>io.stdin</code></a>, <a name=\"pdf-io.stdout\"><code>io.stdout</code></a>, and <a name=\"pdf-io.stderr\"><code>io.stderr</code></a>.\nThe I/O library never closes these files.\n\n\n<p>\nUnless otherwise stated,\nall I/O functions return <b>nil</b> on failure\n(plus an error message as a second result and\na system-dependent error code as a third result)\nand some value different from <b>nil</b> on success.\n\n\n<p>\n<hr><h3><a name=\"pdf-io.close\"><code>io.close ([file])</code></a></h3>\n\n\n<p>\nEquivalent to <code>file:close()</code>.\nWithout a <code>file</code>, closes the default output file.\n\n\n\n\n<p>\n<hr><h3><a name=\"pdf-io.flush\"><code>io.flush ()</code></a></h3>\n\n\n<p>\nEquivalent to <code>file:flush</code> over the default output file.\n\n\n\n\n<p>\n<hr><h3><a name=\"pdf-io.input\"><code>io.input ([file])</code></a></h3>\n\n\n<p>\nWhen called with a file name, it opens the named file (in text mode),\nand sets its handle as the default input file.\nWhen called with a file handle,\nit simply sets this file handle as the default input file.\nWhen called without parameters,\nit returns the current default input file.\n\n\n<p>\nIn case of errors this function raises the error,\ninstead of returning an error code.\n\n\n\n\n<p>\n<hr><h3><a name=\"pdf-io.lines\"><code>io.lines ([filename])</code></a></h3>\n\n\n<p>\nOpens the given file name in read mode\nand returns an iterator function that,\neach time it is called,\nreturns a new line from the file.\nTherefore, the construction\n\n<pre>\n     for line in io.lines(filename) do <em>body</em> end\n</pre><p>\nwill iterate over all lines of the file.\nWhen the iterator function detects the end of file,\nit returns <b>nil</b> (to finish the loop) and automatically closes the file.\n\n\n<p>\nThe call <code>io.lines()</code> (with no file name) is equivalent\nto <code>io.input():lines()</code>;\nthat is, it iterates over the lines of the default input file.\nIn this case it does not close the file when the loop ends.\n\n\n\n\n<p>\n<hr><h3><a name=\"pdf-io.open\"><code>io.open (filename [, mode])</code></a></h3>\n\n\n<p>\nThis function opens a file,\nin the mode specified in the string <code>mode</code>.\nIt returns a new file handle,\nor, in case of errors, <b>nil</b> plus an error message.\n\n\n<p>\nThe <code>mode</code> string can be any of the following:\n\n<ul>\n<li><b>\"r\":</b> read mode (the default);</li>\n<li><b>\"w\":</b> write mode;</li>\n<li><b>\"a\":</b> append mode;</li>\n<li><b>\"r+\":</b> update mode, all previous data is preserved;</li>\n<li><b>\"w+\":</b> update mode, all previous data is erased;</li>\n<li><b>\"a+\":</b> append update mode, previous data is preserved,\n  writing is only allowed at the end of file.</li>\n</ul><p>\nThe <code>mode</code> string can also have a '<code>b</code>' at the end,\nwhich is needed in some systems to open the file in binary mode.\nThis string is exactly what is used in the\nstandard&nbsp;C function <code>fopen</code>.\n\n\n\n\n<p>\n<hr><h3><a name=\"pdf-io.output\"><code>io.output ([file])</code></a></h3>\n\n\n<p>\nSimilar to <a href=\"#pdf-io.input\"><code>io.input</code></a>, but operates over the default output file.\n\n\n\n\n<p>\n<hr><h3><a name=\"pdf-io.popen\"><code>io.popen (prog [, mode])</code></a></h3>\n\n\n<p>\nStarts program <code>prog</code> in a separated process and returns\na file handle that you can use to read data from this program\n(if <code>mode</code> is <code>\"r\"</code>, the default)\nor to write data to this program\n(if <code>mode</code> is <code>\"w\"</code>).\n\n\n<p>\nThis function is system dependent and is not available\non all platforms.\n\n\n\n\n<p>\n<hr><h3><a name=\"pdf-io.read\"><code>io.read (&middot;&middot;&middot;)</code></a></h3>\n\n\n<p>\nEquivalent to <code>io.input():read</code>.\n\n\n\n\n<p>\n<hr><h3><a name=\"pdf-io.tmpfile\"><code>io.tmpfile ()</code></a></h3>\n\n\n<p>\nReturns a handle for a temporary file.\nThis file is opened in update mode\nand it is automatically removed when the program ends.\n\n\n\n\n<p>\n<hr><h3><a name=\"pdf-io.type\"><code>io.type (obj)</code></a></h3>\n\n\n<p>\nChecks whether <code>obj</code> is a valid file handle.\nReturns the string <code>\"file\"</code> if <code>obj</code> is an open file handle,\n<code>\"closed file\"</code> if <code>obj</code> is a closed file handle,\nor <b>nil</b> if <code>obj</code> is not a file handle.\n\n\n\n\n<p>\n<hr><h3><a name=\"pdf-io.write\"><code>io.write (&middot;&middot;&middot;)</code></a></h3>\n\n\n<p>\nEquivalent to <code>io.output():write</code>.\n\n\n\n\n<p>\n<hr><h3><a name=\"pdf-file:close\"><code>file:close ()</code></a></h3>\n\n\n<p>\nCloses <code>file</code>.\nNote that files are automatically closed when\ntheir handles are garbage collected,\nbut that takes an unpredictable amount of time to happen.\n\n\n\n\n<p>\n<hr><h3><a name=\"pdf-file:flush\"><code>file:flush ()</code></a></h3>\n\n\n<p>\nSaves any written data to <code>file</code>.\n\n\n\n\n<p>\n<hr><h3><a name=\"pdf-file:lines\"><code>file:lines ()</code></a></h3>\n\n\n<p>\nReturns an iterator function that,\neach time it is called,\nreturns a new line from the file.\nTherefore, the construction\n\n<pre>\n     for line in file:lines() do <em>body</em> end\n</pre><p>\nwill iterate over all lines of the file.\n(Unlike <a href=\"#pdf-io.lines\"><code>io.lines</code></a>, this function does not close the file\nwhen the loop ends.)\n\n\n\n\n<p>\n<hr><h3><a name=\"pdf-file:read\"><code>file:read (&middot;&middot;&middot;)</code></a></h3>\n\n\n<p>\nReads the file <code>file</code>,\naccording to the given formats, which specify what to read.\nFor each format,\nthe function returns a string (or a number) with the characters read,\nor <b>nil</b> if it cannot read data with the specified format.\nWhen called without formats,\nit uses a default format that reads the entire next line\n(see below).\n\n\n<p>\nThe available formats are\n\n<ul>\n\n<li><b>\"*n\":</b>\nreads a number;\nthis is the only format that returns a number instead of a string.\n</li>\n\n<li><b>\"*a\":</b>\nreads the whole file, starting at the current position.\nOn end of file, it returns the empty string.\n</li>\n\n<li><b>\"*l\":</b>\nreads the next line (skipping the end of line),\nreturning <b>nil</b> on end of file.\nThis is the default format.\n</li>\n\n<li><b><em>number</em>:</b>\nreads a string with up to this number of characters,\nreturning <b>nil</b> on end of file.\nIf number is zero,\nit reads nothing and returns an empty string,\nor <b>nil</b> on end of file.\n</li>\n\n</ul>\n\n\n\n<p>\n<hr><h3><a name=\"pdf-file:seek\"><code>file:seek ([whence] [, offset])</code></a></h3>\n\n\n<p>\nSets and gets the file position,\nmeasured from the beginning of the file,\nto the position given by <code>offset</code> plus a base\nspecified by the string <code>whence</code>, as follows:\n\n<ul>\n<li><b>\"set\":</b> base is position 0 (beginning of the file);</li>\n<li><b>\"cur\":</b> base is current position;</li>\n<li><b>\"end\":</b> base is end of file;</li>\n</ul><p>\nIn case of success, function <code>seek</code> returns the final file position,\nmeasured in bytes from the beginning of the file.\nIf this function fails, it returns <b>nil</b>,\nplus a string describing the error.\n\n\n<p>\nThe default value for <code>whence</code> is <code>\"cur\"</code>,\nand for <code>offset</code> is 0.\nTherefore, the call <code>file:seek()</code> returns the current\nfile position, without changing it;\nthe call <code>file:seek(\"set\")</code> sets the position to the\nbeginning of the file (and returns 0);\nand the call <code>file:seek(\"end\")</code> sets the position to the\nend of the file, and returns its size.\n\n\n\n\n<p>\n<hr><h3><a name=\"pdf-file:setvbuf\"><code>file:setvbuf (mode [, size])</code></a></h3>\n\n\n<p>\nSets the buffering mode for an output file.\nThere are three available modes:\n\n<ul>\n\n<li><b>\"no\":</b>\nno buffering; the result of any output operation appears immediately.\n</li>\n\n<li><b>\"full\":</b>\nfull buffering; output operation is performed only\nwhen the buffer is full (or when you explicitly <code>flush</code> the file\n(see <a href=\"#pdf-io.flush\"><code>io.flush</code></a>)).\n</li>\n\n<li><b>\"line\":</b>\nline buffering; output is buffered until a newline is output\nor there is any input from some special files\n(such as a terminal device).\n</li>\n\n</ul><p>\nFor the last two cases, <code>size</code>\nspecifies the size of the buffer, in bytes.\nThe default is an appropriate size.\n\n\n\n\n<p>\n<hr><h3><a name=\"pdf-file:write\"><code>file:write (&middot;&middot;&middot;)</code></a></h3>\n\n\n<p>\nWrites the value of each of its arguments to\nthe <code>file</code>.\nThe arguments must be strings or numbers.\nTo write other values,\nuse <a href=\"#pdf-tostring\"><code>tostring</code></a> or <a href=\"#pdf-string.format\"><code>string.format</code></a> before <code>write</code>.\n\n\n\n\n\n\n\n<h2>5.8 - <a name=\"5.8\">Operating System Facilities</a></h2>\n\n<p>\nThis library is implemented through table <a name=\"pdf-os\"><code>os</code></a>.\n\n\n<p>\n<hr><h3><a name=\"pdf-os.clock\"><code>os.clock ()</code></a></h3>\n\n\n<p>\nReturns an approximation of the amount in seconds of CPU time\nused by the program.\n\n\n\n\n<p>\n<hr><h3><a name=\"pdf-os.date\"><code>os.date ([format [, time]])</code></a></h3>\n\n\n<p>\nReturns a string or a table containing date and time,\nformatted according to the given string <code>format</code>.\n\n\n<p>\nIf the <code>time</code> argument is present,\nthis is the time to be formatted\n(see the <a href=\"#pdf-os.time\"><code>os.time</code></a> function for a description of this value).\nOtherwise, <code>date</code> formats the current time.\n\n\n<p>\nIf <code>format</code> starts with '<code>!</code>',\nthen the date is formatted in Coordinated Universal Time.\nAfter this optional character,\nif <code>format</code> is the string \"<code>*t</code>\",\nthen <code>date</code> returns a table with the following fields:\n<code>year</code> (four digits), <code>month</code> (1--12), <code>day</code> (1--31),\n<code>hour</code> (0--23), <code>min</code> (0--59), <code>sec</code> (0--61),\n<code>wday</code> (weekday, Sunday is&nbsp;1),\n<code>yday</code> (day of the year),\nand <code>isdst</code> (daylight saving flag, a boolean).\n\n\n<p>\nIf <code>format</code> is not \"<code>*t</code>\",\nthen <code>date</code> returns the date as a string,\nformatted according to the same rules as the C&nbsp;function <code>strftime</code>.\n\n\n<p>\nWhen called without arguments,\n<code>date</code> returns a reasonable date and time representation that depends on\nthe host system and on the current locale\n(that is, <code>os.date()</code> is equivalent to <code>os.date(\"%c\")</code>).\n\n\n\n\n<p>\n<hr><h3><a name=\"pdf-os.difftime\"><code>os.difftime (t2, t1)</code></a></h3>\n\n\n<p>\nReturns the number of seconds from time <code>t1</code> to time <code>t2</code>.\nIn POSIX, Windows, and some other systems,\nthis value is exactly <code>t2</code><em>-</em><code>t1</code>.\n\n\n\n\n<p>\n<hr><h3><a name=\"pdf-os.execute\"><code>os.execute ([command])</code></a></h3>\n\n\n<p>\nThis function is equivalent to the C&nbsp;function <code>system</code>.\nIt passes <code>command</code> to be executed by an operating system shell.\nIt returns a status code, which is system-dependent.\nIf <code>command</code> is absent, then it returns nonzero if a shell is available\nand zero otherwise.\n\n\n\n\n<p>\n<hr><h3><a name=\"pdf-os.exit\"><code>os.exit ([code])</code></a></h3>\n\n\n<p>\nCalls the C&nbsp;function <code>exit</code>,\nwith an optional <code>code</code>,\nto terminate the host program.\nThe default value for <code>code</code> is the success code.\n\n\n\n\n<p>\n<hr><h3><a name=\"pdf-os.getenv\"><code>os.getenv (varname)</code></a></h3>\n\n\n<p>\nReturns the value of the process environment variable <code>varname</code>,\nor <b>nil</b> if the variable is not defined.\n\n\n\n\n<p>\n<hr><h3><a name=\"pdf-os.remove\"><code>os.remove (filename)</code></a></h3>\n\n\n<p>\nDeletes the file or directory with the given name.\nDirectories must be empty to be removed.\nIf this function fails, it returns <b>nil</b>,\nplus a string describing the error.\n\n\n\n\n<p>\n<hr><h3><a name=\"pdf-os.rename\"><code>os.rename (oldname, newname)</code></a></h3>\n\n\n<p>\nRenames file or directory named <code>oldname</code> to <code>newname</code>.\nIf this function fails, it returns <b>nil</b>,\nplus a string describing the error.\n\n\n\n\n<p>\n<hr><h3><a name=\"pdf-os.setlocale\"><code>os.setlocale (locale [, category])</code></a></h3>\n\n\n<p>\nSets the current locale of the program.\n<code>locale</code> is a string specifying a locale;\n<code>category</code> is an optional string describing which category to change:\n<code>\"all\"</code>, <code>\"collate\"</code>, <code>\"ctype\"</code>,\n<code>\"monetary\"</code>, <code>\"numeric\"</code>, or <code>\"time\"</code>;\nthe default category is <code>\"all\"</code>.\nThe function returns the name of the new locale,\nor <b>nil</b> if the request cannot be honored.\n\n\n<p>\nIf <code>locale</code> is the empty string,\nthe current locale is set to an implementation-defined native locale.\nIf <code>locale</code> is the string \"<code>C</code>\",\nthe current locale is set to the standard C locale.\n\n\n<p>\nWhen called with <b>nil</b> as the first argument,\nthis function only returns the name of the current locale\nfor the given category.\n\n\n\n\n<p>\n<hr><h3><a name=\"pdf-os.time\"><code>os.time ([table])</code></a></h3>\n\n\n<p>\nReturns the current time when called without arguments,\nor a time representing the date and time specified by the given table.\nThis table must have fields <code>year</code>, <code>month</code>, and <code>day</code>,\nand may have fields <code>hour</code>, <code>min</code>, <code>sec</code>, and <code>isdst</code>\n(for a description of these fields, see the <a href=\"#pdf-os.date\"><code>os.date</code></a> function).\n\n\n<p>\nThe returned value is a number, whose meaning depends on your system.\nIn POSIX, Windows, and some other systems, this number counts the number\nof seconds since some given start time (the \"epoch\").\nIn other systems, the meaning is not specified,\nand the number returned by <code>time</code> can be used only as an argument to\n<code>date</code> and <code>difftime</code>.\n\n\n\n\n<p>\n<hr><h3><a name=\"pdf-os.tmpname\"><code>os.tmpname ()</code></a></h3>\n\n\n<p>\nReturns a string with a file name that can\nbe used for a temporary file.\nThe file must be explicitly opened before its use\nand explicitly removed when no longer needed.\n\n\n<p>\nOn some systems (POSIX),\nthis function also creates a file with that name,\nto avoid security risks.\n(Someone else might create the file with wrong permissions\nin the time between getting the name and creating the file.)\nYou still have to open the file to use it\nand to remove it (even if you do not use it).\n\n\n<p>\nWhen possible,\nyou may prefer to use <a href=\"#pdf-io.tmpfile\"><code>io.tmpfile</code></a>,\nwhich automatically removes the file when the program ends.\n\n\n\n\n\n\n\n<h2>5.9 - <a name=\"5.9\">The Debug Library</a></h2>\n\n<p>\nThis library provides\nthe functionality of the debug interface to Lua programs.\nYou should exert care when using this library.\nThe functions provided here should be used exclusively for debugging\nand similar tasks, such as profiling.\nPlease resist the temptation to use them as a\nusual programming tool:\nthey can be very slow.\nMoreover, several of these functions\nviolate some assumptions about Lua code\n(e.g., that variables local to a function\ncannot be accessed from outside or\nthat userdata metatables cannot be changed by Lua code)\nand therefore can compromise otherwise secure code.\n\n\n<p>\nAll functions in this library are provided\ninside the <a name=\"pdf-debug\"><code>debug</code></a> table.\nAll functions that operate over a thread\nhave an optional first argument which is the\nthread to operate over.\nThe default is always the current thread.\n\n\n<p>\n<hr><h3><a name=\"pdf-debug.debug\"><code>debug.debug ()</code></a></h3>\n\n\n<p>\nEnters an interactive mode with the user,\nrunning each string that the user enters.\nUsing simple commands and other debug facilities,\nthe user can inspect global and local variables,\nchange their values, evaluate expressions, and so on.\nA line containing only the word <code>cont</code> finishes this function,\nso that the caller continues its execution.\n\n\n<p>\nNote that commands for <code>debug.debug</code> are not lexically nested\nwithin any function, and so have no direct access to local variables.\n\n\n\n\n<p>\n<hr><h3><a name=\"pdf-debug.getfenv\"><code>debug.getfenv (o)</code></a></h3>\nReturns the environment of object <code>o</code>.\n\n\n\n\n<p>\n<hr><h3><a name=\"pdf-debug.gethook\"><code>debug.gethook ([thread])</code></a></h3>\n\n\n<p>\nReturns the current hook settings of the thread, as three values:\nthe current hook function, the current hook mask,\nand the current hook count\n(as set by the <a href=\"#pdf-debug.sethook\"><code>debug.sethook</code></a> function).\n\n\n\n\n<p>\n<hr><h3><a name=\"pdf-debug.getinfo\"><code>debug.getinfo ([thread,] function [, what])</code></a></h3>\n\n\n<p>\nReturns a table with information about a function.\nYou can give the function directly,\nor you can give a number as the value of <code>function</code>,\nwhich means the function running at level <code>function</code> of the call stack\nof the given thread:\nlevel&nbsp;0 is the current function (<code>getinfo</code> itself);\nlevel&nbsp;1 is the function that called <code>getinfo</code>;\nand so on.\nIf <code>function</code> is a number larger than the number of active functions,\nthen <code>getinfo</code> returns <b>nil</b>.\n\n\n<p>\nThe returned table can contain all the fields returned by <a href=\"#lua_getinfo\"><code>lua_getinfo</code></a>,\nwith the string <code>what</code> describing which fields to fill in.\nThe default for <code>what</code> is to get all information available,\nexcept the table of valid lines.\nIf present,\nthe option '<code>f</code>'\nadds a field named <code>func</code> with the function itself.\nIf present,\nthe option '<code>L</code>'\nadds a field named <code>activelines</code> with the table of\nvalid lines.\n\n\n<p>\nFor instance, the expression <code>debug.getinfo(1,\"n\").name</code> returns\na table with a name for the current function,\nif a reasonable name can be found,\nand the expression <code>debug.getinfo(print)</code>\nreturns a table with all available information\nabout the <a href=\"#pdf-print\"><code>print</code></a> function.\n\n\n\n\n<p>\n<hr><h3><a name=\"pdf-debug.getlocal\"><code>debug.getlocal ([thread,] level, local)</code></a></h3>\n\n\n<p>\nThis function returns the name and the value of the local variable\nwith index <code>local</code> of the function at level <code>level</code> of the stack.\n(The first parameter or local variable has index&nbsp;1, and so on,\nuntil the last active local variable.)\nThe function returns <b>nil</b> if there is no local\nvariable with the given index,\nand raises an error when called with a <code>level</code> out of range.\n(You can call <a href=\"#pdf-debug.getinfo\"><code>debug.getinfo</code></a> to check whether the level is valid.)\n\n\n<p>\nVariable names starting with '<code>(</code>' (open parentheses)\nrepresent internal variables\n(loop control variables, temporaries, and C&nbsp;function locals).\n\n\n\n\n<p>\n<hr><h3><a name=\"pdf-debug.getmetatable\"><code>debug.getmetatable (object)</code></a></h3>\n\n\n<p>\nReturns the metatable of the given <code>object</code>\nor <b>nil</b> if it does not have a metatable.\n\n\n\n\n<p>\n<hr><h3><a name=\"pdf-debug.getregistry\"><code>debug.getregistry ()</code></a></h3>\n\n\n<p>\nReturns the registry table (see <a href=\"#3.5\">&sect;3.5</a>).\n\n\n\n\n<p>\n<hr><h3><a name=\"pdf-debug.getupvalue\"><code>debug.getupvalue (func, up)</code></a></h3>\n\n\n<p>\nThis function returns the name and the value of the upvalue\nwith index <code>up</code> of the function <code>func</code>.\nThe function returns <b>nil</b> if there is no upvalue with the given index.\n\n\n\n\n<p>\n<hr><h3><a name=\"pdf-debug.setfenv\"><code>debug.setfenv (object, table)</code></a></h3>\n\n\n<p>\nSets the environment of the given <code>object</code> to the given <code>table</code>.\nReturns <code>object</code>.\n\n\n\n\n<p>\n<hr><h3><a name=\"pdf-debug.sethook\"><code>debug.sethook ([thread,] hook, mask [, count])</code></a></h3>\n\n\n<p>\nSets the given function as a hook.\nThe string <code>mask</code> and the number <code>count</code> describe\nwhen the hook will be called.\nThe string mask may have the following characters,\nwith the given meaning:\n\n<ul>\n<li><b><code>\"c\"</code>:</b> the hook is called every time Lua calls a function;</li>\n<li><b><code>\"r\"</code>:</b> the hook is called every time Lua returns from a function;</li>\n<li><b><code>\"l\"</code>:</b> the hook is called every time Lua enters a new line of code.</li>\n</ul><p>\nWith a <code>count</code> different from zero,\nthe hook is called after every <code>count</code> instructions.\n\n\n<p>\nWhen called without arguments,\n<a href=\"#pdf-debug.sethook\"><code>debug.sethook</code></a> turns off the hook.\n\n\n<p>\nWhen the hook is called, its first parameter is a string\ndescribing the event that has triggered its call:\n<code>\"call\"</code>, <code>\"return\"</code> (or <code>\"tail return\"</code>,\nwhen simulating a return from a tail call),\n<code>\"line\"</code>, and <code>\"count\"</code>.\nFor line events,\nthe hook also gets the new line number as its second parameter.\nInside a hook,\nyou can call <code>getinfo</code> with level&nbsp;2 to get more information about\nthe running function\n(level&nbsp;0 is the <code>getinfo</code> function,\nand level&nbsp;1 is the hook function),\nunless the event is <code>\"tail return\"</code>.\nIn this case, Lua is only simulating the return,\nand a call to <code>getinfo</code> will return invalid data.\n\n\n\n\n<p>\n<hr><h3><a name=\"pdf-debug.setlocal\"><code>debug.setlocal ([thread,] level, local, value)</code></a></h3>\n\n\n<p>\nThis function assigns the value <code>value</code> to the local variable\nwith index <code>local</code> of the function at level <code>level</code> of the stack.\nThe function returns <b>nil</b> if there is no local\nvariable with the given index,\nand raises an error when called with a <code>level</code> out of range.\n(You can call <code>getinfo</code> to check whether the level is valid.)\nOtherwise, it returns the name of the local variable.\n\n\n\n\n<p>\n<hr><h3><a name=\"pdf-debug.setmetatable\"><code>debug.setmetatable (object, table)</code></a></h3>\n\n\n<p>\nSets the metatable for the given <code>object</code> to the given <code>table</code>\n(which can be <b>nil</b>).\n\n\n\n\n<p>\n<hr><h3><a name=\"pdf-debug.setupvalue\"><code>debug.setupvalue (func, up, value)</code></a></h3>\n\n\n<p>\nThis function assigns the value <code>value</code> to the upvalue\nwith index <code>up</code> of the function <code>func</code>.\nThe function returns <b>nil</b> if there is no upvalue\nwith the given index.\nOtherwise, it returns the name of the upvalue.\n\n\n\n\n<p>\n<hr><h3><a name=\"pdf-debug.traceback\"><code>debug.traceback ([thread,] [message [, level]])</code></a></h3>\n\n\n<p>\nReturns a string with a traceback of the call stack.\nAn optional <code>message</code> string is appended\nat the beginning of the traceback.\nAn optional <code>level</code> number tells at which level\nto start the traceback\n(default is 1, the function calling <code>traceback</code>).\n\n\n\n\n\n\n\n<h1>6 - <a name=\"6\">Lua Stand-alone</a></h1>\n\n<p>\nAlthough Lua has been designed as an extension language,\nto be embedded in a host C&nbsp;program,\nit is also frequently used as a stand-alone language.\nAn interpreter for Lua as a stand-alone language,\ncalled simply <code>lua</code>,\nis provided with the standard distribution.\nThe stand-alone interpreter includes\nall standard libraries, including the debug library.\nIts usage is:\n\n<pre>\n     lua [options] [script [args]]\n</pre><p>\nThe options are:\n\n<ul>\n<li><b><code>-e <em>stat</em></code>:</b> executes string <em>stat</em>;</li>\n<li><b><code>-l <em>mod</em></code>:</b> \"requires\" <em>mod</em>;</li>\n<li><b><code>-i</code>:</b> enters interactive mode after running <em>script</em>;</li>\n<li><b><code>-v</code>:</b> prints version information;</li>\n<li><b><code>--</code>:</b> stops handling options;</li>\n<li><b><code>-</code>:</b> executes <code>stdin</code> as a file and stops handling options.</li>\n</ul><p>\nAfter handling its options, <code>lua</code> runs the given <em>script</em>,\npassing to it the given <em>args</em> as string arguments.\nWhen called without arguments,\n<code>lua</code> behaves as <code>lua -v -i</code>\nwhen the standard input (<code>stdin</code>) is a terminal,\nand as <code>lua -</code> otherwise.\n\n\n<p>\nBefore running any argument,\nthe interpreter checks for an environment variable <a name=\"pdf-LUA_INIT\"><code>LUA_INIT</code></a>.\nIf its format is <code>@<em>filename</em></code>,\nthen <code>lua</code> executes the file.\nOtherwise, <code>lua</code> executes the string itself.\n\n\n<p>\nAll options are handled in order, except <code>-i</code>.\nFor instance, an invocation like\n\n<pre>\n     $ lua -e'a=1' -e 'print(a)' script.lua\n</pre><p>\nwill first set <code>a</code> to 1, then print the value of <code>a</code> (which is '<code>1</code>'),\nand finally run the file <code>script.lua</code> with no arguments.\n(Here <code>$</code> is the shell prompt. Your prompt may be different.)\n\n\n<p>\nBefore starting to run the script,\n<code>lua</code> collects all arguments in the command line\nin a global table called <code>arg</code>.\nThe script name is stored at index 0,\nthe first argument after the script name goes to index 1,\nand so on.\nAny arguments before the script name\n(that is, the interpreter name plus the options)\ngo to negative indices.\nFor instance, in the call\n\n<pre>\n     $ lua -la b.lua t1 t2\n</pre><p>\nthe interpreter first runs the file <code>a.lua</code>,\nthen creates a table\n\n<pre>\n     arg = { [-2] = \"lua\", [-1] = \"-la\",\n             [0] = \"b.lua\",\n             [1] = \"t1\", [2] = \"t2\" }\n</pre><p>\nand finally runs the file <code>b.lua</code>.\nThe script is called with <code>arg[1]</code>, <code>arg[2]</code>, &middot;&middot;&middot;\nas arguments;\nit can also access these arguments with the vararg expression '<code>...</code>'.\n\n\n<p>\nIn interactive mode,\nif you write an incomplete statement,\nthe interpreter waits for its completion\nby issuing a different prompt.\n\n\n<p>\nIf the global variable <a name=\"pdf-_PROMPT\"><code>_PROMPT</code></a> contains a string,\nthen its value is used as the prompt.\nSimilarly, if the global variable <a name=\"pdf-_PROMPT2\"><code>_PROMPT2</code></a> contains a string,\nits value is used as the secondary prompt\n(issued during incomplete statements).\nTherefore, both prompts can be changed directly on the command line\nor in any Lua programs by assigning to <code>_PROMPT</code>.\nSee the next example:\n\n<pre>\n     $ lua -e\"_PROMPT='myprompt&gt; '\" -i\n</pre><p>\n(The outer pair of quotes is for the shell,\nthe inner pair is for Lua.)\nNote the use of <code>-i</code> to enter interactive mode;\notherwise,\nthe program would just end silently\nright after the assignment to <code>_PROMPT</code>.\n\n\n<p>\nTo allow the use of Lua as a\nscript interpreter in Unix systems,\nthe stand-alone interpreter skips\nthe first line of a chunk if it starts with <code>#</code>.\nTherefore, Lua scripts can be made into executable programs\nby using <code>chmod +x</code> and the&nbsp;<code>#!</code> form,\nas in\n\n<pre>\n     #!/usr/local/bin/lua\n</pre><p>\n(Of course,\nthe location of the Lua interpreter may be different in your machine.\nIf <code>lua</code> is in your <code>PATH</code>,\nthen \n\n<pre>\n     #!/usr/bin/env lua\n</pre><p>\nis a more portable solution.) \n\n\n\n<h1>7 - <a name=\"7\">Incompatibilities with the Previous Version</a></h1>\n\n<p>\nHere we list the incompatibilities that you may find when moving a program\nfrom Lua&nbsp;5.0 to Lua&nbsp;5.1.\nYou can avoid most of the incompatibilities compiling Lua with\nappropriate options (see file <code>luaconf.h</code>).\nHowever,\nall these compatibility options will be removed in the next version of Lua.\n\n\n\n<h2>7.1 - <a name=\"7.1\">Changes in the Language</a></h2>\n<ul>\n\n<li>\nThe vararg system changed from the pseudo-argument <code>arg</code> with a\ntable with the extra arguments to the vararg expression.\n(See compile-time option <code>LUA_COMPAT_VARARG</code> in <code>luaconf.h</code>.)\n</li>\n\n<li>\nThere was a subtle change in the scope of the implicit\nvariables of the <b>for</b> statement and for the <b>repeat</b> statement.\n</li>\n\n<li>\nThe long string/long comment syntax (<code>[[<em>string</em>]]</code>)\ndoes not allow nesting.\nYou can use the new syntax (<code>[=[<em>string</em>]=]</code>) in these cases.\n(See compile-time option <code>LUA_COMPAT_LSTR</code> in <code>luaconf.h</code>.)\n</li>\n\n</ul>\n\n\n\n\n<h2>7.2 - <a name=\"7.2\">Changes in the Libraries</a></h2>\n<ul>\n\n<li>\nFunction <code>string.gfind</code> was renamed <a href=\"#pdf-string.gmatch\"><code>string.gmatch</code></a>.\n(See compile-time option <code>LUA_COMPAT_GFIND</code> in <code>luaconf.h</code>.)\n</li>\n\n<li>\nWhen <a href=\"#pdf-string.gsub\"><code>string.gsub</code></a> is called with a function as its\nthird argument,\nwhenever this function returns <b>nil</b> or <b>false</b> the\nreplacement string is the whole match,\ninstead of the empty string.\n</li>\n\n<li>\nFunction <code>table.setn</code> was deprecated.\nFunction <code>table.getn</code> corresponds\nto the new length operator (<code>#</code>);\nuse the operator instead of the function.\n(See compile-time option <code>LUA_COMPAT_GETN</code> in <code>luaconf.h</code>.)\n</li>\n\n<li>\nFunction <code>loadlib</code> was renamed <a href=\"#pdf-package.loadlib\"><code>package.loadlib</code></a>.\n(See compile-time option <code>LUA_COMPAT_LOADLIB</code> in <code>luaconf.h</code>.)\n</li>\n\n<li>\nFunction <code>math.mod</code> was renamed <a href=\"#pdf-math.fmod\"><code>math.fmod</code></a>.\n(See compile-time option <code>LUA_COMPAT_MOD</code> in <code>luaconf.h</code>.)\n</li>\n\n<li>\nFunctions <code>table.foreach</code> and <code>table.foreachi</code> are deprecated.\nYou can use a for loop with <code>pairs</code> or <code>ipairs</code> instead.\n</li>\n\n<li>\nThere were substantial changes in function <a href=\"#pdf-require\"><code>require</code></a> due to\nthe new module system.\nHowever, the new behavior is mostly compatible with the old,\nbut <code>require</code> gets the path from <a href=\"#pdf-package.path\"><code>package.path</code></a> instead\nof from <code>LUA_PATH</code>.\n</li>\n\n<li>\nFunction <a href=\"#pdf-collectgarbage\"><code>collectgarbage</code></a> has different arguments.\nFunction <code>gcinfo</code> is deprecated;\nuse <code>collectgarbage(\"count\")</code> instead.\n</li>\n\n</ul>\n\n\n\n\n<h2>7.3 - <a name=\"7.3\">Changes in the API</a></h2>\n<ul>\n\n<li>\nThe <code>luaopen_*</code> functions (to open libraries)\ncannot be called directly,\nlike a regular C function.\nThey must be called through Lua,\nlike a Lua function.\n</li>\n\n<li>\nFunction <code>lua_open</code> was replaced by <a href=\"#lua_newstate\"><code>lua_newstate</code></a> to\nallow the user to set a memory-allocation function.\nYou can use <a href=\"#luaL_newstate\"><code>luaL_newstate</code></a> from the standard library to\ncreate a state with a standard allocation function\n(based on <code>realloc</code>).\n</li>\n\n<li>\nFunctions <code>luaL_getn</code> and <code>luaL_setn</code>\n(from the auxiliary library) are deprecated.\nUse <a href=\"#lua_objlen\"><code>lua_objlen</code></a> instead of <code>luaL_getn</code>\nand nothing instead of <code>luaL_setn</code>.\n</li>\n\n<li>\nFunction <code>luaL_openlib</code> was replaced by <a href=\"#luaL_register\"><code>luaL_register</code></a>.\n</li>\n\n<li>\nFunction <code>luaL_checkudata</code> now throws an error when the given value\nis not a userdata of the expected type.\n(In Lua&nbsp;5.0 it returned <code>NULL</code>.)\n</li>\n\n</ul>\n\n\n\n\n<h1>8 - <a name=\"8\">The Complete Syntax of Lua</a></h1>\n\n<p>\nHere is the complete syntax of Lua in extended BNF.\n(It does not describe operator precedences.)\n\n\n\n\n<pre>\n\n\tchunk ::= {stat [`<b>;</b>&acute;]} [laststat [`<b>;</b>&acute;]]\n\n\tblock ::= chunk\n\n\tstat ::=  varlist `<b>=</b>&acute; explist | \n\t\t functioncall | \n\t\t <b>do</b> block <b>end</b> | \n\t\t <b>while</b> exp <b>do</b> block <b>end</b> | \n\t\t <b>repeat</b> block <b>until</b> exp | \n\t\t <b>if</b> exp <b>then</b> block {<b>elseif</b> exp <b>then</b> block} [<b>else</b> block] <b>end</b> | \n\t\t <b>for</b> Name `<b>=</b>&acute; exp `<b>,</b>&acute; exp [`<b>,</b>&acute; exp] <b>do</b> block <b>end</b> | \n\t\t <b>for</b> namelist <b>in</b> explist <b>do</b> block <b>end</b> | \n\t\t <b>function</b> funcname funcbody | \n\t\t <b>local</b> <b>function</b> Name funcbody | \n\t\t <b>local</b> namelist [`<b>=</b>&acute; explist] \n\n\tlaststat ::= <b>return</b> [explist] | <b>break</b>\n\n\tfuncname ::= Name {`<b>.</b>&acute; Name} [`<b>:</b>&acute; Name]\n\n\tvarlist ::= var {`<b>,</b>&acute; var}\n\n\tvar ::=  Name | prefixexp `<b>[</b>&acute; exp `<b>]</b>&acute; | prefixexp `<b>.</b>&acute; Name \n\n\tnamelist ::= Name {`<b>,</b>&acute; Name}\n\n\texplist ::= {exp `<b>,</b>&acute;} exp\n\n\texp ::=  <b>nil</b> | <b>false</b> | <b>true</b> | Number | String | `<b>...</b>&acute; | function | \n\t\t prefixexp | tableconstructor | exp binop exp | unop exp \n\n\tprefixexp ::= var | functioncall | `<b>(</b>&acute; exp `<b>)</b>&acute;\n\n\tfunctioncall ::=  prefixexp args | prefixexp `<b>:</b>&acute; Name args \n\n\targs ::=  `<b>(</b>&acute; [explist] `<b>)</b>&acute; | tableconstructor | String \n\n\tfunction ::= <b>function</b> funcbody\n\n\tfuncbody ::= `<b>(</b>&acute; [parlist] `<b>)</b>&acute; block <b>end</b>\n\n\tparlist ::= namelist [`<b>,</b>&acute; `<b>...</b>&acute;] | `<b>...</b>&acute;\n\n\ttableconstructor ::= `<b>{</b>&acute; [fieldlist] `<b>}</b>&acute;\n\n\tfieldlist ::= field {fieldsep field} [fieldsep]\n\n\tfield ::= `<b>[</b>&acute; exp `<b>]</b>&acute; `<b>=</b>&acute; exp | Name `<b>=</b>&acute; exp | exp\n\n\tfieldsep ::= `<b>,</b>&acute; | `<b>;</b>&acute;\n\n\tbinop ::= `<b>+</b>&acute; | `<b>-</b>&acute; | `<b>*</b>&acute; | `<b>/</b>&acute; | `<b>^</b>&acute; | `<b>%</b>&acute; | `<b>..</b>&acute; | \n\t\t `<b>&lt;</b>&acute; | `<b>&lt;=</b>&acute; | `<b>&gt;</b>&acute; | `<b>&gt;=</b>&acute; | `<b>==</b>&acute; | `<b>~=</b>&acute; | \n\t\t <b>and</b> | <b>or</b>\n\n\tunop ::= `<b>-</b>&acute; | <b>not</b> | `<b>#</b>&acute;\n\n</pre>\n\n<p>\n\n\n\n\n\n\n\n<HR>\n<SMALL CLASS=\"footer\">\nLast update:\nMon Feb 13 18:54:19 BRST 2012\n</SMALL>\n<!--\nLast change: revised for Lua 5.1.5\n-->\n\n</body></html>\n\n"
  },
  {
    "path": "extern/deprecated/redis-2.8.21/deps/lua/doc/readme.html",
    "content": "<HTML>\n<HEAD>\n<TITLE>Lua documentation</TITLE>\n<LINK REL=\"stylesheet\" TYPE=\"text/css\" HREF=\"lua.css\">\n</HEAD>\n\n<BODY>\n\n<HR>\n<H1>\n<A HREF=\"http://www.lua.org/\"><IMG SRC=\"logo.gif\" ALT=\"Lua\" BORDER=0></A>\nDocumentation\n</H1>\n\nThis is the documentation included in the source distribution of Lua 5.1.5.\n\n<UL>\n<LI><A HREF=\"contents.html\">Reference manual</A>\n<LI><A HREF=\"lua.html\">lua man page</A>\n<LI><A HREF=\"luac.html\">luac man page</A>\n<LI><A HREF=\"../README\">lua/README</A>\n<LI><A HREF=\"../etc/README\">lua/etc/README</A>\n<LI><A HREF=\"../test/README\">lua/test/README</A>\n</UL>\n\nLua's\n<A HREF=\"http://www.lua.org/\">official web site</A>\ncontains updated documentation,\nespecially the\n<A HREF=\"http://www.lua.org/manual/5.1/\">reference manual</A>.\n<P>\n\n<HR>\n<SMALL>\nLast update:\nFri Feb  3 09:44:42 BRST 2012\n</SMALL>\n\n</BODY>\n</HTML>\n"
  },
  {
    "path": "extern/deprecated/redis-2.8.21/deps/lua/etc/Makefile",
    "content": "# makefile for Lua etc\n\nTOP= ..\nLIB= $(TOP)/src\nINC= $(TOP)/src\nBIN= $(TOP)/src\nSRC= $(TOP)/src\nTST= $(TOP)/test\n\nCC= gcc\nCFLAGS= -O2 -Wall -I$(INC) $(MYCFLAGS)\nMYCFLAGS= \nMYLDFLAGS= -Wl,-E\nMYLIBS= -lm\n#MYLIBS= -lm -Wl,-E -ldl -lreadline -lhistory -lncurses\nRM= rm -f\n\ndefault:\n\t@echo 'Please choose a target: min noparser one strict clean'\n\nmin:\tmin.c\n\t$(CC) $(CFLAGS) $@.c -L$(LIB) -llua $(MYLIBS)\n\techo 'print\"Hello there!\"' | ./a.out\n\nnoparser: noparser.o\n\t$(CC) noparser.o $(SRC)/lua.o -L$(LIB) -llua $(MYLIBS)\n\t$(BIN)/luac $(TST)/hello.lua\n\t-./a.out luac.out\n\t-./a.out -e'a=1'\n\none:\n\t$(CC) $(CFLAGS) all.c $(MYLIBS)\n\t./a.out $(TST)/hello.lua\n\nstrict:\n\t-$(BIN)/lua -e 'print(a);b=2'\n\t-$(BIN)/lua -lstrict -e 'print(a)'\n\t-$(BIN)/lua -e 'function f() b=2 end f()'\n\t-$(BIN)/lua -lstrict -e 'function f() b=2 end f()'\n\nclean:\n\t$(RM) a.out core core.* *.o luac.out\n\n.PHONY:\tdefault min noparser one strict clean\n"
  },
  {
    "path": "extern/deprecated/redis-2.8.21/deps/lua/etc/README",
    "content": "This directory contains some useful files and code.\nUnlike the code in ../src, everything here is in the public domain.\n\nIf any of the makes fail, you're probably not using the same libraries\nused to build Lua. Set MYLIBS in Makefile accordingly.\n\nall.c\n\tFull Lua interpreter in a single file.\n\tDo \"make one\" for a demo.\n\nlua.hpp\n\tLua header files for C++ using 'extern \"C\"'.\n\nlua.ico\n\tA Lua icon for Windows (and web sites: save as favicon.ico).\n\tDrawn by hand by Markus Gritsch <gritsch@iue.tuwien.ac.at>.\n\nlua.pc\n\tpkg-config data for Lua\n\nluavs.bat\n\tScript to build Lua under \"Visual Studio .NET Command Prompt\".\n\tRun it from the toplevel as etc\\luavs.bat.\n\nmin.c\n\tA minimal Lua interpreter.\n\tGood for learning and for starting your own.\n\tDo \"make min\" for a demo.\n\nnoparser.c\n\tLinking with noparser.o avoids loading the parsing modules in lualib.a.\n\tDo \"make noparser\" for a demo.\n\nstrict.lua\n\tTraps uses of undeclared global variables.\n\tDo \"make strict\" for a demo.\n\n"
  },
  {
    "path": "extern/deprecated/redis-2.8.21/deps/lua/etc/all.c",
    "content": "/*\n* all.c -- Lua core, libraries and interpreter in a single file\n*/\n\n#define luaall_c\n\n#include \"lapi.c\"\n#include \"lcode.c\"\n#include \"ldebug.c\"\n#include \"ldo.c\"\n#include \"ldump.c\"\n#include \"lfunc.c\"\n#include \"lgc.c\"\n#include \"llex.c\"\n#include \"lmem.c\"\n#include \"lobject.c\"\n#include \"lopcodes.c\"\n#include \"lparser.c\"\n#include \"lstate.c\"\n#include \"lstring.c\"\n#include \"ltable.c\"\n#include \"ltm.c\"\n#include \"lundump.c\"\n#include \"lvm.c\"\n#include \"lzio.c\"\n\n#include \"lauxlib.c\"\n#include \"lbaselib.c\"\n#include \"ldblib.c\"\n#include \"liolib.c\"\n#include \"linit.c\"\n#include \"lmathlib.c\"\n#include \"loadlib.c\"\n#include \"loslib.c\"\n#include \"lstrlib.c\"\n#include \"ltablib.c\"\n\n#include \"lua.c\"\n"
  },
  {
    "path": "extern/deprecated/redis-2.8.21/deps/lua/etc/lua.hpp",
    "content": "// lua.hpp\n// Lua header files for C++\n// <<extern \"C\">> not supplied automatically because Lua also compiles as C++\n\nextern \"C\" {\n#include \"lua.h\"\n#include \"lualib.h\"\n#include \"lauxlib.h\"\n}\n"
  },
  {
    "path": "extern/deprecated/redis-2.8.21/deps/lua/etc/lua.pc",
    "content": "# lua.pc -- pkg-config data for Lua\n\n# vars from install Makefile\n\n# grep '^V=' ../Makefile\nV= 5.1\n# grep '^R=' ../Makefile\nR= 5.1.5\n\n# grep '^INSTALL_.*=' ../Makefile | sed 's/INSTALL_TOP/prefix/'\nprefix= /usr/local\nINSTALL_BIN= ${prefix}/bin\nINSTALL_INC= ${prefix}/include\nINSTALL_LIB= ${prefix}/lib\nINSTALL_MAN= ${prefix}/man/man1\nINSTALL_LMOD= ${prefix}/share/lua/${V}\nINSTALL_CMOD= ${prefix}/lib/lua/${V}\n\n# canonical vars\nexec_prefix=${prefix}\nlibdir=${exec_prefix}/lib\nincludedir=${prefix}/include\n\nName: Lua\nDescription: An Extensible Extension Language\nVersion: ${R}\nRequires: \nLibs: -L${libdir} -llua -lm\nCflags: -I${includedir}\n\n# (end of lua.pc)\n"
  },
  {
    "path": "extern/deprecated/redis-2.8.21/deps/lua/etc/luavs.bat",
    "content": "@rem Script to build Lua under \"Visual Studio .NET Command Prompt\".\r\n@rem Do not run from this directory; run it from the toplevel: etc\\luavs.bat .\r\n@rem It creates lua51.dll, lua51.lib, lua.exe, and luac.exe in src.\r\n@rem (contributed by David Manura and Mike Pall)\r\n\r\n@setlocal\r\n@set MYCOMPILE=cl /nologo /MD /O2 /W3 /c /D_CRT_SECURE_NO_DEPRECATE\r\n@set MYLINK=link /nologo\r\n@set MYMT=mt /nologo\r\n\r\ncd src\r\n%MYCOMPILE% /DLUA_BUILD_AS_DLL l*.c\r\ndel lua.obj luac.obj\r\n%MYLINK% /DLL /out:lua51.dll l*.obj\r\nif exist lua51.dll.manifest^\r\n  %MYMT% -manifest lua51.dll.manifest -outputresource:lua51.dll;2\r\n%MYCOMPILE% /DLUA_BUILD_AS_DLL lua.c\r\n%MYLINK% /out:lua.exe lua.obj lua51.lib\r\nif exist lua.exe.manifest^\r\n  %MYMT% -manifest lua.exe.manifest -outputresource:lua.exe\r\n%MYCOMPILE% l*.c print.c\r\ndel lua.obj linit.obj lbaselib.obj ldblib.obj liolib.obj lmathlib.obj^\r\n    loslib.obj ltablib.obj lstrlib.obj loadlib.obj\r\n%MYLINK% /out:luac.exe *.obj\r\nif exist luac.exe.manifest^\r\n  %MYMT% -manifest luac.exe.manifest -outputresource:luac.exe\r\ndel *.obj *.manifest\r\ncd ..\r\n"
  },
  {
    "path": "extern/deprecated/redis-2.8.21/deps/lua/etc/min.c",
    "content": "/*\n* min.c -- a minimal Lua interpreter\n* loads stdin only with minimal error handling.\n* no interaction, and no standard library, only a \"print\" function.\n*/\n\n#include <stdio.h>\n\n#include \"lua.h\"\n#include \"lauxlib.h\"\n\nstatic int print(lua_State *L)\n{\n int n=lua_gettop(L);\n int i;\n for (i=1; i<=n; i++)\n {\n  if (i>1) printf(\"\\t\");\n  if (lua_isstring(L,i))\n   printf(\"%s\",lua_tostring(L,i));\n  else if (lua_isnil(L,i))\n   printf(\"%s\",\"nil\");\n  else if (lua_isboolean(L,i))\n   printf(\"%s\",lua_toboolean(L,i) ? \"true\" : \"false\");\n  else\n   printf(\"%s:%p\",luaL_typename(L,i),lua_topointer(L,i));\n }\n printf(\"\\n\");\n return 0;\n}\n\nint main(void)\n{\n lua_State *L=lua_open();\n lua_register(L,\"print\",print);\n if (luaL_dofile(L,NULL)!=0) fprintf(stderr,\"%s\\n\",lua_tostring(L,-1));\n lua_close(L);\n return 0;\n}\n"
  },
  {
    "path": "extern/deprecated/redis-2.8.21/deps/lua/etc/noparser.c",
    "content": "/*\n* The code below can be used to make a Lua core that does not contain the\n* parsing modules (lcode, llex, lparser), which represent 35% of the total core.\n* You'll only be able to load binary files and strings, precompiled with luac.\n* (Of course, you'll have to build luac with the original parsing modules!)\n*\n* To use this module, simply compile it (\"make noparser\" does that) and list\n* its object file before the Lua libraries. The linker should then not load\n* the parsing modules. To try it, do \"make luab\".\n*\n* If you also want to avoid the dump module (ldump.o), define NODUMP.\n* #define NODUMP\n*/\n\n#define LUA_CORE\n\n#include \"llex.h\"\n#include \"lparser.h\"\n#include \"lzio.h\"\n\nLUAI_FUNC void luaX_init (lua_State *L) {\n  UNUSED(L);\n}\n\nLUAI_FUNC Proto *luaY_parser (lua_State *L, ZIO *z, Mbuffer *buff, const char *name) {\n  UNUSED(z);\n  UNUSED(buff);\n  UNUSED(name);\n  lua_pushliteral(L,\"parser not loaded\");\n  lua_error(L);\n  return NULL;\n}\n\n#ifdef NODUMP\n#include \"lundump.h\"\n\nLUAI_FUNC int luaU_dump (lua_State* L, const Proto* f, lua_Writer w, void* data, int strip) {\n  UNUSED(f);\n  UNUSED(w);\n  UNUSED(data);\n  UNUSED(strip);\n#if 1\n  UNUSED(L);\n  return 0;\n#else\n  lua_pushliteral(L,\"dumper not loaded\");\n  lua_error(L);\n#endif\n}\n#endif\n"
  },
  {
    "path": "extern/deprecated/redis-2.8.21/deps/lua/etc/strict.lua",
    "content": "--\n-- strict.lua\n-- checks uses of undeclared global variables\n-- All global variables must be 'declared' through a regular assignment\n-- (even assigning nil will do) in a main chunk before being used\n-- anywhere or assigned to inside a function.\n--\n\nlocal getinfo, error, rawset, rawget = debug.getinfo, error, rawset, rawget\n\nlocal mt = getmetatable(_G)\nif mt == nil then\n  mt = {}\n  setmetatable(_G, mt)\nend\n\nmt.__declared = {}\n\nlocal function what ()\n  local d = getinfo(3, \"S\")\n  return d and d.what or \"C\"\nend\n\nmt.__newindex = function (t, n, v)\n  if not mt.__declared[n] then\n    local w = what()\n    if w ~= \"main\" and w ~= \"C\" then\n      error(\"assign to undeclared variable '\"..n..\"'\", 2)\n    end\n    mt.__declared[n] = true\n  end\n  rawset(t, n, v)\nend\n  \nmt.__index = function (t, n)\n  if not mt.__declared[n] and what() ~= \"C\" then\n    error(\"variable '\"..n..\"' is not declared\", 2)\n  end\n  return rawget(t, n)\nend\n\n"
  },
  {
    "path": "extern/deprecated/redis-2.8.21/deps/lua/src/Makefile",
    "content": "# makefile for building Lua\n# see ../INSTALL for installation instructions\n# see ../Makefile and luaconf.h for further customization\n\n# == CHANGE THE SETTINGS BELOW TO SUIT YOUR ENVIRONMENT =======================\n\n# Your platform. See PLATS for possible values.\nPLAT= none\n\nCC?= gcc\nCFLAGS= -O2 -Wall $(MYCFLAGS)\nAR= ar rcu\nRANLIB= ranlib\nRM= rm -f\nLIBS= -lm $(MYLIBS)\n\nMYCFLAGS=\nMYLDFLAGS=\nMYLIBS=\n\n# == END OF USER SETTINGS. NO NEED TO CHANGE ANYTHING BELOW THIS LINE =========\n\nPLATS= aix ansi bsd freebsd generic linux macosx mingw posix solaris\n\nLUA_A=\tliblua.a\nCORE_O=\tlapi.o lcode.o ldebug.o ldo.o ldump.o lfunc.o lgc.o llex.o lmem.o \\\n\tlobject.o lopcodes.o lparser.o lstate.o lstring.o ltable.o ltm.o  \\\n\tlundump.o lvm.o lzio.o strbuf.o fpconv.o\nLIB_O=\tlauxlib.o lbaselib.o ldblib.o liolib.o lmathlib.o loslib.o ltablib.o \\\n\tlstrlib.o loadlib.o linit.o lua_cjson.o lua_struct.o lua_cmsgpack.o \\\n\tlua_bit.o\n\nLUA_T=\tlua\nLUA_O=\tlua.o\n\nLUAC_T=\tluac\nLUAC_O=\tluac.o print.o\n\nALL_O= $(CORE_O) $(LIB_O) $(LUA_O) $(LUAC_O)\nALL_T= $(LUA_A) $(LUA_T) $(LUAC_T)\nALL_A= $(LUA_A)\n\ndefault: $(PLAT)\n\nall:\t$(ALL_T)\n\no:\t$(ALL_O)\n\na:\t$(ALL_A)\n\n$(LUA_A): $(CORE_O) $(LIB_O)\n\t$(AR) $@ $(CORE_O) $(LIB_O)\t# DLL needs all object files\n\t$(RANLIB) $@\n\n$(LUA_T): $(LUA_O) $(LUA_A)\n\t$(CC) -o $@ $(MYLDFLAGS) $(LUA_O) $(LUA_A) $(LIBS)\n\n$(LUAC_T): $(LUAC_O) $(LUA_A)\n\t$(CC) -o $@ $(MYLDFLAGS) $(LUAC_O) $(LUA_A) $(LIBS)\n\nclean:\n\t$(RM) $(ALL_T) $(ALL_O)\n\ndepend:\n\t@$(CC) $(CFLAGS) -MM l*.c print.c\n\necho:\n\t@echo \"PLAT = $(PLAT)\"\n\t@echo \"CC = $(CC)\"\n\t@echo \"CFLAGS = $(CFLAGS)\"\n\t@echo \"AR = $(AR)\"\n\t@echo \"RANLIB = $(RANLIB)\"\n\t@echo \"RM = $(RM)\"\n\t@echo \"MYCFLAGS = $(MYCFLAGS)\"\n\t@echo \"MYLDFLAGS = $(MYLDFLAGS)\"\n\t@echo \"MYLIBS = $(MYLIBS)\"\n\n# convenience targets for popular platforms\n\nnone:\n\t@echo \"Please choose a platform:\"\n\t@echo \"   $(PLATS)\"\n\naix:\n\t$(MAKE) all CC=\"xlc\" CFLAGS=\"-O2 -DLUA_USE_POSIX -DLUA_USE_DLOPEN\" MYLIBS=\"-ldl\" MYLDFLAGS=\"-brtl -bexpall\"\n\nansi:\n\t$(MAKE) all MYCFLAGS=-DLUA_ANSI\n\nbsd:\n\t$(MAKE) all MYCFLAGS=\"-DLUA_USE_POSIX -DLUA_USE_DLOPEN\" MYLIBS=\"-Wl,-E\"\n\nfreebsd:\n\t$(MAKE) all MYCFLAGS=\"-DLUA_USE_LINUX\" MYLIBS=\"-Wl,-E -lreadline\"\n\ngeneric:\n\t$(MAKE) all MYCFLAGS=\n\nlinux:\n\t$(MAKE) all MYCFLAGS=-DLUA_USE_LINUX MYLIBS=\"-Wl,-E -ldl -lreadline -lhistory -lncurses\"\n\nmacosx:\n\t$(MAKE) all MYCFLAGS=-DLUA_USE_LINUX MYLIBS=\"-lreadline\"\n# use this on Mac OS X 10.3-\n#\t$(MAKE) all MYCFLAGS=-DLUA_USE_MACOSX\n\nmingw:\n\t$(MAKE) \"LUA_A=lua51.dll\" \"LUA_T=lua.exe\" \\\n\t\"AR=$(CC) -shared -o\" \"RANLIB=strip --strip-unneeded\" \\\n\t\"MYCFLAGS=-DLUA_BUILD_AS_DLL\" \"MYLIBS=\" \"MYLDFLAGS=-s\" lua.exe\n\t$(MAKE) \"LUAC_T=luac.exe\" luac.exe\n\nposix:\n\t$(MAKE) all MYCFLAGS=-DLUA_USE_POSIX\n\nsolaris:\n\t$(MAKE) all MYCFLAGS=\"-DLUA_USE_POSIX -DLUA_USE_DLOPEN\" MYLIBS=\"-ldl\"\n\n# list targets that do not create files (but not all makes understand .PHONY)\n.PHONY: all $(PLATS) default o a clean depend echo none\n\n# DO NOT DELETE\n\nlapi.o: lapi.c lua.h luaconf.h lapi.h lobject.h llimits.h ldebug.h \\\n  lstate.h ltm.h lzio.h lmem.h ldo.h lfunc.h lgc.h lstring.h ltable.h \\\n  lundump.h lvm.h\nlauxlib.o: lauxlib.c lua.h luaconf.h lauxlib.h\nlbaselib.o: lbaselib.c lua.h luaconf.h lauxlib.h lualib.h\nlcode.o: lcode.c lua.h luaconf.h lcode.h llex.h lobject.h llimits.h \\\n  lzio.h lmem.h lopcodes.h lparser.h ldebug.h lstate.h ltm.h ldo.h lgc.h \\\n  ltable.h\nldblib.o: ldblib.c lua.h luaconf.h lauxlib.h lualib.h\nldebug.o: ldebug.c lua.h luaconf.h lapi.h lobject.h llimits.h lcode.h \\\n  llex.h lzio.h lmem.h lopcodes.h lparser.h ldebug.h lstate.h ltm.h ldo.h \\\n  lfunc.h lstring.h lgc.h ltable.h lvm.h\nldo.o: ldo.c lua.h luaconf.h ldebug.h lstate.h lobject.h llimits.h ltm.h \\\n  lzio.h lmem.h ldo.h lfunc.h lgc.h lopcodes.h lparser.h lstring.h \\\n  ltable.h lundump.h lvm.h\nldump.o: ldump.c lua.h luaconf.h lobject.h llimits.h lstate.h ltm.h \\\n  lzio.h lmem.h lundump.h\nlfunc.o: lfunc.c lua.h luaconf.h lfunc.h lobject.h llimits.h lgc.h lmem.h \\\n  lstate.h ltm.h lzio.h\nlgc.o: lgc.c lua.h luaconf.h ldebug.h lstate.h lobject.h llimits.h ltm.h \\\n  lzio.h lmem.h ldo.h lfunc.h lgc.h lstring.h ltable.h\nlinit.o: linit.c lua.h luaconf.h lualib.h lauxlib.h\nliolib.o: liolib.c lua.h luaconf.h lauxlib.h lualib.h\nllex.o: llex.c lua.h luaconf.h ldo.h lobject.h llimits.h lstate.h ltm.h \\\n  lzio.h lmem.h llex.h lparser.h lstring.h lgc.h ltable.h\nlmathlib.o: lmathlib.c lua.h luaconf.h lauxlib.h lualib.h\nlmem.o: lmem.c lua.h luaconf.h ldebug.h lstate.h lobject.h llimits.h \\\n  ltm.h lzio.h lmem.h ldo.h\nloadlib.o: loadlib.c lua.h luaconf.h lauxlib.h lualib.h\nlobject.o: lobject.c lua.h luaconf.h ldo.h lobject.h llimits.h lstate.h \\\n  ltm.h lzio.h lmem.h lstring.h lgc.h lvm.h\nlopcodes.o: lopcodes.c lopcodes.h llimits.h lua.h luaconf.h\nloslib.o: loslib.c lua.h luaconf.h lauxlib.h lualib.h\nlparser.o: lparser.c lua.h luaconf.h lcode.h llex.h lobject.h llimits.h \\\n  lzio.h lmem.h lopcodes.h lparser.h ldebug.h lstate.h ltm.h ldo.h \\\n  lfunc.h lstring.h lgc.h ltable.h\nlstate.o: lstate.c lua.h luaconf.h ldebug.h lstate.h lobject.h llimits.h \\\n  ltm.h lzio.h lmem.h ldo.h lfunc.h lgc.h llex.h lstring.h ltable.h\nlstring.o: lstring.c lua.h luaconf.h lmem.h llimits.h lobject.h lstate.h \\\n  ltm.h lzio.h lstring.h lgc.h\nlstrlib.o: lstrlib.c lua.h luaconf.h lauxlib.h lualib.h\nltable.o: ltable.c lua.h luaconf.h ldebug.h lstate.h lobject.h llimits.h \\\n  ltm.h lzio.h lmem.h ldo.h lgc.h ltable.h\nltablib.o: ltablib.c lua.h luaconf.h lauxlib.h lualib.h\nltm.o: ltm.c lua.h luaconf.h lobject.h llimits.h lstate.h ltm.h lzio.h \\\n  lmem.h lstring.h lgc.h ltable.h\nlua.o: lua.c lua.h luaconf.h lauxlib.h lualib.h\nluac.o: luac.c lua.h luaconf.h lauxlib.h ldo.h lobject.h llimits.h \\\n  lstate.h ltm.h lzio.h lmem.h lfunc.h lopcodes.h lstring.h lgc.h \\\n  lundump.h\nlundump.o: lundump.c lua.h luaconf.h ldebug.h lstate.h lobject.h \\\n  llimits.h ltm.h lzio.h lmem.h ldo.h lfunc.h lstring.h lgc.h lundump.h\nlvm.o: lvm.c lua.h luaconf.h ldebug.h lstate.h lobject.h llimits.h ltm.h \\\n  lzio.h lmem.h ldo.h lfunc.h lgc.h lopcodes.h lstring.h ltable.h lvm.h\nlzio.o: lzio.c lua.h luaconf.h llimits.h lmem.h lstate.h lobject.h ltm.h \\\n  lzio.h\nprint.o: print.c ldebug.h lstate.h lua.h luaconf.h lobject.h llimits.h \\\n  ltm.h lzio.h lmem.h lopcodes.h lundump.h\n\n# (end of Makefile)\n"
  },
  {
    "path": "extern/deprecated/redis-2.8.21/deps/lua/src/fpconv.c",
    "content": "/* fpconv - Floating point conversion routines\n *\n * Copyright (c) 2011-2012  Mark Pulford <mark@kyne.com.au>\n *\n * Permission is hereby granted, free of charge, to any person obtaining\n * a copy of this software and associated documentation files (the\n * \"Software\"), to deal in the Software without restriction, including\n * without limitation the rights to use, copy, modify, merge, publish,\n * distribute, sublicense, and/or sell copies of the Software, and to\n * permit persons to whom the Software is furnished to do so, subject to\n * the following conditions:\n *\n * The above copyright notice and this permission notice shall be\n * included in all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND,\n * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\n * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.\n * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY\n * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,\n * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE\n * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n */\n\n/* JSON uses a '.' decimal separator. strtod() / sprintf() under C libraries\n * with locale support will break when the decimal separator is a comma.\n *\n * fpconv_* will around these issues with a translation buffer if required.\n */\n\n#include <stdio.h>\n#include <stdlib.h>\n#include <assert.h>\n#include <string.h>\n\n#include \"fpconv.h\"\n\n/* Lua CJSON assumes the locale is the same for all threads within a\n * process and doesn't change after initialisation.\n *\n * This avoids the need for per thread storage or expensive checks\n * for call. */\nstatic char locale_decimal_point = '.';\n\n/* In theory multibyte decimal_points are possible, but\n * Lua CJSON only supports UTF-8 and known locales only have\n * single byte decimal points ([.,]).\n *\n * localconv() may not be thread safe (=>crash), and nl_langinfo() is\n * not supported on some platforms. Use sprintf() instead - if the\n * locale does change, at least Lua CJSON won't crash. */\nstatic void fpconv_update_locale()\n{\n    char buf[8];\n\n    snprintf(buf, sizeof(buf), \"%g\", 0.5);\n\n    /* Failing this test might imply the platform has a buggy dtoa\n     * implementation or wide characters */\n    if (buf[0] != '0' || buf[2] != '5' || buf[3] != 0) {\n        fprintf(stderr, \"Error: wide characters found or printf() bug.\");\n        abort();\n    }\n\n    locale_decimal_point = buf[1];\n}\n\n/* Check for a valid number character: [-+0-9a-yA-Y.]\n * Eg: -0.6e+5, infinity, 0xF0.F0pF0\n *\n * Used to find the probable end of a number. It doesn't matter if\n * invalid characters are counted - strtod() will find the valid\n * number if it exists.  The risk is that slightly more memory might\n * be allocated before a parse error occurs. */\nstatic inline int valid_number_character(char ch)\n{\n    char lower_ch;\n\n    if ('0' <= ch && ch <= '9')\n        return 1;\n    if (ch == '-' || ch == '+' || ch == '.')\n        return 1;\n\n    /* Hex digits, exponent (e), base (p), \"infinity\",.. */\n    lower_ch = ch | 0x20;\n    if ('a' <= lower_ch && lower_ch <= 'y')\n        return 1;\n\n    return 0;\n}\n\n/* Calculate the size of the buffer required for a strtod locale\n * conversion. */\nstatic int strtod_buffer_size(const char *s)\n{\n    const char *p = s;\n\n    while (valid_number_character(*p))\n        p++;\n\n    return p - s;\n}\n\n/* Similar to strtod(), but must be passed the current locale's decimal point\n * character. Guaranteed to be called at the start of any valid number in a string */\ndouble fpconv_strtod(const char *nptr, char **endptr)\n{\n    char localbuf[FPCONV_G_FMT_BUFSIZE];\n    char *buf, *endbuf, *dp;\n    int buflen;\n    double value;\n\n    /* System strtod() is fine when decimal point is '.' */\n    if (locale_decimal_point == '.')\n        return strtod(nptr, endptr);\n\n    buflen = strtod_buffer_size(nptr);\n    if (!buflen) {\n        /* No valid characters found, standard strtod() return */\n        *endptr = (char *)nptr;\n        return 0;\n    }\n\n    /* Duplicate number into buffer */\n    if (buflen >= FPCONV_G_FMT_BUFSIZE) {\n        /* Handle unusually large numbers */\n        buf = malloc(buflen + 1);\n        if (!buf) {\n            fprintf(stderr, \"Out of memory\");\n            abort();\n        }\n    } else {\n        /* This is the common case.. */\n        buf = localbuf;\n    }\n    memcpy(buf, nptr, buflen);\n    buf[buflen] = 0;\n\n    /* Update decimal point character if found */\n    dp = strchr(buf, '.');\n    if (dp)\n        *dp = locale_decimal_point;\n\n    value = strtod(buf, &endbuf);\n    *endptr = (char *)&nptr[endbuf - buf];\n    if (buflen >= FPCONV_G_FMT_BUFSIZE)\n        free(buf);\n\n    return value;\n}\n\n/* \"fmt\" must point to a buffer of at least 6 characters */\nstatic void set_number_format(char *fmt, int precision)\n{\n    int d1, d2, i;\n\n    assert(1 <= precision && precision <= 14);\n\n    /* Create printf format (%.14g) from precision */\n    d1 = precision / 10;\n    d2 = precision % 10;\n    fmt[0] = '%';\n    fmt[1] = '.';\n    i = 2;\n    if (d1) {\n        fmt[i++] = '0' + d1;\n    }\n    fmt[i++] = '0' + d2;\n    fmt[i++] = 'g';\n    fmt[i] = 0;\n}\n\n/* Assumes there is always at least 32 characters available in the target buffer */\nint fpconv_g_fmt(char *str, double num, int precision)\n{\n    char buf[FPCONV_G_FMT_BUFSIZE];\n    char fmt[6];\n    int len;\n    char *b;\n\n    set_number_format(fmt, precision);\n\n    /* Pass through when decimal point character is dot. */\n    if (locale_decimal_point == '.')\n        return snprintf(str, FPCONV_G_FMT_BUFSIZE, fmt, num);\n\n    /* snprintf() to a buffer then translate for other decimal point characters */\n    len = snprintf(buf, FPCONV_G_FMT_BUFSIZE, fmt, num);\n\n    /* Copy into target location. Translate decimal point if required */\n    b = buf;\n    do {\n        *str++ = (*b == locale_decimal_point ? '.' : *b);\n    } while(*b++);\n\n    return len;\n}\n\nvoid fpconv_init()\n{\n    fpconv_update_locale();\n}\n\n/* vi:ai et sw=4 ts=4:\n */\n"
  },
  {
    "path": "extern/deprecated/redis-2.8.21/deps/lua/src/fpconv.h",
    "content": "/* Lua CJSON floating point conversion routines */\n\n/* Buffer required to store the largest string representation of a double.\n *\n * Longest double printed with %.14g is 21 characters long:\n * -1.7976931348623e+308 */\n# define FPCONV_G_FMT_BUFSIZE   32\n\n#ifdef USE_INTERNAL_FPCONV\nstatic inline void fpconv_init()\n{\n    /* Do nothing - not required */\n}\n#else\nextern void fpconv_init();\n#endif\n\nextern int fpconv_g_fmt(char*, double, int);\nextern double fpconv_strtod(const char*, char**);\n\n/* vi:ai et sw=4 ts=4:\n */\n"
  },
  {
    "path": "extern/deprecated/redis-2.8.21/deps/lua/src/lapi.c",
    "content": "/*\n** $Id: lapi.c,v 2.55.1.5 2008/07/04 18:41:18 roberto Exp $\n** Lua API\n** See Copyright Notice in lua.h\n*/\n\n\n#include <assert.h>\n#include <math.h>\n#include <stdarg.h>\n#include <string.h>\n\n#define lapi_c\n#define LUA_CORE\n\n#include \"lua.h\"\n\n#include \"lapi.h\"\n#include \"ldebug.h\"\n#include \"ldo.h\"\n#include \"lfunc.h\"\n#include \"lgc.h\"\n#include \"lmem.h\"\n#include \"lobject.h\"\n#include \"lstate.h\"\n#include \"lstring.h\"\n#include \"ltable.h\"\n#include \"ltm.h\"\n#include \"lundump.h\"\n#include \"lvm.h\"\n\n\n\nconst char lua_ident[] =\n  \"$Lua: \" LUA_RELEASE \" \" LUA_COPYRIGHT \" $\\n\"\n  \"$Authors: \" LUA_AUTHORS \" $\\n\"\n  \"$URL: www.lua.org $\\n\";\n\n\n\n#define api_checknelems(L, n)\tapi_check(L, (n) <= (L->top - L->base))\n\n#define api_checkvalidindex(L, i)\tapi_check(L, (i) != luaO_nilobject)\n\n#define api_incr_top(L)   {api_check(L, L->top < L->ci->top); L->top++;}\n\n\n\nstatic TValue *index2adr (lua_State *L, int idx) {\n  if (idx > 0) {\n    TValue *o = L->base + (idx - 1);\n    api_check(L, idx <= L->ci->top - L->base);\n    if (o >= L->top) return cast(TValue *, luaO_nilobject);\n    else return o;\n  }\n  else if (idx > LUA_REGISTRYINDEX) {\n    api_check(L, idx != 0 && -idx <= L->top - L->base);\n    return L->top + idx;\n  }\n  else switch (idx) {  /* pseudo-indices */\n    case LUA_REGISTRYINDEX: return registry(L);\n    case LUA_ENVIRONINDEX: {\n      Closure *func = curr_func(L);\n      sethvalue(L, &L->env, func->c.env);\n      return &L->env;\n    }\n    case LUA_GLOBALSINDEX: return gt(L);\n    default: {\n      Closure *func = curr_func(L);\n      idx = LUA_GLOBALSINDEX - idx;\n      return (idx <= func->c.nupvalues)\n                ? &func->c.upvalue[idx-1]\n                : cast(TValue *, luaO_nilobject);\n    }\n  }\n}\n\n\nstatic Table *getcurrenv (lua_State *L) {\n  if (L->ci == L->base_ci)  /* no enclosing function? */\n    return hvalue(gt(L));  /* use global table as environment */\n  else {\n    Closure *func = curr_func(L);\n    return func->c.env;\n  }\n}\n\n\nvoid luaA_pushobject (lua_State *L, const TValue *o) {\n  setobj2s(L, L->top, o);\n  api_incr_top(L);\n}\n\n\nLUA_API int lua_checkstack (lua_State *L, int size) {\n  int res = 1;\n  lua_lock(L);\n  if (size > LUAI_MAXCSTACK || (L->top - L->base + size) > LUAI_MAXCSTACK)\n    res = 0;  /* stack overflow */\n  else if (size > 0) {\n    luaD_checkstack(L, size);\n    if (L->ci->top < L->top + size)\n      L->ci->top = L->top + size;\n  }\n  lua_unlock(L);\n  return res;\n}\n\n\nLUA_API void lua_xmove (lua_State *from, lua_State *to, int n) {\n  int i;\n  if (from == to) return;\n  lua_lock(to);\n  api_checknelems(from, n);\n  api_check(from, G(from) == G(to));\n  api_check(from, to->ci->top - to->top >= n);\n  from->top -= n;\n  for (i = 0; i < n; i++) {\n    setobj2s(to, to->top++, from->top + i);\n  }\n  lua_unlock(to);\n}\n\n\nLUA_API void lua_setlevel (lua_State *from, lua_State *to) {\n  to->nCcalls = from->nCcalls;\n}\n\n\nLUA_API lua_CFunction lua_atpanic (lua_State *L, lua_CFunction panicf) {\n  lua_CFunction old;\n  lua_lock(L);\n  old = G(L)->panic;\n  G(L)->panic = panicf;\n  lua_unlock(L);\n  return old;\n}\n\n\nLUA_API lua_State *lua_newthread (lua_State *L) {\n  lua_State *L1;\n  lua_lock(L);\n  luaC_checkGC(L);\n  L1 = luaE_newthread(L);\n  setthvalue(L, L->top, L1);\n  api_incr_top(L);\n  lua_unlock(L);\n  luai_userstatethread(L, L1);\n  return L1;\n}\n\n\n\n/*\n** basic stack manipulation\n*/\n\n\nLUA_API int lua_gettop (lua_State *L) {\n  return cast_int(L->top - L->base);\n}\n\n\nLUA_API void lua_settop (lua_State *L, int idx) {\n  lua_lock(L);\n  if (idx >= 0) {\n    api_check(L, idx <= L->stack_last - L->base);\n    while (L->top < L->base + idx)\n      setnilvalue(L->top++);\n    L->top = L->base + idx;\n  }\n  else {\n    api_check(L, -(idx+1) <= (L->top - L->base));\n    L->top += idx+1;  /* `subtract' index (index is negative) */\n  }\n  lua_unlock(L);\n}\n\n\nLUA_API void lua_remove (lua_State *L, int idx) {\n  StkId p;\n  lua_lock(L);\n  p = index2adr(L, idx);\n  api_checkvalidindex(L, p);\n  while (++p < L->top) setobjs2s(L, p-1, p);\n  L->top--;\n  lua_unlock(L);\n}\n\n\nLUA_API void lua_insert (lua_State *L, int idx) {\n  StkId p;\n  StkId q;\n  lua_lock(L);\n  p = index2adr(L, idx);\n  api_checkvalidindex(L, p);\n  for (q = L->top; q>p; q--) setobjs2s(L, q, q-1);\n  setobjs2s(L, p, L->top);\n  lua_unlock(L);\n}\n\n\nLUA_API void lua_replace (lua_State *L, int idx) {\n  StkId o;\n  lua_lock(L);\n  /* explicit test for incompatible code */\n  if (idx == LUA_ENVIRONINDEX && L->ci == L->base_ci)\n    luaG_runerror(L, \"no calling environment\");\n  api_checknelems(L, 1);\n  o = index2adr(L, idx);\n  api_checkvalidindex(L, o);\n  if (idx == LUA_ENVIRONINDEX) {\n    Closure *func = curr_func(L);\n    api_check(L, ttistable(L->top - 1)); \n    func->c.env = hvalue(L->top - 1);\n    luaC_barrier(L, func, L->top - 1);\n  }\n  else {\n    setobj(L, o, L->top - 1);\n    if (idx < LUA_GLOBALSINDEX)  /* function upvalue? */\n      luaC_barrier(L, curr_func(L), L->top - 1);\n  }\n  L->top--;\n  lua_unlock(L);\n}\n\n\nLUA_API void lua_pushvalue (lua_State *L, int idx) {\n  lua_lock(L);\n  setobj2s(L, L->top, index2adr(L, idx));\n  api_incr_top(L);\n  lua_unlock(L);\n}\n\n\n\n/*\n** access functions (stack -> C)\n*/\n\n\nLUA_API int lua_type (lua_State *L, int idx) {\n  StkId o = index2adr(L, idx);\n  return (o == luaO_nilobject) ? LUA_TNONE : ttype(o);\n}\n\n\nLUA_API const char *lua_typename (lua_State *L, int t) {\n  UNUSED(L);\n  return (t == LUA_TNONE) ? \"no value\" : luaT_typenames[t];\n}\n\n\nLUA_API int lua_iscfunction (lua_State *L, int idx) {\n  StkId o = index2adr(L, idx);\n  return iscfunction(o);\n}\n\n\nLUA_API int lua_isnumber (lua_State *L, int idx) {\n  TValue n;\n  const TValue *o = index2adr(L, idx);\n  return tonumber(o, &n);\n}\n\n\nLUA_API int lua_isstring (lua_State *L, int idx) {\n  int t = lua_type(L, idx);\n  return (t == LUA_TSTRING || t == LUA_TNUMBER);\n}\n\n\nLUA_API int lua_isuserdata (lua_State *L, int idx) {\n  const TValue *o = index2adr(L, idx);\n  return (ttisuserdata(o) || ttislightuserdata(o));\n}\n\n\nLUA_API int lua_rawequal (lua_State *L, int index1, int index2) {\n  StkId o1 = index2adr(L, index1);\n  StkId o2 = index2adr(L, index2);\n  return (o1 == luaO_nilobject || o2 == luaO_nilobject) ? 0\n         : luaO_rawequalObj(o1, o2);\n}\n\n\nLUA_API int lua_equal (lua_State *L, int index1, int index2) {\n  StkId o1, o2;\n  int i;\n  lua_lock(L);  /* may call tag method */\n  o1 = index2adr(L, index1);\n  o2 = index2adr(L, index2);\n  i = (o1 == luaO_nilobject || o2 == luaO_nilobject) ? 0 : equalobj(L, o1, o2);\n  lua_unlock(L);\n  return i;\n}\n\n\nLUA_API int lua_lessthan (lua_State *L, int index1, int index2) {\n  StkId o1, o2;\n  int i;\n  lua_lock(L);  /* may call tag method */\n  o1 = index2adr(L, index1);\n  o2 = index2adr(L, index2);\n  i = (o1 == luaO_nilobject || o2 == luaO_nilobject) ? 0\n       : luaV_lessthan(L, o1, o2);\n  lua_unlock(L);\n  return i;\n}\n\n\n\nLUA_API lua_Number lua_tonumber (lua_State *L, int idx) {\n  TValue n;\n  const TValue *o = index2adr(L, idx);\n  if (tonumber(o, &n))\n    return nvalue(o);\n  else\n    return 0;\n}\n\n\nLUA_API lua_Integer lua_tointeger (lua_State *L, int idx) {\n  TValue n;\n  const TValue *o = index2adr(L, idx);\n  if (tonumber(o, &n)) {\n    lua_Integer res;\n    lua_Number num = nvalue(o);\n    lua_number2integer(res, num);\n    return res;\n  }\n  else\n    return 0;\n}\n\n\nLUA_API int lua_toboolean (lua_State *L, int idx) {\n  const TValue *o = index2adr(L, idx);\n  return !l_isfalse(o);\n}\n\n\nLUA_API const char *lua_tolstring (lua_State *L, int idx, size_t *len) {\n  StkId o = index2adr(L, idx);\n  if (!ttisstring(o)) {\n    lua_lock(L);  /* `luaV_tostring' may create a new string */\n    if (!luaV_tostring(L, o)) {  /* conversion failed? */\n      if (len != NULL) *len = 0;\n      lua_unlock(L);\n      return NULL;\n    }\n    luaC_checkGC(L);\n    o = index2adr(L, idx);  /* previous call may reallocate the stack */\n    lua_unlock(L);\n  }\n  if (len != NULL) *len = tsvalue(o)->len;\n  return svalue(o);\n}\n\n\nLUA_API size_t lua_objlen (lua_State *L, int idx) {\n  StkId o = index2adr(L, idx);\n  switch (ttype(o)) {\n    case LUA_TSTRING: return tsvalue(o)->len;\n    case LUA_TUSERDATA: return uvalue(o)->len;\n    case LUA_TTABLE: return luaH_getn(hvalue(o));\n    case LUA_TNUMBER: {\n      size_t l;\n      lua_lock(L);  /* `luaV_tostring' may create a new string */\n      l = (luaV_tostring(L, o) ? tsvalue(o)->len : 0);\n      lua_unlock(L);\n      return l;\n    }\n    default: return 0;\n  }\n}\n\n\nLUA_API lua_CFunction lua_tocfunction (lua_State *L, int idx) {\n  StkId o = index2adr(L, idx);\n  return (!iscfunction(o)) ? NULL : clvalue(o)->c.f;\n}\n\n\nLUA_API void *lua_touserdata (lua_State *L, int idx) {\n  StkId o = index2adr(L, idx);\n  switch (ttype(o)) {\n    case LUA_TUSERDATA: return (rawuvalue(o) + 1);\n    case LUA_TLIGHTUSERDATA: return pvalue(o);\n    default: return NULL;\n  }\n}\n\n\nLUA_API lua_State *lua_tothread (lua_State *L, int idx) {\n  StkId o = index2adr(L, idx);\n  return (!ttisthread(o)) ? NULL : thvalue(o);\n}\n\n\nLUA_API const void *lua_topointer (lua_State *L, int idx) {\n  StkId o = index2adr(L, idx);\n  switch (ttype(o)) {\n    case LUA_TTABLE: return hvalue(o);\n    case LUA_TFUNCTION: return clvalue(o);\n    case LUA_TTHREAD: return thvalue(o);\n    case LUA_TUSERDATA:\n    case LUA_TLIGHTUSERDATA:\n      return lua_touserdata(L, idx);\n    default: return NULL;\n  }\n}\n\n\n\n/*\n** push functions (C -> stack)\n*/\n\n\nLUA_API void lua_pushnil (lua_State *L) {\n  lua_lock(L);\n  setnilvalue(L->top);\n  api_incr_top(L);\n  lua_unlock(L);\n}\n\n\nLUA_API void lua_pushnumber (lua_State *L, lua_Number n) {\n  lua_lock(L);\n  setnvalue(L->top, n);\n  api_incr_top(L);\n  lua_unlock(L);\n}\n\n\nLUA_API void lua_pushinteger (lua_State *L, lua_Integer n) {\n  lua_lock(L);\n  setnvalue(L->top, cast_num(n));\n  api_incr_top(L);\n  lua_unlock(L);\n}\n\n\nLUA_API void lua_pushlstring (lua_State *L, const char *s, size_t len) {\n  lua_lock(L);\n  luaC_checkGC(L);\n  setsvalue2s(L, L->top, luaS_newlstr(L, s, len));\n  api_incr_top(L);\n  lua_unlock(L);\n}\n\n\nLUA_API void lua_pushstring (lua_State *L, const char *s) {\n  if (s == NULL)\n    lua_pushnil(L);\n  else\n    lua_pushlstring(L, s, strlen(s));\n}\n\n\nLUA_API const char *lua_pushvfstring (lua_State *L, const char *fmt,\n                                      va_list argp) {\n  const char *ret;\n  lua_lock(L);\n  luaC_checkGC(L);\n  ret = luaO_pushvfstring(L, fmt, argp);\n  lua_unlock(L);\n  return ret;\n}\n\n\nLUA_API const char *lua_pushfstring (lua_State *L, const char *fmt, ...) {\n  const char *ret;\n  va_list argp;\n  lua_lock(L);\n  luaC_checkGC(L);\n  va_start(argp, fmt);\n  ret = luaO_pushvfstring(L, fmt, argp);\n  va_end(argp);\n  lua_unlock(L);\n  return ret;\n}\n\n\nLUA_API void lua_pushcclosure (lua_State *L, lua_CFunction fn, int n) {\n  Closure *cl;\n  lua_lock(L);\n  luaC_checkGC(L);\n  api_checknelems(L, n);\n  cl = luaF_newCclosure(L, n, getcurrenv(L));\n  cl->c.f = fn;\n  L->top -= n;\n  while (n--)\n    setobj2n(L, &cl->c.upvalue[n], L->top+n);\n  setclvalue(L, L->top, cl);\n  lua_assert(iswhite(obj2gco(cl)));\n  api_incr_top(L);\n  lua_unlock(L);\n}\n\n\nLUA_API void lua_pushboolean (lua_State *L, int b) {\n  lua_lock(L);\n  setbvalue(L->top, (b != 0));  /* ensure that true is 1 */\n  api_incr_top(L);\n  lua_unlock(L);\n}\n\n\nLUA_API void lua_pushlightuserdata (lua_State *L, void *p) {\n  lua_lock(L);\n  setpvalue(L->top, p);\n  api_incr_top(L);\n  lua_unlock(L);\n}\n\n\nLUA_API int lua_pushthread (lua_State *L) {\n  lua_lock(L);\n  setthvalue(L, L->top, L);\n  api_incr_top(L);\n  lua_unlock(L);\n  return (G(L)->mainthread == L);\n}\n\n\n\n/*\n** get functions (Lua -> stack)\n*/\n\n\nLUA_API void lua_gettable (lua_State *L, int idx) {\n  StkId t;\n  lua_lock(L);\n  t = index2adr(L, idx);\n  api_checkvalidindex(L, t);\n  luaV_gettable(L, t, L->top - 1, L->top - 1);\n  lua_unlock(L);\n}\n\n\nLUA_API void lua_getfield (lua_State *L, int idx, const char *k) {\n  StkId t;\n  TValue key;\n  lua_lock(L);\n  t = index2adr(L, idx);\n  api_checkvalidindex(L, t);\n  setsvalue(L, &key, luaS_new(L, k));\n  luaV_gettable(L, t, &key, L->top);\n  api_incr_top(L);\n  lua_unlock(L);\n}\n\n\nLUA_API void lua_rawget (lua_State *L, int idx) {\n  StkId t;\n  lua_lock(L);\n  t = index2adr(L, idx);\n  api_check(L, ttistable(t));\n  setobj2s(L, L->top - 1, luaH_get(hvalue(t), L->top - 1));\n  lua_unlock(L);\n}\n\n\nLUA_API void lua_rawgeti (lua_State *L, int idx, int n) {\n  StkId o;\n  lua_lock(L);\n  o = index2adr(L, idx);\n  api_check(L, ttistable(o));\n  setobj2s(L, L->top, luaH_getnum(hvalue(o), n));\n  api_incr_top(L);\n  lua_unlock(L);\n}\n\n\nLUA_API void lua_createtable (lua_State *L, int narray, int nrec) {\n  lua_lock(L);\n  luaC_checkGC(L);\n  sethvalue(L, L->top, luaH_new(L, narray, nrec));\n  api_incr_top(L);\n  lua_unlock(L);\n}\n\n\nLUA_API int lua_getmetatable (lua_State *L, int objindex) {\n  const TValue *obj;\n  Table *mt = NULL;\n  int res;\n  lua_lock(L);\n  obj = index2adr(L, objindex);\n  switch (ttype(obj)) {\n    case LUA_TTABLE:\n      mt = hvalue(obj)->metatable;\n      break;\n    case LUA_TUSERDATA:\n      mt = uvalue(obj)->metatable;\n      break;\n    default:\n      mt = G(L)->mt[ttype(obj)];\n      break;\n  }\n  if (mt == NULL)\n    res = 0;\n  else {\n    sethvalue(L, L->top, mt);\n    api_incr_top(L);\n    res = 1;\n  }\n  lua_unlock(L);\n  return res;\n}\n\n\nLUA_API void lua_getfenv (lua_State *L, int idx) {\n  StkId o;\n  lua_lock(L);\n  o = index2adr(L, idx);\n  api_checkvalidindex(L, o);\n  switch (ttype(o)) {\n    case LUA_TFUNCTION:\n      sethvalue(L, L->top, clvalue(o)->c.env);\n      break;\n    case LUA_TUSERDATA:\n      sethvalue(L, L->top, uvalue(o)->env);\n      break;\n    case LUA_TTHREAD:\n      setobj2s(L, L->top,  gt(thvalue(o)));\n      break;\n    default:\n      setnilvalue(L->top);\n      break;\n  }\n  api_incr_top(L);\n  lua_unlock(L);\n}\n\n\n/*\n** set functions (stack -> Lua)\n*/\n\n\nLUA_API void lua_settable (lua_State *L, int idx) {\n  StkId t;\n  lua_lock(L);\n  api_checknelems(L, 2);\n  t = index2adr(L, idx);\n  api_checkvalidindex(L, t);\n  luaV_settable(L, t, L->top - 2, L->top - 1);\n  L->top -= 2;  /* pop index and value */\n  lua_unlock(L);\n}\n\n\nLUA_API void lua_setfield (lua_State *L, int idx, const char *k) {\n  StkId t;\n  TValue key;\n  lua_lock(L);\n  api_checknelems(L, 1);\n  t = index2adr(L, idx);\n  api_checkvalidindex(L, t);\n  setsvalue(L, &key, luaS_new(L, k));\n  luaV_settable(L, t, &key, L->top - 1);\n  L->top--;  /* pop value */\n  lua_unlock(L);\n}\n\n\nLUA_API void lua_rawset (lua_State *L, int idx) {\n  StkId t;\n  lua_lock(L);\n  api_checknelems(L, 2);\n  t = index2adr(L, idx);\n  api_check(L, ttistable(t));\n  setobj2t(L, luaH_set(L, hvalue(t), L->top-2), L->top-1);\n  luaC_barriert(L, hvalue(t), L->top-1);\n  L->top -= 2;\n  lua_unlock(L);\n}\n\n\nLUA_API void lua_rawseti (lua_State *L, int idx, int n) {\n  StkId o;\n  lua_lock(L);\n  api_checknelems(L, 1);\n  o = index2adr(L, idx);\n  api_check(L, ttistable(o));\n  setobj2t(L, luaH_setnum(L, hvalue(o), n), L->top-1);\n  luaC_barriert(L, hvalue(o), L->top-1);\n  L->top--;\n  lua_unlock(L);\n}\n\n\nLUA_API int lua_setmetatable (lua_State *L, int objindex) {\n  TValue *obj;\n  Table *mt;\n  lua_lock(L);\n  api_checknelems(L, 1);\n  obj = index2adr(L, objindex);\n  api_checkvalidindex(L, obj);\n  if (ttisnil(L->top - 1))\n    mt = NULL;\n  else {\n    api_check(L, ttistable(L->top - 1));\n    mt = hvalue(L->top - 1);\n  }\n  switch (ttype(obj)) {\n    case LUA_TTABLE: {\n      hvalue(obj)->metatable = mt;\n      if (mt)\n        luaC_objbarriert(L, hvalue(obj), mt);\n      break;\n    }\n    case LUA_TUSERDATA: {\n      uvalue(obj)->metatable = mt;\n      if (mt)\n        luaC_objbarrier(L, rawuvalue(obj), mt);\n      break;\n    }\n    default: {\n      G(L)->mt[ttype(obj)] = mt;\n      break;\n    }\n  }\n  L->top--;\n  lua_unlock(L);\n  return 1;\n}\n\n\nLUA_API int lua_setfenv (lua_State *L, int idx) {\n  StkId o;\n  int res = 1;\n  lua_lock(L);\n  api_checknelems(L, 1);\n  o = index2adr(L, idx);\n  api_checkvalidindex(L, o);\n  api_check(L, ttistable(L->top - 1));\n  switch (ttype(o)) {\n    case LUA_TFUNCTION:\n      clvalue(o)->c.env = hvalue(L->top - 1);\n      break;\n    case LUA_TUSERDATA:\n      uvalue(o)->env = hvalue(L->top - 1);\n      break;\n    case LUA_TTHREAD:\n      sethvalue(L, gt(thvalue(o)), hvalue(L->top - 1));\n      break;\n    default:\n      res = 0;\n      break;\n  }\n  if (res) luaC_objbarrier(L, gcvalue(o), hvalue(L->top - 1));\n  L->top--;\n  lua_unlock(L);\n  return res;\n}\n\n\n/*\n** `load' and `call' functions (run Lua code)\n*/\n\n\n#define adjustresults(L,nres) \\\n    { if (nres == LUA_MULTRET && L->top >= L->ci->top) L->ci->top = L->top; }\n\n\n#define checkresults(L,na,nr) \\\n     api_check(L, (nr) == LUA_MULTRET || (L->ci->top - L->top >= (nr) - (na)))\n\t\n\nLUA_API void lua_call (lua_State *L, int nargs, int nresults) {\n  StkId func;\n  lua_lock(L);\n  api_checknelems(L, nargs+1);\n  checkresults(L, nargs, nresults);\n  func = L->top - (nargs+1);\n  luaD_call(L, func, nresults);\n  adjustresults(L, nresults);\n  lua_unlock(L);\n}\n\n\n\n/*\n** Execute a protected call.\n*/\nstruct CallS {  /* data to `f_call' */\n  StkId func;\n  int nresults;\n};\n\n\nstatic void f_call (lua_State *L, void *ud) {\n  struct CallS *c = cast(struct CallS *, ud);\n  luaD_call(L, c->func, c->nresults);\n}\n\n\n\nLUA_API int lua_pcall (lua_State *L, int nargs, int nresults, int errfunc) {\n  struct CallS c;\n  int status;\n  ptrdiff_t func;\n  lua_lock(L);\n  api_checknelems(L, nargs+1);\n  checkresults(L, nargs, nresults);\n  if (errfunc == 0)\n    func = 0;\n  else {\n    StkId o = index2adr(L, errfunc);\n    api_checkvalidindex(L, o);\n    func = savestack(L, o);\n  }\n  c.func = L->top - (nargs+1);  /* function to be called */\n  c.nresults = nresults;\n  status = luaD_pcall(L, f_call, &c, savestack(L, c.func), func);\n  adjustresults(L, nresults);\n  lua_unlock(L);\n  return status;\n}\n\n\n/*\n** Execute a protected C call.\n*/\nstruct CCallS {  /* data to `f_Ccall' */\n  lua_CFunction func;\n  void *ud;\n};\n\n\nstatic void f_Ccall (lua_State *L, void *ud) {\n  struct CCallS *c = cast(struct CCallS *, ud);\n  Closure *cl;\n  cl = luaF_newCclosure(L, 0, getcurrenv(L));\n  cl->c.f = c->func;\n  setclvalue(L, L->top, cl);  /* push function */\n  api_incr_top(L);\n  setpvalue(L->top, c->ud);  /* push only argument */\n  api_incr_top(L);\n  luaD_call(L, L->top - 2, 0);\n}\n\n\nLUA_API int lua_cpcall (lua_State *L, lua_CFunction func, void *ud) {\n  struct CCallS c;\n  int status;\n  lua_lock(L);\n  c.func = func;\n  c.ud = ud;\n  status = luaD_pcall(L, f_Ccall, &c, savestack(L, L->top), 0);\n  lua_unlock(L);\n  return status;\n}\n\n\nLUA_API int lua_load (lua_State *L, lua_Reader reader, void *data,\n                      const char *chunkname) {\n  ZIO z;\n  int status;\n  lua_lock(L);\n  if (!chunkname) chunkname = \"?\";\n  luaZ_init(L, &z, reader, data);\n  status = luaD_protectedparser(L, &z, chunkname);\n  lua_unlock(L);\n  return status;\n}\n\n\nLUA_API int lua_dump (lua_State *L, lua_Writer writer, void *data) {\n  int status;\n  TValue *o;\n  lua_lock(L);\n  api_checknelems(L, 1);\n  o = L->top - 1;\n  if (isLfunction(o))\n    status = luaU_dump(L, clvalue(o)->l.p, writer, data, 0);\n  else\n    status = 1;\n  lua_unlock(L);\n  return status;\n}\n\n\nLUA_API int  lua_status (lua_State *L) {\n  return L->status;\n}\n\n\n/*\n** Garbage-collection function\n*/\n\nLUA_API int lua_gc (lua_State *L, int what, int data) {\n  int res = 0;\n  global_State *g;\n  lua_lock(L);\n  g = G(L);\n  switch (what) {\n    case LUA_GCSTOP: {\n      g->GCthreshold = MAX_LUMEM;\n      break;\n    }\n    case LUA_GCRESTART: {\n      g->GCthreshold = g->totalbytes;\n      break;\n    }\n    case LUA_GCCOLLECT: {\n      luaC_fullgc(L);\n      break;\n    }\n    case LUA_GCCOUNT: {\n      /* GC values are expressed in Kbytes: #bytes/2^10 */\n      res = cast_int(g->totalbytes >> 10);\n      break;\n    }\n    case LUA_GCCOUNTB: {\n      res = cast_int(g->totalbytes & 0x3ff);\n      break;\n    }\n    case LUA_GCSTEP: {\n      lu_mem a = (cast(lu_mem, data) << 10);\n      if (a <= g->totalbytes)\n        g->GCthreshold = g->totalbytes - a;\n      else\n        g->GCthreshold = 0;\n      while (g->GCthreshold <= g->totalbytes) {\n        luaC_step(L);\n        if (g->gcstate == GCSpause) {  /* end of cycle? */\n          res = 1;  /* signal it */\n          break;\n        }\n      }\n      break;\n    }\n    case LUA_GCSETPAUSE: {\n      res = g->gcpause;\n      g->gcpause = data;\n      break;\n    }\n    case LUA_GCSETSTEPMUL: {\n      res = g->gcstepmul;\n      g->gcstepmul = data;\n      break;\n    }\n    default: res = -1;  /* invalid option */\n  }\n  lua_unlock(L);\n  return res;\n}\n\n\n\n/*\n** miscellaneous functions\n*/\n\n\nLUA_API int lua_error (lua_State *L) {\n  lua_lock(L);\n  api_checknelems(L, 1);\n  luaG_errormsg(L);\n  lua_unlock(L);\n  return 0;  /* to avoid warnings */\n}\n\n\nLUA_API int lua_next (lua_State *L, int idx) {\n  StkId t;\n  int more;\n  lua_lock(L);\n  t = index2adr(L, idx);\n  api_check(L, ttistable(t));\n  more = luaH_next(L, hvalue(t), L->top - 1);\n  if (more) {\n    api_incr_top(L);\n  }\n  else  /* no more elements */\n    L->top -= 1;  /* remove key */\n  lua_unlock(L);\n  return more;\n}\n\n\nLUA_API void lua_concat (lua_State *L, int n) {\n  lua_lock(L);\n  api_checknelems(L, n);\n  if (n >= 2) {\n    luaC_checkGC(L);\n    luaV_concat(L, n, cast_int(L->top - L->base) - 1);\n    L->top -= (n-1);\n  }\n  else if (n == 0) {  /* push empty string */\n    setsvalue2s(L, L->top, luaS_newlstr(L, \"\", 0));\n    api_incr_top(L);\n  }\n  /* else n == 1; nothing to do */\n  lua_unlock(L);\n}\n\n\nLUA_API lua_Alloc lua_getallocf (lua_State *L, void **ud) {\n  lua_Alloc f;\n  lua_lock(L);\n  if (ud) *ud = G(L)->ud;\n  f = G(L)->frealloc;\n  lua_unlock(L);\n  return f;\n}\n\n\nLUA_API void lua_setallocf (lua_State *L, lua_Alloc f, void *ud) {\n  lua_lock(L);\n  G(L)->ud = ud;\n  G(L)->frealloc = f;\n  lua_unlock(L);\n}\n\n\nLUA_API void *lua_newuserdata (lua_State *L, size_t size) {\n  Udata *u;\n  lua_lock(L);\n  luaC_checkGC(L);\n  u = luaS_newudata(L, size, getcurrenv(L));\n  setuvalue(L, L->top, u);\n  api_incr_top(L);\n  lua_unlock(L);\n  return u + 1;\n}\n\n\n\n\nstatic const char *aux_upvalue (StkId fi, int n, TValue **val) {\n  Closure *f;\n  if (!ttisfunction(fi)) return NULL;\n  f = clvalue(fi);\n  if (f->c.isC) {\n    if (!(1 <= n && n <= f->c.nupvalues)) return NULL;\n    *val = &f->c.upvalue[n-1];\n    return \"\";\n  }\n  else {\n    Proto *p = f->l.p;\n    if (!(1 <= n && n <= p->sizeupvalues)) return NULL;\n    *val = f->l.upvals[n-1]->v;\n    return getstr(p->upvalues[n-1]);\n  }\n}\n\n\nLUA_API const char *lua_getupvalue (lua_State *L, int funcindex, int n) {\n  const char *name;\n  TValue *val;\n  lua_lock(L);\n  name = aux_upvalue(index2adr(L, funcindex), n, &val);\n  if (name) {\n    setobj2s(L, L->top, val);\n    api_incr_top(L);\n  }\n  lua_unlock(L);\n  return name;\n}\n\n\nLUA_API const char *lua_setupvalue (lua_State *L, int funcindex, int n) {\n  const char *name;\n  TValue *val;\n  StkId fi;\n  lua_lock(L);\n  fi = index2adr(L, funcindex);\n  api_checknelems(L, 1);\n  name = aux_upvalue(fi, n, &val);\n  if (name) {\n    L->top--;\n    setobj(L, val, L->top);\n    luaC_barrier(L, clvalue(fi), L->top);\n  }\n  lua_unlock(L);\n  return name;\n}\n\n"
  },
  {
    "path": "extern/deprecated/redis-2.8.21/deps/lua/src/lapi.h",
    "content": "/*\n** $Id: lapi.h,v 2.2.1.1 2007/12/27 13:02:25 roberto Exp $\n** Auxiliary functions from Lua API\n** See Copyright Notice in lua.h\n*/\n\n#ifndef lapi_h\n#define lapi_h\n\n\n#include \"lobject.h\"\n\n\nLUAI_FUNC void luaA_pushobject (lua_State *L, const TValue *o);\n\n#endif\n"
  },
  {
    "path": "extern/deprecated/redis-2.8.21/deps/lua/src/lauxlib.c",
    "content": "/*\n** $Id: lauxlib.c,v 1.159.1.3 2008/01/21 13:20:51 roberto Exp $\n** Auxiliary functions for building Lua libraries\n** See Copyright Notice in lua.h\n*/\n\n\n#include <ctype.h>\n#include <errno.h>\n#include <stdarg.h>\n#include <stdio.h>\n#include <stdlib.h>\n#include <string.h>\n\n\n/* This file uses only the official API of Lua.\n** Any function declared here could be written as an application function.\n*/\n\n#define lauxlib_c\n#define LUA_LIB\n\n#include \"lua.h\"\n\n#include \"lauxlib.h\"\n\n\n#define FREELIST_REF\t0\t/* free list of references */\n\n\n/* convert a stack index to positive */\n#define abs_index(L, i)\t\t((i) > 0 || (i) <= LUA_REGISTRYINDEX ? (i) : \\\n\t\t\t\t\tlua_gettop(L) + (i) + 1)\n\n\n/*\n** {======================================================\n** Error-report functions\n** =======================================================\n*/\n\n\nLUALIB_API int luaL_argerror (lua_State *L, int narg, const char *extramsg) {\n  lua_Debug ar;\n  if (!lua_getstack(L, 0, &ar))  /* no stack frame? */\n    return luaL_error(L, \"bad argument #%d (%s)\", narg, extramsg);\n  lua_getinfo(L, \"n\", &ar);\n  if (strcmp(ar.namewhat, \"method\") == 0) {\n    narg--;  /* do not count `self' */\n    if (narg == 0)  /* error is in the self argument itself? */\n      return luaL_error(L, \"calling \" LUA_QS \" on bad self (%s)\",\n                           ar.name, extramsg);\n  }\n  if (ar.name == NULL)\n    ar.name = \"?\";\n  return luaL_error(L, \"bad argument #%d to \" LUA_QS \" (%s)\",\n                        narg, ar.name, extramsg);\n}\n\n\nLUALIB_API int luaL_typerror (lua_State *L, int narg, const char *tname) {\n  const char *msg = lua_pushfstring(L, \"%s expected, got %s\",\n                                    tname, luaL_typename(L, narg));\n  return luaL_argerror(L, narg, msg);\n}\n\n\nstatic void tag_error (lua_State *L, int narg, int tag) {\n  luaL_typerror(L, narg, lua_typename(L, tag));\n}\n\n\nLUALIB_API void luaL_where (lua_State *L, int level) {\n  lua_Debug ar;\n  if (lua_getstack(L, level, &ar)) {  /* check function at level */\n    lua_getinfo(L, \"Sl\", &ar);  /* get info about it */\n    if (ar.currentline > 0) {  /* is there info? */\n      lua_pushfstring(L, \"%s:%d: \", ar.short_src, ar.currentline);\n      return;\n    }\n  }\n  lua_pushliteral(L, \"\");  /* else, no information available... */\n}\n\n\nLUALIB_API int luaL_error (lua_State *L, const char *fmt, ...) {\n  va_list argp;\n  va_start(argp, fmt);\n  luaL_where(L, 1);\n  lua_pushvfstring(L, fmt, argp);\n  va_end(argp);\n  lua_concat(L, 2);\n  return lua_error(L);\n}\n\n/* }====================================================== */\n\n\nLUALIB_API int luaL_checkoption (lua_State *L, int narg, const char *def,\n                                 const char *const lst[]) {\n  const char *name = (def) ? luaL_optstring(L, narg, def) :\n                             luaL_checkstring(L, narg);\n  int i;\n  for (i=0; lst[i]; i++)\n    if (strcmp(lst[i], name) == 0)\n      return i;\n  return luaL_argerror(L, narg,\n                       lua_pushfstring(L, \"invalid option \" LUA_QS, name));\n}\n\n\nLUALIB_API int luaL_newmetatable (lua_State *L, const char *tname) {\n  lua_getfield(L, LUA_REGISTRYINDEX, tname);  /* get registry.name */\n  if (!lua_isnil(L, -1))  /* name already in use? */\n    return 0;  /* leave previous value on top, but return 0 */\n  lua_pop(L, 1);\n  lua_newtable(L);  /* create metatable */\n  lua_pushvalue(L, -1);\n  lua_setfield(L, LUA_REGISTRYINDEX, tname);  /* registry.name = metatable */\n  return 1;\n}\n\n\nLUALIB_API void *luaL_checkudata (lua_State *L, int ud, const char *tname) {\n  void *p = lua_touserdata(L, ud);\n  if (p != NULL) {  /* value is a userdata? */\n    if (lua_getmetatable(L, ud)) {  /* does it have a metatable? */\n      lua_getfield(L, LUA_REGISTRYINDEX, tname);  /* get correct metatable */\n      if (lua_rawequal(L, -1, -2)) {  /* does it have the correct mt? */\n        lua_pop(L, 2);  /* remove both metatables */\n        return p;\n      }\n    }\n  }\n  luaL_typerror(L, ud, tname);  /* else error */\n  return NULL;  /* to avoid warnings */\n}\n\n\nLUALIB_API void luaL_checkstack (lua_State *L, int space, const char *mes) {\n  if (!lua_checkstack(L, space))\n    luaL_error(L, \"stack overflow (%s)\", mes);\n}\n\n\nLUALIB_API void luaL_checktype (lua_State *L, int narg, int t) {\n  if (lua_type(L, narg) != t)\n    tag_error(L, narg, t);\n}\n\n\nLUALIB_API void luaL_checkany (lua_State *L, int narg) {\n  if (lua_type(L, narg) == LUA_TNONE)\n    luaL_argerror(L, narg, \"value expected\");\n}\n\n\nLUALIB_API const char *luaL_checklstring (lua_State *L, int narg, size_t *len) {\n  const char *s = lua_tolstring(L, narg, len);\n  if (!s) tag_error(L, narg, LUA_TSTRING);\n  return s;\n}\n\n\nLUALIB_API const char *luaL_optlstring (lua_State *L, int narg,\n                                        const char *def, size_t *len) {\n  if (lua_isnoneornil(L, narg)) {\n    if (len)\n      *len = (def ? strlen(def) : 0);\n    return def;\n  }\n  else return luaL_checklstring(L, narg, len);\n}\n\n\nLUALIB_API lua_Number luaL_checknumber (lua_State *L, int narg) {\n  lua_Number d = lua_tonumber(L, narg);\n  if (d == 0 && !lua_isnumber(L, narg))  /* avoid extra test when d is not 0 */\n    tag_error(L, narg, LUA_TNUMBER);\n  return d;\n}\n\n\nLUALIB_API lua_Number luaL_optnumber (lua_State *L, int narg, lua_Number def) {\n  return luaL_opt(L, luaL_checknumber, narg, def);\n}\n\n\nLUALIB_API lua_Integer luaL_checkinteger (lua_State *L, int narg) {\n  lua_Integer d = lua_tointeger(L, narg);\n  if (d == 0 && !lua_isnumber(L, narg))  /* avoid extra test when d is not 0 */\n    tag_error(L, narg, LUA_TNUMBER);\n  return d;\n}\n\n\nLUALIB_API lua_Integer luaL_optinteger (lua_State *L, int narg,\n                                                      lua_Integer def) {\n  return luaL_opt(L, luaL_checkinteger, narg, def);\n}\n\n\nLUALIB_API int luaL_getmetafield (lua_State *L, int obj, const char *event) {\n  if (!lua_getmetatable(L, obj))  /* no metatable? */\n    return 0;\n  lua_pushstring(L, event);\n  lua_rawget(L, -2);\n  if (lua_isnil(L, -1)) {\n    lua_pop(L, 2);  /* remove metatable and metafield */\n    return 0;\n  }\n  else {\n    lua_remove(L, -2);  /* remove only metatable */\n    return 1;\n  }\n}\n\n\nLUALIB_API int luaL_callmeta (lua_State *L, int obj, const char *event) {\n  obj = abs_index(L, obj);\n  if (!luaL_getmetafield(L, obj, event))  /* no metafield? */\n    return 0;\n  lua_pushvalue(L, obj);\n  lua_call(L, 1, 1);\n  return 1;\n}\n\n\nLUALIB_API void (luaL_register) (lua_State *L, const char *libname,\n                                const luaL_Reg *l) {\n  luaI_openlib(L, libname, l, 0);\n}\n\n\nstatic int libsize (const luaL_Reg *l) {\n  int size = 0;\n  for (; l->name; l++) size++;\n  return size;\n}\n\n\nLUALIB_API void luaI_openlib (lua_State *L, const char *libname,\n                              const luaL_Reg *l, int nup) {\n  if (libname) {\n    int size = libsize(l);\n    /* check whether lib already exists */\n    luaL_findtable(L, LUA_REGISTRYINDEX, \"_LOADED\", 1);\n    lua_getfield(L, -1, libname);  /* get _LOADED[libname] */\n    if (!lua_istable(L, -1)) {  /* not found? */\n      lua_pop(L, 1);  /* remove previous result */\n      /* try global variable (and create one if it does not exist) */\n      if (luaL_findtable(L, LUA_GLOBALSINDEX, libname, size) != NULL)\n        luaL_error(L, \"name conflict for module \" LUA_QS, libname);\n      lua_pushvalue(L, -1);\n      lua_setfield(L, -3, libname);  /* _LOADED[libname] = new table */\n    }\n    lua_remove(L, -2);  /* remove _LOADED table */\n    lua_insert(L, -(nup+1));  /* move library table to below upvalues */\n  }\n  for (; l->name; l++) {\n    int i;\n    for (i=0; i<nup; i++)  /* copy upvalues to the top */\n      lua_pushvalue(L, -nup);\n    lua_pushcclosure(L, l->func, nup);\n    lua_setfield(L, -(nup+2), l->name);\n  }\n  lua_pop(L, nup);  /* remove upvalues */\n}\n\n\n\n/*\n** {======================================================\n** getn-setn: size for arrays\n** =======================================================\n*/\n\n#if defined(LUA_COMPAT_GETN)\n\nstatic int checkint (lua_State *L, int topop) {\n  int n = (lua_type(L, -1) == LUA_TNUMBER) ? lua_tointeger(L, -1) : -1;\n  lua_pop(L, topop);\n  return n;\n}\n\n\nstatic void getsizes (lua_State *L) {\n  lua_getfield(L, LUA_REGISTRYINDEX, \"LUA_SIZES\");\n  if (lua_isnil(L, -1)) {  /* no `size' table? */\n    lua_pop(L, 1);  /* remove nil */\n    lua_newtable(L);  /* create it */\n    lua_pushvalue(L, -1);  /* `size' will be its own metatable */\n    lua_setmetatable(L, -2);\n    lua_pushliteral(L, \"kv\");\n    lua_setfield(L, -2, \"__mode\");  /* metatable(N).__mode = \"kv\" */\n    lua_pushvalue(L, -1);\n    lua_setfield(L, LUA_REGISTRYINDEX, \"LUA_SIZES\");  /* store in register */\n  }\n}\n\n\nLUALIB_API void luaL_setn (lua_State *L, int t, int n) {\n  t = abs_index(L, t);\n  lua_pushliteral(L, \"n\");\n  lua_rawget(L, t);\n  if (checkint(L, 1) >= 0) {  /* is there a numeric field `n'? */\n    lua_pushliteral(L, \"n\");  /* use it */\n    lua_pushinteger(L, n);\n    lua_rawset(L, t);\n  }\n  else {  /* use `sizes' */\n    getsizes(L);\n    lua_pushvalue(L, t);\n    lua_pushinteger(L, n);\n    lua_rawset(L, -3);  /* sizes[t] = n */\n    lua_pop(L, 1);  /* remove `sizes' */\n  }\n}\n\n\nLUALIB_API int luaL_getn (lua_State *L, int t) {\n  int n;\n  t = abs_index(L, t);\n  lua_pushliteral(L, \"n\");  /* try t.n */\n  lua_rawget(L, t);\n  if ((n = checkint(L, 1)) >= 0) return n;\n  getsizes(L);  /* else try sizes[t] */\n  lua_pushvalue(L, t);\n  lua_rawget(L, -2);\n  if ((n = checkint(L, 2)) >= 0) return n;\n  return (int)lua_objlen(L, t);\n}\n\n#endif\n\n/* }====================================================== */\n\n\n\nLUALIB_API const char *luaL_gsub (lua_State *L, const char *s, const char *p,\n                                                               const char *r) {\n  const char *wild;\n  size_t l = strlen(p);\n  luaL_Buffer b;\n  luaL_buffinit(L, &b);\n  while ((wild = strstr(s, p)) != NULL) {\n    luaL_addlstring(&b, s, wild - s);  /* push prefix */\n    luaL_addstring(&b, r);  /* push replacement in place of pattern */\n    s = wild + l;  /* continue after `p' */\n  }\n  luaL_addstring(&b, s);  /* push last suffix */\n  luaL_pushresult(&b);\n  return lua_tostring(L, -1);\n}\n\n\nLUALIB_API const char *luaL_findtable (lua_State *L, int idx,\n                                       const char *fname, int szhint) {\n  const char *e;\n  lua_pushvalue(L, idx);\n  do {\n    e = strchr(fname, '.');\n    if (e == NULL) e = fname + strlen(fname);\n    lua_pushlstring(L, fname, e - fname);\n    lua_rawget(L, -2);\n    if (lua_isnil(L, -1)) {  /* no such field? */\n      lua_pop(L, 1);  /* remove this nil */\n      lua_createtable(L, 0, (*e == '.' ? 1 : szhint)); /* new table for field */\n      lua_pushlstring(L, fname, e - fname);\n      lua_pushvalue(L, -2);\n      lua_settable(L, -4);  /* set new table into field */\n    }\n    else if (!lua_istable(L, -1)) {  /* field has a non-table value? */\n      lua_pop(L, 2);  /* remove table and value */\n      return fname;  /* return problematic part of the name */\n    }\n    lua_remove(L, -2);  /* remove previous table */\n    fname = e + 1;\n  } while (*e == '.');\n  return NULL;\n}\n\n\n\n/*\n** {======================================================\n** Generic Buffer manipulation\n** =======================================================\n*/\n\n\n#define bufflen(B)\t((B)->p - (B)->buffer)\n#define bufffree(B)\t((size_t)(LUAL_BUFFERSIZE - bufflen(B)))\n\n#define LIMIT\t(LUA_MINSTACK/2)\n\n\nstatic int emptybuffer (luaL_Buffer *B) {\n  size_t l = bufflen(B);\n  if (l == 0) return 0;  /* put nothing on stack */\n  else {\n    lua_pushlstring(B->L, B->buffer, l);\n    B->p = B->buffer;\n    B->lvl++;\n    return 1;\n  }\n}\n\n\nstatic void adjuststack (luaL_Buffer *B) {\n  if (B->lvl > 1) {\n    lua_State *L = B->L;\n    int toget = 1;  /* number of levels to concat */\n    size_t toplen = lua_strlen(L, -1);\n    do {\n      size_t l = lua_strlen(L, -(toget+1));\n      if (B->lvl - toget + 1 >= LIMIT || toplen > l) {\n        toplen += l;\n        toget++;\n      }\n      else break;\n    } while (toget < B->lvl);\n    lua_concat(L, toget);\n    B->lvl = B->lvl - toget + 1;\n  }\n}\n\n\nLUALIB_API char *luaL_prepbuffer (luaL_Buffer *B) {\n  if (emptybuffer(B))\n    adjuststack(B);\n  return B->buffer;\n}\n\n\nLUALIB_API void luaL_addlstring (luaL_Buffer *B, const char *s, size_t l) {\n  while (l--)\n    luaL_addchar(B, *s++);\n}\n\n\nLUALIB_API void luaL_addstring (luaL_Buffer *B, const char *s) {\n  luaL_addlstring(B, s, strlen(s));\n}\n\n\nLUALIB_API void luaL_pushresult (luaL_Buffer *B) {\n  emptybuffer(B);\n  lua_concat(B->L, B->lvl);\n  B->lvl = 1;\n}\n\n\nLUALIB_API void luaL_addvalue (luaL_Buffer *B) {\n  lua_State *L = B->L;\n  size_t vl;\n  const char *s = lua_tolstring(L, -1, &vl);\n  if (vl <= bufffree(B)) {  /* fit into buffer? */\n    memcpy(B->p, s, vl);  /* put it there */\n    B->p += vl;\n    lua_pop(L, 1);  /* remove from stack */\n  }\n  else {\n    if (emptybuffer(B))\n      lua_insert(L, -2);  /* put buffer before new value */\n    B->lvl++;  /* add new value into B stack */\n    adjuststack(B);\n  }\n}\n\n\nLUALIB_API void luaL_buffinit (lua_State *L, luaL_Buffer *B) {\n  B->L = L;\n  B->p = B->buffer;\n  B->lvl = 0;\n}\n\n/* }====================================================== */\n\n\nLUALIB_API int luaL_ref (lua_State *L, int t) {\n  int ref;\n  t = abs_index(L, t);\n  if (lua_isnil(L, -1)) {\n    lua_pop(L, 1);  /* remove from stack */\n    return LUA_REFNIL;  /* `nil' has a unique fixed reference */\n  }\n  lua_rawgeti(L, t, FREELIST_REF);  /* get first free element */\n  ref = (int)lua_tointeger(L, -1);  /* ref = t[FREELIST_REF] */\n  lua_pop(L, 1);  /* remove it from stack */\n  if (ref != 0) {  /* any free element? */\n    lua_rawgeti(L, t, ref);  /* remove it from list */\n    lua_rawseti(L, t, FREELIST_REF);  /* (t[FREELIST_REF] = t[ref]) */\n  }\n  else {  /* no free elements */\n    ref = (int)lua_objlen(L, t);\n    ref++;  /* create new reference */\n  }\n  lua_rawseti(L, t, ref);\n  return ref;\n}\n\n\nLUALIB_API void luaL_unref (lua_State *L, int t, int ref) {\n  if (ref >= 0) {\n    t = abs_index(L, t);\n    lua_rawgeti(L, t, FREELIST_REF);\n    lua_rawseti(L, t, ref);  /* t[ref] = t[FREELIST_REF] */\n    lua_pushinteger(L, ref);\n    lua_rawseti(L, t, FREELIST_REF);  /* t[FREELIST_REF] = ref */\n  }\n}\n\n\n\n/*\n** {======================================================\n** Load functions\n** =======================================================\n*/\n\ntypedef struct LoadF {\n  int extraline;\n  FILE *f;\n  char buff[LUAL_BUFFERSIZE];\n} LoadF;\n\n\nstatic const char *getF (lua_State *L, void *ud, size_t *size) {\n  LoadF *lf = (LoadF *)ud;\n  (void)L;\n  if (lf->extraline) {\n    lf->extraline = 0;\n    *size = 1;\n    return \"\\n\";\n  }\n  if (feof(lf->f)) return NULL;\n  *size = fread(lf->buff, 1, sizeof(lf->buff), lf->f);\n  return (*size > 0) ? lf->buff : NULL;\n}\n\n\nstatic int errfile (lua_State *L, const char *what, int fnameindex) {\n  const char *serr = strerror(errno);\n  const char *filename = lua_tostring(L, fnameindex) + 1;\n  lua_pushfstring(L, \"cannot %s %s: %s\", what, filename, serr);\n  lua_remove(L, fnameindex);\n  return LUA_ERRFILE;\n}\n\n\nLUALIB_API int luaL_loadfile (lua_State *L, const char *filename) {\n  LoadF lf;\n  int status, readstatus;\n  int c;\n  int fnameindex = lua_gettop(L) + 1;  /* index of filename on the stack */\n  lf.extraline = 0;\n  if (filename == NULL) {\n    lua_pushliteral(L, \"=stdin\");\n    lf.f = stdin;\n  }\n  else {\n    lua_pushfstring(L, \"@%s\", filename);\n    lf.f = fopen(filename, \"r\");\n    if (lf.f == NULL) return errfile(L, \"open\", fnameindex);\n  }\n  c = getc(lf.f);\n  if (c == '#') {  /* Unix exec. file? */\n    lf.extraline = 1;\n    while ((c = getc(lf.f)) != EOF && c != '\\n') ;  /* skip first line */\n    if (c == '\\n') c = getc(lf.f);\n  }\n  if (c == LUA_SIGNATURE[0] && filename) {  /* binary file? */\n    lf.f = freopen(filename, \"rb\", lf.f);  /* reopen in binary mode */\n    if (lf.f == NULL) return errfile(L, \"reopen\", fnameindex);\n    /* skip eventual `#!...' */\n   while ((c = getc(lf.f)) != EOF && c != LUA_SIGNATURE[0]) ;\n    lf.extraline = 0;\n  }\n  ungetc(c, lf.f);\n  status = lua_load(L, getF, &lf, lua_tostring(L, -1));\n  readstatus = ferror(lf.f);\n  if (filename) fclose(lf.f);  /* close file (even in case of errors) */\n  if (readstatus) {\n    lua_settop(L, fnameindex);  /* ignore results from `lua_load' */\n    return errfile(L, \"read\", fnameindex);\n  }\n  lua_remove(L, fnameindex);\n  return status;\n}\n\n\ntypedef struct LoadS {\n  const char *s;\n  size_t size;\n} LoadS;\n\n\nstatic const char *getS (lua_State *L, void *ud, size_t *size) {\n  LoadS *ls = (LoadS *)ud;\n  (void)L;\n  if (ls->size == 0) return NULL;\n  *size = ls->size;\n  ls->size = 0;\n  return ls->s;\n}\n\n\nLUALIB_API int luaL_loadbuffer (lua_State *L, const char *buff, size_t size,\n                                const char *name) {\n  LoadS ls;\n  ls.s = buff;\n  ls.size = size;\n  return lua_load(L, getS, &ls, name);\n}\n\n\nLUALIB_API int (luaL_loadstring) (lua_State *L, const char *s) {\n  return luaL_loadbuffer(L, s, strlen(s), s);\n}\n\n\n\n/* }====================================================== */\n\n\nstatic void *l_alloc (void *ud, void *ptr, size_t osize, size_t nsize) {\n  (void)ud;\n  (void)osize;\n  if (nsize == 0) {\n    free(ptr);\n    return NULL;\n  }\n  else\n    return realloc(ptr, nsize);\n}\n\n\nstatic int panic (lua_State *L) {\n  (void)L;  /* to avoid warnings */\n  fprintf(stderr, \"PANIC: unprotected error in call to Lua API (%s)\\n\",\n                   lua_tostring(L, -1));\n  return 0;\n}\n\n\nLUALIB_API lua_State *luaL_newstate (void) {\n  lua_State *L = lua_newstate(l_alloc, NULL);\n  if (L) lua_atpanic(L, &panic);\n  return L;\n}\n\n"
  },
  {
    "path": "extern/deprecated/redis-2.8.21/deps/lua/src/lauxlib.h",
    "content": "/*\n** $Id: lauxlib.h,v 1.88.1.1 2007/12/27 13:02:25 roberto Exp $\n** Auxiliary functions for building Lua libraries\n** See Copyright Notice in lua.h\n*/\n\n\n#ifndef lauxlib_h\n#define lauxlib_h\n\n\n#include <stddef.h>\n#include <stdio.h>\n\n#include \"lua.h\"\n\n\n#if defined(LUA_COMPAT_GETN)\nLUALIB_API int (luaL_getn) (lua_State *L, int t);\nLUALIB_API void (luaL_setn) (lua_State *L, int t, int n);\n#else\n#define luaL_getn(L,i)          ((int)lua_objlen(L, i))\n#define luaL_setn(L,i,j)        ((void)0)  /* no op! */\n#endif\n\n#if defined(LUA_COMPAT_OPENLIB)\n#define luaI_openlib\tluaL_openlib\n#endif\n\n\n/* extra error code for `luaL_load' */\n#define LUA_ERRFILE     (LUA_ERRERR+1)\n\n\ntypedef struct luaL_Reg {\n  const char *name;\n  lua_CFunction func;\n} luaL_Reg;\n\n\n\nLUALIB_API void (luaI_openlib) (lua_State *L, const char *libname,\n                                const luaL_Reg *l, int nup);\nLUALIB_API void (luaL_register) (lua_State *L, const char *libname,\n                                const luaL_Reg *l);\nLUALIB_API int (luaL_getmetafield) (lua_State *L, int obj, const char *e);\nLUALIB_API int (luaL_callmeta) (lua_State *L, int obj, const char *e);\nLUALIB_API int (luaL_typerror) (lua_State *L, int narg, const char *tname);\nLUALIB_API int (luaL_argerror) (lua_State *L, int numarg, const char *extramsg);\nLUALIB_API const char *(luaL_checklstring) (lua_State *L, int numArg,\n                                                          size_t *l);\nLUALIB_API const char *(luaL_optlstring) (lua_State *L, int numArg,\n                                          const char *def, size_t *l);\nLUALIB_API lua_Number (luaL_checknumber) (lua_State *L, int numArg);\nLUALIB_API lua_Number (luaL_optnumber) (lua_State *L, int nArg, lua_Number def);\n\nLUALIB_API lua_Integer (luaL_checkinteger) (lua_State *L, int numArg);\nLUALIB_API lua_Integer (luaL_optinteger) (lua_State *L, int nArg,\n                                          lua_Integer def);\n\nLUALIB_API void (luaL_checkstack) (lua_State *L, int sz, const char *msg);\nLUALIB_API void (luaL_checktype) (lua_State *L, int narg, int t);\nLUALIB_API void (luaL_checkany) (lua_State *L, int narg);\n\nLUALIB_API int   (luaL_newmetatable) (lua_State *L, const char *tname);\nLUALIB_API void *(luaL_checkudata) (lua_State *L, int ud, const char *tname);\n\nLUALIB_API void (luaL_where) (lua_State *L, int lvl);\nLUALIB_API int (luaL_error) (lua_State *L, const char *fmt, ...);\n\nLUALIB_API int (luaL_checkoption) (lua_State *L, int narg, const char *def,\n                                   const char *const lst[]);\n\nLUALIB_API int (luaL_ref) (lua_State *L, int t);\nLUALIB_API void (luaL_unref) (lua_State *L, int t, int ref);\n\nLUALIB_API int (luaL_loadfile) (lua_State *L, const char *filename);\nLUALIB_API int (luaL_loadbuffer) (lua_State *L, const char *buff, size_t sz,\n                                  const char *name);\nLUALIB_API int (luaL_loadstring) (lua_State *L, const char *s);\n\nLUALIB_API lua_State *(luaL_newstate) (void);\n\n\nLUALIB_API const char *(luaL_gsub) (lua_State *L, const char *s, const char *p,\n                                                  const char *r);\n\nLUALIB_API const char *(luaL_findtable) (lua_State *L, int idx,\n                                         const char *fname, int szhint);\n\n\n\n\n/*\n** ===============================================================\n** some useful macros\n** ===============================================================\n*/\n\n#define luaL_argcheck(L, cond,numarg,extramsg)\t\\\n\t\t((void)((cond) || luaL_argerror(L, (numarg), (extramsg))))\n#define luaL_checkstring(L,n)\t(luaL_checklstring(L, (n), NULL))\n#define luaL_optstring(L,n,d)\t(luaL_optlstring(L, (n), (d), NULL))\n#define luaL_checkint(L,n)\t((int)luaL_checkinteger(L, (n)))\n#define luaL_optint(L,n,d)\t((int)luaL_optinteger(L, (n), (d)))\n#define luaL_checklong(L,n)\t((long)luaL_checkinteger(L, (n)))\n#define luaL_optlong(L,n,d)\t((long)luaL_optinteger(L, (n), (d)))\n\n#define luaL_typename(L,i)\tlua_typename(L, lua_type(L,(i)))\n\n#define luaL_dofile(L, fn) \\\n\t(luaL_loadfile(L, fn) || lua_pcall(L, 0, LUA_MULTRET, 0))\n\n#define luaL_dostring(L, s) \\\n\t(luaL_loadstring(L, s) || lua_pcall(L, 0, LUA_MULTRET, 0))\n\n#define luaL_getmetatable(L,n)\t(lua_getfield(L, LUA_REGISTRYINDEX, (n)))\n\n#define luaL_opt(L,f,n,d)\t(lua_isnoneornil(L,(n)) ? (d) : f(L,(n)))\n\n/*\n** {======================================================\n** Generic Buffer manipulation\n** =======================================================\n*/\n\n\n\ntypedef struct luaL_Buffer {\n  char *p;\t\t\t/* current position in buffer */\n  int lvl;  /* number of strings in the stack (level) */\n  lua_State *L;\n  char buffer[LUAL_BUFFERSIZE];\n} luaL_Buffer;\n\n#define luaL_addchar(B,c) \\\n  ((void)((B)->p < ((B)->buffer+LUAL_BUFFERSIZE) || luaL_prepbuffer(B)), \\\n   (*(B)->p++ = (char)(c)))\n\n/* compatibility only */\n#define luaL_putchar(B,c)\tluaL_addchar(B,c)\n\n#define luaL_addsize(B,n)\t((B)->p += (n))\n\nLUALIB_API void (luaL_buffinit) (lua_State *L, luaL_Buffer *B);\nLUALIB_API char *(luaL_prepbuffer) (luaL_Buffer *B);\nLUALIB_API void (luaL_addlstring) (luaL_Buffer *B, const char *s, size_t l);\nLUALIB_API void (luaL_addstring) (luaL_Buffer *B, const char *s);\nLUALIB_API void (luaL_addvalue) (luaL_Buffer *B);\nLUALIB_API void (luaL_pushresult) (luaL_Buffer *B);\n\n\n/* }====================================================== */\n\n\n/* compatibility with ref system */\n\n/* pre-defined references */\n#define LUA_NOREF       (-2)\n#define LUA_REFNIL      (-1)\n\n#define lua_ref(L,lock) ((lock) ? luaL_ref(L, LUA_REGISTRYINDEX) : \\\n      (lua_pushstring(L, \"unlocked references are obsolete\"), lua_error(L), 0))\n\n#define lua_unref(L,ref)        luaL_unref(L, LUA_REGISTRYINDEX, (ref))\n\n#define lua_getref(L,ref)       lua_rawgeti(L, LUA_REGISTRYINDEX, (ref))\n\n\n#define luaL_reg\tluaL_Reg\n\n#endif\n\n\n"
  },
  {
    "path": "extern/deprecated/redis-2.8.21/deps/lua/src/lbaselib.c",
    "content": "/*\n** $Id: lbaselib.c,v 1.191.1.6 2008/02/14 16:46:22 roberto Exp $\n** Basic library\n** See Copyright Notice in lua.h\n*/\n\n\n\n#include <ctype.h>\n#include <stdio.h>\n#include <stdlib.h>\n#include <string.h>\n\n#define lbaselib_c\n#define LUA_LIB\n\n#include \"lua.h\"\n\n#include \"lauxlib.h\"\n#include \"lualib.h\"\n\n\n\n\n/*\n** If your system does not support `stdout', you can just remove this function.\n** If you need, you can define your own `print' function, following this\n** model but changing `fputs' to put the strings at a proper place\n** (a console window or a log file, for instance).\n*/\nstatic int luaB_print (lua_State *L) {\n  int n = lua_gettop(L);  /* number of arguments */\n  int i;\n  lua_getglobal(L, \"tostring\");\n  for (i=1; i<=n; i++) {\n    const char *s;\n    lua_pushvalue(L, -1);  /* function to be called */\n    lua_pushvalue(L, i);   /* value to print */\n    lua_call(L, 1, 1);\n    s = lua_tostring(L, -1);  /* get result */\n    if (s == NULL)\n      return luaL_error(L, LUA_QL(\"tostring\") \" must return a string to \"\n                           LUA_QL(\"print\"));\n    if (i>1) fputs(\"\\t\", stdout);\n    fputs(s, stdout);\n    lua_pop(L, 1);  /* pop result */\n  }\n  fputs(\"\\n\", stdout);\n  return 0;\n}\n\n\nstatic int luaB_tonumber (lua_State *L) {\n  int base = luaL_optint(L, 2, 10);\n  if (base == 10) {  /* standard conversion */\n    luaL_checkany(L, 1);\n    if (lua_isnumber(L, 1)) {\n      lua_pushnumber(L, lua_tonumber(L, 1));\n      return 1;\n    }\n  }\n  else {\n    const char *s1 = luaL_checkstring(L, 1);\n    char *s2;\n    unsigned long n;\n    luaL_argcheck(L, 2 <= base && base <= 36, 2, \"base out of range\");\n    n = strtoul(s1, &s2, base);\n    if (s1 != s2) {  /* at least one valid digit? */\n      while (isspace((unsigned char)(*s2))) s2++;  /* skip trailing spaces */\n      if (*s2 == '\\0') {  /* no invalid trailing characters? */\n        lua_pushnumber(L, (lua_Number)n);\n        return 1;\n      }\n    }\n  }\n  lua_pushnil(L);  /* else not a number */\n  return 1;\n}\n\n\nstatic int luaB_error (lua_State *L) {\n  int level = luaL_optint(L, 2, 1);\n  lua_settop(L, 1);\n  if (lua_isstring(L, 1) && level > 0) {  /* add extra information? */\n    luaL_where(L, level);\n    lua_pushvalue(L, 1);\n    lua_concat(L, 2);\n  }\n  return lua_error(L);\n}\n\n\nstatic int luaB_getmetatable (lua_State *L) {\n  luaL_checkany(L, 1);\n  if (!lua_getmetatable(L, 1)) {\n    lua_pushnil(L);\n    return 1;  /* no metatable */\n  }\n  luaL_getmetafield(L, 1, \"__metatable\");\n  return 1;  /* returns either __metatable field (if present) or metatable */\n}\n\n\nstatic int luaB_setmetatable (lua_State *L) {\n  int t = lua_type(L, 2);\n  luaL_checktype(L, 1, LUA_TTABLE);\n  luaL_argcheck(L, t == LUA_TNIL || t == LUA_TTABLE, 2,\n                    \"nil or table expected\");\n  if (luaL_getmetafield(L, 1, \"__metatable\"))\n    luaL_error(L, \"cannot change a protected metatable\");\n  lua_settop(L, 2);\n  lua_setmetatable(L, 1);\n  return 1;\n}\n\n\nstatic void getfunc (lua_State *L, int opt) {\n  if (lua_isfunction(L, 1)) lua_pushvalue(L, 1);\n  else {\n    lua_Debug ar;\n    int level = opt ? luaL_optint(L, 1, 1) : luaL_checkint(L, 1);\n    luaL_argcheck(L, level >= 0, 1, \"level must be non-negative\");\n    if (lua_getstack(L, level, &ar) == 0)\n      luaL_argerror(L, 1, \"invalid level\");\n    lua_getinfo(L, \"f\", &ar);\n    if (lua_isnil(L, -1))\n      luaL_error(L, \"no function environment for tail call at level %d\",\n                    level);\n  }\n}\n\n\nstatic int luaB_getfenv (lua_State *L) {\n  getfunc(L, 1);\n  if (lua_iscfunction(L, -1))  /* is a C function? */\n    lua_pushvalue(L, LUA_GLOBALSINDEX);  /* return the thread's global env. */\n  else\n    lua_getfenv(L, -1);\n  return 1;\n}\n\n\nstatic int luaB_setfenv (lua_State *L) {\n  luaL_checktype(L, 2, LUA_TTABLE);\n  getfunc(L, 0);\n  lua_pushvalue(L, 2);\n  if (lua_isnumber(L, 1) && lua_tonumber(L, 1) == 0) {\n    /* change environment of current thread */\n    lua_pushthread(L);\n    lua_insert(L, -2);\n    lua_setfenv(L, -2);\n    return 0;\n  }\n  else if (lua_iscfunction(L, -2) || lua_setfenv(L, -2) == 0)\n    luaL_error(L,\n          LUA_QL(\"setfenv\") \" cannot change environment of given object\");\n  return 1;\n}\n\n\nstatic int luaB_rawequal (lua_State *L) {\n  luaL_checkany(L, 1);\n  luaL_checkany(L, 2);\n  lua_pushboolean(L, lua_rawequal(L, 1, 2));\n  return 1;\n}\n\n\nstatic int luaB_rawget (lua_State *L) {\n  luaL_checktype(L, 1, LUA_TTABLE);\n  luaL_checkany(L, 2);\n  lua_settop(L, 2);\n  lua_rawget(L, 1);\n  return 1;\n}\n\nstatic int luaB_rawset (lua_State *L) {\n  luaL_checktype(L, 1, LUA_TTABLE);\n  luaL_checkany(L, 2);\n  luaL_checkany(L, 3);\n  lua_settop(L, 3);\n  lua_rawset(L, 1);\n  return 1;\n}\n\n\nstatic int luaB_gcinfo (lua_State *L) {\n  lua_pushinteger(L, lua_getgccount(L));\n  return 1;\n}\n\n\nstatic int luaB_collectgarbage (lua_State *L) {\n  static const char *const opts[] = {\"stop\", \"restart\", \"collect\",\n    \"count\", \"step\", \"setpause\", \"setstepmul\", NULL};\n  static const int optsnum[] = {LUA_GCSTOP, LUA_GCRESTART, LUA_GCCOLLECT,\n    LUA_GCCOUNT, LUA_GCSTEP, LUA_GCSETPAUSE, LUA_GCSETSTEPMUL};\n  int o = luaL_checkoption(L, 1, \"collect\", opts);\n  int ex = luaL_optint(L, 2, 0);\n  int res = lua_gc(L, optsnum[o], ex);\n  switch (optsnum[o]) {\n    case LUA_GCCOUNT: {\n      int b = lua_gc(L, LUA_GCCOUNTB, 0);\n      lua_pushnumber(L, res + ((lua_Number)b/1024));\n      return 1;\n    }\n    case LUA_GCSTEP: {\n      lua_pushboolean(L, res);\n      return 1;\n    }\n    default: {\n      lua_pushnumber(L, res);\n      return 1;\n    }\n  }\n}\n\n\nstatic int luaB_type (lua_State *L) {\n  luaL_checkany(L, 1);\n  lua_pushstring(L, luaL_typename(L, 1));\n  return 1;\n}\n\n\nstatic int luaB_next (lua_State *L) {\n  luaL_checktype(L, 1, LUA_TTABLE);\n  lua_settop(L, 2);  /* create a 2nd argument if there isn't one */\n  if (lua_next(L, 1))\n    return 2;\n  else {\n    lua_pushnil(L);\n    return 1;\n  }\n}\n\n\nstatic int luaB_pairs (lua_State *L) {\n  luaL_checktype(L, 1, LUA_TTABLE);\n  lua_pushvalue(L, lua_upvalueindex(1));  /* return generator, */\n  lua_pushvalue(L, 1);  /* state, */\n  lua_pushnil(L);  /* and initial value */\n  return 3;\n}\n\n\nstatic int ipairsaux (lua_State *L) {\n  int i = luaL_checkint(L, 2);\n  luaL_checktype(L, 1, LUA_TTABLE);\n  i++;  /* next value */\n  lua_pushinteger(L, i);\n  lua_rawgeti(L, 1, i);\n  return (lua_isnil(L, -1)) ? 0 : 2;\n}\n\n\nstatic int luaB_ipairs (lua_State *L) {\n  luaL_checktype(L, 1, LUA_TTABLE);\n  lua_pushvalue(L, lua_upvalueindex(1));  /* return generator, */\n  lua_pushvalue(L, 1);  /* state, */\n  lua_pushinteger(L, 0);  /* and initial value */\n  return 3;\n}\n\n\nstatic int load_aux (lua_State *L, int status) {\n  if (status == 0)  /* OK? */\n    return 1;\n  else {\n    lua_pushnil(L);\n    lua_insert(L, -2);  /* put before error message */\n    return 2;  /* return nil plus error message */\n  }\n}\n\n\nstatic int luaB_loadstring (lua_State *L) {\n  size_t l;\n  const char *s = luaL_checklstring(L, 1, &l);\n  const char *chunkname = luaL_optstring(L, 2, s);\n  return load_aux(L, luaL_loadbuffer(L, s, l, chunkname));\n}\n\n\nstatic int luaB_loadfile (lua_State *L) {\n  const char *fname = luaL_optstring(L, 1, NULL);\n  return load_aux(L, luaL_loadfile(L, fname));\n}\n\n\n/*\n** Reader for generic `load' function: `lua_load' uses the\n** stack for internal stuff, so the reader cannot change the\n** stack top. Instead, it keeps its resulting string in a\n** reserved slot inside the stack.\n*/\nstatic const char *generic_reader (lua_State *L, void *ud, size_t *size) {\n  (void)ud;  /* to avoid warnings */\n  luaL_checkstack(L, 2, \"too many nested functions\");\n  lua_pushvalue(L, 1);  /* get function */\n  lua_call(L, 0, 1);  /* call it */\n  if (lua_isnil(L, -1)) {\n    *size = 0;\n    return NULL;\n  }\n  else if (lua_isstring(L, -1)) {\n    lua_replace(L, 3);  /* save string in a reserved stack slot */\n    return lua_tolstring(L, 3, size);\n  }\n  else luaL_error(L, \"reader function must return a string\");\n  return NULL;  /* to avoid warnings */\n}\n\n\nstatic int luaB_load (lua_State *L) {\n  int status;\n  const char *cname = luaL_optstring(L, 2, \"=(load)\");\n  luaL_checktype(L, 1, LUA_TFUNCTION);\n  lua_settop(L, 3);  /* function, eventual name, plus one reserved slot */\n  status = lua_load(L, generic_reader, NULL, cname);\n  return load_aux(L, status);\n}\n\n\nstatic int luaB_dofile (lua_State *L) {\n  const char *fname = luaL_optstring(L, 1, NULL);\n  int n = lua_gettop(L);\n  if (luaL_loadfile(L, fname) != 0) lua_error(L);\n  lua_call(L, 0, LUA_MULTRET);\n  return lua_gettop(L) - n;\n}\n\n\nstatic int luaB_assert (lua_State *L) {\n  luaL_checkany(L, 1);\n  if (!lua_toboolean(L, 1))\n    return luaL_error(L, \"%s\", luaL_optstring(L, 2, \"assertion failed!\"));\n  return lua_gettop(L);\n}\n\n\nstatic int luaB_unpack (lua_State *L) {\n  int i, e, n;\n  luaL_checktype(L, 1, LUA_TTABLE);\n  i = luaL_optint(L, 2, 1);\n  e = luaL_opt(L, luaL_checkint, 3, luaL_getn(L, 1));\n  if (i > e) return 0;  /* empty range */\n  n = e - i + 1;  /* number of elements */\n  if (n <= 0 || !lua_checkstack(L, n))  /* n <= 0 means arith. overflow */\n    return luaL_error(L, \"too many results to unpack\");\n  lua_rawgeti(L, 1, i);  /* push arg[i] (avoiding overflow problems) */\n  while (i++ < e)  /* push arg[i + 1...e] */\n    lua_rawgeti(L, 1, i);\n  return n;\n}\n\n\nstatic int luaB_select (lua_State *L) {\n  int n = lua_gettop(L);\n  if (lua_type(L, 1) == LUA_TSTRING && *lua_tostring(L, 1) == '#') {\n    lua_pushinteger(L, n-1);\n    return 1;\n  }\n  else {\n    int i = luaL_checkint(L, 1);\n    if (i < 0) i = n + i;\n    else if (i > n) i = n;\n    luaL_argcheck(L, 1 <= i, 1, \"index out of range\");\n    return n - i;\n  }\n}\n\n\nstatic int luaB_pcall (lua_State *L) {\n  int status;\n  luaL_checkany(L, 1);\n  status = lua_pcall(L, lua_gettop(L) - 1, LUA_MULTRET, 0);\n  lua_pushboolean(L, (status == 0));\n  lua_insert(L, 1);\n  return lua_gettop(L);  /* return status + all results */\n}\n\n\nstatic int luaB_xpcall (lua_State *L) {\n  int status;\n  luaL_checkany(L, 2);\n  lua_settop(L, 2);\n  lua_insert(L, 1);  /* put error function under function to be called */\n  status = lua_pcall(L, 0, LUA_MULTRET, 1);\n  lua_pushboolean(L, (status == 0));\n  lua_replace(L, 1);\n  return lua_gettop(L);  /* return status + all results */\n}\n\n\nstatic int luaB_tostring (lua_State *L) {\n  luaL_checkany(L, 1);\n  if (luaL_callmeta(L, 1, \"__tostring\"))  /* is there a metafield? */\n    return 1;  /* use its value */\n  switch (lua_type(L, 1)) {\n    case LUA_TNUMBER:\n      lua_pushstring(L, lua_tostring(L, 1));\n      break;\n    case LUA_TSTRING:\n      lua_pushvalue(L, 1);\n      break;\n    case LUA_TBOOLEAN:\n      lua_pushstring(L, (lua_toboolean(L, 1) ? \"true\" : \"false\"));\n      break;\n    case LUA_TNIL:\n      lua_pushliteral(L, \"nil\");\n      break;\n    default:\n      lua_pushfstring(L, \"%s: %p\", luaL_typename(L, 1), lua_topointer(L, 1));\n      break;\n  }\n  return 1;\n}\n\n\nstatic int luaB_newproxy (lua_State *L) {\n  lua_settop(L, 1);\n  lua_newuserdata(L, 0);  /* create proxy */\n  if (lua_toboolean(L, 1) == 0)\n    return 1;  /* no metatable */\n  else if (lua_isboolean(L, 1)) {\n    lua_newtable(L);  /* create a new metatable `m' ... */\n    lua_pushvalue(L, -1);  /* ... and mark `m' as a valid metatable */\n    lua_pushboolean(L, 1);\n    lua_rawset(L, lua_upvalueindex(1));  /* weaktable[m] = true */\n  }\n  else {\n    int validproxy = 0;  /* to check if weaktable[metatable(u)] == true */\n    if (lua_getmetatable(L, 1)) {\n      lua_rawget(L, lua_upvalueindex(1));\n      validproxy = lua_toboolean(L, -1);\n      lua_pop(L, 1);  /* remove value */\n    }\n    luaL_argcheck(L, validproxy, 1, \"boolean or proxy expected\");\n    lua_getmetatable(L, 1);  /* metatable is valid; get it */\n  }\n  lua_setmetatable(L, 2);\n  return 1;\n}\n\n\nstatic const luaL_Reg base_funcs[] = {\n  {\"assert\", luaB_assert},\n  {\"collectgarbage\", luaB_collectgarbage},\n  {\"dofile\", luaB_dofile},\n  {\"error\", luaB_error},\n  {\"gcinfo\", luaB_gcinfo},\n  {\"getfenv\", luaB_getfenv},\n  {\"getmetatable\", luaB_getmetatable},\n  {\"loadfile\", luaB_loadfile},\n  {\"load\", luaB_load},\n  {\"loadstring\", luaB_loadstring},\n  {\"next\", luaB_next},\n  {\"pcall\", luaB_pcall},\n  {\"print\", luaB_print},\n  {\"rawequal\", luaB_rawequal},\n  {\"rawget\", luaB_rawget},\n  {\"rawset\", luaB_rawset},\n  {\"select\", luaB_select},\n  {\"setfenv\", luaB_setfenv},\n  {\"setmetatable\", luaB_setmetatable},\n  {\"tonumber\", luaB_tonumber},\n  {\"tostring\", luaB_tostring},\n  {\"type\", luaB_type},\n  {\"unpack\", luaB_unpack},\n  {\"xpcall\", luaB_xpcall},\n  {NULL, NULL}\n};\n\n\n/*\n** {======================================================\n** Coroutine library\n** =======================================================\n*/\n\n#define CO_RUN\t0\t/* running */\n#define CO_SUS\t1\t/* suspended */\n#define CO_NOR\t2\t/* 'normal' (it resumed another coroutine) */\n#define CO_DEAD\t3\n\nstatic const char *const statnames[] =\n    {\"running\", \"suspended\", \"normal\", \"dead\"};\n\nstatic int costatus (lua_State *L, lua_State *co) {\n  if (L == co) return CO_RUN;\n  switch (lua_status(co)) {\n    case LUA_YIELD:\n      return CO_SUS;\n    case 0: {\n      lua_Debug ar;\n      if (lua_getstack(co, 0, &ar) > 0)  /* does it have frames? */\n        return CO_NOR;  /* it is running */\n      else if (lua_gettop(co) == 0)\n          return CO_DEAD;\n      else\n        return CO_SUS;  /* initial state */\n    }\n    default:  /* some error occured */\n      return CO_DEAD;\n  }\n}\n\n\nstatic int luaB_costatus (lua_State *L) {\n  lua_State *co = lua_tothread(L, 1);\n  luaL_argcheck(L, co, 1, \"coroutine expected\");\n  lua_pushstring(L, statnames[costatus(L, co)]);\n  return 1;\n}\n\n\nstatic int auxresume (lua_State *L, lua_State *co, int narg) {\n  int status = costatus(L, co);\n  if (!lua_checkstack(co, narg))\n    luaL_error(L, \"too many arguments to resume\");\n  if (status != CO_SUS) {\n    lua_pushfstring(L, \"cannot resume %s coroutine\", statnames[status]);\n    return -1;  /* error flag */\n  }\n  lua_xmove(L, co, narg);\n  lua_setlevel(L, co);\n  status = lua_resume(co, narg);\n  if (status == 0 || status == LUA_YIELD) {\n    int nres = lua_gettop(co);\n    if (!lua_checkstack(L, nres + 1))\n      luaL_error(L, \"too many results to resume\");\n    lua_xmove(co, L, nres);  /* move yielded values */\n    return nres;\n  }\n  else {\n    lua_xmove(co, L, 1);  /* move error message */\n    return -1;  /* error flag */\n  }\n}\n\n\nstatic int luaB_coresume (lua_State *L) {\n  lua_State *co = lua_tothread(L, 1);\n  int r;\n  luaL_argcheck(L, co, 1, \"coroutine expected\");\n  r = auxresume(L, co, lua_gettop(L) - 1);\n  if (r < 0) {\n    lua_pushboolean(L, 0);\n    lua_insert(L, -2);\n    return 2;  /* return false + error message */\n  }\n  else {\n    lua_pushboolean(L, 1);\n    lua_insert(L, -(r + 1));\n    return r + 1;  /* return true + `resume' returns */\n  }\n}\n\n\nstatic int luaB_auxwrap (lua_State *L) {\n  lua_State *co = lua_tothread(L, lua_upvalueindex(1));\n  int r = auxresume(L, co, lua_gettop(L));\n  if (r < 0) {\n    if (lua_isstring(L, -1)) {  /* error object is a string? */\n      luaL_where(L, 1);  /* add extra info */\n      lua_insert(L, -2);\n      lua_concat(L, 2);\n    }\n    lua_error(L);  /* propagate error */\n  }\n  return r;\n}\n\n\nstatic int luaB_cocreate (lua_State *L) {\n  lua_State *NL = lua_newthread(L);\n  luaL_argcheck(L, lua_isfunction(L, 1) && !lua_iscfunction(L, 1), 1,\n    \"Lua function expected\");\n  lua_pushvalue(L, 1);  /* move function to top */\n  lua_xmove(L, NL, 1);  /* move function from L to NL */\n  return 1;\n}\n\n\nstatic int luaB_cowrap (lua_State *L) {\n  luaB_cocreate(L);\n  lua_pushcclosure(L, luaB_auxwrap, 1);\n  return 1;\n}\n\n\nstatic int luaB_yield (lua_State *L) {\n  return lua_yield(L, lua_gettop(L));\n}\n\n\nstatic int luaB_corunning (lua_State *L) {\n  if (lua_pushthread(L))\n    lua_pushnil(L);  /* main thread is not a coroutine */\n  return 1;\n}\n\n\nstatic const luaL_Reg co_funcs[] = {\n  {\"create\", luaB_cocreate},\n  {\"resume\", luaB_coresume},\n  {\"running\", luaB_corunning},\n  {\"status\", luaB_costatus},\n  {\"wrap\", luaB_cowrap},\n  {\"yield\", luaB_yield},\n  {NULL, NULL}\n};\n\n/* }====================================================== */\n\n\nstatic void auxopen (lua_State *L, const char *name,\n                     lua_CFunction f, lua_CFunction u) {\n  lua_pushcfunction(L, u);\n  lua_pushcclosure(L, f, 1);\n  lua_setfield(L, -2, name);\n}\n\n\nstatic void base_open (lua_State *L) {\n  /* set global _G */\n  lua_pushvalue(L, LUA_GLOBALSINDEX);\n  lua_setglobal(L, \"_G\");\n  /* open lib into global table */\n  luaL_register(L, \"_G\", base_funcs);\n  lua_pushliteral(L, LUA_VERSION);\n  lua_setglobal(L, \"_VERSION\");  /* set global _VERSION */\n  /* `ipairs' and `pairs' need auxiliary functions as upvalues */\n  auxopen(L, \"ipairs\", luaB_ipairs, ipairsaux);\n  auxopen(L, \"pairs\", luaB_pairs, luaB_next);\n  /* `newproxy' needs a weaktable as upvalue */\n  lua_createtable(L, 0, 1);  /* new table `w' */\n  lua_pushvalue(L, -1);  /* `w' will be its own metatable */\n  lua_setmetatable(L, -2);\n  lua_pushliteral(L, \"kv\");\n  lua_setfield(L, -2, \"__mode\");  /* metatable(w).__mode = \"kv\" */\n  lua_pushcclosure(L, luaB_newproxy, 1);\n  lua_setglobal(L, \"newproxy\");  /* set global `newproxy' */\n}\n\n\nLUALIB_API int luaopen_base (lua_State *L) {\n  base_open(L);\n  luaL_register(L, LUA_COLIBNAME, co_funcs);\n  return 2;\n}\n\n"
  },
  {
    "path": "extern/deprecated/redis-2.8.21/deps/lua/src/lcode.c",
    "content": "/*\n** $Id: lcode.c,v 2.25.1.5 2011/01/31 14:53:16 roberto Exp $\n** Code generator for Lua\n** See Copyright Notice in lua.h\n*/\n\n\n#include <stdlib.h>\n\n#define lcode_c\n#define LUA_CORE\n\n#include \"lua.h\"\n\n#include \"lcode.h\"\n#include \"ldebug.h\"\n#include \"ldo.h\"\n#include \"lgc.h\"\n#include \"llex.h\"\n#include \"lmem.h\"\n#include \"lobject.h\"\n#include \"lopcodes.h\"\n#include \"lparser.h\"\n#include \"ltable.h\"\n\n\n#define hasjumps(e)\t((e)->t != (e)->f)\n\n\nstatic int isnumeral(expdesc *e) {\n  return (e->k == VKNUM && e->t == NO_JUMP && e->f == NO_JUMP);\n}\n\n\nvoid luaK_nil (FuncState *fs, int from, int n) {\n  Instruction *previous;\n  if (fs->pc > fs->lasttarget) {  /* no jumps to current position? */\n    if (fs->pc == 0) {  /* function start? */\n      if (from >= fs->nactvar)\n        return;  /* positions are already clean */\n    }\n    else {\n      previous = &fs->f->code[fs->pc-1];\n      if (GET_OPCODE(*previous) == OP_LOADNIL) {\n        int pfrom = GETARG_A(*previous);\n        int pto = GETARG_B(*previous);\n        if (pfrom <= from && from <= pto+1) {  /* can connect both? */\n          if (from+n-1 > pto)\n            SETARG_B(*previous, from+n-1);\n          return;\n        }\n      }\n    }\n  }\n  luaK_codeABC(fs, OP_LOADNIL, from, from+n-1, 0);  /* else no optimization */\n}\n\n\nint luaK_jump (FuncState *fs) {\n  int jpc = fs->jpc;  /* save list of jumps to here */\n  int j;\n  fs->jpc = NO_JUMP;\n  j = luaK_codeAsBx(fs, OP_JMP, 0, NO_JUMP);\n  luaK_concat(fs, &j, jpc);  /* keep them on hold */\n  return j;\n}\n\n\nvoid luaK_ret (FuncState *fs, int first, int nret) {\n  luaK_codeABC(fs, OP_RETURN, first, nret+1, 0);\n}\n\n\nstatic int condjump (FuncState *fs, OpCode op, int A, int B, int C) {\n  luaK_codeABC(fs, op, A, B, C);\n  return luaK_jump(fs);\n}\n\n\nstatic void fixjump (FuncState *fs, int pc, int dest) {\n  Instruction *jmp = &fs->f->code[pc];\n  int offset = dest-(pc+1);\n  lua_assert(dest != NO_JUMP);\n  if (abs(offset) > MAXARG_sBx)\n    luaX_syntaxerror(fs->ls, \"control structure too long\");\n  SETARG_sBx(*jmp, offset);\n}\n\n\n/*\n** returns current `pc' and marks it as a jump target (to avoid wrong\n** optimizations with consecutive instructions not in the same basic block).\n*/\nint luaK_getlabel (FuncState *fs) {\n  fs->lasttarget = fs->pc;\n  return fs->pc;\n}\n\n\nstatic int getjump (FuncState *fs, int pc) {\n  int offset = GETARG_sBx(fs->f->code[pc]);\n  if (offset == NO_JUMP)  /* point to itself represents end of list */\n    return NO_JUMP;  /* end of list */\n  else\n    return (pc+1)+offset;  /* turn offset into absolute position */\n}\n\n\nstatic Instruction *getjumpcontrol (FuncState *fs, int pc) {\n  Instruction *pi = &fs->f->code[pc];\n  if (pc >= 1 && testTMode(GET_OPCODE(*(pi-1))))\n    return pi-1;\n  else\n    return pi;\n}\n\n\n/*\n** check whether list has any jump that do not produce a value\n** (or produce an inverted value)\n*/\nstatic int need_value (FuncState *fs, int list) {\n  for (; list != NO_JUMP; list = getjump(fs, list)) {\n    Instruction i = *getjumpcontrol(fs, list);\n    if (GET_OPCODE(i) != OP_TESTSET) return 1;\n  }\n  return 0;  /* not found */\n}\n\n\nstatic int patchtestreg (FuncState *fs, int node, int reg) {\n  Instruction *i = getjumpcontrol(fs, node);\n  if (GET_OPCODE(*i) != OP_TESTSET)\n    return 0;  /* cannot patch other instructions */\n  if (reg != NO_REG && reg != GETARG_B(*i))\n    SETARG_A(*i, reg);\n  else  /* no register to put value or register already has the value */\n    *i = CREATE_ABC(OP_TEST, GETARG_B(*i), 0, GETARG_C(*i));\n\n  return 1;\n}\n\n\nstatic void removevalues (FuncState *fs, int list) {\n  for (; list != NO_JUMP; list = getjump(fs, list))\n      patchtestreg(fs, list, NO_REG);\n}\n\n\nstatic void patchlistaux (FuncState *fs, int list, int vtarget, int reg,\n                          int dtarget) {\n  while (list != NO_JUMP) {\n    int next = getjump(fs, list);\n    if (patchtestreg(fs, list, reg))\n      fixjump(fs, list, vtarget);\n    else\n      fixjump(fs, list, dtarget);  /* jump to default target */\n    list = next;\n  }\n}\n\n\nstatic void dischargejpc (FuncState *fs) {\n  patchlistaux(fs, fs->jpc, fs->pc, NO_REG, fs->pc);\n  fs->jpc = NO_JUMP;\n}\n\n\nvoid luaK_patchlist (FuncState *fs, int list, int target) {\n  if (target == fs->pc)\n    luaK_patchtohere(fs, list);\n  else {\n    lua_assert(target < fs->pc);\n    patchlistaux(fs, list, target, NO_REG, target);\n  }\n}\n\n\nvoid luaK_patchtohere (FuncState *fs, int list) {\n  luaK_getlabel(fs);\n  luaK_concat(fs, &fs->jpc, list);\n}\n\n\nvoid luaK_concat (FuncState *fs, int *l1, int l2) {\n  if (l2 == NO_JUMP) return;\n  else if (*l1 == NO_JUMP)\n    *l1 = l2;\n  else {\n    int list = *l1;\n    int next;\n    while ((next = getjump(fs, list)) != NO_JUMP)  /* find last element */\n      list = next;\n    fixjump(fs, list, l2);\n  }\n}\n\n\nvoid luaK_checkstack (FuncState *fs, int n) {\n  int newstack = fs->freereg + n;\n  if (newstack > fs->f->maxstacksize) {\n    if (newstack >= MAXSTACK)\n      luaX_syntaxerror(fs->ls, \"function or expression too complex\");\n    fs->f->maxstacksize = cast_byte(newstack);\n  }\n}\n\n\nvoid luaK_reserveregs (FuncState *fs, int n) {\n  luaK_checkstack(fs, n);\n  fs->freereg += n;\n}\n\n\nstatic void freereg (FuncState *fs, int reg) {\n  if (!ISK(reg) && reg >= fs->nactvar) {\n    fs->freereg--;\n    lua_assert(reg == fs->freereg);\n  }\n}\n\n\nstatic void freeexp (FuncState *fs, expdesc *e) {\n  if (e->k == VNONRELOC)\n    freereg(fs, e->u.s.info);\n}\n\n\nstatic int addk (FuncState *fs, TValue *k, TValue *v) {\n  lua_State *L = fs->L;\n  TValue *idx = luaH_set(L, fs->h, k);\n  Proto *f = fs->f;\n  int oldsize = f->sizek;\n  if (ttisnumber(idx)) {\n    lua_assert(luaO_rawequalObj(&fs->f->k[cast_int(nvalue(idx))], v));\n    return cast_int(nvalue(idx));\n  }\n  else {  /* constant not found; create a new entry */\n    setnvalue(idx, cast_num(fs->nk));\n    luaM_growvector(L, f->k, fs->nk, f->sizek, TValue,\n                    MAXARG_Bx, \"constant table overflow\");\n    while (oldsize < f->sizek) setnilvalue(&f->k[oldsize++]);\n    setobj(L, &f->k[fs->nk], v);\n    luaC_barrier(L, f, v);\n    return fs->nk++;\n  }\n}\n\n\nint luaK_stringK (FuncState *fs, TString *s) {\n  TValue o;\n  setsvalue(fs->L, &o, s);\n  return addk(fs, &o, &o);\n}\n\n\nint luaK_numberK (FuncState *fs, lua_Number r) {\n  TValue o;\n  setnvalue(&o, r);\n  return addk(fs, &o, &o);\n}\n\n\nstatic int boolK (FuncState *fs, int b) {\n  TValue o;\n  setbvalue(&o, b);\n  return addk(fs, &o, &o);\n}\n\n\nstatic int nilK (FuncState *fs) {\n  TValue k, v;\n  setnilvalue(&v);\n  /* cannot use nil as key; instead use table itself to represent nil */\n  sethvalue(fs->L, &k, fs->h);\n  return addk(fs, &k, &v);\n}\n\n\nvoid luaK_setreturns (FuncState *fs, expdesc *e, int nresults) {\n  if (e->k == VCALL) {  /* expression is an open function call? */\n    SETARG_C(getcode(fs, e), nresults+1);\n  }\n  else if (e->k == VVARARG) {\n    SETARG_B(getcode(fs, e), nresults+1);\n    SETARG_A(getcode(fs, e), fs->freereg);\n    luaK_reserveregs(fs, 1);\n  }\n}\n\n\nvoid luaK_setoneret (FuncState *fs, expdesc *e) {\n  if (e->k == VCALL) {  /* expression is an open function call? */\n    e->k = VNONRELOC;\n    e->u.s.info = GETARG_A(getcode(fs, e));\n  }\n  else if (e->k == VVARARG) {\n    SETARG_B(getcode(fs, e), 2);\n    e->k = VRELOCABLE;  /* can relocate its simple result */\n  }\n}\n\n\nvoid luaK_dischargevars (FuncState *fs, expdesc *e) {\n  switch (e->k) {\n    case VLOCAL: {\n      e->k = VNONRELOC;\n      break;\n    }\n    case VUPVAL: {\n      e->u.s.info = luaK_codeABC(fs, OP_GETUPVAL, 0, e->u.s.info, 0);\n      e->k = VRELOCABLE;\n      break;\n    }\n    case VGLOBAL: {\n      e->u.s.info = luaK_codeABx(fs, OP_GETGLOBAL, 0, e->u.s.info);\n      e->k = VRELOCABLE;\n      break;\n    }\n    case VINDEXED: {\n      freereg(fs, e->u.s.aux);\n      freereg(fs, e->u.s.info);\n      e->u.s.info = luaK_codeABC(fs, OP_GETTABLE, 0, e->u.s.info, e->u.s.aux);\n      e->k = VRELOCABLE;\n      break;\n    }\n    case VVARARG:\n    case VCALL: {\n      luaK_setoneret(fs, e);\n      break;\n    }\n    default: break;  /* there is one value available (somewhere) */\n  }\n}\n\n\nstatic int code_label (FuncState *fs, int A, int b, int jump) {\n  luaK_getlabel(fs);  /* those instructions may be jump targets */\n  return luaK_codeABC(fs, OP_LOADBOOL, A, b, jump);\n}\n\n\nstatic void discharge2reg (FuncState *fs, expdesc *e, int reg) {\n  luaK_dischargevars(fs, e);\n  switch (e->k) {\n    case VNIL: {\n      luaK_nil(fs, reg, 1);\n      break;\n    }\n    case VFALSE:  case VTRUE: {\n      luaK_codeABC(fs, OP_LOADBOOL, reg, e->k == VTRUE, 0);\n      break;\n    }\n    case VK: {\n      luaK_codeABx(fs, OP_LOADK, reg, e->u.s.info);\n      break;\n    }\n    case VKNUM: {\n      luaK_codeABx(fs, OP_LOADK, reg, luaK_numberK(fs, e->u.nval));\n      break;\n    }\n    case VRELOCABLE: {\n      Instruction *pc = &getcode(fs, e);\n      SETARG_A(*pc, reg);\n      break;\n    }\n    case VNONRELOC: {\n      if (reg != e->u.s.info)\n        luaK_codeABC(fs, OP_MOVE, reg, e->u.s.info, 0);\n      break;\n    }\n    default: {\n      lua_assert(e->k == VVOID || e->k == VJMP);\n      return;  /* nothing to do... */\n    }\n  }\n  e->u.s.info = reg;\n  e->k = VNONRELOC;\n}\n\n\nstatic void discharge2anyreg (FuncState *fs, expdesc *e) {\n  if (e->k != VNONRELOC) {\n    luaK_reserveregs(fs, 1);\n    discharge2reg(fs, e, fs->freereg-1);\n  }\n}\n\n\nstatic void exp2reg (FuncState *fs, expdesc *e, int reg) {\n  discharge2reg(fs, e, reg);\n  if (e->k == VJMP)\n    luaK_concat(fs, &e->t, e->u.s.info);  /* put this jump in `t' list */\n  if (hasjumps(e)) {\n    int final;  /* position after whole expression */\n    int p_f = NO_JUMP;  /* position of an eventual LOAD false */\n    int p_t = NO_JUMP;  /* position of an eventual LOAD true */\n    if (need_value(fs, e->t) || need_value(fs, e->f)) {\n      int fj = (e->k == VJMP) ? NO_JUMP : luaK_jump(fs);\n      p_f = code_label(fs, reg, 0, 1);\n      p_t = code_label(fs, reg, 1, 0);\n      luaK_patchtohere(fs, fj);\n    }\n    final = luaK_getlabel(fs);\n    patchlistaux(fs, e->f, final, reg, p_f);\n    patchlistaux(fs, e->t, final, reg, p_t);\n  }\n  e->f = e->t = NO_JUMP;\n  e->u.s.info = reg;\n  e->k = VNONRELOC;\n}\n\n\nvoid luaK_exp2nextreg (FuncState *fs, expdesc *e) {\n  luaK_dischargevars(fs, e);\n  freeexp(fs, e);\n  luaK_reserveregs(fs, 1);\n  exp2reg(fs, e, fs->freereg - 1);\n}\n\n\nint luaK_exp2anyreg (FuncState *fs, expdesc *e) {\n  luaK_dischargevars(fs, e);\n  if (e->k == VNONRELOC) {\n    if (!hasjumps(e)) return e->u.s.info;  /* exp is already in a register */\n    if (e->u.s.info >= fs->nactvar) {  /* reg. is not a local? */\n      exp2reg(fs, e, e->u.s.info);  /* put value on it */\n      return e->u.s.info;\n    }\n  }\n  luaK_exp2nextreg(fs, e);  /* default */\n  return e->u.s.info;\n}\n\n\nvoid luaK_exp2val (FuncState *fs, expdesc *e) {\n  if (hasjumps(e))\n    luaK_exp2anyreg(fs, e);\n  else\n    luaK_dischargevars(fs, e);\n}\n\n\nint luaK_exp2RK (FuncState *fs, expdesc *e) {\n  luaK_exp2val(fs, e);\n  switch (e->k) {\n    case VKNUM:\n    case VTRUE:\n    case VFALSE:\n    case VNIL: {\n      if (fs->nk <= MAXINDEXRK) {  /* constant fit in RK operand? */\n        e->u.s.info = (e->k == VNIL)  ? nilK(fs) :\n                      (e->k == VKNUM) ? luaK_numberK(fs, e->u.nval) :\n                                        boolK(fs, (e->k == VTRUE));\n        e->k = VK;\n        return RKASK(e->u.s.info);\n      }\n      else break;\n    }\n    case VK: {\n      if (e->u.s.info <= MAXINDEXRK)  /* constant fit in argC? */\n        return RKASK(e->u.s.info);\n      else break;\n    }\n    default: break;\n  }\n  /* not a constant in the right range: put it in a register */\n  return luaK_exp2anyreg(fs, e);\n}\n\n\nvoid luaK_storevar (FuncState *fs, expdesc *var, expdesc *ex) {\n  switch (var->k) {\n    case VLOCAL: {\n      freeexp(fs, ex);\n      exp2reg(fs, ex, var->u.s.info);\n      return;\n    }\n    case VUPVAL: {\n      int e = luaK_exp2anyreg(fs, ex);\n      luaK_codeABC(fs, OP_SETUPVAL, e, var->u.s.info, 0);\n      break;\n    }\n    case VGLOBAL: {\n      int e = luaK_exp2anyreg(fs, ex);\n      luaK_codeABx(fs, OP_SETGLOBAL, e, var->u.s.info);\n      break;\n    }\n    case VINDEXED: {\n      int e = luaK_exp2RK(fs, ex);\n      luaK_codeABC(fs, OP_SETTABLE, var->u.s.info, var->u.s.aux, e);\n      break;\n    }\n    default: {\n      lua_assert(0);  /* invalid var kind to store */\n      break;\n    }\n  }\n  freeexp(fs, ex);\n}\n\n\nvoid luaK_self (FuncState *fs, expdesc *e, expdesc *key) {\n  int func;\n  luaK_exp2anyreg(fs, e);\n  freeexp(fs, e);\n  func = fs->freereg;\n  luaK_reserveregs(fs, 2);\n  luaK_codeABC(fs, OP_SELF, func, e->u.s.info, luaK_exp2RK(fs, key));\n  freeexp(fs, key);\n  e->u.s.info = func;\n  e->k = VNONRELOC;\n}\n\n\nstatic void invertjump (FuncState *fs, expdesc *e) {\n  Instruction *pc = getjumpcontrol(fs, e->u.s.info);\n  lua_assert(testTMode(GET_OPCODE(*pc)) && GET_OPCODE(*pc) != OP_TESTSET &&\n                                           GET_OPCODE(*pc) != OP_TEST);\n  SETARG_A(*pc, !(GETARG_A(*pc)));\n}\n\n\nstatic int jumponcond (FuncState *fs, expdesc *e, int cond) {\n  if (e->k == VRELOCABLE) {\n    Instruction ie = getcode(fs, e);\n    if (GET_OPCODE(ie) == OP_NOT) {\n      fs->pc--;  /* remove previous OP_NOT */\n      return condjump(fs, OP_TEST, GETARG_B(ie), 0, !cond);\n    }\n    /* else go through */\n  }\n  discharge2anyreg(fs, e);\n  freeexp(fs, e);\n  return condjump(fs, OP_TESTSET, NO_REG, e->u.s.info, cond);\n}\n\n\nvoid luaK_goiftrue (FuncState *fs, expdesc *e) {\n  int pc;  /* pc of last jump */\n  luaK_dischargevars(fs, e);\n  switch (e->k) {\n    case VK: case VKNUM: case VTRUE: {\n      pc = NO_JUMP;  /* always true; do nothing */\n      break;\n    }\n    case VJMP: {\n      invertjump(fs, e);\n      pc = e->u.s.info;\n      break;\n    }\n    default: {\n      pc = jumponcond(fs, e, 0);\n      break;\n    }\n  }\n  luaK_concat(fs, &e->f, pc);  /* insert last jump in `f' list */\n  luaK_patchtohere(fs, e->t);\n  e->t = NO_JUMP;\n}\n\n\nstatic void luaK_goiffalse (FuncState *fs, expdesc *e) {\n  int pc;  /* pc of last jump */\n  luaK_dischargevars(fs, e);\n  switch (e->k) {\n    case VNIL: case VFALSE: {\n      pc = NO_JUMP;  /* always false; do nothing */\n      break;\n    }\n    case VJMP: {\n      pc = e->u.s.info;\n      break;\n    }\n    default: {\n      pc = jumponcond(fs, e, 1);\n      break;\n    }\n  }\n  luaK_concat(fs, &e->t, pc);  /* insert last jump in `t' list */\n  luaK_patchtohere(fs, e->f);\n  e->f = NO_JUMP;\n}\n\n\nstatic void codenot (FuncState *fs, expdesc *e) {\n  luaK_dischargevars(fs, e);\n  switch (e->k) {\n    case VNIL: case VFALSE: {\n      e->k = VTRUE;\n      break;\n    }\n    case VK: case VKNUM: case VTRUE: {\n      e->k = VFALSE;\n      break;\n    }\n    case VJMP: {\n      invertjump(fs, e);\n      break;\n    }\n    case VRELOCABLE:\n    case VNONRELOC: {\n      discharge2anyreg(fs, e);\n      freeexp(fs, e);\n      e->u.s.info = luaK_codeABC(fs, OP_NOT, 0, e->u.s.info, 0);\n      e->k = VRELOCABLE;\n      break;\n    }\n    default: {\n      lua_assert(0);  /* cannot happen */\n      break;\n    }\n  }\n  /* interchange true and false lists */\n  { int temp = e->f; e->f = e->t; e->t = temp; }\n  removevalues(fs, e->f);\n  removevalues(fs, e->t);\n}\n\n\nvoid luaK_indexed (FuncState *fs, expdesc *t, expdesc *k) {\n  t->u.s.aux = luaK_exp2RK(fs, k);\n  t->k = VINDEXED;\n}\n\n\nstatic int constfolding (OpCode op, expdesc *e1, expdesc *e2) {\n  lua_Number v1, v2, r;\n  if (!isnumeral(e1) || !isnumeral(e2)) return 0;\n  v1 = e1->u.nval;\n  v2 = e2->u.nval;\n  switch (op) {\n    case OP_ADD: r = luai_numadd(v1, v2); break;\n    case OP_SUB: r = luai_numsub(v1, v2); break;\n    case OP_MUL: r = luai_nummul(v1, v2); break;\n    case OP_DIV:\n      if (v2 == 0) return 0;  /* do not attempt to divide by 0 */\n      r = luai_numdiv(v1, v2); break;\n    case OP_MOD:\n      if (v2 == 0) return 0;  /* do not attempt to divide by 0 */\n      r = luai_nummod(v1, v2); break;\n    case OP_POW: r = luai_numpow(v1, v2); break;\n    case OP_UNM: r = luai_numunm(v1); break;\n    case OP_LEN: return 0;  /* no constant folding for 'len' */\n    default: lua_assert(0); r = 0; break;\n  }\n  if (luai_numisnan(r)) return 0;  /* do not attempt to produce NaN */\n  e1->u.nval = r;\n  return 1;\n}\n\n\nstatic void codearith (FuncState *fs, OpCode op, expdesc *e1, expdesc *e2) {\n  if (constfolding(op, e1, e2))\n    return;\n  else {\n    int o2 = (op != OP_UNM && op != OP_LEN) ? luaK_exp2RK(fs, e2) : 0;\n    int o1 = luaK_exp2RK(fs, e1);\n    if (o1 > o2) {\n      freeexp(fs, e1);\n      freeexp(fs, e2);\n    }\n    else {\n      freeexp(fs, e2);\n      freeexp(fs, e1);\n    }\n    e1->u.s.info = luaK_codeABC(fs, op, 0, o1, o2);\n    e1->k = VRELOCABLE;\n  }\n}\n\n\nstatic void codecomp (FuncState *fs, OpCode op, int cond, expdesc *e1,\n                                                          expdesc *e2) {\n  int o1 = luaK_exp2RK(fs, e1);\n  int o2 = luaK_exp2RK(fs, e2);\n  freeexp(fs, e2);\n  freeexp(fs, e1);\n  if (cond == 0 && op != OP_EQ) {\n    int temp;  /* exchange args to replace by `<' or `<=' */\n    temp = o1; o1 = o2; o2 = temp;  /* o1 <==> o2 */\n    cond = 1;\n  }\n  e1->u.s.info = condjump(fs, op, cond, o1, o2);\n  e1->k = VJMP;\n}\n\n\nvoid luaK_prefix (FuncState *fs, UnOpr op, expdesc *e) {\n  expdesc e2;\n  e2.t = e2.f = NO_JUMP; e2.k = VKNUM; e2.u.nval = 0;\n  switch (op) {\n    case OPR_MINUS: {\n      if (!isnumeral(e))\n        luaK_exp2anyreg(fs, e);  /* cannot operate on non-numeric constants */\n      codearith(fs, OP_UNM, e, &e2);\n      break;\n    }\n    case OPR_NOT: codenot(fs, e); break;\n    case OPR_LEN: {\n      luaK_exp2anyreg(fs, e);  /* cannot operate on constants */\n      codearith(fs, OP_LEN, e, &e2);\n      break;\n    }\n    default: lua_assert(0);\n  }\n}\n\n\nvoid luaK_infix (FuncState *fs, BinOpr op, expdesc *v) {\n  switch (op) {\n    case OPR_AND: {\n      luaK_goiftrue(fs, v);\n      break;\n    }\n    case OPR_OR: {\n      luaK_goiffalse(fs, v);\n      break;\n    }\n    case OPR_CONCAT: {\n      luaK_exp2nextreg(fs, v);  /* operand must be on the `stack' */\n      break;\n    }\n    case OPR_ADD: case OPR_SUB: case OPR_MUL: case OPR_DIV:\n    case OPR_MOD: case OPR_POW: {\n      if (!isnumeral(v)) luaK_exp2RK(fs, v);\n      break;\n    }\n    default: {\n      luaK_exp2RK(fs, v);\n      break;\n    }\n  }\n}\n\n\nvoid luaK_posfix (FuncState *fs, BinOpr op, expdesc *e1, expdesc *e2) {\n  switch (op) {\n    case OPR_AND: {\n      lua_assert(e1->t == NO_JUMP);  /* list must be closed */\n      luaK_dischargevars(fs, e2);\n      luaK_concat(fs, &e2->f, e1->f);\n      *e1 = *e2;\n      break;\n    }\n    case OPR_OR: {\n      lua_assert(e1->f == NO_JUMP);  /* list must be closed */\n      luaK_dischargevars(fs, e2);\n      luaK_concat(fs, &e2->t, e1->t);\n      *e1 = *e2;\n      break;\n    }\n    case OPR_CONCAT: {\n      luaK_exp2val(fs, e2);\n      if (e2->k == VRELOCABLE && GET_OPCODE(getcode(fs, e2)) == OP_CONCAT) {\n        lua_assert(e1->u.s.info == GETARG_B(getcode(fs, e2))-1);\n        freeexp(fs, e1);\n        SETARG_B(getcode(fs, e2), e1->u.s.info);\n        e1->k = VRELOCABLE; e1->u.s.info = e2->u.s.info;\n      }\n      else {\n        luaK_exp2nextreg(fs, e2);  /* operand must be on the 'stack' */\n        codearith(fs, OP_CONCAT, e1, e2);\n      }\n      break;\n    }\n    case OPR_ADD: codearith(fs, OP_ADD, e1, e2); break;\n    case OPR_SUB: codearith(fs, OP_SUB, e1, e2); break;\n    case OPR_MUL: codearith(fs, OP_MUL, e1, e2); break;\n    case OPR_DIV: codearith(fs, OP_DIV, e1, e2); break;\n    case OPR_MOD: codearith(fs, OP_MOD, e1, e2); break;\n    case OPR_POW: codearith(fs, OP_POW, e1, e2); break;\n    case OPR_EQ: codecomp(fs, OP_EQ, 1, e1, e2); break;\n    case OPR_NE: codecomp(fs, OP_EQ, 0, e1, e2); break;\n    case OPR_LT: codecomp(fs, OP_LT, 1, e1, e2); break;\n    case OPR_LE: codecomp(fs, OP_LE, 1, e1, e2); break;\n    case OPR_GT: codecomp(fs, OP_LT, 0, e1, e2); break;\n    case OPR_GE: codecomp(fs, OP_LE, 0, e1, e2); break;\n    default: lua_assert(0);\n  }\n}\n\n\nvoid luaK_fixline (FuncState *fs, int line) {\n  fs->f->lineinfo[fs->pc - 1] = line;\n}\n\n\nstatic int luaK_code (FuncState *fs, Instruction i, int line) {\n  Proto *f = fs->f;\n  dischargejpc(fs);  /* `pc' will change */\n  /* put new instruction in code array */\n  luaM_growvector(fs->L, f->code, fs->pc, f->sizecode, Instruction,\n                  MAX_INT, \"code size overflow\");\n  f->code[fs->pc] = i;\n  /* save corresponding line information */\n  luaM_growvector(fs->L, f->lineinfo, fs->pc, f->sizelineinfo, int,\n                  MAX_INT, \"code size overflow\");\n  f->lineinfo[fs->pc] = line;\n  return fs->pc++;\n}\n\n\nint luaK_codeABC (FuncState *fs, OpCode o, int a, int b, int c) {\n  lua_assert(getOpMode(o) == iABC);\n  lua_assert(getBMode(o) != OpArgN || b == 0);\n  lua_assert(getCMode(o) != OpArgN || c == 0);\n  return luaK_code(fs, CREATE_ABC(o, a, b, c), fs->ls->lastline);\n}\n\n\nint luaK_codeABx (FuncState *fs, OpCode o, int a, unsigned int bc) {\n  lua_assert(getOpMode(o) == iABx || getOpMode(o) == iAsBx);\n  lua_assert(getCMode(o) == OpArgN);\n  return luaK_code(fs, CREATE_ABx(o, a, bc), fs->ls->lastline);\n}\n\n\nvoid luaK_setlist (FuncState *fs, int base, int nelems, int tostore) {\n  int c =  (nelems - 1)/LFIELDS_PER_FLUSH + 1;\n  int b = (tostore == LUA_MULTRET) ? 0 : tostore;\n  lua_assert(tostore != 0);\n  if (c <= MAXARG_C)\n    luaK_codeABC(fs, OP_SETLIST, base, b, c);\n  else {\n    luaK_codeABC(fs, OP_SETLIST, base, b, 0);\n    luaK_code(fs, cast(Instruction, c), fs->ls->lastline);\n  }\n  fs->freereg = base + 1;  /* free registers with list values */\n}\n\n"
  },
  {
    "path": "extern/deprecated/redis-2.8.21/deps/lua/src/lcode.h",
    "content": "/*\n** $Id: lcode.h,v 1.48.1.1 2007/12/27 13:02:25 roberto Exp $\n** Code generator for Lua\n** See Copyright Notice in lua.h\n*/\n\n#ifndef lcode_h\n#define lcode_h\n\n#include \"llex.h\"\n#include \"lobject.h\"\n#include \"lopcodes.h\"\n#include \"lparser.h\"\n\n\n/*\n** Marks the end of a patch list. It is an invalid value both as an absolute\n** address, and as a list link (would link an element to itself).\n*/\n#define NO_JUMP (-1)\n\n\n/*\n** grep \"ORDER OPR\" if you change these enums\n*/\ntypedef enum BinOpr {\n  OPR_ADD, OPR_SUB, OPR_MUL, OPR_DIV, OPR_MOD, OPR_POW,\n  OPR_CONCAT,\n  OPR_NE, OPR_EQ,\n  OPR_LT, OPR_LE, OPR_GT, OPR_GE,\n  OPR_AND, OPR_OR,\n  OPR_NOBINOPR\n} BinOpr;\n\n\ntypedef enum UnOpr { OPR_MINUS, OPR_NOT, OPR_LEN, OPR_NOUNOPR } UnOpr;\n\n\n#define getcode(fs,e)\t((fs)->f->code[(e)->u.s.info])\n\n#define luaK_codeAsBx(fs,o,A,sBx)\tluaK_codeABx(fs,o,A,(sBx)+MAXARG_sBx)\n\n#define luaK_setmultret(fs,e)\tluaK_setreturns(fs, e, LUA_MULTRET)\n\nLUAI_FUNC int luaK_codeABx (FuncState *fs, OpCode o, int A, unsigned int Bx);\nLUAI_FUNC int luaK_codeABC (FuncState *fs, OpCode o, int A, int B, int C);\nLUAI_FUNC void luaK_fixline (FuncState *fs, int line);\nLUAI_FUNC void luaK_nil (FuncState *fs, int from, int n);\nLUAI_FUNC void luaK_reserveregs (FuncState *fs, int n);\nLUAI_FUNC void luaK_checkstack (FuncState *fs, int n);\nLUAI_FUNC int luaK_stringK (FuncState *fs, TString *s);\nLUAI_FUNC int luaK_numberK (FuncState *fs, lua_Number r);\nLUAI_FUNC void luaK_dischargevars (FuncState *fs, expdesc *e);\nLUAI_FUNC int luaK_exp2anyreg (FuncState *fs, expdesc *e);\nLUAI_FUNC void luaK_exp2nextreg (FuncState *fs, expdesc *e);\nLUAI_FUNC void luaK_exp2val (FuncState *fs, expdesc *e);\nLUAI_FUNC int luaK_exp2RK (FuncState *fs, expdesc *e);\nLUAI_FUNC void luaK_self (FuncState *fs, expdesc *e, expdesc *key);\nLUAI_FUNC void luaK_indexed (FuncState *fs, expdesc *t, expdesc *k);\nLUAI_FUNC void luaK_goiftrue (FuncState *fs, expdesc *e);\nLUAI_FUNC void luaK_storevar (FuncState *fs, expdesc *var, expdesc *e);\nLUAI_FUNC void luaK_setreturns (FuncState *fs, expdesc *e, int nresults);\nLUAI_FUNC void luaK_setoneret (FuncState *fs, expdesc *e);\nLUAI_FUNC int luaK_jump (FuncState *fs);\nLUAI_FUNC void luaK_ret (FuncState *fs, int first, int nret);\nLUAI_FUNC void luaK_patchlist (FuncState *fs, int list, int target);\nLUAI_FUNC void luaK_patchtohere (FuncState *fs, int list);\nLUAI_FUNC void luaK_concat (FuncState *fs, int *l1, int l2);\nLUAI_FUNC int luaK_getlabel (FuncState *fs);\nLUAI_FUNC void luaK_prefix (FuncState *fs, UnOpr op, expdesc *v);\nLUAI_FUNC void luaK_infix (FuncState *fs, BinOpr op, expdesc *v);\nLUAI_FUNC void luaK_posfix (FuncState *fs, BinOpr op, expdesc *v1, expdesc *v2);\nLUAI_FUNC void luaK_setlist (FuncState *fs, int base, int nelems, int tostore);\n\n\n#endif\n"
  },
  {
    "path": "extern/deprecated/redis-2.8.21/deps/lua/src/ldblib.c",
    "content": "/*\n** $Id: ldblib.c,v 1.104.1.4 2009/08/04 18:50:18 roberto Exp $\n** Interface from Lua to its debug API\n** See Copyright Notice in lua.h\n*/\n\n\n#include <stdio.h>\n#include <stdlib.h>\n#include <string.h>\n\n#define ldblib_c\n#define LUA_LIB\n\n#include \"lua.h\"\n\n#include \"lauxlib.h\"\n#include \"lualib.h\"\n\n\n\nstatic int db_getregistry (lua_State *L) {\n  lua_pushvalue(L, LUA_REGISTRYINDEX);\n  return 1;\n}\n\n\nstatic int db_getmetatable (lua_State *L) {\n  luaL_checkany(L, 1);\n  if (!lua_getmetatable(L, 1)) {\n    lua_pushnil(L);  /* no metatable */\n  }\n  return 1;\n}\n\n\nstatic int db_setmetatable (lua_State *L) {\n  int t = lua_type(L, 2);\n  luaL_argcheck(L, t == LUA_TNIL || t == LUA_TTABLE, 2,\n                    \"nil or table expected\");\n  lua_settop(L, 2);\n  lua_pushboolean(L, lua_setmetatable(L, 1));\n  return 1;\n}\n\n\nstatic int db_getfenv (lua_State *L) {\n  luaL_checkany(L, 1);\n  lua_getfenv(L, 1);\n  return 1;\n}\n\n\nstatic int db_setfenv (lua_State *L) {\n  luaL_checktype(L, 2, LUA_TTABLE);\n  lua_settop(L, 2);\n  if (lua_setfenv(L, 1) == 0)\n    luaL_error(L, LUA_QL(\"setfenv\")\n                  \" cannot change environment of given object\");\n  return 1;\n}\n\n\nstatic void settabss (lua_State *L, const char *i, const char *v) {\n  lua_pushstring(L, v);\n  lua_setfield(L, -2, i);\n}\n\n\nstatic void settabsi (lua_State *L, const char *i, int v) {\n  lua_pushinteger(L, v);\n  lua_setfield(L, -2, i);\n}\n\n\nstatic lua_State *getthread (lua_State *L, int *arg) {\n  if (lua_isthread(L, 1)) {\n    *arg = 1;\n    return lua_tothread(L, 1);\n  }\n  else {\n    *arg = 0;\n    return L;\n  }\n}\n\n\nstatic void treatstackoption (lua_State *L, lua_State *L1, const char *fname) {\n  if (L == L1) {\n    lua_pushvalue(L, -2);\n    lua_remove(L, -3);\n  }\n  else\n    lua_xmove(L1, L, 1);\n  lua_setfield(L, -2, fname);\n}\n\n\nstatic int db_getinfo (lua_State *L) {\n  lua_Debug ar;\n  int arg;\n  lua_State *L1 = getthread(L, &arg);\n  const char *options = luaL_optstring(L, arg+2, \"flnSu\");\n  if (lua_isnumber(L, arg+1)) {\n    if (!lua_getstack(L1, (int)lua_tointeger(L, arg+1), &ar)) {\n      lua_pushnil(L);  /* level out of range */\n      return 1;\n    }\n  }\n  else if (lua_isfunction(L, arg+1)) {\n    lua_pushfstring(L, \">%s\", options);\n    options = lua_tostring(L, -1);\n    lua_pushvalue(L, arg+1);\n    lua_xmove(L, L1, 1);\n  }\n  else\n    return luaL_argerror(L, arg+1, \"function or level expected\");\n  if (!lua_getinfo(L1, options, &ar))\n    return luaL_argerror(L, arg+2, \"invalid option\");\n  lua_createtable(L, 0, 2);\n  if (strchr(options, 'S')) {\n    settabss(L, \"source\", ar.source);\n    settabss(L, \"short_src\", ar.short_src);\n    settabsi(L, \"linedefined\", ar.linedefined);\n    settabsi(L, \"lastlinedefined\", ar.lastlinedefined);\n    settabss(L, \"what\", ar.what);\n  }\n  if (strchr(options, 'l'))\n    settabsi(L, \"currentline\", ar.currentline);\n  if (strchr(options, 'u'))\n    settabsi(L, \"nups\", ar.nups);\n  if (strchr(options, 'n')) {\n    settabss(L, \"name\", ar.name);\n    settabss(L, \"namewhat\", ar.namewhat);\n  }\n  if (strchr(options, 'L'))\n    treatstackoption(L, L1, \"activelines\");\n  if (strchr(options, 'f'))\n    treatstackoption(L, L1, \"func\");\n  return 1;  /* return table */\n}\n    \n\nstatic int db_getlocal (lua_State *L) {\n  int arg;\n  lua_State *L1 = getthread(L, &arg);\n  lua_Debug ar;\n  const char *name;\n  if (!lua_getstack(L1, luaL_checkint(L, arg+1), &ar))  /* out of range? */\n    return luaL_argerror(L, arg+1, \"level out of range\");\n  name = lua_getlocal(L1, &ar, luaL_checkint(L, arg+2));\n  if (name) {\n    lua_xmove(L1, L, 1);\n    lua_pushstring(L, name);\n    lua_pushvalue(L, -2);\n    return 2;\n  }\n  else {\n    lua_pushnil(L);\n    return 1;\n  }\n}\n\n\nstatic int db_setlocal (lua_State *L) {\n  int arg;\n  lua_State *L1 = getthread(L, &arg);\n  lua_Debug ar;\n  if (!lua_getstack(L1, luaL_checkint(L, arg+1), &ar))  /* out of range? */\n    return luaL_argerror(L, arg+1, \"level out of range\");\n  luaL_checkany(L, arg+3);\n  lua_settop(L, arg+3);\n  lua_xmove(L, L1, 1);\n  lua_pushstring(L, lua_setlocal(L1, &ar, luaL_checkint(L, arg+2)));\n  return 1;\n}\n\n\nstatic int auxupvalue (lua_State *L, int get) {\n  const char *name;\n  int n = luaL_checkint(L, 2);\n  luaL_checktype(L, 1, LUA_TFUNCTION);\n  if (lua_iscfunction(L, 1)) return 0;  /* cannot touch C upvalues from Lua */\n  name = get ? lua_getupvalue(L, 1, n) : lua_setupvalue(L, 1, n);\n  if (name == NULL) return 0;\n  lua_pushstring(L, name);\n  lua_insert(L, -(get+1));\n  return get + 1;\n}\n\n\nstatic int db_getupvalue (lua_State *L) {\n  return auxupvalue(L, 1);\n}\n\n\nstatic int db_setupvalue (lua_State *L) {\n  luaL_checkany(L, 3);\n  return auxupvalue(L, 0);\n}\n\n\n\nstatic const char KEY_HOOK = 'h';\n\n\nstatic void hookf (lua_State *L, lua_Debug *ar) {\n  static const char *const hooknames[] =\n    {\"call\", \"return\", \"line\", \"count\", \"tail return\"};\n  lua_pushlightuserdata(L, (void *)&KEY_HOOK);\n  lua_rawget(L, LUA_REGISTRYINDEX);\n  lua_pushlightuserdata(L, L);\n  lua_rawget(L, -2);\n  if (lua_isfunction(L, -1)) {\n    lua_pushstring(L, hooknames[(int)ar->event]);\n    if (ar->currentline >= 0)\n      lua_pushinteger(L, ar->currentline);\n    else lua_pushnil(L);\n    lua_assert(lua_getinfo(L, \"lS\", ar));\n    lua_call(L, 2, 0);\n  }\n}\n\n\nstatic int makemask (const char *smask, int count) {\n  int mask = 0;\n  if (strchr(smask, 'c')) mask |= LUA_MASKCALL;\n  if (strchr(smask, 'r')) mask |= LUA_MASKRET;\n  if (strchr(smask, 'l')) mask |= LUA_MASKLINE;\n  if (count > 0) mask |= LUA_MASKCOUNT;\n  return mask;\n}\n\n\nstatic char *unmakemask (int mask, char *smask) {\n  int i = 0;\n  if (mask & LUA_MASKCALL) smask[i++] = 'c';\n  if (mask & LUA_MASKRET) smask[i++] = 'r';\n  if (mask & LUA_MASKLINE) smask[i++] = 'l';\n  smask[i] = '\\0';\n  return smask;\n}\n\n\nstatic void gethooktable (lua_State *L) {\n  lua_pushlightuserdata(L, (void *)&KEY_HOOK);\n  lua_rawget(L, LUA_REGISTRYINDEX);\n  if (!lua_istable(L, -1)) {\n    lua_pop(L, 1);\n    lua_createtable(L, 0, 1);\n    lua_pushlightuserdata(L, (void *)&KEY_HOOK);\n    lua_pushvalue(L, -2);\n    lua_rawset(L, LUA_REGISTRYINDEX);\n  }\n}\n\n\nstatic int db_sethook (lua_State *L) {\n  int arg, mask, count;\n  lua_Hook func;\n  lua_State *L1 = getthread(L, &arg);\n  if (lua_isnoneornil(L, arg+1)) {\n    lua_settop(L, arg+1);\n    func = NULL; mask = 0; count = 0;  /* turn off hooks */\n  }\n  else {\n    const char *smask = luaL_checkstring(L, arg+2);\n    luaL_checktype(L, arg+1, LUA_TFUNCTION);\n    count = luaL_optint(L, arg+3, 0);\n    func = hookf; mask = makemask(smask, count);\n  }\n  gethooktable(L);\n  lua_pushlightuserdata(L, L1);\n  lua_pushvalue(L, arg+1);\n  lua_rawset(L, -3);  /* set new hook */\n  lua_pop(L, 1);  /* remove hook table */\n  lua_sethook(L1, func, mask, count);  /* set hooks */\n  return 0;\n}\n\n\nstatic int db_gethook (lua_State *L) {\n  int arg;\n  lua_State *L1 = getthread(L, &arg);\n  char buff[5];\n  int mask = lua_gethookmask(L1);\n  lua_Hook hook = lua_gethook(L1);\n  if (hook != NULL && hook != hookf)  /* external hook? */\n    lua_pushliteral(L, \"external hook\");\n  else {\n    gethooktable(L);\n    lua_pushlightuserdata(L, L1);\n    lua_rawget(L, -2);   /* get hook */\n    lua_remove(L, -2);  /* remove hook table */\n  }\n  lua_pushstring(L, unmakemask(mask, buff));\n  lua_pushinteger(L, lua_gethookcount(L1));\n  return 3;\n}\n\n\nstatic int db_debug (lua_State *L) {\n  for (;;) {\n    char buffer[250];\n    fputs(\"lua_debug> \", stderr);\n    if (fgets(buffer, sizeof(buffer), stdin) == 0 ||\n        strcmp(buffer, \"cont\\n\") == 0)\n      return 0;\n    if (luaL_loadbuffer(L, buffer, strlen(buffer), \"=(debug command)\") ||\n        lua_pcall(L, 0, 0, 0)) {\n      fputs(lua_tostring(L, -1), stderr);\n      fputs(\"\\n\", stderr);\n    }\n    lua_settop(L, 0);  /* remove eventual returns */\n  }\n}\n\n\n#define LEVELS1\t12\t/* size of the first part of the stack */\n#define LEVELS2\t10\t/* size of the second part of the stack */\n\nstatic int db_errorfb (lua_State *L) {\n  int level;\n  int firstpart = 1;  /* still before eventual `...' */\n  int arg;\n  lua_State *L1 = getthread(L, &arg);\n  lua_Debug ar;\n  if (lua_isnumber(L, arg+2)) {\n    level = (int)lua_tointeger(L, arg+2);\n    lua_pop(L, 1);\n  }\n  else\n    level = (L == L1) ? 1 : 0;  /* level 0 may be this own function */\n  if (lua_gettop(L) == arg)\n    lua_pushliteral(L, \"\");\n  else if (!lua_isstring(L, arg+1)) return 1;  /* message is not a string */\n  else lua_pushliteral(L, \"\\n\");\n  lua_pushliteral(L, \"stack traceback:\");\n  while (lua_getstack(L1, level++, &ar)) {\n    if (level > LEVELS1 && firstpart) {\n      /* no more than `LEVELS2' more levels? */\n      if (!lua_getstack(L1, level+LEVELS2, &ar))\n        level--;  /* keep going */\n      else {\n        lua_pushliteral(L, \"\\n\\t...\");  /* too many levels */\n        while (lua_getstack(L1, level+LEVELS2, &ar))  /* find last levels */\n          level++;\n      }\n      firstpart = 0;\n      continue;\n    }\n    lua_pushliteral(L, \"\\n\\t\");\n    lua_getinfo(L1, \"Snl\", &ar);\n    lua_pushfstring(L, \"%s:\", ar.short_src);\n    if (ar.currentline > 0)\n      lua_pushfstring(L, \"%d:\", ar.currentline);\n    if (*ar.namewhat != '\\0')  /* is there a name? */\n        lua_pushfstring(L, \" in function \" LUA_QS, ar.name);\n    else {\n      if (*ar.what == 'm')  /* main? */\n        lua_pushfstring(L, \" in main chunk\");\n      else if (*ar.what == 'C' || *ar.what == 't')\n        lua_pushliteral(L, \" ?\");  /* C function or tail call */\n      else\n        lua_pushfstring(L, \" in function <%s:%d>\",\n                           ar.short_src, ar.linedefined);\n    }\n    lua_concat(L, lua_gettop(L) - arg);\n  }\n  lua_concat(L, lua_gettop(L) - arg);\n  return 1;\n}\n\n\nstatic const luaL_Reg dblib[] = {\n  {\"debug\", db_debug},\n  {\"getfenv\", db_getfenv},\n  {\"gethook\", db_gethook},\n  {\"getinfo\", db_getinfo},\n  {\"getlocal\", db_getlocal},\n  {\"getregistry\", db_getregistry},\n  {\"getmetatable\", db_getmetatable},\n  {\"getupvalue\", db_getupvalue},\n  {\"setfenv\", db_setfenv},\n  {\"sethook\", db_sethook},\n  {\"setlocal\", db_setlocal},\n  {\"setmetatable\", db_setmetatable},\n  {\"setupvalue\", db_setupvalue},\n  {\"traceback\", db_errorfb},\n  {NULL, NULL}\n};\n\n\nLUALIB_API int luaopen_debug (lua_State *L) {\n  luaL_register(L, LUA_DBLIBNAME, dblib);\n  return 1;\n}\n\n"
  },
  {
    "path": "extern/deprecated/redis-2.8.21/deps/lua/src/ldebug.c",
    "content": "/*\n** $Id: ldebug.c,v 2.29.1.6 2008/05/08 16:56:26 roberto Exp $\n** Debug Interface\n** See Copyright Notice in lua.h\n*/\n\n\n#include <stdarg.h>\n#include <stddef.h>\n#include <string.h>\n\n\n#define ldebug_c\n#define LUA_CORE\n\n#include \"lua.h\"\n\n#include \"lapi.h\"\n#include \"lcode.h\"\n#include \"ldebug.h\"\n#include \"ldo.h\"\n#include \"lfunc.h\"\n#include \"lobject.h\"\n#include \"lopcodes.h\"\n#include \"lstate.h\"\n#include \"lstring.h\"\n#include \"ltable.h\"\n#include \"ltm.h\"\n#include \"lvm.h\"\n\n\n\nstatic const char *getfuncname (lua_State *L, CallInfo *ci, const char **name);\n\n\nstatic int currentpc (lua_State *L, CallInfo *ci) {\n  if (!isLua(ci)) return -1;  /* function is not a Lua function? */\n  if (ci == L->ci)\n    ci->savedpc = L->savedpc;\n  return pcRel(ci->savedpc, ci_func(ci)->l.p);\n}\n\n\nstatic int currentline (lua_State *L, CallInfo *ci) {\n  int pc = currentpc(L, ci);\n  if (pc < 0)\n    return -1;  /* only active lua functions have current-line information */\n  else\n    return getline(ci_func(ci)->l.p, pc);\n}\n\n\n/*\n** this function can be called asynchronous (e.g. during a signal)\n*/\nLUA_API int lua_sethook (lua_State *L, lua_Hook func, int mask, int count) {\n  if (func == NULL || mask == 0) {  /* turn off hooks? */\n    mask = 0;\n    func = NULL;\n  }\n  L->hook = func;\n  L->basehookcount = count;\n  resethookcount(L);\n  L->hookmask = cast_byte(mask);\n  return 1;\n}\n\n\nLUA_API lua_Hook lua_gethook (lua_State *L) {\n  return L->hook;\n}\n\n\nLUA_API int lua_gethookmask (lua_State *L) {\n  return L->hookmask;\n}\n\n\nLUA_API int lua_gethookcount (lua_State *L) {\n  return L->basehookcount;\n}\n\n\nLUA_API int lua_getstack (lua_State *L, int level, lua_Debug *ar) {\n  int status;\n  CallInfo *ci;\n  lua_lock(L);\n  for (ci = L->ci; level > 0 && ci > L->base_ci; ci--) {\n    level--;\n    if (f_isLua(ci))  /* Lua function? */\n      level -= ci->tailcalls;  /* skip lost tail calls */\n  }\n  if (level == 0 && ci > L->base_ci) {  /* level found? */\n    status = 1;\n    ar->i_ci = cast_int(ci - L->base_ci);\n  }\n  else if (level < 0) {  /* level is of a lost tail call? */\n    status = 1;\n    ar->i_ci = 0;\n  }\n  else status = 0;  /* no such level */\n  lua_unlock(L);\n  return status;\n}\n\n\nstatic Proto *getluaproto (CallInfo *ci) {\n  return (isLua(ci) ? ci_func(ci)->l.p : NULL);\n}\n\n\nstatic const char *findlocal (lua_State *L, CallInfo *ci, int n) {\n  const char *name;\n  Proto *fp = getluaproto(ci);\n  if (fp && (name = luaF_getlocalname(fp, n, currentpc(L, ci))) != NULL)\n    return name;  /* is a local variable in a Lua function */\n  else {\n    StkId limit = (ci == L->ci) ? L->top : (ci+1)->func;\n    if (limit - ci->base >= n && n > 0)  /* is 'n' inside 'ci' stack? */\n      return \"(*temporary)\";\n    else\n      return NULL;\n  }\n}\n\n\nLUA_API const char *lua_getlocal (lua_State *L, const lua_Debug *ar, int n) {\n  CallInfo *ci = L->base_ci + ar->i_ci;\n  const char *name = findlocal(L, ci, n);\n  lua_lock(L);\n  if (name)\n      luaA_pushobject(L, ci->base + (n - 1));\n  lua_unlock(L);\n  return name;\n}\n\n\nLUA_API const char *lua_setlocal (lua_State *L, const lua_Debug *ar, int n) {\n  CallInfo *ci = L->base_ci + ar->i_ci;\n  const char *name = findlocal(L, ci, n);\n  lua_lock(L);\n  if (name)\n      setobjs2s(L, ci->base + (n - 1), L->top - 1);\n  L->top--;  /* pop value */\n  lua_unlock(L);\n  return name;\n}\n\n\nstatic void funcinfo (lua_Debug *ar, Closure *cl) {\n  if (cl->c.isC) {\n    ar->source = \"=[C]\";\n    ar->linedefined = -1;\n    ar->lastlinedefined = -1;\n    ar->what = \"C\";\n  }\n  else {\n    ar->source = getstr(cl->l.p->source);\n    ar->linedefined = cl->l.p->linedefined;\n    ar->lastlinedefined = cl->l.p->lastlinedefined;\n    ar->what = (ar->linedefined == 0) ? \"main\" : \"Lua\";\n  }\n  luaO_chunkid(ar->short_src, ar->source, LUA_IDSIZE);\n}\n\n\nstatic void info_tailcall (lua_Debug *ar) {\n  ar->name = ar->namewhat = \"\";\n  ar->what = \"tail\";\n  ar->lastlinedefined = ar->linedefined = ar->currentline = -1;\n  ar->source = \"=(tail call)\";\n  luaO_chunkid(ar->short_src, ar->source, LUA_IDSIZE);\n  ar->nups = 0;\n}\n\n\nstatic void collectvalidlines (lua_State *L, Closure *f) {\n  if (f == NULL || f->c.isC) {\n    setnilvalue(L->top);\n  }\n  else {\n    Table *t = luaH_new(L, 0, 0);\n    int *lineinfo = f->l.p->lineinfo;\n    int i;\n    for (i=0; i<f->l.p->sizelineinfo; i++)\n      setbvalue(luaH_setnum(L, t, lineinfo[i]), 1);\n    sethvalue(L, L->top, t); \n  }\n  incr_top(L);\n}\n\n\nstatic int auxgetinfo (lua_State *L, const char *what, lua_Debug *ar,\n                    Closure *f, CallInfo *ci) {\n  int status = 1;\n  if (f == NULL) {\n    info_tailcall(ar);\n    return status;\n  }\n  for (; *what; what++) {\n    switch (*what) {\n      case 'S': {\n        funcinfo(ar, f);\n        break;\n      }\n      case 'l': {\n        ar->currentline = (ci) ? currentline(L, ci) : -1;\n        break;\n      }\n      case 'u': {\n        ar->nups = f->c.nupvalues;\n        break;\n      }\n      case 'n': {\n        ar->namewhat = (ci) ? getfuncname(L, ci, &ar->name) : NULL;\n        if (ar->namewhat == NULL) {\n          ar->namewhat = \"\";  /* not found */\n          ar->name = NULL;\n        }\n        break;\n      }\n      case 'L':\n      case 'f':  /* handled by lua_getinfo */\n        break;\n      default: status = 0;  /* invalid option */\n    }\n  }\n  return status;\n}\n\n\nLUA_API int lua_getinfo (lua_State *L, const char *what, lua_Debug *ar) {\n  int status;\n  Closure *f = NULL;\n  CallInfo *ci = NULL;\n  lua_lock(L);\n  if (*what == '>') {\n    StkId func = L->top - 1;\n    luai_apicheck(L, ttisfunction(func));\n    what++;  /* skip the '>' */\n    f = clvalue(func);\n    L->top--;  /* pop function */\n  }\n  else if (ar->i_ci != 0) {  /* no tail call? */\n    ci = L->base_ci + ar->i_ci;\n    lua_assert(ttisfunction(ci->func));\n    f = clvalue(ci->func);\n  }\n  status = auxgetinfo(L, what, ar, f, ci);\n  if (strchr(what, 'f')) {\n    if (f == NULL) setnilvalue(L->top);\n    else setclvalue(L, L->top, f);\n    incr_top(L);\n  }\n  if (strchr(what, 'L'))\n    collectvalidlines(L, f);\n  lua_unlock(L);\n  return status;\n}\n\n\n/*\n** {======================================================\n** Symbolic Execution and code checker\n** =======================================================\n*/\n\n#define check(x)\t\tif (!(x)) return 0;\n\n#define checkjump(pt,pc)\tcheck(0 <= pc && pc < pt->sizecode)\n\n#define checkreg(pt,reg)\tcheck((reg) < (pt)->maxstacksize)\n\n\n\nstatic int precheck (const Proto *pt) {\n  check(pt->maxstacksize <= MAXSTACK);\n  check(pt->numparams+(pt->is_vararg & VARARG_HASARG) <= pt->maxstacksize);\n  check(!(pt->is_vararg & VARARG_NEEDSARG) ||\n              (pt->is_vararg & VARARG_HASARG));\n  check(pt->sizeupvalues <= pt->nups);\n  check(pt->sizelineinfo == pt->sizecode || pt->sizelineinfo == 0);\n  check(pt->sizecode > 0 && GET_OPCODE(pt->code[pt->sizecode-1]) == OP_RETURN);\n  return 1;\n}\n\n\n#define checkopenop(pt,pc)\tluaG_checkopenop((pt)->code[(pc)+1])\n\nint luaG_checkopenop (Instruction i) {\n  switch (GET_OPCODE(i)) {\n    case OP_CALL:\n    case OP_TAILCALL:\n    case OP_RETURN:\n    case OP_SETLIST: {\n      check(GETARG_B(i) == 0);\n      return 1;\n    }\n    default: return 0;  /* invalid instruction after an open call */\n  }\n}\n\n\nstatic int checkArgMode (const Proto *pt, int r, enum OpArgMask mode) {\n  switch (mode) {\n    case OpArgN: check(r == 0); break;\n    case OpArgU: break;\n    case OpArgR: checkreg(pt, r); break;\n    case OpArgK:\n      check(ISK(r) ? INDEXK(r) < pt->sizek : r < pt->maxstacksize);\n      break;\n  }\n  return 1;\n}\n\n\nstatic Instruction symbexec (const Proto *pt, int lastpc, int reg) {\n  int pc;\n  int last;  /* stores position of last instruction that changed `reg' */\n  last = pt->sizecode-1;  /* points to final return (a `neutral' instruction) */\n  check(precheck(pt));\n  for (pc = 0; pc < lastpc; pc++) {\n    Instruction i = pt->code[pc];\n    OpCode op = GET_OPCODE(i);\n    int a = GETARG_A(i);\n    int b = 0;\n    int c = 0;\n    check(op < NUM_OPCODES);\n    checkreg(pt, a);\n    switch (getOpMode(op)) {\n      case iABC: {\n        b = GETARG_B(i);\n        c = GETARG_C(i);\n        check(checkArgMode(pt, b, getBMode(op)));\n        check(checkArgMode(pt, c, getCMode(op)));\n        break;\n      }\n      case iABx: {\n        b = GETARG_Bx(i);\n        if (getBMode(op) == OpArgK) check(b < pt->sizek);\n        break;\n      }\n      case iAsBx: {\n        b = GETARG_sBx(i);\n        if (getBMode(op) == OpArgR) {\n          int dest = pc+1+b;\n          check(0 <= dest && dest < pt->sizecode);\n          if (dest > 0) {\n            int j;\n            /* check that it does not jump to a setlist count; this\n               is tricky, because the count from a previous setlist may\n               have the same value of an invalid setlist; so, we must\n               go all the way back to the first of them (if any) */\n            for (j = 0; j < dest; j++) {\n              Instruction d = pt->code[dest-1-j];\n              if (!(GET_OPCODE(d) == OP_SETLIST && GETARG_C(d) == 0)) break;\n            }\n            /* if 'j' is even, previous value is not a setlist (even if\n               it looks like one) */\n            check((j&1) == 0);\n          }\n        }\n        break;\n      }\n    }\n    if (testAMode(op)) {\n      if (a == reg) last = pc;  /* change register `a' */\n    }\n    if (testTMode(op)) {\n      check(pc+2 < pt->sizecode);  /* check skip */\n      check(GET_OPCODE(pt->code[pc+1]) == OP_JMP);\n    }\n    switch (op) {\n      case OP_LOADBOOL: {\n        if (c == 1) {  /* does it jump? */\n          check(pc+2 < pt->sizecode);  /* check its jump */\n          check(GET_OPCODE(pt->code[pc+1]) != OP_SETLIST ||\n                GETARG_C(pt->code[pc+1]) != 0);\n        }\n        break;\n      }\n      case OP_LOADNIL: {\n        if (a <= reg && reg <= b)\n          last = pc;  /* set registers from `a' to `b' */\n        break;\n      }\n      case OP_GETUPVAL:\n      case OP_SETUPVAL: {\n        check(b < pt->nups);\n        break;\n      }\n      case OP_GETGLOBAL:\n      case OP_SETGLOBAL: {\n        check(ttisstring(&pt->k[b]));\n        break;\n      }\n      case OP_SELF: {\n        checkreg(pt, a+1);\n        if (reg == a+1) last = pc;\n        break;\n      }\n      case OP_CONCAT: {\n        check(b < c);  /* at least two operands */\n        break;\n      }\n      case OP_TFORLOOP: {\n        check(c >= 1);  /* at least one result (control variable) */\n        checkreg(pt, a+2+c);  /* space for results */\n        if (reg >= a+2) last = pc;  /* affect all regs above its base */\n        break;\n      }\n      case OP_FORLOOP:\n      case OP_FORPREP:\n        checkreg(pt, a+3);\n        /* go through */\n      case OP_JMP: {\n        int dest = pc+1+b;\n        /* not full check and jump is forward and do not skip `lastpc'? */\n        if (reg != NO_REG && pc < dest && dest <= lastpc)\n          pc += b;  /* do the jump */\n        break;\n      }\n      case OP_CALL:\n      case OP_TAILCALL: {\n        if (b != 0) {\n          checkreg(pt, a+b-1);\n        }\n        c--;  /* c = num. returns */\n        if (c == LUA_MULTRET) {\n          check(checkopenop(pt, pc));\n        }\n        else if (c != 0)\n          checkreg(pt, a+c-1);\n        if (reg >= a) last = pc;  /* affect all registers above base */\n        break;\n      }\n      case OP_RETURN: {\n        b--;  /* b = num. returns */\n        if (b > 0) checkreg(pt, a+b-1);\n        break;\n      }\n      case OP_SETLIST: {\n        if (b > 0) checkreg(pt, a + b);\n        if (c == 0) {\n          pc++;\n          check(pc < pt->sizecode - 1);\n        }\n        break;\n      }\n      case OP_CLOSURE: {\n        int nup, j;\n        check(b < pt->sizep);\n        nup = pt->p[b]->nups;\n        check(pc + nup < pt->sizecode);\n        for (j = 1; j <= nup; j++) {\n          OpCode op1 = GET_OPCODE(pt->code[pc + j]);\n          check(op1 == OP_GETUPVAL || op1 == OP_MOVE);\n        }\n        if (reg != NO_REG)  /* tracing? */\n          pc += nup;  /* do not 'execute' these pseudo-instructions */\n        break;\n      }\n      case OP_VARARG: {\n        check((pt->is_vararg & VARARG_ISVARARG) &&\n             !(pt->is_vararg & VARARG_NEEDSARG));\n        b--;\n        if (b == LUA_MULTRET) check(checkopenop(pt, pc));\n        checkreg(pt, a+b-1);\n        break;\n      }\n      default: break;\n    }\n  }\n  return pt->code[last];\n}\n\n#undef check\n#undef checkjump\n#undef checkreg\n\n/* }====================================================== */\n\n\nint luaG_checkcode (const Proto *pt) {\n  return (symbexec(pt, pt->sizecode, NO_REG) != 0);\n}\n\n\nstatic const char *kname (Proto *p, int c) {\n  if (ISK(c) && ttisstring(&p->k[INDEXK(c)]))\n    return svalue(&p->k[INDEXK(c)]);\n  else\n    return \"?\";\n}\n\n\nstatic const char *getobjname (lua_State *L, CallInfo *ci, int stackpos,\n                               const char **name) {\n  if (isLua(ci)) {  /* a Lua function? */\n    Proto *p = ci_func(ci)->l.p;\n    int pc = currentpc(L, ci);\n    Instruction i;\n    *name = luaF_getlocalname(p, stackpos+1, pc);\n    if (*name)  /* is a local? */\n      return \"local\";\n    i = symbexec(p, pc, stackpos);  /* try symbolic execution */\n    lua_assert(pc != -1);\n    switch (GET_OPCODE(i)) {\n      case OP_GETGLOBAL: {\n        int g = GETARG_Bx(i);  /* global index */\n        lua_assert(ttisstring(&p->k[g]));\n        *name = svalue(&p->k[g]);\n        return \"global\";\n      }\n      case OP_MOVE: {\n        int a = GETARG_A(i);\n        int b = GETARG_B(i);  /* move from `b' to `a' */\n        if (b < a)\n          return getobjname(L, ci, b, name);  /* get name for `b' */\n        break;\n      }\n      case OP_GETTABLE: {\n        int k = GETARG_C(i);  /* key index */\n        *name = kname(p, k);\n        return \"field\";\n      }\n      case OP_GETUPVAL: {\n        int u = GETARG_B(i);  /* upvalue index */\n        *name = p->upvalues ? getstr(p->upvalues[u]) : \"?\";\n        return \"upvalue\";\n      }\n      case OP_SELF: {\n        int k = GETARG_C(i);  /* key index */\n        *name = kname(p, k);\n        return \"method\";\n      }\n      default: break;\n    }\n  }\n  return NULL;  /* no useful name found */\n}\n\n\nstatic const char *getfuncname (lua_State *L, CallInfo *ci, const char **name) {\n  Instruction i;\n  if ((isLua(ci) && ci->tailcalls > 0) || !isLua(ci - 1))\n    return NULL;  /* calling function is not Lua (or is unknown) */\n  ci--;  /* calling function */\n  i = ci_func(ci)->l.p->code[currentpc(L, ci)];\n  if (GET_OPCODE(i) == OP_CALL || GET_OPCODE(i) == OP_TAILCALL ||\n      GET_OPCODE(i) == OP_TFORLOOP)\n    return getobjname(L, ci, GETARG_A(i), name);\n  else\n    return NULL;  /* no useful name can be found */\n}\n\n\n/* only ANSI way to check whether a pointer points to an array */\nstatic int isinstack (CallInfo *ci, const TValue *o) {\n  StkId p;\n  for (p = ci->base; p < ci->top; p++)\n    if (o == p) return 1;\n  return 0;\n}\n\n\nvoid luaG_typeerror (lua_State *L, const TValue *o, const char *op) {\n  const char *name = NULL;\n  const char *t = luaT_typenames[ttype(o)];\n  const char *kind = (isinstack(L->ci, o)) ?\n                         getobjname(L, L->ci, cast_int(o - L->base), &name) :\n                         NULL;\n  if (kind)\n    luaG_runerror(L, \"attempt to %s %s \" LUA_QS \" (a %s value)\",\n                op, kind, name, t);\n  else\n    luaG_runerror(L, \"attempt to %s a %s value\", op, t);\n}\n\n\nvoid luaG_concaterror (lua_State *L, StkId p1, StkId p2) {\n  if (ttisstring(p1) || ttisnumber(p1)) p1 = p2;\n  lua_assert(!ttisstring(p1) && !ttisnumber(p1));\n  luaG_typeerror(L, p1, \"concatenate\");\n}\n\n\nvoid luaG_aritherror (lua_State *L, const TValue *p1, const TValue *p2) {\n  TValue temp;\n  if (luaV_tonumber(p1, &temp) == NULL)\n    p2 = p1;  /* first operand is wrong */\n  luaG_typeerror(L, p2, \"perform arithmetic on\");\n}\n\n\nint luaG_ordererror (lua_State *L, const TValue *p1, const TValue *p2) {\n  const char *t1 = luaT_typenames[ttype(p1)];\n  const char *t2 = luaT_typenames[ttype(p2)];\n  if (t1[2] == t2[2])\n    luaG_runerror(L, \"attempt to compare two %s values\", t1);\n  else\n    luaG_runerror(L, \"attempt to compare %s with %s\", t1, t2);\n  return 0;\n}\n\n\nstatic void addinfo (lua_State *L, const char *msg) {\n  CallInfo *ci = L->ci;\n  if (isLua(ci)) {  /* is Lua code? */\n    char buff[LUA_IDSIZE];  /* add file:line information */\n    int line = currentline(L, ci);\n    luaO_chunkid(buff, getstr(getluaproto(ci)->source), LUA_IDSIZE);\n    luaO_pushfstring(L, \"%s:%d: %s\", buff, line, msg);\n  }\n}\n\n\nvoid luaG_errormsg (lua_State *L) {\n  if (L->errfunc != 0) {  /* is there an error handling function? */\n    StkId errfunc = restorestack(L, L->errfunc);\n    if (!ttisfunction(errfunc)) luaD_throw(L, LUA_ERRERR);\n    setobjs2s(L, L->top, L->top - 1);  /* move argument */\n    setobjs2s(L, L->top - 1, errfunc);  /* push function */\n    incr_top(L);\n    luaD_call(L, L->top - 2, 1);  /* call it */\n  }\n  luaD_throw(L, LUA_ERRRUN);\n}\n\n\nvoid luaG_runerror (lua_State *L, const char *fmt, ...) {\n  va_list argp;\n  va_start(argp, fmt);\n  addinfo(L, luaO_pushvfstring(L, fmt, argp));\n  va_end(argp);\n  luaG_errormsg(L);\n}\n\n"
  },
  {
    "path": "extern/deprecated/redis-2.8.21/deps/lua/src/ldebug.h",
    "content": "/*\n** $Id: ldebug.h,v 2.3.1.1 2007/12/27 13:02:25 roberto Exp $\n** Auxiliary functions from Debug Interface module\n** See Copyright Notice in lua.h\n*/\n\n#ifndef ldebug_h\n#define ldebug_h\n\n\n#include \"lstate.h\"\n\n\n#define pcRel(pc, p)\t(cast(int, (pc) - (p)->code) - 1)\n\n#define getline(f,pc)\t(((f)->lineinfo) ? (f)->lineinfo[pc] : 0)\n\n#define resethookcount(L)\t(L->hookcount = L->basehookcount)\n\n\nLUAI_FUNC void luaG_typeerror (lua_State *L, const TValue *o,\n                                             const char *opname);\nLUAI_FUNC void luaG_concaterror (lua_State *L, StkId p1, StkId p2);\nLUAI_FUNC void luaG_aritherror (lua_State *L, const TValue *p1,\n                                              const TValue *p2);\nLUAI_FUNC int luaG_ordererror (lua_State *L, const TValue *p1,\n                                             const TValue *p2);\nLUAI_FUNC void luaG_runerror (lua_State *L, const char *fmt, ...);\nLUAI_FUNC void luaG_errormsg (lua_State *L);\nLUAI_FUNC int luaG_checkcode (const Proto *pt);\nLUAI_FUNC int luaG_checkopenop (Instruction i);\n\n#endif\n"
  },
  {
    "path": "extern/deprecated/redis-2.8.21/deps/lua/src/ldo.c",
    "content": "/*\n** $Id: ldo.c,v 2.38.1.4 2012/01/18 02:27:10 roberto Exp $\n** Stack and Call structure of Lua\n** See Copyright Notice in lua.h\n*/\n\n\n#include <setjmp.h>\n#include <stdlib.h>\n#include <string.h>\n\n#define ldo_c\n#define LUA_CORE\n\n#include \"lua.h\"\n\n#include \"ldebug.h\"\n#include \"ldo.h\"\n#include \"lfunc.h\"\n#include \"lgc.h\"\n#include \"lmem.h\"\n#include \"lobject.h\"\n#include \"lopcodes.h\"\n#include \"lparser.h\"\n#include \"lstate.h\"\n#include \"lstring.h\"\n#include \"ltable.h\"\n#include \"ltm.h\"\n#include \"lundump.h\"\n#include \"lvm.h\"\n#include \"lzio.h\"\n\n\n\n\n/*\n** {======================================================\n** Error-recovery functions\n** =======================================================\n*/\n\n\n/* chain list of long jump buffers */\nstruct lua_longjmp {\n  struct lua_longjmp *previous;\n  luai_jmpbuf b;\n  volatile int status;  /* error code */\n};\n\n\nvoid luaD_seterrorobj (lua_State *L, int errcode, StkId oldtop) {\n  switch (errcode) {\n    case LUA_ERRMEM: {\n      setsvalue2s(L, oldtop, luaS_newliteral(L, MEMERRMSG));\n      break;\n    }\n    case LUA_ERRERR: {\n      setsvalue2s(L, oldtop, luaS_newliteral(L, \"error in error handling\"));\n      break;\n    }\n    case LUA_ERRSYNTAX:\n    case LUA_ERRRUN: {\n      setobjs2s(L, oldtop, L->top - 1);  /* error message on current top */\n      break;\n    }\n  }\n  L->top = oldtop + 1;\n}\n\n\nstatic void restore_stack_limit (lua_State *L) {\n  lua_assert(L->stack_last - L->stack == L->stacksize - EXTRA_STACK - 1);\n  if (L->size_ci > LUAI_MAXCALLS) {  /* there was an overflow? */\n    int inuse = cast_int(L->ci - L->base_ci);\n    if (inuse + 1 < LUAI_MAXCALLS)  /* can `undo' overflow? */\n      luaD_reallocCI(L, LUAI_MAXCALLS);\n  }\n}\n\n\nstatic void resetstack (lua_State *L, int status) {\n  L->ci = L->base_ci;\n  L->base = L->ci->base;\n  luaF_close(L, L->base);  /* close eventual pending closures */\n  luaD_seterrorobj(L, status, L->base);\n  L->nCcalls = L->baseCcalls;\n  L->allowhook = 1;\n  restore_stack_limit(L);\n  L->errfunc = 0;\n  L->errorJmp = NULL;\n}\n\n\nvoid luaD_throw (lua_State *L, int errcode) {\n  if (L->errorJmp) {\n    L->errorJmp->status = errcode;\n    LUAI_THROW(L, L->errorJmp);\n  }\n  else {\n    L->status = cast_byte(errcode);\n    if (G(L)->panic) {\n      resetstack(L, errcode);\n      lua_unlock(L);\n      G(L)->panic(L);\n    }\n    exit(EXIT_FAILURE);\n  }\n}\n\n\nint luaD_rawrunprotected (lua_State *L, Pfunc f, void *ud) {\n  struct lua_longjmp lj;\n  lj.status = 0;\n  lj.previous = L->errorJmp;  /* chain new error handler */\n  L->errorJmp = &lj;\n  LUAI_TRY(L, &lj,\n    (*f)(L, ud);\n  );\n  L->errorJmp = lj.previous;  /* restore old error handler */\n  return lj.status;\n}\n\n/* }====================================================== */\n\n\nstatic void correctstack (lua_State *L, TValue *oldstack) {\n  CallInfo *ci;\n  GCObject *up;\n  L->top = (L->top - oldstack) + L->stack;\n  for (up = L->openupval; up != NULL; up = up->gch.next)\n    gco2uv(up)->v = (gco2uv(up)->v - oldstack) + L->stack;\n  for (ci = L->base_ci; ci <= L->ci; ci++) {\n    ci->top = (ci->top - oldstack) + L->stack;\n    ci->base = (ci->base - oldstack) + L->stack;\n    ci->func = (ci->func - oldstack) + L->stack;\n  }\n  L->base = (L->base - oldstack) + L->stack;\n}\n\n\nvoid luaD_reallocstack (lua_State *L, int newsize) {\n  TValue *oldstack = L->stack;\n  int realsize = newsize + 1 + EXTRA_STACK;\n  lua_assert(L->stack_last - L->stack == L->stacksize - EXTRA_STACK - 1);\n  luaM_reallocvector(L, L->stack, L->stacksize, realsize, TValue);\n  L->stacksize = realsize;\n  L->stack_last = L->stack+newsize;\n  correctstack(L, oldstack);\n}\n\n\nvoid luaD_reallocCI (lua_State *L, int newsize) {\n  CallInfo *oldci = L->base_ci;\n  luaM_reallocvector(L, L->base_ci, L->size_ci, newsize, CallInfo);\n  L->size_ci = newsize;\n  L->ci = (L->ci - oldci) + L->base_ci;\n  L->end_ci = L->base_ci + L->size_ci - 1;\n}\n\n\nvoid luaD_growstack (lua_State *L, int n) {\n  if (n <= L->stacksize)  /* double size is enough? */\n    luaD_reallocstack(L, 2*L->stacksize);\n  else\n    luaD_reallocstack(L, L->stacksize + n);\n}\n\n\nstatic CallInfo *growCI (lua_State *L) {\n  if (L->size_ci > LUAI_MAXCALLS)  /* overflow while handling overflow? */\n    luaD_throw(L, LUA_ERRERR);\n  else {\n    luaD_reallocCI(L, 2*L->size_ci);\n    if (L->size_ci > LUAI_MAXCALLS)\n      luaG_runerror(L, \"stack overflow\");\n  }\n  return ++L->ci;\n}\n\n\nvoid luaD_callhook (lua_State *L, int event, int line) {\n  lua_Hook hook = L->hook;\n  if (hook && L->allowhook) {\n    ptrdiff_t top = savestack(L, L->top);\n    ptrdiff_t ci_top = savestack(L, L->ci->top);\n    lua_Debug ar;\n    ar.event = event;\n    ar.currentline = line;\n    if (event == LUA_HOOKTAILRET)\n      ar.i_ci = 0;  /* tail call; no debug information about it */\n    else\n      ar.i_ci = cast_int(L->ci - L->base_ci);\n    luaD_checkstack(L, LUA_MINSTACK);  /* ensure minimum stack size */\n    L->ci->top = L->top + LUA_MINSTACK;\n    lua_assert(L->ci->top <= L->stack_last);\n    L->allowhook = 0;  /* cannot call hooks inside a hook */\n    lua_unlock(L);\n    (*hook)(L, &ar);\n    lua_lock(L);\n    lua_assert(!L->allowhook);\n    L->allowhook = 1;\n    L->ci->top = restorestack(L, ci_top);\n    L->top = restorestack(L, top);\n  }\n}\n\n\nstatic StkId adjust_varargs (lua_State *L, Proto *p, int actual) {\n  int i;\n  int nfixargs = p->numparams;\n  Table *htab = NULL;\n  StkId base, fixed;\n  for (; actual < nfixargs; ++actual)\n    setnilvalue(L->top++);\n#if defined(LUA_COMPAT_VARARG)\n  if (p->is_vararg & VARARG_NEEDSARG) { /* compat. with old-style vararg? */\n    int nvar = actual - nfixargs;  /* number of extra arguments */\n    lua_assert(p->is_vararg & VARARG_HASARG);\n    luaC_checkGC(L);\n    luaD_checkstack(L, p->maxstacksize);\n    htab = luaH_new(L, nvar, 1);  /* create `arg' table */\n    for (i=0; i<nvar; i++)  /* put extra arguments into `arg' table */\n      setobj2n(L, luaH_setnum(L, htab, i+1), L->top - nvar + i);\n    /* store counter in field `n' */\n    setnvalue(luaH_setstr(L, htab, luaS_newliteral(L, \"n\")), cast_num(nvar));\n  }\n#endif\n  /* move fixed parameters to final position */\n  fixed = L->top - actual;  /* first fixed argument */\n  base = L->top;  /* final position of first argument */\n  for (i=0; i<nfixargs; i++) {\n    setobjs2s(L, L->top++, fixed+i);\n    setnilvalue(fixed+i);\n  }\n  /* add `arg' parameter */\n  if (htab) {\n    sethvalue(L, L->top++, htab);\n    lua_assert(iswhite(obj2gco(htab)));\n  }\n  return base;\n}\n\n\nstatic StkId tryfuncTM (lua_State *L, StkId func) {\n  const TValue *tm = luaT_gettmbyobj(L, func, TM_CALL);\n  StkId p;\n  ptrdiff_t funcr = savestack(L, func);\n  if (!ttisfunction(tm))\n    luaG_typeerror(L, func, \"call\");\n  /* Open a hole inside the stack at `func' */\n  for (p = L->top; p > func; p--) setobjs2s(L, p, p-1);\n  incr_top(L);\n  func = restorestack(L, funcr);  /* previous call may change stack */\n  setobj2s(L, func, tm);  /* tag method is the new function to be called */\n  return func;\n}\n\n\n\n#define inc_ci(L) \\\n  ((L->ci == L->end_ci) ? growCI(L) : \\\n   (condhardstacktests(luaD_reallocCI(L, L->size_ci)), ++L->ci))\n\n\nint luaD_precall (lua_State *L, StkId func, int nresults) {\n  LClosure *cl;\n  ptrdiff_t funcr;\n  if (!ttisfunction(func)) /* `func' is not a function? */\n    func = tryfuncTM(L, func);  /* check the `function' tag method */\n  funcr = savestack(L, func);\n  cl = &clvalue(func)->l;\n  L->ci->savedpc = L->savedpc;\n  if (!cl->isC) {  /* Lua function? prepare its call */\n    CallInfo *ci;\n    StkId st, base;\n    Proto *p = cl->p;\n    luaD_checkstack(L, p->maxstacksize);\n    func = restorestack(L, funcr);\n    if (!p->is_vararg) {  /* no varargs? */\n      base = func + 1;\n      if (L->top > base + p->numparams)\n        L->top = base + p->numparams;\n    }\n    else {  /* vararg function */\n      int nargs = cast_int(L->top - func) - 1;\n      base = adjust_varargs(L, p, nargs);\n      func = restorestack(L, funcr);  /* previous call may change the stack */\n    }\n    ci = inc_ci(L);  /* now `enter' new function */\n    ci->func = func;\n    L->base = ci->base = base;\n    ci->top = L->base + p->maxstacksize;\n    lua_assert(ci->top <= L->stack_last);\n    L->savedpc = p->code;  /* starting point */\n    ci->tailcalls = 0;\n    ci->nresults = nresults;\n    for (st = L->top; st < ci->top; st++)\n      setnilvalue(st);\n    L->top = ci->top;\n    if (L->hookmask & LUA_MASKCALL) {\n      L->savedpc++;  /* hooks assume 'pc' is already incremented */\n      luaD_callhook(L, LUA_HOOKCALL, -1);\n      L->savedpc--;  /* correct 'pc' */\n    }\n    return PCRLUA;\n  }\n  else {  /* if is a C function, call it */\n    CallInfo *ci;\n    int n;\n    luaD_checkstack(L, LUA_MINSTACK);  /* ensure minimum stack size */\n    ci = inc_ci(L);  /* now `enter' new function */\n    ci->func = restorestack(L, funcr);\n    L->base = ci->base = ci->func + 1;\n    ci->top = L->top + LUA_MINSTACK;\n    lua_assert(ci->top <= L->stack_last);\n    ci->nresults = nresults;\n    if (L->hookmask & LUA_MASKCALL)\n      luaD_callhook(L, LUA_HOOKCALL, -1);\n    lua_unlock(L);\n    n = (*curr_func(L)->c.f)(L);  /* do the actual call */\n    lua_lock(L);\n    if (n < 0)  /* yielding? */\n      return PCRYIELD;\n    else {\n      luaD_poscall(L, L->top - n);\n      return PCRC;\n    }\n  }\n}\n\n\nstatic StkId callrethooks (lua_State *L, StkId firstResult) {\n  ptrdiff_t fr = savestack(L, firstResult);  /* next call may change stack */\n  luaD_callhook(L, LUA_HOOKRET, -1);\n  if (f_isLua(L->ci)) {  /* Lua function? */\n    while ((L->hookmask & LUA_MASKRET) && L->ci->tailcalls--) /* tail calls */\n      luaD_callhook(L, LUA_HOOKTAILRET, -1);\n  }\n  return restorestack(L, fr);\n}\n\n\nint luaD_poscall (lua_State *L, StkId firstResult) {\n  StkId res;\n  int wanted, i;\n  CallInfo *ci;\n  if (L->hookmask & LUA_MASKRET)\n    firstResult = callrethooks(L, firstResult);\n  ci = L->ci--;\n  res = ci->func;  /* res == final position of 1st result */\n  wanted = ci->nresults;\n  L->base = (ci - 1)->base;  /* restore base */\n  L->savedpc = (ci - 1)->savedpc;  /* restore savedpc */\n  /* move results to correct place */\n  for (i = wanted; i != 0 && firstResult < L->top; i--)\n    setobjs2s(L, res++, firstResult++);\n  while (i-- > 0)\n    setnilvalue(res++);\n  L->top = res;\n  return (wanted - LUA_MULTRET);  /* 0 iff wanted == LUA_MULTRET */\n}\n\n\n/*\n** Call a function (C or Lua). The function to be called is at *func.\n** The arguments are on the stack, right after the function.\n** When returns, all the results are on the stack, starting at the original\n** function position.\n*/ \nvoid luaD_call (lua_State *L, StkId func, int nResults) {\n  if (++L->nCcalls >= LUAI_MAXCCALLS) {\n    if (L->nCcalls == LUAI_MAXCCALLS)\n      luaG_runerror(L, \"C stack overflow\");\n    else if (L->nCcalls >= (LUAI_MAXCCALLS + (LUAI_MAXCCALLS>>3)))\n      luaD_throw(L, LUA_ERRERR);  /* error while handing stack error */\n  }\n  if (luaD_precall(L, func, nResults) == PCRLUA)  /* is a Lua function? */\n    luaV_execute(L, 1);  /* call it */\n  L->nCcalls--;\n  luaC_checkGC(L);\n}\n\n\nstatic void resume (lua_State *L, void *ud) {\n  StkId firstArg = cast(StkId, ud);\n  CallInfo *ci = L->ci;\n  if (L->status == 0) {  /* start coroutine? */\n    lua_assert(ci == L->base_ci && firstArg > L->base);\n    if (luaD_precall(L, firstArg - 1, LUA_MULTRET) != PCRLUA)\n      return;\n  }\n  else {  /* resuming from previous yield */\n    lua_assert(L->status == LUA_YIELD);\n    L->status = 0;\n    if (!f_isLua(ci)) {  /* `common' yield? */\n      /* finish interrupted execution of `OP_CALL' */\n      lua_assert(GET_OPCODE(*((ci-1)->savedpc - 1)) == OP_CALL ||\n                 GET_OPCODE(*((ci-1)->savedpc - 1)) == OP_TAILCALL);\n      if (luaD_poscall(L, firstArg))  /* complete it... */\n        L->top = L->ci->top;  /* and correct top if not multiple results */\n    }\n    else  /* yielded inside a hook: just continue its execution */\n      L->base = L->ci->base;\n  }\n  luaV_execute(L, cast_int(L->ci - L->base_ci));\n}\n\n\nstatic int resume_error (lua_State *L, const char *msg) {\n  L->top = L->ci->base;\n  setsvalue2s(L, L->top, luaS_new(L, msg));\n  incr_top(L);\n  lua_unlock(L);\n  return LUA_ERRRUN;\n}\n\n\nLUA_API int lua_resume (lua_State *L, int nargs) {\n  int status;\n  lua_lock(L);\n  if (L->status != LUA_YIELD && (L->status != 0 || L->ci != L->base_ci))\n      return resume_error(L, \"cannot resume non-suspended coroutine\");\n  if (L->nCcalls >= LUAI_MAXCCALLS)\n    return resume_error(L, \"C stack overflow\");\n  luai_userstateresume(L, nargs);\n  lua_assert(L->errfunc == 0);\n  L->baseCcalls = ++L->nCcalls;\n  status = luaD_rawrunprotected(L, resume, L->top - nargs);\n  if (status != 0) {  /* error? */\n    L->status = cast_byte(status);  /* mark thread as `dead' */\n    luaD_seterrorobj(L, status, L->top);\n    L->ci->top = L->top;\n  }\n  else {\n    lua_assert(L->nCcalls == L->baseCcalls);\n    status = L->status;\n  }\n  --L->nCcalls;\n  lua_unlock(L);\n  return status;\n}\n\n\nLUA_API int lua_yield (lua_State *L, int nresults) {\n  luai_userstateyield(L, nresults);\n  lua_lock(L);\n  if (L->nCcalls > L->baseCcalls)\n    luaG_runerror(L, \"attempt to yield across metamethod/C-call boundary\");\n  L->base = L->top - nresults;  /* protect stack slots below */\n  L->status = LUA_YIELD;\n  lua_unlock(L);\n  return -1;\n}\n\n\nint luaD_pcall (lua_State *L, Pfunc func, void *u,\n                ptrdiff_t old_top, ptrdiff_t ef) {\n  int status;\n  unsigned short oldnCcalls = L->nCcalls;\n  ptrdiff_t old_ci = saveci(L, L->ci);\n  lu_byte old_allowhooks = L->allowhook;\n  ptrdiff_t old_errfunc = L->errfunc;\n  L->errfunc = ef;\n  status = luaD_rawrunprotected(L, func, u);\n  if (status != 0) {  /* an error occurred? */\n    StkId oldtop = restorestack(L, old_top);\n    luaF_close(L, oldtop);  /* close eventual pending closures */\n    luaD_seterrorobj(L, status, oldtop);\n    L->nCcalls = oldnCcalls;\n    L->ci = restoreci(L, old_ci);\n    L->base = L->ci->base;\n    L->savedpc = L->ci->savedpc;\n    L->allowhook = old_allowhooks;\n    restore_stack_limit(L);\n  }\n  L->errfunc = old_errfunc;\n  return status;\n}\n\n\n\n/*\n** Execute a protected parser.\n*/\nstruct SParser {  /* data to `f_parser' */\n  ZIO *z;\n  Mbuffer buff;  /* buffer to be used by the scanner */\n  const char *name;\n};\n\nstatic void f_parser (lua_State *L, void *ud) {\n  int i;\n  Proto *tf;\n  Closure *cl;\n  struct SParser *p = cast(struct SParser *, ud);\n  int c = luaZ_lookahead(p->z);\n  luaC_checkGC(L);\n  tf = (luaY_parser)(L, p->z,\n                                                             &p->buff, p->name);\n  cl = luaF_newLclosure(L, tf->nups, hvalue(gt(L)));\n  cl->l.p = tf;\n  for (i = 0; i < tf->nups; i++)  /* initialize eventual upvalues */\n    cl->l.upvals[i] = luaF_newupval(L);\n  setclvalue(L, L->top, cl);\n  incr_top(L);\n}\n\n\nint luaD_protectedparser (lua_State *L, ZIO *z, const char *name) {\n  struct SParser p;\n  int status;\n  p.z = z; p.name = name;\n  luaZ_initbuffer(L, &p.buff);\n  status = luaD_pcall(L, f_parser, &p, savestack(L, L->top), L->errfunc);\n  luaZ_freebuffer(L, &p.buff);\n  return status;\n}\n\n\n"
  },
  {
    "path": "extern/deprecated/redis-2.8.21/deps/lua/src/ldo.h",
    "content": "/*\n** $Id: ldo.h,v 2.7.1.1 2007/12/27 13:02:25 roberto Exp $\n** Stack and Call structure of Lua\n** See Copyright Notice in lua.h\n*/\n\n#ifndef ldo_h\n#define ldo_h\n\n\n#include \"lobject.h\"\n#include \"lstate.h\"\n#include \"lzio.h\"\n\n\n#define luaD_checkstack(L,n)\t\\\n  if ((char *)L->stack_last - (char *)L->top <= (n)*(int)sizeof(TValue)) \\\n    luaD_growstack(L, n); \\\n  else condhardstacktests(luaD_reallocstack(L, L->stacksize - EXTRA_STACK - 1));\n\n\n#define incr_top(L) {luaD_checkstack(L,1); L->top++;}\n\n#define savestack(L,p)\t\t((char *)(p) - (char *)L->stack)\n#define restorestack(L,n)\t((TValue *)((char *)L->stack + (n)))\n\n#define saveci(L,p)\t\t((char *)(p) - (char *)L->base_ci)\n#define restoreci(L,n)\t\t((CallInfo *)((char *)L->base_ci + (n)))\n\n\n/* results from luaD_precall */\n#define PCRLUA\t\t0\t/* initiated a call to a Lua function */\n#define PCRC\t\t1\t/* did a call to a C function */\n#define PCRYIELD\t2\t/* C funtion yielded */\n\n\n/* type of protected functions, to be ran by `runprotected' */\ntypedef void (*Pfunc) (lua_State *L, void *ud);\n\nLUAI_FUNC int luaD_protectedparser (lua_State *L, ZIO *z, const char *name);\nLUAI_FUNC void luaD_callhook (lua_State *L, int event, int line);\nLUAI_FUNC int luaD_precall (lua_State *L, StkId func, int nresults);\nLUAI_FUNC void luaD_call (lua_State *L, StkId func, int nResults);\nLUAI_FUNC int luaD_pcall (lua_State *L, Pfunc func, void *u,\n                                        ptrdiff_t oldtop, ptrdiff_t ef);\nLUAI_FUNC int luaD_poscall (lua_State *L, StkId firstResult);\nLUAI_FUNC void luaD_reallocCI (lua_State *L, int newsize);\nLUAI_FUNC void luaD_reallocstack (lua_State *L, int newsize);\nLUAI_FUNC void luaD_growstack (lua_State *L, int n);\n\nLUAI_FUNC void luaD_throw (lua_State *L, int errcode);\nLUAI_FUNC int luaD_rawrunprotected (lua_State *L, Pfunc f, void *ud);\n\nLUAI_FUNC void luaD_seterrorobj (lua_State *L, int errcode, StkId oldtop);\n\n#endif\n\n"
  },
  {
    "path": "extern/deprecated/redis-2.8.21/deps/lua/src/ldump.c",
    "content": "/*\n** $Id: ldump.c,v 2.8.1.1 2007/12/27 13:02:25 roberto Exp $\n** save precompiled Lua chunks\n** See Copyright Notice in lua.h\n*/\n\n#include <stddef.h>\n\n#define ldump_c\n#define LUA_CORE\n\n#include \"lua.h\"\n\n#include \"lobject.h\"\n#include \"lstate.h\"\n#include \"lundump.h\"\n\ntypedef struct {\n lua_State* L;\n lua_Writer writer;\n void* data;\n int strip;\n int status;\n} DumpState;\n\n#define DumpMem(b,n,size,D)\tDumpBlock(b,(n)*(size),D)\n#define DumpVar(x,D)\t \tDumpMem(&x,1,sizeof(x),D)\n\nstatic void DumpBlock(const void* b, size_t size, DumpState* D)\n{\n if (D->status==0)\n {\n  lua_unlock(D->L);\n  D->status=(*D->writer)(D->L,b,size,D->data);\n  lua_lock(D->L);\n }\n}\n\nstatic void DumpChar(int y, DumpState* D)\n{\n char x=(char)y;\n DumpVar(x,D);\n}\n\nstatic void DumpInt(int x, DumpState* D)\n{\n DumpVar(x,D);\n}\n\nstatic void DumpNumber(lua_Number x, DumpState* D)\n{\n DumpVar(x,D);\n}\n\nstatic void DumpVector(const void* b, int n, size_t size, DumpState* D)\n{\n DumpInt(n,D);\n DumpMem(b,n,size,D);\n}\n\nstatic void DumpString(const TString* s, DumpState* D)\n{\n if (s==NULL || getstr(s)==NULL)\n {\n  size_t size=0;\n  DumpVar(size,D);\n }\n else\n {\n  size_t size=s->tsv.len+1;\t\t/* include trailing '\\0' */\n  DumpVar(size,D);\n  DumpBlock(getstr(s),size,D);\n }\n}\n\n#define DumpCode(f,D)\t DumpVector(f->code,f->sizecode,sizeof(Instruction),D)\n\nstatic void DumpFunction(const Proto* f, const TString* p, DumpState* D);\n\nstatic void DumpConstants(const Proto* f, DumpState* D)\n{\n int i,n=f->sizek;\n DumpInt(n,D);\n for (i=0; i<n; i++)\n {\n  const TValue* o=&f->k[i];\n  DumpChar(ttype(o),D);\n  switch (ttype(o))\n  {\n   case LUA_TNIL:\n\tbreak;\n   case LUA_TBOOLEAN:\n\tDumpChar(bvalue(o),D);\n\tbreak;\n   case LUA_TNUMBER:\n\tDumpNumber(nvalue(o),D);\n\tbreak;\n   case LUA_TSTRING:\n\tDumpString(rawtsvalue(o),D);\n\tbreak;\n   default:\n\tlua_assert(0);\t\t\t/* cannot happen */\n\tbreak;\n  }\n }\n n=f->sizep;\n DumpInt(n,D);\n for (i=0; i<n; i++) DumpFunction(f->p[i],f->source,D);\n}\n\nstatic void DumpDebug(const Proto* f, DumpState* D)\n{\n int i,n;\n n= (D->strip) ? 0 : f->sizelineinfo;\n DumpVector(f->lineinfo,n,sizeof(int),D);\n n= (D->strip) ? 0 : f->sizelocvars;\n DumpInt(n,D);\n for (i=0; i<n; i++)\n {\n  DumpString(f->locvars[i].varname,D);\n  DumpInt(f->locvars[i].startpc,D);\n  DumpInt(f->locvars[i].endpc,D);\n }\n n= (D->strip) ? 0 : f->sizeupvalues;\n DumpInt(n,D);\n for (i=0; i<n; i++) DumpString(f->upvalues[i],D);\n}\n\nstatic void DumpFunction(const Proto* f, const TString* p, DumpState* D)\n{\n DumpString((f->source==p || D->strip) ? NULL : f->source,D);\n DumpInt(f->linedefined,D);\n DumpInt(f->lastlinedefined,D);\n DumpChar(f->nups,D);\n DumpChar(f->numparams,D);\n DumpChar(f->is_vararg,D);\n DumpChar(f->maxstacksize,D);\n DumpCode(f,D);\n DumpConstants(f,D);\n DumpDebug(f,D);\n}\n\nstatic void DumpHeader(DumpState* D)\n{\n char h[LUAC_HEADERSIZE];\n luaU_header(h);\n DumpBlock(h,LUAC_HEADERSIZE,D);\n}\n\n/*\n** dump Lua function as precompiled chunk\n*/\nint luaU_dump (lua_State* L, const Proto* f, lua_Writer w, void* data, int strip)\n{\n DumpState D;\n D.L=L;\n D.writer=w;\n D.data=data;\n D.strip=strip;\n D.status=0;\n DumpHeader(&D);\n DumpFunction(f,NULL,&D);\n return D.status;\n}\n"
  },
  {
    "path": "extern/deprecated/redis-2.8.21/deps/lua/src/lfunc.c",
    "content": "/*\n** $Id: lfunc.c,v 2.12.1.2 2007/12/28 14:58:43 roberto Exp $\n** Auxiliary functions to manipulate prototypes and closures\n** See Copyright Notice in lua.h\n*/\n\n\n#include <stddef.h>\n\n#define lfunc_c\n#define LUA_CORE\n\n#include \"lua.h\"\n\n#include \"lfunc.h\"\n#include \"lgc.h\"\n#include \"lmem.h\"\n#include \"lobject.h\"\n#include \"lstate.h\"\n\n\n\nClosure *luaF_newCclosure (lua_State *L, int nelems, Table *e) {\n  Closure *c = cast(Closure *, luaM_malloc(L, sizeCclosure(nelems)));\n  luaC_link(L, obj2gco(c), LUA_TFUNCTION);\n  c->c.isC = 1;\n  c->c.env = e;\n  c->c.nupvalues = cast_byte(nelems);\n  return c;\n}\n\n\nClosure *luaF_newLclosure (lua_State *L, int nelems, Table *e) {\n  Closure *c = cast(Closure *, luaM_malloc(L, sizeLclosure(nelems)));\n  luaC_link(L, obj2gco(c), LUA_TFUNCTION);\n  c->l.isC = 0;\n  c->l.env = e;\n  c->l.nupvalues = cast_byte(nelems);\n  while (nelems--) c->l.upvals[nelems] = NULL;\n  return c;\n}\n\n\nUpVal *luaF_newupval (lua_State *L) {\n  UpVal *uv = luaM_new(L, UpVal);\n  luaC_link(L, obj2gco(uv), LUA_TUPVAL);\n  uv->v = &uv->u.value;\n  setnilvalue(uv->v);\n  return uv;\n}\n\n\nUpVal *luaF_findupval (lua_State *L, StkId level) {\n  global_State *g = G(L);\n  GCObject **pp = &L->openupval;\n  UpVal *p;\n  UpVal *uv;\n  while (*pp != NULL && (p = ngcotouv(*pp))->v >= level) {\n    lua_assert(p->v != &p->u.value);\n    if (p->v == level) {  /* found a corresponding upvalue? */\n      if (isdead(g, obj2gco(p)))  /* is it dead? */\n        changewhite(obj2gco(p));  /* ressurect it */\n      return p;\n    }\n    pp = &p->next;\n  }\n  uv = luaM_new(L, UpVal);  /* not found: create a new one */\n  uv->tt = LUA_TUPVAL;\n  uv->marked = luaC_white(g);\n  uv->v = level;  /* current value lives in the stack */\n  uv->next = *pp;  /* chain it in the proper position */\n  *pp = obj2gco(uv);\n  uv->u.l.prev = &g->uvhead;  /* double link it in `uvhead' list */\n  uv->u.l.next = g->uvhead.u.l.next;\n  uv->u.l.next->u.l.prev = uv;\n  g->uvhead.u.l.next = uv;\n  lua_assert(uv->u.l.next->u.l.prev == uv && uv->u.l.prev->u.l.next == uv);\n  return uv;\n}\n\n\nstatic void unlinkupval (UpVal *uv) {\n  lua_assert(uv->u.l.next->u.l.prev == uv && uv->u.l.prev->u.l.next == uv);\n  uv->u.l.next->u.l.prev = uv->u.l.prev;  /* remove from `uvhead' list */\n  uv->u.l.prev->u.l.next = uv->u.l.next;\n}\n\n\nvoid luaF_freeupval (lua_State *L, UpVal *uv) {\n  if (uv->v != &uv->u.value)  /* is it open? */\n    unlinkupval(uv);  /* remove from open list */\n  luaM_free(L, uv);  /* free upvalue */\n}\n\n\nvoid luaF_close (lua_State *L, StkId level) {\n  UpVal *uv;\n  global_State *g = G(L);\n  while (L->openupval != NULL && (uv = ngcotouv(L->openupval))->v >= level) {\n    GCObject *o = obj2gco(uv);\n    lua_assert(!isblack(o) && uv->v != &uv->u.value);\n    L->openupval = uv->next;  /* remove from `open' list */\n    if (isdead(g, o))\n      luaF_freeupval(L, uv);  /* free upvalue */\n    else {\n      unlinkupval(uv);\n      setobj(L, &uv->u.value, uv->v);\n      uv->v = &uv->u.value;  /* now current value lives here */\n      luaC_linkupval(L, uv);  /* link upvalue into `gcroot' list */\n    }\n  }\n}\n\n\nProto *luaF_newproto (lua_State *L) {\n  Proto *f = luaM_new(L, Proto);\n  luaC_link(L, obj2gco(f), LUA_TPROTO);\n  f->k = NULL;\n  f->sizek = 0;\n  f->p = NULL;\n  f->sizep = 0;\n  f->code = NULL;\n  f->sizecode = 0;\n  f->sizelineinfo = 0;\n  f->sizeupvalues = 0;\n  f->nups = 0;\n  f->upvalues = NULL;\n  f->numparams = 0;\n  f->is_vararg = 0;\n  f->maxstacksize = 0;\n  f->lineinfo = NULL;\n  f->sizelocvars = 0;\n  f->locvars = NULL;\n  f->linedefined = 0;\n  f->lastlinedefined = 0;\n  f->source = NULL;\n  return f;\n}\n\n\nvoid luaF_freeproto (lua_State *L, Proto *f) {\n  luaM_freearray(L, f->code, f->sizecode, Instruction);\n  luaM_freearray(L, f->p, f->sizep, Proto *);\n  luaM_freearray(L, f->k, f->sizek, TValue);\n  luaM_freearray(L, f->lineinfo, f->sizelineinfo, int);\n  luaM_freearray(L, f->locvars, f->sizelocvars, struct LocVar);\n  luaM_freearray(L, f->upvalues, f->sizeupvalues, TString *);\n  luaM_free(L, f);\n}\n\n\nvoid luaF_freeclosure (lua_State *L, Closure *c) {\n  int size = (c->c.isC) ? sizeCclosure(c->c.nupvalues) :\n                          sizeLclosure(c->l.nupvalues);\n  luaM_freemem(L, c, size);\n}\n\n\n/*\n** Look for n-th local variable at line `line' in function `func'.\n** Returns NULL if not found.\n*/\nconst char *luaF_getlocalname (const Proto *f, int local_number, int pc) {\n  int i;\n  for (i = 0; i<f->sizelocvars && f->locvars[i].startpc <= pc; i++) {\n    if (pc < f->locvars[i].endpc) {  /* is variable active? */\n      local_number--;\n      if (local_number == 0)\n        return getstr(f->locvars[i].varname);\n    }\n  }\n  return NULL;  /* not found */\n}\n\n"
  },
  {
    "path": "extern/deprecated/redis-2.8.21/deps/lua/src/lfunc.h",
    "content": "/*\n** $Id: lfunc.h,v 2.4.1.1 2007/12/27 13:02:25 roberto Exp $\n** Auxiliary functions to manipulate prototypes and closures\n** See Copyright Notice in lua.h\n*/\n\n#ifndef lfunc_h\n#define lfunc_h\n\n\n#include \"lobject.h\"\n\n\n#define sizeCclosure(n)\t(cast(int, sizeof(CClosure)) + \\\n                         cast(int, sizeof(TValue)*((n)-1)))\n\n#define sizeLclosure(n)\t(cast(int, sizeof(LClosure)) + \\\n                         cast(int, sizeof(TValue *)*((n)-1)))\n\n\nLUAI_FUNC Proto *luaF_newproto (lua_State *L);\nLUAI_FUNC Closure *luaF_newCclosure (lua_State *L, int nelems, Table *e);\nLUAI_FUNC Closure *luaF_newLclosure (lua_State *L, int nelems, Table *e);\nLUAI_FUNC UpVal *luaF_newupval (lua_State *L);\nLUAI_FUNC UpVal *luaF_findupval (lua_State *L, StkId level);\nLUAI_FUNC void luaF_close (lua_State *L, StkId level);\nLUAI_FUNC void luaF_freeproto (lua_State *L, Proto *f);\nLUAI_FUNC void luaF_freeclosure (lua_State *L, Closure *c);\nLUAI_FUNC void luaF_freeupval (lua_State *L, UpVal *uv);\nLUAI_FUNC const char *luaF_getlocalname (const Proto *func, int local_number,\n                                         int pc);\n\n\n#endif\n"
  },
  {
    "path": "extern/deprecated/redis-2.8.21/deps/lua/src/lgc.c",
    "content": "/*\n** $Id: lgc.c,v 2.38.1.2 2011/03/18 18:05:38 roberto Exp $\n** Garbage Collector\n** See Copyright Notice in lua.h\n*/\n\n#include <string.h>\n\n#define lgc_c\n#define LUA_CORE\n\n#include \"lua.h\"\n\n#include \"ldebug.h\"\n#include \"ldo.h\"\n#include \"lfunc.h\"\n#include \"lgc.h\"\n#include \"lmem.h\"\n#include \"lobject.h\"\n#include \"lstate.h\"\n#include \"lstring.h\"\n#include \"ltable.h\"\n#include \"ltm.h\"\n\n\n#define GCSTEPSIZE\t1024u\n#define GCSWEEPMAX\t40\n#define GCSWEEPCOST\t10\n#define GCFINALIZECOST\t100\n\n\n#define maskmarks\tcast_byte(~(bitmask(BLACKBIT)|WHITEBITS))\n\n#define makewhite(g,x)\t\\\n   ((x)->gch.marked = cast_byte(((x)->gch.marked & maskmarks) | luaC_white(g)))\n\n#define white2gray(x)\treset2bits((x)->gch.marked, WHITE0BIT, WHITE1BIT)\n#define black2gray(x)\tresetbit((x)->gch.marked, BLACKBIT)\n\n#define stringmark(s)\treset2bits((s)->tsv.marked, WHITE0BIT, WHITE1BIT)\n\n\n#define isfinalized(u)\t\ttestbit((u)->marked, FINALIZEDBIT)\n#define markfinalized(u)\tl_setbit((u)->marked, FINALIZEDBIT)\n\n\n#define KEYWEAK         bitmask(KEYWEAKBIT)\n#define VALUEWEAK       bitmask(VALUEWEAKBIT)\n\n\n\n#define markvalue(g,o) { checkconsistency(o); \\\n  if (iscollectable(o) && iswhite(gcvalue(o))) reallymarkobject(g,gcvalue(o)); }\n\n#define markobject(g,t) { if (iswhite(obj2gco(t))) \\\n\t\treallymarkobject(g, obj2gco(t)); }\n\n\n#define setthreshold(g)  (g->GCthreshold = (g->estimate/100) * g->gcpause)\n\n\nstatic void removeentry (Node *n) {\n  lua_assert(ttisnil(gval(n)));\n  if (iscollectable(gkey(n)))\n    setttype(gkey(n), LUA_TDEADKEY);  /* dead key; remove it */\n}\n\n\nstatic void reallymarkobject (global_State *g, GCObject *o) {\n  lua_assert(iswhite(o) && !isdead(g, o));\n  white2gray(o);\n  switch (o->gch.tt) {\n    case LUA_TSTRING: {\n      return;\n    }\n    case LUA_TUSERDATA: {\n      Table *mt = gco2u(o)->metatable;\n      gray2black(o);  /* udata are never gray */\n      if (mt) markobject(g, mt);\n      markobject(g, gco2u(o)->env);\n      return;\n    }\n    case LUA_TUPVAL: {\n      UpVal *uv = gco2uv(o);\n      markvalue(g, uv->v);\n      if (uv->v == &uv->u.value)  /* closed? */\n        gray2black(o);  /* open upvalues are never black */\n      return;\n    }\n    case LUA_TFUNCTION: {\n      gco2cl(o)->c.gclist = g->gray;\n      g->gray = o;\n      break;\n    }\n    case LUA_TTABLE: {\n      gco2h(o)->gclist = g->gray;\n      g->gray = o;\n      break;\n    }\n    case LUA_TTHREAD: {\n      gco2th(o)->gclist = g->gray;\n      g->gray = o;\n      break;\n    }\n    case LUA_TPROTO: {\n      gco2p(o)->gclist = g->gray;\n      g->gray = o;\n      break;\n    }\n    default: lua_assert(0);\n  }\n}\n\n\nstatic void marktmu (global_State *g) {\n  GCObject *u = g->tmudata;\n  if (u) {\n    do {\n      u = u->gch.next;\n      makewhite(g, u);  /* may be marked, if left from previous GC */\n      reallymarkobject(g, u);\n    } while (u != g->tmudata);\n  }\n}\n\n\n/* move `dead' udata that need finalization to list `tmudata' */\nsize_t luaC_separateudata (lua_State *L, int all) {\n  global_State *g = G(L);\n  size_t deadmem = 0;\n  GCObject **p = &g->mainthread->next;\n  GCObject *curr;\n  while ((curr = *p) != NULL) {\n    if (!(iswhite(curr) || all) || isfinalized(gco2u(curr)))\n      p = &curr->gch.next;  /* don't bother with them */\n    else if (fasttm(L, gco2u(curr)->metatable, TM_GC) == NULL) {\n      markfinalized(gco2u(curr));  /* don't need finalization */\n      p = &curr->gch.next;\n    }\n    else {  /* must call its gc method */\n      deadmem += sizeudata(gco2u(curr));\n      markfinalized(gco2u(curr));\n      *p = curr->gch.next;\n      /* link `curr' at the end of `tmudata' list */\n      if (g->tmudata == NULL)  /* list is empty? */\n        g->tmudata = curr->gch.next = curr;  /* creates a circular list */\n      else {\n        curr->gch.next = g->tmudata->gch.next;\n        g->tmudata->gch.next = curr;\n        g->tmudata = curr;\n      }\n    }\n  }\n  return deadmem;\n}\n\n\nstatic int traversetable (global_State *g, Table *h) {\n  int i;\n  int weakkey = 0;\n  int weakvalue = 0;\n  const TValue *mode;\n  if (h->metatable)\n    markobject(g, h->metatable);\n  mode = gfasttm(g, h->metatable, TM_MODE);\n  if (mode && ttisstring(mode)) {  /* is there a weak mode? */\n    weakkey = (strchr(svalue(mode), 'k') != NULL);\n    weakvalue = (strchr(svalue(mode), 'v') != NULL);\n    if (weakkey || weakvalue) {  /* is really weak? */\n      h->marked &= ~(KEYWEAK | VALUEWEAK);  /* clear bits */\n      h->marked |= cast_byte((weakkey << KEYWEAKBIT) |\n                             (weakvalue << VALUEWEAKBIT));\n      h->gclist = g->weak;  /* must be cleared after GC, ... */\n      g->weak = obj2gco(h);  /* ... so put in the appropriate list */\n    }\n  }\n  if (weakkey && weakvalue) return 1;\n  if (!weakvalue) {\n    i = h->sizearray;\n    while (i--)\n      markvalue(g, &h->array[i]);\n  }\n  i = sizenode(h);\n  while (i--) {\n    Node *n = gnode(h, i);\n    lua_assert(ttype(gkey(n)) != LUA_TDEADKEY || ttisnil(gval(n)));\n    if (ttisnil(gval(n)))\n      removeentry(n);  /* remove empty entries */\n    else {\n      lua_assert(!ttisnil(gkey(n)));\n      if (!weakkey) markvalue(g, gkey(n));\n      if (!weakvalue) markvalue(g, gval(n));\n    }\n  }\n  return weakkey || weakvalue;\n}\n\n\n/*\n** All marks are conditional because a GC may happen while the\n** prototype is still being created\n*/\nstatic void traverseproto (global_State *g, Proto *f) {\n  int i;\n  if (f->source) stringmark(f->source);\n  for (i=0; i<f->sizek; i++)  /* mark literals */\n    markvalue(g, &f->k[i]);\n  for (i=0; i<f->sizeupvalues; i++) {  /* mark upvalue names */\n    if (f->upvalues[i])\n      stringmark(f->upvalues[i]);\n  }\n  for (i=0; i<f->sizep; i++) {  /* mark nested protos */\n    if (f->p[i])\n      markobject(g, f->p[i]);\n  }\n  for (i=0; i<f->sizelocvars; i++) {  /* mark local-variable names */\n    if (f->locvars[i].varname)\n      stringmark(f->locvars[i].varname);\n  }\n}\n\n\n\nstatic void traverseclosure (global_State *g, Closure *cl) {\n  markobject(g, cl->c.env);\n  if (cl->c.isC) {\n    int i;\n    for (i=0; i<cl->c.nupvalues; i++)  /* mark its upvalues */\n      markvalue(g, &cl->c.upvalue[i]);\n  }\n  else {\n    int i;\n    lua_assert(cl->l.nupvalues == cl->l.p->nups);\n    markobject(g, cl->l.p);\n    for (i=0; i<cl->l.nupvalues; i++)  /* mark its upvalues */\n      markobject(g, cl->l.upvals[i]);\n  }\n}\n\n\nstatic void checkstacksizes (lua_State *L, StkId max) {\n  int ci_used = cast_int(L->ci - L->base_ci);  /* number of `ci' in use */\n  int s_used = cast_int(max - L->stack);  /* part of stack in use */\n  if (L->size_ci > LUAI_MAXCALLS)  /* handling overflow? */\n    return;  /* do not touch the stacks */\n  if (4*ci_used < L->size_ci && 2*BASIC_CI_SIZE < L->size_ci)\n    luaD_reallocCI(L, L->size_ci/2);  /* still big enough... */\n  condhardstacktests(luaD_reallocCI(L, ci_used + 1));\n  if (4*s_used < L->stacksize &&\n      2*(BASIC_STACK_SIZE+EXTRA_STACK) < L->stacksize)\n    luaD_reallocstack(L, L->stacksize/2);  /* still big enough... */\n  condhardstacktests(luaD_reallocstack(L, s_used));\n}\n\n\nstatic void traversestack (global_State *g, lua_State *l) {\n  StkId o, lim;\n  CallInfo *ci;\n  markvalue(g, gt(l));\n  lim = l->top;\n  for (ci = l->base_ci; ci <= l->ci; ci++) {\n    lua_assert(ci->top <= l->stack_last);\n    if (lim < ci->top) lim = ci->top;\n  }\n  for (o = l->stack; o < l->top; o++)\n    markvalue(g, o);\n  for (; o <= lim; o++)\n    setnilvalue(o);\n  checkstacksizes(l, lim);\n}\n\n\n/*\n** traverse one gray object, turning it to black.\n** Returns `quantity' traversed.\n*/\nstatic l_mem propagatemark (global_State *g) {\n  GCObject *o = g->gray;\n  lua_assert(isgray(o));\n  gray2black(o);\n  switch (o->gch.tt) {\n    case LUA_TTABLE: {\n      Table *h = gco2h(o);\n      g->gray = h->gclist;\n      if (traversetable(g, h))  /* table is weak? */\n        black2gray(o);  /* keep it gray */\n      return sizeof(Table) + sizeof(TValue) * h->sizearray +\n                             sizeof(Node) * sizenode(h);\n    }\n    case LUA_TFUNCTION: {\n      Closure *cl = gco2cl(o);\n      g->gray = cl->c.gclist;\n      traverseclosure(g, cl);\n      return (cl->c.isC) ? sizeCclosure(cl->c.nupvalues) :\n                           sizeLclosure(cl->l.nupvalues);\n    }\n    case LUA_TTHREAD: {\n      lua_State *th = gco2th(o);\n      g->gray = th->gclist;\n      th->gclist = g->grayagain;\n      g->grayagain = o;\n      black2gray(o);\n      traversestack(g, th);\n      return sizeof(lua_State) + sizeof(TValue) * th->stacksize +\n                                 sizeof(CallInfo) * th->size_ci;\n    }\n    case LUA_TPROTO: {\n      Proto *p = gco2p(o);\n      g->gray = p->gclist;\n      traverseproto(g, p);\n      return sizeof(Proto) + sizeof(Instruction) * p->sizecode +\n                             sizeof(Proto *) * p->sizep +\n                             sizeof(TValue) * p->sizek + \n                             sizeof(int) * p->sizelineinfo +\n                             sizeof(LocVar) * p->sizelocvars +\n                             sizeof(TString *) * p->sizeupvalues;\n    }\n    default: lua_assert(0); return 0;\n  }\n}\n\n\nstatic size_t propagateall (global_State *g) {\n  size_t m = 0;\n  while (g->gray) m += propagatemark(g);\n  return m;\n}\n\n\n/*\n** The next function tells whether a key or value can be cleared from\n** a weak table. Non-collectable objects are never removed from weak\n** tables. Strings behave as `values', so are never removed too. for\n** other objects: if really collected, cannot keep them; for userdata\n** being finalized, keep them in keys, but not in values\n*/\nstatic int iscleared (const TValue *o, int iskey) {\n  if (!iscollectable(o)) return 0;\n  if (ttisstring(o)) {\n    stringmark(rawtsvalue(o));  /* strings are `values', so are never weak */\n    return 0;\n  }\n  return iswhite(gcvalue(o)) ||\n    (ttisuserdata(o) && (!iskey && isfinalized(uvalue(o))));\n}\n\n\n/*\n** clear collected entries from weaktables\n*/\nstatic void cleartable (GCObject *l) {\n  while (l) {\n    Table *h = gco2h(l);\n    int i = h->sizearray;\n    lua_assert(testbit(h->marked, VALUEWEAKBIT) ||\n               testbit(h->marked, KEYWEAKBIT));\n    if (testbit(h->marked, VALUEWEAKBIT)) {\n      while (i--) {\n        TValue *o = &h->array[i];\n        if (iscleared(o, 0))  /* value was collected? */\n          setnilvalue(o);  /* remove value */\n      }\n    }\n    i = sizenode(h);\n    while (i--) {\n      Node *n = gnode(h, i);\n      if (!ttisnil(gval(n)) &&  /* non-empty entry? */\n          (iscleared(key2tval(n), 1) || iscleared(gval(n), 0))) {\n        setnilvalue(gval(n));  /* remove value ... */\n        removeentry(n);  /* remove entry from table */\n      }\n    }\n    l = h->gclist;\n  }\n}\n\n\nstatic void freeobj (lua_State *L, GCObject *o) {\n  switch (o->gch.tt) {\n    case LUA_TPROTO: luaF_freeproto(L, gco2p(o)); break;\n    case LUA_TFUNCTION: luaF_freeclosure(L, gco2cl(o)); break;\n    case LUA_TUPVAL: luaF_freeupval(L, gco2uv(o)); break;\n    case LUA_TTABLE: luaH_free(L, gco2h(o)); break;\n    case LUA_TTHREAD: {\n      lua_assert(gco2th(o) != L && gco2th(o) != G(L)->mainthread);\n      luaE_freethread(L, gco2th(o));\n      break;\n    }\n    case LUA_TSTRING: {\n      G(L)->strt.nuse--;\n      luaM_freemem(L, o, sizestring(gco2ts(o)));\n      break;\n    }\n    case LUA_TUSERDATA: {\n      luaM_freemem(L, o, sizeudata(gco2u(o)));\n      break;\n    }\n    default: lua_assert(0);\n  }\n}\n\n\n\n#define sweepwholelist(L,p)\tsweeplist(L,p,MAX_LUMEM)\n\n\nstatic GCObject **sweeplist (lua_State *L, GCObject **p, lu_mem count) {\n  GCObject *curr;\n  global_State *g = G(L);\n  int deadmask = otherwhite(g);\n  while ((curr = *p) != NULL && count-- > 0) {\n    if (curr->gch.tt == LUA_TTHREAD)  /* sweep open upvalues of each thread */\n      sweepwholelist(L, &gco2th(curr)->openupval);\n    if ((curr->gch.marked ^ WHITEBITS) & deadmask) {  /* not dead? */\n      lua_assert(!isdead(g, curr) || testbit(curr->gch.marked, FIXEDBIT));\n      makewhite(g, curr);  /* make it white (for next cycle) */\n      p = &curr->gch.next;\n    }\n    else {  /* must erase `curr' */\n      lua_assert(isdead(g, curr) || deadmask == bitmask(SFIXEDBIT));\n      *p = curr->gch.next;\n      if (curr == g->rootgc)  /* is the first element of the list? */\n        g->rootgc = curr->gch.next;  /* adjust first */\n      freeobj(L, curr);\n    }\n  }\n  return p;\n}\n\n\nstatic void checkSizes (lua_State *L) {\n  global_State *g = G(L);\n  /* check size of string hash */\n  if (g->strt.nuse < cast(lu_int32, g->strt.size/4) &&\n      g->strt.size > MINSTRTABSIZE*2)\n    luaS_resize(L, g->strt.size/2);  /* table is too big */\n  /* check size of buffer */\n  if (luaZ_sizebuffer(&g->buff) > LUA_MINBUFFER*2) {  /* buffer too big? */\n    size_t newsize = luaZ_sizebuffer(&g->buff) / 2;\n    luaZ_resizebuffer(L, &g->buff, newsize);\n  }\n}\n\n\nstatic void GCTM (lua_State *L) {\n  global_State *g = G(L);\n  GCObject *o = g->tmudata->gch.next;  /* get first element */\n  Udata *udata = rawgco2u(o);\n  const TValue *tm;\n  /* remove udata from `tmudata' */\n  if (o == g->tmudata)  /* last element? */\n    g->tmudata = NULL;\n  else\n    g->tmudata->gch.next = udata->uv.next;\n  udata->uv.next = g->mainthread->next;  /* return it to `root' list */\n  g->mainthread->next = o;\n  makewhite(g, o);\n  tm = fasttm(L, udata->uv.metatable, TM_GC);\n  if (tm != NULL) {\n    lu_byte oldah = L->allowhook;\n    lu_mem oldt = g->GCthreshold;\n    L->allowhook = 0;  /* stop debug hooks during GC tag method */\n    g->GCthreshold = 2*g->totalbytes;  /* avoid GC steps */\n    setobj2s(L, L->top, tm);\n    setuvalue(L, L->top+1, udata);\n    L->top += 2;\n    luaD_call(L, L->top - 2, 0);\n    L->allowhook = oldah;  /* restore hooks */\n    g->GCthreshold = oldt;  /* restore threshold */\n  }\n}\n\n\n/*\n** Call all GC tag methods\n*/\nvoid luaC_callGCTM (lua_State *L) {\n  while (G(L)->tmudata)\n    GCTM(L);\n}\n\n\nvoid luaC_freeall (lua_State *L) {\n  global_State *g = G(L);\n  int i;\n  g->currentwhite = WHITEBITS | bitmask(SFIXEDBIT);  /* mask to collect all elements */\n  sweepwholelist(L, &g->rootgc);\n  for (i = 0; i < g->strt.size; i++)  /* free all string lists */\n    sweepwholelist(L, &g->strt.hash[i]);\n}\n\n\nstatic void markmt (global_State *g) {\n  int i;\n  for (i=0; i<NUM_TAGS; i++)\n    if (g->mt[i]) markobject(g, g->mt[i]);\n}\n\n\n/* mark root set */\nstatic void markroot (lua_State *L) {\n  global_State *g = G(L);\n  g->gray = NULL;\n  g->grayagain = NULL;\n  g->weak = NULL;\n  markobject(g, g->mainthread);\n  /* make global table be traversed before main stack */\n  markvalue(g, gt(g->mainthread));\n  markvalue(g, registry(L));\n  markmt(g);\n  g->gcstate = GCSpropagate;\n}\n\n\nstatic void remarkupvals (global_State *g) {\n  UpVal *uv;\n  for (uv = g->uvhead.u.l.next; uv != &g->uvhead; uv = uv->u.l.next) {\n    lua_assert(uv->u.l.next->u.l.prev == uv && uv->u.l.prev->u.l.next == uv);\n    if (isgray(obj2gco(uv)))\n      markvalue(g, uv->v);\n  }\n}\n\n\nstatic void atomic (lua_State *L) {\n  global_State *g = G(L);\n  size_t udsize;  /* total size of userdata to be finalized */\n  /* remark occasional upvalues of (maybe) dead threads */\n  remarkupvals(g);\n  /* traverse objects cautch by write barrier and by 'remarkupvals' */\n  propagateall(g);\n  /* remark weak tables */\n  g->gray = g->weak;\n  g->weak = NULL;\n  lua_assert(!iswhite(obj2gco(g->mainthread)));\n  markobject(g, L);  /* mark running thread */\n  markmt(g);  /* mark basic metatables (again) */\n  propagateall(g);\n  /* remark gray again */\n  g->gray = g->grayagain;\n  g->grayagain = NULL;\n  propagateall(g);\n  udsize = luaC_separateudata(L, 0);  /* separate userdata to be finalized */\n  marktmu(g);  /* mark `preserved' userdata */\n  udsize += propagateall(g);  /* remark, to propagate `preserveness' */\n  cleartable(g->weak);  /* remove collected objects from weak tables */\n  /* flip current white */\n  g->currentwhite = cast_byte(otherwhite(g));\n  g->sweepstrgc = 0;\n  g->sweepgc = &g->rootgc;\n  g->gcstate = GCSsweepstring;\n  g->estimate = g->totalbytes - udsize;  /* first estimate */\n}\n\n\nstatic l_mem singlestep (lua_State *L) {\n  global_State *g = G(L);\n  /*lua_checkmemory(L);*/\n  switch (g->gcstate) {\n    case GCSpause: {\n      markroot(L);  /* start a new collection */\n      return 0;\n    }\n    case GCSpropagate: {\n      if (g->gray)\n        return propagatemark(g);\n      else {  /* no more `gray' objects */\n        atomic(L);  /* finish mark phase */\n        return 0;\n      }\n    }\n    case GCSsweepstring: {\n      lu_mem old = g->totalbytes;\n      sweepwholelist(L, &g->strt.hash[g->sweepstrgc++]);\n      if (g->sweepstrgc >= g->strt.size)  /* nothing more to sweep? */\n        g->gcstate = GCSsweep;  /* end sweep-string phase */\n      lua_assert(old >= g->totalbytes);\n      g->estimate -= old - g->totalbytes;\n      return GCSWEEPCOST;\n    }\n    case GCSsweep: {\n      lu_mem old = g->totalbytes;\n      g->sweepgc = sweeplist(L, g->sweepgc, GCSWEEPMAX);\n      if (*g->sweepgc == NULL) {  /* nothing more to sweep? */\n        checkSizes(L);\n        g->gcstate = GCSfinalize;  /* end sweep phase */\n      }\n      lua_assert(old >= g->totalbytes);\n      g->estimate -= old - g->totalbytes;\n      return GCSWEEPMAX*GCSWEEPCOST;\n    }\n    case GCSfinalize: {\n      if (g->tmudata) {\n        GCTM(L);\n        if (g->estimate > GCFINALIZECOST)\n          g->estimate -= GCFINALIZECOST;\n        return GCFINALIZECOST;\n      }\n      else {\n        g->gcstate = GCSpause;  /* end collection */\n        g->gcdept = 0;\n        return 0;\n      }\n    }\n    default: lua_assert(0); return 0;\n  }\n}\n\n\nvoid luaC_step (lua_State *L) {\n  global_State *g = G(L);\n  l_mem lim = (GCSTEPSIZE/100) * g->gcstepmul;\n  if (lim == 0)\n    lim = (MAX_LUMEM-1)/2;  /* no limit */\n  g->gcdept += g->totalbytes - g->GCthreshold;\n  do {\n    lim -= singlestep(L);\n    if (g->gcstate == GCSpause)\n      break;\n  } while (lim > 0);\n  if (g->gcstate != GCSpause) {\n    if (g->gcdept < GCSTEPSIZE)\n      g->GCthreshold = g->totalbytes + GCSTEPSIZE;  /* - lim/g->gcstepmul;*/\n    else {\n      g->gcdept -= GCSTEPSIZE;\n      g->GCthreshold = g->totalbytes;\n    }\n  }\n  else {\n    setthreshold(g);\n  }\n}\n\n\nvoid luaC_fullgc (lua_State *L) {\n  global_State *g = G(L);\n  if (g->gcstate <= GCSpropagate) {\n    /* reset sweep marks to sweep all elements (returning them to white) */\n    g->sweepstrgc = 0;\n    g->sweepgc = &g->rootgc;\n    /* reset other collector lists */\n    g->gray = NULL;\n    g->grayagain = NULL;\n    g->weak = NULL;\n    g->gcstate = GCSsweepstring;\n  }\n  lua_assert(g->gcstate != GCSpause && g->gcstate != GCSpropagate);\n  /* finish any pending sweep phase */\n  while (g->gcstate != GCSfinalize) {\n    lua_assert(g->gcstate == GCSsweepstring || g->gcstate == GCSsweep);\n    singlestep(L);\n  }\n  markroot(L);\n  while (g->gcstate != GCSpause) {\n    singlestep(L);\n  }\n  setthreshold(g);\n}\n\n\nvoid luaC_barrierf (lua_State *L, GCObject *o, GCObject *v) {\n  global_State *g = G(L);\n  lua_assert(isblack(o) && iswhite(v) && !isdead(g, v) && !isdead(g, o));\n  lua_assert(g->gcstate != GCSfinalize && g->gcstate != GCSpause);\n  lua_assert(ttype(&o->gch) != LUA_TTABLE);\n  /* must keep invariant? */\n  if (g->gcstate == GCSpropagate)\n    reallymarkobject(g, v);  /* restore invariant */\n  else  /* don't mind */\n    makewhite(g, o);  /* mark as white just to avoid other barriers */\n}\n\n\nvoid luaC_barrierback (lua_State *L, Table *t) {\n  global_State *g = G(L);\n  GCObject *o = obj2gco(t);\n  lua_assert(isblack(o) && !isdead(g, o));\n  lua_assert(g->gcstate != GCSfinalize && g->gcstate != GCSpause);\n  black2gray(o);  /* make table gray (again) */\n  t->gclist = g->grayagain;\n  g->grayagain = o;\n}\n\n\nvoid luaC_link (lua_State *L, GCObject *o, lu_byte tt) {\n  global_State *g = G(L);\n  o->gch.next = g->rootgc;\n  g->rootgc = o;\n  o->gch.marked = luaC_white(g);\n  o->gch.tt = tt;\n}\n\n\nvoid luaC_linkupval (lua_State *L, UpVal *uv) {\n  global_State *g = G(L);\n  GCObject *o = obj2gco(uv);\n  o->gch.next = g->rootgc;  /* link upvalue into `rootgc' list */\n  g->rootgc = o;\n  if (isgray(o)) { \n    if (g->gcstate == GCSpropagate) {\n      gray2black(o);  /* closed upvalues need barrier */\n      luaC_barrier(L, uv, uv->v);\n    }\n    else {  /* sweep phase: sweep it (turning it into white) */\n      makewhite(g, o);\n      lua_assert(g->gcstate != GCSfinalize && g->gcstate != GCSpause);\n    }\n  }\n}\n\n"
  },
  {
    "path": "extern/deprecated/redis-2.8.21/deps/lua/src/lgc.h",
    "content": "/*\n** $Id: lgc.h,v 2.15.1.1 2007/12/27 13:02:25 roberto Exp $\n** Garbage Collector\n** See Copyright Notice in lua.h\n*/\n\n#ifndef lgc_h\n#define lgc_h\n\n\n#include \"lobject.h\"\n\n\n/*\n** Possible states of the Garbage Collector\n*/\n#define GCSpause\t0\n#define GCSpropagate\t1\n#define GCSsweepstring\t2\n#define GCSsweep\t3\n#define GCSfinalize\t4\n\n\n/*\n** some userful bit tricks\n*/\n#define resetbits(x,m)\t((x) &= cast(lu_byte, ~(m)))\n#define setbits(x,m)\t((x) |= (m))\n#define testbits(x,m)\t((x) & (m))\n#define bitmask(b)\t(1<<(b))\n#define bit2mask(b1,b2)\t(bitmask(b1) | bitmask(b2))\n#define l_setbit(x,b)\tsetbits(x, bitmask(b))\n#define resetbit(x,b)\tresetbits(x, bitmask(b))\n#define testbit(x,b)\ttestbits(x, bitmask(b))\n#define set2bits(x,b1,b2)\tsetbits(x, (bit2mask(b1, b2)))\n#define reset2bits(x,b1,b2)\tresetbits(x, (bit2mask(b1, b2)))\n#define test2bits(x,b1,b2)\ttestbits(x, (bit2mask(b1, b2)))\n\n\n\n/*\n** Layout for bit use in `marked' field:\n** bit 0 - object is white (type 0)\n** bit 1 - object is white (type 1)\n** bit 2 - object is black\n** bit 3 - for userdata: has been finalized\n** bit 3 - for tables: has weak keys\n** bit 4 - for tables: has weak values\n** bit 5 - object is fixed (should not be collected)\n** bit 6 - object is \"super\" fixed (only the main thread)\n*/\n\n\n#define WHITE0BIT\t0\n#define WHITE1BIT\t1\n#define BLACKBIT\t2\n#define FINALIZEDBIT\t3\n#define KEYWEAKBIT\t3\n#define VALUEWEAKBIT\t4\n#define FIXEDBIT\t5\n#define SFIXEDBIT\t6\n#define WHITEBITS\tbit2mask(WHITE0BIT, WHITE1BIT)\n\n\n#define iswhite(x)      test2bits((x)->gch.marked, WHITE0BIT, WHITE1BIT)\n#define isblack(x)      testbit((x)->gch.marked, BLACKBIT)\n#define isgray(x)\t(!isblack(x) && !iswhite(x))\n\n#define otherwhite(g)\t(g->currentwhite ^ WHITEBITS)\n#define isdead(g,v)\t((v)->gch.marked & otherwhite(g) & WHITEBITS)\n\n#define changewhite(x)\t((x)->gch.marked ^= WHITEBITS)\n#define gray2black(x)\tl_setbit((x)->gch.marked, BLACKBIT)\n\n#define valiswhite(x)\t(iscollectable(x) && iswhite(gcvalue(x)))\n\n#define luaC_white(g)\tcast(lu_byte, (g)->currentwhite & WHITEBITS)\n\n\n#define luaC_checkGC(L) { \\\n  condhardstacktests(luaD_reallocstack(L, L->stacksize - EXTRA_STACK - 1)); \\\n  if (G(L)->totalbytes >= G(L)->GCthreshold) \\\n\tluaC_step(L); }\n\n\n#define luaC_barrier(L,p,v) { if (valiswhite(v) && isblack(obj2gco(p)))  \\\n\tluaC_barrierf(L,obj2gco(p),gcvalue(v)); }\n\n#define luaC_barriert(L,t,v) { if (valiswhite(v) && isblack(obj2gco(t)))  \\\n\tluaC_barrierback(L,t); }\n\n#define luaC_objbarrier(L,p,o)  \\\n\t{ if (iswhite(obj2gco(o)) && isblack(obj2gco(p))) \\\n\t\tluaC_barrierf(L,obj2gco(p),obj2gco(o)); }\n\n#define luaC_objbarriert(L,t,o)  \\\n   { if (iswhite(obj2gco(o)) && isblack(obj2gco(t))) luaC_barrierback(L,t); }\n\nLUAI_FUNC size_t luaC_separateudata (lua_State *L, int all);\nLUAI_FUNC void luaC_callGCTM (lua_State *L);\nLUAI_FUNC void luaC_freeall (lua_State *L);\nLUAI_FUNC void luaC_step (lua_State *L);\nLUAI_FUNC void luaC_fullgc (lua_State *L);\nLUAI_FUNC void luaC_link (lua_State *L, GCObject *o, lu_byte tt);\nLUAI_FUNC void luaC_linkupval (lua_State *L, UpVal *uv);\nLUAI_FUNC void luaC_barrierf (lua_State *L, GCObject *o, GCObject *v);\nLUAI_FUNC void luaC_barrierback (lua_State *L, Table *t);\n\n\n#endif\n"
  },
  {
    "path": "extern/deprecated/redis-2.8.21/deps/lua/src/linit.c",
    "content": "/*\n** $Id: linit.c,v 1.14.1.1 2007/12/27 13:02:25 roberto Exp $\n** Initialization of libraries for lua.c\n** See Copyright Notice in lua.h\n*/\n\n\n#define linit_c\n#define LUA_LIB\n\n#include \"lua.h\"\n\n#include \"lualib.h\"\n#include \"lauxlib.h\"\n\n\nstatic const luaL_Reg lualibs[] = {\n  {\"\", luaopen_base},\n  {LUA_LOADLIBNAME, luaopen_package},\n  {LUA_TABLIBNAME, luaopen_table},\n  {LUA_IOLIBNAME, luaopen_io},\n  {LUA_OSLIBNAME, luaopen_os},\n  {LUA_STRLIBNAME, luaopen_string},\n  {LUA_MATHLIBNAME, luaopen_math},\n  {LUA_DBLIBNAME, luaopen_debug},\n  {NULL, NULL}\n};\n\n\nLUALIB_API void luaL_openlibs (lua_State *L) {\n  const luaL_Reg *lib = lualibs;\n  for (; lib->func; lib++) {\n    lua_pushcfunction(L, lib->func);\n    lua_pushstring(L, lib->name);\n    lua_call(L, 1, 0);\n  }\n}\n\n"
  },
  {
    "path": "extern/deprecated/redis-2.8.21/deps/lua/src/liolib.c",
    "content": "/*\n** $Id: liolib.c,v 2.73.1.4 2010/05/14 15:33:51 roberto Exp $\n** Standard I/O (and system) library\n** See Copyright Notice in lua.h\n*/\n\n\n#include <errno.h>\n#include <stdio.h>\n#include <stdlib.h>\n#include <string.h>\n\n#define liolib_c\n#define LUA_LIB\n\n#include \"lua.h\"\n\n#include \"lauxlib.h\"\n#include \"lualib.h\"\n\n\n\n#define IO_INPUT\t1\n#define IO_OUTPUT\t2\n\n\nstatic const char *const fnames[] = {\"input\", \"output\"};\n\n\nstatic int pushresult (lua_State *L, int i, const char *filename) {\n  int en = errno;  /* calls to Lua API may change this value */\n  if (i) {\n    lua_pushboolean(L, 1);\n    return 1;\n  }\n  else {\n    lua_pushnil(L);\n    if (filename)\n      lua_pushfstring(L, \"%s: %s\", filename, strerror(en));\n    else\n      lua_pushfstring(L, \"%s\", strerror(en));\n    lua_pushinteger(L, en);\n    return 3;\n  }\n}\n\n\nstatic void fileerror (lua_State *L, int arg, const char *filename) {\n  lua_pushfstring(L, \"%s: %s\", filename, strerror(errno));\n  luaL_argerror(L, arg, lua_tostring(L, -1));\n}\n\n\n#define tofilep(L)\t((FILE **)luaL_checkudata(L, 1, LUA_FILEHANDLE))\n\n\nstatic int io_type (lua_State *L) {\n  void *ud;\n  luaL_checkany(L, 1);\n  ud = lua_touserdata(L, 1);\n  lua_getfield(L, LUA_REGISTRYINDEX, LUA_FILEHANDLE);\n  if (ud == NULL || !lua_getmetatable(L, 1) || !lua_rawequal(L, -2, -1))\n    lua_pushnil(L);  /* not a file */\n  else if (*((FILE **)ud) == NULL)\n    lua_pushliteral(L, \"closed file\");\n  else\n    lua_pushliteral(L, \"file\");\n  return 1;\n}\n\n\nstatic FILE *tofile (lua_State *L) {\n  FILE **f = tofilep(L);\n  if (*f == NULL)\n    luaL_error(L, \"attempt to use a closed file\");\n  return *f;\n}\n\n\n\n/*\n** When creating file handles, always creates a `closed' file handle\n** before opening the actual file; so, if there is a memory error, the\n** file is not left opened.\n*/\nstatic FILE **newfile (lua_State *L) {\n  FILE **pf = (FILE **)lua_newuserdata(L, sizeof(FILE *));\n  *pf = NULL;  /* file handle is currently `closed' */\n  luaL_getmetatable(L, LUA_FILEHANDLE);\n  lua_setmetatable(L, -2);\n  return pf;\n}\n\n\n/*\n** function to (not) close the standard files stdin, stdout, and stderr\n*/\nstatic int io_noclose (lua_State *L) {\n  lua_pushnil(L);\n  lua_pushliteral(L, \"cannot close standard file\");\n  return 2;\n}\n\n\n/*\n** function to close 'popen' files\n*/\nstatic int io_pclose (lua_State *L) {\n  FILE **p = tofilep(L);\n  int ok = lua_pclose(L, *p);\n  *p = NULL;\n  return pushresult(L, ok, NULL);\n}\n\n\n/*\n** function to close regular files\n*/\nstatic int io_fclose (lua_State *L) {\n  FILE **p = tofilep(L);\n  int ok = (fclose(*p) == 0);\n  *p = NULL;\n  return pushresult(L, ok, NULL);\n}\n\n\nstatic int aux_close (lua_State *L) {\n  lua_getfenv(L, 1);\n  lua_getfield(L, -1, \"__close\");\n  return (lua_tocfunction(L, -1))(L);\n}\n\n\nstatic int io_close (lua_State *L) {\n  if (lua_isnone(L, 1))\n    lua_rawgeti(L, LUA_ENVIRONINDEX, IO_OUTPUT);\n  tofile(L);  /* make sure argument is a file */\n  return aux_close(L);\n}\n\n\nstatic int io_gc (lua_State *L) {\n  FILE *f = *tofilep(L);\n  /* ignore closed files */\n  if (f != NULL)\n    aux_close(L);\n  return 0;\n}\n\n\nstatic int io_tostring (lua_State *L) {\n  FILE *f = *tofilep(L);\n  if (f == NULL)\n    lua_pushliteral(L, \"file (closed)\");\n  else\n    lua_pushfstring(L, \"file (%p)\", f);\n  return 1;\n}\n\n\nstatic int io_open (lua_State *L) {\n  const char *filename = luaL_checkstring(L, 1);\n  const char *mode = luaL_optstring(L, 2, \"r\");\n  FILE **pf = newfile(L);\n  *pf = fopen(filename, mode);\n  return (*pf == NULL) ? pushresult(L, 0, filename) : 1;\n}\n\n\n/*\n** this function has a separated environment, which defines the\n** correct __close for 'popen' files\n*/\nstatic int io_popen (lua_State *L) {\n  const char *filename = luaL_checkstring(L, 1);\n  const char *mode = luaL_optstring(L, 2, \"r\");\n  FILE **pf = newfile(L);\n  *pf = lua_popen(L, filename, mode);\n  return (*pf == NULL) ? pushresult(L, 0, filename) : 1;\n}\n\n\nstatic int io_tmpfile (lua_State *L) {\n  FILE **pf = newfile(L);\n  *pf = tmpfile();\n  return (*pf == NULL) ? pushresult(L, 0, NULL) : 1;\n}\n\n\nstatic FILE *getiofile (lua_State *L, int findex) {\n  FILE *f;\n  lua_rawgeti(L, LUA_ENVIRONINDEX, findex);\n  f = *(FILE **)lua_touserdata(L, -1);\n  if (f == NULL)\n    luaL_error(L, \"standard %s file is closed\", fnames[findex - 1]);\n  return f;\n}\n\n\nstatic int g_iofile (lua_State *L, int f, const char *mode) {\n  if (!lua_isnoneornil(L, 1)) {\n    const char *filename = lua_tostring(L, 1);\n    if (filename) {\n      FILE **pf = newfile(L);\n      *pf = fopen(filename, mode);\n      if (*pf == NULL)\n        fileerror(L, 1, filename);\n    }\n    else {\n      tofile(L);  /* check that it's a valid file handle */\n      lua_pushvalue(L, 1);\n    }\n    lua_rawseti(L, LUA_ENVIRONINDEX, f);\n  }\n  /* return current value */\n  lua_rawgeti(L, LUA_ENVIRONINDEX, f);\n  return 1;\n}\n\n\nstatic int io_input (lua_State *L) {\n  return g_iofile(L, IO_INPUT, \"r\");\n}\n\n\nstatic int io_output (lua_State *L) {\n  return g_iofile(L, IO_OUTPUT, \"w\");\n}\n\n\nstatic int io_readline (lua_State *L);\n\n\nstatic void aux_lines (lua_State *L, int idx, int toclose) {\n  lua_pushvalue(L, idx);\n  lua_pushboolean(L, toclose);  /* close/not close file when finished */\n  lua_pushcclosure(L, io_readline, 2);\n}\n\n\nstatic int f_lines (lua_State *L) {\n  tofile(L);  /* check that it's a valid file handle */\n  aux_lines(L, 1, 0);\n  return 1;\n}\n\n\nstatic int io_lines (lua_State *L) {\n  if (lua_isnoneornil(L, 1)) {  /* no arguments? */\n    /* will iterate over default input */\n    lua_rawgeti(L, LUA_ENVIRONINDEX, IO_INPUT);\n    return f_lines(L);\n  }\n  else {\n    const char *filename = luaL_checkstring(L, 1);\n    FILE **pf = newfile(L);\n    *pf = fopen(filename, \"r\");\n    if (*pf == NULL)\n      fileerror(L, 1, filename);\n    aux_lines(L, lua_gettop(L), 1);\n    return 1;\n  }\n}\n\n\n/*\n** {======================================================\n** READ\n** =======================================================\n*/\n\n\nstatic int read_number (lua_State *L, FILE *f) {\n  lua_Number d;\n  if (fscanf(f, LUA_NUMBER_SCAN, &d) == 1) {\n    lua_pushnumber(L, d);\n    return 1;\n  }\n  else {\n    lua_pushnil(L);  /* \"result\" to be removed */\n    return 0;  /* read fails */\n  }\n}\n\n\nstatic int test_eof (lua_State *L, FILE *f) {\n  int c = getc(f);\n  ungetc(c, f);\n  lua_pushlstring(L, NULL, 0);\n  return (c != EOF);\n}\n\n\nstatic int read_line (lua_State *L, FILE *f) {\n  luaL_Buffer b;\n  luaL_buffinit(L, &b);\n  for (;;) {\n    size_t l;\n    char *p = luaL_prepbuffer(&b);\n    if (fgets(p, LUAL_BUFFERSIZE, f) == NULL) {  /* eof? */\n      luaL_pushresult(&b);  /* close buffer */\n      return (lua_objlen(L, -1) > 0);  /* check whether read something */\n    }\n    l = strlen(p);\n    if (l == 0 || p[l-1] != '\\n')\n      luaL_addsize(&b, l);\n    else {\n      luaL_addsize(&b, l - 1);  /* do not include `eol' */\n      luaL_pushresult(&b);  /* close buffer */\n      return 1;  /* read at least an `eol' */\n    }\n  }\n}\n\n\nstatic int read_chars (lua_State *L, FILE *f, size_t n) {\n  size_t rlen;  /* how much to read */\n  size_t nr;  /* number of chars actually read */\n  luaL_Buffer b;\n  luaL_buffinit(L, &b);\n  rlen = LUAL_BUFFERSIZE;  /* try to read that much each time */\n  do {\n    char *p = luaL_prepbuffer(&b);\n    if (rlen > n) rlen = n;  /* cannot read more than asked */\n    nr = fread(p, sizeof(char), rlen, f);\n    luaL_addsize(&b, nr);\n    n -= nr;  /* still have to read `n' chars */\n  } while (n > 0 && nr == rlen);  /* until end of count or eof */\n  luaL_pushresult(&b);  /* close buffer */\n  return (n == 0 || lua_objlen(L, -1) > 0);\n}\n\n\nstatic int g_read (lua_State *L, FILE *f, int first) {\n  int nargs = lua_gettop(L) - 1;\n  int success;\n  int n;\n  clearerr(f);\n  if (nargs == 0) {  /* no arguments? */\n    success = read_line(L, f);\n    n = first+1;  /* to return 1 result */\n  }\n  else {  /* ensure stack space for all results and for auxlib's buffer */\n    luaL_checkstack(L, nargs+LUA_MINSTACK, \"too many arguments\");\n    success = 1;\n    for (n = first; nargs-- && success; n++) {\n      if (lua_type(L, n) == LUA_TNUMBER) {\n        size_t l = (size_t)lua_tointeger(L, n);\n        success = (l == 0) ? test_eof(L, f) : read_chars(L, f, l);\n      }\n      else {\n        const char *p = lua_tostring(L, n);\n        luaL_argcheck(L, p && p[0] == '*', n, \"invalid option\");\n        switch (p[1]) {\n          case 'n':  /* number */\n            success = read_number(L, f);\n            break;\n          case 'l':  /* line */\n            success = read_line(L, f);\n            break;\n          case 'a':  /* file */\n            read_chars(L, f, ~((size_t)0));  /* read MAX_SIZE_T chars */\n            success = 1; /* always success */\n            break;\n          default:\n            return luaL_argerror(L, n, \"invalid format\");\n        }\n      }\n    }\n  }\n  if (ferror(f))\n    return pushresult(L, 0, NULL);\n  if (!success) {\n    lua_pop(L, 1);  /* remove last result */\n    lua_pushnil(L);  /* push nil instead */\n  }\n  return n - first;\n}\n\n\nstatic int io_read (lua_State *L) {\n  return g_read(L, getiofile(L, IO_INPUT), 1);\n}\n\n\nstatic int f_read (lua_State *L) {\n  return g_read(L, tofile(L), 2);\n}\n\n\nstatic int io_readline (lua_State *L) {\n  FILE *f = *(FILE **)lua_touserdata(L, lua_upvalueindex(1));\n  int sucess;\n  if (f == NULL)  /* file is already closed? */\n    luaL_error(L, \"file is already closed\");\n  sucess = read_line(L, f);\n  if (ferror(f))\n    return luaL_error(L, \"%s\", strerror(errno));\n  if (sucess) return 1;\n  else {  /* EOF */\n    if (lua_toboolean(L, lua_upvalueindex(2))) {  /* generator created file? */\n      lua_settop(L, 0);\n      lua_pushvalue(L, lua_upvalueindex(1));\n      aux_close(L);  /* close it */\n    }\n    return 0;\n  }\n}\n\n/* }====================================================== */\n\n\nstatic int g_write (lua_State *L, FILE *f, int arg) {\n  int nargs = lua_gettop(L) - 1;\n  int status = 1;\n  for (; nargs--; arg++) {\n    if (lua_type(L, arg) == LUA_TNUMBER) {\n      /* optimization: could be done exactly as for strings */\n      status = status &&\n          fprintf(f, LUA_NUMBER_FMT, lua_tonumber(L, arg)) > 0;\n    }\n    else {\n      size_t l;\n      const char *s = luaL_checklstring(L, arg, &l);\n      status = status && (fwrite(s, sizeof(char), l, f) == l);\n    }\n  }\n  return pushresult(L, status, NULL);\n}\n\n\nstatic int io_write (lua_State *L) {\n  return g_write(L, getiofile(L, IO_OUTPUT), 1);\n}\n\n\nstatic int f_write (lua_State *L) {\n  return g_write(L, tofile(L), 2);\n}\n\n\nstatic int f_seek (lua_State *L) {\n  static const int mode[] = {SEEK_SET, SEEK_CUR, SEEK_END};\n  static const char *const modenames[] = {\"set\", \"cur\", \"end\", NULL};\n  FILE *f = tofile(L);\n  int op = luaL_checkoption(L, 2, \"cur\", modenames);\n  long offset = luaL_optlong(L, 3, 0);\n  op = fseek(f, offset, mode[op]);\n  if (op)\n    return pushresult(L, 0, NULL);  /* error */\n  else {\n    lua_pushinteger(L, ftell(f));\n    return 1;\n  }\n}\n\n\nstatic int f_setvbuf (lua_State *L) {\n  static const int mode[] = {_IONBF, _IOFBF, _IOLBF};\n  static const char *const modenames[] = {\"no\", \"full\", \"line\", NULL};\n  FILE *f = tofile(L);\n  int op = luaL_checkoption(L, 2, NULL, modenames);\n  lua_Integer sz = luaL_optinteger(L, 3, LUAL_BUFFERSIZE);\n  int res = setvbuf(f, NULL, mode[op], sz);\n  return pushresult(L, res == 0, NULL);\n}\n\n\n\nstatic int io_flush (lua_State *L) {\n  return pushresult(L, fflush(getiofile(L, IO_OUTPUT)) == 0, NULL);\n}\n\n\nstatic int f_flush (lua_State *L) {\n  return pushresult(L, fflush(tofile(L)) == 0, NULL);\n}\n\n\nstatic const luaL_Reg iolib[] = {\n  {\"close\", io_close},\n  {\"flush\", io_flush},\n  {\"input\", io_input},\n  {\"lines\", io_lines},\n  {\"open\", io_open},\n  {\"output\", io_output},\n  {\"popen\", io_popen},\n  {\"read\", io_read},\n  {\"tmpfile\", io_tmpfile},\n  {\"type\", io_type},\n  {\"write\", io_write},\n  {NULL, NULL}\n};\n\n\nstatic const luaL_Reg flib[] = {\n  {\"close\", io_close},\n  {\"flush\", f_flush},\n  {\"lines\", f_lines},\n  {\"read\", f_read},\n  {\"seek\", f_seek},\n  {\"setvbuf\", f_setvbuf},\n  {\"write\", f_write},\n  {\"__gc\", io_gc},\n  {\"__tostring\", io_tostring},\n  {NULL, NULL}\n};\n\n\nstatic void createmeta (lua_State *L) {\n  luaL_newmetatable(L, LUA_FILEHANDLE);  /* create metatable for file handles */\n  lua_pushvalue(L, -1);  /* push metatable */\n  lua_setfield(L, -2, \"__index\");  /* metatable.__index = metatable */\n  luaL_register(L, NULL, flib);  /* file methods */\n}\n\n\nstatic void createstdfile (lua_State *L, FILE *f, int k, const char *fname) {\n  *newfile(L) = f;\n  if (k > 0) {\n    lua_pushvalue(L, -1);\n    lua_rawseti(L, LUA_ENVIRONINDEX, k);\n  }\n  lua_pushvalue(L, -2);  /* copy environment */\n  lua_setfenv(L, -2);  /* set it */\n  lua_setfield(L, -3, fname);\n}\n\n\nstatic void newfenv (lua_State *L, lua_CFunction cls) {\n  lua_createtable(L, 0, 1);\n  lua_pushcfunction(L, cls);\n  lua_setfield(L, -2, \"__close\");\n}\n\n\nLUALIB_API int luaopen_io (lua_State *L) {\n  createmeta(L);\n  /* create (private) environment (with fields IO_INPUT, IO_OUTPUT, __close) */\n  newfenv(L, io_fclose);\n  lua_replace(L, LUA_ENVIRONINDEX);\n  /* open library */\n  luaL_register(L, LUA_IOLIBNAME, iolib);\n  /* create (and set) default files */\n  newfenv(L, io_noclose);  /* close function for default files */\n  createstdfile(L, stdin, IO_INPUT, \"stdin\");\n  createstdfile(L, stdout, IO_OUTPUT, \"stdout\");\n  createstdfile(L, stderr, 0, \"stderr\");\n  lua_pop(L, 1);  /* pop environment for default files */\n  lua_getfield(L, -1, \"popen\");\n  newfenv(L, io_pclose);  /* create environment for 'popen' */\n  lua_setfenv(L, -2);  /* set fenv for 'popen' */\n  lua_pop(L, 1);  /* pop 'popen' */\n  return 1;\n}\n\n"
  },
  {
    "path": "extern/deprecated/redis-2.8.21/deps/lua/src/llex.c",
    "content": "/*\n** $Id: llex.c,v 2.20.1.2 2009/11/23 14:58:22 roberto Exp $\n** Lexical Analyzer\n** See Copyright Notice in lua.h\n*/\n\n\n#include <ctype.h>\n#include <locale.h>\n#include <string.h>\n\n#define llex_c\n#define LUA_CORE\n\n#include \"lua.h\"\n\n#include \"ldo.h\"\n#include \"llex.h\"\n#include \"lobject.h\"\n#include \"lparser.h\"\n#include \"lstate.h\"\n#include \"lstring.h\"\n#include \"ltable.h\"\n#include \"lzio.h\"\n\n\n\n#define next(ls) (ls->current = zgetc(ls->z))\n\n\n\n\n#define currIsNewline(ls)\t(ls->current == '\\n' || ls->current == '\\r')\n\n\n/* ORDER RESERVED */\nconst char *const luaX_tokens [] = {\n    \"and\", \"break\", \"do\", \"else\", \"elseif\",\n    \"end\", \"false\", \"for\", \"function\", \"if\",\n    \"in\", \"local\", \"nil\", \"not\", \"or\", \"repeat\",\n    \"return\", \"then\", \"true\", \"until\", \"while\",\n    \"..\", \"...\", \"==\", \">=\", \"<=\", \"~=\",\n    \"<number>\", \"<name>\", \"<string>\", \"<eof>\",\n    NULL\n};\n\n\n#define save_and_next(ls) (save(ls, ls->current), next(ls))\n\n\nstatic void save (LexState *ls, int c) {\n  Mbuffer *b = ls->buff;\n  if (b->n + 1 > b->buffsize) {\n    size_t newsize;\n    if (b->buffsize >= MAX_SIZET/2)\n      luaX_lexerror(ls, \"lexical element too long\", 0);\n    newsize = b->buffsize * 2;\n    luaZ_resizebuffer(ls->L, b, newsize);\n  }\n  b->buffer[b->n++] = cast(char, c);\n}\n\n\nvoid luaX_init (lua_State *L) {\n  int i;\n  for (i=0; i<NUM_RESERVED; i++) {\n    TString *ts = luaS_new(L, luaX_tokens[i]);\n    luaS_fix(ts);  /* reserved words are never collected */\n    lua_assert(strlen(luaX_tokens[i])+1 <= TOKEN_LEN);\n    ts->tsv.reserved = cast_byte(i+1);  /* reserved word */\n  }\n}\n\n\n#define MAXSRC          80\n\n\nconst char *luaX_token2str (LexState *ls, int token) {\n  if (token < FIRST_RESERVED) {\n    lua_assert(token == cast(unsigned char, token));\n    return (iscntrl(token)) ? luaO_pushfstring(ls->L, \"char(%d)\", token) :\n                              luaO_pushfstring(ls->L, \"%c\", token);\n  }\n  else\n    return luaX_tokens[token-FIRST_RESERVED];\n}\n\n\nstatic const char *txtToken (LexState *ls, int token) {\n  switch (token) {\n    case TK_NAME:\n    case TK_STRING:\n    case TK_NUMBER:\n      save(ls, '\\0');\n      return luaZ_buffer(ls->buff);\n    default:\n      return luaX_token2str(ls, token);\n  }\n}\n\n\nvoid luaX_lexerror (LexState *ls, const char *msg, int token) {\n  char buff[MAXSRC];\n  luaO_chunkid(buff, getstr(ls->source), MAXSRC);\n  msg = luaO_pushfstring(ls->L, \"%s:%d: %s\", buff, ls->linenumber, msg);\n  if (token)\n    luaO_pushfstring(ls->L, \"%s near \" LUA_QS, msg, txtToken(ls, token));\n  luaD_throw(ls->L, LUA_ERRSYNTAX);\n}\n\n\nvoid luaX_syntaxerror (LexState *ls, const char *msg) {\n  luaX_lexerror(ls, msg, ls->t.token);\n}\n\n\nTString *luaX_newstring (LexState *ls, const char *str, size_t l) {\n  lua_State *L = ls->L;\n  TString *ts = luaS_newlstr(L, str, l);\n  TValue *o = luaH_setstr(L, ls->fs->h, ts);  /* entry for `str' */\n  if (ttisnil(o)) {\n    setbvalue(o, 1);  /* make sure `str' will not be collected */\n    luaC_checkGC(L);\n  }\n  return ts;\n}\n\n\nstatic void inclinenumber (LexState *ls) {\n  int old = ls->current;\n  lua_assert(currIsNewline(ls));\n  next(ls);  /* skip `\\n' or `\\r' */\n  if (currIsNewline(ls) && ls->current != old)\n    next(ls);  /* skip `\\n\\r' or `\\r\\n' */\n  if (++ls->linenumber >= MAX_INT)\n    luaX_syntaxerror(ls, \"chunk has too many lines\");\n}\n\n\nvoid luaX_setinput (lua_State *L, LexState *ls, ZIO *z, TString *source) {\n  ls->decpoint = '.';\n  ls->L = L;\n  ls->lookahead.token = TK_EOS;  /* no look-ahead token */\n  ls->z = z;\n  ls->fs = NULL;\n  ls->linenumber = 1;\n  ls->lastline = 1;\n  ls->source = source;\n  luaZ_resizebuffer(ls->L, ls->buff, LUA_MINBUFFER);  /* initialize buffer */\n  next(ls);  /* read first char */\n}\n\n\n\n/*\n** =======================================================\n** LEXICAL ANALYZER\n** =======================================================\n*/\n\n\n\nstatic int check_next (LexState *ls, const char *set) {\n  if (!strchr(set, ls->current))\n    return 0;\n  save_and_next(ls);\n  return 1;\n}\n\n\nstatic void buffreplace (LexState *ls, char from, char to) {\n  size_t n = luaZ_bufflen(ls->buff);\n  char *p = luaZ_buffer(ls->buff);\n  while (n--)\n    if (p[n] == from) p[n] = to;\n}\n\n\nstatic void trydecpoint (LexState *ls, SemInfo *seminfo) {\n  /* format error: try to update decimal point separator */\n  struct lconv *cv = localeconv();\n  char old = ls->decpoint;\n  ls->decpoint = (cv ? cv->decimal_point[0] : '.');\n  buffreplace(ls, old, ls->decpoint);  /* try updated decimal separator */\n  if (!luaO_str2d(luaZ_buffer(ls->buff), &seminfo->r)) {\n    /* format error with correct decimal point: no more options */\n    buffreplace(ls, ls->decpoint, '.');  /* undo change (for error message) */\n    luaX_lexerror(ls, \"malformed number\", TK_NUMBER);\n  }\n}\n\n\n/* LUA_NUMBER */\nstatic void read_numeral (LexState *ls, SemInfo *seminfo) {\n  lua_assert(isdigit(ls->current));\n  do {\n    save_and_next(ls);\n  } while (isdigit(ls->current) || ls->current == '.');\n  if (check_next(ls, \"Ee\"))  /* `E'? */\n    check_next(ls, \"+-\");  /* optional exponent sign */\n  while (isalnum(ls->current) || ls->current == '_')\n    save_and_next(ls);\n  save(ls, '\\0');\n  buffreplace(ls, '.', ls->decpoint);  /* follow locale for decimal point */\n  if (!luaO_str2d(luaZ_buffer(ls->buff), &seminfo->r))  /* format error? */\n    trydecpoint(ls, seminfo); /* try to update decimal point separator */\n}\n\n\nstatic int skip_sep (LexState *ls) {\n  int count = 0;\n  int s = ls->current;\n  lua_assert(s == '[' || s == ']');\n  save_and_next(ls);\n  while (ls->current == '=') {\n    save_and_next(ls);\n    count++;\n  }\n  return (ls->current == s) ? count : (-count) - 1;\n}\n\n\nstatic void read_long_string (LexState *ls, SemInfo *seminfo, int sep) {\n  int cont = 0;\n  (void)(cont);  /* avoid warnings when `cont' is not used */\n  save_and_next(ls);  /* skip 2nd `[' */\n  if (currIsNewline(ls))  /* string starts with a newline? */\n    inclinenumber(ls);  /* skip it */\n  for (;;) {\n    switch (ls->current) {\n      case EOZ:\n        luaX_lexerror(ls, (seminfo) ? \"unfinished long string\" :\n                                   \"unfinished long comment\", TK_EOS);\n        break;  /* to avoid warnings */\n#if defined(LUA_COMPAT_LSTR)\n      case '[': {\n        if (skip_sep(ls) == sep) {\n          save_and_next(ls);  /* skip 2nd `[' */\n          cont++;\n#if LUA_COMPAT_LSTR == 1\n          if (sep == 0)\n            luaX_lexerror(ls, \"nesting of [[...]] is deprecated\", '[');\n#endif\n        }\n        break;\n      }\n#endif\n      case ']': {\n        if (skip_sep(ls) == sep) {\n          save_and_next(ls);  /* skip 2nd `]' */\n#if defined(LUA_COMPAT_LSTR) && LUA_COMPAT_LSTR == 2\n          cont--;\n          if (sep == 0 && cont >= 0) break;\n#endif\n          goto endloop;\n        }\n        break;\n      }\n      case '\\n':\n      case '\\r': {\n        save(ls, '\\n');\n        inclinenumber(ls);\n        if (!seminfo) luaZ_resetbuffer(ls->buff);  /* avoid wasting space */\n        break;\n      }\n      default: {\n        if (seminfo) save_and_next(ls);\n        else next(ls);\n      }\n    }\n  } endloop:\n  if (seminfo)\n    seminfo->ts = luaX_newstring(ls, luaZ_buffer(ls->buff) + (2 + sep),\n                                     luaZ_bufflen(ls->buff) - 2*(2 + sep));\n}\n\n\nstatic void read_string (LexState *ls, int del, SemInfo *seminfo) {\n  save_and_next(ls);\n  while (ls->current != del) {\n    switch (ls->current) {\n      case EOZ:\n        luaX_lexerror(ls, \"unfinished string\", TK_EOS);\n        continue;  /* to avoid warnings */\n      case '\\n':\n      case '\\r':\n        luaX_lexerror(ls, \"unfinished string\", TK_STRING);\n        continue;  /* to avoid warnings */\n      case '\\\\': {\n        int c;\n        next(ls);  /* do not save the `\\' */\n        switch (ls->current) {\n          case 'a': c = '\\a'; break;\n          case 'b': c = '\\b'; break;\n          case 'f': c = '\\f'; break;\n          case 'n': c = '\\n'; break;\n          case 'r': c = '\\r'; break;\n          case 't': c = '\\t'; break;\n          case 'v': c = '\\v'; break;\n          case '\\n':  /* go through */\n          case '\\r': save(ls, '\\n'); inclinenumber(ls); continue;\n          case EOZ: continue;  /* will raise an error next loop */\n          default: {\n            if (!isdigit(ls->current))\n              save_and_next(ls);  /* handles \\\\, \\\", \\', and \\? */\n            else {  /* \\xxx */\n              int i = 0;\n              c = 0;\n              do {\n                c = 10*c + (ls->current-'0');\n                next(ls);\n              } while (++i<3 && isdigit(ls->current));\n              if (c > UCHAR_MAX)\n                luaX_lexerror(ls, \"escape sequence too large\", TK_STRING);\n              save(ls, c);\n            }\n            continue;\n          }\n        }\n        save(ls, c);\n        next(ls);\n        continue;\n      }\n      default:\n        save_and_next(ls);\n    }\n  }\n  save_and_next(ls);  /* skip delimiter */\n  seminfo->ts = luaX_newstring(ls, luaZ_buffer(ls->buff) + 1,\n                                   luaZ_bufflen(ls->buff) - 2);\n}\n\n\nstatic int llex (LexState *ls, SemInfo *seminfo) {\n  luaZ_resetbuffer(ls->buff);\n  for (;;) {\n    switch (ls->current) {\n      case '\\n':\n      case '\\r': {\n        inclinenumber(ls);\n        continue;\n      }\n      case '-': {\n        next(ls);\n        if (ls->current != '-') return '-';\n        /* else is a comment */\n        next(ls);\n        if (ls->current == '[') {\n          int sep = skip_sep(ls);\n          luaZ_resetbuffer(ls->buff);  /* `skip_sep' may dirty the buffer */\n          if (sep >= 0) {\n            read_long_string(ls, NULL, sep);  /* long comment */\n            luaZ_resetbuffer(ls->buff);\n            continue;\n          }\n        }\n        /* else short comment */\n        while (!currIsNewline(ls) && ls->current != EOZ)\n          next(ls);\n        continue;\n      }\n      case '[': {\n        int sep = skip_sep(ls);\n        if (sep >= 0) {\n          read_long_string(ls, seminfo, sep);\n          return TK_STRING;\n        }\n        else if (sep == -1) return '[';\n        else luaX_lexerror(ls, \"invalid long string delimiter\", TK_STRING);\n      }\n      case '=': {\n        next(ls);\n        if (ls->current != '=') return '=';\n        else { next(ls); return TK_EQ; }\n      }\n      case '<': {\n        next(ls);\n        if (ls->current != '=') return '<';\n        else { next(ls); return TK_LE; }\n      }\n      case '>': {\n        next(ls);\n        if (ls->current != '=') return '>';\n        else { next(ls); return TK_GE; }\n      }\n      case '~': {\n        next(ls);\n        if (ls->current != '=') return '~';\n        else { next(ls); return TK_NE; }\n      }\n      case '\"':\n      case '\\'': {\n        read_string(ls, ls->current, seminfo);\n        return TK_STRING;\n      }\n      case '.': {\n        save_and_next(ls);\n        if (check_next(ls, \".\")) {\n          if (check_next(ls, \".\"))\n            return TK_DOTS;   /* ... */\n          else return TK_CONCAT;   /* .. */\n        }\n        else if (!isdigit(ls->current)) return '.';\n        else {\n          read_numeral(ls, seminfo);\n          return TK_NUMBER;\n        }\n      }\n      case EOZ: {\n        return TK_EOS;\n      }\n      default: {\n        if (isspace(ls->current)) {\n          lua_assert(!currIsNewline(ls));\n          next(ls);\n          continue;\n        }\n        else if (isdigit(ls->current)) {\n          read_numeral(ls, seminfo);\n          return TK_NUMBER;\n        }\n        else if (isalpha(ls->current) || ls->current == '_') {\n          /* identifier or reserved word */\n          TString *ts;\n          do {\n            save_and_next(ls);\n          } while (isalnum(ls->current) || ls->current == '_');\n          ts = luaX_newstring(ls, luaZ_buffer(ls->buff),\n                                  luaZ_bufflen(ls->buff));\n          if (ts->tsv.reserved > 0)  /* reserved word? */\n            return ts->tsv.reserved - 1 + FIRST_RESERVED;\n          else {\n            seminfo->ts = ts;\n            return TK_NAME;\n          }\n        }\n        else {\n          int c = ls->current;\n          next(ls);\n          return c;  /* single-char tokens (+ - / ...) */\n        }\n      }\n    }\n  }\n}\n\n\nvoid luaX_next (LexState *ls) {\n  ls->lastline = ls->linenumber;\n  if (ls->lookahead.token != TK_EOS) {  /* is there a look-ahead token? */\n    ls->t = ls->lookahead;  /* use this one */\n    ls->lookahead.token = TK_EOS;  /* and discharge it */\n  }\n  else\n    ls->t.token = llex(ls, &ls->t.seminfo);  /* read next token */\n}\n\n\nvoid luaX_lookahead (LexState *ls) {\n  lua_assert(ls->lookahead.token == TK_EOS);\n  ls->lookahead.token = llex(ls, &ls->lookahead.seminfo);\n}\n\n"
  },
  {
    "path": "extern/deprecated/redis-2.8.21/deps/lua/src/llex.h",
    "content": "/*\n** $Id: llex.h,v 1.58.1.1 2007/12/27 13:02:25 roberto Exp $\n** Lexical Analyzer\n** See Copyright Notice in lua.h\n*/\n\n#ifndef llex_h\n#define llex_h\n\n#include \"lobject.h\"\n#include \"lzio.h\"\n\n\n#define FIRST_RESERVED\t257\n\n/* maximum length of a reserved word */\n#define TOKEN_LEN\t(sizeof(\"function\")/sizeof(char))\n\n\n/*\n* WARNING: if you change the order of this enumeration,\n* grep \"ORDER RESERVED\"\n*/\nenum RESERVED {\n  /* terminal symbols denoted by reserved words */\n  TK_AND = FIRST_RESERVED, TK_BREAK,\n  TK_DO, TK_ELSE, TK_ELSEIF, TK_END, TK_FALSE, TK_FOR, TK_FUNCTION,\n  TK_IF, TK_IN, TK_LOCAL, TK_NIL, TK_NOT, TK_OR, TK_REPEAT,\n  TK_RETURN, TK_THEN, TK_TRUE, TK_UNTIL, TK_WHILE,\n  /* other terminal symbols */\n  TK_CONCAT, TK_DOTS, TK_EQ, TK_GE, TK_LE, TK_NE, TK_NUMBER,\n  TK_NAME, TK_STRING, TK_EOS\n};\n\n/* number of reserved words */\n#define NUM_RESERVED\t(cast(int, TK_WHILE-FIRST_RESERVED+1))\n\n\n/* array with token `names' */\nLUAI_DATA const char *const luaX_tokens [];\n\n\ntypedef union {\n  lua_Number r;\n  TString *ts;\n} SemInfo;  /* semantics information */\n\n\ntypedef struct Token {\n  int token;\n  SemInfo seminfo;\n} Token;\n\n\ntypedef struct LexState {\n  int current;  /* current character (charint) */\n  int linenumber;  /* input line counter */\n  int lastline;  /* line of last token `consumed' */\n  Token t;  /* current token */\n  Token lookahead;  /* look ahead token */\n  struct FuncState *fs;  /* `FuncState' is private to the parser */\n  struct lua_State *L;\n  ZIO *z;  /* input stream */\n  Mbuffer *buff;  /* buffer for tokens */\n  TString *source;  /* current source name */\n  char decpoint;  /* locale decimal point */\n} LexState;\n\n\nLUAI_FUNC void luaX_init (lua_State *L);\nLUAI_FUNC void luaX_setinput (lua_State *L, LexState *ls, ZIO *z,\n                              TString *source);\nLUAI_FUNC TString *luaX_newstring (LexState *ls, const char *str, size_t l);\nLUAI_FUNC void luaX_next (LexState *ls);\nLUAI_FUNC void luaX_lookahead (LexState *ls);\nLUAI_FUNC void luaX_lexerror (LexState *ls, const char *msg, int token);\nLUAI_FUNC void luaX_syntaxerror (LexState *ls, const char *s);\nLUAI_FUNC const char *luaX_token2str (LexState *ls, int token);\n\n\n#endif\n"
  },
  {
    "path": "extern/deprecated/redis-2.8.21/deps/lua/src/llimits.h",
    "content": "/*\n** $Id: llimits.h,v 1.69.1.1 2007/12/27 13:02:25 roberto Exp $\n** Limits, basic types, and some other `installation-dependent' definitions\n** See Copyright Notice in lua.h\n*/\n\n#ifndef llimits_h\n#define llimits_h\n\n\n#include <limits.h>\n#include <stddef.h>\n\n\n#include \"lua.h\"\n\n\ntypedef LUAI_UINT32 lu_int32;\n\ntypedef LUAI_UMEM lu_mem;\n\ntypedef LUAI_MEM l_mem;\n\n\n\n/* chars used as small naturals (so that `char' is reserved for characters) */\ntypedef unsigned char lu_byte;\n\n\n#define MAX_SIZET\t((size_t)(~(size_t)0)-2)\n\n#define MAX_LUMEM\t((lu_mem)(~(lu_mem)0)-2)\n\n\n#define MAX_INT (INT_MAX-2)  /* maximum value of an int (-2 for safety) */\n\n/*\n** conversion of pointer to integer\n** this is for hashing only; there is no problem if the integer\n** cannot hold the whole pointer value\n*/\n#define IntPoint(p)  ((unsigned int)(lu_mem)(p))\n\n\n\n/* type to ensure maximum alignment */\ntypedef LUAI_USER_ALIGNMENT_T L_Umaxalign;\n\n\n/* result of a `usual argument conversion' over lua_Number */\ntypedef LUAI_UACNUMBER l_uacNumber;\n\n\n/* internal assertions for in-house debugging */\n#ifdef lua_assert\n\n#define check_exp(c,e)\t\t(lua_assert(c), (e))\n#define api_check(l,e)\t\tlua_assert(e)\n\n#else\n\n#define lua_assert(c)\t\t((void)0)\n#define check_exp(c,e)\t\t(e)\n#define api_check\t\tluai_apicheck\n\n#endif\n\n\n#ifndef UNUSED\n#define UNUSED(x)\t((void)(x))\t/* to avoid warnings */\n#endif\n\n\n#ifndef cast\n#define cast(t, exp)\t((t)(exp))\n#endif\n\n#define cast_byte(i)\tcast(lu_byte, (i))\n#define cast_num(i)\tcast(lua_Number, (i))\n#define cast_int(i)\tcast(int, (i))\n\n\n\n/*\n** type for virtual-machine instructions\n** must be an unsigned with (at least) 4 bytes (see details in lopcodes.h)\n*/\ntypedef lu_int32 Instruction;\n\n\n\n/* maximum stack for a Lua function */\n#define MAXSTACK\t250\n\n\n\n/* minimum size for the string table (must be power of 2) */\n#ifndef MINSTRTABSIZE\n#define MINSTRTABSIZE\t32\n#endif\n\n\n/* minimum size for string buffer */\n#ifndef LUA_MINBUFFER\n#define LUA_MINBUFFER\t32\n#endif\n\n\n#ifndef lua_lock\n#define lua_lock(L)     ((void) 0) \n#define lua_unlock(L)   ((void) 0)\n#endif\n\n#ifndef luai_threadyield\n#define luai_threadyield(L)     {lua_unlock(L); lua_lock(L);}\n#endif\n\n\n/*\n** macro to control inclusion of some hard tests on stack reallocation\n*/ \n#ifndef HARDSTACKTESTS\n#define condhardstacktests(x)\t((void)0)\n#else\n#define condhardstacktests(x)\tx\n#endif\n\n#endif\n"
  },
  {
    "path": "extern/deprecated/redis-2.8.21/deps/lua/src/lmathlib.c",
    "content": "/*\n** $Id: lmathlib.c,v 1.67.1.1 2007/12/27 13:02:25 roberto Exp $\n** Standard mathematical library\n** See Copyright Notice in lua.h\n*/\n\n\n#include <stdlib.h>\n#include <math.h>\n\n#define lmathlib_c\n#define LUA_LIB\n\n#include \"lua.h\"\n\n#include \"lauxlib.h\"\n#include \"lualib.h\"\n\n\n#undef PI\n#define PI (3.14159265358979323846)\n#define RADIANS_PER_DEGREE (PI/180.0)\n\n\n\nstatic int math_abs (lua_State *L) {\n  lua_pushnumber(L, fabs(luaL_checknumber(L, 1)));\n  return 1;\n}\n\nstatic int math_sin (lua_State *L) {\n  lua_pushnumber(L, sin(luaL_checknumber(L, 1)));\n  return 1;\n}\n\nstatic int math_sinh (lua_State *L) {\n  lua_pushnumber(L, sinh(luaL_checknumber(L, 1)));\n  return 1;\n}\n\nstatic int math_cos (lua_State *L) {\n  lua_pushnumber(L, cos(luaL_checknumber(L, 1)));\n  return 1;\n}\n\nstatic int math_cosh (lua_State *L) {\n  lua_pushnumber(L, cosh(luaL_checknumber(L, 1)));\n  return 1;\n}\n\nstatic int math_tan (lua_State *L) {\n  lua_pushnumber(L, tan(luaL_checknumber(L, 1)));\n  return 1;\n}\n\nstatic int math_tanh (lua_State *L) {\n  lua_pushnumber(L, tanh(luaL_checknumber(L, 1)));\n  return 1;\n}\n\nstatic int math_asin (lua_State *L) {\n  lua_pushnumber(L, asin(luaL_checknumber(L, 1)));\n  return 1;\n}\n\nstatic int math_acos (lua_State *L) {\n  lua_pushnumber(L, acos(luaL_checknumber(L, 1)));\n  return 1;\n}\n\nstatic int math_atan (lua_State *L) {\n  lua_pushnumber(L, atan(luaL_checknumber(L, 1)));\n  return 1;\n}\n\nstatic int math_atan2 (lua_State *L) {\n  lua_pushnumber(L, atan2(luaL_checknumber(L, 1), luaL_checknumber(L, 2)));\n  return 1;\n}\n\nstatic int math_ceil (lua_State *L) {\n  lua_pushnumber(L, ceil(luaL_checknumber(L, 1)));\n  return 1;\n}\n\nstatic int math_floor (lua_State *L) {\n  lua_pushnumber(L, floor(luaL_checknumber(L, 1)));\n  return 1;\n}\n\nstatic int math_fmod (lua_State *L) {\n  lua_pushnumber(L, fmod(luaL_checknumber(L, 1), luaL_checknumber(L, 2)));\n  return 1;\n}\n\nstatic int math_modf (lua_State *L) {\n  double ip;\n  double fp = modf(luaL_checknumber(L, 1), &ip);\n  lua_pushnumber(L, ip);\n  lua_pushnumber(L, fp);\n  return 2;\n}\n\nstatic int math_sqrt (lua_State *L) {\n  lua_pushnumber(L, sqrt(luaL_checknumber(L, 1)));\n  return 1;\n}\n\nstatic int math_pow (lua_State *L) {\n  lua_pushnumber(L, pow(luaL_checknumber(L, 1), luaL_checknumber(L, 2)));\n  return 1;\n}\n\nstatic int math_log (lua_State *L) {\n  lua_pushnumber(L, log(luaL_checknumber(L, 1)));\n  return 1;\n}\n\nstatic int math_log10 (lua_State *L) {\n  lua_pushnumber(L, log10(luaL_checknumber(L, 1)));\n  return 1;\n}\n\nstatic int math_exp (lua_State *L) {\n  lua_pushnumber(L, exp(luaL_checknumber(L, 1)));\n  return 1;\n}\n\nstatic int math_deg (lua_State *L) {\n  lua_pushnumber(L, luaL_checknumber(L, 1)/RADIANS_PER_DEGREE);\n  return 1;\n}\n\nstatic int math_rad (lua_State *L) {\n  lua_pushnumber(L, luaL_checknumber(L, 1)*RADIANS_PER_DEGREE);\n  return 1;\n}\n\nstatic int math_frexp (lua_State *L) {\n  int e;\n  lua_pushnumber(L, frexp(luaL_checknumber(L, 1), &e));\n  lua_pushinteger(L, e);\n  return 2;\n}\n\nstatic int math_ldexp (lua_State *L) {\n  lua_pushnumber(L, ldexp(luaL_checknumber(L, 1), luaL_checkint(L, 2)));\n  return 1;\n}\n\n\n\nstatic int math_min (lua_State *L) {\n  int n = lua_gettop(L);  /* number of arguments */\n  lua_Number dmin = luaL_checknumber(L, 1);\n  int i;\n  for (i=2; i<=n; i++) {\n    lua_Number d = luaL_checknumber(L, i);\n    if (d < dmin)\n      dmin = d;\n  }\n  lua_pushnumber(L, dmin);\n  return 1;\n}\n\n\nstatic int math_max (lua_State *L) {\n  int n = lua_gettop(L);  /* number of arguments */\n  lua_Number dmax = luaL_checknumber(L, 1);\n  int i;\n  for (i=2; i<=n; i++) {\n    lua_Number d = luaL_checknumber(L, i);\n    if (d > dmax)\n      dmax = d;\n  }\n  lua_pushnumber(L, dmax);\n  return 1;\n}\n\n\nstatic int math_random (lua_State *L) {\n  /* the `%' avoids the (rare) case of r==1, and is needed also because on\n     some systems (SunOS!) `rand()' may return a value larger than RAND_MAX */\n  lua_Number r = (lua_Number)(rand()%RAND_MAX) / (lua_Number)RAND_MAX;\n  switch (lua_gettop(L)) {  /* check number of arguments */\n    case 0: {  /* no arguments */\n      lua_pushnumber(L, r);  /* Number between 0 and 1 */\n      break;\n    }\n    case 1: {  /* only upper limit */\n      int u = luaL_checkint(L, 1);\n      luaL_argcheck(L, 1<=u, 1, \"interval is empty\");\n      lua_pushnumber(L, floor(r*u)+1);  /* int between 1 and `u' */\n      break;\n    }\n    case 2: {  /* lower and upper limits */\n      int l = luaL_checkint(L, 1);\n      int u = luaL_checkint(L, 2);\n      luaL_argcheck(L, l<=u, 2, \"interval is empty\");\n      lua_pushnumber(L, floor(r*(u-l+1))+l);  /* int between `l' and `u' */\n      break;\n    }\n    default: return luaL_error(L, \"wrong number of arguments\");\n  }\n  return 1;\n}\n\n\nstatic int math_randomseed (lua_State *L) {\n  srand(luaL_checkint(L, 1));\n  return 0;\n}\n\n\nstatic const luaL_Reg mathlib[] = {\n  {\"abs\",   math_abs},\n  {\"acos\",  math_acos},\n  {\"asin\",  math_asin},\n  {\"atan2\", math_atan2},\n  {\"atan\",  math_atan},\n  {\"ceil\",  math_ceil},\n  {\"cosh\",   math_cosh},\n  {\"cos\",   math_cos},\n  {\"deg\",   math_deg},\n  {\"exp\",   math_exp},\n  {\"floor\", math_floor},\n  {\"fmod\",   math_fmod},\n  {\"frexp\", math_frexp},\n  {\"ldexp\", math_ldexp},\n  {\"log10\", math_log10},\n  {\"log\",   math_log},\n  {\"max\",   math_max},\n  {\"min\",   math_min},\n  {\"modf\",   math_modf},\n  {\"pow\",   math_pow},\n  {\"rad\",   math_rad},\n  {\"random\",     math_random},\n  {\"randomseed\", math_randomseed},\n  {\"sinh\",   math_sinh},\n  {\"sin\",   math_sin},\n  {\"sqrt\",  math_sqrt},\n  {\"tanh\",   math_tanh},\n  {\"tan\",   math_tan},\n  {NULL, NULL}\n};\n\n\n/*\n** Open math library\n*/\nLUALIB_API int luaopen_math (lua_State *L) {\n  luaL_register(L, LUA_MATHLIBNAME, mathlib);\n  lua_pushnumber(L, PI);\n  lua_setfield(L, -2, \"pi\");\n  lua_pushnumber(L, HUGE_VAL);\n  lua_setfield(L, -2, \"huge\");\n#if defined(LUA_COMPAT_MOD)\n  lua_getfield(L, -1, \"fmod\");\n  lua_setfield(L, -2, \"mod\");\n#endif\n  return 1;\n}\n\n"
  },
  {
    "path": "extern/deprecated/redis-2.8.21/deps/lua/src/lmem.c",
    "content": "/*\n** $Id: lmem.c,v 1.70.1.1 2007/12/27 13:02:25 roberto Exp $\n** Interface to Memory Manager\n** See Copyright Notice in lua.h\n*/\n\n\n#include <stddef.h>\n\n#define lmem_c\n#define LUA_CORE\n\n#include \"lua.h\"\n\n#include \"ldebug.h\"\n#include \"ldo.h\"\n#include \"lmem.h\"\n#include \"lobject.h\"\n#include \"lstate.h\"\n\n\n\n/*\n** About the realloc function:\n** void * frealloc (void *ud, void *ptr, size_t osize, size_t nsize);\n** (`osize' is the old size, `nsize' is the new size)\n**\n** Lua ensures that (ptr == NULL) iff (osize == 0).\n**\n** * frealloc(ud, NULL, 0, x) creates a new block of size `x'\n**\n** * frealloc(ud, p, x, 0) frees the block `p'\n** (in this specific case, frealloc must return NULL).\n** particularly, frealloc(ud, NULL, 0, 0) does nothing\n** (which is equivalent to free(NULL) in ANSI C)\n**\n** frealloc returns NULL if it cannot create or reallocate the area\n** (any reallocation to an equal or smaller size cannot fail!)\n*/\n\n\n\n#define MINSIZEARRAY\t4\n\n\nvoid *luaM_growaux_ (lua_State *L, void *block, int *size, size_t size_elems,\n                     int limit, const char *errormsg) {\n  void *newblock;\n  int newsize;\n  if (*size >= limit/2) {  /* cannot double it? */\n    if (*size >= limit)  /* cannot grow even a little? */\n      luaG_runerror(L, errormsg);\n    newsize = limit;  /* still have at least one free place */\n  }\n  else {\n    newsize = (*size)*2;\n    if (newsize < MINSIZEARRAY)\n      newsize = MINSIZEARRAY;  /* minimum size */\n  }\n  newblock = luaM_reallocv(L, block, *size, newsize, size_elems);\n  *size = newsize;  /* update only when everything else is OK */\n  return newblock;\n}\n\n\nvoid *luaM_toobig (lua_State *L) {\n  luaG_runerror(L, \"memory allocation error: block too big\");\n  return NULL;  /* to avoid warnings */\n}\n\n\n\n/*\n** generic allocation routine.\n*/\nvoid *luaM_realloc_ (lua_State *L, void *block, size_t osize, size_t nsize) {\n  global_State *g = G(L);\n  lua_assert((osize == 0) == (block == NULL));\n  block = (*g->frealloc)(g->ud, block, osize, nsize);\n  if (block == NULL && nsize > 0)\n    luaD_throw(L, LUA_ERRMEM);\n  lua_assert((nsize == 0) == (block == NULL));\n  g->totalbytes = (g->totalbytes - osize) + nsize;\n  return block;\n}\n\n"
  },
  {
    "path": "extern/deprecated/redis-2.8.21/deps/lua/src/lmem.h",
    "content": "/*\n** $Id: lmem.h,v 1.31.1.1 2007/12/27 13:02:25 roberto Exp $\n** Interface to Memory Manager\n** See Copyright Notice in lua.h\n*/\n\n#ifndef lmem_h\n#define lmem_h\n\n\n#include <stddef.h>\n\n#include \"llimits.h\"\n#include \"lua.h\"\n\n#define MEMERRMSG\t\"not enough memory\"\n\n\n#define luaM_reallocv(L,b,on,n,e) \\\n\t((cast(size_t, (n)+1) <= MAX_SIZET/(e)) ?  /* +1 to avoid warnings */ \\\n\t\tluaM_realloc_(L, (b), (on)*(e), (n)*(e)) : \\\n\t\tluaM_toobig(L))\n\n#define luaM_freemem(L, b, s)\tluaM_realloc_(L, (b), (s), 0)\n#define luaM_free(L, b)\t\tluaM_realloc_(L, (b), sizeof(*(b)), 0)\n#define luaM_freearray(L, b, n, t)   luaM_reallocv(L, (b), n, 0, sizeof(t))\n\n#define luaM_malloc(L,t)\tluaM_realloc_(L, NULL, 0, (t))\n#define luaM_new(L,t)\t\tcast(t *, luaM_malloc(L, sizeof(t)))\n#define luaM_newvector(L,n,t) \\\n\t\tcast(t *, luaM_reallocv(L, NULL, 0, n, sizeof(t)))\n\n#define luaM_growvector(L,v,nelems,size,t,limit,e) \\\n          if ((nelems)+1 > (size)) \\\n            ((v)=cast(t *, luaM_growaux_(L,v,&(size),sizeof(t),limit,e)))\n\n#define luaM_reallocvector(L, v,oldn,n,t) \\\n   ((v)=cast(t *, luaM_reallocv(L, v, oldn, n, sizeof(t))))\n\n\nLUAI_FUNC void *luaM_realloc_ (lua_State *L, void *block, size_t oldsize,\n                                                          size_t size);\nLUAI_FUNC void *luaM_toobig (lua_State *L);\nLUAI_FUNC void *luaM_growaux_ (lua_State *L, void *block, int *size,\n                               size_t size_elem, int limit,\n                               const char *errormsg);\n\n#endif\n\n"
  },
  {
    "path": "extern/deprecated/redis-2.8.21/deps/lua/src/loadlib.c",
    "content": "/*\n** $Id: loadlib.c,v 1.52.1.4 2009/09/09 13:17:16 roberto Exp $\n** Dynamic library loader for Lua\n** See Copyright Notice in lua.h\n**\n** This module contains an implementation of loadlib for Unix systems\n** that have dlfcn, an implementation for Darwin (Mac OS X), an\n** implementation for Windows, and a stub for other systems.\n*/\n\n\n#include <stdlib.h>\n#include <string.h>\n\n\n#define loadlib_c\n#define LUA_LIB\n\n#include \"lua.h\"\n\n#include \"lauxlib.h\"\n#include \"lualib.h\"\n\n\n/* prefix for open functions in C libraries */\n#define LUA_POF\t\t\"luaopen_\"\n\n/* separator for open functions in C libraries */\n#define LUA_OFSEP\t\"_\"\n\n\n#define LIBPREFIX\t\"LOADLIB: \"\n\n#define POF\t\tLUA_POF\n#define LIB_FAIL\t\"open\"\n\n\n/* error codes for ll_loadfunc */\n#define ERRLIB\t\t1\n#define ERRFUNC\t\t2\n\n#define setprogdir(L)\t\t((void)0)\n\n\nstatic void ll_unloadlib (void *lib);\nstatic void *ll_load (lua_State *L, const char *path);\nstatic lua_CFunction ll_sym (lua_State *L, void *lib, const char *sym);\n\n\n\n#if defined(LUA_DL_DLOPEN)\n/*\n** {========================================================================\n** This is an implementation of loadlib based on the dlfcn interface.\n** The dlfcn interface is available in Linux, SunOS, Solaris, IRIX, FreeBSD,\n** NetBSD, AIX 4.2, HPUX 11, and  probably most other Unix flavors, at least\n** as an emulation layer on top of native functions.\n** =========================================================================\n*/\n\n#include <dlfcn.h>\n\nstatic void ll_unloadlib (void *lib) {\n  dlclose(lib);\n}\n\n\nstatic void *ll_load (lua_State *L, const char *path) {\n  void *lib = dlopen(path, RTLD_NOW);\n  if (lib == NULL) lua_pushstring(L, dlerror());\n  return lib;\n}\n\n\nstatic lua_CFunction ll_sym (lua_State *L, void *lib, const char *sym) {\n  lua_CFunction f = (lua_CFunction)dlsym(lib, sym);\n  if (f == NULL) lua_pushstring(L, dlerror());\n  return f;\n}\n\n/* }====================================================== */\n\n\n\n#elif defined(LUA_DL_DLL)\n/*\n** {======================================================================\n** This is an implementation of loadlib for Windows using native functions.\n** =======================================================================\n*/\n\n#include <windows.h>\n\n\n#undef setprogdir\n\nstatic void setprogdir (lua_State *L) {\n  char buff[MAX_PATH + 1];\n  char *lb;\n  DWORD nsize = sizeof(buff)/sizeof(char);\n  DWORD n = GetModuleFileNameA(NULL, buff, nsize);\n  if (n == 0 || n == nsize || (lb = strrchr(buff, '\\\\')) == NULL)\n    luaL_error(L, \"unable to get ModuleFileName\");\n  else {\n    *lb = '\\0';\n    luaL_gsub(L, lua_tostring(L, -1), LUA_EXECDIR, buff);\n    lua_remove(L, -2);  /* remove original string */\n  }\n}\n\n\nstatic void pusherror (lua_State *L) {\n  int error = GetLastError();\n  char buffer[128];\n  if (FormatMessageA(FORMAT_MESSAGE_IGNORE_INSERTS | FORMAT_MESSAGE_FROM_SYSTEM,\n      NULL, error, 0, buffer, sizeof(buffer), NULL))\n    lua_pushstring(L, buffer);\n  else\n    lua_pushfstring(L, \"system error %d\\n\", error);\n}\n\nstatic void ll_unloadlib (void *lib) {\n  FreeLibrary((HINSTANCE)lib);\n}\n\n\nstatic void *ll_load (lua_State *L, const char *path) {\n  HINSTANCE lib = LoadLibraryA(path);\n  if (lib == NULL) pusherror(L);\n  return lib;\n}\n\n\nstatic lua_CFunction ll_sym (lua_State *L, void *lib, const char *sym) {\n  lua_CFunction f = (lua_CFunction)GetProcAddress((HINSTANCE)lib, sym);\n  if (f == NULL) pusherror(L);\n  return f;\n}\n\n/* }====================================================== */\n\n\n\n#elif defined(LUA_DL_DYLD)\n/*\n** {======================================================================\n** Native Mac OS X / Darwin Implementation\n** =======================================================================\n*/\n\n#include <mach-o/dyld.h>\n\n\n/* Mac appends a `_' before C function names */\n#undef POF\n#define POF\t\"_\" LUA_POF\n\n\nstatic void pusherror (lua_State *L) {\n  const char *err_str;\n  const char *err_file;\n  NSLinkEditErrors err;\n  int err_num;\n  NSLinkEditError(&err, &err_num, &err_file, &err_str);\n  lua_pushstring(L, err_str);\n}\n\n\nstatic const char *errorfromcode (NSObjectFileImageReturnCode ret) {\n  switch (ret) {\n    case NSObjectFileImageInappropriateFile:\n      return \"file is not a bundle\";\n    case NSObjectFileImageArch:\n      return \"library is for wrong CPU type\";\n    case NSObjectFileImageFormat:\n      return \"bad format\";\n    case NSObjectFileImageAccess:\n      return \"cannot access file\";\n    case NSObjectFileImageFailure:\n    default:\n      return \"unable to load library\";\n  }\n}\n\n\nstatic void ll_unloadlib (void *lib) {\n  NSUnLinkModule((NSModule)lib, NSUNLINKMODULE_OPTION_RESET_LAZY_REFERENCES);\n}\n\n\nstatic void *ll_load (lua_State *L, const char *path) {\n  NSObjectFileImage img;\n  NSObjectFileImageReturnCode ret;\n  /* this would be a rare case, but prevents crashing if it happens */\n  if(!_dyld_present()) {\n    lua_pushliteral(L, \"dyld not present\");\n    return NULL;\n  }\n  ret = NSCreateObjectFileImageFromFile(path, &img);\n  if (ret == NSObjectFileImageSuccess) {\n    NSModule mod = NSLinkModule(img, path, NSLINKMODULE_OPTION_PRIVATE |\n                       NSLINKMODULE_OPTION_RETURN_ON_ERROR);\n    NSDestroyObjectFileImage(img);\n    if (mod == NULL) pusherror(L);\n    return mod;\n  }\n  lua_pushstring(L, errorfromcode(ret));\n  return NULL;\n}\n\n\nstatic lua_CFunction ll_sym (lua_State *L, void *lib, const char *sym) {\n  NSSymbol nss = NSLookupSymbolInModule((NSModule)lib, sym);\n  if (nss == NULL) {\n    lua_pushfstring(L, \"symbol \" LUA_QS \" not found\", sym);\n    return NULL;\n  }\n  return (lua_CFunction)NSAddressOfSymbol(nss);\n}\n\n/* }====================================================== */\n\n\n\n#else\n/*\n** {======================================================\n** Fallback for other systems\n** =======================================================\n*/\n\n#undef LIB_FAIL\n#define LIB_FAIL\t\"absent\"\n\n\n#define DLMSG\t\"dynamic libraries not enabled; check your Lua installation\"\n\n\nstatic void ll_unloadlib (void *lib) {\n  (void)lib;  /* to avoid warnings */\n}\n\n\nstatic void *ll_load (lua_State *L, const char *path) {\n  (void)path;  /* to avoid warnings */\n  lua_pushliteral(L, DLMSG);\n  return NULL;\n}\n\n\nstatic lua_CFunction ll_sym (lua_State *L, void *lib, const char *sym) {\n  (void)lib; (void)sym;  /* to avoid warnings */\n  lua_pushliteral(L, DLMSG);\n  return NULL;\n}\n\n/* }====================================================== */\n#endif\n\n\n\nstatic void **ll_register (lua_State *L, const char *path) {\n  void **plib;\n  lua_pushfstring(L, \"%s%s\", LIBPREFIX, path);\n  lua_gettable(L, LUA_REGISTRYINDEX);  /* check library in registry? */\n  if (!lua_isnil(L, -1))  /* is there an entry? */\n    plib = (void **)lua_touserdata(L, -1);\n  else {  /* no entry yet; create one */\n    lua_pop(L, 1);\n    plib = (void **)lua_newuserdata(L, sizeof(const void *));\n    *plib = NULL;\n    luaL_getmetatable(L, \"_LOADLIB\");\n    lua_setmetatable(L, -2);\n    lua_pushfstring(L, \"%s%s\", LIBPREFIX, path);\n    lua_pushvalue(L, -2);\n    lua_settable(L, LUA_REGISTRYINDEX);\n  }\n  return plib;\n}\n\n\n/*\n** __gc tag method: calls library's `ll_unloadlib' function with the lib\n** handle\n*/\nstatic int gctm (lua_State *L) {\n  void **lib = (void **)luaL_checkudata(L, 1, \"_LOADLIB\");\n  if (*lib) ll_unloadlib(*lib);\n  *lib = NULL;  /* mark library as closed */\n  return 0;\n}\n\n\nstatic int ll_loadfunc (lua_State *L, const char *path, const char *sym) {\n  void **reg = ll_register(L, path);\n  if (*reg == NULL) *reg = ll_load(L, path);\n  if (*reg == NULL)\n    return ERRLIB;  /* unable to load library */\n  else {\n    lua_CFunction f = ll_sym(L, *reg, sym);\n    if (f == NULL)\n      return ERRFUNC;  /* unable to find function */\n    lua_pushcfunction(L, f);\n    return 0;  /* return function */\n  }\n}\n\n\nstatic int ll_loadlib (lua_State *L) {\n  const char *path = luaL_checkstring(L, 1);\n  const char *init = luaL_checkstring(L, 2);\n  int stat = ll_loadfunc(L, path, init);\n  if (stat == 0)  /* no errors? */\n    return 1;  /* return the loaded function */\n  else {  /* error; error message is on stack top */\n    lua_pushnil(L);\n    lua_insert(L, -2);\n    lua_pushstring(L, (stat == ERRLIB) ?  LIB_FAIL : \"init\");\n    return 3;  /* return nil, error message, and where */\n  }\n}\n\n\n\n/*\n** {======================================================\n** 'require' function\n** =======================================================\n*/\n\n\nstatic int readable (const char *filename) {\n  FILE *f = fopen(filename, \"r\");  /* try to open file */\n  if (f == NULL) return 0;  /* open failed */\n  fclose(f);\n  return 1;\n}\n\n\nstatic const char *pushnexttemplate (lua_State *L, const char *path) {\n  const char *l;\n  while (*path == *LUA_PATHSEP) path++;  /* skip separators */\n  if (*path == '\\0') return NULL;  /* no more templates */\n  l = strchr(path, *LUA_PATHSEP);  /* find next separator */\n  if (l == NULL) l = path + strlen(path);\n  lua_pushlstring(L, path, l - path);  /* template */\n  return l;\n}\n\n\nstatic const char *findfile (lua_State *L, const char *name,\n                                           const char *pname) {\n  const char *path;\n  name = luaL_gsub(L, name, \".\", LUA_DIRSEP);\n  lua_getfield(L, LUA_ENVIRONINDEX, pname);\n  path = lua_tostring(L, -1);\n  if (path == NULL)\n    luaL_error(L, LUA_QL(\"package.%s\") \" must be a string\", pname);\n  lua_pushliteral(L, \"\");  /* error accumulator */\n  while ((path = pushnexttemplate(L, path)) != NULL) {\n    const char *filename;\n    filename = luaL_gsub(L, lua_tostring(L, -1), LUA_PATH_MARK, name);\n    lua_remove(L, -2);  /* remove path template */\n    if (readable(filename))  /* does file exist and is readable? */\n      return filename;  /* return that file name */\n    lua_pushfstring(L, \"\\n\\tno file \" LUA_QS, filename);\n    lua_remove(L, -2);  /* remove file name */\n    lua_concat(L, 2);  /* add entry to possible error message */\n  }\n  return NULL;  /* not found */\n}\n\n\nstatic void loaderror (lua_State *L, const char *filename) {\n  luaL_error(L, \"error loading module \" LUA_QS \" from file \" LUA_QS \":\\n\\t%s\",\n                lua_tostring(L, 1), filename, lua_tostring(L, -1));\n}\n\n\nstatic int loader_Lua (lua_State *L) {\n  const char *filename;\n  const char *name = luaL_checkstring(L, 1);\n  filename = findfile(L, name, \"path\");\n  if (filename == NULL) return 1;  /* library not found in this path */\n  if (luaL_loadfile(L, filename) != 0)\n    loaderror(L, filename);\n  return 1;  /* library loaded successfully */\n}\n\n\nstatic const char *mkfuncname (lua_State *L, const char *modname) {\n  const char *funcname;\n  const char *mark = strchr(modname, *LUA_IGMARK);\n  if (mark) modname = mark + 1;\n  funcname = luaL_gsub(L, modname, \".\", LUA_OFSEP);\n  funcname = lua_pushfstring(L, POF\"%s\", funcname);\n  lua_remove(L, -2);  /* remove 'gsub' result */\n  return funcname;\n}\n\n\nstatic int loader_C (lua_State *L) {\n  const char *funcname;\n  const char *name = luaL_checkstring(L, 1);\n  const char *filename = findfile(L, name, \"cpath\");\n  if (filename == NULL) return 1;  /* library not found in this path */\n  funcname = mkfuncname(L, name);\n  if (ll_loadfunc(L, filename, funcname) != 0)\n    loaderror(L, filename);\n  return 1;  /* library loaded successfully */\n}\n\n\nstatic int loader_Croot (lua_State *L) {\n  const char *funcname;\n  const char *filename;\n  const char *name = luaL_checkstring(L, 1);\n  const char *p = strchr(name, '.');\n  int stat;\n  if (p == NULL) return 0;  /* is root */\n  lua_pushlstring(L, name, p - name);\n  filename = findfile(L, lua_tostring(L, -1), \"cpath\");\n  if (filename == NULL) return 1;  /* root not found */\n  funcname = mkfuncname(L, name);\n  if ((stat = ll_loadfunc(L, filename, funcname)) != 0) {\n    if (stat != ERRFUNC) loaderror(L, filename);  /* real error */\n    lua_pushfstring(L, \"\\n\\tno module \" LUA_QS \" in file \" LUA_QS,\n                       name, filename);\n    return 1;  /* function not found */\n  }\n  return 1;\n}\n\n\nstatic int loader_preload (lua_State *L) {\n  const char *name = luaL_checkstring(L, 1);\n  lua_getfield(L, LUA_ENVIRONINDEX, \"preload\");\n  if (!lua_istable(L, -1))\n    luaL_error(L, LUA_QL(\"package.preload\") \" must be a table\");\n  lua_getfield(L, -1, name);\n  if (lua_isnil(L, -1))  /* not found? */\n    lua_pushfstring(L, \"\\n\\tno field package.preload['%s']\", name);\n  return 1;\n}\n\n\nstatic const int sentinel_ = 0;\n#define sentinel\t((void *)&sentinel_)\n\n\nstatic int ll_require (lua_State *L) {\n  const char *name = luaL_checkstring(L, 1);\n  int i;\n  lua_settop(L, 1);  /* _LOADED table will be at index 2 */\n  lua_getfield(L, LUA_REGISTRYINDEX, \"_LOADED\");\n  lua_getfield(L, 2, name);\n  if (lua_toboolean(L, -1)) {  /* is it there? */\n    if (lua_touserdata(L, -1) == sentinel)  /* check loops */\n      luaL_error(L, \"loop or previous error loading module \" LUA_QS, name);\n    return 1;  /* package is already loaded */\n  }\n  /* else must load it; iterate over available loaders */\n  lua_getfield(L, LUA_ENVIRONINDEX, \"loaders\");\n  if (!lua_istable(L, -1))\n    luaL_error(L, LUA_QL(\"package.loaders\") \" must be a table\");\n  lua_pushliteral(L, \"\");  /* error message accumulator */\n  for (i=1; ; i++) {\n    lua_rawgeti(L, -2, i);  /* get a loader */\n    if (lua_isnil(L, -1))\n      luaL_error(L, \"module \" LUA_QS \" not found:%s\",\n                    name, lua_tostring(L, -2));\n    lua_pushstring(L, name);\n    lua_call(L, 1, 1);  /* call it */\n    if (lua_isfunction(L, -1))  /* did it find module? */\n      break;  /* module loaded successfully */\n    else if (lua_isstring(L, -1))  /* loader returned error message? */\n      lua_concat(L, 2);  /* accumulate it */\n    else\n      lua_pop(L, 1);\n  }\n  lua_pushlightuserdata(L, sentinel);\n  lua_setfield(L, 2, name);  /* _LOADED[name] = sentinel */\n  lua_pushstring(L, name);  /* pass name as argument to module */\n  lua_call(L, 1, 1);  /* run loaded module */\n  if (!lua_isnil(L, -1))  /* non-nil return? */\n    lua_setfield(L, 2, name);  /* _LOADED[name] = returned value */\n  lua_getfield(L, 2, name);\n  if (lua_touserdata(L, -1) == sentinel) {   /* module did not set a value? */\n    lua_pushboolean(L, 1);  /* use true as result */\n    lua_pushvalue(L, -1);  /* extra copy to be returned */\n    lua_setfield(L, 2, name);  /* _LOADED[name] = true */\n  }\n  return 1;\n}\n\n/* }====================================================== */\n\n\n\n/*\n** {======================================================\n** 'module' function\n** =======================================================\n*/\n  \n\nstatic void setfenv (lua_State *L) {\n  lua_Debug ar;\n  if (lua_getstack(L, 1, &ar) == 0 ||\n      lua_getinfo(L, \"f\", &ar) == 0 ||  /* get calling function */\n      lua_iscfunction(L, -1))\n    luaL_error(L, LUA_QL(\"module\") \" not called from a Lua function\");\n  lua_pushvalue(L, -2);\n  lua_setfenv(L, -2);\n  lua_pop(L, 1);\n}\n\n\nstatic void dooptions (lua_State *L, int n) {\n  int i;\n  for (i = 2; i <= n; i++) {\n    lua_pushvalue(L, i);  /* get option (a function) */\n    lua_pushvalue(L, -2);  /* module */\n    lua_call(L, 1, 0);\n  }\n}\n\n\nstatic void modinit (lua_State *L, const char *modname) {\n  const char *dot;\n  lua_pushvalue(L, -1);\n  lua_setfield(L, -2, \"_M\");  /* module._M = module */\n  lua_pushstring(L, modname);\n  lua_setfield(L, -2, \"_NAME\");\n  dot = strrchr(modname, '.');  /* look for last dot in module name */\n  if (dot == NULL) dot = modname;\n  else dot++;\n  /* set _PACKAGE as package name (full module name minus last part) */\n  lua_pushlstring(L, modname, dot - modname);\n  lua_setfield(L, -2, \"_PACKAGE\");\n}\n\n\nstatic int ll_module (lua_State *L) {\n  const char *modname = luaL_checkstring(L, 1);\n  int loaded = lua_gettop(L) + 1;  /* index of _LOADED table */\n  lua_getfield(L, LUA_REGISTRYINDEX, \"_LOADED\");\n  lua_getfield(L, loaded, modname);  /* get _LOADED[modname] */\n  if (!lua_istable(L, -1)) {  /* not found? */\n    lua_pop(L, 1);  /* remove previous result */\n    /* try global variable (and create one if it does not exist) */\n    if (luaL_findtable(L, LUA_GLOBALSINDEX, modname, 1) != NULL)\n      return luaL_error(L, \"name conflict for module \" LUA_QS, modname);\n    lua_pushvalue(L, -1);\n    lua_setfield(L, loaded, modname);  /* _LOADED[modname] = new table */\n  }\n  /* check whether table already has a _NAME field */\n  lua_getfield(L, -1, \"_NAME\");\n  if (!lua_isnil(L, -1))  /* is table an initialized module? */\n    lua_pop(L, 1);\n  else {  /* no; initialize it */\n    lua_pop(L, 1);\n    modinit(L, modname);\n  }\n  lua_pushvalue(L, -1);\n  setfenv(L);\n  dooptions(L, loaded - 1);\n  return 0;\n}\n\n\nstatic int ll_seeall (lua_State *L) {\n  luaL_checktype(L, 1, LUA_TTABLE);\n  if (!lua_getmetatable(L, 1)) {\n    lua_createtable(L, 0, 1); /* create new metatable */\n    lua_pushvalue(L, -1);\n    lua_setmetatable(L, 1);\n  }\n  lua_pushvalue(L, LUA_GLOBALSINDEX);\n  lua_setfield(L, -2, \"__index\");  /* mt.__index = _G */\n  return 0;\n}\n\n\n/* }====================================================== */\n\n\n\n/* auxiliary mark (for internal use) */\n#define AUXMARK\t\t\"\\1\"\n\nstatic void setpath (lua_State *L, const char *fieldname, const char *envname,\n                                   const char *def) {\n  const char *path = getenv(envname);\n  if (path == NULL)  /* no environment variable? */\n    lua_pushstring(L, def);  /* use default */\n  else {\n    /* replace \";;\" by \";AUXMARK;\" and then AUXMARK by default path */\n    path = luaL_gsub(L, path, LUA_PATHSEP LUA_PATHSEP,\n                              LUA_PATHSEP AUXMARK LUA_PATHSEP);\n    luaL_gsub(L, path, AUXMARK, def);\n    lua_remove(L, -2);\n  }\n  setprogdir(L);\n  lua_setfield(L, -2, fieldname);\n}\n\n\nstatic const luaL_Reg pk_funcs[] = {\n  {\"loadlib\", ll_loadlib},\n  {\"seeall\", ll_seeall},\n  {NULL, NULL}\n};\n\n\nstatic const luaL_Reg ll_funcs[] = {\n  {\"module\", ll_module},\n  {\"require\", ll_require},\n  {NULL, NULL}\n};\n\n\nstatic const lua_CFunction loaders[] =\n  {loader_preload, loader_Lua, loader_C, loader_Croot, NULL};\n\n\nLUALIB_API int luaopen_package (lua_State *L) {\n  int i;\n  /* create new type _LOADLIB */\n  luaL_newmetatable(L, \"_LOADLIB\");\n  lua_pushcfunction(L, gctm);\n  lua_setfield(L, -2, \"__gc\");\n  /* create `package' table */\n  luaL_register(L, LUA_LOADLIBNAME, pk_funcs);\n#if defined(LUA_COMPAT_LOADLIB) \n  lua_getfield(L, -1, \"loadlib\");\n  lua_setfield(L, LUA_GLOBALSINDEX, \"loadlib\");\n#endif\n  lua_pushvalue(L, -1);\n  lua_replace(L, LUA_ENVIRONINDEX);\n  /* create `loaders' table */\n  lua_createtable(L, sizeof(loaders)/sizeof(loaders[0]) - 1, 0);\n  /* fill it with pre-defined loaders */\n  for (i=0; loaders[i] != NULL; i++) {\n    lua_pushcfunction(L, loaders[i]);\n    lua_rawseti(L, -2, i+1);\n  }\n  lua_setfield(L, -2, \"loaders\");  /* put it in field `loaders' */\n  setpath(L, \"path\", LUA_PATH, LUA_PATH_DEFAULT);  /* set field `path' */\n  setpath(L, \"cpath\", LUA_CPATH, LUA_CPATH_DEFAULT); /* set field `cpath' */\n  /* store config information */\n  lua_pushliteral(L, LUA_DIRSEP \"\\n\" LUA_PATHSEP \"\\n\" LUA_PATH_MARK \"\\n\"\n                     LUA_EXECDIR \"\\n\" LUA_IGMARK);\n  lua_setfield(L, -2, \"config\");\n  /* set field `loaded' */\n  luaL_findtable(L, LUA_REGISTRYINDEX, \"_LOADED\", 2);\n  lua_setfield(L, -2, \"loaded\");\n  /* set field `preload' */\n  lua_newtable(L);\n  lua_setfield(L, -2, \"preload\");\n  lua_pushvalue(L, LUA_GLOBALSINDEX);\n  luaL_register(L, NULL, ll_funcs);  /* open lib into global table */\n  lua_pop(L, 1);\n  return 1;  /* return 'package' table */\n}\n\n"
  },
  {
    "path": "extern/deprecated/redis-2.8.21/deps/lua/src/lobject.c",
    "content": "/*\n** $Id: lobject.c,v 2.22.1.1 2007/12/27 13:02:25 roberto Exp $\n** Some generic functions over Lua objects\n** See Copyright Notice in lua.h\n*/\n\n#include <ctype.h>\n#include <stdarg.h>\n#include <stdio.h>\n#include <stdlib.h>\n#include <string.h>\n\n#define lobject_c\n#define LUA_CORE\n\n#include \"lua.h\"\n\n#include \"ldo.h\"\n#include \"lmem.h\"\n#include \"lobject.h\"\n#include \"lstate.h\"\n#include \"lstring.h\"\n#include \"lvm.h\"\n\n\n\nconst TValue luaO_nilobject_ = {{NULL}, LUA_TNIL};\n\n\n/*\n** converts an integer to a \"floating point byte\", represented as\n** (eeeeexxx), where the real value is (1xxx) * 2^(eeeee - 1) if\n** eeeee != 0 and (xxx) otherwise.\n*/\nint luaO_int2fb (unsigned int x) {\n  int e = 0;  /* expoent */\n  while (x >= 16) {\n    x = (x+1) >> 1;\n    e++;\n  }\n  if (x < 8) return x;\n  else return ((e+1) << 3) | (cast_int(x) - 8);\n}\n\n\n/* converts back */\nint luaO_fb2int (int x) {\n  int e = (x >> 3) & 31;\n  if (e == 0) return x;\n  else return ((x & 7)+8) << (e - 1);\n}\n\n\nint luaO_log2 (unsigned int x) {\n  static const lu_byte log_2[256] = {\n    0,1,2,2,3,3,3,3,4,4,4,4,4,4,4,4,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,\n    6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,\n    7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,\n    7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,\n    8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,\n    8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,\n    8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,\n    8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8\n  };\n  int l = -1;\n  while (x >= 256) { l += 8; x >>= 8; }\n  return l + log_2[x];\n\n}\n\n\nint luaO_rawequalObj (const TValue *t1, const TValue *t2) {\n  if (ttype(t1) != ttype(t2)) return 0;\n  else switch (ttype(t1)) {\n    case LUA_TNIL:\n      return 1;\n    case LUA_TNUMBER:\n      return luai_numeq(nvalue(t1), nvalue(t2));\n    case LUA_TBOOLEAN:\n      return bvalue(t1) == bvalue(t2);  /* boolean true must be 1 !! */\n    case LUA_TLIGHTUSERDATA:\n      return pvalue(t1) == pvalue(t2);\n    default:\n      lua_assert(iscollectable(t1));\n      return gcvalue(t1) == gcvalue(t2);\n  }\n}\n\n\nint luaO_str2d (const char *s, lua_Number *result) {\n  char *endptr;\n  *result = lua_str2number(s, &endptr);\n  if (endptr == s) return 0;  /* conversion failed */\n  if (*endptr == 'x' || *endptr == 'X')  /* maybe an hexadecimal constant? */\n    *result = cast_num(strtoul(s, &endptr, 16));\n  if (*endptr == '\\0') return 1;  /* most common case */\n  while (isspace(cast(unsigned char, *endptr))) endptr++;\n  if (*endptr != '\\0') return 0;  /* invalid trailing characters? */\n  return 1;\n}\n\n\n\nstatic void pushstr (lua_State *L, const char *str) {\n  setsvalue2s(L, L->top, luaS_new(L, str));\n  incr_top(L);\n}\n\n\n/* this function handles only `%d', `%c', %f, %p, and `%s' formats */\nconst char *luaO_pushvfstring (lua_State *L, const char *fmt, va_list argp) {\n  int n = 1;\n  pushstr(L, \"\");\n  for (;;) {\n    const char *e = strchr(fmt, '%');\n    if (e == NULL) break;\n    setsvalue2s(L, L->top, luaS_newlstr(L, fmt, e-fmt));\n    incr_top(L);\n    switch (*(e+1)) {\n      case 's': {\n        const char *s = va_arg(argp, char *);\n        if (s == NULL) s = \"(null)\";\n        pushstr(L, s);\n        break;\n      }\n      case 'c': {\n        char buff[2];\n        buff[0] = cast(char, va_arg(argp, int));\n        buff[1] = '\\0';\n        pushstr(L, buff);\n        break;\n      }\n      case 'd': {\n        setnvalue(L->top, cast_num(va_arg(argp, int)));\n        incr_top(L);\n        break;\n      }\n      case 'f': {\n        setnvalue(L->top, cast_num(va_arg(argp, l_uacNumber)));\n        incr_top(L);\n        break;\n      }\n      case 'p': {\n        char buff[4*sizeof(void *) + 8]; /* should be enough space for a `%p' */\n        sprintf(buff, \"%p\", va_arg(argp, void *));\n        pushstr(L, buff);\n        break;\n      }\n      case '%': {\n        pushstr(L, \"%\");\n        break;\n      }\n      default: {\n        char buff[3];\n        buff[0] = '%';\n        buff[1] = *(e+1);\n        buff[2] = '\\0';\n        pushstr(L, buff);\n        break;\n      }\n    }\n    n += 2;\n    fmt = e+2;\n  }\n  pushstr(L, fmt);\n  luaV_concat(L, n+1, cast_int(L->top - L->base) - 1);\n  L->top -= n;\n  return svalue(L->top - 1);\n}\n\n\nconst char *luaO_pushfstring (lua_State *L, const char *fmt, ...) {\n  const char *msg;\n  va_list argp;\n  va_start(argp, fmt);\n  msg = luaO_pushvfstring(L, fmt, argp);\n  va_end(argp);\n  return msg;\n}\n\n\nvoid luaO_chunkid (char *out, const char *source, size_t bufflen) {\n  if (*source == '=') {\n    strncpy(out, source+1, bufflen);  /* remove first char */\n    out[bufflen-1] = '\\0';  /* ensures null termination */\n  }\n  else {  /* out = \"source\", or \"...source\" */\n    if (*source == '@') {\n      size_t l;\n      source++;  /* skip the `@' */\n      bufflen -= sizeof(\" '...' \");\n      l = strlen(source);\n      strcpy(out, \"\");\n      if (l > bufflen) {\n        source += (l-bufflen);  /* get last part of file name */\n        strcat(out, \"...\");\n      }\n      strcat(out, source);\n    }\n    else {  /* out = [string \"string\"] */\n      size_t len = strcspn(source, \"\\n\\r\");  /* stop at first newline */\n      bufflen -= sizeof(\" [string \\\"...\\\"] \");\n      if (len > bufflen) len = bufflen;\n      strcpy(out, \"[string \\\"\");\n      if (source[len] != '\\0') {  /* must truncate? */\n        strncat(out, source, len);\n        strcat(out, \"...\");\n      }\n      else\n        strcat(out, source);\n      strcat(out, \"\\\"]\");\n    }\n  }\n}\n"
  },
  {
    "path": "extern/deprecated/redis-2.8.21/deps/lua/src/lobject.h",
    "content": "/*\n** $Id: lobject.h,v 2.20.1.2 2008/08/06 13:29:48 roberto Exp $\n** Type definitions for Lua objects\n** See Copyright Notice in lua.h\n*/\n\n\n#ifndef lobject_h\n#define lobject_h\n\n\n#include <stdarg.h>\n\n\n#include \"llimits.h\"\n#include \"lua.h\"\n\n\n/* tags for values visible from Lua */\n#define LAST_TAG\tLUA_TTHREAD\n\n#define NUM_TAGS\t(LAST_TAG+1)\n\n\n/*\n** Extra tags for non-values\n*/\n#define LUA_TPROTO\t(LAST_TAG+1)\n#define LUA_TUPVAL\t(LAST_TAG+2)\n#define LUA_TDEADKEY\t(LAST_TAG+3)\n\n\n/*\n** Union of all collectable objects\n*/\ntypedef union GCObject GCObject;\n\n\n/*\n** Common Header for all collectable objects (in macro form, to be\n** included in other objects)\n*/\n#define CommonHeader\tGCObject *next; lu_byte tt; lu_byte marked\n\n\n/*\n** Common header in struct form\n*/\ntypedef struct GCheader {\n  CommonHeader;\n} GCheader;\n\n\n\n\n/*\n** Union of all Lua values\n*/\ntypedef union {\n  GCObject *gc;\n  void *p;\n  lua_Number n;\n  int b;\n} Value;\n\n\n/*\n** Tagged Values\n*/\n\n#define TValuefields\tValue value; int tt\n\ntypedef struct lua_TValue {\n  TValuefields;\n} TValue;\n\n\n/* Macros to test type */\n#define ttisnil(o)\t(ttype(o) == LUA_TNIL)\n#define ttisnumber(o)\t(ttype(o) == LUA_TNUMBER)\n#define ttisstring(o)\t(ttype(o) == LUA_TSTRING)\n#define ttistable(o)\t(ttype(o) == LUA_TTABLE)\n#define ttisfunction(o)\t(ttype(o) == LUA_TFUNCTION)\n#define ttisboolean(o)\t(ttype(o) == LUA_TBOOLEAN)\n#define ttisuserdata(o)\t(ttype(o) == LUA_TUSERDATA)\n#define ttisthread(o)\t(ttype(o) == LUA_TTHREAD)\n#define ttislightuserdata(o)\t(ttype(o) == LUA_TLIGHTUSERDATA)\n\n/* Macros to access values */\n#define ttype(o)\t((o)->tt)\n#define gcvalue(o)\tcheck_exp(iscollectable(o), (o)->value.gc)\n#define pvalue(o)\tcheck_exp(ttislightuserdata(o), (o)->value.p)\n#define nvalue(o)\tcheck_exp(ttisnumber(o), (o)->value.n)\n#define rawtsvalue(o)\tcheck_exp(ttisstring(o), &(o)->value.gc->ts)\n#define tsvalue(o)\t(&rawtsvalue(o)->tsv)\n#define rawuvalue(o)\tcheck_exp(ttisuserdata(o), &(o)->value.gc->u)\n#define uvalue(o)\t(&rawuvalue(o)->uv)\n#define clvalue(o)\tcheck_exp(ttisfunction(o), &(o)->value.gc->cl)\n#define hvalue(o)\tcheck_exp(ttistable(o), &(o)->value.gc->h)\n#define bvalue(o)\tcheck_exp(ttisboolean(o), (o)->value.b)\n#define thvalue(o)\tcheck_exp(ttisthread(o), &(o)->value.gc->th)\n\n#define l_isfalse(o)\t(ttisnil(o) || (ttisboolean(o) && bvalue(o) == 0))\n\n/*\n** for internal debug only\n*/\n#define checkconsistency(obj) \\\n  lua_assert(!iscollectable(obj) || (ttype(obj) == (obj)->value.gc->gch.tt))\n\n#define checkliveness(g,obj) \\\n  lua_assert(!iscollectable(obj) || \\\n  ((ttype(obj) == (obj)->value.gc->gch.tt) && !isdead(g, (obj)->value.gc)))\n\n\n/* Macros to set values */\n#define setnilvalue(obj) ((obj)->tt=LUA_TNIL)\n\n#define setnvalue(obj,x) \\\n  { TValue *i_o=(obj); i_o->value.n=(x); i_o->tt=LUA_TNUMBER; }\n\n#define setpvalue(obj,x) \\\n  { TValue *i_o=(obj); i_o->value.p=(x); i_o->tt=LUA_TLIGHTUSERDATA; }\n\n#define setbvalue(obj,x) \\\n  { TValue *i_o=(obj); i_o->value.b=(x); i_o->tt=LUA_TBOOLEAN; }\n\n#define setsvalue(L,obj,x) \\\n  { TValue *i_o=(obj); \\\n    i_o->value.gc=cast(GCObject *, (x)); i_o->tt=LUA_TSTRING; \\\n    checkliveness(G(L),i_o); }\n\n#define setuvalue(L,obj,x) \\\n  { TValue *i_o=(obj); \\\n    i_o->value.gc=cast(GCObject *, (x)); i_o->tt=LUA_TUSERDATA; \\\n    checkliveness(G(L),i_o); }\n\n#define setthvalue(L,obj,x) \\\n  { TValue *i_o=(obj); \\\n    i_o->value.gc=cast(GCObject *, (x)); i_o->tt=LUA_TTHREAD; \\\n    checkliveness(G(L),i_o); }\n\n#define setclvalue(L,obj,x) \\\n  { TValue *i_o=(obj); \\\n    i_o->value.gc=cast(GCObject *, (x)); i_o->tt=LUA_TFUNCTION; \\\n    checkliveness(G(L),i_o); }\n\n#define sethvalue(L,obj,x) \\\n  { TValue *i_o=(obj); \\\n    i_o->value.gc=cast(GCObject *, (x)); i_o->tt=LUA_TTABLE; \\\n    checkliveness(G(L),i_o); }\n\n#define setptvalue(L,obj,x) \\\n  { TValue *i_o=(obj); \\\n    i_o->value.gc=cast(GCObject *, (x)); i_o->tt=LUA_TPROTO; \\\n    checkliveness(G(L),i_o); }\n\n\n\n\n#define setobj(L,obj1,obj2) \\\n  { const TValue *o2=(obj2); TValue *o1=(obj1); \\\n    o1->value = o2->value; o1->tt=o2->tt; \\\n    checkliveness(G(L),o1); }\n\n\n/*\n** different types of sets, according to destination\n*/\n\n/* from stack to (same) stack */\n#define setobjs2s\tsetobj\n/* to stack (not from same stack) */\n#define setobj2s\tsetobj\n#define setsvalue2s\tsetsvalue\n#define sethvalue2s\tsethvalue\n#define setptvalue2s\tsetptvalue\n/* from table to same table */\n#define setobjt2t\tsetobj\n/* to table */\n#define setobj2t\tsetobj\n/* to new object */\n#define setobj2n\tsetobj\n#define setsvalue2n\tsetsvalue\n\n#define setttype(obj, tt) (ttype(obj) = (tt))\n\n\n#define iscollectable(o)\t(ttype(o) >= LUA_TSTRING)\n\n\n\ntypedef TValue *StkId;  /* index to stack elements */\n\n\n/*\n** String headers for string table\n*/\ntypedef union TString {\n  L_Umaxalign dummy;  /* ensures maximum alignment for strings */\n  struct {\n    CommonHeader;\n    lu_byte reserved;\n    unsigned int hash;\n    size_t len;\n  } tsv;\n} TString;\n\n\n#define getstr(ts)\tcast(const char *, (ts) + 1)\n#define svalue(o)       getstr(rawtsvalue(o))\n\n\n\ntypedef union Udata {\n  L_Umaxalign dummy;  /* ensures maximum alignment for `local' udata */\n  struct {\n    CommonHeader;\n    struct Table *metatable;\n    struct Table *env;\n    size_t len;\n  } uv;\n} Udata;\n\n\n\n\n/*\n** Function Prototypes\n*/\ntypedef struct Proto {\n  CommonHeader;\n  TValue *k;  /* constants used by the function */\n  Instruction *code;\n  struct Proto **p;  /* functions defined inside the function */\n  int *lineinfo;  /* map from opcodes to source lines */\n  struct LocVar *locvars;  /* information about local variables */\n  TString **upvalues;  /* upvalue names */\n  TString  *source;\n  int sizeupvalues;\n  int sizek;  /* size of `k' */\n  int sizecode;\n  int sizelineinfo;\n  int sizep;  /* size of `p' */\n  int sizelocvars;\n  int linedefined;\n  int lastlinedefined;\n  GCObject *gclist;\n  lu_byte nups;  /* number of upvalues */\n  lu_byte numparams;\n  lu_byte is_vararg;\n  lu_byte maxstacksize;\n} Proto;\n\n\n/* masks for new-style vararg */\n#define VARARG_HASARG\t\t1\n#define VARARG_ISVARARG\t\t2\n#define VARARG_NEEDSARG\t\t4\n\n\ntypedef struct LocVar {\n  TString *varname;\n  int startpc;  /* first point where variable is active */\n  int endpc;    /* first point where variable is dead */\n} LocVar;\n\n\n\n/*\n** Upvalues\n*/\n\ntypedef struct UpVal {\n  CommonHeader;\n  TValue *v;  /* points to stack or to its own value */\n  union {\n    TValue value;  /* the value (when closed) */\n    struct {  /* double linked list (when open) */\n      struct UpVal *prev;\n      struct UpVal *next;\n    } l;\n  } u;\n} UpVal;\n\n\n/*\n** Closures\n*/\n\n#define ClosureHeader \\\n\tCommonHeader; lu_byte isC; lu_byte nupvalues; GCObject *gclist; \\\n\tstruct Table *env\n\ntypedef struct CClosure {\n  ClosureHeader;\n  lua_CFunction f;\n  TValue upvalue[1];\n} CClosure;\n\n\ntypedef struct LClosure {\n  ClosureHeader;\n  struct Proto *p;\n  UpVal *upvals[1];\n} LClosure;\n\n\ntypedef union Closure {\n  CClosure c;\n  LClosure l;\n} Closure;\n\n\n#define iscfunction(o)\t(ttype(o) == LUA_TFUNCTION && clvalue(o)->c.isC)\n#define isLfunction(o)\t(ttype(o) == LUA_TFUNCTION && !clvalue(o)->c.isC)\n\n\n/*\n** Tables\n*/\n\ntypedef union TKey {\n  struct {\n    TValuefields;\n    struct Node *next;  /* for chaining */\n  } nk;\n  TValue tvk;\n} TKey;\n\n\ntypedef struct Node {\n  TValue i_val;\n  TKey i_key;\n} Node;\n\n\ntypedef struct Table {\n  CommonHeader;\n  lu_byte flags;  /* 1<<p means tagmethod(p) is not present */ \n  lu_byte lsizenode;  /* log2 of size of `node' array */\n  struct Table *metatable;\n  TValue *array;  /* array part */\n  Node *node;\n  Node *lastfree;  /* any free position is before this position */\n  GCObject *gclist;\n  int sizearray;  /* size of `array' array */\n} Table;\n\n\n\n/*\n** `module' operation for hashing (size is always a power of 2)\n*/\n#define lmod(s,size) \\\n\t(check_exp((size&(size-1))==0, (cast(int, (s) & ((size)-1)))))\n\n\n#define twoto(x)\t(1<<(x))\n#define sizenode(t)\t(twoto((t)->lsizenode))\n\n\n#define luaO_nilobject\t\t(&luaO_nilobject_)\n\nLUAI_DATA const TValue luaO_nilobject_;\n\n#define ceillog2(x)\t(luaO_log2((x)-1) + 1)\n\nLUAI_FUNC int luaO_log2 (unsigned int x);\nLUAI_FUNC int luaO_int2fb (unsigned int x);\nLUAI_FUNC int luaO_fb2int (int x);\nLUAI_FUNC int luaO_rawequalObj (const TValue *t1, const TValue *t2);\nLUAI_FUNC int luaO_str2d (const char *s, lua_Number *result);\nLUAI_FUNC const char *luaO_pushvfstring (lua_State *L, const char *fmt,\n                                                       va_list argp);\nLUAI_FUNC const char *luaO_pushfstring (lua_State *L, const char *fmt, ...);\nLUAI_FUNC void luaO_chunkid (char *out, const char *source, size_t len);\n\n\n#endif\n\n"
  },
  {
    "path": "extern/deprecated/redis-2.8.21/deps/lua/src/lopcodes.c",
    "content": "/*\n** $Id: lopcodes.c,v 1.37.1.1 2007/12/27 13:02:25 roberto Exp $\n** See Copyright Notice in lua.h\n*/\n\n\n#define lopcodes_c\n#define LUA_CORE\n\n\n#include \"lopcodes.h\"\n\n\n/* ORDER OP */\n\nconst char *const luaP_opnames[NUM_OPCODES+1] = {\n  \"MOVE\",\n  \"LOADK\",\n  \"LOADBOOL\",\n  \"LOADNIL\",\n  \"GETUPVAL\",\n  \"GETGLOBAL\",\n  \"GETTABLE\",\n  \"SETGLOBAL\",\n  \"SETUPVAL\",\n  \"SETTABLE\",\n  \"NEWTABLE\",\n  \"SELF\",\n  \"ADD\",\n  \"SUB\",\n  \"MUL\",\n  \"DIV\",\n  \"MOD\",\n  \"POW\",\n  \"UNM\",\n  \"NOT\",\n  \"LEN\",\n  \"CONCAT\",\n  \"JMP\",\n  \"EQ\",\n  \"LT\",\n  \"LE\",\n  \"TEST\",\n  \"TESTSET\",\n  \"CALL\",\n  \"TAILCALL\",\n  \"RETURN\",\n  \"FORLOOP\",\n  \"FORPREP\",\n  \"TFORLOOP\",\n  \"SETLIST\",\n  \"CLOSE\",\n  \"CLOSURE\",\n  \"VARARG\",\n  NULL\n};\n\n\n#define opmode(t,a,b,c,m) (((t)<<7) | ((a)<<6) | ((b)<<4) | ((c)<<2) | (m))\n\nconst lu_byte luaP_opmodes[NUM_OPCODES] = {\n/*       T  A    B       C     mode\t\t   opcode\t*/\n  opmode(0, 1, OpArgR, OpArgN, iABC) \t\t/* OP_MOVE */\n ,opmode(0, 1, OpArgK, OpArgN, iABx)\t\t/* OP_LOADK */\n ,opmode(0, 1, OpArgU, OpArgU, iABC)\t\t/* OP_LOADBOOL */\n ,opmode(0, 1, OpArgR, OpArgN, iABC)\t\t/* OP_LOADNIL */\n ,opmode(0, 1, OpArgU, OpArgN, iABC)\t\t/* OP_GETUPVAL */\n ,opmode(0, 1, OpArgK, OpArgN, iABx)\t\t/* OP_GETGLOBAL */\n ,opmode(0, 1, OpArgR, OpArgK, iABC)\t\t/* OP_GETTABLE */\n ,opmode(0, 0, OpArgK, OpArgN, iABx)\t\t/* OP_SETGLOBAL */\n ,opmode(0, 0, OpArgU, OpArgN, iABC)\t\t/* OP_SETUPVAL */\n ,opmode(0, 0, OpArgK, OpArgK, iABC)\t\t/* OP_SETTABLE */\n ,opmode(0, 1, OpArgU, OpArgU, iABC)\t\t/* OP_NEWTABLE */\n ,opmode(0, 1, OpArgR, OpArgK, iABC)\t\t/* OP_SELF */\n ,opmode(0, 1, OpArgK, OpArgK, iABC)\t\t/* OP_ADD */\n ,opmode(0, 1, OpArgK, OpArgK, iABC)\t\t/* OP_SUB */\n ,opmode(0, 1, OpArgK, OpArgK, iABC)\t\t/* OP_MUL */\n ,opmode(0, 1, OpArgK, OpArgK, iABC)\t\t/* OP_DIV */\n ,opmode(0, 1, OpArgK, OpArgK, iABC)\t\t/* OP_MOD */\n ,opmode(0, 1, OpArgK, OpArgK, iABC)\t\t/* OP_POW */\n ,opmode(0, 1, OpArgR, OpArgN, iABC)\t\t/* OP_UNM */\n ,opmode(0, 1, OpArgR, OpArgN, iABC)\t\t/* OP_NOT */\n ,opmode(0, 1, OpArgR, OpArgN, iABC)\t\t/* OP_LEN */\n ,opmode(0, 1, OpArgR, OpArgR, iABC)\t\t/* OP_CONCAT */\n ,opmode(0, 0, OpArgR, OpArgN, iAsBx)\t\t/* OP_JMP */\n ,opmode(1, 0, OpArgK, OpArgK, iABC)\t\t/* OP_EQ */\n ,opmode(1, 0, OpArgK, OpArgK, iABC)\t\t/* OP_LT */\n ,opmode(1, 0, OpArgK, OpArgK, iABC)\t\t/* OP_LE */\n ,opmode(1, 1, OpArgR, OpArgU, iABC)\t\t/* OP_TEST */\n ,opmode(1, 1, OpArgR, OpArgU, iABC)\t\t/* OP_TESTSET */\n ,opmode(0, 1, OpArgU, OpArgU, iABC)\t\t/* OP_CALL */\n ,opmode(0, 1, OpArgU, OpArgU, iABC)\t\t/* OP_TAILCALL */\n ,opmode(0, 0, OpArgU, OpArgN, iABC)\t\t/* OP_RETURN */\n ,opmode(0, 1, OpArgR, OpArgN, iAsBx)\t\t/* OP_FORLOOP */\n ,opmode(0, 1, OpArgR, OpArgN, iAsBx)\t\t/* OP_FORPREP */\n ,opmode(1, 0, OpArgN, OpArgU, iABC)\t\t/* OP_TFORLOOP */\n ,opmode(0, 0, OpArgU, OpArgU, iABC)\t\t/* OP_SETLIST */\n ,opmode(0, 0, OpArgN, OpArgN, iABC)\t\t/* OP_CLOSE */\n ,opmode(0, 1, OpArgU, OpArgN, iABx)\t\t/* OP_CLOSURE */\n ,opmode(0, 1, OpArgU, OpArgN, iABC)\t\t/* OP_VARARG */\n};\n\n"
  },
  {
    "path": "extern/deprecated/redis-2.8.21/deps/lua/src/lopcodes.h",
    "content": "/*\n** $Id: lopcodes.h,v 1.125.1.1 2007/12/27 13:02:25 roberto Exp $\n** Opcodes for Lua virtual machine\n** See Copyright Notice in lua.h\n*/\n\n#ifndef lopcodes_h\n#define lopcodes_h\n\n#include \"llimits.h\"\n\n\n/*===========================================================================\n  We assume that instructions are unsigned numbers.\n  All instructions have an opcode in the first 6 bits.\n  Instructions can have the following fields:\n\t`A' : 8 bits\n\t`B' : 9 bits\n\t`C' : 9 bits\n\t`Bx' : 18 bits (`B' and `C' together)\n\t`sBx' : signed Bx\n\n  A signed argument is represented in excess K; that is, the number\n  value is the unsigned value minus K. K is exactly the maximum value\n  for that argument (so that -max is represented by 0, and +max is\n  represented by 2*max), which is half the maximum for the corresponding\n  unsigned argument.\n===========================================================================*/\n\n\nenum OpMode {iABC, iABx, iAsBx};  /* basic instruction format */\n\n\n/*\n** size and position of opcode arguments.\n*/\n#define SIZE_C\t\t9\n#define SIZE_B\t\t9\n#define SIZE_Bx\t\t(SIZE_C + SIZE_B)\n#define SIZE_A\t\t8\n\n#define SIZE_OP\t\t6\n\n#define POS_OP\t\t0\n#define POS_A\t\t(POS_OP + SIZE_OP)\n#define POS_C\t\t(POS_A + SIZE_A)\n#define POS_B\t\t(POS_C + SIZE_C)\n#define POS_Bx\t\tPOS_C\n\n\n/*\n** limits for opcode arguments.\n** we use (signed) int to manipulate most arguments,\n** so they must fit in LUAI_BITSINT-1 bits (-1 for sign)\n*/\n#if SIZE_Bx < LUAI_BITSINT-1\n#define MAXARG_Bx        ((1<<SIZE_Bx)-1)\n#define MAXARG_sBx        (MAXARG_Bx>>1)         /* `sBx' is signed */\n#else\n#define MAXARG_Bx        MAX_INT\n#define MAXARG_sBx        MAX_INT\n#endif\n\n\n#define MAXARG_A        ((1<<SIZE_A)-1)\n#define MAXARG_B        ((1<<SIZE_B)-1)\n#define MAXARG_C        ((1<<SIZE_C)-1)\n\n\n/* creates a mask with `n' 1 bits at position `p' */\n#define MASK1(n,p)\t((~((~(Instruction)0)<<n))<<p)\n\n/* creates a mask with `n' 0 bits at position `p' */\n#define MASK0(n,p)\t(~MASK1(n,p))\n\n/*\n** the following macros help to manipulate instructions\n*/\n\n#define GET_OPCODE(i)\t(cast(OpCode, ((i)>>POS_OP) & MASK1(SIZE_OP,0)))\n#define SET_OPCODE(i,o)\t((i) = (((i)&MASK0(SIZE_OP,POS_OP)) | \\\n\t\t((cast(Instruction, o)<<POS_OP)&MASK1(SIZE_OP,POS_OP))))\n\n#define GETARG_A(i)\t(cast(int, ((i)>>POS_A) & MASK1(SIZE_A,0)))\n#define SETARG_A(i,u)\t((i) = (((i)&MASK0(SIZE_A,POS_A)) | \\\n\t\t((cast(Instruction, u)<<POS_A)&MASK1(SIZE_A,POS_A))))\n\n#define GETARG_B(i)\t(cast(int, ((i)>>POS_B) & MASK1(SIZE_B,0)))\n#define SETARG_B(i,b)\t((i) = (((i)&MASK0(SIZE_B,POS_B)) | \\\n\t\t((cast(Instruction, b)<<POS_B)&MASK1(SIZE_B,POS_B))))\n\n#define GETARG_C(i)\t(cast(int, ((i)>>POS_C) & MASK1(SIZE_C,0)))\n#define SETARG_C(i,b)\t((i) = (((i)&MASK0(SIZE_C,POS_C)) | \\\n\t\t((cast(Instruction, b)<<POS_C)&MASK1(SIZE_C,POS_C))))\n\n#define GETARG_Bx(i)\t(cast(int, ((i)>>POS_Bx) & MASK1(SIZE_Bx,0)))\n#define SETARG_Bx(i,b)\t((i) = (((i)&MASK0(SIZE_Bx,POS_Bx)) | \\\n\t\t((cast(Instruction, b)<<POS_Bx)&MASK1(SIZE_Bx,POS_Bx))))\n\n#define GETARG_sBx(i)\t(GETARG_Bx(i)-MAXARG_sBx)\n#define SETARG_sBx(i,b)\tSETARG_Bx((i),cast(unsigned int, (b)+MAXARG_sBx))\n\n\n#define CREATE_ABC(o,a,b,c)\t((cast(Instruction, o)<<POS_OP) \\\n\t\t\t| (cast(Instruction, a)<<POS_A) \\\n\t\t\t| (cast(Instruction, b)<<POS_B) \\\n\t\t\t| (cast(Instruction, c)<<POS_C))\n\n#define CREATE_ABx(o,a,bc)\t((cast(Instruction, o)<<POS_OP) \\\n\t\t\t| (cast(Instruction, a)<<POS_A) \\\n\t\t\t| (cast(Instruction, bc)<<POS_Bx))\n\n\n/*\n** Macros to operate RK indices\n*/\n\n/* this bit 1 means constant (0 means register) */\n#define BITRK\t\t(1 << (SIZE_B - 1))\n\n/* test whether value is a constant */\n#define ISK(x)\t\t((x) & BITRK)\n\n/* gets the index of the constant */\n#define INDEXK(r)\t((int)(r) & ~BITRK)\n\n#define MAXINDEXRK\t(BITRK - 1)\n\n/* code a constant index as a RK value */\n#define RKASK(x)\t((x) | BITRK)\n\n\n/*\n** invalid register that fits in 8 bits\n*/\n#define NO_REG\t\tMAXARG_A\n\n\n/*\n** R(x) - register\n** Kst(x) - constant (in constant table)\n** RK(x) == if ISK(x) then Kst(INDEXK(x)) else R(x)\n*/\n\n\n/*\n** grep \"ORDER OP\" if you change these enums\n*/\n\ntypedef enum {\n/*----------------------------------------------------------------------\nname\t\targs\tdescription\n------------------------------------------------------------------------*/\nOP_MOVE,/*\tA B\tR(A) := R(B)\t\t\t\t\t*/\nOP_LOADK,/*\tA Bx\tR(A) := Kst(Bx)\t\t\t\t\t*/\nOP_LOADBOOL,/*\tA B C\tR(A) := (Bool)B; if (C) pc++\t\t\t*/\nOP_LOADNIL,/*\tA B\tR(A) := ... := R(B) := nil\t\t\t*/\nOP_GETUPVAL,/*\tA B\tR(A) := UpValue[B]\t\t\t\t*/\n\nOP_GETGLOBAL,/*\tA Bx\tR(A) := Gbl[Kst(Bx)]\t\t\t\t*/\nOP_GETTABLE,/*\tA B C\tR(A) := R(B)[RK(C)]\t\t\t\t*/\n\nOP_SETGLOBAL,/*\tA Bx\tGbl[Kst(Bx)] := R(A)\t\t\t\t*/\nOP_SETUPVAL,/*\tA B\tUpValue[B] := R(A)\t\t\t\t*/\nOP_SETTABLE,/*\tA B C\tR(A)[RK(B)] := RK(C)\t\t\t\t*/\n\nOP_NEWTABLE,/*\tA B C\tR(A) := {} (size = B,C)\t\t\t\t*/\n\nOP_SELF,/*\tA B C\tR(A+1) := R(B); R(A) := R(B)[RK(C)]\t\t*/\n\nOP_ADD,/*\tA B C\tR(A) := RK(B) + RK(C)\t\t\t\t*/\nOP_SUB,/*\tA B C\tR(A) := RK(B) - RK(C)\t\t\t\t*/\nOP_MUL,/*\tA B C\tR(A) := RK(B) * RK(C)\t\t\t\t*/\nOP_DIV,/*\tA B C\tR(A) := RK(B) / RK(C)\t\t\t\t*/\nOP_MOD,/*\tA B C\tR(A) := RK(B) % RK(C)\t\t\t\t*/\nOP_POW,/*\tA B C\tR(A) := RK(B) ^ RK(C)\t\t\t\t*/\nOP_UNM,/*\tA B\tR(A) := -R(B)\t\t\t\t\t*/\nOP_NOT,/*\tA B\tR(A) := not R(B)\t\t\t\t*/\nOP_LEN,/*\tA B\tR(A) := length of R(B)\t\t\t\t*/\n\nOP_CONCAT,/*\tA B C\tR(A) := R(B).. ... ..R(C)\t\t\t*/\n\nOP_JMP,/*\tsBx\tpc+=sBx\t\t\t\t\t*/\n\nOP_EQ,/*\tA B C\tif ((RK(B) == RK(C)) ~= A) then pc++\t\t*/\nOP_LT,/*\tA B C\tif ((RK(B) <  RK(C)) ~= A) then pc++  \t\t*/\nOP_LE,/*\tA B C\tif ((RK(B) <= RK(C)) ~= A) then pc++  \t\t*/\n\nOP_TEST,/*\tA C\tif not (R(A) <=> C) then pc++\t\t\t*/ \nOP_TESTSET,/*\tA B C\tif (R(B) <=> C) then R(A) := R(B) else pc++\t*/ \n\nOP_CALL,/*\tA B C\tR(A), ... ,R(A+C-2) := R(A)(R(A+1), ... ,R(A+B-1)) */\nOP_TAILCALL,/*\tA B C\treturn R(A)(R(A+1), ... ,R(A+B-1))\t\t*/\nOP_RETURN,/*\tA B\treturn R(A), ... ,R(A+B-2)\t(see note)\t*/\n\nOP_FORLOOP,/*\tA sBx\tR(A)+=R(A+2);\n\t\t\tif R(A) <?= R(A+1) then { pc+=sBx; R(A+3)=R(A) }*/\nOP_FORPREP,/*\tA sBx\tR(A)-=R(A+2); pc+=sBx\t\t\t\t*/\n\nOP_TFORLOOP,/*\tA C\tR(A+3), ... ,R(A+2+C) := R(A)(R(A+1), R(A+2)); \n                        if R(A+3) ~= nil then R(A+2)=R(A+3) else pc++\t*/ \nOP_SETLIST,/*\tA B C\tR(A)[(C-1)*FPF+i] := R(A+i), 1 <= i <= B\t*/\n\nOP_CLOSE,/*\tA \tclose all variables in the stack up to (>=) R(A)*/\nOP_CLOSURE,/*\tA Bx\tR(A) := closure(KPROTO[Bx], R(A), ... ,R(A+n))\t*/\n\nOP_VARARG/*\tA B\tR(A), R(A+1), ..., R(A+B-1) = vararg\t\t*/\n} OpCode;\n\n\n#define NUM_OPCODES\t(cast(int, OP_VARARG) + 1)\n\n\n\n/*===========================================================================\n  Notes:\n  (*) In OP_CALL, if (B == 0) then B = top. C is the number of returns - 1,\n      and can be 0: OP_CALL then sets `top' to last_result+1, so\n      next open instruction (OP_CALL, OP_RETURN, OP_SETLIST) may use `top'.\n\n  (*) In OP_VARARG, if (B == 0) then use actual number of varargs and\n      set top (like in OP_CALL with C == 0).\n\n  (*) In OP_RETURN, if (B == 0) then return up to `top'\n\n  (*) In OP_SETLIST, if (B == 0) then B = `top';\n      if (C == 0) then next `instruction' is real C\n\n  (*) For comparisons, A specifies what condition the test should accept\n      (true or false).\n\n  (*) All `skips' (pc++) assume that next instruction is a jump\n===========================================================================*/\n\n\n/*\n** masks for instruction properties. The format is:\n** bits 0-1: op mode\n** bits 2-3: C arg mode\n** bits 4-5: B arg mode\n** bit 6: instruction set register A\n** bit 7: operator is a test\n*/  \n\nenum OpArgMask {\n  OpArgN,  /* argument is not used */\n  OpArgU,  /* argument is used */\n  OpArgR,  /* argument is a register or a jump offset */\n  OpArgK   /* argument is a constant or register/constant */\n};\n\nLUAI_DATA const lu_byte luaP_opmodes[NUM_OPCODES];\n\n#define getOpMode(m)\t(cast(enum OpMode, luaP_opmodes[m] & 3))\n#define getBMode(m)\t(cast(enum OpArgMask, (luaP_opmodes[m] >> 4) & 3))\n#define getCMode(m)\t(cast(enum OpArgMask, (luaP_opmodes[m] >> 2) & 3))\n#define testAMode(m)\t(luaP_opmodes[m] & (1 << 6))\n#define testTMode(m)\t(luaP_opmodes[m] & (1 << 7))\n\n\nLUAI_DATA const char *const luaP_opnames[NUM_OPCODES+1];  /* opcode names */\n\n\n/* number of list items to accumulate before a SETLIST instruction */\n#define LFIELDS_PER_FLUSH\t50\n\n\n#endif\n"
  },
  {
    "path": "extern/deprecated/redis-2.8.21/deps/lua/src/loslib.c",
    "content": "/*\n** $Id: loslib.c,v 1.19.1.3 2008/01/18 16:38:18 roberto Exp $\n** Standard Operating System library\n** See Copyright Notice in lua.h\n*/\n\n\n#include <errno.h>\n#include <locale.h>\n#include <stdlib.h>\n#include <string.h>\n#include <time.h>\n\n#define loslib_c\n#define LUA_LIB\n\n#include \"lua.h\"\n\n#include \"lauxlib.h\"\n#include \"lualib.h\"\n\n\nstatic int os_pushresult (lua_State *L, int i, const char *filename) {\n  int en = errno;  /* calls to Lua API may change this value */\n  if (i) {\n    lua_pushboolean(L, 1);\n    return 1;\n  }\n  else {\n    lua_pushnil(L);\n    lua_pushfstring(L, \"%s: %s\", filename, strerror(en));\n    lua_pushinteger(L, en);\n    return 3;\n  }\n}\n\n\nstatic int os_execute (lua_State *L) {\n  lua_pushinteger(L, system(luaL_optstring(L, 1, NULL)));\n  return 1;\n}\n\n\nstatic int os_remove (lua_State *L) {\n  const char *filename = luaL_checkstring(L, 1);\n  return os_pushresult(L, remove(filename) == 0, filename);\n}\n\n\nstatic int os_rename (lua_State *L) {\n  const char *fromname = luaL_checkstring(L, 1);\n  const char *toname = luaL_checkstring(L, 2);\n  return os_pushresult(L, rename(fromname, toname) == 0, fromname);\n}\n\n\nstatic int os_tmpname (lua_State *L) {\n  char buff[LUA_TMPNAMBUFSIZE];\n  int err;\n  lua_tmpnam(buff, err);\n  if (err)\n    return luaL_error(L, \"unable to generate a unique filename\");\n  lua_pushstring(L, buff);\n  return 1;\n}\n\n\nstatic int os_getenv (lua_State *L) {\n  lua_pushstring(L, getenv(luaL_checkstring(L, 1)));  /* if NULL push nil */\n  return 1;\n}\n\n\nstatic int os_clock (lua_State *L) {\n  lua_pushnumber(L, ((lua_Number)clock())/(lua_Number)CLOCKS_PER_SEC);\n  return 1;\n}\n\n\n/*\n** {======================================================\n** Time/Date operations\n** { year=%Y, month=%m, day=%d, hour=%H, min=%M, sec=%S,\n**   wday=%w+1, yday=%j, isdst=? }\n** =======================================================\n*/\n\nstatic void setfield (lua_State *L, const char *key, int value) {\n  lua_pushinteger(L, value);\n  lua_setfield(L, -2, key);\n}\n\nstatic void setboolfield (lua_State *L, const char *key, int value) {\n  if (value < 0)  /* undefined? */\n    return;  /* does not set field */\n  lua_pushboolean(L, value);\n  lua_setfield(L, -2, key);\n}\n\nstatic int getboolfield (lua_State *L, const char *key) {\n  int res;\n  lua_getfield(L, -1, key);\n  res = lua_isnil(L, -1) ? -1 : lua_toboolean(L, -1);\n  lua_pop(L, 1);\n  return res;\n}\n\n\nstatic int getfield (lua_State *L, const char *key, int d) {\n  int res;\n  lua_getfield(L, -1, key);\n  if (lua_isnumber(L, -1))\n    res = (int)lua_tointeger(L, -1);\n  else {\n    if (d < 0)\n      return luaL_error(L, \"field \" LUA_QS \" missing in date table\", key);\n    res = d;\n  }\n  lua_pop(L, 1);\n  return res;\n}\n\n\nstatic int os_date (lua_State *L) {\n  const char *s = luaL_optstring(L, 1, \"%c\");\n  time_t t = luaL_opt(L, (time_t)luaL_checknumber, 2, time(NULL));\n  struct tm *stm;\n  if (*s == '!') {  /* UTC? */\n    stm = gmtime(&t);\n    s++;  /* skip `!' */\n  }\n  else\n    stm = localtime(&t);\n  if (stm == NULL)  /* invalid date? */\n    lua_pushnil(L);\n  else if (strcmp(s, \"*t\") == 0) {\n    lua_createtable(L, 0, 9);  /* 9 = number of fields */\n    setfield(L, \"sec\", stm->tm_sec);\n    setfield(L, \"min\", stm->tm_min);\n    setfield(L, \"hour\", stm->tm_hour);\n    setfield(L, \"day\", stm->tm_mday);\n    setfield(L, \"month\", stm->tm_mon+1);\n    setfield(L, \"year\", stm->tm_year+1900);\n    setfield(L, \"wday\", stm->tm_wday+1);\n    setfield(L, \"yday\", stm->tm_yday+1);\n    setboolfield(L, \"isdst\", stm->tm_isdst);\n  }\n  else {\n    char cc[3];\n    luaL_Buffer b;\n    cc[0] = '%'; cc[2] = '\\0';\n    luaL_buffinit(L, &b);\n    for (; *s; s++) {\n      if (*s != '%' || *(s + 1) == '\\0')  /* no conversion specifier? */\n        luaL_addchar(&b, *s);\n      else {\n        size_t reslen;\n        char buff[200];  /* should be big enough for any conversion result */\n        cc[1] = *(++s);\n        reslen = strftime(buff, sizeof(buff), cc, stm);\n        luaL_addlstring(&b, buff, reslen);\n      }\n    }\n    luaL_pushresult(&b);\n  }\n  return 1;\n}\n\n\nstatic int os_time (lua_State *L) {\n  time_t t;\n  if (lua_isnoneornil(L, 1))  /* called without args? */\n    t = time(NULL);  /* get current time */\n  else {\n    struct tm ts;\n    luaL_checktype(L, 1, LUA_TTABLE);\n    lua_settop(L, 1);  /* make sure table is at the top */\n    ts.tm_sec = getfield(L, \"sec\", 0);\n    ts.tm_min = getfield(L, \"min\", 0);\n    ts.tm_hour = getfield(L, \"hour\", 12);\n    ts.tm_mday = getfield(L, \"day\", -1);\n    ts.tm_mon = getfield(L, \"month\", -1) - 1;\n    ts.tm_year = getfield(L, \"year\", -1) - 1900;\n    ts.tm_isdst = getboolfield(L, \"isdst\");\n    t = mktime(&ts);\n  }\n  if (t == (time_t)(-1))\n    lua_pushnil(L);\n  else\n    lua_pushnumber(L, (lua_Number)t);\n  return 1;\n}\n\n\nstatic int os_difftime (lua_State *L) {\n  lua_pushnumber(L, difftime((time_t)(luaL_checknumber(L, 1)),\n                             (time_t)(luaL_optnumber(L, 2, 0))));\n  return 1;\n}\n\n/* }====================================================== */\n\n\nstatic int os_setlocale (lua_State *L) {\n  static const int cat[] = {LC_ALL, LC_COLLATE, LC_CTYPE, LC_MONETARY,\n                      LC_NUMERIC, LC_TIME};\n  static const char *const catnames[] = {\"all\", \"collate\", \"ctype\", \"monetary\",\n     \"numeric\", \"time\", NULL};\n  const char *l = luaL_optstring(L, 1, NULL);\n  int op = luaL_checkoption(L, 2, \"all\", catnames);\n  lua_pushstring(L, setlocale(cat[op], l));\n  return 1;\n}\n\n\nstatic int os_exit (lua_State *L) {\n  exit(luaL_optint(L, 1, EXIT_SUCCESS));\n}\n\nstatic const luaL_Reg syslib[] = {\n  {\"clock\",     os_clock},\n  {\"date\",      os_date},\n  {\"difftime\",  os_difftime},\n  {\"execute\",   os_execute},\n  {\"exit\",      os_exit},\n  {\"getenv\",    os_getenv},\n  {\"remove\",    os_remove},\n  {\"rename\",    os_rename},\n  {\"setlocale\", os_setlocale},\n  {\"time\",      os_time},\n  {\"tmpname\",   os_tmpname},\n  {NULL, NULL}\n};\n\n/* }====================================================== */\n\n\n\nLUALIB_API int luaopen_os (lua_State *L) {\n  luaL_register(L, LUA_OSLIBNAME, syslib);\n  return 1;\n}\n\n"
  },
  {
    "path": "extern/deprecated/redis-2.8.21/deps/lua/src/lparser.c",
    "content": "/*\n** $Id: lparser.c,v 2.42.1.4 2011/10/21 19:31:42 roberto Exp $\n** Lua Parser\n** See Copyright Notice in lua.h\n*/\n\n\n#include <string.h>\n\n#define lparser_c\n#define LUA_CORE\n\n#include \"lua.h\"\n\n#include \"lcode.h\"\n#include \"ldebug.h\"\n#include \"ldo.h\"\n#include \"lfunc.h\"\n#include \"llex.h\"\n#include \"lmem.h\"\n#include \"lobject.h\"\n#include \"lopcodes.h\"\n#include \"lparser.h\"\n#include \"lstate.h\"\n#include \"lstring.h\"\n#include \"ltable.h\"\n\n\n\n#define hasmultret(k)\t\t((k) == VCALL || (k) == VVARARG)\n\n#define getlocvar(fs, i)\t((fs)->f->locvars[(fs)->actvar[i]])\n\n#define luaY_checklimit(fs,v,l,m)\tif ((v)>(l)) errorlimit(fs,l,m)\n\n\n/*\n** nodes for block list (list of active blocks)\n*/\ntypedef struct BlockCnt {\n  struct BlockCnt *previous;  /* chain */\n  int breaklist;  /* list of jumps out of this loop */\n  lu_byte nactvar;  /* # active locals outside the breakable structure */\n  lu_byte upval;  /* true if some variable in the block is an upvalue */\n  lu_byte isbreakable;  /* true if `block' is a loop */\n} BlockCnt;\n\n\n\n/*\n** prototypes for recursive non-terminal functions\n*/\nstatic void chunk (LexState *ls);\nstatic void expr (LexState *ls, expdesc *v);\n\n\nstatic void anchor_token (LexState *ls) {\n  if (ls->t.token == TK_NAME || ls->t.token == TK_STRING) {\n    TString *ts = ls->t.seminfo.ts;\n    luaX_newstring(ls, getstr(ts), ts->tsv.len);\n  }\n}\n\n\nstatic void error_expected (LexState *ls, int token) {\n  luaX_syntaxerror(ls,\n      luaO_pushfstring(ls->L, LUA_QS \" expected\", luaX_token2str(ls, token)));\n}\n\n\nstatic void errorlimit (FuncState *fs, int limit, const char *what) {\n  const char *msg = (fs->f->linedefined == 0) ?\n    luaO_pushfstring(fs->L, \"main function has more than %d %s\", limit, what) :\n    luaO_pushfstring(fs->L, \"function at line %d has more than %d %s\",\n                            fs->f->linedefined, limit, what);\n  luaX_lexerror(fs->ls, msg, 0);\n}\n\n\nstatic int testnext (LexState *ls, int c) {\n  if (ls->t.token == c) {\n    luaX_next(ls);\n    return 1;\n  }\n  else return 0;\n}\n\n\nstatic void check (LexState *ls, int c) {\n  if (ls->t.token != c)\n    error_expected(ls, c);\n}\n\nstatic void checknext (LexState *ls, int c) {\n  check(ls, c);\n  luaX_next(ls);\n}\n\n\n#define check_condition(ls,c,msg)\t{ if (!(c)) luaX_syntaxerror(ls, msg); }\n\n\n\nstatic void check_match (LexState *ls, int what, int who, int where) {\n  if (!testnext(ls, what)) {\n    if (where == ls->linenumber)\n      error_expected(ls, what);\n    else {\n      luaX_syntaxerror(ls, luaO_pushfstring(ls->L,\n             LUA_QS \" expected (to close \" LUA_QS \" at line %d)\",\n              luaX_token2str(ls, what), luaX_token2str(ls, who), where));\n    }\n  }\n}\n\n\nstatic TString *str_checkname (LexState *ls) {\n  TString *ts;\n  check(ls, TK_NAME);\n  ts = ls->t.seminfo.ts;\n  luaX_next(ls);\n  return ts;\n}\n\n\nstatic void init_exp (expdesc *e, expkind k, int i) {\n  e->f = e->t = NO_JUMP;\n  e->k = k;\n  e->u.s.info = i;\n}\n\n\nstatic void codestring (LexState *ls, expdesc *e, TString *s) {\n  init_exp(e, VK, luaK_stringK(ls->fs, s));\n}\n\n\nstatic void checkname(LexState *ls, expdesc *e) {\n  codestring(ls, e, str_checkname(ls));\n}\n\n\nstatic int registerlocalvar (LexState *ls, TString *varname) {\n  FuncState *fs = ls->fs;\n  Proto *f = fs->f;\n  int oldsize = f->sizelocvars;\n  luaM_growvector(ls->L, f->locvars, fs->nlocvars, f->sizelocvars,\n                  LocVar, SHRT_MAX, \"too many local variables\");\n  while (oldsize < f->sizelocvars) f->locvars[oldsize++].varname = NULL;\n  f->locvars[fs->nlocvars].varname = varname;\n  luaC_objbarrier(ls->L, f, varname);\n  return fs->nlocvars++;\n}\n\n\n#define new_localvarliteral(ls,v,n) \\\n  new_localvar(ls, luaX_newstring(ls, \"\" v, (sizeof(v)/sizeof(char))-1), n)\n\n\nstatic void new_localvar (LexState *ls, TString *name, int n) {\n  FuncState *fs = ls->fs;\n  luaY_checklimit(fs, fs->nactvar+n+1, LUAI_MAXVARS, \"local variables\");\n  fs->actvar[fs->nactvar+n] = cast(unsigned short, registerlocalvar(ls, name));\n}\n\n\nstatic void adjustlocalvars (LexState *ls, int nvars) {\n  FuncState *fs = ls->fs;\n  fs->nactvar = cast_byte(fs->nactvar + nvars);\n  for (; nvars; nvars--) {\n    getlocvar(fs, fs->nactvar - nvars).startpc = fs->pc;\n  }\n}\n\n\nstatic void removevars (LexState *ls, int tolevel) {\n  FuncState *fs = ls->fs;\n  while (fs->nactvar > tolevel)\n    getlocvar(fs, --fs->nactvar).endpc = fs->pc;\n}\n\n\nstatic int indexupvalue (FuncState *fs, TString *name, expdesc *v) {\n  int i;\n  Proto *f = fs->f;\n  int oldsize = f->sizeupvalues;\n  for (i=0; i<f->nups; i++) {\n    if (fs->upvalues[i].k == v->k && fs->upvalues[i].info == v->u.s.info) {\n      lua_assert(f->upvalues[i] == name);\n      return i;\n    }\n  }\n  /* new one */\n  luaY_checklimit(fs, f->nups + 1, LUAI_MAXUPVALUES, \"upvalues\");\n  luaM_growvector(fs->L, f->upvalues, f->nups, f->sizeupvalues,\n                  TString *, MAX_INT, \"\");\n  while (oldsize < f->sizeupvalues) f->upvalues[oldsize++] = NULL;\n  f->upvalues[f->nups] = name;\n  luaC_objbarrier(fs->L, f, name);\n  lua_assert(v->k == VLOCAL || v->k == VUPVAL);\n  fs->upvalues[f->nups].k = cast_byte(v->k);\n  fs->upvalues[f->nups].info = cast_byte(v->u.s.info);\n  return f->nups++;\n}\n\n\nstatic int searchvar (FuncState *fs, TString *n) {\n  int i;\n  for (i=fs->nactvar-1; i >= 0; i--) {\n    if (n == getlocvar(fs, i).varname)\n      return i;\n  }\n  return -1;  /* not found */\n}\n\n\nstatic void markupval (FuncState *fs, int level) {\n  BlockCnt *bl = fs->bl;\n  while (bl && bl->nactvar > level) bl = bl->previous;\n  if (bl) bl->upval = 1;\n}\n\n\nstatic int singlevaraux (FuncState *fs, TString *n, expdesc *var, int base) {\n  if (fs == NULL) {  /* no more levels? */\n    init_exp(var, VGLOBAL, NO_REG);  /* default is global variable */\n    return VGLOBAL;\n  }\n  else {\n    int v = searchvar(fs, n);  /* look up at current level */\n    if (v >= 0) {\n      init_exp(var, VLOCAL, v);\n      if (!base)\n        markupval(fs, v);  /* local will be used as an upval */\n      return VLOCAL;\n    }\n    else {  /* not found at current level; try upper one */\n      if (singlevaraux(fs->prev, n, var, 0) == VGLOBAL)\n        return VGLOBAL;\n      var->u.s.info = indexupvalue(fs, n, var);  /* else was LOCAL or UPVAL */\n      var->k = VUPVAL;  /* upvalue in this level */\n      return VUPVAL;\n    }\n  }\n}\n\n\nstatic void singlevar (LexState *ls, expdesc *var) {\n  TString *varname = str_checkname(ls);\n  FuncState *fs = ls->fs;\n  if (singlevaraux(fs, varname, var, 1) == VGLOBAL)\n    var->u.s.info = luaK_stringK(fs, varname);  /* info points to global name */\n}\n\n\nstatic void adjust_assign (LexState *ls, int nvars, int nexps, expdesc *e) {\n  FuncState *fs = ls->fs;\n  int extra = nvars - nexps;\n  if (hasmultret(e->k)) {\n    extra++;  /* includes call itself */\n    if (extra < 0) extra = 0;\n    luaK_setreturns(fs, e, extra);  /* last exp. provides the difference */\n    if (extra > 1) luaK_reserveregs(fs, extra-1);\n  }\n  else {\n    if (e->k != VVOID) luaK_exp2nextreg(fs, e);  /* close last expression */\n    if (extra > 0) {\n      int reg = fs->freereg;\n      luaK_reserveregs(fs, extra);\n      luaK_nil(fs, reg, extra);\n    }\n  }\n}\n\n\nstatic void enterlevel (LexState *ls) {\n  if (++ls->L->nCcalls > LUAI_MAXCCALLS)\n\tluaX_lexerror(ls, \"chunk has too many syntax levels\", 0);\n}\n\n\n#define leavelevel(ls)\t((ls)->L->nCcalls--)\n\n\nstatic void enterblock (FuncState *fs, BlockCnt *bl, lu_byte isbreakable) {\n  bl->breaklist = NO_JUMP;\n  bl->isbreakable = isbreakable;\n  bl->nactvar = fs->nactvar;\n  bl->upval = 0;\n  bl->previous = fs->bl;\n  fs->bl = bl;\n  lua_assert(fs->freereg == fs->nactvar);\n}\n\n\nstatic void leaveblock (FuncState *fs) {\n  BlockCnt *bl = fs->bl;\n  fs->bl = bl->previous;\n  removevars(fs->ls, bl->nactvar);\n  if (bl->upval)\n    luaK_codeABC(fs, OP_CLOSE, bl->nactvar, 0, 0);\n  /* a block either controls scope or breaks (never both) */\n  lua_assert(!bl->isbreakable || !bl->upval);\n  lua_assert(bl->nactvar == fs->nactvar);\n  fs->freereg = fs->nactvar;  /* free registers */\n  luaK_patchtohere(fs, bl->breaklist);\n}\n\n\nstatic void pushclosure (LexState *ls, FuncState *func, expdesc *v) {\n  FuncState *fs = ls->fs;\n  Proto *f = fs->f;\n  int oldsize = f->sizep;\n  int i;\n  luaM_growvector(ls->L, f->p, fs->np, f->sizep, Proto *,\n                  MAXARG_Bx, \"constant table overflow\");\n  while (oldsize < f->sizep) f->p[oldsize++] = NULL;\n  f->p[fs->np++] = func->f;\n  luaC_objbarrier(ls->L, f, func->f);\n  init_exp(v, VRELOCABLE, luaK_codeABx(fs, OP_CLOSURE, 0, fs->np-1));\n  for (i=0; i<func->f->nups; i++) {\n    OpCode o = (func->upvalues[i].k == VLOCAL) ? OP_MOVE : OP_GETUPVAL;\n    luaK_codeABC(fs, o, 0, func->upvalues[i].info, 0);\n  }\n}\n\n\nstatic void open_func (LexState *ls, FuncState *fs) {\n  lua_State *L = ls->L;\n  Proto *f = luaF_newproto(L);\n  fs->f = f;\n  fs->prev = ls->fs;  /* linked list of funcstates */\n  fs->ls = ls;\n  fs->L = L;\n  ls->fs = fs;\n  fs->pc = 0;\n  fs->lasttarget = -1;\n  fs->jpc = NO_JUMP;\n  fs->freereg = 0;\n  fs->nk = 0;\n  fs->np = 0;\n  fs->nlocvars = 0;\n  fs->nactvar = 0;\n  fs->bl = NULL;\n  f->source = ls->source;\n  f->maxstacksize = 2;  /* registers 0/1 are always valid */\n  fs->h = luaH_new(L, 0, 0);\n  /* anchor table of constants and prototype (to avoid being collected) */\n  sethvalue2s(L, L->top, fs->h);\n  incr_top(L);\n  setptvalue2s(L, L->top, f);\n  incr_top(L);\n}\n\n\nstatic void close_func (LexState *ls) {\n  lua_State *L = ls->L;\n  FuncState *fs = ls->fs;\n  Proto *f = fs->f;\n  removevars(ls, 0);\n  luaK_ret(fs, 0, 0);  /* final return */\n  luaM_reallocvector(L, f->code, f->sizecode, fs->pc, Instruction);\n  f->sizecode = fs->pc;\n  luaM_reallocvector(L, f->lineinfo, f->sizelineinfo, fs->pc, int);\n  f->sizelineinfo = fs->pc;\n  luaM_reallocvector(L, f->k, f->sizek, fs->nk, TValue);\n  f->sizek = fs->nk;\n  luaM_reallocvector(L, f->p, f->sizep, fs->np, Proto *);\n  f->sizep = fs->np;\n  luaM_reallocvector(L, f->locvars, f->sizelocvars, fs->nlocvars, LocVar);\n  f->sizelocvars = fs->nlocvars;\n  luaM_reallocvector(L, f->upvalues, f->sizeupvalues, f->nups, TString *);\n  f->sizeupvalues = f->nups;\n  lua_assert(luaG_checkcode(f));\n  lua_assert(fs->bl == NULL);\n  ls->fs = fs->prev;\n  /* last token read was anchored in defunct function; must reanchor it */\n  if (fs) anchor_token(ls);\n  L->top -= 2;  /* remove table and prototype from the stack */\n}\n\n\nProto *luaY_parser (lua_State *L, ZIO *z, Mbuffer *buff, const char *name) {\n  struct LexState lexstate;\n  struct FuncState funcstate;\n  lexstate.buff = buff;\n  luaX_setinput(L, &lexstate, z, luaS_new(L, name));\n  open_func(&lexstate, &funcstate);\n  funcstate.f->is_vararg = VARARG_ISVARARG;  /* main func. is always vararg */\n  luaX_next(&lexstate);  /* read first token */\n  chunk(&lexstate);\n  check(&lexstate, TK_EOS);\n  close_func(&lexstate);\n  lua_assert(funcstate.prev == NULL);\n  lua_assert(funcstate.f->nups == 0);\n  lua_assert(lexstate.fs == NULL);\n  return funcstate.f;\n}\n\n\n\n/*============================================================*/\n/* GRAMMAR RULES */\n/*============================================================*/\n\n\nstatic void field (LexState *ls, expdesc *v) {\n  /* field -> ['.' | ':'] NAME */\n  FuncState *fs = ls->fs;\n  expdesc key;\n  luaK_exp2anyreg(fs, v);\n  luaX_next(ls);  /* skip the dot or colon */\n  checkname(ls, &key);\n  luaK_indexed(fs, v, &key);\n}\n\n\nstatic void yindex (LexState *ls, expdesc *v) {\n  /* index -> '[' expr ']' */\n  luaX_next(ls);  /* skip the '[' */\n  expr(ls, v);\n  luaK_exp2val(ls->fs, v);\n  checknext(ls, ']');\n}\n\n\n/*\n** {======================================================================\n** Rules for Constructors\n** =======================================================================\n*/\n\n\nstruct ConsControl {\n  expdesc v;  /* last list item read */\n  expdesc *t;  /* table descriptor */\n  int nh;  /* total number of `record' elements */\n  int na;  /* total number of array elements */\n  int tostore;  /* number of array elements pending to be stored */\n};\n\n\nstatic void recfield (LexState *ls, struct ConsControl *cc) {\n  /* recfield -> (NAME | `['exp1`]') = exp1 */\n  FuncState *fs = ls->fs;\n  int reg = ls->fs->freereg;\n  expdesc key, val;\n  int rkkey;\n  if (ls->t.token == TK_NAME) {\n    luaY_checklimit(fs, cc->nh, MAX_INT, \"items in a constructor\");\n    checkname(ls, &key);\n  }\n  else  /* ls->t.token == '[' */\n    yindex(ls, &key);\n  cc->nh++;\n  checknext(ls, '=');\n  rkkey = luaK_exp2RK(fs, &key);\n  expr(ls, &val);\n  luaK_codeABC(fs, OP_SETTABLE, cc->t->u.s.info, rkkey, luaK_exp2RK(fs, &val));\n  fs->freereg = reg;  /* free registers */\n}\n\n\nstatic void closelistfield (FuncState *fs, struct ConsControl *cc) {\n  if (cc->v.k == VVOID) return;  /* there is no list item */\n  luaK_exp2nextreg(fs, &cc->v);\n  cc->v.k = VVOID;\n  if (cc->tostore == LFIELDS_PER_FLUSH) {\n    luaK_setlist(fs, cc->t->u.s.info, cc->na, cc->tostore);  /* flush */\n    cc->tostore = 0;  /* no more items pending */\n  }\n}\n\n\nstatic void lastlistfield (FuncState *fs, struct ConsControl *cc) {\n  if (cc->tostore == 0) return;\n  if (hasmultret(cc->v.k)) {\n    luaK_setmultret(fs, &cc->v);\n    luaK_setlist(fs, cc->t->u.s.info, cc->na, LUA_MULTRET);\n    cc->na--;  /* do not count last expression (unknown number of elements) */\n  }\n  else {\n    if (cc->v.k != VVOID)\n      luaK_exp2nextreg(fs, &cc->v);\n    luaK_setlist(fs, cc->t->u.s.info, cc->na, cc->tostore);\n  }\n}\n\n\nstatic void listfield (LexState *ls, struct ConsControl *cc) {\n  expr(ls, &cc->v);\n  luaY_checklimit(ls->fs, cc->na, MAX_INT, \"items in a constructor\");\n  cc->na++;\n  cc->tostore++;\n}\n\n\nstatic void constructor (LexState *ls, expdesc *t) {\n  /* constructor -> ?? */\n  FuncState *fs = ls->fs;\n  int line = ls->linenumber;\n  int pc = luaK_codeABC(fs, OP_NEWTABLE, 0, 0, 0);\n  struct ConsControl cc;\n  cc.na = cc.nh = cc.tostore = 0;\n  cc.t = t;\n  init_exp(t, VRELOCABLE, pc);\n  init_exp(&cc.v, VVOID, 0);  /* no value (yet) */\n  luaK_exp2nextreg(ls->fs, t);  /* fix it at stack top (for gc) */\n  checknext(ls, '{');\n  do {\n    lua_assert(cc.v.k == VVOID || cc.tostore > 0);\n    if (ls->t.token == '}') break;\n    closelistfield(fs, &cc);\n    switch(ls->t.token) {\n      case TK_NAME: {  /* may be listfields or recfields */\n        luaX_lookahead(ls);\n        if (ls->lookahead.token != '=')  /* expression? */\n          listfield(ls, &cc);\n        else\n          recfield(ls, &cc);\n        break;\n      }\n      case '[': {  /* constructor_item -> recfield */\n        recfield(ls, &cc);\n        break;\n      }\n      default: {  /* constructor_part -> listfield */\n        listfield(ls, &cc);\n        break;\n      }\n    }\n  } while (testnext(ls, ',') || testnext(ls, ';'));\n  check_match(ls, '}', '{', line);\n  lastlistfield(fs, &cc);\n  SETARG_B(fs->f->code[pc], luaO_int2fb(cc.na)); /* set initial array size */\n  SETARG_C(fs->f->code[pc], luaO_int2fb(cc.nh));  /* set initial table size */\n}\n\n/* }====================================================================== */\n\n\n\nstatic void parlist (LexState *ls) {\n  /* parlist -> [ param { `,' param } ] */\n  FuncState *fs = ls->fs;\n  Proto *f = fs->f;\n  int nparams = 0;\n  f->is_vararg = 0;\n  if (ls->t.token != ')') {  /* is `parlist' not empty? */\n    do {\n      switch (ls->t.token) {\n        case TK_NAME: {  /* param -> NAME */\n          new_localvar(ls, str_checkname(ls), nparams++);\n          break;\n        }\n        case TK_DOTS: {  /* param -> `...' */\n          luaX_next(ls);\n#if defined(LUA_COMPAT_VARARG)\n          /* use `arg' as default name */\n          new_localvarliteral(ls, \"arg\", nparams++);\n          f->is_vararg = VARARG_HASARG | VARARG_NEEDSARG;\n#endif\n          f->is_vararg |= VARARG_ISVARARG;\n          break;\n        }\n        default: luaX_syntaxerror(ls, \"<name> or \" LUA_QL(\"...\") \" expected\");\n      }\n    } while (!f->is_vararg && testnext(ls, ','));\n  }\n  adjustlocalvars(ls, nparams);\n  f->numparams = cast_byte(fs->nactvar - (f->is_vararg & VARARG_HASARG));\n  luaK_reserveregs(fs, fs->nactvar);  /* reserve register for parameters */\n}\n\n\nstatic void body (LexState *ls, expdesc *e, int needself, int line) {\n  /* body ->  `(' parlist `)' chunk END */\n  FuncState new_fs;\n  open_func(ls, &new_fs);\n  new_fs.f->linedefined = line;\n  checknext(ls, '(');\n  if (needself) {\n    new_localvarliteral(ls, \"self\", 0);\n    adjustlocalvars(ls, 1);\n  }\n  parlist(ls);\n  checknext(ls, ')');\n  chunk(ls);\n  new_fs.f->lastlinedefined = ls->linenumber;\n  check_match(ls, TK_END, TK_FUNCTION, line);\n  close_func(ls);\n  pushclosure(ls, &new_fs, e);\n}\n\n\nstatic int explist1 (LexState *ls, expdesc *v) {\n  /* explist1 -> expr { `,' expr } */\n  int n = 1;  /* at least one expression */\n  expr(ls, v);\n  while (testnext(ls, ',')) {\n    luaK_exp2nextreg(ls->fs, v);\n    expr(ls, v);\n    n++;\n  }\n  return n;\n}\n\n\nstatic void funcargs (LexState *ls, expdesc *f) {\n  FuncState *fs = ls->fs;\n  expdesc args;\n  int base, nparams;\n  int line = ls->linenumber;\n  switch (ls->t.token) {\n    case '(': {  /* funcargs -> `(' [ explist1 ] `)' */\n      if (line != ls->lastline)\n        luaX_syntaxerror(ls,\"ambiguous syntax (function call x new statement)\");\n      luaX_next(ls);\n      if (ls->t.token == ')')  /* arg list is empty? */\n        args.k = VVOID;\n      else {\n        explist1(ls, &args);\n        luaK_setmultret(fs, &args);\n      }\n      check_match(ls, ')', '(', line);\n      break;\n    }\n    case '{': {  /* funcargs -> constructor */\n      constructor(ls, &args);\n      break;\n    }\n    case TK_STRING: {  /* funcargs -> STRING */\n      codestring(ls, &args, ls->t.seminfo.ts);\n      luaX_next(ls);  /* must use `seminfo' before `next' */\n      break;\n    }\n    default: {\n      luaX_syntaxerror(ls, \"function arguments expected\");\n      return;\n    }\n  }\n  lua_assert(f->k == VNONRELOC);\n  base = f->u.s.info;  /* base register for call */\n  if (hasmultret(args.k))\n    nparams = LUA_MULTRET;  /* open call */\n  else {\n    if (args.k != VVOID)\n      luaK_exp2nextreg(fs, &args);  /* close last argument */\n    nparams = fs->freereg - (base+1);\n  }\n  init_exp(f, VCALL, luaK_codeABC(fs, OP_CALL, base, nparams+1, 2));\n  luaK_fixline(fs, line);\n  fs->freereg = base+1;  /* call remove function and arguments and leaves\n                            (unless changed) one result */\n}\n\n\n\n\n/*\n** {======================================================================\n** Expression parsing\n** =======================================================================\n*/\n\n\nstatic void prefixexp (LexState *ls, expdesc *v) {\n  /* prefixexp -> NAME | '(' expr ')' */\n  switch (ls->t.token) {\n    case '(': {\n      int line = ls->linenumber;\n      luaX_next(ls);\n      expr(ls, v);\n      check_match(ls, ')', '(', line);\n      luaK_dischargevars(ls->fs, v);\n      return;\n    }\n    case TK_NAME: {\n      singlevar(ls, v);\n      return;\n    }\n    default: {\n      luaX_syntaxerror(ls, \"unexpected symbol\");\n      return;\n    }\n  }\n}\n\n\nstatic void primaryexp (LexState *ls, expdesc *v) {\n  /* primaryexp ->\n        prefixexp { `.' NAME | `[' exp `]' | `:' NAME funcargs | funcargs } */\n  FuncState *fs = ls->fs;\n  prefixexp(ls, v);\n  for (;;) {\n    switch (ls->t.token) {\n      case '.': {  /* field */\n        field(ls, v);\n        break;\n      }\n      case '[': {  /* `[' exp1 `]' */\n        expdesc key;\n        luaK_exp2anyreg(fs, v);\n        yindex(ls, &key);\n        luaK_indexed(fs, v, &key);\n        break;\n      }\n      case ':': {  /* `:' NAME funcargs */\n        expdesc key;\n        luaX_next(ls);\n        checkname(ls, &key);\n        luaK_self(fs, v, &key);\n        funcargs(ls, v);\n        break;\n      }\n      case '(': case TK_STRING: case '{': {  /* funcargs */\n        luaK_exp2nextreg(fs, v);\n        funcargs(ls, v);\n        break;\n      }\n      default: return;\n    }\n  }\n}\n\n\nstatic void simpleexp (LexState *ls, expdesc *v) {\n  /* simpleexp -> NUMBER | STRING | NIL | true | false | ... |\n                  constructor | FUNCTION body | primaryexp */\n  switch (ls->t.token) {\n    case TK_NUMBER: {\n      init_exp(v, VKNUM, 0);\n      v->u.nval = ls->t.seminfo.r;\n      break;\n    }\n    case TK_STRING: {\n      codestring(ls, v, ls->t.seminfo.ts);\n      break;\n    }\n    case TK_NIL: {\n      init_exp(v, VNIL, 0);\n      break;\n    }\n    case TK_TRUE: {\n      init_exp(v, VTRUE, 0);\n      break;\n    }\n    case TK_FALSE: {\n      init_exp(v, VFALSE, 0);\n      break;\n    }\n    case TK_DOTS: {  /* vararg */\n      FuncState *fs = ls->fs;\n      check_condition(ls, fs->f->is_vararg,\n                      \"cannot use \" LUA_QL(\"...\") \" outside a vararg function\");\n      fs->f->is_vararg &= ~VARARG_NEEDSARG;  /* don't need 'arg' */\n      init_exp(v, VVARARG, luaK_codeABC(fs, OP_VARARG, 0, 1, 0));\n      break;\n    }\n    case '{': {  /* constructor */\n      constructor(ls, v);\n      return;\n    }\n    case TK_FUNCTION: {\n      luaX_next(ls);\n      body(ls, v, 0, ls->linenumber);\n      return;\n    }\n    default: {\n      primaryexp(ls, v);\n      return;\n    }\n  }\n  luaX_next(ls);\n}\n\n\nstatic UnOpr getunopr (int op) {\n  switch (op) {\n    case TK_NOT: return OPR_NOT;\n    case '-': return OPR_MINUS;\n    case '#': return OPR_LEN;\n    default: return OPR_NOUNOPR;\n  }\n}\n\n\nstatic BinOpr getbinopr (int op) {\n  switch (op) {\n    case '+': return OPR_ADD;\n    case '-': return OPR_SUB;\n    case '*': return OPR_MUL;\n    case '/': return OPR_DIV;\n    case '%': return OPR_MOD;\n    case '^': return OPR_POW;\n    case TK_CONCAT: return OPR_CONCAT;\n    case TK_NE: return OPR_NE;\n    case TK_EQ: return OPR_EQ;\n    case '<': return OPR_LT;\n    case TK_LE: return OPR_LE;\n    case '>': return OPR_GT;\n    case TK_GE: return OPR_GE;\n    case TK_AND: return OPR_AND;\n    case TK_OR: return OPR_OR;\n    default: return OPR_NOBINOPR;\n  }\n}\n\n\nstatic const struct {\n  lu_byte left;  /* left priority for each binary operator */\n  lu_byte right; /* right priority */\n} priority[] = {  /* ORDER OPR */\n   {6, 6}, {6, 6}, {7, 7}, {7, 7}, {7, 7},  /* `+' `-' `/' `%' */\n   {10, 9}, {5, 4},                 /* power and concat (right associative) */\n   {3, 3}, {3, 3},                  /* equality and inequality */\n   {3, 3}, {3, 3}, {3, 3}, {3, 3},  /* order */\n   {2, 2}, {1, 1}                   /* logical (and/or) */\n};\n\n#define UNARY_PRIORITY\t8  /* priority for unary operators */\n\n\n/*\n** subexpr -> (simpleexp | unop subexpr) { binop subexpr }\n** where `binop' is any binary operator with a priority higher than `limit'\n*/\nstatic BinOpr subexpr (LexState *ls, expdesc *v, unsigned int limit) {\n  BinOpr op;\n  UnOpr uop;\n  enterlevel(ls);\n  uop = getunopr(ls->t.token);\n  if (uop != OPR_NOUNOPR) {\n    luaX_next(ls);\n    subexpr(ls, v, UNARY_PRIORITY);\n    luaK_prefix(ls->fs, uop, v);\n  }\n  else simpleexp(ls, v);\n  /* expand while operators have priorities higher than `limit' */\n  op = getbinopr(ls->t.token);\n  while (op != OPR_NOBINOPR && priority[op].left > limit) {\n    expdesc v2;\n    BinOpr nextop;\n    luaX_next(ls);\n    luaK_infix(ls->fs, op, v);\n    /* read sub-expression with higher priority */\n    nextop = subexpr(ls, &v2, priority[op].right);\n    luaK_posfix(ls->fs, op, v, &v2);\n    op = nextop;\n  }\n  leavelevel(ls);\n  return op;  /* return first untreated operator */\n}\n\n\nstatic void expr (LexState *ls, expdesc *v) {\n  subexpr(ls, v, 0);\n}\n\n/* }==================================================================== */\n\n\n\n/*\n** {======================================================================\n** Rules for Statements\n** =======================================================================\n*/\n\n\nstatic int block_follow (int token) {\n  switch (token) {\n    case TK_ELSE: case TK_ELSEIF: case TK_END:\n    case TK_UNTIL: case TK_EOS:\n      return 1;\n    default: return 0;\n  }\n}\n\n\nstatic void block (LexState *ls) {\n  /* block -> chunk */\n  FuncState *fs = ls->fs;\n  BlockCnt bl;\n  enterblock(fs, &bl, 0);\n  chunk(ls);\n  lua_assert(bl.breaklist == NO_JUMP);\n  leaveblock(fs);\n}\n\n\n/*\n** structure to chain all variables in the left-hand side of an\n** assignment\n*/\nstruct LHS_assign {\n  struct LHS_assign *prev;\n  expdesc v;  /* variable (global, local, upvalue, or indexed) */\n};\n\n\n/*\n** check whether, in an assignment to a local variable, the local variable\n** is needed in a previous assignment (to a table). If so, save original\n** local value in a safe place and use this safe copy in the previous\n** assignment.\n*/\nstatic void check_conflict (LexState *ls, struct LHS_assign *lh, expdesc *v) {\n  FuncState *fs = ls->fs;\n  int extra = fs->freereg;  /* eventual position to save local variable */\n  int conflict = 0;\n  for (; lh; lh = lh->prev) {\n    if (lh->v.k == VINDEXED) {\n      if (lh->v.u.s.info == v->u.s.info) {  /* conflict? */\n        conflict = 1;\n        lh->v.u.s.info = extra;  /* previous assignment will use safe copy */\n      }\n      if (lh->v.u.s.aux == v->u.s.info) {  /* conflict? */\n        conflict = 1;\n        lh->v.u.s.aux = extra;  /* previous assignment will use safe copy */\n      }\n    }\n  }\n  if (conflict) {\n    luaK_codeABC(fs, OP_MOVE, fs->freereg, v->u.s.info, 0);  /* make copy */\n    luaK_reserveregs(fs, 1);\n  }\n}\n\n\nstatic void assignment (LexState *ls, struct LHS_assign *lh, int nvars) {\n  expdesc e;\n  check_condition(ls, VLOCAL <= lh->v.k && lh->v.k <= VINDEXED,\n                      \"syntax error\");\n  if (testnext(ls, ',')) {  /* assignment -> `,' primaryexp assignment */\n    struct LHS_assign nv;\n    nv.prev = lh;\n    primaryexp(ls, &nv.v);\n    if (nv.v.k == VLOCAL)\n      check_conflict(ls, lh, &nv.v);\n    luaY_checklimit(ls->fs, nvars, LUAI_MAXCCALLS - ls->L->nCcalls,\n                    \"variables in assignment\");\n    assignment(ls, &nv, nvars+1);\n  }\n  else {  /* assignment -> `=' explist1 */\n    int nexps;\n    checknext(ls, '=');\n    nexps = explist1(ls, &e);\n    if (nexps != nvars) {\n      adjust_assign(ls, nvars, nexps, &e);\n      if (nexps > nvars)\n        ls->fs->freereg -= nexps - nvars;  /* remove extra values */\n    }\n    else {\n      luaK_setoneret(ls->fs, &e);  /* close last expression */\n      luaK_storevar(ls->fs, &lh->v, &e);\n      return;  /* avoid default */\n    }\n  }\n  init_exp(&e, VNONRELOC, ls->fs->freereg-1);  /* default assignment */\n  luaK_storevar(ls->fs, &lh->v, &e);\n}\n\n\nstatic int cond (LexState *ls) {\n  /* cond -> exp */\n  expdesc v;\n  expr(ls, &v);  /* read condition */\n  if (v.k == VNIL) v.k = VFALSE;  /* `falses' are all equal here */\n  luaK_goiftrue(ls->fs, &v);\n  return v.f;\n}\n\n\nstatic void breakstat (LexState *ls) {\n  FuncState *fs = ls->fs;\n  BlockCnt *bl = fs->bl;\n  int upval = 0;\n  while (bl && !bl->isbreakable) {\n    upval |= bl->upval;\n    bl = bl->previous;\n  }\n  if (!bl)\n    luaX_syntaxerror(ls, \"no loop to break\");\n  if (upval)\n    luaK_codeABC(fs, OP_CLOSE, bl->nactvar, 0, 0);\n  luaK_concat(fs, &bl->breaklist, luaK_jump(fs));\n}\n\n\nstatic void whilestat (LexState *ls, int line) {\n  /* whilestat -> WHILE cond DO block END */\n  FuncState *fs = ls->fs;\n  int whileinit;\n  int condexit;\n  BlockCnt bl;\n  luaX_next(ls);  /* skip WHILE */\n  whileinit = luaK_getlabel(fs);\n  condexit = cond(ls);\n  enterblock(fs, &bl, 1);\n  checknext(ls, TK_DO);\n  block(ls);\n  luaK_patchlist(fs, luaK_jump(fs), whileinit);\n  check_match(ls, TK_END, TK_WHILE, line);\n  leaveblock(fs);\n  luaK_patchtohere(fs, condexit);  /* false conditions finish the loop */\n}\n\n\nstatic void repeatstat (LexState *ls, int line) {\n  /* repeatstat -> REPEAT block UNTIL cond */\n  int condexit;\n  FuncState *fs = ls->fs;\n  int repeat_init = luaK_getlabel(fs);\n  BlockCnt bl1, bl2;\n  enterblock(fs, &bl1, 1);  /* loop block */\n  enterblock(fs, &bl2, 0);  /* scope block */\n  luaX_next(ls);  /* skip REPEAT */\n  chunk(ls);\n  check_match(ls, TK_UNTIL, TK_REPEAT, line);\n  condexit = cond(ls);  /* read condition (inside scope block) */\n  if (!bl2.upval) {  /* no upvalues? */\n    leaveblock(fs);  /* finish scope */\n    luaK_patchlist(ls->fs, condexit, repeat_init);  /* close the loop */\n  }\n  else {  /* complete semantics when there are upvalues */\n    breakstat(ls);  /* if condition then break */\n    luaK_patchtohere(ls->fs, condexit);  /* else... */\n    leaveblock(fs);  /* finish scope... */\n    luaK_patchlist(ls->fs, luaK_jump(fs), repeat_init);  /* and repeat */\n  }\n  leaveblock(fs);  /* finish loop */\n}\n\n\nstatic int exp1 (LexState *ls) {\n  expdesc e;\n  int k;\n  expr(ls, &e);\n  k = e.k;\n  luaK_exp2nextreg(ls->fs, &e);\n  return k;\n}\n\n\nstatic void forbody (LexState *ls, int base, int line, int nvars, int isnum) {\n  /* forbody -> DO block */\n  BlockCnt bl;\n  FuncState *fs = ls->fs;\n  int prep, endfor;\n  adjustlocalvars(ls, 3);  /* control variables */\n  checknext(ls, TK_DO);\n  prep = isnum ? luaK_codeAsBx(fs, OP_FORPREP, base, NO_JUMP) : luaK_jump(fs);\n  enterblock(fs, &bl, 0);  /* scope for declared variables */\n  adjustlocalvars(ls, nvars);\n  luaK_reserveregs(fs, nvars);\n  block(ls);\n  leaveblock(fs);  /* end of scope for declared variables */\n  luaK_patchtohere(fs, prep);\n  endfor = (isnum) ? luaK_codeAsBx(fs, OP_FORLOOP, base, NO_JUMP) :\n                     luaK_codeABC(fs, OP_TFORLOOP, base, 0, nvars);\n  luaK_fixline(fs, line);  /* pretend that `OP_FOR' starts the loop */\n  luaK_patchlist(fs, (isnum ? endfor : luaK_jump(fs)), prep + 1);\n}\n\n\nstatic void fornum (LexState *ls, TString *varname, int line) {\n  /* fornum -> NAME = exp1,exp1[,exp1] forbody */\n  FuncState *fs = ls->fs;\n  int base = fs->freereg;\n  new_localvarliteral(ls, \"(for index)\", 0);\n  new_localvarliteral(ls, \"(for limit)\", 1);\n  new_localvarliteral(ls, \"(for step)\", 2);\n  new_localvar(ls, varname, 3);\n  checknext(ls, '=');\n  exp1(ls);  /* initial value */\n  checknext(ls, ',');\n  exp1(ls);  /* limit */\n  if (testnext(ls, ','))\n    exp1(ls);  /* optional step */\n  else {  /* default step = 1 */\n    luaK_codeABx(fs, OP_LOADK, fs->freereg, luaK_numberK(fs, 1));\n    luaK_reserveregs(fs, 1);\n  }\n  forbody(ls, base, line, 1, 1);\n}\n\n\nstatic void forlist (LexState *ls, TString *indexname) {\n  /* forlist -> NAME {,NAME} IN explist1 forbody */\n  FuncState *fs = ls->fs;\n  expdesc e;\n  int nvars = 0;\n  int line;\n  int base = fs->freereg;\n  /* create control variables */\n  new_localvarliteral(ls, \"(for generator)\", nvars++);\n  new_localvarliteral(ls, \"(for state)\", nvars++);\n  new_localvarliteral(ls, \"(for control)\", nvars++);\n  /* create declared variables */\n  new_localvar(ls, indexname, nvars++);\n  while (testnext(ls, ','))\n    new_localvar(ls, str_checkname(ls), nvars++);\n  checknext(ls, TK_IN);\n  line = ls->linenumber;\n  adjust_assign(ls, 3, explist1(ls, &e), &e);\n  luaK_checkstack(fs, 3);  /* extra space to call generator */\n  forbody(ls, base, line, nvars - 3, 0);\n}\n\n\nstatic void forstat (LexState *ls, int line) {\n  /* forstat -> FOR (fornum | forlist) END */\n  FuncState *fs = ls->fs;\n  TString *varname;\n  BlockCnt bl;\n  enterblock(fs, &bl, 1);  /* scope for loop and control variables */\n  luaX_next(ls);  /* skip `for' */\n  varname = str_checkname(ls);  /* first variable name */\n  switch (ls->t.token) {\n    case '=': fornum(ls, varname, line); break;\n    case ',': case TK_IN: forlist(ls, varname); break;\n    default: luaX_syntaxerror(ls, LUA_QL(\"=\") \" or \" LUA_QL(\"in\") \" expected\");\n  }\n  check_match(ls, TK_END, TK_FOR, line);\n  leaveblock(fs);  /* loop scope (`break' jumps to this point) */\n}\n\n\nstatic int test_then_block (LexState *ls) {\n  /* test_then_block -> [IF | ELSEIF] cond THEN block */\n  int condexit;\n  luaX_next(ls);  /* skip IF or ELSEIF */\n  condexit = cond(ls);\n  checknext(ls, TK_THEN);\n  block(ls);  /* `then' part */\n  return condexit;\n}\n\n\nstatic void ifstat (LexState *ls, int line) {\n  /* ifstat -> IF cond THEN block {ELSEIF cond THEN block} [ELSE block] END */\n  FuncState *fs = ls->fs;\n  int flist;\n  int escapelist = NO_JUMP;\n  flist = test_then_block(ls);  /* IF cond THEN block */\n  while (ls->t.token == TK_ELSEIF) {\n    luaK_concat(fs, &escapelist, luaK_jump(fs));\n    luaK_patchtohere(fs, flist);\n    flist = test_then_block(ls);  /* ELSEIF cond THEN block */\n  }\n  if (ls->t.token == TK_ELSE) {\n    luaK_concat(fs, &escapelist, luaK_jump(fs));\n    luaK_patchtohere(fs, flist);\n    luaX_next(ls);  /* skip ELSE (after patch, for correct line info) */\n    block(ls);  /* `else' part */\n  }\n  else\n    luaK_concat(fs, &escapelist, flist);\n  luaK_patchtohere(fs, escapelist);\n  check_match(ls, TK_END, TK_IF, line);\n}\n\n\nstatic void localfunc (LexState *ls) {\n  expdesc v, b;\n  FuncState *fs = ls->fs;\n  new_localvar(ls, str_checkname(ls), 0);\n  init_exp(&v, VLOCAL, fs->freereg);\n  luaK_reserveregs(fs, 1);\n  adjustlocalvars(ls, 1);\n  body(ls, &b, 0, ls->linenumber);\n  luaK_storevar(fs, &v, &b);\n  /* debug information will only see the variable after this point! */\n  getlocvar(fs, fs->nactvar - 1).startpc = fs->pc;\n}\n\n\nstatic void localstat (LexState *ls) {\n  /* stat -> LOCAL NAME {`,' NAME} [`=' explist1] */\n  int nvars = 0;\n  int nexps;\n  expdesc e;\n  do {\n    new_localvar(ls, str_checkname(ls), nvars++);\n  } while (testnext(ls, ','));\n  if (testnext(ls, '='))\n    nexps = explist1(ls, &e);\n  else {\n    e.k = VVOID;\n    nexps = 0;\n  }\n  adjust_assign(ls, nvars, nexps, &e);\n  adjustlocalvars(ls, nvars);\n}\n\n\nstatic int funcname (LexState *ls, expdesc *v) {\n  /* funcname -> NAME {field} [`:' NAME] */\n  int needself = 0;\n  singlevar(ls, v);\n  while (ls->t.token == '.')\n    field(ls, v);\n  if (ls->t.token == ':') {\n    needself = 1;\n    field(ls, v);\n  }\n  return needself;\n}\n\n\nstatic void funcstat (LexState *ls, int line) {\n  /* funcstat -> FUNCTION funcname body */\n  int needself;\n  expdesc v, b;\n  luaX_next(ls);  /* skip FUNCTION */\n  needself = funcname(ls, &v);\n  body(ls, &b, needself, line);\n  luaK_storevar(ls->fs, &v, &b);\n  luaK_fixline(ls->fs, line);  /* definition `happens' in the first line */\n}\n\n\nstatic void exprstat (LexState *ls) {\n  /* stat -> func | assignment */\n  FuncState *fs = ls->fs;\n  struct LHS_assign v;\n  primaryexp(ls, &v.v);\n  if (v.v.k == VCALL)  /* stat -> func */\n    SETARG_C(getcode(fs, &v.v), 1);  /* call statement uses no results */\n  else {  /* stat -> assignment */\n    v.prev = NULL;\n    assignment(ls, &v, 1);\n  }\n}\n\n\nstatic void retstat (LexState *ls) {\n  /* stat -> RETURN explist */\n  FuncState *fs = ls->fs;\n  expdesc e;\n  int first, nret;  /* registers with returned values */\n  luaX_next(ls);  /* skip RETURN */\n  if (block_follow(ls->t.token) || ls->t.token == ';')\n    first = nret = 0;  /* return no values */\n  else {\n    nret = explist1(ls, &e);  /* optional return values */\n    if (hasmultret(e.k)) {\n      luaK_setmultret(fs, &e);\n      if (e.k == VCALL && nret == 1) {  /* tail call? */\n        SET_OPCODE(getcode(fs,&e), OP_TAILCALL);\n        lua_assert(GETARG_A(getcode(fs,&e)) == fs->nactvar);\n      }\n      first = fs->nactvar;\n      nret = LUA_MULTRET;  /* return all values */\n    }\n    else {\n      if (nret == 1)  /* only one single value? */\n        first = luaK_exp2anyreg(fs, &e);\n      else {\n        luaK_exp2nextreg(fs, &e);  /* values must go to the `stack' */\n        first = fs->nactvar;  /* return all `active' values */\n        lua_assert(nret == fs->freereg - first);\n      }\n    }\n  }\n  luaK_ret(fs, first, nret);\n}\n\n\nstatic int statement (LexState *ls) {\n  int line = ls->linenumber;  /* may be needed for error messages */\n  switch (ls->t.token) {\n    case TK_IF: {  /* stat -> ifstat */\n      ifstat(ls, line);\n      return 0;\n    }\n    case TK_WHILE: {  /* stat -> whilestat */\n      whilestat(ls, line);\n      return 0;\n    }\n    case TK_DO: {  /* stat -> DO block END */\n      luaX_next(ls);  /* skip DO */\n      block(ls);\n      check_match(ls, TK_END, TK_DO, line);\n      return 0;\n    }\n    case TK_FOR: {  /* stat -> forstat */\n      forstat(ls, line);\n      return 0;\n    }\n    case TK_REPEAT: {  /* stat -> repeatstat */\n      repeatstat(ls, line);\n      return 0;\n    }\n    case TK_FUNCTION: {\n      funcstat(ls, line);  /* stat -> funcstat */\n      return 0;\n    }\n    case TK_LOCAL: {  /* stat -> localstat */\n      luaX_next(ls);  /* skip LOCAL */\n      if (testnext(ls, TK_FUNCTION))  /* local function? */\n        localfunc(ls);\n      else\n        localstat(ls);\n      return 0;\n    }\n    case TK_RETURN: {  /* stat -> retstat */\n      retstat(ls);\n      return 1;  /* must be last statement */\n    }\n    case TK_BREAK: {  /* stat -> breakstat */\n      luaX_next(ls);  /* skip BREAK */\n      breakstat(ls);\n      return 1;  /* must be last statement */\n    }\n    default: {\n      exprstat(ls);\n      return 0;  /* to avoid warnings */\n    }\n  }\n}\n\n\nstatic void chunk (LexState *ls) {\n  /* chunk -> { stat [`;'] } */\n  int islast = 0;\n  enterlevel(ls);\n  while (!islast && !block_follow(ls->t.token)) {\n    islast = statement(ls);\n    testnext(ls, ';');\n    lua_assert(ls->fs->f->maxstacksize >= ls->fs->freereg &&\n               ls->fs->freereg >= ls->fs->nactvar);\n    ls->fs->freereg = ls->fs->nactvar;  /* free registers */\n  }\n  leavelevel(ls);\n}\n\n/* }====================================================================== */\n"
  },
  {
    "path": "extern/deprecated/redis-2.8.21/deps/lua/src/lparser.h",
    "content": "/*\n** $Id: lparser.h,v 1.57.1.1 2007/12/27 13:02:25 roberto Exp $\n** Lua Parser\n** See Copyright Notice in lua.h\n*/\n\n#ifndef lparser_h\n#define lparser_h\n\n#include \"llimits.h\"\n#include \"lobject.h\"\n#include \"lzio.h\"\n\n\n/*\n** Expression descriptor\n*/\n\ntypedef enum {\n  VVOID,\t/* no value */\n  VNIL,\n  VTRUE,\n  VFALSE,\n  VK,\t\t/* info = index of constant in `k' */\n  VKNUM,\t/* nval = numerical value */\n  VLOCAL,\t/* info = local register */\n  VUPVAL,       /* info = index of upvalue in `upvalues' */\n  VGLOBAL,\t/* info = index of table; aux = index of global name in `k' */\n  VINDEXED,\t/* info = table register; aux = index register (or `k') */\n  VJMP,\t\t/* info = instruction pc */\n  VRELOCABLE,\t/* info = instruction pc */\n  VNONRELOC,\t/* info = result register */\n  VCALL,\t/* info = instruction pc */\n  VVARARG\t/* info = instruction pc */\n} expkind;\n\ntypedef struct expdesc {\n  expkind k;\n  union {\n    struct { int info, aux; } s;\n    lua_Number nval;\n  } u;\n  int t;  /* patch list of `exit when true' */\n  int f;  /* patch list of `exit when false' */\n} expdesc;\n\n\ntypedef struct upvaldesc {\n  lu_byte k;\n  lu_byte info;\n} upvaldesc;\n\n\nstruct BlockCnt;  /* defined in lparser.c */\n\n\n/* state needed to generate code for a given function */\ntypedef struct FuncState {\n  Proto *f;  /* current function header */\n  Table *h;  /* table to find (and reuse) elements in `k' */\n  struct FuncState *prev;  /* enclosing function */\n  struct LexState *ls;  /* lexical state */\n  struct lua_State *L;  /* copy of the Lua state */\n  struct BlockCnt *bl;  /* chain of current blocks */\n  int pc;  /* next position to code (equivalent to `ncode') */\n  int lasttarget;   /* `pc' of last `jump target' */\n  int jpc;  /* list of pending jumps to `pc' */\n  int freereg;  /* first free register */\n  int nk;  /* number of elements in `k' */\n  int np;  /* number of elements in `p' */\n  short nlocvars;  /* number of elements in `locvars' */\n  lu_byte nactvar;  /* number of active local variables */\n  upvaldesc upvalues[LUAI_MAXUPVALUES];  /* upvalues */\n  unsigned short actvar[LUAI_MAXVARS];  /* declared-variable stack */\n} FuncState;\n\n\nLUAI_FUNC Proto *luaY_parser (lua_State *L, ZIO *z, Mbuffer *buff,\n                                            const char *name);\n\n\n#endif\n"
  },
  {
    "path": "extern/deprecated/redis-2.8.21/deps/lua/src/lstate.c",
    "content": "/*\n** $Id: lstate.c,v 2.36.1.2 2008/01/03 15:20:39 roberto Exp $\n** Global State\n** See Copyright Notice in lua.h\n*/\n\n\n#include <stddef.h>\n\n#define lstate_c\n#define LUA_CORE\n\n#include \"lua.h\"\n\n#include \"ldebug.h\"\n#include \"ldo.h\"\n#include \"lfunc.h\"\n#include \"lgc.h\"\n#include \"llex.h\"\n#include \"lmem.h\"\n#include \"lstate.h\"\n#include \"lstring.h\"\n#include \"ltable.h\"\n#include \"ltm.h\"\n\n\n#define state_size(x)\t(sizeof(x) + LUAI_EXTRASPACE)\n#define fromstate(l)\t(cast(lu_byte *, (l)) - LUAI_EXTRASPACE)\n#define tostate(l)   (cast(lua_State *, cast(lu_byte *, l) + LUAI_EXTRASPACE))\n\n\n/*\n** Main thread combines a thread state and the global state\n*/\ntypedef struct LG {\n  lua_State l;\n  global_State g;\n} LG;\n  \n\n\nstatic void stack_init (lua_State *L1, lua_State *L) {\n  /* initialize CallInfo array */\n  L1->base_ci = luaM_newvector(L, BASIC_CI_SIZE, CallInfo);\n  L1->ci = L1->base_ci;\n  L1->size_ci = BASIC_CI_SIZE;\n  L1->end_ci = L1->base_ci + L1->size_ci - 1;\n  /* initialize stack array */\n  L1->stack = luaM_newvector(L, BASIC_STACK_SIZE + EXTRA_STACK, TValue);\n  L1->stacksize = BASIC_STACK_SIZE + EXTRA_STACK;\n  L1->top = L1->stack;\n  L1->stack_last = L1->stack+(L1->stacksize - EXTRA_STACK)-1;\n  /* initialize first ci */\n  L1->ci->func = L1->top;\n  setnilvalue(L1->top++);  /* `function' entry for this `ci' */\n  L1->base = L1->ci->base = L1->top;\n  L1->ci->top = L1->top + LUA_MINSTACK;\n}\n\n\nstatic void freestack (lua_State *L, lua_State *L1) {\n  luaM_freearray(L, L1->base_ci, L1->size_ci, CallInfo);\n  luaM_freearray(L, L1->stack, L1->stacksize, TValue);\n}\n\n\n/*\n** open parts that may cause memory-allocation errors\n*/\nstatic void f_luaopen (lua_State *L, void *ud) {\n  global_State *g = G(L);\n  UNUSED(ud);\n  stack_init(L, L);  /* init stack */\n  sethvalue(L, gt(L), luaH_new(L, 0, 2));  /* table of globals */\n  sethvalue(L, registry(L), luaH_new(L, 0, 2));  /* registry */\n  luaS_resize(L, MINSTRTABSIZE);  /* initial size of string table */\n  luaT_init(L);\n  luaX_init(L);\n  luaS_fix(luaS_newliteral(L, MEMERRMSG));\n  g->GCthreshold = 4*g->totalbytes;\n}\n\n\nstatic void preinit_state (lua_State *L, global_State *g) {\n  G(L) = g;\n  L->stack = NULL;\n  L->stacksize = 0;\n  L->errorJmp = NULL;\n  L->hook = NULL;\n  L->hookmask = 0;\n  L->basehookcount = 0;\n  L->allowhook = 1;\n  resethookcount(L);\n  L->openupval = NULL;\n  L->size_ci = 0;\n  L->nCcalls = L->baseCcalls = 0;\n  L->status = 0;\n  L->base_ci = L->ci = NULL;\n  L->savedpc = NULL;\n  L->errfunc = 0;\n  setnilvalue(gt(L));\n}\n\n\nstatic void close_state (lua_State *L) {\n  global_State *g = G(L);\n  luaF_close(L, L->stack);  /* close all upvalues for this thread */\n  luaC_freeall(L);  /* collect all objects */\n  lua_assert(g->rootgc == obj2gco(L));\n  lua_assert(g->strt.nuse == 0);\n  luaM_freearray(L, G(L)->strt.hash, G(L)->strt.size, TString *);\n  luaZ_freebuffer(L, &g->buff);\n  freestack(L, L);\n  lua_assert(g->totalbytes == sizeof(LG));\n  (*g->frealloc)(g->ud, fromstate(L), state_size(LG), 0);\n}\n\n\nlua_State *luaE_newthread (lua_State *L) {\n  lua_State *L1 = tostate(luaM_malloc(L, state_size(lua_State)));\n  luaC_link(L, obj2gco(L1), LUA_TTHREAD);\n  preinit_state(L1, G(L));\n  stack_init(L1, L);  /* init stack */\n  setobj2n(L, gt(L1), gt(L));  /* share table of globals */\n  L1->hookmask = L->hookmask;\n  L1->basehookcount = L->basehookcount;\n  L1->hook = L->hook;\n  resethookcount(L1);\n  lua_assert(iswhite(obj2gco(L1)));\n  return L1;\n}\n\n\nvoid luaE_freethread (lua_State *L, lua_State *L1) {\n  luaF_close(L1, L1->stack);  /* close all upvalues for this thread */\n  lua_assert(L1->openupval == NULL);\n  luai_userstatefree(L1);\n  freestack(L, L1);\n  luaM_freemem(L, fromstate(L1), state_size(lua_State));\n}\n\n\nLUA_API lua_State *lua_newstate (lua_Alloc f, void *ud) {\n  int i;\n  lua_State *L;\n  global_State *g;\n  void *l = (*f)(ud, NULL, 0, state_size(LG));\n  if (l == NULL) return NULL;\n  L = tostate(l);\n  g = &((LG *)L)->g;\n  L->next = NULL;\n  L->tt = LUA_TTHREAD;\n  g->currentwhite = bit2mask(WHITE0BIT, FIXEDBIT);\n  L->marked = luaC_white(g);\n  set2bits(L->marked, FIXEDBIT, SFIXEDBIT);\n  preinit_state(L, g);\n  g->frealloc = f;\n  g->ud = ud;\n  g->mainthread = L;\n  g->uvhead.u.l.prev = &g->uvhead;\n  g->uvhead.u.l.next = &g->uvhead;\n  g->GCthreshold = 0;  /* mark it as unfinished state */\n  g->strt.size = 0;\n  g->strt.nuse = 0;\n  g->strt.hash = NULL;\n  setnilvalue(registry(L));\n  luaZ_initbuffer(L, &g->buff);\n  g->panic = NULL;\n  g->gcstate = GCSpause;\n  g->rootgc = obj2gco(L);\n  g->sweepstrgc = 0;\n  g->sweepgc = &g->rootgc;\n  g->gray = NULL;\n  g->grayagain = NULL;\n  g->weak = NULL;\n  g->tmudata = NULL;\n  g->totalbytes = sizeof(LG);\n  g->gcpause = LUAI_GCPAUSE;\n  g->gcstepmul = LUAI_GCMUL;\n  g->gcdept = 0;\n  for (i=0; i<NUM_TAGS; i++) g->mt[i] = NULL;\n  if (luaD_rawrunprotected(L, f_luaopen, NULL) != 0) {\n    /* memory allocation error: free partial state */\n    close_state(L);\n    L = NULL;\n  }\n  else\n    luai_userstateopen(L);\n  return L;\n}\n\n\nstatic void callallgcTM (lua_State *L, void *ud) {\n  UNUSED(ud);\n  luaC_callGCTM(L);  /* call GC metamethods for all udata */\n}\n\n\nLUA_API void lua_close (lua_State *L) {\n  L = G(L)->mainthread;  /* only the main thread can be closed */\n  lua_lock(L);\n  luaF_close(L, L->stack);  /* close all upvalues for this thread */\n  luaC_separateudata(L, 1);  /* separate udata that have GC metamethods */\n  L->errfunc = 0;  /* no error function during GC metamethods */\n  do {  /* repeat until no more errors */\n    L->ci = L->base_ci;\n    L->base = L->top = L->ci->base;\n    L->nCcalls = L->baseCcalls = 0;\n  } while (luaD_rawrunprotected(L, callallgcTM, NULL) != 0);\n  lua_assert(G(L)->tmudata == NULL);\n  luai_userstateclose(L);\n  close_state(L);\n}\n\n"
  },
  {
    "path": "extern/deprecated/redis-2.8.21/deps/lua/src/lstate.h",
    "content": "/*\n** $Id: lstate.h,v 2.24.1.2 2008/01/03 15:20:39 roberto Exp $\n** Global State\n** See Copyright Notice in lua.h\n*/\n\n#ifndef lstate_h\n#define lstate_h\n\n#include \"lua.h\"\n\n#include \"lobject.h\"\n#include \"ltm.h\"\n#include \"lzio.h\"\n\n\n\nstruct lua_longjmp;  /* defined in ldo.c */\n\n\n/* table of globals */\n#define gt(L)\t(&L->l_gt)\n\n/* registry */\n#define registry(L)\t(&G(L)->l_registry)\n\n\n/* extra stack space to handle TM calls and some other extras */\n#define EXTRA_STACK   5\n\n\n#define BASIC_CI_SIZE           8\n\n#define BASIC_STACK_SIZE        (2*LUA_MINSTACK)\n\n\n\ntypedef struct stringtable {\n  GCObject **hash;\n  lu_int32 nuse;  /* number of elements */\n  int size;\n} stringtable;\n\n\n/*\n** informations about a call\n*/\ntypedef struct CallInfo {\n  StkId base;  /* base for this function */\n  StkId func;  /* function index in the stack */\n  StkId\ttop;  /* top for this function */\n  const Instruction *savedpc;\n  int nresults;  /* expected number of results from this function */\n  int tailcalls;  /* number of tail calls lost under this entry */\n} CallInfo;\n\n\n\n#define curr_func(L)\t(clvalue(L->ci->func))\n#define ci_func(ci)\t(clvalue((ci)->func))\n#define f_isLua(ci)\t(!ci_func(ci)->c.isC)\n#define isLua(ci)\t(ttisfunction((ci)->func) && f_isLua(ci))\n\n\n/*\n** `global state', shared by all threads of this state\n*/\ntypedef struct global_State {\n  stringtable strt;  /* hash table for strings */\n  lua_Alloc frealloc;  /* function to reallocate memory */\n  void *ud;         /* auxiliary data to `frealloc' */\n  lu_byte currentwhite;\n  lu_byte gcstate;  /* state of garbage collector */\n  int sweepstrgc;  /* position of sweep in `strt' */\n  GCObject *rootgc;  /* list of all collectable objects */\n  GCObject **sweepgc;  /* position of sweep in `rootgc' */\n  GCObject *gray;  /* list of gray objects */\n  GCObject *grayagain;  /* list of objects to be traversed atomically */\n  GCObject *weak;  /* list of weak tables (to be cleared) */\n  GCObject *tmudata;  /* last element of list of userdata to be GC */\n  Mbuffer buff;  /* temporary buffer for string concatentation */\n  lu_mem GCthreshold;\n  lu_mem totalbytes;  /* number of bytes currently allocated */\n  lu_mem estimate;  /* an estimate of number of bytes actually in use */\n  lu_mem gcdept;  /* how much GC is `behind schedule' */\n  int gcpause;  /* size of pause between successive GCs */\n  int gcstepmul;  /* GC `granularity' */\n  lua_CFunction panic;  /* to be called in unprotected errors */\n  TValue l_registry;\n  struct lua_State *mainthread;\n  UpVal uvhead;  /* head of double-linked list of all open upvalues */\n  struct Table *mt[NUM_TAGS];  /* metatables for basic types */\n  TString *tmname[TM_N];  /* array with tag-method names */\n} global_State;\n\n\n/*\n** `per thread' state\n*/\nstruct lua_State {\n  CommonHeader;\n  lu_byte status;\n  StkId top;  /* first free slot in the stack */\n  StkId base;  /* base of current function */\n  global_State *l_G;\n  CallInfo *ci;  /* call info for current function */\n  const Instruction *savedpc;  /* `savedpc' of current function */\n  StkId stack_last;  /* last free slot in the stack */\n  StkId stack;  /* stack base */\n  CallInfo *end_ci;  /* points after end of ci array*/\n  CallInfo *base_ci;  /* array of CallInfo's */\n  int stacksize;\n  int size_ci;  /* size of array `base_ci' */\n  unsigned short nCcalls;  /* number of nested C calls */\n  unsigned short baseCcalls;  /* nested C calls when resuming coroutine */\n  lu_byte hookmask;\n  lu_byte allowhook;\n  int basehookcount;\n  int hookcount;\n  lua_Hook hook;\n  TValue l_gt;  /* table of globals */\n  TValue env;  /* temporary place for environments */\n  GCObject *openupval;  /* list of open upvalues in this stack */\n  GCObject *gclist;\n  struct lua_longjmp *errorJmp;  /* current error recover point */\n  ptrdiff_t errfunc;  /* current error handling function (stack index) */\n};\n\n\n#define G(L)\t(L->l_G)\n\n\n/*\n** Union of all collectable objects\n*/\nunion GCObject {\n  GCheader gch;\n  union TString ts;\n  union Udata u;\n  union Closure cl;\n  struct Table h;\n  struct Proto p;\n  struct UpVal uv;\n  struct lua_State th;  /* thread */\n};\n\n\n/* macros to convert a GCObject into a specific value */\n#define rawgco2ts(o)\tcheck_exp((o)->gch.tt == LUA_TSTRING, &((o)->ts))\n#define gco2ts(o)\t(&rawgco2ts(o)->tsv)\n#define rawgco2u(o)\tcheck_exp((o)->gch.tt == LUA_TUSERDATA, &((o)->u))\n#define gco2u(o)\t(&rawgco2u(o)->uv)\n#define gco2cl(o)\tcheck_exp((o)->gch.tt == LUA_TFUNCTION, &((o)->cl))\n#define gco2h(o)\tcheck_exp((o)->gch.tt == LUA_TTABLE, &((o)->h))\n#define gco2p(o)\tcheck_exp((o)->gch.tt == LUA_TPROTO, &((o)->p))\n#define gco2uv(o)\tcheck_exp((o)->gch.tt == LUA_TUPVAL, &((o)->uv))\n#define ngcotouv(o) \\\n\tcheck_exp((o) == NULL || (o)->gch.tt == LUA_TUPVAL, &((o)->uv))\n#define gco2th(o)\tcheck_exp((o)->gch.tt == LUA_TTHREAD, &((o)->th))\n\n/* macro to convert any Lua object into a GCObject */\n#define obj2gco(v)\t(cast(GCObject *, (v)))\n\n\nLUAI_FUNC lua_State *luaE_newthread (lua_State *L);\nLUAI_FUNC void luaE_freethread (lua_State *L, lua_State *L1);\n\n#endif\n\n"
  },
  {
    "path": "extern/deprecated/redis-2.8.21/deps/lua/src/lstring.c",
    "content": "/*\n** $Id: lstring.c,v 2.8.1.1 2007/12/27 13:02:25 roberto Exp $\n** String table (keeps all strings handled by Lua)\n** See Copyright Notice in lua.h\n*/\n\n\n#include <string.h>\n\n#define lstring_c\n#define LUA_CORE\n\n#include \"lua.h\"\n\n#include \"lmem.h\"\n#include \"lobject.h\"\n#include \"lstate.h\"\n#include \"lstring.h\"\n\n\n\nvoid luaS_resize (lua_State *L, int newsize) {\n  GCObject **newhash;\n  stringtable *tb;\n  int i;\n  if (G(L)->gcstate == GCSsweepstring)\n    return;  /* cannot resize during GC traverse */\n  newhash = luaM_newvector(L, newsize, GCObject *);\n  tb = &G(L)->strt;\n  for (i=0; i<newsize; i++) newhash[i] = NULL;\n  /* rehash */\n  for (i=0; i<tb->size; i++) {\n    GCObject *p = tb->hash[i];\n    while (p) {  /* for each node in the list */\n      GCObject *next = p->gch.next;  /* save next */\n      unsigned int h = gco2ts(p)->hash;\n      int h1 = lmod(h, newsize);  /* new position */\n      lua_assert(cast_int(h%newsize) == lmod(h, newsize));\n      p->gch.next = newhash[h1];  /* chain it */\n      newhash[h1] = p;\n      p = next;\n    }\n  }\n  luaM_freearray(L, tb->hash, tb->size, TString *);\n  tb->size = newsize;\n  tb->hash = newhash;\n}\n\n\nstatic TString *newlstr (lua_State *L, const char *str, size_t l,\n                                       unsigned int h) {\n  TString *ts;\n  stringtable *tb;\n  if (l+1 > (MAX_SIZET - sizeof(TString))/sizeof(char))\n    luaM_toobig(L);\n  ts = cast(TString *, luaM_malloc(L, (l+1)*sizeof(char)+sizeof(TString)));\n  ts->tsv.len = l;\n  ts->tsv.hash = h;\n  ts->tsv.marked = luaC_white(G(L));\n  ts->tsv.tt = LUA_TSTRING;\n  ts->tsv.reserved = 0;\n  memcpy(ts+1, str, l*sizeof(char));\n  ((char *)(ts+1))[l] = '\\0';  /* ending 0 */\n  tb = &G(L)->strt;\n  h = lmod(h, tb->size);\n  ts->tsv.next = tb->hash[h];  /* chain new entry */\n  tb->hash[h] = obj2gco(ts);\n  tb->nuse++;\n  if (tb->nuse > cast(lu_int32, tb->size) && tb->size <= MAX_INT/2)\n    luaS_resize(L, tb->size*2);  /* too crowded */\n  return ts;\n}\n\n\nTString *luaS_newlstr (lua_State *L, const char *str, size_t l) {\n  GCObject *o;\n  unsigned int h = cast(unsigned int, l);  /* seed */\n  size_t step = (l>>5)+1;  /* if string is too long, don't hash all its chars */\n  size_t l1;\n  for (l1=l; l1>=step; l1-=step)  /* compute hash */\n    h = h ^ ((h<<5)+(h>>2)+cast(unsigned char, str[l1-1]));\n  for (o = G(L)->strt.hash[lmod(h, G(L)->strt.size)];\n       o != NULL;\n       o = o->gch.next) {\n    TString *ts = rawgco2ts(o);\n    if (ts->tsv.len == l && (memcmp(str, getstr(ts), l) == 0)) {\n      /* string may be dead */\n      if (isdead(G(L), o)) changewhite(o);\n      return ts;\n    }\n  }\n  return newlstr(L, str, l, h);  /* not found */\n}\n\n\nUdata *luaS_newudata (lua_State *L, size_t s, Table *e) {\n  Udata *u;\n  if (s > MAX_SIZET - sizeof(Udata))\n    luaM_toobig(L);\n  u = cast(Udata *, luaM_malloc(L, s + sizeof(Udata)));\n  u->uv.marked = luaC_white(G(L));  /* is not finalized */\n  u->uv.tt = LUA_TUSERDATA;\n  u->uv.len = s;\n  u->uv.metatable = NULL;\n  u->uv.env = e;\n  /* chain it on udata list (after main thread) */\n  u->uv.next = G(L)->mainthread->next;\n  G(L)->mainthread->next = obj2gco(u);\n  return u;\n}\n\n"
  },
  {
    "path": "extern/deprecated/redis-2.8.21/deps/lua/src/lstring.h",
    "content": "/*\n** $Id: lstring.h,v 1.43.1.1 2007/12/27 13:02:25 roberto Exp $\n** String table (keep all strings handled by Lua)\n** See Copyright Notice in lua.h\n*/\n\n#ifndef lstring_h\n#define lstring_h\n\n\n#include \"lgc.h\"\n#include \"lobject.h\"\n#include \"lstate.h\"\n\n\n#define sizestring(s)\t(sizeof(union TString)+((s)->len+1)*sizeof(char))\n\n#define sizeudata(u)\t(sizeof(union Udata)+(u)->len)\n\n#define luaS_new(L, s)\t(luaS_newlstr(L, s, strlen(s)))\n#define luaS_newliteral(L, s)\t(luaS_newlstr(L, \"\" s, \\\n                                 (sizeof(s)/sizeof(char))-1))\n\n#define luaS_fix(s)\tl_setbit((s)->tsv.marked, FIXEDBIT)\n\nLUAI_FUNC void luaS_resize (lua_State *L, int newsize);\nLUAI_FUNC Udata *luaS_newudata (lua_State *L, size_t s, Table *e);\nLUAI_FUNC TString *luaS_newlstr (lua_State *L, const char *str, size_t l);\n\n\n#endif\n"
  },
  {
    "path": "extern/deprecated/redis-2.8.21/deps/lua/src/lstrlib.c",
    "content": "/*\n** $Id: lstrlib.c,v 1.132.1.5 2010/05/14 15:34:19 roberto Exp $\n** Standard library for string operations and pattern-matching\n** See Copyright Notice in lua.h\n*/\n\n\n#include <ctype.h>\n#include <stddef.h>\n#include <stdio.h>\n#include <stdlib.h>\n#include <string.h>\n\n#define lstrlib_c\n#define LUA_LIB\n\n#include \"lua.h\"\n\n#include \"lauxlib.h\"\n#include \"lualib.h\"\n\n\n/* macro to `unsign' a character */\n#define uchar(c)        ((unsigned char)(c))\n\n\n\nstatic int str_len (lua_State *L) {\n  size_t l;\n  luaL_checklstring(L, 1, &l);\n  lua_pushinteger(L, l);\n  return 1;\n}\n\n\nstatic ptrdiff_t posrelat (ptrdiff_t pos, size_t len) {\n  /* relative string position: negative means back from end */\n  if (pos < 0) pos += (ptrdiff_t)len + 1;\n  return (pos >= 0) ? pos : 0;\n}\n\n\nstatic int str_sub (lua_State *L) {\n  size_t l;\n  const char *s = luaL_checklstring(L, 1, &l);\n  ptrdiff_t start = posrelat(luaL_checkinteger(L, 2), l);\n  ptrdiff_t end = posrelat(luaL_optinteger(L, 3, -1), l);\n  if (start < 1) start = 1;\n  if (end > (ptrdiff_t)l) end = (ptrdiff_t)l;\n  if (start <= end)\n    lua_pushlstring(L, s+start-1, end-start+1);\n  else lua_pushliteral(L, \"\");\n  return 1;\n}\n\n\nstatic int str_reverse (lua_State *L) {\n  size_t l;\n  luaL_Buffer b;\n  const char *s = luaL_checklstring(L, 1, &l);\n  luaL_buffinit(L, &b);\n  while (l--) luaL_addchar(&b, s[l]);\n  luaL_pushresult(&b);\n  return 1;\n}\n\n\nstatic int str_lower (lua_State *L) {\n  size_t l;\n  size_t i;\n  luaL_Buffer b;\n  const char *s = luaL_checklstring(L, 1, &l);\n  luaL_buffinit(L, &b);\n  for (i=0; i<l; i++)\n    luaL_addchar(&b, tolower(uchar(s[i])));\n  luaL_pushresult(&b);\n  return 1;\n}\n\n\nstatic int str_upper (lua_State *L) {\n  size_t l;\n  size_t i;\n  luaL_Buffer b;\n  const char *s = luaL_checklstring(L, 1, &l);\n  luaL_buffinit(L, &b);\n  for (i=0; i<l; i++)\n    luaL_addchar(&b, toupper(uchar(s[i])));\n  luaL_pushresult(&b);\n  return 1;\n}\n\nstatic int str_rep (lua_State *L) {\n  size_t l;\n  luaL_Buffer b;\n  const char *s = luaL_checklstring(L, 1, &l);\n  int n = luaL_checkint(L, 2);\n  luaL_buffinit(L, &b);\n  while (n-- > 0)\n    luaL_addlstring(&b, s, l);\n  luaL_pushresult(&b);\n  return 1;\n}\n\n\nstatic int str_byte (lua_State *L) {\n  size_t l;\n  const char *s = luaL_checklstring(L, 1, &l);\n  ptrdiff_t posi = posrelat(luaL_optinteger(L, 2, 1), l);\n  ptrdiff_t pose = posrelat(luaL_optinteger(L, 3, posi), l);\n  int n, i;\n  if (posi <= 0) posi = 1;\n  if ((size_t)pose > l) pose = l;\n  if (posi > pose) return 0;  /* empty interval; return no values */\n  n = (int)(pose -  posi + 1);\n  if (posi + n <= pose)  /* overflow? */\n    luaL_error(L, \"string slice too long\");\n  luaL_checkstack(L, n, \"string slice too long\");\n  for (i=0; i<n; i++)\n    lua_pushinteger(L, uchar(s[posi+i-1]));\n  return n;\n}\n\n\nstatic int str_char (lua_State *L) {\n  int n = lua_gettop(L);  /* number of arguments */\n  int i;\n  luaL_Buffer b;\n  luaL_buffinit(L, &b);\n  for (i=1; i<=n; i++) {\n    int c = luaL_checkint(L, i);\n    luaL_argcheck(L, uchar(c) == c, i, \"invalid value\");\n    luaL_addchar(&b, uchar(c));\n  }\n  luaL_pushresult(&b);\n  return 1;\n}\n\n\nstatic int writer (lua_State *L, const void* b, size_t size, void* B) {\n  (void)L;\n  luaL_addlstring((luaL_Buffer*) B, (const char *)b, size);\n  return 0;\n}\n\n\nstatic int str_dump (lua_State *L) {\n  luaL_Buffer b;\n  luaL_checktype(L, 1, LUA_TFUNCTION);\n  lua_settop(L, 1);\n  luaL_buffinit(L,&b);\n  if (lua_dump(L, writer, &b) != 0)\n    luaL_error(L, \"unable to dump given function\");\n  luaL_pushresult(&b);\n  return 1;\n}\n\n\n\n/*\n** {======================================================\n** PATTERN MATCHING\n** =======================================================\n*/\n\n\n#define CAP_UNFINISHED\t(-1)\n#define CAP_POSITION\t(-2)\n\ntypedef struct MatchState {\n  const char *src_init;  /* init of source string */\n  const char *src_end;  /* end (`\\0') of source string */\n  lua_State *L;\n  int level;  /* total number of captures (finished or unfinished) */\n  struct {\n    const char *init;\n    ptrdiff_t len;\n  } capture[LUA_MAXCAPTURES];\n} MatchState;\n\n\n#define L_ESC\t\t'%'\n#define SPECIALS\t\"^$*+?.([%-\"\n\n\nstatic int check_capture (MatchState *ms, int l) {\n  l -= '1';\n  if (l < 0 || l >= ms->level || ms->capture[l].len == CAP_UNFINISHED)\n    return luaL_error(ms->L, \"invalid capture index\");\n  return l;\n}\n\n\nstatic int capture_to_close (MatchState *ms) {\n  int level = ms->level;\n  for (level--; level>=0; level--)\n    if (ms->capture[level].len == CAP_UNFINISHED) return level;\n  return luaL_error(ms->L, \"invalid pattern capture\");\n}\n\n\nstatic const char *classend (MatchState *ms, const char *p) {\n  switch (*p++) {\n    case L_ESC: {\n      if (*p == '\\0')\n        luaL_error(ms->L, \"malformed pattern (ends with \" LUA_QL(\"%%\") \")\");\n      return p+1;\n    }\n    case '[': {\n      if (*p == '^') p++;\n      do {  /* look for a `]' */\n        if (*p == '\\0')\n          luaL_error(ms->L, \"malformed pattern (missing \" LUA_QL(\"]\") \")\");\n        if (*(p++) == L_ESC && *p != '\\0')\n          p++;  /* skip escapes (e.g. `%]') */\n      } while (*p != ']');\n      return p+1;\n    }\n    default: {\n      return p;\n    }\n  }\n}\n\n\nstatic int match_class (int c, int cl) {\n  int res;\n  switch (tolower(cl)) {\n    case 'a' : res = isalpha(c); break;\n    case 'c' : res = iscntrl(c); break;\n    case 'd' : res = isdigit(c); break;\n    case 'l' : res = islower(c); break;\n    case 'p' : res = ispunct(c); break;\n    case 's' : res = isspace(c); break;\n    case 'u' : res = isupper(c); break;\n    case 'w' : res = isalnum(c); break;\n    case 'x' : res = isxdigit(c); break;\n    case 'z' : res = (c == 0); break;\n    default: return (cl == c);\n  }\n  return (islower(cl) ? res : !res);\n}\n\n\nstatic int matchbracketclass (int c, const char *p, const char *ec) {\n  int sig = 1;\n  if (*(p+1) == '^') {\n    sig = 0;\n    p++;  /* skip the `^' */\n  }\n  while (++p < ec) {\n    if (*p == L_ESC) {\n      p++;\n      if (match_class(c, uchar(*p)))\n        return sig;\n    }\n    else if ((*(p+1) == '-') && (p+2 < ec)) {\n      p+=2;\n      if (uchar(*(p-2)) <= c && c <= uchar(*p))\n        return sig;\n    }\n    else if (uchar(*p) == c) return sig;\n  }\n  return !sig;\n}\n\n\nstatic int singlematch (int c, const char *p, const char *ep) {\n  switch (*p) {\n    case '.': return 1;  /* matches any char */\n    case L_ESC: return match_class(c, uchar(*(p+1)));\n    case '[': return matchbracketclass(c, p, ep-1);\n    default:  return (uchar(*p) == c);\n  }\n}\n\n\nstatic const char *match (MatchState *ms, const char *s, const char *p);\n\n\nstatic const char *matchbalance (MatchState *ms, const char *s,\n                                   const char *p) {\n  if (*p == 0 || *(p+1) == 0)\n    luaL_error(ms->L, \"unbalanced pattern\");\n  if (*s != *p) return NULL;\n  else {\n    int b = *p;\n    int e = *(p+1);\n    int cont = 1;\n    while (++s < ms->src_end) {\n      if (*s == e) {\n        if (--cont == 0) return s+1;\n      }\n      else if (*s == b) cont++;\n    }\n  }\n  return NULL;  /* string ends out of balance */\n}\n\n\nstatic const char *max_expand (MatchState *ms, const char *s,\n                                 const char *p, const char *ep) {\n  ptrdiff_t i = 0;  /* counts maximum expand for item */\n  while ((s+i)<ms->src_end && singlematch(uchar(*(s+i)), p, ep))\n    i++;\n  /* keeps trying to match with the maximum repetitions */\n  while (i>=0) {\n    const char *res = match(ms, (s+i), ep+1);\n    if (res) return res;\n    i--;  /* else didn't match; reduce 1 repetition to try again */\n  }\n  return NULL;\n}\n\n\nstatic const char *min_expand (MatchState *ms, const char *s,\n                                 const char *p, const char *ep) {\n  for (;;) {\n    const char *res = match(ms, s, ep+1);\n    if (res != NULL)\n      return res;\n    else if (s<ms->src_end && singlematch(uchar(*s), p, ep))\n      s++;  /* try with one more repetition */\n    else return NULL;\n  }\n}\n\n\nstatic const char *start_capture (MatchState *ms, const char *s,\n                                    const char *p, int what) {\n  const char *res;\n  int level = ms->level;\n  if (level >= LUA_MAXCAPTURES) luaL_error(ms->L, \"too many captures\");\n  ms->capture[level].init = s;\n  ms->capture[level].len = what;\n  ms->level = level+1;\n  if ((res=match(ms, s, p)) == NULL)  /* match failed? */\n    ms->level--;  /* undo capture */\n  return res;\n}\n\n\nstatic const char *end_capture (MatchState *ms, const char *s,\n                                  const char *p) {\n  int l = capture_to_close(ms);\n  const char *res;\n  ms->capture[l].len = s - ms->capture[l].init;  /* close capture */\n  if ((res = match(ms, s, p)) == NULL)  /* match failed? */\n    ms->capture[l].len = CAP_UNFINISHED;  /* undo capture */\n  return res;\n}\n\n\nstatic const char *match_capture (MatchState *ms, const char *s, int l) {\n  size_t len;\n  l = check_capture(ms, l);\n  len = ms->capture[l].len;\n  if ((size_t)(ms->src_end-s) >= len &&\n      memcmp(ms->capture[l].init, s, len) == 0)\n    return s+len;\n  else return NULL;\n}\n\n\nstatic const char *match (MatchState *ms, const char *s, const char *p) {\n  init: /* using goto's to optimize tail recursion */\n  switch (*p) {\n    case '(': {  /* start capture */\n      if (*(p+1) == ')')  /* position capture? */\n        return start_capture(ms, s, p+2, CAP_POSITION);\n      else\n        return start_capture(ms, s, p+1, CAP_UNFINISHED);\n    }\n    case ')': {  /* end capture */\n      return end_capture(ms, s, p+1);\n    }\n    case L_ESC: {\n      switch (*(p+1)) {\n        case 'b': {  /* balanced string? */\n          s = matchbalance(ms, s, p+2);\n          if (s == NULL) return NULL;\n          p+=4; goto init;  /* else return match(ms, s, p+4); */\n        }\n        case 'f': {  /* frontier? */\n          const char *ep; char previous;\n          p += 2;\n          if (*p != '[')\n            luaL_error(ms->L, \"missing \" LUA_QL(\"[\") \" after \"\n                               LUA_QL(\"%%f\") \" in pattern\");\n          ep = classend(ms, p);  /* points to what is next */\n          previous = (s == ms->src_init) ? '\\0' : *(s-1);\n          if (matchbracketclass(uchar(previous), p, ep-1) ||\n             !matchbracketclass(uchar(*s), p, ep-1)) return NULL;\n          p=ep; goto init;  /* else return match(ms, s, ep); */\n        }\n        default: {\n          if (isdigit(uchar(*(p+1)))) {  /* capture results (%0-%9)? */\n            s = match_capture(ms, s, uchar(*(p+1)));\n            if (s == NULL) return NULL;\n            p+=2; goto init;  /* else return match(ms, s, p+2) */\n          }\n          goto dflt;  /* case default */\n        }\n      }\n    }\n    case '\\0': {  /* end of pattern */\n      return s;  /* match succeeded */\n    }\n    case '$': {\n      if (*(p+1) == '\\0')  /* is the `$' the last char in pattern? */\n        return (s == ms->src_end) ? s : NULL;  /* check end of string */\n      else goto dflt;\n    }\n    default: dflt: {  /* it is a pattern item */\n      const char *ep = classend(ms, p);  /* points to what is next */\n      int m = s<ms->src_end && singlematch(uchar(*s), p, ep);\n      switch (*ep) {\n        case '?': {  /* optional */\n          const char *res;\n          if (m && ((res=match(ms, s+1, ep+1)) != NULL))\n            return res;\n          p=ep+1; goto init;  /* else return match(ms, s, ep+1); */\n        }\n        case '*': {  /* 0 or more repetitions */\n          return max_expand(ms, s, p, ep);\n        }\n        case '+': {  /* 1 or more repetitions */\n          return (m ? max_expand(ms, s+1, p, ep) : NULL);\n        }\n        case '-': {  /* 0 or more repetitions (minimum) */\n          return min_expand(ms, s, p, ep);\n        }\n        default: {\n          if (!m) return NULL;\n          s++; p=ep; goto init;  /* else return match(ms, s+1, ep); */\n        }\n      }\n    }\n  }\n}\n\n\n\nstatic const char *lmemfind (const char *s1, size_t l1,\n                               const char *s2, size_t l2) {\n  if (l2 == 0) return s1;  /* empty strings are everywhere */\n  else if (l2 > l1) return NULL;  /* avoids a negative `l1' */\n  else {\n    const char *init;  /* to search for a `*s2' inside `s1' */\n    l2--;  /* 1st char will be checked by `memchr' */\n    l1 = l1-l2;  /* `s2' cannot be found after that */\n    while (l1 > 0 && (init = (const char *)memchr(s1, *s2, l1)) != NULL) {\n      init++;   /* 1st char is already checked */\n      if (memcmp(init, s2+1, l2) == 0)\n        return init-1;\n      else {  /* correct `l1' and `s1' to try again */\n        l1 -= init-s1;\n        s1 = init;\n      }\n    }\n    return NULL;  /* not found */\n  }\n}\n\n\nstatic void push_onecapture (MatchState *ms, int i, const char *s,\n                                                    const char *e) {\n  if (i >= ms->level) {\n    if (i == 0)  /* ms->level == 0, too */\n      lua_pushlstring(ms->L, s, e - s);  /* add whole match */\n    else\n      luaL_error(ms->L, \"invalid capture index\");\n  }\n  else {\n    ptrdiff_t l = ms->capture[i].len;\n    if (l == CAP_UNFINISHED) luaL_error(ms->L, \"unfinished capture\");\n    if (l == CAP_POSITION)\n      lua_pushinteger(ms->L, ms->capture[i].init - ms->src_init + 1);\n    else\n      lua_pushlstring(ms->L, ms->capture[i].init, l);\n  }\n}\n\n\nstatic int push_captures (MatchState *ms, const char *s, const char *e) {\n  int i;\n  int nlevels = (ms->level == 0 && s) ? 1 : ms->level;\n  luaL_checkstack(ms->L, nlevels, \"too many captures\");\n  for (i = 0; i < nlevels; i++)\n    push_onecapture(ms, i, s, e);\n  return nlevels;  /* number of strings pushed */\n}\n\n\nstatic int str_find_aux (lua_State *L, int find) {\n  size_t l1, l2;\n  const char *s = luaL_checklstring(L, 1, &l1);\n  const char *p = luaL_checklstring(L, 2, &l2);\n  ptrdiff_t init = posrelat(luaL_optinteger(L, 3, 1), l1) - 1;\n  if (init < 0) init = 0;\n  else if ((size_t)(init) > l1) init = (ptrdiff_t)l1;\n  if (find && (lua_toboolean(L, 4) ||  /* explicit request? */\n      strpbrk(p, SPECIALS) == NULL)) {  /* or no special characters? */\n    /* do a plain search */\n    const char *s2 = lmemfind(s+init, l1-init, p, l2);\n    if (s2) {\n      lua_pushinteger(L, s2-s+1);\n      lua_pushinteger(L, s2-s+l2);\n      return 2;\n    }\n  }\n  else {\n    MatchState ms;\n    int anchor = (*p == '^') ? (p++, 1) : 0;\n    const char *s1=s+init;\n    ms.L = L;\n    ms.src_init = s;\n    ms.src_end = s+l1;\n    do {\n      const char *res;\n      ms.level = 0;\n      if ((res=match(&ms, s1, p)) != NULL) {\n        if (find) {\n          lua_pushinteger(L, s1-s+1);  /* start */\n          lua_pushinteger(L, res-s);   /* end */\n          return push_captures(&ms, NULL, 0) + 2;\n        }\n        else\n          return push_captures(&ms, s1, res);\n      }\n    } while (s1++ < ms.src_end && !anchor);\n  }\n  lua_pushnil(L);  /* not found */\n  return 1;\n}\n\n\nstatic int str_find (lua_State *L) {\n  return str_find_aux(L, 1);\n}\n\n\nstatic int str_match (lua_State *L) {\n  return str_find_aux(L, 0);\n}\n\n\nstatic int gmatch_aux (lua_State *L) {\n  MatchState ms;\n  size_t ls;\n  const char *s = lua_tolstring(L, lua_upvalueindex(1), &ls);\n  const char *p = lua_tostring(L, lua_upvalueindex(2));\n  const char *src;\n  ms.L = L;\n  ms.src_init = s;\n  ms.src_end = s+ls;\n  for (src = s + (size_t)lua_tointeger(L, lua_upvalueindex(3));\n       src <= ms.src_end;\n       src++) {\n    const char *e;\n    ms.level = 0;\n    if ((e = match(&ms, src, p)) != NULL) {\n      lua_Integer newstart = e-s;\n      if (e == src) newstart++;  /* empty match? go at least one position */\n      lua_pushinteger(L, newstart);\n      lua_replace(L, lua_upvalueindex(3));\n      return push_captures(&ms, src, e);\n    }\n  }\n  return 0;  /* not found */\n}\n\n\nstatic int gmatch (lua_State *L) {\n  luaL_checkstring(L, 1);\n  luaL_checkstring(L, 2);\n  lua_settop(L, 2);\n  lua_pushinteger(L, 0);\n  lua_pushcclosure(L, gmatch_aux, 3);\n  return 1;\n}\n\n\nstatic int gfind_nodef (lua_State *L) {\n  return luaL_error(L, LUA_QL(\"string.gfind\") \" was renamed to \"\n                       LUA_QL(\"string.gmatch\"));\n}\n\n\nstatic void add_s (MatchState *ms, luaL_Buffer *b, const char *s,\n                                                   const char *e) {\n  size_t l, i;\n  const char *news = lua_tolstring(ms->L, 3, &l);\n  for (i = 0; i < l; i++) {\n    if (news[i] != L_ESC)\n      luaL_addchar(b, news[i]);\n    else {\n      i++;  /* skip ESC */\n      if (!isdigit(uchar(news[i])))\n        luaL_addchar(b, news[i]);\n      else if (news[i] == '0')\n          luaL_addlstring(b, s, e - s);\n      else {\n        push_onecapture(ms, news[i] - '1', s, e);\n        luaL_addvalue(b);  /* add capture to accumulated result */\n      }\n    }\n  }\n}\n\n\nstatic void add_value (MatchState *ms, luaL_Buffer *b, const char *s,\n                                                       const char *e) {\n  lua_State *L = ms->L;\n  switch (lua_type(L, 3)) {\n    case LUA_TNUMBER:\n    case LUA_TSTRING: {\n      add_s(ms, b, s, e);\n      return;\n    }\n    case LUA_TFUNCTION: {\n      int n;\n      lua_pushvalue(L, 3);\n      n = push_captures(ms, s, e);\n      lua_call(L, n, 1);\n      break;\n    }\n    case LUA_TTABLE: {\n      push_onecapture(ms, 0, s, e);\n      lua_gettable(L, 3);\n      break;\n    }\n  }\n  if (!lua_toboolean(L, -1)) {  /* nil or false? */\n    lua_pop(L, 1);\n    lua_pushlstring(L, s, e - s);  /* keep original text */\n  }\n  else if (!lua_isstring(L, -1))\n    luaL_error(L, \"invalid replacement value (a %s)\", luaL_typename(L, -1)); \n  luaL_addvalue(b);  /* add result to accumulator */\n}\n\n\nstatic int str_gsub (lua_State *L) {\n  size_t srcl;\n  const char *src = luaL_checklstring(L, 1, &srcl);\n  const char *p = luaL_checkstring(L, 2);\n  int  tr = lua_type(L, 3);\n  int max_s = luaL_optint(L, 4, srcl+1);\n  int anchor = (*p == '^') ? (p++, 1) : 0;\n  int n = 0;\n  MatchState ms;\n  luaL_Buffer b;\n  luaL_argcheck(L, tr == LUA_TNUMBER || tr == LUA_TSTRING ||\n                   tr == LUA_TFUNCTION || tr == LUA_TTABLE, 3,\n                      \"string/function/table expected\");\n  luaL_buffinit(L, &b);\n  ms.L = L;\n  ms.src_init = src;\n  ms.src_end = src+srcl;\n  while (n < max_s) {\n    const char *e;\n    ms.level = 0;\n    e = match(&ms, src, p);\n    if (e) {\n      n++;\n      add_value(&ms, &b, src, e);\n    }\n    if (e && e>src) /* non empty match? */\n      src = e;  /* skip it */\n    else if (src < ms.src_end)\n      luaL_addchar(&b, *src++);\n    else break;\n    if (anchor) break;\n  }\n  luaL_addlstring(&b, src, ms.src_end-src);\n  luaL_pushresult(&b);\n  lua_pushinteger(L, n);  /* number of substitutions */\n  return 2;\n}\n\n/* }====================================================== */\n\n\n/* maximum size of each formatted item (> len(format('%99.99f', -1e308))) */\n#define MAX_ITEM\t512\n/* valid flags in a format specification */\n#define FLAGS\t\"-+ #0\"\n/*\n** maximum size of each format specification (such as '%-099.99d')\n** (+10 accounts for %99.99x plus margin of error)\n*/\n#define MAX_FORMAT\t(sizeof(FLAGS) + sizeof(LUA_INTFRMLEN) + 10)\n\n\nstatic void addquoted (lua_State *L, luaL_Buffer *b, int arg) {\n  size_t l;\n  const char *s = luaL_checklstring(L, arg, &l);\n  luaL_addchar(b, '\"');\n  while (l--) {\n    switch (*s) {\n      case '\"': case '\\\\': case '\\n': {\n        luaL_addchar(b, '\\\\');\n        luaL_addchar(b, *s);\n        break;\n      }\n      case '\\r': {\n        luaL_addlstring(b, \"\\\\r\", 2);\n        break;\n      }\n      case '\\0': {\n        luaL_addlstring(b, \"\\\\000\", 4);\n        break;\n      }\n      default: {\n        luaL_addchar(b, *s);\n        break;\n      }\n    }\n    s++;\n  }\n  luaL_addchar(b, '\"');\n}\n\nstatic const char *scanformat (lua_State *L, const char *strfrmt, char *form) {\n  const char *p = strfrmt;\n  while (*p != '\\0' && strchr(FLAGS, *p) != NULL) p++;  /* skip flags */\n  if ((size_t)(p - strfrmt) >= sizeof(FLAGS))\n    luaL_error(L, \"invalid format (repeated flags)\");\n  if (isdigit(uchar(*p))) p++;  /* skip width */\n  if (isdigit(uchar(*p))) p++;  /* (2 digits at most) */\n  if (*p == '.') {\n    p++;\n    if (isdigit(uchar(*p))) p++;  /* skip precision */\n    if (isdigit(uchar(*p))) p++;  /* (2 digits at most) */\n  }\n  if (isdigit(uchar(*p)))\n    luaL_error(L, \"invalid format (width or precision too long)\");\n  *(form++) = '%';\n  strncpy(form, strfrmt, p - strfrmt + 1);\n  form += p - strfrmt + 1;\n  *form = '\\0';\n  return p;\n}\n\n\nstatic void addintlen (char *form) {\n  size_t l = strlen(form);\n  char spec = form[l - 1];\n  strcpy(form + l - 1, LUA_INTFRMLEN);\n  form[l + sizeof(LUA_INTFRMLEN) - 2] = spec;\n  form[l + sizeof(LUA_INTFRMLEN) - 1] = '\\0';\n}\n\n\nstatic int str_format (lua_State *L) {\n  int top = lua_gettop(L);\n  int arg = 1;\n  size_t sfl;\n  const char *strfrmt = luaL_checklstring(L, arg, &sfl);\n  const char *strfrmt_end = strfrmt+sfl;\n  luaL_Buffer b;\n  luaL_buffinit(L, &b);\n  while (strfrmt < strfrmt_end) {\n    if (*strfrmt != L_ESC)\n      luaL_addchar(&b, *strfrmt++);\n    else if (*++strfrmt == L_ESC)\n      luaL_addchar(&b, *strfrmt++);  /* %% */\n    else { /* format item */\n      char form[MAX_FORMAT];  /* to store the format (`%...') */\n      char buff[MAX_ITEM];  /* to store the formatted item */\n      if (++arg > top)\n        luaL_argerror(L, arg, \"no value\");\n      strfrmt = scanformat(L, strfrmt, form);\n      switch (*strfrmt++) {\n        case 'c': {\n          sprintf(buff, form, (int)luaL_checknumber(L, arg));\n          break;\n        }\n        case 'd':  case 'i': {\n          addintlen(form);\n          sprintf(buff, form, (LUA_INTFRM_T)luaL_checknumber(L, arg));\n          break;\n        }\n        case 'o':  case 'u':  case 'x':  case 'X': {\n          addintlen(form);\n          sprintf(buff, form, (unsigned LUA_INTFRM_T)luaL_checknumber(L, arg));\n          break;\n        }\n        case 'e':  case 'E': case 'f':\n        case 'g': case 'G': {\n          sprintf(buff, form, (double)luaL_checknumber(L, arg));\n          break;\n        }\n        case 'q': {\n          addquoted(L, &b, arg);\n          continue;  /* skip the 'addsize' at the end */\n        }\n        case 's': {\n          size_t l;\n          const char *s = luaL_checklstring(L, arg, &l);\n          if (!strchr(form, '.') && l >= 100) {\n            /* no precision and string is too long to be formatted;\n               keep original string */\n            lua_pushvalue(L, arg);\n            luaL_addvalue(&b);\n            continue;  /* skip the `addsize' at the end */\n          }\n          else {\n            sprintf(buff, form, s);\n            break;\n          }\n        }\n        default: {  /* also treat cases `pnLlh' */\n          return luaL_error(L, \"invalid option \" LUA_QL(\"%%%c\") \" to \"\n                               LUA_QL(\"format\"), *(strfrmt - 1));\n        }\n      }\n      luaL_addlstring(&b, buff, strlen(buff));\n    }\n  }\n  luaL_pushresult(&b);\n  return 1;\n}\n\n\nstatic const luaL_Reg strlib[] = {\n  {\"byte\", str_byte},\n  {\"char\", str_char},\n  {\"dump\", str_dump},\n  {\"find\", str_find},\n  {\"format\", str_format},\n  {\"gfind\", gfind_nodef},\n  {\"gmatch\", gmatch},\n  {\"gsub\", str_gsub},\n  {\"len\", str_len},\n  {\"lower\", str_lower},\n  {\"match\", str_match},\n  {\"rep\", str_rep},\n  {\"reverse\", str_reverse},\n  {\"sub\", str_sub},\n  {\"upper\", str_upper},\n  {NULL, NULL}\n};\n\n\nstatic void createmetatable (lua_State *L) {\n  lua_createtable(L, 0, 1);  /* create metatable for strings */\n  lua_pushliteral(L, \"\");  /* dummy string */\n  lua_pushvalue(L, -2);\n  lua_setmetatable(L, -2);  /* set string metatable */\n  lua_pop(L, 1);  /* pop dummy string */\n  lua_pushvalue(L, -2);  /* string library... */\n  lua_setfield(L, -2, \"__index\");  /* ...is the __index metamethod */\n  lua_pop(L, 1);  /* pop metatable */\n}\n\n\n/*\n** Open string library\n*/\nLUALIB_API int luaopen_string (lua_State *L) {\n  luaL_register(L, LUA_STRLIBNAME, strlib);\n#if defined(LUA_COMPAT_GFIND)\n  lua_getfield(L, -1, \"gmatch\");\n  lua_setfield(L, -2, \"gfind\");\n#endif\n  createmetatable(L);\n  return 1;\n}\n\n"
  },
  {
    "path": "extern/deprecated/redis-2.8.21/deps/lua/src/ltable.c",
    "content": "/*\n** $Id: ltable.c,v 2.32.1.2 2007/12/28 15:32:23 roberto Exp $\n** Lua tables (hash)\n** See Copyright Notice in lua.h\n*/\n\n\n/*\n** Implementation of tables (aka arrays, objects, or hash tables).\n** Tables keep its elements in two parts: an array part and a hash part.\n** Non-negative integer keys are all candidates to be kept in the array\n** part. The actual size of the array is the largest `n' such that at\n** least half the slots between 0 and n are in use.\n** Hash uses a mix of chained scatter table with Brent's variation.\n** A main invariant of these tables is that, if an element is not\n** in its main position (i.e. the `original' position that its hash gives\n** to it), then the colliding element is in its own main position.\n** Hence even when the load factor reaches 100%, performance remains good.\n*/\n\n#include <math.h>\n#include <string.h>\n\n#define ltable_c\n#define LUA_CORE\n\n#include \"lua.h\"\n\n#include \"ldebug.h\"\n#include \"ldo.h\"\n#include \"lgc.h\"\n#include \"lmem.h\"\n#include \"lobject.h\"\n#include \"lstate.h\"\n#include \"ltable.h\"\n\n\n/*\n** max size of array part is 2^MAXBITS\n*/\n#if LUAI_BITSINT > 26\n#define MAXBITS\t\t26\n#else\n#define MAXBITS\t\t(LUAI_BITSINT-2)\n#endif\n\n#define MAXASIZE\t(1 << MAXBITS)\n\n\n#define hashpow2(t,n)      (gnode(t, lmod((n), sizenode(t))))\n  \n#define hashstr(t,str)  hashpow2(t, (str)->tsv.hash)\n#define hashboolean(t,p)        hashpow2(t, p)\n\n\n/*\n** for some types, it is better to avoid modulus by power of 2, as\n** they tend to have many 2 factors.\n*/\n#define hashmod(t,n)\t(gnode(t, ((n) % ((sizenode(t)-1)|1))))\n\n\n#define hashpointer(t,p)\thashmod(t, IntPoint(p))\n\n\n/*\n** number of ints inside a lua_Number\n*/\n#define numints\t\tcast_int(sizeof(lua_Number)/sizeof(int))\n\n\n\n#define dummynode\t\t(&dummynode_)\n\nstatic const Node dummynode_ = {\n  {{NULL}, LUA_TNIL},  /* value */\n  {{{NULL}, LUA_TNIL, NULL}}  /* key */\n};\n\n\n/*\n** hash for lua_Numbers\n*/\nstatic Node *hashnum (const Table *t, lua_Number n) {\n  unsigned int a[numints];\n  int i;\n  if (luai_numeq(n, 0))  /* avoid problems with -0 */\n    return gnode(t, 0);\n  memcpy(a, &n, sizeof(a));\n  for (i = 1; i < numints; i++) a[0] += a[i];\n  return hashmod(t, a[0]);\n}\n\n\n\n/*\n** returns the `main' position of an element in a table (that is, the index\n** of its hash value)\n*/\nstatic Node *mainposition (const Table *t, const TValue *key) {\n  switch (ttype(key)) {\n    case LUA_TNUMBER:\n      return hashnum(t, nvalue(key));\n    case LUA_TSTRING:\n      return hashstr(t, rawtsvalue(key));\n    case LUA_TBOOLEAN:\n      return hashboolean(t, bvalue(key));\n    case LUA_TLIGHTUSERDATA:\n      return hashpointer(t, pvalue(key));\n    default:\n      return hashpointer(t, gcvalue(key));\n  }\n}\n\n\n/*\n** returns the index for `key' if `key' is an appropriate key to live in\n** the array part of the table, -1 otherwise.\n*/\nstatic int arrayindex (const TValue *key) {\n  if (ttisnumber(key)) {\n    lua_Number n = nvalue(key);\n    int k;\n    lua_number2int(k, n);\n    if (luai_numeq(cast_num(k), n))\n      return k;\n  }\n  return -1;  /* `key' did not match some condition */\n}\n\n\n/*\n** returns the index of a `key' for table traversals. First goes all\n** elements in the array part, then elements in the hash part. The\n** beginning of a traversal is signalled by -1.\n*/\nstatic int findindex (lua_State *L, Table *t, StkId key) {\n  int i;\n  if (ttisnil(key)) return -1;  /* first iteration */\n  i = arrayindex(key);\n  if (0 < i && i <= t->sizearray)  /* is `key' inside array part? */\n    return i-1;  /* yes; that's the index (corrected to C) */\n  else {\n    Node *n = mainposition(t, key);\n    do {  /* check whether `key' is somewhere in the chain */\n      /* key may be dead already, but it is ok to use it in `next' */\n      if (luaO_rawequalObj(key2tval(n), key) ||\n            (ttype(gkey(n)) == LUA_TDEADKEY && iscollectable(key) &&\n             gcvalue(gkey(n)) == gcvalue(key))) {\n        i = cast_int(n - gnode(t, 0));  /* key index in hash table */\n        /* hash elements are numbered after array ones */\n        return i + t->sizearray;\n      }\n      else n = gnext(n);\n    } while (n);\n    luaG_runerror(L, \"invalid key to \" LUA_QL(\"next\"));  /* key not found */\n    return 0;  /* to avoid warnings */\n  }\n}\n\n\nint luaH_next (lua_State *L, Table *t, StkId key) {\n  int i = findindex(L, t, key);  /* find original element */\n  for (i++; i < t->sizearray; i++) {  /* try first array part */\n    if (!ttisnil(&t->array[i])) {  /* a non-nil value? */\n      setnvalue(key, cast_num(i+1));\n      setobj2s(L, key+1, &t->array[i]);\n      return 1;\n    }\n  }\n  for (i -= t->sizearray; i < sizenode(t); i++) {  /* then hash part */\n    if (!ttisnil(gval(gnode(t, i)))) {  /* a non-nil value? */\n      setobj2s(L, key, key2tval(gnode(t, i)));\n      setobj2s(L, key+1, gval(gnode(t, i)));\n      return 1;\n    }\n  }\n  return 0;  /* no more elements */\n}\n\n\n/*\n** {=============================================================\n** Rehash\n** ==============================================================\n*/\n\n\nstatic int computesizes (int nums[], int *narray) {\n  int i;\n  int twotoi;  /* 2^i */\n  int a = 0;  /* number of elements smaller than 2^i */\n  int na = 0;  /* number of elements to go to array part */\n  int n = 0;  /* optimal size for array part */\n  for (i = 0, twotoi = 1; twotoi/2 < *narray; i++, twotoi *= 2) {\n    if (nums[i] > 0) {\n      a += nums[i];\n      if (a > twotoi/2) {  /* more than half elements present? */\n        n = twotoi;  /* optimal size (till now) */\n        na = a;  /* all elements smaller than n will go to array part */\n      }\n    }\n    if (a == *narray) break;  /* all elements already counted */\n  }\n  *narray = n;\n  lua_assert(*narray/2 <= na && na <= *narray);\n  return na;\n}\n\n\nstatic int countint (const TValue *key, int *nums) {\n  int k = arrayindex(key);\n  if (0 < k && k <= MAXASIZE) {  /* is `key' an appropriate array index? */\n    nums[ceillog2(k)]++;  /* count as such */\n    return 1;\n  }\n  else\n    return 0;\n}\n\n\nstatic int numusearray (const Table *t, int *nums) {\n  int lg;\n  int ttlg;  /* 2^lg */\n  int ause = 0;  /* summation of `nums' */\n  int i = 1;  /* count to traverse all array keys */\n  for (lg=0, ttlg=1; lg<=MAXBITS; lg++, ttlg*=2) {  /* for each slice */\n    int lc = 0;  /* counter */\n    int lim = ttlg;\n    if (lim > t->sizearray) {\n      lim = t->sizearray;  /* adjust upper limit */\n      if (i > lim)\n        break;  /* no more elements to count */\n    }\n    /* count elements in range (2^(lg-1), 2^lg] */\n    for (; i <= lim; i++) {\n      if (!ttisnil(&t->array[i-1]))\n        lc++;\n    }\n    nums[lg] += lc;\n    ause += lc;\n  }\n  return ause;\n}\n\n\nstatic int numusehash (const Table *t, int *nums, int *pnasize) {\n  int totaluse = 0;  /* total number of elements */\n  int ause = 0;  /* summation of `nums' */\n  int i = sizenode(t);\n  while (i--) {\n    Node *n = &t->node[i];\n    if (!ttisnil(gval(n))) {\n      ause += countint(key2tval(n), nums);\n      totaluse++;\n    }\n  }\n  *pnasize += ause;\n  return totaluse;\n}\n\n\nstatic void setarrayvector (lua_State *L, Table *t, int size) {\n  int i;\n  luaM_reallocvector(L, t->array, t->sizearray, size, TValue);\n  for (i=t->sizearray; i<size; i++)\n     setnilvalue(&t->array[i]);\n  t->sizearray = size;\n}\n\n\nstatic void setnodevector (lua_State *L, Table *t, int size) {\n  int lsize;\n  if (size == 0) {  /* no elements to hash part? */\n    t->node = cast(Node *, dummynode);  /* use common `dummynode' */\n    lsize = 0;\n  }\n  else {\n    int i;\n    lsize = ceillog2(size);\n    if (lsize > MAXBITS)\n      luaG_runerror(L, \"table overflow\");\n    size = twoto(lsize);\n    t->node = luaM_newvector(L, size, Node);\n    for (i=0; i<size; i++) {\n      Node *n = gnode(t, i);\n      gnext(n) = NULL;\n      setnilvalue(gkey(n));\n      setnilvalue(gval(n));\n    }\n  }\n  t->lsizenode = cast_byte(lsize);\n  t->lastfree = gnode(t, size);  /* all positions are free */\n}\n\n\nstatic void resize (lua_State *L, Table *t, int nasize, int nhsize) {\n  int i;\n  int oldasize = t->sizearray;\n  int oldhsize = t->lsizenode;\n  Node *nold = t->node;  /* save old hash ... */\n  if (nasize > oldasize)  /* array part must grow? */\n    setarrayvector(L, t, nasize);\n  /* create new hash part with appropriate size */\n  setnodevector(L, t, nhsize);  \n  if (nasize < oldasize) {  /* array part must shrink? */\n    t->sizearray = nasize;\n    /* re-insert elements from vanishing slice */\n    for (i=nasize; i<oldasize; i++) {\n      if (!ttisnil(&t->array[i]))\n        setobjt2t(L, luaH_setnum(L, t, i+1), &t->array[i]);\n    }\n    /* shrink array */\n    luaM_reallocvector(L, t->array, oldasize, nasize, TValue);\n  }\n  /* re-insert elements from hash part */\n  for (i = twoto(oldhsize) - 1; i >= 0; i--) {\n    Node *old = nold+i;\n    if (!ttisnil(gval(old)))\n      setobjt2t(L, luaH_set(L, t, key2tval(old)), gval(old));\n  }\n  if (nold != dummynode)\n    luaM_freearray(L, nold, twoto(oldhsize), Node);  /* free old array */\n}\n\n\nvoid luaH_resizearray (lua_State *L, Table *t, int nasize) {\n  int nsize = (t->node == dummynode) ? 0 : sizenode(t);\n  resize(L, t, nasize, nsize);\n}\n\n\nstatic void rehash (lua_State *L, Table *t, const TValue *ek) {\n  int nasize, na;\n  int nums[MAXBITS+1];  /* nums[i] = number of keys between 2^(i-1) and 2^i */\n  int i;\n  int totaluse;\n  for (i=0; i<=MAXBITS; i++) nums[i] = 0;  /* reset counts */\n  nasize = numusearray(t, nums);  /* count keys in array part */\n  totaluse = nasize;  /* all those keys are integer keys */\n  totaluse += numusehash(t, nums, &nasize);  /* count keys in hash part */\n  /* count extra key */\n  nasize += countint(ek, nums);\n  totaluse++;\n  /* compute new size for array part */\n  na = computesizes(nums, &nasize);\n  /* resize the table to new computed sizes */\n  resize(L, t, nasize, totaluse - na);\n}\n\n\n\n/*\n** }=============================================================\n*/\n\n\nTable *luaH_new (lua_State *L, int narray, int nhash) {\n  Table *t = luaM_new(L, Table);\n  luaC_link(L, obj2gco(t), LUA_TTABLE);\n  t->metatable = NULL;\n  t->flags = cast_byte(~0);\n  /* temporary values (kept only if some malloc fails) */\n  t->array = NULL;\n  t->sizearray = 0;\n  t->lsizenode = 0;\n  t->node = cast(Node *, dummynode);\n  setarrayvector(L, t, narray);\n  setnodevector(L, t, nhash);\n  return t;\n}\n\n\nvoid luaH_free (lua_State *L, Table *t) {\n  if (t->node != dummynode)\n    luaM_freearray(L, t->node, sizenode(t), Node);\n  luaM_freearray(L, t->array, t->sizearray, TValue);\n  luaM_free(L, t);\n}\n\n\nstatic Node *getfreepos (Table *t) {\n  while (t->lastfree-- > t->node) {\n    if (ttisnil(gkey(t->lastfree)))\n      return t->lastfree;\n  }\n  return NULL;  /* could not find a free place */\n}\n\n\n\n/*\n** inserts a new key into a hash table; first, check whether key's main \n** position is free. If not, check whether colliding node is in its main \n** position or not: if it is not, move colliding node to an empty place and \n** put new key in its main position; otherwise (colliding node is in its main \n** position), new key goes to an empty position. \n*/\nstatic TValue *newkey (lua_State *L, Table *t, const TValue *key) {\n  Node *mp = mainposition(t, key);\n  if (!ttisnil(gval(mp)) || mp == dummynode) {\n    Node *othern;\n    Node *n = getfreepos(t);  /* get a free place */\n    if (n == NULL) {  /* cannot find a free place? */\n      rehash(L, t, key);  /* grow table */\n      return luaH_set(L, t, key);  /* re-insert key into grown table */\n    }\n    lua_assert(n != dummynode);\n    othern = mainposition(t, key2tval(mp));\n    if (othern != mp) {  /* is colliding node out of its main position? */\n      /* yes; move colliding node into free position */\n      while (gnext(othern) != mp) othern = gnext(othern);  /* find previous */\n      gnext(othern) = n;  /* redo the chain with `n' in place of `mp' */\n      *n = *mp;  /* copy colliding node into free pos. (mp->next also goes) */\n      gnext(mp) = NULL;  /* now `mp' is free */\n      setnilvalue(gval(mp));\n    }\n    else {  /* colliding node is in its own main position */\n      /* new node will go into free position */\n      gnext(n) = gnext(mp);  /* chain new position */\n      gnext(mp) = n;\n      mp = n;\n    }\n  }\n  gkey(mp)->value = key->value; gkey(mp)->tt = key->tt;\n  luaC_barriert(L, t, key);\n  lua_assert(ttisnil(gval(mp)));\n  return gval(mp);\n}\n\n\n/*\n** search function for integers\n*/\nconst TValue *luaH_getnum (Table *t, int key) {\n  /* (1 <= key && key <= t->sizearray) */\n  if (cast(unsigned int, key-1) < cast(unsigned int, t->sizearray))\n    return &t->array[key-1];\n  else {\n    lua_Number nk = cast_num(key);\n    Node *n = hashnum(t, nk);\n    do {  /* check whether `key' is somewhere in the chain */\n      if (ttisnumber(gkey(n)) && luai_numeq(nvalue(gkey(n)), nk))\n        return gval(n);  /* that's it */\n      else n = gnext(n);\n    } while (n);\n    return luaO_nilobject;\n  }\n}\n\n\n/*\n** search function for strings\n*/\nconst TValue *luaH_getstr (Table *t, TString *key) {\n  Node *n = hashstr(t, key);\n  do {  /* check whether `key' is somewhere in the chain */\n    if (ttisstring(gkey(n)) && rawtsvalue(gkey(n)) == key)\n      return gval(n);  /* that's it */\n    else n = gnext(n);\n  } while (n);\n  return luaO_nilobject;\n}\n\n\n/*\n** main search function\n*/\nconst TValue *luaH_get (Table *t, const TValue *key) {\n  switch (ttype(key)) {\n    case LUA_TNIL: return luaO_nilobject;\n    case LUA_TSTRING: return luaH_getstr(t, rawtsvalue(key));\n    case LUA_TNUMBER: {\n      int k;\n      lua_Number n = nvalue(key);\n      lua_number2int(k, n);\n      if (luai_numeq(cast_num(k), nvalue(key))) /* index is int? */\n        return luaH_getnum(t, k);  /* use specialized version */\n      /* else go through */\n    }\n    default: {\n      Node *n = mainposition(t, key);\n      do {  /* check whether `key' is somewhere in the chain */\n        if (luaO_rawequalObj(key2tval(n), key))\n          return gval(n);  /* that's it */\n        else n = gnext(n);\n      } while (n);\n      return luaO_nilobject;\n    }\n  }\n}\n\n\nTValue *luaH_set (lua_State *L, Table *t, const TValue *key) {\n  const TValue *p = luaH_get(t, key);\n  t->flags = 0;\n  if (p != luaO_nilobject)\n    return cast(TValue *, p);\n  else {\n    if (ttisnil(key)) luaG_runerror(L, \"table index is nil\");\n    else if (ttisnumber(key) && luai_numisnan(nvalue(key)))\n      luaG_runerror(L, \"table index is NaN\");\n    return newkey(L, t, key);\n  }\n}\n\n\nTValue *luaH_setnum (lua_State *L, Table *t, int key) {\n  const TValue *p = luaH_getnum(t, key);\n  if (p != luaO_nilobject)\n    return cast(TValue *, p);\n  else {\n    TValue k;\n    setnvalue(&k, cast_num(key));\n    return newkey(L, t, &k);\n  }\n}\n\n\nTValue *luaH_setstr (lua_State *L, Table *t, TString *key) {\n  const TValue *p = luaH_getstr(t, key);\n  if (p != luaO_nilobject)\n    return cast(TValue *, p);\n  else {\n    TValue k;\n    setsvalue(L, &k, key);\n    return newkey(L, t, &k);\n  }\n}\n\n\nstatic int unbound_search (Table *t, unsigned int j) {\n  unsigned int i = j;  /* i is zero or a present index */\n  j++;\n  /* find `i' and `j' such that i is present and j is not */\n  while (!ttisnil(luaH_getnum(t, j))) {\n    i = j;\n    j *= 2;\n    if (j > cast(unsigned int, MAX_INT)) {  /* overflow? */\n      /* table was built with bad purposes: resort to linear search */\n      i = 1;\n      while (!ttisnil(luaH_getnum(t, i))) i++;\n      return i - 1;\n    }\n  }\n  /* now do a binary search between them */\n  while (j - i > 1) {\n    unsigned int m = (i+j)/2;\n    if (ttisnil(luaH_getnum(t, m))) j = m;\n    else i = m;\n  }\n  return i;\n}\n\n\n/*\n** Try to find a boundary in table `t'. A `boundary' is an integer index\n** such that t[i] is non-nil and t[i+1] is nil (and 0 if t[1] is nil).\n*/\nint luaH_getn (Table *t) {\n  unsigned int j = t->sizearray;\n  if (j > 0 && ttisnil(&t->array[j - 1])) {\n    /* there is a boundary in the array part: (binary) search for it */\n    unsigned int i = 0;\n    while (j - i > 1) {\n      unsigned int m = (i+j)/2;\n      if (ttisnil(&t->array[m - 1])) j = m;\n      else i = m;\n    }\n    return i;\n  }\n  /* else must find a boundary in hash part */\n  else if (t->node == dummynode)  /* hash part is empty? */\n    return j;  /* that is easy... */\n  else return unbound_search(t, j);\n}\n\n\n\n#if defined(LUA_DEBUG)\n\nNode *luaH_mainposition (const Table *t, const TValue *key) {\n  return mainposition(t, key);\n}\n\nint luaH_isdummy (Node *n) { return n == dummynode; }\n\n#endif\n"
  },
  {
    "path": "extern/deprecated/redis-2.8.21/deps/lua/src/ltable.h",
    "content": "/*\n** $Id: ltable.h,v 2.10.1.1 2007/12/27 13:02:25 roberto Exp $\n** Lua tables (hash)\n** See Copyright Notice in lua.h\n*/\n\n#ifndef ltable_h\n#define ltable_h\n\n#include \"lobject.h\"\n\n\n#define gnode(t,i)\t(&(t)->node[i])\n#define gkey(n)\t\t(&(n)->i_key.nk)\n#define gval(n)\t\t(&(n)->i_val)\n#define gnext(n)\t((n)->i_key.nk.next)\n\n#define key2tval(n)\t(&(n)->i_key.tvk)\n\n\nLUAI_FUNC const TValue *luaH_getnum (Table *t, int key);\nLUAI_FUNC TValue *luaH_setnum (lua_State *L, Table *t, int key);\nLUAI_FUNC const TValue *luaH_getstr (Table *t, TString *key);\nLUAI_FUNC TValue *luaH_setstr (lua_State *L, Table *t, TString *key);\nLUAI_FUNC const TValue *luaH_get (Table *t, const TValue *key);\nLUAI_FUNC TValue *luaH_set (lua_State *L, Table *t, const TValue *key);\nLUAI_FUNC Table *luaH_new (lua_State *L, int narray, int lnhash);\nLUAI_FUNC void luaH_resizearray (lua_State *L, Table *t, int nasize);\nLUAI_FUNC void luaH_free (lua_State *L, Table *t);\nLUAI_FUNC int luaH_next (lua_State *L, Table *t, StkId key);\nLUAI_FUNC int luaH_getn (Table *t);\n\n\n#if defined(LUA_DEBUG)\nLUAI_FUNC Node *luaH_mainposition (const Table *t, const TValue *key);\nLUAI_FUNC int luaH_isdummy (Node *n);\n#endif\n\n\n#endif\n"
  },
  {
    "path": "extern/deprecated/redis-2.8.21/deps/lua/src/ltablib.c",
    "content": "/*\n** $Id: ltablib.c,v 1.38.1.3 2008/02/14 16:46:58 roberto Exp $\n** Library for Table Manipulation\n** See Copyright Notice in lua.h\n*/\n\n\n#include <stddef.h>\n\n#define ltablib_c\n#define LUA_LIB\n\n#include \"lua.h\"\n\n#include \"lauxlib.h\"\n#include \"lualib.h\"\n\n\n#define aux_getn(L,n)\t(luaL_checktype(L, n, LUA_TTABLE), luaL_getn(L, n))\n\n\nstatic int foreachi (lua_State *L) {\n  int i;\n  int n = aux_getn(L, 1);\n  luaL_checktype(L, 2, LUA_TFUNCTION);\n  for (i=1; i <= n; i++) {\n    lua_pushvalue(L, 2);  /* function */\n    lua_pushinteger(L, i);  /* 1st argument */\n    lua_rawgeti(L, 1, i);  /* 2nd argument */\n    lua_call(L, 2, 1);\n    if (!lua_isnil(L, -1))\n      return 1;\n    lua_pop(L, 1);  /* remove nil result */\n  }\n  return 0;\n}\n\n\nstatic int foreach (lua_State *L) {\n  luaL_checktype(L, 1, LUA_TTABLE);\n  luaL_checktype(L, 2, LUA_TFUNCTION);\n  lua_pushnil(L);  /* first key */\n  while (lua_next(L, 1)) {\n    lua_pushvalue(L, 2);  /* function */\n    lua_pushvalue(L, -3);  /* key */\n    lua_pushvalue(L, -3);  /* value */\n    lua_call(L, 2, 1);\n    if (!lua_isnil(L, -1))\n      return 1;\n    lua_pop(L, 2);  /* remove value and result */\n  }\n  return 0;\n}\n\n\nstatic int maxn (lua_State *L) {\n  lua_Number max = 0;\n  luaL_checktype(L, 1, LUA_TTABLE);\n  lua_pushnil(L);  /* first key */\n  while (lua_next(L, 1)) {\n    lua_pop(L, 1);  /* remove value */\n    if (lua_type(L, -1) == LUA_TNUMBER) {\n      lua_Number v = lua_tonumber(L, -1);\n      if (v > max) max = v;\n    }\n  }\n  lua_pushnumber(L, max);\n  return 1;\n}\n\n\nstatic int getn (lua_State *L) {\n  lua_pushinteger(L, aux_getn(L, 1));\n  return 1;\n}\n\n\nstatic int setn (lua_State *L) {\n  luaL_checktype(L, 1, LUA_TTABLE);\n#ifndef luaL_setn\n  luaL_setn(L, 1, luaL_checkint(L, 2));\n#else\n  luaL_error(L, LUA_QL(\"setn\") \" is obsolete\");\n#endif\n  lua_pushvalue(L, 1);\n  return 1;\n}\n\n\nstatic int tinsert (lua_State *L) {\n  int e = aux_getn(L, 1) + 1;  /* first empty element */\n  int pos;  /* where to insert new element */\n  switch (lua_gettop(L)) {\n    case 2: {  /* called with only 2 arguments */\n      pos = e;  /* insert new element at the end */\n      break;\n    }\n    case 3: {\n      int i;\n      pos = luaL_checkint(L, 2);  /* 2nd argument is the position */\n      if (pos > e) e = pos;  /* `grow' array if necessary */\n      for (i = e; i > pos; i--) {  /* move up elements */\n        lua_rawgeti(L, 1, i-1);\n        lua_rawseti(L, 1, i);  /* t[i] = t[i-1] */\n      }\n      break;\n    }\n    default: {\n      return luaL_error(L, \"wrong number of arguments to \" LUA_QL(\"insert\"));\n    }\n  }\n  luaL_setn(L, 1, e);  /* new size */\n  lua_rawseti(L, 1, pos);  /* t[pos] = v */\n  return 0;\n}\n\n\nstatic int tremove (lua_State *L) {\n  int e = aux_getn(L, 1);\n  int pos = luaL_optint(L, 2, e);\n  if (!(1 <= pos && pos <= e))  /* position is outside bounds? */\n   return 0;  /* nothing to remove */\n  luaL_setn(L, 1, e - 1);  /* t.n = n-1 */\n  lua_rawgeti(L, 1, pos);  /* result = t[pos] */\n  for ( ;pos<e; pos++) {\n    lua_rawgeti(L, 1, pos+1);\n    lua_rawseti(L, 1, pos);  /* t[pos] = t[pos+1] */\n  }\n  lua_pushnil(L);\n  lua_rawseti(L, 1, e);  /* t[e] = nil */\n  return 1;\n}\n\n\nstatic void addfield (lua_State *L, luaL_Buffer *b, int i) {\n  lua_rawgeti(L, 1, i);\n  if (!lua_isstring(L, -1))\n    luaL_error(L, \"invalid value (%s) at index %d in table for \"\n                  LUA_QL(\"concat\"), luaL_typename(L, -1), i);\n    luaL_addvalue(b);\n}\n\n\nstatic int tconcat (lua_State *L) {\n  luaL_Buffer b;\n  size_t lsep;\n  int i, last;\n  const char *sep = luaL_optlstring(L, 2, \"\", &lsep);\n  luaL_checktype(L, 1, LUA_TTABLE);\n  i = luaL_optint(L, 3, 1);\n  last = luaL_opt(L, luaL_checkint, 4, luaL_getn(L, 1));\n  luaL_buffinit(L, &b);\n  for (; i < last; i++) {\n    addfield(L, &b, i);\n    luaL_addlstring(&b, sep, lsep);\n  }\n  if (i == last)  /* add last value (if interval was not empty) */\n    addfield(L, &b, i);\n  luaL_pushresult(&b);\n  return 1;\n}\n\n\n\n/*\n** {======================================================\n** Quicksort\n** (based on `Algorithms in MODULA-3', Robert Sedgewick;\n**  Addison-Wesley, 1993.)\n*/\n\n\nstatic void set2 (lua_State *L, int i, int j) {\n  lua_rawseti(L, 1, i);\n  lua_rawseti(L, 1, j);\n}\n\nstatic int sort_comp (lua_State *L, int a, int b) {\n  if (!lua_isnil(L, 2)) {  /* function? */\n    int res;\n    lua_pushvalue(L, 2);\n    lua_pushvalue(L, a-1);  /* -1 to compensate function */\n    lua_pushvalue(L, b-2);  /* -2 to compensate function and `a' */\n    lua_call(L, 2, 1);\n    res = lua_toboolean(L, -1);\n    lua_pop(L, 1);\n    return res;\n  }\n  else  /* a < b? */\n    return lua_lessthan(L, a, b);\n}\n\nstatic void auxsort (lua_State *L, int l, int u) {\n  while (l < u) {  /* for tail recursion */\n    int i, j;\n    /* sort elements a[l], a[(l+u)/2] and a[u] */\n    lua_rawgeti(L, 1, l);\n    lua_rawgeti(L, 1, u);\n    if (sort_comp(L, -1, -2))  /* a[u] < a[l]? */\n      set2(L, l, u);  /* swap a[l] - a[u] */\n    else\n      lua_pop(L, 2);\n    if (u-l == 1) break;  /* only 2 elements */\n    i = (l+u)/2;\n    lua_rawgeti(L, 1, i);\n    lua_rawgeti(L, 1, l);\n    if (sort_comp(L, -2, -1))  /* a[i]<a[l]? */\n      set2(L, i, l);\n    else {\n      lua_pop(L, 1);  /* remove a[l] */\n      lua_rawgeti(L, 1, u);\n      if (sort_comp(L, -1, -2))  /* a[u]<a[i]? */\n        set2(L, i, u);\n      else\n        lua_pop(L, 2);\n    }\n    if (u-l == 2) break;  /* only 3 elements */\n    lua_rawgeti(L, 1, i);  /* Pivot */\n    lua_pushvalue(L, -1);\n    lua_rawgeti(L, 1, u-1);\n    set2(L, i, u-1);\n    /* a[l] <= P == a[u-1] <= a[u], only need to sort from l+1 to u-2 */\n    i = l; j = u-1;\n    for (;;) {  /* invariant: a[l..i] <= P <= a[j..u] */\n      /* repeat ++i until a[i] >= P */\n      while (lua_rawgeti(L, 1, ++i), sort_comp(L, -1, -2)) {\n        if (i>u) luaL_error(L, \"invalid order function for sorting\");\n        lua_pop(L, 1);  /* remove a[i] */\n      }\n      /* repeat --j until a[j] <= P */\n      while (lua_rawgeti(L, 1, --j), sort_comp(L, -3, -1)) {\n        if (j<l) luaL_error(L, \"invalid order function for sorting\");\n        lua_pop(L, 1);  /* remove a[j] */\n      }\n      if (j<i) {\n        lua_pop(L, 3);  /* pop pivot, a[i], a[j] */\n        break;\n      }\n      set2(L, i, j);\n    }\n    lua_rawgeti(L, 1, u-1);\n    lua_rawgeti(L, 1, i);\n    set2(L, u-1, i);  /* swap pivot (a[u-1]) with a[i] */\n    /* a[l..i-1] <= a[i] == P <= a[i+1..u] */\n    /* adjust so that smaller half is in [j..i] and larger one in [l..u] */\n    if (i-l < u-i) {\n      j=l; i=i-1; l=i+2;\n    }\n    else {\n      j=i+1; i=u; u=j-2;\n    }\n    auxsort(L, j, i);  /* call recursively the smaller one */\n  }  /* repeat the routine for the larger one */\n}\n\nstatic int sort (lua_State *L) {\n  int n = aux_getn(L, 1);\n  luaL_checkstack(L, 40, \"\");  /* assume array is smaller than 2^40 */\n  if (!lua_isnoneornil(L, 2))  /* is there a 2nd argument? */\n    luaL_checktype(L, 2, LUA_TFUNCTION);\n  lua_settop(L, 2);  /* make sure there is two arguments */\n  auxsort(L, 1, n);\n  return 0;\n}\n\n/* }====================================================== */\n\n\nstatic const luaL_Reg tab_funcs[] = {\n  {\"concat\", tconcat},\n  {\"foreach\", foreach},\n  {\"foreachi\", foreachi},\n  {\"getn\", getn},\n  {\"maxn\", maxn},\n  {\"insert\", tinsert},\n  {\"remove\", tremove},\n  {\"setn\", setn},\n  {\"sort\", sort},\n  {NULL, NULL}\n};\n\n\nLUALIB_API int luaopen_table (lua_State *L) {\n  luaL_register(L, LUA_TABLIBNAME, tab_funcs);\n  return 1;\n}\n\n"
  },
  {
    "path": "extern/deprecated/redis-2.8.21/deps/lua/src/ltm.c",
    "content": "/*\n** $Id: ltm.c,v 2.8.1.1 2007/12/27 13:02:25 roberto Exp $\n** Tag methods\n** See Copyright Notice in lua.h\n*/\n\n\n#include <string.h>\n\n#define ltm_c\n#define LUA_CORE\n\n#include \"lua.h\"\n\n#include \"lobject.h\"\n#include \"lstate.h\"\n#include \"lstring.h\"\n#include \"ltable.h\"\n#include \"ltm.h\"\n\n\n\nconst char *const luaT_typenames[] = {\n  \"nil\", \"boolean\", \"userdata\", \"number\",\n  \"string\", \"table\", \"function\", \"userdata\", \"thread\",\n  \"proto\", \"upval\"\n};\n\n\nvoid luaT_init (lua_State *L) {\n  static const char *const luaT_eventname[] = {  /* ORDER TM */\n    \"__index\", \"__newindex\",\n    \"__gc\", \"__mode\", \"__eq\",\n    \"__add\", \"__sub\", \"__mul\", \"__div\", \"__mod\",\n    \"__pow\", \"__unm\", \"__len\", \"__lt\", \"__le\",\n    \"__concat\", \"__call\"\n  };\n  int i;\n  for (i=0; i<TM_N; i++) {\n    G(L)->tmname[i] = luaS_new(L, luaT_eventname[i]);\n    luaS_fix(G(L)->tmname[i]);  /* never collect these names */\n  }\n}\n\n\n/*\n** function to be used with macro \"fasttm\": optimized for absence of\n** tag methods\n*/\nconst TValue *luaT_gettm (Table *events, TMS event, TString *ename) {\n  const TValue *tm = luaH_getstr(events, ename);\n  lua_assert(event <= TM_EQ);\n  if (ttisnil(tm)) {  /* no tag method? */\n    events->flags |= cast_byte(1u<<event);  /* cache this fact */\n    return NULL;\n  }\n  else return tm;\n}\n\n\nconst TValue *luaT_gettmbyobj (lua_State *L, const TValue *o, TMS event) {\n  Table *mt;\n  switch (ttype(o)) {\n    case LUA_TTABLE:\n      mt = hvalue(o)->metatable;\n      break;\n    case LUA_TUSERDATA:\n      mt = uvalue(o)->metatable;\n      break;\n    default:\n      mt = G(L)->mt[ttype(o)];\n  }\n  return (mt ? luaH_getstr(mt, G(L)->tmname[event]) : luaO_nilobject);\n}\n\n"
  },
  {
    "path": "extern/deprecated/redis-2.8.21/deps/lua/src/ltm.h",
    "content": "/*\n** $Id: ltm.h,v 2.6.1.1 2007/12/27 13:02:25 roberto Exp $\n** Tag methods\n** See Copyright Notice in lua.h\n*/\n\n#ifndef ltm_h\n#define ltm_h\n\n\n#include \"lobject.h\"\n\n\n/*\n* WARNING: if you change the order of this enumeration,\n* grep \"ORDER TM\"\n*/\ntypedef enum {\n  TM_INDEX,\n  TM_NEWINDEX,\n  TM_GC,\n  TM_MODE,\n  TM_EQ,  /* last tag method with `fast' access */\n  TM_ADD,\n  TM_SUB,\n  TM_MUL,\n  TM_DIV,\n  TM_MOD,\n  TM_POW,\n  TM_UNM,\n  TM_LEN,\n  TM_LT,\n  TM_LE,\n  TM_CONCAT,\n  TM_CALL,\n  TM_N\t\t/* number of elements in the enum */\n} TMS;\n\n\n\n#define gfasttm(g,et,e) ((et) == NULL ? NULL : \\\n  ((et)->flags & (1u<<(e))) ? NULL : luaT_gettm(et, e, (g)->tmname[e]))\n\n#define fasttm(l,et,e)\tgfasttm(G(l), et, e)\n\nLUAI_DATA const char *const luaT_typenames[];\n\n\nLUAI_FUNC const TValue *luaT_gettm (Table *events, TMS event, TString *ename);\nLUAI_FUNC const TValue *luaT_gettmbyobj (lua_State *L, const TValue *o,\n                                                       TMS event);\nLUAI_FUNC void luaT_init (lua_State *L);\n\n#endif\n"
  },
  {
    "path": "extern/deprecated/redis-2.8.21/deps/lua/src/lua.c",
    "content": "/*\n** $Id: lua.c,v 1.160.1.2 2007/12/28 15:32:23 roberto Exp $\n** Lua stand-alone interpreter\n** See Copyright Notice in lua.h\n*/\n\n\n#include <signal.h>\n#include <stdio.h>\n#include <stdlib.h>\n#include <string.h>\n\n#define lua_c\n\n#include \"lua.h\"\n\n#include \"lauxlib.h\"\n#include \"lualib.h\"\n\n\n\nstatic lua_State *globalL = NULL;\n\nstatic const char *progname = LUA_PROGNAME;\n\n\n\nstatic void lstop (lua_State *L, lua_Debug *ar) {\n  (void)ar;  /* unused arg. */\n  lua_sethook(L, NULL, 0, 0);\n  luaL_error(L, \"interrupted!\");\n}\n\n\nstatic void laction (int i) {\n  signal(i, SIG_DFL); /* if another SIGINT happens before lstop,\n                              terminate process (default action) */\n  lua_sethook(globalL, lstop, LUA_MASKCALL | LUA_MASKRET | LUA_MASKCOUNT, 1);\n}\n\n\nstatic void print_usage (void) {\n  fprintf(stderr,\n  \"usage: %s [options] [script [args]].\\n\"\n  \"Available options are:\\n\"\n  \"  -e stat  execute string \" LUA_QL(\"stat\") \"\\n\"\n  \"  -l name  require library \" LUA_QL(\"name\") \"\\n\"\n  \"  -i       enter interactive mode after executing \" LUA_QL(\"script\") \"\\n\"\n  \"  -v       show version information\\n\"\n  \"  --       stop handling options\\n\"\n  \"  -        execute stdin and stop handling options\\n\"\n  ,\n  progname);\n  fflush(stderr);\n}\n\n\nstatic void l_message (const char *pname, const char *msg) {\n  if (pname) fprintf(stderr, \"%s: \", pname);\n  fprintf(stderr, \"%s\\n\", msg);\n  fflush(stderr);\n}\n\n\nstatic int report (lua_State *L, int status) {\n  if (status && !lua_isnil(L, -1)) {\n    const char *msg = lua_tostring(L, -1);\n    if (msg == NULL) msg = \"(error object is not a string)\";\n    l_message(progname, msg);\n    lua_pop(L, 1);\n  }\n  return status;\n}\n\n\nstatic int traceback (lua_State *L) {\n  if (!lua_isstring(L, 1))  /* 'message' not a string? */\n    return 1;  /* keep it intact */\n  lua_getfield(L, LUA_GLOBALSINDEX, \"debug\");\n  if (!lua_istable(L, -1)) {\n    lua_pop(L, 1);\n    return 1;\n  }\n  lua_getfield(L, -1, \"traceback\");\n  if (!lua_isfunction(L, -1)) {\n    lua_pop(L, 2);\n    return 1;\n  }\n  lua_pushvalue(L, 1);  /* pass error message */\n  lua_pushinteger(L, 2);  /* skip this function and traceback */\n  lua_call(L, 2, 1);  /* call debug.traceback */\n  return 1;\n}\n\n\nstatic int docall (lua_State *L, int narg, int clear) {\n  int status;\n  int base = lua_gettop(L) - narg;  /* function index */\n  lua_pushcfunction(L, traceback);  /* push traceback function */\n  lua_insert(L, base);  /* put it under chunk and args */\n  signal(SIGINT, laction);\n  status = lua_pcall(L, narg, (clear ? 0 : LUA_MULTRET), base);\n  signal(SIGINT, SIG_DFL);\n  lua_remove(L, base);  /* remove traceback function */\n  /* force a complete garbage collection in case of errors */\n  if (status != 0) lua_gc(L, LUA_GCCOLLECT, 0);\n  return status;\n}\n\n\nstatic void print_version (void) {\n  l_message(NULL, LUA_RELEASE \"  \" LUA_COPYRIGHT);\n}\n\n\nstatic int getargs (lua_State *L, char **argv, int n) {\n  int narg;\n  int i;\n  int argc = 0;\n  while (argv[argc]) argc++;  /* count total number of arguments */\n  narg = argc - (n + 1);  /* number of arguments to the script */\n  luaL_checkstack(L, narg + 3, \"too many arguments to script\");\n  for (i=n+1; i < argc; i++)\n    lua_pushstring(L, argv[i]);\n  lua_createtable(L, narg, n + 1);\n  for (i=0; i < argc; i++) {\n    lua_pushstring(L, argv[i]);\n    lua_rawseti(L, -2, i - n);\n  }\n  return narg;\n}\n\n\nstatic int dofile (lua_State *L, const char *name) {\n  int status = luaL_loadfile(L, name) || docall(L, 0, 1);\n  return report(L, status);\n}\n\n\nstatic int dostring (lua_State *L, const char *s, const char *name) {\n  int status = luaL_loadbuffer(L, s, strlen(s), name) || docall(L, 0, 1);\n  return report(L, status);\n}\n\n\nstatic int dolibrary (lua_State *L, const char *name) {\n  lua_getglobal(L, \"require\");\n  lua_pushstring(L, name);\n  return report(L, docall(L, 1, 1));\n}\n\n\nstatic const char *get_prompt (lua_State *L, int firstline) {\n  const char *p;\n  lua_getfield(L, LUA_GLOBALSINDEX, firstline ? \"_PROMPT\" : \"_PROMPT2\");\n  p = lua_tostring(L, -1);\n  if (p == NULL) p = (firstline ? LUA_PROMPT : LUA_PROMPT2);\n  lua_pop(L, 1);  /* remove global */\n  return p;\n}\n\n\nstatic int incomplete (lua_State *L, int status) {\n  if (status == LUA_ERRSYNTAX) {\n    size_t lmsg;\n    const char *msg = lua_tolstring(L, -1, &lmsg);\n    const char *tp = msg + lmsg - (sizeof(LUA_QL(\"<eof>\")) - 1);\n    if (strstr(msg, LUA_QL(\"<eof>\")) == tp) {\n      lua_pop(L, 1);\n      return 1;\n    }\n  }\n  return 0;  /* else... */\n}\n\n\nstatic int pushline (lua_State *L, int firstline) {\n  char buffer[LUA_MAXINPUT];\n  char *b = buffer;\n  size_t l;\n  const char *prmt = get_prompt(L, firstline);\n  if (lua_readline(L, b, prmt) == 0)\n    return 0;  /* no input */\n  l = strlen(b);\n  if (l > 0 && b[l-1] == '\\n')  /* line ends with newline? */\n    b[l-1] = '\\0';  /* remove it */\n  if (firstline && b[0] == '=')  /* first line starts with `=' ? */\n    lua_pushfstring(L, \"return %s\", b+1);  /* change it to `return' */\n  else\n    lua_pushstring(L, b);\n  lua_freeline(L, b);\n  return 1;\n}\n\n\nstatic int loadline (lua_State *L) {\n  int status;\n  lua_settop(L, 0);\n  if (!pushline(L, 1))\n    return -1;  /* no input */\n  for (;;) {  /* repeat until gets a complete line */\n    status = luaL_loadbuffer(L, lua_tostring(L, 1), lua_strlen(L, 1), \"=stdin\");\n    if (!incomplete(L, status)) break;  /* cannot try to add lines? */\n    if (!pushline(L, 0))  /* no more input? */\n      return -1;\n    lua_pushliteral(L, \"\\n\");  /* add a new line... */\n    lua_insert(L, -2);  /* ...between the two lines */\n    lua_concat(L, 3);  /* join them */\n  }\n  lua_saveline(L, 1);\n  lua_remove(L, 1);  /* remove line */\n  return status;\n}\n\n\nstatic void dotty (lua_State *L) {\n  int status;\n  const char *oldprogname = progname;\n  progname = NULL;\n  while ((status = loadline(L)) != -1) {\n    if (status == 0) status = docall(L, 0, 0);\n    report(L, status);\n    if (status == 0 && lua_gettop(L) > 0) {  /* any result to print? */\n      lua_getglobal(L, \"print\");\n      lua_insert(L, 1);\n      if (lua_pcall(L, lua_gettop(L)-1, 0, 0) != 0)\n        l_message(progname, lua_pushfstring(L,\n                               \"error calling \" LUA_QL(\"print\") \" (%s)\",\n                               lua_tostring(L, -1)));\n    }\n  }\n  lua_settop(L, 0);  /* clear stack */\n  fputs(\"\\n\", stdout);\n  fflush(stdout);\n  progname = oldprogname;\n}\n\n\nstatic int handle_script (lua_State *L, char **argv, int n) {\n  int status;\n  const char *fname;\n  int narg = getargs(L, argv, n);  /* collect arguments */\n  lua_setglobal(L, \"arg\");\n  fname = argv[n];\n  if (strcmp(fname, \"-\") == 0 && strcmp(argv[n-1], \"--\") != 0) \n    fname = NULL;  /* stdin */\n  status = luaL_loadfile(L, fname);\n  lua_insert(L, -(narg+1));\n  if (status == 0)\n    status = docall(L, narg, 0);\n  else\n    lua_pop(L, narg);      \n  return report(L, status);\n}\n\n\n/* check that argument has no extra characters at the end */\n#define notail(x)\t{if ((x)[2] != '\\0') return -1;}\n\n\nstatic int collectargs (char **argv, int *pi, int *pv, int *pe) {\n  int i;\n  for (i = 1; argv[i] != NULL; i++) {\n    if (argv[i][0] != '-')  /* not an option? */\n        return i;\n    switch (argv[i][1]) {  /* option */\n      case '-':\n        notail(argv[i]);\n        return (argv[i+1] != NULL ? i+1 : 0);\n      case '\\0':\n        return i;\n      case 'i':\n        notail(argv[i]);\n        *pi = 1;  /* go through */\n      case 'v':\n        notail(argv[i]);\n        *pv = 1;\n        break;\n      case 'e':\n        *pe = 1;  /* go through */\n      case 'l':\n        if (argv[i][2] == '\\0') {\n          i++;\n          if (argv[i] == NULL) return -1;\n        }\n        break;\n      default: return -1;  /* invalid option */\n    }\n  }\n  return 0;\n}\n\n\nstatic int runargs (lua_State *L, char **argv, int n) {\n  int i;\n  for (i = 1; i < n; i++) {\n    if (argv[i] == NULL) continue;\n    lua_assert(argv[i][0] == '-');\n    switch (argv[i][1]) {  /* option */\n      case 'e': {\n        const char *chunk = argv[i] + 2;\n        if (*chunk == '\\0') chunk = argv[++i];\n        lua_assert(chunk != NULL);\n        if (dostring(L, chunk, \"=(command line)\") != 0)\n          return 1;\n        break;\n      }\n      case 'l': {\n        const char *filename = argv[i] + 2;\n        if (*filename == '\\0') filename = argv[++i];\n        lua_assert(filename != NULL);\n        if (dolibrary(L, filename))\n          return 1;  /* stop if file fails */\n        break;\n      }\n      default: break;\n    }\n  }\n  return 0;\n}\n\n\nstatic int handle_luainit (lua_State *L) {\n  const char *init = getenv(LUA_INIT);\n  if (init == NULL) return 0;  /* status OK */\n  else if (init[0] == '@')\n    return dofile(L, init+1);\n  else\n    return dostring(L, init, \"=\" LUA_INIT);\n}\n\n\nstruct Smain {\n  int argc;\n  char **argv;\n  int status;\n};\n\n\nstatic int pmain (lua_State *L) {\n  struct Smain *s = (struct Smain *)lua_touserdata(L, 1);\n  char **argv = s->argv;\n  int script;\n  int has_i = 0, has_v = 0, has_e = 0;\n  globalL = L;\n  if (argv[0] && argv[0][0]) progname = argv[0];\n  lua_gc(L, LUA_GCSTOP, 0);  /* stop collector during initialization */\n  luaL_openlibs(L);  /* open libraries */\n  lua_gc(L, LUA_GCRESTART, 0);\n  s->status = handle_luainit(L);\n  if (s->status != 0) return 0;\n  script = collectargs(argv, &has_i, &has_v, &has_e);\n  if (script < 0) {  /* invalid args? */\n    print_usage();\n    s->status = 1;\n    return 0;\n  }\n  if (has_v) print_version();\n  s->status = runargs(L, argv, (script > 0) ? script : s->argc);\n  if (s->status != 0) return 0;\n  if (script)\n    s->status = handle_script(L, argv, script);\n  if (s->status != 0) return 0;\n  if (has_i)\n    dotty(L);\n  else if (script == 0 && !has_e && !has_v) {\n    if (lua_stdin_is_tty()) {\n      print_version();\n      dotty(L);\n    }\n    else dofile(L, NULL);  /* executes stdin as a file */\n  }\n  return 0;\n}\n\n\nint main (int argc, char **argv) {\n  int status;\n  struct Smain s;\n  lua_State *L = lua_open();  /* create state */\n  if (L == NULL) {\n    l_message(argv[0], \"cannot create state: not enough memory\");\n    return EXIT_FAILURE;\n  }\n  s.argc = argc;\n  s.argv = argv;\n  status = lua_cpcall(L, &pmain, &s);\n  report(L, status);\n  lua_close(L);\n  return (status || s.status) ? EXIT_FAILURE : EXIT_SUCCESS;\n}\n\n"
  },
  {
    "path": "extern/deprecated/redis-2.8.21/deps/lua/src/lua.h",
    "content": "/*\n** $Id: lua.h,v 1.218.1.7 2012/01/13 20:36:20 roberto Exp $\n** Lua - An Extensible Extension Language\n** Lua.org, PUC-Rio, Brazil (http://www.lua.org)\n** See Copyright Notice at the end of this file\n*/\n\n\n#ifndef lua_h\n#define lua_h\n\n#include <stdarg.h>\n#include <stddef.h>\n\n\n#include \"luaconf.h\"\n\n\n#define LUA_VERSION\t\"Lua 5.1\"\n#define LUA_RELEASE\t\"Lua 5.1.5\"\n#define LUA_VERSION_NUM\t501\n#define LUA_COPYRIGHT\t\"Copyright (C) 1994-2012 Lua.org, PUC-Rio\"\n#define LUA_AUTHORS \t\"R. Ierusalimschy, L. H. de Figueiredo & W. Celes\"\n\n\n/* mark for precompiled code (`<esc>Lua') */\n#define\tLUA_SIGNATURE\t\"\\033Lua\"\n\n/* option for multiple returns in `lua_pcall' and `lua_call' */\n#define LUA_MULTRET\t(-1)\n\n\n/*\n** pseudo-indices\n*/\n#define LUA_REGISTRYINDEX\t(-10000)\n#define LUA_ENVIRONINDEX\t(-10001)\n#define LUA_GLOBALSINDEX\t(-10002)\n#define lua_upvalueindex(i)\t(LUA_GLOBALSINDEX-(i))\n\n\n/* thread status; 0 is OK */\n#define LUA_YIELD\t1\n#define LUA_ERRRUN\t2\n#define LUA_ERRSYNTAX\t3\n#define LUA_ERRMEM\t4\n#define LUA_ERRERR\t5\n\n\ntypedef struct lua_State lua_State;\n\ntypedef int (*lua_CFunction) (lua_State *L);\n\n\n/*\n** functions that read/write blocks when loading/dumping Lua chunks\n*/\ntypedef const char * (*lua_Reader) (lua_State *L, void *ud, size_t *sz);\n\ntypedef int (*lua_Writer) (lua_State *L, const void* p, size_t sz, void* ud);\n\n\n/*\n** prototype for memory-allocation functions\n*/\ntypedef void * (*lua_Alloc) (void *ud, void *ptr, size_t osize, size_t nsize);\n\n\n/*\n** basic types\n*/\n#define LUA_TNONE\t\t(-1)\n\n#define LUA_TNIL\t\t0\n#define LUA_TBOOLEAN\t\t1\n#define LUA_TLIGHTUSERDATA\t2\n#define LUA_TNUMBER\t\t3\n#define LUA_TSTRING\t\t4\n#define LUA_TTABLE\t\t5\n#define LUA_TFUNCTION\t\t6\n#define LUA_TUSERDATA\t\t7\n#define LUA_TTHREAD\t\t8\n\n\n\n/* minimum Lua stack available to a C function */\n#define LUA_MINSTACK\t20\n\n\n/*\n** generic extra include file\n*/\n#if defined(LUA_USER_H)\n#include LUA_USER_H\n#endif\n\n\n/* type of numbers in Lua */\ntypedef LUA_NUMBER lua_Number;\n\n\n/* type for integer functions */\ntypedef LUA_INTEGER lua_Integer;\n\n\n\n/*\n** state manipulation\n*/\nLUA_API lua_State *(lua_newstate) (lua_Alloc f, void *ud);\nLUA_API void       (lua_close) (lua_State *L);\nLUA_API lua_State *(lua_newthread) (lua_State *L);\n\nLUA_API lua_CFunction (lua_atpanic) (lua_State *L, lua_CFunction panicf);\n\n\n/*\n** basic stack manipulation\n*/\nLUA_API int   (lua_gettop) (lua_State *L);\nLUA_API void  (lua_settop) (lua_State *L, int idx);\nLUA_API void  (lua_pushvalue) (lua_State *L, int idx);\nLUA_API void  (lua_remove) (lua_State *L, int idx);\nLUA_API void  (lua_insert) (lua_State *L, int idx);\nLUA_API void  (lua_replace) (lua_State *L, int idx);\nLUA_API int   (lua_checkstack) (lua_State *L, int sz);\n\nLUA_API void  (lua_xmove) (lua_State *from, lua_State *to, int n);\n\n\n/*\n** access functions (stack -> C)\n*/\n\nLUA_API int             (lua_isnumber) (lua_State *L, int idx);\nLUA_API int             (lua_isstring) (lua_State *L, int idx);\nLUA_API int             (lua_iscfunction) (lua_State *L, int idx);\nLUA_API int             (lua_isuserdata) (lua_State *L, int idx);\nLUA_API int             (lua_type) (lua_State *L, int idx);\nLUA_API const char     *(lua_typename) (lua_State *L, int tp);\n\nLUA_API int            (lua_equal) (lua_State *L, int idx1, int idx2);\nLUA_API int            (lua_rawequal) (lua_State *L, int idx1, int idx2);\nLUA_API int            (lua_lessthan) (lua_State *L, int idx1, int idx2);\n\nLUA_API lua_Number      (lua_tonumber) (lua_State *L, int idx);\nLUA_API lua_Integer     (lua_tointeger) (lua_State *L, int idx);\nLUA_API int             (lua_toboolean) (lua_State *L, int idx);\nLUA_API const char     *(lua_tolstring) (lua_State *L, int idx, size_t *len);\nLUA_API size_t          (lua_objlen) (lua_State *L, int idx);\nLUA_API lua_CFunction   (lua_tocfunction) (lua_State *L, int idx);\nLUA_API void\t       *(lua_touserdata) (lua_State *L, int idx);\nLUA_API lua_State      *(lua_tothread) (lua_State *L, int idx);\nLUA_API const void     *(lua_topointer) (lua_State *L, int idx);\n\n\n/*\n** push functions (C -> stack)\n*/\nLUA_API void  (lua_pushnil) (lua_State *L);\nLUA_API void  (lua_pushnumber) (lua_State *L, lua_Number n);\nLUA_API void  (lua_pushinteger) (lua_State *L, lua_Integer n);\nLUA_API void  (lua_pushlstring) (lua_State *L, const char *s, size_t l);\nLUA_API void  (lua_pushstring) (lua_State *L, const char *s);\nLUA_API const char *(lua_pushvfstring) (lua_State *L, const char *fmt,\n                                                      va_list argp);\nLUA_API const char *(lua_pushfstring) (lua_State *L, const char *fmt, ...);\nLUA_API void  (lua_pushcclosure) (lua_State *L, lua_CFunction fn, int n);\nLUA_API void  (lua_pushboolean) (lua_State *L, int b);\nLUA_API void  (lua_pushlightuserdata) (lua_State *L, void *p);\nLUA_API int   (lua_pushthread) (lua_State *L);\n\n\n/*\n** get functions (Lua -> stack)\n*/\nLUA_API void  (lua_gettable) (lua_State *L, int idx);\nLUA_API void  (lua_getfield) (lua_State *L, int idx, const char *k);\nLUA_API void  (lua_rawget) (lua_State *L, int idx);\nLUA_API void  (lua_rawgeti) (lua_State *L, int idx, int n);\nLUA_API void  (lua_createtable) (lua_State *L, int narr, int nrec);\nLUA_API void *(lua_newuserdata) (lua_State *L, size_t sz);\nLUA_API int   (lua_getmetatable) (lua_State *L, int objindex);\nLUA_API void  (lua_getfenv) (lua_State *L, int idx);\n\n\n/*\n** set functions (stack -> Lua)\n*/\nLUA_API void  (lua_settable) (lua_State *L, int idx);\nLUA_API void  (lua_setfield) (lua_State *L, int idx, const char *k);\nLUA_API void  (lua_rawset) (lua_State *L, int idx);\nLUA_API void  (lua_rawseti) (lua_State *L, int idx, int n);\nLUA_API int   (lua_setmetatable) (lua_State *L, int objindex);\nLUA_API int   (lua_setfenv) (lua_State *L, int idx);\n\n\n/*\n** `load' and `call' functions (load and run Lua code)\n*/\nLUA_API void  (lua_call) (lua_State *L, int nargs, int nresults);\nLUA_API int   (lua_pcall) (lua_State *L, int nargs, int nresults, int errfunc);\nLUA_API int   (lua_cpcall) (lua_State *L, lua_CFunction func, void *ud);\nLUA_API int   (lua_load) (lua_State *L, lua_Reader reader, void *dt,\n                                        const char *chunkname);\n\nLUA_API int (lua_dump) (lua_State *L, lua_Writer writer, void *data);\n\n\n/*\n** coroutine functions\n*/\nLUA_API int  (lua_yield) (lua_State *L, int nresults);\nLUA_API int  (lua_resume) (lua_State *L, int narg);\nLUA_API int  (lua_status) (lua_State *L);\n\n/*\n** garbage-collection function and options\n*/\n\n#define LUA_GCSTOP\t\t0\n#define LUA_GCRESTART\t\t1\n#define LUA_GCCOLLECT\t\t2\n#define LUA_GCCOUNT\t\t3\n#define LUA_GCCOUNTB\t\t4\n#define LUA_GCSTEP\t\t5\n#define LUA_GCSETPAUSE\t\t6\n#define LUA_GCSETSTEPMUL\t7\n\nLUA_API int (lua_gc) (lua_State *L, int what, int data);\n\n\n/*\n** miscellaneous functions\n*/\n\nLUA_API int   (lua_error) (lua_State *L);\n\nLUA_API int   (lua_next) (lua_State *L, int idx);\n\nLUA_API void  (lua_concat) (lua_State *L, int n);\n\nLUA_API lua_Alloc (lua_getallocf) (lua_State *L, void **ud);\nLUA_API void lua_setallocf (lua_State *L, lua_Alloc f, void *ud);\n\n\n\n/* \n** ===============================================================\n** some useful macros\n** ===============================================================\n*/\n\n#define lua_pop(L,n)\t\tlua_settop(L, -(n)-1)\n\n#define lua_newtable(L)\t\tlua_createtable(L, 0, 0)\n\n#define lua_register(L,n,f) (lua_pushcfunction(L, (f)), lua_setglobal(L, (n)))\n\n#define lua_pushcfunction(L,f)\tlua_pushcclosure(L, (f), 0)\n\n#define lua_strlen(L,i)\t\tlua_objlen(L, (i))\n\n#define lua_isfunction(L,n)\t(lua_type(L, (n)) == LUA_TFUNCTION)\n#define lua_istable(L,n)\t(lua_type(L, (n)) == LUA_TTABLE)\n#define lua_islightuserdata(L,n)\t(lua_type(L, (n)) == LUA_TLIGHTUSERDATA)\n#define lua_isnil(L,n)\t\t(lua_type(L, (n)) == LUA_TNIL)\n#define lua_isboolean(L,n)\t(lua_type(L, (n)) == LUA_TBOOLEAN)\n#define lua_isthread(L,n)\t(lua_type(L, (n)) == LUA_TTHREAD)\n#define lua_isnone(L,n)\t\t(lua_type(L, (n)) == LUA_TNONE)\n#define lua_isnoneornil(L, n)\t(lua_type(L, (n)) <= 0)\n\n#define lua_pushliteral(L, s)\t\\\n\tlua_pushlstring(L, \"\" s, (sizeof(s)/sizeof(char))-1)\n\n#define lua_setglobal(L,s)\tlua_setfield(L, LUA_GLOBALSINDEX, (s))\n#define lua_getglobal(L,s)\tlua_getfield(L, LUA_GLOBALSINDEX, (s))\n\n#define lua_tostring(L,i)\tlua_tolstring(L, (i), NULL)\n\n\n\n/*\n** compatibility macros and functions\n*/\n\n#define lua_open()\tluaL_newstate()\n\n#define lua_getregistry(L)\tlua_pushvalue(L, LUA_REGISTRYINDEX)\n\n#define lua_getgccount(L)\tlua_gc(L, LUA_GCCOUNT, 0)\n\n#define lua_Chunkreader\t\tlua_Reader\n#define lua_Chunkwriter\t\tlua_Writer\n\n\n/* hack */\nLUA_API void lua_setlevel\t(lua_State *from, lua_State *to);\n\n\n/*\n** {======================================================================\n** Debug API\n** =======================================================================\n*/\n\n\n/*\n** Event codes\n*/\n#define LUA_HOOKCALL\t0\n#define LUA_HOOKRET\t1\n#define LUA_HOOKLINE\t2\n#define LUA_HOOKCOUNT\t3\n#define LUA_HOOKTAILRET 4\n\n\n/*\n** Event masks\n*/\n#define LUA_MASKCALL\t(1 << LUA_HOOKCALL)\n#define LUA_MASKRET\t(1 << LUA_HOOKRET)\n#define LUA_MASKLINE\t(1 << LUA_HOOKLINE)\n#define LUA_MASKCOUNT\t(1 << LUA_HOOKCOUNT)\n\ntypedef struct lua_Debug lua_Debug;  /* activation record */\n\n\n/* Functions to be called by the debuger in specific events */\ntypedef void (*lua_Hook) (lua_State *L, lua_Debug *ar);\n\n\nLUA_API int lua_getstack (lua_State *L, int level, lua_Debug *ar);\nLUA_API int lua_getinfo (lua_State *L, const char *what, lua_Debug *ar);\nLUA_API const char *lua_getlocal (lua_State *L, const lua_Debug *ar, int n);\nLUA_API const char *lua_setlocal (lua_State *L, const lua_Debug *ar, int n);\nLUA_API const char *lua_getupvalue (lua_State *L, int funcindex, int n);\nLUA_API const char *lua_setupvalue (lua_State *L, int funcindex, int n);\n\nLUA_API int lua_sethook (lua_State *L, lua_Hook func, int mask, int count);\nLUA_API lua_Hook lua_gethook (lua_State *L);\nLUA_API int lua_gethookmask (lua_State *L);\nLUA_API int lua_gethookcount (lua_State *L);\n\n\nstruct lua_Debug {\n  int event;\n  const char *name;\t/* (n) */\n  const char *namewhat;\t/* (n) `global', `local', `field', `method' */\n  const char *what;\t/* (S) `Lua', `C', `main', `tail' */\n  const char *source;\t/* (S) */\n  int currentline;\t/* (l) */\n  int nups;\t\t/* (u) number of upvalues */\n  int linedefined;\t/* (S) */\n  int lastlinedefined;\t/* (S) */\n  char short_src[LUA_IDSIZE]; /* (S) */\n  /* private part */\n  int i_ci;  /* active function */\n};\n\n/* }====================================================================== */\n\n\n/******************************************************************************\n* Copyright (C) 1994-2012 Lua.org, PUC-Rio.  All rights reserved.\n*\n* Permission is hereby granted, free of charge, to any person obtaining\n* a copy of this software and associated documentation files (the\n* \"Software\"), to deal in the Software without restriction, including\n* without limitation the rights to use, copy, modify, merge, publish,\n* distribute, sublicense, and/or sell copies of the Software, and to\n* permit persons to whom the Software is furnished to do so, subject to\n* the following conditions:\n*\n* The above copyright notice and this permission notice shall be\n* included in all copies or substantial portions of the Software.\n*\n* THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND,\n* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\n* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.\n* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY\n* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,\n* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE\n* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n******************************************************************************/\n\n\n#endif\n"
  },
  {
    "path": "extern/deprecated/redis-2.8.21/deps/lua/src/lua_bit.c",
    "content": "/*\n** Lua BitOp -- a bit operations library for Lua 5.1/5.2.\n** http://bitop.luajit.org/\n**\n** Copyright (C) 2008-2012 Mike Pall. All rights reserved.\n**\n** Permission is hereby granted, free of charge, to any person obtaining\n** a copy of this software and associated documentation files (the\n** \"Software\"), to deal in the Software without restriction, including\n** without limitation the rights to use, copy, modify, merge, publish,\n** distribute, sublicense, and/or sell copies of the Software, and to\n** permit persons to whom the Software is furnished to do so, subject to\n** the following conditions:\n**\n** The above copyright notice and this permission notice shall be\n** included in all copies or substantial portions of the Software.\n**\n** THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND,\n** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\n** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.\n** IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY\n** CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,\n** TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE\n** SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n**\n** [ MIT license: http://www.opensource.org/licenses/mit-license.php ]\n*/\n\n#define LUA_BITOP_VERSION\t\"1.0.2\"\n\n#define LUA_LIB\n#include \"lua.h\"\n#include \"lauxlib.h\"\n\n#ifdef _MSC_VER\n/* MSVC is stuck in the last century and doesn't have C99's stdint.h. */\ntypedef __int32 int32_t;\ntypedef unsigned __int32 uint32_t;\ntypedef unsigned __int64 uint64_t;\n#else\n#include <stdint.h>\n#endif\n\ntypedef int32_t SBits;\ntypedef uint32_t UBits;\n\ntypedef union {\n  lua_Number n;\n#ifdef LUA_NUMBER_DOUBLE\n  uint64_t b;\n#else\n  UBits b;\n#endif\n} BitNum;\n\n/* Convert argument to bit type. */\nstatic UBits barg(lua_State *L, int idx)\n{\n  BitNum bn;\n  UBits b;\n#if LUA_VERSION_NUM < 502\n  bn.n = lua_tonumber(L, idx);\n#else\n  bn.n = luaL_checknumber(L, idx);\n#endif\n#if defined(LUA_NUMBER_DOUBLE)\n  bn.n += 6755399441055744.0;  /* 2^52+2^51 */\n#ifdef SWAPPED_DOUBLE\n  b = (UBits)(bn.b >> 32);\n#else\n  b = (UBits)bn.b;\n#endif\n#elif defined(LUA_NUMBER_INT) || defined(LUA_NUMBER_LONG) || \\\n      defined(LUA_NUMBER_LONGLONG) || defined(LUA_NUMBER_LONG_LONG) || \\\n      defined(LUA_NUMBER_LLONG)\n  if (sizeof(UBits) == sizeof(lua_Number))\n    b = bn.b;\n  else\n    b = (UBits)(SBits)bn.n;\n#elif defined(LUA_NUMBER_FLOAT)\n#error \"A 'float' lua_Number type is incompatible with this library\"\n#else\n#error \"Unknown number type, check LUA_NUMBER_* in luaconf.h\"\n#endif\n#if LUA_VERSION_NUM < 502\n  if (b == 0 && !lua_isnumber(L, idx)) {\n    luaL_typerror(L, idx, \"number\");\n  }\n#endif\n  return b;\n}\n\n/* Return bit type. */\n#define BRET(b)  lua_pushnumber(L, (lua_Number)(SBits)(b)); return 1;\n\nstatic int bit_tobit(lua_State *L) { BRET(barg(L, 1)) }\nstatic int bit_bnot(lua_State *L) { BRET(~barg(L, 1)) }\n\n#define BIT_OP(func, opr) \\\n  static int func(lua_State *L) { int i; UBits b = barg(L, 1); \\\n    for (i = lua_gettop(L); i > 1; i--) b opr barg(L, i); BRET(b) }\nBIT_OP(bit_band, &=)\nBIT_OP(bit_bor, |=)\nBIT_OP(bit_bxor, ^=)\n\n#define bshl(b, n)  (b << n)\n#define bshr(b, n)  (b >> n)\n#define bsar(b, n)  ((SBits)b >> n)\n#define brol(b, n)  ((b << n) | (b >> (32-n)))\n#define bror(b, n)  ((b << (32-n)) | (b >> n))\n#define BIT_SH(func, fn) \\\n  static int func(lua_State *L) { \\\n    UBits b = barg(L, 1); UBits n = barg(L, 2) & 31; BRET(fn(b, n)) }\nBIT_SH(bit_lshift, bshl)\nBIT_SH(bit_rshift, bshr)\nBIT_SH(bit_arshift, bsar)\nBIT_SH(bit_rol, brol)\nBIT_SH(bit_ror, bror)\n\nstatic int bit_bswap(lua_State *L)\n{\n  UBits b = barg(L, 1);\n  b = (b >> 24) | ((b >> 8) & 0xff00) | ((b & 0xff00) << 8) | (b << 24);\n  BRET(b)\n}\n\nstatic int bit_tohex(lua_State *L)\n{\n  UBits b = barg(L, 1);\n  SBits n = lua_isnone(L, 2) ? 8 : (SBits)barg(L, 2);\n  const char *hexdigits = \"0123456789abcdef\";\n  char buf[8];\n  int i;\n  if (n < 0) { n = -n; hexdigits = \"0123456789ABCDEF\"; }\n  if (n > 8) n = 8;\n  for (i = (int)n; --i >= 0; ) { buf[i] = hexdigits[b & 15]; b >>= 4; }\n  lua_pushlstring(L, buf, (size_t)n);\n  return 1;\n}\n\nstatic const struct luaL_Reg bit_funcs[] = {\n  { \"tobit\",\tbit_tobit },\n  { \"bnot\",\tbit_bnot },\n  { \"band\",\tbit_band },\n  { \"bor\",\tbit_bor },\n  { \"bxor\",\tbit_bxor },\n  { \"lshift\",\tbit_lshift },\n  { \"rshift\",\tbit_rshift },\n  { \"arshift\",\tbit_arshift },\n  { \"rol\",\tbit_rol },\n  { \"ror\",\tbit_ror },\n  { \"bswap\",\tbit_bswap },\n  { \"tohex\",\tbit_tohex },\n  { NULL, NULL }\n};\n\n/* Signed right-shifts are implementation-defined per C89/C99.\n** But the de facto standard are arithmetic right-shifts on two's\n** complement CPUs. This behaviour is required here, so test for it.\n*/\n#define BAD_SAR\t\t(bsar(-8, 2) != (SBits)-2)\n\nLUALIB_API int luaopen_bit(lua_State *L)\n{\n  UBits b;\n  lua_pushnumber(L, (lua_Number)1437217655L);\n  b = barg(L, -1);\n  if (b != (UBits)1437217655L || BAD_SAR) {  /* Perform a simple self-test. */\n    const char *msg = \"compiled with incompatible luaconf.h\";\n#ifdef LUA_NUMBER_DOUBLE\n#ifdef _WIN32\n    if (b == (UBits)1610612736L)\n      msg = \"use D3DCREATE_FPU_PRESERVE with DirectX\";\n#endif\n    if (b == (UBits)1127743488L)\n      msg = \"not compiled with SWAPPED_DOUBLE\";\n#endif\n    if (BAD_SAR)\n      msg = \"arithmetic right-shift broken\";\n    luaL_error(L, \"bit library self-test failed (%s)\", msg);\n  }\n#if LUA_VERSION_NUM < 502\n  luaL_register(L, \"bit\", bit_funcs);\n#else\n  luaL_newlib(L, bit_funcs);\n#endif\n  return 1;\n}\n\n"
  },
  {
    "path": "extern/deprecated/redis-2.8.21/deps/lua/src/lua_cjson.c",
    "content": "/* Lua CJSON - JSON support for Lua\n *\n * Copyright (c) 2010-2012  Mark Pulford <mark@kyne.com.au>\n *\n * Permission is hereby granted, free of charge, to any person obtaining\n * a copy of this software and associated documentation files (the\n * \"Software\"), to deal in the Software without restriction, including\n * without limitation the rights to use, copy, modify, merge, publish,\n * distribute, sublicense, and/or sell copies of the Software, and to\n * permit persons to whom the Software is furnished to do so, subject to\n * the following conditions:\n *\n * The above copyright notice and this permission notice shall be\n * included in all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND,\n * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\n * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.\n * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY\n * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,\n * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE\n * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n */\n\n/* Caveats:\n * - JSON \"null\" values are represented as lightuserdata since Lua\n *   tables cannot contain \"nil\". Compare with cjson.null.\n * - Invalid UTF-8 characters are not detected and will be passed\n *   untouched. If required, UTF-8 error checking should be done\n *   outside this library.\n * - Javascript comments are not part of the JSON spec, and are not\n *   currently supported.\n *\n * Note: Decoding is slower than encoding. Lua spends significant\n *       time (30%) managing tables when parsing JSON since it is\n *       difficult to know object/array sizes ahead of time.\n */\n\n#include <assert.h>\n#include <string.h>\n#include <math.h>\n#include <limits.h>\n#include \"lua.h\"\n#include \"lauxlib.h\"\n\n#include \"strbuf.h\"\n#include \"fpconv.h\"\n\n#include \"../../../src/solarisfixes.h\"\n\n#ifndef CJSON_MODNAME\n#define CJSON_MODNAME   \"cjson\"\n#endif\n\n#ifndef CJSON_VERSION\n#define CJSON_VERSION   \"2.1.0\"\n#endif\n\n/* Workaround for Solaris platforms missing isinf() */\n#if !defined(isinf) && (defined(USE_INTERNAL_ISINF) || defined(MISSING_ISINF))\n#define isinf(x) (!isnan(x) && isnan((x) - (x)))\n#endif\n\n#define DEFAULT_SPARSE_CONVERT 0\n#define DEFAULT_SPARSE_RATIO 2\n#define DEFAULT_SPARSE_SAFE 10\n#define DEFAULT_ENCODE_MAX_DEPTH 1000\n#define DEFAULT_DECODE_MAX_DEPTH 1000\n#define DEFAULT_ENCODE_INVALID_NUMBERS 0\n#define DEFAULT_DECODE_INVALID_NUMBERS 1\n#define DEFAULT_ENCODE_KEEP_BUFFER 1\n#define DEFAULT_ENCODE_NUMBER_PRECISION 14\n\n#ifdef DISABLE_INVALID_NUMBERS\n#undef DEFAULT_DECODE_INVALID_NUMBERS\n#define DEFAULT_DECODE_INVALID_NUMBERS 0\n#endif\n\ntypedef enum {\n    T_OBJ_BEGIN,\n    T_OBJ_END,\n    T_ARR_BEGIN,\n    T_ARR_END,\n    T_STRING,\n    T_NUMBER,\n    T_BOOLEAN,\n    T_NULL,\n    T_COLON,\n    T_COMMA,\n    T_END,\n    T_WHITESPACE,\n    T_ERROR,\n    T_UNKNOWN\n} json_token_type_t;\n\nstatic const char *json_token_type_name[] = {\n    \"T_OBJ_BEGIN\",\n    \"T_OBJ_END\",\n    \"T_ARR_BEGIN\",\n    \"T_ARR_END\",\n    \"T_STRING\",\n    \"T_NUMBER\",\n    \"T_BOOLEAN\",\n    \"T_NULL\",\n    \"T_COLON\",\n    \"T_COMMA\",\n    \"T_END\",\n    \"T_WHITESPACE\",\n    \"T_ERROR\",\n    \"T_UNKNOWN\",\n    NULL\n};\n\ntypedef struct {\n    json_token_type_t ch2token[256];\n    char escape2char[256];  /* Decoding */\n\n    /* encode_buf is only allocated and used when\n     * encode_keep_buffer is set */\n    strbuf_t encode_buf;\n\n    int encode_sparse_convert;\n    int encode_sparse_ratio;\n    int encode_sparse_safe;\n    int encode_max_depth;\n    int encode_invalid_numbers;     /* 2 => Encode as \"null\" */\n    int encode_number_precision;\n    int encode_keep_buffer;\n\n    int decode_invalid_numbers;\n    int decode_max_depth;\n} json_config_t;\n\ntypedef struct {\n    const char *data;\n    const char *ptr;\n    strbuf_t *tmp;    /* Temporary storage for strings */\n    json_config_t *cfg;\n    int current_depth;\n} json_parse_t;\n\ntypedef struct {\n    json_token_type_t type;\n    int index;\n    union {\n        const char *string;\n        double number;\n        int boolean;\n    } value;\n    int string_len;\n} json_token_t;\n\nstatic const char *char2escape[256] = {\n    \"\\\\u0000\", \"\\\\u0001\", \"\\\\u0002\", \"\\\\u0003\",\n    \"\\\\u0004\", \"\\\\u0005\", \"\\\\u0006\", \"\\\\u0007\",\n    \"\\\\b\", \"\\\\t\", \"\\\\n\", \"\\\\u000b\",\n    \"\\\\f\", \"\\\\r\", \"\\\\u000e\", \"\\\\u000f\",\n    \"\\\\u0010\", \"\\\\u0011\", \"\\\\u0012\", \"\\\\u0013\",\n    \"\\\\u0014\", \"\\\\u0015\", \"\\\\u0016\", \"\\\\u0017\",\n    \"\\\\u0018\", \"\\\\u0019\", \"\\\\u001a\", \"\\\\u001b\",\n    \"\\\\u001c\", \"\\\\u001d\", \"\\\\u001e\", \"\\\\u001f\",\n    NULL, NULL, \"\\\\\\\"\", NULL, NULL, NULL, NULL, NULL,\n    NULL, NULL, NULL, NULL, NULL, NULL, NULL, \"\\\\/\",\n    NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,\n    NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,\n    NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,\n    NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,\n    NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,\n    NULL, NULL, NULL, NULL, \"\\\\\\\\\", NULL, NULL, NULL,\n    NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,\n    NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,\n    NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,\n    NULL, NULL, NULL, NULL, NULL, NULL, NULL, \"\\\\u007f\",\n    NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,\n    NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,\n    NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,\n    NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,\n    NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,\n    NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,\n    NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,\n    NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,\n    NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,\n    NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,\n    NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,\n    NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,\n    NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,\n    NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,\n    NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,\n    NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,\n};\n\n/* ===== CONFIGURATION ===== */\n\nstatic json_config_t *json_fetch_config(lua_State *l)\n{\n    json_config_t *cfg;\n\n    cfg = lua_touserdata(l, lua_upvalueindex(1));\n    if (!cfg)\n        luaL_error(l, \"BUG: Unable to fetch CJSON configuration\");\n\n    return cfg;\n}\n\n/* Ensure the correct number of arguments have been provided.\n * Pad with nil to allow other functions to simply check arg[i]\n * to find whether an argument was provided */\nstatic json_config_t *json_arg_init(lua_State *l, int args)\n{\n    luaL_argcheck(l, lua_gettop(l) <= args, args + 1,\n                  \"found too many arguments\");\n\n    while (lua_gettop(l) < args)\n        lua_pushnil(l);\n\n    return json_fetch_config(l);\n}\n\n/* Process integer options for configuration functions */\nstatic int json_integer_option(lua_State *l, int optindex, int *setting,\n                               int min, int max)\n{\n    char errmsg[64];\n    int value;\n\n    if (!lua_isnil(l, optindex)) {\n        value = luaL_checkinteger(l, optindex);\n        snprintf(errmsg, sizeof(errmsg), \"expected integer between %d and %d\", min, max);\n        luaL_argcheck(l, min <= value && value <= max, 1, errmsg);\n        *setting = value;\n    }\n\n    lua_pushinteger(l, *setting);\n\n    return 1;\n}\n\n/* Process enumerated arguments for a configuration function */\nstatic int json_enum_option(lua_State *l, int optindex, int *setting,\n                            const char **options, int bool_true)\n{\n    static const char *bool_options[] = { \"off\", \"on\", NULL };\n\n    if (!options) {\n        options = bool_options;\n        bool_true = 1;\n    }\n\n    if (!lua_isnil(l, optindex)) {\n        if (bool_true && lua_isboolean(l, optindex))\n            *setting = lua_toboolean(l, optindex) * bool_true;\n        else\n            *setting = luaL_checkoption(l, optindex, NULL, options);\n    }\n\n    if (bool_true && (*setting == 0 || *setting == bool_true))\n        lua_pushboolean(l, *setting);\n    else\n        lua_pushstring(l, options[*setting]);\n\n    return 1;\n}\n\n/* Configures handling of extremely sparse arrays:\n * convert: Convert extremely sparse arrays into objects? Otherwise error.\n * ratio: 0: always allow sparse; 1: never allow sparse; >1: use ratio\n * safe: Always use an array when the max index <= safe */\nstatic int json_cfg_encode_sparse_array(lua_State *l)\n{\n    json_config_t *cfg = json_arg_init(l, 3);\n\n    json_enum_option(l, 1, &cfg->encode_sparse_convert, NULL, 1);\n    json_integer_option(l, 2, &cfg->encode_sparse_ratio, 0, INT_MAX);\n    json_integer_option(l, 3, &cfg->encode_sparse_safe, 0, INT_MAX);\n\n    return 3;\n}\n\n/* Configures the maximum number of nested arrays/objects allowed when\n * encoding */\nstatic int json_cfg_encode_max_depth(lua_State *l)\n{\n    json_config_t *cfg = json_arg_init(l, 1);\n\n    return json_integer_option(l, 1, &cfg->encode_max_depth, 1, INT_MAX);\n}\n\n/* Configures the maximum number of nested arrays/objects allowed when\n * encoding */\nstatic int json_cfg_decode_max_depth(lua_State *l)\n{\n    json_config_t *cfg = json_arg_init(l, 1);\n\n    return json_integer_option(l, 1, &cfg->decode_max_depth, 1, INT_MAX);\n}\n\n/* Configures number precision when converting doubles to text */\nstatic int json_cfg_encode_number_precision(lua_State *l)\n{\n    json_config_t *cfg = json_arg_init(l, 1);\n\n    return json_integer_option(l, 1, &cfg->encode_number_precision, 1, 14);\n}\n\n/* Configures JSON encoding buffer persistence */\nstatic int json_cfg_encode_keep_buffer(lua_State *l)\n{\n    json_config_t *cfg = json_arg_init(l, 1);\n    int old_value;\n\n    old_value = cfg->encode_keep_buffer;\n\n    json_enum_option(l, 1, &cfg->encode_keep_buffer, NULL, 1);\n\n    /* Init / free the buffer if the setting has changed */\n    if (old_value ^ cfg->encode_keep_buffer) {\n        if (cfg->encode_keep_buffer)\n            strbuf_init(&cfg->encode_buf, 0);\n        else\n            strbuf_free(&cfg->encode_buf);\n    }\n\n    return 1;\n}\n\n#if defined(DISABLE_INVALID_NUMBERS) && !defined(USE_INTERNAL_FPCONV)\nvoid json_verify_invalid_number_setting(lua_State *l, int *setting)\n{\n    if (*setting == 1) {\n        *setting = 0;\n        luaL_error(l, \"Infinity, NaN, and/or hexadecimal numbers are not supported.\");\n    }\n}\n#else\n#define json_verify_invalid_number_setting(l, s)    do { } while(0)\n#endif\n\nstatic int json_cfg_encode_invalid_numbers(lua_State *l)\n{\n    static const char *options[] = { \"off\", \"on\", \"null\", NULL };\n    json_config_t *cfg = json_arg_init(l, 1);\n\n    json_enum_option(l, 1, &cfg->encode_invalid_numbers, options, 1);\n\n    json_verify_invalid_number_setting(l, &cfg->encode_invalid_numbers);\n\n    return 1;\n}\n\nstatic int json_cfg_decode_invalid_numbers(lua_State *l)\n{\n    json_config_t *cfg = json_arg_init(l, 1);\n\n    json_enum_option(l, 1, &cfg->decode_invalid_numbers, NULL, 1);\n\n    json_verify_invalid_number_setting(l, &cfg->encode_invalid_numbers);\n\n    return 1;\n}\n\nstatic int json_destroy_config(lua_State *l)\n{\n    json_config_t *cfg;\n\n    cfg = lua_touserdata(l, 1);\n    if (cfg)\n        strbuf_free(&cfg->encode_buf);\n    cfg = NULL;\n\n    return 0;\n}\n\nstatic void json_create_config(lua_State *l)\n{\n    json_config_t *cfg;\n    int i;\n\n    cfg = lua_newuserdata(l, sizeof(*cfg));\n\n    /* Create GC method to clean up strbuf */\n    lua_newtable(l);\n    lua_pushcfunction(l, json_destroy_config);\n    lua_setfield(l, -2, \"__gc\");\n    lua_setmetatable(l, -2);\n\n    cfg->encode_sparse_convert = DEFAULT_SPARSE_CONVERT;\n    cfg->encode_sparse_ratio = DEFAULT_SPARSE_RATIO;\n    cfg->encode_sparse_safe = DEFAULT_SPARSE_SAFE;\n    cfg->encode_max_depth = DEFAULT_ENCODE_MAX_DEPTH;\n    cfg->decode_max_depth = DEFAULT_DECODE_MAX_DEPTH;\n    cfg->encode_invalid_numbers = DEFAULT_ENCODE_INVALID_NUMBERS;\n    cfg->decode_invalid_numbers = DEFAULT_DECODE_INVALID_NUMBERS;\n    cfg->encode_keep_buffer = DEFAULT_ENCODE_KEEP_BUFFER;\n    cfg->encode_number_precision = DEFAULT_ENCODE_NUMBER_PRECISION;\n\n#if DEFAULT_ENCODE_KEEP_BUFFER > 0\n    strbuf_init(&cfg->encode_buf, 0);\n#endif\n\n    /* Decoding init */\n\n    /* Tag all characters as an error */\n    for (i = 0; i < 256; i++)\n        cfg->ch2token[i] = T_ERROR;\n\n    /* Set tokens that require no further processing */\n    cfg->ch2token['{'] = T_OBJ_BEGIN;\n    cfg->ch2token['}'] = T_OBJ_END;\n    cfg->ch2token['['] = T_ARR_BEGIN;\n    cfg->ch2token[']'] = T_ARR_END;\n    cfg->ch2token[','] = T_COMMA;\n    cfg->ch2token[':'] = T_COLON;\n    cfg->ch2token['\\0'] = T_END;\n    cfg->ch2token[' '] = T_WHITESPACE;\n    cfg->ch2token['\\t'] = T_WHITESPACE;\n    cfg->ch2token['\\n'] = T_WHITESPACE;\n    cfg->ch2token['\\r'] = T_WHITESPACE;\n\n    /* Update characters that require further processing */\n    cfg->ch2token['f'] = T_UNKNOWN;     /* false? */\n    cfg->ch2token['i'] = T_UNKNOWN;     /* inf, ininity? */\n    cfg->ch2token['I'] = T_UNKNOWN;\n    cfg->ch2token['n'] = T_UNKNOWN;     /* null, nan? */\n    cfg->ch2token['N'] = T_UNKNOWN;\n    cfg->ch2token['t'] = T_UNKNOWN;     /* true? */\n    cfg->ch2token['\"'] = T_UNKNOWN;     /* string? */\n    cfg->ch2token['+'] = T_UNKNOWN;     /* number? */\n    cfg->ch2token['-'] = T_UNKNOWN;\n    for (i = 0; i < 10; i++)\n        cfg->ch2token['0' + i] = T_UNKNOWN;\n\n    /* Lookup table for parsing escape characters */\n    for (i = 0; i < 256; i++)\n        cfg->escape2char[i] = 0;          /* String error */\n    cfg->escape2char['\"'] = '\"';\n    cfg->escape2char['\\\\'] = '\\\\';\n    cfg->escape2char['/'] = '/';\n    cfg->escape2char['b'] = '\\b';\n    cfg->escape2char['t'] = '\\t';\n    cfg->escape2char['n'] = '\\n';\n    cfg->escape2char['f'] = '\\f';\n    cfg->escape2char['r'] = '\\r';\n    cfg->escape2char['u'] = 'u';          /* Unicode parsing required */\n}\n\n/* ===== ENCODING ===== */\n\nstatic void json_encode_exception(lua_State *l, json_config_t *cfg, strbuf_t *json, int lindex,\n                                  const char *reason)\n{\n    if (!cfg->encode_keep_buffer)\n        strbuf_free(json);\n    luaL_error(l, \"Cannot serialise %s: %s\",\n                  lua_typename(l, lua_type(l, lindex)), reason);\n}\n\n/* json_append_string args:\n * - lua_State\n * - JSON strbuf\n * - String (Lua stack index)\n *\n * Returns nothing. Doesn't remove string from Lua stack */\nstatic void json_append_string(lua_State *l, strbuf_t *json, int lindex)\n{\n    const char *escstr;\n    int i;\n    const char *str;\n    size_t len;\n\n    str = lua_tolstring(l, lindex, &len);\n\n    /* Worst case is len * 6 (all unicode escapes).\n     * This buffer is reused constantly for small strings\n     * If there are any excess pages, they won't be hit anyway.\n     * This gains ~5% speedup. */\n    strbuf_ensure_empty_length(json, len * 6 + 2);\n\n    strbuf_append_char_unsafe(json, '\\\"');\n    for (i = 0; i < len; i++) {\n        escstr = char2escape[(unsigned char)str[i]];\n        if (escstr)\n            strbuf_append_string(json, escstr);\n        else\n            strbuf_append_char_unsafe(json, str[i]);\n    }\n    strbuf_append_char_unsafe(json, '\\\"');\n}\n\n/* Find the size of the array on the top of the Lua stack\n * -1   object (not a pure array)\n * >=0  elements in array\n */\nstatic int lua_array_length(lua_State *l, json_config_t *cfg, strbuf_t *json)\n{\n    double k;\n    int max;\n    int items;\n\n    max = 0;\n    items = 0;\n\n    lua_pushnil(l);\n    /* table, startkey */\n    while (lua_next(l, -2) != 0) {\n        /* table, key, value */\n        if (lua_type(l, -2) == LUA_TNUMBER &&\n            (k = lua_tonumber(l, -2))) {\n            /* Integer >= 1 ? */\n            if (floor(k) == k && k >= 1) {\n                if (k > max)\n                    max = k;\n                items++;\n                lua_pop(l, 1);\n                continue;\n            }\n        }\n\n        /* Must not be an array (non integer key) */\n        lua_pop(l, 2);\n        return -1;\n    }\n\n    /* Encode excessively sparse arrays as objects (if enabled) */\n    if (cfg->encode_sparse_ratio > 0 &&\n        max > items * cfg->encode_sparse_ratio &&\n        max > cfg->encode_sparse_safe) {\n        if (!cfg->encode_sparse_convert)\n            json_encode_exception(l, cfg, json, -1, \"excessively sparse array\");\n\n        return -1;\n    }\n\n    return max;\n}\n\nstatic void json_check_encode_depth(lua_State *l, json_config_t *cfg,\n                                    int current_depth, strbuf_t *json)\n{\n    /* Ensure there are enough slots free to traverse a table (key,\n     * value) and push a string for a potential error message.\n     *\n     * Unlike \"decode\", the key and value are still on the stack when\n     * lua_checkstack() is called.  Hence an extra slot for luaL_error()\n     * below is required just in case the next check to lua_checkstack()\n     * fails.\n     *\n     * While this won't cause a crash due to the EXTRA_STACK reserve\n     * slots, it would still be an improper use of the API. */\n    if (current_depth <= cfg->encode_max_depth && lua_checkstack(l, 3))\n        return;\n\n    if (!cfg->encode_keep_buffer)\n        strbuf_free(json);\n\n    luaL_error(l, \"Cannot serialise, excessive nesting (%d)\",\n               current_depth);\n}\n\nstatic void json_append_data(lua_State *l, json_config_t *cfg,\n                             int current_depth, strbuf_t *json);\n\n/* json_append_array args:\n * - lua_State\n * - JSON strbuf\n * - Size of passwd Lua array (top of stack) */\nstatic void json_append_array(lua_State *l, json_config_t *cfg, int current_depth,\n                              strbuf_t *json, int array_length)\n{\n    int comma, i;\n\n    strbuf_append_char(json, '[');\n\n    comma = 0;\n    for (i = 1; i <= array_length; i++) {\n        if (comma)\n            strbuf_append_char(json, ',');\n        else\n            comma = 1;\n\n        lua_rawgeti(l, -1, i);\n        json_append_data(l, cfg, current_depth, json);\n        lua_pop(l, 1);\n    }\n\n    strbuf_append_char(json, ']');\n}\n\nstatic void json_append_number(lua_State *l, json_config_t *cfg,\n                               strbuf_t *json, int lindex)\n{\n    double num = lua_tonumber(l, lindex);\n    int len;\n\n    if (cfg->encode_invalid_numbers == 0) {\n        /* Prevent encoding invalid numbers */\n        if (isinf(num) || isnan(num))\n            json_encode_exception(l, cfg, json, lindex, \"must not be NaN or Inf\");\n    } else if (cfg->encode_invalid_numbers == 1) {\n        /* Encode invalid numbers, but handle \"nan\" separately\n         * since some platforms may encode as \"-nan\". */\n        if (isnan(num)) {\n            strbuf_append_mem(json, \"nan\", 3);\n            return;\n        }\n    } else {\n        /* Encode invalid numbers as \"null\" */\n        if (isinf(num) || isnan(num)) {\n            strbuf_append_mem(json, \"null\", 4);\n            return;\n        }\n    }\n\n    strbuf_ensure_empty_length(json, FPCONV_G_FMT_BUFSIZE);\n    len = fpconv_g_fmt(strbuf_empty_ptr(json), num, cfg->encode_number_precision);\n    strbuf_extend_length(json, len);\n}\n\nstatic void json_append_object(lua_State *l, json_config_t *cfg,\n                               int current_depth, strbuf_t *json)\n{\n    int comma, keytype;\n\n    /* Object */\n    strbuf_append_char(json, '{');\n\n    lua_pushnil(l);\n    /* table, startkey */\n    comma = 0;\n    while (lua_next(l, -2) != 0) {\n        if (comma)\n            strbuf_append_char(json, ',');\n        else\n            comma = 1;\n\n        /* table, key, value */\n        keytype = lua_type(l, -2);\n        if (keytype == LUA_TNUMBER) {\n            strbuf_append_char(json, '\"');\n            json_append_number(l, cfg, json, -2);\n            strbuf_append_mem(json, \"\\\":\", 2);\n        } else if (keytype == LUA_TSTRING) {\n            json_append_string(l, json, -2);\n            strbuf_append_char(json, ':');\n        } else {\n            json_encode_exception(l, cfg, json, -2,\n                                  \"table key must be a number or string\");\n            /* never returns */\n        }\n\n        /* table, key, value */\n        json_append_data(l, cfg, current_depth, json);\n        lua_pop(l, 1);\n        /* table, key */\n    }\n\n    strbuf_append_char(json, '}');\n}\n\n/* Serialise Lua data into JSON string. */\nstatic void json_append_data(lua_State *l, json_config_t *cfg,\n                             int current_depth, strbuf_t *json)\n{\n    int len;\n\n    switch (lua_type(l, -1)) {\n    case LUA_TSTRING:\n        json_append_string(l, json, -1);\n        break;\n    case LUA_TNUMBER:\n        json_append_number(l, cfg, json, -1);\n        break;\n    case LUA_TBOOLEAN:\n        if (lua_toboolean(l, -1))\n            strbuf_append_mem(json, \"true\", 4);\n        else\n            strbuf_append_mem(json, \"false\", 5);\n        break;\n    case LUA_TTABLE:\n        current_depth++;\n        json_check_encode_depth(l, cfg, current_depth, json);\n        len = lua_array_length(l, cfg, json);\n        if (len > 0)\n            json_append_array(l, cfg, current_depth, json, len);\n        else\n            json_append_object(l, cfg, current_depth, json);\n        break;\n    case LUA_TNIL:\n        strbuf_append_mem(json, \"null\", 4);\n        break;\n    case LUA_TLIGHTUSERDATA:\n        if (lua_touserdata(l, -1) == NULL) {\n            strbuf_append_mem(json, \"null\", 4);\n            break;\n        }\n    default:\n        /* Remaining types (LUA_TFUNCTION, LUA_TUSERDATA, LUA_TTHREAD,\n         * and LUA_TLIGHTUSERDATA) cannot be serialised */\n        json_encode_exception(l, cfg, json, -1, \"type not supported\");\n        /* never returns */\n    }\n}\n\nstatic int json_encode(lua_State *l)\n{\n    json_config_t *cfg = json_fetch_config(l);\n    strbuf_t local_encode_buf;\n    strbuf_t *encode_buf;\n    char *json;\n    int len;\n\n    luaL_argcheck(l, lua_gettop(l) == 1, 1, \"expected 1 argument\");\n\n    if (!cfg->encode_keep_buffer) {\n        /* Use private buffer */\n        encode_buf = &local_encode_buf;\n        strbuf_init(encode_buf, 0);\n    } else {\n        /* Reuse existing buffer */\n        encode_buf = &cfg->encode_buf;\n        strbuf_reset(encode_buf);\n    }\n\n    json_append_data(l, cfg, 0, encode_buf);\n    json = strbuf_string(encode_buf, &len);\n\n    lua_pushlstring(l, json, len);\n\n    if (!cfg->encode_keep_buffer)\n        strbuf_free(encode_buf);\n\n    return 1;\n}\n\n/* ===== DECODING ===== */\n\nstatic void json_process_value(lua_State *l, json_parse_t *json,\n                               json_token_t *token);\n\nstatic int hexdigit2int(char hex)\n{\n    if ('0' <= hex  && hex <= '9')\n        return hex - '0';\n\n    /* Force lowercase */\n    hex |= 0x20;\n    if ('a' <= hex && hex <= 'f')\n        return 10 + hex - 'a';\n\n    return -1;\n}\n\nstatic int decode_hex4(const char *hex)\n{\n    int digit[4];\n    int i;\n\n    /* Convert ASCII hex digit to numeric digit\n     * Note: this returns an error for invalid hex digits, including\n     *       NULL */\n    for (i = 0; i < 4; i++) {\n        digit[i] = hexdigit2int(hex[i]);\n        if (digit[i] < 0) {\n            return -1;\n        }\n    }\n\n    return (digit[0] << 12) +\n           (digit[1] << 8) +\n           (digit[2] << 4) +\n            digit[3];\n}\n\n/* Converts a Unicode codepoint to UTF-8.\n * Returns UTF-8 string length, and up to 4 bytes in *utf8 */\nstatic int codepoint_to_utf8(char *utf8, int codepoint)\n{\n    /* 0xxxxxxx */\n    if (codepoint <= 0x7F) {\n        utf8[0] = codepoint;\n        return 1;\n    }\n\n    /* 110xxxxx 10xxxxxx */\n    if (codepoint <= 0x7FF) {\n        utf8[0] = (codepoint >> 6) | 0xC0;\n        utf8[1] = (codepoint & 0x3F) | 0x80;\n        return 2;\n    }\n\n    /* 1110xxxx 10xxxxxx 10xxxxxx */\n    if (codepoint <= 0xFFFF) {\n        utf8[0] = (codepoint >> 12) | 0xE0;\n        utf8[1] = ((codepoint >> 6) & 0x3F) | 0x80;\n        utf8[2] = (codepoint & 0x3F) | 0x80;\n        return 3;\n    }\n\n    /* 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx */\n    if (codepoint <= 0x1FFFFF) {\n        utf8[0] = (codepoint >> 18) | 0xF0;\n        utf8[1] = ((codepoint >> 12) & 0x3F) | 0x80;\n        utf8[2] = ((codepoint >> 6) & 0x3F) | 0x80;\n        utf8[3] = (codepoint & 0x3F) | 0x80;\n        return 4;\n    }\n\n    return 0;\n}\n\n\n/* Called when index pointing to beginning of UTF-16 code escape: \\uXXXX\n * \\u is guaranteed to exist, but the remaining hex characters may be\n * missing.\n * Translate to UTF-8 and append to temporary token string.\n * Must advance index to the next character to be processed.\n * Returns: 0   success\n *          -1  error\n */\nstatic int json_append_unicode_escape(json_parse_t *json)\n{\n    char utf8[4];       /* Surrogate pairs require 4 UTF-8 bytes */\n    int codepoint;\n    int surrogate_low;\n    int len;\n    int escape_len = 6;\n\n    /* Fetch UTF-16 code unit */\n    codepoint = decode_hex4(json->ptr + 2);\n    if (codepoint < 0)\n        return -1;\n\n    /* UTF-16 surrogate pairs take the following 2 byte form:\n     *      11011 x yyyyyyyyyy\n     * When x = 0: y is the high 10 bits of the codepoint\n     *      x = 1: y is the low 10 bits of the codepoint\n     *\n     * Check for a surrogate pair (high or low) */\n    if ((codepoint & 0xF800) == 0xD800) {\n        /* Error if the 1st surrogate is not high */\n        if (codepoint & 0x400)\n            return -1;\n\n        /* Ensure the next code is a unicode escape */\n        if (*(json->ptr + escape_len) != '\\\\' ||\n            *(json->ptr + escape_len + 1) != 'u') {\n            return -1;\n        }\n\n        /* Fetch the next codepoint */\n        surrogate_low = decode_hex4(json->ptr + 2 + escape_len);\n        if (surrogate_low < 0)\n            return -1;\n\n        /* Error if the 2nd code is not a low surrogate */\n        if ((surrogate_low & 0xFC00) != 0xDC00)\n            return -1;\n\n        /* Calculate Unicode codepoint */\n        codepoint = (codepoint & 0x3FF) << 10;\n        surrogate_low &= 0x3FF;\n        codepoint = (codepoint | surrogate_low) + 0x10000;\n        escape_len = 12;\n    }\n\n    /* Convert codepoint to UTF-8 */\n    len = codepoint_to_utf8(utf8, codepoint);\n    if (!len)\n        return -1;\n\n    /* Append bytes and advance parse index */\n    strbuf_append_mem_unsafe(json->tmp, utf8, len);\n    json->ptr += escape_len;\n\n    return 0;\n}\n\nstatic void json_set_token_error(json_token_t *token, json_parse_t *json,\n                                 const char *errtype)\n{\n    token->type = T_ERROR;\n    token->index = json->ptr - json->data;\n    token->value.string = errtype;\n}\n\nstatic void json_next_string_token(json_parse_t *json, json_token_t *token)\n{\n    char *escape2char = json->cfg->escape2char;\n    char ch;\n\n    /* Caller must ensure a string is next */\n    assert(*json->ptr == '\"');\n\n    /* Skip \" */\n    json->ptr++;\n\n    /* json->tmp is the temporary strbuf used to accumulate the\n     * decoded string value.\n     * json->tmp is sized to handle JSON containing only a string value.\n     */\n    strbuf_reset(json->tmp);\n\n    while ((ch = *json->ptr) != '\"') {\n        if (!ch) {\n            /* Premature end of the string */\n            json_set_token_error(token, json, \"unexpected end of string\");\n            return;\n        }\n\n        /* Handle escapes */\n        if (ch == '\\\\') {\n            /* Fetch escape character */\n            ch = *(json->ptr + 1);\n\n            /* Translate escape code and append to tmp string */\n            ch = escape2char[(unsigned char)ch];\n            if (ch == 'u') {\n                if (json_append_unicode_escape(json) == 0)\n                    continue;\n\n                json_set_token_error(token, json,\n                                     \"invalid unicode escape code\");\n                return;\n            }\n            if (!ch) {\n                json_set_token_error(token, json, \"invalid escape code\");\n                return;\n            }\n\n            /* Skip '\\' */\n            json->ptr++;\n        }\n        /* Append normal character or translated single character\n         * Unicode escapes are handled above */\n        strbuf_append_char_unsafe(json->tmp, ch);\n        json->ptr++;\n    }\n    json->ptr++;    /* Eat final quote (\") */\n\n    strbuf_ensure_null(json->tmp);\n\n    token->type = T_STRING;\n    token->value.string = strbuf_string(json->tmp, &token->string_len);\n}\n\n/* JSON numbers should take the following form:\n *      -?(0|[1-9]|[1-9][0-9]+)(.[0-9]+)?([eE][-+]?[0-9]+)?\n *\n * json_next_number_token() uses strtod() which allows other forms:\n * - numbers starting with '+'\n * - NaN, -NaN, infinity, -infinity\n * - hexadecimal numbers\n * - numbers with leading zeros\n *\n * json_is_invalid_number() detects \"numbers\" which may pass strtod()'s\n * error checking, but should not be allowed with strict JSON.\n *\n * json_is_invalid_number() may pass numbers which cause strtod()\n * to generate an error.\n */\nstatic int json_is_invalid_number(json_parse_t *json)\n{\n    const char *p = json->ptr;\n\n    /* Reject numbers starting with + */\n    if (*p == '+')\n        return 1;\n\n    /* Skip minus sign if it exists */\n    if (*p == '-')\n        p++;\n\n    /* Reject numbers starting with 0x, or leading zeros */\n    if (*p == '0') {\n        int ch2 = *(p + 1);\n\n        if ((ch2 | 0x20) == 'x' ||          /* Hex */\n            ('0' <= ch2 && ch2 <= '9'))     /* Leading zero */\n            return 1;\n\n        return 0;\n    } else if (*p <= '9') {\n        return 0;                           /* Ordinary number */\n    }\n\n    /* Reject inf/nan */\n    if (!strncasecmp(p, \"inf\", 3))\n        return 1;\n    if (!strncasecmp(p, \"nan\", 3))\n        return 1;\n\n    /* Pass all other numbers which may still be invalid, but\n     * strtod() will catch them. */\n    return 0;\n}\n\nstatic void json_next_number_token(json_parse_t *json, json_token_t *token)\n{\n    char *endptr;\n\n    token->type = T_NUMBER;\n    token->value.number = fpconv_strtod(json->ptr, &endptr);\n    if (json->ptr == endptr)\n        json_set_token_error(token, json, \"invalid number\");\n    else\n        json->ptr = endptr;     /* Skip the processed number */\n\n    return;\n}\n\n/* Fills in the token struct.\n * T_STRING will return a pointer to the json_parse_t temporary string\n * T_ERROR will leave the json->ptr pointer at the error.\n */\nstatic void json_next_token(json_parse_t *json, json_token_t *token)\n{\n    const json_token_type_t *ch2token = json->cfg->ch2token;\n    int ch;\n\n    /* Eat whitespace. */\n    while (1) {\n        ch = (unsigned char)*(json->ptr);\n        token->type = ch2token[ch];\n        if (token->type != T_WHITESPACE)\n            break;\n        json->ptr++;\n    }\n\n    /* Store location of new token. Required when throwing errors\n     * for unexpected tokens (syntax errors). */\n    token->index = json->ptr - json->data;\n\n    /* Don't advance the pointer for an error or the end */\n    if (token->type == T_ERROR) {\n        json_set_token_error(token, json, \"invalid token\");\n        return;\n    }\n\n    if (token->type == T_END) {\n        return;\n    }\n\n    /* Found a known single character token, advance index and return */\n    if (token->type != T_UNKNOWN) {\n        json->ptr++;\n        return;\n    }\n\n    /* Process characters which triggered T_UNKNOWN\n     *\n     * Must use strncmp() to match the front of the JSON string.\n     * JSON identifier must be lowercase.\n     * When strict_numbers if disabled, either case is allowed for\n     * Infinity/NaN (since we are no longer following the spec..) */\n    if (ch == '\"') {\n        json_next_string_token(json, token);\n        return;\n    } else if (ch == '-' || ('0' <= ch && ch <= '9')) {\n        if (!json->cfg->decode_invalid_numbers && json_is_invalid_number(json)) {\n            json_set_token_error(token, json, \"invalid number\");\n            return;\n        }\n        json_next_number_token(json, token);\n        return;\n    } else if (!strncmp(json->ptr, \"true\", 4)) {\n        token->type = T_BOOLEAN;\n        token->value.boolean = 1;\n        json->ptr += 4;\n        return;\n    } else if (!strncmp(json->ptr, \"false\", 5)) {\n        token->type = T_BOOLEAN;\n        token->value.boolean = 0;\n        json->ptr += 5;\n        return;\n    } else if (!strncmp(json->ptr, \"null\", 4)) {\n        token->type = T_NULL;\n        json->ptr += 4;\n        return;\n    } else if (json->cfg->decode_invalid_numbers &&\n               json_is_invalid_number(json)) {\n        /* When decode_invalid_numbers is enabled, only attempt to process\n         * numbers we know are invalid JSON (Inf, NaN, hex)\n         * This is required to generate an appropriate token error,\n         * otherwise all bad tokens will register as \"invalid number\"\n         */\n        json_next_number_token(json, token);\n        return;\n    }\n\n    /* Token starts with t/f/n but isn't recognised above. */\n    json_set_token_error(token, json, \"invalid token\");\n}\n\n/* This function does not return.\n * DO NOT CALL WITH DYNAMIC MEMORY ALLOCATED.\n * The only supported exception is the temporary parser string\n * json->tmp struct.\n * json and token should exist on the stack somewhere.\n * luaL_error() will long_jmp and release the stack */\nstatic void json_throw_parse_error(lua_State *l, json_parse_t *json,\n                                   const char *exp, json_token_t *token)\n{\n    const char *found;\n\n    strbuf_free(json->tmp);\n\n    if (token->type == T_ERROR)\n        found = token->value.string;\n    else\n        found = json_token_type_name[token->type];\n\n    /* Note: token->index is 0 based, display starting from 1 */\n    luaL_error(l, \"Expected %s but found %s at character %d\",\n               exp, found, token->index + 1);\n}\n\nstatic inline void json_decode_ascend(json_parse_t *json)\n{\n    json->current_depth--;\n}\n\nstatic void json_decode_descend(lua_State *l, json_parse_t *json, int slots)\n{\n    json->current_depth++;\n\n    if (json->current_depth <= json->cfg->decode_max_depth &&\n        lua_checkstack(l, slots)) {\n        return;\n    }\n\n    strbuf_free(json->tmp);\n    luaL_error(l, \"Found too many nested data structures (%d) at character %d\",\n        json->current_depth, json->ptr - json->data);\n}\n\nstatic void json_parse_object_context(lua_State *l, json_parse_t *json)\n{\n    json_token_t token;\n\n    /* 3 slots required:\n     * .., table, key, value */\n    json_decode_descend(l, json, 3);\n\n    lua_newtable(l);\n\n    json_next_token(json, &token);\n\n    /* Handle empty objects */\n    if (token.type == T_OBJ_END) {\n        json_decode_ascend(json);\n        return;\n    }\n\n    while (1) {\n        if (token.type != T_STRING)\n            json_throw_parse_error(l, json, \"object key string\", &token);\n\n        /* Push key */\n        lua_pushlstring(l, token.value.string, token.string_len);\n\n        json_next_token(json, &token);\n        if (token.type != T_COLON)\n            json_throw_parse_error(l, json, \"colon\", &token);\n\n        /* Fetch value */\n        json_next_token(json, &token);\n        json_process_value(l, json, &token);\n\n        /* Set key = value */\n        lua_rawset(l, -3);\n\n        json_next_token(json, &token);\n\n        if (token.type == T_OBJ_END) {\n            json_decode_ascend(json);\n            return;\n        }\n\n        if (token.type != T_COMMA)\n            json_throw_parse_error(l, json, \"comma or object end\", &token);\n\n        json_next_token(json, &token);\n    }\n}\n\n/* Handle the array context */\nstatic void json_parse_array_context(lua_State *l, json_parse_t *json)\n{\n    json_token_t token;\n    int i;\n\n    /* 2 slots required:\n     * .., table, value */\n    json_decode_descend(l, json, 2);\n\n    lua_newtable(l);\n\n    json_next_token(json, &token);\n\n    /* Handle empty arrays */\n    if (token.type == T_ARR_END) {\n        json_decode_ascend(json);\n        return;\n    }\n\n    for (i = 1; ; i++) {\n        json_process_value(l, json, &token);\n        lua_rawseti(l, -2, i);            /* arr[i] = value */\n\n        json_next_token(json, &token);\n\n        if (token.type == T_ARR_END) {\n            json_decode_ascend(json);\n            return;\n        }\n\n        if (token.type != T_COMMA)\n            json_throw_parse_error(l, json, \"comma or array end\", &token);\n\n        json_next_token(json, &token);\n    }\n}\n\n/* Handle the \"value\" context */\nstatic void json_process_value(lua_State *l, json_parse_t *json,\n                               json_token_t *token)\n{\n    switch (token->type) {\n    case T_STRING:\n        lua_pushlstring(l, token->value.string, token->string_len);\n        break;;\n    case T_NUMBER:\n        lua_pushnumber(l, token->value.number);\n        break;;\n    case T_BOOLEAN:\n        lua_pushboolean(l, token->value.boolean);\n        break;;\n    case T_OBJ_BEGIN:\n        json_parse_object_context(l, json);\n        break;;\n    case T_ARR_BEGIN:\n        json_parse_array_context(l, json);\n        break;;\n    case T_NULL:\n        /* In Lua, setting \"t[k] = nil\" will delete k from the table.\n         * Hence a NULL pointer lightuserdata object is used instead */\n        lua_pushlightuserdata(l, NULL);\n        break;;\n    default:\n        json_throw_parse_error(l, json, \"value\", token);\n    }\n}\n\nstatic int json_decode(lua_State *l)\n{\n    json_parse_t json;\n    json_token_t token;\n    size_t json_len;\n\n    luaL_argcheck(l, lua_gettop(l) == 1, 1, \"expected 1 argument\");\n\n    json.cfg = json_fetch_config(l);\n    json.data = luaL_checklstring(l, 1, &json_len);\n    json.current_depth = 0;\n    json.ptr = json.data;\n\n    /* Detect Unicode other than UTF-8 (see RFC 4627, Sec 3)\n     *\n     * CJSON can support any simple data type, hence only the first\n     * character is guaranteed to be ASCII (at worst: '\"'). This is\n     * still enough to detect whether the wrong encoding is in use. */\n    if (json_len >= 2 && (!json.data[0] || !json.data[1]))\n        luaL_error(l, \"JSON parser does not support UTF-16 or UTF-32\");\n\n    /* Ensure the temporary buffer can hold the entire string.\n     * This means we no longer need to do length checks since the decoded\n     * string must be smaller than the entire json string */\n    json.tmp = strbuf_new(json_len);\n\n    json_next_token(&json, &token);\n    json_process_value(l, &json, &token);\n\n    /* Ensure there is no more input left */\n    json_next_token(&json, &token);\n\n    if (token.type != T_END)\n        json_throw_parse_error(l, &json, \"the end\", &token);\n\n    strbuf_free(json.tmp);\n\n    return 1;\n}\n\n/* ===== INITIALISATION ===== */\n\n#if !defined(LUA_VERSION_NUM) || LUA_VERSION_NUM < 502\n/* Compatibility for Lua 5.1.\n *\n * luaL_setfuncs() is used to create a module table where the functions have\n * json_config_t as their first upvalue. Code borrowed from Lua 5.2 source. */\nstatic void luaL_setfuncs (lua_State *l, const luaL_Reg *reg, int nup)\n{\n    int i;\n\n    luaL_checkstack(l, nup, \"too many upvalues\");\n    for (; reg->name != NULL; reg++) {  /* fill the table with given functions */\n        for (i = 0; i < nup; i++)  /* copy upvalues to the top */\n            lua_pushvalue(l, -nup);\n        lua_pushcclosure(l, reg->func, nup);  /* closure with those upvalues */\n        lua_setfield(l, -(nup + 2), reg->name);\n    }\n    lua_pop(l, nup);  /* remove upvalues */\n}\n#endif\n\n/* Call target function in protected mode with all supplied args.\n * Assumes target function only returns a single non-nil value.\n * Convert and return thrown errors as: nil, \"error message\" */\nstatic int json_protect_conversion(lua_State *l)\n{\n    int err;\n\n    /* Deliberately throw an error for invalid arguments */\n    luaL_argcheck(l, lua_gettop(l) == 1, 1, \"expected 1 argument\");\n\n    /* pcall() the function stored as upvalue(1) */\n    lua_pushvalue(l, lua_upvalueindex(1));\n    lua_insert(l, 1);\n    err = lua_pcall(l, 1, 1, 0);\n    if (!err)\n        return 1;\n\n    if (err == LUA_ERRRUN) {\n        lua_pushnil(l);\n        lua_insert(l, -2);\n        return 2;\n    }\n\n    /* Since we are not using a custom error handler, the only remaining\n     * errors are memory related */\n    return luaL_error(l, \"Memory allocation error in CJSON protected call\");\n}\n\n/* Return cjson module table */\nstatic int lua_cjson_new(lua_State *l)\n{\n    luaL_Reg reg[] = {\n        { \"encode\", json_encode },\n        { \"decode\", json_decode },\n        { \"encode_sparse_array\", json_cfg_encode_sparse_array },\n        { \"encode_max_depth\", json_cfg_encode_max_depth },\n        { \"decode_max_depth\", json_cfg_decode_max_depth },\n        { \"encode_number_precision\", json_cfg_encode_number_precision },\n        { \"encode_keep_buffer\", json_cfg_encode_keep_buffer },\n        { \"encode_invalid_numbers\", json_cfg_encode_invalid_numbers },\n        { \"decode_invalid_numbers\", json_cfg_decode_invalid_numbers },\n        { \"new\", lua_cjson_new },\n        { NULL, NULL }\n    };\n\n    /* Initialise number conversions */\n    fpconv_init();\n\n    /* cjson module table */\n    lua_newtable(l);\n\n    /* Register functions with config data as upvalue */\n    json_create_config(l);\n    luaL_setfuncs(l, reg, 1);\n\n    /* Set cjson.null */\n    lua_pushlightuserdata(l, NULL);\n    lua_setfield(l, -2, \"null\");\n\n    /* Set module name / version fields */\n    lua_pushliteral(l, CJSON_MODNAME);\n    lua_setfield(l, -2, \"_NAME\");\n    lua_pushliteral(l, CJSON_VERSION);\n    lua_setfield(l, -2, \"_VERSION\");\n\n    return 1;\n}\n\n/* Return cjson.safe module table */\nstatic int lua_cjson_safe_new(lua_State *l)\n{\n    const char *func[] = { \"decode\", \"encode\", NULL };\n    int i;\n\n    lua_cjson_new(l);\n\n    /* Fix new() method */\n    lua_pushcfunction(l, lua_cjson_safe_new);\n    lua_setfield(l, -2, \"new\");\n\n    for (i = 0; func[i]; i++) {\n        lua_getfield(l, -1, func[i]);\n        lua_pushcclosure(l, json_protect_conversion, 1);\n        lua_setfield(l, -2, func[i]);\n    }\n\n    return 1;\n}\n\nint luaopen_cjson(lua_State *l)\n{\n    lua_cjson_new(l);\n\n#ifdef ENABLE_CJSON_GLOBAL\n    /* Register a global \"cjson\" table. */\n    lua_pushvalue(l, -1);\n    lua_setglobal(l, CJSON_MODNAME);\n#endif\n\n    /* Return cjson table */\n    return 1;\n}\n\nint luaopen_cjson_safe(lua_State *l)\n{\n    lua_cjson_safe_new(l);\n\n    /* Return cjson.safe table */\n    return 1;\n}\n\n/* vi:ai et sw=4 ts=4:\n */\n"
  },
  {
    "path": "extern/deprecated/redis-2.8.21/deps/lua/src/lua_cmsgpack.c",
    "content": "#include <math.h>\n#include <stdlib.h>\n#include <stdint.h>\n#include <string.h>\n#include <assert.h>\n\n#include \"lua.h\"\n#include \"lauxlib.h\"\n\n#define LUACMSGPACK_NAME        \"cmsgpack\"\n#define LUACMSGPACK_SAFE_NAME   \"cmsgpack_safe\"\n#define LUACMSGPACK_VERSION     \"lua-cmsgpack 0.4.0\"\n#define LUACMSGPACK_COPYRIGHT   \"Copyright (C) 2012, Salvatore Sanfilippo\"\n#define LUACMSGPACK_DESCRIPTION \"MessagePack C implementation for Lua\"\n\n/* Allows a preprocessor directive to override MAX_NESTING */\n#ifndef LUACMSGPACK_MAX_NESTING\n    #define LUACMSGPACK_MAX_NESTING  16 /* Max tables nesting. */\n#endif\n\n/* Check if float or double can be an integer without loss of precision */\n#define IS_INT_TYPE_EQUIVALENT(x, T) (!isinf(x) && (T)(x) == (x))\n\n#define IS_INT64_EQUIVALENT(x) IS_INT_TYPE_EQUIVALENT(x, int64_t)\n#define IS_INT_EQUIVALENT(x) IS_INT_TYPE_EQUIVALENT(x, int)\n\n/* If size of pointer is equal to a 4 byte integer, we're on 32 bits. */\n#if UINTPTR_MAX == UINT_MAX\n    #define BITS_32 1\n#else\n    #define BITS_32 0\n#endif\n\n#if BITS_32\n    #define lua_pushunsigned(L, n) lua_pushnumber(L, n)\n#else\n    #define lua_pushunsigned(L, n) lua_pushinteger(L, n)\n#endif\n\n/* =============================================================================\n * MessagePack implementation and bindings for Lua 5.1/5.2.\n * Copyright(C) 2012 Salvatore Sanfilippo <antirez@gmail.com>\n *\n * http://github.com/antirez/lua-cmsgpack\n *\n * For MessagePack specification check the following web site:\n * http://wiki.msgpack.org/display/MSGPACK/Format+specification\n *\n * See Copyright Notice at the end of this file.\n *\n * CHANGELOG:\n * 19-Feb-2012 (ver 0.1.0): Initial release.\n * 20-Feb-2012 (ver 0.2.0): Tables encoding improved.\n * 20-Feb-2012 (ver 0.2.1): Minor bug fixing.\n * 20-Feb-2012 (ver 0.3.0): Module renamed lua-cmsgpack (was lua-msgpack).\n * 04-Apr-2014 (ver 0.3.1): Lua 5.2 support and minor bug fix.\n * 07-Apr-2014 (ver 0.4.0): Multiple pack/unpack, lua allocator, efficiency.\n * ========================================================================== */\n\n/* -------------------------- Endian conversion --------------------------------\n * We use it only for floats and doubles, all the other conversions performed\n * in an endian independent fashion. So the only thing we need is a function\n * that swaps a binary string if arch is little endian (and left it untouched\n * otherwise). */\n\n/* Reverse memory bytes if arch is little endian. Given the conceptual\n * simplicity of the Lua build system we prefer check for endianess at runtime.\n * The performance difference should be acceptable. */\nvoid memrevifle(void *ptr, size_t len) {\n    unsigned char   *p = (unsigned char *)ptr,\n                    *e = (unsigned char *)p+len-1,\n                    aux;\n    int test = 1;\n    unsigned char *testp = (unsigned char*) &test;\n\n    if (testp[0] == 0) return; /* Big endian, nothing to do. */\n    len /= 2;\n    while(len--) {\n        aux = *p;\n        *p = *e;\n        *e = aux;\n        p++;\n        e--;\n    }\n}\n\n/* ---------------------------- String buffer ----------------------------------\n * This is a simple implementation of string buffers. The only operation\n * supported is creating empty buffers and appending bytes to it.\n * The string buffer uses 2x preallocation on every realloc for O(N) append\n * behavior.  */\n\ntypedef struct mp_buf {\n    lua_State *L;\n    unsigned char *b;\n    size_t len, free;\n} mp_buf;\n\nvoid *mp_realloc(lua_State *L, void *target, size_t osize,size_t nsize) {\n    void *(*local_realloc) (void *, void *, size_t osize, size_t nsize) = NULL;\n    void *ud;\n\n    local_realloc = lua_getallocf(L, &ud);\n\n    return local_realloc(ud, target, osize, nsize);\n}\n\nmp_buf *mp_buf_new(lua_State *L) {\n    mp_buf *buf = NULL;\n\n    /* Old size = 0; new size = sizeof(*buf) */\n    buf = (mp_buf*)mp_realloc(L, NULL, 0, sizeof(*buf));\n\n    buf->L = L;\n    buf->b = NULL;\n    buf->len = buf->free = 0;\n    return buf;\n}\n\nvoid mp_buf_append(mp_buf *buf, const unsigned char *s, size_t len) {\n    if (buf->free < len) {\n        size_t newlen = buf->len+len;\n\n        buf->b = (unsigned char*)mp_realloc(buf->L, buf->b, buf->len, newlen*2);\n        buf->free = newlen;\n    }\n    memcpy(buf->b+buf->len,s,len);\n    buf->len += len;\n    buf->free -= len;\n}\n\nvoid mp_buf_free(mp_buf *buf) {\n    mp_realloc(buf->L, buf->b, buf->len, 0); /* realloc to 0 = free */\n    mp_realloc(buf->L, buf, sizeof(*buf), 0);\n}\n\n/* ---------------------------- String cursor ----------------------------------\n * This simple data structure is used for parsing. Basically you create a cursor\n * using a string pointer and a length, then it is possible to access the\n * current string position with cursor->p, check the remaining length\n * in cursor->left, and finally consume more string using\n * mp_cur_consume(cursor,len), to advance 'p' and subtract 'left'.\n * An additional field cursor->error is set to zero on initialization and can\n * be used to report errors. */\n\n#define MP_CUR_ERROR_NONE   0\n#define MP_CUR_ERROR_EOF    1   /* Not enough data to complete operation. */\n#define MP_CUR_ERROR_BADFMT 2   /* Bad data format */\n\ntypedef struct mp_cur {\n    const unsigned char *p;\n    size_t left;\n    int err;\n} mp_cur;\n\nvoid mp_cur_init(mp_cur *cursor, const unsigned char *s, size_t len) {\n    cursor->p = s;\n    cursor->left = len;\n    cursor->err = MP_CUR_ERROR_NONE;\n}\n\n#define mp_cur_consume(_c,_len) do { _c->p += _len; _c->left -= _len; } while(0)\n\n/* When there is not enough room we set an error in the cursor and return. This\n * is very common across the code so we have a macro to make the code look\n * a bit simpler. */\n#define mp_cur_need(_c,_len) do { \\\n    if (_c->left < _len) { \\\n        _c->err = MP_CUR_ERROR_EOF; \\\n        return; \\\n    } \\\n} while(0)\n\n/* ------------------------- Low level MP encoding -------------------------- */\n\nvoid mp_encode_bytes(mp_buf *buf, const unsigned char *s, size_t len) {\n    unsigned char hdr[5];\n    int hdrlen;\n\n    if (len < 32) {\n        hdr[0] = 0xa0 | (len&0xff); /* fix raw */\n        hdrlen = 1;\n    } else if (len <= 0xff) {\n        hdr[0] = 0xd9;\n        hdr[1] = len;\n        hdrlen = 2;\n    } else if (len <= 0xffff) {\n        hdr[0] = 0xda;\n        hdr[1] = (len&0xff00)>>8;\n        hdr[2] = len&0xff;\n        hdrlen = 3;\n    } else {\n        hdr[0] = 0xdb;\n        hdr[1] = (len&0xff000000)>>24;\n        hdr[2] = (len&0xff0000)>>16;\n        hdr[3] = (len&0xff00)>>8;\n        hdr[4] = len&0xff;\n        hdrlen = 5;\n    }\n    mp_buf_append(buf,hdr,hdrlen);\n    mp_buf_append(buf,s,len);\n}\n\n/* we assume IEEE 754 internal format for single and double precision floats. */\nvoid mp_encode_double(mp_buf *buf, double d) {\n    unsigned char b[9];\n    float f = d;\n\n    assert(sizeof(f) == 4 && sizeof(d) == 8);\n    if (d == (double)f) {\n        b[0] = 0xca;    /* float IEEE 754 */\n        memcpy(b+1,&f,4);\n        memrevifle(b+1,4);\n        mp_buf_append(buf,b,5);\n    } else if (sizeof(d) == 8) {\n        b[0] = 0xcb;    /* double IEEE 754 */\n        memcpy(b+1,&d,8);\n        memrevifle(b+1,8);\n        mp_buf_append(buf,b,9);\n    }\n}\n\nvoid mp_encode_int(mp_buf *buf, int64_t n) {\n    unsigned char b[9];\n    int enclen;\n\n    if (n >= 0) {\n        if (n <= 127) {\n            b[0] = n & 0x7f;    /* positive fixnum */\n            enclen = 1;\n        } else if (n <= 0xff) {\n            b[0] = 0xcc;        /* uint 8 */\n            b[1] = n & 0xff;\n            enclen = 2;\n        } else if (n <= 0xffff) {\n            b[0] = 0xcd;        /* uint 16 */\n            b[1] = (n & 0xff00) >> 8;\n            b[2] = n & 0xff;\n            enclen = 3;\n        } else if (n <= 0xffffffffLL) {\n            b[0] = 0xce;        /* uint 32 */\n            b[1] = (n & 0xff000000) >> 24;\n            b[2] = (n & 0xff0000) >> 16;\n            b[3] = (n & 0xff00) >> 8;\n            b[4] = n & 0xff;\n            enclen = 5;\n        } else {\n            b[0] = 0xcf;        /* uint 64 */\n            b[1] = (n & 0xff00000000000000LL) >> 56;\n            b[2] = (n & 0xff000000000000LL) >> 48;\n            b[3] = (n & 0xff0000000000LL) >> 40;\n            b[4] = (n & 0xff00000000LL) >> 32;\n            b[5] = (n & 0xff000000) >> 24;\n            b[6] = (n & 0xff0000) >> 16;\n            b[7] = (n & 0xff00) >> 8;\n            b[8] = n & 0xff;\n            enclen = 9;\n        }\n    } else {\n        if (n >= -32) {\n            b[0] = ((signed char)n);   /* negative fixnum */\n            enclen = 1;\n        } else if (n >= -128) {\n            b[0] = 0xd0;        /* int 8 */\n            b[1] = n & 0xff;\n            enclen = 2;\n        } else if (n >= -32768) {\n            b[0] = 0xd1;        /* int 16 */\n            b[1] = (n & 0xff00) >> 8;\n            b[2] = n & 0xff;\n            enclen = 3;\n        } else if (n >= -2147483648LL) {\n            b[0] = 0xd2;        /* int 32 */\n            b[1] = (n & 0xff000000) >> 24;\n            b[2] = (n & 0xff0000) >> 16;\n            b[3] = (n & 0xff00) >> 8;\n            b[4] = n & 0xff;\n            enclen = 5;\n        } else {\n            b[0] = 0xd3;        /* int 64 */\n            b[1] = (n & 0xff00000000000000LL) >> 56;\n            b[2] = (n & 0xff000000000000LL) >> 48;\n            b[3] = (n & 0xff0000000000LL) >> 40;\n            b[4] = (n & 0xff00000000LL) >> 32;\n            b[5] = (n & 0xff000000) >> 24;\n            b[6] = (n & 0xff0000) >> 16;\n            b[7] = (n & 0xff00) >> 8;\n            b[8] = n & 0xff;\n            enclen = 9;\n        }\n    }\n    mp_buf_append(buf,b,enclen);\n}\n\nvoid mp_encode_array(mp_buf *buf, int64_t n) {\n    unsigned char b[5];\n    int enclen;\n\n    if (n <= 15) {\n        b[0] = 0x90 | (n & 0xf);    /* fix array */\n        enclen = 1;\n    } else if (n <= 65535) {\n        b[0] = 0xdc;                /* array 16 */\n        b[1] = (n & 0xff00) >> 8;\n        b[2] = n & 0xff;\n        enclen = 3;\n    } else {\n        b[0] = 0xdd;                /* array 32 */\n        b[1] = (n & 0xff000000) >> 24;\n        b[2] = (n & 0xff0000) >> 16;\n        b[3] = (n & 0xff00) >> 8;\n        b[4] = n & 0xff;\n        enclen = 5;\n    }\n    mp_buf_append(buf,b,enclen);\n}\n\nvoid mp_encode_map(mp_buf *buf, int64_t n) {\n    unsigned char b[5];\n    int enclen;\n\n    if (n <= 15) {\n        b[0] = 0x80 | (n & 0xf);    /* fix map */\n        enclen = 1;\n    } else if (n <= 65535) {\n        b[0] = 0xde;                /* map 16 */\n        b[1] = (n & 0xff00) >> 8;\n        b[2] = n & 0xff;\n        enclen = 3;\n    } else {\n        b[0] = 0xdf;                /* map 32 */\n        b[1] = (n & 0xff000000) >> 24;\n        b[2] = (n & 0xff0000) >> 16;\n        b[3] = (n & 0xff00) >> 8;\n        b[4] = n & 0xff;\n        enclen = 5;\n    }\n    mp_buf_append(buf,b,enclen);\n}\n\n/* --------------------------- Lua types encoding --------------------------- */\n\nvoid mp_encode_lua_string(lua_State *L, mp_buf *buf) {\n    size_t len;\n    const char *s;\n\n    s = lua_tolstring(L,-1,&len);\n    mp_encode_bytes(buf,(const unsigned char*)s,len);\n}\n\nvoid mp_encode_lua_bool(lua_State *L, mp_buf *buf) {\n    unsigned char b = lua_toboolean(L,-1) ? 0xc3 : 0xc2;\n    mp_buf_append(buf,&b,1);\n}\n\n/* Lua 5.3 has a built in 64-bit integer type */\nvoid mp_encode_lua_integer(lua_State *L, mp_buf *buf) {\n#if (LUA_VERSION_NUM < 503) && BITS_32\n    lua_Number i = lua_tonumber(L,-1);\n#else\n    lua_Integer i = lua_tointeger(L,-1);\n#endif\n    mp_encode_int(buf, (int64_t)i);\n}\n\n/* Lua 5.2 and lower only has 64-bit doubles, so we need to\n * detect if the double may be representable as an int\n * for Lua < 5.3 */\nvoid mp_encode_lua_number(lua_State *L, mp_buf *buf) {\n    lua_Number n = lua_tonumber(L,-1);\n\n    if (IS_INT64_EQUIVALENT(n)) {\n        mp_encode_lua_integer(L, buf);\n    } else {\n        mp_encode_double(buf,(double)n);\n    }\n}\n\nvoid mp_encode_lua_type(lua_State *L, mp_buf *buf, int level);\n\n/* Convert a lua table into a message pack list. */\nvoid mp_encode_lua_table_as_array(lua_State *L, mp_buf *buf, int level) {\n#if LUA_VERSION_NUM < 502\n    size_t len = lua_objlen(L,-1), j;\n#else\n    size_t len = lua_rawlen(L,-1), j;\n#endif\n\n    mp_encode_array(buf,len);\n    for (j = 1; j <= len; j++) {\n        lua_pushnumber(L,j);\n        lua_gettable(L,-2);\n        mp_encode_lua_type(L,buf,level+1);\n    }\n}\n\n/* Convert a lua table into a message pack key-value map. */\nvoid mp_encode_lua_table_as_map(lua_State *L, mp_buf *buf, int level) {\n    size_t len = 0;\n\n    /* First step: count keys into table. No other way to do it with the\n     * Lua API, we need to iterate a first time. Note that an alternative\n     * would be to do a single run, and then hack the buffer to insert the\n     * map opcodes for message pack. Too hackish for this lib. */\n    lua_pushnil(L);\n    while(lua_next(L,-2)) {\n        lua_pop(L,1); /* remove value, keep key for next iteration. */\n        len++;\n    }\n\n    /* Step two: actually encoding of the map. */\n    mp_encode_map(buf,len);\n    lua_pushnil(L);\n    while(lua_next(L,-2)) {\n        /* Stack: ... key value */\n        lua_pushvalue(L,-2); /* Stack: ... key value key */\n        mp_encode_lua_type(L,buf,level+1); /* encode key */\n        mp_encode_lua_type(L,buf,level+1); /* encode val */\n    }\n}\n\n/* Returns true if the Lua table on top of the stack is exclusively composed\n * of keys from numerical keys from 1 up to N, with N being the total number\n * of elements, without any hole in the middle. */\nint table_is_an_array(lua_State *L) {\n    int count = 0, max = 0;\n#if LUA_VERSION_NUM < 503\n    lua_Number n;\n#else\n    lua_Integer n;\n#endif\n\n    /* Stack top on function entry */\n    int stacktop;\n\n    stacktop = lua_gettop(L);\n\n    lua_pushnil(L);\n    while(lua_next(L,-2)) {\n        /* Stack: ... key value */\n        lua_pop(L,1); /* Stack: ... key */\n        /* The <= 0 check is valid here because we're comparing indexes. */\n#if LUA_VERSION_NUM < 503\n        if ((LUA_TNUMBER != lua_type(L,-1)) || (n = lua_tonumber(L, -1)) <= 0 ||\n            !IS_INT_EQUIVALENT(n))\n#else\n        if (!lua_isinteger(L,-1) || (n = lua_tointeger(L, -1)) <= 0)\n#endif\n        {\n            lua_settop(L, stacktop);\n            return 0;\n        }\n        max = (n > max ? n : max);\n        count++;\n    }\n    /* We have the total number of elements in \"count\". Also we have\n     * the max index encountered in \"max\". We can't reach this code\n     * if there are indexes <= 0. If you also note that there can not be\n     * repeated keys into a table, you have that if max==count you are sure\n     * that there are all the keys form 1 to count (both included). */\n    lua_settop(L, stacktop);\n    return max == count;\n}\n\n/* If the length operator returns non-zero, that is, there is at least\n * an object at key '1', we serialize to message pack list. Otherwise\n * we use a map. */\nvoid mp_encode_lua_table(lua_State *L, mp_buf *buf, int level) {\n    if (table_is_an_array(L))\n        mp_encode_lua_table_as_array(L,buf,level);\n    else\n        mp_encode_lua_table_as_map(L,buf,level);\n}\n\nvoid mp_encode_lua_null(lua_State *L, mp_buf *buf) {\n    unsigned char b[1];\n    (void)L;\n\n    b[0] = 0xc0;\n    mp_buf_append(buf,b,1);\n}\n\nvoid mp_encode_lua_type(lua_State *L, mp_buf *buf, int level) {\n    int t = lua_type(L,-1);\n\n    /* Limit the encoding of nested tables to a specified maximum depth, so that\n     * we survive when called against circular references in tables. */\n    if (t == LUA_TTABLE && level == LUACMSGPACK_MAX_NESTING) t = LUA_TNIL;\n    switch(t) {\n    case LUA_TSTRING: mp_encode_lua_string(L,buf); break;\n    case LUA_TBOOLEAN: mp_encode_lua_bool(L,buf); break;\n    case LUA_TNUMBER:\n    #if LUA_VERSION_NUM < 503\n        mp_encode_lua_number(L,buf); break;\n    #else\n        if (lua_isinteger(L, -1)) {\n            mp_encode_lua_integer(L, buf);\n        } else {\n            mp_encode_lua_number(L, buf);\n        }\n        break;\n    #endif\n    case LUA_TTABLE: mp_encode_lua_table(L,buf,level); break;\n    default: mp_encode_lua_null(L,buf); break;\n    }\n    lua_pop(L,1);\n}\n\n/*\n * Packs all arguments as a stream for multiple upacking later.\n * Returns error if no arguments provided.\n */\nint mp_pack(lua_State *L) {\n    int nargs = lua_gettop(L);\n    int i;\n    mp_buf *buf;\n\n    if (nargs == 0)\n        return luaL_argerror(L, 0, \"MessagePack pack needs input.\");\n\n    buf = mp_buf_new(L);\n    for(i = 1; i <= nargs; i++) {\n        /* Copy argument i to top of stack for _encode processing;\n         * the encode function pops it from the stack when complete. */\n        lua_pushvalue(L, i);\n\n        mp_encode_lua_type(L,buf,0);\n\n        lua_pushlstring(L,(char*)buf->b,buf->len);\n\n        /* Reuse the buffer for the next operation by\n         * setting its free count to the total buffer size\n         * and the current position to zero. */\n        buf->free += buf->len;\n        buf->len = 0;\n    }\n    mp_buf_free(buf);\n\n    /* Concatenate all nargs buffers together */\n    lua_concat(L, nargs);\n    return 1;\n}\n\n/* ------------------------------- Decoding --------------------------------- */\n\nvoid mp_decode_to_lua_type(lua_State *L, mp_cur *c);\n\nvoid mp_decode_to_lua_array(lua_State *L, mp_cur *c, size_t len) {\n    assert(len <= UINT_MAX);\n    int index = 1;\n\n    lua_newtable(L);\n    while(len--) {\n        lua_pushnumber(L,index++);\n        mp_decode_to_lua_type(L,c);\n        if (c->err) return;\n        lua_settable(L,-3);\n    }\n}\n\nvoid mp_decode_to_lua_hash(lua_State *L, mp_cur *c, size_t len) {\n    assert(len <= UINT_MAX);\n    lua_newtable(L);\n    while(len--) {\n        mp_decode_to_lua_type(L,c); /* key */\n        if (c->err) return;\n        mp_decode_to_lua_type(L,c); /* value */\n        if (c->err) return;\n        lua_settable(L,-3);\n    }\n}\n\n/* Decode a Message Pack raw object pointed by the string cursor 'c' to\n * a Lua type, that is left as the only result on the stack. */\nvoid mp_decode_to_lua_type(lua_State *L, mp_cur *c) {\n    mp_cur_need(c,1);\n\n    /* If we return more than 18 elements, we must resize the stack to\n     * fit all our return values.  But, there is no way to\n     * determine how many objects a msgpack will unpack to up front, so\n     * we request a +1 larger stack on each iteration (noop if stack is\n     * big enough, and when stack does require resize it doubles in size) */\n    luaL_checkstack(L, 1,\n        \"too many return values at once; \"\n        \"use unpack_one or unpack_limit instead.\");\n\n    switch(c->p[0]) {\n    case 0xcc:  /* uint 8 */\n        mp_cur_need(c,2);\n        lua_pushunsigned(L,c->p[1]);\n        mp_cur_consume(c,2);\n        break;\n    case 0xd0:  /* int 8 */\n        mp_cur_need(c,2);\n        lua_pushinteger(L,(signed char)c->p[1]);\n        mp_cur_consume(c,2);\n        break;\n    case 0xcd:  /* uint 16 */\n        mp_cur_need(c,3);\n        lua_pushunsigned(L,\n            (c->p[1] << 8) |\n             c->p[2]);\n        mp_cur_consume(c,3);\n        break;\n    case 0xd1:  /* int 16 */\n        mp_cur_need(c,3);\n        lua_pushinteger(L,(int16_t)\n            (c->p[1] << 8) |\n             c->p[2]);\n        mp_cur_consume(c,3);\n        break;\n    case 0xce:  /* uint 32 */\n        mp_cur_need(c,5);\n        lua_pushunsigned(L,\n            ((uint32_t)c->p[1] << 24) |\n            ((uint32_t)c->p[2] << 16) |\n            ((uint32_t)c->p[3] << 8) |\n             (uint32_t)c->p[4]);\n        mp_cur_consume(c,5);\n        break;\n    case 0xd2:  /* int 32 */\n        mp_cur_need(c,5);\n        lua_pushinteger(L,\n            ((int32_t)c->p[1] << 24) |\n            ((int32_t)c->p[2] << 16) |\n            ((int32_t)c->p[3] << 8) |\n             (int32_t)c->p[4]);\n        mp_cur_consume(c,5);\n        break;\n    case 0xcf:  /* uint 64 */\n        mp_cur_need(c,9);\n        lua_pushunsigned(L,\n            ((uint64_t)c->p[1] << 56) |\n            ((uint64_t)c->p[2] << 48) |\n            ((uint64_t)c->p[3] << 40) |\n            ((uint64_t)c->p[4] << 32) |\n            ((uint64_t)c->p[5] << 24) |\n            ((uint64_t)c->p[6] << 16) |\n            ((uint64_t)c->p[7] << 8) |\n             (uint64_t)c->p[8]);\n        mp_cur_consume(c,9);\n        break;\n    case 0xd3:  /* int 64 */\n        mp_cur_need(c,9);\n#if LUA_VERSION_NUM < 503\n        lua_pushnumber(L,\n#else\n        lua_pushinteger(L,\n#endif\n            ((int64_t)c->p[1] << 56) |\n            ((int64_t)c->p[2] << 48) |\n            ((int64_t)c->p[3] << 40) |\n            ((int64_t)c->p[4] << 32) |\n            ((int64_t)c->p[5] << 24) |\n            ((int64_t)c->p[6] << 16) |\n            ((int64_t)c->p[7] << 8) |\n             (int64_t)c->p[8]);\n        mp_cur_consume(c,9);\n        break;\n    case 0xc0:  /* nil */\n        lua_pushnil(L);\n        mp_cur_consume(c,1);\n        break;\n    case 0xc3:  /* true */\n        lua_pushboolean(L,1);\n        mp_cur_consume(c,1);\n        break;\n    case 0xc2:  /* false */\n        lua_pushboolean(L,0);\n        mp_cur_consume(c,1);\n        break;\n    case 0xca:  /* float */\n        mp_cur_need(c,5);\n        assert(sizeof(float) == 4);\n        {\n            float f;\n            memcpy(&f,c->p+1,4);\n            memrevifle(&f,4);\n            lua_pushnumber(L,f);\n            mp_cur_consume(c,5);\n        }\n        break;\n    case 0xcb:  /* double */\n        mp_cur_need(c,9);\n        assert(sizeof(double) == 8);\n        {\n            double d;\n            memcpy(&d,c->p+1,8);\n            memrevifle(&d,8);\n            lua_pushnumber(L,d);\n            mp_cur_consume(c,9);\n        }\n        break;\n    case 0xd9:  /* raw 8 */\n        mp_cur_need(c,2);\n        {\n            size_t l = c->p[1];\n            mp_cur_need(c,2+l);\n            lua_pushlstring(L,(char*)c->p+2,l);\n            mp_cur_consume(c,2+l);\n        }\n        break;\n    case 0xda:  /* raw 16 */\n        mp_cur_need(c,3);\n        {\n            size_t l = (c->p[1] << 8) | c->p[2];\n            mp_cur_need(c,3+l);\n            lua_pushlstring(L,(char*)c->p+3,l);\n            mp_cur_consume(c,3+l);\n        }\n        break;\n    case 0xdb:  /* raw 32 */\n        mp_cur_need(c,5);\n        {\n            size_t l = ((size_t)c->p[1] << 24) |\n                       ((size_t)c->p[2] << 16) |\n                       ((size_t)c->p[3] << 8) |\n                       (size_t)c->p[4];\n            mp_cur_consume(c,5);\n            mp_cur_need(c,l);\n            lua_pushlstring(L,(char*)c->p,l);\n            mp_cur_consume(c,l);\n        }\n        break;\n    case 0xdc:  /* array 16 */\n        mp_cur_need(c,3);\n        {\n            size_t l = (c->p[1] << 8) | c->p[2];\n            mp_cur_consume(c,3);\n            mp_decode_to_lua_array(L,c,l);\n        }\n        break;\n    case 0xdd:  /* array 32 */\n        mp_cur_need(c,5);\n        {\n            size_t l = ((size_t)c->p[1] << 24) |\n                       ((size_t)c->p[2] << 16) |\n                       ((size_t)c->p[3] << 8) |\n                       (size_t)c->p[4];\n            mp_cur_consume(c,5);\n            mp_decode_to_lua_array(L,c,l);\n        }\n        break;\n    case 0xde:  /* map 16 */\n        mp_cur_need(c,3);\n        {\n            size_t l = (c->p[1] << 8) | c->p[2];\n            mp_cur_consume(c,3);\n            mp_decode_to_lua_hash(L,c,l);\n        }\n        break;\n    case 0xdf:  /* map 32 */\n        mp_cur_need(c,5);\n        {\n            size_t l = ((size_t)c->p[1] << 24) |\n                       ((size_t)c->p[2] << 16) |\n                       ((size_t)c->p[3] << 8) |\n                       (size_t)c->p[4];\n            mp_cur_consume(c,5);\n            mp_decode_to_lua_hash(L,c,l);\n        }\n        break;\n    default:    /* types that can't be idenitified by first byte value. */\n        if ((c->p[0] & 0x80) == 0) {   /* positive fixnum */\n            lua_pushunsigned(L,c->p[0]);\n            mp_cur_consume(c,1);\n        } else if ((c->p[0] & 0xe0) == 0xe0) {  /* negative fixnum */\n            lua_pushinteger(L,(signed char)c->p[0]);\n            mp_cur_consume(c,1);\n        } else if ((c->p[0] & 0xe0) == 0xa0) {  /* fix raw */\n            size_t l = c->p[0] & 0x1f;\n            mp_cur_need(c,1+l);\n            lua_pushlstring(L,(char*)c->p+1,l);\n            mp_cur_consume(c,1+l);\n        } else if ((c->p[0] & 0xf0) == 0x90) {  /* fix map */\n            size_t l = c->p[0] & 0xf;\n            mp_cur_consume(c,1);\n            mp_decode_to_lua_array(L,c,l);\n        } else if ((c->p[0] & 0xf0) == 0x80) {  /* fix map */\n            size_t l = c->p[0] & 0xf;\n            mp_cur_consume(c,1);\n            mp_decode_to_lua_hash(L,c,l);\n        } else {\n            c->err = MP_CUR_ERROR_BADFMT;\n        }\n    }\n}\n\nint mp_unpack_full(lua_State *L, int limit, int offset) {\n    size_t len;\n    const char *s;\n    mp_cur c;\n    int cnt; /* Number of objects unpacked */\n    int decode_all = (!limit && !offset);\n\n    s = luaL_checklstring(L,1,&len); /* if no match, exits */\n\n    if (offset < 0 || limit < 0) /* requesting negative off or lim is invalid */\n        return luaL_error(L,\n            \"Invalid request to unpack with offset of %d and limit of %d.\",\n            offset, len);\n    else if (offset > len)\n        return luaL_error(L,\n            \"Start offset %d greater than input length %d.\", offset, len);\n\n    if (decode_all) limit = INT_MAX;\n\n    mp_cur_init(&c,(const unsigned char *)s+offset,len-offset);\n\n    /* We loop over the decode because this could be a stream\n     * of multiple top-level values serialized together */\n    for(cnt = 0; c.left > 0 && cnt < limit; cnt++) {\n        mp_decode_to_lua_type(L,&c);\n\n        if (c.err == MP_CUR_ERROR_EOF) {\n            return luaL_error(L,\"Missing bytes in input.\");\n        } else if (c.err == MP_CUR_ERROR_BADFMT) {\n            return luaL_error(L,\"Bad data format in input.\");\n        }\n    }\n\n    if (!decode_all) {\n        /* c->left is the remaining size of the input buffer.\n         * subtract the entire buffer size from the unprocessed size\n         * to get our next start offset */\n        int offset = len - c.left;\n        /* Return offset -1 when we have have processed the entire buffer. */\n        lua_pushinteger(L, c.left == 0 ? -1 : offset);\n        /* Results are returned with the arg elements still\n         * in place. Lua takes care of only returning\n         * elements above the args for us.\n         * In this case, we have one arg on the stack\n         * for this function, so we insert our first return\n         * value at position 2. */\n        lua_insert(L, 2);\n        cnt += 1; /* increase return count by one to make room for offset */\n    }\n\n    return cnt;\n}\n\nint mp_unpack(lua_State *L) {\n    return mp_unpack_full(L, 0, 0);\n}\n\nint mp_unpack_one(lua_State *L) {\n    int offset = luaL_optinteger(L, 2, 0);\n    /* Variable pop because offset may not exist */\n    lua_pop(L, lua_gettop(L)-1);\n    return mp_unpack_full(L, 1, offset);\n}\n\nint mp_unpack_limit(lua_State *L) {\n    int limit = luaL_checkinteger(L, 2);\n    int offset = luaL_optinteger(L, 3, 0);\n    /* Variable pop because offset may not exist */\n    lua_pop(L, lua_gettop(L)-1);\n\n    return mp_unpack_full(L, limit, offset);\n}\n\nint mp_safe(lua_State *L) {\n    int argc, err, total_results;\n\n    argc = lua_gettop(L);\n\n    /* This adds our function to the bottom of the stack\n     * (the \"call this function\" position) */\n    lua_pushvalue(L, lua_upvalueindex(1));\n    lua_insert(L, 1);\n\n    err = lua_pcall(L, argc, LUA_MULTRET, 0);\n    total_results = lua_gettop(L);\n\n    if (!err) {\n        return total_results;\n    } else {\n        lua_pushnil(L);\n        lua_insert(L,-2);\n        return 2;\n    }\n}\n\n/* -------------------------------------------------------------------------- */\nconst struct luaL_Reg cmds[] = {\n    {\"pack\", mp_pack},\n    {\"unpack\", mp_unpack},\n    {\"unpack_one\", mp_unpack_one},\n    {\"unpack_limit\", mp_unpack_limit},\n    {0}\n};\n\nint luaopen_create(lua_State *L) {\n    int i;\n    /* Manually construct our module table instead of\n     * relying on _register or _newlib */\n    lua_newtable(L);\n\n    for (i = 0; i < (sizeof(cmds)/sizeof(*cmds) - 1); i++) {\n        lua_pushcfunction(L, cmds[i].func);\n        lua_setfield(L, -2, cmds[i].name);\n    }\n\n    /* Add metadata */\n    lua_pushliteral(L, LUACMSGPACK_NAME);\n    lua_setfield(L, -2, \"_NAME\");\n    lua_pushliteral(L, LUACMSGPACK_VERSION);\n    lua_setfield(L, -2, \"_VERSION\");\n    lua_pushliteral(L, LUACMSGPACK_COPYRIGHT);\n    lua_setfield(L, -2, \"_COPYRIGHT\");\n    lua_pushliteral(L, LUACMSGPACK_DESCRIPTION);\n    lua_setfield(L, -2, \"_DESCRIPTION\");\n    return 1;\n}\n\nLUALIB_API int luaopen_cmsgpack(lua_State *L) {\n    luaopen_create(L);\n\n#if LUA_VERSION_NUM < 502\n    /* Register name globally for 5.1 */\n    lua_pushvalue(L, -1);\n    lua_setglobal(L, LUACMSGPACK_NAME);\n#endif\n\n    return 1;\n}\n\nLUALIB_API int luaopen_cmsgpack_safe(lua_State *L) {\n    int i;\n\n    luaopen_cmsgpack(L);\n\n    /* Wrap all functions in the safe handler */\n    for (i = 0; i < (sizeof(cmds)/sizeof(*cmds) - 1); i++) {\n        lua_getfield(L, -1, cmds[i].name);\n        lua_pushcclosure(L, mp_safe, 1);\n        lua_setfield(L, -2, cmds[i].name);\n    }\n\n#if LUA_VERSION_NUM < 502\n    /* Register name globally for 5.1 */\n    lua_pushvalue(L, -1);\n    lua_setglobal(L, LUACMSGPACK_SAFE_NAME);\n#endif\n\n    return 1;\n}\n\n/******************************************************************************\n* Copyright (C) 2012 Salvatore Sanfilippo.  All rights reserved.\n*\n* Permission is hereby granted, free of charge, to any person obtaining\n* a copy of this software and associated documentation files (the\n* \"Software\"), to deal in the Software without restriction, including\n* without limitation the rights to use, copy, modify, merge, publish,\n* distribute, sublicense, and/or sell copies of the Software, and to\n* permit persons to whom the Software is furnished to do so, subject to\n* the following conditions:\n*\n* The above copyright notice and this permission notice shall be\n* included in all copies or substantial portions of the Software.\n*\n* THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND,\n* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\n* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.\n* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY\n* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,\n* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE\n* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n******************************************************************************/\n"
  },
  {
    "path": "extern/deprecated/redis-2.8.21/deps/lua/src/lua_struct.c",
    "content": "/*\n** {======================================================\n** Library for packing/unpacking structures.\n** $Id: struct.c,v 1.4 2012/07/04 18:54:29 roberto Exp $\n** See Copyright Notice at the end of this file\n** =======================================================\n*/\n/*\n** Valid formats:\n** > - big endian\n** < - little endian\n** ![num] - alignment\n** x - pading\n** b/B - signed/unsigned byte\n** h/H - signed/unsigned short\n** l/L - signed/unsigned long\n** T   - size_t\n** i/In - signed/unsigned integer with size `n' (default is size of int)\n** cn - sequence of `n' chars (from/to a string); when packing, n==0 means\n        the whole string; when unpacking, n==0 means use the previous\n        read number as the string length\n** s - zero-terminated string\n** f - float\n** d - double\n** ' ' - ignored\n*/\n\n\n#include <assert.h>\n#include <ctype.h>\n#include <limits.h>\n#include <stddef.h>\n#include <string.h>\n\n\n#include \"lua.h\"\n#include \"lauxlib.h\"\n\n\n#if (LUA_VERSION_NUM >= 502)\n\n#define luaL_register(L,n,f)\tluaL_newlib(L,f)\n\n#endif\n\n\n/* basic integer type */\n#if !defined(STRUCT_INT)\n#define STRUCT_INT\tlong\n#endif\n\ntypedef STRUCT_INT Inttype;\n\n/* corresponding unsigned version */\ntypedef unsigned STRUCT_INT Uinttype;\n\n\n/* maximum size (in bytes) for integral types */\n#define MAXINTSIZE\t32\n\n/* is 'x' a power of 2? */\n#define isp2(x)\t\t((x) > 0 && ((x) & ((x) - 1)) == 0)\n\n/* dummy structure to get alignment requirements */\nstruct cD {\n  char c;\n  double d;\n};\n\n\n#define PADDING\t\t(sizeof(struct cD) - sizeof(double))\n#define MAXALIGN  \t(PADDING > sizeof(int) ? PADDING : sizeof(int))\n\n\n/* endian options */\n#define BIG\t0\n#define LITTLE\t1\n\n\nstatic union {\n  int dummy;\n  char endian;\n} const native = {1};\n\n\ntypedef struct Header {\n  int endian;\n  int align;\n} Header;\n\n\nstatic int getnum (const char **fmt, int df) {\n  if (!isdigit(**fmt))  /* no number? */\n    return df;  /* return default value */\n  else {\n    int a = 0;\n    do {\n      a = a*10 + *((*fmt)++) - '0';\n    } while (isdigit(**fmt));\n    return a;\n  }\n}\n\n\n#define defaultoptions(h)\t((h)->endian = native.endian, (h)->align = 1)\n\n\n\nstatic size_t optsize (lua_State *L, char opt, const char **fmt) {\n  switch (opt) {\n    case 'B': case 'b': return sizeof(char);\n    case 'H': case 'h': return sizeof(short);\n    case 'L': case 'l': return sizeof(long);\n    case 'T': return sizeof(size_t);\n    case 'f':  return sizeof(float);\n    case 'd':  return sizeof(double);\n    case 'x': return 1;\n    case 'c': return getnum(fmt, 1);\n    case 'i': case 'I': {\n      int sz = getnum(fmt, sizeof(int));\n      if (sz > MAXINTSIZE)\n        luaL_error(L, \"integral size %d is larger than limit of %d\",\n                       sz, MAXINTSIZE);\n      return sz;\n    }\n    default: return 0;  /* other cases do not need alignment */\n  }\n}\n\n\n/*\n** return number of bytes needed to align an element of size 'size'\n** at current position 'len'\n*/\nstatic int gettoalign (size_t len, Header *h, int opt, size_t size) {\n  if (size == 0 || opt == 'c') return 0;\n  if (size > (size_t)h->align)\n    size = h->align;  /* respect max. alignment */\n  return (size - (len & (size - 1))) & (size - 1);\n}\n\n\n/*\n** options to control endianess and alignment\n*/\nstatic void controloptions (lua_State *L, int opt, const char **fmt,\n                            Header *h) {\n  switch (opt) {\n    case  ' ': return;  /* ignore white spaces */\n    case '>': h->endian = BIG; return;\n    case '<': h->endian = LITTLE; return;\n    case '!': {\n      int a = getnum(fmt, MAXALIGN);\n      if (!isp2(a))\n        luaL_error(L, \"alignment %d is not a power of 2\", a);\n      h->align = a;\n      return;\n    }\n    default: {\n      const char *msg = lua_pushfstring(L, \"invalid format option '%c'\", opt);\n      luaL_argerror(L, 1, msg);\n    }\n  }\n}\n\n\nstatic void putinteger (lua_State *L, luaL_Buffer *b, int arg, int endian,\n                        int size) {\n  lua_Number n = luaL_checknumber(L, arg);\n  Uinttype value;\n  char buff[MAXINTSIZE];\n  if (n < 0)\n    value = (Uinttype)(Inttype)n;\n  else\n    value = (Uinttype)n;\n  if (endian == LITTLE) {\n    int i;\n    for (i = 0; i < size; i++) {\n      buff[i] = (value & 0xff);\n      value >>= 8;\n    }\n  }\n  else {\n    int i;\n    for (i = size - 1; i >= 0; i--) {\n      buff[i] = (value & 0xff);\n      value >>= 8;\n    }\n  }\n  luaL_addlstring(b, buff, size);\n}\n\n\nstatic void correctbytes (char *b, int size, int endian) {\n  if (endian != native.endian) {\n    int i = 0;\n    while (i < --size) {\n      char temp = b[i];\n      b[i++] = b[size];\n      b[size] = temp;\n    }\n  }\n}\n\n\nstatic int b_pack (lua_State *L) {\n  luaL_Buffer b;\n  const char *fmt = luaL_checkstring(L, 1);\n  Header h;\n  int arg = 2;\n  size_t totalsize = 0;\n  defaultoptions(&h);\n  lua_pushnil(L);  /* mark to separate arguments from string buffer */\n  luaL_buffinit(L, &b);\n  while (*fmt != '\\0') {\n    int opt = *fmt++;\n    size_t size = optsize(L, opt, &fmt);\n    int toalign = gettoalign(totalsize, &h, opt, size);\n    totalsize += toalign;\n    while (toalign-- > 0) luaL_addchar(&b, '\\0');\n    switch (opt) {\n      case 'b': case 'B': case 'h': case 'H':\n      case 'l': case 'L': case 'T': case 'i': case 'I': {  /* integer types */\n        putinteger(L, &b, arg++, h.endian, size);\n        break;\n      }\n      case 'x': {\n        luaL_addchar(&b, '\\0');\n        break;\n      }\n      case 'f': {\n        float f = (float)luaL_checknumber(L, arg++);\n        correctbytes((char *)&f, size, h.endian);\n        luaL_addlstring(&b, (char *)&f, size);\n        break;\n      }\n      case 'd': {\n        double d = luaL_checknumber(L, arg++);\n        correctbytes((char *)&d, size, h.endian);\n        luaL_addlstring(&b, (char *)&d, size);\n        break;\n      }\n      case 'c': case 's': {\n        size_t l;\n        const char *s = luaL_checklstring(L, arg++, &l);\n        if (size == 0) size = l;\n        luaL_argcheck(L, l >= (size_t)size, arg, \"string too short\");\n        luaL_addlstring(&b, s, size);\n        if (opt == 's') {\n          luaL_addchar(&b, '\\0');  /* add zero at the end */\n          size++;\n        }\n        break;\n      }\n      default: controloptions(L, opt, &fmt, &h);\n    }\n    totalsize += size;\n  }\n  luaL_pushresult(&b);\n  return 1;\n}\n\n\nstatic lua_Number getinteger (const char *buff, int endian,\n                        int issigned, int size) {\n  Uinttype l = 0;\n  int i;\n  if (endian == BIG) {\n    for (i = 0; i < size; i++) {\n      l <<= 8;\n      l |= (Uinttype)(unsigned char)buff[i];\n    }\n  }\n  else {\n    for (i = size - 1; i >= 0; i--) {\n      l <<= 8;\n      l |= (Uinttype)(unsigned char)buff[i];\n    }\n  }\n  if (!issigned)\n    return (lua_Number)l;\n  else {  /* signed format */\n    Uinttype mask = (Uinttype)(~((Uinttype)0)) << (size*8 - 1);\n    if (l & mask)  /* negative value? */\n      l |= mask;  /* signal extension */\n    return (lua_Number)(Inttype)l;\n  }\n}\n\n\nstatic int b_unpack (lua_State *L) {\n  Header h;\n  const char *fmt = luaL_checkstring(L, 1);\n  size_t ld;\n  const char *data = luaL_checklstring(L, 2, &ld);\n  size_t pos = luaL_optinteger(L, 3, 1) - 1;\n  defaultoptions(&h);\n  lua_settop(L, 2);\n  while (*fmt) {\n    int opt = *fmt++;\n    size_t size = optsize(L, opt, &fmt);\n    pos += gettoalign(pos, &h, opt, size);\n    luaL_argcheck(L, pos+size <= ld, 2, \"data string too short\");\n    luaL_checkstack(L, 1, \"too many results\");\n    switch (opt) {\n      case 'b': case 'B': case 'h': case 'H':\n      case 'l': case 'L': case 'T': case 'i':  case 'I': {  /* integer types */\n        int issigned = islower(opt);\n        lua_Number res = getinteger(data+pos, h.endian, issigned, size);\n        lua_pushnumber(L, res);\n        break;\n      }\n      case 'x': {\n        break;\n      }\n      case 'f': {\n        float f;\n        memcpy(&f, data+pos, size);\n        correctbytes((char *)&f, sizeof(f), h.endian);\n        lua_pushnumber(L, f);\n        break;\n      }\n      case 'd': {\n        double d;\n        memcpy(&d, data+pos, size);\n        correctbytes((char *)&d, sizeof(d), h.endian);\n        lua_pushnumber(L, d);\n        break;\n      }\n      case 'c': {\n        if (size == 0) {\n          if (!lua_isnumber(L, -1))\n            luaL_error(L, \"format `c0' needs a previous size\");\n          size = lua_tonumber(L, -1);\n          lua_pop(L, 1);\n          luaL_argcheck(L, pos+size <= ld, 2, \"data string too short\");\n        }\n        lua_pushlstring(L, data+pos, size);\n        break;\n      }\n      case 's': {\n        const char *e = (const char *)memchr(data+pos, '\\0', ld - pos);\n        if (e == NULL)\n          luaL_error(L, \"unfinished string in data\");\n        size = (e - (data+pos)) + 1;\n        lua_pushlstring(L, data+pos, size - 1);\n        break;\n      }\n      default: controloptions(L, opt, &fmt, &h);\n    }\n    pos += size;\n  }\n  lua_pushinteger(L, pos + 1);\n  return lua_gettop(L) - 2;\n}\n\n\nstatic int b_size (lua_State *L) {\n  Header h;\n  const char *fmt = luaL_checkstring(L, 1);\n  size_t pos = 0;\n  defaultoptions(&h);\n  while (*fmt) {\n    int opt = *fmt++;\n    size_t size = optsize(L, opt, &fmt);\n    pos += gettoalign(pos, &h, opt, size);\n    if (opt == 's')\n      luaL_argerror(L, 1, \"option 's' has no fixed size\");\n    else if (opt == 'c' && size == 0)\n      luaL_argerror(L, 1, \"option 'c0' has no fixed size\");\n    if (!isalnum(opt))\n      controloptions(L, opt, &fmt, &h);\n    pos += size;\n  }\n  lua_pushinteger(L, pos);\n  return 1;\n}\n\n/* }====================================================== */\n\n\n\nstatic const struct luaL_Reg thislib[] = {\n  {\"pack\", b_pack},\n  {\"unpack\", b_unpack},\n  {\"size\", b_size},\n  {NULL, NULL}\n};\n\n\nLUALIB_API int luaopen_struct (lua_State *L);\n\nLUALIB_API int luaopen_struct (lua_State *L) {\n  luaL_register(L, \"struct\", thislib);\n  return 1;\n}\n\n\n/******************************************************************************\n* Copyright (C) 2010-2012 Lua.org, PUC-Rio.  All rights reserved.\n*\n* Permission is hereby granted, free of charge, to any person obtaining\n* a copy of this software and associated documentation files (the\n* \"Software\"), to deal in the Software without restriction, including\n* without limitation the rights to use, copy, modify, merge, publish,\n* distribute, sublicense, and/or sell copies of the Software, and to\n* permit persons to whom the Software is furnished to do so, subject to\n* the following conditions:\n*\n* The above copyright notice and this permission notice shall be\n* included in all copies or substantial portions of the Software.\n*\n* THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND,\n* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\n* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.\n* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY\n* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,\n* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE\n* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n******************************************************************************/\n\n"
  },
  {
    "path": "extern/deprecated/redis-2.8.21/deps/lua/src/luac.c",
    "content": "/*\n** $Id: luac.c,v 1.54 2006/06/02 17:37:11 lhf Exp $\n** Lua compiler (saves bytecodes to files; also list bytecodes)\n** See Copyright Notice in lua.h\n*/\n\n#include <errno.h>\n#include <stdio.h>\n#include <stdlib.h>\n#include <string.h>\n\n#define luac_c\n#define LUA_CORE\n\n#include \"lua.h\"\n#include \"lauxlib.h\"\n\n#include \"ldo.h\"\n#include \"lfunc.h\"\n#include \"lmem.h\"\n#include \"lobject.h\"\n#include \"lopcodes.h\"\n#include \"lstring.h\"\n#include \"lundump.h\"\n\n#define PROGNAME\t\"luac\"\t\t/* default program name */\n#define\tOUTPUT\t\tPROGNAME \".out\"\t/* default output file */\n\nstatic int listing=0;\t\t\t/* list bytecodes? */\nstatic int dumping=1;\t\t\t/* dump bytecodes? */\nstatic int stripping=0;\t\t\t/* strip debug information? */\nstatic char Output[]={ OUTPUT };\t/* default output file name */\nstatic const char* output=Output;\t/* actual output file name */\nstatic const char* progname=PROGNAME;\t/* actual program name */\n\nstatic void fatal(const char* message)\n{\n fprintf(stderr,\"%s: %s\\n\",progname,message);\n exit(EXIT_FAILURE);\n}\n\nstatic void cannot(const char* what)\n{\n fprintf(stderr,\"%s: cannot %s %s: %s\\n\",progname,what,output,strerror(errno));\n exit(EXIT_FAILURE);\n}\n\nstatic void usage(const char* message)\n{\n if (*message=='-')\n  fprintf(stderr,\"%s: unrecognized option \" LUA_QS \"\\n\",progname,message);\n else\n  fprintf(stderr,\"%s: %s\\n\",progname,message);\n fprintf(stderr,\n \"usage: %s [options] [filenames].\\n\"\n \"Available options are:\\n\"\n \"  -        process stdin\\n\"\n \"  -l       list\\n\"\n \"  -o name  output to file \" LUA_QL(\"name\") \" (default is \\\"%s\\\")\\n\"\n \"  -p       parse only\\n\"\n \"  -s       strip debug information\\n\"\n \"  -v       show version information\\n\"\n \"  --       stop handling options\\n\",\n progname,Output);\n exit(EXIT_FAILURE);\n}\n\n#define\tIS(s)\t(strcmp(argv[i],s)==0)\n\nstatic int doargs(int argc, char* argv[])\n{\n int i;\n int version=0;\n if (argv[0]!=NULL && *argv[0]!=0) progname=argv[0];\n for (i=1; i<argc; i++)\n {\n  if (*argv[i]!='-')\t\t\t/* end of options; keep it */\n   break;\n  else if (IS(\"--\"))\t\t\t/* end of options; skip it */\n  {\n   ++i;\n   if (version) ++version;\n   break;\n  }\n  else if (IS(\"-\"))\t\t\t/* end of options; use stdin */\n   break;\n  else if (IS(\"-l\"))\t\t\t/* list */\n   ++listing;\n  else if (IS(\"-o\"))\t\t\t/* output file */\n  {\n   output=argv[++i];\n   if (output==NULL || *output==0) usage(LUA_QL(\"-o\") \" needs argument\");\n   if (IS(\"-\")) output=NULL;\n  }\n  else if (IS(\"-p\"))\t\t\t/* parse only */\n   dumping=0;\n  else if (IS(\"-s\"))\t\t\t/* strip debug information */\n   stripping=1;\n  else if (IS(\"-v\"))\t\t\t/* show version */\n   ++version;\n  else\t\t\t\t\t/* unknown option */\n   usage(argv[i]);\n }\n if (i==argc && (listing || !dumping))\n {\n  dumping=0;\n  argv[--i]=Output;\n }\n if (version)\n {\n  printf(\"%s  %s\\n\",LUA_RELEASE,LUA_COPYRIGHT);\n  if (version==argc-1) exit(EXIT_SUCCESS);\n }\n return i;\n}\n\n#define toproto(L,i) (clvalue(L->top+(i))->l.p)\n\nstatic const Proto* combine(lua_State* L, int n)\n{\n if (n==1)\n  return toproto(L,-1);\n else\n {\n  int i,pc;\n  Proto* f=luaF_newproto(L);\n  setptvalue2s(L,L->top,f); incr_top(L);\n  f->source=luaS_newliteral(L,\"=(\" PROGNAME \")\");\n  f->maxstacksize=1;\n  pc=2*n+1;\n  f->code=luaM_newvector(L,pc,Instruction);\n  f->sizecode=pc;\n  f->p=luaM_newvector(L,n,Proto*);\n  f->sizep=n;\n  pc=0;\n  for (i=0; i<n; i++)\n  {\n   f->p[i]=toproto(L,i-n-1);\n   f->code[pc++]=CREATE_ABx(OP_CLOSURE,0,i);\n   f->code[pc++]=CREATE_ABC(OP_CALL,0,1,1);\n  }\n  f->code[pc++]=CREATE_ABC(OP_RETURN,0,1,0);\n  return f;\n }\n}\n\nstatic int writer(lua_State* L, const void* p, size_t size, void* u)\n{\n UNUSED(L);\n return (fwrite(p,size,1,(FILE*)u)!=1) && (size!=0);\n}\n\nstruct Smain {\n int argc;\n char** argv;\n};\n\nstatic int pmain(lua_State* L)\n{\n struct Smain* s = (struct Smain*)lua_touserdata(L, 1);\n int argc=s->argc;\n char** argv=s->argv;\n const Proto* f;\n int i;\n if (!lua_checkstack(L,argc)) fatal(\"too many input files\");\n for (i=0; i<argc; i++)\n {\n  const char* filename=IS(\"-\") ? NULL : argv[i];\n  if (luaL_loadfile(L,filename)!=0) fatal(lua_tostring(L,-1));\n }\n f=combine(L,argc);\n if (listing) luaU_print(f,listing>1);\n if (dumping)\n {\n  FILE* D= (output==NULL) ? stdout : fopen(output,\"wb\");\n  if (D==NULL) cannot(\"open\");\n  lua_lock(L);\n  luaU_dump(L,f,writer,D,stripping);\n  lua_unlock(L);\n  if (ferror(D)) cannot(\"write\");\n  if (fclose(D)) cannot(\"close\");\n }\n return 0;\n}\n\nint main(int argc, char* argv[])\n{\n lua_State* L;\n struct Smain s;\n int i=doargs(argc,argv);\n argc-=i; argv+=i;\n if (argc<=0) usage(\"no input files given\");\n L=lua_open();\n if (L==NULL) fatal(\"not enough memory for state\");\n s.argc=argc;\n s.argv=argv;\n if (lua_cpcall(L,pmain,&s)!=0) fatal(lua_tostring(L,-1));\n lua_close(L);\n return EXIT_SUCCESS;\n}\n"
  },
  {
    "path": "extern/deprecated/redis-2.8.21/deps/lua/src/luaconf.h",
    "content": "/*\n** $Id: luaconf.h,v 1.82.1.7 2008/02/11 16:25:08 roberto Exp $\n** Configuration file for Lua\n** See Copyright Notice in lua.h\n*/\n\n\n#ifndef lconfig_h\n#define lconfig_h\n\n#include <limits.h>\n#include <stddef.h>\n\n\n/*\n** ==================================================================\n** Search for \"@@\" to find all configurable definitions.\n** ===================================================================\n*/\n\n\n/*\n@@ LUA_ANSI controls the use of non-ansi features.\n** CHANGE it (define it) if you want Lua to avoid the use of any\n** non-ansi feature or library.\n*/\n#if defined(__STRICT_ANSI__)\n#define LUA_ANSI\n#endif\n\n\n#if !defined(LUA_ANSI) && defined(_WIN32)\n#define LUA_WIN\n#endif\n\n#if defined(LUA_USE_LINUX)\n#define LUA_USE_POSIX\n#define LUA_USE_DLOPEN\t\t/* needs an extra library: -ldl */\n#define LUA_USE_READLINE\t/* needs some extra libraries */\n#endif\n\n#if defined(LUA_USE_MACOSX)\n#define LUA_USE_POSIX\n#define LUA_DL_DYLD\t\t/* does not need extra library */\n#endif\n\n\n\n/*\n@@ LUA_USE_POSIX includes all functionallity listed as X/Open System\n@* Interfaces Extension (XSI).\n** CHANGE it (define it) if your system is XSI compatible.\n*/\n#if defined(LUA_USE_POSIX)\n#define LUA_USE_MKSTEMP\n#define LUA_USE_ISATTY\n#define LUA_USE_POPEN\n#define LUA_USE_ULONGJMP\n#endif\n\n\n/*\n@@ LUA_PATH and LUA_CPATH are the names of the environment variables that\n@* Lua check to set its paths.\n@@ LUA_INIT is the name of the environment variable that Lua\n@* checks for initialization code.\n** CHANGE them if you want different names.\n*/\n#define LUA_PATH        \"LUA_PATH\"\n#define LUA_CPATH       \"LUA_CPATH\"\n#define LUA_INIT\t\"LUA_INIT\"\n\n\n/*\n@@ LUA_PATH_DEFAULT is the default path that Lua uses to look for\n@* Lua libraries.\n@@ LUA_CPATH_DEFAULT is the default path that Lua uses to look for\n@* C libraries.\n** CHANGE them if your machine has a non-conventional directory\n** hierarchy or if you want to install your libraries in\n** non-conventional directories.\n*/\n#if defined(_WIN32)\n/*\n** In Windows, any exclamation mark ('!') in the path is replaced by the\n** path of the directory of the executable file of the current process.\n*/\n#define LUA_LDIR\t\"!\\\\lua\\\\\"\n#define LUA_CDIR\t\"!\\\\\"\n#define LUA_PATH_DEFAULT  \\\n\t\t\".\\\\?.lua;\"  LUA_LDIR\"?.lua;\"  LUA_LDIR\"?\\\\init.lua;\" \\\n\t\t             LUA_CDIR\"?.lua;\"  LUA_CDIR\"?\\\\init.lua\"\n#define LUA_CPATH_DEFAULT \\\n\t\".\\\\?.dll;\"  LUA_CDIR\"?.dll;\" LUA_CDIR\"loadall.dll\"\n\n#else\n#define LUA_ROOT\t\"/usr/local/\"\n#define LUA_LDIR\tLUA_ROOT \"share/lua/5.1/\"\n#define LUA_CDIR\tLUA_ROOT \"lib/lua/5.1/\"\n#define LUA_PATH_DEFAULT  \\\n\t\t\"./?.lua;\"  LUA_LDIR\"?.lua;\"  LUA_LDIR\"?/init.lua;\" \\\n\t\t            LUA_CDIR\"?.lua;\"  LUA_CDIR\"?/init.lua\"\n#define LUA_CPATH_DEFAULT \\\n\t\"./?.so;\"  LUA_CDIR\"?.so;\" LUA_CDIR\"loadall.so\"\n#endif\n\n\n/*\n@@ LUA_DIRSEP is the directory separator (for submodules).\n** CHANGE it if your machine does not use \"/\" as the directory separator\n** and is not Windows. (On Windows Lua automatically uses \"\\\".)\n*/\n#if defined(_WIN32)\n#define LUA_DIRSEP\t\"\\\\\"\n#else\n#define LUA_DIRSEP\t\"/\"\n#endif\n\n\n/*\n@@ LUA_PATHSEP is the character that separates templates in a path.\n@@ LUA_PATH_MARK is the string that marks the substitution points in a\n@* template.\n@@ LUA_EXECDIR in a Windows path is replaced by the executable's\n@* directory.\n@@ LUA_IGMARK is a mark to ignore all before it when bulding the\n@* luaopen_ function name.\n** CHANGE them if for some reason your system cannot use those\n** characters. (E.g., if one of those characters is a common character\n** in file/directory names.) Probably you do not need to change them.\n*/\n#define LUA_PATHSEP\t\";\"\n#define LUA_PATH_MARK\t\"?\"\n#define LUA_EXECDIR\t\"!\"\n#define LUA_IGMARK\t\"-\"\n\n\n/*\n@@ LUA_INTEGER is the integral type used by lua_pushinteger/lua_tointeger.\n** CHANGE that if ptrdiff_t is not adequate on your machine. (On most\n** machines, ptrdiff_t gives a good choice between int or long.)\n*/\n#define LUA_INTEGER\tptrdiff_t\n\n\n/*\n@@ LUA_API is a mark for all core API functions.\n@@ LUALIB_API is a mark for all standard library functions.\n** CHANGE them if you need to define those functions in some special way.\n** For instance, if you want to create one Windows DLL with the core and\n** the libraries, you may want to use the following definition (define\n** LUA_BUILD_AS_DLL to get it).\n*/\n#if defined(LUA_BUILD_AS_DLL)\n\n#if defined(LUA_CORE) || defined(LUA_LIB)\n#define LUA_API __declspec(dllexport)\n#else\n#define LUA_API __declspec(dllimport)\n#endif\n\n#else\n\n#define LUA_API\t\textern\n\n#endif\n\n/* more often than not the libs go together with the core */\n#define LUALIB_API\tLUA_API\n\n\n/*\n@@ LUAI_FUNC is a mark for all extern functions that are not to be\n@* exported to outside modules.\n@@ LUAI_DATA is a mark for all extern (const) variables that are not to\n@* be exported to outside modules.\n** CHANGE them if you need to mark them in some special way. Elf/gcc\n** (versions 3.2 and later) mark them as \"hidden\" to optimize access\n** when Lua is compiled as a shared library.\n*/\n#if defined(luaall_c)\n#define LUAI_FUNC\tstatic\n#define LUAI_DATA\t/* empty */\n\n#elif defined(__GNUC__) && ((__GNUC__*100 + __GNUC_MINOR__) >= 302) && \\\n      defined(__ELF__)\n#define LUAI_FUNC\t__attribute__((visibility(\"hidden\"))) extern\n#define LUAI_DATA\tLUAI_FUNC\n\n#else\n#define LUAI_FUNC\textern\n#define LUAI_DATA\textern\n#endif\n\n\n\n/*\n@@ LUA_QL describes how error messages quote program elements.\n** CHANGE it if you want a different appearance.\n*/\n#define LUA_QL(x)\t\"'\" x \"'\"\n#define LUA_QS\t\tLUA_QL(\"%s\")\n\n\n/*\n@@ LUA_IDSIZE gives the maximum size for the description of the source\n@* of a function in debug information.\n** CHANGE it if you want a different size.\n*/\n#define LUA_IDSIZE\t60\n\n\n/*\n** {==================================================================\n** Stand-alone configuration\n** ===================================================================\n*/\n\n#if defined(lua_c) || defined(luaall_c)\n\n/*\n@@ lua_stdin_is_tty detects whether the standard input is a 'tty' (that\n@* is, whether we're running lua interactively).\n** CHANGE it if you have a better definition for non-POSIX/non-Windows\n** systems.\n*/\n#if defined(LUA_USE_ISATTY)\n#include <unistd.h>\n#define lua_stdin_is_tty()\tisatty(0)\n#elif defined(LUA_WIN)\n#include <io.h>\n#include <stdio.h>\n#define lua_stdin_is_tty()\t_isatty(_fileno(stdin))\n#else\n#define lua_stdin_is_tty()\t1  /* assume stdin is a tty */\n#endif\n\n\n/*\n@@ LUA_PROMPT is the default prompt used by stand-alone Lua.\n@@ LUA_PROMPT2 is the default continuation prompt used by stand-alone Lua.\n** CHANGE them if you want different prompts. (You can also change the\n** prompts dynamically, assigning to globals _PROMPT/_PROMPT2.)\n*/\n#define LUA_PROMPT\t\t\"> \"\n#define LUA_PROMPT2\t\t\">> \"\n\n\n/*\n@@ LUA_PROGNAME is the default name for the stand-alone Lua program.\n** CHANGE it if your stand-alone interpreter has a different name and\n** your system is not able to detect that name automatically.\n*/\n#define LUA_PROGNAME\t\t\"lua\"\n\n\n/*\n@@ LUA_MAXINPUT is the maximum length for an input line in the\n@* stand-alone interpreter.\n** CHANGE it if you need longer lines.\n*/\n#define LUA_MAXINPUT\t512\n\n\n/*\n@@ lua_readline defines how to show a prompt and then read a line from\n@* the standard input.\n@@ lua_saveline defines how to \"save\" a read line in a \"history\".\n@@ lua_freeline defines how to free a line read by lua_readline.\n** CHANGE them if you want to improve this functionality (e.g., by using\n** GNU readline and history facilities).\n*/\n#if defined(LUA_USE_READLINE)\n#include <stdio.h>\n#include <readline/readline.h>\n#include <readline/history.h>\n#define lua_readline(L,b,p)\t((void)L, ((b)=readline(p)) != NULL)\n#define lua_saveline(L,idx) \\\n\tif (lua_strlen(L,idx) > 0)  /* non-empty line? */ \\\n\t  add_history(lua_tostring(L, idx));  /* add it to history */\n#define lua_freeline(L,b)\t((void)L, free(b))\n#else\n#define lua_readline(L,b,p)\t\\\n\t((void)L, fputs(p, stdout), fflush(stdout),  /* show prompt */ \\\n\tfgets(b, LUA_MAXINPUT, stdin) != NULL)  /* get line */\n#define lua_saveline(L,idx)\t{ (void)L; (void)idx; }\n#define lua_freeline(L,b)\t{ (void)L; (void)b; }\n#endif\n\n#endif\n\n/* }================================================================== */\n\n\n/*\n@@ LUAI_GCPAUSE defines the default pause between garbage-collector cycles\n@* as a percentage.\n** CHANGE it if you want the GC to run faster or slower (higher values\n** mean larger pauses which mean slower collection.) You can also change\n** this value dynamically.\n*/\n#define LUAI_GCPAUSE\t200  /* 200% (wait memory to double before next GC) */\n\n\n/*\n@@ LUAI_GCMUL defines the default speed of garbage collection relative to\n@* memory allocation as a percentage.\n** CHANGE it if you want to change the granularity of the garbage\n** collection. (Higher values mean coarser collections. 0 represents\n** infinity, where each step performs a full collection.) You can also\n** change this value dynamically.\n*/\n#define LUAI_GCMUL\t200 /* GC runs 'twice the speed' of memory allocation */\n\n\n\n/*\n@@ LUA_COMPAT_GETN controls compatibility with old getn behavior.\n** CHANGE it (define it) if you want exact compatibility with the\n** behavior of setn/getn in Lua 5.0.\n*/\n#undef LUA_COMPAT_GETN\n\n/*\n@@ LUA_COMPAT_LOADLIB controls compatibility about global loadlib.\n** CHANGE it to undefined as soon as you do not need a global 'loadlib'\n** function (the function is still available as 'package.loadlib').\n*/\n#undef LUA_COMPAT_LOADLIB\n\n/*\n@@ LUA_COMPAT_VARARG controls compatibility with old vararg feature.\n** CHANGE it to undefined as soon as your programs use only '...' to\n** access vararg parameters (instead of the old 'arg' table).\n*/\n#define LUA_COMPAT_VARARG\n\n/*\n@@ LUA_COMPAT_MOD controls compatibility with old math.mod function.\n** CHANGE it to undefined as soon as your programs use 'math.fmod' or\n** the new '%' operator instead of 'math.mod'.\n*/\n#define LUA_COMPAT_MOD\n\n/*\n@@ LUA_COMPAT_LSTR controls compatibility with old long string nesting\n@* facility.\n** CHANGE it to 2 if you want the old behaviour, or undefine it to turn\n** off the advisory error when nesting [[...]].\n*/\n#define LUA_COMPAT_LSTR\t\t1\n\n/*\n@@ LUA_COMPAT_GFIND controls compatibility with old 'string.gfind' name.\n** CHANGE it to undefined as soon as you rename 'string.gfind' to\n** 'string.gmatch'.\n*/\n#define LUA_COMPAT_GFIND\n\n/*\n@@ LUA_COMPAT_OPENLIB controls compatibility with old 'luaL_openlib'\n@* behavior.\n** CHANGE it to undefined as soon as you replace to 'luaL_register'\n** your uses of 'luaL_openlib'\n*/\n#define LUA_COMPAT_OPENLIB\n\n\n\n/*\n@@ luai_apicheck is the assert macro used by the Lua-C API.\n** CHANGE luai_apicheck if you want Lua to perform some checks in the\n** parameters it gets from API calls. This may slow down the interpreter\n** a bit, but may be quite useful when debugging C code that interfaces\n** with Lua. A useful redefinition is to use assert.h.\n*/\n#if defined(LUA_USE_APICHECK)\n#include <assert.h>\n#define luai_apicheck(L,o)\t{ (void)L; assert(o); }\n#else\n#define luai_apicheck(L,o)\t{ (void)L; }\n#endif\n\n\n/*\n@@ LUAI_BITSINT defines the number of bits in an int.\n** CHANGE here if Lua cannot automatically detect the number of bits of\n** your machine. Probably you do not need to change this.\n*/\n/* avoid overflows in comparison */\n#if INT_MAX-20 < 32760\n#define LUAI_BITSINT\t16\n#elif INT_MAX > 2147483640L\n/* int has at least 32 bits */\n#define LUAI_BITSINT\t32\n#else\n#error \"you must define LUA_BITSINT with number of bits in an integer\"\n#endif\n\n\n/*\n@@ LUAI_UINT32 is an unsigned integer with at least 32 bits.\n@@ LUAI_INT32 is an signed integer with at least 32 bits.\n@@ LUAI_UMEM is an unsigned integer big enough to count the total\n@* memory used by Lua.\n@@ LUAI_MEM is a signed integer big enough to count the total memory\n@* used by Lua.\n** CHANGE here if for some weird reason the default definitions are not\n** good enough for your machine. (The definitions in the 'else'\n** part always works, but may waste space on machines with 64-bit\n** longs.) Probably you do not need to change this.\n*/\n#if LUAI_BITSINT >= 32\n#define LUAI_UINT32\tunsigned int\n#define LUAI_INT32\tint\n#define LUAI_MAXINT32\tINT_MAX\n#define LUAI_UMEM\tsize_t\n#define LUAI_MEM\tptrdiff_t\n#else\n/* 16-bit ints */\n#define LUAI_UINT32\tunsigned long\n#define LUAI_INT32\tlong\n#define LUAI_MAXINT32\tLONG_MAX\n#define LUAI_UMEM\tunsigned long\n#define LUAI_MEM\tlong\n#endif\n\n\n/*\n@@ LUAI_MAXCALLS limits the number of nested calls.\n** CHANGE it if you need really deep recursive calls. This limit is\n** arbitrary; its only purpose is to stop infinite recursion before\n** exhausting memory.\n*/\n#define LUAI_MAXCALLS\t20000\n\n\n/*\n@@ LUAI_MAXCSTACK limits the number of Lua stack slots that a C function\n@* can use.\n** CHANGE it if you need lots of (Lua) stack space for your C\n** functions. This limit is arbitrary; its only purpose is to stop C\n** functions to consume unlimited stack space. (must be smaller than\n** -LUA_REGISTRYINDEX)\n*/\n#define LUAI_MAXCSTACK\t8000\n\n\n\n/*\n** {==================================================================\n** CHANGE (to smaller values) the following definitions if your system\n** has a small C stack. (Or you may want to change them to larger\n** values if your system has a large C stack and these limits are\n** too rigid for you.) Some of these constants control the size of\n** stack-allocated arrays used by the compiler or the interpreter, while\n** others limit the maximum number of recursive calls that the compiler\n** or the interpreter can perform. Values too large may cause a C stack\n** overflow for some forms of deep constructs.\n** ===================================================================\n*/\n\n\n/*\n@@ LUAI_MAXCCALLS is the maximum depth for nested C calls (short) and\n@* syntactical nested non-terminals in a program.\n*/\n#define LUAI_MAXCCALLS\t\t200\n\n\n/*\n@@ LUAI_MAXVARS is the maximum number of local variables per function\n@* (must be smaller than 250).\n*/\n#define LUAI_MAXVARS\t\t200\n\n\n/*\n@@ LUAI_MAXUPVALUES is the maximum number of upvalues per function\n@* (must be smaller than 250).\n*/\n#define LUAI_MAXUPVALUES\t60\n\n\n/*\n@@ LUAL_BUFFERSIZE is the buffer size used by the lauxlib buffer system.\n*/\n#define LUAL_BUFFERSIZE\t\tBUFSIZ\n\n/* }================================================================== */\n\n\n\n\n/*\n** {==================================================================\n@@ LUA_NUMBER is the type of numbers in Lua.\n** CHANGE the following definitions only if you want to build Lua\n** with a number type different from double. You may also need to\n** change lua_number2int & lua_number2integer.\n** ===================================================================\n*/\n\n#define LUA_NUMBER_DOUBLE\n#define LUA_NUMBER\tdouble\n\n/*\n@@ LUAI_UACNUMBER is the result of an 'usual argument conversion'\n@* over a number.\n*/\n#define LUAI_UACNUMBER\tdouble\n\n\n/*\n@@ LUA_NUMBER_SCAN is the format for reading numbers.\n@@ LUA_NUMBER_FMT is the format for writing numbers.\n@@ lua_number2str converts a number to a string.\n@@ LUAI_MAXNUMBER2STR is maximum size of previous conversion.\n@@ lua_str2number converts a string to a number.\n*/\n#define LUA_NUMBER_SCAN\t\t\"%lf\"\n#define LUA_NUMBER_FMT\t\t\"%.14g\"\n#define lua_number2str(s,n)\tsprintf((s), LUA_NUMBER_FMT, (n))\n#define LUAI_MAXNUMBER2STR\t32 /* 16 digits, sign, point, and \\0 */\n#define lua_str2number(s,p)\tstrtod((s), (p))\n\n\n/*\n@@ The luai_num* macros define the primitive operations over numbers.\n*/\n#if defined(LUA_CORE)\n#include <math.h>\n#define luai_numadd(a,b)\t((a)+(b))\n#define luai_numsub(a,b)\t((a)-(b))\n#define luai_nummul(a,b)\t((a)*(b))\n#define luai_numdiv(a,b)\t((a)/(b))\n#define luai_nummod(a,b)\t((a) - floor((a)/(b))*(b))\n#define luai_numpow(a,b)\t(pow(a,b))\n#define luai_numunm(a)\t\t(-(a))\n#define luai_numeq(a,b)\t\t((a)==(b))\n#define luai_numlt(a,b)\t\t((a)<(b))\n#define luai_numle(a,b)\t\t((a)<=(b))\n#define luai_numisnan(a)\t(!luai_numeq((a), (a)))\n#endif\n\n\n/*\n@@ lua_number2int is a macro to convert lua_Number to int.\n@@ lua_number2integer is a macro to convert lua_Number to lua_Integer.\n** CHANGE them if you know a faster way to convert a lua_Number to\n** int (with any rounding method and without throwing errors) in your\n** system. In Pentium machines, a naive typecast from double to int\n** in C is extremely slow, so any alternative is worth trying.\n*/\n\n/* On a Pentium, resort to a trick */\n#if defined(LUA_NUMBER_DOUBLE) && !defined(LUA_ANSI) && !defined(__SSE2__) && \\\n    (defined(__i386) || defined (_M_IX86) || defined(__i386__))\n\n/* On a Microsoft compiler, use assembler */\n#if defined(_MSC_VER)\n\n#define lua_number2int(i,d)   __asm fld d   __asm fistp i\n#define lua_number2integer(i,n)\t\tlua_number2int(i, n)\n\n/* the next trick should work on any Pentium, but sometimes clashes\n   with a DirectX idiosyncrasy */\n#else\n\nunion luai_Cast { double l_d; long l_l; };\n#define lua_number2int(i,d) \\\n  { volatile union luai_Cast u; u.l_d = (d) + 6755399441055744.0; (i) = u.l_l; }\n#define lua_number2integer(i,n)\t\tlua_number2int(i, n)\n\n#endif\n\n\n/* this option always works, but may be slow */\n#else\n#define lua_number2int(i,d)\t((i)=(int)(d))\n#define lua_number2integer(i,d)\t((i)=(lua_Integer)(d))\n\n#endif\n\n/* }================================================================== */\n\n\n/*\n@@ LUAI_USER_ALIGNMENT_T is a type that requires maximum alignment.\n** CHANGE it if your system requires alignments larger than double. (For\n** instance, if your system supports long doubles and they must be\n** aligned in 16-byte boundaries, then you should add long double in the\n** union.) Probably you do not need to change this.\n*/\n#define LUAI_USER_ALIGNMENT_T\tunion { double u; void *s; long l; }\n\n\n/*\n@@ LUAI_THROW/LUAI_TRY define how Lua does exception handling.\n** CHANGE them if you prefer to use longjmp/setjmp even with C++\n** or if want/don't to use _longjmp/_setjmp instead of regular\n** longjmp/setjmp. By default, Lua handles errors with exceptions when\n** compiling as C++ code, with _longjmp/_setjmp when asked to use them,\n** and with longjmp/setjmp otherwise.\n*/\n#if defined(__cplusplus)\n/* C++ exceptions */\n#define LUAI_THROW(L,c)\tthrow(c)\n#define LUAI_TRY(L,c,a)\ttry { a } catch(...) \\\n\t{ if ((c)->status == 0) (c)->status = -1; }\n#define luai_jmpbuf\tint  /* dummy variable */\n\n#elif defined(LUA_USE_ULONGJMP)\n/* in Unix, try _longjmp/_setjmp (more efficient) */\n#define LUAI_THROW(L,c)\t_longjmp((c)->b, 1)\n#define LUAI_TRY(L,c,a)\tif (_setjmp((c)->b) == 0) { a }\n#define luai_jmpbuf\tjmp_buf\n\n#else\n/* default handling with long jumps */\n#define LUAI_THROW(L,c)\tlongjmp((c)->b, 1)\n#define LUAI_TRY(L,c,a)\tif (setjmp((c)->b) == 0) { a }\n#define luai_jmpbuf\tjmp_buf\n\n#endif\n\n\n/*\n@@ LUA_MAXCAPTURES is the maximum number of captures that a pattern\n@* can do during pattern-matching.\n** CHANGE it if you need more captures. This limit is arbitrary.\n*/\n#define LUA_MAXCAPTURES\t\t32\n\n\n/*\n@@ lua_tmpnam is the function that the OS library uses to create a\n@* temporary name.\n@@ LUA_TMPNAMBUFSIZE is the maximum size of a name created by lua_tmpnam.\n** CHANGE them if you have an alternative to tmpnam (which is considered\n** insecure) or if you want the original tmpnam anyway.  By default, Lua\n** uses tmpnam except when POSIX is available, where it uses mkstemp.\n*/\n#if defined(loslib_c) || defined(luaall_c)\n\n#if defined(LUA_USE_MKSTEMP)\n#include <unistd.h>\n#define LUA_TMPNAMBUFSIZE\t32\n#define lua_tmpnam(b,e)\t{ \\\n\tstrcpy(b, \"/tmp/lua_XXXXXX\"); \\\n\te = mkstemp(b); \\\n\tif (e != -1) close(e); \\\n\te = (e == -1); }\n\n#else\n#define LUA_TMPNAMBUFSIZE\tL_tmpnam\n#define lua_tmpnam(b,e)\t\t{ e = (tmpnam(b) == NULL); }\n#endif\n\n#endif\n\n\n/*\n@@ lua_popen spawns a new process connected to the current one through\n@* the file streams.\n** CHANGE it if you have a way to implement it in your system.\n*/\n#if defined(LUA_USE_POPEN)\n\n#define lua_popen(L,c,m)\t((void)L, fflush(NULL), popen(c,m))\n#define lua_pclose(L,file)\t((void)L, (pclose(file) != -1))\n\n#elif defined(LUA_WIN)\n\n#define lua_popen(L,c,m)\t((void)L, _popen(c,m))\n#define lua_pclose(L,file)\t((void)L, (_pclose(file) != -1))\n\n#else\n\n#define lua_popen(L,c,m)\t((void)((void)c, m),  \\\n\t\tluaL_error(L, LUA_QL(\"popen\") \" not supported\"), (FILE*)0)\n#define lua_pclose(L,file)\t\t((void)((void)L, file), 0)\n\n#endif\n\n/*\n@@ LUA_DL_* define which dynamic-library system Lua should use.\n** CHANGE here if Lua has problems choosing the appropriate\n** dynamic-library system for your platform (either Windows' DLL, Mac's\n** dyld, or Unix's dlopen). If your system is some kind of Unix, there\n** is a good chance that it has dlopen, so LUA_DL_DLOPEN will work for\n** it.  To use dlopen you also need to adapt the src/Makefile (probably\n** adding -ldl to the linker options), so Lua does not select it\n** automatically.  (When you change the makefile to add -ldl, you must\n** also add -DLUA_USE_DLOPEN.)\n** If you do not want any kind of dynamic library, undefine all these\n** options.\n** By default, _WIN32 gets LUA_DL_DLL and MAC OS X gets LUA_DL_DYLD.\n*/\n#if defined(LUA_USE_DLOPEN)\n#define LUA_DL_DLOPEN\n#endif\n\n#if defined(LUA_WIN)\n#define LUA_DL_DLL\n#endif\n\n\n/*\n@@ LUAI_EXTRASPACE allows you to add user-specific data in a lua_State\n@* (the data goes just *before* the lua_State pointer).\n** CHANGE (define) this if you really need that. This value must be\n** a multiple of the maximum alignment required for your machine.\n*/\n#define LUAI_EXTRASPACE\t\t0\n\n\n/*\n@@ luai_userstate* allow user-specific actions on threads.\n** CHANGE them if you defined LUAI_EXTRASPACE and need to do something\n** extra when a thread is created/deleted/resumed/yielded.\n*/\n#define luai_userstateopen(L)\t\t((void)L)\n#define luai_userstateclose(L)\t\t((void)L)\n#define luai_userstatethread(L,L1)\t((void)L)\n#define luai_userstatefree(L)\t\t((void)L)\n#define luai_userstateresume(L,n)\t((void)L)\n#define luai_userstateyield(L,n)\t((void)L)\n\n\n/*\n@@ LUA_INTFRMLEN is the length modifier for integer conversions\n@* in 'string.format'.\n@@ LUA_INTFRM_T is the integer type correspoding to the previous length\n@* modifier.\n** CHANGE them if your system supports long long or does not support long.\n*/\n\n#if defined(LUA_USELONGLONG)\n\n#define LUA_INTFRMLEN\t\t\"ll\"\n#define LUA_INTFRM_T\t\tlong long\n\n#else\n\n#define LUA_INTFRMLEN\t\t\"l\"\n#define LUA_INTFRM_T\t\tlong\n\n#endif\n\n\n\n/* =================================================================== */\n\n/*\n** Local configuration. You can use this space to add your redefinitions\n** without modifying the main part of the file.\n*/\n\n\n\n#endif\n\n"
  },
  {
    "path": "extern/deprecated/redis-2.8.21/deps/lua/src/lualib.h",
    "content": "/*\n** $Id: lualib.h,v 1.36.1.1 2007/12/27 13:02:25 roberto Exp $\n** Lua standard libraries\n** See Copyright Notice in lua.h\n*/\n\n\n#ifndef lualib_h\n#define lualib_h\n\n#include \"lua.h\"\n\n\n/* Key to file-handle type */\n#define LUA_FILEHANDLE\t\t\"FILE*\"\n\n\n#define LUA_COLIBNAME\t\"coroutine\"\nLUALIB_API int (luaopen_base) (lua_State *L);\n\n#define LUA_TABLIBNAME\t\"table\"\nLUALIB_API int (luaopen_table) (lua_State *L);\n\n#define LUA_IOLIBNAME\t\"io\"\nLUALIB_API int (luaopen_io) (lua_State *L);\n\n#define LUA_OSLIBNAME\t\"os\"\nLUALIB_API int (luaopen_os) (lua_State *L);\n\n#define LUA_STRLIBNAME\t\"string\"\nLUALIB_API int (luaopen_string) (lua_State *L);\n\n#define LUA_MATHLIBNAME\t\"math\"\nLUALIB_API int (luaopen_math) (lua_State *L);\n\n#define LUA_DBLIBNAME\t\"debug\"\nLUALIB_API int (luaopen_debug) (lua_State *L);\n\n#define LUA_LOADLIBNAME\t\"package\"\nLUALIB_API int (luaopen_package) (lua_State *L);\n\n\n/* open all previous libraries */\nLUALIB_API void (luaL_openlibs) (lua_State *L); \n\n\n\n#ifndef lua_assert\n#define lua_assert(x)\t((void)0)\n#endif\n\n\n#endif\n"
  },
  {
    "path": "extern/deprecated/redis-2.8.21/deps/lua/src/lundump.c",
    "content": "/*\n** $Id: lundump.c,v 2.7.1.4 2008/04/04 19:51:41 roberto Exp $\n** load precompiled Lua chunks\n** See Copyright Notice in lua.h\n*/\n\n#include <string.h>\n\n#define lundump_c\n#define LUA_CORE\n\n#include \"lua.h\"\n\n#include \"ldebug.h\"\n#include \"ldo.h\"\n#include \"lfunc.h\"\n#include \"lmem.h\"\n#include \"lobject.h\"\n#include \"lstring.h\"\n#include \"lundump.h\"\n#include \"lzio.h\"\n\ntypedef struct {\n lua_State* L;\n ZIO* Z;\n Mbuffer* b;\n const char* name;\n} LoadState;\n\n#ifdef LUAC_TRUST_BINARIES\n#define IF(c,s)\n#define error(S,s)\n#else\n#define IF(c,s)\t\tif (c) error(S,s)\n\nstatic void error(LoadState* S, const char* why)\n{\n luaO_pushfstring(S->L,\"%s: %s in precompiled chunk\",S->name,why);\n luaD_throw(S->L,LUA_ERRSYNTAX);\n}\n#endif\n\n#define LoadMem(S,b,n,size)\tLoadBlock(S,b,(n)*(size))\n#define\tLoadByte(S)\t\t(lu_byte)LoadChar(S)\n#define LoadVar(S,x)\t\tLoadMem(S,&x,1,sizeof(x))\n#define LoadVector(S,b,n,size)\tLoadMem(S,b,n,size)\n\nstatic void LoadBlock(LoadState* S, void* b, size_t size)\n{\n size_t r=luaZ_read(S->Z,b,size);\n IF (r!=0, \"unexpected end\");\n}\n\nstatic int LoadChar(LoadState* S)\n{\n char x;\n LoadVar(S,x);\n return x;\n}\n\nstatic int LoadInt(LoadState* S)\n{\n int x;\n LoadVar(S,x);\n IF (x<0, \"bad integer\");\n return x;\n}\n\nstatic lua_Number LoadNumber(LoadState* S)\n{\n lua_Number x;\n LoadVar(S,x);\n return x;\n}\n\nstatic TString* LoadString(LoadState* S)\n{\n size_t size;\n LoadVar(S,size);\n if (size==0)\n  return NULL;\n else\n {\n  char* s=luaZ_openspace(S->L,S->b,size);\n  LoadBlock(S,s,size);\n  return luaS_newlstr(S->L,s,size-1);\t\t/* remove trailing '\\0' */\n }\n}\n\nstatic void LoadCode(LoadState* S, Proto* f)\n{\n int n=LoadInt(S);\n f->code=luaM_newvector(S->L,n,Instruction);\n f->sizecode=n;\n LoadVector(S,f->code,n,sizeof(Instruction));\n}\n\nstatic Proto* LoadFunction(LoadState* S, TString* p);\n\nstatic void LoadConstants(LoadState* S, Proto* f)\n{\n int i,n;\n n=LoadInt(S);\n f->k=luaM_newvector(S->L,n,TValue);\n f->sizek=n;\n for (i=0; i<n; i++) setnilvalue(&f->k[i]);\n for (i=0; i<n; i++)\n {\n  TValue* o=&f->k[i];\n  int t=LoadChar(S);\n  switch (t)\n  {\n   case LUA_TNIL:\n   \tsetnilvalue(o);\n\tbreak;\n   case LUA_TBOOLEAN:\n   \tsetbvalue(o,LoadChar(S)!=0);\n\tbreak;\n   case LUA_TNUMBER:\n\tsetnvalue(o,LoadNumber(S));\n\tbreak;\n   case LUA_TSTRING:\n\tsetsvalue2n(S->L,o,LoadString(S));\n\tbreak;\n   default:\n\terror(S,\"bad constant\");\n\tbreak;\n  }\n }\n n=LoadInt(S);\n f->p=luaM_newvector(S->L,n,Proto*);\n f->sizep=n;\n for (i=0; i<n; i++) f->p[i]=NULL;\n for (i=0; i<n; i++) f->p[i]=LoadFunction(S,f->source);\n}\n\nstatic void LoadDebug(LoadState* S, Proto* f)\n{\n int i,n;\n n=LoadInt(S);\n f->lineinfo=luaM_newvector(S->L,n,int);\n f->sizelineinfo=n;\n LoadVector(S,f->lineinfo,n,sizeof(int));\n n=LoadInt(S);\n f->locvars=luaM_newvector(S->L,n,LocVar);\n f->sizelocvars=n;\n for (i=0; i<n; i++) f->locvars[i].varname=NULL;\n for (i=0; i<n; i++)\n {\n  f->locvars[i].varname=LoadString(S);\n  f->locvars[i].startpc=LoadInt(S);\n  f->locvars[i].endpc=LoadInt(S);\n }\n n=LoadInt(S);\n f->upvalues=luaM_newvector(S->L,n,TString*);\n f->sizeupvalues=n;\n for (i=0; i<n; i++) f->upvalues[i]=NULL;\n for (i=0; i<n; i++) f->upvalues[i]=LoadString(S);\n}\n\nstatic Proto* LoadFunction(LoadState* S, TString* p)\n{\n Proto* f;\n if (++S->L->nCcalls > LUAI_MAXCCALLS) error(S,\"code too deep\");\n f=luaF_newproto(S->L);\n setptvalue2s(S->L,S->L->top,f); incr_top(S->L);\n f->source=LoadString(S); if (f->source==NULL) f->source=p;\n f->linedefined=LoadInt(S);\n f->lastlinedefined=LoadInt(S);\n f->nups=LoadByte(S);\n f->numparams=LoadByte(S);\n f->is_vararg=LoadByte(S);\n f->maxstacksize=LoadByte(S);\n LoadCode(S,f);\n LoadConstants(S,f);\n LoadDebug(S,f);\n IF (!luaG_checkcode(f), \"bad code\");\n S->L->top--;\n S->L->nCcalls--;\n return f;\n}\n\nstatic void LoadHeader(LoadState* S)\n{\n char h[LUAC_HEADERSIZE];\n char s[LUAC_HEADERSIZE];\n luaU_header(h);\n LoadBlock(S,s,LUAC_HEADERSIZE);\n IF (memcmp(h,s,LUAC_HEADERSIZE)!=0, \"bad header\");\n}\n\n/*\n** load precompiled chunk\n*/\nProto* luaU_undump (lua_State* L, ZIO* Z, Mbuffer* buff, const char* name)\n{\n LoadState S;\n if (*name=='@' || *name=='=')\n  S.name=name+1;\n else if (*name==LUA_SIGNATURE[0])\n  S.name=\"binary string\";\n else\n  S.name=name;\n S.L=L;\n S.Z=Z;\n S.b=buff;\n LoadHeader(&S);\n return LoadFunction(&S,luaS_newliteral(L,\"=?\"));\n}\n\n/*\n* make header\n*/\nvoid luaU_header (char* h)\n{\n int x=1;\n memcpy(h,LUA_SIGNATURE,sizeof(LUA_SIGNATURE)-1);\n h+=sizeof(LUA_SIGNATURE)-1;\n *h++=(char)LUAC_VERSION;\n *h++=(char)LUAC_FORMAT;\n *h++=(char)*(char*)&x;\t\t\t\t/* endianness */\n *h++=(char)sizeof(int);\n *h++=(char)sizeof(size_t);\n *h++=(char)sizeof(Instruction);\n *h++=(char)sizeof(lua_Number);\n *h++=(char)(((lua_Number)0.5)==0);\t\t/* is lua_Number integral? */\n}\n"
  },
  {
    "path": "extern/deprecated/redis-2.8.21/deps/lua/src/lundump.h",
    "content": "/*\n** $Id: lundump.h,v 1.37.1.1 2007/12/27 13:02:25 roberto Exp $\n** load precompiled Lua chunks\n** See Copyright Notice in lua.h\n*/\n\n#ifndef lundump_h\n#define lundump_h\n\n#include \"lobject.h\"\n#include \"lzio.h\"\n\n/* load one chunk; from lundump.c */\nLUAI_FUNC Proto* luaU_undump (lua_State* L, ZIO* Z, Mbuffer* buff, const char* name);\n\n/* make header; from lundump.c */\nLUAI_FUNC void luaU_header (char* h);\n\n/* dump one chunk; from ldump.c */\nLUAI_FUNC int luaU_dump (lua_State* L, const Proto* f, lua_Writer w, void* data, int strip);\n\n#ifdef luac_c\n/* print one chunk; from print.c */\nLUAI_FUNC void luaU_print (const Proto* f, int full);\n#endif\n\n/* for header of binary files -- this is Lua 5.1 */\n#define LUAC_VERSION\t\t0x51\n\n/* for header of binary files -- this is the official format */\n#define LUAC_FORMAT\t\t0\n\n/* size of header of binary files */\n#define LUAC_HEADERSIZE\t\t12\n\n#endif\n"
  },
  {
    "path": "extern/deprecated/redis-2.8.21/deps/lua/src/lvm.c",
    "content": "/*\n** $Id: lvm.c,v 2.63.1.5 2011/08/17 20:43:11 roberto Exp $\n** Lua virtual machine\n** See Copyright Notice in lua.h\n*/\n\n\n#include <stdio.h>\n#include <stdlib.h>\n#include <string.h>\n\n#define lvm_c\n#define LUA_CORE\n\n#include \"lua.h\"\n\n#include \"ldebug.h\"\n#include \"ldo.h\"\n#include \"lfunc.h\"\n#include \"lgc.h\"\n#include \"lobject.h\"\n#include \"lopcodes.h\"\n#include \"lstate.h\"\n#include \"lstring.h\"\n#include \"ltable.h\"\n#include \"ltm.h\"\n#include \"lvm.h\"\n\n\n\n/* limit for table tag-method chains (to avoid loops) */\n#define MAXTAGLOOP\t100\n\n\nconst TValue *luaV_tonumber (const TValue *obj, TValue *n) {\n  lua_Number num;\n  if (ttisnumber(obj)) return obj;\n  if (ttisstring(obj) && luaO_str2d(svalue(obj), &num)) {\n    setnvalue(n, num);\n    return n;\n  }\n  else\n    return NULL;\n}\n\n\nint luaV_tostring (lua_State *L, StkId obj) {\n  if (!ttisnumber(obj))\n    return 0;\n  else {\n    char s[LUAI_MAXNUMBER2STR];\n    lua_Number n = nvalue(obj);\n    lua_number2str(s, n);\n    setsvalue2s(L, obj, luaS_new(L, s));\n    return 1;\n  }\n}\n\n\nstatic void traceexec (lua_State *L, const Instruction *pc) {\n  lu_byte mask = L->hookmask;\n  const Instruction *oldpc = L->savedpc;\n  L->savedpc = pc;\n  if ((mask & LUA_MASKCOUNT) && L->hookcount == 0) {\n    resethookcount(L);\n    luaD_callhook(L, LUA_HOOKCOUNT, -1);\n  }\n  if (mask & LUA_MASKLINE) {\n    Proto *p = ci_func(L->ci)->l.p;\n    int npc = pcRel(pc, p);\n    int newline = getline(p, npc);\n    /* call linehook when enter a new function, when jump back (loop),\n       or when enter a new line */\n    if (npc == 0 || pc <= oldpc || newline != getline(p, pcRel(oldpc, p)))\n      luaD_callhook(L, LUA_HOOKLINE, newline);\n  }\n}\n\n\nstatic void callTMres (lua_State *L, StkId res, const TValue *f,\n                        const TValue *p1, const TValue *p2) {\n  ptrdiff_t result = savestack(L, res);\n  setobj2s(L, L->top, f);  /* push function */\n  setobj2s(L, L->top+1, p1);  /* 1st argument */\n  setobj2s(L, L->top+2, p2);  /* 2nd argument */\n  luaD_checkstack(L, 3);\n  L->top += 3;\n  luaD_call(L, L->top - 3, 1);\n  res = restorestack(L, result);\n  L->top--;\n  setobjs2s(L, res, L->top);\n}\n\n\n\nstatic void callTM (lua_State *L, const TValue *f, const TValue *p1,\n                    const TValue *p2, const TValue *p3) {\n  setobj2s(L, L->top, f);  /* push function */\n  setobj2s(L, L->top+1, p1);  /* 1st argument */\n  setobj2s(L, L->top+2, p2);  /* 2nd argument */\n  setobj2s(L, L->top+3, p3);  /* 3th argument */\n  luaD_checkstack(L, 4);\n  L->top += 4;\n  luaD_call(L, L->top - 4, 0);\n}\n\n\nvoid luaV_gettable (lua_State *L, const TValue *t, TValue *key, StkId val) {\n  int loop;\n  for (loop = 0; loop < MAXTAGLOOP; loop++) {\n    const TValue *tm;\n    if (ttistable(t)) {  /* `t' is a table? */\n      Table *h = hvalue(t);\n      const TValue *res = luaH_get(h, key); /* do a primitive get */\n      if (!ttisnil(res) ||  /* result is no nil? */\n          (tm = fasttm(L, h->metatable, TM_INDEX)) == NULL) { /* or no TM? */\n        setobj2s(L, val, res);\n        return;\n      }\n      /* else will try the tag method */\n    }\n    else if (ttisnil(tm = luaT_gettmbyobj(L, t, TM_INDEX)))\n      luaG_typeerror(L, t, \"index\");\n    if (ttisfunction(tm)) {\n      callTMres(L, val, tm, t, key);\n      return;\n    }\n    t = tm;  /* else repeat with `tm' */ \n  }\n  luaG_runerror(L, \"loop in gettable\");\n}\n\n\nvoid luaV_settable (lua_State *L, const TValue *t, TValue *key, StkId val) {\n  int loop;\n  TValue temp;\n  for (loop = 0; loop < MAXTAGLOOP; loop++) {\n    const TValue *tm;\n    if (ttistable(t)) {  /* `t' is a table? */\n      Table *h = hvalue(t);\n      TValue *oldval = luaH_set(L, h, key); /* do a primitive set */\n      if (!ttisnil(oldval) ||  /* result is no nil? */\n          (tm = fasttm(L, h->metatable, TM_NEWINDEX)) == NULL) { /* or no TM? */\n        setobj2t(L, oldval, val);\n        h->flags = 0;\n        luaC_barriert(L, h, val);\n        return;\n      }\n      /* else will try the tag method */\n    }\n    else if (ttisnil(tm = luaT_gettmbyobj(L, t, TM_NEWINDEX)))\n      luaG_typeerror(L, t, \"index\");\n    if (ttisfunction(tm)) {\n      callTM(L, tm, t, key, val);\n      return;\n    }\n    /* else repeat with `tm' */\n    setobj(L, &temp, tm);  /* avoid pointing inside table (may rehash) */\n    t = &temp;\n  }\n  luaG_runerror(L, \"loop in settable\");\n}\n\n\nstatic int call_binTM (lua_State *L, const TValue *p1, const TValue *p2,\n                       StkId res, TMS event) {\n  const TValue *tm = luaT_gettmbyobj(L, p1, event);  /* try first operand */\n  if (ttisnil(tm))\n    tm = luaT_gettmbyobj(L, p2, event);  /* try second operand */\n  if (ttisnil(tm)) return 0;\n  callTMres(L, res, tm, p1, p2);\n  return 1;\n}\n\n\nstatic const TValue *get_compTM (lua_State *L, Table *mt1, Table *mt2,\n                                  TMS event) {\n  const TValue *tm1 = fasttm(L, mt1, event);\n  const TValue *tm2;\n  if (tm1 == NULL) return NULL;  /* no metamethod */\n  if (mt1 == mt2) return tm1;  /* same metatables => same metamethods */\n  tm2 = fasttm(L, mt2, event);\n  if (tm2 == NULL) return NULL;  /* no metamethod */\n  if (luaO_rawequalObj(tm1, tm2))  /* same metamethods? */\n    return tm1;\n  return NULL;\n}\n\n\nstatic int call_orderTM (lua_State *L, const TValue *p1, const TValue *p2,\n                         TMS event) {\n  const TValue *tm1 = luaT_gettmbyobj(L, p1, event);\n  const TValue *tm2;\n  if (ttisnil(tm1)) return -1;  /* no metamethod? */\n  tm2 = luaT_gettmbyobj(L, p2, event);\n  if (!luaO_rawequalObj(tm1, tm2))  /* different metamethods? */\n    return -1;\n  callTMres(L, L->top, tm1, p1, p2);\n  return !l_isfalse(L->top);\n}\n\n\nstatic int l_strcmp (const TString *ls, const TString *rs) {\n  const char *l = getstr(ls);\n  size_t ll = ls->tsv.len;\n  const char *r = getstr(rs);\n  size_t lr = rs->tsv.len;\n  for (;;) {\n    int temp = strcoll(l, r);\n    if (temp != 0) return temp;\n    else {  /* strings are equal up to a `\\0' */\n      size_t len = strlen(l);  /* index of first `\\0' in both strings */\n      if (len == lr)  /* r is finished? */\n        return (len == ll) ? 0 : 1;\n      else if (len == ll)  /* l is finished? */\n        return -1;  /* l is smaller than r (because r is not finished) */\n      /* both strings longer than `len'; go on comparing (after the `\\0') */\n      len++;\n      l += len; ll -= len; r += len; lr -= len;\n    }\n  }\n}\n\n\nint luaV_lessthan (lua_State *L, const TValue *l, const TValue *r) {\n  int res;\n  if (ttype(l) != ttype(r))\n    return luaG_ordererror(L, l, r);\n  else if (ttisnumber(l))\n    return luai_numlt(nvalue(l), nvalue(r));\n  else if (ttisstring(l))\n    return l_strcmp(rawtsvalue(l), rawtsvalue(r)) < 0;\n  else if ((res = call_orderTM(L, l, r, TM_LT)) != -1)\n    return res;\n  return luaG_ordererror(L, l, r);\n}\n\n\nstatic int lessequal (lua_State *L, const TValue *l, const TValue *r) {\n  int res;\n  if (ttype(l) != ttype(r))\n    return luaG_ordererror(L, l, r);\n  else if (ttisnumber(l))\n    return luai_numle(nvalue(l), nvalue(r));\n  else if (ttisstring(l))\n    return l_strcmp(rawtsvalue(l), rawtsvalue(r)) <= 0;\n  else if ((res = call_orderTM(L, l, r, TM_LE)) != -1)  /* first try `le' */\n    return res;\n  else if ((res = call_orderTM(L, r, l, TM_LT)) != -1)  /* else try `lt' */\n    return !res;\n  return luaG_ordererror(L, l, r);\n}\n\n\nint luaV_equalval (lua_State *L, const TValue *t1, const TValue *t2) {\n  const TValue *tm;\n  lua_assert(ttype(t1) == ttype(t2));\n  switch (ttype(t1)) {\n    case LUA_TNIL: return 1;\n    case LUA_TNUMBER: return luai_numeq(nvalue(t1), nvalue(t2));\n    case LUA_TBOOLEAN: return bvalue(t1) == bvalue(t2);  /* true must be 1 !! */\n    case LUA_TLIGHTUSERDATA: return pvalue(t1) == pvalue(t2);\n    case LUA_TUSERDATA: {\n      if (uvalue(t1) == uvalue(t2)) return 1;\n      tm = get_compTM(L, uvalue(t1)->metatable, uvalue(t2)->metatable,\n                         TM_EQ);\n      break;  /* will try TM */\n    }\n    case LUA_TTABLE: {\n      if (hvalue(t1) == hvalue(t2)) return 1;\n      tm = get_compTM(L, hvalue(t1)->metatable, hvalue(t2)->metatable, TM_EQ);\n      break;  /* will try TM */\n    }\n    default: return gcvalue(t1) == gcvalue(t2);\n  }\n  if (tm == NULL) return 0;  /* no TM? */\n  callTMres(L, L->top, tm, t1, t2);  /* call TM */\n  return !l_isfalse(L->top);\n}\n\n\nvoid luaV_concat (lua_State *L, int total, int last) {\n  do {\n    StkId top = L->base + last + 1;\n    int n = 2;  /* number of elements handled in this pass (at least 2) */\n    if (!(ttisstring(top-2) || ttisnumber(top-2)) || !tostring(L, top-1)) {\n      if (!call_binTM(L, top-2, top-1, top-2, TM_CONCAT))\n        luaG_concaterror(L, top-2, top-1);\n    } else if (tsvalue(top-1)->len == 0)  /* second op is empty? */\n      (void)tostring(L, top - 2);  /* result is first op (as string) */\n    else {\n      /* at least two string values; get as many as possible */\n      size_t tl = tsvalue(top-1)->len;\n      char *buffer;\n      int i;\n      /* collect total length */\n      for (n = 1; n < total && tostring(L, top-n-1); n++) {\n        size_t l = tsvalue(top-n-1)->len;\n        if (l >= MAX_SIZET - tl) luaG_runerror(L, \"string length overflow\");\n        tl += l;\n      }\n      buffer = luaZ_openspace(L, &G(L)->buff, tl);\n      tl = 0;\n      for (i=n; i>0; i--) {  /* concat all strings */\n        size_t l = tsvalue(top-i)->len;\n        memcpy(buffer+tl, svalue(top-i), l);\n        tl += l;\n      }\n      setsvalue2s(L, top-n, luaS_newlstr(L, buffer, tl));\n    }\n    total -= n-1;  /* got `n' strings to create 1 new */\n    last -= n-1;\n  } while (total > 1);  /* repeat until only 1 result left */\n}\n\n\nstatic void Arith (lua_State *L, StkId ra, const TValue *rb,\n                   const TValue *rc, TMS op) {\n  TValue tempb, tempc;\n  const TValue *b, *c;\n  if ((b = luaV_tonumber(rb, &tempb)) != NULL &&\n      (c = luaV_tonumber(rc, &tempc)) != NULL) {\n    lua_Number nb = nvalue(b), nc = nvalue(c);\n    switch (op) {\n      case TM_ADD: setnvalue(ra, luai_numadd(nb, nc)); break;\n      case TM_SUB: setnvalue(ra, luai_numsub(nb, nc)); break;\n      case TM_MUL: setnvalue(ra, luai_nummul(nb, nc)); break;\n      case TM_DIV: setnvalue(ra, luai_numdiv(nb, nc)); break;\n      case TM_MOD: setnvalue(ra, luai_nummod(nb, nc)); break;\n      case TM_POW: setnvalue(ra, luai_numpow(nb, nc)); break;\n      case TM_UNM: setnvalue(ra, luai_numunm(nb)); break;\n      default: lua_assert(0); break;\n    }\n  }\n  else if (!call_binTM(L, rb, rc, ra, op))\n    luaG_aritherror(L, rb, rc);\n}\n\n\n\n/*\n** some macros for common tasks in `luaV_execute'\n*/\n\n#define runtime_check(L, c)\t{ if (!(c)) break; }\n\n#define RA(i)\t(base+GETARG_A(i))\n/* to be used after possible stack reallocation */\n#define RB(i)\tcheck_exp(getBMode(GET_OPCODE(i)) == OpArgR, base+GETARG_B(i))\n#define RC(i)\tcheck_exp(getCMode(GET_OPCODE(i)) == OpArgR, base+GETARG_C(i))\n#define RKB(i)\tcheck_exp(getBMode(GET_OPCODE(i)) == OpArgK, \\\n\tISK(GETARG_B(i)) ? k+INDEXK(GETARG_B(i)) : base+GETARG_B(i))\n#define RKC(i)\tcheck_exp(getCMode(GET_OPCODE(i)) == OpArgK, \\\n\tISK(GETARG_C(i)) ? k+INDEXK(GETARG_C(i)) : base+GETARG_C(i))\n#define KBx(i)\tcheck_exp(getBMode(GET_OPCODE(i)) == OpArgK, k+GETARG_Bx(i))\n\n\n#define dojump(L,pc,i)\t{(pc) += (i); luai_threadyield(L);}\n\n\n#define Protect(x)\t{ L->savedpc = pc; {x;}; base = L->base; }\n\n\n#define arith_op(op,tm) { \\\n        TValue *rb = RKB(i); \\\n        TValue *rc = RKC(i); \\\n        if (ttisnumber(rb) && ttisnumber(rc)) { \\\n          lua_Number nb = nvalue(rb), nc = nvalue(rc); \\\n          setnvalue(ra, op(nb, nc)); \\\n        } \\\n        else \\\n          Protect(Arith(L, ra, rb, rc, tm)); \\\n      }\n\n\n\nvoid luaV_execute (lua_State *L, int nexeccalls) {\n  LClosure *cl;\n  StkId base;\n  TValue *k;\n  const Instruction *pc;\n reentry:  /* entry point */\n  lua_assert(isLua(L->ci));\n  pc = L->savedpc;\n  cl = &clvalue(L->ci->func)->l;\n  base = L->base;\n  k = cl->p->k;\n  /* main loop of interpreter */\n  for (;;) {\n    const Instruction i = *pc++;\n    StkId ra;\n    if ((L->hookmask & (LUA_MASKLINE | LUA_MASKCOUNT)) &&\n        (--L->hookcount == 0 || L->hookmask & LUA_MASKLINE)) {\n      traceexec(L, pc);\n      if (L->status == LUA_YIELD) {  /* did hook yield? */\n        L->savedpc = pc - 1;\n        return;\n      }\n      base = L->base;\n    }\n    /* warning!! several calls may realloc the stack and invalidate `ra' */\n    ra = RA(i);\n    lua_assert(base == L->base && L->base == L->ci->base);\n    lua_assert(base <= L->top && L->top <= L->stack + L->stacksize);\n    lua_assert(L->top == L->ci->top || luaG_checkopenop(i));\n    switch (GET_OPCODE(i)) {\n      case OP_MOVE: {\n        setobjs2s(L, ra, RB(i));\n        continue;\n      }\n      case OP_LOADK: {\n        setobj2s(L, ra, KBx(i));\n        continue;\n      }\n      case OP_LOADBOOL: {\n        setbvalue(ra, GETARG_B(i));\n        if (GETARG_C(i)) pc++;  /* skip next instruction (if C) */\n        continue;\n      }\n      case OP_LOADNIL: {\n        TValue *rb = RB(i);\n        do {\n          setnilvalue(rb--);\n        } while (rb >= ra);\n        continue;\n      }\n      case OP_GETUPVAL: {\n        int b = GETARG_B(i);\n        setobj2s(L, ra, cl->upvals[b]->v);\n        continue;\n      }\n      case OP_GETGLOBAL: {\n        TValue g;\n        TValue *rb = KBx(i);\n        sethvalue(L, &g, cl->env);\n        lua_assert(ttisstring(rb));\n        Protect(luaV_gettable(L, &g, rb, ra));\n        continue;\n      }\n      case OP_GETTABLE: {\n        Protect(luaV_gettable(L, RB(i), RKC(i), ra));\n        continue;\n      }\n      case OP_SETGLOBAL: {\n        TValue g;\n        sethvalue(L, &g, cl->env);\n        lua_assert(ttisstring(KBx(i)));\n        Protect(luaV_settable(L, &g, KBx(i), ra));\n        continue;\n      }\n      case OP_SETUPVAL: {\n        UpVal *uv = cl->upvals[GETARG_B(i)];\n        setobj(L, uv->v, ra);\n        luaC_barrier(L, uv, ra);\n        continue;\n      }\n      case OP_SETTABLE: {\n        Protect(luaV_settable(L, ra, RKB(i), RKC(i)));\n        continue;\n      }\n      case OP_NEWTABLE: {\n        int b = GETARG_B(i);\n        int c = GETARG_C(i);\n        sethvalue(L, ra, luaH_new(L, luaO_fb2int(b), luaO_fb2int(c)));\n        Protect(luaC_checkGC(L));\n        continue;\n      }\n      case OP_SELF: {\n        StkId rb = RB(i);\n        setobjs2s(L, ra+1, rb);\n        Protect(luaV_gettable(L, rb, RKC(i), ra));\n        continue;\n      }\n      case OP_ADD: {\n        arith_op(luai_numadd, TM_ADD);\n        continue;\n      }\n      case OP_SUB: {\n        arith_op(luai_numsub, TM_SUB);\n        continue;\n      }\n      case OP_MUL: {\n        arith_op(luai_nummul, TM_MUL);\n        continue;\n      }\n      case OP_DIV: {\n        arith_op(luai_numdiv, TM_DIV);\n        continue;\n      }\n      case OP_MOD: {\n        arith_op(luai_nummod, TM_MOD);\n        continue;\n      }\n      case OP_POW: {\n        arith_op(luai_numpow, TM_POW);\n        continue;\n      }\n      case OP_UNM: {\n        TValue *rb = RB(i);\n        if (ttisnumber(rb)) {\n          lua_Number nb = nvalue(rb);\n          setnvalue(ra, luai_numunm(nb));\n        }\n        else {\n          Protect(Arith(L, ra, rb, rb, TM_UNM));\n        }\n        continue;\n      }\n      case OP_NOT: {\n        int res = l_isfalse(RB(i));  /* next assignment may change this value */\n        setbvalue(ra, res);\n        continue;\n      }\n      case OP_LEN: {\n        const TValue *rb = RB(i);\n        switch (ttype(rb)) {\n          case LUA_TTABLE: {\n            setnvalue(ra, cast_num(luaH_getn(hvalue(rb))));\n            break;\n          }\n          case LUA_TSTRING: {\n            setnvalue(ra, cast_num(tsvalue(rb)->len));\n            break;\n          }\n          default: {  /* try metamethod */\n            Protect(\n              if (!call_binTM(L, rb, luaO_nilobject, ra, TM_LEN))\n                luaG_typeerror(L, rb, \"get length of\");\n            )\n          }\n        }\n        continue;\n      }\n      case OP_CONCAT: {\n        int b = GETARG_B(i);\n        int c = GETARG_C(i);\n        Protect(luaV_concat(L, c-b+1, c); luaC_checkGC(L));\n        setobjs2s(L, RA(i), base+b);\n        continue;\n      }\n      case OP_JMP: {\n        dojump(L, pc, GETARG_sBx(i));\n        continue;\n      }\n      case OP_EQ: {\n        TValue *rb = RKB(i);\n        TValue *rc = RKC(i);\n        Protect(\n          if (equalobj(L, rb, rc) == GETARG_A(i))\n            dojump(L, pc, GETARG_sBx(*pc));\n        )\n        pc++;\n        continue;\n      }\n      case OP_LT: {\n        Protect(\n          if (luaV_lessthan(L, RKB(i), RKC(i)) == GETARG_A(i))\n            dojump(L, pc, GETARG_sBx(*pc));\n        )\n        pc++;\n        continue;\n      }\n      case OP_LE: {\n        Protect(\n          if (lessequal(L, RKB(i), RKC(i)) == GETARG_A(i))\n            dojump(L, pc, GETARG_sBx(*pc));\n        )\n        pc++;\n        continue;\n      }\n      case OP_TEST: {\n        if (l_isfalse(ra) != GETARG_C(i))\n          dojump(L, pc, GETARG_sBx(*pc));\n        pc++;\n        continue;\n      }\n      case OP_TESTSET: {\n        TValue *rb = RB(i);\n        if (l_isfalse(rb) != GETARG_C(i)) {\n          setobjs2s(L, ra, rb);\n          dojump(L, pc, GETARG_sBx(*pc));\n        }\n        pc++;\n        continue;\n      }\n      case OP_CALL: {\n        int b = GETARG_B(i);\n        int nresults = GETARG_C(i) - 1;\n        if (b != 0) L->top = ra+b;  /* else previous instruction set top */\n        L->savedpc = pc;\n        switch (luaD_precall(L, ra, nresults)) {\n          case PCRLUA: {\n            nexeccalls++;\n            goto reentry;  /* restart luaV_execute over new Lua function */\n          }\n          case PCRC: {\n            /* it was a C function (`precall' called it); adjust results */\n            if (nresults >= 0) L->top = L->ci->top;\n            base = L->base;\n            continue;\n          }\n          default: {\n            return;  /* yield */\n          }\n        }\n      }\n      case OP_TAILCALL: {\n        int b = GETARG_B(i);\n        if (b != 0) L->top = ra+b;  /* else previous instruction set top */\n        L->savedpc = pc;\n        lua_assert(GETARG_C(i) - 1 == LUA_MULTRET);\n        switch (luaD_precall(L, ra, LUA_MULTRET)) {\n          case PCRLUA: {\n            /* tail call: put new frame in place of previous one */\n            CallInfo *ci = L->ci - 1;  /* previous frame */\n            int aux;\n            StkId func = ci->func;\n            StkId pfunc = (ci+1)->func;  /* previous function index */\n            if (L->openupval) luaF_close(L, ci->base);\n            L->base = ci->base = ci->func + ((ci+1)->base - pfunc);\n            for (aux = 0; pfunc+aux < L->top; aux++)  /* move frame down */\n              setobjs2s(L, func+aux, pfunc+aux);\n            ci->top = L->top = func+aux;  /* correct top */\n            lua_assert(L->top == L->base + clvalue(func)->l.p->maxstacksize);\n            ci->savedpc = L->savedpc;\n            ci->tailcalls++;  /* one more call lost */\n            L->ci--;  /* remove new frame */\n            goto reentry;\n          }\n          case PCRC: {  /* it was a C function (`precall' called it) */\n            base = L->base;\n            continue;\n          }\n          default: {\n            return;  /* yield */\n          }\n        }\n      }\n      case OP_RETURN: {\n        int b = GETARG_B(i);\n        if (b != 0) L->top = ra+b-1;\n        if (L->openupval) luaF_close(L, base);\n        L->savedpc = pc;\n        b = luaD_poscall(L, ra);\n        if (--nexeccalls == 0)  /* was previous function running `here'? */\n          return;  /* no: return */\n        else {  /* yes: continue its execution */\n          if (b) L->top = L->ci->top;\n          lua_assert(isLua(L->ci));\n          lua_assert(GET_OPCODE(*((L->ci)->savedpc - 1)) == OP_CALL);\n          goto reentry;\n        }\n      }\n      case OP_FORLOOP: {\n        lua_Number step = nvalue(ra+2);\n        lua_Number idx = luai_numadd(nvalue(ra), step); /* increment index */\n        lua_Number limit = nvalue(ra+1);\n        if (luai_numlt(0, step) ? luai_numle(idx, limit)\n                                : luai_numle(limit, idx)) {\n          dojump(L, pc, GETARG_sBx(i));  /* jump back */\n          setnvalue(ra, idx);  /* update internal index... */\n          setnvalue(ra+3, idx);  /* ...and external index */\n        }\n        continue;\n      }\n      case OP_FORPREP: {\n        const TValue *init = ra;\n        const TValue *plimit = ra+1;\n        const TValue *pstep = ra+2;\n        L->savedpc = pc;  /* next steps may throw errors */\n        if (!tonumber(init, ra))\n          luaG_runerror(L, LUA_QL(\"for\") \" initial value must be a number\");\n        else if (!tonumber(plimit, ra+1))\n          luaG_runerror(L, LUA_QL(\"for\") \" limit must be a number\");\n        else if (!tonumber(pstep, ra+2))\n          luaG_runerror(L, LUA_QL(\"for\") \" step must be a number\");\n        setnvalue(ra, luai_numsub(nvalue(ra), nvalue(pstep)));\n        dojump(L, pc, GETARG_sBx(i));\n        continue;\n      }\n      case OP_TFORLOOP: {\n        StkId cb = ra + 3;  /* call base */\n        setobjs2s(L, cb+2, ra+2);\n        setobjs2s(L, cb+1, ra+1);\n        setobjs2s(L, cb, ra);\n        L->top = cb+3;  /* func. + 2 args (state and index) */\n        Protect(luaD_call(L, cb, GETARG_C(i)));\n        L->top = L->ci->top;\n        cb = RA(i) + 3;  /* previous call may change the stack */\n        if (!ttisnil(cb)) {  /* continue loop? */\n          setobjs2s(L, cb-1, cb);  /* save control variable */\n          dojump(L, pc, GETARG_sBx(*pc));  /* jump back */\n        }\n        pc++;\n        continue;\n      }\n      case OP_SETLIST: {\n        int n = GETARG_B(i);\n        int c = GETARG_C(i);\n        int last;\n        Table *h;\n        if (n == 0) {\n          n = cast_int(L->top - ra) - 1;\n          L->top = L->ci->top;\n        }\n        if (c == 0) c = cast_int(*pc++);\n        runtime_check(L, ttistable(ra));\n        h = hvalue(ra);\n        last = ((c-1)*LFIELDS_PER_FLUSH) + n;\n        if (last > h->sizearray)  /* needs more space? */\n          luaH_resizearray(L, h, last);  /* pre-alloc it at once */\n        for (; n > 0; n--) {\n          TValue *val = ra+n;\n          setobj2t(L, luaH_setnum(L, h, last--), val);\n          luaC_barriert(L, h, val);\n        }\n        continue;\n      }\n      case OP_CLOSE: {\n        luaF_close(L, ra);\n        continue;\n      }\n      case OP_CLOSURE: {\n        Proto *p;\n        Closure *ncl;\n        int nup, j;\n        p = cl->p->p[GETARG_Bx(i)];\n        nup = p->nups;\n        ncl = luaF_newLclosure(L, nup, cl->env);\n        ncl->l.p = p;\n        for (j=0; j<nup; j++, pc++) {\n          if (GET_OPCODE(*pc) == OP_GETUPVAL)\n            ncl->l.upvals[j] = cl->upvals[GETARG_B(*pc)];\n          else {\n            lua_assert(GET_OPCODE(*pc) == OP_MOVE);\n            ncl->l.upvals[j] = luaF_findupval(L, base + GETARG_B(*pc));\n          }\n        }\n        setclvalue(L, ra, ncl);\n        Protect(luaC_checkGC(L));\n        continue;\n      }\n      case OP_VARARG: {\n        int b = GETARG_B(i) - 1;\n        int j;\n        CallInfo *ci = L->ci;\n        int n = cast_int(ci->base - ci->func) - cl->p->numparams - 1;\n        if (b == LUA_MULTRET) {\n          Protect(luaD_checkstack(L, n));\n          ra = RA(i);  /* previous call may change the stack */\n          b = n;\n          L->top = ra + n;\n        }\n        for (j = 0; j < b; j++) {\n          if (j < n) {\n            setobjs2s(L, ra + j, ci->base - n + j);\n          }\n          else {\n            setnilvalue(ra + j);\n          }\n        }\n        continue;\n      }\n    }\n  }\n}\n\n"
  },
  {
    "path": "extern/deprecated/redis-2.8.21/deps/lua/src/lvm.h",
    "content": "/*\n** $Id: lvm.h,v 2.5.1.1 2007/12/27 13:02:25 roberto Exp $\n** Lua virtual machine\n** See Copyright Notice in lua.h\n*/\n\n#ifndef lvm_h\n#define lvm_h\n\n\n#include \"ldo.h\"\n#include \"lobject.h\"\n#include \"ltm.h\"\n\n\n#define tostring(L,o) ((ttype(o) == LUA_TSTRING) || (luaV_tostring(L, o)))\n\n#define tonumber(o,n)\t(ttype(o) == LUA_TNUMBER || \\\n                         (((o) = luaV_tonumber(o,n)) != NULL))\n\n#define equalobj(L,o1,o2) \\\n\t(ttype(o1) == ttype(o2) && luaV_equalval(L, o1, o2))\n\n\nLUAI_FUNC int luaV_lessthan (lua_State *L, const TValue *l, const TValue *r);\nLUAI_FUNC int luaV_equalval (lua_State *L, const TValue *t1, const TValue *t2);\nLUAI_FUNC const TValue *luaV_tonumber (const TValue *obj, TValue *n);\nLUAI_FUNC int luaV_tostring (lua_State *L, StkId obj);\nLUAI_FUNC void luaV_gettable (lua_State *L, const TValue *t, TValue *key,\n                                            StkId val);\nLUAI_FUNC void luaV_settable (lua_State *L, const TValue *t, TValue *key,\n                                            StkId val);\nLUAI_FUNC void luaV_execute (lua_State *L, int nexeccalls);\nLUAI_FUNC void luaV_concat (lua_State *L, int total, int last);\n\n#endif\n"
  },
  {
    "path": "extern/deprecated/redis-2.8.21/deps/lua/src/lzio.c",
    "content": "/*\n** $Id: lzio.c,v 1.31.1.1 2007/12/27 13:02:25 roberto Exp $\n** a generic input stream interface\n** See Copyright Notice in lua.h\n*/\n\n\n#include <string.h>\n\n#define lzio_c\n#define LUA_CORE\n\n#include \"lua.h\"\n\n#include \"llimits.h\"\n#include \"lmem.h\"\n#include \"lstate.h\"\n#include \"lzio.h\"\n\n\nint luaZ_fill (ZIO *z) {\n  size_t size;\n  lua_State *L = z->L;\n  const char *buff;\n  lua_unlock(L);\n  buff = z->reader(L, z->data, &size);\n  lua_lock(L);\n  if (buff == NULL || size == 0) return EOZ;\n  z->n = size - 1;\n  z->p = buff;\n  return char2int(*(z->p++));\n}\n\n\nint luaZ_lookahead (ZIO *z) {\n  if (z->n == 0) {\n    if (luaZ_fill(z) == EOZ)\n      return EOZ;\n    else {\n      z->n++;  /* luaZ_fill removed first byte; put back it */\n      z->p--;\n    }\n  }\n  return char2int(*z->p);\n}\n\n\nvoid luaZ_init (lua_State *L, ZIO *z, lua_Reader reader, void *data) {\n  z->L = L;\n  z->reader = reader;\n  z->data = data;\n  z->n = 0;\n  z->p = NULL;\n}\n\n\n/* --------------------------------------------------------------- read --- */\nsize_t luaZ_read (ZIO *z, void *b, size_t n) {\n  while (n) {\n    size_t m;\n    if (luaZ_lookahead(z) == EOZ)\n      return n;  /* return number of missing bytes */\n    m = (n <= z->n) ? n : z->n;  /* min. between n and z->n */\n    memcpy(b, z->p, m);\n    z->n -= m;\n    z->p += m;\n    b = (char *)b + m;\n    n -= m;\n  }\n  return 0;\n}\n\n/* ------------------------------------------------------------------------ */\nchar *luaZ_openspace (lua_State *L, Mbuffer *buff, size_t n) {\n  if (n > buff->buffsize) {\n    if (n < LUA_MINBUFFER) n = LUA_MINBUFFER;\n    luaZ_resizebuffer(L, buff, n);\n  }\n  return buff->buffer;\n}\n\n\n"
  },
  {
    "path": "extern/deprecated/redis-2.8.21/deps/lua/src/lzio.h",
    "content": "/*\n** $Id: lzio.h,v 1.21.1.1 2007/12/27 13:02:25 roberto Exp $\n** Buffered streams\n** See Copyright Notice in lua.h\n*/\n\n\n#ifndef lzio_h\n#define lzio_h\n\n#include \"lua.h\"\n\n#include \"lmem.h\"\n\n\n#define EOZ\t(-1)\t\t\t/* end of stream */\n\ntypedef struct Zio ZIO;\n\n#define char2int(c)\tcast(int, cast(unsigned char, (c)))\n\n#define zgetc(z)  (((z)->n--)>0 ?  char2int(*(z)->p++) : luaZ_fill(z))\n\ntypedef struct Mbuffer {\n  char *buffer;\n  size_t n;\n  size_t buffsize;\n} Mbuffer;\n\n#define luaZ_initbuffer(L, buff) ((buff)->buffer = NULL, (buff)->buffsize = 0)\n\n#define luaZ_buffer(buff)\t((buff)->buffer)\n#define luaZ_sizebuffer(buff)\t((buff)->buffsize)\n#define luaZ_bufflen(buff)\t((buff)->n)\n\n#define luaZ_resetbuffer(buff) ((buff)->n = 0)\n\n\n#define luaZ_resizebuffer(L, buff, size) \\\n\t(luaM_reallocvector(L, (buff)->buffer, (buff)->buffsize, size, char), \\\n\t(buff)->buffsize = size)\n\n#define luaZ_freebuffer(L, buff)\tluaZ_resizebuffer(L, buff, 0)\n\n\nLUAI_FUNC char *luaZ_openspace (lua_State *L, Mbuffer *buff, size_t n);\nLUAI_FUNC void luaZ_init (lua_State *L, ZIO *z, lua_Reader reader,\n                                        void *data);\nLUAI_FUNC size_t luaZ_read (ZIO* z, void* b, size_t n);\t/* read next n bytes */\nLUAI_FUNC int luaZ_lookahead (ZIO *z);\n\n\n\n/* --------- Private Part ------------------ */\n\nstruct Zio {\n  size_t n;\t\t\t/* bytes still unread */\n  const char *p;\t\t/* current position in buffer */\n  lua_Reader reader;\n  void* data;\t\t\t/* additional data */\n  lua_State *L;\t\t\t/* Lua state (for reader) */\n};\n\n\nLUAI_FUNC int luaZ_fill (ZIO *z);\n\n#endif\n"
  },
  {
    "path": "extern/deprecated/redis-2.8.21/deps/lua/src/print.c",
    "content": "/*\n** $Id: print.c,v 1.55a 2006/05/31 13:30:05 lhf Exp $\n** print bytecodes\n** See Copyright Notice in lua.h\n*/\n\n#include <ctype.h>\n#include <stdio.h>\n\n#define luac_c\n#define LUA_CORE\n\n#include \"ldebug.h\"\n#include \"lobject.h\"\n#include \"lopcodes.h\"\n#include \"lundump.h\"\n\n#define PrintFunction\tluaU_print\n\n#define Sizeof(x)\t((int)sizeof(x))\n#define VOID(p)\t\t((const void*)(p))\n\nstatic void PrintString(const TString* ts)\n{\n const char* s=getstr(ts);\n size_t i,n=ts->tsv.len;\n putchar('\"');\n for (i=0; i<n; i++)\n {\n  int c=s[i];\n  switch (c)\n  {\n   case '\"': printf(\"\\\\\\\"\"); break;\n   case '\\\\': printf(\"\\\\\\\\\"); break;\n   case '\\a': printf(\"\\\\a\"); break;\n   case '\\b': printf(\"\\\\b\"); break;\n   case '\\f': printf(\"\\\\f\"); break;\n   case '\\n': printf(\"\\\\n\"); break;\n   case '\\r': printf(\"\\\\r\"); break;\n   case '\\t': printf(\"\\\\t\"); break;\n   case '\\v': printf(\"\\\\v\"); break;\n   default:\tif (isprint((unsigned char)c))\n   \t\t\tputchar(c);\n\t\telse\n\t\t\tprintf(\"\\\\%03u\",(unsigned char)c);\n  }\n }\n putchar('\"');\n}\n\nstatic void PrintConstant(const Proto* f, int i)\n{\n const TValue* o=&f->k[i];\n switch (ttype(o))\n {\n  case LUA_TNIL:\n\tprintf(\"nil\");\n\tbreak;\n  case LUA_TBOOLEAN:\n\tprintf(bvalue(o) ? \"true\" : \"false\");\n\tbreak;\n  case LUA_TNUMBER:\n\tprintf(LUA_NUMBER_FMT,nvalue(o));\n\tbreak;\n  case LUA_TSTRING:\n\tPrintString(rawtsvalue(o));\n\tbreak;\n  default:\t\t\t\t/* cannot happen */\n\tprintf(\"? type=%d\",ttype(o));\n\tbreak;\n }\n}\n\nstatic void PrintCode(const Proto* f)\n{\n const Instruction* code=f->code;\n int pc,n=f->sizecode;\n for (pc=0; pc<n; pc++)\n {\n  Instruction i=code[pc];\n  OpCode o=GET_OPCODE(i);\n  int a=GETARG_A(i);\n  int b=GETARG_B(i);\n  int c=GETARG_C(i);\n  int bx=GETARG_Bx(i);\n  int sbx=GETARG_sBx(i);\n  int line=getline(f,pc);\n  printf(\"\\t%d\\t\",pc+1);\n  if (line>0) printf(\"[%d]\\t\",line); else printf(\"[-]\\t\");\n  printf(\"%-9s\\t\",luaP_opnames[o]);\n  switch (getOpMode(o))\n  {\n   case iABC:\n    printf(\"%d\",a);\n    if (getBMode(o)!=OpArgN) printf(\" %d\",ISK(b) ? (-1-INDEXK(b)) : b);\n    if (getCMode(o)!=OpArgN) printf(\" %d\",ISK(c) ? (-1-INDEXK(c)) : c);\n    break;\n   case iABx:\n    if (getBMode(o)==OpArgK) printf(\"%d %d\",a,-1-bx); else printf(\"%d %d\",a,bx);\n    break;\n   case iAsBx:\n    if (o==OP_JMP) printf(\"%d\",sbx); else printf(\"%d %d\",a,sbx);\n    break;\n  }\n  switch (o)\n  {\n   case OP_LOADK:\n    printf(\"\\t; \"); PrintConstant(f,bx);\n    break;\n   case OP_GETUPVAL:\n   case OP_SETUPVAL:\n    printf(\"\\t; %s\", (f->sizeupvalues>0) ? getstr(f->upvalues[b]) : \"-\");\n    break;\n   case OP_GETGLOBAL:\n   case OP_SETGLOBAL:\n    printf(\"\\t; %s\",svalue(&f->k[bx]));\n    break;\n   case OP_GETTABLE:\n   case OP_SELF:\n    if (ISK(c)) { printf(\"\\t; \"); PrintConstant(f,INDEXK(c)); }\n    break;\n   case OP_SETTABLE:\n   case OP_ADD:\n   case OP_SUB:\n   case OP_MUL:\n   case OP_DIV:\n   case OP_POW:\n   case OP_EQ:\n   case OP_LT:\n   case OP_LE:\n    if (ISK(b) || ISK(c))\n    {\n     printf(\"\\t; \");\n     if (ISK(b)) PrintConstant(f,INDEXK(b)); else printf(\"-\");\n     printf(\" \");\n     if (ISK(c)) PrintConstant(f,INDEXK(c)); else printf(\"-\");\n    }\n    break;\n   case OP_JMP:\n   case OP_FORLOOP:\n   case OP_FORPREP:\n    printf(\"\\t; to %d\",sbx+pc+2);\n    break;\n   case OP_CLOSURE:\n    printf(\"\\t; %p\",VOID(f->p[bx]));\n    break;\n   case OP_SETLIST:\n    if (c==0) printf(\"\\t; %d\",(int)code[++pc]);\n    else printf(\"\\t; %d\",c);\n    break;\n   default:\n    break;\n  }\n  printf(\"\\n\");\n }\n}\n\n#define SS(x)\t(x==1)?\"\":\"s\"\n#define S(x)\tx,SS(x)\n\nstatic void PrintHeader(const Proto* f)\n{\n const char* s=getstr(f->source);\n if (*s=='@' || *s=='=')\n  s++;\n else if (*s==LUA_SIGNATURE[0])\n  s=\"(bstring)\";\n else\n  s=\"(string)\";\n printf(\"\\n%s <%s:%d,%d> (%d instruction%s, %d bytes at %p)\\n\",\n \t(f->linedefined==0)?\"main\":\"function\",s,\n\tf->linedefined,f->lastlinedefined,\n\tS(f->sizecode),f->sizecode*Sizeof(Instruction),VOID(f));\n printf(\"%d%s param%s, %d slot%s, %d upvalue%s, \",\n\tf->numparams,f->is_vararg?\"+\":\"\",SS(f->numparams),\n\tS(f->maxstacksize),S(f->nups));\n printf(\"%d local%s, %d constant%s, %d function%s\\n\",\n\tS(f->sizelocvars),S(f->sizek),S(f->sizep));\n}\n\nstatic void PrintConstants(const Proto* f)\n{\n int i,n=f->sizek;\n printf(\"constants (%d) for %p:\\n\",n,VOID(f));\n for (i=0; i<n; i++)\n {\n  printf(\"\\t%d\\t\",i+1);\n  PrintConstant(f,i);\n  printf(\"\\n\");\n }\n}\n\nstatic void PrintLocals(const Proto* f)\n{\n int i,n=f->sizelocvars;\n printf(\"locals (%d) for %p:\\n\",n,VOID(f));\n for (i=0; i<n; i++)\n {\n  printf(\"\\t%d\\t%s\\t%d\\t%d\\n\",\n  i,getstr(f->locvars[i].varname),f->locvars[i].startpc+1,f->locvars[i].endpc+1);\n }\n}\n\nstatic void PrintUpvalues(const Proto* f)\n{\n int i,n=f->sizeupvalues;\n printf(\"upvalues (%d) for %p:\\n\",n,VOID(f));\n if (f->upvalues==NULL) return;\n for (i=0; i<n; i++)\n {\n  printf(\"\\t%d\\t%s\\n\",i,getstr(f->upvalues[i]));\n }\n}\n\nvoid PrintFunction(const Proto* f, int full)\n{\n int i,n=f->sizep;\n PrintHeader(f);\n PrintCode(f);\n if (full)\n {\n  PrintConstants(f);\n  PrintLocals(f);\n  PrintUpvalues(f);\n }\n for (i=0; i<n; i++) PrintFunction(f->p[i],full);\n}\n"
  },
  {
    "path": "extern/deprecated/redis-2.8.21/deps/lua/src/strbuf.c",
    "content": "/* strbuf - String buffer routines\n *\n * Copyright (c) 2010-2012  Mark Pulford <mark@kyne.com.au>\n *\n * Permission is hereby granted, free of charge, to any person obtaining\n * a copy of this software and associated documentation files (the\n * \"Software\"), to deal in the Software without restriction, including\n * without limitation the rights to use, copy, modify, merge, publish,\n * distribute, sublicense, and/or sell copies of the Software, and to\n * permit persons to whom the Software is furnished to do so, subject to\n * the following conditions:\n *\n * The above copyright notice and this permission notice shall be\n * included in all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND,\n * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\n * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.\n * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY\n * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,\n * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE\n * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n */\n\n#include <stdio.h>\n#include <stdlib.h>\n#include <stdarg.h>\n#include <string.h>\n\n#include \"strbuf.h\"\n\nstatic void die(const char *fmt, ...)\n{\n    va_list arg;\n\n    va_start(arg, fmt);\n    vfprintf(stderr, fmt, arg);\n    va_end(arg);\n    fprintf(stderr, \"\\n\");\n\n    exit(-1);\n}\n\nvoid strbuf_init(strbuf_t *s, int len)\n{\n    int size;\n\n    if (len <= 0)\n        size = STRBUF_DEFAULT_SIZE;\n    else\n        size = len + 1;         /* \\0 terminator */\n\n    s->buf = NULL;\n    s->size = size;\n    s->length = 0;\n    s->increment = STRBUF_DEFAULT_INCREMENT;\n    s->dynamic = 0;\n    s->reallocs = 0;\n    s->debug = 0;\n\n    s->buf = malloc(size);\n    if (!s->buf)\n        die(\"Out of memory\");\n\n    strbuf_ensure_null(s);\n}\n\nstrbuf_t *strbuf_new(int len)\n{\n    strbuf_t *s;\n\n    s = malloc(sizeof(strbuf_t));\n    if (!s)\n        die(\"Out of memory\");\n\n    strbuf_init(s, len);\n\n    /* Dynamic strbuf allocation / deallocation */\n    s->dynamic = 1;\n\n    return s;\n}\n\nvoid strbuf_set_increment(strbuf_t *s, int increment)\n{\n    /* Increment > 0:  Linear buffer growth rate\n     * Increment < -1: Exponential buffer growth rate */\n    if (increment == 0 || increment == -1)\n        die(\"BUG: Invalid string increment\");\n\n    s->increment = increment;\n}\n\nstatic inline void debug_stats(strbuf_t *s)\n{\n    if (s->debug) {\n        fprintf(stderr, \"strbuf(%lx) reallocs: %d, length: %d, size: %d\\n\",\n                (long)s, s->reallocs, s->length, s->size);\n    }\n}\n\n/* If strbuf_t has not been dynamically allocated, strbuf_free() can\n * be called any number of times strbuf_init() */\nvoid strbuf_free(strbuf_t *s)\n{\n    debug_stats(s);\n\n    if (s->buf) {\n        free(s->buf);\n        s->buf = NULL;\n    }\n    if (s->dynamic)\n        free(s);\n}\n\nchar *strbuf_free_to_string(strbuf_t *s, int *len)\n{\n    char *buf;\n\n    debug_stats(s);\n\n    strbuf_ensure_null(s);\n\n    buf = s->buf;\n    if (len)\n        *len = s->length;\n\n    if (s->dynamic)\n        free(s);\n\n    return buf;\n}\n\nstatic int calculate_new_size(strbuf_t *s, int len)\n{\n    int reqsize, newsize;\n\n    if (len <= 0)\n        die(\"BUG: Invalid strbuf length requested\");\n\n    /* Ensure there is room for optional NULL termination */\n    reqsize = len + 1;\n\n    /* If the user has requested to shrink the buffer, do it exactly */\n    if (s->size > reqsize)\n        return reqsize;\n\n    newsize = s->size;\n    if (s->increment < 0) {\n        /* Exponential sizing */\n        while (newsize < reqsize)\n            newsize *= -s->increment;\n    } else {\n        /* Linear sizing */\n        newsize = ((newsize + s->increment - 1) / s->increment) * s->increment;\n    }\n\n    return newsize;\n}\n\n\n/* Ensure strbuf can handle a string length bytes long (ignoring NULL\n * optional termination). */\nvoid strbuf_resize(strbuf_t *s, int len)\n{\n    int newsize;\n\n    newsize = calculate_new_size(s, len);\n\n    if (s->debug > 1) {\n        fprintf(stderr, \"strbuf(%lx) resize: %d => %d\\n\",\n                (long)s, s->size, newsize);\n    }\n\n    s->size = newsize;\n    s->buf = realloc(s->buf, s->size);\n    if (!s->buf)\n        die(\"Out of memory\");\n    s->reallocs++;\n}\n\nvoid strbuf_append_string(strbuf_t *s, const char *str)\n{\n    int space, i;\n\n    space = strbuf_empty_length(s);\n\n    for (i = 0; str[i]; i++) {\n        if (space < 1) {\n            strbuf_resize(s, s->length + 1);\n            space = strbuf_empty_length(s);\n        }\n\n        s->buf[s->length] = str[i];\n        s->length++;\n        space--;\n    }\n}\n\n/* strbuf_append_fmt() should only be used when an upper bound\n * is known for the output string. */\nvoid strbuf_append_fmt(strbuf_t *s, int len, const char *fmt, ...)\n{\n    va_list arg;\n    int fmt_len;\n\n    strbuf_ensure_empty_length(s, len);\n\n    va_start(arg, fmt);\n    fmt_len = vsnprintf(s->buf + s->length, len, fmt, arg);\n    va_end(arg);\n\n    if (fmt_len < 0)\n        die(\"BUG: Unable to convert number\");  /* This should never happen.. */\n\n    s->length += fmt_len;\n}\n\n/* strbuf_append_fmt_retry() can be used when the there is no known\n * upper bound for the output string. */\nvoid strbuf_append_fmt_retry(strbuf_t *s, const char *fmt, ...)\n{\n    va_list arg;\n    int fmt_len, try;\n    int empty_len;\n\n    /* If the first attempt to append fails, resize the buffer appropriately\n     * and try again */\n    for (try = 0; ; try++) {\n        va_start(arg, fmt);\n        /* Append the new formatted string */\n        /* fmt_len is the length of the string required, excluding the\n         * trailing NULL */\n        empty_len = strbuf_empty_length(s);\n        /* Add 1 since there is also space to store the terminating NULL. */\n        fmt_len = vsnprintf(s->buf + s->length, empty_len + 1, fmt, arg);\n        va_end(arg);\n\n        if (fmt_len <= empty_len)\n            break;  /* SUCCESS */\n        if (try > 0)\n            die(\"BUG: length of formatted string changed\");\n\n        strbuf_resize(s, s->length + fmt_len);\n    }\n\n    s->length += fmt_len;\n}\n\n/* vi:ai et sw=4 ts=4:\n */\n"
  },
  {
    "path": "extern/deprecated/redis-2.8.21/deps/lua/src/strbuf.h",
    "content": "/* strbuf - String buffer routines\n *\n * Copyright (c) 2010-2012  Mark Pulford <mark@kyne.com.au>\n *\n * Permission is hereby granted, free of charge, to any person obtaining\n * a copy of this software and associated documentation files (the\n * \"Software\"), to deal in the Software without restriction, including\n * without limitation the rights to use, copy, modify, merge, publish,\n * distribute, sublicense, and/or sell copies of the Software, and to\n * permit persons to whom the Software is furnished to do so, subject to\n * the following conditions:\n *\n * The above copyright notice and this permission notice shall be\n * included in all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND,\n * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\n * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.\n * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY\n * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,\n * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE\n * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n */\n\n#include <stdlib.h>\n#include <stdarg.h>\n\n/* Size: Total bytes allocated to *buf\n * Length: String length, excluding optional NULL terminator.\n * Increment: Allocation increments when resizing the string buffer.\n * Dynamic: True if created via strbuf_new()\n */\n\ntypedef struct {\n    char *buf;\n    int size;\n    int length;\n    int increment;\n    int dynamic;\n    int reallocs;\n    int debug;\n} strbuf_t;\n\n#ifndef STRBUF_DEFAULT_SIZE\n#define STRBUF_DEFAULT_SIZE 1023\n#endif\n#ifndef STRBUF_DEFAULT_INCREMENT\n#define STRBUF_DEFAULT_INCREMENT -2\n#endif\n\n/* Initialise */\nextern strbuf_t *strbuf_new(int len);\nextern void strbuf_init(strbuf_t *s, int len);\nextern void strbuf_set_increment(strbuf_t *s, int increment);\n\n/* Release */\nextern void strbuf_free(strbuf_t *s);\nextern char *strbuf_free_to_string(strbuf_t *s, int *len);\n\n/* Management */\nextern void strbuf_resize(strbuf_t *s, int len);\nstatic int strbuf_empty_length(strbuf_t *s);\nstatic int strbuf_length(strbuf_t *s);\nstatic char *strbuf_string(strbuf_t *s, int *len);\nstatic void strbuf_ensure_empty_length(strbuf_t *s, int len);\nstatic char *strbuf_empty_ptr(strbuf_t *s);\nstatic void strbuf_extend_length(strbuf_t *s, int len);\n\n/* Update */\nextern void strbuf_append_fmt(strbuf_t *s, int len, const char *fmt, ...);\nextern void strbuf_append_fmt_retry(strbuf_t *s, const char *format, ...);\nstatic void strbuf_append_mem(strbuf_t *s, const char *c, int len);\nextern void strbuf_append_string(strbuf_t *s, const char *str);\nstatic void strbuf_append_char(strbuf_t *s, const char c);\nstatic void strbuf_ensure_null(strbuf_t *s);\n\n/* Reset string for before use */\nstatic inline void strbuf_reset(strbuf_t *s)\n{\n    s->length = 0;\n}\n\nstatic inline int strbuf_allocated(strbuf_t *s)\n{\n    return s->buf != NULL;\n}\n\n/* Return bytes remaining in the string buffer\n * Ensure there is space for a NULL terminator. */\nstatic inline int strbuf_empty_length(strbuf_t *s)\n{\n    return s->size - s->length - 1;\n}\n\nstatic inline void strbuf_ensure_empty_length(strbuf_t *s, int len)\n{\n    if (len > strbuf_empty_length(s))\n        strbuf_resize(s, s->length + len);\n}\n\nstatic inline char *strbuf_empty_ptr(strbuf_t *s)\n{\n    return s->buf + s->length;\n}\n\nstatic inline void strbuf_extend_length(strbuf_t *s, int len)\n{\n    s->length += len;\n}\n\nstatic inline int strbuf_length(strbuf_t *s)\n{\n    return s->length;\n}\n\nstatic inline void strbuf_append_char(strbuf_t *s, const char c)\n{\n    strbuf_ensure_empty_length(s, 1);\n    s->buf[s->length++] = c;\n}\n\nstatic inline void strbuf_append_char_unsafe(strbuf_t *s, const char c)\n{\n    s->buf[s->length++] = c;\n}\n\nstatic inline void strbuf_append_mem(strbuf_t *s, const char *c, int len)\n{\n    strbuf_ensure_empty_length(s, len);\n    memcpy(s->buf + s->length, c, len);\n    s->length += len;\n}\n\nstatic inline void strbuf_append_mem_unsafe(strbuf_t *s, const char *c, int len)\n{\n    memcpy(s->buf + s->length, c, len);\n    s->length += len;\n}\n\nstatic inline void strbuf_ensure_null(strbuf_t *s)\n{\n    s->buf[s->length] = 0;\n}\n\nstatic inline char *strbuf_string(strbuf_t *s, int *len)\n{\n    if (len)\n        *len = s->length;\n\n    return s->buf;\n}\n\n/* vi:ai et sw=4 ts=4:\n */\n"
  },
  {
    "path": "extern/deprecated/redis-2.8.21/deps/lua/test/README",
    "content": "These are simple tests for Lua.  Some of them contain useful code.\nThey are meant to be run to make sure Lua is built correctly and also\nto be read, to see how Lua programs look.\n\nHere is a one-line summary of each program:\n\n   bisect.lua\t\tbisection method for solving non-linear equations\n   cf.lua\t\ttemperature conversion table (celsius to farenheit)\n   echo.lua             echo command line arguments\n   env.lua              environment variables as automatic global variables\n   factorial.lua\tfactorial without recursion\n   fib.lua\t\tfibonacci function with cache\n   fibfor.lua\t\tfibonacci numbers with coroutines and generators\n   globals.lua\t\treport global variable usage\n   hello.lua\t\tthe first program in every language\n   life.lua\t\tConway's Game of Life\n   luac.lua\t \tbare-bones luac\n   printf.lua\t\tan implementation of printf\n   readonly.lua\t\tmake global variables readonly\n   sieve.lua\t\tthe sieve of of Eratosthenes programmed with coroutines\n   sort.lua\t\ttwo implementations of a sort function\n   table.lua\t\tmake table, grouping all data for the same item\n   trace-calls.lua\ttrace calls\n   trace-globals.lua\ttrace assigments to global variables\n   xd.lua\t\thex dump\n\n"
  },
  {
    "path": "extern/deprecated/redis-2.8.21/deps/lua/test/bisect.lua",
    "content": "-- bisection method for solving non-linear equations\n\ndelta=1e-6\t-- tolerance\n\nfunction bisect(f,a,b,fa,fb)\n local c=(a+b)/2\n io.write(n,\" c=\",c,\" a=\",a,\" b=\",b,\"\\n\")\n if c==a or c==b or math.abs(a-b)<delta then return c,b-a end\n n=n+1\n local fc=f(c)\n if fa*fc<0 then return bisect(f,a,c,fa,fc) else return bisect(f,c,b,fc,fb) end\nend\n\n-- find root of f in the inverval [a,b]. needs f(a)*f(b)<0\nfunction solve(f,a,b)\n n=0\n local z,e=bisect(f,a,b,f(a),f(b))\n io.write(string.format(\"after %d steps, root is %.17g with error %.1e, f=%.1e\\n\",n,z,e,f(z)))\nend\n\n-- our function\nfunction f(x)\n return x*x*x-x-1\nend\n\n-- find zero in [1,2]\nsolve(f,1,2)\n"
  },
  {
    "path": "extern/deprecated/redis-2.8.21/deps/lua/test/cf.lua",
    "content": "-- temperature conversion table (celsius to farenheit)\n\nfor c0=-20,50-1,10 do\n\tio.write(\"C \")\n\tfor c=c0,c0+10-1 do\n\t\tio.write(string.format(\"%3.0f \",c))\n\tend\n\tio.write(\"\\n\")\n\t\n\tio.write(\"F \")\n\tfor c=c0,c0+10-1 do\n\t\tf=(9/5)*c+32\n\t\tio.write(string.format(\"%3.0f \",f))\n\tend\n\tio.write(\"\\n\\n\")\nend\n"
  },
  {
    "path": "extern/deprecated/redis-2.8.21/deps/lua/test/echo.lua",
    "content": "-- echo command line arguments\n\nfor i=0,table.getn(arg) do\n print(i,arg[i])\nend\n"
  },
  {
    "path": "extern/deprecated/redis-2.8.21/deps/lua/test/env.lua",
    "content": "-- read environment variables as if they were global variables\n\nlocal f=function (t,i) return os.getenv(i) end\nsetmetatable(getfenv(),{__index=f})\n\n-- an example\nprint(a,USER,PATH)\n"
  },
  {
    "path": "extern/deprecated/redis-2.8.21/deps/lua/test/factorial.lua",
    "content": "-- function closures are powerful\n\n-- traditional fixed-point operator from functional programming\nY = function (g)\n      local a = function (f) return f(f) end\n      return a(function (f)\n                 return g(function (x)\n                             local c=f(f)\n                             return c(x)\n                           end)\n               end)\nend\n\n\n-- factorial without recursion\nF = function (f)\n      return function (n)\n               if n == 0 then return 1\n               else return n*f(n-1) end\n             end\n    end\n\nfactorial = Y(F)   -- factorial is the fixed point of F\n\n-- now test it\nfunction test(x)\n\tio.write(x,\"! = \",factorial(x),\"\\n\")\nend\n\nfor n=0,16 do\n\ttest(n)\nend\n"
  },
  {
    "path": "extern/deprecated/redis-2.8.21/deps/lua/test/fib.lua",
    "content": "-- fibonacci function with cache\n\n-- very inefficient fibonacci function\nfunction fib(n)\n\tN=N+1\n\tif n<2 then\n\t\treturn n\n\telse\n\t\treturn fib(n-1)+fib(n-2)\n\tend\nend\n\n-- a general-purpose value cache\nfunction cache(f)\n\tlocal c={}\n\treturn function (x)\n\t\tlocal y=c[x]\n\t\tif not y then\n\t\t\ty=f(x)\n\t\t\tc[x]=y\n\t\tend\n\t\treturn y\n\tend\nend\n\n-- run and time it\nfunction test(s,f)\n\tN=0\n\tlocal c=os.clock()\n\tlocal v=f(n)\n\tlocal t=os.clock()-c\n\tprint(s,n,v,t,N)\nend\n\nn=arg[1] or 24\t\t-- for other values, do lua fib.lua XX\nn=tonumber(n)\nprint(\"\",\"n\",\"value\",\"time\",\"evals\")\ntest(\"plain\",fib)\nfib=cache(fib)\ntest(\"cached\",fib)\n"
  },
  {
    "path": "extern/deprecated/redis-2.8.21/deps/lua/test/fibfor.lua",
    "content": "-- example of for with generator functions\n\nfunction generatefib (n)\n  return coroutine.wrap(function ()\n    local a,b = 1, 1\n    while a <= n do\n      coroutine.yield(a)\n      a, b = b, a+b\n    end\n  end)\nend\n\nfor i in generatefib(1000) do print(i) end\n"
  },
  {
    "path": "extern/deprecated/redis-2.8.21/deps/lua/test/globals.lua",
    "content": "-- reads luac listings and reports global variable usage\n-- lines where a global is written to are marked with \"*\"\n-- typical usage: luac -p -l file.lua | lua globals.lua | sort | lua table.lua\n\nwhile 1 do\n local s=io.read()\n if s==nil then break end\n local ok,_,l,op,g=string.find(s,\"%[%-?(%d*)%]%s*([GS])ETGLOBAL.-;%s+(.*)$\")\n if ok then\n  if op==\"S\" then op=\"*\" else op=\"\" end\n  io.write(g,\"\\t\",l,op,\"\\n\")\n end\nend\n"
  },
  {
    "path": "extern/deprecated/redis-2.8.21/deps/lua/test/hello.lua",
    "content": "-- the first program in every language\n\nio.write(\"Hello world, from \",_VERSION,\"!\\n\")\n"
  },
  {
    "path": "extern/deprecated/redis-2.8.21/deps/lua/test/life.lua",
    "content": "-- life.lua\n-- original by Dave Bollinger <DBollinger@compuserve.com> posted to lua-l\n-- modified to use ANSI terminal escape sequences\n-- modified to use for instead of while\n\nlocal write=io.write\n\nALIVE=\"\"\tDEAD=\"\"\nALIVE=\"O\"\tDEAD=\"-\"\n\nfunction delay() -- NOTE: SYSTEM-DEPENDENT, adjust as necessary\n  for i=1,10000 do end\n  -- local i=os.clock()+1 while(os.clock()<i) do end\nend\n\nfunction ARRAY2D(w,h)\n  local t = {w=w,h=h}\n  for y=1,h do\n    t[y] = {}\n    for x=1,w do\n      t[y][x]=0\n    end\n  end\n  return t\nend\n\n_CELLS = {}\n\n-- give birth to a \"shape\" within the cell array\nfunction _CELLS:spawn(shape,left,top)\n  for y=0,shape.h-1 do\n    for x=0,shape.w-1 do\n      self[top+y][left+x] = shape[y*shape.w+x+1]\n    end\n  end\nend\n\n-- run the CA and produce the next generation\nfunction _CELLS:evolve(next)\n  local ym1,y,yp1,yi=self.h-1,self.h,1,self.h\n  while yi > 0 do\n    local xm1,x,xp1,xi=self.w-1,self.w,1,self.w\n    while xi > 0 do\n      local sum = self[ym1][xm1] + self[ym1][x] + self[ym1][xp1] +\n                  self[y][xm1] + self[y][xp1] +\n                  self[yp1][xm1] + self[yp1][x] + self[yp1][xp1]\n      next[y][x] = ((sum==2) and self[y][x]) or ((sum==3) and 1) or 0\n      xm1,x,xp1,xi = x,xp1,xp1+1,xi-1\n    end\n    ym1,y,yp1,yi = y,yp1,yp1+1,yi-1\n  end\nend\n\n-- output the array to screen\nfunction _CELLS:draw()\n  local out=\"\" -- accumulate to reduce flicker\n  for y=1,self.h do\n   for x=1,self.w do\n      out=out..(((self[y][x]>0) and ALIVE) or DEAD)\n    end\n    out=out..\"\\n\"\n  end\n  write(out)\nend\n\n-- constructor\nfunction CELLS(w,h)\n  local c = ARRAY2D(w,h)\n  c.spawn = _CELLS.spawn\n  c.evolve = _CELLS.evolve\n  c.draw = _CELLS.draw\n  return c\nend\n\n--\n-- shapes suitable for use with spawn() above\n--\nHEART = { 1,0,1,1,0,1,1,1,1; w=3,h=3 }\nGLIDER = { 0,0,1,1,0,1,0,1,1; w=3,h=3 }\nEXPLODE = { 0,1,0,1,1,1,1,0,1,0,1,0; w=3,h=4 }\nFISH = { 0,1,1,1,1,1,0,0,0,1,0,0,0,0,1,1,0,0,1,0; w=5,h=4 }\nBUTTERFLY = { 1,0,0,0,1,0,1,1,1,0,1,0,0,0,1,1,0,1,0,1,1,0,0,0,1; w=5,h=5 }\n\n-- the main routine\nfunction LIFE(w,h)\n  -- create two arrays\n  local thisgen = CELLS(w,h)\n  local nextgen = CELLS(w,h)\n\n  -- create some life\n  -- about 1000 generations of fun, then a glider steady-state\n  thisgen:spawn(GLIDER,5,4)\n  thisgen:spawn(EXPLODE,25,10)\n  thisgen:spawn(FISH,4,12)\n\n  -- run until break\n  local gen=1\n  write(\"\\027[2J\")\t-- ANSI clear screen\n  while 1 do\n    thisgen:evolve(nextgen)\n    thisgen,nextgen = nextgen,thisgen\n    write(\"\\027[H\")\t-- ANSI home cursor\n    thisgen:draw()\n    write(\"Life - generation \",gen,\"\\n\")\n    gen=gen+1\n    if gen>2000 then break end\n    --delay()\t\t-- no delay\n  end\nend\n\nLIFE(40,20)\n"
  },
  {
    "path": "extern/deprecated/redis-2.8.21/deps/lua/test/luac.lua",
    "content": "-- bare-bones luac in Lua\n-- usage: lua luac.lua file.lua\n\nassert(arg[1]~=nil and arg[2]==nil,\"usage: lua luac.lua file.lua\")\nf=assert(io.open(\"luac.out\",\"wb\"))\nassert(f:write(string.dump(assert(loadfile(arg[1])))))\nassert(f:close())\n"
  },
  {
    "path": "extern/deprecated/redis-2.8.21/deps/lua/test/printf.lua",
    "content": "-- an implementation of printf\n\nfunction printf(...)\n io.write(string.format(...))\nend\n\nprintf(\"Hello %s from %s on %s\\n\",os.getenv\"USER\" or \"there\",_VERSION,os.date())\n"
  },
  {
    "path": "extern/deprecated/redis-2.8.21/deps/lua/test/readonly.lua",
    "content": "-- make global variables readonly\n\nlocal f=function (t,i) error(\"cannot redefine global variable `\"..i..\"'\",2) end\nlocal g={}\nlocal G=getfenv()\nsetmetatable(g,{__index=G,__newindex=f})\nsetfenv(1,g)\n\n-- an example\nrawset(g,\"x\",3)\nx=2\ny=1\t-- cannot redefine `y'\n"
  },
  {
    "path": "extern/deprecated/redis-2.8.21/deps/lua/test/sieve.lua",
    "content": "-- the sieve of of Eratosthenes programmed with coroutines\n-- typical usage: lua -e N=1000 sieve.lua | column\n\n-- generate all the numbers from 2 to n\nfunction gen (n)\n  return coroutine.wrap(function ()\n    for i=2,n do coroutine.yield(i) end\n  end)\nend\n\n-- filter the numbers generated by `g', removing multiples of `p'\nfunction filter (p, g)\n  return coroutine.wrap(function ()\n    while 1 do\n      local n = g()\n      if n == nil then return end\n      if math.mod(n, p) ~= 0 then coroutine.yield(n) end\n    end\n  end)\nend\n\nN=N or 1000\t\t-- from command line\nx = gen(N)\t\t-- generate primes up to N\nwhile 1 do\n  local n = x()\t\t-- pick a number until done\n  if n == nil then break end\n  print(n)\t\t-- must be a prime number\n  x = filter(n, x)\t-- now remove its multiples\nend\n"
  },
  {
    "path": "extern/deprecated/redis-2.8.21/deps/lua/test/sort.lua",
    "content": "-- two implementations of a sort function\n-- this is an example only. Lua has now a built-in function \"sort\"\n\n-- extracted from Programming Pearls, page 110\nfunction qsort(x,l,u,f)\n if l<u then\n  local m=math.random(u-(l-1))+l-1\t-- choose a random pivot in range l..u\n  x[l],x[m]=x[m],x[l]\t\t\t-- swap pivot to first position\n  local t=x[l]\t\t\t\t-- pivot value\n  m=l\n  local i=l+1\n  while i<=u do\n    -- invariant: x[l+1..m] < t <= x[m+1..i-1]\n    if f(x[i],t) then\n      m=m+1\n      x[m],x[i]=x[i],x[m]\t\t-- swap x[i] and x[m]\n    end\n    i=i+1\n  end\n  x[l],x[m]=x[m],x[l]\t\t\t-- swap pivot to a valid place\n  -- x[l+1..m-1] < x[m] <= x[m+1..u]\n  qsort(x,l,m-1,f)\n  qsort(x,m+1,u,f)\n end\nend\n\nfunction selectionsort(x,n,f)\n local i=1\n while i<=n do\n  local m,j=i,i+1\n  while j<=n do\n   if f(x[j],x[m]) then m=j end\n   j=j+1\n  end\n x[i],x[m]=x[m],x[i]\t\t\t-- swap x[i] and x[m]\n i=i+1\n end\nend\n\nfunction show(m,x)\n io.write(m,\"\\n\\t\")\n local i=1\n while x[i] do\n  io.write(x[i])\n  i=i+1\n  if x[i] then io.write(\",\") end\n end\n io.write(\"\\n\")\nend\n\nfunction testsorts(x)\n local n=1\n while x[n] do n=n+1 end; n=n-1\t\t-- count elements\n show(\"original\",x)\n qsort(x,1,n,function (x,y) return x<y end)\n show(\"after quicksort\",x)\n selectionsort(x,n,function (x,y) return x>y end)\n show(\"after reverse selection sort\",x)\n qsort(x,1,n,function (x,y) return x<y end)\n show(\"after quicksort again\",x)\nend\n\n-- array to be sorted\nx={\"Jan\",\"Feb\",\"Mar\",\"Apr\",\"May\",\"Jun\",\"Jul\",\"Aug\",\"Sep\",\"Oct\",\"Nov\",\"Dec\"}\n\ntestsorts(x)\n"
  },
  {
    "path": "extern/deprecated/redis-2.8.21/deps/lua/test/table.lua",
    "content": "-- make table, grouping all data for the same item\n-- input is 2 columns (item, data)\n\nlocal A\nwhile 1 do\n local l=io.read()\n if l==nil then break end\n local _,_,a,b=string.find(l,'\"?([_%w]+)\"?%s*(.*)$')\n if a~=A then A=a io.write(\"\\n\",a,\":\") end\n io.write(\" \",b)\nend\nio.write(\"\\n\")\n"
  },
  {
    "path": "extern/deprecated/redis-2.8.21/deps/lua/test/trace-calls.lua",
    "content": "-- trace calls\n-- example: lua -ltrace-calls bisect.lua\n\nlocal level=0\n\nlocal function hook(event)\n local t=debug.getinfo(3)\n io.write(level,\" >>> \",string.rep(\" \",level))\n if t~=nil and t.currentline>=0 then io.write(t.short_src,\":\",t.currentline,\" \") end\n t=debug.getinfo(2)\n if event==\"call\" then\n  level=level+1\n else\n  level=level-1 if level<0 then level=0 end\n end\n if t.what==\"main\" then\n  if event==\"call\" then\n   io.write(\"begin \",t.short_src)\n  else\n   io.write(\"end \",t.short_src)\n  end\n elseif t.what==\"Lua\" then\n-- table.foreach(t,print)\n  io.write(event,\" \",t.name or \"(Lua)\",\" <\",t.linedefined,\":\",t.short_src,\">\")\n else\n io.write(event,\" \",t.name or \"(C)\",\" [\",t.what,\"] \")\n end\n io.write(\"\\n\")\nend\n\ndebug.sethook(hook,\"cr\")\nlevel=0\n"
  },
  {
    "path": "extern/deprecated/redis-2.8.21/deps/lua/test/trace-globals.lua",
    "content": "-- trace assigments to global variables\n\ndo\n -- a tostring that quotes strings. note the use of the original tostring.\n local _tostring=tostring\n local tostring=function(a)\n  if type(a)==\"string\" then\n   return string.format(\"%q\",a)\n  else\n   return _tostring(a)\n  end\n end\n\n local log=function (name,old,new)\n  local t=debug.getinfo(3,\"Sl\")\n  local line=t.currentline\n  io.write(t.short_src)\n  if line>=0 then io.write(\":\",line) end\n  io.write(\": \",name,\" is now \",tostring(new),\" (was \",tostring(old),\")\",\"\\n\")\n end\n\n local g={}\n local set=function (t,name,value)\n  log(name,g[name],value)\n  g[name]=value\n end\n setmetatable(getfenv(),{__index=g,__newindex=set})\nend\n\n-- an example\n\na=1\nb=2\na=10\nb=20\nb=nil\nb=200\nprint(a,b,c)\n"
  },
  {
    "path": "extern/deprecated/redis-2.8.21/deps/lua/test/xd.lua",
    "content": "-- hex dump\n-- usage: lua xd.lua < file\n\nlocal offset=0\nwhile true do\n local s=io.read(16)\n if s==nil then return end\n io.write(string.format(\"%08X  \",offset))\n string.gsub(s,\"(.)\",\n\tfunction (c) io.write(string.format(\"%02X \",string.byte(c))) end)\n io.write(string.rep(\" \",3*(16-string.len(s))))\n io.write(\" \",string.gsub(s,\"%c\",\".\"),\"\\n\") \n offset=offset+16\nend\n"
  },
  {
    "path": "extern/deprecated/redis-2.8.21/deps/update-jemalloc.sh",
    "content": "#!/bin/bash\nVER=$1\nURL=\"http://www.canonware.com/download/jemalloc/jemalloc-${VER}.tar.bz2\"\necho \"Downloading $URL\"\ncurl $URL > /tmp/jemalloc.tar.bz2\ntar xvjf /tmp/jemalloc.tar.bz2\nrm -rf jemalloc\nmv jemalloc-${VER} jemalloc\necho \"Use git status, add all files and commit changes.\"\n"
  },
  {
    "path": "extern/deprecated/redis-2.8.21/redis.conf",
    "content": "# Redis configuration file example\n\n# Note on units: when memory size is needed, it is possible to specify\n# it in the usual form of 1k 5GB 4M and so forth:\n#\n# 1k => 1000 bytes\n# 1kb => 1024 bytes\n# 1m => 1000000 bytes\n# 1mb => 1024*1024 bytes\n# 1g => 1000000000 bytes\n# 1gb => 1024*1024*1024 bytes\n#\n# units are case insensitive so 1GB 1Gb 1gB are all the same.\n\n################################## INCLUDES ###################################\n\n# Include one or more other config files here.  This is useful if you\n# have a standard template that goes to all Redis servers but also need\n# to customize a few per-server settings.  Include files can include\n# other files, so use this wisely.\n#\n# Notice option \"include\" won't be rewritten by command \"CONFIG REWRITE\"\n# from admin or Redis Sentinel. Since Redis always uses the last processed\n# line as value of a configuration directive, you'd better put includes\n# at the beginning of this file to avoid overwriting config change at runtime.\n#\n# If instead you are interested in using includes to override configuration\n# options, it is better to use include as the last line.\n#\n# include /path/to/local.conf\n# include /path/to/other.conf\n\n################################ GENERAL  #####################################\n\n# By default Redis does not run as a daemon. Use 'yes' if you need it.\n# Note that Redis will write a pid file in /var/run/redis.pid when daemonized.\ndaemonize yes\n\n# When running daemonized, Redis writes a pid file in /var/run/redis.pid by\n# default. You can specify a custom pid file location here.\npidfile /var/run/redis.pid\n\n# Accept connections on the specified port, default is 6379.\n# If port 0 is specified Redis will not listen on a TCP socket.\nport 6379\n\n# TCP listen() backlog.\n#\n# In high requests-per-second environments you need an high backlog in order\n# to avoid slow clients connections issues. Note that the Linux kernel\n# will silently truncate it to the value of /proc/sys/net/core/somaxconn so\n# make sure to raise both the value of somaxconn and tcp_max_syn_backlog\n# in order to get the desired effect.\ntcp-backlog 511\n\n# By default Redis listens for connections from all the network interfaces\n# available on the server. It is possible to listen to just one or multiple\n# interfaces using the \"bind\" configuration directive, followed by one or\n# more IP addresses.\n#\n# Examples:\n#\n# bind 192.168.1.100 10.0.0.1\n# bind 127.0.0.1\n\n# Specify the path for the Unix socket that will be used to listen for\n# incoming connections. There is no default, so Redis will not listen\n# on a unix socket when not specified.\n#\n# unixsocket /tmp/redis.sock\n# unixsocketperm 700\n\n# Close the connection after a client is idle for N seconds (0 to disable)\ntimeout 0\n\n# TCP keepalive.\n#\n# If non-zero, use SO_KEEPALIVE to send TCP ACKs to clients in absence\n# of communication. This is useful for two reasons:\n#\n# 1) Detect dead peers.\n# 2) Take the connection alive from the point of view of network\n#    equipment in the middle.\n#\n# On Linux, the specified value (in seconds) is the period used to send ACKs.\n# Note that to close the connection the double of the time is needed.\n# On other kernels the period depends on the kernel configuration.\n#\n# A reasonable value for this option is 60 seconds.\ntcp-keepalive 0\n\n# Specify the server verbosity level.\n# This can be one of:\n# debug (a lot of information, useful for development/testing)\n# verbose (many rarely useful info, but not a mess like the debug level)\n# notice (moderately verbose, what you want in production probably)\n# warning (only very important / critical messages are logged)\nloglevel notice\n\n# Specify the log file name. Also the empty string can be used to force\n# Redis to log on the standard output. Note that if you use standard\n# output for logging but daemonize, logs will be sent to /dev/null\nlogfile \"\"\n\n# To enable logging to the system logger, just set 'syslog-enabled' to yes,\n# and optionally update the other syslog parameters to suit your needs.\n# syslog-enabled no\n\n# Specify the syslog identity.\n# syslog-ident redis\n\n# Specify the syslog facility. Must be USER or between LOCAL0-LOCAL7.\n# syslog-facility local0\n\n# Set the number of databases. The default database is DB 0, you can select\n# a different one on a per-connection basis using SELECT <dbid> where\n# dbid is a number between 0 and 'databases'-1\ndatabases 16\n\n################################ SNAPSHOTTING  ################################\n#\n# Save the DB on disk:\n#\n#   save <seconds> <changes>\n#\n#   Will save the DB if both the given number of seconds and the given\n#   number of write operations against the DB occurred.\n#\n#   In the example below the behaviour will be to save:\n#   after 900 sec (15 min) if at least 1 key changed\n#   after 300 sec (5 min) if at least 10 keys changed\n#   after 60 sec if at least 10000 keys changed\n#\n#   Note: you can disable saving completely by commenting out all \"save\" lines.\n#\n#   It is also possible to remove all the previously configured save\n#   points by adding a save directive with a single empty string argument\n#   like in the following example:\n#\n#   save \"\"\n\nsave 900 1\nsave 300 10\nsave 60 10000\n\n# By default Redis will stop accepting writes if RDB snapshots are enabled\n# (at least one save point) and the latest background save failed.\n# This will make the user aware (in a hard way) that data is not persisting\n# on disk properly, otherwise chances are that no one will notice and some\n# disaster will happen.\n#\n# If the background saving process will start working again Redis will\n# automatically allow writes again.\n#\n# However if you have setup your proper monitoring of the Redis server\n# and persistence, you may want to disable this feature so that Redis will\n# continue to work as usual even if there are problems with disk,\n# permissions, and so forth.\nstop-writes-on-bgsave-error yes\n\n# Compress string objects using LZF when dump .rdb databases?\n# For default that's set to 'yes' as it's almost always a win.\n# If you want to save some CPU in the saving child set it to 'no' but\n# the dataset will likely be bigger if you have compressible values or keys.\nrdbcompression yes\n\n# Since version 5 of RDB a CRC64 checksum is placed at the end of the file.\n# This makes the format more resistant to corruption but there is a performance\n# hit to pay (around 10%) when saving and loading RDB files, so you can disable it\n# for maximum performances.\n#\n# RDB files created with checksum disabled have a checksum of zero that will\n# tell the loading code to skip the check.\nrdbchecksum yes\n\n# The filename where to dump the DB\ndbfilename dump.rdb\n\n# The working directory.\n#\n# The DB will be written inside this directory, with the filename specified\n# above using the 'dbfilename' configuration directive.\n#\n# The Append Only File will also be created inside this directory.\n#\n# Note that you must specify a directory here, not a file name.\ndir ./\n\n################################# REPLICATION #################################\n\n# Master-Slave replication. Use slaveof to make a Redis instance a copy of\n# another Redis server. A few things to understand ASAP about Redis replication.\n#\n# 1) Redis replication is asynchronous, but you can configure a master to\n#    stop accepting writes if it appears to be not connected with at least\n#    a given number of slaves.\n# 2) Redis slaves are able to perform a partial resynchronization with the\n#    master if the replication link is lost for a relatively small amount of\n#    time. You may want to configure the replication backlog size (see the next\n#    sections of this file) with a sensible value depending on your needs.\n# 3) Replication is automatic and does not need user intervention. After a\n#    network partition slaves automatically try to reconnect to masters\n#    and resynchronize with them.\n#\n# slaveof <masterip> <masterport>\n\n# If the master is password protected (using the \"requirepass\" configuration\n# directive below) it is possible to tell the slave to authenticate before\n# starting the replication synchronization process, otherwise the master will\n# refuse the slave request.\n#\n# masterauth <master-password>\n\n# When a slave loses its connection with the master, or when the replication\n# is still in progress, the slave can act in two different ways:\n#\n# 1) if slave-serve-stale-data is set to 'yes' (the default) the slave will\n#    still reply to client requests, possibly with out of date data, or the\n#    data set may just be empty if this is the first synchronization.\n#\n# 2) if slave-serve-stale-data is set to 'no' the slave will reply with\n#    an error \"SYNC with master in progress\" to all the kind of commands\n#    but to INFO and SLAVEOF.\n#\nslave-serve-stale-data yes\n\n# You can configure a slave instance to accept writes or not. Writing against\n# a slave instance may be useful to store some ephemeral data (because data\n# written on a slave will be easily deleted after resync with the master) but\n# may also cause problems if clients are writing to it because of a\n# misconfiguration.\n#\n# Since Redis 2.6 by default slaves are read-only.\n#\n# Note: read only slaves are not designed to be exposed to untrusted clients\n# on the internet. It's just a protection layer against misuse of the instance.\n# Still a read only slave exports by default all the administrative commands\n# such as CONFIG, DEBUG, and so forth. To a limited extent you can improve\n# security of read only slaves using 'rename-command' to shadow all the\n# administrative / dangerous commands.\nslave-read-only yes\n\n# Replication SYNC strategy: disk or socket.\n#\n# -------------------------------------------------------\n# WARNING: DISKLESS REPLICATION IS EXPERIMENTAL CURRENTLY\n# -------------------------------------------------------\n#\n# New slaves and reconnecting slaves that are not able to continue the replication\n# process just receiving differences, need to do what is called a \"full\n# synchronization\". An RDB file is transmitted from the master to the slaves.\n# The transmission can happen in two different ways:\n#\n# 1) Disk-backed: The Redis master creates a new process that writes the RDB\n#                 file on disk. Later the file is transferred by the parent\n#                 process to the slaves incrementally.\n# 2) Diskless: The Redis master creates a new process that directly writes the\n#              RDB file to slave sockets, without touching the disk at all.\n#\n# With disk-backed replication, while the RDB file is generated, more slaves\n# can be queued and served with the RDB file as soon as the current child producing\n# the RDB file finishes its work. With diskless replication instead once\n# the transfer starts, new slaves arriving will be queued and a new transfer\n# will start when the current one terminates.\n#\n# When diskless replication is used, the master waits a configurable amount of\n# time (in seconds) before starting the transfer in the hope that multiple slaves\n# will arrive and the transfer can be parallelized.\n#\n# With slow disks and fast (large bandwidth) networks, diskless replication\n# works better.\nrepl-diskless-sync no\n\n# When diskless replication is enabled, it is possible to configure the delay\n# the server waits in order to spawn the child that trnasfers the RDB via socket\n# to the slaves.\n#\n# This is important since once the transfer starts, it is not possible to serve\n# new slaves arriving, that will be queued for the next RDB transfer, so the server\n# waits a delay in order to let more slaves arrive.\n#\n# The delay is specified in seconds, and by default is 5 seconds. To disable\n# it entirely just set it to 0 seconds and the transfer will start ASAP.\nrepl-diskless-sync-delay 5\n\n# Slaves send PINGs to server in a predefined interval. It's possible to change\n# this interval with the repl_ping_slave_period option. The default value is 10\n# seconds.\n#\n# repl-ping-slave-period 10\n\n# The following option sets the replication timeout for:\n#\n# 1) Bulk transfer I/O during SYNC, from the point of view of slave.\n# 2) Master timeout from the point of view of slaves (data, pings).\n# 3) Slave timeout from the point of view of masters (REPLCONF ACK pings).\n#\n# It is important to make sure that this value is greater than the value\n# specified for repl-ping-slave-period otherwise a timeout will be detected\n# every time there is low traffic between the master and the slave.\n#\n# repl-timeout 60\n\n# Disable TCP_NODELAY on the slave socket after SYNC?\n#\n# If you select \"yes\" Redis will use a smaller number of TCP packets and\n# less bandwidth to send data to slaves. But this can add a delay for\n# the data to appear on the slave side, up to 40 milliseconds with\n# Linux kernels using a default configuration.\n#\n# If you select \"no\" the delay for data to appear on the slave side will\n# be reduced but more bandwidth will be used for replication.\n#\n# By default we optimize for low latency, but in very high traffic conditions\n# or when the master and slaves are many hops away, turning this to \"yes\" may\n# be a good idea.\nrepl-disable-tcp-nodelay no\n\n# Set the replication backlog size. The backlog is a buffer that accumulates\n# slave data when slaves are disconnected for some time, so that when a slave\n# wants to reconnect again, often a full resync is not needed, but a partial\n# resync is enough, just passing the portion of data the slave missed while\n# disconnected.\n#\n# The bigger the replication backlog, the longer the time the slave can be\n# disconnected and later be able to perform a partial resynchronization.\n#\n# The backlog is only allocated once there is at least a slave connected.\n#\n# repl-backlog-size 1mb\n\n# After a master has no longer connected slaves for some time, the backlog\n# will be freed. The following option configures the amount of seconds that\n# need to elapse, starting from the time the last slave disconnected, for\n# the backlog buffer to be freed.\n#\n# A value of 0 means to never release the backlog.\n#\n# repl-backlog-ttl 3600\n\n# The slave priority is an integer number published by Redis in the INFO output.\n# It is used by Redis Sentinel in order to select a slave to promote into a\n# master if the master is no longer working correctly.\n#\n# A slave with a low priority number is considered better for promotion, so\n# for instance if there are three slaves with priority 10, 100, 25 Sentinel will\n# pick the one with priority 10, that is the lowest.\n#\n# However a special priority of 0 marks the slave as not able to perform the\n# role of master, so a slave with priority of 0 will never be selected by\n# Redis Sentinel for promotion.\n#\n# By default the priority is 100.\nslave-priority 100\n\n# It is possible for a master to stop accepting writes if there are less than\n# N slaves connected, having a lag less or equal than M seconds.\n#\n# The N slaves need to be in \"online\" state.\n#\n# The lag in seconds, that must be <= the specified value, is calculated from\n# the last ping received from the slave, that is usually sent every second.\n#\n# This option does not GUARANTEE that N replicas will accept the write, but\n# will limit the window of exposure for lost writes in case not enough slaves\n# are available, to the specified number of seconds.\n#\n# For example to require at least 3 slaves with a lag <= 10 seconds use:\n#\n# min-slaves-to-write 3\n# min-slaves-max-lag 10\n#\n# Setting one or the other to 0 disables the feature.\n#\n# By default min-slaves-to-write is set to 0 (feature disabled) and\n# min-slaves-max-lag is set to 10.\n\n################################## SECURITY ###################################\n\n# Require clients to issue AUTH <PASSWORD> before processing any other\n# commands.  This might be useful in environments in which you do not trust\n# others with access to the host running redis-server.\n#\n# This should stay commented out for backward compatibility and because most\n# people do not need auth (e.g. they run their own servers).\n#\n# Warning: since Redis is pretty fast an outside user can try up to\n# 150k passwords per second against a good box. This means that you should\n# use a very strong password otherwise it will be very easy to break.\n#\n# requirepass foobared\n\n# Command renaming.\n#\n# It is possible to change the name of dangerous commands in a shared\n# environment. For instance the CONFIG command may be renamed into something\n# hard to guess so that it will still be available for internal-use tools\n# but not available for general clients.\n#\n# Example:\n#\n# rename-command CONFIG b840fc02d524045429941cc15f59e41cb7be6c52\n#\n# It is also possible to completely kill a command by renaming it into\n# an empty string:\n#\n# rename-command CONFIG \"\"\n#\n# Please note that changing the name of commands that are logged into the\n# AOF file or transmitted to slaves may cause problems.\n\n################################### LIMITS ####################################\n\n# Set the max number of connected clients at the same time. By default\n# this limit is set to 10000 clients, however if the Redis server is not\n# able to configure the process file limit to allow for the specified limit\n# the max number of allowed clients is set to the current file limit\n# minus 32 (as Redis reserves a few file descriptors for internal uses).\n#\n# Once the limit is reached Redis will close all the new connections sending\n# an error 'max number of clients reached'.\n#\n# maxclients 10000\n\n# Don't use more memory than the specified amount of bytes.\n# When the memory limit is reached Redis will try to remove keys\n# according to the eviction policy selected (see maxmemory-policy).\n#\n# If Redis can't remove keys according to the policy, or if the policy is\n# set to 'noeviction', Redis will start to reply with errors to commands\n# that would use more memory, like SET, LPUSH, and so on, and will continue\n# to reply to read-only commands like GET.\n#\n# This option is usually useful when using Redis as an LRU cache, or to set\n# a hard memory limit for an instance (using the 'noeviction' policy).\n#\n# WARNING: If you have slaves attached to an instance with maxmemory on,\n# the size of the output buffers needed to feed the slaves are subtracted\n# from the used memory count, so that network problems / resyncs will\n# not trigger a loop where keys are evicted, and in turn the output\n# buffer of slaves is full with DELs of keys evicted triggering the deletion\n# of more keys, and so forth until the database is completely emptied.\n#\n# In short... if you have slaves attached it is suggested that you set a lower\n# limit for maxmemory so that there is some free RAM on the system for slave\n# output buffers (but this is not needed if the policy is 'noeviction').\n#\n# maxmemory <bytes>\n\n# MAXMEMORY POLICY: how Redis will select what to remove when maxmemory\n# is reached. You can select among five behaviors:\n#\n# volatile-lru -> remove the key with an expire set using an LRU algorithm\n# allkeys-lru -> remove any key according to the LRU algorithm\n# volatile-random -> remove a random key with an expire set\n# allkeys-random -> remove a random key, any key\n# volatile-ttl -> remove the key with the nearest expire time (minor TTL)\n# noeviction -> don't expire at all, just return an error on write operations\n#\n# Note: with any of the above policies, Redis will return an error on write\n#       operations, when there are no suitable keys for eviction.\n#\n#       At the date of writing these commands are: set setnx setex append\n#       incr decr rpush lpush rpushx lpushx linsert lset rpoplpush sadd\n#       sinter sinterstore sunion sunionstore sdiff sdiffstore zadd zincrby\n#       zunionstore zinterstore hset hsetnx hmset hincrby incrby decrby\n#       getset mset msetnx exec sort\n#\n# The default is:\n#\n# maxmemory-policy volatile-lru\n\n# LRU and minimal TTL algorithms are not precise algorithms but approximated\n# algorithms (in order to save memory), so you can select as well the sample\n# size to check. For instance for default Redis will check three keys and\n# pick the one that was used less recently, you can change the sample size\n# using the following configuration directive.\n#\n# maxmemory-samples 3\n\n############################## APPEND ONLY MODE ###############################\n\n# By default Redis asynchronously dumps the dataset on disk. This mode is\n# good enough in many applications, but an issue with the Redis process or\n# a power outage may result into a few minutes of writes lost (depending on\n# the configured save points).\n#\n# The Append Only File is an alternative persistence mode that provides\n# much better durability. For instance using the default data fsync policy\n# (see later in the config file) Redis can lose just one second of writes in a\n# dramatic event like a server power outage, or a single write if something\n# wrong with the Redis process itself happens, but the operating system is\n# still running correctly.\n#\n# AOF and RDB persistence can be enabled at the same time without problems.\n# If the AOF is enabled on startup Redis will load the AOF, that is the file\n# with the better durability guarantees.\n#\n# Please check http://redis.io/topics/persistence for more information.\n\nappendonly no\n\n# The name of the append only file (default: \"appendonly.aof\")\n\nappendfilename \"appendonly.aof\"\n\n# The fsync() call tells the Operating System to actually write data on disk\n# instead of waiting for more data in the output buffer. Some OS will really flush\n# data on disk, some other OS will just try to do it ASAP.\n#\n# Redis supports three different modes:\n#\n# no: don't fsync, just let the OS flush the data when it wants. Faster.\n# always: fsync after every write to the append only log. Slow, Safest.\n# everysec: fsync only one time every second. Compromise.\n#\n# The default is \"everysec\", as that's usually the right compromise between\n# speed and data safety. It's up to you to understand if you can relax this to\n# \"no\" that will let the operating system flush the output buffer when\n# it wants, for better performances (but if you can live with the idea of\n# some data loss consider the default persistence mode that's snapshotting),\n# or on the contrary, use \"always\" that's very slow but a bit safer than\n# everysec.\n#\n# More details please check the following article:\n# http://antirez.com/post/redis-persistence-demystified.html\n#\n# If unsure, use \"everysec\".\n\n# appendfsync always\nappendfsync everysec\n# appendfsync no\n\n# When the AOF fsync policy is set to always or everysec, and a background\n# saving process (a background save or AOF log background rewriting) is\n# performing a lot of I/O against the disk, in some Linux configurations\n# Redis may block too long on the fsync() call. Note that there is no fix for\n# this currently, as even performing fsync in a different thread will block\n# our synchronous write(2) call.\n#\n# In order to mitigate this problem it's possible to use the following option\n# that will prevent fsync() from being called in the main process while a\n# BGSAVE or BGREWRITEAOF is in progress.\n#\n# This means that while another child is saving, the durability of Redis is\n# the same as \"appendfsync none\". In practical terms, this means that it is\n# possible to lose up to 30 seconds of log in the worst scenario (with the\n# default Linux settings).\n#\n# If you have latency problems turn this to \"yes\". Otherwise leave it as\n# \"no\" that is the safest pick from the point of view of durability.\n\nno-appendfsync-on-rewrite no\n\n# Automatic rewrite of the append only file.\n# Redis is able to automatically rewrite the log file implicitly calling\n# BGREWRITEAOF when the AOF log size grows by the specified percentage.\n#\n# This is how it works: Redis remembers the size of the AOF file after the\n# latest rewrite (if no rewrite has happened since the restart, the size of\n# the AOF at startup is used).\n#\n# This base size is compared to the current size. If the current size is\n# bigger than the specified percentage, the rewrite is triggered. Also\n# you need to specify a minimal size for the AOF file to be rewritten, this\n# is useful to avoid rewriting the AOF file even if the percentage increase\n# is reached but it is still pretty small.\n#\n# Specify a percentage of zero in order to disable the automatic AOF\n# rewrite feature.\n\nauto-aof-rewrite-percentage 100\nauto-aof-rewrite-min-size 64mb\n\n# An AOF file may be found to be truncated at the end during the Redis\n# startup process, when the AOF data gets loaded back into memory.\n# This may happen when the system where Redis is running\n# crashes, especially when an ext4 filesystem is mounted without the\n# data=ordered option (however this can't happen when Redis itself\n# crashes or aborts but the operating system still works correctly).\n#\n# Redis can either exit with an error when this happens, or load as much\n# data as possible (the default now) and start if the AOF file is found\n# to be truncated at the end. The following option controls this behavior.\n#\n# If aof-load-truncated is set to yes, a truncated AOF file is loaded and\n# the Redis server starts emitting a log to inform the user of the event.\n# Otherwise if the option is set to no, the server aborts with an error\n# and refuses to start. When the option is set to no, the user requires\n# to fix the AOF file using the \"redis-check-aof\" utility before to restart\n# the server.\n#\n# Note that if the AOF file will be found to be corrupted in the middle\n# the server will still exit with an error. This option only applies when\n# Redis will try to read more data from the AOF file but not enough bytes\n# will be found.\naof-load-truncated yes\n\n################################ LUA SCRIPTING  ###############################\n\n# Max execution time of a Lua script in milliseconds.\n#\n# If the maximum execution time is reached Redis will log that a script is\n# still in execution after the maximum allowed time and will start to\n# reply to queries with an error.\n#\n# When a long running script exceeds the maximum execution time only the\n# SCRIPT KILL and SHUTDOWN NOSAVE commands are available. The first can be\n# used to stop a script that did not yet called write commands. The second\n# is the only way to shut down the server in the case a write command was\n# already issued by the script but the user doesn't want to wait for the natural\n# termination of the script.\n#\n# Set it to 0 or a negative value for unlimited execution without warnings.\nlua-time-limit 5000\n\n################################## SLOW LOG ###################################\n\n# The Redis Slow Log is a system to log queries that exceeded a specified\n# execution time. The execution time does not include the I/O operations\n# like talking with the client, sending the reply and so forth,\n# but just the time needed to actually execute the command (this is the only\n# stage of command execution where the thread is blocked and can not serve\n# other requests in the meantime).\n#\n# You can configure the slow log with two parameters: one tells Redis\n# what is the execution time, in microseconds, to exceed in order for the\n# command to get logged, and the other parameter is the length of the\n# slow log. When a new command is logged the oldest one is removed from the\n# queue of logged commands.\n\n# The following time is expressed in microseconds, so 1000000 is equivalent\n# to one second. Note that a negative number disables the slow log, while\n# a value of zero forces the logging of every command.\nslowlog-log-slower-than 10000\n\n# There is no limit to this length. Just be aware that it will consume memory.\n# You can reclaim memory used by the slow log with SLOWLOG RESET.\nslowlog-max-len 128\n\n################################ LATENCY MONITOR ##############################\n\n# The Redis latency monitoring subsystem samples different operations\n# at runtime in order to collect data related to possible sources of\n# latency of a Redis instance.\n#\n# Via the LATENCY command this information is available to the user that can\n# print graphs and obtain reports.\n#\n# The system only logs operations that were performed in a time equal or\n# greater than the amount of milliseconds specified via the\n# latency-monitor-threshold configuration directive. When its value is set\n# to zero, the latency monitor is turned off.\n#\n# By default latency monitoring is disabled since it is mostly not needed\n# if you don't have latency issues, and collecting data has a performance\n# impact, that while very small, can be measured under big load. Latency\n# monitoring can easily be enalbed at runtime using the command\n# \"CONFIG SET latency-monitor-threshold <milliseconds>\" if needed.\nlatency-monitor-threshold 0\n\n############################# Event notification ##############################\n\n# Redis can notify Pub/Sub clients about events happening in the key space.\n# This feature is documented at http://redis.io/topics/notifications\n#\n# For instance if keyspace events notification is enabled, and a client\n# performs a DEL operation on key \"foo\" stored in the Database 0, two\n# messages will be published via Pub/Sub:\n#\n# PUBLISH __keyspace@0__:foo del\n# PUBLISH __keyevent@0__:del foo\n#\n# It is possible to select the events that Redis will notify among a set\n# of classes. Every class is identified by a single character:\n#\n#  K     Keyspace events, published with __keyspace@<db>__ prefix.\n#  E     Keyevent events, published with __keyevent@<db>__ prefix.\n#  g     Generic commands (non-type specific) like DEL, EXPIRE, RENAME, ...\n#  $     String commands\n#  l     List commands\n#  s     Set commands\n#  h     Hash commands\n#  z     Sorted set commands\n#  x     Expired events (events generated every time a key expires)\n#  e     Evicted events (events generated when a key is evicted for maxmemory)\n#  A     Alias for g$lshzxe, so that the \"AKE\" string means all the events.\n#\n#  The \"notify-keyspace-events\" takes as argument a string that is composed\n#  of zero or multiple characters. The empty string means that notifications\n#  are disabled.\n#\n#  Example: to enable list and generic events, from the point of view of the\n#           event name, use:\n#\n#  notify-keyspace-events Elg\n#\n#  Example 2: to get the stream of the expired keys subscribing to channel\n#             name __keyevent@0__:expired use:\n#\n#  notify-keyspace-events Ex\n#\n#  By default all notifications are disabled because most users don't need\n#  this feature and the feature has some overhead. Note that if you don't\n#  specify at least one of K or E, no events will be delivered.\nnotify-keyspace-events \"\"\n\n############################### ADVANCED CONFIG ###############################\n\n# Hashes are encoded using a memory efficient data structure when they have a\n# small number of entries, and the biggest entry does not exceed a given\n# threshold. These thresholds can be configured using the following directives.\nhash-max-ziplist-entries 512\nhash-max-ziplist-value 64\n\n# Similarly to hashes, small lists are also encoded in a special way in order\n# to save a lot of space. The special representation is only used when\n# you are under the following limits:\nlist-max-ziplist-entries 512\nlist-max-ziplist-value 64\n\n# Sets have a special encoding in just one case: when a set is composed\n# of just strings that happen to be integers in radix 10 in the range\n# of 64 bit signed integers.\n# The following configuration setting sets the limit in the size of the\n# set in order to use this special memory saving encoding.\nset-max-intset-entries 512\n\n# Similarly to hashes and lists, sorted sets are also specially encoded in\n# order to save a lot of space. This encoding is only used when the length and\n# elements of a sorted set are below the following limits:\nzset-max-ziplist-entries 128\nzset-max-ziplist-value 64\n\n# HyperLogLog sparse representation bytes limit. The limit includes the\n# 16 bytes header. When an HyperLogLog using the sparse representation crosses\n# this limit, it is converted into the dense representation.\n#\n# A value greater than 16000 is totally useless, since at that point the\n# dense representation is more memory efficient.\n#\n# The suggested value is ~ 3000 in order to have the benefits of\n# the space efficient encoding without slowing down too much PFADD,\n# which is O(N) with the sparse encoding. The value can be raised to\n# ~ 10000 when CPU is not a concern, but space is, and the data set is\n# composed of many HyperLogLogs with cardinality in the 0 - 15000 range.\nhll-sparse-max-bytes 3000\n\n# Active rehashing uses 1 millisecond every 100 milliseconds of CPU time in\n# order to help rehashing the main Redis hash table (the one mapping top-level\n# keys to values). The hash table implementation Redis uses (see dict.c)\n# performs a lazy rehashing: the more operation you run into a hash table\n# that is rehashing, the more rehashing \"steps\" are performed, so if the\n# server is idle the rehashing is never complete and some more memory is used\n# by the hash table.\n#\n# The default is to use this millisecond 10 times every second in order to\n# actively rehash the main dictionaries, freeing memory when possible.\n#\n# If unsure:\n# use \"activerehashing no\" if you have hard latency requirements and it is\n# not a good thing in your environment that Redis can reply from time to time\n# to queries with 2 milliseconds delay.\n#\n# use \"activerehashing yes\" if you don't have such hard requirements but\n# want to free memory asap when possible.\nactiverehashing yes\n\n# The client output buffer limits can be used to force disconnection of clients\n# that are not reading data from the server fast enough for some reason (a\n# common reason is that a Pub/Sub client can't consume messages as fast as the\n# publisher can produce them).\n#\n# The limit can be set differently for the three different classes of clients:\n#\n# normal -> normal clients including MONITOR clients\n# slave  -> slave clients\n# pubsub -> clients subscribed to at least one pubsub channel or pattern\n#\n# The syntax of every client-output-buffer-limit directive is the following:\n#\n# client-output-buffer-limit <class> <hard limit> <soft limit> <soft seconds>\n#\n# A client is immediately disconnected once the hard limit is reached, or if\n# the soft limit is reached and remains reached for the specified number of\n# seconds (continuously).\n# So for instance if the hard limit is 32 megabytes and the soft limit is\n# 16 megabytes / 10 seconds, the client will get disconnected immediately\n# if the size of the output buffers reach 32 megabytes, but will also get\n# disconnected if the client reaches 16 megabytes and continuously overcomes\n# the limit for 10 seconds.\n#\n# By default normal clients are not limited because they don't receive data\n# without asking (in a push way), but just after a request, so only\n# asynchronous clients may create a scenario where data is requested faster\n# than it can read.\n#\n# Instead there is a default limit for pubsub and slave clients, since\n# subscribers and slaves receive data in a push fashion.\n#\n# Both the hard or the soft limit can be disabled by setting them to zero.\nclient-output-buffer-limit normal 0 0 0\nclient-output-buffer-limit slave 256mb 64mb 60\nclient-output-buffer-limit pubsub 32mb 8mb 60\n\n# Redis calls an internal function to perform many background tasks, like\n# closing connections of clients in timeout, purging expired keys that are\n# never requested, and so forth.\n#\n# Not all tasks are performed with the same frequency, but Redis checks for\n# tasks to perform according to the specified \"hz\" value.\n#\n# By default \"hz\" is set to 10. Raising the value will use more CPU when\n# Redis is idle, but at the same time will make Redis more responsive when\n# there are many keys expiring at the same time, and timeouts may be\n# handled with more precision.\n#\n# The range is between 1 and 500, however a value over 100 is usually not\n# a good idea. Most users should use the default of 10 and raise this up to\n# 100 only in environments where very low latency is required.\nhz 10\n\n# When a child rewrites the AOF file, if the following option is enabled\n# the file will be fsync-ed every 32 MB of data generated. This is useful\n# in order to commit the file to the disk more incrementally and avoid\n# big latency spikes.\naof-rewrite-incremental-fsync yes\n"
  },
  {
    "path": "extern/deprecated/redis-2.8.21/runtest",
    "content": "#!/bin/sh\nTCL_VERSIONS=\"8.5 8.6\"\nTCLSH=\"\"\n\nfor VERSION in $TCL_VERSIONS; do\n\tTCL=`which tclsh$VERSION 2>/dev/null` && TCLSH=$TCL\ndone\n\nif [ -z $TCLSH ]\nthen\n    echo \"You need tcl 8.5 or newer in order to run the Redis test\"\n    exit 1\nfi\n$TCLSH tests/test_helper.tcl $*\n"
  },
  {
    "path": "extern/deprecated/redis-2.8.21/runtest-sentinel",
    "content": "#!/bin/sh\nTCL_VERSIONS=\"8.5 8.6\"\nTCLSH=\"\"\n\nfor VERSION in $TCL_VERSIONS; do\n\tTCL=`which tclsh$VERSION 2>/dev/null` && TCLSH=$TCL\ndone\n\nif [ -z $TCLSH ]\nthen\n    echo \"You need tcl 8.5 or newer in order to run the Redis Sentinel test\"\n    exit 1\nfi\n$TCLSH tests/sentinel/run.tcl $*\n"
  },
  {
    "path": "extern/deprecated/redis-2.8.21/sentinel.conf",
    "content": "# Example sentinel.conf\n\n# port <sentinel-port>\n# The port that this sentinel instance will run on\nport 26379\n\n# sentinel announce-ip <ip>\n# sentinel announce-port <port>\n#\n# The above two configuration directives are useful in environments where,\n# because of NAT, Sentinel is reachable from outside via a non-local address.\n#\n# When announce-ip is provided, the Sentinel will claim the specified IP address\n# in HELLO messages used to gossip its presence, instead of auto-detecting the\n# local address as it usually does.\n#\n# Similarly when announce-port is provided and is valid and non-zero, Sentinel\n# will announce the specified TCP port.\n#\n# The two options don't need to be used together, if only announce-ip is\n# provided, the Sentinel will announce the specified IP and the server port\n# as specified by the \"port\" option. If only announce-port is provided, the\n# Sentinel will announce the auto-detected local IP and the specified port.\n#\n# Example:\n#\n# sentinel announce-ip 1.2.3.4\n\n# dir <working-directory>\n# Every long running process should have a well-defined working directory.\n# For Redis Sentinel to chdir to /tmp at startup is the simplest thing\n# for the process to don't interfere with administrative tasks such as\n# unmounting filesystems.\ndir /tmp\n\n# sentinel monitor <master-name> <ip> <redis-port> <quorum>\n#\n# Tells Sentinel to monitor this master, and to consider it in O_DOWN\n# (Objectively Down) state only if at least <quorum> sentinels agree.\n#\n# Note that whatever is the ODOWN quorum, a Sentinel will require to\n# be elected by the majority of the known Sentinels in order to\n# start a failover, so no failover can be performed in minority.\n#\n# Slaves are auto-discovered, so you don't need to specify slaves in\n# any way. Sentinel itself will rewrite this configuration file adding\n# the slaves using additional configuration options.\n# Also note that the configuration file is rewritten when a\n# slave is promoted to master.\n#\n# Note: master name should not include special characters or spaces.\n# The valid charset is A-z 0-9 and the three characters \".-_\".\nsentinel monitor mymaster 127.0.0.1 6379 2\n\n# sentinel auth-pass <master-name> <password>\n#\n# Set the password to use to authenticate with the master and slaves.\n# Useful if there is a password set in the Redis instances to monitor.\n#\n# Note that the master password is also used for slaves, so it is not\n# possible to set a different password in masters and slaves instances\n# if you want to be able to monitor these instances with Sentinel.\n#\n# However you can have Redis instances without the authentication enabled\n# mixed with Redis instances requiring the authentication (as long as the\n# password set is the same for all the instances requiring the password) as\n# the AUTH command will have no effect in Redis instances with authentication\n# switched off.\n#\n# Example:\n#\n# sentinel auth-pass mymaster MySUPER--secret-0123passw0rd\n\n# sentinel down-after-milliseconds <master-name> <milliseconds>\n#\n# Number of milliseconds the master (or any attached slave or sentinel) should\n# be unreachable (as in, not acceptable reply to PING, continuously, for the\n# specified period) in order to consider it in S_DOWN state (Subjectively\n# Down).\n#\n# Default is 30 seconds.\nsentinel down-after-milliseconds mymaster 30000\n\n# sentinel parallel-syncs <master-name> <numslaves>\n#\n# How many slaves we can reconfigure to point to the new slave simultaneously\n# during the failover. Use a low number if you use the slaves to serve query\n# to avoid that all the slaves will be unreachable at about the same\n# time while performing the synchronization with the master.\nsentinel parallel-syncs mymaster 1\n\n# sentinel failover-timeout <master-name> <milliseconds>\n#\n# Specifies the failover timeout in milliseconds. It is used in many ways:\n#\n# - The time needed to re-start a failover after a previous failover was\n#   already tried against the same master by a given Sentinel, is two\n#   times the failover timeout.\n#\n# - The time needed for a slave replicating to a wrong master according\n#   to a Sentinel current configuration, to be forced to replicate\n#   with the right master, is exactly the failover timeout (counting since\n#   the moment a Sentinel detected the misconfiguration).\n#\n# - The time needed to cancel a failover that is already in progress but\n#   did not produced any configuration change (SLAVEOF NO ONE yet not\n#   acknowledged by the promoted slave).\n#\n# - The maximum time a failover in progress waits for all the slaves to be\n#   reconfigured as slaves of the new master. However even after this time\n#   the slaves will be reconfigured by the Sentinels anyway, but not with\n#   the exact parallel-syncs progression as specified.\n#\n# Default is 3 minutes.\nsentinel failover-timeout mymaster 180000\n\n# SCRIPTS EXECUTION\n#\n# sentinel notification-script and sentinel reconfig-script are used in order\n# to configure scripts that are called to notify the system administrator\n# or to reconfigure clients after a failover. The scripts are executed\n# with the following rules for error handling:\n#\n# If script exits with \"1\" the execution is retried later (up to a maximum\n# number of times currently set to 10).\n#\n# If script exits with \"2\" (or an higher value) the script execution is\n# not retried.\n#\n# If script terminates because it receives a signal the behavior is the same\n# as exit code 1.\n#\n# A script has a maximum running time of 60 seconds. After this limit is\n# reached the script is terminated with a SIGKILL and the execution retried.\n\n# NOTIFICATION SCRIPT\n#\n# sentinel notification-script <master-name> <script-path>\n# \n# Call the specified notification script for any sentinel event that is\n# generated in the WARNING level (for instance -sdown, -odown, and so forth).\n# This script should notify the system administrator via email, SMS, or any\n# other messaging system, that there is something wrong with the monitored\n# Redis systems.\n#\n# The script is called with just two arguments: the first is the event type\n# and the second the event description.\n#\n# The script must exist and be executable in order for sentinel to start if\n# this option is provided.\n#\n# Example:\n#\n# sentinel notification-script mymaster /var/redis/notify.sh\n\n# CLIENTS RECONFIGURATION SCRIPT\n#\n# sentinel client-reconfig-script <master-name> <script-path>\n#\n# When the master changed because of a failover a script can be called in\n# order to perform application-specific tasks to notify the clients that the\n# configuration has changed and the master is at a different address.\n# \n# The following arguments are passed to the script:\n#\n# <master-name> <role> <state> <from-ip> <from-port> <to-ip> <to-port>\n#\n# <state> is currently always \"failover\"\n# <role> is either \"leader\" or \"observer\"\n# \n# The arguments from-ip, from-port, to-ip, to-port are used to communicate\n# the old address of the master and the new address of the elected slave\n# (now a master).\n#\n# This script should be resistant to multiple invocations.\n#\n# Example:\n#\n# sentinel client-reconfig-script mymaster /var/redis/reconfig.sh\n\n\n"
  },
  {
    "path": "extern/deprecated/redis-2.8.21/src/.gitignore",
    "content": "*.gcda\n*.gcno\n*.gcov\nredis.info\nlcov-html\n"
  },
  {
    "path": "extern/deprecated/redis-2.8.21/src/Makefile",
    "content": "# Redis Makefile\n# Copyright (C) 2009 Salvatore Sanfilippo <antirez at gmail dot com>\n# This file is released under the BSD license, see the COPYING file\n#\n# The Makefile composes the final FINAL_CFLAGS and FINAL_LDFLAGS using\n# what is needed for Redis plus the standard CFLAGS and LDFLAGS passed.\n# However when building the dependencies (Jemalloc, Lua, Hiredis, ...)\n# CFLAGS and LDFLAGS are propagated to the dependencies, so to pass\n# flags only to be used when compiling / linking Redis itself REDIS_CFLAGS\n# and REDIS_LDFLAGS are used instead (this is the case of 'make gcov').\n#\n# Dependencies are stored in the Makefile.dep file. To rebuild this file\n# Just use 'make dep', but this is only needed by developers.\n\nrelease_hdr := $(shell sh -c './mkreleasehdr.sh')\nuname_S := $(shell sh -c 'uname -s 2>/dev/null || echo not')\nOPTIMIZATION?=-O2\nDEPENDENCY_TARGETS=hiredis linenoise lua\n\n# Default settings\nSTD=-std=c99 -pedantic\nWARN=-Wall -W\nOPT=$(OPTIMIZATION)\n\nPREFIX?=/usr/local\nINSTALL_BIN=$(PREFIX)/bin\nINSTALL=install\n\n# Default allocator\nifeq ($(uname_S),Linux)\n\tMALLOC=jemalloc\nelse\n\tMALLOC=libc\nendif\n\n# Backwards compatibility for selecting an allocator\nifeq ($(USE_TCMALLOC),yes)\n\tMALLOC=tcmalloc\nendif\n\nifeq ($(USE_TCMALLOC_MINIMAL),yes)\n\tMALLOC=tcmalloc_minimal\nendif\n\nifeq ($(USE_JEMALLOC),yes)\n\tMALLOC=jemalloc\nendif\n\n# Override default settings if possible\n-include .make-settings\n\nFINAL_CFLAGS=$(STD) $(WARN) $(OPT) $(DEBUG) $(CFLAGS) $(REDIS_CFLAGS)\nFINAL_LDFLAGS=$(LDFLAGS) $(REDIS_LDFLAGS) $(DEBUG)\nFINAL_LIBS=-lm\nDEBUG=-g -ggdb\n\nifeq ($(uname_S),SunOS)\n\t# SunOS\n\tINSTALL=cp -pf\n\tFINAL_CFLAGS+= -D__EXTENSIONS__ -D_XPG6\n\tFINAL_LIBS+= -ldl -lnsl -lsocket -lresolv -lpthread -lrt\nelse\nifeq ($(uname_S),Darwin)\n\t# Darwin (nothing to do)\nelse\nifeq ($(uname_S),AIX)\n        # AIX\n        FINAL_LDFLAGS+= -Wl,-bexpall\n        FINAL_LIBS+= -pthread -lcrypt -lbsd\n\nelse\n\t# All the other OSes (notably Linux)\n\tFINAL_LDFLAGS+= -rdynamic\n\tFINAL_LIBS+= -pthread\nendif\nendif\nendif\n# Include paths to dependencies\nFINAL_CFLAGS+= -I../deps/hiredis -I../deps/linenoise -I../deps/lua/src\n\nifeq ($(MALLOC),tcmalloc)\n\tFINAL_CFLAGS+= -DUSE_TCMALLOC\n\tFINAL_LIBS+= -ltcmalloc\nendif\n\nifeq ($(MALLOC),tcmalloc_minimal)\n\tFINAL_CFLAGS+= -DUSE_TCMALLOC\n\tFINAL_LIBS+= -ltcmalloc_minimal\nendif\n\nifeq ($(MALLOC),jemalloc)\n\tDEPENDENCY_TARGETS+= jemalloc\n\tFINAL_CFLAGS+= -DUSE_JEMALLOC -I../deps/jemalloc/include\n\tFINAL_LIBS+= ../deps/jemalloc/lib/libjemalloc.a -ldl\nendif\n\nREDIS_CC=$(QUIET_CC)$(CC) $(FINAL_CFLAGS)\nREDIS_LD=$(QUIET_LINK)$(CC) $(FINAL_LDFLAGS)\nREDIS_INSTALL=$(QUIET_INSTALL)$(INSTALL)\n\nCCCOLOR=\"\\033[34m\"\nLINKCOLOR=\"\\033[34;1m\"\nSRCCOLOR=\"\\033[33m\"\nBINCOLOR=\"\\033[37;1m\"\nMAKECOLOR=\"\\033[32;1m\"\nENDCOLOR=\"\\033[0m\"\n\nifndef V\nQUIET_CC = @printf '    %b %b\\n' $(CCCOLOR)CC$(ENDCOLOR) $(SRCCOLOR)$@$(ENDCOLOR) 1>&2;\nQUIET_LINK = @printf '    %b %b\\n' $(LINKCOLOR)LINK$(ENDCOLOR) $(BINCOLOR)$@$(ENDCOLOR) 1>&2;\nQUIET_INSTALL = @printf '    %b %b\\n' $(LINKCOLOR)INSTALL$(ENDCOLOR) $(BINCOLOR)$@$(ENDCOLOR) 1>&2;\nendif\n\nREDIS_SERVER_NAME=redis-server\nREDIS_SENTINEL_NAME=redis-sentinel\nREDIS_SERVER_OBJ=adlist.o ae.o anet.o dict.o redis.o sds.o zmalloc.o lzf_c.o lzf_d.o pqsort.o zipmap.o sha1.o ziplist.o release.o networking.o util.o object.o db.o replication.o rdb.o t_string.o t_list.o t_set.o t_zset.o t_hash.o config.o aof.o pubsub.o multi.o debug.o sort.o intset.o syncio.o migrate.o endianconv.o slowlog.o scripting.o bio.o rio.o rand.o memtest.o crc64.o crc32.o bitops.o sentinel.o notify.o setproctitle.o hyperloglog.o latency.o sparkline.o slots.o\nREDIS_CLI_NAME=redis-cli\nREDIS_CLI_OBJ=anet.o sds.o adlist.o redis-cli.o zmalloc.o release.o anet.o ae.o crc64.o\nREDIS_BENCHMARK_NAME=redis-benchmark\nREDIS_BENCHMARK_OBJ=ae.o anet.o redis-benchmark.o sds.o adlist.o zmalloc.o redis-benchmark.o\nREDIS_CHECK_DUMP_NAME=redis-check-dump\nREDIS_CHECK_DUMP_OBJ=redis-check-dump.o lzf_c.o lzf_d.o crc64.o\nREDIS_CHECK_AOF_NAME=redis-check-aof\nREDIS_CHECK_AOF_OBJ=redis-check-aof.o\n\nall: $(REDIS_SERVER_NAME) $(REDIS_SENTINEL_NAME) $(REDIS_CLI_NAME) $(REDIS_BENCHMARK_NAME) $(REDIS_CHECK_DUMP_NAME) $(REDIS_CHECK_AOF_NAME)\n\t@echo \"\"\n\t@echo \"Hint: It's a good idea to run 'make test' ;)\"\n\t@echo \"\"\n\n.PHONY: all\n\n# Deps (use make dep to generate this)\ninclude Makefile.dep\n\ndep:\n\t$(REDIS_CC) -MM *.c > Makefile.dep\n\n.PHONY: dep\n\npersist-settings: distclean\n\techo STD=$(STD) >> .make-settings\n\techo WARN=$(WARN) >> .make-settings\n\techo OPT=$(OPT) >> .make-settings\n\techo MALLOC=$(MALLOC) >> .make-settings\n\techo CFLAGS=$(CFLAGS) >> .make-settings\n\techo LDFLAGS=$(LDFLAGS) >> .make-settings\n\techo REDIS_CFLAGS=$(REDIS_CFLAGS) >> .make-settings\n\techo REDIS_LDFLAGS=$(REDIS_LDFLAGS) >> .make-settings\n\techo PREV_FINAL_CFLAGS=$(FINAL_CFLAGS) >> .make-settings\n\techo PREV_FINAL_LDFLAGS=$(FINAL_LDFLAGS) >> .make-settings\n\t-(cd ../deps && $(MAKE) $(DEPENDENCY_TARGETS))\n\n.PHONY: persist-settings\n\n# Prerequisites target\n.make-prerequisites:\n\t@touch $@\n\n# Clean everything, persist settings and build dependencies if anything changed\nifneq ($(strip $(PREV_FINAL_CFLAGS)), $(strip $(FINAL_CFLAGS)))\n.make-prerequisites: persist-settings\nendif\n\nifneq ($(strip $(PREV_FINAL_LDFLAGS)), $(strip $(FINAL_LDFLAGS)))\n.make-prerequisites: persist-settings\nendif\n\n# redis-server\n$(REDIS_SERVER_NAME): $(REDIS_SERVER_OBJ)\n\t$(REDIS_LD) -o $@ $^ ../deps/hiredis/libhiredis.a ../deps/lua/src/liblua.a $(FINAL_LIBS)\n\n# redis-sentinel\n$(REDIS_SENTINEL_NAME): $(REDIS_SERVER_NAME)\n\t$(REDIS_INSTALL) $(REDIS_SERVER_NAME) $(REDIS_SENTINEL_NAME)\n\n# redis-cli\n$(REDIS_CLI_NAME): $(REDIS_CLI_OBJ)\n\t$(REDIS_LD) -o $@ $^ ../deps/hiredis/libhiredis.a ../deps/linenoise/linenoise.o $(FINAL_LIBS)\n\n# redis-benchmark\n$(REDIS_BENCHMARK_NAME): $(REDIS_BENCHMARK_OBJ)\n\t$(REDIS_LD) -o $@ $^ ../deps/hiredis/libhiredis.a $(FINAL_LIBS)\n\n# redis-check-dump\n$(REDIS_CHECK_DUMP_NAME): $(REDIS_CHECK_DUMP_OBJ)\n\t$(REDIS_LD) -o $@ $^ $(FINAL_LIBS)\n\n# redis-check-aof\n$(REDIS_CHECK_AOF_NAME): $(REDIS_CHECK_AOF_OBJ)\n\t$(REDIS_LD) -o $@ $^ $(FINAL_LIBS)\n\n# Because the jemalloc.h header is generated as a part of the jemalloc build,\n# building it should complete before building any other object. Instead of\n# depending on a single artifact, build all dependencies first.\n%.o: %.c .make-prerequisites\n\t$(REDIS_CC) -c $<\n\nclean:\n\trm -rf $(REDIS_SERVER_NAME) $(REDIS_SENTINEL_NAME) $(REDIS_CLI_NAME) $(REDIS_BENCHMARK_NAME) $(REDIS_CHECK_DUMP_NAME) $(REDIS_CHECK_AOF_NAME) *.o *.gcda *.gcno *.gcov redis.info lcov-html\n\n.PHONY: clean\n\ndistclean: clean\n\t-(cd ../deps && $(MAKE) distclean)\n\t-(rm -f .make-*)\n\n.PHONY: distclean\n\ntest: $(REDIS_SERVER_NAME) $(REDIS_CHECK_AOF_NAME)\n\t@(cd ..; ./runtest)\n\ntest-sentinel: $(REDIS_SENTINEL_NAME)\n\t@(cd ..; ./runtest-sentinel)\n\ncheck: test\n\nlcov:\n\t$(MAKE) gcov\n\t@(set -e; cd ..; ./runtest --clients 1)\n\t@geninfo -o redis.info .\n\t@genhtml --legend -o lcov-html redis.info\n\n.PHONY: lcov\n\nbench: $(REDIS_BENCHMARK_NAME)\n\t./$(REDIS_BENCHMARK_NAME)\n\n32bit:\n\t@echo \"\"\n\t@echo \"WARNING: if it fails under Linux you probably need to install libc6-dev-i386\"\n\t@echo \"\"\n\t$(MAKE) CFLAGS=\"-m32\" LDFLAGS=\"-m32\"\n\ngcov:\n\t$(MAKE) REDIS_CFLAGS=\"-fprofile-arcs -ftest-coverage -DCOVERAGE_TEST\" REDIS_LDFLAGS=\"-fprofile-arcs -ftest-coverage\"\n\nnoopt:\n\t$(MAKE) OPTIMIZATION=\"-O0\"\n\nvalgrind:\n\t$(MAKE) OPTIMIZATION=\"-O0\" MALLOC=\"libc\"\n\nsrc/help.h:\n\t@../utils/generate-command-help.rb > help.h\n\ninstall: all\n\t@mkdir -p $(INSTALL_BIN)\n\t$(REDIS_INSTALL) $(REDIS_SERVER_NAME) $(INSTALL_BIN)\n\t$(REDIS_INSTALL) $(REDIS_BENCHMARK_NAME) $(INSTALL_BIN)\n\t$(REDIS_INSTALL) $(REDIS_CLI_NAME) $(INSTALL_BIN)\n\t$(REDIS_INSTALL) $(REDIS_CHECK_DUMP_NAME) $(INSTALL_BIN)\n\t$(REDIS_INSTALL) $(REDIS_CHECK_AOF_NAME) $(INSTALL_BIN)\n\t@ln -sf $(REDIS_SERVER_NAME) $(INSTALL_BIN)/$(REDIS_SENTINEL_NAME)\n"
  },
  {
    "path": "extern/deprecated/redis-2.8.21/src/Makefile.dep",
    "content": "adlist.o: adlist.c adlist.h zmalloc.h\nae.o: ae.c ae.h zmalloc.h config.h ae_kqueue.c ae_select.c ae_evport.c ae_epoll.c\nae_epoll.o: ae_epoll.c\nae_evport.o: ae_evport.c\nae_kqueue.o: ae_kqueue.c\nae_select.o: ae_select.c\nanet.o: anet.c fmacros.h anet.h\naof.o: aof.c redis.h fmacros.h config.h ../deps/lua/src/lua.h \\\n  ../deps/lua/src/luaconf.h ae.h sds.h dict.h adlist.h zmalloc.h anet.h \\\n  ziplist.h intset.h version.h util.h latency.h sparkline.h rdb.h rio.h \\\n  bio.h\nbio.o: bio.c redis.h fmacros.h config.h ../deps/lua/src/lua.h \\\n  ../deps/lua/src/luaconf.h ae.h sds.h dict.h adlist.h zmalloc.h anet.h \\\n  ziplist.h intset.h version.h util.h latency.h sparkline.h rdb.h rio.h \\\n  bio.h\nbitops.o: bitops.c redis.h fmacros.h config.h ../deps/lua/src/lua.h \\\n  ../deps/lua/src/luaconf.h ae.h sds.h dict.h adlist.h zmalloc.h anet.h \\\n  ziplist.h intset.h version.h util.h latency.h sparkline.h rdb.h rio.h\nconfig.o: config.c redis.h fmacros.h config.h ../deps/lua/src/lua.h \\\n  ../deps/lua/src/luaconf.h ae.h sds.h dict.h adlist.h zmalloc.h anet.h \\\n  ziplist.h intset.h version.h util.h latency.h sparkline.h rdb.h rio.h\ncrc64.o: crc64.c\ncrc32.o: crc32.c\ndb.o: db.c redis.h fmacros.h config.h ../deps/lua/src/lua.h \\\n  ../deps/lua/src/luaconf.h ae.h sds.h dict.h adlist.h zmalloc.h anet.h \\\n  ziplist.h intset.h version.h util.h latency.h sparkline.h rdb.h rio.h\ndebug.o: debug.c redis.h fmacros.h config.h ../deps/lua/src/lua.h \\\n  ../deps/lua/src/luaconf.h ae.h sds.h dict.h adlist.h zmalloc.h anet.h \\\n  ziplist.h intset.h version.h util.h latency.h sparkline.h rdb.h rio.h \\\n  sha1.h crc64.h bio.h\ndict.o: dict.c fmacros.h dict.h zmalloc.h redisassert.h\nendianconv.o: endianconv.c\nhyperloglog.o: hyperloglog.c redis.h fmacros.h config.h \\\n  ../deps/lua/src/lua.h ../deps/lua/src/luaconf.h ae.h sds.h dict.h \\\n  adlist.h zmalloc.h anet.h ziplist.h intset.h version.h util.h \\\n  latency.h sparkline.h rdb.h rio.h\nintset.o: intset.c intset.h zmalloc.h endianconv.h config.h\nlatency.o: latency.c redis.h fmacros.h config.h ../deps/lua/src/lua.h \\\n  ../deps/lua/src/luaconf.h ae.h sds.h dict.h adlist.h zmalloc.h anet.h \\\n  ziplist.h intset.h version.h util.h latency.h sparkline.h rdb.h rio.h\nlzf_c.o: lzf_c.c lzfP.h\nlzf_d.o: lzf_d.c lzfP.h\nmemtest.o: memtest.c config.h\nslots.o: slots.c redis.h\nmigrate.o: migrate.c redis.h fmacros.h config.h ../deps/lua/src/lua.h \\\n  ../deps/lua/src/luaconf.h ae.h sds.h dict.h adlist.h zmalloc.h anet.h \\\n  ziplist.h intset.h version.h util.h latency.h sparkline.h rdb.h rio.h \\\n  endianconv.h\nmulti.o: multi.c redis.h fmacros.h config.h ../deps/lua/src/lua.h \\\n  ../deps/lua/src/luaconf.h ae.h sds.h dict.h adlist.h zmalloc.h anet.h \\\n  ziplist.h intset.h version.h util.h latency.h sparkline.h rdb.h rio.h\nnetworking.o: networking.c redis.h fmacros.h config.h \\\n  ../deps/lua/src/lua.h ../deps/lua/src/luaconf.h ae.h sds.h dict.h \\\n  adlist.h zmalloc.h anet.h ziplist.h intset.h version.h util.h \\\n  latency.h sparkline.h rdb.h rio.h\nnotify.o: notify.c redis.h fmacros.h config.h ../deps/lua/src/lua.h \\\n  ../deps/lua/src/luaconf.h ae.h sds.h dict.h adlist.h zmalloc.h anet.h \\\n  ziplist.h intset.h version.h util.h latency.h sparkline.h rdb.h rio.h\nobject.o: object.c redis.h fmacros.h config.h ../deps/lua/src/lua.h \\\n  ../deps/lua/src/luaconf.h ae.h sds.h dict.h adlist.h zmalloc.h anet.h \\\n  ziplist.h intset.h version.h util.h latency.h sparkline.h rdb.h rio.h\npqsort.o: pqsort.c\npubsub.o: pubsub.c redis.h fmacros.h config.h ../deps/lua/src/lua.h \\\n  ../deps/lua/src/luaconf.h ae.h sds.h dict.h adlist.h zmalloc.h anet.h \\\n  ziplist.h intset.h version.h util.h latency.h sparkline.h rdb.h rio.h\nrand.o: rand.c\nrdb.o: rdb.c redis.h fmacros.h config.h ../deps/lua/src/lua.h \\\n  ../deps/lua/src/luaconf.h ae.h sds.h dict.h adlist.h zmalloc.h anet.h \\\n  ziplist.h intset.h version.h util.h latency.h sparkline.h rdb.h rio.h \\\n  lzf.h zipmap.h endianconv.h\nredis-benchmark.o: redis-benchmark.c fmacros.h ae.h \\\n  ../deps/hiredis/hiredis.h sds.h adlist.h zmalloc.h\nredis-check-aof.o: redis-check-aof.c fmacros.h config.h\nredis-check-dump.o: redis-check-dump.c lzf.h crc64.h\nredis-cli.o: redis-cli.c fmacros.h version.h ../deps/hiredis/hiredis.h \\\n  sds.h zmalloc.h ../deps/linenoise/linenoise.h help.h anet.h ae.h\nredis.o: redis.c redis.h fmacros.h config.h ../deps/lua/src/lua.h \\\n  ../deps/lua/src/luaconf.h ae.h sds.h dict.h adlist.h zmalloc.h anet.h \\\n  ziplist.h intset.h version.h util.h latency.h sparkline.h rdb.h rio.h \\\n  slowlog.h bio.h asciilogo.h\nrelease.o: release.c release.h version.h crc64.h\nreplication.o: replication.c redis.h fmacros.h config.h \\\n  ../deps/lua/src/lua.h ../deps/lua/src/luaconf.h ae.h sds.h dict.h \\\n  adlist.h zmalloc.h anet.h ziplist.h intset.h version.h util.h \\\n  latency.h sparkline.h rdb.h rio.h\nrio.o: rio.c fmacros.h rio.h sds.h util.h crc64.h config.h redis.h \\\n  ../deps/lua/src/lua.h ../deps/lua/src/luaconf.h ae.h dict.h adlist.h \\\n  zmalloc.h anet.h ziplist.h intset.h version.h latency.h sparkline.h \\\n  rdb.h\nscripting.o: scripting.c redis.h fmacros.h config.h ../deps/lua/src/lua.h \\\n  ../deps/lua/src/luaconf.h ae.h sds.h dict.h adlist.h zmalloc.h anet.h \\\n  ziplist.h intset.h version.h util.h latency.h sparkline.h rdb.h rio.h \\\n  sha1.h rand.h ../deps/lua/src/lauxlib.h ../deps/lua/src/lualib.h\nsds.o: sds.c sds.h zmalloc.h\nsentinel.o: sentinel.c redis.h fmacros.h config.h ../deps/lua/src/lua.h \\\n  ../deps/lua/src/luaconf.h ae.h sds.h dict.h adlist.h zmalloc.h anet.h \\\n  ziplist.h intset.h version.h util.h latency.h sparkline.h rdb.h rio.h \\\n  ../deps/hiredis/hiredis.h ../deps/hiredis/async.h\nsetproctitle.o: setproctitle.c\nsha1.o: sha1.c sha1.h config.h\nslowlog.o: slowlog.c redis.h fmacros.h config.h ../deps/lua/src/lua.h \\\n  ../deps/lua/src/luaconf.h ae.h sds.h dict.h adlist.h zmalloc.h anet.h \\\n  ziplist.h intset.h version.h util.h latency.h sparkline.h rdb.h rio.h \\\n  slowlog.h\nsort.o: sort.c redis.h fmacros.h config.h ../deps/lua/src/lua.h \\\n  ../deps/lua/src/luaconf.h ae.h sds.h dict.h adlist.h zmalloc.h anet.h \\\n  ziplist.h intset.h version.h util.h latency.h sparkline.h rdb.h rio.h \\\n  pqsort.h\nsparkline.o: sparkline.c redis.h fmacros.h config.h ../deps/lua/src/lua.h \\\n  ../deps/lua/src/luaconf.h ae.h sds.h dict.h adlist.h zmalloc.h anet.h \\\n  ziplist.h intset.h version.h util.h latency.h sparkline.h rdb.h rio.h\nsyncio.o: syncio.c redis.h fmacros.h config.h ../deps/lua/src/lua.h \\\n  ../deps/lua/src/luaconf.h ae.h sds.h dict.h adlist.h zmalloc.h anet.h \\\n  ziplist.h intset.h version.h util.h latency.h sparkline.h rdb.h rio.h\nt_hash.o: t_hash.c redis.h fmacros.h config.h ../deps/lua/src/lua.h \\\n  ../deps/lua/src/luaconf.h ae.h sds.h dict.h adlist.h zmalloc.h anet.h \\\n  ziplist.h intset.h version.h util.h latency.h sparkline.h rdb.h rio.h\nt_list.o: t_list.c redis.h fmacros.h config.h ../deps/lua/src/lua.h \\\n  ../deps/lua/src/luaconf.h ae.h sds.h dict.h adlist.h zmalloc.h anet.h \\\n  ziplist.h intset.h version.h util.h latency.h sparkline.h rdb.h rio.h\nt_set.o: t_set.c redis.h fmacros.h config.h ../deps/lua/src/lua.h \\\n  ../deps/lua/src/luaconf.h ae.h sds.h dict.h adlist.h zmalloc.h anet.h \\\n  ziplist.h intset.h version.h util.h latency.h sparkline.h rdb.h rio.h\nt_string.o: t_string.c redis.h fmacros.h config.h ../deps/lua/src/lua.h \\\n  ../deps/lua/src/luaconf.h ae.h sds.h dict.h adlist.h zmalloc.h anet.h \\\n  ziplist.h intset.h version.h util.h latency.h sparkline.h rdb.h rio.h\nt_zset.o: t_zset.c redis.h fmacros.h config.h ../deps/lua/src/lua.h \\\n  ../deps/lua/src/luaconf.h ae.h sds.h dict.h adlist.h zmalloc.h anet.h \\\n  ziplist.h intset.h version.h util.h latency.h sparkline.h rdb.h rio.h\nutil.o: util.c fmacros.h util.h sds.h\nziplist.o: ziplist.c zmalloc.h util.h sds.h ziplist.h endianconv.h \\\n  config.h redisassert.h\nzipmap.o: zipmap.c zmalloc.h endianconv.h config.h\nzmalloc.o: zmalloc.c config.h zmalloc.h\n"
  },
  {
    "path": "extern/deprecated/redis-2.8.21/src/adlist.c",
    "content": "/* adlist.c - A generic doubly linked list implementation\n *\n * Copyright (c) 2006-2010, Salvatore Sanfilippo <antirez at gmail dot com>\n * All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions are met:\n *\n *   * Redistributions of source code must retain the above copyright notice,\n *     this list of conditions and the following disclaimer.\n *   * Redistributions in binary form must reproduce the above copyright\n *     notice, this list of conditions and the following disclaimer in the\n *     documentation and/or other materials provided with the distribution.\n *   * Neither the name of Redis nor the names of its contributors may be used\n *     to endorse or promote products derived from this software without\n *     specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\"\n * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\n * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE\n * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR\n * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF\n * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS\n * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN\n * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)\n * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE\n * POSSIBILITY OF SUCH DAMAGE.\n */\n\n\n#include <stdlib.h>\n#include \"adlist.h\"\n#include \"zmalloc.h\"\n\n/* Create a new list. The created list can be freed with\n * AlFreeList(), but private value of every node need to be freed\n * by the user before to call AlFreeList().\n *\n * On error, NULL is returned. Otherwise the pointer to the new list. */\nlist *listCreate(void)\n{\n    struct list *list;\n\n    if ((list = zmalloc(sizeof(*list))) == NULL)\n        return NULL;\n    list->head = list->tail = NULL;\n    list->len = 0;\n    list->dup = NULL;\n    list->free = NULL;\n    list->match = NULL;\n    return list;\n}\n\n/* Free the whole list.\n *\n * This function can't fail. */\nvoid listRelease(list *list)\n{\n    unsigned long len;\n    listNode *current, *next;\n\n    current = list->head;\n    len = list->len;\n    while(len--) {\n        next = current->next;\n        if (list->free) list->free(current->value);\n        zfree(current);\n        current = next;\n    }\n    zfree(list);\n}\n\n/* Add a new node to the list, to head, containing the specified 'value'\n * pointer as value.\n *\n * On error, NULL is returned and no operation is performed (i.e. the\n * list remains unaltered).\n * On success the 'list' pointer you pass to the function is returned. */\nlist *listAddNodeHead(list *list, void *value)\n{\n    listNode *node;\n\n    if ((node = zmalloc(sizeof(*node))) == NULL)\n        return NULL;\n    node->value = value;\n    if (list->len == 0) {\n        list->head = list->tail = node;\n        node->prev = node->next = NULL;\n    } else {\n        node->prev = NULL;\n        node->next = list->head;\n        list->head->prev = node;\n        list->head = node;\n    }\n    list->len++;\n    return list;\n}\n\n/* Add a new node to the list, to tail, containing the specified 'value'\n * pointer as value.\n *\n * On error, NULL is returned and no operation is performed (i.e. the\n * list remains unaltered).\n * On success the 'list' pointer you pass to the function is returned. */\nlist *listAddNodeTail(list *list, void *value)\n{\n    listNode *node;\n\n    if ((node = zmalloc(sizeof(*node))) == NULL)\n        return NULL;\n    node->value = value;\n    if (list->len == 0) {\n        list->head = list->tail = node;\n        node->prev = node->next = NULL;\n    } else {\n        node->prev = list->tail;\n        node->next = NULL;\n        list->tail->next = node;\n        list->tail = node;\n    }\n    list->len++;\n    return list;\n}\n\nlist *listInsertNode(list *list, listNode *old_node, void *value, int after) {\n    listNode *node;\n\n    if ((node = zmalloc(sizeof(*node))) == NULL)\n        return NULL;\n    node->value = value;\n    if (after) {\n        node->prev = old_node;\n        node->next = old_node->next;\n        if (list->tail == old_node) {\n            list->tail = node;\n        }\n    } else {\n        node->next = old_node;\n        node->prev = old_node->prev;\n        if (list->head == old_node) {\n            list->head = node;\n        }\n    }\n    if (node->prev != NULL) {\n        node->prev->next = node;\n    }\n    if (node->next != NULL) {\n        node->next->prev = node;\n    }\n    list->len++;\n    return list;\n}\n\n/* Remove the specified node from the specified list.\n * It's up to the caller to free the private value of the node.\n *\n * This function can't fail. */\nvoid listDelNode(list *list, listNode *node)\n{\n    if (node->prev)\n        node->prev->next = node->next;\n    else\n        list->head = node->next;\n    if (node->next)\n        node->next->prev = node->prev;\n    else\n        list->tail = node->prev;\n    if (list->free) list->free(node->value);\n    zfree(node);\n    list->len--;\n}\n\n/* Returns a list iterator 'iter'. After the initialization every\n * call to listNext() will return the next element of the list.\n *\n * This function can't fail. */\nlistIter *listGetIterator(list *list, int direction)\n{\n    listIter *iter;\n\n    if ((iter = zmalloc(sizeof(*iter))) == NULL) return NULL;\n    if (direction == AL_START_HEAD)\n        iter->next = list->head;\n    else\n        iter->next = list->tail;\n    iter->direction = direction;\n    return iter;\n}\n\n/* Release the iterator memory */\nvoid listReleaseIterator(listIter *iter) {\n    zfree(iter);\n}\n\n/* Create an iterator in the list private iterator structure */\nvoid listRewind(list *list, listIter *li) {\n    li->next = list->head;\n    li->direction = AL_START_HEAD;\n}\n\nvoid listRewindTail(list *list, listIter *li) {\n    li->next = list->tail;\n    li->direction = AL_START_TAIL;\n}\n\n/* Return the next element of an iterator.\n * It's valid to remove the currently returned element using\n * listDelNode(), but not to remove other elements.\n *\n * The function returns a pointer to the next element of the list,\n * or NULL if there are no more elements, so the classical usage patter\n * is:\n *\n * iter = listGetIterator(list,<direction>);\n * while ((node = listNext(iter)) != NULL) {\n *     doSomethingWith(listNodeValue(node));\n * }\n *\n * */\nlistNode *listNext(listIter *iter)\n{\n    listNode *current = iter->next;\n\n    if (current != NULL) {\n        if (iter->direction == AL_START_HEAD)\n            iter->next = current->next;\n        else\n            iter->next = current->prev;\n    }\n    return current;\n}\n\n/* Duplicate the whole list. On out of memory NULL is returned.\n * On success a copy of the original list is returned.\n *\n * The 'Dup' method set with listSetDupMethod() function is used\n * to copy the node value. Otherwise the same pointer value of\n * the original node is used as value of the copied node.\n *\n * The original list both on success or error is never modified. */\nlist *listDup(list *orig)\n{\n    list *copy;\n    listIter *iter;\n    listNode *node;\n\n    if ((copy = listCreate()) == NULL)\n        return NULL;\n    copy->dup = orig->dup;\n    copy->free = orig->free;\n    copy->match = orig->match;\n    iter = listGetIterator(orig, AL_START_HEAD);\n    while((node = listNext(iter)) != NULL) {\n        void *value;\n\n        if (copy->dup) {\n            value = copy->dup(node->value);\n            if (value == NULL) {\n                listRelease(copy);\n                listReleaseIterator(iter);\n                return NULL;\n            }\n        } else\n            value = node->value;\n        if (listAddNodeTail(copy, value) == NULL) {\n            listRelease(copy);\n            listReleaseIterator(iter);\n            return NULL;\n        }\n    }\n    listReleaseIterator(iter);\n    return copy;\n}\n\n/* Search the list for a node matching a given key.\n * The match is performed using the 'match' method\n * set with listSetMatchMethod(). If no 'match' method\n * is set, the 'value' pointer of every node is directly\n * compared with the 'key' pointer.\n *\n * On success the first matching node pointer is returned\n * (search starts from head). If no matching node exists\n * NULL is returned. */\nlistNode *listSearchKey(list *list, void *key)\n{\n    listIter *iter;\n    listNode *node;\n\n    iter = listGetIterator(list, AL_START_HEAD);\n    while((node = listNext(iter)) != NULL) {\n        if (list->match) {\n            if (list->match(node->value, key)) {\n                listReleaseIterator(iter);\n                return node;\n            }\n        } else {\n            if (key == node->value) {\n                listReleaseIterator(iter);\n                return node;\n            }\n        }\n    }\n    listReleaseIterator(iter);\n    return NULL;\n}\n\n/* Return the element at the specified zero-based index\n * where 0 is the head, 1 is the element next to head\n * and so on. Negative integers are used in order to count\n * from the tail, -1 is the last element, -2 the penultimate\n * and so on. If the index is out of range NULL is returned. */\nlistNode *listIndex(list *list, long index) {\n    listNode *n;\n\n    if (index < 0) {\n        index = (-index)-1;\n        n = list->tail;\n        while(index-- && n) n = n->prev;\n    } else {\n        n = list->head;\n        while(index-- && n) n = n->next;\n    }\n    return n;\n}\n\n/* Rotate the list removing the tail node and inserting it to the head. */\nvoid listRotate(list *list) {\n    listNode *tail = list->tail;\n\n    if (listLength(list) <= 1) return;\n\n    /* Detach current tail */\n    list->tail = tail->prev;\n    list->tail->next = NULL;\n    /* Move it as head */\n    list->head->prev = tail;\n    tail->prev = NULL;\n    tail->next = list->head;\n    list->head = tail;\n}\n"
  },
  {
    "path": "extern/deprecated/redis-2.8.21/src/adlist.h",
    "content": "/* adlist.h - A generic doubly linked list implementation\n *\n * Copyright (c) 2006-2012, Salvatore Sanfilippo <antirez at gmail dot com>\n * All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions are met:\n *\n *   * Redistributions of source code must retain the above copyright notice,\n *     this list of conditions and the following disclaimer.\n *   * Redistributions in binary form must reproduce the above copyright\n *     notice, this list of conditions and the following disclaimer in the\n *     documentation and/or other materials provided with the distribution.\n *   * Neither the name of Redis nor the names of its contributors may be used\n *     to endorse or promote products derived from this software without\n *     specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\"\n * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\n * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE\n * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR\n * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF\n * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS\n * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN\n * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)\n * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE\n * POSSIBILITY OF SUCH DAMAGE.\n */\n\n#ifndef __ADLIST_H__\n#define __ADLIST_H__\n\n/* Node, List, and Iterator are the only data structures used currently. */\n\ntypedef struct listNode {\n    struct listNode *prev;\n    struct listNode *next;\n    void *value;\n} listNode;\n\ntypedef struct listIter {\n    listNode *next;\n    int direction;\n} listIter;\n\ntypedef struct list {\n    listNode *head;\n    listNode *tail;\n    void *(*dup)(void *ptr);\n    void (*free)(void *ptr);\n    int (*match)(void *ptr, void *key);\n    unsigned long len;\n} list;\n\n/* Functions implemented as macros */\n#define listLength(l) ((l)->len)\n#define listFirst(l) ((l)->head)\n#define listLast(l) ((l)->tail)\n#define listPrevNode(n) ((n)->prev)\n#define listNextNode(n) ((n)->next)\n#define listNodeValue(n) ((n)->value)\n\n#define listSetDupMethod(l,m) ((l)->dup = (m))\n#define listSetFreeMethod(l,m) ((l)->free = (m))\n#define listSetMatchMethod(l,m) ((l)->match = (m))\n\n#define listGetDupMethod(l) ((l)->dup)\n#define listGetFree(l) ((l)->free)\n#define listGetMatchMethod(l) ((l)->match)\n\n/* Prototypes */\nlist *listCreate(void);\nvoid listRelease(list *list);\nlist *listAddNodeHead(list *list, void *value);\nlist *listAddNodeTail(list *list, void *value);\nlist *listInsertNode(list *list, listNode *old_node, void *value, int after);\nvoid listDelNode(list *list, listNode *node);\nlistIter *listGetIterator(list *list, int direction);\nlistNode *listNext(listIter *iter);\nvoid listReleaseIterator(listIter *iter);\nlist *listDup(list *orig);\nlistNode *listSearchKey(list *list, void *key);\nlistNode *listIndex(list *list, long index);\nvoid listRewind(list *list, listIter *li);\nvoid listRewindTail(list *list, listIter *li);\nvoid listRotate(list *list);\n\n/* Directions for iterators */\n#define AL_START_HEAD 0\n#define AL_START_TAIL 1\n\n#endif /* __ADLIST_H__ */\n"
  },
  {
    "path": "extern/deprecated/redis-2.8.21/src/ae.c",
    "content": "/* A simple event-driven programming library. Originally I wrote this code\n * for the Jim's event-loop (Jim is a Tcl interpreter) but later translated\n * it in form of a library for easy reuse.\n *\n * Copyright (c) 2006-2010, Salvatore Sanfilippo <antirez at gmail dot com>\n * All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions are met:\n *\n *   * Redistributions of source code must retain the above copyright notice,\n *     this list of conditions and the following disclaimer.\n *   * Redistributions in binary form must reproduce the above copyright\n *     notice, this list of conditions and the following disclaimer in the\n *     documentation and/or other materials provided with the distribution.\n *   * Neither the name of Redis nor the names of its contributors may be used\n *     to endorse or promote products derived from this software without\n *     specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\"\n * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\n * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE\n * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR\n * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF\n * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS\n * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN\n * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)\n * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE\n * POSSIBILITY OF SUCH DAMAGE.\n */\n\n#include <stdio.h>\n#include <sys/time.h>\n#include <sys/types.h>\n#include <unistd.h>\n#include <stdlib.h>\n#include <poll.h>\n#include <string.h>\n#include <time.h>\n#include <errno.h>\n\n#include \"ae.h\"\n#include \"zmalloc.h\"\n#include \"config.h\"\n\n/* Include the best multiplexing layer supported by this system.\n * The following should be ordered by performances, descending. */\n#ifdef HAVE_EVPORT\n#include \"ae_evport.c\"\n#else\n    #ifdef HAVE_EPOLL\n    #include \"ae_epoll.c\"\n    #else\n        #ifdef HAVE_KQUEUE\n        #include \"ae_kqueue.c\"\n        #else\n        #include \"ae_select.c\"\n        #endif\n    #endif\n#endif\n\naeEventLoop *aeCreateEventLoop(int setsize) {\n    aeEventLoop *eventLoop;\n    int i;\n\n    if ((eventLoop = zmalloc(sizeof(*eventLoop))) == NULL) goto err;\n    eventLoop->events = zmalloc(sizeof(aeFileEvent)*setsize);\n    eventLoop->fired = zmalloc(sizeof(aeFiredEvent)*setsize);\n    if (eventLoop->events == NULL || eventLoop->fired == NULL) goto err;\n    eventLoop->setsize = setsize;\n    eventLoop->lastTime = time(NULL);\n    eventLoop->timeEventHead = NULL;\n    eventLoop->timeEventNextId = 0;\n    eventLoop->stop = 0;\n    eventLoop->maxfd = -1;\n    eventLoop->beforesleep = NULL;\n    if (aeApiCreate(eventLoop) == -1) goto err;\n    /* Events with mask == AE_NONE are not set. So let's initialize the\n     * vector with it. */\n    for (i = 0; i < setsize; i++)\n        eventLoop->events[i].mask = AE_NONE;\n    return eventLoop;\n\nerr:\n    if (eventLoop) {\n        zfree(eventLoop->events);\n        zfree(eventLoop->fired);\n        zfree(eventLoop);\n    }\n    return NULL;\n}\n\n/* Return the current set size. */\nint aeGetSetSize(aeEventLoop *eventLoop) {\n    return eventLoop->setsize;\n}\n\n/* Resize the maximum set size of the event loop.\n * If the requested set size is smaller than the current set size, but\n * there is already a file descriptor in use that is >= the requested\n * set size minus one, AE_ERR is returned and the operation is not\n * performed at all.\n *\n * Otherwise AE_OK is returned and the operation is successful. */\nint aeResizeSetSize(aeEventLoop *eventLoop, int setsize) {\n    int i;\n\n    if (setsize == eventLoop->setsize) return AE_OK;\n    if (eventLoop->maxfd >= setsize) return AE_ERR;\n    if (aeApiResize(eventLoop,setsize) == -1) return AE_ERR;\n\n    eventLoop->events = zrealloc(eventLoop->events,sizeof(aeFileEvent)*setsize);\n    eventLoop->fired = zrealloc(eventLoop->fired,sizeof(aeFiredEvent)*setsize);\n    eventLoop->setsize = setsize;\n\n    /* Make sure that if we created new slots, they are initialized with\n     * an AE_NONE mask. */\n    for (i = eventLoop->maxfd+1; i < setsize; i++)\n        eventLoop->events[i].mask = AE_NONE;\n    return AE_OK;\n}\n\nvoid aeDeleteEventLoop(aeEventLoop *eventLoop) {\n    aeApiFree(eventLoop);\n    zfree(eventLoop->events);\n    zfree(eventLoop->fired);\n    zfree(eventLoop);\n}\n\nvoid aeStop(aeEventLoop *eventLoop) {\n    eventLoop->stop = 1;\n}\n\nint aeCreateFileEvent(aeEventLoop *eventLoop, int fd, int mask,\n        aeFileProc *proc, void *clientData)\n{\n    if (fd >= eventLoop->setsize) {\n        errno = ERANGE;\n        return AE_ERR;\n    }\n    aeFileEvent *fe = &eventLoop->events[fd];\n\n    if (aeApiAddEvent(eventLoop, fd, mask) == -1)\n        return AE_ERR;\n    fe->mask |= mask;\n    if (mask & AE_READABLE) fe->rfileProc = proc;\n    if (mask & AE_WRITABLE) fe->wfileProc = proc;\n    fe->clientData = clientData;\n    if (fd > eventLoop->maxfd)\n        eventLoop->maxfd = fd;\n    return AE_OK;\n}\n\nvoid aeDeleteFileEvent(aeEventLoop *eventLoop, int fd, int mask)\n{\n    if (fd >= eventLoop->setsize) return;\n    aeFileEvent *fe = &eventLoop->events[fd];\n    if (fe->mask == AE_NONE) return;\n\n    aeApiDelEvent(eventLoop, fd, mask);\n    fe->mask = fe->mask & (~mask);\n    if (fd == eventLoop->maxfd && fe->mask == AE_NONE) {\n        /* Update the max fd */\n        int j;\n\n        for (j = eventLoop->maxfd-1; j >= 0; j--)\n            if (eventLoop->events[j].mask != AE_NONE) break;\n        eventLoop->maxfd = j;\n    }\n}\n\nint aeGetFileEvents(aeEventLoop *eventLoop, int fd) {\n    if (fd >= eventLoop->setsize) return 0;\n    aeFileEvent *fe = &eventLoop->events[fd];\n\n    return fe->mask;\n}\n\nstatic void aeGetTime(long *seconds, long *milliseconds)\n{\n    struct timeval tv;\n\n    gettimeofday(&tv, NULL);\n    *seconds = tv.tv_sec;\n    *milliseconds = tv.tv_usec/1000;\n}\n\nstatic void aeAddMillisecondsToNow(long long milliseconds, long *sec, long *ms) {\n    long cur_sec, cur_ms, when_sec, when_ms;\n\n    aeGetTime(&cur_sec, &cur_ms);\n    when_sec = cur_sec + milliseconds/1000;\n    when_ms = cur_ms + milliseconds%1000;\n    if (when_ms >= 1000) {\n        when_sec ++;\n        when_ms -= 1000;\n    }\n    *sec = when_sec;\n    *ms = when_ms;\n}\n\nlong long aeCreateTimeEvent(aeEventLoop *eventLoop, long long milliseconds,\n        aeTimeProc *proc, void *clientData,\n        aeEventFinalizerProc *finalizerProc)\n{\n    long long id = eventLoop->timeEventNextId++;\n    aeTimeEvent *te;\n\n    te = zmalloc(sizeof(*te));\n    if (te == NULL) return AE_ERR;\n    te->id = id;\n    aeAddMillisecondsToNow(milliseconds,&te->when_sec,&te->when_ms);\n    te->timeProc = proc;\n    te->finalizerProc = finalizerProc;\n    te->clientData = clientData;\n    te->next = eventLoop->timeEventHead;\n    eventLoop->timeEventHead = te;\n    return id;\n}\n\nint aeDeleteTimeEvent(aeEventLoop *eventLoop, long long id)\n{\n    aeTimeEvent *te, *prev = NULL;\n\n    te = eventLoop->timeEventHead;\n    while(te) {\n        if (te->id == id) {\n            if (prev == NULL)\n                eventLoop->timeEventHead = te->next;\n            else\n                prev->next = te->next;\n            if (te->finalizerProc)\n                te->finalizerProc(eventLoop, te->clientData);\n            zfree(te);\n            return AE_OK;\n        }\n        prev = te;\n        te = te->next;\n    }\n    return AE_ERR; /* NO event with the specified ID found */\n}\n\n/* Search the first timer to fire.\n * This operation is useful to know how many time the select can be\n * put in sleep without to delay any event.\n * If there are no timers NULL is returned.\n *\n * Note that's O(N) since time events are unsorted.\n * Possible optimizations (not needed by Redis so far, but...):\n * 1) Insert the event in order, so that the nearest is just the head.\n *    Much better but still insertion or deletion of timers is O(N).\n * 2) Use a skiplist to have this operation as O(1) and insertion as O(log(N)).\n */\nstatic aeTimeEvent *aeSearchNearestTimer(aeEventLoop *eventLoop)\n{\n    aeTimeEvent *te = eventLoop->timeEventHead;\n    aeTimeEvent *nearest = NULL;\n\n    while(te) {\n        if (!nearest || te->when_sec < nearest->when_sec ||\n                (te->when_sec == nearest->when_sec &&\n                 te->when_ms < nearest->when_ms))\n            nearest = te;\n        te = te->next;\n    }\n    return nearest;\n}\n\n/* Process time events */\nstatic int processTimeEvents(aeEventLoop *eventLoop) {\n    int processed = 0;\n    aeTimeEvent *te;\n    long long maxId;\n    time_t now = time(NULL);\n\n    /* If the system clock is moved to the future, and then set back to the\n     * right value, time events may be delayed in a random way. Often this\n     * means that scheduled operations will not be performed soon enough.\n     *\n     * Here we try to detect system clock skews, and force all the time\n     * events to be processed ASAP when this happens: the idea is that\n     * processing events earlier is less dangerous than delaying them\n     * indefinitely, and practice suggests it is. */\n    if (now < eventLoop->lastTime) {\n        te = eventLoop->timeEventHead;\n        while(te) {\n            te->when_sec = 0;\n            te = te->next;\n        }\n    }\n    eventLoop->lastTime = now;\n\n    te = eventLoop->timeEventHead;\n    maxId = eventLoop->timeEventNextId-1;\n    while(te) {\n        long now_sec, now_ms;\n        long long id;\n\n        if (te->id > maxId) {\n            te = te->next;\n            continue;\n        }\n        aeGetTime(&now_sec, &now_ms);\n        if (now_sec > te->when_sec ||\n            (now_sec == te->when_sec && now_ms >= te->when_ms))\n        {\n            int retval;\n\n            id = te->id;\n            retval = te->timeProc(eventLoop, id, te->clientData);\n            processed++;\n            /* After an event is processed our time event list may\n             * no longer be the same, so we restart from head.\n             * Still we make sure to don't process events registered\n             * by event handlers itself in order to don't loop forever.\n             * To do so we saved the max ID we want to handle.\n             *\n             * FUTURE OPTIMIZATIONS:\n             * Note that this is NOT great algorithmically. Redis uses\n             * a single time event so it's not a problem but the right\n             * way to do this is to add the new elements on head, and\n             * to flag deleted elements in a special way for later\n             * deletion (putting references to the nodes to delete into\n             * another linked list). */\n            if (retval != AE_NOMORE) {\n                aeAddMillisecondsToNow(retval,&te->when_sec,&te->when_ms);\n            } else {\n                aeDeleteTimeEvent(eventLoop, id);\n            }\n            te = eventLoop->timeEventHead;\n        } else {\n            te = te->next;\n        }\n    }\n    return processed;\n}\n\n/* Process every pending time event, then every pending file event\n * (that may be registered by time event callbacks just processed).\n * Without special flags the function sleeps until some file event\n * fires, or when the next time event occurs (if any).\n *\n * If flags is 0, the function does nothing and returns.\n * if flags has AE_ALL_EVENTS set, all the kind of events are processed.\n * if flags has AE_FILE_EVENTS set, file events are processed.\n * if flags has AE_TIME_EVENTS set, time events are processed.\n * if flags has AE_DONT_WAIT set the function returns ASAP until all\n * the events that's possible to process without to wait are processed.\n *\n * The function returns the number of events processed. */\nint aeProcessEvents(aeEventLoop *eventLoop, int flags)\n{\n    int processed = 0, numevents;\n\n    /* Nothing to do? return ASAP */\n    if (!(flags & AE_TIME_EVENTS) && !(flags & AE_FILE_EVENTS)) return 0;\n\n    /* Note that we want call select() even if there are no\n     * file events to process as long as we want to process time\n     * events, in order to sleep until the next time event is ready\n     * to fire. */\n    if (eventLoop->maxfd != -1 ||\n        ((flags & AE_TIME_EVENTS) && !(flags & AE_DONT_WAIT))) {\n        int j;\n        aeTimeEvent *shortest = NULL;\n        struct timeval tv, *tvp;\n\n        if (flags & AE_TIME_EVENTS && !(flags & AE_DONT_WAIT))\n            shortest = aeSearchNearestTimer(eventLoop);\n        if (shortest) {\n            long now_sec, now_ms;\n\n            /* Calculate the time missing for the nearest\n             * timer to fire. */\n            aeGetTime(&now_sec, &now_ms);\n            tvp = &tv;\n            tvp->tv_sec = shortest->when_sec - now_sec;\n            if (shortest->when_ms < now_ms) {\n                tvp->tv_usec = ((shortest->when_ms+1000) - now_ms)*1000;\n                tvp->tv_sec --;\n            } else {\n                tvp->tv_usec = (shortest->when_ms - now_ms)*1000;\n            }\n            if (tvp->tv_sec < 0) tvp->tv_sec = 0;\n            if (tvp->tv_usec < 0) tvp->tv_usec = 0;\n        } else {\n            /* If we have to check for events but need to return\n             * ASAP because of AE_DONT_WAIT we need to set the timeout\n             * to zero */\n            if (flags & AE_DONT_WAIT) {\n                tv.tv_sec = tv.tv_usec = 0;\n                tvp = &tv;\n            } else {\n                /* Otherwise we can block */\n                tvp = NULL; /* wait forever */\n            }\n        }\n\n        numevents = aeApiPoll(eventLoop, tvp);\n        for (j = 0; j < numevents; j++) {\n            aeFileEvent *fe = &eventLoop->events[eventLoop->fired[j].fd];\n            int mask = eventLoop->fired[j].mask;\n            int fd = eventLoop->fired[j].fd;\n            int rfired = 0;\n\n\t    /* note the fe->mask & mask & ... code: maybe an already processed\n             * event removed an element that fired and we still didn't\n             * processed, so we check if the event is still valid. */\n            if (fe->mask & mask & AE_READABLE) {\n                rfired = 1;\n                fe->rfileProc(eventLoop,fd,fe->clientData,mask);\n            }\n            if (fe->mask & mask & AE_WRITABLE) {\n                if (!rfired || fe->wfileProc != fe->rfileProc)\n                    fe->wfileProc(eventLoop,fd,fe->clientData,mask);\n            }\n            processed++;\n        }\n    }\n    /* Check time events */\n    if (flags & AE_TIME_EVENTS)\n        processed += processTimeEvents(eventLoop);\n\n    return processed; /* return the number of processed file/time events */\n}\n\n/* Wait for milliseconds until the given file descriptor becomes\n * writable/readable/exception */\nint aeWait(int fd, int mask, long long milliseconds) {\n    struct pollfd pfd;\n    int retmask = 0, retval;\n\n    memset(&pfd, 0, sizeof(pfd));\n    pfd.fd = fd;\n    if (mask & AE_READABLE) pfd.events |= POLLIN;\n    if (mask & AE_WRITABLE) pfd.events |= POLLOUT;\n\n    if ((retval = poll(&pfd, 1, milliseconds))== 1) {\n        if (pfd.revents & POLLIN) retmask |= AE_READABLE;\n        if (pfd.revents & POLLOUT) retmask |= AE_WRITABLE;\n\tif (pfd.revents & POLLERR) retmask |= AE_WRITABLE;\n        if (pfd.revents & POLLHUP) retmask |= AE_WRITABLE;\n        return retmask;\n    } else {\n        return retval;\n    }\n}\n\nvoid aeMain(aeEventLoop *eventLoop) {\n    eventLoop->stop = 0;\n    while (!eventLoop->stop) {\n        if (eventLoop->beforesleep != NULL)\n            eventLoop->beforesleep(eventLoop);\n        aeProcessEvents(eventLoop, AE_ALL_EVENTS);\n    }\n}\n\nchar *aeGetApiName(void) {\n    return aeApiName();\n}\n\nvoid aeSetBeforeSleepProc(aeEventLoop *eventLoop, aeBeforeSleepProc *beforesleep) {\n    eventLoop->beforesleep = beforesleep;\n}\n"
  },
  {
    "path": "extern/deprecated/redis-2.8.21/src/ae.h",
    "content": "/* A simple event-driven programming library. Originally I wrote this code\n * for the Jim's event-loop (Jim is a Tcl interpreter) but later translated\n * it in form of a library for easy reuse.\n *\n * Copyright (c) 2006-2012, Salvatore Sanfilippo <antirez at gmail dot com>\n * All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions are met:\n *\n *   * Redistributions of source code must retain the above copyright notice,\n *     this list of conditions and the following disclaimer.\n *   * Redistributions in binary form must reproduce the above copyright\n *     notice, this list of conditions and the following disclaimer in the\n *     documentation and/or other materials provided with the distribution.\n *   * Neither the name of Redis nor the names of its contributors may be used\n *     to endorse or promote products derived from this software without\n *     specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\"\n * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\n * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE\n * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR\n * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF\n * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS\n * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN\n * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)\n * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE\n * POSSIBILITY OF SUCH DAMAGE.\n */\n\n#ifndef __AE_H__\n#define __AE_H__\n\n#define AE_OK 0\n#define AE_ERR -1\n\n#define AE_NONE 0\n#define AE_READABLE 1\n#define AE_WRITABLE 2\n\n#define AE_FILE_EVENTS 1\n#define AE_TIME_EVENTS 2\n#define AE_ALL_EVENTS (AE_FILE_EVENTS|AE_TIME_EVENTS)\n#define AE_DONT_WAIT 4\n\n#define AE_NOMORE -1\n\n/* Macros */\n#define AE_NOTUSED(V) ((void) V)\n\nstruct aeEventLoop;\n\n/* Types and data structures */\ntypedef void aeFileProc(struct aeEventLoop *eventLoop, int fd, void *clientData, int mask);\ntypedef int aeTimeProc(struct aeEventLoop *eventLoop, long long id, void *clientData);\ntypedef void aeEventFinalizerProc(struct aeEventLoop *eventLoop, void *clientData);\ntypedef void aeBeforeSleepProc(struct aeEventLoop *eventLoop);\n\n/* File event structure */\ntypedef struct aeFileEvent {\n    int mask; /* one of AE_(READABLE|WRITABLE) */\n    aeFileProc *rfileProc;\n    aeFileProc *wfileProc;\n    void *clientData;\n} aeFileEvent;\n\n/* Time event structure */\ntypedef struct aeTimeEvent {\n    long long id; /* time event identifier. */\n    long when_sec; /* seconds */\n    long when_ms; /* milliseconds */\n    aeTimeProc *timeProc;\n    aeEventFinalizerProc *finalizerProc;\n    void *clientData;\n    struct aeTimeEvent *next;\n} aeTimeEvent;\n\n/* A fired event */\ntypedef struct aeFiredEvent {\n    int fd;\n    int mask;\n} aeFiredEvent;\n\n/* State of an event based program */\ntypedef struct aeEventLoop {\n    int maxfd;   /* highest file descriptor currently registered */\n    int setsize; /* max number of file descriptors tracked */\n    long long timeEventNextId;\n    time_t lastTime;     /* Used to detect system clock skew */\n    aeFileEvent *events; /* Registered events */\n    aeFiredEvent *fired; /* Fired events */\n    aeTimeEvent *timeEventHead;\n    int stop;\n    void *apidata; /* This is used for polling API specific data */\n    aeBeforeSleepProc *beforesleep;\n} aeEventLoop;\n\n/* Prototypes */\naeEventLoop *aeCreateEventLoop(int setsize);\nvoid aeDeleteEventLoop(aeEventLoop *eventLoop);\nvoid aeStop(aeEventLoop *eventLoop);\nint aeCreateFileEvent(aeEventLoop *eventLoop, int fd, int mask,\n        aeFileProc *proc, void *clientData);\nvoid aeDeleteFileEvent(aeEventLoop *eventLoop, int fd, int mask);\nint aeGetFileEvents(aeEventLoop *eventLoop, int fd);\nlong long aeCreateTimeEvent(aeEventLoop *eventLoop, long long milliseconds,\n        aeTimeProc *proc, void *clientData,\n        aeEventFinalizerProc *finalizerProc);\nint aeDeleteTimeEvent(aeEventLoop *eventLoop, long long id);\nint aeProcessEvents(aeEventLoop *eventLoop, int flags);\nint aeWait(int fd, int mask, long long milliseconds);\nvoid aeMain(aeEventLoop *eventLoop);\nchar *aeGetApiName(void);\nvoid aeSetBeforeSleepProc(aeEventLoop *eventLoop, aeBeforeSleepProc *beforesleep);\nint aeGetSetSize(aeEventLoop *eventLoop);\nint aeResizeSetSize(aeEventLoop *eventLoop, int setsize);\n\n#endif\n"
  },
  {
    "path": "extern/deprecated/redis-2.8.21/src/ae_epoll.c",
    "content": "/* Linux epoll(2) based ae.c module\n *\n * Copyright (c) 2009-2012, Salvatore Sanfilippo <antirez at gmail dot com>\n * All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions are met:\n *\n *   * Redistributions of source code must retain the above copyright notice,\n *     this list of conditions and the following disclaimer.\n *   * Redistributions in binary form must reproduce the above copyright\n *     notice, this list of conditions and the following disclaimer in the\n *     documentation and/or other materials provided with the distribution.\n *   * Neither the name of Redis nor the names of its contributors may be used\n *     to endorse or promote products derived from this software without\n *     specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\"\n * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\n * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE\n * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR\n * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF\n * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS\n * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN\n * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)\n * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE\n * POSSIBILITY OF SUCH DAMAGE.\n */\n\n\n#include <sys/epoll.h>\n\ntypedef struct aeApiState {\n    int epfd;\n    struct epoll_event *events;\n} aeApiState;\n\nstatic int aeApiCreate(aeEventLoop *eventLoop) {\n    aeApiState *state = zmalloc(sizeof(aeApiState));\n\n    if (!state) return -1;\n    state->events = zmalloc(sizeof(struct epoll_event)*eventLoop->setsize);\n    if (!state->events) {\n        zfree(state);\n        return -1;\n    }\n    state->epfd = epoll_create(1024); /* 1024 is just a hint for the kernel */\n    if (state->epfd == -1) {\n        zfree(state->events);\n        zfree(state);\n        return -1;\n    }\n    eventLoop->apidata = state;\n    return 0;\n}\n\nstatic int aeApiResize(aeEventLoop *eventLoop, int setsize) {\n    aeApiState *state = eventLoop->apidata;\n\n    state->events = zrealloc(state->events, sizeof(struct epoll_event)*setsize);\n    return 0;\n}\n\nstatic void aeApiFree(aeEventLoop *eventLoop) {\n    aeApiState *state = eventLoop->apidata;\n\n    close(state->epfd);\n    zfree(state->events);\n    zfree(state);\n}\n\nstatic int aeApiAddEvent(aeEventLoop *eventLoop, int fd, int mask) {\n    aeApiState *state = eventLoop->apidata;\n    struct epoll_event ee;\n    /* If the fd was already monitored for some event, we need a MOD\n     * operation. Otherwise we need an ADD operation. */\n    int op = eventLoop->events[fd].mask == AE_NONE ?\n            EPOLL_CTL_ADD : EPOLL_CTL_MOD;\n\n    ee.events = 0;\n    mask |= eventLoop->events[fd].mask; /* Merge old events */\n    if (mask & AE_READABLE) ee.events |= EPOLLIN;\n    if (mask & AE_WRITABLE) ee.events |= EPOLLOUT;\n    ee.data.u64 = 0; /* avoid valgrind warning */\n    ee.data.fd = fd;\n    if (epoll_ctl(state->epfd,op,fd,&ee) == -1) return -1;\n    return 0;\n}\n\nstatic void aeApiDelEvent(aeEventLoop *eventLoop, int fd, int delmask) {\n    aeApiState *state = eventLoop->apidata;\n    struct epoll_event ee;\n    int mask = eventLoop->events[fd].mask & (~delmask);\n\n    ee.events = 0;\n    if (mask & AE_READABLE) ee.events |= EPOLLIN;\n    if (mask & AE_WRITABLE) ee.events |= EPOLLOUT;\n    ee.data.u64 = 0; /* avoid valgrind warning */\n    ee.data.fd = fd;\n    if (mask != AE_NONE) {\n        epoll_ctl(state->epfd,EPOLL_CTL_MOD,fd,&ee);\n    } else {\n        /* Note, Kernel < 2.6.9 requires a non null event pointer even for\n         * EPOLL_CTL_DEL. */\n        epoll_ctl(state->epfd,EPOLL_CTL_DEL,fd,&ee);\n    }\n}\n\nstatic int aeApiPoll(aeEventLoop *eventLoop, struct timeval *tvp) {\n    aeApiState *state = eventLoop->apidata;\n    int retval, numevents = 0;\n\n    retval = epoll_wait(state->epfd,state->events,eventLoop->setsize,\n            tvp ? (tvp->tv_sec*1000 + tvp->tv_usec/1000) : -1);\n    if (retval > 0) {\n        int j;\n\n        numevents = retval;\n        for (j = 0; j < numevents; j++) {\n            int mask = 0;\n            struct epoll_event *e = state->events+j;\n\n            if (e->events & EPOLLIN) mask |= AE_READABLE;\n            if (e->events & EPOLLOUT) mask |= AE_WRITABLE;\n            if (e->events & EPOLLERR) mask |= AE_WRITABLE;\n            if (e->events & EPOLLHUP) mask |= AE_WRITABLE;\n            eventLoop->fired[j].fd = e->data.fd;\n            eventLoop->fired[j].mask = mask;\n        }\n    }\n    return numevents;\n}\n\nstatic char *aeApiName(void) {\n    return \"epoll\";\n}\n"
  },
  {
    "path": "extern/deprecated/redis-2.8.21/src/ae_evport.c",
    "content": "/* ae.c module for illumos event ports.\n *\n * Copyright (c) 2012, Joyent, Inc. All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions are met:\n *\n *   * Redistributions of source code must retain the above copyright notice,\n *     this list of conditions and the following disclaimer.\n *   * Redistributions in binary form must reproduce the above copyright\n *     notice, this list of conditions and the following disclaimer in the\n *     documentation and/or other materials provided with the distribution.\n *   * Neither the name of Redis nor the names of its contributors may be used\n *     to endorse or promote products derived from this software without\n *     specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\"\n * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\n * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE\n * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR\n * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF\n * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS\n * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN\n * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)\n * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE\n * POSSIBILITY OF SUCH DAMAGE.\n */\n\n\n#include <assert.h>\n#include <errno.h>\n#include <port.h>\n#include <poll.h>\n\n#include <sys/types.h>\n#include <sys/time.h>\n\n#include <stdio.h>\n\nstatic int evport_debug = 0;\n\n/*\n * This file implements the ae API using event ports, present on Solaris-based\n * systems since Solaris 10.  Using the event port interface, we associate file\n * descriptors with the port.  Each association also includes the set of poll(2)\n * events that the consumer is interested in (e.g., POLLIN and POLLOUT).\n *\n * There's one tricky piece to this implementation: when we return events via\n * aeApiPoll, the corresponding file descriptors become dissociated from the\n * port.  This is necessary because poll events are level-triggered, so if the\n * fd didn't become dissociated, it would immediately fire another event since\n * the underlying state hasn't changed yet.  We must re-associate the file\n * descriptor, but only after we know that our caller has actually read from it.\n * The ae API does not tell us exactly when that happens, but we do know that\n * it must happen by the time aeApiPoll is called again.  Our solution is to\n * keep track of the last fds returned by aeApiPoll and re-associate them next\n * time aeApiPoll is invoked.\n *\n * To summarize, in this module, each fd association is EITHER (a) represented\n * only via the in-kernel association OR (b) represented by pending_fds and\n * pending_masks.  (b) is only true for the last fds we returned from aeApiPoll,\n * and only until we enter aeApiPoll again (at which point we restore the\n * in-kernel association).\n */\n#define MAX_EVENT_BATCHSZ 512\n\ntypedef struct aeApiState {\n    int     portfd;                             /* event port */\n    int     npending;                           /* # of pending fds */\n    int     pending_fds[MAX_EVENT_BATCHSZ];     /* pending fds */\n    int     pending_masks[MAX_EVENT_BATCHSZ];   /* pending fds' masks */\n} aeApiState;\n\nstatic int aeApiCreate(aeEventLoop *eventLoop) {\n    int i;\n    aeApiState *state = zmalloc(sizeof(aeApiState));\n    if (!state) return -1;\n\n    state->portfd = port_create();\n    if (state->portfd == -1) {\n        zfree(state);\n        return -1;\n    }\n\n    state->npending = 0;\n\n    for (i = 0; i < MAX_EVENT_BATCHSZ; i++) {\n        state->pending_fds[i] = -1;\n        state->pending_masks[i] = AE_NONE;\n    }\n\n    eventLoop->apidata = state;\n    return 0;\n}\n\nstatic int aeApiResize(aeEventLoop *eventLoop, int setsize) {\n    /* Nothing to resize here. */\n    return 0;\n}\n\nstatic void aeApiFree(aeEventLoop *eventLoop) {\n    aeApiState *state = eventLoop->apidata;\n\n    close(state->portfd);\n    zfree(state);\n}\n\nstatic int aeApiLookupPending(aeApiState *state, int fd) {\n    int i;\n\n    for (i = 0; i < state->npending; i++) {\n        if (state->pending_fds[i] == fd)\n            return (i);\n    }\n\n    return (-1);\n}\n\n/*\n * Helper function to invoke port_associate for the given fd and mask.\n */\nstatic int aeApiAssociate(const char *where, int portfd, int fd, int mask) {\n    int events = 0;\n    int rv, err;\n\n    if (mask & AE_READABLE)\n        events |= POLLIN;\n    if (mask & AE_WRITABLE)\n        events |= POLLOUT;\n\n    if (evport_debug)\n        fprintf(stderr, \"%s: port_associate(%d, 0x%x) = \", where, fd, events);\n\n    rv = port_associate(portfd, PORT_SOURCE_FD, fd, events,\n        (void *)(uintptr_t)mask);\n    err = errno;\n\n    if (evport_debug)\n        fprintf(stderr, \"%d (%s)\\n\", rv, rv == 0 ? \"no error\" : strerror(err));\n\n    if (rv == -1) {\n        fprintf(stderr, \"%s: port_associate: %s\\n\", where, strerror(err));\n\n        if (err == EAGAIN)\n            fprintf(stderr, \"aeApiAssociate: event port limit exceeded.\");\n    }\n\n    return rv;\n}\n\nstatic int aeApiAddEvent(aeEventLoop *eventLoop, int fd, int mask) {\n    aeApiState *state = eventLoop->apidata;\n    int fullmask, pfd;\n\n    if (evport_debug)\n        fprintf(stderr, \"aeApiAddEvent: fd %d mask 0x%x\\n\", fd, mask);\n\n    /*\n     * Since port_associate's \"events\" argument replaces any existing events, we\n     * must be sure to include whatever events are already associated when\n     * we call port_associate() again.\n     */\n    fullmask = mask | eventLoop->events[fd].mask;\n    pfd = aeApiLookupPending(state, fd);\n\n    if (pfd != -1) {\n        /*\n         * This fd was recently returned from aeApiPoll.  It should be safe to\n         * assume that the consumer has processed that poll event, but we play\n         * it safer by simply updating pending_mask.  The fd will be\n         * re-associated as usual when aeApiPoll is called again.\n         */\n        if (evport_debug)\n            fprintf(stderr, \"aeApiAddEvent: adding to pending fd %d\\n\", fd);\n        state->pending_masks[pfd] |= fullmask;\n        return 0;\n    }\n\n    return (aeApiAssociate(\"aeApiAddEvent\", state->portfd, fd, fullmask));\n}\n\nstatic void aeApiDelEvent(aeEventLoop *eventLoop, int fd, int mask) {\n    aeApiState *state = eventLoop->apidata;\n    int fullmask, pfd;\n\n    if (evport_debug)\n        fprintf(stderr, \"del fd %d mask 0x%x\\n\", fd, mask);\n\n    pfd = aeApiLookupPending(state, fd);\n\n    if (pfd != -1) {\n        if (evport_debug)\n            fprintf(stderr, \"deleting event from pending fd %d\\n\", fd);\n\n        /*\n         * This fd was just returned from aeApiPoll, so it's not currently\n         * associated with the port.  All we need to do is update\n         * pending_mask appropriately.\n         */\n        state->pending_masks[pfd] &= ~mask;\n\n        if (state->pending_masks[pfd] == AE_NONE)\n            state->pending_fds[pfd] = -1;\n\n        return;\n    }\n\n    /*\n     * The fd is currently associated with the port.  Like with the add case\n     * above, we must look at the full mask for the file descriptor before\n     * updating that association.  We don't have a good way of knowing what the\n     * events are without looking into the eventLoop state directly.  We rely on\n     * the fact that our caller has already updated the mask in the eventLoop.\n     */\n\n    fullmask = eventLoop->events[fd].mask;\n    if (fullmask == AE_NONE) {\n        /*\n         * We're removing *all* events, so use port_dissociate to remove the\n         * association completely.  Failure here indicates a bug.\n         */\n        if (evport_debug)\n            fprintf(stderr, \"aeApiDelEvent: port_dissociate(%d)\\n\", fd);\n\n        if (port_dissociate(state->portfd, PORT_SOURCE_FD, fd) != 0) {\n            perror(\"aeApiDelEvent: port_dissociate\");\n            abort(); /* will not return */\n        }\n    } else if (aeApiAssociate(\"aeApiDelEvent\", state->portfd, fd,\n        fullmask) != 0) {\n        /*\n         * ENOMEM is a potentially transient condition, but the kernel won't\n         * generally return it unless things are really bad.  EAGAIN indicates\n         * we've reached an resource limit, for which it doesn't make sense to\n         * retry (counter-intuitively).  All other errors indicate a bug.  In any\n         * of these cases, the best we can do is to abort.\n         */\n        abort(); /* will not return */\n    }\n}\n\nstatic int aeApiPoll(aeEventLoop *eventLoop, struct timeval *tvp) {\n    aeApiState *state = eventLoop->apidata;\n    struct timespec timeout, *tsp;\n    int mask, i;\n    uint_t nevents;\n    port_event_t event[MAX_EVENT_BATCHSZ];\n\n    /*\n     * If we've returned fd events before, we must re-associate them with the\n     * port now, before calling port_get().  See the block comment at the top of\n     * this file for an explanation of why.\n     */\n    for (i = 0; i < state->npending; i++) {\n        if (state->pending_fds[i] == -1)\n            /* This fd has since been deleted. */\n            continue;\n\n        if (aeApiAssociate(\"aeApiPoll\", state->portfd,\n            state->pending_fds[i], state->pending_masks[i]) != 0) {\n            /* See aeApiDelEvent for why this case is fatal. */\n            abort();\n        }\n\n        state->pending_masks[i] = AE_NONE;\n        state->pending_fds[i] = -1;\n    }\n\n    state->npending = 0;\n\n    if (tvp != NULL) {\n        timeout.tv_sec = tvp->tv_sec;\n        timeout.tv_nsec = tvp->tv_usec * 1000;\n        tsp = &timeout;\n    } else {\n        tsp = NULL;\n    }\n\n    /*\n     * port_getn can return with errno == ETIME having returned some events (!).\n     * So if we get ETIME, we check nevents, too.\n     */\n    nevents = 1;\n    if (port_getn(state->portfd, event, MAX_EVENT_BATCHSZ, &nevents,\n        tsp) == -1 && (errno != ETIME || nevents == 0)) {\n        if (errno == ETIME || errno == EINTR)\n            return 0;\n\n        /* Any other error indicates a bug. */\n        perror(\"aeApiPoll: port_get\");\n        abort();\n    }\n\n    state->npending = nevents;\n\n    for (i = 0; i < nevents; i++) {\n            mask = 0;\n            if (event[i].portev_events & POLLIN)\n                mask |= AE_READABLE;\n            if (event[i].portev_events & POLLOUT)\n                mask |= AE_WRITABLE;\n\n            eventLoop->fired[i].fd = event[i].portev_object;\n            eventLoop->fired[i].mask = mask;\n\n            if (evport_debug)\n                fprintf(stderr, \"aeApiPoll: fd %d mask 0x%x\\n\",\n                    (int)event[i].portev_object, mask);\n\n            state->pending_fds[i] = event[i].portev_object;\n            state->pending_masks[i] = (uintptr_t)event[i].portev_user;\n    }\n\n    return nevents;\n}\n\nstatic char *aeApiName(void) {\n    return \"evport\";\n}\n"
  },
  {
    "path": "extern/deprecated/redis-2.8.21/src/ae_kqueue.c",
    "content": "/* Kqueue(2)-based ae.c module\n *\n * Copyright (C) 2009 Harish Mallipeddi - harish.mallipeddi@gmail.com\n * All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions are met:\n *\n *   * Redistributions of source code must retain the above copyright notice,\n *     this list of conditions and the following disclaimer.\n *   * Redistributions in binary form must reproduce the above copyright\n *     notice, this list of conditions and the following disclaimer in the\n *     documentation and/or other materials provided with the distribution.\n *   * Neither the name of Redis nor the names of its contributors may be used\n *     to endorse or promote products derived from this software without\n *     specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\"\n * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\n * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE\n * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR\n * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF\n * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS\n * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN\n * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)\n * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE\n * POSSIBILITY OF SUCH DAMAGE.\n */\n\n\n#include <sys/types.h>\n#include <sys/event.h>\n#include <sys/time.h>\n\ntypedef struct aeApiState {\n    int kqfd;\n    struct kevent *events;\n} aeApiState;\n\nstatic int aeApiCreate(aeEventLoop *eventLoop) {\n    aeApiState *state = zmalloc(sizeof(aeApiState));\n\n    if (!state) return -1;\n    state->events = zmalloc(sizeof(struct kevent)*eventLoop->setsize);\n    if (!state->events) {\n        zfree(state);\n        return -1;\n    }\n    state->kqfd = kqueue();\n    if (state->kqfd == -1) {\n        zfree(state->events);\n        zfree(state);\n        return -1;\n    }\n    eventLoop->apidata = state;\n    return 0;\n}\n\nstatic int aeApiResize(aeEventLoop *eventLoop, int setsize) {\n    aeApiState *state = eventLoop->apidata;\n\n    state->events = zrealloc(state->events, sizeof(struct kevent)*setsize);\n    return 0;\n}\n\nstatic void aeApiFree(aeEventLoop *eventLoop) {\n    aeApiState *state = eventLoop->apidata;\n\n    close(state->kqfd);\n    zfree(state->events);\n    zfree(state);\n}\n\nstatic int aeApiAddEvent(aeEventLoop *eventLoop, int fd, int mask) {\n    aeApiState *state = eventLoop->apidata;\n    struct kevent ke;\n\n    if (mask & AE_READABLE) {\n        EV_SET(&ke, fd, EVFILT_READ, EV_ADD, 0, 0, NULL);\n        if (kevent(state->kqfd, &ke, 1, NULL, 0, NULL) == -1) return -1;\n    }\n    if (mask & AE_WRITABLE) {\n        EV_SET(&ke, fd, EVFILT_WRITE, EV_ADD, 0, 0, NULL);\n        if (kevent(state->kqfd, &ke, 1, NULL, 0, NULL) == -1) return -1;\n    }\n    return 0;\n}\n\nstatic void aeApiDelEvent(aeEventLoop *eventLoop, int fd, int mask) {\n    aeApiState *state = eventLoop->apidata;\n    struct kevent ke;\n\n    if (mask & AE_READABLE) {\n        EV_SET(&ke, fd, EVFILT_READ, EV_DELETE, 0, 0, NULL);\n        kevent(state->kqfd, &ke, 1, NULL, 0, NULL);\n    }\n    if (mask & AE_WRITABLE) {\n        EV_SET(&ke, fd, EVFILT_WRITE, EV_DELETE, 0, 0, NULL);\n        kevent(state->kqfd, &ke, 1, NULL, 0, NULL);\n    }\n}\n\nstatic int aeApiPoll(aeEventLoop *eventLoop, struct timeval *tvp) {\n    aeApiState *state = eventLoop->apidata;\n    int retval, numevents = 0;\n\n    if (tvp != NULL) {\n        struct timespec timeout;\n        timeout.tv_sec = tvp->tv_sec;\n        timeout.tv_nsec = tvp->tv_usec * 1000;\n        retval = kevent(state->kqfd, NULL, 0, state->events, eventLoop->setsize,\n                        &timeout);\n    } else {\n        retval = kevent(state->kqfd, NULL, 0, state->events, eventLoop->setsize,\n                        NULL);\n    }\n\n    if (retval > 0) {\n        int j;\n\n        numevents = retval;\n        for(j = 0; j < numevents; j++) {\n            int mask = 0;\n            struct kevent *e = state->events+j;\n\n            if (e->filter == EVFILT_READ) mask |= AE_READABLE;\n            if (e->filter == EVFILT_WRITE) mask |= AE_WRITABLE;\n            eventLoop->fired[j].fd = e->ident;\n            eventLoop->fired[j].mask = mask;\n        }\n    }\n    return numevents;\n}\n\nstatic char *aeApiName(void) {\n    return \"kqueue\";\n}\n"
  },
  {
    "path": "extern/deprecated/redis-2.8.21/src/ae_select.c",
    "content": "/* Select()-based ae.c module.\n *\n * Copyright (c) 2009-2012, Salvatore Sanfilippo <antirez at gmail dot com>\n * All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions are met:\n *\n *   * Redistributions of source code must retain the above copyright notice,\n *     this list of conditions and the following disclaimer.\n *   * Redistributions in binary form must reproduce the above copyright\n *     notice, this list of conditions and the following disclaimer in the\n *     documentation and/or other materials provided with the distribution.\n *   * Neither the name of Redis nor the names of its contributors may be used\n *     to endorse or promote products derived from this software without\n *     specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\"\n * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\n * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE\n * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR\n * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF\n * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS\n * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN\n * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)\n * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE\n * POSSIBILITY OF SUCH DAMAGE.\n */\n\n\n#include <string.h>\n\ntypedef struct aeApiState {\n    fd_set rfds, wfds;\n    /* We need to have a copy of the fd sets as it's not safe to reuse\n     * FD sets after select(). */\n    fd_set _rfds, _wfds;\n} aeApiState;\n\nstatic int aeApiCreate(aeEventLoop *eventLoop) {\n    aeApiState *state = zmalloc(sizeof(aeApiState));\n\n    if (!state) return -1;\n    FD_ZERO(&state->rfds);\n    FD_ZERO(&state->wfds);\n    eventLoop->apidata = state;\n    return 0;\n}\n\nstatic int aeApiResize(aeEventLoop *eventLoop, int setsize) {\n    /* Just ensure we have enough room in the fd_set type. */\n    if (setsize >= FD_SETSIZE) return -1;\n    return 0;\n}\n\nstatic void aeApiFree(aeEventLoop *eventLoop) {\n    zfree(eventLoop->apidata);\n}\n\nstatic int aeApiAddEvent(aeEventLoop *eventLoop, int fd, int mask) {\n    aeApiState *state = eventLoop->apidata;\n\n    if (mask & AE_READABLE) FD_SET(fd,&state->rfds);\n    if (mask & AE_WRITABLE) FD_SET(fd,&state->wfds);\n    return 0;\n}\n\nstatic void aeApiDelEvent(aeEventLoop *eventLoop, int fd, int mask) {\n    aeApiState *state = eventLoop->apidata;\n\n    if (mask & AE_READABLE) FD_CLR(fd,&state->rfds);\n    if (mask & AE_WRITABLE) FD_CLR(fd,&state->wfds);\n}\n\nstatic int aeApiPoll(aeEventLoop *eventLoop, struct timeval *tvp) {\n    aeApiState *state = eventLoop->apidata;\n    int retval, j, numevents = 0;\n\n    memcpy(&state->_rfds,&state->rfds,sizeof(fd_set));\n    memcpy(&state->_wfds,&state->wfds,sizeof(fd_set));\n\n    retval = select(eventLoop->maxfd+1,\n                &state->_rfds,&state->_wfds,NULL,tvp);\n    if (retval > 0) {\n        for (j = 0; j <= eventLoop->maxfd; j++) {\n            int mask = 0;\n            aeFileEvent *fe = &eventLoop->events[j];\n\n            if (fe->mask == AE_NONE) continue;\n            if (fe->mask & AE_READABLE && FD_ISSET(j,&state->_rfds))\n                mask |= AE_READABLE;\n            if (fe->mask & AE_WRITABLE && FD_ISSET(j,&state->_wfds))\n                mask |= AE_WRITABLE;\n            eventLoop->fired[numevents].fd = j;\n            eventLoop->fired[numevents].mask = mask;\n            numevents++;\n        }\n    }\n    return numevents;\n}\n\nstatic char *aeApiName(void) {\n    return \"select\";\n}\n"
  },
  {
    "path": "extern/deprecated/redis-2.8.21/src/anet.c",
    "content": "/* anet.c -- Basic TCP socket stuff made a bit less boring\n *\n * Copyright (c) 2006-2012, Salvatore Sanfilippo <antirez at gmail dot com>\n * All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions are met:\n *\n *   * Redistributions of source code must retain the above copyright notice,\n *     this list of conditions and the following disclaimer.\n *   * Redistributions in binary form must reproduce the above copyright\n *     notice, this list of conditions and the following disclaimer in the\n *     documentation and/or other materials provided with the distribution.\n *   * Neither the name of Redis nor the names of its contributors may be used\n *     to endorse or promote products derived from this software without\n *     specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\"\n * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\n * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE\n * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR\n * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF\n * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS\n * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN\n * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)\n * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE\n * POSSIBILITY OF SUCH DAMAGE.\n */\n\n#include \"fmacros.h\"\n\n#include <sys/types.h>\n#include <sys/socket.h>\n#include <sys/stat.h>\n#include <sys/un.h>\n#include <sys/time.h>\n#include <netinet/in.h>\n#include <netinet/tcp.h>\n#include <arpa/inet.h>\n#include <unistd.h>\n#include <fcntl.h>\n#include <string.h>\n#include <netdb.h>\n#include <errno.h>\n#include <stdarg.h>\n#include <stdio.h>\n\n#include \"anet.h\"\n\nstatic void anetSetError(char *err, const char *fmt, ...)\n{\n    va_list ap;\n\n    if (!err) return;\n    va_start(ap, fmt);\n    vsnprintf(err, ANET_ERR_LEN, fmt, ap);\n    va_end(ap);\n}\n\nint anetSetBlock(char *err, int fd, int non_block) {\n    int flags;\n\n    /* Set the socket blocking (if non_block is zero) or non-blocking.\n     * Note that fcntl(2) for F_GETFL and F_SETFL can't be\n     * interrupted by a signal. */\n    if ((flags = fcntl(fd, F_GETFL)) == -1) {\n        anetSetError(err, \"fcntl(F_GETFL): %s\", strerror(errno));\n        return ANET_ERR;\n    }\n\n    if (non_block)\n        flags |= O_NONBLOCK;\n    else\n        flags &= ~O_NONBLOCK;\n\n    if (fcntl(fd, F_SETFL, flags) == -1) {\n        anetSetError(err, \"fcntl(F_SETFL,O_NONBLOCK): %s\", strerror(errno));\n        return ANET_ERR;\n    }\n    return ANET_OK;\n}\n\nint anetNonBlock(char *err, int fd) {\n    return anetSetBlock(err,fd,1);\n}\n\nint anetBlock(char *err, int fd) {\n    return anetSetBlock(err,fd,0);\n}\n\n/* Set TCP keep alive option to detect dead peers. The interval option\n * is only used for Linux as we are using Linux-specific APIs to set\n * the probe send time, interval, and count. */\nint anetKeepAlive(char *err, int fd, int interval)\n{\n    int val = 1;\n\n    if (setsockopt(fd, SOL_SOCKET, SO_KEEPALIVE, &val, sizeof(val)) == -1)\n    {\n        anetSetError(err, \"setsockopt SO_KEEPALIVE: %s\", strerror(errno));\n        return ANET_ERR;\n    }\n\n#ifdef __linux__\n    /* Default settings are more or less garbage, with the keepalive time\n     * set to 7200 by default on Linux. Modify settings to make the feature\n     * actually useful. */\n\n    /* Send first probe after interval. */\n    val = interval;\n    if (setsockopt(fd, IPPROTO_TCP, TCP_KEEPIDLE, &val, sizeof(val)) < 0) {\n        anetSetError(err, \"setsockopt TCP_KEEPIDLE: %s\\n\", strerror(errno));\n        return ANET_ERR;\n    }\n\n    /* Send next probes after the specified interval. Note that we set the\n     * delay as interval / 3, as we send three probes before detecting\n     * an error (see the next setsockopt call). */\n    val = interval/3;\n    if (val == 0) val = 1;\n    if (setsockopt(fd, IPPROTO_TCP, TCP_KEEPINTVL, &val, sizeof(val)) < 0) {\n        anetSetError(err, \"setsockopt TCP_KEEPINTVL: %s\\n\", strerror(errno));\n        return ANET_ERR;\n    }\n\n    /* Consider the socket in error state after three we send three ACK\n     * probes without getting a reply. */\n    val = 3;\n    if (setsockopt(fd, IPPROTO_TCP, TCP_KEEPCNT, &val, sizeof(val)) < 0) {\n        anetSetError(err, \"setsockopt TCP_KEEPCNT: %s\\n\", strerror(errno));\n        return ANET_ERR;\n    }\n#else\n    ((void) interval); /* Avoid unused var warning for non Linux systems. */\n#endif\n\n    return ANET_OK;\n}\n\nstatic int anetSetTcpNoDelay(char *err, int fd, int val)\n{\n    if (setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, &val, sizeof(val)) == -1)\n    {\n        anetSetError(err, \"setsockopt TCP_NODELAY: %s\", strerror(errno));\n        return ANET_ERR;\n    }\n    return ANET_OK;\n}\n\nint anetEnableTcpNoDelay(char *err, int fd)\n{\n    return anetSetTcpNoDelay(err, fd, 1);\n}\n\nint anetDisableTcpNoDelay(char *err, int fd)\n{\n    return anetSetTcpNoDelay(err, fd, 0);\n}\n\n\nint anetSetSendBuffer(char *err, int fd, int buffsize)\n{\n    if (setsockopt(fd, SOL_SOCKET, SO_SNDBUF, &buffsize, sizeof(buffsize)) == -1)\n    {\n        anetSetError(err, \"setsockopt SO_SNDBUF: %s\", strerror(errno));\n        return ANET_ERR;\n    }\n    return ANET_OK;\n}\n\nint anetTcpKeepAlive(char *err, int fd)\n{\n    int yes = 1;\n    if (setsockopt(fd, SOL_SOCKET, SO_KEEPALIVE, &yes, sizeof(yes)) == -1) {\n        anetSetError(err, \"setsockopt SO_KEEPALIVE: %s\", strerror(errno));\n        return ANET_ERR;\n    }\n    return ANET_OK;\n}\n\n/* Set the socket send timeout (SO_SNDTIMEO socket option) to the specified\n * number of milliseconds, or disable it if the 'ms' argument is zero. */\nint anetSendTimeout(char *err, int fd, long long ms) {\n    struct timeval tv;\n\n    tv.tv_sec = ms/1000;\n    tv.tv_usec = (ms%1000)*1000;\n    if (setsockopt(fd, SOL_SOCKET, SO_SNDTIMEO, &tv, sizeof(tv)) == -1) {\n        anetSetError(err, \"setsockopt SO_SNDTIMEO: %s\", strerror(errno));\n        return ANET_ERR;\n    }\n    return ANET_OK;\n}\n\n/* anetGenericResolve() is called by anetResolve() and anetResolveIP() to\n * do the actual work. It resolves the hostname \"host\" and set the string\n * representation of the IP address into the buffer pointed by \"ipbuf\".\n *\n * If flags is set to ANET_IP_ONLY the function only resolves hostnames\n * that are actually already IPv4 or IPv6 addresses. This turns the function\n * into a validating / normalizing function. */\nint anetGenericResolve(char *err, char *host, char *ipbuf, size_t ipbuf_len,\n                       int flags)\n{\n    struct addrinfo hints, *info;\n    int rv;\n\n    memset(&hints,0,sizeof(hints));\n    if (flags & ANET_IP_ONLY) hints.ai_flags = AI_NUMERICHOST;\n    hints.ai_family = AF_UNSPEC;\n    hints.ai_socktype = SOCK_STREAM;  /* specify socktype to avoid dups */\n\n    if ((rv = getaddrinfo(host, NULL, &hints, &info)) != 0) {\n        anetSetError(err, \"%s\", gai_strerror(rv));\n        return ANET_ERR;\n    }\n    if (info->ai_family == AF_INET) {\n        struct sockaddr_in *sa = (struct sockaddr_in *)info->ai_addr;\n        inet_ntop(AF_INET, &(sa->sin_addr), ipbuf, ipbuf_len);\n    } else {\n        struct sockaddr_in6 *sa = (struct sockaddr_in6 *)info->ai_addr;\n        inet_ntop(AF_INET6, &(sa->sin6_addr), ipbuf, ipbuf_len);\n    }\n\n    freeaddrinfo(info);\n    return ANET_OK;\n}\n\nint anetResolve(char *err, char *host, char *ipbuf, size_t ipbuf_len) {\n    return anetGenericResolve(err,host,ipbuf,ipbuf_len,ANET_NONE);\n}\n\nint anetResolveIP(char *err, char *host, char *ipbuf, size_t ipbuf_len) {\n    return anetGenericResolve(err,host,ipbuf,ipbuf_len,ANET_IP_ONLY);\n}\n\nstatic int anetSetReuseAddr(char *err, int fd) {\n    int yes = 1;\n    /* Make sure connection-intensive things like the redis benckmark\n     * will be able to close/open sockets a zillion of times */\n    if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(yes)) == -1) {\n        anetSetError(err, \"setsockopt SO_REUSEADDR: %s\", strerror(errno));\n        return ANET_ERR;\n    }\n    return ANET_OK;\n}\n\nstatic int anetCreateSocket(char *err, int domain) {\n    int s;\n    if ((s = socket(domain, SOCK_STREAM, 0)) == -1) {\n        anetSetError(err, \"creating socket: %s\", strerror(errno));\n        return ANET_ERR;\n    }\n\n    /* Make sure connection-intensive things like the redis benchmark\n     * will be able to close/open sockets a zillion of times */\n    if (anetSetReuseAddr(err,s) == ANET_ERR) {\n        close(s);\n        return ANET_ERR;\n    }\n    return s;\n}\n\n#define ANET_CONNECT_NONE 0\n#define ANET_CONNECT_NONBLOCK 1\nstatic int anetTcpGenericConnect(char *err, char *addr, int port, int flags)\n{\n    int s = ANET_ERR, rv;\n    char portstr[6];  /* strlen(\"65535\") + 1; */\n    struct addrinfo hints, *servinfo, *p;\n\n    snprintf(portstr,sizeof(portstr),\"%d\",port);\n    memset(&hints,0,sizeof(hints));\n    hints.ai_family = AF_UNSPEC;\n    hints.ai_socktype = SOCK_STREAM;\n\n    if ((rv = getaddrinfo(addr,portstr,&hints,&servinfo)) != 0) {\n        anetSetError(err, \"%s\", gai_strerror(rv));\n        return ANET_ERR;\n    }\n    for (p = servinfo; p != NULL; p = p->ai_next) {\n        /* Try to create the socket and to connect it.\n         * If we fail in the socket() call, or on connect(), we retry with\n         * the next entry in servinfo. */\n        if ((s = socket(p->ai_family,p->ai_socktype,p->ai_protocol)) == -1)\n            continue;\n        if (anetSetReuseAddr(err,s) == ANET_ERR) goto error;\n        if (flags & ANET_CONNECT_NONBLOCK && anetNonBlock(err,s) != ANET_OK)\n            goto error;\n        if (connect(s,p->ai_addr,p->ai_addrlen) == -1) {\n            /* If the socket is non-blocking, it is ok for connect() to\n             * return an EINPROGRESS error here. */\n            if (errno == EINPROGRESS && flags & ANET_CONNECT_NONBLOCK)\n                goto end;\n            close(s);\n            s = ANET_ERR;\n            continue;\n        }\n\n        /* If we ended an iteration of the for loop without errors, we\n         * have a connected socket. Let's return to the caller. */\n        goto end;\n    }\n    if (p == NULL)\n        anetSetError(err, \"creating socket: %s\", strerror(errno));\n\nerror:\n    if (s != ANET_ERR) {\n        close(s);\n        s = ANET_ERR;\n    }\nend:\n    freeaddrinfo(servinfo);\n    return s;\n}\n\nint anetTcpConnect(char *err, char *addr, int port)\n{\n    return anetTcpGenericConnect(err,addr,port,ANET_CONNECT_NONE);\n}\n\nint anetTcpNonBlockConnect(char *err, char *addr, int port)\n{\n    return anetTcpGenericConnect(err,addr,port,ANET_CONNECT_NONBLOCK);\n}\n\nint anetUnixGenericConnect(char *err, char *path, int flags)\n{\n    int s;\n    struct sockaddr_un sa;\n\n    if ((s = anetCreateSocket(err,AF_LOCAL)) == ANET_ERR)\n        return ANET_ERR;\n\n    sa.sun_family = AF_LOCAL;\n    strncpy(sa.sun_path,path,sizeof(sa.sun_path)-1);\n    if (flags & ANET_CONNECT_NONBLOCK) {\n        if (anetNonBlock(err,s) != ANET_OK)\n            return ANET_ERR;\n    }\n    if (connect(s,(struct sockaddr*)&sa,sizeof(sa)) == -1) {\n        if (errno == EINPROGRESS &&\n            flags & ANET_CONNECT_NONBLOCK)\n            return s;\n\n        anetSetError(err, \"connect: %s\", strerror(errno));\n        close(s);\n        return ANET_ERR;\n    }\n    return s;\n}\n\nint anetUnixConnect(char *err, char *path)\n{\n    return anetUnixGenericConnect(err,path,ANET_CONNECT_NONE);\n}\n\nint anetUnixNonBlockConnect(char *err, char *path)\n{\n    return anetUnixGenericConnect(err,path,ANET_CONNECT_NONBLOCK);\n}\n\n/* Like read(2) but make sure 'count' is read before to return\n * (unless error or EOF condition is encountered) */\nint anetRead(int fd, char *buf, int count)\n{\n    int nread, totlen = 0;\n    while(totlen != count) {\n        nread = read(fd,buf,count-totlen);\n        if (nread == 0) return totlen;\n        if (nread == -1) return -1;\n        totlen += nread;\n        buf += nread;\n    }\n    return totlen;\n}\n\n/* Like write(2) but make sure 'count' is read before to return\n * (unless error is encountered) */\nint anetWrite(int fd, char *buf, int count)\n{\n    int nwritten, totlen = 0;\n    while(totlen != count) {\n        nwritten = write(fd,buf,count-totlen);\n        if (nwritten == 0) return totlen;\n        if (nwritten == -1) return -1;\n        totlen += nwritten;\n        buf += nwritten;\n    }\n    return totlen;\n}\n\nstatic int anetListen(char *err, int s, struct sockaddr *sa, socklen_t len, int backlog) {\n    if (bind(s,sa,len) == -1) {\n        anetSetError(err, \"bind: %s\", strerror(errno));\n        close(s);\n        return ANET_ERR;\n    }\n\n    if (listen(s, backlog) == -1) {\n        anetSetError(err, \"listen: %s\", strerror(errno));\n        close(s);\n        return ANET_ERR;\n    }\n    return ANET_OK;\n}\n\nstatic int anetV6Only(char *err, int s) {\n    int yes = 1;\n    if (setsockopt(s,IPPROTO_IPV6,IPV6_V6ONLY,&yes,sizeof(yes)) == -1) {\n        anetSetError(err, \"setsockopt: %s\", strerror(errno));\n        close(s);\n        return ANET_ERR;\n    }\n    return ANET_OK;\n}\n\nstatic int _anetTcpServer(char *err, int port, char *bindaddr, int af, int backlog)\n{\n    int s, rv;\n    char _port[6];  /* strlen(\"65535\") */\n    struct addrinfo hints, *servinfo, *p;\n\n    snprintf(_port,6,\"%d\",port);\n    memset(&hints,0,sizeof(hints));\n    hints.ai_family = af;\n    hints.ai_socktype = SOCK_STREAM;\n    hints.ai_flags = AI_PASSIVE;    /* No effect if bindaddr != NULL */\n\n    if ((rv = getaddrinfo(bindaddr,_port,&hints,&servinfo)) != 0) {\n        anetSetError(err, \"%s\", gai_strerror(rv));\n        return ANET_ERR;\n    }\n    for (p = servinfo; p != NULL; p = p->ai_next) {\n        if ((s = socket(p->ai_family,p->ai_socktype,p->ai_protocol)) == -1)\n            continue;\n\n        if (af == AF_INET6 && anetV6Only(err,s) == ANET_ERR) goto error;\n        if (anetSetReuseAddr(err,s) == ANET_ERR) goto error;\n        if (anetListen(err,s,p->ai_addr,p->ai_addrlen,backlog) == ANET_ERR) goto error;\n        goto end;\n    }\n    if (p == NULL) {\n        anetSetError(err, \"unable to bind socket\");\n        goto error;\n    }\n\nerror:\n    s = ANET_ERR;\nend:\n    freeaddrinfo(servinfo);\n    return s;\n}\n\nint anetTcpServer(char *err, int port, char *bindaddr, int backlog)\n{\n    return _anetTcpServer(err, port, bindaddr, AF_INET, backlog);\n}\n\nint anetTcp6Server(char *err, int port, char *bindaddr, int backlog)\n{\n    return _anetTcpServer(err, port, bindaddr, AF_INET6, backlog);\n}\n\nint anetUnixServer(char *err, char *path, mode_t perm, int backlog)\n{\n    int s;\n    struct sockaddr_un sa;\n\n    if ((s = anetCreateSocket(err,AF_LOCAL)) == ANET_ERR)\n        return ANET_ERR;\n\n    memset(&sa,0,sizeof(sa));\n    sa.sun_family = AF_LOCAL;\n    strncpy(sa.sun_path,path,sizeof(sa.sun_path)-1);\n    if (anetListen(err,s,(struct sockaddr*)&sa,sizeof(sa),backlog) == ANET_ERR)\n        return ANET_ERR;\n    if (perm)\n        chmod(sa.sun_path, perm);\n    return s;\n}\n\nstatic int anetGenericAccept(char *err, int s, struct sockaddr *sa, socklen_t *len) {\n    int fd;\n    while(1) {\n        fd = accept(s,sa,len);\n        if (fd == -1) {\n            if (errno == EINTR)\n                continue;\n            else {\n                anetSetError(err, \"accept: %s\", strerror(errno));\n                return ANET_ERR;\n            }\n        }\n        break;\n    }\n    return fd;\n}\n\nint anetTcpAccept(char *err, int s, char *ip, size_t ip_len, int *port) {\n    int fd;\n    struct sockaddr_storage sa;\n    socklen_t salen = sizeof(sa);\n    if ((fd = anetGenericAccept(err,s,(struct sockaddr*)&sa,&salen)) == -1)\n        return ANET_ERR;\n\n    if (sa.ss_family == AF_INET) {\n        struct sockaddr_in *s = (struct sockaddr_in *)&sa;\n        if (ip) inet_ntop(AF_INET,(void*)&(s->sin_addr),ip,ip_len);\n        if (port) *port = ntohs(s->sin_port);\n    } else {\n        struct sockaddr_in6 *s = (struct sockaddr_in6 *)&sa;\n        if (ip) inet_ntop(AF_INET6,(void*)&(s->sin6_addr),ip,ip_len);\n        if (port) *port = ntohs(s->sin6_port);\n    }\n    return fd;\n}\n\nint anetUnixAccept(char *err, int s) {\n    int fd;\n    struct sockaddr_un sa;\n    socklen_t salen = sizeof(sa);\n    if ((fd = anetGenericAccept(err,s,(struct sockaddr*)&sa,&salen)) == -1)\n        return ANET_ERR;\n\n    return fd;\n}\n\nint anetPeerToString(int fd, char *ip, size_t ip_len, int *port) {\n    struct sockaddr_storage sa;\n    socklen_t salen = sizeof(sa);\n\n    if (getpeername(fd,(struct sockaddr*)&sa,&salen) == -1) {\n        if (port) *port = 0;\n        ip[0] = '?';\n        ip[1] = '\\0';\n        return -1;\n    }\n    if (sa.ss_family == AF_INET) {\n        struct sockaddr_in *s = (struct sockaddr_in *)&sa;\n        if (ip) inet_ntop(AF_INET,(void*)&(s->sin_addr),ip,ip_len);\n        if (port) *port = ntohs(s->sin_port);\n    } else {\n        struct sockaddr_in6 *s = (struct sockaddr_in6 *)&sa;\n        if (ip) inet_ntop(AF_INET6,(void*)&(s->sin6_addr),ip,ip_len);\n        if (port) *port = ntohs(s->sin6_port);\n    }\n    return 0;\n}\n\nint anetSockName(int fd, char *ip, size_t ip_len, int *port) {\n    struct sockaddr_storage sa;\n    socklen_t salen = sizeof(sa);\n\n    if (getsockname(fd,(struct sockaddr*)&sa,&salen) == -1) {\n        if (port) *port = 0;\n        ip[0] = '?';\n        ip[1] = '\\0';\n        return -1;\n    }\n    if (sa.ss_family == AF_INET) {\n        struct sockaddr_in *s = (struct sockaddr_in *)&sa;\n        if (ip) inet_ntop(AF_INET,(void*)&(s->sin_addr),ip,ip_len);\n        if (port) *port = ntohs(s->sin_port);\n    } else {\n        struct sockaddr_in6 *s = (struct sockaddr_in6 *)&sa;\n        if (ip) inet_ntop(AF_INET6,(void*)&(s->sin6_addr),ip,ip_len);\n        if (port) *port = ntohs(s->sin6_port);\n    }\n    return 0;\n}\n"
  },
  {
    "path": "extern/deprecated/redis-2.8.21/src/anet.h",
    "content": "/* anet.c -- Basic TCP socket stuff made a bit less boring\n *\n * Copyright (c) 2006-2012, Salvatore Sanfilippo <antirez at gmail dot com>\n * All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions are met:\n *\n *   * Redistributions of source code must retain the above copyright notice,\n *     this list of conditions and the following disclaimer.\n *   * Redistributions in binary form must reproduce the above copyright\n *     notice, this list of conditions and the following disclaimer in the\n *     documentation and/or other materials provided with the distribution.\n *   * Neither the name of Redis nor the names of its contributors may be used\n *     to endorse or promote products derived from this software without\n *     specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\"\n * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\n * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE\n * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR\n * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF\n * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS\n * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN\n * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)\n * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE\n * POSSIBILITY OF SUCH DAMAGE.\n */\n\n#ifndef ANET_H\n#define ANET_H\n\n#define ANET_OK 0\n#define ANET_ERR -1\n#define ANET_ERR_LEN 256\n\n/* Flags used with certain functions. */\n#define ANET_NONE 0\n#define ANET_IP_ONLY (1<<0)\n\n#if defined(__sun) || defined(_AIX)\n#define AF_LOCAL AF_UNIX\n#endif\n\n#ifdef _AIX\n#undef ip_len\n#endif\n\nint anetTcpConnect(char *err, char *addr, int port);\nint anetTcpNonBlockConnect(char *err, char *addr, int port);\nint anetUnixConnect(char *err, char *path);\nint anetUnixNonBlockConnect(char *err, char *path);\nint anetRead(int fd, char *buf, int count);\nint anetResolve(char *err, char *host, char *ipbuf, size_t ipbuf_len);\nint anetResolveIP(char *err, char *host, char *ipbuf, size_t ipbuf_len);\nint anetTcpServer(char *err, int port, char *bindaddr, int backlog);\nint anetTcp6Server(char *err, int port, char *bindaddr, int backlog);\nint anetUnixServer(char *err, char *path, mode_t perm, int backlog);\nint anetTcpAccept(char *err, int serversock, char *ip, size_t ip_len, int *port);\nint anetUnixAccept(char *err, int serversock);\nint anetWrite(int fd, char *buf, int count);\nint anetNonBlock(char *err, int fd);\nint anetBlock(char *err, int fd);\nint anetEnableTcpNoDelay(char *err, int fd);\nint anetDisableTcpNoDelay(char *err, int fd);\nint anetTcpKeepAlive(char *err, int fd);\nint anetSendTimeout(char *err, int fd, long long ms);\nint anetPeerToString(int fd, char *ip, size_t ip_len, int *port);\nint anetKeepAlive(char *err, int fd, int interval);\nint anetSockName(int fd, char *ip, size_t ip_len, int *port);\n\n#endif\n"
  },
  {
    "path": "extern/deprecated/redis-2.8.21/src/aof.c",
    "content": "/*\n * Copyright (c) 2009-2012, Salvatore Sanfilippo <antirez at gmail dot com>\n * All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions are met:\n *\n *   * Redistributions of source code must retain the above copyright notice,\n *     this list of conditions and the following disclaimer.\n *   * Redistributions in binary form must reproduce the above copyright\n *     notice, this list of conditions and the following disclaimer in the\n *     documentation and/or other materials provided with the distribution.\n *   * Neither the name of Redis nor the names of its contributors may be used\n *     to endorse or promote products derived from this software without\n *     specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\"\n * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\n * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE\n * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR\n * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF\n * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS\n * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN\n * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)\n * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE\n * POSSIBILITY OF SUCH DAMAGE.\n */\n\n#include \"redis.h\"\n#include \"bio.h\"\n#include \"rio.h\"\n\n#include <signal.h>\n#include <fcntl.h>\n#include <sys/stat.h>\n#include <sys/types.h>\n#include <sys/time.h>\n#include <sys/resource.h>\n#include <sys/wait.h>\n\nvoid aofUpdateCurrentSize(void);\n\n/* ----------------------------------------------------------------------------\n * AOF rewrite buffer implementation.\n *\n * The following code implement a simple buffer used in order to accumulate\n * changes while the background process is rewriting the AOF file.\n *\n * We only need to append, but can't just use realloc with a large block\n * because 'huge' reallocs are not always handled as one could expect\n * (via remapping of pages at OS level) but may involve copying data.\n *\n * For this reason we use a list of blocks, every block is\n * AOF_RW_BUF_BLOCK_SIZE bytes.\n * ------------------------------------------------------------------------- */\n\n#define AOF_RW_BUF_BLOCK_SIZE (1024*1024*10)    /* 10 MB per block */\n\ntypedef struct aofrwblock {\n    unsigned long used, free;\n    char buf[AOF_RW_BUF_BLOCK_SIZE];\n} aofrwblock;\n\n/* This function free the old AOF rewrite buffer if needed, and initialize\n * a fresh new one. It tests for server.aof_rewrite_buf_blocks equal to NULL\n * so can be used for the first initialization as well. */\nvoid aofRewriteBufferReset(void) {\n    if (server.aof_rewrite_buf_blocks)\n        listRelease(server.aof_rewrite_buf_blocks);\n\n    server.aof_rewrite_buf_blocks = listCreate();\n    listSetFreeMethod(server.aof_rewrite_buf_blocks,zfree);\n}\n\n/* Return the current size of the AOF rewrite buffer. */\nunsigned long aofRewriteBufferSize(void) {\n    listNode *ln = listLast(server.aof_rewrite_buf_blocks);\n    aofrwblock *block = ln ? ln->value : NULL;\n\n    if (block == NULL) return 0;\n    unsigned long size =\n        (listLength(server.aof_rewrite_buf_blocks)-1) * AOF_RW_BUF_BLOCK_SIZE;\n    size += block->used;\n    return size;\n}\n\n/* Append data to the AOF rewrite buffer, allocating new blocks if needed. */\nvoid aofRewriteBufferAppend(unsigned char *s, unsigned long len) {\n    listNode *ln = listLast(server.aof_rewrite_buf_blocks);\n    aofrwblock *block = ln ? ln->value : NULL;\n\n    while(len) {\n        /* If we already got at least an allocated block, try appending\n         * at least some piece into it. */\n        if (block) {\n            unsigned long thislen = (block->free < len) ? block->free : len;\n            if (thislen) {  /* The current block is not already full. */\n                memcpy(block->buf+block->used, s, thislen);\n                block->used += thislen;\n                block->free -= thislen;\n                s += thislen;\n                len -= thislen;\n            }\n        }\n\n        if (len) { /* First block to allocate, or need another block. */\n            int numblocks;\n\n            block = zmalloc(sizeof(*block));\n            block->free = AOF_RW_BUF_BLOCK_SIZE;\n            block->used = 0;\n            listAddNodeTail(server.aof_rewrite_buf_blocks,block);\n\n            /* Log every time we cross more 10 or 100 blocks, respectively\n             * as a notice or warning. */\n            numblocks = listLength(server.aof_rewrite_buf_blocks);\n            if (((numblocks+1) % 10) == 0) {\n                int level = ((numblocks+1) % 100) == 0 ? REDIS_WARNING :\n                                                         REDIS_NOTICE;\n                redisLog(level,\"Background AOF buffer size: %lu MB\",\n                    aofRewriteBufferSize()/(1024*1024));\n            }\n        }\n    }\n}\n\n/* Write the buffer (possibly composed of multiple blocks) into the specified\n * fd. If a short write or any other error happens -1 is returned,\n * otherwise the number of bytes written is returned. */\nssize_t aofRewriteBufferWrite(int fd) {\n    listNode *ln;\n    listIter li;\n    ssize_t count = 0;\n\n    listRewind(server.aof_rewrite_buf_blocks,&li);\n    while((ln = listNext(&li))) {\n        aofrwblock *block = listNodeValue(ln);\n        ssize_t nwritten;\n\n        if (block->used) {\n            nwritten = write(fd,block->buf,block->used);\n            if (nwritten != (ssize_t)block->used) {\n                if (nwritten == 0) errno = EIO;\n                return -1;\n            }\n            count += nwritten;\n        }\n    }\n    return count;\n}\n\n/* ----------------------------------------------------------------------------\n * AOF file implementation\n * ------------------------------------------------------------------------- */\n\n/* Starts a background task that performs fsync() against the specified\n * file descriptor (the one of the AOF file) in another thread. */\nvoid aof_background_fsync(int fd) {\n    bioCreateBackgroundJob(REDIS_BIO_AOF_FSYNC,(void*)(long)fd,NULL,NULL);\n}\n\n/* Called when the user switches from \"appendonly yes\" to \"appendonly no\"\n * at runtime using the CONFIG command. */\nvoid stopAppendOnly(void) {\n    redisAssert(server.aof_state != REDIS_AOF_OFF);\n    flushAppendOnlyFile(1);\n    aof_fsync(server.aof_fd);\n    close(server.aof_fd);\n\n    server.aof_fd = -1;\n    server.aof_selected_db = -1;\n    server.aof_state = REDIS_AOF_OFF;\n    /* rewrite operation in progress? kill it, wait child exit */\n    if (server.aof_child_pid != -1) {\n        int statloc;\n\n        redisLog(REDIS_NOTICE,\"Killing running AOF rewrite child: %ld\",\n            (long) server.aof_child_pid);\n        if (kill(server.aof_child_pid,SIGUSR1) != -1)\n            wait3(&statloc,0,NULL);\n        /* reset the buffer accumulating changes while the child saves */\n        aofRewriteBufferReset();\n        aofRemoveTempFile(server.aof_child_pid);\n        server.aof_child_pid = -1;\n        server.aof_rewrite_time_start = -1;\n    }\n}\n\n/* Called when the user switches from \"appendonly no\" to \"appendonly yes\"\n * at runtime using the CONFIG command. */\nint startAppendOnly(void) {\n    server.aof_last_fsync = server.unixtime;\n    server.aof_fd = open(server.aof_filename,O_WRONLY|O_APPEND|O_CREAT,0644);\n    redisAssert(server.aof_state == REDIS_AOF_OFF);\n    if (server.aof_fd == -1) {\n        redisLog(REDIS_WARNING,\"Redis needs to enable the AOF but can't open the append only file: %s\",strerror(errno));\n        return REDIS_ERR;\n    }\n    if (rewriteAppendOnlyFileBackground() == REDIS_ERR) {\n        close(server.aof_fd);\n        redisLog(REDIS_WARNING,\"Redis needs to enable the AOF but can't trigger a background AOF rewrite operation. Check the above logs for more info about the error.\");\n        return REDIS_ERR;\n    }\n    /* We correctly switched on AOF, now wait for the rewrite to be complete\n     * in order to append data on disk. */\n    server.aof_state = REDIS_AOF_WAIT_REWRITE;\n    return REDIS_OK;\n}\n\n/* Write the append only file buffer on disk.\n *\n * Since we are required to write the AOF before replying to the client,\n * and the only way the client socket can get a write is entering when the\n * the event loop, we accumulate all the AOF writes in a memory\n * buffer and write it on disk using this function just before entering\n * the event loop again.\n *\n * About the 'force' argument:\n *\n * When the fsync policy is set to 'everysec' we may delay the flush if there\n * is still an fsync() going on in the background thread, since for instance\n * on Linux write(2) will be blocked by the background fsync anyway.\n * When this happens we remember that there is some aof buffer to be\n * flushed ASAP, and will try to do that in the serverCron() function.\n *\n * However if force is set to 1 we'll write regardless of the background\n * fsync. */\n#define AOF_WRITE_LOG_ERROR_RATE 30 /* Seconds between errors logging. */\nvoid flushAppendOnlyFile(int force) {\n    ssize_t nwritten;\n    int sync_in_progress = 0;\n    mstime_t latency;\n\n    if (sdslen(server.aof_buf) == 0) return;\n\n    if (server.aof_fsync == AOF_FSYNC_EVERYSEC)\n        sync_in_progress = bioPendingJobsOfType(REDIS_BIO_AOF_FSYNC) != 0;\n\n    if (server.aof_fsync == AOF_FSYNC_EVERYSEC && !force) {\n        /* With this append fsync policy we do background fsyncing.\n         * If the fsync is still in progress we can try to delay\n         * the write for a couple of seconds. */\n        if (sync_in_progress) {\n            if (server.aof_flush_postponed_start == 0) {\n                /* No previous write postponing, remember that we are\n                 * postponing the flush and return. */\n                server.aof_flush_postponed_start = server.unixtime;\n                return;\n            } else if (server.unixtime - server.aof_flush_postponed_start < 2) {\n                /* We were already waiting for fsync to finish, but for less\n                 * than two seconds this is still ok. Postpone again. */\n                return;\n            }\n            /* Otherwise fall trough, and go write since we can't wait\n             * over two seconds. */\n            server.aof_delayed_fsync++;\n            redisLog(REDIS_NOTICE,\"Asynchronous AOF fsync is taking too long (disk is busy?). Writing the AOF buffer without waiting for fsync to complete, this may slow down Redis.\");\n        }\n    }\n    /* We want to perform a single write. This should be guaranteed atomic\n     * at least if the filesystem we are writing is a real physical one.\n     * While this will save us against the server being killed I don't think\n     * there is much to do about the whole server stopping for power problems\n     * or alike */\n\n    latencyStartMonitor(latency);\n    nwritten = write(server.aof_fd,server.aof_buf,sdslen(server.aof_buf));\n    latencyEndMonitor(latency);\n    /* We want to capture different events for delayed writes:\n     * when the delay happens with a pending fsync, or with a saving child\n     * active, and when the above two conditions are missing.\n     * We also use an additional event name to save all samples which is\n     * useful for graphing / monitoring purposes. */\n    if (sync_in_progress) {\n        latencyAddSampleIfNeeded(\"aof-write-pending-fsync\",latency);\n    } else if (server.aof_child_pid != -1 || server.rdb_child_pid != -1) {\n        latencyAddSampleIfNeeded(\"aof-write-active-child\",latency);\n    } else {\n        latencyAddSampleIfNeeded(\"aof-write-alone\",latency);\n    }\n    latencyAddSampleIfNeeded(\"aof-write\",latency);\n\n    /* We performed the write so reset the postponed flush sentinel to zero. */\n    server.aof_flush_postponed_start = 0;\n\n    if (nwritten != (signed)sdslen(server.aof_buf)) {\n        static time_t last_write_error_log = 0;\n        int can_log = 0;\n\n        /* Limit logging rate to 1 line per AOF_WRITE_LOG_ERROR_RATE seconds. */\n        if ((server.unixtime - last_write_error_log) > AOF_WRITE_LOG_ERROR_RATE) {\n            can_log = 1;\n            last_write_error_log = server.unixtime;\n        }\n\n        /* Log the AOF write error and record the error code. */\n        if (nwritten == -1) {\n            if (can_log) {\n                redisLog(REDIS_WARNING,\"Error writing to the AOF file: %s\",\n                    strerror(errno));\n                server.aof_last_write_errno = errno;\n            }\n        } else {\n            if (can_log) {\n                redisLog(REDIS_WARNING,\"Short write while writing to \"\n                                       \"the AOF file: (nwritten=%lld, \"\n                                       \"expected=%lld)\",\n                                       (long long)nwritten,\n                                       (long long)sdslen(server.aof_buf));\n            }\n\n            if (ftruncate(server.aof_fd, server.aof_current_size) == -1) {\n                if (can_log) {\n                    redisLog(REDIS_WARNING, \"Could not remove short write \"\n                             \"from the append-only file.  Redis may refuse \"\n                             \"to load the AOF the next time it starts.  \"\n                             \"ftruncate: %s\", strerror(errno));\n                }\n            } else {\n                /* If the ftruncate() succeeded we can set nwritten to\n                 * -1 since there is no longer partial data into the AOF. */\n                nwritten = -1;\n            }\n            server.aof_last_write_errno = ENOSPC;\n        }\n\n        /* Handle the AOF write error. */\n        if (server.aof_fsync == AOF_FSYNC_ALWAYS) {\n            /* We can't recover when the fsync policy is ALWAYS since the\n             * reply for the client is already in the output buffers, and we\n             * have the contract with the user that on acknowledged write data\n             * is synced on disk. */\n            redisLog(REDIS_WARNING,\"Can't recover from AOF write error when the AOF fsync policy is 'always'. Exiting...\");\n            exit(1);\n        } else {\n            /* Recover from failed write leaving data into the buffer. However\n             * set an error to stop accepting writes as long as the error\n             * condition is not cleared. */\n            server.aof_last_write_status = REDIS_ERR;\n\n            /* Trim the sds buffer if there was a partial write, and there\n             * was no way to undo it with ftruncate(2). */\n            if (nwritten > 0) {\n                server.aof_current_size += nwritten;\n                sdsrange(server.aof_buf,nwritten,-1);\n            }\n            return; /* We'll try again on the next call... */\n        }\n    } else {\n        /* Successful write(2). If AOF was in error state, restore the\n         * OK state and log the event. */\n        if (server.aof_last_write_status == REDIS_ERR) {\n            redisLog(REDIS_WARNING,\n                \"AOF write error looks solved, Redis can write again.\");\n            server.aof_last_write_status = REDIS_OK;\n        }\n    }\n    server.aof_current_size += nwritten;\n\n    /* Re-use AOF buffer when it is small enough. The maximum comes from the\n     * arena size of 4k minus some overhead (but is otherwise arbitrary). */\n    if ((sdslen(server.aof_buf)+sdsavail(server.aof_buf)) < 4000) {\n        sdsclear(server.aof_buf);\n    } else {\n        sdsfree(server.aof_buf);\n        server.aof_buf = sdsempty();\n    }\n\n    /* Don't fsync if no-appendfsync-on-rewrite is set to yes and there are\n     * children doing I/O in the background. */\n    if (server.aof_no_fsync_on_rewrite &&\n        (server.aof_child_pid != -1 || server.rdb_child_pid != -1))\n            return;\n\n    /* Perform the fsync if needed. */\n    if (server.aof_fsync == AOF_FSYNC_ALWAYS) {\n        /* aof_fsync is defined as fdatasync() for Linux in order to avoid\n         * flushing metadata. */\n        latencyStartMonitor(latency);\n        aof_fsync(server.aof_fd); /* Let's try to get this data on the disk */\n        latencyEndMonitor(latency);\n        latencyAddSampleIfNeeded(\"aof-fsync-always\",latency);\n        server.aof_last_fsync = server.unixtime;\n    } else if ((server.aof_fsync == AOF_FSYNC_EVERYSEC &&\n                server.unixtime > server.aof_last_fsync)) {\n        if (!sync_in_progress) aof_background_fsync(server.aof_fd);\n        server.aof_last_fsync = server.unixtime;\n    }\n}\n\nsds catAppendOnlyGenericCommand(sds dst, int argc, robj **argv) {\n    char buf[32];\n    int len, j;\n    robj *o;\n\n    buf[0] = '*';\n    len = 1+ll2string(buf+1,sizeof(buf)-1,argc);\n    buf[len++] = '\\r';\n    buf[len++] = '\\n';\n    dst = sdscatlen(dst,buf,len);\n\n    for (j = 0; j < argc; j++) {\n        o = getDecodedObject(argv[j]);\n        buf[0] = '$';\n        len = 1+ll2string(buf+1,sizeof(buf)-1,sdslen(o->ptr));\n        buf[len++] = '\\r';\n        buf[len++] = '\\n';\n        dst = sdscatlen(dst,buf,len);\n        dst = sdscatlen(dst,o->ptr,sdslen(o->ptr));\n        dst = sdscatlen(dst,\"\\r\\n\",2);\n        decrRefCount(o);\n    }\n    return dst;\n}\n\n/* Create the sds representation of an PEXPIREAT command, using\n * 'seconds' as time to live and 'cmd' to understand what command\n * we are translating into a PEXPIREAT.\n *\n * This command is used in order to translate EXPIRE and PEXPIRE commands\n * into PEXPIREAT command so that we retain precision in the append only\n * file, and the time is always absolute and not relative. */\nsds catAppendOnlyExpireAtCommand(sds buf, struct redisCommand *cmd, robj *key, robj *seconds) {\n    long long when;\n    robj *argv[3];\n\n    /* Make sure we can use strtoll */\n    seconds = getDecodedObject(seconds);\n    when = strtoll(seconds->ptr,NULL,10);\n    /* Convert argument into milliseconds for EXPIRE, SETEX, EXPIREAT */\n    if (cmd->proc == expireCommand || cmd->proc == setexCommand ||\n        cmd->proc == expireatCommand)\n    {\n        when *= 1000;\n    }\n    /* Convert into absolute time for EXPIRE, PEXPIRE, SETEX, PSETEX */\n    if (cmd->proc == expireCommand || cmd->proc == pexpireCommand ||\n        cmd->proc == setexCommand || cmd->proc == psetexCommand)\n    {\n        when += mstime();\n    }\n    decrRefCount(seconds);\n\n    argv[0] = createStringObject(\"PEXPIREAT\",9);\n    argv[1] = key;\n    argv[2] = createStringObjectFromLongLong(when);\n    buf = catAppendOnlyGenericCommand(buf, 3, argv);\n    decrRefCount(argv[0]);\n    decrRefCount(argv[2]);\n    return buf;\n}\n\nvoid feedAppendOnlyFile(struct redisCommand *cmd, int dictid, robj **argv, int argc) {\n    sds buf = sdsempty();\n    robj *tmpargv[3];\n\n    /* The DB this command was targeting is not the same as the last command\n     * we appended. To issue a SELECT command is needed. */\n    if (dictid != server.aof_selected_db) {\n        char seldb[64];\n\n        snprintf(seldb,sizeof(seldb),\"%d\",dictid);\n        buf = sdscatprintf(buf,\"*2\\r\\n$6\\r\\nSELECT\\r\\n$%lu\\r\\n%s\\r\\n\",\n            (unsigned long)strlen(seldb),seldb);\n        server.aof_selected_db = dictid;\n    }\n\n    if (cmd->proc == expireCommand || cmd->proc == pexpireCommand ||\n        cmd->proc == expireatCommand) {\n        /* Translate EXPIRE/PEXPIRE/EXPIREAT into PEXPIREAT */\n        buf = catAppendOnlyExpireAtCommand(buf,cmd,argv[1],argv[2]);\n    } else if (cmd->proc == setexCommand || cmd->proc == psetexCommand) {\n        /* Translate SETEX/PSETEX to SET and PEXPIREAT */\n        tmpargv[0] = createStringObject(\"SET\",3);\n        tmpargv[1] = argv[1];\n        tmpargv[2] = argv[3];\n        buf = catAppendOnlyGenericCommand(buf,3,tmpargv);\n        decrRefCount(tmpargv[0]);\n        buf = catAppendOnlyExpireAtCommand(buf,cmd,argv[1],argv[2]);\n    } else {\n        /* All the other commands don't need translation or need the\n         * same translation already operated in the command vector\n         * for the replication itself. */\n        buf = catAppendOnlyGenericCommand(buf,argc,argv);\n    }\n\n    /* Append to the AOF buffer. This will be flushed on disk just before\n     * of re-entering the event loop, so before the client will get a\n     * positive reply about the operation performed. */\n    if (server.aof_state == REDIS_AOF_ON)\n        server.aof_buf = sdscatlen(server.aof_buf,buf,sdslen(buf));\n\n    /* If a background append only file rewriting is in progress we want to\n     * accumulate the differences between the child DB and the current one\n     * in a buffer, so that when the child process will do its work we\n     * can append the differences to the new append only file. */\n    if (server.aof_child_pid != -1)\n        aofRewriteBufferAppend((unsigned char*)buf,sdslen(buf));\n\n    sdsfree(buf);\n}\n\n/* ----------------------------------------------------------------------------\n * AOF loading\n * ------------------------------------------------------------------------- */\n\n/* In Redis commands are always executed in the context of a client, so in\n * order to load the append only file we need to create a fake client. */\nstruct redisClient *createFakeClient(void) {\n    struct redisClient *c = zmalloc(sizeof(*c));\n\n    selectDb(c,0);\n    c->fd = -1;\n    c->name = NULL;\n    c->querybuf = sdsempty();\n    c->querybuf_peak = 0;\n    c->argc = 0;\n    c->argv = NULL;\n    c->bufpos = 0;\n    c->flags = 0;\n    /* We set the fake client as a slave waiting for the synchronization\n     * so that Redis will not try to send replies to this client. */\n    c->replstate = REDIS_REPL_WAIT_BGSAVE_START;\n    c->reply = listCreate();\n    c->reply_bytes = 0;\n    c->obuf_soft_limit_reached_time = 0;\n    c->watched_keys = listCreate();\n    c->peerid = NULL;\n    listSetFreeMethod(c->reply,decrRefCountVoid);\n    listSetDupMethod(c->reply,dupClientReplyValue);\n    initClientMultiState(c);\n    return c;\n}\n\nvoid freeFakeClientArgv(struct redisClient *c) {\n    int j;\n\n    for (j = 0; j < c->argc; j++)\n        decrRefCount(c->argv[j]);\n    zfree(c->argv);\n}\n\nvoid freeFakeClient(struct redisClient *c) {\n    sdsfree(c->querybuf);\n    listRelease(c->reply);\n    listRelease(c->watched_keys);\n    freeClientMultiState(c);\n    zfree(c);\n}\n\n/* Replay the append log file. On success REDIS_OK is returned. On non fatal\n * error (the append only file is zero-length) REDIS_ERR is returned. On\n * fatal error an error message is logged and the program exists. */\nint loadAppendOnlyFile(char *filename) {\n    struct redisClient *fakeClient;\n    FILE *fp = fopen(filename,\"r\");\n    struct redis_stat sb;\n    int old_aof_state = server.aof_state;\n    long loops = 0;\n    off_t valid_up_to = 0; /* Offset of the latest well-formed command loaded. */\n\n    if (fp && redis_fstat(fileno(fp),&sb) != -1 && sb.st_size == 0) {\n        server.aof_current_size = 0;\n        fclose(fp);\n        return REDIS_ERR;\n    }\n\n    if (fp == NULL) {\n        redisLog(REDIS_WARNING,\"Fatal error: can't open the append log file for reading: %s\",strerror(errno));\n        exit(1);\n    }\n\n    /* Temporarily disable AOF, to prevent EXEC from feeding a MULTI\n     * to the same file we're about to read. */\n    server.aof_state = REDIS_AOF_OFF;\n\n    fakeClient = createFakeClient();\n    startLoading(fp);\n\n    while(1) {\n        int argc, j;\n        unsigned long len;\n        robj **argv;\n        char buf[128];\n        sds argsds;\n        struct redisCommand *cmd;\n\n        /* Serve the clients from time to time */\n        if (!(loops++ % 1000)) {\n            loadingProgress(ftello(fp));\n            processEventsWhileBlocked();\n        }\n\n        if (fgets(buf,sizeof(buf),fp) == NULL) {\n            if (feof(fp))\n                break;\n            else\n                goto readerr;\n        }\n        if (buf[0] != '*') goto fmterr;\n        if (buf[1] == '\\0') goto readerr;\n        argc = atoi(buf+1);\n        if (argc < 1) goto fmterr;\n\n        argv = zmalloc(sizeof(robj*)*argc);\n        fakeClient->argc = argc;\n        fakeClient->argv = argv;\n\n        for (j = 0; j < argc; j++) {\n            if (fgets(buf,sizeof(buf),fp) == NULL) {\n                fakeClient->argc = j; /* Free up to j-1. */\n                freeFakeClientArgv(fakeClient);\n                goto readerr;\n            }\n            if (buf[0] != '$') goto fmterr;\n            len = strtol(buf+1,NULL,10);\n            argsds = sdsnewlen(NULL,len);\n            if (len && fread(argsds,len,1,fp) == 0) {\n                sdsfree(argsds);\n                fakeClient->argc = j; /* Free up to j-1. */\n                freeFakeClientArgv(fakeClient);\n                goto readerr;\n            }\n            argv[j] = createObject(REDIS_STRING,argsds);\n            if (fread(buf,2,1,fp) == 0) {\n                fakeClient->argc = j+1; /* Free up to j. */\n                freeFakeClientArgv(fakeClient);\n                goto readerr; /* discard CRLF */\n            }\n        }\n\n        /* Command lookup */\n        cmd = lookupCommand(argv[0]->ptr);\n        if (!cmd) {\n            redisLog(REDIS_WARNING,\"Unknown command '%s' reading the append only file\", (char*)argv[0]->ptr);\n            exit(1);\n        }\n\n        /* Run the command in the context of a fake client */\n        cmd->proc(fakeClient);\n\n        /* The fake client should not have a reply */\n        redisAssert(fakeClient->bufpos == 0 && listLength(fakeClient->reply) == 0);\n        /* The fake client should never get blocked */\n        redisAssert((fakeClient->flags & REDIS_BLOCKED) == 0);\n\n        /* Clean up. Command code may have changed argv/argc so we use the\n         * argv/argc of the client instead of the local variables. */\n        freeFakeClientArgv(fakeClient);\n        if (server.aof_load_truncated) valid_up_to = ftello(fp);\n    }\n\n    /* This point can only be reached when EOF is reached without errors.\n     * If the client is in the middle of a MULTI/EXEC, log error and quit. */\n    if (fakeClient->flags & REDIS_MULTI) goto uxeof;\n\nloaded_ok: /* DB loaded, cleanup and return REDIS_OK to the caller. */\n    fclose(fp);\n    freeFakeClient(fakeClient);\n    server.aof_state = old_aof_state;\n    stopLoading();\n    aofUpdateCurrentSize();\n    server.aof_rewrite_base_size = server.aof_current_size;\n    return REDIS_OK;\n\nreaderr: /* Read error. If feof(fp) is true, fall through to unexpected EOF. */\n    if (!feof(fp)) {\n        redisLog(REDIS_WARNING,\"Unrecoverable error reading the append only file: %s\", strerror(errno));\n        exit(1);\n    }\n\nuxeof: /* Unexpected AOF end of file. */\n    if (server.aof_load_truncated) {\n        redisLog(REDIS_WARNING,\"!!! Warning: short read while loading the AOF file !!!\");\n        redisLog(REDIS_WARNING,\"!!! Truncating the AOF at offset %llu !!!\",\n            (unsigned long long) valid_up_to);\n        if (valid_up_to == -1 || truncate(filename,valid_up_to) == -1) {\n            if (valid_up_to == -1) {\n                redisLog(REDIS_WARNING,\"Last valid command offset is invalid\");\n            } else {\n                redisLog(REDIS_WARNING,\"Error truncating the AOF file: %s\",\n                    strerror(errno));\n            }\n        } else {\n            /* Make sure the AOF file descriptor points to the end of the\n             * file after the truncate call. */\n            if (server.aof_fd != -1 && lseek(server.aof_fd,0,SEEK_END) == -1) {\n                redisLog(REDIS_WARNING,\"Can't seek the end of the AOF file: %s\",\n                    strerror(errno));\n            } else {\n                redisLog(REDIS_WARNING,\n                    \"AOF loaded anyway because aof-load-truncated is enabled\");\n                goto loaded_ok;\n            }\n        }\n    }\n    redisLog(REDIS_WARNING,\"Unexpected end of file reading the append only file. You can: 1) Make a backup of your AOF file, then use ./redis-check-aof --fix <filename>. 2) Alternatively you can set the 'aof-load-truncated' configuration option to yes and restart the server.\");\n    exit(1);\n\nfmterr: /* Format error. */\n    redisLog(REDIS_WARNING,\"Bad file format reading the append only file: make a backup of your AOF file, then use ./redis-check-aof --fix <filename>\");\n    exit(1);\n}\n\n/* ----------------------------------------------------------------------------\n * AOF rewrite\n * ------------------------------------------------------------------------- */\n\n/* Delegate writing an object to writing a bulk string or bulk long long.\n * This is not placed in rio.c since that adds the redis.h dependency. */\nint rioWriteBulkObject(rio *r, robj *obj) {\n    /* Avoid using getDecodedObject to help copy-on-write (we are often\n     * in a child process when this function is called). */\n    if (obj->encoding == REDIS_ENCODING_INT) {\n        return rioWriteBulkLongLong(r,(long)obj->ptr);\n    } else if (obj->encoding == REDIS_ENCODING_RAW) {\n        return rioWriteBulkString(r,obj->ptr,sdslen(obj->ptr));\n    } else {\n        redisPanic(\"Unknown string encoding\");\n    }\n}\n\n/* Emit the commands needed to rebuild a list object.\n * The function returns 0 on error, 1 on success. */\nint rewriteListObject(rio *r, robj *key, robj *o) {\n    long long count = 0, items = listTypeLength(o);\n\n    if (o->encoding == REDIS_ENCODING_ZIPLIST) {\n        unsigned char *zl = o->ptr;\n        unsigned char *p = ziplistIndex(zl,0);\n        unsigned char *vstr;\n        unsigned int vlen;\n        long long vlong;\n\n        while(ziplistGet(p,&vstr,&vlen,&vlong)) {\n            if (count == 0) {\n                int cmd_items = (items > REDIS_AOF_REWRITE_ITEMS_PER_CMD) ?\n                    REDIS_AOF_REWRITE_ITEMS_PER_CMD : items;\n\n                if (rioWriteBulkCount(r,'*',2+cmd_items) == 0) return 0;\n                if (rioWriteBulkString(r,\"RPUSH\",5) == 0) return 0;\n                if (rioWriteBulkObject(r,key) == 0) return 0;\n            }\n            if (vstr) {\n                if (rioWriteBulkString(r,(char*)vstr,vlen) == 0) return 0;\n            } else {\n                if (rioWriteBulkLongLong(r,vlong) == 0) return 0;\n            }\n            p = ziplistNext(zl,p);\n            if (++count == REDIS_AOF_REWRITE_ITEMS_PER_CMD) count = 0;\n            items--;\n        }\n    } else if (o->encoding == REDIS_ENCODING_LINKEDLIST) {\n        list *list = o->ptr;\n        listNode *ln;\n        listIter li;\n\n        listRewind(list,&li);\n        while((ln = listNext(&li))) {\n            robj *eleobj = listNodeValue(ln);\n\n            if (count == 0) {\n                int cmd_items = (items > REDIS_AOF_REWRITE_ITEMS_PER_CMD) ?\n                    REDIS_AOF_REWRITE_ITEMS_PER_CMD : items;\n\n                if (rioWriteBulkCount(r,'*',2+cmd_items) == 0) return 0;\n                if (rioWriteBulkString(r,\"RPUSH\",5) == 0) return 0;\n                if (rioWriteBulkObject(r,key) == 0) return 0;\n            }\n            if (rioWriteBulkObject(r,eleobj) == 0) return 0;\n            if (++count == REDIS_AOF_REWRITE_ITEMS_PER_CMD) count = 0;\n            items--;\n        }\n    } else {\n        redisPanic(\"Unknown list encoding\");\n    }\n    return 1;\n}\n\n/* Emit the commands needed to rebuild a set object.\n * The function returns 0 on error, 1 on success. */\nint rewriteSetObject(rio *r, robj *key, robj *o) {\n    long long count = 0, items = setTypeSize(o);\n\n    if (o->encoding == REDIS_ENCODING_INTSET) {\n        int ii = 0;\n        int64_t llval;\n\n        while(intsetGet(o->ptr,ii++,&llval)) {\n            if (count == 0) {\n                int cmd_items = (items > REDIS_AOF_REWRITE_ITEMS_PER_CMD) ?\n                    REDIS_AOF_REWRITE_ITEMS_PER_CMD : items;\n\n                if (rioWriteBulkCount(r,'*',2+cmd_items) == 0) return 0;\n                if (rioWriteBulkString(r,\"SADD\",4) == 0) return 0;\n                if (rioWriteBulkObject(r,key) == 0) return 0;\n            }\n            if (rioWriteBulkLongLong(r,llval) == 0) return 0;\n            if (++count == REDIS_AOF_REWRITE_ITEMS_PER_CMD) count = 0;\n            items--;\n        }\n    } else if (o->encoding == REDIS_ENCODING_HT) {\n        dictIterator *di = dictGetIterator(o->ptr);\n        dictEntry *de;\n\n        while((de = dictNext(di)) != NULL) {\n            robj *eleobj = dictGetKey(de);\n            if (count == 0) {\n                int cmd_items = (items > REDIS_AOF_REWRITE_ITEMS_PER_CMD) ?\n                    REDIS_AOF_REWRITE_ITEMS_PER_CMD : items;\n\n                if (rioWriteBulkCount(r,'*',2+cmd_items) == 0) return 0;\n                if (rioWriteBulkString(r,\"SADD\",4) == 0) return 0;\n                if (rioWriteBulkObject(r,key) == 0) return 0;\n            }\n            if (rioWriteBulkObject(r,eleobj) == 0) return 0;\n            if (++count == REDIS_AOF_REWRITE_ITEMS_PER_CMD) count = 0;\n            items--;\n        }\n        dictReleaseIterator(di);\n    } else {\n        redisPanic(\"Unknown set encoding\");\n    }\n    return 1;\n}\n\n/* Emit the commands needed to rebuild a sorted set object.\n * The function returns 0 on error, 1 on success. */\nint rewriteSortedSetObject(rio *r, robj *key, robj *o) {\n    long long count = 0, items = zsetLength(o);\n\n    if (o->encoding == REDIS_ENCODING_ZIPLIST) {\n        unsigned char *zl = o->ptr;\n        unsigned char *eptr, *sptr;\n        unsigned char *vstr;\n        unsigned int vlen;\n        long long vll;\n        double score;\n\n        eptr = ziplistIndex(zl,0);\n        redisAssert(eptr != NULL);\n        sptr = ziplistNext(zl,eptr);\n        redisAssert(sptr != NULL);\n\n        while (eptr != NULL) {\n            redisAssert(ziplistGet(eptr,&vstr,&vlen,&vll));\n            score = zzlGetScore(sptr);\n\n            if (count == 0) {\n                int cmd_items = (items > REDIS_AOF_REWRITE_ITEMS_PER_CMD) ?\n                    REDIS_AOF_REWRITE_ITEMS_PER_CMD : items;\n\n                if (rioWriteBulkCount(r,'*',2+cmd_items*2) == 0) return 0;\n                if (rioWriteBulkString(r,\"ZADD\",4) == 0) return 0;\n                if (rioWriteBulkObject(r,key) == 0) return 0;\n            }\n            if (rioWriteBulkDouble(r,score) == 0) return 0;\n            if (vstr != NULL) {\n                if (rioWriteBulkString(r,(char*)vstr,vlen) == 0) return 0;\n            } else {\n                if (rioWriteBulkLongLong(r,vll) == 0) return 0;\n            }\n            zzlNext(zl,&eptr,&sptr);\n            if (++count == REDIS_AOF_REWRITE_ITEMS_PER_CMD) count = 0;\n            items--;\n        }\n    } else if (o->encoding == REDIS_ENCODING_SKIPLIST) {\n        zset *zs = o->ptr;\n        dictIterator *di = dictGetIterator(zs->dict);\n        dictEntry *de;\n\n        while((de = dictNext(di)) != NULL) {\n            robj *eleobj = dictGetKey(de);\n            double *score = dictGetVal(de);\n\n            if (count == 0) {\n                int cmd_items = (items > REDIS_AOF_REWRITE_ITEMS_PER_CMD) ?\n                    REDIS_AOF_REWRITE_ITEMS_PER_CMD : items;\n\n                if (rioWriteBulkCount(r,'*',2+cmd_items*2) == 0) return 0;\n                if (rioWriteBulkString(r,\"ZADD\",4) == 0) return 0;\n                if (rioWriteBulkObject(r,key) == 0) return 0;\n            }\n            if (rioWriteBulkDouble(r,*score) == 0) return 0;\n            if (rioWriteBulkObject(r,eleobj) == 0) return 0;\n            if (++count == REDIS_AOF_REWRITE_ITEMS_PER_CMD) count = 0;\n            items--;\n        }\n        dictReleaseIterator(di);\n    } else {\n        redisPanic(\"Unknown sorted zset encoding\");\n    }\n    return 1;\n}\n\n/* Write either the key or the value of the currently selected item of a hash.\n * The 'hi' argument passes a valid Redis hash iterator.\n * The 'what' filed specifies if to write a key or a value and can be\n * either REDIS_HASH_KEY or REDIS_HASH_VALUE.\n *\n * The function returns 0 on error, non-zero on success. */\nstatic int rioWriteHashIteratorCursor(rio *r, hashTypeIterator *hi, int what) {\n    if (hi->encoding == REDIS_ENCODING_ZIPLIST) {\n        unsigned char *vstr = NULL;\n        unsigned int vlen = UINT_MAX;\n        long long vll = LLONG_MAX;\n\n        hashTypeCurrentFromZiplist(hi, what, &vstr, &vlen, &vll);\n        if (vstr) {\n            return rioWriteBulkString(r, (char*)vstr, vlen);\n        } else {\n            return rioWriteBulkLongLong(r, vll);\n        }\n\n    } else if (hi->encoding == REDIS_ENCODING_HT) {\n        robj *value;\n\n        hashTypeCurrentFromHashTable(hi, what, &value);\n        return rioWriteBulkObject(r, value);\n    }\n\n    redisPanic(\"Unknown hash encoding\");\n    return 0;\n}\n\n/* Emit the commands needed to rebuild a hash object.\n * The function returns 0 on error, 1 on success. */\nint rewriteHashObject(rio *r, robj *key, robj *o) {\n    hashTypeIterator *hi;\n    long long count = 0, items = hashTypeLength(o);\n\n    hi = hashTypeInitIterator(o);\n    while (hashTypeNext(hi) != REDIS_ERR) {\n        if (count == 0) {\n            int cmd_items = (items > REDIS_AOF_REWRITE_ITEMS_PER_CMD) ?\n                REDIS_AOF_REWRITE_ITEMS_PER_CMD : items;\n\n            if (rioWriteBulkCount(r,'*',2+cmd_items*2) == 0) return 0;\n            if (rioWriteBulkString(r,\"HMSET\",5) == 0) return 0;\n            if (rioWriteBulkObject(r,key) == 0) return 0;\n        }\n\n        if (rioWriteHashIteratorCursor(r, hi, REDIS_HASH_KEY) == 0) return 0;\n        if (rioWriteHashIteratorCursor(r, hi, REDIS_HASH_VALUE) == 0) return 0;\n        if (++count == REDIS_AOF_REWRITE_ITEMS_PER_CMD) count = 0;\n        items--;\n    }\n\n    hashTypeReleaseIterator(hi);\n\n    return 1;\n}\n\n/* Write a sequence of commands able to fully rebuild the dataset into\n * \"filename\". Used both by REWRITEAOF and BGREWRITEAOF.\n *\n * In order to minimize the number of commands needed in the rewritten\n * log Redis uses variadic commands when possible, such as RPUSH, SADD\n * and ZADD. However at max REDIS_AOF_REWRITE_ITEMS_PER_CMD items per time\n * are inserted using a single command. */\nint rewriteAppendOnlyFile(char *filename) {\n    dictIterator *di = NULL;\n    dictEntry *de;\n    rio aof;\n    FILE *fp;\n    char tmpfile[256];\n    int j;\n    long long now = mstime();\n\n    /* Note that we have to use a different temp name here compared to the\n     * one used by rewriteAppendOnlyFileBackground() function. */\n    snprintf(tmpfile,256,\"temp-rewriteaof-%d.aof\", (int) getpid());\n    fp = fopen(tmpfile,\"w\");\n    if (!fp) {\n        redisLog(REDIS_WARNING, \"Opening the temp file for AOF rewrite in rewriteAppendOnlyFile(): %s\", strerror(errno));\n        return REDIS_ERR;\n    }\n\n    rioInitWithFile(&aof,fp);\n    if (server.aof_rewrite_incremental_fsync)\n        rioSetAutoSync(&aof,REDIS_AOF_AUTOSYNC_BYTES);\n    for (j = 0; j < server.dbnum; j++) {\n        char selectcmd[] = \"*2\\r\\n$6\\r\\nSELECT\\r\\n\";\n        redisDb *db = server.db+j;\n        dict *d = db->dict;\n        if (dictSize(d) == 0) continue;\n        di = dictGetSafeIterator(d);\n        if (!di) {\n            fclose(fp);\n            return REDIS_ERR;\n        }\n\n        /* SELECT the new DB */\n        if (rioWrite(&aof,selectcmd,sizeof(selectcmd)-1) == 0) goto werr;\n        if (rioWriteBulkLongLong(&aof,j) == 0) goto werr;\n\n        /* Iterate this DB writing every entry */\n        while((de = dictNext(di)) != NULL) {\n            sds keystr;\n            robj key, *o;\n            long long expiretime;\n\n            keystr = dictGetKey(de);\n            o = dictGetVal(de);\n            initStaticStringObject(key,keystr);\n\n            expiretime = getExpire(db,&key);\n\n            /* If this key is already expired skip it */\n            if (expiretime != -1 && expiretime < now) continue;\n\n            /* Save the key and associated value */\n            if (o->type == REDIS_STRING) {\n                /* Emit a SET command */\n                char cmd[]=\"*3\\r\\n$3\\r\\nSET\\r\\n\";\n                if (rioWrite(&aof,cmd,sizeof(cmd)-1) == 0) goto werr;\n                /* Key and value */\n                if (rioWriteBulkObject(&aof,&key) == 0) goto werr;\n                if (rioWriteBulkObject(&aof,o) == 0) goto werr;\n            } else if (o->type == REDIS_LIST) {\n                if (rewriteListObject(&aof,&key,o) == 0) goto werr;\n            } else if (o->type == REDIS_SET) {\n                if (rewriteSetObject(&aof,&key,o) == 0) goto werr;\n            } else if (o->type == REDIS_ZSET) {\n                if (rewriteSortedSetObject(&aof,&key,o) == 0) goto werr;\n            } else if (o->type == REDIS_HASH) {\n                if (rewriteHashObject(&aof,&key,o) == 0) goto werr;\n            } else {\n                redisPanic(\"Unknown object type\");\n            }\n            /* Save the expire time */\n            if (expiretime != -1) {\n                char cmd[]=\"*3\\r\\n$9\\r\\nPEXPIREAT\\r\\n\";\n                if (rioWrite(&aof,cmd,sizeof(cmd)-1) == 0) goto werr;\n                if (rioWriteBulkObject(&aof,&key) == 0) goto werr;\n                if (rioWriteBulkLongLong(&aof,expiretime) == 0) goto werr;\n            }\n        }\n        dictReleaseIterator(di);\n        di = NULL;\n    }\n\n    /* Make sure data will not remain on the OS's output buffers */\n    if (fflush(fp) == EOF) goto werr;\n    if (fsync(fileno(fp)) == -1) goto werr;\n    if (fclose(fp) == EOF) goto werr;\n\n    /* Use RENAME to make sure the DB file is changed atomically only\n     * if the generate DB file is ok. */\n    if (rename(tmpfile,filename) == -1) {\n        redisLog(REDIS_WARNING,\"Error moving temp append only file on the final destination: %s\", strerror(errno));\n        unlink(tmpfile);\n        return REDIS_ERR;\n    }\n    redisLog(REDIS_NOTICE,\"SYNC append only file rewrite performed\");\n    return REDIS_OK;\n\nwerr:\n    fclose(fp);\n    unlink(tmpfile);\n    redisLog(REDIS_WARNING,\"Write error writing append only file on disk: %s\", strerror(errno));\n    if (di) dictReleaseIterator(di);\n    return REDIS_ERR;\n}\n\n/* This is how rewriting of the append only file in background works:\n *\n * 1) The user calls BGREWRITEAOF\n * 2) Redis calls this function, that forks():\n *    2a) the child rewrite the append only file in a temp file.\n *    2b) the parent accumulates differences in server.aof_rewrite_buf.\n * 3) When the child finished '2a' exists.\n * 4) The parent will trap the exit code, if it's OK, will append the\n *    data accumulated into server.aof_rewrite_buf into the temp file, and\n *    finally will rename(2) the temp file in the actual file name.\n *    The the new file is reopened as the new append only file. Profit!\n */\nint rewriteAppendOnlyFileBackground(void) {\n    pid_t childpid;\n    long long start;\n\n    if (server.aof_child_pid != -1) return REDIS_ERR;\n    start = ustime();\n    if ((childpid = fork()) == 0) {\n        char tmpfile[256];\n\n        /* Child */\n        closeListeningSockets(0);\n        redisSetProcTitle(\"redis-aof-rewrite\");\n        snprintf(tmpfile,256,\"temp-rewriteaof-bg-%d.aof\", (int) getpid());\n        if (rewriteAppendOnlyFile(tmpfile) == REDIS_OK) {\n            size_t private_dirty = zmalloc_get_private_dirty();\n\n            if (private_dirty) {\n                redisLog(REDIS_NOTICE,\n                    \"AOF rewrite: %zu MB of memory used by copy-on-write\",\n                    private_dirty/(1024*1024));\n            }\n            exitFromChild(0);\n        } else {\n            exitFromChild(1);\n        }\n    } else {\n        /* Parent */\n        server.stat_fork_time = ustime()-start;\n        server.stat_fork_rate = (double) zmalloc_used_memory() * 1000000 / server.stat_fork_time / (1024*1024*1024); /* GB per second. */\n        latencyAddSampleIfNeeded(\"fork\",server.stat_fork_time/1000);\n        if (childpid == -1) {\n            redisLog(REDIS_WARNING,\n                \"Can't rewrite append only file in background: fork: %s\",\n                strerror(errno));\n            return REDIS_ERR;\n        }\n        redisLog(REDIS_NOTICE,\n            \"Background append only file rewriting started by pid %d\",childpid);\n        server.aof_rewrite_scheduled = 0;\n        server.aof_rewrite_time_start = time(NULL);\n        server.aof_child_pid = childpid;\n        updateDictResizePolicy();\n        /* We set appendseldb to -1 in order to force the next call to the\n         * feedAppendOnlyFile() to issue a SELECT command, so the differences\n         * accumulated by the parent into server.aof_rewrite_buf will start\n         * with a SELECT statement and it will be safe to merge. */\n        server.aof_selected_db = -1;\n        replicationScriptCacheFlush();\n        return REDIS_OK;\n    }\n    return REDIS_OK; /* unreached */\n}\n\nvoid bgrewriteaofCommand(redisClient *c) {\n    if (server.aof_child_pid != -1) {\n        addReplyError(c,\"Background append only file rewriting already in progress\");\n    } else if (server.rdb_child_pid != -1) {\n        server.aof_rewrite_scheduled = 1;\n        addReplyStatus(c,\"Background append only file rewriting scheduled\");\n    } else if (rewriteAppendOnlyFileBackground() == REDIS_OK) {\n        addReplyStatus(c,\"Background append only file rewriting started\");\n    } else {\n        addReply(c,shared.err);\n    }\n}\n\nvoid aofRemoveTempFile(pid_t childpid) {\n    char tmpfile[256];\n\n    snprintf(tmpfile,256,\"temp-rewriteaof-bg-%d.aof\", (int) childpid);\n    unlink(tmpfile);\n}\n\n/* Update the server.aof_current_size field explicitly using stat(2)\n * to check the size of the file. This is useful after a rewrite or after\n * a restart, normally the size is updated just adding the write length\n * to the current length, that is much faster. */\nvoid aofUpdateCurrentSize(void) {\n    struct redis_stat sb;\n    mstime_t latency;\n\n    latencyStartMonitor(latency);\n    if (redis_fstat(server.aof_fd,&sb) == -1) {\n        redisLog(REDIS_WARNING,\"Unable to obtain the AOF file length. stat: %s\",\n            strerror(errno));\n    } else {\n        server.aof_current_size = sb.st_size;\n    }\n    latencyEndMonitor(latency);\n    latencyAddSampleIfNeeded(\"aof-fstat\",latency);\n}\n\n/* A background append only file rewriting (BGREWRITEAOF) terminated its work.\n * Handle this. */\nvoid backgroundRewriteDoneHandler(int exitcode, int bysignal) {\n    if (!bysignal && exitcode == 0) {\n        int newfd, oldfd;\n        char tmpfile[256];\n        long long now = ustime();\n        mstime_t latency;\n\n        redisLog(REDIS_NOTICE,\n            \"Background AOF rewrite terminated with success\");\n\n        /* Flush the differences accumulated by the parent to the\n         * rewritten AOF. */\n        latencyStartMonitor(latency);\n        snprintf(tmpfile,256,\"temp-rewriteaof-bg-%d.aof\",\n            (int)server.aof_child_pid);\n        newfd = open(tmpfile,O_WRONLY|O_APPEND);\n        if (newfd == -1) {\n            redisLog(REDIS_WARNING,\n                \"Unable to open the temporary AOF produced by the child: %s\", strerror(errno));\n            goto cleanup;\n        }\n\n        if (aofRewriteBufferWrite(newfd) == -1) {\n            redisLog(REDIS_WARNING,\n                \"Error trying to flush the parent diff to the rewritten AOF: %s\", strerror(errno));\n            close(newfd);\n            goto cleanup;\n        }\n        latencyEndMonitor(latency);\n        latencyAddSampleIfNeeded(\"aof-rewrite-diff-write\",latency);\n\n        redisLog(REDIS_NOTICE,\n            \"Parent diff successfully flushed to the rewritten AOF (%lu bytes)\", aofRewriteBufferSize());\n\n        /* The only remaining thing to do is to rename the temporary file to\n         * the configured file and switch the file descriptor used to do AOF\n         * writes. We don't want close(2) or rename(2) calls to block the\n         * server on old file deletion.\n         *\n         * There are two possible scenarios:\n         *\n         * 1) AOF is DISABLED and this was a one time rewrite. The temporary\n         * file will be renamed to the configured file. When this file already\n         * exists, it will be unlinked, which may block the server.\n         *\n         * 2) AOF is ENABLED and the rewritten AOF will immediately start\n         * receiving writes. After the temporary file is renamed to the\n         * configured file, the original AOF file descriptor will be closed.\n         * Since this will be the last reference to that file, closing it\n         * causes the underlying file to be unlinked, which may block the\n         * server.\n         *\n         * To mitigate the blocking effect of the unlink operation (either\n         * caused by rename(2) in scenario 1, or by close(2) in scenario 2), we\n         * use a background thread to take care of this. First, we\n         * make scenario 1 identical to scenario 2 by opening the target file\n         * when it exists. The unlink operation after the rename(2) will then\n         * be executed upon calling close(2) for its descriptor. Everything to\n         * guarantee atomicity for this switch has already happened by then, so\n         * we don't care what the outcome or duration of that close operation\n         * is, as long as the file descriptor is released again. */\n        if (server.aof_fd == -1) {\n            /* AOF disabled */\n\n             /* Don't care if this fails: oldfd will be -1 and we handle that.\n              * One notable case of -1 return is if the old file does\n              * not exist. */\n             oldfd = open(server.aof_filename,O_RDONLY|O_NONBLOCK);\n        } else {\n            /* AOF enabled */\n            oldfd = -1; /* We'll set this to the current AOF filedes later. */\n        }\n\n        /* Rename the temporary file. This will not unlink the target file if\n         * it exists, because we reference it with \"oldfd\". */\n        latencyStartMonitor(latency);\n        if (rename(tmpfile,server.aof_filename) == -1) {\n            redisLog(REDIS_WARNING,\n                \"Error trying to rename the temporary AOF file: %s\", strerror(errno));\n            close(newfd);\n            if (oldfd != -1) close(oldfd);\n            goto cleanup;\n        }\n        latencyEndMonitor(latency);\n        latencyAddSampleIfNeeded(\"aof-rename\",latency);\n\n        if (server.aof_fd == -1) {\n            /* AOF disabled, we don't need to set the AOF file descriptor\n             * to this new file, so we can close it. */\n            close(newfd);\n        } else {\n            /* AOF enabled, replace the old fd with the new one. */\n            oldfd = server.aof_fd;\n            server.aof_fd = newfd;\n            if (server.aof_fsync == AOF_FSYNC_ALWAYS)\n                aof_fsync(newfd);\n            else if (server.aof_fsync == AOF_FSYNC_EVERYSEC)\n                aof_background_fsync(newfd);\n            server.aof_selected_db = -1; /* Make sure SELECT is re-issued */\n            aofUpdateCurrentSize();\n            server.aof_rewrite_base_size = server.aof_current_size;\n\n            /* Clear regular AOF buffer since its contents was just written to\n             * the new AOF from the background rewrite buffer. */\n            sdsfree(server.aof_buf);\n            server.aof_buf = sdsempty();\n        }\n\n        server.aof_lastbgrewrite_status = REDIS_OK;\n\n        redisLog(REDIS_NOTICE, \"Background AOF rewrite finished successfully\");\n        /* Change state from WAIT_REWRITE to ON if needed */\n        if (server.aof_state == REDIS_AOF_WAIT_REWRITE)\n            server.aof_state = REDIS_AOF_ON;\n\n        /* Asynchronously close the overwritten AOF. */\n        if (oldfd != -1) bioCreateBackgroundJob(REDIS_BIO_CLOSE_FILE,(void*)(long)oldfd,NULL,NULL);\n\n        redisLog(REDIS_VERBOSE,\n            \"Background AOF rewrite signal handler took %lldus\", ustime()-now);\n    } else if (!bysignal && exitcode != 0) {\n        server.aof_lastbgrewrite_status = REDIS_ERR;\n\n        redisLog(REDIS_WARNING,\n            \"Background AOF rewrite terminated with error\");\n    } else {\n        server.aof_lastbgrewrite_status = REDIS_ERR;\n\n        redisLog(REDIS_WARNING,\n            \"Background AOF rewrite terminated by signal %d\", bysignal);\n    }\n\ncleanup:\n    aofRewriteBufferReset();\n    aofRemoveTempFile(server.aof_child_pid);\n    server.aof_child_pid = -1;\n    server.aof_rewrite_time_last = time(NULL)-server.aof_rewrite_time_start;\n    server.aof_rewrite_time_start = -1;\n    /* Schedule a new rewrite if we are waiting for it to switch the AOF ON. */\n    if (server.aof_state == REDIS_AOF_WAIT_REWRITE)\n        server.aof_rewrite_scheduled = 1;\n}\n"
  },
  {
    "path": "extern/deprecated/redis-2.8.21/src/asciilogo.h",
    "content": "/*\n * Copyright (c) 2009-2012, Salvatore Sanfilippo <antirez at gmail dot com>\n * All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions are met:\n *\n *   * Redistributions of source code must retain the above copyright notice,\n *     this list of conditions and the following disclaimer.\n *   * Redistributions in binary form must reproduce the above copyright\n *     notice, this list of conditions and the following disclaimer in the\n *     documentation and/or other materials provided with the distribution.\n *   * Neither the name of Redis nor the names of its contributors may be used\n *     to endorse or promote products derived from this software without\n *     specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\"\n * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\n * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE\n * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR\n * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF\n * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS\n * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN\n * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)\n * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE\n * POSSIBILITY OF SUCH DAMAGE.\n */\n\nchar *ascii_logo =\n\"                _._                                                  \\n\"\n\"           _.-``__ ''-._                                             \\n\"\n\"      _.-``    `.  `_.  ''-._           Redis %s (%s/%d) %s bit\\n\"\n\"  .-`` .-```.  ```\\\\/    _.,_ ''-._                                   \\n\"\n\" (    '      ,       .-`  | `,    )     Running in %s mode\\n\"\n\" |`-._`-...-` __...-.``-._|'` _.-'|     Port: %d\\n\"\n\" |    `-._   `._    /     _.-'    |     PID: %ld\\n\"\n\"  `-._    `-._  `-./  _.-'    _.-'                                   \\n\"\n\" |`-._`-._    `-.__.-'    _.-'_.-'|                                  \\n\"\n\" |    `-._`-._        _.-'_.-'    |           http://redis.io        \\n\"\n\"  `-._    `-._`-.__.-'_.-'    _.-'                                   \\n\"\n\" |`-._`-._    `-.__.-'    _.-'_.-'|                                  \\n\"\n\" |    `-._`-._        _.-'_.-'    |                                  \\n\"\n\"  `-._    `-._`-.__.-'_.-'    _.-'                                   \\n\"\n\"      `-._    `-.__.-'    _.-'                                       \\n\"\n\"          `-._        _.-'                                           \\n\"\n\"              `-.__.-'                                               \\n\\n\";\n"
  },
  {
    "path": "extern/deprecated/redis-2.8.21/src/bio.c",
    "content": "/* Background I/O service for Redis.\n *\n * This file implements operations that we need to perform in the background.\n * Currently there is only a single operation, that is a background close(2)\n * system call. This is needed as when the process is the last owner of a\n * reference to a file closing it means unlinking it, and the deletion of the\n * file is slow, blocking the server.\n *\n * In the future we'll either continue implementing new things we need or\n * we'll switch to libeio. However there are probably long term uses for this\n * file as we may want to put here Redis specific background tasks (for instance\n * it is not impossible that we'll need a non blocking FLUSHDB/FLUSHALL\n * implementation).\n *\n * DESIGN\n * ------\n *\n * The design is trivial, we have a structure representing a job to perform\n * and a different thread and job queue for every job type.\n * Every thread wait for new jobs in its queue, and process every job\n * sequentially.\n *\n * Jobs of the same type are guaranteed to be processed from the least\n * recently inserted to the most recently inserted (older jobs processed\n * first).\n *\n * Currently there is no way for the creator of the job to be notified about\n * the completion of the operation, this will only be added when/if needed.\n *\n * ----------------------------------------------------------------------------\n *\n * Copyright (c) 2009-2012, Salvatore Sanfilippo <antirez at gmail dot com>\n * All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions are met:\n *\n *   * Redistributions of source code must retain the above copyright notice,\n *     this list of conditions and the following disclaimer.\n *   * Redistributions in binary form must reproduce the above copyright\n *     notice, this list of conditions and the following disclaimer in the\n *     documentation and/or other materials provided with the distribution.\n *   * Neither the name of Redis nor the names of its contributors may be used\n *     to endorse or promote products derived from this software without\n *     specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\"\n * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\n * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE\n * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR\n * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF\n * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS\n * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN\n * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)\n * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE\n * POSSIBILITY OF SUCH DAMAGE.\n */\n\n\n#include \"redis.h\"\n#include \"bio.h\"\n\nstatic pthread_t bio_threads[REDIS_BIO_NUM_OPS];\nstatic pthread_mutex_t bio_mutex[REDIS_BIO_NUM_OPS];\nstatic pthread_cond_t bio_condvar[REDIS_BIO_NUM_OPS];\nstatic list *bio_jobs[REDIS_BIO_NUM_OPS];\n/* The following array is used to hold the number of pending jobs for every\n * OP type. This allows us to export the bioPendingJobsOfType() API that is\n * useful when the main thread wants to perform some operation that may involve\n * objects shared with the background thread. The main thread will just wait\n * that there are no longer jobs of this type to be executed before performing\n * the sensible operation. This data is also useful for reporting. */\nstatic unsigned long long bio_pending[REDIS_BIO_NUM_OPS];\n\n/* This structure represents a background Job. It is only used locally to this\n * file as the API does not expose the internals at all. */\nstruct bio_job {\n    time_t time; /* Time at which the job was created. */\n    /* Job specific arguments pointers. If we need to pass more than three\n     * arguments we can just pass a pointer to a structure or alike. */\n    void *arg1, *arg2, *arg3;\n};\n\nvoid *bioProcessBackgroundJobs(void *arg);\n\n/* Make sure we have enough stack to perform all the things we do in the\n * main thread. */\n#define REDIS_THREAD_STACK_SIZE (1024*1024*4)\n\n/* Initialize the background system, spawning the thread. */\nvoid bioInit(void) {\n    pthread_attr_t attr;\n    pthread_t thread;\n    size_t stacksize;\n    int j;\n\n    /* Initialization of state vars and objects */\n    for (j = 0; j < REDIS_BIO_NUM_OPS; j++) {\n        pthread_mutex_init(&bio_mutex[j],NULL);\n        pthread_cond_init(&bio_condvar[j],NULL);\n        bio_jobs[j] = listCreate();\n        bio_pending[j] = 0;\n    }\n\n    /* Set the stack size as by default it may be small in some system */\n    pthread_attr_init(&attr);\n    pthread_attr_getstacksize(&attr,&stacksize);\n    if (!stacksize) stacksize = 1; /* The world is full of Solaris Fixes */\n    while (stacksize < REDIS_THREAD_STACK_SIZE) stacksize *= 2;\n    pthread_attr_setstacksize(&attr, stacksize);\n\n    /* Ready to spawn our threads. We use the single argument the thread\n     * function accepts in order to pass the job ID the thread is\n     * responsible of. */\n    for (j = 0; j < REDIS_BIO_NUM_OPS; j++) {\n        void *arg = (void*)(unsigned long) j;\n        if (pthread_create(&thread,&attr,bioProcessBackgroundJobs,arg) != 0) {\n            redisLog(REDIS_WARNING,\"Fatal: Can't initialize Background Jobs.\");\n            exit(1);\n        }\n        bio_threads[j] = thread;\n    }\n}\n\nvoid bioCreateBackgroundJob(int type, void *arg1, void *arg2, void *arg3) {\n    struct bio_job *job = zmalloc(sizeof(*job));\n\n    job->time = time(NULL);\n    job->arg1 = arg1;\n    job->arg2 = arg2;\n    job->arg3 = arg3;\n    pthread_mutex_lock(&bio_mutex[type]);\n    listAddNodeTail(bio_jobs[type],job);\n    bio_pending[type]++;\n    pthread_cond_signal(&bio_condvar[type]);\n    pthread_mutex_unlock(&bio_mutex[type]);\n}\n\nvoid *bioProcessBackgroundJobs(void *arg) {\n    struct bio_job *job;\n    unsigned long type = (unsigned long) arg;\n    sigset_t sigset;\n\n    /* Make the thread killable at any time, so that bioKillThreads()\n     * can work reliably. */\n    pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);\n    pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL);\n\n    pthread_mutex_lock(&bio_mutex[type]);\n    /* Block SIGALRM so we are sure that only the main thread will\n     * receive the watchdog signal. */\n    sigemptyset(&sigset);\n    sigaddset(&sigset, SIGALRM);\n    if (pthread_sigmask(SIG_BLOCK, &sigset, NULL))\n        redisLog(REDIS_WARNING,\n            \"Warning: can't mask SIGALRM in bio.c thread: %s\", strerror(errno));\n\n    while(1) {\n        listNode *ln;\n\n        /* The loop always starts with the lock hold. */\n        if (listLength(bio_jobs[type]) == 0) {\n            pthread_cond_wait(&bio_condvar[type],&bio_mutex[type]);\n            continue;\n        }\n        /* Pop the job from the queue. */\n        ln = listFirst(bio_jobs[type]);\n        job = ln->value;\n        /* It is now possible to unlock the background system as we know have\n         * a stand alone job structure to process.*/\n        pthread_mutex_unlock(&bio_mutex[type]);\n\n        /* Process the job accordingly to its type. */\n        if (type == REDIS_BIO_CLOSE_FILE) {\n            close((long)job->arg1);\n        } else if (type == REDIS_BIO_AOF_FSYNC) {\n            aof_fsync((long)job->arg1);\n        } else {\n            redisPanic(\"Wrong job type in bioProcessBackgroundJobs().\");\n        }\n        zfree(job);\n\n        /* Lock again before reiterating the loop, if there are no longer\n         * jobs to process we'll block again in pthread_cond_wait(). */\n        pthread_mutex_lock(&bio_mutex[type]);\n        listDelNode(bio_jobs[type],ln);\n        bio_pending[type]--;\n    }\n}\n\n/* Return the number of pending jobs of the specified type. */\nunsigned long long bioPendingJobsOfType(int type) {\n    unsigned long long val;\n    pthread_mutex_lock(&bio_mutex[type]);\n    val = bio_pending[type];\n    pthread_mutex_unlock(&bio_mutex[type]);\n    return val;\n}\n\n/* Kill the running bio threads in an unclean way. This function should be\n * used only when it's critical to stop the threads for some reason.\n * Currently Redis does this only on crash (for instance on SIGSEGV) in order\n * to perform a fast memory check without other threads messing with memory. */\nvoid bioKillThreads(void) {\n    int err, j;\n\n    for (j = 0; j < REDIS_BIO_NUM_OPS; j++) {\n        if (pthread_cancel(bio_threads[j]) == 0) {\n            if ((err = pthread_join(bio_threads[j],NULL)) != 0) {\n                redisLog(REDIS_WARNING,\n                    \"Bio thread for job type #%d can be joined: %s\",\n                        j, strerror(err));\n            } else {\n                redisLog(REDIS_WARNING,\n                    \"Bio thread for job type #%d terminated\",j);\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "extern/deprecated/redis-2.8.21/src/bio.h",
    "content": "/*\n * Copyright (c) 2009-2012, Salvatore Sanfilippo <antirez at gmail dot com>\n * All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions are met:\n *\n *   * Redistributions of source code must retain the above copyright notice,\n *     this list of conditions and the following disclaimer.\n *   * Redistributions in binary form must reproduce the above copyright\n *     notice, this list of conditions and the following disclaimer in the\n *     documentation and/or other materials provided with the distribution.\n *   * Neither the name of Redis nor the names of its contributors may be used\n *     to endorse or promote products derived from this software without\n *     specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\"\n * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\n * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE\n * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR\n * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF\n * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS\n * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN\n * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)\n * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE\n * POSSIBILITY OF SUCH DAMAGE.\n */\n\n/* Exported API */\nvoid bioInit(void);\nvoid bioCreateBackgroundJob(int type, void *arg1, void *arg2, void *arg3);\nunsigned long long bioPendingJobsOfType(int type);\nvoid bioWaitPendingJobsLE(int type, unsigned long long num);\ntime_t bioOlderJobOfType(int type);\nvoid bioKillThreads(void);\n\n/* Background job opcodes */\n#define REDIS_BIO_CLOSE_FILE    0 /* Deferred close(2) syscall. */\n#define REDIS_BIO_AOF_FSYNC     1 /* Deferred AOF fsync. */\n#define REDIS_BIO_NUM_OPS       2\n"
  },
  {
    "path": "extern/deprecated/redis-2.8.21/src/bitops.c",
    "content": "/* Bit operations.\n *\n * Copyright (c) 2009-2012, Salvatore Sanfilippo <antirez at gmail dot com>\n * All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions are met:\n *\n *   * Redistributions of source code must retain the above copyright notice,\n *     this list of conditions and the following disclaimer.\n *   * Redistributions in binary form must reproduce the above copyright\n *     notice, this list of conditions and the following disclaimer in the\n *     documentation and/or other materials provided with the distribution.\n *   * Neither the name of Redis nor the names of its contributors may be used\n *     to endorse or promote products derived from this software without\n *     specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\"\n * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\n * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE\n * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR\n * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF\n * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS\n * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN\n * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)\n * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE\n * POSSIBILITY OF SUCH DAMAGE.\n */\n\n#include \"redis.h\"\n\n/* -----------------------------------------------------------------------------\n * Helpers and low level bit functions.\n * -------------------------------------------------------------------------- */\n\n/* This helper function used by GETBIT / SETBIT parses the bit offset argument\n * making sure an error is returned if it is negative or if it overflows\n * Redis 512 MB limit for the string value. */\nstatic int getBitOffsetFromArgument(redisClient *c, robj *o, size_t *offset) {\n    long long loffset;\n    char *err = \"bit offset is not an integer or out of range\";\n\n    if (getLongLongFromObjectOrReply(c,o,&loffset,err) != REDIS_OK)\n        return REDIS_ERR;\n\n    /* Limit offset to 512MB in bytes */\n    if ((loffset < 0) || ((unsigned long long)loffset >> 3) >= (512*1024*1024))\n    {\n        addReplyError(c,err);\n        return REDIS_ERR;\n    }\n\n    *offset = (size_t)loffset;\n    return REDIS_OK;\n}\n\n/* Count number of bits set in the binary array pointed by 's' and long\n * 'count' bytes. The implementation of this function is required to\n * work with a input string length up to 512 MB. */\nsize_t redisPopcount(void *s, long count) {\n    size_t bits = 0;\n    unsigned char *p = s;\n    uint32_t *p4;\n    static const unsigned char bitsinbyte[256] = {0,1,1,2,1,2,2,3,1,2,2,3,2,3,3,4,1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5,1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5,2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5,2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5,2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8};\n\n    /* Count initial bytes not aligned to 32 bit. */\n    while((unsigned long)p & 3 && count) {\n        bits += bitsinbyte[*p++];\n        count--;\n    }\n\n    /* Count bits 16 bytes at a time */\n    p4 = (uint32_t*)p;\n    while(count>=16) {\n        uint32_t aux1, aux2, aux3, aux4;\n\n        aux1 = *p4++;\n        aux2 = *p4++;\n        aux3 = *p4++;\n        aux4 = *p4++;\n        count -= 16;\n\n        aux1 = aux1 - ((aux1 >> 1) & 0x55555555);\n        aux1 = (aux1 & 0x33333333) + ((aux1 >> 2) & 0x33333333);\n        aux2 = aux2 - ((aux2 >> 1) & 0x55555555);\n        aux2 = (aux2 & 0x33333333) + ((aux2 >> 2) & 0x33333333);\n        aux3 = aux3 - ((aux3 >> 1) & 0x55555555);\n        aux3 = (aux3 & 0x33333333) + ((aux3 >> 2) & 0x33333333);\n        aux4 = aux4 - ((aux4 >> 1) & 0x55555555);\n        aux4 = (aux4 & 0x33333333) + ((aux4 >> 2) & 0x33333333);\n        bits += ((((aux1 + (aux1 >> 4)) & 0x0F0F0F0F) * 0x01010101) >> 24) +\n                ((((aux2 + (aux2 >> 4)) & 0x0F0F0F0F) * 0x01010101) >> 24) +\n                ((((aux3 + (aux3 >> 4)) & 0x0F0F0F0F) * 0x01010101) >> 24) +\n                ((((aux4 + (aux4 >> 4)) & 0x0F0F0F0F) * 0x01010101) >> 24);\n    }\n    /* Count the remaining bytes. */\n    p = (unsigned char*)p4;\n    while(count--) bits += bitsinbyte[*p++];\n    return bits;\n}\n\n/* Return the position of the first bit set to one (if 'bit' is 1) or\n * zero (if 'bit' is 0) in the bitmap starting at 's' and long 'count' bytes.\n *\n * The function is guaranteed to return a value >= 0 if 'bit' is 0 since if\n * no zero bit is found, it returns count*8 assuming the string is zero\n * padded on the right. However if 'bit' is 1 it is possible that there is\n * not a single set bit in the bitmap. In this special case -1 is returned. */\nlong redisBitpos(void *s, unsigned long count, int bit) {\n    unsigned long *l;\n    unsigned char *c;\n    unsigned long skipval, word = 0, one;\n    long pos = 0; /* Position of bit, to return to the caller. */\n    unsigned long j;\n\n    /* Process whole words first, seeking for first word that is not\n     * all ones or all zeros respectively if we are lookig for zeros\n     * or ones. This is much faster with large strings having contiguous\n     * blocks of 1 or 0 bits compared to the vanilla bit per bit processing.\n     *\n     * Note that if we start from an address that is not aligned\n     * to sizeof(unsigned long) we consume it byte by byte until it is\n     * aligned. */\n\n    /* Skip initial bits not aligned to sizeof(unsigned long) byte by byte. */\n    skipval = bit ? 0 : UCHAR_MAX;\n    c = (unsigned char*) s;\n    while((unsigned long)c & (sizeof(*l)-1) && count) {\n        if (*c != skipval) break;\n        c++;\n        count--;\n        pos += 8;\n    }\n\n    /* Skip bits with full word step. */\n    skipval = bit ? 0 : ULONG_MAX;\n    l = (unsigned long*) c;\n    while (count >= sizeof(*l)) {\n        if (*l != skipval) break;\n        l++;\n        count -= sizeof(*l);\n        pos += sizeof(*l)*8;\n    }\n\n    /* Load bytes into \"word\" considering the first byte as the most significant\n     * (we basically consider it as written in big endian, since we consider the\n     * string as a set of bits from left to right, with the first bit at position\n     * zero.\n     *\n     * Note that the loading is designed to work even when the bytes left\n     * (count) are less than a full word. We pad it with zero on the right. */\n    c = (unsigned char*)l;\n    for (j = 0; j < sizeof(*l); j++) {\n        word <<= 8;\n        if (count) {\n            word |= *c;\n            c++;\n            count--;\n        }\n    }\n\n    /* Special case:\n     * If bits in the string are all zero and we are looking for one,\n     * return -1 to signal that there is not a single \"1\" in the whole\n     * string. This can't happen when we are looking for \"0\" as we assume\n     * that the right of the string is zero padded. */\n    if (bit == 1 && word == 0) return -1;\n\n    /* Last word left, scan bit by bit. The first thing we need is to\n     * have a single \"1\" set in the most significant position in an\n     * unsigned long. We don't know the size of the long so we use a\n     * simple trick. */\n    one = ULONG_MAX; /* All bits set to 1.*/\n    one >>= 1;       /* All bits set to 1 but the MSB. */\n    one = ~one;      /* All bits set to 0 but the MSB. */\n\n    while(one) {\n        if (((one & word) != 0) == bit) return pos;\n        pos++;\n        one >>= 1;\n    }\n\n    /* If we reached this point, there is a bug in the algorithm, since\n     * the case of no match is handled as a special case before. */\n    redisPanic(\"End of redisBitpos() reached.\");\n    return 0; /* Just to avoid warnings. */\n}\n\n/* -----------------------------------------------------------------------------\n * Bits related string commands: GETBIT, SETBIT, BITCOUNT, BITOP.\n * -------------------------------------------------------------------------- */\n\n#define BITOP_AND   0\n#define BITOP_OR    1\n#define BITOP_XOR   2\n#define BITOP_NOT   3\n\n/* SETBIT key offset bitvalue */\nvoid setbitCommand(redisClient *c) {\n    robj *o;\n    char *err = \"bit is not an integer or out of range\";\n    size_t bitoffset;\n    int byte, bit;\n    int byteval, bitval;\n    long on;\n\n    if (getBitOffsetFromArgument(c,c->argv[2],&bitoffset) != REDIS_OK)\n        return;\n\n    if (getLongFromObjectOrReply(c,c->argv[3],&on,err) != REDIS_OK)\n        return;\n\n    /* Bits can only be set or cleared... */\n    if (on & ~1) {\n        addReplyError(c,err);\n        return;\n    }\n\n    o = lookupKeyWrite(c->db,c->argv[1]);\n    if (o == NULL) {\n        o = createObject(REDIS_STRING,sdsempty());\n        dbAdd(c->db,c->argv[1],o);\n    } else {\n        if (checkType(c,o,REDIS_STRING)) return;\n        o = dbUnshareStringValue(c->db,c->argv[1],o);\n    }\n\n    /* Grow sds value to the right length if necessary */\n    byte = bitoffset >> 3;\n    o->ptr = sdsgrowzero(o->ptr,byte+1);\n\n    /* Get current values */\n    byteval = ((uint8_t*)o->ptr)[byte];\n    bit = 7 - (bitoffset & 0x7);\n    bitval = byteval & (1 << bit);\n\n    /* Update byte with new bit value and return original value */\n    byteval &= ~(1 << bit);\n    byteval |= ((on & 0x1) << bit);\n    ((uint8_t*)o->ptr)[byte] = byteval;\n    signalModifiedKey(c->db,c->argv[1]);\n    notifyKeyspaceEvent(REDIS_NOTIFY_STRING,\"setbit\",c->argv[1],c->db->id);\n    server.dirty++;\n    addReply(c, bitval ? shared.cone : shared.czero);\n}\n\n/* GETBIT key offset */\nvoid getbitCommand(redisClient *c) {\n    robj *o;\n    char llbuf[32];\n    size_t bitoffset;\n    size_t byte, bit;\n    size_t bitval = 0;\n\n    if (getBitOffsetFromArgument(c,c->argv[2],&bitoffset) != REDIS_OK)\n        return;\n\n    if ((o = lookupKeyReadOrReply(c,c->argv[1],shared.czero)) == NULL ||\n        checkType(c,o,REDIS_STRING)) return;\n\n    byte = bitoffset >> 3;\n    bit = 7 - (bitoffset & 0x7);\n    if (o->encoding != REDIS_ENCODING_RAW) {\n        if (byte < (size_t)ll2string(llbuf,sizeof(llbuf),(long)o->ptr))\n            bitval = llbuf[byte] & (1 << bit);\n    } else {\n        if (byte < sdslen(o->ptr))\n            bitval = ((uint8_t*)o->ptr)[byte] & (1 << bit);\n    }\n\n    addReply(c, bitval ? shared.cone : shared.czero);\n}\n\n/* BITOP op_name target_key src_key1 src_key2 src_key3 ... src_keyN */\nvoid bitopCommand(redisClient *c) {\n    char *opname = c->argv[1]->ptr;\n    robj *o, *targetkey = c->argv[2];\n    unsigned long op, j, numkeys;\n    robj **objects;      /* Array of source objects. */\n    unsigned char **src; /* Array of source strings pointers. */\n    unsigned long *len, maxlen = 0; /* Array of length of src strings,\n                                       and max len. */\n    unsigned long minlen = 0;    /* Min len among the input keys. */\n    unsigned char *res = NULL; /* Resulting string. */\n\n    /* Parse the operation name. */\n    if ((opname[0] == 'a' || opname[0] == 'A') && !strcasecmp(opname,\"and\"))\n        op = BITOP_AND;\n    else if((opname[0] == 'o' || opname[0] == 'O') && !strcasecmp(opname,\"or\"))\n        op = BITOP_OR;\n    else if((opname[0] == 'x' || opname[0] == 'X') && !strcasecmp(opname,\"xor\"))\n        op = BITOP_XOR;\n    else if((opname[0] == 'n' || opname[0] == 'N') && !strcasecmp(opname,\"not\"))\n        op = BITOP_NOT;\n    else {\n        addReply(c,shared.syntaxerr);\n        return;\n    }\n\n    /* Sanity check: NOT accepts only a single key argument. */\n    if (op == BITOP_NOT && c->argc != 4) {\n        addReplyError(c,\"BITOP NOT must be called with a single source key.\");\n        return;\n    }\n\n    /* Lookup keys, and store pointers to the string objects into an array. */\n    numkeys = c->argc - 3;\n    src = zmalloc(sizeof(unsigned char*) * numkeys);\n    len = zmalloc(sizeof(long) * numkeys);\n    objects = zmalloc(sizeof(robj*) * numkeys);\n    for (j = 0; j < numkeys; j++) {\n        o = lookupKeyRead(c->db,c->argv[j+3]);\n        /* Handle non-existing keys as empty strings. */\n        if (o == NULL) {\n            objects[j] = NULL;\n            src[j] = NULL;\n            len[j] = 0;\n            minlen = 0;\n            continue;\n        }\n        /* Return an error if one of the keys is not a string. */\n        if (checkType(c,o,REDIS_STRING)) {\n            unsigned long i;\n            for (i = 0; i < j; i++) {\n                if (objects[i])\n                    decrRefCount(objects[i]);\n            }\n            zfree(src);\n            zfree(len);\n            zfree(objects);\n            return;\n        }\n        objects[j] = getDecodedObject(o);\n        src[j] = objects[j]->ptr;\n        len[j] = sdslen(objects[j]->ptr);\n        if (len[j] > maxlen) maxlen = len[j];\n        if (j == 0 || len[j] < minlen) minlen = len[j];\n    }\n\n    /* Compute the bit operation, if at least one string is not empty. */\n    if (maxlen) {\n        res = (unsigned char*) sdsnewlen(NULL,maxlen);\n        unsigned char output, byte;\n        unsigned long i;\n\n        /* Fast path: as far as we have data for all the input bitmaps we\n         * can take a fast path that performs much better than the\n         * vanilla algorithm. */\n        j = 0;\n        if (minlen && numkeys <= 16) {\n            unsigned long *lp[16];\n            unsigned long *lres = (unsigned long*) res;\n\n            /* Note: sds pointer is always aligned to 8 byte boundary. */\n            memcpy(lp,src,sizeof(unsigned long*)*numkeys);\n            memcpy(res,src[0],minlen);\n\n            /* Different branches per different operations for speed (sorry). */\n            if (op == BITOP_AND) {\n                while(minlen >= sizeof(unsigned long)*4) {\n                    for (i = 1; i < numkeys; i++) {\n                        lres[0] &= lp[i][0];\n                        lres[1] &= lp[i][1];\n                        lres[2] &= lp[i][2];\n                        lres[3] &= lp[i][3];\n                        lp[i]+=4;\n                    }\n                    lres+=4;\n                    j += sizeof(unsigned long)*4;\n                    minlen -= sizeof(unsigned long)*4;\n                }\n            } else if (op == BITOP_OR) {\n                while(minlen >= sizeof(unsigned long)*4) {\n                    for (i = 1; i < numkeys; i++) {\n                        lres[0] |= lp[i][0];\n                        lres[1] |= lp[i][1];\n                        lres[2] |= lp[i][2];\n                        lres[3] |= lp[i][3];\n                        lp[i]+=4;\n                    }\n                    lres+=4;\n                    j += sizeof(unsigned long)*4;\n                    minlen -= sizeof(unsigned long)*4;\n                }\n            } else if (op == BITOP_XOR) {\n                while(minlen >= sizeof(unsigned long)*4) {\n                    for (i = 1; i < numkeys; i++) {\n                        lres[0] ^= lp[i][0];\n                        lres[1] ^= lp[i][1];\n                        lres[2] ^= lp[i][2];\n                        lres[3] ^= lp[i][3];\n                        lp[i]+=4;\n                    }\n                    lres+=4;\n                    j += sizeof(unsigned long)*4;\n                    minlen -= sizeof(unsigned long)*4;\n                }\n            } else if (op == BITOP_NOT) {\n                while(minlen >= sizeof(unsigned long)*4) {\n                    lres[0] = ~lres[0];\n                    lres[1] = ~lres[1];\n                    lres[2] = ~lres[2];\n                    lres[3] = ~lres[3];\n                    lres+=4;\n                    j += sizeof(unsigned long)*4;\n                    minlen -= sizeof(unsigned long)*4;\n                }\n            }\n        }\n\n        /* j is set to the next byte to process by the previous loop. */\n        for (; j < maxlen; j++) {\n            output = (len[0] <= j) ? 0 : src[0][j];\n            if (op == BITOP_NOT) output = ~output;\n            for (i = 1; i < numkeys; i++) {\n                byte = (len[i] <= j) ? 0 : src[i][j];\n                switch(op) {\n                case BITOP_AND: output &= byte; break;\n                case BITOP_OR:  output |= byte; break;\n                case BITOP_XOR: output ^= byte; break;\n                }\n            }\n            res[j] = output;\n        }\n    }\n    for (j = 0; j < numkeys; j++) {\n        if (objects[j])\n            decrRefCount(objects[j]);\n    }\n    zfree(src);\n    zfree(len);\n    zfree(objects);\n\n    /* Store the computed value into the target key */\n    if (maxlen) {\n        o = createObject(REDIS_STRING,res);\n        setKey(c->db,targetkey,o);\n        notifyKeyspaceEvent(REDIS_NOTIFY_STRING,\"set\",targetkey,c->db->id);\n        decrRefCount(o);\n    } else if (dbDelete(c->db,targetkey)) {\n        signalModifiedKey(c->db,targetkey);\n        notifyKeyspaceEvent(REDIS_NOTIFY_GENERIC,\"del\",targetkey,c->db->id);\n    }\n    server.dirty++;\n    addReplyLongLong(c,maxlen); /* Return the output string length in bytes. */\n}\n\n/* BITCOUNT key [start end] */\nvoid bitcountCommand(redisClient *c) {\n    robj *o;\n    long start, end, strlen;\n    unsigned char *p;\n    char llbuf[32];\n\n    /* Lookup, check for type, and return 0 for non existing keys. */\n    if ((o = lookupKeyReadOrReply(c,c->argv[1],shared.czero)) == NULL ||\n        checkType(c,o,REDIS_STRING)) return;\n\n    /* Set the 'p' pointer to the string, that can be just a stack allocated\n     * array if our string was integer encoded. */\n    if (o->encoding == REDIS_ENCODING_INT) {\n        p = (unsigned char*) llbuf;\n        strlen = ll2string(llbuf,sizeof(llbuf),(long)o->ptr);\n    } else {\n        p = (unsigned char*) o->ptr;\n        strlen = sdslen(o->ptr);\n    }\n\n    /* Parse start/end range if any. */\n    if (c->argc == 4) {\n        if (getLongFromObjectOrReply(c,c->argv[2],&start,NULL) != REDIS_OK)\n            return;\n        if (getLongFromObjectOrReply(c,c->argv[3],&end,NULL) != REDIS_OK)\n            return;\n        /* Convert negative indexes */\n        if (start < 0) start = strlen+start;\n        if (end < 0) end = strlen+end;\n        if (start < 0) start = 0;\n        if (end < 0) end = 0;\n        if (end >= strlen) end = strlen-1;\n    } else if (c->argc == 2) {\n        /* The whole string. */\n        start = 0;\n        end = strlen-1;\n    } else {\n        /* Syntax error. */\n        addReply(c,shared.syntaxerr);\n        return;\n    }\n\n    /* Precondition: end >= 0 && end < strlen, so the only condition where\n     * zero can be returned is: start > end. */\n    if (start > end) {\n        addReply(c,shared.czero);\n    } else {\n        long bytes = end-start+1;\n\n        addReplyLongLong(c,redisPopcount(p+start,bytes));\n    }\n}\n\n/* BITPOS key bit [start [end]] */\nvoid bitposCommand(redisClient *c) {\n    robj *o;\n    long bit, start, end, strlen;\n    unsigned char *p;\n    char llbuf[32];\n    int end_given = 0;\n\n    /* Parse the bit argument to understand what we are looking for, set\n     * or clear bits. */\n    if (getLongFromObjectOrReply(c,c->argv[2],&bit,NULL) != REDIS_OK)\n        return;\n    if (bit != 0 && bit != 1) {\n        addReplyError(c, \"The bit argument must be 1 or 0.\");\n        return;\n    }\n\n    /* If the key does not exist, from our point of view it is an infinite\n     * array of 0 bits. If the user is looking for the fist clear bit return 0,\n     * If the user is looking for the first set bit, return -1. */\n    if ((o = lookupKeyRead(c->db,c->argv[1])) == NULL) {\n        addReplyLongLong(c, bit ? -1 : 0);\n        return;\n    }\n    if (checkType(c,o,REDIS_STRING)) return;\n\n    /* Set the 'p' pointer to the string, that can be just a stack allocated\n     * array if our string was integer encoded. */\n    if (o->encoding == REDIS_ENCODING_INT) {\n        p = (unsigned char*) llbuf;\n        strlen = ll2string(llbuf,sizeof(llbuf),(long)o->ptr);\n    } else {\n        p = (unsigned char*) o->ptr;\n        strlen = sdslen(o->ptr);\n    }\n\n    /* Parse start/end range if any. */\n    if (c->argc == 4 || c->argc == 5) {\n        if (getLongFromObjectOrReply(c,c->argv[3],&start,NULL) != REDIS_OK)\n            return;\n        if (c->argc == 5) {\n            if (getLongFromObjectOrReply(c,c->argv[4],&end,NULL) != REDIS_OK)\n                return;\n            end_given = 1;\n        } else {\n            end = strlen-1;\n        }\n        /* Convert negative indexes */\n        if (start < 0) start = strlen+start;\n        if (end < 0) end = strlen+end;\n        if (start < 0) start = 0;\n        if (end < 0) end = 0;\n        if (end >= strlen) end = strlen-1;\n    } else if (c->argc == 3) {\n        /* The whole string. */\n        start = 0;\n        end = strlen-1;\n    } else {\n        /* Syntax error. */\n        addReply(c,shared.syntaxerr);\n        return;\n    }\n\n    /* For empty ranges (start > end) we return -1 as an empty range does\n     * not contain a 0 nor a 1. */\n    if (start > end) {\n        addReplyLongLong(c, -1);\n    } else {\n        long bytes = end-start+1;\n        long pos = redisBitpos(p+start,bytes,bit);\n\n        /* If we are looking for clear bits, and the user specified an exact\n         * range with start-end, we can't consider the right of the range as\n         * zero padded (as we do when no explicit end is given).\n         *\n         * So if redisBitpos() returns the first bit outside the range,\n         * we return -1 to the caller, to mean, in the specified range there\n         * is not a single \"0\" bit. */\n        if (end_given && bit == 0 && pos == bytes*8) {\n            addReplyLongLong(c,-1);\n            return;\n        }\n        if (pos != -1) pos += start*8; /* Adjust for the bytes we skipped. */\n        addReplyLongLong(c,pos);\n    }\n}\n"
  },
  {
    "path": "extern/deprecated/redis-2.8.21/src/config.c",
    "content": "/* Configuration file parsing and CONFIG GET/SET commands implementation.\n *\n * Copyright (c) 2009-2012, Salvatore Sanfilippo <antirez at gmail dot com>\n * All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions are met:\n *\n *   * Redistributions of source code must retain the above copyright notice,\n *     this list of conditions and the following disclaimer.\n *   * Redistributions in binary form must reproduce the above copyright\n *     notice, this list of conditions and the following disclaimer in the\n *     documentation and/or other materials provided with the distribution.\n *   * Neither the name of Redis nor the names of its contributors may be used\n *     to endorse or promote products derived from this software without\n *     specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\"\n * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\n * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE\n * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR\n * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF\n * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS\n * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN\n * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)\n * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE\n * POSSIBILITY OF SUCH DAMAGE.\n */\n\n#include \"redis.h\"\n\n#include <fcntl.h>\n#include <sys/stat.h>\n\nstatic struct {\n    const char     *name;\n    const int       value;\n} validSyslogFacilities[] = {\n    {\"user\",    LOG_USER},\n    {\"local0\",  LOG_LOCAL0},\n    {\"local1\",  LOG_LOCAL1},\n    {\"local2\",  LOG_LOCAL2},\n    {\"local3\",  LOG_LOCAL3},\n    {\"local4\",  LOG_LOCAL4},\n    {\"local5\",  LOG_LOCAL5},\n    {\"local6\",  LOG_LOCAL6},\n    {\"local7\",  LOG_LOCAL7},\n    {NULL, 0}\n};\n\nclientBufferLimitsConfig clientBufferLimitsDefaults[REDIS_CLIENT_TYPE_COUNT] = {\n    {0, 0, 0}, /* normal */\n    {1024*1024*256, 1024*1024*64, 60}, /* slave */\n    {1024*1024*32, 1024*1024*8, 60}  /* pubsub */\n};\n\n/*-----------------------------------------------------------------------------\n * Config file parsing\n *----------------------------------------------------------------------------*/\n\nint yesnotoi(char *s) {\n    if (!strcasecmp(s,\"yes\")) return 1;\n    else if (!strcasecmp(s,\"no\")) return 0;\n    else return -1;\n}\n\nvoid appendServerSaveParams(time_t seconds, int changes) {\n    server.saveparams = zrealloc(server.saveparams,sizeof(struct saveparam)*(server.saveparamslen+1));\n    server.saveparams[server.saveparamslen].seconds = seconds;\n    server.saveparams[server.saveparamslen].changes = changes;\n    server.saveparamslen++;\n}\n\nvoid resetServerSaveParams(void) {\n    zfree(server.saveparams);\n    server.saveparams = NULL;\n    server.saveparamslen = 0;\n}\n\nvoid loadServerConfigFromString(char *config) {\n    char *err = NULL;\n    int linenum = 0, totlines, i;\n    sds *lines;\n\n    lines = sdssplitlen(config,strlen(config),\"\\n\",1,&totlines);\n\n    for (i = 0; i < totlines; i++) {\n        sds *argv;\n        int argc;\n\n        linenum = i+1;\n        lines[i] = sdstrim(lines[i],\" \\t\\r\\n\");\n\n        /* Skip comments and blank lines */\n        if (lines[i][0] == '#' || lines[i][0] == '\\0') continue;\n\n        /* Split into arguments */\n        argv = sdssplitargs(lines[i],&argc);\n        if (argv == NULL) {\n            err = \"Unbalanced quotes in configuration line\";\n            goto loaderr;\n        }\n\n        /* Skip this line if the resulting command vector is empty. */\n        if (argc == 0) {\n            sdsfreesplitres(argv,argc);\n            continue;\n        }\n        sdstolower(argv[0]);\n\n        /* Execute config directives */\n        if (!strcasecmp(argv[0],\"timeout\") && argc == 2) {\n            server.maxidletime = atoi(argv[1]);\n            if (server.maxidletime < 0) {\n                err = \"Invalid timeout value\"; goto loaderr;\n            }\n        } else if (!strcasecmp(argv[0],\"tcp-keepalive\") && argc == 2) {\n            server.tcpkeepalive = atoi(argv[1]);\n            if (server.tcpkeepalive < 0) {\n                err = \"Invalid tcp-keepalive value\"; goto loaderr;\n            }\n        } else if (!strcasecmp(argv[0],\"port\") && argc == 2) {\n            server.port = atoi(argv[1]);\n            if (server.port < 0 || server.port > 65535) {\n                err = \"Invalid port\"; goto loaderr;\n            }\n        } else if (!strcasecmp(argv[0],\"tcp-backlog\") && argc == 2) {\n            server.tcp_backlog = atoi(argv[1]);\n            if (server.tcp_backlog < 0) {\n                err = \"Invalid backlog value\"; goto loaderr;\n            }\n        } else if (!strcasecmp(argv[0],\"bind\") && argc >= 2) {\n            int j, addresses = argc-1;\n\n            if (addresses > REDIS_BINDADDR_MAX) {\n                err = \"Too many bind addresses specified\"; goto loaderr;\n            }\n            for (j = 0; j < addresses; j++)\n                server.bindaddr[j] = zstrdup(argv[j+1]);\n            server.bindaddr_count = addresses;\n        } else if (!strcasecmp(argv[0],\"unixsocket\") && argc == 2) {\n            server.unixsocket = zstrdup(argv[1]);\n        } else if (!strcasecmp(argv[0],\"unixsocketperm\") && argc == 2) {\n            errno = 0;\n            server.unixsocketperm = (mode_t)strtol(argv[1], NULL, 8);\n            if (errno || server.unixsocketperm > 0777) {\n                err = \"Invalid socket file permissions\"; goto loaderr;\n            }\n        } else if (!strcasecmp(argv[0],\"save\")) {\n            if (argc == 3) {\n                int seconds = atoi(argv[1]);\n                int changes = atoi(argv[2]);\n                if (seconds < 1 || changes < 0) {\n                    err = \"Invalid save parameters\"; goto loaderr;\n                }\n                appendServerSaveParams(seconds,changes);\n            } else if (argc == 2 && !strcasecmp(argv[1],\"\")) {\n                resetServerSaveParams();\n            }\n        } else if (!strcasecmp(argv[0],\"dir\") && argc == 2) {\n            if (chdir(argv[1]) == -1) {\n                redisLog(REDIS_WARNING,\"Can't chdir to '%s': %s\",\n                    argv[1], strerror(errno));\n                exit(1);\n            }\n        } else if (!strcasecmp(argv[0],\"loglevel\") && argc == 2) {\n            if (!strcasecmp(argv[1],\"debug\")) server.verbosity = REDIS_DEBUG;\n            else if (!strcasecmp(argv[1],\"verbose\")) server.verbosity = REDIS_VERBOSE;\n            else if (!strcasecmp(argv[1],\"notice\")) server.verbosity = REDIS_NOTICE;\n            else if (!strcasecmp(argv[1],\"warning\")) server.verbosity = REDIS_WARNING;\n            else {\n                err = \"Invalid log level. Must be one of debug, notice, warning\";\n                goto loaderr;\n            }\n        } else if (!strcasecmp(argv[0],\"logfile\") && argc == 2) {\n            FILE *logfp;\n\n            zfree(server.logfile);\n            server.logfile = zstrdup(argv[1]);\n            if (server.logfile[0] != '\\0') {\n                /* Test if we are able to open the file. The server will not\n                 * be able to abort just for this problem later... */\n                logfp = fopen(server.logfile,\"a\");\n                if (logfp == NULL) {\n                    err = sdscatprintf(sdsempty(),\n                        \"Can't open the log file: %s\", strerror(errno));\n                    goto loaderr;\n                }\n                fclose(logfp);\n            }\n        } else if (!strcasecmp(argv[0],\"syslog-enabled\") && argc == 2) {\n            if ((server.syslog_enabled = yesnotoi(argv[1])) == -1) {\n                err = \"argument must be 'yes' or 'no'\"; goto loaderr;\n            }\n        } else if (!strcasecmp(argv[0],\"syslog-ident\") && argc == 2) {\n            if (server.syslog_ident) zfree(server.syslog_ident);\n            server.syslog_ident = zstrdup(argv[1]);\n        } else if (!strcasecmp(argv[0],\"syslog-facility\") && argc == 2) {\n            int i;\n\n            for (i = 0; validSyslogFacilities[i].name; i++) {\n                if (!strcasecmp(validSyslogFacilities[i].name, argv[1])) {\n                    server.syslog_facility = validSyslogFacilities[i].value;\n                    break;\n                }\n            }\n\n            if (!validSyslogFacilities[i].name) {\n                err = \"Invalid log facility. Must be one of USER or between LOCAL0-LOCAL7\";\n                goto loaderr;\n            }\n        } else if (!strcasecmp(argv[0],\"databases\") && argc == 2) {\n            server.dbnum = atoi(argv[1]);\n            if (server.dbnum < 1) {\n                err = \"Invalid number of databases\"; goto loaderr;\n            }\n        } else if (!strcasecmp(argv[0],\"include\") && argc == 2) {\n            loadServerConfig(argv[1],NULL);\n        } else if (!strcasecmp(argv[0],\"maxclients\") && argc == 2) {\n            server.maxclients = atoi(argv[1]);\n            if (server.maxclients < 1) {\n                err = \"Invalid max clients limit\"; goto loaderr;\n            }\n        } else if (!strcasecmp(argv[0],\"maxmemory\") && argc == 2) {\n            server.maxmemory = memtoll(argv[1],NULL);\n        } else if (!strcasecmp(argv[0],\"maxmemory-policy\") && argc == 2) {\n            if (!strcasecmp(argv[1],\"volatile-lru\")) {\n                server.maxmemory_policy = REDIS_MAXMEMORY_VOLATILE_LRU;\n            } else if (!strcasecmp(argv[1],\"volatile-random\")) {\n                server.maxmemory_policy = REDIS_MAXMEMORY_VOLATILE_RANDOM;\n            } else if (!strcasecmp(argv[1],\"volatile-ttl\")) {\n                server.maxmemory_policy = REDIS_MAXMEMORY_VOLATILE_TTL;\n            } else if (!strcasecmp(argv[1],\"allkeys-lru\")) {\n                server.maxmemory_policy = REDIS_MAXMEMORY_ALLKEYS_LRU;\n            } else if (!strcasecmp(argv[1],\"allkeys-random\")) {\n                server.maxmemory_policy = REDIS_MAXMEMORY_ALLKEYS_RANDOM;\n            } else if (!strcasecmp(argv[1],\"noeviction\")) {\n                server.maxmemory_policy = REDIS_MAXMEMORY_NO_EVICTION;\n            } else {\n                err = \"Invalid maxmemory policy\";\n                goto loaderr;\n            }\n        } else if (!strcasecmp(argv[0],\"maxmemory-samples\") && argc == 2) {\n            server.maxmemory_samples = atoi(argv[1]);\n            if (server.maxmemory_samples <= 0) {\n                err = \"maxmemory-samples must be 1 or greater\";\n                goto loaderr;\n            }\n        } else if (!strcasecmp(argv[0],\"slaveof\") && argc == 3) {\n            server.masterhost = sdsnew(argv[1]);\n            server.masterport = atoi(argv[2]);\n            server.repl_state = REDIS_REPL_CONNECT;\n        } else if (!strcasecmp(argv[0],\"repl-ping-slave-period\") && argc == 2) {\n            server.repl_ping_slave_period = atoi(argv[1]);\n            if (server.repl_ping_slave_period <= 0) {\n                err = \"repl-ping-slave-period must be 1 or greater\";\n                goto loaderr;\n            }\n        } else if (!strcasecmp(argv[0],\"repl-timeout\") && argc == 2) {\n            server.repl_timeout = atoi(argv[1]);\n            if (server.repl_timeout <= 0) {\n                err = \"repl-timeout must be 1 or greater\";\n                goto loaderr;\n            }\n        } else if (!strcasecmp(argv[0],\"repl-disable-tcp-nodelay\") && argc==2) {\n            if ((server.repl_disable_tcp_nodelay = yesnotoi(argv[1])) == -1) {\n                err = \"argument must be 'yes' or 'no'\"; goto loaderr;\n            }\n        } else if (!strcasecmp(argv[0],\"repl-diskless-sync\") && argc==2) {\n            if ((server.repl_diskless_sync = yesnotoi(argv[1])) == -1) {\n                err = \"argument must be 'yes' or 'no'\"; goto loaderr;\n            }\n        } else if (!strcasecmp(argv[0],\"repl-diskless-sync-delay\") && argc==2) {\n            server.repl_diskless_sync_delay = atoi(argv[1]);\n            if (server.repl_diskless_sync_delay < 0) {\n                err = \"repl-diskless-sync-delay can't be negative\";\n                goto loaderr;\n            }\n        } else if (!strcasecmp(argv[0],\"repl-backlog-size\") && argc == 2) {\n            long long size = memtoll(argv[1],NULL);\n            if (size <= 0) {\n                err = \"repl-backlog-size must be 1 or greater.\";\n                goto loaderr;\n            }\n            resizeReplicationBacklog(size);\n        } else if (!strcasecmp(argv[0],\"repl-backlog-ttl\") && argc == 2) {\n            server.repl_backlog_time_limit = atoi(argv[1]);\n            if (server.repl_backlog_time_limit < 0) {\n                err = \"repl-backlog-ttl can't be negative \";\n                goto loaderr;\n            }\n        } else if (!strcasecmp(argv[0],\"masterauth\") && argc == 2) {\n            server.masterauth = zstrdup(argv[1]);\n        } else if (!strcasecmp(argv[0],\"slave-serve-stale-data\") && argc == 2) {\n            if ((server.repl_serve_stale_data = yesnotoi(argv[1])) == -1) {\n                err = \"argument must be 'yes' or 'no'\"; goto loaderr;\n            }\n        } else if (!strcasecmp(argv[0],\"slave-read-only\") && argc == 2) {\n            if ((server.repl_slave_ro = yesnotoi(argv[1])) == -1) {\n                err = \"argument must be 'yes' or 'no'\"; goto loaderr;\n            }\n        } else if (!strcasecmp(argv[0],\"rdbcompression\") && argc == 2) {\n            if ((server.rdb_compression = yesnotoi(argv[1])) == -1) {\n                err = \"argument must be 'yes' or 'no'\"; goto loaderr;\n            }\n        } else if (!strcasecmp(argv[0],\"rdbchecksum\") && argc == 2) {\n            if ((server.rdb_checksum = yesnotoi(argv[1])) == -1) {\n                err = \"argument must be 'yes' or 'no'\"; goto loaderr;\n            }\n        } else if (!strcasecmp(argv[0],\"activerehashing\") && argc == 2) {\n            if ((server.activerehashing = yesnotoi(argv[1])) == -1) {\n                err = \"argument must be 'yes' or 'no'\"; goto loaderr;\n            }\n        } else if (!strcasecmp(argv[0],\"daemonize\") && argc == 2) {\n            if ((server.daemonize = yesnotoi(argv[1])) == -1) {\n                err = \"argument must be 'yes' or 'no'\"; goto loaderr;\n            }\n        } else if (!strcasecmp(argv[0],\"hz\") && argc == 2) {\n            server.hz = atoi(argv[1]);\n            if (server.hz < REDIS_MIN_HZ) server.hz = REDIS_MIN_HZ;\n            if (server.hz > REDIS_MAX_HZ) server.hz = REDIS_MAX_HZ;\n        } else if (!strcasecmp(argv[0],\"appendonly\") && argc == 2) {\n            int yes;\n\n            if ((yes = yesnotoi(argv[1])) == -1) {\n                err = \"argument must be 'yes' or 'no'\"; goto loaderr;\n            }\n            server.aof_state = yes ? REDIS_AOF_ON : REDIS_AOF_OFF;\n        } else if (!strcasecmp(argv[0],\"appendfilename\") && argc == 2) {\n            if (!pathIsBaseName(argv[1])) {\n                err = \"appendfilename can't be a path, just a filename\";\n                goto loaderr;\n            }\n            zfree(server.aof_filename);\n            server.aof_filename = zstrdup(argv[1]);\n        } else if (!strcasecmp(argv[0],\"no-appendfsync-on-rewrite\")\n                   && argc == 2) {\n            if ((server.aof_no_fsync_on_rewrite= yesnotoi(argv[1])) == -1) {\n                err = \"argument must be 'yes' or 'no'\"; goto loaderr;\n            }\n        } else if (!strcasecmp(argv[0],\"appendfsync\") && argc == 2) {\n            if (!strcasecmp(argv[1],\"no\")) {\n                server.aof_fsync = AOF_FSYNC_NO;\n            } else if (!strcasecmp(argv[1],\"always\")) {\n                server.aof_fsync = AOF_FSYNC_ALWAYS;\n            } else if (!strcasecmp(argv[1],\"everysec\")) {\n                server.aof_fsync = AOF_FSYNC_EVERYSEC;\n            } else {\n                err = \"argument must be 'no', 'always' or 'everysec'\";\n                goto loaderr;\n            }\n        } else if (!strcasecmp(argv[0],\"auto-aof-rewrite-percentage\") &&\n                   argc == 2)\n        {\n            server.aof_rewrite_perc = atoi(argv[1]);\n            if (server.aof_rewrite_perc < 0) {\n                err = \"Invalid negative percentage for AOF auto rewrite\";\n                goto loaderr;\n            }\n        } else if (!strcasecmp(argv[0],\"auto-aof-rewrite-min-size\") &&\n                   argc == 2)\n        {\n            server.aof_rewrite_min_size = memtoll(argv[1],NULL);\n        } else if (!strcasecmp(argv[0],\"aof-rewrite-incremental-fsync\") &&\n                   argc == 2)\n        {\n            if ((server.aof_rewrite_incremental_fsync =\n                 yesnotoi(argv[1])) == -1) {\n                err = \"argument must be 'yes' or 'no'\"; goto loaderr;\n            }\n        } else if (!strcasecmp(argv[0],\"aof-load-truncated\") && argc == 2) {\n            if ((server.aof_load_truncated = yesnotoi(argv[1])) == -1) {\n                err = \"argument must be 'yes' or 'no'\"; goto loaderr;\n            }\n        } else if (!strcasecmp(argv[0],\"requirepass\") && argc == 2) {\n            if (strlen(argv[1]) > REDIS_AUTHPASS_MAX_LEN) {\n                err = \"Password is longer than REDIS_AUTHPASS_MAX_LEN\";\n                goto loaderr;\n            }\n            server.requirepass = zstrdup(argv[1]);\n        } else if (!strcasecmp(argv[0],\"pidfile\") && argc == 2) {\n            zfree(server.pidfile);\n            server.pidfile = zstrdup(argv[1]);\n        } else if (!strcasecmp(argv[0],\"dbfilename\") && argc == 2) {\n            if (!pathIsBaseName(argv[1])) {\n                err = \"dbfilename can't be a path, just a filename\";\n                goto loaderr;\n            }\n            zfree(server.rdb_filename);\n            server.rdb_filename = zstrdup(argv[1]);\n        } else if (!strcasecmp(argv[0],\"hash-max-ziplist-entries\") && argc == 2) {\n            server.hash_max_ziplist_entries = memtoll(argv[1], NULL);\n        } else if (!strcasecmp(argv[0],\"hash-max-ziplist-value\") && argc == 2) {\n            server.hash_max_ziplist_value = memtoll(argv[1], NULL);\n        } else if (!strcasecmp(argv[0],\"list-max-ziplist-entries\") && argc == 2){\n            server.list_max_ziplist_entries = memtoll(argv[1], NULL);\n        } else if (!strcasecmp(argv[0],\"list-max-ziplist-value\") && argc == 2) {\n            server.list_max_ziplist_value = memtoll(argv[1], NULL);\n        } else if (!strcasecmp(argv[0],\"set-max-intset-entries\") && argc == 2) {\n            server.set_max_intset_entries = memtoll(argv[1], NULL);\n        } else if (!strcasecmp(argv[0],\"zset-max-ziplist-entries\") && argc == 2) {\n            server.zset_max_ziplist_entries = memtoll(argv[1], NULL);\n        } else if (!strcasecmp(argv[0],\"zset-max-ziplist-value\") && argc == 2) {\n            server.zset_max_ziplist_value = memtoll(argv[1], NULL);\n        } else if (!strcasecmp(argv[0],\"hll-sparse-max-bytes\") && argc == 2) {\n            server.hll_sparse_max_bytes = memtoll(argv[1], NULL);\n        } else if (!strcasecmp(argv[0],\"rename-command\") && argc == 3) {\n            struct redisCommand *cmd = lookupCommand(argv[1]);\n            int retval;\n\n            if (!cmd) {\n                err = \"No such command in rename-command\";\n                goto loaderr;\n            }\n\n            /* If the target command name is the empty string we just\n             * remove it from the command table. */\n            retval = dictDelete(server.commands, argv[1]);\n            redisAssert(retval == DICT_OK);\n\n            /* Otherwise we re-add the command under a different name. */\n            if (sdslen(argv[2]) != 0) {\n                sds copy = sdsdup(argv[2]);\n\n                retval = dictAdd(server.commands, copy, cmd);\n                if (retval != DICT_OK) {\n                    sdsfree(copy);\n                    err = \"Target command name already exists\"; goto loaderr;\n                }\n            }\n        } else if (!strcasecmp(argv[0],\"lua-time-limit\") && argc == 2) {\n            server.lua_time_limit = strtoll(argv[1],NULL,10);\n        } else if (!strcasecmp(argv[0],\"slowlog-log-slower-than\") &&\n                   argc == 2)\n        {\n            server.slowlog_log_slower_than = strtoll(argv[1],NULL,10);\n        } else if (!strcasecmp(argv[0],\"latency-monitor-threshold\") &&\n                   argc == 2)\n        {\n            server.latency_monitor_threshold = strtoll(argv[1],NULL,10);\n            if (server.latency_monitor_threshold < 0) {\n                err = \"The latency threshold can't be negative\";\n                goto loaderr;\n            }\n        } else if (!strcasecmp(argv[0],\"slowlog-max-len\") && argc == 2) {\n            server.slowlog_max_len = strtoll(argv[1],NULL,10);\n        } else if (!strcasecmp(argv[0],\"client-output-buffer-limit\") &&\n                   argc == 5)\n        {\n            int class = getClientTypeByName(argv[1]);\n            unsigned long long hard, soft;\n            int soft_seconds;\n\n            if (class == -1) {\n                err = \"Unrecognized client limit class\";\n                goto loaderr;\n            }\n            hard = memtoll(argv[2],NULL);\n            soft = memtoll(argv[3],NULL);\n            soft_seconds = atoi(argv[4]);\n            if (soft_seconds < 0) {\n                err = \"Negative number of seconds in soft limit is invalid\";\n                goto loaderr;\n            }\n            server.client_obuf_limits[class].hard_limit_bytes = hard;\n            server.client_obuf_limits[class].soft_limit_bytes = soft;\n            server.client_obuf_limits[class].soft_limit_seconds = soft_seconds;\n        } else if (!strcasecmp(argv[0],\"stop-writes-on-bgsave-error\") &&\n                   argc == 2) {\n            if ((server.stop_writes_on_bgsave_err = yesnotoi(argv[1])) == -1) {\n                err = \"argument must be 'yes' or 'no'\"; goto loaderr;\n            }\n        } else if (!strcasecmp(argv[0],\"slave-priority\") && argc == 2) {\n            server.slave_priority = atoi(argv[1]);\n        } else if (!strcasecmp(argv[0],\"min-slaves-to-write\") && argc == 2) {\n            server.repl_min_slaves_to_write = atoi(argv[1]);\n            if (server.repl_min_slaves_to_write < 0) {\n                err = \"Invalid value for min-slaves-to-write.\"; goto loaderr;\n            }\n        } else if (!strcasecmp(argv[0],\"min-slaves-max-lag\") && argc == 2) {\n            server.repl_min_slaves_max_lag = atoi(argv[1]);\n            if (server.repl_min_slaves_max_lag < 0) {\n                err = \"Invalid value for min-slaves-max-lag.\"; goto loaderr;\n            }\n        } else if (!strcasecmp(argv[0],\"notify-keyspace-events\") && argc == 2) {\n            int flags = keyspaceEventsStringToFlags(argv[1]);\n\n            if (flags == -1) {\n                err = \"Invalid event class character. Use 'g$lshzxeA'.\";\n                goto loaderr;\n            }\n            server.notify_keyspace_events = flags;\n        } else if (!strcasecmp(argv[0],\"sentinel\")) {\n            /* argc == 1 is handled by main() as we need to enter the sentinel\n             * mode ASAP. */\n            if (argc != 1) {\n                if (!server.sentinel_mode) {\n                    err = \"sentinel directive while not in sentinel mode\";\n                    goto loaderr;\n                }\n                err = sentinelHandleConfiguration(argv+1,argc-1);\n                if (err) goto loaderr;\n            }\n        } else {\n            err = \"Bad directive or wrong number of arguments\"; goto loaderr;\n        }\n        sdsfreesplitres(argv,argc);\n    }\n    sdsfreesplitres(lines,totlines);\n    return;\n\nloaderr:\n    fprintf(stderr, \"\\n*** FATAL CONFIG FILE ERROR ***\\n\");\n    fprintf(stderr, \"Reading the configuration file, at line %d\\n\", linenum);\n    fprintf(stderr, \">>> '%s'\\n\", lines[i]);\n    fprintf(stderr, \"%s\\n\", err);\n    exit(1);\n}\n\n/* Load the server configuration from the specified filename.\n * The function appends the additional configuration directives stored\n * in the 'options' string to the config file before loading.\n *\n * Both filename and options can be NULL, in such a case are considered\n * empty. This way loadServerConfig can be used to just load a file or\n * just load a string. */\nvoid loadServerConfig(char *filename, char *options) {\n    sds config = sdsempty();\n    char buf[REDIS_CONFIGLINE_MAX+1];\n\n    /* Load the file content */\n    if (filename) {\n        FILE *fp;\n\n        if (filename[0] == '-' && filename[1] == '\\0') {\n            fp = stdin;\n        } else {\n            if ((fp = fopen(filename,\"r\")) == NULL) {\n                redisLog(REDIS_WARNING,\n                    \"Fatal error, can't open config file '%s'\", filename);\n                exit(1);\n            }\n        }\n        while(fgets(buf,REDIS_CONFIGLINE_MAX+1,fp) != NULL)\n            config = sdscat(config,buf);\n        if (fp != stdin) fclose(fp);\n    }\n    /* Append the additional options */\n    if (options) {\n        config = sdscat(config,\"\\n\");\n        config = sdscat(config,options);\n    }\n    loadServerConfigFromString(config);\n    sdsfree(config);\n}\n\n/*-----------------------------------------------------------------------------\n * CONFIG SET implementation\n *----------------------------------------------------------------------------*/\n\nvoid configSetCommand(redisClient *c) {\n    robj *o;\n    long long ll;\n    redisAssertWithInfo(c,c->argv[2],c->argv[2]->encoding == REDIS_ENCODING_RAW);\n    redisAssertWithInfo(c,c->argv[2],c->argv[3]->encoding == REDIS_ENCODING_RAW);\n    o = c->argv[3];\n\n    if (!strcasecmp(c->argv[2]->ptr,\"dbfilename\")) {\n        if (!pathIsBaseName(o->ptr)) {\n            addReplyError(c, \"dbfilename can't be a path, just a filename\");\n            return;\n        }\n        zfree(server.rdb_filename);\n        server.rdb_filename = zstrdup(o->ptr);\n    } else if (!strcasecmp(c->argv[2]->ptr,\"requirepass\")) {\n        if (sdslen(o->ptr) > REDIS_AUTHPASS_MAX_LEN) goto badfmt;\n        zfree(server.requirepass);\n        server.requirepass = ((char*)o->ptr)[0] ? zstrdup(o->ptr) : NULL;\n    } else if (!strcasecmp(c->argv[2]->ptr,\"masterauth\")) {\n        zfree(server.masterauth);\n        server.masterauth = ((char*)o->ptr)[0] ? zstrdup(o->ptr) : NULL;\n    } else if (!strcasecmp(c->argv[2]->ptr,\"maxmemory\")) {\n        if (getLongLongFromObject(o,&ll) == REDIS_ERR ||\n            ll < 0) goto badfmt;\n        server.maxmemory = ll;\n        if (server.maxmemory) {\n            if (server.maxmemory < zmalloc_used_memory()) {\n                redisLog(REDIS_WARNING,\"WARNING: the new maxmemory value set via CONFIG SET is smaller than the current memory usage. This will result in keys eviction and/or inability to accept new write commands depending on the maxmemory-policy.\");\n            }\n            freeMemoryIfNeeded();\n        }\n    } else if (!strcasecmp(c->argv[2]->ptr,\"maxclients\")) {\n        int orig_value = server.maxclients;\n\n        if (getLongLongFromObject(o,&ll) == REDIS_ERR || ll < 1) goto badfmt;\n\n        /* Try to check if the OS is capable of supporting so many FDs. */\n        server.maxclients = ll;\n        if (ll > orig_value) {\n            adjustOpenFilesLimit();\n            if (server.maxclients != ll) {\n                addReplyErrorFormat(c,\"The operating system is not able to handle the specified number of clients, try with %d\", server.maxclients);\n                server.maxclients = orig_value;\n                return;\n            }\n            if ((unsigned int) aeGetSetSize(server.el) <\n                server.maxclients + REDIS_EVENTLOOP_FDSET_INCR)\n            {\n                if (aeResizeSetSize(server.el,\n                    server.maxclients + REDIS_EVENTLOOP_FDSET_INCR) == AE_ERR)\n                {\n                    addReplyError(c,\"The event loop API used by Redis is not able to handle the specified number of clients\");\n                    server.maxclients = orig_value;\n                    return;\n                }\n            }\n        }\n    } else if (!strcasecmp(c->argv[2]->ptr,\"hz\")) {\n        if (getLongLongFromObject(o,&ll) == REDIS_ERR || ll < 0) goto badfmt;\n        server.hz = ll;\n        if (server.hz < REDIS_MIN_HZ) server.hz = REDIS_MIN_HZ;\n        if (server.hz > REDIS_MAX_HZ) server.hz = REDIS_MAX_HZ;\n    } else if (!strcasecmp(c->argv[2]->ptr,\"maxmemory-policy\")) {\n        if (!strcasecmp(o->ptr,\"volatile-lru\")) {\n            server.maxmemory_policy = REDIS_MAXMEMORY_VOLATILE_LRU;\n        } else if (!strcasecmp(o->ptr,\"volatile-random\")) {\n            server.maxmemory_policy = REDIS_MAXMEMORY_VOLATILE_RANDOM;\n        } else if (!strcasecmp(o->ptr,\"volatile-ttl\")) {\n            server.maxmemory_policy = REDIS_MAXMEMORY_VOLATILE_TTL;\n        } else if (!strcasecmp(o->ptr,\"allkeys-lru\")) {\n            server.maxmemory_policy = REDIS_MAXMEMORY_ALLKEYS_LRU;\n        } else if (!strcasecmp(o->ptr,\"allkeys-random\")) {\n            server.maxmemory_policy = REDIS_MAXMEMORY_ALLKEYS_RANDOM;\n        } else if (!strcasecmp(o->ptr,\"noeviction\")) {\n            server.maxmemory_policy = REDIS_MAXMEMORY_NO_EVICTION;\n        } else {\n            goto badfmt;\n        }\n    } else if (!strcasecmp(c->argv[2]->ptr,\"maxmemory-samples\")) {\n        if (getLongLongFromObject(o,&ll) == REDIS_ERR ||\n            ll <= 0) goto badfmt;\n        server.maxmemory_samples = ll;\n    } else if (!strcasecmp(c->argv[2]->ptr,\"timeout\")) {\n        if (getLongLongFromObject(o,&ll) == REDIS_ERR ||\n            ll < 0 || ll > LONG_MAX) goto badfmt;\n        server.maxidletime = ll;\n    } else if (!strcasecmp(c->argv[2]->ptr,\"tcp-keepalive\")) {\n        if (getLongLongFromObject(o,&ll) == REDIS_ERR ||\n            ll < 0 || ll > INT_MAX) goto badfmt;\n        server.tcpkeepalive = ll;\n    } else if (!strcasecmp(c->argv[2]->ptr,\"appendfsync\")) {\n        if (!strcasecmp(o->ptr,\"no\")) {\n            server.aof_fsync = AOF_FSYNC_NO;\n        } else if (!strcasecmp(o->ptr,\"everysec\")) {\n            server.aof_fsync = AOF_FSYNC_EVERYSEC;\n        } else if (!strcasecmp(o->ptr,\"always\")) {\n            server.aof_fsync = AOF_FSYNC_ALWAYS;\n        } else {\n            goto badfmt;\n        }\n    } else if (!strcasecmp(c->argv[2]->ptr,\"no-appendfsync-on-rewrite\")) {\n        int yn = yesnotoi(o->ptr);\n\n        if (yn == -1) goto badfmt;\n        server.aof_no_fsync_on_rewrite = yn;\n    } else if (!strcasecmp(c->argv[2]->ptr,\"appendonly\")) {\n        int enable = yesnotoi(o->ptr);\n\n        if (enable == -1) goto badfmt;\n        if (enable == 0 && server.aof_state != REDIS_AOF_OFF) {\n            stopAppendOnly();\n        } else if (enable && server.aof_state == REDIS_AOF_OFF) {\n            if (startAppendOnly() == REDIS_ERR) {\n                addReplyError(c,\n                    \"Unable to turn on AOF. Check server logs.\");\n                return;\n            }\n        }\n    } else if (!strcasecmp(c->argv[2]->ptr,\"auto-aof-rewrite-percentage\")) {\n        if (getLongLongFromObject(o,&ll) == REDIS_ERR || ll < 0) goto badfmt;\n        server.aof_rewrite_perc = ll;\n    } else if (!strcasecmp(c->argv[2]->ptr,\"auto-aof-rewrite-min-size\")) {\n        if (getLongLongFromObject(o,&ll) == REDIS_ERR || ll < 0) goto badfmt;\n        server.aof_rewrite_min_size = ll;\n    } else if (!strcasecmp(c->argv[2]->ptr,\"aof-rewrite-incremental-fsync\")) {\n        int yn = yesnotoi(o->ptr);\n\n        if (yn == -1) goto badfmt;\n        server.aof_rewrite_incremental_fsync = yn;\n    } else if (!strcasecmp(c->argv[2]->ptr,\"aof-load-truncated\")) {\n        int yn = yesnotoi(o->ptr);\n\n        if (yn == -1) goto badfmt;\n        server.aof_load_truncated = yn;\n    } else if (!strcasecmp(c->argv[2]->ptr,\"save\")) {\n        int vlen, j;\n        sds *v = sdssplitlen(o->ptr,sdslen(o->ptr),\" \",1,&vlen);\n\n        /* Perform sanity check before setting the new config:\n         * - Even number of args\n         * - Seconds >= 1, changes >= 0 */\n        if (vlen & 1) {\n            sdsfreesplitres(v,vlen);\n            goto badfmt;\n        }\n        for (j = 0; j < vlen; j++) {\n            char *eptr;\n            long val;\n\n            val = strtoll(v[j], &eptr, 10);\n            if (eptr[0] != '\\0' ||\n                ((j & 1) == 0 && val < 1) ||\n                ((j & 1) == 1 && val < 0)) {\n                sdsfreesplitres(v,vlen);\n                goto badfmt;\n            }\n        }\n        /* Finally set the new config */\n        resetServerSaveParams();\n        for (j = 0; j < vlen; j += 2) {\n            time_t seconds;\n            int changes;\n\n            seconds = strtoll(v[j],NULL,10);\n            changes = strtoll(v[j+1],NULL,10);\n            appendServerSaveParams(seconds, changes);\n        }\n        sdsfreesplitres(v,vlen);\n    } else if (!strcasecmp(c->argv[2]->ptr,\"slave-serve-stale-data\")) {\n        int yn = yesnotoi(o->ptr);\n\n        if (yn == -1) goto badfmt;\n        server.repl_serve_stale_data = yn;\n    } else if (!strcasecmp(c->argv[2]->ptr,\"slave-read-only\")) {\n        int yn = yesnotoi(o->ptr);\n\n        if (yn == -1) goto badfmt;\n        server.repl_slave_ro = yn;\n    } else if (!strcasecmp(c->argv[2]->ptr,\"activerehashing\")) {\n        int yn = yesnotoi(o->ptr);\n\n        if (yn == -1) goto badfmt;\n        server.activerehashing = yn;\n    } else if (!strcasecmp(c->argv[2]->ptr,\"dir\")) {\n        if (chdir((char*)o->ptr) == -1) {\n            addReplyErrorFormat(c,\"Changing directory: %s\", strerror(errno));\n            return;\n        }\n    } else if (!strcasecmp(c->argv[2]->ptr,\"hash-max-ziplist-entries\")) {\n        if (getLongLongFromObject(o,&ll) == REDIS_ERR || ll < 0) goto badfmt;\n        server.hash_max_ziplist_entries = ll;\n    } else if (!strcasecmp(c->argv[2]->ptr,\"hash-max-ziplist-value\")) {\n        if (getLongLongFromObject(o,&ll) == REDIS_ERR || ll < 0) goto badfmt;\n        server.hash_max_ziplist_value = ll;\n    } else if (!strcasecmp(c->argv[2]->ptr,\"list-max-ziplist-entries\")) {\n        if (getLongLongFromObject(o,&ll) == REDIS_ERR || ll < 0) goto badfmt;\n        server.list_max_ziplist_entries = ll;\n    } else if (!strcasecmp(c->argv[2]->ptr,\"list-max-ziplist-value\")) {\n        if (getLongLongFromObject(o,&ll) == REDIS_ERR || ll < 0) goto badfmt;\n        server.list_max_ziplist_value = ll;\n    } else if (!strcasecmp(c->argv[2]->ptr,\"set-max-intset-entries\")) {\n        if (getLongLongFromObject(o,&ll) == REDIS_ERR || ll < 0) goto badfmt;\n        server.set_max_intset_entries = ll;\n    } else if (!strcasecmp(c->argv[2]->ptr,\"zset-max-ziplist-entries\")) {\n        if (getLongLongFromObject(o,&ll) == REDIS_ERR || ll < 0) goto badfmt;\n        server.zset_max_ziplist_entries = ll;\n    } else if (!strcasecmp(c->argv[2]->ptr,\"zset-max-ziplist-value\")) {\n        if (getLongLongFromObject(o,&ll) == REDIS_ERR || ll < 0) goto badfmt;\n        server.zset_max_ziplist_value = ll;\n    } else if (!strcasecmp(c->argv[2]->ptr,\"hll-sparse-max-bytes\")) {\n        if (getLongLongFromObject(o,&ll) == REDIS_ERR || ll < 0) goto badfmt;\n        server.hll_sparse_max_bytes = ll;\n    } else if (!strcasecmp(c->argv[2]->ptr,\"lua-time-limit\")) {\n        if (getLongLongFromObject(o,&ll) == REDIS_ERR || ll < 0) goto badfmt;\n        server.lua_time_limit = ll;\n    } else if (!strcasecmp(c->argv[2]->ptr,\"slowlog-log-slower-than\")) {\n        if (getLongLongFromObject(o,&ll) == REDIS_ERR) goto badfmt;\n        server.slowlog_log_slower_than = ll;\n    } else if (!strcasecmp(c->argv[2]->ptr,\"slowlog-max-len\")) {\n        if (getLongLongFromObject(o,&ll) == REDIS_ERR || ll < 0) goto badfmt;\n        server.slowlog_max_len = (unsigned)ll;\n    } else if (!strcasecmp(c->argv[2]->ptr,\"latency-monitor-threshold\")) {\n        if (getLongLongFromObject(o,&ll) == REDIS_ERR || ll < 0) goto badfmt;\n        server.latency_monitor_threshold = ll;\n    } else if (!strcasecmp(c->argv[2]->ptr,\"loglevel\")) {\n        if (!strcasecmp(o->ptr,\"warning\")) {\n            server.verbosity = REDIS_WARNING;\n        } else if (!strcasecmp(o->ptr,\"notice\")) {\n            server.verbosity = REDIS_NOTICE;\n        } else if (!strcasecmp(o->ptr,\"verbose\")) {\n            server.verbosity = REDIS_VERBOSE;\n        } else if (!strcasecmp(o->ptr,\"debug\")) {\n            server.verbosity = REDIS_DEBUG;\n        } else {\n            goto badfmt;\n        }\n    } else if (!strcasecmp(c->argv[2]->ptr,\"client-output-buffer-limit\")) {\n        int vlen, j;\n        sds *v = sdssplitlen(o->ptr,sdslen(o->ptr),\" \",1,&vlen);\n\n        /* We need a multiple of 4: <class> <hard> <soft> <soft_seconds> */\n        if (vlen % 4) {\n            sdsfreesplitres(v,vlen);\n            goto badfmt;\n        }\n\n        /* Sanity check of single arguments, so that we either refuse the\n         * whole configuration string or accept it all, even if a single\n         * error in a single client class is present. */\n        for (j = 0; j < vlen; j++) {\n            char *eptr;\n            long val;\n\n            if ((j % 4) == 0) {\n                if (getClientTypeByName(v[j]) == -1) {\n                    sdsfreesplitres(v,vlen);\n                    goto badfmt;\n                }\n            } else {\n                val = strtoll(v[j], &eptr, 10);\n                if (eptr[0] != '\\0' || val < 0) {\n                    sdsfreesplitres(v,vlen);\n                    goto badfmt;\n                }\n            }\n        }\n        /* Finally set the new config */\n        for (j = 0; j < vlen; j += 4) {\n            int class;\n            unsigned long long hard, soft;\n            int soft_seconds;\n\n            class = getClientTypeByName(v[j]);\n            hard = strtoll(v[j+1],NULL,10);\n            soft = strtoll(v[j+2],NULL,10);\n            soft_seconds = strtoll(v[j+3],NULL,10);\n\n            server.client_obuf_limits[class].hard_limit_bytes = hard;\n            server.client_obuf_limits[class].soft_limit_bytes = soft;\n            server.client_obuf_limits[class].soft_limit_seconds = soft_seconds;\n        }\n        sdsfreesplitres(v,vlen);\n    } else if (!strcasecmp(c->argv[2]->ptr,\"stop-writes-on-bgsave-error\")) {\n        int yn = yesnotoi(o->ptr);\n\n        if (yn == -1) goto badfmt;\n        server.stop_writes_on_bgsave_err = yn;\n    } else if (!strcasecmp(c->argv[2]->ptr,\"repl-ping-slave-period\")) {\n        if (getLongLongFromObject(o,&ll) == REDIS_ERR || ll <= 0) goto badfmt;\n        server.repl_ping_slave_period = ll;\n    } else if (!strcasecmp(c->argv[2]->ptr,\"repl-timeout\")) {\n        if (getLongLongFromObject(o,&ll) == REDIS_ERR || ll <= 0) goto badfmt;\n        server.repl_timeout = ll;\n    } else if (!strcasecmp(c->argv[2]->ptr,\"repl-backlog-size\")) {\n        if (getLongLongFromObject(o,&ll) == REDIS_ERR || ll <= 0) goto badfmt;\n        resizeReplicationBacklog(ll);\n    } else if (!strcasecmp(c->argv[2]->ptr,\"repl-backlog-ttl\")) {\n        if (getLongLongFromObject(o,&ll) == REDIS_ERR || ll < 0) goto badfmt;\n        server.repl_backlog_time_limit = ll;\n    } else if (!strcasecmp(c->argv[2]->ptr,\"watchdog-period\")) {\n        if (getLongLongFromObject(o,&ll) == REDIS_ERR || ll < 0) goto badfmt;\n        if (ll)\n            enableWatchdog(ll);\n        else\n            disableWatchdog();\n    } else if (!strcasecmp(c->argv[2]->ptr,\"rdbcompression\")) {\n        int yn = yesnotoi(o->ptr);\n\n        if (yn == -1) goto badfmt;\n        server.rdb_compression = yn;\n    } else if (!strcasecmp(c->argv[2]->ptr,\"notify-keyspace-events\")) {\n        int flags = keyspaceEventsStringToFlags(o->ptr);\n\n        if (flags == -1) goto badfmt;\n        server.notify_keyspace_events = flags;\n    } else if (!strcasecmp(c->argv[2]->ptr,\"repl-disable-tcp-nodelay\")) {\n        int yn = yesnotoi(o->ptr);\n\n        if (yn == -1) goto badfmt;\n        server.repl_disable_tcp_nodelay = yn;\n    } else if (!strcasecmp(c->argv[2]->ptr,\"repl-diskless-sync\")) {\n        int yn = yesnotoi(o->ptr);\n\n        if (yn == -1) goto badfmt;\n        server.repl_diskless_sync = yn;\n    } else if (!strcasecmp(c->argv[2]->ptr,\"repl-diskless-sync-delay\")) {\n        if (getLongLongFromObject(o,&ll) == REDIS_ERR ||\n            ll < 0) goto badfmt;\n        server.repl_diskless_sync_delay = ll;\n    } else if (!strcasecmp(c->argv[2]->ptr,\"slave-priority\")) {\n        if (getLongLongFromObject(o,&ll) == REDIS_ERR ||\n            ll < 0) goto badfmt;\n        server.slave_priority = ll;\n    } else if (!strcasecmp(c->argv[2]->ptr,\"min-slaves-to-write\")) {\n        if (getLongLongFromObject(o,&ll) == REDIS_ERR ||\n            ll < 0) goto badfmt;\n        server.repl_min_slaves_to_write = ll;\n        refreshGoodSlavesCount();\n    } else if (!strcasecmp(c->argv[2]->ptr,\"min-slaves-max-lag\")) {\n        if (getLongLongFromObject(o,&ll) == REDIS_ERR ||\n            ll < 0) goto badfmt;\n        server.repl_min_slaves_max_lag = ll;\n        refreshGoodSlavesCount();\n    } else {\n        addReplyErrorFormat(c,\"Unsupported CONFIG parameter: %s\",\n            (char*)c->argv[2]->ptr);\n        return;\n    }\n    addReply(c,shared.ok);\n    return;\n\nbadfmt: /* Bad format errors */\n    addReplyErrorFormat(c,\"Invalid argument '%s' for CONFIG SET '%s'\",\n            (char*)o->ptr,\n            (char*)c->argv[2]->ptr);\n}\n\n/*-----------------------------------------------------------------------------\n * CONFIG GET implementation\n *----------------------------------------------------------------------------*/\n\n#define config_get_string_field(_name,_var) do { \\\n    if (stringmatch(pattern,_name,0)) { \\\n        addReplyBulkCString(c,_name); \\\n        addReplyBulkCString(c,_var ? _var : \"\"); \\\n        matches++; \\\n    } \\\n} while(0);\n\n#define config_get_bool_field(_name,_var) do { \\\n    if (stringmatch(pattern,_name,0)) { \\\n        addReplyBulkCString(c,_name); \\\n        addReplyBulkCString(c,_var ? \"yes\" : \"no\"); \\\n        matches++; \\\n    } \\\n} while(0);\n\n#define config_get_numerical_field(_name,_var) do { \\\n    if (stringmatch(pattern,_name,0)) { \\\n        ll2string(buf,sizeof(buf),_var); \\\n        addReplyBulkCString(c,_name); \\\n        addReplyBulkCString(c,buf); \\\n        matches++; \\\n    } \\\n} while(0);\n\nvoid configGetCommand(redisClient *c) {\n    robj *o = c->argv[2];\n    void *replylen = addDeferredMultiBulkLength(c);\n    char *pattern = o->ptr;\n    char buf[128];\n    int matches = 0;\n    redisAssertWithInfo(c,o,o->encoding == REDIS_ENCODING_RAW);\n\n    /* String values */\n    config_get_string_field(\"dbfilename\",server.rdb_filename);\n    config_get_string_field(\"requirepass\",server.requirepass);\n    config_get_string_field(\"masterauth\",server.masterauth);\n    config_get_string_field(\"unixsocket\",server.unixsocket);\n    config_get_string_field(\"logfile\",server.logfile);\n    config_get_string_field(\"pidfile\",server.pidfile);\n\n    /* Numerical values */\n    config_get_numerical_field(\"maxmemory\",server.maxmemory);\n    config_get_numerical_field(\"maxmemory-samples\",server.maxmemory_samples);\n    config_get_numerical_field(\"timeout\",server.maxidletime);\n    config_get_numerical_field(\"tcp-keepalive\",server.tcpkeepalive);\n    config_get_numerical_field(\"auto-aof-rewrite-percentage\",\n            server.aof_rewrite_perc);\n    config_get_numerical_field(\"auto-aof-rewrite-min-size\",\n            server.aof_rewrite_min_size);\n    config_get_numerical_field(\"hash-max-ziplist-entries\",\n            server.hash_max_ziplist_entries);\n    config_get_numerical_field(\"hash-max-ziplist-value\",\n            server.hash_max_ziplist_value);\n    config_get_numerical_field(\"list-max-ziplist-entries\",\n            server.list_max_ziplist_entries);\n    config_get_numerical_field(\"list-max-ziplist-value\",\n            server.list_max_ziplist_value);\n    config_get_numerical_field(\"set-max-intset-entries\",\n            server.set_max_intset_entries);\n    config_get_numerical_field(\"zset-max-ziplist-entries\",\n            server.zset_max_ziplist_entries);\n    config_get_numerical_field(\"zset-max-ziplist-value\",\n            server.zset_max_ziplist_value);\n    config_get_numerical_field(\"hll-sparse-max-bytes\",\n            server.hll_sparse_max_bytes);\n    config_get_numerical_field(\"lua-time-limit\",server.lua_time_limit);\n    config_get_numerical_field(\"slowlog-log-slower-than\",\n            server.slowlog_log_slower_than);\n    config_get_numerical_field(\"latency-monitor-threshold\",\n            server.latency_monitor_threshold);\n    config_get_numerical_field(\"slowlog-max-len\",\n            server.slowlog_max_len);\n    config_get_numerical_field(\"port\",server.port);\n    config_get_numerical_field(\"tcp-backlog\",server.tcp_backlog);\n    config_get_numerical_field(\"databases\",server.dbnum);\n    config_get_numerical_field(\"repl-ping-slave-period\",server.repl_ping_slave_period);\n    config_get_numerical_field(\"repl-timeout\",server.repl_timeout);\n    config_get_numerical_field(\"repl-backlog-size\",server.repl_backlog_size);\n    config_get_numerical_field(\"repl-backlog-ttl\",server.repl_backlog_time_limit);\n    config_get_numerical_field(\"maxclients\",server.maxclients);\n    config_get_numerical_field(\"watchdog-period\",server.watchdog_period);\n    config_get_numerical_field(\"slave-priority\",server.slave_priority);\n    config_get_numerical_field(\"min-slaves-to-write\",server.repl_min_slaves_to_write);\n    config_get_numerical_field(\"min-slaves-max-lag\",server.repl_min_slaves_max_lag);\n    config_get_numerical_field(\"hz\",server.hz);\n    config_get_numerical_field(\"repl-diskless-sync-delay\",server.repl_diskless_sync_delay);\n\n    /* Bool (yes/no) values */\n    config_get_bool_field(\"no-appendfsync-on-rewrite\",\n            server.aof_no_fsync_on_rewrite);\n    config_get_bool_field(\"slave-serve-stale-data\",\n            server.repl_serve_stale_data);\n    config_get_bool_field(\"slave-read-only\",\n            server.repl_slave_ro);\n    config_get_bool_field(\"stop-writes-on-bgsave-error\",\n            server.stop_writes_on_bgsave_err);\n    config_get_bool_field(\"daemonize\", server.daemonize);\n    config_get_bool_field(\"rdbcompression\", server.rdb_compression);\n    config_get_bool_field(\"rdbchecksum\", server.rdb_checksum);\n    config_get_bool_field(\"activerehashing\", server.activerehashing);\n    config_get_bool_field(\"repl-disable-tcp-nodelay\",\n            server.repl_disable_tcp_nodelay);\n    config_get_bool_field(\"repl-diskless-sync\",\n            server.repl_diskless_sync);\n    config_get_bool_field(\"aof-rewrite-incremental-fsync\",\n            server.aof_rewrite_incremental_fsync);\n    config_get_bool_field(\"aof-load-truncated\",\n            server.aof_load_truncated);\n\n    /* Everything we can't handle with macros follows. */\n\n    if (stringmatch(pattern,\"appendonly\",0)) {\n        addReplyBulkCString(c,\"appendonly\");\n        addReplyBulkCString(c,server.aof_state == REDIS_AOF_OFF ? \"no\" : \"yes\");\n        matches++;\n    }\n    if (stringmatch(pattern,\"dir\",0)) {\n        char buf[1024];\n\n        if (getcwd(buf,sizeof(buf)) == NULL)\n            buf[0] = '\\0';\n\n        addReplyBulkCString(c,\"dir\");\n        addReplyBulkCString(c,buf);\n        matches++;\n    }\n    if (stringmatch(pattern,\"maxmemory-policy\",0)) {\n        char *s;\n\n        switch(server.maxmemory_policy) {\n        case REDIS_MAXMEMORY_VOLATILE_LRU: s = \"volatile-lru\"; break;\n        case REDIS_MAXMEMORY_VOLATILE_TTL: s = \"volatile-ttl\"; break;\n        case REDIS_MAXMEMORY_VOLATILE_RANDOM: s = \"volatile-random\"; break;\n        case REDIS_MAXMEMORY_ALLKEYS_LRU: s = \"allkeys-lru\"; break;\n        case REDIS_MAXMEMORY_ALLKEYS_RANDOM: s = \"allkeys-random\"; break;\n        case REDIS_MAXMEMORY_NO_EVICTION: s = \"noeviction\"; break;\n        default: s = \"unknown\"; break; /* too harmless to panic */\n        }\n        addReplyBulkCString(c,\"maxmemory-policy\");\n        addReplyBulkCString(c,s);\n        matches++;\n    }\n    if (stringmatch(pattern,\"appendfsync\",0)) {\n        char *policy;\n\n        switch(server.aof_fsync) {\n        case AOF_FSYNC_NO: policy = \"no\"; break;\n        case AOF_FSYNC_EVERYSEC: policy = \"everysec\"; break;\n        case AOF_FSYNC_ALWAYS: policy = \"always\"; break;\n        default: policy = \"unknown\"; break; /* too harmless to panic */\n        }\n        addReplyBulkCString(c,\"appendfsync\");\n        addReplyBulkCString(c,policy);\n        matches++;\n    }\n    if (stringmatch(pattern,\"save\",0)) {\n        sds buf = sdsempty();\n        int j;\n\n        for (j = 0; j < server.saveparamslen; j++) {\n            buf = sdscatprintf(buf,\"%jd %d\",\n                    (intmax_t)server.saveparams[j].seconds,\n                    server.saveparams[j].changes);\n            if (j != server.saveparamslen-1)\n                buf = sdscatlen(buf,\" \",1);\n        }\n        addReplyBulkCString(c,\"save\");\n        addReplyBulkCString(c,buf);\n        sdsfree(buf);\n        matches++;\n    }\n    if (stringmatch(pattern,\"loglevel\",0)) {\n        char *s;\n\n        switch(server.verbosity) {\n        case REDIS_WARNING: s = \"warning\"; break;\n        case REDIS_VERBOSE: s = \"verbose\"; break;\n        case REDIS_NOTICE: s = \"notice\"; break;\n        case REDIS_DEBUG: s = \"debug\"; break;\n        default: s = \"unknown\"; break; /* too harmless to panic */\n        }\n        addReplyBulkCString(c,\"loglevel\");\n        addReplyBulkCString(c,s);\n        matches++;\n    }\n    if (stringmatch(pattern,\"client-output-buffer-limit\",0)) {\n        sds buf = sdsempty();\n        int j;\n\n        for (j = 0; j < REDIS_CLIENT_TYPE_COUNT; j++) {\n            buf = sdscatprintf(buf,\"%s %llu %llu %ld\",\n                    getClientTypeName(j),\n                    server.client_obuf_limits[j].hard_limit_bytes,\n                    server.client_obuf_limits[j].soft_limit_bytes,\n                    (long) server.client_obuf_limits[j].soft_limit_seconds);\n            if (j != REDIS_CLIENT_TYPE_COUNT-1)\n                buf = sdscatlen(buf,\" \",1);\n        }\n        addReplyBulkCString(c,\"client-output-buffer-limit\");\n        addReplyBulkCString(c,buf);\n        sdsfree(buf);\n        matches++;\n    }\n    if (stringmatch(pattern,\"unixsocketperm\",0)) {\n        char buf[32];\n        snprintf(buf,sizeof(buf),\"%o\",server.unixsocketperm);\n        addReplyBulkCString(c,\"unixsocketperm\");\n        addReplyBulkCString(c,buf);\n        matches++;\n    }\n    if (stringmatch(pattern,\"slaveof\",0)) {\n        char buf[256];\n\n        addReplyBulkCString(c,\"slaveof\");\n        if (server.masterhost)\n            snprintf(buf,sizeof(buf),\"%s %d\",\n                server.masterhost, server.masterport);\n        else\n            buf[0] = '\\0';\n        addReplyBulkCString(c,buf);\n        matches++;\n    }\n    if (stringmatch(pattern,\"notify-keyspace-events\",0)) {\n        robj *flagsobj = createObject(REDIS_STRING,\n            keyspaceEventsFlagsToString(server.notify_keyspace_events));\n\n        addReplyBulkCString(c,\"notify-keyspace-events\");\n        addReplyBulk(c,flagsobj);\n        decrRefCount(flagsobj);\n        matches++;\n    }\n    if (stringmatch(pattern,\"bind\",0)) {\n        sds aux = sdsjoin(server.bindaddr,server.bindaddr_count,\" \");\n\n        addReplyBulkCString(c,\"bind\");\n        addReplyBulkCString(c,aux);\n        sdsfree(aux);\n        matches++;\n    }\n    setDeferredMultiBulkLength(c,replylen,matches*2);\n}\n\n/*-----------------------------------------------------------------------------\n * CONFIG REWRITE implementation\n *----------------------------------------------------------------------------*/\n\n#define REDIS_CONFIG_REWRITE_SIGNATURE \"# Generated by CONFIG REWRITE\"\n\n/* We use the following dictionary type to store where a configuration\n * option is mentioned in the old configuration file, so it's\n * like \"maxmemory\" -> list of line numbers (first line is zero). */\nunsigned int dictSdsCaseHash(const void *key);\nint dictSdsKeyCaseCompare(void *privdata, const void *key1, const void *key2);\nvoid dictSdsDestructor(void *privdata, void *val);\nvoid dictListDestructor(void *privdata, void *val);\n\n/* Sentinel config rewriting is implemented inside sentinel.c by\n * rewriteConfigSentinelOption(). */\nvoid rewriteConfigSentinelOption(struct rewriteConfigState *state);\n\ndictType optionToLineDictType = {\n    dictSdsCaseHash,            /* hash function */\n    NULL,                       /* key dup */\n    NULL,                       /* val dup */\n    dictSdsKeyCaseCompare,      /* key compare */\n    dictSdsDestructor,          /* key destructor */\n    dictListDestructor          /* val destructor */\n};\n\ndictType optionSetDictType = {\n    dictSdsCaseHash,            /* hash function */\n    NULL,                       /* key dup */\n    NULL,                       /* val dup */\n    dictSdsKeyCaseCompare,      /* key compare */\n    dictSdsDestructor,          /* key destructor */\n    NULL                        /* val destructor */\n};\n\n/* The config rewrite state. */\nstruct rewriteConfigState {\n    dict *option_to_line; /* Option -> list of config file lines map */\n    dict *rewritten;      /* Dictionary of already processed options */\n    int numlines;         /* Number of lines in current config */\n    sds *lines;           /* Current lines as an array of sds strings */\n    int has_tail;         /* True if we already added directives that were\n                             not present in the original config file. */\n};\n\n/* Append the new line to the current configuration state. */\nvoid rewriteConfigAppendLine(struct rewriteConfigState *state, sds line) {\n    state->lines = zrealloc(state->lines, sizeof(char*) * (state->numlines+1));\n    state->lines[state->numlines++] = line;\n}\n\n/* Populate the option -> list of line numbers map. */\nvoid rewriteConfigAddLineNumberToOption(struct rewriteConfigState *state, sds option, int linenum) {\n    list *l = dictFetchValue(state->option_to_line,option);\n\n    if (l == NULL) {\n        l = listCreate();\n        dictAdd(state->option_to_line,sdsdup(option),l);\n    }\n    listAddNodeTail(l,(void*)(long)linenum);\n}\n\n/* Add the specified option to the set of processed options.\n * This is useful as only unused lines of processed options will be blanked\n * in the config file, while options the rewrite process does not understand\n * remain untouched. */\nvoid rewriteConfigMarkAsProcessed(struct rewriteConfigState *state, char *option) {\n    sds opt = sdsnew(option);\n\n    if (dictAdd(state->rewritten,opt,NULL) != DICT_OK) sdsfree(opt);\n}\n\n/* Read the old file, split it into lines to populate a newly created\n * config rewrite state, and return it to the caller.\n *\n * If it is impossible to read the old file, NULL is returned.\n * If the old file does not exist at all, an empty state is returned. */\nstruct rewriteConfigState *rewriteConfigReadOldFile(char *path) {\n    FILE *fp = fopen(path,\"r\");\n    struct rewriteConfigState *state = zmalloc(sizeof(*state));\n    char buf[REDIS_CONFIGLINE_MAX+1];\n    int linenum = -1;\n\n    if (fp == NULL && errno != ENOENT) return NULL;\n\n    state->option_to_line = dictCreate(&optionToLineDictType,NULL);\n    state->rewritten = dictCreate(&optionSetDictType,NULL);\n    state->numlines = 0;\n    state->lines = NULL;\n    state->has_tail = 0;\n    if (fp == NULL) return state;\n\n    /* Read the old file line by line, populate the state. */\n    while(fgets(buf,REDIS_CONFIGLINE_MAX+1,fp) != NULL) {\n        int argc;\n        sds *argv;\n        sds line = sdstrim(sdsnew(buf),\"\\r\\n\\t \");\n\n        linenum++; /* Zero based, so we init at -1 */\n\n        /* Handle comments and empty lines. */\n        if (line[0] == '#' || line[0] == '\\0') {\n            if (!state->has_tail && !strcmp(line,REDIS_CONFIG_REWRITE_SIGNATURE))\n                state->has_tail = 1;\n            rewriteConfigAppendLine(state,line);\n            continue;\n        }\n\n        /* Not a comment, split into arguments. */\n        argv = sdssplitargs(line,&argc);\n        if (argv == NULL) {\n            /* Apparently the line is unparsable for some reason, for\n             * instance it may have unbalanced quotes. Load it as a\n             * comment. */\n            sds aux = sdsnew(\"# ??? \");\n            aux = sdscatsds(aux,line);\n            sdsfree(line);\n            rewriteConfigAppendLine(state,aux);\n            continue;\n        }\n\n        sdstolower(argv[0]); /* We only want lowercase config directives. */\n\n        /* Now we populate the state according to the content of this line.\n         * Append the line and populate the option -> line numbers map. */\n        rewriteConfigAppendLine(state,line);\n        rewriteConfigAddLineNumberToOption(state,argv[0],linenum);\n\n        sdsfreesplitres(argv,argc);\n    }\n    fclose(fp);\n    return state;\n}\n\n/* Rewrite the specified configuration option with the new \"line\".\n * It progressively uses lines of the file that were already used for the same\n * configuration option in the old version of the file, removing that line from\n * the map of options -> line numbers.\n *\n * If there are lines associated with a given configuration option and\n * \"force\" is non-zero, the line is appended to the configuration file.\n * Usually \"force\" is true when an option has not its default value, so it\n * must be rewritten even if not present previously.\n *\n * The first time a line is appended into a configuration file, a comment\n * is added to show that starting from that point the config file was generated\n * by CONFIG REWRITE.\n *\n * \"line\" is either used, or freed, so the caller does not need to free it\n * in any way. */\nvoid rewriteConfigRewriteLine(struct rewriteConfigState *state, char *option, sds line, int force) {\n    sds o = sdsnew(option);\n    list *l = dictFetchValue(state->option_to_line,o);\n\n    rewriteConfigMarkAsProcessed(state,option);\n\n    if (!l && !force) {\n        /* Option not used previously, and we are not forced to use it. */\n        sdsfree(line);\n        sdsfree(o);\n        return;\n    }\n\n    if (l) {\n        listNode *ln = listFirst(l);\n        int linenum = (long) ln->value;\n\n        /* There are still lines in the old configuration file we can reuse\n         * for this option. Replace the line with the new one. */\n        listDelNode(l,ln);\n        if (listLength(l) == 0) dictDelete(state->option_to_line,o);\n        sdsfree(state->lines[linenum]);\n        state->lines[linenum] = line;\n    } else {\n        /* Append a new line. */\n        if (!state->has_tail) {\n            rewriteConfigAppendLine(state,\n                sdsnew(REDIS_CONFIG_REWRITE_SIGNATURE));\n            state->has_tail = 1;\n        }\n        rewriteConfigAppendLine(state,line);\n    }\n    sdsfree(o);\n}\n\n/* Write the long long 'bytes' value as a string in a way that is parsable\n * inside redis.conf. If possible uses the GB, MB, KB notation. */\nint rewriteConfigFormatMemory(char *buf, size_t len, long long bytes) {\n    int gb = 1024*1024*1024;\n    int mb = 1024*1024;\n    int kb = 1024;\n\n    if (bytes && (bytes % gb) == 0) {\n        return snprintf(buf,len,\"%lldgb\",bytes/gb);\n    } else if (bytes && (bytes % mb) == 0) {\n        return snprintf(buf,len,\"%lldmb\",bytes/mb);\n    } else if (bytes && (bytes % kb) == 0) {\n        return snprintf(buf,len,\"%lldkb\",bytes/kb);\n    } else {\n        return snprintf(buf,len,\"%lld\",bytes);\n    }\n}\n\n/* Rewrite a simple \"option-name <bytes>\" configuration option. */\nvoid rewriteConfigBytesOption(struct rewriteConfigState *state, char *option, long long value, long long defvalue) {\n    char buf[64];\n    int force = value != defvalue;\n    sds line;\n\n    rewriteConfigFormatMemory(buf,sizeof(buf),value);\n    line = sdscatprintf(sdsempty(),\"%s %s\",option,buf);\n    rewriteConfigRewriteLine(state,option,line,force);\n}\n\n/* Rewrite a yes/no option. */\nvoid rewriteConfigYesNoOption(struct rewriteConfigState *state, char *option, int value, int defvalue) {\n    int force = value != defvalue;\n    sds line = sdscatprintf(sdsempty(),\"%s %s\",option,\n        value ? \"yes\" : \"no\");\n\n    rewriteConfigRewriteLine(state,option,line,force);\n}\n\n/* Rewrite a string option. */\nvoid rewriteConfigStringOption(struct rewriteConfigState *state, char *option, char *value, char *defvalue) {\n    int force = 1;\n    sds line;\n\n    /* String options set to NULL need to be not present at all in the\n     * configuration file to be set to NULL again at the next reboot. */\n    if (value == NULL) {\n        rewriteConfigMarkAsProcessed(state,option);\n        return;\n    }\n\n    /* Set force to zero if the value is set to its default. */\n    if (defvalue && strcmp(value,defvalue) == 0) force = 0;\n\n    line = sdsnew(option);\n    line = sdscatlen(line, \" \", 1);\n    line = sdscatrepr(line, value, strlen(value));\n\n    rewriteConfigRewriteLine(state,option,line,force);\n}\n\n/* Rewrite a numerical (long long range) option. */\nvoid rewriteConfigNumericalOption(struct rewriteConfigState *state, char *option, long long value, long long defvalue) {\n    int force = value != defvalue;\n    sds line = sdscatprintf(sdsempty(),\"%s %lld\",option,value);\n\n    rewriteConfigRewriteLine(state,option,line,force);\n}\n\n/* Rewrite a octal option. */\nvoid rewriteConfigOctalOption(struct rewriteConfigState *state, char *option, int value, int defvalue) {\n    int force = value != defvalue;\n    sds line = sdscatprintf(sdsempty(),\"%s %o\",option,value);\n\n    rewriteConfigRewriteLine(state,option,line,force);\n}\n\n/* Rewrite an enumeration option, after the \"value\" every enum/value pair\n * is specified, terminated by NULL. After NULL the default value is\n * specified. See how the function is used for more information. */\nvoid rewriteConfigEnumOption(struct rewriteConfigState *state, char *option, int value, ...) {\n    va_list ap;\n    char *enum_name, *matching_name = NULL;\n    int enum_val, def_val, force;\n    sds line;\n\n    va_start(ap, value);\n    while(1) {\n        enum_name = va_arg(ap,char*);\n        enum_val = va_arg(ap,int);\n        if (enum_name == NULL) {\n            def_val = enum_val;\n            break;\n        }\n        if (value == enum_val) matching_name = enum_name;\n    }\n    va_end(ap);\n\n    force = value != def_val;\n    line = sdscatprintf(sdsempty(),\"%s %s\",option,matching_name);\n    rewriteConfigRewriteLine(state,option,line,force);\n}\n\n/* Rewrite the syslog-facility option. */\nvoid rewriteConfigSyslogfacilityOption(struct rewriteConfigState *state) {\n    int value = server.syslog_facility, j;\n    int force = value != LOG_LOCAL0;\n    char *name = NULL, *option = \"syslog-facility\";\n    sds line;\n\n    for (j = 0; validSyslogFacilities[j].name; j++) {\n        if (validSyslogFacilities[j].value == value) {\n            name = (char*) validSyslogFacilities[j].name;\n            break;\n        }\n    }\n    line = sdscatprintf(sdsempty(),\"%s %s\",option,name);\n    rewriteConfigRewriteLine(state,option,line,force);\n}\n\n/* Rewrite the save option. */\nvoid rewriteConfigSaveOption(struct rewriteConfigState *state) {\n    int j;\n    sds line;\n\n    /* Note that if there are no save parameters at all, all the current\n     * config line with \"save\" will be detected as orphaned and deleted,\n     * resulting into no RDB persistence as expected. */\n    for (j = 0; j < server.saveparamslen; j++) {\n        line = sdscatprintf(sdsempty(),\"save %ld %d\",\n            (long) server.saveparams[j].seconds, server.saveparams[j].changes);\n        rewriteConfigRewriteLine(state,\"save\",line,1);\n    }\n    /* Mark \"save\" as processed in case server.saveparamslen is zero. */\n    rewriteConfigMarkAsProcessed(state,\"save\");\n}\n\n/* Rewrite the dir option, always using absolute paths.*/\nvoid rewriteConfigDirOption(struct rewriteConfigState *state) {\n    char cwd[1024];\n\n    if (getcwd(cwd,sizeof(cwd)) == NULL) {\n        rewriteConfigMarkAsProcessed(state,\"dir\");\n        return; /* no rewrite on error. */\n    }\n    rewriteConfigStringOption(state,\"dir\",cwd,NULL);\n}\n\n/* Rewrite the slaveof option. */\nvoid rewriteConfigSlaveofOption(struct rewriteConfigState *state) {\n    char *option = \"slaveof\";\n    sds line;\n\n    /* If this is a master, we want all the slaveof config options\n     * in the file to be removed. */\n    if (server.masterhost == NULL) {\n        rewriteConfigMarkAsProcessed(state,\"slaveof\");\n        return;\n    }\n    line = sdscatprintf(sdsempty(),\"%s %s %d\", option,\n        server.masterhost, server.masterport);\n    rewriteConfigRewriteLine(state,option,line,1);\n}\n\n/* Rewrite the notify-keyspace-events option. */\nvoid rewriteConfigNotifykeyspaceeventsOption(struct rewriteConfigState *state) {\n    int force = server.notify_keyspace_events != 0;\n    char *option = \"notify-keyspace-events\";\n    sds line, flags;\n\n    flags = keyspaceEventsFlagsToString(server.notify_keyspace_events);\n    line = sdsnew(option);\n    line = sdscatlen(line, \" \", 1);\n    line = sdscatrepr(line, flags, sdslen(flags));\n    sdsfree(flags);\n    rewriteConfigRewriteLine(state,option,line,force);\n}\n\n/* Rewrite the client-output-buffer-limit option. */\nvoid rewriteConfigClientoutputbufferlimitOption(struct rewriteConfigState *state) {\n    int j;\n    char *option = \"client-output-buffer-limit\";\n\n    for (j = 0; j < REDIS_CLIENT_TYPE_COUNT; j++) {\n        int force = (server.client_obuf_limits[j].hard_limit_bytes !=\n                    clientBufferLimitsDefaults[j].hard_limit_bytes) ||\n                    (server.client_obuf_limits[j].soft_limit_bytes !=\n                    clientBufferLimitsDefaults[j].soft_limit_bytes) ||\n                    (server.client_obuf_limits[j].soft_limit_seconds !=\n                    clientBufferLimitsDefaults[j].soft_limit_seconds);\n        sds line;\n        char hard[64], soft[64];\n\n        rewriteConfigFormatMemory(hard,sizeof(hard),\n                server.client_obuf_limits[j].hard_limit_bytes);\n        rewriteConfigFormatMemory(soft,sizeof(soft),\n                server.client_obuf_limits[j].soft_limit_bytes);\n\n        line = sdscatprintf(sdsempty(),\"%s %s %s %s %ld\",\n                option, getClientTypeName(j), hard, soft,\n                (long) server.client_obuf_limits[j].soft_limit_seconds);\n        rewriteConfigRewriteLine(state,option,line,force);\n    }\n}\n\n/* Rewrite the bind option. */\nvoid rewriteConfigBindOption(struct rewriteConfigState *state) {\n    int force = 1;\n    sds line, addresses;\n    char *option = \"bind\";\n\n    /* Nothing to rewrite if we don't have bind addresses. */\n    if (server.bindaddr_count == 0) {\n        rewriteConfigMarkAsProcessed(state,option);\n        return;\n    }\n\n    /* Rewrite as bind <addr1> <addr2> ... <addrN> */\n    addresses = sdsjoin(server.bindaddr,server.bindaddr_count,\" \");\n    line = sdsnew(option);\n    line = sdscatlen(line, \" \", 1);\n    line = sdscatsds(line, addresses);\n    sdsfree(addresses);\n\n    rewriteConfigRewriteLine(state,option,line,force);\n}\n\n/* Glue together the configuration lines in the current configuration\n * rewrite state into a single string, stripping multiple empty lines. */\nsds rewriteConfigGetContentFromState(struct rewriteConfigState *state) {\n    sds content = sdsempty();\n    int j, was_empty = 0;\n\n    for (j = 0; j < state->numlines; j++) {\n        /* Every cluster of empty lines is turned into a single empty line. */\n        if (sdslen(state->lines[j]) == 0) {\n            if (was_empty) continue;\n            was_empty = 1;\n        } else {\n            was_empty = 0;\n        }\n        content = sdscatsds(content,state->lines[j]);\n        content = sdscatlen(content,\"\\n\",1);\n    }\n    return content;\n}\n\n/* Free the configuration rewrite state. */\nvoid rewriteConfigReleaseState(struct rewriteConfigState *state) {\n    sdsfreesplitres(state->lines,state->numlines);\n    dictRelease(state->option_to_line);\n    dictRelease(state->rewritten);\n    zfree(state);\n}\n\n/* At the end of the rewrite process the state contains the remaining\n * map between \"option name\" => \"lines in the original config file\".\n * Lines used by the rewrite process were removed by the function\n * rewriteConfigRewriteLine(), all the other lines are \"orphaned\" and\n * should be replaced by empty lines.\n *\n * This function does just this, iterating all the option names and\n * blanking all the lines still associated. */\nvoid rewriteConfigRemoveOrphaned(struct rewriteConfigState *state) {\n    dictIterator *di = dictGetIterator(state->option_to_line);\n    dictEntry *de;\n\n    while((de = dictNext(di)) != NULL) {\n        list *l = dictGetVal(de);\n        sds option = dictGetKey(de);\n\n        /* Don't blank lines about options the rewrite process\n         * don't understand. */\n        if (dictFind(state->rewritten,option) == NULL) {\n            redisLog(REDIS_DEBUG,\"Not rewritten option: %s\", option);\n            continue;\n        }\n\n        while(listLength(l)) {\n            listNode *ln = listFirst(l);\n            int linenum = (long) ln->value;\n\n            sdsfree(state->lines[linenum]);\n            state->lines[linenum] = sdsempty();\n            listDelNode(l,ln);\n        }\n    }\n    dictReleaseIterator(di);\n}\n\n/* This function overwrites the old configuration file with the new content.\n *\n * 1) The old file length is obtained.\n * 2) If the new content is smaller, padding is added.\n * 3) A single write(2) call is used to replace the content of the file.\n * 4) Later the file is truncated to the length of the new content.\n *\n * This way we are sure the file is left in a consistent state even if the\n * process is stopped between any of the four operations.\n *\n * The function returns 0 on success, otherwise -1 is returned and errno\n * set accordingly. */\nint rewriteConfigOverwriteFile(char *configfile, sds content) {\n    int retval = 0;\n    int fd = open(configfile,O_RDWR|O_CREAT,0644);\n    int content_size = sdslen(content), padding = 0;\n    struct stat sb;\n    sds content_padded;\n\n    /* 1) Open the old file (or create a new one if it does not\n     *    exist), get the size. */\n    if (fd == -1) return -1; /* errno set by open(). */\n    if (fstat(fd,&sb) == -1) {\n        close(fd);\n        return -1; /* errno set by fstat(). */\n    }\n\n    /* 2) Pad the content at least match the old file size. */\n    content_padded = sdsdup(content);\n    if (content_size < sb.st_size) {\n        /* If the old file was bigger, pad the content with\n         * a newline plus as many \"#\" chars as required. */\n        padding = sb.st_size - content_size;\n        content_padded = sdsgrowzero(content_padded,sb.st_size);\n        content_padded[content_size] = '\\n';\n        memset(content_padded+content_size+1,'#',padding-1);\n    }\n\n    /* 3) Write the new content using a single write(2). */\n    if (write(fd,content_padded,strlen(content_padded)) == -1) {\n        retval = -1;\n        goto cleanup;\n    }\n\n    /* 4) Truncate the file to the right length if we used padding. */\n    if (padding) {\n        if (ftruncate(fd,content_size) == -1) {\n            /* Non critical error... */\n        }\n    }\n\ncleanup:\n    sdsfree(content_padded);\n    close(fd);\n    return retval;\n}\n\n/* Rewrite the configuration file at \"path\".\n * If the configuration file already exists, we try at best to retain comments\n * and overall structure.\n *\n * Configuration parameters that are at their default value, unless already\n * explicitly included in the old configuration file, are not rewritten.\n *\n * On error -1 is returned and errno is set accordingly, otherwise 0. */\nint rewriteConfig(char *path) {\n    struct rewriteConfigState *state;\n    sds newcontent;\n    int retval;\n\n    /* Step 1: read the old config into our rewrite state. */\n    if ((state = rewriteConfigReadOldFile(path)) == NULL) return -1;\n\n    /* Step 2: rewrite every single option, replacing or appending it inside\n     * the rewrite state. */\n\n    rewriteConfigYesNoOption(state,\"daemonize\",server.daemonize,0);\n    rewriteConfigStringOption(state,\"pidfile\",server.pidfile,REDIS_DEFAULT_PID_FILE);\n    rewriteConfigNumericalOption(state,\"port\",server.port,REDIS_SERVERPORT);\n    rewriteConfigNumericalOption(state,\"tcp-backlog\",server.tcp_backlog,REDIS_TCP_BACKLOG);\n    rewriteConfigBindOption(state);\n    rewriteConfigStringOption(state,\"unixsocket\",server.unixsocket,NULL);\n    rewriteConfigOctalOption(state,\"unixsocketperm\",server.unixsocketperm,REDIS_DEFAULT_UNIX_SOCKET_PERM);\n    rewriteConfigNumericalOption(state,\"timeout\",server.maxidletime,REDIS_MAXIDLETIME);\n    rewriteConfigNumericalOption(state,\"tcp-keepalive\",server.tcpkeepalive,REDIS_DEFAULT_TCP_KEEPALIVE);\n    rewriteConfigEnumOption(state,\"loglevel\",server.verbosity,\n        \"debug\", REDIS_DEBUG,\n        \"verbose\", REDIS_VERBOSE,\n        \"notice\", REDIS_NOTICE,\n        \"warning\", REDIS_WARNING,\n        NULL, REDIS_DEFAULT_VERBOSITY);\n    rewriteConfigStringOption(state,\"logfile\",server.logfile,REDIS_DEFAULT_LOGFILE);\n    rewriteConfigYesNoOption(state,\"syslog-enabled\",server.syslog_enabled,REDIS_DEFAULT_SYSLOG_ENABLED);\n    rewriteConfigStringOption(state,\"syslog-ident\",server.syslog_ident,REDIS_DEFAULT_SYSLOG_IDENT);\n    rewriteConfigSyslogfacilityOption(state);\n    rewriteConfigSaveOption(state);\n    rewriteConfigNumericalOption(state,\"databases\",server.dbnum,REDIS_DEFAULT_DBNUM);\n    rewriteConfigYesNoOption(state,\"stop-writes-on-bgsave-error\",server.stop_writes_on_bgsave_err,REDIS_DEFAULT_STOP_WRITES_ON_BGSAVE_ERROR);\n    rewriteConfigYesNoOption(state,\"rdbcompression\",server.rdb_compression,REDIS_DEFAULT_RDB_COMPRESSION);\n    rewriteConfigYesNoOption(state,\"rdbchecksum\",server.rdb_checksum,REDIS_DEFAULT_RDB_CHECKSUM);\n    rewriteConfigStringOption(state,\"dbfilename\",server.rdb_filename,REDIS_DEFAULT_RDB_FILENAME);\n    rewriteConfigDirOption(state);\n    rewriteConfigSlaveofOption(state);\n    rewriteConfigStringOption(state,\"masterauth\",server.masterauth,NULL);\n    rewriteConfigYesNoOption(state,\"slave-serve-stale-data\",server.repl_serve_stale_data,REDIS_DEFAULT_SLAVE_SERVE_STALE_DATA);\n    rewriteConfigYesNoOption(state,\"slave-read-only\",server.repl_slave_ro,REDIS_DEFAULT_SLAVE_READ_ONLY);\n    rewriteConfigNumericalOption(state,\"repl-ping-slave-period\",server.repl_ping_slave_period,REDIS_REPL_PING_SLAVE_PERIOD);\n    rewriteConfigNumericalOption(state,\"repl-timeout\",server.repl_timeout,REDIS_REPL_TIMEOUT);\n    rewriteConfigBytesOption(state,\"repl-backlog-size\",server.repl_backlog_size,REDIS_DEFAULT_REPL_BACKLOG_SIZE);\n    rewriteConfigBytesOption(state,\"repl-backlog-ttl\",server.repl_backlog_time_limit,REDIS_DEFAULT_REPL_BACKLOG_TIME_LIMIT);\n    rewriteConfigYesNoOption(state,\"repl-disable-tcp-nodelay\",server.repl_disable_tcp_nodelay,REDIS_DEFAULT_REPL_DISABLE_TCP_NODELAY);\n    rewriteConfigYesNoOption(state,\"repl-diskless-sync\",server.repl_diskless_sync,REDIS_DEFAULT_REPL_DISKLESS_SYNC);\n    rewriteConfigNumericalOption(state,\"repl-diskless-sync-delay\",server.repl_diskless_sync_delay,REDIS_DEFAULT_REPL_DISKLESS_SYNC_DELAY);\n    rewriteConfigNumericalOption(state,\"slave-priority\",server.slave_priority,REDIS_DEFAULT_SLAVE_PRIORITY);\n    rewriteConfigNumericalOption(state,\"min-slaves-to-write\",server.repl_min_slaves_to_write,REDIS_DEFAULT_MIN_SLAVES_TO_WRITE);\n    rewriteConfigNumericalOption(state,\"min-slaves-max-lag\",server.repl_min_slaves_max_lag,REDIS_DEFAULT_MIN_SLAVES_MAX_LAG);\n    rewriteConfigStringOption(state,\"requirepass\",server.requirepass,NULL);\n    rewriteConfigNumericalOption(state,\"maxclients\",server.maxclients,REDIS_MAX_CLIENTS);\n    rewriteConfigBytesOption(state,\"maxmemory\",server.maxmemory,REDIS_DEFAULT_MAXMEMORY);\n    rewriteConfigEnumOption(state,\"maxmemory-policy\",server.maxmemory_policy,\n        \"volatile-lru\", REDIS_MAXMEMORY_VOLATILE_LRU,\n        \"allkeys-lru\", REDIS_MAXMEMORY_ALLKEYS_LRU,\n        \"volatile-random\", REDIS_MAXMEMORY_VOLATILE_RANDOM,\n        \"allkeys-random\", REDIS_MAXMEMORY_ALLKEYS_RANDOM,\n        \"volatile-ttl\", REDIS_MAXMEMORY_VOLATILE_TTL,\n        \"noeviction\", REDIS_MAXMEMORY_NO_EVICTION,\n        NULL, REDIS_DEFAULT_MAXMEMORY_POLICY);\n    rewriteConfigNumericalOption(state,\"maxmemory-samples\",server.maxmemory_samples,REDIS_DEFAULT_MAXMEMORY_SAMPLES);\n    rewriteConfigYesNoOption(state,\"appendonly\",server.aof_state != REDIS_AOF_OFF,0);\n    rewriteConfigStringOption(state,\"appendfilename\",server.aof_filename,REDIS_DEFAULT_AOF_FILENAME);\n    rewriteConfigEnumOption(state,\"appendfsync\",server.aof_fsync,\n        \"everysec\", AOF_FSYNC_EVERYSEC,\n        \"always\", AOF_FSYNC_ALWAYS,\n        \"no\", AOF_FSYNC_NO,\n        NULL, REDIS_DEFAULT_AOF_FSYNC);\n    rewriteConfigYesNoOption(state,\"no-appendfsync-on-rewrite\",server.aof_no_fsync_on_rewrite,REDIS_DEFAULT_AOF_NO_FSYNC_ON_REWRITE);\n    rewriteConfigNumericalOption(state,\"auto-aof-rewrite-percentage\",server.aof_rewrite_perc,REDIS_AOF_REWRITE_PERC);\n    rewriteConfigBytesOption(state,\"auto-aof-rewrite-min-size\",server.aof_rewrite_min_size,REDIS_AOF_REWRITE_MIN_SIZE);\n    rewriteConfigNumericalOption(state,\"lua-time-limit\",server.lua_time_limit,REDIS_LUA_TIME_LIMIT);\n    rewriteConfigNumericalOption(state,\"slowlog-log-slower-than\",server.slowlog_log_slower_than,REDIS_SLOWLOG_LOG_SLOWER_THAN);\n    rewriteConfigNumericalOption(state,\"latency-monitor-threshold\",server.latency_monitor_threshold,REDIS_DEFAULT_LATENCY_MONITOR_THRESHOLD);\n    rewriteConfigNumericalOption(state,\"slowlog-max-len\",server.slowlog_max_len,REDIS_SLOWLOG_MAX_LEN);\n    rewriteConfigNotifykeyspaceeventsOption(state);\n    rewriteConfigNumericalOption(state,\"hash-max-ziplist-entries\",server.hash_max_ziplist_entries,REDIS_HASH_MAX_ZIPLIST_ENTRIES);\n    rewriteConfigNumericalOption(state,\"hash-max-ziplist-value\",server.hash_max_ziplist_value,REDIS_HASH_MAX_ZIPLIST_VALUE);\n    rewriteConfigNumericalOption(state,\"list-max-ziplist-entries\",server.list_max_ziplist_entries,REDIS_LIST_MAX_ZIPLIST_ENTRIES);\n    rewriteConfigNumericalOption(state,\"list-max-ziplist-value\",server.list_max_ziplist_value,REDIS_LIST_MAX_ZIPLIST_VALUE);\n    rewriteConfigNumericalOption(state,\"set-max-intset-entries\",server.set_max_intset_entries,REDIS_SET_MAX_INTSET_ENTRIES);\n    rewriteConfigNumericalOption(state,\"zset-max-ziplist-entries\",server.zset_max_ziplist_entries,REDIS_ZSET_MAX_ZIPLIST_ENTRIES);\n    rewriteConfigNumericalOption(state,\"zset-max-ziplist-value\",server.zset_max_ziplist_value,REDIS_ZSET_MAX_ZIPLIST_VALUE);\n    rewriteConfigNumericalOption(state,\"hll-sparse-max-bytes\",server.hll_sparse_max_bytes,REDIS_DEFAULT_HLL_SPARSE_MAX_BYTES);\n    rewriteConfigYesNoOption(state,\"activerehashing\",server.activerehashing,REDIS_DEFAULT_ACTIVE_REHASHING);\n    rewriteConfigClientoutputbufferlimitOption(state);\n    rewriteConfigNumericalOption(state,\"hz\",server.hz,REDIS_DEFAULT_HZ);\n    rewriteConfigYesNoOption(state,\"aof-rewrite-incremental-fsync\",server.aof_rewrite_incremental_fsync,REDIS_DEFAULT_AOF_REWRITE_INCREMENTAL_FSYNC);\n    rewriteConfigYesNoOption(state,\"aof-load-truncated\",server.aof_load_truncated,REDIS_DEFAULT_AOF_LOAD_TRUNCATED);\n    if (server.sentinel_mode) rewriteConfigSentinelOption(state);\n\n    /* Step 3: remove all the orphaned lines in the old file, that is, lines\n     * that were used by a config option and are no longer used, like in case\n     * of multiple \"save\" options or duplicated options. */\n    rewriteConfigRemoveOrphaned(state);\n\n    /* Step 4: generate a new configuration file from the modified state\n     * and write it into the original file. */\n    newcontent = rewriteConfigGetContentFromState(state);\n    retval = rewriteConfigOverwriteFile(server.configfile,newcontent);\n\n    sdsfree(newcontent);\n    rewriteConfigReleaseState(state);\n    return retval;\n}\n\n/*-----------------------------------------------------------------------------\n * CONFIG command entry point\n *----------------------------------------------------------------------------*/\n\nvoid configCommand(redisClient *c) {\n    if (!strcasecmp(c->argv[1]->ptr,\"set\")) {\n        if (c->argc != 4) goto badarity;\n        configSetCommand(c);\n    } else if (!strcasecmp(c->argv[1]->ptr,\"get\")) {\n        if (c->argc != 3) goto badarity;\n        configGetCommand(c);\n    } else if (!strcasecmp(c->argv[1]->ptr,\"resetstat\")) {\n        if (c->argc != 2) goto badarity;\n        resetServerStats();\n        resetCommandTableStats();\n        addReply(c,shared.ok);\n    } else if (!strcasecmp(c->argv[1]->ptr,\"rewrite\")) {\n        if (c->argc != 2) goto badarity;\n        if (server.configfile == NULL) {\n            addReplyError(c,\"The server is running without a config file\");\n            return;\n        }\n        if (rewriteConfig(server.configfile) == -1) {\n            redisLog(REDIS_WARNING,\"CONFIG REWRITE failed: %s\", strerror(errno));\n            addReplyErrorFormat(c,\"Rewriting config file: %s\", strerror(errno));\n        } else {\n            redisLog(REDIS_WARNING,\"CONFIG REWRITE executed with success.\");\n            addReply(c,shared.ok);\n        }\n    } else {\n        addReplyError(c,\n            \"CONFIG subcommand must be one of GET, SET, RESETSTAT, REWRITE\");\n    }\n    return;\n\nbadarity:\n    addReplyErrorFormat(c,\"Wrong number of arguments for CONFIG %s\",\n        (char*) c->argv[1]->ptr);\n}\n"
  },
  {
    "path": "extern/deprecated/redis-2.8.21/src/config.h",
    "content": "/*\n * Copyright (c) 2009-2012, Salvatore Sanfilippo <antirez at gmail dot com>\n * All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions are met:\n *\n *   * Redistributions of source code must retain the above copyright notice,\n *     this list of conditions and the following disclaimer.\n *   * Redistributions in binary form must reproduce the above copyright\n *     notice, this list of conditions and the following disclaimer in the\n *     documentation and/or other materials provided with the distribution.\n *   * Neither the name of Redis nor the names of its contributors may be used\n *     to endorse or promote products derived from this software without\n *     specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\"\n * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\n * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE\n * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR\n * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF\n * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS\n * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN\n * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)\n * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE\n * POSSIBILITY OF SUCH DAMAGE.\n */\n\n#ifndef __CONFIG_H\n#define __CONFIG_H\n\n#ifdef __APPLE__\n#include <AvailabilityMacros.h>\n#endif\n\n/* Define redis_fstat to fstat or fstat64() */\n#if defined(__APPLE__) && !defined(MAC_OS_X_VERSION_10_6)\n#define redis_fstat fstat64\n#define redis_stat stat64\n#else\n#define redis_fstat fstat\n#define redis_stat stat\n#endif\n\n/* Test for proc filesystem */\n#ifdef __linux__\n#define HAVE_PROC_STAT 1\n#define HAVE_PROC_MAPS 1\n#define HAVE_PROC_SMAPS 1\n#define HAVE_PROC_SOMAXCONN 1\n#endif\n\n/* Test for task_info() */\n#if defined(__APPLE__)\n#define HAVE_TASKINFO 1\n#endif\n\n/* Test for backtrace() */\n#if defined(__APPLE__) || defined(__linux__)\n#define HAVE_BACKTRACE 1\n#endif\n\n/* Test for polling API */\n#ifdef __linux__\n#define HAVE_EPOLL 1\n#endif\n\n#if (defined(__APPLE__) && defined(MAC_OS_X_VERSION_10_6)) || defined(__FreeBSD__) || defined(__OpenBSD__) || defined (__NetBSD__)\n#define HAVE_KQUEUE 1\n#endif\n\n#ifdef __sun\n#include <sys/feature_tests.h>\n#ifdef _DTRACE_VERSION\n#define HAVE_EVPORT 1\n#endif\n#endif\n\n/* Define aof_fsync to fdatasync() in Linux and fsync() for all the rest */\n#ifdef __linux__\n#define aof_fsync fdatasync\n#else\n#define aof_fsync fsync\n#endif\n\n/* Define rdb_fsync_range to sync_file_range() on Linux, otherwise we use\n * the plain fsync() call. */\n#ifdef __linux__\n#include <linux/version.h>\n#include <features.h>\n#if defined(__GLIBC__) && defined(__GLIBC_PREREQ)\n#if (LINUX_VERSION_CODE >= 0x020611 && __GLIBC_PREREQ(2, 6))\n#define HAVE_SYNC_FILE_RANGE 1\n#endif\n#else\n#if (LINUX_VERSION_CODE >= 0x020611)\n#define HAVE_SYNC_FILE_RANGE 1\n#endif\n#endif\n#endif\n\n#ifdef HAVE_SYNC_FILE_RANGE\n#define rdb_fsync_range(fd,off,size) sync_file_range(fd,off,size,SYNC_FILE_RANGE_WAIT_BEFORE|SYNC_FILE_RANGE_WRITE)\n#else\n#define rdb_fsync_range(fd,off,size) fsync(fd)\n#endif\n\n/* Check if we can use setproctitle().\n * BSD systems have support for it, we provide an implementation for\n * Linux and osx. */\n#if (defined __NetBSD__ || defined __FreeBSD__ || defined __OpenBSD__)\n#define USE_SETPROCTITLE\n#endif\n\n#if (defined __linux || defined __APPLE__)\n#define USE_SETPROCTITLE\n#define INIT_SETPROCTITLE_REPLACEMENT\nvoid spt_init(int argc, char *argv[]);\nvoid setproctitle(const char *fmt, ...);\n#endif\n\n/* Byte ordering detection */\n#include <sys/types.h> /* This will likely define BYTE_ORDER */\n\n#ifndef BYTE_ORDER\n#if (BSD >= 199103)\n# include <machine/endian.h>\n#else\n#if defined(linux) || defined(__linux__)\n# include <endian.h>\n#else\n#define\tLITTLE_ENDIAN\t1234\t/* least-significant byte first (vax, pc) */\n#define\tBIG_ENDIAN\t4321\t/* most-significant byte first (IBM, net) */\n#define\tPDP_ENDIAN\t3412\t/* LSB first in word, MSW first in long (pdp)*/\n\n#if defined(__i386__) || defined(__x86_64__) || defined(__amd64__) || \\\n   defined(vax) || defined(ns32000) || defined(sun386) || \\\n   defined(MIPSEL) || defined(_MIPSEL) || defined(BIT_ZERO_ON_RIGHT) || \\\n   defined(__alpha__) || defined(__alpha)\n#define BYTE_ORDER    LITTLE_ENDIAN\n#endif\n\n#if defined(sel) || defined(pyr) || defined(mc68000) || defined(sparc) || \\\n    defined(is68k) || defined(tahoe) || defined(ibm032) || defined(ibm370) || \\\n    defined(MIPSEB) || defined(_MIPSEB) || defined(_IBMR2) || defined(DGUX) ||\\\n    defined(apollo) || defined(__convex__) || defined(_CRAY) || \\\n    defined(__hppa) || defined(__hp9000) || \\\n    defined(__hp9000s300) || defined(__hp9000s700) || \\\n    defined (BIT_ZERO_ON_LEFT) || defined(m68k) || defined(__sparc)\n#define BYTE_ORDER\tBIG_ENDIAN\n#endif\n#endif /* linux */\n#endif /* BSD */\n#endif /* BYTE_ORDER */\n\n/* Sometimes after including an OS-specific header that defines the\n * endianess we end with __BYTE_ORDER but not with BYTE_ORDER that is what\n * the Redis code uses. In this case let's define everything without the\n * underscores. */\n#ifndef BYTE_ORDER\n#ifdef __BYTE_ORDER\n#if defined(__LITTLE_ENDIAN) && defined(__BIG_ENDIAN)\n#ifndef LITTLE_ENDIAN\n#define LITTLE_ENDIAN __LITTLE_ENDIAN\n#endif\n#ifndef BIG_ENDIAN\n#define BIG_ENDIAN __BIG_ENDIAN\n#endif\n#if (__BYTE_ORDER == __LITTLE_ENDIAN)\n#define BYTE_ORDER LITTLE_ENDIAN\n#else\n#define BYTE_ORDER BIG_ENDIAN\n#endif\n#endif\n#endif\n#endif\n\n#if !defined(BYTE_ORDER) || \\\n    (BYTE_ORDER != BIG_ENDIAN && BYTE_ORDER != LITTLE_ENDIAN)\n\t/* you must determine what the correct bit order is for\n\t * your compiler - the next line is an intentional error\n\t * which will force your compiles to bomb until you fix\n\t * the above macros.\n\t */\n#error \"Undefined or invalid BYTE_ORDER\"\n#endif\n\n#if (__i386 || __amd64 || __powerpc__) && __GNUC__\n#define GNUC_VERSION (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__)\n#if defined(__clang__)\n#define HAVE_ATOMIC\n#endif\n#if (defined(__GLIBC__) && defined(__GLIBC_PREREQ))\n#if (GNUC_VERSION >= 40100 && __GLIBC_PREREQ(2, 6))\n#define HAVE_ATOMIC\n#endif\n#endif\n#endif\n\n#endif\n"
  },
  {
    "path": "extern/deprecated/redis-2.8.21/src/crc32.c",
    "content": "#include <stdint.h>\n\nstatic const uint32_t IEEE_POLY = 0xedb88320;\nstatic const uint32_t CAST_POLY = 0x82f63b78;\nstatic const uint32_t KOOP_POLY = 0xeb31d82e;\n\nstatic uint32_t crc32tab[256];\n\nstatic void\ncrc32_tabinit(uint32_t poly) {\n    int i, j;\n    for (i = 0; i < 256; i ++) {\n        uint32_t crc = i;\n        for (j = 0; j < 8; j ++) {\n            if (crc & 1) {\n                crc = (crc >> 1) ^ poly;\n            } else {\n                crc = (crc >> 1);\n            }\n        }\n        crc32tab[i] = crc;\n    }\n}\n\nvoid\ncrc32_init() {\n    crc32_tabinit(IEEE_POLY);\n}\n\nstatic uint32_t\ncrc32_update(uint32_t crc, const char *buf, int len) {\n    int i;\n    crc = ~crc;\n    for (i = 0; i < len; i ++) {\n        crc = crc32tab[(uint8_t)((char)crc ^ buf[i])] ^ (crc >> 8);\n    }\n    return ~crc;\n}\n\nuint32_t\ncrc32_checksum(const char *buf, int len) {\n    return crc32_update(0, buf, len);\n}\n"
  },
  {
    "path": "extern/deprecated/redis-2.8.21/src/crc64.c",
    "content": "/* Redis uses the CRC64 variant with \"Jones\" coefficients and init value of 0.\n *\n * Specification of this CRC64 variant follows:\n * Name: crc-64-jones\n * Width: 64 bites\n * Poly: 0xad93d23594c935a9\n * Reflected In: True\n * Xor_In: 0xffffffffffffffff\n * Reflected_Out: True\n * Xor_Out: 0x0\n * Check(\"123456789\"): 0xe9c6d914c4b8d9ca\n *\n * Copyright (c) 2012, Salvatore Sanfilippo <antirez at gmail dot com>\n * All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions are met:\n *\n *   * Redistributions of source code must retain the above copyright notice,\n *     this list of conditions and the following disclaimer.\n *   * Redistributions in binary form must reproduce the above copyright\n *     notice, this list of conditions and the following disclaimer in the\n *     documentation and/or other materials provided with the distribution.\n *   * Neither the name of Redis nor the names of its contributors may be used\n *     to endorse or promote products derived from this software without\n *     specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\"\n * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\n * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE\n * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR\n * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF\n * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS\n * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN\n * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)\n * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE\n * POSSIBILITY OF SUCH DAMAGE. */\n\n#include <stdint.h>\n\nstatic const uint64_t crc64_tab[256] = {\n    UINT64_C(0x0000000000000000), UINT64_C(0x7ad870c830358979),\n    UINT64_C(0xf5b0e190606b12f2), UINT64_C(0x8f689158505e9b8b),\n    UINT64_C(0xc038e5739841b68f), UINT64_C(0xbae095bba8743ff6),\n    UINT64_C(0x358804e3f82aa47d), UINT64_C(0x4f50742bc81f2d04),\n    UINT64_C(0xab28ecb46814fe75), UINT64_C(0xd1f09c7c5821770c),\n    UINT64_C(0x5e980d24087fec87), UINT64_C(0x24407dec384a65fe),\n    UINT64_C(0x6b1009c7f05548fa), UINT64_C(0x11c8790fc060c183),\n    UINT64_C(0x9ea0e857903e5a08), UINT64_C(0xe478989fa00bd371),\n    UINT64_C(0x7d08ff3b88be6f81), UINT64_C(0x07d08ff3b88be6f8),\n    UINT64_C(0x88b81eabe8d57d73), UINT64_C(0xf2606e63d8e0f40a),\n    UINT64_C(0xbd301a4810ffd90e), UINT64_C(0xc7e86a8020ca5077),\n    UINT64_C(0x4880fbd87094cbfc), UINT64_C(0x32588b1040a14285),\n    UINT64_C(0xd620138fe0aa91f4), UINT64_C(0xacf86347d09f188d),\n    UINT64_C(0x2390f21f80c18306), UINT64_C(0x594882d7b0f40a7f),\n    UINT64_C(0x1618f6fc78eb277b), UINT64_C(0x6cc0863448deae02),\n    UINT64_C(0xe3a8176c18803589), UINT64_C(0x997067a428b5bcf0),\n    UINT64_C(0xfa11fe77117cdf02), UINT64_C(0x80c98ebf2149567b),\n    UINT64_C(0x0fa11fe77117cdf0), UINT64_C(0x75796f2f41224489),\n    UINT64_C(0x3a291b04893d698d), UINT64_C(0x40f16bccb908e0f4),\n    UINT64_C(0xcf99fa94e9567b7f), UINT64_C(0xb5418a5cd963f206),\n    UINT64_C(0x513912c379682177), UINT64_C(0x2be1620b495da80e),\n    UINT64_C(0xa489f35319033385), UINT64_C(0xde51839b2936bafc),\n    UINT64_C(0x9101f7b0e12997f8), UINT64_C(0xebd98778d11c1e81),\n    UINT64_C(0x64b116208142850a), UINT64_C(0x1e6966e8b1770c73),\n    UINT64_C(0x8719014c99c2b083), UINT64_C(0xfdc17184a9f739fa),\n    UINT64_C(0x72a9e0dcf9a9a271), UINT64_C(0x08719014c99c2b08),\n    UINT64_C(0x4721e43f0183060c), UINT64_C(0x3df994f731b68f75),\n    UINT64_C(0xb29105af61e814fe), UINT64_C(0xc849756751dd9d87),\n    UINT64_C(0x2c31edf8f1d64ef6), UINT64_C(0x56e99d30c1e3c78f),\n    UINT64_C(0xd9810c6891bd5c04), UINT64_C(0xa3597ca0a188d57d),\n    UINT64_C(0xec09088b6997f879), UINT64_C(0x96d1784359a27100),\n    UINT64_C(0x19b9e91b09fcea8b), UINT64_C(0x636199d339c963f2),\n    UINT64_C(0xdf7adabd7a6e2d6f), UINT64_C(0xa5a2aa754a5ba416),\n    UINT64_C(0x2aca3b2d1a053f9d), UINT64_C(0x50124be52a30b6e4),\n    UINT64_C(0x1f423fcee22f9be0), UINT64_C(0x659a4f06d21a1299),\n    UINT64_C(0xeaf2de5e82448912), UINT64_C(0x902aae96b271006b),\n    UINT64_C(0x74523609127ad31a), UINT64_C(0x0e8a46c1224f5a63),\n    UINT64_C(0x81e2d7997211c1e8), UINT64_C(0xfb3aa75142244891),\n    UINT64_C(0xb46ad37a8a3b6595), UINT64_C(0xceb2a3b2ba0eecec),\n    UINT64_C(0x41da32eaea507767), UINT64_C(0x3b024222da65fe1e),\n    UINT64_C(0xa2722586f2d042ee), UINT64_C(0xd8aa554ec2e5cb97),\n    UINT64_C(0x57c2c41692bb501c), UINT64_C(0x2d1ab4dea28ed965),\n    UINT64_C(0x624ac0f56a91f461), UINT64_C(0x1892b03d5aa47d18),\n    UINT64_C(0x97fa21650afae693), UINT64_C(0xed2251ad3acf6fea),\n    UINT64_C(0x095ac9329ac4bc9b), UINT64_C(0x7382b9faaaf135e2),\n    UINT64_C(0xfcea28a2faafae69), UINT64_C(0x8632586aca9a2710),\n    UINT64_C(0xc9622c4102850a14), UINT64_C(0xb3ba5c8932b0836d),\n    UINT64_C(0x3cd2cdd162ee18e6), UINT64_C(0x460abd1952db919f),\n    UINT64_C(0x256b24ca6b12f26d), UINT64_C(0x5fb354025b277b14),\n    UINT64_C(0xd0dbc55a0b79e09f), UINT64_C(0xaa03b5923b4c69e6),\n    UINT64_C(0xe553c1b9f35344e2), UINT64_C(0x9f8bb171c366cd9b),\n    UINT64_C(0x10e3202993385610), UINT64_C(0x6a3b50e1a30ddf69),\n    UINT64_C(0x8e43c87e03060c18), UINT64_C(0xf49bb8b633338561),\n    UINT64_C(0x7bf329ee636d1eea), UINT64_C(0x012b592653589793),\n    UINT64_C(0x4e7b2d0d9b47ba97), UINT64_C(0x34a35dc5ab7233ee),\n    UINT64_C(0xbbcbcc9dfb2ca865), UINT64_C(0xc113bc55cb19211c),\n    UINT64_C(0x5863dbf1e3ac9dec), UINT64_C(0x22bbab39d3991495),\n    UINT64_C(0xadd33a6183c78f1e), UINT64_C(0xd70b4aa9b3f20667),\n    UINT64_C(0x985b3e827bed2b63), UINT64_C(0xe2834e4a4bd8a21a),\n    UINT64_C(0x6debdf121b863991), UINT64_C(0x1733afda2bb3b0e8),\n    UINT64_C(0xf34b37458bb86399), UINT64_C(0x8993478dbb8deae0),\n    UINT64_C(0x06fbd6d5ebd3716b), UINT64_C(0x7c23a61ddbe6f812),\n    UINT64_C(0x3373d23613f9d516), UINT64_C(0x49aba2fe23cc5c6f),\n    UINT64_C(0xc6c333a67392c7e4), UINT64_C(0xbc1b436e43a74e9d),\n    UINT64_C(0x95ac9329ac4bc9b5), UINT64_C(0xef74e3e19c7e40cc),\n    UINT64_C(0x601c72b9cc20db47), UINT64_C(0x1ac40271fc15523e),\n    UINT64_C(0x5594765a340a7f3a), UINT64_C(0x2f4c0692043ff643),\n    UINT64_C(0xa02497ca54616dc8), UINT64_C(0xdafce7026454e4b1),\n    UINT64_C(0x3e847f9dc45f37c0), UINT64_C(0x445c0f55f46abeb9),\n    UINT64_C(0xcb349e0da4342532), UINT64_C(0xb1eceec59401ac4b),\n    UINT64_C(0xfebc9aee5c1e814f), UINT64_C(0x8464ea266c2b0836),\n    UINT64_C(0x0b0c7b7e3c7593bd), UINT64_C(0x71d40bb60c401ac4),\n    UINT64_C(0xe8a46c1224f5a634), UINT64_C(0x927c1cda14c02f4d),\n    UINT64_C(0x1d148d82449eb4c6), UINT64_C(0x67ccfd4a74ab3dbf),\n    UINT64_C(0x289c8961bcb410bb), UINT64_C(0x5244f9a98c8199c2),\n    UINT64_C(0xdd2c68f1dcdf0249), UINT64_C(0xa7f41839ecea8b30),\n    UINT64_C(0x438c80a64ce15841), UINT64_C(0x3954f06e7cd4d138),\n    UINT64_C(0xb63c61362c8a4ab3), UINT64_C(0xcce411fe1cbfc3ca),\n    UINT64_C(0x83b465d5d4a0eece), UINT64_C(0xf96c151de49567b7),\n    UINT64_C(0x76048445b4cbfc3c), UINT64_C(0x0cdcf48d84fe7545),\n    UINT64_C(0x6fbd6d5ebd3716b7), UINT64_C(0x15651d968d029fce),\n    UINT64_C(0x9a0d8ccedd5c0445), UINT64_C(0xe0d5fc06ed698d3c),\n    UINT64_C(0xaf85882d2576a038), UINT64_C(0xd55df8e515432941),\n    UINT64_C(0x5a3569bd451db2ca), UINT64_C(0x20ed197575283bb3),\n    UINT64_C(0xc49581ead523e8c2), UINT64_C(0xbe4df122e51661bb),\n    UINT64_C(0x3125607ab548fa30), UINT64_C(0x4bfd10b2857d7349),\n    UINT64_C(0x04ad64994d625e4d), UINT64_C(0x7e7514517d57d734),\n    UINT64_C(0xf11d85092d094cbf), UINT64_C(0x8bc5f5c11d3cc5c6),\n    UINT64_C(0x12b5926535897936), UINT64_C(0x686de2ad05bcf04f),\n    UINT64_C(0xe70573f555e26bc4), UINT64_C(0x9ddd033d65d7e2bd),\n    UINT64_C(0xd28d7716adc8cfb9), UINT64_C(0xa85507de9dfd46c0),\n    UINT64_C(0x273d9686cda3dd4b), UINT64_C(0x5de5e64efd965432),\n    UINT64_C(0xb99d7ed15d9d8743), UINT64_C(0xc3450e196da80e3a),\n    UINT64_C(0x4c2d9f413df695b1), UINT64_C(0x36f5ef890dc31cc8),\n    UINT64_C(0x79a59ba2c5dc31cc), UINT64_C(0x037deb6af5e9b8b5),\n    UINT64_C(0x8c157a32a5b7233e), UINT64_C(0xf6cd0afa9582aa47),\n    UINT64_C(0x4ad64994d625e4da), UINT64_C(0x300e395ce6106da3),\n    UINT64_C(0xbf66a804b64ef628), UINT64_C(0xc5bed8cc867b7f51),\n    UINT64_C(0x8aeeace74e645255), UINT64_C(0xf036dc2f7e51db2c),\n    UINT64_C(0x7f5e4d772e0f40a7), UINT64_C(0x05863dbf1e3ac9de),\n    UINT64_C(0xe1fea520be311aaf), UINT64_C(0x9b26d5e88e0493d6),\n    UINT64_C(0x144e44b0de5a085d), UINT64_C(0x6e963478ee6f8124),\n    UINT64_C(0x21c640532670ac20), UINT64_C(0x5b1e309b16452559),\n    UINT64_C(0xd476a1c3461bbed2), UINT64_C(0xaeaed10b762e37ab),\n    UINT64_C(0x37deb6af5e9b8b5b), UINT64_C(0x4d06c6676eae0222),\n    UINT64_C(0xc26e573f3ef099a9), UINT64_C(0xb8b627f70ec510d0),\n    UINT64_C(0xf7e653dcc6da3dd4), UINT64_C(0x8d3e2314f6efb4ad),\n    UINT64_C(0x0256b24ca6b12f26), UINT64_C(0x788ec2849684a65f),\n    UINT64_C(0x9cf65a1b368f752e), UINT64_C(0xe62e2ad306bafc57),\n    UINT64_C(0x6946bb8b56e467dc), UINT64_C(0x139ecb4366d1eea5),\n    UINT64_C(0x5ccebf68aecec3a1), UINT64_C(0x2616cfa09efb4ad8),\n    UINT64_C(0xa97e5ef8cea5d153), UINT64_C(0xd3a62e30fe90582a),\n    UINT64_C(0xb0c7b7e3c7593bd8), UINT64_C(0xca1fc72bf76cb2a1),\n    UINT64_C(0x45775673a732292a), UINT64_C(0x3faf26bb9707a053),\n    UINT64_C(0x70ff52905f188d57), UINT64_C(0x0a2722586f2d042e),\n    UINT64_C(0x854fb3003f739fa5), UINT64_C(0xff97c3c80f4616dc),\n    UINT64_C(0x1bef5b57af4dc5ad), UINT64_C(0x61372b9f9f784cd4),\n    UINT64_C(0xee5fbac7cf26d75f), UINT64_C(0x9487ca0fff135e26),\n    UINT64_C(0xdbd7be24370c7322), UINT64_C(0xa10fceec0739fa5b),\n    UINT64_C(0x2e675fb4576761d0), UINT64_C(0x54bf2f7c6752e8a9),\n    UINT64_C(0xcdcf48d84fe75459), UINT64_C(0xb71738107fd2dd20),\n    UINT64_C(0x387fa9482f8c46ab), UINT64_C(0x42a7d9801fb9cfd2),\n    UINT64_C(0x0df7adabd7a6e2d6), UINT64_C(0x772fdd63e7936baf),\n    UINT64_C(0xf8474c3bb7cdf024), UINT64_C(0x829f3cf387f8795d),\n    UINT64_C(0x66e7a46c27f3aa2c), UINT64_C(0x1c3fd4a417c62355),\n    UINT64_C(0x935745fc4798b8de), UINT64_C(0xe98f353477ad31a7),\n    UINT64_C(0xa6df411fbfb21ca3), UINT64_C(0xdc0731d78f8795da),\n    UINT64_C(0x536fa08fdfd90e51), UINT64_C(0x29b7d047efec8728),\n};\n\nuint64_t crc64(uint64_t crc, const unsigned char *s, uint64_t l) {\n    uint64_t j;\n\n    for (j = 0; j < l; j++) {\n        uint8_t byte = s[j];\n        crc = crc64_tab[(uint8_t)crc ^ byte] ^ (crc >> 8);\n    }\n    return crc;\n}\n\n/* Test main */\n#ifdef TEST_MAIN\n#include <stdio.h>\nint main(void) {\n    printf(\"e9c6d914c4b8d9ca == %016llx\\n\",\n        (unsigned long long) crc64(0,(unsigned char*)\"123456789\",9));\n    return 0;\n}\n#endif\n"
  },
  {
    "path": "extern/deprecated/redis-2.8.21/src/crc64.h",
    "content": "#ifndef CRC64_H\n#define CRC64_H\n\n#include <stdint.h>\n\nuint64_t crc64(uint64_t crc, const unsigned char *s, uint64_t l);\n\n#endif\n"
  },
  {
    "path": "extern/deprecated/redis-2.8.21/src/db.c",
    "content": "/*\n * Copyright (c) 2009-2012, Salvatore Sanfilippo <antirez at gmail dot com>\n * All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions are met:\n *\n *   * Redistributions of source code must retain the above copyright notice,\n *     this list of conditions and the following disclaimer.\n *   * Redistributions in binary form must reproduce the above copyright\n *     notice, this list of conditions and the following disclaimer in the\n *     documentation and/or other materials provided with the distribution.\n *   * Neither the name of Redis nor the names of its contributors may be used\n *     to endorse or promote products derived from this software without\n *     specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\"\n * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\n * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE\n * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR\n * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF\n * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS\n * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN\n * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)\n * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE\n * POSSIBILITY OF SUCH DAMAGE.\n */\n\n#include \"redis.h\"\n\n#include <signal.h>\n#include <ctype.h>\n\n/*-----------------------------------------------------------------------------\n * C-level DB API\n *----------------------------------------------------------------------------*/\n\nrobj *lookupKey(redisDb *db, robj *key) {\n    dictEntry *de = dictFind(db->dict,key->ptr);\n    if (de) {\n        robj *val = dictGetVal(de);\n\n        /* Update the access time for the ageing algorithm.\n         * Don't do it if we have a saving child, as this will trigger\n         * a copy on write madness. */\n        if (server.rdb_child_pid == -1 && server.aof_child_pid == -1)\n            val->lru = server.lruclock;\n        return val;\n    } else {\n        return NULL;\n    }\n}\n\nrobj *lookupKeyRead(redisDb *db, robj *key) {\n    robj *val;\n\n    expireIfNeeded(db,key);\n    val = lookupKey(db,key);\n    if (val == NULL)\n        server.stat_keyspace_misses++;\n    else\n        server.stat_keyspace_hits++;\n    return val;\n}\n\nrobj *lookupKeyWrite(redisDb *db, robj *key) {\n    expireIfNeeded(db,key);\n    return lookupKey(db,key);\n}\n\nrobj *lookupKeyReadOrReply(redisClient *c, robj *key, robj *reply) {\n    robj *o = lookupKeyRead(c->db, key);\n    if (!o) addReply(c,reply);\n    return o;\n}\n\nrobj *lookupKeyWriteOrReply(redisClient *c, robj *key, robj *reply) {\n    robj *o = lookupKeyWrite(c->db, key);\n    if (!o) addReply(c,reply);\n    return o;\n}\n\n/* Add the key to the DB. It's up to the caller to increment the reference\n * counter of the value if needed.\n *\n * The program is aborted if the key already exists. */\nvoid dbAdd(redisDb *db, robj *key, robj *val) {\n    sds copy = sdsdup(key->ptr);\n\n    int retval = dictAdd(db->dict, copy, val);\n\n    do {\n        uint32_t crc;\n        int hastag;\n        int slot = slots_num(key->ptr, &crc, &hastag);\n        dictAdd(db->hash_slots[slot], copy, (void *)(long)crc);\n        if (hastag) {\n            incrRefCount(key);\n            zslInsert(db->tagged_keys, (double)crc, key);\n        }\n    } while (0);\n\n    redisAssertWithInfo(NULL,key,retval == REDIS_OK);\n    if (val->type == REDIS_LIST) signalListAsReady(db, key);\n}\n\n/* Overwrite an existing key with a new value. Incrementing the reference\n * count of the new value is up to the caller.\n * This function does not modify the expire time of the existing key.\n *\n * The program is aborted if the key was not already present. */\nvoid dbOverwrite(redisDb *db, robj *key, robj *val) {\n    struct dictEntry *de = dictFind(db->dict,key->ptr);\n\n    redisAssertWithInfo(NULL,key,de != NULL);\n    dictReplace(db->dict, key->ptr, val);\n}\n\n/* High level Set operation. This function can be used in order to set\n * a key, whatever it was existing or not, to a new object.\n *\n * 1) The ref count of the value object is incremented.\n * 2) clients WATCHing for the destination key notified.\n * 3) The expire time of the key is reset (the key is made persistent). */\nvoid setKey(redisDb *db, robj *key, robj *val) {\n    if (lookupKeyWrite(db,key) == NULL) {\n        dbAdd(db,key,val);\n    } else {\n        dbOverwrite(db,key,val);\n    }\n    incrRefCount(val);\n    removeExpire(db,key);\n    signalModifiedKey(db,key);\n}\n\nint dbExists(redisDb *db, robj *key) {\n    return dictFind(db->dict,key->ptr) != NULL;\n}\n\n/* Return a random key, in form of a Redis object.\n * If there are no keys, NULL is returned.\n *\n * The function makes sure to return keys not already expired. */\nrobj *dbRandomKey(redisDb *db) {\n    struct dictEntry *de;\n\n    while(1) {\n        sds key;\n        robj *keyobj;\n\n        de = dictGetRandomKey(db->dict);\n        if (de == NULL) return NULL;\n\n        key = dictGetKey(de);\n        keyobj = createStringObject(key,sdslen(key));\n        if (dictFind(db->expires,key)) {\n            if (expireIfNeeded(db,keyobj)) {\n                decrRefCount(keyobj);\n                continue; /* search for another key. This expired. */\n            }\n        }\n        return keyobj;\n    }\n}\n\n/* Delete a key, value, and associated expiration entry if any, from the DB */\nint dbDelete(redisDb *db, robj *key) {\n    /* Deleting an entry from the expires dict will not free the sds of\n     * the key, because it is shared with the main dictionary. */\n    if (dictSize(db->expires) > 0) dictDelete(db->expires,key->ptr);\n\n    do {\n        uint32_t crc;\n        int hastag;\n        int slot = slots_num(key->ptr, &crc, &hastag);\n        if (dictDelete(db->hash_slots[slot], key->ptr) == DICT_OK) {\n            if (hastag) {\n                zslDelete(db->tagged_keys, (double)crc, key);\n            }\n        }\n    } while (0);\n\n    if (dictDelete(db->dict,key->ptr) == DICT_OK) {\n        return 1;\n    } else {\n        return 0;\n    }\n}\n\n/* Prepare the string object stored at 'key' to be modified destructively\n * to implement commands like SETBIT or APPEND.\n *\n * An object is usually ready to be modified unless one of the two conditions\n * are true:\n *\n * 1) The object 'o' is shared (refcount > 1), we don't want to affect\n *    other users.\n * 2) The object encoding is not \"RAW\".\n *\n * If the object is found in one of the above conditions (or both) by the\n * function, an unshared / not-encoded copy of the string object is stored\n * at 'key' in the specified 'db'. Otherwise the object 'o' itself is\n * returned.\n *\n * USAGE:\n *\n * The object 'o' is what the caller already obtained by looking up 'key'\n * in 'db', the usage pattern looks like this:\n *\n * o = lookupKeyWrite(db,key);\n * if (checkType(c,o,REDIS_STRING)) return;\n * o = dbUnshareStringValue(db,key,o);\n *\n * At this point the caller is ready to modify the object, for example\n * using an sdscat() call to append some data, or anything else.\n */\nrobj *dbUnshareStringValue(redisDb *db, robj *key, robj *o) {\n    redisAssert(o->type == REDIS_STRING);\n    if (o->refcount != 1 || o->encoding != REDIS_ENCODING_RAW) {\n        robj *decoded = getDecodedObject(o);\n        o = createStringObject(decoded->ptr, sdslen(decoded->ptr));\n        decrRefCount(decoded);\n        dbOverwrite(db,key,o);\n    }\n    return o;\n}\n\nlong long emptyDb(void(callback)(void*)) {\n    int i, j;\n    long long removed = 0;\n    \n    for (j = 0; j < server.dbnum; j++) {\n        removed += dictSize(server.db[j].dict);\n        for (i = 0; i < HASH_SLOTS_SIZE; i ++) {\n            dictEmpty(server.db[j].hash_slots[i], NULL);\n        }\n        if (server.db[j].tagged_keys->length != 0) {\n            zslFree(server.db[j].tagged_keys);\n            server.db[j].tagged_keys = zslCreate();\n        }\n        dictEmpty(server.db[j].dict,callback);\n        dictEmpty(server.db[j].expires,callback);\n    }\n    return removed;\n}\n\nint selectDb(redisClient *c, int id) {\n    if (id < 0 || id >= server.dbnum)\n        return REDIS_ERR;\n    c->db = &server.db[id];\n    return REDIS_OK;\n}\n\n/*-----------------------------------------------------------------------------\n * Hooks for key space changes.\n *\n * Every time a key in the database is modified the function\n * signalModifiedKey() is called.\n *\n * Every time a DB is flushed the function signalFlushDb() is called.\n *----------------------------------------------------------------------------*/\n\nvoid signalModifiedKey(redisDb *db, robj *key) {\n    touchWatchedKey(db,key);\n}\n\nvoid signalFlushedDb(int dbid) {\n    touchWatchedKeysOnFlush(dbid);\n}\n\n/*-----------------------------------------------------------------------------\n * Type agnostic commands operating on the key space\n *----------------------------------------------------------------------------*/\n\nvoid flushdbCommand(redisClient *c) {\n    int i;\n    server.dirty += dictSize(c->db->dict);\n    signalFlushedDb(c->db->id);\n    for (i = 0; i < HASH_SLOTS_SIZE; i ++) {\n        dictEmpty(c->db->hash_slots[i], NULL);\n    }\n    if (c->db->tagged_keys->length != 0) {\n        zslFree(c->db->tagged_keys);\n        c->db->tagged_keys = zslCreate();\n    }\n    dictEmpty(c->db->dict,NULL);\n    dictEmpty(c->db->expires,NULL);\n    addReply(c,shared.ok);\n}\n\nvoid flushallCommand(redisClient *c) {\n    signalFlushedDb(-1);\n    server.dirty += emptyDb(NULL);\n    addReply(c,shared.ok);\n    if (server.rdb_child_pid != -1) {\n        kill(server.rdb_child_pid,SIGUSR1);\n        rdbRemoveTempFile(server.rdb_child_pid);\n    }\n    if (server.saveparamslen > 0) {\n        /* Normally rdbSave() will reset dirty, but we don't want this here\n         * as otherwise FLUSHALL will not be replicated nor put into the AOF. */\n        int saved_dirty = server.dirty;\n        rdbSave(server.rdb_filename);\n        server.dirty = saved_dirty;\n    }\n    server.dirty++;\n}\n\nvoid delCommand(redisClient *c) {\n    int deleted = 0, j;\n\n    for (j = 1; j < c->argc; j++) {\n        expireIfNeeded(c->db,c->argv[j]);\n        if (dbDelete(c->db,c->argv[j])) {\n            signalModifiedKey(c->db,c->argv[j]);\n            notifyKeyspaceEvent(REDIS_NOTIFY_GENERIC,\n                \"del\",c->argv[j],c->db->id);\n            server.dirty++;\n            deleted++;\n        }\n    }\n    addReplyLongLong(c,deleted);\n}\n\nvoid existsCommand(redisClient *c) {\n    expireIfNeeded(c->db,c->argv[1]);\n    if (dbExists(c->db,c->argv[1])) {\n        addReply(c, shared.cone);\n    } else {\n        addReply(c, shared.czero);\n    }\n}\n\nvoid selectCommand(redisClient *c) {\n    long id;\n\n    if (getLongFromObjectOrReply(c, c->argv[1], &id,\n        \"invalid DB index\") != REDIS_OK)\n        return;\n\n    if (selectDb(c,id) == REDIS_ERR) {\n        addReplyError(c,\"invalid DB index\");\n    } else {\n        addReply(c,shared.ok);\n    }\n}\n\nvoid randomkeyCommand(redisClient *c) {\n    robj *key;\n\n    if ((key = dbRandomKey(c->db)) == NULL) {\n        addReply(c,shared.nullbulk);\n        return;\n    }\n\n    addReplyBulk(c,key);\n    decrRefCount(key);\n}\n\nvoid keysCommand(redisClient *c) {\n    dictIterator *di;\n    dictEntry *de;\n    sds pattern = c->argv[1]->ptr;\n    int plen = sdslen(pattern), allkeys;\n    unsigned long numkeys = 0;\n    void *replylen = addDeferredMultiBulkLength(c);\n\n    di = dictGetSafeIterator(c->db->dict);\n    allkeys = (pattern[0] == '*' && pattern[1] == '\\0');\n    while((de = dictNext(di)) != NULL) {\n        sds key = dictGetKey(de);\n        robj *keyobj;\n\n        if (allkeys || stringmatchlen(pattern,plen,key,sdslen(key),0)) {\n            keyobj = createStringObject(key,sdslen(key));\n            if (expireIfNeeded(c->db,keyobj) == 0) {\n                addReplyBulk(c,keyobj);\n                numkeys++;\n            }\n            decrRefCount(keyobj);\n        }\n    }\n    dictReleaseIterator(di);\n    setDeferredMultiBulkLength(c,replylen,numkeys);\n}\n\n/* This callback is used by scanGenericCommand in order to collect elements\n * returned by the dictionary iterator into a list. */\nvoid scanCallback(void *privdata, const dictEntry *de) {\n    void **pd = (void**) privdata;\n    list *keys = pd[0];\n    robj *o = pd[1];\n    robj *key, *val = NULL;\n\n    if (o == NULL) {\n        sds sdskey = dictGetKey(de);\n        key = createStringObject(sdskey, sdslen(sdskey));\n    } else if (o->type == REDIS_SET) {\n        key = dictGetKey(de);\n        incrRefCount(key);\n    } else if (o->type == REDIS_HASH) {\n        key = dictGetKey(de);\n        incrRefCount(key);\n        val = dictGetVal(de);\n        incrRefCount(val);\n    } else if (o->type == REDIS_ZSET) {\n        key = dictGetKey(de);\n        incrRefCount(key);\n        val = createStringObjectFromLongDouble(*(double*)dictGetVal(de),0);\n    } else {\n        redisPanic(\"Type not handled in SCAN callback.\");\n    }\n\n    listAddNodeTail(keys, key);\n    if (val) listAddNodeTail(keys, val);\n}\n\n/* Try to parse a SCAN cursor stored at object 'o':\n * if the cursor is valid, store it as unsigned integer into *cursor and\n * returns REDIS_OK. Otherwise return REDIS_ERR and send an error to the\n * client. */\nint parseScanCursorOrReply(redisClient *c, robj *o, unsigned long *cursor) {\n    char *eptr;\n\n    /* Use strtoul() because we need an *unsigned* long, so\n     * getLongLongFromObject() does not cover the whole cursor space. */\n    errno = 0;\n    *cursor = strtoul(o->ptr, &eptr, 10);\n    if (isspace(((char*)o->ptr)[0]) || eptr[0] != '\\0' || errno == ERANGE)\n    {\n        addReplyError(c, \"invalid cursor\");\n        return REDIS_ERR;\n    }\n    return REDIS_OK;\n}\n\n/* This command implements SCAN, HSCAN and SSCAN commands.\n * If object 'o' is passed, then it must be a Hash or Set object, otherwise\n * if 'o' is NULL the command will operate on the dictionary associated with\n * the current database.\n *\n * When 'o' is not NULL the function assumes that the first argument in\n * the client arguments vector is a key so it skips it before iterating\n * in order to parse options.\n *\n * In the case of a Hash object the function returns both the field and value\n * of every element on the Hash. */\nvoid scanGenericCommand(redisClient *c, robj *o, unsigned long cursor) {\n    int i, j;\n    list *keys = listCreate();\n    listNode *node, *nextnode;\n    long count = 10;\n    sds pat;\n    int patlen, use_pattern = 0;\n    dict *ht;\n\n    /* Object must be NULL (to iterate keys names), or the type of the object\n     * must be Set, Sorted Set, or Hash. */\n    redisAssert(o == NULL || o->type == REDIS_SET || o->type == REDIS_HASH ||\n                o->type == REDIS_ZSET);\n\n    /* Set i to the first option argument. The previous one is the cursor. */\n    i = (o == NULL) ? 2 : 3; /* Skip the key argument if needed. */\n\n    /* Step 1: Parse options. */\n    while (i < c->argc) {\n        j = c->argc - i;\n        if (!strcasecmp(c->argv[i]->ptr, \"count\") && j >= 2) {\n            if (getLongFromObjectOrReply(c, c->argv[i+1], &count, NULL)\n                != REDIS_OK)\n            {\n                goto cleanup;\n            }\n\n            if (count < 1) {\n                addReply(c,shared.syntaxerr);\n                goto cleanup;\n            }\n\n            i += 2;\n        } else if (!strcasecmp(c->argv[i]->ptr, \"match\") && j >= 2) {\n            pat = c->argv[i+1]->ptr;\n            patlen = sdslen(pat);\n\n            /* The pattern always matches if it is exactly \"*\", so it is\n             * equivalent to disabling it. */\n            use_pattern = !(pat[0] == '*' && patlen == 1);\n\n            i += 2;\n        } else {\n            addReply(c,shared.syntaxerr);\n            goto cleanup;\n        }\n    }\n\n    /* Step 2: Iterate the collection.\n     *\n     * Note that if the object is encoded with a ziplist, intset, or any other\n     * representation that is not a hash table, we are sure that it is also\n     * composed of a small number of elements. So to avoid taking state we\n     * just return everything inside the object in a single call, setting the\n     * cursor to zero to signal the end of the iteration. */\n\n    /* Handle the case of a hash table. */\n    ht = NULL;\n    if (o == NULL) {\n        ht = c->db->dict;\n    } else if (o->type == REDIS_SET && o->encoding == REDIS_ENCODING_HT) {\n        ht = o->ptr;\n    } else if (o->type == REDIS_HASH && o->encoding == REDIS_ENCODING_HT) {\n        ht = o->ptr;\n        count *= 2; /* We return key / value for this type. */\n    } else if (o->type == REDIS_ZSET && o->encoding == REDIS_ENCODING_SKIPLIST) {\n        zset *zs = o->ptr;\n        ht = zs->dict;\n        count *= 2; /* We return key / value for this type. */\n    }\n\n    if (ht) {\n        void *privdata[2];\n        /* We set the max number of iterations to ten times the specified\n         * COUNT, so if the hash table is in a pathological state (very\n         * sparsely populated) we avoid to block too much time at the cost\n         * of returning no or very few elements. */\n        long maxiterations = count*10;\n\n        /* We pass two pointers to the callback: the list to which it will\n         * add new elements, and the object containing the dictionary so that\n         * it is possible to fetch more data in a type-dependent way. */\n        privdata[0] = keys;\n        privdata[1] = o;\n        do {\n            cursor = dictScan(ht, cursor, scanCallback, privdata);\n        } while (cursor &&\n              maxiterations-- &&\n              listLength(keys) < (unsigned long)count);\n    } else if (o->type == REDIS_SET) {\n        int pos = 0;\n        int64_t ll;\n\n        while(intsetGet(o->ptr,pos++,&ll))\n            listAddNodeTail(keys,createStringObjectFromLongLong(ll));\n        cursor = 0;\n    } else if (o->type == REDIS_HASH || o->type == REDIS_ZSET) {\n        unsigned char *p = ziplistIndex(o->ptr,0);\n        unsigned char *vstr;\n        unsigned int vlen;\n        long long vll;\n\n        while(p) {\n            ziplistGet(p,&vstr,&vlen,&vll);\n            listAddNodeTail(keys,\n                (vstr != NULL) ? createStringObject((char*)vstr,vlen) :\n                                 createStringObjectFromLongLong(vll));\n            p = ziplistNext(o->ptr,p);\n        }\n        cursor = 0;\n    } else {\n        redisPanic(\"Not handled encoding in SCAN.\");\n    }\n\n    /* Step 3: Filter elements. */\n    node = listFirst(keys);\n    while (node) {\n        robj *kobj = listNodeValue(node);\n        nextnode = listNextNode(node);\n        int filter = 0;\n\n        /* Filter element if it does not match the pattern. */\n        if (!filter && use_pattern) {\n            if (kobj->encoding == REDIS_ENCODING_INT) {\n                char buf[REDIS_LONGSTR_SIZE];\n                int len;\n\n                redisAssert(kobj->encoding == REDIS_ENCODING_INT);\n                len = ll2string(buf,sizeof(buf),(long)kobj->ptr);\n                if (!stringmatchlen(pat, patlen, buf, len, 0)) filter = 1;\n            } else {\n                if (!stringmatchlen(pat, patlen, kobj->ptr, sdslen(kobj->ptr), 0))\n                    filter = 1;\n            }\n        }\n\n        /* Filter element if it is an expired key. */\n        if (!filter && o == NULL && expireIfNeeded(c->db, kobj)) filter = 1;\n\n        /* Remove the element and its associted value if needed. */\n        if (filter) {\n            decrRefCount(kobj);\n            listDelNode(keys, node);\n        }\n\n        /* If this is a hash or a sorted set, we have a flat list of\n         * key-value elements, so if this element was filtered, remove the\n         * value, or skip it if it was not filtered: we only match keys. */\n        if (o && (o->type == REDIS_ZSET || o->type == REDIS_HASH)) {\n            node = nextnode;\n            nextnode = listNextNode(node);\n            if (filter) {\n                kobj = listNodeValue(node);\n                decrRefCount(kobj);\n                listDelNode(keys, node);\n            }\n        }\n        node = nextnode;\n    }\n\n    /* Step 4: Reply to the client. */\n    addReplyMultiBulkLen(c, 2);\n    addReplyBulkLongLong(c,cursor);\n\n    addReplyMultiBulkLen(c, listLength(keys));\n    while ((node = listFirst(keys)) != NULL) {\n        robj *kobj = listNodeValue(node);\n        addReplyBulk(c, kobj);\n        decrRefCount(kobj);\n        listDelNode(keys, node);\n    }\n\ncleanup:\n    listSetFreeMethod(keys,decrRefCountVoid);\n    listRelease(keys);\n}\n\n/* The SCAN command completely relies on scanGenericCommand. */\nvoid scanCommand(redisClient *c) {\n    unsigned long cursor;\n    if (parseScanCursorOrReply(c,c->argv[1],&cursor) == REDIS_ERR) return;\n    scanGenericCommand(c,NULL,cursor);\n}\n\nvoid dbsizeCommand(redisClient *c) {\n    addReplyLongLong(c,dictSize(c->db->dict));\n}\n\nvoid lastsaveCommand(redisClient *c) {\n    addReplyLongLong(c,server.lastsave);\n}\n\nvoid typeCommand(redisClient *c) {\n    robj *o;\n    char *type;\n\n    o = lookupKeyRead(c->db,c->argv[1]);\n    if (o == NULL) {\n        type = \"none\";\n    } else {\n        switch(o->type) {\n        case REDIS_STRING: type = \"string\"; break;\n        case REDIS_LIST: type = \"list\"; break;\n        case REDIS_SET: type = \"set\"; break;\n        case REDIS_ZSET: type = \"zset\"; break;\n        case REDIS_HASH: type = \"hash\"; break;\n        default: type = \"unknown\"; break;\n        }\n    }\n    addReplyStatus(c,type);\n}\n\nvoid shutdownCommand(redisClient *c) {\n    int flags = 0;\n\n    if (c->argc > 2) {\n        addReply(c,shared.syntaxerr);\n        return;\n    } else if (c->argc == 2) {\n        if (!strcasecmp(c->argv[1]->ptr,\"nosave\")) {\n            flags |= REDIS_SHUTDOWN_NOSAVE;\n        } else if (!strcasecmp(c->argv[1]->ptr,\"save\")) {\n            flags |= REDIS_SHUTDOWN_SAVE;\n        } else {\n            addReply(c,shared.syntaxerr);\n            return;\n        }\n    }\n    /* When SHUTDOWN is called while the server is loading a dataset in\n     * memory we need to make sure no attempt is performed to save\n     * the dataset on shutdown (otherwise it could overwrite the current DB\n     * with half-read data).\n     *\n     * Also when in Sentinel mode clear the SAVE flag and force NOSAVE. */\n    if (server.loading || server.sentinel_mode)\n        flags = (flags & ~REDIS_SHUTDOWN_SAVE) | REDIS_SHUTDOWN_NOSAVE;\n    if (prepareForShutdown(flags) == REDIS_OK) {\n        for (int j = 0; j < server.dbnum; j ++) {\n            for (int i = 0; i < HASH_SLOTS_SIZE; i ++) {\n                dictRelease(server.db[j].hash_slots[i]);\n            }\n            zslFree(server.db[j].tagged_keys);\n        }\n        exit(0);\n    }\n    addReplyError(c,\"Errors trying to SHUTDOWN. Check logs.\");\n}\n\nvoid renameGenericCommand(redisClient *c, int nx) {\n    robj *o;\n    long long expire;\n\n    /* To use the same key as src and dst is probably an error */\n    if (sdscmp(c->argv[1]->ptr,c->argv[2]->ptr) == 0) {\n        addReply(c,shared.sameobjecterr);\n        return;\n    }\n\n    if ((o = lookupKeyWriteOrReply(c,c->argv[1],shared.nokeyerr)) == NULL)\n        return;\n\n    incrRefCount(o);\n    expire = getExpire(c->db,c->argv[1]);\n    if (lookupKeyWrite(c->db,c->argv[2]) != NULL) {\n        if (nx) {\n            decrRefCount(o);\n            addReply(c,shared.czero);\n            return;\n        }\n        /* Overwrite: delete the old key before creating the new one\n         * with the same name. */\n        dbDelete(c->db,c->argv[2]);\n    }\n    dbAdd(c->db,c->argv[2],o);\n    if (expire != -1) setExpire(c->db,c->argv[2],expire);\n    dbDelete(c->db,c->argv[1]);\n    signalModifiedKey(c->db,c->argv[1]);\n    signalModifiedKey(c->db,c->argv[2]);\n    notifyKeyspaceEvent(REDIS_NOTIFY_GENERIC,\"rename_from\",\n        c->argv[1],c->db->id);\n    notifyKeyspaceEvent(REDIS_NOTIFY_GENERIC,\"rename_to\",\n        c->argv[2],c->db->id);\n    server.dirty++;\n    addReply(c,nx ? shared.cone : shared.ok);\n}\n\nvoid renameCommand(redisClient *c) {\n    renameGenericCommand(c,0);\n}\n\nvoid renamenxCommand(redisClient *c) {\n    renameGenericCommand(c,1);\n}\n\nvoid moveCommand(redisClient *c) {\n    robj *o;\n    redisDb *src, *dst;\n    int srcid;\n    long long dbid;\n\n    /* Obtain source and target DB pointers */\n    src = c->db;\n    srcid = c->db->id;\n\n    if (getLongLongFromObject(c->argv[2],&dbid) == REDIS_ERR ||\n        dbid < INT_MIN || dbid > INT_MAX ||\n        selectDb(c,dbid) == REDIS_ERR)\n    {\n        addReply(c,shared.outofrangeerr);\n        return;\n    }\n    dst = c->db;\n    selectDb(c,srcid); /* Back to the source DB */\n\n    /* If the user is moving using as target the same\n     * DB as the source DB it is probably an error. */\n    if (src == dst) {\n        addReply(c,shared.sameobjecterr);\n        return;\n    }\n\n    /* Check if the element exists and get a reference */\n    o = lookupKeyWrite(c->db,c->argv[1]);\n    if (!o) {\n        addReply(c,shared.czero);\n        return;\n    }\n\n    /* Return zero if the key already exists in the target DB */\n    if (lookupKeyWrite(dst,c->argv[1]) != NULL) {\n        addReply(c,shared.czero);\n        return;\n    }\n    dbAdd(dst,c->argv[1],o);\n    incrRefCount(o);\n\n    /* OK! key moved, free the entry in the source DB */\n    dbDelete(src,c->argv[1]);\n    server.dirty++;\n    addReply(c,shared.cone);\n}\n\n/*-----------------------------------------------------------------------------\n * Expires API\n *----------------------------------------------------------------------------*/\n\nint removeExpire(redisDb *db, robj *key) {\n    /* An expire may only be removed if there is a corresponding entry in the\n     * main dict. Otherwise, the key will never be freed. */\n    redisAssertWithInfo(NULL,key,dictFind(db->dict,key->ptr) != NULL);\n    return dictDelete(db->expires,key->ptr) == DICT_OK;\n}\n\nvoid setExpire(redisDb *db, robj *key, long long when) {\n    dictEntry *kde, *de;\n\n    /* Reuse the sds from the main dict in the expire dict */\n    kde = dictFind(db->dict,key->ptr);\n    redisAssertWithInfo(NULL,key,kde != NULL);\n    de = dictReplaceRaw(db->expires,dictGetKey(kde));\n    dictSetSignedIntegerVal(de,when);\n}\n\n/* Return the expire time of the specified key, or -1 if no expire\n * is associated with this key (i.e. the key is non volatile) */\nlong long getExpire(redisDb *db, robj *key) {\n    dictEntry *de;\n\n    /* No expire? return ASAP */\n    if (dictSize(db->expires) == 0 ||\n       (de = dictFind(db->expires,key->ptr)) == NULL) return -1;\n\n    /* The entry was found in the expire dict, this means it should also\n     * be present in the main dict (safety check). */\n    redisAssertWithInfo(NULL,key,dictFind(db->dict,key->ptr) != NULL);\n    return dictGetSignedIntegerVal(de);\n}\n\n/* Propagate expires into slaves and the AOF file.\n * When a key expires in the master, a DEL operation for this key is sent\n * to all the slaves and the AOF file if enabled.\n *\n * This way the key expiry is centralized in one place, and since both\n * AOF and the master->slave link guarantee operation ordering, everything\n * will be consistent even if we allow write operations against expiring\n * keys. */\nvoid propagateExpire(redisDb *db, robj *key) {\n    robj *argv[2];\n\n    argv[0] = shared.del;\n    argv[1] = key;\n    incrRefCount(argv[0]);\n    incrRefCount(argv[1]);\n\n    if (server.aof_state != REDIS_AOF_OFF)\n        feedAppendOnlyFile(server.delCommand,db->id,argv,2);\n    replicationFeedSlaves(server.slaves,db->id,argv,2);\n\n    decrRefCount(argv[0]);\n    decrRefCount(argv[1]);\n}\n\nint expireIfNeeded(redisDb *db, robj *key) {\n    mstime_t when = getExpire(db,key);\n    mstime_t now;\n\n    if (when < 0) return 0; /* No expire for this key */\n\n    /* Don't expire anything while loading. It will be done later. */\n    if (server.loading) return 0;\n\n    /* If we are in the context of a Lua script, we claim that time is\n     * blocked to when the Lua script started. This way a key can expire\n     * only the first time it is accessed and not in the middle of the\n     * script execution, making propagation to slaves / AOF consistent.\n     * See issue #1525 on Github for more information. */\n    now = server.lua_caller ? server.lua_time_start : mstime();\n\n    /* If we are running in the context of a slave, return ASAP:\n     * the slave key expiration is controlled by the master that will\n     * send us synthesized DEL operations for expired keys.\n     *\n     * Still we try to return the right information to the caller,\n     * that is, 0 if we think the key should be still valid, 1 if\n     * we think the key is expired at this time. */\n    if (server.masterhost != NULL) return now > when;\n\n    /* Return when this key has not expired */\n    if (now <= when) return 0;\n\n    /* Delete the key */\n    server.stat_expiredkeys++;\n    propagateExpire(db,key);\n    notifyKeyspaceEvent(REDIS_NOTIFY_EXPIRED,\n        \"expired\",key,db->id);\n    return dbDelete(db,key);\n}\n\n/*-----------------------------------------------------------------------------\n * Expires Commands\n *----------------------------------------------------------------------------*/\n\n/* This is the generic command implementation for EXPIRE, PEXPIRE, EXPIREAT\n * and PEXPIREAT. Because the commad second argument may be relative or absolute\n * the \"basetime\" argument is used to signal what the base time is (either 0\n * for *AT variants of the command, or the current time for relative expires).\n *\n * unit is either UNIT_SECONDS or UNIT_MILLISECONDS, and is only used for\n * the argv[2] parameter. The basetime is always specified in milliseconds. */\nvoid expireGenericCommand(redisClient *c, long long basetime, int unit) {\n    robj *key = c->argv[1], *param = c->argv[2];\n    long long when; /* unix time in milliseconds when the key will expire. */\n\n    if (getLongLongFromObjectOrReply(c, param, &when, NULL) != REDIS_OK)\n        return;\n\n    if (unit == UNIT_SECONDS) when *= 1000;\n    when += basetime;\n\n    /* No key, return zero. */\n    if (lookupKeyRead(c->db,key) == NULL) {\n        addReply(c,shared.czero);\n        return;\n    }\n\n    /* EXPIRE with negative TTL, or EXPIREAT with a timestamp into the past\n     * should never be executed as a DEL when load the AOF or in the context\n     * of a slave instance.\n     *\n     * Instead we take the other branch of the IF statement setting an expire\n     * (possibly in the past) and wait for an explicit DEL from the master. */\n    if (when <= mstime() && !server.loading && !server.masterhost) {\n        robj *aux;\n\n        redisAssertWithInfo(c,key,dbDelete(c->db,key));\n        server.dirty++;\n\n        /* Replicate/AOF this as an explicit DEL. */\n        aux = createStringObject(\"DEL\",3);\n        rewriteClientCommandVector(c,2,aux,key);\n        decrRefCount(aux);\n        signalModifiedKey(c->db,key);\n        notifyKeyspaceEvent(REDIS_NOTIFY_GENERIC,\"del\",key,c->db->id);\n        addReply(c, shared.cone);\n        return;\n    } else {\n        setExpire(c->db,key,when);\n        addReply(c,shared.cone);\n        signalModifiedKey(c->db,key);\n        notifyKeyspaceEvent(REDIS_NOTIFY_GENERIC,\"expire\",key,c->db->id);\n        server.dirty++;\n        return;\n    }\n}\n\nvoid expireCommand(redisClient *c) {\n    expireGenericCommand(c,mstime(),UNIT_SECONDS);\n}\n\nvoid expireatCommand(redisClient *c) {\n    expireGenericCommand(c,0,UNIT_SECONDS);\n}\n\nvoid pexpireCommand(redisClient *c) {\n    expireGenericCommand(c,mstime(),UNIT_MILLISECONDS);\n}\n\nvoid pexpireatCommand(redisClient *c) {\n    expireGenericCommand(c,0,UNIT_MILLISECONDS);\n}\n\nvoid ttlGenericCommand(redisClient *c, int output_ms) {\n    long long expire, ttl = -1;\n\n    /* If the key does not exist at all, return -2 */\n    if (lookupKeyRead(c->db,c->argv[1]) == NULL) {\n        addReplyLongLong(c,-2);\n        return;\n    }\n    /* The key exists. Return -1 if it has no expire, or the actual\n     * TTL value otherwise. */\n    expire = getExpire(c->db,c->argv[1]);\n    if (expire != -1) {\n        ttl = expire-mstime();\n        if (ttl < 0) ttl = 0;\n    }\n    if (ttl == -1) {\n        addReplyLongLong(c,-1);\n    } else {\n        addReplyLongLong(c,output_ms ? ttl : ((ttl+500)/1000));\n    }\n}\n\nvoid ttlCommand(redisClient *c) {\n    ttlGenericCommand(c, 0);\n}\n\nvoid pttlCommand(redisClient *c) {\n    ttlGenericCommand(c, 1);\n}\n\nvoid persistCommand(redisClient *c) {\n    dictEntry *de;\n\n    de = dictFind(c->db->dict,c->argv[1]->ptr);\n    if (de == NULL) {\n        addReply(c,shared.czero);\n    } else {\n        if (removeExpire(c->db,c->argv[1])) {\n            addReply(c,shared.cone);\n            server.dirty++;\n        } else {\n            addReply(c,shared.czero);\n        }\n    }\n}\n\n/* -----------------------------------------------------------------------------\n * API to get key arguments from commands\n * ---------------------------------------------------------------------------*/\n\nint *getKeysUsingCommandTable(struct redisCommand *cmd,robj **argv, int argc, int *numkeys) {\n    int j, i = 0, last, *keys;\n    REDIS_NOTUSED(argv);\n\n    if (cmd->firstkey == 0) {\n        *numkeys = 0;\n        return NULL;\n    }\n    last = cmd->lastkey;\n    if (last < 0) last = argc+last;\n    keys = zmalloc(sizeof(int)*((last - cmd->firstkey)+1));\n    for (j = cmd->firstkey; j <= last; j += cmd->keystep) {\n        redisAssert(j < argc);\n        keys[i++] = j;\n    }\n    *numkeys = i;\n    return keys;\n}\n\nint *getKeysFromCommand(struct redisCommand *cmd,robj **argv, int argc, int *numkeys, int flags) {\n    if (cmd->getkeys_proc) {\n        return cmd->getkeys_proc(cmd,argv,argc,numkeys,flags);\n    } else {\n        return getKeysUsingCommandTable(cmd,argv,argc,numkeys);\n    }\n}\n\nvoid getKeysFreeResult(int *result) {\n    zfree(result);\n}\n\nint *noPreloadGetKeys(struct redisCommand *cmd,robj **argv, int argc, int *numkeys, int flags) {\n    if (flags & REDIS_GETKEYS_PRELOAD) {\n        *numkeys = 0;\n        return NULL;\n    } else {\n        return getKeysUsingCommandTable(cmd,argv,argc,numkeys);\n    }\n}\n\nint *renameGetKeys(struct redisCommand *cmd,robj **argv, int argc, int *numkeys, int flags) {\n    if (flags & REDIS_GETKEYS_PRELOAD) {\n        int *keys = zmalloc(sizeof(int));\n        *numkeys = 1;\n        keys[0] = 1;\n        return keys;\n    } else {\n        return getKeysUsingCommandTable(cmd,argv,argc,numkeys);\n    }\n}\n\nint *zunionInterGetKeys(struct redisCommand *cmd,robj **argv, int argc, int *numkeys, int flags) {\n    int i, num, *keys;\n    REDIS_NOTUSED(cmd);\n    REDIS_NOTUSED(flags);\n\n    num = atoi(argv[2]->ptr);\n    /* Sanity check. Don't return any key if the command is going to\n     * reply with syntax error. */\n    if (num > (argc-3)) {\n        *numkeys = 0;\n        return NULL;\n    }\n    keys = zmalloc(sizeof(int)*num);\n    for (i = 0; i < num; i++) keys[i] = 3+i;\n    *numkeys = num;\n    return keys;\n}\n"
  },
  {
    "path": "extern/deprecated/redis-2.8.21/src/debug.c",
    "content": "/*\n * Copyright (c) 2009-2012, Salvatore Sanfilippo <antirez at gmail dot com>\n * All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions are met:\n *\n *   * Redistributions of source code must retain the above copyright notice,\n *     this list of conditions and the following disclaimer.\n *   * Redistributions in binary form must reproduce the above copyright\n *     notice, this list of conditions and the following disclaimer in the\n *     documentation and/or other materials provided with the distribution.\n *   * Neither the name of Redis nor the names of its contributors may be used\n *     to endorse or promote products derived from this software without\n *     specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\"\n * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\n * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE\n * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR\n * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF\n * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS\n * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN\n * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)\n * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE\n * POSSIBILITY OF SUCH DAMAGE.\n */\n\n#include \"redis.h\"\n#include \"sha1.h\"   /* SHA1 is used for DEBUG DIGEST */\n#include \"crc64.h\"\n\n#include <arpa/inet.h>\n#include <signal.h>\n\n#ifdef HAVE_BACKTRACE\n#include <execinfo.h>\n#include <ucontext.h>\n#include <fcntl.h>\n#include \"bio.h\"\n#endif /* HAVE_BACKTRACE */\n\n#ifdef __CYGWIN__\n#ifndef SA_ONSTACK\n#define SA_ONSTACK 0x08000000\n#endif\n#endif\n\n/* ================================= Debugging ============================== */\n\n/* Compute the sha1 of string at 's' with 'len' bytes long.\n * The SHA1 is then xored against the string pointed by digest.\n * Since xor is commutative, this operation is used in order to\n * \"add\" digests relative to unordered elements.\n *\n * So digest(a,b,c,d) will be the same of digest(b,a,c,d) */\nvoid xorDigest(unsigned char *digest, void *ptr, size_t len) {\n    SHA1_CTX ctx;\n    unsigned char hash[20], *s = ptr;\n    int j;\n\n    SHA1Init(&ctx);\n    SHA1Update(&ctx,s,len);\n    SHA1Final(hash,&ctx);\n\n    for (j = 0; j < 20; j++)\n        digest[j] ^= hash[j];\n}\n\nvoid xorObjectDigest(unsigned char *digest, robj *o) {\n    o = getDecodedObject(o);\n    xorDigest(digest,o->ptr,sdslen(o->ptr));\n    decrRefCount(o);\n}\n\n/* This function instead of just computing the SHA1 and xoring it\n * against digest, also perform the digest of \"digest\" itself and\n * replace the old value with the new one.\n *\n * So the final digest will be:\n *\n * digest = SHA1(digest xor SHA1(data))\n *\n * This function is used every time we want to preserve the order so\n * that digest(a,b,c,d) will be different than digest(b,c,d,a)\n *\n * Also note that mixdigest(\"foo\") followed by mixdigest(\"bar\")\n * will lead to a different digest compared to \"fo\", \"obar\".\n */\nvoid mixDigest(unsigned char *digest, void *ptr, size_t len) {\n    SHA1_CTX ctx;\n    char *s = ptr;\n\n    xorDigest(digest,s,len);\n    SHA1Init(&ctx);\n    SHA1Update(&ctx,digest,20);\n    SHA1Final(digest,&ctx);\n}\n\nvoid mixObjectDigest(unsigned char *digest, robj *o) {\n    o = getDecodedObject(o);\n    mixDigest(digest,o->ptr,sdslen(o->ptr));\n    decrRefCount(o);\n}\n\n/* Compute the dataset digest. Since keys, sets elements, hashes elements\n * are not ordered, we use a trick: every aggregate digest is the xor\n * of the digests of their elements. This way the order will not change\n * the result. For list instead we use a feedback entering the output digest\n * as input in order to ensure that a different ordered list will result in\n * a different digest. */\nvoid computeDatasetDigest(unsigned char *final) {\n    unsigned char digest[20];\n    char buf[128];\n    dictIterator *di = NULL;\n    dictEntry *de;\n    int j;\n    uint32_t aux;\n\n    memset(final,0,20); /* Start with a clean result */\n\n    for (j = 0; j < server.dbnum; j++) {\n        redisDb *db = server.db+j;\n\n        if (dictSize(db->dict) == 0) continue;\n        di = dictGetIterator(db->dict);\n\n        /* hash the DB id, so the same dataset moved in a different\n         * DB will lead to a different digest */\n        aux = htonl(j);\n        mixDigest(final,&aux,sizeof(aux));\n\n        /* Iterate this DB writing every entry */\n        while((de = dictNext(di)) != NULL) {\n            sds key;\n            robj *keyobj, *o;\n            long long expiretime;\n\n            memset(digest,0,20); /* This key-val digest */\n            key = dictGetKey(de);\n            keyobj = createStringObject(key,sdslen(key));\n\n            mixDigest(digest,key,sdslen(key));\n\n            o = dictGetVal(de);\n\n            aux = htonl(o->type);\n            mixDigest(digest,&aux,sizeof(aux));\n            expiretime = getExpire(db,keyobj);\n\n            /* Save the key and associated value */\n            if (o->type == REDIS_STRING) {\n                mixObjectDigest(digest,o);\n            } else if (o->type == REDIS_LIST) {\n                listTypeIterator *li = listTypeInitIterator(o,0,REDIS_TAIL);\n                listTypeEntry entry;\n                while(listTypeNext(li,&entry)) {\n                    robj *eleobj = listTypeGet(&entry);\n                    mixObjectDigest(digest,eleobj);\n                    decrRefCount(eleobj);\n                }\n                listTypeReleaseIterator(li);\n            } else if (o->type == REDIS_SET) {\n                setTypeIterator *si = setTypeInitIterator(o);\n                robj *ele;\n                while((ele = setTypeNextObject(si)) != NULL) {\n                    xorObjectDigest(digest,ele);\n                    decrRefCount(ele);\n                }\n                setTypeReleaseIterator(si);\n            } else if (o->type == REDIS_ZSET) {\n                unsigned char eledigest[20];\n\n                if (o->encoding == REDIS_ENCODING_ZIPLIST) {\n                    unsigned char *zl = o->ptr;\n                    unsigned char *eptr, *sptr;\n                    unsigned char *vstr;\n                    unsigned int vlen;\n                    long long vll;\n                    double score;\n\n                    eptr = ziplistIndex(zl,0);\n                    redisAssert(eptr != NULL);\n                    sptr = ziplistNext(zl,eptr);\n                    redisAssert(sptr != NULL);\n\n                    while (eptr != NULL) {\n                        redisAssert(ziplistGet(eptr,&vstr,&vlen,&vll));\n                        score = zzlGetScore(sptr);\n\n                        memset(eledigest,0,20);\n                        if (vstr != NULL) {\n                            mixDigest(eledigest,vstr,vlen);\n                        } else {\n                            ll2string(buf,sizeof(buf),vll);\n                            mixDigest(eledigest,buf,strlen(buf));\n                        }\n\n                        snprintf(buf,sizeof(buf),\"%.17g\",score);\n                        mixDigest(eledigest,buf,strlen(buf));\n                        xorDigest(digest,eledigest,20);\n                        zzlNext(zl,&eptr,&sptr);\n                    }\n                } else if (o->encoding == REDIS_ENCODING_SKIPLIST) {\n                    zset *zs = o->ptr;\n                    dictIterator *di = dictGetIterator(zs->dict);\n                    dictEntry *de;\n\n                    while((de = dictNext(di)) != NULL) {\n                        robj *eleobj = dictGetKey(de);\n                        double *score = dictGetVal(de);\n\n                        snprintf(buf,sizeof(buf),\"%.17g\",*score);\n                        memset(eledigest,0,20);\n                        mixObjectDigest(eledigest,eleobj);\n                        mixDigest(eledigest,buf,strlen(buf));\n                        xorDigest(digest,eledigest,20);\n                    }\n                    dictReleaseIterator(di);\n                } else {\n                    redisPanic(\"Unknown sorted set encoding\");\n                }\n            } else if (o->type == REDIS_HASH) {\n                hashTypeIterator *hi;\n                robj *obj;\n\n                hi = hashTypeInitIterator(o);\n                while (hashTypeNext(hi) != REDIS_ERR) {\n                    unsigned char eledigest[20];\n\n                    memset(eledigest,0,20);\n                    obj = hashTypeCurrentObject(hi,REDIS_HASH_KEY);\n                    mixObjectDigest(eledigest,obj);\n                    decrRefCount(obj);\n                    obj = hashTypeCurrentObject(hi,REDIS_HASH_VALUE);\n                    mixObjectDigest(eledigest,obj);\n                    decrRefCount(obj);\n                    xorDigest(digest,eledigest,20);\n                }\n                hashTypeReleaseIterator(hi);\n            } else {\n                redisPanic(\"Unknown object type\");\n            }\n            /* If the key has an expire, add it to the mix */\n            if (expiretime != -1) xorDigest(digest,\"!!expire!!\",10);\n            /* We can finally xor the key-val digest to the final digest */\n            xorDigest(final,digest,20);\n            decrRefCount(keyobj);\n        }\n        dictReleaseIterator(di);\n    }\n}\n\nvoid debugCommand(redisClient *c) {\n    if (!strcasecmp(c->argv[1]->ptr,\"segfault\")) {\n        *((char*)-1) = 'x';\n    } else if (!strcasecmp(c->argv[1]->ptr,\"oom\")) {\n        void *ptr = zmalloc(ULONG_MAX); /* Should trigger an out of memory. */\n        zfree(ptr);\n        addReply(c,shared.ok);\n    } else if (!strcasecmp(c->argv[1]->ptr,\"assert\")) {\n        if (c->argc >= 3) c->argv[2] = tryObjectEncoding(c->argv[2]);\n        redisAssertWithInfo(c,c->argv[0],1 == 2);\n    } else if (!strcasecmp(c->argv[1]->ptr,\"reload\")) {\n        if (rdbSave(server.rdb_filename) != REDIS_OK) {\n            addReply(c,shared.err);\n            return;\n        }\n        emptyDb(NULL);\n        if (rdbLoad(server.rdb_filename) != REDIS_OK) {\n            addReplyError(c,\"Error trying to load the RDB dump\");\n            return;\n        }\n        redisLog(REDIS_WARNING,\"DB reloaded by DEBUG RELOAD\");\n        addReply(c,shared.ok);\n    } else if (!strcasecmp(c->argv[1]->ptr,\"loadaof\")) {\n        emptyDb(NULL);\n        if (loadAppendOnlyFile(server.aof_filename) != REDIS_OK) {\n            addReply(c,shared.err);\n            return;\n        }\n        server.dirty = 0; /* Prevent AOF / replication */\n        redisLog(REDIS_WARNING,\"Append Only File loaded by DEBUG LOADAOF\");\n        addReply(c,shared.ok);\n    } else if (!strcasecmp(c->argv[1]->ptr,\"object\") && c->argc == 3) {\n        dictEntry *de;\n        robj *val;\n        char *strenc;\n\n        if ((de = dictFind(c->db->dict,c->argv[2]->ptr)) == NULL) {\n            addReply(c,shared.nokeyerr);\n            return;\n        }\n        val = dictGetVal(de);\n        strenc = strEncoding(val->encoding);\n\n        addReplyStatusFormat(c,\n            \"Value at:%p refcount:%d \"\n            \"encoding:%s serializedlength:%lld \"\n            \"lru:%d lru_seconds_idle:%lu\",\n            (void*)val, val->refcount,\n            strenc, (long long) rdbSavedObjectLen(val),\n            val->lru, estimateObjectIdleTime(val));\n    } else if (!strcasecmp(c->argv[1]->ptr,\"sdslen\") && c->argc == 3) {\n        dictEntry *de;\n        robj *val;\n        sds key;\n\n        if ((de = dictFind(c->db->dict,c->argv[2]->ptr)) == NULL) {\n            addReply(c,shared.nokeyerr);\n            return;\n        }\n        val = dictGetVal(de);\n        key = dictGetKey(de);\n\n        if (val->type != REDIS_STRING || val->encoding != REDIS_ENCODING_RAW) {\n            addReplyError(c,\"Not an sds encoded string.\");\n        } else {\n            addReplyStatusFormat(c,\n                \"key_sds_len:%lld, key_sds_avail:%lld, \"\n                \"val_sds_len:%lld, val_sds_avail:%lld\",\n                (long long) sdslen(key),\n                (long long) sdsavail(key),\n                (long long) sdslen(val->ptr),\n                (long long) sdsavail(val->ptr));\n        }\n    } else if (!strcasecmp(c->argv[1]->ptr,\"populate\") &&\n               (c->argc == 3 || c->argc == 4)) {\n        long keys, j;\n        robj *key, *val;\n        char buf[128];\n\n        if (getLongFromObjectOrReply(c, c->argv[2], &keys, NULL) != REDIS_OK)\n            return;\n        dictExpand(c->db->dict,keys);\n        for (j = 0; j < keys; j++) {\n            snprintf(buf,sizeof(buf),\"%s:%lu\",\n                (c->argc == 3) ? \"key\" : (char*)c->argv[3]->ptr, j);\n            key = createStringObject(buf,strlen(buf));\n            if (lookupKeyRead(c->db,key) != NULL) {\n                decrRefCount(key);\n                continue;\n            }\n            snprintf(buf,sizeof(buf),\"value:%lu\",j);\n            val = createStringObject(buf,strlen(buf));\n            dbAdd(c->db,key,val);\n            decrRefCount(key);\n        }\n        addReply(c,shared.ok);\n    } else if (!strcasecmp(c->argv[1]->ptr,\"digest\") && c->argc == 2) {\n        unsigned char digest[20];\n        sds d = sdsempty();\n        int j;\n\n        computeDatasetDigest(digest);\n        for (j = 0; j < 20; j++)\n            d = sdscatprintf(d, \"%02x\",digest[j]);\n        addReplyStatus(c,d);\n        sdsfree(d);\n    } else if (!strcasecmp(c->argv[1]->ptr,\"sleep\") && c->argc == 3) {\n        double dtime = strtod(c->argv[2]->ptr,NULL);\n        long long utime = dtime*1000000;\n        struct timespec tv;\n\n        tv.tv_sec = utime / 1000000;\n        tv.tv_nsec = (utime % 1000000) * 1000;\n        nanosleep(&tv, NULL);\n        addReply(c,shared.ok);\n    } else if (!strcasecmp(c->argv[1]->ptr,\"set-active-expire\") &&\n               c->argc == 3)\n    {\n        server.active_expire_enabled = atoi(c->argv[2]->ptr);\n        addReply(c,shared.ok);\n    } else if (!strcasecmp(c->argv[1]->ptr,\"error\") && c->argc == 3) {\n        sds errstr = sdsnewlen(\"-\",1);\n\n        errstr = sdscatsds(errstr,c->argv[2]->ptr);\n        errstr = sdsmapchars(errstr,\"\\n\\r\",\"  \",2); /* no newlines in errors. */\n        errstr = sdscatlen(errstr,\"\\r\\n\",2);\n        addReplySds(c,errstr);\n    } else {\n        addReplyErrorFormat(c, \"Unknown DEBUG subcommand or wrong number of arguments for '%s'\",\n            (char*)c->argv[1]->ptr);\n    }\n}\n\n/* =========================== Crash handling  ============================== */\n\nvoid _redisAssert(char *estr, char *file, int line) {\n    bugReportStart();\n    redisLog(REDIS_WARNING,\"=== ASSERTION FAILED ===\");\n    redisLog(REDIS_WARNING,\"==> %s:%d '%s' is not true\",file,line,estr);\n#ifdef HAVE_BACKTRACE\n    server.assert_failed = estr;\n    server.assert_file = file;\n    server.assert_line = line;\n    redisLog(REDIS_WARNING,\"(forcing SIGSEGV to print the bug report.)\");\n#endif\n    *((char*)-1) = 'x';\n}\n\nvoid _redisAssertPrintClientInfo(redisClient *c) {\n    int j;\n\n    bugReportStart();\n    redisLog(REDIS_WARNING,\"=== ASSERTION FAILED CLIENT CONTEXT ===\");\n    redisLog(REDIS_WARNING,\"client->flags = %d\", c->flags);\n    redisLog(REDIS_WARNING,\"client->fd = %d\", c->fd);\n    redisLog(REDIS_WARNING,\"client->argc = %d\", c->argc);\n    for (j=0; j < c->argc; j++) {\n        char buf[128];\n        char *arg;\n\n        if (c->argv[j]->type == REDIS_STRING &&\n            c->argv[j]->encoding == REDIS_ENCODING_RAW)\n        {\n            arg = (char*) c->argv[j]->ptr;\n        } else {\n            snprintf(buf,sizeof(buf),\"Object type: %d, encoding: %d\",\n                c->argv[j]->type, c->argv[j]->encoding);\n            arg = buf;\n        }\n        redisLog(REDIS_WARNING,\"client->argv[%d] = \\\"%s\\\" (refcount: %d)\",\n            j, arg, c->argv[j]->refcount);\n    }\n}\n\nvoid redisLogObjectDebugInfo(robj *o) {\n    redisLog(REDIS_WARNING,\"Object type: %d\", o->type);\n    redisLog(REDIS_WARNING,\"Object encoding: %d\", o->encoding);\n    redisLog(REDIS_WARNING,\"Object refcount: %d\", o->refcount);\n    if (o->type == REDIS_STRING && o->encoding == REDIS_ENCODING_RAW) {\n        redisLog(REDIS_WARNING,\"Object raw string len: %zu\", sdslen(o->ptr));\n        if (sdslen(o->ptr) < 4096) {\n            sds repr = sdscatrepr(sdsempty(),o->ptr,sdslen(o->ptr));\n            redisLog(REDIS_WARNING,\"Object raw string content: %s\", repr);\n            sdsfree(repr);\n        }\n    } else if (o->type == REDIS_LIST) {\n        redisLog(REDIS_WARNING,\"List length: %d\", (int) listTypeLength(o));\n    } else if (o->type == REDIS_SET) {\n        redisLog(REDIS_WARNING,\"Set size: %d\", (int) setTypeSize(o));\n    } else if (o->type == REDIS_HASH) {\n        redisLog(REDIS_WARNING,\"Hash size: %d\", (int) hashTypeLength(o));\n    } else if (o->type == REDIS_ZSET) {\n        redisLog(REDIS_WARNING,\"Sorted set size: %d\", (int) zsetLength(o));\n        if (o->encoding == REDIS_ENCODING_SKIPLIST)\n            redisLog(REDIS_WARNING,\"Skiplist level: %d\", (int) ((zset*)o->ptr)->zsl->level);\n    }\n}\n\nvoid _redisAssertPrintObject(robj *o) {\n    bugReportStart();\n    redisLog(REDIS_WARNING,\"=== ASSERTION FAILED OBJECT CONTEXT ===\");\n    redisLogObjectDebugInfo(o);\n}\n\nvoid _redisAssertWithInfo(redisClient *c, robj *o, char *estr, char *file, int line) {\n    if (c) _redisAssertPrintClientInfo(c);\n    if (o) _redisAssertPrintObject(o);\n    _redisAssert(estr,file,line);\n}\n\nvoid _redisPanic(char *msg, char *file, int line) {\n    bugReportStart();\n    redisLog(REDIS_WARNING,\"------------------------------------------------\");\n    redisLog(REDIS_WARNING,\"!!! Software Failure. Press left mouse button to continue\");\n    redisLog(REDIS_WARNING,\"Guru Meditation: %s #%s:%d\",msg,file,line);\n#ifdef HAVE_BACKTRACE\n    redisLog(REDIS_WARNING,\"(forcing SIGSEGV in order to print the stack trace)\");\n#endif\n    redisLog(REDIS_WARNING,\"------------------------------------------------\");\n    *((char*)-1) = 'x';\n}\n\nvoid bugReportStart(void) {\n    if (server.bug_report_start == 0) {\n        redisLog(REDIS_WARNING,\n            \"\\n\\n=== REDIS BUG REPORT START: Cut & paste starting from here ===\");\n        server.bug_report_start = 1;\n    }\n}\n\n#ifdef HAVE_BACKTRACE\nstatic void *getMcontextEip(ucontext_t *uc) {\n#if defined(__APPLE__) && !defined(MAC_OS_X_VERSION_10_6)\n    /* OSX < 10.6 */\n    #if defined(__x86_64__)\n    return (void*) uc->uc_mcontext->__ss.__rip;\n    #elif defined(__i386__)\n    return (void*) uc->uc_mcontext->__ss.__eip;\n    #else\n    return (void*) uc->uc_mcontext->__ss.__srr0;\n    #endif\n#elif defined(__APPLE__) && defined(MAC_OS_X_VERSION_10_6)\n    /* OSX >= 10.6 */\n    #if defined(_STRUCT_X86_THREAD_STATE64) && !defined(__i386__)\n    return (void*) uc->uc_mcontext->__ss.__rip;\n    #else\n    return (void*) uc->uc_mcontext->__ss.__eip;\n    #endif\n#elif defined(__linux__)\n    /* Linux */\n    #if defined(__i386__)\n    return (void*) uc->uc_mcontext.gregs[14]; /* Linux 32 */\n    #elif defined(__X86_64__) || defined(__x86_64__)\n    return (void*) uc->uc_mcontext.gregs[16]; /* Linux 64 */\n    #elif defined(__ia64__) /* Linux IA64 */\n    return (void*) uc->uc_mcontext.sc_ip;\n    #endif\n#else\n    return NULL;\n#endif\n}\n\nvoid logStackContent(void **sp) {\n    int i;\n    for (i = 15; i >= 0; i--) {\n        unsigned long addr = (unsigned long) sp+i;\n        unsigned long val = (unsigned long) sp[i];\n\n        if (sizeof(long) == 4)\n            redisLog(REDIS_WARNING, \"(%08lx) -> %08lx\", addr, val);\n        else\n            redisLog(REDIS_WARNING, \"(%016lx) -> %016lx\", addr, val);\n    }\n}\n\nvoid logRegisters(ucontext_t *uc) {\n    redisLog(REDIS_WARNING, \"--- REGISTERS\");\n\n/* OSX */\n#if defined(__APPLE__) && defined(MAC_OS_X_VERSION_10_6)\n  /* OSX AMD64 */\n    #if defined(_STRUCT_X86_THREAD_STATE64) && !defined(__i386__)\n    redisLog(REDIS_WARNING,\n    \"\\n\"\n    \"RAX:%016lx RBX:%016lx\\nRCX:%016lx RDX:%016lx\\n\"\n    \"RDI:%016lx RSI:%016lx\\nRBP:%016lx RSP:%016lx\\n\"\n    \"R8 :%016lx R9 :%016lx\\nR10:%016lx R11:%016lx\\n\"\n    \"R12:%016lx R13:%016lx\\nR14:%016lx R15:%016lx\\n\"\n    \"RIP:%016lx EFL:%016lx\\nCS :%016lx FS:%016lx  GS:%016lx\",\n        (unsigned long) uc->uc_mcontext->__ss.__rax,\n        (unsigned long) uc->uc_mcontext->__ss.__rbx,\n        (unsigned long) uc->uc_mcontext->__ss.__rcx,\n        (unsigned long) uc->uc_mcontext->__ss.__rdx,\n        (unsigned long) uc->uc_mcontext->__ss.__rdi,\n        (unsigned long) uc->uc_mcontext->__ss.__rsi,\n        (unsigned long) uc->uc_mcontext->__ss.__rbp,\n        (unsigned long) uc->uc_mcontext->__ss.__rsp,\n        (unsigned long) uc->uc_mcontext->__ss.__r8,\n        (unsigned long) uc->uc_mcontext->__ss.__r9,\n        (unsigned long) uc->uc_mcontext->__ss.__r10,\n        (unsigned long) uc->uc_mcontext->__ss.__r11,\n        (unsigned long) uc->uc_mcontext->__ss.__r12,\n        (unsigned long) uc->uc_mcontext->__ss.__r13,\n        (unsigned long) uc->uc_mcontext->__ss.__r14,\n        (unsigned long) uc->uc_mcontext->__ss.__r15,\n        (unsigned long) uc->uc_mcontext->__ss.__rip,\n        (unsigned long) uc->uc_mcontext->__ss.__rflags,\n        (unsigned long) uc->uc_mcontext->__ss.__cs,\n        (unsigned long) uc->uc_mcontext->__ss.__fs,\n        (unsigned long) uc->uc_mcontext->__ss.__gs\n    );\n    logStackContent((void**)uc->uc_mcontext->__ss.__rsp);\n    #else\n    /* OSX x86 */\n    redisLog(REDIS_WARNING,\n    \"\\n\"\n    \"EAX:%08lx EBX:%08lx ECX:%08lx EDX:%08lx\\n\"\n    \"EDI:%08lx ESI:%08lx EBP:%08lx ESP:%08lx\\n\"\n    \"SS:%08lx  EFL:%08lx EIP:%08lx CS :%08lx\\n\"\n    \"DS:%08lx  ES:%08lx  FS :%08lx GS :%08lx\",\n        (unsigned long) uc->uc_mcontext->__ss.__eax,\n        (unsigned long) uc->uc_mcontext->__ss.__ebx,\n        (unsigned long) uc->uc_mcontext->__ss.__ecx,\n        (unsigned long) uc->uc_mcontext->__ss.__edx,\n        (unsigned long) uc->uc_mcontext->__ss.__edi,\n        (unsigned long) uc->uc_mcontext->__ss.__esi,\n        (unsigned long) uc->uc_mcontext->__ss.__ebp,\n        (unsigned long) uc->uc_mcontext->__ss.__esp,\n        (unsigned long) uc->uc_mcontext->__ss.__ss,\n        (unsigned long) uc->uc_mcontext->__ss.__eflags,\n        (unsigned long) uc->uc_mcontext->__ss.__eip,\n        (unsigned long) uc->uc_mcontext->__ss.__cs,\n        (unsigned long) uc->uc_mcontext->__ss.__ds,\n        (unsigned long) uc->uc_mcontext->__ss.__es,\n        (unsigned long) uc->uc_mcontext->__ss.__fs,\n        (unsigned long) uc->uc_mcontext->__ss.__gs\n    );\n    logStackContent((void**)uc->uc_mcontext->__ss.__esp);\n    #endif\n/* Linux */\n#elif defined(__linux__)\n    /* Linux x86 */\n    #if defined(__i386__)\n    redisLog(REDIS_WARNING,\n    \"\\n\"\n    \"EAX:%08lx EBX:%08lx ECX:%08lx EDX:%08lx\\n\"\n    \"EDI:%08lx ESI:%08lx EBP:%08lx ESP:%08lx\\n\"\n    \"SS :%08lx EFL:%08lx EIP:%08lx CS:%08lx\\n\"\n    \"DS :%08lx ES :%08lx FS :%08lx GS:%08lx\",\n        (unsigned long) uc->uc_mcontext.gregs[11],\n        (unsigned long) uc->uc_mcontext.gregs[8],\n        (unsigned long) uc->uc_mcontext.gregs[10],\n        (unsigned long) uc->uc_mcontext.gregs[9],\n        (unsigned long) uc->uc_mcontext.gregs[4],\n        (unsigned long) uc->uc_mcontext.gregs[5],\n        (unsigned long) uc->uc_mcontext.gregs[6],\n        (unsigned long) uc->uc_mcontext.gregs[7],\n        (unsigned long) uc->uc_mcontext.gregs[18],\n        (unsigned long) uc->uc_mcontext.gregs[17],\n        (unsigned long) uc->uc_mcontext.gregs[14],\n        (unsigned long) uc->uc_mcontext.gregs[15],\n        (unsigned long) uc->uc_mcontext.gregs[3],\n        (unsigned long) uc->uc_mcontext.gregs[2],\n        (unsigned long) uc->uc_mcontext.gregs[1],\n        (unsigned long) uc->uc_mcontext.gregs[0]\n    );\n    logStackContent((void**)uc->uc_mcontext.gregs[7]);\n    #elif defined(__X86_64__) || defined(__x86_64__)\n    /* Linux AMD64 */\n    redisLog(REDIS_WARNING,\n    \"\\n\"\n    \"RAX:%016lx RBX:%016lx\\nRCX:%016lx RDX:%016lx\\n\"\n    \"RDI:%016lx RSI:%016lx\\nRBP:%016lx RSP:%016lx\\n\"\n    \"R8 :%016lx R9 :%016lx\\nR10:%016lx R11:%016lx\\n\"\n    \"R12:%016lx R13:%016lx\\nR14:%016lx R15:%016lx\\n\"\n    \"RIP:%016lx EFL:%016lx\\nCSGSFS:%016lx\",\n        (unsigned long) uc->uc_mcontext.gregs[13],\n        (unsigned long) uc->uc_mcontext.gregs[11],\n        (unsigned long) uc->uc_mcontext.gregs[14],\n        (unsigned long) uc->uc_mcontext.gregs[12],\n        (unsigned long) uc->uc_mcontext.gregs[8],\n        (unsigned long) uc->uc_mcontext.gregs[9],\n        (unsigned long) uc->uc_mcontext.gregs[10],\n        (unsigned long) uc->uc_mcontext.gregs[15],\n        (unsigned long) uc->uc_mcontext.gregs[0],\n        (unsigned long) uc->uc_mcontext.gregs[1],\n        (unsigned long) uc->uc_mcontext.gregs[2],\n        (unsigned long) uc->uc_mcontext.gregs[3],\n        (unsigned long) uc->uc_mcontext.gregs[4],\n        (unsigned long) uc->uc_mcontext.gregs[5],\n        (unsigned long) uc->uc_mcontext.gregs[6],\n        (unsigned long) uc->uc_mcontext.gregs[7],\n        (unsigned long) uc->uc_mcontext.gregs[16],\n        (unsigned long) uc->uc_mcontext.gregs[17],\n        (unsigned long) uc->uc_mcontext.gregs[18]\n    );\n    logStackContent((void**)uc->uc_mcontext.gregs[15]);\n    #endif\n#else\n    redisLog(REDIS_WARNING,\n        \"  Dumping of registers not supported for this OS/arch\");\n#endif\n}\n\n/* Logs the stack trace using the backtrace() call. This function is designed\n * to be called from signal handlers safely. */\nvoid logStackTrace(ucontext_t *uc) {\n    void *trace[100];\n    int trace_size = 0, fd;\n    int log_to_stdout = server.logfile[0] == '\\0';\n\n    /* Open the log file in append mode. */\n    fd = log_to_stdout ?\n        STDOUT_FILENO :\n        open(server.logfile, O_APPEND|O_CREAT|O_WRONLY, 0644);\n    if (fd == -1) return;\n\n    /* Generate the stack trace */\n    trace_size = backtrace(trace, 100);\n\n    /* overwrite sigaction with caller's address */\n    if (getMcontextEip(uc) != NULL)\n        trace[1] = getMcontextEip(uc);\n\n    /* Write symbols to log file */\n    backtrace_symbols_fd(trace, trace_size, fd);\n\n    /* Cleanup */\n    if (!log_to_stdout) close(fd);\n}\n\n/* Log information about the \"current\" client, that is, the client that is\n * currently being served by Redis. May be NULL if Redis is not serving a\n * client right now. */\nvoid logCurrentClient(void) {\n    if (server.current_client == NULL) return;\n\n    redisClient *cc = server.current_client;\n    sds client;\n    int j;\n\n    redisLog(REDIS_WARNING, \"--- CURRENT CLIENT INFO\");\n    client = catClientInfoString(sdsempty(),cc);\n    redisLog(REDIS_WARNING,\"client: %s\", client);\n    sdsfree(client);\n    for (j = 0; j < cc->argc; j++) {\n        robj *decoded;\n\n        decoded = getDecodedObject(cc->argv[j]);\n        redisLog(REDIS_WARNING,\"argv[%d]: '%s'\", j, (char*)decoded->ptr);\n        decrRefCount(decoded);\n    }\n    /* Check if the first argument, usually a key, is found inside the\n     * selected DB, and if so print info about the associated object. */\n    if (cc->argc >= 1) {\n        robj *val, *key;\n        dictEntry *de;\n\n        key = getDecodedObject(cc->argv[1]);\n        de = dictFind(cc->db->dict, key->ptr);\n        if (de) {\n            val = dictGetVal(de);\n            redisLog(REDIS_WARNING,\"key '%s' found in DB containing the following object:\", (char*)key->ptr);\n            redisLogObjectDebugInfo(val);\n        }\n        decrRefCount(key);\n    }\n}\n\n#if defined(HAVE_PROC_MAPS)\nvoid memtest_non_destructive_invert(void *addr, size_t size);\nvoid memtest_non_destructive_swap(void *addr, size_t size);\n#define MEMTEST_MAX_REGIONS 128\n\nint memtest_test_linux_anonymous_maps(void) {\n    FILE *fp = fopen(\"/proc/self/maps\",\"r\");\n    char line[1024];\n    size_t start_addr, end_addr, size;\n    size_t start_vect[MEMTEST_MAX_REGIONS];\n    size_t size_vect[MEMTEST_MAX_REGIONS];\n    int regions = 0, j;\n    uint64_t crc1 = 0, crc2 = 0, crc3 = 0;\n\n    while(fgets(line,sizeof(line),fp) != NULL) {\n        char *start, *end, *p = line;\n\n        start = p;\n        p = strchr(p,'-');\n        if (!p) continue;\n        *p++ = '\\0';\n        end = p;\n        p = strchr(p,' ');\n        if (!p) continue;\n        *p++ = '\\0';\n        if (strstr(p,\"stack\") ||\n            strstr(p,\"vdso\") ||\n            strstr(p,\"vsyscall\")) continue;\n        if (!strstr(p,\"00:00\")) continue;\n        if (!strstr(p,\"rw\")) continue;\n\n        start_addr = strtoul(start,NULL,16);\n        end_addr = strtoul(end,NULL,16);\n        size = end_addr-start_addr;\n\n        start_vect[regions] = start_addr;\n        size_vect[regions] = size;\n        printf(\"Testing %lx %lu\\n\", (unsigned long) start_vect[regions],\n                                    (unsigned long) size_vect[regions]);\n        regions++;\n    }\n\n    /* Test all the regions as an unique sequential region.\n     * 1) Take the CRC64 of the memory region. */\n    for (j = 0; j < regions; j++) {\n        crc1 = crc64(crc1,(void*)start_vect[j],size_vect[j]);\n    }\n\n    /* 2) Invert bits, swap adjacent words, swap again, invert bits.\n     * This is the error amplification step. */\n    for (j = 0; j < regions; j++)\n        memtest_non_destructive_invert((void*)start_vect[j],size_vect[j]);\n    for (j = 0; j < regions; j++)\n        memtest_non_destructive_swap((void*)start_vect[j],size_vect[j]);\n    for (j = 0; j < regions; j++)\n        memtest_non_destructive_swap((void*)start_vect[j],size_vect[j]);\n    for (j = 0; j < regions; j++)\n        memtest_non_destructive_invert((void*)start_vect[j],size_vect[j]);\n\n    /* 3) Take the CRC64 sum again. */\n    for (j = 0; j < regions; j++)\n        crc2 = crc64(crc2,(void*)start_vect[j],size_vect[j]);\n\n    /* 4) Swap + Swap again */\n    for (j = 0; j < regions; j++)\n        memtest_non_destructive_swap((void*)start_vect[j],size_vect[j]);\n    for (j = 0; j < regions; j++)\n        memtest_non_destructive_swap((void*)start_vect[j],size_vect[j]);\n\n    /* 5) Take the CRC64 sum again. */\n    for (j = 0; j < regions; j++)\n        crc3 = crc64(crc3,(void*)start_vect[j],size_vect[j]);\n\n    /* NOTE: It is very important to close the file descriptor only now\n     * because closing it before may result into unmapping of some memory\n     * region that we are testing. */\n    fclose(fp);\n\n    /* If the two CRC are not the same, we trapped a memory error. */\n    return crc1 != crc2 || crc2 != crc3;\n}\n#endif\n\nvoid sigsegvHandler(int sig, siginfo_t *info, void *secret) {\n    ucontext_t *uc = (ucontext_t*) secret;\n    sds infostring, clients;\n    struct sigaction act;\n    REDIS_NOTUSED(info);\n\n    bugReportStart();\n    redisLog(REDIS_WARNING,\n        \"    Redis %s crashed by signal: %d\", REDIS_VERSION, sig);\n    redisLog(REDIS_WARNING,\n        \"    Failed assertion: %s (%s:%d)\", server.assert_failed,\n                        server.assert_file, server.assert_line);\n\n    /* Log the stack trace */\n    redisLog(REDIS_WARNING, \"--- STACK TRACE\");\n    logStackTrace(uc);\n\n    /* Log INFO and CLIENT LIST */\n    redisLog(REDIS_WARNING, \"--- INFO OUTPUT\");\n    infostring = genRedisInfoString(\"all\");\n    infostring = sdscatprintf(infostring, \"hash_init_value: %u\\n\",\n        dictGetHashFunctionSeed());\n    redisLogRaw(REDIS_WARNING, infostring);\n    redisLog(REDIS_WARNING, \"--- CLIENT LIST OUTPUT\");\n    clients = getAllClientsInfoString();\n    redisLogRaw(REDIS_WARNING, clients);\n    sdsfree(infostring);\n    sdsfree(clients);\n\n    /* Log the current client */\n    logCurrentClient();\n\n    /* Log dump of processor registers */\n    logRegisters(uc);\n\n#if defined(HAVE_PROC_MAPS)\n    /* Test memory */\n    redisLog(REDIS_WARNING, \"--- FAST MEMORY TEST\");\n    bioKillThreads();\n    if (memtest_test_linux_anonymous_maps()) {\n        redisLog(REDIS_WARNING,\n            \"!!! MEMORY ERROR DETECTED! Check your memory ASAP !!!\");\n    } else {\n        redisLog(REDIS_WARNING,\n            \"Fast memory test PASSED, however your memory can still be broken. Please run a memory test for several hours if possible.\");\n    }\n#endif\n\n    redisLog(REDIS_WARNING,\n\"\\n=== REDIS BUG REPORT END. Make sure to include from START to END. ===\\n\\n\"\n\"       Please report the crash by opening an issue on github:\\n\\n\"\n\"           http://github.com/antirez/redis/issues\\n\\n\"\n\"  Suspect RAM error? Use redis-server --test-memory to verify it.\\n\\n\"\n);\n    /* free(messages); Don't call free() with possibly corrupted memory. */\n    if (server.daemonize) unlink(server.pidfile);\n\n    /* Make sure we exit with the right signal at the end. So for instance\n     * the core will be dumped if enabled. */\n    sigemptyset (&act.sa_mask);\n    act.sa_flags = SA_NODEFER | SA_ONSTACK | SA_RESETHAND;\n    act.sa_handler = SIG_DFL;\n    sigaction (sig, &act, NULL);\n    kill(getpid(),sig);\n}\n#endif /* HAVE_BACKTRACE */\n\n/* ==================== Logging functions for debugging ===================== */\n\nvoid redisLogHexDump(int level, char *descr, void *value, size_t len) {\n    char buf[65], *b;\n    unsigned char *v = value;\n    char charset[] = \"0123456789abcdef\";\n\n    redisLog(level,\"%s (hexdump):\", descr);\n    b = buf;\n    while(len) {\n        b[0] = charset[(*v)>>4];\n        b[1] = charset[(*v)&0xf];\n        b[2] = '\\0';\n        b += 2;\n        len--;\n        v++;\n        if (b-buf == 64 || len == 0) {\n            redisLogRaw(level|REDIS_LOG_RAW,buf);\n            b = buf;\n        }\n    }\n    redisLogRaw(level|REDIS_LOG_RAW,\"\\n\");\n}\n\n/* =========================== Software Watchdog ============================ */\n#include <sys/time.h>\n\nvoid watchdogSignalHandler(int sig, siginfo_t *info, void *secret) {\n#ifdef HAVE_BACKTRACE\n    ucontext_t *uc = (ucontext_t*) secret;\n#endif\n    REDIS_NOTUSED(info);\n    REDIS_NOTUSED(sig);\n\n    redisLogFromHandler(REDIS_WARNING,\"\\n--- WATCHDOG TIMER EXPIRED ---\");\n#ifdef HAVE_BACKTRACE\n    logStackTrace(uc);\n#else\n    redisLogFromHandler(REDIS_WARNING,\"Sorry: no support for backtrace().\");\n#endif\n    redisLogFromHandler(REDIS_WARNING,\"--------\\n\");\n}\n\n/* Schedule a SIGALRM delivery after the specified period in milliseconds.\n * If a timer is already scheduled, this function will re-schedule it to the\n * specified time. If period is 0 the current timer is disabled. */\nvoid watchdogScheduleSignal(int period) {\n    struct itimerval it;\n\n    /* Will stop the timer if period is 0. */\n    it.it_value.tv_sec = period/1000;\n    it.it_value.tv_usec = (period%1000)*1000;\n    /* Don't automatically restart. */\n    it.it_interval.tv_sec = 0;\n    it.it_interval.tv_usec = 0;\n    setitimer(ITIMER_REAL, &it, NULL);\n}\n\n/* Enable the software watchdog with the specified period in milliseconds. */\nvoid enableWatchdog(int period) {\n    int min_period;\n\n    if (server.watchdog_period == 0) {\n        struct sigaction act;\n\n        /* Watchdog was actually disabled, so we have to setup the signal\n         * handler. */\n        sigemptyset(&act.sa_mask);\n        act.sa_flags = SA_ONSTACK | SA_SIGINFO;\n        act.sa_sigaction = watchdogSignalHandler;\n        sigaction(SIGALRM, &act, NULL);\n    }\n    /* If the configured period is smaller than twice the timer period, it is\n     * too short for the software watchdog to work reliably. Fix it now\n     * if needed. */\n    min_period = (1000/server.hz)*2;\n    if (period < min_period) period = min_period;\n    watchdogScheduleSignal(period); /* Adjust the current timer. */\n    server.watchdog_period = period;\n}\n\n/* Disable the software watchdog. */\nvoid disableWatchdog(void) {\n    struct sigaction act;\n    if (server.watchdog_period == 0) return; /* Already disabled. */\n    watchdogScheduleSignal(0); /* Stop the current timer. */\n\n    /* Set the signal handler to SIG_IGN, this will also remove pending\n     * signals from the queue. */\n    sigemptyset(&act.sa_mask);\n    act.sa_flags = 0;\n    act.sa_handler = SIG_IGN;\n    sigaction(SIGALRM, &act, NULL);\n    server.watchdog_period = 0;\n}\n"
  },
  {
    "path": "extern/deprecated/redis-2.8.21/src/dict.c",
    "content": "/* Hash Tables Implementation.\n *\n * This file implements in memory hash tables with insert/del/replace/find/\n * get-random-element operations. Hash tables will auto resize if needed\n * tables of power of two in size are used, collisions are handled by\n * chaining. See the source code for more information... :)\n *\n * Copyright (c) 2006-2012, Salvatore Sanfilippo <antirez at gmail dot com>\n * All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions are met:\n *\n *   * Redistributions of source code must retain the above copyright notice,\n *     this list of conditions and the following disclaimer.\n *   * Redistributions in binary form must reproduce the above copyright\n *     notice, this list of conditions and the following disclaimer in the\n *     documentation and/or other materials provided with the distribution.\n *   * Neither the name of Redis nor the names of its contributors may be used\n *     to endorse or promote products derived from this software without\n *     specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\"\n * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\n * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE\n * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR\n * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF\n * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS\n * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN\n * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)\n * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE\n * POSSIBILITY OF SUCH DAMAGE.\n */\n\n#include \"fmacros.h\"\n\n#include <stdio.h>\n#include <stdlib.h>\n#include <string.h>\n#include <stdarg.h>\n#include <limits.h>\n#include <sys/time.h>\n#include <ctype.h>\n\n#include \"dict.h\"\n#include \"zmalloc.h\"\n#include \"redisassert.h\"\n\n/* Using dictEnableResize() / dictDisableResize() we make possible to\n * enable/disable resizing of the hash table as needed. This is very important\n * for Redis, as we use copy-on-write and don't want to move too much memory\n * around when there is a child performing saving operations.\n *\n * Note that even when dict_can_resize is set to 0, not all resizes are\n * prevented: a hash table is still allowed to grow if the ratio between\n * the number of elements and the buckets > dict_force_resize_ratio. */\nstatic int dict_can_resize = 1;\nstatic unsigned int dict_force_resize_ratio = 5;\n\n/* -------------------------- private prototypes ---------------------------- */\n\nstatic int _dictExpandIfNeeded(dict *ht);\nstatic unsigned long _dictNextPower(unsigned long size);\nstatic int _dictKeyIndex(dict *ht, const void *key);\nstatic int _dictInit(dict *ht, dictType *type, void *privDataPtr);\n\n/* -------------------------- hash functions -------------------------------- */\n\n/* Thomas Wang's 32 bit Mix Function */\nunsigned int dictIntHashFunction(unsigned int key)\n{\n    key += ~(key << 15);\n    key ^=  (key >> 10);\n    key +=  (key << 3);\n    key ^=  (key >> 6);\n    key += ~(key << 11);\n    key ^=  (key >> 16);\n    return key;\n}\n\nstatic uint32_t dict_hash_function_seed = 5381;\n\nvoid dictSetHashFunctionSeed(uint32_t seed) {\n    dict_hash_function_seed = seed;\n}\n\nuint32_t dictGetHashFunctionSeed(void) {\n    return dict_hash_function_seed;\n}\n\n/* MurmurHash2, by Austin Appleby\n * Note - This code makes a few assumptions about how your machine behaves -\n * 1. We can read a 4-byte value from any address without crashing\n * 2. sizeof(int) == 4\n *\n * And it has a few limitations -\n *\n * 1. It will not work incrementally.\n * 2. It will not produce the same results on little-endian and big-endian\n *    machines.\n */\nunsigned int dictGenHashFunction(const void *key, int len) {\n    /* 'm' and 'r' are mixing constants generated offline.\n     They're not really 'magic', they just happen to work well.  */\n    uint32_t seed = dict_hash_function_seed;\n    const uint32_t m = 0x5bd1e995;\n    const int r = 24;\n\n    /* Initialize the hash to a 'random' value */\n    uint32_t h = seed ^ len;\n\n    /* Mix 4 bytes at a time into the hash */\n    const unsigned char *data = (const unsigned char *)key;\n\n    while(len >= 4) {\n        uint32_t k = *(uint32_t*)data;\n\n        k *= m;\n        k ^= k >> r;\n        k *= m;\n\n        h *= m;\n        h ^= k;\n\n        data += 4;\n        len -= 4;\n    }\n\n    /* Handle the last few bytes of the input array  */\n    switch(len) {\n    case 3: h ^= data[2] << 16;\n    case 2: h ^= data[1] << 8;\n    case 1: h ^= data[0]; h *= m;\n    };\n\n    /* Do a few final mixes of the hash to ensure the last few\n     * bytes are well-incorporated. */\n    h ^= h >> 13;\n    h *= m;\n    h ^= h >> 15;\n\n    return (unsigned int)h;\n}\n\n/* And a case insensitive hash function (based on djb hash) */\nunsigned int dictGenCaseHashFunction(const unsigned char *buf, int len) {\n    unsigned int hash = (unsigned int)dict_hash_function_seed;\n\n    while (len--)\n        hash = ((hash << 5) + hash) + (tolower(*buf++)); /* hash * 33 + c */\n    return hash;\n}\n\n/* ----------------------------- API implementation ------------------------- */\n\n/* Reset a hash table already initialized with ht_init().\n * NOTE: This function should only be called by ht_destroy(). */\nstatic void _dictReset(dictht *ht)\n{\n    ht->table = NULL;\n    ht->size = 0;\n    ht->sizemask = 0;\n    ht->used = 0;\n}\n\n/* Create a new hash table */\ndict *dictCreate(dictType *type,\n        void *privDataPtr)\n{\n    dict *d = zmalloc(sizeof(*d));\n\n    _dictInit(d,type,privDataPtr);\n    return d;\n}\n\n/* Initialize the hash table */\nint _dictInit(dict *d, dictType *type,\n        void *privDataPtr)\n{\n    _dictReset(&d->ht[0]);\n    _dictReset(&d->ht[1]);\n    d->type = type;\n    d->privdata = privDataPtr;\n    d->rehashidx = -1;\n    d->iterators = 0;\n    return DICT_OK;\n}\n\n/* Resize the table to the minimal size that contains all the elements,\n * but with the invariant of a USED/BUCKETS ratio near to <= 1 */\nint dictResize(dict *d)\n{\n    int minimal;\n\n    if (!dict_can_resize || dictIsRehashing(d)) return DICT_ERR;\n    minimal = d->ht[0].used;\n    if (minimal < DICT_HT_INITIAL_SIZE)\n        minimal = DICT_HT_INITIAL_SIZE;\n    return dictExpand(d, minimal);\n}\n\n/* Expand or create the hash table */\nint dictExpand(dict *d, unsigned long size)\n{\n    dictht n; /* the new hash table */\n    unsigned long realsize = _dictNextPower(size);\n\n    /* the size is invalid if it is smaller than the number of\n     * elements already inside the hash table */\n    if (dictIsRehashing(d) || d->ht[0].used > size)\n        return DICT_ERR;\n\n    /* Allocate the new hash table and initialize all pointers to NULL */\n    n.size = realsize;\n    n.sizemask = realsize-1;\n    n.table = zcalloc(realsize*sizeof(dictEntry*));\n    n.used = 0;\n\n    /* Is this the first initialization? If so it's not really a rehashing\n     * we just set the first hash table so that it can accept keys. */\n    if (d->ht[0].table == NULL) {\n        d->ht[0] = n;\n        return DICT_OK;\n    }\n\n    /* Prepare a second hash table for incremental rehashing */\n    d->ht[1] = n;\n    d->rehashidx = 0;\n    return DICT_OK;\n}\n\n/* Performs N steps of incremental rehashing. Returns 1 if there are still\n * keys to move from the old to the new hash table, otherwise 0 is returned.\n * Note that a rehashing step consists in moving a bucket (that may have more\n * than one key as we use chaining) from the old to the new hash table. */\nint dictRehash(dict *d, int n) {\n    if (!dictIsRehashing(d)) return 0;\n\n    while(n--) {\n        dictEntry *de, *nextde;\n\n        /* Check if we already rehashed the whole table... */\n        if (d->ht[0].used == 0) {\n            zfree(d->ht[0].table);\n            d->ht[0] = d->ht[1];\n            _dictReset(&d->ht[1]);\n            d->rehashidx = -1;\n            return 0;\n        }\n\n        /* Note that rehashidx can't overflow as we are sure there are more\n         * elements because ht[0].used != 0 */\n        assert(d->ht[0].size > (unsigned long)d->rehashidx);\n        while(d->ht[0].table[d->rehashidx] == NULL) d->rehashidx++;\n        de = d->ht[0].table[d->rehashidx];\n        /* Move all the keys in this bucket from the old to the new hash HT */\n        while(de) {\n            unsigned int h;\n\n            nextde = de->next;\n            /* Get the index in the new hash table */\n            h = dictHashKey(d, de->key) & d->ht[1].sizemask;\n            de->next = d->ht[1].table[h];\n            d->ht[1].table[h] = de;\n            d->ht[0].used--;\n            d->ht[1].used++;\n            de = nextde;\n        }\n        d->ht[0].table[d->rehashidx] = NULL;\n        d->rehashidx++;\n    }\n    return 1;\n}\n\nlong long timeInMilliseconds(void) {\n    struct timeval tv;\n\n    gettimeofday(&tv,NULL);\n    return (((long long)tv.tv_sec)*1000)+(tv.tv_usec/1000);\n}\n\n/* Rehash for an amount of time between ms milliseconds and ms+1 milliseconds */\nint dictRehashMilliseconds(dict *d, int ms) {\n    long long start = timeInMilliseconds();\n    int rehashes = 0;\n\n    while(dictRehash(d,100)) {\n        rehashes += 100;\n        if (timeInMilliseconds()-start > ms) break;\n    }\n    return rehashes;\n}\n\n/* This function performs just a step of rehashing, and only if there are\n * no safe iterators bound to our hash table. When we have iterators in the\n * middle of a rehashing we can't mess with the two hash tables otherwise\n * some element can be missed or duplicated.\n *\n * This function is called by common lookup or update operations in the\n * dictionary so that the hash table automatically migrates from H1 to H2\n * while it is actively used. */\nstatic void _dictRehashStep(dict *d) {\n    if (d->iterators == 0) dictRehash(d,1);\n}\n\n/* Add an element to the target hash table */\nint dictAdd(dict *d, void *key, void *val)\n{\n    dictEntry *entry = dictAddRaw(d,key);\n\n    if (!entry) return DICT_ERR;\n    dictSetVal(d, entry, val);\n    return DICT_OK;\n}\n\n/* Low level add. This function adds the entry but instead of setting\n * a value returns the dictEntry structure to the user, that will make\n * sure to fill the value field as he wishes.\n *\n * This function is also directly exposed to user API to be called\n * mainly in order to store non-pointers inside the hash value, example:\n *\n * entry = dictAddRaw(dict,mykey);\n * if (entry != NULL) dictSetSignedIntegerVal(entry,1000);\n *\n * Return values:\n *\n * If key already exists NULL is returned.\n * If key was added, the hash entry is returned to be manipulated by the caller.\n */\ndictEntry *dictAddRaw(dict *d, void *key)\n{\n    int index;\n    dictEntry *entry;\n    dictht *ht;\n\n    if (dictIsRehashing(d)) _dictRehashStep(d);\n\n    /* Get the index of the new element, or -1 if\n     * the element already exists. */\n    if ((index = _dictKeyIndex(d, key)) == -1)\n        return NULL;\n\n    /* Allocate the memory and store the new entry */\n    ht = dictIsRehashing(d) ? &d->ht[1] : &d->ht[0];\n    entry = zmalloc(sizeof(*entry));\n    entry->next = ht->table[index];\n    ht->table[index] = entry;\n    ht->used++;\n\n    /* Set the hash entry fields. */\n    dictSetKey(d, entry, key);\n    return entry;\n}\n\n/* Add an element, discarding the old if the key already exists.\n * Return 1 if the key was added from scratch, 0 if there was already an\n * element with such key and dictReplace() just performed a value update\n * operation. */\nint dictReplace(dict *d, void *key, void *val)\n{\n    dictEntry *entry, auxentry;\n\n    /* Try to add the element. If the key\n     * does not exists dictAdd will suceed. */\n    if (dictAdd(d, key, val) == DICT_OK)\n        return 1;\n    /* It already exists, get the entry */\n    entry = dictFind(d, key);\n    /* Set the new value and free the old one. Note that it is important\n     * to do that in this order, as the value may just be exactly the same\n     * as the previous one. In this context, think to reference counting,\n     * you want to increment (set), and then decrement (free), and not the\n     * reverse. */\n    auxentry = *entry;\n    dictSetVal(d, entry, val);\n    dictFreeVal(d, &auxentry);\n    return 0;\n}\n\n/* dictReplaceRaw() is simply a version of dictAddRaw() that always\n * returns the hash entry of the specified key, even if the key already\n * exists and can't be added (in that case the entry of the already\n * existing key is returned.)\n *\n * See dictAddRaw() for more information. */\ndictEntry *dictReplaceRaw(dict *d, void *key) {\n    dictEntry *entry = dictFind(d,key);\n\n    return entry ? entry : dictAddRaw(d,key);\n}\n\n/* Search and remove an element */\nstatic int dictGenericDelete(dict *d, const void *key, int nofree)\n{\n    unsigned int h, idx;\n    dictEntry *he, *prevHe;\n    int table;\n\n    if (d->ht[0].size == 0) return DICT_ERR; /* d->ht[0].table is NULL */\n    if (dictIsRehashing(d)) _dictRehashStep(d);\n    h = dictHashKey(d, key);\n\n    for (table = 0; table <= 1; table++) {\n        idx = h & d->ht[table].sizemask;\n        he = d->ht[table].table[idx];\n        prevHe = NULL;\n        while(he) {\n            if (dictCompareKeys(d, key, he->key)) {\n                /* Unlink the element from the list */\n                if (prevHe)\n                    prevHe->next = he->next;\n                else\n                    d->ht[table].table[idx] = he->next;\n                if (!nofree) {\n                    dictFreeKey(d, he);\n                    dictFreeVal(d, he);\n                }\n                zfree(he);\n                d->ht[table].used--;\n                return DICT_OK;\n            }\n            prevHe = he;\n            he = he->next;\n        }\n        if (!dictIsRehashing(d)) break;\n    }\n    return DICT_ERR; /* not found */\n}\n\nint dictDelete(dict *ht, const void *key) {\n    return dictGenericDelete(ht,key,0);\n}\n\nint dictDeleteNoFree(dict *ht, const void *key) {\n    return dictGenericDelete(ht,key,1);\n}\n\n/* Destroy an entire dictionary */\nint _dictClear(dict *d, dictht *ht, void(callback)(void *)) {\n    unsigned long i;\n\n    /* Free all the elements */\n    for (i = 0; i < ht->size && ht->used > 0; i++) {\n        dictEntry *he, *nextHe;\n\n        if (callback && (i & 65535) == 0) callback(d->privdata);\n\n        if ((he = ht->table[i]) == NULL) continue;\n        while(he) {\n            nextHe = he->next;\n            dictFreeKey(d, he);\n            dictFreeVal(d, he);\n            zfree(he);\n            ht->used--;\n            he = nextHe;\n        }\n    }\n    /* Free the table and the allocated cache structure */\n    zfree(ht->table);\n    /* Re-initialize the table */\n    _dictReset(ht);\n    return DICT_OK; /* never fails */\n}\n\n/* Clear & Release the hash table */\nvoid dictRelease(dict *d)\n{\n    _dictClear(d,&d->ht[0],NULL);\n    _dictClear(d,&d->ht[1],NULL);\n    zfree(d);\n}\n\ndictEntry *dictFind(dict *d, const void *key)\n{\n    dictEntry *he;\n    unsigned int h, idx, table;\n\n    if (d->ht[0].size == 0) return NULL; /* We don't have a table at all */\n    if (dictIsRehashing(d)) _dictRehashStep(d);\n    h = dictHashKey(d, key);\n    for (table = 0; table <= 1; table++) {\n        idx = h & d->ht[table].sizemask;\n        he = d->ht[table].table[idx];\n        while(he) {\n            if (dictCompareKeys(d, key, he->key))\n                return he;\n            he = he->next;\n        }\n        if (!dictIsRehashing(d)) return NULL;\n    }\n    return NULL;\n}\n\nvoid *dictFetchValue(dict *d, const void *key) {\n    dictEntry *he;\n\n    he = dictFind(d,key);\n    return he ? dictGetVal(he) : NULL;\n}\n\n/* A fingerprint is a 64 bit number that represents the state of the dictionary\n * at a given time, it's just a few dict properties xored together.\n * When an unsafe iterator is initialized, we get the dict fingerprint, and check\n * the fingerprint again when the iterator is released.\n * If the two fingerprints are different it means that the user of the iterator\n * performed forbidden operations against the dictionary while iterating. */\nlong long dictFingerprint(dict *d) {\n    long long integers[6], hash = 0;\n    int j;\n\n    integers[0] = (long) d->ht[0].table;\n    integers[1] = d->ht[0].size;\n    integers[2] = d->ht[0].used;\n    integers[3] = (long) d->ht[1].table;\n    integers[4] = d->ht[1].size;\n    integers[5] = d->ht[1].used;\n\n    /* We hash N integers by summing every successive integer with the integer\n     * hashing of the previous sum. Basically:\n     *\n     * Result = hash(hash(hash(int1)+int2)+int3) ...\n     *\n     * This way the same set of integers in a different order will (likely) hash\n     * to a different number. */\n    for (j = 0; j < 6; j++) {\n        hash += integers[j];\n        /* For the hashing step we use Tomas Wang's 64 bit integer hash. */\n        hash = (~hash) + (hash << 21); // hash = (hash << 21) - hash - 1;\n        hash = hash ^ (hash >> 24);\n        hash = (hash + (hash << 3)) + (hash << 8); // hash * 265\n        hash = hash ^ (hash >> 14);\n        hash = (hash + (hash << 2)) + (hash << 4); // hash * 21\n        hash = hash ^ (hash >> 28);\n        hash = hash + (hash << 31);\n    }\n    return hash;\n}\n\ndictIterator *dictGetIterator(dict *d)\n{\n    dictIterator *iter = zmalloc(sizeof(*iter));\n\n    iter->d = d;\n    iter->table = 0;\n    iter->index = -1;\n    iter->safe = 0;\n    iter->entry = NULL;\n    iter->nextEntry = NULL;\n    return iter;\n}\n\ndictIterator *dictGetSafeIterator(dict *d) {\n    dictIterator *i = dictGetIterator(d);\n\n    i->safe = 1;\n    return i;\n}\n\ndictEntry *dictNext(dictIterator *iter)\n{\n    while (1) {\n        if (iter->entry == NULL) {\n            dictht *ht = &iter->d->ht[iter->table];\n            if (iter->index == -1 && iter->table == 0) {\n                if (iter->safe)\n                    iter->d->iterators++;\n                else\n                    iter->fingerprint = dictFingerprint(iter->d);\n            }\n            iter->index++;\n            if (iter->index >= (long) ht->size) {\n                if (dictIsRehashing(iter->d) && iter->table == 0) {\n                    iter->table++;\n                    iter->index = 0;\n                    ht = &iter->d->ht[1];\n                } else {\n                    break;\n                }\n            }\n            iter->entry = ht->table[iter->index];\n        } else {\n            iter->entry = iter->nextEntry;\n        }\n        if (iter->entry) {\n            /* We need to save the 'next' here, the iterator user\n             * may delete the entry we are returning. */\n            iter->nextEntry = iter->entry->next;\n            return iter->entry;\n        }\n    }\n    return NULL;\n}\n\nvoid dictReleaseIterator(dictIterator *iter)\n{\n    if (!(iter->index == -1 && iter->table == 0)) {\n        if (iter->safe)\n            iter->d->iterators--;\n        else\n            assert(iter->fingerprint == dictFingerprint(iter->d));\n    }\n    zfree(iter);\n}\n\n/* Return a random entry from the hash table. Useful to\n * implement randomized algorithms */\ndictEntry *dictGetRandomKey(dict *d)\n{\n    dictEntry *he, *orighe;\n    unsigned int h;\n    int listlen, listele;\n\n    if (dictSize(d) == 0) return NULL;\n    if (dictIsRehashing(d)) _dictRehashStep(d);\n    if (dictIsRehashing(d)) {\n        do {\n            h = random() % (d->ht[0].size+d->ht[1].size);\n            he = (h >= d->ht[0].size) ? d->ht[1].table[h - d->ht[0].size] :\n                                      d->ht[0].table[h];\n        } while(he == NULL);\n    } else {\n        do {\n            h = random() & d->ht[0].sizemask;\n            he = d->ht[0].table[h];\n        } while(he == NULL);\n    }\n\n    /* Now we found a non empty bucket, but it is a linked\n     * list and we need to get a random element from the list.\n     * The only sane way to do so is counting the elements and\n     * select a random index. */\n    listlen = 0;\n    orighe = he;\n    while(he) {\n        he = he->next;\n        listlen++;\n    }\n    listele = random() % listlen;\n    he = orighe;\n    while(listele--) he = he->next;\n    return he;\n}\n\n/* Function to reverse bits. Algorithm from:\n * http://graphics.stanford.edu/~seander/bithacks.html#ReverseParallel */\nstatic unsigned long rev(unsigned long v) {\n    unsigned long s = 8 * sizeof(v); // bit size; must be power of 2\n    unsigned long mask = ~0;\n    while ((s >>= 1) > 0) {\n        mask ^= (mask << s);\n        v = ((v >> s) & mask) | ((v << s) & ~mask);\n    }\n    return v;\n}\n\n/* dictScan() is used to iterate over the elements of a dictionary.\n *\n * Iterating works the following way:\n *\n * 1) Initially you call the function using a cursor (v) value of 0.\n * 2) The function performs one step of the iteration, and returns the\n *    new cursor value you must use in the next call.\n * 3) When the returned cursor is 0, the iteration is complete.\n *\n * The function guarantees all elements present in the\n * dictionary get returned between the start and end of the iteration.\n * However it is possible some elements get returned multiple times.\n *\n * For every element returned, the callback argument 'fn' is\n * called with 'privdata' as first argument and the dictionary entry\n * 'de' as second argument.\n *\n * HOW IT WORKS.\n *\n * The iteration algorithm was designed by Pieter Noordhuis.\n * The main idea is to increment a cursor starting from the higher order\n * bits. That is, instead of incrementing the cursor normally, the bits\n * of the cursor are reversed, then the cursor is incremented, and finally\n * the bits are reversed again.\n *\n * This strategy is needed because the hash table may be resized between\n * iteration calls.\n *\n * dict.c hash tables are always power of two in size, and they\n * use chaining, so the position of an element in a given table is given\n * by computing the bitwise AND between Hash(key) and SIZE-1\n * (where SIZE-1 is always the mask that is equivalent to taking the rest\n *  of the division between the Hash of the key and SIZE).\n *\n * For example if the current hash table size is 16, the mask is\n * (in binary) 1111. The position of a key in the hash table will always be\n * the last four bits of the hash output, and so forth.\n *\n * WHAT HAPPENS IF THE TABLE CHANGES IN SIZE?\n *\n * If the hash table grows, elements can go anywhere in one multiple of\n * the old bucket: for example let's say we already iterated with\n * a 4 bit cursor 1100 (the mask is 1111 because hash table size = 16).\n *\n * If the hash table will be resized to 64 elements, then the new mask will\n * be 111111. The new buckets you obtain by substituting in ??1100\n * with either 0 or 1 can be targeted only by keys we already visited\n * when scanning the bucket 1100 in the smaller hash table.\n *\n * By iterating the higher bits first, because of the inverted counter, the\n * cursor does not need to restart if the table size gets bigger. It will\n * continue iterating using cursors without '1100' at the end, and also\n * without any other combination of the final 4 bits already explored.\n *\n * Similarly when the table size shrinks over time, for example going from\n * 16 to 8, if a combination of the lower three bits (the mask for size 8\n * is 111) were already completely explored, it would not be visited again\n * because we are sure we tried, for example, both 0111 and 1111 (all the\n * variations of the higher bit) so we don't need to test it again.\n *\n * WAIT... YOU HAVE *TWO* TABLES DURING REHASHING!\n *\n * Yes, this is true, but we always iterate the smaller table first, then\n * we test all the expansions of the current cursor into the larger\n * table. For example if the current cursor is 101 and we also have a\n * larger table of size 16, we also test (0)101 and (1)101 inside the larger\n * table. This reduces the problem back to having only one table, where\n * the larger one, if it exists, is just an expansion of the smaller one.\n *\n * LIMITATIONS\n *\n * This iterator is completely stateless, and this is a huge advantage,\n * including no additional memory used.\n *\n * The disadvantages resulting from this design are:\n *\n * 1) It is possible we return elements more than once. However this is usually\n *    easy to deal with in the application level.\n * 2) The iterator must return multiple elements per call, as it needs to always\n *    return all the keys chained in a given bucket, and all the expansions, so\n *    we are sure we don't miss keys moving during rehashing.\n * 3) The reverse cursor is somewhat hard to understand at first, but this\n *    comment is supposed to help.\n */\nunsigned long dictScan(dict *d,\n                       unsigned long v,\n                       dictScanFunction *fn,\n                       void *privdata)\n{\n    dictht *t0, *t1;\n    const dictEntry *de;\n    unsigned long m0, m1;\n\n    if (dictSize(d) == 0) return 0;\n\n    if (!dictIsRehashing(d)) {\n        t0 = &(d->ht[0]);\n        m0 = t0->sizemask;\n\n        /* Emit entries at cursor */\n        de = t0->table[v & m0];\n        while (de) {\n            fn(privdata, de);\n            de = de->next;\n        }\n\n    } else {\n        t0 = &d->ht[0];\n        t1 = &d->ht[1];\n\n        /* Make sure t0 is the smaller and t1 is the bigger table */\n        if (t0->size > t1->size) {\n            t0 = &d->ht[1];\n            t1 = &d->ht[0];\n        }\n\n        m0 = t0->sizemask;\n        m1 = t1->sizemask;\n\n        /* Emit entries at cursor */\n        de = t0->table[v & m0];\n        while (de) {\n            fn(privdata, de);\n            de = de->next;\n        }\n\n        /* Iterate over indices in larger table that are the expansion\n         * of the index pointed to by the cursor in the smaller table */\n        do {\n            /* Emit entries at cursor */\n            de = t1->table[v & m1];\n            while (de) {\n                fn(privdata, de);\n                de = de->next;\n            }\n\n            /* Increment bits not covered by the smaller mask */\n            v = (((v | m0) + 1) & ~m0) | (v & m0);\n\n            /* Continue while bits covered by mask difference is non-zero */\n        } while (v & (m0 ^ m1));\n    }\n\n    /* Set unmasked bits so incrementing the reversed cursor\n     * operates on the masked bits of the smaller table */\n    v |= ~m0;\n\n    /* Increment the reverse cursor */\n    v = rev(v);\n    v++;\n    v = rev(v);\n\n    return v;\n}\n\n/* ------------------------- private functions ------------------------------ */\n\n/* Expand the hash table if needed */\nstatic int _dictExpandIfNeeded(dict *d)\n{\n    /* Incremental rehashing already in progress. Return. */\n    if (dictIsRehashing(d)) return DICT_OK;\n\n    /* If the hash table is empty expand it to the initial size. */\n    if (d->ht[0].size == 0) return dictExpand(d, DICT_HT_INITIAL_SIZE);\n\n    /* If we reached the 1:1 ratio, and we are allowed to resize the hash\n     * table (global setting) or we should avoid it but the ratio between\n     * elements/buckets is over the \"safe\" threshold, we resize doubling\n     * the number of buckets. */\n    if (d->ht[0].used >= d->ht[0].size &&\n        (dict_can_resize ||\n         d->ht[0].used/d->ht[0].size > dict_force_resize_ratio))\n    {\n        return dictExpand(d, d->ht[0].used*2);\n    }\n    return DICT_OK;\n}\n\n/* Our hash table capability is a power of two */\nstatic unsigned long _dictNextPower(unsigned long size)\n{\n    unsigned long i = DICT_HT_INITIAL_SIZE;\n\n    if (size >= LONG_MAX) return LONG_MAX;\n    while(1) {\n        if (i >= size)\n            return i;\n        i *= 2;\n    }\n}\n\n/* Returns the index of a free slot that can be populated with\n * a hash entry for the given 'key'.\n * If the key already exists, -1 is returned.\n *\n * Note that if we are in the process of rehashing the hash table, the\n * index is always returned in the context of the second (new) hash table. */\nstatic int _dictKeyIndex(dict *d, const void *key)\n{\n    unsigned int h, idx, table;\n    dictEntry *he;\n\n    /* Expand the hash table if needed */\n    if (_dictExpandIfNeeded(d) == DICT_ERR)\n        return -1;\n    /* Compute the key hash value */\n    h = dictHashKey(d, key);\n    for (table = 0; table <= 1; table++) {\n        idx = h & d->ht[table].sizemask;\n        /* Search if this slot does not already contain the given key */\n        he = d->ht[table].table[idx];\n        while(he) {\n            if (dictCompareKeys(d, key, he->key))\n                return -1;\n            he = he->next;\n        }\n        if (!dictIsRehashing(d)) break;\n    }\n    return idx;\n}\n\nvoid dictEmpty(dict *d, void(callback)(void*)) {\n    _dictClear(d,&d->ht[0],callback);\n    _dictClear(d,&d->ht[1],callback);\n    d->rehashidx = -1;\n    d->iterators = 0;\n}\n\nvoid dictEnableResize(void) {\n    dict_can_resize = 1;\n}\n\nvoid dictDisableResize(void) {\n    dict_can_resize = 0;\n}\n\n#if 0\n\n/* The following is code that we don't use for Redis currently, but that is part\nof the library. */\n\n/* ----------------------- Debugging ------------------------*/\n\n#define DICT_STATS_VECTLEN 50\nstatic void _dictPrintStatsHt(dictht *ht) {\n    unsigned long i, slots = 0, chainlen, maxchainlen = 0;\n    unsigned long totchainlen = 0;\n    unsigned long clvector[DICT_STATS_VECTLEN];\n\n    if (ht->used == 0) {\n        printf(\"No stats available for empty dictionaries\\n\");\n        return;\n    }\n\n    for (i = 0; i < DICT_STATS_VECTLEN; i++) clvector[i] = 0;\n    for (i = 0; i < ht->size; i++) {\n        dictEntry *he;\n\n        if (ht->table[i] == NULL) {\n            clvector[0]++;\n            continue;\n        }\n        slots++;\n        /* For each hash entry on this slot... */\n        chainlen = 0;\n        he = ht->table[i];\n        while(he) {\n            chainlen++;\n            he = he->next;\n        }\n        clvector[(chainlen < DICT_STATS_VECTLEN) ? chainlen : (DICT_STATS_VECTLEN-1)]++;\n        if (chainlen > maxchainlen) maxchainlen = chainlen;\n        totchainlen += chainlen;\n    }\n    printf(\"Hash table stats:\\n\");\n    printf(\" table size: %ld\\n\", ht->size);\n    printf(\" number of elements: %ld\\n\", ht->used);\n    printf(\" different slots: %ld\\n\", slots);\n    printf(\" max chain length: %ld\\n\", maxchainlen);\n    printf(\" avg chain length (counted): %.02f\\n\", (float)totchainlen/slots);\n    printf(\" avg chain length (computed): %.02f\\n\", (float)ht->used/slots);\n    printf(\" Chain length distribution:\\n\");\n    for (i = 0; i < DICT_STATS_VECTLEN-1; i++) {\n        if (clvector[i] == 0) continue;\n        printf(\"   %s%ld: %ld (%.02f%%)\\n\",(i == DICT_STATS_VECTLEN-1)?\">= \":\"\", i, clvector[i], ((float)clvector[i]/ht->size)*100);\n    }\n}\n\nvoid dictPrintStats(dict *d) {\n    _dictPrintStatsHt(&d->ht[0]);\n    if (dictIsRehashing(d)) {\n        printf(\"-- Rehashing into ht[1]:\\n\");\n        _dictPrintStatsHt(&d->ht[1]);\n    }\n}\n\n/* ----------------------- StringCopy Hash Table Type ------------------------*/\n\nstatic unsigned int _dictStringCopyHTHashFunction(const void *key)\n{\n    return dictGenHashFunction(key, strlen(key));\n}\n\nstatic void *_dictStringDup(void *privdata, const void *key)\n{\n    int len = strlen(key);\n    char *copy = zmalloc(len+1);\n    DICT_NOTUSED(privdata);\n\n    memcpy(copy, key, len);\n    copy[len] = '\\0';\n    return copy;\n}\n\nstatic int _dictStringCopyHTKeyCompare(void *privdata, const void *key1,\n        const void *key2)\n{\n    DICT_NOTUSED(privdata);\n\n    return strcmp(key1, key2) == 0;\n}\n\nstatic void _dictStringDestructor(void *privdata, void *key)\n{\n    DICT_NOTUSED(privdata);\n\n    zfree(key);\n}\n\ndictType dictTypeHeapStringCopyKey = {\n    _dictStringCopyHTHashFunction, /* hash function */\n    _dictStringDup,                /* key dup */\n    NULL,                          /* val dup */\n    _dictStringCopyHTKeyCompare,   /* key compare */\n    _dictStringDestructor,         /* key destructor */\n    NULL                           /* val destructor */\n};\n\n/* This is like StringCopy but does not auto-duplicate the key.\n * It's used for intepreter's shared strings. */\ndictType dictTypeHeapStrings = {\n    _dictStringCopyHTHashFunction, /* hash function */\n    NULL,                          /* key dup */\n    NULL,                          /* val dup */\n    _dictStringCopyHTKeyCompare,   /* key compare */\n    _dictStringDestructor,         /* key destructor */\n    NULL                           /* val destructor */\n};\n\n/* This is like StringCopy but also automatically handle dynamic\n * allocated C strings as values. */\ndictType dictTypeHeapStringCopyKeyValue = {\n    _dictStringCopyHTHashFunction, /* hash function */\n    _dictStringDup,                /* key dup */\n    _dictStringDup,                /* val dup */\n    _dictStringCopyHTKeyCompare,   /* key compare */\n    _dictStringDestructor,         /* key destructor */\n    _dictStringDestructor,         /* val destructor */\n};\n#endif\n"
  },
  {
    "path": "extern/deprecated/redis-2.8.21/src/dict.h",
    "content": "/* Hash Tables Implementation.\n *\n * This file implements in-memory hash tables with insert/del/replace/find/\n * get-random-element operations. Hash tables will auto-resize if needed\n * tables of power of two in size are used, collisions are handled by\n * chaining. See the source code for more information... :)\n *\n * Copyright (c) 2006-2012, Salvatore Sanfilippo <antirez at gmail dot com>\n * All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions are met:\n *\n *   * Redistributions of source code must retain the above copyright notice,\n *     this list of conditions and the following disclaimer.\n *   * Redistributions in binary form must reproduce the above copyright\n *     notice, this list of conditions and the following disclaimer in the\n *     documentation and/or other materials provided with the distribution.\n *   * Neither the name of Redis nor the names of its contributors may be used\n *     to endorse or promote products derived from this software without\n *     specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\"\n * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\n * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE\n * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR\n * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF\n * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS\n * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN\n * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)\n * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE\n * POSSIBILITY OF SUCH DAMAGE.\n */\n\n#include <stdint.h>\n\n#ifndef __DICT_H\n#define __DICT_H\n\n#define DICT_OK 0\n#define DICT_ERR 1\n\n/* Unused arguments generate annoying warnings... */\n#define DICT_NOTUSED(V) ((void) V)\n\ntypedef struct dictEntry {\n    void *key;\n    union {\n        void *val;\n        uint64_t u64;\n        int64_t s64;\n        double d;\n    } v;\n    struct dictEntry *next;\n} dictEntry;\n\ntypedef struct dictType {\n    unsigned int (*hashFunction)(const void *key);\n    void *(*keyDup)(void *privdata, const void *key);\n    void *(*valDup)(void *privdata, const void *obj);\n    int (*keyCompare)(void *privdata, const void *key1, const void *key2);\n    void (*keyDestructor)(void *privdata, void *key);\n    void (*valDestructor)(void *privdata, void *obj);\n} dictType;\n\n/* This is our hash table structure. Every dictionary has two of this as we\n * implement incremental rehashing, for the old to the new table. */\ntypedef struct dictht {\n    dictEntry **table;\n    unsigned long size;\n    unsigned long sizemask;\n    unsigned long used;\n} dictht;\n\ntypedef struct dict {\n    dictType *type;\n    void *privdata;\n    dictht ht[2];\n    long rehashidx; /* rehashing not in progress if rehashidx == -1 */\n    int iterators; /* number of iterators currently running */\n} dict;\n\n/* If safe is set to 1 this is a safe iterator, that means, you can call\n * dictAdd, dictFind, and other functions against the dictionary even while\n * iterating. Otherwise it is a non safe iterator, and only dictNext()\n * should be called while iterating. */\ntypedef struct dictIterator {\n    dict *d;\n    long index;\n    int table, safe;\n    dictEntry *entry, *nextEntry;\n    /* unsafe iterator fingerprint for misuse detection. */\n    long long fingerprint;\n} dictIterator;\n\ntypedef void (dictScanFunction)(void *privdata, const dictEntry *de);\n\n/* This is the initial size of every hash table */\n#define DICT_HT_INITIAL_SIZE     4\n\n/* ------------------------------- Macros ------------------------------------*/\n#define dictFreeVal(d, entry) \\\n    if ((d)->type->valDestructor) \\\n        (d)->type->valDestructor((d)->privdata, (entry)->v.val)\n\n#define dictSetVal(d, entry, _val_) do { \\\n    if ((d)->type->valDup) \\\n        entry->v.val = (d)->type->valDup((d)->privdata, _val_); \\\n    else \\\n        entry->v.val = (_val_); \\\n} while(0)\n\n#define dictSetSignedIntegerVal(entry, _val_) \\\n    do { entry->v.s64 = _val_; } while(0)\n\n#define dictSetUnsignedIntegerVal(entry, _val_) \\\n    do { entry->v.u64 = _val_; } while(0)\n\n#define dictSetDoubleVal(entry, _val_) \\\n    do { entry->v.d = _val_; } while(0)\n\n#define dictFreeKey(d, entry) \\\n    if ((d)->type->keyDestructor) \\\n        (d)->type->keyDestructor((d)->privdata, (entry)->key)\n\n#define dictSetKey(d, entry, _key_) do { \\\n    if ((d)->type->keyDup) \\\n        entry->key = (d)->type->keyDup((d)->privdata, _key_); \\\n    else \\\n        entry->key = (_key_); \\\n} while(0)\n\n#define dictCompareKeys(d, key1, key2) \\\n    (((d)->type->keyCompare) ? \\\n        (d)->type->keyCompare((d)->privdata, key1, key2) : \\\n        (key1) == (key2))\n\n#define dictHashKey(d, key) (d)->type->hashFunction(key)\n#define dictGetKey(he) ((he)->key)\n#define dictGetVal(he) ((he)->v.val)\n#define dictGetSignedIntegerVal(he) ((he)->v.s64)\n#define dictGetUnsignedIntegerVal(he) ((he)->v.u64)\n#define dictGetDoubleVal(he) ((he)->v.d)\n#define dictSlots(d) ((d)->ht[0].size+(d)->ht[1].size)\n#define dictSize(d) ((d)->ht[0].used+(d)->ht[1].used)\n#define dictIsRehashing(d) ((d)->rehashidx != -1)\n\n/* API */\ndict *dictCreate(dictType *type, void *privDataPtr);\nint dictExpand(dict *d, unsigned long size);\nint dictAdd(dict *d, void *key, void *val);\ndictEntry *dictAddRaw(dict *d, void *key);\nint dictReplace(dict *d, void *key, void *val);\ndictEntry *dictReplaceRaw(dict *d, void *key);\nint dictDelete(dict *d, const void *key);\nint dictDeleteNoFree(dict *d, const void *key);\nvoid dictRelease(dict *d);\ndictEntry * dictFind(dict *d, const void *key);\nvoid *dictFetchValue(dict *d, const void *key);\nint dictResize(dict *d);\ndictIterator *dictGetIterator(dict *d);\ndictIterator *dictGetSafeIterator(dict *d);\ndictEntry *dictNext(dictIterator *iter);\nvoid dictReleaseIterator(dictIterator *iter);\ndictEntry *dictGetRandomKey(dict *d);\nvoid dictPrintStats(dict *d);\nunsigned int dictGenHashFunction(const void *key, int len);\nunsigned int dictGenCaseHashFunction(const unsigned char *buf, int len);\nvoid dictEmpty(dict *d, void(callback)(void*));\nvoid dictEnableResize(void);\nvoid dictDisableResize(void);\nint dictRehash(dict *d, int n);\nint dictRehashMilliseconds(dict *d, int ms);\nvoid dictSetHashFunctionSeed(unsigned int initval);\nunsigned int dictGetHashFunctionSeed(void);\nunsigned long dictScan(dict *d, unsigned long v, dictScanFunction *fn, void *privdata);\n\n/* Hash table types */\nextern dictType dictTypeHeapStringCopyKey;\nextern dictType dictTypeHeapStrings;\nextern dictType dictTypeHeapStringCopyKeyValue;\n\n#endif /* __DICT_H */\n"
  },
  {
    "path": "extern/deprecated/redis-2.8.21/src/endianconv.c",
    "content": "/* endinconv.c -- Endian conversions utilities.\n *\n * This functions are never called directly, but always using the macros\n * defined into endianconv.h, this way we define everything is a non-operation\n * if the arch is already little endian.\n *\n * Redis tries to encode everything as little endian (but a few things that need\n * to be backward compatible are still in big endian) because most of the\n * production environments are little endian, and we have a lot of conversions\n * in a few places because ziplists, intsets, zipmaps, need to be endian-neutral\n * even in memory, since they are serialied on RDB files directly with a single\n * write(2) without other additional steps.\n *\n * ----------------------------------------------------------------------------\n *\n * Copyright (c) 2011-2012, Salvatore Sanfilippo <antirez at gmail dot com>\n * All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions are met:\n *\n *   * Redistributions of source code must retain the above copyright notice,\n *     this list of conditions and the following disclaimer.\n *   * Redistributions in binary form must reproduce the above copyright\n *     notice, this list of conditions and the following disclaimer in the\n *     documentation and/or other materials provided with the distribution.\n *   * Neither the name of Redis nor the names of its contributors may be used\n *     to endorse or promote products derived from this software without\n *     specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\"\n * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\n * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE\n * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR\n * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF\n * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS\n * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN\n * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)\n * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE\n * POSSIBILITY OF SUCH DAMAGE.\n */\n\n\n#include <stdint.h>\n\n/* Toggle the 16 bit unsigned integer pointed by *p from little endian to\n * big endian */\nvoid memrev16(void *p) {\n    unsigned char *x = p, t;\n\n    t = x[0];\n    x[0] = x[1];\n    x[1] = t;\n}\n\n/* Toggle the 32 bit unsigned integer pointed by *p from little endian to\n * big endian */\nvoid memrev32(void *p) {\n    unsigned char *x = p, t;\n\n    t = x[0];\n    x[0] = x[3];\n    x[3] = t;\n    t = x[1];\n    x[1] = x[2];\n    x[2] = t;\n}\n\n/* Toggle the 64 bit unsigned integer pointed by *p from little endian to\n * big endian */\nvoid memrev64(void *p) {\n    unsigned char *x = p, t;\n\n    t = x[0];\n    x[0] = x[7];\n    x[7] = t;\n    t = x[1];\n    x[1] = x[6];\n    x[6] = t;\n    t = x[2];\n    x[2] = x[5];\n    x[5] = t;\n    t = x[3];\n    x[3] = x[4];\n    x[4] = t;\n}\n\nuint16_t intrev16(uint16_t v) {\n    memrev16(&v);\n    return v;\n}\n\nuint32_t intrev32(uint32_t v) {\n    memrev32(&v);\n    return v;\n}\n\nuint64_t intrev64(uint64_t v) {\n    memrev64(&v);\n    return v;\n}\n\n#ifdef TESTMAIN\n#include <stdio.h>\n\nint main(void) {\n    char buf[32];\n\n    sprintf(buf,\"ciaoroma\");\n    memrev16(buf);\n    printf(\"%s\\n\", buf);\n\n    sprintf(buf,\"ciaoroma\");\n    memrev32(buf);\n    printf(\"%s\\n\", buf);\n\n    sprintf(buf,\"ciaoroma\");\n    memrev64(buf);\n    printf(\"%s\\n\", buf);\n\n    return 0;\n}\n#endif\n"
  },
  {
    "path": "extern/deprecated/redis-2.8.21/src/endianconv.h",
    "content": "/* See endianconv.c top comments for more information\n *\n * ----------------------------------------------------------------------------\n *\n * Copyright (c) 2011-2012, Salvatore Sanfilippo <antirez at gmail dot com>\n * All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions are met:\n *\n *   * Redistributions of source code must retain the above copyright notice,\n *     this list of conditions and the following disclaimer.\n *   * Redistributions in binary form must reproduce the above copyright\n *     notice, this list of conditions and the following disclaimer in the\n *     documentation and/or other materials provided with the distribution.\n *   * Neither the name of Redis nor the names of its contributors may be used\n *     to endorse or promote products derived from this software without\n *     specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\"\n * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\n * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE\n * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR\n * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF\n * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS\n * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN\n * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)\n * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE\n * POSSIBILITY OF SUCH DAMAGE.\n */\n\n#ifndef __ENDIANCONV_H\n#define __ENDIANCONV_H\n\n#include \"config.h\"\n#include <stdint.h>\n\nvoid memrev16(void *p);\nvoid memrev32(void *p);\nvoid memrev64(void *p);\nuint16_t intrev16(uint16_t v);\nuint32_t intrev32(uint32_t v);\nuint64_t intrev64(uint64_t v);\n\n/* variants of the function doing the actual convertion only if the target\n * host is big endian */\n#if (BYTE_ORDER == LITTLE_ENDIAN)\n#define memrev16ifbe(p)\n#define memrev32ifbe(p)\n#define memrev64ifbe(p)\n#define intrev16ifbe(v) (v)\n#define intrev32ifbe(v) (v)\n#define intrev64ifbe(v) (v)\n#else\n#define memrev16ifbe(p) memrev16(p)\n#define memrev32ifbe(p) memrev32(p)\n#define memrev64ifbe(p) memrev64(p)\n#define intrev16ifbe(v) intrev16(v)\n#define intrev32ifbe(v) intrev32(v)\n#define intrev64ifbe(v) intrev64(v)\n#endif\n\n#endif\n"
  },
  {
    "path": "extern/deprecated/redis-2.8.21/src/fmacros.h",
    "content": "/*\n * Copyright (c) 2009-2012, Salvatore Sanfilippo <antirez at gmail dot com>\n * All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions are met:\n *\n *   * Redistributions of source code must retain the above copyright notice,\n *     this list of conditions and the following disclaimer.\n *   * Redistributions in binary form must reproduce the above copyright\n *     notice, this list of conditions and the following disclaimer in the\n *     documentation and/or other materials provided with the distribution.\n *   * Neither the name of Redis nor the names of its contributors may be used\n *     to endorse or promote products derived from this software without\n *     specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\"\n * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\n * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE\n * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR\n * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF\n * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS\n * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN\n * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)\n * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE\n * POSSIBILITY OF SUCH DAMAGE.\n */\n\n#ifndef _REDIS_FMACRO_H\n#define _REDIS_FMACRO_H\n\n#define _BSD_SOURCE\n\n#if defined(__linux__)\n#define _GNU_SOURCE\n#define _DEFAULT_SOURCE\n#endif\n\n#if defined(_AIX)\n#define _ALL_SOURCE\n#endif\n\n#if defined(__linux__) || defined(__OpenBSD__)\n#define _XOPEN_SOURCE 700\n/*\n * On NetBSD, _XOPEN_SOURCE undefines _NETBSD_SOURCE and\n * thus hides inet_aton etc.\n */\n#elif !defined(__NetBSD__)\n#define _XOPEN_SOURCE\n#endif\n\n#if defined(__sun)\n#define _POSIX_C_SOURCE 199506L\n#endif\n\n#define _LARGEFILE_SOURCE\n#define _FILE_OFFSET_BITS 64\n\n#endif\n"
  },
  {
    "path": "extern/deprecated/redis-2.8.21/src/help.h",
    "content": "/* Automatically generated by utils/generate-command-help.rb, do not edit. */\n\n#ifndef __REDIS_HELP_H\n#define __REDIS_HELP_H\n\nstatic char *commandGroups[] = {\n    \"generic\",\n    \"string\",\n    \"list\",\n    \"set\",\n    \"sorted_set\",\n    \"hash\",\n    \"pubsub\",\n    \"transactions\",\n    \"connection\",\n    \"server\",\n    \"scripting\",\n    \"hyperloglog\"\n};\n\nstruct commandHelp {\n  char *name;\n  char *params;\n  char *summary;\n  int group;\n  char *since;\n} commandHelp[] = {\n    { \"APPEND\",\n    \"key value\",\n    \"Append a value to a key\",\n    1,\n    \"2.0.0\" },\n    { \"AUTH\",\n    \"password\",\n    \"Authenticate to the server\",\n    8,\n    \"1.0.0\" },\n    { \"BGREWRITEAOF\",\n    \"-\",\n    \"Asynchronously rewrite the append-only file\",\n    9,\n    \"1.0.0\" },\n    { \"BGSAVE\",\n    \"-\",\n    \"Asynchronously save the dataset to disk\",\n    9,\n    \"1.0.0\" },\n    { \"BITCOUNT\",\n    \"key [start] [end]\",\n    \"Count set bits in a string\",\n    1,\n    \"2.6.0\" },\n    { \"BITOP\",\n    \"operation destkey key [key ...]\",\n    \"Perform bitwise operations between strings\",\n    1,\n    \"2.6.0\" },\n    { \"BITPOS\",\n    \"key bit [start] [end]\",\n    \"Find first bit set or clear in a string\",\n    1,\n    \"2.8.7\" },\n    { \"BLPOP\",\n    \"key [key ...] timeout\",\n    \"Remove and get the first element in a list, or block until one is available\",\n    2,\n    \"2.0.0\" },\n    { \"BRPOP\",\n    \"key [key ...] timeout\",\n    \"Remove and get the last element in a list, or block until one is available\",\n    2,\n    \"2.0.0\" },\n    { \"BRPOPLPUSH\",\n    \"source destination timeout\",\n    \"Pop a value from a list, push it to another list and return it; or block until one is available\",\n    2,\n    \"2.2.0\" },\n    { \"CLIENT GETNAME\",\n    \"-\",\n    \"Get the current connection name\",\n    9,\n    \"2.6.9\" },\n    { \"CLIENT KILL\",\n    \"ip:port\",\n    \"Kill the connection of a client\",\n    9,\n    \"2.4.0\" },\n    { \"CLIENT LIST\",\n    \"-\",\n    \"Get the list of client connections\",\n    9,\n    \"2.4.0\" },\n    { \"CLIENT PAUSE\",\n    \"timeout\",\n    \"Stop processing commands from clients for some time\",\n    9,\n    \"2.9.50\" },\n    { \"CLIENT SETNAME\",\n    \"connection-name\",\n    \"Set the current connection name\",\n    9,\n    \"2.6.9\" },\n    { \"CONFIG GET\",\n    \"parameter\",\n    \"Get the value of a configuration parameter\",\n    9,\n    \"2.0.0\" },\n    { \"CONFIG RESETSTAT\",\n    \"-\",\n    \"Reset the stats returned by INFO\",\n    9,\n    \"2.0.0\" },\n    { \"CONFIG REWRITE\",\n    \"-\",\n    \"Rewrite the configuration file with the in memory configuration\",\n    9,\n    \"2.8.0\" },\n    { \"CONFIG SET\",\n    \"parameter value\",\n    \"Set a configuration parameter to the given value\",\n    9,\n    \"2.0.0\" },\n    { \"DBSIZE\",\n    \"-\",\n    \"Return the number of keys in the selected database\",\n    9,\n    \"1.0.0\" },\n    { \"DEBUG OBJECT\",\n    \"key\",\n    \"Get debugging information about a key\",\n    9,\n    \"1.0.0\" },\n    { \"DEBUG SEGFAULT\",\n    \"-\",\n    \"Make the server crash\",\n    9,\n    \"1.0.0\" },\n    { \"DECR\",\n    \"key\",\n    \"Decrement the integer value of a key by one\",\n    1,\n    \"1.0.0\" },\n    { \"DECRBY\",\n    \"key decrement\",\n    \"Decrement the integer value of a key by the given number\",\n    1,\n    \"1.0.0\" },\n    { \"DEL\",\n    \"key [key ...]\",\n    \"Delete a key\",\n    0,\n    \"1.0.0\" },\n    { \"DISCARD\",\n    \"-\",\n    \"Discard all commands issued after MULTI\",\n    7,\n    \"2.0.0\" },\n    { \"DUMP\",\n    \"key\",\n    \"Return a serialized version of the value stored at the specified key.\",\n    0,\n    \"2.6.0\" },\n    { \"ECHO\",\n    \"message\",\n    \"Echo the given string\",\n    8,\n    \"1.0.0\" },\n    { \"EVAL\",\n    \"script numkeys key [key ...] arg [arg ...]\",\n    \"Execute a Lua script server side\",\n    10,\n    \"2.6.0\" },\n    { \"EVALSHA\",\n    \"sha1 numkeys key [key ...] arg [arg ...]\",\n    \"Execute a Lua script server side\",\n    10,\n    \"2.6.0\" },\n    { \"EXEC\",\n    \"-\",\n    \"Execute all commands issued after MULTI\",\n    7,\n    \"1.2.0\" },\n    { \"EXISTS\",\n    \"key\",\n    \"Determine if a key exists\",\n    0,\n    \"1.0.0\" },\n    { \"EXPIRE\",\n    \"key seconds\",\n    \"Set a key's time to live in seconds\",\n    0,\n    \"1.0.0\" },\n    { \"EXPIREAT\",\n    \"key timestamp\",\n    \"Set the expiration for a key as a UNIX timestamp\",\n    0,\n    \"1.2.0\" },\n    { \"FLUSHALL\",\n    \"-\",\n    \"Remove all keys from all databases\",\n    9,\n    \"1.0.0\" },\n    { \"FLUSHDB\",\n    \"-\",\n    \"Remove all keys from the current database\",\n    9,\n    \"1.0.0\" },\n    { \"GET\",\n    \"key\",\n    \"Get the value of a key\",\n    1,\n    \"1.0.0\" },\n    { \"GETBIT\",\n    \"key offset\",\n    \"Returns the bit value at offset in the string value stored at key\",\n    1,\n    \"2.2.0\" },\n    { \"GETRANGE\",\n    \"key start end\",\n    \"Get a substring of the string stored at a key\",\n    1,\n    \"2.4.0\" },\n    { \"GETSET\",\n    \"key value\",\n    \"Set the string value of a key and return its old value\",\n    1,\n    \"1.0.0\" },\n    { \"HDEL\",\n    \"key field [field ...]\",\n    \"Delete one or more hash fields\",\n    5,\n    \"2.0.0\" },\n    { \"HEXISTS\",\n    \"key field\",\n    \"Determine if a hash field exists\",\n    5,\n    \"2.0.0\" },\n    { \"HGET\",\n    \"key field\",\n    \"Get the value of a hash field\",\n    5,\n    \"2.0.0\" },\n    { \"HGETALL\",\n    \"key\",\n    \"Get all the fields and values in a hash\",\n    5,\n    \"2.0.0\" },\n    { \"HINCRBY\",\n    \"key field increment\",\n    \"Increment the integer value of a hash field by the given number\",\n    5,\n    \"2.0.0\" },\n    { \"HINCRBYFLOAT\",\n    \"key field increment\",\n    \"Increment the float value of a hash field by the given amount\",\n    5,\n    \"2.6.0\" },\n    { \"HKEYS\",\n    \"key\",\n    \"Get all the fields in a hash\",\n    5,\n    \"2.0.0\" },\n    { \"HLEN\",\n    \"key\",\n    \"Get the number of fields in a hash\",\n    5,\n    \"2.0.0\" },\n    { \"HMGET\",\n    \"key field [field ...]\",\n    \"Get the values of all the given hash fields\",\n    5,\n    \"2.0.0\" },\n    { \"HMSET\",\n    \"key field value [field value ...]\",\n    \"Set multiple hash fields to multiple values\",\n    5,\n    \"2.0.0\" },\n    { \"HSCAN\",\n    \"key cursor [MATCH pattern] [COUNT count]\",\n    \"Incrementally iterate hash fields and associated values\",\n    5,\n    \"2.8.0\" },\n    { \"HSET\",\n    \"key field value\",\n    \"Set the string value of a hash field\",\n    5,\n    \"2.0.0\" },\n    { \"HSETNX\",\n    \"key field value\",\n    \"Set the value of a hash field, only if the field does not exist\",\n    5,\n    \"2.0.0\" },\n    { \"HVALS\",\n    \"key\",\n    \"Get all the values in a hash\",\n    5,\n    \"2.0.0\" },\n    { \"INCR\",\n    \"key\",\n    \"Increment the integer value of a key by one\",\n    1,\n    \"1.0.0\" },\n    { \"INCRBY\",\n    \"key increment\",\n    \"Increment the integer value of a key by the given amount\",\n    1,\n    \"1.0.0\" },\n    { \"INCRBYFLOAT\",\n    \"key increment\",\n    \"Increment the float value of a key by the given amount\",\n    1,\n    \"2.6.0\" },\n    { \"INFO\",\n    \"[section]\",\n    \"Get information and statistics about the server\",\n    9,\n    \"1.0.0\" },\n    { \"KEYS\",\n    \"pattern\",\n    \"Find all keys matching the given pattern\",\n    0,\n    \"1.0.0\" },\n    { \"LASTSAVE\",\n    \"-\",\n    \"Get the UNIX time stamp of the last successful save to disk\",\n    9,\n    \"1.0.0\" },\n    { \"LINDEX\",\n    \"key index\",\n    \"Get an element from a list by its index\",\n    2,\n    \"1.0.0\" },\n    { \"LINSERT\",\n    \"key BEFORE|AFTER pivot value\",\n    \"Insert an element before or after another element in a list\",\n    2,\n    \"2.2.0\" },\n    { \"LLEN\",\n    \"key\",\n    \"Get the length of a list\",\n    2,\n    \"1.0.0\" },\n    { \"LPOP\",\n    \"key\",\n    \"Remove and get the first element in a list\",\n    2,\n    \"1.0.0\" },\n    { \"LPUSH\",\n    \"key value [value ...]\",\n    \"Prepend one or multiple values to a list\",\n    2,\n    \"1.0.0\" },\n    { \"LPUSHX\",\n    \"key value\",\n    \"Prepend a value to a list, only if the list exists\",\n    2,\n    \"2.2.0\" },\n    { \"LRANGE\",\n    \"key start stop\",\n    \"Get a range of elements from a list\",\n    2,\n    \"1.0.0\" },\n    { \"LREM\",\n    \"key count value\",\n    \"Remove elements from a list\",\n    2,\n    \"1.0.0\" },\n    { \"LSET\",\n    \"key index value\",\n    \"Set the value of an element in a list by its index\",\n    2,\n    \"1.0.0\" },\n    { \"LTRIM\",\n    \"key start stop\",\n    \"Trim a list to the specified range\",\n    2,\n    \"1.0.0\" },\n    { \"MGET\",\n    \"key [key ...]\",\n    \"Get the values of all the given keys\",\n    1,\n    \"1.0.0\" },\n    { \"MIGRATE\",\n    \"host port key destination-db timeout [COPY] [REPLACE]\",\n    \"Atomically transfer a key from a Redis instance to another one.\",\n    0,\n    \"2.6.0\" },\n    { \"MONITOR\",\n    \"-\",\n    \"Listen for all requests received by the server in real time\",\n    9,\n    \"1.0.0\" },\n    { \"MOVE\",\n    \"key db\",\n    \"Move a key to another database\",\n    0,\n    \"1.0.0\" },\n    { \"MSET\",\n    \"key value [key value ...]\",\n    \"Set multiple keys to multiple values\",\n    1,\n    \"1.0.1\" },\n    { \"MSETNX\",\n    \"key value [key value ...]\",\n    \"Set multiple keys to multiple values, only if none of the keys exist\",\n    1,\n    \"1.0.1\" },\n    { \"MULTI\",\n    \"-\",\n    \"Mark the start of a transaction block\",\n    7,\n    \"1.2.0\" },\n    { \"OBJECT\",\n    \"subcommand [arguments [arguments ...]]\",\n    \"Inspect the internals of Redis objects\",\n    0,\n    \"2.2.3\" },\n    { \"PERSIST\",\n    \"key\",\n    \"Remove the expiration from a key\",\n    0,\n    \"2.2.0\" },\n    { \"PEXPIRE\",\n    \"key milliseconds\",\n    \"Set a key's time to live in milliseconds\",\n    0,\n    \"2.6.0\" },\n    { \"PEXPIREAT\",\n    \"key milliseconds-timestamp\",\n    \"Set the expiration for a key as a UNIX timestamp specified in milliseconds\",\n    0,\n    \"2.6.0\" },\n    { \"PFADD\",\n    \"key element [element ...]\",\n    \"Adds the specified elements to the specified HyperLogLog.\",\n    11,\n    \"2.8.9\" },\n    { \"PFCOUNT\",\n    \"key [key ...]\",\n    \"Return the approximated cardinality of the set(s) observed by the HyperLogLog at key(s).\",\n    11,\n    \"2.8.9\" },\n    { \"PFMERGE\",\n    \"destkey sourcekey [sourcekey ...]\",\n    \"Merge N different HyperLogLogs into a single one.\",\n    11,\n    \"2.8.9\" },\n    { \"PING\",\n    \"-\",\n    \"Ping the server\",\n    8,\n    \"1.0.0\" },\n    { \"PSETEX\",\n    \"key milliseconds value\",\n    \"Set the value and expiration in milliseconds of a key\",\n    1,\n    \"2.6.0\" },\n    { \"PSUBSCRIBE\",\n    \"pattern [pattern ...]\",\n    \"Listen for messages published to channels matching the given patterns\",\n    6,\n    \"2.0.0\" },\n    { \"PTTL\",\n    \"key\",\n    \"Get the time to live for a key in milliseconds\",\n    0,\n    \"2.6.0\" },\n    { \"PUBLISH\",\n    \"channel message\",\n    \"Post a message to a channel\",\n    6,\n    \"2.0.0\" },\n    { \"PUBSUB\",\n    \"subcommand [argument [argument ...]]\",\n    \"Inspect the state of the Pub/Sub subsystem\",\n    6,\n    \"2.8.0\" },\n    { \"PUNSUBSCRIBE\",\n    \"[pattern [pattern ...]]\",\n    \"Stop listening for messages posted to channels matching the given patterns\",\n    6,\n    \"2.0.0\" },\n    { \"QUIT\",\n    \"-\",\n    \"Close the connection\",\n    8,\n    \"1.0.0\" },\n    { \"RANDOMKEY\",\n    \"-\",\n    \"Return a random key from the keyspace\",\n    0,\n    \"1.0.0\" },\n    { \"RENAME\",\n    \"key newkey\",\n    \"Rename a key\",\n    0,\n    \"1.0.0\" },\n    { \"RENAMENX\",\n    \"key newkey\",\n    \"Rename a key, only if the new key does not exist\",\n    0,\n    \"1.0.0\" },\n    { \"RESTORE\",\n    \"key ttl serialized-value\",\n    \"Create a key using the provided serialized value, previously obtained using DUMP.\",\n    0,\n    \"2.6.0\" },\n    { \"RPOP\",\n    \"key\",\n    \"Remove and get the last element in a list\",\n    2,\n    \"1.0.0\" },\n    { \"RPOPLPUSH\",\n    \"source destination\",\n    \"Remove the last element in a list, append it to another list and return it\",\n    2,\n    \"1.2.0\" },\n    { \"RPUSH\",\n    \"key value [value ...]\",\n    \"Append one or multiple values to a list\",\n    2,\n    \"1.0.0\" },\n    { \"RPUSHX\",\n    \"key value\",\n    \"Append a value to a list, only if the list exists\",\n    2,\n    \"2.2.0\" },\n    { \"SADD\",\n    \"key member [member ...]\",\n    \"Add one or more members to a set\",\n    3,\n    \"1.0.0\" },\n    { \"SAVE\",\n    \"-\",\n    \"Synchronously save the dataset to disk\",\n    9,\n    \"1.0.0\" },\n    { \"SCAN\",\n    \"cursor [MATCH pattern] [COUNT count]\",\n    \"Incrementally iterate the keys space\",\n    0,\n    \"2.8.0\" },\n    { \"SCARD\",\n    \"key\",\n    \"Get the number of members in a set\",\n    3,\n    \"1.0.0\" },\n    { \"SCRIPT EXISTS\",\n    \"script [script ...]\",\n    \"Check existence of scripts in the script cache.\",\n    10,\n    \"2.6.0\" },\n    { \"SCRIPT FLUSH\",\n    \"-\",\n    \"Remove all the scripts from the script cache.\",\n    10,\n    \"2.6.0\" },\n    { \"SCRIPT KILL\",\n    \"-\",\n    \"Kill the script currently in execution.\",\n    10,\n    \"2.6.0\" },\n    { \"SCRIPT LOAD\",\n    \"script\",\n    \"Load the specified Lua script into the script cache.\",\n    10,\n    \"2.6.0\" },\n    { \"SDIFF\",\n    \"key [key ...]\",\n    \"Subtract multiple sets\",\n    3,\n    \"1.0.0\" },\n    { \"SDIFFSTORE\",\n    \"destination key [key ...]\",\n    \"Subtract multiple sets and store the resulting set in a key\",\n    3,\n    \"1.0.0\" },\n    { \"SELECT\",\n    \"index\",\n    \"Change the selected database for the current connection\",\n    8,\n    \"1.0.0\" },\n    { \"SET\",\n    \"key value [EX seconds] [PX milliseconds] [NX|XX]\",\n    \"Set the string value of a key\",\n    1,\n    \"1.0.0\" },\n    { \"SETBIT\",\n    \"key offset value\",\n    \"Sets or clears the bit at offset in the string value stored at key\",\n    1,\n    \"2.2.0\" },\n    { \"SETEX\",\n    \"key seconds value\",\n    \"Set the value and expiration of a key\",\n    1,\n    \"2.0.0\" },\n    { \"SETNX\",\n    \"key value\",\n    \"Set the value of a key, only if the key does not exist\",\n    1,\n    \"1.0.0\" },\n    { \"SETRANGE\",\n    \"key offset value\",\n    \"Overwrite part of a string at key starting at the specified offset\",\n    1,\n    \"2.2.0\" },\n    { \"SHUTDOWN\",\n    \"[NOSAVE] [SAVE]\",\n    \"Synchronously save the dataset to disk and then shut down the server\",\n    9,\n    \"1.0.0\" },\n    { \"SINTER\",\n    \"key [key ...]\",\n    \"Intersect multiple sets\",\n    3,\n    \"1.0.0\" },\n    { \"SINTERSTORE\",\n    \"destination key [key ...]\",\n    \"Intersect multiple sets and store the resulting set in a key\",\n    3,\n    \"1.0.0\" },\n    { \"SISMEMBER\",\n    \"key member\",\n    \"Determine if a given value is a member of a set\",\n    3,\n    \"1.0.0\" },\n    { \"SLAVEOF\",\n    \"host port\",\n    \"Make the server a slave of another instance, or promote it as master\",\n    9,\n    \"1.0.0\" },\n    { \"SLOWLOG\",\n    \"subcommand [argument]\",\n    \"Manages the Redis slow queries log\",\n    9,\n    \"2.2.12\" },\n    { \"SMEMBERS\",\n    \"key\",\n    \"Get all the members in a set\",\n    3,\n    \"1.0.0\" },\n    { \"SMOVE\",\n    \"source destination member\",\n    \"Move a member from one set to another\",\n    3,\n    \"1.0.0\" },\n    { \"SORT\",\n    \"key [BY pattern] [LIMIT offset count] [GET pattern [GET pattern ...]] [ASC|DESC] [ALPHA] [STORE destination]\",\n    \"Sort the elements in a list, set or sorted set\",\n    0,\n    \"1.0.0\" },\n    { \"SPOP\",\n    \"key\",\n    \"Remove and return a random member from a set\",\n    3,\n    \"1.0.0\" },\n    { \"SRANDMEMBER\",\n    \"key [count]\",\n    \"Get one or multiple random members from a set\",\n    3,\n    \"1.0.0\" },\n    { \"SREM\",\n    \"key member [member ...]\",\n    \"Remove one or more members from a set\",\n    3,\n    \"1.0.0\" },\n    { \"SSCAN\",\n    \"key cursor [MATCH pattern] [COUNT count]\",\n    \"Incrementally iterate Set elements\",\n    3,\n    \"2.8.0\" },\n    { \"STRLEN\",\n    \"key\",\n    \"Get the length of the value stored in a key\",\n    1,\n    \"2.2.0\" },\n    { \"SUBSCRIBE\",\n    \"channel [channel ...]\",\n    \"Listen for messages published to the given channels\",\n    6,\n    \"2.0.0\" },\n    { \"SUNION\",\n    \"key [key ...]\",\n    \"Add multiple sets\",\n    3,\n    \"1.0.0\" },\n    { \"SUNIONSTORE\",\n    \"destination key [key ...]\",\n    \"Add multiple sets and store the resulting set in a key\",\n    3,\n    \"1.0.0\" },\n    { \"SYNC\",\n    \"-\",\n    \"Internal command used for replication\",\n    9,\n    \"1.0.0\" },\n    { \"TIME\",\n    \"-\",\n    \"Return the current server time\",\n    9,\n    \"2.6.0\" },\n    { \"TTL\",\n    \"key\",\n    \"Get the time to live for a key\",\n    0,\n    \"1.0.0\" },\n    { \"TYPE\",\n    \"key\",\n    \"Determine the type stored at key\",\n    0,\n    \"1.0.0\" },\n    { \"UNSUBSCRIBE\",\n    \"[channel [channel ...]]\",\n    \"Stop listening for messages posted to the given channels\",\n    6,\n    \"2.0.0\" },\n    { \"UNWATCH\",\n    \"-\",\n    \"Forget about all watched keys\",\n    7,\n    \"2.2.0\" },\n    { \"WATCH\",\n    \"key [key ...]\",\n    \"Watch the given keys to determine execution of the MULTI/EXEC block\",\n    7,\n    \"2.2.0\" },\n    { \"ZADD\",\n    \"key score member [score member ...]\",\n    \"Add one or more members to a sorted set, or update its score if it already exists\",\n    4,\n    \"1.2.0\" },\n    { \"ZCARD\",\n    \"key\",\n    \"Get the number of members in a sorted set\",\n    4,\n    \"1.2.0\" },\n    { \"ZCOUNT\",\n    \"key min max\",\n    \"Count the members in a sorted set with scores within the given values\",\n    4,\n    \"2.0.0\" },\n    { \"ZINCRBY\",\n    \"key increment member\",\n    \"Increment the score of a member in a sorted set\",\n    4,\n    \"1.2.0\" },\n    { \"ZINTERSTORE\",\n    \"destination numkeys key [key ...] [WEIGHTS weight] [AGGREGATE SUM|MIN|MAX]\",\n    \"Intersect multiple sorted sets and store the resulting sorted set in a new key\",\n    4,\n    \"2.0.0\" },\n    { \"ZLEXCOUNT\",\n    \"key min max\",\n    \"Count the number of members in a sorted set between a given lexicographical range\",\n    4,\n    \"2.8.9\" },\n    { \"ZRANGE\",\n    \"key start stop [WITHSCORES]\",\n    \"Return a range of members in a sorted set, by index\",\n    4,\n    \"1.2.0\" },\n    { \"ZRANGEBYLEX\",\n    \"key min max [LIMIT offset count]\",\n    \"Return a range of members in a sorted set, by lexicographical range\",\n    4,\n    \"2.8.9\" },\n    { \"ZRANGEBYSCORE\",\n    \"key min max [WITHSCORES] [LIMIT offset count]\",\n    \"Return a range of members in a sorted set, by score\",\n    4,\n    \"1.0.5\" },\n    { \"ZRANK\",\n    \"key member\",\n    \"Determine the index of a member in a sorted set\",\n    4,\n    \"2.0.0\" },\n    { \"ZREM\",\n    \"key member [member ...]\",\n    \"Remove one or more members from a sorted set\",\n    4,\n    \"1.2.0\" },\n    { \"ZREMRANGEBYLEX\",\n    \"key min max\",\n    \"Remove all members in a sorted set between the given lexicographical range\",\n    4,\n    \"2.8.9\" },\n    { \"ZREMRANGEBYRANK\",\n    \"key start stop\",\n    \"Remove all members in a sorted set within the given indexes\",\n    4,\n    \"2.0.0\" },\n    { \"ZREMRANGEBYSCORE\",\n    \"key min max\",\n    \"Remove all members in a sorted set within the given scores\",\n    4,\n    \"1.2.0\" },\n    { \"ZREVRANGE\",\n    \"key start stop [WITHSCORES]\",\n    \"Return a range of members in a sorted set, by index, with scores ordered from high to low\",\n    4,\n    \"1.2.0\" },\n    { \"ZREVRANGEBYSCORE\",\n    \"key max min [WITHSCORES] [LIMIT offset count]\",\n    \"Return a range of members in a sorted set, by score, with scores ordered from high to low\",\n    4,\n    \"2.2.0\" },\n    { \"ZREVRANK\",\n    \"key member\",\n    \"Determine the index of a member in a sorted set, with scores ordered from high to low\",\n    4,\n    \"2.0.0\" },\n    { \"ZSCAN\",\n    \"key cursor [MATCH pattern] [COUNT count]\",\n    \"Incrementally iterate sorted sets elements and associated scores\",\n    4,\n    \"2.8.0\" },\n    { \"ZSCORE\",\n    \"key member\",\n    \"Get the score associated with the given member in a sorted set\",\n    4,\n    \"1.2.0\" },\n    { \"ZUNIONSTORE\",\n    \"destination numkeys key [key ...] [WEIGHTS weight] [AGGREGATE SUM|MIN|MAX]\",\n    \"Add multiple sorted sets and store the resulting sorted set in a new key\",\n    4,\n    \"2.0.0\" }\n};\n\n#endif\n"
  },
  {
    "path": "extern/deprecated/redis-2.8.21/src/hyperloglog.c",
    "content": "/* hyperloglog.c - Redis HyperLogLog probabilistic cardinality approximation.\n * This file implements the algorithm and the exported Redis commands.\n *\n * Copyright (c) 2014, Salvatore Sanfilippo <antirez at gmail dot com>\n * All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions are met:\n *\n *   * Redistributions of source code must retain the above copyright notice,\n *     this list of conditions and the following disclaimer.\n *   * Redistributions in binary form must reproduce the above copyright\n *     notice, this list of conditions and the following disclaimer in the\n *     documentation and/or other materials provided with the distribution.\n *   * Neither the name of Redis nor the names of its contributors may be used\n *     to endorse or promote products derived from this software without\n *     specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\"\n * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\n * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE\n * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR\n * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF\n * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS\n * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN\n * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)\n * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE\n * POSSIBILITY OF SUCH DAMAGE.\n */\n\n#include \"redis.h\"\n\n#include <stdint.h>\n#include <math.h>\n\n/* The Redis HyperLogLog implementation is based on the following ideas:\n *\n * * The use of a 64 bit hash function as proposed in [1], in order to don't\n *   limited to cardinalities up to 10^9, at the cost of just 1 additional\n *   bit per register.\n * * The use of 16384 6-bit registers for a great level of accuracy, using\n *   a total of 12k per key.\n * * The use of the Redis string data type. No new type is introduced.\n * * No attempt is made to compress the data structure as in [1]. Also the\n *   algorithm used is the original HyperLogLog Algorithm as in [2], with\n *   the only difference that a 64 bit hash function is used, so no correction\n *   is performed for values near 2^32 as in [1].\n *\n * [1] Heule, Nunkesser, Hall: HyperLogLog in Practice: Algorithmic\n *     Engineering of a State of The Art Cardinality Estimation Algorithm.\n *\n * [2] P. Flajolet, Éric Fusy, O. Gandouet, and F. Meunier. Hyperloglog: The\n *     analysis of a near-optimal cardinality estimation algorithm.\n *\n * Redis uses two representations:\n *\n * 1) A \"dense\" representation where every entry is represented by\n *    a 6-bit integer.\n * 2) A \"sparse\" representation using run length compression suitable\n *    for representing HyperLogLogs with many registers set to 0 in\n *    a memory efficient way.\n *\n *\n * HLL header\n * ===\n *\n * Both the dense and sparse representation have a 16 byte header as follows:\n *\n * +------+---+-----+----------+\n * | HYLL | E | N/U | Cardin.  |\n * +------+---+-----+----------+\n *\n * The first 4 bytes are a magic string set to the bytes \"HYLL\".\n * \"E\" is one byte encoding, currently set to HLL_DENSE or\n * HLL_SPARSE. N/U are three not used bytes.\n *\n * The \"Cardin.\" field is a 64 bit integer stored in little endian format\n * with the latest cardinality computed that can be reused if the data\n * structure was not modified since the last computation (this is useful\n * because there are high probabilities that HLLADD operations don't\n * modify the actual data structure and hence the approximated cardinality).\n *\n * When the most significant bit in the most significant byte of the cached\n * cardinality is set, it means that the data structure was modified and\n * we can't reuse the cached value that must be recomputed.\n *\n * Dense representation\n * ===\n *\n * The dense representation used by Redis is the following:\n *\n * +--------+--------+--------+------//      //--+\n * |11000000|22221111|33333322|55444444 ....     |\n * +--------+--------+--------+------//      //--+\n *\n * The 6 bits counters are encoded one after the other starting from the\n * LSB to the MSB, and using the next bytes as needed.\n *\n * Sparse representation\n * ===\n *\n * The sparse representation encodes registers using a run length\n * encoding composed of three opcodes, two using one byte, and one using\n * of two bytes. The opcodes are called ZERO, XZERO and VAL.\n *\n * ZERO opcode is represented as 00xxxxxx. The 6-bit integer represented\n * by the six bits 'xxxxxx', plus 1, means that there are N registers set\n * to 0. This opcode can represent from 1 to 64 contiguous registers set\n * to the value of 0.\n *\n * XZERO opcode is represented by two bytes 01xxxxxx yyyyyyyy. The 14-bit\n * integer represented by the bits 'xxxxxx' as most significant bits and\n * 'yyyyyyyy' as least significant bits, plus 1, means that there are N\n * registers set to 0. This opcode can represent from 0 to 16384 contiguous\n * registers set to the value of 0.\n *\n * VAL opcode is represented as 1vvvvvxx. It contains a 5-bit integer\n * representing the value of a register, and a 2-bit integer representing\n * the number of contiguous registers set to that value 'vvvvv'.\n * To obtain the value and run length, the integers vvvvv and xx must be\n * incremented by one. This opcode can represent values from 1 to 32,\n * repeated from 1 to 4 times.\n *\n * The sparse representation can't represent registers with a value greater\n * than 32, however it is very unlikely that we find such a register in an\n * HLL with a cardinality where the sparse representation is still more\n * memory efficient than the dense representation. When this happens the\n * HLL is converted to the dense representation.\n *\n * The sparse representation is purely positional. For example a sparse\n * representation of an empty HLL is just: XZERO:16384.\n *\n * An HLL having only 3 non-zero registers at position 1000, 1020, 1021\n * respectively set to 2, 3, 3, is represented by the following three\n * opcodes:\n *\n * XZERO:1000 (Registers 0-999 are set to 0)\n * VAL:2,1    (1 register set to value 2, that is register 1000)\n * ZERO:19    (Registers 1001-1019 set to 0)\n * VAL:3,2    (2 registers set to value 3, that is registers 1020,1021)\n * XZERO:15362 (Registers 1022-16383 set to 0)\n *\n * In the example the sparse representation used just 7 bytes instead\n * of 12k in order to represent the HLL registers. In general for low\n * cardinality there is a big win in terms of space efficiency, traded\n * with CPU time since the sparse representation is slower to access:\n *\n * The following table shows average cardinality vs bytes used, 100\n * samples per cardinality (when the set was not representable because\n * of registers with too big value, the dense representation size was used\n * as a sample).\n *\n * 100 267\n * 200 485\n * 300 678\n * 400 859\n * 500 1033\n * 600 1205\n * 700 1375\n * 800 1544\n * 900 1713\n * 1000 1882\n * 2000 3480\n * 3000 4879\n * 4000 6089\n * 5000 7138\n * 6000 8042\n * 7000 8823\n * 8000 9500\n * 9000 10088\n * 10000 10591\n *\n * The dense representation uses 12288 bytes, so there is a big win up to\n * a cardinality of ~2000-3000. For bigger cardinalities the constant times\n * involved in updating the sparse representation is not justified by the\n * memory savings. The exact maximum length of the sparse representation\n * when this implementation switches to the dense representation is\n * configured via the define server.hll_sparse_max_bytes.\n */\n\nstruct hllhdr {\n    char magic[4];      /* \"HYLL\" */\n    uint8_t encoding;   /* HLL_DENSE or HLL_SPARSE. */\n    uint8_t notused[3]; /* Reserved for future use, must be zero. */\n    uint8_t card[8];    /* Cached cardinality, little endian. */\n    uint8_t registers[]; /* Data bytes. */\n};\n\n/* The cached cardinality MSB is used to signal validity of the cached value. */\n#define HLL_INVALIDATE_CACHE(hdr) (hdr)->card[7] |= (1<<7)\n#define HLL_VALID_CACHE(hdr) (((hdr)->card[7] & (1<<7)) == 0)\n\n#define HLL_P 14 /* The greater is P, the smaller the error. */\n#define HLL_REGISTERS (1<<HLL_P) /* With P=14, 16384 registers. */\n#define HLL_P_MASK (HLL_REGISTERS-1) /* Mask to index register. */\n#define HLL_BITS 6 /* Enough to count up to 63 leading zeroes. */\n#define HLL_REGISTER_MAX ((1<<HLL_BITS)-1)\n#define HLL_HDR_SIZE sizeof(struct hllhdr)\n#define HLL_DENSE_SIZE (HLL_HDR_SIZE+((HLL_REGISTERS*HLL_BITS+7)/8))\n#define HLL_DENSE 0 /* Dense encoding. */\n#define HLL_SPARSE 1 /* Sparse encoding. */\n#define HLL_RAW 255 /* Only used internally, never exposed. */\n#define HLL_MAX_ENCODING 1\n\nstatic char *invalid_hll_err = \"-INVALIDOBJ Corrupted HLL object detected\\r\\n\";\n\n/* =========================== Low level bit macros ========================= */\n\n/* Macros to access the dense representation.\n *\n * We need to get and set 6 bit counters in an array of 8 bit bytes.\n * We use macros to make sure the code is inlined since speed is critical\n * especially in order to compute the approximated cardinality in\n * HLLCOUNT where we need to access all the registers at once.\n * For the same reason we also want to avoid conditionals in this code path.\n *\n * +--------+--------+--------+------//\n * |11000000|22221111|33333322|55444444\n * +--------+--------+--------+------//\n *\n * Note: in the above representation the most significant bit (MSB)\n * of every byte is on the left. We start using bits from the LSB to MSB,\n * and so forth passing to the next byte.\n *\n * Example, we want to access to counter at pos = 1 (\"111111\" in the\n * illustration above).\n *\n * The index of the first byte b0 containing our data is:\n *\n *  b0 = 6 * pos / 8 = 0\n *\n *   +--------+\n *   |11000000|  <- Our byte at b0\n *   +--------+\n *\n * The position of the first bit (counting from the LSB = 0) in the byte\n * is given by:\n *\n *  fb = 6 * pos % 8 -> 6\n *\n * Right shift b0 of 'fb' bits.\n *\n *   +--------+\n *   |11000000|  <- Initial value of b0\n *   |00000011|  <- After right shift of 6 pos.\n *   +--------+\n *\n * Left shift b1 of bits 8-fb bits (2 bits)\n *\n *   +--------+\n *   |22221111|  <- Initial value of b1\n *   |22111100|  <- After left shift of 2 bits.\n *   +--------+\n *\n * OR the two bits, and finally AND with 111111 (63 in decimal) to\n * clean the higher order bits we are not interested in:\n *\n *   +--------+\n *   |00000011|  <- b0 right shifted\n *   |22111100|  <- b1 left shifted\n *   |22111111|  <- b0 OR b1\n *   |  111111|  <- (b0 OR b1) AND 63, our value.\n *   +--------+\n *\n * We can try with a different example, like pos = 0. In this case\n * the 6-bit counter is actually contained in a single byte.\n *\n *  b0 = 6 * pos / 8 = 0\n *\n *   +--------+\n *   |11000000|  <- Our byte at b0\n *   +--------+\n *\n *  fb = 6 * pos % 8 = 0\n *\n *  So we right shift of 0 bits (no shift in practice) and\n *  left shift the next byte of 8 bits, even if we don't use it,\n *  but this has the effect of clearing the bits so the result\n *  will not be affacted after the OR.\n *\n * -------------------------------------------------------------------------\n *\n * Setting the register is a bit more complex, let's assume that 'val'\n * is the value we want to set, already in the right range.\n *\n * We need two steps, in one we need to clear the bits, and in the other\n * we need to bitwise-OR the new bits.\n *\n * Let's try with 'pos' = 1, so our first byte at 'b' is 0,\n *\n * \"fb\" is 6 in this case.\n *\n *   +--------+\n *   |11000000|  <- Our byte at b0\n *   +--------+\n *\n * To create a AND-mask to clear the bits about this position, we just\n * initialize the mask with the value 63, left shift it of \"fs\" bits,\n * and finally invert the result.\n *\n *   +--------+\n *   |00111111|  <- \"mask\" starts at 63\n *   |11000000|  <- \"mask\" after left shift of \"ls\" bits.\n *   |00111111|  <- \"mask\" after invert.\n *   +--------+\n *\n * Now we can bitwise-AND the byte at \"b\" with the mask, and bitwise-OR\n * it with \"val\" left-shifted of \"ls\" bits to set the new bits.\n *\n * Now let's focus on the next byte b1:\n *\n *   +--------+\n *   |22221111|  <- Initial value of b1\n *   +--------+\n *\n * To build the AND mask we start again with the 63 value, right shift\n * it by 8-fb bits, and invert it.\n *\n *   +--------+\n *   |00111111|  <- \"mask\" set at 2&6-1\n *   |00001111|  <- \"mask\" after the right shift by 8-fb = 2 bits\n *   |11110000|  <- \"mask\" after bitwise not.\n *   +--------+\n *\n * Now we can mask it with b+1 to clear the old bits, and bitwise-OR\n * with \"val\" left-shifted by \"rs\" bits to set the new value.\n */\n\n/* Note: if we access the last counter, we will also access the b+1 byte\n * that is out of the array, but sds strings always have an implicit null\n * term, so the byte exists, and we can skip the conditional (or the need\n * to allocate 1 byte more explicitly). */\n\n/* Store the value of the register at position 'regnum' into variable 'target'.\n * 'p' is an array of unsigned bytes. */\n#define HLL_DENSE_GET_REGISTER(target,p,regnum) do { \\\n    uint8_t *_p = (uint8_t*) p; \\\n    unsigned long _byte = regnum*HLL_BITS/8; \\\n    unsigned long _fb = regnum*HLL_BITS&7; \\\n    unsigned long _fb8 = 8 - _fb; \\\n    unsigned long b0 = _p[_byte]; \\\n    unsigned long b1 = _p[_byte+1]; \\\n    target = ((b0 >> _fb) | (b1 << _fb8)) & HLL_REGISTER_MAX; \\\n} while(0)\n\n/* Set the value of the register at position 'regnum' to 'val'.\n * 'p' is an array of unsigned bytes. */\n#define HLL_DENSE_SET_REGISTER(p,regnum,val) do { \\\n    uint8_t *_p = (uint8_t*) p; \\\n    unsigned long _byte = regnum*HLL_BITS/8; \\\n    unsigned long _fb = regnum*HLL_BITS&7; \\\n    unsigned long _fb8 = 8 - _fb; \\\n    unsigned long _v = val; \\\n    _p[_byte] &= ~(HLL_REGISTER_MAX << _fb); \\\n    _p[_byte] |= _v << _fb; \\\n    _p[_byte+1] &= ~(HLL_REGISTER_MAX >> _fb8); \\\n    _p[_byte+1] |= _v >> _fb8; \\\n} while(0)\n\n/* Macros to access the sparse representation.\n * The macros parameter is expected to be an uint8_t pointer. */\n#define HLL_SPARSE_XZERO_BIT 0x40 /* 01xxxxxx */\n#define HLL_SPARSE_VAL_BIT 0x80 /* 1vvvvvxx */\n#define HLL_SPARSE_IS_ZERO(p) (((*(p)) & 0xc0) == 0) /* 00xxxxxx */\n#define HLL_SPARSE_IS_XZERO(p) (((*(p)) & 0xc0) == HLL_SPARSE_XZERO_BIT)\n#define HLL_SPARSE_IS_VAL(p) ((*(p)) & HLL_SPARSE_VAL_BIT)\n#define HLL_SPARSE_ZERO_LEN(p) (((*(p)) & 0x3f)+1)\n#define HLL_SPARSE_XZERO_LEN(p) (((((*(p)) & 0x3f) << 8) | (*((p)+1)))+1)\n#define HLL_SPARSE_VAL_VALUE(p) ((((*(p)) >> 2) & 0x1f)+1)\n#define HLL_SPARSE_VAL_LEN(p) (((*(p)) & 0x3)+1)\n#define HLL_SPARSE_VAL_MAX_VALUE 32\n#define HLL_SPARSE_VAL_MAX_LEN 4\n#define HLL_SPARSE_ZERO_MAX_LEN 64\n#define HLL_SPARSE_XZERO_MAX_LEN 16384\n#define HLL_SPARSE_VAL_SET(p,val,len) do { \\\n    *(p) = (((val)-1)<<2|((len)-1))|HLL_SPARSE_VAL_BIT; \\\n} while(0)\n#define HLL_SPARSE_ZERO_SET(p,len) do { \\\n    *(p) = (len)-1; \\\n} while(0)\n#define HLL_SPARSE_XZERO_SET(p,len) do { \\\n    int _l = (len)-1; \\\n    *(p) = (_l>>8) | HLL_SPARSE_XZERO_BIT; \\\n    *((p)+1) = (_l&0xff); \\\n} while(0)\n\n/* ========================= HyperLogLog algorithm  ========================= */\n\n/* Our hash function is MurmurHash2, 64 bit version.\n * It was modified for Redis in order to provide the same result in\n * big and little endian archs (endian neutral). */\nuint64_t MurmurHash64A (const void * key, int len, unsigned int seed) {\n    const uint64_t m = 0xc6a4a7935bd1e995;\n    const int r = 47;\n    uint64_t h = seed ^ (len * m);\n    const uint8_t *data = (const uint8_t *)key;\n    const uint8_t *end = data + (len-(len&7));\n\n    while(data != end) {\n        uint64_t k;\n\n#if (BYTE_ORDER == LITTLE_ENDIAN)\n        k = *((uint64_t*)data);\n#else\n        k = (uint64_t) data[0];\n        k |= (uint64_t) data[1] << 8;\n        k |= (uint64_t) data[2] << 16;\n        k |= (uint64_t) data[3] << 24;\n        k |= (uint64_t) data[4] << 32;\n        k |= (uint64_t) data[5] << 40;\n        k |= (uint64_t) data[6] << 48;\n        k |= (uint64_t) data[7] << 56;\n#endif\n\n        k *= m;\n        k ^= k >> r;\n        k *= m;\n        h ^= k;\n        h *= m;\n        data += 8;\n    }\n\n    switch(len & 7) {\n    case 7: h ^= (uint64_t)data[6] << 48;\n    case 6: h ^= (uint64_t)data[5] << 40;\n    case 5: h ^= (uint64_t)data[4] << 32;\n    case 4: h ^= (uint64_t)data[3] << 24;\n    case 3: h ^= (uint64_t)data[2] << 16;\n    case 2: h ^= (uint64_t)data[1] << 8;\n    case 1: h ^= (uint64_t)data[0];\n            h *= m;\n    };\n\n    h ^= h >> r;\n    h *= m;\n    h ^= h >> r;\n    return h;\n}\n\n/* Given a string element to add to the HyperLogLog, returns the length\n * of the pattern 000..1 of the element hash. As a side effect 'regp' is\n * set to the register index this element hashes to. */\nint hllPatLen(unsigned char *ele, size_t elesize, long *regp) {\n    uint64_t hash, bit, index;\n    int count;\n\n    /* Count the number of zeroes starting from bit HLL_REGISTERS\n     * (that is a power of two corresponding to the first bit we don't use\n     * as index). The max run can be 64-P+1 bits.\n     *\n     * Note that the final \"1\" ending the sequence of zeroes must be\n     * included in the count, so if we find \"001\" the count is 3, and\n     * the smallest count possible is no zeroes at all, just a 1 bit\n     * at the first position, that is a count of 1.\n     *\n     * This may sound like inefficient, but actually in the average case\n     * there are high probabilities to find a 1 after a few iterations. */\n    hash = MurmurHash64A(ele,elesize,0xadc83b19ULL);\n    index = hash & HLL_P_MASK; /* Register index. */\n    hash |= ((uint64_t)1<<63); /* Make sure the loop terminates. */\n    bit = HLL_REGISTERS; /* First bit not used to address the register. */\n    count = 1; /* Initialized to 1 since we count the \"00000...1\" pattern. */\n    while((hash & bit) == 0) {\n        count++;\n        bit <<= 1;\n    }\n    *regp = (int) index;\n    return count;\n}\n\n/* ================== Dense representation implementation  ================== */\n\n/* \"Add\" the element in the dense hyperloglog data structure.\n * Actually nothing is added, but the max 0 pattern counter of the subset\n * the element belongs to is incremented if needed.\n *\n * 'registers' is expected to have room for HLL_REGISTERS plus an\n * additional byte on the right. This requirement is met by sds strings\n * automatically since they are implicitly null terminated.\n *\n * The function always succeed, however if as a result of the operation\n * the approximated cardinality changed, 1 is returned. Otherwise 0\n * is returned. */\nint hllDenseAdd(uint8_t *registers, unsigned char *ele, size_t elesize) {\n    uint8_t oldcount, count;\n    long index;\n\n    /* Update the register if this element produced a longer run of zeroes. */\n    count = hllPatLen(ele,elesize,&index);\n    HLL_DENSE_GET_REGISTER(oldcount,registers,index);\n    if (count > oldcount) {\n        HLL_DENSE_SET_REGISTER(registers,index,count);\n        return 1;\n    } else {\n        return 0;\n    }\n}\n\n/* Compute SUM(2^-reg) in the dense representation.\n * PE is an array with a pre-computer table of values 2^-reg indexed by reg.\n * As a side effect the integer pointed by 'ezp' is set to the number\n * of zero registers. */\ndouble hllDenseSum(uint8_t *registers, double *PE, int *ezp) {\n    double E = 0;\n    int j, ez = 0;\n\n    /* Redis default is to use 16384 registers 6 bits each. The code works\n     * with other values by modifying the defines, but for our target value\n     * we take a faster path with unrolled loops. */\n    if (HLL_REGISTERS == 16384 && HLL_BITS == 6) {\n        uint8_t *r = registers;\n        unsigned long r0, r1, r2, r3, r4, r5, r6, r7, r8, r9,\n                      r10, r11, r12, r13, r14, r15;\n        for (j = 0; j < 1024; j++) {\n            /* Handle 16 registers per iteration. */\n            r0 = r[0] & 63; if (r0 == 0) ez++;\n            r1 = (r[0] >> 6 | r[1] << 2) & 63; if (r1 == 0) ez++;\n            r2 = (r[1] >> 4 | r[2] << 4) & 63; if (r2 == 0) ez++;\n            r3 = (r[2] >> 2) & 63; if (r3 == 0) ez++;\n            r4 = r[3] & 63; if (r4 == 0) ez++;\n            r5 = (r[3] >> 6 | r[4] << 2) & 63; if (r5 == 0) ez++;\n            r6 = (r[4] >> 4 | r[5] << 4) & 63; if (r6 == 0) ez++;\n            r7 = (r[5] >> 2) & 63; if (r7 == 0) ez++;\n            r8 = r[6] & 63; if (r8 == 0) ez++;\n            r9 = (r[6] >> 6 | r[7] << 2) & 63; if (r9 == 0) ez++;\n            r10 = (r[7] >> 4 | r[8] << 4) & 63; if (r10 == 0) ez++;\n            r11 = (r[8] >> 2) & 63; if (r11 == 0) ez++;\n            r12 = r[9] & 63; if (r12 == 0) ez++;\n            r13 = (r[9] >> 6 | r[10] << 2) & 63; if (r13 == 0) ez++;\n            r14 = (r[10] >> 4 | r[11] << 4) & 63; if (r14 == 0) ez++;\n            r15 = (r[11] >> 2) & 63; if (r15 == 0) ez++;\n\n            /* Additional parens will allow the compiler to optimize the\n             * code more with a loss of precision that is not very relevant\n             * here (floating point math is not commutative!). */\n            E += (PE[r0] + PE[r1]) + (PE[r2] + PE[r3]) + (PE[r4] + PE[r5]) +\n                 (PE[r6] + PE[r7]) + (PE[r8] + PE[r9]) + (PE[r10] + PE[r11]) +\n                 (PE[r12] + PE[r13]) + (PE[r14] + PE[r15]);\n            r += 12;\n        }\n    } else {\n        for (j = 0; j < HLL_REGISTERS; j++) {\n            unsigned long reg;\n\n            HLL_DENSE_GET_REGISTER(reg,registers,j);\n            if (reg == 0) {\n                ez++;\n                /* Increment E at the end of the loop. */\n            } else {\n                E += PE[reg]; /* Precomputed 2^(-reg[j]). */\n            }\n        }\n        E += ez; /* Add 2^0 'ez' times. */\n    }\n    *ezp = ez;\n    return E;\n}\n\n/* ================== Sparse representation implementation  ================= */\n\n/* Convert the HLL with sparse representation given as input in its dense\n * representation. Both representations are represented by SDS strings, and\n * the input representation is freed as a side effect.\n *\n * The function returns REDIS_OK if the sparse representation was valid,\n * otherwise REDIS_ERR is returned if the representation was corrupted. */\nint hllSparseToDense(robj *o) {\n    sds sparse = o->ptr, dense;\n    struct hllhdr *hdr, *oldhdr = (struct hllhdr*)sparse;\n    int idx = 0, runlen, regval;\n    uint8_t *p = (uint8_t*)sparse, *end = p+sdslen(sparse);\n\n    /* If the representation is already the right one return ASAP. */\n    hdr = (struct hllhdr*) sparse;\n    if (hdr->encoding == HLL_DENSE) return REDIS_OK;\n\n    /* Create a string of the right size filled with zero bytes.\n     * Note that the cached cardinality is set to 0 as a side effect\n     * that is exactly the cardinality of an empty HLL. */\n    dense = sdsnewlen(NULL,HLL_DENSE_SIZE);\n    hdr = (struct hllhdr*) dense;\n    *hdr = *oldhdr; /* This will copy the magic and cached cardinality. */\n    hdr->encoding = HLL_DENSE;\n\n    /* Now read the sparse representation and set non-zero registers\n     * accordingly. */\n    p += HLL_HDR_SIZE;\n    while(p < end) {\n        if (HLL_SPARSE_IS_ZERO(p)) {\n            runlen = HLL_SPARSE_ZERO_LEN(p);\n            idx += runlen;\n            p++;\n        } else if (HLL_SPARSE_IS_XZERO(p)) {\n            runlen = HLL_SPARSE_XZERO_LEN(p);\n            idx += runlen;\n            p += 2;\n        } else {\n            runlen = HLL_SPARSE_VAL_LEN(p);\n            regval = HLL_SPARSE_VAL_VALUE(p);\n            while(runlen--) {\n                HLL_DENSE_SET_REGISTER(hdr->registers,idx,regval);\n                idx++;\n            }\n            p++;\n        }\n    }\n\n    /* If the sparse representation was valid, we expect to find idx\n     * set to HLL_REGISTERS. */\n    if (idx != HLL_REGISTERS) {\n        sdsfree(dense);\n        return REDIS_ERR;\n    }\n\n    /* Free the old representation and set the new one. */\n    sdsfree(o->ptr);\n    o->ptr = dense;\n    return REDIS_OK;\n}\n\n/* \"Add\" the element in the sparse hyperloglog data structure.\n * Actually nothing is added, but the max 0 pattern counter of the subset\n * the element belongs to is incremented if needed.\n *\n * The object 'o' is the String object holding the HLL. The function requires\n * a reference to the object in order to be able to enlarge the string if\n * needed.\n *\n * On success, the function returns 1 if the cardinality changed, or 0\n * if the register for this element was not updated.\n * On error (if the representation is invalid) -1 is returned.\n *\n * As a side effect the function may promote the HLL representation from\n * sparse to dense: this happens when a register requires to be set to a value\n * not representable with the sparse representation, or when the resulting\n * size would be greater than server.hll_sparse_max_bytes. */\nint hllSparseAdd(robj *o, unsigned char *ele, size_t elesize) {\n    struct hllhdr *hdr;\n    uint8_t oldcount, count, *sparse, *end, *p, *prev, *next;\n    long index, first, span;\n    long is_zero = 0, is_xzero = 0, is_val = 0, runlen = 0;\n\n    /* Update the register if this element produced a longer run of zeroes. */\n    count = hllPatLen(ele,elesize,&index);\n\n    /* If the count is too big to be representable by the sparse representation\n     * switch to dense representation. */\n    if (count > HLL_SPARSE_VAL_MAX_VALUE) goto promote;\n\n    /* When updating a sparse representation, sometimes we may need to\n     * enlarge the buffer for up to 3 bytes in the worst case (XZERO split\n     * into XZERO-VAL-XZERO). Make sure there is enough space right now\n     * so that the pointers we take during the execution of the function\n     * will be valid all the time. */\n    o->ptr = sdsMakeRoomFor(o->ptr,3);\n\n    /* Step 1: we need to locate the opcode we need to modify to check\n     * if a value update is actually needed. */\n    sparse = p = ((uint8_t*)o->ptr) + HLL_HDR_SIZE;\n    end = p + sdslen(o->ptr) - HLL_HDR_SIZE;\n\n    first = 0;\n    prev = NULL; /* Points to previos opcode at the end of the loop. */\n    next = NULL; /* Points to the next opcode at the end of the loop. */\n    span = 0;\n    while(p < end) {\n        long oplen;\n\n        /* Set span to the number of registers covered by this opcode.\n         *\n         * This is the most performance critical loop of the sparse\n         * representation. Sorting the conditionals from the most to the\n         * least frequent opcode in many-bytes sparse HLLs is faster. */\n        oplen = 1;\n        if (HLL_SPARSE_IS_ZERO(p)) {\n            span = HLL_SPARSE_ZERO_LEN(p);\n        } else if (HLL_SPARSE_IS_VAL(p)) {\n            span = HLL_SPARSE_VAL_LEN(p);\n        } else { /* XZERO. */\n            span = HLL_SPARSE_XZERO_LEN(p);\n            oplen = 2;\n        }\n        /* Break if this opcode covers the register as 'index'. */\n        if (index <= first+span-1) break;\n        prev = p;\n        p += oplen;\n        first += span;\n    }\n    if (span == 0) return -1; /* Invalid format. */\n\n    next = HLL_SPARSE_IS_XZERO(p) ? p+2 : p+1;\n    if (next >= end) next = NULL;\n\n    /* Cache current opcode type to avoid using the macro again and\n     * again for something that will not change.\n     * Also cache the run-length of the opcode. */\n    if (HLL_SPARSE_IS_ZERO(p)) {\n        is_zero = 1;\n        runlen = HLL_SPARSE_ZERO_LEN(p);\n    } else if (HLL_SPARSE_IS_XZERO(p)) {\n        is_xzero = 1;\n        runlen = HLL_SPARSE_XZERO_LEN(p);\n    } else {\n        is_val = 1;\n        runlen = HLL_SPARSE_VAL_LEN(p);\n    }\n\n    /* Step 2: After the loop:\n     *\n     * 'first' stores to the index of the first register covered\n     *  by the current opcode, which is pointed by 'p'.\n     *\n     * 'next' ad 'prev' store respectively the next and previous opcode,\n     *  or NULL if the opcode at 'p' is respectively the last or first.\n     *\n     * 'span' is set to the number of registers covered by the current\n     *  opcode.\n     *\n     * There are different cases in order to update the data structure\n     * in place without generating it from scratch:\n     *\n     * A) If it is a VAL opcode already set to a value >= our 'count'\n     *    no update is needed, regardless of the VAL run-length field.\n     *    In this case PFADD returns 0 since no changes are performed.\n     *\n     * B) If it is a VAL opcode with len = 1 (representing only our\n     *    register) and the value is less than 'count', we just update it\n     *    since this is a trivial case. */\n    if (is_val) {\n        oldcount = HLL_SPARSE_VAL_VALUE(p);\n        /* Case A. */\n        if (oldcount >= count) return 0;\n\n        /* Case B. */\n        if (runlen == 1) {\n            HLL_SPARSE_VAL_SET(p,count,1);\n            goto updated;\n        }\n    }\n\n    /* C) Another trivial to handle case is a ZERO opcode with a len of 1.\n     * We can just replace it with a VAL opcode with our value and len of 1. */\n    if (is_zero && runlen == 1) {\n        HLL_SPARSE_VAL_SET(p,count,1);\n        goto updated;\n    }\n\n    /* D) General case.\n     *\n     * The other cases are more complex: our register requires to be updated\n     * and is either currently represented by a VAL opcode with len > 1,\n     * by a ZERO opcode with len > 1, or by an XZERO opcode.\n     *\n     * In those cases the original opcode must be split into muliple\n     * opcodes. The worst case is an XZERO split in the middle resuling into\n     * XZERO - VAL - XZERO, so the resulting sequence max length is\n     * 5 bytes.\n     *\n     * We perform the split writing the new sequence into the 'new' buffer\n     * with 'newlen' as length. Later the new sequence is inserted in place\n     * of the old one, possibly moving what is on the right a few bytes\n     * if the new sequence is longer than the older one. */\n    uint8_t seq[5], *n = seq;\n    int last = first+span-1; /* Last register covered by the sequence. */\n    int len;\n\n    if (is_zero || is_xzero) {\n        /* Handle splitting of ZERO / XZERO. */\n        if (index != first) {\n            len = index-first;\n            if (len > HLL_SPARSE_ZERO_MAX_LEN) {\n                HLL_SPARSE_XZERO_SET(n,len);\n                n += 2;\n            } else {\n                HLL_SPARSE_ZERO_SET(n,len);\n                n++;\n            }\n        }\n        HLL_SPARSE_VAL_SET(n,count,1);\n        n++;\n        if (index != last) {\n            len = last-index;\n            if (len > HLL_SPARSE_ZERO_MAX_LEN) {\n                HLL_SPARSE_XZERO_SET(n,len);\n                n += 2;\n            } else {\n                HLL_SPARSE_ZERO_SET(n,len);\n                n++;\n            }\n        }\n    } else {\n        /* Handle splitting of VAL. */\n        int curval = HLL_SPARSE_VAL_VALUE(p);\n\n        if (index != first) {\n            len = index-first;\n            HLL_SPARSE_VAL_SET(n,curval,len);\n            n++;\n        }\n        HLL_SPARSE_VAL_SET(n,count,1);\n        n++;\n        if (index != last) {\n            len = last-index;\n            HLL_SPARSE_VAL_SET(n,curval,len);\n            n++;\n        }\n    }\n\n    /* Step 3: substitute the new sequence with the old one.\n     *\n     * Note that we already allocated space on the sds string\n     * calling sdsMakeRoomFor(). */\n     int seqlen = n-seq;\n     int oldlen = is_xzero ? 2 : 1;\n     int deltalen = seqlen-oldlen;\n\n     if (deltalen > 0 &&\n         sdslen(o->ptr)+deltalen > server.hll_sparse_max_bytes) goto promote;\n     if (deltalen && next) memmove(next+deltalen,next,end-next);\n     sdsIncrLen(o->ptr,deltalen);\n     memcpy(p,seq,seqlen);\n     end += deltalen;\n\nupdated:\n    /* Step 4: Merge adjacent values if possible.\n     *\n     * The representation was updated, however the resulting representation\n     * may not be optimal: adjacent VAL opcodes can sometimes be merged into\n     * a single one. */\n    p = prev ? prev : sparse;\n    int scanlen = 5; /* Scan up to 5 upcodes starting from prev. */\n    while (p < end && scanlen--) {\n        if (HLL_SPARSE_IS_XZERO(p)) {\n            p += 2;\n            continue;\n        } else if (HLL_SPARSE_IS_ZERO(p)) {\n            p++;\n            continue;\n        }\n        /* We need two adjacent VAL opcodes to try a merge, having\n         * the same value, and a len that fits the VAL opcode max len. */\n        if (p+1 < end && HLL_SPARSE_IS_VAL(p+1)) {\n            int v1 = HLL_SPARSE_VAL_VALUE(p);\n            int v2 = HLL_SPARSE_VAL_VALUE(p+1);\n            if (v1 == v2) {\n                int len = HLL_SPARSE_VAL_LEN(p)+HLL_SPARSE_VAL_LEN(p+1);\n                if (len <= HLL_SPARSE_VAL_MAX_LEN) {\n                    HLL_SPARSE_VAL_SET(p+1,v1,len);\n                    memmove(p,p+1,end-p);\n                    sdsIncrLen(o->ptr,-1);\n                    end--;\n                    /* After a merge we reiterate without incrementing 'p'\n                     * in order to try to merge the just merged value with\n                     * a value on its right. */\n                    continue;\n                }\n            }\n        }\n        p++;\n    }\n\n    /* Invalidate the cached cardinality. */\n    hdr = o->ptr;\n    HLL_INVALIDATE_CACHE(hdr);\n    return 1;\n\npromote: /* Promote to dense representation. */\n    if (hllSparseToDense(o) == REDIS_ERR) return -1; /* Corrupted HLL. */\n    hdr = o->ptr;\n\n    /* We need to call hllDenseAdd() to perform the operation after the\n     * conversion. However the result must be 1, since if we need to\n     * convert from sparse to dense a register requires to be updated.\n     *\n     * Note that this in turn means that PFADD will make sure the command\n     * is propagated to slaves / AOF, so if there is a sparse -> dense\n     * convertion, it will be performed in all the slaves as well. */\n    int dense_retval = hllDenseAdd(hdr->registers, ele, elesize);\n    redisAssert(dense_retval == 1);\n    return dense_retval;\n}\n\n/* Compute SUM(2^-reg) in the sparse representation.\n * PE is an array with a pre-computer table of values 2^-reg indexed by reg.\n * As a side effect the integer pointed by 'ezp' is set to the number\n * of zero registers. */\ndouble hllSparseSum(uint8_t *sparse, int sparselen, double *PE, int *ezp, int *invalid) {\n    double E = 0;\n    int ez = 0, idx = 0, runlen, regval;\n    uint8_t *end = sparse+sparselen, *p = sparse;\n\n    while(p < end) {\n        if (HLL_SPARSE_IS_ZERO(p)) {\n            runlen = HLL_SPARSE_ZERO_LEN(p);\n            idx += runlen;\n            ez += runlen;\n            /* Increment E at the end of the loop. */\n            p++;\n        } else if (HLL_SPARSE_IS_XZERO(p)) {\n            runlen = HLL_SPARSE_XZERO_LEN(p);\n            idx += runlen;\n            ez += runlen;\n            /* Increment E at the end of the loop. */\n            p += 2;\n        } else {\n            runlen = HLL_SPARSE_VAL_LEN(p);\n            regval = HLL_SPARSE_VAL_VALUE(p);\n            idx += runlen;\n            E += PE[regval]*runlen;\n            p++;\n        }\n    }\n    if (idx != HLL_REGISTERS && invalid) *invalid = 1;\n    E += ez; /* Add 2^0 'ez' times. */\n    *ezp = ez;\n    return E;\n}\n\n/* ========================= HyperLogLog Count ==============================\n * This is the core of the algorithm where the approximated count is computed.\n * The function uses the lower level hllDenseSum() and hllSparseSum() functions\n * as helpers to compute the SUM(2^-reg) part of the computation, which is\n * representation-specific, while all the rest is common. */\n\n/* Implements the SUM operation for uint8_t data type which is only used\n * internally as speedup for PFCOUNT with multiple keys. */\ndouble hllRawSum(uint8_t *registers, double *PE, int *ezp) {\n    double E = 0;\n    int j, ez = 0;\n    uint64_t *word = (uint64_t*) registers;\n    uint8_t *bytes;\n\n    for (j = 0; j < HLL_REGISTERS/8; j++) {\n        if (*word == 0) {\n            ez += 8;\n        } else {\n            bytes = (uint8_t*) word;\n            if (bytes[0]) E += PE[bytes[0]]; else ez++;\n            if (bytes[1]) E += PE[bytes[1]]; else ez++;\n            if (bytes[2]) E += PE[bytes[2]]; else ez++;\n            if (bytes[3]) E += PE[bytes[3]]; else ez++;\n            if (bytes[4]) E += PE[bytes[4]]; else ez++;\n            if (bytes[5]) E += PE[bytes[5]]; else ez++;\n            if (bytes[6]) E += PE[bytes[6]]; else ez++;\n            if (bytes[7]) E += PE[bytes[7]]; else ez++;\n        }\n        word++;\n    }\n    E += ez; /* 2^(-reg[j]) is 1 when m is 0, add it 'ez' times for every\n                zero register in the HLL. */\n    *ezp = ez;\n    return E;\n}\n\n/* Return the approximated cardinality of the set based on the harmonic\n * mean of the registers values. 'hdr' points to the start of the SDS\n * representing the String object holding the HLL representation.\n *\n * If the sparse representation of the HLL object is not valid, the integer\n * pointed by 'invalid' is set to non-zero, otherwise it is left untouched.\n *\n * hllCount() supports a special internal-only encoding of HLL_RAW, that\n * is, hdr->registers will point to an uint8_t array of HLL_REGISTERS element.\n * This is useful in order to speedup PFCOUNT when called against multiple\n * keys (no need to work with 6-bit integers encoding). */\nuint64_t hllCount(struct hllhdr *hdr, int *invalid) {\n    double m = HLL_REGISTERS;\n    double E, alpha = 0.7213/(1+1.079/m);\n    int j, ez; /* Number of registers equal to 0. */\n\n    /* We precompute 2^(-reg[j]) in a small table in order to\n     * speedup the computation of SUM(2^-register[0..i]). */\n    static int initialized = 0;\n    static double PE[64];\n    if (!initialized) {\n        PE[0] = 1; /* 2^(-reg[j]) is 1 when m is 0. */\n        for (j = 1; j < 64; j++) {\n            /* 2^(-reg[j]) is the same as 1/2^reg[j]. */\n            PE[j] = 1.0/(1ULL << j);\n        }\n        initialized = 1;\n    }\n\n    /* Compute SUM(2^-register[0..i]). */\n    if (hdr->encoding == HLL_DENSE) {\n        E = hllDenseSum(hdr->registers,PE,&ez);\n    } else if (hdr->encoding == HLL_SPARSE) {\n        E = hllSparseSum(hdr->registers,\n                         sdslen((sds)hdr)-HLL_HDR_SIZE,PE,&ez,invalid);\n    } else if (hdr->encoding == HLL_RAW) {\n        E = hllRawSum(hdr->registers,PE,&ez);\n    } else {\n        redisPanic(\"Unknown HyperLogLog encoding in hllCount()\");\n    }\n\n    /* Muliply the inverse of E for alpha_m * m^2 to have the raw estimate. */\n    E = (1/E)*alpha*m*m;\n\n    /* Use the LINEARCOUNTING algorithm for small cardinalities.\n     * For larger values but up to 72000 HyperLogLog raw approximation is\n     * used since linear counting error starts to increase. However HyperLogLog\n     * shows a strong bias in the range 2.5*16384 - 72000, so we try to\n     * compensate for it. */\n    if (E < m*2.5 && ez != 0) {\n        E = m*log(m/ez); /* LINEARCOUNTING() */\n    } else if (m == 16384 && E < 72000) {\n        /* We did polynomial regression of the bias for this range, this\n         * way we can compute the bias for a given cardinality and correct\n         * according to it. Only apply the correction for P=14 that's what\n         * we use and the value the correction was verified with. */\n        double bias = 5.9119*1.0e-18*(E*E*E*E)\n                      -1.4253*1.0e-12*(E*E*E)+\n                      1.2940*1.0e-7*(E*E)\n                      -5.2921*1.0e-3*E+\n                      83.3216;\n        E -= E*(bias/100);\n    }\n    /* We don't apply the correction for E > 1/30 of 2^32 since we use\n     * a 64 bit function and 6 bit counters. To apply the correction for\n     * 1/30 of 2^64 is not needed since it would require a huge set\n     * to approach such a value. */\n    return (uint64_t) E;\n}\n\n/* Call hllDenseAdd() or hllSparseAdd() according to the HLL encoding. */\nint hllAdd(robj *o, unsigned char *ele, size_t elesize) {\n    struct hllhdr *hdr = o->ptr;\n    switch(hdr->encoding) {\n    case HLL_DENSE: return hllDenseAdd(hdr->registers,ele,elesize);\n    case HLL_SPARSE: return hllSparseAdd(o,ele,elesize);\n    default: return -1; /* Invalid representation. */\n    }\n}\n\n/* Merge by computing MAX(registers[i],hll[i]) the HyperLogLog 'hll'\n * with an array of uint8_t HLL_REGISTERS registers pointed by 'max'.\n *\n * The hll object must be already validated via isHLLObjectOrReply()\n * or in some other way.\n *\n * If the HyperLogLog is sparse and is found to be invalid, REDIS_ERR\n * is returned, otherwise the function always succeeds. */\nint hllMerge(uint8_t *max, robj *hll) {\n    struct hllhdr *hdr = hll->ptr;\n    int i;\n\n    if (hdr->encoding == HLL_DENSE) {\n        uint8_t val;\n\n        for (i = 0; i < HLL_REGISTERS; i++) {\n            HLL_DENSE_GET_REGISTER(val,hdr->registers,i);\n            if (val > max[i]) max[i] = val;\n        }\n    } else {\n        uint8_t *p = hll->ptr, *end = p + sdslen(hll->ptr);\n        long runlen, regval;\n\n        p += HLL_HDR_SIZE;\n        i = 0;\n        while(p < end) {\n            if (HLL_SPARSE_IS_ZERO(p)) {\n                runlen = HLL_SPARSE_ZERO_LEN(p);\n                i += runlen;\n                p++;\n            } else if (HLL_SPARSE_IS_XZERO(p)) {\n                runlen = HLL_SPARSE_XZERO_LEN(p);\n                i += runlen;\n                p += 2;\n            } else {\n                runlen = HLL_SPARSE_VAL_LEN(p);\n                regval = HLL_SPARSE_VAL_VALUE(p);\n                while(runlen--) {\n                    if (regval > max[i]) max[i] = regval;\n                    i++;\n                }\n                p++;\n            }\n        }\n        if (i != HLL_REGISTERS) return REDIS_ERR;\n    }\n    return REDIS_OK;\n}\n\n/* ========================== HyperLogLog commands ========================== */\n\n/* Create an HLL object. We always create the HLL using sparse encoding.\n * This will be upgraded to the dense representation as needed. */\nrobj *createHLLObject(void) {\n    robj *o;\n    struct hllhdr *hdr;\n    sds s;\n    uint8_t *p;\n    int sparselen = HLL_HDR_SIZE +\n                    (((HLL_REGISTERS+(HLL_SPARSE_XZERO_MAX_LEN-1)) /\n                     HLL_SPARSE_XZERO_MAX_LEN)*2);\n    int aux;\n\n    /* Populate the sparse representation with as many XZERO opcodes as\n     * needed to represent all the registers. */\n    aux = HLL_REGISTERS;\n    s = sdsnewlen(NULL,sparselen);\n    p = (uint8_t*)s + HLL_HDR_SIZE;\n    while(aux) {\n        int xzero = HLL_SPARSE_XZERO_MAX_LEN;\n        if (xzero > aux) xzero = aux;\n        HLL_SPARSE_XZERO_SET(p,xzero);\n        p += 2;\n        aux -= xzero;\n    }\n    redisAssert((p-(uint8_t*)s) == sparselen);\n\n    /* Create the actual object. */\n    o = createObject(REDIS_STRING,s);\n    hdr = o->ptr;\n    memcpy(hdr->magic,\"HYLL\",4);\n    hdr->encoding = HLL_SPARSE;\n    return o;\n}\n\n/* Check if the object is a String with a valid HLL representation.\n * Return REDIS_OK if this is true, otherwise reply to the client\n * with an error and return REDIS_ERR. */\nint isHLLObjectOrReply(redisClient *c, robj *o) {\n    struct hllhdr *hdr;\n\n    /* Key exists, check type */\n    if (checkType(c,o,REDIS_STRING))\n        return REDIS_ERR; /* Error already sent. */\n\n    if (stringObjectLen(o) < sizeof(*hdr)) goto invalid;\n    hdr = o->ptr;\n\n    /* Magic should be \"HYLL\". */\n    if (hdr->magic[0] != 'H' || hdr->magic[1] != 'Y' ||\n        hdr->magic[2] != 'L' || hdr->magic[3] != 'L') goto invalid;\n\n    if (hdr->encoding > HLL_MAX_ENCODING) goto invalid;\n\n    /* Dense representation string length should match exactly. */\n    if (hdr->encoding == HLL_DENSE &&\n        stringObjectLen(o) != HLL_DENSE_SIZE) goto invalid;\n\n    /* All tests passed. */\n    return REDIS_OK;\n\ninvalid:\n    addReplySds(c,\n        sdsnew(\"-WRONGTYPE Key is not a valid \"\n               \"HyperLogLog string value.\\r\\n\"));\n    return REDIS_ERR;\n}\n\n/* PFADD var ele ele ele ... ele => :0 or :1 */\nvoid pfaddCommand(redisClient *c) {\n    robj *o = lookupKeyWrite(c->db,c->argv[1]);\n    struct hllhdr *hdr;\n    int updated = 0, j;\n\n    if (o == NULL) {\n        /* Create the key with a string value of the exact length to\n         * hold our HLL data structure. sdsnewlen() when NULL is passed\n         * is guaranteed to return bytes initialized to zero. */\n        o = createHLLObject();\n        dbAdd(c->db,c->argv[1],o);\n        updated++;\n    } else {\n        if (isHLLObjectOrReply(c,o) != REDIS_OK) return;\n        o = dbUnshareStringValue(c->db,c->argv[1],o);\n    }\n    /* Perform the low level ADD operation for every element. */\n    for (j = 2; j < c->argc; j++) {\n        int retval = hllAdd(o, (unsigned char*)c->argv[j]->ptr,\n                               sdslen(c->argv[j]->ptr));\n        switch(retval) {\n        case 1:\n            updated++;\n            break;\n        case -1:\n            addReplySds(c,sdsnew(invalid_hll_err));\n            return;\n        }\n    }\n    hdr = o->ptr;\n    if (updated) {\n        signalModifiedKey(c->db,c->argv[1]);\n        notifyKeyspaceEvent(REDIS_NOTIFY_STRING,\"pfadd\",c->argv[1],c->db->id);\n        server.dirty++;\n        HLL_INVALIDATE_CACHE(hdr);\n    }\n    addReply(c, updated ? shared.cone : shared.czero);\n}\n\n/* PFCOUNT var -> approximated cardinality of set. */\nvoid pfcountCommand(redisClient *c) {\n    robj *o;\n    struct hllhdr *hdr;\n    uint64_t card;\n\n    /* Case 1: multi-key keys, cardinality of the union.\n     *\n     * When multiple keys are specified, PFCOUNT actually computes\n     * the cardinality of the merge of the N HLLs specified. */\n    if (c->argc > 2) {\n        uint8_t max[HLL_HDR_SIZE+HLL_REGISTERS], *registers;\n        int j;\n\n        /* Compute an HLL with M[i] = MAX(M[i]_j). */\n        memset(max,0,sizeof(max));\n        hdr = (struct hllhdr*) max;\n        hdr->encoding = HLL_RAW; /* Special internal-only encoding. */\n        registers = max + HLL_HDR_SIZE;\n        for (j = 1; j < c->argc; j++) {\n            /* Check type and size. */\n            robj *o = lookupKeyRead(c->db,c->argv[j]);\n            if (o == NULL) continue; /* Assume empty HLL for non existing var.*/\n            if (isHLLObjectOrReply(c,o) != REDIS_OK) return;\n\n            /* Merge with this HLL with our 'max' HHL by setting max[i]\n             * to MAX(max[i],hll[i]). */\n            if (hllMerge(registers,o) == REDIS_ERR) {\n                addReplySds(c,sdsnew(invalid_hll_err));\n                return;\n            }\n        }\n\n        /* Compute cardinality of the resulting set. */\n        addReplyLongLong(c,hllCount(hdr,NULL));\n        return;\n    }\n\n    /* Case 2: cardinality of the single HLL.\n     *\n     * The user specified a single key. Either return the cached value\n     * or compute one and update the cache. */\n    o = lookupKeyRead(c->db,c->argv[1]);\n    if (o == NULL) {\n        /* No key? Cardinality is zero since no element was added, otherwise\n         * we would have a key as HLLADD creates it as a side effect. */\n        addReply(c,shared.czero);\n    } else {\n        if (isHLLObjectOrReply(c,o) != REDIS_OK) return;\n        o = dbUnshareStringValue(c->db,c->argv[1],o);\n\n        /* Check if the cached cardinality is valid. */\n        hdr = o->ptr;\n        if (HLL_VALID_CACHE(hdr)) {\n            /* Just return the cached value. */\n            card = (uint64_t)hdr->card[0];\n            card |= (uint64_t)hdr->card[1] << 8;\n            card |= (uint64_t)hdr->card[2] << 16;\n            card |= (uint64_t)hdr->card[3] << 24;\n            card |= (uint64_t)hdr->card[4] << 32;\n            card |= (uint64_t)hdr->card[5] << 40;\n            card |= (uint64_t)hdr->card[6] << 48;\n            card |= (uint64_t)hdr->card[7] << 56;\n        } else {\n            int invalid = 0;\n            /* Recompute it and update the cached value. */\n            card = hllCount(hdr,&invalid);\n            if (invalid) {\n                addReplySds(c,sdsnew(invalid_hll_err));\n                return;\n            }\n            hdr->card[0] = card & 0xff;\n            hdr->card[1] = (card >> 8) & 0xff;\n            hdr->card[2] = (card >> 16) & 0xff;\n            hdr->card[3] = (card >> 24) & 0xff;\n            hdr->card[4] = (card >> 32) & 0xff;\n            hdr->card[5] = (card >> 40) & 0xff;\n            hdr->card[6] = (card >> 48) & 0xff;\n            hdr->card[7] = (card >> 56) & 0xff;\n            /* This is not considered a read-only command even if the\n             * data structure is not modified, since the cached value\n             * may be modified and given that the HLL is a Redis string\n             * we need to propagate the change. */\n            signalModifiedKey(c->db,c->argv[1]);\n            server.dirty++;\n        }\n        addReplyLongLong(c,card);\n    }\n}\n\n/* PFMERGE dest src1 src2 src3 ... srcN => OK */\nvoid pfmergeCommand(redisClient *c) {\n    uint8_t max[HLL_REGISTERS];\n    struct hllhdr *hdr;\n    int j;\n\n    /* Compute an HLL with M[i] = MAX(M[i]_j).\n     * We we the maximum into the max array of registers. We'll write\n     * it to the target variable later. */\n    memset(max,0,sizeof(max));\n    for (j = 1; j < c->argc; j++) {\n        /* Check type and size. */\n        robj *o = lookupKeyRead(c->db,c->argv[j]);\n        if (o == NULL) continue; /* Assume empty HLL for non existing var. */\n        if (isHLLObjectOrReply(c,o) != REDIS_OK) return;\n\n        /* Merge with this HLL with our 'max' HHL by setting max[i]\n         * to MAX(max[i],hll[i]). */\n        if (hllMerge(max,o) == REDIS_ERR) {\n            addReplySds(c,sdsnew(invalid_hll_err));\n            return;\n        }\n    }\n\n    /* Create / unshare the destination key's value if needed. */\n    robj *o = lookupKeyWrite(c->db,c->argv[1]);\n    if (o == NULL) {\n        /* Create the key with a string value of the exact length to\n         * hold our HLL data structure. sdsnewlen() when NULL is passed\n         * is guaranteed to return bytes initialized to zero. */\n        o = createHLLObject();\n        dbAdd(c->db,c->argv[1],o);\n    } else {\n        /* If key exists we are sure it's of the right type/size\n         * since we checked when merging the different HLLs, so we\n         * don't check again. */\n        o = dbUnshareStringValue(c->db,c->argv[1],o);\n    }\n\n    /* Only support dense objects as destination. */\n    if (hllSparseToDense(o) == REDIS_ERR) {\n        addReplySds(c,sdsnew(invalid_hll_err));\n        return;\n    }\n\n    /* Write the resulting HLL to the destination HLL registers and\n     * invalidate the cached value. */\n    hdr = o->ptr;\n    for (j = 0; j < HLL_REGISTERS; j++) {\n        HLL_DENSE_SET_REGISTER(hdr->registers,j,max[j]);\n    }\n    HLL_INVALIDATE_CACHE(hdr);\n\n    signalModifiedKey(c->db,c->argv[1]);\n    /* We generate an PFADD event for PFMERGE for semantical simplicity\n     * since in theory this is a mass-add of elements. */\n    notifyKeyspaceEvent(REDIS_NOTIFY_STRING,\"pfadd\",c->argv[1],c->db->id);\n    server.dirty++;\n    addReply(c,shared.ok);\n}\n\n/* ========================== Testing / Debugging  ========================== */\n\n/* PFSELFTEST\n * This command performs a self-test of the HLL registers implementation.\n * Something that is not easy to test from within the outside. */\n#define HLL_TEST_CYCLES 1000\nvoid pfselftestCommand(redisClient *c) {\n    unsigned int j, i;\n    sds bitcounters = sdsnewlen(NULL,HLL_DENSE_SIZE);\n    struct hllhdr *hdr = (struct hllhdr*) bitcounters, *hdr2;\n    robj *o = NULL;\n    uint8_t bytecounters[HLL_REGISTERS];\n\n    /* Test 1: access registers.\n     * The test is conceived to test that the different counters of our data\n     * structure are accessible and that setting their values both result in\n     * the correct value to be retained and not affect adjacent values. */\n    for (j = 0; j < HLL_TEST_CYCLES; j++) {\n        /* Set the HLL counters and an array of unsigned byes of the\n         * same size to the same set of random values. */\n        for (i = 0; i < HLL_REGISTERS; i++) {\n            unsigned int r = rand() & HLL_REGISTER_MAX;\n\n            bytecounters[i] = r;\n            HLL_DENSE_SET_REGISTER(hdr->registers,i,r);\n        }\n        /* Check that we are able to retrieve the same values. */\n        for (i = 0; i < HLL_REGISTERS; i++) {\n            unsigned int val;\n\n            HLL_DENSE_GET_REGISTER(val,hdr->registers,i);\n            if (val != bytecounters[i]) {\n                addReplyErrorFormat(c,\n                    \"TESTFAILED Register %d should be %d but is %d\",\n                    i, (int) bytecounters[i], (int) val);\n                goto cleanup;\n            }\n        }\n    }\n\n    /* Test 2: approximation error.\n     * The test adds unique elements and check that the estimated value\n     * is always reasonable bounds.\n     *\n     * We check that the error is smaller than a few times than the expected\n     * standard error, to make it very unlikely for the test to fail because\n     * of a \"bad\" run.\n     *\n     * The test is performed with both dense and sparse HLLs at the same\n     * time also verifying that the computed cardinality is the same. */\n    memset(hdr->registers,0,HLL_DENSE_SIZE-HLL_HDR_SIZE);\n    o = createHLLObject();\n    double relerr = 1.04/sqrt(HLL_REGISTERS);\n    int64_t checkpoint = 1;\n    uint64_t seed = (uint64_t)rand() | (uint64_t)rand() << 32;\n    uint64_t ele;\n    for (j = 1; j <= 10000000; j++) {\n        ele = j ^ seed;\n        hllDenseAdd(hdr->registers,(unsigned char*)&ele,sizeof(ele));\n        hllAdd(o,(unsigned char*)&ele,sizeof(ele));\n\n        /* Make sure that for small cardinalities we use sparse\n         * encoding. */\n        if (j == checkpoint && j < server.hll_sparse_max_bytes/2) {\n            hdr2 = o->ptr;\n            if (hdr2->encoding != HLL_SPARSE) {\n                addReplyError(c, \"TESTFAILED sparse encoding not used\");\n                goto cleanup;\n            }\n        }\n\n        /* Check that dense and sparse representations agree. */\n        if (j == checkpoint && hllCount(hdr,NULL) != hllCount(o->ptr,NULL)) {\n                addReplyError(c, \"TESTFAILED dense/sparse disagree\");\n                goto cleanup;\n        }\n\n        /* Check error. */\n        if (j == checkpoint) {\n            int64_t abserr = checkpoint - (int64_t)hllCount(hdr,NULL);\n            uint64_t maxerr = ceil(relerr*6*checkpoint);\n\n            /* Adjust the max error we expect for cardinality 10\n             * since from time to time it is statistically likely to get\n             * much higher error due to collision, resulting into a false\n             * positive. */\n            if (j == 10) maxerr = 1;\n\n            if (abserr < 0) abserr = -abserr;\n            if (abserr > (int64_t)maxerr) {\n                addReplyErrorFormat(c,\n                    \"TESTFAILED Too big error. card:%llu abserr:%llu\",\n                    (unsigned long long) checkpoint,\n                    (unsigned long long) abserr);\n                goto cleanup;\n            }\n            checkpoint *= 10;\n        }\n    }\n\n    /* Success! */\n    addReply(c,shared.ok);\n\ncleanup:\n    sdsfree(bitcounters);\n    if (o) decrRefCount(o);\n}\n\n/* PFDEBUG <subcommand> <key> ... args ...\n * Different debugging related operations about the HLL implementation. */\nvoid pfdebugCommand(redisClient *c) {\n    char *cmd = c->argv[1]->ptr;\n    struct hllhdr *hdr;\n    robj *o;\n    int j;\n\n    o = lookupKeyRead(c->db,c->argv[2]);\n    if (o == NULL) {\n        addReplyError(c,\"The specified key does not exist\");\n        return;\n    }\n    if (isHLLObjectOrReply(c,o) != REDIS_OK) return;\n    o = dbUnshareStringValue(c->db,c->argv[2],o);\n    hdr = o->ptr;\n\n    /* PFDEBUG GETREG <key> */\n    if (!strcasecmp(cmd,\"getreg\")) {\n        if (c->argc != 3) goto arityerr;\n\n        if (hdr->encoding == HLL_SPARSE) {\n            if (hllSparseToDense(o) == REDIS_ERR) {\n                addReplySds(c,sdsnew(invalid_hll_err));\n                return;\n            }\n            server.dirty++; /* Force propagation on encoding change. */\n        }\n\n        hdr = o->ptr;\n        addReplyMultiBulkLen(c,HLL_REGISTERS);\n        for (j = 0; j < HLL_REGISTERS; j++) {\n            uint8_t val;\n\n            HLL_DENSE_GET_REGISTER(val,hdr->registers,j);\n            addReplyLongLong(c,val);\n        }\n    }\n    /* PFDEBUG DECODE <key> */\n    else if (!strcasecmp(cmd,\"decode\")) {\n        if (c->argc != 3) goto arityerr;\n\n        uint8_t *p = o->ptr, *end = p+sdslen(o->ptr);\n        sds decoded = sdsempty();\n\n        if (hdr->encoding != HLL_SPARSE) {\n            addReplyError(c,\"HLL encoding is not sparse\");\n            return;\n        }\n\n        p += HLL_HDR_SIZE;\n        while(p < end) {\n            int runlen, regval;\n\n            if (HLL_SPARSE_IS_ZERO(p)) {\n                runlen = HLL_SPARSE_ZERO_LEN(p);\n                p++;\n                decoded = sdscatprintf(decoded,\"z:%d \",runlen);\n            } else if (HLL_SPARSE_IS_XZERO(p)) {\n                runlen = HLL_SPARSE_XZERO_LEN(p);\n                p += 2;\n                decoded = sdscatprintf(decoded,\"Z:%d \",runlen);\n            } else {\n                runlen = HLL_SPARSE_VAL_LEN(p);\n                regval = HLL_SPARSE_VAL_VALUE(p);\n                p++;\n                decoded = sdscatprintf(decoded,\"v:%d,%d \",regval,runlen);\n            }\n        }\n        decoded = sdstrim(decoded,\" \");\n        addReplyBulkCBuffer(c,decoded,sdslen(decoded));\n        sdsfree(decoded);\n    }\n    /* PFDEBUG ENCODING <key> */\n    else if (!strcasecmp(cmd,\"encoding\")) {\n        char *encodingstr[2] = {\"dense\",\"sparse\"};\n        if (c->argc != 3) goto arityerr;\n\n        addReplyStatus(c,encodingstr[hdr->encoding]);\n    }\n    /* PFDEBUG TODENSE <key> */\n    else if (!strcasecmp(cmd,\"todense\")) {\n        int conv = 0;\n        if (c->argc != 3) goto arityerr;\n\n        if (hdr->encoding == HLL_SPARSE) {\n            if (hllSparseToDense(o) == REDIS_ERR) {\n                addReplySds(c,sdsnew(invalid_hll_err));\n                return;\n            }\n            conv = 1;\n            server.dirty++; /* Force propagation on encoding change. */\n        }\n        addReply(c,conv ? shared.cone : shared.czero);\n    } else {\n        addReplyErrorFormat(c,\"Unknown PFDEBUG subcommand '%s'\", cmd);\n    }\n    return;\n\narityerr:\n    addReplyErrorFormat(c,\n        \"Wrong number of arguments for the '%s' subcommand\",cmd);\n}\n\n"
  },
  {
    "path": "extern/deprecated/redis-2.8.21/src/intset.c",
    "content": "/*\n * Copyright (c) 2009-2012, Pieter Noordhuis <pcnoordhuis at gmail dot com>\n * Copyright (c) 2009-2012, Salvatore Sanfilippo <antirez at gmail dot com>\n * All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions are met:\n *\n *   * Redistributions of source code must retain the above copyright notice,\n *     this list of conditions and the following disclaimer.\n *   * Redistributions in binary form must reproduce the above copyright\n *     notice, this list of conditions and the following disclaimer in the\n *     documentation and/or other materials provided with the distribution.\n *   * Neither the name of Redis nor the names of its contributors may be used\n *     to endorse or promote products derived from this software without\n *     specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\"\n * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\n * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE\n * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR\n * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF\n * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS\n * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN\n * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)\n * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE\n * POSSIBILITY OF SUCH DAMAGE.\n */\n\n#include <stdio.h>\n#include <stdlib.h>\n#include <string.h>\n#include \"intset.h\"\n#include \"zmalloc.h\"\n#include \"endianconv.h\"\n\n/* Note that these encodings are ordered, so:\n * INTSET_ENC_INT16 < INTSET_ENC_INT32 < INTSET_ENC_INT64. */\n#define INTSET_ENC_INT16 (sizeof(int16_t))\n#define INTSET_ENC_INT32 (sizeof(int32_t))\n#define INTSET_ENC_INT64 (sizeof(int64_t))\n\n/* Return the required encoding for the provided value. */\nstatic uint8_t _intsetValueEncoding(int64_t v) {\n    if (v < INT32_MIN || v > INT32_MAX)\n        return INTSET_ENC_INT64;\n    else if (v < INT16_MIN || v > INT16_MAX)\n        return INTSET_ENC_INT32;\n    else\n        return INTSET_ENC_INT16;\n}\n\n/* Return the value at pos, given an encoding. */\nstatic int64_t _intsetGetEncoded(intset *is, int pos, uint8_t enc) {\n    int64_t v64;\n    int32_t v32;\n    int16_t v16;\n\n    if (enc == INTSET_ENC_INT64) {\n        memcpy(&v64,((int64_t*)is->contents)+pos,sizeof(v64));\n        memrev64ifbe(&v64);\n        return v64;\n    } else if (enc == INTSET_ENC_INT32) {\n        memcpy(&v32,((int32_t*)is->contents)+pos,sizeof(v32));\n        memrev32ifbe(&v32);\n        return v32;\n    } else {\n        memcpy(&v16,((int16_t*)is->contents)+pos,sizeof(v16));\n        memrev16ifbe(&v16);\n        return v16;\n    }\n}\n\n/* Return the value at pos, using the configured encoding. */\nstatic int64_t _intsetGet(intset *is, int pos) {\n    return _intsetGetEncoded(is,pos,intrev32ifbe(is->encoding));\n}\n\n/* Set the value at pos, using the configured encoding. */\nstatic void _intsetSet(intset *is, int pos, int64_t value) {\n    uint32_t encoding = intrev32ifbe(is->encoding);\n\n    if (encoding == INTSET_ENC_INT64) {\n        ((int64_t*)is->contents)[pos] = value;\n        memrev64ifbe(((int64_t*)is->contents)+pos);\n    } else if (encoding == INTSET_ENC_INT32) {\n        ((int32_t*)is->contents)[pos] = value;\n        memrev32ifbe(((int32_t*)is->contents)+pos);\n    } else {\n        ((int16_t*)is->contents)[pos] = value;\n        memrev16ifbe(((int16_t*)is->contents)+pos);\n    }\n}\n\n/* Create an empty intset. */\nintset *intsetNew(void) {\n    intset *is = zmalloc(sizeof(intset));\n    is->encoding = intrev32ifbe(INTSET_ENC_INT16);\n    is->length = 0;\n    return is;\n}\n\n/* Resize the intset */\nstatic intset *intsetResize(intset *is, uint32_t len) {\n    uint32_t size = len*intrev32ifbe(is->encoding);\n    is = zrealloc(is,sizeof(intset)+size);\n    return is;\n}\n\n/* Search for the position of \"value\". Return 1 when the value was found and\n * sets \"pos\" to the position of the value within the intset. Return 0 when\n * the value is not present in the intset and sets \"pos\" to the position\n * where \"value\" can be inserted. */\nstatic uint8_t intsetSearch(intset *is, int64_t value, uint32_t *pos) {\n    int min = 0, max = intrev32ifbe(is->length)-1, mid = -1;\n    int64_t cur = -1;\n\n    /* The value can never be found when the set is empty */\n    if (intrev32ifbe(is->length) == 0) {\n        if (pos) *pos = 0;\n        return 0;\n    } else {\n        /* Check for the case where we know we cannot find the value,\n         * but do know the insert position. */\n        if (value > _intsetGet(is,intrev32ifbe(is->length)-1)) {\n            if (pos) *pos = intrev32ifbe(is->length);\n            return 0;\n        } else if (value < _intsetGet(is,0)) {\n            if (pos) *pos = 0;\n            return 0;\n        }\n    }\n\n    while(max >= min) {\n        mid = ((unsigned int)min + (unsigned int)max) >> 1;\n        cur = _intsetGet(is,mid);\n        if (value > cur) {\n            min = mid+1;\n        } else if (value < cur) {\n            max = mid-1;\n        } else {\n            break;\n        }\n    }\n\n    if (value == cur) {\n        if (pos) *pos = mid;\n        return 1;\n    } else {\n        if (pos) *pos = min;\n        return 0;\n    }\n}\n\n/* Upgrades the intset to a larger encoding and inserts the given integer. */\nstatic intset *intsetUpgradeAndAdd(intset *is, int64_t value) {\n    uint8_t curenc = intrev32ifbe(is->encoding);\n    uint8_t newenc = _intsetValueEncoding(value);\n    int length = intrev32ifbe(is->length);\n    int prepend = value < 0 ? 1 : 0;\n\n    /* First set new encoding and resize */\n    is->encoding = intrev32ifbe(newenc);\n    is = intsetResize(is,intrev32ifbe(is->length)+1);\n\n    /* Upgrade back-to-front so we don't overwrite values.\n     * Note that the \"prepend\" variable is used to make sure we have an empty\n     * space at either the beginning or the end of the intset. */\n    while(length--)\n        _intsetSet(is,length+prepend,_intsetGetEncoded(is,length,curenc));\n\n    /* Set the value at the beginning or the end. */\n    if (prepend)\n        _intsetSet(is,0,value);\n    else\n        _intsetSet(is,intrev32ifbe(is->length),value);\n    is->length = intrev32ifbe(intrev32ifbe(is->length)+1);\n    return is;\n}\n\nstatic void intsetMoveTail(intset *is, uint32_t from, uint32_t to) {\n    void *src, *dst;\n    uint32_t bytes = intrev32ifbe(is->length)-from;\n    uint32_t encoding = intrev32ifbe(is->encoding);\n\n    if (encoding == INTSET_ENC_INT64) {\n        src = (int64_t*)is->contents+from;\n        dst = (int64_t*)is->contents+to;\n        bytes *= sizeof(int64_t);\n    } else if (encoding == INTSET_ENC_INT32) {\n        src = (int32_t*)is->contents+from;\n        dst = (int32_t*)is->contents+to;\n        bytes *= sizeof(int32_t);\n    } else {\n        src = (int16_t*)is->contents+from;\n        dst = (int16_t*)is->contents+to;\n        bytes *= sizeof(int16_t);\n    }\n    memmove(dst,src,bytes);\n}\n\n/* Insert an integer in the intset */\nintset *intsetAdd(intset *is, int64_t value, uint8_t *success) {\n    uint8_t valenc = _intsetValueEncoding(value);\n    uint32_t pos;\n    if (success) *success = 1;\n\n    /* Upgrade encoding if necessary. If we need to upgrade, we know that\n     * this value should be either appended (if > 0) or prepended (if < 0),\n     * because it lies outside the range of existing values. */\n    if (valenc > intrev32ifbe(is->encoding)) {\n        /* This always succeeds, so we don't need to curry *success. */\n        return intsetUpgradeAndAdd(is,value);\n    } else {\n        /* Abort if the value is already present in the set.\n         * This call will populate \"pos\" with the right position to insert\n         * the value when it cannot be found. */\n        if (intsetSearch(is,value,&pos)) {\n            if (success) *success = 0;\n            return is;\n        }\n\n        is = intsetResize(is,intrev32ifbe(is->length)+1);\n        if (pos < intrev32ifbe(is->length)) intsetMoveTail(is,pos,pos+1);\n    }\n\n    _intsetSet(is,pos,value);\n    is->length = intrev32ifbe(intrev32ifbe(is->length)+1);\n    return is;\n}\n\n/* Delete integer from intset */\nintset *intsetRemove(intset *is, int64_t value, int *success) {\n    uint8_t valenc = _intsetValueEncoding(value);\n    uint32_t pos;\n    if (success) *success = 0;\n\n    if (valenc <= intrev32ifbe(is->encoding) && intsetSearch(is,value,&pos)) {\n        uint32_t len = intrev32ifbe(is->length);\n\n        /* We know we can delete */\n        if (success) *success = 1;\n\n        /* Overwrite value with tail and update length */\n        if (pos < (len-1)) intsetMoveTail(is,pos+1,pos);\n        is = intsetResize(is,len-1);\n        is->length = intrev32ifbe(len-1);\n    }\n    return is;\n}\n\n/* Determine whether a value belongs to this set */\nuint8_t intsetFind(intset *is, int64_t value) {\n    uint8_t valenc = _intsetValueEncoding(value);\n    return valenc <= intrev32ifbe(is->encoding) && intsetSearch(is,value,NULL);\n}\n\n/* Return random member */\nint64_t intsetRandom(intset *is) {\n    return _intsetGet(is,rand()%intrev32ifbe(is->length));\n}\n\n/* Sets the value to the value at the given position. When this position is\n * out of range the function returns 0, when in range it returns 1. */\nuint8_t intsetGet(intset *is, uint32_t pos, int64_t *value) {\n    if (pos < intrev32ifbe(is->length)) {\n        *value = _intsetGet(is,pos);\n        return 1;\n    }\n    return 0;\n}\n\n/* Return intset length */\nuint32_t intsetLen(intset *is) {\n    return intrev32ifbe(is->length);\n}\n\n/* Return intset blob size in bytes. */\nsize_t intsetBlobLen(intset *is) {\n    return sizeof(intset)+intrev32ifbe(is->length)*intrev32ifbe(is->encoding);\n}\n\n#ifdef INTSET_TEST_MAIN\n#include <sys/time.h>\n\nvoid intsetRepr(intset *is) {\n    int i;\n    for (i = 0; i < intrev32ifbe(is->length); i++) {\n        printf(\"%lld\\n\", (uint64_t)_intsetGet(is,i));\n    }\n    printf(\"\\n\");\n}\n\nvoid error(char *err) {\n    printf(\"%s\\n\", err);\n    exit(1);\n}\n\nvoid ok(void) {\n    printf(\"OK\\n\");\n}\n\nlong long usec(void) {\n    struct timeval tv;\n    gettimeofday(&tv,NULL);\n    return (((long long)tv.tv_sec)*1000000)+tv.tv_usec;\n}\n\n#define assert(_e) ((_e)?(void)0:(_assert(#_e,__FILE__,__LINE__),exit(1)))\nvoid _assert(char *estr, char *file, int line) {\n    printf(\"\\n\\n=== ASSERTION FAILED ===\\n\");\n    printf(\"==> %s:%d '%s' is not true\\n\",file,line,estr);\n}\n\nintset *createSet(int bits, int size) {\n    uint64_t mask = (1<<bits)-1;\n    uint64_t i, value;\n    intset *is = intsetNew();\n\n    for (i = 0; i < size; i++) {\n        if (bits > 32) {\n            value = (rand()*rand()) & mask;\n        } else {\n            value = rand() & mask;\n        }\n        is = intsetAdd(is,value,NULL);\n    }\n    return is;\n}\n\nvoid checkConsistency(intset *is) {\n    int i;\n\n    for (i = 0; i < (intrev32ifbe(is->length)-1); i++) {\n        uint32_t encoding = intrev32ifbe(is->encoding);\n\n        if (encoding == INTSET_ENC_INT16) {\n            int16_t *i16 = (int16_t*)is->contents;\n            assert(i16[i] < i16[i+1]);\n        } else if (encoding == INTSET_ENC_INT32) {\n            int32_t *i32 = (int32_t*)is->contents;\n            assert(i32[i] < i32[i+1]);\n        } else {\n            int64_t *i64 = (int64_t*)is->contents;\n            assert(i64[i] < i64[i+1]);\n        }\n    }\n}\n\nint main(int argc, char **argv) {\n    uint8_t success;\n    int i;\n    intset *is;\n    sranddev();\n\n    printf(\"Value encodings: \"); {\n        assert(_intsetValueEncoding(-32768) == INTSET_ENC_INT16);\n        assert(_intsetValueEncoding(+32767) == INTSET_ENC_INT16);\n        assert(_intsetValueEncoding(-32769) == INTSET_ENC_INT32);\n        assert(_intsetValueEncoding(+32768) == INTSET_ENC_INT32);\n        assert(_intsetValueEncoding(-2147483648) == INTSET_ENC_INT32);\n        assert(_intsetValueEncoding(+2147483647) == INTSET_ENC_INT32);\n        assert(_intsetValueEncoding(-2147483649) == INTSET_ENC_INT64);\n        assert(_intsetValueEncoding(+2147483648) == INTSET_ENC_INT64);\n        assert(_intsetValueEncoding(-9223372036854775808ull) == INTSET_ENC_INT64);\n        assert(_intsetValueEncoding(+9223372036854775807ull) == INTSET_ENC_INT64);\n        ok();\n    }\n\n    printf(\"Basic adding: \"); {\n        is = intsetNew();\n        is = intsetAdd(is,5,&success); assert(success);\n        is = intsetAdd(is,6,&success); assert(success);\n        is = intsetAdd(is,4,&success); assert(success);\n        is = intsetAdd(is,4,&success); assert(!success);\n        ok();\n    }\n\n    printf(\"Large number of random adds: \"); {\n        int inserts = 0;\n        is = intsetNew();\n        for (i = 0; i < 1024; i++) {\n            is = intsetAdd(is,rand()%0x800,&success);\n            if (success) inserts++;\n        }\n        assert(intrev32ifbe(is->length) == inserts);\n        checkConsistency(is);\n        ok();\n    }\n\n    printf(\"Upgrade from int16 to int32: \"); {\n        is = intsetNew();\n        is = intsetAdd(is,32,NULL);\n        assert(intrev32ifbe(is->encoding) == INTSET_ENC_INT16);\n        is = intsetAdd(is,65535,NULL);\n        assert(intrev32ifbe(is->encoding) == INTSET_ENC_INT32);\n        assert(intsetFind(is,32));\n        assert(intsetFind(is,65535));\n        checkConsistency(is);\n\n        is = intsetNew();\n        is = intsetAdd(is,32,NULL);\n        assert(intrev32ifbe(is->encoding) == INTSET_ENC_INT16);\n        is = intsetAdd(is,-65535,NULL);\n        assert(intrev32ifbe(is->encoding) == INTSET_ENC_INT32);\n        assert(intsetFind(is,32));\n        assert(intsetFind(is,-65535));\n        checkConsistency(is);\n        ok();\n    }\n\n    printf(\"Upgrade from int16 to int64: \"); {\n        is = intsetNew();\n        is = intsetAdd(is,32,NULL);\n        assert(intrev32ifbe(is->encoding) == INTSET_ENC_INT16);\n        is = intsetAdd(is,4294967295,NULL);\n        assert(intrev32ifbe(is->encoding) == INTSET_ENC_INT64);\n        assert(intsetFind(is,32));\n        assert(intsetFind(is,4294967295));\n        checkConsistency(is);\n\n        is = intsetNew();\n        is = intsetAdd(is,32,NULL);\n        assert(intrev32ifbe(is->encoding) == INTSET_ENC_INT16);\n        is = intsetAdd(is,-4294967295,NULL);\n        assert(intrev32ifbe(is->encoding) == INTSET_ENC_INT64);\n        assert(intsetFind(is,32));\n        assert(intsetFind(is,-4294967295));\n        checkConsistency(is);\n        ok();\n    }\n\n    printf(\"Upgrade from int32 to int64: \"); {\n        is = intsetNew();\n        is = intsetAdd(is,65535,NULL);\n        assert(intrev32ifbe(is->encoding) == INTSET_ENC_INT32);\n        is = intsetAdd(is,4294967295,NULL);\n        assert(intrev32ifbe(is->encoding) == INTSET_ENC_INT64);\n        assert(intsetFind(is,65535));\n        assert(intsetFind(is,4294967295));\n        checkConsistency(is);\n\n        is = intsetNew();\n        is = intsetAdd(is,65535,NULL);\n        assert(intrev32ifbe(is->encoding) == INTSET_ENC_INT32);\n        is = intsetAdd(is,-4294967295,NULL);\n        assert(intrev32ifbe(is->encoding) == INTSET_ENC_INT64);\n        assert(intsetFind(is,65535));\n        assert(intsetFind(is,-4294967295));\n        checkConsistency(is);\n        ok();\n    }\n\n    printf(\"Stress lookups: \"); {\n        long num = 100000, size = 10000;\n        int i, bits = 20;\n        long long start;\n        is = createSet(bits,size);\n        checkConsistency(is);\n\n        start = usec();\n        for (i = 0; i < num; i++) intsetSearch(is,rand() % ((1<<bits)-1),NULL);\n        printf(\"%ld lookups, %ld element set, %lldusec\\n\",num,size,usec()-start);\n    }\n\n    printf(\"Stress add+delete: \"); {\n        int i, v1, v2;\n        is = intsetNew();\n        for (i = 0; i < 0xffff; i++) {\n            v1 = rand() % 0xfff;\n            is = intsetAdd(is,v1,NULL);\n            assert(intsetFind(is,v1));\n\n            v2 = rand() % 0xfff;\n            is = intsetRemove(is,v2,NULL);\n            assert(!intsetFind(is,v2));\n        }\n        checkConsistency(is);\n        ok();\n    }\n}\n#endif\n"
  },
  {
    "path": "extern/deprecated/redis-2.8.21/src/intset.h",
    "content": "/*\n * Copyright (c) 2009-2012, Pieter Noordhuis <pcnoordhuis at gmail dot com>\n * Copyright (c) 2009-2012, Salvatore Sanfilippo <antirez at gmail dot com>\n * All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions are met:\n *\n *   * Redistributions of source code must retain the above copyright notice,\n *     this list of conditions and the following disclaimer.\n *   * Redistributions in binary form must reproduce the above copyright\n *     notice, this list of conditions and the following disclaimer in the\n *     documentation and/or other materials provided with the distribution.\n *   * Neither the name of Redis nor the names of its contributors may be used\n *     to endorse or promote products derived from this software without\n *     specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\"\n * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\n * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE\n * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR\n * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF\n * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS\n * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN\n * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)\n * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE\n * POSSIBILITY OF SUCH DAMAGE.\n */\n\n#ifndef __INTSET_H\n#define __INTSET_H\n#include <stdint.h>\n\ntypedef struct intset {\n    uint32_t encoding;\n    uint32_t length;\n    int8_t contents[];\n} intset;\n\nintset *intsetNew(void);\nintset *intsetAdd(intset *is, int64_t value, uint8_t *success);\nintset *intsetRemove(intset *is, int64_t value, int *success);\nuint8_t intsetFind(intset *is, int64_t value);\nint64_t intsetRandom(intset *is);\nuint8_t intsetGet(intset *is, uint32_t pos, int64_t *value);\nuint32_t intsetLen(intset *is);\nsize_t intsetBlobLen(intset *is);\n\n#endif // __INTSET_H\n"
  },
  {
    "path": "extern/deprecated/redis-2.8.21/src/latency.c",
    "content": "/* The latency monitor allows to easily observe the sources of latency\n * in a Redis instance using the LATENCY command. Different latency\n * sources are monitored, like disk I/O, execution of commands, fork\n * system call, and so forth.\n *\n * ----------------------------------------------------------------------------\n *\n * Copyright (c) 2014, Salvatore Sanfilippo <antirez at gmail dot com>\n * All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions are met:\n *\n *   * Redistributions of source code must retain the above copyright notice,\n *     this list of conditions and the following disclaimer.\n *   * Redistributions in binary form must reproduce the above copyright\n *     notice, this list of conditions and the following disclaimer in the\n *     documentation and/or other materials provided with the distribution.\n *   * Neither the name of Redis nor the names of its contributors may be used\n *     to endorse or promote products derived from this software without\n *     specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\"\n * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\n * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE\n * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR\n * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF\n * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS\n * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN\n * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)\n * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE\n * POSSIBILITY OF SUCH DAMAGE.\n */\n\n#include \"redis.h\"\n\n/* Dictionary type for latency events. */\nint dictStringKeyCompare(void *privdata, const void *key1, const void *key2) {\n    REDIS_NOTUSED(privdata);\n    return strcmp(key1,key2) == 0;\n}\n\nunsigned int dictStringHash(const void *key) {\n    return dictGenHashFunction(key, strlen(key));\n}\n\nvoid dictVanillaFree(void *privdata, void *val);\n\ndictType latencyTimeSeriesDictType = {\n    dictStringHash,             /* hash function */\n    NULL,                       /* key dup */\n    NULL,                       /* val dup */\n    dictStringKeyCompare,       /* key compare */\n    dictVanillaFree,            /* key destructor */\n    dictVanillaFree             /* val destructor */\n};\n\n/* ------------------------- Utility functions ------------------------------ */\n\n#ifdef __linux__\n/* Returns 1 if Transparent Huge Pages support is enabled in the kernel.\n * Otherwise (or if we are unable to check) 0 is returned. */\nint THPIsEnabled(void) {\n    char buf[1024];\n\n    FILE *fp = fopen(\"/sys/kernel/mm/transparent_hugepage/enabled\",\"r\");\n    if (!fp) return 0;\n    if (fgets(buf,sizeof(buf),fp) == NULL) {\n        fclose(fp);\n        return 0;\n    }\n    fclose(fp);\n    return (strstr(buf,\"[never]\") == NULL) ? 1 : 0;\n}\n#endif\n\n/* Report the amount of AnonHugePages in smap, in bytes. If the return\n * value of the function is non-zero, the process is being targeted by\n * THP support, and is likely to have memory usage / latency issues. */\nint THPGetAnonHugePagesSize(void) {\n    return zmalloc_get_smap_bytes_by_field(\"AnonHugePages:\");\n}\n\n/* ---------------------------- Latency API --------------------------------- */\n\n/* Latency monitor initialization. We just need to create the dictionary\n * of time series, each time serie is craeted on demand in order to avoid\n * having a fixed list to maintain. */\nvoid latencyMonitorInit(void) {\n    server.latency_events = dictCreate(&latencyTimeSeriesDictType,NULL);\n}\n\n/* Add the specified sample to the specified time series \"event\".\n * This function is usually called via latencyAddSampleIfNeeded(), that\n * is a macro that only adds the sample if the latency is higher than\n * server.latency_monitor_threshold. */\nvoid latencyAddSample(char *event, mstime_t latency) {\n    struct latencyTimeSeries *ts = dictFetchValue(server.latency_events,event);\n    time_t now = time(NULL);\n    int prev;\n\n    /* Create the time series if it does not exist. */\n    if (ts == NULL) {\n        ts = zmalloc(sizeof(*ts));\n        ts->idx = 0;\n        ts->max = 0;\n        memset(ts->samples,0,sizeof(ts->samples));\n        dictAdd(server.latency_events,zstrdup(event),ts);\n    }\n\n    /* If the previous sample is in the same second, we update our old sample\n     * if this latency is > of the old one, or just return. */\n    prev = (ts->idx + LATENCY_TS_LEN - 1) % LATENCY_TS_LEN;\n    if (ts->samples[prev].time == now) {\n        if (latency > ts->samples[prev].latency)\n            ts->samples[prev].latency = latency;\n        return;\n    }\n\n    ts->samples[ts->idx].time = time(NULL);\n    ts->samples[ts->idx].latency = latency;\n    if (latency > ts->max) ts->max = latency;\n\n    ts->idx++;\n    if (ts->idx == LATENCY_TS_LEN) ts->idx = 0;\n}\n\n/* Reset data for the specified event, or all the events data if 'event' is\n * NULL.\n *\n * Note: this is O(N) even when event_to_reset is not NULL because makes\n * the code simpler and we have a small fixed max number of events. */\nint latencyResetEvent(char *event_to_reset) {\n    dictIterator *di;\n    dictEntry *de;\n    int resets = 0;\n\n    di = dictGetSafeIterator(server.latency_events);\n    while((de = dictNext(di)) != NULL) {\n        char *event = dictGetKey(de);\n\n        if (event_to_reset == NULL || strcasecmp(event,event_to_reset) == 0) {\n            dictDelete(server.latency_events, event);\n            resets++;\n        }\n    }\n    dictReleaseIterator(di);\n    return resets;\n}\n\n/* ------------------------ Latency reporting (doctor) ---------------------- */\n\n/* Analyze the samples avaialble for a given event and return a structure\n * populate with different metrics, average, MAD, min, max, and so forth.\n * Check latency.h definition of struct latenctStat for more info.\n * If the specified event has no elements the structure is populate with\n * zero values. */\nvoid analyzeLatencyForEvent(char *event, struct latencyStats *ls) {\n    struct latencyTimeSeries *ts = dictFetchValue(server.latency_events,event);\n    int j;\n    uint64_t sum;\n\n    ls->all_time_high = ts ? ts->max : 0;\n    ls->avg = 0;\n    ls->min = 0;\n    ls->max = 0;\n    ls->mad = 0;\n    ls->samples = 0;\n    ls->period = 0;\n    if (!ts) return;\n\n    /* First pass, populate everything but the MAD. */\n    sum = 0;\n    for (j = 0; j < LATENCY_TS_LEN; j++) {\n        if (ts->samples[j].time == 0) continue;\n        ls->samples++;\n        if (ls->samples == 1) {\n            ls->min = ls->max = ts->samples[j].latency;\n        } else {\n            if (ls->min > ts->samples[j].latency)\n                ls->min = ts->samples[j].latency;\n            if (ls->max < ts->samples[j].latency)\n                ls->max = ts->samples[j].latency;\n        }\n        sum += ts->samples[j].latency;\n\n        /* Track the oldest event time in ls->period. */\n        if (ls->period == 0 || ts->samples[j].time < ls->period)\n            ls->period = ts->samples[j].time;\n    }\n\n    /* So far avg is actually the sum of the latencies, and period is\n     * the oldest event time. We need to make the first an average and\n     * the second a range of seconds. */\n    if (ls->samples) {\n        ls->avg = sum / ls->samples;\n        ls->period = time(NULL) - ls->period;\n        if (ls->period == 0) ls->period = 1;\n    }\n\n    /* Second pass, compute MAD. */\n    sum = 0;\n    for (j = 0; j < LATENCY_TS_LEN; j++) {\n        int64_t delta;\n\n        if (ts->samples[j].time == 0) continue;\n        delta = (int64_t)ls->avg - ts->samples[j].latency;\n        if (delta < 0) delta = -delta;\n        sum += delta;\n    }\n    if (ls->samples) ls->mad = sum / ls->samples;\n}\n\n/* Create a human readable report of latency events for this Redis instance. */\nsds createLatencyReport(void) {\n    sds report = sdsempty();\n    int advise_better_vm = 0;       /* Better virtual machines. */\n    int advise_slowlog_enabled = 0; /* Enable slowlog. */\n    int advise_slowlog_tuning = 0;  /* Reconfigure slowlog. */\n    int advise_slowlog_inspect = 0; /* Check your slowlog. */\n    int advise_disk_contention = 0; /* Try to lower disk contention. */\n    int advise_scheduler = 0;       /* Intrinsic latency. */\n    int advise_data_writeback = 0;  /* data=writeback. */\n    int advise_no_appendfsync = 0;  /* don't fsync during rewrites. */\n    int advise_local_disk = 0;      /* Avoid remote disks. */\n    int advise_ssd = 0;             /* Use an SSD drive. */\n    int advise_write_load_info = 0; /* Print info about AOF and write load. */\n    int advise_hz = 0;              /* Use higher HZ. */\n    int advise_large_objects = 0;   /* Deletion of large objects. */\n    int advise_relax_fsync_policy = 0; /* appendfsync always is slow. */\n    int advise_disable_thp = 0;     /* AnonHugePages detected. */\n    int advices = 0;\n\n    /* Return ASAP if the latency engine is disabled and it looks like it\n     * was never enabled so far. */\n    if (dictSize(server.latency_events) == 0 &&\n        server.latency_monitor_threshold == 0)\n    {\n        report = sdscat(report,\"I'm sorry, Dave, I can't do that. Latency monitoring is disabled in this Redis instance. You may use \\\"CONFIG SET latency-monitor-threshold <milliseconds>.\\\" in order to enable it. If we weren't in a deep space mission I'd suggest to take a look at http://redis.io/topics/latency-monitor.\\n\");\n        return report;\n    }\n\n    /* Show all the events stats and add for each event some event-related\n     * comment depending on the values. */\n    dictIterator *di;\n    dictEntry *de;\n    int eventnum = 0;\n\n    di = dictGetSafeIterator(server.latency_events);\n    while((de = dictNext(di)) != NULL) {\n        char *event = dictGetKey(de);\n        struct latencyTimeSeries *ts = dictGetVal(de);\n        struct latencyStats ls;\n\n        if (ts == NULL) continue;\n        eventnum++;\n        if (eventnum == 1) {\n            report = sdscat(report,\"Dave, I have observed latency spikes in this Redis instance. You don't mind talking about it, do you Dave?\\n\\n\");\n        }\n        analyzeLatencyForEvent(event,&ls);\n\n        report = sdscatprintf(report,\n            \"%d. %s: %d latency spikes (average %lums, mean deviation %lums, period %.2f sec). Worst all time event %lums.\",\n            eventnum, event,\n            ls.samples,\n            (unsigned long) ls.avg,\n            (unsigned long) ls.mad,\n            (double) ls.period/ls.samples,\n            (unsigned long) ts->max);\n\n        /* Fork */\n        if (!strcasecmp(event,\"fork\")) {\n            char *fork_quality;\n            if (server.stat_fork_rate < 10) {\n                fork_quality = \"terrible\";\n                advise_better_vm = 1;\n                advices++;\n            } else if (server.stat_fork_rate < 25) {\n                fork_quality = \"poor\";\n                advise_better_vm = 1;\n                advices++;\n            } else if (server.stat_fork_rate < 100) {\n                fork_quality = \"good\";\n            } else {\n                fork_quality = \"excellent\";\n            }\n            report = sdscatprintf(report,\n                \" Fork rate is %.2f GB/sec (%s).\", server.stat_fork_rate,\n                fork_quality);\n        }\n\n        /* Potentially commands. */\n        if (!strcasecmp(event,\"command\")) {\n            if (server.slowlog_log_slower_than == 0) {\n                advise_slowlog_enabled = 1;\n                advices++;\n            } else if (server.slowlog_log_slower_than/1000 >\n                       server.latency_monitor_threshold)\n            {\n                advise_slowlog_tuning = 1;\n                advices++;\n            }\n            advise_slowlog_inspect = 1;\n            advise_large_objects = 1;\n            advices += 2;\n        }\n\n        /* fast-command. */\n        if (!strcasecmp(event,\"fast-command\")) {\n            advise_scheduler = 1;\n            advices++;\n        }\n\n        /* AOF and I/O. */\n        if (!strcasecmp(event,\"aof-write-pending-fsync\")) {\n            advise_local_disk = 1;\n            advise_disk_contention = 1;\n            advise_ssd = 1;\n            advise_data_writeback = 1;\n            advices += 4;\n        }\n\n        if (!strcasecmp(event,\"aof-write-active-child\")) {\n            advise_no_appendfsync = 1;\n            advise_data_writeback = 1;\n            advise_ssd = 1;\n            advices += 3;\n        }\n\n        if (!strcasecmp(event,\"aof-write-alone\")) {\n            advise_local_disk = 1;\n            advise_data_writeback = 1;\n            advise_ssd = 1;\n            advices += 3;\n        }\n\n        if (!strcasecmp(event,\"aof-fsync-always\")) {\n            advise_relax_fsync_policy = 1;\n            advices++;\n        }\n\n        if (!strcasecmp(event,\"aof-fstat\") ||\n            !strcasecmp(event,\"rdb-unlik-temp-file\")) {\n            advise_disk_contention = 1;\n            advise_local_disk = 1;\n            advices += 2;\n        }\n\n        if (!strcasecmp(event,\"aof-rewrite-diff-write\") ||\n            !strcasecmp(event,\"aof-rename\")) {\n            advise_write_load_info = 1;\n            advise_data_writeback = 1;\n            advise_ssd = 1;\n            advise_local_disk = 1;\n            advices += 4;\n        }\n\n        /* Expire cycle. */\n        if (!strcasecmp(event,\"expire-cycle\")) {\n            advise_hz = 1;\n            advise_large_objects = 1;\n            advices += 2;\n        }\n\n        /* Eviction cycle. */\n        if (!strcasecmp(event,\"eviction-cycle\")) {\n            advise_large_objects = 1;\n            advices++;\n        }\n\n        report = sdscatlen(report,\"\\n\",1);\n    }\n    dictReleaseIterator(di);\n\n    /* Add non event based advices. */\n    if (THPGetAnonHugePagesSize() > 0) {\n        advise_disable_thp = 1;\n        advices++;\n    }\n\n    if (eventnum == 0 && advices == 0) {\n        report = sdscat(report,\"Dave, no latency spike was observed during the lifetime of this Redis instance, not in the slightest bit. I honestly think you ought to sit down calmly, take a stress pill, and think things over.\\n\");\n    } else if (eventnum > 0 && advices == 0) {\n        report = sdscat(report,\"\\nWhile there are latency events logged, I'm not able to suggest any easy fix. Please use the Redis community to get some help, providing this report in your help request.\\n\");\n    } else {\n        /* Add all the suggestions accumulated so far. */\n\n        /* Better VM. */\n        report = sdscat(report,\"\\nI have a few advices for you:\\n\\n\");\n        if (advise_better_vm) {\n            report = sdscat(report,\"- If you are using a virtual machine, consider upgrading it with a faster one using an hypervisior that provides less latency during fork() calls. Xen is known to have poor fork() performance. Even in the context of the same VM provider, certain kinds of instances can execute fork faster than others.\\n\");\n        }\n\n        /* Slow log. */\n        if (advise_slowlog_enabled) {\n            report = sdscatprintf(report,\"- There are latency issues with potentially slow commands you are using. Try to enable the Slow Log Redis feature using the command 'CONFIG SET slowlog-log-slower-than %llu'. If the Slow log is disabled Redis is not able to log slow commands execution for you.\\n\", (unsigned long long)server.latency_monitor_threshold*1000);\n        }\n\n        if (advise_slowlog_tuning) {\n            report = sdscatprintf(report,\"- Your current Slow Log configuration only logs events that are slower than your configured latency monitor threshold. Please use 'CONFIG SET slowlog-log-slower-than %llu'.\\n\", (unsigned long long)server.latency_monitor_threshold*1000);\n        }\n\n        if (advise_slowlog_inspect) {\n            report = sdscat(report,\"- Check your Slow Log to understand what are the commands you are running which are too slow to execute. Please check http://redis.io/commands/slowlog for more information.\\n\");\n        }\n\n        /* Intrinsic latency. */\n        if (advise_scheduler) {\n            report = sdscat(report,\"- The system is slow to execute Redis code paths not containing system calls. This usually means the system does not provide Redis CPU time to run for long periods. You should try to:\\n\"\n            \"  1) Lower the system load.\\n\"\n            \"  2) Use a computer / VM just for Redis if you are running other softawre in the same system.\\n\"\n            \"  3) Check if you have a \\\"noisy neighbour\\\" problem.\\n\"\n            \"  4) Check with 'redis-cli --intrinsic-latency 100' what is the intrinsic latency in your system.\\n\"\n            \"  5) Check if the problem is allocator-related by recompiling Redis with MALLOC=libc, if you are using Jemalloc. However this may create fragmentation problems.\\n\");\n        }\n\n        /* AOF / Disk latency. */\n        if (advise_local_disk) {\n            report = sdscat(report,\"- It is strongly advised to use local disks for persistence, especially if you are using AOF. Remote disks provided by platform-as-a-service providers are known to be slow.\\n\");\n        }\n\n        if (advise_ssd) {\n            report = sdscat(report,\"- SSD disks are able to reduce fsync latency, and total time needed for snapshotting and AOF log rewriting (resulting in smaller memory usage and smaller final AOF rewrite buffer flushes). With extremely high write load SSD disks can be a good option. However Redis should perform reasonably with high load using normal disks. Use this advice as a last resort.\\n\");\n        }\n\n        if (advise_data_writeback) {\n            report = sdscat(report,\"- Mounting ext3/4 filesystems with data=writeback can provide a performance boost compared to data=ordered, however this mode of operation provides less guarantees, and sometimes it can happen that after a hard crash the AOF file will have an half-written command at the end and will require to be repaired before Redis restarts.\\n\");\n        }\n\n        if (advise_disk_contention) {\n            report = sdscat(report,\"- Try to lower the disk contention. This is often caused by other disk intensive processes running in the same computer (including other Redis instances).\\n\");\n        }\n\n        if (advise_no_appendfsync) {\n            report = sdscat(report,\"- Assuming from the point of view of data safety this is viable in your environment, you could try to enable the 'no-appendfsync-on-rewrite' option, so that fsync will not be performed while there is a child rewriting the AOF file or producing an RDB file (the moment where there is high disk contention).\\n\");\n        }\n\n        if (advise_relax_fsync_policy && server.aof_fsync == AOF_FSYNC_ALWAYS) {\n            report = sdscat(report,\"- Your fsync policy is set to 'always'. It is very hard to get good performances with such a setup, if possible try to relax the fsync policy to 'onesec'.\\n\");\n        }\n\n        if (advise_write_load_info) {\n            report = sdscat(report,\"- Latency during the AOF atomic rename operation or when the final difference is flushed to the AOF file at the end of the rewrite, sometimes is caused by very high write load, causing the AOF buffer to get very large. If possible try to send less commands to accomplish the same work, or use Lua scripts to group multiple operations into a single EVALSHA call.\\n\");\n        }\n\n        if (advise_hz && server.hz < 100) {\n            report = sdscat(report,\"- In order to make the Redis keys expiring process more incremental, try to set the 'hz' configuration parameter to 100 using 'CONFIG SET hz 100'.\\n\");\n        }\n\n        if (advise_large_objects) {\n            report = sdscat(report,\"- Deleting, expiring or evicting (because of maxmemory policy) large objects is a blocking operation. If you have very large objects that are often deleted, expired, or evicted, try to fragment those objects into multiple smaller objects.\\n\");\n        }\n\n        if (advise_disable_thp) {\n            report = sdscat(report,\"- I detected a non zero amount of anonymous huge pages used by your process. This creates very serious latency events in different conditions, especially when Redis is persisting on disk. To disable THP support use the command 'echo never > /sys/kernel/mm/transparent_hugepage/enabled', make sure to also add it into /etc/rc.local so that the command will be executed again after a reboot. Note that even if you have already disabled THP, you still need to restart the Redis process to get rid of the huge pages already created.\\n\");\n        }\n    }\n\n    return report;\n}\n\n/* ---------------------- Latency command implementation -------------------- */\n\n/* latencyCommand() helper to produce a time-delay reply for all the samples\n * in memory for the specified time series. */\nvoid latencyCommandReplyWithSamples(redisClient *c, struct latencyTimeSeries *ts) {\n    void *replylen = addDeferredMultiBulkLength(c);\n    int samples = 0, j;\n\n    for (j = 0; j < LATENCY_TS_LEN; j++) {\n        int i = (ts->idx + j) % LATENCY_TS_LEN;\n\n        if (ts->samples[i].time == 0) continue;\n        addReplyMultiBulkLen(c,2);\n        addReplyLongLong(c,ts->samples[i].time);\n        addReplyLongLong(c,ts->samples[i].latency);\n        samples++;\n    }\n    setDeferredMultiBulkLength(c,replylen,samples);\n}\n\n/* latencyCommand() helper to produce the reply for the LATEST subcommand,\n * listing the last latency sample for every event type registered so far. */\nvoid latencyCommandReplyWithLatestEvents(redisClient *c) {\n    dictIterator *di;\n    dictEntry *de;\n\n    addReplyMultiBulkLen(c,dictSize(server.latency_events));\n    di = dictGetIterator(server.latency_events);\n    while((de = dictNext(di)) != NULL) {\n        char *event = dictGetKey(de);\n        struct latencyTimeSeries *ts = dictGetVal(de);\n        int last = (ts->idx + LATENCY_TS_LEN - 1) % LATENCY_TS_LEN;\n\n        addReplyMultiBulkLen(c,4);\n        addReplyBulkCString(c,event);\n        addReplyLongLong(c,ts->samples[last].time);\n        addReplyLongLong(c,ts->samples[last].latency);\n        addReplyLongLong(c,ts->max);\n    }\n    dictReleaseIterator(di);\n}\n\n#define LATENCY_GRAPH_COLS 80\nsds latencyCommandGenSparkeline(char *event, struct latencyTimeSeries *ts) {\n    int j;\n    struct sequence *seq = createSparklineSequence();\n    sds graph = sdsempty();\n    uint32_t min = 0, max = 0;\n\n    for (j = 0; j < LATENCY_TS_LEN; j++) {\n        int i = (ts->idx + j) % LATENCY_TS_LEN;\n        int elapsed;\n        char buf[64];\n\n        if (ts->samples[i].time == 0) continue;\n        /* Update min and max. */\n        if (seq->length == 0) {\n            min = max = ts->samples[i].latency;\n        } else {\n            if (ts->samples[i].latency > max) max = ts->samples[i].latency;\n            if (ts->samples[i].latency < min) min = ts->samples[i].latency;\n        }\n        /* Use as label the number of seconds / minutes / hours / days\n         * ago the event happened. */\n        elapsed = time(NULL) - ts->samples[i].time;\n        if (elapsed < 60)\n            snprintf(buf,sizeof(buf),\"%ds\",elapsed);\n        else if (elapsed < 3600)\n            snprintf(buf,sizeof(buf),\"%dm\",elapsed/60);\n        else if (elapsed < 3600*24)\n            snprintf(buf,sizeof(buf),\"%dh\",elapsed/3600);\n        else\n            snprintf(buf,sizeof(buf),\"%dd\",elapsed/(3600*24));\n        sparklineSequenceAddSample(seq,ts->samples[i].latency,buf);\n    }\n\n    graph = sdscatprintf(graph,\n        \"%s - high %lu ms, low %lu ms (all time high %lu ms)\\n\", event,\n        (unsigned long) max, (unsigned long) min, (unsigned long) ts->max);\n    for (j = 0; j < LATENCY_GRAPH_COLS; j++)\n        graph = sdscatlen(graph,\"-\",1);\n    graph = sdscatlen(graph,\"\\n\",1);\n    graph = sparklineRender(graph,seq,LATENCY_GRAPH_COLS,4,SPARKLINE_FILL);\n    freeSparklineSequence(seq);\n    return graph;\n}\n\n/* LATENCY command implementations.\n *\n * LATENCY SAMPLES: return time-latency samples for the specified event.\n * LATENCY LATEST: return the latest latency for all the events classes.\n * LATENCY DOCTOR: returns an human readable analysis of instance latency.\n * LATENCY GRAPH: provide an ASCII graph of the latency of the specified event.\n */\nvoid latencyCommand(redisClient *c) {\n    struct latencyTimeSeries *ts;\n\n    if (!strcasecmp(c->argv[1]->ptr,\"history\") && c->argc == 3) {\n        /* LATENCY HISTORY <event> */\n        ts = dictFetchValue(server.latency_events,c->argv[2]->ptr);\n        if (ts == NULL) {\n            addReplyMultiBulkLen(c,0);\n        } else {\n            latencyCommandReplyWithSamples(c,ts);\n        }\n    } else if (!strcasecmp(c->argv[1]->ptr,\"graph\") && c->argc == 3) {\n        /* LATENCY GRAPH <event> */\n        sds graph;\n        dictEntry *de;\n        char *event;\n\n        de = dictFind(server.latency_events,c->argv[2]->ptr);\n        if (de == NULL) goto nodataerr;\n        ts = dictGetVal(de);\n        event = dictGetKey(de);\n\n        graph = latencyCommandGenSparkeline(event,ts);\n        addReplyBulkCString(c,graph);\n        sdsfree(graph);\n    } else if (!strcasecmp(c->argv[1]->ptr,\"latest\") && c->argc == 2) {\n        /* LATENCY LATEST */\n        latencyCommandReplyWithLatestEvents(c);\n    } else if (!strcasecmp(c->argv[1]->ptr,\"doctor\") && c->argc == 2) {\n        /* LATENCY DOCTOR */\n        sds report = createLatencyReport();\n\n        addReplyBulkCBuffer(c,report,sdslen(report));\n        sdsfree(report);\n    } else if (!strcasecmp(c->argv[1]->ptr,\"reset\") && c->argc >= 2) {\n        /* LATENCY RESET */\n        if (c->argc == 2) {\n            addReplyLongLong(c,latencyResetEvent(NULL));\n        } else {\n            int j, resets = 0;\n\n            for (j = 2; j < c->argc; j++)\n                resets += latencyResetEvent(c->argv[j]->ptr);\n            addReplyLongLong(c,resets);\n        }\n    } else {\n        addReply(c,shared.syntaxerr);\n    }\n    return;\n\nnodataerr:\n    /* Common error when the user asks for an event we have no latency\n     * information about. */\n    addReplyErrorFormat(c,\n        \"No samples available for event '%s'\", (char*) c->argv[2]->ptr);\n}\n\n"
  },
  {
    "path": "extern/deprecated/redis-2.8.21/src/latency.h",
    "content": "/* latency.h -- latency monitor API header file\n * See latency.c for more information.\n *\n * ----------------------------------------------------------------------------\n *\n * Copyright (c) 2014, Salvatore Sanfilippo <antirez at gmail dot com>\n * All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions are met:\n *\n *   * Redistributions of source code must retain the above copyright notice,\n *     this list of conditions and the following disclaimer.\n *   * Redistributions in binary form must reproduce the above copyright\n *     notice, this list of conditions and the following disclaimer in the\n *     documentation and/or other materials provided with the distribution.\n *   * Neither the name of Redis nor the names of its contributors may be used\n *     to endorse or promote products derived from this software without\n *     specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\"\n * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\n * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE\n * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR\n * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF\n * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS\n * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN\n * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)\n * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE\n * POSSIBILITY OF SUCH DAMAGE.\n */\n\n#ifndef __LATENCY_H\n#define __LATENCY_H\n\n#define LATENCY_TS_LEN 160 /* History length for every monitored event. */\n\n/* Representation of a latency sample: the sampling time and the latency\n * observed in milliseconds. */\nstruct latencySample {\n    int32_t time; /* We don't use time_t to force 4 bytes usage everywhere. */\n    uint32_t latency; /* Latency in milliseconds. */\n};\n\n/* The latency time series for a given event. */\nstruct latencyTimeSeries {\n    int idx; /* Index of the next sample to store. */\n    uint32_t max; /* Max latency observed for this event. */\n    struct latencySample samples[LATENCY_TS_LEN]; /* Latest history. */\n};\n\n/* Latency statistics structure. */\nstruct latencyStats {\n    uint32_t all_time_high; /* Absolute max observed since latest reset. */\n    uint32_t avg;           /* Average of current samples. */\n    uint32_t min;           /* Min of current samples. */\n    uint32_t max;           /* Max of current samples. */\n    uint32_t mad;           /* Mean absolute deviation. */\n    uint32_t samples;       /* Number of non-zero samples. */\n    time_t period;          /* Number of seconds since first event and now. */\n};\n\nvoid latencyMonitorInit(void);\nvoid latencyAddSample(char *event, mstime_t latency);\nint THPIsEnabled(void);\n\n/* Latency monitoring macros. */\n\n/* Start monitoring an event. We just set the current time. */\n#define latencyStartMonitor(var) if (server.latency_monitor_threshold) { \\\n    var = mstime(); \\\n} else { \\\n    var = 0; \\\n}\n\n/* End monitoring an event, compute the difference with the current time\n * to check the amount of time elapsed. */\n#define latencyEndMonitor(var) if (server.latency_monitor_threshold) { \\\n    var = mstime() - var; \\\n}\n\n/* Add the sample only if the elapsed time is >= to the configured threshold. */\n#define latencyAddSampleIfNeeded(event,var) \\\n    if (server.latency_monitor_threshold && \\\n        (var) >= server.latency_monitor_threshold) \\\n          latencyAddSample((event),(var));\n\n#endif /* __LATENCY_H */\n"
  },
  {
    "path": "extern/deprecated/redis-2.8.21/src/lzf.h",
    "content": "/*\n * Copyright (c) 2000-2008 Marc Alexander Lehmann <schmorp@schmorp.de>\n *\n * Redistribution and use in source and binary forms, with or without modifica-\n * tion, are permitted provided that the following conditions are met:\n *\n *   1.  Redistributions of source code must retain the above copyright notice,\n *       this list of conditions and the following disclaimer.\n *\n *   2.  Redistributions in binary form must reproduce the above copyright\n *       notice, this list of conditions and the following disclaimer in the\n *       documentation and/or other materials provided with the distribution.\n *\n * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED\n * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MER-\n * CHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO\n * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPE-\n * CIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,\n * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;\n * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,\n * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTH-\n * ERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED\n * OF THE POSSIBILITY OF SUCH DAMAGE.\n *\n * Alternatively, the contents of this file may be used under the terms of\n * the GNU General Public License (\"GPL\") version 2 or any later version,\n * in which case the provisions of the GPL are applicable instead of\n * the above. If you wish to allow the use of your version of this file\n * only under the terms of the GPL and not to allow others to use your\n * version of this file under the BSD license, indicate your decision\n * by deleting the provisions above and replace them with the notice\n * and other provisions required by the GPL. If you do not delete the\n * provisions above, a recipient may use your version of this file under\n * either the BSD or the GPL.\n */\n\n#ifndef LZF_H\n#define LZF_H\n\n/***********************************************************************\n**\n**\tlzf -- an extremely fast/free compression/decompression-method\n**\thttp://liblzf.plan9.de/\n**\n**\tThis algorithm is believed to be patent-free.\n**\n***********************************************************************/\n\n#define LZF_VERSION 0x0105 /* 1.5, API version */\n\n/*\n * Compress in_len bytes stored at the memory block starting at\n * in_data and write the result to out_data, up to a maximum length\n * of out_len bytes.\n *\n * If the output buffer is not large enough or any error occurs return 0,\n * otherwise return the number of bytes used, which might be considerably\n * more than in_len (but less than 104% of the original size), so it\n * makes sense to always use out_len == in_len - 1), to ensure _some_\n * compression, and store the data uncompressed otherwise (with a flag, of\n * course.\n *\n * lzf_compress might use different algorithms on different systems and\n * even different runs, thus might result in different compressed strings\n * depending on the phase of the moon or similar factors. However, all\n * these strings are architecture-independent and will result in the\n * original data when decompressed using lzf_decompress.\n *\n * The buffers must not be overlapping.\n *\n * If the option LZF_STATE_ARG is enabled, an extra argument must be\n * supplied which is not reflected in this header file. Refer to lzfP.h\n * and lzf_c.c.\n *\n */\nunsigned int\nlzf_compress (const void *const in_data,  unsigned int in_len,\n              void             *out_data, unsigned int out_len);\n\n/*\n * Decompress data compressed with some version of the lzf_compress\n * function and stored at location in_data and length in_len. The result\n * will be stored at out_data up to a maximum of out_len characters.\n *\n * If the output buffer is not large enough to hold the decompressed\n * data, a 0 is returned and errno is set to E2BIG. Otherwise the number\n * of decompressed bytes (i.e. the original length of the data) is\n * returned.\n *\n * If an error in the compressed data is detected, a zero is returned and\n * errno is set to EINVAL.\n *\n * This function is very fast, about as fast as a copying loop.\n */\nunsigned int\nlzf_decompress (const void *const in_data,  unsigned int in_len,\n                void             *out_data, unsigned int out_len);\n\n#endif\n\n"
  },
  {
    "path": "extern/deprecated/redis-2.8.21/src/lzfP.h",
    "content": "/*\n * Copyright (c) 2000-2007 Marc Alexander Lehmann <schmorp@schmorp.de>\n *\n * Redistribution and use in source and binary forms, with or without modifica-\n * tion, are permitted provided that the following conditions are met:\n *\n *   1.  Redistributions of source code must retain the above copyright notice,\n *       this list of conditions and the following disclaimer.\n *\n *   2.  Redistributions in binary form must reproduce the above copyright\n *       notice, this list of conditions and the following disclaimer in the\n *       documentation and/or other materials provided with the distribution.\n *\n * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED\n * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MER-\n * CHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO\n * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPE-\n * CIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,\n * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;\n * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,\n * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTH-\n * ERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED\n * OF THE POSSIBILITY OF SUCH DAMAGE.\n *\n * Alternatively, the contents of this file may be used under the terms of\n * the GNU General Public License (\"GPL\") version 2 or any later version,\n * in which case the provisions of the GPL are applicable instead of\n * the above. If you wish to allow the use of your version of this file\n * only under the terms of the GPL and not to allow others to use your\n * version of this file under the BSD license, indicate your decision\n * by deleting the provisions above and replace them with the notice\n * and other provisions required by the GPL. If you do not delete the\n * provisions above, a recipient may use your version of this file under\n * either the BSD or the GPL.\n */\n\n#ifndef LZFP_h\n#define LZFP_h\n\n#define STANDALONE 1 /* at the moment, this is ok. */\n\n#ifndef STANDALONE\n# include \"lzf.h\"\n#endif\n\n/*\n * Size of hashtable is (1 << HLOG) * sizeof (char *)\n * decompression is independent of the hash table size\n * the difference between 15 and 14 is very small\n * for small blocks (and 14 is usually a bit faster).\n * For a low-memory/faster configuration, use HLOG == 13;\n * For best compression, use 15 or 16 (or more, up to 23).\n */\n#ifndef HLOG\n# define HLOG 16\n#endif\n\n/*\n * Sacrifice very little compression quality in favour of compression speed.\n * This gives almost the same compression as the default code, and is\n * (very roughly) 15% faster. This is the preferred mode of operation.\n */\n#ifndef VERY_FAST\n# define VERY_FAST 1\n#endif\n\n/*\n * Sacrifice some more compression quality in favour of compression speed.\n * (roughly 1-2% worse compression for large blocks and\n * 9-10% for small, redundant, blocks and >>20% better speed in both cases)\n * In short: when in need for speed, enable this for binary data,\n * possibly disable this for text data.\n */\n#ifndef ULTRA_FAST\n# define ULTRA_FAST 0\n#endif\n\n/*\n * Unconditionally aligning does not cost very much, so do it if unsure\n */\n#ifndef STRICT_ALIGN\n# define STRICT_ALIGN !(defined(__i386) || defined (__amd64))\n#endif\n\n/*\n * You may choose to pre-set the hash table (might be faster on some\n * modern cpus and large (>>64k) blocks, and also makes compression\n * deterministic/repeatable when the configuration otherwise is the same).\n */\n#ifndef INIT_HTAB\n# define INIT_HTAB 0\n#endif\n\n/*\n * Avoid assigning values to errno variable? for some embedding purposes\n * (linux kernel for example), this is necessary. NOTE: this breaks\n * the documentation in lzf.h.\n */\n#ifndef AVOID_ERRNO\n# define AVOID_ERRNO 0\n#endif\n\n/*\n * Whether to pass the LZF_STATE variable as argument, or allocate it\n * on the stack. For small-stack environments, define this to 1.\n * NOTE: this breaks the prototype in lzf.h.\n */\n#ifndef LZF_STATE_ARG\n# define LZF_STATE_ARG 0\n#endif\n\n/*\n * Whether to add extra checks for input validity in lzf_decompress\n * and return EINVAL if the input stream has been corrupted. This\n * only shields against overflowing the input buffer and will not\n * detect most corrupted streams.\n * This check is not normally noticeable on modern hardware\n * (<1% slowdown), but might slow down older cpus considerably.\n */\n#ifndef CHECK_INPUT\n# define CHECK_INPUT 1\n#endif\n\n/*****************************************************************************/\n/* nothing should be changed below */\n\ntypedef unsigned char u8;\n\ntypedef const u8 *LZF_STATE[1 << (HLOG)];\n\n#if !STRICT_ALIGN\n/* for unaligned accesses we need a 16 bit datatype. */\n# include <limits.h>\n# if USHRT_MAX == 65535\n    typedef unsigned short u16;\n# elif UINT_MAX == 65535\n    typedef unsigned int u16;\n# else\n#  undef STRICT_ALIGN\n#  define STRICT_ALIGN 1\n# endif\n#endif\n\n#if ULTRA_FAST\n# if defined(VERY_FAST)\n#  undef VERY_FAST\n# endif\n#endif\n\n#if INIT_HTAB\n# ifdef __cplusplus\n#  include <cstring>\n# else\n#  include <string.h>\n# endif\n#endif\n\n#endif\n\n"
  },
  {
    "path": "extern/deprecated/redis-2.8.21/src/lzf_c.c",
    "content": "/*\n * Copyright (c) 2000-2008 Marc Alexander Lehmann <schmorp@schmorp.de>\n *\n * Redistribution and use in source and binary forms, with or without modifica-\n * tion, are permitted provided that the following conditions are met:\n *\n *   1.  Redistributions of source code must retain the above copyright notice,\n *       this list of conditions and the following disclaimer.\n *\n *   2.  Redistributions in binary form must reproduce the above copyright\n *       notice, this list of conditions and the following disclaimer in the\n *       documentation and/or other materials provided with the distribution.\n *\n * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED\n * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MER-\n * CHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO\n * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPE-\n * CIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,\n * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;\n * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,\n * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTH-\n * ERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED\n * OF THE POSSIBILITY OF SUCH DAMAGE.\n *\n * Alternatively, the contents of this file may be used under the terms of\n * the GNU General Public License (\"GPL\") version 2 or any later version,\n * in which case the provisions of the GPL are applicable instead of\n * the above. If you wish to allow the use of your version of this file\n * only under the terms of the GPL and not to allow others to use your\n * version of this file under the BSD license, indicate your decision\n * by deleting the provisions above and replace them with the notice\n * and other provisions required by the GPL. If you do not delete the\n * provisions above, a recipient may use your version of this file under\n * either the BSD or the GPL.\n */\n\n#include \"lzfP.h\"\n\n#define HSIZE (1 << (HLOG))\n\n/*\n * don't play with this unless you benchmark!\n * decompression is not dependent on the hash function\n * the hashing function might seem strange, just believe me\n * it works ;)\n */\n#ifndef FRST\n# define FRST(p) (((p[0]) << 8) | p[1])\n# define NEXT(v,p) (((v) << 8) | p[2])\n# if ULTRA_FAST\n#  define IDX(h) ((( h             >> (3*8 - HLOG)) - h  ) & (HSIZE - 1))\n# elif VERY_FAST\n#  define IDX(h) ((( h             >> (3*8 - HLOG)) - h*5) & (HSIZE - 1))\n# else\n#  define IDX(h) ((((h ^ (h << 5)) >> (3*8 - HLOG)) - h*5) & (HSIZE - 1))\n# endif\n#endif\n/*\n * IDX works because it is very similar to a multiplicative hash, e.g.\n * ((h * 57321 >> (3*8 - HLOG)) & (HSIZE - 1))\n * the latter is also quite fast on newer CPUs, and compresses similarly.\n *\n * the next one is also quite good, albeit slow ;)\n * (int)(cos(h & 0xffffff) * 1e6)\n */\n\n#if 0\n/* original lzv-like hash function, much worse and thus slower */\n# define FRST(p) (p[0] << 5) ^ p[1]\n# define NEXT(v,p) ((v) << 5) ^ p[2]\n# define IDX(h) ((h) & (HSIZE - 1))\n#endif\n\n#define        MAX_LIT        (1 <<  5)\n#define        MAX_OFF        (1 << 13)\n#define        MAX_REF        ((1 << 8) + (1 << 3))\n\n#if __GNUC__ >= 3\n# define expect(expr,value)         __builtin_expect ((expr),(value))\n# define inline                     inline\n#else\n# define expect(expr,value)         (expr)\n# define inline                     static\n#endif\n\n#define expect_false(expr) expect ((expr) != 0, 0)\n#define expect_true(expr)  expect ((expr) != 0, 1)\n\n/*\n * compressed format\n *\n * 000LLLLL <L+1>    ; literal\n * LLLooooo oooooooo ; backref L\n * 111ooooo LLLLLLLL oooooooo ; backref L+7\n *\n */\n\nunsigned int\nlzf_compress (const void *const in_data, unsigned int in_len,\n\t      void *out_data, unsigned int out_len\n#if LZF_STATE_ARG\n              , LZF_STATE htab\n#endif\n              )\n{\n#if !LZF_STATE_ARG\n  LZF_STATE htab;\n#endif\n  const u8 **hslot;\n  const u8 *ip = (const u8 *)in_data;\n        u8 *op = (u8 *)out_data;\n  const u8 *in_end  = ip + in_len;\n        u8 *out_end = op + out_len;\n  const u8 *ref;\n\n  /* off requires a type wide enough to hold a general pointer difference.\n   * ISO C doesn't have that (size_t might not be enough and ptrdiff_t only\n   * works for differences within a single object). We also assume that no\n   * no bit pattern traps. Since the only platform that is both non-POSIX\n   * and fails to support both assumptions is windows 64 bit, we make a\n   * special workaround for it.\n   */\n#if defined (WIN32) && defined (_M_X64)\n  unsigned _int64 off; /* workaround for missing POSIX compliance */\n#else\n  unsigned long off;\n#endif\n  unsigned int hval;\n  int lit;\n\n  if (!in_len || !out_len)\n    return 0;\n\n#if INIT_HTAB\n  memset (htab, 0, sizeof (htab));\n# if 0\n  for (hslot = htab; hslot < htab + HSIZE; hslot++)\n    *hslot++ = ip;\n# endif\n#endif\n\n  lit = 0; op++; /* start run */\n\n  hval = FRST (ip);\n  while (ip < in_end - 2)\n    {\n      hval = NEXT (hval, ip);\n      hslot = htab + IDX (hval);\n      ref = *hslot; *hslot = ip;\n\n      if (1\n#if INIT_HTAB\n          && ref < ip /* the next test will actually take care of this, but this is faster */\n#endif\n          && (off = ip - ref - 1) < MAX_OFF\n          && ip + 4 < in_end\n          && ref > (u8 *)in_data\n#if STRICT_ALIGN\n          && ref[0] == ip[0]\n          && ref[1] == ip[1]\n          && ref[2] == ip[2]\n#else\n          && *(u16 *)ref == *(u16 *)ip\n          && ref[2] == ip[2]\n#endif\n        )\n        {\n          /* match found at *ref++ */\n          unsigned int len = 2;\n          unsigned int maxlen = in_end - ip - len;\n          maxlen = maxlen > MAX_REF ? MAX_REF : maxlen;\n\n          op [- lit - 1] = lit - 1; /* stop run */\n          op -= !lit; /* undo run if length is zero */\n\n          if (expect_false (op + 3 + 1 >= out_end))\n            return 0;\n\n          for (;;)\n            {\n              if (expect_true (maxlen > 16))\n                {\n                  len++; if (ref [len] != ip [len]) break;\n                  len++; if (ref [len] != ip [len]) break;\n                  len++; if (ref [len] != ip [len]) break;\n                  len++; if (ref [len] != ip [len]) break;\n\n                  len++; if (ref [len] != ip [len]) break;\n                  len++; if (ref [len] != ip [len]) break;\n                  len++; if (ref [len] != ip [len]) break;\n                  len++; if (ref [len] != ip [len]) break;\n\n                  len++; if (ref [len] != ip [len]) break;\n                  len++; if (ref [len] != ip [len]) break;\n                  len++; if (ref [len] != ip [len]) break;\n                  len++; if (ref [len] != ip [len]) break;\n\n                  len++; if (ref [len] != ip [len]) break;\n                  len++; if (ref [len] != ip [len]) break;\n                  len++; if (ref [len] != ip [len]) break;\n                  len++; if (ref [len] != ip [len]) break;\n                }\n\n              do\n                len++;\n              while (len < maxlen && ref[len] == ip[len]);\n\n              break;\n            }\n\n          len -= 2; /* len is now #octets - 1 */\n          ip++;\n\n          if (len < 7)\n            {\n              *op++ = (off >> 8) + (len << 5);\n            }\n          else\n            {\n              *op++ = (off >> 8) + (  7 << 5);\n              *op++ = len - 7;\n            }\n\n          *op++ = off;\n          lit = 0; op++; /* start run */\n\n          ip += len + 1;\n\n          if (expect_false (ip >= in_end - 2))\n            break;\n\n#if ULTRA_FAST || VERY_FAST\n          --ip;\n# if VERY_FAST && !ULTRA_FAST\n          --ip;\n# endif\n          hval = FRST (ip);\n\n          hval = NEXT (hval, ip);\n          htab[IDX (hval)] = ip;\n          ip++;\n\n# if VERY_FAST && !ULTRA_FAST\n          hval = NEXT (hval, ip);\n          htab[IDX (hval)] = ip;\n          ip++;\n# endif\n#else\n          ip -= len + 1;\n\n          do\n            {\n              hval = NEXT (hval, ip);\n              htab[IDX (hval)] = ip;\n              ip++;\n            }\n          while (len--);\n#endif\n        }\n      else\n        {\n          /* one more literal byte we must copy */\n          if (expect_false (op >= out_end))\n            return 0;\n\n          lit++; *op++ = *ip++;\n\n          if (expect_false (lit == MAX_LIT))\n            {\n              op [- lit - 1] = lit - 1; /* stop run */\n              lit = 0; op++; /* start run */\n            }\n        }\n    }\n\n  if (op + 3 > out_end) /* at most 3 bytes can be missing here */\n    return 0;\n\n  while (ip < in_end)\n    {\n      lit++; *op++ = *ip++;\n\n      if (expect_false (lit == MAX_LIT))\n        {\n          op [- lit - 1] = lit - 1; /* stop run */\n          lit = 0; op++; /* start run */\n        }\n    }\n\n  op [- lit - 1] = lit - 1; /* end run */\n  op -= !lit; /* undo run if length is zero */\n\n  return op - (u8 *)out_data;\n}\n\n"
  },
  {
    "path": "extern/deprecated/redis-2.8.21/src/lzf_d.c",
    "content": "/*\n * Copyright (c) 2000-2007 Marc Alexander Lehmann <schmorp@schmorp.de>\n *\n * Redistribution and use in source and binary forms, with or without modifica-\n * tion, are permitted provided that the following conditions are met:\n *\n *   1.  Redistributions of source code must retain the above copyright notice,\n *       this list of conditions and the following disclaimer.\n *\n *   2.  Redistributions in binary form must reproduce the above copyright\n *       notice, this list of conditions and the following disclaimer in the\n *       documentation and/or other materials provided with the distribution.\n *\n * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED\n * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MER-\n * CHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO\n * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPE-\n * CIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,\n * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;\n * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,\n * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTH-\n * ERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED\n * OF THE POSSIBILITY OF SUCH DAMAGE.\n *\n * Alternatively, the contents of this file may be used under the terms of\n * the GNU General Public License (\"GPL\") version 2 or any later version,\n * in which case the provisions of the GPL are applicable instead of\n * the above. If you wish to allow the use of your version of this file\n * only under the terms of the GPL and not to allow others to use your\n * version of this file under the BSD license, indicate your decision\n * by deleting the provisions above and replace them with the notice\n * and other provisions required by the GPL. If you do not delete the\n * provisions above, a recipient may use your version of this file under\n * either the BSD or the GPL.\n */\n\n#include \"lzfP.h\"\n\n#if AVOID_ERRNO\n# define SET_ERRNO(n)\n#else\n# include <errno.h>\n# define SET_ERRNO(n) errno = (n)\n#endif\n\n/*\n#if (__i386 || __amd64) && __GNUC__ >= 3\n# define lzf_movsb(dst, src, len)                \\\n   asm (\"rep movsb\"                              \\\n        : \"=D\" (dst), \"=S\" (src), \"=c\" (len)     \\\n        :  \"0\" (dst),  \"1\" (src),  \"2\" (len));\n#endif\n*/\n\nunsigned int\nlzf_decompress (const void *const in_data,  unsigned int in_len,\n                void             *out_data, unsigned int out_len)\n{\n  u8 const *ip = (const u8 *)in_data;\n  u8       *op = (u8 *)out_data;\n  u8 const *const in_end  = ip + in_len;\n  u8       *const out_end = op + out_len;\n\n  do\n    {\n      unsigned int ctrl = *ip++;\n\n      if (ctrl < (1 << 5)) /* literal run */\n        {\n          ctrl++;\n\n          if (op + ctrl > out_end)\n            {\n              SET_ERRNO (E2BIG);\n              return 0;\n            }\n\n#if CHECK_INPUT\n          if (ip + ctrl > in_end)\n            {\n              SET_ERRNO (EINVAL);\n              return 0;\n            }\n#endif\n\n#ifdef lzf_movsb\n          lzf_movsb (op, ip, ctrl);\n#else\n          do\n            *op++ = *ip++;\n          while (--ctrl);\n#endif\n        }\n      else /* back reference */\n        {\n          unsigned int len = ctrl >> 5;\n\n          u8 *ref = op - ((ctrl & 0x1f) << 8) - 1;\n\n#if CHECK_INPUT\n          if (ip >= in_end)\n            {\n              SET_ERRNO (EINVAL);\n              return 0;\n            }\n#endif\n          if (len == 7)\n            {\n              len += *ip++;\n#if CHECK_INPUT\n              if (ip >= in_end)\n                {\n                  SET_ERRNO (EINVAL);\n                  return 0;\n                }\n#endif\n            }\n\n          ref -= *ip++;\n\n          if (op + len + 2 > out_end)\n            {\n              SET_ERRNO (E2BIG);\n              return 0;\n            }\n\n          if (ref < (u8 *)out_data)\n            {\n              SET_ERRNO (EINVAL);\n              return 0;\n            }\n\n#ifdef lzf_movsb\n          len += 2;\n          lzf_movsb (op, ref, len);\n#else\n          *op++ = *ref++;\n          *op++ = *ref++;\n\n          do\n            *op++ = *ref++;\n          while (--len);\n#endif\n        }\n    }\n  while (ip < in_end);\n\n  return op - (u8 *)out_data;\n}\n\n"
  },
  {
    "path": "extern/deprecated/redis-2.8.21/src/memtest.c",
    "content": "/*\n * Copyright (c) 2009-2012, Salvatore Sanfilippo <antirez at gmail dot com>\n * All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions are met:\n *\n *   * Redistributions of source code must retain the above copyright notice,\n *     this list of conditions and the following disclaimer.\n *   * Redistributions in binary form must reproduce the above copyright\n *     notice, this list of conditions and the following disclaimer in the\n *     documentation and/or other materials provided with the distribution.\n *   * Neither the name of Redis nor the names of its contributors may be used\n *     to endorse or promote products derived from this software without\n *     specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\"\n * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\n * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE\n * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR\n * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF\n * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS\n * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN\n * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)\n * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE\n * POSSIBILITY OF SUCH DAMAGE.\n */\n\n#include <stdlib.h>\n#include <stdio.h>\n#include <string.h>\n#include <assert.h>\n#include <limits.h>\n#include <errno.h>\n#include <termios.h>\n#include <sys/ioctl.h>\n#if defined(__sun)\n#include <stropts.h>\n#endif\n#include \"config.h\"\n\n#if (ULONG_MAX == 4294967295UL)\n#define MEMTEST_32BIT\n#elif (ULONG_MAX == 18446744073709551615ULL)\n#define MEMTEST_64BIT\n#else\n#error \"ULONG_MAX value not supported.\"\n#endif\n\n#ifdef MEMTEST_32BIT\n#define ULONG_ONEZERO 0xaaaaaaaaUL\n#define ULONG_ZEROONE 0x55555555UL\n#else\n#define ULONG_ONEZERO 0xaaaaaaaaaaaaaaaaUL\n#define ULONG_ZEROONE 0x5555555555555555UL\n#endif\n\nstatic struct winsize ws;\nsize_t progress_printed; /* Printed chars in screen-wide progress bar. */\nsize_t progress_full; /* How many chars to write to fill the progress bar. */\n\nvoid memtest_progress_start(char *title, int pass) {\n    int j;\n\n    printf(\"\\x1b[H\\x1b[2J\");    /* Cursor home, clear screen. */\n    /* Fill with dots. */\n    for (j = 0; j < ws.ws_col*(ws.ws_row-2); j++) printf(\".\");\n    printf(\"Please keep the test running several minutes per GB of memory.\\n\");\n    printf(\"Also check http://www.memtest86.com/ and http://pyropus.ca/software/memtester/\");\n    printf(\"\\x1b[H\\x1b[2K\");          /* Cursor home, clear current line.  */\n    printf(\"%s [%d]\\n\", title, pass); /* Print title. */\n    progress_printed = 0;\n    progress_full = ws.ws_col*(ws.ws_row-3);\n    fflush(stdout);\n}\n\nvoid memtest_progress_end(void) {\n    printf(\"\\x1b[H\\x1b[2J\");    /* Cursor home, clear screen. */\n}\n\nvoid memtest_progress_step(size_t curr, size_t size, char c) {\n    size_t chars = ((unsigned long long)curr*progress_full)/size, j;\n\n    for (j = 0; j < chars-progress_printed; j++) printf(\"%c\",c);\n    progress_printed = chars;\n    fflush(stdout);\n}\n\n/* Test that addressing is fine. Every location is populated with its own\n * address, and finally verified. This test is very fast but may detect\n * ASAP big issues with the memory subsystem. */\nvoid memtest_addressing(unsigned long *l, size_t bytes) {\n    unsigned long words = bytes/sizeof(unsigned long);\n    unsigned long j, *p;\n\n    /* Fill */\n    p = l;\n    for (j = 0; j < words; j++) {\n        *p = (unsigned long)p;\n        p++;\n        if ((j & 0xffff) == 0) memtest_progress_step(j,words*2,'A');\n    }\n    /* Test */\n    p = l;\n    for (j = 0; j < words; j++) {\n        if (*p != (unsigned long)p) {\n            printf(\"\\n*** MEMORY ADDRESSING ERROR: %p contains %lu\\n\",\n                (void*) p, *p);\n            exit(1);\n        }\n        p++;\n        if ((j & 0xffff) == 0) memtest_progress_step(j+words,words*2,'A');\n    }\n}\n\n/* Fill words stepping a single page at every write, so we continue to\n * touch all the pages in the smallest amount of time reducing the\n * effectiveness of caches, and making it hard for the OS to transfer\n * pages on the swap. */\nvoid memtest_fill_random(unsigned long *l, size_t bytes) {\n    unsigned long step = 4096/sizeof(unsigned long);\n    unsigned long words = bytes/sizeof(unsigned long)/2;\n    unsigned long iwords = words/step;  /* words per iteration */\n    unsigned long off, w, *l1, *l2;\n\n    assert((bytes & 4095) == 0);\n    for (off = 0; off < step; off++) {\n        l1 = l+off;\n        l2 = l1+words;\n        for (w = 0; w < iwords; w++) {\n#ifdef MEMTEST_32BIT\n            *l1 = *l2 = ((unsigned long)     (rand()&0xffff)) |\n                        (((unsigned long)    (rand()&0xffff)) << 16);\n#else\n            *l1 = *l2 = ((unsigned long)     (rand()&0xffff)) |\n                        (((unsigned long)    (rand()&0xffff)) << 16) |\n                        (((unsigned long)    (rand()&0xffff)) << 32) |\n                        (((unsigned long)    (rand()&0xffff)) << 48);\n#endif\n            l1 += step;\n            l2 += step;\n            if ((w & 0xffff) == 0)\n                memtest_progress_step(w+iwords*off,words,'R');\n        }\n    }\n}\n\n/* Like memtest_fill_random() but uses the two specified values to fill\n * memory, in an alternated way (v1|v2|v1|v2|...) */\nvoid memtest_fill_value(unsigned long *l, size_t bytes, unsigned long v1,\n                        unsigned long v2, char sym)\n{\n    unsigned long step = 4096/sizeof(unsigned long);\n    unsigned long words = bytes/sizeof(unsigned long)/2;\n    unsigned long iwords = words/step;  /* words per iteration */\n    unsigned long off, w, *l1, *l2, v;\n\n    assert((bytes & 4095) == 0);\n    for (off = 0; off < step; off++) {\n        l1 = l+off;\n        l2 = l1+words;\n        v = (off & 1) ? v2 : v1;\n        for (w = 0; w < iwords; w++) {\n#ifdef MEMTEST_32BIT\n            *l1 = *l2 = ((unsigned long)     v) |\n                        (((unsigned long)    v) << 16);\n#else\n            *l1 = *l2 = ((unsigned long)     v) |\n                        (((unsigned long)    v) << 16) |\n                        (((unsigned long)    v) << 32) |\n                        (((unsigned long)    v) << 48);\n#endif\n            l1 += step;\n            l2 += step;\n            if ((w & 0xffff) == 0)\n                memtest_progress_step(w+iwords*off,words,sym);\n        }\n    }\n}\n\nvoid memtest_compare(unsigned long *l, size_t bytes) {\n    unsigned long words = bytes/sizeof(unsigned long)/2;\n    unsigned long w, *l1, *l2;\n\n    assert((bytes & 4095) == 0);\n    l1 = l;\n    l2 = l1+words;\n    for (w = 0; w < words; w++) {\n        if (*l1 != *l2) {\n            printf(\"\\n*** MEMORY ERROR DETECTED: %p != %p (%lu vs %lu)\\n\",\n                (void*)l1, (void*)l2, *l1, *l2);\n            exit(1);\n        }\n        l1 ++;\n        l2 ++;\n        if ((w & 0xffff) == 0) memtest_progress_step(w,words,'=');\n    }\n}\n\nvoid memtest_compare_times(unsigned long *m, size_t bytes, int pass, int times) {\n    int j;\n\n    for (j = 0; j < times; j++) {\n        memtest_progress_start(\"Compare\",pass);\n        memtest_compare(m,bytes);\n        memtest_progress_end();\n    }\n}\n\nvoid memtest_test(size_t megabytes, int passes) {\n    size_t bytes = megabytes*1024*1024;\n    unsigned long *m = malloc(bytes);\n    int pass = 0;\n\n    if (m == NULL) {\n        fprintf(stderr,\"Unable to allocate %zu megabytes: %s\",\n            megabytes, strerror(errno));\n        exit(1);\n    }\n    while (pass != passes) {\n        pass++;\n\n        memtest_progress_start(\"Addressing test\",pass);\n        memtest_addressing(m,bytes);\n        memtest_progress_end();\n\n        memtest_progress_start(\"Random fill\",pass);\n        memtest_fill_random(m,bytes);\n        memtest_progress_end();\n        memtest_compare_times(m,bytes,pass,4);\n\n        memtest_progress_start(\"Solid fill\",pass);\n        memtest_fill_value(m,bytes,0,(unsigned long)-1,'S');\n        memtest_progress_end();\n        memtest_compare_times(m,bytes,pass,4);\n\n        memtest_progress_start(\"Checkerboard fill\",pass);\n        memtest_fill_value(m,bytes,ULONG_ONEZERO,ULONG_ZEROONE,'C');\n        memtest_progress_end();\n        memtest_compare_times(m,bytes,pass,4);\n    }\n    free(m);\n}\n\nvoid memtest_non_destructive_invert(void *addr, size_t size) {\n    volatile unsigned long *p = addr;\n    size_t words = size / sizeof(unsigned long);\n    size_t j;\n\n    /* Invert */\n    for (j = 0; j < words; j++)\n        p[j] = ~p[j];\n}\n\nvoid memtest_non_destructive_swap(void *addr, size_t size) {\n    volatile unsigned long *p = addr;\n    size_t words = size / sizeof(unsigned long);\n    size_t j;\n\n    /* Swap */\n    for (j = 0; j < words; j += 2) {\n        unsigned long a, b;\n\n        a = p[j];\n        b = p[j+1];\n        p[j] = b;\n        p[j+1] = a;\n    }\n}\n\nvoid memtest(size_t megabytes, int passes) {\n    if (ioctl(1, TIOCGWINSZ, &ws) == -1) {\n        ws.ws_col = 80;\n        ws.ws_row = 20;\n    }\n    memtest_test(megabytes,passes);\n    printf(\"\\nYour memory passed this test.\\n\");\n    printf(\"Please if you are still in doubt use the following two tools:\\n\");\n    printf(\"1) memtest86: http://www.memtest86.com/\\n\");\n    printf(\"2) memtester: http://pyropus.ca/software/memtester/\\n\");\n    exit(0);\n}\n"
  },
  {
    "path": "extern/deprecated/redis-2.8.21/src/migrate.c",
    "content": "#include \"redis.h\"\n#include \"endianconv.h\"\n\n/* -----------------------------------------------------------------------------\n * DUMP, RESTORE and MIGRATE commands\n * -------------------------------------------------------------------------- */\n\n/* Generates a DUMP-format representation of the object 'o', adding it to the\n * io stream pointed by 'rio'. This function can't fail. */\nvoid createDumpPayload(rio *payload, robj *o) {\n    unsigned char buf[2];\n    uint64_t crc;\n\n    /* Serialize the object in a RDB-like format. It consist of an object type\n     * byte followed by the serialized object. This is understood by RESTORE. */\n    rioInitWithBuffer(payload,sdsempty());\n    redisAssert(rdbSaveObjectType(payload,o));\n    redisAssert(rdbSaveObject(payload,o));\n\n    /* Write the footer, this is how it looks like:\n     * ----------------+---------------------+---------------+\n     * ... RDB payload | 2 bytes RDB version | 8 bytes CRC64 |\n     * ----------------+---------------------+---------------+\n     * RDB version and CRC are both in little endian.\n     */\n\n    /* RDB version */\n    buf[0] = REDIS_RDB_VERSION & 0xff;\n    buf[1] = (REDIS_RDB_VERSION >> 8) & 0xff;\n    payload->io.buffer.ptr = sdscatlen(payload->io.buffer.ptr,buf,2);\n\n    /* CRC64 */\n    crc = crc64(0,(unsigned char*)payload->io.buffer.ptr,\n                sdslen(payload->io.buffer.ptr));\n    memrev64ifbe(&crc);\n    payload->io.buffer.ptr = sdscatlen(payload->io.buffer.ptr,&crc,8);\n}\n\n/* Verify that the RDB version of the dump payload matches the one of this Redis\n * instance and that the checksum is ok.\n * If the DUMP payload looks valid REDIS_OK is returned, otherwise REDIS_ERR\n * is returned. */\nint verifyDumpPayload(unsigned char *p, size_t len) {\n    unsigned char *footer;\n    uint16_t rdbver;\n    uint64_t crc;\n\n    /* At least 2 bytes of RDB version and 8 of CRC64 should be present. */\n    if (len < 10) return REDIS_ERR;\n    footer = p+(len-10);\n\n    /* Verify RDB version */\n    rdbver = (footer[1] << 8) | footer[0];\n    if (rdbver != REDIS_RDB_VERSION) return REDIS_ERR;\n\n    /* Verify CRC64 */\n    crc = crc64(0,p,len-8);\n    memrev64ifbe(&crc);\n    return (memcmp(&crc,footer+2,8) == 0) ? REDIS_OK : REDIS_ERR;\n}\n\n/* DUMP keyname\n * DUMP is actually not used by Redis Cluster but it is the obvious\n * complement of RESTORE and can be useful for different applications. */\nvoid dumpCommand(redisClient *c) {\n    robj *o, *dumpobj;\n    rio payload;\n\n    /* Check if the key is here. */\n    if ((o = lookupKeyRead(c->db,c->argv[1])) == NULL) {\n        addReply(c,shared.nullbulk);\n        return;\n    }\n\n    /* Create the DUMP encoded representation. */\n    createDumpPayload(&payload,o);\n\n    /* Transfer to the client */\n    dumpobj = createObject(REDIS_STRING,payload.io.buffer.ptr);\n    addReplyBulk(c,dumpobj);\n    decrRefCount(dumpobj);\n    return;\n}\n\n/* RESTORE key ttl serialized-value */\nvoid restoreCommand(redisClient *c) {\n    long long ttl;\n    rio payload;\n    int type;\n    robj *obj;\n\n    /* Make sure this key does not already exist here... */\n    if (lookupKeyWrite(c->db,c->argv[1]) != NULL) {\n        addReplyError(c,\"Target key name is busy.\");\n        return;\n    }\n\n    /* Check if the TTL value makes sense */\n    if (getLongLongFromObjectOrReply(c,c->argv[2],&ttl,NULL) != REDIS_OK) {\n        return;\n    } else if (ttl < 0) {\n        addReplyError(c,\"Invalid TTL value, must be >= 0\");\n        return;\n    }\n\n    /* Verify RDB version and data checksum. */\n    if (verifyDumpPayload(c->argv[3]->ptr,sdslen(c->argv[3]->ptr)) == REDIS_ERR)\n    {\n        addReplyError(c,\"DUMP payload version or checksum are wrong\");\n        return;\n    }\n\n    rioInitWithBuffer(&payload,c->argv[3]->ptr);\n    if (((type = rdbLoadObjectType(&payload)) == -1) ||\n        ((obj = rdbLoadObject(type,&payload)) == NULL))\n    {\n        addReplyError(c,\"Bad data format\");\n        return;\n    }\n\n    /* Create the key and set the TTL if any */\n    dbAdd(c->db,c->argv[1],obj);\n    if (ttl) setExpire(c->db,c->argv[1],mstime()+ttl);\n    signalModifiedKey(c->db,c->argv[1]);\n    addReply(c,shared.ok);\n    server.dirty++;\n}\n\n/* MIGRATE host port key dbid timeout */\nvoid migrateCommand(redisClient *c) {\n    int fd;\n    long timeout;\n    long dbid;\n    long long ttl = 0, expireat;\n    robj *o;\n    rio cmd, payload;\n\n    /* Sanity check */\n    if (getLongFromObjectOrReply(c,c->argv[5],&timeout,NULL) != REDIS_OK)\n        return;\n    if (getLongFromObjectOrReply(c,c->argv[4],&dbid,NULL) != REDIS_OK)\n        return;\n    if (timeout <= 0) timeout = 1000;\n\n    /* Check if the key is here. If not we reply with success as there is\n     * nothing to migrate (for instance the key expired in the meantime), but\n     * we include such information in the reply string. */\n    if ((o = lookupKeyRead(c->db,c->argv[3])) == NULL) {\n        addReplySds(c,sdsnew(\"+NOKEY\\r\\n\"));\n        return;\n    }\n\n    /* Connect */\n    fd = anetTcpNonBlockConnect(server.neterr,c->argv[1]->ptr,\n                atoi(c->argv[2]->ptr));\n    if (fd == -1) {\n        addReplyErrorFormat(c,\"Can't connect to target node: %s\",\n            server.neterr);\n        return;\n    }\n    anetEnableTcpNoDelay(server.neterr,fd);\n\n    if ((aeWait(fd,AE_WRITABLE,timeout) & AE_WRITABLE) == 0) {\n        addReplySds(c,sdsnew(\"-IOERR error or timeout connecting to the client\\r\\n\"));\n        close(fd);\n        return;\n    }\n\n    /* Create RESTORE payload and generate the protocol to call the command. */\n    rioInitWithBuffer(&cmd,sdsempty());\n    redisAssertWithInfo(c,NULL,rioWriteBulkCount(&cmd,'*',2));\n    redisAssertWithInfo(c,NULL,rioWriteBulkString(&cmd,\"SELECT\",6));\n    redisAssertWithInfo(c,NULL,rioWriteBulkLongLong(&cmd,dbid));\n\n    expireat = getExpire(c->db,c->argv[3]);\n    if (expireat != -1) {\n        ttl = expireat-mstime();\n        if (ttl < 1) ttl = 1;\n    }\n    redisAssertWithInfo(c,NULL,rioWriteBulkCount(&cmd,'*',4));\n    redisAssertWithInfo(c,NULL,rioWriteBulkString(&cmd,\"RESTORE\",7));\n    redisAssertWithInfo(c,NULL,c->argv[3]->encoding == REDIS_ENCODING_RAW);\n    redisAssertWithInfo(c,NULL,rioWriteBulkString(&cmd,c->argv[3]->ptr,sdslen(c->argv[3]->ptr)));\n    redisAssertWithInfo(c,NULL,rioWriteBulkLongLong(&cmd,ttl));\n\n    /* Finally the last argument that is the serailized object payload\n     * in the DUMP format. */\n    createDumpPayload(&payload,o);\n    redisAssertWithInfo(c,NULL,rioWriteBulkString(&cmd,payload.io.buffer.ptr,\n                                sdslen(payload.io.buffer.ptr)));\n    sdsfree(payload.io.buffer.ptr);\n\n    /* Tranfer the query to the other node in 64K chunks. */\n    {\n        sds buf = cmd.io.buffer.ptr;\n        size_t pos = 0, towrite;\n        int nwritten = 0;\n\n        while ((towrite = sdslen(buf)-pos) > 0) {\n            towrite = (towrite > (64*1024) ? (64*1024) : towrite);\n            nwritten = syncWrite(fd,buf+pos,towrite,timeout);\n            if (nwritten != (signed)towrite) goto socket_wr_err;\n            pos += nwritten;\n        }\n    }\n\n    /* Read back the reply. */\n    {\n        char buf1[1024];\n        char buf2[1024];\n\n        /* Read the two replies */\n        if (syncReadLine(fd, buf1, sizeof(buf1), timeout) <= 0)\n            goto socket_rd_err;\n        if (syncReadLine(fd, buf2, sizeof(buf2), timeout) <= 0)\n            goto socket_rd_err;\n        if (buf1[0] == '-' || buf2[0] == '-') {\n            addReplyErrorFormat(c,\"Target instance replied with error: %s\",\n                (buf1[0] == '-') ? buf1+1 : buf2+1);\n        } else {\n            robj *aux;\n\n            dbDelete(c->db,c->argv[3]);\n            signalModifiedKey(c->db,c->argv[3]);\n            addReply(c,shared.ok);\n            server.dirty++;\n\n            /* Translate MIGRATE as DEL for replication/AOF. */\n            aux = createStringObject(\"DEL\",3);\n            rewriteClientCommandVector(c,2,aux,c->argv[3]);\n            decrRefCount(aux);\n        }\n    }\n\n    sdsfree(cmd.io.buffer.ptr);\n    close(fd);\n    return;\n\nsocket_wr_err:\n    addReplySds(c,sdsnew(\"-IOERR error or timeout writing to target instance\\r\\n\"));\n    sdsfree(cmd.io.buffer.ptr);\n    close(fd);\n    return;\n\nsocket_rd_err:\n    addReplySds(c,sdsnew(\"-IOERR error or timeout reading from target node\\r\\n\"));\n    sdsfree(cmd.io.buffer.ptr);\n    close(fd);\n    return;\n}\n"
  },
  {
    "path": "extern/deprecated/redis-2.8.21/src/mkreleasehdr.sh",
    "content": "#!/bin/sh\nGIT_SHA1=`(git show-ref --head --hash=8 2> /dev/null || echo 00000000) | head -n1`\nGIT_DIRTY=`git diff --no-ext-diff 2> /dev/null | wc -l`\nBUILD_ID=`uname -n`\"-\"`date +%s`\ntest -f release.h || touch release.h\n(cat release.h | grep SHA1 | grep $GIT_SHA1) && \\\n(cat release.h | grep DIRTY | grep $GIT_DIRTY) && exit 0 # Already up-to-date\necho \"#define REDIS_GIT_SHA1 \\\"$GIT_SHA1\\\"\" > release.h\necho \"#define REDIS_GIT_DIRTY \\\"$GIT_DIRTY\\\"\" >> release.h\necho \"#define REDIS_BUILD_ID \\\"$BUILD_ID\\\"\" >> release.h\ntouch release.c # Force recompile of release.c\n"
  },
  {
    "path": "extern/deprecated/redis-2.8.21/src/multi.c",
    "content": "/*\n * Copyright (c) 2009-2012, Salvatore Sanfilippo <antirez at gmail dot com>\n * All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions are met:\n *\n *   * Redistributions of source code must retain the above copyright notice,\n *     this list of conditions and the following disclaimer.\n *   * Redistributions in binary form must reproduce the above copyright\n *     notice, this list of conditions and the following disclaimer in the\n *     documentation and/or other materials provided with the distribution.\n *   * Neither the name of Redis nor the names of its contributors may be used\n *     to endorse or promote products derived from this software without\n *     specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\"\n * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\n * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE\n * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR\n * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF\n * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS\n * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN\n * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)\n * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE\n * POSSIBILITY OF SUCH DAMAGE.\n */\n\n#include \"redis.h\"\n\n/* ================================ MULTI/EXEC ============================== */\n\n/* Client state initialization for MULTI/EXEC */\nvoid initClientMultiState(redisClient *c) {\n    c->mstate.commands = NULL;\n    c->mstate.count = 0;\n}\n\n/* Release all the resources associated with MULTI/EXEC state */\nvoid freeClientMultiState(redisClient *c) {\n    int j;\n\n    for (j = 0; j < c->mstate.count; j++) {\n        int i;\n        multiCmd *mc = c->mstate.commands+j;\n\n        for (i = 0; i < mc->argc; i++)\n            decrRefCount(mc->argv[i]);\n        zfree(mc->argv);\n    }\n    zfree(c->mstate.commands);\n}\n\n/* Add a new command into the MULTI commands queue */\nvoid queueMultiCommand(redisClient *c) {\n    multiCmd *mc;\n    int j;\n\n    c->mstate.commands = zrealloc(c->mstate.commands,\n            sizeof(multiCmd)*(c->mstate.count+1));\n    mc = c->mstate.commands+c->mstate.count;\n    mc->cmd = c->cmd;\n    mc->argc = c->argc;\n    mc->argv = zmalloc(sizeof(robj*)*c->argc);\n    memcpy(mc->argv,c->argv,sizeof(robj*)*c->argc);\n    for (j = 0; j < c->argc; j++)\n        incrRefCount(mc->argv[j]);\n    c->mstate.count++;\n}\n\nvoid discardTransaction(redisClient *c) {\n    freeClientMultiState(c);\n    initClientMultiState(c);\n    c->flags &= ~(REDIS_MULTI|REDIS_DIRTY_CAS|REDIS_DIRTY_EXEC);\n    unwatchAllKeys(c);\n}\n\n/* Flag the transacation as DIRTY_EXEC so that EXEC will fail.\n * Should be called every time there is an error while queueing a command. */\nvoid flagTransaction(redisClient *c) {\n    if (c->flags & REDIS_MULTI)\n        c->flags |= REDIS_DIRTY_EXEC;\n}\n\nvoid multiCommand(redisClient *c) {\n    if (c->flags & REDIS_MULTI) {\n        addReplyError(c,\"MULTI calls can not be nested\");\n        return;\n    }\n    c->flags |= REDIS_MULTI;\n    addReply(c,shared.ok);\n}\n\nvoid discardCommand(redisClient *c) {\n    if (!(c->flags & REDIS_MULTI)) {\n        addReplyError(c,\"DISCARD without MULTI\");\n        return;\n    }\n    discardTransaction(c);\n    addReply(c,shared.ok);\n}\n\n/* Send a MULTI command to all the slaves and AOF file. Check the execCommand\n * implementation for more information. */\nvoid execCommandPropagateMulti(redisClient *c) {\n    robj *multistring = createStringObject(\"MULTI\",5);\n\n    propagate(server.multiCommand,c->db->id,&multistring,1,\n              REDIS_PROPAGATE_AOF|REDIS_PROPAGATE_REPL);\n    decrRefCount(multistring);\n}\n\nvoid execCommand(redisClient *c) {\n    int j;\n    robj **orig_argv;\n    int orig_argc;\n    struct redisCommand *orig_cmd;\n    int must_propagate = 0; /* Need to propagate MULTI/EXEC to AOF / slaves? */\n\n    if (!(c->flags & REDIS_MULTI)) {\n        addReplyError(c,\"EXEC without MULTI\");\n        return;\n    }\n\n    /* Check if we need to abort the EXEC because:\n     * 1) Some WATCHed key was touched.\n     * 2) There was a previous error while queueing commands.\n     * A failed EXEC in the first case returns a multi bulk nil object\n     * (technically it is not an error but a special behavior), while\n     * in the second an EXECABORT error is returned. */\n    if (c->flags & (REDIS_DIRTY_CAS|REDIS_DIRTY_EXEC)) {\n        addReply(c, c->flags & REDIS_DIRTY_EXEC ? shared.execaborterr :\n                                                  shared.nullmultibulk);\n        discardTransaction(c);\n        goto handle_monitor;\n    }\n\n    /* Exec all the queued commands */\n    unwatchAllKeys(c); /* Unwatch ASAP otherwise we'll waste CPU cycles */\n    orig_argv = c->argv;\n    orig_argc = c->argc;\n    orig_cmd = c->cmd;\n    addReplyMultiBulkLen(c,c->mstate.count);\n    for (j = 0; j < c->mstate.count; j++) {\n        c->argc = c->mstate.commands[j].argc;\n        c->argv = c->mstate.commands[j].argv;\n        c->cmd = c->mstate.commands[j].cmd;\n\n        /* Propagate a MULTI request once we encounter the first write op.\n         * This way we'll deliver the MULTI/..../EXEC block as a whole and\n         * both the AOF and the replication link will have the same consistency\n         * and atomicity guarantees. */\n        if (!must_propagate && !(c->cmd->flags & REDIS_CMD_READONLY)) {\n            execCommandPropagateMulti(c);\n            must_propagate = 1;\n        }\n\n        call(c,REDIS_CALL_FULL);\n\n        /* Commands may alter argc/argv, restore mstate. */\n        c->mstate.commands[j].argc = c->argc;\n        c->mstate.commands[j].argv = c->argv;\n        c->mstate.commands[j].cmd = c->cmd;\n    }\n    c->argv = orig_argv;\n    c->argc = orig_argc;\n    c->cmd = orig_cmd;\n    discardTransaction(c);\n    /* Make sure the EXEC command will be propagated as well if MULTI\n     * was already propagated. */\n    if (must_propagate) server.dirty++;\n\nhandle_monitor:\n    /* Send EXEC to clients waiting data from MONITOR. We do it here\n     * since the natural order of commands execution is actually:\n     * MUTLI, EXEC, ... commands inside transaction ...\n     * Instead EXEC is flagged as REDIS_CMD_SKIP_MONITOR in the command\n     * table, and we do it here with correct ordering. */\n    if (listLength(server.monitors) && !server.loading)\n        replicationFeedMonitors(c,server.monitors,c->db->id,c->argv,c->argc);\n}\n\n/* ===================== WATCH (CAS alike for MULTI/EXEC) ===================\n *\n * The implementation uses a per-DB hash table mapping keys to list of clients\n * WATCHing those keys, so that given a key that is going to be modified\n * we can mark all the associated clients as dirty.\n *\n * Also every client contains a list of WATCHed keys so that's possible to\n * un-watch such keys when the client is freed or when UNWATCH is called. */\n\n/* In the client->watched_keys list we need to use watchedKey structures\n * as in order to identify a key in Redis we need both the key name and the\n * DB */\ntypedef struct watchedKey {\n    robj *key;\n    redisDb *db;\n} watchedKey;\n\n/* Watch for the specified key */\nvoid watchForKey(redisClient *c, robj *key) {\n    list *clients = NULL;\n    listIter li;\n    listNode *ln;\n    watchedKey *wk;\n\n    /* Check if we are already watching for this key */\n    listRewind(c->watched_keys,&li);\n    while((ln = listNext(&li))) {\n        wk = listNodeValue(ln);\n        if (wk->db == c->db && equalStringObjects(key,wk->key))\n            return; /* Key already watched */\n    }\n    /* This key is not already watched in this DB. Let's add it */\n    clients = dictFetchValue(c->db->watched_keys,key);\n    if (!clients) {\n        clients = listCreate();\n        dictAdd(c->db->watched_keys,key,clients);\n        incrRefCount(key);\n    }\n    listAddNodeTail(clients,c);\n    /* Add the new key to the list of keys watched by this client */\n    wk = zmalloc(sizeof(*wk));\n    wk->key = key;\n    wk->db = c->db;\n    incrRefCount(key);\n    listAddNodeTail(c->watched_keys,wk);\n}\n\n/* Unwatch all the keys watched by this client. To clean the EXEC dirty\n * flag is up to the caller. */\nvoid unwatchAllKeys(redisClient *c) {\n    listIter li;\n    listNode *ln;\n\n    if (listLength(c->watched_keys) == 0) return;\n    listRewind(c->watched_keys,&li);\n    while((ln = listNext(&li))) {\n        list *clients;\n        watchedKey *wk;\n\n        /* Lookup the watched key -> clients list and remove the client\n         * from the list */\n        wk = listNodeValue(ln);\n        clients = dictFetchValue(wk->db->watched_keys, wk->key);\n        redisAssertWithInfo(c,NULL,clients != NULL);\n        listDelNode(clients,listSearchKey(clients,c));\n        /* Kill the entry at all if this was the only client */\n        if (listLength(clients) == 0)\n            dictDelete(wk->db->watched_keys, wk->key);\n        /* Remove this watched key from the client->watched list */\n        listDelNode(c->watched_keys,ln);\n        decrRefCount(wk->key);\n        zfree(wk);\n    }\n}\n\n/* \"Touch\" a key, so that if this key is being WATCHed by some client the\n * next EXEC will fail. */\nvoid touchWatchedKey(redisDb *db, robj *key) {\n    list *clients;\n    listIter li;\n    listNode *ln;\n\n    if (dictSize(db->watched_keys) == 0) return;\n    clients = dictFetchValue(db->watched_keys, key);\n    if (!clients) return;\n\n    /* Mark all the clients watching this key as REDIS_DIRTY_CAS */\n    /* Check if we are already watching for this key */\n    listRewind(clients,&li);\n    while((ln = listNext(&li))) {\n        redisClient *c = listNodeValue(ln);\n\n        c->flags |= REDIS_DIRTY_CAS;\n    }\n}\n\n/* On FLUSHDB or FLUSHALL all the watched keys that are present before the\n * flush but will be deleted as effect of the flushing operation should\n * be touched. \"dbid\" is the DB that's getting the flush. -1 if it is\n * a FLUSHALL operation (all the DBs flushed). */\nvoid touchWatchedKeysOnFlush(int dbid) {\n    listIter li1, li2;\n    listNode *ln;\n\n    /* For every client, check all the waited keys */\n    listRewind(server.clients,&li1);\n    while((ln = listNext(&li1))) {\n        redisClient *c = listNodeValue(ln);\n        listRewind(c->watched_keys,&li2);\n        while((ln = listNext(&li2))) {\n            watchedKey *wk = listNodeValue(ln);\n\n            /* For every watched key matching the specified DB, if the\n             * key exists, mark the client as dirty, as the key will be\n             * removed. */\n            if (dbid == -1 || wk->db->id == dbid) {\n                if (dictFind(wk->db->dict, wk->key->ptr) != NULL)\n                    c->flags |= REDIS_DIRTY_CAS;\n            }\n        }\n    }\n}\n\nvoid watchCommand(redisClient *c) {\n    int j;\n\n    if (c->flags & REDIS_MULTI) {\n        addReplyError(c,\"WATCH inside MULTI is not allowed\");\n        return;\n    }\n    for (j = 1; j < c->argc; j++)\n        watchForKey(c,c->argv[j]);\n    addReply(c,shared.ok);\n}\n\nvoid unwatchCommand(redisClient *c) {\n    unwatchAllKeys(c);\n    c->flags &= (~REDIS_DIRTY_CAS);\n    addReply(c,shared.ok);\n}\n"
  },
  {
    "path": "extern/deprecated/redis-2.8.21/src/networking.c",
    "content": "/*\n * Copyright (c) 2009-2012, Salvatore Sanfilippo <antirez at gmail dot com>\n * All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions are met:\n *\n *   * Redistributions of source code must retain the above copyright notice,\n *     this list of conditions and the following disclaimer.\n *   * Redistributions in binary form must reproduce the above copyright\n *     notice, this list of conditions and the following disclaimer in the\n *     documentation and/or other materials provided with the distribution.\n *   * Neither the name of Redis nor the names of its contributors may be used\n *     to endorse or promote products derived from this software without\n *     specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\"\n * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\n * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE\n * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR\n * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF\n * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS\n * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN\n * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)\n * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE\n * POSSIBILITY OF SUCH DAMAGE.\n */\n\n#include \"redis.h\"\n#include <sys/uio.h>\n#include <math.h>\n\nstatic void setProtocolError(redisClient *c, int pos);\n\n/* To evaluate the output buffer size of a client we need to get size of\n * allocated objects, however we can't used zmalloc_size() directly on sds\n * strings because of the trick they use to work (the header is before the\n * returned pointer), so we use this helper function. */\nsize_t zmalloc_size_sds(sds s) {\n    return zmalloc_size(s-sizeof(struct sdshdr));\n}\n\nvoid *dupClientReplyValue(void *o) {\n    incrRefCount((robj*)o);\n    return o;\n}\n\nint listMatchObjects(void *a, void *b) {\n    return equalStringObjects(a,b);\n}\n\nredisClient *createClient(int fd) {\n    redisClient *c = zmalloc(sizeof(redisClient));\n\n    /* passing -1 as fd it is possible to create a non connected client.\n     * This is useful since all the Redis commands needs to be executed\n     * in the context of a client. When commands are executed in other\n     * contexts (for instance a Lua script) we need a non connected client. */\n    if (fd != -1) {\n        anetNonBlock(NULL,fd);\n        anetEnableTcpNoDelay(NULL,fd);\n        if (server.tcpkeepalive)\n            anetKeepAlive(NULL,fd,server.tcpkeepalive);\n        if (aeCreateFileEvent(server.el,fd,AE_READABLE,\n            readQueryFromClient, c) == AE_ERR)\n        {\n            close(fd);\n            zfree(c);\n            return NULL;\n        }\n    }\n\n    selectDb(c,0);\n    c->id = server.next_client_id++;\n    c->fd = fd;\n    c->name = NULL;\n    c->bufpos = 0;\n    c->querybuf = sdsempty();\n    c->querybuf_peak = 0;\n    c->reqtype = 0;\n    c->argc = 0;\n    c->argv = NULL;\n    c->cmd = c->lastcmd = NULL;\n    c->multibulklen = 0;\n    c->bulklen = -1;\n    c->sentlen = 0;\n    c->flags = 0;\n    c->ctime = c->lastinteraction = server.unixtime;\n    c->authenticated = 0;\n    c->replstate = REDIS_REPL_NONE;\n    c->repl_put_online_on_ack = 0;\n    c->reploff = 0;\n    c->repl_ack_off = 0;\n    c->repl_ack_time = 0;\n    c->slave_listening_port = 0;\n    c->reply = listCreate();\n    c->reply_bytes = 0;\n    c->obuf_soft_limit_reached_time = 0;\n    listSetFreeMethod(c->reply,decrRefCountVoid);\n    listSetDupMethod(c->reply,dupClientReplyValue);\n    c->bpop.keys = dictCreate(&setDictType,NULL);\n    c->bpop.timeout = 0;\n    c->bpop.target = NULL;\n    c->watched_keys = listCreate();\n    c->pubsub_channels = dictCreate(&setDictType,NULL);\n    c->pubsub_patterns = listCreate();\n    c->peerid = NULL;\n    listSetFreeMethod(c->pubsub_patterns,decrRefCountVoid);\n    listSetMatchMethod(c->pubsub_patterns,listMatchObjects);\n    if (fd != -1) listAddNodeTail(server.clients,c);\n    initClientMultiState(c);\n    return c;\n}\n\n/* This function is called every time we are going to transmit new data\n * to the client. The behavior is the following:\n *\n * If the client should receive new data (normal clients will) the function\n * returns REDIS_OK, and make sure to install the write handler in our event\n * loop so that when the socket is writable new data gets written.\n *\n * If the client should not receive new data, because it is a fake client,\n * a master, a slave not yet online, or because the setup of the write handler\n * failed, the function returns REDIS_ERR.\n *\n * Typically gets called every time a reply is built, before adding more\n * data to the clients output buffers. If the function returns REDIS_ERR no\n * data should be appended to the output buffers. */\nint prepareClientToWrite(redisClient *c) {\n    if (c->flags & REDIS_LUA_CLIENT) return REDIS_OK;\n    if ((c->flags & REDIS_MASTER) &&\n        !(c->flags & REDIS_MASTER_FORCE_REPLY)) return REDIS_ERR;\n    if (c->fd <= 0) return REDIS_ERR; /* Fake client */\n    if (c->bufpos == 0 && listLength(c->reply) == 0 &&\n        (c->replstate == REDIS_REPL_NONE ||\n         c->replstate == REDIS_REPL_ONLINE) && !c->repl_put_online_on_ack &&\n        aeCreateFileEvent(server.el, c->fd, AE_WRITABLE,\n        sendReplyToClient, c) == AE_ERR) return REDIS_ERR;\n    return REDIS_OK;\n}\n\n/* Create a duplicate of the last object in the reply list when\n * it is not exclusively owned by the reply list. */\nrobj *dupLastObjectIfNeeded(list *reply) {\n    robj *new, *cur;\n    listNode *ln;\n    redisAssert(listLength(reply) > 0);\n    ln = listLast(reply);\n    cur = listNodeValue(ln);\n    if (cur->refcount > 1) {\n        new = dupStringObject(cur);\n        decrRefCount(cur);\n        listNodeValue(ln) = new;\n    }\n    return listNodeValue(ln);\n}\n\n/* -----------------------------------------------------------------------------\n * Low level functions to add more data to output buffers.\n * -------------------------------------------------------------------------- */\n\nint _addReplyToBuffer(redisClient *c, char *s, size_t len) {\n    size_t available = sizeof(c->buf)-c->bufpos;\n\n    if (c->flags & REDIS_CLOSE_AFTER_REPLY) return REDIS_OK;\n\n    /* If there already are entries in the reply list, we cannot\n     * add anything more to the static buffer. */\n    if (listLength(c->reply) > 0) return REDIS_ERR;\n\n    /* Check that the buffer has enough space available for this string. */\n    if (len > available) return REDIS_ERR;\n\n    memcpy(c->buf+c->bufpos,s,len);\n    c->bufpos+=len;\n    return REDIS_OK;\n}\n\nvoid _addReplyObjectToList(redisClient *c, robj *o) {\n    robj *tail;\n\n    if (c->flags & REDIS_CLOSE_AFTER_REPLY) return;\n\n    if (listLength(c->reply) == 0) {\n        incrRefCount(o);\n        listAddNodeTail(c->reply,o);\n        c->reply_bytes += zmalloc_size_sds(o->ptr);\n    } else {\n        tail = listNodeValue(listLast(c->reply));\n\n        /* Append to this object when possible. */\n        if (tail->ptr != NULL &&\n            sdslen(tail->ptr)+sdslen(o->ptr) <= REDIS_REPLY_CHUNK_BYTES)\n        {\n            c->reply_bytes -= zmalloc_size_sds(tail->ptr);\n            tail = dupLastObjectIfNeeded(c->reply);\n            tail->ptr = sdscatlen(tail->ptr,o->ptr,sdslen(o->ptr));\n            c->reply_bytes += zmalloc_size_sds(tail->ptr);\n        } else {\n            incrRefCount(o);\n            listAddNodeTail(c->reply,o);\n            c->reply_bytes += zmalloc_size_sds(o->ptr);\n        }\n    }\n    asyncCloseClientOnOutputBufferLimitReached(c);\n}\n\n/* This method takes responsibility over the sds. When it is no longer\n * needed it will be free'd, otherwise it ends up in a robj. */\nvoid _addReplySdsToList(redisClient *c, sds s) {\n    robj *tail;\n\n    if (c->flags & REDIS_CLOSE_AFTER_REPLY) {\n        sdsfree(s);\n        return;\n    }\n\n    if (listLength(c->reply) == 0) {\n        listAddNodeTail(c->reply,createObject(REDIS_STRING,s));\n        c->reply_bytes += zmalloc_size_sds(s);\n    } else {\n        tail = listNodeValue(listLast(c->reply));\n\n        /* Append to this object when possible. */\n        if (tail->ptr != NULL &&\n            sdslen(tail->ptr)+sdslen(s) <= REDIS_REPLY_CHUNK_BYTES)\n        {\n            c->reply_bytes -= zmalloc_size_sds(tail->ptr);\n            tail = dupLastObjectIfNeeded(c->reply);\n            tail->ptr = sdscatlen(tail->ptr,s,sdslen(s));\n            c->reply_bytes += zmalloc_size_sds(tail->ptr);\n            sdsfree(s);\n        } else {\n            listAddNodeTail(c->reply,createObject(REDIS_STRING,s));\n            c->reply_bytes += zmalloc_size_sds(s);\n        }\n    }\n    asyncCloseClientOnOutputBufferLimitReached(c);\n}\n\nvoid _addReplyStringToList(redisClient *c, char *s, size_t len) {\n    robj *tail;\n\n    if (c->flags & REDIS_CLOSE_AFTER_REPLY) return;\n\n    if (listLength(c->reply) == 0) {\n        robj *o = createStringObject(s,len);\n\n        listAddNodeTail(c->reply,o);\n        c->reply_bytes += zmalloc_size_sds(o->ptr);\n    } else {\n        tail = listNodeValue(listLast(c->reply));\n\n        /* Append to this object when possible. */\n        if (tail->ptr != NULL &&\n            sdslen(tail->ptr)+len <= REDIS_REPLY_CHUNK_BYTES)\n        {\n            c->reply_bytes -= zmalloc_size_sds(tail->ptr);\n            tail = dupLastObjectIfNeeded(c->reply);\n            tail->ptr = sdscatlen(tail->ptr,s,len);\n            c->reply_bytes += zmalloc_size_sds(tail->ptr);\n        } else {\n            robj *o = createStringObject(s,len);\n\n            listAddNodeTail(c->reply,o);\n            c->reply_bytes += zmalloc_size_sds(o->ptr);\n        }\n    }\n    asyncCloseClientOnOutputBufferLimitReached(c);\n}\n\n/* -----------------------------------------------------------------------------\n * Higher level functions to queue data on the client output buffer.\n * The following functions are the ones that commands implementations will call.\n * -------------------------------------------------------------------------- */\n\nvoid addReply(redisClient *c, robj *obj) {\n    if (prepareClientToWrite(c) != REDIS_OK) return;\n\n    /* This is an important place where we can avoid copy-on-write\n     * when there is a saving child running, avoiding touching the\n     * refcount field of the object if it's not needed.\n     *\n     * If the encoding is RAW and there is room in the static buffer\n     * we'll be able to send the object to the client without\n     * messing with its page. */\n    if (obj->encoding == REDIS_ENCODING_RAW) {\n        if (_addReplyToBuffer(c,obj->ptr,sdslen(obj->ptr)) != REDIS_OK)\n            _addReplyObjectToList(c,obj);\n    } else if (obj->encoding == REDIS_ENCODING_INT) {\n        /* Optimization: if there is room in the static buffer for 32 bytes\n         * (more than the max chars a 64 bit integer can take as string) we\n         * avoid decoding the object and go for the lower level approach. */\n        if (listLength(c->reply) == 0 && (sizeof(c->buf) - c->bufpos) >= 32) {\n            char buf[32];\n            int len;\n\n            len = ll2string(buf,sizeof(buf),(long)obj->ptr);\n            if (_addReplyToBuffer(c,buf,len) == REDIS_OK)\n                return;\n            /* else... continue with the normal code path, but should never\n             * happen actually since we verified there is room. */\n        }\n        obj = getDecodedObject(obj);\n        if (_addReplyToBuffer(c,obj->ptr,sdslen(obj->ptr)) != REDIS_OK)\n            _addReplyObjectToList(c,obj);\n        decrRefCount(obj);\n    } else {\n        redisPanic(\"Wrong obj->encoding in addReply()\");\n    }\n}\n\nvoid addReplySds(redisClient *c, sds s) {\n    if (prepareClientToWrite(c) != REDIS_OK) {\n        /* The caller expects the sds to be free'd. */\n        sdsfree(s);\n        return;\n    }\n    if (_addReplyToBuffer(c,s,sdslen(s)) == REDIS_OK) {\n        sdsfree(s);\n    } else {\n        /* This method free's the sds when it is no longer needed. */\n        _addReplySdsToList(c,s);\n    }\n}\n\nvoid addReplyString(redisClient *c, char *s, size_t len) {\n    if (prepareClientToWrite(c) != REDIS_OK) return;\n    if (_addReplyToBuffer(c,s,len) != REDIS_OK)\n        _addReplyStringToList(c,s,len);\n}\n\nvoid addReplyErrorLength(redisClient *c, char *s, size_t len) {\n    addReplyString(c,\"-ERR \",5);\n    addReplyString(c,s,len);\n    addReplyString(c,\"\\r\\n\",2);\n}\n\nvoid addReplyError(redisClient *c, char *err) {\n    addReplyErrorLength(c,err,strlen(err));\n}\n\nvoid addReplyErrorFormat(redisClient *c, const char *fmt, ...) {\n    size_t l, j;\n    va_list ap;\n    va_start(ap,fmt);\n    sds s = sdscatvprintf(sdsempty(),fmt,ap);\n    va_end(ap);\n    /* Make sure there are no newlines in the string, otherwise invalid protocol\n     * is emitted. */\n    l = sdslen(s);\n    for (j = 0; j < l; j++) {\n        if (s[j] == '\\r' || s[j] == '\\n') s[j] = ' ';\n    }\n    addReplyErrorLength(c,s,sdslen(s));\n    sdsfree(s);\n}\n\nvoid addReplyStatusLength(redisClient *c, char *s, size_t len) {\n    addReplyString(c,\"+\",1);\n    addReplyString(c,s,len);\n    addReplyString(c,\"\\r\\n\",2);\n}\n\nvoid addReplyStatus(redisClient *c, char *status) {\n    addReplyStatusLength(c,status,strlen(status));\n}\n\nvoid addReplyStatusFormat(redisClient *c, const char *fmt, ...) {\n    va_list ap;\n    va_start(ap,fmt);\n    sds s = sdscatvprintf(sdsempty(),fmt,ap);\n    va_end(ap);\n    addReplyStatusLength(c,s,sdslen(s));\n    sdsfree(s);\n}\n\n/* Adds an empty object to the reply list that will contain the multi bulk\n * length, which is not known when this function is called. */\nvoid *addDeferredMultiBulkLength(redisClient *c) {\n    /* Note that we install the write event here even if the object is not\n     * ready to be sent, since we are sure that before returning to the\n     * event loop setDeferredMultiBulkLength() will be called. */\n    if (prepareClientToWrite(c) != REDIS_OK) return NULL;\n    listAddNodeTail(c->reply,createObject(REDIS_STRING,NULL));\n    return listLast(c->reply);\n}\n\n/* Populate the length object and try gluing it to the next chunk. */\nvoid setDeferredMultiBulkLength(redisClient *c, void *node, long length) {\n    listNode *ln = (listNode*)node;\n    robj *len, *next;\n\n    /* Abort when *node is NULL (see addDeferredMultiBulkLength). */\n    if (node == NULL) return;\n\n    len = listNodeValue(ln);\n    len->ptr = sdscatprintf(sdsempty(),\"*%ld\\r\\n\",length);\n    c->reply_bytes += zmalloc_size_sds(len->ptr);\n    if (ln->next != NULL) {\n        next = listNodeValue(ln->next);\n\n        /* Only glue when the next node is non-NULL (an sds in this case) */\n        if (next->ptr != NULL) {\n            c->reply_bytes -= zmalloc_size_sds(len->ptr);\n            c->reply_bytes -= zmalloc_size_sds(next->ptr);\n            len->ptr = sdscatlen(len->ptr,next->ptr,sdslen(next->ptr));\n            c->reply_bytes += zmalloc_size_sds(len->ptr);\n            listDelNode(c->reply,ln->next);\n        }\n    }\n    asyncCloseClientOnOutputBufferLimitReached(c);\n}\n\n/* Add a double as a bulk reply */\nvoid addReplyDouble(redisClient *c, double d) {\n    char dbuf[128], sbuf[128];\n    int dlen, slen;\n    if (isinf(d)) {\n        /* Libc in odd systems (Hi Solaris!) will format infinite in a\n         * different way, so better to handle it in an explicit way. */\n        addReplyBulkCString(c, d > 0 ? \"inf\" : \"-inf\");\n    } else {\n        dlen = snprintf(dbuf,sizeof(dbuf),\"%.17g\",d);\n        slen = snprintf(sbuf,sizeof(sbuf),\"$%d\\r\\n%s\\r\\n\",dlen,dbuf);\n        addReplyString(c,sbuf,slen);\n    }\n}\n\n/* Add a long long as integer reply or bulk len / multi bulk count.\n * Basically this is used to output <prefix><long long><crlf>. */\nvoid addReplyLongLongWithPrefix(redisClient *c, long long ll, char prefix) {\n    char buf[128];\n    int len;\n\n    /* Things like $3\\r\\n or *2\\r\\n are emitted very often by the protocol\n     * so we have a few shared objects to use if the integer is small\n     * like it is most of the times. */\n    if (prefix == '*' && ll < REDIS_SHARED_BULKHDR_LEN) {\n        addReply(c,shared.mbulkhdr[ll]);\n        return;\n    } else if (prefix == '$' && ll < REDIS_SHARED_BULKHDR_LEN) {\n        addReply(c,shared.bulkhdr[ll]);\n        return;\n    }\n\n    buf[0] = prefix;\n    len = ll2string(buf+1,sizeof(buf)-1,ll);\n    buf[len+1] = '\\r';\n    buf[len+2] = '\\n';\n    addReplyString(c,buf,len+3);\n}\n\nvoid addReplyLongLong(redisClient *c, long long ll) {\n    if (ll == 0)\n        addReply(c,shared.czero);\n    else if (ll == 1)\n        addReply(c,shared.cone);\n    else\n        addReplyLongLongWithPrefix(c,ll,':');\n}\n\nvoid addReplyMultiBulkLen(redisClient *c, long length) {\n    if (length < REDIS_SHARED_BULKHDR_LEN)\n        addReply(c,shared.mbulkhdr[length]);\n    else\n        addReplyLongLongWithPrefix(c,length,'*');\n}\n\n/* Create the length prefix of a bulk reply, example: $2234 */\nvoid addReplyBulkLen(redisClient *c, robj *obj) {\n    size_t len;\n\n    if (obj->encoding == REDIS_ENCODING_RAW) {\n        len = sdslen(obj->ptr);\n    } else {\n        long n = (long)obj->ptr;\n\n        /* Compute how many bytes will take this integer as a radix 10 string */\n        len = 1;\n        if (n < 0) {\n            len++;\n            n = -n;\n        }\n        while((n = n/10) != 0) {\n            len++;\n        }\n    }\n\n    if (len < REDIS_SHARED_BULKHDR_LEN)\n        addReply(c,shared.bulkhdr[len]);\n    else\n        addReplyLongLongWithPrefix(c,len,'$');\n}\n\n/* Add a Redis Object as a bulk reply */\nvoid addReplyBulk(redisClient *c, robj *obj) {\n    addReplyBulkLen(c,obj);\n    addReply(c,obj);\n    addReply(c,shared.crlf);\n}\n\n/* Add a C buffer as bulk reply */\nvoid addReplyBulkCBuffer(redisClient *c, void *p, size_t len) {\n    addReplyLongLongWithPrefix(c,len,'$');\n    addReplyString(c,p,len);\n    addReply(c,shared.crlf);\n}\n\n/* Add a C nul term string as bulk reply */\nvoid addReplyBulkCString(redisClient *c, char *s) {\n    if (s == NULL) {\n        addReply(c,shared.nullbulk);\n    } else {\n        addReplyBulkCBuffer(c,s,strlen(s));\n    }\n}\n\n/* Add a long long as a bulk reply */\nvoid addReplyBulkLongLong(redisClient *c, long long ll) {\n    char buf[64];\n    int len;\n\n    len = ll2string(buf,64,ll);\n    addReplyBulkCBuffer(c,buf,len);\n}\n\n/* Copy 'src' client output buffers into 'dst' client output buffers.\n * The function takes care of freeing the old output buffers of the\n * destination client. */\nvoid copyClientOutputBuffer(redisClient *dst, redisClient *src) {\n    listRelease(dst->reply);\n    dst->reply = listDup(src->reply);\n    memcpy(dst->buf,src->buf,src->bufpos);\n    dst->bufpos = src->bufpos;\n    dst->reply_bytes = src->reply_bytes;\n}\n\n#define MAX_ACCEPTS_PER_CALL 1000\nstatic void acceptCommonHandler(int fd, int flags) {\n    redisClient *c;\n    if ((c = createClient(fd)) == NULL) {\n        redisLog(REDIS_WARNING,\n            \"Error registering fd event for the new client: %s (fd=%d)\",\n            strerror(errno),fd);\n        close(fd); /* May be already closed, just ignore errors */\n        return;\n    }\n    /* If maxclient directive is set and this is one client more... close the\n     * connection. Note that we create the client instead to check before\n     * for this condition, since now the socket is already set in non-blocking\n     * mode and we can send an error for free using the Kernel I/O */\n    if (listLength(server.clients) > server.maxclients) {\n        char *err = \"-ERR max number of clients reached\\r\\n\";\n\n        /* That's a best effort error message, don't check write errors */\n        if (write(c->fd,err,strlen(err)) == -1) {\n            /* Nothing to do, Just to avoid the warning... */\n        }\n        server.stat_rejected_conn++;\n        freeClient(c);\n        return;\n    }\n    server.stat_numconnections++;\n    c->flags |= flags;\n}\n\nvoid acceptTcpHandler(aeEventLoop *el, int fd, void *privdata, int mask) {\n    int cport, cfd, max = MAX_ACCEPTS_PER_CALL;\n    char cip[REDIS_IP_STR_LEN];\n    REDIS_NOTUSED(el);\n    REDIS_NOTUSED(mask);\n    REDIS_NOTUSED(privdata);\n\n    while(max--) {\n        cfd = anetTcpAccept(server.neterr, fd, cip, sizeof(cip), &cport);\n        if (cfd == ANET_ERR) {\n            if (errno != EWOULDBLOCK)\n                redisLog(REDIS_WARNING,\n                    \"Accepting client connection: %s\", server.neterr);\n            return;\n        }\n        redisLog(REDIS_VERBOSE,\"Accepted %s:%d\", cip, cport);\n        acceptCommonHandler(cfd,0);\n    }\n}\n\nvoid acceptUnixHandler(aeEventLoop *el, int fd, void *privdata, int mask) {\n    int cfd, max = MAX_ACCEPTS_PER_CALL;\n    REDIS_NOTUSED(el);\n    REDIS_NOTUSED(mask);\n    REDIS_NOTUSED(privdata);\n\n    while(max--) {\n        cfd = anetUnixAccept(server.neterr, fd);\n        if (cfd == ANET_ERR) {\n            if (errno != EWOULDBLOCK)\n                redisLog(REDIS_WARNING,\n                    \"Accepting client connection: %s\", server.neterr);\n            return;\n        }\n        redisLog(REDIS_VERBOSE,\"Accepted connection to %s\", server.unixsocket);\n        acceptCommonHandler(cfd,REDIS_UNIX_SOCKET);\n    }\n}\n\nstatic void freeClientArgv(redisClient *c) {\n    int j;\n    for (j = 0; j < c->argc; j++)\n        decrRefCount(c->argv[j]);\n    c->argc = 0;\n    c->cmd = NULL;\n}\n\n/* Close all the slaves connections. This is useful in chained replication\n * when we resync with our own master and want to force all our slaves to\n * resync with us as well. */\nvoid disconnectSlaves(void) {\n    while (listLength(server.slaves)) {\n        listNode *ln = listFirst(server.slaves);\n        freeClient((redisClient*)ln->value);\n    }\n}\n\n/* This function is called when the slave lose the connection with the\n * master into an unexpected way. */\nvoid replicationHandleMasterDisconnection(void) {\n    server.master = NULL;\n    server.repl_state = REDIS_REPL_CONNECT;\n    server.repl_down_since = server.unixtime;\n    /* We lost connection with our master, force our slaves to resync\n     * with us as well to load the new data set.\n     *\n     * If server.masterhost is NULL the user called SLAVEOF NO ONE so\n     * slave resync is not needed. */\n    if (server.masterhost != NULL) disconnectSlaves();\n}\n\nvoid freeClient(redisClient *c) {\n    listNode *ln;\n\n    /* If this is marked as current client unset it */\n    if (server.current_client == c) server.current_client = NULL;\n\n    /* If it is our master that's beging disconnected we should make sure\n     * to cache the state to try a partial resynchronization later.\n     *\n     * Note that before doing this we make sure that the client is not in\n     * some unexpected state, by checking its flags. */\n    if (server.master && c->flags & REDIS_MASTER) {\n        redisLog(REDIS_WARNING,\"Connection with master lost.\");\n        if (!(c->flags & (REDIS_CLOSE_AFTER_REPLY|\n                          REDIS_CLOSE_ASAP|\n                          REDIS_BLOCKED|\n                          REDIS_UNBLOCKED)))\n        {\n            replicationCacheMaster(c);\n            return;\n        }\n    }\n\n    /* Log link disconnection with slave */\n    if ((c->flags & REDIS_SLAVE) && !(c->flags & REDIS_MONITOR)) {\n        redisLog(REDIS_WARNING,\"Connection with slave %s lost.\",\n            replicationGetSlaveName(c));\n    }\n\n    /* Free the query buffer */\n    sdsfree(c->querybuf);\n    c->querybuf = NULL;\n\n    /* Deallocate structures used to block on blocking ops. */\n    if (c->flags & REDIS_BLOCKED)\n        unblockClientWaitingData(c);\n    dictRelease(c->bpop.keys);\n\n    /* UNWATCH all the keys */\n    unwatchAllKeys(c);\n    listRelease(c->watched_keys);\n\n    /* Unsubscribe from all the pubsub channels */\n    pubsubUnsubscribeAllChannels(c,0);\n    pubsubUnsubscribeAllPatterns(c,0);\n    dictRelease(c->pubsub_channels);\n    listRelease(c->pubsub_patterns);\n\n    /* Close socket, unregister events, and remove list of replies and\n     * accumulated arguments. */\n    if (c->fd != -1) {\n        aeDeleteFileEvent(server.el,c->fd,AE_READABLE);\n        aeDeleteFileEvent(server.el,c->fd,AE_WRITABLE);\n        close(c->fd);\n    }\n    listRelease(c->reply);\n    freeClientArgv(c);\n\n    /* Remove from the list of clients */\n    if (c->fd != -1) {\n        ln = listSearchKey(server.clients,c);\n        redisAssert(ln != NULL);\n        listDelNode(server.clients,ln);\n    }\n\n    /* When client was just unblocked because of a blocking operation,\n     * remove it from the list of unblocked clients. */\n    if (c->flags & REDIS_UNBLOCKED) {\n        ln = listSearchKey(server.unblocked_clients,c);\n        redisAssert(ln != NULL);\n        listDelNode(server.unblocked_clients,ln);\n    }\n\n    /* Master/slave cleanup Case 1:\n     * we lost the connection with a slave. */\n    if (c->flags & REDIS_SLAVE) {\n        if (c->replstate == REDIS_REPL_SEND_BULK) {\n            if (c->repldbfd != -1) close(c->repldbfd);\n            if (c->replpreamble) sdsfree(c->replpreamble);\n        }\n        list *l = (c->flags & REDIS_MONITOR) ? server.monitors : server.slaves;\n        ln = listSearchKey(l,c);\n        redisAssert(ln != NULL);\n        listDelNode(l,ln);\n        /* We need to remember the time when we started to have zero\n         * attached slaves, as after some time we'll free the replication\n         * backlog. */\n        if (c->flags & REDIS_SLAVE && listLength(server.slaves) == 0)\n            server.repl_no_slaves_since = server.unixtime;\n        refreshGoodSlavesCount();\n    }\n\n    /* Master/slave cleanup Case 2:\n     * we lost the connection with the master. */\n    if (c->flags & REDIS_MASTER) replicationHandleMasterDisconnection();\n\n    /* If this client was scheduled for async freeing we need to remove it\n     * from the queue. */\n    if (c->flags & REDIS_CLOSE_ASAP) {\n        ln = listSearchKey(server.clients_to_close,c);\n        redisAssert(ln != NULL);\n        listDelNode(server.clients_to_close,ln);\n    }\n\n    /* Release other dynamically allocated client structure fields,\n     * and finally release the client structure itself. */\n    if (c->name) decrRefCount(c->name);\n    zfree(c->argv);\n    freeClientMultiState(c);\n    sdsfree(c->peerid);\n    zfree(c);\n}\n\n/* Schedule a client to free it at a safe time in the serverCron() function.\n * This function is useful when we need to terminate a client but we are in\n * a context where calling freeClient() is not possible, because the client\n * should be valid for the continuation of the flow of the program. */\nvoid freeClientAsync(redisClient *c) {\n    if (c->flags & REDIS_CLOSE_ASAP || c->flags & REDIS_LUA_CLIENT) return;\n    c->flags |= REDIS_CLOSE_ASAP;\n    listAddNodeTail(server.clients_to_close,c);\n}\n\nvoid freeClientsInAsyncFreeQueue(void) {\n    while (listLength(server.clients_to_close)) {\n        listNode *ln = listFirst(server.clients_to_close);\n        redisClient *c = listNodeValue(ln);\n\n        c->flags &= ~REDIS_CLOSE_ASAP;\n        freeClient(c);\n        listDelNode(server.clients_to_close,ln);\n    }\n}\n\nvoid sendReplyToClient(aeEventLoop *el, int fd, void *privdata, int mask) {\n    redisClient *c = privdata;\n    int nwritten = 0, totwritten = 0, objlen;\n    size_t objmem;\n    robj *o;\n    REDIS_NOTUSED(el);\n    REDIS_NOTUSED(mask);\n\n    while(c->bufpos > 0 || listLength(c->reply)) {\n        if (c->bufpos > 0) {\n            nwritten = write(fd,c->buf+c->sentlen,c->bufpos-c->sentlen);\n            if (nwritten <= 0) break;\n            c->sentlen += nwritten;\n            totwritten += nwritten;\n\n            /* If the buffer was sent, set bufpos to zero to continue with\n             * the remainder of the reply. */\n            if (c->sentlen == c->bufpos) {\n                c->bufpos = 0;\n                c->sentlen = 0;\n            }\n        } else {\n            o = listNodeValue(listFirst(c->reply));\n            objlen = sdslen(o->ptr);\n            objmem = zmalloc_size_sds(o->ptr);\n\n            if (objlen == 0) {\n                listDelNode(c->reply,listFirst(c->reply));\n                continue;\n            }\n\n            nwritten = write(fd, ((char*)o->ptr)+c->sentlen,objlen-c->sentlen);\n            if (nwritten <= 0) break;\n            c->sentlen += nwritten;\n            totwritten += nwritten;\n\n            /* If we fully sent the object on head go to the next one */\n            if (c->sentlen == objlen) {\n                listDelNode(c->reply,listFirst(c->reply));\n                c->sentlen = 0;\n                c->reply_bytes -= objmem;\n            }\n        }\n        /* Note that we avoid to send more than REDIS_MAX_WRITE_PER_EVENT\n         * bytes, in a single threaded server it's a good idea to serve\n         * other clients as well, even if a very large request comes from\n         * super fast link that is always able to accept data (in real world\n         * scenario think about 'KEYS *' against the loopback interface).\n         *\n         * However if we are over the maxmemory limit we ignore that and\n         * just deliver as much data as it is possible to deliver. */\n        server.stat_net_output_bytes += totwritten;\n        if (totwritten > REDIS_MAX_WRITE_PER_EVENT &&\n            (server.maxmemory == 0 ||\n             zmalloc_used_memory() < server.maxmemory)) break;\n    }\n    if (nwritten == -1) {\n        if (errno == EAGAIN) {\n            nwritten = 0;\n        } else {\n            redisLog(REDIS_VERBOSE,\n                \"Error writing to client: %s\", strerror(errno));\n            freeClient(c);\n            return;\n        }\n    }\n    if (totwritten > 0) {\n        /* For clients representing masters we don't count sending data\n         * as an interaction, since we always send REPLCONF ACK commands\n         * that take some time to just fill the socket output buffer.\n         * We just rely on data / pings received for timeout detection. */\n        if (!(c->flags & REDIS_MASTER)) c->lastinteraction = server.unixtime;\n    }\n    if (c->bufpos == 0 && listLength(c->reply) == 0) {\n        c->sentlen = 0;\n        aeDeleteFileEvent(server.el,c->fd,AE_WRITABLE);\n\n        /* Close connection after entire reply has been sent. */\n        if (c->flags & REDIS_CLOSE_AFTER_REPLY) freeClient(c);\n    }\n}\n\n/* resetClient prepare the client to process the next command */\nvoid resetClient(redisClient *c) {\n    freeClientArgv(c);\n    c->reqtype = 0;\n    c->multibulklen = 0;\n    c->bulklen = -1;\n    /* We clear the ASKING flag as well if we are not inside a MULTI. */\n    if (!(c->flags & REDIS_MULTI)) c->flags &= (~REDIS_ASKING);\n}\n\nint processInlineBuffer(redisClient *c) {\n    char *newline;\n    int argc, j;\n    sds *argv, aux;\n    size_t querylen;\n\n    /* Search for end of line */\n    newline = strchr(c->querybuf,'\\n');\n\n    /* Nothing to do without a \\r\\n */\n    if (newline == NULL) {\n        if (sdslen(c->querybuf) > REDIS_INLINE_MAX_SIZE) {\n            addReplyError(c,\"Protocol error: too big inline request\");\n            setProtocolError(c,0);\n        }\n        return REDIS_ERR;\n    }\n\n    /* Handle the \\r\\n case. */\n    if (newline && newline != c->querybuf && *(newline-1) == '\\r')\n        newline--;\n\n    /* Split the input buffer up to the \\r\\n */\n    querylen = newline-(c->querybuf);\n    aux = sdsnewlen(c->querybuf,querylen);\n    argv = sdssplitargs(aux,&argc);\n    sdsfree(aux);\n    if (argv == NULL) {\n        addReplyError(c,\"Protocol error: unbalanced quotes in request\");\n        setProtocolError(c,0);\n        return REDIS_ERR;\n    }\n\n    /* Newline from slaves can be used to refresh the last ACK time.\n     * This is useful for a slave to ping back while loading a big\n     * RDB file. */\n    if (querylen == 0 && c->flags & REDIS_SLAVE)\n        c->repl_ack_time = server.unixtime;\n\n    /* Leave data after the first line of the query in the buffer */\n    sdsrange(c->querybuf,querylen+2,-1);\n\n    /* Setup argv array on client structure */\n    if (argc) {\n        if (c->argv) zfree(c->argv);\n        c->argv = zmalloc(sizeof(robj*)*argc);\n    }\n\n    /* Create redis objects for all arguments. */\n    for (c->argc = 0, j = 0; j < argc; j++) {\n        if (sdslen(argv[j])) {\n            c->argv[c->argc] = createObject(REDIS_STRING,argv[j]);\n            c->argc++;\n        } else {\n            sdsfree(argv[j]);\n        }\n    }\n    zfree(argv);\n    return REDIS_OK;\n}\n\n/* Helper function. Trims query buffer to make the function that processes\n * multi bulk requests idempotent. */\nstatic void setProtocolError(redisClient *c, int pos) {\n    if (server.verbosity <= REDIS_VERBOSE) {\n        sds client = catClientInfoString(sdsempty(),c);\n        redisLog(REDIS_VERBOSE,\n            \"Protocol error from client: %s\", client);\n        sdsfree(client);\n    }\n    c->flags |= REDIS_CLOSE_AFTER_REPLY;\n    sdsrange(c->querybuf,pos,-1);\n}\n\nint processMultibulkBuffer(redisClient *c) {\n    char *newline = NULL;\n    int pos = 0, ok;\n    long long ll;\n\n    if (c->multibulklen == 0) {\n        /* The client should have been reset */\n        redisAssertWithInfo(c,NULL,c->argc == 0);\n\n        /* Multi bulk length cannot be read without a \\r\\n */\n        newline = strchr(c->querybuf,'\\r');\n        if (newline == NULL) {\n            if (sdslen(c->querybuf) > REDIS_INLINE_MAX_SIZE) {\n                addReplyError(c,\"Protocol error: too big mbulk count string\");\n                setProtocolError(c,0);\n            }\n            return REDIS_ERR;\n        }\n\n        /* Buffer should also contain \\n */\n        if (newline-(c->querybuf) > ((signed)sdslen(c->querybuf)-2))\n            return REDIS_ERR;\n\n        /* We know for sure there is a whole line since newline != NULL,\n         * so go ahead and find out the multi bulk length. */\n        redisAssertWithInfo(c,NULL,c->querybuf[0] == '*');\n        ok = string2ll(c->querybuf+1,newline-(c->querybuf+1),&ll);\n        if (!ok || ll > 1024*1024) {\n            addReplyError(c,\"Protocol error: invalid multibulk length\");\n            setProtocolError(c,pos);\n            return REDIS_ERR;\n        }\n\n        pos = (newline-c->querybuf)+2;\n        if (ll <= 0) {\n            sdsrange(c->querybuf,pos,-1);\n            return REDIS_OK;\n        }\n\n        c->multibulklen = ll;\n\n        /* Setup argv array on client structure */\n        if (c->argv) zfree(c->argv);\n        c->argv = zmalloc(sizeof(robj*)*c->multibulklen);\n    }\n\n    redisAssertWithInfo(c,NULL,c->multibulklen > 0);\n    while(c->multibulklen) {\n        /* Read bulk length if unknown */\n        if (c->bulklen == -1) {\n            newline = strchr(c->querybuf+pos,'\\r');\n            if (newline == NULL) {\n                if (sdslen(c->querybuf) > REDIS_INLINE_MAX_SIZE) {\n                    addReplyError(c,\n                        \"Protocol error: too big bulk count string\");\n                    setProtocolError(c,0);\n                    return REDIS_ERR;\n                }\n                break;\n            }\n\n            /* Buffer should also contain \\n */\n            if (newline-(c->querybuf) > ((signed)sdslen(c->querybuf)-2))\n                break;\n\n            if (c->querybuf[pos] != '$') {\n                addReplyErrorFormat(c,\n                    \"Protocol error: expected '$', got '%c'\",\n                    c->querybuf[pos]);\n                setProtocolError(c,pos);\n                return REDIS_ERR;\n            }\n\n            ok = string2ll(c->querybuf+pos+1,newline-(c->querybuf+pos+1),&ll);\n            if (!ok || ll < 0 || ll > 512*1024*1024) {\n                addReplyError(c,\"Protocol error: invalid bulk length\");\n                setProtocolError(c,pos);\n                return REDIS_ERR;\n            }\n\n            pos += newline-(c->querybuf+pos)+2;\n            if (ll >= REDIS_MBULK_BIG_ARG) {\n                size_t qblen;\n\n                /* If we are going to read a large object from network\n                 * try to make it likely that it will start at c->querybuf\n                 * boundary so that we can optimize object creation\n                 * avoiding a large copy of data. */\n                sdsrange(c->querybuf,pos,-1);\n                pos = 0;\n                qblen = sdslen(c->querybuf);\n                /* Hint the sds library about the amount of bytes this string is\n                 * going to contain. */\n                if (qblen < (size_t)ll+2)\n                    c->querybuf = sdsMakeRoomFor(c->querybuf,ll+2-qblen);\n            }\n            c->bulklen = ll;\n        }\n\n        /* Read bulk argument */\n        if (sdslen(c->querybuf)-pos < (unsigned)(c->bulklen+2)) {\n            /* Not enough data (+2 == trailing \\r\\n) */\n            break;\n        } else {\n            /* Optimization: if the buffer contains JUST our bulk element\n             * instead of creating a new object by *copying* the sds we\n             * just use the current sds string. */\n            if (pos == 0 &&\n                c->bulklen >= REDIS_MBULK_BIG_ARG &&\n                (signed) sdslen(c->querybuf) == c->bulklen+2)\n            {\n                c->argv[c->argc++] = createObject(REDIS_STRING,c->querybuf);\n                sdsIncrLen(c->querybuf,-2); /* remove CRLF */\n                c->querybuf = sdsempty();\n                /* Assume that if we saw a fat argument we'll see another one\n                 * likely... */\n                c->querybuf = sdsMakeRoomFor(c->querybuf,c->bulklen+2);\n                pos = 0;\n            } else {\n                c->argv[c->argc++] =\n                    createStringObject(c->querybuf+pos,c->bulklen);\n                pos += c->bulklen+2;\n            }\n            c->bulklen = -1;\n            c->multibulklen--;\n        }\n    }\n\n    /* Trim to pos */\n    if (pos) sdsrange(c->querybuf,pos,-1);\n\n    /* We're done when c->multibulk == 0 */\n    if (c->multibulklen == 0) return REDIS_OK;\n\n    /* Still not read to process the command */\n    return REDIS_ERR;\n}\n\nvoid processInputBuffer(redisClient *c) {\n    /* Keep processing while there is something in the input buffer */\n    while(sdslen(c->querybuf)) {\n        /* Immediately abort if the client is in the middle of something. */\n        if (c->flags & REDIS_BLOCKED) return;\n\n        /* REDIS_CLOSE_AFTER_REPLY closes the connection once the reply is\n         * written to the client. Make sure to not let the reply grow after\n         * this flag has been set (i.e. don't process more commands). */\n        if (c->flags & REDIS_CLOSE_AFTER_REPLY) return;\n\n        /* Determine request type when unknown. */\n        if (!c->reqtype) {\n            if (c->querybuf[0] == '*') {\n                c->reqtype = REDIS_REQ_MULTIBULK;\n            } else {\n                c->reqtype = REDIS_REQ_INLINE;\n            }\n        }\n\n        if (c->reqtype == REDIS_REQ_INLINE) {\n            if (processInlineBuffer(c) != REDIS_OK) break;\n        } else if (c->reqtype == REDIS_REQ_MULTIBULK) {\n            if (processMultibulkBuffer(c) != REDIS_OK) break;\n        } else {\n            redisPanic(\"Unknown request type\");\n        }\n\n        /* Multibulk processing could see a <= 0 length. */\n        if (c->argc == 0) {\n            resetClient(c);\n        } else {\n            /* Only reset the client when the command was executed. */\n            if (processCommand(c) == REDIS_OK)\n                resetClient(c);\n        }\n    }\n}\n\nvoid readQueryFromClient(aeEventLoop *el, int fd, void *privdata, int mask) {\n    redisClient *c = (redisClient*) privdata;\n    int nread, readlen;\n    size_t qblen;\n    REDIS_NOTUSED(el);\n    REDIS_NOTUSED(mask);\n\n    server.current_client = c;\n    readlen = REDIS_IOBUF_LEN;\n    /* If this is a multi bulk request, and we are processing a bulk reply\n     * that is large enough, try to maximize the probability that the query\n     * buffer contains exactly the SDS string representing the object, even\n     * at the risk of requiring more read(2) calls. This way the function\n     * processMultiBulkBuffer() can avoid copying buffers to create the\n     * Redis Object representing the argument. */\n    if (c->reqtype == REDIS_REQ_MULTIBULK && c->multibulklen && c->bulklen != -1\n        && c->bulklen >= REDIS_MBULK_BIG_ARG)\n    {\n        int remaining = (unsigned)(c->bulklen+2)-sdslen(c->querybuf);\n\n        if (remaining < readlen) readlen = remaining;\n    }\n\n    qblen = sdslen(c->querybuf);\n    if (c->querybuf_peak < qblen) c->querybuf_peak = qblen;\n    c->querybuf = sdsMakeRoomFor(c->querybuf, readlen);\n    nread = read(fd, c->querybuf+qblen, readlen);\n    if (nread == -1) {\n        if (errno == EAGAIN) {\n            nread = 0;\n        } else {\n            redisLog(REDIS_VERBOSE, \"Reading from client: %s\",strerror(errno));\n            freeClient(c);\n            return;\n        }\n    } else if (nread == 0) {\n        redisLog(REDIS_VERBOSE, \"Client closed connection\");\n        freeClient(c);\n        return;\n    }\n    if (nread) {\n        sdsIncrLen(c->querybuf,nread);\n        c->lastinteraction = server.unixtime;\n        if (c->flags & REDIS_MASTER) c->reploff += nread;\n        server.stat_net_input_bytes += nread;\n    } else {\n        server.current_client = NULL;\n        return;\n    }\n    if (sdslen(c->querybuf) > server.client_max_querybuf_len) {\n        sds ci = catClientInfoString(sdsempty(),c), bytes = sdsempty();\n\n        bytes = sdscatrepr(bytes,c->querybuf,64);\n        redisLog(REDIS_WARNING,\"Closing client that reached max query buffer length: %s (qbuf initial bytes: %s)\", ci, bytes);\n        sdsfree(ci);\n        sdsfree(bytes);\n        freeClient(c);\n        return;\n    }\n    processInputBuffer(c);\n    server.current_client = NULL;\n}\n\nvoid getClientsMaxBuffers(unsigned long *longest_output_list,\n                          unsigned long *biggest_input_buffer) {\n    redisClient *c;\n    listNode *ln;\n    listIter li;\n    unsigned long lol = 0, bib = 0;\n\n    listRewind(server.clients,&li);\n    while ((ln = listNext(&li)) != NULL) {\n        c = listNodeValue(ln);\n\n        if (listLength(c->reply) > lol) lol = listLength(c->reply);\n        if (sdslen(c->querybuf) > bib) bib = sdslen(c->querybuf);\n    }\n    *longest_output_list = lol;\n    *biggest_input_buffer = bib;\n}\n\n/* This is a helper function for genClientPeerId().\n * It writes the specified ip/port to \"peerid\" as a null termiated string\n * in the form ip:port if ip does not contain \":\" itself, otherwise\n * [ip]:port format is used (for IPv6 addresses basically). */\nvoid formatPeerId(char *peerid, size_t peerid_len, char *ip, int port) {\n    if (strchr(ip,':'))\n        snprintf(peerid,peerid_len,\"[%s]:%d\",ip,port);\n    else\n        snprintf(peerid,peerid_len,\"%s:%d\",ip,port);\n}\n\n/* A Redis \"Peer ID\" is a colon separated ip:port pair.\n * For IPv4 it's in the form x.y.z.k:port, example: \"127.0.0.1:1234\".\n * For IPv6 addresses we use [] around the IP part, like in \"[::1]:1234\".\n * For Unix sockets we use path:0, like in \"/tmp/redis:0\".\n *\n * A Peer ID always fits inside a buffer of REDIS_PEER_ID_LEN bytes, including\n * the null term.\n *\n * The function returns REDIS_OK on succcess, and REDIS_ERR on failure.\n *\n * On failure the function still populates 'peerid' with the \"?:0\" string\n * in case you want to relax error checking or need to display something\n * anyway (see anetPeerToString implementation for more info). */\nint genClientPeerId(redisClient *client, char *peerid, size_t peerid_len) {\n    char ip[REDIS_IP_STR_LEN];\n    int port;\n\n    if (client->flags & REDIS_UNIX_SOCKET) {\n        /* Unix socket client. */\n        snprintf(peerid,peerid_len,\"%s:0\",server.unixsocket);\n        return REDIS_OK;\n    } else {\n        /* TCP client. */\n        int retval = anetPeerToString(client->fd,ip,sizeof(ip),&port);\n        formatPeerId(peerid,peerid_len,ip,port);\n        return (retval == -1) ? REDIS_ERR : REDIS_OK;\n    }\n}\n\n/* This function returns the client peer id, by creating and caching it\n * if client->peerid is NULL, otherwise returning the cached value.\n * The Peer ID never changes during the life of the client, however it\n * is expensive to compute. */\nchar *getClientPeerId(redisClient *c) {\n    char peerid[REDIS_PEER_ID_LEN];\n\n    if (c->peerid == NULL) {\n        genClientPeerId(c,peerid,sizeof(peerid));\n        c->peerid = sdsnew(peerid);\n    }\n    return c->peerid;\n}\n\n/* Concatenate a string representing the state of a client in an human\n * readable format, into the sds string 's'. */\nsds catClientInfoString(sds s, redisClient *client) {\n    char flags[16], events[3], *p;\n    int emask;\n\n    p = flags;\n    if (client->flags & REDIS_SLAVE) {\n        if (client->flags & REDIS_MONITOR)\n            *p++ = 'O';\n        else\n            *p++ = 'S';\n    }\n    if (client->flags & REDIS_MASTER) *p++ = 'M';\n    if (client->flags & REDIS_MULTI) *p++ = 'x';\n    if (client->flags & REDIS_BLOCKED) *p++ = 'b';\n    if (client->flags & REDIS_DIRTY_CAS) *p++ = 'd';\n    if (client->flags & REDIS_CLOSE_AFTER_REPLY) *p++ = 'c';\n    if (client->flags & REDIS_UNBLOCKED) *p++ = 'u';\n    if (client->flags & REDIS_CLOSE_ASAP) *p++ = 'A';\n    if (client->flags & REDIS_UNIX_SOCKET) *p++ = 'U';\n    if (p == flags) *p++ = 'N';\n    *p++ = '\\0';\n\n    emask = client->fd == -1 ? 0 : aeGetFileEvents(server.el,client->fd);\n    p = events;\n    if (emask & AE_READABLE) *p++ = 'r';\n    if (emask & AE_WRITABLE) *p++ = 'w';\n    *p = '\\0';\n    return sdscatfmt(s,\n        \"id=%U addr=%s fd=%i name=%s age=%I idle=%I flags=%s db=%i sub=%i psub=%i multi=%i qbuf=%U qbuf-free=%U obl=%U oll=%U omem=%U events=%s cmd=%s\",\n        (unsigned long long) client->id,\n        getClientPeerId(client),\n        client->fd,\n        client->name ? (char*)client->name->ptr : \"\",\n        (long long)(server.unixtime - client->ctime),\n        (long long)(server.unixtime - client->lastinteraction),\n        flags,\n        client->db->id,\n        (int) dictSize(client->pubsub_channels),\n        (int) listLength(client->pubsub_patterns),\n        (client->flags & REDIS_MULTI) ? client->mstate.count : -1,\n        (unsigned long long) sdslen(client->querybuf),\n        (unsigned long long) sdsavail(client->querybuf),\n        (unsigned long long) client->bufpos,\n        (unsigned long long) listLength(client->reply),\n        (unsigned long long) getClientOutputBufferMemoryUsage(client),\n        events,\n        client->lastcmd ? client->lastcmd->name : \"NULL\");\n}\n\nsds getAllClientsInfoString(void) {\n    listNode *ln;\n    listIter li;\n    redisClient *client;\n    sds o = sdsempty();\n\n    o = sdsMakeRoomFor(o,200*listLength(server.clients));\n    listRewind(server.clients,&li);\n    while ((ln = listNext(&li)) != NULL) {\n        client = listNodeValue(ln);\n        o = catClientInfoString(o,client);\n        o = sdscatlen(o,\"\\n\",1);\n    }\n    return o;\n}\n\nvoid clientCommand(redisClient *c) {\n    listNode *ln;\n    listIter li;\n    redisClient *client;\n\n    if (!strcasecmp(c->argv[1]->ptr,\"list\") && c->argc == 2) {\n        /* CLIENT LIST */\n        sds o = getAllClientsInfoString();\n        addReplyBulkCBuffer(c,o,sdslen(o));\n        sdsfree(o);\n    } else if (!strcasecmp(c->argv[1]->ptr,\"kill\")) {\n        /* CLIENT KILL <ip:port>\n         * CLIENT KILL <option> [value] ... <option> [value] */\n        char *addr = NULL;\n        int type = -1;\n        uint64_t id = 0;\n        int skipme = 1;\n        int killed = 0, close_this_client = 0;\n\n        if (c->argc == 3) {\n            /* Old style syntax: CLIENT KILL <addr> */\n            addr = c->argv[2]->ptr;\n            skipme = 0; /* With the old form, you can kill yourself. */\n        } else if (c->argc > 3) {\n            int i = 2; /* Next option index. */\n\n            /* New style syntax: parse options. */\n            while(i < c->argc) {\n                int moreargs = c->argc > i+1;\n\n                if (!strcasecmp(c->argv[i]->ptr,\"id\") && moreargs) {\n                    long long tmp;\n\n                    if (getLongLongFromObjectOrReply(c,c->argv[i+1],&tmp,NULL)\n                        != REDIS_OK) return;\n                    id = tmp;\n                } else if (!strcasecmp(c->argv[i]->ptr,\"type\") && moreargs) {\n                    type = getClientTypeByName(c->argv[i+1]->ptr);\n                    if (type == -1) {\n                        addReplyErrorFormat(c,\"Unknown client type '%s'\",\n                            (char*) c->argv[i+1]->ptr);\n                        return;\n                    }\n                } else if (!strcasecmp(c->argv[i]->ptr,\"addr\") && moreargs) {\n                    addr = c->argv[i+1]->ptr;\n                } else if (!strcasecmp(c->argv[i]->ptr,\"skipme\") && moreargs) {\n                    if (!strcasecmp(c->argv[i+1]->ptr,\"yes\")) {\n                        skipme = 1;\n                    } else if (!strcasecmp(c->argv[i+1]->ptr,\"no\")) {\n                        skipme = 0;\n                    } else {\n                        addReply(c,shared.syntaxerr);\n                        return;\n                    }\n                } else {\n                    addReply(c,shared.syntaxerr);\n                    return;\n                }\n                i += 2;\n            }\n        } else {\n            addReply(c,shared.syntaxerr);\n            return;\n        }\n\n        /* Iterate clients killing all the matching clients. */\n        listRewind(server.clients,&li);\n        while ((ln = listNext(&li)) != NULL) {\n            client = listNodeValue(ln);\n            if (addr && strcmp(getClientPeerId(client),addr) != 0) continue;\n            if (type != -1 &&\n                (client->flags & REDIS_MASTER ||\n                 getClientType(client) != type)) continue;\n            if (id != 0 && client->id != id) continue;\n            if (c == client && skipme) continue;\n\n            /* Kill it. */\n            if (c == client) {\n                close_this_client = 1;\n            } else {\n                freeClient(client);\n            }\n            killed++;\n        }\n\n        /* Reply according to old/new format. */\n        if (c->argc == 3) {\n            if (killed == 0)\n                addReplyError(c,\"No such client\");\n            else\n                addReply(c,shared.ok);\n        } else {\n            addReplyLongLong(c,killed);\n        }\n\n        /* If this client has to be closed, flag it as CLOSE_AFTER_REPLY\n         * only after we queued the reply to its output buffers. */\n        if (close_this_client) c->flags |= REDIS_CLOSE_AFTER_REPLY;\n    } else if (!strcasecmp(c->argv[1]->ptr,\"setname\") && c->argc == 3) {\n        int j, len = sdslen(c->argv[2]->ptr);\n        char *p = c->argv[2]->ptr;\n\n        /* Setting the client name to an empty string actually removes\n         * the current name. */\n        if (len == 0) {\n            if (c->name) decrRefCount(c->name);\n            c->name = NULL;\n            addReply(c,shared.ok);\n            return;\n        }\n\n        /* Otherwise check if the charset is ok. We need to do this otherwise\n         * CLIENT LIST format will break. You should always be able to\n         * split by space to get the different fields. */\n        for (j = 0; j < len; j++) {\n            if (p[j] < '!' || p[j] > '~') { /* ASCII is assumed. */\n                addReplyError(c,\n                    \"Client names cannot contain spaces, \"\n                    \"newlines or special characters.\");\n                return;\n            }\n        }\n        if (c->name) decrRefCount(c->name);\n        c->name = c->argv[2];\n        incrRefCount(c->name);\n        addReply(c,shared.ok);\n    } else if (!strcasecmp(c->argv[1]->ptr,\"getname\") && c->argc == 2) {\n        if (c->name)\n            addReplyBulk(c,c->name);\n        else\n            addReply(c,shared.nullbulk);\n    } else {\n        addReplyError(c, \"Syntax error, try CLIENT (LIST | KILL ip:port | GETNAME | SETNAME connection-name)\");\n    }\n}\n\n/* Rewrite the command vector of the client. All the new objects ref count\n * is incremented. The old command vector is freed, and the old objects\n * ref count is decremented. */\nvoid rewriteClientCommandVector(redisClient *c, int argc, ...) {\n    va_list ap;\n    int j;\n    robj **argv; /* The new argument vector */\n\n    argv = zmalloc(sizeof(robj*)*argc);\n    va_start(ap,argc);\n    for (j = 0; j < argc; j++) {\n        robj *a;\n\n        a = va_arg(ap, robj*);\n        argv[j] = a;\n        incrRefCount(a);\n    }\n    /* We free the objects in the original vector at the end, so we are\n     * sure that if the same objects are reused in the new vector the\n     * refcount gets incremented before it gets decremented. */\n    for (j = 0; j < c->argc; j++) decrRefCount(c->argv[j]);\n    zfree(c->argv);\n    /* Replace argv and argc with our new versions. */\n    c->argv = argv;\n    c->argc = argc;\n    c->cmd = lookupCommandOrOriginal(c->argv[0]->ptr);\n    redisAssertWithInfo(c,NULL,c->cmd != NULL);\n    va_end(ap);\n}\n\n/* Rewrite a single item in the command vector.\n * The new val ref count is incremented, and the old decremented. */\nvoid rewriteClientCommandArgument(redisClient *c, int i, robj *newval) {\n    robj *oldval;\n\n    redisAssertWithInfo(c,NULL,i < c->argc);\n    oldval = c->argv[i];\n    c->argv[i] = newval;\n    incrRefCount(newval);\n    decrRefCount(oldval);\n\n    /* If this is the command name make sure to fix c->cmd. */\n    if (i == 0) {\n        c->cmd = lookupCommandOrOriginal(c->argv[0]->ptr);\n        redisAssertWithInfo(c,NULL,c->cmd != NULL);\n    }\n}\n\n/* This function returns the number of bytes that Redis is virtually\n * using to store the reply still not read by the client.\n * It is \"virtual\" since the reply output list may contain objects that\n * are shared and are not really using additional memory.\n *\n * The function returns the total sum of the length of all the objects\n * stored in the output list, plus the memory used to allocate every\n * list node. The static reply buffer is not taken into account since it\n * is allocated anyway.\n *\n * Note: this function is very fast so can be called as many time as\n * the caller wishes. The main usage of this function currently is\n * enforcing the client output length limits. */\nunsigned long getClientOutputBufferMemoryUsage(redisClient *c) {\n    unsigned long list_item_size = sizeof(listNode)+sizeof(robj);\n\n    return c->reply_bytes + (list_item_size*listLength(c->reply));\n}\n\n/* Get the class of a client, used in order to enforce limits to different\n * classes of clients.\n *\n * The function will return one of the following:\n * REDIS_CLIENT_TYPE_NORMAL -> Normal client\n * REDIS_CLIENT_TYPE_SLAVE  -> Slave or client executing MONITOR command\n * REDIS_CLIENT_TYPE_PUBSUB -> Client subscribed to Pub/Sub channels\n */\nint getClientType(redisClient *c) {\n    if ((c->flags & REDIS_SLAVE) && !(c->flags & REDIS_MONITOR))\n        return REDIS_CLIENT_TYPE_SLAVE;\n    if (c->flags & REDIS_PUBSUB)\n        return REDIS_CLIENT_TYPE_PUBSUB;\n    return REDIS_CLIENT_TYPE_NORMAL;\n}\n\nint getClientTypeByName(char *name) {\n    if (!strcasecmp(name,\"normal\")) return REDIS_CLIENT_TYPE_NORMAL;\n    else if (!strcasecmp(name,\"slave\")) return REDIS_CLIENT_TYPE_SLAVE;\n    else if (!strcasecmp(name,\"pubsub\")) return REDIS_CLIENT_TYPE_PUBSUB;\n    else return -1;\n}\n\nchar *getClientTypeName(int class) {\n    switch(class) {\n    case REDIS_CLIENT_TYPE_NORMAL: return \"normal\";\n    case REDIS_CLIENT_TYPE_SLAVE:  return \"slave\";\n    case REDIS_CLIENT_TYPE_PUBSUB: return \"pubsub\";\n    default:                       return NULL;\n    }\n}\n\n/* The function checks if the client reached output buffer soft or hard\n * limit, and also update the state needed to check the soft limit as\n * a side effect.\n *\n * Return value: non-zero if the client reached the soft or the hard limit.\n *               Otherwise zero is returned. */\nint checkClientOutputBufferLimits(redisClient *c) {\n    int soft = 0, hard = 0, class;\n    unsigned long used_mem = getClientOutputBufferMemoryUsage(c);\n\n    class = getClientType(c);\n    if (server.client_obuf_limits[class].hard_limit_bytes &&\n        used_mem >= server.client_obuf_limits[class].hard_limit_bytes)\n        hard = 1;\n    if (server.client_obuf_limits[class].soft_limit_bytes &&\n        used_mem >= server.client_obuf_limits[class].soft_limit_bytes)\n        soft = 1;\n\n    /* We need to check if the soft limit is reached continuously for the\n     * specified amount of seconds. */\n    if (soft) {\n        if (c->obuf_soft_limit_reached_time == 0) {\n            c->obuf_soft_limit_reached_time = server.unixtime;\n            soft = 0; /* First time we see the soft limit reached */\n        } else {\n            time_t elapsed = server.unixtime - c->obuf_soft_limit_reached_time;\n\n            if (elapsed <=\n                server.client_obuf_limits[class].soft_limit_seconds) {\n                soft = 0; /* The client still did not reached the max number of\n                             seconds for the soft limit to be considered\n                             reached. */\n            }\n        }\n    } else {\n        c->obuf_soft_limit_reached_time = 0;\n    }\n    return soft || hard;\n}\n\n/* Asynchronously close a client if soft or hard limit is reached on the\n * output buffer size. The caller can check if the client will be closed\n * checking if the client REDIS_CLOSE_ASAP flag is set.\n *\n * Note: we need to close the client asynchronously because this function is\n * called from contexts where the client can't be freed safely, i.e. from the\n * lower level functions pushing data inside the client output buffers. */\nvoid asyncCloseClientOnOutputBufferLimitReached(redisClient *c) {\n    redisAssert(c->reply_bytes < ULONG_MAX-(1024*64));\n    if (c->reply_bytes == 0 || c->flags & REDIS_CLOSE_ASAP) return;\n    if (checkClientOutputBufferLimits(c)) {\n        sds client = catClientInfoString(sdsempty(),c);\n\n        freeClientAsync(c);\n        redisLog(REDIS_WARNING,\"Client %s scheduled to be closed ASAP for overcoming of output buffer limits.\", client);\n        sdsfree(client);\n    }\n}\n\n/* Helper function used by freeMemoryIfNeeded() in order to flush slaves\n * output buffers without returning control to the event loop. */\nvoid flushSlavesOutputBuffers(void) {\n    listIter li;\n    listNode *ln;\n\n    listRewind(server.slaves,&li);\n    while((ln = listNext(&li))) {\n        redisClient *slave = listNodeValue(ln);\n        int events;\n\n        events = aeGetFileEvents(server.el,slave->fd);\n        if (events & AE_WRITABLE &&\n            slave->replstate == REDIS_REPL_ONLINE &&\n            listLength(slave->reply))\n        {\n            sendReplyToClient(server.el,slave->fd,slave,0);\n        }\n    }\n}\n\n/* This function is called by Redis in order to process a few events from\n * time to time while blocked into some not interruptible operation.\n * This allows to reply to clients with the -LOADING error while loading the\n * data set at startup or after a full resynchronization with the master\n * and so forth.\n *\n * It calls the event loop in order to process a few events. Specifically we\n * try to call the event loop for times as long as we receive acknowledge that\n * some event was processed, in order to go forward with the accept, read,\n * write, close sequence needed to serve a client.\n *\n * The function returns the total number of events processed. */\nint processEventsWhileBlocked(void) {\n    int iterations = 4; /* See the function top-comment. */\n    int count = 0;\n    while (iterations--) {\n        int events = aeProcessEvents(server.el, AE_FILE_EVENTS|AE_DONT_WAIT);\n        if (!events) break;\n        count += events;\n    }\n    return count;\n}\n"
  },
  {
    "path": "extern/deprecated/redis-2.8.21/src/notify.c",
    "content": "/*\n * Copyright (c) 2013, Salvatore Sanfilippo <antirez at gmail dot com>\n * All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions are met:\n *\n *   * Redistributions of source code must retain the above copyright notice,\n *     this list of conditions and the following disclaimer.\n *   * Redistributions in binary form must reproduce the above copyright\n *     notice, this list of conditions and the following disclaimer in the\n *     documentation and/or other materials provided with the distribution.\n *   * Neither the name of Redis nor the names of its contributors may be used\n *     to endorse or promote products derived from this software without\n *     specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\"\n * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\n * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE\n * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR\n * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF\n * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS\n * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN\n * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)\n * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE\n * POSSIBILITY OF SUCH DAMAGE.\n */\n\n#include \"redis.h\"\n\n/* This file implements keyspace events notification via Pub/Sub ad\n * described at http://redis.io/topics/keyspace-events. */\n\n/* Turn a string representing notification classes into an integer\n * representing notification classes flags xored.\n *\n * The function returns -1 if the input contains characters not mapping to\n * any class. */\nint keyspaceEventsStringToFlags(char *classes) {\n    char *p = classes;\n    int c, flags = 0;\n\n    while((c = *p++) != '\\0') {\n        switch(c) {\n        case 'A': flags |= REDIS_NOTIFY_ALL; break;\n        case 'g': flags |= REDIS_NOTIFY_GENERIC; break;\n        case '$': flags |= REDIS_NOTIFY_STRING; break;\n        case 'l': flags |= REDIS_NOTIFY_LIST; break;\n        case 's': flags |= REDIS_NOTIFY_SET; break;\n        case 'h': flags |= REDIS_NOTIFY_HASH; break;\n        case 'z': flags |= REDIS_NOTIFY_ZSET; break;\n        case 'x': flags |= REDIS_NOTIFY_EXPIRED; break;\n        case 'e': flags |= REDIS_NOTIFY_EVICTED; break;\n        case 'K': flags |= REDIS_NOTIFY_KEYSPACE; break;\n        case 'E': flags |= REDIS_NOTIFY_KEYEVENT; break;\n        default: return -1;\n        }\n    }\n    return flags;\n}\n\n/* This function does exactly the revese of the function above: it gets\n * as input an integer with the xored flags and returns a string representing\n * the selected classes. The string returned is an sds string that needs to\n * be released with sdsfree(). */\nsds keyspaceEventsFlagsToString(int flags) {\n    sds res;\n\n    res = sdsempty();\n    if ((flags & REDIS_NOTIFY_ALL) == REDIS_NOTIFY_ALL) {\n        res = sdscatlen(res,\"A\",1);\n    } else {\n        if (flags & REDIS_NOTIFY_GENERIC) res = sdscatlen(res,\"g\",1);\n        if (flags & REDIS_NOTIFY_STRING) res = sdscatlen(res,\"$\",1);\n        if (flags & REDIS_NOTIFY_LIST) res = sdscatlen(res,\"l\",1);\n        if (flags & REDIS_NOTIFY_SET) res = sdscatlen(res,\"s\",1);\n        if (flags & REDIS_NOTIFY_HASH) res = sdscatlen(res,\"h\",1);\n        if (flags & REDIS_NOTIFY_ZSET) res = sdscatlen(res,\"z\",1);\n        if (flags & REDIS_NOTIFY_EXPIRED) res = sdscatlen(res,\"x\",1);\n        if (flags & REDIS_NOTIFY_EVICTED) res = sdscatlen(res,\"e\",1);\n    }\n    if (flags & REDIS_NOTIFY_KEYSPACE) res = sdscatlen(res,\"K\",1);\n    if (flags & REDIS_NOTIFY_KEYEVENT) res = sdscatlen(res,\"E\",1);\n    return res;\n}\n\n/* The API provided to the rest of the Redis core is a simple function:\n *\n * notifyKeyspaceEvent(char *event, robj *key, int dbid);\n *\n * 'event' is a C string representing the event name.\n * 'key' is a Redis object representing the key name.\n * 'dbid' is the database ID where the key lives.  */\nvoid notifyKeyspaceEvent(int type, char *event, robj *key, int dbid) {\n    sds chan;\n    robj *chanobj, *eventobj;\n    int len = -1;\n    char buf[24];\n\n    /* If notifications for this class of events are off, return ASAP. */\n    if (!(server.notify_keyspace_events & type)) return;\n\n    eventobj = createStringObject(event,strlen(event));\n\n    /* __keyspace@<db>__:<key> <event> notifications. */\n    if (server.notify_keyspace_events & REDIS_NOTIFY_KEYSPACE) {\n        chan = sdsnewlen(\"__keyspace@\",11);\n        len = ll2string(buf,sizeof(buf),dbid);\n        chan = sdscatlen(chan, buf, len);\n        chan = sdscatlen(chan, \"__:\", 3);\n        chan = sdscatsds(chan, key->ptr);\n        chanobj = createObject(REDIS_STRING, chan);\n        pubsubPublishMessage(chanobj, eventobj);\n        decrRefCount(chanobj);\n    }\n\n    /* __keyevente@<db>__:<event> <key> notifications. */\n    if (server.notify_keyspace_events & REDIS_NOTIFY_KEYEVENT) {\n        chan = sdsnewlen(\"__keyevent@\",11);\n        if (len == -1) len = ll2string(buf,sizeof(buf),dbid);\n        chan = sdscatlen(chan, buf, len);\n        chan = sdscatlen(chan, \"__:\", 3);\n        chan = sdscatsds(chan, eventobj->ptr);\n        chanobj = createObject(REDIS_STRING, chan);\n        pubsubPublishMessage(chanobj, key);\n        decrRefCount(chanobj);\n    }\n    decrRefCount(eventobj);\n}\n"
  },
  {
    "path": "extern/deprecated/redis-2.8.21/src/object.c",
    "content": "/* Redis Object implementation.\n *\n * Copyright (c) 2009-2012, Salvatore Sanfilippo <antirez at gmail dot com>\n * All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions are met:\n *\n *   * Redistributions of source code must retain the above copyright notice,\n *     this list of conditions and the following disclaimer.\n *   * Redistributions in binary form must reproduce the above copyright\n *     notice, this list of conditions and the following disclaimer in the\n *     documentation and/or other materials provided with the distribution.\n *   * Neither the name of Redis nor the names of its contributors may be used\n *     to endorse or promote products derived from this software without\n *     specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\"\n * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\n * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE\n * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR\n * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF\n * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS\n * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN\n * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)\n * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE\n * POSSIBILITY OF SUCH DAMAGE.\n */\n\n#include \"redis.h\"\n#include <math.h>\n#include <ctype.h>\n\n#ifdef __CYGWIN__\n#define strtold(a,b) ((long double)strtod((a),(b)))\n#endif\n\nrobj *createObject(int type, void *ptr) {\n    robj *o = zmalloc(sizeof(*o));\n    o->type = type;\n    o->encoding = REDIS_ENCODING_RAW;\n    o->ptr = ptr;\n    o->refcount = 1;\n\n    /* Set the LRU to the current lruclock (minutes resolution). */\n    o->lru = server.lruclock;\n    return o;\n}\n\nrobj *createStringObject(char *ptr, size_t len) {\n    return createObject(REDIS_STRING,sdsnewlen(ptr,len));\n}\n\nrobj *createStringObjectFromLongLong(long long value) {\n    robj *o;\n    if (value >= 0 && value < REDIS_SHARED_INTEGERS) {\n        incrRefCount(shared.integers[value]);\n        o = shared.integers[value];\n    } else {\n        if (value >= LONG_MIN && value <= LONG_MAX) {\n            o = createObject(REDIS_STRING, NULL);\n            o->encoding = REDIS_ENCODING_INT;\n            o->ptr = (void*)((long)value);\n        } else {\n            o = createObject(REDIS_STRING,sdsfromlonglong(value));\n        }\n    }\n    return o;\n}\n\n/* Create a string object from a long double. If humanfriendly is non-zero\n * it does not use exponential format and trims trailing zeroes at the end,\n * however this results in loss of precision. Otherwise exp format is used\n * and the output of snprintf() is not modified.\n *\n * The 'humanfriendly' option is used for INCRBYFLOAT and HINCRBYFLOAT. */\nrobj *createStringObjectFromLongDouble(long double value, int humanfriendly) {\n    char buf[256];\n    int len;\n\n    if (isinf(value)) {\n        /* Libc in odd systems (Hi Solaris!) will format infinite in a\n         * different way, so better to handle it in an explicit way. */\n        if (value > 0) {\n            memcpy(buf,\"inf\",3);\n            len = 3;\n        } else {\n            memcpy(buf,\"-inf\",4);\n            len = 4;\n        }\n    } else if (humanfriendly) {\n        /* We use 17 digits precision since with 128 bit floats that precision\n         * after rounding is able to represent most small decimal numbers in a\n         * way that is \"non surprising\" for the user (that is, most small\n         * decimal numbers will be represented in a way that when converted\n         * back into a string are exactly the same as what the user typed.) */\n        len = snprintf(buf,sizeof(buf),\"%.17Lf\", value);\n        /* Now remove trailing zeroes after the '.' */\n        if (strchr(buf,'.') != NULL) {\n            char *p = buf+len-1;\n            while(*p == '0') {\n                p--;\n                len--;\n            }\n            if (*p == '.') len--;\n        }\n    } else {\n        len = snprintf(buf,sizeof(buf),\"%.17Lg\", value);\n    }\n    return createStringObject(buf,len);\n}\n\nrobj *dupStringObject(robj *o) {\n    redisAssertWithInfo(NULL,o,o->encoding == REDIS_ENCODING_RAW);\n    return createStringObject(o->ptr,sdslen(o->ptr));\n}\n\nrobj *createListObject(void) {\n    list *l = listCreate();\n    robj *o = createObject(REDIS_LIST,l);\n    listSetFreeMethod(l,decrRefCountVoid);\n    o->encoding = REDIS_ENCODING_LINKEDLIST;\n    return o;\n}\n\nrobj *createZiplistObject(void) {\n    unsigned char *zl = ziplistNew();\n    robj *o = createObject(REDIS_LIST,zl);\n    o->encoding = REDIS_ENCODING_ZIPLIST;\n    return o;\n}\n\nrobj *createSetObject(void) {\n    dict *d = dictCreate(&setDictType,NULL);\n    robj *o = createObject(REDIS_SET,d);\n    o->encoding = REDIS_ENCODING_HT;\n    return o;\n}\n\nrobj *createIntsetObject(void) {\n    intset *is = intsetNew();\n    robj *o = createObject(REDIS_SET,is);\n    o->encoding = REDIS_ENCODING_INTSET;\n    return o;\n}\n\nrobj *createHashObject(void) {\n    unsigned char *zl = ziplistNew();\n    robj *o = createObject(REDIS_HASH, zl);\n    o->encoding = REDIS_ENCODING_ZIPLIST;\n    return o;\n}\n\nrobj *createZsetObject(void) {\n    zset *zs = zmalloc(sizeof(*zs));\n    robj *o;\n\n    zs->dict = dictCreate(&zsetDictType,NULL);\n    zs->zsl = zslCreate();\n    o = createObject(REDIS_ZSET,zs);\n    o->encoding = REDIS_ENCODING_SKIPLIST;\n    return o;\n}\n\nrobj *createZsetZiplistObject(void) {\n    unsigned char *zl = ziplistNew();\n    robj *o = createObject(REDIS_ZSET,zl);\n    o->encoding = REDIS_ENCODING_ZIPLIST;\n    return o;\n}\n\nvoid freeStringObject(robj *o) {\n    if (o->encoding == REDIS_ENCODING_RAW) {\n        sdsfree(o->ptr);\n    }\n}\n\nvoid freeListObject(robj *o) {\n    switch (o->encoding) {\n    case REDIS_ENCODING_LINKEDLIST:\n        listRelease((list*) o->ptr);\n        break;\n    case REDIS_ENCODING_ZIPLIST:\n        zfree(o->ptr);\n        break;\n    default:\n        redisPanic(\"Unknown list encoding type\");\n    }\n}\n\nvoid freeSetObject(robj *o) {\n    switch (o->encoding) {\n    case REDIS_ENCODING_HT:\n        dictRelease((dict*) o->ptr);\n        break;\n    case REDIS_ENCODING_INTSET:\n        zfree(o->ptr);\n        break;\n    default:\n        redisPanic(\"Unknown set encoding type\");\n    }\n}\n\nvoid freeZsetObject(robj *o) {\n    zset *zs;\n    switch (o->encoding) {\n    case REDIS_ENCODING_SKIPLIST:\n        zs = o->ptr;\n        dictRelease(zs->dict);\n        zslFree(zs->zsl);\n        zfree(zs);\n        break;\n    case REDIS_ENCODING_ZIPLIST:\n        zfree(o->ptr);\n        break;\n    default:\n        redisPanic(\"Unknown sorted set encoding\");\n    }\n}\n\nvoid freeHashObject(robj *o) {\n    switch (o->encoding) {\n    case REDIS_ENCODING_HT:\n        dictRelease((dict*) o->ptr);\n        break;\n    case REDIS_ENCODING_ZIPLIST:\n        zfree(o->ptr);\n        break;\n    default:\n        redisPanic(\"Unknown hash encoding type\");\n        break;\n    }\n}\n\nvoid incrRefCount(robj *o) {\n    o->refcount++;\n}\n\nvoid decrRefCount(robj *o) {\n    if (o->refcount <= 0) redisPanic(\"decrRefCount against refcount <= 0\");\n    if (o->refcount == 1) {\n        switch(o->type) {\n        case REDIS_STRING: freeStringObject(o); break;\n        case REDIS_LIST: freeListObject(o); break;\n        case REDIS_SET: freeSetObject(o); break;\n        case REDIS_ZSET: freeZsetObject(o); break;\n        case REDIS_HASH: freeHashObject(o); break;\n        default: redisPanic(\"Unknown object type\"); break;\n        }\n        zfree(o);\n    } else {\n        o->refcount--;\n    }\n}\n\n/* This variant of decrRefCount() gets its argument as void, and is useful\n * as free method in data structures that expect a 'void free_object(void*)'\n * prototype for the free method. */\nvoid decrRefCountVoid(void *o) {\n    decrRefCount(o);\n}\n\n/* This function set the ref count to zero without freeing the object.\n * It is useful in order to pass a new object to functions incrementing\n * the ref count of the received object. Example:\n *\n *    functionThatWillIncrementRefCount(resetRefCount(CreateObject(...)));\n *\n * Otherwise you need to resort to the less elegant pattern:\n *\n *    *obj = createObject(...);\n *    functionThatWillIncrementRefCount(obj);\n *    decrRefCount(obj);\n */\nrobj *resetRefCount(robj *obj) {\n    obj->refcount = 0;\n    return obj;\n}\n\nint checkType(redisClient *c, robj *o, int type) {\n    if (o->type != type) {\n        addReply(c,shared.wrongtypeerr);\n        return 1;\n    }\n    return 0;\n}\n\nint isObjectRepresentableAsLongLong(robj *o, long long *llval) {\n    redisAssertWithInfo(NULL,o,o->type == REDIS_STRING);\n    if (o->encoding == REDIS_ENCODING_INT) {\n        if (llval) *llval = (long) o->ptr;\n        return REDIS_OK;\n    } else {\n        return string2ll(o->ptr,sdslen(o->ptr),llval) ? REDIS_OK : REDIS_ERR;\n    }\n}\n\n/* Try to encode a string object in order to save space */\nrobj *tryObjectEncoding(robj *o) {\n    long value;\n    sds s = o->ptr;\n    size_t len;\n\n    if (o->encoding != REDIS_ENCODING_RAW)\n        return o; /* Already encoded */\n\n    /* It's not safe to encode shared objects: shared objects can be shared\n     * everywhere in the \"object space\" of Redis. Encoded objects can only\n     * appear as \"values\" (and not, for instance, as keys) */\n     if (o->refcount > 1) return o;\n\n    /* Currently we try to encode only strings */\n    redisAssertWithInfo(NULL,o,o->type == REDIS_STRING);\n\n    /* Check if we can represent this string as a long integer */\n    len = sdslen(s);\n    if (len > 21 || !string2l(s,len,&value)) {\n        /* We can't encode the object...\n         *\n         * Do the last try, and at least optimize the SDS string inside\n         * the string object to require little space, in case there\n         * is more than 10% of free space at the end of the SDS string.\n         *\n         * We do that for larger strings, using the arbitrary value\n         * of 32 bytes. This code was backported from the unstable branch\n         * where this is performed when the object is too large to be\n         * encoded as EMBSTR. */\n        if (len > 32 &&\n            o->encoding == REDIS_ENCODING_RAW &&\n            sdsavail(s) > len/10)\n        {\n            o->ptr = sdsRemoveFreeSpace(o->ptr);\n        }\n        /* Return the original object. */\n        return o;\n    }\n\n    /* Ok, this object can be encoded...\n     *\n     * Can I use a shared object? Only if the object is inside a given range\n     *\n     * Note that we also avoid using shared integers when maxmemory is used\n     * because every object needs to have a private LRU field for the LRU\n     * algorithm to work well. */\n    if ((server.maxmemory == 0 ||\n         (server.maxmemory_policy != REDIS_MAXMEMORY_VOLATILE_LRU &&\n          server.maxmemory_policy != REDIS_MAXMEMORY_ALLKEYS_LRU)) &&\n        value >= 0 && value < REDIS_SHARED_INTEGERS)\n    {\n        decrRefCount(o);\n        incrRefCount(shared.integers[value]);\n        return shared.integers[value];\n    } else {\n        o->encoding = REDIS_ENCODING_INT;\n        sdsfree(o->ptr);\n        o->ptr = (void*) value;\n        return o;\n    }\n}\n\n/* Get a decoded version of an encoded object (returned as a new object).\n * If the object is already raw-encoded just increment the ref count. */\nrobj *getDecodedObject(robj *o) {\n    robj *dec;\n\n    if (o->encoding == REDIS_ENCODING_RAW) {\n        incrRefCount(o);\n        return o;\n    }\n    if (o->type == REDIS_STRING && o->encoding == REDIS_ENCODING_INT) {\n        char buf[32];\n\n        ll2string(buf,32,(long)o->ptr);\n        dec = createStringObject(buf,strlen(buf));\n        return dec;\n    } else {\n        redisPanic(\"Unknown encoding type\");\n    }\n}\n\n/* Compare two string objects via strcmp() or strcoll() depending on flags.\n * Note that the objects may be integer-encoded. In such a case we\n * use ll2string() to get a string representation of the numbers on the stack\n * and compare the strings, it's much faster than calling getDecodedObject().\n *\n * Important note: when REDIS_COMPARE_BINARY is used a binary-safe comparison\n * is used. */\n\n#define REDIS_COMPARE_BINARY (1<<0)\n#define REDIS_COMPARE_COLL (1<<1)\n\nint compareStringObjectsWithFlags(robj *a, robj *b, int flags) {\n    redisAssertWithInfo(NULL,a,a->type == REDIS_STRING && b->type == REDIS_STRING);\n    char bufa[128], bufb[128], *astr, *bstr;\n    size_t alen, blen, minlen;\n\n    if (a == b) return 0;\n    if (a->encoding != REDIS_ENCODING_RAW) {\n        alen = ll2string(bufa,sizeof(bufa),(long) a->ptr);\n        astr = bufa;\n    } else {\n        astr = a->ptr;\n        alen = sdslen(astr);\n    }\n    if (b->encoding != REDIS_ENCODING_RAW) {\n        blen = ll2string(bufb,sizeof(bufb),(long) b->ptr);\n        bstr = bufb;\n    } else {\n        bstr = b->ptr;\n        blen = sdslen(bstr);\n    }\n    if (flags & REDIS_COMPARE_COLL) {\n        return strcoll(astr,bstr);\n    } else {\n        int cmp;\n\n        minlen = (alen < blen) ? alen : blen;\n        cmp = memcmp(astr,bstr,minlen);\n        if (cmp == 0) return alen-blen;\n        return cmp;\n    }\n}\n\n/* Wrapper for compareStringObjectsWithFlags() using binary comparison. */\nint compareStringObjects(robj *a, robj *b) {\n    return compareStringObjectsWithFlags(a,b,REDIS_COMPARE_BINARY);\n}\n\n/* Wrapper for compareStringObjectsWithFlags() using collation. */\nint collateStringObjects(robj *a, robj *b) {\n    return compareStringObjectsWithFlags(a,b,REDIS_COMPARE_COLL);\n}\n\n/* Equal string objects return 1 if the two objects are the same from the\n * point of view of a string comparison, otherwise 0 is returned. Note that\n * this function is faster then checking for (compareStringObject(a,b) == 0)\n * because it can perform some more optimization. */\nint equalStringObjects(robj *a, robj *b) {\n    if (a->encoding != REDIS_ENCODING_RAW && b->encoding != REDIS_ENCODING_RAW){\n        return a->ptr == b->ptr;\n    } else {\n        return compareStringObjects(a,b) == 0;\n    }\n}\n\nsize_t stringObjectLen(robj *o) {\n    redisAssertWithInfo(NULL,o,o->type == REDIS_STRING);\n    if (o->encoding == REDIS_ENCODING_RAW) {\n        return sdslen(o->ptr);\n    } else {\n        char buf[32];\n\n        return ll2string(buf,32,(long)o->ptr);\n    }\n}\n\nint getDoubleFromObject(robj *o, double *target) {\n    double value;\n    char *eptr;\n\n    if (o == NULL) {\n        value = 0;\n    } else {\n        redisAssertWithInfo(NULL,o,o->type == REDIS_STRING);\n        if (o->encoding == REDIS_ENCODING_RAW) {\n            errno = 0;\n            value = strtod(o->ptr, &eptr);\n            if (isspace(((char*)o->ptr)[0]) ||\n                eptr[0] != '\\0' ||\n                (errno == ERANGE &&\n                    (value == HUGE_VAL || value == -HUGE_VAL || value == 0)) ||\n                errno == EINVAL ||\n                isnan(value))\n                return REDIS_ERR;\n        } else if (o->encoding == REDIS_ENCODING_INT) {\n            value = (long)o->ptr;\n        } else {\n            redisPanic(\"Unknown string encoding\");\n        }\n    }\n    *target = value;\n    return REDIS_OK;\n}\n\nint getDoubleFromObjectOrReply(redisClient *c, robj *o, double *target, const char *msg) {\n    double value;\n    if (getDoubleFromObject(o, &value) != REDIS_OK) {\n        if (msg != NULL) {\n            addReplyError(c,(char*)msg);\n        } else {\n            addReplyError(c,\"value is not a valid float\");\n        }\n        return REDIS_ERR;\n    }\n    *target = value;\n    return REDIS_OK;\n}\n\nint getLongDoubleFromObject(robj *o, long double *target) {\n    long double value;\n    char *eptr;\n\n    if (o == NULL) {\n        value = 0;\n    } else {\n        redisAssertWithInfo(NULL,o,o->type == REDIS_STRING);\n        if (o->encoding == REDIS_ENCODING_RAW) {\n            errno = 0;\n            value = strtold(o->ptr, &eptr);\n            if (isspace(((char*)o->ptr)[0]) || eptr[0] != '\\0' ||\n                errno == ERANGE || isnan(value))\n                return REDIS_ERR;\n        } else if (o->encoding == REDIS_ENCODING_INT) {\n            value = (long)o->ptr;\n        } else {\n            redisPanic(\"Unknown string encoding\");\n        }\n    }\n    *target = value;\n    return REDIS_OK;\n}\n\nint getLongDoubleFromObjectOrReply(redisClient *c, robj *o, long double *target, const char *msg) {\n    long double value;\n    if (getLongDoubleFromObject(o, &value) != REDIS_OK) {\n        if (msg != NULL) {\n            addReplyError(c,(char*)msg);\n        } else {\n            addReplyError(c,\"value is not a valid float\");\n        }\n        return REDIS_ERR;\n    }\n    *target = value;\n    return REDIS_OK;\n}\n\nint getLongLongFromObject(robj *o, long long *target) {\n    long long value;\n    char *eptr;\n\n    if (o == NULL) {\n        value = 0;\n    } else {\n        redisAssertWithInfo(NULL,o,o->type == REDIS_STRING);\n        if (o->encoding == REDIS_ENCODING_RAW) {\n            errno = 0;\n            value = strtoll(o->ptr, &eptr, 10);\n            if (isspace(((char*)o->ptr)[0]) || eptr[0] != '\\0' ||\n                errno == ERANGE)\n                return REDIS_ERR;\n        } else if (o->encoding == REDIS_ENCODING_INT) {\n            value = (long)o->ptr;\n        } else {\n            redisPanic(\"Unknown string encoding\");\n        }\n    }\n    if (target) *target = value;\n    return REDIS_OK;\n}\n\nint getLongLongFromObjectOrReply(redisClient *c, robj *o, long long *target, const char *msg) {\n    long long value;\n    if (getLongLongFromObject(o, &value) != REDIS_OK) {\n        if (msg != NULL) {\n            addReplyError(c,(char*)msg);\n        } else {\n            addReplyError(c,\"value is not an integer or out of range\");\n        }\n        return REDIS_ERR;\n    }\n    *target = value;\n    return REDIS_OK;\n}\n\nint getLongFromObjectOrReply(redisClient *c, robj *o, long *target, const char *msg) {\n    long long value;\n\n    if (getLongLongFromObjectOrReply(c, o, &value, msg) != REDIS_OK) return REDIS_ERR;\n    if (value < LONG_MIN || value > LONG_MAX) {\n        if (msg != NULL) {\n            addReplyError(c,(char*)msg);\n        } else {\n            addReplyError(c,\"value is out of range\");\n        }\n        return REDIS_ERR;\n    }\n    *target = value;\n    return REDIS_OK;\n}\n\nchar *strEncoding(int encoding) {\n    switch(encoding) {\n    case REDIS_ENCODING_RAW: return \"raw\";\n    case REDIS_ENCODING_INT: return \"int\";\n    case REDIS_ENCODING_HT: return \"hashtable\";\n    case REDIS_ENCODING_LINKEDLIST: return \"linkedlist\";\n    case REDIS_ENCODING_ZIPLIST: return \"ziplist\";\n    case REDIS_ENCODING_INTSET: return \"intset\";\n    case REDIS_ENCODING_SKIPLIST: return \"skiplist\";\n    default: return \"unknown\";\n    }\n}\n\n/* Given an object returns the min number of seconds the object was never\n * requested, using an approximated LRU algorithm. */\nunsigned long estimateObjectIdleTime(robj *o) {\n    if (server.lruclock >= o->lru) {\n        return (server.lruclock - o->lru) * REDIS_LRU_CLOCK_RESOLUTION;\n    } else {\n        return ((REDIS_LRU_CLOCK_MAX - o->lru) + server.lruclock) *\n                    REDIS_LRU_CLOCK_RESOLUTION;\n    }\n}\n\n/* This is a helper function for the OBJECT command. We need to lookup keys\n * without any modification of LRU or other parameters. */\nrobj *objectCommandLookup(redisClient *c, robj *key) {\n    dictEntry *de;\n\n    if ((de = dictFind(c->db->dict,key->ptr)) == NULL) return NULL;\n    return (robj*) dictGetVal(de);\n}\n\nrobj *objectCommandLookupOrReply(redisClient *c, robj *key, robj *reply) {\n    robj *o = objectCommandLookup(c,key);\n\n    if (!o) addReply(c, reply);\n    return o;\n}\n\n/* Object command allows to inspect the internals of an Redis Object.\n * Usage: OBJECT <refcount|encoding|idletime> <key> */\nvoid objectCommand(redisClient *c) {\n    robj *o;\n\n    if (!strcasecmp(c->argv[1]->ptr,\"refcount\") && c->argc == 3) {\n        if ((o = objectCommandLookupOrReply(c,c->argv[2],shared.nullbulk))\n                == NULL) return;\n        addReplyLongLong(c,o->refcount);\n    } else if (!strcasecmp(c->argv[1]->ptr,\"encoding\") && c->argc == 3) {\n        if ((o = objectCommandLookupOrReply(c,c->argv[2],shared.nullbulk))\n                == NULL) return;\n        addReplyBulkCString(c,strEncoding(o->encoding));\n    } else if (!strcasecmp(c->argv[1]->ptr,\"idletime\") && c->argc == 3) {\n        if ((o = objectCommandLookupOrReply(c,c->argv[2],shared.nullbulk))\n                == NULL) return;\n        addReplyLongLong(c,estimateObjectIdleTime(o));\n    } else {\n        addReplyError(c,\"Syntax error. Try OBJECT (refcount|encoding|idletime)\");\n    }\n}\n\n"
  },
  {
    "path": "extern/deprecated/redis-2.8.21/src/pqsort.c",
    "content": "/* The following is the NetBSD libc qsort implementation modified in order to\n * support partial sorting of ranges for Redis.\n *\n * Copyright(C) 2009-2012 Salvatore Sanfilippo. All rights reserved.\n *\n * The original copyright notice follows. */\n\n\n/*\t$NetBSD: qsort.c,v 1.19 2009/01/30 23:38:44 lukem Exp $\t*/\n\n/*-\n * Copyright (c) 1992, 1993\n *\tThe Regents of the University of California.  All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions\n * are met:\n * 1. Redistributions of source code must retain the above copyright\n *    notice, this list of conditions and the following disclaimer.\n * 2. Redistributions in binary form must reproduce the above copyright\n *    notice, this list of conditions and the following disclaimer in the\n *    documentation and/or other materials provided with the distribution.\n * 3. Neither the name of the University nor the names of its contributors\n *    may be used to endorse or promote products derived from this software\n *    without specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND\n * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\n * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE\n * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL\n * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS\n * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)\n * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT\n * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY\n * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF\n * SUCH DAMAGE.\n */\n\n#include <sys/types.h>\n\n#include <errno.h>\n#include <stdlib.h>\n\nstatic inline char\t*med3 (char *, char *, char *,\n    int (*)(const void *, const void *));\nstatic inline void\t swapfunc (char *, char *, size_t, int);\n\n#define min(a, b)\t(a) < (b) ? a : b\n\n/*\n * Qsort routine from Bentley & McIlroy's \"Engineering a Sort Function\".\n */\n#define swapcode(TYPE, parmi, parmj, n) { \t\t\\\n\tsize_t i = (n) / sizeof (TYPE); \t\t\\\n\tTYPE *pi = (TYPE *)(void *)(parmi); \t\t\\\n\tTYPE *pj = (TYPE *)(void *)(parmj); \t\t\\\n\tdo { \t\t\t\t\t\t\\\n\t\tTYPE\tt = *pi;\t\t\t\\\n\t\t*pi++ = *pj;\t\t\t\t\\\n\t\t*pj++ = t;\t\t\t\t\\\n        } while (--i > 0);\t\t\t\t\\\n}\n\n#define SWAPINIT(a, es) swaptype = ((char *)a - (char *)0) % sizeof(long) || \\\n\tes % sizeof(long) ? 2 : es == sizeof(long)? 0 : 1;\n\nstatic inline void\nswapfunc(char *a, char *b, size_t n, int swaptype)\n{\n\n\tif (swaptype <= 1)\n\t\tswapcode(long, a, b, n)\n\telse\n\t\tswapcode(char, a, b, n)\n}\n\n#define swap(a, b)\t\t\t\t\t\t\\\n\tif (swaptype == 0) {\t\t\t\t\t\\\n\t\tlong t = *(long *)(void *)(a);\t\t\t\\\n\t\t*(long *)(void *)(a) = *(long *)(void *)(b);\t\\\n\t\t*(long *)(void *)(b) = t;\t\t\t\\\n\t} else\t\t\t\t\t\t\t\\\n\t\tswapfunc(a, b, es, swaptype)\n\n#define vecswap(a, b, n) if ((n) > 0) swapfunc((a), (b), (size_t)(n), swaptype)\n\nstatic inline char *\nmed3(char *a, char *b, char *c,\n    int (*cmp) (const void *, const void *))\n{\n\n\treturn cmp(a, b) < 0 ?\n\t       (cmp(b, c) < 0 ? b : (cmp(a, c) < 0 ? c : a ))\n              :(cmp(b, c) > 0 ? b : (cmp(a, c) < 0 ? a : c ));\n}\n\nstatic void\n_pqsort(void *a, size_t n, size_t es,\n    int (*cmp) (const void *, const void *), void *lrange, void *rrange)\n{\n\tchar *pa, *pb, *pc, *pd, *pl, *pm, *pn;\n\tsize_t d, r;\n\tint swaptype, cmp_result;\n\nloop:\tSWAPINIT(a, es);\n\tif (n < 7) {\n\t\tfor (pm = (char *) a + es; pm < (char *) a + n * es; pm += es)\n\t\t\tfor (pl = pm; pl > (char *) a && cmp(pl - es, pl) > 0;\n\t\t\t     pl -= es)\n\t\t\t\tswap(pl, pl - es);\n\t\treturn;\n\t}\n\tpm = (char *) a + (n / 2) * es;\n\tif (n > 7) {\n\t\tpl = (char *) a;\n\t\tpn = (char *) a + (n - 1) * es;\n\t\tif (n > 40) {\n\t\t\td = (n / 8) * es;\n\t\t\tpl = med3(pl, pl + d, pl + 2 * d, cmp);\n\t\t\tpm = med3(pm - d, pm, pm + d, cmp);\n\t\t\tpn = med3(pn - 2 * d, pn - d, pn, cmp);\n\t\t}\n\t\tpm = med3(pl, pm, pn, cmp);\n\t}\n\tswap(a, pm);\n\tpa = pb = (char *) a + es;\n\n\tpc = pd = (char *) a + (n - 1) * es;\n\tfor (;;) {\n\t\twhile (pb <= pc && (cmp_result = cmp(pb, a)) <= 0) {\n\t\t\tif (cmp_result == 0) {\n\t\t\t\tswap(pa, pb);\n\t\t\t\tpa += es;\n\t\t\t}\n\t\t\tpb += es;\n\t\t}\n\t\twhile (pb <= pc && (cmp_result = cmp(pc, a)) >= 0) {\n\t\t\tif (cmp_result == 0) {\n\t\t\t\tswap(pc, pd);\n\t\t\t\tpd -= es;\n\t\t\t}\n\t\t\tpc -= es;\n\t\t}\n\t\tif (pb > pc)\n\t\t\tbreak;\n\t\tswap(pb, pc);\n\t\tpb += es;\n\t\tpc -= es;\n\t}\n\n\tpn = (char *) a + n * es;\n\tr = min(pa - (char *) a, pb - pa);\n\tvecswap(a, pb - r, r);\n\tr = min((size_t)(pd - pc), pn - pd - es);\n\tvecswap(pb, pn - r, r);\n\tif ((r = pb - pa) > es) {\n                void *_l = a, *_r = ((unsigned char*)a)+r-1;\n                if (!((lrange < _l && rrange < _l) ||\n                    (lrange > _r && rrange > _r)))\n\t\t    _pqsort(a, r / es, es, cmp, lrange, rrange);\n        }\n\tif ((r = pd - pc) > es) {\n                void *_l, *_r;\n\n\t\t/* Iterate rather than recurse to save stack space */\n\t\ta = pn - r;\n\t\tn = r / es;\n\n                _l = a;\n                _r = ((unsigned char*)a)+r-1;\n                if (!((lrange < _l && rrange < _l) ||\n                    (lrange > _r && rrange > _r)))\n\t\t    goto loop;\n\t}\n/*\t\tqsort(pn - r, r / es, es, cmp);*/\n}\n\nvoid\npqsort(void *a, size_t n, size_t es,\n    int (*cmp) (const void *, const void *), size_t lrange, size_t rrange)\n{\n    _pqsort(a,n,es,cmp,((unsigned char*)a)+(lrange*es),\n                       ((unsigned char*)a)+((rrange+1)*es)-1);\n}\n"
  },
  {
    "path": "extern/deprecated/redis-2.8.21/src/pqsort.h",
    "content": "/* The following is the NetBSD libc qsort implementation modified in order to\n * support partial sorting of ranges for Redis.\n *\n * Copyright (c) 2009-2012, Salvatore Sanfilippo <antirez at gmail dot com>\n * All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions are met:\n *\n *   * Redistributions of source code must retain the above copyright notice,\n *     this list of conditions and the following disclaimer.\n *   * Redistributions in binary form must reproduce the above copyright\n *     notice, this list of conditions and the following disclaimer in the\n *     documentation and/or other materials provided with the distribution.\n *   * Neither the name of Redis nor the names of its contributors may be used\n *     to endorse or promote products derived from this software without\n *     specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\"\n * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\n * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE\n * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR\n * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF\n * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS\n * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN\n * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)\n * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE\n * POSSIBILITY OF SUCH DAMAGE.\n *\n * See the pqsort.c file for the original copyright notice. */\n\n#ifndef __PQSORT_H\n#define __PQSORT_H\n\nvoid\npqsort(void *a, size_t n, size_t es,\n    int (*cmp) (const void *, const void *), size_t lrange, size_t rrange);\n\n#endif\n"
  },
  {
    "path": "extern/deprecated/redis-2.8.21/src/pubsub.c",
    "content": "/*\n * Copyright (c) 2009-2012, Salvatore Sanfilippo <antirez at gmail dot com>\n * All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions are met:\n *\n *   * Redistributions of source code must retain the above copyright notice,\n *     this list of conditions and the following disclaimer.\n *   * Redistributions in binary form must reproduce the above copyright\n *     notice, this list of conditions and the following disclaimer in the\n *     documentation and/or other materials provided with the distribution.\n *   * Neither the name of Redis nor the names of its contributors may be used\n *     to endorse or promote products derived from this software without\n *     specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\"\n * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\n * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE\n * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR\n * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF\n * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS\n * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN\n * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)\n * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE\n * POSSIBILITY OF SUCH DAMAGE.\n */\n\n#include \"redis.h\"\n\n/*-----------------------------------------------------------------------------\n * Pubsub low level API\n *----------------------------------------------------------------------------*/\n\nvoid freePubsubPattern(void *p) {\n    pubsubPattern *pat = p;\n\n    decrRefCount(pat->pattern);\n    zfree(pat);\n}\n\nint listMatchPubsubPattern(void *a, void *b) {\n    pubsubPattern *pa = a, *pb = b;\n\n    return (pa->client == pb->client) &&\n           (equalStringObjects(pa->pattern,pb->pattern));\n}\n\n/* Return the number of channels + patterns a client is subscribed to. */\nint clientSubscriptionsCount(redisClient *c) {\n    return dictSize(c->pubsub_channels)+\n           listLength(c->pubsub_patterns);\n}\n\n/* Subscribe a client to a channel. Returns 1 if the operation succeeded, or\n * 0 if the client was already subscribed to that channel. */\nint pubsubSubscribeChannel(redisClient *c, robj *channel) {\n    struct dictEntry *de;\n    list *clients = NULL;\n    int retval = 0;\n\n    /* Add the channel to the client -> channels hash table */\n    if (dictAdd(c->pubsub_channels,channel,NULL) == DICT_OK) {\n        retval = 1;\n        incrRefCount(channel);\n        /* Add the client to the channel -> list of clients hash table */\n        de = dictFind(server.pubsub_channels,channel);\n        if (de == NULL) {\n            clients = listCreate();\n            dictAdd(server.pubsub_channels,channel,clients);\n            incrRefCount(channel);\n        } else {\n            clients = dictGetVal(de);\n        }\n        listAddNodeTail(clients,c);\n    }\n    /* Notify the client */\n    addReply(c,shared.mbulkhdr[3]);\n    addReply(c,shared.subscribebulk);\n    addReplyBulk(c,channel);\n    addReplyLongLong(c,clientSubscriptionsCount(c));\n    return retval;\n}\n\n/* Unsubscribe a client from a channel. Returns 1 if the operation succeeded, or\n * 0 if the client was not subscribed to the specified channel. */\nint pubsubUnsubscribeChannel(redisClient *c, robj *channel, int notify) {\n    struct dictEntry *de;\n    list *clients;\n    listNode *ln;\n    int retval = 0;\n\n    /* Remove the channel from the client -> channels hash table */\n    incrRefCount(channel); /* channel may be just a pointer to the same object\n                            we have in the hash tables. Protect it... */\n    if (dictDelete(c->pubsub_channels,channel) == DICT_OK) {\n        retval = 1;\n        /* Remove the client from the channel -> clients list hash table */\n        de = dictFind(server.pubsub_channels,channel);\n        redisAssertWithInfo(c,NULL,de != NULL);\n        clients = dictGetVal(de);\n        ln = listSearchKey(clients,c);\n        redisAssertWithInfo(c,NULL,ln != NULL);\n        listDelNode(clients,ln);\n        if (listLength(clients) == 0) {\n            /* Free the list and associated hash entry at all if this was\n             * the latest client, so that it will be possible to abuse\n             * Redis PUBSUB creating millions of channels. */\n            dictDelete(server.pubsub_channels,channel);\n        }\n    }\n    /* Notify the client */\n    if (notify) {\n        addReply(c,shared.mbulkhdr[3]);\n        addReply(c,shared.unsubscribebulk);\n        addReplyBulk(c,channel);\n        addReplyLongLong(c,dictSize(c->pubsub_channels)+\n                       listLength(c->pubsub_patterns));\n\n    }\n    decrRefCount(channel); /* it is finally safe to release it */\n    return retval;\n}\n\n/* Subscribe a client to a pattern. Returns 1 if the operation succeeded, or 0 if the client was already subscribed to that pattern. */\nint pubsubSubscribePattern(redisClient *c, robj *pattern) {\n    int retval = 0;\n\n    if (listSearchKey(c->pubsub_patterns,pattern) == NULL) {\n        retval = 1;\n        pubsubPattern *pat;\n        listAddNodeTail(c->pubsub_patterns,pattern);\n        incrRefCount(pattern);\n        pat = zmalloc(sizeof(*pat));\n        pat->pattern = getDecodedObject(pattern);\n        pat->client = c;\n        listAddNodeTail(server.pubsub_patterns,pat);\n    }\n    /* Notify the client */\n    addReply(c,shared.mbulkhdr[3]);\n    addReply(c,shared.psubscribebulk);\n    addReplyBulk(c,pattern);\n    addReplyLongLong(c,clientSubscriptionsCount(c));\n    return retval;\n}\n\n/* Unsubscribe a client from a channel. Returns 1 if the operation succeeded, or\n * 0 if the client was not subscribed to the specified channel. */\nint pubsubUnsubscribePattern(redisClient *c, robj *pattern, int notify) {\n    listNode *ln;\n    pubsubPattern pat;\n    int retval = 0;\n\n    incrRefCount(pattern); /* Protect the object. May be the same we remove */\n    if ((ln = listSearchKey(c->pubsub_patterns,pattern)) != NULL) {\n        retval = 1;\n        listDelNode(c->pubsub_patterns,ln);\n        pat.client = c;\n        pat.pattern = pattern;\n        ln = listSearchKey(server.pubsub_patterns,&pat);\n        listDelNode(server.pubsub_patterns,ln);\n    }\n    /* Notify the client */\n    if (notify) {\n        addReply(c,shared.mbulkhdr[3]);\n        addReply(c,shared.punsubscribebulk);\n        addReplyBulk(c,pattern);\n        addReplyLongLong(c,dictSize(c->pubsub_channels)+\n                       listLength(c->pubsub_patterns));\n    }\n    decrRefCount(pattern);\n    return retval;\n}\n\n/* Unsubscribe from all the channels. Return the number of channels the\n * client was subscribed to. */\nint pubsubUnsubscribeAllChannels(redisClient *c, int notify) {\n    dictIterator *di = dictGetSafeIterator(c->pubsub_channels);\n    dictEntry *de;\n    int count = 0;\n\n    while((de = dictNext(di)) != NULL) {\n        robj *channel = dictGetKey(de);\n\n        count += pubsubUnsubscribeChannel(c,channel,notify);\n    }\n    /* We were subscribed to nothing? Still reply to the client. */\n    if (notify && count == 0) {\n        addReply(c,shared.mbulkhdr[3]);\n        addReply(c,shared.unsubscribebulk);\n        addReply(c,shared.nullbulk);\n        addReplyLongLong(c,dictSize(c->pubsub_channels)+\n                       listLength(c->pubsub_patterns));\n    }\n    dictReleaseIterator(di);\n    return count;\n}\n\n/* Unsubscribe from all the patterns. Return the number of patterns the\n * client was subscribed from. */\nint pubsubUnsubscribeAllPatterns(redisClient *c, int notify) {\n    listNode *ln;\n    listIter li;\n    int count = 0;\n\n    listRewind(c->pubsub_patterns,&li);\n    while ((ln = listNext(&li)) != NULL) {\n        robj *pattern = ln->value;\n\n        count += pubsubUnsubscribePattern(c,pattern,notify);\n    }\n    if (notify && count == 0) {\n        /* We were subscribed to nothing? Still reply to the client. */\n        addReply(c,shared.mbulkhdr[3]);\n        addReply(c,shared.punsubscribebulk);\n        addReply(c,shared.nullbulk);\n        addReplyLongLong(c,dictSize(c->pubsub_channels)+\n                       listLength(c->pubsub_patterns));\n    }\n    return count;\n}\n\n/* Publish a message */\nint pubsubPublishMessage(robj *channel, robj *message) {\n    int receivers = 0;\n    struct dictEntry *de;\n    listNode *ln;\n    listIter li;\n\n    /* Send to clients listening for that channel */\n    de = dictFind(server.pubsub_channels,channel);\n    if (de) {\n        list *list = dictGetVal(de);\n        listNode *ln;\n        listIter li;\n\n        listRewind(list,&li);\n        while ((ln = listNext(&li)) != NULL) {\n            redisClient *c = ln->value;\n\n            addReply(c,shared.mbulkhdr[3]);\n            addReply(c,shared.messagebulk);\n            addReplyBulk(c,channel);\n            addReplyBulk(c,message);\n            receivers++;\n        }\n    }\n    /* Send to clients listening to matching channels */\n    if (listLength(server.pubsub_patterns)) {\n        listRewind(server.pubsub_patterns,&li);\n        channel = getDecodedObject(channel);\n        while ((ln = listNext(&li)) != NULL) {\n            pubsubPattern *pat = ln->value;\n\n            if (stringmatchlen((char*)pat->pattern->ptr,\n                                sdslen(pat->pattern->ptr),\n                                (char*)channel->ptr,\n                                sdslen(channel->ptr),0)) {\n                addReply(pat->client,shared.mbulkhdr[4]);\n                addReply(pat->client,shared.pmessagebulk);\n                addReplyBulk(pat->client,pat->pattern);\n                addReplyBulk(pat->client,channel);\n                addReplyBulk(pat->client,message);\n                receivers++;\n            }\n        }\n        decrRefCount(channel);\n    }\n    return receivers;\n}\n\n/*-----------------------------------------------------------------------------\n * Pubsub commands implementation\n *----------------------------------------------------------------------------*/\n\nvoid subscribeCommand(redisClient *c) {\n    int j;\n\n    for (j = 1; j < c->argc; j++)\n        pubsubSubscribeChannel(c,c->argv[j]);\n    c->flags |= REDIS_PUBSUB;\n}\n\nvoid unsubscribeCommand(redisClient *c) {\n    if (c->argc == 1) {\n        pubsubUnsubscribeAllChannels(c,1);\n    } else {\n        int j;\n\n        for (j = 1; j < c->argc; j++)\n            pubsubUnsubscribeChannel(c,c->argv[j],1);\n    }\n    if (clientSubscriptionsCount(c) == 0) c->flags &= ~REDIS_PUBSUB;\n}\n\nvoid psubscribeCommand(redisClient *c) {\n    int j;\n\n    for (j = 1; j < c->argc; j++)\n        pubsubSubscribePattern(c,c->argv[j]);\n    c->flags |= REDIS_PUBSUB;\n}\n\nvoid punsubscribeCommand(redisClient *c) {\n    if (c->argc == 1) {\n        pubsubUnsubscribeAllPatterns(c,1);\n    } else {\n        int j;\n\n        for (j = 1; j < c->argc; j++)\n            pubsubUnsubscribePattern(c,c->argv[j],1);\n    }\n    if (clientSubscriptionsCount(c) == 0) c->flags &= ~REDIS_PUBSUB;\n}\n\nvoid publishCommand(redisClient *c) {\n    int receivers = pubsubPublishMessage(c->argv[1],c->argv[2]);\n    forceCommandPropagation(c,REDIS_PROPAGATE_REPL);\n    addReplyLongLong(c,receivers);\n}\n\n/* PUBSUB command for Pub/Sub introspection. */\nvoid pubsubCommand(redisClient *c) {\n    if (!strcasecmp(c->argv[1]->ptr,\"channels\") &&\n        (c->argc == 2 || c->argc ==3))\n    {\n        /* PUBSUB CHANNELS [<pattern>] */\n        sds pat = (c->argc == 2) ? NULL : c->argv[2]->ptr;\n        dictIterator *di = dictGetIterator(server.pubsub_channels);\n        dictEntry *de;\n        long mblen = 0;\n        void *replylen;\n\n        replylen = addDeferredMultiBulkLength(c);\n        while((de = dictNext(di)) != NULL) {\n            robj *cobj = dictGetKey(de);\n            sds channel = cobj->ptr;\n\n            if (!pat || stringmatchlen(pat, sdslen(pat),\n                                       channel, sdslen(channel),0))\n            {\n                addReplyBulk(c,cobj);\n                mblen++;\n            }\n        }\n        dictReleaseIterator(di);\n        setDeferredMultiBulkLength(c,replylen,mblen);\n    } else if (!strcasecmp(c->argv[1]->ptr,\"numsub\") && c->argc >= 2) {\n        /* PUBSUB NUMSUB [Channel_1 ... Channel_N] */\n        int j;\n\n        addReplyMultiBulkLen(c,(c->argc-2)*2);\n        for (j = 2; j < c->argc; j++) {\n            list *l = dictFetchValue(server.pubsub_channels,c->argv[j]);\n\n            addReplyBulk(c,c->argv[j]);\n            addReplyLongLong(c,l ? listLength(l) : 0);\n        }\n    } else if (!strcasecmp(c->argv[1]->ptr,\"numpat\") && c->argc == 2) {\n        /* PUBSUB NUMPAT */\n        addReplyLongLong(c,listLength(server.pubsub_patterns));\n    } else {\n        addReplyErrorFormat(c,\n            \"Unknown PUBSUB subcommand or wrong number of arguments for '%s'\",\n            (char*)c->argv[1]->ptr);\n    }\n}\n"
  },
  {
    "path": "extern/deprecated/redis-2.8.21/src/rand.c",
    "content": "/* Pseudo random number generation functions derived from the drand48()\n * function obtained from pysam source code.\n *\n * This functions are used in order to replace the default math.random()\n * Lua implementation with something having exactly the same behavior\n * across different systems (by default Lua uses libc's rand() that is not\n * required to implement a specific PRNG generating the same sequence\n * in different systems if seeded with the same integer).\n *\n * The original code appears to be under the public domain.\n * I modified it removing the non needed functions and all the\n * 1960-style C coding stuff...\n *\n * ----------------------------------------------------------------------------\n *\n * Copyright (c) 2010-2012, Salvatore Sanfilippo <antirez at gmail dot com>\n * All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions are met:\n *\n *   * Redistributions of source code must retain the above copyright notice,\n *     this list of conditions and the following disclaimer.\n *   * Redistributions in binary form must reproduce the above copyright\n *     notice, this list of conditions and the following disclaimer in the\n *     documentation and/or other materials provided with the distribution.\n *   * Neither the name of Redis nor the names of its contributors may be used\n *     to endorse or promote products derived from this software without\n *     specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\"\n * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\n * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE\n * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR\n * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF\n * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS\n * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN\n * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)\n * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE\n * POSSIBILITY OF SUCH DAMAGE.\n */\n\n#include <stdint.h>\n\n#define N\t16\n#define MASK\t((1 << (N - 1)) + (1 << (N - 1)) - 1)\n#define LOW(x)\t((unsigned)(x) & MASK)\n#define HIGH(x)\tLOW((x) >> N)\n#define MUL(x, y, z)\t{ int32_t l = (long)(x) * (long)(y); \\\n\t\t(z)[0] = LOW(l); (z)[1] = HIGH(l); }\n#define CARRY(x, y)\t((int32_t)(x) + (long)(y) > MASK)\n#define ADDEQU(x, y, z)\t(z = CARRY(x, (y)), x = LOW(x + (y)))\n#define X0\t0x330E\n#define X1\t0xABCD\n#define X2\t0x1234\n#define A0\t0xE66D\n#define A1\t0xDEEC\n#define A2\t0x5\n#define C\t0xB\n#define SET3(x, x0, x1, x2)\t((x)[0] = (x0), (x)[1] = (x1), (x)[2] = (x2))\n#define SETLOW(x, y, n) SET3(x, LOW((y)[n]), LOW((y)[(n)+1]), LOW((y)[(n)+2]))\n#define SEED(x0, x1, x2) (SET3(x, x0, x1, x2), SET3(a, A0, A1, A2), c = C)\n#define REST(v)\tfor (i = 0; i < 3; i++) { xsubi[i] = x[i]; x[i] = temp[i]; } \\\n\t\treturn (v);\n#define HI_BIT\t(1L << (2 * N - 1))\n\nstatic uint32_t x[3] = { X0, X1, X2 }, a[3] = { A0, A1, A2 }, c = C;\nstatic void next(void);\n\nint32_t redisLrand48() {\n    next();\n    return (((int32_t)x[2] << (N - 1)) + (x[1] >> 1));\n}\n\nvoid redisSrand48(int32_t seedval) {\n    SEED(X0, LOW(seedval), HIGH(seedval));\n}\n\nstatic void next(void) {\n    uint32_t p[2], q[2], r[2], carry0, carry1;\n\n    MUL(a[0], x[0], p);\n    ADDEQU(p[0], c, carry0);\n    ADDEQU(p[1], carry0, carry1);\n    MUL(a[0], x[1], q);\n    ADDEQU(p[1], q[0], carry0);\n    MUL(a[1], x[0], r);\n    x[2] = LOW(carry0 + carry1 + CARRY(p[1], r[0]) + q[1] + r[1] +\n            a[0] * x[2] + a[1] * x[1] + a[2] * x[0]);\n    x[1] = LOW(p[1] + r[0]);\n    x[0] = LOW(p[0]);\n}\n"
  },
  {
    "path": "extern/deprecated/redis-2.8.21/src/rand.h",
    "content": "/*\n * Copyright (c) 2009-2012, Salvatore Sanfilippo <antirez at gmail dot com>\n * All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions are met:\n *\n *   * Redistributions of source code must retain the above copyright notice,\n *     this list of conditions and the following disclaimer.\n *   * Redistributions in binary form must reproduce the above copyright\n *     notice, this list of conditions and the following disclaimer in the\n *     documentation and/or other materials provided with the distribution.\n *   * Neither the name of Redis nor the names of its contributors may be used\n *     to endorse or promote products derived from this software without\n *     specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\"\n * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\n * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE\n * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR\n * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF\n * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS\n * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN\n * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)\n * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE\n * POSSIBILITY OF SUCH DAMAGE.\n */\n\n#ifndef REDIS_RANDOM_H\n#define REDIS_RANDOM_H\n\nint32_t redisLrand48();\nvoid redisSrand48(int32_t seedval);\n\n#define REDIS_LRAND48_MAX INT32_MAX\n\n#endif\n"
  },
  {
    "path": "extern/deprecated/redis-2.8.21/src/rdb.c",
    "content": "/*\n * Copyright (c) 2009-2012, Salvatore Sanfilippo <antirez at gmail dot com>\n * All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions are met:\n *\n *   * Redistributions of source code must retain the above copyright notice,\n *     this list of conditions and the following disclaimer.\n *   * Redistributions in binary form must reproduce the above copyright\n *     notice, this list of conditions and the following disclaimer in the\n *     documentation and/or other materials provided with the distribution.\n *   * Neither the name of Redis nor the names of its contributors may be used\n *     to endorse or promote products derived from this software without\n *     specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\"\n * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\n * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE\n * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR\n * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF\n * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS\n * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN\n * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)\n * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE\n * POSSIBILITY OF SUCH DAMAGE.\n */\n\n#include \"redis.h\"\n#include \"lzf.h\"    /* LZF compression library */\n#include \"zipmap.h\"\n#include \"endianconv.h\"\n\n#include <math.h>\n#include <sys/types.h>\n#include <sys/time.h>\n#include <sys/resource.h>\n#include <sys/wait.h>\n#include <arpa/inet.h>\n#include <sys/stat.h>\n\nstatic int rdbWriteRaw(rio *rdb, void *p, size_t len) {\n    if (rdb && rioWrite(rdb,p,len) == 0)\n        return -1;\n    return len;\n}\n\nint rdbSaveType(rio *rdb, unsigned char type) {\n    return rdbWriteRaw(rdb,&type,1);\n}\n\n/* Load a \"type\" in RDB format, that is a one byte unsigned integer.\n * This function is not only used to load object types, but also special\n * \"types\" like the end-of-file type, the EXPIRE type, and so forth. */\nint rdbLoadType(rio *rdb) {\n    unsigned char type;\n    if (rioRead(rdb,&type,1) == 0) return -1;\n    return type;\n}\n\ntime_t rdbLoadTime(rio *rdb) {\n    int32_t t32;\n    if (rioRead(rdb,&t32,4) == 0) return -1;\n    return (time_t)t32;\n}\n\nint rdbSaveMillisecondTime(rio *rdb, long long t) {\n    int64_t t64 = (int64_t) t;\n    return rdbWriteRaw(rdb,&t64,8);\n}\n\nlong long rdbLoadMillisecondTime(rio *rdb) {\n    int64_t t64;\n    if (rioRead(rdb,&t64,8) == 0) return -1;\n    return (long long)t64;\n}\n\n/* Saves an encoded length. The first two bits in the first byte are used to\n * hold the encoding type. See the REDIS_RDB_* definitions for more information\n * on the types of encoding. */\nint rdbSaveLen(rio *rdb, uint32_t len) {\n    unsigned char buf[2];\n    size_t nwritten;\n\n    if (len < (1<<6)) {\n        /* Save a 6 bit len */\n        buf[0] = (len&0xFF)|(REDIS_RDB_6BITLEN<<6);\n        if (rdbWriteRaw(rdb,buf,1) == -1) return -1;\n        nwritten = 1;\n    } else if (len < (1<<14)) {\n        /* Save a 14 bit len */\n        buf[0] = ((len>>8)&0xFF)|(REDIS_RDB_14BITLEN<<6);\n        buf[1] = len&0xFF;\n        if (rdbWriteRaw(rdb,buf,2) == -1) return -1;\n        nwritten = 2;\n    } else {\n        /* Save a 32 bit len */\n        buf[0] = (REDIS_RDB_32BITLEN<<6);\n        if (rdbWriteRaw(rdb,buf,1) == -1) return -1;\n        len = htonl(len);\n        if (rdbWriteRaw(rdb,&len,4) == -1) return -1;\n        nwritten = 1+4;\n    }\n    return nwritten;\n}\n\n/* Load an encoded length. The \"isencoded\" argument is set to 1 if the length\n * is not actually a length but an \"encoding type\". See the REDIS_RDB_ENC_*\n * definitions in rdb.h for more information. */\nuint32_t rdbLoadLen(rio *rdb, int *isencoded) {\n    unsigned char buf[2];\n    uint32_t len;\n    int type;\n\n    if (isencoded) *isencoded = 0;\n    if (rioRead(rdb,buf,1) == 0) return REDIS_RDB_LENERR;\n    type = (buf[0]&0xC0)>>6;\n    if (type == REDIS_RDB_ENCVAL) {\n        /* Read a 6 bit encoding type. */\n        if (isencoded) *isencoded = 1;\n        return buf[0]&0x3F;\n    } else if (type == REDIS_RDB_6BITLEN) {\n        /* Read a 6 bit len. */\n        return buf[0]&0x3F;\n    } else if (type == REDIS_RDB_14BITLEN) {\n        /* Read a 14 bit len. */\n        if (rioRead(rdb,buf+1,1) == 0) return REDIS_RDB_LENERR;\n        return ((buf[0]&0x3F)<<8)|buf[1];\n    } else {\n        /* Read a 32 bit len. */\n        if (rioRead(rdb,&len,4) == 0) return REDIS_RDB_LENERR;\n        return ntohl(len);\n    }\n}\n\n/* Encodes the \"value\" argument as integer when it fits in the supported ranges\n * for encoded types. If the function successfully encodes the integer, the\n * representation is stored in the buffer pointer to by \"enc\" and the string\n * length is returned. Otherwise 0 is returned. */\nint rdbEncodeInteger(long long value, unsigned char *enc) {\n    if (value >= -(1<<7) && value <= (1<<7)-1) {\n        enc[0] = (REDIS_RDB_ENCVAL<<6)|REDIS_RDB_ENC_INT8;\n        enc[1] = value&0xFF;\n        return 2;\n    } else if (value >= -(1<<15) && value <= (1<<15)-1) {\n        enc[0] = (REDIS_RDB_ENCVAL<<6)|REDIS_RDB_ENC_INT16;\n        enc[1] = value&0xFF;\n        enc[2] = (value>>8)&0xFF;\n        return 3;\n    } else if (value >= -((long long)1<<31) && value <= ((long long)1<<31)-1) {\n        enc[0] = (REDIS_RDB_ENCVAL<<6)|REDIS_RDB_ENC_INT32;\n        enc[1] = value&0xFF;\n        enc[2] = (value>>8)&0xFF;\n        enc[3] = (value>>16)&0xFF;\n        enc[4] = (value>>24)&0xFF;\n        return 5;\n    } else {\n        return 0;\n    }\n}\n\n/* Loads an integer-encoded object with the specified encoding type \"enctype\".\n * If the \"encode\" argument is set the function may return an integer-encoded\n * string object, otherwise it always returns a raw string object. */\nrobj *rdbLoadIntegerObject(rio *rdb, int enctype, int encode) {\n    unsigned char enc[4];\n    long long val;\n\n    if (enctype == REDIS_RDB_ENC_INT8) {\n        if (rioRead(rdb,enc,1) == 0) return NULL;\n        val = (signed char)enc[0];\n    } else if (enctype == REDIS_RDB_ENC_INT16) {\n        uint16_t v;\n        if (rioRead(rdb,enc,2) == 0) return NULL;\n        v = enc[0]|(enc[1]<<8);\n        val = (int16_t)v;\n    } else if (enctype == REDIS_RDB_ENC_INT32) {\n        uint32_t v;\n        if (rioRead(rdb,enc,4) == 0) return NULL;\n        v = enc[0]|(enc[1]<<8)|(enc[2]<<16)|(enc[3]<<24);\n        val = (int32_t)v;\n    } else {\n        val = 0; /* anti-warning */\n        redisPanic(\"Unknown RDB integer encoding type\");\n    }\n    if (encode)\n        return createStringObjectFromLongLong(val);\n    else\n        return createObject(REDIS_STRING,sdsfromlonglong(val));\n}\n\n/* String objects in the form \"2391\" \"-100\" without any space and with a\n * range of values that can fit in an 8, 16 or 32 bit signed value can be\n * encoded as integers to save space */\nint rdbTryIntegerEncoding(char *s, size_t len, unsigned char *enc) {\n    long long value;\n    char *endptr, buf[32];\n\n    /* Check if it's possible to encode this value as a number */\n    value = strtoll(s, &endptr, 10);\n    if (endptr[0] != '\\0') return 0;\n    ll2string(buf,32,value);\n\n    /* If the number converted back into a string is not identical\n     * then it's not possible to encode the string as integer */\n    if (strlen(buf) != len || memcmp(buf,s,len)) return 0;\n\n    return rdbEncodeInteger(value,enc);\n}\n\nint rdbSaveLzfStringObject(rio *rdb, unsigned char *s, size_t len) {\n    size_t comprlen, outlen;\n    unsigned char byte;\n    int n, nwritten = 0;\n    void *out;\n\n    /* We require at least four bytes compression for this to be worth it */\n    if (len <= 4) return 0;\n    outlen = len-4;\n    if ((out = zmalloc(outlen+1)) == NULL) return 0;\n    comprlen = lzf_compress(s, len, out, outlen);\n    if (comprlen == 0) {\n        zfree(out);\n        return 0;\n    }\n    /* Data compressed! Let's save it on disk */\n    byte = (REDIS_RDB_ENCVAL<<6)|REDIS_RDB_ENC_LZF;\n    if ((n = rdbWriteRaw(rdb,&byte,1)) == -1) goto writeerr;\n    nwritten += n;\n\n    if ((n = rdbSaveLen(rdb,comprlen)) == -1) goto writeerr;\n    nwritten += n;\n\n    if ((n = rdbSaveLen(rdb,len)) == -1) goto writeerr;\n    nwritten += n;\n\n    if ((n = rdbWriteRaw(rdb,out,comprlen)) == -1) goto writeerr;\n    nwritten += n;\n\n    zfree(out);\n    return nwritten;\n\nwriteerr:\n    zfree(out);\n    return -1;\n}\n\nrobj *rdbLoadLzfStringObject(rio *rdb) {\n    unsigned int len, clen;\n    unsigned char *c = NULL;\n    sds val = NULL;\n\n    if ((clen = rdbLoadLen(rdb,NULL)) == REDIS_RDB_LENERR) return NULL;\n    if ((len = rdbLoadLen(rdb,NULL)) == REDIS_RDB_LENERR) return NULL;\n    if ((c = zmalloc(clen)) == NULL) goto err;\n    if ((val = sdsnewlen(NULL,len)) == NULL) goto err;\n    if (rioRead(rdb,c,clen) == 0) goto err;\n    if (lzf_decompress(c,clen,val,len) == 0) goto err;\n    zfree(c);\n    return createObject(REDIS_STRING,val);\nerr:\n    zfree(c);\n    sdsfree(val);\n    return NULL;\n}\n\n/* Save a string object as [len][data] on disk. If the object is a string\n * representation of an integer value we try to save it in a special form */\nint rdbSaveRawString(rio *rdb, unsigned char *s, size_t len) {\n    int enclen;\n    int n, nwritten = 0;\n\n    /* Try integer encoding */\n    if (len <= 11) {\n        unsigned char buf[5];\n        if ((enclen = rdbTryIntegerEncoding((char*)s,len,buf)) > 0) {\n            if (rdbWriteRaw(rdb,buf,enclen) == -1) return -1;\n            return enclen;\n        }\n    }\n\n    /* Try LZF compression - under 20 bytes it's unable to compress even\n     * aaaaaaaaaaaaaaaaaa so skip it */\n    if (server.rdb_compression && len > 20) {\n        n = rdbSaveLzfStringObject(rdb,s,len);\n        if (n == -1) return -1;\n        if (n > 0) return n;\n        /* Return value of 0 means data can't be compressed, save the old way */\n    }\n\n    /* Store verbatim */\n    if ((n = rdbSaveLen(rdb,len)) == -1) return -1;\n    nwritten += n;\n    if (len > 0) {\n        if (rdbWriteRaw(rdb,s,len) == -1) return -1;\n        nwritten += len;\n    }\n    return nwritten;\n}\n\n/* Save a long long value as either an encoded string or a string. */\nint rdbSaveLongLongAsStringObject(rio *rdb, long long value) {\n    unsigned char buf[32];\n    int n, nwritten = 0;\n    int enclen = rdbEncodeInteger(value,buf);\n    if (enclen > 0) {\n        return rdbWriteRaw(rdb,buf,enclen);\n    } else {\n        /* Encode as string */\n        enclen = ll2string((char*)buf,32,value);\n        redisAssert(enclen < 32);\n        if ((n = rdbSaveLen(rdb,enclen)) == -1) return -1;\n        nwritten += n;\n        if ((n = rdbWriteRaw(rdb,buf,enclen)) == -1) return -1;\n        nwritten += n;\n    }\n    return nwritten;\n}\n\n/* Like rdbSaveStringObjectRaw() but handle encoded objects */\nint rdbSaveStringObject(rio *rdb, robj *obj) {\n    /* Avoid to decode the object, then encode it again, if the\n     * object is already integer encoded. */\n    if (obj->encoding == REDIS_ENCODING_INT) {\n        return rdbSaveLongLongAsStringObject(rdb,(long)obj->ptr);\n    } else {\n        redisAssertWithInfo(NULL,obj,obj->encoding == REDIS_ENCODING_RAW);\n        return rdbSaveRawString(rdb,obj->ptr,sdslen(obj->ptr));\n    }\n}\n\nrobj *rdbGenericLoadStringObject(rio *rdb, int encode) {\n    int isencoded;\n    uint32_t len;\n    sds val;\n\n    len = rdbLoadLen(rdb,&isencoded);\n    if (isencoded) {\n        switch(len) {\n        case REDIS_RDB_ENC_INT8:\n        case REDIS_RDB_ENC_INT16:\n        case REDIS_RDB_ENC_INT32:\n            return rdbLoadIntegerObject(rdb,len,encode);\n        case REDIS_RDB_ENC_LZF:\n            return rdbLoadLzfStringObject(rdb);\n        default:\n            redisPanic(\"Unknown RDB encoding type\");\n        }\n    }\n\n    if (len == REDIS_RDB_LENERR) return NULL;\n    val = sdsnewlen(NULL,len);\n    if (len && rioRead(rdb,val,len) == 0) {\n        sdsfree(val);\n        return NULL;\n    }\n    return createObject(REDIS_STRING,val);\n}\n\nrobj *rdbLoadStringObject(rio *rdb) {\n    return rdbGenericLoadStringObject(rdb,0);\n}\n\nrobj *rdbLoadEncodedStringObject(rio *rdb) {\n    return rdbGenericLoadStringObject(rdb,1);\n}\n\n/* Save a double value. Doubles are saved as strings prefixed by an unsigned\n * 8 bit integer specifying the length of the representation.\n * This 8 bit integer has special values in order to specify the following\n * conditions:\n * 253: not a number\n * 254: + inf\n * 255: - inf\n */\nint rdbSaveDoubleValue(rio *rdb, double val) {\n    unsigned char buf[128];\n    int len;\n\n    if (isnan(val)) {\n        buf[0] = 253;\n        len = 1;\n    } else if (!isfinite(val)) {\n        len = 1;\n        buf[0] = (val < 0) ? 255 : 254;\n    } else {\n#if (DBL_MANT_DIG >= 52) && (LLONG_MAX == 0x7fffffffffffffffLL)\n        /* Check if the float is in a safe range to be casted into a\n         * long long. We are assuming that long long is 64 bit here.\n         * Also we are assuming that there are no implementations around where\n         * double has precision < 52 bit.\n         *\n         * Under this assumptions we test if a double is inside an interval\n         * where casting to long long is safe. Then using two castings we\n         * make sure the decimal part is zero. If all this is true we use\n         * integer printing function that is much faster. */\n        double min = -4503599627370495; /* (2^52)-1 */\n        double max = 4503599627370496; /* -(2^52) */\n        if (val > min && val < max && val == ((double)((long long)val)))\n            ll2string((char*)buf+1,sizeof(buf)-1,(long long)val);\n        else\n#endif\n            snprintf((char*)buf+1,sizeof(buf)-1,\"%.17g\",val);\n        buf[0] = strlen((char*)buf+1);\n        len = buf[0]+1;\n    }\n    return rdbWriteRaw(rdb,buf,len);\n}\n\n/* For information about double serialization check rdbSaveDoubleValue() */\nint rdbLoadDoubleValue(rio *rdb, double *val) {\n    char buf[256];\n    unsigned char len;\n\n    if (rioRead(rdb,&len,1) == 0) return -1;\n    switch(len) {\n    case 255: *val = R_NegInf; return 0;\n    case 254: *val = R_PosInf; return 0;\n    case 253: *val = R_Nan; return 0;\n    default:\n        if (rioRead(rdb,buf,len) == 0) return -1;\n        buf[len] = '\\0';\n        sscanf(buf, \"%lg\", val);\n        return 0;\n    }\n}\n\n/* Save the object type of object \"o\". */\nint rdbSaveObjectType(rio *rdb, robj *o) {\n    switch (o->type) {\n    case REDIS_STRING:\n        return rdbSaveType(rdb,REDIS_RDB_TYPE_STRING);\n    case REDIS_LIST:\n        if (o->encoding == REDIS_ENCODING_ZIPLIST)\n            return rdbSaveType(rdb,REDIS_RDB_TYPE_LIST_ZIPLIST);\n        else if (o->encoding == REDIS_ENCODING_LINKEDLIST)\n            return rdbSaveType(rdb,REDIS_RDB_TYPE_LIST);\n        else\n            redisPanic(\"Unknown list encoding\");\n    case REDIS_SET:\n        if (o->encoding == REDIS_ENCODING_INTSET)\n            return rdbSaveType(rdb,REDIS_RDB_TYPE_SET_INTSET);\n        else if (o->encoding == REDIS_ENCODING_HT)\n            return rdbSaveType(rdb,REDIS_RDB_TYPE_SET);\n        else\n            redisPanic(\"Unknown set encoding\");\n    case REDIS_ZSET:\n        if (o->encoding == REDIS_ENCODING_ZIPLIST)\n            return rdbSaveType(rdb,REDIS_RDB_TYPE_ZSET_ZIPLIST);\n        else if (o->encoding == REDIS_ENCODING_SKIPLIST)\n            return rdbSaveType(rdb,REDIS_RDB_TYPE_ZSET);\n        else\n            redisPanic(\"Unknown sorted set encoding\");\n    case REDIS_HASH:\n        if (o->encoding == REDIS_ENCODING_ZIPLIST)\n            return rdbSaveType(rdb,REDIS_RDB_TYPE_HASH_ZIPLIST);\n        else if (o->encoding == REDIS_ENCODING_HT)\n            return rdbSaveType(rdb,REDIS_RDB_TYPE_HASH);\n        else\n            redisPanic(\"Unknown hash encoding\");\n    default:\n        redisPanic(\"Unknown object type\");\n    }\n    return -1; /* avoid warning */\n}\n\n/* Use rdbLoadType() to load a TYPE in RDB format, but returns -1 if the\n * type is not specifically a valid Object Type. */\nint rdbLoadObjectType(rio *rdb) {\n    int type;\n    if ((type = rdbLoadType(rdb)) == -1) return -1;\n    if (!rdbIsObjectType(type)) return -1;\n    return type;\n}\n\n/* Save a Redis object. Returns -1 on error, number of bytes written on success. */\nint rdbSaveObject(rio *rdb, robj *o) {\n    int n, nwritten = 0;\n\n    if (o->type == REDIS_STRING) {\n        /* Save a string value */\n        if ((n = rdbSaveStringObject(rdb,o)) == -1) return -1;\n        nwritten += n;\n    } else if (o->type == REDIS_LIST) {\n        /* Save a list value */\n        if (o->encoding == REDIS_ENCODING_ZIPLIST) {\n            size_t l = ziplistBlobLen((unsigned char*)o->ptr);\n\n            if ((n = rdbSaveRawString(rdb,o->ptr,l)) == -1) return -1;\n            nwritten += n;\n        } else if (o->encoding == REDIS_ENCODING_LINKEDLIST) {\n            list *list = o->ptr;\n            listIter li;\n            listNode *ln;\n\n            if ((n = rdbSaveLen(rdb,listLength(list))) == -1) return -1;\n            nwritten += n;\n\n            listRewind(list,&li);\n            while((ln = listNext(&li))) {\n                robj *eleobj = listNodeValue(ln);\n                if ((n = rdbSaveStringObject(rdb,eleobj)) == -1) return -1;\n                nwritten += n;\n            }\n        } else {\n            redisPanic(\"Unknown list encoding\");\n        }\n    } else if (o->type == REDIS_SET) {\n        /* Save a set value */\n        if (o->encoding == REDIS_ENCODING_HT) {\n            dict *set = o->ptr;\n            dictIterator *di = dictGetIterator(set);\n            dictEntry *de;\n\n            if ((n = rdbSaveLen(rdb,dictSize(set))) == -1) return -1;\n            nwritten += n;\n\n            while((de = dictNext(di)) != NULL) {\n                robj *eleobj = dictGetKey(de);\n                if ((n = rdbSaveStringObject(rdb,eleobj)) == -1) return -1;\n                nwritten += n;\n            }\n            dictReleaseIterator(di);\n        } else if (o->encoding == REDIS_ENCODING_INTSET) {\n            size_t l = intsetBlobLen((intset*)o->ptr);\n\n            if ((n = rdbSaveRawString(rdb,o->ptr,l)) == -1) return -1;\n            nwritten += n;\n        } else {\n            redisPanic(\"Unknown set encoding\");\n        }\n    } else if (o->type == REDIS_ZSET) {\n        /* Save a sorted set value */\n        if (o->encoding == REDIS_ENCODING_ZIPLIST) {\n            size_t l = ziplistBlobLen((unsigned char*)o->ptr);\n\n            if ((n = rdbSaveRawString(rdb,o->ptr,l)) == -1) return -1;\n            nwritten += n;\n        } else if (o->encoding == REDIS_ENCODING_SKIPLIST) {\n            zset *zs = o->ptr;\n            dictIterator *di = dictGetIterator(zs->dict);\n            dictEntry *de;\n\n            if ((n = rdbSaveLen(rdb,dictSize(zs->dict))) == -1) return -1;\n            nwritten += n;\n\n            while((de = dictNext(di)) != NULL) {\n                robj *eleobj = dictGetKey(de);\n                double *score = dictGetVal(de);\n\n                if ((n = rdbSaveStringObject(rdb,eleobj)) == -1) return -1;\n                nwritten += n;\n                if ((n = rdbSaveDoubleValue(rdb,*score)) == -1) return -1;\n                nwritten += n;\n            }\n            dictReleaseIterator(di);\n        } else {\n            redisPanic(\"Unknown sorted set encoding\");\n        }\n    } else if (o->type == REDIS_HASH) {\n        /* Save a hash value */\n        if (o->encoding == REDIS_ENCODING_ZIPLIST) {\n            size_t l = ziplistBlobLen((unsigned char*)o->ptr);\n\n            if ((n = rdbSaveRawString(rdb,o->ptr,l)) == -1) return -1;\n            nwritten += n;\n\n        } else if (o->encoding == REDIS_ENCODING_HT) {\n            dictIterator *di = dictGetIterator(o->ptr);\n            dictEntry *de;\n\n            if ((n = rdbSaveLen(rdb,dictSize((dict*)o->ptr))) == -1) return -1;\n            nwritten += n;\n\n            while((de = dictNext(di)) != NULL) {\n                robj *key = dictGetKey(de);\n                robj *val = dictGetVal(de);\n\n                if ((n = rdbSaveStringObject(rdb,key)) == -1) return -1;\n                nwritten += n;\n                if ((n = rdbSaveStringObject(rdb,val)) == -1) return -1;\n                nwritten += n;\n            }\n            dictReleaseIterator(di);\n\n        } else {\n            redisPanic(\"Unknown hash encoding\");\n        }\n\n    } else {\n        redisPanic(\"Unknown object type\");\n    }\n    return nwritten;\n}\n\n/* Return the length the object will have on disk if saved with\n * the rdbSaveObject() function. Currently we use a trick to get\n * this length with very little changes to the code. In the future\n * we could switch to a faster solution. */\noff_t rdbSavedObjectLen(robj *o) {\n    int len = rdbSaveObject(NULL,o);\n    redisAssertWithInfo(NULL,o,len != -1);\n    return len;\n}\n\n/* Save a key-value pair, with expire time, type, key, value.\n * On error -1 is returned.\n * On success if the key was actually saved 1 is returned, otherwise 0\n * is returned (the key was already expired). */\nint rdbSaveKeyValuePair(rio *rdb, robj *key, robj *val,\n                        long long expiretime, long long now)\n{\n    /* Save the expire time */\n    if (expiretime != -1) {\n        /* If this key is already expired skip it */\n        if (expiretime < now) return 0;\n        if (rdbSaveType(rdb,REDIS_RDB_OPCODE_EXPIRETIME_MS) == -1) return -1;\n        if (rdbSaveMillisecondTime(rdb,expiretime) == -1) return -1;\n    }\n\n    /* Save type, key, value */\n    if (rdbSaveObjectType(rdb,val) == -1) return -1;\n    if (rdbSaveStringObject(rdb,key) == -1) return -1;\n    if (rdbSaveObject(rdb,val) == -1) return -1;\n    return 1;\n}\n\n/* Produces a dump of the database in RDB format sending it to the specified\n * Redis I/O channel. On success REDIS_OK is returned, otherwise REDIS_ERR\n * is returned and part of the output, or all the output, can be\n * missing because of I/O errors.\n *\n * When the function returns REDIS_ERR and if 'error' is not NULL, the\n * integer pointed by 'error' is set to the value of errno just after the I/O\n * error. */\nint rdbSaveRio(rio *rdb, int *error) {\n    dictIterator *di = NULL;\n    dictEntry *de;\n    char magic[10];\n    int j;\n    long long now = mstime();\n    uint64_t cksum;\n\n    if (server.rdb_checksum)\n        rdb->update_cksum = rioGenericUpdateChecksum;\n    snprintf(magic,sizeof(magic),\"REDIS%04d\",REDIS_RDB_VERSION);\n    if (rdbWriteRaw(rdb,magic,9) == -1) goto werr;\n\n    for (j = 0; j < server.dbnum; j++) {\n        redisDb *db = server.db+j;\n        dict *d = db->dict;\n        if (dictSize(d) == 0) continue;\n        di = dictGetSafeIterator(d);\n        if (!di) return REDIS_ERR;\n\n        /* Write the SELECT DB opcode */\n        if (rdbSaveType(rdb,REDIS_RDB_OPCODE_SELECTDB) == -1) goto werr;\n        if (rdbSaveLen(rdb,j) == -1) goto werr;\n\n        /* Iterate this DB writing every entry */\n        while((de = dictNext(di)) != NULL) {\n            sds keystr = dictGetKey(de);\n            robj key, *o = dictGetVal(de);\n            long long expire;\n\n            initStaticStringObject(key,keystr);\n            expire = getExpire(db,&key);\n            if (rdbSaveKeyValuePair(rdb,&key,o,expire,now) == -1) goto werr;\n        }\n        dictReleaseIterator(di);\n    }\n    di = NULL; /* So that we don't release it again on error. */\n\n    /* EOF opcode */\n    if (rdbSaveType(rdb,REDIS_RDB_OPCODE_EOF) == -1) goto werr;\n\n    /* CRC64 checksum. It will be zero if checksum computation is disabled, the\n     * loading code skips the check in this case. */\n    cksum = rdb->cksum;\n    memrev64ifbe(&cksum);\n    if (rioWrite(rdb,&cksum,8) == 0) goto werr;\n    return REDIS_OK;\n\nwerr:\n    if (error) *error = errno;\n    if (di) dictReleaseIterator(di);\n    return REDIS_ERR;\n}\n\n/* This is just a wrapper to rdbSaveRio() that additionally adds a prefix\n * and a suffix to the generated RDB dump. The prefix is:\n *\n * $EOF:<40 bytes unguessable hex string>\\r\\n\n *\n * While the suffix is the 40 bytes hex string we announced in the prefix.\n * This way processes receiving the payload can understand when it ends\n * without doing any processing of the content. */\nint rdbSaveRioWithEOFMark(rio *rdb, int *error) {\n    char eofmark[REDIS_EOF_MARK_SIZE];\n\n    getRandomHexChars(eofmark,REDIS_EOF_MARK_SIZE);\n    if (error) *error = 0;\n    if (rioWrite(rdb,\"$EOF:\",5) == 0) goto werr;\n    if (rioWrite(rdb,eofmark,REDIS_EOF_MARK_SIZE) == 0) goto werr;\n    if (rioWrite(rdb,\"\\r\\n\",2) == 0) goto werr;\n    if (rdbSaveRio(rdb,error) == REDIS_ERR) goto werr;\n    if (rioWrite(rdb,eofmark,REDIS_EOF_MARK_SIZE) == 0) goto werr;\n    return REDIS_OK;\n\nwerr: /* Write error. */\n    /* Set 'error' only if not already set by rdbSaveRio() call. */\n    if (error && *error == 0) *error = errno;\n    return REDIS_ERR;\n}\n\n/* Save the DB on disk. Return REDIS_ERR on error, REDIS_OK on success. */\nint rdbSave(char *filename) {\n    char tmpfile[256];\n    FILE *fp;\n    rio rdb;\n    int error;\n\n    snprintf(tmpfile,256,\"temp-%d.rdb\", (int) getpid());\n    fp = fopen(tmpfile,\"w\");\n    if (!fp) {\n        redisLog(REDIS_WARNING, \"Failed opening .rdb for saving: %s\",\n            strerror(errno));\n        return REDIS_ERR;\n    }\n\n    rioInitWithFile(&rdb,fp);\n    if (rdbSaveRio(&rdb,&error) == REDIS_ERR) {\n        errno = error;\n        goto werr;\n    }\n\n    /* Make sure data will not remain on the OS's output buffers */\n    if (fflush(fp) == EOF) goto werr;\n    if (fsync(fileno(fp)) == -1) goto werr;\n    if (fclose(fp) == EOF) goto werr;\n\n    /* Use RENAME to make sure the DB file is changed atomically only\n     * if the generate DB file is ok. */\n    if (rename(tmpfile,filename) == -1) {\n        redisLog(REDIS_WARNING,\"Error moving temp DB file on the final destination: %s\", strerror(errno));\n        unlink(tmpfile);\n        return REDIS_ERR;\n    }\n    redisLog(REDIS_NOTICE,\"DB saved on disk\");\n    server.dirty = 0;\n    server.lastsave = time(NULL);\n    server.lastbgsave_status = REDIS_OK;\n    return REDIS_OK;\n\nwerr:\n    fclose(fp);\n    unlink(tmpfile);\n    redisLog(REDIS_WARNING,\"Write error saving DB on disk: %s\", strerror(errno));\n    return REDIS_ERR;\n}\n\nint rdbSaveBackground(char *filename) {\n    pid_t childpid;\n    long long start;\n\n    if (server.rdb_child_pid != -1) return REDIS_ERR;\n\n    server.dirty_before_bgsave = server.dirty;\n    server.lastbgsave_try = time(NULL);\n\n    start = ustime();\n    if ((childpid = fork()) == 0) {\n        int retval;\n\n        /* Child */\n        closeListeningSockets(0);\n        redisSetProcTitle(\"redis-rdb-bgsave\");\n        retval = rdbSave(filename);\n        if (retval == REDIS_OK) {\n            size_t private_dirty = zmalloc_get_private_dirty();\n\n            if (private_dirty) {\n                redisLog(REDIS_NOTICE,\n                    \"RDB: %zu MB of memory used by copy-on-write\",\n                    private_dirty/(1024*1024));\n            }\n        }\n        exitFromChild((retval == REDIS_OK) ? 0 : 1);\n    } else {\n        /* Parent */\n        server.stat_fork_time = ustime()-start;\n        server.stat_fork_rate = (double) zmalloc_used_memory() * 1000000 / server.stat_fork_time / (1024*1024*1024); /* GB per second. */\n        latencyAddSampleIfNeeded(\"fork\",server.stat_fork_time/1000);\n        if (childpid == -1) {\n            server.lastbgsave_status = REDIS_ERR;\n            redisLog(REDIS_WARNING,\"Can't save in background: fork: %s\",\n                strerror(errno));\n            return REDIS_ERR;\n        }\n        redisLog(REDIS_NOTICE,\"Background saving started by pid %d\",childpid);\n        server.rdb_save_time_start = time(NULL);\n        server.rdb_child_pid = childpid;\n        server.rdb_child_type = REDIS_RDB_CHILD_TYPE_DISK;\n        updateDictResizePolicy();\n        return REDIS_OK;\n    }\n    return REDIS_OK; /* unreached */\n}\n\nvoid rdbRemoveTempFile(pid_t childpid) {\n    char tmpfile[256];\n\n    snprintf(tmpfile,sizeof(tmpfile),\"temp-%d.rdb\", (int) childpid);\n    unlink(tmpfile);\n}\n\n/* Load a Redis object of the specified type from the specified file.\n * On success a newly allocated object is returned, otherwise NULL. */\nrobj *rdbLoadObject(int rdbtype, rio *rdb) {\n    robj *o, *ele, *dec;\n    size_t len;\n    unsigned int i;\n\n    if (rdbtype == REDIS_RDB_TYPE_STRING) {\n        /* Read string value */\n        if ((o = rdbLoadEncodedStringObject(rdb)) == NULL) return NULL;\n        o = tryObjectEncoding(o);\n    } else if (rdbtype == REDIS_RDB_TYPE_LIST) {\n        /* Read list value */\n        if ((len = rdbLoadLen(rdb,NULL)) == REDIS_RDB_LENERR) return NULL;\n\n        /* Use a real list when there are too many entries */\n        if (len > server.list_max_ziplist_entries) {\n            o = createListObject();\n        } else {\n            o = createZiplistObject();\n        }\n\n        /* Load every single element of the list */\n        while(len--) {\n            if ((ele = rdbLoadEncodedStringObject(rdb)) == NULL) return NULL;\n\n            /* If we are using a ziplist and the value is too big, convert\n             * the object to a real list. */\n            if (o->encoding == REDIS_ENCODING_ZIPLIST &&\n                ele->encoding == REDIS_ENCODING_RAW &&\n                sdslen(ele->ptr) > server.list_max_ziplist_value)\n                    listTypeConvert(o,REDIS_ENCODING_LINKEDLIST);\n\n            if (o->encoding == REDIS_ENCODING_ZIPLIST) {\n                dec = getDecodedObject(ele);\n                o->ptr = ziplistPush(o->ptr,dec->ptr,sdslen(dec->ptr),REDIS_TAIL);\n                decrRefCount(dec);\n                decrRefCount(ele);\n            } else {\n                ele = tryObjectEncoding(ele);\n                listAddNodeTail(o->ptr,ele);\n            }\n        }\n    } else if (rdbtype == REDIS_RDB_TYPE_SET) {\n        /* Read list/set value */\n        if ((len = rdbLoadLen(rdb,NULL)) == REDIS_RDB_LENERR) return NULL;\n\n        /* Use a regular set when there are too many entries. */\n        if (len > server.set_max_intset_entries) {\n            o = createSetObject();\n            /* It's faster to expand the dict to the right size asap in order\n             * to avoid rehashing */\n            if (len > DICT_HT_INITIAL_SIZE)\n                dictExpand(o->ptr,len);\n        } else {\n            o = createIntsetObject();\n        }\n\n        /* Load every single element of the list/set */\n        for (i = 0; i < len; i++) {\n            long long llval;\n            if ((ele = rdbLoadEncodedStringObject(rdb)) == NULL) return NULL;\n            ele = tryObjectEncoding(ele);\n\n            if (o->encoding == REDIS_ENCODING_INTSET) {\n                /* Fetch integer value from element */\n                if (isObjectRepresentableAsLongLong(ele,&llval) == REDIS_OK) {\n                    o->ptr = intsetAdd(o->ptr,llval,NULL);\n                } else {\n                    setTypeConvert(o,REDIS_ENCODING_HT);\n                    dictExpand(o->ptr,len);\n                }\n            }\n\n            /* This will also be called when the set was just converted\n             * to regular hash table encoded set */\n            if (o->encoding == REDIS_ENCODING_HT) {\n                dictAdd((dict*)o->ptr,ele,NULL);\n            } else {\n                decrRefCount(ele);\n            }\n        }\n    } else if (rdbtype == REDIS_RDB_TYPE_ZSET) {\n        /* Read list/set value */\n        size_t zsetlen;\n        size_t maxelelen = 0;\n        zset *zs;\n\n        if ((zsetlen = rdbLoadLen(rdb,NULL)) == REDIS_RDB_LENERR) return NULL;\n        o = createZsetObject();\n        zs = o->ptr;\n\n        /* Load every single element of the list/set */\n        while(zsetlen--) {\n            robj *ele;\n            double score;\n            zskiplistNode *znode;\n\n            if ((ele = rdbLoadEncodedStringObject(rdb)) == NULL) return NULL;\n            ele = tryObjectEncoding(ele);\n            if (rdbLoadDoubleValue(rdb,&score) == -1) return NULL;\n\n            /* Don't care about integer-encoded strings. */\n            if (ele->encoding == REDIS_ENCODING_RAW &&\n                sdslen(ele->ptr) > maxelelen)\n                    maxelelen = sdslen(ele->ptr);\n\n            znode = zslInsert(zs->zsl,score,ele);\n            dictAdd(zs->dict,ele,&znode->score);\n            incrRefCount(ele); /* added to skiplist */\n        }\n\n        /* Convert *after* loading, since sorted sets are not stored ordered. */\n        if (zsetLength(o) <= server.zset_max_ziplist_entries &&\n            maxelelen <= server.zset_max_ziplist_value)\n                zsetConvert(o,REDIS_ENCODING_ZIPLIST);\n    } else if (rdbtype == REDIS_RDB_TYPE_HASH) {\n        size_t len;\n        int ret;\n\n        len = rdbLoadLen(rdb, NULL);\n        if (len == REDIS_RDB_LENERR) return NULL;\n\n        o = createHashObject();\n\n        /* Too many entries? Use a hash table. */\n        if (len > server.hash_max_ziplist_entries)\n            hashTypeConvert(o, REDIS_ENCODING_HT);\n\n        /* Load every field and value into the ziplist */\n        while (o->encoding == REDIS_ENCODING_ZIPLIST && len > 0) {\n            robj *field, *value;\n\n            len--;\n            /* Load raw strings */\n            field = rdbLoadStringObject(rdb);\n            if (field == NULL) return NULL;\n            redisAssert(field->encoding == REDIS_ENCODING_RAW);\n            value = rdbLoadStringObject(rdb);\n            if (value == NULL) return NULL;\n            redisAssert(field->encoding == REDIS_ENCODING_RAW);\n\n            /* Add pair to ziplist */\n            o->ptr = ziplistPush(o->ptr, field->ptr, sdslen(field->ptr), ZIPLIST_TAIL);\n            o->ptr = ziplistPush(o->ptr, value->ptr, sdslen(value->ptr), ZIPLIST_TAIL);\n            /* Convert to hash table if size threshold is exceeded */\n            if (sdslen(field->ptr) > server.hash_max_ziplist_value ||\n                sdslen(value->ptr) > server.hash_max_ziplist_value)\n            {\n                decrRefCount(field);\n                decrRefCount(value);\n                hashTypeConvert(o, REDIS_ENCODING_HT);\n                break;\n            }\n            decrRefCount(field);\n            decrRefCount(value);\n        }\n\n        /* Load remaining fields and values into the hash table */\n        while (o->encoding == REDIS_ENCODING_HT && len > 0) {\n            robj *field, *value;\n\n            len--;\n            /* Load encoded strings */\n            field = rdbLoadEncodedStringObject(rdb);\n            if (field == NULL) return NULL;\n            value = rdbLoadEncodedStringObject(rdb);\n            if (value == NULL) return NULL;\n\n            field = tryObjectEncoding(field);\n            value = tryObjectEncoding(value);\n\n            /* Add pair to hash table */\n            ret = dictAdd((dict*)o->ptr, field, value);\n            redisAssert(ret == DICT_OK);\n        }\n\n        /* All pairs should be read by now */\n        redisAssert(len == 0);\n\n    } else if (rdbtype == REDIS_RDB_TYPE_HASH_ZIPMAP  ||\n               rdbtype == REDIS_RDB_TYPE_LIST_ZIPLIST ||\n               rdbtype == REDIS_RDB_TYPE_SET_INTSET   ||\n               rdbtype == REDIS_RDB_TYPE_ZSET_ZIPLIST ||\n               rdbtype == REDIS_RDB_TYPE_HASH_ZIPLIST)\n    {\n        robj *aux = rdbLoadStringObject(rdb);\n\n        if (aux == NULL) return NULL;\n        o = createObject(REDIS_STRING,NULL); /* string is just placeholder */\n        o->ptr = zmalloc(sdslen(aux->ptr));\n        memcpy(o->ptr,aux->ptr,sdslen(aux->ptr));\n        decrRefCount(aux);\n\n        /* Fix the object encoding, and make sure to convert the encoded\n         * data type into the base type if accordingly to the current\n         * configuration there are too many elements in the encoded data\n         * type. Note that we only check the length and not max element\n         * size as this is an O(N) scan. Eventually everything will get\n         * converted. */\n        switch(rdbtype) {\n            case REDIS_RDB_TYPE_HASH_ZIPMAP:\n                /* Convert to ziplist encoded hash. This must be deprecated\n                 * when loading dumps created by Redis 2.4 gets deprecated. */\n                {\n                    unsigned char *zl = ziplistNew();\n                    unsigned char *zi = zipmapRewind(o->ptr);\n                    unsigned char *fstr, *vstr;\n                    unsigned int flen, vlen;\n                    unsigned int maxlen = 0;\n\n                    while ((zi = zipmapNext(zi, &fstr, &flen, &vstr, &vlen)) != NULL) {\n                        if (flen > maxlen) maxlen = flen;\n                        if (vlen > maxlen) maxlen = vlen;\n                        zl = ziplistPush(zl, fstr, flen, ZIPLIST_TAIL);\n                        zl = ziplistPush(zl, vstr, vlen, ZIPLIST_TAIL);\n                    }\n\n                    zfree(o->ptr);\n                    o->ptr = zl;\n                    o->type = REDIS_HASH;\n                    o->encoding = REDIS_ENCODING_ZIPLIST;\n\n                    if (hashTypeLength(o) > server.hash_max_ziplist_entries ||\n                        maxlen > server.hash_max_ziplist_value)\n                    {\n                        hashTypeConvert(o, REDIS_ENCODING_HT);\n                    }\n                }\n                break;\n            case REDIS_RDB_TYPE_LIST_ZIPLIST:\n                o->type = REDIS_LIST;\n                o->encoding = REDIS_ENCODING_ZIPLIST;\n                if (ziplistLen(o->ptr) > server.list_max_ziplist_entries)\n                    listTypeConvert(o,REDIS_ENCODING_LINKEDLIST);\n                break;\n            case REDIS_RDB_TYPE_SET_INTSET:\n                o->type = REDIS_SET;\n                o->encoding = REDIS_ENCODING_INTSET;\n                if (intsetLen(o->ptr) > server.set_max_intset_entries)\n                    setTypeConvert(o,REDIS_ENCODING_HT);\n                break;\n            case REDIS_RDB_TYPE_ZSET_ZIPLIST:\n                o->type = REDIS_ZSET;\n                o->encoding = REDIS_ENCODING_ZIPLIST;\n                if (zsetLength(o) > server.zset_max_ziplist_entries)\n                    zsetConvert(o,REDIS_ENCODING_SKIPLIST);\n                break;\n            case REDIS_RDB_TYPE_HASH_ZIPLIST:\n                o->type = REDIS_HASH;\n                o->encoding = REDIS_ENCODING_ZIPLIST;\n                if (hashTypeLength(o) > server.hash_max_ziplist_entries)\n                    hashTypeConvert(o, REDIS_ENCODING_HT);\n                break;\n            default:\n                redisPanic(\"Unknown encoding\");\n                break;\n        }\n    } else {\n        redisPanic(\"Unknown object type\");\n    }\n    return o;\n}\n\n/* Mark that we are loading in the global state and setup the fields\n * needed to provide loading stats. */\nvoid startLoading(FILE *fp) {\n    struct stat sb;\n\n    /* Load the DB */\n    server.loading = 1;\n    server.loading_start_time = time(NULL);\n    server.loading_loaded_bytes = 0;\n    if (fstat(fileno(fp), &sb) == -1) {\n        server.loading_total_bytes = 0;\n    } else {\n        server.loading_total_bytes = sb.st_size;\n    }\n}\n\n/* Refresh the loading progress info */\nvoid loadingProgress(off_t pos) {\n    server.loading_loaded_bytes = pos;\n    if (server.stat_peak_memory < zmalloc_used_memory())\n        server.stat_peak_memory = zmalloc_used_memory();\n}\n\n/* Loading finished */\nvoid stopLoading(void) {\n    server.loading = 0;\n}\n\n/* Track loading progress in order to serve client's from time to time\n   and if needed calculate rdb checksum  */\nvoid rdbLoadProgressCallback(rio *r, const void *buf, size_t len) {\n    if (server.rdb_checksum)\n        rioGenericUpdateChecksum(r, buf, len);\n    if (server.loading_process_events_interval_bytes &&\n        (r->processed_bytes + len)/server.loading_process_events_interval_bytes > r->processed_bytes/server.loading_process_events_interval_bytes)\n    {\n        /* The DB can take some non trivial amount of time to load. Update\n         * our cached time since it is used to create and update the last\n         * interaction time with clients and for other important things. */\n        updateCachedTime();\n        if (server.masterhost && server.repl_state == REDIS_REPL_TRANSFER)\n            replicationSendNewlineToMaster();\n        loadingProgress(r->processed_bytes);\n        processEventsWhileBlocked();\n    }\n}\n\nint rdbLoad(char *filename) {\n    uint32_t dbid;\n    int type, rdbver;\n    redisDb *db = server.db+0;\n    char buf[1024];\n    long long expiretime, now = mstime();\n    FILE *fp;\n    rio rdb;\n\n    if ((fp = fopen(filename,\"r\")) == NULL) return REDIS_ERR;\n\n    rioInitWithFile(&rdb,fp);\n    rdb.update_cksum = rdbLoadProgressCallback;\n    rdb.max_processing_chunk = server.loading_process_events_interval_bytes;\n    if (rioRead(&rdb,buf,9) == 0) goto eoferr;\n    buf[9] = '\\0';\n    if (memcmp(buf,\"REDIS\",5) != 0) {\n        fclose(fp);\n        redisLog(REDIS_WARNING,\"Wrong signature trying to load DB from file\");\n        errno = EINVAL;\n        return REDIS_ERR;\n    }\n    rdbver = atoi(buf+5);\n    if (rdbver < 1 || rdbver > REDIS_RDB_VERSION) {\n        fclose(fp);\n        redisLog(REDIS_WARNING,\"Can't handle RDB format version %d\",rdbver);\n        errno = EINVAL;\n        return REDIS_ERR;\n    }\n\n    startLoading(fp);\n    while(1) {\n        robj *key, *val;\n        expiretime = -1;\n\n        /* Read type. */\n        if ((type = rdbLoadType(&rdb)) == -1) goto eoferr;\n        if (type == REDIS_RDB_OPCODE_EXPIRETIME) {\n            if ((expiretime = rdbLoadTime(&rdb)) == -1) goto eoferr;\n            /* We read the time so we need to read the object type again. */\n            if ((type = rdbLoadType(&rdb)) == -1) goto eoferr;\n            /* the EXPIRETIME opcode specifies time in seconds, so convert\n             * into milliseconds. */\n            expiretime *= 1000;\n        } else if (type == REDIS_RDB_OPCODE_EXPIRETIME_MS) {\n            /* Milliseconds precision expire times introduced with RDB\n             * version 3. */\n            if ((expiretime = rdbLoadMillisecondTime(&rdb)) == -1) goto eoferr;\n            /* We read the time so we need to read the object type again. */\n            if ((type = rdbLoadType(&rdb)) == -1) goto eoferr;\n        }\n\n        if (type == REDIS_RDB_OPCODE_EOF)\n            break;\n\n        /* Handle SELECT DB opcode as a special case */\n        if (type == REDIS_RDB_OPCODE_SELECTDB) {\n            if ((dbid = rdbLoadLen(&rdb,NULL)) == REDIS_RDB_LENERR)\n                goto eoferr;\n            if (dbid >= (unsigned)server.dbnum) {\n                redisLog(REDIS_WARNING,\"FATAL: Data file was created with a Redis server configured to handle more than %d databases. Exiting\\n\", server.dbnum);\n                exit(1);\n            }\n            db = server.db+dbid;\n            continue;\n        }\n        /* Read key */\n        if ((key = rdbLoadStringObject(&rdb)) == NULL) goto eoferr;\n        /* Read value */\n        if ((val = rdbLoadObject(type,&rdb)) == NULL) goto eoferr;\n        /* Check if the key already expired. This function is used when loading\n         * an RDB file from disk, either at startup, or when an RDB was\n         * received from the master. In the latter case, the master is\n         * responsible for key expiry. If we would expire keys here, the\n         * snapshot taken by the master may not be reflected on the slave. */\n        if (server.masterhost == NULL && expiretime != -1 && expiretime < now) {\n            decrRefCount(key);\n            decrRefCount(val);\n            continue;\n        }\n        /* Add the new object in the hash table */\n        dbAdd(db,key,val);\n\n        /* Set the expire time if needed */\n        if (expiretime != -1) setExpire(db,key,expiretime);\n\n        decrRefCount(key);\n    }\n    /* Verify the checksum if RDB version is >= 5 */\n    if (rdbver >= 5 && server.rdb_checksum) {\n        uint64_t cksum, expected = rdb.cksum;\n\n        if (rioRead(&rdb,&cksum,8) == 0) goto eoferr;\n        memrev64ifbe(&cksum);\n        if (cksum == 0) {\n            redisLog(REDIS_WARNING,\"RDB file was saved with checksum disabled: no check performed.\");\n        } else if (cksum != expected) {\n            redisLog(REDIS_WARNING,\"Wrong RDB checksum. Aborting now.\");\n            exit(1);\n        }\n    }\n\n    fclose(fp);\n    stopLoading();\n    return REDIS_OK;\n\neoferr: /* unexpected end of file is handled here with a fatal exit */\n    redisLog(REDIS_WARNING,\"Short read or OOM loading DB. Unrecoverable error, aborting now.\");\n    exit(1);\n    return REDIS_ERR; /* Just to avoid warning */\n}\n\n/* A background saving child (BGSAVE) terminated its work. Handle this.\n * This function covers the case of actual BGSAVEs. */\nvoid backgroundSaveDoneHandlerDisk(int exitcode, int bysignal) {\n    if (!bysignal && exitcode == 0) {\n        redisLog(REDIS_NOTICE,\n            \"Background saving terminated with success\");\n        server.dirty = server.dirty - server.dirty_before_bgsave;\n        server.lastsave = time(NULL);\n        server.lastbgsave_status = REDIS_OK;\n    } else if (!bysignal && exitcode != 0) {\n        redisLog(REDIS_WARNING, \"Background saving error\");\n        server.lastbgsave_status = REDIS_ERR;\n    } else {\n        mstime_t latency;\n\n        redisLog(REDIS_WARNING,\n            \"Background saving terminated by signal %d\", bysignal);\n        latencyStartMonitor(latency);\n        rdbRemoveTempFile(server.rdb_child_pid);\n        latencyEndMonitor(latency);\n        latencyAddSampleIfNeeded(\"rdb-unlink-temp-file\",latency);\n        /* SIGUSR1 is whitelisted, so we have a way to kill a child without\n         * tirggering an error conditon. */\n        if (bysignal != SIGUSR1)\n            server.lastbgsave_status = REDIS_ERR;\n    }\n    server.rdb_child_pid = -1;\n    server.rdb_child_type = REDIS_RDB_CHILD_TYPE_NONE;\n    server.rdb_save_time_last = time(NULL)-server.rdb_save_time_start;\n    server.rdb_save_time_start = -1;\n    /* Possibly there are slaves waiting for a BGSAVE in order to be served\n     * (the first stage of SYNC is a bulk transfer of dump.rdb) */\n    updateSlavesWaitingBgsave((!bysignal && exitcode == 0) ? REDIS_OK : REDIS_ERR, REDIS_RDB_CHILD_TYPE_DISK);\n}\n\n/* A background saving child (BGSAVE) terminated its work. Handle this.\n * This function covers the case of RDB -> Salves socket transfers for\n * diskless replication. */\nvoid backgroundSaveDoneHandlerSocket(int exitcode, int bysignal) {\n    uint64_t *ok_slaves;\n\n    if (!bysignal && exitcode == 0) {\n        redisLog(REDIS_NOTICE,\n            \"Background RDB transfer terminated with success\");\n    } else if (!bysignal && exitcode != 0) {\n        redisLog(REDIS_WARNING, \"Background transfer error\");\n    } else {\n        redisLog(REDIS_WARNING,\n            \"Background transfer terminated by signal %d\", bysignal);\n    }\n    server.rdb_child_pid = -1;\n    server.rdb_child_type = REDIS_RDB_CHILD_TYPE_NONE;\n    server.rdb_save_time_start = -1;\n\n    /* If the child returns an OK exit code, read the set of slave client\n     * IDs and the associated status code. We'll terminate all the slaves\n     * in error state.\n     *\n     * If the process returned an error, consider the list of slaves that\n     * can continue to be emtpy, so that it's just a special case of the\n     * normal code path. */\n    ok_slaves = zmalloc(sizeof(uint64_t)); /* Make space for the count. */\n    ok_slaves[0] = 0;\n    if (!bysignal && exitcode == 0) {\n        int readlen = sizeof(uint64_t);\n\n        if (read(server.rdb_pipe_read_result_from_child, ok_slaves, readlen) ==\n                 readlen)\n        {\n            readlen = ok_slaves[0]*sizeof(uint64_t)*2;\n\n            /* Make space for enough elements as specified by the first\n             * uint64_t element in the array. */\n            ok_slaves = zrealloc(ok_slaves,sizeof(uint64_t)+readlen);\n            if (readlen &&\n                read(server.rdb_pipe_read_result_from_child, ok_slaves+1,\n                     readlen) != readlen)\n            {\n                ok_slaves[0] = 0;\n            }\n        }\n    }\n\n    close(server.rdb_pipe_read_result_from_child);\n    close(server.rdb_pipe_write_result_to_parent);\n\n    /* We can continue the replication process with all the slaves that\n     * correctly received the full payload. Others are terminated. */\n    listNode *ln;\n    listIter li;\n\n    listRewind(server.slaves,&li);\n    while((ln = listNext(&li))) {\n        redisClient *slave = ln->value;\n\n        if (slave->replstate == REDIS_REPL_WAIT_BGSAVE_END) {\n            uint64_t j;\n            int errorcode = 0;\n\n            /* Search for the slave ID in the reply. In order for a slave to\n             * continue the replication process, we need to find it in the list,\n             * and it must have an error code set to 0 (which means success). */\n            for (j = 0; j < ok_slaves[0]; j++) {\n                if (slave->id == ok_slaves[2*j+1]) {\n                    errorcode = ok_slaves[2*j+2];\n                    break; /* Found in slaves list. */\n                }\n            }\n            if (j == ok_slaves[0] || errorcode != 0) {\n                redisLog(REDIS_WARNING,\n                \"Closing slave %s: child->slave RDB transfer failed: %s\",\n                    replicationGetSlaveName(slave),\n                    (errorcode == 0) ? \"RDB transfer child aborted\"\n                                     : strerror(errorcode));\n                freeClient(slave);\n            } else {\n                redisLog(REDIS_WARNING,\n                \"Slave %s correctly received the streamed RDB file.\",\n                    replicationGetSlaveName(slave));\n                /* Restore the socket as non-blocking. */\n                anetNonBlock(NULL,slave->fd);\n                anetSendTimeout(NULL,slave->fd,0);\n            }\n        }\n    }\n    zfree(ok_slaves);\n\n    updateSlavesWaitingBgsave((!bysignal && exitcode == 0) ? REDIS_OK : REDIS_ERR, REDIS_RDB_CHILD_TYPE_SOCKET);\n}\n\n/* When a background RDB saving/transfer terminates, call the right handler. */\nvoid backgroundSaveDoneHandler(int exitcode, int bysignal) {\n    switch(server.rdb_child_type) {\n    case REDIS_RDB_CHILD_TYPE_DISK:\n        backgroundSaveDoneHandlerDisk(exitcode,bysignal);\n        break;\n    case REDIS_RDB_CHILD_TYPE_SOCKET:\n        backgroundSaveDoneHandlerSocket(exitcode,bysignal);\n        break;\n    default:\n        redisPanic(\"Unknown RDB child type.\");\n        break;\n    }\n}\n\n/* Spawn an RDB child that writes the RDB to the sockets of the slaves\n * that are currently in REDIS_REPL_WAIT_BGSAVE_START state. */\nint rdbSaveToSlavesSockets(void) {\n    int *fds;\n    uint64_t *clientids;\n    int numfds;\n    listNode *ln;\n    listIter li;\n    pid_t childpid;\n    long long start;\n    int pipefds[2];\n\n    if (server.rdb_child_pid != -1) return REDIS_ERR;\n\n    /* Before to fork, create a pipe that will be used in order to\n     * send back to the parent the IDs of the slaves that successfully\n     * received all the writes. */\n    if (pipe(pipefds) == -1) return REDIS_ERR;\n    server.rdb_pipe_read_result_from_child = pipefds[0];\n    server.rdb_pipe_write_result_to_parent = pipefds[1];\n\n    /* Collect the file descriptors of the slaves we want to transfer\n     * the RDB to, which are i WAIT_BGSAVE_START state. */\n    fds = zmalloc(sizeof(int)*listLength(server.slaves));\n    /* We also allocate an array of corresponding client IDs. This will\n     * be useful for the child process in order to build the report\n     * (sent via unix pipe) that will be sent to the parent. */\n    clientids = zmalloc(sizeof(uint64_t)*listLength(server.slaves));\n    numfds = 0;\n\n    listRewind(server.slaves,&li);\n    while((ln = listNext(&li))) {\n        redisClient *slave = ln->value;\n\n        if (slave->replstate == REDIS_REPL_WAIT_BGSAVE_START) {\n            clientids[numfds] = slave->id;\n            fds[numfds++] = slave->fd;\n            slave->replstate = REDIS_REPL_WAIT_BGSAVE_END;\n            /* Put the socket in non-blocking mode to simplify RDB transfer.\n             * We'll restore it when the children returns (since duped socket\n             * will share the O_NONBLOCK attribute with the parent). */\n            anetBlock(NULL,slave->fd);\n            anetSendTimeout(NULL,slave->fd,server.repl_timeout*1000);\n        }\n    }\n\n    /* Create the child process. */\n    start = ustime();\n    if ((childpid = fork()) == 0) {\n        /* Child */\n        int retval;\n        rio slave_sockets;\n\n        rioInitWithFdset(&slave_sockets,fds,numfds);\n        zfree(fds);\n\n        closeListeningSockets(0);\n        redisSetProcTitle(\"redis-rdb-to-slaves\");\n\n        retval = rdbSaveRioWithEOFMark(&slave_sockets,NULL);\n        if (retval == REDIS_OK && rioFlush(&slave_sockets) == 0)\n            retval = REDIS_ERR;\n\n        if (retval == REDIS_OK) {\n            size_t private_dirty = zmalloc_get_private_dirty();\n\n            if (private_dirty) {\n                redisLog(REDIS_NOTICE,\n                    \"RDB: %zu MB of memory used by copy-on-write\",\n                    private_dirty/(1024*1024));\n            }\n\n            /* If we are returning OK, at least one slave was served\n             * with the RDB file as expected, so we need to send a report\n             * to the parent via the pipe. The format of the message is:\n             *\n             * <len> <slave[0].id> <slave[0].error> ...\n             *\n             * len, slave IDs, and slave errors, are all uint64_t integers,\n             * so basically the reply is composed of 64 bits for the len field\n             * plus 2 additional 64 bit integers for each entry, for a total\n             * of 'len' entries.\n             *\n             * The 'id' represents the slave's client ID, so that the master\n             * can match the report with a specific slave, and 'error' is\n             * set to 0 if the replication process terminated with a success\n             * or the error code if an error occurred. */\n            void *msg = zmalloc(sizeof(uint64_t)*(1+2*numfds));\n            uint64_t *len = msg;\n            uint64_t *ids = len+1;\n            int j, msglen;\n\n            *len = numfds;\n            for (j = 0; j < numfds; j++) {\n                *ids++ = clientids[j];\n                *ids++ = slave_sockets.io.fdset.state[j];\n            }\n\n            /* Write the message to the parent. If we have no good slaves or\n             * we are unable to transfer the message to the parent, we exit\n             * with an error so that the parent will abort the replication\n             * process with all the childre that were waiting. */\n            msglen = sizeof(uint64_t)*(1+2*numfds);\n            if (*len == 0 ||\n                write(server.rdb_pipe_write_result_to_parent,msg,msglen)\n                != msglen)\n            {\n                retval = REDIS_ERR;\n            }\n            zfree(msg);\n        }\n        zfree(clientids);\n        exitFromChild((retval == REDIS_OK) ? 0 : 1);\n    } else {\n        /* Parent */\n        zfree(clientids); /* Not used by parent. Free ASAP. */\n        server.stat_fork_time = ustime()-start;\n        server.stat_fork_rate = (double) zmalloc_used_memory() * 1000000 / server.stat_fork_time / (1024*1024*1024); /* GB per second. */\n        latencyAddSampleIfNeeded(\"fork\",server.stat_fork_time/1000);\n        if (childpid == -1) {\n            redisLog(REDIS_WARNING,\"Can't save in background: fork: %s\",\n                strerror(errno));\n            zfree(fds);\n            close(pipefds[0]);\n            close(pipefds[1]);\n            return REDIS_ERR;\n        }\n        redisLog(REDIS_NOTICE,\"Background RDB transfer started by pid %d\",childpid);\n        server.rdb_save_time_start = time(NULL);\n        server.rdb_child_pid = childpid;\n        server.rdb_child_type = REDIS_RDB_CHILD_TYPE_SOCKET;\n        updateDictResizePolicy();\n        zfree(fds);\n        return REDIS_OK;\n    }\n    return REDIS_OK; /* unreached */\n}\n\nvoid saveCommand(redisClient *c) {\n    if (server.rdb_child_pid != -1) {\n        addReplyError(c,\"Background save already in progress\");\n        return;\n    }\n    if (rdbSave(server.rdb_filename) == REDIS_OK) {\n        addReply(c,shared.ok);\n    } else {\n        addReply(c,shared.err);\n    }\n}\n\nvoid bgsaveCommand(redisClient *c) {\n    if (server.rdb_child_pid != -1) {\n        addReplyError(c,\"Background save already in progress\");\n    } else if (server.aof_child_pid != -1) {\n        addReplyError(c,\"Can't BGSAVE while AOF log rewriting is in progress\");\n    } else if (rdbSaveBackground(server.rdb_filename) == REDIS_OK) {\n        addReplyStatus(c,\"Background saving started\");\n    } else {\n        addReply(c,shared.err);\n    }\n}\n"
  },
  {
    "path": "extern/deprecated/redis-2.8.21/src/rdb.h",
    "content": "/*\n * Copyright (c) 2009-2012, Salvatore Sanfilippo <antirez at gmail dot com>\n * All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions are met:\n *\n *   * Redistributions of source code must retain the above copyright notice,\n *     this list of conditions and the following disclaimer.\n *   * Redistributions in binary form must reproduce the above copyright\n *     notice, this list of conditions and the following disclaimer in the\n *     documentation and/or other materials provided with the distribution.\n *   * Neither the name of Redis nor the names of its contributors may be used\n *     to endorse or promote products derived from this software without\n *     specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\"\n * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\n * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE\n * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR\n * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF\n * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS\n * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN\n * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)\n * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE\n * POSSIBILITY OF SUCH DAMAGE.\n */\n\n#ifndef __REDIS_RDB_H\n#define __REDIS_RDB_H\n\n#include <stdio.h>\n#include \"rio.h\"\n\n/* TBD: include only necessary headers. */\n#include \"redis.h\"\n\n/* The current RDB version. When the format changes in a way that is no longer\n * backward compatible this number gets incremented. */\n#define REDIS_RDB_VERSION 6\n\n/* Defines related to the dump file format. To store 32 bits lengths for short\n * keys requires a lot of space, so we check the most significant 2 bits of\n * the first byte to interpreter the length:\n *\n * 00|000000 => if the two MSB are 00 the len is the 6 bits of this byte\n * 01|000000 00000000 =>  01, the len is 14 byes, 6 bits + 8 bits of next byte\n * 10|000000 [32 bit integer] => if it's 01, a full 32 bit len will follow\n * 11|000000 this means: specially encoded object will follow. The six bits\n *           number specify the kind of object that follows.\n *           See the REDIS_RDB_ENC_* defines.\n *\n * Lengths up to 63 are stored using a single byte, most DB keys, and may\n * values, will fit inside. */\n#define REDIS_RDB_6BITLEN 0\n#define REDIS_RDB_14BITLEN 1\n#define REDIS_RDB_32BITLEN 2\n#define REDIS_RDB_ENCVAL 3\n#define REDIS_RDB_LENERR UINT_MAX\n\n/* When a length of a string object stored on disk has the first two bits\n * set, the remaining two bits specify a special encoding for the object\n * accordingly to the following defines: */\n#define REDIS_RDB_ENC_INT8 0        /* 8 bit signed integer */\n#define REDIS_RDB_ENC_INT16 1       /* 16 bit signed integer */\n#define REDIS_RDB_ENC_INT32 2       /* 32 bit signed integer */\n#define REDIS_RDB_ENC_LZF 3         /* string compressed with FASTLZ */\n\n/* Dup object types to RDB object types. Only reason is readability (are we\n * dealing with RDB types or with in-memory object types?). */\n#define REDIS_RDB_TYPE_STRING 0\n#define REDIS_RDB_TYPE_LIST   1\n#define REDIS_RDB_TYPE_SET    2\n#define REDIS_RDB_TYPE_ZSET   3\n#define REDIS_RDB_TYPE_HASH   4\n\n/* Object types for encoded objects. */\n#define REDIS_RDB_TYPE_HASH_ZIPMAP    9\n#define REDIS_RDB_TYPE_LIST_ZIPLIST  10\n#define REDIS_RDB_TYPE_SET_INTSET    11\n#define REDIS_RDB_TYPE_ZSET_ZIPLIST  12\n#define REDIS_RDB_TYPE_HASH_ZIPLIST  13\n\n/* Test if a type is an object type. */\n#define rdbIsObjectType(t) ((t >= 0 && t <= 4) || (t >= 9 && t <= 13))\n\n/* Special RDB opcodes (saved/loaded with rdbSaveType/rdbLoadType). */\n#define REDIS_RDB_OPCODE_EXPIRETIME_MS 252\n#define REDIS_RDB_OPCODE_EXPIRETIME 253\n#define REDIS_RDB_OPCODE_SELECTDB   254\n#define REDIS_RDB_OPCODE_EOF        255\n\nint rdbSaveType(rio *rdb, unsigned char type);\nint rdbLoadType(rio *rdb);\nint rdbSaveTime(rio *rdb, time_t t);\ntime_t rdbLoadTime(rio *rdb);\nint rdbSaveLen(rio *rdb, uint32_t len);\nuint32_t rdbLoadLen(rio *rdb, int *isencoded);\nint rdbSaveObjectType(rio *rdb, robj *o);\nint rdbLoadObjectType(rio *rdb);\nint rdbLoad(char *filename);\nint rdbSaveBackground(char *filename);\nint rdbSaveToSlavesSockets(void);\nvoid rdbRemoveTempFile(pid_t childpid);\nint rdbSave(char *filename);\nint rdbSaveObject(rio *rdb, robj *o);\noff_t rdbSavedObjectLen(robj *o);\noff_t rdbSavedObjectPages(robj *o);\nrobj *rdbLoadObject(int type, rio *rdb);\nvoid backgroundSaveDoneHandler(int exitcode, int bysignal);\nint rdbSaveKeyValuePair(rio *rdb, robj *key, robj *val, long long expiretime, long long now);\nrobj *rdbLoadStringObject(rio *rdb);\n\n#endif\n"
  },
  {
    "path": "extern/deprecated/redis-2.8.21/src/redis-benchmark.c",
    "content": "/* Redis benchmark utility.\n *\n * Copyright (c) 2009-2012, Salvatore Sanfilippo <antirez at gmail dot com>\n * All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions are met:\n *\n *   * Redistributions of source code must retain the above copyright notice,\n *     this list of conditions and the following disclaimer.\n *   * Redistributions in binary form must reproduce the above copyright\n *     notice, this list of conditions and the following disclaimer in the\n *     documentation and/or other materials provided with the distribution.\n *   * Neither the name of Redis nor the names of its contributors may be used\n *     to endorse or promote products derived from this software without\n *     specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\"\n * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\n * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE\n * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR\n * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF\n * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS\n * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN\n * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)\n * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE\n * POSSIBILITY OF SUCH DAMAGE.\n */\n\n#include \"fmacros.h\"\n\n#include <stdio.h>\n#include <string.h>\n#include <stdlib.h>\n#include <unistd.h>\n#include <errno.h>\n#include <time.h>\n#include <sys/time.h>\n#include <signal.h>\n#include <assert.h>\n\n#include \"ae.h\"\n#include \"hiredis.h\"\n#include \"sds.h\"\n#include \"adlist.h\"\n#include \"zmalloc.h\"\n\n#define REDIS_NOTUSED(V) ((void) V)\n#define RANDPTR_INITIAL_SIZE 8\n\nstatic struct config {\n    aeEventLoop *el;\n    const char *hostip;\n    int hostport;\n    const char *hostsocket;\n    int numclients;\n    int liveclients;\n    int requests;\n    int requests_issued;\n    int requests_finished;\n    int keysize;\n    int datasize;\n    int randomkeys;\n    int randomkeys_keyspacelen;\n    int keepalive;\n    int pipeline;\n    long long start;\n    long long totlatency;\n    long long *latency;\n    const char *title;\n    list *clients;\n    int quiet;\n    int csv;\n    int loop;\n    int idlemode;\n    int dbnum;\n    sds dbnumstr;\n    char *tests;\n    char *auth;\n} config;\n\ntypedef struct _client {\n    redisContext *context;\n    sds obuf;\n    char **randptr;         /* Pointers to :rand: strings inside the command buf */\n    size_t randlen;         /* Number of pointers in client->randptr */\n    size_t randfree;        /* Number of unused pointers in client->randptr */\n    unsigned int written;   /* Bytes of 'obuf' already written */\n    long long start;        /* Start time of a request */\n    long long latency;      /* Request latency */\n    int pending;            /* Number of pending requests (replies to consume) */\n    int prefix_pending;     /* If non-zero, number of pending prefix commands. Commands\n                               such as auth and select are prefixed to the pipeline of\n                               benchmark commands and discarded after the first send. */\n    int prefixlen;          /* Size in bytes of the pending prefix commands */\n} *client;\n\n/* Prototypes */\nstatic void writeHandler(aeEventLoop *el, int fd, void *privdata, int mask);\nstatic void createMissingClients(client c);\n\n/* Implementation */\nstatic long long ustime(void) {\n    struct timeval tv;\n    long long ust;\n\n    gettimeofday(&tv, NULL);\n    ust = ((long)tv.tv_sec)*1000000;\n    ust += tv.tv_usec;\n    return ust;\n}\n\nstatic long long mstime(void) {\n    struct timeval tv;\n    long long mst;\n\n    gettimeofday(&tv, NULL);\n    mst = ((long long)tv.tv_sec)*1000;\n    mst += tv.tv_usec/1000;\n    return mst;\n}\n\nstatic void freeClient(client c) {\n    listNode *ln;\n    aeDeleteFileEvent(config.el,c->context->fd,AE_WRITABLE);\n    aeDeleteFileEvent(config.el,c->context->fd,AE_READABLE);\n    redisFree(c->context);\n    sdsfree(c->obuf);\n    zfree(c->randptr);\n    zfree(c);\n    config.liveclients--;\n    ln = listSearchKey(config.clients,c);\n    assert(ln != NULL);\n    listDelNode(config.clients,ln);\n}\n\nstatic void freeAllClients(void) {\n    listNode *ln = config.clients->head, *next;\n\n    while(ln) {\n        next = ln->next;\n        freeClient(ln->value);\n        ln = next;\n    }\n}\n\nstatic void resetClient(client c) {\n    aeDeleteFileEvent(config.el,c->context->fd,AE_WRITABLE);\n    aeDeleteFileEvent(config.el,c->context->fd,AE_READABLE);\n    aeCreateFileEvent(config.el,c->context->fd,AE_WRITABLE,writeHandler,c);\n    c->written = 0;\n    c->pending = config.pipeline;\n}\n\nstatic void randomizeClientKey(client c) {\n    size_t i;\n\n    for (i = 0; i < c->randlen; i++) {\n        char *p = c->randptr[i]+11;\n        size_t r = random() % config.randomkeys_keyspacelen;\n        size_t j;\n\n        for (j = 0; j < 12; j++) {\n            *p = '0'+r%10;\n            r/=10;\n            p--;\n        }\n    }\n}\n\nstatic void clientDone(client c) {\n    if (config.requests_finished == config.requests) {\n        freeClient(c);\n        aeStop(config.el);\n        return;\n    }\n    if (config.keepalive) {\n        resetClient(c);\n    } else {\n        config.liveclients--;\n        createMissingClients(c);\n        config.liveclients++;\n        freeClient(c);\n    }\n}\n\nstatic void readHandler(aeEventLoop *el, int fd, void *privdata, int mask) {\n    client c = privdata;\n    void *reply = NULL;\n    REDIS_NOTUSED(el);\n    REDIS_NOTUSED(fd);\n    REDIS_NOTUSED(mask);\n\n    /* Calculate latency only for the first read event. This means that the\n     * server already sent the reply and we need to parse it. Parsing overhead\n     * is not part of the latency, so calculate it only once, here. */\n    if (c->latency < 0) c->latency = ustime()-(c->start);\n\n    if (redisBufferRead(c->context) != REDIS_OK) {\n        fprintf(stderr,\"Error: %s\\n\",c->context->errstr);\n        exit(1);\n    } else {\n        while(c->pending) {\n            if (redisGetReply(c->context,&reply) != REDIS_OK) {\n                fprintf(stderr,\"Error: %s\\n\",c->context->errstr);\n                exit(1);\n            }\n            if (reply != NULL) {\n                if (reply == (void*)REDIS_REPLY_ERROR) {\n                    fprintf(stderr,\"Unexpected error reply, exiting...\\n\");\n                    exit(1);\n                }\n\n                freeReplyObject(reply);\n                /* This is an OK for prefix commands such as auth and select.*/\n                if (c->prefix_pending > 0) {\n                    c->prefix_pending--;\n                    c->pending--;\n                    /* Discard prefix commands on first response.*/\n                    if (c->prefixlen > 0) {\n                        size_t j;\n                        sdsrange(c->obuf, c->prefixlen, -1);\n                        /* We also need to fix the pointers to the strings\n                        * we need to randomize. */\n                        for (j = 0; j < c->randlen; j++)\n                            c->randptr[j] -= c->prefixlen;\n                        c->prefixlen = 0;\n                    }\n                    continue;                \n                }\n\n                if (config.requests_finished < config.requests)\n                    config.latency[config.requests_finished++] = c->latency;\n                c->pending--;\n                if (c->pending == 0) {\n                    clientDone(c);\n                    break;\n                }\n            } else {\n                break;\n            }\n        }\n    }\n}\n\nstatic void writeHandler(aeEventLoop *el, int fd, void *privdata, int mask) {\n    client c = privdata;\n    REDIS_NOTUSED(el);\n    REDIS_NOTUSED(fd);\n    REDIS_NOTUSED(mask);\n\n    /* Initialize request when nothing was written. */\n    if (c->written == 0) {\n        /* Enforce upper bound to number of requests. */\n        if (config.requests_issued++ >= config.requests) {\n            freeClient(c);\n            return;\n        }\n\n        /* Really initialize: randomize keys and set start time. */\n        if (config.randomkeys) randomizeClientKey(c);\n        c->start = ustime();\n        c->latency = -1;\n    }\n\n    if (sdslen(c->obuf) > c->written) {\n        void *ptr = c->obuf+c->written;\n        int nwritten = write(c->context->fd,ptr,sdslen(c->obuf)-c->written);\n        if (nwritten == -1) {\n            if (errno != EPIPE)\n                fprintf(stderr, \"Writing to socket: %s\\n\", strerror(errno));\n            freeClient(c);\n            return;\n        }\n        c->written += nwritten;\n        if (sdslen(c->obuf) == c->written) {\n            aeDeleteFileEvent(config.el,c->context->fd,AE_WRITABLE);\n            aeCreateFileEvent(config.el,c->context->fd,AE_READABLE,readHandler,c);\n        }\n    }\n}\n\n/* Create a benchmark client, configured to send the command passed as 'cmd' of\n * 'len' bytes.\n *\n * The command is copied N times in the client output buffer (that is reused\n * again and again to send the request to the server) accordingly to the configured\n * pipeline size.\n *\n * Also an initial SELECT command is prepended in order to make sure the right\n * database is selected, if needed. The initial SELECT will be discarded as soon\n * as the first reply is received.\n *\n * To create a client from scratch, the 'from' pointer is set to NULL. If instead\n * we want to create a client using another client as reference, the 'from' pointer\n * points to the client to use as reference. In such a case the following\n * information is take from the 'from' client:\n *\n * 1) The command line to use.\n * 2) The offsets of the __rand_int__ elements inside the command line, used\n *    for arguments randomization.\n *\n * Even when cloning another client, prefix commands are applied if needed.*/\nstatic client createClient(char *cmd, size_t len, client from) {\n    int j;\n    client c = zmalloc(sizeof(struct _client));\n\n    if (config.hostsocket == NULL) {\n        c->context = redisConnectNonBlock(config.hostip,config.hostport);\n    } else {\n        c->context = redisConnectUnixNonBlock(config.hostsocket);\n    }\n    if (c->context->err) {\n        fprintf(stderr,\"Could not connect to Redis at \");\n        if (config.hostsocket == NULL)\n            fprintf(stderr,\"%s:%d: %s\\n\",config.hostip,config.hostport,c->context->errstr);\n        else\n            fprintf(stderr,\"%s: %s\\n\",config.hostsocket,c->context->errstr);\n        exit(1);\n    }\n    /* Suppress hiredis cleanup of unused buffers for max speed. */\n    c->context->reader->maxbuf = 0;\n\n    /* Build the request buffer:\n     * Queue N requests accordingly to the pipeline size, or simply clone\n     * the example client buffer. */\n    c->obuf = sdsempty();\n    /* Prefix the request buffer with AUTH and/or SELECT commands, if applicable.\n     * These commands are discarded after the first response, so if the client is\n     * reused the commands will not be used again. */\n    c->prefix_pending = 0;\n    if (config.auth) {\n        char *buf = NULL;\n        int len = redisFormatCommand(&buf, \"AUTH %s\", config.auth);\n        c->obuf = sdscatlen(c->obuf, buf, len);\n        free(buf);\n        c->prefix_pending++;\n    }\n\n    /* If a DB number different than zero is selected, prefix our request\n     * buffer with the SELECT command, that will be discarded the first\n     * time the replies are received, so if the client is reused the\n     * SELECT command will not be used again. */\n    if (config.dbnum != 0) {\n        c->obuf = sdscatprintf(c->obuf,\"*2\\r\\n$6\\r\\nSELECT\\r\\n$%d\\r\\n%s\\r\\n\",\n            (int)sdslen(config.dbnumstr),config.dbnumstr);\n        c->prefix_pending++;\n    }\n    c->prefixlen = sdslen(c->obuf);\n    /* Append the request itself. */\n    if (from) {\n        c->obuf = sdscatlen(c->obuf,\n            from->obuf+from->prefixlen,\n            sdslen(from->obuf)-from->prefixlen);\n    } else {\n        for (j = 0; j < config.pipeline; j++)\n            c->obuf = sdscatlen(c->obuf,cmd,len);\n    }\n\n    c->written = 0;\n    c->pending = config.pipeline+c->prefix_pending;\n    c->randptr = NULL;\n    c->randlen = 0;\n\n    /* Find substrings in the output buffer that need to be randomized. */\n    if (config.randomkeys) {\n        if (from) {\n            c->randlen = from->randlen;\n            c->randfree = 0;\n            c->randptr = zmalloc(sizeof(char*)*c->randlen);\n            /* copy the offsets. */\n            for (j = 0; j < (int)c->randlen; j++) {\n                c->randptr[j] = c->obuf + (from->randptr[j]-from->obuf);\n                /* Adjust for the different select prefix length. */\n                c->randptr[j] += c->prefixlen - from->prefixlen;\n            }\n        } else {\n            char *p = c->obuf;\n\n            c->randlen = 0;\n            c->randfree = RANDPTR_INITIAL_SIZE;\n            c->randptr = zmalloc(sizeof(char*)*c->randfree);\n            while ((p = strstr(p,\"__rand_int__\")) != NULL) {\n                if (c->randfree == 0) {\n                    c->randptr = zrealloc(c->randptr,sizeof(char*)*c->randlen*2);\n                    c->randfree += c->randlen;\n                }\n                c->randptr[c->randlen++] = p;\n                c->randfree--;\n                p += 12; /* 12 is strlen(\"__rand_int__). */\n            }\n        }\n    }\n    if (config.idlemode == 0)\n        aeCreateFileEvent(config.el,c->context->fd,AE_WRITABLE,writeHandler,c);\n    listAddNodeTail(config.clients,c);\n    config.liveclients++;\n    return c;\n}\n\nstatic void createMissingClients(client c) {\n    int n = 0;\n\n    while(config.liveclients < config.numclients) {\n        createClient(NULL,0,c);\n\n        /* Listen backlog is quite limited on most systems */\n        if (++n > 64) {\n            usleep(50000);\n            n = 0;\n        }\n    }\n}\n\nstatic int compareLatency(const void *a, const void *b) {\n    return (*(long long*)a)-(*(long long*)b);\n}\n\nstatic void showLatencyReport(void) {\n    int i, curlat = 0;\n    float perc, reqpersec;\n\n    reqpersec = (float)config.requests_finished/((float)config.totlatency/1000);\n    if (!config.quiet && !config.csv) {\n        printf(\"====== %s ======\\n\", config.title);\n        printf(\"  %d requests completed in %.2f seconds\\n\", config.requests_finished,\n            (float)config.totlatency/1000);\n        printf(\"  %d parallel clients\\n\", config.numclients);\n        printf(\"  %d bytes payload\\n\", config.datasize);\n        printf(\"  keep alive: %d\\n\", config.keepalive);\n        printf(\"\\n\");\n\n        qsort(config.latency,config.requests,sizeof(long long),compareLatency);\n        for (i = 0; i < config.requests; i++) {\n            if (config.latency[i]/1000 != curlat || i == (config.requests-1)) {\n                curlat = config.latency[i]/1000;\n                perc = ((float)(i+1)*100)/config.requests;\n                printf(\"%.2f%% <= %d milliseconds\\n\", perc, curlat);\n            }\n        }\n        printf(\"%.2f requests per second\\n\\n\", reqpersec);\n    } else if (config.csv) {\n        printf(\"\\\"%s\\\",\\\"%.2f\\\"\\n\", config.title, reqpersec);\n    } else {\n        printf(\"%s: %.2f requests per second\\n\", config.title, reqpersec);\n    }\n}\n\nstatic void benchmark(char *title, char *cmd, int len) {\n    client c;\n\n    config.title = title;\n    config.requests_issued = 0;\n    config.requests_finished = 0;\n\n    c = createClient(cmd,len,NULL);\n    createMissingClients(c);\n\n    config.start = mstime();\n    aeMain(config.el);\n    config.totlatency = mstime()-config.start;\n\n    showLatencyReport();\n    freeAllClients();\n}\n\n/* Returns number of consumed options. */\nint parseOptions(int argc, const char **argv) {\n    int i;\n    int lastarg;\n    int exit_status = 1;\n\n    for (i = 1; i < argc; i++) {\n        lastarg = (i == (argc-1));\n\n        if (!strcmp(argv[i],\"-c\")) {\n            if (lastarg) goto invalid;\n            config.numclients = atoi(argv[++i]);\n        } else if (!strcmp(argv[i],\"-n\")) {\n            if (lastarg) goto invalid;\n            config.requests = atoi(argv[++i]);\n        } else if (!strcmp(argv[i],\"-k\")) {\n            if (lastarg) goto invalid;\n            config.keepalive = atoi(argv[++i]);\n        } else if (!strcmp(argv[i],\"-h\")) {\n            if (lastarg) goto invalid;\n            config.hostip = strdup(argv[++i]);\n        } else if (!strcmp(argv[i],\"-p\")) {\n            if (lastarg) goto invalid;\n            config.hostport = atoi(argv[++i]);\n        } else if (!strcmp(argv[i],\"-s\")) {\n            if (lastarg) goto invalid;\n            config.hostsocket = strdup(argv[++i]);\n        } else if (!strcmp(argv[i],\"-a\") ) {\n            if (lastarg) goto invalid;\n            config.auth = strdup(argv[++i]);\n        } else if (!strcmp(argv[i],\"-d\")) {\n            if (lastarg) goto invalid;\n            config.datasize = atoi(argv[++i]);\n            if (config.datasize < 1) config.datasize=1;\n            if (config.datasize > 1024*1024*1024) config.datasize = 1024*1024*1024;\n        } else if (!strcmp(argv[i],\"-P\")) {\n            if (lastarg) goto invalid;\n            config.pipeline = atoi(argv[++i]);\n            if (config.pipeline <= 0) config.pipeline=1;\n        } else if (!strcmp(argv[i],\"-r\")) {\n            if (lastarg) goto invalid;\n            config.randomkeys = 1;\n            config.randomkeys_keyspacelen = atoi(argv[++i]);\n            if (config.randomkeys_keyspacelen < 0)\n                config.randomkeys_keyspacelen = 0;\n        } else if (!strcmp(argv[i],\"-q\")) {\n            config.quiet = 1;\n        } else if (!strcmp(argv[i],\"--csv\")) {\n            config.csv = 1;\n        } else if (!strcmp(argv[i],\"-l\")) {\n            config.loop = 1;\n        } else if (!strcmp(argv[i],\"-I\")) {\n            config.idlemode = 1;\n        } else if (!strcmp(argv[i],\"-t\")) {\n            if (lastarg) goto invalid;\n            /* We get the list of tests to run as a string in the form\n             * get,set,lrange,...,test_N. Then we add a comma before and\n             * after the string in order to make sure that searching\n             * for \",testname,\" will always get a match if the test is\n             * enabled. */\n            config.tests = sdsnew(\",\");\n            config.tests = sdscat(config.tests,(char*)argv[++i]);\n            config.tests = sdscat(config.tests,\",\");\n            sdstolower(config.tests);\n        } else if (!strcmp(argv[i],\"--dbnum\")) {\n            if (lastarg) goto invalid;\n            config.dbnum = atoi(argv[++i]);\n            config.dbnumstr = sdsfromlonglong(config.dbnum);\n        } else if (!strcmp(argv[i],\"--help\")) {\n            exit_status = 0;\n            goto usage;\n        } else {\n            /* Assume the user meant to provide an option when the arg starts\n             * with a dash. We're done otherwise and should use the remainder\n             * as the command and arguments for running the benchmark. */\n            if (argv[i][0] == '-') goto invalid;\n            return i;\n        }\n    }\n\n    return i;\n\ninvalid:\n    printf(\"Invalid option \\\"%s\\\" or option argument missing\\n\\n\",argv[i]);\n\nusage:\n    printf(\n\"Usage: redis-benchmark [-h <host>] [-p <port>] [-c <clients>] [-n <requests]> [-k <boolean>]\\n\\n\"\n\" -h <hostname>      Server hostname (default 127.0.0.1)\\n\"\n\" -p <port>          Server port (default 6379)\\n\"\n\" -s <socket>        Server socket (overrides host and port)\\n\"\n\" -a <password>      Password for Redis Auth\\n\"\n\" -c <clients>       Number of parallel connections (default 50)\\n\"\n\" -n <requests>      Total number of requests (default 100000)\\n\"\n\" -d <size>          Data size of SET/GET value in bytes (default 2)\\n\"\n\" -dbnum <db>        SELECT the specified db number (default 0)\\n\"\n\" -k <boolean>       1=keep alive 0=reconnect (default 1)\\n\"\n\" -r <keyspacelen>   Use random keys for SET/GET/INCR, random values for SADD\\n\"\n\"  Using this option the benchmark will expand the string __rand_int__\\n\"\n\"  inside an argument with a 12 digits number in the specified range\\n\"\n\"  from 0 to keyspacelen-1. The substitution changes every time a command\\n\"\n\"  is executed. Default tests use this to hit random keys in the\\n\"\n\"  specified range.\\n\"\n\" -P <numreq>        Pipeline <numreq> requests. Default 1 (no pipeline).\\n\"\n\" -q                 Quiet. Just show query/sec values\\n\"\n\" --csv              Output in CSV format\\n\"\n\" -l                 Loop. Run the tests forever\\n\"\n\" -t <tests>         Only run the comma separated list of tests. The test\\n\"\n\"                    names are the same as the ones produced as output.\\n\"\n\" -I                 Idle mode. Just open N idle connections and wait.\\n\\n\"\n\"Examples:\\n\\n\"\n\" Run the benchmark with the default configuration against 127.0.0.1:6379:\\n\"\n\"   $ redis-benchmark\\n\\n\"\n\" Use 20 parallel clients, for a total of 100k requests, against 192.168.1.1:\\n\"\n\"   $ redis-benchmark -h 192.168.1.1 -p 6379 -n 100000 -c 20\\n\\n\"\n\" Fill 127.0.0.1:6379 with about 1 million keys only using the SET test:\\n\"\n\"   $ redis-benchmark -t set -n 1000000 -r 100000000\\n\\n\"\n\" Benchmark 127.0.0.1:6379 for a few commands producing CSV output:\\n\"\n\"   $ redis-benchmark -t ping,set,get -n 100000 --csv\\n\\n\"\n\" Benchmark a specific command line:\\n\"\n\"   $ redis-benchmark -r 10000 -n 10000 eval 'return redis.call(\\\"ping\\\")' 0\\n\\n\"\n\" Fill a list with 10000 random elements:\\n\"\n\"   $ redis-benchmark -r 10000 -n 10000 lpush mylist __rand_int__\\n\\n\"\n\" On user specified command lines __rand_int__ is replaced with a random integer\\n\"\n\" with a range of values selected by the -r option.\\n\"\n    );\n    exit(exit_status);\n}\n\nint showThroughput(struct aeEventLoop *eventLoop, long long id, void *clientData) {\n    REDIS_NOTUSED(eventLoop);\n    REDIS_NOTUSED(id);\n    REDIS_NOTUSED(clientData);\n\n    if (config.liveclients == 0) {\n        fprintf(stderr,\"All clients disconnected... aborting.\\n\");\n        exit(1);\n    } \n    if (config.csv) return 250;\n    if (config.idlemode == 1) {\n        printf(\"clients: %d\\r\", config.liveclients);\n        fflush(stdout);\n\treturn 250;\n    }\n    float dt = (float)(mstime()-config.start)/1000.0;\n    float rps = (float)config.requests_finished/dt;\n    printf(\"%s: %.2f\\r\", config.title, rps);\n    fflush(stdout);\n    return 250; /* every 250ms */\n}\n\n/* Return true if the named test was selected using the -t command line\n * switch, or if all the tests are selected (no -t passed by user). */\nint test_is_selected(char *name) {\n    char buf[256];\n    int l = strlen(name);\n\n    if (config.tests == NULL) return 1;\n    buf[0] = ',';\n    memcpy(buf+1,name,l);\n    buf[l+1] = ',';\n    buf[l+2] = '\\0';\n    return strstr(config.tests,buf) != NULL;\n}\n\nint main(int argc, const char **argv) {\n    int i;\n    char *data, *cmd;\n    int len;\n\n    client c;\n\n    srandom(time(NULL));\n    signal(SIGHUP, SIG_IGN);\n    signal(SIGPIPE, SIG_IGN);\n\n    config.numclients = 50;\n    config.requests = 100000;\n    config.liveclients = 0;\n    config.el = aeCreateEventLoop(1024*10);\n    aeCreateTimeEvent(config.el,1,showThroughput,NULL,NULL);\n    config.keepalive = 1;\n    config.datasize = 3;\n    config.pipeline = 1;\n    config.randomkeys = 0;\n    config.randomkeys_keyspacelen = 0;\n    config.quiet = 0;\n    config.csv = 0;\n    config.loop = 0;\n    config.idlemode = 0;\n    config.latency = NULL;\n    config.clients = listCreate();\n    config.hostip = \"127.0.0.1\";\n    config.hostport = 6379;\n    config.hostsocket = NULL;\n    config.tests = NULL;\n    config.dbnum = 0;\n    config.auth = NULL;\n\n    i = parseOptions(argc,argv);\n    argc -= i;\n    argv += i;\n\n    config.latency = zmalloc(sizeof(long long)*config.requests);\n\n    if (config.keepalive == 0) {\n        printf(\"WARNING: keepalive disabled, you probably need 'echo 1 > /proc/sys/net/ipv4/tcp_tw_reuse' for Linux and 'sudo sysctl -w net.inet.tcp.msl=1000' for Mac OS X in order to use a lot of clients/requests\\n\");\n    }\n\n    if (config.idlemode) {\n        printf(\"Creating %d idle connections and waiting forever (Ctrl+C when done)\\n\", config.numclients);\n        c = createClient(\"\",0,NULL); /* will never receive a reply */\n        createMissingClients(c);\n        aeMain(config.el);\n        /* and will wait for every */\n    }\n\n    /* Run benchmark with command in the remainder of the arguments. */\n    if (argc) {\n        sds title = sdsnew(argv[0]);\n        for (i = 1; i < argc; i++) {\n            title = sdscatlen(title, \" \", 1);\n            title = sdscatlen(title, (char*)argv[i], strlen(argv[i]));\n        }\n\n        do {\n            len = redisFormatCommandArgv(&cmd,argc,argv,NULL);\n            benchmark(title,cmd,len);\n            free(cmd);\n        } while(config.loop);\n\n        return 0;\n    }\n\n    /* Run default benchmark suite. */\n    data = zmalloc(config.datasize+1);\n    do {\n        memset(data,'x',config.datasize);\n        data[config.datasize] = '\\0';\n\n        if (test_is_selected(\"ping_inline\") || test_is_selected(\"ping\"))\n            benchmark(\"PING_INLINE\",\"PING\\r\\n\",6);\n\n        if (test_is_selected(\"ping_mbulk\") || test_is_selected(\"ping\")) {\n            len = redisFormatCommand(&cmd,\"PING\");\n            benchmark(\"PING_BULK\",cmd,len);\n            free(cmd);\n        }\n\n        if (test_is_selected(\"set\")) {\n            len = redisFormatCommand(&cmd,\"SET key:__rand_int__ %s\",data);\n            benchmark(\"SET\",cmd,len);\n            free(cmd);\n        }\n\n        if (test_is_selected(\"get\")) {\n            len = redisFormatCommand(&cmd,\"GET key:__rand_int__\");\n            benchmark(\"GET\",cmd,len);\n            free(cmd);\n        }\n\n        if (test_is_selected(\"incr\")) {\n            len = redisFormatCommand(&cmd,\"INCR counter:__rand_int__\");\n            benchmark(\"INCR\",cmd,len);\n            free(cmd);\n        }\n\n        if (test_is_selected(\"lpush\")) {\n            len = redisFormatCommand(&cmd,\"LPUSH mylist %s\",data);\n            benchmark(\"LPUSH\",cmd,len);\n            free(cmd);\n        }\n\n        if (test_is_selected(\"lpop\")) {\n            len = redisFormatCommand(&cmd,\"LPOP mylist\");\n            benchmark(\"LPOP\",cmd,len);\n            free(cmd);\n        }\n\n        if (test_is_selected(\"sadd\")) {\n            len = redisFormatCommand(&cmd,\n                \"SADD myset element:__rand_int__\");\n            benchmark(\"SADD\",cmd,len);\n            free(cmd);\n        }\n\n        if (test_is_selected(\"spop\")) {\n            len = redisFormatCommand(&cmd,\"SPOP myset\");\n            benchmark(\"SPOP\",cmd,len);\n            free(cmd);\n        }\n\n        if (test_is_selected(\"lrange\") ||\n            test_is_selected(\"lrange_100\") ||\n            test_is_selected(\"lrange_300\") ||\n            test_is_selected(\"lrange_500\") ||\n            test_is_selected(\"lrange_600\"))\n        {\n            len = redisFormatCommand(&cmd,\"LPUSH mylist %s\",data);\n            benchmark(\"LPUSH (needed to benchmark LRANGE)\",cmd,len);\n            free(cmd);\n        }\n\n        if (test_is_selected(\"lrange\") || test_is_selected(\"lrange_100\")) {\n            len = redisFormatCommand(&cmd,\"LRANGE mylist 0 99\");\n            benchmark(\"LRANGE_100 (first 100 elements)\",cmd,len);\n            free(cmd);\n        }\n\n        if (test_is_selected(\"lrange\") || test_is_selected(\"lrange_300\")) {\n            len = redisFormatCommand(&cmd,\"LRANGE mylist 0 299\");\n            benchmark(\"LRANGE_300 (first 300 elements)\",cmd,len);\n            free(cmd);\n        }\n\n        if (test_is_selected(\"lrange\") || test_is_selected(\"lrange_500\")) {\n            len = redisFormatCommand(&cmd,\"LRANGE mylist 0 449\");\n            benchmark(\"LRANGE_500 (first 450 elements)\",cmd,len);\n            free(cmd);\n        }\n\n        if (test_is_selected(\"lrange\") || test_is_selected(\"lrange_600\")) {\n            len = redisFormatCommand(&cmd,\"LRANGE mylist 0 599\");\n            benchmark(\"LRANGE_600 (first 600 elements)\",cmd,len);\n            free(cmd);\n        }\n\n        if (test_is_selected(\"mset\")) {\n            const char *argv[21];\n            argv[0] = \"MSET\";\n            for (i = 1; i < 21; i += 2) {\n                argv[i] = \"key:__rand_int__\";\n                argv[i+1] = data;\n            }\n            len = redisFormatCommandArgv(&cmd,21,argv,NULL);\n            benchmark(\"MSET (10 keys)\",cmd,len);\n            free(cmd);\n        }\n\n        if (!config.csv) printf(\"\\n\");\n    } while(config.loop);\n\n    return 0;\n}\n"
  },
  {
    "path": "extern/deprecated/redis-2.8.21/src/redis-check-aof.c",
    "content": "/*\n * Copyright (c) 2009-2012, Pieter Noordhuis <pcnoordhuis at gmail dot com>\n * Copyright (c) 2009-2012, Salvatore Sanfilippo <antirez at gmail dot com>\n * All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions are met:\n *\n *   * Redistributions of source code must retain the above copyright notice,\n *     this list of conditions and the following disclaimer.\n *   * Redistributions in binary form must reproduce the above copyright\n *     notice, this list of conditions and the following disclaimer in the\n *     documentation and/or other materials provided with the distribution.\n *   * Neither the name of Redis nor the names of its contributors may be used\n *     to endorse or promote products derived from this software without\n *     specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\"\n * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\n * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE\n * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR\n * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF\n * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS\n * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN\n * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)\n * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE\n * POSSIBILITY OF SUCH DAMAGE.\n */\n\n#include \"fmacros.h\"\n#include <stdlib.h>\n#include <stdio.h>\n#include <string.h>\n#include <unistd.h>\n#include <sys/stat.h>\n#include \"config.h\"\n\n#define ERROR(...) { \\\n    char __buf[1024]; \\\n    sprintf(__buf, __VA_ARGS__); \\\n    sprintf(error, \"0x%16llx: %s\", (long long)epos, __buf); \\\n}\n\nstatic char error[1024];\nstatic off_t epos;\n\nint consumeNewline(char *buf) {\n    if (strncmp(buf,\"\\r\\n\",2) != 0) {\n        ERROR(\"Expected \\\\r\\\\n, got: %02x%02x\",buf[0],buf[1]);\n        return 0;\n    }\n    return 1;\n}\n\nint readLong(FILE *fp, char prefix, long *target) {\n    char buf[128], *eptr;\n    epos = ftello(fp);\n    if (fgets(buf,sizeof(buf),fp) == NULL) {\n        return 0;\n    }\n    if (buf[0] != prefix) {\n        ERROR(\"Expected prefix '%c', got: '%c'\",buf[0],prefix);\n        return 0;\n    }\n    *target = strtol(buf+1,&eptr,10);\n    return consumeNewline(eptr);\n}\n\nint readBytes(FILE *fp, char *target, long length) {\n    long real;\n    epos = ftello(fp);\n    real = fread(target,1,length,fp);\n    if (real != length) {\n        ERROR(\"Expected to read %ld bytes, got %ld bytes\",length,real);\n        return 0;\n    }\n    return 1;\n}\n\nint readString(FILE *fp, char** target) {\n    long len;\n    *target = NULL;\n    if (!readLong(fp,'$',&len)) {\n        return 0;\n    }\n\n    /* Increase length to also consume \\r\\n */\n    len += 2;\n    *target = (char*)malloc(len);\n    if (!readBytes(fp,*target,len)) {\n        return 0;\n    }\n    if (!consumeNewline(*target+len-2)) {\n        return 0;\n    }\n    (*target)[len-2] = '\\0';\n    return 1;\n}\n\nint readArgc(FILE *fp, long *target) {\n    return readLong(fp,'*',target);\n}\n\noff_t process(FILE *fp) {\n    long argc;\n    off_t pos = 0;\n    int i, multi = 0;\n    char *str;\n\n    while(1) {\n        if (!multi) pos = ftello(fp);\n        if (!readArgc(fp, &argc)) break;\n\n        for (i = 0; i < argc; i++) {\n            if (!readString(fp,&str)) break;\n            if (i == 0) {\n                if (strcasecmp(str, \"multi\") == 0) {\n                    if (multi++) {\n                        ERROR(\"Unexpected MULTI\");\n                        break;\n                    }\n                } else if (strcasecmp(str, \"exec\") == 0) {\n                    if (--multi) {\n                        ERROR(\"Unexpected EXEC\");\n                        break;\n                    }\n                }\n            }\n            free(str);\n        }\n\n        /* Stop if the loop did not finish */\n        if (i < argc) {\n            if (str) free(str);\n            break;\n        }\n    }\n\n    if (feof(fp) && multi && strlen(error) == 0) {\n        ERROR(\"Reached EOF before reading EXEC for MULTI\");\n    }\n    if (strlen(error) > 0) {\n        printf(\"%s\\n\", error);\n    }\n    return pos;\n}\n\nint main(int argc, char **argv) {\n    char *filename;\n    int fix = 0;\n\n    if (argc < 2) {\n        printf(\"Usage: %s [--fix] <file.aof>\\n\", argv[0]);\n        exit(1);\n    } else if (argc == 2) {\n        filename = argv[1];\n    } else if (argc == 3) {\n        if (strcmp(argv[1],\"--fix\") != 0) {\n            printf(\"Invalid argument: %s\\n\", argv[1]);\n            exit(1);\n        }\n        filename = argv[2];\n        fix = 1;\n    } else {\n        printf(\"Invalid arguments\\n\");\n        exit(1);\n    }\n\n    FILE *fp = fopen(filename,\"r+\");\n    if (fp == NULL) {\n        printf(\"Cannot open file: %s\\n\", filename);\n        exit(1);\n    }\n\n    struct redis_stat sb;\n    if (redis_fstat(fileno(fp),&sb) == -1) {\n        printf(\"Cannot stat file: %s\\n\", filename);\n        exit(1);\n    }\n\n    off_t size = sb.st_size;\n    if (size == 0) {\n        printf(\"Empty file: %s\\n\", filename);\n        exit(1);\n    }\n\n    off_t pos = process(fp);\n    off_t diff = size-pos;\n    printf(\"AOF analyzed: size=%lld, ok_up_to=%lld, diff=%lld\\n\",\n        (long long) size, (long long) pos, (long long) diff);\n    if (diff > 0) {\n        if (fix) {\n            char buf[2];\n            printf(\"This will shrink the AOF from %lld bytes, with %lld bytes, to %lld bytes\\n\",(long long)size,(long long)diff,(long long)pos);\n            printf(\"Continue? [y/N]: \");\n            if (fgets(buf,sizeof(buf),stdin) == NULL ||\n                strncasecmp(buf,\"y\",1) != 0) {\n                    printf(\"Aborting...\\n\");\n                    exit(1);\n            }\n            if (ftruncate(fileno(fp), pos) == -1) {\n                printf(\"Failed to truncate AOF\\n\");\n                exit(1);\n            } else {\n                printf(\"Successfully truncated AOF\\n\");\n            }\n        } else {\n            printf(\"AOF is not valid\\n\");\n            exit(1);\n        }\n    } else {\n        printf(\"AOF is valid\\n\");\n    }\n\n    fclose(fp);\n    return 0;\n}\n"
  },
  {
    "path": "extern/deprecated/redis-2.8.21/src/redis-check-dump.c",
    "content": "/*\n * Copyright (c) 2009-2012, Pieter Noordhuis <pcnoordhuis at gmail dot com>\n * Copyright (c) 2009-2012, Salvatore Sanfilippo <antirez at gmail dot com>\n * All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions are met:\n *\n *   * Redistributions of source code must retain the above copyright notice,\n *     this list of conditions and the following disclaimer.\n *   * Redistributions in binary form must reproduce the above copyright\n *     notice, this list of conditions and the following disclaimer in the\n *     documentation and/or other materials provided with the distribution.\n *   * Neither the name of Redis nor the names of its contributors may be used\n *     to endorse or promote products derived from this software without\n *     specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\"\n * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\n * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE\n * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR\n * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF\n * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS\n * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN\n * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)\n * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE\n * POSSIBILITY OF SUCH DAMAGE.\n */\n\n\n#include <stdlib.h>\n#include <stdio.h>\n#include <unistd.h>\n#include <fcntl.h>\n#include <sys/stat.h>\n#include <sys/mman.h>\n#include <string.h>\n#include <arpa/inet.h>\n#include <stdint.h>\n#include <limits.h>\n#include \"lzf.h\"\n#include \"crc64.h\"\n\n/* Object types */\n#define REDIS_STRING 0\n#define REDIS_LIST 1\n#define REDIS_SET 2\n#define REDIS_ZSET 3\n#define REDIS_HASH 4\n#define REDIS_HASH_ZIPMAP 9\n#define REDIS_LIST_ZIPLIST 10\n#define REDIS_SET_INTSET 11\n#define REDIS_ZSET_ZIPLIST 12\n#define REDIS_HASH_ZIPLIST 13\n\n/* Objects encoding. Some kind of objects like Strings and Hashes can be\n * internally represented in multiple ways. The 'encoding' field of the object\n * is set to one of this fields for this object. */\n#define REDIS_ENCODING_RAW 0    /* Raw representation */\n#define REDIS_ENCODING_INT 1    /* Encoded as integer */\n#define REDIS_ENCODING_ZIPMAP 2 /* Encoded as zipmap */\n#define REDIS_ENCODING_HT 3     /* Encoded as a hash table */\n\n/* Object types only used for dumping to disk */\n#define REDIS_EXPIRETIME_MS 252\n#define REDIS_EXPIRETIME 253\n#define REDIS_SELECTDB 254\n#define REDIS_EOF 255\n\n/* Defines related to the dump file format. To store 32 bits lengths for short\n * keys requires a lot of space, so we check the most significant 2 bits of\n * the first byte to interpreter the length:\n *\n * 00|000000 => if the two MSB are 00 the len is the 6 bits of this byte\n * 01|000000 00000000 =>  01, the len is 14 byes, 6 bits + 8 bits of next byte\n * 10|000000 [32 bit integer] => if it's 01, a full 32 bit len will follow\n * 11|000000 this means: specially encoded object will follow. The six bits\n *           number specify the kind of object that follows.\n *           See the REDIS_RDB_ENC_* defines.\n *\n * Lengths up to 63 are stored using a single byte, most DB keys, and may\n * values, will fit inside. */\n#define REDIS_RDB_6BITLEN 0\n#define REDIS_RDB_14BITLEN 1\n#define REDIS_RDB_32BITLEN 2\n#define REDIS_RDB_ENCVAL 3\n#define REDIS_RDB_LENERR UINT_MAX\n\n/* When a length of a string object stored on disk has the first two bits\n * set, the remaining two bits specify a special encoding for the object\n * accordingly to the following defines: */\n#define REDIS_RDB_ENC_INT8 0        /* 8 bit signed integer */\n#define REDIS_RDB_ENC_INT16 1       /* 16 bit signed integer */\n#define REDIS_RDB_ENC_INT32 2       /* 32 bit signed integer */\n#define REDIS_RDB_ENC_LZF 3         /* string compressed with FASTLZ */\n\n#define ERROR(...) { \\\n    printf(__VA_ARGS__); \\\n    exit(1); \\\n}\n\n/* data type to hold offset in file and size */\ntypedef struct {\n    void *data;\n    size_t size;\n    size_t offset;\n} pos;\n\nstatic unsigned char level = 0;\nstatic pos positions[16];\n\n#define CURR_OFFSET (positions[level].offset)\n\n/* Hold a stack of errors */\ntypedef struct {\n    char error[16][1024];\n    size_t offset[16];\n    size_t level;\n} errors_t;\nstatic errors_t errors;\n\n#define SHIFT_ERROR(provided_offset, ...) { \\\n    sprintf(errors.error[errors.level], __VA_ARGS__); \\\n    errors.offset[errors.level] = provided_offset; \\\n    errors.level++; \\\n}\n\n/* Data type to hold opcode with optional key name an success status */\ntypedef struct {\n    char* key;\n    int type;\n    char success;\n} entry;\n\n/* Global vars that are actually used as constants. The following double\n * values are used for double on-disk serialization, and are initialized\n * at runtime to avoid strange compiler optimizations. */\nstatic double R_Zero, R_PosInf, R_NegInf, R_Nan;\n\n#define MAX_TYPES_NUM 256\n#define MAX_TYPE_NAME_LEN 16\n/* store string types for output */\nstatic char types[MAX_TYPES_NUM][MAX_TYPE_NAME_LEN];\n\n/* Return true if 't' is a valid object type. */\nint checkType(unsigned char t) {\n    /* In case a new object type is added, update the following\n     * condition as necessary. */\n    return\n        (t >= REDIS_HASH_ZIPMAP && t <= REDIS_HASH_ZIPLIST) ||\n        t <= REDIS_HASH ||\n        t >= REDIS_EXPIRETIME_MS;\n}\n\n/* when number of bytes to read is negative, do a peek */\nint readBytes(void *target, long num) {\n    char peek = (num < 0) ? 1 : 0;\n    num = (num < 0) ? -num : num;\n\n    pos p = positions[level];\n    if (p.offset + num > p.size) {\n        return 0;\n    } else {\n        memcpy(target, (void*)((size_t)p.data + p.offset), num);\n        if (!peek) positions[level].offset += num;\n    }\n    return 1;\n}\n\nint processHeader(void) {\n    char buf[10] = \"_________\";\n    int dump_version;\n\n    if (!readBytes(buf, 9)) {\n        ERROR(\"Cannot read header\\n\");\n    }\n\n    /* expect the first 5 bytes to equal REDIS */\n    if (memcmp(buf,\"REDIS\",5) != 0) {\n        ERROR(\"Wrong signature in header\\n\");\n    }\n\n    dump_version = (int)strtol(buf + 5, NULL, 10);\n    if (dump_version < 1 || dump_version > 6) {\n        ERROR(\"Unknown RDB format version: %d\\n\", dump_version);\n    }\n    return dump_version;\n}\n\nint loadType(entry *e) {\n    uint32_t offset = CURR_OFFSET;\n\n    /* this byte needs to qualify as type */\n    unsigned char t;\n    if (readBytes(&t, 1)) {\n        if (checkType(t)) {\n            e->type = t;\n            return 1;\n        } else {\n            SHIFT_ERROR(offset, \"Unknown type (0x%02x)\", t);\n        }\n    } else {\n        SHIFT_ERROR(offset, \"Could not read type\");\n    }\n\n    /* failure */\n    return 0;\n}\n\nint peekType() {\n    unsigned char t;\n    if (readBytes(&t, -1) && (checkType(t)))\n        return t;\n    return -1;\n}\n\n/* discard time, just consume the bytes */\nint processTime(int type) {\n    uint32_t offset = CURR_OFFSET;\n    unsigned char t[8];\n    int timelen = (type == REDIS_EXPIRETIME_MS) ? 8 : 4;\n\n    if (readBytes(t,timelen)) {\n        return 1;\n    } else {\n        SHIFT_ERROR(offset, \"Could not read time\");\n    }\n\n    /* failure */\n    return 0;\n}\n\nuint32_t loadLength(int *isencoded) {\n    unsigned char buf[2];\n    uint32_t len;\n    int type;\n\n    if (isencoded) *isencoded = 0;\n    if (!readBytes(buf, 1)) return REDIS_RDB_LENERR;\n    type = (buf[0] & 0xC0) >> 6;\n    if (type == REDIS_RDB_6BITLEN) {\n        /* Read a 6 bit len */\n        return buf[0] & 0x3F;\n    } else if (type == REDIS_RDB_ENCVAL) {\n        /* Read a 6 bit len encoding type */\n        if (isencoded) *isencoded = 1;\n        return buf[0] & 0x3F;\n    } else if (type == REDIS_RDB_14BITLEN) {\n        /* Read a 14 bit len */\n        if (!readBytes(buf+1,1)) return REDIS_RDB_LENERR;\n        return ((buf[0] & 0x3F) << 8) | buf[1];\n    } else {\n        /* Read a 32 bit len */\n        if (!readBytes(&len, 4)) return REDIS_RDB_LENERR;\n        return (unsigned int)ntohl(len);\n    }\n}\n\nchar *loadIntegerObject(int enctype) {\n    uint32_t offset = CURR_OFFSET;\n    unsigned char enc[4];\n    long long val;\n\n    if (enctype == REDIS_RDB_ENC_INT8) {\n        uint8_t v;\n        if (!readBytes(enc, 1)) return NULL;\n        v = enc[0];\n        val = (int8_t)v;\n    } else if (enctype == REDIS_RDB_ENC_INT16) {\n        uint16_t v;\n        if (!readBytes(enc, 2)) return NULL;\n        v = enc[0]|(enc[1]<<8);\n        val = (int16_t)v;\n    } else if (enctype == REDIS_RDB_ENC_INT32) {\n        uint32_t v;\n        if (!readBytes(enc, 4)) return NULL;\n        v = enc[0]|(enc[1]<<8)|(enc[2]<<16)|(enc[3]<<24);\n        val = (int32_t)v;\n    } else {\n        SHIFT_ERROR(offset, \"Unknown integer encoding (0x%02x)\", enctype);\n        return NULL;\n    }\n\n    /* convert val into string */\n    char *buf;\n    buf = malloc(sizeof(char) * 128);\n    sprintf(buf, \"%lld\", val);\n    return buf;\n}\n\nchar* loadLzfStringObject() {\n    unsigned int slen, clen;\n    char *c, *s;\n\n    if ((clen = loadLength(NULL)) == REDIS_RDB_LENERR) return NULL;\n    if ((slen = loadLength(NULL)) == REDIS_RDB_LENERR) return NULL;\n\n    c = malloc(clen);\n    if (!readBytes(c, clen)) {\n        free(c);\n        return NULL;\n    }\n\n    s = malloc(slen+1);\n    if (lzf_decompress(c,clen,s,slen) == 0) {\n        free(c); free(s);\n        return NULL;\n    }\n\n    free(c);\n    return s;\n}\n\n/* returns NULL when not processable, char* when valid */\nchar* loadStringObject() {\n    uint32_t offset = CURR_OFFSET;\n    int isencoded;\n    uint32_t len;\n\n    len = loadLength(&isencoded);\n    if (isencoded) {\n        switch(len) {\n        case REDIS_RDB_ENC_INT8:\n        case REDIS_RDB_ENC_INT16:\n        case REDIS_RDB_ENC_INT32:\n            return loadIntegerObject(len);\n        case REDIS_RDB_ENC_LZF:\n            return loadLzfStringObject();\n        default:\n            /* unknown encoding */\n            SHIFT_ERROR(offset, \"Unknown string encoding (0x%02x)\", len);\n            return NULL;\n        }\n    }\n\n    if (len == REDIS_RDB_LENERR) return NULL;\n\n    char *buf = malloc(sizeof(char) * (len+1));\n    if (buf == NULL) return NULL;\n    buf[len] = '\\0';\n    if (!readBytes(buf, len)) {\n        free(buf);\n        return NULL;\n    }\n    return buf;\n}\n\nint processStringObject(char** store) {\n    unsigned long offset = CURR_OFFSET;\n    char *key = loadStringObject();\n    if (key == NULL) {\n        SHIFT_ERROR(offset, \"Error reading string object\");\n        free(key);\n        return 0;\n    }\n\n    if (store != NULL) {\n        *store = key;\n    } else {\n        free(key);\n    }\n    return 1;\n}\n\ndouble* loadDoubleValue() {\n    char buf[256];\n    unsigned char len;\n    double* val;\n\n    if (!readBytes(&len,1)) return NULL;\n\n    val = malloc(sizeof(double));\n    switch(len) {\n    case 255: *val = R_NegInf;  return val;\n    case 254: *val = R_PosInf;  return val;\n    case 253: *val = R_Nan;     return val;\n    default:\n        if (!readBytes(buf, len)) {\n            free(val);\n            return NULL;\n        }\n        buf[len] = '\\0';\n        sscanf(buf, \"%lg\", val);\n        return val;\n    }\n}\n\nint processDoubleValue(double** store) {\n    unsigned long offset = CURR_OFFSET;\n    double *val = loadDoubleValue();\n    if (val == NULL) {\n        SHIFT_ERROR(offset, \"Error reading double value\");\n        free(val);\n        return 0;\n    }\n\n    if (store != NULL) {\n        *store = val;\n    } else {\n        free(val);\n    }\n    return 1;\n}\n\nint loadPair(entry *e) {\n    uint32_t offset = CURR_OFFSET;\n    uint32_t i;\n\n    /* read key first */\n    char *key;\n    if (processStringObject(&key)) {\n        e->key = key;\n    } else {\n        SHIFT_ERROR(offset, \"Error reading entry key\");\n        return 0;\n    }\n\n    uint32_t length = 0;\n    if (e->type == REDIS_LIST ||\n        e->type == REDIS_SET  ||\n        e->type == REDIS_ZSET ||\n        e->type == REDIS_HASH) {\n        if ((length = loadLength(NULL)) == REDIS_RDB_LENERR) {\n            SHIFT_ERROR(offset, \"Error reading %s length\", types[e->type]);\n            return 0;\n        }\n    }\n\n    switch(e->type) {\n    case REDIS_STRING:\n    case REDIS_HASH_ZIPMAP:\n    case REDIS_LIST_ZIPLIST:\n    case REDIS_SET_INTSET:\n    case REDIS_ZSET_ZIPLIST:\n    case REDIS_HASH_ZIPLIST:\n        if (!processStringObject(NULL)) {\n            SHIFT_ERROR(offset, \"Error reading entry value\");\n            return 0;\n        }\n    break;\n    case REDIS_LIST:\n    case REDIS_SET:\n        for (i = 0; i < length; i++) {\n            offset = CURR_OFFSET;\n            if (!processStringObject(NULL)) {\n                SHIFT_ERROR(offset, \"Error reading element at index %d (length: %d)\", i, length);\n                return 0;\n            }\n        }\n    break;\n    case REDIS_ZSET:\n        for (i = 0; i < length; i++) {\n            offset = CURR_OFFSET;\n            if (!processStringObject(NULL)) {\n                SHIFT_ERROR(offset, \"Error reading element key at index %d (length: %d)\", i, length);\n                return 0;\n            }\n            offset = CURR_OFFSET;\n            if (!processDoubleValue(NULL)) {\n                SHIFT_ERROR(offset, \"Error reading element value at index %d (length: %d)\", i, length);\n                return 0;\n            }\n        }\n    break;\n    case REDIS_HASH:\n        for (i = 0; i < length; i++) {\n            offset = CURR_OFFSET;\n            if (!processStringObject(NULL)) {\n                SHIFT_ERROR(offset, \"Error reading element key at index %d (length: %d)\", i, length);\n                return 0;\n            }\n            offset = CURR_OFFSET;\n            if (!processStringObject(NULL)) {\n                SHIFT_ERROR(offset, \"Error reading element value at index %d (length: %d)\", i, length);\n                return 0;\n            }\n        }\n    break;\n    default:\n        SHIFT_ERROR(offset, \"Type not implemented\");\n        return 0;\n    }\n    /* because we're done, we assume success */\n    e->success = 1;\n    return 1;\n}\n\nentry loadEntry() {\n    entry e = { NULL, -1, 0 };\n    uint32_t length, offset[4];\n\n    /* reset error container */\n    errors.level = 0;\n\n    offset[0] = CURR_OFFSET;\n    if (!loadType(&e)) {\n        return e;\n    }\n\n    offset[1] = CURR_OFFSET;\n    if (e.type == REDIS_SELECTDB) {\n        if ((length = loadLength(NULL)) == REDIS_RDB_LENERR) {\n            SHIFT_ERROR(offset[1], \"Error reading database number\");\n            return e;\n        }\n        if (length > 63) {\n            SHIFT_ERROR(offset[1], \"Database number out of range (%d)\", length);\n            return e;\n        }\n    } else if (e.type == REDIS_EOF) {\n        if (positions[level].offset < positions[level].size) {\n            SHIFT_ERROR(offset[0], \"Unexpected EOF\");\n        } else {\n            e.success = 1;\n        }\n        return e;\n    } else {\n        /* optionally consume expire */\n        if (e.type == REDIS_EXPIRETIME ||\n            e.type == REDIS_EXPIRETIME_MS) {\n            if (!processTime(e.type)) return e;\n            if (!loadType(&e)) return e;\n        }\n\n        offset[1] = CURR_OFFSET;\n        if (!loadPair(&e)) {\n            SHIFT_ERROR(offset[1], \"Error for type %s\", types[e.type]);\n            return e;\n        }\n    }\n\n    /* all entries are followed by a valid type:\n     * e.g. a new entry, SELECTDB, EXPIRE, EOF */\n    offset[2] = CURR_OFFSET;\n    if (peekType() == -1) {\n        SHIFT_ERROR(offset[2], \"Followed by invalid type\");\n        SHIFT_ERROR(offset[0], \"Error for type %s\", types[e.type]);\n        e.success = 0;\n    } else {\n        e.success = 1;\n    }\n\n    return e;\n}\n\nvoid printCentered(int indent, int width, char* body) {\n    char head[256], tail[256];\n    memset(head, '\\0', 256);\n    memset(tail, '\\0', 256);\n\n    memset(head, '=', indent);\n    memset(tail, '=', width - 2 - indent - strlen(body));\n    printf(\"%s %s %s\\n\", head, body, tail);\n}\n\nvoid printValid(uint64_t ops, uint64_t bytes) {\n    char body[80];\n    sprintf(body, \"Processed %llu valid opcodes (in %llu bytes)\",\n        (unsigned long long) ops, (unsigned long long) bytes);\n    printCentered(4, 80, body);\n}\n\nvoid printSkipped(uint64_t bytes, uint64_t offset) {\n    char body[80];\n    sprintf(body, \"Skipped %llu bytes (resuming at 0x%08llx)\",\n        (unsigned long long) bytes, (unsigned long long) offset);\n    printCentered(4, 80, body);\n}\n\nvoid printErrorStack(entry *e) {\n    unsigned int i;\n    char body[64];\n\n    if (e->type == -1) {\n        sprintf(body, \"Error trace\");\n    } else if (e->type >= 253) {\n        sprintf(body, \"Error trace (%s)\", types[e->type]);\n    } else if (!e->key) {\n        sprintf(body, \"Error trace (%s: (unknown))\", types[e->type]);\n    } else {\n        char tmp[41];\n        strncpy(tmp, e->key, 40);\n\n        /* display truncation at the last 3 chars */\n        if (strlen(e->key) > 40) {\n            memset(&tmp[37], '.', 3);\n        }\n\n        /* display unprintable characters as ? */\n        for (i = 0; i < strlen(tmp); i++) {\n            if (tmp[i] <= 32) tmp[i] = '?';\n        }\n        sprintf(body, \"Error trace (%s: %s)\", types[e->type], tmp);\n    }\n\n    printCentered(4, 80, body);\n\n    /* display error stack */\n    for (i = 0; i < errors.level; i++) {\n        printf(\"0x%08lx - %s\\n\",\n            (unsigned long) errors.offset[i], errors.error[i]);\n    }\n}\n\nvoid process(void) {\n    uint64_t num_errors = 0, num_valid_ops = 0, num_valid_bytes = 0;\n    entry entry;\n    int dump_version = processHeader();\n\n    /* Exclude the final checksum for RDB >= 5. Will be checked at the end. */\n    if (dump_version >= 5) {\n        if (positions[0].size < 8) {\n            printf(\"RDB version >= 5 but no room for checksum.\\n\");\n            exit(1);\n        }\n        positions[0].size -= 8;\n    }\n\n    level = 1;\n    while(positions[0].offset < positions[0].size) {\n        positions[1] = positions[0];\n\n        entry = loadEntry();\n        if (!entry.success) {\n            printValid(num_valid_ops, num_valid_bytes);\n            printErrorStack(&entry);\n            num_errors++;\n            num_valid_ops = 0;\n            num_valid_bytes = 0;\n\n            /* search for next valid entry */\n            uint64_t offset = positions[0].offset + 1;\n            int i = 0;\n\n            while (!entry.success && offset < positions[0].size) {\n                positions[1].offset = offset;\n\n                /* find 3 consecutive valid entries */\n                for (i = 0; i < 3; i++) {\n                    entry = loadEntry();\n                    if (!entry.success) break;\n                }\n                /* check if we found 3 consecutive valid entries */\n                if (i < 3) {\n                    offset++;\n                }\n            }\n\n            /* print how many bytes we have skipped to find a new valid opcode */\n            if (offset < positions[0].size) {\n                printSkipped(offset - positions[0].offset, offset);\n            }\n\n            positions[0].offset = offset;\n        } else {\n            num_valid_ops++;\n            num_valid_bytes += positions[1].offset - positions[0].offset;\n\n            /* advance position */\n            positions[0] = positions[1];\n        }\n        free(entry.key);\n    }\n\n    /* because there is another potential error,\n     * print how many valid ops we have processed */\n    printValid(num_valid_ops, num_valid_bytes);\n\n    /* expect an eof */\n    if (entry.type != REDIS_EOF) {\n        /* last byte should be EOF, add error */\n        errors.level = 0;\n        SHIFT_ERROR(positions[0].offset, \"Expected EOF, got %s\", types[entry.type]);\n\n        /* this is an EOF error so reset type */\n        entry.type = -1;\n        printErrorStack(&entry);\n\n        num_errors++;\n    }\n\n    /* Verify checksum */\n    if (dump_version >= 5) {\n        uint64_t crc = crc64(0,positions[0].data,positions[0].size);\n        uint64_t crc2;\n        unsigned char *p = (unsigned char*)positions[0].data+positions[0].size;\n        crc2 = ((uint64_t)p[0] << 0) |\n               ((uint64_t)p[1] << 8) |\n               ((uint64_t)p[2] << 16) |\n               ((uint64_t)p[3] << 24) |\n               ((uint64_t)p[4] << 32) |\n               ((uint64_t)p[5] << 40) |\n               ((uint64_t)p[6] << 48) |\n               ((uint64_t)p[7] << 56);\n        if (crc != crc2) {\n            SHIFT_ERROR(positions[0].offset, \"RDB CRC64 does not match.\");\n        } else {\n            printf(\"CRC64 checksum is OK\\n\");\n        }\n    }\n\n    /* print summary on errors */\n    if (num_errors) {\n        printf(\"\\n\");\n        printf(\"Total unprocessable opcodes: %llu\\n\",\n            (unsigned long long) num_errors);\n    }\n}\n\nint main(int argc, char **argv) {\n    /* expect the first argument to be the dump file */\n    if (argc <= 1) {\n        printf(\"Usage: %s <dump.rdb>\\n\", argv[0]);\n        exit(0);\n    }\n\n    int fd;\n    off_t size;\n    struct stat stat;\n    void *data;\n\n    fd = open(argv[1], O_RDONLY);\n    if (fd < 1) {\n        ERROR(\"Cannot open file: %s\\n\", argv[1]);\n    }\n    if (fstat(fd, &stat) == -1) {\n        ERROR(\"Cannot stat: %s\\n\", argv[1]);\n    } else {\n        size = stat.st_size;\n    }\n\n    if (sizeof(size_t) == sizeof(int32_t) && size >= INT_MAX) {\n        ERROR(\"Cannot check dump files >2GB on a 32-bit platform\\n\");\n    }\n\n    data = mmap(NULL, size, PROT_READ, MAP_SHARED, fd, 0);\n    if (data == MAP_FAILED) {\n        ERROR(\"Cannot mmap: %s\\n\", argv[1]);\n    }\n\n    /* Initialize static vars */\n    positions[0].data = data;\n    positions[0].size = size;\n    positions[0].offset = 0;\n    errors.level = 0;\n\n    /* Object types */\n    sprintf(types[REDIS_STRING], \"STRING\");\n    sprintf(types[REDIS_LIST], \"LIST\");\n    sprintf(types[REDIS_SET], \"SET\");\n    sprintf(types[REDIS_ZSET], \"ZSET\");\n    sprintf(types[REDIS_HASH], \"HASH\");\n\n    /* Object types only used for dumping to disk */\n    sprintf(types[REDIS_EXPIRETIME], \"EXPIRETIME\");\n    sprintf(types[REDIS_SELECTDB], \"SELECTDB\");\n    sprintf(types[REDIS_EOF], \"EOF\");\n\n    /* Double constants initialization */\n    R_Zero = 0.0;\n    R_PosInf = 1.0/R_Zero;\n    R_NegInf = -1.0/R_Zero;\n    R_Nan = R_Zero/R_Zero;\n\n    process();\n\n    munmap(data, size);\n    close(fd);\n    return 0;\n}\n"
  },
  {
    "path": "extern/deprecated/redis-2.8.21/src/redis-cli.c",
    "content": "/* Redis CLI (command line interface)\n *\n * Copyright (c) 2009-2012, Salvatore Sanfilippo <antirez at gmail dot com>\n * All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions are met:\n *\n *   * Redistributions of source code must retain the above copyright notice,\n *     this list of conditions and the following disclaimer.\n *   * Redistributions in binary form must reproduce the above copyright\n *     notice, this list of conditions and the following disclaimer in the\n *     documentation and/or other materials provided with the distribution.\n *   * Neither the name of Redis nor the names of its contributors may be used\n *     to endorse or promote products derived from this software without\n *     specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\"\n * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\n * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE\n * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR\n * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF\n * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS\n * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN\n * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)\n * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE\n * POSSIBILITY OF SUCH DAMAGE.\n */\n\n#include \"fmacros.h\"\n#include \"version.h\"\n\n#include <stdio.h>\n#include <string.h>\n#include <stdlib.h>\n#include <signal.h>\n#include <unistd.h>\n#include <time.h>\n#include <ctype.h>\n#include <errno.h>\n#include <sys/stat.h>\n#include <sys/time.h>\n#include <assert.h>\n#include <fcntl.h>\n#include <limits.h>\n#include <math.h>\n\n#include \"hiredis.h\"\n#include \"sds.h\"\n#include \"zmalloc.h\"\n#include \"linenoise.h\"\n#include \"help.h\"\n#include \"anet.h\"\n#include \"ae.h\"\n\n#define REDIS_NOTUSED(V) ((void) V)\n\n#define OUTPUT_STANDARD 0\n#define OUTPUT_RAW 1\n#define OUTPUT_CSV 2\n#define REDIS_CLI_KEEPALIVE_INTERVAL 15 /* seconds */\n#define REDIS_CLI_DEFAULT_PIPE_TIMEOUT 30 /* seconds */\n#define REDIS_CLI_HISTFILE_ENV \"REDISCLI_HISTFILE\"\n#define REDIS_CLI_HISTFILE_DEFAULT \".rediscli_history\"\n\nstatic redisContext *context;\nstatic struct config {\n    char *hostip;\n    int hostport;\n    char *hostsocket;\n    long repeat;\n    long interval;\n    int dbnum;\n    int interactive;\n    int shutdown;\n    int monitor_mode;\n    int pubsub_mode;\n    int latency_mode;\n    int latency_dist_mode;\n    int latency_history;\n    int lru_test_mode;\n    long long lru_test_sample_size;\n    int cluster_mode;\n    int cluster_reissue_command;\n    int slave_mode;\n    int pipe_mode;\n    int pipe_timeout;\n    int getrdb_mode;\n    int stat_mode;\n    int scan_mode;\n    int intrinsic_latency_mode;\n    int intrinsic_latency_duration;\n    char *pattern;\n    char *rdb_filename;\n    int bigkeys;\n    int stdinarg; /* get last arg from stdin. (-x option) */\n    char *auth;\n    int output; /* output mode, see OUTPUT_* defines */\n    sds mb_delim;\n    char prompt[128];\n    char *eval;\n    int last_cmd_type;\n} config;\n\nstatic volatile sig_atomic_t force_cancel_loop = 0;\nstatic void usage(void);\nstatic void slaveMode(void);\nchar *redisGitSHA1(void);\nchar *redisGitDirty(void);\n\n/*------------------------------------------------------------------------------\n * Utility functions\n *--------------------------------------------------------------------------- */\n\nstatic long long ustime(void) {\n    struct timeval tv;\n    long long ust;\n\n    gettimeofday(&tv, NULL);\n    ust = ((long long)tv.tv_sec)*1000000;\n    ust += tv.tv_usec;\n    return ust;\n}\n\nstatic long long mstime(void) {\n    return ustime()/1000;\n}\n\nstatic void cliRefreshPrompt(void) {\n    int len;\n\n    if (config.hostsocket != NULL)\n        len = snprintf(config.prompt,sizeof(config.prompt),\"redis %s\",\n                       config.hostsocket);\n    else\n        len = snprintf(config.prompt,sizeof(config.prompt),\n                       strchr(config.hostip,':') ? \"[%s]:%d\" : \"%s:%d\",\n                       config.hostip, config.hostport);\n    /* Add [dbnum] if needed */\n    if (config.dbnum != 0 && config.last_cmd_type != REDIS_REPLY_ERROR)\n        len += snprintf(config.prompt+len,sizeof(config.prompt)-len,\"[%d]\",\n            config.dbnum);\n    snprintf(config.prompt+len,sizeof(config.prompt)-len,\"> \");\n}\n\nstatic sds getHistoryPath() {\n    char *path = NULL;\n    sds historyPath = NULL;\n\n    /* check the env for a histfile override */\n    path = getenv(REDIS_CLI_HISTFILE_ENV);\n    if (path != NULL && *path != '\\0') {\n        if (!strcmp(\"/dev/null\", path)) {\n            return NULL;\n        }\n\n        /* if the env is set, return it */\n        historyPath = sdscatprintf(sdsempty(), \"%s\", path);\n    } else {\n        char *home = getenv(\"HOME\");\n        if (home != NULL && *home != '\\0') {\n            /* otherwise, return the default */\n            historyPath = sdscatprintf(sdsempty(), \"%s/%s\", home, REDIS_CLI_HISTFILE_DEFAULT);\n        }\n    }\n\n    return historyPath;\n}\n\n/*------------------------------------------------------------------------------\n * Help functions\n *--------------------------------------------------------------------------- */\n\n#define CLI_HELP_COMMAND 1\n#define CLI_HELP_GROUP 2\n\ntypedef struct {\n    int type;\n    int argc;\n    sds *argv;\n    sds full;\n\n    /* Only used for help on commands */\n    struct commandHelp *org;\n} helpEntry;\n\nstatic helpEntry *helpEntries;\nstatic int helpEntriesLen;\n\nstatic sds cliVersion(void) {\n    sds version;\n    version = sdscatprintf(sdsempty(), \"%s\", REDIS_VERSION);\n\n    /* Add git commit and working tree status when available */\n    if (strtoll(redisGitSHA1(),NULL,16)) {\n        version = sdscatprintf(version, \" (git:%s\", redisGitSHA1());\n        if (strtoll(redisGitDirty(),NULL,10))\n            version = sdscatprintf(version, \"-dirty\");\n        version = sdscat(version, \")\");\n    }\n    return version;\n}\n\nstatic void cliInitHelp(void) {\n    int commandslen = sizeof(commandHelp)/sizeof(struct commandHelp);\n    int groupslen = sizeof(commandGroups)/sizeof(char*);\n    int i, len, pos = 0;\n    helpEntry tmp;\n\n    helpEntriesLen = len = commandslen+groupslen;\n    helpEntries = malloc(sizeof(helpEntry)*len);\n\n    for (i = 0; i < groupslen; i++) {\n        tmp.argc = 1;\n        tmp.argv = malloc(sizeof(sds));\n        tmp.argv[0] = sdscatprintf(sdsempty(),\"@%s\",commandGroups[i]);\n        tmp.full = tmp.argv[0];\n        tmp.type = CLI_HELP_GROUP;\n        tmp.org = NULL;\n        helpEntries[pos++] = tmp;\n    }\n\n    for (i = 0; i < commandslen; i++) {\n        tmp.argv = sdssplitargs(commandHelp[i].name,&tmp.argc);\n        tmp.full = sdsnew(commandHelp[i].name);\n        tmp.type = CLI_HELP_COMMAND;\n        tmp.org = &commandHelp[i];\n        helpEntries[pos++] = tmp;\n    }\n}\n\n/* Output command help to stdout. */\nstatic void cliOutputCommandHelp(struct commandHelp *help, int group) {\n    printf(\"\\r\\n  \\x1b[1m%s\\x1b[0m \\x1b[90m%s\\x1b[0m\\r\\n\", help->name, help->params);\n    printf(\"  \\x1b[33msummary:\\x1b[0m %s\\r\\n\", help->summary);\n    printf(\"  \\x1b[33msince:\\x1b[0m %s\\r\\n\", help->since);\n    if (group) {\n        printf(\"  \\x1b[33mgroup:\\x1b[0m %s\\r\\n\", commandGroups[help->group]);\n    }\n}\n\n/* Print generic help. */\nstatic void cliOutputGenericHelp(void) {\n    sds version = cliVersion();\n    printf(\n        \"redis-cli %s\\r\\n\"\n        \"Type: \\\"help @<group>\\\" to get a list of commands in <group>\\r\\n\"\n        \"      \\\"help <command>\\\" for help on <command>\\r\\n\"\n        \"      \\\"help <tab>\\\" to get a list of possible help topics\\r\\n\"\n        \"      \\\"quit\\\" to exit\\r\\n\",\n        version\n    );\n    sdsfree(version);\n}\n\n/* Output all command help, filtering by group or command name. */\nstatic void cliOutputHelp(int argc, char **argv) {\n    int i, j, len;\n    int group = -1;\n    helpEntry *entry;\n    struct commandHelp *help;\n\n    if (argc == 0) {\n        cliOutputGenericHelp();\n        return;\n    } else if (argc > 0 && argv[0][0] == '@') {\n        len = sizeof(commandGroups)/sizeof(char*);\n        for (i = 0; i < len; i++) {\n            if (strcasecmp(argv[0]+1,commandGroups[i]) == 0) {\n                group = i;\n                break;\n            }\n        }\n    }\n\n    assert(argc > 0);\n    for (i = 0; i < helpEntriesLen; i++) {\n        entry = &helpEntries[i];\n        if (entry->type != CLI_HELP_COMMAND) continue;\n\n        help = entry->org;\n        if (group == -1) {\n            /* Compare all arguments */\n            if (argc == entry->argc) {\n                for (j = 0; j < argc; j++) {\n                    if (strcasecmp(argv[j],entry->argv[j]) != 0) break;\n                }\n                if (j == argc) {\n                    cliOutputCommandHelp(help,1);\n                }\n            }\n        } else {\n            if (group == help->group) {\n                cliOutputCommandHelp(help,0);\n            }\n        }\n    }\n    printf(\"\\r\\n\");\n}\n\nstatic void completionCallback(const char *buf, linenoiseCompletions *lc) {\n    size_t startpos = 0;\n    int mask;\n    int i;\n    size_t matchlen;\n    sds tmp;\n\n    if (strncasecmp(buf,\"help \",5) == 0) {\n        startpos = 5;\n        while (isspace(buf[startpos])) startpos++;\n        mask = CLI_HELP_COMMAND | CLI_HELP_GROUP;\n    } else {\n        mask = CLI_HELP_COMMAND;\n    }\n\n    for (i = 0; i < helpEntriesLen; i++) {\n        if (!(helpEntries[i].type & mask)) continue;\n\n        matchlen = strlen(buf+startpos);\n        if (strncasecmp(buf+startpos,helpEntries[i].full,matchlen) == 0) {\n            tmp = sdsnewlen(buf,startpos);\n            tmp = sdscat(tmp,helpEntries[i].full);\n            linenoiseAddCompletion(lc,tmp);\n            sdsfree(tmp);\n        }\n    }\n}\n\n/*------------------------------------------------------------------------------\n * Networking / parsing\n *--------------------------------------------------------------------------- */\n\n/* Send AUTH command to the server */\nstatic int cliAuth() {\n    redisReply *reply;\n    if (config.auth == NULL) return REDIS_OK;\n\n    reply = redisCommand(context,\"AUTH %s\",config.auth);\n    if (reply != NULL) {\n        freeReplyObject(reply);\n        return REDIS_OK;\n    }\n    return REDIS_ERR;\n}\n\n/* Send SELECT dbnum to the server */\nstatic int cliSelect() {\n    redisReply *reply;\n    if (config.dbnum == 0) return REDIS_OK;\n\n    reply = redisCommand(context,\"SELECT %d\",config.dbnum);\n    if (reply != NULL) {\n        int result = REDIS_OK;\n        if (reply->type == REDIS_REPLY_ERROR) result = REDIS_ERR;\n        freeReplyObject(reply);\n        return result;\n    }\n    return REDIS_ERR;\n}\n\n/* Connect to the server. If force is not zero the connection is performed\n * even if there is already a connected socket. */\nstatic int cliConnect(int force) {\n    if (context == NULL || force) {\n        if (context != NULL)\n            redisFree(context);\n\n        if (config.hostsocket == NULL) {\n            context = redisConnect(config.hostip,config.hostport);\n        } else {\n            context = redisConnectUnix(config.hostsocket);\n        }\n\n        if (context->err) {\n            fprintf(stderr,\"Could not connect to Redis at \");\n            if (config.hostsocket == NULL)\n                fprintf(stderr,\"%s:%d: %s\\n\",config.hostip,config.hostport,context->errstr);\n            else\n                fprintf(stderr,\"%s: %s\\n\",config.hostsocket,context->errstr);\n            redisFree(context);\n            context = NULL;\n            return REDIS_ERR;\n        }\n\n        /* Set aggressive KEEP_ALIVE socket option in the Redis context socket\n         * in order to prevent timeouts caused by the execution of long\n         * commands. At the same time this improves the detection of real\n         * errors. */\n        anetKeepAlive(NULL, context->fd, REDIS_CLI_KEEPALIVE_INTERVAL);\n\n        /* Do AUTH and select the right DB. */\n        if (cliAuth() != REDIS_OK)\n            return REDIS_ERR;\n        if (cliSelect() != REDIS_OK)\n            return REDIS_ERR;\n    }\n    return REDIS_OK;\n}\n\nstatic void cliPrintContextError(void) {\n    if (context == NULL) return;\n    fprintf(stderr,\"Error: %s\\n\",context->errstr);\n}\n\nstatic sds cliFormatReplyTTY(redisReply *r, char *prefix) {\n    sds out = sdsempty();\n    switch (r->type) {\n    case REDIS_REPLY_ERROR:\n        out = sdscatprintf(out,\"(error) %s\\n\", r->str);\n    break;\n    case REDIS_REPLY_STATUS:\n        out = sdscat(out,r->str);\n        out = sdscat(out,\"\\n\");\n    break;\n    case REDIS_REPLY_INTEGER:\n        out = sdscatprintf(out,\"(integer) %lld\\n\",r->integer);\n    break;\n    case REDIS_REPLY_STRING:\n        /* If you are producing output for the standard output we want\n        * a more interesting output with quoted characters and so forth */\n        out = sdscatrepr(out,r->str,r->len);\n        out = sdscat(out,\"\\n\");\n    break;\n    case REDIS_REPLY_NIL:\n        out = sdscat(out,\"(nil)\\n\");\n    break;\n    case REDIS_REPLY_ARRAY:\n        if (r->elements == 0) {\n            out = sdscat(out,\"(empty list or set)\\n\");\n        } else {\n            unsigned int i, idxlen = 0;\n            char _prefixlen[16];\n            char _prefixfmt[16];\n            sds _prefix;\n            sds tmp;\n\n            /* Calculate chars needed to represent the largest index */\n            i = r->elements;\n            do {\n                idxlen++;\n                i /= 10;\n            } while(i);\n\n            /* Prefix for nested multi bulks should grow with idxlen+2 spaces */\n            memset(_prefixlen,' ',idxlen+2);\n            _prefixlen[idxlen+2] = '\\0';\n            _prefix = sdscat(sdsnew(prefix),_prefixlen);\n\n            /* Setup prefix format for every entry */\n            snprintf(_prefixfmt,sizeof(_prefixfmt),\"%%s%%%dd) \",idxlen);\n\n            for (i = 0; i < r->elements; i++) {\n                /* Don't use the prefix for the first element, as the parent\n                 * caller already prepended the index number. */\n                out = sdscatprintf(out,_prefixfmt,i == 0 ? \"\" : prefix,i+1);\n\n                /* Format the multi bulk entry */\n                tmp = cliFormatReplyTTY(r->element[i],_prefix);\n                out = sdscatlen(out,tmp,sdslen(tmp));\n                sdsfree(tmp);\n            }\n            sdsfree(_prefix);\n        }\n    break;\n    default:\n        fprintf(stderr,\"Unknown reply type: %d\\n\", r->type);\n        exit(1);\n    }\n    return out;\n}\n\nstatic sds cliFormatReplyRaw(redisReply *r) {\n    sds out = sdsempty(), tmp;\n    size_t i;\n\n    switch (r->type) {\n    case REDIS_REPLY_NIL:\n        /* Nothing... */\n        break;\n    case REDIS_REPLY_ERROR:\n        out = sdscatlen(out,r->str,r->len);\n        out = sdscatlen(out,\"\\n\",1);\n        break;\n    case REDIS_REPLY_STATUS:\n    case REDIS_REPLY_STRING:\n        out = sdscatlen(out,r->str,r->len);\n        break;\n    case REDIS_REPLY_INTEGER:\n        out = sdscatprintf(out,\"%lld\",r->integer);\n        break;\n    case REDIS_REPLY_ARRAY:\n        for (i = 0; i < r->elements; i++) {\n            if (i > 0) out = sdscat(out,config.mb_delim);\n            tmp = cliFormatReplyRaw(r->element[i]);\n            out = sdscatlen(out,tmp,sdslen(tmp));\n            sdsfree(tmp);\n        }\n        break;\n    default:\n        fprintf(stderr,\"Unknown reply type: %d\\n\", r->type);\n        exit(1);\n    }\n    return out;\n}\n\nstatic sds cliFormatReplyCSV(redisReply *r) {\n    unsigned int i;\n\n    sds out = sdsempty();\n    switch (r->type) {\n    case REDIS_REPLY_ERROR:\n        out = sdscat(out,\"ERROR,\");\n        out = sdscatrepr(out,r->str,strlen(r->str));\n    break;\n    case REDIS_REPLY_STATUS:\n        out = sdscatrepr(out,r->str,r->len);\n    break;\n    case REDIS_REPLY_INTEGER:\n        out = sdscatprintf(out,\"%lld\",r->integer);\n    break;\n    case REDIS_REPLY_STRING:\n        out = sdscatrepr(out,r->str,r->len);\n    break;\n    case REDIS_REPLY_NIL:\n        out = sdscat(out,\"NIL\");\n    break;\n    case REDIS_REPLY_ARRAY:\n        for (i = 0; i < r->elements; i++) {\n            sds tmp = cliFormatReplyCSV(r->element[i]);\n            out = sdscatlen(out,tmp,sdslen(tmp));\n            if (i != r->elements-1) out = sdscat(out,\",\");\n            sdsfree(tmp);\n        }\n    break;\n    default:\n        fprintf(stderr,\"Unknown reply type: %d\\n\", r->type);\n        exit(1);\n    }\n    return out;\n}\n\nstatic int cliReadReply(int output_raw_strings) {\n    void *_reply;\n    redisReply *reply;\n    sds out = NULL;\n    int output = 1;\n\n    if (redisGetReply(context,&_reply) != REDIS_OK) {\n        if (config.shutdown) {\n            redisFree(context);\n            context = NULL;\n            return REDIS_OK;\n        }\n        if (config.interactive) {\n            /* Filter cases where we should reconnect */\n            if (context->err == REDIS_ERR_IO &&\n                (errno == ECONNRESET || errno == EPIPE))\n                return REDIS_ERR;\n            if (context->err == REDIS_ERR_EOF)\n                return REDIS_ERR;\n        }\n        cliPrintContextError();\n        exit(1);\n        return REDIS_ERR; /* avoid compiler warning */\n    }\n\n    reply = (redisReply*)_reply;\n\n    config.last_cmd_type = reply->type;\n\n    /* Check if we need to connect to a different node and reissue the\n     * request. */\n    if (config.cluster_mode && reply->type == REDIS_REPLY_ERROR &&\n        (!strncmp(reply->str,\"MOVED\",5) || !strcmp(reply->str,\"ASK\")))\n    {\n        char *p = reply->str, *s;\n        int slot;\n\n        output = 0;\n        /* Comments show the position of the pointer as:\n         *\n         * [S] for pointer 's'\n         * [P] for pointer 'p'\n         */\n        s = strchr(p,' ');      /* MOVED[S]3999 127.0.0.1:6381 */\n        p = strchr(s+1,' ');    /* MOVED[S]3999[P]127.0.0.1:6381 */\n        *p = '\\0';\n        slot = atoi(s+1);\n        s = strchr(p+1,':');    /* MOVED 3999[P]127.0.0.1[S]6381 */\n        *s = '\\0';\n        sdsfree(config.hostip);\n        config.hostip = sdsnew(p+1);\n        config.hostport = atoi(s+1);\n        if (config.interactive)\n            printf(\"-> Redirected to slot [%d] located at %s:%d\\n\",\n                slot, config.hostip, config.hostport);\n        config.cluster_reissue_command = 1;\n    }\n\n    if (output) {\n        if (output_raw_strings) {\n            out = cliFormatReplyRaw(reply);\n        } else {\n            if (config.output == OUTPUT_RAW) {\n                out = cliFormatReplyRaw(reply);\n                out = sdscat(out,\"\\n\");\n            } else if (config.output == OUTPUT_STANDARD) {\n                out = cliFormatReplyTTY(reply,\"\");\n            } else if (config.output == OUTPUT_CSV) {\n                out = cliFormatReplyCSV(reply);\n                out = sdscat(out,\"\\n\");\n            }\n        }\n        fwrite(out,sdslen(out),1,stdout);\n        sdsfree(out);\n    }\n    freeReplyObject(reply);\n    return REDIS_OK;\n}\n\nstatic int cliSendCommand(int argc, char **argv, int repeat) {\n    char *command = argv[0];\n    size_t *argvlen;\n    int j, output_raw;\n\n    if (!strcasecmp(command,\"help\") || !strcasecmp(command,\"?\")) {\n        cliOutputHelp(--argc, ++argv);\n        return REDIS_OK;\n    }\n\n    if (context == NULL) return REDIS_ERR;\n\n    output_raw = 0;\n    if (!strcasecmp(command,\"info\") ||\n        (argc == 2 && !strcasecmp(command,\"cluster\") &&\n                      (!strcasecmp(argv[1],\"nodes\") ||\n                       !strcasecmp(argv[1],\"info\"))) ||\n        (argc == 2 && !strcasecmp(command,\"client\") &&\n                       !strcasecmp(argv[1],\"list\")) ||\n        (argc == 3 && !strcasecmp(command,\"latency\") &&\n                       !strcasecmp(argv[1],\"graph\")) ||\n        (argc == 2 && !strcasecmp(command,\"latency\") &&\n                       !strcasecmp(argv[1],\"doctor\")))\n    {\n        output_raw = 1;\n    }\n\n    if (!strcasecmp(command,\"shutdown\")) config.shutdown = 1;\n    if (!strcasecmp(command,\"monitor\")) config.monitor_mode = 1;\n    if (!strcasecmp(command,\"subscribe\") ||\n        !strcasecmp(command,\"psubscribe\")) config.pubsub_mode = 1;\n    if (!strcasecmp(command,\"sync\") ||\n        !strcasecmp(command,\"psync\")) config.slave_mode = 1;\n\n    /* Setup argument length */\n    argvlen = malloc(argc*sizeof(size_t));\n    for (j = 0; j < argc; j++)\n        argvlen[j] = sdslen(argv[j]);\n\n    while(repeat--) {\n        redisAppendCommandArgv(context,argc,(const char**)argv,argvlen);\n        while (config.monitor_mode) {\n            if (cliReadReply(output_raw) != REDIS_OK) exit(1);\n            fflush(stdout);\n        }\n\n        if (config.pubsub_mode) {\n            if (config.output != OUTPUT_RAW)\n                printf(\"Reading messages... (press Ctrl-C to quit)\\n\");\n            while (1) {\n                if (cliReadReply(output_raw) != REDIS_OK) exit(1);\n            }\n        }\n\n        if (config.slave_mode) {\n            printf(\"Entering slave output mode...  (press Ctrl-C to quit)\\n\");\n            slaveMode();\n            config.slave_mode = 0;\n            free(argvlen);\n            return REDIS_ERR;  /* Error = slaveMode lost connection to master */\n        }\n\n        if (cliReadReply(output_raw) != REDIS_OK) {\n            free(argvlen);\n            return REDIS_ERR;\n        } else {\n            /* Store database number when SELECT was successfully executed. */\n            if (!strcasecmp(command,\"select\") && argc == 2) {\n                config.dbnum = atoi(argv[1]);\n                cliRefreshPrompt();\n            } else if (!strcasecmp(command,\"auth\") && argc == 2) {\n                cliSelect();\n            }\n        }\n        if (config.interval) usleep(config.interval);\n        fflush(stdout); /* Make it grep friendly */\n    }\n\n    free(argvlen);\n    return REDIS_OK;\n}\n\n/* Send a command reconnecting the link if needed. */\nstatic redisReply *reconnectingRedisCommand(redisContext *c, const char *fmt, ...) {\n    redisReply *reply = NULL;\n    int tries = 0;\n    va_list ap;\n\n    assert(!c->err);\n    while(reply == NULL) {\n        while (c->err & (REDIS_ERR_IO | REDIS_ERR_EOF)) {\n            printf(\"\\r\\x1b[0K\"); /* Cursor to left edge + clear line. */\n            printf(\"Reconnecting... %d\\r\", ++tries);\n            fflush(stdout);\n\n            redisFree(c);\n            c = redisConnect(config.hostip,config.hostport);\n            usleep(1000000);\n        }\n\n        va_start(ap,fmt);\n        reply = redisvCommand(c,fmt,ap);\n        va_end(ap);\n\n        if (c->err && !(c->err & (REDIS_ERR_IO | REDIS_ERR_EOF))) {\n            fprintf(stderr, \"Error: %s\\n\", c->errstr);\n            exit(1);\n        } else if (tries > 0) {\n            printf(\"\\r\\x1b[0K\"); /* Cursor to left edge + clear line. */\n        }\n    }\n\n    context = c;\n    return reply;\n}\n\n/*------------------------------------------------------------------------------\n * User interface\n *--------------------------------------------------------------------------- */\n\nstatic int parseOptions(int argc, char **argv) {\n    int i;\n\n    for (i = 1; i < argc; i++) {\n        int lastarg = i==argc-1;\n\n        if (!strcmp(argv[i],\"-h\") && !lastarg) {\n            sdsfree(config.hostip);\n            config.hostip = sdsnew(argv[++i]);\n        } else if (!strcmp(argv[i],\"-h\") && lastarg) {\n            usage();\n        } else if (!strcmp(argv[i],\"--help\")) {\n            usage();\n        } else if (!strcmp(argv[i],\"-x\")) {\n            config.stdinarg = 1;\n        } else if (!strcmp(argv[i],\"-p\") && !lastarg) {\n            config.hostport = atoi(argv[++i]);\n        } else if (!strcmp(argv[i],\"-s\") && !lastarg) {\n            config.hostsocket = argv[++i];\n        } else if (!strcmp(argv[i],\"-r\") && !lastarg) {\n            config.repeat = strtoll(argv[++i],NULL,10);\n        } else if (!strcmp(argv[i],\"-i\") && !lastarg) {\n            double seconds = atof(argv[++i]);\n            config.interval = seconds*1000000;\n        } else if (!strcmp(argv[i],\"-n\") && !lastarg) {\n            config.dbnum = atoi(argv[++i]);\n        } else if (!strcmp(argv[i],\"-a\") && !lastarg) {\n            config.auth = argv[++i];\n        } else if (!strcmp(argv[i],\"--raw\")) {\n            config.output = OUTPUT_RAW;\n        } else if (!strcmp(argv[i],\"--no-raw\")) {\n            config.output = OUTPUT_STANDARD;\n        } else if (!strcmp(argv[i],\"--csv\")) {\n            config.output = OUTPUT_CSV;\n        } else if (!strcmp(argv[i],\"--latency\")) {\n            config.latency_mode = 1;\n        } else if (!strcmp(argv[i],\"--latency-dist\")) {\n            config.latency_dist_mode = 1;\n        } else if (!strcmp(argv[i],\"--latency-history\")) {\n            config.latency_mode = 1;\n            config.latency_history = 1;\n        } else if (!strcmp(argv[i],\"--lru-test\") && !lastarg) {\n            config.lru_test_mode = 1;\n            config.lru_test_sample_size = strtoll(argv[++i],NULL,10);\n        } else if (!strcmp(argv[i],\"--slave\")) {\n            config.slave_mode = 1;\n        } else if (!strcmp(argv[i],\"--stat\")) {\n            config.stat_mode = 1;\n        } else if (!strcmp(argv[i],\"--scan\")) {\n            config.scan_mode = 1;\n        } else if (!strcmp(argv[i],\"--pattern\") && !lastarg) {\n            config.pattern = argv[++i];\n        } else if (!strcmp(argv[i],\"--intrinsic-latency\") && !lastarg) {\n            config.intrinsic_latency_mode = 1;\n            config.intrinsic_latency_duration = atoi(argv[++i]);\n        } else if (!strcmp(argv[i],\"--rdb\") && !lastarg) {\n            config.getrdb_mode = 1;\n            config.rdb_filename = argv[++i];\n        } else if (!strcmp(argv[i],\"--pipe\")) {\n            config.pipe_mode = 1;\n        } else if (!strcmp(argv[i],\"--pipe-timeout\") && !lastarg) {\n            config.pipe_timeout = atoi(argv[++i]);\n        } else if (!strcmp(argv[i],\"--bigkeys\")) {\n            config.bigkeys = 1;\n        } else if (!strcmp(argv[i],\"--eval\") && !lastarg) {\n            config.eval = argv[++i];\n        } else if (!strcmp(argv[i],\"-c\")) {\n            config.cluster_mode = 1;\n        } else if (!strcmp(argv[i],\"-d\") && !lastarg) {\n            sdsfree(config.mb_delim);\n            config.mb_delim = sdsnew(argv[++i]);\n        } else if (!strcmp(argv[i],\"-v\") || !strcmp(argv[i], \"--version\")) {\n            sds version = cliVersion();\n            printf(\"redis-cli %s\\n\", version);\n            sdsfree(version);\n            exit(0);\n        } else {\n            if (argv[i][0] == '-') {\n                fprintf(stderr,\n                    \"Unrecognized option or bad number of args for: '%s'\\n\",\n                    argv[i]);\n                exit(1);\n            } else {\n                /* Likely the command name, stop here. */\n                break;\n            }\n        }\n    }\n    return i;\n}\n\nstatic sds readArgFromStdin(void) {\n    char buf[1024];\n    sds arg = sdsempty();\n\n    while(1) {\n        int nread = read(fileno(stdin),buf,1024);\n\n        if (nread == 0) break;\n        else if (nread == -1) {\n            perror(\"Reading from standard input\");\n            exit(1);\n        }\n        arg = sdscatlen(arg,buf,nread);\n    }\n    return arg;\n}\n\nstatic void usage(void) {\n    sds version = cliVersion();\n    fprintf(stderr,\n\"redis-cli %s\\n\"\n\"\\n\"\n\"Usage: redis-cli [OPTIONS] [cmd [arg [arg ...]]]\\n\"\n\"  -h <hostname>      Server hostname (default: 127.0.0.1).\\n\"\n\"  -p <port>          Server port (default: 6379).\\n\"\n\"  -s <socket>        Server socket (overrides hostname and port).\\n\"\n\"  -a <password>      Password to use when connecting to the server.\\n\"\n\"  -r <repeat>        Execute specified command N times.\\n\"\n\"  -i <interval>      When -r is used, waits <interval> seconds per command.\\n\"\n\"                     It is possible to specify sub-second times like -i 0.1.\\n\"\n\"  -n <db>            Database number.\\n\"\n\"  -x                 Read last argument from STDIN.\\n\"\n\"  -d <delimiter>     Multi-bulk delimiter in for raw formatting (default: \\\\n).\\n\"\n\"  -c                 Enable cluster mode (follow -ASK and -MOVED redirections).\\n\"\n\"  --raw              Use raw formatting for replies (default when STDOUT is\\n\"\n\"                     not a tty).\\n\"\n\"  --no-raw           Force formatted output even when STDOUT is not a tty.\\n\"\n\"  --csv              Output in CSV format.\\n\"\n\"  --stat             Print rolling stats about server: mem, clients, ...\\n\"\n\"  --latency          Enter a special mode continuously sampling latency.\\n\"\n\"  --latency-history  Like --latency but tracking latency changes over time.\\n\"\n\"                     Default time interval is 15 sec. Change it using -i.\\n\"\n\"  --latency-dist     Shows latency as a spectrum, requires xterm 256 colors.\\n\"\n\"                     Default time interval is 1 sec. Change it using -i.\\n\"\n\"  --lru-test <keys>  Simulate a cache workload with an 80-20 distribution.\\n\"\n\"  --slave            Simulate a slave showing commands received from the master.\\n\"\n\"  --rdb <filename>   Transfer an RDB dump from remote server to local file.\\n\"\n\"  --pipe             Transfer raw Redis protocol from stdin to server.\\n\"\n\"  --pipe-timeout <n> In --pipe mode, abort with error if after sending all data.\\n\"\n\"                     no reply is received within <n> seconds.\\n\"\n\"                     Default timeout: %d. Use 0 to wait forever.\\n\"\n\"  --bigkeys          Sample Redis keys looking for big keys.\\n\"\n\"  --scan             List all keys using the SCAN command.\\n\"\n\"  --pattern <pat>    Useful with --scan to specify a SCAN pattern.\\n\"\n\"  --intrinsic-latency <sec> Run a test to measure intrinsic system latency.\\n\"\n\"                     The test will run for the specified amount of seconds.\\n\"\n\"  --eval <file>      Send an EVAL command using the Lua script at <file>.\\n\"\n\"  --help             Output this help and exit.\\n\"\n\"  --version          Output version and exit.\\n\"\n\"\\n\"\n\"Examples:\\n\"\n\"  cat /etc/passwd | redis-cli -x set mypasswd\\n\"\n\"  redis-cli get mypasswd\\n\"\n\"  redis-cli -r 100 lpush mylist x\\n\"\n\"  redis-cli -r 100 -i 1 info | grep used_memory_human:\\n\"\n\"  redis-cli --eval myscript.lua key1 key2 , arg1 arg2 arg3\\n\"\n\"  redis-cli --scan --pattern '*:12345*'\\n\"\n\"\\n\"\n\"  (Note: when using --eval the comma separates KEYS[] from ARGV[] items)\\n\"\n\"\\n\"\n\"When no command is given, redis-cli starts in interactive mode.\\n\"\n\"Type \\\"help\\\" in interactive mode for information on available commands.\\n\"\n\"\\n\",\n        version, REDIS_CLI_DEFAULT_PIPE_TIMEOUT);\n    sdsfree(version);\n    exit(1);\n}\n\n/* Turn the plain C strings into Sds strings */\nstatic char **convertToSds(int count, char** args) {\n  int j;\n  char **sds = zmalloc(sizeof(char*)*count);\n\n  for(j = 0; j < count; j++)\n    sds[j] = sdsnew(args[j]);\n\n  return sds;\n}\n\nstatic void repl(void) {\n    sds historyfile = NULL;\n    int history = 0;\n    char *line;\n    int argc;\n    sds *argv;\n\n    config.interactive = 1;\n    linenoiseSetMultiLine(1);\n    linenoiseSetCompletionCallback(completionCallback);\n\n    /* Only use history when stdin is a tty. */\n    if (isatty(fileno(stdin))) {\n        historyfile = getHistoryPath();\n        if (historyfile != NULL) {\n            history = 1;\n            linenoiseHistoryLoad(historyfile);\n        }\n    }\n\n    cliRefreshPrompt();\n    while((line = linenoise(context ? config.prompt : \"not connected> \")) != NULL) {\n        if (line[0] != '\\0') {\n            argv = sdssplitargs(line,&argc);\n            if (history) linenoiseHistoryAdd(line);\n            if (historyfile) linenoiseHistorySave(historyfile);\n\n            if (argv == NULL) {\n                printf(\"Invalid argument(s)\\n\");\n                free(line);\n                continue;\n            } else if (argc > 0) {\n                if (strcasecmp(argv[0],\"quit\") == 0 ||\n                    strcasecmp(argv[0],\"exit\") == 0)\n                {\n                    exit(0);\n                } else if (argc == 3 && !strcasecmp(argv[0],\"connect\")) {\n                    sdsfree(config.hostip);\n                    config.hostip = sdsnew(argv[1]);\n                    config.hostport = atoi(argv[2]);\n                    cliRefreshPrompt();\n                    cliConnect(1);\n                } else if (argc == 1 && !strcasecmp(argv[0],\"clear\")) {\n                    linenoiseClearScreen();\n                } else {\n                    long long start_time = mstime(), elapsed;\n                    int repeat, skipargs = 0;\n\n                    repeat = atoi(argv[0]);\n                    if (argc > 1 && repeat) {\n                        skipargs = 1;\n                    } else {\n                        repeat = 1;\n                    }\n\n                    while (1) {\n                        config.cluster_reissue_command = 0;\n                        if (cliSendCommand(argc-skipargs,argv+skipargs,repeat)\n                            != REDIS_OK)\n                        {\n                            cliConnect(1);\n\n                            /* If we still cannot send the command print error.\n                             * We'll try to reconnect the next time. */\n                            if (cliSendCommand(argc-skipargs,argv+skipargs,repeat)\n                                != REDIS_OK)\n                                cliPrintContextError();\n                        }\n                        /* Issue the command again if we got redirected in cluster mode */\n                        if (config.cluster_mode && config.cluster_reissue_command) {\n                            cliConnect(1);\n                        } else {\n                            break;\n                        }\n                    }\n                    elapsed = mstime()-start_time;\n                    if (elapsed >= 500) {\n                        printf(\"(%.2fs)\\n\",(double)elapsed/1000);\n                    }\n                }\n            }\n            /* Free the argument vector */\n            sdsfreesplitres(argv,argc);\n        }\n        /* linenoise() returns malloc-ed lines like readline() */\n        free(line);\n    }\n    exit(0);\n}\n\nstatic int noninteractive(int argc, char **argv) {\n    int retval = 0;\n    if (config.stdinarg) {\n        argv = zrealloc(argv, (argc+1)*sizeof(char*));\n        argv[argc] = readArgFromStdin();\n        retval = cliSendCommand(argc+1, argv, config.repeat);\n    } else {\n        /* stdin is probably a tty, can be tested with S_ISCHR(s.st_mode) */\n        retval = cliSendCommand(argc, argv, config.repeat);\n    }\n    return retval;\n}\n\n/*------------------------------------------------------------------------------\n * Eval mode\n *--------------------------------------------------------------------------- */\n\nstatic int evalMode(int argc, char **argv) {\n    sds script = sdsempty();\n    FILE *fp;\n    char buf[1024];\n    size_t nread;\n    char **argv2;\n    int j, got_comma = 0, keys = 0;\n\n    /* Load the script from the file, as an sds string. */\n    fp = fopen(config.eval,\"r\");\n    if (!fp) {\n        fprintf(stderr,\n            \"Can't open file '%s': %s\\n\", config.eval, strerror(errno));\n        exit(1);\n    }\n    while((nread = fread(buf,1,sizeof(buf),fp)) != 0) {\n        script = sdscatlen(script,buf,nread);\n    }\n    fclose(fp);\n\n    /* Create our argument vector */\n    argv2 = zmalloc(sizeof(sds)*(argc+3));\n    argv2[0] = sdsnew(\"EVAL\");\n    argv2[1] = script;\n    for (j = 0; j < argc; j++) {\n        if (!got_comma && argv[j][0] == ',' && argv[j][1] == 0) {\n            got_comma = 1;\n            continue;\n        }\n        argv2[j+3-got_comma] = sdsnew(argv[j]);\n        if (!got_comma) keys++;\n    }\n    argv2[2] = sdscatprintf(sdsempty(),\"%d\",keys);\n\n    /* Call it */\n    return cliSendCommand(argc+3-got_comma, argv2, config.repeat);\n}\n\n/*------------------------------------------------------------------------------\n * Latency and latency history modes\n *--------------------------------------------------------------------------- */\n\n#define LATENCY_SAMPLE_RATE 10 /* milliseconds. */\n#define LATENCY_HISTORY_DEFAULT_INTERVAL 15000 /* milliseconds. */\nstatic void latencyMode(void) {\n    redisReply *reply;\n    long long start, latency, min = 0, max = 0, tot = 0, count = 0;\n    long long history_interval =\n        config.interval ? config.interval/1000 :\n                          LATENCY_HISTORY_DEFAULT_INTERVAL;\n    double avg;\n    long long history_start = mstime();\n\n    if (!context) exit(1);\n    while(1) {\n        start = mstime();\n        reply = reconnectingRedisCommand(context,\"PING\");\n        if (reply == NULL) {\n            fprintf(stderr,\"\\nI/O error\\n\");\n            exit(1);\n        }\n        latency = mstime()-start;\n        freeReplyObject(reply);\n        count++;\n        if (count == 1) {\n            min = max = tot = latency;\n            avg = (double) latency;\n        } else {\n            if (latency < min) min = latency;\n            if (latency > max) max = latency;\n            tot += latency;\n            avg = (double) tot/count;\n        }\n        printf(\"\\x1b[0G\\x1b[2Kmin: %lld, max: %lld, avg: %.2f (%lld samples)\",\n            min, max, avg, count);\n        fflush(stdout);\n        if (config.latency_history && mstime()-history_start > history_interval)\n        {\n            printf(\" -- %.2f seconds range\\n\", (float)(mstime()-history_start)/1000);\n            history_start = mstime();\n            min = max = tot = count = 0;\n        }\n        usleep(LATENCY_SAMPLE_RATE * 1000);\n    }\n}\n\n/*------------------------------------------------------------------------------\n * Latency distribution mode -- requires 256 colors xterm\n *--------------------------------------------------------------------------- */\n\n#define LATENCY_DIST_DEFAULT_INTERVAL 1000 /* milliseconds. */\n#define LATENCY_DIST_MIN_GRAY 233 /* Less than that is too hard to see gray. */\n#define LATENCY_DIST_MAX_GRAY 255\n#define LATENCY_DIST_GRAYS (LATENCY_DIST_MAX_GRAY-LATENCY_DIST_MIN_GRAY+1)\n\n/* Gray palette. */\nint spectrum_palette_size = 24;\nint spectrum_palette[] = {0, 233,234,235,236,237,238,239,240,241,242,243,244,245,246,247,248,249,250,251,252,253,254,255};\n\n/* Structure to store samples distribution. */\nstruct distsamples {\n    long long max;   /* Max latency to fit into this interval (usec). */\n    long long count; /* Number of samples in this interval. */\n    int character;   /* Associated character in visualization. */\n};\n\n/* Helper function for latencyDistMode(). Performs the spectrum visualization\n * of the collected samples targeting an xterm 256 terminal.\n *\n * Takes an array of distsamples structures, ordered from smaller to bigger\n * 'max' value. Last sample max must be 0, to mean that it olds all the\n * samples greater than the previous one, and is also the stop sentinel.\n *\n * \"tot' is the total number of samples in the different buckets, so it\n * is the SUM(samples[i].conut) for i to 0 up to the max sample.\n *\n * As a side effect the function sets all the buckets count to 0. */\nvoid showLatencyDistSamples(struct distsamples *samples, long long tot) {\n    int j;\n\n     /* We convert samples into a index inside the palette\n     * proportional to the percentage a given bucket represents.\n     * This way intensity of the different parts of the spectrum\n     * don't change relative to the number of requests, which avoids to\n     * pollute the visualization with non-latency related info. */\n    printf(\"\\033[38;5;0m\"); /* Set foreground color to black. */\n    for (j = 0; ; j++) {\n        int coloridx =\n            ceil((float) samples[j].count / tot * (spectrum_palette_size-1));\n        int color = spectrum_palette[coloridx];\n        printf(\"\\033[48;5;%dm%c\", (int)color, samples[j].character);\n        samples[j].count = 0;\n        if (samples[j].max == 0) break; /* Last sample. */\n    }\n    printf(\"\\033[0m\\n\");\n    fflush(stdout);\n}\n\n/* Show the legend: different buckets values and colors meaning, so\n * that the spectrum is more easily readable. */\nvoid showLatencyDistLegend(void) {\n    int j;\n\n    printf(\"---------------------------------------------\\n\");\n    printf(\". - * #          .01 .125 .25 .5 milliseconds\\n\");\n    printf(\"1,2,3,...,9      from 1 to 9     milliseconds\\n\");\n    printf(\"A,B,C,D,E        10,20,30,40,50  milliseconds\\n\");\n    printf(\"F,G,H,I,J        .1,.2,.3,.4,.5       seconds\\n\");\n    printf(\"K,L,M,N,O,P,Q,?  1,2,4,8,16,30,60,>60 seconds\\n\");\n    printf(\"From 0 to 100%%: \");\n    for (j = 0; j < spectrum_palette_size; j++) {\n        printf(\"\\033[48;5;%dm \", spectrum_palette[j]);\n    }\n    printf(\"\\033[0m\\n\");\n    printf(\"---------------------------------------------\\n\");\n}\n\nstatic void latencyDistMode(void) {\n    redisReply *reply;\n    long long start, latency, count = 0;\n    long long history_interval =\n        config.interval ? config.interval/1000 :\n                          LATENCY_DIST_DEFAULT_INTERVAL;\n    long long history_start = ustime();\n    int j, outputs = 0;\n\n    struct distsamples samples[] = {\n        /* We use a mostly logarithmic scale, with certain linear intervals\n         * which are more interesting than others, like 1-10 milliseconds\n         * range. */\n        {10,0,'.'},         /* 0.01 ms */\n        {125,0,'-'},        /* 0.125 ms */\n        {250,0,'*'},        /* 0.25 ms */\n        {500,0,'#'},        /* 0.5 ms */\n        {1000,0,'1'},       /* 1 ms */\n        {2000,0,'2'},       /* 2 ms */\n        {3000,0,'3'},       /* 3 ms */\n        {4000,0,'4'},       /* 4 ms */\n        {5000,0,'5'},       /* 5 ms */\n        {6000,0,'6'},       /* 6 ms */\n        {7000,0,'7'},       /* 7 ms */\n        {8000,0,'8'},       /* 8 ms */\n        {9000,0,'9'},       /* 9 ms */\n        {10000,0,'A'},      /* 10 ms */\n        {20000,0,'B'},      /* 20 ms */\n        {30000,0,'C'},      /* 30 ms */\n        {40000,0,'D'},      /* 40 ms */\n        {50000,0,'E'},      /* 50 ms */\n        {100000,0,'F'},     /* 0.1 s */\n        {200000,0,'G'},     /* 0.2 s */\n        {300000,0,'H'},     /* 0.3 s */\n        {400000,0,'I'},     /* 0.4 s */\n        {500000,0,'J'},     /* 0.5 s */\n        {1000000,0,'K'},    /* 1 s */\n        {2000000,0,'L'},    /* 2 s */\n        {4000000,0,'M'},    /* 4 s */\n        {8000000,0,'N'},    /* 8 s */\n        {16000000,0,'O'},   /* 16 s */\n        {30000000,0,'P'},   /* 30 s */\n        {60000000,0,'Q'},   /* 1 minute */\n        {0,0,'?'},          /* > 1 minute */\n    };\n\n    if (!context) exit(1);\n    while(1) {\n        start = ustime();\n        reply = reconnectingRedisCommand(context,\"PING\");\n        if (reply == NULL) {\n            fprintf(stderr,\"\\nI/O error\\n\");\n            exit(1);\n        }\n        latency = ustime()-start;\n        freeReplyObject(reply);\n        count++;\n\n        /* Populate the relevant bucket. */\n        for (j = 0; ; j++) {\n            if (samples[j].max == 0 || latency <= samples[j].max) {\n                samples[j].count++;\n                break;\n            }\n        }\n\n        /* From time to time show the spectrum. */\n        if (count && (ustime()-history_start)/1000 > history_interval) {\n            if ((outputs++ % 20) == 0)\n                showLatencyDistLegend();\n            showLatencyDistSamples(samples,count);\n            history_start = ustime();\n            count = 0;\n        }\n        usleep(LATENCY_SAMPLE_RATE * 1000);\n    }\n}\n\n/*------------------------------------------------------------------------------\n * Slave mode\n *--------------------------------------------------------------------------- */\n\n/* Sends SYNC and reads the number of bytes in the payload. Used both by\n * slaveMode() and getRDB(). */\nunsigned long long sendSync(int fd) {\n    /* To start we need to send the SYNC command and return the payload.\n     * The hiredis client lib does not understand this part of the protocol\n     * and we don't want to mess with its buffers, so everything is performed\n     * using direct low-level I/O. */\n    char buf[4096], *p;\n    ssize_t nread;\n\n    /* Send the SYNC command. */\n    if (write(fd,\"SYNC\\r\\n\",6) != 6) {\n        fprintf(stderr,\"Error writing to master\\n\");\n        exit(1);\n    }\n\n    /* Read $<payload>\\r\\n, making sure to read just up to \"\\n\" */\n    p = buf;\n    while(1) {\n        nread = read(fd,p,1);\n        if (nread <= 0) {\n            fprintf(stderr,\"Error reading bulk length while SYNCing\\n\");\n            exit(1);\n        }\n        if (*p == '\\n' && p != buf) break;\n        if (*p != '\\n') p++;\n    }\n    *p = '\\0';\n    if (buf[0] == '-') {\n        printf(\"SYNC with master failed: %s\\n\", buf);\n        exit(1);\n    }\n    return strtoull(buf+1,NULL,10);\n}\n\nstatic void slaveMode(void) {\n    int fd = context->fd;\n    unsigned long long payload = sendSync(fd);\n    char buf[1024];\n    int original_output = config.output;\n\n    fprintf(stderr,\"SYNC with master, discarding %llu \"\n                   \"bytes of bulk transfer...\\n\", payload);\n\n    /* Discard the payload. */\n    while(payload) {\n        ssize_t nread;\n\n        nread = read(fd,buf,(payload > sizeof(buf)) ? sizeof(buf) : payload);\n        if (nread <= 0) {\n            fprintf(stderr,\"Error reading RDB payload while SYNCing\\n\");\n            exit(1);\n        }\n        payload -= nread;\n    }\n    fprintf(stderr,\"SYNC done. Logging commands from master.\\n\");\n\n    /* Now we can use hiredis to read the incoming protocol. */\n    config.output = OUTPUT_CSV;\n    while (cliReadReply(0) == REDIS_OK);\n    config.output = original_output;\n}\n\n/*------------------------------------------------------------------------------\n * RDB transfer mode\n *--------------------------------------------------------------------------- */\n\n/* This function implements --rdb, so it uses the replication protocol in order\n * to fetch the RDB file from a remote server. */\nstatic void getRDB(void) {\n    int s = context->fd;\n    int fd;\n    unsigned long long payload = sendSync(s);\n    char buf[4096];\n\n    fprintf(stderr,\"SYNC sent to master, writing %llu bytes to '%s'\\n\",\n        payload, config.rdb_filename);\n\n    /* Write to file. */\n    if (!strcmp(config.rdb_filename,\"-\")) {\n        fd = STDOUT_FILENO;\n    } else {\n        fd = open(config.rdb_filename, O_CREAT|O_WRONLY, 0644);\n        if (fd == -1) {\n            fprintf(stderr, \"Error opening '%s': %s\\n\", config.rdb_filename,\n                strerror(errno));\n            exit(1);\n        }\n    }\n\n    while(payload) {\n        ssize_t nread, nwritten;\n\n        nread = read(s,buf,(payload > sizeof(buf)) ? sizeof(buf) : payload);\n        if (nread <= 0) {\n            fprintf(stderr,\"I/O Error reading RDB payload from socket\\n\");\n            exit(1);\n        }\n        nwritten = write(fd, buf, nread);\n        if (nwritten != nread) {\n            fprintf(stderr,\"Error writing data to file: %s\\n\",\n                strerror(errno));\n            exit(1);\n        }\n        payload -= nread;\n    }\n    close(s); /* Close the file descriptor ASAP as fsync() may take time. */\n    fsync(fd);\n    fprintf(stderr,\"Transfer finished with success.\\n\");\n    exit(0);\n}\n\n/*------------------------------------------------------------------------------\n * Bulk import (pipe) mode\n *--------------------------------------------------------------------------- */\n\nstatic void pipeMode(void) {\n    int fd = context->fd;\n    long long errors = 0, replies = 0, obuf_len = 0, obuf_pos = 0;\n    char ibuf[1024*16], obuf[1024*16]; /* Input and output buffers */\n    char aneterr[ANET_ERR_LEN];\n    redisReader *reader = redisReaderCreate();\n    redisReply *reply;\n    int eof = 0; /* True once we consumed all the standard input. */\n    int done = 0;\n    char magic[20]; /* Special reply we recognize. */\n    time_t last_read_time = time(NULL);\n\n    srand(time(NULL));\n\n    /* Use non blocking I/O. */\n    if (anetNonBlock(aneterr,fd) == ANET_ERR) {\n        fprintf(stderr, \"Can't set the socket in non blocking mode: %s\\n\",\n            aneterr);\n        exit(1);\n    }\n\n    /* Transfer raw protocol and read replies from the server at the same\n     * time. */\n    while(!done) {\n        int mask = AE_READABLE;\n\n        if (!eof || obuf_len != 0) mask |= AE_WRITABLE;\n        mask = aeWait(fd,mask,1000);\n\n        /* Handle the readable state: we can read replies from the server. */\n        if (mask & AE_READABLE) {\n            ssize_t nread;\n\n            /* Read from socket and feed the hiredis reader. */\n            do {\n                nread = read(fd,ibuf,sizeof(ibuf));\n                if (nread == -1 && errno != EAGAIN && errno != EINTR) {\n                    fprintf(stderr, \"Error reading from the server: %s\\n\",\n                        strerror(errno));\n                    exit(1);\n                }\n                if (nread > 0) {\n                    redisReaderFeed(reader,ibuf,nread);\n                    last_read_time = time(NULL);\n                }\n            } while(nread > 0);\n\n            /* Consume replies. */\n            do {\n                if (redisReaderGetReply(reader,(void**)&reply) == REDIS_ERR) {\n                    fprintf(stderr, \"Error reading replies from server\\n\");\n                    exit(1);\n                }\n                if (reply) {\n                    if (reply->type == REDIS_REPLY_ERROR) {\n                        fprintf(stderr,\"%s\\n\", reply->str);\n                        errors++;\n                    } else if (eof && reply->type == REDIS_REPLY_STRING &&\n                                      reply->len == 20) {\n                        /* Check if this is the reply to our final ECHO\n                         * command. If so everything was received\n                         * from the server. */\n                        if (memcmp(reply->str,magic,20) == 0) {\n                            printf(\"Last reply received from server.\\n\");\n                            done = 1;\n                            replies--;\n                        }\n                    }\n                    replies++;\n                    freeReplyObject(reply);\n                }\n            } while(reply);\n        }\n\n        /* Handle the writable state: we can send protocol to the server. */\n        if (mask & AE_WRITABLE) {\n            while(1) {\n                /* Transfer current buffer to server. */\n                if (obuf_len != 0) {\n                    ssize_t nwritten = write(fd,obuf+obuf_pos,obuf_len);\n\n                    if (nwritten == -1) {\n                        if (errno != EAGAIN && errno != EINTR) {\n                            fprintf(stderr, \"Error writing to the server: %s\\n\",\n                                strerror(errno));\n                            exit(1);\n                        } else {\n                            nwritten = 0;\n                        }\n                    }\n                    obuf_len -= nwritten;\n                    obuf_pos += nwritten;\n                    if (obuf_len != 0) break; /* Can't accept more data. */\n                }\n                /* If buffer is empty, load from stdin. */\n                if (obuf_len == 0 && !eof) {\n                    ssize_t nread = read(STDIN_FILENO,obuf,sizeof(obuf));\n\n                    if (nread == 0) {\n                        /* The ECHO sequence starts with a \"\\r\\n\" so that if there\n                         * is garbage in the protocol we read from stdin, the ECHO\n                         * will likely still be properly formatted.\n                         * CRLF is ignored by Redis, so it has no effects. */\n                        char echo[] =\n                        \"\\r\\n*2\\r\\n$4\\r\\nECHO\\r\\n$20\\r\\n01234567890123456789\\r\\n\";\n                        int j;\n\n                        eof = 1;\n                        /* Everything transferred, so we queue a special\n                         * ECHO command that we can match in the replies\n                         * to make sure everything was read from the server. */\n                        for (j = 0; j < 20; j++)\n                            magic[j] = rand() & 0xff;\n                        memcpy(echo+21,magic,20);\n                        memcpy(obuf,echo,sizeof(echo)-1);\n                        obuf_len = sizeof(echo)-1;\n                        obuf_pos = 0;\n                        printf(\"All data transferred. Waiting for the last reply...\\n\");\n                    } else if (nread == -1) {\n                        fprintf(stderr, \"Error reading from stdin: %s\\n\",\n                            strerror(errno));\n                        exit(1);\n                    } else {\n                        obuf_len = nread;\n                        obuf_pos = 0;\n                    }\n                }\n                if (obuf_len == 0 && eof) break;\n            }\n        }\n\n        /* Handle timeout, that is, we reached EOF, and we are not getting\n         * replies from the server for a few seconds, nor the final ECHO is\n         * received. */\n        if (eof && config.pipe_timeout > 0 &&\n            time(NULL)-last_read_time > config.pipe_timeout)\n        {\n            fprintf(stderr,\"No replies for %d seconds: exiting.\\n\",\n                config.pipe_timeout);\n            errors++;\n            break;\n        }\n    }\n    redisReaderFree(reader);\n    printf(\"errors: %lld, replies: %lld\\n\", errors, replies);\n    if (errors)\n        exit(1);\n    else\n        exit(0);\n}\n\n/*------------------------------------------------------------------------------\n * Find big keys\n *--------------------------------------------------------------------------- */\n\n#define TYPE_STRING 0\n#define TYPE_LIST   1\n#define TYPE_SET    2\n#define TYPE_HASH   3\n#define TYPE_ZSET   4\n#define TYPE_NONE   5\n\nstatic redisReply *sendScan(unsigned long long *it) {\n    redisReply *reply = redisCommand(context, \"SCAN %llu\", *it);\n\n    /* Handle any error conditions */\n    if(reply == NULL) {\n        fprintf(stderr, \"\\nI/O error\\n\");\n        exit(1);\n    } else if(reply->type == REDIS_REPLY_ERROR) {\n        fprintf(stderr, \"SCAN error: %s\\n\", reply->str);\n        exit(1);\n    } else if(reply->type != REDIS_REPLY_ARRAY) {\n        fprintf(stderr, \"Non ARRAY response from SCAN!\\n\");\n        exit(1);\n    } else if(reply->elements != 2) {\n        fprintf(stderr, \"Invalid element count from SCAN!\\n\");\n        exit(1);\n    }\n\n    /* Validate our types are correct */\n    assert(reply->element[0]->type == REDIS_REPLY_STRING);\n    assert(reply->element[1]->type == REDIS_REPLY_ARRAY);\n\n    /* Update iterator */\n    *it = atoi(reply->element[0]->str);\n\n    return reply;\n}\n\nstatic int getDbSize(void) {\n    redisReply *reply;\n    int size;\n\n    reply = redisCommand(context, \"DBSIZE\");\n\n    if(reply == NULL || reply->type != REDIS_REPLY_INTEGER) {\n        fprintf(stderr, \"Couldn't determine DBSIZE!\\n\");\n        exit(1);\n    }\n\n    /* Grab the number of keys and free our reply */\n    size = reply->integer;\n    freeReplyObject(reply);\n\n    return size;\n}\n\nstatic int toIntType(char *key, char *type) {\n    if(!strcmp(type, \"string\")) {\n        return TYPE_STRING;\n    } else if(!strcmp(type, \"list\")) {\n        return TYPE_LIST;\n    } else if(!strcmp(type, \"set\")) {\n        return TYPE_SET;\n    } else if(!strcmp(type, \"hash\")) {\n        return TYPE_HASH;\n    } else if(!strcmp(type, \"zset\")) {\n        return TYPE_ZSET;\n    } else if(!strcmp(type, \"none\")) {\n        return TYPE_NONE;\n    } else {\n        fprintf(stderr, \"Unknown type '%s' for key '%s'\\n\", type, key);\n        exit(1);\n    }\n}\n\nstatic void getKeyTypes(redisReply *keys, int *types) {\n    redisReply *reply;\n    unsigned int i;\n\n    /* Pipeline TYPE commands */\n    for(i=0;i<keys->elements;i++) {\n        redisAppendCommand(context, \"TYPE %s\", keys->element[i]->str);\n    }\n\n    /* Retrieve types */\n    for(i=0;i<keys->elements;i++) {\n        if(redisGetReply(context, (void**)&reply)!=REDIS_OK) {\n            fprintf(stderr, \"Error getting type for key '%s' (%d: %s)\\n\",\n                keys->element[i]->str, context->err, context->errstr);\n            exit(1);\n        } else if(reply->type != REDIS_REPLY_STATUS) {\n            fprintf(stderr, \"Invalid reply type (%d) for TYPE on key '%s'!\\n\",\n                reply->type, keys->element[i]->str);\n            exit(1);\n        }\n\n        types[i] = toIntType(keys->element[i]->str, reply->str);\n        freeReplyObject(reply);\n    }\n}\n\nstatic void getKeySizes(redisReply *keys, int *types,\n                        unsigned long long *sizes)\n{\n    redisReply *reply;\n    char *sizecmds[] = {\"STRLEN\",\"LLEN\",\"SCARD\",\"HLEN\",\"ZCARD\"};\n    unsigned int i;\n\n    /* Pipeline size commands */\n    for(i=0;i<keys->elements;i++) {\n        /* Skip keys that were deleted */\n        if(types[i]==TYPE_NONE)\n            continue;\n\n        redisAppendCommand(context, \"%s %s\", sizecmds[types[i]],\n            keys->element[i]->str);\n    }\n\n    /* Retreive sizes */\n    for(i=0;i<keys->elements;i++) {\n        /* Skip keys that dissapeared between SCAN and TYPE */\n        if(types[i] == TYPE_NONE) {\n            sizes[i] = 0;\n            continue;\n        }\n\n        /* Retreive size */\n        if(redisGetReply(context, (void**)&reply)!=REDIS_OK) {\n            fprintf(stderr, \"Error getting size for key '%s' (%d: %s)\\n\",\n                keys->element[i]->str, context->err, context->errstr);\n            exit(1);\n        } else if(reply->type != REDIS_REPLY_INTEGER) {\n            /* Theoretically the key could have been removed and\n             * added as a different type between TYPE and SIZE */\n            fprintf(stderr,\n                \"Warning:  %s on '%s' failed (may have changed type)\\n\",\n                 sizecmds[types[i]], keys->element[i]->str);\n            sizes[i] = 0;\n        } else {\n            sizes[i] = reply->integer;\n        }\n\n        freeReplyObject(reply);\n    }\n}\n\nstatic void findBigKeys(void) {\n    unsigned long long biggest[5] = {0}, counts[5] = {0}, totalsize[5] = {0};\n    unsigned long long sampled = 0, total_keys, totlen=0, *sizes=NULL, it=0;\n    sds maxkeys[5] = {0};\n    char *typename[] = {\"string\",\"list\",\"set\",\"hash\",\"zset\"};\n    char *typeunit[] = {\"bytes\",\"items\",\"members\",\"fields\",\"members\"};\n    redisReply *reply, *keys;\n    unsigned int arrsize=0, i;\n    int type, *types=NULL;\n    double pct;\n\n    /* Total keys pre scanning */\n    total_keys = getDbSize();\n\n    /* Status message */\n    printf(\"\\n# Scanning the entire keyspace to find biggest keys as well as\\n\");\n    printf(\"# average sizes per key type.  You can use -i 0.1 to sleep 0.1 sec\\n\");\n    printf(\"# per 100 SCAN commands (not usually needed).\\n\\n\");\n\n    /* New up sds strings to keep track of overall biggest per type */\n    for(i=0;i<TYPE_NONE; i++) {\n        maxkeys[i] = sdsempty();\n        if(!maxkeys[i]) {\n            fprintf(stderr, \"Failed to allocate memory for largest key names!\\n\");\n            exit(1);\n        }\n    }\n\n    /* SCAN loop */\n    do {\n        /* Calculate approximate percentage completion */\n        pct = 100 * (double)sampled/total_keys;\n\n        /* Grab some keys and point to the keys array */\n        reply = sendScan(&it);\n        keys  = reply->element[1];\n\n        /* Reallocate our type and size array if we need to */\n        if(keys->elements > arrsize) {\n            types = zrealloc(types, sizeof(int)*keys->elements);\n            sizes = zrealloc(sizes, sizeof(unsigned long long)*keys->elements);\n\n            if(!types || !sizes) {\n                fprintf(stderr, \"Failed to allocate storage for keys!\\n\");\n                exit(1);\n            }\n\n            arrsize = keys->elements;\n        }\n\n        /* Retreive types and then sizes */\n        getKeyTypes(keys, types);\n        getKeySizes(keys, types, sizes);\n\n        /* Now update our stats */\n        for(i=0;i<keys->elements;i++) {\n            if((type = types[i]) == TYPE_NONE)\n                continue;\n\n            totalsize[type] += sizes[i];\n            counts[type]++;\n            totlen += keys->element[i]->len;\n            sampled++;\n\n            if(biggest[type]<sizes[i]) {\n                printf(\n                   \"[%05.2f%%] Biggest %-6s found so far '%s' with %llu %s\\n\",\n                   pct, typename[type], keys->element[i]->str, sizes[i],\n                   typeunit[type]);\n\n                /* Keep track of biggest key name for this type */\n                maxkeys[type] = sdscpy(maxkeys[type], keys->element[i]->str);\n                if(!maxkeys[type]) {\n                    fprintf(stderr, \"Failed to allocate memory for key!\\n\");\n                    exit(1);\n                }\n\n                /* Keep track of the biggest size for this type */\n                biggest[type] = sizes[i];\n            }\n\n            /* Update overall progress */\n            if(sampled % 1000000 == 0) {\n                printf(\"[%05.2f%%] Sampled %llu keys so far\\n\", pct, sampled);\n            }\n        }\n\n        /* Sleep if we've been directed to do so */\n        if(sampled && (sampled %100) == 0 && config.interval) {\n            usleep(config.interval);\n        }\n\n        freeReplyObject(reply);\n    } while(it != 0);\n\n    if(types) zfree(types);\n    if(sizes) zfree(sizes);\n\n    /* We're done */\n    printf(\"\\n-------- summary -------\\n\\n\");\n\n    printf(\"Sampled %llu keys in the keyspace!\\n\", sampled);\n    printf(\"Total key length in bytes is %llu (avg len %.2f)\\n\\n\",\n       totlen, totlen ? (double)totlen/sampled : 0);\n\n    /* Output the biggest keys we found, for types we did find */\n    for(i=0;i<TYPE_NONE;i++) {\n        if(sdslen(maxkeys[i])>0) {\n            printf(\"Biggest %6s found '%s' has %llu %s\\n\", typename[i], maxkeys[i],\n               biggest[i], typeunit[i]);\n        }\n    }\n\n    printf(\"\\n\");\n\n    for(i=0;i<TYPE_NONE;i++) {\n        printf(\"%llu %ss with %llu %s (%05.2f%% of keys, avg size %.2f)\\n\",\n           counts[i], typename[i], totalsize[i], typeunit[i],\n           sampled ? 100 * (double)counts[i]/sampled : 0,\n           counts[i] ? (double)totalsize[i]/counts[i] : 0);\n    }\n\n    /* Free sds strings containing max keys */\n    for(i=0;i<TYPE_NONE;i++) {\n        sdsfree(maxkeys[i]);\n    }\n\n    /* Success! */\n    exit(0);\n}\n\n/*------------------------------------------------------------------------------\n * Stats mode\n *--------------------------------------------------------------------------- */\n\n/* Return the specified INFO field from the INFO command output \"info\".\n * A new buffer is allocated for the result, that needs to be free'd.\n * If the field is not found NULL is returned. */\nstatic char *getInfoField(char *info, char *field) {\n    char *p = strstr(info,field);\n    char *n1, *n2;\n    char *result;\n\n    if (!p) return NULL;\n    p += strlen(field)+1;\n    n1 = strchr(p,'\\r');\n    n2 = strchr(p,',');\n    if (n2 && n2 < n1) n1 = n2;\n    result = malloc(sizeof(char)*(n1-p)+1);\n    memcpy(result,p,(n1-p));\n    result[n1-p] = '\\0';\n    return result;\n}\n\n/* Like the above function but automatically convert the result into\n * a long. On error (missing field) LONG_MIN is returned. */\nstatic long getLongInfoField(char *info, char *field) {\n    char *value = getInfoField(info,field);\n    long l;\n\n    if (!value) return LONG_MIN;\n    l = strtol(value,NULL,10);\n    free(value);\n    return l;\n}\n\n/* Convert number of bytes into a human readable string of the form:\n * 100B, 2G, 100M, 4K, and so forth. */\nvoid bytesToHuman(char *s, long long n) {\n    double d;\n\n    if (n < 0) {\n        *s = '-';\n        s++;\n        n = -n;\n    }\n    if (n < 1024) {\n        /* Bytes */\n        sprintf(s,\"%lluB\",n);\n        return;\n    } else if (n < (1024*1024)) {\n        d = (double)n/(1024);\n        sprintf(s,\"%.2fK\",d);\n    } else if (n < (1024LL*1024*1024)) {\n        d = (double)n/(1024*1024);\n        sprintf(s,\"%.2fM\",d);\n    } else if (n < (1024LL*1024*1024*1024)) {\n        d = (double)n/(1024LL*1024*1024);\n        sprintf(s,\"%.2fG\",d);\n    }\n}\n\nstatic void statMode(void) {\n    redisReply *reply;\n    long aux, requests = 0;\n    int i = 0;\n\n    while(1) {\n        char buf[64];\n        int j;\n\n        reply = reconnectingRedisCommand(context,\"INFO\");\n        if (reply->type == REDIS_REPLY_ERROR) {\n            printf(\"ERROR: %s\\n\", reply->str);\n            exit(1);\n        }\n\n        if ((i++ % 20) == 0) {\n            printf(\n\"------- data ------ --------------------- load -------------------- - child -\\n\"\n\"keys       mem      clients blocked requests            connections          \\n\");\n        }\n\n        /* Keys */\n        aux = 0;\n        for (j = 0; j < 20; j++) {\n            long k;\n\n            sprintf(buf,\"db%d:keys\",j);\n            k = getLongInfoField(reply->str,buf);\n            if (k == LONG_MIN) continue;\n            aux += k;\n        }\n        sprintf(buf,\"%ld\",aux);\n        printf(\"%-11s\",buf);\n\n        /* Used memory */\n        aux = getLongInfoField(reply->str,\"used_memory\");\n        bytesToHuman(buf,aux);\n        printf(\"%-8s\",buf);\n\n        /* Clients */\n        aux = getLongInfoField(reply->str,\"connected_clients\");\n        sprintf(buf,\"%ld\",aux);\n        printf(\" %-8s\",buf);\n\n        /* Blocked (BLPOPPING) Clients */\n        aux = getLongInfoField(reply->str,\"blocked_clients\");\n        sprintf(buf,\"%ld\",aux);\n        printf(\"%-8s\",buf);\n\n        /* Requets */\n        aux = getLongInfoField(reply->str,\"total_commands_processed\");\n        sprintf(buf,\"%ld (+%ld)\",aux,requests == 0 ? 0 : aux-requests);\n        printf(\"%-19s\",buf);\n        requests = aux;\n\n        /* Connections */\n        aux = getLongInfoField(reply->str,\"total_connections_received\");\n        sprintf(buf,\"%ld\",aux);\n        printf(\" %-12s\",buf);\n\n        /* Children */\n        aux = getLongInfoField(reply->str,\"bgsave_in_progress\");\n        aux |= getLongInfoField(reply->str,\"aof_rewrite_in_progress\") << 1;\n        switch(aux) {\n        case 0: break;\n        case 1:\n            printf(\"SAVE\");\n            break;\n        case 2:\n            printf(\"AOF\");\n            break;\n        case 3:\n            printf(\"SAVE+AOF\");\n            break;\n        }\n\n        printf(\"\\n\");\n        freeReplyObject(reply);\n        usleep(config.interval);\n    }\n}\n\n/*------------------------------------------------------------------------------\n * Scan mode\n *--------------------------------------------------------------------------- */\n\nstatic void scanMode(void) {\n    redisReply *reply;\n    unsigned long long cur = 0;\n\n    do {\n        if (config.pattern)\n            reply = redisCommand(context,\"SCAN %llu MATCH %s\",\n                cur,config.pattern);\n        else\n            reply = redisCommand(context,\"SCAN %llu\",cur);\n        if (reply == NULL) {\n            printf(\"I/O error\\n\");\n            exit(1);\n        } else if (reply->type == REDIS_REPLY_ERROR) {\n            printf(\"ERROR: %s\\n\", reply->str);\n            exit(1);\n        } else {\n            unsigned int j;\n\n            cur = strtoull(reply->element[0]->str,NULL,10);\n            for (j = 0; j < reply->element[1]->elements; j++)\n                printf(\"%s\\n\", reply->element[1]->element[j]->str);\n        }\n        freeReplyObject(reply);\n    } while(cur != 0);\n\n    exit(0);\n}\n\n/*------------------------------------------------------------------------------\n * LRU test mode\n *--------------------------------------------------------------------------- */\n\n/* Return an integer from min to max (both inclusive) using a power-law\n * distribution, depending on the value of alpha: the greater the alpha\n * the more bias towards lower values.\n *\n * With alpha = 6.2 the output follows the 80-20 rule where 20% of\n * the returned numbers will account for 80% of the frequency. */\nlong long powerLawRand(long long min, long long max, double alpha) {\n    double pl, r;\n\n    max += 1;\n    r = ((double)rand()) / RAND_MAX;\n    pl = pow(\n        ((pow(max,alpha+1) - pow(min,alpha+1))*r + pow(min,alpha+1)),\n        (1.0/(alpha+1)));\n    return (max-1-(long long)pl)+min;\n}\n\n/* Generates a key name among a set of lru_test_sample_size keys, using\n * an 80-20 distribution. */\nvoid LRUTestGenKey(char *buf, size_t buflen) {\n    snprintf(buf, buflen, \"lru:%lld\\n\",\n        powerLawRand(1, config.lru_test_sample_size, 6.2));\n}\n\n#define LRU_CYCLE_PERIOD 1000 /* 1000 milliseconds. */\n#define LRU_CYCLE_PIPELINE_SIZE 250\nstatic void LRUTestMode(void) {\n    redisReply *reply;\n    char key[128];\n    long long start_cycle;\n    int j;\n\n    srand(time(NULL)^getpid());\n    while(1) {\n        /* Perform cycles of 1 second with 50% writes and 50% reads.\n         * We use pipelining batching writes / reads N times per cycle in order\n         * to fill the target instance easily. */\n        start_cycle = mstime();\n        long long hits = 0, misses = 0;\n        while(mstime() - start_cycle < 1000) {\n            /* Write cycle. */\n            for (j = 0; j < LRU_CYCLE_PIPELINE_SIZE; j++) {\n                LRUTestGenKey(key,sizeof(key));\n                redisAppendCommand(context, \"SET %s val\",key);\n            }\n            for (j = 0; j < LRU_CYCLE_PIPELINE_SIZE; j++)\n                redisGetReply(context, (void**)&reply);\n\n            /* Read cycle. */\n            for (j = 0; j < LRU_CYCLE_PIPELINE_SIZE; j++) {\n                LRUTestGenKey(key,sizeof(key));\n                redisAppendCommand(context, \"GET %s\",key);\n            }\n            for (j = 0; j < LRU_CYCLE_PIPELINE_SIZE; j++) {\n                if (redisGetReply(context, (void**)&reply) == REDIS_OK) {\n                    switch(reply->type) {\n                        case REDIS_REPLY_ERROR:\n                            printf(\"%s\\n\", reply->str);\n                            break;\n                        case REDIS_REPLY_NIL:\n                            misses++;\n                            break;\n                        default:\n                            hits++;\n                            break;\n                    }\n                }\n            }\n\n            if (context->err) {\n                fprintf(stderr,\"I/O error during LRU test\\n\");\n                exit(1);\n            }\n        }\n        /* Print stats. */\n        printf(\n            \"%lld Gets/sec | Hits: %lld (%.2f%%) | Misses: %lld (%.2f%%)\\n\",\n            hits+misses,\n            hits, (double)hits/(hits+misses)*100,\n            misses, (double)misses/(hits+misses)*100);\n    }\n    exit(0);\n}\n\n/*------------------------------------------------------------------------------\n * Intrisic latency mode.\n *\n * Measure max latency of a running process that does not result from\n * syscalls. Basically this software should provide an hint about how much\n * time the kernel leaves the process without a chance to run.\n *--------------------------------------------------------------------------- */\n\n/* This is just some computation the compiler can't optimize out.\n * Should run in less than 100-200 microseconds even using very\n * slow hardware. Runs in less than 10 microseconds in modern HW. */\nunsigned long compute_something_fast(void) {\n    unsigned char s[256], i, j, t;\n    int count = 1000, k;\n    unsigned long output = 0;\n\n    for (k = 0; k < 256; k++) s[k] = k;\n\n    i = 0;\n    j = 0;\n    while(count--) {\n        i++;\n        j = j + s[i];\n        t = s[i];\n        s[i] = s[j];\n        s[j] = t;\n        output += s[(s[i]+s[j])&255];\n    }\n    return output;\n}\n\nstatic void intrinsicLatencyModeStop(int s) {\n    REDIS_NOTUSED(s);\n    force_cancel_loop = 1;\n}\n\nstatic void intrinsicLatencyMode(void) {\n    long long test_end, run_time, max_latency = 0, runs = 0;\n\n    run_time = config.intrinsic_latency_duration*1000000;\n    test_end = ustime() + run_time;\n    signal(SIGINT, intrinsicLatencyModeStop);\n\n    while(1) {\n        long long start, end, latency;\n\n        start = ustime();\n        compute_something_fast();\n        end = ustime();\n        latency = end-start;\n        runs++;\n        if (latency <= 0) continue;\n\n        /* Reporting */\n        if (latency > max_latency) {\n            max_latency = latency;\n            printf(\"Max latency so far: %lld microseconds.\\n\", max_latency);\n        }\n\n        double avg_us = (double)run_time/runs;\n        double avg_ns = avg_us * 10e3;\n        if (force_cancel_loop || end > test_end) {\n            printf(\"\\n%lld total runs \"\n                \"(avg latency: \"\n                \"%.4f microseconds / %.2f nanoseconds per run).\\n\",\n                runs, avg_us, avg_ns);\n            printf(\"Worst run took %.0fx longer than the average latency.\\n\",\n                max_latency / avg_us);\n            exit(0);\n        }\n    }\n}\n\n/*------------------------------------------------------------------------------\n * Program main()\n *--------------------------------------------------------------------------- */\n\nint main(int argc, char **argv) {\n    int firstarg;\n\n    config.hostip = sdsnew(\"127.0.0.1\");\n    config.hostport = 6379;\n    config.hostsocket = NULL;\n    config.repeat = 1;\n    config.interval = 0;\n    config.dbnum = 0;\n    config.interactive = 0;\n    config.shutdown = 0;\n    config.monitor_mode = 0;\n    config.pubsub_mode = 0;\n    config.latency_mode = 0;\n    config.latency_dist_mode = 0;\n    config.latency_history = 0;\n    config.lru_test_mode = 0;\n    config.lru_test_sample_size = 0;\n    config.cluster_mode = 0;\n    config.slave_mode = 0;\n    config.getrdb_mode = 0;\n    config.stat_mode = 0;\n    config.scan_mode = 0;\n    config.intrinsic_latency_mode = 0;\n    config.pattern = NULL;\n    config.rdb_filename = NULL;\n    config.pipe_mode = 0;\n    config.pipe_timeout = REDIS_CLI_DEFAULT_PIPE_TIMEOUT;\n    config.bigkeys = 0;\n    config.stdinarg = 0;\n    config.auth = NULL;\n    config.eval = NULL;\n    config.last_cmd_type = -1;\n\n    if (!isatty(fileno(stdout)) && (getenv(\"FAKETTY\") == NULL))\n        config.output = OUTPUT_RAW;\n    else\n        config.output = OUTPUT_STANDARD;\n    config.mb_delim = sdsnew(\"\\n\");\n    cliInitHelp();\n\n    firstarg = parseOptions(argc,argv);\n    argc -= firstarg;\n    argv += firstarg;\n\n    /* Latency mode */\n    if (config.latency_mode) {\n        if (cliConnect(0) == REDIS_ERR) exit(1);\n        latencyMode();\n    }\n\n    /* Latency distribution mode */\n    if (config.latency_dist_mode) {\n        if (cliConnect(0) == REDIS_ERR) exit(1);\n        latencyDistMode();\n    }\n\n    /* Slave mode */\n    if (config.slave_mode) {\n        if (cliConnect(0) == REDIS_ERR) exit(1);\n        slaveMode();\n    }\n\n    /* Get RDB mode. */\n    if (config.getrdb_mode) {\n        if (cliConnect(0) == REDIS_ERR) exit(1);\n        getRDB();\n    }\n\n    /* Pipe mode */\n    if (config.pipe_mode) {\n        if (cliConnect(0) == REDIS_ERR) exit(1);\n        pipeMode();\n    }\n\n    /* Find big keys */\n    if (config.bigkeys) {\n        if (cliConnect(0) == REDIS_ERR) exit(1);\n        findBigKeys();\n    }\n\n    /* Stat mode */\n    if (config.stat_mode) {\n        if (cliConnect(0) == REDIS_ERR) exit(1);\n        if (config.interval == 0) config.interval = 1000000;\n        statMode();\n    }\n\n    /* Scan mode */\n    if (config.scan_mode) {\n        if (cliConnect(0) == REDIS_ERR) exit(1);\n        scanMode();\n    }\n\n    /* LRU test mode */\n    if (config.lru_test_mode) {\n        if (cliConnect(0) == REDIS_ERR) exit(1);\n        LRUTestMode();\n    }\n\n    /* Intrinsic latency mode */\n    if (config.intrinsic_latency_mode) intrinsicLatencyMode();\n\n    /* Start interactive mode when no command is provided */\n    if (argc == 0 && !config.eval) {\n        /* Ignore SIGPIPE in interactive mode to force a reconnect */\n        signal(SIGPIPE, SIG_IGN);\n\n        /* Note that in repl mode we don't abort on connection error.\n         * A new attempt will be performed for every command send. */\n        cliConnect(0);\n        repl();\n    }\n\n    /* Otherwise, we have some arguments to execute */\n    if (cliConnect(0) != REDIS_OK) exit(1);\n    if (config.eval) {\n        return evalMode(argc,argv);\n    } else {\n        return noninteractive(argc,convertToSds(argc,argv));\n    }\n}\n"
  },
  {
    "path": "extern/deprecated/redis-2.8.21/src/redis.c",
    "content": "/*\n * Copyright (c) 2009-2012, Salvatore Sanfilippo <antirez at gmail dot com>\n * All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions are met:\n *\n *   * Redistributions of source code must retain the above copyright notice,\n *     this list of conditions and the following disclaimer.\n *   * Redistributions in binary form must reproduce the above copyright\n *     notice, this list of conditions and the following disclaimer in the\n *     documentation and/or other materials provided with the distribution.\n *   * Neither the name of Redis nor the names of its contributors may be used\n *     to endorse or promote products derived from this software without\n *     specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\"\n * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\n * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE\n * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR\n * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF\n * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS\n * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN\n * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)\n * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE\n * POSSIBILITY OF SUCH DAMAGE.\n */\n\n#include \"redis.h\"\n#include \"slowlog.h\"\n#include \"bio.h\"\n#include \"latency.h\"\n\n#include <time.h>\n#include <signal.h>\n#include <sys/wait.h>\n#include <errno.h>\n#include <assert.h>\n#include <ctype.h>\n#include <stdarg.h>\n#include <arpa/inet.h>\n#include <sys/stat.h>\n#include <fcntl.h>\n#include <sys/time.h>\n#include <sys/resource.h>\n#include <sys/uio.h>\n#include <limits.h>\n#include <float.h>\n#include <math.h>\n#include <sys/resource.h>\n#include <sys/utsname.h>\n#include <locale.h>\n\n/* Our shared \"common\" objects */\n\nstruct sharedObjectsStruct shared;\n\n/* Global vars that are actually used as constants. The following double\n * values are used for double on-disk serialization, and are initialized\n * at runtime to avoid strange compiler optimizations. */\n\ndouble R_Zero, R_PosInf, R_NegInf, R_Nan;\n\n/*================================= Globals ================================= */\n\n/* Global vars */\nstruct redisServer server; /* server global state */\n\n/* Our command table.\n *\n * Every entry is composed of the following fields:\n *\n * name: a string representing the command name.\n * function: pointer to the C function implementing the command.\n * arity: number of arguments, it is possible to use -N to say >= N\n * sflags: command flags as string. See below for a table of flags.\n * flags: flags as bitmask. Computed by Redis using the 'sflags' field.\n * get_keys_proc: an optional function to get key arguments from a command.\n *                This is only used when the following three fields are not\n *                enough to specify what arguments are keys.\n * first_key_index: first argument that is a key\n * last_key_index: last argument that is a key\n * key_step: step to get all the keys from first to last argument. For instance\n *           in MSET the step is two since arguments are key,val,key,val,...\n * microseconds: microseconds of total execution time for this command.\n * calls: total number of calls of this command.\n *\n * The flags, microseconds and calls fields are computed by Redis and should\n * always be set to zero.\n *\n * Command flags are expressed using strings where every character represents\n * a flag. Later the populateCommandTable() function will take care of\n * populating the real 'flags' field using this characters.\n *\n * This is the meaning of the flags:\n *\n * w: write command (may modify the key space).\n * r: read command  (will never modify the key space).\n * m: may increase memory usage once called. Don't allow if out of memory.\n * a: admin command, like SAVE or SHUTDOWN.\n * p: Pub/Sub related command.\n * f: force replication of this command, regardless of server.dirty.\n * s: command not allowed in scripts.\n * R: random command. Command is not deterministic, that is, the same command\n *    with the same arguments, with the same key space, may have different\n *    results. For instance SPOP and RANDOMKEY are two random commands.\n * S: Sort command output array if called from script, so that the output\n *    is deterministic.\n * l: Allow command while loading the database.\n * t: Allow command while a slave has stale data but is not allowed to\n *    server this data. Normally no command is accepted in this condition\n *    but just a few.\n * M: Do not automatically propagate the command on MONITOR.\n * F: Fast command: O(1) or O(log(N)) command that should never delay\n *    its execution as long as the kernel scheduler is giving us time.\n *    Note that commands that may trigger a DEL as a side effect (like SET)\n *    are not fast commands.\n */\nstruct redisCommand redisCommandTable[] = {\n    {\"get\",getCommand,2,\"rF\",0,NULL,1,1,1,0,0},\n    {\"set\",setCommand,-3,\"wm\",0,NULL,1,1,1,0,0},\n    {\"setnx\",setnxCommand,3,\"wmF\",0,NULL,1,1,1,0,0},\n    {\"setex\",setexCommand,4,\"wm\",0,NULL,1,1,1,0,0},\n    {\"psetex\",psetexCommand,4,\"wm\",0,NULL,1,1,1,0,0},\n    {\"append\",appendCommand,3,\"wm\",0,NULL,1,1,1,0,0},\n    {\"strlen\",strlenCommand,2,\"rF\",0,NULL,1,1,1,0,0},\n    {\"del\",delCommand,-2,\"w\",0,NULL,1,-1,1,0,0},\n    {\"exists\",existsCommand,2,\"rF\",0,NULL,1,1,1,0,0},\n    {\"setbit\",setbitCommand,4,\"wm\",0,NULL,1,1,1,0,0},\n    {\"getbit\",getbitCommand,3,\"rF\",0,NULL,1,1,1,0,0},\n    {\"setrange\",setrangeCommand,4,\"wm\",0,NULL,1,1,1,0,0},\n    {\"getrange\",getrangeCommand,4,\"r\",0,NULL,1,1,1,0,0},\n    {\"substr\",getrangeCommand,4,\"r\",0,NULL,1,1,1,0,0},\n    {\"incr\",incrCommand,2,\"wmF\",0,NULL,1,1,1,0,0},\n    {\"decr\",decrCommand,2,\"wmF\",0,NULL,1,1,1,0,0},\n    {\"mget\",mgetCommand,-2,\"r\",0,NULL,1,-1,1,0,0},\n    {\"rpush\",rpushCommand,-3,\"wmF\",0,NULL,1,1,1,0,0},\n    {\"lpush\",lpushCommand,-3,\"wmF\",0,NULL,1,1,1,0,0},\n    {\"rpushx\",rpushxCommand,3,\"wmF\",0,NULL,1,1,1,0,0},\n    {\"lpushx\",lpushxCommand,3,\"wmF\",0,NULL,1,1,1,0,0},\n    {\"linsert\",linsertCommand,5,\"wm\",0,NULL,1,1,1,0,0},\n    {\"rpop\",rpopCommand,2,\"wF\",0,NULL,1,1,1,0,0},\n    {\"lpop\",lpopCommand,2,\"wF\",0,NULL,1,1,1,0,0},\n    {\"brpop\",brpopCommand,-3,\"ws\",0,NULL,1,1,1,0,0},\n    {\"brpoplpush\",brpoplpushCommand,4,\"wms\",0,NULL,1,2,1,0,0},\n    {\"blpop\",blpopCommand,-3,\"ws\",0,NULL,1,-2,1,0,0},\n    {\"llen\",llenCommand,2,\"rF\",0,NULL,1,1,1,0,0},\n    {\"lindex\",lindexCommand,3,\"r\",0,NULL,1,1,1,0,0},\n    {\"lset\",lsetCommand,4,\"wm\",0,NULL,1,1,1,0,0},\n    {\"lrange\",lrangeCommand,4,\"r\",0,NULL,1,1,1,0,0},\n    {\"ltrim\",ltrimCommand,4,\"w\",0,NULL,1,1,1,0,0},\n    {\"lrem\",lremCommand,4,\"w\",0,NULL,1,1,1,0,0},\n    {\"rpoplpush\",rpoplpushCommand,3,\"wm\",0,NULL,1,2,1,0,0},\n    {\"sadd\",saddCommand,-3,\"wmF\",0,NULL,1,1,1,0,0},\n    {\"srem\",sremCommand,-3,\"wF\",0,NULL,1,1,1,0,0},\n    {\"smove\",smoveCommand,4,\"wF\",0,NULL,1,2,1,0,0},\n    {\"sismember\",sismemberCommand,3,\"rF\",0,NULL,1,1,1,0,0},\n    {\"scard\",scardCommand,2,\"rF\",0,NULL,1,1,1,0,0},\n    {\"spop\",spopCommand,2,\"wRsF\",0,NULL,1,1,1,0,0},\n    {\"srandmember\",srandmemberCommand,-2,\"rR\",0,NULL,1,1,1,0,0},\n    {\"sinter\",sinterCommand,-2,\"rS\",0,NULL,1,-1,1,0,0},\n    {\"sinterstore\",sinterstoreCommand,-3,\"wm\",0,NULL,1,-1,1,0,0},\n    {\"sunion\",sunionCommand,-2,\"rS\",0,NULL,1,-1,1,0,0},\n    {\"sunionstore\",sunionstoreCommand,-3,\"wm\",0,NULL,1,-1,1,0,0},\n    {\"sdiff\",sdiffCommand,-2,\"rS\",0,NULL,1,-1,1,0,0},\n    {\"sdiffstore\",sdiffstoreCommand,-3,\"wm\",0,NULL,1,-1,1,0,0},\n    {\"smembers\",sinterCommand,2,\"rS\",0,NULL,1,1,1,0,0},\n    {\"sscan\",sscanCommand,-3,\"rR\",0,NULL,1,1,1,0,0},\n    {\"zadd\",zaddCommand,-4,\"wmF\",0,NULL,1,1,1,0,0},\n    {\"zincrby\",zincrbyCommand,4,\"wmF\",0,NULL,1,1,1,0,0},\n    {\"zrem\",zremCommand,-3,\"wF\",0,NULL,1,1,1,0,0},\n    {\"zremrangebyscore\",zremrangebyscoreCommand,4,\"w\",0,NULL,1,1,1,0,0},\n    {\"zremrangebyrank\",zremrangebyrankCommand,4,\"w\",0,NULL,1,1,1,0,0},\n    {\"zremrangebylex\",zremrangebylexCommand,4,\"w\",0,NULL,1,1,1,0,0},\n    {\"zunionstore\",zunionstoreCommand,-4,\"wm\",0,zunionInterGetKeys,0,0,0,0,0},\n    {\"zinterstore\",zinterstoreCommand,-4,\"wm\",0,zunionInterGetKeys,0,0,0,0,0},\n    {\"zrange\",zrangeCommand,-4,\"r\",0,NULL,1,1,1,0,0},\n    {\"zrangebyscore\",zrangebyscoreCommand,-4,\"r\",0,NULL,1,1,1,0,0},\n    {\"zrevrangebyscore\",zrevrangebyscoreCommand,-4,\"r\",0,NULL,1,1,1,0,0},\n    {\"zrangebylex\",zrangebylexCommand,-4,\"r\",0,NULL,1,1,1,0,0},\n    {\"zrevrangebylex\",zrevrangebylexCommand,-4,\"r\",0,NULL,1,1,1,0,0},\n    {\"zcount\",zcountCommand,4,\"rF\",0,NULL,1,1,1,0,0},\n    {\"zlexcount\",zlexcountCommand,4,\"rF\",0,NULL,1,1,1,0,0},\n    {\"zrevrange\",zrevrangeCommand,-4,\"r\",0,NULL,1,1,1,0,0},\n    {\"zcard\",zcardCommand,2,\"rF\",0,NULL,1,1,1,0,0},\n    {\"zscore\",zscoreCommand,3,\"rF\",0,NULL,1,1,1,0,0},\n    {\"zrank\",zrankCommand,3,\"rF\",0,NULL,1,1,1,0,0},\n    {\"zrevrank\",zrevrankCommand,3,\"rF\",0,NULL,1,1,1,0,0},\n    {\"zscan\",zscanCommand,-3,\"rR\",0,NULL,1,1,1,0,0},\n    {\"hset\",hsetCommand,4,\"wmF\",0,NULL,1,1,1,0,0},\n    {\"hsetnx\",hsetnxCommand,4,\"wmF\",0,NULL,1,1,1,0,0},\n    {\"hget\",hgetCommand,3,\"rF\",0,NULL,1,1,1,0,0},\n    {\"hmset\",hmsetCommand,-4,\"wm\",0,NULL,1,1,1,0,0},\n    {\"hmget\",hmgetCommand,-3,\"r\",0,NULL,1,1,1,0,0},\n    {\"hincrby\",hincrbyCommand,4,\"wmF\",0,NULL,1,1,1,0,0},\n    {\"hincrbyfloat\",hincrbyfloatCommand,4,\"wmF\",0,NULL,1,1,1,0,0},\n    {\"hdel\",hdelCommand,-3,\"wF\",0,NULL,1,1,1,0,0},\n    {\"hlen\",hlenCommand,2,\"rF\",0,NULL,1,1,1,0,0},\n    {\"hkeys\",hkeysCommand,2,\"rS\",0,NULL,1,1,1,0,0},\n    {\"hvals\",hvalsCommand,2,\"rS\",0,NULL,1,1,1,0,0},\n    {\"hgetall\",hgetallCommand,2,\"r\",0,NULL,1,1,1,0,0},\n    {\"hexists\",hexistsCommand,3,\"rF\",0,NULL,1,1,1,0,0},\n    {\"hscan\",hscanCommand,-3,\"rR\",0,NULL,1,1,1,0,0},\n    {\"incrby\",incrbyCommand,3,\"wmF\",0,NULL,1,1,1,0,0},\n    {\"decrby\",decrbyCommand,3,\"wmF\",0,NULL,1,1,1,0,0},\n    {\"incrbyfloat\",incrbyfloatCommand,3,\"wmF\",0,NULL,1,1,1,0,0},\n    {\"getset\",getsetCommand,3,\"wm\",0,NULL,1,1,1,0,0},\n    {\"mset\",msetCommand,-3,\"wm\",0,NULL,1,-1,2,0,0},\n    {\"msetnx\",msetnxCommand,-3,\"wm\",0,NULL,1,-1,2,0,0},\n    {\"randomkey\",randomkeyCommand,1,\"rR\",0,NULL,0,0,0,0,0},\n    {\"select\",selectCommand,2,\"rlF\",0,NULL,0,0,0,0,0},\n    {\"move\",moveCommand,3,\"wF\",0,NULL,1,1,1,0,0},\n    {\"rename\",renameCommand,3,\"w\",0,NULL,1,2,1,0,0},\n    {\"renamenx\",renamenxCommand,3,\"wF\",0,NULL,1,2,1,0,0},\n    {\"expire\",expireCommand,3,\"wF\",0,NULL,1,1,1,0,0},\n    {\"expireat\",expireatCommand,3,\"wF\",0,NULL,1,1,1,0,0},\n    {\"pexpire\",pexpireCommand,3,\"wF\",0,NULL,1,1,1,0,0},\n    {\"pexpireat\",pexpireatCommand,3,\"wF\",0,NULL,1,1,1,0,0},\n    {\"keys\",keysCommand,2,\"rS\",0,NULL,0,0,0,0,0},\n    {\"scan\",scanCommand,-2,\"rR\",0,NULL,0,0,0,0,0},\n    {\"dbsize\",dbsizeCommand,1,\"rF\",0,NULL,0,0,0,0,0},\n    {\"auth\",authCommand,2,\"rsltF\",0,NULL,0,0,0,0,0},\n    {\"ping\",pingCommand,-1,\"rtF\",0,NULL,0,0,0,0,0},\n    {\"echo\",echoCommand,2,\"rF\",0,NULL,0,0,0,0,0},\n    {\"save\",saveCommand,1,\"ars\",0,NULL,0,0,0,0,0},\n    {\"bgsave\",bgsaveCommand,1,\"ar\",0,NULL,0,0,0,0,0},\n    {\"bgrewriteaof\",bgrewriteaofCommand,1,\"ar\",0,NULL,0,0,0,0,0},\n    {\"shutdown\",shutdownCommand,-1,\"arlt\",0,NULL,0,0,0,0,0},\n    {\"lastsave\",lastsaveCommand,1,\"rRF\",0,NULL,0,0,0,0,0},\n    {\"type\",typeCommand,2,\"rF\",0,NULL,1,1,1,0,0},\n    {\"multi\",multiCommand,1,\"rsF\",0,NULL,0,0,0,0,0},\n    {\"exec\",execCommand,1,\"sM\",0,NULL,0,0,0,0,0},\n    {\"discard\",discardCommand,1,\"rsF\",0,NULL,0,0,0,0,0},\n    {\"sync\",syncCommand,1,\"ars\",0,NULL,0,0,0,0,0},\n    {\"psync\",syncCommand,3,\"ars\",0,NULL,0,0,0,0,0},\n    {\"replconf\",replconfCommand,-1,\"arslt\",0,NULL,0,0,0,0,0},\n    {\"flushdb\",flushdbCommand,1,\"w\",0,NULL,0,0,0,0,0},\n    {\"flushall\",flushallCommand,1,\"w\",0,NULL,0,0,0,0,0},\n    {\"sort\",sortCommand,-2,\"wm\",0,NULL,1,1,1,0,0},\n    {\"info\",infoCommand,-1,\"rlt\",0,NULL,0,0,0,0,0},\n    {\"monitor\",monitorCommand,1,\"ars\",0,NULL,0,0,0,0,0},\n    {\"ttl\",ttlCommand,2,\"rF\",0,NULL,1,1,1,0,0},\n    {\"pttl\",pttlCommand,2,\"rF\",0,NULL,1,1,1,0,0},\n    {\"persist\",persistCommand,2,\"wF\",0,NULL,1,1,1,0,0},\n    {\"slaveof\",slaveofCommand,3,\"ast\",0,NULL,0,0,0,0,0},\n    {\"role\",roleCommand,1,\"lst\",0,NULL,0,0,0,0,0},\n    {\"debug\",debugCommand,-2,\"as\",0,NULL,0,0,0,0,0},\n    {\"config\",configCommand,-2,\"art\",0,NULL,0,0,0,0,0},\n    {\"subscribe\",subscribeCommand,-2,\"rpslt\",0,NULL,0,0,0,0,0},\n    {\"unsubscribe\",unsubscribeCommand,-1,\"rpslt\",0,NULL,0,0,0,0,0},\n    {\"psubscribe\",psubscribeCommand,-2,\"rpslt\",0,NULL,0,0,0,0,0},\n    {\"punsubscribe\",punsubscribeCommand,-1,\"rpslt\",0,NULL,0,0,0,0,0},\n    {\"publish\",publishCommand,3,\"pltrF\",0,NULL,0,0,0,0,0},\n    {\"pubsub\",pubsubCommand,-2,\"pltrR\",0,NULL,0,0,0,0,0},\n    {\"watch\",watchCommand,-2,\"rsF\",0,NULL,1,-1,1,0,0},\n    {\"unwatch\",unwatchCommand,1,\"rsF\",0,NULL,0,0,0,0,0},\n    {\"restore\",restoreCommand,4,\"wm\",0,NULL,1,1,1,0,0},\n    {\"migrate\",migrateCommand,6,\"w\",0,NULL,0,0,0,0,0},\n    {\"dump\",dumpCommand,2,\"r\",0,NULL,1,1,1,0,0},\n    {\"object\",objectCommand,3,\"r\",0,NULL,2,2,2,0,0},\n    {\"client\",clientCommand,-2,\"rs\",0,NULL,0,0,0,0,0},\n    {\"eval\",evalCommand,-3,\"s\",0,zunionInterGetKeys,0,0,0,0,0},\n    {\"evalsha\",evalShaCommand,-3,\"s\",0,zunionInterGetKeys,0,0,0,0,0},\n    {\"slowlog\",slowlogCommand,-2,\"r\",0,NULL,0,0,0,0,0},\n    {\"script\",scriptCommand,-2,\"rs\",0,NULL,0,0,0,0,0},\n    {\"time\",timeCommand,1,\"rRF\",0,NULL,0,0,0,0,0},\n    {\"bitop\",bitopCommand,-4,\"wm\",0,NULL,2,-1,1,0,0},\n    {\"bitcount\",bitcountCommand,-2,\"r\",0,NULL,1,1,1,0,0},\n    {\"bitpos\",bitposCommand,-3,\"r\",0,NULL,1,1,1,0,0},\n    {\"command\",commandCommand,0,\"rlt\",0,NULL,0,0,0,0,0},\n    {\"pfselftest\",pfselftestCommand,1,\"r\",0,NULL,0,0,0,0,0},\n    {\"pfadd\",pfaddCommand,-2,\"wmF\",0,NULL,1,1,1,0,0},\n    {\"pfcount\",pfcountCommand,-2,\"r\",0,NULL,1,1,1,0,0},\n    {\"pfmerge\",pfmergeCommand,-2,\"wm\",0,NULL,1,-1,1,0,0},\n    {\"pfdebug\",pfdebugCommand,-3,\"w\",0,NULL,0,0,0,0,0},\n    {\"latency\",latencyCommand,-2,\"arslt\",0,NULL,0,0,0,0,0},\n    {\"slotsinfo\",slotsinfoCommand,-1,\"rF\",0,NULL,0,0,0,0,0},\n    {\"slotsscan\",slotsscanCommand,-3,\"rR\",0,NULL,0,0,0,0,0},\n    {\"slotsdel\",slotsdelCommand,-2,\"w\",0,NULL,1,-1,1,0,0},\n    {\"slotsmgrtslot\",slotsmgrtslotCommand,5,\"aw\",0,NULL,0,0,0,0,0},\n    {\"slotsmgrtone\",slotsmgrtoneCommand,5,\"aw\",0,NULL,0,0,0,0,0},\n    {\"slotsmgrttagslot\",slotsmgrttagslotCommand,5,\"aw\",0,NULL,0,0,0,0,0},\n    {\"slotsmgrttagone\",slotsmgrttagoneCommand,5,\"aw\",0,NULL,0,0,0,0,0},\n    {\"slotshashkey\",slotshashkeyCommand,-1,\"rF\",0,NULL,0,0,0,0,0},\n    {\"slotscheck\",slotscheckCommand,0,\"r\",0,NULL,0,0,0,0,0},\n    {\"slotsrestore\",slotsrestoreCommand,-4,\"awm\",0,NULL,1,1,1,0,0},\n};\n\n/*============================ Utility functions ============================ */\n\n/* Low level logging. To use only for very big messages, otherwise\n * redisLog() is to prefer. */\nvoid redisLogRaw(int level, const char *msg) {\n    const int syslogLevelMap[] = { LOG_DEBUG, LOG_INFO, LOG_NOTICE, LOG_WARNING };\n    const char *c = \".-*#\";\n    FILE *fp;\n    char buf[64];\n    int rawmode = (level & REDIS_LOG_RAW);\n    int log_to_stdout = server.logfile[0] == '\\0';\n\n    level &= 0xff; /* clear flags */\n    if (level < server.verbosity) return;\n\n    fp = log_to_stdout ? stdout : fopen(server.logfile,\"a\");\n    if (!fp) return;\n\n    if (rawmode) {\n        fprintf(fp,\"%s\",msg);\n    } else {\n        int off;\n        struct timeval tv;\n\n        gettimeofday(&tv,NULL);\n        off = strftime(buf,sizeof(buf),\"%d %b %H:%M:%S.\",localtime(&tv.tv_sec));\n        snprintf(buf+off,sizeof(buf)-off,\"%03d\",(int)tv.tv_usec/1000);\n        fprintf(fp,\"[%d] %s %c %s\\n\",(int)getpid(),buf,c[level],msg);\n    }\n    fflush(fp);\n\n    if (!log_to_stdout) fclose(fp);\n    if (server.syslog_enabled) syslog(syslogLevelMap[level], \"%s\", msg);\n}\n\n/* Like redisLogRaw() but with printf-alike support. This is the function that\n * is used across the code. The raw version is only used in order to dump\n * the INFO output on crash. */\nvoid redisLog(int level, const char *fmt, ...) {\n    va_list ap;\n    char msg[REDIS_MAX_LOGMSG_LEN];\n\n    if ((level&0xff) < server.verbosity) return;\n\n    va_start(ap, fmt);\n    vsnprintf(msg, sizeof(msg), fmt, ap);\n    va_end(ap);\n\n    redisLogRaw(level,msg);\n}\n\n/* Log a fixed message without printf-alike capabilities, in a way that is\n * safe to call from a signal handler.\n *\n * We actually use this only for signals that are not fatal from the point\n * of view of Redis. Signals that are going to kill the server anyway and\n * where we need printf-alike features are served by redisLog(). */\nvoid redisLogFromHandler(int level, const char *msg) {\n    int fd;\n    int log_to_stdout = server.logfile[0] == '\\0';\n    char buf[64];\n\n    if ((level&0xff) < server.verbosity || (log_to_stdout && server.daemonize))\n        return;\n    fd = log_to_stdout ? STDOUT_FILENO :\n                         open(server.logfile, O_APPEND|O_CREAT|O_WRONLY, 0644);\n    if (fd == -1) return;\n    ll2string(buf,sizeof(buf),getpid());\n    if (write(fd,\"[\",1) == -1) goto err;\n    if (write(fd,buf,strlen(buf)) == -1) goto err;\n    if (write(fd,\" | signal handler] (\",20) == -1) goto err;\n    ll2string(buf,sizeof(buf),time(NULL));\n    if (write(fd,buf,strlen(buf)) == -1) goto err;\n    if (write(fd,\") \",2) == -1) goto err;\n    if (write(fd,msg,strlen(msg)) == -1) goto err;\n    if (write(fd,\"\\n\",1) == -1) goto err;\nerr:\n    if (!log_to_stdout) close(fd);\n}\n\n/* Return the UNIX time in microseconds */\nlong long ustime(void) {\n    struct timeval tv;\n    long long ust;\n\n    gettimeofday(&tv, NULL);\n    ust = ((long long)tv.tv_sec)*1000000;\n    ust += tv.tv_usec;\n    return ust;\n}\n\n/* Return the UNIX time in milliseconds */\nlong long mstime(void) {\n    return ustime()/1000;\n}\n\n/* After an RDB dump or AOF rewrite we exit from children using _exit() instead of\n * exit(), because the latter may interact with the same file objects used by\n * the parent process. However if we are testing the coverage normal exit() is\n * used in order to obtain the right coverage information. */\nvoid exitFromChild(int retcode) {\n#ifdef COVERAGE_TEST\n    exit(retcode);\n#else\n    _exit(retcode);\n#endif\n}\n\n/*====================== Hash table type implementation  ==================== */\n\n/* This is a hash table type that uses the SDS dynamic strings library as\n * keys and redis objects as values (objects can hold SDS strings,\n * lists, sets). */\n\nvoid dictVanillaFree(void *privdata, void *val)\n{\n    DICT_NOTUSED(privdata);\n    zfree(val);\n}\n\nvoid dictListDestructor(void *privdata, void *val)\n{\n    DICT_NOTUSED(privdata);\n    listRelease((list*)val);\n}\n\nint dictSdsKeyCompare(void *privdata, const void *key1,\n        const void *key2)\n{\n    int l1,l2;\n    DICT_NOTUSED(privdata);\n\n    l1 = sdslen((sds)key1);\n    l2 = sdslen((sds)key2);\n    if (l1 != l2) return 0;\n    return memcmp(key1, key2, l1) == 0;\n}\n\n/* A case insensitive version used for the command lookup table and other\n * places where case insensitive non binary-safe comparison is needed. */\nint dictSdsKeyCaseCompare(void *privdata, const void *key1,\n        const void *key2)\n{\n    DICT_NOTUSED(privdata);\n\n    return strcasecmp(key1, key2) == 0;\n}\n\nvoid dictRedisObjectDestructor(void *privdata, void *val)\n{\n    DICT_NOTUSED(privdata);\n\n    if (val == NULL) return; /* Values of swapped out keys as set to NULL */\n    decrRefCount(val);\n}\n\nvoid dictSdsDestructor(void *privdata, void *val)\n{\n    DICT_NOTUSED(privdata);\n\n    sdsfree(val);\n}\n\nint dictObjKeyCompare(void *privdata, const void *key1,\n        const void *key2)\n{\n    const robj *o1 = key1, *o2 = key2;\n    return dictSdsKeyCompare(privdata,o1->ptr,o2->ptr);\n}\n\nunsigned int dictObjHash(const void *key) {\n    const robj *o = key;\n    return dictGenHashFunction(o->ptr, sdslen((sds)o->ptr));\n}\n\nunsigned int dictSdsHash(const void *key) {\n    return dictGenHashFunction((unsigned char*)key, sdslen((char*)key));\n}\n\nunsigned int dictSdsCaseHash(const void *key) {\n    return dictGenCaseHashFunction((unsigned char*)key, sdslen((char*)key));\n}\n\nint dictEncObjKeyCompare(void *privdata, const void *key1,\n        const void *key2)\n{\n    robj *o1 = (robj*) key1, *o2 = (robj*) key2;\n    int cmp;\n\n    if (o1->encoding == REDIS_ENCODING_INT &&\n        o2->encoding == REDIS_ENCODING_INT)\n            return o1->ptr == o2->ptr;\n\n    o1 = getDecodedObject(o1);\n    o2 = getDecodedObject(o2);\n    cmp = dictSdsKeyCompare(privdata,o1->ptr,o2->ptr);\n    decrRefCount(o1);\n    decrRefCount(o2);\n    return cmp;\n}\n\nunsigned int dictEncObjHash(const void *key) {\n    robj *o = (robj*) key;\n\n    if (o->encoding == REDIS_ENCODING_RAW) {\n        return dictGenHashFunction(o->ptr, sdslen((sds)o->ptr));\n    } else {\n        if (o->encoding == REDIS_ENCODING_INT) {\n            char buf[32];\n            int len;\n\n            len = ll2string(buf,32,(long)o->ptr);\n            return dictGenHashFunction((unsigned char*)buf, len);\n        } else {\n            unsigned int hash;\n\n            o = getDecodedObject(o);\n            hash = dictGenHashFunction(o->ptr, sdslen((sds)o->ptr));\n            decrRefCount(o);\n            return hash;\n        }\n    }\n}\n\n/* Sets type hash table */\ndictType setDictType = {\n    dictEncObjHash,            /* hash function */\n    NULL,                      /* key dup */\n    NULL,                      /* val dup */\n    dictEncObjKeyCompare,      /* key compare */\n    dictRedisObjectDestructor, /* key destructor */\n    NULL                       /* val destructor */\n};\n\n/* Sorted sets hash (note: a skiplist is used in addition to the hash table) */\ndictType zsetDictType = {\n    dictEncObjHash,            /* hash function */\n    NULL,                      /* key dup */\n    NULL,                      /* val dup */\n    dictEncObjKeyCompare,      /* key compare */\n    dictRedisObjectDestructor, /* key destructor */\n    NULL                       /* val destructor */\n};\n\n/* Db->dict, keys are sds strings, vals are Redis objects. */\ndictType dbDictType = {\n    dictSdsHash,                /* hash function */\n    NULL,                       /* key dup */\n    NULL,                       /* val dup */\n    dictSdsKeyCompare,          /* key compare */\n    dictSdsDestructor,          /* key destructor */\n    dictRedisObjectDestructor   /* val destructor */\n};\n\ndictType hashSlotType = {\n    dictSdsHash,                /* hash function */\n    NULL,                       /* key dup */\n    NULL,                       /* val dup */\n    dictSdsKeyCompare,          /* key compare */\n    NULL,                       /* key destructor */\n    NULL                        /* val destructor */\n};\n\n/* server.lua_scripts sha (as sds string) -> scripts (as robj) cache. */\ndictType shaScriptObjectDictType = {\n    dictSdsCaseHash,            /* hash function */\n    NULL,                       /* key dup */\n    NULL,                       /* val dup */\n    dictSdsKeyCaseCompare,      /* key compare */\n    dictSdsDestructor,          /* key destructor */\n    dictRedisObjectDestructor   /* val destructor */\n};\n\n/* Db->expires */\ndictType keyptrDictType = {\n    dictSdsHash,               /* hash function */\n    NULL,                      /* key dup */\n    NULL,                      /* val dup */\n    dictSdsKeyCompare,         /* key compare */\n    NULL,                      /* key destructor */\n    NULL                       /* val destructor */\n};\n\n/* Command table. sds string -> command struct pointer. */\ndictType commandTableDictType = {\n    dictSdsCaseHash,           /* hash function */\n    NULL,                      /* key dup */\n    NULL,                      /* val dup */\n    dictSdsKeyCaseCompare,     /* key compare */\n    dictSdsDestructor,         /* key destructor */\n    NULL                       /* val destructor */\n};\n\n/* Hash type hash table (note that small hashes are represented with ziplists) */\ndictType hashDictType = {\n    dictEncObjHash,             /* hash function */\n    NULL,                       /* key dup */\n    NULL,                       /* val dup */\n    dictEncObjKeyCompare,       /* key compare */\n    dictRedisObjectDestructor,  /* key destructor */\n    dictRedisObjectDestructor   /* val destructor */\n};\n\n/* Keylist hash table type has unencoded redis objects as keys and\n * lists as values. It's used for blocking operations (BLPOP) and to\n * map swapped keys to a list of clients waiting for this keys to be loaded. */\ndictType keylistDictType = {\n    dictObjHash,                /* hash function */\n    NULL,                       /* key dup */\n    NULL,                       /* val dup */\n    dictObjKeyCompare,          /* key compare */\n    dictRedisObjectDestructor,  /* key destructor */\n    dictListDestructor          /* val destructor */\n};\n\n/* Replication cached script dict (server.repl_scriptcache_dict).\n * Keys are sds SHA1 strings, while values are not used at all in the current\n * implementation. */\ndictType replScriptCacheDictType = {\n    dictSdsCaseHash,            /* hash function */\n    NULL,                       /* key dup */\n    NULL,                       /* val dup */\n    dictSdsKeyCaseCompare,      /* key compare */\n    dictSdsDestructor,          /* key destructor */\n    NULL                        /* val destructor */\n};\n\ndictType migrateCacheDictType = {\n    dictSdsHash,                /* hash function */\n    NULL,                       /* key dup */\n    NULL,                       /* val dup */\n    dictSdsKeyCompare,          /* key compare */\n    dictSdsDestructor,          /* key destructor */\n    NULL                        /* val destructor */\n};\n\nint htNeedsResize(dict *dict) {\n    long long size, used;\n\n    size = dictSlots(dict);\n    used = dictSize(dict);\n    return (size && used && size > DICT_HT_INITIAL_SIZE &&\n            (used*100/size < REDIS_HT_MINFILL));\n}\n\n/* If the percentage of used slots in the HT reaches REDIS_HT_MINFILL\n * we resize the hash table to save memory */\nvoid tryResizeHashTables(int dbid) {\n    if (htNeedsResize(server.db[dbid].dict)) {\n        dictResize(server.db[dbid].dict);\n        for (int i = 0; i < HASH_SLOTS_SIZE; i ++) {\n            dict *d = server.db[dbid].hash_slots[i];\n            if (htNeedsResize(d)) {\n                dictResize(d);\n            }\n        }\n    }\n    if (htNeedsResize(server.db[dbid].expires))\n        dictResize(server.db[dbid].expires);\n}\n\n/* Our hash table implementation performs rehashing incrementally while\n * we write/read from the hash table. Still if the server is idle, the hash\n * table will use two tables for a long time. So we try to use 1 millisecond\n * of CPU time at every call of this function to perform some rehahsing.\n *\n * The function returns 1 if some rehashing was performed, otherwise 0\n * is returned. */\nint incrementallyRehash(int dbid) {\n    /* Keys dictionary */\n    if (dictIsRehashing(server.db[dbid].dict)) {\n        dictRehashMilliseconds(server.db[dbid].dict,1);\n\n        long long start = timeInMilliseconds();\n        for (int i = 0; i < HASH_SLOTS_SIZE; i ++) {\n            int idx = ((i + start) & HASH_SLOTS_MASK);\n            dict *d = server.db[dbid].hash_slots[idx];\n            if (dictIsRehashing(d)) {\n                dictRehashMilliseconds(d, 1);\n                if (timeInMilliseconds() != start) {\n                    break;\n                }\n            }\n        }\n        return 1; /* already used our millisecond for this loop... */\n    }\n    /* Expires */\n    if (dictIsRehashing(server.db[dbid].expires)) {\n        dictRehashMilliseconds(server.db[dbid].expires,1);\n        return 1; /* already used our millisecond for this loop... */\n    }\n    return 0;\n}\n\n/* This function is called once a background process of some kind terminates,\n * as we want to avoid resizing the hash tables when there is a child in order\n * to play well with copy-on-write (otherwise when a resize happens lots of\n * memory pages are copied). The goal of this function is to update the ability\n * for dict.c to resize the hash tables accordingly to the fact we have o not\n * running childs. */\nvoid updateDictResizePolicy(void) {\n    if (server.rdb_child_pid == -1 && server.aof_child_pid == -1)\n        dictEnableResize();\n    else\n        dictDisableResize();\n}\n\n/* ======================= Cron: called every 100 ms ======================== */\n\n/* Helper function for the activeExpireCycle() function.\n * This function will try to expire the key that is stored in the hash table\n * entry 'de' of the 'expires' hash table of a Redis database.\n *\n * If the key is found to be expired, it is removed from the database and\n * 1 is returned. Otherwise no operation is performed and 0 is returned.\n *\n * When a key is expired, server.stat_expiredkeys is incremented.\n *\n * The parameter 'now' is the current time in milliseconds as is passed\n * to the function to avoid too many gettimeofday() syscalls. */\nint activeExpireCycleTryExpire(redisDb *db, struct dictEntry *de, long long now) {\n    long long t = dictGetSignedIntegerVal(de);\n    if (now > t) {\n        sds key = dictGetKey(de);\n        robj *keyobj = createStringObject(key,sdslen(key));\n\n        propagateExpire(db,keyobj);\n        dbDelete(db,keyobj);\n        notifyKeyspaceEvent(REDIS_NOTIFY_EXPIRED,\n            \"expired\",keyobj,db->id);\n        decrRefCount(keyobj);\n        server.stat_expiredkeys++;\n        return 1;\n    } else {\n        return 0;\n    }\n}\n\n/* Try to expire a few timed out keys. The algorithm used is adaptive and\n * will use few CPU cycles if there are few expiring keys, otherwise\n * it will get more aggressive to avoid that too much memory is used by\n * keys that can be removed from the keyspace.\n *\n * No more than REDIS_DBCRON_DBS_PER_CALL databases are tested at every\n * iteration.\n *\n * This kind of call is used when Redis detects that timelimit_exit is\n * true, so there is more work to do, and we do it more incrementally from\n * the beforeSleep() function of the event loop.\n *\n * Expire cycle type:\n *\n * If type is ACTIVE_EXPIRE_CYCLE_FAST the function will try to run a\n * \"fast\" expire cycle that takes no longer than EXPIRE_FAST_CYCLE_DURATION\n * microseconds, and is not repeated again before the same amount of time.\n *\n * If type is ACTIVE_EXPIRE_CYCLE_SLOW, that normal expire cycle is\n * executed, where the time limit is a percentage of the REDIS_HZ period\n * as specified by the REDIS_EXPIRELOOKUPS_TIME_PERC define. */\n\nvoid activeExpireCycle(int type) {\n    /* This function has some global state in order to continue the work\n     * incrementally across calls. */\n    static unsigned int current_db = 0; /* Last DB tested. */\n    static int timelimit_exit = 0;      /* Time limit hit in previous call? */\n    static long long last_fast_cycle = 0; /* When last fast cycle ran. */\n\n    int j, iteration = 0;\n    int dbs_per_call = REDIS_DBCRON_DBS_PER_CALL;\n    long long start = ustime(), timelimit;\n\n    if (type == ACTIVE_EXPIRE_CYCLE_FAST) {\n        /* Don't start a fast cycle if the previous cycle did not exited\n         * for time limt. Also don't repeat a fast cycle for the same period\n         * as the fast cycle total duration itself. */\n        if (!timelimit_exit) return;\n        if (start < last_fast_cycle + ACTIVE_EXPIRE_CYCLE_FAST_DURATION*2) return;\n        last_fast_cycle = start;\n    }\n\n    /* We usually should test REDIS_DBCRON_DBS_PER_CALL per iteration, with\n     * two exceptions:\n     *\n     * 1) Don't test more DBs than we have.\n     * 2) If last time we hit the time limit, we want to scan all DBs\n     * in this iteration, as there is work to do in some DB and we don't want\n     * expired keys to use memory for too much time. */\n    if (dbs_per_call > server.dbnum || timelimit_exit)\n        dbs_per_call = server.dbnum;\n\n    /* We can use at max ACTIVE_EXPIRE_CYCLE_SLOW_TIME_PERC percentage of CPU time\n     * per iteration. Since this function gets called with a frequency of\n     * server.hz times per second, the following is the max amount of\n     * microseconds we can spend in this function. */\n    timelimit = 1000000*ACTIVE_EXPIRE_CYCLE_SLOW_TIME_PERC/server.hz/100;\n    timelimit_exit = 0;\n    if (timelimit <= 0) timelimit = 1;\n\n    if (type == ACTIVE_EXPIRE_CYCLE_FAST)\n        timelimit = ACTIVE_EXPIRE_CYCLE_FAST_DURATION; /* in microseconds. */\n\n    for (j = 0; j < dbs_per_call; j++) {\n        int expired;\n        redisDb *db = server.db+(current_db % server.dbnum);\n\n        /* Increment the DB now so we are sure if we run out of time\n         * in the current DB we'll restart from the next. This allows to\n         * distribute the time evenly across DBs. */\n        current_db++;\n\n        /* Continue to expire if at the end of the cycle more than 25%\n         * of the keys were expired. */\n        do {\n            unsigned long num, slots;\n            long long now, ttl_sum;\n            int ttl_samples;\n\n            /* If there is nothing to expire try next DB ASAP. */\n            if ((num = dictSize(db->expires)) == 0) {\n                db->avg_ttl = 0;\n                break;\n            }\n            slots = dictSlots(db->expires);\n            now = mstime();\n\n            /* When there are less than 1% filled slots getting random\n             * keys is expensive, so stop here waiting for better times...\n             * The dictionary will be resized asap. */\n            if (num && slots > DICT_HT_INITIAL_SIZE &&\n                (num*100/slots < 1)) break;\n\n            /* The main collection cycle. Sample random keys among keys\n             * with an expire set, checking for expired ones. */\n            expired = 0;\n            ttl_sum = 0;\n            ttl_samples = 0;\n\n            if (num > ACTIVE_EXPIRE_CYCLE_LOOKUPS_PER_LOOP)\n                num = ACTIVE_EXPIRE_CYCLE_LOOKUPS_PER_LOOP;\n\n            while (num--) {\n                dictEntry *de;\n                long long ttl;\n\n                if ((de = dictGetRandomKey(db->expires)) == NULL) break;\n                ttl = dictGetSignedIntegerVal(de)-now;\n                if (activeExpireCycleTryExpire(db,de,now)) expired++;\n                if (ttl < 0) ttl = 0;\n                ttl_sum += ttl;\n                ttl_samples++;\n            }\n\n            /* Update the average TTL stats for this database. */\n            if (ttl_samples) {\n                long long avg_ttl = ttl_sum/ttl_samples;\n\n                if (db->avg_ttl == 0) db->avg_ttl = avg_ttl;\n                /* Smooth the value averaging with the previous one. */\n                db->avg_ttl = (db->avg_ttl+avg_ttl)/2;\n            }\n\n            /* We can't block forever here even if there are many keys to\n             * expire. So after a given amount of milliseconds return to the\n             * caller waiting for the other active expire cycle. */\n            iteration++;\n            if ((iteration & 0xf) == 0) { /* check once every 16 iterations. */\n                long long elapsed = ustime()-start;\n\n                latencyAddSampleIfNeeded(\"expire-cycle\",elapsed/1000);\n                if (elapsed > timelimit) timelimit_exit = 1;\n            }\n            if (timelimit_exit) return;\n            /* We don't repeat the cycle if there are less than 25% of keys\n             * found expired in the current DB. */\n        } while (expired > ACTIVE_EXPIRE_CYCLE_LOOKUPS_PER_LOOP/4);\n    }\n}\n\nvoid updateLRUClock(void) {\n    server.lruclock = (server.unixtime/REDIS_LRU_CLOCK_RESOLUTION) &\n                                                REDIS_LRU_CLOCK_MAX;\n}\n\n\n/* Add a sample to the operations per second array of samples. */\nvoid trackInstantaneousMetric(int metric, long long current_reading) {\n    long long t = mstime() - server.inst_metric[metric].last_sample_time;\n    long long ops = current_reading -\n                    server.inst_metric[metric].last_sample_count;\n    long long ops_sec;\n\n    ops_sec = t > 0 ? (ops*1000/t) : 0;\n\n    server.inst_metric[metric].samples[server.inst_metric[metric].idx] =\n        ops_sec;\n    server.inst_metric[metric].idx++;\n    server.inst_metric[metric].idx %= REDIS_METRIC_SAMPLES;\n    server.inst_metric[metric].last_sample_time = mstime();\n    server.inst_metric[metric].last_sample_count = current_reading;\n}\n\n/* Return the mean of all the samples. */\nlong long getInstantaneousMetric(int metric) {\n    int j;\n    long long sum = 0;\n\n    for (j = 0; j < REDIS_METRIC_SAMPLES; j++)\n        sum += server.inst_metric[metric].samples[j];\n    return sum / REDIS_METRIC_SAMPLES;\n}\n\n/* Check for timeouts. Returns non-zero if the client was terminated */\nint clientsCronHandleTimeout(redisClient *c) {\n    time_t now = server.unixtime;\n\n    if (server.maxidletime &&\n        !(c->flags & REDIS_SLAVE) &&    /* no timeout for slaves */\n        !(c->flags & REDIS_MASTER) &&   /* no timeout for masters */\n        !(c->flags & REDIS_BLOCKED) &&  /* no timeout for BLPOP */\n        !(c->flags & REDIS_PUBSUB) &&   /* no timeout for Pub/Sub clients */\n        (now - c->lastinteraction > server.maxidletime))\n    {\n        redisLog(REDIS_VERBOSE,\"Closing idle client\");\n        freeClient(c);\n        return 1;\n    } else if (c->flags & REDIS_BLOCKED) {\n        if (c->bpop.timeout != 0 && c->bpop.timeout < now) {\n            addReply(c,shared.nullmultibulk);\n            unblockClientWaitingData(c);\n        }\n    }\n    return 0;\n}\n\n/* The client query buffer is an sds.c string that can end with a lot of\n * free space not used, this function reclaims space if needed.\n *\n * The function always returns 0 as it never terminates the client. */\nint clientsCronResizeQueryBuffer(redisClient *c) {\n    size_t querybuf_size = sdsAllocSize(c->querybuf);\n    time_t idletime = server.unixtime - c->lastinteraction;\n\n    /* There are two conditions to resize the query buffer:\n     * 1) Query buffer is > BIG_ARG and too big for latest peak.\n     * 2) Client is inactive and the buffer is bigger than 1k. */\n    if (((querybuf_size > REDIS_MBULK_BIG_ARG) &&\n         (querybuf_size/(c->querybuf_peak+1)) > 2) ||\n         (querybuf_size > 1024 && idletime > 2))\n    {\n        /* Only resize the query buffer if it is actually wasting space. */\n        if (sdsavail(c->querybuf) > 1024) {\n            c->querybuf = sdsRemoveFreeSpace(c->querybuf);\n        }\n    }\n    /* Reset the peak again to capture the peak memory usage in the next\n     * cycle. */\n    c->querybuf_peak = 0;\n    return 0;\n}\n\nvoid clientsCron(void) {\n    /* Make sure to process at least 1/(server.hz*10) of clients per call.\n     * Since this function is called server.hz times per second we are sure that\n     * in the worst case we process all the clients in 10 seconds.\n     * In normal conditions (a reasonable number of clients) we process\n     * all the clients in a shorter time. */\n    int numclients = listLength(server.clients);\n    int iterations = numclients/(server.hz*10);\n\n    if (iterations < 50)\n        iterations = (numclients < 50) ? numclients : 50;\n    while(listLength(server.clients) && iterations--) {\n        redisClient *c;\n        listNode *head;\n\n        /* Rotate the list, take the current head, process.\n         * This way if the client must be removed from the list it's the\n         * first element and we don't incur into O(N) computation. */\n        listRotate(server.clients);\n        head = listFirst(server.clients);\n        c = listNodeValue(head);\n        /* The following functions do different service checks on the client.\n         * The protocol is that they return non-zero if the client was\n         * terminated. */\n        if (clientsCronHandleTimeout(c)) continue;\n        if (clientsCronResizeQueryBuffer(c)) continue;\n    }\n}\n\n/* This function handles 'background' operations we are required to do\n * incrementally in Redis databases, such as active key expiring, resizing,\n * rehashing. */\nvoid databasesCron(void) {\n    /* Expire keys by random sampling. Not required for slaves\n     * as master will synthesize DELs for us. */\n    if (server.active_expire_enabled && server.masterhost == NULL)\n        activeExpireCycle(ACTIVE_EXPIRE_CYCLE_SLOW);\n\n    /* Perform hash tables rehashing if needed, but only if there are no\n     * other processes saving the DB on disk. Otherwise rehashing is bad\n     * as will cause a lot of copy-on-write of memory pages. */\n    if (server.rdb_child_pid == -1 && server.aof_child_pid == -1) {\n        /* We use global counters so if we stop the computation at a given\n         * DB we'll be able to start from the successive in the next\n         * cron loop iteration. */\n        static unsigned int resize_db = 0;\n        static unsigned int rehash_db = 0;\n        int dbs_per_call = REDIS_DBCRON_DBS_PER_CALL;\n        int j;\n\n        /* Don't test more DBs than we have. */\n        if (dbs_per_call > server.dbnum) dbs_per_call = server.dbnum;\n\n        /* Resize */\n        for (j = 0; j < dbs_per_call; j++) {\n            tryResizeHashTables(resize_db % server.dbnum);\n            resize_db++;\n        }\n\n        /* Rehash */\n        if (server.activerehashing) {\n            for (j = 0; j < dbs_per_call; j++) {\n                int work_done = incrementallyRehash(rehash_db % server.dbnum);\n                rehash_db++;\n                if (work_done) {\n                    /* If the function did some work, stop here, we'll do\n                     * more at the next cron loop. */\n                    break;\n                }\n            }\n        }\n    }\n}\n\n/* We take a cached value of the unix time in the global state because with\n * virtual memory and aging there is to store the current time in objects at\n * every object access, and accuracy is not needed. To access a global var is\n * a lot faster than calling time(NULL) */\nvoid updateCachedTime(void) {\n    server.unixtime = time(NULL);\n    server.mstime = mstime();\n}\n\n/* This is our timer interrupt, called server.hz times per second.\n * Here is where we do a number of things that need to be done asynchronously.\n * For instance:\n *\n * - Active expired keys collection (it is also performed in a lazy way on\n *   lookup).\n * - Software watchdog.\n * - Update some statistic.\n * - Incremental rehashing of the DBs hash tables.\n * - Triggering BGSAVE / AOF rewrite, and handling of terminated children.\n * - Clients timeout of different kinds.\n * - Replication reconnection.\n * - Many more...\n *\n * Everything directly called here will be called server.hz times per second,\n * so in order to throttle execution of things we want to do less frequently\n * a macro is used: run_with_period(milliseconds) { .... }\n */\n\nint serverCron(struct aeEventLoop *eventLoop, long long id, void *clientData) {\n    int j;\n    REDIS_NOTUSED(eventLoop);\n    REDIS_NOTUSED(id);\n    REDIS_NOTUSED(clientData);\n\n    /* Software watchdog: deliver the SIGALRM that will reach the signal\n     * handler if we don't return here fast enough. */\n    if (server.watchdog_period) watchdogScheduleSignal(server.watchdog_period);\n\n    /* Update the time cache. */\n    updateCachedTime();\n\n    run_with_period(100) {\n        trackInstantaneousMetric(REDIS_METRIC_COMMAND,server.stat_numcommands);\n        trackInstantaneousMetric(REDIS_METRIC_NET_INPUT,\n                server.stat_net_input_bytes);\n        trackInstantaneousMetric(REDIS_METRIC_NET_OUTPUT,\n                server.stat_net_output_bytes);\n    }\n\n    /* We have just 22 bits per object for LRU information.\n     * So we use an (eventually wrapping) LRU clock with 10 seconds resolution.\n     * 2^22 bits with 10 seconds resolution is more or less 1.5 years.\n     *\n     * Note that even if this will wrap after 1.5 years it's not a problem,\n     * everything will still work but just some object will appear younger\n     * to Redis. But for this to happen a given object should never be touched\n     * for 1.5 years.\n     *\n     * Note that you can change the resolution altering the\n     * REDIS_LRU_CLOCK_RESOLUTION define.\n     */\n    updateLRUClock();\n\n    /* Record the max memory used since the server was started. */\n    if (zmalloc_used_memory() > server.stat_peak_memory)\n        server.stat_peak_memory = zmalloc_used_memory();\n\n    /* Sample the RSS here since this is a relatively slow call. */\n    server.resident_set_size = zmalloc_get_rss();\n\n    /* We received a SIGTERM, shutting down here in a safe way, as it is\n     * not ok doing so inside the signal handler. */\n    if (server.shutdown_asap) {\n        if (prepareForShutdown(0) == REDIS_OK) exit(0);\n        redisLog(REDIS_WARNING,\"SIGTERM received but errors trying to shut down the server, check the logs for more information\");\n        server.shutdown_asap = 0;\n    }\n\n    /* Show some info about non-empty databases */\n    run_with_period(5000) {\n        for (j = 0; j < server.dbnum; j++) {\n            long long size, used, vkeys;\n\n            size = dictSlots(server.db[j].dict);\n            used = dictSize(server.db[j].dict);\n            vkeys = dictSize(server.db[j].expires);\n            if (used || vkeys) {\n                redisLog(REDIS_VERBOSE,\"DB %d: %lld keys (%lld volatile) in %lld slots HT.\",j,used,vkeys,size);\n                /* dictPrintStats(server.dict); */\n            }\n        }\n    }\n\n    /* Show information about connected clients */\n    if (!server.sentinel_mode) {\n        run_with_period(5000) {\n            redisLog(REDIS_VERBOSE,\n                \"%lu clients connected (%lu slaves), %zu bytes in use\",\n                listLength(server.clients)-listLength(server.slaves),\n                listLength(server.slaves),\n                zmalloc_used_memory());\n        }\n    }\n\n    /* We need to do a few operations on clients asynchronously. */\n    clientsCron();\n\n    /* Handle background operations on Redis databases. */\n    databasesCron();\n\n    /* Start a scheduled AOF rewrite if this was requested by the user while\n     * a BGSAVE was in progress. */\n    if (server.rdb_child_pid == -1 && server.aof_child_pid == -1 &&\n        server.aof_rewrite_scheduled)\n    {\n        rewriteAppendOnlyFileBackground();\n    }\n\n    /* Check if a background saving or AOF rewrite in progress terminated. */\n    if (server.rdb_child_pid != -1 || server.aof_child_pid != -1) {\n        int statloc;\n        pid_t pid;\n\n        if ((pid = wait3(&statloc,WNOHANG,NULL)) != 0) {\n            int exitcode = WEXITSTATUS(statloc);\n            int bysignal = 0;\n\n            if (WIFSIGNALED(statloc)) bysignal = WTERMSIG(statloc);\n\n            if (pid == server.rdb_child_pid) {\n                backgroundSaveDoneHandler(exitcode,bysignal);\n            } else if (pid == server.aof_child_pid) {\n                backgroundRewriteDoneHandler(exitcode,bysignal);\n            } else {\n                redisLog(REDIS_WARNING,\n                    \"Warning, detected child with unmatched pid: %ld\",\n                    (long)pid);\n            }\n            updateDictResizePolicy();\n        }\n    } else {\n        /* If there is not a background saving/rewrite in progress check if\n         * we have to save/rewrite now */\n         for (j = 0; j < server.saveparamslen; j++) {\n            struct saveparam *sp = server.saveparams+j;\n\n            /* Save if we reached the given amount of changes,\n             * the given amount of seconds, and if the latest bgsave was\n             * successful or if, in case of an error, at least\n             * REDIS_BGSAVE_RETRY_DELAY seconds already elapsed. */\n            if (server.dirty >= sp->changes &&\n                server.unixtime-server.lastsave > sp->seconds &&\n                (server.unixtime-server.lastbgsave_try >\n                 REDIS_BGSAVE_RETRY_DELAY ||\n                 server.lastbgsave_status == REDIS_OK))\n            {\n                redisLog(REDIS_NOTICE,\"%d changes in %d seconds. Saving...\",\n                    sp->changes, (int)sp->seconds);\n                rdbSaveBackground(server.rdb_filename);\n                break;\n            }\n         }\n\n         /* Trigger an AOF rewrite if needed */\n         if (server.rdb_child_pid == -1 &&\n             server.aof_child_pid == -1 &&\n             server.aof_rewrite_perc &&\n             server.aof_current_size > server.aof_rewrite_min_size)\n         {\n            long long base = server.aof_rewrite_base_size ?\n                            server.aof_rewrite_base_size : 1;\n            long long growth = (server.aof_current_size*100/base) - 100;\n            if (growth >= server.aof_rewrite_perc) {\n                redisLog(REDIS_NOTICE,\"Starting automatic rewriting of AOF on %lld%% growth\",growth);\n                rewriteAppendOnlyFileBackground();\n            }\n         }\n    }\n\n\n    /* AOF postponed flush: Try at every cron cycle if the slow fsync\n     * completed. */\n    if (server.aof_flush_postponed_start) flushAppendOnlyFile(0);\n\n    /* AOF write errors: in this case we have a buffer to flush as well and\n     * clear the AOF error in case of success to make the DB writable again,\n     * however to try every second is enough in case of 'hz' is set to\n     * an higher frequency. */\n    run_with_period(1000) {\n        if (server.aof_last_write_status == REDIS_ERR)\n            flushAppendOnlyFile(0);\n    }\n\n    /* Close clients that need to be closed asynchronous */\n    freeClientsInAsyncFreeQueue();\n\n    /* Replication cron function -- used to reconnect to master and\n     * to detect transfer failures. */\n    run_with_period(1000) replicationCron();\n\n    /* Run the sentinel timer if we are in sentinel mode. */\n    run_with_period(100) {\n        if (server.sentinel_mode) sentinelTimer();\n    }\n\n    run_with_period(1000) {\n        slotsmgrt_cleanup();\n    }\n\n    server.cronloops++;\n    return 1000/server.hz;\n}\n\n/* This function gets called every time Redis is entering the\n * main loop of the event driven library, that is, before to sleep\n * for ready file descriptors. */\nvoid beforeSleep(struct aeEventLoop *eventLoop) {\n    REDIS_NOTUSED(eventLoop);\n    listNode *ln;\n    redisClient *c;\n\n    /* Run a fast expire cycle (the called function will return\n     * ASAP if a fast cycle is not needed). */\n    if (server.active_expire_enabled && server.masterhost == NULL)\n        activeExpireCycle(ACTIVE_EXPIRE_CYCLE_FAST);\n\n    /* Try to process pending commands for clients that were just unblocked. */\n    while (listLength(server.unblocked_clients)) {\n        ln = listFirst(server.unblocked_clients);\n        redisAssert(ln != NULL);\n        c = ln->value;\n        listDelNode(server.unblocked_clients,ln);\n        c->flags &= ~REDIS_UNBLOCKED;\n\n        /* Process remaining data in the input buffer. */\n        if (c->querybuf && sdslen(c->querybuf) > 0) {\n            server.current_client = c;\n            processInputBuffer(c);\n            server.current_client = NULL;\n        }\n    }\n\n    /* Write the AOF buffer on disk */\n    flushAppendOnlyFile(0);\n}\n\n/* =========================== Server initialization ======================== */\n\nvoid createSharedObjects(void) {\n    int j;\n\n    shared.crlf = createObject(REDIS_STRING,sdsnew(\"\\r\\n\"));\n    shared.ok = createObject(REDIS_STRING,sdsnew(\"+OK\\r\\n\"));\n    shared.err = createObject(REDIS_STRING,sdsnew(\"-ERR\\r\\n\"));\n    shared.emptybulk = createObject(REDIS_STRING,sdsnew(\"$0\\r\\n\\r\\n\"));\n    shared.czero = createObject(REDIS_STRING,sdsnew(\":0\\r\\n\"));\n    shared.cone = createObject(REDIS_STRING,sdsnew(\":1\\r\\n\"));\n    shared.cnegone = createObject(REDIS_STRING,sdsnew(\":-1\\r\\n\"));\n    shared.nullbulk = createObject(REDIS_STRING,sdsnew(\"$-1\\r\\n\"));\n    shared.nullmultibulk = createObject(REDIS_STRING,sdsnew(\"*-1\\r\\n\"));\n    shared.emptymultibulk = createObject(REDIS_STRING,sdsnew(\"*0\\r\\n\"));\n    shared.pong = createObject(REDIS_STRING,sdsnew(\"+PONG\\r\\n\"));\n    shared.queued = createObject(REDIS_STRING,sdsnew(\"+QUEUED\\r\\n\"));\n    shared.emptyscan = createObject(REDIS_STRING,sdsnew(\"*2\\r\\n$1\\r\\n0\\r\\n*0\\r\\n\"));\n    shared.wrongtypeerr = createObject(REDIS_STRING,sdsnew(\n        \"-WRONGTYPE Operation against a key holding the wrong kind of value\\r\\n\"));\n    shared.nokeyerr = createObject(REDIS_STRING,sdsnew(\n        \"-ERR no such key\\r\\n\"));\n    shared.syntaxerr = createObject(REDIS_STRING,sdsnew(\n        \"-ERR syntax error\\r\\n\"));\n    shared.sameobjecterr = createObject(REDIS_STRING,sdsnew(\n        \"-ERR source and destination objects are the same\\r\\n\"));\n    shared.outofrangeerr = createObject(REDIS_STRING,sdsnew(\n        \"-ERR index out of range\\r\\n\"));\n    shared.noscripterr = createObject(REDIS_STRING,sdsnew(\n        \"-NOSCRIPT No matching script. Please use EVAL.\\r\\n\"));\n    shared.loadingerr = createObject(REDIS_STRING,sdsnew(\n        \"-LOADING Redis is loading the dataset in memory\\r\\n\"));\n    shared.slowscripterr = createObject(REDIS_STRING,sdsnew(\n        \"-BUSY Redis is busy running a script. You can only call SCRIPT KILL or SHUTDOWN NOSAVE.\\r\\n\"));\n    shared.masterdownerr = createObject(REDIS_STRING,sdsnew(\n        \"-MASTERDOWN Link with MASTER is down and slave-serve-stale-data is set to 'no'.\\r\\n\"));\n    shared.bgsaveerr = createObject(REDIS_STRING,sdsnew(\n        \"-MISCONF Redis is configured to save RDB snapshots, but is currently not able to persist on disk. Commands that may modify the data set are disabled. Please check Redis logs for details about the error.\\r\\n\"));\n    shared.roslaveerr = createObject(REDIS_STRING,sdsnew(\n        \"-READONLY You can't write against a read only slave.\\r\\n\"));\n    shared.noautherr = createObject(REDIS_STRING,sdsnew(\n        \"-NOAUTH Authentication required.\\r\\n\"));\n    shared.oomerr = createObject(REDIS_STRING,sdsnew(\n        \"-OOM command not allowed when used memory > 'maxmemory'.\\r\\n\"));\n    shared.execaborterr = createObject(REDIS_STRING,sdsnew(\n        \"-EXECABORT Transaction discarded because of previous errors.\\r\\n\"));\n    shared.noreplicaserr = createObject(REDIS_STRING,sdsnew(\n        \"-NOREPLICAS Not enough good slaves to write.\\r\\n\"));\n    shared.space = createObject(REDIS_STRING,sdsnew(\" \"));\n    shared.colon = createObject(REDIS_STRING,sdsnew(\":\"));\n    shared.plus = createObject(REDIS_STRING,sdsnew(\"+\"));\n\n    for (j = 0; j < REDIS_SHARED_SELECT_CMDS; j++) {\n        char dictid_str[64];\n        int dictid_len;\n\n        dictid_len = ll2string(dictid_str,sizeof(dictid_str),j);\n        shared.select[j] = createObject(REDIS_STRING,\n            sdscatprintf(sdsempty(),\n                \"*2\\r\\n$6\\r\\nSELECT\\r\\n$%d\\r\\n%s\\r\\n\",\n                dictid_len, dictid_str));\n    }\n    shared.messagebulk = createStringObject(\"$7\\r\\nmessage\\r\\n\",13);\n    shared.pmessagebulk = createStringObject(\"$8\\r\\npmessage\\r\\n\",14);\n    shared.subscribebulk = createStringObject(\"$9\\r\\nsubscribe\\r\\n\",15);\n    shared.unsubscribebulk = createStringObject(\"$11\\r\\nunsubscribe\\r\\n\",18);\n    shared.psubscribebulk = createStringObject(\"$10\\r\\npsubscribe\\r\\n\",17);\n    shared.punsubscribebulk = createStringObject(\"$12\\r\\npunsubscribe\\r\\n\",19);\n    shared.del = createStringObject(\"DEL\",3);\n    shared.rpop = createStringObject(\"RPOP\",4);\n    shared.lpop = createStringObject(\"LPOP\",4);\n    shared.lpush = createStringObject(\"LPUSH\",5);\n    for (j = 0; j < REDIS_SHARED_INTEGERS; j++) {\n        shared.integers[j] = createObject(REDIS_STRING,(void*)(long)j);\n        shared.integers[j]->encoding = REDIS_ENCODING_INT;\n    }\n    for (j = 0; j < REDIS_SHARED_BULKHDR_LEN; j++) {\n        shared.mbulkhdr[j] = createObject(REDIS_STRING,\n            sdscatprintf(sdsempty(),\"*%d\\r\\n\",j));\n        shared.bulkhdr[j] = createObject(REDIS_STRING,\n            sdscatprintf(sdsempty(),\"$%d\\r\\n\",j));\n    }\n    /* The following two shared objects, minstring and maxstrings, are not\n     * actually used for their value but as a special object meaning\n     * respectively the minimum possible string and the maximum possible\n     * string in string comparisons for the ZRANGEBYLEX command. */\n    shared.minstring = createStringObject(\"minstring\",9);\n    shared.maxstring = createStringObject(\"maxstring\",9);\n}\n\nvoid initServerConfig(void) {\n    int j;\n\n    getRandomHexChars(server.runid,REDIS_RUN_ID_SIZE);\n    server.configfile = NULL;\n    server.hz = REDIS_DEFAULT_HZ;\n    server.runid[REDIS_RUN_ID_SIZE] = '\\0';\n    server.arch_bits = (sizeof(long) == 8) ? 64 : 32;\n    server.port = REDIS_SERVERPORT;\n    server.tcp_backlog = REDIS_TCP_BACKLOG;\n    server.bindaddr_count = 0;\n    server.unixsocket = NULL;\n    server.unixsocketperm = REDIS_DEFAULT_UNIX_SOCKET_PERM;\n    server.ipfd_count = 0;\n    server.sofd = -1;\n    server.dbnum = REDIS_DEFAULT_DBNUM;\n    server.verbosity = REDIS_DEFAULT_VERBOSITY;\n    server.maxidletime = REDIS_MAXIDLETIME;\n    server.tcpkeepalive = REDIS_DEFAULT_TCP_KEEPALIVE;\n    server.active_expire_enabled = 1;\n    server.client_max_querybuf_len = REDIS_MAX_QUERYBUF_LEN;\n    server.saveparams = NULL;\n    server.loading = 0;\n    server.logfile = zstrdup(REDIS_DEFAULT_LOGFILE);\n    server.syslog_enabled = REDIS_DEFAULT_SYSLOG_ENABLED;\n    server.syslog_ident = zstrdup(REDIS_DEFAULT_SYSLOG_IDENT);\n    server.syslog_facility = LOG_LOCAL0;\n    server.daemonize = REDIS_DEFAULT_DAEMONIZE;\n    server.aof_state = REDIS_AOF_OFF;\n    server.aof_fsync = REDIS_DEFAULT_AOF_FSYNC;\n    server.aof_no_fsync_on_rewrite = REDIS_DEFAULT_AOF_NO_FSYNC_ON_REWRITE;\n    server.aof_rewrite_perc = REDIS_AOF_REWRITE_PERC;\n    server.aof_rewrite_min_size = REDIS_AOF_REWRITE_MIN_SIZE;\n    server.aof_rewrite_base_size = 0;\n    server.aof_rewrite_scheduled = 0;\n    server.aof_last_fsync = time(NULL);\n    server.aof_rewrite_time_last = -1;\n    server.aof_rewrite_time_start = -1;\n    server.aof_lastbgrewrite_status = REDIS_OK;\n    server.aof_delayed_fsync = 0;\n    server.aof_fd = -1;\n    server.aof_selected_db = -1; /* Make sure the first time will not match */\n    server.aof_flush_postponed_start = 0;\n    server.aof_rewrite_incremental_fsync = REDIS_DEFAULT_AOF_REWRITE_INCREMENTAL_FSYNC;\n    server.aof_load_truncated = REDIS_DEFAULT_AOF_LOAD_TRUNCATED;\n    server.pidfile = zstrdup(REDIS_DEFAULT_PID_FILE);\n    server.rdb_filename = zstrdup(REDIS_DEFAULT_RDB_FILENAME);\n    server.aof_filename = zstrdup(REDIS_DEFAULT_AOF_FILENAME);\n    server.requirepass = NULL;\n    server.rdb_compression = REDIS_DEFAULT_RDB_COMPRESSION;\n    server.rdb_checksum = REDIS_DEFAULT_RDB_CHECKSUM;\n    server.stop_writes_on_bgsave_err = REDIS_DEFAULT_STOP_WRITES_ON_BGSAVE_ERROR;\n    server.activerehashing = REDIS_DEFAULT_ACTIVE_REHASHING;\n    server.notify_keyspace_events = 0;\n    server.maxclients = REDIS_MAX_CLIENTS;\n    server.bpop_blocked_clients = 0;\n    server.maxmemory = REDIS_DEFAULT_MAXMEMORY;\n    server.maxmemory_policy = REDIS_DEFAULT_MAXMEMORY_POLICY;\n    server.maxmemory_samples = REDIS_DEFAULT_MAXMEMORY_SAMPLES;\n    server.hash_max_ziplist_entries = REDIS_HASH_MAX_ZIPLIST_ENTRIES;\n    server.hash_max_ziplist_value = REDIS_HASH_MAX_ZIPLIST_VALUE;\n    server.list_max_ziplist_entries = REDIS_LIST_MAX_ZIPLIST_ENTRIES;\n    server.list_max_ziplist_value = REDIS_LIST_MAX_ZIPLIST_VALUE;\n    server.set_max_intset_entries = REDIS_SET_MAX_INTSET_ENTRIES;\n    server.zset_max_ziplist_entries = REDIS_ZSET_MAX_ZIPLIST_ENTRIES;\n    server.zset_max_ziplist_value = REDIS_ZSET_MAX_ZIPLIST_VALUE;\n    server.hll_sparse_max_bytes = REDIS_DEFAULT_HLL_SPARSE_MAX_BYTES;\n    server.shutdown_asap = 0;\n    server.repl_ping_slave_period = REDIS_REPL_PING_SLAVE_PERIOD;\n    server.repl_timeout = REDIS_REPL_TIMEOUT;\n    server.repl_min_slaves_to_write = REDIS_DEFAULT_MIN_SLAVES_TO_WRITE;\n    server.repl_min_slaves_max_lag = REDIS_DEFAULT_MIN_SLAVES_MAX_LAG;\n    server.lua_caller = NULL;\n    server.lua_time_limit = REDIS_LUA_TIME_LIMIT;\n    server.lua_client = NULL;\n    server.lua_timedout = 0;\n    server.next_client_id = 1; /* Client IDs, start from 1 .*/\n    server.loading_process_events_interval_bytes = (1024*1024*2);\n\n    server.slotsmgrt_cached_sockfds = dictCreate(&migrateCacheDictType, NULL);\n\n    updateLRUClock();\n    resetServerSaveParams();\n\n    appendServerSaveParams(60*60,1);  /* save after 1 hour and 1 change */\n    appendServerSaveParams(300,100);  /* save after 5 minutes and 100 changes */\n    appendServerSaveParams(60,10000); /* save after 1 minute and 10000 changes */\n    /* Replication related */\n    server.masterauth = NULL;\n    server.masterhost = NULL;\n    server.masterport = 6379;\n    server.master = NULL;\n    server.cached_master = NULL;\n    server.repl_master_initial_offset = -1;\n    server.repl_state = REDIS_REPL_NONE;\n    server.repl_syncio_timeout = REDIS_REPL_SYNCIO_TIMEOUT;\n    server.repl_serve_stale_data = REDIS_DEFAULT_SLAVE_SERVE_STALE_DATA;\n    server.repl_slave_ro = REDIS_DEFAULT_SLAVE_READ_ONLY;\n    server.repl_down_since = 0; /* Never connected, repl is down since EVER. */\n    server.repl_disable_tcp_nodelay = REDIS_DEFAULT_REPL_DISABLE_TCP_NODELAY;\n    server.repl_diskless_sync = REDIS_DEFAULT_REPL_DISKLESS_SYNC;\n    server.repl_diskless_sync_delay = REDIS_DEFAULT_REPL_DISKLESS_SYNC_DELAY;\n    server.slave_priority = REDIS_DEFAULT_SLAVE_PRIORITY;\n    server.master_repl_offset = 0;\n\n    /* Replication partial resync backlog */\n    server.repl_backlog = NULL;\n    server.repl_backlog_size = REDIS_DEFAULT_REPL_BACKLOG_SIZE;\n    server.repl_backlog_histlen = 0;\n    server.repl_backlog_idx = 0;\n    server.repl_backlog_off = 0;\n    server.repl_backlog_time_limit = REDIS_DEFAULT_REPL_BACKLOG_TIME_LIMIT;\n    server.repl_no_slaves_since = time(NULL);\n\n    /* Client output buffer limits */\n    for (j = 0; j < REDIS_CLIENT_TYPE_COUNT; j++)\n        server.client_obuf_limits[j] = clientBufferLimitsDefaults[j];\n\n    /* Double constants initialization */\n    R_Zero = 0.0;\n    R_PosInf = 1.0/R_Zero;\n    R_NegInf = -1.0/R_Zero;\n    R_Nan = R_Zero/R_Zero;\n\n    /* Command table -- we initiialize it here as it is part of the\n     * initial configuration, since command names may be changed via\n     * redis.conf using the rename-command directive. */\n    server.commands = dictCreate(&commandTableDictType,NULL);\n    server.orig_commands = dictCreate(&commandTableDictType,NULL);\n    populateCommandTable();\n    server.delCommand = lookupCommandByCString(\"del\");\n    server.multiCommand = lookupCommandByCString(\"multi\");\n    server.lpushCommand = lookupCommandByCString(\"lpush\");\n    server.lpopCommand = lookupCommandByCString(\"lpop\");\n    server.rpopCommand = lookupCommandByCString(\"rpop\");\n\n    /* Slow log */\n    server.slowlog_log_slower_than = REDIS_SLOWLOG_LOG_SLOWER_THAN;\n    server.slowlog_max_len = REDIS_SLOWLOG_MAX_LEN;\n\n    /* Latency monitor */\n    server.latency_monitor_threshold = REDIS_DEFAULT_LATENCY_MONITOR_THRESHOLD;\n\n    /* Debugging */\n    server.assert_failed = \"<no assertion failed>\";\n    server.assert_file = \"<no file>\";\n    server.assert_line = 0;\n    server.bug_report_start = 0;\n    server.watchdog_period = 0;\n}\n\n/* This function will try to raise the max number of open files accordingly to\n * the configured max number of clients. It also reserves a number of file\n * descriptors (REDIS_MIN_RESERVED_FDS) for extra operations of\n * persistence, listening sockets, log files and so forth.\n *\n * If it will not be possible to set the limit accordingly to the configured\n * max number of clients, the function will do the reverse setting\n * server.maxclients to the value that we can actually handle. */\nvoid adjustOpenFilesLimit(void) {\n    rlim_t maxfiles = server.maxclients+REDIS_MIN_RESERVED_FDS;\n    struct rlimit limit;\n\n    if (getrlimit(RLIMIT_NOFILE,&limit) == -1) {\n        redisLog(REDIS_WARNING,\"Unable to obtain the current NOFILE limit (%s), assuming 1024 and setting the max clients configuration accordingly.\",\n            strerror(errno));\n        server.maxclients = 1024-REDIS_MIN_RESERVED_FDS;\n    } else {\n        rlim_t oldlimit = limit.rlim_cur;\n\n        /* Set the max number of files if the current limit is not enough\n         * for our needs. */\n        if (oldlimit < maxfiles) {\n            rlim_t bestlimit;\n            int setrlimit_error = 0;\n\n            /* Try to set the file limit to match 'maxfiles' or at least\n             * to the higher value supported less than maxfiles. */\n            bestlimit = maxfiles;\n            while(bestlimit > oldlimit) {\n                rlim_t decr_step = 16;\n\n                limit.rlim_cur = bestlimit;\n                limit.rlim_max = bestlimit;\n                if (setrlimit(RLIMIT_NOFILE,&limit) != -1) break;\n                setrlimit_error = errno;\n\n                /* We failed to set file limit to 'bestlimit'. Try with a\n                 * smaller limit decrementing by a few FDs per iteration. */\n                if (bestlimit < decr_step) break;\n                bestlimit -= decr_step;\n            }\n\n            /* Assume that the limit we get initially is still valid if\n             * our last try was even lower. */\n            if (bestlimit < oldlimit) bestlimit = oldlimit;\n\n            if (bestlimit < maxfiles) {\n                int old_maxclients = server.maxclients;\n                server.maxclients = bestlimit-REDIS_MIN_RESERVED_FDS;\n                if (server.maxclients < 1) {\n                    redisLog(REDIS_WARNING,\"Your current 'ulimit -n' \"\n                        \"of %llu is not enough for Redis to start. \"\n                        \"Please increase your open file limit to at least \"\n                        \"%llu. Exiting.\",\n                        (unsigned long long) oldlimit,\n                        (unsigned long long) maxfiles);\n                    exit(1);\n                }\n                redisLog(REDIS_WARNING,\"You requested maxclients of %d \"\n                    \"requiring at least %llu max file descriptors.\",\n                    old_maxclients,\n                    (unsigned long long) maxfiles);\n                redisLog(REDIS_WARNING,\"Redis can't set maximum open files \"\n                    \"to %llu because of OS error: %s.\",\n                    (unsigned long long) maxfiles, strerror(setrlimit_error));\n                redisLog(REDIS_WARNING,\"Current maximum open files is %llu. \"\n                    \"maxclients has been reduced to %d to compensate for \"\n                    \"low ulimit. \"\n                    \"If you need higher maxclients increase 'ulimit -n'.\",\n                    (unsigned long long) bestlimit, server.maxclients);\n            } else {\n                redisLog(REDIS_NOTICE,\"Increased maximum number of open files \"\n                    \"to %llu (it was originally set to %llu).\",\n                    (unsigned long long) maxfiles,\n                    (unsigned long long) oldlimit);\n            }\n        }\n    }\n}\n\n/* Check that server.tcp_backlog can be actually enforced in Linux according\n * to the value of /proc/sys/net/core/somaxconn, or warn about it. */\nvoid checkTcpBacklogSettings(void) {\n#ifdef HAVE_PROC_SOMAXCONN\n    FILE *fp = fopen(\"/proc/sys/net/core/somaxconn\",\"r\");\n    char buf[1024];\n    if (!fp) return;\n    if (fgets(buf,sizeof(buf),fp) != NULL) {\n        int somaxconn = atoi(buf);\n        if (somaxconn > 0 && somaxconn < server.tcp_backlog) {\n            redisLog(REDIS_WARNING,\"WARNING: The TCP backlog setting of %d cannot be enforced because /proc/sys/net/core/somaxconn is set to the lower value of %d.\", server.tcp_backlog, somaxconn);\n        }\n    }\n    fclose(fp);\n#endif\n}\n\n/* Initialize a set of file descriptors to listen to the specified 'port'\n * binding the addresses specified in the Redis server configuration.\n *\n * The listening file descriptors are stored in the integer array 'fds'\n * and their number is set in '*count'.\n *\n * The addresses to bind are specified in the global server.bindaddr array\n * and their number is server.bindaddr_count. If the server configuration\n * contains no specific addresses to bind, this function will try to\n * bind * (all addresses) for both the IPv4 and IPv6 protocols.\n *\n * On success the function returns REDIS_OK.\n *\n * On error the function returns REDIS_ERR. For the function to be on\n * error, at least one of the server.bindaddr addresses was\n * impossible to bind, or no bind addresses were specified in the server\n * configuration but the function is not able to bind * for at least\n * one of the IPv4 or IPv6 protocols. */\nint listenToPort(int port, int *fds, int *count) {\n    int j;\n\n    /* Force binding of 0.0.0.0 if no bind address is specified, always\n     * entering the loop if j == 0. */\n    if (server.bindaddr_count == 0) server.bindaddr[0] = NULL;\n    for (j = 0; j < server.bindaddr_count || j == 0; j++) {\n        if (server.bindaddr[j] == NULL) {\n            /* Bind * for both IPv6 and IPv4, we enter here only if\n             * server.bindaddr_count == 0. */\n            fds[*count] = anetTcp6Server(server.neterr,port,NULL,\n                server.tcp_backlog);\n            if (fds[*count] != ANET_ERR) {\n                anetNonBlock(NULL,fds[*count]);\n                (*count)++;\n            }\n            fds[*count] = anetTcpServer(server.neterr,port,NULL,\n                server.tcp_backlog);\n            if (fds[*count] != ANET_ERR) {\n                anetNonBlock(NULL,fds[*count]);\n                (*count)++;\n            }\n            /* Exit the loop if we were able to bind * on IPv4 or IPv6,\n             * otherwise fds[*count] will be ANET_ERR and we'll print an\n             * error and return to the caller with an error. */\n            if (*count) break;\n        } else if (strchr(server.bindaddr[j],':')) {\n            /* Bind IPv6 address. */\n            fds[*count] = anetTcp6Server(server.neterr,port,server.bindaddr[j],\n                server.tcp_backlog);\n        } else {\n            /* Bind IPv4 address. */\n            fds[*count] = anetTcpServer(server.neterr,port,server.bindaddr[j],\n                server.tcp_backlog);\n        }\n        if (fds[*count] == ANET_ERR) {\n            redisLog(REDIS_WARNING,\n                \"Creating Server TCP listening socket %s:%d: %s\",\n                server.bindaddr[j] ? server.bindaddr[j] : \"*\",\n                server.port, server.neterr);\n            return REDIS_ERR;\n        }\n        anetNonBlock(NULL,fds[*count]);\n        (*count)++;\n    }\n    return REDIS_OK;\n}\n\n/* Resets the stats that we expose via INFO or other means that we want\n * to reset via CONFIG RESETSTAT. The function is also used in order to\n * initialize these fields in initServer() at server startup. */\nvoid resetServerStats(void) {\n    int j;\n\n    server.stat_numcommands = 0;\n    server.stat_numconnections = 0;\n    server.stat_expiredkeys = 0;\n    server.stat_evictedkeys = 0;\n    server.stat_keyspace_misses = 0;\n    server.stat_keyspace_hits = 0;\n    server.stat_fork_time = 0;\n    server.stat_fork_rate = 0;\n    server.stat_rejected_conn = 0;\n    server.stat_sync_full = 0;\n    server.stat_sync_partial_ok = 0;\n    server.stat_sync_partial_err = 0;\n    for (j = 0; j < REDIS_METRIC_COUNT; j++) {\n        server.inst_metric[j].idx = 0;\n        server.inst_metric[j].last_sample_time = mstime();\n        server.inst_metric[j].last_sample_count = 0;\n        memset(server.inst_metric[j].samples,0,\n            sizeof(server.inst_metric[j].samples));\n    }\n    server.stat_net_input_bytes = 0;\n    server.stat_net_output_bytes = 0;\n}\n\nvoid initServer(void) {\n    int i, j;\n\n    signal(SIGHUP, SIG_IGN);\n    signal(SIGPIPE, SIG_IGN);\n    setupSignalHandlers();\n\n    crc32_init();\n\n    if (server.syslog_enabled) {\n        openlog(server.syslog_ident, LOG_PID | LOG_NDELAY | LOG_NOWAIT,\n            server.syslog_facility);\n    }\n\n    server.current_client = NULL;\n    server.clients = listCreate();\n    server.clients_to_close = listCreate();\n    server.slaves = listCreate();\n    server.monitors = listCreate();\n    server.slaveseldb = -1; /* Force to emit the first SELECT command. */\n    server.unblocked_clients = listCreate();\n    server.ready_keys = listCreate();\n\n    createSharedObjects();\n    adjustOpenFilesLimit();\n    server.el = aeCreateEventLoop(server.maxclients+REDIS_EVENTLOOP_FDSET_INCR);\n    server.db = zmalloc(sizeof(redisDb)*server.dbnum);\n\n    /* Open the TCP listening socket for the user commands. */\n    if (server.port != 0 &&\n        listenToPort(server.port,server.ipfd,&server.ipfd_count) == REDIS_ERR)\n        exit(1);\n\n    /* Open the listening Unix domain socket. */\n    if (server.unixsocket != NULL) {\n        unlink(server.unixsocket); /* don't care if this fails */\n        server.sofd = anetUnixServer(server.neterr,server.unixsocket,\n            server.unixsocketperm, server.tcp_backlog);\n        if (server.sofd == ANET_ERR) {\n            redisLog(REDIS_WARNING, \"Opening socket: %s\", server.neterr);\n            exit(1);\n        }\n        anetNonBlock(NULL,server.sofd);\n    }\n\n    /* Abort if there are no listening sockets at all. */\n    if (server.ipfd_count == 0 && server.sofd < 0) {\n        redisLog(REDIS_WARNING, \"Configured to not listen anywhere, exiting.\");\n        exit(1);\n    }\n\n    /* Create the Redis databases, and initialize other internal state. */\n    for (j = 0; j < server.dbnum; j++) {\n        server.db[j].dict = dictCreate(&dbDictType,NULL);\n        server.db[j].expires = dictCreate(&keyptrDictType,NULL);\n        server.db[j].blocking_keys = dictCreate(&keylistDictType,NULL);\n        server.db[j].ready_keys = dictCreate(&setDictType,NULL);\n        server.db[j].watched_keys = dictCreate(&keylistDictType,NULL);\n        server.db[j].id = j;\n        server.db[j].avg_ttl = 0;\n        for (i = 0; i < HASH_SLOTS_SIZE; i ++) {\n            server.db[j].hash_slots[i] = dictCreate(&hashSlotType, NULL);\n        }\n        server.db[j].tagged_keys = zslCreate();\n    }\n    server.pubsub_channels = dictCreate(&keylistDictType,NULL);\n    server.pubsub_patterns = listCreate();\n    listSetFreeMethod(server.pubsub_patterns,freePubsubPattern);\n    listSetMatchMethod(server.pubsub_patterns,listMatchPubsubPattern);\n    server.cronloops = 0;\n    server.rdb_child_pid = -1;\n    server.aof_child_pid = -1;\n    server.rdb_child_type = REDIS_RDB_CHILD_TYPE_NONE;\n    aofRewriteBufferReset();\n    server.aof_buf = sdsempty();\n    server.lastsave = time(NULL); /* At startup we consider the DB saved. */\n    server.lastbgsave_try = 0;    /* At startup we never tried to BGSAVE. */\n    server.rdb_save_time_last = -1;\n    server.rdb_save_time_start = -1;\n    server.dirty = 0;\n    resetServerStats();\n    /* A few stats we don't want to reset: server startup time, and peak mem. */\n    server.stat_starttime = time(NULL);\n    server.stat_peak_memory = 0;\n    server.resident_set_size = 0;\n    server.lastbgsave_status = REDIS_OK;\n    server.aof_last_write_status = REDIS_OK;\n    server.aof_last_write_errno = 0;\n    server.repl_good_slaves_count = 0;\n    updateCachedTime();\n\n    /* Create the serverCron() time event, that's our main way to process\n     * background operations. */\n    if(aeCreateTimeEvent(server.el, 1, serverCron, NULL, NULL) == AE_ERR) {\n        redisPanic(\"Can't create the serverCron time event.\");\n        exit(1);\n    }\n\n    /* Create an event handler for accepting new connections in TCP and Unix\n     * domain sockets. */\n    for (j = 0; j < server.ipfd_count; j++) {\n        if (aeCreateFileEvent(server.el, server.ipfd[j], AE_READABLE,\n            acceptTcpHandler,NULL) == AE_ERR)\n            {\n                redisPanic(\n                    \"Unrecoverable error creating server.ipfd file event.\");\n            }\n    }\n    if (server.sofd > 0 && aeCreateFileEvent(server.el,server.sofd,AE_READABLE,\n        acceptUnixHandler,NULL) == AE_ERR) redisPanic(\"Unrecoverable error creating server.sofd file event.\");\n\n    /* Open the AOF file if needed. */\n    if (server.aof_state == REDIS_AOF_ON) {\n        server.aof_fd = open(server.aof_filename,\n                               O_WRONLY|O_APPEND|O_CREAT,0644);\n        if (server.aof_fd == -1) {\n            redisLog(REDIS_WARNING, \"Can't open the append-only file: %s\",\n                strerror(errno));\n            exit(1);\n        }\n    }\n\n    /* 32 bit instances are limited to 4GB of address space, so if there is\n     * no explicit limit in the user provided configuration we set a limit\n     * at 3 GB using maxmemory with 'noeviction' policy'. This avoids\n     * useless crashes of the Redis instance for out of memory. */\n    if (server.arch_bits == 32 && server.maxmemory == 0) {\n        redisLog(REDIS_WARNING,\"Warning: 32 bit instance detected but no memory limit set. Setting 3 GB maxmemory limit with 'noeviction' policy now.\");\n        server.maxmemory = 3072LL*(1024*1024); /* 3 GB */\n        server.maxmemory_policy = REDIS_MAXMEMORY_NO_EVICTION;\n    }\n\n    replicationScriptCacheInit();\n    scriptingInit();\n    slowlogInit();\n    latencyMonitorInit();\n    bioInit();\n}\n\n/* Populates the Redis Command Table starting from the hard coded list\n * we have on top of redis.c file. */\nvoid populateCommandTable(void) {\n    int j;\n    int numcommands = sizeof(redisCommandTable)/sizeof(struct redisCommand);\n\n    for (j = 0; j < numcommands; j++) {\n        struct redisCommand *c = redisCommandTable+j;\n        char *f = c->sflags;\n        int retval1, retval2;\n\n        while(*f != '\\0') {\n            switch(*f) {\n            case 'w': c->flags |= REDIS_CMD_WRITE; break;\n            case 'r': c->flags |= REDIS_CMD_READONLY; break;\n            case 'm': c->flags |= REDIS_CMD_DENYOOM; break;\n            case 'a': c->flags |= REDIS_CMD_ADMIN; break;\n            case 'p': c->flags |= REDIS_CMD_PUBSUB; break;\n            case 's': c->flags |= REDIS_CMD_NOSCRIPT; break;\n            case 'R': c->flags |= REDIS_CMD_RANDOM; break;\n            case 'S': c->flags |= REDIS_CMD_SORT_FOR_SCRIPT; break;\n            case 'l': c->flags |= REDIS_CMD_LOADING; break;\n            case 't': c->flags |= REDIS_CMD_STALE; break;\n            case 'M': c->flags |= REDIS_CMD_SKIP_MONITOR; break;\n            case 'F': c->flags |= REDIS_CMD_FAST; break;\n            default: redisPanic(\"Unsupported command flag\"); break;\n            }\n            f++;\n        }\n\n        retval1 = dictAdd(server.commands, sdsnew(c->name), c);\n        /* Populate an additional dictionary that will be unaffected\n         * by rename-command statements in redis.conf. */\n        retval2 = dictAdd(server.orig_commands, sdsnew(c->name), c);\n        redisAssert(retval1 == DICT_OK && retval2 == DICT_OK);\n    }\n}\n\nvoid resetCommandTableStats(void) {\n    int numcommands = sizeof(redisCommandTable)/sizeof(struct redisCommand);\n    int j;\n\n    for (j = 0; j < numcommands; j++) {\n        struct redisCommand *c = redisCommandTable+j;\n\n        c->microseconds = 0;\n        c->calls = 0;\n    }\n}\n\n/* ========================== Redis OP Array API ============================ */\n\nvoid redisOpArrayInit(redisOpArray *oa) {\n    oa->ops = NULL;\n    oa->numops = 0;\n}\n\nint redisOpArrayAppend(redisOpArray *oa, struct redisCommand *cmd, int dbid,\n                       robj **argv, int argc, int target)\n{\n    redisOp *op;\n\n    oa->ops = zrealloc(oa->ops,sizeof(redisOp)*(oa->numops+1));\n    op = oa->ops+oa->numops;\n    op->cmd = cmd;\n    op->dbid = dbid;\n    op->argv = argv;\n    op->argc = argc;\n    op->target = target;\n    oa->numops++;\n    return oa->numops;\n}\n\nvoid redisOpArrayFree(redisOpArray *oa) {\n    while(oa->numops) {\n        int j;\n        redisOp *op;\n\n        oa->numops--;\n        op = oa->ops+oa->numops;\n        for (j = 0; j < op->argc; j++)\n            decrRefCount(op->argv[j]);\n        zfree(op->argv);\n    }\n    zfree(oa->ops);\n}\n\n/* ====================== Commands lookup and execution ===================== */\n\nstruct redisCommand *lookupCommand(sds name) {\n    return dictFetchValue(server.commands, name);\n}\n\nstruct redisCommand *lookupCommandByCString(char *s) {\n    struct redisCommand *cmd;\n    sds name = sdsnew(s);\n\n    cmd = dictFetchValue(server.commands, name);\n    sdsfree(name);\n    return cmd;\n}\n\n/* Lookup the command in the current table, if not found also check in\n * the original table containing the original command names unaffected by\n * redis.conf rename-command statement.\n *\n * This is used by functions rewriting the argument vector such as\n * rewriteClientCommandVector() in order to set client->cmd pointer\n * correctly even if the command was renamed. */\nstruct redisCommand *lookupCommandOrOriginal(sds name) {\n    struct redisCommand *cmd = dictFetchValue(server.commands, name);\n\n    if (!cmd) cmd = dictFetchValue(server.orig_commands,name);\n    return cmd;\n}\n\n/* Propagate the specified command (in the context of the specified database id)\n * to AOF and Slaves.\n *\n * flags are an xor between:\n * + REDIS_PROPAGATE_NONE (no propagation of command at all)\n * + REDIS_PROPAGATE_AOF (propagate into the AOF file if is enabled)\n * + REDIS_PROPAGATE_REPL (propagate into the replication link)\n */\nvoid propagate(struct redisCommand *cmd, int dbid, robj **argv, int argc,\n               int flags)\n{\n    if (server.aof_state != REDIS_AOF_OFF && flags & REDIS_PROPAGATE_AOF)\n        feedAppendOnlyFile(cmd,dbid,argv,argc);\n    if (flags & REDIS_PROPAGATE_REPL)\n        replicationFeedSlaves(server.slaves,dbid,argv,argc);\n}\n\n/* Used inside commands to schedule the propagation of additional commands\n * after the current command is propagated to AOF / Replication. */\nvoid alsoPropagate(struct redisCommand *cmd, int dbid, robj **argv, int argc,\n                   int target)\n{\n    redisOpArrayAppend(&server.also_propagate,cmd,dbid,argv,argc,target);\n}\n\n/* It is possible to call the function forceCommandPropagation() inside a\n * Redis command implementation in order to to force the propagation of a\n * specific command execution into AOF / Replication. */\nvoid forceCommandPropagation(redisClient *c, int flags) {\n    if (flags & REDIS_PROPAGATE_REPL) c->flags |= REDIS_FORCE_REPL;\n    if (flags & REDIS_PROPAGATE_AOF) c->flags |= REDIS_FORCE_AOF;\n}\n\n/* Call() is the core of Redis execution of a command */\nvoid call(redisClient *c, int flags) {\n    long long dirty, start, duration;\n    int client_old_flags = c->flags;\n\n    /* Sent the command to clients in MONITOR mode, only if the commands are\n     * not generated from reading an AOF. */\n    if (listLength(server.monitors) &&\n        !server.loading &&\n        !(c->cmd->flags & (REDIS_CMD_SKIP_MONITOR|REDIS_CMD_ADMIN)))\n    {\n        replicationFeedMonitors(c,server.monitors,c->db->id,c->argv,c->argc);\n    }\n\n    /* Call the command. */\n    c->flags &= ~(REDIS_FORCE_AOF|REDIS_FORCE_REPL);\n    redisOpArrayInit(&server.also_propagate);\n    dirty = server.dirty;\n    start = ustime();\n    c->cmd->proc(c);\n    duration = ustime()-start;\n    dirty = server.dirty-dirty;\n    if (dirty < 0) dirty = 0;\n\n    /* When EVAL is called loading the AOF we don't want commands called\n     * from Lua to go into the slowlog or to populate statistics. */\n    if (server.loading && c->flags & REDIS_LUA_CLIENT)\n        flags &= ~(REDIS_CALL_SLOWLOG | REDIS_CALL_STATS);\n\n    /* If the caller is Lua, we want to force the EVAL caller to propagate\n     * the script if the command flag or client flag are forcing the\n     * propagation. */\n    if (c->flags & REDIS_LUA_CLIENT && server.lua_caller) {\n        if (c->flags & REDIS_FORCE_REPL)\n            server.lua_caller->flags |= REDIS_FORCE_REPL;\n        if (c->flags & REDIS_FORCE_AOF)\n            server.lua_caller->flags |= REDIS_FORCE_AOF;\n    }\n\n    /* Log the command into the Slow log if needed, and populate the\n     * per-command statistics that we show in INFO commandstats. */\n    if (flags & REDIS_CALL_SLOWLOG && c->cmd->proc != execCommand) {\n        char *latency_event = (c->cmd->flags & REDIS_CMD_FAST) ?\n                              \"fast-command\" : \"command\";\n        latencyAddSampleIfNeeded(latency_event,duration/1000);\n        slowlogPushEntryIfNeeded(c->argv,c->argc,duration);\n    }\n    if (flags & REDIS_CALL_STATS) {\n        c->cmd->microseconds += duration;\n        c->cmd->calls++;\n    }\n\n    /* Propagate the command into the AOF and replication link */\n    if (flags & REDIS_CALL_PROPAGATE) {\n        int flags = REDIS_PROPAGATE_NONE;\n\n        if (c->flags & REDIS_FORCE_REPL) flags |= REDIS_PROPAGATE_REPL;\n        if (c->flags & REDIS_FORCE_AOF) flags |= REDIS_PROPAGATE_AOF;\n        if (dirty)\n            flags |= (REDIS_PROPAGATE_REPL | REDIS_PROPAGATE_AOF);\n        if (flags != REDIS_PROPAGATE_NONE)\n            propagate(c->cmd,c->db->id,c->argv,c->argc,flags);\n    }\n\n    /* Restore the old FORCE_AOF/REPL flags, since call can be executed\n     * recursively. */\n    c->flags &= ~(REDIS_FORCE_AOF|REDIS_FORCE_REPL);\n    c->flags |= client_old_flags & (REDIS_FORCE_AOF|REDIS_FORCE_REPL);\n\n    /* Handle the alsoPropagate() API to handle commands that want to propagate\n     * multiple separated commands. */\n    if (server.also_propagate.numops) {\n        int j;\n        redisOp *rop;\n\n        for (j = 0; j < server.also_propagate.numops; j++) {\n            rop = &server.also_propagate.ops[j];\n            propagate(rop->cmd, rop->dbid, rop->argv, rop->argc, rop->target);\n        }\n        redisOpArrayFree(&server.also_propagate);\n    }\n    server.stat_numcommands++;\n}\n\n/* If this function gets called we already read a whole\n * command, arguments are in the client argv/argc fields.\n * processCommand() execute the command or prepare the\n * server for a bulk read from the client.\n *\n * If 1 is returned the client is still alive and valid and\n * other operations can be performed by the caller. Otherwise\n * if 0 is returned the client was destroyed (i.e. after QUIT). */\nint processCommand(redisClient *c) {\n    /* The QUIT command is handled separately. Normal command procs will\n     * go through checking for replication and QUIT will cause trouble\n     * when FORCE_REPLICATION is enabled and would be implemented in\n     * a regular command proc. */\n    if (!strcasecmp(c->argv[0]->ptr,\"quit\")) {\n        addReply(c,shared.ok);\n        c->flags |= REDIS_CLOSE_AFTER_REPLY;\n        return REDIS_ERR;\n    }\n\n    /* Now lookup the command and check ASAP about trivial error conditions\n     * such as wrong arity, bad command name and so forth. */\n    c->cmd = c->lastcmd = lookupCommand(c->argv[0]->ptr);\n    if (!c->cmd) {\n        flagTransaction(c);\n        addReplyErrorFormat(c,\"unknown command '%s'\",\n            (char*)c->argv[0]->ptr);\n        return REDIS_OK;\n    } else if ((c->cmd->arity > 0 && c->cmd->arity != c->argc) ||\n               (c->argc < -c->cmd->arity)) {\n        flagTransaction(c);\n        addReplyErrorFormat(c,\"wrong number of arguments for '%s' command\",\n            c->cmd->name);\n        return REDIS_OK;\n    }\n\n    /* Check if the user is authenticated */\n    if (server.requirepass && !c->authenticated && c->cmd->proc != authCommand)\n    {\n        flagTransaction(c);\n        addReply(c,shared.noautherr);\n        return REDIS_OK;\n    }\n\n    /* Handle the maxmemory directive.\n     *\n     * First we try to free some memory if possible (if there are volatile\n     * keys in the dataset). If there are not the only thing we can do\n     * is returning an error. */\n    if (server.maxmemory) {\n        int retval = freeMemoryIfNeeded();\n        if ((c->cmd->flags & REDIS_CMD_DENYOOM) && retval == REDIS_ERR) {\n            flagTransaction(c);\n            addReply(c, shared.oomerr);\n            return REDIS_OK;\n        }\n    }\n\n    /* Don't accept write commands if there are problems persisting on disk\n     * and if this is a master instance. */\n    if (((server.stop_writes_on_bgsave_err &&\n          server.saveparamslen > 0 &&\n          server.lastbgsave_status == REDIS_ERR) ||\n          server.aof_last_write_status == REDIS_ERR) &&\n        server.masterhost == NULL &&\n        (c->cmd->flags & REDIS_CMD_WRITE ||\n         c->cmd->proc == pingCommand))\n    {\n        flagTransaction(c);\n        if (server.aof_last_write_status == REDIS_OK)\n            addReply(c, shared.bgsaveerr);\n        else\n            addReplySds(c,\n                sdscatprintf(sdsempty(),\n                \"-MISCONF Errors writing to the AOF file: %s\\r\\n\",\n                strerror(server.aof_last_write_errno)));\n        return REDIS_OK;\n    }\n\n    /* Don't accept write commands if there are not enough good slaves and\n     * user configured the min-slaves-to-write option. */\n    if (server.masterhost == NULL &&\n        server.repl_min_slaves_to_write &&\n        server.repl_min_slaves_max_lag &&\n        c->cmd->flags & REDIS_CMD_WRITE &&\n        server.repl_good_slaves_count < server.repl_min_slaves_to_write)\n    {\n        flagTransaction(c);\n        addReply(c, shared.noreplicaserr);\n        return REDIS_OK;\n    }\n\n    /* Don't accept write commands if this is a read only slave. But\n     * accept write commands if this is our master. */\n    if (server.masterhost && server.repl_slave_ro &&\n        !(c->flags & REDIS_MASTER) &&\n        c->cmd->flags & REDIS_CMD_WRITE)\n    {\n        addReply(c, shared.roslaveerr);\n        return REDIS_OK;\n    }\n\n    /* Only allow SUBSCRIBE and UNSUBSCRIBE in the context of Pub/Sub */\n    if (c->flags & REDIS_PUBSUB &&\n        c->cmd->proc != pingCommand &&\n        c->cmd->proc != subscribeCommand &&\n        c->cmd->proc != unsubscribeCommand &&\n        c->cmd->proc != psubscribeCommand &&\n        c->cmd->proc != punsubscribeCommand) {\n        addReplyError(c,\"only (P)SUBSCRIBE / (P)UNSUBSCRIBE / QUIT allowed in this context\");\n        return REDIS_OK;\n    }\n\n    /* Only allow INFO and SLAVEOF when slave-serve-stale-data is no and\n     * we are a slave with a broken link with master. */\n    if (server.masterhost && server.repl_state != REDIS_REPL_CONNECTED &&\n        server.repl_serve_stale_data == 0 &&\n        !(c->cmd->flags & REDIS_CMD_STALE))\n    {\n        flagTransaction(c);\n        addReply(c, shared.masterdownerr);\n        return REDIS_OK;\n    }\n\n    /* Loading DB? Return an error if the command has not the\n     * REDIS_CMD_LOADING flag. */\n    if (server.loading && !(c->cmd->flags & REDIS_CMD_LOADING)) {\n        addReply(c, shared.loadingerr);\n        return REDIS_OK;\n    }\n\n    /* Lua script too slow? Only allow a limited number of commands. */\n    if (server.lua_timedout &&\n          c->cmd->proc != authCommand &&\n          c->cmd->proc != replconfCommand &&\n        !(c->cmd->proc == shutdownCommand &&\n          c->argc == 2 &&\n          tolower(((char*)c->argv[1]->ptr)[0]) == 'n') &&\n        !(c->cmd->proc == scriptCommand &&\n          c->argc == 2 &&\n          tolower(((char*)c->argv[1]->ptr)[0]) == 'k'))\n    {\n        flagTransaction(c);\n        addReply(c, shared.slowscripterr);\n        return REDIS_OK;\n    }\n\n    /* Exec the command */\n    if (c->flags & REDIS_MULTI &&\n        c->cmd->proc != execCommand && c->cmd->proc != discardCommand &&\n        c->cmd->proc != multiCommand && c->cmd->proc != watchCommand)\n    {\n        queueMultiCommand(c);\n        addReply(c,shared.queued);\n    } else {\n        call(c,REDIS_CALL_FULL);\n        if (listLength(server.ready_keys))\n            handleClientsBlockedOnLists();\n    }\n    return REDIS_OK;\n}\n\n/*================================== Shutdown =============================== */\n\n/* Close listening sockets. Also unlink the unix domain socket if\n * unlink_unix_socket is non-zero. */\nvoid closeListeningSockets(int unlink_unix_socket) {\n    int j;\n\n    for (j = 0; j < server.ipfd_count; j++) close(server.ipfd[j]);\n    if (server.sofd != -1) close(server.sofd);\n    if (unlink_unix_socket && server.unixsocket) {\n        redisLog(REDIS_NOTICE,\"Removing the unix socket file.\");\n        unlink(server.unixsocket); /* don't care if this fails */\n    }\n}\n\nint prepareForShutdown(int flags) {\n    int save = flags & REDIS_SHUTDOWN_SAVE;\n    int nosave = flags & REDIS_SHUTDOWN_NOSAVE;\n\n    redisLog(REDIS_WARNING,\"User requested shutdown...\");\n    /* Kill the saving child if there is a background saving in progress.\n       We want to avoid race conditions, for instance our saving child may\n       overwrite the synchronous saving did by SHUTDOWN. */\n    if (server.rdb_child_pid != -1) {\n        redisLog(REDIS_WARNING,\"There is a child saving an .rdb. Killing it!\");\n        kill(server.rdb_child_pid,SIGUSR1);\n        rdbRemoveTempFile(server.rdb_child_pid);\n    }\n    if (server.aof_state != REDIS_AOF_OFF) {\n        /* Kill the AOF saving child as the AOF we already have may be longer\n         * but contains the full dataset anyway. */\n        if (server.aof_child_pid != -1) {\n            /* If we have AOF enabled but haven't written the AOF yet, don't\n             * shutdown or else the dataset will be lost. */\n            if (server.aof_state == REDIS_AOF_WAIT_REWRITE) {\n                redisLog(REDIS_WARNING, \"Writing initial AOF, can't exit.\");\n                return REDIS_ERR;\n            }\n            redisLog(REDIS_WARNING,\n                \"There is a child rewriting the AOF. Killing it!\");\n            kill(server.aof_child_pid,SIGUSR1);\n        }\n        /* Append only file: fsync() the AOF and exit */\n        redisLog(REDIS_NOTICE,\"Calling fsync() on the AOF file.\");\n        aof_fsync(server.aof_fd);\n    }\n    if ((server.saveparamslen > 0 && !nosave) || save) {\n        redisLog(REDIS_NOTICE,\"Saving the final RDB snapshot before exiting.\");\n        /* Snapshotting. Perform a SYNC SAVE and exit */\n        if (rdbSave(server.rdb_filename) != REDIS_OK) {\n            /* Ooops.. error saving! The best we can do is to continue\n             * operating. Note that if there was a background saving process,\n             * in the next cron() Redis will be notified that the background\n             * saving aborted, handling special stuff like slaves pending for\n             * synchronization... */\n            redisLog(REDIS_WARNING,\"Error trying to save the DB, can't exit.\");\n            return REDIS_ERR;\n        }\n    }\n    if (server.daemonize) {\n        redisLog(REDIS_NOTICE,\"Removing the pid file.\");\n        unlink(server.pidfile);\n    }\n    /* Close the listening sockets. Apparently this allows faster restarts. */\n    closeListeningSockets(1);\n    redisLog(REDIS_WARNING,\"%s is now ready to exit, bye bye...\",\n        server.sentinel_mode ? \"Sentinel\" : \"Redis\");\n    return REDIS_OK;\n}\n\n/*================================== Commands =============================== */\n\n/* Return zero if strings are the same, non-zero if they are not.\n * The comparison is performed in a way that prevents an attacker to obtain\n * information about the nature of the strings just monitoring the execution\n * time of the function.\n *\n * Note that limiting the comparison length to strings up to 512 bytes we\n * can avoid leaking any information about the password length and any\n * possible branch misprediction related leak.\n */\nint time_independent_strcmp(char *a, char *b) {\n    char bufa[REDIS_AUTHPASS_MAX_LEN], bufb[REDIS_AUTHPASS_MAX_LEN];\n    /* The above two strlen perform len(a) + len(b) operations where either\n     * a or b are fixed (our password) length, and the difference is only\n     * relative to the length of the user provided string, so no information\n     * leak is possible in the following two lines of code. */\n    unsigned int alen = strlen(a);\n    unsigned int blen = strlen(b);\n    unsigned int j;\n    int diff = 0;\n\n    /* We can't compare strings longer than our static buffers.\n     * Note that this will never pass the first test in practical circumstances\n     * so there is no info leak. */\n    if (alen > sizeof(bufa) || blen > sizeof(bufb)) return 1;\n\n    memset(bufa,0,sizeof(bufa));        /* Constant time. */\n    memset(bufb,0,sizeof(bufb));        /* Constant time. */\n    /* Again the time of the following two copies is proportional to\n     * len(a) + len(b) so no info is leaked. */\n    memcpy(bufa,a,alen);\n    memcpy(bufb,b,blen);\n\n    /* Always compare all the chars in the two buffers without\n     * conditional expressions. */\n    for (j = 0; j < sizeof(bufa); j++) {\n        diff |= (bufa[j] ^ bufb[j]);\n    }\n    /* Length must be equal as well. */\n    diff |= alen ^ blen;\n    return diff; /* If zero strings are the same. */\n}\n\nvoid authCommand(redisClient *c) {\n    if (!server.requirepass) {\n        addReplyError(c,\"Client sent AUTH, but no password is set\");\n    } else if (!time_independent_strcmp(c->argv[1]->ptr, server.requirepass)) {\n      c->authenticated = 1;\n      addReply(c,shared.ok);\n    } else {\n      c->authenticated = 0;\n      addReplyError(c,\"invalid password\");\n    }\n}\n\n/* The PING command. It works in a different way if the client is in\n * in Pub/Sub mode. */\nvoid pingCommand(redisClient *c) {\n    /* The command takes zero or one arguments. */\n    if (c->argc > 2) {\n        addReplyErrorFormat(c,\"wrong number of arguments for '%s' command\",\n            c->cmd->name);\n        return;\n    }\n\n    if (c->flags & REDIS_PUBSUB) {\n        addReply(c,shared.mbulkhdr[2]);\n        addReplyBulkCBuffer(c,\"pong\",4);\n        if (c->argc == 1)\n            addReplyBulkCBuffer(c,\"\",0);\n        else\n            addReplyBulk(c,c->argv[1]);\n    } else {\n        if (c->argc == 1)\n            addReply(c,shared.pong);\n        else\n            addReplyBulk(c,c->argv[1]);\n    }\n}\n\nvoid echoCommand(redisClient *c) {\n    addReplyBulk(c,c->argv[1]);\n}\n\nvoid timeCommand(redisClient *c) {\n    struct timeval tv;\n\n    /* gettimeofday() can only fail if &tv is a bad address so we\n     * don't check for errors. */\n    gettimeofday(&tv,NULL);\n    addReplyMultiBulkLen(c,2);\n    addReplyBulkLongLong(c,tv.tv_sec);\n    addReplyBulkLongLong(c,tv.tv_usec);\n}\n\n\n/* Helper function for addReplyCommand() to output flags. */\nint addReplyCommandFlag(redisClient *c, struct redisCommand *cmd, int f, char *reply) {\n    if (cmd->flags & f) {\n        addReplyStatus(c, reply);\n        return 1;\n    }\n    return 0;\n}\n\n/* Output the representation of a Redis command. Used by the COMMAND command. */\nvoid addReplyCommand(redisClient *c, struct redisCommand *cmd) {\n    if (!cmd) {\n        addReply(c, shared.nullbulk);\n    } else {\n        /* We are adding: command name, arg count, flags, first, last, offset */\n        addReplyMultiBulkLen(c, 6);\n        addReplyBulkCString(c, cmd->name);\n        addReplyLongLong(c, cmd->arity);\n\n        int flagcount = 0;\n        void *flaglen = addDeferredMultiBulkLength(c);\n        flagcount += addReplyCommandFlag(c,cmd,REDIS_CMD_WRITE, \"write\");\n        flagcount += addReplyCommandFlag(c,cmd,REDIS_CMD_READONLY, \"readonly\");\n        flagcount += addReplyCommandFlag(c,cmd,REDIS_CMD_DENYOOM, \"denyoom\");\n        flagcount += addReplyCommandFlag(c,cmd,REDIS_CMD_ADMIN, \"admin\");\n        flagcount += addReplyCommandFlag(c,cmd,REDIS_CMD_PUBSUB, \"pubsub\");\n        flagcount += addReplyCommandFlag(c,cmd,REDIS_CMD_NOSCRIPT, \"noscript\");\n        flagcount += addReplyCommandFlag(c,cmd,REDIS_CMD_RANDOM, \"random\");\n        flagcount += addReplyCommandFlag(c,cmd,REDIS_CMD_SORT_FOR_SCRIPT,\"sort_for_script\");\n        flagcount += addReplyCommandFlag(c,cmd,REDIS_CMD_LOADING, \"loading\");\n        flagcount += addReplyCommandFlag(c,cmd,REDIS_CMD_STALE, \"stale\");\n        flagcount += addReplyCommandFlag(c,cmd,REDIS_CMD_SKIP_MONITOR, \"skip_monitor\");\n        flagcount += addReplyCommandFlag(c,cmd,REDIS_CMD_FAST, \"fast\");\n        if (cmd->getkeys_proc) {\n            addReplyStatus(c, \"movablekeys\");\n            flagcount += 1;\n        }\n        setDeferredMultiBulkLength(c, flaglen, flagcount);\n\n        addReplyLongLong(c, cmd->firstkey);\n        addReplyLongLong(c, cmd->lastkey);\n        addReplyLongLong(c, cmd->keystep);\n    }\n}\n\n/* COMMAND <subcommand> <args> */\nvoid commandCommand(redisClient *c) {\n    dictIterator *di;\n    dictEntry *de;\n\n    if (c->argc == 1) {\n        addReplyMultiBulkLen(c, dictSize(server.commands));\n        di = dictGetIterator(server.commands);\n        while ((de = dictNext(di)) != NULL) {\n            addReplyCommand(c, dictGetVal(de));\n        }\n        dictReleaseIterator(di);\n    } else if (!strcasecmp(c->argv[1]->ptr, \"info\")) {\n        int i;\n        addReplyMultiBulkLen(c, c->argc-2);\n        for (i = 2; i < c->argc; i++) {\n            addReplyCommand(c, dictFetchValue(server.commands, c->argv[i]->ptr));\n        }\n    } else if (!strcasecmp(c->argv[1]->ptr, \"count\") && c->argc == 2) {\n        addReplyLongLong(c, dictSize(server.commands));\n    } else {\n        addReplyError(c, \"Unknown subcommand or wrong number of arguments.\");\n        return;\n    }\n}\n\n/* Convert an amount of bytes into a human readable string in the form\n * of 100B, 2G, 100M, 4K, and so forth. */\nvoid bytesToHuman(char *s, unsigned long long n) {\n    double d;\n\n    if (n < 1024) {\n        /* Bytes */\n        sprintf(s,\"%lluB\",n);\n        return;\n    } else if (n < (1024*1024)) {\n        d = (double)n/(1024);\n        sprintf(s,\"%.2fK\",d);\n    } else if (n < (1024LL*1024*1024)) {\n        d = (double)n/(1024*1024);\n        sprintf(s,\"%.2fM\",d);\n    } else if (n < (1024LL*1024*1024*1024)) {\n        d = (double)n/(1024LL*1024*1024);\n        sprintf(s,\"%.2fG\",d);\n    } else if (n < (1024LL*1024*1024*1024*1024)) {\n        d = (double)n/(1024LL*1024*1024*1024);\n        sprintf(s,\"%.2fT\",d);\n    } else if (n < (1024LL*1024*1024*1024*1024*1024)) {\n        d = (double)n/(1024LL*1024*1024*1024*1024);\n        sprintf(s,\"%.2fP\",d);\n    } else {\n        /* Let's hope we never need this */\n        sprintf(s,\"%lluB\",n);\n    }\n}\n\n/* Create the string returned by the INFO command. This is decoupled\n * by the INFO command itself as we need to report the same information\n * on memory corruption problems. */\nsds genRedisInfoString(char *section) {\n    sds info = sdsempty();\n    time_t uptime = server.unixtime-server.stat_starttime;\n    int j, numcommands;\n    struct rusage self_ru, c_ru;\n    unsigned long lol, bib;\n    int allsections = 0, defsections = 0;\n    int sections = 0;\n\n    if (section == NULL) section = \"default\";\n    allsections = strcasecmp(section,\"all\") == 0;\n    defsections = strcasecmp(section,\"default\") == 0;\n\n    getrusage(RUSAGE_SELF, &self_ru);\n    getrusage(RUSAGE_CHILDREN, &c_ru);\n    getClientsMaxBuffers(&lol,&bib);\n\n    /* Server */\n    if (allsections || defsections || !strcasecmp(section,\"server\")) {\n        static int call_uname = 1;\n        static struct utsname name;\n        char *mode;\n\n        if (server.sentinel_mode) mode = \"sentinel\";\n        else mode = \"standalone\";\n\n        if (sections++) info = sdscat(info,\"\\r\\n\");\n\n        if (call_uname) {\n            /* Uname can be slow and is always the same output. Cache it. */\n            uname(&name);\n            call_uname = 0;\n        }\n\n        info = sdscatprintf(info,\n            \"# Server\\r\\n\"\n            \"redis_version:%s\\r\\n\"\n            \"redis_git_sha1:%s\\r\\n\"\n            \"redis_git_dirty:%d\\r\\n\"\n            \"redis_build_id:%llx\\r\\n\"\n            \"redis_mode:%s\\r\\n\"\n            \"os:%s %s %s\\r\\n\"\n            \"arch_bits:%d\\r\\n\"\n            \"multiplexing_api:%s\\r\\n\"\n            \"gcc_version:%d.%d.%d\\r\\n\"\n            \"process_id:%ld\\r\\n\"\n            \"run_id:%s\\r\\n\"\n            \"tcp_port:%d\\r\\n\"\n            \"uptime_in_seconds:%jd\\r\\n\"\n            \"uptime_in_days:%jd\\r\\n\"\n            \"hz:%d\\r\\n\"\n            \"lru_clock:%ld\\r\\n\"\n            \"config_file:%s\\r\\n\",\n            REDIS_VERSION,\n            redisGitSHA1(),\n            strtol(redisGitDirty(),NULL,10) > 0,\n            (unsigned long long) redisBuildId(),\n            mode,\n            name.sysname, name.release, name.machine,\n            server.arch_bits,\n            aeGetApiName(),\n#ifdef __GNUC__\n            __GNUC__,__GNUC_MINOR__,__GNUC_PATCHLEVEL__,\n#else\n            0,0,0,\n#endif\n            (long) getpid(),\n            server.runid,\n            server.port,\n            (intmax_t)uptime,\n            (intmax_t)(uptime/(3600*24)),\n            server.hz,\n            (unsigned long) server.lruclock,\n            server.configfile ? server.configfile : \"\");\n    }\n\n    /* Clients */\n    if (allsections || defsections || !strcasecmp(section,\"clients\")) {\n        if (sections++) info = sdscat(info,\"\\r\\n\");\n        info = sdscatprintf(info,\n            \"# Clients\\r\\n\"\n            \"connected_clients:%lu\\r\\n\"\n            \"client_longest_output_list:%lu\\r\\n\"\n            \"client_biggest_input_buf:%lu\\r\\n\"\n            \"blocked_clients:%d\\r\\n\",\n            listLength(server.clients)-listLength(server.slaves),\n            lol, bib,\n            server.bpop_blocked_clients);\n    }\n\n    /* Memory */\n    if (allsections || defsections || !strcasecmp(section,\"memory\")) {\n        char hmem[64];\n        char peak_hmem[64];\n        size_t zmalloc_used = zmalloc_used_memory();\n\n        /* Peak memory is updated from time to time by serverCron() so it\n         * may happen that the instantaneous value is slightly bigger than\n         * the peak value. This may confuse users, so we update the peak\n         * if found smaller than the current memory usage. */\n        if (zmalloc_used > server.stat_peak_memory)\n            server.stat_peak_memory = zmalloc_used;\n\n        bytesToHuman(hmem,zmalloc_used);\n        bytesToHuman(peak_hmem,server.stat_peak_memory);\n        if (sections++) info = sdscat(info,\"\\r\\n\");\n        info = sdscatprintf(info,\n            \"# Memory\\r\\n\"\n            \"used_memory:%zu\\r\\n\"\n            \"used_memory_human:%s\\r\\n\"\n            \"used_memory_rss:%zu\\r\\n\"\n            \"used_memory_peak:%zu\\r\\n\"\n            \"used_memory_peak_human:%s\\r\\n\"\n            \"used_memory_lua:%lld\\r\\n\"\n            \"mem_fragmentation_ratio:%.2f\\r\\n\"\n            \"mem_allocator:%s\\r\\n\",\n            zmalloc_used,\n            hmem,\n            server.resident_set_size,\n            server.stat_peak_memory,\n            peak_hmem,\n            ((long long)lua_gc(server.lua,LUA_GCCOUNT,0))*1024LL,\n            zmalloc_get_fragmentation_ratio(server.resident_set_size),\n            ZMALLOC_LIB\n            );\n    }\n\n    /* Persistence */\n    if (allsections || defsections || !strcasecmp(section,\"persistence\")) {\n        if (sections++) info = sdscat(info,\"\\r\\n\");\n        info = sdscatprintf(info,\n            \"# Persistence\\r\\n\"\n            \"loading:%d\\r\\n\"\n            \"rdb_changes_since_last_save:%lld\\r\\n\"\n            \"rdb_bgsave_in_progress:%d\\r\\n\"\n            \"rdb_last_save_time:%jd\\r\\n\"\n            \"rdb_last_bgsave_status:%s\\r\\n\"\n            \"rdb_last_bgsave_time_sec:%jd\\r\\n\"\n            \"rdb_current_bgsave_time_sec:%jd\\r\\n\"\n            \"aof_enabled:%d\\r\\n\"\n            \"aof_rewrite_in_progress:%d\\r\\n\"\n            \"aof_rewrite_scheduled:%d\\r\\n\"\n            \"aof_last_rewrite_time_sec:%jd\\r\\n\"\n            \"aof_current_rewrite_time_sec:%jd\\r\\n\"\n            \"aof_last_bgrewrite_status:%s\\r\\n\"\n            \"aof_last_write_status:%s\\r\\n\",\n            server.loading,\n            server.dirty,\n            server.rdb_child_pid != -1,\n            (intmax_t)server.lastsave,\n            (server.lastbgsave_status == REDIS_OK) ? \"ok\" : \"err\",\n            (intmax_t)server.rdb_save_time_last,\n            (intmax_t)((server.rdb_child_pid == -1) ?\n                -1 : time(NULL)-server.rdb_save_time_start),\n            server.aof_state != REDIS_AOF_OFF,\n            server.aof_child_pid != -1,\n            server.aof_rewrite_scheduled,\n            (intmax_t)server.aof_rewrite_time_last,\n            (intmax_t)((server.aof_child_pid == -1) ?\n                -1 : time(NULL)-server.aof_rewrite_time_start),\n            (server.aof_lastbgrewrite_status == REDIS_OK) ? \"ok\" : \"err\",\n            (server.aof_last_write_status == REDIS_OK) ? \"ok\" : \"err\");\n\n        if (server.aof_state != REDIS_AOF_OFF) {\n            info = sdscatprintf(info,\n                \"aof_current_size:%lld\\r\\n\"\n                \"aof_base_size:%lld\\r\\n\"\n                \"aof_pending_rewrite:%d\\r\\n\"\n                \"aof_buffer_length:%zu\\r\\n\"\n                \"aof_rewrite_buffer_length:%lu\\r\\n\"\n                \"aof_pending_bio_fsync:%llu\\r\\n\"\n                \"aof_delayed_fsync:%lu\\r\\n\",\n                (long long) server.aof_current_size,\n                (long long) server.aof_rewrite_base_size,\n                server.aof_rewrite_scheduled,\n                sdslen(server.aof_buf),\n                aofRewriteBufferSize(),\n                bioPendingJobsOfType(REDIS_BIO_AOF_FSYNC),\n                server.aof_delayed_fsync);\n        }\n\n        if (server.loading) {\n            double perc;\n            time_t eta, elapsed;\n            off_t remaining_bytes = server.loading_total_bytes-\n                                    server.loading_loaded_bytes;\n\n            perc = ((double)server.loading_loaded_bytes /\n                   (server.loading_total_bytes+1)) * 100;\n\n            elapsed = time(NULL)-server.loading_start_time;\n            if (elapsed == 0) {\n                eta = 1; /* A fake 1 second figure if we don't have\n                            enough info */\n            } else {\n                eta = (elapsed*remaining_bytes)/(server.loading_loaded_bytes+1);\n            }\n\n            info = sdscatprintf(info,\n                \"loading_start_time:%jd\\r\\n\"\n                \"loading_total_bytes:%llu\\r\\n\"\n                \"loading_loaded_bytes:%llu\\r\\n\"\n                \"loading_loaded_perc:%.2f\\r\\n\"\n                \"loading_eta_seconds:%jd\\r\\n\",\n                (intmax_t) server.loading_start_time,\n                (unsigned long long) server.loading_total_bytes,\n                (unsigned long long) server.loading_loaded_bytes,\n                perc,\n                (intmax_t)eta\n            );\n        }\n    }\n\n    /* Stats */\n    if (allsections || defsections || !strcasecmp(section,\"stats\")) {\n        if (sections++) info = sdscat(info,\"\\r\\n\");\n        info = sdscatprintf(info,\n            \"# Stats\\r\\n\"\n            \"total_connections_received:%lld\\r\\n\"\n            \"total_commands_processed:%lld\\r\\n\"\n            \"instantaneous_ops_per_sec:%lld\\r\\n\"\n            \"total_net_input_bytes:%lld\\r\\n\"\n            \"total_net_output_bytes:%lld\\r\\n\"\n            \"instantaneous_input_kbps:%.2f\\r\\n\"\n            \"instantaneous_output_kbps:%.2f\\r\\n\"\n            \"rejected_connections:%lld\\r\\n\"\n            \"sync_full:%lld\\r\\n\"\n            \"sync_partial_ok:%lld\\r\\n\"\n            \"sync_partial_err:%lld\\r\\n\"\n            \"expired_keys:%lld\\r\\n\"\n            \"evicted_keys:%lld\\r\\n\"\n            \"keyspace_hits:%lld\\r\\n\"\n            \"keyspace_misses:%lld\\r\\n\"\n            \"pubsub_channels:%ld\\r\\n\"\n            \"pubsub_patterns:%lu\\r\\n\"\n            \"latest_fork_usec:%lld\\r\\n\",\n            server.stat_numconnections,\n            server.stat_numcommands,\n            getInstantaneousMetric(REDIS_METRIC_COMMAND),\n            server.stat_net_input_bytes,\n            server.stat_net_output_bytes,\n            (float)getInstantaneousMetric(REDIS_METRIC_NET_INPUT)/1024,\n            (float)getInstantaneousMetric(REDIS_METRIC_NET_OUTPUT)/1024,\n            server.stat_rejected_conn,\n            server.stat_sync_full,\n            server.stat_sync_partial_ok,\n            server.stat_sync_partial_err,\n            server.stat_expiredkeys,\n            server.stat_evictedkeys,\n            server.stat_keyspace_hits,\n            server.stat_keyspace_misses,\n            dictSize(server.pubsub_channels),\n            listLength(server.pubsub_patterns),\n            server.stat_fork_time);\n    }\n\n    /* Replication */\n    if (allsections || defsections || !strcasecmp(section,\"replication\")) {\n        if (sections++) info = sdscat(info,\"\\r\\n\");\n        info = sdscatprintf(info,\n            \"# Replication\\r\\n\"\n            \"role:%s\\r\\n\",\n            server.masterhost == NULL ? \"master\" : \"slave\");\n        if (server.masterhost) {\n            long long slave_repl_offset = 1;\n\n            if (server.master)\n                slave_repl_offset = server.master->reploff;\n            else if (server.cached_master)\n                slave_repl_offset = server.cached_master->reploff;\n\n            info = sdscatprintf(info,\n                \"master_host:%s\\r\\n\"\n                \"master_port:%d\\r\\n\"\n                \"master_link_status:%s\\r\\n\"\n                \"master_last_io_seconds_ago:%d\\r\\n\"\n                \"master_sync_in_progress:%d\\r\\n\"\n                \"slave_repl_offset:%lld\\r\\n\"\n                ,server.masterhost,\n                server.masterport,\n                (server.repl_state == REDIS_REPL_CONNECTED) ?\n                    \"up\" : \"down\",\n                server.master ?\n                ((int)(server.unixtime-server.master->lastinteraction)) : -1,\n                server.repl_state == REDIS_REPL_TRANSFER,\n                slave_repl_offset\n            );\n\n            if (server.repl_state == REDIS_REPL_TRANSFER) {\n                info = sdscatprintf(info,\n                    \"master_sync_left_bytes:%lld\\r\\n\"\n                    \"master_sync_last_io_seconds_ago:%d\\r\\n\"\n                    , (long long)\n                        (server.repl_transfer_size - server.repl_transfer_read),\n                    (int)(server.unixtime-server.repl_transfer_lastio)\n                );\n            }\n\n            if (server.repl_state != REDIS_REPL_CONNECTED) {\n                info = sdscatprintf(info,\n                    \"master_link_down_since_seconds:%jd\\r\\n\",\n                    (intmax_t)server.unixtime-server.repl_down_since);\n            }\n            info = sdscatprintf(info,\n                \"slave_priority:%d\\r\\n\"\n                \"slave_read_only:%d\\r\\n\",\n                server.slave_priority,\n                server.repl_slave_ro);\n        }\n\n        info = sdscatprintf(info,\n            \"connected_slaves:%lu\\r\\n\",\n            listLength(server.slaves));\n\n        /* If min-slaves-to-write is active, write the number of slaves\n         * currently considered 'good'. */\n        if (server.repl_min_slaves_to_write &&\n            server.repl_min_slaves_max_lag) {\n            info = sdscatprintf(info,\n                \"min_slaves_good_slaves:%d\\r\\n\",\n                server.repl_good_slaves_count);\n        }\n\n        if (listLength(server.slaves)) {\n            int slaveid = 0;\n            listNode *ln;\n            listIter li;\n\n            listRewind(server.slaves,&li);\n            while((ln = listNext(&li))) {\n                redisClient *slave = listNodeValue(ln);\n                char *state = NULL;\n                char ip[REDIS_IP_STR_LEN];\n                int port;\n                long lag = 0;\n\n                if (anetPeerToString(slave->fd,ip,sizeof(ip),&port) == -1) continue;\n                switch(slave->replstate) {\n                case REDIS_REPL_WAIT_BGSAVE_START:\n                case REDIS_REPL_WAIT_BGSAVE_END:\n                    state = \"wait_bgsave\";\n                    break;\n                case REDIS_REPL_SEND_BULK:\n                    state = \"send_bulk\";\n                    break;\n                case REDIS_REPL_ONLINE:\n                    state = \"online\";\n                    break;\n                }\n                if (state == NULL) continue;\n                if (slave->replstate == REDIS_REPL_ONLINE)\n                    lag = time(NULL) - slave->repl_ack_time;\n\n                info = sdscatprintf(info,\n                    \"slave%d:ip=%s,port=%d,state=%s,\"\n                    \"offset=%lld,lag=%ld\\r\\n\",\n                    slaveid,ip,slave->slave_listening_port,state,\n                    slave->repl_ack_off, lag);\n                slaveid++;\n            }\n        }\n        info = sdscatprintf(info,\n            \"master_repl_offset:%lld\\r\\n\"\n            \"repl_backlog_active:%d\\r\\n\"\n            \"repl_backlog_size:%lld\\r\\n\"\n            \"repl_backlog_first_byte_offset:%lld\\r\\n\"\n            \"repl_backlog_histlen:%lld\\r\\n\",\n            server.master_repl_offset,\n            server.repl_backlog != NULL,\n            server.repl_backlog_size,\n            server.repl_backlog_off,\n            server.repl_backlog_histlen);\n    }\n\n    /* CPU */\n    if (allsections || defsections || !strcasecmp(section,\"cpu\")) {\n        if (sections++) info = sdscat(info,\"\\r\\n\");\n        info = sdscatprintf(info,\n        \"# CPU\\r\\n\"\n        \"used_cpu_sys:%.2f\\r\\n\"\n        \"used_cpu_user:%.2f\\r\\n\"\n        \"used_cpu_sys_children:%.2f\\r\\n\"\n        \"used_cpu_user_children:%.2f\\r\\n\",\n        (float)self_ru.ru_stime.tv_sec+(float)self_ru.ru_stime.tv_usec/1000000,\n        (float)self_ru.ru_utime.tv_sec+(float)self_ru.ru_utime.tv_usec/1000000,\n        (float)c_ru.ru_stime.tv_sec+(float)c_ru.ru_stime.tv_usec/1000000,\n        (float)c_ru.ru_utime.tv_sec+(float)c_ru.ru_utime.tv_usec/1000000);\n    }\n\n    /* cmdtime */\n    if (allsections || !strcasecmp(section,\"commandstats\")) {\n        if (sections++) info = sdscat(info,\"\\r\\n\");\n        info = sdscatprintf(info, \"# Commandstats\\r\\n\");\n        numcommands = sizeof(redisCommandTable)/sizeof(struct redisCommand);\n        for (j = 0; j < numcommands; j++) {\n            struct redisCommand *c = redisCommandTable+j;\n\n            if (!c->calls) continue;\n            info = sdscatprintf(info,\n                \"cmdstat_%s:calls=%lld,usec=%lld,usec_per_call=%.2f\\r\\n\",\n                c->name, c->calls, c->microseconds,\n                (c->calls == 0) ? 0 : ((float)c->microseconds/c->calls));\n        }\n    }\n\n    /* Key space */\n    if (allsections || defsections || !strcasecmp(section,\"keyspace\")) {\n        if (sections++) info = sdscat(info,\"\\r\\n\");\n        info = sdscatprintf(info, \"# Keyspace\\r\\n\");\n        for (j = 0; j < server.dbnum; j++) {\n            long long keys, vkeys;\n\n            keys = dictSize(server.db[j].dict);\n            vkeys = dictSize(server.db[j].expires);\n            if (keys || vkeys) {\n                info = sdscatprintf(info,\n                    \"db%d:keys=%lld,expires=%lld,avg_ttl=%lld\\r\\n\",\n                    j, keys, vkeys, server.db[j].avg_ttl);\n            }\n        }\n    }\n    return info;\n}\n\nvoid infoCommand(redisClient *c) {\n    char *section = c->argc == 2 ? c->argv[1]->ptr : \"default\";\n\n    if (c->argc > 2) {\n        addReply(c,shared.syntaxerr);\n        return;\n    }\n    sds info = genRedisInfoString(section);\n    addReplySds(c,sdscatprintf(sdsempty(),\"$%lu\\r\\n\",\n        (unsigned long)sdslen(info)));\n    addReplySds(c,info);\n    addReply(c,shared.crlf);\n}\n\nvoid monitorCommand(redisClient *c) {\n    /* ignore MONITOR if already slave or in monitor mode */\n    if (c->flags & REDIS_SLAVE) return;\n\n    c->flags |= (REDIS_SLAVE|REDIS_MONITOR);\n    listAddNodeTail(server.monitors,c);\n    addReply(c,shared.ok);\n}\n\n/* ============================ Maxmemory directive  ======================== */\n\n/* This function gets called when 'maxmemory' is set on the config file to limit\n * the max memory used by the server, before processing a command.\n *\n * The goal of the function is to free enough memory to keep Redis under the\n * configured memory limit.\n *\n * The function starts calculating how many bytes should be freed to keep\n * Redis under the limit, and enters a loop selecting the best keys to\n * evict accordingly to the configured policy.\n *\n * If all the bytes needed to return back under the limit were freed the\n * function returns REDIS_OK, otherwise REDIS_ERR is returned, and the caller\n * should block the execution of commands that will result in more memory\n * used by the server.\n */\nint freeMemoryIfNeeded(void) {\n    size_t mem_used, mem_tofree, mem_freed;\n    int slaves = listLength(server.slaves);\n    mstime_t latency;\n\n    /* Remove the size of slaves output buffers and AOF buffer from the\n     * count of used memory. */\n    mem_used = zmalloc_used_memory();\n    if (slaves) {\n        listIter li;\n        listNode *ln;\n\n        listRewind(server.slaves,&li);\n        while((ln = listNext(&li))) {\n            redisClient *slave = listNodeValue(ln);\n            unsigned long obuf_bytes = getClientOutputBufferMemoryUsage(slave);\n            if (obuf_bytes > mem_used)\n                mem_used = 0;\n            else\n                mem_used -= obuf_bytes;\n        }\n    }\n    if (server.aof_state != REDIS_AOF_OFF) {\n        mem_used -= sdslen(server.aof_buf);\n        mem_used -= aofRewriteBufferSize();\n    }\n\n    /* Check if we are over the memory limit. */\n    if (mem_used <= server.maxmemory) return REDIS_OK;\n\n    if (server.maxmemory_policy == REDIS_MAXMEMORY_NO_EVICTION)\n        return REDIS_ERR; /* We need to free memory, but policy forbids. */\n\n    /* Compute how much memory we need to free. */\n    mem_tofree = mem_used - server.maxmemory;\n    mem_freed = 0;\n    latencyStartMonitor(latency);\n    while (mem_freed < mem_tofree) {\n        int j, k, keys_freed = 0;\n\n        for (j = 0; j < server.dbnum; j++) {\n            long bestval = 0; /* just to prevent warning */\n            sds bestkey = NULL;\n            struct dictEntry *de;\n            redisDb *db = server.db+j;\n            dict *dict;\n\n            if (server.maxmemory_policy == REDIS_MAXMEMORY_ALLKEYS_LRU ||\n                server.maxmemory_policy == REDIS_MAXMEMORY_ALLKEYS_RANDOM)\n            {\n                dict = server.db[j].dict;\n            } else {\n                dict = server.db[j].expires;\n            }\n            if (dictSize(dict) == 0) continue;\n\n            /* volatile-random and allkeys-random policy */\n            if (server.maxmemory_policy == REDIS_MAXMEMORY_ALLKEYS_RANDOM ||\n                server.maxmemory_policy == REDIS_MAXMEMORY_VOLATILE_RANDOM)\n            {\n                de = dictGetRandomKey(dict);\n                bestkey = dictGetKey(de);\n            }\n\n            /* volatile-lru and allkeys-lru policy */\n            else if (server.maxmemory_policy == REDIS_MAXMEMORY_ALLKEYS_LRU ||\n                server.maxmemory_policy == REDIS_MAXMEMORY_VOLATILE_LRU)\n            {\n                for (k = 0; k < server.maxmemory_samples; k++) {\n                    sds thiskey;\n                    long thisval;\n                    robj *o;\n\n                    de = dictGetRandomKey(dict);\n                    thiskey = dictGetKey(de);\n                    /* When policy is volatile-lru we need an additional lookup\n                     * to locate the real key, as dict is set to db->expires. */\n                    if (server.maxmemory_policy == REDIS_MAXMEMORY_VOLATILE_LRU)\n                        de = dictFind(db->dict, thiskey);\n                    o = dictGetVal(de);\n                    thisval = estimateObjectIdleTime(o);\n\n                    /* Higher idle time is better candidate for deletion */\n                    if (bestkey == NULL || thisval > bestval) {\n                        bestkey = thiskey;\n                        bestval = thisval;\n                    }\n                }\n            }\n\n            /* volatile-ttl */\n            else if (server.maxmemory_policy == REDIS_MAXMEMORY_VOLATILE_TTL) {\n                for (k = 0; k < server.maxmemory_samples; k++) {\n                    sds thiskey;\n                    long thisval;\n\n                    de = dictGetRandomKey(dict);\n                    thiskey = dictGetKey(de);\n                    thisval = (long) dictGetVal(de);\n\n                    /* Expire sooner (minor expire unix timestamp) is better\n                     * candidate for deletion */\n                    if (bestkey == NULL || thisval < bestval) {\n                        bestkey = thiskey;\n                        bestval = thisval;\n                    }\n                }\n            }\n\n            /* Finally remove the selected key. */\n            if (bestkey) {\n                long long delta;\n\n                robj *keyobj = createStringObject(bestkey,sdslen(bestkey));\n                propagateExpire(db,keyobj);\n                /* We compute the amount of memory freed by dbDelete() alone.\n                 * It is possible that actually the memory needed to propagate\n                 * the DEL in AOF and replication link is greater than the one\n                 * we are freeing removing the key, but we can't account for\n                 * that otherwise we would never exit the loop.\n                 *\n                 * AOF and Output buffer memory will be freed eventually so\n                 * we only care about memory used by the key space. */\n                delta = (long long) zmalloc_used_memory();\n                dbDelete(db,keyobj);\n                delta -= (long long) zmalloc_used_memory();\n                mem_freed += delta;\n                server.stat_evictedkeys++;\n                notifyKeyspaceEvent(REDIS_NOTIFY_EVICTED, \"evicted\",\n                    keyobj, db->id);\n                decrRefCount(keyobj);\n                keys_freed++;\n\n                /* When the memory to free starts to be big enough, we may\n                 * start spending so much time here that is impossible to\n                 * deliver data to the slaves fast enough, so we force the\n                 * transmission here inside the loop. */\n                if (slaves) flushSlavesOutputBuffers();\n            }\n        }\n        if (!keys_freed) {\n            latencyEndMonitor(latency);\n            latencyAddSampleIfNeeded(\"eviction-cycle\",latency);\n            return REDIS_ERR; /* nothing to free... */\n        }\n    }\n    latencyEndMonitor(latency);\n    latencyAddSampleIfNeeded(\"eviction-cycle\",latency);\n    return REDIS_OK;\n}\n\n/* =================================== Main! ================================ */\n\n#ifdef __linux__\nint linuxOvercommitMemoryValue(void) {\n    FILE *fp = fopen(\"/proc/sys/vm/overcommit_memory\",\"r\");\n    char buf[64];\n\n    if (!fp) return -1;\n    if (fgets(buf,64,fp) == NULL) {\n        fclose(fp);\n        return -1;\n    }\n    fclose(fp);\n\n    return atoi(buf);\n}\n\nvoid linuxMemoryWarnings(void) {\n    if (linuxOvercommitMemoryValue() == 0) {\n        redisLog(REDIS_WARNING,\"WARNING overcommit_memory is set to 0! Background save may fail under low memory condition. To fix this issue add 'vm.overcommit_memory = 1' to /etc/sysctl.conf and then reboot or run the command 'sysctl vm.overcommit_memory=1' for this to take effect.\");\n    }\n    if (THPIsEnabled()) {\n        redisLog(REDIS_WARNING,\"WARNING you have Transparent Huge Pages (THP) support enabled in your kernel. This will create latency and memory usage issues with Redis. To fix this issue run the command 'echo never > /sys/kernel/mm/transparent_hugepage/enabled' as root, and add it to your /etc/rc.local in order to retain the setting after a reboot. Redis must be restarted after THP is disabled.\");\n    }\n}\n#endif /* __linux__ */\n\nvoid createPidFile(void) {\n    /* Try to write the pid file in a best-effort way. */\n    FILE *fp = fopen(server.pidfile,\"w\");\n    if (fp) {\n        fprintf(fp,\"%d\\n\",(int)getpid());\n        fclose(fp);\n    }\n}\n\nvoid daemonize(void) {\n    int fd;\n\n    if (fork() != 0) exit(0); /* parent exits */\n    setsid(); /* create a new session */\n\n    /* Every output goes to /dev/null. If Redis is daemonized but\n     * the 'logfile' is set to 'stdout' in the configuration file\n     * it will not log at all. */\n    if ((fd = open(\"/dev/null\", O_RDWR, 0)) != -1) {\n        dup2(fd, STDIN_FILENO);\n        dup2(fd, STDOUT_FILENO);\n        dup2(fd, STDERR_FILENO);\n        if (fd > STDERR_FILENO) close(fd);\n    }\n}\n\nvoid version(void) {\n    printf(\"Redis server v=%s sha=%s:%d malloc=%s bits=%d build=%llx\\n\",\n        REDIS_VERSION,\n        redisGitSHA1(),\n        atoi(redisGitDirty()) > 0,\n        ZMALLOC_LIB,\n        sizeof(long) == 4 ? 32 : 64,\n        (unsigned long long) redisBuildId());\n    exit(0);\n}\n\nvoid usage(void) {\n    fprintf(stderr,\"Usage: ./redis-server [/path/to/redis.conf] [options]\\n\");\n    fprintf(stderr,\"       ./redis-server - (read config from stdin)\\n\");\n    fprintf(stderr,\"       ./redis-server -v or --version\\n\");\n    fprintf(stderr,\"       ./redis-server -h or --help\\n\");\n    fprintf(stderr,\"       ./redis-server --test-memory <megabytes>\\n\\n\");\n    fprintf(stderr,\"Examples:\\n\");\n    fprintf(stderr,\"       ./redis-server (run the server with default conf)\\n\");\n    fprintf(stderr,\"       ./redis-server /etc/redis/6379.conf\\n\");\n    fprintf(stderr,\"       ./redis-server --port 7777\\n\");\n    fprintf(stderr,\"       ./redis-server --port 7777 --slaveof 127.0.0.1 8888\\n\");\n    fprintf(stderr,\"       ./redis-server /etc/myredis.conf --loglevel verbose\\n\\n\");\n    fprintf(stderr,\"Sentinel mode:\\n\");\n    fprintf(stderr,\"       ./redis-server /etc/sentinel.conf --sentinel\\n\");\n    exit(1);\n}\n\nvoid redisAsciiArt(void) {\n#include \"asciilogo.h\"\n    char *buf = zmalloc(1024*16);\n    char *mode = \"stand alone\";\n\n    if (server.sentinel_mode) mode = \"sentinel\";\n\n    if (server.syslog_enabled) {\n        redisLog(REDIS_NOTICE,\n            \"Redis %s (%s/%d) %s bit, %s mode, port %d, pid %ld ready to start.\",\n            REDIS_VERSION,\n            redisGitSHA1(),\n            strtol(redisGitDirty(),NULL,10) > 0,\n            (sizeof(long) == 8) ? \"64\" : \"32\",\n            mode, server.port,\n            (long) getpid()\n        );\n    } else {\n        snprintf(buf,1024*16,ascii_logo,\n            REDIS_VERSION,\n            redisGitSHA1(),\n            strtol(redisGitDirty(),NULL,10) > 0,\n            (sizeof(long) == 8) ? \"64\" : \"32\",\n            mode, server.port,\n            (long) getpid()\n        );\n        redisLogRaw(REDIS_NOTICE|REDIS_LOG_RAW,buf);\n    }\n    zfree(buf);\n}\n\nstatic void sigShutdownHandler(int sig) {\n    char *msg;\n\n    switch (sig) {\n    case SIGINT:\n        msg = \"Received SIGINT scheduling shutdown...\";\n        break;\n    case SIGTERM:\n        msg = \"Received SIGTERM scheduling shutdown...\";\n        break;\n    default:\n        msg = \"Received shutdown signal, scheduling shutdown...\";\n    };\n\n    /* SIGINT is often delivered via Ctrl+C in an interactive session.\n     * If we receive the signal the second time, we interpret this as\n     * the user really wanting to quit ASAP without waiting to persist\n     * on disk. */\n    if (server.shutdown_asap && sig == SIGINT) {\n        redisLogFromHandler(REDIS_WARNING, \"You insist... exiting now.\");\n        rdbRemoveTempFile(getpid());\n        exit(1); /* Exit with an error since this was not a clean shutdown. */\n    } else if (server.loading) {\n        exit(0);\n    }\n\n    redisLogFromHandler(REDIS_WARNING, msg);\n    server.shutdown_asap = 1;\n}\n\nvoid setupSignalHandlers(void) {\n    struct sigaction act;\n\n    /* When the SA_SIGINFO flag is set in sa_flags then sa_sigaction is used.\n     * Otherwise, sa_handler is used. */\n    sigemptyset(&act.sa_mask);\n    act.sa_flags = 0;\n    act.sa_handler = sigShutdownHandler;\n    sigaction(SIGTERM, &act, NULL);\n    sigaction(SIGINT, &act, NULL);\n\n#ifdef HAVE_BACKTRACE\n    sigemptyset(&act.sa_mask);\n    act.sa_flags = SA_NODEFER | SA_RESETHAND | SA_SIGINFO;\n    act.sa_sigaction = sigsegvHandler;\n    sigaction(SIGSEGV, &act, NULL);\n    sigaction(SIGBUS, &act, NULL);\n    sigaction(SIGFPE, &act, NULL);\n    sigaction(SIGILL, &act, NULL);\n#endif\n    return;\n}\n\nvoid memtest(size_t megabytes, int passes);\n\n/* Returns 1 if there is --sentinel among the arguments or if\n * argv[0] is exactly \"redis-sentinel\". */\nint checkForSentinelMode(int argc, char **argv) {\n    int j;\n\n    if (strstr(argv[0],\"redis-sentinel\") != NULL) return 1;\n    for (j = 1; j < argc; j++)\n        if (!strcmp(argv[j],\"--sentinel\")) return 1;\n    return 0;\n}\n\n/* Function called at startup to load RDB or AOF file in memory. */\nvoid loadDataFromDisk(void) {\n    long long start = ustime();\n    if (server.aof_state == REDIS_AOF_ON) {\n        if (loadAppendOnlyFile(server.aof_filename) == REDIS_OK)\n            redisLog(REDIS_NOTICE,\"DB loaded from append only file: %.3f seconds\",(float)(ustime()-start)/1000000);\n    } else {\n        if (rdbLoad(server.rdb_filename) == REDIS_OK) {\n            redisLog(REDIS_NOTICE,\"DB loaded from disk: %.3f seconds\",\n                (float)(ustime()-start)/1000000);\n        } else if (errno != ENOENT) {\n            redisLog(REDIS_WARNING,\"Fatal error loading the DB: %s. Exiting.\",strerror(errno));\n            exit(1);\n        }\n    }\n}\n\nvoid redisOutOfMemoryHandler(size_t allocation_size) {\n    redisLog(REDIS_WARNING,\"Out Of Memory allocating %zu bytes!\",\n        allocation_size);\n    redisPanic(\"Redis aborting for OUT OF MEMORY\");\n}\n\nvoid redisSetProcTitle(char *title) {\n#ifdef USE_SETPROCTITLE\n    setproctitle(\"%s %s:%d\",\n        title,\n        server.bindaddr_count ? server.bindaddr[0] : \"*\",\n        server.port);\n#else\n    REDIS_NOTUSED(title);\n#endif\n}\n\nint main(int argc, char **argv) {\n    struct timeval tv;\n\n    /* We need to initialize our libraries, and the server configuration. */\n#ifdef INIT_SETPROCTITLE_REPLACEMENT\n    spt_init(argc, argv);\n#endif\n    setlocale(LC_COLLATE,\"\");\n    zmalloc_enable_thread_safeness();\n    zmalloc_set_oom_handler(redisOutOfMemoryHandler);\n    srand(time(NULL)^getpid());\n    gettimeofday(&tv,NULL);\n    dictSetHashFunctionSeed(tv.tv_sec^tv.tv_usec^getpid());\n    server.sentinel_mode = checkForSentinelMode(argc,argv);\n    initServerConfig();\n\n    /* We need to init sentinel right now as parsing the configuration file\n     * in sentinel mode will have the effect of populating the sentinel\n     * data structures with master nodes to monitor. */\n    if (server.sentinel_mode) {\n        initSentinelConfig();\n        initSentinel();\n    }\n\n    if (argc >= 2) {\n        int j = 1; /* First option to parse in argv[] */\n        sds options = sdsempty();\n        char *configfile = NULL;\n\n        /* Handle special options --help and --version */\n        if (strcmp(argv[1], \"-v\") == 0 ||\n            strcmp(argv[1], \"--version\") == 0) version();\n        if (strcmp(argv[1], \"--help\") == 0 ||\n            strcmp(argv[1], \"-h\") == 0) usage();\n        if (strcmp(argv[1], \"--test-memory\") == 0) {\n            if (argc == 3) {\n                memtest(atoi(argv[2]),50);\n                exit(0);\n            } else {\n                fprintf(stderr,\"Please specify the amount of memory to test in megabytes.\\n\");\n                fprintf(stderr,\"Example: ./redis-server --test-memory 4096\\n\\n\");\n                exit(1);\n            }\n        }\n\n        /* First argument is the config file name? */\n        if (argv[j][0] != '-' || argv[j][1] != '-')\n            configfile = argv[j++];\n        /* All the other options are parsed and conceptually appended to the\n         * configuration file. For instance --port 6380 will generate the\n         * string \"port 6380\\n\" to be parsed after the actual file name\n         * is parsed, if any. */\n        while(j != argc) {\n            if (argv[j][0] == '-' && argv[j][1] == '-') {\n                /* Option name */\n                if (sdslen(options)) options = sdscat(options,\"\\n\");\n                options = sdscat(options,argv[j]+2);\n                options = sdscat(options,\" \");\n            } else {\n                /* Option argument */\n                options = sdscatrepr(options,argv[j],strlen(argv[j]));\n                options = sdscat(options,\" \");\n            }\n            j++;\n        }\n        if (server.sentinel_mode && configfile && *configfile == '-') {\n            redisLog(REDIS_WARNING,\n                \"Sentinel config from STDIN not allowed.\");\n            redisLog(REDIS_WARNING,\n                \"Sentinel needs config file on disk to save state.  Exiting...\");\n            exit(1);\n        }\n        if (configfile) server.configfile = getAbsolutePath(configfile);\n        resetServerSaveParams();\n        loadServerConfig(configfile,options);\n        sdsfree(options);\n    } else {\n        redisLog(REDIS_WARNING, \"Warning: no config file specified, using the default config. In order to specify a config file use %s /path/to/%s.conf\", argv[0], server.sentinel_mode ? \"sentinel\" : \"redis\");\n    }\n    if (server.daemonize) daemonize();\n    initServer();\n    if (server.daemonize) createPidFile();\n    redisSetProcTitle(argv[0]);\n    redisAsciiArt();\n\n    if (!server.sentinel_mode) {\n        /* Things not needed when running in Sentinel mode. */\n        redisLog(REDIS_WARNING,\"Server started, Redis version \" REDIS_VERSION);\n    #ifdef __linux__\n        linuxMemoryWarnings();\n    #endif\n        checkTcpBacklogSettings();\n        loadDataFromDisk();\n        if (server.ipfd_count > 0)\n            redisLog(REDIS_NOTICE,\"The server is now ready to accept connections on port %d\", server.port);\n        if (server.sofd > 0)\n            redisLog(REDIS_NOTICE,\"The server is now ready to accept connections at %s\", server.unixsocket);\n    } else {\n        sentinelIsRunning();\n    }\n\n    /* Warning the user about suspicious maxmemory setting. */\n    if (server.maxmemory > 0 && server.maxmemory < 1024*1024) {\n        redisLog(REDIS_WARNING,\"WARNING: You specified a maxmemory value that is less than 1MB (current value is %llu bytes). Are you sure this is what you really want?\", server.maxmemory);\n    }\n\n    aeSetBeforeSleepProc(server.el,beforeSleep);\n    aeMain(server.el);\n    aeDeleteEventLoop(server.el);\n    return 0;\n}\n\n/* The End */\n"
  },
  {
    "path": "extern/deprecated/redis-2.8.21/src/redis.h",
    "content": "/*\n * Copyright (c) 2009-2012, Salvatore Sanfilippo <antirez at gmail dot com>\n * All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions are met:\n *\n *   * Redistributions of source code must retain the above copyright notice,\n *     this list of conditions and the following disclaimer.\n *   * Redistributions in binary form must reproduce the above copyright\n *     notice, this list of conditions and the following disclaimer in the\n *     documentation and/or other materials provided with the distribution.\n *   * Neither the name of Redis nor the names of its contributors may be used\n *     to endorse or promote products derived from this software without\n *     specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\"\n * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\n * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE\n * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR\n * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF\n * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS\n * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN\n * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)\n * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE\n * POSSIBILITY OF SUCH DAMAGE.\n */\n\n#ifndef __REDIS_H\n#define __REDIS_H\n\n#include \"fmacros.h\"\n#include \"config.h\"\n#include \"solarisfixes.h\"\n\n#include <stdio.h>\n#include <stdlib.h>\n#include <string.h>\n#include <time.h>\n#include <limits.h>\n#include <unistd.h>\n#include <errno.h>\n#include <inttypes.h>\n#include <pthread.h>\n#include <syslog.h>\n#include <netinet/in.h>\n#include <lua.h>\n#include <signal.h>\n\ntypedef long long mstime_t; /* millisecond time type. */\n\n#include \"ae.h\"      /* Event driven programming library */\n#include \"sds.h\"     /* Dynamic safe strings */\n#include \"dict.h\"    /* Hash tables */\n#include \"adlist.h\"  /* Linked lists */\n#include \"zmalloc.h\" /* total memory usage aware version of malloc/free */\n#include \"anet.h\"    /* Networking the easy way */\n#include \"ziplist.h\" /* Compact list data structure */\n#include \"intset.h\"  /* Compact integer set structure */\n#include \"version.h\" /* Version macro */\n#include \"util.h\"    /* Misc functions useful in many places */\n#include \"latency.h\" /* Latency monitor API */\n#include \"sparkline.h\" /* ASII graphs API */\n\n/* Error codes */\n#define REDIS_OK                0\n#define REDIS_ERR               -1\n\n/* Static server configuration */\n#define REDIS_DEFAULT_HZ        10      /* Time interrupt calls/sec. */\n#define REDIS_MIN_HZ            1\n#define REDIS_MAX_HZ            500\n#define REDIS_SERVERPORT        6379    /* TCP port */\n#define REDIS_TCP_BACKLOG       511     /* TCP listen backlog */\n#define REDIS_MAXIDLETIME       0       /* default client timeout: infinite */\n#define REDIS_DEFAULT_DBNUM     16\n#define REDIS_CONFIGLINE_MAX    1024\n#define REDIS_DBCRON_DBS_PER_CALL 16\n#define REDIS_MAX_WRITE_PER_EVENT (1024*64)\n#define REDIS_SHARED_SELECT_CMDS 10\n#define REDIS_SHARED_INTEGERS 10000\n#define REDIS_SHARED_BULKHDR_LEN 32\n#define REDIS_MAX_LOGMSG_LEN    1024 /* Default maximum length of syslog messages */\n#define REDIS_AOF_REWRITE_PERC  100\n#define REDIS_AOF_REWRITE_MIN_SIZE (64*1024*1024)\n#define REDIS_AOF_REWRITE_ITEMS_PER_CMD 64\n#define REDIS_SLOWLOG_LOG_SLOWER_THAN 10000\n#define REDIS_SLOWLOG_MAX_LEN 128\n#define REDIS_MAX_CLIENTS 10000\n#define REDIS_AUTHPASS_MAX_LEN 512\n#define REDIS_DEFAULT_SLAVE_PRIORITY 100\n#define REDIS_REPL_TIMEOUT 60\n#define REDIS_REPL_PING_SLAVE_PERIOD 10\n#define REDIS_RUN_ID_SIZE 40\n#define REDIS_EOF_MARK_SIZE 40\n#define REDIS_DEFAULT_REPL_BACKLOG_SIZE (1024*1024)    /* 1mb */\n#define REDIS_DEFAULT_REPL_BACKLOG_TIME_LIMIT (60*60)  /* 1 hour */\n#define REDIS_REPL_BACKLOG_MIN_SIZE (1024*16)          /* 16k */\n#define REDIS_BGSAVE_RETRY_DELAY 5 /* Wait a few secs before trying again. */\n#define REDIS_DEFAULT_PID_FILE \"/var/run/redis.pid\"\n#define REDIS_DEFAULT_SYSLOG_IDENT \"redis\"\n#define REDIS_DEFAULT_CLUSTER_CONFIG_FILE \"nodes.conf\"\n#define REDIS_DEFAULT_DAEMONIZE 0\n#define REDIS_DEFAULT_UNIX_SOCKET_PERM 0\n#define REDIS_DEFAULT_TCP_KEEPALIVE 0\n#define REDIS_DEFAULT_LOGFILE \"\"\n#define REDIS_DEFAULT_SYSLOG_ENABLED 0\n#define REDIS_DEFAULT_STOP_WRITES_ON_BGSAVE_ERROR 1\n#define REDIS_DEFAULT_RDB_COMPRESSION 1\n#define REDIS_DEFAULT_RDB_CHECKSUM 1\n#define REDIS_DEFAULT_RDB_FILENAME \"dump.rdb\"\n#define REDIS_DEFAULT_REPL_DISKLESS_SYNC 0\n#define REDIS_DEFAULT_REPL_DISKLESS_SYNC_DELAY 5\n#define REDIS_DEFAULT_SLAVE_SERVE_STALE_DATA 1\n#define REDIS_DEFAULT_SLAVE_READ_ONLY 1\n#define REDIS_DEFAULT_REPL_DISABLE_TCP_NODELAY 0\n#define REDIS_DEFAULT_MAXMEMORY 0\n#define REDIS_DEFAULT_MAXMEMORY_SAMPLES 3\n#define REDIS_DEFAULT_AOF_FILENAME \"appendonly.aof\"\n#define REDIS_DEFAULT_AOF_NO_FSYNC_ON_REWRITE 0\n#define REDIS_DEFAULT_AOF_LOAD_TRUNCATED 1\n#define REDIS_DEFAULT_ACTIVE_REHASHING 1\n#define REDIS_DEFAULT_AOF_REWRITE_INCREMENTAL_FSYNC 1\n#define REDIS_DEFAULT_MIN_SLAVES_TO_WRITE 0\n#define REDIS_DEFAULT_MIN_SLAVES_MAX_LAG 10\n#define REDIS_IP_STR_LEN INET6_ADDRSTRLEN\n#define REDIS_PEER_ID_LEN (REDIS_IP_STR_LEN+32) /* Must be enough for ip:port */\n#define REDIS_BINDADDR_MAX 16\n#define REDIS_MIN_RESERVED_FDS 32\n#define REDIS_DEFAULT_LATENCY_MONITOR_THRESHOLD 0\n\n#define ACTIVE_EXPIRE_CYCLE_LOOKUPS_PER_LOOP 20 /* Loopkups per loop. */\n#define ACTIVE_EXPIRE_CYCLE_FAST_DURATION 1000 /* Microseconds */\n#define ACTIVE_EXPIRE_CYCLE_SLOW_TIME_PERC 25 /* CPU max % for keys collection */\n#define ACTIVE_EXPIRE_CYCLE_SLOW 0\n#define ACTIVE_EXPIRE_CYCLE_FAST 1\n\n/* Instantaneous metrics tracking. */\n#define REDIS_METRIC_SAMPLES 16     /* Number of samples per metric. */\n#define REDIS_METRIC_COMMAND 0      /* Number of commands executed. */\n#define REDIS_METRIC_NET_INPUT 1    /* Bytes read to network .*/\n#define REDIS_METRIC_NET_OUTPUT 2   /* Bytes written to network. */\n#define REDIS_METRIC_COUNT 3\n\n/* Protocol and I/O related defines */\n#define REDIS_MAX_QUERYBUF_LEN  (1024*1024*1024) /* 1GB max query buffer. */\n#define REDIS_IOBUF_LEN         (1024*16)  /* Generic I/O buffer size */\n#define REDIS_REPLY_CHUNK_BYTES (16*1024) /* 16k output buffer */\n#define REDIS_INLINE_MAX_SIZE   (1024*64) /* Max size of inline reads */\n#define REDIS_MBULK_BIG_ARG     (1024*32)\n#define REDIS_LONGSTR_SIZE      21          /* Bytes needed for long -> str */\n#define REDIS_AOF_AUTOSYNC_BYTES (1024*1024*32) /* fdatasync every 32MB */\n/* When configuring the Redis eventloop, we setup it so that the total number\n * of file descriptors we can handle are server.maxclients + RESERVED_FDS + FDSET_INCR\n * that is our safety margin. */\n#define REDIS_EVENTLOOP_FDSET_INCR (REDIS_MIN_RESERVED_FDS+96)\n\n/* Hash table parameters */\n#define REDIS_HT_MINFILL        10      /* Minimal hash table fill 10% */\n\n/* Command flags. Please check the command table defined in the redis.c file\n * for more information about the meaning of every flag. */\n#define REDIS_CMD_WRITE 1                   /* \"w\" flag */\n#define REDIS_CMD_READONLY 2                /* \"r\" flag */\n#define REDIS_CMD_DENYOOM 4                 /* \"m\" flag */\n#define REDIS_CMD_NOT_USED_1 8              /* no longer used flag */\n#define REDIS_CMD_ADMIN 16                  /* \"a\" flag */\n#define REDIS_CMD_PUBSUB 32                 /* \"p\" flag */\n#define REDIS_CMD_NOSCRIPT  64              /* \"s\" flag */\n#define REDIS_CMD_RANDOM 128                /* \"R\" flag */\n#define REDIS_CMD_SORT_FOR_SCRIPT 256       /* \"S\" flag */\n#define REDIS_CMD_LOADING 512               /* \"l\" flag */\n#define REDIS_CMD_STALE 1024                /* \"t\" flag */\n#define REDIS_CMD_SKIP_MONITOR 2048         /* \"M\" flag */\n#define REDIS_CMD_ASKING 4096               /* \"k\" flag */\n#define REDIS_CMD_FAST 8192                 /* \"F\" flag */\n\n/* Object types */\n#define REDIS_STRING 0\n#define REDIS_LIST 1\n#define REDIS_SET 2\n#define REDIS_ZSET 3\n#define REDIS_HASH 4\n\n/* Objects encoding. Some kind of objects like Strings and Hashes can be\n * internally represented in multiple ways. The 'encoding' field of the object\n * is set to one of this fields for this object. */\n#define REDIS_ENCODING_RAW 0     /* Raw representation */\n#define REDIS_ENCODING_INT 1     /* Encoded as integer */\n#define REDIS_ENCODING_HT 2      /* Encoded as hash table */\n#define REDIS_ENCODING_ZIPMAP 3  /* Encoded as zipmap */\n#define REDIS_ENCODING_LINKEDLIST 4 /* Encoded as regular linked list */\n#define REDIS_ENCODING_ZIPLIST 5 /* Encoded as ziplist */\n#define REDIS_ENCODING_INTSET 6  /* Encoded as intset */\n#define REDIS_ENCODING_SKIPLIST 7  /* Encoded as skiplist */\n\n/* Defines related to the dump file format. To store 32 bits lengths for short\n * keys requires a lot of space, so we check the most significant 2 bits of\n * the first byte to interpreter the length:\n *\n * 00|000000 => if the two MSB are 00 the len is the 6 bits of this byte\n * 01|000000 00000000 =>  01, the len is 14 byes, 6 bits + 8 bits of next byte\n * 10|000000 [32 bit integer] => if it's 10, a full 32 bit len will follow\n * 11|000000 this means: specially encoded object will follow. The six bits\n *           number specify the kind of object that follows.\n *           See the REDIS_RDB_ENC_* defines.\n *\n * Lengths up to 63 are stored using a single byte, most DB keys, and may\n * values, will fit inside. */\n#define REDIS_RDB_6BITLEN 0\n#define REDIS_RDB_14BITLEN 1\n#define REDIS_RDB_32BITLEN 2\n#define REDIS_RDB_ENCVAL 3\n#define REDIS_RDB_LENERR UINT_MAX\n\n/* When a length of a string object stored on disk has the first two bits\n * set, the remaining two bits specify a special encoding for the object\n * accordingly to the following defines: */\n#define REDIS_RDB_ENC_INT8 0        /* 8 bit signed integer */\n#define REDIS_RDB_ENC_INT16 1       /* 16 bit signed integer */\n#define REDIS_RDB_ENC_INT32 2       /* 32 bit signed integer */\n#define REDIS_RDB_ENC_LZF 3         /* string compressed with FASTLZ */\n\n/* AOF states */\n#define REDIS_AOF_OFF 0             /* AOF is off */\n#define REDIS_AOF_ON 1              /* AOF is on */\n#define REDIS_AOF_WAIT_REWRITE 2    /* AOF waits rewrite to start appending */\n\n/* Client flags */\n#define REDIS_SLAVE (1<<0)   /* This client is a slave server */\n#define REDIS_MASTER (1<<1)  /* This client is a master server */\n#define REDIS_MONITOR (1<<2) /* This client is a slave monitor, see MONITOR */\n#define REDIS_MULTI (1<<3)   /* This client is in a MULTI context */\n#define REDIS_BLOCKED (1<<4) /* The client is waiting in a blocking operation */\n#define REDIS_DIRTY_CAS (1<<5) /* Watched keys modified. EXEC will fail. */\n#define REDIS_CLOSE_AFTER_REPLY (1<<6) /* Close after writing entire reply. */\n#define REDIS_UNBLOCKED (1<<7) /* This client was unblocked and is stored in\n                                  server.unblocked_clients */\n#define REDIS_LUA_CLIENT (1<<8) /* This is a non connected client used by Lua */\n#define REDIS_ASKING (1<<9)     /* Client issued the ASKING command */\n#define REDIS_CLOSE_ASAP (1<<10)/* Close this client ASAP */\n#define REDIS_UNIX_SOCKET (1<<11) /* Client connected via Unix domain socket */\n#define REDIS_DIRTY_EXEC (1<<12)  /* EXEC will fail for errors while queueing */\n#define REDIS_MASTER_FORCE_REPLY (1<<13)  /* Queue replies even if is master */\n#define REDIS_FORCE_AOF (1<<14)   /* Force AOF propagation of current cmd. */\n#define REDIS_FORCE_REPL (1<<15)  /* Force replication of current cmd. */\n#define REDIS_PRE_PSYNC (1<<16)   /* Instance don't understand PSYNC. */\n#define REDIS_READONLY (1<<17)    /* Cluster client is in read-only state. */\n#define REDIS_PUBSUB (1<<18)      /* Client is in Pub/Sub mode. */\n\n/* Client request types */\n#define REDIS_REQ_INLINE 1\n#define REDIS_REQ_MULTIBULK 2\n\n/* Client classes for client limits, currently used only for\n * the max-client-output-buffer limit implementation. */\n#define REDIS_CLIENT_TYPE_NORMAL 0 /* Normal req-reply clients + MONITORs */\n#define REDIS_CLIENT_TYPE_SLAVE 1  /* Slaves. */\n#define REDIS_CLIENT_TYPE_PUBSUB 2 /* Clients subscribed to PubSub channels. */\n#define REDIS_CLIENT_TYPE_COUNT 3\n\n/* Slave replication state - from the point of view of the slave. */\n#define REDIS_REPL_NONE 0 /* No active replication */\n#define REDIS_REPL_CONNECT 1 /* Must connect to master */\n#define REDIS_REPL_CONNECTING 2 /* Connecting to master */\n#define REDIS_REPL_RECEIVE_PONG 3 /* Wait for PING reply */\n#define REDIS_REPL_TRANSFER 4 /* Receiving .rdb from master */\n#define REDIS_REPL_CONNECTED 5 /* Connected to master */\n\n/* Slave replication state - from the point of view of the master.\n * In SEND_BULK and ONLINE state the slave receives new updates\n * in its output queue. In the WAIT_BGSAVE state instead the server is waiting\n * to start the next background saving in order to send updates to it. */\n#define REDIS_REPL_WAIT_BGSAVE_START 6 /* We need to produce a new RDB file. */\n#define REDIS_REPL_WAIT_BGSAVE_END 7 /* Waiting RDB file creation to finish. */\n#define REDIS_REPL_SEND_BULK 8 /* Sending RDB file to slave. */\n#define REDIS_REPL_ONLINE 9 /* RDB file transmitted, sending just updates. */\n\n/* Synchronous read timeout - slave side */\n#define REDIS_REPL_SYNCIO_TIMEOUT 5\n\n/* List related stuff */\n#define REDIS_HEAD 0\n#define REDIS_TAIL 1\n\n/* Sort operations */\n#define REDIS_SORT_GET 0\n#define REDIS_SORT_ASC 1\n#define REDIS_SORT_DESC 2\n#define REDIS_SORTKEY_MAX 1024\n\n/* Log levels */\n#define REDIS_DEBUG 0\n#define REDIS_VERBOSE 1\n#define REDIS_NOTICE 2\n#define REDIS_WARNING 3\n#define REDIS_LOG_RAW (1<<10) /* Modifier to log without timestamp */\n#define REDIS_DEFAULT_VERBOSITY REDIS_NOTICE\n\n/* Anti-warning macro... */\n#define REDIS_NOTUSED(V) ((void) V)\n\n#define ZSKIPLIST_MAXLEVEL 32 /* Should be enough for 2^32 elements */\n#define ZSKIPLIST_P 0.25      /* Skiplist P = 1/4 */\n\n/* Append only defines */\n#define AOF_FSYNC_NO 0\n#define AOF_FSYNC_ALWAYS 1\n#define AOF_FSYNC_EVERYSEC 2\n#define REDIS_DEFAULT_AOF_FSYNC AOF_FSYNC_EVERYSEC\n\n/* Zip structure related defaults */\n#define REDIS_HASH_MAX_ZIPLIST_ENTRIES 512\n#define REDIS_HASH_MAX_ZIPLIST_VALUE 64\n#define REDIS_LIST_MAX_ZIPLIST_ENTRIES 512\n#define REDIS_LIST_MAX_ZIPLIST_VALUE 64\n#define REDIS_SET_MAX_INTSET_ENTRIES 512\n#define REDIS_ZSET_MAX_ZIPLIST_ENTRIES 128\n#define REDIS_ZSET_MAX_ZIPLIST_VALUE 64\n\n/* HyperLogLog defines */\n#define REDIS_DEFAULT_HLL_SPARSE_MAX_BYTES 3000\n\n/* Sets operations codes */\n#define REDIS_OP_UNION 0\n#define REDIS_OP_DIFF 1\n#define REDIS_OP_INTER 2\n\n/* Redis maxmemory strategies */\n#define REDIS_MAXMEMORY_VOLATILE_LRU 0\n#define REDIS_MAXMEMORY_VOLATILE_TTL 1\n#define REDIS_MAXMEMORY_VOLATILE_RANDOM 2\n#define REDIS_MAXMEMORY_ALLKEYS_LRU 3\n#define REDIS_MAXMEMORY_ALLKEYS_RANDOM 4\n#define REDIS_MAXMEMORY_NO_EVICTION 5\n#define REDIS_DEFAULT_MAXMEMORY_POLICY REDIS_MAXMEMORY_VOLATILE_LRU\n\n/* Scripting */\n#define REDIS_LUA_TIME_LIMIT 5000 /* milliseconds */\n\n/* Units */\n#define UNIT_SECONDS 0\n#define UNIT_MILLISECONDS 1\n\n/* SHUTDOWN flags */\n#define REDIS_SHUTDOWN_SAVE 1       /* Force SAVE on SHUTDOWN even if no save\n                                       points are configured. */\n#define REDIS_SHUTDOWN_NOSAVE 2     /* Don't SAVE on SHUTDOWN. */\n\n/* Command call flags, see call() function */\n#define REDIS_CALL_NONE 0\n#define REDIS_CALL_SLOWLOG 1\n#define REDIS_CALL_STATS 2\n#define REDIS_CALL_PROPAGATE 4\n#define REDIS_CALL_FULL (REDIS_CALL_SLOWLOG | REDIS_CALL_STATS | REDIS_CALL_PROPAGATE)\n\n/* Command propagation flags, see propagate() function */\n#define REDIS_PROPAGATE_NONE 0\n#define REDIS_PROPAGATE_AOF 1\n#define REDIS_PROPAGATE_REPL 2\n\n/* RDB active child save type. */\n#define REDIS_RDB_CHILD_TYPE_NONE 0\n#define REDIS_RDB_CHILD_TYPE_DISK 1     /* RDB is written to disk. */\n#define REDIS_RDB_CHILD_TYPE_SOCKET 2   /* RDB is written to slave socket. */\n\n/* Keyspace changes notification classes. Every class is associated with a\n * character for configuration purposes. */\n#define REDIS_NOTIFY_KEYSPACE (1<<0)    /* K */\n#define REDIS_NOTIFY_KEYEVENT (1<<1)    /* E */\n#define REDIS_NOTIFY_GENERIC (1<<2)     /* g */\n#define REDIS_NOTIFY_STRING (1<<3)      /* $ */\n#define REDIS_NOTIFY_LIST (1<<4)        /* l */\n#define REDIS_NOTIFY_SET (1<<5)         /* s */\n#define REDIS_NOTIFY_HASH (1<<6)        /* h */\n#define REDIS_NOTIFY_ZSET (1<<7)        /* z */\n#define REDIS_NOTIFY_EXPIRED (1<<8)     /* x */\n#define REDIS_NOTIFY_EVICTED (1<<9)     /* e */\n#define REDIS_NOTIFY_ALL (REDIS_NOTIFY_GENERIC | REDIS_NOTIFY_STRING | REDIS_NOTIFY_LIST | REDIS_NOTIFY_SET | REDIS_NOTIFY_HASH | REDIS_NOTIFY_ZSET | REDIS_NOTIFY_EXPIRED | REDIS_NOTIFY_EVICTED)      /* A */\n\n/* Get the first bind addr or NULL */\n#define REDIS_BIND_ADDR (server.bindaddr_count ? server.bindaddr[0] : NULL)\n\n/* Using the following macro you can run code inside serverCron() with the\n * specified period, specified in milliseconds.\n * The actual resolution depends on server.hz. */\n#define run_with_period(_ms_) if ((_ms_ <= 1000/server.hz) || !(server.cronloops%((_ms_)/(1000/server.hz))))\n\n/* We can print the stacktrace, so our assert is defined this way: */\n#define redisAssertWithInfo(_c,_o,_e) ((_e)?(void)0 : (_redisAssertWithInfo(_c,_o,#_e,__FILE__,__LINE__),_exit(1)))\n#define redisAssert(_e) ((_e)?(void)0 : (_redisAssert(#_e,__FILE__,__LINE__),_exit(1)))\n#define redisPanic(_e) _redisPanic(#_e,__FILE__,__LINE__),_exit(1)\n\n/*-----------------------------------------------------------------------------\n * Data types\n *----------------------------------------------------------------------------*/\n\n/* A redis object, that is a type able to hold a string / list / set */\n\n/* The actual Redis Object */\n#define REDIS_LRU_BITS 24\n#define REDIS_LRU_CLOCK_MAX ((1<<REDIS_LRU_BITS)-1) /* Max value of obj->lru */\n#define REDIS_LRU_CLOCK_RESOLUTION 1 /* LRU clock resolution in seconds */\ntypedef struct redisObject {\n    unsigned type:4;\n    unsigned encoding:4;\n    unsigned lru:REDIS_LRU_BITS; /* lru time (relative to server.lruclock) */\n    int refcount;\n    void *ptr;\n} robj;\n\n/* Macro used to initialize a Redis object allocated on the stack.\n * Note that this macro is taken near the structure definition to make sure\n * we'll update it when the structure is changed, to avoid bugs like\n * bug #85 introduced exactly in this way. */\n#define initStaticStringObject(_var,_ptr) do { \\\n    _var.refcount = 1; \\\n    _var.type = REDIS_STRING; \\\n    _var.encoding = REDIS_ENCODING_RAW; \\\n    _var.ptr = _ptr; \\\n} while(0);\n\nvoid crc32_init();\nuint32_t crc32_checksum(const char *buf, int len);\n\nlong long timeInMilliseconds(void);\n\n#define HASH_SLOTS_MASK 0x000003ff\n#define HASH_SLOTS_SIZE (HASH_SLOTS_MASK + 1)\n\nstruct zskiplist;\n\ntypedef struct redisDb {\n    dict *dict;                 /* The keyspace for this DB */\n    dict *expires;              /* Timeout of keys with a timeout set */\n    dict *blocking_keys;        /* Keys with clients waiting for data (BLPOP) */\n    dict *ready_keys;           /* Blocked keys that received a PUSH */\n    dict *watched_keys;         /* WATCHED keys for MULTI/EXEC CAS */\n    dict *hash_slots[HASH_SLOTS_SIZE];\n    struct zskiplist *tagged_keys;\n    int id;\n    long long avg_ttl;          /* Average TTL, just for stats */\n} redisDb;\n\n/* Client MULTI/EXEC state */\ntypedef struct multiCmd {\n    robj **argv;\n    int argc;\n    struct redisCommand *cmd;\n} multiCmd;\n\ntypedef struct multiState {\n    multiCmd *commands;     /* Array of MULTI commands */\n    int count;              /* Total number of MULTI commands */\n    int minreplicas;        /* MINREPLICAS for synchronous replication */\n    time_t minreplicas_timeout; /* MINREPLICAS timeout as unixtime. */\n} multiState;\n\ntypedef struct blockingState {\n    dict *keys;             /* The keys we are waiting to terminate a blocking\n                             * operation such as BLPOP. Otherwise NULL. */\n    time_t timeout;         /* Blocking operation timeout. If UNIX current time\n                             * is > timeout then the operation timed out. */\n    robj *target;           /* The key that should receive the element,\n                             * for BRPOPLPUSH. */\n} blockingState;\n\n/* The following structure represents a node in the server.ready_keys list,\n * where we accumulate all the keys that had clients blocked with a blocking\n * operation such as B[LR]POP, but received new data in the context of the\n * last executed command.\n *\n * After the execution of every command or script, we run this list to check\n * if as a result we should serve data to clients blocked, unblocking them.\n * Note that server.ready_keys will not have duplicates as there dictionary\n * also called ready_keys in every structure representing a Redis database,\n * where we make sure to remember if a given key was already added in the\n * server.ready_keys list. */\ntypedef struct readyList {\n    redisDb *db;\n    robj *key;\n} readyList;\n\n/* With multiplexing we need to take per-client state.\n * Clients are taken in a linked list. */\ntypedef struct redisClient {\n    uint64_t id;            /* Client incremental unique ID. */\n    int fd;\n    redisDb *db;\n    int dictid;\n    robj *name;             /* As set by CLIENT SETNAME */\n    sds querybuf;\n    size_t querybuf_peak;   /* Recent (100ms or more) peak of querybuf size */\n    int argc;\n    robj **argv;\n    struct redisCommand *cmd, *lastcmd;\n    int reqtype;\n    int multibulklen;       /* number of multi bulk arguments left to read */\n    long bulklen;           /* length of bulk argument in multi bulk request */\n    list *reply;\n    unsigned long reply_bytes; /* Tot bytes of objects in reply list */\n    int sentlen;            /* Amount of bytes already sent in the current\n                               buffer or object being sent. */\n    time_t ctime;           /* Client creation time */\n    time_t lastinteraction; /* time of the last interaction, used for timeout */\n    time_t obuf_soft_limit_reached_time;\n    int flags;              /* REDIS_SLAVE | REDIS_MONITOR | REDIS_MULTI ... */\n    int authenticated;      /* when requirepass is non-NULL */\n    int replstate;          /* replication state if this is a slave */\n    int repl_put_online_on_ack; /* Install slave write handler on ACK. */\n    int repldbfd;           /* replication DB file descriptor */\n    off_t repldboff;        /* replication DB file offset */\n    off_t repldbsize;       /* replication DB file size */\n    sds replpreamble;       /* replication DB preamble. */\n    long long reploff;      /* replication offset if this is our master */\n    long long repl_ack_off; /* replication ack offset, if this is a slave */\n    long long repl_ack_time;/* replication ack time, if this is a slave */\n    char replrunid[REDIS_RUN_ID_SIZE+1]; /* master run id if this is a master */\n    int slave_listening_port; /* As configured with: SLAVECONF listening-port */\n    multiState mstate;      /* MULTI/EXEC state */\n    blockingState bpop;   /* blocking state */\n    list *watched_keys;     /* Keys WATCHED for MULTI/EXEC CAS */\n    dict *pubsub_channels;  /* channels a client is interested in (SUBSCRIBE) */\n    list *pubsub_patterns;  /* patterns a client is interested in (SUBSCRIBE) */\n    sds peerid;             /* Cached peer ID. */\n\n    /* Response buffer */\n    int bufpos;\n    char buf[REDIS_REPLY_CHUNK_BYTES];\n} redisClient;\n\nstruct saveparam {\n    time_t seconds;\n    int changes;\n};\n\nstruct sharedObjectsStruct {\n    robj *crlf, *ok, *err, *emptybulk, *czero, *cone, *cnegone, *pong, *space,\n    *colon, *nullbulk, *nullmultibulk, *queued,\n    *emptymultibulk, *wrongtypeerr, *nokeyerr, *syntaxerr, *sameobjecterr,\n    *outofrangeerr, *noscripterr, *loadingerr, *slowscripterr, *bgsaveerr,\n    *masterdownerr, *roslaveerr, *execaborterr, *noautherr, *noreplicaserr,\n    *oomerr, *plus, *messagebulk, *pmessagebulk, *subscribebulk,\n    *unsubscribebulk, *psubscribebulk, *punsubscribebulk, *del, *rpop, *lpop,\n    *lpush, *emptyscan, *minstring, *maxstring,\n    *select[REDIS_SHARED_SELECT_CMDS],\n    *integers[REDIS_SHARED_INTEGERS],\n    *mbulkhdr[REDIS_SHARED_BULKHDR_LEN], /* \"*<value>\\r\\n\" */\n    *bulkhdr[REDIS_SHARED_BULKHDR_LEN];  /* \"$<value>\\r\\n\" */\n};\n\n/* ZSETs use a specialized version of Skiplists */\ntypedef struct zskiplistNode {\n    robj *obj;\n    double score;\n    struct zskiplistNode *backward;\n    struct zskiplistLevel {\n        struct zskiplistNode *forward;\n        unsigned int span;\n    } level[];\n} zskiplistNode;\n\ntypedef struct zskiplist {\n    struct zskiplistNode *header, *tail;\n    unsigned long length;\n    int level;\n} zskiplist;\n\ntypedef struct zset {\n    dict *dict;\n    zskiplist *zsl;\n} zset;\n\ntypedef struct clientBufferLimitsConfig {\n    unsigned long long hard_limit_bytes;\n    unsigned long long soft_limit_bytes;\n    time_t soft_limit_seconds;\n} clientBufferLimitsConfig;\n\nextern clientBufferLimitsConfig clientBufferLimitsDefaults[REDIS_CLIENT_TYPE_COUNT];\n\n/* The redisOp structure defines a Redis Operation, that is an instance of\n * a command with an argument vector, database ID, propagation target\n * (REDIS_PROPAGATE_*), and command pointer.\n *\n * Currently only used to additionally propagate more commands to AOF/Replication\n * after the propagation of the executed command. */\ntypedef struct redisOp {\n    robj **argv;\n    int argc, dbid, target;\n    struct redisCommand *cmd;\n} redisOp;\n\n/* Defines an array of Redis operations. There is an API to add to this\n * structure in a easy way.\n *\n * redisOpArrayInit();\n * redisOpArrayAppend();\n * redisOpArrayFree();\n */\ntypedef struct redisOpArray {\n    redisOp *ops;\n    int numops;\n} redisOpArray;\n\n/*-----------------------------------------------------------------------------\n * Global server state\n *----------------------------------------------------------------------------*/\n\n/* AIX defines hz to __hz, we don't use this define and in order to allow\n * Redis build on AIX we need to undef it. */\n#ifdef _AIX\n#undef hz\n#endif\n\nstruct redisServer {\n    /* General */\n    char *configfile;           /* Absolute config file path, or NULL */\n    int hz;                     /* serverCron() calls frequency in hertz */\n    redisDb *db;\n    dict *commands;             /* Command table */\n    dict *orig_commands;        /* Command table before command renaming. */\n    aeEventLoop *el;\n    unsigned lruclock:REDIS_LRU_BITS; /* Clock for LRU eviction */\n    int shutdown_asap;          /* SHUTDOWN needed ASAP */\n    int activerehashing;        /* Incremental rehash in serverCron() */\n    char *requirepass;          /* Pass for AUTH command, or NULL */\n    char *pidfile;              /* PID file path */\n    int arch_bits;              /* 32 or 64 depending on sizeof(long) */\n    int cronloops;              /* Number of times the cron function run */\n    char runid[REDIS_RUN_ID_SIZE+1];  /* ID always different at every exec. */\n    int sentinel_mode;          /* True if this instance is a Sentinel. */\n    /* Networking */\n    int port;                   /* TCP listening port */\n    int tcp_backlog;            /* TCP listen() backlog */\n    char *bindaddr[REDIS_BINDADDR_MAX]; /* Addresses we should bind to */\n    int bindaddr_count;         /* Number of addresses in server.bindaddr[] */\n    char *unixsocket;           /* UNIX socket path */\n    mode_t unixsocketperm;      /* UNIX socket permission */\n    int ipfd[REDIS_BINDADDR_MAX]; /* TCP socket file descriptors */\n    int ipfd_count;             /* Used slots in ipfd[] */\n    int sofd;                   /* Unix socket file descriptor */\n    list *clients;              /* List of active clients */\n    list *clients_to_close;     /* Clients to close asynchronously */\n    list *slaves, *monitors;    /* List of slaves and MONITORs */\n    redisClient *current_client; /* Current client, only used on crash report */\n    char neterr[ANET_ERR_LEN];   /* Error buffer for anet.c */\n    dict *slotsmgrt_cached_sockfds;\n    uint64_t next_client_id;    /* Next client unique ID. Incremental. */\n    /* RDB / AOF loading information */\n    int loading;                /* We are loading data from disk if true */\n    off_t loading_total_bytes;\n    off_t loading_loaded_bytes;\n    time_t loading_start_time;\n    off_t loading_process_events_interval_bytes;\n    /* Fast pointers to often looked up command */\n    struct redisCommand *delCommand, *multiCommand, *lpushCommand, *lpopCommand,\n                        *rpopCommand;\n    /* Fields used only for stats */\n    time_t stat_starttime;          /* Server start time */\n    long long stat_numcommands;     /* Number of processed commands */\n    long long stat_numconnections;  /* Number of connections received */\n    long long stat_expiredkeys;     /* Number of expired keys */\n    long long stat_evictedkeys;     /* Number of evicted keys (maxmemory) */\n    long long stat_keyspace_hits;   /* Number of successful lookups of keys */\n    long long stat_keyspace_misses; /* Number of failed lookups of keys */\n    size_t stat_peak_memory;        /* Max used memory record */\n    long long stat_fork_time;       /* Time needed to perform latest fork() */\n    double stat_fork_rate;          /* Fork rate in GB/sec. */\n    long long stat_rejected_conn;   /* Clients rejected because of maxclients */\n    long long stat_sync_full;       /* Number of full resyncs with slaves. */\n    long long stat_sync_partial_ok; /* Number of accepted PSYNC requests. */\n    long long stat_sync_partial_err;/* Number of unaccepted PSYNC requests. */\n    list *slowlog;                  /* SLOWLOG list of commands */\n    long long slowlog_entry_id;     /* SLOWLOG current entry ID */\n    long long slowlog_log_slower_than; /* SLOWLOG time limit (to get logged) */\n    unsigned long slowlog_max_len;     /* SLOWLOG max number of items logged */\n    size_t resident_set_size;       /* RSS sampled in serverCron(). */\n    long long stat_net_input_bytes; /* Bytes read from network. */\n    long long stat_net_output_bytes; /* Bytes written to network. */\n    /* The following two are used to track instantaneous metrics, like\n     * number of operations per second, network traffic. */\n    struct {\n        long long last_sample_time; /* Timestamp of last sample in ms */\n        long long last_sample_count;/* Count in last sample */\n        long long samples[REDIS_METRIC_SAMPLES];\n        int idx;\n    } inst_metric[REDIS_METRIC_COUNT];\n    /* Configuration */\n    int verbosity;                  /* Loglevel in redis.conf */\n    int maxidletime;                /* Client timeout in seconds */\n    int tcpkeepalive;               /* Set SO_KEEPALIVE if non-zero. */\n    int active_expire_enabled;      /* Can be disabled for testing purposes. */\n    size_t client_max_querybuf_len; /* Limit for client query buffer length */\n    int dbnum;                      /* Total number of configured DBs */\n    int daemonize;                  /* True if running as a daemon */\n    clientBufferLimitsConfig client_obuf_limits[REDIS_CLIENT_TYPE_COUNT];\n    /* AOF persistence */\n    int aof_state;                  /* REDIS_AOF_(ON|OFF|WAIT_REWRITE) */\n    int aof_fsync;                  /* Kind of fsync() policy */\n    char *aof_filename;             /* Name of the AOF file */\n    int aof_no_fsync_on_rewrite;    /* Don't fsync if a rewrite is in prog. */\n    int aof_rewrite_perc;           /* Rewrite AOF if % growth is > M and... */\n    off_t aof_rewrite_min_size;     /* the AOF file is at least N bytes. */\n    off_t aof_rewrite_base_size;    /* AOF size on latest startup or rewrite. */\n    off_t aof_current_size;         /* AOF current size. */\n    int aof_rewrite_scheduled;      /* Rewrite once BGSAVE terminates. */\n    pid_t aof_child_pid;            /* PID if rewriting process */\n    list *aof_rewrite_buf_blocks;   /* Hold changes during an AOF rewrite. */\n    sds aof_buf;      /* AOF buffer, written before entering the event loop */\n    int aof_fd;       /* File descriptor of currently selected AOF file */\n    int aof_selected_db; /* Currently selected DB in AOF */\n    time_t aof_flush_postponed_start; /* UNIX time of postponed AOF flush */\n    time_t aof_last_fsync;            /* UNIX time of last fsync() */\n    time_t aof_rewrite_time_last;   /* Time used by last AOF rewrite run. */\n    time_t aof_rewrite_time_start;  /* Current AOF rewrite start time. */\n    int aof_lastbgrewrite_status;   /* REDIS_OK or REDIS_ERR */\n    unsigned long aof_delayed_fsync;  /* delayed AOF fsync() counter */\n    int aof_rewrite_incremental_fsync;/* fsync incrementally while rewriting? */\n    int aof_last_write_status;      /* REDIS_OK or REDIS_ERR */\n    int aof_last_write_errno;       /* Valid if aof_last_write_status is ERR */\n    int aof_load_truncated;         /* Don't stop on unexpected AOF EOF. */\n    /* RDB persistence */\n    long long dirty;                /* Changes to DB from the last save */\n    long long dirty_before_bgsave;  /* Used to restore dirty on failed BGSAVE */\n    pid_t rdb_child_pid;            /* PID of RDB saving child */\n    struct saveparam *saveparams;   /* Save points array for RDB */\n    int saveparamslen;              /* Number of saving points */\n    char *rdb_filename;             /* Name of RDB file */\n    int rdb_compression;            /* Use compression in RDB? */\n    int rdb_checksum;               /* Use RDB checksum? */\n    time_t lastsave;                /* Unix time of last successful save */\n    time_t lastbgsave_try;          /* Unix time of last attempted bgsave */\n    time_t rdb_save_time_last;      /* Time used by last RDB save run. */\n    time_t rdb_save_time_start;     /* Current RDB save start time. */\n    int rdb_child_type;             /* Type of save by active child. */\n    int lastbgsave_status;          /* REDIS_OK or REDIS_ERR */\n    int stop_writes_on_bgsave_err;  /* Don't allow writes if can't BGSAVE */\n    int rdb_pipe_write_result_to_parent; /* RDB pipes used to return the state */\n    int rdb_pipe_read_result_from_child; /* of each slave in diskless SYNC. */\n    /* Propagation of commands in AOF / replication */\n    redisOpArray also_propagate;    /* Additional command to propagate. */\n    /* Logging */\n    char *logfile;                  /* Path of log file */\n    int syslog_enabled;             /* Is syslog enabled? */\n    char *syslog_ident;             /* Syslog ident */\n    int syslog_facility;            /* Syslog facility */\n    /* Replication (master) */\n    int slaveseldb;                 /* Last SELECTed DB in replication output */\n    long long master_repl_offset;   /* Global replication offset */\n    int repl_ping_slave_period;     /* Master pings the slave every N seconds */\n    char *repl_backlog;             /* Replication backlog for partial syncs */\n    long long repl_backlog_size;    /* Backlog circular buffer size */\n    long long repl_backlog_histlen; /* Backlog actual data length */\n    long long repl_backlog_idx;     /* Backlog circular buffer current offset */\n    long long repl_backlog_off;     /* Replication offset of first byte in the\n                                       backlog buffer. */\n    time_t repl_backlog_time_limit; /* Time without slaves after the backlog\n                                       gets released. */\n    time_t repl_no_slaves_since;    /* We have no slaves since that time.\n                                       Only valid if server.slaves len is 0. */\n    int repl_min_slaves_to_write;   /* Min number of slaves to write. */\n    int repl_min_slaves_max_lag;    /* Max lag of <count> slaves to write. */\n    int repl_good_slaves_count;     /* Number of slaves with lag <= max_lag. */\n    int repl_diskless_sync;         /* Send RDB to slaves sockets directly. */\n    int repl_diskless_sync_delay;   /* Delay to start a diskless repl BGSAVE. */\n    /* Replication (slave) */\n    char *masterauth;               /* AUTH with this password with master */\n    char *masterhost;               /* Hostname of master */\n    int masterport;                 /* Port of master */\n    int repl_timeout;               /* Timeout after N seconds of master idle */\n    redisClient *master;     /* Client that is master for this slave */\n    redisClient *cached_master; /* Cached master to be reused for PSYNC. */\n    int repl_syncio_timeout; /* Timeout for synchronous I/O calls */\n    int repl_state;          /* Replication status if the instance is a slave */\n    off_t repl_transfer_size; /* Size of RDB to read from master during sync. */\n    off_t repl_transfer_read; /* Amount of RDB read from master during sync. */\n    off_t repl_transfer_last_fsync_off; /* Offset when we fsync-ed last time. */\n    int repl_transfer_s;     /* Slave -> Master SYNC socket */\n    int repl_transfer_fd;    /* Slave -> Master SYNC temp file descriptor */\n    char *repl_transfer_tmpfile; /* Slave-> master SYNC temp file name */\n    time_t repl_transfer_lastio; /* Unix time of the latest read, for timeout */\n    int repl_serve_stale_data; /* Serve stale data when link is down? */\n    int repl_slave_ro;          /* Slave is read only? */\n    time_t repl_down_since; /* Unix time at which link with master went down */\n    int repl_disable_tcp_nodelay;   /* Disable TCP_NODELAY after SYNC? */\n    int slave_priority;             /* Reported in INFO and used by Sentinel. */\n    char repl_master_runid[REDIS_RUN_ID_SIZE+1];  /* Master run id for PSYNC. */\n    long long repl_master_initial_offset;         /* Master PSYNC offset. */\n    /* Replication script cache. */\n    dict *repl_scriptcache_dict;        /* SHA1 all slaves are aware of. */\n    list *repl_scriptcache_fifo;        /* First in, first out LRU eviction. */\n    unsigned int repl_scriptcache_size; /* Max number of elements. */\n    /* Limits */\n    unsigned int maxclients;            /* Max number of simultaneous clients */\n    unsigned long long maxmemory;   /* Max number of memory bytes to use */\n    int maxmemory_policy;           /* Policy for key eviction */\n    int maxmemory_samples;          /* Pricision of random sampling */\n    /* Blocked clients */\n    unsigned int bpop_blocked_clients; /* Number of clients blocked by lists */\n    list *unblocked_clients; /* list of clients to unblock before next loop */\n    list *ready_keys;        /* List of readyList structures for BLPOP & co */\n    /* Sort parameters - qsort_r() is only available under BSD so we\n     * have to take this state global, in order to pass it to sortCompare() */\n    int sort_desc;\n    int sort_alpha;\n    int sort_bypattern;\n    int sort_store;\n    /* Zip structure config, see redis.conf for more information  */\n    size_t hash_max_ziplist_entries;\n    size_t hash_max_ziplist_value;\n    size_t list_max_ziplist_entries;\n    size_t list_max_ziplist_value;\n    size_t set_max_intset_entries;\n    size_t zset_max_ziplist_entries;\n    size_t zset_max_ziplist_value;\n    size_t hll_sparse_max_bytes;\n    time_t unixtime;        /* Unix time sampled every cron cycle. */\n    long long mstime;       /* Like 'unixtime' but with milliseconds resolution. */\n    /* Pubsub */\n    dict *pubsub_channels;  /* Map channels to list of subscribed clients */\n    list *pubsub_patterns;  /* A list of pubsub_patterns */\n    int notify_keyspace_events; /* Events to propagate via Pub/Sub. This is an\n                                   xor of REDIS_NOTIFY... flags. */\n    /* Scripting */\n    lua_State *lua; /* The Lua interpreter. We use just one for all clients */\n    redisClient *lua_client;   /* The \"fake client\" to query Redis from Lua */\n    redisClient *lua_caller;   /* The client running EVAL right now, or NULL */\n    dict *lua_scripts;         /* A dictionary of SHA1 -> Lua scripts */\n    mstime_t lua_time_limit;  /* Script timeout in milliseconds */\n    mstime_t lua_time_start;  /* Start time of script, milliseconds time */\n    int lua_write_dirty;  /* True if a write command was called during the\n                             execution of the current script. */\n    int lua_random_dirty; /* True if a random command was called during the\n                             execution of the current script. */\n    int lua_timedout;     /* True if we reached the time limit for script\n                             execution. */\n    int lua_kill;         /* Kill the script if true. */\n    /* Latency monitor */\n    long long latency_monitor_threshold;\n    dict *latency_events;\n    /* Assert & bug reporting */\n    char *assert_failed;\n    char *assert_file;\n    int assert_line;\n    int bug_report_start; /* True if bug report header was already logged. */\n    int watchdog_period;  /* Software watchdog period in ms. 0 = off */\n};\n\ntypedef struct pubsubPattern {\n    redisClient *client;\n    robj *pattern;\n} pubsubPattern;\n\ntypedef void redisCommandProc(redisClient *c);\ntypedef int *redisGetKeysProc(struct redisCommand *cmd, robj **argv, int argc, int *numkeys, int flags);\nstruct redisCommand {\n    char *name;\n    redisCommandProc *proc;\n    int arity;\n    char *sflags; /* Flags as string representation, one char per flag. */\n    int flags;    /* The actual flags, obtained from the 'sflags' field. */\n    /* Use a function to determine keys arguments in a command line. */\n    redisGetKeysProc *getkeys_proc;\n    /* What keys should be loaded in background when calling this command? */\n    int firstkey; /* The first argument that's a key (0 = no keys) */\n    int lastkey;  /* The last argument that's a key */\n    int keystep;  /* The step between first and last key */\n    long long microseconds, calls;\n};\n\nstruct redisFunctionSym {\n    char *name;\n    unsigned long pointer;\n};\n\ntypedef struct _redisSortObject {\n    robj *obj;\n    union {\n        double score;\n        robj *cmpobj;\n    } u;\n} redisSortObject;\n\ntypedef struct _redisSortOperation {\n    int type;\n    robj *pattern;\n} redisSortOperation;\n\n/* Structure to hold list iteration abstraction. */\ntypedef struct {\n    robj *subject;\n    unsigned char encoding;\n    unsigned char direction; /* Iteration direction */\n    unsigned char *zi;\n    listNode *ln;\n} listTypeIterator;\n\n/* Structure for an entry while iterating over a list. */\ntypedef struct {\n    listTypeIterator *li;\n    unsigned char *zi;  /* Entry in ziplist */\n    listNode *ln;       /* Entry in linked list */\n} listTypeEntry;\n\n/* Structure to hold set iteration abstraction. */\ntypedef struct {\n    robj *subject;\n    int encoding;\n    int ii; /* intset iterator */\n    dictIterator *di;\n} setTypeIterator;\n\n/* Structure to hold hash iteration abstraction. Note that iteration over\n * hashes involves both fields and values. Because it is possible that\n * not both are required, store pointers in the iterator to avoid\n * unnecessary memory allocation for fields/values. */\ntypedef struct {\n    robj *subject;\n    int encoding;\n\n    unsigned char *fptr, *vptr;\n\n    dictIterator *di;\n    dictEntry *de;\n} hashTypeIterator;\n\n#define REDIS_HASH_KEY 1\n#define REDIS_HASH_VALUE 2\n\n/*-----------------------------------------------------------------------------\n * Extern declarations\n *----------------------------------------------------------------------------*/\n\nextern struct redisServer server;\nextern struct sharedObjectsStruct shared;\nextern dictType setDictType;\nextern dictType zsetDictType;\nextern dictType dbDictType;\nextern dictType shaScriptObjectDictType;\nextern double R_Zero, R_PosInf, R_NegInf, R_Nan;\nextern dictType hashDictType;\nextern dictType replScriptCacheDictType;\n\n/*-----------------------------------------------------------------------------\n * Functions prototypes\n *----------------------------------------------------------------------------*/\n\n/* Utils */\nlong long ustime(void);\nlong long mstime(void);\nvoid getRandomHexChars(char *p, unsigned int len);\nuint64_t crc64(uint64_t crc, const unsigned char *s, uint64_t l);\nvoid exitFromChild(int retcode);\nsize_t redisPopcount(void *s, long count);\nvoid redisSetProcTitle(char *title);\n\n/* networking.c -- Networking and Client related operations */\nredisClient *createClient(int fd);\nvoid closeTimedoutClients(void);\nvoid freeClient(redisClient *c);\nvoid freeClientAsync(redisClient *c);\nvoid resetClient(redisClient *c);\nvoid sendReplyToClient(aeEventLoop *el, int fd, void *privdata, int mask);\nvoid *addDeferredMultiBulkLength(redisClient *c);\nvoid setDeferredMultiBulkLength(redisClient *c, void *node, long length);\nvoid processInputBuffer(redisClient *c);\nvoid acceptHandler(aeEventLoop *el, int fd, void *privdata, int mask);\nvoid acceptTcpHandler(aeEventLoop *el, int fd, void *privdata, int mask);\nvoid acceptUnixHandler(aeEventLoop *el, int fd, void *privdata, int mask);\nvoid readQueryFromClient(aeEventLoop *el, int fd, void *privdata, int mask);\nvoid addReplyBulk(redisClient *c, robj *obj);\nvoid addReplyBulkCString(redisClient *c, char *s);\nvoid addReplyBulkCBuffer(redisClient *c, void *p, size_t len);\nvoid addReplyBulkLongLong(redisClient *c, long long ll);\nvoid addReply(redisClient *c, robj *obj);\nvoid addReplySds(redisClient *c, sds s);\nvoid addReplyError(redisClient *c, char *err);\nvoid addReplyStatus(redisClient *c, char *status);\nvoid addReplyDouble(redisClient *c, double d);\nvoid addReplyLongLong(redisClient *c, long long ll);\nvoid addReplyMultiBulkLen(redisClient *c, long length);\nvoid copyClientOutputBuffer(redisClient *dst, redisClient *src);\nvoid *dupClientReplyValue(void *o);\nvoid getClientsMaxBuffers(unsigned long *longest_output_list,\n                          unsigned long *biggest_input_buffer);\nvoid formatPeerId(char *peerid, size_t peerid_len, char *ip, int port);\nchar *getClientPeerId(redisClient *client);\nsds catClientInfoString(sds s, redisClient *client);\nsds getAllClientsInfoString(void);\nvoid rewriteClientCommandVector(redisClient *c, int argc, ...);\nvoid rewriteClientCommandArgument(redisClient *c, int i, robj *newval);\nunsigned long getClientOutputBufferMemoryUsage(redisClient *c);\nvoid freeClientsInAsyncFreeQueue(void);\nvoid asyncCloseClientOnOutputBufferLimitReached(redisClient *c);\nint getClientType(redisClient *c);\nint getClientTypeByName(char *name);\nchar *getClientTypeName(int class);\nvoid flushSlavesOutputBuffers(void);\nvoid disconnectSlaves(void);\nint processEventsWhileBlocked(void);\n\n#ifdef __GNUC__\nvoid addReplyErrorFormat(redisClient *c, const char *fmt, ...)\n    __attribute__((format(printf, 2, 3)));\nvoid addReplyStatusFormat(redisClient *c, const char *fmt, ...)\n    __attribute__((format(printf, 2, 3)));\n#else\nvoid addReplyErrorFormat(redisClient *c, const char *fmt, ...);\nvoid addReplyStatusFormat(redisClient *c, const char *fmt, ...);\n#endif\n\n/* List data type */\nvoid listTypeTryConversion(robj *subject, robj *value);\nvoid listTypePush(robj *subject, robj *value, int where);\nrobj *listTypePop(robj *subject, int where);\nunsigned long listTypeLength(robj *subject);\nlistTypeIterator *listTypeInitIterator(robj *subject, long index, unsigned char direction);\nvoid listTypeReleaseIterator(listTypeIterator *li);\nint listTypeNext(listTypeIterator *li, listTypeEntry *entry);\nrobj *listTypeGet(listTypeEntry *entry);\nvoid listTypeInsert(listTypeEntry *entry, robj *value, int where);\nint listTypeEqual(listTypeEntry *entry, robj *o);\nvoid listTypeDelete(listTypeEntry *entry);\nvoid listTypeConvert(robj *subject, int enc);\nvoid unblockClientWaitingData(redisClient *c);\nvoid handleClientsBlockedOnLists(void);\nvoid popGenericCommand(redisClient *c, int where);\nvoid signalListAsReady(redisDb *db, robj *key);\n\n/* MULTI/EXEC/WATCH... */\nvoid unwatchAllKeys(redisClient *c);\nvoid initClientMultiState(redisClient *c);\nvoid freeClientMultiState(redisClient *c);\nvoid queueMultiCommand(redisClient *c);\nvoid touchWatchedKey(redisDb *db, robj *key);\nvoid touchWatchedKeysOnFlush(int dbid);\nvoid discardTransaction(redisClient *c);\nvoid flagTransaction(redisClient *c);\n\n/* Redis object implementation */\nvoid decrRefCount(robj *o);\nvoid decrRefCountVoid(void *o);\nvoid incrRefCount(robj *o);\nrobj *resetRefCount(robj *obj);\nvoid freeStringObject(robj *o);\nvoid freeListObject(robj *o);\nvoid freeSetObject(robj *o);\nvoid freeZsetObject(robj *o);\nvoid freeHashObject(robj *o);\nrobj *createObject(int type, void *ptr);\nrobj *createStringObject(char *ptr, size_t len);\nrobj *dupStringObject(robj *o);\nint isObjectRepresentableAsLongLong(robj *o, long long *llongval);\nrobj *tryObjectEncoding(robj *o);\nrobj *getDecodedObject(robj *o);\nsize_t stringObjectLen(robj *o);\nrobj *createStringObjectFromLongLong(long long value);\nrobj *createStringObjectFromLongDouble(long double value, int humanfriendly);\nrobj *createListObject(void);\nrobj *createZiplistObject(void);\nrobj *createSetObject(void);\nrobj *createIntsetObject(void);\nrobj *createHashObject(void);\nrobj *createZsetObject(void);\nrobj *createZsetZiplistObject(void);\nint getLongFromObjectOrReply(redisClient *c, robj *o, long *target, const char *msg);\nint checkType(redisClient *c, robj *o, int type);\nint getLongLongFromObjectOrReply(redisClient *c, robj *o, long long *target, const char *msg);\nint getDoubleFromObjectOrReply(redisClient *c, robj *o, double *target, const char *msg);\nint getLongLongFromObject(robj *o, long long *target);\nint getLongDoubleFromObject(robj *o, long double *target);\nint getLongDoubleFromObjectOrReply(redisClient *c, robj *o, long double *target, const char *msg);\nchar *strEncoding(int encoding);\nint compareStringObjects(robj *a, robj *b);\nint collateStringObjects(robj *a, robj *b);\nint equalStringObjects(robj *a, robj *b);\nunsigned long estimateObjectIdleTime(robj *o);\n\n/* Synchronous I/O with timeout */\nssize_t syncWrite(int fd, char *ptr, ssize_t size, long long timeout);\nssize_t syncRead(int fd, char *ptr, ssize_t size, long long timeout);\nssize_t syncReadLine(int fd, char *ptr, ssize_t size, long long timeout);\n\n/* Replication */\nvoid replicationFeedSlaves(list *slaves, int dictid, robj **argv, int argc);\nvoid replicationFeedMonitors(redisClient *c, list *monitors, int dictid, robj **argv, int argc);\nvoid updateSlavesWaitingBgsave(int bgsaveerr, int type);\nvoid replicationCron(void);\nvoid replicationHandleMasterDisconnection(void);\nvoid replicationCacheMaster(redisClient *c);\nvoid resizeReplicationBacklog(long long newsize);\nvoid refreshGoodSlavesCount(void);\nvoid replicationScriptCacheInit(void);\nvoid replicationScriptCacheFlush(void);\nvoid replicationScriptCacheAdd(sds sha1);\nint replicationScriptCacheExists(sds sha1);\nvoid replicationSetMaster(char *ip, int port);\nvoid replicationUnsetMaster(void);\nvoid replicationSendNewlineToMaster(void);\nchar *replicationGetSlaveName(redisClient *c);\n\n/* Generic persistence functions */\nvoid startLoading(FILE *fp);\nvoid loadingProgress(off_t pos);\nvoid stopLoading(void);\n\n/* RDB persistence */\n#include \"rdb.h\"\n\n/* AOF persistence */\nvoid flushAppendOnlyFile(int force);\nvoid feedAppendOnlyFile(struct redisCommand *cmd, int dictid, robj **argv, int argc);\nvoid aofRemoveTempFile(pid_t childpid);\nint rewriteAppendOnlyFileBackground(void);\nint loadAppendOnlyFile(char *filename);\nvoid stopAppendOnly(void);\nint startAppendOnly(void);\nvoid backgroundRewriteDoneHandler(int exitcode, int bysignal);\nvoid aofRewriteBufferReset(void);\nunsigned long aofRewriteBufferSize(void);\n\n/* Sorted sets data type */\n\n/* Struct to hold a inclusive/exclusive range spec by score comparison. */\ntypedef struct {\n    double min, max;\n    int minex, maxex; /* are min or max exclusive? */\n} zrangespec;\n\n/* Struct to hold an inclusive/exclusive range spec by lexicographic comparison. */\ntypedef struct {\n    robj *min, *max;  /* May be set to shared.(minstring|maxstring) */\n    int minex, maxex; /* are min or max exclusive? */\n} zlexrangespec;\n\nzskiplist *zslCreate(void);\nvoid zslFree(zskiplist *zsl);\nzskiplistNode *zslInsert(zskiplist *zsl, double score, robj *obj);\nunsigned char *zzlInsert(unsigned char *zl, robj *ele, double score);\nint zslDelete(zskiplist *zsl, double score, robj *obj);\nzskiplistNode *zslFirstInRange(zskiplist *zsl, zrangespec *range);\ndouble zzlGetScore(unsigned char *sptr);\nvoid zzlNext(unsigned char *zl, unsigned char **eptr, unsigned char **sptr);\nvoid zzlPrev(unsigned char *zl, unsigned char **eptr, unsigned char **sptr);\nunsigned int zsetLength(robj *zobj);\nvoid zsetConvert(robj *zobj, int encoding);\n\n/* Core functions */\nint freeMemoryIfNeeded(void);\nint processCommand(redisClient *c);\nvoid setupSignalHandlers(void);\nstruct redisCommand *lookupCommand(sds name);\nstruct redisCommand *lookupCommandByCString(char *s);\nstruct redisCommand *lookupCommandOrOriginal(sds name);\nvoid call(redisClient *c, int flags);\nvoid propagate(struct redisCommand *cmd, int dbid, robj **argv, int argc, int flags);\nvoid alsoPropagate(struct redisCommand *cmd, int dbid, robj **argv, int argc, int target);\nvoid forceCommandPropagation(redisClient *c, int flags);\nint prepareForShutdown();\n#ifdef __GNUC__\nvoid redisLog(int level, const char *fmt, ...)\n    __attribute__((format(printf, 2, 3)));\n#else\nvoid redisLog(int level, const char *fmt, ...);\n#endif\nvoid redisLogRaw(int level, const char *msg);\nvoid redisLogFromHandler(int level, const char *msg);\nvoid usage(void);\nvoid updateDictResizePolicy(void);\nint htNeedsResize(dict *dict);\nvoid oom(const char *msg);\nvoid populateCommandTable(void);\nvoid resetCommandTableStats(void);\nvoid adjustOpenFilesLimit(void);\nvoid closeListeningSockets(int unlink_unix_socket);\nvoid updateCachedTime(void);\nvoid resetServerStats(void);\n\n/* Set data type */\nrobj *setTypeCreate(robj *value);\nint setTypeAdd(robj *subject, robj *value);\nint setTypeRemove(robj *subject, robj *value);\nint setTypeIsMember(robj *subject, robj *value);\nsetTypeIterator *setTypeInitIterator(robj *subject);\nvoid setTypeReleaseIterator(setTypeIterator *si);\nint setTypeNext(setTypeIterator *si, robj **objele, int64_t *llele);\nrobj *setTypeNextObject(setTypeIterator *si);\nint setTypeRandomElement(robj *setobj, robj **objele, int64_t *llele);\nunsigned long setTypeSize(robj *subject);\nvoid setTypeConvert(robj *subject, int enc);\n\n/* Hash data type */\nvoid hashTypeConvert(robj *o, int enc);\nvoid hashTypeTryConversion(robj *subject, robj **argv, int start, int end);\nvoid hashTypeTryObjectEncoding(robj *subject, robj **o1, robj **o2);\nrobj *hashTypeGetObject(robj *o, robj *key);\nint hashTypeExists(robj *o, robj *key);\nint hashTypeSet(robj *o, robj *key, robj *value);\nint hashTypeDelete(robj *o, robj *key);\nunsigned long hashTypeLength(robj *o);\nhashTypeIterator *hashTypeInitIterator(robj *subject);\nvoid hashTypeReleaseIterator(hashTypeIterator *hi);\nint hashTypeNext(hashTypeIterator *hi);\nvoid hashTypeCurrentFromZiplist(hashTypeIterator *hi, int what,\n                                unsigned char **vstr,\n                                unsigned int *vlen,\n                                long long *vll);\nvoid hashTypeCurrentFromHashTable(hashTypeIterator *hi, int what, robj **dst);\nrobj *hashTypeCurrentObject(hashTypeIterator *hi, int what);\nrobj *hashTypeLookupWriteOrCreate(redisClient *c, robj *key);\n\n/* Pub / Sub */\nint pubsubUnsubscribeAllChannels(redisClient *c, int notify);\nint pubsubUnsubscribeAllPatterns(redisClient *c, int notify);\nvoid freePubsubPattern(void *p);\nint listMatchPubsubPattern(void *a, void *b);\nint pubsubPublishMessage(robj *channel, robj *message);\n\n/* Keyspace events notification */\nvoid notifyKeyspaceEvent(int type, char *event, robj *key, int dbid);\nint keyspaceEventsStringToFlags(char *classes);\nsds keyspaceEventsFlagsToString(int flags);\n\n/* Configuration */\nvoid loadServerConfig(char *filename, char *options);\nvoid appendServerSaveParams(time_t seconds, int changes);\nvoid resetServerSaveParams(void);\nstruct rewriteConfigState; /* Forward declaration to export API. */\nvoid rewriteConfigRewriteLine(struct rewriteConfigState *state, char *option, sds line, int force);\nint rewriteConfig(char *path);\n\n/* db.c -- Keyspace access API */\nint removeExpire(redisDb *db, robj *key);\nvoid propagateExpire(redisDb *db, robj *key);\nint expireIfNeeded(redisDb *db, robj *key);\nlong long getExpire(redisDb *db, robj *key);\nvoid setExpire(redisDb *db, robj *key, long long when);\nrobj *lookupKey(redisDb *db, robj *key);\nrobj *lookupKeyRead(redisDb *db, robj *key);\nrobj *lookupKeyWrite(redisDb *db, robj *key);\nrobj *lookupKeyReadOrReply(redisClient *c, robj *key, robj *reply);\nrobj *lookupKeyWriteOrReply(redisClient *c, robj *key, robj *reply);\nvoid dbAdd(redisDb *db, robj *key, robj *val);\nvoid dbOverwrite(redisDb *db, robj *key, robj *val);\nvoid setKey(redisDb *db, robj *key, robj *val);\nint dbExists(redisDb *db, robj *key);\nrobj *dbRandomKey(redisDb *db);\nint dbDelete(redisDb *db, robj *key);\nrobj *dbUnshareStringValue(redisDb *db, robj *key, robj *o);\nlong long emptyDb(void(callback)(void*));\nint selectDb(redisClient *c, int id);\nvoid signalModifiedKey(redisDb *db, robj *key);\nvoid signalFlushedDb(int dbid);\nunsigned int GetKeysInSlot(unsigned int hashslot, robj **keys, unsigned int count);\nvoid scanGenericCommand(redisClient *c, robj *o, unsigned long cursor);\nint parseScanCursorOrReply(redisClient *c, robj *o, unsigned long *cursor);\n\n/* API to get key arguments from commands */\n#define REDIS_GETKEYS_ALL 0\n#define REDIS_GETKEYS_PRELOAD 1\nint *getKeysFromCommand(struct redisCommand *cmd, robj **argv, int argc, int *numkeys, int flags);\nvoid getKeysFreeResult(int *result);\nint *noPreloadGetKeys(struct redisCommand *cmd,robj **argv, int argc, int *numkeys, int flags);\nint *renameGetKeys(struct redisCommand *cmd,robj **argv, int argc, int *numkeys, int flags);\nint *zunionInterGetKeys(struct redisCommand *cmd,robj **argv, int argc, int *numkeys, int flags);\n\n/* Sentinel */\nvoid initSentinelConfig(void);\nvoid initSentinel(void);\nvoid sentinelTimer(void);\nchar *sentinelHandleConfiguration(char **argv, int argc);\nvoid sentinelIsRunning(void);\n\n/* Scripting */\nvoid scriptingInit(void);\n\n/* Git SHA1 */\nchar *redisGitSHA1(void);\nchar *redisGitDirty(void);\nuint64_t redisBuildId(void);\n\n/* Commands prototypes */\nvoid authCommand(redisClient *c);\nvoid pingCommand(redisClient *c);\nvoid echoCommand(redisClient *c);\nvoid commandCommand(redisClient *c);\nvoid setCommand(redisClient *c);\nvoid setnxCommand(redisClient *c);\nvoid setexCommand(redisClient *c);\nvoid psetexCommand(redisClient *c);\nvoid getCommand(redisClient *c);\nvoid delCommand(redisClient *c);\nvoid existsCommand(redisClient *c);\nvoid setbitCommand(redisClient *c);\nvoid getbitCommand(redisClient *c);\nvoid setrangeCommand(redisClient *c);\nvoid getrangeCommand(redisClient *c);\nvoid incrCommand(redisClient *c);\nvoid decrCommand(redisClient *c);\nvoid incrbyCommand(redisClient *c);\nvoid decrbyCommand(redisClient *c);\nvoid incrbyfloatCommand(redisClient *c);\nvoid selectCommand(redisClient *c);\nvoid randomkeyCommand(redisClient *c);\nvoid keysCommand(redisClient *c);\nvoid scanCommand(redisClient *c);\nvoid dbsizeCommand(redisClient *c);\nvoid lastsaveCommand(redisClient *c);\nvoid saveCommand(redisClient *c);\nvoid bgsaveCommand(redisClient *c);\nvoid bgrewriteaofCommand(redisClient *c);\nvoid shutdownCommand(redisClient *c);\nvoid moveCommand(redisClient *c);\nvoid renameCommand(redisClient *c);\nvoid renamenxCommand(redisClient *c);\nvoid lpushCommand(redisClient *c);\nvoid rpushCommand(redisClient *c);\nvoid lpushxCommand(redisClient *c);\nvoid rpushxCommand(redisClient *c);\nvoid linsertCommand(redisClient *c);\nvoid lpopCommand(redisClient *c);\nvoid rpopCommand(redisClient *c);\nvoid llenCommand(redisClient *c);\nvoid lindexCommand(redisClient *c);\nvoid lrangeCommand(redisClient *c);\nvoid ltrimCommand(redisClient *c);\nvoid typeCommand(redisClient *c);\nvoid lsetCommand(redisClient *c);\nvoid saddCommand(redisClient *c);\nvoid sremCommand(redisClient *c);\nvoid smoveCommand(redisClient *c);\nvoid sismemberCommand(redisClient *c);\nvoid scardCommand(redisClient *c);\nvoid spopCommand(redisClient *c);\nvoid srandmemberCommand(redisClient *c);\nvoid sinterCommand(redisClient *c);\nvoid sinterstoreCommand(redisClient *c);\nvoid sunionCommand(redisClient *c);\nvoid sunionstoreCommand(redisClient *c);\nvoid sdiffCommand(redisClient *c);\nvoid sdiffstoreCommand(redisClient *c);\nvoid sscanCommand(redisClient *c);\nvoid syncCommand(redisClient *c);\nvoid flushdbCommand(redisClient *c);\nvoid flushallCommand(redisClient *c);\nvoid sortCommand(redisClient *c);\nvoid lremCommand(redisClient *c);\nvoid rpoplpushCommand(redisClient *c);\nvoid infoCommand(redisClient *c);\nvoid mgetCommand(redisClient *c);\nvoid monitorCommand(redisClient *c);\nvoid expireCommand(redisClient *c);\nvoid expireatCommand(redisClient *c);\nvoid pexpireCommand(redisClient *c);\nvoid pexpireatCommand(redisClient *c);\nvoid getsetCommand(redisClient *c);\nvoid ttlCommand(redisClient *c);\nvoid pttlCommand(redisClient *c);\nvoid persistCommand(redisClient *c);\nvoid slaveofCommand(redisClient *c);\nvoid roleCommand(redisClient *c);\nvoid debugCommand(redisClient *c);\nvoid msetCommand(redisClient *c);\nvoid msetnxCommand(redisClient *c);\nvoid zaddCommand(redisClient *c);\nvoid zincrbyCommand(redisClient *c);\nvoid zrangeCommand(redisClient *c);\nvoid zrangebyscoreCommand(redisClient *c);\nvoid zrevrangebyscoreCommand(redisClient *c);\nvoid zrangebylexCommand(redisClient *c);\nvoid zrevrangebylexCommand(redisClient *c);\nvoid zcountCommand(redisClient *c);\nvoid zlexcountCommand(redisClient *c);\nvoid zrevrangeCommand(redisClient *c);\nvoid zcardCommand(redisClient *c);\nvoid zremCommand(redisClient *c);\nvoid zscoreCommand(redisClient *c);\nvoid zremrangebyscoreCommand(redisClient *c);\nvoid zremrangebylexCommand(redisClient *c);\nvoid multiCommand(redisClient *c);\nvoid execCommand(redisClient *c);\nvoid discardCommand(redisClient *c);\nvoid blpopCommand(redisClient *c);\nvoid brpopCommand(redisClient *c);\nvoid brpoplpushCommand(redisClient *c);\nvoid appendCommand(redisClient *c);\nvoid strlenCommand(redisClient *c);\nvoid zrankCommand(redisClient *c);\nvoid zrevrankCommand(redisClient *c);\nvoid hsetCommand(redisClient *c);\nvoid hsetnxCommand(redisClient *c);\nvoid hgetCommand(redisClient *c);\nvoid hmsetCommand(redisClient *c);\nvoid hmgetCommand(redisClient *c);\nvoid hdelCommand(redisClient *c);\nvoid hlenCommand(redisClient *c);\nvoid zremrangebyrankCommand(redisClient *c);\nvoid zunionstoreCommand(redisClient *c);\nvoid zinterstoreCommand(redisClient *c);\nvoid zscanCommand(redisClient *c);\nvoid hkeysCommand(redisClient *c);\nvoid hvalsCommand(redisClient *c);\nvoid hgetallCommand(redisClient *c);\nvoid hexistsCommand(redisClient *c);\nvoid hscanCommand(redisClient *c);\nvoid configCommand(redisClient *c);\nvoid hincrbyCommand(redisClient *c);\nvoid hincrbyfloatCommand(redisClient *c);\nvoid subscribeCommand(redisClient *c);\nvoid unsubscribeCommand(redisClient *c);\nvoid psubscribeCommand(redisClient *c);\nvoid punsubscribeCommand(redisClient *c);\nvoid publishCommand(redisClient *c);\nvoid pubsubCommand(redisClient *c);\nvoid watchCommand(redisClient *c);\nvoid unwatchCommand(redisClient *c);\nvoid restoreCommand(redisClient *c);\nvoid migrateCommand(redisClient *c);\nvoid dumpCommand(redisClient *c);\nvoid objectCommand(redisClient *c);\nvoid clientCommand(redisClient *c);\nvoid evalCommand(redisClient *c);\nvoid evalShaCommand(redisClient *c);\nvoid scriptCommand(redisClient *c);\nvoid timeCommand(redisClient *c);\nvoid bitopCommand(redisClient *c);\nvoid bitcountCommand(redisClient *c);\nvoid bitposCommand(redisClient *c);\nvoid replconfCommand(redisClient *c);\nvoid pfselftestCommand(redisClient *c);\nvoid pfaddCommand(redisClient *c);\nvoid pfcountCommand(redisClient *c);\nvoid pfmergeCommand(redisClient *c);\nvoid pfdebugCommand(redisClient *c);\nvoid latencyCommand(redisClient *c);\nvoid slotsinfoCommand(redisClient *c);\nvoid slotsscanCommand(redisClient *c);\nvoid slotsdelCommand(redisClient *c);\nvoid slotsmgrtslotCommand(redisClient *c);\nvoid slotsmgrtoneCommand(redisClient *c);\nvoid slotsmgrttagslotCommand(redisClient *c);\nvoid slotsmgrttagoneCommand(redisClient *c);\nvoid slotshashkeyCommand(redisClient *c);\nvoid slotscheckCommand(redisClient *c);\nvoid slotsrestoreCommand(redisClient *c);\n\nvoid slotsmgrt_cleanup();\nint slots_num(const sds s, uint32_t *pcrc, int *phastag);\n\n#if defined(__GNUC__)\nvoid *calloc(size_t count, size_t size) __attribute__ ((deprecated));\nvoid free(void *ptr) __attribute__ ((deprecated));\nvoid *malloc(size_t size) __attribute__ ((deprecated));\nvoid *realloc(void *ptr, size_t size) __attribute__ ((deprecated));\n#endif\n\n/* Debugging stuff */\nvoid _redisAssertWithInfo(redisClient *c, robj *o, char *estr, char *file, int line);\nvoid _redisAssert(char *estr, char *file, int line);\nvoid _redisPanic(char *msg, char *file, int line);\nvoid bugReportStart(void);\nvoid redisLogObjectDebugInfo(robj *o);\nvoid sigsegvHandler(int sig, siginfo_t *info, void *secret);\nsds genRedisInfoString(char *section);\nvoid enableWatchdog(int period);\nvoid disableWatchdog(void);\nvoid watchdogScheduleSignal(int period);\nvoid redisLogHexDump(int level, char *descr, void *value, size_t len);\n\n#define redisDebug(fmt, ...) \\\n    printf(\"DEBUG %s:%d > \" fmt \"\\n\", __FILE__, __LINE__, __VA_ARGS__)\n#define redisDebugMark() \\\n    printf(\"-- MARK %s:%d --\\n\", __FILE__, __LINE__)\n\n#endif\n"
  },
  {
    "path": "extern/deprecated/redis-2.8.21/src/redisassert.h",
    "content": "/* redisassert.h -- Drop in replacemnet assert.h that prints the stack trace\n *                  in the Redis logs.\n *\n * This file should be included instead of \"assert.h\" inside libraries used by\n * Redis that are using assertions, so instead of Redis disappearing with\n * SIGABORT, we get the details and stack trace inside the log file.\n *\n * ----------------------------------------------------------------------------\n *\n * Copyright (c) 2006-2012, Salvatore Sanfilippo <antirez at gmail dot com>\n * All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions are met:\n *\n *   * Redistributions of source code must retain the above copyright notice,\n *     this list of conditions and the following disclaimer.\n *   * Redistributions in binary form must reproduce the above copyright\n *     notice, this list of conditions and the following disclaimer in the\n *     documentation and/or other materials provided with the distribution.\n *   * Neither the name of Redis nor the names of its contributors may be used\n *     to endorse or promote products derived from this software without\n *     specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\"\n * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\n * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE\n * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR\n * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF\n * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS\n * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN\n * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)\n * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE\n * POSSIBILITY OF SUCH DAMAGE.\n */\n\n#ifndef __REDIS_ASSERT_H__\n#define __REDIS_ASSERT_H__\n\n#include <unistd.h> /* for _exit() */\n\n#define assert(_e) ((_e)?(void)0 : (_redisAssert(#_e,__FILE__,__LINE__),_exit(1)))\n\nvoid _redisAssert(char *estr, char *file, int line);\n\n#endif\n"
  },
  {
    "path": "extern/deprecated/redis-2.8.21/src/release.c",
    "content": "/*\n * Copyright (c) 2009-2012, Salvatore Sanfilippo <antirez at gmail dot com>\n * All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions are met:\n *\n *   * Redistributions of source code must retain the above copyright notice,\n *     this list of conditions and the following disclaimer.\n *   * Redistributions in binary form must reproduce the above copyright\n *     notice, this list of conditions and the following disclaimer in the\n *     documentation and/or other materials provided with the distribution.\n *   * Neither the name of Redis nor the names of its contributors may be used\n *     to endorse or promote products derived from this software without\n *     specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\"\n * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\n * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE\n * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR\n * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF\n * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS\n * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN\n * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)\n * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE\n * POSSIBILITY OF SUCH DAMAGE.\n */\n\n/* Every time the Redis Git SHA1 or Dirty status changes only this small\n * file is recompiled, as we access this information in all the other\n * files using this functions. */\n\n#include <string.h>\n\n#include \"release.h\"\n#include \"version.h\"\n#include \"crc64.h\"\n\nchar *redisGitSHA1(void) {\n    return REDIS_GIT_SHA1;\n}\n\nchar *redisGitDirty(void) {\n    return REDIS_GIT_DIRTY;\n}\n\nuint64_t redisBuildId(void) {\n    char *buildid = REDIS_VERSION REDIS_BUILD_ID REDIS_GIT_DIRTY REDIS_GIT_SHA1;\n\n    return crc64(0,(unsigned char*)buildid,strlen(buildid));\n}\n"
  },
  {
    "path": "extern/deprecated/redis-2.8.21/src/replication.c",
    "content": "/* Asynchronous replication implementation.\n *\n * Copyright (c) 2009-2012, Salvatore Sanfilippo <antirez at gmail dot com>\n * All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions are met:\n *\n *   * Redistributions of source code must retain the above copyright notice,\n *     this list of conditions and the following disclaimer.\n *   * Redistributions in binary form must reproduce the above copyright\n *     notice, this list of conditions and the following disclaimer in the\n *     documentation and/or other materials provided with the distribution.\n *   * Neither the name of Redis nor the names of its contributors may be used\n *     to endorse or promote products derived from this software without\n *     specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\"\n * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\n * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE\n * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR\n * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF\n * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS\n * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN\n * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)\n * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE\n * POSSIBILITY OF SUCH DAMAGE.\n */\n\n\n#include \"redis.h\"\n\n#include <sys/time.h>\n#include <unistd.h>\n#include <fcntl.h>\n#include <sys/socket.h>\n#include <sys/stat.h>\n\nvoid replicationDiscardCachedMaster(void);\nvoid replicationResurrectCachedMaster(int newfd);\nvoid replicationSendAck(void);\nvoid putSlaveOnline(redisClient *slave);\n\n/* --------------------------- Utility functions ---------------------------- */\n\n/* Return the pointer to a string representing the slave ip:listening_port\n * pair. Mostly useful for logging, since we want to log a slave using its\n * IP address and it's listening port which is more clear for the user, for\n * example: \"Closing connection with slave 10.1.2.3:6380\". */\nchar *replicationGetSlaveName(redisClient *c) {\n    static char buf[REDIS_PEER_ID_LEN];\n    char ip[REDIS_IP_STR_LEN];\n\n    ip[0] = '\\0';\n    buf[0] = '\\0';\n    if (anetPeerToString(c->fd,ip,sizeof(ip),NULL) != -1) {\n        if (c->slave_listening_port)\n            snprintf(buf,sizeof(buf),\"%s:%d\",ip,c->slave_listening_port);\n        else\n            snprintf(buf,sizeof(buf),\"%s:<unknown-slave-port>\",ip);\n    } else {\n        snprintf(buf,sizeof(buf),\"client id #%llu\",\n            (unsigned long long) c->id);\n    }\n    return buf;\n}\n\n/* ---------------------------------- MASTER -------------------------------- */\n\nvoid createReplicationBacklog(void) {\n    redisAssert(server.repl_backlog == NULL);\n    server.repl_backlog = zmalloc(server.repl_backlog_size);\n    server.repl_backlog_histlen = 0;\n    server.repl_backlog_idx = 0;\n    /* When a new backlog buffer is created, we increment the replication\n     * offset by one to make sure we'll not be able to PSYNC with any\n     * previous slave. This is needed because we avoid incrementing the\n     * master_repl_offset if no backlog exists nor slaves are attached. */\n    server.master_repl_offset++;\n\n    /* We don't have any data inside our buffer, but virtually the first\n     * byte we have is the next byte that will be generated for the\n     * replication stream. */\n    server.repl_backlog_off = server.master_repl_offset+1;\n}\n\n/* This function is called when the user modifies the replication backlog\n * size at runtime. It is up to the function to both update the\n * server.repl_backlog_size and to resize the buffer and setup it so that\n * it contains the same data as the previous one (possibly less data, but\n * the most recent bytes, or the same data and more free space in case the\n * buffer is enlarged). */\nvoid resizeReplicationBacklog(long long newsize) {\n    if (newsize < REDIS_REPL_BACKLOG_MIN_SIZE)\n        newsize = REDIS_REPL_BACKLOG_MIN_SIZE;\n    if (server.repl_backlog_size == newsize) return;\n\n    server.repl_backlog_size = newsize;\n    if (server.repl_backlog != NULL) {\n        /* What we actually do is to flush the old buffer and realloc a new\n         * empty one. It will refill with new data incrementally.\n         * The reason is that copying a few gigabytes adds latency and even\n         * worse often we need to alloc additional space before freeing the\n         * old buffer. */\n        zfree(server.repl_backlog);\n        server.repl_backlog = zmalloc(server.repl_backlog_size);\n        server.repl_backlog_histlen = 0;\n        server.repl_backlog_idx = 0;\n        /* Next byte we have is... the next since the buffer is empty. */\n        server.repl_backlog_off = server.master_repl_offset+1;\n    }\n}\n\nvoid freeReplicationBacklog(void) {\n    redisAssert(listLength(server.slaves) == 0);\n    zfree(server.repl_backlog);\n    server.repl_backlog = NULL;\n}\n\n/* Add data to the replication backlog.\n * This function also increments the global replication offset stored at\n * server.master_repl_offset, because there is no case where we want to feed\n * the backlog without incrementing the buffer. */\nvoid feedReplicationBacklog(void *ptr, size_t len) {\n    unsigned char *p = ptr;\n\n    server.master_repl_offset += len;\n\n    /* This is a circular buffer, so write as much data we can at every\n     * iteration and rewind the \"idx\" index if we reach the limit. */\n    while(len) {\n        size_t thislen = server.repl_backlog_size - server.repl_backlog_idx;\n        if (thislen > len) thislen = len;\n        memcpy(server.repl_backlog+server.repl_backlog_idx,p,thislen);\n        server.repl_backlog_idx += thislen;\n        if (server.repl_backlog_idx == server.repl_backlog_size)\n            server.repl_backlog_idx = 0;\n        len -= thislen;\n        p += thislen;\n        server.repl_backlog_histlen += thislen;\n    }\n    if (server.repl_backlog_histlen > server.repl_backlog_size)\n        server.repl_backlog_histlen = server.repl_backlog_size;\n    /* Set the offset of the first byte we have in the backlog. */\n    server.repl_backlog_off = server.master_repl_offset -\n                              server.repl_backlog_histlen + 1;\n}\n\n/* Wrapper for feedReplicationBacklog() that takes Redis string objects\n * as input. */\nvoid feedReplicationBacklogWithObject(robj *o) {\n    char llstr[REDIS_LONGSTR_SIZE];\n    void *p;\n    size_t len;\n\n    if (o->encoding == REDIS_ENCODING_INT) {\n        len = ll2string(llstr,sizeof(llstr),(long)o->ptr);\n        p = llstr;\n    } else {\n        len = sdslen(o->ptr);\n        p = o->ptr;\n    }\n    feedReplicationBacklog(p,len);\n}\n\nvoid replicationFeedSlaves(list *slaves, int dictid, robj **argv, int argc) {\n    listNode *ln;\n    listIter li;\n    int j, len;\n    char llstr[REDIS_LONGSTR_SIZE];\n\n    /* If there aren't slaves, and there is no backlog buffer to populate,\n     * we can return ASAP. */\n    if (server.repl_backlog == NULL && listLength(slaves) == 0) return;\n\n    /* We can't have slaves attached and no backlog. */\n    redisAssert(!(listLength(slaves) != 0 && server.repl_backlog == NULL));\n\n    /* Send SELECT command to every slave if needed. */\n    if (server.slaveseldb != dictid) {\n        robj *selectcmd;\n\n        /* For a few DBs we have pre-computed SELECT command. */\n        if (dictid >= 0 && dictid < REDIS_SHARED_SELECT_CMDS) {\n            selectcmd = shared.select[dictid];\n        } else {\n            int dictid_len;\n\n            dictid_len = ll2string(llstr,sizeof(llstr),dictid);\n            selectcmd = createObject(REDIS_STRING,\n                sdscatprintf(sdsempty(),\n                \"*2\\r\\n$6\\r\\nSELECT\\r\\n$%d\\r\\n%s\\r\\n\",\n                dictid_len, llstr));\n        }\n\n        /* Add the SELECT command into the backlog. */\n        if (server.repl_backlog) feedReplicationBacklogWithObject(selectcmd);\n\n        /* Send it to slaves. */\n        listRewind(slaves,&li);\n        while((ln = listNext(&li))) {\n            redisClient *slave = ln->value;\n            addReply(slave,selectcmd);\n        }\n\n        if (dictid < 0 || dictid >= REDIS_SHARED_SELECT_CMDS)\n            decrRefCount(selectcmd);\n    }\n    server.slaveseldb = dictid;\n\n    /* Write the command to the replication backlog if any. */\n    if (server.repl_backlog) {\n        char aux[REDIS_LONGSTR_SIZE+3];\n\n        /* Add the multi bulk reply length. */\n        aux[0] = '*';\n        len = ll2string(aux+1,sizeof(aux)-1,argc);\n        aux[len+1] = '\\r';\n        aux[len+2] = '\\n';\n        feedReplicationBacklog(aux,len+3);\n\n        for (j = 0; j < argc; j++) {\n            long objlen = stringObjectLen(argv[j]);\n\n            /* We need to feed the buffer with the object as a bulk reply\n             * not just as a plain string, so create the $..CRLF payload len\n             * and add the final CRLF */\n            aux[0] = '$';\n            len = ll2string(aux+1,sizeof(aux)-1,objlen);\n            aux[len+1] = '\\r';\n            aux[len+2] = '\\n';\n            feedReplicationBacklog(aux,len+3);\n            feedReplicationBacklogWithObject(argv[j]);\n            feedReplicationBacklog(aux+len+1,2);\n        }\n    }\n\n    /* Write the command to every slave. */\n    listRewind(server.slaves,&li);\n    while((ln = listNext(&li))) {\n        redisClient *slave = ln->value;\n\n        /* Don't feed slaves that are still waiting for BGSAVE to start */\n        if (slave->replstate == REDIS_REPL_WAIT_BGSAVE_START) continue;\n\n        /* Feed slaves that are waiting for the initial SYNC (so these commands\n         * are queued in the output buffer until the initial SYNC completes),\n         * or are already in sync with the master. */\n\n        /* Add the multi bulk length. */\n        addReplyMultiBulkLen(slave,argc);\n\n        /* Finally any additional argument that was not stored inside the\n         * static buffer if any (from j to argc). */\n        for (j = 0; j < argc; j++)\n            addReplyBulk(slave,argv[j]);\n    }\n}\n\nvoid replicationFeedMonitors(redisClient *c, list *monitors, int dictid, robj **argv, int argc) {\n    listNode *ln;\n    listIter li;\n    int j;\n    sds cmdrepr = sdsnew(\"+\");\n    robj *cmdobj;\n    struct timeval tv;\n\n    gettimeofday(&tv,NULL);\n    cmdrepr = sdscatprintf(cmdrepr,\"%ld.%06ld \",(long)tv.tv_sec,(long)tv.tv_usec);\n    if (c->flags & REDIS_LUA_CLIENT) {\n        cmdrepr = sdscatprintf(cmdrepr,\"[%d lua] \",dictid);\n    } else if (c->flags & REDIS_UNIX_SOCKET) {\n        cmdrepr = sdscatprintf(cmdrepr,\"[%d unix:%s] \",dictid,server.unixsocket);\n    } else {\n        cmdrepr = sdscatprintf(cmdrepr,\"[%d %s] \",dictid,getClientPeerId(c));\n    }\n\n    for (j = 0; j < argc; j++) {\n        if (argv[j]->encoding == REDIS_ENCODING_INT) {\n            cmdrepr = sdscatprintf(cmdrepr, \"\\\"%ld\\\"\", (long)argv[j]->ptr);\n        } else {\n            cmdrepr = sdscatrepr(cmdrepr,(char*)argv[j]->ptr,\n                        sdslen(argv[j]->ptr));\n        }\n        if (j != argc-1)\n            cmdrepr = sdscatlen(cmdrepr,\" \",1);\n    }\n    cmdrepr = sdscatlen(cmdrepr,\"\\r\\n\",2);\n    cmdobj = createObject(REDIS_STRING,cmdrepr);\n\n    listRewind(monitors,&li);\n    while((ln = listNext(&li))) {\n        redisClient *monitor = ln->value;\n        addReply(monitor,cmdobj);\n    }\n    decrRefCount(cmdobj);\n}\n\n/* Feed the slave 'c' with the replication backlog starting from the\n * specified 'offset' up to the end of the backlog. */\nlong long addReplyReplicationBacklog(redisClient *c, long long offset) {\n    long long j, skip, len;\n\n    redisLog(REDIS_DEBUG, \"[PSYNC] Slave request offset: %lld\", offset);\n\n    if (server.repl_backlog_histlen == 0) {\n        redisLog(REDIS_DEBUG, \"[PSYNC] Backlog history len is zero\");\n        return 0;\n    }\n\n    redisLog(REDIS_DEBUG, \"[PSYNC] Backlog size: %lld\",\n             server.repl_backlog_size);\n    redisLog(REDIS_DEBUG, \"[PSYNC] First byte: %lld\",\n             server.repl_backlog_off);\n    redisLog(REDIS_DEBUG, \"[PSYNC] History len: %lld\",\n             server.repl_backlog_histlen);\n    redisLog(REDIS_DEBUG, \"[PSYNC] Current index: %lld\",\n             server.repl_backlog_idx);\n\n    /* Compute the amount of bytes we need to discard. */\n    skip = offset - server.repl_backlog_off;\n    redisLog(REDIS_DEBUG, \"[PSYNC] Skipping: %lld\", skip);\n\n    /* Point j to the oldest byte, that is actaully our\n     * server.repl_backlog_off byte. */\n    j = (server.repl_backlog_idx +\n        (server.repl_backlog_size-server.repl_backlog_histlen)) %\n        server.repl_backlog_size;\n    redisLog(REDIS_DEBUG, \"[PSYNC] Index of first byte: %lld\", j);\n\n    /* Discard the amount of data to seek to the specified 'offset'. */\n    j = (j + skip) % server.repl_backlog_size;\n\n    /* Feed slave with data. Since it is a circular buffer we have to\n     * split the reply in two parts if we are cross-boundary. */\n    len = server.repl_backlog_histlen - skip;\n    redisLog(REDIS_DEBUG, \"[PSYNC] Reply total length: %lld\", len);\n    while(len) {\n        long long thislen =\n            ((server.repl_backlog_size - j) < len) ?\n            (server.repl_backlog_size - j) : len;\n\n        redisLog(REDIS_DEBUG, \"[PSYNC] addReply() length: %lld\", thislen);\n        addReplySds(c,sdsnewlen(server.repl_backlog + j, thislen));\n        len -= thislen;\n        j = 0;\n    }\n    return server.repl_backlog_histlen - skip;\n}\n\n/* This function handles the PSYNC command from the point of view of a\n * master receiving a request for partial resynchronization.\n *\n * On success return REDIS_OK, otherwise REDIS_ERR is returned and we proceed\n * with the usual full resync. */\nint masterTryPartialResynchronization(redisClient *c) {\n    long long psync_offset, psync_len;\n    char *master_runid = c->argv[1]->ptr;\n    char buf[128];\n    int buflen;\n\n    /* Is the runid of this master the same advertised by the wannabe slave\n     * via PSYNC? If runid changed this master is a different instance and\n     * there is no way to continue. */\n    if (strcasecmp(master_runid, server.runid)) {\n        /* Run id \"?\" is used by slaves that want to force a full resync. */\n        if (master_runid[0] != '?') {\n            redisLog(REDIS_NOTICE,\"Partial resynchronization not accepted: \"\n                \"Runid mismatch (Client asked for '%s', I'm '%s')\",\n                master_runid, server.runid);\n        } else {\n            redisLog(REDIS_NOTICE,\"Full resync requested by slave %s\",\n                replicationGetSlaveName(c));\n        }\n        goto need_full_resync;\n    }\n\n    /* We still have the data our slave is asking for? */\n    if (getLongLongFromObjectOrReply(c,c->argv[2],&psync_offset,NULL) !=\n       REDIS_OK) goto need_full_resync;\n    if (!server.repl_backlog ||\n        psync_offset < server.repl_backlog_off ||\n        psync_offset > (server.repl_backlog_off + server.repl_backlog_histlen))\n    {\n        redisLog(REDIS_NOTICE,\n            \"Unable to partial resync with slave %s for lack of backlog (Slave request was: %lld).\", replicationGetSlaveName(c), psync_offset);\n        if (psync_offset > server.master_repl_offset) {\n            redisLog(REDIS_WARNING,\n                \"Warning: slave %s tried to PSYNC with an offset that is greater than the master replication offset.\", replicationGetSlaveName(c));\n        }\n        goto need_full_resync;\n    }\n\n    /* If we reached this point, we are able to perform a partial resync:\n     * 1) Set client state to make it a slave.\n     * 2) Inform the client we can continue with +CONTINUE\n     * 3) Send the backlog data (from the offset to the end) to the slave. */\n    c->flags |= REDIS_SLAVE;\n    c->replstate = REDIS_REPL_ONLINE;\n    c->repl_ack_time = server.unixtime;\n    c->repl_put_online_on_ack = 0;\n    listAddNodeTail(server.slaves,c);\n    /* We can't use the connection buffers since they are used to accumulate\n     * new commands at this stage. But we are sure the socket send buffer is\n     * empty so this write will never fail actually. */\n    buflen = snprintf(buf,sizeof(buf),\"+CONTINUE\\r\\n\");\n    if (write(c->fd,buf,buflen) != buflen) {\n        freeClientAsync(c);\n        return REDIS_OK;\n    }\n    psync_len = addReplyReplicationBacklog(c,psync_offset);\n    redisLog(REDIS_NOTICE,\n        \"Partial resynchronization request from %s accepted. Sending %lld bytes of backlog starting from offset %lld.\",\n            replicationGetSlaveName(c),\n            psync_len, psync_offset);\n    /* Note that we don't need to set the selected DB at server.slaveseldb\n     * to -1 to force the master to emit SELECT, since the slave already\n     * has this state from the previous connection with the master. */\n\n    refreshGoodSlavesCount();\n    return REDIS_OK; /* The caller can return, no full resync needed. */\n\nneed_full_resync:\n    /* We need a full resync for some reason... notify the client. */\n    psync_offset = server.master_repl_offset;\n    /* Add 1 to psync_offset if it the replication backlog does not exists\n     * as when it will be created later we'll increment the offset by one. */\n    if (server.repl_backlog == NULL) psync_offset++;\n    /* Again, we can't use the connection buffers (see above). */\n    buflen = snprintf(buf,sizeof(buf),\"+FULLRESYNC %s %lld\\r\\n\",\n                      server.runid,psync_offset);\n    if (write(c->fd,buf,buflen) != buflen) {\n        freeClientAsync(c);\n        return REDIS_OK;\n    }\n    return REDIS_ERR;\n}\n\n/* Start a BGSAVE for replication goals, which is, selecting the disk or\n * socket target depending on the configuration, and making sure that\n * the script cache is flushed before to start.\n *\n * Returns REDIS_OK on success or REDIS_ERR otherwise. */\nint startBgsaveForReplication(void) {\n    int retval;\n\n    redisLog(REDIS_NOTICE,\"Starting BGSAVE for SYNC with target: %s\",\n        server.repl_diskless_sync ? \"slaves sockets\" : \"disk\");\n\n    if (server.repl_diskless_sync)\n        retval = rdbSaveToSlavesSockets();\n    else\n        retval = rdbSaveBackground(server.rdb_filename);\n\n    /* Flush the script cache, since we need that slave differences are\n     * accumulated without requiring slaves to match our cached scripts. */\n    if (retval == REDIS_OK) replicationScriptCacheFlush();\n    return retval;\n}\n\n/* SYNC and PSYNC command implemenation. */\nvoid syncCommand(redisClient *c) {\n    /* ignore SYNC if already slave or in monitor mode */\n    if (c->flags & REDIS_SLAVE) return;\n\n    /* Refuse SYNC requests if we are a slave but the link with our master\n     * is not ok... */\n    if (server.masterhost && server.repl_state != REDIS_REPL_CONNECTED) {\n        addReplyError(c,\"Can't SYNC while not connected with my master\");\n        return;\n    }\n\n    /* SYNC can't be issued when the server has pending data to send to\n     * the client about already issued commands. We need a fresh reply\n     * buffer registering the differences between the BGSAVE and the current\n     * dataset, so that we can copy to other slaves if needed. */\n    if (listLength(c->reply) != 0 || c->bufpos != 0) {\n        addReplyError(c,\"SYNC and PSYNC are invalid with pending output\");\n        return;\n    }\n\n    redisLog(REDIS_NOTICE,\"Slave %s asks for synchronization\",\n        replicationGetSlaveName(c));\n\n    /* Try a partial resynchronization if this is a PSYNC command.\n     * If it fails, we continue with usual full resynchronization, however\n     * when this happens masterTryPartialResynchronization() already\n     * replied with:\n     *\n     * +FULLRESYNC <runid> <offset>\n     *\n     * So the slave knows the new runid and offset to try a PSYNC later\n     * if the connection with the master is lost. */\n    if (!strcasecmp(c->argv[0]->ptr,\"psync\")) {\n        if (masterTryPartialResynchronization(c) == REDIS_OK) {\n            server.stat_sync_partial_ok++;\n            return; /* No full resync needed, return. */\n        } else {\n            char *master_runid = c->argv[1]->ptr;\n\n            /* Increment stats for failed PSYNCs, but only if the\n             * runid is not \"?\", as this is used by slaves to force a full\n             * resync on purpose when they are not albe to partially\n             * resync. */\n            if (master_runid[0] != '?') server.stat_sync_partial_err++;\n        }\n    } else {\n        /* If a slave uses SYNC, we are dealing with an old implementation\n         * of the replication protocol (like redis-cli --slave). Flag the client\n         * so that we don't expect to receive REPLCONF ACK feedbacks. */\n        c->flags |= REDIS_PRE_PSYNC;\n    }\n\n    /* Full resynchronization. */\n    server.stat_sync_full++;\n\n    /* Here we need to check if there is a background saving operation\n     * in progress, or if it is required to start one */\n    if (server.rdb_child_pid != -1 &&\n        server.rdb_child_type == REDIS_RDB_CHILD_TYPE_DISK)\n    {\n        /* Ok a background save is in progress. Let's check if it is a good\n         * one for replication, i.e. if there is another slave that is\n         * registering differences since the server forked to save. */\n        redisClient *slave;\n        listNode *ln;\n        listIter li;\n\n        listRewind(server.slaves,&li);\n        while((ln = listNext(&li))) {\n            slave = ln->value;\n            if (slave->replstate == REDIS_REPL_WAIT_BGSAVE_END) break;\n        }\n        if (ln) {\n            /* Perfect, the server is already registering differences for\n             * another slave. Set the right state, and copy the buffer. */\n            copyClientOutputBuffer(c,slave);\n            c->replstate = REDIS_REPL_WAIT_BGSAVE_END;\n            redisLog(REDIS_NOTICE,\"Waiting for end of BGSAVE for SYNC\");\n        } else {\n            /* No way, we need to wait for the next BGSAVE in order to\n             * register differences. */\n            c->replstate = REDIS_REPL_WAIT_BGSAVE_START;\n            redisLog(REDIS_NOTICE,\"Waiting for next BGSAVE for SYNC\");\n        }\n    } else if (server.rdb_child_pid != -1 &&\n               server.rdb_child_type == REDIS_RDB_CHILD_TYPE_SOCKET)\n    {\n        /* There is an RDB child process but it is writing directly to\n         * children sockets. We need to wait for the next BGSAVE\n         * in order to synchronize. */\n        c->replstate = REDIS_REPL_WAIT_BGSAVE_START;\n        redisLog(REDIS_NOTICE,\"Waiting for next BGSAVE for SYNC\");\n    } else {\n        if (server.repl_diskless_sync) {\n            /* Diskless replication RDB child is created inside\n             * replicationCron() since we want to delay its start a\n             * few seconds to wait for more slaves to arrive. */\n            c->replstate = REDIS_REPL_WAIT_BGSAVE_START;\n            if (server.repl_diskless_sync_delay)\n                redisLog(REDIS_NOTICE,\"Delay next BGSAVE for SYNC\");\n        } else {\n            /* Ok we don't have a BGSAVE in progress, let's start one. */\n            if (startBgsaveForReplication() != REDIS_OK) {\n                redisLog(REDIS_NOTICE,\"Replication failed, can't BGSAVE\");\n                addReplyError(c,\"Unable to perform background save\");\n                return;\n            }\n            c->replstate = REDIS_REPL_WAIT_BGSAVE_END;\n        }\n    }\n\n    if (server.repl_disable_tcp_nodelay)\n        anetDisableTcpNoDelay(NULL, c->fd); /* Non critical if it fails. */\n    c->repldbfd = -1;\n    c->flags |= REDIS_SLAVE;\n    server.slaveseldb = -1; /* Force to re-emit the SELECT command. */\n    listAddNodeTail(server.slaves,c);\n    if (listLength(server.slaves) == 1 && server.repl_backlog == NULL)\n        createReplicationBacklog();\n    return;\n}\n\n/* REPLCONF <option> <value> <option> <value> ...\n * This command is used by a slave in order to configure the replication\n * process before starting it with the SYNC command.\n *\n * Currently the only use of this command is to communicate to the master\n * what is the listening port of the Slave redis instance, so that the\n * master can accurately list slaves and their listening ports in\n * the INFO output.\n *\n * In the future the same command can be used in order to configure\n * the replication to initiate an incremental replication instead of a\n * full resync. */\nvoid replconfCommand(redisClient *c) {\n    int j;\n\n    if ((c->argc % 2) == 0) {\n        /* Number of arguments must be odd to make sure that every\n         * option has a corresponding value. */\n        addReply(c,shared.syntaxerr);\n        return;\n    }\n\n    /* Process every option-value pair. */\n    for (j = 1; j < c->argc; j+=2) {\n        if (!strcasecmp(c->argv[j]->ptr,\"listening-port\")) {\n            long port;\n\n            if ((getLongFromObjectOrReply(c,c->argv[j+1],\n                    &port,NULL) != REDIS_OK))\n                return;\n            c->slave_listening_port = port;\n        } else if (!strcasecmp(c->argv[j]->ptr,\"ack\")) {\n            /* REPLCONF ACK is used by slave to inform the master the amount\n             * of replication stream that it processed so far. It is an\n             * internal only command that normal clients should never use. */\n            long long offset;\n\n            if (!(c->flags & REDIS_SLAVE)) return;\n            if ((getLongLongFromObject(c->argv[j+1], &offset) != REDIS_OK))\n                return;\n            if (offset > c->repl_ack_off)\n                c->repl_ack_off = offset;\n            c->repl_ack_time = server.unixtime;\n            /* If this was a diskless replication, we need to really put\n             * the slave online when the first ACK is received (which\n             * confirms slave is online and ready to get more data). */\n            if (c->repl_put_online_on_ack && c->replstate == REDIS_REPL_ONLINE)\n                putSlaveOnline(c);\n            /* Note: this command does not reply anything! */\n            return;\n        } else {\n            addReplyErrorFormat(c,\"Unrecognized REPLCONF option: %s\",\n                (char*)c->argv[j]->ptr);\n            return;\n        }\n    }\n    addReply(c,shared.ok);\n}\n\n/* This function puts a slave in the online state, and should be called just\n * after a slave received the RDB file for the initial synchronization, and\n * we are finally ready to send the incremental stream of commands.\n *\n * It does a few things:\n *\n * 1) Put the slave in ONLINE state.\n * 2) Make sure the writable event is re-installed, since calling the SYNC\n *    command disables it, so that we can accumulate output buffer without\n *    sending it to the slave.\n * 3) Update the count of good slaves. */\nvoid putSlaveOnline(redisClient *slave) {\n    slave->replstate = REDIS_REPL_ONLINE;\n    slave->repl_put_online_on_ack = 0;\n    slave->repl_ack_time = server.unixtime;\n    if (aeCreateFileEvent(server.el, slave->fd, AE_WRITABLE,\n        sendReplyToClient, slave) == AE_ERR) {\n        redisLog(REDIS_WARNING,\"Unable to register writable event for slave bulk transfer: %s\", strerror(errno));\n        freeClient(slave);\n        return;\n    }\n    refreshGoodSlavesCount();\n    redisLog(REDIS_NOTICE,\"Synchronization with slave %s succeeded\",\n        replicationGetSlaveName(slave));\n}\n\nvoid sendBulkToSlave(aeEventLoop *el, int fd, void *privdata, int mask) {\n    redisClient *slave = privdata;\n    REDIS_NOTUSED(el);\n    REDIS_NOTUSED(mask);\n    char buf[REDIS_IOBUF_LEN];\n    ssize_t nwritten, buflen;\n\n    /* Before sending the RDB file, we send the preamble as configured by the\n     * replication process. Currently the preamble is just the bulk count of\n     * the file in the form \"$<length>\\r\\n\". */\n    if (slave->replpreamble) {\n        nwritten = write(fd,slave->replpreamble,sdslen(slave->replpreamble));\n        if (nwritten == -1) {\n            redisLog(REDIS_VERBOSE,\"Write error sending RDB preamble to slave: %s\",\n                strerror(errno));\n            freeClient(slave);\n            return;\n        }\n        server.stat_net_output_bytes += nwritten;\n        sdsrange(slave->replpreamble,nwritten,-1);\n        if (sdslen(slave->replpreamble) == 0) {\n            sdsfree(slave->replpreamble);\n            slave->replpreamble = NULL;\n            /* fall through sending data. */\n        } else {\n            return;\n        }\n    }\n\n    /* If the preamble was already transfered, send the RDB bulk data. */\n    lseek(slave->repldbfd,slave->repldboff,SEEK_SET);\n    buflen = read(slave->repldbfd,buf,REDIS_IOBUF_LEN);\n    if (buflen <= 0) {\n        redisLog(REDIS_WARNING,\"Read error sending DB to slave: %s\",\n            (buflen == 0) ? \"premature EOF\" : strerror(errno));\n        freeClient(slave);\n        return;\n    }\n    if ((nwritten = write(fd,buf,buflen)) == -1) {\n        if (errno != EAGAIN) {\n            redisLog(REDIS_WARNING,\"Write error sending DB to slave: %s\",\n                strerror(errno));\n            freeClient(slave);\n        }\n        return;\n    }\n    slave->repldboff += nwritten;\n    server.stat_net_output_bytes += nwritten;\n    if (slave->repldboff == slave->repldbsize) {\n        close(slave->repldbfd);\n        slave->repldbfd = -1;\n        aeDeleteFileEvent(server.el,slave->fd,AE_WRITABLE);\n        putSlaveOnline(slave);\n    }\n}\n\n/* This function is called at the end of every background saving,\n * or when the replication RDB transfer strategy is modified from\n * disk to socket or the other way around.\n *\n * The goal of this function is to handle slaves waiting for a successful\n * background saving in order to perform non-blocking synchronization, and\n * to schedule a new BGSAVE if there are slaves that attached while a\n * BGSAVE was in progress, but it was not a good one for replication (no\n * other slave was accumulating differences).\n *\n * The argument bgsaveerr is REDIS_OK if the background saving succeeded\n * otherwise REDIS_ERR is passed to the function.\n * The 'type' argument is the type of the child that terminated\n * (if it had a disk or socket target). */\nvoid updateSlavesWaitingBgsave(int bgsaveerr, int type) {\n    listNode *ln;\n    int startbgsave = 0;\n    listIter li;\n\n    listRewind(server.slaves,&li);\n    while((ln = listNext(&li))) {\n        redisClient *slave = ln->value;\n\n        if (slave->replstate == REDIS_REPL_WAIT_BGSAVE_START) {\n            startbgsave = 1;\n            slave->replstate = REDIS_REPL_WAIT_BGSAVE_END;\n        } else if (slave->replstate == REDIS_REPL_WAIT_BGSAVE_END) {\n            struct redis_stat buf;\n\n            /* If this was an RDB on disk save, we have to prepare to send\n             * the RDB from disk to the slave socket. Otherwise if this was\n             * already an RDB -> Slaves socket transfer, used in the case of\n             * diskless replication, our work is trivial, we can just put\n             * the slave online. */\n            if (type == REDIS_RDB_CHILD_TYPE_SOCKET) {\n                redisLog(REDIS_NOTICE,\n                    \"Streamed RDB transfer with slave %s succeeded (socket). Waiting for REPLCONF ACK from slave to enable streaming\",\n                        replicationGetSlaveName(slave));\n                /* Note: we wait for a REPLCONF ACK message from slave in\n                 * order to really put it online (install the write handler\n                 * so that the accumulated data can be transfered). However\n                 * we change the replication state ASAP, since our slave\n                 * is technically online now. */\n                slave->replstate = REDIS_REPL_ONLINE;\n                slave->repl_put_online_on_ack = 1;\n                slave->repl_ack_time = server.unixtime;\n            } else {\n                if (bgsaveerr != REDIS_OK) {\n                    freeClient(slave);\n                    redisLog(REDIS_WARNING,\"SYNC failed. BGSAVE child returned an error\");\n                    continue;\n                }\n                if ((slave->repldbfd = open(server.rdb_filename,O_RDONLY)) == -1 ||\n                    redis_fstat(slave->repldbfd,&buf) == -1) {\n                    freeClient(slave);\n                    redisLog(REDIS_WARNING,\"SYNC failed. Can't open/stat DB after BGSAVE: %s\", strerror(errno));\n                    continue;\n                }\n                slave->repldboff = 0;\n                slave->repldbsize = buf.st_size;\n                slave->replstate = REDIS_REPL_SEND_BULK;\n                slave->replpreamble = sdscatprintf(sdsempty(),\"$%lld\\r\\n\",\n                    (unsigned long long) slave->repldbsize);\n\n                aeDeleteFileEvent(server.el,slave->fd,AE_WRITABLE);\n                if (aeCreateFileEvent(server.el, slave->fd, AE_WRITABLE, sendBulkToSlave, slave) == AE_ERR) {\n                    freeClient(slave);\n                    continue;\n                }\n            }\n        }\n    }\n    if (startbgsave) {\n        if (startBgsaveForReplication() != REDIS_OK) {\n            listIter li;\n\n            listRewind(server.slaves,&li);\n            redisLog(REDIS_WARNING,\"SYNC failed. BGSAVE failed\");\n            while((ln = listNext(&li))) {\n                redisClient *slave = ln->value;\n\n                if (slave->replstate == REDIS_REPL_WAIT_BGSAVE_START)\n                    freeClient(slave);\n            }\n        }\n    }\n}\n\n/* ----------------------------------- SLAVE -------------------------------- */\n\n/* Abort the async download of the bulk dataset while SYNC-ing with master */\nvoid replicationAbortSyncTransfer(void) {\n    redisAssert(server.repl_state == REDIS_REPL_TRANSFER);\n\n    aeDeleteFileEvent(server.el,server.repl_transfer_s,AE_READABLE);\n    close(server.repl_transfer_s);\n    close(server.repl_transfer_fd);\n    unlink(server.repl_transfer_tmpfile);\n    zfree(server.repl_transfer_tmpfile);\n    server.repl_state = REDIS_REPL_CONNECT;\n}\n\n/* Avoid the master to detect the slave is timing out while loading the\n * RDB file in initial synchronization. We send a single newline character\n * that is valid protocol but is guaranteed to either be sent entierly or\n * not, since the byte is indivisible.\n *\n * The function is called in two contexts: while we flush the current\n * data with emptyDb(), and while we load the new data received as an\n * RDB file from the master. */\nvoid replicationSendNewlineToMaster(void) {\n    static time_t newline_sent;\n    if (time(NULL) != newline_sent) {\n        newline_sent = time(NULL);\n        if (write(server.repl_transfer_s,\"\\n\",1) == -1) {\n            /* Pinging back in this stage is best-effort. */\n        }\n    }\n}\n\n/* Callback used by emptyDb() while flushing away old data to load\n * the new dataset received by the master. */\nvoid replicationEmptyDbCallback(void *privdata) {\n    REDIS_NOTUSED(privdata);\n    replicationSendNewlineToMaster();\n}\n\n/* Asynchronously read the SYNC payload we receive from a master */\n#define REPL_MAX_WRITTEN_BEFORE_FSYNC (1024*1024*8) /* 8 MB */\nvoid readSyncBulkPayload(aeEventLoop *el, int fd, void *privdata, int mask) {\n    char buf[4096];\n    ssize_t nread, readlen;\n    off_t left;\n    REDIS_NOTUSED(el);\n    REDIS_NOTUSED(privdata);\n    REDIS_NOTUSED(mask);\n\n    /* Static vars used to hold the EOF mark, and the last bytes received\n     * form the server: when they match, we reached the end of the transfer. */\n    static char eofmark[REDIS_RUN_ID_SIZE];\n    static char lastbytes[REDIS_RUN_ID_SIZE];\n    static int usemark = 0;\n\n    /* If repl_transfer_size == -1 we still have to read the bulk length\n     * from the master reply. */\n    if (server.repl_transfer_size == -1) {\n        if (syncReadLine(fd,buf,1024,server.repl_syncio_timeout*1000) == -1) {\n            redisLog(REDIS_WARNING,\n                \"I/O error reading bulk count from MASTER: %s\",\n                strerror(errno));\n            goto error;\n        }\n\n        if (buf[0] == '-') {\n            redisLog(REDIS_WARNING,\n                \"MASTER aborted replication with an error: %s\",\n                buf+1);\n            goto error;\n        } else if (buf[0] == '\\0') {\n            /* At this stage just a newline works as a PING in order to take\n             * the connection live. So we refresh our last interaction\n             * timestamp. */\n            server.repl_transfer_lastio = server.unixtime;\n            return;\n        } else if (buf[0] != '$') {\n            redisLog(REDIS_WARNING,\"Bad protocol from MASTER, the first byte is not '$' (we received '%s'), are you sure the host and port are right?\", buf);\n            goto error;\n        }\n\n        /* There are two possible forms for the bulk payload. One is the\n         * usual $<count> bulk format. The other is used for diskless transfers\n         * when the master does not know beforehand the size of the file to\n         * transfer. In the latter case, the following format is used:\n         *\n         * $EOF:<40 bytes delimiter>\n         *\n         * At the end of the file the announced delimiter is transmitted. The\n         * delimiter is long and random enough that the probability of a\n         * collision with the actual file content can be ignored. */\n        if (strncmp(buf+1,\"EOF:\",4) == 0 && strlen(buf+5) >= REDIS_RUN_ID_SIZE) {\n            usemark = 1;\n            memcpy(eofmark,buf+5,REDIS_RUN_ID_SIZE);\n            memset(lastbytes,0,REDIS_RUN_ID_SIZE);\n            /* Set any repl_transfer_size to avoid entering this code path\n             * at the next call. */\n            server.repl_transfer_size = 0;\n            redisLog(REDIS_NOTICE,\n                \"MASTER <-> SLAVE sync: receiving streamed RDB from master\");\n        } else {\n            usemark = 0;\n            server.repl_transfer_size = strtol(buf+1,NULL,10);\n            redisLog(REDIS_NOTICE,\n                \"MASTER <-> SLAVE sync: receiving %lld bytes from master\",\n                (long long) server.repl_transfer_size);\n        }\n        return;\n    }\n\n    /* Read bulk data */\n    if (usemark) {\n        readlen = sizeof(buf);\n    } else {\n        left = server.repl_transfer_size - server.repl_transfer_read;\n        readlen = (left < (signed)sizeof(buf)) ? left : (signed)sizeof(buf);\n    }\n\n    nread = read(fd,buf,readlen);\n    if (nread <= 0) {\n        redisLog(REDIS_WARNING,\"I/O error trying to sync with MASTER: %s\",\n            (nread == -1) ? strerror(errno) : \"connection lost\");\n        replicationAbortSyncTransfer();\n        return;\n    }\n    server.stat_net_input_bytes += nread;\n\n    /* When a mark is used, we want to detect EOF asap in order to avoid\n     * writing the EOF mark into the file... */\n    int eof_reached = 0;\n\n    if (usemark) {\n        /* Update the last bytes array, and check if it matches our delimiter.*/\n        if (nread >= REDIS_RUN_ID_SIZE) {\n            memcpy(lastbytes,buf+nread-REDIS_RUN_ID_SIZE,REDIS_RUN_ID_SIZE);\n        } else {\n            int rem = REDIS_RUN_ID_SIZE-nread;\n            memmove(lastbytes,lastbytes+nread,rem);\n            memcpy(lastbytes+rem,buf,nread);\n        }\n        if (memcmp(lastbytes,eofmark,REDIS_RUN_ID_SIZE) == 0) eof_reached = 1;\n    }\n\n    server.repl_transfer_lastio = server.unixtime;\n    if (write(server.repl_transfer_fd,buf,nread) != nread) {\n        redisLog(REDIS_WARNING,\"Write error or short write writing to the DB dump file needed for MASTER <-> SLAVE synchronization: %s\", strerror(errno));\n        goto error;\n    }\n    server.repl_transfer_read += nread;\n\n    /* Delete the last 40 bytes from the file if we reached EOF. */\n    if (usemark && eof_reached) {\n        if (ftruncate(server.repl_transfer_fd,\n            server.repl_transfer_read - REDIS_RUN_ID_SIZE) == -1)\n        {\n            redisLog(REDIS_WARNING,\"Error truncating the RDB file received from the master for SYNC: %s\", strerror(errno));\n            goto error;\n        }\n    }\n\n    /* Sync data on disk from time to time, otherwise at the end of the transfer\n     * we may suffer a big delay as the memory buffers are copied into the\n     * actual disk. */\n    if (server.repl_transfer_read >=\n        server.repl_transfer_last_fsync_off + REPL_MAX_WRITTEN_BEFORE_FSYNC)\n    {\n        off_t sync_size = server.repl_transfer_read -\n                          server.repl_transfer_last_fsync_off;\n        rdb_fsync_range(server.repl_transfer_fd,\n            server.repl_transfer_last_fsync_off, sync_size);\n        server.repl_transfer_last_fsync_off += sync_size;\n    }\n\n    /* Check if the transfer is now complete */\n    if (!usemark) {\n        if (server.repl_transfer_read == server.repl_transfer_size)\n            eof_reached = 1;\n    }\n\n    if (eof_reached) {\n        if (rename(server.repl_transfer_tmpfile,server.rdb_filename) == -1) {\n            redisLog(REDIS_WARNING,\"Failed trying to rename the temp DB into dump.rdb in MASTER <-> SLAVE synchronization: %s\", strerror(errno));\n            replicationAbortSyncTransfer();\n            return;\n        }\n        redisLog(REDIS_NOTICE, \"MASTER <-> SLAVE sync: Flushing old data\");\n        signalFlushedDb(-1);\n        emptyDb(replicationEmptyDbCallback);\n        /* Before loading the DB into memory we need to delete the readable\n         * handler, otherwise it will get called recursively since\n         * rdbLoad() will call the event loop to process events from time to\n         * time for non blocking loading. */\n        aeDeleteFileEvent(server.el,server.repl_transfer_s,AE_READABLE);\n        redisLog(REDIS_NOTICE, \"MASTER <-> SLAVE sync: Loading DB in memory\");\n        if (rdbLoad(server.rdb_filename) != REDIS_OK) {\n            redisLog(REDIS_WARNING,\"Failed trying to load the MASTER synchronization DB from disk\");\n            replicationAbortSyncTransfer();\n            return;\n        }\n        /* Final setup of the connected slave <- master link */\n        zfree(server.repl_transfer_tmpfile);\n        close(server.repl_transfer_fd);\n        server.master = createClient(server.repl_transfer_s);\n        server.master->flags |= REDIS_MASTER;\n        server.master->authenticated = 1;\n        server.repl_state = REDIS_REPL_CONNECTED;\n        server.master->reploff = server.repl_master_initial_offset;\n        memcpy(server.master->replrunid, server.repl_master_runid,\n            sizeof(server.repl_master_runid));\n        /* If master offset is set to -1, this master is old and is not\n         * PSYNC capable, so we flag it accordingly. */\n        if (server.master->reploff == -1)\n            server.master->flags |= REDIS_PRE_PSYNC;\n        redisLog(REDIS_NOTICE, \"MASTER <-> SLAVE sync: Finished with success\");\n        /* Restart the AOF subsystem now that we finished the sync. This\n         * will trigger an AOF rewrite, and when done will start appending\n         * to the new file. */\n        if (server.aof_state != REDIS_AOF_OFF) {\n            int retry = 10;\n\n            stopAppendOnly();\n            while (retry-- && startAppendOnly() == REDIS_ERR) {\n                redisLog(REDIS_WARNING,\"Failed enabling the AOF after successful master synchronization! Trying it again in one second.\");\n                sleep(1);\n            }\n            if (!retry) {\n                redisLog(REDIS_WARNING,\"FATAL: this slave instance finished the synchronization with its master, but the AOF can't be turned on. Exiting now.\");\n                exit(1);\n            }\n        }\n    }\n\n    return;\n\nerror:\n    replicationAbortSyncTransfer();\n    return;\n}\n\n/* Send a synchronous command to the master. Used to send AUTH and\n * REPLCONF commands before starting the replication with SYNC.\n *\n * The command returns an sds string representing the result of the\n * operation. On error the first byte is a \"-\".\n */\nchar *sendSynchronousCommand(int fd, ...) {\n    va_list ap;\n    sds cmd = sdsempty();\n    char *arg, buf[256];\n\n    /* Create the command to send to the master, we use simple inline\n     * protocol for simplicity as currently we only send simple strings. */\n    va_start(ap,fd);\n    while(1) {\n        arg = va_arg(ap, char*);\n        if (arg == NULL) break;\n\n        if (sdslen(cmd) != 0) cmd = sdscatlen(cmd,\" \",1);\n        cmd = sdscat(cmd,arg);\n    }\n    cmd = sdscatlen(cmd,\"\\r\\n\",2);\n\n    /* Transfer command to the server. */\n    if (syncWrite(fd,cmd,sdslen(cmd),server.repl_syncio_timeout*1000) == -1) {\n        sdsfree(cmd);\n        return sdscatprintf(sdsempty(),\"-Writing to master: %s\",\n                strerror(errno));\n    }\n    sdsfree(cmd);\n\n    /* Read the reply from the server. */\n    if (syncReadLine(fd,buf,sizeof(buf),server.repl_syncio_timeout*1000) == -1)\n    {\n        return sdscatprintf(sdsempty(),\"-Reading from master: %s\",\n                strerror(errno));\n    }\n    return sdsnew(buf);\n}\n\n/* Try a partial resynchronization with the master if we are about to reconnect.\n * If there is no cached master structure, at least try to issue a\n * \"PSYNC ? -1\" command in order to trigger a full resync using the PSYNC\n * command in order to obtain the master run id and the master replication\n * global offset.\n *\n * This function is designed to be called from syncWithMaster(), so the\n * following assumptions are made:\n *\n * 1) We pass the function an already connected socket \"fd\".\n * 2) This function does not close the file descriptor \"fd\". However in case\n *    of successful partial resynchronization, the function will reuse\n *    'fd' as file descriptor of the server.master client structure.\n *\n * The function returns:\n *\n * PSYNC_CONTINUE: If the PSYNC command succeded and we can continue.\n * PSYNC_FULLRESYNC: If PSYNC is supported but a full resync is needed.\n *                   In this case the master run_id and global replication\n *                   offset is saved.\n * PSYNC_NOT_SUPPORTED: If the server does not understand PSYNC at all and\n *                      the caller should fall back to SYNC.\n */\n\n#define PSYNC_CONTINUE 0\n#define PSYNC_FULLRESYNC 1\n#define PSYNC_NOT_SUPPORTED 2\nint slaveTryPartialResynchronization(int fd) {\n    char *psync_runid;\n    char psync_offset[32];\n    sds reply;\n\n    /* Initially set repl_master_initial_offset to -1 to mark the current\n     * master run_id and offset as not valid. Later if we'll be able to do\n     * a FULL resync using the PSYNC command we'll set the offset at the\n     * right value, so that this information will be propagated to the\n     * client structure representing the master into server.master. */\n    server.repl_master_initial_offset = -1;\n\n    if (server.cached_master) {\n        psync_runid = server.cached_master->replrunid;\n        snprintf(psync_offset,sizeof(psync_offset),\"%lld\", server.cached_master->reploff+1);\n        redisLog(REDIS_NOTICE,\"Trying a partial resynchronization (request %s:%s).\", psync_runid, psync_offset);\n    } else {\n        redisLog(REDIS_NOTICE,\"Partial resynchronization not possible (no cached master)\");\n        psync_runid = \"?\";\n        memcpy(psync_offset,\"-1\",3);\n    }\n\n    /* Issue the PSYNC command */\n    reply = sendSynchronousCommand(fd,\"PSYNC\",psync_runid,psync_offset,NULL);\n\n    if (!strncmp(reply,\"+FULLRESYNC\",11)) {\n        char *runid = NULL, *offset = NULL;\n\n        /* FULL RESYNC, parse the reply in order to extract the run id\n         * and the replication offset. */\n        runid = strchr(reply,' ');\n        if (runid) {\n            runid++;\n            offset = strchr(runid,' ');\n            if (offset) offset++;\n        }\n        if (!runid || !offset || (offset-runid-1) != REDIS_RUN_ID_SIZE) {\n            redisLog(REDIS_WARNING,\n                \"Master replied with wrong +FULLRESYNC syntax.\");\n            /* This is an unexpected condition, actually the +FULLRESYNC\n             * reply means that the master supports PSYNC, but the reply\n             * format seems wrong. To stay safe we blank the master\n             * runid to make sure next PSYNCs will fail. */\n            memset(server.repl_master_runid,0,REDIS_RUN_ID_SIZE+1);\n        } else {\n            memcpy(server.repl_master_runid, runid, offset-runid-1);\n            server.repl_master_runid[REDIS_RUN_ID_SIZE] = '\\0';\n            server.repl_master_initial_offset = strtoll(offset,NULL,10);\n            redisLog(REDIS_NOTICE,\"Full resync from master: %s:%lld\",\n                server.repl_master_runid,\n                server.repl_master_initial_offset);\n        }\n        /* We are going to full resync, discard the cached master structure. */\n        replicationDiscardCachedMaster();\n        sdsfree(reply);\n        return PSYNC_FULLRESYNC;\n    }\n\n    if (!strncmp(reply,\"+CONTINUE\",9)) {\n        /* Partial resync was accepted, set the replication state accordingly */\n        redisLog(REDIS_NOTICE,\n            \"Successful partial resynchronization with master.\");\n        sdsfree(reply);\n        replicationResurrectCachedMaster(fd);\n        return PSYNC_CONTINUE;\n    }\n\n    /* If we reach this point we receied either an error since the master does\n     * not understand PSYNC, or an unexpected reply from the master.\n     * Return PSYNC_NOT_SUPPORTED to the caller in both cases. */\n\n    if (strncmp(reply,\"-ERR\",4)) {\n        /* If it's not an error, log the unexpected event. */\n        redisLog(REDIS_WARNING,\n            \"Unexpected reply to PSYNC from master: %s\", reply);\n    } else {\n        redisLog(REDIS_NOTICE,\n            \"Master does not support PSYNC or is in \"\n            \"error state (reply: %s)\", reply);\n    }\n    sdsfree(reply);\n    replicationDiscardCachedMaster();\n    return PSYNC_NOT_SUPPORTED;\n}\n\nvoid syncWithMaster(aeEventLoop *el, int fd, void *privdata, int mask) {\n    char tmpfile[256], *err;\n    int dfd, maxtries = 5;\n    int sockerr = 0, psync_result;\n    socklen_t errlen = sizeof(sockerr);\n    REDIS_NOTUSED(el);\n    REDIS_NOTUSED(privdata);\n    REDIS_NOTUSED(mask);\n\n    /* If this event fired after the user turned the instance into a master\n     * with SLAVEOF NO ONE we must just return ASAP. */\n    if (server.repl_state == REDIS_REPL_NONE) {\n        close(fd);\n        return;\n    }\n\n    /* Check for errors in the socket. */\n    if (getsockopt(fd, SOL_SOCKET, SO_ERROR, &sockerr, &errlen) == -1)\n        sockerr = errno;\n    if (sockerr) {\n        aeDeleteFileEvent(server.el,fd,AE_READABLE|AE_WRITABLE);\n        redisLog(REDIS_WARNING,\"Error condition on socket for SYNC: %s\",\n            strerror(sockerr));\n        goto error;\n    }\n\n    /* If we were connecting, it's time to send a non blocking PING, we want to\n     * make sure the master is able to reply before going into the actual\n     * replication process where we have long timeouts in the order of\n     * seconds (in the meantime the slave would block). */\n    if (server.repl_state == REDIS_REPL_CONNECTING) {\n        redisLog(REDIS_NOTICE,\"Non blocking connect for SYNC fired the event.\");\n        /* Delete the writable event so that the readable event remains\n         * registered and we can wait for the PONG reply. */\n        aeDeleteFileEvent(server.el,fd,AE_WRITABLE);\n        server.repl_state = REDIS_REPL_RECEIVE_PONG;\n        /* Send the PING, don't check for errors at all, we have the timeout\n         * that will take care about this. */\n        syncWrite(fd,\"PING\\r\\n\",6,100);\n        return;\n    }\n\n    /* Receive the PONG command. */\n    if (server.repl_state == REDIS_REPL_RECEIVE_PONG) {\n        char buf[1024];\n\n        /* Delete the readable event, we no longer need it now that there is\n         * the PING reply to read. */\n        aeDeleteFileEvent(server.el,fd,AE_READABLE);\n\n        /* Read the reply with explicit timeout. */\n        buf[0] = '\\0';\n        if (syncReadLine(fd,buf,sizeof(buf),\n            server.repl_syncio_timeout*1000) == -1)\n        {\n            redisLog(REDIS_WARNING,\n                \"I/O error reading PING reply from master: %s\",\n                strerror(errno));\n            goto error;\n        }\n\n        /* We accept only two replies as valid, a positive +PONG reply\n         * (we just check for \"+\") or an authentication error.\n         * Note that older versions of Redis replied with \"operation not\n         * permitted\" instead of using a proper error code, so we test\n         * both. */\n        if (buf[0] != '+' &&\n            strncmp(buf,\"-NOAUTH\",7) != 0 &&\n            strncmp(buf,\"-ERR operation not permitted\",28) != 0)\n        {\n            redisLog(REDIS_WARNING,\"Error reply to PING from master: '%s'\",buf);\n            goto error;\n        } else {\n            redisLog(REDIS_NOTICE,\n                \"Master replied to PING, replication can continue...\");\n        }\n    }\n\n    /* AUTH with the master if required. */\n    if(server.masterauth) {\n        err = sendSynchronousCommand(fd,\"AUTH\",server.masterauth,NULL);\n        if (err[0] == '-') {\n            redisLog(REDIS_WARNING,\"Unable to AUTH to MASTER: %s\",err);\n            sdsfree(err);\n            goto error;\n        }\n        sdsfree(err);\n    }\n\n    /* Set the slave port, so that Master's INFO command can list the\n     * slave listening port correctly. */\n    {\n        sds port = sdsfromlonglong(server.port);\n        err = sendSynchronousCommand(fd,\"REPLCONF\",\"listening-port\",port,\n                                         NULL);\n        sdsfree(port);\n        /* Ignore the error if any, not all the Redis versions support\n         * REPLCONF listening-port. */\n        if (err[0] == '-') {\n            redisLog(REDIS_NOTICE,\"(Non critical) Master does not understand REPLCONF listening-port: %s\", err);\n        }\n        sdsfree(err);\n    }\n\n    /* Try a partial resynchonization. If we don't have a cached master\n     * slaveTryPartialResynchronization() will at least try to use PSYNC\n     * to start a full resynchronization so that we get the master run id\n     * and the global offset, to try a partial resync at the next\n     * reconnection attempt. */\n    psync_result = slaveTryPartialResynchronization(fd);\n    if (psync_result == PSYNC_CONTINUE) {\n        redisLog(REDIS_NOTICE, \"MASTER <-> SLAVE sync: Master accepted a Partial Resynchronization.\");\n        return;\n    }\n\n    /* Fall back to SYNC if needed. Otherwise psync_result == PSYNC_FULLRESYNC\n     * and the server.repl_master_runid and repl_master_initial_offset are\n     * already populated. */\n    if (psync_result == PSYNC_NOT_SUPPORTED) {\n        redisLog(REDIS_NOTICE,\"Retrying with SYNC...\");\n        if (syncWrite(fd,\"SYNC\\r\\n\",6,server.repl_syncio_timeout*1000) == -1) {\n            redisLog(REDIS_WARNING,\"I/O error writing to MASTER: %s\",\n                strerror(errno));\n            goto error;\n        }\n    }\n\n    /* Prepare a suitable temp file for bulk transfer */\n    while(maxtries--) {\n        snprintf(tmpfile,256,\n            \"temp-%d.%ld.rdb\",(int)server.unixtime,(long int)getpid());\n        dfd = open(tmpfile,O_CREAT|O_WRONLY|O_EXCL,0644);\n        if (dfd != -1) break;\n        sleep(1);\n    }\n    if (dfd == -1) {\n        redisLog(REDIS_WARNING,\"Opening the temp file needed for MASTER <-> SLAVE synchronization: %s\",strerror(errno));\n        goto error;\n    }\n\n    /* Setup the non blocking download of the bulk file. */\n    if (aeCreateFileEvent(server.el,fd, AE_READABLE,readSyncBulkPayload,NULL)\n            == AE_ERR)\n    {\n        redisLog(REDIS_WARNING,\n            \"Can't create readable event for SYNC: %s (fd=%d)\",\n            strerror(errno),fd);\n        goto error;\n    }\n\n    server.repl_state = REDIS_REPL_TRANSFER;\n    server.repl_transfer_size = -1;\n    server.repl_transfer_read = 0;\n    server.repl_transfer_last_fsync_off = 0;\n    server.repl_transfer_fd = dfd;\n    server.repl_transfer_lastio = server.unixtime;\n    server.repl_transfer_tmpfile = zstrdup(tmpfile);\n    return;\n\nerror:\n    close(fd);\n    server.repl_transfer_s = -1;\n    server.repl_state = REDIS_REPL_CONNECT;\n    return;\n}\n\nint connectWithMaster(void) {\n    int fd;\n\n    fd = anetTcpNonBlockConnect(NULL,server.masterhost,server.masterport);\n    if (fd == -1) {\n        redisLog(REDIS_WARNING,\"Unable to connect to MASTER: %s\",\n            strerror(errno));\n        return REDIS_ERR;\n    }\n\n    if (aeCreateFileEvent(server.el,fd,AE_READABLE|AE_WRITABLE,syncWithMaster,NULL) ==\n            AE_ERR)\n    {\n        close(fd);\n        redisLog(REDIS_WARNING,\"Can't create readable event for SYNC\");\n        return REDIS_ERR;\n    }\n\n    server.repl_transfer_lastio = server.unixtime;\n    server.repl_transfer_s = fd;\n    server.repl_state = REDIS_REPL_CONNECTING;\n    return REDIS_OK;\n}\n\n/* This function can be called when a non blocking connection is currently\n * in progress to undo it. */\nvoid undoConnectWithMaster(void) {\n    int fd = server.repl_transfer_s;\n\n    redisAssert(server.repl_state == REDIS_REPL_CONNECTING ||\n                server.repl_state == REDIS_REPL_RECEIVE_PONG);\n    aeDeleteFileEvent(server.el,fd,AE_READABLE|AE_WRITABLE);\n    close(fd);\n    server.repl_transfer_s = -1;\n    server.repl_state = REDIS_REPL_CONNECT;\n}\n\n/* This function aborts a non blocking replication attempt if there is one\n * in progress, by canceling the non-blocking connect attempt or\n * the initial bulk transfer.\n *\n * If there was a replication handshake in progress 1 is returned and\n * the replication state (server.repl_state) set to REDIS_REPL_CONNECT.\n *\n * Otherwise zero is returned and no operation is perforemd at all. */\nint cancelReplicationHandshake(void) {\n    if (server.repl_state == REDIS_REPL_TRANSFER) {\n        replicationAbortSyncTransfer();\n    } else if (server.repl_state == REDIS_REPL_CONNECTING ||\n             server.repl_state == REDIS_REPL_RECEIVE_PONG)\n    {\n        undoConnectWithMaster();\n    } else {\n        return 0;\n    }\n    return 1;\n}\n\n/* Mass-unblock clients because something changed in the instance that makes\n * blocking no longer safe. For example clients blocked in list operations\n * in an instance which turns from master to slave is unsafe, so this function\n * is called when a master turns into a slave.\n *\n * The semantics is to send an -UNBLOCKED error to the client, disconnecting\n * it at the same time. */\nvoid disconnectAllBlockedClients(void) {\n    listNode *ln;\n    listIter li;\n\n    listRewind(server.clients,&li);\n    while((ln = listNext(&li))) {\n        redisClient *c = listNodeValue(ln);\n\n        if (c->flags & REDIS_BLOCKED) {\n            addReplySds(c,sdsnew(\n                \"-UNBLOCKED force unblock from blocking operation, \"\n                \"instance state changed (master -> slave?)\\r\\n\"));\n            unblockClientWaitingData(c);\n            c->flags |= REDIS_CLOSE_AFTER_REPLY;\n        }\n    }\n}\n\n/* Set replication to the specified master address and port. */\nvoid replicationSetMaster(char *ip, int port) {\n    sdsfree(server.masterhost);\n    server.masterhost = sdsdup(ip);\n    server.masterport = port;\n    if (server.master) freeClient(server.master);\n    disconnectAllBlockedClients(); /* Clients blocked in master, now slave. */\n    disconnectSlaves(); /* Force our slaves to resync with us as well. */\n    replicationDiscardCachedMaster(); /* Don't try a PSYNC. */\n    freeReplicationBacklog(); /* Don't allow our chained slaves to PSYNC. */\n    cancelReplicationHandshake();\n    server.repl_state = REDIS_REPL_CONNECT;\n    server.master_repl_offset = 0;\n}\n\n/* Cancel replication, setting the instance as a master itself. */\nvoid replicationUnsetMaster(void) {\n    if (server.masterhost == NULL) return; /* Nothing to do. */\n    sdsfree(server.masterhost);\n    server.masterhost = NULL;\n    if (server.master) {\n        if (listLength(server.slaves) == 0) {\n            /* If this instance is turned into a master and there are no\n             * slaves, it inherits the replication offset from the master.\n             * Under certain conditions this makes replicas comparable by\n             * replication offset to understand what is the most updated. */\n            server.master_repl_offset = server.master->reploff;\n            freeReplicationBacklog();\n        }\n        freeClient(server.master);\n    }\n    replicationDiscardCachedMaster();\n    cancelReplicationHandshake();\n    server.repl_state = REDIS_REPL_NONE;\n}\n\nvoid slaveofCommand(redisClient *c) {\n    if (!strcasecmp(c->argv[1]->ptr,\"no\") &&\n        !strcasecmp(c->argv[2]->ptr,\"one\")) {\n        if (server.masterhost) {\n            replicationUnsetMaster();\n            redisLog(REDIS_NOTICE,\"MASTER MODE enabled (user request)\");\n        }\n    } else {\n        long port;\n\n        if ((getLongFromObjectOrReply(c, c->argv[2], &port, NULL) != REDIS_OK))\n            return;\n\n        /* Check if we are already attached to the specified slave */\n        if (server.masterhost && !strcasecmp(server.masterhost,c->argv[1]->ptr)\n            && server.masterport == port) {\n            redisLog(REDIS_NOTICE,\"SLAVE OF would result into synchronization with the master we are already connected with. No operation performed.\");\n            addReplySds(c,sdsnew(\"+OK Already connected to specified master\\r\\n\"));\n            return;\n        }\n        /* There was no previous master or the user specified a different one,\n         * we can continue. */\n        replicationSetMaster(c->argv[1]->ptr, port);\n        redisLog(REDIS_NOTICE,\"SLAVE OF %s:%d enabled (user request)\",\n            server.masterhost, server.masterport);\n    }\n    addReply(c,shared.ok);\n}\n\n/* ROLE command: provide information about the role of the instance\n * (master or slave) and additional information related to replication\n * in an easy to process format. */\nvoid roleCommand(redisClient *c) {\n    if (server.masterhost == NULL) {\n        listIter li;\n        listNode *ln;\n        void *mbcount;\n        int slaves = 0;\n\n        addReplyMultiBulkLen(c,3);\n        addReplyBulkCBuffer(c,\"master\",6);\n        addReplyLongLong(c,server.master_repl_offset);\n        mbcount = addDeferredMultiBulkLength(c);\n        listRewind(server.slaves,&li);\n        while((ln = listNext(&li))) {\n            redisClient *slave = ln->value;\n            char ip[REDIS_IP_STR_LEN];\n\n            if (anetPeerToString(slave->fd,ip,sizeof(ip),NULL) == -1) continue;\n            if (slave->replstate != REDIS_REPL_ONLINE) continue;\n            addReplyMultiBulkLen(c,3);\n            addReplyBulkCString(c,ip);\n            addReplyBulkLongLong(c,slave->slave_listening_port);\n            addReplyBulkLongLong(c,slave->repl_ack_off);\n            slaves++;\n        }\n        setDeferredMultiBulkLength(c,mbcount,slaves);\n    } else {\n        char *slavestate = NULL;\n\n        addReplyMultiBulkLen(c,5);\n        addReplyBulkCBuffer(c,\"slave\",5);\n        addReplyBulkCString(c,server.masterhost);\n        addReplyLongLong(c,server.masterport);\n        switch(server.repl_state) {\n        case REDIS_REPL_NONE: slavestate = \"none\"; break;\n        case REDIS_REPL_CONNECT: slavestate = \"connect\"; break;\n        case REDIS_REPL_CONNECTING: slavestate = \"connecting\"; break;\n        case REDIS_REPL_RECEIVE_PONG: /* see next */\n        case REDIS_REPL_TRANSFER: slavestate = \"sync\"; break;\n        case REDIS_REPL_CONNECTED: slavestate = \"connected\"; break;\n        default: slavestate = \"unknown\"; break;\n        }\n        addReplyBulkCString(c,slavestate);\n        addReplyLongLong(c,server.master ? server.master->reploff : -1);\n    }\n}\n\n/* Send a REPLCONF ACK command to the master to inform it about the current\n * processed offset. If we are not connected with a master, the command has\n * no effects. */\nvoid replicationSendAck(void) {\n    redisClient *c = server.master;\n\n    if (c != NULL) {\n        c->flags |= REDIS_MASTER_FORCE_REPLY;\n        addReplyMultiBulkLen(c,3);\n        addReplyBulkCString(c,\"REPLCONF\");\n        addReplyBulkCString(c,\"ACK\");\n        addReplyBulkLongLong(c,c->reploff);\n        c->flags &= ~REDIS_MASTER_FORCE_REPLY;\n    }\n}\n\n/* ---------------------- MASTER CACHING FOR PSYNC -------------------------- */\n\n/* In order to implement partial synchronization we need to be able to cache\n * our master's client structure after a transient disconnection.\n * It is cached into server.cached_master and flushed away using the following\n * functions. */\n\n/* This function is called by freeClient() in order to cache the master\n * client structure instead of destryoing it. freeClient() will return\n * ASAP after this function returns, so every action needed to avoid problems\n * with a client that is really \"suspended\" has to be done by this function.\n *\n * The other functions that will deal with the cached master are:\n *\n * replicationDiscardCachedMaster() that will make sure to kill the client\n * as for some reason we don't want to use it in the future.\n *\n * replicationResurrectCachedMaster() that is used after a successful PSYNC\n * handshake in order to reactivate the cached master.\n */\nvoid replicationCacheMaster(redisClient *c) {\n    listNode *ln;\n\n    redisAssert(server.master != NULL && server.cached_master == NULL);\n    redisLog(REDIS_NOTICE,\"Caching the disconnected master state.\");\n\n    /* Remove from the list of clients, we don't want this client to be\n     * listed by CLIENT LIST or processed in any way by batch operations. */\n    ln = listSearchKey(server.clients,c);\n    redisAssert(ln != NULL);\n    listDelNode(server.clients,ln);\n\n    /* Save the master. Server.master will be set to null later by\n     * replicationHandleMasterDisconnection(). */\n    server.cached_master = server.master;\n\n    /* Remove the event handlers and close the socket. We'll later reuse\n     * the socket of the new connection with the master during PSYNC. */\n    aeDeleteFileEvent(server.el,c->fd,AE_READABLE);\n    aeDeleteFileEvent(server.el,c->fd,AE_WRITABLE);\n    close(c->fd);\n\n    /* Set fd to -1 so that we can safely call freeClient(c) later. */\n    c->fd = -1;\n\n    /* Invalidate the Peer ID cache. */\n    if (c->peerid) {\n        sdsfree(c->peerid);\n        c->peerid = NULL;\n    }\n\n    /* Caching the master happens instead of the actual freeClient() call,\n     * so make sure to adjust the replication state. This function will\n     * also set server.master to NULL. */\n    replicationHandleMasterDisconnection();\n}\n\n/* Free a cached master, called when there are no longer the conditions for\n * a partial resync on reconnection. */\nvoid replicationDiscardCachedMaster(void) {\n    if (server.cached_master == NULL) return;\n\n    redisLog(REDIS_NOTICE,\"Discarding previously cached master state.\");\n    server.cached_master->flags &= ~REDIS_MASTER;\n    freeClient(server.cached_master);\n    server.cached_master = NULL;\n}\n\n/* Turn the cached master into the current master, using the file descriptor\n * passed as argument as the socket for the new master.\n *\n * This function is called when successfully setup a partial resynchronization\n * so the stream of data that we'll receive will start from were this\n * master left. */\nvoid replicationResurrectCachedMaster(int newfd) {\n    server.master = server.cached_master;\n    server.cached_master = NULL;\n    server.master->fd = newfd;\n    server.master->flags &= ~(REDIS_CLOSE_AFTER_REPLY|REDIS_CLOSE_ASAP);\n    server.master->authenticated = 1;\n    server.master->lastinteraction = server.unixtime;\n    server.repl_state = REDIS_REPL_CONNECTED;\n\n    /* Re-add to the list of clients. */\n    listAddNodeTail(server.clients,server.master);\n    if (aeCreateFileEvent(server.el, newfd, AE_READABLE,\n                          readQueryFromClient, server.master)) {\n        redisLog(REDIS_WARNING,\"Error resurrecting the cached master, impossible to add the readable handler: %s\", strerror(errno));\n        freeClientAsync(server.master); /* Close ASAP. */\n    }\n\n    /* We may also need to install the write handler as well if there is\n     * pending data in the write buffers. */\n    if (server.master->bufpos || listLength(server.master->reply)) {\n        if (aeCreateFileEvent(server.el, newfd, AE_WRITABLE,\n                          sendReplyToClient, server.master)) {\n            redisLog(REDIS_WARNING,\"Error resurrecting the cached master, impossible to add the writable handler: %s\", strerror(errno));\n            freeClientAsync(server.master); /* Close ASAP. */\n        }\n    }\n}\n\n/* ------------------------- MIN-SLAVES-TO-WRITE  --------------------------- */\n\n/* This function counts the number of slaves with lag <= min-slaves-max-lag.\n * If the option is active, the server will prevent writes if there are not\n * enough connected slaves with the specified lag (or less). */\nvoid refreshGoodSlavesCount(void) {\n    listIter li;\n    listNode *ln;\n    int good = 0;\n\n    if (!server.repl_min_slaves_to_write ||\n        !server.repl_min_slaves_max_lag) return;\n\n    listRewind(server.slaves,&li);\n    while((ln = listNext(&li))) {\n        redisClient *slave = ln->value;\n        time_t lag = server.unixtime - slave->repl_ack_time;\n\n        if (slave->replstate == REDIS_REPL_ONLINE &&\n            lag <= server.repl_min_slaves_max_lag) good++;\n    }\n    server.repl_good_slaves_count = good;\n}\n\n/* ----------------------- REPLICATION SCRIPT CACHE --------------------------\n * The goal of this code is to keep track of scripts already sent to every\n * connected slave, in order to be able to replicate EVALSHA as it is without\n * translating it to EVAL every time it is possible.\n *\n * We use a capped collection implemented by a hash table for fast lookup\n * of scripts we can send as EVALSHA, plus a linked list that is used for\n * eviction of the oldest entry when the max number of items is reached.\n *\n * We don't care about taking a different cache for every different slave\n * since to fill the cache again is not very costly, the goal of this code\n * is to avoid that the same big script is trasmitted a big number of times\n * per second wasting bandwidth and processor speed, but it is not a problem\n * if we need to rebuild the cache from scratch from time to time, every used\n * script will need to be transmitted a single time to reappear in the cache.\n *\n * This is how the system works:\n *\n * 1) Every time a new slave connects, we flush the whole script cache.\n * 2) We only send as EVALSHA what was sent to the master as EVALSHA, without\n *    trying to convert EVAL into EVALSHA specifically for slaves.\n * 3) Every time we trasmit a script as EVAL to the slaves, we also add the\n *    corresponding SHA1 of the script into the cache as we are sure every\n *    slave knows about the script starting from now.\n * 4) On SCRIPT FLUSH command, we replicate the command to all the slaves\n *    and at the same time flush the script cache.\n * 5) When the last slave disconnects, flush the cache.\n * 6) We handle SCRIPT LOAD as well since that's how scripts are loaded\n *    in the master sometimes.\n */\n\n/* Initialize the script cache, only called at startup. */\nvoid replicationScriptCacheInit(void) {\n    server.repl_scriptcache_size = 10000;\n    server.repl_scriptcache_dict = dictCreate(&replScriptCacheDictType,NULL);\n    server.repl_scriptcache_fifo = listCreate();\n}\n\n/* Empty the script cache. Should be called every time we are no longer sure\n * that every slave knows about all the scripts in our set, or when the\n * current AOF \"context\" is no longer aware of the script. In general we\n * should flush the cache:\n *\n * 1) Every time a new slave reconnects to this master and performs a\n *    full SYNC (PSYNC does not require flushing).\n * 2) Every time an AOF rewrite is performed.\n * 3) Every time we are left without slaves at all, and AOF is off, in order\n *    to reclaim otherwise unused memory.\n */\nvoid replicationScriptCacheFlush(void) {\n    dictEmpty(server.repl_scriptcache_dict,NULL);\n    listRelease(server.repl_scriptcache_fifo);\n    server.repl_scriptcache_fifo = listCreate();\n}\n\n/* Add an entry into the script cache, if we reach max number of entries the\n * oldest is removed from the list. */\nvoid replicationScriptCacheAdd(sds sha1) {\n    int retval;\n    sds key = sdsdup(sha1);\n\n    /* Evict oldest. */\n    if (listLength(server.repl_scriptcache_fifo) == server.repl_scriptcache_size)\n    {\n        listNode *ln = listLast(server.repl_scriptcache_fifo);\n        sds oldest = listNodeValue(ln);\n\n        retval = dictDelete(server.repl_scriptcache_dict,oldest);\n        redisAssert(retval == DICT_OK);\n        listDelNode(server.repl_scriptcache_fifo,ln);\n    }\n\n    /* Add current. */\n    retval = dictAdd(server.repl_scriptcache_dict,key,NULL);\n    listAddNodeHead(server.repl_scriptcache_fifo,key);\n    redisAssert(retval == DICT_OK);\n}\n\n/* Returns non-zero if the specified entry exists inside the cache, that is,\n * if all the slaves are aware of this script SHA1. */\nint replicationScriptCacheExists(sds sha1) {\n    return dictFind(server.repl_scriptcache_dict,sha1) != NULL;\n}\n\n/* --------------------------- REPLICATION CRON  ----------------------------- */\n\n/* Replication cron function, called 1 time per second. */\nvoid replicationCron(void) {\n    /* Non blocking connection timeout? */\n    if (server.masterhost &&\n        (server.repl_state == REDIS_REPL_CONNECTING ||\n         server.repl_state == REDIS_REPL_RECEIVE_PONG) &&\n        (time(NULL)-server.repl_transfer_lastio) > server.repl_timeout)\n    {\n        redisLog(REDIS_WARNING,\"Timeout connecting to the MASTER...\");\n        undoConnectWithMaster();\n    }\n\n    /* Bulk transfer I/O timeout? */\n    if (server.masterhost && server.repl_state == REDIS_REPL_TRANSFER &&\n        (time(NULL)-server.repl_transfer_lastio) > server.repl_timeout)\n    {\n        redisLog(REDIS_WARNING,\"Timeout receiving bulk data from MASTER... If the problem persists try to set the 'repl-timeout' parameter in redis.conf to a larger value.\");\n        replicationAbortSyncTransfer();\n    }\n\n    /* Timed out master when we are an already connected slave? */\n    if (server.masterhost && server.repl_state == REDIS_REPL_CONNECTED &&\n        (time(NULL)-server.master->lastinteraction) > server.repl_timeout)\n    {\n        redisLog(REDIS_WARNING,\"MASTER timeout: no data nor PING received...\");\n        freeClient(server.master);\n    }\n\n    /* Check if we should connect to a MASTER */\n    if (server.repl_state == REDIS_REPL_CONNECT) {\n        redisLog(REDIS_NOTICE,\"Connecting to MASTER %s:%d\",\n            server.masterhost, server.masterport);\n        if (connectWithMaster() == REDIS_OK) {\n            redisLog(REDIS_NOTICE,\"MASTER <-> SLAVE sync started\");\n        }\n    }\n\n    /* Send ACK to master from time to time.\n     * Note that we do not send periodic acks to masters that don't\n     * support PSYNC and replication offsets. */\n    if (server.masterhost && server.master &&\n        !(server.master->flags & REDIS_PRE_PSYNC))\n        replicationSendAck();\n\n    /* If we have attached slaves, PING them from time to time.\n     * So slaves can implement an explicit timeout to masters, and will\n     * be able to detect a link disconnection even if the TCP connection\n     * will not actually go down. */\n    if (!(server.cronloops % (server.repl_ping_slave_period * server.hz))) {\n        listIter li;\n        listNode *ln;\n        robj *ping_argv[1];\n\n        /* First, send PING */\n        ping_argv[0] = createStringObject(\"PING\",4);\n        replicationFeedSlaves(server.slaves, server.slaveseldb, ping_argv, 1);\n        decrRefCount(ping_argv[0]);\n\n        /* Second, send a newline to all the slaves in pre-synchronization\n         * stage, that is, slaves waiting for the master to create the RDB file.\n         * The newline will be ignored by the slave but will refresh the\n         * last-io timer preventing a timeout. */\n        listRewind(server.slaves,&li);\n        while((ln = listNext(&li))) {\n            redisClient *slave = ln->value;\n\n            if (slave->replstate == REDIS_REPL_WAIT_BGSAVE_START ||\n                (slave->replstate == REDIS_REPL_WAIT_BGSAVE_END &&\n                 server.rdb_child_type != REDIS_RDB_CHILD_TYPE_SOCKET))\n            {\n                if (write(slave->fd, \"\\n\", 1) == -1) {\n                    /* Don't worry, it's just a ping. */\n                }\n            }\n        }\n    }\n\n    /* Disconnect timedout slaves. */\n    if (listLength(server.slaves)) {\n        listIter li;\n        listNode *ln;\n\n        listRewind(server.slaves,&li);\n        while((ln = listNext(&li))) {\n            redisClient *slave = ln->value;\n\n            if (slave->replstate != REDIS_REPL_ONLINE) continue;\n            if (slave->flags & REDIS_PRE_PSYNC) continue;\n            if ((server.unixtime - slave->repl_ack_time) > server.repl_timeout)\n            {\n                redisLog(REDIS_WARNING, \"Disconnecting timedout slave: %s\",\n                    replicationGetSlaveName(slave));\n                freeClient(slave);\n            }\n        }\n    }\n\n    /* If we have no attached slaves and there is a replication backlog\n     * using memory, free it after some (configured) time. */\n    if (listLength(server.slaves) == 0 && server.repl_backlog_time_limit &&\n        server.repl_backlog)\n    {\n        time_t idle = server.unixtime - server.repl_no_slaves_since;\n\n        if (idle > server.repl_backlog_time_limit) {\n            freeReplicationBacklog();\n            redisLog(REDIS_NOTICE,\n                \"Replication backlog freed after %d seconds \"\n                \"without connected slaves.\",\n                (int) server.repl_backlog_time_limit);\n        }\n    }\n\n    /* If AOF is disabled and we no longer have attached slaves, we can\n     * free our Replication Script Cache as there is no need to propagate\n     * EVALSHA at all. */\n    if (listLength(server.slaves) == 0 &&\n        server.aof_state == REDIS_AOF_OFF &&\n        listLength(server.repl_scriptcache_fifo) != 0)\n    {\n        replicationScriptCacheFlush();\n    }\n\n    /* If we are using diskless replication and there are slaves waiting\n     * in WAIT_BGSAVE_START state, check if enough seconds elapsed and\n     * start a BGSAVE.\n     *\n     * This code is also useful to trigger a BGSAVE if the diskless\n     * replication was turned off with CONFIG SET, while there were already\n     * slaves in WAIT_BGSAVE_START state. */\n    if (server.rdb_child_pid == -1 && server.aof_child_pid == -1) {\n        time_t idle, max_idle = 0;\n        int slaves_waiting = 0;\n        listNode *ln;\n        listIter li;\n\n        listRewind(server.slaves,&li);\n        while((ln = listNext(&li))) {\n            redisClient *slave = ln->value;\n            if (slave->replstate == REDIS_REPL_WAIT_BGSAVE_START) {\n                idle = server.unixtime - slave->lastinteraction;\n                if (idle > max_idle) max_idle = idle;\n                slaves_waiting++;\n            }\n        }\n\n        if (slaves_waiting && max_idle > server.repl_diskless_sync_delay) {\n            /* Start a BGSAVE. Usually with socket target, or with disk target\n             * if there was a recent socket -> disk config change. */\n            if (startBgsaveForReplication() == REDIS_OK) {\n                /* It started! We need to change the state of slaves\n                 * from WAIT_BGSAVE_START to WAIT_BGSAVE_END in case\n                 * the current target is disk. Otherwise it was already done\n                 * by rdbSaveToSlavesSockets() which is called by\n                 * startBgsaveForReplication(). */\n                listRewind(server.slaves,&li);\n                while((ln = listNext(&li))) {\n                    redisClient *slave = ln->value;\n                    if (slave->replstate == REDIS_REPL_WAIT_BGSAVE_START)\n                        slave->replstate = REDIS_REPL_WAIT_BGSAVE_END;\n                }\n            }\n        }\n    }\n\n    /* Refresh the number of slaves with lag <= min-slaves-max-lag. */\n    refreshGoodSlavesCount();\n}\n"
  },
  {
    "path": "extern/deprecated/redis-2.8.21/src/rio.c",
    "content": "/* rio.c is a simple stream-oriented I/O abstraction that provides an interface\n * to write code that can consume/produce data using different concrete input\n * and output devices. For instance the same rdb.c code using the rio\n * abstraction can be used to read and write the RDB format using in-memory\n * buffers or files.\n *\n * A rio object provides the following methods:\n *  read: read from stream.\n *  write: write to stream.\n *  tell: get the current offset.\n *\n * It is also possible to set a 'checksum' method that is used by rio.c in order\n * to compute a checksum of the data written or read, or to query the rio object\n * for the current checksum.\n *\n * ----------------------------------------------------------------------------\n *\n * Copyright (c) 2009-2012, Pieter Noordhuis <pcnoordhuis at gmail dot com>\n * Copyright (c) 2009-2012, Salvatore Sanfilippo <antirez at gmail dot com>\n * All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions are met:\n *\n *   * Redistributions of source code must retain the above copyright notice,\n *     this list of conditions and the following disclaimer.\n *   * Redistributions in binary form must reproduce the above copyright\n *     notice, this list of conditions and the following disclaimer in the\n *     documentation and/or other materials provided with the distribution.\n *   * Neither the name of Redis nor the names of its contributors may be used\n *     to endorse or promote products derived from this software without\n *     specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\"\n * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\n * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE\n * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR\n * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF\n * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS\n * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN\n * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)\n * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE\n * POSSIBILITY OF SUCH DAMAGE.\n */\n\n\n#include \"fmacros.h\"\n#include <string.h>\n#include <stdio.h>\n#include <unistd.h>\n#include \"rio.h\"\n#include \"util.h\"\n#include \"crc64.h\"\n#include \"config.h\"\n#include \"redis.h\"\n\n/* ------------------------- Buffer I/O implementation ----------------------- */\n\n/* Returns 1 or 0 for success/failure. */\nstatic size_t rioBufferWrite(rio *r, const void *buf, size_t len) {\n    r->io.buffer.ptr = sdscatlen(r->io.buffer.ptr,(char*)buf,len);\n    r->io.buffer.pos += len;\n    return 1;\n}\n\n/* Returns 1 or 0 for success/failure. */\nstatic size_t rioBufferRead(rio *r, void *buf, size_t len) {\n    if (sdslen(r->io.buffer.ptr)-r->io.buffer.pos < len)\n        return 0; /* not enough buffer to return len bytes. */\n    memcpy(buf,r->io.buffer.ptr+r->io.buffer.pos,len);\n    r->io.buffer.pos += len;\n    return 1;\n}\n\n/* Returns read/write position in buffer. */\nstatic off_t rioBufferTell(rio *r) {\n    return r->io.buffer.pos;\n}\n\n/* Flushes any buffer to target device if applicable. Returns 1 on success\n * and 0 on failures. */\nstatic int rioBufferFlush(rio *r) {\n    REDIS_NOTUSED(r);\n    return 1; /* Nothing to do, our write just appends to the buffer. */\n}\n\nstatic const rio rioBufferIO = {\n    rioBufferRead,\n    rioBufferWrite,\n    rioBufferTell,\n    rioBufferFlush,\n    NULL,           /* update_checksum */\n    0,              /* current checksum */\n    0,              /* bytes read or written */\n    0,              /* read/write chunk size */\n    { { NULL, 0 } } /* union for io-specific vars */\n};\n\nvoid rioInitWithBuffer(rio *r, sds s) {\n    *r = rioBufferIO;\n    r->io.buffer.ptr = s;\n    r->io.buffer.pos = 0;\n}\n\n/* --------------------- Stdio file pointer implementation ------------------- */\n\n/* Returns 1 or 0 for success/failure. */\nstatic size_t rioFileWrite(rio *r, const void *buf, size_t len) {\n    size_t retval;\n\n    retval = fwrite(buf,len,1,r->io.file.fp);\n    r->io.file.buffered += len;\n\n    if (r->io.file.autosync &&\n        r->io.file.buffered >= r->io.file.autosync)\n    {\n        fflush(r->io.file.fp);\n        aof_fsync(fileno(r->io.file.fp));\n        r->io.file.buffered = 0;\n    }\n    return retval;\n}\n\n/* Returns 1 or 0 for success/failure. */\nstatic size_t rioFileRead(rio *r, void *buf, size_t len) {\n    return fread(buf,len,1,r->io.file.fp);\n}\n\n/* Returns read/write position in file. */\nstatic off_t rioFileTell(rio *r) {\n    return ftello(r->io.file.fp);\n}\n\n/* Flushes any buffer to target device if applicable. Returns 1 on success\n * and 0 on failures. */\nstatic int rioFileFlush(rio *r) {\n    return (fflush(r->io.file.fp) == 0) ? 1 : 0;\n}\n\nstatic const rio rioFileIO = {\n    rioFileRead,\n    rioFileWrite,\n    rioFileTell,\n    rioFileFlush,\n    NULL,           /* update_checksum */\n    0,              /* current checksum */\n    0,              /* bytes read or written */\n    0,              /* read/write chunk size */\n    { { NULL, 0 } } /* union for io-specific vars */\n};\n\nvoid rioInitWithFile(rio *r, FILE *fp) {\n    *r = rioFileIO;\n    r->io.file.fp = fp;\n    r->io.file.buffered = 0;\n    r->io.file.autosync = 0;\n}\n\n/* ------------------- File descriptors set implementation ------------------- */\n\n/* Returns 1 or 0 for success/failure.\n * The function returns success as long as we are able to correctly write\n * to at least one file descriptor.\n *\n * When buf is NULL adn len is 0, the function performs a flush operation\n * if there is some pending buffer, so this function is also used in order\n * to implement rioFdsetFlush(). */\nstatic size_t rioFdsetWrite(rio *r, const void *buf, size_t len) {\n    ssize_t retval;\n    int j;\n    unsigned char *p = (unsigned char*) buf;\n    int doflush = (buf == NULL && len == 0);\n\n    /* To start we always append to our buffer. If it gets larger than\n     * a given size, we actually write to the sockets. */\n    if (len) {\n        r->io.fdset.buf = sdscatlen(r->io.fdset.buf,buf,len);\n        len = 0; /* Prevent entering the while belove if we don't flush. */\n        if (sdslen(r->io.fdset.buf) > REDIS_IOBUF_LEN) doflush = 1;\n    }\n\n    if (doflush) {\n        p = (unsigned char*) r->io.fdset.buf;\n        len = sdslen(r->io.fdset.buf);\n    }\n\n    /* Write in little chunchs so that when there are big writes we\n     * parallelize while the kernel is sending data in background to\n     * the TCP socket. */\n    while(len) {\n        size_t count = len < 1024 ? len : 1024;\n        int broken = 0;\n        for (j = 0; j < r->io.fdset.numfds; j++) {\n            if (r->io.fdset.state[j] != 0) {\n                /* Skip FDs alraedy in error. */\n                broken++;\n                continue;\n            }\n\n            /* Make sure to write 'count' bytes to the socket regardless\n             * of short writes. */\n            size_t nwritten = 0;\n            while(nwritten != count) {\n                retval = write(r->io.fdset.fds[j],p+nwritten,count-nwritten);\n                if (retval <= 0) {\n                    /* With blocking sockets, which is the sole user of this\n                     * rio target, EWOULDBLOCK is returned only because of\n                     * the SO_SNDTIMEO socket option, so we translate the error\n                     * into one more recognizable by the user. */\n                    if (retval == -1 && errno == EWOULDBLOCK) errno = ETIMEDOUT;\n                    break;\n                }\n                nwritten += retval;\n            }\n\n            if (nwritten != count) {\n                /* Mark this FD as broken. */\n                r->io.fdset.state[j] = errno;\n                if (r->io.fdset.state[j] == 0) r->io.fdset.state[j] = EIO;\n            }\n        }\n        if (broken == r->io.fdset.numfds) return 0; /* All the FDs in error. */\n        p += count;\n        len -= count;\n        r->io.fdset.pos += count;\n    }\n\n    if (doflush) sdsclear(r->io.fdset.buf);\n    return 1;\n}\n\n/* Returns 1 or 0 for success/failure. */\nstatic size_t rioFdsetRead(rio *r, void *buf, size_t len) {\n    REDIS_NOTUSED(r);\n    REDIS_NOTUSED(buf);\n    REDIS_NOTUSED(len);\n    return 0; /* Error, this target does not support reading. */\n}\n\n/* Returns read/write position in file. */\nstatic off_t rioFdsetTell(rio *r) {\n    return r->io.fdset.pos;\n}\n\n/* Flushes any buffer to target device if applicable. Returns 1 on success\n * and 0 on failures. */\nstatic int rioFdsetFlush(rio *r) {\n    /* Our flush is implemented by the write method, that recognizes a\n     * buffer set to NULL with a count of zero as a flush request. */\n    return rioFdsetWrite(r,NULL,0);\n}\n\nstatic const rio rioFdsetIO = {\n    rioFdsetRead,\n    rioFdsetWrite,\n    rioFdsetTell,\n    rioFdsetFlush,\n    NULL,           /* update_checksum */\n    0,              /* current checksum */\n    0,              /* bytes read or written */\n    0,              /* read/write chunk size */\n    { { NULL, 0 } } /* union for io-specific vars */\n};\n\nvoid rioInitWithFdset(rio *r, int *fds, int numfds) {\n    int j;\n\n    *r = rioFdsetIO;\n    r->io.fdset.fds = zmalloc(sizeof(int)*numfds);\n    r->io.fdset.state = zmalloc(sizeof(int)*numfds);\n    memcpy(r->io.fdset.fds,fds,sizeof(int)*numfds);\n    for (j = 0; j < numfds; j++) r->io.fdset.state[j] = 0;\n    r->io.fdset.numfds = numfds;\n    r->io.fdset.pos = 0;\n    r->io.fdset.buf = sdsempty();\n}\n\nvoid rioFreeFdset(rio *r) {\n    zfree(r->io.fdset.fds);\n    zfree(r->io.fdset.state);\n    sdsfree(r->io.fdset.buf);\n}\n\n/* ---------------------------- Generic functions ---------------------------- */\n\n/* This function can be installed both in memory and file streams when checksum\n * computation is needed. */\nvoid rioGenericUpdateChecksum(rio *r, const void *buf, size_t len) {\n    r->cksum = crc64(r->cksum,buf,len);\n}\n\n/* Set the file-based rio object to auto-fsync every 'bytes' file written.\n * By default this is set to zero that means no automatic file sync is\n * performed.\n *\n * This feature is useful in a few contexts since when we rely on OS write\n * buffers sometimes the OS buffers way too much, resulting in too many\n * disk I/O concentrated in very little time. When we fsync in an explicit\n * way instead the I/O pressure is more distributed across time. */\nvoid rioSetAutoSync(rio *r, off_t bytes) {\n    redisAssert(r->read == rioFileIO.read);\n    r->io.file.autosync = bytes;\n}\n\n/* --------------------------- Higher level interface --------------------------\n *\n * The following higher level functions use lower level rio.c functions to help\n * generating the Redis protocol for the Append Only File. */\n\n/* Write multi bulk count in the format: \"*<count>\\r\\n\". */\nsize_t rioWriteBulkCount(rio *r, char prefix, int count) {\n    char cbuf[128];\n    int clen;\n\n    cbuf[0] = prefix;\n    clen = 1+ll2string(cbuf+1,sizeof(cbuf)-1,count);\n    cbuf[clen++] = '\\r';\n    cbuf[clen++] = '\\n';\n    if (rioWrite(r,cbuf,clen) == 0) return 0;\n    return clen;\n}\n\n/* Write binary-safe string in the format: \"$<count>\\r\\n<payload>\\r\\n\". */\nsize_t rioWriteBulkString(rio *r, const char *buf, size_t len) {\n    size_t nwritten;\n\n    if ((nwritten = rioWriteBulkCount(r,'$',len)) == 0) return 0;\n    if (len > 0 && rioWrite(r,buf,len) == 0) return 0;\n    if (rioWrite(r,\"\\r\\n\",2) == 0) return 0;\n    return nwritten+len+2;\n}\n\n/* Write a long long value in format: \"$<count>\\r\\n<payload>\\r\\n\". */\nsize_t rioWriteBulkLongLong(rio *r, long long l) {\n    char lbuf[32];\n    unsigned int llen;\n\n    llen = ll2string(lbuf,sizeof(lbuf),l);\n    return rioWriteBulkString(r,lbuf,llen);\n}\n\n/* Write a double value in the format: \"$<count>\\r\\n<payload>\\r\\n\" */\nsize_t rioWriteBulkDouble(rio *r, double d) {\n    char dbuf[128];\n    unsigned int dlen;\n\n    dlen = snprintf(dbuf,sizeof(dbuf),\"%.17g\",d);\n    return rioWriteBulkString(r,dbuf,dlen);\n}\n"
  },
  {
    "path": "extern/deprecated/redis-2.8.21/src/rio.h",
    "content": "/*\n * Copyright (c) 2009-2012, Pieter Noordhuis <pcnoordhuis at gmail dot com>\n * Copyright (c) 2009-2012, Salvatore Sanfilippo <antirez at gmail dot com>\n * All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions are met:\n *\n *   * Redistributions of source code must retain the above copyright notice,\n *     this list of conditions and the following disclaimer.\n *   * Redistributions in binary form must reproduce the above copyright\n *     notice, this list of conditions and the following disclaimer in the\n *     documentation and/or other materials provided with the distribution.\n *   * Neither the name of Redis nor the names of its contributors may be used\n *     to endorse or promote products derived from this software without\n *     specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\"\n * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\n * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE\n * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR\n * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF\n * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS\n * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN\n * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)\n * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE\n * POSSIBILITY OF SUCH DAMAGE.\n */\n\n\n#ifndef __REDIS_RIO_H\n#define __REDIS_RIO_H\n\n#include <stdio.h>\n#include <stdint.h>\n#include \"sds.h\"\n\nstruct _rio {\n    /* Backend functions.\n     * Since this functions do not tolerate short writes or reads the return\n     * value is simplified to: zero on error, non zero on complete success. */\n    size_t (*read)(struct _rio *, void *buf, size_t len);\n    size_t (*write)(struct _rio *, const void *buf, size_t len);\n    off_t (*tell)(struct _rio *);\n    int (*flush)(struct _rio *);\n    /* The update_cksum method if not NULL is used to compute the checksum of\n     * all the data that was read or written so far. The method should be\n     * designed so that can be called with the current checksum, and the buf\n     * and len fields pointing to the new block of data to add to the checksum\n     * computation. */\n    void (*update_cksum)(struct _rio *, const void *buf, size_t len);\n\n    /* The current checksum */\n    uint64_t cksum;\n\n    /* number of bytes read or written */\n    size_t processed_bytes;\n\n    /* maximum single read or write chunk size */\n    size_t max_processing_chunk;\n\n    /* Backend-specific vars. */\n    union {\n        /* In-memory buffer target. */\n        struct {\n            sds ptr;\n            off_t pos;\n        } buffer;\n        /* Stdio file pointer target. */\n        struct {\n            FILE *fp;\n            off_t buffered; /* Bytes written since last fsync. */\n            off_t autosync; /* fsync after 'autosync' bytes written. */\n        } file;\n        /* Multiple FDs target (used to write to N sockets). */\n        struct {\n            int *fds;       /* File descriptors. */\n            int *state;     /* Error state of each fd. 0 (if ok) or errno. */\n            int numfds;\n            off_t pos;\n            sds buf;\n        } fdset;\n    } io;\n};\n\ntypedef struct _rio rio;\n\n/* The following functions are our interface with the stream. They'll call the\n * actual implementation of read / write / tell, and will update the checksum\n * if needed. */\n\nstatic inline size_t rioWrite(rio *r, const void *buf, size_t len) {\n    while (len) {\n        size_t bytes_to_write = (r->max_processing_chunk && r->max_processing_chunk < len) ? r->max_processing_chunk : len;\n        if (r->update_cksum) r->update_cksum(r,buf,bytes_to_write);\n        if (r->write(r,buf,bytes_to_write) == 0)\n            return 0;\n        buf = (char*)buf + bytes_to_write;\n        len -= bytes_to_write;\n        r->processed_bytes += bytes_to_write;\n    }\n    return 1;\n}\n\nstatic inline size_t rioRead(rio *r, void *buf, size_t len) {\n    while (len) {\n        size_t bytes_to_read = (r->max_processing_chunk && r->max_processing_chunk < len) ? r->max_processing_chunk : len;\n        if (r->read(r,buf,bytes_to_read) == 0)\n            return 0;\n        if (r->update_cksum) r->update_cksum(r,buf,bytes_to_read);\n        buf = (char*)buf + bytes_to_read;\n        len -= bytes_to_read;\n        r->processed_bytes += bytes_to_read;\n    }\n    return 1;\n}\n\nstatic inline off_t rioTell(rio *r) {\n    return r->tell(r);\n}\n\nstatic inline int rioFlush(rio *r) {\n    return r->flush(r);\n}\n\nvoid rioInitWithFile(rio *r, FILE *fp);\nvoid rioInitWithBuffer(rio *r, sds s);\nvoid rioInitWithFdset(rio *r, int *fds, int numfds);\n\nsize_t rioWriteBulkCount(rio *r, char prefix, int count);\nsize_t rioWriteBulkString(rio *r, const char *buf, size_t len);\nsize_t rioWriteBulkLongLong(rio *r, long long l);\nsize_t rioWriteBulkDouble(rio *r, double d);\n\nvoid rioGenericUpdateChecksum(rio *r, const void *buf, size_t len);\nvoid rioSetAutoSync(rio *r, off_t bytes);\n\n#endif\n"
  },
  {
    "path": "extern/deprecated/redis-2.8.21/src/scripting.c",
    "content": "/*\n * Copyright (c) 2009-2012, Salvatore Sanfilippo <antirez at gmail dot com>\n * All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions are met:\n *\n *   * Redistributions of source code must retain the above copyright notice,\n *     this list of conditions and the following disclaimer.\n *   * Redistributions in binary form must reproduce the above copyright\n *     notice, this list of conditions and the following disclaimer in the\n *     documentation and/or other materials provided with the distribution.\n *   * Neither the name of Redis nor the names of its contributors may be used\n *     to endorse or promote products derived from this software without\n *     specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\"\n * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\n * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE\n * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR\n * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF\n * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS\n * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN\n * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)\n * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE\n * POSSIBILITY OF SUCH DAMAGE.\n */\n\n#include \"redis.h\"\n#include \"sha1.h\"\n#include \"rand.h\"\n\n#include <lua.h>\n#include <lauxlib.h>\n#include <lualib.h>\n#include <ctype.h>\n#include <math.h>\n\nchar *redisProtocolToLuaType_Int(lua_State *lua, char *reply);\nchar *redisProtocolToLuaType_Bulk(lua_State *lua, char *reply);\nchar *redisProtocolToLuaType_Status(lua_State *lua, char *reply);\nchar *redisProtocolToLuaType_Error(lua_State *lua, char *reply);\nchar *redisProtocolToLuaType_MultiBulk(lua_State *lua, char *reply);\nint redis_math_random (lua_State *L);\nint redis_math_randomseed (lua_State *L);\nvoid sha1hex(char *digest, char *script, size_t len);\n\n/* Take a Redis reply in the Redis protocol format and convert it into a\n * Lua type. Thanks to this function, and the introduction of not connected\n * clients, it is trivial to implement the redis() lua function.\n *\n * Basically we take the arguments, execute the Redis command in the context\n * of a non connected client, then take the generated reply and convert it\n * into a suitable Lua type. With this trick the scripting feature does not\n * need the introduction of a full Redis internals API. Basically the script\n * is like a normal client that bypasses all the slow I/O paths.\n *\n * Note: in this function we do not do any sanity check as the reply is\n * generated by Redis directly. This allows us to go faster.\n * The reply string can be altered during the parsing as it is discarded\n * after the conversion is completed.\n *\n * Errors are returned as a table with a single 'err' field set to the\n * error string.\n */\n\nchar *redisProtocolToLuaType(lua_State *lua, char* reply) {\n    char *p = reply;\n\n    switch(*p) {\n    case ':':\n        p = redisProtocolToLuaType_Int(lua,reply);\n        break;\n    case '$':\n        p = redisProtocolToLuaType_Bulk(lua,reply);\n        break;\n    case '+':\n        p = redisProtocolToLuaType_Status(lua,reply);\n        break;\n    case '-':\n        p = redisProtocolToLuaType_Error(lua,reply);\n        break;\n    case '*':\n        p = redisProtocolToLuaType_MultiBulk(lua,reply);\n        break;\n    }\n    return p;\n}\n\nchar *redisProtocolToLuaType_Int(lua_State *lua, char *reply) {\n    char *p = strchr(reply+1,'\\r');\n    long long value;\n\n    string2ll(reply+1,p-reply-1,&value);\n    lua_pushnumber(lua,(lua_Number)value);\n    return p+2;\n}\n\nchar *redisProtocolToLuaType_Bulk(lua_State *lua, char *reply) {\n    char *p = strchr(reply+1,'\\r');\n    long long bulklen;\n\n    string2ll(reply+1,p-reply-1,&bulklen);\n    if (bulklen == -1) {\n        lua_pushboolean(lua,0);\n        return p+2;\n    } else {\n        lua_pushlstring(lua,p+2,bulklen);\n        return p+2+bulklen+2;\n    }\n}\n\nchar *redisProtocolToLuaType_Status(lua_State *lua, char *reply) {\n    char *p = strchr(reply+1,'\\r');\n\n    lua_newtable(lua);\n    lua_pushstring(lua,\"ok\");\n    lua_pushlstring(lua,reply+1,p-reply-1);\n    lua_settable(lua,-3);\n    return p+2;\n}\n\nchar *redisProtocolToLuaType_Error(lua_State *lua, char *reply) {\n    char *p = strchr(reply+1,'\\r');\n\n    lua_newtable(lua);\n    lua_pushstring(lua,\"err\");\n    lua_pushlstring(lua,reply+1,p-reply-1);\n    lua_settable(lua,-3);\n    return p+2;\n}\n\nchar *redisProtocolToLuaType_MultiBulk(lua_State *lua, char *reply) {\n    char *p = strchr(reply+1,'\\r');\n    long long mbulklen;\n    int j = 0;\n\n    string2ll(reply+1,p-reply-1,&mbulklen);\n    p += 2;\n    if (mbulklen == -1) {\n        lua_pushboolean(lua,0);\n        return p;\n    }\n    lua_newtable(lua);\n    for (j = 0; j < mbulklen; j++) {\n        lua_pushnumber(lua,j+1);\n        p = redisProtocolToLuaType(lua,p);\n        lua_settable(lua,-3);\n    }\n    return p;\n}\n\nvoid luaPushError(lua_State *lua, char *error) {\n    lua_Debug dbg;\n\n    lua_newtable(lua);\n    lua_pushstring(lua,\"err\");\n\n    /* Attempt to figure out where this function was called, if possible */\n    if(lua_getstack(lua, 1, &dbg) && lua_getinfo(lua, \"nSl\", &dbg)) {\n        sds msg = sdscatprintf(sdsempty(), \"%s: %d: %s\",\n            dbg.source, dbg.currentline, error);\n        lua_pushstring(lua, msg);\n        sdsfree(msg);\n    } else {\n        lua_pushstring(lua, error);\n    }\n    lua_settable(lua,-3);\n}\n\n/* Sort the array currently in the stack. We do this to make the output\n * of commands like KEYS or SMEMBERS something deterministic when called\n * from Lua (to play well with AOf/replication).\n *\n * The array is sorted using table.sort itself, and assuming all the\n * list elements are strings. */\nvoid luaSortArray(lua_State *lua) {\n    /* Initial Stack: array */\n    lua_getglobal(lua,\"table\");\n    lua_pushstring(lua,\"sort\");\n    lua_gettable(lua,-2);       /* Stack: array, table, table.sort */\n    lua_pushvalue(lua,-3);      /* Stack: array, table, table.sort, array */\n    if (lua_pcall(lua,1,0,0)) {\n        /* Stack: array, table, error */\n\n        /* We are not interested in the error, we assume that the problem is\n         * that there are 'false' elements inside the array, so we try\n         * again with a slower function but able to handle this case, that\n         * is: table.sort(table, __redis__compare_helper) */\n        lua_pop(lua,1);             /* Stack: array, table */\n        lua_pushstring(lua,\"sort\"); /* Stack: array, table, sort */\n        lua_gettable(lua,-2);       /* Stack: array, table, table.sort */\n        lua_pushvalue(lua,-3);      /* Stack: array, table, table.sort, array */\n        lua_getglobal(lua,\"__redis__compare_helper\");\n        /* Stack: array, table, table.sort, array, __redis__compare_helper */\n        lua_call(lua,2,0);\n    }\n    /* Stack: array (sorted), table */\n    lua_pop(lua,1);             /* Stack: array (sorted) */\n}\n\n#define LUA_CMD_OBJCACHE_SIZE 32\n#define LUA_CMD_OBJCACHE_MAX_LEN 64\nint luaRedisGenericCommand(lua_State *lua, int raise_error) {\n    int j, argc = lua_gettop(lua);\n    struct redisCommand *cmd;\n    redisClient *c = server.lua_client;\n    sds reply;\n\n    /* Cached across calls. */\n    static robj **argv = NULL;\n    static int argv_size = 0;\n    static robj *cached_objects[LUA_CMD_OBJCACHE_SIZE];\n    static size_t cached_objects_len[LUA_CMD_OBJCACHE_SIZE];\n    static int inuse = 0;   /* Recursive calls detection. */\n\n    /* By using Lua debug hooks it is possible to trigger a recursive call\n     * to luaRedisGenericCommand(), which normally should never happen.\n     * To make this function reentrant is futile and makes it slower, but\n     * we should at least detect such a misuse, and abort. */\n    if (inuse) {\n        char *recursion_warning =\n            \"luaRedisGenericCommand() recursive call detected. \"\n            \"Are you doing funny stuff with Lua debug hooks?\";\n        redisLog(REDIS_WARNING,\"%s\",recursion_warning);\n        luaPushError(lua,recursion_warning);\n        return 1;\n    }\n    inuse++;\n\n    /* Require at least one argument */\n    if (argc == 0) {\n        luaPushError(lua,\n            \"Please specify at least one argument for redis.call()\");\n        inuse--;\n        return 1;\n    }\n\n    /* Build the arguments vector */\n    if (argv_size < argc) {\n        argv = zrealloc(argv,sizeof(robj*)*argc);\n        argv_size = argc;\n    }\n\n    for (j = 0; j < argc; j++) {\n        char *obj_s;\n        size_t obj_len;\n        char dbuf[64];\n\n        if (lua_type(lua,j+1) == LUA_TNUMBER) {\n            /* We can't use lua_tolstring() for number -> string conversion\n             * since Lua uses a format specifier that loses precision. */\n            lua_Number num = lua_tonumber(lua,j+1);\n\n            obj_len = snprintf(dbuf,sizeof(dbuf),\"%.17g\",(double)num);\n            obj_s = dbuf;\n        } else {\n            obj_s = (char*)lua_tolstring(lua,j+1,&obj_len);\n            if (obj_s == NULL) break; /* Not a string. */\n        }\n\n        /* Try to use a cached object. */\n        if (j < LUA_CMD_OBJCACHE_SIZE && cached_objects[j] &&\n            cached_objects_len[j] >= obj_len)\n        {\n            char *s = cached_objects[j]->ptr;\n            struct sdshdr *sh = (void*)(s-(sizeof(struct sdshdr)));\n\n            argv[j] = cached_objects[j];\n            cached_objects[j] = NULL;\n            memcpy(s,obj_s,obj_len+1);\n            sh->free += sh->len - obj_len;\n            sh->len = obj_len;\n        } else {\n            argv[j] = createStringObject(obj_s, obj_len);\n        }\n    }\n\n    /* Check if one of the arguments passed by the Lua script\n     * is not a string or an integer (lua_isstring() return true for\n     * integers as well). */\n    if (j != argc) {\n        j--;\n        while (j >= 0) {\n            decrRefCount(argv[j]);\n            j--;\n        }\n        luaPushError(lua,\n            \"Lua redis() command arguments must be strings or integers\");\n        inuse--;\n        return 1;\n    }\n\n    /* Setup our fake client for command execution */\n    c->argv = argv;\n    c->argc = argc;\n\n    /* Command lookup */\n    cmd = lookupCommand(argv[0]->ptr);\n    if (!cmd || ((cmd->arity > 0 && cmd->arity != argc) ||\n                   (argc < -cmd->arity)))\n    {\n        if (cmd)\n            luaPushError(lua,\n                \"Wrong number of args calling Redis command From Lua script\");\n        else\n            luaPushError(lua,\"Unknown Redis command called from Lua script\");\n        goto cleanup;\n    }\n\n    /* There are commands that are not allowed inside scripts. */\n    if (cmd->flags & REDIS_CMD_NOSCRIPT) {\n        luaPushError(lua, \"This Redis command is not allowed from scripts\");\n        goto cleanup;\n    }\n\n    /* Write commands are forbidden against read-only slaves, or if a\n     * command marked as non-deterministic was already called in the context\n     * of this script. */\n    if (cmd->flags & REDIS_CMD_WRITE) {\n        if (server.lua_random_dirty) {\n            luaPushError(lua,\n                \"Write commands not allowed after non deterministic commands\");\n            goto cleanup;\n        } else if (server.masterhost && server.repl_slave_ro &&\n                   !server.loading &&\n                   !(server.lua_caller->flags & REDIS_MASTER))\n        {\n            luaPushError(lua, shared.roslaveerr->ptr);\n            goto cleanup;\n        } else if (server.stop_writes_on_bgsave_err &&\n                   server.saveparamslen > 0 &&\n                   server.lastbgsave_status == REDIS_ERR)\n        {\n            luaPushError(lua, shared.bgsaveerr->ptr);\n            goto cleanup;\n        }\n    }\n\n    /* If we reached the memory limit configured via maxmemory, commands that\n     * could enlarge the memory usage are not allowed, but only if this is the\n     * first write in the context of this script, otherwise we can't stop\n     * in the middle. */\n    if (server.maxmemory && server.lua_write_dirty == 0 &&\n        (cmd->flags & REDIS_CMD_DENYOOM))\n    {\n        if (freeMemoryIfNeeded() == REDIS_ERR) {\n            luaPushError(lua, shared.oomerr->ptr);\n            goto cleanup;\n        }\n    }\n\n    if (cmd->flags & REDIS_CMD_RANDOM) server.lua_random_dirty = 1;\n    if (cmd->flags & REDIS_CMD_WRITE) server.lua_write_dirty = 1;\n\n    /* Run the command */\n    c->cmd = cmd;\n    call(c,REDIS_CALL_SLOWLOG | REDIS_CALL_STATS);\n\n    /* Convert the result of the Redis command into a suitable Lua type.\n     * The first thing we need is to create a single string from the client\n     * output buffers. */\n    if (listLength(c->reply) == 0 && c->bufpos < REDIS_REPLY_CHUNK_BYTES) {\n        /* This is a fast path for the common case of a reply inside the\n         * client static buffer. Don't create an SDS string but just use\n         * the client buffer directly. */\n        c->buf[c->bufpos] = '\\0';\n        reply = c->buf;\n        c->bufpos = 0;\n    } else {\n        reply = sdsnewlen(c->buf,c->bufpos);\n        c->bufpos = 0;\n        while(listLength(c->reply)) {\n            robj *o = listNodeValue(listFirst(c->reply));\n\n            reply = sdscatlen(reply,o->ptr,sdslen(o->ptr));\n            listDelNode(c->reply,listFirst(c->reply));\n        }\n    }\n    if (raise_error && reply[0] != '-') raise_error = 0;\n    redisProtocolToLuaType(lua,reply);\n    /* Sort the output array if needed, assuming it is a non-null multi bulk\n     * reply as expected. */\n    if ((cmd->flags & REDIS_CMD_SORT_FOR_SCRIPT) &&\n        (reply[0] == '*' && reply[1] != '-')) {\n            luaSortArray(lua);\n    }\n    if (reply != c->buf) sdsfree(reply);\n    c->reply_bytes = 0;\n\ncleanup:\n    /* Clean up. Command code may have changed argv/argc so we use the\n     * argv/argc of the client instead of the local variables. */\n    for (j = 0; j < c->argc; j++) {\n        robj *o = c->argv[j];\n\n        /* Try to cache the object in the cached_objects array.\n         * The object must be small, SDS-encoded, and with refcount = 1\n         * (we must be the only owner) for us to cache it. */\n        if (j < LUA_CMD_OBJCACHE_SIZE &&\n            o->refcount == 1 &&\n            o->encoding == REDIS_ENCODING_RAW &&\n            sdslen(o->ptr) <= LUA_CMD_OBJCACHE_MAX_LEN)\n        {\n            struct sdshdr *sh = (void*)(((char*)(o->ptr))-(sizeof(struct sdshdr)));\n\n            if (cached_objects[j]) decrRefCount(cached_objects[j]);\n            cached_objects[j] = o;\n            cached_objects_len[j] = sh->free + sh->len;\n        } else {\n            decrRefCount(o);\n        }\n    }\n\n    if (c->argv != argv) {\n        zfree(c->argv);\n        argv = NULL;\n        argv_size = 0;\n    }\n\n    if (raise_error) {\n        /* If we are here we should have an error in the stack, in the\n         * form of a table with an \"err\" field. Extract the string to\n         * return the plain error. */\n        lua_pushstring(lua,\"err\");\n        lua_gettable(lua,-2);\n        inuse--;\n        return lua_error(lua);\n    }\n    inuse--;\n    return 1;\n}\n\nint luaRedisCallCommand(lua_State *lua) {\n    return luaRedisGenericCommand(lua,1);\n}\n\nint luaRedisPCallCommand(lua_State *lua) {\n    return luaRedisGenericCommand(lua,0);\n}\n\n/* This adds redis.sha1hex(string) to Lua scripts using the same hashing\n * function used for sha1ing lua scripts. */\nint luaRedisSha1hexCommand(lua_State *lua) {\n    int argc = lua_gettop(lua);\n    char digest[41];\n    size_t len;\n    char *s;\n\n    if (argc != 1) {\n        luaPushError(lua, \"wrong number of arguments\");\n        return 1;\n    }\n\n    s = (char*)lua_tolstring(lua,1,&len);\n    sha1hex(digest,s,len);\n    lua_pushstring(lua,digest);\n    return 1;\n}\n\n/* Returns a table with a single field 'field' set to the string value\n * passed as argument. This helper function is handy when returning\n * a Redis Protocol error or status reply from Lua:\n *\n * return redis.error_reply(\"ERR Some Error\")\n * return redis.status_reply(\"ERR Some Error\")\n */\nint luaRedisReturnSingleFieldTable(lua_State *lua, char *field) {\n    if (lua_gettop(lua) != 1 || lua_type(lua,-1) != LUA_TSTRING) {\n        luaPushError(lua, \"wrong number or type of arguments\");\n        return 1;\n    }\n\n    lua_newtable(lua);\n    lua_pushstring(lua, field);\n    lua_pushvalue(lua, -3);\n    lua_settable(lua, -3);\n    return 1;\n}\n\nint luaRedisErrorReplyCommand(lua_State *lua) {\n    return luaRedisReturnSingleFieldTable(lua,\"err\");\n}\n\nint luaRedisStatusReplyCommand(lua_State *lua) {\n    return luaRedisReturnSingleFieldTable(lua,\"ok\");\n}\n\nint luaLogCommand(lua_State *lua) {\n    int j, argc = lua_gettop(lua);\n    int level;\n    sds log;\n\n    if (argc < 2) {\n        luaPushError(lua, \"redis.log() requires two arguments or more.\");\n        return 1;\n    } else if (!lua_isnumber(lua,-argc)) {\n        luaPushError(lua, \"First argument must be a number (log level).\");\n        return 1;\n    }\n    level = lua_tonumber(lua,-argc);\n    if (level < REDIS_DEBUG || level > REDIS_WARNING) {\n        luaPushError(lua, \"Invalid debug level.\");\n        return 1;\n    }\n\n    /* Glue together all the arguments */\n    log = sdsempty();\n    for (j = 1; j < argc; j++) {\n        size_t len;\n        char *s;\n\n        s = (char*)lua_tolstring(lua,(-argc)+j,&len);\n        if (s) {\n            if (j != 1) log = sdscatlen(log,\" \",1);\n            log = sdscatlen(log,s,len);\n        }\n    }\n    redisLogRaw(level,log);\n    sdsfree(log);\n    return 0;\n}\n\nvoid luaMaskCountHook(lua_State *lua, lua_Debug *ar) {\n    long long elapsed;\n    REDIS_NOTUSED(ar);\n    REDIS_NOTUSED(lua);\n\n    elapsed = mstime() - server.lua_time_start;\n    if (elapsed >= server.lua_time_limit && server.lua_timedout == 0) {\n        redisLog(REDIS_WARNING,\"Lua slow script detected: still in execution after %lld milliseconds. You can try killing the script using the SCRIPT KILL command.\",elapsed);\n        server.lua_timedout = 1;\n        /* Once the script timeouts we reenter the event loop to permit others\n         * to call SCRIPT KILL or SHUTDOWN NOSAVE if needed. For this reason\n         * we need to mask the client executing the script from the event loop.\n         * If we don't do that the client may disconnect and could no longer be\n         * here when the EVAL command will return. */\n         aeDeleteFileEvent(server.el, server.lua_caller->fd, AE_READABLE);\n    }\n    if (server.lua_timedout) processEventsWhileBlocked();\n    if (server.lua_kill) {\n        redisLog(REDIS_WARNING,\"Lua script killed by user with SCRIPT KILL.\");\n        lua_pushstring(lua,\"Script killed by user with SCRIPT KILL...\");\n        lua_error(lua);\n    }\n}\n\nvoid luaLoadLib(lua_State *lua, const char *libname, lua_CFunction luafunc) {\n  lua_pushcfunction(lua, luafunc);\n  lua_pushstring(lua, libname);\n  lua_call(lua, 1, 0);\n}\n\nLUALIB_API int (luaopen_cjson) (lua_State *L);\nLUALIB_API int (luaopen_struct) (lua_State *L);\nLUALIB_API int (luaopen_cmsgpack) (lua_State *L);\nLUALIB_API int (luaopen_bit) (lua_State *L);\n\nvoid luaLoadLibraries(lua_State *lua) {\n    luaLoadLib(lua, \"\", luaopen_base);\n    luaLoadLib(lua, LUA_TABLIBNAME, luaopen_table);\n    luaLoadLib(lua, LUA_STRLIBNAME, luaopen_string);\n    luaLoadLib(lua, LUA_MATHLIBNAME, luaopen_math);\n    luaLoadLib(lua, LUA_DBLIBNAME, luaopen_debug);\n    luaLoadLib(lua, \"cjson\", luaopen_cjson);\n    luaLoadLib(lua, \"struct\", luaopen_struct);\n    luaLoadLib(lua, \"cmsgpack\", luaopen_cmsgpack);\n    luaLoadLib(lua, \"bit\", luaopen_bit);\n\n#if 0 /* Stuff that we don't load currently, for sandboxing concerns. */\n    luaLoadLib(lua, LUA_LOADLIBNAME, luaopen_package);\n    luaLoadLib(lua, LUA_OSLIBNAME, luaopen_os);\n#endif\n}\n\n/* Remove a functions that we don't want to expose to the Redis scripting\n * environment. */\nvoid luaRemoveUnsupportedFunctions(lua_State *lua) {\n    lua_pushnil(lua);\n    lua_setglobal(lua,\"loadfile\");\n}\n\n/* This function installs metamethods in the global table _G that prevent\n * the creation of globals accidentally.\n *\n * It should be the last to be called in the scripting engine initialization\n * sequence, because it may interact with creation of globals. */\nvoid scriptingEnableGlobalsProtection(lua_State *lua) {\n    char *s[32];\n    sds code = sdsempty();\n    int j = 0;\n\n    /* strict.lua from: http://metalua.luaforge.net/src/lib/strict.lua.html.\n     * Modified to be adapted to Redis. */\n    s[j++]=\"local dbg=debug\\n\";\n    s[j++]=\"local mt = {}\\n\";\n    s[j++]=\"setmetatable(_G, mt)\\n\";\n    s[j++]=\"mt.__newindex = function (t, n, v)\\n\";\n    s[j++]=\"  if dbg.getinfo(2) then\\n\";\n    s[j++]=\"    local w = dbg.getinfo(2, \\\"S\\\").what\\n\";\n    s[j++]=\"    if w ~= \\\"main\\\" and w ~= \\\"C\\\" then\\n\";\n    s[j++]=\"      error(\\\"Script attempted to create global variable '\\\"..tostring(n)..\\\"'\\\", 2)\\n\";\n    s[j++]=\"    end\\n\";\n    s[j++]=\"  end\\n\";\n    s[j++]=\"  rawset(t, n, v)\\n\";\n    s[j++]=\"end\\n\";\n    s[j++]=\"mt.__index = function (t, n)\\n\";\n    s[j++]=\"  if dbg.getinfo(2) and dbg.getinfo(2, \\\"S\\\").what ~= \\\"C\\\" then\\n\";\n    s[j++]=\"    error(\\\"Script attempted to access unexisting global variable '\\\"..tostring(n)..\\\"'\\\", 2)\\n\";\n    s[j++]=\"  end\\n\";\n    s[j++]=\"  return rawget(t, n)\\n\";\n    s[j++]=\"end\\n\";\n    s[j++]=\"debug = nil\\n\";\n    s[j++]=NULL;\n\n    for (j = 0; s[j] != NULL; j++) code = sdscatlen(code,s[j],strlen(s[j]));\n    luaL_loadbuffer(lua,code,sdslen(code),\"@enable_strict_lua\");\n    lua_pcall(lua,0,0,0);\n    sdsfree(code);\n}\n\n/* Initialize the scripting environment.\n * It is possible to call this function to reset the scripting environment\n * assuming that we call scriptingRelease() before.\n * See scriptingReset() for more information. */\nvoid scriptingInit(void) {\n    lua_State *lua = lua_open();\n\n    luaLoadLibraries(lua);\n    luaRemoveUnsupportedFunctions(lua);\n\n    /* Initialize a dictionary we use to map SHAs to scripts.\n     * This is useful for replication, as we need to replicate EVALSHA\n     * as EVAL, so we need to remember the associated script. */\n    server.lua_scripts = dictCreate(&shaScriptObjectDictType,NULL);\n\n    /* Register the redis commands table and fields */\n    lua_newtable(lua);\n\n    /* redis.call */\n    lua_pushstring(lua,\"call\");\n    lua_pushcfunction(lua,luaRedisCallCommand);\n    lua_settable(lua,-3);\n\n    /* redis.pcall */\n    lua_pushstring(lua,\"pcall\");\n    lua_pushcfunction(lua,luaRedisPCallCommand);\n    lua_settable(lua,-3);\n\n    /* redis.log and log levels. */\n    lua_pushstring(lua,\"log\");\n    lua_pushcfunction(lua,luaLogCommand);\n    lua_settable(lua,-3);\n\n    lua_pushstring(lua,\"LOG_DEBUG\");\n    lua_pushnumber(lua,REDIS_DEBUG);\n    lua_settable(lua,-3);\n\n    lua_pushstring(lua,\"LOG_VERBOSE\");\n    lua_pushnumber(lua,REDIS_VERBOSE);\n    lua_settable(lua,-3);\n\n    lua_pushstring(lua,\"LOG_NOTICE\");\n    lua_pushnumber(lua,REDIS_NOTICE);\n    lua_settable(lua,-3);\n\n    lua_pushstring(lua,\"LOG_WARNING\");\n    lua_pushnumber(lua,REDIS_WARNING);\n    lua_settable(lua,-3);\n\n    /* redis.sha1hex */\n    lua_pushstring(lua, \"sha1hex\");\n    lua_pushcfunction(lua, luaRedisSha1hexCommand);\n    lua_settable(lua, -3);\n\n    /* redis.error_reply and redis.status_reply */\n    lua_pushstring(lua, \"error_reply\");\n    lua_pushcfunction(lua, luaRedisErrorReplyCommand);\n    lua_settable(lua, -3);\n    lua_pushstring(lua, \"status_reply\");\n    lua_pushcfunction(lua, luaRedisStatusReplyCommand);\n    lua_settable(lua, -3);\n\n    /* Finally set the table as 'redis' global var. */\n    lua_setglobal(lua,\"redis\");\n\n    /* Replace math.random and math.randomseed with our implementations. */\n    lua_getglobal(lua,\"math\");\n\n    lua_pushstring(lua,\"random\");\n    lua_pushcfunction(lua,redis_math_random);\n    lua_settable(lua,-3);\n\n    lua_pushstring(lua,\"randomseed\");\n    lua_pushcfunction(lua,redis_math_randomseed);\n    lua_settable(lua,-3);\n\n    lua_setglobal(lua,\"math\");\n\n    /* Add a helper function that we use to sort the multi bulk output of non\n     * deterministic commands, when containing 'false' elements. */\n    {\n        char *compare_func =    \"function __redis__compare_helper(a,b)\\n\"\n                                \"  if a == false then a = '' end\\n\"\n                                \"  if b == false then b = '' end\\n\"\n                                \"  return a<b\\n\"\n                                \"end\\n\";\n        luaL_loadbuffer(lua,compare_func,strlen(compare_func),\"@cmp_func_def\");\n        lua_pcall(lua,0,0,0);\n    }\n\n    /* Add a helper function we use for pcall error reporting.\n     * Note that when the error is in the C function we want to report the\n     * information about the caller, that's what makes sense from the point\n     * of view of the user debugging a script. */\n    {\n        char *errh_func =       \"local dbg = debug\\n\"\n                                \"function __redis__err__handler(err)\\n\"\n                                \"  local i = dbg.getinfo(2,'nSl')\\n\"\n                                \"  if i and i.what == 'C' then\\n\"\n                                \"    i = dbg.getinfo(3,'nSl')\\n\"\n                                \"  end\\n\"\n                                \"  if i then\\n\"\n                                \"    return i.source .. ':' .. i.currentline .. ': ' .. err\\n\"\n                                \"  else\\n\"\n                                \"    return err\\n\"\n                                \"  end\\n\"\n                                \"end\\n\";\n        luaL_loadbuffer(lua,errh_func,strlen(errh_func),\"@err_handler_def\");\n        lua_pcall(lua,0,0,0);\n    }\n\n    /* Create the (non connected) client that we use to execute Redis commands\n     * inside the Lua interpreter.\n     * Note: there is no need to create it again when this function is called\n     * by scriptingReset(). */\n    if (server.lua_client == NULL) {\n        server.lua_client = createClient(-1);\n        server.lua_client->flags |= REDIS_LUA_CLIENT;\n    }\n\n    /* Lua beginners often don't use \"local\", this is likely to introduce\n     * subtle bugs in their code. To prevent problems we protect accesses\n     * to global variables. */\n    scriptingEnableGlobalsProtection(lua);\n\n    server.lua = lua;\n}\n\n/* Release resources related to Lua scripting.\n * This function is used in order to reset the scripting environment. */\nvoid scriptingRelease(void) {\n    dictRelease(server.lua_scripts);\n    lua_close(server.lua);\n}\n\nvoid scriptingReset(void) {\n    scriptingRelease();\n    scriptingInit();\n}\n\n/* Perform the SHA1 of the input string. We use this both for hashing script\n * bodies in order to obtain the Lua function name, and in the implementation\n * of redis.sha1().\n *\n * 'digest' should point to a 41 bytes buffer: 40 for SHA1 converted into an\n * hexadecimal number, plus 1 byte for null term. */\nvoid sha1hex(char *digest, char *script, size_t len) {\n    SHA1_CTX ctx;\n    unsigned char hash[20];\n    char *cset = \"0123456789abcdef\";\n    int j;\n\n    SHA1Init(&ctx);\n    SHA1Update(&ctx,(unsigned char*)script,len);\n    SHA1Final(hash,&ctx);\n\n    for (j = 0; j < 20; j++) {\n        digest[j*2] = cset[((hash[j]&0xF0)>>4)];\n        digest[j*2+1] = cset[(hash[j]&0xF)];\n    }\n    digest[40] = '\\0';\n}\n\nvoid luaReplyToRedisReply(redisClient *c, lua_State *lua) {\n    int t = lua_type(lua,-1);\n\n    switch(t) {\n    case LUA_TSTRING:\n        addReplyBulkCBuffer(c,(char*)lua_tostring(lua,-1),lua_strlen(lua,-1));\n        break;\n    case LUA_TBOOLEAN:\n        addReply(c,lua_toboolean(lua,-1) ? shared.cone : shared.nullbulk);\n        break;\n    case LUA_TNUMBER:\n        addReplyLongLong(c,(long long)lua_tonumber(lua,-1));\n        break;\n    case LUA_TTABLE:\n        /* We need to check if it is an array, an error, or a status reply.\n         * Error are returned as a single element table with 'err' field.\n         * Status replies are returned as single element table with 'ok' field */\n        lua_pushstring(lua,\"err\");\n        lua_gettable(lua,-2);\n        t = lua_type(lua,-1);\n        if (t == LUA_TSTRING) {\n            sds err = sdsnew(lua_tostring(lua,-1));\n            sdsmapchars(err,\"\\r\\n\",\"  \",2);\n            addReplySds(c,sdscatprintf(sdsempty(),\"-%s\\r\\n\",err));\n            sdsfree(err);\n            lua_pop(lua,2);\n            return;\n        }\n\n        lua_pop(lua,1);\n        lua_pushstring(lua,\"ok\");\n        lua_gettable(lua,-2);\n        t = lua_type(lua,-1);\n        if (t == LUA_TSTRING) {\n            sds ok = sdsnew(lua_tostring(lua,-1));\n            sdsmapchars(ok,\"\\r\\n\",\"  \",2);\n            addReplySds(c,sdscatprintf(sdsempty(),\"+%s\\r\\n\",ok));\n            sdsfree(ok);\n            lua_pop(lua,1);\n        } else {\n            void *replylen = addDeferredMultiBulkLength(c);\n            int j = 1, mbulklen = 0;\n\n            lua_pop(lua,1); /* Discard the 'ok' field value we popped */\n            while(1) {\n                lua_pushnumber(lua,j++);\n                lua_gettable(lua,-2);\n                t = lua_type(lua,-1);\n                if (t == LUA_TNIL) {\n                    lua_pop(lua,1);\n                    break;\n                }\n                luaReplyToRedisReply(c, lua);\n                mbulklen++;\n            }\n            setDeferredMultiBulkLength(c,replylen,mbulklen);\n        }\n        break;\n    default:\n        addReply(c,shared.nullbulk);\n    }\n    lua_pop(lua,1);\n}\n\n/* Set an array of Redis String Objects as a Lua array (table) stored into a\n * global variable. */\nvoid luaSetGlobalArray(lua_State *lua, char *var, robj **elev, int elec) {\n    int j;\n\n    lua_newtable(lua);\n    for (j = 0; j < elec; j++) {\n        lua_pushlstring(lua,(char*)elev[j]->ptr,sdslen(elev[j]->ptr));\n        lua_rawseti(lua,-2,j+1);\n    }\n    lua_setglobal(lua,var);\n}\n\n/* Define a lua function with the specified function name and body.\n * The function name musts be a 2 characters long string, since all the\n * functions we defined in the Lua context are in the form:\n *\n *   f_<hex sha1 sum>\n *\n * On success REDIS_OK is returned, and nothing is left on the Lua stack.\n * On error REDIS_ERR is returned and an appropriate error is set in the\n * client context. */\nint luaCreateFunction(redisClient *c, lua_State *lua, char *funcname, robj *body) {\n    sds funcdef = sdsempty();\n\n    funcdef = sdscat(funcdef,\"function \");\n    funcdef = sdscatlen(funcdef,funcname,42);\n    funcdef = sdscatlen(funcdef,\"() \",3);\n    funcdef = sdscatlen(funcdef,body->ptr,sdslen(body->ptr));\n    funcdef = sdscatlen(funcdef,\" end\",4);\n\n    if (luaL_loadbuffer(lua,funcdef,sdslen(funcdef),\"@user_script\")) {\n        addReplyErrorFormat(c,\"Error compiling script (new function): %s\\n\",\n            lua_tostring(lua,-1));\n        lua_pop(lua,1);\n        sdsfree(funcdef);\n        return REDIS_ERR;\n    }\n    sdsfree(funcdef);\n    if (lua_pcall(lua,0,0,0)) {\n        addReplyErrorFormat(c,\"Error running script (new function): %s\\n\",\n            lua_tostring(lua,-1));\n        lua_pop(lua,1);\n        return REDIS_ERR;\n    }\n\n    /* We also save a SHA1 -> Original script map in a dictionary\n     * so that we can replicate / write in the AOF all the\n     * EVALSHA commands as EVAL using the original script. */\n    {\n        int retval = dictAdd(server.lua_scripts,\n                             sdsnewlen(funcname+2,40),body);\n        redisAssertWithInfo(c,NULL,retval == DICT_OK);\n        incrRefCount(body);\n    }\n    return REDIS_OK;\n}\n\nvoid evalGenericCommand(redisClient *c, int evalsha) {\n    lua_State *lua = server.lua;\n    char funcname[43];\n    long long numkeys;\n    int delhook = 0, err;\n\n    /* We want the same PRNG sequence at every call so that our PRNG is\n     * not affected by external state. */\n    redisSrand48(0);\n\n    /* We set this flag to zero to remember that so far no random command\n     * was called. This way we can allow the user to call commands like\n     * SRANDMEMBER or RANDOMKEY from Lua scripts as far as no write command\n     * is called (otherwise the replication and AOF would end with non\n     * deterministic sequences).\n     *\n     * Thanks to this flag we'll raise an error every time a write command\n     * is called after a random command was used. */\n    server.lua_random_dirty = 0;\n    server.lua_write_dirty = 0;\n\n    /* Get the number of arguments that are keys */\n    if (getLongLongFromObjectOrReply(c,c->argv[2],&numkeys,NULL) != REDIS_OK)\n        return;\n    if (numkeys > (c->argc - 3)) {\n        addReplyError(c,\"Number of keys can't be greater than number of args\");\n        return;\n    } else if (numkeys < 0) {\n        addReplyError(c,\"Number of keys can't be negative\");\n        return;\n    }\n\n    /* We obtain the script SHA1, then check if this function is already\n     * defined into the Lua state */\n    funcname[0] = 'f';\n    funcname[1] = '_';\n    if (!evalsha) {\n        /* Hash the code if this is an EVAL call */\n        sha1hex(funcname+2,c->argv[1]->ptr,sdslen(c->argv[1]->ptr));\n    } else {\n        /* We already have the SHA if it is a EVALSHA */\n        int j;\n        char *sha = c->argv[1]->ptr;\n\n        /* Convert to lowercase. We don't use tolower since the function\n         * managed to always show up in the profiler output consuming\n         * a non trivial amount of time. */\n        for (j = 0; j < 40; j++)\n            funcname[j+2] = (sha[j] >= 'A' && sha[j] <= 'Z') ?\n                sha[j]+('a'-'A') : sha[j];\n        funcname[42] = '\\0';\n    }\n\n    /* Push the pcall error handler function on the stack. */\n    lua_getglobal(lua, \"__redis__err__handler\");\n\n    /* Try to lookup the Lua function */\n    lua_getglobal(lua, funcname);\n    if (lua_isnil(lua,-1)) {\n        lua_pop(lua,1); /* remove the nil from the stack */\n        /* Function not defined... let's define it if we have the\n         * body of the function. If this is an EVALSHA call we can just\n         * return an error. */\n        if (evalsha) {\n            lua_pop(lua,1); /* remove the error handler from the stack. */\n            addReply(c, shared.noscripterr);\n            return;\n        }\n        if (luaCreateFunction(c,lua,funcname,c->argv[1]) == REDIS_ERR) {\n            lua_pop(lua,1); /* remove the error handler from the stack. */\n            /* The error is sent to the client by luaCreateFunction()\n             * itself when it returns REDIS_ERR. */\n            return;\n        }\n        /* Now the following is guaranteed to return non nil */\n        lua_getglobal(lua, funcname);\n        redisAssert(!lua_isnil(lua,-1));\n    }\n\n    /* Populate the argv and keys table accordingly to the arguments that\n     * EVAL received. */\n    luaSetGlobalArray(lua,\"KEYS\",c->argv+3,numkeys);\n    luaSetGlobalArray(lua,\"ARGV\",c->argv+3+numkeys,c->argc-3-numkeys);\n\n    /* Select the right DB in the context of the Lua client */\n    selectDb(server.lua_client,c->db->id);\n\n    /* Set a hook in order to be able to stop the script execution if it\n     * is running for too much time.\n     * We set the hook only if the time limit is enabled as the hook will\n     * make the Lua script execution slower. */\n    server.lua_caller = c;\n    server.lua_time_start = mstime();\n    server.lua_kill = 0;\n    if (server.lua_time_limit > 0 && server.masterhost == NULL) {\n        lua_sethook(lua,luaMaskCountHook,LUA_MASKCOUNT,100000);\n        delhook = 1;\n    }\n\n    /* At this point whether this script was never seen before or if it was\n     * already defined, we can call it. We have zero arguments and expect\n     * a single return value. */\n    err = lua_pcall(lua,0,1,-2);\n\n    /* Perform some cleanup that we need to do both on error and success. */\n    if (delhook) lua_sethook(lua,luaMaskCountHook,0,0); /* Disable hook */\n    if (server.lua_timedout) {\n        server.lua_timedout = 0;\n        /* Restore the readable handler that was unregistered when the\n         * script timeout was detected. */\n        aeCreateFileEvent(server.el,c->fd,AE_READABLE,\n                          readQueryFromClient,c);\n    }\n    server.lua_caller = NULL;\n\n    /* Call the Lua garbage collector from time to time to avoid a\n     * full cycle performed by Lua, which adds too latency.\n     *\n     * The call is performed every LUA_GC_CYCLE_PERIOD executed commands\n     * (and for LUA_GC_CYCLE_PERIOD collection steps) because calling it\n     * for every command uses too much CPU. */\n    #define LUA_GC_CYCLE_PERIOD 50\n    {\n        static long gc_count = 0;\n\n        gc_count++;\n        if (gc_count == LUA_GC_CYCLE_PERIOD) {\n            lua_gc(lua,LUA_GCSTEP,LUA_GC_CYCLE_PERIOD);\n            gc_count = 0;\n        }\n    }\n\n    if (err) {\n        addReplyErrorFormat(c,\"Error running script (call to %s): %s\\n\",\n            funcname, lua_tostring(lua,-1));\n        lua_pop(lua,2); /* Consume the Lua reply and remove error handler. */\n    } else {\n        /* On success convert the Lua return value into Redis protocol, and\n         * send it to * the client. */\n        luaReplyToRedisReply(c,lua); /* Convert and consume the reply. */\n        lua_pop(lua,1); /* Remove the error handler. */\n    }\n\n    /* EVALSHA should be propagated to Slave and AOF file as full EVAL, unless\n     * we are sure that the script was already in the context of all the\n     * attached slaves *and* the current AOF file if enabled.\n     *\n     * To do so we use a cache of SHA1s of scripts that we already propagated\n     * as full EVAL, that's called the Replication Script Cache.\n     *\n     * For repliation, everytime a new slave attaches to the master, we need to\n     * flush our cache of scripts that can be replicated as EVALSHA, while\n     * for AOF we need to do so every time we rewrite the AOF file. */\n    if (evalsha) {\n        if (!replicationScriptCacheExists(c->argv[1]->ptr)) {\n            /* This script is not in our script cache, replicate it as\n             * EVAL, then add it into the script cache, as from now on\n             * slaves and AOF know about it. */\n            robj *script = dictFetchValue(server.lua_scripts,c->argv[1]->ptr);\n\n            replicationScriptCacheAdd(c->argv[1]->ptr);\n            redisAssertWithInfo(c,NULL,script != NULL);\n            rewriteClientCommandArgument(c,0,\n                resetRefCount(createStringObject(\"EVAL\",4)));\n            rewriteClientCommandArgument(c,1,script);\n            forceCommandPropagation(c,REDIS_PROPAGATE_REPL|REDIS_PROPAGATE_AOF);\n        }\n    }\n}\n\nvoid evalCommand(redisClient *c) {\n    evalGenericCommand(c,0);\n}\n\nvoid evalShaCommand(redisClient *c) {\n    if (sdslen(c->argv[1]->ptr) != 40) {\n        /* We know that a match is not possible if the provided SHA is\n         * not the right length. So we return an error ASAP, this way\n         * evalGenericCommand() can be implemented without string length\n         * sanity check */\n        addReply(c, shared.noscripterr);\n        return;\n    }\n    evalGenericCommand(c,1);\n}\n\n/* We replace math.random() with our implementation that is not affected\n * by specific libc random() implementations and will output the same sequence\n * (for the same seed) in every arch. */\n\n/* The following implementation is the one shipped with Lua itself but with\n * rand() replaced by redisLrand48(). */\nint redis_math_random (lua_State *L) {\n  /* the `%' avoids the (rare) case of r==1, and is needed also because on\n     some systems (SunOS!) `rand()' may return a value larger than RAND_MAX */\n  lua_Number r = (lua_Number)(redisLrand48()%REDIS_LRAND48_MAX) /\n                                (lua_Number)REDIS_LRAND48_MAX;\n  switch (lua_gettop(L)) {  /* check number of arguments */\n    case 0: {  /* no arguments */\n      lua_pushnumber(L, r);  /* Number between 0 and 1 */\n      break;\n    }\n    case 1: {  /* only upper limit */\n      int u = luaL_checkint(L, 1);\n      luaL_argcheck(L, 1<=u, 1, \"interval is empty\");\n      lua_pushnumber(L, floor(r*u)+1);  /* int between 1 and `u' */\n      break;\n    }\n    case 2: {  /* lower and upper limits */\n      int l = luaL_checkint(L, 1);\n      int u = luaL_checkint(L, 2);\n      luaL_argcheck(L, l<=u, 2, \"interval is empty\");\n      lua_pushnumber(L, floor(r*(u-l+1))+l);  /* int between `l' and `u' */\n      break;\n    }\n    default: return luaL_error(L, \"wrong number of arguments\");\n  }\n  return 1;\n}\n\nint redis_math_randomseed (lua_State *L) {\n  redisSrand48(luaL_checkint(L, 1));\n  return 0;\n}\n\n/* ---------------------------------------------------------------------------\n * SCRIPT command for script environment introspection and control\n * ------------------------------------------------------------------------- */\n\nvoid scriptCommand(redisClient *c) {\n    if (c->argc == 2 && !strcasecmp(c->argv[1]->ptr,\"flush\")) {\n        scriptingReset();\n        addReply(c,shared.ok);\n        replicationScriptCacheFlush();\n        server.dirty++; /* Propagating this command is a good idea. */\n    } else if (c->argc >= 2 && !strcasecmp(c->argv[1]->ptr,\"exists\")) {\n        int j;\n\n        addReplyMultiBulkLen(c, c->argc-2);\n        for (j = 2; j < c->argc; j++) {\n            if (dictFind(server.lua_scripts,c->argv[j]->ptr))\n                addReply(c,shared.cone);\n            else\n                addReply(c,shared.czero);\n        }\n    } else if (c->argc == 3 && !strcasecmp(c->argv[1]->ptr,\"load\")) {\n        char funcname[43];\n        sds sha;\n\n        funcname[0] = 'f';\n        funcname[1] = '_';\n        sha1hex(funcname+2,c->argv[2]->ptr,sdslen(c->argv[2]->ptr));\n        sha = sdsnewlen(funcname+2,40);\n        if (dictFind(server.lua_scripts,sha) == NULL) {\n            if (luaCreateFunction(c,server.lua,funcname,c->argv[2])\n                    == REDIS_ERR) {\n                sdsfree(sha);\n                return;\n            }\n        }\n        addReplyBulkCBuffer(c,funcname+2,40);\n        sdsfree(sha);\n        forceCommandPropagation(c,REDIS_PROPAGATE_REPL|REDIS_PROPAGATE_AOF);\n    } else if (c->argc == 2 && !strcasecmp(c->argv[1]->ptr,\"kill\")) {\n        if (server.lua_caller == NULL) {\n            addReplySds(c,sdsnew(\"-NOTBUSY No scripts in execution right now.\\r\\n\"));\n        } else if (server.lua_write_dirty) {\n            addReplySds(c,sdsnew(\"-UNKILLABLE Sorry the script already executed write commands against the dataset. You can either wait the script termination or kill the server in a hard way using the SHUTDOWN NOSAVE command.\\r\\n\"));\n        } else {\n            server.lua_kill = 1;\n            addReply(c,shared.ok);\n        }\n    } else {\n        addReplyError(c, \"Unknown SCRIPT subcommand or wrong # of args.\");\n    }\n}\n"
  },
  {
    "path": "extern/deprecated/redis-2.8.21/src/sds.c",
    "content": "/* SDSLib, A C dynamic strings library\n *\n * Copyright (c) 2006-2012, Salvatore Sanfilippo <antirez at gmail dot com>\n * All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions are met:\n *\n *   * Redistributions of source code must retain the above copyright notice,\n *     this list of conditions and the following disclaimer.\n *   * Redistributions in binary form must reproduce the above copyright\n *     notice, this list of conditions and the following disclaimer in the\n *     documentation and/or other materials provided with the distribution.\n *   * Neither the name of Redis nor the names of its contributors may be used\n *     to endorse or promote products derived from this software without\n *     specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\"\n * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\n * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE\n * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR\n * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF\n * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS\n * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN\n * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)\n * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE\n * POSSIBILITY OF SUCH DAMAGE.\n */\n\n#include <stdio.h>\n#include <stdlib.h>\n#include <string.h>\n#include <ctype.h>\n#include <assert.h>\n#include \"sds.h\"\n#include \"zmalloc.h\"\n\n/* Create a new sds string with the content specified by the 'init' pointer\n * and 'initlen'.\n * If NULL is used for 'init' the string is initialized with zero bytes.\n *\n * The string is always null-termined (all the sds strings are, always) so\n * even if you create an sds string with:\n *\n * mystring = sdsnewlen(\"abc\",3);\n *\n * You can print the string with printf() as there is an implicit \\0 at the\n * end of the string. However the string is binary safe and can contain\n * \\0 characters in the middle, as the length is stored in the sds header. */\nsds sdsnewlen(const void *init, size_t initlen) {\n    struct sdshdr *sh;\n\n    if (init) {\n        sh = zmalloc(sizeof(struct sdshdr)+initlen+1);\n    } else {\n        sh = zcalloc(sizeof(struct sdshdr)+initlen+1);\n    }\n    if (sh == NULL) return NULL;\n    sh->len = initlen;\n    sh->free = 0;\n    if (initlen && init)\n        memcpy(sh->buf, init, initlen);\n    sh->buf[initlen] = '\\0';\n    return (char*)sh->buf;\n}\n\n/* Create an empty (zero length) sds string. Even in this case the string\n * always has an implicit null term. */\nsds sdsempty(void) {\n    return sdsnewlen(\"\",0);\n}\n\n/* Create a new sds string starting from a null terminated C string. */\nsds sdsnew(const char *init) {\n    size_t initlen = (init == NULL) ? 0 : strlen(init);\n    return sdsnewlen(init, initlen);\n}\n\n/* Duplicate an sds string. */\nsds sdsdup(const sds s) {\n    return sdsnewlen(s, sdslen(s));\n}\n\n/* Free an sds string. No operation is performed if 's' is NULL. */\nvoid sdsfree(sds s) {\n    if (s == NULL) return;\n    zfree(s-sizeof(struct sdshdr));\n}\n\n/* Set the sds string length to the length as obtained with strlen(), so\n * considering as content only up to the first null term character.\n *\n * This function is useful when the sds string is hacked manually in some\n * way, like in the following example:\n *\n * s = sdsnew(\"foobar\");\n * s[2] = '\\0';\n * sdsupdatelen(s);\n * printf(\"%d\\n\", sdslen(s));\n *\n * The output will be \"2\", but if we comment out the call to sdsupdatelen()\n * the output will be \"6\" as the string was modified but the logical length\n * remains 6 bytes. */\nvoid sdsupdatelen(sds s) {\n    struct sdshdr *sh = (void*) (s-(sizeof(struct sdshdr)));\n    int reallen = strlen(s);\n    sh->free += (sh->len-reallen);\n    sh->len = reallen;\n}\n\n/* Modify an sds string in-place to make it empty (zero length).\n * However all the existing buffer is not discarded but set as free space\n * so that next append operations will not require allocations up to the\n * number of bytes previously available. */\nvoid sdsclear(sds s) {\n    struct sdshdr *sh = (void*) (s-(sizeof(struct sdshdr)));\n    sh->free += sh->len;\n    sh->len = 0;\n    sh->buf[0] = '\\0';\n}\n\n/* Enlarge the free space at the end of the sds string so that the caller\n * is sure that after calling this function can overwrite up to addlen\n * bytes after the end of the string, plus one more byte for nul term.\n *\n * Note: this does not change the *length* of the sds string as returned\n * by sdslen(), but only the free buffer space we have. */\nsds sdsMakeRoomFor(sds s, size_t addlen) {\n    struct sdshdr *sh, *newsh;\n    size_t free = sdsavail(s);\n    size_t len, newlen;\n\n    if (free >= addlen) return s;\n    len = sdslen(s);\n    sh = (void*) (s-(sizeof(struct sdshdr)));\n    newlen = (len+addlen);\n    if (newlen < SDS_MAX_PREALLOC)\n        newlen *= 2;\n    else\n        newlen += SDS_MAX_PREALLOC;\n    newsh = zrealloc(sh, sizeof(struct sdshdr)+newlen+1);\n    if (newsh == NULL) return NULL;\n\n    newsh->free = newlen - len;\n    return newsh->buf;\n}\n\n/* Reallocate the sds string so that it has no free space at the end. The\n * contained string remains not altered, but next concatenation operations\n * will require a reallocation.\n *\n * After the call, the passed sds string is no longer valid and all the\n * references must be substituted with the new pointer returned by the call. */\nsds sdsRemoveFreeSpace(sds s) {\n    struct sdshdr *sh;\n\n    sh = (void*) (s-(sizeof(struct sdshdr)));\n    sh = zrealloc(sh, sizeof(struct sdshdr)+sh->len+1);\n    sh->free = 0;\n    return sh->buf;\n}\n\n/* Return the total size of the allocation of the specifed sds string,\n * including:\n * 1) The sds header before the pointer.\n * 2) The string.\n * 3) The free buffer at the end if any.\n * 4) The implicit null term.\n */\nsize_t sdsAllocSize(sds s) {\n    struct sdshdr *sh = (void*) (s-(sizeof(struct sdshdr)));\n\n    return sizeof(*sh)+sh->len+sh->free+1;\n}\n\n/* Increment the sds length and decrements the left free space at the\n * end of the string according to 'incr'. Also set the null term\n * in the new end of the string.\n *\n * This function is used in order to fix the string length after the\n * user calls sdsMakeRoomFor(), writes something after the end of\n * the current string, and finally needs to set the new length.\n *\n * Note: it is possible to use a negative increment in order to\n * right-trim the string.\n *\n * Usage example:\n *\n * Using sdsIncrLen() and sdsMakeRoomFor() it is possible to mount the\n * following schema, to cat bytes coming from the kernel to the end of an\n * sds string without copying into an intermediate buffer:\n *\n * oldlen = sdslen(s);\n * s = sdsMakeRoomFor(s, BUFFER_SIZE);\n * nread = read(fd, s+oldlen, BUFFER_SIZE);\n * ... check for nread <= 0 and handle it ...\n * sdsIncrLen(s, nread);\n */\nvoid sdsIncrLen(sds s, int incr) {\n    struct sdshdr *sh = (void*) (s-(sizeof(struct sdshdr)));\n\n    if (incr >= 0)\n        assert(sh->free >= (unsigned int)incr);\n    else\n        assert(sh->len >= (unsigned int)(-incr));\n    sh->len += incr;\n    sh->free -= incr;\n    s[sh->len] = '\\0';\n}\n\n/* Grow the sds to have the specified length. Bytes that were not part of\n * the original length of the sds will be set to zero.\n *\n * if the specified length is smaller than the current length, no operation\n * is performed. */\nsds sdsgrowzero(sds s, size_t len) {\n    struct sdshdr *sh = (void*)(s-(sizeof(struct sdshdr)));\n    size_t totlen, curlen = sh->len;\n\n    if (len <= curlen) return s;\n    s = sdsMakeRoomFor(s,len-curlen);\n    if (s == NULL) return NULL;\n\n    /* Make sure added region doesn't contain garbage */\n    sh = (void*)(s-(sizeof(struct sdshdr)));\n    memset(s+curlen,0,(len-curlen+1)); /* also set trailing \\0 byte */\n    totlen = sh->len+sh->free;\n    sh->len = len;\n    sh->free = totlen-sh->len;\n    return s;\n}\n\n/* Append the specified binary-safe string pointed by 't' of 'len' bytes to the\n * end of the specified sds string 's'.\n *\n * After the call, the passed sds string is no longer valid and all the\n * references must be substituted with the new pointer returned by the call. */\nsds sdscatlen(sds s, const void *t, size_t len) {\n    struct sdshdr *sh;\n    size_t curlen = sdslen(s);\n\n    s = sdsMakeRoomFor(s,len);\n    if (s == NULL) return NULL;\n    sh = (void*) (s-(sizeof(struct sdshdr)));\n    memcpy(s+curlen, t, len);\n    sh->len = curlen+len;\n    sh->free = sh->free-len;\n    s[curlen+len] = '\\0';\n    return s;\n}\n\n/* Append the specified null termianted C string to the sds string 's'.\n *\n * After the call, the passed sds string is no longer valid and all the\n * references must be substituted with the new pointer returned by the call. */\nsds sdscat(sds s, const char *t) {\n    return sdscatlen(s, t, strlen(t));\n}\n\n/* Append the specified sds 't' to the existing sds 's'.\n *\n * After the call, the modified sds string is no longer valid and all the\n * references must be substituted with the new pointer returned by the call. */\nsds sdscatsds(sds s, const sds t) {\n    return sdscatlen(s, t, sdslen(t));\n}\n\n/* Destructively modify the sds string 's' to hold the specified binary\n * safe string pointed by 't' of length 'len' bytes. */\nsds sdscpylen(sds s, const char *t, size_t len) {\n    struct sdshdr *sh = (void*) (s-(sizeof(struct sdshdr)));\n    size_t totlen = sh->free+sh->len;\n\n    if (totlen < len) {\n        s = sdsMakeRoomFor(s,len-sh->len);\n        if (s == NULL) return NULL;\n        sh = (void*) (s-(sizeof(struct sdshdr)));\n        totlen = sh->free+sh->len;\n    }\n    memcpy(s, t, len);\n    s[len] = '\\0';\n    sh->len = len;\n    sh->free = totlen-len;\n    return s;\n}\n\n/* Like sdscpylen() but 't' must be a null-termined string so that the length\n * of the string is obtained with strlen(). */\nsds sdscpy(sds s, const char *t) {\n    return sdscpylen(s, t, strlen(t));\n}\n\n/* Helper for sdscatlonglong() doing the actual number -> string\n * conversion. 's' must point to a string with room for at least\n * SDS_LLSTR_SIZE bytes.\n *\n * The function returns the length of the null-terminated string\n * representation stored at 's'. */\n#define SDS_LLSTR_SIZE 21\nint sdsll2str(char *s, long long value) {\n    char *p, aux;\n    unsigned long long v;\n    size_t l;\n\n    /* Generate the string representation, this method produces\n     * an reversed string. */\n    v = (value < 0) ? -value : value;\n    p = s;\n    do {\n        *p++ = '0'+(v%10);\n        v /= 10;\n    } while(v);\n    if (value < 0) *p++ = '-';\n\n    /* Compute length and add null term. */\n    l = p-s;\n    *p = '\\0';\n\n    /* Reverse the string. */\n    p--;\n    while(s < p) {\n        aux = *s;\n        *s = *p;\n        *p = aux;\n        s++;\n        p--;\n    }\n    return l;\n}\n\n/* Identical sdsll2str(), but for unsigned long long type. */\nint sdsull2str(char *s, unsigned long long v) {\n    char *p, aux;\n    size_t l;\n\n    /* Generate the string representation, this method produces\n     * an reversed string. */\n    p = s;\n    do {\n        *p++ = '0'+(v%10);\n        v /= 10;\n    } while(v);\n\n    /* Compute length and add null term. */\n    l = p-s;\n    *p = '\\0';\n\n    /* Reverse the string. */\n    p--;\n    while(s < p) {\n        aux = *s;\n        *s = *p;\n        *p = aux;\n        s++;\n        p--;\n    }\n    return l;\n}\n\n/* Create an sds string from a long long value. It is much faster than:\n *\n * sdscatprintf(sdsempty(),\"%lld\\n\", value);\n */\nsds sdsfromlonglong(long long value) {\n    char buf[SDS_LLSTR_SIZE];\n    int len = sdsll2str(buf,value);\n\n    return sdsnewlen(buf,len);\n}\n\n/* Like sdscatprintf() but gets va_list instead of being variadic. */\nsds sdscatvprintf(sds s, const char *fmt, va_list ap) {\n    va_list cpy;\n    char staticbuf[1024], *buf = staticbuf, *t;\n    size_t buflen = strlen(fmt)*2;\n\n    /* We try to start using a static buffer for speed.\n     * If not possible we revert to heap allocation. */\n    if (buflen > sizeof(staticbuf)) {\n        buf = zmalloc(buflen);\n        if (buf == NULL) return NULL;\n    } else {\n        buflen = sizeof(staticbuf);\n    }\n\n    /* Try with buffers two times bigger every time we fail to\n     * fit the string in the current buffer size. */\n    while(1) {\n        buf[buflen-2] = '\\0';\n        va_copy(cpy,ap);\n        vsnprintf(buf, buflen, fmt, cpy);\n        va_end(cpy);\n        if (buf[buflen-2] != '\\0') {\n            if (buf != staticbuf) zfree(buf);\n            buflen *= 2;\n            buf = zmalloc(buflen);\n            if (buf == NULL) return NULL;\n            continue;\n        }\n        break;\n    }\n\n    /* Finally concat the obtained string to the SDS string and return it. */\n    t = sdscat(s, buf);\n    if (buf != staticbuf) zfree(buf);\n    return t;\n}\n\n/* Append to the sds string 's' a string obtained using printf-alike format\n * specifier.\n *\n * After the call, the modified sds string is no longer valid and all the\n * references must be substituted with the new pointer returned by the call.\n *\n * Example:\n *\n * s = sdsnew(\"Sum is: \");\n * s = sdscatprintf(s,\"%d+%d = %d\",a,b,a+b).\n *\n * Often you need to create a string from scratch with the printf-alike\n * format. When this is the need, just use sdsempty() as the target string:\n *\n * s = sdscatprintf(sdsempty(), \"... your format ...\", args);\n */\nsds sdscatprintf(sds s, const char *fmt, ...) {\n    va_list ap;\n    char *t;\n    va_start(ap, fmt);\n    t = sdscatvprintf(s,fmt,ap);\n    va_end(ap);\n    return t;\n}\n\n/* This function is similar to sdscatprintf, but much faster as it does\n * not rely on sprintf() family functions implemented by the libc that\n * are often very slow. Moreover directly handling the sds string as\n * new data is concatenated provides a performance improvement.\n *\n * However this function only handles an incompatible subset of printf-alike\n * format specifiers:\n *\n * %s - C String\n * %S - SDS string\n * %i - signed int\n * %I - 64 bit signed integer (long long, int64_t)\n * %u - unsigned int\n * %U - 64 bit unsigned integer (unsigned long long, uint64_t)\n * %% - Verbatim \"%\" character.\n */\nsds sdscatfmt(sds s, char const *fmt, ...) {\n    struct sdshdr *sh = (void*) (s-(sizeof(struct sdshdr)));\n    size_t initlen = sdslen(s);\n    const char *f = fmt;\n    int i;\n    va_list ap;\n\n    va_start(ap,fmt);\n    f = fmt;    /* Next format specifier byte to process. */\n    i = initlen; /* Position of the next byte to write to dest str. */\n    while(*f) {\n        char next, *str;\n        unsigned int l;\n        long long num;\n        unsigned long long unum;\n\n        /* Make sure there is always space for at least 1 char. */\n        if (sh->free == 0) {\n            s = sdsMakeRoomFor(s,1);\n            sh = (void*) (s-(sizeof(struct sdshdr)));\n        }\n\n        switch(*f) {\n        case '%':\n            next = *(f+1);\n            f++;\n            switch(next) {\n            case 's':\n            case 'S':\n                str = va_arg(ap,char*);\n                l = (next == 's') ? strlen(str) : sdslen(str);\n                if (sh->free < l) {\n                    s = sdsMakeRoomFor(s,l);\n                    sh = (void*) (s-(sizeof(struct sdshdr)));\n                }\n                memcpy(s+i,str,l);\n                sh->len += l;\n                sh->free -= l;\n                i += l;\n                break;\n            case 'i':\n            case 'I':\n                if (next == 'i')\n                    num = va_arg(ap,int);\n                else\n                    num = va_arg(ap,long long);\n                {\n                    char buf[SDS_LLSTR_SIZE];\n                    l = sdsll2str(buf,num);\n                    if (sh->free < l) {\n                        s = sdsMakeRoomFor(s,l);\n                        sh = (void*) (s-(sizeof(struct sdshdr)));\n                    }\n                    memcpy(s+i,buf,l);\n                    sh->len += l;\n                    sh->free -= l;\n                    i += l;\n                }\n                break;\n            case 'u':\n            case 'U':\n                if (next == 'u')\n                    unum = va_arg(ap,unsigned int);\n                else\n                    unum = va_arg(ap,unsigned long long);\n                {\n                    char buf[SDS_LLSTR_SIZE];\n                    l = sdsull2str(buf,unum);\n                    if (sh->free < l) {\n                        s = sdsMakeRoomFor(s,l);\n                        sh = (void*) (s-(sizeof(struct sdshdr)));\n                    }\n                    memcpy(s+i,buf,l);\n                    sh->len += l;\n                    sh->free -= l;\n                    i += l;\n                }\n                break;\n            default: /* Handle %% and generally %<unknown>. */\n                s[i++] = next;\n                sh->len += 1;\n                sh->free -= 1;\n                break;\n            }\n            break;\n        default:\n            s[i++] = *f;\n            sh->len += 1;\n            sh->free -= 1;\n            break;\n        }\n        f++;\n    }\n    va_end(ap);\n\n    /* Add null-term */\n    s[i] = '\\0';\n    return s;\n}\n\n/* Remove the part of the string from left and from right composed just of\n * contiguous characters found in 'cset', that is a null terminted C string.\n *\n * After the call, the modified sds string is no longer valid and all the\n * references must be substituted with the new pointer returned by the call.\n *\n * Example:\n *\n * s = sdsnew(\"AA...AA.a.aa.aHelloWorld     :::\");\n * s = sdstrim(s,\"Aa. :\");\n * printf(\"%s\\n\", s);\n *\n * Output will be just \"Hello World\".\n */\nsds sdstrim(sds s, const char *cset) {\n    struct sdshdr *sh = (void*) (s-(sizeof(struct sdshdr)));\n    char *start, *end, *sp, *ep;\n    size_t len;\n\n    sp = start = s;\n    ep = end = s+sdslen(s)-1;\n    while(sp <= end && strchr(cset, *sp)) sp++;\n    while(ep > start && strchr(cset, *ep)) ep--;\n    len = (sp > ep) ? 0 : ((ep-sp)+1);\n    if (sh->buf != sp) memmove(sh->buf, sp, len);\n    sh->buf[len] = '\\0';\n    sh->free = sh->free+(sh->len-len);\n    sh->len = len;\n    return s;\n}\n\n/* Turn the string into a smaller (or equal) string containing only the\n * substring specified by the 'start' and 'end' indexes.\n *\n * start and end can be negative, where -1 means the last character of the\n * string, -2 the penultimate character, and so forth.\n *\n * The interval is inclusive, so the start and end characters will be part\n * of the resulting string.\n *\n * The string is modified in-place.\n *\n * Example:\n *\n * s = sdsnew(\"Hello World\");\n * sdsrange(s,1,-1); => \"ello World\"\n */\nvoid sdsrange(sds s, int start, int end) {\n    struct sdshdr *sh = (void*) (s-(sizeof(struct sdshdr)));\n    size_t newlen, len = sdslen(s);\n\n    if (len == 0) return;\n    if (start < 0) {\n        start = len+start;\n        if (start < 0) start = 0;\n    }\n    if (end < 0) {\n        end = len+end;\n        if (end < 0) end = 0;\n    }\n    newlen = (start > end) ? 0 : (end-start)+1;\n    if (newlen != 0) {\n        if (start >= (signed)len) {\n            newlen = 0;\n        } else if (end >= (signed)len) {\n            end = len-1;\n            newlen = (start > end) ? 0 : (end-start)+1;\n        }\n    } else {\n        start = 0;\n    }\n    if (start && newlen) memmove(sh->buf, sh->buf+start, newlen);\n    sh->buf[newlen] = 0;\n    sh->free = sh->free+(sh->len-newlen);\n    sh->len = newlen;\n}\n\n/* Apply tolower() to every character of the sds string 's'. */\nvoid sdstolower(sds s) {\n    int len = sdslen(s), j;\n\n    for (j = 0; j < len; j++) s[j] = tolower(s[j]);\n}\n\n/* Apply toupper() to every character of the sds string 's'. */\nvoid sdstoupper(sds s) {\n    int len = sdslen(s), j;\n\n    for (j = 0; j < len; j++) s[j] = toupper(s[j]);\n}\n\n/* Compare two sds strings s1 and s2 with memcmp().\n *\n * Return value:\n *\n *     positive if s1 > s2.\n *     negative if s1 < s2.\n *     0 if s1 and s2 are exactly the same binary string.\n *\n * If two strings share exactly the same prefix, but one of the two has\n * additional characters, the longer string is considered to be greater than\n * the smaller one. */\nint sdscmp(const sds s1, const sds s2) {\n    size_t l1, l2, minlen;\n    int cmp;\n\n    l1 = sdslen(s1);\n    l2 = sdslen(s2);\n    minlen = (l1 < l2) ? l1 : l2;\n    cmp = memcmp(s1,s2,minlen);\n    if (cmp == 0) return l1-l2;\n    return cmp;\n}\n\n/* Split 's' with separator in 'sep'. An array\n * of sds strings is returned. *count will be set\n * by reference to the number of tokens returned.\n *\n * On out of memory, zero length string, zero length\n * separator, NULL is returned.\n *\n * Note that 'sep' is able to split a string using\n * a multi-character separator. For example\n * sdssplit(\"foo_-_bar\",\"_-_\"); will return two\n * elements \"foo\" and \"bar\".\n *\n * This version of the function is binary-safe but\n * requires length arguments. sdssplit() is just the\n * same function but for zero-terminated strings.\n */\nsds *sdssplitlen(const char *s, int len, const char *sep, int seplen, int *count) {\n    int elements = 0, slots = 5, start = 0, j;\n    sds *tokens;\n\n    if (seplen < 1 || len < 0) return NULL;\n\n    tokens = zmalloc(sizeof(sds)*slots);\n    if (tokens == NULL) return NULL;\n\n    if (len == 0) {\n        *count = 0;\n        return tokens;\n    }\n    for (j = 0; j < (len-(seplen-1)); j++) {\n        /* make sure there is room for the next element and the final one */\n        if (slots < elements+2) {\n            sds *newtokens;\n\n            slots *= 2;\n            newtokens = zrealloc(tokens,sizeof(sds)*slots);\n            if (newtokens == NULL) goto cleanup;\n            tokens = newtokens;\n        }\n        /* search the separator */\n        if ((seplen == 1 && *(s+j) == sep[0]) || (memcmp(s+j,sep,seplen) == 0)) {\n            tokens[elements] = sdsnewlen(s+start,j-start);\n            if (tokens[elements] == NULL) goto cleanup;\n            elements++;\n            start = j+seplen;\n            j = j+seplen-1; /* skip the separator */\n        }\n    }\n    /* Add the final element. We are sure there is room in the tokens array. */\n    tokens[elements] = sdsnewlen(s+start,len-start);\n    if (tokens[elements] == NULL) goto cleanup;\n    elements++;\n    *count = elements;\n    return tokens;\n\ncleanup:\n    {\n        int i;\n        for (i = 0; i < elements; i++) sdsfree(tokens[i]);\n        zfree(tokens);\n        *count = 0;\n        return NULL;\n    }\n}\n\n/* Free the result returned by sdssplitlen(), or do nothing if 'tokens' is NULL. */\nvoid sdsfreesplitres(sds *tokens, int count) {\n    if (!tokens) return;\n    while(count--)\n        sdsfree(tokens[count]);\n    zfree(tokens);\n}\n\n/* Append to the sds string \"s\" an escaped string representation where\n * all the non-printable characters (tested with isprint()) are turned into\n * escapes in the form \"\\n\\r\\a....\" or \"\\x<hex-number>\".\n *\n * After the call, the modified sds string is no longer valid and all the\n * references must be substituted with the new pointer returned by the call. */\nsds sdscatrepr(sds s, const char *p, size_t len) {\n    s = sdscatlen(s,\"\\\"\",1);\n    while(len--) {\n        switch(*p) {\n        case '\\\\':\n        case '\"':\n            s = sdscatprintf(s,\"\\\\%c\",*p);\n            break;\n        case '\\n': s = sdscatlen(s,\"\\\\n\",2); break;\n        case '\\r': s = sdscatlen(s,\"\\\\r\",2); break;\n        case '\\t': s = sdscatlen(s,\"\\\\t\",2); break;\n        case '\\a': s = sdscatlen(s,\"\\\\a\",2); break;\n        case '\\b': s = sdscatlen(s,\"\\\\b\",2); break;\n        default:\n            if (isprint(*p))\n                s = sdscatprintf(s,\"%c\",*p);\n            else\n                s = sdscatprintf(s,\"\\\\x%02x\",(unsigned char)*p);\n            break;\n        }\n        p++;\n    }\n    return sdscatlen(s,\"\\\"\",1);\n}\n\n/* Helper function for sdssplitargs() that returns non zero if 'c'\n * is a valid hex digit. */\nint is_hex_digit(char c) {\n    return (c >= '0' && c <= '9') || (c >= 'a' && c <= 'f') ||\n           (c >= 'A' && c <= 'F');\n}\n\n/* Helper function for sdssplitargs() that converts a hex digit into an\n * integer from 0 to 15 */\nint hex_digit_to_int(char c) {\n    switch(c) {\n    case '0': return 0;\n    case '1': return 1;\n    case '2': return 2;\n    case '3': return 3;\n    case '4': return 4;\n    case '5': return 5;\n    case '6': return 6;\n    case '7': return 7;\n    case '8': return 8;\n    case '9': return 9;\n    case 'a': case 'A': return 10;\n    case 'b': case 'B': return 11;\n    case 'c': case 'C': return 12;\n    case 'd': case 'D': return 13;\n    case 'e': case 'E': return 14;\n    case 'f': case 'F': return 15;\n    default: return 0;\n    }\n}\n\n/* Split a line into arguments, where every argument can be in the\n * following programming-language REPL-alike form:\n *\n * foo bar \"newline are supported\\n\" and \"\\xff\\x00otherstuff\"\n *\n * The number of arguments is stored into *argc, and an array\n * of sds is returned.\n *\n * The caller should free the resulting array of sds strings with\n * sdsfreesplitres().\n *\n * Note that sdscatrepr() is able to convert back a string into\n * a quoted string in the same format sdssplitargs() is able to parse.\n *\n * The function returns the allocated tokens on success, even when the\n * input string is empty, or NULL if the input contains unbalanced\n * quotes or closed quotes followed by non space characters\n * as in: \"foo\"bar or \"foo'\n */\nsds *sdssplitargs(const char *line, int *argc) {\n    const char *p = line;\n    char *current = NULL;\n    char **vector = NULL;\n\n    *argc = 0;\n    while(1) {\n        /* skip blanks */\n        while(*p && isspace(*p)) p++;\n        if (*p) {\n            /* get a token */\n            int inq=0;  /* set to 1 if we are in \"quotes\" */\n            int insq=0; /* set to 1 if we are in 'single quotes' */\n            int done=0;\n\n            if (current == NULL) current = sdsempty();\n            while(!done) {\n                if (inq) {\n                    if (*p == '\\\\' && *(p+1) == 'x' &&\n                                             is_hex_digit(*(p+2)) &&\n                                             is_hex_digit(*(p+3)))\n                    {\n                        unsigned char byte;\n\n                        byte = (hex_digit_to_int(*(p+2))*16)+\n                                hex_digit_to_int(*(p+3));\n                        current = sdscatlen(current,(char*)&byte,1);\n                        p += 3;\n                    } else if (*p == '\\\\' && *(p+1)) {\n                        char c;\n\n                        p++;\n                        switch(*p) {\n                        case 'n': c = '\\n'; break;\n                        case 'r': c = '\\r'; break;\n                        case 't': c = '\\t'; break;\n                        case 'b': c = '\\b'; break;\n                        case 'a': c = '\\a'; break;\n                        default: c = *p; break;\n                        }\n                        current = sdscatlen(current,&c,1);\n                    } else if (*p == '\"') {\n                        /* closing quote must be followed by a space or\n                         * nothing at all. */\n                        if (*(p+1) && !isspace(*(p+1))) goto err;\n                        done=1;\n                    } else if (!*p) {\n                        /* unterminated quotes */\n                        goto err;\n                    } else {\n                        current = sdscatlen(current,p,1);\n                    }\n                } else if (insq) {\n                    if (*p == '\\\\' && *(p+1) == '\\'') {\n                        p++;\n                        current = sdscatlen(current,\"'\",1);\n                    } else if (*p == '\\'') {\n                        /* closing quote must be followed by a space or\n                         * nothing at all. */\n                        if (*(p+1) && !isspace(*(p+1))) goto err;\n                        done=1;\n                    } else if (!*p) {\n                        /* unterminated quotes */\n                        goto err;\n                    } else {\n                        current = sdscatlen(current,p,1);\n                    }\n                } else {\n                    switch(*p) {\n                    case ' ':\n                    case '\\n':\n                    case '\\r':\n                    case '\\t':\n                    case '\\0':\n                        done=1;\n                        break;\n                    case '\"':\n                        inq=1;\n                        break;\n                    case '\\'':\n                        insq=1;\n                        break;\n                    default:\n                        current = sdscatlen(current,p,1);\n                        break;\n                    }\n                }\n                if (*p) p++;\n            }\n            /* add the token to the vector */\n            vector = zrealloc(vector,((*argc)+1)*sizeof(char*));\n            vector[*argc] = current;\n            (*argc)++;\n            current = NULL;\n        } else {\n            /* Even on empty input string return something not NULL. */\n            if (vector == NULL) vector = zmalloc(sizeof(void*));\n            return vector;\n        }\n    }\n\nerr:\n    while((*argc)--)\n        sdsfree(vector[*argc]);\n    zfree(vector);\n    if (current) sdsfree(current);\n    *argc = 0;\n    return NULL;\n}\n\n/* Modify the string substituting all the occurrences of the set of\n * characters specified in the 'from' string to the corresponding character\n * in the 'to' array.\n *\n * For instance: sdsmapchars(mystring, \"ho\", \"01\", 2)\n * will have the effect of turning the string \"hello\" into \"0ell1\".\n *\n * The function returns the sds string pointer, that is always the same\n * as the input pointer since no resize is needed. */\nsds sdsmapchars(sds s, const char *from, const char *to, size_t setlen) {\n    size_t j, i, l = sdslen(s);\n\n    for (j = 0; j < l; j++) {\n        for (i = 0; i < setlen; i++) {\n            if (s[j] == from[i]) {\n                s[j] = to[i];\n                break;\n            }\n        }\n    }\n    return s;\n}\n\n/* Join an array of C strings using the specified separator (also a C string).\n * Returns the result as an sds string. */\nsds sdsjoin(char **argv, int argc, char *sep) {\n    sds join = sdsempty();\n    int j;\n\n    for (j = 0; j < argc; j++) {\n        join = sdscat(join, argv[j]);\n        if (j != argc-1) join = sdscat(join,sep);\n    }\n    return join;\n}\n\n#ifdef SDS_TEST_MAIN\n#include <stdio.h>\n#include \"testhelp.h\"\n#include \"limits.h\"\n\nint main(void) {\n    {\n        struct sdshdr *sh;\n        sds x = sdsnew(\"foo\"), y;\n\n        test_cond(\"Create a string and obtain the length\",\n            sdslen(x) == 3 && memcmp(x,\"foo\\0\",4) == 0)\n\n        sdsfree(x);\n        x = sdsnewlen(\"foo\",2);\n        test_cond(\"Create a string with specified length\",\n            sdslen(x) == 2 && memcmp(x,\"fo\\0\",3) == 0)\n\n        x = sdscat(x,\"bar\");\n        test_cond(\"Strings concatenation\",\n            sdslen(x) == 5 && memcmp(x,\"fobar\\0\",6) == 0);\n\n        x = sdscpy(x,\"a\");\n        test_cond(\"sdscpy() against an originally longer string\",\n            sdslen(x) == 1 && memcmp(x,\"a\\0\",2) == 0)\n\n        x = sdscpy(x,\"xyzxxxxxxxxxxyyyyyyyyyykkkkkkkkkk\");\n        test_cond(\"sdscpy() against an originally shorter string\",\n            sdslen(x) == 33 &&\n            memcmp(x,\"xyzxxxxxxxxxxyyyyyyyyyykkkkkkkkkk\\0\",33) == 0)\n\n        sdsfree(x);\n        x = sdscatprintf(sdsempty(),\"%d\",123);\n        test_cond(\"sdscatprintf() seems working in the base case\",\n            sdslen(x) == 3 && memcmp(x,\"123\\0\",4) == 0)\n\n        sdsfree(x);\n        x = sdsnew(\"--\");\n        x = sdscatfmt(x, \"Hello %s World %I,%I--\", \"Hi!\", LLONG_MIN,LLONG_MAX);\n        test_cond(\"sdscatfmt() seems working in the base case\",\n            sdslen(x) == 60 &&\n            memcmp(x,\"--Hello Hi! World -9223372036854775808,\"\n                     \"9223372036854775807--\",60) == 0)\n\n        sdsfree(x);\n        x = sdsnew(\"--\");\n        x = sdscatfmt(x, \"%u,%U--\", UINT_MAX, ULLONG_MAX);\n        test_cond(\"sdscatfmt() seems working with unsigned numbers\",\n            sdslen(x) == 35 &&\n            memcmp(x,\"--4294967295,18446744073709551615--\",35) == 0)\n\n        sdsfree(x);\n        x = sdsnew(\"xxciaoyyy\");\n        sdstrim(x,\"xy\");\n        test_cond(\"sdstrim() correctly trims characters\",\n            sdslen(x) == 4 && memcmp(x,\"ciao\\0\",5) == 0)\n\n        y = sdsdup(x);\n        sdsrange(y,1,1);\n        test_cond(\"sdsrange(...,1,1)\",\n            sdslen(y) == 1 && memcmp(y,\"i\\0\",2) == 0)\n\n        sdsfree(y);\n        y = sdsdup(x);\n        sdsrange(y,1,-1);\n        test_cond(\"sdsrange(...,1,-1)\",\n            sdslen(y) == 3 && memcmp(y,\"iao\\0\",4) == 0)\n\n        sdsfree(y);\n        y = sdsdup(x);\n        sdsrange(y,-2,-1);\n        test_cond(\"sdsrange(...,-2,-1)\",\n            sdslen(y) == 2 && memcmp(y,\"ao\\0\",3) == 0)\n\n        sdsfree(y);\n        y = sdsdup(x);\n        sdsrange(y,2,1);\n        test_cond(\"sdsrange(...,2,1)\",\n            sdslen(y) == 0 && memcmp(y,\"\\0\",1) == 0)\n\n        sdsfree(y);\n        y = sdsdup(x);\n        sdsrange(y,1,100);\n        test_cond(\"sdsrange(...,1,100)\",\n            sdslen(y) == 3 && memcmp(y,\"iao\\0\",4) == 0)\n\n        sdsfree(y);\n        y = sdsdup(x);\n        sdsrange(y,100,100);\n        test_cond(\"sdsrange(...,100,100)\",\n            sdslen(y) == 0 && memcmp(y,\"\\0\",1) == 0)\n\n        sdsfree(y);\n        sdsfree(x);\n        x = sdsnew(\"foo\");\n        y = sdsnew(\"foa\");\n        test_cond(\"sdscmp(foo,foa)\", sdscmp(x,y) > 0)\n\n        sdsfree(y);\n        sdsfree(x);\n        x = sdsnew(\"bar\");\n        y = sdsnew(\"bar\");\n        test_cond(\"sdscmp(bar,bar)\", sdscmp(x,y) == 0)\n\n        sdsfree(y);\n        sdsfree(x);\n        x = sdsnew(\"aar\");\n        y = sdsnew(\"bar\");\n        test_cond(\"sdscmp(bar,bar)\", sdscmp(x,y) < 0)\n\n        sdsfree(y);\n        sdsfree(x);\n        x = sdsnewlen(\"\\a\\n\\0foo\\r\",7);\n        y = sdscatrepr(sdsempty(),x,sdslen(x));\n        test_cond(\"sdscatrepr(...data...)\",\n            memcmp(y,\"\\\"\\\\a\\\\n\\\\x00foo\\\\r\\\"\",15) == 0)\n\n        {\n            int oldfree;\n\n            sdsfree(x);\n            sdsfree(y);\n            x = sdsnew(\"0\");\n            sh = (void*) (x-(sizeof(struct sdshdr)));\n            test_cond(\"sdsnew() free/len buffers\", sh->len == 1 && sh->free == 0);\n            x = sdsMakeRoomFor(x,1);\n            sh = (void*) (x-(sizeof(struct sdshdr)));\n            test_cond(\"sdsMakeRoomFor()\", sh->len == 1 && sh->free > 0);\n            oldfree = sh->free;\n            x[1] = '1';\n            sdsIncrLen(x,1);\n            test_cond(\"sdsIncrLen() -- content\", x[0] == '0' && x[1] == '1');\n            test_cond(\"sdsIncrLen() -- len\", sh->len == 2);\n            test_cond(\"sdsIncrLen() -- free\", sh->free == oldfree-1);\n\n            sdsfree(x);\n        }\n    }\n    test_report()\n    return 0;\n}\n#endif\n"
  },
  {
    "path": "extern/deprecated/redis-2.8.21/src/sds.h",
    "content": "/* SDSLib, A C dynamic strings library\n *\n * Copyright (c) 2006-2010, Salvatore Sanfilippo <antirez at gmail dot com>\n * All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions are met:\n *\n *   * Redistributions of source code must retain the above copyright notice,\n *     this list of conditions and the following disclaimer.\n *   * Redistributions in binary form must reproduce the above copyright\n *     notice, this list of conditions and the following disclaimer in the\n *     documentation and/or other materials provided with the distribution.\n *   * Neither the name of Redis nor the names of its contributors may be used\n *     to endorse or promote products derived from this software without\n *     specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\"\n * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\n * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE\n * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR\n * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF\n * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS\n * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN\n * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)\n * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE\n * POSSIBILITY OF SUCH DAMAGE.\n */\n\n#ifndef __SDS_H\n#define __SDS_H\n\n#define SDS_MAX_PREALLOC (1024*1024)\n\n#include <sys/types.h>\n#include <stdarg.h>\n\ntypedef char *sds;\n\nstruct sdshdr {\n    unsigned int len;\n    unsigned int free;\n    char buf[];\n};\n\nstatic inline size_t sdslen(const sds s) {\n    struct sdshdr *sh = (void*)(s-(sizeof(struct sdshdr)));\n    return sh->len;\n}\n\nstatic inline size_t sdsavail(const sds s) {\n    struct sdshdr *sh = (void*)(s-(sizeof(struct sdshdr)));\n    return sh->free;\n}\n\nsds sdsnewlen(const void *init, size_t initlen);\nsds sdsnew(const char *init);\nsds sdsempty(void);\nsize_t sdslen(const sds s);\nsds sdsdup(const sds s);\nvoid sdsfree(sds s);\nsize_t sdsavail(const sds s);\nsds sdsgrowzero(sds s, size_t len);\nsds sdscatlen(sds s, const void *t, size_t len);\nsds sdscat(sds s, const char *t);\nsds sdscatsds(sds s, const sds t);\nsds sdscpylen(sds s, const char *t, size_t len);\nsds sdscpy(sds s, const char *t);\n\nsds sdscatvprintf(sds s, const char *fmt, va_list ap);\n#ifdef __GNUC__\nsds sdscatprintf(sds s, const char *fmt, ...)\n    __attribute__((format(printf, 2, 3)));\n#else\nsds sdscatprintf(sds s, const char *fmt, ...);\n#endif\n\nsds sdscatfmt(sds s, char const *fmt, ...);\nsds sdstrim(sds s, const char *cset);\nvoid sdsrange(sds s, int start, int end);\nvoid sdsupdatelen(sds s);\nvoid sdsclear(sds s);\nint sdscmp(const sds s1, const sds s2);\nsds *sdssplitlen(const char *s, int len, const char *sep, int seplen, int *count);\nvoid sdsfreesplitres(sds *tokens, int count);\nvoid sdstolower(sds s);\nvoid sdstoupper(sds s);\nsds sdsfromlonglong(long long value);\nsds sdscatrepr(sds s, const char *p, size_t len);\nsds *sdssplitargs(const char *line, int *argc);\nsds sdsmapchars(sds s, const char *from, const char *to, size_t setlen);\nsds sdsjoin(char **argv, int argc, char *sep);\n\n/* Low level functions exposed to the user API */\nsds sdsMakeRoomFor(sds s, size_t addlen);\nvoid sdsIncrLen(sds s, int incr);\nsds sdsRemoveFreeSpace(sds s);\nsize_t sdsAllocSize(sds s);\n\n#endif\n"
  },
  {
    "path": "extern/deprecated/redis-2.8.21/src/sentinel.c",
    "content": "/* Redis Sentinel implementation\n *\n * Copyright (c) 2009-2012, Salvatore Sanfilippo <antirez at gmail dot com>\n * All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions are met:\n *\n *   * Redistributions of source code must retain the above copyright notice,\n *     this list of conditions and the following disclaimer.\n *   * Redistributions in binary form must reproduce the above copyright\n *     notice, this list of conditions and the following disclaimer in the\n *     documentation and/or other materials provided with the distribution.\n *   * Neither the name of Redis nor the names of its contributors may be used\n *     to endorse or promote products derived from this software without\n *     specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\"\n * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\n * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE\n * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR\n * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF\n * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS\n * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN\n * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)\n * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE\n * POSSIBILITY OF SUCH DAMAGE.\n */\n\n#include \"redis.h\"\n#include \"hiredis.h\"\n#include \"async.h\"\n\n#include <ctype.h>\n#include <arpa/inet.h>\n#include <sys/socket.h>\n#include <sys/wait.h>\n#include <fcntl.h>\n\nextern char **environ;\n\n#define REDIS_SENTINEL_PORT 26379\n\n/* ======================== Sentinel global state =========================== */\n\n/* Address object, used to describe an ip:port pair. */\ntypedef struct sentinelAddr {\n    char *ip;\n    int port;\n} sentinelAddr;\n\n/* A Sentinel Redis Instance object is monitoring. */\n#define SRI_MASTER  (1<<0)\n#define SRI_SLAVE   (1<<1)\n#define SRI_SENTINEL (1<<2)\n#define SRI_DISCONNECTED (1<<3)\n#define SRI_S_DOWN (1<<4)   /* Subjectively down (no quorum). */\n#define SRI_O_DOWN (1<<5)   /* Objectively down (confirmed by others). */\n#define SRI_MASTER_DOWN (1<<6) /* A Sentinel with this flag set thinks that\n                                   its master is down. */\n#define SRI_FAILOVER_IN_PROGRESS (1<<7) /* Failover is in progress for\n                                           this master. */\n#define SRI_PROMOTED (1<<8)            /* Slave selected for promotion. */\n#define SRI_RECONF_SENT (1<<9)     /* SLAVEOF <newmaster> sent. */\n#define SRI_RECONF_INPROG (1<<10)   /* Slave synchronization in progress. */\n#define SRI_RECONF_DONE (1<<11)     /* Slave synchronized with new master. */\n#define SRI_FORCE_FAILOVER (1<<12)  /* Force failover with master up. */\n#define SRI_SCRIPT_KILL_SENT (1<<13) /* SCRIPT KILL already sent on -BUSY */\n\n/* Note: times are in milliseconds. */\n#define SENTINEL_INFO_PERIOD 10000\n#define SENTINEL_PING_PERIOD 1000\n#define SENTINEL_ASK_PERIOD 1000\n#define SENTINEL_PUBLISH_PERIOD 2000\n#define SENTINEL_DEFAULT_DOWN_AFTER 30000\n#define SENTINEL_HELLO_CHANNEL \"__sentinel__:hello\"\n#define SENTINEL_TILT_TRIGGER 2000\n#define SENTINEL_TILT_PERIOD (SENTINEL_PING_PERIOD*30)\n#define SENTINEL_DEFAULT_SLAVE_PRIORITY 100\n#define SENTINEL_SLAVE_RECONF_TIMEOUT 10000\n#define SENTINEL_DEFAULT_PARALLEL_SYNCS 1\n#define SENTINEL_MIN_LINK_RECONNECT_PERIOD 15000\n#define SENTINEL_DEFAULT_FAILOVER_TIMEOUT (60*3*1000)\n#define SENTINEL_MAX_PENDING_COMMANDS 100\n#define SENTINEL_ELECTION_TIMEOUT 10000\n#define SENTINEL_MAX_DESYNC 1000\n\n/* Failover machine different states. */\n#define SENTINEL_FAILOVER_STATE_NONE 0  /* No failover in progress. */\n#define SENTINEL_FAILOVER_STATE_WAIT_START 1  /* Wait for failover_start_time*/\n#define SENTINEL_FAILOVER_STATE_SELECT_SLAVE 2 /* Select slave to promote */\n#define SENTINEL_FAILOVER_STATE_SEND_SLAVEOF_NOONE 3 /* Slave -> Master */\n#define SENTINEL_FAILOVER_STATE_WAIT_PROMOTION 4 /* Wait slave to change role */\n#define SENTINEL_FAILOVER_STATE_RECONF_SLAVES 5 /* SLAVEOF newmaster */\n#define SENTINEL_FAILOVER_STATE_UPDATE_CONFIG 6 /* Monitor promoted slave. */\n\n#define SENTINEL_MASTER_LINK_STATUS_UP 0\n#define SENTINEL_MASTER_LINK_STATUS_DOWN 1\n\n/* Generic flags that can be used with different functions.\n * They use higher bits to avoid colliding with the function specific\n * flags. */\n#define SENTINEL_NO_FLAGS 0\n#define SENTINEL_GENERATE_EVENT (1<<16)\n#define SENTINEL_LEADER (1<<17)\n#define SENTINEL_OBSERVER (1<<18)\n\n/* Script execution flags and limits. */\n#define SENTINEL_SCRIPT_NONE 0\n#define SENTINEL_SCRIPT_RUNNING 1\n#define SENTINEL_SCRIPT_MAX_QUEUE 256\n#define SENTINEL_SCRIPT_MAX_RUNNING 16\n#define SENTINEL_SCRIPT_MAX_RUNTIME 60000 /* 60 seconds max exec time. */\n#define SENTINEL_SCRIPT_MAX_RETRY 10\n#define SENTINEL_SCRIPT_RETRY_DELAY 30000 /* 30 seconds between retries. */\n\ntypedef struct sentinelRedisInstance {\n    int flags;      /* See SRI_... defines */\n    char *name;     /* Master name from the point of view of this sentinel. */\n    char *runid;    /* run ID of this instance. */\n    uint64_t config_epoch;  /* Configuration epoch. */\n    sentinelAddr *addr; /* Master host. */\n    redisAsyncContext *cc; /* Hiredis context for commands. */\n    redisAsyncContext *pc; /* Hiredis context for Pub / Sub. */\n    int pending_commands;   /* Number of commands sent waiting for a reply. */\n    mstime_t cc_conn_time; /* cc connection time. */\n    mstime_t pc_conn_time; /* pc connection time. */\n    mstime_t pc_last_activity; /* Last time we received any message. */\n    mstime_t last_avail_time; /* Last time the instance replied to ping with\n                                 a reply we consider valid. */\n    mstime_t last_ping_time;  /* Last time a pending ping was sent in the\n                                 context of the current command connection\n                                 with the instance. 0 if still not sent or\n                                 if pong already received. */\n    mstime_t last_pong_time;  /* Last time the instance replied to ping,\n                                 whatever the reply was. That's used to check\n                                 if the link is idle and must be reconnected. */\n    mstime_t last_pub_time;   /* Last time we sent hello via Pub/Sub. */\n    mstime_t last_hello_time; /* Only used if SRI_SENTINEL is set. Last time\n                                 we received a hello from this Sentinel\n                                 via Pub/Sub. */\n    mstime_t last_master_down_reply_time; /* Time of last reply to\n                                             SENTINEL is-master-down command. */\n    mstime_t s_down_since_time; /* Subjectively down since time. */\n    mstime_t o_down_since_time; /* Objectively down since time. */\n    mstime_t down_after_period; /* Consider it down after that period. */\n    mstime_t info_refresh;  /* Time at which we received INFO output from it. */\n\n    /* Role and the first time we observed it.\n     * This is useful in order to delay replacing what the instance reports\n     * with our own configuration. We need to always wait some time in order\n     * to give a chance to the leader to report the new configuration before\n     * we do silly things. */\n    int role_reported;\n    mstime_t role_reported_time;\n    mstime_t slave_conf_change_time; /* Last time slave master addr changed. */\n\n    /* Master specific. */\n    dict *sentinels;    /* Other sentinels monitoring the same master. */\n    dict *slaves;       /* Slaves for this master instance. */\n    unsigned int quorum;/* Number of sentinels that need to agree on failure. */\n    int parallel_syncs; /* How many slaves to reconfigure at same time. */\n    char *auth_pass;    /* Password to use for AUTH against master & slaves. */\n\n    /* Slave specific. */\n    mstime_t master_link_down_time; /* Slave replication link down time. */\n    int slave_priority; /* Slave priority according to its INFO output. */\n    mstime_t slave_reconf_sent_time; /* Time at which we sent SLAVE OF <new> */\n    struct sentinelRedisInstance *master; /* Master instance if it's slave. */\n    char *slave_master_host;    /* Master host as reported by INFO */\n    int slave_master_port;      /* Master port as reported by INFO */\n    int slave_master_link_status; /* Master link status as reported by INFO */\n    unsigned long long slave_repl_offset; /* Slave replication offset. */\n    /* Failover */\n    char *leader;       /* If this is a master instance, this is the runid of\n                           the Sentinel that should perform the failover. If\n                           this is a Sentinel, this is the runid of the Sentinel\n                           that this Sentinel voted as leader. */\n    uint64_t leader_epoch; /* Epoch of the 'leader' field. */\n    uint64_t failover_epoch; /* Epoch of the currently started failover. */\n    int failover_state; /* See SENTINEL_FAILOVER_STATE_* defines. */\n    mstime_t failover_state_change_time;\n    mstime_t failover_start_time;   /* Last failover attempt start time. */\n    mstime_t failover_timeout;      /* Max time to refresh failover state. */\n    mstime_t failover_delay_logged; /* For what failover_start_time value we\n                                       logged the failover delay. */\n    struct sentinelRedisInstance *promoted_slave; /* Promoted slave instance. */\n    /* Scripts executed to notify admin or reconfigure clients: when they\n     * are set to NULL no script is executed. */\n    char *notification_script;\n    char *client_reconfig_script;\n} sentinelRedisInstance;\n\n/* Main state. */\nstruct sentinelState {\n    uint64_t current_epoch;     /* Current epoch. */\n    dict *masters;      /* Dictionary of master sentinelRedisInstances.\n                           Key is the instance name, value is the\n                           sentinelRedisInstance structure pointer. */\n    int tilt;           /* Are we in TILT mode? */\n    int running_scripts;    /* Number of scripts in execution right now. */\n    mstime_t tilt_start_time;   /* When TITL started. */\n    mstime_t previous_time;     /* Last time we ran the time handler. */\n    list *scripts_queue;    /* Queue of user scripts to execute. */\n    char *announce_ip;      /* IP addr that is gossiped to other sentinels if\n                               not NULL. */\n    int announce_port;      /* Port that is gossiped to other sentinels if\n                               non zero. */\n} sentinel;\n\n/* A script execution job. */\ntypedef struct sentinelScriptJob {\n    int flags;              /* Script job flags: SENTINEL_SCRIPT_* */\n    int retry_num;          /* Number of times we tried to execute it. */\n    char **argv;            /* Arguments to call the script. */\n    mstime_t start_time;    /* Script execution time if the script is running,\n                               otherwise 0 if we are allowed to retry the\n                               execution at any time. If the script is not\n                               running and it's not 0, it means: do not run\n                               before the specified time. */\n    pid_t pid;              /* Script execution pid. */\n} sentinelScriptJob;\n\n/* ======================= hiredis ae.c adapters =============================\n * Note: this implementation is taken from hiredis/adapters/ae.h, however\n * we have our modified copy for Sentinel in order to use our allocator\n * and to have full control over how the adapter works. */\n\ntypedef struct redisAeEvents {\n    redisAsyncContext *context;\n    aeEventLoop *loop;\n    int fd;\n    int reading, writing;\n} redisAeEvents;\n\nstatic void redisAeReadEvent(aeEventLoop *el, int fd, void *privdata, int mask) {\n    ((void)el); ((void)fd); ((void)mask);\n\n    redisAeEvents *e = (redisAeEvents*)privdata;\n    redisAsyncHandleRead(e->context);\n}\n\nstatic void redisAeWriteEvent(aeEventLoop *el, int fd, void *privdata, int mask) {\n    ((void)el); ((void)fd); ((void)mask);\n\n    redisAeEvents *e = (redisAeEvents*)privdata;\n    redisAsyncHandleWrite(e->context);\n}\n\nstatic void redisAeAddRead(void *privdata) {\n    redisAeEvents *e = (redisAeEvents*)privdata;\n    aeEventLoop *loop = e->loop;\n    if (!e->reading) {\n        e->reading = 1;\n        aeCreateFileEvent(loop,e->fd,AE_READABLE,redisAeReadEvent,e);\n    }\n}\n\nstatic void redisAeDelRead(void *privdata) {\n    redisAeEvents *e = (redisAeEvents*)privdata;\n    aeEventLoop *loop = e->loop;\n    if (e->reading) {\n        e->reading = 0;\n        aeDeleteFileEvent(loop,e->fd,AE_READABLE);\n    }\n}\n\nstatic void redisAeAddWrite(void *privdata) {\n    redisAeEvents *e = (redisAeEvents*)privdata;\n    aeEventLoop *loop = e->loop;\n    if (!e->writing) {\n        e->writing = 1;\n        aeCreateFileEvent(loop,e->fd,AE_WRITABLE,redisAeWriteEvent,e);\n    }\n}\n\nstatic void redisAeDelWrite(void *privdata) {\n    redisAeEvents *e = (redisAeEvents*)privdata;\n    aeEventLoop *loop = e->loop;\n    if (e->writing) {\n        e->writing = 0;\n        aeDeleteFileEvent(loop,e->fd,AE_WRITABLE);\n    }\n}\n\nstatic void redisAeCleanup(void *privdata) {\n    redisAeEvents *e = (redisAeEvents*)privdata;\n    redisAeDelRead(privdata);\n    redisAeDelWrite(privdata);\n    zfree(e);\n}\n\nstatic int redisAeAttach(aeEventLoop *loop, redisAsyncContext *ac) {\n    redisContext *c = &(ac->c);\n    redisAeEvents *e;\n\n    /* Nothing should be attached when something is already attached */\n    if (ac->ev.data != NULL)\n        return REDIS_ERR;\n\n    /* Create container for context and r/w events */\n    e = (redisAeEvents*)zmalloc(sizeof(*e));\n    e->context = ac;\n    e->loop = loop;\n    e->fd = c->fd;\n    e->reading = e->writing = 0;\n\n    /* Register functions to start/stop listening for events */\n    ac->ev.addRead = redisAeAddRead;\n    ac->ev.delRead = redisAeDelRead;\n    ac->ev.addWrite = redisAeAddWrite;\n    ac->ev.delWrite = redisAeDelWrite;\n    ac->ev.cleanup = redisAeCleanup;\n    ac->ev.data = e;\n\n    return REDIS_OK;\n}\n\n/* ============================= Prototypes ================================= */\n\nvoid sentinelLinkEstablishedCallback(const redisAsyncContext *c, int status);\nvoid sentinelDisconnectCallback(const redisAsyncContext *c, int status);\nvoid sentinelReceiveHelloMessages(redisAsyncContext *c, void *reply, void *privdata);\nsentinelRedisInstance *sentinelGetMasterByName(char *name);\nchar *sentinelGetSubjectiveLeader(sentinelRedisInstance *master);\nchar *sentinelGetObjectiveLeader(sentinelRedisInstance *master);\nint yesnotoi(char *s);\nvoid sentinelDisconnectInstanceFromContext(const redisAsyncContext *c);\nvoid sentinelKillLink(sentinelRedisInstance *ri, redisAsyncContext *c);\nconst char *sentinelRedisInstanceTypeStr(sentinelRedisInstance *ri);\nvoid sentinelAbortFailover(sentinelRedisInstance *ri);\nvoid sentinelEvent(int level, char *type, sentinelRedisInstance *ri, const char *fmt, ...);\nsentinelRedisInstance *sentinelSelectSlave(sentinelRedisInstance *master);\nvoid sentinelScheduleScriptExecution(char *path, ...);\nvoid sentinelStartFailover(sentinelRedisInstance *master);\nvoid sentinelDiscardReplyCallback(redisAsyncContext *c, void *reply, void *privdata);\nint sentinelSendSlaveOf(sentinelRedisInstance *ri, char *host, int port);\nchar *sentinelVoteLeader(sentinelRedisInstance *master, uint64_t req_epoch, char *req_runid, uint64_t *leader_epoch);\nvoid sentinelFlushConfig(void);\nvoid sentinelGenerateInitialMonitorEvents(void);\nint sentinelSendPing(sentinelRedisInstance *ri);\nint sentinelForceHelloUpdateForMaster(sentinelRedisInstance *master);\n\n/* ========================= Dictionary types =============================== */\n\nunsigned int dictSdsHash(const void *key);\nint dictSdsKeyCompare(void *privdata, const void *key1, const void *key2);\nvoid releaseSentinelRedisInstance(sentinelRedisInstance *ri);\n\nvoid dictInstancesValDestructor (void *privdata, void *obj) {\n    REDIS_NOTUSED(privdata);\n    releaseSentinelRedisInstance(obj);\n}\n\n/* Instance name (sds) -> instance (sentinelRedisInstance pointer)\n *\n * also used for: sentinelRedisInstance->sentinels dictionary that maps\n * sentinels ip:port to last seen time in Pub/Sub hello message. */\ndictType instancesDictType = {\n    dictSdsHash,               /* hash function */\n    NULL,                      /* key dup */\n    NULL,                      /* val dup */\n    dictSdsKeyCompare,         /* key compare */\n    NULL,                      /* key destructor */\n    dictInstancesValDestructor /* val destructor */\n};\n\n/* Instance runid (sds) -> votes (long casted to void*)\n *\n * This is useful into sentinelGetObjectiveLeader() function in order to\n * count the votes and understand who is the leader. */\ndictType leaderVotesDictType = {\n    dictSdsHash,               /* hash function */\n    NULL,                      /* key dup */\n    NULL,                      /* val dup */\n    dictSdsKeyCompare,         /* key compare */\n    NULL,                      /* key destructor */\n    NULL                       /* val destructor */\n};\n\n/* =========================== Initialization =============================== */\n\nvoid sentinelCommand(redisClient *c);\nvoid sentinelInfoCommand(redisClient *c);\nvoid sentinelSetCommand(redisClient *c);\nvoid sentinelPublishCommand(redisClient *c);\nvoid sentinelRoleCommand(redisClient *c);\n\nstruct redisCommand sentinelcmds[] = {\n    {\"ping\",pingCommand,1,\"\",0,NULL,0,0,0,0,0},\n    {\"sentinel\",sentinelCommand,-2,\"\",0,NULL,0,0,0,0,0},\n    {\"subscribe\",subscribeCommand,-2,\"\",0,NULL,0,0,0,0,0},\n    {\"unsubscribe\",unsubscribeCommand,-1,\"\",0,NULL,0,0,0,0,0},\n    {\"psubscribe\",psubscribeCommand,-2,\"\",0,NULL,0,0,0,0,0},\n    {\"punsubscribe\",punsubscribeCommand,-1,\"\",0,NULL,0,0,0,0,0},\n    {\"publish\",sentinelPublishCommand,3,\"\",0,NULL,0,0,0,0,0},\n    {\"info\",sentinelInfoCommand,-1,\"\",0,NULL,0,0,0,0,0},\n    {\"role\",sentinelRoleCommand,1,\"l\",0,NULL,0,0,0,0,0},\n    {\"shutdown\",shutdownCommand,-1,\"\",0,NULL,0,0,0,0,0}\n};\n\n/* This function overwrites a few normal Redis config default with Sentinel\n * specific defaults. */\nvoid initSentinelConfig(void) {\n    server.port = REDIS_SENTINEL_PORT;\n}\n\n/* Perform the Sentinel mode initialization. */\nvoid initSentinel(void) {\n    unsigned int j;\n\n    /* Remove usual Redis commands from the command table, then just add\n     * the SENTINEL command. */\n    dictEmpty(server.commands,NULL);\n    for (j = 0; j < sizeof(sentinelcmds)/sizeof(sentinelcmds[0]); j++) {\n        int retval;\n        struct redisCommand *cmd = sentinelcmds+j;\n\n        retval = dictAdd(server.commands, sdsnew(cmd->name), cmd);\n        redisAssert(retval == DICT_OK);\n    }\n\n    /* Initialize various data structures. */\n    sentinel.current_epoch = 0;\n    sentinel.masters = dictCreate(&instancesDictType,NULL);\n    sentinel.tilt = 0;\n    sentinel.tilt_start_time = 0;\n    sentinel.previous_time = mstime();\n    sentinel.running_scripts = 0;\n    sentinel.scripts_queue = listCreate();\n    sentinel.announce_ip = NULL;\n    sentinel.announce_port = 0;\n}\n\n/* This function gets called when the server is in Sentinel mode, started,\n * loaded the configuration, and is ready for normal operations. */\nvoid sentinelIsRunning(void) {\n    redisLog(REDIS_WARNING,\"Sentinel runid is %s\", server.runid);\n\n    if (server.configfile == NULL) {\n        redisLog(REDIS_WARNING,\n            \"Sentinel started without a config file. Exiting...\");\n        exit(1);\n    } else if (access(server.configfile,W_OK) == -1) {\n        redisLog(REDIS_WARNING,\n            \"Sentinel config file %s is not writable: %s. Exiting...\",\n            server.configfile,strerror(errno));\n        exit(1);\n    }\n\n    /* We want to generate a +monitor event for every configured master\n     * at startup. */\n    sentinelGenerateInitialMonitorEvents();\n}\n\n/* ============================== sentinelAddr ============================== */\n\n/* Create a sentinelAddr object and return it on success.\n * On error NULL is returned and errno is set to:\n *  ENOENT: Can't resolve the hostname.\n *  EINVAL: Invalid port number.\n */\nsentinelAddr *createSentinelAddr(char *hostname, int port) {\n    char ip[REDIS_IP_STR_LEN];\n    sentinelAddr *sa;\n\n    if (port <= 0 || port > 65535) {\n        errno = EINVAL;\n        return NULL;\n    }\n    if (anetResolve(NULL,hostname,ip,sizeof(ip)) == ANET_ERR) {\n        errno = ENOENT;\n        return NULL;\n    }\n    sa = zmalloc(sizeof(*sa));\n    sa->ip = sdsnew(ip);\n    sa->port = port;\n    return sa;\n}\n\n/* Return a duplicate of the source address. */\nsentinelAddr *dupSentinelAddr(sentinelAddr *src) {\n    sentinelAddr *sa;\n\n    sa = zmalloc(sizeof(*sa));\n    sa->ip = sdsnew(src->ip);\n    sa->port = src->port;\n    return sa;\n}\n\n/* Free a Sentinel address. Can't fail. */\nvoid releaseSentinelAddr(sentinelAddr *sa) {\n    sdsfree(sa->ip);\n    zfree(sa);\n}\n\n/* Return non-zero if two addresses are equal. */\nint sentinelAddrIsEqual(sentinelAddr *a, sentinelAddr *b) {\n    return a->port == b->port && !strcasecmp(a->ip,b->ip);\n}\n\n/* =========================== Events notification ========================== */\n\n/* Send an event to log, pub/sub, user notification script.\n *\n * 'level' is the log level for logging. Only REDIS_WARNING events will trigger\n * the execution of the user notification script.\n *\n * 'type' is the message type, also used as a pub/sub channel name.\n *\n * 'ri', is the redis instance target of this event if applicable, and is\n * used to obtain the path of the notification script to execute.\n *\n * The remaining arguments are printf-alike.\n * If the format specifier starts with the two characters \"%@\" then ri is\n * not NULL, and the message is prefixed with an instance identifier in the\n * following format:\n *\n *  <instance type> <instance name> <ip> <port>\n *\n *  If the instance type is not master, than the additional string is\n *  added to specify the originating master:\n *\n *  @ <master name> <master ip> <master port>\n *\n *  Any other specifier after \"%@\" is processed by printf itself.\n */\nvoid sentinelEvent(int level, char *type, sentinelRedisInstance *ri,\n                   const char *fmt, ...) {\n    va_list ap;\n    char msg[REDIS_MAX_LOGMSG_LEN];\n    robj *channel, *payload;\n\n    /* Handle %@ */\n    if (fmt[0] == '%' && fmt[1] == '@') {\n        sentinelRedisInstance *master = (ri->flags & SRI_MASTER) ?\n                                         NULL : ri->master;\n\n        if (master) {\n            snprintf(msg, sizeof(msg), \"%s %s %s %d @ %s %s %d\",\n                sentinelRedisInstanceTypeStr(ri),\n                ri->name, ri->addr->ip, ri->addr->port,\n                master->name, master->addr->ip, master->addr->port);\n        } else {\n            snprintf(msg, sizeof(msg), \"%s %s %s %d\",\n                sentinelRedisInstanceTypeStr(ri),\n                ri->name, ri->addr->ip, ri->addr->port);\n        }\n        fmt += 2;\n    } else {\n        msg[0] = '\\0';\n    }\n\n    /* Use vsprintf for the rest of the formatting if any. */\n    if (fmt[0] != '\\0') {\n        va_start(ap, fmt);\n        vsnprintf(msg+strlen(msg), sizeof(msg)-strlen(msg), fmt, ap);\n        va_end(ap);\n    }\n\n    /* Log the message if the log level allows it to be logged. */\n    if (level >= server.verbosity)\n        redisLog(level,\"%s %s\",type,msg);\n\n    /* Publish the message via Pub/Sub if it's not a debugging one. */\n    if (level != REDIS_DEBUG) {\n        channel = createStringObject(type,strlen(type));\n        payload = createStringObject(msg,strlen(msg));\n        pubsubPublishMessage(channel,payload);\n        decrRefCount(channel);\n        decrRefCount(payload);\n    }\n\n    /* Call the notification script if applicable. */\n    if (level == REDIS_WARNING && ri != NULL) {\n        sentinelRedisInstance *master = (ri->flags & SRI_MASTER) ?\n                                         ri : ri->master;\n        if (master->notification_script) {\n            sentinelScheduleScriptExecution(master->notification_script,\n                type,msg,NULL);\n        }\n    }\n}\n\n/* This function is called only at startup and is used to generate a\n * +monitor event for every configured master. The same events are also\n * generated when a master to monitor is added at runtime via the\n * SENTINEL MONITOR command. */\nvoid sentinelGenerateInitialMonitorEvents(void) {\n    dictIterator *di;\n    dictEntry *de;\n\n    di = dictGetIterator(sentinel.masters);\n    while((de = dictNext(di)) != NULL) {\n        sentinelRedisInstance *ri = dictGetVal(de);\n        sentinelEvent(REDIS_WARNING,\"+monitor\",ri,\"%@ quorum %d\",ri->quorum);\n    }\n    dictReleaseIterator(di);\n}\n\n/* ============================ script execution ============================ */\n\n/* Release a script job structure and all the associated data. */\nvoid sentinelReleaseScriptJob(sentinelScriptJob *sj) {\n    int j = 0;\n\n    while(sj->argv[j]) sdsfree(sj->argv[j++]);\n    zfree(sj->argv);\n    zfree(sj);\n}\n\n#define SENTINEL_SCRIPT_MAX_ARGS 16\nvoid sentinelScheduleScriptExecution(char *path, ...) {\n    va_list ap;\n    char *argv[SENTINEL_SCRIPT_MAX_ARGS+1];\n    int argc = 1;\n    sentinelScriptJob *sj;\n\n    va_start(ap, path);\n    while(argc < SENTINEL_SCRIPT_MAX_ARGS) {\n        argv[argc] = va_arg(ap,char*);\n        if (!argv[argc]) break;\n        argv[argc] = sdsnew(argv[argc]); /* Copy the string. */\n        argc++;\n    }\n    va_end(ap);\n    argv[0] = sdsnew(path);\n\n    sj = zmalloc(sizeof(*sj));\n    sj->flags = SENTINEL_SCRIPT_NONE;\n    sj->retry_num = 0;\n    sj->argv = zmalloc(sizeof(char*)*(argc+1));\n    sj->start_time = 0;\n    sj->pid = 0;\n    memcpy(sj->argv,argv,sizeof(char*)*(argc+1));\n\n    listAddNodeTail(sentinel.scripts_queue,sj);\n\n    /* Remove the oldest non running script if we already hit the limit. */\n    if (listLength(sentinel.scripts_queue) > SENTINEL_SCRIPT_MAX_QUEUE) {\n        listNode *ln;\n        listIter li;\n\n        listRewind(sentinel.scripts_queue,&li);\n        while ((ln = listNext(&li)) != NULL) {\n            sj = ln->value;\n\n            if (sj->flags & SENTINEL_SCRIPT_RUNNING) continue;\n            /* The first node is the oldest as we add on tail. */\n            listDelNode(sentinel.scripts_queue,ln);\n            sentinelReleaseScriptJob(sj);\n            break;\n        }\n        redisAssert(listLength(sentinel.scripts_queue) <=\n                    SENTINEL_SCRIPT_MAX_QUEUE);\n    }\n}\n\n/* Lookup a script in the scripts queue via pid, and returns the list node\n * (so that we can easily remove it from the queue if needed). */\nlistNode *sentinelGetScriptListNodeByPid(pid_t pid) {\n    listNode *ln;\n    listIter li;\n\n    listRewind(sentinel.scripts_queue,&li);\n    while ((ln = listNext(&li)) != NULL) {\n        sentinelScriptJob *sj = ln->value;\n\n        if ((sj->flags & SENTINEL_SCRIPT_RUNNING) && sj->pid == pid)\n            return ln;\n    }\n    return NULL;\n}\n\n/* Run pending scripts if we are not already at max number of running\n * scripts. */\nvoid sentinelRunPendingScripts(void) {\n    listNode *ln;\n    listIter li;\n    mstime_t now = mstime();\n\n    /* Find jobs that are not running and run them, from the top to the\n     * tail of the queue, so we run older jobs first. */\n    listRewind(sentinel.scripts_queue,&li);\n    while (sentinel.running_scripts < SENTINEL_SCRIPT_MAX_RUNNING &&\n           (ln = listNext(&li)) != NULL)\n    {\n        sentinelScriptJob *sj = ln->value;\n        pid_t pid;\n\n        /* Skip if already running. */\n        if (sj->flags & SENTINEL_SCRIPT_RUNNING) continue;\n\n        /* Skip if it's a retry, but not enough time has elapsed. */\n        if (sj->start_time && sj->start_time > now) continue;\n\n        sj->flags |= SENTINEL_SCRIPT_RUNNING;\n        sj->start_time = mstime();\n        sj->retry_num++;\n        pid = fork();\n\n        if (pid == -1) {\n            /* Parent (fork error).\n             * We report fork errors as signal 99, in order to unify the\n             * reporting with other kind of errors. */\n            sentinelEvent(REDIS_WARNING,\"-script-error\",NULL,\n                          \"%s %d %d\", sj->argv[0], 99, 0);\n            sj->flags &= ~SENTINEL_SCRIPT_RUNNING;\n            sj->pid = 0;\n        } else if (pid == 0) {\n            /* Child */\n            execve(sj->argv[0],sj->argv,environ);\n            /* If we are here an error occurred. */\n            _exit(2); /* Don't retry execution. */\n        } else {\n            sentinel.running_scripts++;\n            sj->pid = pid;\n            sentinelEvent(REDIS_DEBUG,\"+script-child\",NULL,\"%ld\",(long)pid);\n        }\n    }\n}\n\n/* How much to delay the execution of a script that we need to retry after\n * an error?\n *\n * We double the retry delay for every further retry we do. So for instance\n * if RETRY_DELAY is set to 30 seconds and the max number of retries is 10\n * starting from the second attempt to execute the script the delays are:\n * 30 sec, 60 sec, 2 min, 4 min, 8 min, 16 min, 32 min, 64 min, 128 min. */\nmstime_t sentinelScriptRetryDelay(int retry_num) {\n    mstime_t delay = SENTINEL_SCRIPT_RETRY_DELAY;\n\n    while (retry_num-- > 1) delay *= 2;\n    return delay;\n}\n\n/* Check for scripts that terminated, and remove them from the queue if the\n * script terminated successfully. If instead the script was terminated by\n * a signal, or returned exit code \"1\", it is scheduled to run again if\n * the max number of retries did not already elapsed. */\nvoid sentinelCollectTerminatedScripts(void) {\n    int statloc;\n    pid_t pid;\n\n    while ((pid = wait3(&statloc,WNOHANG,NULL)) > 0) {\n        int exitcode = WEXITSTATUS(statloc);\n        int bysignal = 0;\n        listNode *ln;\n        sentinelScriptJob *sj;\n\n        if (WIFSIGNALED(statloc)) bysignal = WTERMSIG(statloc);\n        sentinelEvent(REDIS_DEBUG,\"-script-child\",NULL,\"%ld %d %d\",\n            (long)pid, exitcode, bysignal);\n\n        ln = sentinelGetScriptListNodeByPid(pid);\n        if (ln == NULL) {\n            redisLog(REDIS_WARNING,\"wait3() returned a pid (%ld) we can't find in our scripts execution queue!\", (long)pid);\n            continue;\n        }\n        sj = ln->value;\n\n        /* If the script was terminated by a signal or returns an\n         * exit code of \"1\" (that means: please retry), we reschedule it\n         * if the max number of retries is not already reached. */\n        if ((bysignal || exitcode == 1) &&\n            sj->retry_num != SENTINEL_SCRIPT_MAX_RETRY)\n        {\n            sj->flags &= ~SENTINEL_SCRIPT_RUNNING;\n            sj->pid = 0;\n            sj->start_time = mstime() +\n                             sentinelScriptRetryDelay(sj->retry_num);\n        } else {\n            /* Otherwise let's remove the script, but log the event if the\n             * execution did not terminated in the best of the ways. */\n            if (bysignal || exitcode != 0) {\n                sentinelEvent(REDIS_WARNING,\"-script-error\",NULL,\n                              \"%s %d %d\", sj->argv[0], bysignal, exitcode);\n            }\n            listDelNode(sentinel.scripts_queue,ln);\n            sentinelReleaseScriptJob(sj);\n            sentinel.running_scripts--;\n        }\n    }\n}\n\n/* Kill scripts in timeout, they'll be collected by the\n * sentinelCollectTerminatedScripts() function. */\nvoid sentinelKillTimedoutScripts(void) {\n    listNode *ln;\n    listIter li;\n    mstime_t now = mstime();\n\n    listRewind(sentinel.scripts_queue,&li);\n    while ((ln = listNext(&li)) != NULL) {\n        sentinelScriptJob *sj = ln->value;\n\n        if (sj->flags & SENTINEL_SCRIPT_RUNNING &&\n            (now - sj->start_time) > SENTINEL_SCRIPT_MAX_RUNTIME)\n        {\n            sentinelEvent(REDIS_WARNING,\"-script-timeout\",NULL,\"%s %ld\",\n                sj->argv[0], (long)sj->pid);\n            kill(sj->pid,SIGKILL);\n        }\n    }\n}\n\n/* Implements SENTINEL PENDING-SCRIPTS command. */\nvoid sentinelPendingScriptsCommand(redisClient *c) {\n    listNode *ln;\n    listIter li;\n\n    addReplyMultiBulkLen(c,listLength(sentinel.scripts_queue));\n    listRewind(sentinel.scripts_queue,&li);\n    while ((ln = listNext(&li)) != NULL) {\n        sentinelScriptJob *sj = ln->value;\n        int j = 0;\n\n        addReplyMultiBulkLen(c,10);\n\n        addReplyBulkCString(c,\"argv\");\n        while (sj->argv[j]) j++;\n        addReplyMultiBulkLen(c,j);\n        j = 0;\n        while (sj->argv[j]) addReplyBulkCString(c,sj->argv[j++]);\n\n        addReplyBulkCString(c,\"flags\");\n        addReplyBulkCString(c,\n            (sj->flags & SENTINEL_SCRIPT_RUNNING) ? \"running\" : \"scheduled\");\n\n        addReplyBulkCString(c,\"pid\");\n        addReplyBulkLongLong(c,sj->pid);\n\n        if (sj->flags & SENTINEL_SCRIPT_RUNNING) {\n            addReplyBulkCString(c,\"run-time\");\n            addReplyBulkLongLong(c,mstime() - sj->start_time);\n        } else {\n            mstime_t delay = sj->start_time ? (sj->start_time-mstime()) : 0;\n            if (delay < 0) delay = 0;\n            addReplyBulkCString(c,\"run-delay\");\n            addReplyBulkLongLong(c,delay);\n        }\n\n        addReplyBulkCString(c,\"retry-num\");\n        addReplyBulkLongLong(c,sj->retry_num);\n    }\n}\n\n/* This function calls, if any, the client reconfiguration script with the\n * following parameters:\n *\n * <master-name> <role> <state> <from-ip> <from-port> <to-ip> <to-port>\n *\n * It is called every time a failover is performed.\n *\n * <state> is currently always \"failover\".\n * <role> is either \"leader\" or \"observer\".\n *\n * from/to fields are respectively master -> promoted slave addresses for\n * \"start\" and \"end\". */\nvoid sentinelCallClientReconfScript(sentinelRedisInstance *master, int role, char *state, sentinelAddr *from, sentinelAddr *to) {\n    char fromport[32], toport[32];\n\n    if (master->client_reconfig_script == NULL) return;\n    ll2string(fromport,sizeof(fromport),from->port);\n    ll2string(toport,sizeof(toport),to->port);\n    sentinelScheduleScriptExecution(master->client_reconfig_script,\n        master->name,\n        (role == SENTINEL_LEADER) ? \"leader\" : \"observer\",\n        state, from->ip, fromport, to->ip, toport, NULL);\n}\n\n/* ========================== sentinelRedisInstance ========================= */\n\n/* Create a redis instance, the following fields must be populated by the\n * caller if needed:\n * runid: set to NULL but will be populated once INFO output is received.\n * info_refresh: is set to 0 to mean that we never received INFO so far.\n *\n * If SRI_MASTER is set into initial flags the instance is added to\n * sentinel.masters table.\n *\n * if SRI_SLAVE or SRI_SENTINEL is set then 'master' must be not NULL and the\n * instance is added into master->slaves or master->sentinels table.\n *\n * If the instance is a slave or sentinel, the name parameter is ignored and\n * is created automatically as hostname:port.\n *\n * The function fails if hostname can't be resolved or port is out of range.\n * When this happens NULL is returned and errno is set accordingly to the\n * createSentinelAddr() function.\n *\n * The function may also fail and return NULL with errno set to EBUSY if\n * a master or slave with the same name already exists. */\nsentinelRedisInstance *createSentinelRedisInstance(char *name, int flags, char *hostname, int port, int quorum, sentinelRedisInstance *master) {\n    sentinelRedisInstance *ri;\n    sentinelAddr *addr;\n    dict *table = NULL;\n    char slavename[128], *sdsname;\n\n    redisAssert(flags & (SRI_MASTER|SRI_SLAVE|SRI_SENTINEL));\n    redisAssert((flags & SRI_MASTER) || master != NULL);\n\n    /* Check address validity. */\n    addr = createSentinelAddr(hostname,port);\n    if (addr == NULL) return NULL;\n\n    /* For slaves and sentinel we use ip:port as name. */\n    if (flags & (SRI_SLAVE|SRI_SENTINEL)) {\n        snprintf(slavename,sizeof(slavename),\n            strchr(hostname,':') ? \"[%s]:%d\" : \"%s:%d\",\n            hostname,port);\n        name = slavename;\n    }\n\n    /* Make sure the entry is not duplicated. This may happen when the same\n     * name for a master is used multiple times inside the configuration or\n     * if we try to add multiple times a slave or sentinel with same ip/port\n     * to a master. */\n    if (flags & SRI_MASTER) table = sentinel.masters;\n    else if (flags & SRI_SLAVE) table = master->slaves;\n    else if (flags & SRI_SENTINEL) table = master->sentinels;\n    sdsname = sdsnew(name);\n    if (dictFind(table,sdsname)) {\n        releaseSentinelAddr(addr);\n        sdsfree(sdsname);\n        errno = EBUSY;\n        return NULL;\n    }\n\n    /* Create the instance object. */\n    ri = zmalloc(sizeof(*ri));\n    /* Note that all the instances are started in the disconnected state,\n     * the event loop will take care of connecting them. */\n    ri->flags = flags | SRI_DISCONNECTED;\n    ri->name = sdsname;\n    ri->runid = NULL;\n    ri->config_epoch = 0;\n    ri->addr = addr;\n    ri->cc = NULL;\n    ri->pc = NULL;\n    ri->pending_commands = 0;\n    ri->cc_conn_time = 0;\n    ri->pc_conn_time = 0;\n    ri->pc_last_activity = 0;\n    /* We set the last_ping_time to \"now\" even if we actually don't have yet\n     * a connection with the node, nor we sent a ping.\n     * This is useful to detect a timeout in case we'll not be able to connect\n     * with the node at all. */\n    ri->last_ping_time = mstime();\n    ri->last_avail_time = mstime();\n    ri->last_pong_time = mstime();\n    ri->last_pub_time = mstime();\n    ri->last_hello_time = mstime();\n    ri->last_master_down_reply_time = mstime();\n    ri->s_down_since_time = 0;\n    ri->o_down_since_time = 0;\n    ri->down_after_period = master ? master->down_after_period :\n                            SENTINEL_DEFAULT_DOWN_AFTER;\n    ri->master_link_down_time = 0;\n    ri->auth_pass = NULL;\n    ri->slave_priority = SENTINEL_DEFAULT_SLAVE_PRIORITY;\n    ri->slave_reconf_sent_time = 0;\n    ri->slave_master_host = NULL;\n    ri->slave_master_port = 0;\n    ri->slave_master_link_status = SENTINEL_MASTER_LINK_STATUS_DOWN;\n    ri->slave_repl_offset = 0;\n    ri->sentinels = dictCreate(&instancesDictType,NULL);\n    ri->quorum = quorum;\n    ri->parallel_syncs = SENTINEL_DEFAULT_PARALLEL_SYNCS;\n    ri->master = master;\n    ri->slaves = dictCreate(&instancesDictType,NULL);\n    ri->info_refresh = 0;\n\n    /* Failover state. */\n    ri->leader = NULL;\n    ri->leader_epoch = 0;\n    ri->failover_epoch = 0;\n    ri->failover_state = SENTINEL_FAILOVER_STATE_NONE;\n    ri->failover_state_change_time = 0;\n    ri->failover_start_time = 0;\n    ri->failover_timeout = SENTINEL_DEFAULT_FAILOVER_TIMEOUT;\n    ri->failover_delay_logged = 0;\n    ri->promoted_slave = NULL;\n    ri->notification_script = NULL;\n    ri->client_reconfig_script = NULL;\n\n    /* Role */\n    ri->role_reported = ri->flags & (SRI_MASTER|SRI_SLAVE);\n    ri->role_reported_time = mstime();\n    ri->slave_conf_change_time = mstime();\n\n    /* Add into the right table. */\n    dictAdd(table, ri->name, ri);\n    return ri;\n}\n\n/* Release this instance and all its slaves, sentinels, hiredis connections.\n * This function does not take care of unlinking the instance from the main\n * masters table (if it is a master) or from its master sentinels/slaves table\n * if it is a slave or sentinel. */\nvoid releaseSentinelRedisInstance(sentinelRedisInstance *ri) {\n    /* Release all its slaves or sentinels if any. */\n    dictRelease(ri->sentinels);\n    dictRelease(ri->slaves);\n\n    /* Release hiredis connections. */\n    if (ri->cc) sentinelKillLink(ri,ri->cc);\n    if (ri->pc) sentinelKillLink(ri,ri->pc);\n\n    /* Free other resources. */\n    sdsfree(ri->name);\n    sdsfree(ri->runid);\n    sdsfree(ri->notification_script);\n    sdsfree(ri->client_reconfig_script);\n    sdsfree(ri->slave_master_host);\n    sdsfree(ri->leader);\n    sdsfree(ri->auth_pass);\n    releaseSentinelAddr(ri->addr);\n\n    /* Clear state into the master if needed. */\n    if ((ri->flags & SRI_SLAVE) && (ri->flags & SRI_PROMOTED) && ri->master)\n        ri->master->promoted_slave = NULL;\n\n    zfree(ri);\n}\n\n/* Lookup a slave in a master Redis instance, by ip and port. */\nsentinelRedisInstance *sentinelRedisInstanceLookupSlave(\n                sentinelRedisInstance *ri, char *ip, int port)\n{\n    sds key;\n    sentinelRedisInstance *slave;\n\n    redisAssert(ri->flags & SRI_MASTER);\n    key = sdscatprintf(sdsempty(),\n        strchr(ip,':') ? \"[%s]:%d\" : \"%s:%d\",\n        ip,port);\n    slave = dictFetchValue(ri->slaves,key);\n    sdsfree(key);\n    return slave;\n}\n\n/* Return the name of the type of the instance as a string. */\nconst char *sentinelRedisInstanceTypeStr(sentinelRedisInstance *ri) {\n    if (ri->flags & SRI_MASTER) return \"master\";\n    else if (ri->flags & SRI_SLAVE) return \"slave\";\n    else if (ri->flags & SRI_SENTINEL) return \"sentinel\";\n    else return \"unknown\";\n}\n\n/* This function removes all the instances found in the dictionary of\n * sentinels in the specified 'master', having either:\n *\n * 1) The same ip/port as specified.\n * 2) The same runid.\n *\n * \"1\" and \"2\" don't need to verify at the same time, just one is enough.\n * If \"runid\" is NULL it is not checked.\n * Similarly if \"ip\" is NULL it is not checked.\n *\n * This function is useful because every time we add a new Sentinel into\n * a master's Sentinels dictionary, we want to be very sure about not\n * having duplicated instances for any reason. This is important because\n * other sentinels are needed to reach ODOWN quorum, and later to get\n * voted for a given configuration epoch in order to perform the failover.\n *\n * The function returns the number of Sentinels removed. */\nint removeMatchingSentinelsFromMaster(sentinelRedisInstance *master, char *ip, int port, char *runid) {\n    dictIterator *di;\n    dictEntry *de;\n    int removed = 0;\n\n    di = dictGetSafeIterator(master->sentinels);\n    while((de = dictNext(di)) != NULL) {\n        sentinelRedisInstance *ri = dictGetVal(de);\n\n        if ((ri->runid && runid && strcmp(ri->runid,runid) == 0) ||\n            (ip && strcmp(ri->addr->ip,ip) == 0 && port == ri->addr->port))\n        {\n            dictDelete(master->sentinels,ri->name);\n            removed++;\n        }\n    }\n    dictReleaseIterator(di);\n    return removed;\n}\n\n/* Search an instance with the same runid, ip and port into a dictionary\n * of instances. Return NULL if not found, otherwise return the instance\n * pointer.\n *\n * runid or ip can be NULL. In such a case the search is performed only\n * by the non-NULL field. */\nsentinelRedisInstance *getSentinelRedisInstanceByAddrAndRunID(dict *instances, char *ip, int port, char *runid) {\n    dictIterator *di;\n    dictEntry *de;\n    sentinelRedisInstance *instance = NULL;\n\n    redisAssert(ip || runid);   /* User must pass at least one search param. */\n    di = dictGetIterator(instances);\n    while((de = dictNext(di)) != NULL) {\n        sentinelRedisInstance *ri = dictGetVal(de);\n\n        if (runid && !ri->runid) continue;\n        if ((runid == NULL || strcmp(ri->runid, runid) == 0) &&\n            (ip == NULL || (strcmp(ri->addr->ip, ip) == 0 &&\n                            ri->addr->port == port)))\n        {\n            instance = ri;\n            break;\n        }\n    }\n    dictReleaseIterator(di);\n    return instance;\n}\n\n/* Master lookup by name */\nsentinelRedisInstance *sentinelGetMasterByName(char *name) {\n    sentinelRedisInstance *ri;\n    sds sdsname = sdsnew(name);\n\n    ri = dictFetchValue(sentinel.masters,sdsname);\n    sdsfree(sdsname);\n    return ri;\n}\n\n/* Add the specified flags to all the instances in the specified dictionary. */\nvoid sentinelAddFlagsToDictOfRedisInstances(dict *instances, int flags) {\n    dictIterator *di;\n    dictEntry *de;\n\n    di = dictGetIterator(instances);\n    while((de = dictNext(di)) != NULL) {\n        sentinelRedisInstance *ri = dictGetVal(de);\n        ri->flags |= flags;\n    }\n    dictReleaseIterator(di);\n}\n\n/* Remove the specified flags to all the instances in the specified\n * dictionary. */\nvoid sentinelDelFlagsToDictOfRedisInstances(dict *instances, int flags) {\n    dictIterator *di;\n    dictEntry *de;\n\n    di = dictGetIterator(instances);\n    while((de = dictNext(di)) != NULL) {\n        sentinelRedisInstance *ri = dictGetVal(de);\n        ri->flags &= ~flags;\n    }\n    dictReleaseIterator(di);\n}\n\n/* Reset the state of a monitored master:\n * 1) Remove all slaves.\n * 2) Remove all sentinels.\n * 3) Remove most of the flags resulting from runtime operations.\n * 4) Reset timers to their default value.\n * 5) In the process of doing this undo the failover if in progress.\n * 6) Disconnect the connections with the master (will reconnect automatically).\n */\n\n#define SENTINEL_RESET_NO_SENTINELS (1<<0)\nvoid sentinelResetMaster(sentinelRedisInstance *ri, int flags) {\n    redisAssert(ri->flags & SRI_MASTER);\n    dictRelease(ri->slaves);\n    ri->slaves = dictCreate(&instancesDictType,NULL);\n    if (!(flags & SENTINEL_RESET_NO_SENTINELS)) {\n        dictRelease(ri->sentinels);\n        ri->sentinels = dictCreate(&instancesDictType,NULL);\n    }\n    if (ri->cc) sentinelKillLink(ri,ri->cc);\n    if (ri->pc) sentinelKillLink(ri,ri->pc);\n    ri->flags &= SRI_MASTER|SRI_DISCONNECTED;\n    if (ri->leader) {\n        sdsfree(ri->leader);\n        ri->leader = NULL;\n    }\n    ri->failover_state = SENTINEL_FAILOVER_STATE_NONE;\n    ri->failover_state_change_time = 0;\n    ri->failover_start_time = 0;\n    ri->promoted_slave = NULL;\n    sdsfree(ri->runid);\n    sdsfree(ri->slave_master_host);\n    ri->runid = NULL;\n    ri->slave_master_host = NULL;\n    ri->last_ping_time = mstime();\n    ri->last_avail_time = mstime();\n    ri->last_pong_time = mstime();\n    ri->role_reported_time = mstime();\n    ri->role_reported = SRI_MASTER;\n    if (flags & SENTINEL_GENERATE_EVENT)\n        sentinelEvent(REDIS_WARNING,\"+reset-master\",ri,\"%@\");\n}\n\n/* Call sentinelResetMaster() on every master with a name matching the specified\n * pattern. */\nint sentinelResetMastersByPattern(char *pattern, int flags) {\n    dictIterator *di;\n    dictEntry *de;\n    int reset = 0;\n\n    di = dictGetIterator(sentinel.masters);\n    while((de = dictNext(di)) != NULL) {\n        sentinelRedisInstance *ri = dictGetVal(de);\n\n        if (ri->name) {\n            if (stringmatch(pattern,ri->name,0)) {\n                sentinelResetMaster(ri,flags);\n                reset++;\n            }\n        }\n    }\n    dictReleaseIterator(di);\n    return reset;\n}\n\n/* Reset the specified master with sentinelResetMaster(), and also change\n * the ip:port address, but take the name of the instance unmodified.\n *\n * This is used to handle the +switch-master event.\n *\n * The function returns REDIS_ERR if the address can't be resolved for some\n * reason. Otherwise REDIS_OK is returned.  */\nint sentinelResetMasterAndChangeAddress(sentinelRedisInstance *master, char *ip, int port) {\n    sentinelAddr *oldaddr, *newaddr;\n    sentinelAddr **slaves = NULL;\n    int numslaves = 0, j;\n    dictIterator *di;\n    dictEntry *de;\n\n    newaddr = createSentinelAddr(ip,port);\n    if (newaddr == NULL) return REDIS_ERR;\n\n    /* Make a list of slaves to add back after the reset.\n     * Don't include the one having the address we are switching to. */\n    di = dictGetIterator(master->slaves);\n    while((de = dictNext(di)) != NULL) {\n        sentinelRedisInstance *slave = dictGetVal(de);\n\n        if (sentinelAddrIsEqual(slave->addr,newaddr)) continue;\n        slaves = zrealloc(slaves,sizeof(sentinelAddr*)*(numslaves+1));\n        slaves[numslaves++] = createSentinelAddr(slave->addr->ip,\n                                                 slave->addr->port);\n    }\n    dictReleaseIterator(di);\n\n    /* If we are switching to a different address, include the old address\n     * as a slave as well, so that we'll be able to sense / reconfigure\n     * the old master. */\n    if (!sentinelAddrIsEqual(newaddr,master->addr)) {\n        slaves = zrealloc(slaves,sizeof(sentinelAddr*)*(numslaves+1));\n        slaves[numslaves++] = createSentinelAddr(master->addr->ip,\n                                                 master->addr->port);\n    }\n\n    /* Reset and switch address. */\n    sentinelResetMaster(master,SENTINEL_RESET_NO_SENTINELS);\n    oldaddr = master->addr;\n    master->addr = newaddr;\n    master->o_down_since_time = 0;\n    master->s_down_since_time = 0;\n\n    /* Add slaves back. */\n    for (j = 0; j < numslaves; j++) {\n        sentinelRedisInstance *slave;\n\n        slave = createSentinelRedisInstance(NULL,SRI_SLAVE,slaves[j]->ip,\n                    slaves[j]->port, master->quorum, master);\n        releaseSentinelAddr(slaves[j]);\n        if (slave) sentinelEvent(REDIS_NOTICE,\"+slave\",slave,\"%@\");\n    }\n    zfree(slaves);\n\n    /* Release the old address at the end so we are safe even if the function\n     * gets the master->addr->ip and master->addr->port as arguments. */\n    releaseSentinelAddr(oldaddr);\n    sentinelFlushConfig();\n    return REDIS_OK;\n}\n\n/* Return non-zero if there was no SDOWN or ODOWN error associated to this\n * instance in the latest 'ms' milliseconds. */\nint sentinelRedisInstanceNoDownFor(sentinelRedisInstance *ri, mstime_t ms) {\n    mstime_t most_recent;\n\n    most_recent = ri->s_down_since_time;\n    if (ri->o_down_since_time > most_recent)\n        most_recent = ri->o_down_since_time;\n    return most_recent == 0 || (mstime() - most_recent) > ms;\n}\n\n/* Return the current master address, that is, its address or the address\n * of the promoted slave if already operational. */\nsentinelAddr *sentinelGetCurrentMasterAddress(sentinelRedisInstance *master) {\n    /* If we are failing over the master, and the state is already\n     * SENTINEL_FAILOVER_STATE_RECONF_SLAVES or greater, it means that we\n     * already have the new configuration epoch in the master, and the\n     * slave acknowledged the configuration switch. Advertise the new\n     * address. */\n    if ((master->flags & SRI_FAILOVER_IN_PROGRESS) &&\n        master->promoted_slave &&\n        master->failover_state >= SENTINEL_FAILOVER_STATE_RECONF_SLAVES)\n    {\n        return master->promoted_slave->addr;\n    } else {\n        return master->addr;\n    }\n}\n\n/* This function sets the down_after_period field value in 'master' to all\n * the slaves and sentinel instances connected to this master. */\nvoid sentinelPropagateDownAfterPeriod(sentinelRedisInstance *master) {\n    dictIterator *di;\n    dictEntry *de;\n    int j;\n    dict *d[] = {master->slaves, master->sentinels, NULL};\n\n    for (j = 0; d[j]; j++) {\n        di = dictGetIterator(d[j]);\n        while((de = dictNext(di)) != NULL) {\n            sentinelRedisInstance *ri = dictGetVal(de);\n            ri->down_after_period = master->down_after_period;\n        }\n        dictReleaseIterator(di);\n    }\n}\n\n/* ============================ Config handling ============================= */\nchar *sentinelHandleConfiguration(char **argv, int argc) {\n    sentinelRedisInstance *ri;\n\n    if (!strcasecmp(argv[0],\"monitor\") && argc == 5) {\n        /* monitor <name> <host> <port> <quorum> */\n        int quorum = atoi(argv[4]);\n\n        if (quorum <= 0) return \"Quorum must be 1 or greater.\";\n        if (createSentinelRedisInstance(argv[1],SRI_MASTER,argv[2],\n                                        atoi(argv[3]),quorum,NULL) == NULL)\n        {\n            switch(errno) {\n            case EBUSY: return \"Duplicated master name.\";\n            case ENOENT: return \"Can't resolve master instance hostname.\";\n            case EINVAL: return \"Invalid port number\";\n            }\n        }\n    } else if (!strcasecmp(argv[0],\"down-after-milliseconds\") && argc == 3) {\n        /* down-after-milliseconds <name> <milliseconds> */\n        ri = sentinelGetMasterByName(argv[1]);\n        if (!ri) return \"No such master with specified name.\";\n        ri->down_after_period = atoi(argv[2]);\n        if (ri->down_after_period <= 0)\n            return \"negative or zero time parameter.\";\n        sentinelPropagateDownAfterPeriod(ri);\n    } else if (!strcasecmp(argv[0],\"failover-timeout\") && argc == 3) {\n        /* failover-timeout <name> <milliseconds> */\n        ri = sentinelGetMasterByName(argv[1]);\n        if (!ri) return \"No such master with specified name.\";\n        ri->failover_timeout = atoi(argv[2]);\n        if (ri->failover_timeout <= 0)\n            return \"negative or zero time parameter.\";\n   } else if (!strcasecmp(argv[0],\"parallel-syncs\") && argc == 3) {\n        /* parallel-syncs <name> <milliseconds> */\n        ri = sentinelGetMasterByName(argv[1]);\n        if (!ri) return \"No such master with specified name.\";\n        ri->parallel_syncs = atoi(argv[2]);\n   } else if (!strcasecmp(argv[0],\"notification-script\") && argc == 3) {\n        /* notification-script <name> <path> */\n        ri = sentinelGetMasterByName(argv[1]);\n        if (!ri) return \"No such master with specified name.\";\n        if (access(argv[2],X_OK) == -1)\n            return \"Notification script seems non existing or non executable.\";\n        ri->notification_script = sdsnew(argv[2]);\n   } else if (!strcasecmp(argv[0],\"client-reconfig-script\") && argc == 3) {\n        /* client-reconfig-script <name> <path> */\n        ri = sentinelGetMasterByName(argv[1]);\n        if (!ri) return \"No such master with specified name.\";\n        if (access(argv[2],X_OK) == -1)\n            return \"Client reconfiguration script seems non existing or \"\n                   \"non executable.\";\n        ri->client_reconfig_script = sdsnew(argv[2]);\n   } else if (!strcasecmp(argv[0],\"auth-pass\") && argc == 3) {\n        /* auth-pass <name> <password> */\n        ri = sentinelGetMasterByName(argv[1]);\n        if (!ri) return \"No such master with specified name.\";\n        ri->auth_pass = sdsnew(argv[2]);\n    } else if (!strcasecmp(argv[0],\"current-epoch\") && argc == 2) {\n        /* current-epoch <epoch> */\n        unsigned long long current_epoch = strtoull(argv[1],NULL,10);\n        if (current_epoch > sentinel.current_epoch)\n            sentinel.current_epoch = current_epoch;\n    } else if (!strcasecmp(argv[0],\"config-epoch\") && argc == 3) {\n        /* config-epoch <name> <epoch> */\n        ri = sentinelGetMasterByName(argv[1]);\n        if (!ri) return \"No such master with specified name.\";\n        ri->config_epoch = strtoull(argv[2],NULL,10);\n        /* The following update of current_epoch is not really useful as\n         * now the current epoch is persisted on the config file, but\n         * we leave this check here for redundancy. */\n        if (ri->config_epoch > sentinel.current_epoch)\n            sentinel.current_epoch = ri->config_epoch;\n    } else if (!strcasecmp(argv[0],\"leader-epoch\") && argc == 3) {\n        /* leader-epoch <name> <epoch> */\n        ri = sentinelGetMasterByName(argv[1]);\n        if (!ri) return \"No such master with specified name.\";\n        ri->leader_epoch = strtoull(argv[2],NULL,10);\n    } else if (!strcasecmp(argv[0],\"known-slave\") && argc == 4) {\n        sentinelRedisInstance *slave;\n\n        /* known-slave <name> <ip> <port> */\n        ri = sentinelGetMasterByName(argv[1]);\n        if (!ri) return \"No such master with specified name.\";\n        if ((slave = createSentinelRedisInstance(NULL,SRI_SLAVE,argv[2],\n                    atoi(argv[3]), ri->quorum, ri)) == NULL)\n        {\n            return \"Wrong hostname or port for slave.\";\n        }\n    } else if (!strcasecmp(argv[0],\"known-sentinel\") &&\n               (argc == 4 || argc == 5)) {\n        sentinelRedisInstance *si;\n\n        /* known-sentinel <name> <ip> <port> [runid] */\n        ri = sentinelGetMasterByName(argv[1]);\n        if (!ri) return \"No such master with specified name.\";\n        if ((si = createSentinelRedisInstance(NULL,SRI_SENTINEL,argv[2],\n                    atoi(argv[3]), ri->quorum, ri)) == NULL)\n        {\n            return \"Wrong hostname or port for sentinel.\";\n        }\n        if (argc == 5) si->runid = sdsnew(argv[4]);\n    } else if (!strcasecmp(argv[0],\"announce-ip\") && argc == 2) {\n        /* announce-ip <ip-address> */\n        if (strlen(argv[1]))\n            sentinel.announce_ip = sdsnew(argv[1]);\n    } else if (!strcasecmp(argv[0],\"announce-port\") && argc == 2) {\n        /* announce-port <port> */\n        sentinel.announce_port = atoi(argv[1]);\n    } else {\n        return \"Unrecognized sentinel configuration statement.\";\n    }\n    return NULL;\n}\n\n/* Implements CONFIG REWRITE for \"sentinel\" option.\n * This is used not just to rewrite the configuration given by the user\n * (the configured masters) but also in order to retain the state of\n * Sentinel across restarts: config epoch of masters, associated slaves\n * and sentinel instances, and so forth. */\nvoid rewriteConfigSentinelOption(struct rewriteConfigState *state) {\n    dictIterator *di, *di2;\n    dictEntry *de;\n    sds line;\n\n    /* For every master emit a \"sentinel monitor\" config entry. */\n    di = dictGetIterator(sentinel.masters);\n    while((de = dictNext(di)) != NULL) {\n        sentinelRedisInstance *master, *ri;\n        sentinelAddr *master_addr;\n\n        /* sentinel monitor */\n        master = dictGetVal(de);\n        master_addr = sentinelGetCurrentMasterAddress(master);\n        line = sdscatprintf(sdsempty(),\"sentinel monitor %s %s %d %d\",\n            master->name, master_addr->ip, master_addr->port,\n            master->quorum);\n        rewriteConfigRewriteLine(state,\"sentinel\",line,1);\n\n        /* sentinel down-after-milliseconds */\n        if (master->down_after_period != SENTINEL_DEFAULT_DOWN_AFTER) {\n            line = sdscatprintf(sdsempty(),\n                \"sentinel down-after-milliseconds %s %ld\",\n                master->name, (long) master->down_after_period);\n            rewriteConfigRewriteLine(state,\"sentinel\",line,1);\n        }\n\n        /* sentinel failover-timeout */\n        if (master->failover_timeout != SENTINEL_DEFAULT_FAILOVER_TIMEOUT) {\n            line = sdscatprintf(sdsempty(),\n                \"sentinel failover-timeout %s %ld\",\n                master->name, (long) master->failover_timeout);\n            rewriteConfigRewriteLine(state,\"sentinel\",line,1);\n        }\n\n        /* sentinel parallel-syncs */\n        if (master->parallel_syncs != SENTINEL_DEFAULT_PARALLEL_SYNCS) {\n            line = sdscatprintf(sdsempty(),\n                \"sentinel parallel-syncs %s %d\",\n                master->name, master->parallel_syncs);\n            rewriteConfigRewriteLine(state,\"sentinel\",line,1);\n        }\n\n        /* sentinel notification-script */\n        if (master->notification_script) {\n            line = sdscatprintf(sdsempty(),\n                \"sentinel notification-script %s %s\",\n                master->name, master->notification_script);\n            rewriteConfigRewriteLine(state,\"sentinel\",line,1);\n        }\n\n        /* sentinel client-reconfig-script */\n        if (master->client_reconfig_script) {\n            line = sdscatprintf(sdsempty(),\n                \"sentinel client-reconfig-script %s %s\",\n                master->name, master->client_reconfig_script);\n            rewriteConfigRewriteLine(state,\"sentinel\",line,1);\n        }\n\n        /* sentinel auth-pass */\n        if (master->auth_pass) {\n            line = sdscatprintf(sdsempty(),\n                \"sentinel auth-pass %s %s\",\n                master->name, master->auth_pass);\n            rewriteConfigRewriteLine(state,\"sentinel\",line,1);\n        }\n\n        /* sentinel config-epoch */\n        line = sdscatprintf(sdsempty(),\n            \"sentinel config-epoch %s %llu\",\n            master->name, (unsigned long long) master->config_epoch);\n        rewriteConfigRewriteLine(state,\"sentinel\",line,1);\n\n        /* sentinel leader-epoch */\n        line = sdscatprintf(sdsempty(),\n            \"sentinel leader-epoch %s %llu\",\n            master->name, (unsigned long long) master->leader_epoch);\n        rewriteConfigRewriteLine(state,\"sentinel\",line,1);\n\n        /* sentinel known-slave */\n        di2 = dictGetIterator(master->slaves);\n        while((de = dictNext(di2)) != NULL) {\n            sentinelAddr *slave_addr;\n\n            ri = dictGetVal(de);\n            slave_addr = ri->addr;\n\n            /* If master_addr (obtained using sentinelGetCurrentMasterAddress()\n             * so it may be the address of the promoted slave) is equal to this\n             * slave's address, a failover is in progress and the slave was\n             * already successfully promoted. So as the address of this slave\n             * we use the old master address instead. */\n            if (sentinelAddrIsEqual(slave_addr,master_addr))\n                slave_addr = master->addr;\n            line = sdscatprintf(sdsempty(),\n                \"sentinel known-slave %s %s %d\",\n                master->name, ri->addr->ip, ri->addr->port);\n            rewriteConfigRewriteLine(state,\"sentinel\",line,1);\n        }\n        dictReleaseIterator(di2);\n\n        /* sentinel known-sentinel */\n        di2 = dictGetIterator(master->sentinels);\n        while((de = dictNext(di2)) != NULL) {\n            ri = dictGetVal(de);\n            line = sdscatprintf(sdsempty(),\n                \"sentinel known-sentinel %s %s %d%s%s\",\n                master->name, ri->addr->ip, ri->addr->port,\n                ri->runid ? \" \" : \"\",\n                ri->runid ? ri->runid : \"\");\n            rewriteConfigRewriteLine(state,\"sentinel\",line,1);\n        }\n        dictReleaseIterator(di2);\n    }\n\n    /* sentinel current-epoch is a global state valid for all the masters. */\n    line = sdscatprintf(sdsempty(),\n        \"sentinel current-epoch %llu\", (unsigned long long) sentinel.current_epoch);\n    rewriteConfigRewriteLine(state,\"sentinel\",line,1);\n\n    /* sentinel announce-ip. */\n    if (sentinel.announce_ip) {\n        line = sdsnew(\"sentinel announce-ip \");\n        line = sdscatrepr(line, sentinel.announce_ip, sdslen(sentinel.announce_ip));\n        rewriteConfigRewriteLine(state,\"sentinel\",line,1);\n    }\n\n    /* sentinel announce-port. */\n    if (sentinel.announce_port) {\n        line = sdscatprintf(sdsempty(),\"sentinel announce-port %d\",\n                            sentinel.announce_port);\n        rewriteConfigRewriteLine(state,\"sentinel\",line,1);\n    }\n\n    dictReleaseIterator(di);\n}\n\n/* This function uses the config rewriting Redis engine in order to persist\n * the state of the Sentinel in the current configuration file.\n *\n * Before returning the function calls fsync() against the generated\n * configuration file to make sure changes are committed to disk.\n *\n * On failure the function logs a warning on the Redis log. */\nvoid sentinelFlushConfig(void) {\n    int fd = -1;\n    int saved_hz = server.hz;\n    int rewrite_status;\n\n    server.hz = REDIS_DEFAULT_HZ;\n    rewrite_status = rewriteConfig(server.configfile);\n    server.hz = saved_hz;\n\n    if (rewrite_status == -1) goto werr;\n    if ((fd = open(server.configfile,O_RDONLY)) == -1) goto werr;\n    if (fsync(fd) == -1) goto werr;\n    if (close(fd) == EOF) goto werr;\n    return;\n\nwerr:\n    if (fd != -1) close(fd);\n    redisLog(REDIS_WARNING,\"WARNING: Sentinel was not able to save the new configuration on disk!!!: %s\", strerror(errno));\n}\n\n/* ====================== hiredis connection handling ======================= */\n\n/* Completely disconnect a hiredis link from an instance. */\nvoid sentinelKillLink(sentinelRedisInstance *ri, redisAsyncContext *c) {\n    if (ri->cc == c) {\n        ri->cc = NULL;\n        ri->pending_commands = 0;\n    }\n    if (ri->pc == c) ri->pc = NULL;\n    c->data = NULL;\n    ri->flags |= SRI_DISCONNECTED;\n    redisAsyncFree(c);\n}\n\n/* This function takes a hiredis context that is in an error condition\n * and make sure to mark the instance as disconnected performing the\n * cleanup needed.\n *\n * Note: we don't free the hiredis context as hiredis will do it for us\n * for async connections. */\nvoid sentinelDisconnectInstanceFromContext(const redisAsyncContext *c) {\n    sentinelRedisInstance *ri = c->data;\n    int pubsub;\n\n    if (ri == NULL) return; /* The instance no longer exists. */\n\n    pubsub = (ri->pc == c);\n    sentinelEvent(REDIS_DEBUG, pubsub ? \"-pubsub-link\" : \"-cmd-link\", ri,\n        \"%@ #%s\", c->errstr);\n    if (pubsub)\n        ri->pc = NULL;\n    else\n        ri->cc = NULL;\n    ri->flags |= SRI_DISCONNECTED;\n}\n\nvoid sentinelLinkEstablishedCallback(const redisAsyncContext *c, int status) {\n    if (status != REDIS_OK) {\n        sentinelDisconnectInstanceFromContext(c);\n    } else {\n        sentinelRedisInstance *ri = c->data;\n        int pubsub = (ri->pc == c);\n\n        sentinelEvent(REDIS_DEBUG, pubsub ? \"+pubsub-link\" : \"+cmd-link\", ri,\n            \"%@\");\n    }\n}\n\nvoid sentinelDisconnectCallback(const redisAsyncContext *c, int status) {\n    REDIS_NOTUSED(status);\n    sentinelDisconnectInstanceFromContext(c);\n}\n\n/* Send the AUTH command with the specified master password if needed.\n * Note that for slaves the password set for the master is used.\n *\n * We don't check at all if the command was successfully transmitted\n * to the instance as if it fails Sentinel will detect the instance down,\n * will disconnect and reconnect the link and so forth. */\nvoid sentinelSendAuthIfNeeded(sentinelRedisInstance *ri, redisAsyncContext *c) {\n    char *auth_pass = (ri->flags & SRI_MASTER) ? ri->auth_pass :\n                                                 ri->master->auth_pass;\n\n    if (auth_pass) {\n        if (redisAsyncCommand(c, sentinelDiscardReplyCallback, NULL, \"AUTH %s\",\n            auth_pass) == REDIS_OK) ri->pending_commands++;\n    }\n}\n\n/* Use CLIENT SETNAME to name the connection in the Redis instance as\n * sentinel-<first_8_chars_of_runid>-<connection_type>\n * The connection type is \"cmd\" or \"pubsub\" as specified by 'type'.\n *\n * This makes it possible to list all the sentinel instances connected\n * to a Redis servewr with CLIENT LIST, grepping for a specific name format. */\nvoid sentinelSetClientName(sentinelRedisInstance *ri, redisAsyncContext *c, char *type) {\n    char name[64];\n\n    snprintf(name,sizeof(name),\"sentinel-%.8s-%s\",server.runid,type);\n    if (redisAsyncCommand(c, sentinelDiscardReplyCallback, NULL,\n        \"CLIENT SETNAME %s\", name) == REDIS_OK)\n    {\n        ri->pending_commands++;\n    }\n}\n\n/* Create the async connections for the specified instance if the instance\n * is disconnected. Note that the SRI_DISCONNECTED flag is set even if just\n * one of the two links (commands and pub/sub) is missing. */\nvoid sentinelReconnectInstance(sentinelRedisInstance *ri) {\n    if (!(ri->flags & SRI_DISCONNECTED)) return;\n\n    /* Commands connection. */\n    if (ri->cc == NULL) {\n        ri->cc = redisAsyncConnectBind(ri->addr->ip,ri->addr->port,REDIS_BIND_ADDR);\n        if (ri->cc->err) {\n            sentinelEvent(REDIS_DEBUG,\"-cmd-link-reconnection\",ri,\"%@ #%s\",\n                ri->cc->errstr);\n            sentinelKillLink(ri,ri->cc);\n        } else {\n            ri->cc_conn_time = mstime();\n            ri->cc->data = ri;\n            redisAeAttach(server.el,ri->cc);\n            redisAsyncSetConnectCallback(ri->cc,\n                                            sentinelLinkEstablishedCallback);\n            redisAsyncSetDisconnectCallback(ri->cc,\n                                            sentinelDisconnectCallback);\n            sentinelSendAuthIfNeeded(ri,ri->cc);\n            sentinelSetClientName(ri,ri->cc,\"cmd\");\n\n            /* Send a PING ASAP when reconnecting. */\n            sentinelSendPing(ri);\n        }\n    }\n    /* Pub / Sub */\n    if ((ri->flags & (SRI_MASTER|SRI_SLAVE)) && ri->pc == NULL) {\n        ri->pc = redisAsyncConnectBind(ri->addr->ip,ri->addr->port,REDIS_BIND_ADDR);\n        if (ri->pc->err) {\n            sentinelEvent(REDIS_DEBUG,\"-pubsub-link-reconnection\",ri,\"%@ #%s\",\n                ri->pc->errstr);\n            sentinelKillLink(ri,ri->pc);\n        } else {\n            int retval;\n\n            ri->pc_conn_time = mstime();\n            ri->pc->data = ri;\n            redisAeAttach(server.el,ri->pc);\n            redisAsyncSetConnectCallback(ri->pc,\n                                            sentinelLinkEstablishedCallback);\n            redisAsyncSetDisconnectCallback(ri->pc,\n                                            sentinelDisconnectCallback);\n            sentinelSendAuthIfNeeded(ri,ri->pc);\n            sentinelSetClientName(ri,ri->pc,\"pubsub\");\n            /* Now we subscribe to the Sentinels \"Hello\" channel. */\n            retval = redisAsyncCommand(ri->pc,\n                sentinelReceiveHelloMessages, NULL, \"SUBSCRIBE %s\",\n                    SENTINEL_HELLO_CHANNEL);\n            if (retval != REDIS_OK) {\n                /* If we can't subscribe, the Pub/Sub connection is useless\n                 * and we can simply disconnect it and try again. */\n                sentinelKillLink(ri,ri->pc);\n                return;\n            }\n        }\n    }\n    /* Clear the DISCONNECTED flags only if we have both the connections\n     * (or just the commands connection if this is a sentinel instance). */\n    if (ri->cc && (ri->flags & SRI_SENTINEL || ri->pc))\n        ri->flags &= ~SRI_DISCONNECTED;\n}\n\n/* ======================== Redis instances pinging  ======================== */\n\n/* Return true if master looks \"sane\", that is:\n * 1) It is actually a master in the current configuration.\n * 2) It reports itself as a master.\n * 3) It is not SDOWN or ODOWN.\n * 4) We obtained last INFO no more than two times the INFO period time ago. */\nint sentinelMasterLooksSane(sentinelRedisInstance *master) {\n    return\n        master->flags & SRI_MASTER &&\n        master->role_reported == SRI_MASTER &&\n        (master->flags & (SRI_S_DOWN|SRI_O_DOWN)) == 0 &&\n        (mstime() - master->info_refresh) < SENTINEL_INFO_PERIOD*2;\n}\n\n/* Process the INFO output from masters. */\nvoid sentinelRefreshInstanceInfo(sentinelRedisInstance *ri, const char *info) {\n    sds *lines;\n    int numlines, j;\n    int role = 0;\n\n    /* The following fields must be reset to a given value in the case they\n     * are not found at all in the INFO output. */\n    ri->master_link_down_time = 0;\n\n    /* Process line by line. */\n    lines = sdssplitlen(info,strlen(info),\"\\r\\n\",2,&numlines);\n    for (j = 0; j < numlines; j++) {\n        sentinelRedisInstance *slave;\n        sds l = lines[j];\n\n        /* run_id:<40 hex chars>*/\n        if (sdslen(l) >= 47 && !memcmp(l,\"run_id:\",7)) {\n            if (ri->runid == NULL) {\n                ri->runid = sdsnewlen(l+7,40);\n            } else {\n                if (strncmp(ri->runid,l+7,40) != 0) {\n                    sentinelEvent(REDIS_NOTICE,\"+reboot\",ri,\"%@\");\n                    sdsfree(ri->runid);\n                    ri->runid = sdsnewlen(l+7,40);\n                }\n            }\n        }\n\n        /* old versions: slave0:<ip>,<port>,<state>\n         * new versions: slave0:ip=127.0.0.1,port=9999,... */\n        if ((ri->flags & SRI_MASTER) &&\n            sdslen(l) >= 7 &&\n            !memcmp(l,\"slave\",5) && isdigit(l[5]))\n        {\n            char *ip, *port, *end;\n\n            if (strstr(l,\"ip=\") == NULL) {\n                /* Old format. */\n                ip = strchr(l,':'); if (!ip) continue;\n                ip++; /* Now ip points to start of ip address. */\n                port = strchr(ip,','); if (!port) continue;\n                *port = '\\0'; /* nul term for easy access. */\n                port++; /* Now port points to start of port number. */\n                end = strchr(port,','); if (!end) continue;\n                *end = '\\0'; /* nul term for easy access. */\n            } else {\n                /* New format. */\n                ip = strstr(l,\"ip=\"); if (!ip) continue;\n                ip += 3; /* Now ip points to start of ip address. */\n                port = strstr(l,\"port=\"); if (!port) continue;\n                port += 5; /* Now port points to start of port number. */\n                /* Nul term both fields for easy access. */\n                end = strchr(ip,','); if (end) *end = '\\0';\n                end = strchr(port,','); if (end) *end = '\\0';\n            }\n\n            /* Check if we already have this slave into our table,\n             * otherwise add it. */\n            if (sentinelRedisInstanceLookupSlave(ri,ip,atoi(port)) == NULL) {\n                if ((slave = createSentinelRedisInstance(NULL,SRI_SLAVE,ip,\n                            atoi(port), ri->quorum, ri)) != NULL)\n                {\n                    sentinelEvent(REDIS_NOTICE,\"+slave\",slave,\"%@\");\n                    sentinelFlushConfig();\n                }\n            }\n        }\n\n        /* master_link_down_since_seconds:<seconds> */\n        if (sdslen(l) >= 32 &&\n            !memcmp(l,\"master_link_down_since_seconds\",30))\n        {\n            ri->master_link_down_time = strtoll(l+31,NULL,10)*1000;\n        }\n\n        /* role:<role> */\n        if (!memcmp(l,\"role:master\",11)) role = SRI_MASTER;\n        else if (!memcmp(l,\"role:slave\",10)) role = SRI_SLAVE;\n\n        if (role == SRI_SLAVE) {\n            /* master_host:<host> */\n            if (sdslen(l) >= 12 && !memcmp(l,\"master_host:\",12)) {\n                if (ri->slave_master_host == NULL ||\n                    strcasecmp(l+12,ri->slave_master_host))\n                {\n                    sdsfree(ri->slave_master_host);\n                    ri->slave_master_host = sdsnew(l+12);\n                    ri->slave_conf_change_time = mstime();\n                }\n            }\n\n            /* master_port:<port> */\n            if (sdslen(l) >= 12 && !memcmp(l,\"master_port:\",12)) {\n                int slave_master_port = atoi(l+12);\n\n                if (ri->slave_master_port != slave_master_port) {\n                    ri->slave_master_port = slave_master_port;\n                    ri->slave_conf_change_time = mstime();\n                }\n            }\n\n            /* master_link_status:<status> */\n            if (sdslen(l) >= 19 && !memcmp(l,\"master_link_status:\",19)) {\n                ri->slave_master_link_status =\n                    (strcasecmp(l+19,\"up\") == 0) ?\n                    SENTINEL_MASTER_LINK_STATUS_UP :\n                    SENTINEL_MASTER_LINK_STATUS_DOWN;\n            }\n\n            /* slave_priority:<priority> */\n            if (sdslen(l) >= 15 && !memcmp(l,\"slave_priority:\",15))\n                ri->slave_priority = atoi(l+15);\n\n            /* slave_repl_offset:<offset> */\n            if (sdslen(l) >= 18 && !memcmp(l,\"slave_repl_offset:\",18))\n                ri->slave_repl_offset = strtoull(l+18,NULL,10);\n        }\n    }\n    ri->info_refresh = mstime();\n    sdsfreesplitres(lines,numlines);\n\n    /* ---------------------------- Acting half -----------------------------\n     * Some things will not happen if sentinel.tilt is true, but some will\n     * still be processed. */\n\n    /* Remember when the role changed. */\n    if (role != ri->role_reported) {\n        ri->role_reported_time = mstime();\n        ri->role_reported = role;\n        if (role == SRI_SLAVE) ri->slave_conf_change_time = mstime();\n        /* Log the event with +role-change if the new role is coherent or\n         * with -role-change if there is a mismatch with the current config. */\n        sentinelEvent(REDIS_VERBOSE,\n            ((ri->flags & (SRI_MASTER|SRI_SLAVE)) == role) ?\n            \"+role-change\" : \"-role-change\",\n            ri, \"%@ new reported role is %s\",\n            role == SRI_MASTER ? \"master\" : \"slave\",\n            ri->flags & SRI_MASTER ? \"master\" : \"slave\");\n    }\n\n    /* None of the following conditions are processed when in tilt mode, so\n     * return asap. */\n    if (sentinel.tilt) return;\n\n    /* Handle master -> slave role switch. */\n    if ((ri->flags & SRI_MASTER) && role == SRI_SLAVE) {\n        /* Nothing to do, but masters claiming to be slaves are\n         * considered to be unreachable by Sentinel, so eventually\n         * a failover will be triggered. */\n    }\n\n    /* Handle slave -> master role switch. */\n    if ((ri->flags & SRI_SLAVE) && role == SRI_MASTER) {\n        /* If this is a promoted slave we can change state to the\n         * failover state machine. */\n        if ((ri->flags & SRI_PROMOTED) &&\n            (ri->master->flags & SRI_FAILOVER_IN_PROGRESS) &&\n            (ri->master->failover_state ==\n                SENTINEL_FAILOVER_STATE_WAIT_PROMOTION))\n        {\n            /* Now that we are sure the slave was reconfigured as a master\n             * set the master configuration epoch to the epoch we won the\n             * election to perform this failover. This will force the other\n             * Sentinels to update their config (assuming there is not\n             * a newer one already available). */\n            ri->master->config_epoch = ri->master->failover_epoch;\n            ri->master->failover_state = SENTINEL_FAILOVER_STATE_RECONF_SLAVES;\n            ri->master->failover_state_change_time = mstime();\n            sentinelFlushConfig();\n            sentinelEvent(REDIS_WARNING,\"+promoted-slave\",ri,\"%@\");\n            sentinelEvent(REDIS_WARNING,\"+failover-state-reconf-slaves\",\n                ri->master,\"%@\");\n            sentinelCallClientReconfScript(ri->master,SENTINEL_LEADER,\n                \"start\",ri->master->addr,ri->addr);\n            sentinelForceHelloUpdateForMaster(ri->master);\n        } else {\n            /* A slave turned into a master. We want to force our view and\n             * reconfigure as slave. Wait some time after the change before\n             * going forward, to receive new configs if any. */\n            mstime_t wait_time = SENTINEL_PUBLISH_PERIOD*4;\n\n            if (!(ri->flags & SRI_PROMOTED) &&\n                 sentinelMasterLooksSane(ri->master) &&\n                 sentinelRedisInstanceNoDownFor(ri,wait_time) &&\n                 mstime() - ri->role_reported_time > wait_time)\n            {\n                int retval = sentinelSendSlaveOf(ri,\n                        ri->master->addr->ip,\n                        ri->master->addr->port);\n                if (retval == REDIS_OK)\n                    sentinelEvent(REDIS_NOTICE,\"+convert-to-slave\",ri,\"%@\");\n            }\n        }\n    }\n\n    /* Handle slaves replicating to a different master address. */\n    if ((ri->flags & SRI_SLAVE) &&\n        role == SRI_SLAVE &&\n        (ri->slave_master_port != ri->master->addr->port ||\n         strcasecmp(ri->slave_master_host,ri->master->addr->ip)))\n    {\n        mstime_t wait_time = ri->master->failover_timeout;\n\n        /* Make sure the master is sane before reconfiguring this instance\n         * into a slave. */\n        if (sentinelMasterLooksSane(ri->master) &&\n            sentinelRedisInstanceNoDownFor(ri,wait_time) &&\n            mstime() - ri->slave_conf_change_time > wait_time)\n        {\n            int retval = sentinelSendSlaveOf(ri,\n                    ri->master->addr->ip,\n                    ri->master->addr->port);\n            if (retval == REDIS_OK)\n                sentinelEvent(REDIS_NOTICE,\"+fix-slave-config\",ri,\"%@\");\n        }\n    }\n\n    /* Detect if the slave that is in the process of being reconfigured\n     * changed state. */\n    if ((ri->flags & SRI_SLAVE) && role == SRI_SLAVE &&\n        (ri->flags & (SRI_RECONF_SENT|SRI_RECONF_INPROG)))\n    {\n        /* SRI_RECONF_SENT -> SRI_RECONF_INPROG. */\n        if ((ri->flags & SRI_RECONF_SENT) &&\n            ri->slave_master_host &&\n            strcmp(ri->slave_master_host,\n                    ri->master->promoted_slave->addr->ip) == 0 &&\n            ri->slave_master_port == ri->master->promoted_slave->addr->port)\n        {\n            ri->flags &= ~SRI_RECONF_SENT;\n            ri->flags |= SRI_RECONF_INPROG;\n            sentinelEvent(REDIS_NOTICE,\"+slave-reconf-inprog\",ri,\"%@\");\n        }\n\n        /* SRI_RECONF_INPROG -> SRI_RECONF_DONE */\n        if ((ri->flags & SRI_RECONF_INPROG) &&\n            ri->slave_master_link_status == SENTINEL_MASTER_LINK_STATUS_UP)\n        {\n            ri->flags &= ~SRI_RECONF_INPROG;\n            ri->flags |= SRI_RECONF_DONE;\n            sentinelEvent(REDIS_NOTICE,\"+slave-reconf-done\",ri,\"%@\");\n        }\n    }\n}\n\nvoid sentinelInfoReplyCallback(redisAsyncContext *c, void *reply, void *privdata) {\n    sentinelRedisInstance *ri = c->data;\n    redisReply *r;\n    REDIS_NOTUSED(privdata);\n\n    if (ri) ri->pending_commands--;\n    if (!reply || !ri) return;\n    r = reply;\n\n    if (r->type == REDIS_REPLY_STRING) {\n        sentinelRefreshInstanceInfo(ri,r->str);\n    }\n}\n\n/* Just discard the reply. We use this when we are not monitoring the return\n * value of the command but its effects directly. */\nvoid sentinelDiscardReplyCallback(redisAsyncContext *c, void *reply, void *privdata) {\n    sentinelRedisInstance *ri = c->data;\n    REDIS_NOTUSED(reply);\n    REDIS_NOTUSED(privdata);\n\n    if (ri) ri->pending_commands--;\n}\n\nvoid sentinelPingReplyCallback(redisAsyncContext *c, void *reply, void *privdata) {\n    sentinelRedisInstance *ri = c->data;\n    redisReply *r;\n    REDIS_NOTUSED(privdata);\n\n    if (ri) ri->pending_commands--;\n    if (!reply || !ri) return;\n    r = reply;\n\n    if (r->type == REDIS_REPLY_STATUS ||\n        r->type == REDIS_REPLY_ERROR) {\n        /* Update the \"instance available\" field only if this is an\n         * acceptable reply. */\n        if (strncmp(r->str,\"PONG\",4) == 0 ||\n            strncmp(r->str,\"LOADING\",7) == 0 ||\n            strncmp(r->str,\"MASTERDOWN\",10) == 0)\n        {\n            ri->last_avail_time = mstime();\n            ri->last_ping_time = 0; /* Flag the pong as received. */\n        } else {\n            /* Send a SCRIPT KILL command if the instance appears to be\n             * down because of a busy script. */\n            if (strncmp(r->str,\"BUSY\",4) == 0 &&\n                (ri->flags & SRI_S_DOWN) &&\n                !(ri->flags & SRI_SCRIPT_KILL_SENT))\n            {\n                if (redisAsyncCommand(ri->cc,\n                        sentinelDiscardReplyCallback, NULL,\n                        \"SCRIPT KILL\") == REDIS_OK)\n                    ri->pending_commands++;\n                ri->flags |= SRI_SCRIPT_KILL_SENT;\n            }\n        }\n    }\n    ri->last_pong_time = mstime();\n}\n\n/* This is called when we get the reply about the PUBLISH command we send\n * to the master to advertise this sentinel. */\nvoid sentinelPublishReplyCallback(redisAsyncContext *c, void *reply, void *privdata) {\n    sentinelRedisInstance *ri = c->data;\n    redisReply *r;\n    REDIS_NOTUSED(privdata);\n\n    if (ri) ri->pending_commands--;\n    if (!reply || !ri) return;\n    r = reply;\n\n    /* Only update pub_time if we actually published our message. Otherwise\n     * we'll retry again in 100 milliseconds. */\n    if (r->type != REDIS_REPLY_ERROR)\n        ri->last_pub_time = mstime();\n}\n\n/* Process an hello message received via Pub/Sub in master or slave instance,\n * or sent directly to this sentinel via the (fake) PUBLISH command of Sentinel.\n *\n * If the master name specified in the message is not known, the message is\n * discarded. */\nvoid sentinelProcessHelloMessage(char *hello, int hello_len) {\n    /* Format is composed of 8 tokens:\n     * 0=ip,1=port,2=runid,3=current_epoch,4=master_name,\n     * 5=master_ip,6=master_port,7=master_config_epoch. */\n    int numtokens, port, removed, master_port;\n    uint64_t current_epoch, master_config_epoch;\n    char **token = sdssplitlen(hello, hello_len, \",\", 1, &numtokens);\n    sentinelRedisInstance *si, *master;\n\n    if (numtokens == 8) {\n        /* Obtain a reference to the master this hello message is about */\n        master = sentinelGetMasterByName(token[4]);\n        if (!master) goto cleanup; /* Unknown master, skip the message. */\n\n        /* First, try to see if we already have this sentinel. */\n        port = atoi(token[1]);\n        master_port = atoi(token[6]);\n        si = getSentinelRedisInstanceByAddrAndRunID(\n                        master->sentinels,token[0],port,token[2]);\n        current_epoch = strtoull(token[3],NULL,10);\n        master_config_epoch = strtoull(token[7],NULL,10);\n\n        if (!si) {\n            /* If not, remove all the sentinels that have the same runid\n             * OR the same ip/port, because it's either a restart or a\n             * network topology change. */\n            removed = removeMatchingSentinelsFromMaster(master,token[0],port,\n                            token[2]);\n            if (removed) {\n                sentinelEvent(REDIS_NOTICE,\"-dup-sentinel\",master,\n                    \"%@ #duplicate of %s:%d or %s\",\n                    token[0],port,token[2]);\n            }\n\n            /* Add the new sentinel. */\n            si = createSentinelRedisInstance(NULL,SRI_SENTINEL,\n                            token[0],port,master->quorum,master);\n            if (si) {\n                sentinelEvent(REDIS_NOTICE,\"+sentinel\",si,\"%@\");\n                /* The runid is NULL after a new instance creation and\n                 * for Sentinels we don't have a later chance to fill it,\n                 * so do it now. */\n                si->runid = sdsnew(token[2]);\n                sentinelFlushConfig();\n            }\n        }\n\n        /* Update local current_epoch if received current_epoch is greater.*/\n        if (current_epoch > sentinel.current_epoch) {\n            sentinel.current_epoch = current_epoch;\n            sentinelFlushConfig();\n            sentinelEvent(REDIS_WARNING,\"+new-epoch\",master,\"%llu\",\n                (unsigned long long) sentinel.current_epoch);\n        }\n\n        /* Update master info if received configuration is newer. */\n        if (master->config_epoch < master_config_epoch) {\n            master->config_epoch = master_config_epoch;\n            if (master_port != master->addr->port ||\n                strcmp(master->addr->ip, token[5]))\n            {\n                sentinelAddr *old_addr;\n\n                sentinelEvent(REDIS_WARNING,\"+config-update-from\",si,\"%@\");\n                sentinelEvent(REDIS_WARNING,\"+switch-master\",\n                    master,\"%s %s %d %s %d\",\n                    master->name,\n                    master->addr->ip, master->addr->port,\n                    token[5], master_port);\n\n                old_addr = dupSentinelAddr(master->addr);\n                sentinelResetMasterAndChangeAddress(master, token[5], master_port);\n                sentinelCallClientReconfScript(master,\n                    SENTINEL_OBSERVER,\"start\",\n                    old_addr,master->addr);\n                releaseSentinelAddr(old_addr);\n            }\n        }\n\n        /* Update the state of the Sentinel. */\n        if (si) si->last_hello_time = mstime();\n    }\n\ncleanup:\n    sdsfreesplitres(token,numtokens);\n}\n\n\n/* This is our Pub/Sub callback for the Hello channel. It's useful in order\n * to discover other sentinels attached at the same master. */\nvoid sentinelReceiveHelloMessages(redisAsyncContext *c, void *reply, void *privdata) {\n    sentinelRedisInstance *ri = c->data;\n    redisReply *r;\n    REDIS_NOTUSED(privdata);\n\n    if (!reply || !ri) return;\n    r = reply;\n\n    /* Update the last activity in the pubsub channel. Note that since we\n     * receive our messages as well this timestamp can be used to detect\n     * if the link is probably disconnected even if it seems otherwise. */\n    ri->pc_last_activity = mstime();\n\n    /* Sanity check in the reply we expect, so that the code that follows\n     * can avoid to check for details. */\n    if (r->type != REDIS_REPLY_ARRAY ||\n        r->elements != 3 ||\n        r->element[0]->type != REDIS_REPLY_STRING ||\n        r->element[1]->type != REDIS_REPLY_STRING ||\n        r->element[2]->type != REDIS_REPLY_STRING ||\n        strcmp(r->element[0]->str,\"message\") != 0) return;\n\n    /* We are not interested in meeting ourselves */\n    if (strstr(r->element[2]->str,server.runid) != NULL) return;\n\n    sentinelProcessHelloMessage(r->element[2]->str, r->element[2]->len);\n}\n\n/* Send an \"Hello\" message via Pub/Sub to the specified 'ri' Redis\n * instance in order to broadcast the current configuraiton for this\n * master, and to advertise the existence of this Sentinel at the same time.\n *\n * The message has the following format:\n *\n * sentinel_ip,sentinel_port,sentinel_runid,current_epoch,\n * master_name,master_ip,master_port,master_config_epoch.\n *\n * Returns REDIS_OK if the PUBLISH was queued correctly, otherwise\n * REDIS_ERR is returned. */\nint sentinelSendHello(sentinelRedisInstance *ri) {\n    char ip[REDIS_IP_STR_LEN];\n    char payload[REDIS_IP_STR_LEN+1024];\n    int retval;\n    char *announce_ip;\n    int announce_port;\n    sentinelRedisInstance *master = (ri->flags & SRI_MASTER) ? ri : ri->master;\n    sentinelAddr *master_addr = sentinelGetCurrentMasterAddress(master);\n\n    if (ri->flags & SRI_DISCONNECTED) return REDIS_ERR;\n\n    /* Use the specified announce address if specified, otherwise try to\n     * obtain our own IP address. */\n    if (sentinel.announce_ip) {\n        announce_ip = sentinel.announce_ip;\n    } else {\n        if (anetSockName(ri->cc->c.fd,ip,sizeof(ip),NULL) == -1)\n            return REDIS_ERR;\n        announce_ip = ip;\n    }\n    announce_port = sentinel.announce_port ?\n                    sentinel.announce_port : server.port;\n\n    /* Format and send the Hello message. */\n    snprintf(payload,sizeof(payload),\n        \"%s,%d,%s,%llu,\" /* Info about this sentinel. */\n        \"%s,%s,%d,%llu\", /* Info about current master. */\n        announce_ip, announce_port, server.runid,\n        (unsigned long long) sentinel.current_epoch,\n        /* --- */\n        master->name,master_addr->ip,master_addr->port,\n        (unsigned long long) master->config_epoch);\n    retval = redisAsyncCommand(ri->cc,\n        sentinelPublishReplyCallback, NULL, \"PUBLISH %s %s\",\n            SENTINEL_HELLO_CHANNEL,payload);\n    if (retval != REDIS_OK) return REDIS_ERR;\n    ri->pending_commands++;\n    return REDIS_OK;\n}\n\n/* Reset last_pub_time in all the instances in the specified dictionary\n * in order to force the delivery of an Hello update ASAP. */\nvoid sentinelForceHelloUpdateDictOfRedisInstances(dict *instances) {\n    dictIterator *di;\n    dictEntry *de;\n\n    di = dictGetSafeIterator(instances);\n    while((de = dictNext(di)) != NULL) {\n        sentinelRedisInstance *ri = dictGetVal(de);\n        if (ri->last_pub_time >= (SENTINEL_PUBLISH_PERIOD+1))\n            ri->last_pub_time -= (SENTINEL_PUBLISH_PERIOD+1);\n    }\n    dictReleaseIterator(di);\n}\n\n/* This function forces the delivery of an \"Hello\" message (see\n * sentinelSendHello() top comment for further information) to all the Redis\n * and Sentinel instances related to the specified 'master'.\n *\n * It is technically not needed since we send an update to every instance\n * with a period of SENTINEL_PUBLISH_PERIOD milliseconds, however when a\n * Sentinel upgrades a configuration it is a good idea to deliever an update\n * to the other Sentinels ASAP. */\nint sentinelForceHelloUpdateForMaster(sentinelRedisInstance *master) {\n    if (!(master->flags & SRI_MASTER)) return REDIS_ERR;\n    if (master->last_pub_time >= (SENTINEL_PUBLISH_PERIOD+1))\n        master->last_pub_time -= (SENTINEL_PUBLISH_PERIOD+1);\n    sentinelForceHelloUpdateDictOfRedisInstances(master->sentinels);\n    sentinelForceHelloUpdateDictOfRedisInstances(master->slaves);\n    return REDIS_OK;\n}\n\n/* Send a PING to the specified instance and refresh the last_ping_time\n * if it is zero (that is, if we received a pong for the previous ping).\n *\n * On error zero is returned, and we can't consider the PING command\n * queued in the connection. */\nint sentinelSendPing(sentinelRedisInstance *ri) {\n    int retval = redisAsyncCommand(ri->cc,\n        sentinelPingReplyCallback, NULL, \"PING\");\n    if (retval == REDIS_OK) {\n        ri->pending_commands++;\n        /* We update the ping time only if we received the pong for\n         * the previous ping, otherwise we are technically waiting\n         * since the first ping that did not received a reply. */\n        if (ri->last_ping_time == 0) ri->last_ping_time = mstime();\n        return 1;\n    } else {\n        return 0;\n    }\n}\n\n/* Send periodic PING, INFO, and PUBLISH to the Hello channel to\n * the specified master or slave instance. */\nvoid sentinelSendPeriodicCommands(sentinelRedisInstance *ri) {\n    mstime_t now = mstime();\n    mstime_t info_period, ping_period;\n    int retval;\n\n    /* Return ASAP if we have already a PING or INFO already pending, or\n     * in the case the instance is not properly connected. */\n    if (ri->flags & SRI_DISCONNECTED) return;\n\n    /* For INFO, PING, PUBLISH that are not critical commands to send we\n     * also have a limit of SENTINEL_MAX_PENDING_COMMANDS. We don't\n     * want to use a lot of memory just because a link is not working\n     * properly (note that anyway there is a redundant protection about this,\n     * that is, the link will be disconnected and reconnected if a long\n     * timeout condition is detected. */\n    if (ri->pending_commands >= SENTINEL_MAX_PENDING_COMMANDS) return;\n\n    /* If this is a slave of a master in O_DOWN condition we start sending\n     * it INFO every second, instead of the usual SENTINEL_INFO_PERIOD\n     * period. In this state we want to closely monitor slaves in case they\n     * are turned into masters by another Sentinel, or by the sysadmin. */\n    if ((ri->flags & SRI_SLAVE) &&\n        (ri->master->flags & (SRI_O_DOWN|SRI_FAILOVER_IN_PROGRESS))) {\n        info_period = 1000;\n    } else {\n        info_period = SENTINEL_INFO_PERIOD;\n    }\n\n    /* We ping instances every time the last received pong is older than\n     * the configured 'down-after-milliseconds' time, but every second\n     * anyway if 'down-after-milliseconds' is greater than 1 second. */\n    ping_period = ri->down_after_period;\n    if (ping_period > SENTINEL_PING_PERIOD) ping_period = SENTINEL_PING_PERIOD;\n\n    if ((ri->flags & SRI_SENTINEL) == 0 &&\n        (ri->info_refresh == 0 ||\n        (now - ri->info_refresh) > info_period))\n    {\n        /* Send INFO to masters and slaves, not sentinels. */\n        retval = redisAsyncCommand(ri->cc,\n            sentinelInfoReplyCallback, NULL, \"INFO\");\n        if (retval == REDIS_OK) ri->pending_commands++;\n    } else if ((now - ri->last_pong_time) > ping_period) {\n        /* Send PING to all the three kinds of instances. */\n        sentinelSendPing(ri);\n    } else if ((now - ri->last_pub_time) > SENTINEL_PUBLISH_PERIOD) {\n        /* PUBLISH hello messages to all the three kinds of instances. */\n        sentinelSendHello(ri);\n    }\n}\n\n/* =========================== SENTINEL command ============================= */\n\nconst char *sentinelFailoverStateStr(int state) {\n    switch(state) {\n    case SENTINEL_FAILOVER_STATE_NONE: return \"none\";\n    case SENTINEL_FAILOVER_STATE_WAIT_START: return \"wait_start\";\n    case SENTINEL_FAILOVER_STATE_SELECT_SLAVE: return \"select_slave\";\n    case SENTINEL_FAILOVER_STATE_SEND_SLAVEOF_NOONE: return \"send_slaveof_noone\";\n    case SENTINEL_FAILOVER_STATE_WAIT_PROMOTION: return \"wait_promotion\";\n    case SENTINEL_FAILOVER_STATE_RECONF_SLAVES: return \"reconf_slaves\";\n    case SENTINEL_FAILOVER_STATE_UPDATE_CONFIG: return \"update_config\";\n    default: return \"unknown\";\n    }\n}\n\n/* Redis instance to Redis protocol representation. */\nvoid addReplySentinelRedisInstance(redisClient *c, sentinelRedisInstance *ri) {\n    char *flags = sdsempty();\n    void *mbl;\n    int fields = 0;\n\n    mbl = addDeferredMultiBulkLength(c);\n\n    addReplyBulkCString(c,\"name\");\n    addReplyBulkCString(c,ri->name);\n    fields++;\n\n    addReplyBulkCString(c,\"ip\");\n    addReplyBulkCString(c,ri->addr->ip);\n    fields++;\n\n    addReplyBulkCString(c,\"port\");\n    addReplyBulkLongLong(c,ri->addr->port);\n    fields++;\n\n    addReplyBulkCString(c,\"runid\");\n    addReplyBulkCString(c,ri->runid ? ri->runid : \"\");\n    fields++;\n\n    addReplyBulkCString(c,\"flags\");\n    if (ri->flags & SRI_S_DOWN) flags = sdscat(flags,\"s_down,\");\n    if (ri->flags & SRI_O_DOWN) flags = sdscat(flags,\"o_down,\");\n    if (ri->flags & SRI_MASTER) flags = sdscat(flags,\"master,\");\n    if (ri->flags & SRI_SLAVE) flags = sdscat(flags,\"slave,\");\n    if (ri->flags & SRI_SENTINEL) flags = sdscat(flags,\"sentinel,\");\n    if (ri->flags & SRI_DISCONNECTED) flags = sdscat(flags,\"disconnected,\");\n    if (ri->flags & SRI_MASTER_DOWN) flags = sdscat(flags,\"master_down,\");\n    if (ri->flags & SRI_FAILOVER_IN_PROGRESS)\n        flags = sdscat(flags,\"failover_in_progress,\");\n    if (ri->flags & SRI_PROMOTED) flags = sdscat(flags,\"promoted,\");\n    if (ri->flags & SRI_RECONF_SENT) flags = sdscat(flags,\"reconf_sent,\");\n    if (ri->flags & SRI_RECONF_INPROG) flags = sdscat(flags,\"reconf_inprog,\");\n    if (ri->flags & SRI_RECONF_DONE) flags = sdscat(flags,\"reconf_done,\");\n\n    if (sdslen(flags) != 0) sdsrange(flags,0,-2); /* remove last \",\" */\n    addReplyBulkCString(c,flags);\n    sdsfree(flags);\n    fields++;\n\n    addReplyBulkCString(c,\"pending-commands\");\n    addReplyBulkLongLong(c,ri->pending_commands);\n    fields++;\n\n    if (ri->flags & SRI_FAILOVER_IN_PROGRESS) {\n        addReplyBulkCString(c,\"failover-state\");\n        addReplyBulkCString(c,(char*)sentinelFailoverStateStr(ri->failover_state));\n        fields++;\n    }\n\n    addReplyBulkCString(c,\"last-ping-sent\");\n    addReplyBulkLongLong(c,\n        ri->last_ping_time ? (mstime() - ri->last_ping_time) : 0);\n    fields++;\n\n    addReplyBulkCString(c,\"last-ok-ping-reply\");\n    addReplyBulkLongLong(c,mstime() - ri->last_avail_time);\n    fields++;\n\n    addReplyBulkCString(c,\"last-ping-reply\");\n    addReplyBulkLongLong(c,mstime() - ri->last_pong_time);\n    fields++;\n\n    if (ri->flags & SRI_S_DOWN) {\n        addReplyBulkCString(c,\"s-down-time\");\n        addReplyBulkLongLong(c,mstime()-ri->s_down_since_time);\n        fields++;\n    }\n\n    if (ri->flags & SRI_O_DOWN) {\n        addReplyBulkCString(c,\"o-down-time\");\n        addReplyBulkLongLong(c,mstime()-ri->o_down_since_time);\n        fields++;\n    }\n\n    addReplyBulkCString(c,\"down-after-milliseconds\");\n    addReplyBulkLongLong(c,ri->down_after_period);\n    fields++;\n\n    /* Masters and Slaves */\n    if (ri->flags & (SRI_MASTER|SRI_SLAVE)) {\n        addReplyBulkCString(c,\"info-refresh\");\n        addReplyBulkLongLong(c,mstime() - ri->info_refresh);\n        fields++;\n\n        addReplyBulkCString(c,\"role-reported\");\n        addReplyBulkCString(c, (ri->role_reported == SRI_MASTER) ? \"master\" :\n                                                                   \"slave\");\n        fields++;\n\n        addReplyBulkCString(c,\"role-reported-time\");\n        addReplyBulkLongLong(c,mstime() - ri->role_reported_time);\n        fields++;\n    }\n\n    /* Only masters */\n    if (ri->flags & SRI_MASTER) {\n        addReplyBulkCString(c,\"config-epoch\");\n        addReplyBulkLongLong(c,ri->config_epoch);\n        fields++;\n\n        addReplyBulkCString(c,\"num-slaves\");\n        addReplyBulkLongLong(c,dictSize(ri->slaves));\n        fields++;\n\n        addReplyBulkCString(c,\"num-other-sentinels\");\n        addReplyBulkLongLong(c,dictSize(ri->sentinels));\n        fields++;\n\n        addReplyBulkCString(c,\"quorum\");\n        addReplyBulkLongLong(c,ri->quorum);\n        fields++;\n\n        addReplyBulkCString(c,\"failover-timeout\");\n        addReplyBulkLongLong(c,ri->failover_timeout);\n        fields++;\n\n        addReplyBulkCString(c,\"parallel-syncs\");\n        addReplyBulkLongLong(c,ri->parallel_syncs);\n        fields++;\n\n        if (ri->notification_script) {\n            addReplyBulkCString(c,\"notification-script\");\n            addReplyBulkCString(c,ri->notification_script);\n            fields++;\n        }\n\n        if (ri->client_reconfig_script) {\n            addReplyBulkCString(c,\"client-reconfig-script\");\n            addReplyBulkCString(c,ri->client_reconfig_script);\n            fields++;\n        }\n    }\n\n    /* Only slaves */\n    if (ri->flags & SRI_SLAVE) {\n        addReplyBulkCString(c,\"master-link-down-time\");\n        addReplyBulkLongLong(c,ri->master_link_down_time);\n        fields++;\n\n        addReplyBulkCString(c,\"master-link-status\");\n        addReplyBulkCString(c,\n            (ri->slave_master_link_status == SENTINEL_MASTER_LINK_STATUS_UP) ?\n            \"ok\" : \"err\");\n        fields++;\n\n        addReplyBulkCString(c,\"master-host\");\n        addReplyBulkCString(c,\n            ri->slave_master_host ? ri->slave_master_host : \"?\");\n        fields++;\n\n        addReplyBulkCString(c,\"master-port\");\n        addReplyBulkLongLong(c,ri->slave_master_port);\n        fields++;\n\n        addReplyBulkCString(c,\"slave-priority\");\n        addReplyBulkLongLong(c,ri->slave_priority);\n        fields++;\n\n        addReplyBulkCString(c,\"slave-repl-offset\");\n        addReplyBulkLongLong(c,ri->slave_repl_offset);\n        fields++;\n    }\n\n    /* Only sentinels */\n    if (ri->flags & SRI_SENTINEL) {\n        addReplyBulkCString(c,\"last-hello-message\");\n        addReplyBulkLongLong(c,mstime() - ri->last_hello_time);\n        fields++;\n\n        addReplyBulkCString(c,\"voted-leader\");\n        addReplyBulkCString(c,ri->leader ? ri->leader : \"?\");\n        fields++;\n\n        addReplyBulkCString(c,\"voted-leader-epoch\");\n        addReplyBulkLongLong(c,ri->leader_epoch);\n        fields++;\n    }\n\n    setDeferredMultiBulkLength(c,mbl,fields*2);\n}\n\n/* Output a number of instances contained inside a dictionary as\n * Redis protocol. */\nvoid addReplyDictOfRedisInstances(redisClient *c, dict *instances) {\n    dictIterator *di;\n    dictEntry *de;\n\n    di = dictGetIterator(instances);\n    addReplyMultiBulkLen(c,dictSize(instances));\n    while((de = dictNext(di)) != NULL) {\n        sentinelRedisInstance *ri = dictGetVal(de);\n\n        addReplySentinelRedisInstance(c,ri);\n    }\n    dictReleaseIterator(di);\n}\n\n/* Lookup the named master into sentinel.masters.\n * If the master is not found reply to the client with an error and returns\n * NULL. */\nsentinelRedisInstance *sentinelGetMasterByNameOrReplyError(redisClient *c,\n                        robj *name)\n{\n    sentinelRedisInstance *ri;\n\n    ri = dictFetchValue(sentinel.masters,name->ptr);\n    if (!ri) {\n        addReplyError(c,\"No such master with that name\");\n        return NULL;\n    }\n    return ri;\n}\n\n#define SENTINEL_ISQR_OK 0\n#define SENTINEL_ISQR_NOQUORUM (1<<0)\n#define SENTINEL_ISQR_NOAUTH (1<<1)\nint sentinelIsQuorumReachable(sentinelRedisInstance *master, int *usableptr) {\n    dictIterator *di;\n    dictEntry *de;\n    int usable = 1; /* Number of usable Sentinels. Init to 1 to count myself. */\n    int result = SENTINEL_ISQR_OK;\n    int voters = dictSize(master->sentinels)+1; /* Known Sentinels + myself. */\n\n    di = dictGetIterator(master->sentinels);\n    while((de = dictNext(di)) != NULL) {\n        sentinelRedisInstance *ri = dictGetVal(de);\n\n        if (ri->flags & (SRI_S_DOWN|SRI_O_DOWN)) continue;\n        usable++;\n    }\n    dictReleaseIterator(di);\n\n    if (usable < (int)master->quorum) result |= SENTINEL_ISQR_NOQUORUM;\n    if (usable < voters/2+1) result |= SENTINEL_ISQR_NOAUTH;\n    if (usableptr) *usableptr = usable;\n    return result;\n}\n\nvoid sentinelCommand(redisClient *c) {\n    if (!strcasecmp(c->argv[1]->ptr,\"masters\")) {\n        /* SENTINEL MASTERS */\n        if (c->argc != 2) goto numargserr;\n        addReplyDictOfRedisInstances(c,sentinel.masters);\n    } else if (!strcasecmp(c->argv[1]->ptr,\"master\")) {\n        /* SENTINEL MASTER <name> */\n        sentinelRedisInstance *ri;\n\n        if (c->argc != 3) goto numargserr;\n        if ((ri = sentinelGetMasterByNameOrReplyError(c,c->argv[2]))\n            == NULL) return;\n        addReplySentinelRedisInstance(c,ri);\n    } else if (!strcasecmp(c->argv[1]->ptr,\"slaves\")) {\n        /* SENTINEL SLAVES <master-name> */\n        sentinelRedisInstance *ri;\n\n        if (c->argc != 3) goto numargserr;\n        if ((ri = sentinelGetMasterByNameOrReplyError(c,c->argv[2])) == NULL)\n            return;\n        addReplyDictOfRedisInstances(c,ri->slaves);\n    } else if (!strcasecmp(c->argv[1]->ptr,\"sentinels\")) {\n        /* SENTINEL SENTINELS <master-name> */\n        sentinelRedisInstance *ri;\n\n        if (c->argc != 3) goto numargserr;\n        if ((ri = sentinelGetMasterByNameOrReplyError(c,c->argv[2])) == NULL)\n            return;\n        addReplyDictOfRedisInstances(c,ri->sentinels);\n    } else if (!strcasecmp(c->argv[1]->ptr,\"is-master-down-by-addr\")) {\n        /* SENTINEL IS-MASTER-DOWN-BY-ADDR <ip> <port> <current-epoch> <runid>*/\n        sentinelRedisInstance *ri;\n        long long req_epoch;\n        uint64_t leader_epoch = 0;\n        char *leader = NULL;\n        long port;\n        int isdown = 0;\n\n        if (c->argc != 6) goto numargserr;\n        if (getLongFromObjectOrReply(c,c->argv[3],&port,NULL) != REDIS_OK ||\n            getLongLongFromObjectOrReply(c,c->argv[4],&req_epoch,NULL)\n                                                              != REDIS_OK)\n            return;\n        ri = getSentinelRedisInstanceByAddrAndRunID(sentinel.masters,\n            c->argv[2]->ptr,port,NULL);\n\n        /* It exists? Is actually a master? Is subjectively down? It's down.\n         * Note: if we are in tilt mode we always reply with \"0\". */\n        if (!sentinel.tilt && ri && (ri->flags & SRI_S_DOWN) &&\n                                    (ri->flags & SRI_MASTER))\n            isdown = 1;\n\n        /* Vote for the master (or fetch the previous vote) if the request\n         * includes a runid, otherwise the sender is not seeking for a vote. */\n        if (ri && ri->flags & SRI_MASTER && strcasecmp(c->argv[5]->ptr,\"*\")) {\n            leader = sentinelVoteLeader(ri,(uint64_t)req_epoch,\n                                            c->argv[5]->ptr,\n                                            &leader_epoch);\n        }\n\n        /* Reply with a three-elements multi-bulk reply:\n         * down state, leader, vote epoch. */\n        addReplyMultiBulkLen(c,3);\n        addReply(c, isdown ? shared.cone : shared.czero);\n        addReplyBulkCString(c, leader ? leader : \"*\");\n        addReplyLongLong(c, (long long)leader_epoch);\n        if (leader) sdsfree(leader);\n    } else if (!strcasecmp(c->argv[1]->ptr,\"reset\")) {\n        /* SENTINEL RESET <pattern> */\n        if (c->argc != 3) goto numargserr;\n        addReplyLongLong(c,sentinelResetMastersByPattern(c->argv[2]->ptr,SENTINEL_GENERATE_EVENT));\n    } else if (!strcasecmp(c->argv[1]->ptr,\"get-master-addr-by-name\")) {\n        /* SENTINEL GET-MASTER-ADDR-BY-NAME <master-name> */\n        sentinelRedisInstance *ri;\n\n        if (c->argc != 3) goto numargserr;\n        ri = sentinelGetMasterByName(c->argv[2]->ptr);\n        if (ri == NULL) {\n            addReply(c,shared.nullmultibulk);\n        } else {\n            sentinelAddr *addr = sentinelGetCurrentMasterAddress(ri);\n\n            addReplyMultiBulkLen(c,2);\n            addReplyBulkCString(c,addr->ip);\n            addReplyBulkLongLong(c,addr->port);\n        }\n    } else if (!strcasecmp(c->argv[1]->ptr,\"failover\")) {\n        /* SENTINEL FAILOVER <master-name> */\n        sentinelRedisInstance *ri;\n\n        if (c->argc != 3) goto numargserr;\n        if ((ri = sentinelGetMasterByNameOrReplyError(c,c->argv[2])) == NULL)\n            return;\n        if (ri->flags & SRI_FAILOVER_IN_PROGRESS) {\n            addReplySds(c,sdsnew(\"-INPROG Failover already in progress\\r\\n\"));\n            return;\n        }\n        if (sentinelSelectSlave(ri) == NULL) {\n            addReplySds(c,sdsnew(\"-NOGOODSLAVE No suitable slave to promote\\r\\n\"));\n            return;\n        }\n        redisLog(REDIS_WARNING,\"Executing user requested FAILOVER of '%s'\",\n            ri->name);\n        sentinelStartFailover(ri);\n        ri->flags |= SRI_FORCE_FAILOVER;\n        addReply(c,shared.ok);\n    } else if (!strcasecmp(c->argv[1]->ptr,\"pending-scripts\")) {\n        /* SENTINEL PENDING-SCRIPTS */\n\n        if (c->argc != 2) goto numargserr;\n        sentinelPendingScriptsCommand(c);\n    } else if (!strcasecmp(c->argv[1]->ptr,\"monitor\")) {\n        /* SENTINEL MONITOR <name> <ip> <port> <quorum> */\n        sentinelRedisInstance *ri;\n        long quorum, port;\n        char ip[REDIS_IP_STR_LEN];\n\n        if (c->argc != 6) goto numargserr;\n        if (getLongFromObjectOrReply(c,c->argv[5],&quorum,\"Invalid quorum\")\n            != REDIS_OK) return;\n        if (getLongFromObjectOrReply(c,c->argv[4],&port,\"Invalid port\")\n            != REDIS_OK) return;\n        /* Make sure the IP field is actually a valid IP before passing it\n         * to createSentinelRedisInstance(), otherwise we may trigger a\n         * DNS lookup at runtime. */\n        if (anetResolveIP(NULL,c->argv[3]->ptr,ip,sizeof(ip)) == ANET_ERR) {\n            addReplyError(c,\"Invalid IP address specified\");\n            return;\n        }\n\n        /* Parameters are valid. Try to create the master instance. */\n        ri = createSentinelRedisInstance(c->argv[2]->ptr,SRI_MASTER,\n                c->argv[3]->ptr,port,quorum,NULL);\n        if (ri == NULL) {\n            switch(errno) {\n            case EBUSY:\n                addReplyError(c,\"Duplicated master name\");\n                break;\n            case EINVAL:\n                addReplyError(c,\"Invalid port number\");\n                break;\n            default:\n                addReplyError(c,\"Unspecified error adding the instance\");\n                break;\n            }\n        } else {\n            sentinelFlushConfig();\n            sentinelEvent(REDIS_WARNING,\"+monitor\",ri,\"%@ quorum %d\",ri->quorum);\n            addReply(c,shared.ok);\n        }\n    } else if (!strcasecmp(c->argv[1]->ptr,\"flushconfig\")) {\n        sentinelFlushConfig();\n        addReply(c,shared.ok);\n        return;\n    } else if (!strcasecmp(c->argv[1]->ptr,\"remove\")) {\n        /* SENTINEL REMOVE <name> */\n        sentinelRedisInstance *ri;\n\n        if ((ri = sentinelGetMasterByNameOrReplyError(c,c->argv[2]))\n            == NULL) return;\n        sentinelEvent(REDIS_WARNING,\"-monitor\",ri,\"%@\");\n        dictDelete(sentinel.masters,c->argv[2]->ptr);\n        sentinelFlushConfig();\n        addReply(c,shared.ok);\n    } else if (!strcasecmp(c->argv[1]->ptr,\"ckquorum\")) {\n        /* SENTINEL CKQUORUM <name> */\n        sentinelRedisInstance *ri;\n        int usable;\n\n        if ((ri = sentinelGetMasterByNameOrReplyError(c,c->argv[2]))\n            == NULL) return;\n        int result = sentinelIsQuorumReachable(ri,&usable);\n        if (result == SENTINEL_ISQR_OK) {\n            addReplySds(c, sdscatfmt(sdsempty(),\n                \"+OK %i usable Sentinels. Quorum and failover authorization \"\n                \"can be reached\\r\\n\",usable));\n        } else {\n            sds e = sdscatfmt(sdsempty(),\n                \"-NOQUORUM %i usable Sentinels. \",usable);\n            if (result & SENTINEL_ISQR_NOQUORUM)\n                e = sdscat(e,\"Not enough available Sentinels to reach the\"\n                             \" specified quorum for this master\");\n            if (result & SENTINEL_ISQR_NOAUTH) {\n                if (result & SENTINEL_ISQR_NOQUORUM) e = sdscat(e,\". \");\n                e = sdscat(e, \"Not enough available Sentinels to reach the\"\n                              \" majority and authorize a failover\");\n            }\n            e = sdscat(e,\"\\r\\n\");\n            addReplySds(c,e);\n        }\n    } else if (!strcasecmp(c->argv[1]->ptr,\"set\")) {\n        if (c->argc < 3 || c->argc % 2 == 0) goto numargserr;\n        sentinelSetCommand(c);\n    } else {\n        addReplyErrorFormat(c,\"Unknown sentinel subcommand '%s'\",\n                               (char*)c->argv[1]->ptr);\n    }\n    return;\n\nnumargserr:\n    addReplyErrorFormat(c,\"Wrong number of arguments for 'sentinel %s'\",\n                          (char*)c->argv[1]->ptr);\n}\n\n/* SENTINEL INFO [section] */\nvoid sentinelInfoCommand(redisClient *c) {\n    char *section = c->argc == 2 ? c->argv[1]->ptr : \"default\";\n    sds info = sdsempty();\n    int defsections = !strcasecmp(section,\"default\");\n    int sections = 0;\n\n    if (c->argc > 2) {\n        addReply(c,shared.syntaxerr);\n        return;\n    }\n\n    if (!strcasecmp(section,\"server\") || defsections) {\n        if (sections++) info = sdscat(info,\"\\r\\n\");\n        sds serversection = genRedisInfoString(\"server\");\n        info = sdscatlen(info,serversection,sdslen(serversection));\n        sdsfree(serversection);\n    }\n\n    if (!strcasecmp(section,\"sentinel\") || defsections) {\n        dictIterator *di;\n        dictEntry *de;\n        int master_id = 0;\n\n        if (sections++) info = sdscat(info,\"\\r\\n\");\n        info = sdscatprintf(info,\n            \"# Sentinel\\r\\n\"\n            \"sentinel_masters:%lu\\r\\n\"\n            \"sentinel_tilt:%d\\r\\n\"\n            \"sentinel_running_scripts:%d\\r\\n\"\n            \"sentinel_scripts_queue_length:%ld\\r\\n\",\n            dictSize(sentinel.masters),\n            sentinel.tilt,\n            sentinel.running_scripts,\n            listLength(sentinel.scripts_queue));\n\n        di = dictGetIterator(sentinel.masters);\n        while((de = dictNext(di)) != NULL) {\n            sentinelRedisInstance *ri = dictGetVal(de);\n            char *status = \"ok\";\n\n            if (ri->flags & SRI_O_DOWN) status = \"odown\";\n            else if (ri->flags & SRI_S_DOWN) status = \"sdown\";\n            info = sdscatprintf(info,\n                \"master%d:name=%s,status=%s,address=%s:%d,\"\n                \"slaves=%lu,sentinels=%lu\\r\\n\",\n                master_id++, ri->name, status,\n                ri->addr->ip, ri->addr->port,\n                dictSize(ri->slaves),\n                dictSize(ri->sentinels)+1);\n        }\n        dictReleaseIterator(di);\n    }\n\n    addReplySds(c,sdscatprintf(sdsempty(),\"$%lu\\r\\n\",\n        (unsigned long)sdslen(info)));\n    addReplySds(c,info);\n    addReply(c,shared.crlf);\n}\n\n/* Implements Sentinel verison of the ROLE command. The output is\n * \"sentinel\" and the list of currently monitored master names. */\nvoid sentinelRoleCommand(redisClient *c) {\n    dictIterator *di;\n    dictEntry *de;\n\n    addReplyMultiBulkLen(c,2);\n    addReplyBulkCBuffer(c,\"sentinel\",8);\n    addReplyMultiBulkLen(c,dictSize(sentinel.masters));\n\n    di = dictGetIterator(sentinel.masters);\n    while((de = dictNext(di)) != NULL) {\n        sentinelRedisInstance *ri = dictGetVal(de);\n\n        addReplyBulkCString(c,ri->name);\n    }\n    dictReleaseIterator(di);\n}\n\n/* SENTINEL SET <mastername> [<option> <value> ...] */\nvoid sentinelSetCommand(redisClient *c) {\n    sentinelRedisInstance *ri;\n    int j, changes = 0;\n    char *option, *value;\n\n    if ((ri = sentinelGetMasterByNameOrReplyError(c,c->argv[2]))\n        == NULL) return;\n\n    /* Process option - value pairs. */\n    for (j = 3; j < c->argc; j += 2) {\n        option = c->argv[j]->ptr;\n        value = c->argv[j+1]->ptr;\n        robj *o = c->argv[j+1];\n        long long ll;\n\n        if (!strcasecmp(option,\"down-after-milliseconds\")) {\n            /* down-after-millisecodns <milliseconds> */\n            if (getLongLongFromObject(o,&ll) == REDIS_ERR || ll <= 0)\n                goto badfmt;\n            ri->down_after_period = ll;\n            sentinelPropagateDownAfterPeriod(ri);\n            changes++;\n        } else if (!strcasecmp(option,\"failover-timeout\")) {\n            /* failover-timeout <milliseconds> */\n            if (getLongLongFromObject(o,&ll) == REDIS_ERR || ll <= 0)\n                goto badfmt;\n            ri->failover_timeout = ll;\n            changes++;\n       } else if (!strcasecmp(option,\"parallel-syncs\")) {\n            /* parallel-syncs <milliseconds> */\n            if (getLongLongFromObject(o,&ll) == REDIS_ERR || ll <= 0)\n                goto badfmt;\n            ri->parallel_syncs = ll;\n            changes++;\n       } else if (!strcasecmp(option,\"notification-script\")) {\n            /* notification-script <path> */\n            if (strlen(value) && access(value,X_OK) == -1) {\n                addReplyError(c,\n                    \"Notification script seems non existing or non executable\");\n                if (changes) sentinelFlushConfig();\n                return;\n            }\n            sdsfree(ri->notification_script);\n            ri->notification_script = strlen(value) ? sdsnew(value) : NULL;\n            changes++;\n       } else if (!strcasecmp(option,\"client-reconfig-script\")) {\n            /* client-reconfig-script <path> */\n            if (strlen(value) && access(value,X_OK) == -1) {\n                addReplyError(c,\n                    \"Client reconfiguration script seems non existing or \"\n                    \"non executable\");\n                if (changes) sentinelFlushConfig();\n                return;\n            }\n            sdsfree(ri->client_reconfig_script);\n            ri->client_reconfig_script = strlen(value) ? sdsnew(value) : NULL;\n            changes++;\n       } else if (!strcasecmp(option,\"auth-pass\")) {\n            /* auth-pass <password> */\n            sdsfree(ri->auth_pass);\n            ri->auth_pass = strlen(value) ? sdsnew(value) : NULL;\n            changes++;\n       } else if (!strcasecmp(option,\"quorum\")) {\n            /* quorum <count> */\n            if (getLongLongFromObject(o,&ll) == REDIS_ERR || ll <= 0)\n                goto badfmt;\n            ri->quorum = ll;\n            changes++;\n        } else {\n            addReplyErrorFormat(c,\"Unknown option '%s' for SENTINEL SET\",\n                option);\n            if (changes) sentinelFlushConfig();\n            return;\n        }\n        sentinelEvent(REDIS_WARNING,\"+set\",ri,\"%@ %s %s\",option,value);\n    }\n\n    if (changes) sentinelFlushConfig();\n    addReply(c,shared.ok);\n    return;\n\nbadfmt: /* Bad format errors */\n    if (changes) sentinelFlushConfig();\n    addReplyErrorFormat(c,\"Invalid argument '%s' for SENTINEL SET '%s'\",\n            value, option);\n}\n\n/* Our fake PUBLISH command: it is actually useful only to receive hello messages\n * from the other sentinel instances, and publishing to a channel other than\n * SENTINEL_HELLO_CHANNEL is forbidden.\n *\n * Because we have a Sentinel PUBLISH, the code to send hello messages is the same\n * for all the three kind of instances: masters, slaves, sentinels. */\nvoid sentinelPublishCommand(redisClient *c) {\n    if (strcmp(c->argv[1]->ptr,SENTINEL_HELLO_CHANNEL)) {\n        addReplyError(c, \"Only HELLO messages are accepted by Sentinel instances.\");\n        return;\n    }\n    sentinelProcessHelloMessage(c->argv[2]->ptr,sdslen(c->argv[2]->ptr));\n    addReplyLongLong(c,1);\n}\n\n/* ===================== SENTINEL availability checks ======================= */\n\n/* Is this instance down from our point of view? */\nvoid sentinelCheckSubjectivelyDown(sentinelRedisInstance *ri) {\n    mstime_t elapsed = 0;\n\n    if (ri->last_ping_time)\n        elapsed = mstime() - ri->last_ping_time;\n\n    /* Check if we are in need for a reconnection of one of the\n     * links, because we are detecting low activity.\n     *\n     * 1) Check if the command link seems connected, was connected not less\n     *    than SENTINEL_MIN_LINK_RECONNECT_PERIOD, but still we have a\n     *    pending ping for more than half the timeout. */\n    if (ri->cc &&\n        (mstime() - ri->cc_conn_time) > SENTINEL_MIN_LINK_RECONNECT_PERIOD &&\n        ri->last_ping_time != 0 && /* Ther is a pending ping... */\n        /* The pending ping is delayed, and we did not received\n         * error replies as well. */\n        (mstime() - ri->last_ping_time) > (ri->down_after_period/2) &&\n        (mstime() - ri->last_pong_time) > (ri->down_after_period/2))\n    {\n        sentinelKillLink(ri,ri->cc);\n    }\n\n    /* 2) Check if the pubsub link seems connected, was connected not less\n     *    than SENTINEL_MIN_LINK_RECONNECT_PERIOD, but still we have no\n     *    activity in the Pub/Sub channel for more than\n     *    SENTINEL_PUBLISH_PERIOD * 3.\n     */\n    if (ri->pc &&\n        (mstime() - ri->pc_conn_time) > SENTINEL_MIN_LINK_RECONNECT_PERIOD &&\n        (mstime() - ri->pc_last_activity) > (SENTINEL_PUBLISH_PERIOD*3))\n    {\n        sentinelKillLink(ri,ri->pc);\n    }\n\n    /* Update the SDOWN flag. We believe the instance is SDOWN if:\n     *\n     * 1) It is not replying.\n     * 2) We believe it is a master, it reports to be a slave for enough time\n     *    to meet the down_after_period, plus enough time to get two times\n     *    INFO report from the instance. */\n    if (elapsed > ri->down_after_period ||\n        (ri->flags & SRI_MASTER &&\n         ri->role_reported == SRI_SLAVE &&\n         mstime() - ri->role_reported_time >\n          (ri->down_after_period+SENTINEL_INFO_PERIOD*2)))\n    {\n        /* Is subjectively down */\n        if ((ri->flags & SRI_S_DOWN) == 0) {\n            sentinelEvent(REDIS_WARNING,\"+sdown\",ri,\"%@\");\n            ri->s_down_since_time = mstime();\n            ri->flags |= SRI_S_DOWN;\n        }\n    } else {\n        /* Is subjectively up */\n        if (ri->flags & SRI_S_DOWN) {\n            sentinelEvent(REDIS_WARNING,\"-sdown\",ri,\"%@\");\n            ri->flags &= ~(SRI_S_DOWN|SRI_SCRIPT_KILL_SENT);\n        }\n    }\n}\n\n/* Is this instance down according to the configured quorum?\n *\n * Note that ODOWN is a weak quorum, it only means that enough Sentinels\n * reported in a given time range that the instance was not reachable.\n * However messages can be delayed so there are no strong guarantees about\n * N instances agreeing at the same time about the down state. */\nvoid sentinelCheckObjectivelyDown(sentinelRedisInstance *master) {\n    dictIterator *di;\n    dictEntry *de;\n    unsigned int quorum = 0, odown = 0;\n\n    if (master->flags & SRI_S_DOWN) {\n        /* Is down for enough sentinels? */\n        quorum = 1; /* the current sentinel. */\n        /* Count all the other sentinels. */\n        di = dictGetIterator(master->sentinels);\n        while((de = dictNext(di)) != NULL) {\n            sentinelRedisInstance *ri = dictGetVal(de);\n\n            if (ri->flags & SRI_MASTER_DOWN) quorum++;\n        }\n        dictReleaseIterator(di);\n        if (quorum >= master->quorum) odown = 1;\n    }\n\n    /* Set the flag accordingly to the outcome. */\n    if (odown) {\n        if ((master->flags & SRI_O_DOWN) == 0) {\n            sentinelEvent(REDIS_WARNING,\"+odown\",master,\"%@ #quorum %d/%d\",\n                quorum, master->quorum);\n            master->flags |= SRI_O_DOWN;\n            master->o_down_since_time = mstime();\n        }\n    } else {\n        if (master->flags & SRI_O_DOWN) {\n            sentinelEvent(REDIS_WARNING,\"-odown\",master,\"%@\");\n            master->flags &= ~SRI_O_DOWN;\n        }\n    }\n}\n\n/* Receive the SENTINEL is-master-down-by-addr reply, see the\n * sentinelAskMasterStateToOtherSentinels() function for more information. */\nvoid sentinelReceiveIsMasterDownReply(redisAsyncContext *c, void *reply, void *privdata) {\n    sentinelRedisInstance *ri = c->data;\n    redisReply *r;\n    REDIS_NOTUSED(privdata);\n\n    if (ri) ri->pending_commands--;\n    if (!reply || !ri) return;\n    r = reply;\n\n    /* Ignore every error or unexpected reply.\n     * Note that if the command returns an error for any reason we'll\n     * end clearing the SRI_MASTER_DOWN flag for timeout anyway. */\n    if (r->type == REDIS_REPLY_ARRAY && r->elements == 3 &&\n        r->element[0]->type == REDIS_REPLY_INTEGER &&\n        r->element[1]->type == REDIS_REPLY_STRING &&\n        r->element[2]->type == REDIS_REPLY_INTEGER)\n    {\n        ri->last_master_down_reply_time = mstime();\n        if (r->element[0]->integer == 1) {\n            ri->flags |= SRI_MASTER_DOWN;\n        } else {\n            ri->flags &= ~SRI_MASTER_DOWN;\n        }\n        if (strcmp(r->element[1]->str,\"*\")) {\n            /* If the runid in the reply is not \"*\" the Sentinel actually\n             * replied with a vote. */\n            sdsfree(ri->leader);\n            if ((long long)ri->leader_epoch != r->element[2]->integer)\n                redisLog(REDIS_WARNING,\n                    \"%s voted for %s %llu\", ri->name,\n                    r->element[1]->str,\n                    (unsigned long long) r->element[2]->integer);\n            ri->leader = sdsnew(r->element[1]->str);\n            ri->leader_epoch = r->element[2]->integer;\n        }\n    }\n}\n\n/* If we think the master is down, we start sending\n * SENTINEL IS-MASTER-DOWN-BY-ADDR requests to other sentinels\n * in order to get the replies that allow to reach the quorum\n * needed to mark the master in ODOWN state and trigger a failover. */\n#define SENTINEL_ASK_FORCED (1<<0)\nvoid sentinelAskMasterStateToOtherSentinels(sentinelRedisInstance *master, int flags) {\n    dictIterator *di;\n    dictEntry *de;\n\n    di = dictGetIterator(master->sentinels);\n    while((de = dictNext(di)) != NULL) {\n        sentinelRedisInstance *ri = dictGetVal(de);\n        mstime_t elapsed = mstime() - ri->last_master_down_reply_time;\n        char port[32];\n        int retval;\n\n        /* If the master state from other sentinel is too old, we clear it. */\n        if (elapsed > SENTINEL_ASK_PERIOD*5) {\n            ri->flags &= ~SRI_MASTER_DOWN;\n            sdsfree(ri->leader);\n            ri->leader = NULL;\n        }\n\n        /* Only ask if master is down to other sentinels if:\n         *\n         * 1) We believe it is down, or there is a failover in progress.\n         * 2) Sentinel is connected.\n         * 3) We did not received the info within SENTINEL_ASK_PERIOD ms. */\n        if ((master->flags & SRI_S_DOWN) == 0) continue;\n        if (ri->flags & SRI_DISCONNECTED) continue;\n        if (!(flags & SENTINEL_ASK_FORCED) &&\n            mstime() - ri->last_master_down_reply_time < SENTINEL_ASK_PERIOD)\n            continue;\n\n        /* Ask */\n        ll2string(port,sizeof(port),master->addr->port);\n        retval = redisAsyncCommand(ri->cc,\n                    sentinelReceiveIsMasterDownReply, NULL,\n                    \"SENTINEL is-master-down-by-addr %s %s %llu %s\",\n                    master->addr->ip, port,\n                    sentinel.current_epoch,\n                    (master->failover_state > SENTINEL_FAILOVER_STATE_NONE) ?\n                    server.runid : \"*\");\n        if (retval == REDIS_OK) ri->pending_commands++;\n    }\n    dictReleaseIterator(di);\n}\n\n/* =============================== FAILOVER ================================= */\n\n/* Vote for the sentinel with 'req_runid' or return the old vote if already\n * voted for the specifed 'req_epoch' or one greater.\n *\n * If a vote is not available returns NULL, otherwise return the Sentinel\n * runid and populate the leader_epoch with the epoch of the vote. */\nchar *sentinelVoteLeader(sentinelRedisInstance *master, uint64_t req_epoch, char *req_runid, uint64_t *leader_epoch) {\n    if (req_epoch > sentinel.current_epoch) {\n        sentinel.current_epoch = req_epoch;\n        sentinelFlushConfig();\n        sentinelEvent(REDIS_WARNING,\"+new-epoch\",master,\"%llu\",\n            (unsigned long long) sentinel.current_epoch);\n    }\n\n    if (master->leader_epoch < req_epoch && sentinel.current_epoch <= req_epoch)\n    {\n        sdsfree(master->leader);\n        master->leader = sdsnew(req_runid);\n        master->leader_epoch = sentinel.current_epoch;\n        sentinelFlushConfig();\n        sentinelEvent(REDIS_WARNING,\"+vote-for-leader\",master,\"%s %llu\",\n            master->leader, (unsigned long long) master->leader_epoch);\n        /* If we did not voted for ourselves, set the master failover start\n         * time to now, in order to force a delay before we can start a\n         * failover for the same master. */\n        if (strcasecmp(master->leader,server.runid))\n            master->failover_start_time = mstime()+rand()%SENTINEL_MAX_DESYNC;\n    }\n\n    *leader_epoch = master->leader_epoch;\n    return master->leader ? sdsnew(master->leader) : NULL;\n}\n\nstruct sentinelLeader {\n    char *runid;\n    unsigned long votes;\n};\n\n/* Helper function for sentinelGetLeader, increment the counter\n * relative to the specified runid. */\nint sentinelLeaderIncr(dict *counters, char *runid) {\n    dictEntry *de = dictFind(counters,runid);\n    uint64_t oldval;\n\n    if (de) {\n        oldval = dictGetUnsignedIntegerVal(de);\n        dictSetUnsignedIntegerVal(de,oldval+1);\n        return oldval+1;\n    } else {\n        de = dictAddRaw(counters,runid);\n        redisAssert(de != NULL);\n        dictSetUnsignedIntegerVal(de,1);\n        return 1;\n    }\n}\n\n/* Scan all the Sentinels attached to this master to check if there\n * is a leader for the specified epoch.\n *\n * To be a leader for a given epoch, we should have the majority of\n * the Sentinels we know (ever seen since the last SENTINEL RESET) that\n * reported the same instance as leader for the same epoch. */\nchar *sentinelGetLeader(sentinelRedisInstance *master, uint64_t epoch) {\n    dict *counters;\n    dictIterator *di;\n    dictEntry *de;\n    unsigned int voters = 0, voters_quorum;\n    char *myvote;\n    char *winner = NULL;\n    uint64_t leader_epoch;\n    uint64_t max_votes = 0;\n\n    redisAssert(master->flags & (SRI_O_DOWN|SRI_FAILOVER_IN_PROGRESS));\n    counters = dictCreate(&leaderVotesDictType,NULL);\n\n    voters = dictSize(master->sentinels)+1; /* All the other sentinels and me. */\n\n    /* Count other sentinels votes */\n    di = dictGetIterator(master->sentinels);\n    while((de = dictNext(di)) != NULL) {\n        sentinelRedisInstance *ri = dictGetVal(de);\n        if (ri->leader != NULL && ri->leader_epoch == sentinel.current_epoch)\n            sentinelLeaderIncr(counters,ri->leader);\n    }\n    dictReleaseIterator(di);\n\n    /* Check what's the winner. For the winner to win, it needs two conditions:\n     * 1) Absolute majority between voters (50% + 1).\n     * 2) And anyway at least master->quorum votes. */\n    di = dictGetIterator(counters);\n    while((de = dictNext(di)) != NULL) {\n        uint64_t votes = dictGetUnsignedIntegerVal(de);\n\n        if (votes > max_votes) {\n            max_votes = votes;\n            winner = dictGetKey(de);\n        }\n    }\n    dictReleaseIterator(di);\n\n    /* Count this Sentinel vote:\n     * if this Sentinel did not voted yet, either vote for the most\n     * common voted sentinel, or for itself if no vote exists at all. */\n    if (winner)\n        myvote = sentinelVoteLeader(master,epoch,winner,&leader_epoch);\n    else\n        myvote = sentinelVoteLeader(master,epoch,server.runid,&leader_epoch);\n\n    if (myvote && leader_epoch == epoch) {\n        uint64_t votes = sentinelLeaderIncr(counters,myvote);\n\n        if (votes > max_votes) {\n            max_votes = votes;\n            winner = myvote;\n        }\n    }\n\n    voters_quorum = voters/2+1;\n    if (winner && (max_votes < voters_quorum || max_votes < master->quorum))\n        winner = NULL;\n\n    winner = winner ? sdsnew(winner) : NULL;\n    sdsfree(myvote);\n    dictRelease(counters);\n    return winner;\n}\n\n/* Send SLAVEOF to the specified instance, always followed by a\n * CONFIG REWRITE command in order to store the new configuration on disk\n * when possible (that is, if the Redis instance is recent enough to support\n * config rewriting, and if the server was started with a configuration file).\n *\n * If Host is NULL the function sends \"SLAVEOF NO ONE\".\n *\n * The command returns REDIS_OK if the SLAVEOF command was accepted for\n * (later) delivery otherwise REDIS_ERR. The command replies are just\n * discarded. */\nint sentinelSendSlaveOf(sentinelRedisInstance *ri, char *host, int port) {\n    char portstr[32];\n    int retval;\n\n    ll2string(portstr,sizeof(portstr),port);\n\n    /* If host is NULL we send SLAVEOF NO ONE that will turn the instance\n     * into a master. */\n    if (host == NULL) {\n        host = \"NO\";\n        memcpy(portstr,\"ONE\",4);\n    }\n\n    /* In order to send SLAVEOF in a safe way, we send a transaction performing\n     * the following tasks:\n     * 1) Reconfigure the instance according to the specified host/port params.\n     * 2) Rewrite the configuraiton.\n     * 3) Disconnect all clients (but this one sending the commnad) in order\n     *    to trigger the ask-master-on-reconnection protocol for connected\n     *    clients.\n     *\n     * Note that we don't check the replies returned by commands, since we\n     * will observe instead the effects in the next INFO output. */\n    retval = redisAsyncCommand(ri->cc,\n        sentinelDiscardReplyCallback, NULL, \"MULTI\");\n    if (retval == REDIS_ERR) return retval;\n    ri->pending_commands++;\n\n    retval = redisAsyncCommand(ri->cc,\n        sentinelDiscardReplyCallback, NULL, \"SLAVEOF %s %s\", host, portstr);\n    if (retval == REDIS_ERR) return retval;\n    ri->pending_commands++;\n\n    retval = redisAsyncCommand(ri->cc,\n        sentinelDiscardReplyCallback, NULL, \"CONFIG REWRITE\");\n    if (retval == REDIS_ERR) return retval;\n    ri->pending_commands++;\n\n    /* CLIENT KILL TYPE <type> is only supported starting from Redis 2.8.12,\n     * however sending it to an instance not understanding this command is not\n     * an issue because CLIENT is variadic command, so Redis will not\n     * recognized as a syntax error, and the transaction will not fail (but\n     * only the unsupported command will fail). */\n    retval = redisAsyncCommand(ri->cc,\n        sentinelDiscardReplyCallback, NULL, \"CLIENT KILL TYPE normal\");\n    if (retval == REDIS_ERR) return retval;\n    ri->pending_commands++;\n\n    retval = redisAsyncCommand(ri->cc,\n        sentinelDiscardReplyCallback, NULL, \"EXEC\");\n    if (retval == REDIS_ERR) return retval;\n    ri->pending_commands++;\n\n    return REDIS_OK;\n}\n\n/* Setup the master state to start a failover. */\nvoid sentinelStartFailover(sentinelRedisInstance *master) {\n    redisAssert(master->flags & SRI_MASTER);\n\n    master->failover_state = SENTINEL_FAILOVER_STATE_WAIT_START;\n    master->flags |= SRI_FAILOVER_IN_PROGRESS;\n    master->failover_epoch = ++sentinel.current_epoch;\n    sentinelEvent(REDIS_WARNING,\"+new-epoch\",master,\"%llu\",\n        (unsigned long long) sentinel.current_epoch);\n    sentinelEvent(REDIS_WARNING,\"+try-failover\",master,\"%@\");\n    master->failover_start_time = mstime()+rand()%SENTINEL_MAX_DESYNC;\n    master->failover_state_change_time = mstime();\n}\n\n/* This function checks if there are the conditions to start the failover,\n * that is:\n *\n * 1) Master must be in ODOWN condition.\n * 2) No failover already in progress.\n * 3) No failover already attempted recently.\n *\n * We still don't know if we'll win the election so it is possible that we\n * start the failover but that we'll not be able to act.\n *\n * Return non-zero if a failover was started. */\nint sentinelStartFailoverIfNeeded(sentinelRedisInstance *master) {\n    /* We can't failover if the master is not in O_DOWN state. */\n    if (!(master->flags & SRI_O_DOWN)) return 0;\n\n    /* Failover already in progress? */\n    if (master->flags & SRI_FAILOVER_IN_PROGRESS) return 0;\n\n    /* Last failover attempt started too little time ago? */\n    if (mstime() - master->failover_start_time <\n        master->failover_timeout*2)\n    {\n        if (master->failover_delay_logged != master->failover_start_time) {\n            time_t clock = (master->failover_start_time +\n                            master->failover_timeout*2) / 1000;\n            char ctimebuf[26];\n\n            ctime_r(&clock,ctimebuf);\n            ctimebuf[24] = '\\0'; /* Remove newline. */\n            master->failover_delay_logged = master->failover_start_time;\n            redisLog(REDIS_WARNING,\n                \"Next failover delay: I will not start a failover before %s\",\n                ctimebuf);\n        }\n        return 0;\n    }\n\n    sentinelStartFailover(master);\n    return 1;\n}\n\n/* Select a suitable slave to promote. The current algorithm only uses\n * the following parameters:\n *\n * 1) None of the following conditions: S_DOWN, O_DOWN, DISCONNECTED.\n * 2) Last time the slave replied to ping no more than 5 times the PING period.\n * 3) info_refresh not older than 3 times the INFO refresh period.\n * 4) master_link_down_time no more than:\n *     (now - master->s_down_since_time) + (master->down_after_period * 10).\n *    Basically since the master is down from our POV, the slave reports\n *    to be disconnected no more than 10 times the configured down-after-period.\n *    This is pretty much black magic but the idea is, the master was not\n *    available so the slave may be lagging, but not over a certain time.\n *    Anyway we'll select the best slave according to replication offset.\n * 5) Slave priority can't be zero, otherwise the slave is discarded.\n *\n * Among all the slaves matching the above conditions we select the slave\n * with, in order of sorting key:\n *\n * - lower slave_priority.\n * - bigger processed replication offset.\n * - lexicographically smaller runid.\n *\n * Basically if runid is the same, the slave that processed more commands\n * from the master is selected.\n *\n * The function returns the pointer to the selected slave, otherwise\n * NULL if no suitable slave was found.\n */\n\n/* Helper for sentinelSelectSlave(). This is used by qsort() in order to\n * sort suitable slaves in a \"better first\" order, to take the first of\n * the list. */\nint compareSlavesForPromotion(const void *a, const void *b) {\n    sentinelRedisInstance **sa = (sentinelRedisInstance **)a,\n                          **sb = (sentinelRedisInstance **)b;\n    char *sa_runid, *sb_runid;\n\n    if ((*sa)->slave_priority != (*sb)->slave_priority)\n        return (*sa)->slave_priority - (*sb)->slave_priority;\n\n    /* If priority is the same, select the slave with greater replication\n     * offset (processed more data frmo the master). */\n    if ((*sa)->slave_repl_offset > (*sb)->slave_repl_offset) {\n        return -1; /* a < b */\n    } else if ((*sa)->slave_repl_offset < (*sb)->slave_repl_offset) {\n        return 1; /* b > a */\n    }\n\n    /* If the replication offset is the same select the slave with that has\n     * the lexicographically smaller runid. Note that we try to handle runid\n     * == NULL as there are old Redis versions that don't publish runid in\n     * INFO. A NULL runid is considered bigger than any other runid. */\n    sa_runid = (*sa)->runid;\n    sb_runid = (*sb)->runid;\n    if (sa_runid == NULL && sb_runid == NULL) return 0;\n    else if (sa_runid == NULL) return 1;  /* a > b */\n    else if (sb_runid == NULL) return -1; /* a < b */\n    return strcasecmp(sa_runid, sb_runid);\n}\n\nsentinelRedisInstance *sentinelSelectSlave(sentinelRedisInstance *master) {\n    sentinelRedisInstance **instance =\n        zmalloc(sizeof(instance[0])*dictSize(master->slaves));\n    sentinelRedisInstance *selected = NULL;\n    int instances = 0;\n    dictIterator *di;\n    dictEntry *de;\n    mstime_t max_master_down_time = 0;\n\n    if (master->flags & SRI_S_DOWN)\n        max_master_down_time += mstime() - master->s_down_since_time;\n    max_master_down_time += master->down_after_period * 10;\n\n    di = dictGetIterator(master->slaves);\n    while((de = dictNext(di)) != NULL) {\n        sentinelRedisInstance *slave = dictGetVal(de);\n        mstime_t info_validity_time;\n\n        if (slave->flags & (SRI_S_DOWN|SRI_O_DOWN|SRI_DISCONNECTED)) continue;\n        if (mstime() - slave->last_avail_time > SENTINEL_PING_PERIOD*5) continue;\n        if (slave->slave_priority == 0) continue;\n\n        /* If the master is in SDOWN state we get INFO for slaves every second.\n         * Otherwise we get it with the usual period so we need to account for\n         * a larger delay. */\n        if (master->flags & SRI_S_DOWN)\n            info_validity_time = SENTINEL_PING_PERIOD*5;\n        else\n            info_validity_time = SENTINEL_INFO_PERIOD*3;\n        if (mstime() - slave->info_refresh > info_validity_time) continue;\n        if (slave->master_link_down_time > max_master_down_time) continue;\n        instance[instances++] = slave;\n    }\n    dictReleaseIterator(di);\n    if (instances) {\n        qsort(instance,instances,sizeof(sentinelRedisInstance*),\n            compareSlavesForPromotion);\n        selected = instance[0];\n    }\n    zfree(instance);\n    return selected;\n}\n\n/* ---------------- Failover state machine implementation ------------------- */\nvoid sentinelFailoverWaitStart(sentinelRedisInstance *ri) {\n    char *leader;\n    int isleader;\n\n    /* Check if we are the leader for the failover epoch. */\n    leader = sentinelGetLeader(ri, ri->failover_epoch);\n    isleader = leader && strcasecmp(leader,server.runid) == 0;\n    sdsfree(leader);\n\n    /* If I'm not the leader, and it is not a forced failover via\n     * SENTINEL FAILOVER, then I can't continue with the failover. */\n    if (!isleader && !(ri->flags & SRI_FORCE_FAILOVER)) {\n        int election_timeout = SENTINEL_ELECTION_TIMEOUT;\n\n        /* The election timeout is the MIN between SENTINEL_ELECTION_TIMEOUT\n         * and the configured failover timeout. */\n        if (election_timeout > ri->failover_timeout)\n            election_timeout = ri->failover_timeout;\n        /* Abort the failover if I'm not the leader after some time. */\n        if (mstime() - ri->failover_start_time > election_timeout) {\n            sentinelEvent(REDIS_WARNING,\"-failover-abort-not-elected\",ri,\"%@\");\n            sentinelAbortFailover(ri);\n        }\n        return;\n    }\n    sentinelEvent(REDIS_WARNING,\"+elected-leader\",ri,\"%@\");\n    ri->failover_state = SENTINEL_FAILOVER_STATE_SELECT_SLAVE;\n    ri->failover_state_change_time = mstime();\n    sentinelEvent(REDIS_WARNING,\"+failover-state-select-slave\",ri,\"%@\");\n}\n\nvoid sentinelFailoverSelectSlave(sentinelRedisInstance *ri) {\n    sentinelRedisInstance *slave = sentinelSelectSlave(ri);\n\n    /* We don't handle the timeout in this state as the function aborts\n     * the failover or go forward in the next state. */\n    if (slave == NULL) {\n        sentinelEvent(REDIS_WARNING,\"-failover-abort-no-good-slave\",ri,\"%@\");\n        sentinelAbortFailover(ri);\n    } else {\n        sentinelEvent(REDIS_WARNING,\"+selected-slave\",slave,\"%@\");\n        slave->flags |= SRI_PROMOTED;\n        ri->promoted_slave = slave;\n        ri->failover_state = SENTINEL_FAILOVER_STATE_SEND_SLAVEOF_NOONE;\n        ri->failover_state_change_time = mstime();\n        sentinelEvent(REDIS_NOTICE,\"+failover-state-send-slaveof-noone\",\n            slave, \"%@\");\n    }\n}\n\nvoid sentinelFailoverSendSlaveOfNoOne(sentinelRedisInstance *ri) {\n    int retval;\n\n    /* We can't send the command to the promoted slave if it is now\n     * disconnected. Retry again and again with this state until the timeout\n     * is reached, then abort the failover. */\n    if (ri->promoted_slave->flags & SRI_DISCONNECTED) {\n        if (mstime() - ri->failover_state_change_time > ri->failover_timeout) {\n            sentinelEvent(REDIS_WARNING,\"-failover-abort-slave-timeout\",ri,\"%@\");\n            sentinelAbortFailover(ri);\n        }\n        return;\n    }\n\n    /* Send SLAVEOF NO ONE command to turn the slave into a master.\n     * We actually register a generic callback for this command as we don't\n     * really care about the reply. We check if it worked indirectly observing\n     * if INFO returns a different role (master instead of slave). */\n    retval = sentinelSendSlaveOf(ri->promoted_slave,NULL,0);\n    if (retval != REDIS_OK) return;\n    sentinelEvent(REDIS_NOTICE, \"+failover-state-wait-promotion\",\n        ri->promoted_slave,\"%@\");\n    ri->failover_state = SENTINEL_FAILOVER_STATE_WAIT_PROMOTION;\n    ri->failover_state_change_time = mstime();\n}\n\n/* We actually wait for promotion indirectly checking with INFO when the\n * slave turns into a master. */\nvoid sentinelFailoverWaitPromotion(sentinelRedisInstance *ri) {\n    /* Just handle the timeout. Switching to the next state is handled\n     * by the function parsing the INFO command of the promoted slave. */\n    if (mstime() - ri->failover_state_change_time > ri->failover_timeout) {\n        sentinelEvent(REDIS_WARNING,\"-failover-abort-slave-timeout\",ri,\"%@\");\n        sentinelAbortFailover(ri);\n    }\n}\n\nvoid sentinelFailoverDetectEnd(sentinelRedisInstance *master) {\n    int not_reconfigured = 0, timeout = 0;\n    dictIterator *di;\n    dictEntry *de;\n    mstime_t elapsed = mstime() - master->failover_state_change_time;\n\n    /* We can't consider failover finished if the promoted slave is\n     * not reachable. */\n    if (master->promoted_slave == NULL ||\n        master->promoted_slave->flags & SRI_S_DOWN) return;\n\n    /* The failover terminates once all the reachable slaves are properly\n     * configured. */\n    di = dictGetIterator(master->slaves);\n    while((de = dictNext(di)) != NULL) {\n        sentinelRedisInstance *slave = dictGetVal(de);\n\n        if (slave->flags & (SRI_PROMOTED|SRI_RECONF_DONE)) continue;\n        if (slave->flags & SRI_S_DOWN) continue;\n        not_reconfigured++;\n    }\n    dictReleaseIterator(di);\n\n    /* Force end of failover on timeout. */\n    if (elapsed > master->failover_timeout) {\n        not_reconfigured = 0;\n        timeout = 1;\n        sentinelEvent(REDIS_WARNING,\"+failover-end-for-timeout\",master,\"%@\");\n    }\n\n    if (not_reconfigured == 0) {\n        sentinelEvent(REDIS_WARNING,\"+failover-end\",master,\"%@\");\n        master->failover_state = SENTINEL_FAILOVER_STATE_UPDATE_CONFIG;\n        master->failover_state_change_time = mstime();\n    }\n\n    /* If I'm the leader it is a good idea to send a best effort SLAVEOF\n     * command to all the slaves still not reconfigured to replicate with\n     * the new master. */\n    if (timeout) {\n        dictIterator *di;\n        dictEntry *de;\n\n        di = dictGetIterator(master->slaves);\n        while((de = dictNext(di)) != NULL) {\n            sentinelRedisInstance *slave = dictGetVal(de);\n            int retval;\n\n            if (slave->flags &\n                (SRI_RECONF_DONE|SRI_RECONF_SENT|SRI_DISCONNECTED)) continue;\n\n            retval = sentinelSendSlaveOf(slave,\n                    master->promoted_slave->addr->ip,\n                    master->promoted_slave->addr->port);\n            if (retval == REDIS_OK) {\n                sentinelEvent(REDIS_NOTICE,\"+slave-reconf-sent-be\",slave,\"%@\");\n                slave->flags |= SRI_RECONF_SENT;\n            }\n        }\n        dictReleaseIterator(di);\n    }\n}\n\n/* Send SLAVE OF <new master address> to all the remaining slaves that\n * still don't appear to have the configuration updated. */\nvoid sentinelFailoverReconfNextSlave(sentinelRedisInstance *master) {\n    dictIterator *di;\n    dictEntry *de;\n    int in_progress = 0;\n\n    di = dictGetIterator(master->slaves);\n    while((de = dictNext(di)) != NULL) {\n        sentinelRedisInstance *slave = dictGetVal(de);\n\n        if (slave->flags & (SRI_RECONF_SENT|SRI_RECONF_INPROG))\n            in_progress++;\n    }\n    dictReleaseIterator(di);\n\n    di = dictGetIterator(master->slaves);\n    while(in_progress < master->parallel_syncs &&\n          (de = dictNext(di)) != NULL)\n    {\n        sentinelRedisInstance *slave = dictGetVal(de);\n        int retval;\n\n        /* Skip the promoted slave, and already configured slaves. */\n        if (slave->flags & (SRI_PROMOTED|SRI_RECONF_DONE)) continue;\n\n        /* If too much time elapsed without the slave moving forward to\n         * the next state, consider it reconfigured even if it is not.\n         * Sentinels will detect the slave as misconfigured and fix its\n         * configuration later. */\n        if ((slave->flags & SRI_RECONF_SENT) &&\n            (mstime() - slave->slave_reconf_sent_time) >\n            SENTINEL_SLAVE_RECONF_TIMEOUT)\n        {\n            sentinelEvent(REDIS_NOTICE,\"-slave-reconf-sent-timeout\",slave,\"%@\");\n            slave->flags &= ~SRI_RECONF_SENT;\n            slave->flags |= SRI_RECONF_DONE;\n        }\n\n        /* Nothing to do for instances that are disconnected or already\n         * in RECONF_SENT state. */\n        if (slave->flags & (SRI_DISCONNECTED|SRI_RECONF_SENT|SRI_RECONF_INPROG))\n            continue;\n\n        /* Send SLAVEOF <new master>. */\n        retval = sentinelSendSlaveOf(slave,\n                master->promoted_slave->addr->ip,\n                master->promoted_slave->addr->port);\n        if (retval == REDIS_OK) {\n            slave->flags |= SRI_RECONF_SENT;\n            slave->slave_reconf_sent_time = mstime();\n            sentinelEvent(REDIS_NOTICE,\"+slave-reconf-sent\",slave,\"%@\");\n            in_progress++;\n        }\n    }\n    dictReleaseIterator(di);\n\n    /* Check if all the slaves are reconfigured and handle timeout. */\n    sentinelFailoverDetectEnd(master);\n}\n\n/* This function is called when the slave is in\n * SENTINEL_FAILOVER_STATE_UPDATE_CONFIG state. In this state we need\n * to remove it from the master table and add the promoted slave instead. */\nvoid sentinelFailoverSwitchToPromotedSlave(sentinelRedisInstance *master) {\n    sentinelRedisInstance *ref = master->promoted_slave ?\n                                 master->promoted_slave : master;\n\n    sentinelEvent(REDIS_WARNING,\"+switch-master\",master,\"%s %s %d %s %d\",\n        master->name, master->addr->ip, master->addr->port,\n        ref->addr->ip, ref->addr->port);\n\n    sentinelResetMasterAndChangeAddress(master,ref->addr->ip,ref->addr->port);\n}\n\nvoid sentinelFailoverStateMachine(sentinelRedisInstance *ri) {\n    redisAssert(ri->flags & SRI_MASTER);\n\n    if (!(ri->flags & SRI_FAILOVER_IN_PROGRESS)) return;\n\n    switch(ri->failover_state) {\n        case SENTINEL_FAILOVER_STATE_WAIT_START:\n            sentinelFailoverWaitStart(ri);\n            break;\n        case SENTINEL_FAILOVER_STATE_SELECT_SLAVE:\n            sentinelFailoverSelectSlave(ri);\n            break;\n        case SENTINEL_FAILOVER_STATE_SEND_SLAVEOF_NOONE:\n            sentinelFailoverSendSlaveOfNoOne(ri);\n            break;\n        case SENTINEL_FAILOVER_STATE_WAIT_PROMOTION:\n            sentinelFailoverWaitPromotion(ri);\n            break;\n        case SENTINEL_FAILOVER_STATE_RECONF_SLAVES:\n            sentinelFailoverReconfNextSlave(ri);\n            break;\n    }\n}\n\n/* Abort a failover in progress:\n *\n * This function can only be called before the promoted slave acknowledged\n * the slave -> master switch. Otherwise the failover can't be aborted and\n * will reach its end (possibly by timeout). */\nvoid sentinelAbortFailover(sentinelRedisInstance *ri) {\n    redisAssert(ri->flags & SRI_FAILOVER_IN_PROGRESS);\n    redisAssert(ri->failover_state <= SENTINEL_FAILOVER_STATE_WAIT_PROMOTION);\n\n    ri->flags &= ~(SRI_FAILOVER_IN_PROGRESS|SRI_FORCE_FAILOVER);\n    ri->failover_state = SENTINEL_FAILOVER_STATE_NONE;\n    ri->failover_state_change_time = mstime();\n    if (ri->promoted_slave) {\n        ri->promoted_slave->flags &= ~SRI_PROMOTED;\n        ri->promoted_slave = NULL;\n    }\n}\n\n/* ======================== SENTINEL timer handler ==========================\n * This is the \"main\" our Sentinel, being sentinel completely non blocking\n * in design. The function is called every second.\n * -------------------------------------------------------------------------- */\n\n/* Perform scheduled operations for the specified Redis instance. */\nvoid sentinelHandleRedisInstance(sentinelRedisInstance *ri) {\n    /* ========== MONITORING HALF ============ */\n    /* Every kind of instance */\n    sentinelReconnectInstance(ri);\n    sentinelSendPeriodicCommands(ri);\n\n    /* ============== ACTING HALF ============= */\n    /* We don't proceed with the acting half if we are in TILT mode.\n     * TILT happens when we find something odd with the time, like a\n     * sudden change in the clock. */\n    if (sentinel.tilt) {\n        if (mstime()-sentinel.tilt_start_time < SENTINEL_TILT_PERIOD) return;\n        sentinel.tilt = 0;\n        sentinelEvent(REDIS_WARNING,\"-tilt\",NULL,\"#tilt mode exited\");\n    }\n\n    /* Every kind of instance */\n    sentinelCheckSubjectivelyDown(ri);\n\n    /* Masters and slaves */\n    if (ri->flags & (SRI_MASTER|SRI_SLAVE)) {\n        /* Nothing so far. */\n    }\n\n    /* Only masters */\n    if (ri->flags & SRI_MASTER) {\n        sentinelCheckObjectivelyDown(ri);\n        if (sentinelStartFailoverIfNeeded(ri))\n            sentinelAskMasterStateToOtherSentinels(ri,SENTINEL_ASK_FORCED);\n        sentinelFailoverStateMachine(ri);\n        sentinelAskMasterStateToOtherSentinels(ri,SENTINEL_NO_FLAGS);\n    }\n}\n\n/* Perform scheduled operations for all the instances in the dictionary.\n * Recursively call the function against dictionaries of slaves. */\nvoid sentinelHandleDictOfRedisInstances(dict *instances) {\n    dictIterator *di;\n    dictEntry *de;\n    sentinelRedisInstance *switch_to_promoted = NULL;\n\n    /* There are a number of things we need to perform against every master. */\n    di = dictGetIterator(instances);\n    while((de = dictNext(di)) != NULL) {\n        sentinelRedisInstance *ri = dictGetVal(de);\n\n        sentinelHandleRedisInstance(ri);\n        if (ri->flags & SRI_MASTER) {\n            sentinelHandleDictOfRedisInstances(ri->slaves);\n            sentinelHandleDictOfRedisInstances(ri->sentinels);\n            if (ri->failover_state == SENTINEL_FAILOVER_STATE_UPDATE_CONFIG) {\n                switch_to_promoted = ri;\n            }\n        }\n    }\n    if (switch_to_promoted)\n        sentinelFailoverSwitchToPromotedSlave(switch_to_promoted);\n    dictReleaseIterator(di);\n}\n\n/* This function checks if we need to enter the TITL mode.\n *\n * The TILT mode is entered if we detect that between two invocations of the\n * timer interrupt, a negative amount of time, or too much time has passed.\n * Note that we expect that more or less just 100 milliseconds will pass\n * if everything is fine. However we'll see a negative number or a\n * difference bigger than SENTINEL_TILT_TRIGGER milliseconds if one of the\n * following conditions happen:\n *\n * 1) The Sentiel process for some time is blocked, for every kind of\n * random reason: the load is huge, the computer was frozen for some time\n * in I/O or alike, the process was stopped by a signal. Everything.\n * 2) The system clock was altered significantly.\n *\n * Under both this conditions we'll see everything as timed out and failing\n * without good reasons. Instead we enter the TILT mode and wait\n * for SENTINEL_TILT_PERIOD to elapse before starting to act again.\n *\n * During TILT time we still collect information, we just do not act. */\nvoid sentinelCheckTiltCondition(void) {\n    mstime_t now = mstime();\n    mstime_t delta = now - sentinel.previous_time;\n\n    if (delta < 0 || delta > SENTINEL_TILT_TRIGGER) {\n        sentinel.tilt = 1;\n        sentinel.tilt_start_time = mstime();\n        sentinelEvent(REDIS_WARNING,\"+tilt\",NULL,\"#tilt mode entered\");\n    }\n    sentinel.previous_time = mstime();\n}\n\nvoid sentinelTimer(void) {\n    sentinelCheckTiltCondition();\n    sentinelHandleDictOfRedisInstances(sentinel.masters);\n    sentinelRunPendingScripts();\n    sentinelCollectTerminatedScripts();\n    sentinelKillTimedoutScripts();\n\n    /* We continuously change the frequency of the Redis \"timer interrupt\"\n     * in order to desynchronize every Sentinel from every other.\n     * This non-determinism avoids that Sentinels started at the same time\n     * exactly continue to stay synchronized asking to be voted at the\n     * same time again and again (resulting in nobody likely winning the\n     * election because of split brain voting). */\n    server.hz = REDIS_DEFAULT_HZ + rand() % REDIS_DEFAULT_HZ;\n}\n\n"
  },
  {
    "path": "extern/deprecated/redis-2.8.21/src/setproctitle.c",
    "content": "/* ==========================================================================\n * setproctitle.c - Linux/Darwin setproctitle.\n * --------------------------------------------------------------------------\n * Copyright (C) 2010  William Ahern\n * Copyright (C) 2013  Salvatore Sanfilippo\n * Copyright (C) 2013  Stam He\n *\n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the\n * \"Software\"), to deal in the Software without restriction, including\n * without limitation the rights to use, copy, modify, merge, publish,\n * distribute, sublicense, and/or sell copies of the Software, and to permit\n * persons to whom the Software is furnished to do so, subject to the\n * following conditions:\n *\n * The above copyright notice and this permission notice shall be included\n * in all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS\n * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\n * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN\n * NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,\n * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR\n * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE\n * USE OR OTHER DEALINGS IN THE SOFTWARE.\n * ==========================================================================\n */\n#ifndef _GNU_SOURCE\n#define _GNU_SOURCE\n#endif\n\n#include <stddef.h>\t/* NULL size_t */\n#include <stdarg.h>\t/* va_list va_start va_end */\n#include <stdlib.h>\t/* malloc(3) setenv(3) clearenv(3) setproctitle(3) getprogname(3) */\n#include <stdio.h>\t/* vsnprintf(3) snprintf(3) */\n\n#include <string.h>\t/* strlen(3) strchr(3) strdup(3) memset(3) memcpy(3) */\n\n#include <errno.h>\t/* errno program_invocation_name program_invocation_short_name */\n\n#if !defined(HAVE_SETPROCTITLE)\n#define HAVE_SETPROCTITLE (defined __NetBSD__ || defined __FreeBSD__ || defined __OpenBSD__)\n#endif\n\n\n#if !HAVE_SETPROCTITLE\n#if (defined __linux || defined __APPLE__)\n\nextern char **environ;\n\nstatic struct {\n\t/* original value */\n\tconst char *arg0;\n\n\t/* title space available */\n\tchar *base, *end;\n\n\t /* pointer to original nul character within base */\n\tchar *nul;\n\n\t_Bool reset;\n\tint error;\n} SPT;\n\n\n#ifndef SPT_MIN\n#define SPT_MIN(a, b) (((a) < (b))? (a) : (b))\n#endif\n\nstatic inline size_t spt_min(size_t a, size_t b) {\n\treturn SPT_MIN(a, b);\n} /* spt_min() */\n\n\n/*\n * For discussion on the portability of the various methods, see\n * http://lists.freebsd.org/pipermail/freebsd-stable/2008-June/043136.html\n */\nstatic int spt_clearenv(void) {\n#if __GLIBC__\n\tclearenv();\n\n\treturn 0;\n#else\n\textern char **environ;\n\tstatic char **tmp;\n\n\tif (!(tmp = malloc(sizeof *tmp)))\n\t\treturn errno;\n\n\ttmp[0]  = NULL;\n\tenviron = tmp;\n\n\treturn 0;\n#endif\n} /* spt_clearenv() */\n\n\nstatic int spt_copyenv(char *oldenv[]) {\n\textern char **environ;\n\tchar *eq;\n\tint i, error;\n\n\tif (environ != oldenv)\n\t\treturn 0;\n\n\tif ((error = spt_clearenv()))\n\t\tgoto error;\n\n\tfor (i = 0; oldenv[i]; i++) {\n\t\tif (!(eq = strchr(oldenv[i], '=')))\n\t\t\tcontinue;\n\n\t\t*eq = '\\0';\n\t\terror = (0 != setenv(oldenv[i], eq + 1, 1))? errno : 0;\n\t\t*eq = '=';\n\n\t\tif (error)\n\t\t\tgoto error;\n\t}\n\n\treturn 0;\nerror:\n\tenviron = oldenv;\n\n\treturn error;\n} /* spt_copyenv() */\n\n\nstatic int spt_copyargs(int argc, char *argv[]) {\n\tchar *tmp;\n\tint i;\n\n\tfor (i = 1; i < argc || (i >= argc && argv[i]); i++) {\n\t\tif (!argv[i])\n\t\t\tcontinue;\n\n\t\tif (!(tmp = strdup(argv[i])))\n\t\t\treturn errno;\n\n\t\targv[i] = tmp;\n\t}\n\n\treturn 0;\n} /* spt_copyargs() */\n\n\nvoid spt_init(int argc, char *argv[]) {\n        char **envp = environ;\n\tchar *base, *end, *nul, *tmp;\n\tint i, error;\n\n\tif (!(base = argv[0]))\n\t\treturn;\n\n\tnul = &base[strlen(base)];\n\tend = nul + 1;\n\n\tfor (i = 0; i < argc || (i >= argc && argv[i]); i++) {\n\t\tif (!argv[i] || argv[i] < end)\n\t\t\tcontinue;\n\n\t\tend = argv[i] + strlen(argv[i]) + 1;\n\t}\n\n\tfor (i = 0; envp[i]; i++) {\n\t\tif (envp[i] < end)\n\t\t\tcontinue;\n\n\t\tend = envp[i] + strlen(envp[i]) + 1;\n\t}\n\n\tif (!(SPT.arg0 = strdup(argv[0])))\n\t\tgoto syerr;\n\n#if __GLIBC__\n\tif (!(tmp = strdup(program_invocation_name)))\n\t\tgoto syerr;\n\n\tprogram_invocation_name = tmp;\n\n\tif (!(tmp = strdup(program_invocation_short_name)))\n\t\tgoto syerr;\n\n\tprogram_invocation_short_name = tmp;\n#elif __APPLE__\n\tif (!(tmp = strdup(getprogname())))\n\t\tgoto syerr;\n\n\tsetprogname(tmp);\n#endif\n\n\n\tif ((error = spt_copyenv(envp)))\n\t\tgoto error;\n\n\tif ((error = spt_copyargs(argc, argv)))\n\t\tgoto error;\n\n\tSPT.nul  = nul;\n\tSPT.base = base;\n\tSPT.end  = end;\n\n\treturn;\nsyerr:\n\terror = errno;\nerror:\n\tSPT.error = error;\n} /* spt_init() */\n\n\n#ifndef SPT_MAXTITLE\n#define SPT_MAXTITLE 255\n#endif\n\nvoid setproctitle(const char *fmt, ...) {\n\tchar buf[SPT_MAXTITLE + 1]; /* use buffer in case argv[0] is passed */\n\tva_list ap;\n\tchar *nul;\n\tint len, error;\n\n\tif (!SPT.base)\n\t\treturn;\n\n\tif (fmt) {\n\t\tva_start(ap, fmt);\n\t\tlen = vsnprintf(buf, sizeof buf, fmt, ap);\n\t\tva_end(ap);\n\t} else {\n\t\tlen = snprintf(buf, sizeof buf, \"%s\", SPT.arg0);\n\t}\n\n\tif (len <= 0)\n\t\t{ error = errno; goto error; }\n\n\tif (!SPT.reset) {\n\t\tmemset(SPT.base, 0, SPT.end - SPT.base);\n\t\tSPT.reset = 1;\n\t} else {\n\t\tmemset(SPT.base, 0, spt_min(sizeof buf, SPT.end - SPT.base));\n\t}\n\n\tlen = spt_min(len, spt_min(sizeof buf, SPT.end - SPT.base) - 1);\n\tmemcpy(SPT.base, buf, len);\n\tnul = &SPT.base[len];\n\n\tif (nul < SPT.nul) {\n\t\t*SPT.nul = '.';\n\t} else if (nul == SPT.nul && &nul[1] < SPT.end) {\n\t\t*SPT.nul = ' ';\n\t\t*++nul = '\\0';\n\t}\n\n\treturn;\nerror:\n\tSPT.error = error;\n} /* setproctitle() */\n\n\n#endif /* __linux || __APPLE__ */\n#endif /* !HAVE_SETPROCTITLE */\n"
  },
  {
    "path": "extern/deprecated/redis-2.8.21/src/sha1.c",
    "content": "\n/* from valgrind tests */\n\n/* ================ sha1.c ================ */\n/*\nSHA-1 in C\nBy Steve Reid <steve@edmweb.com>\n100% Public Domain\n\nTest Vectors (from FIPS PUB 180-1)\n\"abc\"\n  A9993E36 4706816A BA3E2571 7850C26C 9CD0D89D\n\"abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq\"\n  84983E44 1C3BD26E BAAE4AA1 F95129E5 E54670F1\nA million repetitions of \"a\"\n  34AA973C D4C4DAA4 F61EEB2B DBAD2731 6534016F\n*/\n\n/* #define LITTLE_ENDIAN * This should be #define'd already, if true. */\n/* #define SHA1HANDSOFF * Copies data before messing with it. */\n\n#define SHA1HANDSOFF\n\n#include <stdio.h>\n#include <string.h>\n#include <stdint.h>\n#include \"solarisfixes.h\"\n#include \"sha1.h\"\n#include \"config.h\"\n\n#define rol(value, bits) (((value) << (bits)) | ((value) >> (32 - (bits))))\n\n/* blk0() and blk() perform the initial expand. */\n/* I got the idea of expanding during the round function from SSLeay */\n#if BYTE_ORDER == LITTLE_ENDIAN\n#define blk0(i) (block->l[i] = (rol(block->l[i],24)&0xFF00FF00) \\\n    |(rol(block->l[i],8)&0x00FF00FF))\n#elif BYTE_ORDER == BIG_ENDIAN\n#define blk0(i) block->l[i]\n#else\n#error \"Endianness not defined!\"\n#endif\n#define blk(i) (block->l[i&15] = rol(block->l[(i+13)&15]^block->l[(i+8)&15] \\\n    ^block->l[(i+2)&15]^block->l[i&15],1))\n\n/* (R0+R1), R2, R3, R4 are the different operations used in SHA1 */\n#define R0(v,w,x,y,z,i) z+=((w&(x^y))^y)+blk0(i)+0x5A827999+rol(v,5);w=rol(w,30);\n#define R1(v,w,x,y,z,i) z+=((w&(x^y))^y)+blk(i)+0x5A827999+rol(v,5);w=rol(w,30);\n#define R2(v,w,x,y,z,i) z+=(w^x^y)+blk(i)+0x6ED9EBA1+rol(v,5);w=rol(w,30);\n#define R3(v,w,x,y,z,i) z+=(((w|x)&y)|(w&x))+blk(i)+0x8F1BBCDC+rol(v,5);w=rol(w,30);\n#define R4(v,w,x,y,z,i) z+=(w^x^y)+blk(i)+0xCA62C1D6+rol(v,5);w=rol(w,30);\n\n\n/* Hash a single 512-bit block. This is the core of the algorithm. */\n\nvoid SHA1Transform(uint32_t state[5], const unsigned char buffer[64])\n{\n    uint32_t a, b, c, d, e;\n    typedef union {\n        unsigned char c[64];\n        uint32_t l[16];\n    } CHAR64LONG16;\n#ifdef SHA1HANDSOFF\n    CHAR64LONG16 block[1];  /* use array to appear as a pointer */\n    memcpy(block, buffer, 64);\n#else\n    /* The following had better never be used because it causes the\n     * pointer-to-const buffer to be cast into a pointer to non-const.\n     * And the result is written through.  I threw a \"const\" in, hoping\n     * this will cause a diagnostic.\n     */\n    CHAR64LONG16* block = (const CHAR64LONG16*)buffer;\n#endif\n    /* Copy context->state[] to working vars */\n    a = state[0];\n    b = state[1];\n    c = state[2];\n    d = state[3];\n    e = state[4];\n    /* 4 rounds of 20 operations each. Loop unrolled. */\n    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);\n    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);\n    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);\n    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);\n    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);\n    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);\n    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);\n    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);\n    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);\n    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);\n    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);\n    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);\n    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);\n    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);\n    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);\n    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);\n    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);\n    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);\n    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);\n    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);\n    /* Add the working vars back into context.state[] */\n    state[0] += a;\n    state[1] += b;\n    state[2] += c;\n    state[3] += d;\n    state[4] += e;\n    /* Wipe variables */\n    a = b = c = d = e = 0;\n#ifdef SHA1HANDSOFF\n    memset(block, '\\0', sizeof(block));\n#endif\n}\n\n\n/* SHA1Init - Initialize new context */\n\nvoid SHA1Init(SHA1_CTX* context)\n{\n    /* SHA1 initialization constants */\n    context->state[0] = 0x67452301;\n    context->state[1] = 0xEFCDAB89;\n    context->state[2] = 0x98BADCFE;\n    context->state[3] = 0x10325476;\n    context->state[4] = 0xC3D2E1F0;\n    context->count[0] = context->count[1] = 0;\n}\n\n\n/* Run your data through this. */\n\nvoid SHA1Update(SHA1_CTX* context, const unsigned char* data, uint32_t len)\n{\n    uint32_t i, j;\n\n    j = context->count[0];\n    if ((context->count[0] += len << 3) < j)\n        context->count[1]++;\n    context->count[1] += (len>>29);\n    j = (j >> 3) & 63;\n    if ((j + len) > 63) {\n        memcpy(&context->buffer[j], data, (i = 64-j));\n        SHA1Transform(context->state, context->buffer);\n        for ( ; i + 63 < len; i += 64) {\n            SHA1Transform(context->state, &data[i]);\n        }\n        j = 0;\n    }\n    else i = 0;\n    memcpy(&context->buffer[j], &data[i], len - i);\n}\n\n\n/* Add padding and return the message digest. */\n\nvoid SHA1Final(unsigned char digest[20], SHA1_CTX* context)\n{\n    unsigned i;\n    unsigned char finalcount[8];\n    unsigned char c;\n\n#if 0\t/* untested \"improvement\" by DHR */\n    /* Convert context->count to a sequence of bytes\n     * in finalcount.  Second element first, but\n     * big-endian order within element.\n     * But we do it all backwards.\n     */\n    unsigned char *fcp = &finalcount[8];\n\n    for (i = 0; i < 2; i++)\n       {\n        uint32_t t = context->count[i];\n        int j;\n\n        for (j = 0; j < 4; t >>= 8, j++)\n\t          *--fcp = (unsigned char) t;\n    }\n#else\n    for (i = 0; i < 8; i++) {\n        finalcount[i] = (unsigned char)((context->count[(i >= 4 ? 0 : 1)]\n         >> ((3-(i & 3)) * 8) ) & 255);  /* Endian independent */\n    }\n#endif\n    c = 0200;\n    SHA1Update(context, &c, 1);\n    while ((context->count[0] & 504) != 448) {\n\tc = 0000;\n        SHA1Update(context, &c, 1);\n    }\n    SHA1Update(context, finalcount, 8);  /* Should cause a SHA1Transform() */\n    for (i = 0; i < 20; i++) {\n        digest[i] = (unsigned char)\n         ((context->state[i>>2] >> ((3-(i & 3)) * 8) ) & 255);\n    }\n    /* Wipe variables */\n    memset(context, '\\0', sizeof(*context));\n    memset(&finalcount, '\\0', sizeof(finalcount));\n}\n/* ================ end of sha1.c ================ */\n\n#if 0\n#define BUFSIZE 4096\n\nint\nmain(int argc, char **argv)\n{\n    SHA1_CTX ctx;\n    unsigned char hash[20], buf[BUFSIZE];\n    int i;\n\n    for(i=0;i<BUFSIZE;i++)\n        buf[i] = i;\n\n    SHA1Init(&ctx);\n    for(i=0;i<1000;i++)\n        SHA1Update(&ctx, buf, BUFSIZE);\n    SHA1Final(hash, &ctx);\n\n    printf(\"SHA1=\");\n    for(i=0;i<20;i++)\n        printf(\"%02x\", hash[i]);\n    printf(\"\\n\");\n    return 0;\n}\n\n#endif\n\n"
  },
  {
    "path": "extern/deprecated/redis-2.8.21/src/sha1.h",
    "content": "/* ================ sha1.h ================ */\n/*\nSHA-1 in C\nBy Steve Reid <steve@edmweb.com>\n100% Public Domain\n*/\n\ntypedef struct {\n    uint32_t state[5];\n    uint32_t count[2];\n    unsigned char buffer[64];\n} SHA1_CTX;\n\nvoid SHA1Transform(uint32_t state[5], const unsigned char buffer[64]);\nvoid SHA1Init(SHA1_CTX* context);\nvoid SHA1Update(SHA1_CTX* context, const unsigned char* data, uint32_t len);\nvoid SHA1Final(unsigned char digest[20], SHA1_CTX* context);\n"
  },
  {
    "path": "extern/deprecated/redis-2.8.21/src/slots.c",
    "content": "#include \"redis.h\"\n\nextern void createDumpPayload(rio *payload, robj *o);\nextern int verifyDumpPayload(unsigned char *p, size_t len);\n\nstatic void *\nslots_tag(const sds s, int *plen) {\n    int i, j, n = sdslen(s);\n    for (i = 0; i < n && s[i] != '{'; i ++) {}\n    if (i == n) {\n        return NULL;\n    }\n    i ++;\n    for (j = i; j < n && s[j] != '}'; j ++) {}\n    if (j == n) {\n        return NULL;\n    }\n    if (plen != NULL) {\n        *plen = j - i;\n    }\n    return s + i;\n}\n\nint\nslots_num(const sds s, uint32_t *pcrc, int *phastag) {\n    int taglen;\n    int hastag = 0;\n    void *tag = slots_tag(s, &taglen);\n    if (tag == NULL) {\n        tag = s, taglen = sdslen(s);\n    } else {\n        hastag = 1;\n    }\n    uint32_t crc = crc32_checksum(tag, taglen);\n    if (pcrc != NULL) {\n        *pcrc = crc;\n    }\n    if (phastag != NULL) {\n        *phastag = hastag;\n    }\n    return crc & HASH_SLOTS_MASK;\n}\n\nstatic int\nparse_int(redisClient *c, robj *obj, int *p) {\n    long v;\n    if (getLongFromObjectOrReply(c, obj, &v, NULL) != REDIS_OK) {\n        return -1;\n    }\n    if (v < INT_MIN || v > INT_MAX) {\n        addReplyError(c, \"value is out of range\");\n        return -1;\n    } else {\n        *p = v;\n        return 0;\n    }\n}\n\nstatic int\nparse_timeout(redisClient *c, robj *obj, int *p) {\n    int v;\n    if (parse_int(c, obj, &v) != 0) {\n        return -1;\n    }\n    if (v < 0) {\n        addReplyErrorFormat(c, \"invalid timeout = %d\", v);\n        return -1;\n    }\n    *p = (v == 0) ? 100 : v;\n    return 0;\n}\n\nstatic int\nparse_slot(redisClient *c, robj *obj, int *p) {\n    int v;\n    if (parse_int(c, obj, &v) != 0) {\n        return -1;\n    }\n    if (v < 0 || v >= HASH_SLOTS_SIZE) {\n        addReplyErrorFormat(c, \"invalid slot number = %d\", v);\n        return -1;\n    }\n    *p = v;\n    return 0;\n}\n\n/* *\n * slotshashkey [key1 key2...]\n * */\nvoid\nslotshashkeyCommand(redisClient *c) {\n    int i;\n    addReplyMultiBulkLen(c, c->argc - 1);\n    for (i = 1; i < c->argc; i ++) {\n        robj *key = c->argv[i];\n        addReplyLongLong(c, slots_num(key->ptr, NULL, NULL));\n    }\n}\n\n/* *\n * slotsinfo [start] [count]\n * */\nvoid\nslotsinfoCommand(redisClient *c) {\n    int slots_slot[HASH_SLOTS_SIZE];\n    int slots_size[HASH_SLOTS_SIZE];\n    int n = 0, beg = 0, end = HASH_SLOTS_SIZE;\n    if (c->argc >= 2) {\n        if (parse_slot(c, c->argv[1], &beg) != 0) {\n            return;\n        }\n    }\n    if (c->argc >= 3) {\n        int v;\n        if (parse_int(c, c->argv[2], &v) != 0) {\n            return;\n        }\n        if (v < 0) {\n            addReplyErrorFormat(c, \"invalid slot count = %d\", v);\n            return;\n        }\n        if (beg + v < end) {\n            end = beg + v;\n        }\n    }\n    if (c->argc >= 4) {\n        addReplyErrorFormat(c, \"wrong number of arguments for 'slotsinfo' command\");\n        return;\n    }\n    int i;\n    for (i = beg; i < end; i ++) {\n        int s = dictSize(c->db->hash_slots[i]);\n        if (s == 0) {\n            continue;\n        }\n        slots_slot[n] = i;\n        slots_size[n] = s;\n        n ++;\n    }\n    addReplyMultiBulkLen(c, n);\n    for (i = 0; i < n; i ++) {\n        addReplyMultiBulkLen(c, 2);\n        addReplyLongLong(c, slots_slot[i]);\n        addReplyLongLong(c, slots_size[i]);\n    }\n}\n\ntypedef struct {\n    int fd;\n    int db;\n    int authorized;\n    time_t lasttime;\n} slotsmgrt_sockfd;\n\nstatic slotsmgrt_sockfd *\nslotsmgrt_get_sockfd(redisClient *c, sds host, sds port, int timeout) {\n    sds name = sdsempty();\n    name = sdscatlen(name, host, sdslen(host));\n    name = sdscatlen(name, \":\", 1);\n    name = sdscatlen(name, port, sdslen(port));\n\n    slotsmgrt_sockfd *pfd = dictFetchValue(server.slotsmgrt_cached_sockfds, name);\n    if (pfd != NULL) {\n        sdsfree(name);\n        pfd->lasttime = server.unixtime;\n        return pfd;\n    }\n\n    int fd = anetTcpNonBlockConnect(server.neterr, host, atoi(port));\n    if (fd == -1) {\n        redisLog(REDIS_WARNING, \"slotsmgrt: connect to target %s:%s, error = '%s'\",\n                host, port, server.neterr);\n        sdsfree(name);\n        addReplyErrorFormat(c,\"Can't connect to target node: %s\", server.neterr);\n        return NULL;\n    }\n    anetEnableTcpNoDelay(server.neterr, fd);\n    if ((aeWait(fd, AE_WRITABLE, timeout) & AE_WRITABLE) == 0) {\n        redisLog(REDIS_WARNING, \"slotsmgrt: connect to target %s:%s, aewait error = '%s'\",\n                host, port, server.neterr);\n        sdsfree(name);\n        close(fd);\n        addReplySds(c, sdsnew(\"-IOERR error or timeout connecting to the client\\r\\n\"));\n        return NULL;\n    }\n    redisLog(REDIS_WARNING, \"slotsmgrt: connect to target %s:%s\", host, port);\n\n    pfd = zmalloc(sizeof(*pfd));\n    pfd->fd = fd;\n    pfd->db = -1;\n    pfd->authorized = (server.requirepass == NULL) ? 1 : 0;\n    pfd->lasttime = server.unixtime;\n    dictAdd(server.slotsmgrt_cached_sockfds, name, pfd);\n    return pfd;\n}\n\nstatic void\nslotsmgrt_close_socket(sds host, sds port) {\n    sds name = sdsempty();\n    name = sdscatlen(name, host, sdslen(host));\n    name = sdscatlen(name, \":\", 1);\n    name = sdscatlen(name, port, sdslen(port));\n\n    slotsmgrt_sockfd *pfd = dictFetchValue(server.slotsmgrt_cached_sockfds, name);\n    if (pfd == NULL) {\n        redisLog(REDIS_WARNING, \"slotsmgrt: close target %s:%s again\", host, port);\n        sdsfree(name);\n        return;\n    } else {\n        redisLog(REDIS_WARNING, \"slotsmgrt: close target %s:%s\", host, port);\n    }\n    dictDelete(server.slotsmgrt_cached_sockfds, name);\n    close(pfd->fd);\n    zfree(pfd);\n    sdsfree(name);\n}\n\nvoid\nslotsmgrt_cleanup() {\n    dictIterator *di = dictGetSafeIterator(server.slotsmgrt_cached_sockfds);\n    dictEntry *de;\n    while((de = dictNext(di)) != NULL) {\n        slotsmgrt_sockfd *pfd = dictGetVal(de);\n        if ((server.unixtime - pfd->lasttime) > 15) {\n            redisLog(REDIS_WARNING, \"slotsmgrt: timeout target %s, lasttime = %ld, now = %ld\",\n                   (char *)dictGetKey(de), pfd->lasttime, server.unixtime);\n            dictDelete(server.slotsmgrt_cached_sockfds, dictGetKey(de));\n            close(pfd->fd);\n            zfree(pfd);\n        }\n    }\n    dictReleaseIterator(di);\n}\n\nstatic int\nslotsmgrt(redisClient *c, sds host, sds port, slotsmgrt_sockfd *pfd, int db, int timeout, robj *keys[], robj *vals[], int n) {\n    rio cmd;\n    rioInitWithBuffer(&cmd, sdsempty());\n\n    int needauth = 0;\n    if (pfd->authorized == 0 && server.requirepass != NULL) {\n        needauth = 1;\n        redisAssertWithInfo(c, NULL, rioWriteBulkCount(&cmd, '*', 2));\n        redisAssertWithInfo(c, NULL, rioWriteBulkString(&cmd, \"AUTH\", 4));\n        redisAssertWithInfo(c, NULL, rioWriteBulkString(&cmd, server.requirepass, strlen(server.requirepass)));\n    }\n\n    int selectdb = 0;\n    if (pfd->db != db) {\n        selectdb = 1;\n        redisAssertWithInfo(c, NULL, rioWriteBulkCount(&cmd, '*', 2));\n        redisAssertWithInfo(c, NULL, rioWriteBulkString(&cmd, \"SELECT\", 6));\n        redisAssertWithInfo(c, NULL, rioWriteBulkLongLong(&cmd, db));\n    }\n\n    redisAssertWithInfo(c, NULL, rioWriteBulkCount(&cmd, '*', 1 + 3 * n));\n    redisAssertWithInfo(c, NULL, rioWriteBulkString(&cmd, \"SLOTSRESTORE\", 12));\n\n    sds onekey = NULL;\n    for (int i = 0; i < n; i ++) {\n        robj *key = keys[i], *val = vals[i];\n        long long ttl = 0, expireat = getExpire(c->db, key);\n        if (expireat != -1) {\n            ttl = expireat - mstime();\n            if (ttl < 1) {\n                ttl = 1;\n            }\n        }\n        sds skey = key->ptr;\n        redisAssertWithInfo(c, NULL, rioWriteBulkString(&cmd, skey, sdslen(skey)));\n        redisAssertWithInfo(c, NULL, rioWriteBulkLongLong(&cmd, ttl));\n        do {\n            rio pld;\n            createDumpPayload(&pld, val);\n            sds buf = pld.io.buffer.ptr;\n            redisAssertWithInfo(c, NULL, rioWriteBulkString(&cmd, buf, sdslen(buf)));\n            sdsfree(buf);\n        } while (0);\n        if (onekey == NULL) {\n            onekey = skey;\n        }\n    }\n\n    do {\n        sds buf = cmd.io.buffer.ptr;\n        size_t pos = 0, towrite;\n        int nwritten = 0;\n        while ((towrite = sdslen(buf) - pos) > 0) {\n            towrite = (towrite > (64 * 1024) ? (64 * 1024) : towrite);\n            nwritten = syncWrite(pfd->fd, buf + pos, towrite, timeout);\n            if (nwritten != (signed)towrite) {\n                redisLog(REDIS_WARNING, \"slotsmgrt: writing to target %s:%s, error '%s', \"\n                        \"nkeys = %d, onekey = '%s', cmd.len = %ld, pos = %ld, towrite = %ld\",\n                        host, port, server.neterr, n, onekey, sdslen(buf), pos, towrite);\n                addReplySds(c, sdsnew(\"-IOERR error or timeout writing to target\\r\\n\"));\n                sdsfree(buf);\n                return -1;\n            }\n            pos += nwritten;\n        }\n        sdsfree(buf);\n    } while (0);\n\n    do {\n        char buf[1024];\n        if (needauth) {\n            if (syncReadLine(pfd->fd, buf, sizeof(buf), timeout) <= 0) {\n                redisLog(REDIS_WARNING, \"slotsmgrt: auth failed, reading from target %s:%s: nkeys = %d, onekey = '%s', error = '%s'\",\n                        host, port, n, onekey, server.neterr);\n                addReplySds(c, sdsnew(\"-IOERR error or timeout reading from target\\r\\n\"));\n                return -1;\n            }\n            if (buf[0] != '+') {\n                redisLog(REDIS_WARNING, \"slotsmgrt: auth failed, reading from target %s:%s: nkeys = %d, onekey = '%s', response = '%s'\",\n                        host, port, n, onekey, buf);\n                addReplyError(c, \"error on slotsrestore, auth failed\");\n                return -1;\n            }\n            pfd->authorized = 1;\n        }\n\n        if (selectdb) {\n            if (syncReadLine(pfd->fd, buf, sizeof(buf), timeout) <= 0) {\n                redisLog(REDIS_WARNING, \"slotsmgrt: select failed, reading from target %s:%s: nkeys = %d, onekey = '%s', error = '%s'\",\n                        host, port, n, onekey, server.neterr);\n                addReplySds(c, sdsnew(\"-IOERR error or timeout reading from target\\r\\n\"));\n                return -1;\n            }\n            if (buf[0] != '+') {\n                redisLog(REDIS_WARNING, \"slotsmgrt: select failed, reading from target %s:%s: nkeys = %d, onekey = '%s', response = '%s'\",\n                        host, port, n, onekey, buf);\n                addReplyError(c, \"error on slotsrestore, select failed\");\n                return -1;\n            }\n            pfd->db = db;\n        }\n\n        if (syncReadLine(pfd->fd, buf, sizeof(buf), timeout) <= 0) {\n            redisLog(REDIS_WARNING, \"slotsmgrt: migration failed, reading from target %s:%s: nkeys = %d, onekey = '%s', error = '%s'\",\n                    host, port, n, onekey, server.neterr);\n            addReplySds(c, sdsnew(\"-IOERR error or timeout reading from target\\r\\n\"));\n            return -1;\n        }\n        if (buf[0] == '-') {\n            redisLog(REDIS_WARNING, \"slotsmgrt: migration failed, reading from target %s:%s: nkeys = %d, onekey = '%s', response = '%s'\",\n                    host, port, n, onekey, buf);\n            addReplyError(c, \"error on slotsrestore, migration failed\");\n            return -1;\n        }\n    } while (0);\n\n    pfd->lasttime = server.unixtime;\n\n    redisLog(REDIS_VERBOSE, \"slotsmgrt: migrate to %s:%s, nkeys = %d, onekey = '%s'\", host, port, n, onekey);\n    return 0;\n}\n\nstatic void\nslotsremove(redisClient *c, robj **keys, int n, int rewrite) {\n    for (int i = 0; i < n; i ++) {\n        dbDelete(c->db, keys[i]);\n        signalModifiedKey(c->db, keys[i]);\n        server.dirty ++;\n    }\n    if (!rewrite) {\n        return;\n    }\n    for (int i = 0; i < n; i ++) {\n        incrRefCount(keys[i]);\n    }\n    for (int i = 0; i < c->argc; i ++) {\n        decrRefCount(c->argv[i]);\n    }\n    zfree(c->argv);\n    c->argc = n + 1;\n    c->argv = zmalloc(sizeof(robj *) * c->argc);\n    c->argv[0] = createStringObject(\"DEL\", 3);\n    for (int i = 0; i < n; i ++) {\n        c->argv[i + 1] = keys[i];\n    }\n    c->cmd = lookupCommandOrOriginal(c->argv[0]->ptr);\n    redisAssertWithInfo(c, NULL, c->cmd != NULL);\n}\n\n/* *\n * do migrate a key-value for slotsmgrt/slotsmgrtone commands\n * return value:\n *    -1 - error happens\n *   >=0 - # of success migration (0 or 1)\n * */\nstatic int\nslotsmgrtone_command(redisClient *c, sds host, sds port, int timeout, robj *key) {\n    slotsmgrt_sockfd *pfd = slotsmgrt_get_sockfd(c, host, port, timeout);\n    if (pfd == NULL) {\n        return -1;\n    }\n\n    robj *val = lookupKeyWrite(c->db, key);\n    if (val == NULL) {\n        return 0;\n    }\n    robj *keys[] = {key};\n    robj *vals[] = {val};\n    if (slotsmgrt(c, host, port, pfd, c->db->id, timeout, keys, vals, 1) != 0) {\n        slotsmgrt_close_socket(host, port);\n        return -1;\n    }\n    slotsremove(c, keys, 1, 1);\n    return 1;\n}\n\n/* *\n * slotsmgrtslot host port timeout slot\n * */\nvoid\nslotsmgrtslotCommand(redisClient *c) {\n    sds host = c->argv[1]->ptr;\n    sds port = c->argv[2]->ptr;\n    int timeout, slot;\n    if (parse_timeout(c, c->argv[3], &timeout) != 0) {\n        return;\n    }\n    if (parse_slot(c, c->argv[4], &slot) != 0) {\n        return;\n    }\n\n    dict *d = c->db->hash_slots[slot];\n    int succ = 0;\n    do {\n        const dictEntry *de = dictGetRandomKey(d);\n        if (de == NULL) {\n            break;\n        }\n        sds skey = dictGetKey(de);\n        robj *key = createStringObject(skey, sdslen(skey));\n        succ = slotsmgrtone_command(c, host, port, timeout, key);\n        decrRefCount(key);\n        if (succ < 0) {\n            return;\n        }\n    } while (0);\n    addReplyMultiBulkLen(c, 2);\n    addReplyLongLong(c, succ);\n    addReplyLongLong(c, dictSize(d));\n}\n\n/* *\n * slotsmgrtone host port timeout key\n * */\nvoid\nslotsmgrtoneCommand(redisClient *c) {\n    sds host = c->argv[1]->ptr;\n    sds port = c->argv[2]->ptr;\n    int timeout;\n    if (parse_timeout(c, c->argv[3], &timeout) != 0) {\n        return;\n    }\n\n    robj *key = c->argv[4];\n    int succ = slotsmgrtone_command(c, host, port, timeout, key);\n    if (succ < 0) {\n        return;\n    }\n    addReplyLongLong(c, succ);\n}\n\nstatic void\nslotsScanSdsKeyCallback(void *l, const dictEntry *de) {\n    sds skey = dictGetKey(de);\n    robj *key = createStringObject(skey, sdslen(skey));\n    listAddNodeTail((list *)l, key);\n}\n\n/* *\n * slotsdel slot1 [slot2 ...]\n * */\nvoid\nslotsdelCommand(redisClient *c) {\n    int slots_slot[HASH_SLOTS_SIZE];\n    int n = 0;\n    if (c->argc <= 1) {\n        addReplyErrorFormat(c, \"wrong number of arguments for 'slotsdel' command\");\n        return;\n    }\n    int i;\n    for (i = 1; i < c->argc; i ++) {\n        int slot;\n        if (parse_slot(c, c->argv[i], &slot) != 0) {\n            return;\n        }\n        slots_slot[n] = slot;\n        n ++;\n    }\n    for (i = 0; i < n; i ++) {\n        dict *d = c->db->hash_slots[slots_slot[i]];\n        int s = dictSize(d);\n        if (s == 0) {\n            continue;\n        }\n        list *l = listCreate();\n        listSetFreeMethod(l, decrRefCountVoid);\n        unsigned long cursor = 0;\n        do {\n            cursor = dictScan(d, cursor, slotsScanSdsKeyCallback, l);\n        } while (cursor != 0);\n        while (1) {\n            listNode *head = listFirst(l);\n            if (head == NULL) {\n                break;\n            }\n            robj *key = listNodeValue(head);\n            robj *keys[] = {key};\n            slotsremove(c, keys, 1, 0);\n            listDelNode(l, head);\n        }\n        listRelease(l);\n    }\n    addReplyMultiBulkLen(c, n);\n    for (i = 0; i < n; i ++) {\n        int n = slots_slot[i];\n        int s = dictSize(c->db->hash_slots[n]);\n        addReplyMultiBulkLen(c, 2);\n        addReplyLongLong(c, n);\n        addReplyLongLong(c, s);\n    }\n}\n\n/* *\n * slotscheck\n * */\nvoid\nslotscheckCommand(redisClient *c) {\n    sds bug = NULL;\n    int i;\n    for (i = 0; i < HASH_SLOTS_SIZE && bug == NULL; i ++) {\n        dict *d = c->db->hash_slots[i];\n        if (dictSize(d) == 0) {\n            continue;\n        }\n        list *l = listCreate();\n        listSetFreeMethod(l, decrRefCountVoid);\n        unsigned long cursor = 0;\n        do {\n            cursor = dictScan(d, cursor, slotsScanSdsKeyCallback, l);\n            while (1) {\n                listNode *head = listFirst(l);\n                if (head == NULL) {\n                    break;\n                }\n                robj *key = listNodeValue(head);\n                if (lookupKey(c->db, key) == NULL) {\n                    if (bug == NULL) {\n                        bug = sdsdup(key->ptr);\n                    }\n                }\n                listDelNode(l, head);\n            }\n        } while (cursor != 0 && bug == NULL);\n        listRelease(l);\n    }\n    if (bug != NULL) {\n        addReplyErrorFormat(c, \"step 1, miss = '%s'\", bug);\n        sdsfree(bug);\n        return;\n    }\n    do {\n        dict *d = c->db->dict;\n        if (dictSize(d) == 0) {\n            break;\n        }\n        list *l = listCreate();\n        listSetFreeMethod(l, decrRefCountVoid);\n        unsigned long cursor = 0;\n        do {\n            cursor = dictScan(d, cursor, slotsScanSdsKeyCallback, l);\n            while (1) {\n                listNode *head = listFirst(l);\n                if (head == NULL) {\n                    break;\n                }\n                robj *key = listNodeValue(head);\n                int slot = slots_num(key->ptr, NULL, NULL);\n                if (dictFind(c->db->hash_slots[slot], key->ptr) == NULL) {\n                    if (bug == NULL) {\n                        bug = sdsdup(key->ptr);\n                    }\n                }\n                listDelNode(l, head);\n            }\n        } while (cursor != 0 && bug == NULL);\n        listRelease(l);\n    } while (0);\n    if (bug != NULL) {\n        addReplyErrorFormat(c, \"step 2, miss = '%s'\", bug);\n        sdsfree(bug);\n        return;\n    }\n    zskiplistNode *node = c->db->tagged_keys->header->level[0].forward;\n    while (node != NULL && bug == NULL) {\n        if (lookupKey(c->db, node->obj) == NULL) {\n            bug = sdsdup(node->obj->ptr);\n        }\n        node = node->level[0].forward;\n    }\n    if (bug != NULL) {\n        addReplyErrorFormat(c, \"step 3, miss = '%s'\", bug);\n        sdsfree(bug);\n        return;\n    }\n    addReply(c, shared.ok);\n}\n\n/* *\n * slotsrestore key ttl val [key ttl val ...]\n * */\nvoid\nslotsrestoreCommand(redisClient *c) {\n    if (c->argc < 4 || (c->argc - 1) % 3 != 0) {\n        addReplyErrorFormat(c, \"wrong number of arguments for 'slotsrestore' command\");\n        return;\n    }\n    int n = (c->argc - 1) / 3;\n\n    long long *ttls = zmalloc(sizeof(long long) * n);\n    robj **vals = zmalloc(sizeof(robj *) * n);\n    for (int i = 0; i < n; i ++) {\n        vals[i] = NULL;\n    }\n\n    for (int i = 0; i < n; i ++) {\n        robj *key = c->argv[i * 3 + 1];\n        robj *ttl = c->argv[i * 3 + 2];\n        robj *val = c->argv[i * 3 + 3];\n        if (lookupKeyWrite(c->db, key) != NULL) {\n            redisLog(REDIS_WARNING, \"slotsrestore: slot = %d, key = '%s' already exists\",\n                    slots_num(key->ptr, NULL, NULL), (char *)key->ptr);\n        }\n        if (getLongLongFromObjectOrReply(c, ttl, &ttls[i], NULL) != REDIS_OK) {\n            goto cleanup;\n        } else if (ttls[i] < 0) {\n            addReplyError(c, \"invalid ttl value, must be >= 0\");\n            goto cleanup;\n        }\n        rio payload;\n        int type;\n        if (verifyDumpPayload(val->ptr, sdslen(val->ptr)) != REDIS_OK) {\n            addReplyError(c, \"dump payload version or checksum are wrong\");\n            goto cleanup;\n        }\n        rioInitWithBuffer(&payload, val->ptr);\n        if (((type = rdbLoadObjectType(&payload)) == -1) ||\n                ((vals[i] = rdbLoadObject(type, &payload)) == NULL)) {\n            addReplyError(c, \"bad data format\");\n            goto cleanup;\n        }\n    }\n\n    for (int i = 0; i < n; i ++) {\n        robj *key = c->argv[i * 3 + 1];\n        long long ttl = ttls[i];\n        robj *val = vals[i];\n        dbDelete(c->db, key);\n        dbAdd(c->db, key, val);\n        incrRefCount(val);\n        if (ttl) {\n            setExpire(c->db, key, mstime() + ttl);\n        }\n        signalModifiedKey(c->db, key);\n        server.dirty ++;\n    }\n    addReply(c, shared.ok);\n\ncleanup:\n    for (int i = 0; i < n; i ++) {\n        if (vals[i] != NULL) {\n            decrRefCount(vals[i]);\n        }\n    }\n    zfree(vals);\n    zfree(ttls);\n}\n\n/* *\n * do migrate mutli key-value(s) for {slotsmgrt/slotsmgrtone}with tag commands\n * return value:\n *    -1 - error happens\n *   >=0 - # of success migration\n * */\nstatic int\nslotsmgrttag_command(redisClient *c, sds host, sds port, int timeout, robj *key) {\n    uint32_t crc;\n    int hastag;\n    int slot = slots_num(key->ptr, &crc, &hastag);\n    if (!hastag) {\n        return slotsmgrtone_command(c, host, port, timeout, key);\n    }\n\n    slotsmgrt_sockfd *pfd = slotsmgrt_get_sockfd(c, host, port, timeout);\n    if (pfd == NULL) {\n        return -1;\n    }\n\n    dict *d = c->db->hash_slots[slot];\n    if (dictSize(d) == 0) {\n        return 0;\n    }\n\n    zrangespec range;\n    range.min = (double)crc;\n    range.minex = 0;\n    range.max = (double)crc;\n    range.maxex = 0;\n\n    list *l = listCreate();\n    listSetFreeMethod(l, decrRefCountVoid);\n\n    zskiplistNode *node = zslFirstInRange(c->db->tagged_keys, &range);\n    while (node != NULL && node->score == (double)crc) {\n        listAddNodeTail(l, node->obj);\n        incrRefCount(node->obj);\n        node = node->level[0].forward;\n    }\n\n    int max = listLength(l);\n    if (max == 0) {\n        listRelease(l);\n        return 0;\n    }\n\n    robj **keys = zmalloc(sizeof(robj *) * max);\n    robj **vals = zmalloc(sizeof(robj *) * max);\n\n    int n = 0;\n    for (int i = 0; i < max; i ++) {\n        listNode *head = listFirst(l);\n        robj *key = listNodeValue(head);\n        robj *val = lookupKeyWrite(c->db, key);\n        if (val != NULL) {\n            keys[n] = key;\n            vals[n] = val;\n            n ++;\n            incrRefCount(key);\n            incrRefCount(val);\n        }\n        listDelNode(l, head);\n    }\n\n    int ret = 0;\n    if (n != 0) {\n        if (slotsmgrt(c, host, port, pfd, c->db->id, timeout, keys, vals, n) != 0) {\n            slotsmgrt_close_socket(host, port);\n            ret = -1;\n        } else {\n            slotsremove(c, keys, n, 1);\n            ret = n;\n        }\n    }\n\n    listRelease(l);\n    for (int i = 0; i < n; i ++) {\n        decrRefCount(keys[i]);\n        decrRefCount(vals[i]);\n    }\n    zfree(keys);\n    zfree(vals);\n    return ret;\n}\n\n/* *\n * slotsmgrttagslot host port timeout slot\n * */\nvoid\nslotsmgrttagslotCommand(redisClient *c) {\n    sds host = c->argv[1]->ptr;\n    sds port = c->argv[2]->ptr;\n    int timeout, slot;\n    if (parse_timeout(c, c->argv[3], &timeout) != 0) {\n        return;\n    }\n    if (parse_slot(c, c->argv[4], &slot) != 0) {\n        return;\n    }\n\n    dict *d = c->db->hash_slots[slot];\n    int succ = 0;\n    do {\n        const dictEntry *de = dictGetRandomKey(d);\n        if (de == NULL) {\n            break;\n        }\n        sds skey = dictGetKey(de);\n        robj *key = createStringObject(skey, sdslen(skey));\n        succ = slotsmgrttag_command(c, host, port, timeout, key);\n        decrRefCount(key);\n        if (succ < 0) {\n            return;\n        }\n    } while (0);\n    addReplyMultiBulkLen(c, 2);\n    addReplyLongLong(c, succ);\n    addReplyLongLong(c, dictSize(d));\n}\n\n/* *\n * slotsmgrttagone host port timeout key\n * */\nvoid\nslotsmgrttagoneCommand(redisClient *c) {\n    sds host = c->argv[1]->ptr;\n    sds port = c->argv[2]->ptr;\n    int timeout;\n    if (parse_timeout(c, c->argv[3], &timeout) != 0) {\n        return;\n    }\n\n    robj *key = c->argv[4];\n    int succ = slotsmgrttag_command(c, host, port, timeout, key);\n    if (succ < 0) {\n        return;\n    }\n    addReplyLongLong(c, succ);\n}\n\n/* *\n * slotsscan slotnum cursor [COUNT count]\n * */\nvoid\nslotsscanCommand(redisClient *c) {\n    int slot;\n    if (parse_slot(c, c->argv[1], &slot) != 0) {\n        return;\n    }\n    unsigned long cursor;\n    if (parseScanCursorOrReply(c, c->argv[2], &cursor) == REDIS_ERR) {\n        return;\n    }\n    unsigned long count = 10;\n    if (c->argc != 3 && c->argc != 5) {\n        addReplyErrorFormat(c, \"wrong number of arguments for 'slotsscan' command\");\n        return;\n    }\n    if (c->argc == 5) {\n        if (strcasecmp(c->argv[3]->ptr, \"count\") != 0) {\n            addReply(c, shared.syntaxerr);\n            return;\n        }\n        int v;\n        if (parse_int(c, c->argv[4], &v) != 0) {\n            return;\n        }\n        if (v < 1) {\n            addReply(c, shared.syntaxerr);\n            return;\n        }\n        count = v;\n    }\n    dict *d = c->db->hash_slots[slot];\n    list *l = listCreate();\n    listSetFreeMethod(l, decrRefCountVoid);\n\n    long loops = count * 10;\n    do {\n        cursor = dictScan(d, cursor, slotsScanSdsKeyCallback, l);\n        loops --;\n    } while (cursor != 0 && loops > 0 && listLength(l) < count);\n\n    addReplyMultiBulkLen(c, 2);\n    addReplyBulkLongLong(c, cursor);\n\n    addReplyMultiBulkLen(c, listLength(l));\n    while (1) {\n        listNode *head = listFirst(l);\n        if (head == NULL) {\n            break;\n        }\n        robj *key = listNodeValue(head);\n        addReplyBulk(c, key);\n        listDelNode(l, head);\n    }\n\n    listRelease(l);\n}\n"
  },
  {
    "path": "extern/deprecated/redis-2.8.21/src/slowlog.c",
    "content": "/* Slowlog implements a system that is able to remember the latest N\n * queries that took more than M microseconds to execute.\n *\n * The execution time to reach to be logged in the slow log is set\n * using the 'slowlog-log-slower-than' config directive, that is also\n * readable and writable using the CONFIG SET/GET command.\n *\n * The slow queries log is actually not \"logged\" in the Redis log file\n * but is accessible thanks to the SLOWLOG command.\n *\n * ----------------------------------------------------------------------------\n *\n * Copyright (c) 2009-2012, Salvatore Sanfilippo <antirez at gmail dot com>\n * All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions are met:\n *\n *   * Redistributions of source code must retain the above copyright notice,\n *     this list of conditions and the following disclaimer.\n *   * Redistributions in binary form must reproduce the above copyright\n *     notice, this list of conditions and the following disclaimer in the\n *     documentation and/or other materials provided with the distribution.\n *   * Neither the name of Redis nor the names of its contributors may be used\n *     to endorse or promote products derived from this software without\n *     specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\"\n * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\n * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE\n * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR\n * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF\n * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS\n * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN\n * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)\n * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE\n * POSSIBILITY OF SUCH DAMAGE.\n */\n\n\n#include \"redis.h\"\n#include \"slowlog.h\"\n\n/* Create a new slowlog entry.\n * Incrementing the ref count of all the objects retained is up to\n * this function. */\nslowlogEntry *slowlogCreateEntry(robj **argv, int argc, long long duration) {\n    slowlogEntry *se = zmalloc(sizeof(*se));\n    int j, slargc = argc;\n\n    if (slargc > SLOWLOG_ENTRY_MAX_ARGC) slargc = SLOWLOG_ENTRY_MAX_ARGC;\n    se->argc = slargc;\n    se->argv = zmalloc(sizeof(robj*)*slargc);\n    for (j = 0; j < slargc; j++) {\n        /* Logging too many arguments is a useless memory waste, so we stop\n         * at SLOWLOG_ENTRY_MAX_ARGC, but use the last argument to specify\n         * how many remaining arguments there were in the original command. */\n        if (slargc != argc && j == slargc-1) {\n            se->argv[j] = createObject(REDIS_STRING,\n                sdscatprintf(sdsempty(),\"... (%d more arguments)\",\n                argc-slargc+1));\n        } else {\n            /* Trim too long strings as well... */\n            if (argv[j]->type == REDIS_STRING &&\n                argv[j]->encoding == REDIS_ENCODING_RAW &&\n                sdslen(argv[j]->ptr) > SLOWLOG_ENTRY_MAX_STRING)\n            {\n                sds s = sdsnewlen(argv[j]->ptr, SLOWLOG_ENTRY_MAX_STRING);\n\n                s = sdscatprintf(s,\"... (%lu more bytes)\",\n                    (unsigned long)\n                    sdslen(argv[j]->ptr) - SLOWLOG_ENTRY_MAX_STRING);\n                se->argv[j] = createObject(REDIS_STRING,s);\n            } else {\n                se->argv[j] = argv[j];\n                incrRefCount(argv[j]);\n            }\n        }\n    }\n    se->time = time(NULL);\n    se->duration = duration;\n    se->id = server.slowlog_entry_id++;\n    return se;\n}\n\n/* Free a slow log entry. The argument is void so that the prototype of this\n * function matches the one of the 'free' method of adlist.c.\n *\n * This function will take care to release all the retained object. */\nvoid slowlogFreeEntry(void *septr) {\n    slowlogEntry *se = septr;\n    int j;\n\n    for (j = 0; j < se->argc; j++)\n        decrRefCount(se->argv[j]);\n    zfree(se->argv);\n    zfree(se);\n}\n\n/* Initialize the slow log. This function should be called a single time\n * at server startup. */\nvoid slowlogInit(void) {\n    server.slowlog = listCreate();\n    server.slowlog_entry_id = 0;\n    listSetFreeMethod(server.slowlog,slowlogFreeEntry);\n}\n\n/* Push a new entry into the slow log.\n * This function will make sure to trim the slow log accordingly to the\n * configured max length. */\nvoid slowlogPushEntryIfNeeded(robj **argv, int argc, long long duration) {\n    if (server.slowlog_log_slower_than < 0) return; /* Slowlog disabled */\n    if (duration >= server.slowlog_log_slower_than)\n        listAddNodeHead(server.slowlog,slowlogCreateEntry(argv,argc,duration));\n\n    /* Remove old entries if needed. */\n    while (listLength(server.slowlog) > server.slowlog_max_len)\n        listDelNode(server.slowlog,listLast(server.slowlog));\n}\n\n/* Remove all the entries from the current slow log. */\nvoid slowlogReset(void) {\n    while (listLength(server.slowlog) > 0)\n        listDelNode(server.slowlog,listLast(server.slowlog));\n}\n\n/* The SLOWLOG command. Implements all the subcommands needed to handle the\n * Redis slow log. */\nvoid slowlogCommand(redisClient *c) {\n    if (c->argc == 2 && !strcasecmp(c->argv[1]->ptr,\"reset\")) {\n        slowlogReset();\n        addReply(c,shared.ok);\n    } else if (c->argc == 2 && !strcasecmp(c->argv[1]->ptr,\"len\")) {\n        addReplyLongLong(c,listLength(server.slowlog));\n    } else if ((c->argc == 2 || c->argc == 3) &&\n               !strcasecmp(c->argv[1]->ptr,\"get\"))\n    {\n        long count = 10, sent = 0;\n        listIter li;\n        void *totentries;\n        listNode *ln;\n        slowlogEntry *se;\n\n        if (c->argc == 3 &&\n            getLongFromObjectOrReply(c,c->argv[2],&count,NULL) != REDIS_OK)\n            return;\n\n        listRewind(server.slowlog,&li);\n        totentries = addDeferredMultiBulkLength(c);\n        while(count-- && (ln = listNext(&li))) {\n            int j;\n\n            se = ln->value;\n            addReplyMultiBulkLen(c,4);\n            addReplyLongLong(c,se->id);\n            addReplyLongLong(c,se->time);\n            addReplyLongLong(c,se->duration);\n            addReplyMultiBulkLen(c,se->argc);\n            for (j = 0; j < se->argc; j++)\n                addReplyBulk(c,se->argv[j]);\n            sent++;\n        }\n        setDeferredMultiBulkLength(c,totentries,sent);\n    } else {\n        addReplyError(c,\n            \"Unknown SLOWLOG subcommand or wrong # of args. Try GET, RESET, LEN.\");\n    }\n}\n"
  },
  {
    "path": "extern/deprecated/redis-2.8.21/src/slowlog.h",
    "content": "/*\n * Copyright (c) 2009-2012, Salvatore Sanfilippo <antirez at gmail dot com>\n * All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions are met:\n *\n *   * Redistributions of source code must retain the above copyright notice,\n *     this list of conditions and the following disclaimer.\n *   * Redistributions in binary form must reproduce the above copyright\n *     notice, this list of conditions and the following disclaimer in the\n *     documentation and/or other materials provided with the distribution.\n *   * Neither the name of Redis nor the names of its contributors may be used\n *     to endorse or promote products derived from this software without\n *     specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\"\n * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\n * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE\n * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR\n * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF\n * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS\n * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN\n * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)\n * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE\n * POSSIBILITY OF SUCH DAMAGE.\n */\n\n#define SLOWLOG_ENTRY_MAX_ARGC 32\n#define SLOWLOG_ENTRY_MAX_STRING 128\n\n/* This structure defines an entry inside the slow log list */\ntypedef struct slowlogEntry {\n    robj **argv;\n    int argc;\n    long long id;       /* Unique entry identifier. */\n    long long duration; /* Time spent by the query, in nanoseconds. */\n    time_t time;        /* Unix time at which the query was executed. */\n} slowlogEntry;\n\n/* Exported API */\nvoid slowlogInit(void);\nvoid slowlogPushEntryIfNeeded(robj **argv, int argc, long long duration);\n\n/* Exported commands */\nvoid slowlogCommand(redisClient *c);\n"
  },
  {
    "path": "extern/deprecated/redis-2.8.21/src/solarisfixes.h",
    "content": "/* Solaris specific fixes.\n *\n * Copyright (c) 2009-2012, Salvatore Sanfilippo <antirez at gmail dot com>\n * All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions are met:\n *\n *   * Redistributions of source code must retain the above copyright notice,\n *     this list of conditions and the following disclaimer.\n *   * Redistributions in binary form must reproduce the above copyright\n *     notice, this list of conditions and the following disclaimer in the\n *     documentation and/or other materials provided with the distribution.\n *   * Neither the name of Redis nor the names of its contributors may be used\n *     to endorse or promote products derived from this software without\n *     specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\"\n * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\n * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE\n * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR\n * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF\n * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS\n * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN\n * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)\n * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE\n * POSSIBILITY OF SUCH DAMAGE.\n */\n\n#if defined(__sun)\n\n#if defined(__GNUC__)\n#include <math.h>\n#undef isnan\n#define isnan(x) \\\n     __extension__({ __typeof (x) __x_a = (x); \\\n     __builtin_expect(__x_a != __x_a, 0); })\n\n#undef isfinite\n#define isfinite(x) \\\n     __extension__ ({ __typeof (x) __x_f = (x); \\\n     __builtin_expect(!isnan(__x_f - __x_f), 1); })\n\n#undef isinf\n#define isinf(x) \\\n     __extension__ ({ __typeof (x) __x_i = (x); \\\n     __builtin_expect(!isnan(__x_i) && !isfinite(__x_i), 0); })\n\n#define u_int uint\n#define u_int32_t uint32_t\n#endif /* __GNUC__ */\n\n#endif /* __sun */\n"
  },
  {
    "path": "extern/deprecated/redis-2.8.21/src/sort.c",
    "content": "/* SORT command and helper functions.\n *\n * Copyright (c) 2009-2012, Salvatore Sanfilippo <antirez at gmail dot com>\n * All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions are met:\n *\n *   * Redistributions of source code must retain the above copyright notice,\n *     this list of conditions and the following disclaimer.\n *   * Redistributions in binary form must reproduce the above copyright\n *     notice, this list of conditions and the following disclaimer in the\n *     documentation and/or other materials provided with the distribution.\n *   * Neither the name of Redis nor the names of its contributors may be used\n *     to endorse or promote products derived from this software without\n *     specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\"\n * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\n * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE\n * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR\n * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF\n * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS\n * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN\n * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)\n * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE\n * POSSIBILITY OF SUCH DAMAGE.\n */\n\n\n#include \"redis.h\"\n#include \"pqsort.h\" /* Partial qsort for SORT+LIMIT */\n#include <math.h> /* isnan() */\n\nzskiplistNode* zslGetElementByRank(zskiplist *zsl, unsigned long rank);\n\nredisSortOperation *createSortOperation(int type, robj *pattern) {\n    redisSortOperation *so = zmalloc(sizeof(*so));\n    so->type = type;\n    so->pattern = pattern;\n    return so;\n}\n\n/* Return the value associated to the key with a name obtained using\n * the following rules:\n *\n * 1) The first occurrence of '*' in 'pattern' is substituted with 'subst'.\n *\n * 2) If 'pattern' matches the \"->\" string, everything on the left of\n *    the arrow is treated as the name of a hash field, and the part on the\n *    left as the key name containing a hash. The value of the specified\n *    field is returned.\n *\n * 3) If 'pattern' equals \"#\", the function simply returns 'subst' itself so\n *    that the SORT command can be used like: SORT key GET # to retrieve\n *    the Set/List elements directly.\n *\n * The returned object will always have its refcount increased by 1\n * when it is non-NULL. */\nrobj *lookupKeyByPattern(redisDb *db, robj *pattern, robj *subst) {\n    char *p, *f, *k;\n    sds spat, ssub;\n    robj *keyobj, *fieldobj = NULL, *o;\n    int prefixlen, sublen, postfixlen, fieldlen;\n\n    /* If the pattern is \"#\" return the substitution object itself in order\n     * to implement the \"SORT ... GET #\" feature. */\n    spat = pattern->ptr;\n    if (spat[0] == '#' && spat[1] == '\\0') {\n        incrRefCount(subst);\n        return subst;\n    }\n\n    /* The substitution object may be specially encoded. If so we create\n     * a decoded object on the fly. Otherwise getDecodedObject will just\n     * increment the ref count, that we'll decrement later. */\n    subst = getDecodedObject(subst);\n    ssub = subst->ptr;\n\n    /* If we can't find '*' in the pattern we return NULL as to GET a\n     * fixed key does not make sense. */\n    p = strchr(spat,'*');\n    if (!p) {\n        decrRefCount(subst);\n        return NULL;\n    }\n\n    /* Find out if we're dealing with a hash dereference. */\n    if ((f = strstr(p+1, \"->\")) != NULL && *(f+2) != '\\0') {\n        fieldlen = sdslen(spat)-(f-spat)-2;\n        fieldobj = createStringObject(f+2,fieldlen);\n    } else {\n        fieldlen = 0;\n    }\n\n    /* Perform the '*' substitution. */\n    prefixlen = p-spat;\n    sublen = sdslen(ssub);\n    postfixlen = sdslen(spat)-(prefixlen+1)-(fieldlen ? fieldlen+2 : 0);\n    keyobj = createStringObject(NULL,prefixlen+sublen+postfixlen);\n    k = keyobj->ptr;\n    memcpy(k,spat,prefixlen);\n    memcpy(k+prefixlen,ssub,sublen);\n    memcpy(k+prefixlen+sublen,p+1,postfixlen);\n    decrRefCount(subst); /* Incremented by decodeObject() */\n\n    /* Lookup substituted key */\n    o = lookupKeyRead(db,keyobj);\n    if (o == NULL) goto noobj;\n\n    if (fieldobj) {\n        if (o->type != REDIS_HASH) goto noobj;\n\n        /* Retrieve value from hash by the field name. This operation\n         * already increases the refcount of the returned object. */\n        o = hashTypeGetObject(o, fieldobj);\n    } else {\n        if (o->type != REDIS_STRING) goto noobj;\n\n        /* Every object that this function returns needs to have its refcount\n         * increased. sortCommand decreases it again. */\n        incrRefCount(o);\n    }\n    decrRefCount(keyobj);\n    if (fieldobj) decrRefCount(fieldobj);\n    return o;\n\nnoobj:\n    decrRefCount(keyobj);\n    if (fieldlen) decrRefCount(fieldobj);\n    return NULL;\n}\n\n/* sortCompare() is used by qsort in sortCommand(). Given that qsort_r with\n * the additional parameter is not standard but a BSD-specific we have to\n * pass sorting parameters via the global 'server' structure */\nint sortCompare(const void *s1, const void *s2) {\n    const redisSortObject *so1 = s1, *so2 = s2;\n    int cmp;\n\n    if (!server.sort_alpha) {\n        /* Numeric sorting. Here it's trivial as we precomputed scores */\n        if (so1->u.score > so2->u.score) {\n            cmp = 1;\n        } else if (so1->u.score < so2->u.score) {\n            cmp = -1;\n        } else {\n            /* Objects have the same score, but we don't want the comparison\n             * to be undefined, so we compare objects lexicographically.\n             * This way the result of SORT is deterministic. */\n            cmp = compareStringObjects(so1->obj,so2->obj);\n        }\n    } else {\n        /* Alphanumeric sorting */\n        if (server.sort_bypattern) {\n            if (!so1->u.cmpobj || !so2->u.cmpobj) {\n                /* At least one compare object is NULL */\n                if (so1->u.cmpobj == so2->u.cmpobj)\n                    cmp = 0;\n                else if (so1->u.cmpobj == NULL)\n                    cmp = -1;\n                else\n                    cmp = 1;\n            } else {\n                /* We have both the objects, compare them. */\n                if (server.sort_store) {\n                    cmp = compareStringObjects(so1->u.cmpobj,so2->u.cmpobj);\n                } else {\n                    /* Here we can use strcoll() directly as we are sure that\n                     * the objects are decoded string objects. */\n                    cmp = strcoll(so1->u.cmpobj->ptr,so2->u.cmpobj->ptr);\n                }\n            }\n        } else {\n            /* Compare elements directly. */\n            if (server.sort_store) {\n                cmp = compareStringObjects(so1->obj,so2->obj);\n            } else {\n                cmp = collateStringObjects(so1->obj,so2->obj);\n            }\n        }\n    }\n    return server.sort_desc ? -cmp : cmp;\n}\n\n/* The SORT command is the most complex command in Redis. Warning: this code\n * is optimized for speed and a bit less for readability */\nvoid sortCommand(redisClient *c) {\n    list *operations;\n    unsigned int outputlen = 0;\n    int desc = 0, alpha = 0;\n    long limit_start = 0, limit_count = -1, start, end;\n    int j, dontsort = 0, vectorlen;\n    int getop = 0; /* GET operation counter */\n    int int_convertion_error = 0;\n    robj *sortval, *sortby = NULL, *storekey = NULL;\n    redisSortObject *vector; /* Resulting vector to sort */\n\n    /* Lookup the key to sort. It must be of the right types */\n    sortval = lookupKeyRead(c->db,c->argv[1]);\n    if (sortval && sortval->type != REDIS_SET &&\n                   sortval->type != REDIS_LIST &&\n                   sortval->type != REDIS_ZSET)\n    {\n        addReply(c,shared.wrongtypeerr);\n        return;\n    }\n\n    /* Create a list of operations to perform for every sorted element.\n     * Operations can be GET/DEL/INCR/DECR */\n    operations = listCreate();\n    listSetFreeMethod(operations,zfree);\n    j = 2; /* options start at argv[2] */\n\n    /* Now we need to protect sortval incrementing its count, in the future\n     * SORT may have options able to overwrite/delete keys during the sorting\n     * and the sorted key itself may get destroyed */\n    if (sortval)\n        incrRefCount(sortval);\n    else\n        sortval = createListObject();\n\n    /* The SORT command has an SQL-alike syntax, parse it */\n    while(j < c->argc) {\n        int leftargs = c->argc-j-1;\n        if (!strcasecmp(c->argv[j]->ptr,\"asc\")) {\n            desc = 0;\n        } else if (!strcasecmp(c->argv[j]->ptr,\"desc\")) {\n            desc = 1;\n        } else if (!strcasecmp(c->argv[j]->ptr,\"alpha\")) {\n            alpha = 1;\n        } else if (!strcasecmp(c->argv[j]->ptr,\"limit\") && leftargs >= 2) {\n            if ((getLongFromObjectOrReply(c, c->argv[j+1], &limit_start, NULL)\n                 != REDIS_OK) ||\n                (getLongFromObjectOrReply(c, c->argv[j+2], &limit_count, NULL)\n                 != REDIS_OK))\n            {\n                decrRefCount(sortval);\n                listRelease(operations);\n                return;\n            }\n            j+=2;\n        } else if (!strcasecmp(c->argv[j]->ptr,\"store\") && leftargs >= 1) {\n            storekey = c->argv[j+1];\n            j++;\n        } else if (!strcasecmp(c->argv[j]->ptr,\"by\") && leftargs >= 1) {\n            sortby = c->argv[j+1];\n            /* If the BY pattern does not contain '*', i.e. it is constant,\n             * we don't need to sort nor to lookup the weight keys. */\n            if (strchr(c->argv[j+1]->ptr,'*') == NULL) dontsort = 1;\n            j++;\n        } else if (!strcasecmp(c->argv[j]->ptr,\"get\") && leftargs >= 1) {\n            listAddNodeTail(operations,createSortOperation(\n                REDIS_SORT_GET,c->argv[j+1]));\n            getop++;\n            j++;\n        } else {\n            decrRefCount(sortval);\n            listRelease(operations);\n            addReply(c,shared.syntaxerr);\n            return;\n        }\n        j++;\n    }\n\n    /* When sorting a set with no sort specified, we must sort the output\n     * so the result is consistent across scripting and replication.\n     *\n     * The other types (list, sorted set) will retain their native order\n     * even if no sort order is requested, so they remain stable across\n     * scripting and replication. */\n    if (dontsort &&\n        sortval->type == REDIS_SET &&\n        (storekey || c->flags & REDIS_LUA_CLIENT))\n    {\n        /* Force ALPHA sorting */\n        dontsort = 0;\n        alpha = 1;\n        sortby = NULL;\n    }\n\n    /* Destructively convert encoded sorted sets for SORT. */\n    if (sortval->type == REDIS_ZSET)\n        zsetConvert(sortval, REDIS_ENCODING_SKIPLIST);\n\n    /* Objtain the length of the object to sort. */\n    switch(sortval->type) {\n    case REDIS_LIST: vectorlen = listTypeLength(sortval); break;\n    case REDIS_SET: vectorlen =  setTypeSize(sortval); break;\n    case REDIS_ZSET: vectorlen = dictSize(((zset*)sortval->ptr)->dict); break;\n    default: vectorlen = 0; redisPanic(\"Bad SORT type\"); /* Avoid GCC warning */\n    }\n\n    /* Perform LIMIT start,count sanity checking. */\n    start = (limit_start < 0) ? 0 : limit_start;\n    end = (limit_count < 0) ? vectorlen-1 : start+limit_count-1;\n    if (start >= vectorlen) {\n        start = vectorlen-1;\n        end = vectorlen-2;\n    }\n    if (end >= vectorlen) end = vectorlen-1;\n\n    /* Optimization:\n     *\n     * 1) if the object to sort is a sorted set.\n     * 2) There is nothing to sort as dontsort is true (BY <constant string>).\n     * 3) We have a LIMIT option that actually reduces the number of elements\n     *    to fetch.\n     *\n     * In this case to load all the objects in the vector is a huge waste of\n     * resources. We just allocate a vector that is big enough for the selected\n     * range length, and make sure to load just this part in the vector. */\n    if (sortval->type == REDIS_ZSET &&\n        dontsort &&\n        (start != 0 || end != vectorlen-1))\n    {\n        vectorlen = end-start+1;\n    }\n\n    /* Load the sorting vector with all the objects to sort */\n    vector = zmalloc(sizeof(redisSortObject)*vectorlen);\n    j = 0;\n\n    if (sortval->type == REDIS_LIST) {\n        listTypeIterator *li = listTypeInitIterator(sortval,0,REDIS_TAIL);\n        listTypeEntry entry;\n        while(listTypeNext(li,&entry)) {\n            vector[j].obj = listTypeGet(&entry);\n            vector[j].u.score = 0;\n            vector[j].u.cmpobj = NULL;\n            j++;\n        }\n        listTypeReleaseIterator(li);\n    } else if (sortval->type == REDIS_SET) {\n        setTypeIterator *si = setTypeInitIterator(sortval);\n        robj *ele;\n        while((ele = setTypeNextObject(si)) != NULL) {\n            vector[j].obj = ele;\n            vector[j].u.score = 0;\n            vector[j].u.cmpobj = NULL;\n            j++;\n        }\n        setTypeReleaseIterator(si);\n    } else if (sortval->type == REDIS_ZSET && dontsort) {\n        /* Special handling for a sorted set, if 'dontsort' is true.\n         * This makes sure we return elements in the sorted set original\n         * ordering, accordingly to DESC / ASC options.\n         *\n         * Note that in this case we also handle LIMIT here in a direct\n         * way, just getting the required range, as an optimization. */\n\n        zset *zs = sortval->ptr;\n        zskiplist *zsl = zs->zsl;\n        zskiplistNode *ln;\n        robj *ele;\n        int rangelen = vectorlen;\n\n        /* Check if starting point is trivial, before doing log(N) lookup. */\n        if (desc) {\n            long zsetlen = dictSize(((zset*)sortval->ptr)->dict);\n\n            ln = zsl->tail;\n            if (start > 0)\n                ln = zslGetElementByRank(zsl,zsetlen-start);\n        } else {\n            ln = zsl->header->level[0].forward;\n            if (start > 0)\n                ln = zslGetElementByRank(zsl,start+1);\n        }\n\n        while(rangelen--) {\n            redisAssertWithInfo(c,sortval,ln != NULL);\n            ele = ln->obj;\n            vector[j].obj = ele;\n            vector[j].u.score = 0;\n            vector[j].u.cmpobj = NULL;\n            j++;\n            ln = desc ? ln->backward : ln->level[0].forward;\n        }\n        /* The code producing the output does not know that in the case of\n         * sorted set, 'dontsort', and LIMIT, we are able to get just the\n         * range, already sorted, so we need to adjust \"start\" and \"end\"\n         * to make sure start is set to 0. */\n        end -= start;\n        start = 0;\n    } else if (sortval->type == REDIS_ZSET) {\n        dict *set = ((zset*)sortval->ptr)->dict;\n        dictIterator *di;\n        dictEntry *setele;\n        di = dictGetIterator(set);\n        while((setele = dictNext(di)) != NULL) {\n            vector[j].obj = dictGetKey(setele);\n            vector[j].u.score = 0;\n            vector[j].u.cmpobj = NULL;\n            j++;\n        }\n        dictReleaseIterator(di);\n    } else {\n        redisPanic(\"Unknown type\");\n    }\n    redisAssertWithInfo(c,sortval,j == vectorlen);\n\n    /* Now it's time to load the right scores in the sorting vector */\n    if (dontsort == 0) {\n        for (j = 0; j < vectorlen; j++) {\n            robj *byval;\n            if (sortby) {\n                /* lookup value to sort by */\n                byval = lookupKeyByPattern(c->db,sortby,vector[j].obj);\n                if (!byval) continue;\n            } else {\n                /* use object itself to sort by */\n                byval = vector[j].obj;\n            }\n\n            if (alpha) {\n                if (sortby) vector[j].u.cmpobj = getDecodedObject(byval);\n            } else {\n                if (byval->encoding == REDIS_ENCODING_RAW) {\n                    char *eptr;\n\n                    vector[j].u.score = strtod(byval->ptr,&eptr);\n                    if (eptr[0] != '\\0' || errno == ERANGE ||\n                        isnan(vector[j].u.score))\n                    {\n                        int_convertion_error = 1;\n                    }\n                } else if (byval->encoding == REDIS_ENCODING_INT) {\n                    /* Don't need to decode the object if it's\n                     * integer-encoded (the only encoding supported) so\n                     * far. We can just cast it */\n                    vector[j].u.score = (long)byval->ptr;\n                } else {\n                    redisAssertWithInfo(c,sortval,1 != 1);\n                }\n            }\n\n            /* when the object was retrieved using lookupKeyByPattern,\n             * its refcount needs to be decreased. */\n            if (sortby) {\n                decrRefCount(byval);\n            }\n        }\n    }\n\n    if (dontsort == 0) {\n        server.sort_desc = desc;\n        server.sort_alpha = alpha;\n        server.sort_bypattern = sortby ? 1 : 0;\n        server.sort_store = storekey ? 1 : 0;\n        if (sortby && (start != 0 || end != vectorlen-1))\n            pqsort(vector,vectorlen,sizeof(redisSortObject),sortCompare, start,end);\n        else\n            qsort(vector,vectorlen,sizeof(redisSortObject),sortCompare);\n    }\n\n    /* Send command output to the output buffer, performing the specified\n     * GET/DEL/INCR/DECR operations if any. */\n    outputlen = getop ? getop*(end-start+1) : end-start+1;\n    if (int_convertion_error) {\n        addReplyError(c,\"One or more scores can't be converted into double\");\n    } else if (storekey == NULL) {\n        /* STORE option not specified, sent the sorting result to client */\n        addReplyMultiBulkLen(c,outputlen);\n        for (j = start; j <= end; j++) {\n            listNode *ln;\n            listIter li;\n\n            if (!getop) addReplyBulk(c,vector[j].obj);\n            listRewind(operations,&li);\n            while((ln = listNext(&li))) {\n                redisSortOperation *sop = ln->value;\n                robj *val = lookupKeyByPattern(c->db,sop->pattern,\n                    vector[j].obj);\n\n                if (sop->type == REDIS_SORT_GET) {\n                    if (!val) {\n                        addReply(c,shared.nullbulk);\n                    } else {\n                        addReplyBulk(c,val);\n                        decrRefCount(val);\n                    }\n                } else {\n                    /* Always fails */\n                    redisAssertWithInfo(c,sortval,sop->type == REDIS_SORT_GET);\n                }\n            }\n        }\n    } else {\n        robj *sobj = createZiplistObject();\n\n        /* STORE option specified, set the sorting result as a List object */\n        for (j = start; j <= end; j++) {\n            listNode *ln;\n            listIter li;\n\n            if (!getop) {\n                listTypePush(sobj,vector[j].obj,REDIS_TAIL);\n            } else {\n                listRewind(operations,&li);\n                while((ln = listNext(&li))) {\n                    redisSortOperation *sop = ln->value;\n                    robj *val = lookupKeyByPattern(c->db,sop->pattern,\n                        vector[j].obj);\n\n                    if (sop->type == REDIS_SORT_GET) {\n                        if (!val) val = createStringObject(\"\",0);\n\n                        /* listTypePush does an incrRefCount, so we should take care\n                         * care of the incremented refcount caused by either\n                         * lookupKeyByPattern or createStringObject(\"\",0) */\n                        listTypePush(sobj,val,REDIS_TAIL);\n                        decrRefCount(val);\n                    } else {\n                        /* Always fails */\n                        redisAssertWithInfo(c,sortval,sop->type == REDIS_SORT_GET);\n                    }\n                }\n            }\n        }\n        if (outputlen) {\n            setKey(c->db,storekey,sobj);\n            notifyKeyspaceEvent(REDIS_NOTIFY_LIST,\"sortstore\",storekey,\n                                c->db->id);\n            server.dirty += outputlen;\n        } else if (dbDelete(c->db,storekey)) {\n            signalModifiedKey(c->db,storekey);\n            notifyKeyspaceEvent(REDIS_NOTIFY_GENERIC,\"del\",storekey,c->db->id);\n            server.dirty++;\n        }\n        decrRefCount(sobj);\n        addReplyLongLong(c,outputlen);\n    }\n\n    /* Cleanup */\n    if (sortval->type == REDIS_LIST || sortval->type == REDIS_SET)\n        for (j = 0; j < vectorlen; j++)\n            decrRefCount(vector[j].obj);\n    decrRefCount(sortval);\n    listRelease(operations);\n    for (j = 0; j < vectorlen; j++) {\n        if (alpha && vector[j].u.cmpobj)\n            decrRefCount(vector[j].u.cmpobj);\n    }\n    zfree(vector);\n}\n"
  },
  {
    "path": "extern/deprecated/redis-2.8.21/src/sparkline.c",
    "content": "/* sparkline.c -- ASCII Sparklines\n * This code is modified from http://github.com/antirez/aspark and adapted\n * in order to return SDS strings instead of outputting directly to\n * the terminal.\n *\n * ---------------------------------------------------------------------------\n *\n * Copyright(C) 2011-2014 Salvatore Sanfilippo <antirez@gmail.com>\n * All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions are met:\n *\n *   * Redistributions of source code must retain the above copyright notice,\n *     this list of conditions and the following disclaimer.\n *   * Redistributions in binary form must reproduce the above copyright\n *     notice, this list of conditions and the following disclaimer in the\n *     documentation and/or other materials provided with the distribution.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\"\n * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\n * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE\n * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR\n * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF\n * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS\n * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN\n * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)\n * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE\n * POSSIBILITY OF SUCH DAMAGE.\n */\n\n#include \"redis.h\"\n\n#include <math.h>\n\n/* This is the charset used to display the graphs, but multiple rows are used\n * to increase the resolution. */\nstatic char charset[] = \"_-`\";\nstatic char charset_fill[] = \"_o#\";\nstatic int charset_len = sizeof(charset)-1;\nstatic int label_margin_top = 1;\n\n/* ----------------------------------------------------------------------------\n * Sequences are arrays of samples we use to represent data to turn\n * into sparklines. This is the API in order to generate a sparkline:\n *\n * struct sequence *seq = createSparklineSequence();\n * sparklineSequenceAddSample(seq, 10, NULL);\n * sparklineSequenceAddSample(seq, 20, NULL);\n * sparklineSequenceAddSample(seq, 30, \"last sample label\");\n * sds output = sparklineRender(sdsempty(), seq, 80, 4, SPARKLINE_FILL);\n * freeSparklineSequence(seq);\n * ------------------------------------------------------------------------- */\n\n/* Create a new sequence. */\nstruct sequence *createSparklineSequence(void) {\n    struct sequence *seq = zmalloc(sizeof(*seq));\n    seq->length = 0;\n    seq->samples = NULL;\n    return seq;\n}\n\n/* Add a new sample into a sequence. */\nvoid sparklineSequenceAddSample(struct sequence *seq, double value, char *label) {\n    label = (label == NULL || label[0] == '\\0') ? NULL : zstrdup(label);\n    if (seq->length == 0) {\n        seq->min = seq->max = value;\n    } else {\n        if (value < seq->min) seq->min = value;\n        else if (value > seq->max) seq->max = value;\n    }\n    seq->samples = zrealloc(seq->samples,sizeof(struct sample)*(seq->length+1));\n    seq->samples[seq->length].value = value;\n    seq->samples[seq->length].label = label;\n    seq->length++;\n    if (label) seq->labels++;\n}\n\n/* Free a sequence. */\nvoid freeSparklineSequence(struct sequence *seq) {\n    int j;\n\n    for (j = 0; j < seq->length; j++)\n        zfree(seq->samples[j].label);\n    zfree(seq->samples);\n    zfree(seq);\n}\n\n/* ----------------------------------------------------------------------------\n * ASCII rendering of sequence\n * ------------------------------------------------------------------------- */\n\n/* Render part of a sequence, so that render_sequence() call call this function\n * with differnent parts in order to create the full output without overflowing\n * the current terminal columns. */\nsds sparklineRenderRange(sds output, struct sequence *seq, int rows, int offset, int len, int flags) {\n    int j;\n    double relmax = seq->max - seq->min;\n    int steps = charset_len*rows;\n    int row = 0;\n    char *chars = zmalloc(len);\n    int loop = 1;\n    int opt_fill = flags & SPARKLINE_FILL;\n    int opt_log = flags & SPARKLINE_LOG_SCALE;\n\n    if (opt_log) {\n        relmax = log(relmax+1);\n    } else if (relmax == 0) {\n        relmax = 1;\n    }\n\n    while(loop) {\n        loop = 0;\n        memset(chars,' ',len);\n        for (j = 0; j < len; j++) {\n            struct sample *s = &seq->samples[j+offset];\n            double relval = s->value - seq->min;\n            int step;\n\n            if (opt_log) relval = log(relval+1);\n            step = (int) (relval*steps)/relmax;\n            if (step < 0) step = 0;\n            if (step >= steps) step = steps-1;\n\n            if (row < rows) {\n                /* Print the character needed to create the sparkline */\n                int charidx = step-((rows-row-1)*charset_len);\n                loop = 1;\n                if (charidx >= 0 && charidx < charset_len) {\n                    chars[j] = opt_fill ? charset_fill[charidx] :\n                                          charset[charidx];\n                } else if(opt_fill && charidx >= charset_len) {\n                    chars[j] = '|';\n                }\n            } else {\n                /* Labels spacing */\n                if (seq->labels && row-rows < label_margin_top) {\n                    loop = 1;\n                    break;\n                }\n                /* Print the label if needed. */\n                if (s->label) {\n                    int label_len = strlen(s->label);\n                    int label_char = row - rows - label_margin_top;\n\n                    if (label_len > label_char) {\n                        loop = 1;\n                        chars[j] = s->label[label_char];\n                    }\n                }\n            }\n        }\n        if (loop) {\n            row++;\n            output = sdscatlen(output,chars,len);\n            output = sdscatlen(output,\"\\n\",1);\n        }\n    }\n    zfree(chars);\n    return output;\n}\n\n/* Turn a sequence into its ASCII representation */\nsds sparklineRender(sds output, struct sequence *seq, int columns, int rows, int flags) {\n    int j;\n\n    for (j = 0; j < seq->length; j += columns) {\n        int sublen = (seq->length-j) < columns ? (seq->length-j) : columns;\n\n        if (j != 0) output = sdscatlen(output,\"\\n\",1);\n        output = sparklineRenderRange(output, seq, rows, j, sublen, flags);\n    }\n    return output;\n}\n\n"
  },
  {
    "path": "extern/deprecated/redis-2.8.21/src/sparkline.h",
    "content": "/* sparkline.h -- ASCII Sparklines header file\n *\n * ---------------------------------------------------------------------------\n *\n * Copyright(C) 2011-2014 Salvatore Sanfilippo <antirez@gmail.com>\n * All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions are met:\n *\n *   * Redistributions of source code must retain the above copyright notice,\n *     this list of conditions and the following disclaimer.\n *   * Redistributions in binary form must reproduce the above copyright\n *     notice, this list of conditions and the following disclaimer in the\n *     documentation and/or other materials provided with the distribution.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\"\n * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\n * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE\n * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR\n * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF\n * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS\n * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN\n * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)\n * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE\n * POSSIBILITY OF SUCH DAMAGE.\n */\n\n#ifndef __SPARKLINE_H\n#define __SPARKLINE_H\n\n/* A sequence is represented of many \"samples\" */\nstruct sample {\n    double value;\n    char *label;\n};\n\nstruct sequence {\n    int length;\n    int labels;\n    struct sample *samples;\n    double min, max;\n};\n\n#define SPARKLINE_NO_FLAGS 0\n#define SPARKLINE_FILL 1      /* Fill the area under the curve. */\n#define SPARKLINE_LOG_SCALE 2 /* Use logarithmic scale. */\n\nstruct sequence *createSparklineSequence(void);\nvoid sparklineSequenceAddSample(struct sequence *seq, double value, char *label);\nvoid freeSparklineSequence(struct sequence *seq);\nsds sparklineRenderRange(sds output, struct sequence *seq, int rows, int offset, int len, int flags);\nsds sparklineRender(sds output, struct sequence *seq, int columns, int rows, int flags);\n\n#endif /* __SPARKLINE_H */\n"
  },
  {
    "path": "extern/deprecated/redis-2.8.21/src/syncio.c",
    "content": "/* Synchronous socket and file I/O operations useful across the core.\n *\n * Copyright (c) 2009-2010, Salvatore Sanfilippo <antirez at gmail dot com>\n * All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions are met:\n *\n *   * Redistributions of source code must retain the above copyright notice,\n *     this list of conditions and the following disclaimer.\n *   * Redistributions in binary form must reproduce the above copyright\n *     notice, this list of conditions and the following disclaimer in the\n *     documentation and/or other materials provided with the distribution.\n *   * Neither the name of Redis nor the names of its contributors may be used\n *     to endorse or promote products derived from this software without\n *     specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\"\n * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\n * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE\n * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR\n * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF\n * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS\n * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN\n * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)\n * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE\n * POSSIBILITY OF SUCH DAMAGE.\n */\n\n#include \"redis.h\"\n\n/* ----------------- Blocking sockets I/O with timeouts --------------------- */\n\n/* Redis performs most of the I/O in a nonblocking way, with the exception\n * of the SYNC command where the slave does it in a blocking way, and\n * the MIGRATE command that must be blocking in order to be atomic from the\n * point of view of the two instances (one migrating the key and one receiving\n * the key). This is why need the following blocking I/O functions.\n *\n * All the functions take the timeout in milliseconds. */\n\n#define REDIS_SYNCIO_RESOLUTION 10 /* Resolution in milliseconds */\n\n/* Write the specified payload to 'fd'. If writing the whole payload will be\n * done within 'timeout' milliseconds the operation succeeds and 'size' is\n * returned. Otherwise the operation fails, -1 is returned, and an unspecified\n * partial write could be performed against the file descriptor. */\nssize_t syncWrite(int fd, char *ptr, ssize_t size, long long timeout) {\n    ssize_t nwritten, ret = size;\n    long long start = mstime();\n    long long remaining = timeout;\n\n    while(1) {\n        long long wait = (remaining > REDIS_SYNCIO_RESOLUTION) ?\n                          remaining : REDIS_SYNCIO_RESOLUTION;\n        long long elapsed;\n\n        /* Optimistically try to write before checking if the file descriptor\n         * is actually writable. At worst we get EAGAIN. */\n        nwritten = write(fd,ptr,size);\n        if (nwritten == -1) {\n            if (errno != EAGAIN) return -1;\n        } else {\n            ptr += nwritten;\n            size -= nwritten;\n        }\n        if (size == 0) return ret;\n\n        /* Wait */\n        aeWait(fd,AE_WRITABLE,wait);\n        elapsed = mstime() - start;\n        if (elapsed >= timeout) {\n            errno = ETIMEDOUT;\n            return -1;\n        }\n        remaining = timeout - elapsed;\n    }\n}\n\n/* Read the specified amount of bytes from 'fd'. If all the bytes are read\n * within 'timeout' milliseconds the operation succeed and 'size' is returned.\n * Otherwise the operation fails, -1 is returned, and an unspecified amount of\n * data could be read from the file descriptor. */\nssize_t syncRead(int fd, char *ptr, ssize_t size, long long timeout) {\n    ssize_t nread, totread = 0;\n    long long start = mstime();\n    long long remaining = timeout;\n\n    if (size == 0) return 0;\n    while(1) {\n        long long wait = (remaining > REDIS_SYNCIO_RESOLUTION) ?\n                          remaining : REDIS_SYNCIO_RESOLUTION;\n        long long elapsed;\n\n        /* Optimistically try to read before checking if the file descriptor\n         * is actually readable. At worst we get EAGAIN. */\n        nread = read(fd,ptr,size);\n        if (nread == 0) return -1; /* short read. */\n        if (nread == -1) {\n            if (errno != EAGAIN) return -1;\n        } else {\n            ptr += nread;\n            size -= nread;\n            totread += nread;\n        }\n        if (size == 0) return totread;\n\n        /* Wait */\n        aeWait(fd,AE_READABLE,wait);\n        elapsed = mstime() - start;\n        if (elapsed >= timeout) {\n            errno = ETIMEDOUT;\n            return -1;\n        }\n        remaining = timeout - elapsed;\n    }\n}\n\n/* Read a line making sure that every char will not require more than 'timeout'\n * milliseconds to be read.\n *\n * On success the number of bytes read is returned, otherwise -1.\n * On success the string is always correctly terminated with a 0 byte. */\nssize_t syncReadLine(int fd, char *ptr, ssize_t size, long long timeout) {\n    ssize_t nread = 0;\n\n    size--;\n    while(size) {\n        char c;\n\n        if (syncRead(fd,&c,1,timeout) == -1) return -1;\n        if (c == '\\n') {\n            *ptr = '\\0';\n            if (nread && *(ptr-1) == '\\r') *(ptr-1) = '\\0';\n            return nread;\n        } else {\n            *ptr++ = c;\n            *ptr = '\\0';\n            nread++;\n        }\n        size--;\n    }\n    return nread;\n}\n"
  },
  {
    "path": "extern/deprecated/redis-2.8.21/src/t_hash.c",
    "content": "/*\n * Copyright (c) 2009-2012, Salvatore Sanfilippo <antirez at gmail dot com>\n * All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions are met:\n *\n *   * Redistributions of source code must retain the above copyright notice,\n *     this list of conditions and the following disclaimer.\n *   * Redistributions in binary form must reproduce the above copyright\n *     notice, this list of conditions and the following disclaimer in the\n *     documentation and/or other materials provided with the distribution.\n *   * Neither the name of Redis nor the names of its contributors may be used\n *     to endorse or promote products derived from this software without\n *     specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\"\n * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\n * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE\n * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR\n * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF\n * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS\n * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN\n * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)\n * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE\n * POSSIBILITY OF SUCH DAMAGE.\n */\n\n#include \"redis.h\"\n#include <math.h>\n\n/*-----------------------------------------------------------------------------\n * Hash type API\n *----------------------------------------------------------------------------*/\n\n/* Check the length of a number of objects to see if we need to convert a\n * ziplist to a real hash. Note that we only check string encoded objects\n * as their string length can be queried in constant time. */\nvoid hashTypeTryConversion(robj *o, robj **argv, int start, int end) {\n    int i;\n\n    if (o->encoding != REDIS_ENCODING_ZIPLIST) return;\n\n    for (i = start; i <= end; i++) {\n        if (argv[i]->encoding == REDIS_ENCODING_RAW &&\n            sdslen(argv[i]->ptr) > server.hash_max_ziplist_value)\n        {\n            hashTypeConvert(o, REDIS_ENCODING_HT);\n            break;\n        }\n    }\n}\n\n/* Encode given objects in-place when the hash uses a dict. */\nvoid hashTypeTryObjectEncoding(robj *subject, robj **o1, robj **o2) {\n    if (subject->encoding == REDIS_ENCODING_HT) {\n        if (o1) *o1 = tryObjectEncoding(*o1);\n        if (o2) *o2 = tryObjectEncoding(*o2);\n    }\n}\n\n/* Get the value from a ziplist encoded hash, identified by field.\n * Returns -1 when the field cannot be found. */\nint hashTypeGetFromZiplist(robj *o, robj *field,\n                           unsigned char **vstr,\n                           unsigned int *vlen,\n                           long long *vll)\n{\n    unsigned char *zl, *fptr = NULL, *vptr = NULL;\n    int ret;\n\n    redisAssert(o->encoding == REDIS_ENCODING_ZIPLIST);\n\n    field = getDecodedObject(field);\n\n    zl = o->ptr;\n    fptr = ziplistIndex(zl, ZIPLIST_HEAD);\n    if (fptr != NULL) {\n        fptr = ziplistFind(fptr, field->ptr, sdslen(field->ptr), 1);\n        if (fptr != NULL) {\n            /* Grab pointer to the value (fptr points to the field) */\n            vptr = ziplistNext(zl, fptr);\n            redisAssert(vptr != NULL);\n        }\n    }\n\n    decrRefCount(field);\n\n    if (vptr != NULL) {\n        ret = ziplistGet(vptr, vstr, vlen, vll);\n        redisAssert(ret);\n        return 0;\n    }\n\n    return -1;\n}\n\n/* Get the value from a hash table encoded hash, identified by field.\n * Returns -1 when the field cannot be found. */\nint hashTypeGetFromHashTable(robj *o, robj *field, robj **value) {\n    dictEntry *de;\n\n    redisAssert(o->encoding == REDIS_ENCODING_HT);\n\n    de = dictFind(o->ptr, field);\n    if (de == NULL) return -1;\n    *value = dictGetVal(de);\n    return 0;\n}\n\n/* Higher level function of hashTypeGet*() that always returns a Redis\n * object (either new or with refcount incremented), so that the caller\n * can retain a reference or call decrRefCount after the usage.\n *\n * The lower level function can prevent copy on write so it is\n * the preferred way of doing read operations. */\nrobj *hashTypeGetObject(robj *o, robj *field) {\n    robj *value = NULL;\n\n    if (o->encoding == REDIS_ENCODING_ZIPLIST) {\n        unsigned char *vstr = NULL;\n        unsigned int vlen = UINT_MAX;\n        long long vll = LLONG_MAX;\n\n        if (hashTypeGetFromZiplist(o, field, &vstr, &vlen, &vll) == 0) {\n            if (vstr) {\n                value = createStringObject((char*)vstr, vlen);\n            } else {\n                value = createStringObjectFromLongLong(vll);\n            }\n        }\n\n    } else if (o->encoding == REDIS_ENCODING_HT) {\n        robj *aux;\n\n        if (hashTypeGetFromHashTable(o, field, &aux) == 0) {\n            incrRefCount(aux);\n            value = aux;\n        }\n    } else {\n        redisPanic(\"Unknown hash encoding\");\n    }\n    return value;\n}\n\n/* Test if the specified field exists in the given hash. Returns 1 if the field\n * exists, and 0 when it doesn't. */\nint hashTypeExists(robj *o, robj *field) {\n    if (o->encoding == REDIS_ENCODING_ZIPLIST) {\n        unsigned char *vstr = NULL;\n        unsigned int vlen = UINT_MAX;\n        long long vll = LLONG_MAX;\n\n        if (hashTypeGetFromZiplist(o, field, &vstr, &vlen, &vll) == 0) return 1;\n    } else if (o->encoding == REDIS_ENCODING_HT) {\n        robj *aux;\n\n        if (hashTypeGetFromHashTable(o, field, &aux) == 0) return 1;\n    } else {\n        redisPanic(\"Unknown hash encoding\");\n    }\n    return 0;\n}\n\n/* Add an element, discard the old if the key already exists.\n * Return 0 on insert and 1 on update.\n * This function will take care of incrementing the reference count of the\n * retained fields and value objects. */\nint hashTypeSet(robj *o, robj *field, robj *value) {\n    int update = 0;\n\n    if (o->encoding == REDIS_ENCODING_ZIPLIST) {\n        unsigned char *zl, *fptr, *vptr;\n\n        field = getDecodedObject(field);\n        value = getDecodedObject(value);\n\n        zl = o->ptr;\n        fptr = ziplistIndex(zl, ZIPLIST_HEAD);\n        if (fptr != NULL) {\n            fptr = ziplistFind(fptr, field->ptr, sdslen(field->ptr), 1);\n            if (fptr != NULL) {\n                /* Grab pointer to the value (fptr points to the field) */\n                vptr = ziplistNext(zl, fptr);\n                redisAssert(vptr != NULL);\n                update = 1;\n\n                /* Delete value */\n                zl = ziplistDelete(zl, &vptr);\n\n                /* Insert new value */\n                zl = ziplistInsert(zl, vptr, value->ptr, sdslen(value->ptr));\n            }\n        }\n\n        if (!update) {\n            /* Push new field/value pair onto the tail of the ziplist */\n            zl = ziplistPush(zl, field->ptr, sdslen(field->ptr), ZIPLIST_TAIL);\n            zl = ziplistPush(zl, value->ptr, sdslen(value->ptr), ZIPLIST_TAIL);\n        }\n        o->ptr = zl;\n        decrRefCount(field);\n        decrRefCount(value);\n\n        /* Check if the ziplist needs to be converted to a hash table */\n        if (hashTypeLength(o) > server.hash_max_ziplist_entries)\n            hashTypeConvert(o, REDIS_ENCODING_HT);\n    } else if (o->encoding == REDIS_ENCODING_HT) {\n        if (dictReplace(o->ptr, field, value)) { /* Insert */\n            incrRefCount(field);\n        } else { /* Update */\n            update = 1;\n        }\n        incrRefCount(value);\n    } else {\n        redisPanic(\"Unknown hash encoding\");\n    }\n    return update;\n}\n\n/* Delete an element from a hash.\n * Return 1 on deleted and 0 on not found. */\nint hashTypeDelete(robj *o, robj *field) {\n    int deleted = 0;\n\n    if (o->encoding == REDIS_ENCODING_ZIPLIST) {\n        unsigned char *zl, *fptr;\n\n        field = getDecodedObject(field);\n\n        zl = o->ptr;\n        fptr = ziplistIndex(zl, ZIPLIST_HEAD);\n        if (fptr != NULL) {\n            fptr = ziplistFind(fptr, field->ptr, sdslen(field->ptr), 1);\n            if (fptr != NULL) {\n                zl = ziplistDelete(zl,&fptr);\n                zl = ziplistDelete(zl,&fptr);\n                o->ptr = zl;\n                deleted = 1;\n            }\n        }\n\n        decrRefCount(field);\n\n    } else if (o->encoding == REDIS_ENCODING_HT) {\n        if (dictDelete((dict*)o->ptr, field) == REDIS_OK) {\n            deleted = 1;\n\n            /* Always check if the dictionary needs a resize after a delete. */\n            if (htNeedsResize(o->ptr)) dictResize(o->ptr);\n        }\n\n    } else {\n        redisPanic(\"Unknown hash encoding\");\n    }\n\n    return deleted;\n}\n\n/* Return the number of elements in a hash. */\nunsigned long hashTypeLength(robj *o) {\n    unsigned long length = ULONG_MAX;\n\n    if (o->encoding == REDIS_ENCODING_ZIPLIST) {\n        length = ziplistLen(o->ptr) / 2;\n    } else if (o->encoding == REDIS_ENCODING_HT) {\n        length = dictSize((dict*)o->ptr);\n    } else {\n        redisPanic(\"Unknown hash encoding\");\n    }\n\n    return length;\n}\n\nhashTypeIterator *hashTypeInitIterator(robj *subject) {\n    hashTypeIterator *hi = zmalloc(sizeof(hashTypeIterator));\n    hi->subject = subject;\n    hi->encoding = subject->encoding;\n\n    if (hi->encoding == REDIS_ENCODING_ZIPLIST) {\n        hi->fptr = NULL;\n        hi->vptr = NULL;\n    } else if (hi->encoding == REDIS_ENCODING_HT) {\n        hi->di = dictGetIterator(subject->ptr);\n    } else {\n        redisPanic(\"Unknown hash encoding\");\n    }\n\n    return hi;\n}\n\nvoid hashTypeReleaseIterator(hashTypeIterator *hi) {\n    if (hi->encoding == REDIS_ENCODING_HT) {\n        dictReleaseIterator(hi->di);\n    }\n\n    zfree(hi);\n}\n\n/* Move to the next entry in the hash. Return REDIS_OK when the next entry\n * could be found and REDIS_ERR when the iterator reaches the end. */\nint hashTypeNext(hashTypeIterator *hi) {\n    if (hi->encoding == REDIS_ENCODING_ZIPLIST) {\n        unsigned char *zl;\n        unsigned char *fptr, *vptr;\n\n        zl = hi->subject->ptr;\n        fptr = hi->fptr;\n        vptr = hi->vptr;\n\n        if (fptr == NULL) {\n            /* Initialize cursor */\n            redisAssert(vptr == NULL);\n            fptr = ziplistIndex(zl, 0);\n        } else {\n            /* Advance cursor */\n            redisAssert(vptr != NULL);\n            fptr = ziplistNext(zl, vptr);\n        }\n        if (fptr == NULL) return REDIS_ERR;\n\n        /* Grab pointer to the value (fptr points to the field) */\n        vptr = ziplistNext(zl, fptr);\n        redisAssert(vptr != NULL);\n\n        /* fptr, vptr now point to the first or next pair */\n        hi->fptr = fptr;\n        hi->vptr = vptr;\n    } else if (hi->encoding == REDIS_ENCODING_HT) {\n        if ((hi->de = dictNext(hi->di)) == NULL) return REDIS_ERR;\n    } else {\n        redisPanic(\"Unknown hash encoding\");\n    }\n    return REDIS_OK;\n}\n\n/* Get the field or value at iterator cursor, for an iterator on a hash value\n * encoded as a ziplist. Prototype is similar to `hashTypeGetFromZiplist`. */\nvoid hashTypeCurrentFromZiplist(hashTypeIterator *hi, int what,\n                                unsigned char **vstr,\n                                unsigned int *vlen,\n                                long long *vll)\n{\n    int ret;\n\n    redisAssert(hi->encoding == REDIS_ENCODING_ZIPLIST);\n\n    if (what & REDIS_HASH_KEY) {\n        ret = ziplistGet(hi->fptr, vstr, vlen, vll);\n        redisAssert(ret);\n    } else {\n        ret = ziplistGet(hi->vptr, vstr, vlen, vll);\n        redisAssert(ret);\n    }\n}\n\n/* Get the field or value at iterator cursor, for an iterator on a hash value\n * encoded as a ziplist. Prototype is similar to `hashTypeGetFromHashTable`. */\nvoid hashTypeCurrentFromHashTable(hashTypeIterator *hi, int what, robj **dst) {\n    redisAssert(hi->encoding == REDIS_ENCODING_HT);\n\n    if (what & REDIS_HASH_KEY) {\n        *dst = dictGetKey(hi->de);\n    } else {\n        *dst = dictGetVal(hi->de);\n    }\n}\n\n/* A non copy-on-write friendly but higher level version of hashTypeCurrent*()\n * that returns an object with incremented refcount (or a new object). It is up\n * to the caller to decrRefCount() the object if no reference is retained. */\nrobj *hashTypeCurrentObject(hashTypeIterator *hi, int what) {\n    robj *dst;\n\n    if (hi->encoding == REDIS_ENCODING_ZIPLIST) {\n        unsigned char *vstr = NULL;\n        unsigned int vlen = UINT_MAX;\n        long long vll = LLONG_MAX;\n\n        hashTypeCurrentFromZiplist(hi, what, &vstr, &vlen, &vll);\n        if (vstr) {\n            dst = createStringObject((char*)vstr, vlen);\n        } else {\n            dst = createStringObjectFromLongLong(vll);\n        }\n\n    } else if (hi->encoding == REDIS_ENCODING_HT) {\n        hashTypeCurrentFromHashTable(hi, what, &dst);\n        incrRefCount(dst);\n\n    } else {\n        redisPanic(\"Unknown hash encoding\");\n    }\n\n    return dst;\n}\n\nrobj *hashTypeLookupWriteOrCreate(redisClient *c, robj *key) {\n    robj *o = lookupKeyWrite(c->db,key);\n    if (o == NULL) {\n        o = createHashObject();\n        dbAdd(c->db,key,o);\n    } else {\n        if (o->type != REDIS_HASH) {\n            addReply(c,shared.wrongtypeerr);\n            return NULL;\n        }\n    }\n    return o;\n}\n\nvoid hashTypeConvertZiplist(robj *o, int enc) {\n    redisAssert(o->encoding == REDIS_ENCODING_ZIPLIST);\n\n    if (enc == REDIS_ENCODING_ZIPLIST) {\n        /* Nothing to do... */\n\n    } else if (enc == REDIS_ENCODING_HT) {\n        hashTypeIterator *hi;\n        dict *dict;\n        int ret;\n\n        hi = hashTypeInitIterator(o);\n        dict = dictCreate(&hashDictType, NULL);\n\n        while (hashTypeNext(hi) != REDIS_ERR) {\n            robj *field, *value;\n\n            field = hashTypeCurrentObject(hi, REDIS_HASH_KEY);\n            field = tryObjectEncoding(field);\n            value = hashTypeCurrentObject(hi, REDIS_HASH_VALUE);\n            value = tryObjectEncoding(value);\n            ret = dictAdd(dict, field, value);\n            if (ret != DICT_OK) {\n                redisLogHexDump(REDIS_WARNING,\"ziplist with dup elements dump\",\n                    o->ptr,ziplistBlobLen(o->ptr));\n                redisAssert(ret == DICT_OK);\n            }\n        }\n\n        hashTypeReleaseIterator(hi);\n        zfree(o->ptr);\n\n        o->encoding = REDIS_ENCODING_HT;\n        o->ptr = dict;\n\n    } else {\n        redisPanic(\"Unknown hash encoding\");\n    }\n}\n\nvoid hashTypeConvert(robj *o, int enc) {\n    if (o->encoding == REDIS_ENCODING_ZIPLIST) {\n        hashTypeConvertZiplist(o, enc);\n    } else if (o->encoding == REDIS_ENCODING_HT) {\n        redisPanic(\"Not implemented\");\n    } else {\n        redisPanic(\"Unknown hash encoding\");\n    }\n}\n\n/*-----------------------------------------------------------------------------\n * Hash type commands\n *----------------------------------------------------------------------------*/\n\nvoid hsetCommand(redisClient *c) {\n    int update;\n    robj *o;\n\n    if ((o = hashTypeLookupWriteOrCreate(c,c->argv[1])) == NULL) return;\n    hashTypeTryConversion(o,c->argv,2,3);\n    hashTypeTryObjectEncoding(o,&c->argv[2], &c->argv[3]);\n    update = hashTypeSet(o,c->argv[2],c->argv[3]);\n    addReply(c, update ? shared.czero : shared.cone);\n    signalModifiedKey(c->db,c->argv[1]);\n    notifyKeyspaceEvent(REDIS_NOTIFY_HASH,\"hset\",c->argv[1],c->db->id);\n    server.dirty++;\n}\n\nvoid hsetnxCommand(redisClient *c) {\n    robj *o;\n    if ((o = hashTypeLookupWriteOrCreate(c,c->argv[1])) == NULL) return;\n    hashTypeTryConversion(o,c->argv,2,3);\n\n    if (hashTypeExists(o, c->argv[2])) {\n        addReply(c, shared.czero);\n    } else {\n        hashTypeTryObjectEncoding(o,&c->argv[2], &c->argv[3]);\n        hashTypeSet(o,c->argv[2],c->argv[3]);\n        addReply(c, shared.cone);\n        signalModifiedKey(c->db,c->argv[1]);\n        notifyKeyspaceEvent(REDIS_NOTIFY_HASH,\"hset\",c->argv[1],c->db->id);\n        server.dirty++;\n    }\n}\n\nvoid hmsetCommand(redisClient *c) {\n    int i;\n    robj *o;\n\n    if ((c->argc % 2) == 1) {\n        addReplyError(c,\"wrong number of arguments for HMSET\");\n        return;\n    }\n\n    if ((o = hashTypeLookupWriteOrCreate(c,c->argv[1])) == NULL) return;\n    hashTypeTryConversion(o,c->argv,2,c->argc-1);\n    for (i = 2; i < c->argc; i += 2) {\n        hashTypeTryObjectEncoding(o,&c->argv[i], &c->argv[i+1]);\n        hashTypeSet(o,c->argv[i],c->argv[i+1]);\n    }\n    addReply(c, shared.ok);\n    signalModifiedKey(c->db,c->argv[1]);\n    notifyKeyspaceEvent(REDIS_NOTIFY_HASH,\"hset\",c->argv[1],c->db->id);\n    server.dirty++;\n}\n\nvoid hincrbyCommand(redisClient *c) {\n    long long value, incr, oldvalue;\n    robj *o, *current, *new;\n\n    if (getLongLongFromObjectOrReply(c,c->argv[3],&incr,NULL) != REDIS_OK) return;\n    if ((o = hashTypeLookupWriteOrCreate(c,c->argv[1])) == NULL) return;\n    if ((current = hashTypeGetObject(o,c->argv[2])) != NULL) {\n        if (getLongLongFromObjectOrReply(c,current,&value,\n            \"hash value is not an integer\") != REDIS_OK) {\n            decrRefCount(current);\n            return;\n        }\n        decrRefCount(current);\n    } else {\n        value = 0;\n    }\n\n    oldvalue = value;\n    if ((incr < 0 && oldvalue < 0 && incr < (LLONG_MIN-oldvalue)) ||\n        (incr > 0 && oldvalue > 0 && incr > (LLONG_MAX-oldvalue))) {\n        addReplyError(c,\"increment or decrement would overflow\");\n        return;\n    }\n    value += incr;\n    new = createStringObjectFromLongLong(value);\n    hashTypeTryObjectEncoding(o,&c->argv[2],NULL);\n    hashTypeSet(o,c->argv[2],new);\n    decrRefCount(new);\n    addReplyLongLong(c,value);\n    signalModifiedKey(c->db,c->argv[1]);\n    notifyKeyspaceEvent(REDIS_NOTIFY_HASH,\"hincrby\",c->argv[1],c->db->id);\n    server.dirty++;\n}\n\nvoid hincrbyfloatCommand(redisClient *c) {\n    double long value, incr;\n    robj *o, *current, *new, *aux;\n\n    if (getLongDoubleFromObjectOrReply(c,c->argv[3],&incr,NULL) != REDIS_OK) return;\n    if ((o = hashTypeLookupWriteOrCreate(c,c->argv[1])) == NULL) return;\n    if ((current = hashTypeGetObject(o,c->argv[2])) != NULL) {\n        if (getLongDoubleFromObjectOrReply(c,current,&value,\n            \"hash value is not a valid float\") != REDIS_OK) {\n            decrRefCount(current);\n            return;\n        }\n        decrRefCount(current);\n    } else {\n        value = 0;\n    }\n\n    value += incr;\n    new = createStringObjectFromLongDouble(value,1);\n    hashTypeTryObjectEncoding(o,&c->argv[2],NULL);\n    hashTypeSet(o,c->argv[2],new);\n    addReplyBulk(c,new);\n    signalModifiedKey(c->db,c->argv[1]);\n    notifyKeyspaceEvent(REDIS_NOTIFY_HASH,\"hincrbyfloat\",c->argv[1],c->db->id);\n    server.dirty++;\n\n    /* Always replicate HINCRBYFLOAT as an HSET command with the final value\n     * in order to make sure that differences in float pricision or formatting\n     * will not create differences in replicas or after an AOF restart. */\n    aux = createStringObject(\"HSET\",4);\n    rewriteClientCommandArgument(c,0,aux);\n    decrRefCount(aux);\n    rewriteClientCommandArgument(c,3,new);\n    decrRefCount(new);\n}\n\nstatic void addHashFieldToReply(redisClient *c, robj *o, robj *field) {\n    int ret;\n\n    if (o == NULL) {\n        addReply(c, shared.nullbulk);\n        return;\n    }\n\n    if (o->encoding == REDIS_ENCODING_ZIPLIST) {\n        unsigned char *vstr = NULL;\n        unsigned int vlen = UINT_MAX;\n        long long vll = LLONG_MAX;\n\n        ret = hashTypeGetFromZiplist(o, field, &vstr, &vlen, &vll);\n        if (ret < 0) {\n            addReply(c, shared.nullbulk);\n        } else {\n            if (vstr) {\n                addReplyBulkCBuffer(c, vstr, vlen);\n            } else {\n                addReplyBulkLongLong(c, vll);\n            }\n        }\n\n    } else if (o->encoding == REDIS_ENCODING_HT) {\n        robj *value;\n\n        ret = hashTypeGetFromHashTable(o, field, &value);\n        if (ret < 0) {\n            addReply(c, shared.nullbulk);\n        } else {\n            addReplyBulk(c, value);\n        }\n\n    } else {\n        redisPanic(\"Unknown hash encoding\");\n    }\n}\n\nvoid hgetCommand(redisClient *c) {\n    robj *o;\n\n    if ((o = lookupKeyReadOrReply(c,c->argv[1],shared.nullbulk)) == NULL ||\n        checkType(c,o,REDIS_HASH)) return;\n\n    addHashFieldToReply(c, o, c->argv[2]);\n}\n\nvoid hmgetCommand(redisClient *c) {\n    robj *o;\n    int i;\n\n    /* Don't abort when the key cannot be found. Non-existing keys are empty\n     * hashes, where HMGET should respond with a series of null bulks. */\n    o = lookupKeyRead(c->db, c->argv[1]);\n    if (o != NULL && o->type != REDIS_HASH) {\n        addReply(c, shared.wrongtypeerr);\n        return;\n    }\n\n    addReplyMultiBulkLen(c, c->argc-2);\n    for (i = 2; i < c->argc; i++) {\n        addHashFieldToReply(c, o, c->argv[i]);\n    }\n}\n\nvoid hdelCommand(redisClient *c) {\n    robj *o;\n    int j, deleted = 0, keyremoved = 0;\n\n    if ((o = lookupKeyWriteOrReply(c,c->argv[1],shared.czero)) == NULL ||\n        checkType(c,o,REDIS_HASH)) return;\n\n    for (j = 2; j < c->argc; j++) {\n        if (hashTypeDelete(o,c->argv[j])) {\n            deleted++;\n            if (hashTypeLength(o) == 0) {\n                dbDelete(c->db,c->argv[1]);\n                keyremoved = 1;\n                break;\n            }\n        }\n    }\n    if (deleted) {\n        signalModifiedKey(c->db,c->argv[1]);\n        notifyKeyspaceEvent(REDIS_NOTIFY_HASH,\"hdel\",c->argv[1],c->db->id);\n        if (keyremoved)\n            notifyKeyspaceEvent(REDIS_NOTIFY_GENERIC,\"del\",c->argv[1],\n                                c->db->id);\n        server.dirty += deleted;\n    }\n    addReplyLongLong(c,deleted);\n}\n\nvoid hlenCommand(redisClient *c) {\n    robj *o;\n    if ((o = lookupKeyReadOrReply(c,c->argv[1],shared.czero)) == NULL ||\n        checkType(c,o,REDIS_HASH)) return;\n\n    addReplyLongLong(c,hashTypeLength(o));\n}\n\nstatic void addHashIteratorCursorToReply(redisClient *c, hashTypeIterator *hi, int what) {\n    if (hi->encoding == REDIS_ENCODING_ZIPLIST) {\n        unsigned char *vstr = NULL;\n        unsigned int vlen = UINT_MAX;\n        long long vll = LLONG_MAX;\n\n        hashTypeCurrentFromZiplist(hi, what, &vstr, &vlen, &vll);\n        if (vstr) {\n            addReplyBulkCBuffer(c, vstr, vlen);\n        } else {\n            addReplyBulkLongLong(c, vll);\n        }\n\n    } else if (hi->encoding == REDIS_ENCODING_HT) {\n        robj *value;\n\n        hashTypeCurrentFromHashTable(hi, what, &value);\n        addReplyBulk(c, value);\n\n    } else {\n        redisPanic(\"Unknown hash encoding\");\n    }\n}\n\nvoid genericHgetallCommand(redisClient *c, int flags) {\n    robj *o;\n    hashTypeIterator *hi;\n    int multiplier = 0;\n    int length, count = 0;\n\n    if ((o = lookupKeyReadOrReply(c,c->argv[1],shared.emptymultibulk)) == NULL\n        || checkType(c,o,REDIS_HASH)) return;\n\n    if (flags & REDIS_HASH_KEY) multiplier++;\n    if (flags & REDIS_HASH_VALUE) multiplier++;\n\n    length = hashTypeLength(o) * multiplier;\n    addReplyMultiBulkLen(c, length);\n\n    hi = hashTypeInitIterator(o);\n    while (hashTypeNext(hi) != REDIS_ERR) {\n        if (flags & REDIS_HASH_KEY) {\n            addHashIteratorCursorToReply(c, hi, REDIS_HASH_KEY);\n            count++;\n        }\n        if (flags & REDIS_HASH_VALUE) {\n            addHashIteratorCursorToReply(c, hi, REDIS_HASH_VALUE);\n            count++;\n        }\n    }\n\n    hashTypeReleaseIterator(hi);\n    redisAssert(count == length);\n}\n\nvoid hkeysCommand(redisClient *c) {\n    genericHgetallCommand(c,REDIS_HASH_KEY);\n}\n\nvoid hvalsCommand(redisClient *c) {\n    genericHgetallCommand(c,REDIS_HASH_VALUE);\n}\n\nvoid hgetallCommand(redisClient *c) {\n    genericHgetallCommand(c,REDIS_HASH_KEY|REDIS_HASH_VALUE);\n}\n\nvoid hexistsCommand(redisClient *c) {\n    robj *o;\n    if ((o = lookupKeyReadOrReply(c,c->argv[1],shared.czero)) == NULL ||\n        checkType(c,o,REDIS_HASH)) return;\n\n    addReply(c, hashTypeExists(o,c->argv[2]) ? shared.cone : shared.czero);\n}\n\nvoid hscanCommand(redisClient *c) {\n    robj *o;\n    unsigned long cursor;\n\n    if (parseScanCursorOrReply(c,c->argv[2],&cursor) == REDIS_ERR) return;\n    if ((o = lookupKeyReadOrReply(c,c->argv[1],shared.emptyscan)) == NULL ||\n        checkType(c,o,REDIS_HASH)) return;\n    scanGenericCommand(c,o,cursor);\n}\n"
  },
  {
    "path": "extern/deprecated/redis-2.8.21/src/t_list.c",
    "content": "/*\n * Copyright (c) 2009-2012, Salvatore Sanfilippo <antirez at gmail dot com>\n * All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions are met:\n *\n *   * Redistributions of source code must retain the above copyright notice,\n *     this list of conditions and the following disclaimer.\n *   * Redistributions in binary form must reproduce the above copyright\n *     notice, this list of conditions and the following disclaimer in the\n *     documentation and/or other materials provided with the distribution.\n *   * Neither the name of Redis nor the names of its contributors may be used\n *     to endorse or promote products derived from this software without\n *     specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\"\n * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\n * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE\n * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR\n * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF\n * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS\n * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN\n * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)\n * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE\n * POSSIBILITY OF SUCH DAMAGE.\n */\n\n#include \"redis.h\"\n\n/*-----------------------------------------------------------------------------\n * List API\n *----------------------------------------------------------------------------*/\n\n/* Check the argument length to see if it requires us to convert the ziplist\n * to a real list. Only check raw-encoded objects because integer encoded\n * objects are never too long. */\nvoid listTypeTryConversion(robj *subject, robj *value) {\n    if (subject->encoding != REDIS_ENCODING_ZIPLIST) return;\n    if (value->encoding == REDIS_ENCODING_RAW &&\n        sdslen(value->ptr) > server.list_max_ziplist_value)\n            listTypeConvert(subject,REDIS_ENCODING_LINKEDLIST);\n}\n\n/* The function pushes an element to the specified list object 'subject',\n * at head or tail position as specified by 'where'.\n *\n * There is no need for the caller to increment the refcount of 'value' as\n * the function takes care of it if needed. */\nvoid listTypePush(robj *subject, robj *value, int where) {\n    /* Check if we need to convert the ziplist */\n    listTypeTryConversion(subject,value);\n    if (subject->encoding == REDIS_ENCODING_ZIPLIST &&\n        ziplistLen(subject->ptr) >= server.list_max_ziplist_entries)\n            listTypeConvert(subject,REDIS_ENCODING_LINKEDLIST);\n\n    if (subject->encoding == REDIS_ENCODING_ZIPLIST) {\n        int pos = (where == REDIS_HEAD) ? ZIPLIST_HEAD : ZIPLIST_TAIL;\n        value = getDecodedObject(value);\n        subject->ptr = ziplistPush(subject->ptr,value->ptr,sdslen(value->ptr),pos);\n        decrRefCount(value);\n    } else if (subject->encoding == REDIS_ENCODING_LINKEDLIST) {\n        if (where == REDIS_HEAD) {\n            listAddNodeHead(subject->ptr,value);\n        } else {\n            listAddNodeTail(subject->ptr,value);\n        }\n        incrRefCount(value);\n    } else {\n        redisPanic(\"Unknown list encoding\");\n    }\n}\n\nrobj *listTypePop(robj *subject, int where) {\n    robj *value = NULL;\n    if (subject->encoding == REDIS_ENCODING_ZIPLIST) {\n        unsigned char *p;\n        unsigned char *vstr;\n        unsigned int vlen;\n        long long vlong;\n        int pos = (where == REDIS_HEAD) ? 0 : -1;\n        p = ziplistIndex(subject->ptr,pos);\n        if (ziplistGet(p,&vstr,&vlen,&vlong)) {\n            if (vstr) {\n                value = createStringObject((char*)vstr,vlen);\n            } else {\n                value = createStringObjectFromLongLong(vlong);\n            }\n            /* We only need to delete an element when it exists */\n            subject->ptr = ziplistDelete(subject->ptr,&p);\n        }\n    } else if (subject->encoding == REDIS_ENCODING_LINKEDLIST) {\n        list *list = subject->ptr;\n        listNode *ln;\n        if (where == REDIS_HEAD) {\n            ln = listFirst(list);\n        } else {\n            ln = listLast(list);\n        }\n        if (ln != NULL) {\n            value = listNodeValue(ln);\n            incrRefCount(value);\n            listDelNode(list,ln);\n        }\n    } else {\n        redisPanic(\"Unknown list encoding\");\n    }\n    return value;\n}\n\nunsigned long listTypeLength(robj *subject) {\n    if (subject->encoding == REDIS_ENCODING_ZIPLIST) {\n        return ziplistLen(subject->ptr);\n    } else if (subject->encoding == REDIS_ENCODING_LINKEDLIST) {\n        return listLength((list*)subject->ptr);\n    } else {\n        redisPanic(\"Unknown list encoding\");\n    }\n}\n\n/* Initialize an iterator at the specified index. */\nlistTypeIterator *listTypeInitIterator(robj *subject, long index, unsigned char direction) {\n    listTypeIterator *li = zmalloc(sizeof(listTypeIterator));\n    li->subject = subject;\n    li->encoding = subject->encoding;\n    li->direction = direction;\n    if (li->encoding == REDIS_ENCODING_ZIPLIST) {\n        li->zi = ziplistIndex(subject->ptr,index);\n    } else if (li->encoding == REDIS_ENCODING_LINKEDLIST) {\n        li->ln = listIndex(subject->ptr,index);\n    } else {\n        redisPanic(\"Unknown list encoding\");\n    }\n    return li;\n}\n\n/* Clean up the iterator. */\nvoid listTypeReleaseIterator(listTypeIterator *li) {\n    zfree(li);\n}\n\n/* Stores pointer to current the entry in the provided entry structure\n * and advances the position of the iterator. Returns 1 when the current\n * entry is in fact an entry, 0 otherwise. */\nint listTypeNext(listTypeIterator *li, listTypeEntry *entry) {\n    /* Protect from converting when iterating */\n    redisAssert(li->subject->encoding == li->encoding);\n\n    entry->li = li;\n    if (li->encoding == REDIS_ENCODING_ZIPLIST) {\n        entry->zi = li->zi;\n        if (entry->zi != NULL) {\n            if (li->direction == REDIS_TAIL)\n                li->zi = ziplistNext(li->subject->ptr,li->zi);\n            else\n                li->zi = ziplistPrev(li->subject->ptr,li->zi);\n            return 1;\n        }\n    } else if (li->encoding == REDIS_ENCODING_LINKEDLIST) {\n        entry->ln = li->ln;\n        if (entry->ln != NULL) {\n            if (li->direction == REDIS_TAIL)\n                li->ln = li->ln->next;\n            else\n                li->ln = li->ln->prev;\n            return 1;\n        }\n    } else {\n        redisPanic(\"Unknown list encoding\");\n    }\n    return 0;\n}\n\n/* Return entry or NULL at the current position of the iterator. */\nrobj *listTypeGet(listTypeEntry *entry) {\n    listTypeIterator *li = entry->li;\n    robj *value = NULL;\n    if (li->encoding == REDIS_ENCODING_ZIPLIST) {\n        unsigned char *vstr;\n        unsigned int vlen;\n        long long vlong;\n        redisAssert(entry->zi != NULL);\n        if (ziplistGet(entry->zi,&vstr,&vlen,&vlong)) {\n            if (vstr) {\n                value = createStringObject((char*)vstr,vlen);\n            } else {\n                value = createStringObjectFromLongLong(vlong);\n            }\n        }\n    } else if (li->encoding == REDIS_ENCODING_LINKEDLIST) {\n        redisAssert(entry->ln != NULL);\n        value = listNodeValue(entry->ln);\n        incrRefCount(value);\n    } else {\n        redisPanic(\"Unknown list encoding\");\n    }\n    return value;\n}\n\nvoid listTypeInsert(listTypeEntry *entry, robj *value, int where) {\n    robj *subject = entry->li->subject;\n    if (entry->li->encoding == REDIS_ENCODING_ZIPLIST) {\n        value = getDecodedObject(value);\n        if (where == REDIS_TAIL) {\n            unsigned char *next = ziplistNext(subject->ptr,entry->zi);\n\n            /* When we insert after the current element, but the current element\n             * is the tail of the list, we need to do a push. */\n            if (next == NULL) {\n                subject->ptr = ziplistPush(subject->ptr,value->ptr,sdslen(value->ptr),REDIS_TAIL);\n            } else {\n                subject->ptr = ziplistInsert(subject->ptr,next,value->ptr,sdslen(value->ptr));\n            }\n        } else {\n            subject->ptr = ziplistInsert(subject->ptr,entry->zi,value->ptr,sdslen(value->ptr));\n        }\n        decrRefCount(value);\n    } else if (entry->li->encoding == REDIS_ENCODING_LINKEDLIST) {\n        if (where == REDIS_TAIL) {\n            listInsertNode(subject->ptr,entry->ln,value,AL_START_TAIL);\n        } else {\n            listInsertNode(subject->ptr,entry->ln,value,AL_START_HEAD);\n        }\n        incrRefCount(value);\n    } else {\n        redisPanic(\"Unknown list encoding\");\n    }\n}\n\n/* Compare the given object with the entry at the current position. */\nint listTypeEqual(listTypeEntry *entry, robj *o) {\n    listTypeIterator *li = entry->li;\n    if (li->encoding == REDIS_ENCODING_ZIPLIST) {\n        redisAssertWithInfo(NULL,o,o->encoding == REDIS_ENCODING_RAW);\n        return ziplistCompare(entry->zi,o->ptr,sdslen(o->ptr));\n    } else if (li->encoding == REDIS_ENCODING_LINKEDLIST) {\n        return equalStringObjects(o,listNodeValue(entry->ln));\n    } else {\n        redisPanic(\"Unknown list encoding\");\n    }\n}\n\n/* Delete the element pointed to. */\nvoid listTypeDelete(listTypeEntry *entry) {\n    listTypeIterator *li = entry->li;\n    if (li->encoding == REDIS_ENCODING_ZIPLIST) {\n        unsigned char *p = entry->zi;\n        li->subject->ptr = ziplistDelete(li->subject->ptr,&p);\n\n        /* Update position of the iterator depending on the direction */\n        if (li->direction == REDIS_TAIL)\n            li->zi = p;\n        else\n            li->zi = ziplistPrev(li->subject->ptr,p);\n    } else if (entry->li->encoding == REDIS_ENCODING_LINKEDLIST) {\n        listNode *next;\n        if (li->direction == REDIS_TAIL)\n            next = entry->ln->next;\n        else\n            next = entry->ln->prev;\n        listDelNode(li->subject->ptr,entry->ln);\n        li->ln = next;\n    } else {\n        redisPanic(\"Unknown list encoding\");\n    }\n}\n\nvoid listTypeConvert(robj *subject, int enc) {\n    listTypeIterator *li;\n    listTypeEntry entry;\n    redisAssertWithInfo(NULL,subject,subject->type == REDIS_LIST);\n\n    if (enc == REDIS_ENCODING_LINKEDLIST) {\n        list *l = listCreate();\n        listSetFreeMethod(l,decrRefCountVoid);\n\n        /* listTypeGet returns a robj with incremented refcount */\n        li = listTypeInitIterator(subject,0,REDIS_TAIL);\n        while (listTypeNext(li,&entry)) listAddNodeTail(l,listTypeGet(&entry));\n        listTypeReleaseIterator(li);\n\n        subject->encoding = REDIS_ENCODING_LINKEDLIST;\n        zfree(subject->ptr);\n        subject->ptr = l;\n    } else {\n        redisPanic(\"Unsupported list conversion\");\n    }\n}\n\n/*-----------------------------------------------------------------------------\n * List Commands\n *----------------------------------------------------------------------------*/\n\nvoid pushGenericCommand(redisClient *c, int where) {\n    int j, waiting = 0, pushed = 0;\n    robj *lobj = lookupKeyWrite(c->db,c->argv[1]);\n\n    if (lobj && lobj->type != REDIS_LIST) {\n        addReply(c,shared.wrongtypeerr);\n        return;\n    }\n\n    for (j = 2; j < c->argc; j++) {\n        c->argv[j] = tryObjectEncoding(c->argv[j]);\n        if (!lobj) {\n            lobj = createZiplistObject();\n            dbAdd(c->db,c->argv[1],lobj);\n        }\n        listTypePush(lobj,c->argv[j],where);\n        pushed++;\n    }\n    addReplyLongLong(c, waiting + (lobj ? listTypeLength(lobj) : 0));\n    if (pushed) {\n        char *event = (where == REDIS_HEAD) ? \"lpush\" : \"rpush\";\n\n        signalModifiedKey(c->db,c->argv[1]);\n        notifyKeyspaceEvent(REDIS_NOTIFY_LIST,event,c->argv[1],c->db->id);\n    }\n    server.dirty += pushed;\n}\n\nvoid lpushCommand(redisClient *c) {\n    pushGenericCommand(c,REDIS_HEAD);\n}\n\nvoid rpushCommand(redisClient *c) {\n    pushGenericCommand(c,REDIS_TAIL);\n}\n\nvoid pushxGenericCommand(redisClient *c, robj *refval, robj *val, int where) {\n    robj *subject;\n    listTypeIterator *iter;\n    listTypeEntry entry;\n    int inserted = 0;\n\n    if ((subject = lookupKeyReadOrReply(c,c->argv[1],shared.czero)) == NULL ||\n        checkType(c,subject,REDIS_LIST)) return;\n\n    if (refval != NULL) {\n        /* We're not sure if this value can be inserted yet, but we cannot\n         * convert the list inside the iterator. We don't want to loop over\n         * the list twice (once to see if the value can be inserted and once\n         * to do the actual insert), so we assume this value can be inserted\n         * and convert the ziplist to a regular list if necessary. */\n        listTypeTryConversion(subject,val);\n\n        /* Seek refval from head to tail */\n        iter = listTypeInitIterator(subject,0,REDIS_TAIL);\n        while (listTypeNext(iter,&entry)) {\n            if (listTypeEqual(&entry,refval)) {\n                listTypeInsert(&entry,val,where);\n                inserted = 1;\n                break;\n            }\n        }\n        listTypeReleaseIterator(iter);\n\n        if (inserted) {\n            /* Check if the length exceeds the ziplist length threshold. */\n            if (subject->encoding == REDIS_ENCODING_ZIPLIST &&\n                ziplistLen(subject->ptr) > server.list_max_ziplist_entries)\n                    listTypeConvert(subject,REDIS_ENCODING_LINKEDLIST);\n            signalModifiedKey(c->db,c->argv[1]);\n            notifyKeyspaceEvent(REDIS_NOTIFY_LIST,\"linsert\",\n                                c->argv[1],c->db->id);\n            server.dirty++;\n        } else {\n            /* Notify client of a failed insert */\n            addReply(c,shared.cnegone);\n            return;\n        }\n    } else {\n        char *event = (where == REDIS_HEAD) ? \"lpush\" : \"rpush\";\n\n        listTypePush(subject,val,where);\n        signalModifiedKey(c->db,c->argv[1]);\n        notifyKeyspaceEvent(REDIS_NOTIFY_LIST,event,c->argv[1],c->db->id);\n        server.dirty++;\n    }\n\n    addReplyLongLong(c,listTypeLength(subject));\n}\n\nvoid lpushxCommand(redisClient *c) {\n    c->argv[2] = tryObjectEncoding(c->argv[2]);\n    pushxGenericCommand(c,NULL,c->argv[2],REDIS_HEAD);\n}\n\nvoid rpushxCommand(redisClient *c) {\n    c->argv[2] = tryObjectEncoding(c->argv[2]);\n    pushxGenericCommand(c,NULL,c->argv[2],REDIS_TAIL);\n}\n\nvoid linsertCommand(redisClient *c) {\n    c->argv[4] = tryObjectEncoding(c->argv[4]);\n    if (strcasecmp(c->argv[2]->ptr,\"after\") == 0) {\n        pushxGenericCommand(c,c->argv[3],c->argv[4],REDIS_TAIL);\n    } else if (strcasecmp(c->argv[2]->ptr,\"before\") == 0) {\n        pushxGenericCommand(c,c->argv[3],c->argv[4],REDIS_HEAD);\n    } else {\n        addReply(c,shared.syntaxerr);\n    }\n}\n\nvoid llenCommand(redisClient *c) {\n    robj *o = lookupKeyReadOrReply(c,c->argv[1],shared.czero);\n    if (o == NULL || checkType(c,o,REDIS_LIST)) return;\n    addReplyLongLong(c,listTypeLength(o));\n}\n\nvoid lindexCommand(redisClient *c) {\n    robj *o = lookupKeyReadOrReply(c,c->argv[1],shared.nullbulk);\n    if (o == NULL || checkType(c,o,REDIS_LIST)) return;\n    long index;\n    robj *value = NULL;\n\n    if ((getLongFromObjectOrReply(c, c->argv[2], &index, NULL) != REDIS_OK))\n        return;\n\n    if (o->encoding == REDIS_ENCODING_ZIPLIST) {\n        unsigned char *p;\n        unsigned char *vstr;\n        unsigned int vlen;\n        long long vlong;\n        p = ziplistIndex(o->ptr,index);\n        if (ziplistGet(p,&vstr,&vlen,&vlong)) {\n            if (vstr) {\n                value = createStringObject((char*)vstr,vlen);\n            } else {\n                value = createStringObjectFromLongLong(vlong);\n            }\n            addReplyBulk(c,value);\n            decrRefCount(value);\n        } else {\n            addReply(c,shared.nullbulk);\n        }\n    } else if (o->encoding == REDIS_ENCODING_LINKEDLIST) {\n        listNode *ln = listIndex(o->ptr,index);\n        if (ln != NULL) {\n            value = listNodeValue(ln);\n            addReplyBulk(c,value);\n        } else {\n            addReply(c,shared.nullbulk);\n        }\n    } else {\n        redisPanic(\"Unknown list encoding\");\n    }\n}\n\nvoid lsetCommand(redisClient *c) {\n    robj *o = lookupKeyWriteOrReply(c,c->argv[1],shared.nokeyerr);\n    if (o == NULL || checkType(c,o,REDIS_LIST)) return;\n    long index;\n    robj *value = (c->argv[3] = tryObjectEncoding(c->argv[3]));\n\n    if ((getLongFromObjectOrReply(c, c->argv[2], &index, NULL) != REDIS_OK))\n        return;\n\n    listTypeTryConversion(o,value);\n    if (o->encoding == REDIS_ENCODING_ZIPLIST) {\n        unsigned char *p, *zl = o->ptr;\n        p = ziplistIndex(zl,index);\n        if (p == NULL) {\n            addReply(c,shared.outofrangeerr);\n        } else {\n            o->ptr = ziplistDelete(o->ptr,&p);\n            value = getDecodedObject(value);\n            o->ptr = ziplistInsert(o->ptr,p,value->ptr,sdslen(value->ptr));\n            decrRefCount(value);\n            addReply(c,shared.ok);\n            signalModifiedKey(c->db,c->argv[1]);\n            notifyKeyspaceEvent(REDIS_NOTIFY_LIST,\"lset\",c->argv[1],c->db->id);\n            server.dirty++;\n        }\n    } else if (o->encoding == REDIS_ENCODING_LINKEDLIST) {\n        listNode *ln = listIndex(o->ptr,index);\n        if (ln == NULL) {\n            addReply(c,shared.outofrangeerr);\n        } else {\n            decrRefCount((robj*)listNodeValue(ln));\n            listNodeValue(ln) = value;\n            incrRefCount(value);\n            addReply(c,shared.ok);\n            signalModifiedKey(c->db,c->argv[1]);\n            notifyKeyspaceEvent(REDIS_NOTIFY_LIST,\"lset\",c->argv[1],c->db->id);\n            server.dirty++;\n        }\n    } else {\n        redisPanic(\"Unknown list encoding\");\n    }\n}\n\nvoid popGenericCommand(redisClient *c, int where) {\n    robj *o = lookupKeyWriteOrReply(c,c->argv[1],shared.nullbulk);\n    if (o == NULL || checkType(c,o,REDIS_LIST)) return;\n\n    robj *value = listTypePop(o,where);\n    if (value == NULL) {\n        addReply(c,shared.nullbulk);\n    } else {\n        char *event = (where == REDIS_HEAD) ? \"lpop\" : \"rpop\";\n\n        addReplyBulk(c,value);\n        decrRefCount(value);\n        notifyKeyspaceEvent(REDIS_NOTIFY_LIST,event,c->argv[1],c->db->id);\n        if (listTypeLength(o) == 0) {\n            notifyKeyspaceEvent(REDIS_NOTIFY_GENERIC,\"del\",\n                                c->argv[1],c->db->id);\n            dbDelete(c->db,c->argv[1]);\n        }\n        signalModifiedKey(c->db,c->argv[1]);\n        server.dirty++;\n    }\n}\n\nvoid lpopCommand(redisClient *c) {\n    popGenericCommand(c,REDIS_HEAD);\n}\n\nvoid rpopCommand(redisClient *c) {\n    popGenericCommand(c,REDIS_TAIL);\n}\n\nvoid lrangeCommand(redisClient *c) {\n    robj *o;\n    long start, end, llen, rangelen;\n\n    if ((getLongFromObjectOrReply(c, c->argv[2], &start, NULL) != REDIS_OK) ||\n        (getLongFromObjectOrReply(c, c->argv[3], &end, NULL) != REDIS_OK)) return;\n\n    if ((o = lookupKeyReadOrReply(c,c->argv[1],shared.emptymultibulk)) == NULL\n         || checkType(c,o,REDIS_LIST)) return;\n    llen = listTypeLength(o);\n\n    /* convert negative indexes */\n    if (start < 0) start = llen+start;\n    if (end < 0) end = llen+end;\n    if (start < 0) start = 0;\n\n    /* Invariant: start >= 0, so this test will be true when end < 0.\n     * The range is empty when start > end or start >= length. */\n    if (start > end || start >= llen) {\n        addReply(c,shared.emptymultibulk);\n        return;\n    }\n    if (end >= llen) end = llen-1;\n    rangelen = (end-start)+1;\n\n    /* Return the result in form of a multi-bulk reply */\n    addReplyMultiBulkLen(c,rangelen);\n    if (o->encoding == REDIS_ENCODING_ZIPLIST) {\n        unsigned char *p = ziplistIndex(o->ptr,start);\n        unsigned char *vstr;\n        unsigned int vlen;\n        long long vlong;\n\n        while(rangelen--) {\n            ziplistGet(p,&vstr,&vlen,&vlong);\n            if (vstr) {\n                addReplyBulkCBuffer(c,vstr,vlen);\n            } else {\n                addReplyBulkLongLong(c,vlong);\n            }\n            p = ziplistNext(o->ptr,p);\n        }\n    } else if (o->encoding == REDIS_ENCODING_LINKEDLIST) {\n        listNode *ln;\n\n        /* If we are nearest to the end of the list, reach the element\n         * starting from tail and going backward, as it is faster. */\n        if (start > llen/2) start -= llen;\n        ln = listIndex(o->ptr,start);\n\n        while(rangelen--) {\n            addReplyBulk(c,ln->value);\n            ln = ln->next;\n        }\n    } else {\n        redisPanic(\"List encoding is not LINKEDLIST nor ZIPLIST!\");\n    }\n}\n\nvoid ltrimCommand(redisClient *c) {\n    robj *o;\n    long start, end, llen, j, ltrim, rtrim;\n    list *list;\n    listNode *ln;\n\n    if ((getLongFromObjectOrReply(c, c->argv[2], &start, NULL) != REDIS_OK) ||\n        (getLongFromObjectOrReply(c, c->argv[3], &end, NULL) != REDIS_OK)) return;\n\n    if ((o = lookupKeyWriteOrReply(c,c->argv[1],shared.ok)) == NULL ||\n        checkType(c,o,REDIS_LIST)) return;\n    llen = listTypeLength(o);\n\n    /* convert negative indexes */\n    if (start < 0) start = llen+start;\n    if (end < 0) end = llen+end;\n    if (start < 0) start = 0;\n\n    /* Invariant: start >= 0, so this test will be true when end < 0.\n     * The range is empty when start > end or start >= length. */\n    if (start > end || start >= llen) {\n        /* Out of range start or start > end result in empty list */\n        ltrim = llen;\n        rtrim = 0;\n    } else {\n        if (end >= llen) end = llen-1;\n        ltrim = start;\n        rtrim = llen-end-1;\n    }\n\n    /* Remove list elements to perform the trim */\n    if (o->encoding == REDIS_ENCODING_ZIPLIST) {\n        o->ptr = ziplistDeleteRange(o->ptr,0,ltrim);\n        o->ptr = ziplistDeleteRange(o->ptr,-rtrim,rtrim);\n    } else if (o->encoding == REDIS_ENCODING_LINKEDLIST) {\n        list = o->ptr;\n        for (j = 0; j < ltrim; j++) {\n            ln = listFirst(list);\n            listDelNode(list,ln);\n        }\n        for (j = 0; j < rtrim; j++) {\n            ln = listLast(list);\n            listDelNode(list,ln);\n        }\n    } else {\n        redisPanic(\"Unknown list encoding\");\n    }\n\n    notifyKeyspaceEvent(REDIS_NOTIFY_LIST,\"ltrim\",c->argv[1],c->db->id);\n    if (listTypeLength(o) == 0) {\n        dbDelete(c->db,c->argv[1]);\n        notifyKeyspaceEvent(REDIS_NOTIFY_GENERIC,\"del\",c->argv[1],c->db->id);\n    }\n    signalModifiedKey(c->db,c->argv[1]);\n    server.dirty++;\n    addReply(c,shared.ok);\n}\n\nvoid lremCommand(redisClient *c) {\n    robj *subject, *obj;\n    obj = c->argv[3] = tryObjectEncoding(c->argv[3]);\n    long toremove;\n    long removed = 0;\n    listTypeEntry entry;\n\n    if ((getLongFromObjectOrReply(c, c->argv[2], &toremove, NULL) != REDIS_OK))\n        return;\n\n    subject = lookupKeyWriteOrReply(c,c->argv[1],shared.czero);\n    if (subject == NULL || checkType(c,subject,REDIS_LIST)) return;\n\n    /* Make sure obj is raw when we're dealing with a ziplist */\n    if (subject->encoding == REDIS_ENCODING_ZIPLIST)\n        obj = getDecodedObject(obj);\n\n    listTypeIterator *li;\n    if (toremove < 0) {\n        toremove = -toremove;\n        li = listTypeInitIterator(subject,-1,REDIS_HEAD);\n    } else {\n        li = listTypeInitIterator(subject,0,REDIS_TAIL);\n    }\n\n    while (listTypeNext(li,&entry)) {\n        if (listTypeEqual(&entry,obj)) {\n            listTypeDelete(&entry);\n            server.dirty++;\n            removed++;\n            if (toremove && removed == toremove) break;\n        }\n    }\n    listTypeReleaseIterator(li);\n\n    /* Clean up raw encoded object */\n    if (subject->encoding == REDIS_ENCODING_ZIPLIST)\n        decrRefCount(obj);\n\n    if (listTypeLength(subject) == 0) dbDelete(c->db,c->argv[1]);\n    addReplyLongLong(c,removed);\n    if (removed) signalModifiedKey(c->db,c->argv[1]);\n}\n\n/* This is the semantic of this command:\n *  RPOPLPUSH srclist dstlist:\n *    IF LLEN(srclist) > 0\n *      element = RPOP srclist\n *      LPUSH dstlist element\n *      RETURN element\n *    ELSE\n *      RETURN nil\n *    END\n *  END\n *\n * The idea is to be able to get an element from a list in a reliable way\n * since the element is not just returned but pushed against another list\n * as well. This command was originally proposed by Ezra Zygmuntowicz.\n */\n\nvoid rpoplpushHandlePush(redisClient *c, robj *dstkey, robj *dstobj, robj *value) {\n    /* Create the list if the key does not exist */\n    if (!dstobj) {\n        dstobj = createZiplistObject();\n        dbAdd(c->db,dstkey,dstobj);\n    }\n    signalModifiedKey(c->db,dstkey);\n    listTypePush(dstobj,value,REDIS_HEAD);\n    notifyKeyspaceEvent(REDIS_NOTIFY_LIST,\"lpush\",dstkey,c->db->id);\n    /* Always send the pushed value to the client. */\n    addReplyBulk(c,value);\n}\n\nvoid rpoplpushCommand(redisClient *c) {\n    robj *sobj, *value;\n    if ((sobj = lookupKeyWriteOrReply(c,c->argv[1],shared.nullbulk)) == NULL ||\n        checkType(c,sobj,REDIS_LIST)) return;\n\n    if (listTypeLength(sobj) == 0) {\n        /* This may only happen after loading very old RDB files. Recent\n         * versions of Redis delete keys of empty lists. */\n        addReply(c,shared.nullbulk);\n    } else {\n        robj *dobj = lookupKeyWrite(c->db,c->argv[2]);\n        robj *touchedkey = c->argv[1];\n\n        if (dobj && checkType(c,dobj,REDIS_LIST)) return;\n        value = listTypePop(sobj,REDIS_TAIL);\n        /* We saved touched key, and protect it, since rpoplpushHandlePush\n         * may change the client command argument vector (it does not\n         * currently). */\n        incrRefCount(touchedkey);\n        rpoplpushHandlePush(c,c->argv[2],dobj,value);\n\n        /* listTypePop returns an object with its refcount incremented */\n        decrRefCount(value);\n\n        /* Delete the source list when it is empty */\n        notifyKeyspaceEvent(REDIS_NOTIFY_LIST,\"rpop\",touchedkey,c->db->id);\n        if (listTypeLength(sobj) == 0) {\n            dbDelete(c->db,touchedkey);\n            notifyKeyspaceEvent(REDIS_NOTIFY_GENERIC,\"del\",\n                                touchedkey,c->db->id);\n        }\n        signalModifiedKey(c->db,touchedkey);\n        decrRefCount(touchedkey);\n        server.dirty++;\n    }\n}\n\n/*-----------------------------------------------------------------------------\n * Blocking POP operations\n *----------------------------------------------------------------------------*/\n\n/* This is how the current blocking POP works, we use BLPOP as example:\n * - If the user calls BLPOP and the key exists and contains a non empty list\n *   then LPOP is called instead. So BLPOP is semantically the same as LPOP\n *   if blocking is not required.\n * - If instead BLPOP is called and the key does not exists or the list is\n *   empty we need to block. In order to do so we remove the notification for\n *   new data to read in the client socket (so that we'll not serve new\n *   requests if the blocking request is not served). Also we put the client\n *   in a dictionary (db->blocking_keys) mapping keys to a list of clients\n *   blocking for this keys.\n * - If a PUSH operation against a key with blocked clients waiting is\n *   performed, we mark this key as \"ready\", and after the current command,\n *   MULTI/EXEC block, or script, is executed, we serve all the clients waiting\n *   for this list, from the one that blocked first, to the last, accordingly\n *   to the number of elements we have in the ready list.\n */\n\n/* Set a client in blocking mode for the specified key, with the specified\n * timeout */\nvoid blockForKeys(redisClient *c, robj **keys, int numkeys, time_t timeout, robj *target) {\n    dictEntry *de;\n    list *l;\n    int j;\n\n    c->bpop.timeout = timeout;\n    c->bpop.target = target;\n\n    if (target != NULL) incrRefCount(target);\n\n    for (j = 0; j < numkeys; j++) {\n        /* If the key already exists in the dict ignore it. */\n        if (dictAdd(c->bpop.keys,keys[j],NULL) != DICT_OK) continue;\n        incrRefCount(keys[j]);\n\n        /* And in the other \"side\", to map keys -> clients */\n        de = dictFind(c->db->blocking_keys,keys[j]);\n        if (de == NULL) {\n            int retval;\n\n            /* For every key we take a list of clients blocked for it */\n            l = listCreate();\n            retval = dictAdd(c->db->blocking_keys,keys[j],l);\n            incrRefCount(keys[j]);\n            redisAssertWithInfo(c,keys[j],retval == DICT_OK);\n        } else {\n            l = dictGetVal(de);\n        }\n        listAddNodeTail(l,c);\n    }\n\n    /* Mark the client as a blocked client */\n    c->flags |= REDIS_BLOCKED;\n    server.bpop_blocked_clients++;\n}\n\n/* Unblock a client that's waiting in a blocking operation such as BLPOP */\nvoid unblockClientWaitingData(redisClient *c) {\n    dictEntry *de;\n    dictIterator *di;\n    list *l;\n\n    redisAssertWithInfo(c,NULL,dictSize(c->bpop.keys) != 0);\n    di = dictGetIterator(c->bpop.keys);\n    /* The client may wait for multiple keys, so unblock it for every key. */\n    while((de = dictNext(di)) != NULL) {\n        robj *key = dictGetKey(de);\n\n        /* Remove this client from the list of clients waiting for this key. */\n        l = dictFetchValue(c->db->blocking_keys,key);\n        redisAssertWithInfo(c,key,l != NULL);\n        listDelNode(l,listSearchKey(l,c));\n        /* If the list is empty we need to remove it to avoid wasting memory */\n        if (listLength(l) == 0)\n            dictDelete(c->db->blocking_keys,key);\n    }\n    dictReleaseIterator(di);\n\n    /* Cleanup the client structure */\n    dictEmpty(c->bpop.keys,NULL);\n    if (c->bpop.target) {\n        decrRefCount(c->bpop.target);\n        c->bpop.target = NULL;\n    }\n    c->flags &= ~REDIS_BLOCKED;\n    c->flags |= REDIS_UNBLOCKED;\n    server.bpop_blocked_clients--;\n    listAddNodeTail(server.unblocked_clients,c);\n}\n\n/* If the specified key has clients blocked waiting for list pushes, this\n * function will put the key reference into the server.ready_keys list.\n * Note that db->ready_keys is a hash table that allows us to avoid putting\n * the same key again and again in the list in case of multiple pushes\n * made by a script or in the context of MULTI/EXEC.\n *\n * The list will be finally processed by handleClientsBlockedOnLists() */\nvoid signalListAsReady(redisDb *db, robj *key) {\n    readyList *rl;\n\n    /* No clients blocking for this key? No need to queue it. */\n    if (dictFind(db->blocking_keys,key) == NULL) return;\n\n    /* Key was already signaled? No need to queue it again. */\n    if (dictFind(db->ready_keys,key) != NULL) return;\n\n    /* Ok, we need to queue this key into server.ready_keys. */\n    rl = zmalloc(sizeof(*rl));\n    rl->key = key;\n    rl->db = db;\n    incrRefCount(key);\n    listAddNodeTail(server.ready_keys,rl);\n\n    /* We also add the key in the db->ready_keys dictionary in order\n     * to avoid adding it multiple times into a list with a simple O(1)\n     * check. */\n    incrRefCount(key);\n    redisAssert(dictAdd(db->ready_keys,key,NULL) == DICT_OK);\n}\n\n/* This is a helper function for handleClientsBlockedOnLists(). It's work\n * is to serve a specific client (receiver) that is blocked on 'key'\n * in the context of the specified 'db', doing the following:\n *\n * 1) Provide the client with the 'value' element.\n * 2) If the dstkey is not NULL (we are serving a BRPOPLPUSH) also push the\n *    'value' element on the destination list (the LPUSH side of the command).\n * 3) Propagate the resulting BRPOP, BLPOP and additional LPUSH if any into\n *    the AOF and replication channel.\n *\n * The argument 'where' is REDIS_TAIL or REDIS_HEAD, and indicates if the\n * 'value' element was popped fron the head (BLPOP) or tail (BRPOP) so that\n * we can propagate the command properly.\n *\n * The function returns REDIS_OK if we are able to serve the client, otherwise\n * REDIS_ERR is returned to signal the caller that the list POP operation\n * should be undone as the client was not served: This only happens for\n * BRPOPLPUSH that fails to push the value to the destination key as it is\n * of the wrong type. */\nint serveClientBlockedOnList(redisClient *receiver, robj *key, robj *dstkey, redisDb *db, robj *value, int where)\n{\n    robj *argv[3];\n\n    if (dstkey == NULL) {\n        /* Propagate the [LR]POP operation. */\n        argv[0] = (where == REDIS_HEAD) ? shared.lpop :\n                                          shared.rpop;\n        argv[1] = key;\n        propagate((where == REDIS_HEAD) ?\n            server.lpopCommand : server.rpopCommand,\n            db->id,argv,2,REDIS_PROPAGATE_AOF|REDIS_PROPAGATE_REPL);\n\n        /* BRPOP/BLPOP */\n        addReplyMultiBulkLen(receiver,2);\n        addReplyBulk(receiver,key);\n        addReplyBulk(receiver,value);\n    } else {\n        /* BRPOPLPUSH */\n        robj *dstobj =\n            lookupKeyWrite(receiver->db,dstkey);\n        if (!(dstobj &&\n             checkType(receiver,dstobj,REDIS_LIST)))\n        {\n            /* Propagate the RPOP operation. */\n            argv[0] = shared.rpop;\n            argv[1] = key;\n            propagate(server.rpopCommand,\n                db->id,argv,2,\n                REDIS_PROPAGATE_AOF|\n                REDIS_PROPAGATE_REPL);\n            rpoplpushHandlePush(receiver,dstkey,dstobj,\n                value);\n            /* Propagate the LPUSH operation. */\n            argv[0] = shared.lpush;\n            argv[1] = dstkey;\n            argv[2] = value;\n            propagate(server.lpushCommand,\n                db->id,argv,3,\n                REDIS_PROPAGATE_AOF|\n                REDIS_PROPAGATE_REPL);\n        } else {\n            /* BRPOPLPUSH failed because of wrong\n             * destination type. */\n            return REDIS_ERR;\n        }\n    }\n    return REDIS_OK;\n}\n\n/* This function should be called by Redis every time a single command,\n * a MULTI/EXEC block, or a Lua script, terminated its execution after\n * being called by a client.\n *\n * All the keys with at least one client blocked that received at least\n * one new element via some PUSH operation are accumulated into\n * the server.ready_keys list. This function will run the list and will\n * serve clients accordingly. Note that the function will iterate again and\n * again as a result of serving BRPOPLPUSH we can have new blocking clients\n * to serve because of the PUSH side of BRPOPLPUSH. */\nvoid handleClientsBlockedOnLists(void) {\n    while(listLength(server.ready_keys) != 0) {\n        list *l;\n\n        /* Point server.ready_keys to a fresh list and save the current one\n         * locally. This way as we run the old list we are free to call\n         * signalListAsReady() that may push new elements in server.ready_keys\n         * when handling clients blocked into BRPOPLPUSH. */\n        l = server.ready_keys;\n        server.ready_keys = listCreate();\n\n        while(listLength(l) != 0) {\n            listNode *ln = listFirst(l);\n            readyList *rl = ln->value;\n\n            /* First of all remove this key from db->ready_keys so that\n             * we can safely call signalListAsReady() against this key. */\n            dictDelete(rl->db->ready_keys,rl->key);\n\n            /* If the key exists and it's a list, serve blocked clients\n             * with data. */\n            robj *o = lookupKeyWrite(rl->db,rl->key);\n            if (o != NULL && o->type == REDIS_LIST) {\n                dictEntry *de;\n\n                /* We serve clients in the same order they blocked for\n                 * this key, from the first blocked to the last. */\n                de = dictFind(rl->db->blocking_keys,rl->key);\n                if (de) {\n                    list *clients = dictGetVal(de);\n                    int numclients = listLength(clients);\n\n                    while(numclients--) {\n                        listNode *clientnode = listFirst(clients);\n                        redisClient *receiver = clientnode->value;\n                        robj *dstkey = receiver->bpop.target;\n                        int where = (receiver->lastcmd &&\n                                     receiver->lastcmd->proc == blpopCommand) ?\n                                    REDIS_HEAD : REDIS_TAIL;\n                        robj *value = listTypePop(o,where);\n\n                        if (value) {\n                            /* Protect receiver->bpop.target, that will be\n                             * freed by the next unblockClientWaitingData()\n                             * call. */\n                            if (dstkey) incrRefCount(dstkey);\n                            unblockClientWaitingData(receiver);\n\n                            if (serveClientBlockedOnList(receiver,\n                                rl->key,dstkey,rl->db,value,\n                                where) == REDIS_ERR)\n                            {\n                                /* If we failed serving the client we need\n                                 * to also undo the POP operation. */\n                                    listTypePush(o,value,where);\n                            }\n\n                            if (dstkey) decrRefCount(dstkey);\n                            decrRefCount(value);\n                        } else {\n                            break;\n                        }\n                    }\n                }\n\n                if (listTypeLength(o) == 0) dbDelete(rl->db,rl->key);\n                /* We don't call signalModifiedKey() as it was already called\n                 * when an element was pushed on the list. */\n            }\n\n            /* Free this item. */\n            decrRefCount(rl->key);\n            zfree(rl);\n            listDelNode(l,ln);\n        }\n        listRelease(l); /* We have the new list on place at this point. */\n    }\n}\n\nint getTimeoutFromObjectOrReply(redisClient *c, robj *object, time_t *timeout) {\n    long tval;\n\n    if (getLongFromObjectOrReply(c,object,&tval,\n        \"timeout is not an integer or out of range\") != REDIS_OK)\n        return REDIS_ERR;\n\n    if (tval < 0) {\n        addReplyError(c,\"timeout is negative\");\n        return REDIS_ERR;\n    }\n\n    if (tval > 0) tval += server.unixtime;\n    *timeout = tval;\n\n    return REDIS_OK;\n}\n\n/* Blocking RPOP/LPOP */\nvoid blockingPopGenericCommand(redisClient *c, int where) {\n    robj *o;\n    time_t timeout;\n    int j;\n\n    if (getTimeoutFromObjectOrReply(c,c->argv[c->argc-1],&timeout) != REDIS_OK)\n        return;\n\n    for (j = 1; j < c->argc-1; j++) {\n        o = lookupKeyWrite(c->db,c->argv[j]);\n        if (o != NULL) {\n            if (o->type != REDIS_LIST) {\n                addReply(c,shared.wrongtypeerr);\n                return;\n            } else {\n                if (listTypeLength(o) != 0) {\n                    /* Non empty list, this is like a non normal [LR]POP. */\n                    char *event = (where == REDIS_HEAD) ? \"lpop\" : \"rpop\";\n                    robj *value = listTypePop(o,where);\n                    redisAssert(value != NULL);\n\n                    addReplyMultiBulkLen(c,2);\n                    addReplyBulk(c,c->argv[j]);\n                    addReplyBulk(c,value);\n                    decrRefCount(value);\n                    notifyKeyspaceEvent(REDIS_NOTIFY_LIST,event,\n                                        c->argv[j],c->db->id);\n                    if (listTypeLength(o) == 0) {\n                        dbDelete(c->db,c->argv[j]);\n                        notifyKeyspaceEvent(REDIS_NOTIFY_GENERIC,\"del\",\n                                            c->argv[j],c->db->id);\n                    }\n                    signalModifiedKey(c->db,c->argv[j]);\n                    server.dirty++;\n\n                    /* Replicate it as an [LR]POP instead of B[LR]POP. */\n                    rewriteClientCommandVector(c,2,\n                        (where == REDIS_HEAD) ? shared.lpop : shared.rpop,\n                        c->argv[j]);\n                    return;\n                }\n            }\n        }\n    }\n\n    /* If we are inside a MULTI/EXEC and the list is empty the only thing\n     * we can do is treating it as a timeout (even with timeout 0). */\n    if (c->flags & REDIS_MULTI) {\n        addReply(c,shared.nullmultibulk);\n        return;\n    }\n\n    /* If the list is empty or the key does not exists we must block */\n    blockForKeys(c, c->argv + 1, c->argc - 2, timeout, NULL);\n}\n\nvoid blpopCommand(redisClient *c) {\n    blockingPopGenericCommand(c,REDIS_HEAD);\n}\n\nvoid brpopCommand(redisClient *c) {\n    blockingPopGenericCommand(c,REDIS_TAIL);\n}\n\nvoid brpoplpushCommand(redisClient *c) {\n    time_t timeout;\n\n    if (getTimeoutFromObjectOrReply(c,c->argv[3],&timeout) != REDIS_OK)\n        return;\n\n    robj *key = lookupKeyWrite(c->db, c->argv[1]);\n\n    if (key == NULL) {\n        if (c->flags & REDIS_MULTI) {\n            /* Blocking against an empty list in a multi state\n             * returns immediately. */\n            addReply(c, shared.nullbulk);\n        } else {\n            /* The list is empty and the client blocks. */\n            blockForKeys(c, c->argv + 1, 1, timeout, c->argv[2]);\n        }\n    } else {\n        if (key->type != REDIS_LIST) {\n            addReply(c, shared.wrongtypeerr);\n        } else {\n            /* The list exists and has elements, so\n             * the regular rpoplpushCommand is executed. */\n            redisAssertWithInfo(c,key,listTypeLength(key) > 0);\n            rpoplpushCommand(c);\n        }\n    }\n}\n"
  },
  {
    "path": "extern/deprecated/redis-2.8.21/src/t_set.c",
    "content": "/*\n * Copyright (c) 2009-2012, Salvatore Sanfilippo <antirez at gmail dot com>\n * All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions are met:\n *\n *   * Redistributions of source code must retain the above copyright notice,\n *     this list of conditions and the following disclaimer.\n *   * Redistributions in binary form must reproduce the above copyright\n *     notice, this list of conditions and the following disclaimer in the\n *     documentation and/or other materials provided with the distribution.\n *   * Neither the name of Redis nor the names of its contributors may be used\n *     to endorse or promote products derived from this software without\n *     specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\"\n * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\n * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE\n * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR\n * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF\n * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS\n * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN\n * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)\n * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE\n * POSSIBILITY OF SUCH DAMAGE.\n */\n\n#include \"redis.h\"\n\n/*-----------------------------------------------------------------------------\n * Set Commands\n *----------------------------------------------------------------------------*/\n\nvoid sunionDiffGenericCommand(redisClient *c, robj **setkeys, int setnum, robj *dstkey, int op);\n\n/* Factory method to return a set that *can* hold \"value\". When the object has\n * an integer-encodable value, an intset will be returned. Otherwise a regular\n * hash table. */\nrobj *setTypeCreate(robj *value) {\n    if (isObjectRepresentableAsLongLong(value,NULL) == REDIS_OK)\n        return createIntsetObject();\n    return createSetObject();\n}\n\nint setTypeAdd(robj *subject, robj *value) {\n    long long llval;\n    if (subject->encoding == REDIS_ENCODING_HT) {\n        if (dictAdd(subject->ptr,value,NULL) == DICT_OK) {\n            incrRefCount(value);\n            return 1;\n        }\n    } else if (subject->encoding == REDIS_ENCODING_INTSET) {\n        if (isObjectRepresentableAsLongLong(value,&llval) == REDIS_OK) {\n            uint8_t success = 0;\n            subject->ptr = intsetAdd(subject->ptr,llval,&success);\n            if (success) {\n                /* Convert to regular set when the intset contains\n                 * too many entries. */\n                if (intsetLen(subject->ptr) > server.set_max_intset_entries)\n                    setTypeConvert(subject,REDIS_ENCODING_HT);\n                return 1;\n            }\n        } else {\n            /* Failed to get integer from object, convert to regular set. */\n            setTypeConvert(subject,REDIS_ENCODING_HT);\n\n            /* The set *was* an intset and this value is not integer\n             * encodable, so dictAdd should always work. */\n            redisAssertWithInfo(NULL,value,dictAdd(subject->ptr,value,NULL) == DICT_OK);\n            incrRefCount(value);\n            return 1;\n        }\n    } else {\n        redisPanic(\"Unknown set encoding\");\n    }\n    return 0;\n}\n\nint setTypeRemove(robj *setobj, robj *value) {\n    long long llval;\n    if (setobj->encoding == REDIS_ENCODING_HT) {\n        if (dictDelete(setobj->ptr,value) == DICT_OK) {\n            if (htNeedsResize(setobj->ptr)) dictResize(setobj->ptr);\n            return 1;\n        }\n    } else if (setobj->encoding == REDIS_ENCODING_INTSET) {\n        if (isObjectRepresentableAsLongLong(value,&llval) == REDIS_OK) {\n            int success;\n            setobj->ptr = intsetRemove(setobj->ptr,llval,&success);\n            if (success) return 1;\n        }\n    } else {\n        redisPanic(\"Unknown set encoding\");\n    }\n    return 0;\n}\n\nint setTypeIsMember(robj *subject, robj *value) {\n    long long llval;\n    if (subject->encoding == REDIS_ENCODING_HT) {\n        return dictFind((dict*)subject->ptr,value) != NULL;\n    } else if (subject->encoding == REDIS_ENCODING_INTSET) {\n        if (isObjectRepresentableAsLongLong(value,&llval) == REDIS_OK) {\n            return intsetFind((intset*)subject->ptr,llval);\n        }\n    } else {\n        redisPanic(\"Unknown set encoding\");\n    }\n    return 0;\n}\n\nsetTypeIterator *setTypeInitIterator(robj *subject) {\n    setTypeIterator *si = zmalloc(sizeof(setTypeIterator));\n    si->subject = subject;\n    si->encoding = subject->encoding;\n    if (si->encoding == REDIS_ENCODING_HT) {\n        si->di = dictGetIterator(subject->ptr);\n    } else if (si->encoding == REDIS_ENCODING_INTSET) {\n        si->ii = 0;\n    } else {\n        redisPanic(\"Unknown set encoding\");\n    }\n    return si;\n}\n\nvoid setTypeReleaseIterator(setTypeIterator *si) {\n    if (si->encoding == REDIS_ENCODING_HT)\n        dictReleaseIterator(si->di);\n    zfree(si);\n}\n\n/* Move to the next entry in the set. Returns the object at the current\n * position.\n *\n * Since set elements can be internally be stored as redis objects or\n * simple arrays of integers, setTypeNext returns the encoding of the\n * set object you are iterating, and will populate the appropriate pointer\n * (eobj) or (llobj) accordingly.\n *\n * When there are no longer elements -1 is returned.\n * Returned objects ref count is not incremented, so this function is\n * copy on write friendly. */\nint setTypeNext(setTypeIterator *si, robj **objele, int64_t *llele) {\n    if (si->encoding == REDIS_ENCODING_HT) {\n        dictEntry *de = dictNext(si->di);\n        if (de == NULL) return -1;\n        *objele = dictGetKey(de);\n    } else if (si->encoding == REDIS_ENCODING_INTSET) {\n        if (!intsetGet(si->subject->ptr,si->ii++,llele))\n            return -1;\n    }\n    return si->encoding;\n}\n\n/* The not copy on write friendly version but easy to use version\n * of setTypeNext() is setTypeNextObject(), returning new objects\n * or incrementing the ref count of returned objects. So if you don't\n * retain a pointer to this object you should call decrRefCount() against it.\n *\n * This function is the way to go for write operations where COW is not\n * an issue as the result will be anyway of incrementing the ref count. */\nrobj *setTypeNextObject(setTypeIterator *si) {\n    int64_t intele;\n    robj *objele;\n    int encoding;\n\n    encoding = setTypeNext(si,&objele,&intele);\n    switch(encoding) {\n        case -1:    return NULL;\n        case REDIS_ENCODING_INTSET:\n            return createStringObjectFromLongLong(intele);\n        case REDIS_ENCODING_HT:\n            incrRefCount(objele);\n            return objele;\n        default:\n            redisPanic(\"Unsupported encoding\");\n    }\n    return NULL; /* just to suppress warnings */\n}\n\n/* Return random element from a non empty set.\n * The returned element can be a int64_t value if the set is encoded\n * as an \"intset\" blob of integers, or a redis object if the set\n * is a regular set.\n *\n * The caller provides both pointers to be populated with the right\n * object. The return value of the function is the object->encoding\n * field of the object and is used by the caller to check if the\n * int64_t pointer or the redis object pointer was populated.\n *\n * When an object is returned (the set was a real set) the ref count\n * of the object is not incremented so this function can be considered\n * copy on write friendly. */\nint setTypeRandomElement(robj *setobj, robj **objele, int64_t *llele) {\n    if (setobj->encoding == REDIS_ENCODING_HT) {\n        dictEntry *de = dictGetRandomKey(setobj->ptr);\n        *objele = dictGetKey(de);\n    } else if (setobj->encoding == REDIS_ENCODING_INTSET) {\n        *llele = intsetRandom(setobj->ptr);\n    } else {\n        redisPanic(\"Unknown set encoding\");\n    }\n    return setobj->encoding;\n}\n\nunsigned long setTypeSize(robj *subject) {\n    if (subject->encoding == REDIS_ENCODING_HT) {\n        return dictSize((dict*)subject->ptr);\n    } else if (subject->encoding == REDIS_ENCODING_INTSET) {\n        return intsetLen((intset*)subject->ptr);\n    } else {\n        redisPanic(\"Unknown set encoding\");\n    }\n}\n\n/* Convert the set to specified encoding. The resulting dict (when converting\n * to a hash table) is presized to hold the number of elements in the original\n * set. */\nvoid setTypeConvert(robj *setobj, int enc) {\n    setTypeIterator *si;\n    redisAssertWithInfo(NULL,setobj,setobj->type == REDIS_SET &&\n                             setobj->encoding == REDIS_ENCODING_INTSET);\n\n    if (enc == REDIS_ENCODING_HT) {\n        int64_t intele;\n        dict *d = dictCreate(&setDictType,NULL);\n        robj *element;\n\n        /* Presize the dict to avoid rehashing */\n        dictExpand(d,intsetLen(setobj->ptr));\n\n        /* To add the elements we extract integers and create redis objects */\n        si = setTypeInitIterator(setobj);\n        while (setTypeNext(si,NULL,&intele) != -1) {\n            element = createStringObjectFromLongLong(intele);\n            redisAssertWithInfo(NULL,element,dictAdd(d,element,NULL) == DICT_OK);\n        }\n        setTypeReleaseIterator(si);\n\n        setobj->encoding = REDIS_ENCODING_HT;\n        zfree(setobj->ptr);\n        setobj->ptr = d;\n    } else {\n        redisPanic(\"Unsupported set conversion\");\n    }\n}\n\nvoid saddCommand(redisClient *c) {\n    robj *set;\n    int j, added = 0;\n\n    set = lookupKeyWrite(c->db,c->argv[1]);\n    if (set == NULL) {\n        set = setTypeCreate(c->argv[2]);\n        dbAdd(c->db,c->argv[1],set);\n    } else {\n        if (set->type != REDIS_SET) {\n            addReply(c,shared.wrongtypeerr);\n            return;\n        }\n    }\n\n    for (j = 2; j < c->argc; j++) {\n        c->argv[j] = tryObjectEncoding(c->argv[j]);\n        if (setTypeAdd(set,c->argv[j])) added++;\n    }\n    if (added) {\n        signalModifiedKey(c->db,c->argv[1]);\n        notifyKeyspaceEvent(REDIS_NOTIFY_SET,\"sadd\",c->argv[1],c->db->id);\n    }\n    server.dirty += added;\n    addReplyLongLong(c,added);\n}\n\nvoid sremCommand(redisClient *c) {\n    robj *set;\n    int j, deleted = 0, keyremoved = 0;\n\n    if ((set = lookupKeyWriteOrReply(c,c->argv[1],shared.czero)) == NULL ||\n        checkType(c,set,REDIS_SET)) return;\n\n    for (j = 2; j < c->argc; j++) {\n        if (setTypeRemove(set,c->argv[j])) {\n            deleted++;\n            if (setTypeSize(set) == 0) {\n                dbDelete(c->db,c->argv[1]);\n                keyremoved = 1;\n                break;\n            }\n        }\n    }\n    if (deleted) {\n        signalModifiedKey(c->db,c->argv[1]);\n        notifyKeyspaceEvent(REDIS_NOTIFY_SET,\"srem\",c->argv[1],c->db->id);\n        if (keyremoved)\n            notifyKeyspaceEvent(REDIS_NOTIFY_GENERIC,\"del\",c->argv[1],\n                                c->db->id);\n        server.dirty += deleted;\n    }\n    addReplyLongLong(c,deleted);\n}\n\nvoid smoveCommand(redisClient *c) {\n    robj *srcset, *dstset, *ele;\n    srcset = lookupKeyWrite(c->db,c->argv[1]);\n    dstset = lookupKeyWrite(c->db,c->argv[2]);\n    ele = c->argv[3] = tryObjectEncoding(c->argv[3]);\n\n    /* If the source key does not exist return 0 */\n    if (srcset == NULL) {\n        addReply(c,shared.czero);\n        return;\n    }\n\n    /* If the source key has the wrong type, or the destination key\n     * is set and has the wrong type, return with an error. */\n    if (checkType(c,srcset,REDIS_SET) ||\n        (dstset && checkType(c,dstset,REDIS_SET))) return;\n\n    /* If srcset and dstset are equal, SMOVE is a no-op */\n    if (srcset == dstset) {\n        addReply(c,setTypeIsMember(srcset,ele) ? shared.cone : shared.czero);\n        return;\n    }\n\n    /* If the element cannot be removed from the src set, return 0. */\n    if (!setTypeRemove(srcset,ele)) {\n        addReply(c,shared.czero);\n        return;\n    }\n    notifyKeyspaceEvent(REDIS_NOTIFY_SET,\"srem\",c->argv[1],c->db->id);\n\n    /* Remove the src set from the database when empty */\n    if (setTypeSize(srcset) == 0) {\n        dbDelete(c->db,c->argv[1]);\n        notifyKeyspaceEvent(REDIS_NOTIFY_GENERIC,\"del\",c->argv[1],c->db->id);\n    }\n    signalModifiedKey(c->db,c->argv[1]);\n    signalModifiedKey(c->db,c->argv[2]);\n    server.dirty++;\n\n    /* Create the destination set when it doesn't exist */\n    if (!dstset) {\n        dstset = setTypeCreate(ele);\n        dbAdd(c->db,c->argv[2],dstset);\n    }\n\n    /* An extra key has changed when ele was successfully added to dstset */\n    if (setTypeAdd(dstset,ele)) {\n        server.dirty++;\n        notifyKeyspaceEvent(REDIS_NOTIFY_SET,\"sadd\",c->argv[2],c->db->id);\n    }\n    addReply(c,shared.cone);\n}\n\nvoid sismemberCommand(redisClient *c) {\n    robj *set;\n\n    if ((set = lookupKeyReadOrReply(c,c->argv[1],shared.czero)) == NULL ||\n        checkType(c,set,REDIS_SET)) return;\n\n    c->argv[2] = tryObjectEncoding(c->argv[2]);\n    if (setTypeIsMember(set,c->argv[2]))\n        addReply(c,shared.cone);\n    else\n        addReply(c,shared.czero);\n}\n\nvoid scardCommand(redisClient *c) {\n    robj *o;\n\n    if ((o = lookupKeyReadOrReply(c,c->argv[1],shared.czero)) == NULL ||\n        checkType(c,o,REDIS_SET)) return;\n\n    addReplyLongLong(c,setTypeSize(o));\n}\n\nvoid spopCommand(redisClient *c) {\n    robj *set, *ele, *aux;\n    int64_t llele;\n    int encoding;\n\n    if ((set = lookupKeyWriteOrReply(c,c->argv[1],shared.nullbulk)) == NULL ||\n        checkType(c,set,REDIS_SET)) return;\n\n    encoding = setTypeRandomElement(set,&ele,&llele);\n    if (encoding == REDIS_ENCODING_INTSET) {\n        ele = createStringObjectFromLongLong(llele);\n        set->ptr = intsetRemove(set->ptr,llele,NULL);\n    } else {\n        incrRefCount(ele);\n        setTypeRemove(set,ele);\n    }\n    notifyKeyspaceEvent(REDIS_NOTIFY_SET,\"spop\",c->argv[1],c->db->id);\n\n    /* Replicate/AOF this command as an SREM operation */\n    aux = createStringObject(\"SREM\",4);\n    rewriteClientCommandVector(c,3,aux,c->argv[1],ele);\n    decrRefCount(ele);\n    decrRefCount(aux);\n\n    addReplyBulk(c,ele);\n    if (setTypeSize(set) == 0) {\n        dbDelete(c->db,c->argv[1]);\n        notifyKeyspaceEvent(REDIS_NOTIFY_GENERIC,\"del\",c->argv[1],c->db->id);\n    }\n    signalModifiedKey(c->db,c->argv[1]);\n    server.dirty++;\n}\n\n/* handle the \"SRANDMEMBER key <count>\" variant. The normal version of the\n * command is handled by the srandmemberCommand() function itself. */\n\n/* How many times bigger should be the set compared to the requested size\n * for us to don't use the \"remove elements\" strategy? Read later in the\n * implementation for more info. */\n#define SRANDMEMBER_SUB_STRATEGY_MUL 3\n\nvoid srandmemberWithCountCommand(redisClient *c) {\n    long l;\n    unsigned long count, size;\n    int uniq = 1;\n    robj *set, *ele;\n    int64_t llele;\n    int encoding;\n\n    dict *d;\n\n    if (getLongFromObjectOrReply(c,c->argv[2],&l,NULL) != REDIS_OK) return;\n    if (l >= 0) {\n        count = (unsigned) l;\n    } else {\n        /* A negative count means: return the same elements multiple times\n         * (i.e. don't remove the extracted element after every extraction). */\n        count = -l;\n        uniq = 0;\n    }\n\n    if ((set = lookupKeyReadOrReply(c,c->argv[1],shared.emptymultibulk))\n        == NULL || checkType(c,set,REDIS_SET)) return;\n    size = setTypeSize(set);\n\n    /* If count is zero, serve it ASAP to avoid special cases later. */\n    if (count == 0) {\n        addReply(c,shared.emptymultibulk);\n        return;\n    }\n\n    /* CASE 1: The count was negative, so the extraction method is just:\n     * \"return N random elements\" sampling the whole set every time.\n     * This case is trivial and can be served without auxiliary data\n     * structures. */\n    if (!uniq) {\n        addReplyMultiBulkLen(c,count);\n        while(count--) {\n            encoding = setTypeRandomElement(set,&ele,&llele);\n            if (encoding == REDIS_ENCODING_INTSET) {\n                addReplyBulkLongLong(c,llele);\n            } else {\n                addReplyBulk(c,ele);\n            }\n        }\n        return;\n    }\n\n    /* CASE 2:\n     * The number of requested elements is greater than the number of\n     * elements inside the set: simply return the whole set. */\n    if (count >= size) {\n        sunionDiffGenericCommand(c,c->argv+1,1,NULL,REDIS_OP_UNION);\n        return;\n    }\n\n    /* For CASE 3 and CASE 4 we need an auxiliary dictionary. */\n    d = dictCreate(&setDictType,NULL);\n\n    /* CASE 3:\n     * The number of elements inside the set is not greater than\n     * SRANDMEMBER_SUB_STRATEGY_MUL times the number of requested elements.\n     * In this case we create a set from scratch with all the elements, and\n     * subtract random elements to reach the requested number of elements.\n     *\n     * This is done because if the number of requsted elements is just\n     * a bit less than the number of elements in the set, the natural approach\n     * used into CASE 3 is highly inefficient. */\n    if (count*SRANDMEMBER_SUB_STRATEGY_MUL > size) {\n        setTypeIterator *si;\n\n        /* Add all the elements into the temporary dictionary. */\n        si = setTypeInitIterator(set);\n        while((encoding = setTypeNext(si,&ele,&llele)) != -1) {\n            int retval = DICT_ERR;\n\n            if (encoding == REDIS_ENCODING_INTSET) {\n                retval = dictAdd(d,createStringObjectFromLongLong(llele),NULL);\n            } else if (ele->encoding == REDIS_ENCODING_RAW) {\n                retval = dictAdd(d,dupStringObject(ele),NULL);\n            } else if (ele->encoding == REDIS_ENCODING_INT) {\n                retval = dictAdd(d,\n                    createStringObjectFromLongLong((long)ele->ptr),NULL);\n            }\n            redisAssert(retval == DICT_OK);\n        }\n        setTypeReleaseIterator(si);\n        redisAssert(dictSize(d) == size);\n\n        /* Remove random elements to reach the right count. */\n        while(size > count) {\n            dictEntry *de;\n\n            de = dictGetRandomKey(d);\n            dictDelete(d,dictGetKey(de));\n            size--;\n        }\n    }\n\n    /* CASE 4: We have a big set compared to the requested number of elements.\n     * In this case we can simply get random elements from the set and add\n     * to the temporary set, trying to eventually get enough unique elements\n     * to reach the specified count. */\n    else {\n        unsigned long added = 0;\n\n        while(added < count) {\n            encoding = setTypeRandomElement(set,&ele,&llele);\n            if (encoding == REDIS_ENCODING_INTSET) {\n                ele = createStringObjectFromLongLong(llele);\n            } else if (ele->encoding == REDIS_ENCODING_RAW) {\n                ele = dupStringObject(ele);\n            } else if (ele->encoding == REDIS_ENCODING_INT) {\n                ele = createStringObjectFromLongLong((long)ele->ptr);\n            }\n            /* Try to add the object to the dictionary. If it already exists\n             * free it, otherwise increment the number of objects we have\n             * in the result dictionary. */\n            if (dictAdd(d,ele,NULL) == DICT_OK)\n                added++;\n            else\n                decrRefCount(ele);\n        }\n    }\n\n    /* CASE 3 & 4: send the result to the user. */\n    {\n        dictIterator *di;\n        dictEntry *de;\n\n        addReplyMultiBulkLen(c,count);\n        di = dictGetIterator(d);\n        while((de = dictNext(di)) != NULL)\n            addReplyBulk(c,dictGetKey(de));\n        dictReleaseIterator(di);\n        dictRelease(d);\n    }\n}\n\nvoid srandmemberCommand(redisClient *c) {\n    robj *set, *ele;\n    int64_t llele;\n    int encoding;\n\n    if (c->argc == 3) {\n        srandmemberWithCountCommand(c);\n        return;\n    } else if (c->argc > 3) {\n        addReply(c,shared.syntaxerr);\n        return;\n    }\n\n    if ((set = lookupKeyReadOrReply(c,c->argv[1],shared.nullbulk)) == NULL ||\n        checkType(c,set,REDIS_SET)) return;\n\n    encoding = setTypeRandomElement(set,&ele,&llele);\n    if (encoding == REDIS_ENCODING_INTSET) {\n        addReplyBulkLongLong(c,llele);\n    } else {\n        addReplyBulk(c,ele);\n    }\n}\n\nint qsortCompareSetsByCardinality(const void *s1, const void *s2) {\n    return setTypeSize(*(robj**)s1)-setTypeSize(*(robj**)s2);\n}\n\n/* This is used by SDIFF and in this case we can receive NULL that should\n * be handled as empty sets. */\nint qsortCompareSetsByRevCardinality(const void *s1, const void *s2) {\n    robj *o1 = *(robj**)s1, *o2 = *(robj**)s2;\n\n    return  (o2 ? setTypeSize(o2) : 0) - (o1 ? setTypeSize(o1) : 0);\n}\n\nvoid sinterGenericCommand(redisClient *c, robj **setkeys, unsigned long setnum, robj *dstkey) {\n    robj **sets = zmalloc(sizeof(robj*)*setnum);\n    setTypeIterator *si;\n    robj *eleobj, *dstset = NULL;\n    int64_t intobj;\n    void *replylen = NULL;\n    unsigned long j, cardinality = 0;\n    int encoding;\n\n    for (j = 0; j < setnum; j++) {\n        robj *setobj = dstkey ?\n            lookupKeyWrite(c->db,setkeys[j]) :\n            lookupKeyRead(c->db,setkeys[j]);\n        if (!setobj) {\n            zfree(sets);\n            if (dstkey) {\n                if (dbDelete(c->db,dstkey)) {\n                    signalModifiedKey(c->db,dstkey);\n                    server.dirty++;\n                }\n                addReply(c,shared.czero);\n            } else {\n                addReply(c,shared.emptymultibulk);\n            }\n            return;\n        }\n        if (checkType(c,setobj,REDIS_SET)) {\n            zfree(sets);\n            return;\n        }\n        sets[j] = setobj;\n    }\n    /* Sort sets from the smallest to largest, this will improve our\n     * algorithm's performance */\n    qsort(sets,setnum,sizeof(robj*),qsortCompareSetsByCardinality);\n\n    /* The first thing we should output is the total number of elements...\n     * since this is a multi-bulk write, but at this stage we don't know\n     * the intersection set size, so we use a trick, append an empty object\n     * to the output list and save the pointer to later modify it with the\n     * right length */\n    if (!dstkey) {\n        replylen = addDeferredMultiBulkLength(c);\n    } else {\n        /* If we have a target key where to store the resulting set\n         * create this key with an empty set inside */\n        dstset = createIntsetObject();\n    }\n\n    /* Iterate all the elements of the first (smallest) set, and test\n     * the element against all the other sets, if at least one set does\n     * not include the element it is discarded */\n    si = setTypeInitIterator(sets[0]);\n    while((encoding = setTypeNext(si,&eleobj,&intobj)) != -1) {\n        for (j = 1; j < setnum; j++) {\n            if (sets[j] == sets[0]) continue;\n            if (encoding == REDIS_ENCODING_INTSET) {\n                /* intset with intset is simple... and fast */\n                if (sets[j]->encoding == REDIS_ENCODING_INTSET &&\n                    !intsetFind((intset*)sets[j]->ptr,intobj))\n                {\n                    break;\n                /* in order to compare an integer with an object we\n                 * have to use the generic function, creating an object\n                 * for this */\n                } else if (sets[j]->encoding == REDIS_ENCODING_HT) {\n                    eleobj = createStringObjectFromLongLong(intobj);\n                    if (!setTypeIsMember(sets[j],eleobj)) {\n                        decrRefCount(eleobj);\n                        break;\n                    }\n                    decrRefCount(eleobj);\n                }\n            } else if (encoding == REDIS_ENCODING_HT) {\n                /* Optimization... if the source object is integer\n                 * encoded AND the target set is an intset, we can get\n                 * a much faster path. */\n                if (eleobj->encoding == REDIS_ENCODING_INT &&\n                    sets[j]->encoding == REDIS_ENCODING_INTSET &&\n                    !intsetFind((intset*)sets[j]->ptr,(long)eleobj->ptr))\n                {\n                    break;\n                /* else... object to object check is easy as we use the\n                 * type agnostic API here. */\n                } else if (!setTypeIsMember(sets[j],eleobj)) {\n                    break;\n                }\n            }\n        }\n\n        /* Only take action when all sets contain the member */\n        if (j == setnum) {\n            if (!dstkey) {\n                if (encoding == REDIS_ENCODING_HT)\n                    addReplyBulk(c,eleobj);\n                else\n                    addReplyBulkLongLong(c,intobj);\n                cardinality++;\n            } else {\n                if (encoding == REDIS_ENCODING_INTSET) {\n                    eleobj = createStringObjectFromLongLong(intobj);\n                    setTypeAdd(dstset,eleobj);\n                    decrRefCount(eleobj);\n                } else {\n                    setTypeAdd(dstset,eleobj);\n                }\n            }\n        }\n    }\n    setTypeReleaseIterator(si);\n\n    if (dstkey) {\n        /* Store the resulting set into the target, if the intersection\n         * is not an empty set. */\n        int deleted = dbDelete(c->db,dstkey);\n        if (setTypeSize(dstset) > 0) {\n            dbAdd(c->db,dstkey,dstset);\n            addReplyLongLong(c,setTypeSize(dstset));\n            notifyKeyspaceEvent(REDIS_NOTIFY_SET,\"sinterstore\",\n                dstkey,c->db->id);\n        } else {\n            decrRefCount(dstset);\n            addReply(c,shared.czero);\n            if (deleted)\n                notifyKeyspaceEvent(REDIS_NOTIFY_GENERIC,\"del\",\n                    dstkey,c->db->id);\n        }\n        signalModifiedKey(c->db,dstkey);\n        server.dirty++;\n    } else {\n        setDeferredMultiBulkLength(c,replylen,cardinality);\n    }\n    zfree(sets);\n}\n\nvoid sinterCommand(redisClient *c) {\n    sinterGenericCommand(c,c->argv+1,c->argc-1,NULL);\n}\n\nvoid sinterstoreCommand(redisClient *c) {\n    sinterGenericCommand(c,c->argv+2,c->argc-2,c->argv[1]);\n}\n\n#define REDIS_OP_UNION 0\n#define REDIS_OP_DIFF 1\n#define REDIS_OP_INTER 2\n\nvoid sunionDiffGenericCommand(redisClient *c, robj **setkeys, int setnum, robj *dstkey, int op) {\n    robj **sets = zmalloc(sizeof(robj*)*setnum);\n    setTypeIterator *si;\n    robj *ele, *dstset = NULL;\n    int j, cardinality = 0;\n    int diff_algo = 1;\n\n    for (j = 0; j < setnum; j++) {\n        robj *setobj = dstkey ?\n            lookupKeyWrite(c->db,setkeys[j]) :\n            lookupKeyRead(c->db,setkeys[j]);\n        if (!setobj) {\n            sets[j] = NULL;\n            continue;\n        }\n        if (checkType(c,setobj,REDIS_SET)) {\n            zfree(sets);\n            return;\n        }\n        sets[j] = setobj;\n    }\n\n    /* Select what DIFF algorithm to use.\n     *\n     * Algorithm 1 is O(N*M) where N is the size of the element first set\n     * and M the total number of sets.\n     *\n     * Algorithm 2 is O(N) where N is the total number of elements in all\n     * the sets.\n     *\n     * We compute what is the best bet with the current input here. */\n    if (op == REDIS_OP_DIFF && sets[0]) {\n        long long algo_one_work = 0, algo_two_work = 0;\n\n        for (j = 0; j < setnum; j++) {\n            if (sets[j] == NULL) continue;\n\n            algo_one_work += setTypeSize(sets[0]);\n            algo_two_work += setTypeSize(sets[j]);\n        }\n\n        /* Algorithm 1 has better constant times and performs less operations\n         * if there are elements in common. Give it some advantage. */\n        algo_one_work /= 2;\n        diff_algo = (algo_one_work <= algo_two_work) ? 1 : 2;\n\n        if (diff_algo == 1 && setnum > 1) {\n            /* With algorithm 1 it is better to order the sets to subtract\n             * by decreasing size, so that we are more likely to find\n             * duplicated elements ASAP. */\n            qsort(sets+1,setnum-1,sizeof(robj*),\n                qsortCompareSetsByRevCardinality);\n        }\n    }\n\n    /* We need a temp set object to store our union. If the dstkey\n     * is not NULL (that is, we are inside an SUNIONSTORE operation) then\n     * this set object will be the resulting object to set into the target key*/\n    dstset = createIntsetObject();\n\n    if (op == REDIS_OP_UNION) {\n        /* Union is trivial, just add every element of every set to the\n         * temporary set. */\n        for (j = 0; j < setnum; j++) {\n            if (!sets[j]) continue; /* non existing keys are like empty sets */\n\n            si = setTypeInitIterator(sets[j]);\n            while((ele = setTypeNextObject(si)) != NULL) {\n                if (setTypeAdd(dstset,ele)) cardinality++;\n                decrRefCount(ele);\n            }\n            setTypeReleaseIterator(si);\n        }\n    } else if (op == REDIS_OP_DIFF && sets[0] && diff_algo == 1) {\n        /* DIFF Algorithm 1:\n         *\n         * We perform the diff by iterating all the elements of the first set,\n         * and only adding it to the target set if the element does not exist\n         * into all the other sets.\n         *\n         * This way we perform at max N*M operations, where N is the size of\n         * the first set, and M the number of sets. */\n        si = setTypeInitIterator(sets[0]);\n        while((ele = setTypeNextObject(si)) != NULL) {\n            for (j = 1; j < setnum; j++) {\n                if (!sets[j]) continue; /* no key is an empty set. */\n                if (sets[j] == sets[0]) break; /* same set! */\n                if (setTypeIsMember(sets[j],ele)) break;\n            }\n            if (j == setnum) {\n                /* There is no other set with this element. Add it. */\n                setTypeAdd(dstset,ele);\n                cardinality++;\n            }\n            decrRefCount(ele);\n        }\n        setTypeReleaseIterator(si);\n    } else if (op == REDIS_OP_DIFF && sets[0] && diff_algo == 2) {\n        /* DIFF Algorithm 2:\n         *\n         * Add all the elements of the first set to the auxiliary set.\n         * Then remove all the elements of all the next sets from it.\n         *\n         * This is O(N) where N is the sum of all the elements in every\n         * set. */\n        for (j = 0; j < setnum; j++) {\n            if (!sets[j]) continue; /* non existing keys are like empty sets */\n\n            si = setTypeInitIterator(sets[j]);\n            while((ele = setTypeNextObject(si)) != NULL) {\n                if (j == 0) {\n                    if (setTypeAdd(dstset,ele)) cardinality++;\n                } else {\n                    if (setTypeRemove(dstset,ele)) cardinality--;\n                }\n                decrRefCount(ele);\n            }\n            setTypeReleaseIterator(si);\n\n            /* Exit if result set is empty as any additional removal\n             * of elements will have no effect. */\n            if (cardinality == 0) break;\n        }\n    }\n\n    /* Output the content of the resulting set, if not in STORE mode */\n    if (!dstkey) {\n        addReplyMultiBulkLen(c,cardinality);\n        si = setTypeInitIterator(dstset);\n        while((ele = setTypeNextObject(si)) != NULL) {\n            addReplyBulk(c,ele);\n            decrRefCount(ele);\n        }\n        setTypeReleaseIterator(si);\n        decrRefCount(dstset);\n    } else {\n        /* If we have a target key where to store the resulting set\n         * create this key with the result set inside */\n        int deleted = dbDelete(c->db,dstkey);\n        if (setTypeSize(dstset) > 0) {\n            dbAdd(c->db,dstkey,dstset);\n            addReplyLongLong(c,setTypeSize(dstset));\n            notifyKeyspaceEvent(REDIS_NOTIFY_SET,\n                op == REDIS_OP_UNION ? \"sunionstore\" : \"sdiffstore\",\n                dstkey,c->db->id);\n        } else {\n            decrRefCount(dstset);\n            addReply(c,shared.czero);\n            if (deleted)\n                notifyKeyspaceEvent(REDIS_NOTIFY_GENERIC,\"del\",\n                    dstkey,c->db->id);\n        }\n        signalModifiedKey(c->db,dstkey);\n        server.dirty++;\n    }\n    zfree(sets);\n}\n\nvoid sunionCommand(redisClient *c) {\n    sunionDiffGenericCommand(c,c->argv+1,c->argc-1,NULL,REDIS_OP_UNION);\n}\n\nvoid sunionstoreCommand(redisClient *c) {\n    sunionDiffGenericCommand(c,c->argv+2,c->argc-2,c->argv[1],REDIS_OP_UNION);\n}\n\nvoid sdiffCommand(redisClient *c) {\n    sunionDiffGenericCommand(c,c->argv+1,c->argc-1,NULL,REDIS_OP_DIFF);\n}\n\nvoid sdiffstoreCommand(redisClient *c) {\n    sunionDiffGenericCommand(c,c->argv+2,c->argc-2,c->argv[1],REDIS_OP_DIFF);\n}\n\nvoid sscanCommand(redisClient *c) {\n    robj *set;\n    unsigned long cursor;\n\n    if (parseScanCursorOrReply(c,c->argv[2],&cursor) == REDIS_ERR) return;\n    if ((set = lookupKeyReadOrReply(c,c->argv[1],shared.emptyscan)) == NULL ||\n        checkType(c,set,REDIS_SET)) return;\n    scanGenericCommand(c,set,cursor);\n}\n"
  },
  {
    "path": "extern/deprecated/redis-2.8.21/src/t_string.c",
    "content": "/*\n * Copyright (c) 2009-2012, Salvatore Sanfilippo <antirez at gmail dot com>\n * All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions are met:\n *\n *   * Redistributions of source code must retain the above copyright notice,\n *     this list of conditions and the following disclaimer.\n *   * Redistributions in binary form must reproduce the above copyright\n *     notice, this list of conditions and the following disclaimer in the\n *     documentation and/or other materials provided with the distribution.\n *   * Neither the name of Redis nor the names of its contributors may be used\n *     to endorse or promote products derived from this software without\n *     specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\"\n * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\n * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE\n * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR\n * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF\n * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS\n * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN\n * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)\n * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE\n * POSSIBILITY OF SUCH DAMAGE.\n */\n\n#include \"redis.h\"\n#include <math.h> /* isnan(), isinf() */\n\n/*-----------------------------------------------------------------------------\n * String Commands\n *----------------------------------------------------------------------------*/\n\nstatic int checkStringLength(redisClient *c, long long size) {\n    if (size > 512*1024*1024) {\n        addReplyError(c,\"string exceeds maximum allowed size (512MB)\");\n        return REDIS_ERR;\n    }\n    return REDIS_OK;\n}\n\n/* The setGenericCommand() function implements the SET operation with different\n * options and variants. This function is called in order to implement the\n * following commands: SET, SETEX, PSETEX, SETNX.\n *\n * 'flags' changes the behavior of the command (NX or XX, see belove).\n *\n * 'expire' represents an expire to set in form of a Redis object as passed\n * by the user. It is interpreted according to the specified 'unit'.\n *\n * 'ok_reply' and 'abort_reply' is what the function will reply to the client\n * if the operation is performed, or when it is not because of NX or\n * XX flags.\n *\n * If ok_reply is NULL \"+OK\" is used.\n * If abort_reply is NULL, \"$-1\" is used. */\n\n#define REDIS_SET_NO_FLAGS 0\n#define REDIS_SET_NX (1<<0)     /* Set if key not exists. */\n#define REDIS_SET_XX (1<<1)     /* Set if key exists. */\n\nvoid setGenericCommand(redisClient *c, int flags, robj *key, robj *val, robj *expire, int unit, robj *ok_reply, robj *abort_reply) {\n    long long milliseconds = 0; /* initialized to avoid any harmness warning */\n\n    if (expire) {\n        if (getLongLongFromObjectOrReply(c, expire, &milliseconds, NULL) != REDIS_OK)\n            return;\n        if (milliseconds <= 0) {\n            addReplyErrorFormat(c,\"invalid expire time in %s\",c->cmd->name);\n            return;\n        }\n        if (unit == UNIT_SECONDS) milliseconds *= 1000;\n    }\n\n    if ((flags & REDIS_SET_NX && lookupKeyWrite(c->db,key) != NULL) ||\n        (flags & REDIS_SET_XX && lookupKeyWrite(c->db,key) == NULL))\n    {\n        addReply(c, abort_reply ? abort_reply : shared.nullbulk);\n        return;\n    }\n    setKey(c->db,key,val);\n    server.dirty++;\n    if (expire) setExpire(c->db,key,mstime()+milliseconds);\n    notifyKeyspaceEvent(REDIS_NOTIFY_STRING,\"set\",key,c->db->id);\n    if (expire) notifyKeyspaceEvent(REDIS_NOTIFY_GENERIC,\n        \"expire\",key,c->db->id);\n    addReply(c, ok_reply ? ok_reply : shared.ok);\n}\n\n/* SET key value [NX] [XX] [EX <seconds>] [PX <milliseconds>] */\nvoid setCommand(redisClient *c) {\n    int j;\n    robj *expire = NULL;\n    int unit = UNIT_SECONDS;\n    int flags = REDIS_SET_NO_FLAGS;\n\n    for (j = 3; j < c->argc; j++) {\n        char *a = c->argv[j]->ptr;\n        robj *next = (j == c->argc-1) ? NULL : c->argv[j+1];\n\n        if ((a[0] == 'n' || a[0] == 'N') &&\n            (a[1] == 'x' || a[1] == 'X') && a[2] == '\\0') {\n            flags |= REDIS_SET_NX;\n        } else if ((a[0] == 'x' || a[0] == 'X') &&\n                   (a[1] == 'x' || a[1] == 'X') && a[2] == '\\0') {\n            flags |= REDIS_SET_XX;\n        } else if ((a[0] == 'e' || a[0] == 'E') &&\n                   (a[1] == 'x' || a[1] == 'X') && a[2] == '\\0' && next) {\n            unit = UNIT_SECONDS;\n            expire = next;\n            j++;\n        } else if ((a[0] == 'p' || a[0] == 'P') &&\n                   (a[1] == 'x' || a[1] == 'X') && a[2] == '\\0' && next) {\n            unit = UNIT_MILLISECONDS;\n            expire = next;\n            j++;\n        } else {\n            addReply(c,shared.syntaxerr);\n            return;\n        }\n    }\n\n    c->argv[2] = tryObjectEncoding(c->argv[2]);\n    setGenericCommand(c,flags,c->argv[1],c->argv[2],expire,unit,NULL,NULL);\n}\n\nvoid setnxCommand(redisClient *c) {\n    c->argv[2] = tryObjectEncoding(c->argv[2]);\n    setGenericCommand(c,REDIS_SET_NX,c->argv[1],c->argv[2],NULL,0,shared.cone,shared.czero);\n}\n\nvoid setexCommand(redisClient *c) {\n    c->argv[3] = tryObjectEncoding(c->argv[3]);\n    setGenericCommand(c,REDIS_SET_NO_FLAGS,c->argv[1],c->argv[3],c->argv[2],UNIT_SECONDS,NULL,NULL);\n}\n\nvoid psetexCommand(redisClient *c) {\n    c->argv[3] = tryObjectEncoding(c->argv[3]);\n    setGenericCommand(c,REDIS_SET_NO_FLAGS,c->argv[1],c->argv[3],c->argv[2],UNIT_MILLISECONDS,NULL,NULL);\n}\n\nint getGenericCommand(redisClient *c) {\n    robj *o;\n\n    if ((o = lookupKeyReadOrReply(c,c->argv[1],shared.nullbulk)) == NULL)\n        return REDIS_OK;\n\n    if (o->type != REDIS_STRING) {\n        addReply(c,shared.wrongtypeerr);\n        return REDIS_ERR;\n    } else {\n        addReplyBulk(c,o);\n        return REDIS_OK;\n    }\n}\n\nvoid getCommand(redisClient *c) {\n    getGenericCommand(c);\n}\n\nvoid getsetCommand(redisClient *c) {\n    if (getGenericCommand(c) == REDIS_ERR) return;\n    c->argv[2] = tryObjectEncoding(c->argv[2]);\n    setKey(c->db,c->argv[1],c->argv[2]);\n    notifyKeyspaceEvent(REDIS_NOTIFY_STRING,\"set\",c->argv[1],c->db->id);\n    server.dirty++;\n}\n\nvoid setrangeCommand(redisClient *c) {\n    robj *o;\n    long offset;\n    sds value = c->argv[3]->ptr;\n\n    if (getLongFromObjectOrReply(c,c->argv[2],&offset,NULL) != REDIS_OK)\n        return;\n\n    if (offset < 0) {\n        addReplyError(c,\"offset is out of range\");\n        return;\n    }\n\n    o = lookupKeyWrite(c->db,c->argv[1]);\n    if (o == NULL) {\n        /* Return 0 when setting nothing on a non-existing string */\n        if (sdslen(value) == 0) {\n            addReply(c,shared.czero);\n            return;\n        }\n\n        /* Return when the resulting string exceeds allowed size */\n        if (checkStringLength(c,offset+sdslen(value)) != REDIS_OK)\n            return;\n\n        o = createObject(REDIS_STRING,sdsempty());\n        dbAdd(c->db,c->argv[1],o);\n    } else {\n        size_t olen;\n\n        /* Key exists, check type */\n        if (checkType(c,o,REDIS_STRING))\n            return;\n\n        /* Return existing string length when setting nothing */\n        olen = stringObjectLen(o);\n        if (sdslen(value) == 0) {\n            addReplyLongLong(c,olen);\n            return;\n        }\n\n        /* Return when the resulting string exceeds allowed size */\n        if (checkStringLength(c,offset+sdslen(value)) != REDIS_OK)\n            return;\n\n        /* Create a copy when the object is shared or encoded. */\n        o = dbUnshareStringValue(c->db,c->argv[1],o);\n    }\n\n    if (sdslen(value) > 0) {\n        o->ptr = sdsgrowzero(o->ptr,offset+sdslen(value));\n        memcpy((char*)o->ptr+offset,value,sdslen(value));\n        signalModifiedKey(c->db,c->argv[1]);\n        notifyKeyspaceEvent(REDIS_NOTIFY_STRING,\n            \"setrange\",c->argv[1],c->db->id);\n        server.dirty++;\n    }\n    addReplyLongLong(c,sdslen(o->ptr));\n}\n\nvoid getrangeCommand(redisClient *c) {\n    robj *o;\n    long long start, end;\n    char *str, llbuf[32];\n    size_t strlen;\n\n    if (getLongLongFromObjectOrReply(c,c->argv[2],&start,NULL) != REDIS_OK)\n        return;\n    if (getLongLongFromObjectOrReply(c,c->argv[3],&end,NULL) != REDIS_OK)\n        return;\n    if ((o = lookupKeyReadOrReply(c,c->argv[1],shared.emptybulk)) == NULL ||\n        checkType(c,o,REDIS_STRING)) return;\n\n    if (o->encoding == REDIS_ENCODING_INT) {\n        str = llbuf;\n        strlen = ll2string(llbuf,sizeof(llbuf),(long)o->ptr);\n    } else {\n        str = o->ptr;\n        strlen = sdslen(str);\n    }\n\n    /* Convert negative indexes */\n    if (start < 0) start = strlen+start;\n    if (end < 0) end = strlen+end;\n    if (start < 0) start = 0;\n    if (end < 0) end = 0;\n    if ((unsigned long long)end >= strlen) end = strlen-1;\n\n    /* Precondition: end >= 0 && end < strlen, so the only condition where\n     * nothing can be returned is: start > end. */\n    if (start > end || strlen == 0) {\n        addReply(c,shared.emptybulk);\n    } else {\n        addReplyBulkCBuffer(c,(char*)str+start,end-start+1);\n    }\n}\n\nvoid mgetCommand(redisClient *c) {\n    int j;\n\n    addReplyMultiBulkLen(c,c->argc-1);\n    for (j = 1; j < c->argc; j++) {\n        robj *o = lookupKeyRead(c->db,c->argv[j]);\n        if (o == NULL) {\n            addReply(c,shared.nullbulk);\n        } else {\n            if (o->type != REDIS_STRING) {\n                addReply(c,shared.nullbulk);\n            } else {\n                addReplyBulk(c,o);\n            }\n        }\n    }\n}\n\nvoid msetGenericCommand(redisClient *c, int nx) {\n    int j, busykeys = 0;\n\n    if ((c->argc % 2) == 0) {\n        addReplyError(c,\"wrong number of arguments for MSET\");\n        return;\n    }\n    /* Handle the NX flag. The MSETNX semantic is to return zero and don't\n     * set nothing at all if at least one already key exists. */\n    if (nx) {\n        for (j = 1; j < c->argc; j += 2) {\n            if (lookupKeyWrite(c->db,c->argv[j]) != NULL) {\n                busykeys++;\n            }\n        }\n        if (busykeys) {\n            addReply(c, shared.czero);\n            return;\n        }\n    }\n\n    for (j = 1; j < c->argc; j += 2) {\n        c->argv[j+1] = tryObjectEncoding(c->argv[j+1]);\n        setKey(c->db,c->argv[j],c->argv[j+1]);\n        notifyKeyspaceEvent(REDIS_NOTIFY_STRING,\"set\",c->argv[j],c->db->id);\n    }\n    server.dirty += (c->argc-1)/2;\n    addReply(c, nx ? shared.cone : shared.ok);\n}\n\nvoid msetCommand(redisClient *c) {\n    msetGenericCommand(c,0);\n}\n\nvoid msetnxCommand(redisClient *c) {\n    msetGenericCommand(c,1);\n}\n\nvoid incrDecrCommand(redisClient *c, long long incr) {\n    long long value, oldvalue;\n    robj *o, *new;\n\n    o = lookupKeyWrite(c->db,c->argv[1]);\n    if (o != NULL && checkType(c,o,REDIS_STRING)) return;\n    if (getLongLongFromObjectOrReply(c,o,&value,NULL) != REDIS_OK) return;\n\n    oldvalue = value;\n    if ((incr < 0 && oldvalue < 0 && incr < (LLONG_MIN-oldvalue)) ||\n        (incr > 0 && oldvalue > 0 && incr > (LLONG_MAX-oldvalue))) {\n        addReplyError(c,\"increment or decrement would overflow\");\n        return;\n    }\n    value += incr;\n    new = createStringObjectFromLongLong(value);\n    if (o)\n        dbOverwrite(c->db,c->argv[1],new);\n    else\n        dbAdd(c->db,c->argv[1],new);\n    signalModifiedKey(c->db,c->argv[1]);\n    notifyKeyspaceEvent(REDIS_NOTIFY_STRING,\"incrby\",c->argv[1],c->db->id);\n    server.dirty++;\n    addReply(c,shared.colon);\n    addReply(c,new);\n    addReply(c,shared.crlf);\n}\n\nvoid incrCommand(redisClient *c) {\n    incrDecrCommand(c,1);\n}\n\nvoid decrCommand(redisClient *c) {\n    incrDecrCommand(c,-1);\n}\n\nvoid incrbyCommand(redisClient *c) {\n    long long incr;\n\n    if (getLongLongFromObjectOrReply(c, c->argv[2], &incr, NULL) != REDIS_OK) return;\n    incrDecrCommand(c,incr);\n}\n\nvoid decrbyCommand(redisClient *c) {\n    long long incr;\n\n    if (getLongLongFromObjectOrReply(c, c->argv[2], &incr, NULL) != REDIS_OK) return;\n    incrDecrCommand(c,-incr);\n}\n\nvoid incrbyfloatCommand(redisClient *c) {\n    long double incr, value;\n    robj *o, *new, *aux;\n\n    o = lookupKeyWrite(c->db,c->argv[1]);\n    if (o != NULL && checkType(c,o,REDIS_STRING)) return;\n    if (getLongDoubleFromObjectOrReply(c,o,&value,NULL) != REDIS_OK ||\n        getLongDoubleFromObjectOrReply(c,c->argv[2],&incr,NULL) != REDIS_OK)\n        return;\n\n    value += incr;\n    if (isnan(value) || isinf(value)) {\n        addReplyError(c,\"increment would produce NaN or Infinity\");\n        return;\n    }\n    new = createStringObjectFromLongDouble(value,1);\n    if (o)\n        dbOverwrite(c->db,c->argv[1],new);\n    else\n        dbAdd(c->db,c->argv[1],new);\n    signalModifiedKey(c->db,c->argv[1]);\n    notifyKeyspaceEvent(REDIS_NOTIFY_STRING,\"incrbyfloat\",c->argv[1],c->db->id);\n    server.dirty++;\n    addReplyBulk(c,new);\n\n    /* Always replicate INCRBYFLOAT as a SET command with the final value\n     * in order to make sure that differences in float precision or formatting\n     * will not create differences in replicas or after an AOF restart. */\n    aux = createStringObject(\"SET\",3);\n    rewriteClientCommandArgument(c,0,aux);\n    decrRefCount(aux);\n    rewriteClientCommandArgument(c,2,new);\n}\n\nvoid appendCommand(redisClient *c) {\n    size_t totlen;\n    robj *o, *append;\n\n    o = lookupKeyWrite(c->db,c->argv[1]);\n    if (o == NULL) {\n        /* Create the key */\n        c->argv[2] = tryObjectEncoding(c->argv[2]);\n        dbAdd(c->db,c->argv[1],c->argv[2]);\n        incrRefCount(c->argv[2]);\n        totlen = stringObjectLen(c->argv[2]);\n    } else {\n        /* Key exists, check type */\n        if (checkType(c,o,REDIS_STRING))\n            return;\n\n        /* \"append\" is an argument, so always an sds */\n        append = c->argv[2];\n        totlen = stringObjectLen(o)+sdslen(append->ptr);\n        if (checkStringLength(c,totlen) != REDIS_OK)\n            return;\n\n        /* Append the value */\n        o = dbUnshareStringValue(c->db,c->argv[1],o);\n        o->ptr = sdscatlen(o->ptr,append->ptr,sdslen(append->ptr));\n        totlen = sdslen(o->ptr);\n    }\n    signalModifiedKey(c->db,c->argv[1]);\n    notifyKeyspaceEvent(REDIS_NOTIFY_STRING,\"append\",c->argv[1],c->db->id);\n    server.dirty++;\n    addReplyLongLong(c,totlen);\n}\n\nvoid strlenCommand(redisClient *c) {\n    robj *o;\n    if ((o = lookupKeyReadOrReply(c,c->argv[1],shared.czero)) == NULL ||\n        checkType(c,o,REDIS_STRING)) return;\n    addReplyLongLong(c,stringObjectLen(o));\n}\n"
  },
  {
    "path": "extern/deprecated/redis-2.8.21/src/t_zset.c",
    "content": "/*\n * Copyright (c) 2009-2012, Salvatore Sanfilippo <antirez at gmail dot com>\n * Copyright (c) 2009-2012, Pieter Noordhuis <pcnoordhuis at gmail dot com>\n * All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions are met:\n *\n *   * Redistributions of source code must retain the above copyright notice,\n *     this list of conditions and the following disclaimer.\n *   * Redistributions in binary form must reproduce the above copyright\n *     notice, this list of conditions and the following disclaimer in the\n *     documentation and/or other materials provided with the distribution.\n *   * Neither the name of Redis nor the names of its contributors may be used\n *     to endorse or promote products derived from this software without\n *     specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\"\n * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\n * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE\n * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR\n * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF\n * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS\n * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN\n * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)\n * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE\n * POSSIBILITY OF SUCH DAMAGE.\n */\n\n/*-----------------------------------------------------------------------------\n * Sorted set API\n *----------------------------------------------------------------------------*/\n\n/* ZSETs are ordered sets using two data structures to hold the same elements\n * in order to get O(log(N)) INSERT and REMOVE operations into a sorted\n * data structure.\n *\n * The elements are added to a hash table mapping Redis objects to scores.\n * At the same time the elements are added to a skip list mapping scores\n * to Redis objects (so objects are sorted by scores in this \"view\"). */\n\n/* This skiplist implementation is almost a C translation of the original\n * algorithm described by William Pugh in \"Skip Lists: A Probabilistic\n * Alternative to Balanced Trees\", modified in three ways:\n * a) this implementation allows for repeated scores.\n * b) the comparison is not just by key (our 'score') but by satellite data.\n * c) there is a back pointer, so it's a doubly linked list with the back\n * pointers being only at \"level 1\". This allows to traverse the list\n * from tail to head, useful for ZREVRANGE. */\n\n#include \"redis.h\"\n#include <math.h>\n\nstatic int zslLexValueGteMin(robj *value, zlexrangespec *spec);\nstatic int zslLexValueLteMax(robj *value, zlexrangespec *spec);\n\nzskiplistNode *zslCreateNode(int level, double score, robj *obj) {\n    zskiplistNode *zn = zmalloc(sizeof(*zn)+level*sizeof(struct zskiplistLevel));\n    zn->score = score;\n    zn->obj = obj;\n    return zn;\n}\n\nzskiplist *zslCreate(void) {\n    int j;\n    zskiplist *zsl;\n\n    zsl = zmalloc(sizeof(*zsl));\n    zsl->level = 1;\n    zsl->length = 0;\n    zsl->header = zslCreateNode(ZSKIPLIST_MAXLEVEL,0,NULL);\n    for (j = 0; j < ZSKIPLIST_MAXLEVEL; j++) {\n        zsl->header->level[j].forward = NULL;\n        zsl->header->level[j].span = 0;\n    }\n    zsl->header->backward = NULL;\n    zsl->tail = NULL;\n    return zsl;\n}\n\nvoid zslFreeNode(zskiplistNode *node) {\n    decrRefCount(node->obj);\n    zfree(node);\n}\n\nvoid zslFree(zskiplist *zsl) {\n    zskiplistNode *node = zsl->header->level[0].forward, *next;\n\n    zfree(zsl->header);\n    while(node) {\n        next = node->level[0].forward;\n        zslFreeNode(node);\n        node = next;\n    }\n    zfree(zsl);\n}\n\n/* Returns a random level for the new skiplist node we are going to create.\n * The return value of this function is between 1 and ZSKIPLIST_MAXLEVEL\n * (both inclusive), with a powerlaw-alike distribution where higher\n * levels are less likely to be returned. */\nint zslRandomLevel(void) {\n    int level = 1;\n    while ((random()&0xFFFF) < (ZSKIPLIST_P * 0xFFFF))\n        level += 1;\n    return (level<ZSKIPLIST_MAXLEVEL) ? level : ZSKIPLIST_MAXLEVEL;\n}\n\nzskiplistNode *zslInsert(zskiplist *zsl, double score, robj *obj) {\n    zskiplistNode *update[ZSKIPLIST_MAXLEVEL], *x;\n    unsigned int rank[ZSKIPLIST_MAXLEVEL];\n    int i, level;\n\n    redisAssert(!isnan(score));\n    x = zsl->header;\n    for (i = zsl->level-1; i >= 0; i--) {\n        /* store rank that is crossed to reach the insert position */\n        rank[i] = i == (zsl->level-1) ? 0 : rank[i+1];\n        while (x->level[i].forward &&\n            (x->level[i].forward->score < score ||\n                (x->level[i].forward->score == score &&\n                compareStringObjects(x->level[i].forward->obj,obj) < 0))) {\n            rank[i] += x->level[i].span;\n            x = x->level[i].forward;\n        }\n        update[i] = x;\n    }\n    /* we assume the key is not already inside, since we allow duplicated\n     * scores, and the re-insertion of score and redis object should never\n     * happen since the caller of zslInsert() should test in the hash table\n     * if the element is already inside or not. */\n    level = zslRandomLevel();\n    if (level > zsl->level) {\n        for (i = zsl->level; i < level; i++) {\n            rank[i] = 0;\n            update[i] = zsl->header;\n            update[i]->level[i].span = zsl->length;\n        }\n        zsl->level = level;\n    }\n    x = zslCreateNode(level,score,obj);\n    for (i = 0; i < level; i++) {\n        x->level[i].forward = update[i]->level[i].forward;\n        update[i]->level[i].forward = x;\n\n        /* update span covered by update[i] as x is inserted here */\n        x->level[i].span = update[i]->level[i].span - (rank[0] - rank[i]);\n        update[i]->level[i].span = (rank[0] - rank[i]) + 1;\n    }\n\n    /* increment span for untouched levels */\n    for (i = level; i < zsl->level; i++) {\n        update[i]->level[i].span++;\n    }\n\n    x->backward = (update[0] == zsl->header) ? NULL : update[0];\n    if (x->level[0].forward)\n        x->level[0].forward->backward = x;\n    else\n        zsl->tail = x;\n    zsl->length++;\n    return x;\n}\n\n/* Internal function used by zslDelete, zslDeleteByScore and zslDeleteByRank */\nvoid zslDeleteNode(zskiplist *zsl, zskiplistNode *x, zskiplistNode **update) {\n    int i;\n    for (i = 0; i < zsl->level; i++) {\n        if (update[i]->level[i].forward == x) {\n            update[i]->level[i].span += x->level[i].span - 1;\n            update[i]->level[i].forward = x->level[i].forward;\n        } else {\n            update[i]->level[i].span -= 1;\n        }\n    }\n    if (x->level[0].forward) {\n        x->level[0].forward->backward = x->backward;\n    } else {\n        zsl->tail = x->backward;\n    }\n    while(zsl->level > 1 && zsl->header->level[zsl->level-1].forward == NULL)\n        zsl->level--;\n    zsl->length--;\n}\n\n/* Delete an element with matching score/object from the skiplist. */\nint zslDelete(zskiplist *zsl, double score, robj *obj) {\n    zskiplistNode *update[ZSKIPLIST_MAXLEVEL], *x;\n    int i;\n\n    x = zsl->header;\n    for (i = zsl->level-1; i >= 0; i--) {\n        while (x->level[i].forward &&\n            (x->level[i].forward->score < score ||\n                (x->level[i].forward->score == score &&\n                compareStringObjects(x->level[i].forward->obj,obj) < 0)))\n            x = x->level[i].forward;\n        update[i] = x;\n    }\n    /* We may have multiple elements with the same score, what we need\n     * is to find the element with both the right score and object. */\n    x = x->level[0].forward;\n    if (x && score == x->score && equalStringObjects(x->obj,obj)) {\n        zslDeleteNode(zsl, x, update);\n        zslFreeNode(x);\n        return 1;\n    }\n    return 0; /* not found */\n}\n\nstatic int zslValueGteMin(double value, zrangespec *spec) {\n    return spec->minex ? (value > spec->min) : (value >= spec->min);\n}\n\nstatic int zslValueLteMax(double value, zrangespec *spec) {\n    return spec->maxex ? (value < spec->max) : (value <= spec->max);\n}\n\n/* Returns if there is a part of the zset is in range. */\nint zslIsInRange(zskiplist *zsl, zrangespec *range) {\n    zskiplistNode *x;\n\n    /* Test for ranges that will always be empty. */\n    if (range->min > range->max ||\n            (range->min == range->max && (range->minex || range->maxex)))\n        return 0;\n    x = zsl->tail;\n    if (x == NULL || !zslValueGteMin(x->score,range))\n        return 0;\n    x = zsl->header->level[0].forward;\n    if (x == NULL || !zslValueLteMax(x->score,range))\n        return 0;\n    return 1;\n}\n\n/* Find the first node that is contained in the specified range.\n * Returns NULL when no element is contained in the range. */\nzskiplistNode *zslFirstInRange(zskiplist *zsl, zrangespec *range) {\n    zskiplistNode *x;\n    int i;\n\n    /* If everything is out of range, return early. */\n    if (!zslIsInRange(zsl,range)) return NULL;\n\n    x = zsl->header;\n    for (i = zsl->level-1; i >= 0; i--) {\n        /* Go forward while *OUT* of range. */\n        while (x->level[i].forward &&\n            !zslValueGteMin(x->level[i].forward->score,range))\n                x = x->level[i].forward;\n    }\n\n    /* This is an inner range, so the next node cannot be NULL. */\n    x = x->level[0].forward;\n    redisAssert(x != NULL);\n\n    /* Check if score <= max. */\n    if (!zslValueLteMax(x->score,range)) return NULL;\n    return x;\n}\n\n/* Find the last node that is contained in the specified range.\n * Returns NULL when no element is contained in the range. */\nzskiplistNode *zslLastInRange(zskiplist *zsl, zrangespec *range) {\n    zskiplistNode *x;\n    int i;\n\n    /* If everything is out of range, return early. */\n    if (!zslIsInRange(zsl,range)) return NULL;\n\n    x = zsl->header;\n    for (i = zsl->level-1; i >= 0; i--) {\n        /* Go forward while *IN* range. */\n        while (x->level[i].forward &&\n            zslValueLteMax(x->level[i].forward->score,range))\n                x = x->level[i].forward;\n    }\n\n    /* This is an inner range, so this node cannot be NULL. */\n    redisAssert(x != NULL);\n\n    /* Check if score >= min. */\n    if (!zslValueGteMin(x->score,range)) return NULL;\n    return x;\n}\n\n/* Delete all the elements with score between min and max from the skiplist.\n * Min and max are inclusive, so a score >= min || score <= max is deleted.\n * Note that this function takes the reference to the hash table view of the\n * sorted set, in order to remove the elements from the hash table too. */\nunsigned long zslDeleteRangeByScore(zskiplist *zsl, zrangespec *range, dict *dict) {\n    zskiplistNode *update[ZSKIPLIST_MAXLEVEL], *x;\n    unsigned long removed = 0;\n    int i;\n\n    x = zsl->header;\n    for (i = zsl->level-1; i >= 0; i--) {\n        while (x->level[i].forward && (range->minex ?\n            x->level[i].forward->score <= range->min :\n            x->level[i].forward->score < range->min))\n                x = x->level[i].forward;\n        update[i] = x;\n    }\n\n    /* Current node is the last with score < or <= min. */\n    x = x->level[0].forward;\n\n    /* Delete nodes while in range. */\n    while (x &&\n           (range->maxex ? x->score < range->max : x->score <= range->max))\n    {\n        zskiplistNode *next = x->level[0].forward;\n        zslDeleteNode(zsl,x,update);\n        dictDelete(dict,x->obj);\n        zslFreeNode(x);\n        removed++;\n        x = next;\n    }\n    return removed;\n}\n\nunsigned long zslDeleteRangeByLex(zskiplist *zsl, zlexrangespec *range, dict *dict) {\n    zskiplistNode *update[ZSKIPLIST_MAXLEVEL], *x;\n    unsigned long removed = 0;\n    int i;\n\n\n    x = zsl->header;\n    for (i = zsl->level-1; i >= 0; i--) {\n        while (x->level[i].forward &&\n            !zslLexValueGteMin(x->level[i].forward->obj,range))\n                x = x->level[i].forward;\n        update[i] = x;\n    }\n\n    /* Current node is the last with score < or <= min. */\n    x = x->level[0].forward;\n\n    /* Delete nodes while in range. */\n    while (x && zslLexValueLteMax(x->obj,range)) {\n        zskiplistNode *next = x->level[0].forward;\n        zslDeleteNode(zsl,x,update);\n        dictDelete(dict,x->obj);\n        zslFreeNode(x);\n        removed++;\n        x = next;\n    }\n    return removed;\n}\n\n/* Delete all the elements with rank between start and end from the skiplist.\n * Start and end are inclusive. Note that start and end need to be 1-based */\nunsigned long zslDeleteRangeByRank(zskiplist *zsl, unsigned int start, unsigned int end, dict *dict) {\n    zskiplistNode *update[ZSKIPLIST_MAXLEVEL], *x;\n    unsigned long traversed = 0, removed = 0;\n    int i;\n\n    x = zsl->header;\n    for (i = zsl->level-1; i >= 0; i--) {\n        while (x->level[i].forward && (traversed + x->level[i].span) < start) {\n            traversed += x->level[i].span;\n            x = x->level[i].forward;\n        }\n        update[i] = x;\n    }\n\n    traversed++;\n    x = x->level[0].forward;\n    while (x && traversed <= end) {\n        zskiplistNode *next = x->level[0].forward;\n        zslDeleteNode(zsl,x,update);\n        dictDelete(dict,x->obj);\n        zslFreeNode(x);\n        removed++;\n        traversed++;\n        x = next;\n    }\n    return removed;\n}\n\n/* Find the rank for an element by both score and key.\n * Returns 0 when the element cannot be found, rank otherwise.\n * Note that the rank is 1-based due to the span of zsl->header to the\n * first element. */\nunsigned long zslGetRank(zskiplist *zsl, double score, robj *o) {\n    zskiplistNode *x;\n    unsigned long rank = 0;\n    int i;\n\n    x = zsl->header;\n    for (i = zsl->level-1; i >= 0; i--) {\n        while (x->level[i].forward &&\n            (x->level[i].forward->score < score ||\n                (x->level[i].forward->score == score &&\n                compareStringObjects(x->level[i].forward->obj,o) <= 0))) {\n            rank += x->level[i].span;\n            x = x->level[i].forward;\n        }\n\n        /* x might be equal to zsl->header, so test if obj is non-NULL */\n        if (x->obj && equalStringObjects(x->obj,o)) {\n            return rank;\n        }\n    }\n    return 0;\n}\n\n/* Finds an element by its rank. The rank argument needs to be 1-based. */\nzskiplistNode* zslGetElementByRank(zskiplist *zsl, unsigned long rank) {\n    zskiplistNode *x;\n    unsigned long traversed = 0;\n    int i;\n\n    x = zsl->header;\n    for (i = zsl->level-1; i >= 0; i--) {\n        while (x->level[i].forward && (traversed + x->level[i].span) <= rank)\n        {\n            traversed += x->level[i].span;\n            x = x->level[i].forward;\n        }\n        if (traversed == rank) {\n            return x;\n        }\n    }\n    return NULL;\n}\n\n/* Populate the rangespec according to the objects min and max. */\nstatic int zslParseRange(robj *min, robj *max, zrangespec *spec) {\n    char *eptr;\n    spec->minex = spec->maxex = 0;\n\n    /* Parse the min-max interval. If one of the values is prefixed\n     * by the \"(\" character, it's considered \"open\". For instance\n     * ZRANGEBYSCORE zset (1.5 (2.5 will match min < x < max\n     * ZRANGEBYSCORE zset 1.5 2.5 will instead match min <= x <= max */\n    if (min->encoding == REDIS_ENCODING_INT) {\n        spec->min = (long)min->ptr;\n    } else {\n        if (((char*)min->ptr)[0] == '(') {\n            spec->min = strtod((char*)min->ptr+1,&eptr);\n            if (eptr[0] != '\\0' || isnan(spec->min)) return REDIS_ERR;\n            spec->minex = 1;\n        } else {\n            spec->min = strtod((char*)min->ptr,&eptr);\n            if (eptr[0] != '\\0' || isnan(spec->min)) return REDIS_ERR;\n        }\n    }\n    if (max->encoding == REDIS_ENCODING_INT) {\n        spec->max = (long)max->ptr;\n    } else {\n        if (((char*)max->ptr)[0] == '(') {\n            spec->max = strtod((char*)max->ptr+1,&eptr);\n            if (eptr[0] != '\\0' || isnan(spec->max)) return REDIS_ERR;\n            spec->maxex = 1;\n        } else {\n            spec->max = strtod((char*)max->ptr,&eptr);\n            if (eptr[0] != '\\0' || isnan(spec->max)) return REDIS_ERR;\n        }\n    }\n\n    return REDIS_OK;\n}\n\n/* ------------------------ Lexicographic ranges ---------------------------- */\n\n/* Parse max or min argument of ZRANGEBYLEX.\n  * (foo means foo (open interval)\n  * [foo means foo (closed interval)\n  * - means the min string possible\n  * + means the max string possible\n  *\n  * If the string is valid the *dest pointer is set to the redis object\n  * that will be used for the comparision, and ex will be set to 0 or 1\n  * respectively if the item is exclusive or inclusive. REDIS_OK will be\n  * returned.\n  *\n  * If the string is not a valid range REDIS_ERR is returned, and the value\n  * of *dest and *ex is undefined. */\nint zslParseLexRangeItem(robj *item, robj **dest, int *ex) {\n    char *c = item->ptr;\n\n    switch(c[0]) {\n    case '+':\n        if (c[1] != '\\0') return REDIS_ERR;\n        *ex = 0;\n        *dest = shared.maxstring;\n        incrRefCount(shared.maxstring);\n        return REDIS_OK;\n    case '-':\n        if (c[1] != '\\0') return REDIS_ERR;\n        *ex = 0;\n        *dest = shared.minstring;\n        incrRefCount(shared.minstring);\n        return REDIS_OK;\n    case '(':\n        *ex = 1;\n        *dest = createStringObject(c+1,sdslen(c)-1);\n        return REDIS_OK;\n    case '[':\n        *ex = 0;\n        *dest = createStringObject(c+1,sdslen(c)-1);\n        return REDIS_OK;\n    default:\n        return REDIS_ERR;\n    }\n}\n\n/* Populate the rangespec according to the objects min and max.\n *\n * Return REDIS_OK on success. On error REDIS_ERR is returned.\n * When OK is returned the structure must be freed with zslFreeLexRange(),\n * otherwise no release is needed. */\nstatic int zslParseLexRange(robj *min, robj *max, zlexrangespec *spec) {\n    /* The range can't be valid if objects are integer encoded.\n     * Every item must start with ( or [. */\n    if (min->encoding == REDIS_ENCODING_INT ||\n        max->encoding == REDIS_ENCODING_INT) return REDIS_ERR;\n\n    spec->min = spec->max = NULL;\n    if (zslParseLexRangeItem(min, &spec->min, &spec->minex) == REDIS_ERR ||\n        zslParseLexRangeItem(max, &spec->max, &spec->maxex) == REDIS_ERR) {\n        if (spec->min) decrRefCount(spec->min);\n        if (spec->max) decrRefCount(spec->max);\n        return REDIS_ERR;\n    } else {\n        return REDIS_OK;\n    }\n}\n\n/* Free a lex range structure, must be called only after zelParseLexRange()\n * populated the structure with success (REDIS_OK returned). */\nvoid zslFreeLexRange(zlexrangespec *spec) {\n    decrRefCount(spec->min);\n    decrRefCount(spec->max);\n}\n\n/* This is just a wrapper to compareStringObjects() that is able to\n * handle shared.minstring and shared.maxstring as the equivalent of\n * -inf and +inf for strings */\nint compareStringObjectsForLexRange(robj *a, robj *b) {\n    if (a == b) return 0; /* This makes sure that we handle inf,inf and\n                             -inf,-inf ASAP. One special case less. */\n    if (a == shared.minstring || b == shared.maxstring) return -1;\n    if (a == shared.maxstring || b == shared.minstring) return 1;\n    return compareStringObjects(a,b);\n}\n\nstatic int zslLexValueGteMin(robj *value, zlexrangespec *spec) {\n    return spec->minex ?\n        (compareStringObjectsForLexRange(value,spec->min) > 0) :\n        (compareStringObjectsForLexRange(value,spec->min) >= 0);\n}\n\nstatic int zslLexValueLteMax(robj *value, zlexrangespec *spec) {\n    return spec->maxex ?\n        (compareStringObjectsForLexRange(value,spec->max) < 0) :\n        (compareStringObjectsForLexRange(value,spec->max) <= 0);\n}\n\n/* Returns if there is a part of the zset is in the lex range. */\nint zslIsInLexRange(zskiplist *zsl, zlexrangespec *range) {\n    zskiplistNode *x;\n\n    /* Test for ranges that will always be empty. */\n    if (compareStringObjectsForLexRange(range->min,range->max) > 1 ||\n            (compareStringObjects(range->min,range->max) == 0 &&\n            (range->minex || range->maxex)))\n        return 0;\n    x = zsl->tail;\n    if (x == NULL || !zslLexValueGteMin(x->obj,range))\n        return 0;\n    x = zsl->header->level[0].forward;\n    if (x == NULL || !zslLexValueLteMax(x->obj,range))\n        return 0;\n    return 1;\n}\n\n/* Find the first node that is contained in the specified lex range.\n * Returns NULL when no element is contained in the range. */\nzskiplistNode *zslFirstInLexRange(zskiplist *zsl, zlexrangespec *range) {\n    zskiplistNode *x;\n    int i;\n\n    /* If everything is out of range, return early. */\n    if (!zslIsInLexRange(zsl,range)) return NULL;\n\n    x = zsl->header;\n    for (i = zsl->level-1; i >= 0; i--) {\n        /* Go forward while *OUT* of range. */\n        while (x->level[i].forward &&\n            !zslLexValueGteMin(x->level[i].forward->obj,range))\n                x = x->level[i].forward;\n    }\n\n    /* This is an inner range, so the next node cannot be NULL. */\n    x = x->level[0].forward;\n    redisAssert(x != NULL);\n\n    /* Check if score <= max. */\n    if (!zslLexValueLteMax(x->obj,range)) return NULL;\n    return x;\n}\n\n/* Find the last node that is contained in the specified range.\n * Returns NULL when no element is contained in the range. */\nzskiplistNode *zslLastInLexRange(zskiplist *zsl, zlexrangespec *range) {\n    zskiplistNode *x;\n    int i;\n\n    /* If everything is out of range, return early. */\n    if (!zslIsInLexRange(zsl,range)) return NULL;\n\n    x = zsl->header;\n    for (i = zsl->level-1; i >= 0; i--) {\n        /* Go forward while *IN* range. */\n        while (x->level[i].forward &&\n            zslLexValueLteMax(x->level[i].forward->obj,range))\n                x = x->level[i].forward;\n    }\n\n    /* This is an inner range, so this node cannot be NULL. */\n    redisAssert(x != NULL);\n\n    /* Check if score >= min. */\n    if (!zslLexValueGteMin(x->obj,range)) return NULL;\n    return x;\n}\n\n/*-----------------------------------------------------------------------------\n * Ziplist-backed sorted set API\n *----------------------------------------------------------------------------*/\n\ndouble zzlGetScore(unsigned char *sptr) {\n    unsigned char *vstr;\n    unsigned int vlen;\n    long long vlong;\n    char buf[128];\n    double score;\n\n    redisAssert(sptr != NULL);\n    redisAssert(ziplistGet(sptr,&vstr,&vlen,&vlong));\n\n    if (vstr) {\n        memcpy(buf,vstr,vlen);\n        buf[vlen] = '\\0';\n        score = strtod(buf,NULL);\n    } else {\n        score = vlong;\n    }\n\n    return score;\n}\n\n/* Return a ziplist element as a Redis string object.\n * This simple abstraction can be used to simplifies some code at the\n * cost of some performance. */\nrobj *ziplistGetObject(unsigned char *sptr) {\n    unsigned char *vstr;\n    unsigned int vlen;\n    long long vlong;\n\n    redisAssert(sptr != NULL);\n    redisAssert(ziplistGet(sptr,&vstr,&vlen,&vlong));\n\n    if (vstr) {\n        return createStringObject((char*)vstr,vlen);\n    } else {\n        return createStringObjectFromLongLong(vlong);\n    }\n}\n\n/* Compare element in sorted set with given element. */\nint zzlCompareElements(unsigned char *eptr, unsigned char *cstr, unsigned int clen) {\n    unsigned char *vstr;\n    unsigned int vlen;\n    long long vlong;\n    unsigned char vbuf[32];\n    int minlen, cmp;\n\n    redisAssert(ziplistGet(eptr,&vstr,&vlen,&vlong));\n    if (vstr == NULL) {\n        /* Store string representation of long long in buf. */\n        vlen = ll2string((char*)vbuf,sizeof(vbuf),vlong);\n        vstr = vbuf;\n    }\n\n    minlen = (vlen < clen) ? vlen : clen;\n    cmp = memcmp(vstr,cstr,minlen);\n    if (cmp == 0) return vlen-clen;\n    return cmp;\n}\n\nunsigned int zzlLength(unsigned char *zl) {\n    return ziplistLen(zl)/2;\n}\n\n/* Move to next entry based on the values in eptr and sptr. Both are set to\n * NULL when there is no next entry. */\nvoid zzlNext(unsigned char *zl, unsigned char **eptr, unsigned char **sptr) {\n    unsigned char *_eptr, *_sptr;\n    redisAssert(*eptr != NULL && *sptr != NULL);\n\n    _eptr = ziplistNext(zl,*sptr);\n    if (_eptr != NULL) {\n        _sptr = ziplistNext(zl,_eptr);\n        redisAssert(_sptr != NULL);\n    } else {\n        /* No next entry. */\n        _sptr = NULL;\n    }\n\n    *eptr = _eptr;\n    *sptr = _sptr;\n}\n\n/* Move to the previous entry based on the values in eptr and sptr. Both are\n * set to NULL when there is no next entry. */\nvoid zzlPrev(unsigned char *zl, unsigned char **eptr, unsigned char **sptr) {\n    unsigned char *_eptr, *_sptr;\n    redisAssert(*eptr != NULL && *sptr != NULL);\n\n    _sptr = ziplistPrev(zl,*eptr);\n    if (_sptr != NULL) {\n        _eptr = ziplistPrev(zl,_sptr);\n        redisAssert(_eptr != NULL);\n    } else {\n        /* No previous entry. */\n        _eptr = NULL;\n    }\n\n    *eptr = _eptr;\n    *sptr = _sptr;\n}\n\n/* Returns if there is a part of the zset is in range. Should only be used\n * internally by zzlFirstInRange and zzlLastInRange. */\nint zzlIsInRange(unsigned char *zl, zrangespec *range) {\n    unsigned char *p;\n    double score;\n\n    /* Test for ranges that will always be empty. */\n    if (range->min > range->max ||\n            (range->min == range->max && (range->minex || range->maxex)))\n        return 0;\n\n    p = ziplistIndex(zl,-1); /* Last score. */\n    if (p == NULL) return 0; /* Empty sorted set */\n    score = zzlGetScore(p);\n    if (!zslValueGteMin(score,range))\n        return 0;\n\n    p = ziplistIndex(zl,1); /* First score. */\n    redisAssert(p != NULL);\n    score = zzlGetScore(p);\n    if (!zslValueLteMax(score,range))\n        return 0;\n\n    return 1;\n}\n\n/* Find pointer to the first element contained in the specified range.\n * Returns NULL when no element is contained in the range. */\nunsigned char *zzlFirstInRange(unsigned char *zl, zrangespec *range) {\n    unsigned char *eptr = ziplistIndex(zl,0), *sptr;\n    double score;\n\n    /* If everything is out of range, return early. */\n    if (!zzlIsInRange(zl,range)) return NULL;\n\n    while (eptr != NULL) {\n        sptr = ziplistNext(zl,eptr);\n        redisAssert(sptr != NULL);\n\n        score = zzlGetScore(sptr);\n        if (zslValueGteMin(score,range)) {\n            /* Check if score <= max. */\n            if (zslValueLteMax(score,range))\n                return eptr;\n            return NULL;\n        }\n\n        /* Move to next element. */\n        eptr = ziplistNext(zl,sptr);\n    }\n\n    return NULL;\n}\n\n/* Find pointer to the last element contained in the specified range.\n * Returns NULL when no element is contained in the range. */\nunsigned char *zzlLastInRange(unsigned char *zl, zrangespec *range) {\n    unsigned char *eptr = ziplistIndex(zl,-2), *sptr;\n    double score;\n\n    /* If everything is out of range, return early. */\n    if (!zzlIsInRange(zl,range)) return NULL;\n\n    while (eptr != NULL) {\n        sptr = ziplistNext(zl,eptr);\n        redisAssert(sptr != NULL);\n\n        score = zzlGetScore(sptr);\n        if (zslValueLteMax(score,range)) {\n            /* Check if score >= min. */\n            if (zslValueGteMin(score,range))\n                return eptr;\n            return NULL;\n        }\n\n        /* Move to previous element by moving to the score of previous element.\n         * When this returns NULL, we know there also is no element. */\n        sptr = ziplistPrev(zl,eptr);\n        if (sptr != NULL)\n            redisAssert((eptr = ziplistPrev(zl,sptr)) != NULL);\n        else\n            eptr = NULL;\n    }\n\n    return NULL;\n}\n\nstatic int zzlLexValueGteMin(unsigned char *p, zlexrangespec *spec) {\n    robj *value = ziplistGetObject(p);\n    int res = zslLexValueGteMin(value,spec);\n    decrRefCount(value);\n    return res;\n}\n\nstatic int zzlLexValueLteMax(unsigned char *p, zlexrangespec *spec) {\n    robj *value = ziplistGetObject(p);\n    int res = zslLexValueLteMax(value,spec);\n    decrRefCount(value);\n    return res;\n}\n\n/* Returns if there is a part of the zset is in range. Should only be used\n * internally by zzlFirstInRange and zzlLastInRange. */\nint zzlIsInLexRange(unsigned char *zl, zlexrangespec *range) {\n    unsigned char *p;\n\n    /* Test for ranges that will always be empty. */\n    if (compareStringObjectsForLexRange(range->min,range->max) > 1 ||\n            (compareStringObjects(range->min,range->max) == 0 &&\n            (range->minex || range->maxex)))\n        return 0;\n\n    p = ziplistIndex(zl,-2); /* Last element. */\n    if (p == NULL) return 0;\n    if (!zzlLexValueGteMin(p,range))\n        return 0;\n\n    p = ziplistIndex(zl,0); /* First element. */\n    redisAssert(p != NULL);\n    if (!zzlLexValueLteMax(p,range))\n        return 0;\n\n    return 1;\n}\n\n/* Find pointer to the first element contained in the specified lex range.\n * Returns NULL when no element is contained in the range. */\nunsigned char *zzlFirstInLexRange(unsigned char *zl, zlexrangespec *range) {\n    unsigned char *eptr = ziplistIndex(zl,0), *sptr;\n\n    /* If everything is out of range, return early. */\n    if (!zzlIsInLexRange(zl,range)) return NULL;\n\n    while (eptr != NULL) {\n        if (zzlLexValueGteMin(eptr,range)) {\n            /* Check if score <= max. */\n            if (zzlLexValueLteMax(eptr,range))\n                return eptr;\n            return NULL;\n        }\n\n        /* Move to next element. */\n        sptr = ziplistNext(zl,eptr); /* This element score. Skip it. */\n        redisAssert(sptr != NULL);\n        eptr = ziplistNext(zl,sptr); /* Next element. */\n    }\n\n    return NULL;\n}\n\n/* Find pointer to the last element contained in the specified lex range.\n * Returns NULL when no element is contained in the range. */\nunsigned char *zzlLastInLexRange(unsigned char *zl, zlexrangespec *range) {\n    unsigned char *eptr = ziplistIndex(zl,-2), *sptr;\n\n    /* If everything is out of range, return early. */\n    if (!zzlIsInLexRange(zl,range)) return NULL;\n\n    while (eptr != NULL) {\n        if (zzlLexValueLteMax(eptr,range)) {\n            /* Check if score >= min. */\n            if (zzlLexValueGteMin(eptr,range))\n                return eptr;\n            return NULL;\n        }\n\n        /* Move to previous element by moving to the score of previous element.\n         * When this returns NULL, we know there also is no element. */\n        sptr = ziplistPrev(zl,eptr);\n        if (sptr != NULL)\n            redisAssert((eptr = ziplistPrev(zl,sptr)) != NULL);\n        else\n            eptr = NULL;\n    }\n\n    return NULL;\n}\n\nunsigned char *zzlFind(unsigned char *zl, robj *ele, double *score) {\n    unsigned char *eptr = ziplistIndex(zl,0), *sptr;\n\n    ele = getDecodedObject(ele);\n    while (eptr != NULL) {\n        sptr = ziplistNext(zl,eptr);\n        redisAssertWithInfo(NULL,ele,sptr != NULL);\n\n        if (ziplistCompare(eptr,ele->ptr,sdslen(ele->ptr))) {\n            /* Matching element, pull out score. */\n            if (score != NULL) *score = zzlGetScore(sptr);\n            decrRefCount(ele);\n            return eptr;\n        }\n\n        /* Move to next element. */\n        eptr = ziplistNext(zl,sptr);\n    }\n\n    decrRefCount(ele);\n    return NULL;\n}\n\n/* Delete (element,score) pair from ziplist. Use local copy of eptr because we\n * don't want to modify the one given as argument. */\nunsigned char *zzlDelete(unsigned char *zl, unsigned char *eptr) {\n    unsigned char *p = eptr;\n\n    /* TODO: add function to ziplist API to delete N elements from offset. */\n    zl = ziplistDelete(zl,&p);\n    zl = ziplistDelete(zl,&p);\n    return zl;\n}\n\nunsigned char *zzlInsertAt(unsigned char *zl, unsigned char *eptr, robj *ele, double score) {\n    unsigned char *sptr;\n    char scorebuf[128];\n    int scorelen;\n    size_t offset;\n\n    redisAssertWithInfo(NULL,ele,ele->encoding == REDIS_ENCODING_RAW);\n    scorelen = d2string(scorebuf,sizeof(scorebuf),score);\n    if (eptr == NULL) {\n        zl = ziplistPush(zl,ele->ptr,sdslen(ele->ptr),ZIPLIST_TAIL);\n        zl = ziplistPush(zl,(unsigned char*)scorebuf,scorelen,ZIPLIST_TAIL);\n    } else {\n        /* Keep offset relative to zl, as it might be re-allocated. */\n        offset = eptr-zl;\n        zl = ziplistInsert(zl,eptr,ele->ptr,sdslen(ele->ptr));\n        eptr = zl+offset;\n\n        /* Insert score after the element. */\n        redisAssertWithInfo(NULL,ele,(sptr = ziplistNext(zl,eptr)) != NULL);\n        zl = ziplistInsert(zl,sptr,(unsigned char*)scorebuf,scorelen);\n    }\n\n    return zl;\n}\n\n/* Insert (element,score) pair in ziplist. This function assumes the element is\n * not yet present in the list. */\nunsigned char *zzlInsert(unsigned char *zl, robj *ele, double score) {\n    unsigned char *eptr = ziplistIndex(zl,0), *sptr;\n    double s;\n\n    ele = getDecodedObject(ele);\n    while (eptr != NULL) {\n        sptr = ziplistNext(zl,eptr);\n        redisAssertWithInfo(NULL,ele,sptr != NULL);\n        s = zzlGetScore(sptr);\n\n        if (s > score) {\n            /* First element with score larger than score for element to be\n             * inserted. This means we should take its spot in the list to\n             * maintain ordering. */\n            zl = zzlInsertAt(zl,eptr,ele,score);\n            break;\n        } else if (s == score) {\n            /* Ensure lexicographical ordering for elements. */\n            if (zzlCompareElements(eptr,ele->ptr,sdslen(ele->ptr)) > 0) {\n                zl = zzlInsertAt(zl,eptr,ele,score);\n                break;\n            }\n        }\n\n        /* Move to next element. */\n        eptr = ziplistNext(zl,sptr);\n    }\n\n    /* Push on tail of list when it was not yet inserted. */\n    if (eptr == NULL)\n        zl = zzlInsertAt(zl,NULL,ele,score);\n\n    decrRefCount(ele);\n    return zl;\n}\n\nunsigned char *zzlDeleteRangeByScore(unsigned char *zl, zrangespec *range, unsigned long *deleted) {\n    unsigned char *eptr, *sptr;\n    double score;\n    unsigned long num = 0;\n\n    if (deleted != NULL) *deleted = 0;\n\n    eptr = zzlFirstInRange(zl,range);\n    if (eptr == NULL) return zl;\n\n    /* When the tail of the ziplist is deleted, eptr will point to the sentinel\n     * byte and ziplistNext will return NULL. */\n    while ((sptr = ziplistNext(zl,eptr)) != NULL) {\n        score = zzlGetScore(sptr);\n        if (zslValueLteMax(score,range)) {\n            /* Delete both the element and the score. */\n            zl = ziplistDelete(zl,&eptr);\n            zl = ziplistDelete(zl,&eptr);\n            num++;\n        } else {\n            /* No longer in range. */\n            break;\n        }\n    }\n\n    if (deleted != NULL) *deleted = num;\n    return zl;\n}\n\nunsigned char *zzlDeleteRangeByLex(unsigned char *zl, zlexrangespec *range, unsigned long *deleted) {\n    unsigned char *eptr, *sptr;\n    unsigned long num = 0;\n\n    if (deleted != NULL) *deleted = 0;\n\n    eptr = zzlFirstInLexRange(zl,range);\n    if (eptr == NULL) return zl;\n\n    /* When the tail of the ziplist is deleted, eptr will point to the sentinel\n     * byte and ziplistNext will return NULL. */\n    while ((sptr = ziplistNext(zl,eptr)) != NULL) {\n        if (zzlLexValueLteMax(eptr,range)) {\n            /* Delete both the element and the score. */\n            zl = ziplistDelete(zl,&eptr);\n            zl = ziplistDelete(zl,&eptr);\n            num++;\n        } else {\n            /* No longer in range. */\n            break;\n        }\n    }\n\n    if (deleted != NULL) *deleted = num;\n    return zl;\n}\n\n/* Delete all the elements with rank between start and end from the skiplist.\n * Start and end are inclusive. Note that start and end need to be 1-based */\nunsigned char *zzlDeleteRangeByRank(unsigned char *zl, unsigned int start, unsigned int end, unsigned long *deleted) {\n    unsigned int num = (end-start)+1;\n    if (deleted) *deleted = num;\n    zl = ziplistDeleteRange(zl,2*(start-1),2*num);\n    return zl;\n}\n\n/*-----------------------------------------------------------------------------\n * Common sorted set API\n *----------------------------------------------------------------------------*/\n\nunsigned int zsetLength(robj *zobj) {\n    int length = -1;\n    if (zobj->encoding == REDIS_ENCODING_ZIPLIST) {\n        length = zzlLength(zobj->ptr);\n    } else if (zobj->encoding == REDIS_ENCODING_SKIPLIST) {\n        length = ((zset*)zobj->ptr)->zsl->length;\n    } else {\n        redisPanic(\"Unknown sorted set encoding\");\n    }\n    return length;\n}\n\nvoid zsetConvert(robj *zobj, int encoding) {\n    zset *zs;\n    zskiplistNode *node, *next;\n    robj *ele;\n    double score;\n\n    if (zobj->encoding == encoding) return;\n    if (zobj->encoding == REDIS_ENCODING_ZIPLIST) {\n        unsigned char *zl = zobj->ptr;\n        unsigned char *eptr, *sptr;\n        unsigned char *vstr;\n        unsigned int vlen;\n        long long vlong;\n\n        if (encoding != REDIS_ENCODING_SKIPLIST)\n            redisPanic(\"Unknown target encoding\");\n\n        zs = zmalloc(sizeof(*zs));\n        zs->dict = dictCreate(&zsetDictType,NULL);\n        zs->zsl = zslCreate();\n\n        eptr = ziplistIndex(zl,0);\n        redisAssertWithInfo(NULL,zobj,eptr != NULL);\n        sptr = ziplistNext(zl,eptr);\n        redisAssertWithInfo(NULL,zobj,sptr != NULL);\n\n        while (eptr != NULL) {\n            score = zzlGetScore(sptr);\n            redisAssertWithInfo(NULL,zobj,ziplistGet(eptr,&vstr,&vlen,&vlong));\n            if (vstr == NULL)\n                ele = createStringObjectFromLongLong(vlong);\n            else\n                ele = createStringObject((char*)vstr,vlen);\n\n            /* Has incremented refcount since it was just created. */\n            node = zslInsert(zs->zsl,score,ele);\n            redisAssertWithInfo(NULL,zobj,dictAdd(zs->dict,ele,&node->score) == DICT_OK);\n            incrRefCount(ele); /* Added to dictionary. */\n            zzlNext(zl,&eptr,&sptr);\n        }\n\n        zfree(zobj->ptr);\n        zobj->ptr = zs;\n        zobj->encoding = REDIS_ENCODING_SKIPLIST;\n    } else if (zobj->encoding == REDIS_ENCODING_SKIPLIST) {\n        unsigned char *zl = ziplistNew();\n\n        if (encoding != REDIS_ENCODING_ZIPLIST)\n            redisPanic(\"Unknown target encoding\");\n\n        /* Approach similar to zslFree(), since we want to free the skiplist at\n         * the same time as creating the ziplist. */\n        zs = zobj->ptr;\n        dictRelease(zs->dict);\n        node = zs->zsl->header->level[0].forward;\n        zfree(zs->zsl->header);\n        zfree(zs->zsl);\n\n        while (node) {\n            ele = getDecodedObject(node->obj);\n            zl = zzlInsertAt(zl,NULL,ele,node->score);\n            decrRefCount(ele);\n\n            next = node->level[0].forward;\n            zslFreeNode(node);\n            node = next;\n        }\n\n        zfree(zs);\n        zobj->ptr = zl;\n        zobj->encoding = REDIS_ENCODING_ZIPLIST;\n    } else {\n        redisPanic(\"Unknown sorted set encoding\");\n    }\n}\n\n/*-----------------------------------------------------------------------------\n * Sorted set commands\n *----------------------------------------------------------------------------*/\n\n/* This generic command implements both ZADD and ZINCRBY. */\nvoid zaddGenericCommand(redisClient *c, int incr) {\n    static char *nanerr = \"resulting score is not a number (NaN)\";\n    robj *key = c->argv[1];\n    robj *ele;\n    robj *zobj;\n    robj *curobj;\n    double score = 0, *scores = NULL, curscore = 0.0;\n    int j, elements = (c->argc-2)/2;\n    int added = 0, updated = 0;\n\n    if (c->argc % 2) {\n        addReply(c,shared.syntaxerr);\n        return;\n    }\n\n    /* Start parsing all the scores, we need to emit any syntax error\n     * before executing additions to the sorted set, as the command should\n     * either execute fully or nothing at all. */\n    scores = zmalloc(sizeof(double)*elements);\n    for (j = 0; j < elements; j++) {\n        if (getDoubleFromObjectOrReply(c,c->argv[2+j*2],&scores[j],NULL)\n            != REDIS_OK) goto cleanup;\n    }\n\n    /* Lookup the key and create the sorted set if does not exist. */\n    zobj = lookupKeyWrite(c->db,key);\n    if (zobj == NULL) {\n        if (server.zset_max_ziplist_entries == 0 ||\n            server.zset_max_ziplist_value < sdslen(c->argv[3]->ptr))\n        {\n            zobj = createZsetObject();\n        } else {\n            zobj = createZsetZiplistObject();\n        }\n        dbAdd(c->db,key,zobj);\n    } else {\n        if (zobj->type != REDIS_ZSET) {\n            addReply(c,shared.wrongtypeerr);\n            goto cleanup;\n        }\n    }\n\n    for (j = 0; j < elements; j++) {\n        score = scores[j];\n\n        if (zobj->encoding == REDIS_ENCODING_ZIPLIST) {\n            unsigned char *eptr;\n\n            /* Prefer non-encoded element when dealing with ziplists. */\n            ele = c->argv[3+j*2];\n            if ((eptr = zzlFind(zobj->ptr,ele,&curscore)) != NULL) {\n                if (incr) {\n                    score += curscore;\n                    if (isnan(score)) {\n                        addReplyError(c,nanerr);\n                        goto cleanup;\n                    }\n                }\n\n                /* Remove and re-insert when score changed. */\n                if (score != curscore) {\n                    zobj->ptr = zzlDelete(zobj->ptr,eptr);\n                    zobj->ptr = zzlInsert(zobj->ptr,ele,score);\n                    server.dirty++;\n                    updated++;\n                }\n            } else {\n                /* Optimize: check if the element is too large or the list\n                 * becomes too long *before* executing zzlInsert. */\n                zobj->ptr = zzlInsert(zobj->ptr,ele,score);\n                if (zzlLength(zobj->ptr) > server.zset_max_ziplist_entries)\n                    zsetConvert(zobj,REDIS_ENCODING_SKIPLIST);\n                if (sdslen(ele->ptr) > server.zset_max_ziplist_value)\n                    zsetConvert(zobj,REDIS_ENCODING_SKIPLIST);\n                server.dirty++;\n                added++;\n            }\n        } else if (zobj->encoding == REDIS_ENCODING_SKIPLIST) {\n            zset *zs = zobj->ptr;\n            zskiplistNode *znode;\n            dictEntry *de;\n\n            ele = c->argv[3+j*2] = tryObjectEncoding(c->argv[3+j*2]);\n            de = dictFind(zs->dict,ele);\n            if (de != NULL) {\n                curobj = dictGetKey(de);\n                curscore = *(double*)dictGetVal(de);\n\n                if (incr) {\n                    score += curscore;\n                    if (isnan(score)) {\n                        addReplyError(c,nanerr);\n                        /* Don't need to check if the sorted set is empty\n                         * because we know it has at least one element. */\n                        goto cleanup;\n                    }\n                }\n\n                /* Remove and re-insert when score changed. We can safely\n                 * delete the key object from the skiplist, since the\n                 * dictionary still has a reference to it. */\n                if (score != curscore) {\n                    redisAssertWithInfo(c,curobj,zslDelete(zs->zsl,curscore,curobj));\n                    znode = zslInsert(zs->zsl,score,curobj);\n                    incrRefCount(curobj); /* Re-inserted in skiplist. */\n                    dictGetVal(de) = &znode->score; /* Update score ptr. */\n                    server.dirty++;\n                    updated++;\n                }\n            } else {\n                znode = zslInsert(zs->zsl,score,ele);\n                incrRefCount(ele); /* Inserted in skiplist. */\n                redisAssertWithInfo(c,NULL,dictAdd(zs->dict,ele,&znode->score) == DICT_OK);\n                incrRefCount(ele); /* Added to dictionary. */\n                server.dirty++;\n                added++;\n            }\n        } else {\n            redisPanic(\"Unknown sorted set encoding\");\n        }\n    }\n    if (incr) /* ZINCRBY */\n        addReplyDouble(c,score);\n    else /* ZADD */\n        addReplyLongLong(c,added);\n\ncleanup:\n    zfree(scores);\n    if (added || updated) {\n        signalModifiedKey(c->db,key);\n        notifyKeyspaceEvent(REDIS_NOTIFY_ZSET,\n            incr ? \"zincr\" : \"zadd\", key, c->db->id);\n    }\n}\n\nvoid zaddCommand(redisClient *c) {\n    zaddGenericCommand(c,0);\n}\n\nvoid zincrbyCommand(redisClient *c) {\n    zaddGenericCommand(c,1);\n}\n\nvoid zremCommand(redisClient *c) {\n    robj *key = c->argv[1];\n    robj *zobj;\n    int deleted = 0, keyremoved = 0, j;\n\n    if ((zobj = lookupKeyWriteOrReply(c,key,shared.czero)) == NULL ||\n        checkType(c,zobj,REDIS_ZSET)) return;\n\n    if (zobj->encoding == REDIS_ENCODING_ZIPLIST) {\n        unsigned char *eptr;\n\n        for (j = 2; j < c->argc; j++) {\n            if ((eptr = zzlFind(zobj->ptr,c->argv[j],NULL)) != NULL) {\n                deleted++;\n                zobj->ptr = zzlDelete(zobj->ptr,eptr);\n                if (zzlLength(zobj->ptr) == 0) {\n                    dbDelete(c->db,key);\n                    keyremoved = 1;\n                    break;\n                }\n            }\n        }\n    } else if (zobj->encoding == REDIS_ENCODING_SKIPLIST) {\n        zset *zs = zobj->ptr;\n        dictEntry *de;\n        double score;\n\n        for (j = 2; j < c->argc; j++) {\n            de = dictFind(zs->dict,c->argv[j]);\n            if (de != NULL) {\n                deleted++;\n\n                /* Delete from the skiplist */\n                score = *(double*)dictGetVal(de);\n                redisAssertWithInfo(c,c->argv[j],zslDelete(zs->zsl,score,c->argv[j]));\n\n                /* Delete from the hash table */\n                dictDelete(zs->dict,c->argv[j]);\n                if (htNeedsResize(zs->dict)) dictResize(zs->dict);\n                if (dictSize(zs->dict) == 0) {\n                    dbDelete(c->db,key);\n                    keyremoved = 1;\n                    break;\n                }\n            }\n        }\n    } else {\n        redisPanic(\"Unknown sorted set encoding\");\n    }\n\n    if (deleted) {\n        notifyKeyspaceEvent(REDIS_NOTIFY_ZSET,\"zrem\",key,c->db->id);\n        if (keyremoved)\n            notifyKeyspaceEvent(REDIS_NOTIFY_GENERIC,\"del\",key,c->db->id);\n        signalModifiedKey(c->db,key);\n        server.dirty += deleted;\n    }\n    addReplyLongLong(c,deleted);\n}\n\n/* Implements ZREMRANGEBYRANK, ZREMRANGEBYSCORE, ZREMRANGEBYLEX commands. */\n#define ZRANGE_RANK 0\n#define ZRANGE_SCORE 1\n#define ZRANGE_LEX 2\nvoid zremrangeGenericCommand(redisClient *c, int rangetype) {\n    robj *key = c->argv[1];\n    robj *zobj;\n    int keyremoved = 0;\n    unsigned long deleted;\n    zrangespec range;\n    zlexrangespec lexrange;\n    long start, end, llen;\n\n    /* Step 1: Parse the range. */\n    if (rangetype == ZRANGE_RANK) {\n        if ((getLongFromObjectOrReply(c,c->argv[2],&start,NULL) != REDIS_OK) ||\n            (getLongFromObjectOrReply(c,c->argv[3],&end,NULL) != REDIS_OK))\n            return;\n    } else if (rangetype == ZRANGE_SCORE) {\n        if (zslParseRange(c->argv[2],c->argv[3],&range) != REDIS_OK) {\n            addReplyError(c,\"min or max is not a float\");\n            return;\n        }\n    } else if (rangetype == ZRANGE_LEX) {\n        if (zslParseLexRange(c->argv[2],c->argv[3],&lexrange) != REDIS_OK) {\n            addReplyError(c,\"min or max not valid string range item\");\n            return;\n        }\n    }\n\n    /* Step 2: Lookup & range sanity checks if needed. */\n    if ((zobj = lookupKeyWriteOrReply(c,key,shared.czero)) == NULL ||\n        checkType(c,zobj,REDIS_ZSET)) goto cleanup;\n\n    if (rangetype == ZRANGE_RANK) {\n        /* Sanitize indexes. */\n        llen = zsetLength(zobj);\n        if (start < 0) start = llen+start;\n        if (end < 0) end = llen+end;\n        if (start < 0) start = 0;\n\n        /* Invariant: start >= 0, so this test will be true when end < 0.\n         * The range is empty when start > end or start >= length. */\n        if (start > end || start >= llen) {\n            addReply(c,shared.czero);\n            goto cleanup;\n        }\n        if (end >= llen) end = llen-1;\n    }\n\n    /* Step 3: Perform the range deletion operation. */\n    if (zobj->encoding == REDIS_ENCODING_ZIPLIST) {\n        switch(rangetype) {\n        case ZRANGE_RANK:\n            zobj->ptr = zzlDeleteRangeByRank(zobj->ptr,start+1,end+1,&deleted);\n            break;\n        case ZRANGE_SCORE:\n            zobj->ptr = zzlDeleteRangeByScore(zobj->ptr,&range,&deleted);\n            break;\n        case ZRANGE_LEX:\n            zobj->ptr = zzlDeleteRangeByLex(zobj->ptr,&lexrange,&deleted);\n            break;\n        }\n        if (zzlLength(zobj->ptr) == 0) {\n            dbDelete(c->db,key);\n            keyremoved = 1;\n        }\n    } else if (zobj->encoding == REDIS_ENCODING_SKIPLIST) {\n        zset *zs = zobj->ptr;\n        switch(rangetype) {\n        case ZRANGE_RANK:\n            deleted = zslDeleteRangeByRank(zs->zsl,start+1,end+1,zs->dict);\n            break;\n        case ZRANGE_SCORE:\n            deleted = zslDeleteRangeByScore(zs->zsl,&range,zs->dict);\n            break;\n        case ZRANGE_LEX:\n            deleted = zslDeleteRangeByLex(zs->zsl,&lexrange,zs->dict);\n            break;\n        }\n        if (htNeedsResize(zs->dict)) dictResize(zs->dict);\n        if (dictSize(zs->dict) == 0) {\n            dbDelete(c->db,key);\n            keyremoved = 1;\n        }\n    } else {\n        redisPanic(\"Unknown sorted set encoding\");\n    }\n\n    /* Step 4: Notifications and reply. */\n    if (deleted) {\n        char *event[3] = {\"zremrangebyrank\",\"zremrangebyscore\",\"zremrangebylex\"};\n        signalModifiedKey(c->db,key);\n        notifyKeyspaceEvent(REDIS_NOTIFY_ZSET,event[rangetype],key,c->db->id);\n        if (keyremoved)\n            notifyKeyspaceEvent(REDIS_NOTIFY_GENERIC,\"del\",key,c->db->id);\n    }\n    server.dirty += deleted;\n    addReplyLongLong(c,deleted);\n\ncleanup:\n    if (rangetype == ZRANGE_LEX) zslFreeLexRange(&lexrange);\n}\n\nvoid zremrangebyrankCommand(redisClient *c) {\n    zremrangeGenericCommand(c,ZRANGE_RANK);\n}\n\nvoid zremrangebyscoreCommand(redisClient *c) {\n    zremrangeGenericCommand(c,ZRANGE_SCORE);\n}\n\nvoid zremrangebylexCommand(redisClient *c) {\n    zremrangeGenericCommand(c,ZRANGE_LEX);\n}\n\ntypedef struct {\n    robj *subject;\n    int type; /* Set, sorted set */\n    int encoding;\n    double weight;\n\n    union {\n        /* Set iterators. */\n        union _iterset {\n            struct {\n                intset *is;\n                int ii;\n            } is;\n            struct {\n                dict *dict;\n                dictIterator *di;\n                dictEntry *de;\n            } ht;\n        } set;\n\n        /* Sorted set iterators. */\n        union _iterzset {\n            struct {\n                unsigned char *zl;\n                unsigned char *eptr, *sptr;\n            } zl;\n            struct {\n                zset *zs;\n                zskiplistNode *node;\n            } sl;\n        } zset;\n    } iter;\n} zsetopsrc;\n\n\n/* Use dirty flags for pointers that need to be cleaned up in the next\n * iteration over the zsetopval. The dirty flag for the long long value is\n * special, since long long values don't need cleanup. Instead, it means that\n * we already checked that \"ell\" holds a long long, or tried to convert another\n * representation into a long long value. When this was successful,\n * OPVAL_VALID_LL is set as well. */\n#define OPVAL_DIRTY_ROBJ 1\n#define OPVAL_DIRTY_LL 2\n#define OPVAL_VALID_LL 4\n\n/* Store value retrieved from the iterator. */\ntypedef struct {\n    int flags;\n    unsigned char _buf[32]; /* Private buffer. */\n    robj *ele;\n    unsigned char *estr;\n    unsigned int elen;\n    long long ell;\n    double score;\n} zsetopval;\n\ntypedef union _iterset iterset;\ntypedef union _iterzset iterzset;\n\nvoid zuiInitIterator(zsetopsrc *op) {\n    if (op->subject == NULL)\n        return;\n\n    if (op->type == REDIS_SET) {\n        iterset *it = &op->iter.set;\n        if (op->encoding == REDIS_ENCODING_INTSET) {\n            it->is.is = op->subject->ptr;\n            it->is.ii = 0;\n        } else if (op->encoding == REDIS_ENCODING_HT) {\n            it->ht.dict = op->subject->ptr;\n            it->ht.di = dictGetIterator(op->subject->ptr);\n            it->ht.de = dictNext(it->ht.di);\n        } else {\n            redisPanic(\"Unknown set encoding\");\n        }\n    } else if (op->type == REDIS_ZSET) {\n        iterzset *it = &op->iter.zset;\n        if (op->encoding == REDIS_ENCODING_ZIPLIST) {\n            it->zl.zl = op->subject->ptr;\n            it->zl.eptr = ziplistIndex(it->zl.zl,0);\n            if (it->zl.eptr != NULL) {\n                it->zl.sptr = ziplistNext(it->zl.zl,it->zl.eptr);\n                redisAssert(it->zl.sptr != NULL);\n            }\n        } else if (op->encoding == REDIS_ENCODING_SKIPLIST) {\n            it->sl.zs = op->subject->ptr;\n            it->sl.node = it->sl.zs->zsl->header->level[0].forward;\n        } else {\n            redisPanic(\"Unknown sorted set encoding\");\n        }\n    } else {\n        redisPanic(\"Unsupported type\");\n    }\n}\n\nvoid zuiClearIterator(zsetopsrc *op) {\n    if (op->subject == NULL)\n        return;\n\n    if (op->type == REDIS_SET) {\n        iterset *it = &op->iter.set;\n        if (op->encoding == REDIS_ENCODING_INTSET) {\n            REDIS_NOTUSED(it); /* skip */\n        } else if (op->encoding == REDIS_ENCODING_HT) {\n            dictReleaseIterator(it->ht.di);\n        } else {\n            redisPanic(\"Unknown set encoding\");\n        }\n    } else if (op->type == REDIS_ZSET) {\n        iterzset *it = &op->iter.zset;\n        if (op->encoding == REDIS_ENCODING_ZIPLIST) {\n            REDIS_NOTUSED(it); /* skip */\n        } else if (op->encoding == REDIS_ENCODING_SKIPLIST) {\n            REDIS_NOTUSED(it); /* skip */\n        } else {\n            redisPanic(\"Unknown sorted set encoding\");\n        }\n    } else {\n        redisPanic(\"Unsupported type\");\n    }\n}\n\nint zuiLength(zsetopsrc *op) {\n    if (op->subject == NULL)\n        return 0;\n\n    if (op->type == REDIS_SET) {\n        if (op->encoding == REDIS_ENCODING_INTSET) {\n            return intsetLen(op->subject->ptr);\n        } else if (op->encoding == REDIS_ENCODING_HT) {\n            dict *ht = op->subject->ptr;\n            return dictSize(ht);\n        } else {\n            redisPanic(\"Unknown set encoding\");\n        }\n    } else if (op->type == REDIS_ZSET) {\n        if (op->encoding == REDIS_ENCODING_ZIPLIST) {\n            return zzlLength(op->subject->ptr);\n        } else if (op->encoding == REDIS_ENCODING_SKIPLIST) {\n            zset *zs = op->subject->ptr;\n            return zs->zsl->length;\n        } else {\n            redisPanic(\"Unknown sorted set encoding\");\n        }\n    } else {\n        redisPanic(\"Unsupported type\");\n    }\n}\n\n/* Check if the current value is valid. If so, store it in the passed structure\n * and move to the next element. If not valid, this means we have reached the\n * end of the structure and can abort. */\nint zuiNext(zsetopsrc *op, zsetopval *val) {\n    if (op->subject == NULL)\n        return 0;\n\n    if (val->flags & OPVAL_DIRTY_ROBJ)\n        decrRefCount(val->ele);\n\n    memset(val,0,sizeof(zsetopval));\n\n    if (op->type == REDIS_SET) {\n        iterset *it = &op->iter.set;\n        if (op->encoding == REDIS_ENCODING_INTSET) {\n            int64_t ell;\n\n            if (!intsetGet(it->is.is,it->is.ii,&ell))\n                return 0;\n            val->ell = ell;\n            val->score = 1.0;\n\n            /* Move to next element. */\n            it->is.ii++;\n        } else if (op->encoding == REDIS_ENCODING_HT) {\n            if (it->ht.de == NULL)\n                return 0;\n            val->ele = dictGetKey(it->ht.de);\n            val->score = 1.0;\n\n            /* Move to next element. */\n            it->ht.de = dictNext(it->ht.di);\n        } else {\n            redisPanic(\"Unknown set encoding\");\n        }\n    } else if (op->type == REDIS_ZSET) {\n        iterzset *it = &op->iter.zset;\n        if (op->encoding == REDIS_ENCODING_ZIPLIST) {\n            /* No need to check both, but better be explicit. */\n            if (it->zl.eptr == NULL || it->zl.sptr == NULL)\n                return 0;\n            redisAssert(ziplistGet(it->zl.eptr,&val->estr,&val->elen,&val->ell));\n            val->score = zzlGetScore(it->zl.sptr);\n\n            /* Move to next element. */\n            zzlNext(it->zl.zl,&it->zl.eptr,&it->zl.sptr);\n        } else if (op->encoding == REDIS_ENCODING_SKIPLIST) {\n            if (it->sl.node == NULL)\n                return 0;\n            val->ele = it->sl.node->obj;\n            val->score = it->sl.node->score;\n\n            /* Move to next element. */\n            it->sl.node = it->sl.node->level[0].forward;\n        } else {\n            redisPanic(\"Unknown sorted set encoding\");\n        }\n    } else {\n        redisPanic(\"Unsupported type\");\n    }\n    return 1;\n}\n\nint zuiLongLongFromValue(zsetopval *val) {\n    if (!(val->flags & OPVAL_DIRTY_LL)) {\n        val->flags |= OPVAL_DIRTY_LL;\n\n        if (val->ele != NULL) {\n            if (val->ele->encoding == REDIS_ENCODING_INT) {\n                val->ell = (long)val->ele->ptr;\n                val->flags |= OPVAL_VALID_LL;\n            } else if (val->ele->encoding == REDIS_ENCODING_RAW) {\n                if (string2ll(val->ele->ptr,sdslen(val->ele->ptr),&val->ell))\n                    val->flags |= OPVAL_VALID_LL;\n            } else {\n                redisPanic(\"Unsupported element encoding\");\n            }\n        } else if (val->estr != NULL) {\n            if (string2ll((char*)val->estr,val->elen,&val->ell))\n                val->flags |= OPVAL_VALID_LL;\n        } else {\n            /* The long long was already set, flag as valid. */\n            val->flags |= OPVAL_VALID_LL;\n        }\n    }\n    return val->flags & OPVAL_VALID_LL;\n}\n\nrobj *zuiObjectFromValue(zsetopval *val) {\n    if (val->ele == NULL) {\n        if (val->estr != NULL) {\n            val->ele = createStringObject((char*)val->estr,val->elen);\n        } else {\n            val->ele = createStringObjectFromLongLong(val->ell);\n        }\n        val->flags |= OPVAL_DIRTY_ROBJ;\n    }\n    return val->ele;\n}\n\nint zuiBufferFromValue(zsetopval *val) {\n    if (val->estr == NULL) {\n        if (val->ele != NULL) {\n            if (val->ele->encoding == REDIS_ENCODING_INT) {\n                val->elen = ll2string((char*)val->_buf,sizeof(val->_buf),(long)val->ele->ptr);\n                val->estr = val->_buf;\n            } else if (val->ele->encoding == REDIS_ENCODING_RAW) {\n                val->elen = sdslen(val->ele->ptr);\n                val->estr = val->ele->ptr;\n            } else {\n                redisPanic(\"Unsupported element encoding\");\n            }\n        } else {\n            val->elen = ll2string((char*)val->_buf,sizeof(val->_buf),val->ell);\n            val->estr = val->_buf;\n        }\n    }\n    return 1;\n}\n\n/* Find value pointed to by val in the source pointer to by op. When found,\n * return 1 and store its score in target. Return 0 otherwise. */\nint zuiFind(zsetopsrc *op, zsetopval *val, double *score) {\n    if (op->subject == NULL)\n        return 0;\n\n    if (op->type == REDIS_SET) {\n        if (op->encoding == REDIS_ENCODING_INTSET) {\n            if (zuiLongLongFromValue(val) &&\n                intsetFind(op->subject->ptr,val->ell))\n            {\n                *score = 1.0;\n                return 1;\n            } else {\n                return 0;\n            }\n        } else if (op->encoding == REDIS_ENCODING_HT) {\n            dict *ht = op->subject->ptr;\n            zuiObjectFromValue(val);\n            if (dictFind(ht,val->ele) != NULL) {\n                *score = 1.0;\n                return 1;\n            } else {\n                return 0;\n            }\n        } else {\n            redisPanic(\"Unknown set encoding\");\n        }\n    } else if (op->type == REDIS_ZSET) {\n        zuiObjectFromValue(val);\n\n        if (op->encoding == REDIS_ENCODING_ZIPLIST) {\n            if (zzlFind(op->subject->ptr,val->ele,score) != NULL) {\n                /* Score is already set by zzlFind. */\n                return 1;\n            } else {\n                return 0;\n            }\n        } else if (op->encoding == REDIS_ENCODING_SKIPLIST) {\n            zset *zs = op->subject->ptr;\n            dictEntry *de;\n            if ((de = dictFind(zs->dict,val->ele)) != NULL) {\n                *score = *(double*)dictGetVal(de);\n                return 1;\n            } else {\n                return 0;\n            }\n        } else {\n            redisPanic(\"Unknown sorted set encoding\");\n        }\n    } else {\n        redisPanic(\"Unsupported type\");\n    }\n}\n\nint zuiCompareByCardinality(const void *s1, const void *s2) {\n    return zuiLength((zsetopsrc*)s1) - zuiLength((zsetopsrc*)s2);\n}\n\n#define REDIS_AGGR_SUM 1\n#define REDIS_AGGR_MIN 2\n#define REDIS_AGGR_MAX 3\n#define zunionInterDictValue(_e) (dictGetVal(_e) == NULL ? 1.0 : *(double*)dictGetVal(_e))\n\ninline static void zunionInterAggregate(double *target, double val, int aggregate) {\n    if (aggregate == REDIS_AGGR_SUM) {\n        *target = *target + val;\n        /* The result of adding two doubles is NaN when one variable\n         * is +inf and the other is -inf. When these numbers are added,\n         * we maintain the convention of the result being 0.0. */\n        if (isnan(*target)) *target = 0.0;\n    } else if (aggregate == REDIS_AGGR_MIN) {\n        *target = val < *target ? val : *target;\n    } else if (aggregate == REDIS_AGGR_MAX) {\n        *target = val > *target ? val : *target;\n    } else {\n        /* safety net */\n        redisPanic(\"Unknown ZUNION/INTER aggregate type\");\n    }\n}\n\nvoid zunionInterGenericCommand(redisClient *c, robj *dstkey, int op) {\n    int i, j;\n    long setnum;\n    int aggregate = REDIS_AGGR_SUM;\n    zsetopsrc *src;\n    zsetopval zval;\n    robj *tmp;\n    unsigned int maxelelen = 0;\n    robj *dstobj;\n    zset *dstzset;\n    zskiplistNode *znode;\n    int touched = 0;\n\n    /* expect setnum input keys to be given */\n    if ((getLongFromObjectOrReply(c, c->argv[2], &setnum, NULL) != REDIS_OK))\n        return;\n\n    if (setnum < 1) {\n        addReplyError(c,\n            \"at least 1 input key is needed for ZUNIONSTORE/ZINTERSTORE\");\n        return;\n    }\n\n    /* test if the expected number of keys would overflow */\n    if (setnum > c->argc-3) {\n        addReply(c,shared.syntaxerr);\n        return;\n    }\n\n    /* read keys to be used for input */\n    src = zcalloc(sizeof(zsetopsrc) * setnum);\n    for (i = 0, j = 3; i < setnum; i++, j++) {\n        robj *obj = lookupKeyWrite(c->db,c->argv[j]);\n        if (obj != NULL) {\n            if (obj->type != REDIS_ZSET && obj->type != REDIS_SET) {\n                zfree(src);\n                addReply(c,shared.wrongtypeerr);\n                return;\n            }\n\n            src[i].subject = obj;\n            src[i].type = obj->type;\n            src[i].encoding = obj->encoding;\n        } else {\n            src[i].subject = NULL;\n        }\n\n        /* Default all weights to 1. */\n        src[i].weight = 1.0;\n    }\n\n    /* parse optional extra arguments */\n    if (j < c->argc) {\n        int remaining = c->argc - j;\n\n        while (remaining) {\n            if (remaining >= (setnum + 1) && !strcasecmp(c->argv[j]->ptr,\"weights\")) {\n                j++; remaining--;\n                for (i = 0; i < setnum; i++, j++, remaining--) {\n                    if (getDoubleFromObjectOrReply(c,c->argv[j],&src[i].weight,\n                            \"weight value is not a float\") != REDIS_OK)\n                    {\n                        zfree(src);\n                        return;\n                    }\n                }\n            } else if (remaining >= 2 && !strcasecmp(c->argv[j]->ptr,\"aggregate\")) {\n                j++; remaining--;\n                if (!strcasecmp(c->argv[j]->ptr,\"sum\")) {\n                    aggregate = REDIS_AGGR_SUM;\n                } else if (!strcasecmp(c->argv[j]->ptr,\"min\")) {\n                    aggregate = REDIS_AGGR_MIN;\n                } else if (!strcasecmp(c->argv[j]->ptr,\"max\")) {\n                    aggregate = REDIS_AGGR_MAX;\n                } else {\n                    zfree(src);\n                    addReply(c,shared.syntaxerr);\n                    return;\n                }\n                j++; remaining--;\n            } else {\n                zfree(src);\n                addReply(c,shared.syntaxerr);\n                return;\n            }\n        }\n    }\n\n    /* sort sets from the smallest to largest, this will improve our\n     * algorithm's performance */\n    qsort(src,setnum,sizeof(zsetopsrc),zuiCompareByCardinality);\n\n    dstobj = createZsetObject();\n    dstzset = dstobj->ptr;\n    memset(&zval, 0, sizeof(zval));\n\n    if (op == REDIS_OP_INTER) {\n        /* Skip everything if the smallest input is empty. */\n        if (zuiLength(&src[0]) > 0) {\n            /* Precondition: as src[0] is non-empty and the inputs are ordered\n             * by size, all src[i > 0] are non-empty too. */\n            zuiInitIterator(&src[0]);\n            while (zuiNext(&src[0],&zval)) {\n                double score, value;\n\n                score = src[0].weight * zval.score;\n                if (isnan(score)) score = 0;\n\n                for (j = 1; j < setnum; j++) {\n                    /* It is not safe to access the zset we are\n                     * iterating, so explicitly check for equal object. */\n                    if (src[j].subject == src[0].subject) {\n                        value = zval.score*src[j].weight;\n                        zunionInterAggregate(&score,value,aggregate);\n                    } else if (zuiFind(&src[j],&zval,&value)) {\n                        value *= src[j].weight;\n                        zunionInterAggregate(&score,value,aggregate);\n                    } else {\n                        break;\n                    }\n                }\n\n                /* Only continue when present in every input. */\n                if (j == setnum) {\n                    tmp = zuiObjectFromValue(&zval);\n                    znode = zslInsert(dstzset->zsl,score,tmp);\n                    incrRefCount(tmp); /* added to skiplist */\n                    dictAdd(dstzset->dict,tmp,&znode->score);\n                    incrRefCount(tmp); /* added to dictionary */\n\n                    if (tmp->encoding == REDIS_ENCODING_RAW)\n                        if (sdslen(tmp->ptr) > maxelelen)\n                            maxelelen = sdslen(tmp->ptr);\n                }\n            }\n            zuiClearIterator(&src[0]);\n        }\n    } else if (op == REDIS_OP_UNION) {\n        dict *accumulator = dictCreate(&setDictType,NULL);\n        dictIterator *di;\n        dictEntry *de;\n        double score;\n\n        if (setnum) {\n            /* Our union is at least as large as the largest set.\n             * Resize the dictionary ASAP to avoid useless rehashing. */\n            dictExpand(accumulator,zuiLength(&src[setnum-1]));\n        }\n\n        /* Step 1: Create a dictionary of elements -> aggregated-scores\n         * by iterating one sorted set after the other. */\n        for (i = 0; i < setnum; i++) {\n            if (zuiLength(&src[i]) == 0) continue;\n\n            zuiInitIterator(&src[i]);\n            while (zuiNext(&src[i],&zval)) {\n                /* Initialize value */\n                score = src[i].weight * zval.score;\n                if (isnan(score)) score = 0;\n\n                /* Search for this element in the accumulating dictionary. */\n                de = dictFind(accumulator,zuiObjectFromValue(&zval));\n                /* If we don't have it, we need to create a new entry. */\n                if (de == NULL) {\n                    tmp = zuiObjectFromValue(&zval);\n                    /* Remember the longest single element encountered,\n                     * to understand if it's possible to convert to ziplist\n                     * at the end. */\n                    if (tmp->encoding == REDIS_ENCODING_RAW) {\n                        if (sdslen(tmp->ptr) > maxelelen)\n                            maxelelen = sdslen(tmp->ptr);\n                    }\n                    /* Add the element with its initial score. */\n                    de = dictAddRaw(accumulator,tmp);\n                    incrRefCount(tmp);\n                    dictSetDoubleVal(de,score);\n                } else {\n                    /* Update the score with the score of the new instance\n                     * of the element found in the current sorted set.\n                     *\n                     * Here we access directly the dictEntry double\n                     * value inside the union as it is a big speedup\n                     * compared to using the getDouble/setDouble API. */\n                    zunionInterAggregate(&de->v.d,score,aggregate);\n                }\n            }\n            zuiClearIterator(&src[i]);\n        }\n\n        /* Step 2: convert the dictionary into the final sorted set. */\n        di = dictGetIterator(accumulator);\n\n        /* We now are aware of the final size of the resulting sorted set,\n         * let's resize the dictionary embedded inside the sorted set to the\n         * right size, in order to save rehashing time. */\n        dictExpand(dstzset->dict,dictSize(accumulator));\n\n        while((de = dictNext(di)) != NULL) {\n            robj *ele = dictGetKey(de);\n            score = dictGetDoubleVal(de);\n            znode = zslInsert(dstzset->zsl,score,ele);\n            incrRefCount(ele); /* added to skiplist */\n            dictAdd(dstzset->dict,ele,&znode->score);\n            incrRefCount(ele); /* added to dictionary */\n        }\n        dictReleaseIterator(di);\n\n        /* We can free the accumulator dictionary now. */\n        dictRelease(accumulator);\n    } else {\n        redisPanic(\"Unknown operator\");\n    }\n\n    if (dbDelete(c->db,dstkey)) {\n        signalModifiedKey(c->db,dstkey);\n        touched = 1;\n        server.dirty++;\n    }\n    if (dstzset->zsl->length) {\n        /* Convert to ziplist when in limits. */\n        if (dstzset->zsl->length <= server.zset_max_ziplist_entries &&\n            maxelelen <= server.zset_max_ziplist_value)\n                zsetConvert(dstobj,REDIS_ENCODING_ZIPLIST);\n\n        dbAdd(c->db,dstkey,dstobj);\n        addReplyLongLong(c,zsetLength(dstobj));\n        if (!touched) signalModifiedKey(c->db,dstkey);\n        notifyKeyspaceEvent(REDIS_NOTIFY_ZSET,\n            (op == REDIS_OP_UNION) ? \"zunionstore\" : \"zinterstore\",\n            dstkey,c->db->id);\n        server.dirty++;\n    } else {\n        decrRefCount(dstobj);\n        addReply(c,shared.czero);\n        if (touched)\n            notifyKeyspaceEvent(REDIS_NOTIFY_GENERIC,\"del\",dstkey,c->db->id);\n    }\n    zfree(src);\n}\n\nvoid zunionstoreCommand(redisClient *c) {\n    zunionInterGenericCommand(c,c->argv[1], REDIS_OP_UNION);\n}\n\nvoid zinterstoreCommand(redisClient *c) {\n    zunionInterGenericCommand(c,c->argv[1], REDIS_OP_INTER);\n}\n\nvoid zrangeGenericCommand(redisClient *c, int reverse) {\n    robj *key = c->argv[1];\n    robj *zobj;\n    int withscores = 0;\n    long start;\n    long end;\n    int llen;\n    int rangelen;\n\n    if ((getLongFromObjectOrReply(c, c->argv[2], &start, NULL) != REDIS_OK) ||\n        (getLongFromObjectOrReply(c, c->argv[3], &end, NULL) != REDIS_OK)) return;\n\n    if (c->argc == 5 && !strcasecmp(c->argv[4]->ptr,\"withscores\")) {\n        withscores = 1;\n    } else if (c->argc >= 5) {\n        addReply(c,shared.syntaxerr);\n        return;\n    }\n\n    if ((zobj = lookupKeyReadOrReply(c,key,shared.emptymultibulk)) == NULL\n         || checkType(c,zobj,REDIS_ZSET)) return;\n\n    /* Sanitize indexes. */\n    llen = zsetLength(zobj);\n    if (start < 0) start = llen+start;\n    if (end < 0) end = llen+end;\n    if (start < 0) start = 0;\n\n    /* Invariant: start >= 0, so this test will be true when end < 0.\n     * The range is empty when start > end or start >= length. */\n    if (start > end || start >= llen) {\n        addReply(c,shared.emptymultibulk);\n        return;\n    }\n    if (end >= llen) end = llen-1;\n    rangelen = (end-start)+1;\n\n    /* Return the result in form of a multi-bulk reply */\n    addReplyMultiBulkLen(c, withscores ? (rangelen*2) : rangelen);\n\n    if (zobj->encoding == REDIS_ENCODING_ZIPLIST) {\n        unsigned char *zl = zobj->ptr;\n        unsigned char *eptr, *sptr;\n        unsigned char *vstr;\n        unsigned int vlen;\n        long long vlong;\n\n        if (reverse)\n            eptr = ziplistIndex(zl,-2-(2*start));\n        else\n            eptr = ziplistIndex(zl,2*start);\n\n        redisAssertWithInfo(c,zobj,eptr != NULL);\n        sptr = ziplistNext(zl,eptr);\n\n        while (rangelen--) {\n            redisAssertWithInfo(c,zobj,eptr != NULL && sptr != NULL);\n            redisAssertWithInfo(c,zobj,ziplistGet(eptr,&vstr,&vlen,&vlong));\n            if (vstr == NULL)\n                addReplyBulkLongLong(c,vlong);\n            else\n                addReplyBulkCBuffer(c,vstr,vlen);\n\n            if (withscores)\n                addReplyDouble(c,zzlGetScore(sptr));\n\n            if (reverse)\n                zzlPrev(zl,&eptr,&sptr);\n            else\n                zzlNext(zl,&eptr,&sptr);\n        }\n\n    } else if (zobj->encoding == REDIS_ENCODING_SKIPLIST) {\n        zset *zs = zobj->ptr;\n        zskiplist *zsl = zs->zsl;\n        zskiplistNode *ln;\n        robj *ele;\n\n        /* Check if starting point is trivial, before doing log(N) lookup. */\n        if (reverse) {\n            ln = zsl->tail;\n            if (start > 0)\n                ln = zslGetElementByRank(zsl,llen-start);\n        } else {\n            ln = zsl->header->level[0].forward;\n            if (start > 0)\n                ln = zslGetElementByRank(zsl,start+1);\n        }\n\n        while(rangelen--) {\n            redisAssertWithInfo(c,zobj,ln != NULL);\n            ele = ln->obj;\n            addReplyBulk(c,ele);\n            if (withscores)\n                addReplyDouble(c,ln->score);\n            ln = reverse ? ln->backward : ln->level[0].forward;\n        }\n    } else {\n        redisPanic(\"Unknown sorted set encoding\");\n    }\n}\n\nvoid zrangeCommand(redisClient *c) {\n    zrangeGenericCommand(c,0);\n}\n\nvoid zrevrangeCommand(redisClient *c) {\n    zrangeGenericCommand(c,1);\n}\n\n/* This command implements ZRANGEBYSCORE, ZREVRANGEBYSCORE. */\nvoid genericZrangebyscoreCommand(redisClient *c, int reverse) {\n    zrangespec range;\n    robj *key = c->argv[1];\n    robj *zobj;\n    long offset = 0, limit = -1;\n    int withscores = 0;\n    unsigned long rangelen = 0;\n    void *replylen = NULL;\n    int minidx, maxidx;\n\n    /* Parse the range arguments. */\n    if (reverse) {\n        /* Range is given as [max,min] */\n        maxidx = 2; minidx = 3;\n    } else {\n        /* Range is given as [min,max] */\n        minidx = 2; maxidx = 3;\n    }\n\n    if (zslParseRange(c->argv[minidx],c->argv[maxidx],&range) != REDIS_OK) {\n        addReplyError(c,\"min or max is not a float\");\n        return;\n    }\n\n    /* Parse optional extra arguments. Note that ZCOUNT will exactly have\n     * 4 arguments, so we'll never enter the following code path. */\n    if (c->argc > 4) {\n        int remaining = c->argc - 4;\n        int pos = 4;\n\n        while (remaining) {\n            if (remaining >= 1 && !strcasecmp(c->argv[pos]->ptr,\"withscores\")) {\n                pos++; remaining--;\n                withscores = 1;\n            } else if (remaining >= 3 && !strcasecmp(c->argv[pos]->ptr,\"limit\")) {\n                if ((getLongFromObjectOrReply(c, c->argv[pos+1], &offset, NULL) != REDIS_OK) ||\n                    (getLongFromObjectOrReply(c, c->argv[pos+2], &limit, NULL) != REDIS_OK)) return;\n                pos += 3; remaining -= 3;\n            } else {\n                addReply(c,shared.syntaxerr);\n                return;\n            }\n        }\n    }\n\n    /* Ok, lookup the key and get the range */\n    if ((zobj = lookupKeyReadOrReply(c,key,shared.emptymultibulk)) == NULL ||\n        checkType(c,zobj,REDIS_ZSET)) return;\n\n    if (zobj->encoding == REDIS_ENCODING_ZIPLIST) {\n        unsigned char *zl = zobj->ptr;\n        unsigned char *eptr, *sptr;\n        unsigned char *vstr;\n        unsigned int vlen;\n        long long vlong;\n        double score;\n\n        /* If reversed, get the last node in range as starting point. */\n        if (reverse) {\n            eptr = zzlLastInRange(zl,&range);\n        } else {\n            eptr = zzlFirstInRange(zl,&range);\n        }\n\n        /* No \"first\" element in the specified interval. */\n        if (eptr == NULL) {\n            addReply(c, shared.emptymultibulk);\n            return;\n        }\n\n        /* Get score pointer for the first element. */\n        redisAssertWithInfo(c,zobj,eptr != NULL);\n        sptr = ziplistNext(zl,eptr);\n\n        /* We don't know in advance how many matching elements there are in the\n         * list, so we push this object that will represent the multi-bulk\n         * length in the output buffer, and will \"fix\" it later */\n        replylen = addDeferredMultiBulkLength(c);\n\n        /* If there is an offset, just traverse the number of elements without\n         * checking the score because that is done in the next loop. */\n        while (eptr && offset--) {\n            if (reverse) {\n                zzlPrev(zl,&eptr,&sptr);\n            } else {\n                zzlNext(zl,&eptr,&sptr);\n            }\n        }\n\n        while (eptr && limit--) {\n            score = zzlGetScore(sptr);\n\n            /* Abort when the node is no longer in range. */\n            if (reverse) {\n                if (!zslValueGteMin(score,&range)) break;\n            } else {\n                if (!zslValueLteMax(score,&range)) break;\n            }\n\n            /* We know the element exists, so ziplistGet should always succeed */\n            redisAssertWithInfo(c,zobj,ziplistGet(eptr,&vstr,&vlen,&vlong));\n\n            rangelen++;\n            if (vstr == NULL) {\n                addReplyBulkLongLong(c,vlong);\n            } else {\n                addReplyBulkCBuffer(c,vstr,vlen);\n            }\n\n            if (withscores) {\n                addReplyDouble(c,score);\n            }\n\n            /* Move to next node */\n            if (reverse) {\n                zzlPrev(zl,&eptr,&sptr);\n            } else {\n                zzlNext(zl,&eptr,&sptr);\n            }\n        }\n    } else if (zobj->encoding == REDIS_ENCODING_SKIPLIST) {\n        zset *zs = zobj->ptr;\n        zskiplist *zsl = zs->zsl;\n        zskiplistNode *ln;\n\n        /* If reversed, get the last node in range as starting point. */\n        if (reverse) {\n            ln = zslLastInRange(zsl,&range);\n        } else {\n            ln = zslFirstInRange(zsl,&range);\n        }\n\n        /* No \"first\" element in the specified interval. */\n        if (ln == NULL) {\n            addReply(c, shared.emptymultibulk);\n            return;\n        }\n\n        /* We don't know in advance how many matching elements there are in the\n         * list, so we push this object that will represent the multi-bulk\n         * length in the output buffer, and will \"fix\" it later */\n        replylen = addDeferredMultiBulkLength(c);\n\n        /* If there is an offset, just traverse the number of elements without\n         * checking the score because that is done in the next loop. */\n        while (ln && offset--) {\n            if (reverse) {\n                ln = ln->backward;\n            } else {\n                ln = ln->level[0].forward;\n            }\n        }\n\n        while (ln && limit--) {\n            /* Abort when the node is no longer in range. */\n            if (reverse) {\n                if (!zslValueGteMin(ln->score,&range)) break;\n            } else {\n                if (!zslValueLteMax(ln->score,&range)) break;\n            }\n\n            rangelen++;\n            addReplyBulk(c,ln->obj);\n\n            if (withscores) {\n                addReplyDouble(c,ln->score);\n            }\n\n            /* Move to next node */\n            if (reverse) {\n                ln = ln->backward;\n            } else {\n                ln = ln->level[0].forward;\n            }\n        }\n    } else {\n        redisPanic(\"Unknown sorted set encoding\");\n    }\n\n    if (withscores) {\n        rangelen *= 2;\n    }\n\n    setDeferredMultiBulkLength(c, replylen, rangelen);\n}\n\nvoid zrangebyscoreCommand(redisClient *c) {\n    genericZrangebyscoreCommand(c,0);\n}\n\nvoid zrevrangebyscoreCommand(redisClient *c) {\n    genericZrangebyscoreCommand(c,1);\n}\n\nvoid zcountCommand(redisClient *c) {\n    robj *key = c->argv[1];\n    robj *zobj;\n    zrangespec range;\n    int count = 0;\n\n    /* Parse the range arguments */\n    if (zslParseRange(c->argv[2],c->argv[3],&range) != REDIS_OK) {\n        addReplyError(c,\"min or max is not a float\");\n        return;\n    }\n\n    /* Lookup the sorted set */\n    if ((zobj = lookupKeyReadOrReply(c, key, shared.czero)) == NULL ||\n        checkType(c, zobj, REDIS_ZSET)) return;\n\n    if (zobj->encoding == REDIS_ENCODING_ZIPLIST) {\n        unsigned char *zl = zobj->ptr;\n        unsigned char *eptr, *sptr;\n        double score;\n\n        /* Use the first element in range as the starting point */\n        eptr = zzlFirstInRange(zl,&range);\n\n        /* No \"first\" element */\n        if (eptr == NULL) {\n            addReply(c, shared.czero);\n            return;\n        }\n\n        /* First element is in range */\n        sptr = ziplistNext(zl,eptr);\n        score = zzlGetScore(sptr);\n        redisAssertWithInfo(c,zobj,zslValueLteMax(score,&range));\n\n        /* Iterate over elements in range */\n        while (eptr) {\n            score = zzlGetScore(sptr);\n\n            /* Abort when the node is no longer in range. */\n            if (!zslValueLteMax(score,&range)) {\n                break;\n            } else {\n                count++;\n                zzlNext(zl,&eptr,&sptr);\n            }\n        }\n    } else if (zobj->encoding == REDIS_ENCODING_SKIPLIST) {\n        zset *zs = zobj->ptr;\n        zskiplist *zsl = zs->zsl;\n        zskiplistNode *zn;\n        unsigned long rank;\n\n        /* Find first element in range */\n        zn = zslFirstInRange(zsl, &range);\n\n        /* Use rank of first element, if any, to determine preliminary count */\n        if (zn != NULL) {\n            rank = zslGetRank(zsl, zn->score, zn->obj);\n            count = (zsl->length - (rank - 1));\n\n            /* Find last element in range */\n            zn = zslLastInRange(zsl, &range);\n\n            /* Use rank of last element, if any, to determine the actual count */\n            if (zn != NULL) {\n                rank = zslGetRank(zsl, zn->score, zn->obj);\n                count -= (zsl->length - rank);\n            }\n        }\n    } else {\n        redisPanic(\"Unknown sorted set encoding\");\n    }\n\n    addReplyLongLong(c, count);\n}\n\nvoid zlexcountCommand(redisClient *c) {\n    robj *key = c->argv[1];\n    robj *zobj;\n    zlexrangespec range;\n    int count = 0;\n\n    /* Parse the range arguments */\n    if (zslParseLexRange(c->argv[2],c->argv[3],&range) != REDIS_OK) {\n        addReplyError(c,\"min or max not valid string range item\");\n        return;\n    }\n\n    /* Lookup the sorted set */\n    if ((zobj = lookupKeyReadOrReply(c, key, shared.czero)) == NULL ||\n        checkType(c, zobj, REDIS_ZSET))\n    {\n        zslFreeLexRange(&range);\n        return;\n    }\n\n    if (zobj->encoding == REDIS_ENCODING_ZIPLIST) {\n        unsigned char *zl = zobj->ptr;\n        unsigned char *eptr, *sptr;\n\n        /* Use the first element in range as the starting point */\n        eptr = zzlFirstInLexRange(zl,&range);\n\n        /* No \"first\" element */\n        if (eptr == NULL) {\n            zslFreeLexRange(&range);\n            addReply(c, shared.czero);\n            return;\n        }\n\n        /* First element is in range */\n        sptr = ziplistNext(zl,eptr);\n        redisAssertWithInfo(c,zobj,zzlLexValueLteMax(eptr,&range));\n\n        /* Iterate over elements in range */\n        while (eptr) {\n            /* Abort when the node is no longer in range. */\n            if (!zzlLexValueLteMax(eptr,&range)) {\n                break;\n            } else {\n                count++;\n                zzlNext(zl,&eptr,&sptr);\n            }\n        }\n    } else if (zobj->encoding == REDIS_ENCODING_SKIPLIST) {\n        zset *zs = zobj->ptr;\n        zskiplist *zsl = zs->zsl;\n        zskiplistNode *zn;\n        unsigned long rank;\n\n        /* Find first element in range */\n        zn = zslFirstInLexRange(zsl, &range);\n\n        /* Use rank of first element, if any, to determine preliminary count */\n        if (zn != NULL) {\n            rank = zslGetRank(zsl, zn->score, zn->obj);\n            count = (zsl->length - (rank - 1));\n\n            /* Find last element in range */\n            zn = zslLastInLexRange(zsl, &range);\n\n            /* Use rank of last element, if any, to determine the actual count */\n            if (zn != NULL) {\n                rank = zslGetRank(zsl, zn->score, zn->obj);\n                count -= (zsl->length - rank);\n            }\n        }\n    } else {\n        redisPanic(\"Unknown sorted set encoding\");\n    }\n\n    zslFreeLexRange(&range);\n    addReplyLongLong(c, count);\n}\n\n/* This command implements ZRANGEBYLEX, ZREVRANGEBYLEX. */\nvoid genericZrangebylexCommand(redisClient *c, int reverse) {\n    zlexrangespec range;\n    robj *key = c->argv[1];\n    robj *zobj;\n    long offset = 0, limit = -1;\n    unsigned long rangelen = 0;\n    void *replylen = NULL;\n    int minidx, maxidx;\n\n    /* Parse the range arguments. */\n    if (reverse) {\n        /* Range is given as [max,min] */\n        maxidx = 2; minidx = 3;\n    } else {\n        /* Range is given as [min,max] */\n        minidx = 2; maxidx = 3;\n    }\n\n    if (zslParseLexRange(c->argv[minidx],c->argv[maxidx],&range) != REDIS_OK) {\n        addReplyError(c,\"min or max not valid string range item\");\n        return;\n    }\n\n    /* Parse optional extra arguments. Note that ZCOUNT will exactly have\n     * 4 arguments, so we'll never enter the following code path. */\n    if (c->argc > 4) {\n        int remaining = c->argc - 4;\n        int pos = 4;\n\n        while (remaining) {\n            if (remaining >= 3 && !strcasecmp(c->argv[pos]->ptr,\"limit\")) {\n                if ((getLongFromObjectOrReply(c, c->argv[pos+1], &offset, NULL) != REDIS_OK) ||\n                    (getLongFromObjectOrReply(c, c->argv[pos+2], &limit, NULL) != REDIS_OK)) return;\n                pos += 3; remaining -= 3;\n            } else {\n                zslFreeLexRange(&range);\n                addReply(c,shared.syntaxerr);\n                return;\n            }\n        }\n    }\n\n    /* Ok, lookup the key and get the range */\n    if ((zobj = lookupKeyReadOrReply(c,key,shared.emptymultibulk)) == NULL ||\n        checkType(c,zobj,REDIS_ZSET))\n    {\n        zslFreeLexRange(&range);\n        return;\n    }\n\n    if (zobj->encoding == REDIS_ENCODING_ZIPLIST) {\n        unsigned char *zl = zobj->ptr;\n        unsigned char *eptr, *sptr;\n        unsigned char *vstr;\n        unsigned int vlen;\n        long long vlong;\n\n        /* If reversed, get the last node in range as starting point. */\n        if (reverse) {\n            eptr = zzlLastInLexRange(zl,&range);\n        } else {\n            eptr = zzlFirstInLexRange(zl,&range);\n        }\n\n        /* No \"first\" element in the specified interval. */\n        if (eptr == NULL) {\n            addReply(c, shared.emptymultibulk);\n            zslFreeLexRange(&range);\n            return;\n        }\n\n        /* Get score pointer for the first element. */\n        redisAssertWithInfo(c,zobj,eptr != NULL);\n        sptr = ziplistNext(zl,eptr);\n\n        /* We don't know in advance how many matching elements there are in the\n         * list, so we push this object that will represent the multi-bulk\n         * length in the output buffer, and will \"fix\" it later */\n        replylen = addDeferredMultiBulkLength(c);\n\n        /* If there is an offset, just traverse the number of elements without\n         * checking the score because that is done in the next loop. */\n        while (eptr && offset--) {\n            if (reverse) {\n                zzlPrev(zl,&eptr,&sptr);\n            } else {\n                zzlNext(zl,&eptr,&sptr);\n            }\n        }\n\n        while (eptr && limit--) {\n            /* Abort when the node is no longer in range. */\n            if (reverse) {\n                if (!zzlLexValueGteMin(eptr,&range)) break;\n            } else {\n                if (!zzlLexValueLteMax(eptr,&range)) break;\n            }\n\n            /* We know the element exists, so ziplistGet should always\n             * succeed. */\n            redisAssertWithInfo(c,zobj,ziplistGet(eptr,&vstr,&vlen,&vlong));\n\n            rangelen++;\n            if (vstr == NULL) {\n                addReplyBulkLongLong(c,vlong);\n            } else {\n                addReplyBulkCBuffer(c,vstr,vlen);\n            }\n\n            /* Move to next node */\n            if (reverse) {\n                zzlPrev(zl,&eptr,&sptr);\n            } else {\n                zzlNext(zl,&eptr,&sptr);\n            }\n        }\n    } else if (zobj->encoding == REDIS_ENCODING_SKIPLIST) {\n        zset *zs = zobj->ptr;\n        zskiplist *zsl = zs->zsl;\n        zskiplistNode *ln;\n\n        /* If reversed, get the last node in range as starting point. */\n        if (reverse) {\n            ln = zslLastInLexRange(zsl,&range);\n        } else {\n            ln = zslFirstInLexRange(zsl,&range);\n        }\n\n        /* No \"first\" element in the specified interval. */\n        if (ln == NULL) {\n            addReply(c, shared.emptymultibulk);\n            zslFreeLexRange(&range);\n            return;\n        }\n\n        /* We don't know in advance how many matching elements there are in the\n         * list, so we push this object that will represent the multi-bulk\n         * length in the output buffer, and will \"fix\" it later */\n        replylen = addDeferredMultiBulkLength(c);\n\n        /* If there is an offset, just traverse the number of elements without\n         * checking the score because that is done in the next loop. */\n        while (ln && offset--) {\n            if (reverse) {\n                ln = ln->backward;\n            } else {\n                ln = ln->level[0].forward;\n            }\n        }\n\n        while (ln && limit--) {\n            /* Abort when the node is no longer in range. */\n            if (reverse) {\n                if (!zslLexValueGteMin(ln->obj,&range)) break;\n            } else {\n                if (!zslLexValueLteMax(ln->obj,&range)) break;\n            }\n\n            rangelen++;\n            addReplyBulk(c,ln->obj);\n\n            /* Move to next node */\n            if (reverse) {\n                ln = ln->backward;\n            } else {\n                ln = ln->level[0].forward;\n            }\n        }\n    } else {\n        redisPanic(\"Unknown sorted set encoding\");\n    }\n\n    zslFreeLexRange(&range);\n    setDeferredMultiBulkLength(c, replylen, rangelen);\n}\n\nvoid zrangebylexCommand(redisClient *c) {\n    genericZrangebylexCommand(c,0);\n}\n\nvoid zrevrangebylexCommand(redisClient *c) {\n    genericZrangebylexCommand(c,1);\n}\n\nvoid zcardCommand(redisClient *c) {\n    robj *key = c->argv[1];\n    robj *zobj;\n\n    if ((zobj = lookupKeyReadOrReply(c,key,shared.czero)) == NULL ||\n        checkType(c,zobj,REDIS_ZSET)) return;\n\n    addReplyLongLong(c,zsetLength(zobj));\n}\n\nvoid zscoreCommand(redisClient *c) {\n    robj *key = c->argv[1];\n    robj *zobj;\n    double score;\n\n    if ((zobj = lookupKeyReadOrReply(c,key,shared.nullbulk)) == NULL ||\n        checkType(c,zobj,REDIS_ZSET)) return;\n\n    if (zobj->encoding == REDIS_ENCODING_ZIPLIST) {\n        if (zzlFind(zobj->ptr,c->argv[2],&score) != NULL)\n            addReplyDouble(c,score);\n        else\n            addReply(c,shared.nullbulk);\n    } else if (zobj->encoding == REDIS_ENCODING_SKIPLIST) {\n        zset *zs = zobj->ptr;\n        dictEntry *de;\n\n        c->argv[2] = tryObjectEncoding(c->argv[2]);\n        de = dictFind(zs->dict,c->argv[2]);\n        if (de != NULL) {\n            score = *(double*)dictGetVal(de);\n            addReplyDouble(c,score);\n        } else {\n            addReply(c,shared.nullbulk);\n        }\n    } else {\n        redisPanic(\"Unknown sorted set encoding\");\n    }\n}\n\nvoid zrankGenericCommand(redisClient *c, int reverse) {\n    robj *key = c->argv[1];\n    robj *ele = c->argv[2];\n    robj *zobj;\n    unsigned long llen;\n    unsigned long rank;\n\n    if ((zobj = lookupKeyReadOrReply(c,key,shared.nullbulk)) == NULL ||\n        checkType(c,zobj,REDIS_ZSET)) return;\n    llen = zsetLength(zobj);\n\n    redisAssertWithInfo(c,ele,ele->encoding == REDIS_ENCODING_RAW);\n    if (zobj->encoding == REDIS_ENCODING_ZIPLIST) {\n        unsigned char *zl = zobj->ptr;\n        unsigned char *eptr, *sptr;\n\n        eptr = ziplistIndex(zl,0);\n        redisAssertWithInfo(c,zobj,eptr != NULL);\n        sptr = ziplistNext(zl,eptr);\n        redisAssertWithInfo(c,zobj,sptr != NULL);\n\n        rank = 1;\n        while(eptr != NULL) {\n            if (ziplistCompare(eptr,ele->ptr,sdslen(ele->ptr)))\n                break;\n            rank++;\n            zzlNext(zl,&eptr,&sptr);\n        }\n\n        if (eptr != NULL) {\n            if (reverse)\n                addReplyLongLong(c,llen-rank);\n            else\n                addReplyLongLong(c,rank-1);\n        } else {\n            addReply(c,shared.nullbulk);\n        }\n    } else if (zobj->encoding == REDIS_ENCODING_SKIPLIST) {\n        zset *zs = zobj->ptr;\n        zskiplist *zsl = zs->zsl;\n        dictEntry *de;\n        double score;\n\n        ele = c->argv[2] = tryObjectEncoding(c->argv[2]);\n        de = dictFind(zs->dict,ele);\n        if (de != NULL) {\n            score = *(double*)dictGetVal(de);\n            rank = zslGetRank(zsl,score,ele);\n            redisAssertWithInfo(c,ele,rank); /* Existing elements always have a rank. */\n            if (reverse)\n                addReplyLongLong(c,llen-rank);\n            else\n                addReplyLongLong(c,rank-1);\n        } else {\n            addReply(c,shared.nullbulk);\n        }\n    } else {\n        redisPanic(\"Unknown sorted set encoding\");\n    }\n}\n\nvoid zrankCommand(redisClient *c) {\n    zrankGenericCommand(c, 0);\n}\n\nvoid zrevrankCommand(redisClient *c) {\n    zrankGenericCommand(c, 1);\n}\n\nvoid zscanCommand(redisClient *c) {\n    robj *o;\n    unsigned long cursor;\n\n    if (parseScanCursorOrReply(c,c->argv[2],&cursor) == REDIS_ERR) return;\n    if ((o = lookupKeyReadOrReply(c,c->argv[1],shared.emptyscan)) == NULL ||\n        checkType(c,o,REDIS_ZSET)) return;\n    scanGenericCommand(c,o,cursor);\n}\n"
  },
  {
    "path": "extern/deprecated/redis-2.8.21/src/testhelp.h",
    "content": "/* This is a really minimal testing framework for C.\n *\n * Example:\n *\n * test_cond(\"Check if 1 == 1\", 1==1)\n * test_cond(\"Check if 5 > 10\", 5 > 10)\n * test_report()\n *\n * ----------------------------------------------------------------------------\n *\n * Copyright (c) 2010-2012, Salvatore Sanfilippo <antirez at gmail dot com>\n * All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions are met:\n *\n *   * Redistributions of source code must retain the above copyright notice,\n *     this list of conditions and the following disclaimer.\n *   * Redistributions in binary form must reproduce the above copyright\n *     notice, this list of conditions and the following disclaimer in the\n *     documentation and/or other materials provided with the distribution.\n *   * Neither the name of Redis nor the names of its contributors may be used\n *     to endorse or promote products derived from this software without\n *     specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\"\n * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\n * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE\n * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR\n * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF\n * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS\n * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN\n * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)\n * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE\n * POSSIBILITY OF SUCH DAMAGE.\n */\n\n#ifndef __TESTHELP_H\n#define __TESTHELP_H\n\nint __failed_tests = 0;\nint __test_num = 0;\n#define test_cond(descr,_c) do { \\\n    __test_num++; printf(\"%d - %s: \", __test_num, descr); \\\n    if(_c) printf(\"PASSED\\n\"); else {printf(\"FAILED\\n\"); __failed_tests++;} \\\n} while(0);\n#define test_report() do { \\\n    printf(\"%d tests, %d passed, %d failed\\n\", __test_num, \\\n                    __test_num-__failed_tests, __failed_tests); \\\n    if (__failed_tests) { \\\n        printf(\"=== WARNING === We have failed tests here...\\n\"); \\\n        exit(1); \\\n    } \\\n} while(0);\n\n#endif\n"
  },
  {
    "path": "extern/deprecated/redis-2.8.21/src/util.c",
    "content": "/*\n * Copyright (c) 2009-2012, Salvatore Sanfilippo <antirez at gmail dot com>\n * All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions are met:\n *\n *   * Redistributions of source code must retain the above copyright notice,\n *     this list of conditions and the following disclaimer.\n *   * Redistributions in binary form must reproduce the above copyright\n *     notice, this list of conditions and the following disclaimer in the\n *     documentation and/or other materials provided with the distribution.\n *   * Neither the name of Redis nor the names of its contributors may be used\n *     to endorse or promote products derived from this software without\n *     specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\"\n * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\n * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE\n * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR\n * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF\n * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS\n * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN\n * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)\n * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE\n * POSSIBILITY OF SUCH DAMAGE.\n */\n\n#include \"fmacros.h\"\n#include <stdlib.h>\n#include <stdio.h>\n#include <string.h>\n#include <ctype.h>\n#include <limits.h>\n#include <math.h>\n#include <unistd.h>\n#include <sys/time.h>\n#include <float.h>\n#include <stdint.h>\n\n#include \"util.h\"\n\n/* Glob-style pattern matching. */\nint stringmatchlen(const char *pattern, int patternLen,\n        const char *string, int stringLen, int nocase)\n{\n    while(patternLen) {\n        switch(pattern[0]) {\n        case '*':\n            while (pattern[1] == '*') {\n                pattern++;\n                patternLen--;\n            }\n            if (patternLen == 1)\n                return 1; /* match */\n            while(stringLen) {\n                if (stringmatchlen(pattern+1, patternLen-1,\n                            string, stringLen, nocase))\n                    return 1; /* match */\n                string++;\n                stringLen--;\n            }\n            return 0; /* no match */\n            break;\n        case '?':\n            if (stringLen == 0)\n                return 0; /* no match */\n            string++;\n            stringLen--;\n            break;\n        case '[':\n        {\n            int not, match;\n\n            pattern++;\n            patternLen--;\n            not = pattern[0] == '^';\n            if (not) {\n                pattern++;\n                patternLen--;\n            }\n            match = 0;\n            while(1) {\n                if (pattern[0] == '\\\\') {\n                    pattern++;\n                    patternLen--;\n                    if (pattern[0] == string[0])\n                        match = 1;\n                } else if (pattern[0] == ']') {\n                    break;\n                } else if (patternLen == 0) {\n                    pattern--;\n                    patternLen++;\n                    break;\n                } else if (pattern[1] == '-' && patternLen >= 3) {\n                    int start = pattern[0];\n                    int end = pattern[2];\n                    int c = string[0];\n                    if (start > end) {\n                        int t = start;\n                        start = end;\n                        end = t;\n                    }\n                    if (nocase) {\n                        start = tolower(start);\n                        end = tolower(end);\n                        c = tolower(c);\n                    }\n                    pattern += 2;\n                    patternLen -= 2;\n                    if (c >= start && c <= end)\n                        match = 1;\n                } else {\n                    if (!nocase) {\n                        if (pattern[0] == string[0])\n                            match = 1;\n                    } else {\n                        if (tolower((int)pattern[0]) == tolower((int)string[0]))\n                            match = 1;\n                    }\n                }\n                pattern++;\n                patternLen--;\n            }\n            if (not)\n                match = !match;\n            if (!match)\n                return 0; /* no match */\n            string++;\n            stringLen--;\n            break;\n        }\n        case '\\\\':\n            if (patternLen >= 2) {\n                pattern++;\n                patternLen--;\n            }\n            /* fall through */\n        default:\n            if (!nocase) {\n                if (pattern[0] != string[0])\n                    return 0; /* no match */\n            } else {\n                if (tolower((int)pattern[0]) != tolower((int)string[0]))\n                    return 0; /* no match */\n            }\n            string++;\n            stringLen--;\n            break;\n        }\n        pattern++;\n        patternLen--;\n        if (stringLen == 0) {\n            while(*pattern == '*') {\n                pattern++;\n                patternLen--;\n            }\n            break;\n        }\n    }\n    if (patternLen == 0 && stringLen == 0)\n        return 1;\n    return 0;\n}\n\nint stringmatch(const char *pattern, const char *string, int nocase) {\n    return stringmatchlen(pattern,strlen(pattern),string,strlen(string),nocase);\n}\n\n/* Convert a string representing an amount of memory into the number of\n * bytes, so for instance memtoll(\"1Gi\") will return 1073741824 that is\n * (1024*1024*1024).\n *\n * On parsing error, if *err is not NULL, it's set to 1, otherwise it's\n * set to 0 */\nlong long memtoll(const char *p, int *err) {\n    const char *u;\n    char buf[128];\n    long mul; /* unit multiplier */\n    long long val;\n    unsigned int digits;\n\n    if (err) *err = 0;\n    /* Search the first non digit character. */\n    u = p;\n    if (*u == '-') u++;\n    while(*u && isdigit(*u)) u++;\n    if (*u == '\\0' || !strcasecmp(u,\"b\")) {\n        mul = 1;\n    } else if (!strcasecmp(u,\"k\")) {\n        mul = 1000;\n    } else if (!strcasecmp(u,\"kb\")) {\n        mul = 1024;\n    } else if (!strcasecmp(u,\"m\")) {\n        mul = 1000*1000;\n    } else if (!strcasecmp(u,\"mb\")) {\n        mul = 1024*1024;\n    } else if (!strcasecmp(u,\"g\")) {\n        mul = 1000L*1000*1000;\n    } else if (!strcasecmp(u,\"gb\")) {\n        mul = 1024L*1024*1024;\n    } else {\n        if (err) *err = 1;\n        mul = 1;\n    }\n    digits = u-p;\n    if (digits >= sizeof(buf)) {\n        if (err) *err = 1;\n        return LLONG_MAX;\n    }\n    memcpy(buf,p,digits);\n    buf[digits] = '\\0';\n    val = strtoll(buf,NULL,10);\n    return val*mul;\n}\n\n/* Return the number of digits of 'v' when converted to string in radix 10.\n * See ll2string() for more information. */\nuint32_t digits10(uint64_t v) {\n    if (v < 10) return 1;\n    if (v < 100) return 2;\n    if (v < 1000) return 3;\n    if (v < 1000000000000UL) {\n        if (v < 100000000UL) {\n            if (v < 1000000) {\n                if (v < 10000) return 4;\n                return 5 + (v >= 100000);\n            }\n            return 7 + (v >= 10000000UL);\n        }\n        if (v < 10000000000UL) {\n            return 9 + (v >= 1000000000UL);\n        }\n        return 11 + (v >= 100000000000UL);\n    }\n    return 12 + digits10(v / 1000000000000UL);\n}\n\n/* Convert a long long into a string. Returns the number of\n * characters needed to represent the number.\n * If the buffer is not big enough to store the string, 0 is returned.\n *\n * Based on the following article (that apparently does not provide a\n * novel approach but only publicizes an already used technique):\n *\n * https://www.facebook.com/notes/facebook-engineering/three-optimization-tips-for-c/10151361643253920\n *\n * Modified in order to handle signed integers since the original code was\n * designed for unsigned integers. */\nint ll2string(char* dst, size_t dstlen, long long svalue) {\n    static const char digits[201] =\n        \"0001020304050607080910111213141516171819\"\n        \"2021222324252627282930313233343536373839\"\n        \"4041424344454647484950515253545556575859\"\n        \"6061626364656667686970717273747576777879\"\n        \"8081828384858687888990919293949596979899\";\n    int negative;\n    unsigned long long value;\n\n    /* The main loop works with 64bit unsigned integers for simplicity, so\n     * we convert the number here and remember if it is negative. */\n    if (svalue < 0) {\n        if (svalue != LLONG_MIN) {\n            value = -svalue;\n        } else {\n            value = ((unsigned long long) LLONG_MAX)+1;\n        }\n        negative = 1;\n    } else {\n        value = svalue;\n        negative = 0;\n    }\n\n    /* Check length. */\n    uint32_t const length = digits10(value)+negative;\n    if (length >= dstlen) return 0;\n\n    /* Null term. */\n    uint32_t next = length;\n    dst[next] = '\\0';\n    next--;\n    while (value >= 100) {\n        int const i = (value % 100) * 2;\n        value /= 100;\n        dst[next] = digits[i + 1];\n        dst[next - 1] = digits[i];\n        next -= 2;\n    }\n\n    /* Handle last 1-2 digits. */\n    if (value < 10) {\n        dst[next] = '0' + (uint32_t) value;\n    } else {\n        int i = (uint32_t) value * 2;\n        dst[next] = digits[i + 1];\n        dst[next - 1] = digits[i];\n    }\n\n    /* Add sign. */\n    if (negative) dst[0] = '-';\n    return length;\n}\n\n/* Convert a string into a long long. Returns 1 if the string could be parsed\n * into a (non-overflowing) long long, 0 otherwise. The value will be set to\n * the parsed value when appropriate. */\nint string2ll(const char *s, size_t slen, long long *value) {\n    const char *p = s;\n    size_t plen = 0;\n    int negative = 0;\n    unsigned long long v;\n\n    if (plen == slen)\n        return 0;\n\n    /* Special case: first and only digit is 0. */\n    if (slen == 1 && p[0] == '0') {\n        if (value != NULL) *value = 0;\n        return 1;\n    }\n\n    if (p[0] == '-') {\n        negative = 1;\n        p++; plen++;\n\n        /* Abort on only a negative sign. */\n        if (plen == slen)\n            return 0;\n    }\n\n    /* First digit should be 1-9, otherwise the string should just be 0. */\n    if (p[0] >= '1' && p[0] <= '9') {\n        v = p[0]-'0';\n        p++; plen++;\n    } else if (p[0] == '0' && slen == 1) {\n        *value = 0;\n        return 1;\n    } else {\n        return 0;\n    }\n\n    while (plen < slen && p[0] >= '0' && p[0] <= '9') {\n        if (v > (ULLONG_MAX / 10)) /* Overflow. */\n            return 0;\n        v *= 10;\n\n        if (v > (ULLONG_MAX - (p[0]-'0'))) /* Overflow. */\n            return 0;\n        v += p[0]-'0';\n\n        p++; plen++;\n    }\n\n    /* Return if not all bytes were used. */\n    if (plen < slen)\n        return 0;\n\n    if (negative) {\n        if (v > ((unsigned long long)(-(LLONG_MIN+1))+1)) /* Overflow. */\n            return 0;\n        if (value != NULL) *value = -v;\n    } else {\n        if (v > LLONG_MAX) /* Overflow. */\n            return 0;\n        if (value != NULL) *value = v;\n    }\n    return 1;\n}\n\n/* Convert a string into a long. Returns 1 if the string could be parsed into a\n * (non-overflowing) long, 0 otherwise. The value will be set to the parsed\n * value when appropriate. */\nint string2l(const char *s, size_t slen, long *lval) {\n    long long llval;\n\n    if (!string2ll(s,slen,&llval))\n        return 0;\n\n    if (llval < LONG_MIN || llval > LONG_MAX)\n        return 0;\n\n    *lval = (long)llval;\n    return 1;\n}\n\n/* Convert a double to a string representation. Returns the number of bytes\n * required. The representation should always be parsable by strtod(3). */\nint d2string(char *buf, size_t len, double value) {\n    if (isnan(value)) {\n        len = snprintf(buf,len,\"nan\");\n    } else if (isinf(value)) {\n        if (value < 0)\n            len = snprintf(buf,len,\"-inf\");\n        else\n            len = snprintf(buf,len,\"inf\");\n    } else if (value == 0) {\n        /* See: http://en.wikipedia.org/wiki/Signed_zero, \"Comparisons\". */\n        if (1.0/value < 0)\n            len = snprintf(buf,len,\"-0\");\n        else\n            len = snprintf(buf,len,\"0\");\n    } else {\n#if (DBL_MANT_DIG >= 52) && (LLONG_MAX == 0x7fffffffffffffffLL)\n        /* Check if the float is in a safe range to be casted into a\n         * long long. We are assuming that long long is 64 bit here.\n         * Also we are assuming that there are no implementations around where\n         * double has precision < 52 bit.\n         *\n         * Under this assumptions we test if a double is inside an interval\n         * where casting to long long is safe. Then using two castings we\n         * make sure the decimal part is zero. If all this is true we use\n         * integer printing function that is much faster. */\n        double min = -4503599627370495; /* (2^52)-1 */\n        double max = 4503599627370496; /* -(2^52) */\n        if (value > min && value < max && value == ((double)((long long)value)))\n            len = ll2string(buf,len,(long long)value);\n        else\n#endif\n            len = snprintf(buf,len,\"%.17g\",value);\n    }\n\n    return len;\n}\n\n/* Generate the Redis \"Run ID\", a SHA1-sized random number that identifies a\n * given execution of Redis, so that if you are talking with an instance\n * having run_id == A, and you reconnect and it has run_id == B, you can be\n * sure that it is either a different instance or it was restarted. */\nvoid getRandomHexChars(char *p, unsigned int len) {\n    FILE *fp = fopen(\"/dev/urandom\",\"r\");\n    char *charset = \"0123456789abcdef\";\n    unsigned int j;\n\n    if (fp == NULL || fread(p,len,1,fp) == 0) {\n        /* If we can't read from /dev/urandom, do some reasonable effort\n         * in order to create some entropy, since this function is used to\n         * generate run_id and cluster instance IDs */\n        char *x = p;\n        unsigned int l = len;\n        struct timeval tv;\n        pid_t pid = getpid();\n\n        /* Use time and PID to fill the initial array. */\n        gettimeofday(&tv,NULL);\n        if (l >= sizeof(tv.tv_usec)) {\n            memcpy(x,&tv.tv_usec,sizeof(tv.tv_usec));\n            l -= sizeof(tv.tv_usec);\n            x += sizeof(tv.tv_usec);\n        }\n        if (l >= sizeof(tv.tv_sec)) {\n            memcpy(x,&tv.tv_sec,sizeof(tv.tv_sec));\n            l -= sizeof(tv.tv_sec);\n            x += sizeof(tv.tv_sec);\n        }\n        if (l >= sizeof(pid)) {\n            memcpy(x,&pid,sizeof(pid));\n            l -= sizeof(pid);\n            x += sizeof(pid);\n        }\n        /* Finally xor it with rand() output, that was already seeded with\n         * time() at startup. */\n        for (j = 0; j < len; j++)\n            p[j] ^= rand();\n    }\n    /* Turn it into hex digits taking just 4 bits out of 8 for every byte. */\n    for (j = 0; j < len; j++)\n        p[j] = charset[p[j] & 0x0F];\n    if (fp) fclose(fp);\n}\n\n/* Given the filename, return the absolute path as an SDS string, or NULL\n * if it fails for some reason. Note that \"filename\" may be an absolute path\n * already, this will be detected and handled correctly.\n *\n * The function does not try to normalize everything, but only the obvious\n * case of one or more \"../\" appearning at the start of \"filename\"\n * relative path. */\nsds getAbsolutePath(char *filename) {\n    char cwd[1024];\n    sds abspath;\n    sds relpath = sdsnew(filename);\n\n    relpath = sdstrim(relpath,\" \\r\\n\\t\");\n    if (relpath[0] == '/') return relpath; /* Path is already absolute. */\n\n    /* If path is relative, join cwd and relative path. */\n    if (getcwd(cwd,sizeof(cwd)) == NULL) {\n        sdsfree(relpath);\n        return NULL;\n    }\n    abspath = sdsnew(cwd);\n    if (sdslen(abspath) && abspath[sdslen(abspath)-1] != '/')\n        abspath = sdscat(abspath,\"/\");\n\n    /* At this point we have the current path always ending with \"/\", and\n     * the trimmed relative path. Try to normalize the obvious case of\n     * trailing ../ elements at the start of the path.\n     *\n     * For every \"../\" we find in the filename, we remove it and also remove\n     * the last element of the cwd, unless the current cwd is \"/\". */\n    while (sdslen(relpath) >= 3 &&\n           relpath[0] == '.' && relpath[1] == '.' && relpath[2] == '/')\n    {\n        sdsrange(relpath,3,-1);\n        if (sdslen(abspath) > 1) {\n            char *p = abspath + sdslen(abspath)-2;\n            int trimlen = 1;\n\n            while(*p != '/') {\n                p--;\n                trimlen++;\n            }\n            sdsrange(abspath,0,-(trimlen+1));\n        }\n    }\n\n    /* Finally glue the two parts together. */\n    abspath = sdscatsds(abspath,relpath);\n    sdsfree(relpath);\n    return abspath;\n}\n\n/* Return true if the specified path is just a file basename without any\n * relative or absolute path. This function just checks that no / or \\\n * character exists inside the specified path, that's enough in the\n * environments where Redis runs. */\nint pathIsBaseName(char *path) {\n    return strchr(path,'/') == NULL && strchr(path,'\\\\') == NULL;\n}\n\n#ifdef UTIL_TEST_MAIN\n#include <assert.h>\n\nvoid test_string2ll(void) {\n    char buf[32];\n    long long v;\n\n    /* May not start with +. */\n    strcpy(buf,\"+1\");\n    assert(string2ll(buf,strlen(buf),&v) == 0);\n\n    /* Leading space. */\n    strcpy(buf,\" 1\");\n    assert(string2ll(buf,strlen(buf),&v) == 0);\n\n    /* Trailing space. */\n    strcpy(buf,\"1 \");\n    assert(string2ll(buf,strlen(buf),&v) == 0);\n\n    /* May not start with 0. */\n    strcpy(buf,\"01\");\n    assert(string2ll(buf,strlen(buf),&v) == 0);\n\n    strcpy(buf,\"-1\");\n    assert(string2ll(buf,strlen(buf),&v) == 1);\n    assert(v == -1);\n\n    strcpy(buf,\"0\");\n    assert(string2ll(buf,strlen(buf),&v) == 1);\n    assert(v == 0);\n\n    strcpy(buf,\"1\");\n    assert(string2ll(buf,strlen(buf),&v) == 1);\n    assert(v == 1);\n\n    strcpy(buf,\"99\");\n    assert(string2ll(buf,strlen(buf),&v) == 1);\n    assert(v == 99);\n\n    strcpy(buf,\"-99\");\n    assert(string2ll(buf,strlen(buf),&v) == 1);\n    assert(v == -99);\n\n    strcpy(buf,\"-9223372036854775808\");\n    assert(string2ll(buf,strlen(buf),&v) == 1);\n    assert(v == LLONG_MIN);\n\n    strcpy(buf,\"-9223372036854775809\"); /* overflow */\n    assert(string2ll(buf,strlen(buf),&v) == 0);\n\n    strcpy(buf,\"9223372036854775807\");\n    assert(string2ll(buf,strlen(buf),&v) == 1);\n    assert(v == LLONG_MAX);\n\n    strcpy(buf,\"9223372036854775808\"); /* overflow */\n    assert(string2ll(buf,strlen(buf),&v) == 0);\n}\n\nvoid test_string2l(void) {\n    char buf[32];\n    long v;\n\n    /* May not start with +. */\n    strcpy(buf,\"+1\");\n    assert(string2l(buf,strlen(buf),&v) == 0);\n\n    /* May not start with 0. */\n    strcpy(buf,\"01\");\n    assert(string2l(buf,strlen(buf),&v) == 0);\n\n    strcpy(buf,\"-1\");\n    assert(string2l(buf,strlen(buf),&v) == 1);\n    assert(v == -1);\n\n    strcpy(buf,\"0\");\n    assert(string2l(buf,strlen(buf),&v) == 1);\n    assert(v == 0);\n\n    strcpy(buf,\"1\");\n    assert(string2l(buf,strlen(buf),&v) == 1);\n    assert(v == 1);\n\n    strcpy(buf,\"99\");\n    assert(string2l(buf,strlen(buf),&v) == 1);\n    assert(v == 99);\n\n    strcpy(buf,\"-99\");\n    assert(string2l(buf,strlen(buf),&v) == 1);\n    assert(v == -99);\n\n#if LONG_MAX != LLONG_MAX\n    strcpy(buf,\"-2147483648\");\n    assert(string2l(buf,strlen(buf),&v) == 1);\n    assert(v == LONG_MIN);\n\n    strcpy(buf,\"-2147483649\"); /* overflow */\n    assert(string2l(buf,strlen(buf),&v) == 0);\n\n    strcpy(buf,\"2147483647\");\n    assert(string2l(buf,strlen(buf),&v) == 1);\n    assert(v == LONG_MAX);\n\n    strcpy(buf,\"2147483648\"); /* overflow */\n    assert(string2l(buf,strlen(buf),&v) == 0);\n#endif\n}\n\nint main(int argc, char **argv) {\n    test_string2ll();\n    test_string2l();\n    return 0;\n}\n#endif\n"
  },
  {
    "path": "extern/deprecated/redis-2.8.21/src/util.h",
    "content": "/*\n * Copyright (c) 2009-2012, Salvatore Sanfilippo <antirez at gmail dot com>\n * All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions are met:\n *\n *   * Redistributions of source code must retain the above copyright notice,\n *     this list of conditions and the following disclaimer.\n *   * Redistributions in binary form must reproduce the above copyright\n *     notice, this list of conditions and the following disclaimer in the\n *     documentation and/or other materials provided with the distribution.\n *   * Neither the name of Redis nor the names of its contributors may be used\n *     to endorse or promote products derived from this software without\n *     specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\"\n * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\n * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE\n * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR\n * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF\n * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS\n * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN\n * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)\n * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE\n * POSSIBILITY OF SUCH DAMAGE.\n */\n\n#ifndef __REDIS_UTIL_H\n#define __REDIS_UTIL_H\n\n#include \"sds.h\"\n\nint stringmatchlen(const char *p, int plen, const char *s, int slen, int nocase);\nint stringmatch(const char *p, const char *s, int nocase);\nlong long memtoll(const char *p, int *err);\nint ll2string(char *s, size_t len, long long value);\nint string2ll(const char *s, size_t slen, long long *value);\nint string2l(const char *s, size_t slen, long *value);\nint d2string(char *buf, size_t len, double value);\nsds getAbsolutePath(char *filename);\nint pathIsBaseName(char *path);\n\n#endif\n"
  },
  {
    "path": "extern/deprecated/redis-2.8.21/src/valgrind.sup",
    "content": "{\n   <lzf_unitialized_hash_table>\n   Memcheck:Cond\n   fun:lzf_compress\n}\n\n{\n   <lzf_unitialized_hash_table>\n   Memcheck:Value4\n   fun:lzf_compress\n}\n\n{\n   <lzf_unitialized_hash_table>\n   Memcheck:Value8\n   fun:lzf_compress\n}\n"
  },
  {
    "path": "extern/deprecated/redis-2.8.21/src/version.h",
    "content": "#define REDIS_VERSION \"2.8.21\"\n"
  },
  {
    "path": "extern/deprecated/redis-2.8.21/src/ziplist.c",
    "content": "/* The ziplist is a specially encoded dually linked list that is designed\n * to be very memory efficient. It stores both strings and integer values,\n * where integers are encoded as actual integers instead of a series of\n * characters. It allows push and pop operations on either side of the list\n * in O(1) time. However, because every operation requires a reallocation of\n * the memory used by the ziplist, the actual complexity is related to the\n * amount of memory used by the ziplist.\n *\n * ----------------------------------------------------------------------------\n *\n * ZIPLIST OVERALL LAYOUT:\n * The general layout of the ziplist is as follows:\n * <zlbytes><zltail><zllen><entry><entry><zlend>\n *\n * <zlbytes> is an unsigned integer to hold the number of bytes that the\n * ziplist occupies. This value needs to be stored to be able to resize the\n * entire structure without the need to traverse it first.\n *\n * <zltail> is the offset to the last entry in the list. This allows a pop\n * operation on the far side of the list without the need for full traversal.\n *\n * <zllen> is the number of entries.When this value is larger than 2**16-2,\n * we need to traverse the entire list to know how many items it holds.\n *\n * <zlend> is a single byte special value, equal to 255, which indicates the\n * end of the list.\n *\n * ZIPLIST ENTRIES:\n * Every entry in the ziplist is prefixed by a header that contains two pieces\n * of information. First, the length of the previous entry is stored to be\n * able to traverse the list from back to front. Second, the encoding with an\n * optional string length of the entry itself is stored.\n *\n * The length of the previous entry is encoded in the following way:\n * If this length is smaller than 254 bytes, it will only consume a single\n * byte that takes the length as value. When the length is greater than or\n * equal to 254, it will consume 5 bytes. The first byte is set to 254 to\n * indicate a larger value is following. The remaining 4 bytes take the\n * length of the previous entry as value.\n *\n * The other header field of the entry itself depends on the contents of the\n * entry. When the entry is a string, the first 2 bits of this header will hold\n * the type of encoding used to store the length of the string, followed by the\n * actual length of the string. When the entry is an integer the first 2 bits\n * are both set to 1. The following 2 bits are used to specify what kind of\n * integer will be stored after this header. An overview of the different\n * types and encodings is as follows:\n *\n * |00pppppp| - 1 byte\n *      String value with length less than or equal to 63 bytes (6 bits).\n * |01pppppp|qqqqqqqq| - 2 bytes\n *      String value with length less than or equal to 16383 bytes (14 bits).\n * |10______|qqqqqqqq|rrrrrrrr|ssssssss|tttttttt| - 5 bytes\n *      String value with length greater than or equal to 16384 bytes.\n * |11000000| - 1 byte\n *      Integer encoded as int16_t (2 bytes).\n * |11010000| - 1 byte\n *      Integer encoded as int32_t (4 bytes).\n * |11100000| - 1 byte\n *      Integer encoded as int64_t (8 bytes).\n * |11110000| - 1 byte\n *      Integer encoded as 24 bit signed (3 bytes).\n * |11111110| - 1 byte\n *      Integer encoded as 8 bit signed (1 byte).\n * |1111xxxx| - (with xxxx between 0000 and 1101) immediate 4 bit integer.\n *      Unsigned integer from 0 to 12. The encoded value is actually from\n *      1 to 13 because 0000 and 1111 can not be used, so 1 should be\n *      subtracted from the encoded 4 bit value to obtain the right value.\n * |11111111| - End of ziplist.\n *\n * All the integers are represented in little endian byte order.\n *\n * ----------------------------------------------------------------------------\n *\n * Copyright (c) 2009-2012, Pieter Noordhuis <pcnoordhuis at gmail dot com>\n * Copyright (c) 2009-2012, Salvatore Sanfilippo <antirez at gmail dot com>\n * All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions are met:\n *\n *   * Redistributions of source code must retain the above copyright notice,\n *     this list of conditions and the following disclaimer.\n *   * Redistributions in binary form must reproduce the above copyright\n *     notice, this list of conditions and the following disclaimer in the\n *     documentation and/or other materials provided with the distribution.\n *   * Neither the name of Redis nor the names of its contributors may be used\n *     to endorse or promote products derived from this software without\n *     specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\"\n * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\n * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE\n * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR\n * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF\n * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS\n * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN\n * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)\n * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE\n * POSSIBILITY OF SUCH DAMAGE.\n */\n\n#include <stdio.h>\n#include <stdlib.h>\n#include <string.h>\n#include <stdint.h>\n#include <limits.h>\n#include \"zmalloc.h\"\n#include \"util.h\"\n#include \"ziplist.h\"\n#include \"endianconv.h\"\n#include \"redisassert.h\"\n\n#define ZIP_END 255\n#define ZIP_BIGLEN 254\n\n/* Different encoding/length possibilities */\n#define ZIP_STR_MASK 0xc0\n#define ZIP_INT_MASK 0x30\n#define ZIP_STR_06B (0 << 6)\n#define ZIP_STR_14B (1 << 6)\n#define ZIP_STR_32B (2 << 6)\n#define ZIP_INT_16B (0xc0 | 0<<4)\n#define ZIP_INT_32B (0xc0 | 1<<4)\n#define ZIP_INT_64B (0xc0 | 2<<4)\n#define ZIP_INT_24B (0xc0 | 3<<4)\n#define ZIP_INT_8B 0xfe\n/* 4 bit integer immediate encoding */\n#define ZIP_INT_IMM_MASK 0x0f\n#define ZIP_INT_IMM_MIN 0xf1    /* 11110001 */\n#define ZIP_INT_IMM_MAX 0xfd    /* 11111101 */\n#define ZIP_INT_IMM_VAL(v) (v & ZIP_INT_IMM_MASK)\n\n#define INT24_MAX 0x7fffff\n#define INT24_MIN (-INT24_MAX - 1)\n\n/* Macro to determine type */\n#define ZIP_IS_STR(enc) (((enc) & ZIP_STR_MASK) < ZIP_STR_MASK)\n\n/* Utility macros */\n#define ZIPLIST_BYTES(zl)       (*((uint32_t*)(zl)))\n#define ZIPLIST_TAIL_OFFSET(zl) (*((uint32_t*)((zl)+sizeof(uint32_t))))\n#define ZIPLIST_LENGTH(zl)      (*((uint16_t*)((zl)+sizeof(uint32_t)*2)))\n#define ZIPLIST_HEADER_SIZE     (sizeof(uint32_t)*2+sizeof(uint16_t))\n#define ZIPLIST_ENTRY_HEAD(zl)  ((zl)+ZIPLIST_HEADER_SIZE)\n#define ZIPLIST_ENTRY_TAIL(zl)  ((zl)+intrev32ifbe(ZIPLIST_TAIL_OFFSET(zl)))\n#define ZIPLIST_ENTRY_END(zl)   ((zl)+intrev32ifbe(ZIPLIST_BYTES(zl))-1)\n\n/* We know a positive increment can only be 1 because entries can only be\n * pushed one at a time. */\n#define ZIPLIST_INCR_LENGTH(zl,incr) { \\\n    if (ZIPLIST_LENGTH(zl) < UINT16_MAX) \\\n        ZIPLIST_LENGTH(zl) = intrev16ifbe(intrev16ifbe(ZIPLIST_LENGTH(zl))+incr); \\\n}\n\ntypedef struct zlentry {\n    unsigned int prevrawlensize, prevrawlen;\n    unsigned int lensize, len;\n    unsigned int headersize;\n    unsigned char encoding;\n    unsigned char *p;\n} zlentry;\n\n/* Extract the encoding from the byte pointed by 'ptr' and set it into\n * 'encoding'. */\n#define ZIP_ENTRY_ENCODING(ptr, encoding) do {  \\\n    (encoding) = (ptr[0]); \\\n    if ((encoding) < ZIP_STR_MASK) (encoding) &= ZIP_STR_MASK; \\\n} while(0)\n\n/* Return bytes needed to store integer encoded by 'encoding' */\nstatic unsigned int zipIntSize(unsigned char encoding) {\n    switch(encoding) {\n    case ZIP_INT_8B:  return 1;\n    case ZIP_INT_16B: return 2;\n    case ZIP_INT_24B: return 3;\n    case ZIP_INT_32B: return 4;\n    case ZIP_INT_64B: return 8;\n    default: return 0; /* 4 bit immediate */\n    }\n    assert(NULL);\n    return 0;\n}\n\n/* Encode the length 'rawlen' writing it in 'p'. If p is NULL it just returns\n * the amount of bytes required to encode such a length. */\nstatic unsigned int zipEncodeLength(unsigned char *p, unsigned char encoding, unsigned int rawlen) {\n    unsigned char len = 1, buf[5];\n\n    if (ZIP_IS_STR(encoding)) {\n        /* Although encoding is given it may not be set for strings,\n         * so we determine it here using the raw length. */\n        if (rawlen <= 0x3f) {\n            if (!p) return len;\n            buf[0] = ZIP_STR_06B | rawlen;\n        } else if (rawlen <= 0x3fff) {\n            len += 1;\n            if (!p) return len;\n            buf[0] = ZIP_STR_14B | ((rawlen >> 8) & 0x3f);\n            buf[1] = rawlen & 0xff;\n        } else {\n            len += 4;\n            if (!p) return len;\n            buf[0] = ZIP_STR_32B;\n            buf[1] = (rawlen >> 24) & 0xff;\n            buf[2] = (rawlen >> 16) & 0xff;\n            buf[3] = (rawlen >> 8) & 0xff;\n            buf[4] = rawlen & 0xff;\n        }\n    } else {\n        /* Implies integer encoding, so length is always 1. */\n        if (!p) return len;\n        buf[0] = encoding;\n    }\n\n    /* Store this length at p */\n    memcpy(p,buf,len);\n    return len;\n}\n\n/* Decode the length encoded in 'ptr'. The 'encoding' variable will hold the\n * entries encoding, the 'lensize' variable will hold the number of bytes\n * required to encode the entries length, and the 'len' variable will hold the\n * entries length. */\n#define ZIP_DECODE_LENGTH(ptr, encoding, lensize, len) do {                    \\\n    ZIP_ENTRY_ENCODING((ptr), (encoding));                                     \\\n    if ((encoding) < ZIP_STR_MASK) {                                           \\\n        if ((encoding) == ZIP_STR_06B) {                                       \\\n            (lensize) = 1;                                                     \\\n            (len) = (ptr)[0] & 0x3f;                                           \\\n        } else if ((encoding) == ZIP_STR_14B) {                                \\\n            (lensize) = 2;                                                     \\\n            (len) = (((ptr)[0] & 0x3f) << 8) | (ptr)[1];                       \\\n        } else if (encoding == ZIP_STR_32B) {                                  \\\n            (lensize) = 5;                                                     \\\n            (len) = ((ptr)[1] << 24) |                                         \\\n                    ((ptr)[2] << 16) |                                         \\\n                    ((ptr)[3] <<  8) |                                         \\\n                    ((ptr)[4]);                                                \\\n        } else {                                                               \\\n            assert(NULL);                                                      \\\n        }                                                                      \\\n    } else {                                                                   \\\n        (lensize) = 1;                                                         \\\n        (len) = zipIntSize(encoding);                                          \\\n    }                                                                          \\\n} while(0);\n\n/* Encode the length of the previous entry and write it to \"p\". Return the\n * number of bytes needed to encode this length if \"p\" is NULL. */\nstatic unsigned int zipPrevEncodeLength(unsigned char *p, unsigned int len) {\n    if (p == NULL) {\n        return (len < ZIP_BIGLEN) ? 1 : sizeof(len)+1;\n    } else {\n        if (len < ZIP_BIGLEN) {\n            p[0] = len;\n            return 1;\n        } else {\n            p[0] = ZIP_BIGLEN;\n            memcpy(p+1,&len,sizeof(len));\n            memrev32ifbe(p+1);\n            return 1+sizeof(len);\n        }\n    }\n}\n\n/* Encode the length of the previous entry and write it to \"p\". This only\n * uses the larger encoding (required in __ziplistCascadeUpdate). */\nstatic void zipPrevEncodeLengthForceLarge(unsigned char *p, unsigned int len) {\n    if (p == NULL) return;\n    p[0] = ZIP_BIGLEN;\n    memcpy(p+1,&len,sizeof(len));\n    memrev32ifbe(p+1);\n}\n\n/* Decode the number of bytes required to store the length of the previous\n * element, from the perspective of the entry pointed to by 'ptr'. */\n#define ZIP_DECODE_PREVLENSIZE(ptr, prevlensize) do {                          \\\n    if ((ptr)[0] < ZIP_BIGLEN) {                                               \\\n        (prevlensize) = 1;                                                     \\\n    } else {                                                                   \\\n        (prevlensize) = 5;                                                     \\\n    }                                                                          \\\n} while(0);\n\n/* Decode the length of the previous element, from the perspective of the entry\n * pointed to by 'ptr'. */\n#define ZIP_DECODE_PREVLEN(ptr, prevlensize, prevlen) do {                     \\\n    ZIP_DECODE_PREVLENSIZE(ptr, prevlensize);                                  \\\n    if ((prevlensize) == 1) {                                                  \\\n        (prevlen) = (ptr)[0];                                                  \\\n    } else if ((prevlensize) == 5) {                                           \\\n        assert(sizeof((prevlensize)) == 4);                                    \\\n        memcpy(&(prevlen), ((char*)(ptr)) + 1, 4);                             \\\n        memrev32ifbe(&prevlen);                                                \\\n    }                                                                          \\\n} while(0);\n\n/* Return the difference in number of bytes needed to store the length of the\n * previous element 'len', in the entry pointed to by 'p'. */\nstatic int zipPrevLenByteDiff(unsigned char *p, unsigned int len) {\n    unsigned int prevlensize;\n    ZIP_DECODE_PREVLENSIZE(p, prevlensize);\n    return zipPrevEncodeLength(NULL, len) - prevlensize;\n}\n\n/* Return the total number of bytes used by the entry pointed to by 'p'. */\nstatic unsigned int zipRawEntryLength(unsigned char *p) {\n    unsigned int prevlensize, encoding, lensize, len;\n    ZIP_DECODE_PREVLENSIZE(p, prevlensize);\n    ZIP_DECODE_LENGTH(p + prevlensize, encoding, lensize, len);\n    return prevlensize + lensize + len;\n}\n\n/* Check if string pointed to by 'entry' can be encoded as an integer.\n * Stores the integer value in 'v' and its encoding in 'encoding'. */\nstatic int zipTryEncoding(unsigned char *entry, unsigned int entrylen, long long *v, unsigned char *encoding) {\n    long long value;\n\n    if (entrylen >= 32 || entrylen == 0) return 0;\n    if (string2ll((char*)entry,entrylen,&value)) {\n        /* Great, the string can be encoded. Check what's the smallest\n         * of our encoding types that can hold this value. */\n        if (value >= 0 && value <= 12) {\n            *encoding = ZIP_INT_IMM_MIN+value;\n        } else if (value >= INT8_MIN && value <= INT8_MAX) {\n            *encoding = ZIP_INT_8B;\n        } else if (value >= INT16_MIN && value <= INT16_MAX) {\n            *encoding = ZIP_INT_16B;\n        } else if (value >= INT24_MIN && value <= INT24_MAX) {\n            *encoding = ZIP_INT_24B;\n        } else if (value >= INT32_MIN && value <= INT32_MAX) {\n            *encoding = ZIP_INT_32B;\n        } else {\n            *encoding = ZIP_INT_64B;\n        }\n        *v = value;\n        return 1;\n    }\n    return 0;\n}\n\n/* Store integer 'value' at 'p', encoded as 'encoding' */\nstatic void zipSaveInteger(unsigned char *p, int64_t value, unsigned char encoding) {\n    int16_t i16;\n    int32_t i32;\n    int64_t i64;\n    if (encoding == ZIP_INT_8B) {\n        ((int8_t*)p)[0] = (int8_t)value;\n    } else if (encoding == ZIP_INT_16B) {\n        i16 = value;\n        memcpy(p,&i16,sizeof(i16));\n        memrev16ifbe(p);\n    } else if (encoding == ZIP_INT_24B) {\n        i32 = value<<8;\n        memrev32ifbe(&i32);\n        memcpy(p,((uint8_t*)&i32)+1,sizeof(i32)-sizeof(uint8_t));\n    } else if (encoding == ZIP_INT_32B) {\n        i32 = value;\n        memcpy(p,&i32,sizeof(i32));\n        memrev32ifbe(p);\n    } else if (encoding == ZIP_INT_64B) {\n        i64 = value;\n        memcpy(p,&i64,sizeof(i64));\n        memrev64ifbe(p);\n    } else if (encoding >= ZIP_INT_IMM_MIN && encoding <= ZIP_INT_IMM_MAX) {\n        /* Nothing to do, the value is stored in the encoding itself. */\n    } else {\n        assert(NULL);\n    }\n}\n\n/* Read integer encoded as 'encoding' from 'p' */\nstatic int64_t zipLoadInteger(unsigned char *p, unsigned char encoding) {\n    int16_t i16;\n    int32_t i32;\n    int64_t i64, ret = 0;\n    if (encoding == ZIP_INT_8B) {\n        ret = ((int8_t*)p)[0];\n    } else if (encoding == ZIP_INT_16B) {\n        memcpy(&i16,p,sizeof(i16));\n        memrev16ifbe(&i16);\n        ret = i16;\n    } else if (encoding == ZIP_INT_32B) {\n        memcpy(&i32,p,sizeof(i32));\n        memrev32ifbe(&i32);\n        ret = i32;\n    } else if (encoding == ZIP_INT_24B) {\n        i32 = 0;\n        memcpy(((uint8_t*)&i32)+1,p,sizeof(i32)-sizeof(uint8_t));\n        memrev32ifbe(&i32);\n        ret = i32>>8;\n    } else if (encoding == ZIP_INT_64B) {\n        memcpy(&i64,p,sizeof(i64));\n        memrev64ifbe(&i64);\n        ret = i64;\n    } else if (encoding >= ZIP_INT_IMM_MIN && encoding <= ZIP_INT_IMM_MAX) {\n        ret = (encoding & ZIP_INT_IMM_MASK)-1;\n    } else {\n        assert(NULL);\n    }\n    return ret;\n}\n\n/* Return a struct with all information about an entry. */\nstatic zlentry zipEntry(unsigned char *p) {\n    zlentry e;\n\n    ZIP_DECODE_PREVLEN(p, e.prevrawlensize, e.prevrawlen);\n    ZIP_DECODE_LENGTH(p + e.prevrawlensize, e.encoding, e.lensize, e.len);\n    e.headersize = e.prevrawlensize + e.lensize;\n    e.p = p;\n    return e;\n}\n\n/* Create a new empty ziplist. */\nunsigned char *ziplistNew(void) {\n    unsigned int bytes = ZIPLIST_HEADER_SIZE+1;\n    unsigned char *zl = zmalloc(bytes);\n    ZIPLIST_BYTES(zl) = intrev32ifbe(bytes);\n    ZIPLIST_TAIL_OFFSET(zl) = intrev32ifbe(ZIPLIST_HEADER_SIZE);\n    ZIPLIST_LENGTH(zl) = 0;\n    zl[bytes-1] = ZIP_END;\n    return zl;\n}\n\n/* Resize the ziplist. */\nstatic unsigned char *ziplistResize(unsigned char *zl, unsigned int len) {\n    zl = zrealloc(zl,len);\n    ZIPLIST_BYTES(zl) = intrev32ifbe(len);\n    zl[len-1] = ZIP_END;\n    return zl;\n}\n\n/* When an entry is inserted, we need to set the prevlen field of the next\n * entry to equal the length of the inserted entry. It can occur that this\n * length cannot be encoded in 1 byte and the next entry needs to be grow\n * a bit larger to hold the 5-byte encoded prevlen. This can be done for free,\n * because this only happens when an entry is already being inserted (which\n * causes a realloc and memmove). However, encoding the prevlen may require\n * that this entry is grown as well. This effect may cascade throughout\n * the ziplist when there are consecutive entries with a size close to\n * ZIP_BIGLEN, so we need to check that the prevlen can be encoded in every\n * consecutive entry.\n *\n * Note that this effect can also happen in reverse, where the bytes required\n * to encode the prevlen field can shrink. This effect is deliberately ignored,\n * because it can cause a \"flapping\" effect where a chain prevlen fields is\n * first grown and then shrunk again after consecutive inserts. Rather, the\n * field is allowed to stay larger than necessary, because a large prevlen\n * field implies the ziplist is holding large entries anyway.\n *\n * The pointer \"p\" points to the first entry that does NOT need to be\n * updated, i.e. consecutive fields MAY need an update. */\nstatic unsigned char *__ziplistCascadeUpdate(unsigned char *zl, unsigned char *p) {\n    size_t curlen = intrev32ifbe(ZIPLIST_BYTES(zl)), rawlen, rawlensize;\n    size_t offset, noffset, extra;\n    unsigned char *np;\n    zlentry cur, next;\n\n    while (p[0] != ZIP_END) {\n        cur = zipEntry(p);\n        rawlen = cur.headersize + cur.len;\n        rawlensize = zipPrevEncodeLength(NULL,rawlen);\n\n        /* Abort if there is no next entry. */\n        if (p[rawlen] == ZIP_END) break;\n        next = zipEntry(p+rawlen);\n\n        /* Abort when \"prevlen\" has not changed. */\n        if (next.prevrawlen == rawlen) break;\n\n        if (next.prevrawlensize < rawlensize) {\n            /* The \"prevlen\" field of \"next\" needs more bytes to hold\n             * the raw length of \"cur\". */\n            offset = p-zl;\n            extra = rawlensize-next.prevrawlensize;\n            zl = ziplistResize(zl,curlen+extra);\n            p = zl+offset;\n\n            /* Current pointer and offset for next element. */\n            np = p+rawlen;\n            noffset = np-zl;\n\n            /* Update tail offset when next element is not the tail element. */\n            if ((zl+intrev32ifbe(ZIPLIST_TAIL_OFFSET(zl))) != np) {\n                ZIPLIST_TAIL_OFFSET(zl) =\n                    intrev32ifbe(intrev32ifbe(ZIPLIST_TAIL_OFFSET(zl))+extra);\n            }\n\n            /* Move the tail to the back. */\n            memmove(np+rawlensize,\n                np+next.prevrawlensize,\n                curlen-noffset-next.prevrawlensize-1);\n            zipPrevEncodeLength(np,rawlen);\n\n            /* Advance the cursor */\n            p += rawlen;\n            curlen += extra;\n        } else {\n            if (next.prevrawlensize > rawlensize) {\n                /* This would result in shrinking, which we want to avoid.\n                 * So, set \"rawlen\" in the available bytes. */\n                zipPrevEncodeLengthForceLarge(p+rawlen,rawlen);\n            } else {\n                zipPrevEncodeLength(p+rawlen,rawlen);\n            }\n\n            /* Stop here, as the raw length of \"next\" has not changed. */\n            break;\n        }\n    }\n    return zl;\n}\n\n/* Delete \"num\" entries, starting at \"p\". Returns pointer to the ziplist. */\nstatic unsigned char *__ziplistDelete(unsigned char *zl, unsigned char *p, unsigned int num) {\n    unsigned int i, totlen, deleted = 0;\n    size_t offset;\n    int nextdiff = 0;\n    zlentry first, tail;\n\n    first = zipEntry(p);\n    for (i = 0; p[0] != ZIP_END && i < num; i++) {\n        p += zipRawEntryLength(p);\n        deleted++;\n    }\n\n    totlen = p-first.p;\n    if (totlen > 0) {\n        if (p[0] != ZIP_END) {\n            /* Storing `prevrawlen` in this entry may increase or decrease the\n             * number of bytes required compare to the current `prevrawlen`.\n             * There always is room to store this, because it was previously\n             * stored by an entry that is now being deleted. */\n            nextdiff = zipPrevLenByteDiff(p,first.prevrawlen);\n            p -= nextdiff;\n            zipPrevEncodeLength(p,first.prevrawlen);\n\n            /* Update offset for tail */\n            ZIPLIST_TAIL_OFFSET(zl) =\n                intrev32ifbe(intrev32ifbe(ZIPLIST_TAIL_OFFSET(zl))-totlen);\n\n            /* When the tail contains more than one entry, we need to take\n             * \"nextdiff\" in account as well. Otherwise, a change in the\n             * size of prevlen doesn't have an effect on the *tail* offset. */\n            tail = zipEntry(p);\n            if (p[tail.headersize+tail.len] != ZIP_END) {\n                ZIPLIST_TAIL_OFFSET(zl) =\n                   intrev32ifbe(intrev32ifbe(ZIPLIST_TAIL_OFFSET(zl))+nextdiff);\n            }\n\n            /* Move tail to the front of the ziplist */\n            memmove(first.p,p,\n                intrev32ifbe(ZIPLIST_BYTES(zl))-(p-zl)-1);\n        } else {\n            /* The entire tail was deleted. No need to move memory. */\n            ZIPLIST_TAIL_OFFSET(zl) =\n                intrev32ifbe((first.p-zl)-first.prevrawlen);\n        }\n\n        /* Resize and update length */\n        offset = first.p-zl;\n        zl = ziplistResize(zl, intrev32ifbe(ZIPLIST_BYTES(zl))-totlen+nextdiff);\n        ZIPLIST_INCR_LENGTH(zl,-deleted);\n        p = zl+offset;\n\n        /* When nextdiff != 0, the raw length of the next entry has changed, so\n         * we need to cascade the update throughout the ziplist */\n        if (nextdiff != 0)\n            zl = __ziplistCascadeUpdate(zl,p);\n    }\n    return zl;\n}\n\n/* Insert item at \"p\". */\nstatic unsigned char *__ziplistInsert(unsigned char *zl, unsigned char *p, unsigned char *s, unsigned int slen) {\n    size_t curlen = intrev32ifbe(ZIPLIST_BYTES(zl)), reqlen;\n    unsigned int prevlensize, prevlen = 0;\n    size_t offset;\n    int nextdiff = 0;\n    unsigned char encoding = 0;\n    long long value = 123456789; /* initialized to avoid warning. Using a value\n                                    that is easy to see if for some reason\n                                    we use it uninitialized. */\n    zlentry tail;\n\n    /* Find out prevlen for the entry that is inserted. */\n    if (p[0] != ZIP_END) {\n        ZIP_DECODE_PREVLEN(p, prevlensize, prevlen);\n    } else {\n        unsigned char *ptail = ZIPLIST_ENTRY_TAIL(zl);\n        if (ptail[0] != ZIP_END) {\n            prevlen = zipRawEntryLength(ptail);\n        }\n    }\n\n    /* See if the entry can be encoded */\n    if (zipTryEncoding(s,slen,&value,&encoding)) {\n        /* 'encoding' is set to the appropriate integer encoding */\n        reqlen = zipIntSize(encoding);\n    } else {\n        /* 'encoding' is untouched, however zipEncodeLength will use the\n         * string length to figure out how to encode it. */\n        reqlen = slen;\n    }\n    /* We need space for both the length of the previous entry and\n     * the length of the payload. */\n    reqlen += zipPrevEncodeLength(NULL,prevlen);\n    reqlen += zipEncodeLength(NULL,encoding,slen);\n\n    /* When the insert position is not equal to the tail, we need to\n     * make sure that the next entry can hold this entry's length in\n     * its prevlen field. */\n    nextdiff = (p[0] != ZIP_END) ? zipPrevLenByteDiff(p,reqlen) : 0;\n\n    /* Store offset because a realloc may change the address of zl. */\n    offset = p-zl;\n    zl = ziplistResize(zl,curlen+reqlen+nextdiff);\n    p = zl+offset;\n\n    /* Apply memory move when necessary and update tail offset. */\n    if (p[0] != ZIP_END) {\n        /* Subtract one because of the ZIP_END bytes */\n        memmove(p+reqlen,p-nextdiff,curlen-offset-1+nextdiff);\n\n        /* Encode this entry's raw length in the next entry. */\n        zipPrevEncodeLength(p+reqlen,reqlen);\n\n        /* Update offset for tail */\n        ZIPLIST_TAIL_OFFSET(zl) =\n            intrev32ifbe(intrev32ifbe(ZIPLIST_TAIL_OFFSET(zl))+reqlen);\n\n        /* When the tail contains more than one entry, we need to take\n         * \"nextdiff\" in account as well. Otherwise, a change in the\n         * size of prevlen doesn't have an effect on the *tail* offset. */\n        tail = zipEntry(p+reqlen);\n        if (p[reqlen+tail.headersize+tail.len] != ZIP_END) {\n            ZIPLIST_TAIL_OFFSET(zl) =\n                intrev32ifbe(intrev32ifbe(ZIPLIST_TAIL_OFFSET(zl))+nextdiff);\n        }\n    } else {\n        /* This element will be the new tail. */\n        ZIPLIST_TAIL_OFFSET(zl) = intrev32ifbe(p-zl);\n    }\n\n    /* When nextdiff != 0, the raw length of the next entry has changed, so\n     * we need to cascade the update throughout the ziplist */\n    if (nextdiff != 0) {\n        offset = p-zl;\n        zl = __ziplistCascadeUpdate(zl,p+reqlen);\n        p = zl+offset;\n    }\n\n    /* Write the entry */\n    p += zipPrevEncodeLength(p,prevlen);\n    p += zipEncodeLength(p,encoding,slen);\n    if (ZIP_IS_STR(encoding)) {\n        memcpy(p,s,slen);\n    } else {\n        zipSaveInteger(p,value,encoding);\n    }\n    ZIPLIST_INCR_LENGTH(zl,1);\n    return zl;\n}\n\nunsigned char *ziplistPush(unsigned char *zl, unsigned char *s, unsigned int slen, int where) {\n    unsigned char *p;\n    p = (where == ZIPLIST_HEAD) ? ZIPLIST_ENTRY_HEAD(zl) : ZIPLIST_ENTRY_END(zl);\n    return __ziplistInsert(zl,p,s,slen);\n}\n\n/* Returns an offset to use for iterating with ziplistNext. When the given\n * index is negative, the list is traversed back to front. When the list\n * doesn't contain an element at the provided index, NULL is returned. */\nunsigned char *ziplistIndex(unsigned char *zl, int index) {\n    unsigned char *p;\n    unsigned int prevlensize, prevlen = 0;\n    if (index < 0) {\n        index = (-index)-1;\n        p = ZIPLIST_ENTRY_TAIL(zl);\n        if (p[0] != ZIP_END) {\n            ZIP_DECODE_PREVLEN(p, prevlensize, prevlen);\n            while (prevlen > 0 && index--) {\n                p -= prevlen;\n                ZIP_DECODE_PREVLEN(p, prevlensize, prevlen);\n            }\n        }\n    } else {\n        p = ZIPLIST_ENTRY_HEAD(zl);\n        while (p[0] != ZIP_END && index--) {\n            p += zipRawEntryLength(p);\n        }\n    }\n    return (p[0] == ZIP_END || index > 0) ? NULL : p;\n}\n\n/* Return pointer to next entry in ziplist.\n *\n * zl is the pointer to the ziplist\n * p is the pointer to the current element\n *\n * The element after 'p' is returned, otherwise NULL if we are at the end. */\nunsigned char *ziplistNext(unsigned char *zl, unsigned char *p) {\n    ((void) zl);\n\n    /* \"p\" could be equal to ZIP_END, caused by ziplistDelete,\n     * and we should return NULL. Otherwise, we should return NULL\n     * when the *next* element is ZIP_END (there is no next entry). */\n    if (p[0] == ZIP_END) {\n        return NULL;\n    }\n\n    p += zipRawEntryLength(p);\n    if (p[0] == ZIP_END) {\n        return NULL;\n    }\n\n    return p;\n}\n\n/* Return pointer to previous entry in ziplist. */\nunsigned char *ziplistPrev(unsigned char *zl, unsigned char *p) {\n    unsigned int prevlensize, prevlen = 0;\n\n    /* Iterating backwards from ZIP_END should return the tail. When \"p\" is\n     * equal to the first element of the list, we're already at the head,\n     * and should return NULL. */\n    if (p[0] == ZIP_END) {\n        p = ZIPLIST_ENTRY_TAIL(zl);\n        return (p[0] == ZIP_END) ? NULL : p;\n    } else if (p == ZIPLIST_ENTRY_HEAD(zl)) {\n        return NULL;\n    } else {\n        ZIP_DECODE_PREVLEN(p, prevlensize, prevlen);\n        assert(prevlen > 0);\n        return p-prevlen;\n    }\n}\n\n/* Get entry pointed to by 'p' and store in either '*sstr' or 'sval' depending\n * on the encoding of the entry. '*sstr' is always set to NULL to be able\n * to find out whether the string pointer or the integer value was set.\n * Return 0 if 'p' points to the end of the ziplist, 1 otherwise. */\nunsigned int ziplistGet(unsigned char *p, unsigned char **sstr, unsigned int *slen, long long *sval) {\n    zlentry entry;\n    if (p == NULL || p[0] == ZIP_END) return 0;\n    if (sstr) *sstr = NULL;\n\n    entry = zipEntry(p);\n    if (ZIP_IS_STR(entry.encoding)) {\n        if (sstr) {\n            *slen = entry.len;\n            *sstr = p+entry.headersize;\n        }\n    } else {\n        if (sval) {\n            *sval = zipLoadInteger(p+entry.headersize,entry.encoding);\n        }\n    }\n    return 1;\n}\n\n/* Insert an entry at \"p\". */\nunsigned char *ziplistInsert(unsigned char *zl, unsigned char *p, unsigned char *s, unsigned int slen) {\n    return __ziplistInsert(zl,p,s,slen);\n}\n\n/* Delete a single entry from the ziplist, pointed to by *p.\n * Also update *p in place, to be able to iterate over the\n * ziplist, while deleting entries. */\nunsigned char *ziplistDelete(unsigned char *zl, unsigned char **p) {\n    size_t offset = *p-zl;\n    zl = __ziplistDelete(zl,*p,1);\n\n    /* Store pointer to current element in p, because ziplistDelete will\n     * do a realloc which might result in a different \"zl\"-pointer.\n     * When the delete direction is back to front, we might delete the last\n     * entry and end up with \"p\" pointing to ZIP_END, so check this. */\n    *p = zl+offset;\n    return zl;\n}\n\n/* Delete a range of entries from the ziplist. */\nunsigned char *ziplistDeleteRange(unsigned char *zl, unsigned int index, unsigned int num) {\n    unsigned char *p = ziplistIndex(zl,index);\n    return (p == NULL) ? zl : __ziplistDelete(zl,p,num);\n}\n\n/* Compare entry pointer to by 'p' with 'sstr' of length 'slen'. */\n/* Return 1 if equal. */\nunsigned int ziplistCompare(unsigned char *p, unsigned char *sstr, unsigned int slen) {\n    zlentry entry;\n    unsigned char sencoding;\n    long long zval, sval;\n    if (p[0] == ZIP_END) return 0;\n\n    entry = zipEntry(p);\n    if (ZIP_IS_STR(entry.encoding)) {\n        /* Raw compare */\n        if (entry.len == slen) {\n            return memcmp(p+entry.headersize,sstr,slen) == 0;\n        } else {\n            return 0;\n        }\n    } else {\n        /* Try to compare encoded values. Don't compare encoding because\n         * different implementations may encoded integers differently. */\n        if (zipTryEncoding(sstr,slen,&sval,&sencoding)) {\n          zval = zipLoadInteger(p+entry.headersize,entry.encoding);\n          return zval == sval;\n        }\n    }\n    return 0;\n}\n\n/* Find pointer to the entry equal to the specified entry. Skip 'skip' entries\n * between every comparison. Returns NULL when the field could not be found. */\nunsigned char *ziplistFind(unsigned char *p, unsigned char *vstr, unsigned int vlen, unsigned int skip) {\n    int skipcnt = 0;\n    unsigned char vencoding = 0;\n    long long vll = 0;\n\n    while (p[0] != ZIP_END) {\n        unsigned int prevlensize, encoding, lensize, len;\n        unsigned char *q;\n\n        ZIP_DECODE_PREVLENSIZE(p, prevlensize);\n        ZIP_DECODE_LENGTH(p + prevlensize, encoding, lensize, len);\n        q = p + prevlensize + lensize;\n\n        if (skipcnt == 0) {\n            /* Compare current entry with specified entry */\n            if (ZIP_IS_STR(encoding)) {\n                if (len == vlen && memcmp(q, vstr, vlen) == 0) {\n                    return p;\n                }\n            } else {\n                /* Find out if the searched field can be encoded. Note that\n                 * we do it only the first time, once done vencoding is set\n                 * to non-zero and vll is set to the integer value. */\n                if (vencoding == 0) {\n                    if (!zipTryEncoding(vstr, vlen, &vll, &vencoding)) {\n                        /* If the entry can't be encoded we set it to\n                         * UCHAR_MAX so that we don't retry again the next\n                         * time. */\n                        vencoding = UCHAR_MAX;\n                    }\n                    /* Must be non-zero by now */\n                    assert(vencoding);\n                }\n\n                /* Compare current entry with specified entry, do it only\n                 * if vencoding != UCHAR_MAX because if there is no encoding\n                 * possible for the field it can't be a valid integer. */\n                if (vencoding != UCHAR_MAX) {\n                    long long ll = zipLoadInteger(q, encoding);\n                    if (ll == vll) {\n                        return p;\n                    }\n                }\n            }\n\n            /* Reset skip count */\n            skipcnt = skip;\n        } else {\n            /* Skip entry */\n            skipcnt--;\n        }\n\n        /* Move to next entry */\n        p = q + len;\n    }\n\n    return NULL;\n}\n\n/* Return length of ziplist. */\nunsigned int ziplistLen(unsigned char *zl) {\n    unsigned int len = 0;\n    if (intrev16ifbe(ZIPLIST_LENGTH(zl)) < UINT16_MAX) {\n        len = intrev16ifbe(ZIPLIST_LENGTH(zl));\n    } else {\n        unsigned char *p = zl+ZIPLIST_HEADER_SIZE;\n        while (*p != ZIP_END) {\n            p += zipRawEntryLength(p);\n            len++;\n        }\n\n        /* Re-store length if small enough */\n        if (len < UINT16_MAX) ZIPLIST_LENGTH(zl) = intrev16ifbe(len);\n    }\n    return len;\n}\n\n/* Return ziplist blob size in bytes. */\nsize_t ziplistBlobLen(unsigned char *zl) {\n    return intrev32ifbe(ZIPLIST_BYTES(zl));\n}\n\nvoid ziplistRepr(unsigned char *zl) {\n    unsigned char *p;\n    int index = 0;\n    zlentry entry;\n\n    printf(\n        \"{total bytes %d} \"\n        \"{length %u}\\n\"\n        \"{tail offset %u}\\n\",\n        intrev32ifbe(ZIPLIST_BYTES(zl)),\n        intrev16ifbe(ZIPLIST_LENGTH(zl)),\n        intrev32ifbe(ZIPLIST_TAIL_OFFSET(zl)));\n    p = ZIPLIST_ENTRY_HEAD(zl);\n    while(*p != ZIP_END) {\n        entry = zipEntry(p);\n        printf(\n            \"{\"\n                \"addr 0x%08lx, \"\n                \"index %2d, \"\n                \"offset %5ld, \"\n                \"rl: %5u, \"\n                \"hs %2u, \"\n                \"pl: %5u, \"\n                \"pls: %2u, \"\n                \"payload %5u\"\n            \"} \",\n            (long unsigned)p,\n            index,\n            (unsigned long) (p-zl),\n            entry.headersize+entry.len,\n            entry.headersize,\n            entry.prevrawlen,\n            entry.prevrawlensize,\n            entry.len);\n        p += entry.headersize;\n        if (ZIP_IS_STR(entry.encoding)) {\n            if (entry.len > 40) {\n                if (fwrite(p,40,1,stdout) == 0) perror(\"fwrite\");\n                printf(\"...\");\n            } else {\n                if (entry.len &&\n                    fwrite(p,entry.len,1,stdout) == 0) perror(\"fwrite\");\n            }\n        } else {\n            printf(\"%lld\", (long long) zipLoadInteger(p,entry.encoding));\n        }\n        printf(\"\\n\");\n        p += entry.len;\n        index++;\n    }\n    printf(\"{end}\\n\\n\");\n}\n\n#ifdef ZIPLIST_TEST_MAIN\n#include <sys/time.h>\n#include \"adlist.h\"\n#include \"sds.h\"\n\n#define debug(f, ...) { if (DEBUG) printf(f, __VA_ARGS__); }\n\nunsigned char *createList() {\n    unsigned char *zl = ziplistNew();\n    zl = ziplistPush(zl, (unsigned char*)\"foo\", 3, ZIPLIST_TAIL);\n    zl = ziplistPush(zl, (unsigned char*)\"quux\", 4, ZIPLIST_TAIL);\n    zl = ziplistPush(zl, (unsigned char*)\"hello\", 5, ZIPLIST_HEAD);\n    zl = ziplistPush(zl, (unsigned char*)\"1024\", 4, ZIPLIST_TAIL);\n    return zl;\n}\n\nunsigned char *createIntList() {\n    unsigned char *zl = ziplistNew();\n    char buf[32];\n\n    sprintf(buf, \"100\");\n    zl = ziplistPush(zl, (unsigned char*)buf, strlen(buf), ZIPLIST_TAIL);\n    sprintf(buf, \"128000\");\n    zl = ziplistPush(zl, (unsigned char*)buf, strlen(buf), ZIPLIST_TAIL);\n    sprintf(buf, \"-100\");\n    zl = ziplistPush(zl, (unsigned char*)buf, strlen(buf), ZIPLIST_HEAD);\n    sprintf(buf, \"4294967296\");\n    zl = ziplistPush(zl, (unsigned char*)buf, strlen(buf), ZIPLIST_HEAD);\n    sprintf(buf, \"non integer\");\n    zl = ziplistPush(zl, (unsigned char*)buf, strlen(buf), ZIPLIST_TAIL);\n    sprintf(buf, \"much much longer non integer\");\n    zl = ziplistPush(zl, (unsigned char*)buf, strlen(buf), ZIPLIST_TAIL);\n    return zl;\n}\n\nlong long usec(void) {\n    struct timeval tv;\n    gettimeofday(&tv,NULL);\n    return (((long long)tv.tv_sec)*1000000)+tv.tv_usec;\n}\n\nvoid stress(int pos, int num, int maxsize, int dnum) {\n    int i,j,k;\n    unsigned char *zl;\n    char posstr[2][5] = { \"HEAD\", \"TAIL\" };\n    long long start;\n    for (i = 0; i < maxsize; i+=dnum) {\n        zl = ziplistNew();\n        for (j = 0; j < i; j++) {\n            zl = ziplistPush(zl,(unsigned char*)\"quux\",4,ZIPLIST_TAIL);\n        }\n\n        /* Do num times a push+pop from pos */\n        start = usec();\n        for (k = 0; k < num; k++) {\n            zl = ziplistPush(zl,(unsigned char*)\"quux\",4,pos);\n            zl = ziplistDeleteRange(zl,0,1);\n        }\n        printf(\"List size: %8d, bytes: %8d, %dx push+pop (%s): %6lld usec\\n\",\n            i,intrev32ifbe(ZIPLIST_BYTES(zl)),num,posstr[pos],usec()-start);\n        zfree(zl);\n    }\n}\n\nvoid pop(unsigned char *zl, int where) {\n    unsigned char *p, *vstr;\n    unsigned int vlen;\n    long long vlong;\n\n    p = ziplistIndex(zl,where == ZIPLIST_HEAD ? 0 : -1);\n    if (ziplistGet(p,&vstr,&vlen,&vlong)) {\n        if (where == ZIPLIST_HEAD)\n            printf(\"Pop head: \");\n        else\n            printf(\"Pop tail: \");\n\n        if (vstr)\n            if (vlen && fwrite(vstr,vlen,1,stdout) == 0) perror(\"fwrite\");\n        else\n            printf(\"%lld\", vlong);\n\n        printf(\"\\n\");\n        ziplistDeleteRange(zl,-1,1);\n    } else {\n        printf(\"ERROR: Could not pop\\n\");\n        exit(1);\n    }\n}\n\nint randstring(char *target, unsigned int min, unsigned int max) {\n    int p = 0;\n    int len = min+rand()%(max-min+1);\n    int minval, maxval;\n    switch(rand() % 3) {\n    case 0:\n        minval = 0;\n        maxval = 255;\n    break;\n    case 1:\n        minval = 48;\n        maxval = 122;\n    break;\n    case 2:\n        minval = 48;\n        maxval = 52;\n    break;\n    default:\n        assert(NULL);\n    }\n\n    while(p < len)\n        target[p++] = minval+rand()%(maxval-minval+1);\n    return len;\n}\n\nvoid verify(unsigned char *zl, zlentry *e) {\n    int i;\n    int len = ziplistLen(zl);\n    zlentry _e;\n\n    for (i = 0; i < len; i++) {\n        memset(&e[i], 0, sizeof(zlentry));\n        e[i] = zipEntry(ziplistIndex(zl, i));\n\n        memset(&_e, 0, sizeof(zlentry));\n        _e = zipEntry(ziplistIndex(zl, -len+i));\n\n        assert(memcmp(&e[i], &_e, sizeof(zlentry)) == 0);\n    }\n}\n\nint main(int argc, char **argv) {\n    unsigned char *zl, *p;\n    unsigned char *entry;\n    unsigned int elen;\n    long long value;\n\n    /* If an argument is given, use it as the random seed. */\n    if (argc == 2)\n        srand(atoi(argv[1]));\n\n    zl = createIntList();\n    ziplistRepr(zl);\n\n    zl = createList();\n    ziplistRepr(zl);\n\n    pop(zl,ZIPLIST_TAIL);\n    ziplistRepr(zl);\n\n    pop(zl,ZIPLIST_HEAD);\n    ziplistRepr(zl);\n\n    pop(zl,ZIPLIST_TAIL);\n    ziplistRepr(zl);\n\n    pop(zl,ZIPLIST_TAIL);\n    ziplistRepr(zl);\n\n    printf(\"Get element at index 3:\\n\");\n    {\n        zl = createList();\n        p = ziplistIndex(zl, 3);\n        if (!ziplistGet(p, &entry, &elen, &value)) {\n            printf(\"ERROR: Could not access index 3\\n\");\n            return 1;\n        }\n        if (entry) {\n            if (elen && fwrite(entry,elen,1,stdout) == 0) perror(\"fwrite\");\n            printf(\"\\n\");\n        } else {\n            printf(\"%lld\\n\", value);\n        }\n        printf(\"\\n\");\n    }\n\n    printf(\"Get element at index 4 (out of range):\\n\");\n    {\n        zl = createList();\n        p = ziplistIndex(zl, 4);\n        if (p == NULL) {\n            printf(\"No entry\\n\");\n        } else {\n            printf(\"ERROR: Out of range index should return NULL, returned offset: %ld\\n\", p-zl);\n            return 1;\n        }\n        printf(\"\\n\");\n    }\n\n    printf(\"Get element at index -1 (last element):\\n\");\n    {\n        zl = createList();\n        p = ziplistIndex(zl, -1);\n        if (!ziplistGet(p, &entry, &elen, &value)) {\n            printf(\"ERROR: Could not access index -1\\n\");\n            return 1;\n        }\n        if (entry) {\n            if (elen && fwrite(entry,elen,1,stdout) == 0) perror(\"fwrite\");\n            printf(\"\\n\");\n        } else {\n            printf(\"%lld\\n\", value);\n        }\n        printf(\"\\n\");\n    }\n\n    printf(\"Get element at index -4 (first element):\\n\");\n    {\n        zl = createList();\n        p = ziplistIndex(zl, -4);\n        if (!ziplistGet(p, &entry, &elen, &value)) {\n            printf(\"ERROR: Could not access index -4\\n\");\n            return 1;\n        }\n        if (entry) {\n            if (elen && fwrite(entry,elen,1,stdout) == 0) perror(\"fwrite\");\n            printf(\"\\n\");\n        } else {\n            printf(\"%lld\\n\", value);\n        }\n        printf(\"\\n\");\n    }\n\n    printf(\"Get element at index -5 (reverse out of range):\\n\");\n    {\n        zl = createList();\n        p = ziplistIndex(zl, -5);\n        if (p == NULL) {\n            printf(\"No entry\\n\");\n        } else {\n            printf(\"ERROR: Out of range index should return NULL, returned offset: %ld\\n\", p-zl);\n            return 1;\n        }\n        printf(\"\\n\");\n    }\n\n    printf(\"Iterate list from 0 to end:\\n\");\n    {\n        zl = createList();\n        p = ziplistIndex(zl, 0);\n        while (ziplistGet(p, &entry, &elen, &value)) {\n            printf(\"Entry: \");\n            if (entry) {\n                if (elen && fwrite(entry,elen,1,stdout) == 0) perror(\"fwrite\");\n            } else {\n                printf(\"%lld\", value);\n            }\n            p = ziplistNext(zl,p);\n            printf(\"\\n\");\n        }\n        printf(\"\\n\");\n    }\n\n    printf(\"Iterate list from 1 to end:\\n\");\n    {\n        zl = createList();\n        p = ziplistIndex(zl, 1);\n        while (ziplistGet(p, &entry, &elen, &value)) {\n            printf(\"Entry: \");\n            if (entry) {\n                if (elen && fwrite(entry,elen,1,stdout) == 0) perror(\"fwrite\");\n            } else {\n                printf(\"%lld\", value);\n            }\n            p = ziplistNext(zl,p);\n            printf(\"\\n\");\n        }\n        printf(\"\\n\");\n    }\n\n    printf(\"Iterate list from 2 to end:\\n\");\n    {\n        zl = createList();\n        p = ziplistIndex(zl, 2);\n        while (ziplistGet(p, &entry, &elen, &value)) {\n            printf(\"Entry: \");\n            if (entry) {\n                if (elen && fwrite(entry,elen,1,stdout) == 0) perror(\"fwrite\");\n            } else {\n                printf(\"%lld\", value);\n            }\n            p = ziplistNext(zl,p);\n            printf(\"\\n\");\n        }\n        printf(\"\\n\");\n    }\n\n    printf(\"Iterate starting out of range:\\n\");\n    {\n        zl = createList();\n        p = ziplistIndex(zl, 4);\n        if (!ziplistGet(p, &entry, &elen, &value)) {\n            printf(\"No entry\\n\");\n        } else {\n            printf(\"ERROR\\n\");\n        }\n        printf(\"\\n\");\n    }\n\n    printf(\"Iterate from back to front:\\n\");\n    {\n        zl = createList();\n        p = ziplistIndex(zl, -1);\n        while (ziplistGet(p, &entry, &elen, &value)) {\n            printf(\"Entry: \");\n            if (entry) {\n                if (elen && fwrite(entry,elen,1,stdout) == 0) perror(\"fwrite\");\n            } else {\n                printf(\"%lld\", value);\n            }\n            p = ziplistPrev(zl,p);\n            printf(\"\\n\");\n        }\n        printf(\"\\n\");\n    }\n\n    printf(\"Iterate from back to front, deleting all items:\\n\");\n    {\n        zl = createList();\n        p = ziplistIndex(zl, -1);\n        while (ziplistGet(p, &entry, &elen, &value)) {\n            printf(\"Entry: \");\n            if (entry) {\n                if (elen && fwrite(entry,elen,1,stdout) == 0) perror(\"fwrite\");\n            } else {\n                printf(\"%lld\", value);\n            }\n            zl = ziplistDelete(zl,&p);\n            p = ziplistPrev(zl,p);\n            printf(\"\\n\");\n        }\n        printf(\"\\n\");\n    }\n\n    printf(\"Delete inclusive range 0,0:\\n\");\n    {\n        zl = createList();\n        zl = ziplistDeleteRange(zl, 0, 1);\n        ziplistRepr(zl);\n    }\n\n    printf(\"Delete inclusive range 0,1:\\n\");\n    {\n        zl = createList();\n        zl = ziplistDeleteRange(zl, 0, 2);\n        ziplistRepr(zl);\n    }\n\n    printf(\"Delete inclusive range 1,2:\\n\");\n    {\n        zl = createList();\n        zl = ziplistDeleteRange(zl, 1, 2);\n        ziplistRepr(zl);\n    }\n\n    printf(\"Delete with start index out of range:\\n\");\n    {\n        zl = createList();\n        zl = ziplistDeleteRange(zl, 5, 1);\n        ziplistRepr(zl);\n    }\n\n    printf(\"Delete with num overflow:\\n\");\n    {\n        zl = createList();\n        zl = ziplistDeleteRange(zl, 1, 5);\n        ziplistRepr(zl);\n    }\n\n    printf(\"Delete foo while iterating:\\n\");\n    {\n        zl = createList();\n        p = ziplistIndex(zl,0);\n        while (ziplistGet(p,&entry,&elen,&value)) {\n            if (entry && strncmp(\"foo\",(char*)entry,elen) == 0) {\n                printf(\"Delete foo\\n\");\n                zl = ziplistDelete(zl,&p);\n            } else {\n                printf(\"Entry: \");\n                if (entry) {\n                    if (elen && fwrite(entry,elen,1,stdout) == 0)\n                        perror(\"fwrite\");\n                } else {\n                    printf(\"%lld\",value);\n                }\n                p = ziplistNext(zl,p);\n                printf(\"\\n\");\n            }\n        }\n        printf(\"\\n\");\n        ziplistRepr(zl);\n    }\n\n    printf(\"Regression test for >255 byte strings:\\n\");\n    {\n        char v1[257],v2[257];\n        memset(v1,'x',256);\n        memset(v2,'y',256);\n        zl = ziplistNew();\n        zl = ziplistPush(zl,(unsigned char*)v1,strlen(v1),ZIPLIST_TAIL);\n        zl = ziplistPush(zl,(unsigned char*)v2,strlen(v2),ZIPLIST_TAIL);\n\n        /* Pop values again and compare their value. */\n        p = ziplistIndex(zl,0);\n        assert(ziplistGet(p,&entry,&elen,&value));\n        assert(strncmp(v1,(char*)entry,elen) == 0);\n        p = ziplistIndex(zl,1);\n        assert(ziplistGet(p,&entry,&elen,&value));\n        assert(strncmp(v2,(char*)entry,elen) == 0);\n        printf(\"SUCCESS\\n\\n\");\n    }\n\n    printf(\"Regression test deleting next to last entries:\\n\");\n    {\n        char v[3][257];\n        zlentry e[3];\n        int i;\n\n        for (i = 0; i < (sizeof(v)/sizeof(v[0])); i++) {\n            memset(v[i], 'a' + i, sizeof(v[0]));\n        }\n\n        v[0][256] = '\\0';\n        v[1][  1] = '\\0';\n        v[2][256] = '\\0';\n\n        zl = ziplistNew();\n        for (i = 0; i < (sizeof(v)/sizeof(v[0])); i++) {\n            zl = ziplistPush(zl, (unsigned char *) v[i], strlen(v[i]), ZIPLIST_TAIL);\n        }\n\n        verify(zl, e);\n\n        assert(e[0].prevrawlensize == 1);\n        assert(e[1].prevrawlensize == 5);\n        assert(e[2].prevrawlensize == 1);\n\n        /* Deleting entry 1 will increase `prevrawlensize` for entry 2 */\n        unsigned char *p = e[1].p;\n        zl = ziplistDelete(zl, &p);\n\n        verify(zl, e);\n\n        assert(e[0].prevrawlensize == 1);\n        assert(e[1].prevrawlensize == 5);\n\n        printf(\"SUCCESS\\n\\n\");\n    }\n\n    printf(\"Create long list and check indices:\\n\");\n    {\n        zl = ziplistNew();\n        char buf[32];\n        int i,len;\n        for (i = 0; i < 1000; i++) {\n            len = sprintf(buf,\"%d\",i);\n            zl = ziplistPush(zl,(unsigned char*)buf,len,ZIPLIST_TAIL);\n        }\n        for (i = 0; i < 1000; i++) {\n            p = ziplistIndex(zl,i);\n            assert(ziplistGet(p,NULL,NULL,&value));\n            assert(i == value);\n\n            p = ziplistIndex(zl,-i-1);\n            assert(ziplistGet(p,NULL,NULL,&value));\n            assert(999-i == value);\n        }\n        printf(\"SUCCESS\\n\\n\");\n    }\n\n    printf(\"Compare strings with ziplist entries:\\n\");\n    {\n        zl = createList();\n        p = ziplistIndex(zl,0);\n        if (!ziplistCompare(p,(unsigned char*)\"hello\",5)) {\n            printf(\"ERROR: not \\\"hello\\\"\\n\");\n            return 1;\n        }\n        if (ziplistCompare(p,(unsigned char*)\"hella\",5)) {\n            printf(\"ERROR: \\\"hella\\\"\\n\");\n            return 1;\n        }\n\n        p = ziplistIndex(zl,3);\n        if (!ziplistCompare(p,(unsigned char*)\"1024\",4)) {\n            printf(\"ERROR: not \\\"1024\\\"\\n\");\n            return 1;\n        }\n        if (ziplistCompare(p,(unsigned char*)\"1025\",4)) {\n            printf(\"ERROR: \\\"1025\\\"\\n\");\n            return 1;\n        }\n        printf(\"SUCCESS\\n\\n\");\n    }\n\n    printf(\"Stress with random payloads of different encoding:\\n\");\n    {\n        int i,j,len,where;\n        unsigned char *p;\n        char buf[1024];\n        int buflen;\n        list *ref;\n        listNode *refnode;\n\n        /* Hold temp vars from ziplist */\n        unsigned char *sstr;\n        unsigned int slen;\n        long long sval;\n\n        for (i = 0; i < 20000; i++) {\n            zl = ziplistNew();\n            ref = listCreate();\n            listSetFreeMethod(ref,sdsfree);\n            len = rand() % 256;\n\n            /* Create lists */\n            for (j = 0; j < len; j++) {\n                where = (rand() & 1) ? ZIPLIST_HEAD : ZIPLIST_TAIL;\n                if (rand() % 2) {\n                    buflen = randstring(buf,1,sizeof(buf)-1);\n                } else {\n                    switch(rand() % 3) {\n                    case 0:\n                        buflen = sprintf(buf,\"%lld\",(0LL + rand()) >> 20);\n                        break;\n                    case 1:\n                        buflen = sprintf(buf,\"%lld\",(0LL + rand()));\n                        break;\n                    case 2:\n                        buflen = sprintf(buf,\"%lld\",(0LL + rand()) << 20);\n                        break;\n                    default:\n                        assert(NULL);\n                    }\n                }\n\n                /* Add to ziplist */\n                zl = ziplistPush(zl, (unsigned char*)buf, buflen, where);\n\n                /* Add to reference list */\n                if (where == ZIPLIST_HEAD) {\n                    listAddNodeHead(ref,sdsnewlen(buf, buflen));\n                } else if (where == ZIPLIST_TAIL) {\n                    listAddNodeTail(ref,sdsnewlen(buf, buflen));\n                } else {\n                    assert(NULL);\n                }\n            }\n\n            assert(listLength(ref) == ziplistLen(zl));\n            for (j = 0; j < len; j++) {\n                /* Naive way to get elements, but similar to the stresser\n                 * executed from the Tcl test suite. */\n                p = ziplistIndex(zl,j);\n                refnode = listIndex(ref,j);\n\n                assert(ziplistGet(p,&sstr,&slen,&sval));\n                if (sstr == NULL) {\n                    buflen = sprintf(buf,\"%lld\",sval);\n                } else {\n                    buflen = slen;\n                    memcpy(buf,sstr,buflen);\n                    buf[buflen] = '\\0';\n                }\n                assert(memcmp(buf,listNodeValue(refnode),buflen) == 0);\n            }\n            zfree(zl);\n            listRelease(ref);\n        }\n        printf(\"SUCCESS\\n\\n\");\n    }\n\n    printf(\"Stress with variable ziplist size:\\n\");\n    {\n        stress(ZIPLIST_HEAD,100000,16384,256);\n        stress(ZIPLIST_TAIL,100000,16384,256);\n    }\n\n    return 0;\n}\n\n#endif\n"
  },
  {
    "path": "extern/deprecated/redis-2.8.21/src/ziplist.h",
    "content": "/*\n * Copyright (c) 2009-2012, Pieter Noordhuis <pcnoordhuis at gmail dot com>\n * Copyright (c) 2009-2012, Salvatore Sanfilippo <antirez at gmail dot com>\n * All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions are met:\n *\n *   * Redistributions of source code must retain the above copyright notice,\n *     this list of conditions and the following disclaimer.\n *   * Redistributions in binary form must reproduce the above copyright\n *     notice, this list of conditions and the following disclaimer in the\n *     documentation and/or other materials provided with the distribution.\n *   * Neither the name of Redis nor the names of its contributors may be used\n *     to endorse or promote products derived from this software without\n *     specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\"\n * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\n * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE\n * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR\n * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF\n * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS\n * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN\n * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)\n * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE\n * POSSIBILITY OF SUCH DAMAGE.\n */\n\n#define ZIPLIST_HEAD 0\n#define ZIPLIST_TAIL 1\n\nunsigned char *ziplistNew(void);\nunsigned char *ziplistPush(unsigned char *zl, unsigned char *s, unsigned int slen, int where);\nunsigned char *ziplistIndex(unsigned char *zl, int index);\nunsigned char *ziplistNext(unsigned char *zl, unsigned char *p);\nunsigned char *ziplistPrev(unsigned char *zl, unsigned char *p);\nunsigned int ziplistGet(unsigned char *p, unsigned char **sval, unsigned int *slen, long long *lval);\nunsigned char *ziplistInsert(unsigned char *zl, unsigned char *p, unsigned char *s, unsigned int slen);\nunsigned char *ziplistDelete(unsigned char *zl, unsigned char **p);\nunsigned char *ziplistDeleteRange(unsigned char *zl, unsigned int index, unsigned int num);\nunsigned int ziplistCompare(unsigned char *p, unsigned char *s, unsigned int slen);\nunsigned char *ziplistFind(unsigned char *p, unsigned char *vstr, unsigned int vlen, unsigned int skip);\nunsigned int ziplistLen(unsigned char *zl);\nsize_t ziplistBlobLen(unsigned char *zl);\n"
  },
  {
    "path": "extern/deprecated/redis-2.8.21/src/zipmap.c",
    "content": "/* String -> String Map data structure optimized for size.\n * This file implements a data structure mapping strings to other strings\n * implementing an O(n) lookup data structure designed to be very memory\n * efficient.\n *\n * The Redis Hash type uses this data structure for hashes composed of a small\n * number of elements, to switch to a hash table once a given number of\n * elements is reached.\n *\n * Given that many times Redis Hashes are used to represent objects composed\n * of few fields, this is a very big win in terms of used memory.\n *\n * --------------------------------------------------------------------------\n *\n * Copyright (c) 2009-2010, Salvatore Sanfilippo <antirez at gmail dot com>\n * All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions are met:\n *\n *   * Redistributions of source code must retain the above copyright notice,\n *     this list of conditions and the following disclaimer.\n *   * Redistributions in binary form must reproduce the above copyright\n *     notice, this list of conditions and the following disclaimer in the\n *     documentation and/or other materials provided with the distribution.\n *   * Neither the name of Redis nor the names of its contributors may be used\n *     to endorse or promote products derived from this software without\n *     specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\"\n * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\n * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE\n * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR\n * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF\n * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS\n * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN\n * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)\n * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE\n * POSSIBILITY OF SUCH DAMAGE.\n */\n\n/* Memory layout of a zipmap, for the map \"foo\" => \"bar\", \"hello\" => \"world\":\n *\n * <zmlen><len>\"foo\"<len><free>\"bar\"<len>\"hello\"<len><free>\"world\"\n *\n * <zmlen> is 1 byte length that holds the current size of the zipmap.\n * When the zipmap length is greater than or equal to 254, this value\n * is not used and the zipmap needs to be traversed to find out the length.\n *\n * <len> is the length of the following string (key or value).\n * <len> lengths are encoded in a single value or in a 5 bytes value.\n * If the first byte value (as an unsigned 8 bit value) is between 0 and\n * 253, it's a single-byte length. If it is 254 then a four bytes unsigned\n * integer follows (in the host byte ordering). A value of 255 is used to\n * signal the end of the hash.\n *\n * <free> is the number of free unused bytes after the string, resulting\n * from modification of values associated to a key. For instance if \"foo\"\n * is set to \"bar\", and later \"foo\" will be set to \"hi\", it will have a\n * free byte to use if the value will enlarge again later, or even in\n * order to add a key/value pair if it fits.\n *\n * <free> is always an unsigned 8 bit number, because if after an\n * update operation there are more than a few free bytes, the zipmap will be\n * reallocated to make sure it is as small as possible.\n *\n * The most compact representation of the above two elements hash is actually:\n *\n * \"\\x02\\x03foo\\x03\\x00bar\\x05hello\\x05\\x00world\\xff\"\n *\n * Note that because keys and values are prefixed length \"objects\",\n * the lookup will take O(N) where N is the number of elements\n * in the zipmap and *not* the number of bytes needed to represent the zipmap.\n * This lowers the constant times considerably.\n */\n\n#include <stdio.h>\n#include <string.h>\n#include \"zmalloc.h\"\n#include \"endianconv.h\"\n\n#define ZIPMAP_BIGLEN 254\n#define ZIPMAP_END 255\n\n/* The following defines the max value for the <free> field described in the\n * comments above, that is, the max number of trailing bytes in a value. */\n#define ZIPMAP_VALUE_MAX_FREE 4\n\n/* The following macro returns the number of bytes needed to encode the length\n * for the integer value _l, that is, 1 byte for lengths < ZIPMAP_BIGLEN and\n * 5 bytes for all the other lengths. */\n#define ZIPMAP_LEN_BYTES(_l) (((_l) < ZIPMAP_BIGLEN) ? 1 : sizeof(unsigned int)+1)\n\n/* Create a new empty zipmap. */\nunsigned char *zipmapNew(void) {\n    unsigned char *zm = zmalloc(2);\n\n    zm[0] = 0; /* Length */\n    zm[1] = ZIPMAP_END;\n    return zm;\n}\n\n/* Decode the encoded length pointed by 'p' */\nstatic unsigned int zipmapDecodeLength(unsigned char *p) {\n    unsigned int len = *p;\n\n    if (len < ZIPMAP_BIGLEN) return len;\n    memcpy(&len,p+1,sizeof(unsigned int));\n    memrev32ifbe(&len);\n    return len;\n}\n\n/* Encode the length 'l' writing it in 'p'. If p is NULL it just returns\n * the amount of bytes required to encode such a length. */\nstatic unsigned int zipmapEncodeLength(unsigned char *p, unsigned int len) {\n    if (p == NULL) {\n        return ZIPMAP_LEN_BYTES(len);\n    } else {\n        if (len < ZIPMAP_BIGLEN) {\n            p[0] = len;\n            return 1;\n        } else {\n            p[0] = ZIPMAP_BIGLEN;\n            memcpy(p+1,&len,sizeof(len));\n            memrev32ifbe(p+1);\n            return 1+sizeof(len);\n        }\n    }\n}\n\n/* Search for a matching key, returning a pointer to the entry inside the\n * zipmap. Returns NULL if the key is not found.\n *\n * If NULL is returned, and totlen is not NULL, it is set to the entire\n * size of the zimap, so that the calling function will be able to\n * reallocate the original zipmap to make room for more entries. */\nstatic unsigned char *zipmapLookupRaw(unsigned char *zm, unsigned char *key, unsigned int klen, unsigned int *totlen) {\n    unsigned char *p = zm+1, *k = NULL;\n    unsigned int l,llen;\n\n    while(*p != ZIPMAP_END) {\n        unsigned char free;\n\n        /* Match or skip the key */\n        l = zipmapDecodeLength(p);\n        llen = zipmapEncodeLength(NULL,l);\n        if (key != NULL && k == NULL && l == klen && !memcmp(p+llen,key,l)) {\n            /* Only return when the user doesn't care\n             * for the total length of the zipmap. */\n            if (totlen != NULL) {\n                k = p;\n            } else {\n                return p;\n            }\n        }\n        p += llen+l;\n        /* Skip the value as well */\n        l = zipmapDecodeLength(p);\n        p += zipmapEncodeLength(NULL,l);\n        free = p[0];\n        p += l+1+free; /* +1 to skip the free byte */\n    }\n    if (totlen != NULL) *totlen = (unsigned int)(p-zm)+1;\n    return k;\n}\n\nstatic unsigned long zipmapRequiredLength(unsigned int klen, unsigned int vlen) {\n    unsigned int l;\n\n    l = klen+vlen+3;\n    if (klen >= ZIPMAP_BIGLEN) l += 4;\n    if (vlen >= ZIPMAP_BIGLEN) l += 4;\n    return l;\n}\n\n/* Return the total amount used by a key (encoded length + payload) */\nstatic unsigned int zipmapRawKeyLength(unsigned char *p) {\n    unsigned int l = zipmapDecodeLength(p);\n    return zipmapEncodeLength(NULL,l) + l;\n}\n\n/* Return the total amount used by a value\n * (encoded length + single byte free count + payload) */\nstatic unsigned int zipmapRawValueLength(unsigned char *p) {\n    unsigned int l = zipmapDecodeLength(p);\n    unsigned int used;\n\n    used = zipmapEncodeLength(NULL,l);\n    used += p[used] + 1 + l;\n    return used;\n}\n\n/* If 'p' points to a key, this function returns the total amount of\n * bytes used to store this entry (entry = key + associated value + trailing\n * free space if any). */\nstatic unsigned int zipmapRawEntryLength(unsigned char *p) {\n    unsigned int l = zipmapRawKeyLength(p);\n    return l + zipmapRawValueLength(p+l);\n}\n\nstatic inline unsigned char *zipmapResize(unsigned char *zm, unsigned int len) {\n    zm = zrealloc(zm, len);\n    zm[len-1] = ZIPMAP_END;\n    return zm;\n}\n\n/* Set key to value, creating the key if it does not already exist.\n * If 'update' is not NULL, *update is set to 1 if the key was\n * already preset, otherwise to 0. */\nunsigned char *zipmapSet(unsigned char *zm, unsigned char *key, unsigned int klen, unsigned char *val, unsigned int vlen, int *update) {\n    unsigned int zmlen, offset;\n    unsigned int freelen, reqlen = zipmapRequiredLength(klen,vlen);\n    unsigned int empty, vempty;\n    unsigned char *p;\n\n    freelen = reqlen;\n    if (update) *update = 0;\n    p = zipmapLookupRaw(zm,key,klen,&zmlen);\n    if (p == NULL) {\n        /* Key not found: enlarge */\n        zm = zipmapResize(zm, zmlen+reqlen);\n        p = zm+zmlen-1;\n        zmlen = zmlen+reqlen;\n\n        /* Increase zipmap length (this is an insert) */\n        if (zm[0] < ZIPMAP_BIGLEN) zm[0]++;\n    } else {\n        /* Key found. Is there enough space for the new value? */\n        /* Compute the total length: */\n        if (update) *update = 1;\n        freelen = zipmapRawEntryLength(p);\n        if (freelen < reqlen) {\n            /* Store the offset of this key within the current zipmap, so\n             * it can be resized. Then, move the tail backwards so this\n             * pair fits at the current position. */\n            offset = p-zm;\n            zm = zipmapResize(zm, zmlen-freelen+reqlen);\n            p = zm+offset;\n\n            /* The +1 in the number of bytes to be moved is caused by the\n             * end-of-zipmap byte. Note: the *original* zmlen is used. */\n            memmove(p+reqlen, p+freelen, zmlen-(offset+freelen+1));\n            zmlen = zmlen-freelen+reqlen;\n            freelen = reqlen;\n        }\n    }\n\n    /* We now have a suitable block where the key/value entry can\n     * be written. If there is too much free space, move the tail\n     * of the zipmap a few bytes to the front and shrink the zipmap,\n     * as we want zipmaps to be very space efficient. */\n    empty = freelen-reqlen;\n    if (empty >= ZIPMAP_VALUE_MAX_FREE) {\n        /* First, move the tail <empty> bytes to the front, then resize\n         * the zipmap to be <empty> bytes smaller. */\n        offset = p-zm;\n        memmove(p+reqlen, p+freelen, zmlen-(offset+freelen+1));\n        zmlen -= empty;\n        zm = zipmapResize(zm, zmlen);\n        p = zm+offset;\n        vempty = 0;\n    } else {\n        vempty = empty;\n    }\n\n    /* Just write the key + value and we are done. */\n    /* Key: */\n    p += zipmapEncodeLength(p,klen);\n    memcpy(p,key,klen);\n    p += klen;\n    /* Value: */\n    p += zipmapEncodeLength(p,vlen);\n    *p++ = vempty;\n    memcpy(p,val,vlen);\n    return zm;\n}\n\n/* Remove the specified key. If 'deleted' is not NULL the pointed integer is\n * set to 0 if the key was not found, to 1 if it was found and deleted. */\nunsigned char *zipmapDel(unsigned char *zm, unsigned char *key, unsigned int klen, int *deleted) {\n    unsigned int zmlen, freelen;\n    unsigned char *p = zipmapLookupRaw(zm,key,klen,&zmlen);\n    if (p) {\n        freelen = zipmapRawEntryLength(p);\n        memmove(p, p+freelen, zmlen-((p-zm)+freelen+1));\n        zm = zipmapResize(zm, zmlen-freelen);\n\n        /* Decrease zipmap length */\n        if (zm[0] < ZIPMAP_BIGLEN) zm[0]--;\n\n        if (deleted) *deleted = 1;\n    } else {\n        if (deleted) *deleted = 0;\n    }\n    return zm;\n}\n\n/* Call before iterating through elements via zipmapNext() */\nunsigned char *zipmapRewind(unsigned char *zm) {\n    return zm+1;\n}\n\n/* This function is used to iterate through all the zipmap elements.\n * In the first call the first argument is the pointer to the zipmap + 1.\n * In the next calls what zipmapNext returns is used as first argument.\n * Example:\n *\n * unsigned char *i = zipmapRewind(my_zipmap);\n * while((i = zipmapNext(i,&key,&klen,&value,&vlen)) != NULL) {\n *     printf(\"%d bytes key at $p\\n\", klen, key);\n *     printf(\"%d bytes value at $p\\n\", vlen, value);\n * }\n */\nunsigned char *zipmapNext(unsigned char *zm, unsigned char **key, unsigned int *klen, unsigned char **value, unsigned int *vlen) {\n    if (zm[0] == ZIPMAP_END) return NULL;\n    if (key) {\n        *key = zm;\n        *klen = zipmapDecodeLength(zm);\n        *key += ZIPMAP_LEN_BYTES(*klen);\n    }\n    zm += zipmapRawKeyLength(zm);\n    if (value) {\n        *value = zm+1;\n        *vlen = zipmapDecodeLength(zm);\n        *value += ZIPMAP_LEN_BYTES(*vlen);\n    }\n    zm += zipmapRawValueLength(zm);\n    return zm;\n}\n\n/* Search a key and retrieve the pointer and len of the associated value.\n * If the key is found the function returns 1, otherwise 0. */\nint zipmapGet(unsigned char *zm, unsigned char *key, unsigned int klen, unsigned char **value, unsigned int *vlen) {\n    unsigned char *p;\n\n    if ((p = zipmapLookupRaw(zm,key,klen,NULL)) == NULL) return 0;\n    p += zipmapRawKeyLength(p);\n    *vlen = zipmapDecodeLength(p);\n    *value = p + ZIPMAP_LEN_BYTES(*vlen) + 1;\n    return 1;\n}\n\n/* Return 1 if the key exists, otherwise 0 is returned. */\nint zipmapExists(unsigned char *zm, unsigned char *key, unsigned int klen) {\n    return zipmapLookupRaw(zm,key,klen,NULL) != NULL;\n}\n\n/* Return the number of entries inside a zipmap */\nunsigned int zipmapLen(unsigned char *zm) {\n    unsigned int len = 0;\n    if (zm[0] < ZIPMAP_BIGLEN) {\n        len = zm[0];\n    } else {\n        unsigned char *p = zipmapRewind(zm);\n        while((p = zipmapNext(p,NULL,NULL,NULL,NULL)) != NULL) len++;\n\n        /* Re-store length if small enough */\n        if (len < ZIPMAP_BIGLEN) zm[0] = len;\n    }\n    return len;\n}\n\n/* Return the raw size in bytes of a zipmap, so that we can serialize\n * the zipmap on disk (or everywhere is needed) just writing the returned\n * amount of bytes of the C array starting at the zipmap pointer. */\nsize_t zipmapBlobLen(unsigned char *zm) {\n    unsigned int totlen;\n    zipmapLookupRaw(zm,NULL,0,&totlen);\n    return totlen;\n}\n\n#ifdef ZIPMAP_TEST_MAIN\nvoid zipmapRepr(unsigned char *p) {\n    unsigned int l;\n\n    printf(\"{status %u}\",*p++);\n    while(1) {\n        if (p[0] == ZIPMAP_END) {\n            printf(\"{end}\");\n            break;\n        } else {\n            unsigned char e;\n\n            l = zipmapDecodeLength(p);\n            printf(\"{key %u}\",l);\n            p += zipmapEncodeLength(NULL,l);\n            if (l != 0 && fwrite(p,l,1,stdout) == 0) perror(\"fwrite\");\n            p += l;\n\n            l = zipmapDecodeLength(p);\n            printf(\"{value %u}\",l);\n            p += zipmapEncodeLength(NULL,l);\n            e = *p++;\n            if (l != 0 && fwrite(p,l,1,stdout) == 0) perror(\"fwrite\");\n            p += l+e;\n            if (e) {\n                printf(\"[\");\n                while(e--) printf(\".\");\n                printf(\"]\");\n            }\n        }\n    }\n    printf(\"\\n\");\n}\n\nint main(void) {\n    unsigned char *zm;\n\n    zm = zipmapNew();\n\n    zm = zipmapSet(zm,(unsigned char*) \"name\",4, (unsigned char*) \"foo\",3,NULL);\n    zm = zipmapSet(zm,(unsigned char*) \"surname\",7, (unsigned char*) \"foo\",3,NULL);\n    zm = zipmapSet(zm,(unsigned char*) \"age\",3, (unsigned char*) \"foo\",3,NULL);\n    zipmapRepr(zm);\n\n    zm = zipmapSet(zm,(unsigned char*) \"hello\",5, (unsigned char*) \"world!\",6,NULL);\n    zm = zipmapSet(zm,(unsigned char*) \"foo\",3, (unsigned char*) \"bar\",3,NULL);\n    zm = zipmapSet(zm,(unsigned char*) \"foo\",3, (unsigned char*) \"!\",1,NULL);\n    zipmapRepr(zm);\n    zm = zipmapSet(zm,(unsigned char*) \"foo\",3, (unsigned char*) \"12345\",5,NULL);\n    zipmapRepr(zm);\n    zm = zipmapSet(zm,(unsigned char*) \"new\",3, (unsigned char*) \"xx\",2,NULL);\n    zm = zipmapSet(zm,(unsigned char*) \"noval\",5, (unsigned char*) \"\",0,NULL);\n    zipmapRepr(zm);\n    zm = zipmapDel(zm,(unsigned char*) \"new\",3,NULL);\n    zipmapRepr(zm);\n\n    printf(\"\\nLook up large key:\\n\");\n    {\n        unsigned char buf[512];\n        unsigned char *value;\n        unsigned int vlen, i;\n        for (i = 0; i < 512; i++) buf[i] = 'a';\n\n        zm = zipmapSet(zm,buf,512,(unsigned char*) \"long\",4,NULL);\n        if (zipmapGet(zm,buf,512,&value,&vlen)) {\n            printf(\"  <long key> is associated to the %d bytes value: %.*s\\n\",\n                vlen, vlen, value);\n        }\n    }\n\n    printf(\"\\nPerform a direct lookup:\\n\");\n    {\n        unsigned char *value;\n        unsigned int vlen;\n\n        if (zipmapGet(zm,(unsigned char*) \"foo\",3,&value,&vlen)) {\n            printf(\"  foo is associated to the %d bytes value: %.*s\\n\",\n                vlen, vlen, value);\n        }\n    }\n    printf(\"\\nIterate through elements:\\n\");\n    {\n        unsigned char *i = zipmapRewind(zm);\n        unsigned char *key, *value;\n        unsigned int klen, vlen;\n\n        while((i = zipmapNext(i,&key,&klen,&value,&vlen)) != NULL) {\n            printf(\"  %d:%.*s => %d:%.*s\\n\", klen, klen, key, vlen, vlen, value);\n        }\n    }\n    return 0;\n}\n#endif\n"
  },
  {
    "path": "extern/deprecated/redis-2.8.21/src/zipmap.h",
    "content": "/* String -> String Map data structure optimized for size.\n *\n * See zipmap.c for more info.\n *\n * --------------------------------------------------------------------------\n *\n * Copyright (c) 2009-2010, Salvatore Sanfilippo <antirez at gmail dot com>\n * All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions are met:\n *\n *   * Redistributions of source code must retain the above copyright notice,\n *     this list of conditions and the following disclaimer.\n *   * Redistributions in binary form must reproduce the above copyright\n *     notice, this list of conditions and the following disclaimer in the\n *     documentation and/or other materials provided with the distribution.\n *   * Neither the name of Redis nor the names of its contributors may be used\n *     to endorse or promote products derived from this software without\n *     specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\"\n * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\n * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE\n * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR\n * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF\n * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS\n * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN\n * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)\n * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE\n * POSSIBILITY OF SUCH DAMAGE.\n */\n\n#ifndef _ZIPMAP_H\n#define _ZIPMAP_H\n\nunsigned char *zipmapNew(void);\nunsigned char *zipmapSet(unsigned char *zm, unsigned char *key, unsigned int klen, unsigned char *val, unsigned int vlen, int *update);\nunsigned char *zipmapDel(unsigned char *zm, unsigned char *key, unsigned int klen, int *deleted);\nunsigned char *zipmapRewind(unsigned char *zm);\nunsigned char *zipmapNext(unsigned char *zm, unsigned char **key, unsigned int *klen, unsigned char **value, unsigned int *vlen);\nint zipmapGet(unsigned char *zm, unsigned char *key, unsigned int klen, unsigned char **value, unsigned int *vlen);\nint zipmapExists(unsigned char *zm, unsigned char *key, unsigned int klen);\nunsigned int zipmapLen(unsigned char *zm);\nsize_t zipmapBlobLen(unsigned char *zm);\nvoid zipmapRepr(unsigned char *p);\n\n#endif\n"
  },
  {
    "path": "extern/deprecated/redis-2.8.21/src/zmalloc.c",
    "content": "/* zmalloc - total amount of allocated memory aware version of malloc()\n *\n * Copyright (c) 2009-2010, Salvatore Sanfilippo <antirez at gmail dot com>\n * All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions are met:\n *\n *   * Redistributions of source code must retain the above copyright notice,\n *     this list of conditions and the following disclaimer.\n *   * Redistributions in binary form must reproduce the above copyright\n *     notice, this list of conditions and the following disclaimer in the\n *     documentation and/or other materials provided with the distribution.\n *   * Neither the name of Redis nor the names of its contributors may be used\n *     to endorse or promote products derived from this software without\n *     specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\"\n * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\n * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE\n * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR\n * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF\n * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS\n * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN\n * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)\n * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE\n * POSSIBILITY OF SUCH DAMAGE.\n */\n\n#include <stdio.h>\n#include <stdlib.h>\n\n/* This function provide us access to the original libc free(). This is useful\n * for instance to free results obtained by backtrace_symbols(). We need\n * to define this function before including zmalloc.h that may shadow the\n * free implementation if we use jemalloc or another non standard allocator. */\nvoid zlibc_free(void *ptr) {\n    free(ptr);\n}\n\n#include <string.h>\n#include <pthread.h>\n#include \"config.h\"\n#include \"zmalloc.h\"\n\n#ifdef HAVE_MALLOC_SIZE\n#define PREFIX_SIZE (0)\n#else\n#if defined(__sun) || defined(__sparc) || defined(__sparc__)\n#define PREFIX_SIZE (sizeof(long long))\n#else\n#define PREFIX_SIZE (sizeof(size_t))\n#endif\n#endif\n\n/* Explicitly override malloc/free etc when using tcmalloc. */\n#if defined(USE_TCMALLOC)\n#define malloc(size) tc_malloc(size)\n#define calloc(count,size) tc_calloc(count,size)\n#define realloc(ptr,size) tc_realloc(ptr,size)\n#define free(ptr) tc_free(ptr)\n#elif defined(USE_JEMALLOC)\n#define malloc(size) je_malloc(size)\n#define calloc(count,size) je_calloc(count,size)\n#define realloc(ptr,size) je_realloc(ptr,size)\n#define free(ptr) je_free(ptr)\n#endif\n\n#if defined(__ATOMIC_RELAXED)\n#define update_zmalloc_stat_add(__n) __atomic_add_fetch(&used_memory, (__n), __ATOMIC_RELAXED)\n#define update_zmalloc_stat_sub(__n) __atomic_sub_fetch(&used_memory, (__n), __ATOMIC_RELAXED)\n#elif defined(HAVE_ATOMIC)\n#define update_zmalloc_stat_add(__n) __sync_add_and_fetch(&used_memory, (__n))\n#define update_zmalloc_stat_sub(__n) __sync_sub_and_fetch(&used_memory, (__n))\n#else\n#define update_zmalloc_stat_add(__n) do { \\\n    pthread_mutex_lock(&used_memory_mutex); \\\n    used_memory += (__n); \\\n    pthread_mutex_unlock(&used_memory_mutex); \\\n} while(0)\n\n#define update_zmalloc_stat_sub(__n) do { \\\n    pthread_mutex_lock(&used_memory_mutex); \\\n    used_memory -= (__n); \\\n    pthread_mutex_unlock(&used_memory_mutex); \\\n} while(0)\n\n#endif\n\n#define update_zmalloc_stat_alloc(__n) do { \\\n    size_t _n = (__n); \\\n    if (_n&(sizeof(long)-1)) _n += sizeof(long)-(_n&(sizeof(long)-1)); \\\n    if (zmalloc_thread_safe) { \\\n        update_zmalloc_stat_add(_n); \\\n    } else { \\\n        used_memory += _n; \\\n    } \\\n} while(0)\n\n#define update_zmalloc_stat_free(__n) do { \\\n    size_t _n = (__n); \\\n    if (_n&(sizeof(long)-1)) _n += sizeof(long)-(_n&(sizeof(long)-1)); \\\n    if (zmalloc_thread_safe) { \\\n        update_zmalloc_stat_sub(_n); \\\n    } else { \\\n        used_memory -= _n; \\\n    } \\\n} while(0)\n\nstatic size_t used_memory = 0;\nstatic int zmalloc_thread_safe = 0;\npthread_mutex_t used_memory_mutex = PTHREAD_MUTEX_INITIALIZER;\n\nstatic void zmalloc_default_oom(size_t size) {\n    fprintf(stderr, \"zmalloc: Out of memory trying to allocate %zu bytes\\n\",\n        size);\n    fflush(stderr);\n    abort();\n}\n\nstatic void (*zmalloc_oom_handler)(size_t) = zmalloc_default_oom;\n\nvoid *zmalloc(size_t size) {\n    void *ptr = malloc(size+PREFIX_SIZE);\n\n    if (!ptr) zmalloc_oom_handler(size);\n#ifdef HAVE_MALLOC_SIZE\n    update_zmalloc_stat_alloc(zmalloc_size(ptr));\n    return ptr;\n#else\n    *((size_t*)ptr) = size;\n    update_zmalloc_stat_alloc(size+PREFIX_SIZE);\n    return (char*)ptr+PREFIX_SIZE;\n#endif\n}\n\nvoid *zcalloc(size_t size) {\n    void *ptr = calloc(1, size+PREFIX_SIZE);\n\n    if (!ptr) zmalloc_oom_handler(size);\n#ifdef HAVE_MALLOC_SIZE\n    update_zmalloc_stat_alloc(zmalloc_size(ptr));\n    return ptr;\n#else\n    *((size_t*)ptr) = size;\n    update_zmalloc_stat_alloc(size+PREFIX_SIZE);\n    return (char*)ptr+PREFIX_SIZE;\n#endif\n}\n\nvoid *zrealloc(void *ptr, size_t size) {\n#ifndef HAVE_MALLOC_SIZE\n    void *realptr;\n#endif\n    size_t oldsize;\n    void *newptr;\n\n    if (ptr == NULL) return zmalloc(size);\n#ifdef HAVE_MALLOC_SIZE\n    oldsize = zmalloc_size(ptr);\n    newptr = realloc(ptr,size);\n    if (!newptr) zmalloc_oom_handler(size);\n\n    update_zmalloc_stat_free(oldsize);\n    update_zmalloc_stat_alloc(zmalloc_size(newptr));\n    return newptr;\n#else\n    realptr = (char*)ptr-PREFIX_SIZE;\n    oldsize = *((size_t*)realptr);\n    newptr = realloc(realptr,size+PREFIX_SIZE);\n    if (!newptr) zmalloc_oom_handler(size);\n\n    *((size_t*)newptr) = size;\n    update_zmalloc_stat_free(oldsize);\n    update_zmalloc_stat_alloc(size);\n    return (char*)newptr+PREFIX_SIZE;\n#endif\n}\n\n/* Provide zmalloc_size() for systems where this function is not provided by\n * malloc itself, given that in that case we store a header with this\n * information as the first bytes of every allocation. */\n#ifndef HAVE_MALLOC_SIZE\nsize_t zmalloc_size(void *ptr) {\n    void *realptr = (char*)ptr-PREFIX_SIZE;\n    size_t size = *((size_t*)realptr);\n    /* Assume at least that all the allocations are padded at sizeof(long) by\n     * the underlying allocator. */\n    if (size&(sizeof(long)-1)) size += sizeof(long)-(size&(sizeof(long)-1));\n    return size+PREFIX_SIZE;\n}\n#endif\n\nvoid zfree(void *ptr) {\n#ifndef HAVE_MALLOC_SIZE\n    void *realptr;\n    size_t oldsize;\n#endif\n\n    if (ptr == NULL) return;\n#ifdef HAVE_MALLOC_SIZE\n    update_zmalloc_stat_free(zmalloc_size(ptr));\n    free(ptr);\n#else\n    realptr = (char*)ptr-PREFIX_SIZE;\n    oldsize = *((size_t*)realptr);\n    update_zmalloc_stat_free(oldsize+PREFIX_SIZE);\n    free(realptr);\n#endif\n}\n\nchar *zstrdup(const char *s) {\n    size_t l = strlen(s)+1;\n    char *p = zmalloc(l);\n\n    memcpy(p,s,l);\n    return p;\n}\n\nsize_t zmalloc_used_memory(void) {\n    size_t um;\n\n    if (zmalloc_thread_safe) {\n#if defined(__ATOMIC_RELAXED) || defined(HAVE_ATOMIC)\n        um = update_zmalloc_stat_add(0);\n#else\n        pthread_mutex_lock(&used_memory_mutex);\n        um = used_memory;\n        pthread_mutex_unlock(&used_memory_mutex);\n#endif\n    }\n    else {\n        um = used_memory;\n    }\n\n    return um;\n}\n\nvoid zmalloc_enable_thread_safeness(void) {\n    zmalloc_thread_safe = 1;\n}\n\nvoid zmalloc_set_oom_handler(void (*oom_handler)(size_t)) {\n    zmalloc_oom_handler = oom_handler;\n}\n\n/* Get the RSS information in an OS-specific way.\n *\n * WARNING: the function zmalloc_get_rss() is not designed to be fast\n * and may not be called in the busy loops where Redis tries to release\n * memory expiring or swapping out objects.\n *\n * For this kind of \"fast RSS reporting\" usages use instead the\n * function RedisEstimateRSS() that is a much faster (and less precise)\n * version of the function. */\n\n#if defined(HAVE_PROC_STAT)\n#include <unistd.h>\n#include <sys/types.h>\n#include <sys/stat.h>\n#include <fcntl.h>\n\nsize_t zmalloc_get_rss(void) {\n    int page = sysconf(_SC_PAGESIZE);\n    size_t rss;\n    char buf[4096];\n    char filename[256];\n    int fd, count;\n    char *p, *x;\n\n    snprintf(filename,256,\"/proc/%d/stat\",getpid());\n    if ((fd = open(filename,O_RDONLY)) == -1) return 0;\n    if (read(fd,buf,4096) <= 0) {\n        close(fd);\n        return 0;\n    }\n    close(fd);\n\n    p = buf;\n    count = 23; /* RSS is the 24th field in /proc/<pid>/stat */\n    while(p && count--) {\n        p = strchr(p,' ');\n        if (p) p++;\n    }\n    if (!p) return 0;\n    x = strchr(p,' ');\n    if (!x) return 0;\n    *x = '\\0';\n\n    rss = strtoll(p,NULL,10);\n    rss *= page;\n    return rss;\n}\n#elif defined(HAVE_TASKINFO)\n#include <unistd.h>\n#include <stdio.h>\n#include <stdlib.h>\n#include <sys/types.h>\n#include <sys/sysctl.h>\n#include <mach/task.h>\n#include <mach/mach_init.h>\n\nsize_t zmalloc_get_rss(void) {\n    task_t task = MACH_PORT_NULL;\n    struct task_basic_info t_info;\n    mach_msg_type_number_t t_info_count = TASK_BASIC_INFO_COUNT;\n\n    if (task_for_pid(current_task(), getpid(), &task) != KERN_SUCCESS)\n        return 0;\n    task_info(task, TASK_BASIC_INFO, (task_info_t)&t_info, &t_info_count);\n\n    return t_info.resident_size;\n}\n#else\nsize_t zmalloc_get_rss(void) {\n    /* If we can't get the RSS in an OS-specific way for this system just\n     * return the memory usage we estimated in zmalloc()..\n     *\n     * Fragmentation will appear to be always 1 (no fragmentation)\n     * of course... */\n    return zmalloc_used_memory();\n}\n#endif\n\n/* Fragmentation = RSS / allocated-bytes */\nfloat zmalloc_get_fragmentation_ratio(size_t rss) {\n    return (float)rss/zmalloc_used_memory();\n}\n\n/* Get the sum of the specified field (converted form kb to bytes) in\n * /proc/self/smaps. The field must be specified with trailing \":\" as it\n * apperas in the smaps output.\n *\n * Example: zmalloc_get_smap_bytes_by_field(\"Rss:\");\n */\n#if defined(HAVE_PROC_SMAPS)\nsize_t zmalloc_get_smap_bytes_by_field(char *field) {\n    char line[1024];\n    size_t bytes = 0;\n    FILE *fp = fopen(\"/proc/self/smaps\",\"r\");\n    int flen = strlen(field);\n\n    if (!fp) return 0;\n    while(fgets(line,sizeof(line),fp) != NULL) {\n        if (strncmp(line,field,flen) == 0) {\n            char *p = strchr(line,'k');\n            if (p) {\n                *p = '\\0';\n                bytes += strtol(line+flen,NULL,10) * 1024;\n            }\n        }\n    }\n    fclose(fp);\n    return bytes;\n}\n#else\nsize_t zmalloc_get_smap_bytes_by_field(char *field) {\n    ((void) field);\n    return 0;\n}\n#endif\n\nsize_t zmalloc_get_private_dirty(void) {\n    return zmalloc_get_smap_bytes_by_field(\"Private_Dirty:\");\n}\n"
  },
  {
    "path": "extern/deprecated/redis-2.8.21/src/zmalloc.h",
    "content": "/* zmalloc - total amount of allocated memory aware version of malloc()\n *\n * Copyright (c) 2009-2010, Salvatore Sanfilippo <antirez at gmail dot com>\n * All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions are met:\n *\n *   * Redistributions of source code must retain the above copyright notice,\n *     this list of conditions and the following disclaimer.\n *   * Redistributions in binary form must reproduce the above copyright\n *     notice, this list of conditions and the following disclaimer in the\n *     documentation and/or other materials provided with the distribution.\n *   * Neither the name of Redis nor the names of its contributors may be used\n *     to endorse or promote products derived from this software without\n *     specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\"\n * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\n * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE\n * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR\n * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF\n * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS\n * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN\n * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)\n * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE\n * POSSIBILITY OF SUCH DAMAGE.\n */\n\n#ifndef __ZMALLOC_H\n#define __ZMALLOC_H\n\n/* Double expansion needed for stringification of macro values. */\n#define __xstr(s) __str(s)\n#define __str(s) #s\n\n#if defined(USE_TCMALLOC)\n#define ZMALLOC_LIB (\"tcmalloc-\" __xstr(TC_VERSION_MAJOR) \".\" __xstr(TC_VERSION_MINOR))\n#include <google/tcmalloc.h>\n#if (TC_VERSION_MAJOR == 1 && TC_VERSION_MINOR >= 6) || (TC_VERSION_MAJOR > 1)\n#define HAVE_MALLOC_SIZE 1\n#define zmalloc_size(p) tc_malloc_size(p)\n#else\n#error \"Newer version of tcmalloc required\"\n#endif\n\n#elif defined(USE_JEMALLOC)\n#define ZMALLOC_LIB (\"jemalloc-\" __xstr(JEMALLOC_VERSION_MAJOR) \".\" __xstr(JEMALLOC_VERSION_MINOR) \".\" __xstr(JEMALLOC_VERSION_BUGFIX))\n#include <jemalloc/jemalloc.h>\n#if (JEMALLOC_VERSION_MAJOR == 2 && JEMALLOC_VERSION_MINOR >= 1) || (JEMALLOC_VERSION_MAJOR > 2)\n#define HAVE_MALLOC_SIZE 1\n#define zmalloc_size(p) je_malloc_usable_size(p)\n#else\n#error \"Newer version of jemalloc required\"\n#endif\n\n#elif defined(__APPLE__)\n#include <malloc/malloc.h>\n#define HAVE_MALLOC_SIZE 1\n#define zmalloc_size(p) malloc_size(p)\n#endif\n\n#ifndef ZMALLOC_LIB\n#define ZMALLOC_LIB \"libc\"\n#endif\n\nvoid *zmalloc(size_t size);\nvoid *zcalloc(size_t size);\nvoid *zrealloc(void *ptr, size_t size);\nvoid zfree(void *ptr);\nchar *zstrdup(const char *s);\nsize_t zmalloc_used_memory(void);\nvoid zmalloc_enable_thread_safeness(void);\nvoid zmalloc_set_oom_handler(void (*oom_handler)(size_t));\nfloat zmalloc_get_fragmentation_ratio(size_t rss);\nsize_t zmalloc_get_rss(void);\nsize_t zmalloc_get_private_dirty(void);\nsize_t zmalloc_get_smap_bytes_by_field(char *field);\nvoid zlibc_free(void *ptr);\n\n#ifndef HAVE_MALLOC_SIZE\nsize_t zmalloc_size(void *ptr);\n#endif\n\n#endif /* __ZMALLOC_H */\n"
  },
  {
    "path": "extern/deprecated/redis-2.8.21/tests/assets/default.conf",
    "content": "# Redis configuration for testing.\n\nnotify-keyspace-events KEA\ndaemonize no\npidfile /var/run/redis.pid\nport 6379\ntimeout 0\nbind 127.0.0.1\nloglevel verbose\nlogfile ''\ndatabases 16\nlatency-monitor-threshold 1\n\nsave 900 1\nsave 300 10\nsave 60 10000\n\nrdbcompression yes\ndbfilename dump.rdb\ndir ./\n\nslave-serve-stale-data yes\nappendonly no\nappendfsync everysec\nno-appendfsync-on-rewrite no\nactiverehashing yes\n"
  },
  {
    "path": "extern/deprecated/redis-2.8.21/tests/helpers/bg_complex_data.tcl",
    "content": "source tests/support/redis.tcl\nsource tests/support/util.tcl\n\nproc bg_complex_data {host port db ops} {\n    set r [redis $host $port]\n    $r select $db\n    createComplexDataset $r $ops\n}\n\nbg_complex_data [lindex $argv 0] [lindex $argv 1] [lindex $argv 2] [lindex $argv 3]\n"
  },
  {
    "path": "extern/deprecated/redis-2.8.21/tests/helpers/gen_write_load.tcl",
    "content": "source tests/support/redis.tcl\n\nproc gen_write_load {host port seconds} {\n    set start_time [clock seconds]\n    set r [redis $host $port 1]\n    $r select 9\n    while 1 {\n        $r set [expr rand()] [expr rand()]\n        if {[clock seconds]-$start_time > $seconds} {\n            exit 0\n        }\n    }\n}\n\ngen_write_load [lindex $argv 0] [lindex $argv 1] [lindex $argv 2]\n"
  },
  {
    "path": "extern/deprecated/redis-2.8.21/tests/instances.tcl",
    "content": "# Multi-instance test framework.\n# This is used in order to test Sentinel and Redis Cluster, and provides\n# basic capabilities for spawning and handling N parallel Redis / Sentinel\n# instances.\n#\n# Copyright (C) 2014 Salvatore Sanfilippo antirez@gmail.com\n# This software is released under the BSD License. See the COPYING file for\n# more information.\n\npackage require Tcl 8.5\n\nset tcl_precision 17\nsource ../support/redis.tcl\nsource ../support/util.tcl\nsource ../support/server.tcl\nsource ../support/test.tcl\n\nset ::verbose 0\nset ::pause_on_error 0\nset ::simulate_error 0\nset ::sentinel_instances {}\nset ::redis_instances {}\nset ::sentinel_base_port 20000\nset ::redis_base_port 30000\nset ::pids {} ; # We kill everything at exit\nset ::dirs {} ; # We remove all the temp dirs at exit\nset ::run_matching {} ; # If non empty, only tests matching pattern are run.\n\nif {[catch {cd tmp}]} {\n    puts \"tmp directory not found.\"\n    puts \"Please run this test from the Redis source root.\"\n    exit 1\n}\n\n# Spawn a redis or sentinel instance, depending on 'type'.\nproc spawn_instance {type base_port count {conf {}}} {\n    for {set j 0} {$j < $count} {incr j} {\n        set port [find_available_port $base_port]\n        incr base_port\n        puts \"Starting $type #$j at port $port\"\n\n        # Create a directory for this instance.\n        set dirname \"${type}_${j}\"\n        lappend ::dirs $dirname\n        catch {exec rm -rf $dirname}\n        file mkdir $dirname\n\n        # Write the instance config file.\n        set cfgfile [file join $dirname $type.conf]\n        set cfg [open $cfgfile w]\n        puts $cfg \"port $port\"\n        puts $cfg \"dir ./$dirname\"\n        puts $cfg \"logfile log.txt\"\n        # Add additional config files\n        foreach directive $conf {\n            puts $cfg $directive\n        }\n        close $cfg\n\n        # Finally exec it and remember the pid for later cleanup.\n        if {$type eq \"redis\"} {\n            set prgname redis-server\n        } elseif {$type eq \"sentinel\"} {\n            set prgname redis-sentinel\n        } else {\n            error \"Unknown instance type.\"\n        }\n        set pid [exec ../../../src/${prgname} $cfgfile &]\n        lappend ::pids $pid\n\n        # Check availability\n        if {[server_is_up 127.0.0.1 $port 100] == 0} {\n            abort_sentinel_test \"Problems starting $type #$j: ping timeout\"\n        }\n\n        # Push the instance into the right list\n        set link [redis 127.0.0.1 $port]\n        $link reconnect 1\n        lappend ::${type}_instances [list \\\n            pid $pid \\\n            host 127.0.0.1 \\\n            port $port \\\n            link $link \\\n        ]\n    }\n}\n\nproc cleanup {} {\n    puts \"Cleaning up...\"\n    foreach pid $::pids {\n        catch {exec kill -9 $pid}\n    }\n    foreach dir $::dirs {\n        catch {exec rm -rf $dir}\n    }\n}\n\nproc abort_sentinel_test msg {\n    puts \"WARNING: Aborting the test.\"\n    puts \">>>>>>>> $msg\"\n    cleanup\n    exit 1\n}\n\nproc parse_options {} {\n    for {set j 0} {$j < [llength $::argv]} {incr j} {\n        set opt [lindex $::argv $j]\n        set val [lindex $::argv [expr $j+1]]\n        if {$opt eq \"--single\"} {\n            incr j\n            set ::run_matching \"*${val}*\"\n        } elseif {$opt eq \"--pause-on-error\"} {\n            set ::pause_on_error 1\n        } elseif {$opt eq \"--fail\"} {\n            set ::simulate_error 1\n        } elseif {$opt eq \"--help\"} {\n            puts \"Hello, I'm sentinel.tcl and I run Sentinel unit tests.\"\n            puts \"\\nOptions:\"\n            puts \"--single <pattern>      Only runs tests specified by pattern.\"\n            puts \"--pause-on-error        Pause for manual inspection on error.\"\n            puts \"--fail                  Simulate a test failure.\"\n            puts \"--help                  Shows this help.\"\n            exit 0\n        } else {\n            puts \"Unknown option $opt\"\n            exit 1\n        }\n    }\n}\n\n# If --pause-on-error option was passed at startup this function is called\n# on error in order to give the developer a chance to understand more about\n# the error condition while the instances are still running.\nproc pause_on_error {} {\n    puts \"\"\n    puts [colorstr yellow \"*** Please inspect the error now ***\"]\n    puts \"\\nType \\\"continue\\\" to resume the test, \\\"help\\\" for help screen.\\n\"\n    while 1 {\n        puts -nonewline \"> \"\n        flush stdout\n        set line [gets stdin]\n        set argv [split $line \" \"]\n        set cmd [lindex $argv 0]\n        if {$cmd eq {continue}} {\n            break\n        } elseif {$cmd eq {show-redis-logs}} {\n            set count 10\n            if {[lindex $argv 1] ne {}} {set count [lindex $argv 1]}\n            foreach_redis_id id {\n                puts \"=== REDIS $id ====\"\n                puts [exec tail -$count redis_$id/log.txt]\n                puts \"---------------------\\n\"\n            }\n        } elseif {$cmd eq {show-sentinel-logs}} {\n            set count 10\n            if {[lindex $argv 1] ne {}} {set count [lindex $argv 1]}\n            foreach_sentinel_id id {\n                puts \"=== SENTINEL $id ====\"\n                puts [exec tail -$count sentinel_$id/log.txt]\n                puts \"---------------------\\n\"\n            }\n        } elseif {$cmd eq {ls}} {\n            foreach_redis_id id {\n                puts -nonewline \"Redis $id\"\n                set errcode [catch {\n                    set str {}\n                    append str \"@[RI $id tcp_port]: \"\n                    append str \"[RI $id role] \"\n                    if {[RI $id role] eq {slave}} {\n                        append str \"[RI $id master_host]:[RI $id master_port]\"\n                    }\n                    set str\n                } retval]\n                if {$errcode} {\n                    puts \" -- $retval\"\n                } else {\n                    puts $retval\n                }\n            }\n            foreach_sentinel_id id {\n                puts -nonewline \"Sentinel $id\"\n                set errcode [catch {\n                    set str {}\n                    append str \"@[SI $id tcp_port]: \"\n                    append str \"[join [S $id sentinel get-master-addr-by-name mymaster]]\"\n                    set str\n                } retval]\n                if {$errcode} {\n                    puts \" -- $retval\"\n                } else {\n                    puts $retval\n                }\n            }\n        } elseif {$cmd eq {help}} {\n            puts \"ls                     List Sentinel and Redis instances.\"\n            puts \"show-sentinel-logs \\[N\\] Show latest N lines of logs.\"\n            puts \"show-redis-logs \\[N\\]    Show latest N lines of logs.\"\n            puts \"S <id> cmd ... arg     Call command in Sentinel <id>.\"\n            puts \"R <id> cmd ... arg     Call command in Redis <id>.\"\n            puts \"SI <id> <field>        Show Sentinel <id> INFO <field>.\"\n            puts \"RI <id> <field>        Show Sentinel <id> INFO <field>.\"\n            puts \"continue               Resume test.\"\n        } else {\n            set errcode [catch {eval $line} retval]\n            if {$retval ne {}} {puts \"$retval\"}\n        }\n    }\n}\n\n# We redefine 'test' as for Sentinel we don't use the server-client\n# architecture for the test, everything is sequential.\nproc test {descr code} {\n    set ts [clock format [clock seconds] -format %H:%M:%S]\n    puts -nonewline \"$ts> $descr: \"\n    flush stdout\n\n    if {[catch {set retval [uplevel 1 $code]} error]} {\n        if {[string match \"assertion:*\" $error]} {\n            set msg [string range $error 10 end]\n            puts [colorstr red $msg]\n            if {$::pause_on_error} pause_on_error\n            puts \"(Jumping to next unit after error)\"\n            return -code continue\n        } else {\n            # Re-raise, let handler up the stack take care of this.\n            error $error $::errorInfo\n        }\n    } else {\n        puts [colorstr green OK]\n    }\n}\n\nproc run_tests {} {\n    set tests [lsort [glob ../tests/*]]\n    foreach test $tests {\n        if {$::run_matching ne {} && [string match $::run_matching $test] == 0} {\n            continue\n        }\n        if {[file isdirectory $test]} continue\n        puts [colorstr yellow \"Testing unit: [lindex [file split $test] end]\"]\n        source $test\n    }\n}\n\n# The \"S\" command is used to interact with the N-th Sentinel.\n# The general form is:\n#\n# S <sentinel-id> command arg arg arg ...\n#\n# Example to ping the Sentinel 0 (first instance): S 0 PING\nproc S {n args} {\n    set s [lindex $::sentinel_instances $n]\n    [dict get $s link] {*}$args\n}\n\n# Like R but to chat with Redis instances.\nproc R {n args} {\n    set r [lindex $::redis_instances $n]\n    [dict get $r link] {*}$args\n}\n\nproc get_info_field {info field} {\n    set fl [string length $field]\n    append field :\n    foreach line [split $info \"\\n\"] {\n        set line [string trim $line \"\\r\\n \"]\n        if {[string range $line 0 $fl] eq $field} {\n            return [string range $line [expr {$fl+1}] end]\n        }\n    }\n    return {}\n}\n\nproc SI {n field} {\n    get_info_field [S $n info] $field\n}\n\nproc RI {n field} {\n    get_info_field [R $n info] $field\n}\n\n# Iterate over IDs of sentinel or redis instances.\nproc foreach_instance_id {instances idvar code} {\n    upvar 1 $idvar id\n    for {set id 0} {$id < [llength $instances]} {incr id} {\n        set errcode [catch {uplevel 1 $code} result]\n        if {$errcode == 1} {\n            error $result $::errorInfo $::errorCode\n        } elseif {$errcode == 4} {\n            continue\n        } elseif {$errcode == 3} {\n            break\n        } elseif {$errcode != 0} {\n            return -code $errcode $result\n        }\n    }\n}\n\nproc foreach_sentinel_id {idvar code} {\n    set errcode [catch {uplevel 1 [list foreach_instance_id $::sentinel_instances $idvar $code]} result]\n    return -code $errcode $result\n}\n\nproc foreach_redis_id {idvar code} {\n    set errcode [catch {uplevel 1 [list foreach_instance_id $::redis_instances $idvar $code]} result]\n    return -code $errcode $result\n}\n\n# Get the specific attribute of the specified instance type, id.\nproc get_instance_attrib {type id attrib} {\n    dict get [lindex [set ::${type}_instances] $id] $attrib\n}\n\n# Set the specific attribute of the specified instance type, id.\nproc set_instance_attrib {type id attrib newval} {\n    set d [lindex [set ::${type}_instances] $id]\n    dict set d $attrib $newval\n    lset ::${type}_instances $id $d\n}\n\n# Create a master-slave cluster of the given number of total instances.\n# The first instance \"0\" is the master, all others are configured as\n# slaves.\nproc create_redis_master_slave_cluster n {\n    foreach_redis_id id {\n        if {$id == 0} {\n            # Our master.\n            R $id slaveof no one\n            R $id flushall\n        } elseif {$id < $n} {\n            R $id slaveof [get_instance_attrib redis 0 host] \\\n                          [get_instance_attrib redis 0 port]\n        } else {\n            # Instances not part of the cluster.\n            R $id slaveof no one\n        }\n    }\n    # Wait for all the slaves to sync.\n    wait_for_condition 1000 50 {\n        [RI 0 connected_slaves] == ($n-1)\n    } else {\n        fail \"Unable to create a master-slaves cluster.\"\n    }\n}\n\nproc get_instance_id_by_port {type port} {\n    foreach_${type}_id id {\n        if {[get_instance_attrib $type $id port] == $port} {\n            return $id\n        }\n    }\n    fail \"Instance $type port $port not found.\"\n}\n\n# Kill an instance of the specified type/id with SIGKILL.\n# This function will mark the instance PID as -1 to remember that this instance\n# is no longer running and will remove its PID from the list of pids that\n# we kill at cleanup.\n#\n# The instance can be restarted with restart-instance.\nproc kill_instance {type id} {\n    set pid [get_instance_attrib $type $id pid]\n    if {$pid == -1} {\n        error \"You tried to kill $type $id twice.\"\n    }\n    exec kill -9 $pid\n    set_instance_attrib $type $id pid -1\n    set_instance_attrib $type $id link you_tried_to_talk_with_killed_instance\n\n    # Remove the PID from the list of pids to kill at exit.\n    set ::pids [lsearch -all -inline -not -exact $::pids $pid]\n}\n\n# Return true of the instance of the specified type/id is killed.\nproc instance_is_killed {type id} {\n    set pid [get_instance_attrib $type $id pid]\n    expr {$pid == -1}\n}\n\n# Restart an instance previously killed by kill_instance\nproc restart_instance {type id} {\n    set dirname \"${type}_${id}\"\n    set cfgfile [file join $dirname $type.conf]\n    set port [get_instance_attrib $type $id port]\n\n    # Execute the instance with its old setup and append the new pid\n    # file for cleanup.\n    if {$type eq \"redis\"} {\n        set prgname redis-server\n    } else {\n        set prgname redis-sentinel\n    }\n    set pid [exec ../../../src/${prgname} $cfgfile &]\n    set_instance_attrib $type $id pid $pid\n    lappend ::pids $pid\n\n    # Check that the instance is running\n    if {[server_is_up 127.0.0.1 $port 100] == 0} {\n        abort_sentinel_test \"Problems starting $type #$id: ping timeout\"\n    }\n\n    # Connect with it with a fresh link\n    set link [redis 127.0.0.1 $port]\n    $link reconnect 1\n    set_instance_attrib $type $id link $link\n}\n\n"
  },
  {
    "path": "extern/deprecated/redis-2.8.21/tests/integration/aof-race.tcl",
    "content": "set defaults { appendonly {yes} appendfilename {appendonly.aof} }\nset server_path [tmpdir server.aof]\nset aof_path \"$server_path/appendonly.aof\"\n\nproc start_server_aof {overrides code} {\n    upvar defaults defaults srv srv server_path server_path\n    set config [concat $defaults $overrides]\n    start_server [list overrides $config] $code\n}\n\ntags {\"aof\"} {\n    # Specific test for a regression where internal buffers were not properly\n    # cleaned after a child responsible for an AOF rewrite exited. This buffer\n    # was subsequently appended to the new AOF, resulting in duplicate commands.\n    start_server_aof [list dir $server_path] {\n        set client [redis [srv host] [srv port]]\n        set bench [open \"|src/redis-benchmark -q -p [srv port] -c 20 -n 20000 incr foo\" \"r+\"]\n        after 100\n\n        # Benchmark should be running by now: start background rewrite\n        $client bgrewriteaof\n\n        # Read until benchmark pipe reaches EOF\n        while {[string length [read $bench]] > 0} {}\n\n        # Check contents of foo\n        assert_equal 20000 [$client get foo]\n    }\n\n    # Restart server to replay AOF\n    start_server_aof [list dir $server_path] {\n        set client [redis [srv host] [srv port]]\n        assert_equal 20000 [$client get foo]\n    }\n}\n"
  },
  {
    "path": "extern/deprecated/redis-2.8.21/tests/integration/aof.tcl",
    "content": "set defaults { appendonly {yes} appendfilename {appendonly.aof} }\nset server_path [tmpdir server.aof]\nset aof_path \"$server_path/appendonly.aof\"\n\nproc append_to_aof {str} {\n    upvar fp fp\n    puts -nonewline $fp $str\n}\n\nproc create_aof {code} {\n    upvar fp fp aof_path aof_path\n    set fp [open $aof_path w+]\n    uplevel 1 $code\n    close $fp\n}\n\nproc start_server_aof {overrides code} {\n    upvar defaults defaults srv srv server_path server_path\n    set config [concat $defaults $overrides]\n    set srv [start_server [list overrides $config]]\n    uplevel 1 $code\n    kill_server $srv\n}\n\ntags {\"aof\"} {\n    ## Server can start when aof-load-truncated is set to yes and AOF\n    ## is truncated, with an incomplete MULTI block.\n    create_aof {\n        append_to_aof [formatCommand set foo hello]\n        append_to_aof [formatCommand multi]\n        append_to_aof [formatCommand set bar world]\n    }\n\n    start_server_aof [list dir $server_path aof-load-truncated yes] {\n        test \"Unfinished MULTI: Server should start if load-truncated is yes\" {\n            assert_equal 1 [is_alive $srv]\n        }\n    }\n\n    ## Should also start with truncated AOF without incomplete MULTI block.\n    create_aof {\n        append_to_aof [formatCommand incr foo]\n        append_to_aof [formatCommand incr foo]\n        append_to_aof [formatCommand incr foo]\n        append_to_aof [formatCommand incr foo]\n        append_to_aof [formatCommand incr foo]\n        append_to_aof [string range [formatCommand incr foo] 0 end-1]\n    }\n\n    start_server_aof [list dir $server_path aof-load-truncated yes] {\n        test \"Short read: Server should start if load-truncated is yes\" {\n            assert_equal 1 [is_alive $srv]\n        }\n\n        set client [redis [dict get $srv host] [dict get $srv port]]\n\n        test \"Truncated AOF loaded: we expect foo to be equal to 5\" {\n            assert {[$client get foo] eq \"5\"}\n        }\n\n        test \"Append a new command after loading an incomplete AOF\" {\n            $client incr foo\n        }\n    }\n\n    # Now the AOF file is expected to be correct\n    start_server_aof [list dir $server_path aof-load-truncated yes] {\n        test \"Short read + command: Server should start\" {\n            assert_equal 1 [is_alive $srv]\n        }\n\n        set client [redis [dict get $srv host] [dict get $srv port]]\n\n        test \"Truncated AOF loaded: we expect foo to be equal to 6 now\" {\n            assert {[$client get foo] eq \"6\"}\n        }\n    }\n\n    ## Test that the server exits when the AOF contains a format error\n    create_aof {\n        append_to_aof [formatCommand set foo hello]\n        append_to_aof \"!!!\"\n        append_to_aof [formatCommand set foo hello]\n    }\n\n    start_server_aof [list dir $server_path aof-load-truncated yes] {\n        test \"Bad format: Server should have logged an error\" {\n            set pattern \"*Bad file format reading the append only file*\"\n            set retry 10\n            while {$retry} {\n                set result [exec tail -n1 < [dict get $srv stdout]]\n                if {[string match $pattern $result]} {\n                    break\n                }\n                incr retry -1\n                after 1000\n            }\n            if {$retry == 0} {\n                error \"assertion:expected error not found on config file\"\n            }\n        }\n    }\n\n    ## Test the server doesn't start when the AOF contains an unfinished MULTI\n    create_aof {\n        append_to_aof [formatCommand set foo hello]\n        append_to_aof [formatCommand multi]\n        append_to_aof [formatCommand set bar world]\n    }\n\n    start_server_aof [list dir $server_path aof-load-truncated no] {\n        test \"Unfinished MULTI: Server should have logged an error\" {\n            set pattern \"*Unexpected end of file reading the append only file*\"\n            set retry 10\n            while {$retry} {\n                set result [exec tail -n1 < [dict get $srv stdout]]\n                if {[string match $pattern $result]} {\n                    break\n                }\n                incr retry -1\n                after 1000\n            }\n            if {$retry == 0} {\n                error \"assertion:expected error not found on config file\"\n            }\n        }\n    }\n\n    ## Test that the server exits when the AOF contains a short read\n    create_aof {\n        append_to_aof [formatCommand set foo hello]\n        append_to_aof [string range [formatCommand set bar world] 0 end-1]\n    }\n\n    start_server_aof [list dir $server_path aof-load-truncated no] {\n        test \"Short read: Server should have logged an error\" {\n            set pattern \"*Unexpected end of file reading the append only file*\"\n            set retry 10\n            while {$retry} {\n                set result [exec tail -n1 < [dict get $srv stdout]]\n                if {[string match $pattern $result]} {\n                    break\n                }\n                incr retry -1\n                after 1000\n            }\n            if {$retry == 0} {\n                error \"assertion:expected error not found on config file\"\n            }\n        }\n    }\n\n    ## Test that redis-check-aof indeed sees this AOF is not valid\n    test \"Short read: Utility should confirm the AOF is not valid\" {\n        catch {\n            exec src/redis-check-aof $aof_path\n        } result\n        assert_match \"*not valid*\" $result\n    }\n\n    test \"Short read: Utility should be able to fix the AOF\" {\n        set result [exec src/redis-check-aof --fix $aof_path << \"y\\n\"]\n        assert_match \"*Successfully truncated AOF*\" $result\n    }\n\n    ## Test that the server can be started using the truncated AOF\n    start_server_aof [list dir $server_path aof-load-truncated no] {\n        test \"Fixed AOF: Server should have been started\" {\n            assert_equal 1 [is_alive $srv]\n        }\n\n        test \"Fixed AOF: Keyspace should contain values that were parseable\" {\n            set client [redis [dict get $srv host] [dict get $srv port]]\n            wait_for_condition 50 100 {\n                [catch {$client ping} e] == 0\n            } else {\n                fail \"Loading DB is taking too much time.\"\n            }\n            assert_equal \"hello\" [$client get foo]\n            assert_equal \"\" [$client get bar]\n        }\n    }\n\n    ## Test that SPOP (that modifies the client's argc/argv) is correctly free'd\n    create_aof {\n        append_to_aof [formatCommand sadd set foo]\n        append_to_aof [formatCommand sadd set bar]\n        append_to_aof [formatCommand spop set]\n    }\n\n    start_server_aof [list dir $server_path aof-load-truncated no] {\n        test \"AOF+SPOP: Server should have been started\" {\n            assert_equal 1 [is_alive $srv]\n        }\n\n        test \"AOF+SPOP: Set should have 1 member\" {\n            set client [redis [dict get $srv host] [dict get $srv port]]\n            wait_for_condition 50 100 {\n                [catch {$client ping} e] == 0\n            } else {\n                fail \"Loading DB is taking too much time.\"\n            }\n            assert_equal 1 [$client scard set]\n        }\n    }\n\n    ## Test that EXPIREAT is loaded correctly\n    create_aof {\n        append_to_aof [formatCommand rpush list foo]\n        append_to_aof [formatCommand expireat list 1000]\n        append_to_aof [formatCommand rpush list bar]\n    }\n\n    start_server_aof [list dir $server_path aof-load-truncated no] {\n        test \"AOF+EXPIRE: Server should have been started\" {\n            assert_equal 1 [is_alive $srv]\n        }\n\n        test \"AOF+EXPIRE: List should be empty\" {\n            set client [redis [dict get $srv host] [dict get $srv port]]\n            wait_for_condition 50 100 {\n                [catch {$client ping} e] == 0\n            } else {\n                fail \"Loading DB is taking too much time.\"\n            }\n            assert_equal 0 [$client llen list]\n        }\n    }\n\n    start_server {overrides {appendonly {yes} appendfilename {appendonly.aof}}} {\n        test {Redis should not try to convert DEL into EXPIREAT for EXPIRE -1} {\n            r set x 10\n            r expire x -1\n        }\n    }\n}\n"
  },
  {
    "path": "extern/deprecated/redis-2.8.21/tests/integration/convert-zipmap-hash-on-load.tcl",
    "content": "# Copy RDB with zipmap encoded hash to server path\nset server_path [tmpdir \"server.convert-zipmap-hash-on-load\"]\n\nexec cp -f tests/assets/hash-zipmap.rdb $server_path\nstart_server [list overrides [list \"dir\" $server_path \"dbfilename\" \"hash-zipmap.rdb\"]] {\n  test \"RDB load zipmap hash: converts to ziplist\" {\n    r select 0\n\n    assert_match \"*ziplist*\" [r debug object hash]\n    assert_equal 2 [r hlen hash]\n    assert_match {v1 v2} [r hmget hash f1 f2]\n  }\n}\n\nexec cp -f tests/assets/hash-zipmap.rdb $server_path\nstart_server [list overrides [list \"dir\" $server_path \"dbfilename\" \"hash-zipmap.rdb\" \"hash-max-ziplist-entries\" 1]] {\n  test \"RDB load zipmap hash: converts to hash table when hash-max-ziplist-entries is exceeded\" {\n    r select 0\n\n    assert_match \"*hashtable*\" [r debug object hash]\n    assert_equal 2 [r hlen hash]\n    assert_match {v1 v2} [r hmget hash f1 f2]\n  }\n}\n\nexec cp -f tests/assets/hash-zipmap.rdb $server_path\nstart_server [list overrides [list \"dir\" $server_path \"dbfilename\" \"hash-zipmap.rdb\" \"hash-max-ziplist-value\" 1]] {\n  test \"RDB load zipmap hash: converts to hash table when hash-max-ziplist-value is exceeded\" {\n    r select 0\n\n    assert_match \"*hashtable*\" [r debug object hash]\n    assert_equal 2 [r hlen hash]\n    assert_match {v1 v2} [r hmget hash f1 f2]\n  }\n}\n"
  },
  {
    "path": "extern/deprecated/redis-2.8.21/tests/integration/rdb.tcl",
    "content": "set server_path [tmpdir \"server.rdb-encoding-test\"]\n\n# Copy RDB with different encodings in server path\nexec cp tests/assets/encodings.rdb $server_path\n\nstart_server [list overrides [list \"dir\" $server_path \"dbfilename\" \"encodings.rdb\"]] {\n  test \"RDB encoding loading test\" {\n    r select 0\n    csvdump r\n  } {\"compressible\",\"string\",\"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\"\n\"hash\",\"hash\",\"a\",\"1\",\"aa\",\"10\",\"aaa\",\"100\",\"b\",\"2\",\"bb\",\"20\",\"bbb\",\"200\",\"c\",\"3\",\"cc\",\"30\",\"ccc\",\"300\",\"ddd\",\"400\",\"eee\",\"5000000000\",\n\"hash_zipped\",\"hash\",\"a\",\"1\",\"b\",\"2\",\"c\",\"3\",\n\"list\",\"list\",\"1\",\"2\",\"3\",\"a\",\"b\",\"c\",\"100000\",\"6000000000\",\"1\",\"2\",\"3\",\"a\",\"b\",\"c\",\"100000\",\"6000000000\",\"1\",\"2\",\"3\",\"a\",\"b\",\"c\",\"100000\",\"6000000000\",\n\"list_zipped\",\"list\",\"1\",\"2\",\"3\",\"a\",\"b\",\"c\",\"100000\",\"6000000000\",\n\"number\",\"string\",\"10\"\n\"set\",\"set\",\"1\",\"100000\",\"2\",\"3\",\"6000000000\",\"a\",\"b\",\"c\",\n\"set_zipped_1\",\"set\",\"1\",\"2\",\"3\",\"4\",\n\"set_zipped_2\",\"set\",\"100000\",\"200000\",\"300000\",\"400000\",\n\"set_zipped_3\",\"set\",\"1000000000\",\"2000000000\",\"3000000000\",\"4000000000\",\"5000000000\",\"6000000000\",\n\"string\",\"string\",\"Hello World\"\n\"zset\",\"zset\",\"a\",\"1\",\"b\",\"2\",\"c\",\"3\",\"aa\",\"10\",\"bb\",\"20\",\"cc\",\"30\",\"aaa\",\"100\",\"bbb\",\"200\",\"ccc\",\"300\",\"aaaa\",\"1000\",\"cccc\",\"123456789\",\"bbbb\",\"5000000000\",\n\"zset_zipped\",\"zset\",\"a\",\"1\",\"b\",\"2\",\"c\",\"3\",\n}\n}\n\nset server_path [tmpdir \"server.rdb-startup-test\"]\n\nstart_server [list overrides [list \"dir\" $server_path]] {\n    test {Server started empty with non-existing RDB file} {\n        r debug digest\n    } {0000000000000000000000000000000000000000}\n    # Save an RDB file, needed for the next test.\n    r save\n}\n\nstart_server [list overrides [list \"dir\" $server_path]] {\n    test {Server started empty with empty RDB file} {\n        r debug digest\n    } {0000000000000000000000000000000000000000}\n}\n\n# Helper function to start a server and kill it, just to check the error\n# logged.\nset defaults {}\nproc start_server_and_kill_it {overrides code} {\n    upvar defaults defaults srv srv server_path server_path\n    set config [concat $defaults $overrides]\n    set srv [start_server [list overrides $config]]\n    uplevel 1 $code\n    kill_server $srv\n}\n\n# Make the RDB file unreadable\nfile attributes [file join $server_path dump.rdb] -permissions 0222\n\n# Detect root account (it is able to read the file even with 002 perm)\nset isroot 0\ncatch {\n    open [file join $server_path dump.rdb]\n    set isroot 1\n}\n\n# Now make sure the server aborted with an error\nif {!$isroot} {\n    start_server_and_kill_it [list \"dir\" $server_path] {\n        test {Server should not start if RDB file can't be open} {\n            wait_for_condition 50 100 {\n                [string match {*Fatal error loading*} \\\n                    [exec tail -n1 < [dict get $srv stdout]]]\n            } else {\n                fail \"Server started even if RDB was unreadable!\"\n            }\n        }\n    }\n}\n\n# Fix permissions of the RDB file.\nfile attributes [file join $server_path dump.rdb] -permissions 0666\n\n# Corrupt its CRC64 checksum.\nset filesize [file size [file join $server_path dump.rdb]]\nset fd [open [file join $server_path dump.rdb] r+]\nfconfigure $fd -translation binary\nseek $fd -8 end\nputs -nonewline $fd \"foobar00\"; # Corrupt the checksum\nclose $fd\n\n# Now make sure the server aborted with an error\nstart_server_and_kill_it [list \"dir\" $server_path] {\n    test {Server should not start if RDB is corrupted} {\n        wait_for_condition 50 100 {\n            [string match {*RDB checksum*} \\\n                [exec tail -n1 < [dict get $srv stdout]]]\n        } else {\n            fail \"Server started even if RDB was corrupted!\"\n        }\n    }\n}\n"
  },
  {
    "path": "extern/deprecated/redis-2.8.21/tests/integration/redis-cli.tcl",
    "content": "start_server {tags {\"cli\"}} {\n    proc open_cli {} {\n        set ::env(TERM) dumb\n        set fd [open [format \"|src/redis-cli -p %d -n 9\" [srv port]] \"r+\"]\n        fconfigure $fd -buffering none\n        fconfigure $fd -blocking false\n        fconfigure $fd -translation binary\n        assert_equal \"redis> \" [read_cli $fd]\n        set _ $fd\n    }\n\n    proc close_cli {fd} {\n        close $fd\n    }\n\n    proc read_cli {fd} {\n        set buf [read $fd]\n        while {[string length $buf] == 0} {\n            # wait some time and try again\n            after 10\n            set buf [read $fd]\n        }\n        set _ $buf\n    }\n\n    proc write_cli {fd buf} {\n        puts $fd $buf\n        flush $fd\n    }\n\n    # Helpers to run tests in interactive mode\n    proc run_command {fd cmd} {\n        write_cli $fd $cmd\n        set lines [split [read_cli $fd] \"\\n\"]\n        assert_equal \"redis> \" [lindex $lines end]\n        join [lrange $lines 0 end-1] \"\\n\"\n    }\n\n    proc test_interactive_cli {name code} {\n        set ::env(FAKETTY) 1\n        set fd [open_cli]\n        test \"Interactive CLI: $name\" $code\n        close_cli $fd\n        unset ::env(FAKETTY)\n    }\n\n    # Helpers to run tests where stdout is not a tty\n    proc write_tmpfile {contents} {\n        set tmp [tmpfile \"cli\"]\n        set tmpfd [open $tmp \"w\"]\n        puts -nonewline $tmpfd $contents\n        close $tmpfd\n        set _ $tmp\n    }\n\n    proc _run_cli {opts args} {\n        set cmd [format \"src/redis-cli -p %d -n 9 $args\" [srv port]]\n        foreach {key value} $opts {\n            if {$key eq \"pipe\"} {\n                set cmd \"sh -c \\\"$value | $cmd\\\"\"\n            }\n            if {$key eq \"path\"} {\n                set cmd \"$cmd < $value\"\n            }\n        }\n\n        set fd [open \"|$cmd\" \"r\"]\n        fconfigure $fd -buffering none\n        fconfigure $fd -translation binary\n        set resp [read $fd 1048576]\n        close $fd\n        set _ $resp\n    }\n\n    proc run_cli {args} {\n        _run_cli {} {*}$args\n    }\n\n    proc run_cli_with_input_pipe {cmd args} {\n        _run_cli [list pipe $cmd] {*}$args\n    }\n\n    proc run_cli_with_input_file {path args} {\n        _run_cli [list path $path] {*}$args\n    }\n\n    proc test_nontty_cli {name code} {\n        test \"Non-interactive non-TTY CLI: $name\" $code\n    }\n\n    # Helpers to run tests where stdout is a tty (fake it)\n    proc test_tty_cli {name code} {\n        set ::env(FAKETTY) 1\n        test \"Non-interactive TTY CLI: $name\" $code\n        unset ::env(FAKETTY)\n    }\n\n    test_interactive_cli \"INFO response should be printed raw\" {\n        set lines [split [run_command $fd info] \"\\n\"]\n        foreach line $lines {\n            assert [regexp {^[a-z0-9_]+:[a-z0-9_]+} $line]\n        }\n    }\n\n    test_interactive_cli \"Status reply\" {\n        assert_equal \"OK\" [run_command $fd \"set key foo\"]\n    }\n\n    test_interactive_cli \"Integer reply\" {\n        assert_equal \"(integer) 1\" [run_command $fd \"incr counter\"]\n    }\n\n    test_interactive_cli \"Bulk reply\" {\n        r set key foo\n        assert_equal \"\\\"foo\\\"\" [run_command $fd \"get key\"]\n    }\n\n    test_interactive_cli \"Multi-bulk reply\" {\n        r rpush list foo\n        r rpush list bar\n        assert_equal \"1. \\\"foo\\\"\\n2. \\\"bar\\\"\" [run_command $fd \"lrange list 0 -1\"]\n    }\n\n    test_interactive_cli \"Parsing quotes\" {\n        assert_equal \"OK\" [run_command $fd \"set key \\\"bar\\\"\"]\n        assert_equal \"bar\" [r get key]\n        assert_equal \"OK\" [run_command $fd \"set key \\\" bar \\\"\"]\n        assert_equal \" bar \" [r get key]\n        assert_equal \"OK\" [run_command $fd \"set key \\\"\\\\\\\"bar\\\\\\\"\\\"\"]\n        assert_equal \"\\\"bar\\\"\" [r get key]\n        assert_equal \"OK\" [run_command $fd \"set key \\\"\\tbar\\t\\\"\"]\n        assert_equal \"\\tbar\\t\" [r get key]\n\n        # invalid quotation\n        assert_equal \"Invalid argument(s)\" [run_command $fd \"get \\\"\\\"key\"]\n        assert_equal \"Invalid argument(s)\" [run_command $fd \"get \\\"key\\\"x\"]\n\n        # quotes after the argument are weird, but should be allowed\n        assert_equal \"OK\" [run_command $fd \"set key\\\"\\\" bar\"]\n        assert_equal \"bar\" [r get key]\n    }\n\n    test_tty_cli \"Status reply\" {\n        assert_equal \"OK\\n\" [run_cli set key bar]\n        assert_equal \"bar\" [r get key]\n    }\n\n    test_tty_cli \"Integer reply\" {\n        r del counter\n        assert_equal \"(integer) 1\\n\" [run_cli incr counter]\n    }\n\n    test_tty_cli \"Bulk reply\" {\n        r set key \"tab\\tnewline\\n\"\n        assert_equal \"\\\"tab\\\\tnewline\\\\n\\\"\\n\" [run_cli get key]\n    }\n\n    test_tty_cli \"Multi-bulk reply\" {\n        r del list\n        r rpush list foo\n        r rpush list bar\n        assert_equal \"1. \\\"foo\\\"\\n2. \\\"bar\\\"\\n\" [run_cli lrange list 0 -1]\n    }\n\n    test_tty_cli \"Read last argument from pipe\" {\n        assert_equal \"OK\\n\" [run_cli_with_input_pipe \"echo foo\" set key]\n        assert_equal \"foo\\n\" [r get key]\n    }\n\n    test_tty_cli \"Read last argument from file\" {\n        set tmpfile [write_tmpfile \"from file\"]\n        assert_equal \"OK\\n\" [run_cli_with_input_file $tmpfile set key]\n        assert_equal \"from file\" [r get key]\n    }\n\n    test_nontty_cli \"Status reply\" {\n        assert_equal \"OK\" [run_cli set key bar]\n        assert_equal \"bar\" [r get key]\n    }\n\n    test_nontty_cli \"Integer reply\" {\n        r del counter\n        assert_equal \"1\" [run_cli incr counter]\n    }\n\n    test_nontty_cli \"Bulk reply\" {\n        r set key \"tab\\tnewline\\n\"\n        assert_equal \"tab\\tnewline\\n\" [run_cli get key]\n    }\n\n    test_nontty_cli \"Multi-bulk reply\" {\n        r del list\n        r rpush list foo\n        r rpush list bar\n        assert_equal \"foo\\nbar\" [run_cli lrange list 0 -1]\n    }\n\n    test_nontty_cli \"Read last argument from pipe\" {\n        assert_equal \"OK\" [run_cli_with_input_pipe \"echo foo\" set key]\n        assert_equal \"foo\\n\" [r get key]\n    }\n\n    test_nontty_cli \"Read last argument from file\" {\n        set tmpfile [write_tmpfile \"from file\"]\n        assert_equal \"OK\" [run_cli_with_input_file $tmpfile set key]\n        assert_equal \"from file\" [r get key]\n    }\n}\n"
  },
  {
    "path": "extern/deprecated/redis-2.8.21/tests/integration/replication-2.tcl",
    "content": "start_server {tags {\"repl\"}} {\n    start_server {} {\n        test {First server should have role slave after SLAVEOF} {\n            r -1 slaveof [srv 0 host] [srv 0 port]\n            after 1000\n            s -1 role\n        } {slave}\n\n        test {If min-slaves-to-write is honored, write is accepted} {\n            r config set min-slaves-to-write 1\n            r config set min-slaves-max-lag 10\n            r set foo 12345\n            wait_for_condition 50 100 {\n                [r -1 get foo] eq {12345}\n            } else {\n                fail \"Write did not reached slave\"\n            }\n        }\n\n        test {No write if min-slaves-to-write is < attached slaves} {\n            r config set min-slaves-to-write 2\n            r config set min-slaves-max-lag 10\n            catch {r set foo 12345} err\n            set err\n        } {NOREPLICAS*}\n\n        test {If min-slaves-to-write is honored, write is accepted (again)} {\n            r config set min-slaves-to-write 1\n            r config set min-slaves-max-lag 10\n            r set foo 12345\n            wait_for_condition 50 100 {\n                [r -1 get foo] eq {12345}\n            } else {\n                fail \"Write did not reached slave\"\n            }\n        }\n\n        test {No write if min-slaves-max-lag is > of the slave lag} {\n            r -1 deferred 1\n            r config set min-slaves-to-write 1\n            r config set min-slaves-max-lag 2\n            r -1 debug sleep 6\n            assert {[r set foo 12345] eq {OK}}\n            after 4000\n            catch {r set foo 12345} err\n            assert {[r -1 read] eq {OK}}\n            r -1 deferred 0\n            set err\n        } {NOREPLICAS*}\n\n        test {min-slaves-to-write is ignored by slaves} {\n            r config set min-slaves-to-write 1\n            r config set min-slaves-max-lag 10\n            r -1 config set min-slaves-to-write 1\n            r -1 config set min-slaves-max-lag 10\n            r set foo aaabbb\n            wait_for_condition 50 100 {\n                [r -1 get foo] eq {aaabbb}\n            } else {\n                fail \"Write did not reached slave\"\n            }\n        }\n\n        # Fix parameters for the next test to work\n        r config set min-slaves-to-write 0\n        r -1 config set min-slaves-to-write 0\n        r flushall\n\n        test {MASTER and SLAVE dataset should be identical after complex ops} {\n            createComplexDataset r 10000\n            after 500\n            if {[r debug digest] ne [r -1 debug digest]} {\n                set csv1 [csvdump r]\n                set csv2 [csvdump {r -1}]\n                set fd [open /tmp/repldump1.txt w]\n                puts -nonewline $fd $csv1\n                close $fd\n                set fd [open /tmp/repldump2.txt w]\n                puts -nonewline $fd $csv2\n                close $fd\n                puts \"Master - Slave inconsistency\"\n                puts \"Run diff -u against /tmp/repldump*.txt for more info\"\n            }\n            assert_equal [r debug digest] [r -1 debug digest]\n        }\n    }\n}\n"
  },
  {
    "path": "extern/deprecated/redis-2.8.21/tests/integration/replication-3.tcl",
    "content": "start_server {tags {\"repl\"}} {\n    start_server {} {\n        test {First server should have role slave after SLAVEOF} {\n            r -1 slaveof [srv 0 host] [srv 0 port]\n            wait_for_condition 50 100 {\n                [s -1 master_link_status] eq {up}\n            } else {\n                fail \"Replication not started.\"\n            }\n        }\n\n        if {$::accurate} {set numops 50000} else {set numops 5000}\n\n        test {MASTER and SLAVE consistency with expire} {\n            createComplexDataset r $numops useexpire\n            after 4000 ;# Make sure everything expired before taking the digest\n            r keys *   ;# Force DEL syntesizing to slave\n            after 1000 ;# Wait another second. Now everything should be fine.\n            if {[r debug digest] ne [r -1 debug digest]} {\n                set csv1 [csvdump r]\n                set csv2 [csvdump {r -1}]\n                set fd [open /tmp/repldump1.txt w]\n                puts -nonewline $fd $csv1\n                close $fd\n                set fd [open /tmp/repldump2.txt w]\n                puts -nonewline $fd $csv2\n                close $fd\n                puts \"Master - Slave inconsistency\"\n                puts \"Run diff -u against /tmp/repldump*.txt for more info\"\n            }\n            assert_equal [r debug digest] [r -1 debug digest]\n        }\n    }\n}\n\nstart_server {tags {\"repl\"}} {\n    start_server {} {\n        test {First server should have role slave after SLAVEOF} {\n            r -1 slaveof [srv 0 host] [srv 0 port]\n            wait_for_condition 50 100 {\n                [s -1 master_link_status] eq {up}\n            } else {\n                fail \"Replication not started.\"\n            }\n        }\n\n        set numops 20000 ;# Enough to trigger the Script Cache LRU eviction.\n\n        # While we are at it, enable AOF to test it will be consistent as well\n        # after the test.\n        r config set appendonly yes\n\n        test {MASTER and SLAVE consistency with EVALSHA replication} {\n            array set oldsha {}\n            for {set j 0} {$j < $numops} {incr j} {\n                set key \"key:$j\"\n                # Make sure to create scripts that have different SHA1s\n                set script \"return redis.call('incr','$key')\"\n                set sha1 [r eval \"return redis.sha1hex(\\\"$script\\\")\" 0]\n                set oldsha($j) $sha1\n                r eval $script 0\n                set res [r evalsha $sha1 0]\n                assert {$res == 2}\n                # Additionally call one of the old scripts as well, at random.\n                set res [r evalsha $oldsha([randomInt $j]) 0]\n                assert {$res > 2}\n\n                # Trigger an AOF rewrite while we are half-way, this also\n                # forces the flush of the script cache, and we will cover\n                # more code as a result.\n                if {$j == $numops / 2} {\n                    catch {r bgrewriteaof}\n                }\n            }\n\n            wait_for_condition 50 100 {\n                [r dbsize] == $numops &&\n                [r -1 dbsize] == $numops &&\n                [r debug digest] eq [r -1 debug digest]\n            } else {\n                set csv1 [csvdump r]\n                set csv2 [csvdump {r -1}]\n                set fd [open /tmp/repldump1.txt w]\n                puts -nonewline $fd $csv1\n                close $fd\n                set fd [open /tmp/repldump2.txt w]\n                puts -nonewline $fd $csv2\n                close $fd\n                puts \"Master - Slave inconsistency\"\n                puts \"Run diff -u against /tmp/repldump*.txt for more info\"\n\n            }\n\n            set old_digest [r debug digest]\n            r config set appendonly no\n            r debug loadaof\n            set new_digest [r debug digest]\n            assert {$old_digest eq $new_digest}\n        }\n    }\n}\n"
  },
  {
    "path": "extern/deprecated/redis-2.8.21/tests/integration/replication-4.tcl",
    "content": "proc start_bg_complex_data {host port db ops} {\n    set tclsh [info nameofexecutable]\n    exec $tclsh tests/helpers/bg_complex_data.tcl $host $port $db $ops &\n}\n\nproc stop_bg_complex_data {handle} {\n    catch {exec /bin/kill -9 $handle}\n}\n\nstart_server {tags {\"repl\"}} {\n    start_server {} {\n\n        set master [srv -1 client]\n        set master_host [srv -1 host]\n        set master_port [srv -1 port]\n        set slave [srv 0 client]\n\n        set load_handle0 [start_bg_complex_data $master_host $master_port 9 100000]\n        set load_handle1 [start_bg_complex_data $master_host $master_port 11 100000]\n        set load_handle2 [start_bg_complex_data $master_host $master_port 12 100000]\n\n        test {First server should have role slave after SLAVEOF} {\n            $slave slaveof $master_host $master_port\n            after 1000\n            s 0 role\n        } {slave}\n\n        test {Test replication with parallel clients writing in differnet DBs} {\n            after 5000\n            stop_bg_complex_data $load_handle0\n            stop_bg_complex_data $load_handle1\n            stop_bg_complex_data $load_handle2\n            set retry 10\n            while {$retry && ([$master debug digest] ne [$slave debug digest])}\\\n            {\n                after 1000\n                incr retry -1\n            }\n            assert {[$master dbsize] > 0}\n\n            if {[$master debug digest] ne [$slave debug digest]} {\n                set csv1 [csvdump r]\n                set csv2 [csvdump {r -1}]\n                set fd [open /tmp/repldump1.txt w]\n                puts -nonewline $fd $csv1\n                close $fd\n                set fd [open /tmp/repldump2.txt w]\n                puts -nonewline $fd $csv2\n                close $fd\n                puts \"Master - Slave inconsistency\"\n                puts \"Run diff -u against /tmp/repldump*.txt for more info\"\n            }\n            assert_equal [r debug digest] [r -1 debug digest]\n        }\n    }\n}\n\nstart_server {tags {\"repl\"}} {\n    start_server {} {\n        set master [srv -1 client]\n        set master_host [srv -1 host]\n        set master_port [srv -1 port]\n        set slave [srv 0 client]\n\n        test {First server should have role slave after SLAVEOF} {\n            $slave slaveof $master_host $master_port\n            wait_for_condition 50 100 {\n                [s 0 master_link_status] eq {up}\n            } else {\n                fail \"Replication not started.\"\n            }\n        }\n\n        test {With min-slaves-to-write (1,3): master should be writable} {\n            $master config set min-slaves-max-lag 3\n            $master config set min-slaves-to-write 1\n            $master set foo bar\n        } {OK}\n\n        test {With min-slaves-to-write (2,3): master should not be writable} {\n            $master config set min-slaves-max-lag 3\n            $master config set min-slaves-to-write 2\n            catch {$master set foo bar} e\n            set e\n        } {NOREPLICAS*}\n\n        test {With min-slaves-to-write: master not writable with lagged slave} {\n            $master config set min-slaves-max-lag 2\n            $master config set min-slaves-to-write 1\n            assert {[$master set foo bar] eq {OK}}\n            $slave deferred 1\n            $slave debug sleep 6\n            after 4000\n            catch {$master set foo bar} e\n            set e\n        } {NOREPLICAS*}\n    }\n}\n\nstart_server {tags {\"repl\"}} {\n    start_server {} {\n        set master [srv -1 client]\n        set master_host [srv -1 host]\n        set master_port [srv -1 port]\n        set slave [srv 0 client]\n\n        test {First server should have role slave after SLAVEOF} {\n            $slave slaveof $master_host $master_port\n            wait_for_condition 50 100 {\n                [s 0 role] eq {slave}\n            } else {\n                fail \"Replication not started.\"\n            }\n        }\n\n        test {Replication: commands with many arguments (issue #1221)} {\n            # We now issue large MSET commands, that may trigger a specific\n            # class of bugs, see issue #1221.\n            for {set j 0} {$j < 100} {incr j} {\n                set cmd [list mset]\n                for {set x 0} {$x < 1000} {incr x} {\n                    lappend cmd [randomKey] [randomValue]\n                }\n                $master {*}$cmd\n            }\n\n            set retry 10\n            while {$retry && ([$master debug digest] ne [$slave debug digest])}\\\n            {\n                after 1000\n                incr retry -1\n            }\n            assert {[$master dbsize] > 0}\n        }\n    }\n}\n"
  },
  {
    "path": "extern/deprecated/redis-2.8.21/tests/integration/replication-psync.tcl",
    "content": "proc start_bg_complex_data {host port db ops} {\n    set tclsh [info nameofexecutable]\n    exec $tclsh tests/helpers/bg_complex_data.tcl $host $port $db $ops &\n}\n\nproc stop_bg_complex_data {handle} {\n    catch {exec /bin/kill -9 $handle}\n}\n\n# Creates a master-slave pair and breaks the link continuously to force\n# partial resyncs attempts, all this while flooding the master with\n# write queries.\n#\n# You can specifiy backlog size, ttl, delay before reconnection, test duration\n# in seconds, and an additional condition to verify at the end.\nproc test_psync {descr duration backlog_size backlog_ttl delay cond} {\n    start_server {tags {\"repl\"}} {\n        start_server {} {\n\n            set master [srv -1 client]\n            set master_host [srv -1 host]\n            set master_port [srv -1 port]\n            set slave [srv 0 client]\n\n            $master config set repl-backlog-size $backlog_size\n            $master config set repl-backlog-ttl $backlog_ttl\n\n            set load_handle0 [start_bg_complex_data $master_host $master_port 9 100000]\n            set load_handle1 [start_bg_complex_data $master_host $master_port 11 100000]\n            set load_handle2 [start_bg_complex_data $master_host $master_port 12 100000]\n\n            test {Slave should be able to synchronize with the master} {\n                $slave slaveof $master_host $master_port\n                wait_for_condition 50 100 {\n                    [lindex [r role] 0] eq {slave} &&\n                    [lindex [r role] 3] eq {connected}\n                } else {\n                    fail \"Replication not started.\"\n                }\n            }\n\n            # Check that the background clients are actually writing.\n            test {Detect write load to master} {\n                wait_for_condition 50 100 {\n                    [$master dbsize] > 100\n                } else {\n                    fail \"Can't detect write load from background clients.\"\n                }\n            }\n\n            test \"Test replication partial resync: $descr\" {\n                # Now while the clients are writing data, break the maste-slave\n                # link multiple times.\n                for {set j 0} {$j < $duration*10} {incr j} {\n                    after 100\n                    # catch {puts \"MASTER [$master dbsize] keys, SLAVE [$slave dbsize] keys\"}\n\n                    if {($j % 20) == 0} {\n                        catch {\n                            if {$delay} {\n                                $slave multi\n                                $slave client kill $master_host:$master_port\n                                $slave debug sleep $delay\n                                $slave exec\n                            } else {\n                                $slave client kill $master_host:$master_port\n                            }\n                        }\n                    }\n                }\n                stop_bg_complex_data $load_handle0\n                stop_bg_complex_data $load_handle1\n                stop_bg_complex_data $load_handle2\n                set retry 10\n                while {$retry && ([$master debug digest] ne [$slave debug digest])}\\\n                {\n                    after 1000\n                    incr retry -1\n                }\n                assert {[$master dbsize] > 0}\n\n                if {[$master debug digest] ne [$slave debug digest]} {\n                    set csv1 [csvdump r]\n                    set csv2 [csvdump {r -1}]\n                    set fd [open /tmp/repldump1.txt w]\n                    puts -nonewline $fd $csv1\n                    close $fd\n                    set fd [open /tmp/repldump2.txt w]\n                    puts -nonewline $fd $csv2\n                    close $fd\n                    puts \"Master - Slave inconsistency\"\n                    puts \"Run diff -u against /tmp/repldump*.txt for more info\"\n                }\n                assert_equal [r debug digest] [r -1 debug digest]\n                eval $cond\n            }\n        }\n    }\n}\n\ntest_psync {ok psync} 6 1000000 3600 0 {\n    assert {[s -1 sync_partial_ok] > 0}\n}\n\ntest_psync {no backlog} 6 100 3600 0.5 {\n    assert {[s -1 sync_partial_err] > 0}\n}\n\ntest_psync {ok after delay} 3 100000000 3600 3 {\n    assert {[s -1 sync_partial_ok] > 0}\n}\n\ntest_psync {backlog expired} 3 100000000 1 3 {\n    assert {[s -1 sync_partial_err] > 0}\n}\n"
  },
  {
    "path": "extern/deprecated/redis-2.8.21/tests/integration/replication.tcl",
    "content": "start_server {tags {\"repl\"}} {\n    set A [srv 0 client]\n    set A_host [srv 0 host]\n    set A_port [srv 0 port]\n    start_server {} {\n        set B [srv 0 client]\n        set B_host [srv 0 host]\n        set B_port [srv 0 port]\n\n        test {Set instance A as slave of B} {\n            $A slaveof $B_host $B_port\n            wait_for_condition 50 100 {\n                [lindex [$A role] 0] eq {slave} &&\n                [string match {*master_link_status:up*} [$A info replication]]\n            } else {\n                fail \"Can't turn the instance into a slave\"\n            }\n        }\n\n        test {BRPOPLPUSH replication, when blocking against empty list} {\n            set rd [redis_deferring_client]\n            $rd brpoplpush a b 5\n            r lpush a foo\n            wait_for_condition 50 100 {\n                [$A debug digest] eq [$B debug digest]\n            } else {\n                fail \"Master and slave have different digest: [$A debug digest] VS [$B debug digest]\"\n            }\n        }\n\n        test {BRPOPLPUSH replication, list exists} {\n            set rd [redis_deferring_client]\n            r lpush c 1\n            r lpush c 2\n            r lpush c 3\n            $rd brpoplpush c d 5\n            after 1000\n            assert_equal [$A debug digest] [$B debug digest]\n        }\n\n        test {BLPOP followed by role change, issue #2473} {\n            set rd [redis_deferring_client]\n            $rd blpop foo 0 ; # Block while B is a master\n\n            # Turn B into master of A\n            $A slaveof no one\n            $B slaveof $A_host $A_port\n            wait_for_condition 50 100 {\n                [lindex [$B role] 0] eq {slave} &&\n                [string match {*master_link_status:up*} [$B info replication]]\n            } else {\n                fail \"Can't turn the instance into a slave\"\n            }\n\n            # Push elements into the \"foo\" list of the new slave.\n            # If the client is still attached to the instance, we'll get\n            # a desync between the two instances.\n            $A rpush foo a b c\n            after 100\n\n            wait_for_condition 50 100 {\n                [$A debug digest] eq [$B debug digest] &&\n                [$A lrange foo 0 -1] eq {a b c} &&\n                [$B lrange foo 0 -1] eq {a b c}\n            } else {\n                fail \"Master and slave have different digest: [$A debug digest] VS [$B debug digest]\"\n            }\n        }\n    }\n}\n\nstart_server {tags {\"repl\"}} {\n    r set mykey foo\n\n    start_server {} {\n        test {Second server should have role master at first} {\n            s role\n        } {master}\n\n        test {SLAVEOF should start with link status \"down\"} {\n            r slaveof [srv -1 host] [srv -1 port]\n            s master_link_status\n        } {down}\n\n        test {The role should immediately be changed to \"slave\"} {\n            s role\n        } {slave}\n\n        wait_for_sync r\n        test {Sync should have transferred keys from master} {\n            r get mykey\n        } {foo}\n\n        test {The link status should be up} {\n            s master_link_status\n        } {up}\n\n        test {SET on the master should immediately propagate} {\n            r -1 set mykey bar\n\n            wait_for_condition 500 100 {\n                [r  0 get mykey] eq {bar}\n            } else {\n                fail \"SET on master did not propagated on slave\"\n            }\n        }\n\n        test {FLUSHALL should replicate} {\n            r -1 flushall\n            if {$::valgrind} {after 2000}\n            list [r -1 dbsize] [r 0 dbsize]\n        } {0 0}\n\n        test {ROLE in master reports master with a slave} {\n            set res [r -1 role]\n            lassign $res role offset slaves\n            assert {$role eq {master}}\n            assert {$offset > 0}\n            assert {[llength $slaves] == 1}\n            lassign [lindex $slaves 0] master_host master_port slave_offset\n            assert {$slave_offset <= $offset}\n        }\n\n        test {ROLE in slave reports slave in connected state} {\n            set res [r role]\n            lassign $res role master_host master_port slave_state slave_offset\n            assert {$role eq {slave}}\n            assert {$slave_state eq {connected}}\n        }\n    }\n}\n\nforeach dl {no yes} {\n    start_server {tags {\"repl\"}} {\n        set master [srv 0 client]\n        $master config set repl-diskless-sync $dl\n        set master_host [srv 0 host]\n        set master_port [srv 0 port]\n        set slaves {}\n        set load_handle0 [start_write_load $master_host $master_port 3]\n        set load_handle1 [start_write_load $master_host $master_port 5]\n        set load_handle2 [start_write_load $master_host $master_port 20]\n        set load_handle3 [start_write_load $master_host $master_port 8]\n        set load_handle4 [start_write_load $master_host $master_port 4]\n        start_server {} {\n            lappend slaves [srv 0 client]\n            start_server {} {\n                lappend slaves [srv 0 client]\n                start_server {} {\n                    lappend slaves [srv 0 client]\n                    test \"Connect multiple slaves at the same time (issue #141), diskless=$dl\" {\n                        # Send SLAVEOF commands to slaves\n                        [lindex $slaves 0] slaveof $master_host $master_port\n                        [lindex $slaves 1] slaveof $master_host $master_port\n                        [lindex $slaves 2] slaveof $master_host $master_port\n\n                        # Wait for all the three slaves to reach the \"online\"\n                        # state from the POV of the master.\n                        set retry 500\n                        while {$retry} {\n                            set info [r -3 info]\n                            if {[string match {*slave0:*state=online*slave1:*state=online*slave2:*state=online*} $info]} {\n                                break\n                            } else {\n                                incr retry -1\n                                after 100\n                            }\n                        }\n                        if {$retry == 0} {\n                            error \"assertion:Slaves not correctly synchronized\"\n                        }\n\n                        # Wait that slaves acknowledge they are online so\n                        # we are sure that DBSIZE and DEBUG DIGEST will not\n                        # fail because of timing issues.\n                        wait_for_condition 500 100 {\n                            [lindex [[lindex $slaves 0] role] 3] eq {connected} &&\n                            [lindex [[lindex $slaves 1] role] 3] eq {connected} &&\n                            [lindex [[lindex $slaves 2] role] 3] eq {connected}\n                        } else {\n                            fail \"Slaves still not connected after some time\"\n                        }\n\n                        # Stop the write load\n                        stop_write_load $load_handle0\n                        stop_write_load $load_handle1\n                        stop_write_load $load_handle2\n                        stop_write_load $load_handle3\n                        stop_write_load $load_handle4\n\n                        # Make sure that slaves and master have same\n                        # number of keys\n                        wait_for_condition 500 100 {\n                            [$master dbsize] == [[lindex $slaves 0] dbsize] &&\n                            [$master dbsize] == [[lindex $slaves 1] dbsize] &&\n                            [$master dbsize] == [[lindex $slaves 2] dbsize]\n                        } else {\n                            fail \"Different number of keys between masted and slave after too long time.\"\n                        }\n\n                        # Check digests\n                        set digest [$master debug digest]\n                        set digest0 [[lindex $slaves 0] debug digest]\n                        set digest1 [[lindex $slaves 1] debug digest]\n                        set digest2 [[lindex $slaves 2] debug digest]\n                        assert {$digest ne 0000000000000000000000000000000000000000}\n                        assert {$digest eq $digest0}\n                        assert {$digest eq $digest1}\n                        assert {$digest eq $digest2}\n                    }\n               }\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "extern/deprecated/redis-2.8.21/tests/sentinel/run.tcl",
    "content": "# Sentinel test suite. Copyright (C) 2014 Salvatore Sanfilippo antirez@gmail.com\n# This software is released under the BSD License. See the COPYING file for\n# more information.\n\ncd tests/sentinel\nsource ../instances.tcl\n\nset ::instances_count 5 ; # How many instances we use at max.\n\nproc main {} {\n    parse_options\n    spawn_instance sentinel $::sentinel_base_port $::instances_count\n    spawn_instance redis $::redis_base_port $::instances_count\n    run_tests\n    cleanup\n}\n\nif {[catch main e]} {\n    puts $::errorInfo\n    cleanup\n    exit 1\n}\n"
  },
  {
    "path": "extern/deprecated/redis-2.8.21/tests/sentinel/tests/00-base.tcl",
    "content": "# Check the basic monitoring and failover capabilities.\n\nsource \"../tests/includes/init-tests.tcl\"\n\nif {$::simulate_error} {\n    test \"This test will fail\" {\n        fail \"Simulated error\"\n    }\n}\n\ntest \"Basic failover works if the master is down\" {\n    set old_port [RI $master_id tcp_port]\n    set addr [S 0 SENTINEL GET-MASTER-ADDR-BY-NAME mymaster]\n    assert {[lindex $addr 1] == $old_port}\n    kill_instance redis $master_id\n    foreach_sentinel_id id {\n        wait_for_condition 1000 50 {\n            [lindex [S $id SENTINEL GET-MASTER-ADDR-BY-NAME mymaster] 1] != $old_port\n        } else {\n            fail \"At least one Sentinel did not received failover info\"\n        }\n    }\n    restart_instance redis $master_id\n    set addr [S 0 SENTINEL GET-MASTER-ADDR-BY-NAME mymaster]\n    set master_id [get_instance_id_by_port redis [lindex $addr 1]]\n}\n\ntest \"New master [join $addr {:}] role matches\" {\n    assert {[RI $master_id role] eq {master}}\n}\n\ntest \"All the other slaves now point to the new master\" {\n    foreach_redis_id id {\n        if {$id != $master_id && $id != 0} {\n            wait_for_condition 1000 50 {\n                [RI $id master_port] == [lindex $addr 1]\n            } else {\n                fail \"Redis ID $id not configured to replicate with new master\"\n            }\n        }\n    }\n}\n\ntest \"The old master eventually gets reconfigured as a slave\" {\n    wait_for_condition 1000 50 {\n        [RI 0 master_port] == [lindex $addr 1]\n    } else {\n        fail \"Old master not reconfigured as slave of new master\"\n    }\n}\n\ntest \"ODOWN is not possible without N (quorum) Sentinels reports\" {\n    foreach_sentinel_id id {\n        S $id SENTINEL SET mymaster quorum [expr $sentinels+1]\n    }\n    set old_port [RI $master_id tcp_port]\n    set addr [S 0 SENTINEL GET-MASTER-ADDR-BY-NAME mymaster]\n    assert {[lindex $addr 1] == $old_port}\n    kill_instance redis $master_id\n\n    # Make sure failover did not happened.\n    set addr [S 0 SENTINEL GET-MASTER-ADDR-BY-NAME mymaster]\n    assert {[lindex $addr 1] == $old_port}\n    restart_instance redis $master_id\n}\n\ntest \"Failover is not possible without majority agreement\" {\n    foreach_sentinel_id id {\n        S $id SENTINEL SET mymaster quorum $quorum\n    }\n\n    # Crash majority of sentinels\n    for {set id 0} {$id < $quorum} {incr id} {\n        kill_instance sentinel $id\n    }\n\n    # Kill the current master\n    kill_instance redis $master_id\n\n    # Make sure failover did not happened.\n    set addr [S $quorum SENTINEL GET-MASTER-ADDR-BY-NAME mymaster]\n    assert {[lindex $addr 1] == $old_port}\n    restart_instance redis $master_id\n\n    # Cleanup: restart Sentinels to monitor the master.\n    for {set id 0} {$id < $quorum} {incr id} {\n        restart_instance sentinel $id\n    }\n}\n\ntest \"Failover works if we configure for absolute agreement\" {\n    foreach_sentinel_id id {\n        S $id SENTINEL SET mymaster quorum $sentinels\n    }\n\n    # Wait for Sentinels to monitor the master again\n    foreach_sentinel_id id {\n        wait_for_condition 1000 50 {\n            [dict get [S $id SENTINEL MASTER mymaster] info-refresh] < 100000\n        } else {\n            fail \"At least one Sentinel is not monitoring the master\"\n        }\n    }\n\n    kill_instance redis $master_id\n\n    foreach_sentinel_id id {\n        wait_for_condition 1000 50 {\n            [lindex [S $id SENTINEL GET-MASTER-ADDR-BY-NAME mymaster] 1] != $old_port\n        } else {\n            fail \"At least one Sentinel did not received failover info\"\n        }\n    }\n    restart_instance redis $master_id\n    set addr [S 0 SENTINEL GET-MASTER-ADDR-BY-NAME mymaster]\n    set master_id [get_instance_id_by_port redis [lindex $addr 1]]\n\n    # Set the min ODOWN agreement back to strict majority.\n    foreach_sentinel_id id {\n        S $id SENTINEL SET mymaster quorum $quorum\n    }\n}\n\ntest \"New master [join $addr {:}] role matches\" {\n    assert {[RI $master_id role] eq {master}}\n}\n"
  },
  {
    "path": "extern/deprecated/redis-2.8.21/tests/sentinel/tests/01-conf-update.tcl",
    "content": "# Test Sentinel configuration consistency after partitions heal.\n\nsource \"../tests/includes/init-tests.tcl\"\n\ntest \"We can failover with Sentinel 1 crashed\" {\n    set old_port [RI $master_id tcp_port]\n    set addr [S 0 SENTINEL GET-MASTER-ADDR-BY-NAME mymaster]\n    assert {[lindex $addr 1] == $old_port}\n\n    # Crash Sentinel 1\n    kill_instance sentinel 1\n\n    kill_instance redis $master_id\n    foreach_sentinel_id id {\n        if {$id != 1} {\n            wait_for_condition 1000 50 {\n                [lindex [S $id SENTINEL GET-MASTER-ADDR-BY-NAME mymaster] 1] != $old_port\n            } else {\n                fail \"Sentinel $id did not received failover info\"\n            }\n        }\n    }\n    restart_instance redis $master_id\n    set addr [S 0 SENTINEL GET-MASTER-ADDR-BY-NAME mymaster]\n    set master_id [get_instance_id_by_port redis [lindex $addr 1]]\n}\n\ntest \"After Sentinel 1 is restarted, its config gets updated\" {\n    restart_instance sentinel 1\n    wait_for_condition 1000 50 {\n        [lindex [S 1 SENTINEL GET-MASTER-ADDR-BY-NAME mymaster] 1] != $old_port\n    } else {\n        fail \"Restarted Sentinel did not received failover info\"\n    }\n}\n\ntest \"New master [join $addr {:}] role matches\" {\n    assert {[RI $master_id role] eq {master}}\n}\n"
  },
  {
    "path": "extern/deprecated/redis-2.8.21/tests/sentinel/tests/02-slaves-reconf.tcl",
    "content": "# Check that slaves are reconfigured at a latter time if they are partitioned.\n#\n# Here we should test:\n# 1) That slaves point to the new master after failover.\n# 2) That partitioned slaves point to new master when they are partitioned\n#    away during failover and return at a latter time.\n\nsource \"../tests/includes/init-tests.tcl\"\n\nproc 02_test_slaves_replication {} {\n    uplevel 1 {\n        test \"Check that slaves replicate from current master\" {\n            set master_port [RI $master_id tcp_port]\n            foreach_redis_id id {\n                if {$id == $master_id} continue\n                if {[instance_is_killed redis $id]} continue\n                wait_for_condition 1000 50 {\n                    ([RI $id master_port] == $master_port) &&\n                    ([RI $id master_link_status] eq {up})\n                } else {\n                    fail \"Redis slave $id is replicating from wrong master\"\n                }\n            }\n        }\n    }\n}\n\nproc 02_crash_and_failover {} {\n    uplevel 1 {\n        test \"Crash the master and force a failover\" {\n            set old_port [RI $master_id tcp_port]\n            set addr [S 0 SENTINEL GET-MASTER-ADDR-BY-NAME mymaster]\n            assert {[lindex $addr 1] == $old_port}\n            kill_instance redis $master_id\n            foreach_sentinel_id id {\n                wait_for_condition 1000 50 {\n                    [lindex [S $id SENTINEL GET-MASTER-ADDR-BY-NAME mymaster] 1] != $old_port\n                } else {\n                    fail \"At least one Sentinel did not received failover info\"\n                }\n            }\n            restart_instance redis $master_id\n            set addr [S 0 SENTINEL GET-MASTER-ADDR-BY-NAME mymaster]\n            set master_id [get_instance_id_by_port redis [lindex $addr 1]]\n        }\n    }\n}\n\n02_test_slaves_replication\n02_crash_and_failover\n02_test_slaves_replication\n\ntest \"Kill a slave instance\" {\n    foreach_redis_id id {\n        if {$id == $master_id} continue\n        set killed_slave_id $id\n        kill_instance redis $id\n        break\n    }\n}\n\n02_crash_and_failover\n02_test_slaves_replication\n\ntest \"Wait for failover to end\" {\n    set inprogress 1\n    while {$inprogress} {\n        set inprogress 0\n        foreach_sentinel_id id {\n            if {[dict exists [S $id SENTINEL MASTER mymaster] failover-state]} {\n                incr inprogress\n            }\n        }\n        if {$inprogress} {after 100}\n    }\n}\n\ntest \"Restart killed slave and test replication of slaves again...\" {\n    restart_instance redis $killed_slave_id\n}\n\n# Now we check if the slave rejoining the partition is reconfigured even\n# if the failover finished.\n02_test_slaves_replication\n"
  },
  {
    "path": "extern/deprecated/redis-2.8.21/tests/sentinel/tests/03-runtime-reconf.tcl",
    "content": "# Test runtime reconfiguration command SENTINEL SET.\n"
  },
  {
    "path": "extern/deprecated/redis-2.8.21/tests/sentinel/tests/04-slave-selection.tcl",
    "content": "# Test slave selection algorithm.\n#\n# This unit should test:\n# 1) That when there are no suitable slaves no failover is performed.\n# 2) That among the available slaves, the one with better offset is picked.\n"
  },
  {
    "path": "extern/deprecated/redis-2.8.21/tests/sentinel/tests/05-manual.tcl",
    "content": "# Test manual failover\n\nsource \"../tests/includes/init-tests.tcl\"\n\ntest \"Manual failover works\" {\n    set old_port [RI $master_id tcp_port]\n    set addr [S 0 SENTINEL GET-MASTER-ADDR-BY-NAME mymaster]\n    assert {[lindex $addr 1] == $old_port}\n    S 0 SENTINEL FAILOVER mymaster\n    foreach_sentinel_id id {\n        wait_for_condition 1000 50 {\n            [lindex [S $id SENTINEL GET-MASTER-ADDR-BY-NAME mymaster] 1] != $old_port\n        } else {\n            fail \"At least one Sentinel did not received failover info\"\n        }\n    }\n    set addr [S 0 SENTINEL GET-MASTER-ADDR-BY-NAME mymaster]\n    set master_id [get_instance_id_by_port redis [lindex $addr 1]]\n}\n\ntest \"New master [join $addr {:}] role matches\" {\n    assert {[RI $master_id role] eq {master}}\n}\n\ntest \"All the other slaves now point to the new master\" {\n    foreach_redis_id id {\n        if {$id != $master_id && $id != 0} {\n            wait_for_condition 1000 50 {\n                [RI $id master_port] == [lindex $addr 1]\n            } else {\n                fail \"Redis ID $id not configured to replicate with new master\"\n            }\n        }\n    }\n}\n\ntest \"The old master eventually gets reconfigured as a slave\" {\n    wait_for_condition 1000 50 {\n        [RI 0 master_port] == [lindex $addr 1]\n    } else {\n        fail \"Old master not reconfigured as slave of new master\"\n    }\n}\n\n"
  },
  {
    "path": "extern/deprecated/redis-2.8.21/tests/sentinel/tests/06-ckquorum.tcl",
    "content": "# Test for the SENTINEL CKQUORUM command\n\nsource \"../tests/includes/init-tests.tcl\"\nset num_sentinels [llength $::sentinel_instances]\n\ntest \"CKQUORUM reports OK and the right amount of Sentinels\" {\n    foreach_sentinel_id id {\n        assert_match \"*OK $num_sentinels usable*\" [S $id SENTINEL CKQUORUM mymaster]\n    }\n}\n\ntest \"CKQUORUM detects quorum cannot be reached\" {\n    set orig_quorum [expr {$num_sentinels/2+1}]\n    S 0 SENTINEL SET mymaster quorum [expr {$num_sentinels+1}]\n    catch {[S 0 SENTINEL CKQUORUM mymaster]} err\n    assert_match \"*NOQUORUM*\" $err\n    S 0 SENTINEL SET mymaster quorum $orig_quorum\n}\n\ntest \"CKQUORUM detects failover authorization cannot be reached\" {\n    set orig_quorum [expr {$num_sentinels/2+1}]\n    S 0 SENTINEL SET mymaster quorum 1\n    kill_instance sentinel 1\n    kill_instance sentinel 2\n    kill_instance sentinel 3\n    after 5000\n    catch {[S 0 SENTINEL CKQUORUM mymaster]} err\n    assert_match \"*NOQUORUM*\" $err\n    S 0 SENTINEL SET mymaster quorum $orig_quorum\n    restart_instance sentinel 1\n    restart_instance sentinel 2\n    restart_instance sentinel 3\n}\n\n"
  },
  {
    "path": "extern/deprecated/redis-2.8.21/tests/sentinel/tests/includes/init-tests.tcl",
    "content": "# Initialization tests -- most units will start including this.\n\ntest \"(init) Restart killed instances\" {\n    foreach type {redis sentinel} {\n        foreach_${type}_id id {\n            if {[get_instance_attrib $type $id pid] == -1} {\n                puts -nonewline \"$type/$id \"\n                flush stdout\n                restart_instance $type $id\n            }\n        }\n    }\n}\n\ntest \"(init) Remove old master entry from sentinels\" {\n    foreach_sentinel_id id {\n        catch {S $id SENTINEL REMOVE mymaster}\n    }\n}\n\nset redis_slaves 4\ntest \"(init) Create a master-slaves cluster of [expr $redis_slaves+1] instances\" {\n    create_redis_master_slave_cluster [expr {$redis_slaves+1}]\n}\nset master_id 0\n\ntest \"(init) Sentinels can start monitoring a master\" {\n    set sentinels [llength $::sentinel_instances]\n    set quorum [expr {$sentinels/2+1}]\n    foreach_sentinel_id id {\n        S $id SENTINEL MONITOR mymaster \\\n              [get_instance_attrib redis $master_id host] \\\n              [get_instance_attrib redis $master_id port] $quorum\n    }\n    foreach_sentinel_id id {\n        assert {[S $id sentinel master mymaster] ne {}}\n        S $id SENTINEL SET mymaster down-after-milliseconds 2000\n        S $id SENTINEL SET mymaster failover-timeout 20000\n        S $id SENTINEL SET mymaster parallel-syncs 10\n    }\n}\n\ntest \"(init) Sentinels can talk with the master\" {\n    foreach_sentinel_id id {\n        wait_for_condition 1000 50 {\n            [catch {S $id SENTINEL GET-MASTER-ADDR-BY-NAME mymaster}] == 0\n        } else {\n            fail \"Sentinel $id can't talk with the master.\"\n        }\n    }\n}\n\ntest \"(init) Sentinels are able to auto-discover other sentinels\" {\n    set sentinels [llength $::sentinel_instances]\n    foreach_sentinel_id id {\n        wait_for_condition 1000 50 {\n            [dict get [S $id SENTINEL MASTER mymaster] num-other-sentinels] == ($sentinels-1)\n        } else {\n            fail \"At least some sentinel can't detect some other sentinel\"\n        }\n    }\n}\n\ntest \"(init) Sentinels are able to auto-discover slaves\" {\n    foreach_sentinel_id id {\n        wait_for_condition 1000 50 {\n            [dict get [S $id SENTINEL MASTER mymaster] num-slaves] == $redis_slaves\n        } else {\n            fail \"At least some sentinel can't detect some slave\"\n        }\n    }\n}\n"
  },
  {
    "path": "extern/deprecated/redis-2.8.21/tests/sentinel/tmp/.gitignore",
    "content": "redis_*\nsentinel_*\n"
  },
  {
    "path": "extern/deprecated/redis-2.8.21/tests/support/redis.tcl",
    "content": "# Tcl clinet library - used by test-redis.tcl script for now\n# Copyright (C) 2009 Salvatore Sanfilippo\n# Released under the BSD license like Redis itself\n#\n# Example usage:\n#\n# set r [redis 127.0.0.1 6379]\n# $r lpush mylist foo\n# $r lpush mylist bar\n# $r lrange mylist 0 -1\n# $r close\n#\n# Non blocking usage example:\n#\n# proc handlePong {r type reply} {\n#     puts \"PONG $type '$reply'\"\n#     if {$reply ne \"PONG\"} {\n#         $r ping [list handlePong]\n#     }\n# }\n#\n# set r [redis]\n# $r blocking 0\n# $r get fo [list handlePong]\n#\n# vwait forever\n\npackage require Tcl 8.5\npackage provide redis 0.1\n\nnamespace eval redis {}\nset ::redis::id 0\narray set ::redis::fd {}\narray set ::redis::addr {}\narray set ::redis::blocking {}\narray set ::redis::deferred {}\narray set ::redis::reconnect {}\narray set ::redis::callback {}\narray set ::redis::state {} ;# State in non-blocking reply reading\narray set ::redis::statestack {} ;# Stack of states, for nested mbulks\n\nproc redis {{server 127.0.0.1} {port 6379} {defer 0}} {\n    set fd [socket $server $port]\n    fconfigure $fd -translation binary\n    set id [incr ::redis::id]\n    set ::redis::fd($id) $fd\n    set ::redis::addr($id) [list $server $port]\n    set ::redis::blocking($id) 1\n    set ::redis::deferred($id) $defer\n    set ::redis::reconnect($id) 0\n    ::redis::redis_reset_state $id\n    interp alias {} ::redis::redisHandle$id {} ::redis::__dispatch__ $id\n}\n\n# This is a wrapper to the actual dispatching procedure that handles\n# reconnection if needed.\nproc ::redis::__dispatch__ {id method args} {\n    set errorcode [catch {::redis::__dispatch__raw__ $id $method $args} retval]\n    if {$errorcode && $::redis::reconnect($id) && $::redis::fd($id) eq {}} {\n        # Try again if the connection was lost.\n        # FIXME: we don't re-select the previously selected DB, nor we check\n        # if we are inside a transaction that needs to be re-issued from\n        # scratch.\n        set errorcode [catch {::redis::__dispatch__raw__ $id $method $args} retval]\n    }\n    return -code $errorcode $retval\n}\n\nproc ::redis::__dispatch__raw__ {id method argv} {\n    set fd $::redis::fd($id)\n\n    # Reconnect the link if needed.\n    if {$fd eq {}} {\n        lassign $::redis::addr($id) host port\n        set ::redis::fd($id) [socket $host $port]\n        fconfigure $::redis::fd($id) -translation binary\n        set fd $::redis::fd($id)\n    }\n\n    set blocking $::redis::blocking($id)\n    set deferred $::redis::deferred($id)\n    if {$blocking == 0} {\n        if {[llength $argv] == 0} {\n            error \"Please provide a callback in non-blocking mode\"\n        }\n        set callback [lindex $argv end]\n        set argv [lrange $argv 0 end-1]\n    }\n    if {[info command ::redis::__method__$method] eq {}} {\n        set cmd \"*[expr {[llength $argv]+1}]\\r\\n\"\n        append cmd \"$[string length $method]\\r\\n$method\\r\\n\"\n        foreach a $argv {\n            append cmd \"$[string length $a]\\r\\n$a\\r\\n\"\n        }\n        ::redis::redis_write $fd $cmd\n        if {[catch {flush $fd}]} {\n            set ::redis::fd($id) {}\n            return -code error \"I/O error reading reply\"\n        }\n\n        if {!$deferred} {\n            if {$blocking} {\n                ::redis::redis_read_reply $id $fd\n            } else {\n                # Every well formed reply read will pop an element from this\n                # list and use it as a callback. So pipelining is supported\n                # in non blocking mode.\n                lappend ::redis::callback($id) $callback\n                fileevent $fd readable [list ::redis::redis_readable $fd $id]\n            }\n        }\n    } else {\n        uplevel 1 [list ::redis::__method__$method $id $fd] $argv\n    }\n}\n\nproc ::redis::__method__blocking {id fd val} {\n    set ::redis::blocking($id) $val\n    fconfigure $fd -blocking $val\n}\n\nproc ::redis::__method__reconnect {id fd val} {\n    set ::redis::reconnect($id) $val\n}\n\nproc ::redis::__method__read {id fd} {\n    ::redis::redis_read_reply $id $fd\n}\n\nproc ::redis::__method__write {id fd buf} {\n    ::redis::redis_write $fd $buf\n}\n\nproc ::redis::__method__flush {id fd} {\n    flush $fd\n}\n\nproc ::redis::__method__close {id fd} {\n    catch {close $fd}\n    catch {unset ::redis::fd($id)}\n    catch {unset ::redis::addr($id)}\n    catch {unset ::redis::blocking($id)}\n    catch {unset ::redis::deferred($id)}\n    catch {unset ::redis::reconnect($id)}\n    catch {unset ::redis::state($id)}\n    catch {unset ::redis::statestack($id)}\n    catch {unset ::redis::callback($id)}\n    catch {interp alias {} ::redis::redisHandle$id {}}\n}\n\nproc ::redis::__method__channel {id fd} {\n    return $fd\n}\n\nproc ::redis::__method__deferred {id fd val} {\n    set ::redis::deferred($id) $val\n}\n\nproc ::redis::redis_write {fd buf} {\n    puts -nonewline $fd $buf\n}\n\nproc ::redis::redis_writenl {fd buf} {\n    redis_write $fd $buf\n    redis_write $fd \"\\r\\n\"\n    flush $fd\n}\n\nproc ::redis::redis_readnl {fd len} {\n    set buf [read $fd $len]\n    read $fd 2 ; # discard CR LF\n    return $buf\n}\n\nproc ::redis::redis_bulk_read {fd} {\n    set count [redis_read_line $fd]\n    if {$count == -1} return {}\n    set buf [redis_readnl $fd $count]\n    return $buf\n}\n\nproc ::redis::redis_multi_bulk_read {id fd} {\n    set count [redis_read_line $fd]\n    if {$count == -1} return {}\n    set l {}\n    set err {}\n    for {set i 0} {$i < $count} {incr i} {\n        if {[catch {\n            lappend l [redis_read_reply $id $fd]\n        } e] && $err eq {}} {\n            set err $e\n        }\n    }\n    if {$err ne {}} {return -code error $err}\n    return $l\n}\n\nproc ::redis::redis_read_line fd {\n    string trim [gets $fd]\n}\n\nproc ::redis::redis_read_reply {id fd} {\n    set type [read $fd 1]\n    switch -exact -- $type {\n        : -\n        + {redis_read_line $fd}\n        - {return -code error [redis_read_line $fd]}\n        $ {redis_bulk_read $fd}\n        * {redis_multi_bulk_read $id $fd}\n        default {\n            if {$type eq {}} {\n                set ::redis::fd($id) {}\n                return -code error \"I/O error reading reply\"\n            }\n            return -code error \"Bad protocol, '$type' as reply type byte\"\n        }\n    }\n}\n\nproc ::redis::redis_reset_state id {\n    set ::redis::state($id) [dict create buf {} mbulk -1 bulk -1 reply {}]\n    set ::redis::statestack($id) {}\n}\n\nproc ::redis::redis_call_callback {id type reply} {\n    set cb [lindex $::redis::callback($id) 0]\n    set ::redis::callback($id) [lrange $::redis::callback($id) 1 end]\n    uplevel #0 $cb [list ::redis::redisHandle$id $type $reply]\n    ::redis::redis_reset_state $id\n}\n\n# Read a reply in non-blocking mode.\nproc ::redis::redis_readable {fd id} {\n    if {[eof $fd]} {\n        redis_call_callback $id eof {}\n        ::redis::__method__close $id $fd\n        return\n    }\n    if {[dict get $::redis::state($id) bulk] == -1} {\n        set line [gets $fd]\n        if {$line eq {}} return ;# No complete line available, return\n        switch -exact -- [string index $line 0] {\n            : -\n            + {redis_call_callback $id reply [string range $line 1 end-1]}\n            - {redis_call_callback $id err [string range $line 1 end-1]}\n            $ {\n                dict set ::redis::state($id) bulk \\\n                    [expr [string range $line 1 end-1]+2]\n                if {[dict get $::redis::state($id) bulk] == 1} {\n                    # We got a $-1, hack the state to play well with this.\n                    dict set ::redis::state($id) bulk 2\n                    dict set ::redis::state($id) buf \"\\r\\n\"\n                    ::redis::redis_readable $fd $id\n                }\n            }\n            * {\n                dict set ::redis::state($id) mbulk [string range $line 1 end-1]\n                # Handle *-1\n                if {[dict get $::redis::state($id) mbulk] == -1} {\n                    redis_call_callback $id reply {}\n                }\n            }\n            default {\n                redis_call_callback $id err \\\n                    \"Bad protocol, $type as reply type byte\"\n            }\n        }\n    } else {\n        set totlen [dict get $::redis::state($id) bulk]\n        set buflen [string length [dict get $::redis::state($id) buf]]\n        set toread [expr {$totlen-$buflen}]\n        set data [read $fd $toread]\n        set nread [string length $data]\n        dict append ::redis::state($id) buf $data\n        # Check if we read a complete bulk reply\n        if {[string length [dict get $::redis::state($id) buf]] ==\n            [dict get $::redis::state($id) bulk]} {\n            if {[dict get $::redis::state($id) mbulk] == -1} {\n                redis_call_callback $id reply \\\n                    [string range [dict get $::redis::state($id) buf] 0 end-2]\n            } else {\n                dict with ::redis::state($id) {\n                    lappend reply [string range $buf 0 end-2]\n                    incr mbulk -1\n                    set bulk -1\n                }\n                if {[dict get $::redis::state($id) mbulk] == 0} {\n                    redis_call_callback $id reply \\\n                        [dict get $::redis::state($id) reply]\n                }\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "extern/deprecated/redis-2.8.21/tests/support/server.tcl",
    "content": "set ::global_overrides {}\nset ::tags {}\nset ::valgrind_errors {}\n\nproc start_server_error {config_file error} {\n    set err {}\n    append err \"Cant' start the Redis server\\n\"\n    append err \"CONFIGURATION:\"\n    append err [exec cat $config_file]\n    append err \"\\nERROR:\"\n    append err [string trim $error]\n    send_data_packet $::test_server_fd err $err\n}\n\nproc check_valgrind_errors stderr {\n    set fd [open $stderr]\n    set buf [read $fd]\n    close $fd\n\n    if {[regexp -- { at 0x} $buf] ||\n        (![regexp -- {definitely lost: 0 bytes} $buf] &&\n         ![regexp -- {no leaks are possible} $buf])} {\n        send_data_packet $::test_server_fd err \"Valgrind error: $buf\\n\"\n    }\n}\n\nproc kill_server config {\n    # nothing to kill when running against external server\n    if {$::external} return\n\n    # nevermind if its already dead\n    if {![is_alive $config]} { return }\n    set pid [dict get $config pid]\n\n    # check for leaks\n    if {![dict exists $config \"skipleaks\"]} {\n        catch {\n            if {[string match {*Darwin*} [exec uname -a]]} {\n                tags {\"leaks\"} {\n                    test \"Check for memory leaks (pid $pid)\" {\n                        set output {0 leaks}\n                        catch {exec leaks $pid} output\n                        if {[string match {*process does not exist*} $output] ||\n                            [string match {*cannot examine*} $output]} {\n                            # In a few tests we kill the server process.\n                            set output \"0 leaks\"\n                        }\n                        set output\n                    } {*0 leaks*}\n                }\n            }\n        }\n    }\n\n    # kill server and wait for the process to be totally exited\n    catch {exec kill $pid}\n    while {[is_alive $config]} {\n        incr wait 10\n\n        if {$wait >= 5000} {\n            puts \"Forcing process $pid to exit...\"\n            catch {exec kill -KILL $pid}\n        } elseif {$wait % 1000 == 0} {\n            puts \"Waiting for process $pid to exit...\"\n        }\n        after 10\n    }\n\n    # Check valgrind errors if needed\n    if {$::valgrind} {\n        check_valgrind_errors [dict get $config stderr]\n    }\n\n    # Remove this pid from the set of active pids in the test server.\n    send_data_packet $::test_server_fd server-killed $pid\n}\n\nproc is_alive config {\n    set pid [dict get $config pid]\n    if {[catch {exec ps -p $pid} err]} {\n        return 0\n    } else {\n        return 1\n    }\n}\n\nproc ping_server {host port} {\n    set retval 0\n    if {[catch {\n        set fd [socket $host $port]\n        fconfigure $fd -translation binary\n        puts $fd \"PING\\r\\n\"\n        flush $fd\n        set reply [gets $fd]\n        if {[string range $reply 0 0] eq {+} ||\n            [string range $reply 0 0] eq {-}} {\n            set retval 1\n        }\n        close $fd\n    } e]} {\n        if {$::verbose} {\n            puts -nonewline \".\"\n        }\n    } else {\n        if {$::verbose} {\n            puts -nonewline \"ok\"\n        }\n    }\n    return $retval\n}\n\n# Return 1 if the server at the specified addr is reachable by PING, otherwise\n# returns 0. Performs a try every 50 milliseconds for the specified number\n# of retries.\nproc server_is_up {host port retrynum} {\n    after 10 ;# Use a small delay to make likely a first-try success.\n    set retval 0\n    while {[incr retrynum -1]} {\n        if {[catch {ping_server $host $port} ping]} {\n            set ping 0\n        }\n        if {$ping} {return 1}\n        after 50\n    }\n    return 0\n}\n\n# doesn't really belong here, but highly coupled to code in start_server\nproc tags {tags code} {\n    set ::tags [concat $::tags $tags]\n    uplevel 1 $code\n    set ::tags [lrange $::tags 0 end-[llength $tags]]\n}\n\nproc start_server {options {code undefined}} {\n    # If we are running against an external server, we just push the\n    # host/port pair in the stack the first time\n    if {$::external} {\n        if {[llength $::servers] == 0} {\n            set srv {}\n            dict set srv \"host\" $::host\n            dict set srv \"port\" $::port\n            set client [redis $::host $::port]\n            dict set srv \"client\" $client\n            $client select 9\n\n            # append the server to the stack\n            lappend ::servers $srv\n        }\n        uplevel 1 $code\n        return\n    }\n\n    # setup defaults\n    set baseconfig \"default.conf\"\n    set overrides {}\n    set tags {}\n\n    # parse options\n    foreach {option value} $options {\n        switch $option {\n            \"config\" {\n                set baseconfig $value }\n            \"overrides\" {\n                set overrides $value }\n            \"tags\" {\n                set tags $value\n                set ::tags [concat $::tags $value] }\n            default {\n                error \"Unknown option $option\" }\n        }\n    }\n\n    set data [split [exec cat \"tests/assets/$baseconfig\"] \"\\n\"]\n    set config {}\n    foreach line $data {\n        if {[string length $line] > 0 && [string index $line 0] ne \"#\"} {\n            set elements [split $line \" \"]\n            set directive [lrange $elements 0 0]\n            set arguments [lrange $elements 1 end]\n            dict set config $directive $arguments\n        }\n    }\n\n    # use a different directory every time a server is started\n    dict set config dir [tmpdir server]\n\n    # start every server on a different port\n    set ::port [find_available_port [expr {$::port+1}]]\n    dict set config port $::port\n\n    # apply overrides from global space and arguments\n    foreach {directive arguments} [concat $::global_overrides $overrides] {\n        dict set config $directive $arguments\n    }\n\n    # write new configuration to temporary file\n    set config_file [tmpfile redis.conf]\n    set fp [open $config_file w+]\n    foreach directive [dict keys $config] {\n        puts -nonewline $fp \"$directive \"\n        puts $fp [dict get $config $directive]\n    }\n    close $fp\n\n    set stdout [format \"%s/%s\" [dict get $config \"dir\"] \"stdout\"]\n    set stderr [format \"%s/%s\" [dict get $config \"dir\"] \"stderr\"]\n\n    if {$::valgrind} {\n        set pid [exec valgrind --suppressions=src/valgrind.sup --show-reachable=no --show-possibly-lost=no --leak-check=full src/redis-server $config_file > $stdout 2> $stderr &]\n    } else {\n        set pid [exec src/redis-server $config_file > $stdout 2> $stderr &]\n    }\n\n    # Tell the test server about this new instance.\n    send_data_packet $::test_server_fd server-spawned $pid\n\n    # check that the server actually started\n    # ugly but tries to be as fast as possible...\n    if {$::valgrind} {set retrynum 1000} else {set retrynum 100}\n\n    if {$::verbose} {\n        puts -nonewline \"=== ($tags) Starting server ${::host}:${::port} \"\n    }\n\n    if {$code ne \"undefined\"} {\n        set serverisup [server_is_up $::host $::port $retrynum]\n    } else {\n        set serverisup 1\n    }\n\n    if {$::verbose} {\n        puts \"\"\n    }\n\n    if {!$serverisup} {\n        set err {}\n        append err [exec cat $stdout] \"\\n\" [exec cat $stderr]\n        start_server_error $config_file $err\n        return\n    }\n\n    # Wait for actual startup\n    while {![info exists _pid]} {\n        regexp {PID:\\s(\\d+)} [exec cat $stdout] _ _pid\n        after 100\n    }\n\n    # setup properties to be able to initialize a client object\n    set host $::host\n    set port $::port\n    if {[dict exists $config bind]} { set host [dict get $config bind] }\n    if {[dict exists $config port]} { set port [dict get $config port] }\n\n    # setup config dict\n    dict set srv \"config_file\" $config_file\n    dict set srv \"config\" $config\n    dict set srv \"pid\" $pid\n    dict set srv \"host\" $host\n    dict set srv \"port\" $port\n    dict set srv \"stdout\" $stdout\n    dict set srv \"stderr\" $stderr\n\n    # if a block of code is supplied, we wait for the server to become\n    # available, create a client object and kill the server afterwards\n    if {$code ne \"undefined\"} {\n        set line [exec head -n1 $stdout]\n        if {[string match {*already in use*} $line]} {\n            error_and_quit $config_file $line\n        }\n\n        while 1 {\n            # check that the server actually started and is ready for connections\n            if {[exec grep \"ready to accept\" | wc -l < $stdout] > 0} {\n                break\n            }\n            after 10\n        }\n\n        # append the server to the stack\n        lappend ::servers $srv\n\n        # connect client (after server dict is put on the stack)\n        reconnect\n\n        # execute provided block\n        set num_tests $::num_tests\n        if {[catch { uplevel 1 $code } error]} {\n            set backtrace $::errorInfo\n\n            # Kill the server without checking for leaks\n            dict set srv \"skipleaks\" 1\n            kill_server $srv\n\n            # Print warnings from log\n            puts [format \"\\nLogged warnings (pid %d):\" [dict get $srv \"pid\"]]\n            set warnings [warnings_from_file [dict get $srv \"stdout\"]]\n            if {[string length $warnings] > 0} {\n                puts \"$warnings\"\n            } else {\n                puts \"(none)\"\n            }\n            puts \"\"\n\n            error $error $backtrace\n        }\n\n        # Don't do the leak check when no tests were run\n        if {$num_tests == $::num_tests} {\n            dict set srv \"skipleaks\" 1\n        }\n\n        # pop the server object\n        set ::servers [lrange $::servers 0 end-1]\n\n        set ::tags [lrange $::tags 0 end-[llength $tags]]\n        kill_server $srv\n    } else {\n        set ::tags [lrange $::tags 0 end-[llength $tags]]\n        set _ $srv\n    }\n}\n"
  },
  {
    "path": "extern/deprecated/redis-2.8.21/tests/support/test.tcl",
    "content": "set ::num_tests 0\nset ::num_passed 0\nset ::num_failed 0\nset ::tests_failed {}\n\nproc fail {msg} {\n    error \"assertion:$msg\"\n}\n\nproc assert {condition} {\n    if {![uplevel 1 [list expr $condition]]} {\n        error \"assertion:Expected condition '$condition' to be true ([uplevel 1 [list subst -nocommands $condition]])\"\n    }\n}\n\nproc assert_match {pattern value} {\n    if {![string match $pattern $value]} {\n        error \"assertion:Expected '$value' to match '$pattern'\"\n    }\n}\n\nproc assert_equal {expected value} {\n    if {$expected ne $value} {\n        error \"assertion:Expected '$value' to be equal to '$expected'\"\n    }\n}\n\nproc assert_error {pattern code} {\n    if {[catch {uplevel 1 $code} error]} {\n        assert_match $pattern $error\n    } else {\n        error \"assertion:Expected an error but nothing was caught\"\n    }\n}\n\nproc assert_encoding {enc key} {\n    # Swapped out values don't have an encoding, so make sure that\n    # the value is swapped in before checking the encoding.\n    set dbg [r debug object $key]\n    while {[string match \"* swapped at:*\" $dbg]} {\n        r debug swapin $key\n        set dbg [r debug object $key]\n    }\n    assert_match \"* encoding:$enc *\" $dbg\n}\n\nproc assert_type {type key} {\n    assert_equal $type [r type $key]\n}\n\n# Wait for the specified condition to be true, with the specified number of\n# max retries and delay between retries. Otherwise the 'elsescript' is\n# executed.\nproc wait_for_condition {maxtries delay e _else_ elsescript} {\n    while {[incr maxtries -1] >= 0} {\n        set errcode [catch {uplevel 1 [list expr $e]} result]\n        if {$errcode == 0} {\n            if {$result} break\n        } else {\n            return -code $errcode $result\n        }\n        after $delay\n    }\n    if {$maxtries == -1} {\n        set errcode [catch [uplevel 1 $elsescript] result]\n        return -code $errcode $result\n    }\n}\n\nproc test {name code {okpattern undefined}} {\n    # abort if tagged with a tag to deny\n    foreach tag $::denytags {\n        if {[lsearch $::tags $tag] >= 0} {\n            return\n        }\n    }\n\n    # check if tagged with at least 1 tag to allow when there *is* a list\n    # of tags to allow, because default policy is to run everything\n    if {[llength $::allowtags] > 0} {\n        set matched 0\n        foreach tag $::allowtags {\n            if {[lsearch $::tags $tag] >= 0} {\n                incr matched\n            }\n        }\n        if {$matched < 1} {\n            return\n        }\n    }\n\n    incr ::num_tests\n    set details {}\n    lappend details \"$name in $::curfile\"\n\n    send_data_packet $::test_server_fd testing $name\n\n    if {[catch {set retval [uplevel 1 $code]} error]} {\n        if {[string match \"assertion:*\" $error]} {\n            set msg [string range $error 10 end]\n            lappend details $msg\n            lappend ::tests_failed $details\n\n            incr ::num_failed\n            send_data_packet $::test_server_fd err [join $details \"\\n\"]\n        } else {\n            # Re-raise, let handler up the stack take care of this.\n            error $error $::errorInfo\n        }\n    } else {\n        if {$okpattern eq \"undefined\" || $okpattern eq $retval || [string match $okpattern $retval]} {\n            incr ::num_passed\n            send_data_packet $::test_server_fd ok $name\n        } else {\n            set msg \"Expected '$okpattern' to equal or match '$retval'\"\n            lappend details $msg\n            lappend ::tests_failed $details\n\n            incr ::num_failed\n            send_data_packet $::test_server_fd err [join $details \"\\n\"]\n        }\n    }\n\n    if {$::traceleaks} {\n        set output [exec leaks redis-server]\n        if {![string match {*0 leaks*} $output]} {\n            send_data_packet $::test_server_fd err \"Detected a memory leak in test '$name': $output\"\n        }\n    }\n}\n"
  },
  {
    "path": "extern/deprecated/redis-2.8.21/tests/support/tmpfile.tcl",
    "content": "set ::tmpcounter 0\nset ::tmproot \"./tests/tmp\"\nfile mkdir $::tmproot\n\n# returns a dirname unique to this process to write to\nproc tmpdir {basename} {\n    set dir [file join $::tmproot $basename.[pid].[incr ::tmpcounter]]\n    file mkdir $dir\n    set _ $dir\n}\n\n# return a filename unique to this process to write to\nproc tmpfile {basename} {\n    file join $::tmproot $basename.[pid].[incr ::tmpcounter]\n}\n"
  },
  {
    "path": "extern/deprecated/redis-2.8.21/tests/support/util.tcl",
    "content": "proc randstring {min max {type binary}} {\n    set len [expr {$min+int(rand()*($max-$min+1))}]\n    set output {}\n    if {$type eq {binary}} {\n        set minval 0\n        set maxval 255\n    } elseif {$type eq {alpha}} {\n        set minval 48\n        set maxval 122\n    } elseif {$type eq {compr}} {\n        set minval 48\n        set maxval 52\n    }\n    while {$len} {\n        append output [format \"%c\" [expr {$minval+int(rand()*($maxval-$minval+1))}]]\n        incr len -1\n    }\n    return $output\n}\n\n# Useful for some test\nproc zlistAlikeSort {a b} {\n    if {[lindex $a 0] > [lindex $b 0]} {return 1}\n    if {[lindex $a 0] < [lindex $b 0]} {return -1}\n    string compare [lindex $a 1] [lindex $b 1]\n}\n\n# Return all log lines starting with the first line that contains a warning.\n# Generally, this will be an assertion error with a stack trace.\nproc warnings_from_file {filename} {\n    set lines [split [exec cat $filename] \"\\n\"]\n    set matched 0\n    set logall 0\n    set result {}\n    foreach line $lines {\n        if {[string match {*REDIS BUG REPORT START*} $line]} {\n            set logall 1\n        }\n        if {[regexp {^\\[\\d+\\]\\s+\\d+\\s+\\w+\\s+\\d{2}:\\d{2}:\\d{2} \\#} $line]} {\n            set matched 1\n        }\n        if {$logall || $matched} {\n            lappend result $line\n        }\n    }\n    join $result \"\\n\"\n}\n\n# Return value for INFO property\nproc status {r property} {\n    if {[regexp \"\\r\\n$property:(.*?)\\r\\n\" [{*}$r info] _ value]} {\n        set _ $value\n    }\n}\n\nproc waitForBgsave r {\n    while 1 {\n        if {[status r rdb_bgsave_in_progress] eq 1} {\n            if {$::verbose} {\n                puts -nonewline \"\\nWaiting for background save to finish... \"\n                flush stdout\n            }\n            after 1000\n        } else {\n            break\n        }\n    }\n}\n\nproc waitForBgrewriteaof r {\n    while 1 {\n        if {[status r aof_rewrite_in_progress] eq 1} {\n            if {$::verbose} {\n                puts -nonewline \"\\nWaiting for background AOF rewrite to finish... \"\n                flush stdout\n            }\n            after 1000\n        } else {\n            break\n        }\n    }\n}\n\nproc wait_for_sync r {\n    while 1 {\n        if {[status $r master_link_status] eq \"down\"} {\n            after 10\n        } else {\n            break\n        }\n    }\n}\n\n# Random integer between 0 and max (excluded).\nproc randomInt {max} {\n    expr {int(rand()*$max)}\n}\n\n# Random signed integer between -max and max (both extremes excluded).\nproc randomSignedInt {max} {\n    set i [randomInt $max]\n    if {rand() > 0.5} {\n        set i -$i\n    }\n    return $i\n}\n\nproc randpath args {\n    set path [expr {int(rand()*[llength $args])}]\n    uplevel 1 [lindex $args $path]\n}\n\nproc randomValue {} {\n    randpath {\n        # Small enough to likely collide\n        randomSignedInt 1000\n    } {\n        # 32 bit compressible signed/unsigned\n        randpath {randomSignedInt 2000000000} {randomSignedInt 4000000000}\n    } {\n        # 64 bit\n        randpath {randomSignedInt 1000000000000}\n    } {\n        # Random string\n        randpath {randstring 0 256 alpha} \\\n                {randstring 0 256 compr} \\\n                {randstring 0 256 binary}\n    }\n}\n\nproc randomKey {} {\n    randpath {\n        # Small enough to likely collide\n        randomInt 1000\n    } {\n        # 32 bit compressible signed/unsigned\n        randpath {randomInt 2000000000} {randomInt 4000000000}\n    } {\n        # 64 bit\n        randpath {randomInt 1000000000000}\n    } {\n        # Random string\n        randpath {randstring 1 256 alpha} \\\n                {randstring 1 256 compr}\n    }\n}\n\nproc findKeyWithType {r type} {\n    for {set j 0} {$j < 20} {incr j} {\n        set k [{*}$r randomkey]\n        if {$k eq {}} {\n            return {}\n        }\n        if {[{*}$r type $k] eq $type} {\n            return $k\n        }\n    }\n    return {}\n}\n\nproc createComplexDataset {r ops {opt {}}} {\n    for {set j 0} {$j < $ops} {incr j} {\n        set k [randomKey]\n        set k2 [randomKey]\n        set f [randomValue]\n        set v [randomValue]\n\n        if {[lsearch -exact $opt useexpire] != -1} {\n            if {rand() < 0.1} {\n                {*}$r expire [randomKey] [randomInt 2]\n            }\n        }\n\n        randpath {\n            set d [expr {rand()}]\n        } {\n            set d [expr {rand()}]\n        } {\n            set d [expr {rand()}]\n        } {\n            set d [expr {rand()}]\n        } {\n            set d [expr {rand()}]\n        } {\n            randpath {set d +inf} {set d -inf}\n        }\n        set t [{*}$r type $k]\n\n        if {$t eq {none}} {\n            randpath {\n                {*}$r set $k $v\n            } {\n                {*}$r lpush $k $v\n            } {\n                {*}$r sadd $k $v\n            } {\n                {*}$r zadd $k $d $v\n            } {\n                {*}$r hset $k $f $v\n            } {\n                {*}$r del $k\n            }\n            set t [{*}$r type $k]\n        }\n\n        switch $t {\n            {string} {\n                # Nothing to do\n            }\n            {list} {\n                randpath {{*}$r lpush $k $v} \\\n                        {{*}$r rpush $k $v} \\\n                        {{*}$r lrem $k 0 $v} \\\n                        {{*}$r rpop $k} \\\n                        {{*}$r lpop $k}\n            }\n            {set} {\n                randpath {{*}$r sadd $k $v} \\\n                        {{*}$r srem $k $v} \\\n                        {\n                            set otherset [findKeyWithType {*}$r set]\n                            if {$otherset ne {}} {\n                                randpath {\n                                    {*}$r sunionstore $k2 $k $otherset\n                                } {\n                                    {*}$r sinterstore $k2 $k $otherset\n                                } {\n                                    {*}$r sdiffstore $k2 $k $otherset\n                                }\n                            }\n                        }\n            }\n            {zset} {\n                randpath {{*}$r zadd $k $d $v} \\\n                        {{*}$r zrem $k $v} \\\n                        {\n                            set otherzset [findKeyWithType {*}$r zset]\n                            if {$otherzset ne {}} {\n                                randpath {\n                                    {*}$r zunionstore $k2 2 $k $otherzset\n                                } {\n                                    {*}$r zinterstore $k2 2 $k $otherzset\n                                }\n                            }\n                        }\n            }\n            {hash} {\n                randpath {{*}$r hset $k $f $v} \\\n                        {{*}$r hdel $k $f}\n            }\n        }\n    }\n}\n\nproc formatCommand {args} {\n    set cmd \"*[llength $args]\\r\\n\"\n    foreach a $args {\n        append cmd \"$[string length $a]\\r\\n$a\\r\\n\"\n    }\n    set _ $cmd\n}\n\nproc csvdump r {\n    set o {}\n    foreach k [lsort [{*}$r keys *]] {\n        set type [{*}$r type $k]\n        append o [csvstring $k] , [csvstring $type] ,\n        switch $type {\n            string {\n                append o [csvstring [{*}$r get $k]] \"\\n\"\n            }\n            list {\n                foreach e [{*}$r lrange $k 0 -1] {\n                    append o [csvstring $e] ,\n                }\n                append o \"\\n\"\n            }\n            set {\n                foreach e [lsort [{*}$r smembers $k]] {\n                    append o [csvstring $e] ,\n                }\n                append o \"\\n\"\n            }\n            zset {\n                foreach e [{*}$r zrange $k 0 -1 withscores] {\n                    append o [csvstring $e] ,\n                }\n                append o \"\\n\"\n            }\n            hash {\n                set fields [{*}$r hgetall $k]\n                set newfields {}\n                foreach {k v} $fields {\n                    lappend newfields [list $k $v]\n                }\n                set fields [lsort -index 0 $newfields]\n                foreach kv $fields {\n                    append o [csvstring [lindex $kv 0]] ,\n                    append o [csvstring [lindex $kv 1]] ,\n                }\n                append o \"\\n\"\n            }\n        }\n    }\n    return $o\n}\n\nproc csvstring s {\n    return \"\\\"$s\\\"\"\n}\n\nproc roundFloat f {\n    format \"%.10g\" $f\n}\n\nproc find_available_port start {\n    for {set j $start} {$j < $start+1024} {incr j} {\n        if {[catch {\n            set fd [socket 127.0.0.1 $j]\n        }]} {\n            return $j\n        } else {\n            close $fd\n        }\n    }\n    if {$j == $start+1024} {\n        error \"Can't find a non busy port in the $start-[expr {$start+1023}] range.\"\n    }\n}\n\n# Test if TERM looks like to support colors\nproc color_term {} {\n    expr {[info exists ::env(TERM)] && [string match *xterm* $::env(TERM)]}\n}\n\nproc colorstr {color str} {\n    if {[color_term]} {\n        set b 0\n        if {[string range $color 0 4] eq {bold-}} {\n            set b 1\n            set color [string range $color 5 end]\n        }\n        switch $color {\n            red {set colorcode {31}}\n            green {set colorcode {32}}\n            yellow {set colorcode {33}}\n            blue {set colorcode {34}}\n            magenta {set colorcode {35}}\n            cyan {set colorcode {36}}\n            white {set colorcode {37}}\n            default {set colorcode {37}}\n        }\n        if {$colorcode ne {}} {\n            return \"\\033\\[$b;${colorcode};49m$str\\033\\[0m\"\n        }\n    } else {\n        return $str\n    }\n}\n\n# Execute a background process writing random data for the specified number\n# of seconds to the specified Redis instance.\nproc start_write_load {host port seconds} {\n    set tclsh [info nameofexecutable]\n    exec $tclsh tests/helpers/gen_write_load.tcl $host $port $seconds &\n}\n\n# Stop a process generating write load executed with start_write_load.\nproc stop_write_load {handle} {\n    catch {exec /bin/kill -9 $handle}\n}\n"
  },
  {
    "path": "extern/deprecated/redis-2.8.21/tests/test_helper.tcl",
    "content": "# Redis test suite. Copyright (C) 2009 Salvatore Sanfilippo antirez@gmail.com\n# This software is released under the BSD License. See the COPYING file for\n# more information.\n\npackage require Tcl 8.5\n\nset tcl_precision 17\nsource tests/support/redis.tcl\nsource tests/support/server.tcl\nsource tests/support/tmpfile.tcl\nsource tests/support/test.tcl\nsource tests/support/util.tcl\n\nset ::all_tests {\n    unit/printver\n    unit/auth\n    unit/protocol\n    unit/basic\n    unit/scan\n    unit/type/list\n    unit/type/list-2\n    unit/type/list-3\n    unit/type/set\n    unit/type/zset\n    unit/type/hash\n    unit/sort\n    unit/expire\n    unit/other\n    unit/multi\n    unit/quit\n    unit/aofrw\n    integration/replication\n    integration/replication-2\n    integration/replication-3\n    integration/replication-4\n    integration/replication-psync\n    integration/aof\n    integration/rdb\n    integration/convert-zipmap-hash-on-load\n    unit/pubsub\n    unit/slowlog\n    unit/scripting\n    unit/maxmemory\n    unit/introspection\n    unit/limits\n    unit/obuf-limits\n    unit/dump\n    unit/bitops\n    unit/memefficiency\n    unit/hyperloglog\n}\n# Index to the next test to run in the ::all_tests list.\nset ::next_test 0\n\nset ::host 127.0.0.1\nset ::port 21111\nset ::traceleaks 0\nset ::valgrind 0\nset ::verbose 0\nset ::quiet 0\nset ::denytags {}\nset ::allowtags {}\nset ::external 0; # If \"1\" this means, we are running against external instance\nset ::file \"\"; # If set, runs only the tests in this comma separated list\nset ::curfile \"\"; # Hold the filename of the current suite\nset ::accurate 0; # If true runs fuzz tests with more iterations\nset ::force_failure 0\nset ::timeout 600; # 10 minutes without progresses will quit the test.\nset ::last_progress [clock seconds]\nset ::active_servers {} ; # Pids of active Redis instances.\n\n# Set to 1 when we are running in client mode. The Redis test uses a\n# server-client model to run tests simultaneously. The server instance\n# runs the specified number of client instances that will actually run tests.\n# The server is responsible of showing the result to the user, and exit with\n# the appropriate exit code depending on the test outcome.\nset ::client 0\nset ::numclients 16\n\nproc execute_tests name {\n    set path \"tests/$name.tcl\"\n    set ::curfile $path\n    source $path\n    send_data_packet $::test_server_fd done \"$name\"\n}\n\n# Setup a list to hold a stack of server configs. When calls to start_server\n# are nested, use \"srv 0 pid\" to get the pid of the inner server. To access\n# outer servers, use \"srv -1 pid\" etcetera.\nset ::servers {}\nproc srv {args} {\n    set level 0\n    if {[string is integer [lindex $args 0]]} {\n        set level [lindex $args 0]\n        set property [lindex $args 1]\n    } else {\n        set property [lindex $args 0]\n    }\n    set srv [lindex $::servers end+$level]\n    dict get $srv $property\n}\n\n# Provide easy access to the client for the inner server. It's possible to\n# prepend the argument list with a negative level to access clients for\n# servers running in outer blocks.\nproc r {args} {\n    set level 0\n    if {[string is integer [lindex $args 0]]} {\n        set level [lindex $args 0]\n        set args [lrange $args 1 end]\n    }\n    [srv $level \"client\"] {*}$args\n}\n\nproc reconnect {args} {\n    set level [lindex $args 0]\n    if {[string length $level] == 0 || ![string is integer $level]} {\n        set level 0\n    }\n\n    set srv [lindex $::servers end+$level]\n    set host [dict get $srv \"host\"]\n    set port [dict get $srv \"port\"]\n    set config [dict get $srv \"config\"]\n    set client [redis $host $port]\n    dict set srv \"client\" $client\n\n    # select the right db when we don't have to authenticate\n    if {![dict exists $config \"requirepass\"]} {\n        $client select 9\n    }\n\n    # re-set $srv in the servers list\n    lset ::servers end+$level $srv\n}\n\nproc redis_deferring_client {args} {\n    set level 0\n    if {[llength $args] > 0 && [string is integer [lindex $args 0]]} {\n        set level [lindex $args 0]\n        set args [lrange $args 1 end]\n    }\n\n    # create client that defers reading reply\n    set client [redis [srv $level \"host\"] [srv $level \"port\"] 1]\n\n    # select the right db and read the response (OK)\n    $client select 9\n    $client read\n    return $client\n}\n\n# Provide easy access to INFO properties. Same semantic as \"proc r\".\nproc s {args} {\n    set level 0\n    if {[string is integer [lindex $args 0]]} {\n        set level [lindex $args 0]\n        set args [lrange $args 1 end]\n    }\n    status [srv $level \"client\"] [lindex $args 0]\n}\n\nproc cleanup {} {\n    if {!$::quiet} {puts -nonewline \"Cleanup: may take some time... \"}\n    flush stdout\n    catch {exec rm -rf {*}[glob tests/tmp/redis.conf.*]}\n    catch {exec rm -rf {*}[glob tests/tmp/server.*]}\n    if {!$::quiet} {puts \"OK\"}\n}\n\nproc test_server_main {} {\n    cleanup\n    set tclsh [info nameofexecutable]\n    # Open a listening socket, trying different ports in order to find a\n    # non busy one.\n    set port [find_available_port 11111]\n    if {!$::quiet} {\n        puts \"Starting test server at port $port\"\n    }\n    socket -server accept_test_clients -myaddr 127.0.0.1 $port\n\n    # Start the client instances\n    set ::clients_pids {}\n    set start_port [expr {$::port+100}]\n    for {set j 0} {$j < $::numclients} {incr j} {\n        set start_port [find_available_port $start_port]\n        set p [exec $tclsh [info script] {*}$::argv \\\n            --client $port --port $start_port &]\n        lappend ::clients_pids $p\n        incr start_port 10\n    }\n\n    # Setup global state for the test server\n    set ::idle_clients {}\n    set ::active_clients {}\n    array set ::active_clients_task {}\n    array set ::clients_start_time {}\n    set ::clients_time_history {}\n    set ::failed_tests {}\n\n    # Enter the event loop to handle clients I/O\n    after 100 test_server_cron\n    vwait forever\n}\n\n# This function gets called 10 times per second.\nproc test_server_cron {} {\n    set elapsed [expr {[clock seconds]-$::last_progress}]\n\n    if {$elapsed > $::timeout} {\n        set err \"\\[[colorstr red TIMEOUT]\\]: clients state report follows.\"\n        puts $err\n        show_clients_state\n        kill_clients\n        force_kill_all_servers\n        the_end\n    }\n\n    after 100 test_server_cron\n}\n\nproc accept_test_clients {fd addr port} {\n    fconfigure $fd -encoding binary\n    fileevent $fd readable [list read_from_test_client $fd]\n}\n\n# This is the readable handler of our test server. Clients send us messages\n# in the form of a status code such and additional data. Supported\n# status types are:\n#\n# ready: the client is ready to execute the command. Only sent at client\n#        startup. The server will queue the client FD in the list of idle\n#        clients.\n# testing: just used to signal that a given test started.\n# ok: a test was executed with success.\n# err: a test was executed with an error.\n# exception: there was a runtime exception while executing the test.\n# done: all the specified test file was processed, this test client is\n#       ready to accept a new task.\nproc read_from_test_client fd {\n    set bytes [gets $fd]\n    set payload [read $fd $bytes]\n    foreach {status data} $payload break\n    set ::last_progress [clock seconds]\n\n    if {$status eq {ready}} {\n        if {!$::quiet} {\n            puts \"\\[$status\\]: $data\"\n        }\n        signal_idle_client $fd\n    } elseif {$status eq {done}} {\n        set elapsed [expr {[clock seconds]-$::clients_start_time($fd)}]\n        set all_tests_count [llength $::all_tests]\n        set running_tests_count [expr {[llength $::active_clients]-1}]\n        set completed_tests_count [expr {$::next_test-$running_tests_count}]\n        puts \"\\[$completed_tests_count/$all_tests_count [colorstr yellow $status]\\]: $data ($elapsed seconds)\"\n        lappend ::clients_time_history $elapsed $data\n        signal_idle_client $fd\n        set ::active_clients_task($fd) DONE\n    } elseif {$status eq {ok}} {\n        if {!$::quiet} {\n            puts \"\\[[colorstr green $status]\\]: $data\"\n        }\n        set ::active_clients_task($fd) \"(OK) $data\"\n    } elseif {$status eq {err}} {\n        set err \"\\[[colorstr red $status]\\]: $data\"\n        puts $err\n        lappend ::failed_tests $err\n        set ::active_clients_task($fd) \"(ERR) $data\"\n    } elseif {$status eq {exception}} {\n        puts \"\\[[colorstr red $status]\\]: $data\"\n        kill_clients\n        force_kill_all_servers\n        exit 1\n    } elseif {$status eq {testing}} {\n        set ::active_clients_task($fd) \"(IN PROGRESS) $data\"\n    } elseif {$status eq {server-spawned}} {\n        lappend ::active_servers $data\n    } elseif {$status eq {server-killed}} {\n        set ::active_servers [lsearch -all -inline -not -exact $::active_servers $data]\n    } else {\n        if {!$::quiet} {\n            puts \"\\[$status\\]: $data\"\n        }\n    }\n}\n\nproc show_clients_state {} {\n    # The following loop is only useful for debugging tests that may\n    # enter an infinite loop. Commented out normally.\n    foreach x $::active_clients {\n        if {[info exist ::active_clients_task($x)]} {\n            puts \"$x => $::active_clients_task($x)\"\n        } else {\n            puts \"$x => ???\"\n        }\n    }\n}\n\nproc kill_clients {} {\n    foreach p $::clients_pids {\n        catch {exec kill $p}\n    }\n}\n\nproc force_kill_all_servers {} {\n    foreach p $::active_servers {\n        puts \"Killing still running Redis server $p\"\n        catch {exec kill -9 $p}\n    }\n}\n\n# A new client is idle. Remove it from the list of active clients and\n# if there are still test units to run, launch them.\nproc signal_idle_client fd {\n    # Remove this fd from the list of active clients.\n    set ::active_clients \\\n        [lsearch -all -inline -not -exact $::active_clients $fd]\n\n    if 0 {show_clients_state}\n\n    # New unit to process?\n    if {$::next_test != [llength $::all_tests]} {\n        if {!$::quiet} {\n            puts [colorstr bold-white \"Testing [lindex $::all_tests $::next_test]\"]\n            set ::active_clients_task($fd) \"ASSIGNED: $fd ([lindex $::all_tests $::next_test])\"\n        }\n        set ::clients_start_time($fd) [clock seconds]\n        send_data_packet $fd run [lindex $::all_tests $::next_test]\n        lappend ::active_clients $fd\n        incr ::next_test\n    } else {\n        lappend ::idle_clients $fd\n        if {[llength $::active_clients] == 0} {\n            the_end\n        }\n    }\n}\n\n# The the_end function gets called when all the test units were already\n# executed, so the test finished.\nproc the_end {} {\n    # TODO: print the status, exit with the rigth exit code.\n    puts \"\\n                   The End\\n\"\n    puts \"Execution time of different units:\"\n    foreach {time name} $::clients_time_history {\n        puts \"  $time seconds - $name\"\n    }\n    if {[llength $::failed_tests]} {\n        puts \"\\n[colorstr bold-red {!!! WARNING}] The following tests failed:\\n\"\n        foreach failed $::failed_tests {\n            puts \"*** $failed\"\n        }\n        cleanup\n        exit 1\n    } else {\n        puts \"\\n[colorstr bold-white {\\o/}] [colorstr bold-green {All tests passed without errors!}]\\n\"\n        cleanup\n        exit 0\n    }\n}\n\n# The client is not even driven (the test server is instead) as we just need\n# to read the command, execute, reply... all this in a loop.\nproc test_client_main server_port {\n    set ::test_server_fd [socket localhost $server_port]\n    fconfigure $::test_server_fd -encoding binary\n    send_data_packet $::test_server_fd ready [pid]\n    while 1 {\n        set bytes [gets $::test_server_fd]\n        set payload [read $::test_server_fd $bytes]\n        foreach {cmd data} $payload break\n        if {$cmd eq {run}} {\n            execute_tests $data\n        } else {\n            error \"Unknown test client command: $cmd\"\n        }\n    }\n}\n\nproc send_data_packet {fd status data} {\n    set payload [list $status $data]\n    puts $fd [string length $payload]\n    puts -nonewline $fd $payload\n    flush $fd\n}\n\nproc print_help_screen {} {\n    puts [join {\n        \"--valgrind         Run the test over valgrind.\"\n        \"--accurate         Run slow randomized tests for more iterations.\"\n        \"--quiet            Don't show individual tests.\"\n        \"--single <unit>    Just execute the specified unit (see next option).\"\n        \"--list-tests       List all the available test units.\"\n        \"--clients <num>    Number of test clients (default 16).\"\n        \"--timeout <sec>    Test timeout in seconds (default 10 min).\"\n        \"--force-failure    Force the execution of a test that always fails.\"\n        \"--help             Print this help screen.\"\n    } \"\\n\"]\n}\n\n# parse arguments\nfor {set j 0} {$j < [llength $argv]} {incr j} {\n    set opt [lindex $argv $j]\n    set arg [lindex $argv [expr $j+1]]\n    if {$opt eq {--tags}} {\n        foreach tag $arg {\n            if {[string index $tag 0] eq \"-\"} {\n                lappend ::denytags [string range $tag 1 end]\n            } else {\n                lappend ::allowtags $tag\n            }\n        }\n        incr j\n    } elseif {$opt eq {--valgrind}} {\n        set ::valgrind 1\n    } elseif {$opt eq {--quiet}} {\n        set ::quiet 1\n    } elseif {$opt eq {--host}} {\n        set ::external 1\n        set ::host $arg\n        incr j\n    } elseif {$opt eq {--port}} {\n        set ::port $arg\n        incr j\n    } elseif {$opt eq {--accurate}} {\n        set ::accurate 1\n    } elseif {$opt eq {--force-failure}} {\n        set ::force_failure 1\n    } elseif {$opt eq {--single}} {\n        set ::all_tests $arg\n        incr j\n    } elseif {$opt eq {--list-tests}} {\n        foreach t $::all_tests {\n            puts $t\n        }\n        exit 0\n    } elseif {$opt eq {--client}} {\n        set ::client 1\n        set ::test_server_port $arg\n        incr j\n    } elseif {$opt eq {--clients}} {\n        set ::numclients $arg\n        incr j\n    } elseif {$opt eq {--timeout}} {\n        set ::timeout $arg\n        incr j\n    } elseif {$opt eq {--help}} {\n        print_help_screen\n        exit 0\n    } else {\n        puts \"Wrong argument: $opt\"\n        exit 1\n    }\n}\n\nproc attach_to_replication_stream {} {\n    set s [socket [srv 0 \"host\"] [srv 0 \"port\"]]\n    fconfigure $s -translation binary\n    puts -nonewline $s \"SYNC\\r\\n\"\n    flush $s\n\n    # Get the count\n    set count [gets $s]\n    set prefix [string range $count 0 0]\n    if {$prefix ne {$}} {\n        error \"attach_to_replication_stream error. Received '$count' as count.\"\n    }\n    set count [string range $count 1 end]\n\n    # Consume the bulk payload\n    while {$count} {\n        set buf [read $s $count]\n        set count [expr {$count-[string length $buf]}]\n    }\n    return $s\n}\n\nproc read_from_replication_stream {s} {\n    fconfigure $s -blocking 0\n    set attempt 0\n    while {[gets $s count] == -1} {\n        if {[incr attempt] == 10} return \"\"\n        after 100\n    }\n    fconfigure $s -blocking 1\n    set count [string range $count 1 end]\n\n    # Return a list of arguments for the command.\n    set res {}\n    for {set j 0} {$j < $count} {incr j} {\n        read $s 1\n        set arg [::redis::redis_bulk_read $s]\n        if {$j == 0} {set arg [string tolower $arg]}\n        lappend res $arg\n    }\n    return $res\n}\n\nproc assert_replication_stream {s patterns} {\n    for {set j 0} {$j < [llength $patterns]} {incr j} {\n        assert_match [lindex $patterns $j] [read_from_replication_stream $s]\n    }\n}\n\nproc close_replication_stream {s} {\n    close $s\n}\n\n# With the parallel test running multiple Redis instances at the same time\n# we need a fast enough computer, otherwise a lot of tests may generate\n# false positives.\n# If the computer is too slow we revert the sequential test without any\n# parallelism, that is, clients == 1.\nproc is_a_slow_computer {} {\n    set start [clock milliseconds]\n    for {set j 0} {$j < 1000000} {incr j} {}\n    set elapsed [expr [clock milliseconds]-$start]\n    expr {$elapsed > 200}\n}\n\nif {$::client} {\n    if {[catch { test_client_main $::test_server_port } err]} {\n        set estr \"Executing test client: $err.\\n$::errorInfo\"\n        if {[catch {send_data_packet $::test_server_fd exception $estr}]} {\n            puts $estr\n        }\n        exit 1\n    }\n} else {\n    if {[is_a_slow_computer]} {\n        puts \"** SLOW COMPUTER ** Using a single client to avoid false positives.\"\n        set ::numclients 1\n    }\n\n    if {[catch { test_server_main } err]} {\n        if {[string length $err] > 0} {\n            # only display error when not generated by the test suite\n            if {$err ne \"exception\"} {\n                puts $::errorInfo\n            }\n            exit 1\n        }\n    }\n}\n"
  },
  {
    "path": "extern/deprecated/redis-2.8.21/tests/unit/aofrw.tcl",
    "content": "start_server {tags {\"aofrw\"}} {\n    # Enable the AOF\n    r config set appendonly yes\n    r config set auto-aof-rewrite-percentage 0 ; # Disable auto-rewrite.\n    waitForBgrewriteaof r\n\n    test {AOF rewrite during write load} {\n        # Start a write load for 10 seconds\n        set master [srv 0 client]\n        set master_host [srv 0 host]\n        set master_port [srv 0 port]\n        set load_handle0 [start_write_load $master_host $master_port 10]\n        set load_handle1 [start_write_load $master_host $master_port 10]\n        set load_handle2 [start_write_load $master_host $master_port 10]\n        set load_handle3 [start_write_load $master_host $master_port 10]\n        set load_handle4 [start_write_load $master_host $master_port 10]\n\n        # Make sure the instance is really receiving data\n        wait_for_condition 50 100 {\n            [r dbsize] > 0\n        } else {\n            fail \"No write load detected.\"\n        }\n\n        # After 3 seconds, start a rewrite, while the write load is still\n        # active.\n        after 3000\n        r bgrewriteaof\n        waitForBgrewriteaof r\n\n        # Let it run a bit more so that we'll append some data to the new\n        # AOF.\n        after 1000\n\n        # Stop the processes generating the load if they are still active\n        stop_write_load $load_handle0\n        stop_write_load $load_handle1\n        stop_write_load $load_handle2\n        stop_write_load $load_handle3\n        stop_write_load $load_handle4\n\n        # Make sure that we remain the only connected client.\n        # This step is needed to make sure there are no pending writes\n        # that will be processed between the two \"debug digest\" calls.\n        wait_for_condition 50 100 {\n            [llength [split [string trim [r client list]] \"\\n\"]] == 1\n        } else {\n            puts [r client list]\n            fail \"Clients generating loads are not disconnecting\"\n        }\n\n        # Get the data set digest\n        set d1 [r debug digest]\n\n        # Load the AOF\n        r debug loadaof\n        set d2 [r debug digest]\n\n        # Make sure they are the same\n        assert {$d1 eq $d2}\n    }\n}\n\nstart_server {tags {\"aofrw\"}} {\n    test {Turning off AOF kills the background writing child if any} {\n        r config set appendonly yes\n        waitForBgrewriteaof r\n        r multi\n        r bgrewriteaof\n        r config set appendonly no\n        r exec\n        wait_for_condition 50 100 {\n            [string match {*Killing*AOF*child*} [exec tail -n5 < [srv 0 stdout]]]\n        } else {\n            fail \"Can't find 'Killing AOF child' into recent logs\"\n        }\n    }\n\n    foreach d {string int} {\n        foreach e {ziplist linkedlist} {\n            test \"AOF rewrite of list with $e encoding, $d data\" {\n                r flushall\n                if {$e eq {ziplist}} {set len 10} else {set len 1000}\n                for {set j 0} {$j < $len} {incr j} {\n                    if {$d eq {string}} {\n                        set data [randstring 0 16 alpha]\n                    } else {\n                        set data [randomInt 4000000000]\n                    }\n                    r lpush key $data\n                }\n                assert_equal [r object encoding key] $e\n                set d1 [r debug digest]\n                r bgrewriteaof\n                waitForBgrewriteaof r\n                r debug loadaof\n                set d2 [r debug digest]\n                if {$d1 ne $d2} {\n                    error \"assertion:$d1 is not equal to $d2\"\n                }\n            }\n        }\n    }\n\n    foreach d {string int} {\n        foreach e {intset hashtable} {\n            test \"AOF rewrite of set with $e encoding, $d data\" {\n                r flushall\n                if {$e eq {intset}} {set len 10} else {set len 1000}\n                for {set j 0} {$j < $len} {incr j} {\n                    if {$d eq {string}} {\n                        set data [randstring 0 16 alpha]\n                    } else {\n                        set data [randomInt 4000000000]\n                    }\n                    r sadd key $data\n                }\n                if {$d ne {string}} {\n                    assert_equal [r object encoding key] $e\n                }\n                set d1 [r debug digest]\n                r bgrewriteaof\n                waitForBgrewriteaof r\n                r debug loadaof\n                set d2 [r debug digest]\n                if {$d1 ne $d2} {\n                    error \"assertion:$d1 is not equal to $d2\"\n                }\n            }\n        }\n    }\n\n    foreach d {string int} {\n        foreach e {ziplist hashtable} {\n            test \"AOF rewrite of hash with $e encoding, $d data\" {\n                r flushall\n                if {$e eq {ziplist}} {set len 10} else {set len 1000}\n                for {set j 0} {$j < $len} {incr j} {\n                    if {$d eq {string}} {\n                        set data [randstring 0 16 alpha]\n                    } else {\n                        set data [randomInt 4000000000]\n                    }\n                    r hset key $data $data\n                }\n                assert_equal [r object encoding key] $e\n                set d1 [r debug digest]\n                r bgrewriteaof\n                waitForBgrewriteaof r\n                r debug loadaof\n                set d2 [r debug digest]\n                if {$d1 ne $d2} {\n                    error \"assertion:$d1 is not equal to $d2\"\n                }\n            }\n        }\n    }\n\n    foreach d {string int} {\n        foreach e {ziplist skiplist} {\n            test \"AOF rewrite of zset with $e encoding, $d data\" {\n                r flushall\n                if {$e eq {ziplist}} {set len 10} else {set len 1000}\n                for {set j 0} {$j < $len} {incr j} {\n                    if {$d eq {string}} {\n                        set data [randstring 0 16 alpha]\n                    } else {\n                        set data [randomInt 4000000000]\n                    }\n                    r zadd key [expr rand()] $data\n                }\n                assert_equal [r object encoding key] $e\n                set d1 [r debug digest]\n                r bgrewriteaof\n                waitForBgrewriteaof r\n                r debug loadaof\n                set d2 [r debug digest]\n                if {$d1 ne $d2} {\n                    error \"assertion:$d1 is not equal to $d2\"\n                }\n            }\n        }\n    }\n\n    test {BGREWRITEAOF is delayed if BGSAVE is in progress} {\n        r multi\n        r bgsave\n        r bgrewriteaof\n        r info persistence\n        set res [r exec]\n        assert_match {*scheduled*} [lindex $res 1]\n        assert_match {*aof_rewrite_scheduled:1*} [lindex $res 2]\n        while {[string match {*aof_rewrite_scheduled:1*} [r info persistence]]} {\n            after 100\n        }\n    }\n\n    test {BGREWRITEAOF is refused if already in progress} {\n        catch {\n            r multi\n            r bgrewriteaof\n            r bgrewriteaof\n            r exec\n        } e\n        assert_match {*ERR*already*} $e\n        while {[string match {*aof_rewrite_scheduled:1*} [r info persistence]]} {\n            after 100\n        }\n    }\n}\n"
  },
  {
    "path": "extern/deprecated/redis-2.8.21/tests/unit/auth.tcl",
    "content": "start_server {tags {\"auth\"}} {\n    test {AUTH fails if there is no password configured server side} {\n        catch {r auth foo} err\n        set _ $err\n    } {ERR*no password*}\n}\n\nstart_server {tags {\"auth\"} overrides {requirepass foobar}} {\n    test {AUTH fails when a wrong password is given} {\n        catch {r auth wrong!} err\n        set _ $err\n    } {ERR*invalid password}\n\n    test {Arbitrary command gives an error when AUTH is required} {\n        catch {r set foo bar} err\n        set _ $err\n    } {NOAUTH*}\n\n    test {AUTH succeeds when the right password is given} {\n        r auth foobar\n    } {OK}\n\n    test {Once AUTH succeeded we can actually send commands to the server} {\n        r set foo 100\n        r incr foo\n    } {101}\n}\n"
  },
  {
    "path": "extern/deprecated/redis-2.8.21/tests/unit/basic.tcl",
    "content": "start_server {tags {\"basic\"}} {\n    test {DEL all keys to start with a clean DB} {\n        foreach key [r keys *] {r del $key}\n        r dbsize\n    } {0}\n\n    test {SET and GET an item} {\n        r set x foobar\n        r get x\n    } {foobar}\n\n    test {SET and GET an empty item} {\n        r set x {}\n        r get x\n    } {}\n\n    test {DEL against a single item} {\n        r del x\n        r get x\n    } {}\n\n    test {Vararg DEL} {\n        r set foo1 a\n        r set foo2 b\n        r set foo3 c\n        list [r del foo1 foo2 foo3 foo4] [r mget foo1 foo2 foo3]\n    } {3 {{} {} {}}}\n\n    test {KEYS with pattern} {\n        foreach key {key_x key_y key_z foo_a foo_b foo_c} {\n            r set $key hello\n        }\n        lsort [r keys foo*]\n    } {foo_a foo_b foo_c}\n\n    test {KEYS to get all keys} {\n        lsort [r keys *]\n    } {foo_a foo_b foo_c key_x key_y key_z}\n\n    test {DBSIZE} {\n        r dbsize\n    } {6}\n\n    test {DEL all keys} {\n        foreach key [r keys *] {r del $key}\n        r dbsize\n    } {0}\n\n    test {Very big payload in GET/SET} {\n        set buf [string repeat \"abcd\" 1000000]\n        r set foo $buf\n        r get foo\n    } [string repeat \"abcd\" 1000000]\n\n    tags {\"slow\"} {\n        test {Very big payload random access} {\n            set err {}\n            array set payload {}\n            for {set j 0} {$j < 100} {incr j} {\n                set size [expr 1+[randomInt 100000]]\n                set buf [string repeat \"pl-$j\" $size]\n                set payload($j) $buf\n                r set bigpayload_$j $buf\n            }\n            for {set j 0} {$j < 1000} {incr j} {\n                set index [randomInt 100]\n                set buf [r get bigpayload_$index]\n                if {$buf != $payload($index)} {\n                    set err \"Values differ: I set '$payload($index)' but I read back '$buf'\"\n                    break\n                }\n            }\n            unset payload\n            set _ $err\n        } {}\n\n        test {SET 10000 numeric keys and access all them in reverse order} {\n            set err {}\n            for {set x 0} {$x < 10000} {incr x} {\n                r set $x $x\n            }\n            set sum 0\n            for {set x 9999} {$x >= 0} {incr x -1} {\n                set val [r get $x]\n                if {$val ne $x} {\n                    set err \"Element at position $x is $val instead of $x\"\n                    break\n                }\n            }\n            set _ $err\n        } {}\n\n        test {DBSIZE should be 10101 now} {\n            r dbsize\n        } {10101}\n    }\n\n    test {INCR against non existing key} {\n        set res {}\n        append res [r incr novar]\n        append res [r get novar]\n    } {11}\n\n    test {INCR against key created by incr itself} {\n        r incr novar\n    } {2}\n\n    test {INCR against key originally set with SET} {\n        r set novar 100\n        r incr novar\n    } {101}\n\n    test {INCR over 32bit value} {\n        r set novar 17179869184\n        r incr novar\n    } {17179869185}\n\n    test {INCRBY over 32bit value with over 32bit increment} {\n        r set novar 17179869184\n        r incrby novar 17179869184\n    } {34359738368}\n\n    test {INCR fails against key with spaces (left)} {\n        r set novar \"    11\"\n        catch {r incr novar} err\n        format $err\n    } {ERR*}\n\n    test {INCR fails against key with spaces (right)} {\n        r set novar \"11    \"\n        catch {r incr novar} err\n        format $err\n    } {ERR*}\n\n    test {INCR fails against key with spaces (both)} {\n        r set novar \"    11    \"\n        catch {r incr novar} err\n        format $err\n    } {ERR*}\n\n    test {INCR fails against a key holding a list} {\n        r rpush mylist 1\n        catch {r incr mylist} err\n        r rpop mylist\n        format $err\n    } {WRONGTYPE*}\n\n    test {DECRBY over 32bit value with over 32bit increment, negative res} {\n        r set novar 17179869184\n        r decrby novar 17179869185\n    } {-1}\n\n    test {INCRBYFLOAT against non existing key} {\n        r del novar\n        list    [roundFloat [r incrbyfloat novar 1]] \\\n                [roundFloat [r get novar]] \\\n                [roundFloat [r incrbyfloat novar 0.25]] \\\n                [roundFloat [r get novar]]\n    } {1 1 1.25 1.25}\n\n    test {INCRBYFLOAT against key originally set with SET} {\n        r set novar 1.5\n        roundFloat [r incrbyfloat novar 1.5]\n    } {3}\n\n    test {INCRBYFLOAT over 32bit value} {\n        r set novar 17179869184\n        r incrbyfloat novar 1.5\n    } {17179869185.5}\n\n    test {INCRBYFLOAT over 32bit value with over 32bit increment} {\n        r set novar 17179869184\n        r incrbyfloat novar 17179869184\n    } {34359738368}\n\n    test {INCRBYFLOAT fails against key with spaces (left)} {\n        set err {}\n        r set novar \"    11\"\n        catch {r incrbyfloat novar 1.0} err\n        format $err\n    } {ERR*valid*}\n\n    test {INCRBYFLOAT fails against key with spaces (right)} {\n        set err {}\n        r set novar \"11    \"\n        catch {r incrbyfloat novar 1.0} err\n        format $err\n    } {ERR*valid*}\n\n    test {INCRBYFLOAT fails against key with spaces (both)} {\n        set err {}\n        r set novar \" 11 \"\n        catch {r incrbyfloat novar 1.0} err\n        format $err\n    } {ERR*valid*}\n\n    test {INCRBYFLOAT fails against a key holding a list} {\n        r del mylist\n        set err {}\n        r rpush mylist 1\n        catch {r incrbyfloat mylist 1.0} err\n        r del mylist\n        format $err\n    } {WRONGTYPE*}\n\n    test {INCRBYFLOAT does not allow NaN or Infinity} {\n        r set foo 0\n        set err {}\n        catch {r incrbyfloat foo +inf} err\n        set err\n        # p.s. no way I can force NaN to test it from the API because\n        # there is no way to increment / decrement by infinity nor to\n        # perform divisions.\n    } {ERR*would produce*}\n\n    test {INCRBYFLOAT decrement} {\n        r set foo 1\n        roundFloat [r incrbyfloat foo -1.1]\n    } {-0.1}\n\n    test \"SETNX target key missing\" {\n        r del novar\n        assert_equal 1 [r setnx novar foobared]\n        assert_equal \"foobared\" [r get novar]\n    }\n\n    test \"SETNX target key exists\" {\n        r set novar foobared\n        assert_equal 0 [r setnx novar blabla]\n        assert_equal \"foobared\" [r get novar]\n    }\n\n    test \"SETNX against not-expired volatile key\" {\n        r set x 10\n        r expire x 10000\n        assert_equal 0 [r setnx x 20]\n        assert_equal 10 [r get x]\n    }\n\n    test \"SETNX against expired volatile key\" {\n        # Make it very unlikely for the key this test uses to be expired by the\n        # active expiry cycle. This is tightly coupled to the implementation of\n        # active expiry and dbAdd() but currently the only way to test that\n        # SETNX expires a key when it should have been.\n        for {set x 0} {$x < 9999} {incr x} {\n            r setex key-$x 3600 value\n        }\n\n        # This will be one of 10000 expiring keys. A cycle is executed every\n        # 100ms, sampling 10 keys for being expired or not.  This key will be\n        # expired for at most 1s when we wait 2s, resulting in a total sample\n        # of 100 keys. The probability of the success of this test being a\n        # false positive is therefore approx. 1%.\n        r set x 10\n        r expire x 1\n\n        # Wait for the key to expire\n        after 2000\n\n        assert_equal 1 [r setnx x 20]\n        assert_equal 20 [r get x]\n    }\n\n    test \"DEL against expired key\" {\n        r debug set-active-expire 0\n        r setex keyExpire 1 valExpire\n        after 1100\n        assert_equal 0 [r del keyExpire]\n        r debug set-active-expire 1\n    }\n\n    test {EXISTS} {\n        set res {}\n        r set newkey test\n        append res [r exists newkey]\n        r del newkey\n        append res [r exists newkey]\n    } {10}\n\n    test {Zero length value in key. SET/GET/EXISTS} {\n        r set emptykey {}\n        set res [r get emptykey]\n        append res [r exists emptykey]\n        r del emptykey\n        append res [r exists emptykey]\n    } {10}\n\n    test {Commands pipelining} {\n        set fd [r channel]\n        puts -nonewline $fd \"SET k1 xyzk\\r\\nGET k1\\r\\nPING\\r\\n\"\n        flush $fd\n        set res {}\n        append res [string match OK* [r read]]\n        append res [r read]\n        append res [string match PONG* [r read]]\n        format $res\n    } {1xyzk1}\n\n    test {Non existing command} {\n        catch {r foobaredcommand} err\n        string match ERR* $err\n    } {1}\n\n    test {RENAME basic usage} {\n        r set mykey hello\n        r rename mykey mykey1\n        r rename mykey1 mykey2\n        r get mykey2\n    } {hello}\n\n    test {RENAME source key should no longer exist} {\n        r exists mykey\n    } {0}\n\n    test {RENAME against already existing key} {\n        r set mykey a\n        r set mykey2 b\n        r rename mykey2 mykey\n        set res [r get mykey]\n        append res [r exists mykey2]\n    } {b0}\n\n    test {RENAMENX basic usage} {\n        r del mykey\n        r del mykey2\n        r set mykey foobar\n        r renamenx mykey mykey2\n        set res [r get mykey2]\n        append res [r exists mykey]\n    } {foobar0}\n\n    test {RENAMENX against already existing key} {\n        r set mykey foo\n        r set mykey2 bar\n        r renamenx mykey mykey2\n    } {0}\n\n    test {RENAMENX against already existing key (2)} {\n        set res [r get mykey]\n        append res [r get mykey2]\n    } {foobar}\n\n    test {RENAME against non existing source key} {\n        catch {r rename nokey foobar} err\n        format $err\n    } {ERR*}\n\n    test {RENAME where source and dest key is the same} {\n        catch {r rename mykey mykey} err\n        format $err\n    } {ERR*}\n\n    test {RENAME with volatile key, should move the TTL as well} {\n        r del mykey mykey2\n        r set mykey foo\n        r expire mykey 100\n        assert {[r ttl mykey] > 95 && [r ttl mykey] <= 100}\n        r rename mykey mykey2\n        assert {[r ttl mykey2] > 95 && [r ttl mykey2] <= 100}\n    }\n\n    test {RENAME with volatile key, should not inherit TTL of target key} {\n        r del mykey mykey2\n        r set mykey foo\n        r set mykey2 bar\n        r expire mykey2 100\n        assert {[r ttl mykey] == -1 && [r ttl mykey2] > 0}\n        r rename mykey mykey2\n        r ttl mykey2\n    } {-1}\n\n    test {DEL all keys again (DB 0)} {\n        foreach key [r keys *] {\n            r del $key\n        }\n        r dbsize\n    } {0}\n\n    test {DEL all keys again (DB 1)} {\n        r select 10\n        foreach key [r keys *] {\n            r del $key\n        }\n        set res [r dbsize]\n        r select 9\n        format $res\n    } {0}\n\n    test {MOVE basic usage} {\n        r set mykey foobar\n        r move mykey 10\n        set res {}\n        lappend res [r exists mykey]\n        lappend res [r dbsize]\n        r select 10\n        lappend res [r get mykey]\n        lappend res [r dbsize]\n        r select 9\n        format $res\n    } [list 0 0 foobar 1]\n\n    test {MOVE against key existing in the target DB} {\n        r set mykey hello\n        r move mykey 10\n    } {0}\n\n    test {MOVE against non-integer DB (#1428)} {\n        r set mykey hello\n        catch {r move mykey notanumber} e\n        set e\n    } {*ERR*index out of range}\n\n    test {SET/GET keys in different DBs} {\n        r set a hello\n        r set b world\n        r select 10\n        r set a foo\n        r set b bared\n        r select 9\n        set res {}\n        lappend res [r get a]\n        lappend res [r get b]\n        r select 10\n        lappend res [r get a]\n        lappend res [r get b]\n        r select 9\n        format $res\n    } {hello world foo bared}\n\n    test {MGET} {\n        r flushdb\n        r set foo BAR\n        r set bar FOO\n        r mget foo bar\n    } {BAR FOO}\n\n    test {MGET against non existing key} {\n        r mget foo baazz bar\n    } {BAR {} FOO}\n\n    test {MGET against non-string key} {\n        r sadd myset ciao\n        r sadd myset bau\n        r mget foo baazz bar myset\n    } {BAR {} FOO {}}\n\n    test {RANDOMKEY} {\n        r flushdb\n        r set foo x\n        r set bar y\n        set foo_seen 0\n        set bar_seen 0\n        for {set i 0} {$i < 100} {incr i} {\n            set rkey [r randomkey]\n            if {$rkey eq {foo}} {\n                set foo_seen 1\n            }\n            if {$rkey eq {bar}} {\n                set bar_seen 1\n            }\n        }\n        list $foo_seen $bar_seen\n    } {1 1}\n\n    test {RANDOMKEY against empty DB} {\n        r flushdb\n        r randomkey\n    } {}\n\n    test {RANDOMKEY regression 1} {\n        r flushdb\n        r set x 10\n        r del x\n        r randomkey\n    } {}\n\n    test {GETSET (set new value)} {\n        list [r getset foo xyz] [r get foo]\n    } {{} xyz}\n\n    test {GETSET (replace old value)} {\n        r set foo bar\n        list [r getset foo xyz] [r get foo]\n    } {bar xyz}\n\n    test {MSET base case} {\n        r mset x 10 y \"foo bar\" z \"x x x x x x x\\n\\n\\r\\n\"\n        r mget x y z\n    } [list 10 {foo bar} \"x x x x x x x\\n\\n\\r\\n\"]\n\n    test {MSET wrong number of args} {\n        catch {r mset x 10 y \"foo bar\" z} err\n        format $err\n    } {*wrong number*}\n\n    test {MSETNX with already existent key} {\n        list [r msetnx x1 xxx y2 yyy x 20] [r exists x1] [r exists y2]\n    } {0 0 0}\n\n    test {MSETNX with not existing keys} {\n        list [r msetnx x1 xxx y2 yyy] [r get x1] [r get y2]\n    } {1 xxx yyy}\n\n    test \"STRLEN against non-existing key\" {\n        assert_equal 0 [r strlen notakey]\n    }\n\n    test \"STRLEN against integer-encoded value\" {\n        r set myinteger -555\n        assert_equal 4 [r strlen myinteger]\n    }\n\n    test \"STRLEN against plain string\" {\n        r set mystring \"foozzz0123456789 baz\"\n        assert_equal 20 [r strlen mystring]\n    }\n\n    test \"SETBIT against non-existing key\" {\n        r del mykey\n        assert_equal 0 [r setbit mykey 1 1]\n        assert_equal [binary format B* 01000000] [r get mykey]\n    }\n\n    test \"SETBIT against string-encoded key\" {\n        # Ascii \"@\" is integer 64 = 01 00 00 00\n        r set mykey \"@\"\n\n        assert_equal 0 [r setbit mykey 2 1]\n        assert_equal [binary format B* 01100000] [r get mykey]\n        assert_equal 1 [r setbit mykey 1 0]\n        assert_equal [binary format B* 00100000] [r get mykey]\n    }\n\n    test \"SETBIT against integer-encoded key\" {\n        # Ascii \"1\" is integer 49 = 00 11 00 01\n        r set mykey 1\n        assert_encoding int mykey\n\n        assert_equal 0 [r setbit mykey 6 1]\n        assert_equal [binary format B* 00110011] [r get mykey]\n        assert_equal 1 [r setbit mykey 2 0]\n        assert_equal [binary format B* 00010011] [r get mykey]\n    }\n\n    test \"SETBIT against key with wrong type\" {\n        r del mykey\n        r lpush mykey \"foo\"\n        assert_error \"WRONGTYPE*\" {r setbit mykey 0 1}\n    }\n\n    test \"SETBIT with out of range bit offset\" {\n        r del mykey\n        assert_error \"*out of range*\" {r setbit mykey [expr 4*1024*1024*1024] 1}\n        assert_error \"*out of range*\" {r setbit mykey -1 1}\n    }\n\n    test \"SETBIT with non-bit argument\" {\n        r del mykey\n        assert_error \"*out of range*\" {r setbit mykey 0 -1}\n        assert_error \"*out of range*\" {r setbit mykey 0  2}\n        assert_error \"*out of range*\" {r setbit mykey 0 10}\n        assert_error \"*out of range*\" {r setbit mykey 0 20}\n    }\n\n    test \"SETBIT fuzzing\" {\n        set str \"\"\n        set len [expr 256*8]\n        r del mykey\n\n        for {set i 0} {$i < 2000} {incr i} {\n            set bitnum [randomInt $len]\n            set bitval [randomInt 2]\n            set fmt [format \"%%-%ds%%d%%-s\" $bitnum]\n            set head [string range $str 0 $bitnum-1]\n            set tail [string range $str $bitnum+1 end]\n            set str [string map {\" \" 0} [format $fmt $head $bitval $tail]]\n\n            r setbit mykey $bitnum $bitval\n            assert_equal [binary format B* $str] [r get mykey]\n        }\n    }\n\n    test \"GETBIT against non-existing key\" {\n        r del mykey\n        assert_equal 0 [r getbit mykey 0]\n    }\n\n    test \"GETBIT against string-encoded key\" {\n        # Single byte with 2nd and 3rd bit set\n        r set mykey \"`\"\n\n        # In-range\n        assert_equal 0 [r getbit mykey 0]\n        assert_equal 1 [r getbit mykey 1]\n        assert_equal 1 [r getbit mykey 2]\n        assert_equal 0 [r getbit mykey 3]\n\n        # Out-range\n        assert_equal 0 [r getbit mykey 8]\n        assert_equal 0 [r getbit mykey 100]\n        assert_equal 0 [r getbit mykey 10000]\n    }\n\n    test \"GETBIT against integer-encoded key\" {\n        r set mykey 1\n        assert_encoding int mykey\n\n        # Ascii \"1\" is integer 49 = 00 11 00 01\n        assert_equal 0 [r getbit mykey 0]\n        assert_equal 0 [r getbit mykey 1]\n        assert_equal 1 [r getbit mykey 2]\n        assert_equal 1 [r getbit mykey 3]\n\n        # Out-range\n        assert_equal 0 [r getbit mykey 8]\n        assert_equal 0 [r getbit mykey 100]\n        assert_equal 0 [r getbit mykey 10000]\n    }\n\n    test \"SETRANGE against non-existing key\" {\n        r del mykey\n        assert_equal 3 [r setrange mykey 0 foo]\n        assert_equal \"foo\" [r get mykey]\n\n        r del mykey\n        assert_equal 0 [r setrange mykey 0 \"\"]\n        assert_equal 0 [r exists mykey]\n\n        r del mykey\n        assert_equal 4 [r setrange mykey 1 foo]\n        assert_equal \"\\000foo\" [r get mykey]\n    }\n\n    test \"SETRANGE against string-encoded key\" {\n        r set mykey \"foo\"\n        assert_equal 3 [r setrange mykey 0 b]\n        assert_equal \"boo\" [r get mykey]\n\n        r set mykey \"foo\"\n        assert_equal 3 [r setrange mykey 0 \"\"]\n        assert_equal \"foo\" [r get mykey]\n\n        r set mykey \"foo\"\n        assert_equal 3 [r setrange mykey 1 b]\n        assert_equal \"fbo\" [r get mykey]\n\n        r set mykey \"foo\"\n        assert_equal 7 [r setrange mykey 4 bar]\n        assert_equal \"foo\\000bar\" [r get mykey]\n    }\n\n    test \"SETRANGE against integer-encoded key\" {\n        r set mykey 1234\n        assert_encoding int mykey\n        assert_equal 4 [r setrange mykey 0 2]\n        assert_encoding raw mykey\n        assert_equal 2234 [r get mykey]\n\n        # Shouldn't change encoding when nothing is set\n        r set mykey 1234\n        assert_encoding int mykey\n        assert_equal 4 [r setrange mykey 0 \"\"]\n        assert_encoding int mykey\n        assert_equal 1234 [r get mykey]\n\n        r set mykey 1234\n        assert_encoding int mykey\n        assert_equal 4 [r setrange mykey 1 3]\n        assert_encoding raw mykey\n        assert_equal 1334 [r get mykey]\n\n        r set mykey 1234\n        assert_encoding int mykey\n        assert_equal 6 [r setrange mykey 5 2]\n        assert_encoding raw mykey\n        assert_equal \"1234\\0002\" [r get mykey]\n    }\n\n    test \"SETRANGE against key with wrong type\" {\n        r del mykey\n        r lpush mykey \"foo\"\n        assert_error \"WRONGTYPE*\" {r setrange mykey 0 bar}\n    }\n\n    test \"SETRANGE with out of range offset\" {\n        r del mykey\n        assert_error \"*maximum allowed size*\" {r setrange mykey [expr 512*1024*1024-4] world}\n\n        r set mykey \"hello\"\n        assert_error \"*out of range*\" {r setrange mykey -1 world}\n        assert_error \"*maximum allowed size*\" {r setrange mykey [expr 512*1024*1024-4] world}\n    }\n\n    test \"GETRANGE against non-existing key\" {\n        r del mykey\n        assert_equal \"\" [r getrange mykey 0 -1]\n    }\n\n    test \"GETRANGE against string value\" {\n        r set mykey \"Hello World\"\n        assert_equal \"Hell\" [r getrange mykey 0 3]\n        assert_equal \"Hello World\" [r getrange mykey 0 -1]\n        assert_equal \"orld\" [r getrange mykey -4 -1]\n        assert_equal \"\" [r getrange mykey 5 3]\n        assert_equal \" World\" [r getrange mykey 5 5000]\n        assert_equal \"Hello World\" [r getrange mykey -5000 10000]\n    }\n\n    test \"GETRANGE against integer-encoded value\" {\n        r set mykey 1234\n        assert_equal \"123\" [r getrange mykey 0 2]\n        assert_equal \"1234\" [r getrange mykey 0 -1]\n        assert_equal \"234\" [r getrange mykey -3 -1]\n        assert_equal \"\" [r getrange mykey 5 3]\n        assert_equal \"4\" [r getrange mykey 3 5000]\n        assert_equal \"1234\" [r getrange mykey -5000 10000]\n    }\n\n    test \"GETRANGE fuzzing\" {\n        for {set i 0} {$i < 1000} {incr i} {\n            r set bin [set bin [randstring 0 1024 binary]]\n            set _start [set start [randomInt 1500]]\n            set _end [set end [randomInt 1500]]\n            if {$_start < 0} {set _start \"end-[abs($_start)-1]\"}\n            if {$_end < 0} {set _end \"end-[abs($_end)-1]\"}\n            assert_equal [string range $bin $_start $_end] [r getrange bin $start $end]\n        }\n    }\n\n    test {Extended SET can detect syntax errors} {\n        set e {}\n        catch {r set foo bar non-existing-option} e\n        set e\n    } {*syntax*}\n\n    test {Extended SET NX option} {\n        r del foo\n        set v1 [r set foo 1 nx]\n        set v2 [r set foo 2 nx]\n        list $v1 $v2 [r get foo]\n    } {OK {} 1}\n\n    test {Extended SET XX option} {\n        r del foo\n        set v1 [r set foo 1 xx]\n        r set foo bar\n        set v2 [r set foo 2 xx]\n        list $v1 $v2 [r get foo]\n    } {{} OK 2}\n\n    test {Extended SET EX option} {\n        r del foo\n        r set foo bar ex 10\n        set ttl [r ttl foo]\n        assert {$ttl <= 10 && $ttl > 5}\n    }\n\n    test {Extended SET PX option} {\n        r del foo\n        r set foo bar px 10000\n        set ttl [r ttl foo]\n        assert {$ttl <= 10 && $ttl > 5}\n    }\n\n    test {Extended SET using multiple options at once} {\n        r set foo val\n        assert {[r set foo bar xx px 10000] eq {OK}}\n        set ttl [r ttl foo]\n        assert {$ttl <= 10 && $ttl > 5}\n    }\n\n    test {KEYS * two times with long key, Github issue #1208} {\n        r flushdb\n        r set dlskeriewrioeuwqoirueioqwrueoqwrueqw test\n        r keys *\n        r keys *\n    } {dlskeriewrioeuwqoirueioqwrueoqwrueqw}\n\n    test {GETRANGE with huge ranges, Github issue #1844} {\n        r set foo bar\n        r getrange foo 0 4294967297\n    } {bar}\n}\n"
  },
  {
    "path": "extern/deprecated/redis-2.8.21/tests/unit/bitops.tcl",
    "content": "# Compare Redis commadns against Tcl implementations of the same commands.\nproc count_bits s {\n    binary scan $s b* bits\n    string length [regsub -all {0} $bits {}]\n}\n\nproc simulate_bit_op {op args} {\n    set maxlen 0\n    set j 0\n    set count [llength $args]\n    foreach a $args {\n        binary scan $a b* bits\n        set b($j) $bits\n        if {[string length $bits] > $maxlen} {\n            set maxlen [string length $bits]\n        }\n        incr j\n    }\n    for {set j 0} {$j < $count} {incr j} {\n        if {[string length $b($j)] < $maxlen} {\n            append b($j) [string repeat 0 [expr $maxlen-[string length $b($j)]]]\n        }\n    }\n    set out {}\n    for {set x 0} {$x < $maxlen} {incr x} {\n        set bit [string range $b(0) $x $x]\n        if {$op eq {not}} {set bit [expr {!$bit}]}\n        for {set j 1} {$j < $count} {incr j} {\n            set bit2 [string range $b($j) $x $x]\n            switch $op {\n                and {set bit [expr {$bit & $bit2}]}\n                or  {set bit [expr {$bit | $bit2}]}\n                xor {set bit [expr {$bit ^ $bit2}]}\n            }\n        }\n        append out $bit\n    }\n    binary format b* $out\n}\n\nstart_server {tags {\"bitops\"}} {\n    test {BITCOUNT returns 0 against non existing key} {\n        r bitcount no-key\n    } 0\n\n    catch {unset num}\n    foreach vec [list \"\" \"\\xaa\" \"\\x00\\x00\\xff\" \"foobar\" \"123\"] {\n        incr num\n        test \"BITCOUNT against test vector #$num\" {\n            r set str $vec\n            assert {[r bitcount str] == [count_bits $vec]}\n        }\n    }\n\n    test {BITCOUNT fuzzing without start/end} {\n        for {set j 0} {$j < 100} {incr j} {\n            set str [randstring 0 3000]\n            r set str $str\n            assert {[r bitcount str] == [count_bits $str]}\n        }\n    }\n\n    test {BITCOUNT fuzzing with start/end} {\n        for {set j 0} {$j < 100} {incr j} {\n            set str [randstring 0 3000]\n            r set str $str\n            set l [string length $str]\n            set start [randomInt $l]\n            set end [randomInt $l]\n            if {$start > $end} {\n                lassign [list $end $start] start end\n            }\n            assert {[r bitcount str $start $end] == [count_bits [string range $str $start $end]]}\n        }\n    }\n\n    test {BITCOUNT with start, end} {\n        r set s \"foobar\"\n        assert_equal [r bitcount s 0 -1] [count_bits \"foobar\"]\n        assert_equal [r bitcount s 1 -2] [count_bits \"ooba\"]\n        assert_equal [r bitcount s -2 1] [count_bits \"\"]\n        assert_equal [r bitcount s 0 1000] [count_bits \"foobar\"]\n    }\n\n    test {BITCOUNT syntax error #1} {\n        catch {r bitcount s 0} e\n        set e\n    } {ERR*syntax*}\n\n    test {BITCOUNT regression test for github issue #582} {\n        r del str\n        r setbit foo 0 1\n        if {[catch {r bitcount foo 0 4294967296} e]} {\n            assert_match {*ERR*out of range*} $e\n            set _ 1\n        } else {\n            set e\n        }\n    } {1}\n\n    test {BITCOUNT misaligned prefix} {\n        r del str\n        r set str ab\n        r bitcount str 1 -1\n    } {3}\n\n    test {BITCOUNT misaligned prefix + full words + remainder} {\n        r del str\n        r set str __PPxxxxxxxxxxxxxxxxRR__\n        r bitcount str 2 -3\n    } {74}\n\n    test {BITOP NOT (empty string)} {\n        r set s \"\"\n        r bitop not dest s\n        r get dest\n    } {}\n\n    test {BITOP NOT (known string)} {\n        r set s \"\\xaa\\x00\\xff\\x55\"\n        r bitop not dest s\n        r get dest\n    } \"\\x55\\xff\\x00\\xaa\"\n\n    test {BITOP where dest and target are the same key} {\n        r set s \"\\xaa\\x00\\xff\\x55\"\n        r bitop not s s\n        r get s\n    } \"\\x55\\xff\\x00\\xaa\"\n\n    test {BITOP AND|OR|XOR don't change the string with single input key} {\n        r set a \"\\x01\\x02\\xff\"\n        r bitop and res1 a\n        r bitop or  res2 a\n        r bitop xor res3 a\n        list [r get res1] [r get res2] [r get res3]\n    } [list \"\\x01\\x02\\xff\" \"\\x01\\x02\\xff\" \"\\x01\\x02\\xff\"]\n\n    test {BITOP missing key is considered a stream of zero} {\n        r set a \"\\x01\\x02\\xff\"\n        r bitop and res1 no-suck-key a\n        r bitop or  res2 no-suck-key a no-such-key\n        r bitop xor res3 no-such-key a\n        list [r get res1] [r get res2] [r get res3]\n    } [list \"\\x00\\x00\\x00\" \"\\x01\\x02\\xff\" \"\\x01\\x02\\xff\"]\n\n    test {BITOP shorter keys are zero-padded to the key with max length} {\n        r set a \"\\x01\\x02\\xff\\xff\"\n        r set b \"\\x01\\x02\\xff\"\n        r bitop and res1 a b\n        r bitop or  res2 a b\n        r bitop xor res3 a b\n        list [r get res1] [r get res2] [r get res3]\n    } [list \"\\x01\\x02\\xff\\x00\" \"\\x01\\x02\\xff\\xff\" \"\\x00\\x00\\x00\\xff\"]\n\n    foreach op {and or xor} {\n        test \"BITOP $op fuzzing\" {\n            for {set i 0} {$i < 10} {incr i} {\n                r flushall\n                set vec {}\n                set veckeys {}\n                set numvec [expr {[randomInt 10]+1}]\n                for {set j 0} {$j < $numvec} {incr j} {\n                    set str [randstring 0 1000]\n                    lappend vec $str\n                    lappend veckeys vector_$j\n                    r set vector_$j $str\n                }\n                r bitop $op target {*}$veckeys\n                assert_equal [r get target] [simulate_bit_op $op {*}$vec]\n            }\n        }\n    }\n\n    test {BITOP NOT fuzzing} {\n        for {set i 0} {$i < 10} {incr i} {\n            r flushall\n            set str [randstring 0 1000]\n            r set str $str\n            r bitop not target str\n            assert_equal [r get target] [simulate_bit_op not $str]\n        }\n    }\n\n    test {BITOP with integer encoded source objects} {\n        r set a 1\n        r set b 2\n        r bitop xor dest a b a\n        r get dest\n    } {2}\n\n    test {BITOP with non string source key} {\n        r del c\n        r set a 1\n        r set b 2\n        r lpush c foo\n        catch {r bitop xor dest a b c d} e\n        set e\n    } {WRONGTYPE*}\n\n    test {BITOP with empty string after non empty string (issue #529)} {\n        r flushdb\n        r set a \"\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\"\n        r bitop or x a b\n    } {32}\n\n    test {BITPOS bit=0 with empty key returns 0} {\n        r del str\n        r bitpos str 0\n    } {0}\n\n    test {BITPOS bit=1 with empty key returns -1} {\n        r del str\n        r bitpos str 1\n    } {-1}\n\n    test {BITPOS bit=0 with string less than 1 word works} {\n        r set str \"\\xff\\xf0\\x00\"\n        r bitpos str 0\n    } {12}\n\n    test {BITPOS bit=1 with string less than 1 word works} {\n        r set str \"\\x00\\x0f\\x00\"\n        r bitpos str 1\n    } {12}\n\n    test {BITPOS bit=0 starting at unaligned address} {\n        r set str \"\\xff\\xf0\\x00\"\n        r bitpos str 0 1\n    } {12}\n\n    test {BITPOS bit=1 starting at unaligned address} {\n        r set str \"\\x00\\x0f\\xff\"\n        r bitpos str 1 1\n    } {12}\n\n    test {BITPOS bit=0 unaligned+full word+reminder} {\n        r del str\n        r set str \"\\xff\\xff\\xff\" ; # Prefix\n        # Followed by two (or four in 32 bit systems) full words\n        r append str \"\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xff\"\n        r append str \"\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xff\"\n        r append str \"\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xff\"\n        # First zero bit.\n        r append str \"\\x0f\"\n        assert {[r bitpos str 0] == 216}\n        assert {[r bitpos str 0 1] == 216}\n        assert {[r bitpos str 0 2] == 216}\n        assert {[r bitpos str 0 3] == 216}\n        assert {[r bitpos str 0 4] == 216}\n        assert {[r bitpos str 0 5] == 216}\n        assert {[r bitpos str 0 6] == 216}\n        assert {[r bitpos str 0 7] == 216}\n        assert {[r bitpos str 0 8] == 216}\n    }\n\n    test {BITPOS bit=1 unaligned+full word+reminder} {\n        r del str\n        r set str \"\\x00\\x00\\x00\" ; # Prefix\n        # Followed by two (or four in 32 bit systems) full words\n        r append str \"\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\"\n        r append str \"\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\"\n        r append str \"\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\"\n        # First zero bit.\n        r append str \"\\xf0\"\n        assert {[r bitpos str 1] == 216}\n        assert {[r bitpos str 1 1] == 216}\n        assert {[r bitpos str 1 2] == 216}\n        assert {[r bitpos str 1 3] == 216}\n        assert {[r bitpos str 1 4] == 216}\n        assert {[r bitpos str 1 5] == 216}\n        assert {[r bitpos str 1 6] == 216}\n        assert {[r bitpos str 1 7] == 216}\n        assert {[r bitpos str 1 8] == 216}\n    }\n\n    test {BITPOS bit=1 returns -1 if string is all 0 bits} {\n        r set str \"\"\n        for {set j 0} {$j < 20} {incr j} {\n            assert {[r bitpos str 1] == -1}\n            r append str \"\\x00\"\n        }\n    }\n\n    test {BITPOS bit=0 works with intervals} {\n        r set str \"\\x00\\xff\\x00\"\n        assert {[r bitpos str 0 0 -1] == 0}\n        assert {[r bitpos str 0 1 -1] == 16}\n        assert {[r bitpos str 0 2 -1] == 16}\n        assert {[r bitpos str 0 2 200] == 16}\n        assert {[r bitpos str 0 1 1] == -1}\n    }\n\n    test {BITPOS bit=1 works with intervals} {\n        r set str \"\\x00\\xff\\x00\"\n        assert {[r bitpos str 1 0 -1] == 8}\n        assert {[r bitpos str 1 1 -1] == 8}\n        assert {[r bitpos str 1 2 -1] == -1}\n        assert {[r bitpos str 1 2 200] == -1}\n        assert {[r bitpos str 1 1 1] == 8}\n    }\n\n    test {BITPOS bit=0 changes behavior if end is given} {\n        r set str \"\\xff\\xff\\xff\"\n        assert {[r bitpos str 0] == 24}\n        assert {[r bitpos str 0 0] == 24}\n        assert {[r bitpos str 0 0 -1] == -1}\n    }\n\n    test {BITPOS bit=1 fuzzy testing using SETBIT} {\n        r del str\n        set max 524288; # 64k\n        set first_one_pos -1\n        for {set j 0} {$j < 1000} {incr j} {\n            assert {[r bitpos str 1] == $first_one_pos}\n            set pos [randomInt $max]\n            r setbit str $pos 1\n            if {$first_one_pos == -1 || $first_one_pos > $pos} {\n                # Update the position of the first 1 bit in the array\n                # if the bit we set is on the left of the previous one.\n                set first_one_pos $pos\n            }\n        }\n    }\n\n    test {BITPOS bit=0 fuzzy testing using SETBIT} {\n        set max 524288; # 64k\n        set first_zero_pos $max\n        r set str [string repeat \"\\xff\" [expr $max/8]]\n        for {set j 0} {$j < 1000} {incr j} {\n            assert {[r bitpos str 0] == $first_zero_pos}\n            set pos [randomInt $max]\n            r setbit str $pos 0\n            if {$first_zero_pos > $pos} {\n                # Update the position of the first 0 bit in the array\n                # if the bit we clear is on the left of the previous one.\n                set first_zero_pos $pos\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "extern/deprecated/redis-2.8.21/tests/unit/dump.tcl",
    "content": "start_server {tags {\"dump\"}} {\n    test {DUMP / RESTORE are able to serialize / unserialize a simple key} {\n        r set foo bar\n        set encoded [r dump foo]\n        r del foo\n        list [r exists foo] [r restore foo 0 $encoded] [r ttl foo] [r get foo]\n    } {0 OK -1 bar}\n\n    test {RESTORE can set an arbitrary expire to the materialized key} {\n        r set foo bar\n        set encoded [r dump foo]\n        r del foo\n        r restore foo 5000 $encoded\n        set ttl [r pttl foo]\n        assert {$ttl >= 3000 && $ttl <= 5000}\n        r get foo\n    } {bar}\n\n    test {RESTORE can set an expire that overflows a 32 bit integer} {\n        r set foo bar\n        set encoded [r dump foo]\n        r del foo\n        r restore foo 2569591501 $encoded\n        set ttl [r pttl foo]\n        assert {$ttl >= (2569591501-3000) && $ttl <= 2569591501}\n        r get foo\n    } {bar}\n\n    test {RESTORE returns an error of the key already exists} {\n        r set foo bar\n        set e {}\n        catch {r restore foo 0 \"...\"} e\n        set e\n    } {*is busy*}\n\n    test {DUMP of non existing key returns nil} {\n        r dump nonexisting_key\n    } {}\n\n    test {MIGRATE is able to migrate a key between two instances} {\n        set first [srv 0 client]\n        r set key \"Some Value\"\n        start_server {tags {\"repl\"}} {\n            set second [srv 0 client]\n            set second_host [srv 0 host]\n            set second_port [srv 0 port]\n\n            assert {[$first exists key] == 1}\n            assert {[$second exists key] == 0}\n            set ret [r -1 migrate $second_host $second_port key 9 5000]\n            assert {$ret eq {OK}}\n            assert {[$first exists key] == 0}\n            assert {[$second exists key] == 1}\n            assert {[$second get key] eq {Some Value}}\n            assert {[$second ttl key] == -1}\n        }\n    }\n\n    test {MIGRATE propagates TTL correctly} {\n        set first [srv 0 client]\n        r set key \"Some Value\"\n        start_server {tags {\"repl\"}} {\n            set second [srv 0 client]\n            set second_host [srv 0 host]\n            set second_port [srv 0 port]\n\n            assert {[$first exists key] == 1}\n            assert {[$second exists key] == 0}\n            $first expire key 10\n            set ret [r -1 migrate $second_host $second_port key 9 5000]\n            assert {$ret eq {OK}}\n            assert {[$first exists key] == 0}\n            assert {[$second exists key] == 1}\n            assert {[$second get key] eq {Some Value}}\n            assert {[$second ttl key] >= 7 && [$second ttl key] <= 10}\n        }\n    }\n\n    test {MIGRATE can correctly transfer large values} {\n        set first [srv 0 client]\n        r del key\n        for {set j 0} {$j < 5000} {incr j} {\n            r rpush key 1 2 3 4 5 6 7 8 9 10\n            r rpush key \"item 1\" \"item 2\" \"item 3\" \"item 4\" \"item 5\" \\\n                        \"item 6\" \"item 7\" \"item 8\" \"item 9\" \"item 10\"\n        }\n        assert {[string length [r dump key]] > (1024*64)}\n        start_server {tags {\"repl\"}} {\n            set second [srv 0 client]\n            set second_host [srv 0 host]\n            set second_port [srv 0 port]\n\n            assert {[$first exists key] == 1}\n            assert {[$second exists key] == 0}\n            set ret [r -1 migrate $second_host $second_port key 9 10000]\n            assert {$ret eq {OK}}\n            assert {[$first exists key] == 0}\n            assert {[$second exists key] == 1}\n            assert {[$second ttl key] == -1}\n            assert {[$second llen key] == 5000*20}\n        }\n    }\n\n    test {MIGRATE can correctly transfer hashes} {\n        set first [srv 0 client]\n        r del key\n        r hmset key field1 \"item 1\" field2 \"item 2\" field3 \"item 3\" \\\n                    field4 \"item 4\" field5 \"item 5\" field6 \"item 6\"\n        start_server {tags {\"repl\"}} {\n            set second [srv 0 client]\n            set second_host [srv 0 host]\n            set second_port [srv 0 port]\n\n            assert {[$first exists key] == 1}\n            assert {[$second exists key] == 0}\n            set ret [r -1 migrate $second_host $second_port key 9 10000]\n            assert {$ret eq {OK}}\n            assert {[$first exists key] == 0}\n            assert {[$second exists key] == 1}\n            assert {[$second ttl key] == -1}\n        }\n    }\n\n    test {MIGRATE timeout actually works} {\n        set first [srv 0 client]\n        r set key \"Some Value\"\n        start_server {tags {\"repl\"}} {\n            set second [srv 0 client]\n            set second_host [srv 0 host]\n            set second_port [srv 0 port]\n\n            assert {[$first exists key] == 1}\n            assert {[$second exists key] == 0}\n\n            set rd [redis_deferring_client]\n            $rd debug sleep 5.0 ; # Make second server unable to reply.\n            set e {}\n            catch {r -1 migrate $second_host $second_port key 9 1000} e\n            assert_match {IOERR*} $e\n        }\n    }\n}\n"
  },
  {
    "path": "extern/deprecated/redis-2.8.21/tests/unit/expire.tcl",
    "content": "start_server {tags {\"expire\"}} {\n    test {EXPIRE - set timeouts multiple times} {\n        r set x foobar\n        set v1 [r expire x 5]\n        set v2 [r ttl x]\n        set v3 [r expire x 10]\n        set v4 [r ttl x]\n        r expire x 2\n        list $v1 $v2 $v3 $v4\n    } {1 [45] 1 10}\n\n    test {EXPIRE - It should be still possible to read 'x'} {\n        r get x\n    } {foobar}\n\n    tags {\"slow\"} {\n        test {EXPIRE - After 2.1 seconds the key should no longer be here} {\n            after 2100\n            list [r get x] [r exists x]\n        } {{} 0}\n    }\n\n    test {EXPIRE - write on expire should work} {\n        r del x\n        r lpush x foo\n        r expire x 1000\n        r lpush x bar\n        r lrange x 0 -1\n    } {bar foo}\n\n    test {EXPIREAT - Check for EXPIRE alike behavior} {\n        r del x\n        r set x foo\n        r expireat x [expr [clock seconds]+15]\n        r ttl x\n    } {1[345]}\n\n    test {SETEX - Set + Expire combo operation. Check for TTL} {\n        r setex x 12 test\n        r ttl x\n    } {1[012]}\n\n    test {SETEX - Check value} {\n        r get x\n    } {test}\n\n    test {SETEX - Overwrite old key} {\n        r setex y 1 foo\n        r get y\n    } {foo}\n\n    tags {\"slow\"} {\n        test {SETEX - Wait for the key to expire} {\n            after 1100\n            r get y\n        } {}\n    }\n\n    test {SETEX - Wrong time parameter} {\n        catch {r setex z -10 foo} e\n        set _ $e\n    } {*invalid expire*}\n\n    test {PERSIST can undo an EXPIRE} {\n        r set x foo\n        r expire x 50\n        list [r ttl x] [r persist x] [r ttl x] [r get x]\n    } {50 1 -1 foo}\n\n    test {PERSIST returns 0 against non existing or non volatile keys} {\n        r set x foo\n        list [r persist foo] [r persist nokeyatall]\n    } {0 0}\n\n    test {EXPIRE pricision is now the millisecond} {\n        # This test is very likely to do a false positive if the\n        # server is under pressure, so if it does not work give it a few more\n        # chances.\n        for {set j 0} {$j < 3} {incr j} {\n            r del x\n            r setex x 1 somevalue\n            after 900\n            set a [r get x]\n            after 1100\n            set b [r get x]\n            if {$a eq {somevalue} && $b eq {}} break\n        }\n        list $a $b\n    } {somevalue {}}\n\n    test {PEXPIRE/PSETEX/PEXPIREAT can set sub-second expires} {\n        # This test is very likely to do a false positive if the\n        # server is under pressure, so if it does not work give it a few more\n        # chances.\n        for {set j 0} {$j < 3} {incr j} {\n            r del x y z\n            r psetex x 100 somevalue\n            after 80\n            set a [r get x]\n            after 120\n            set b [r get x]\n\n            r set x somevalue\n            r pexpire x 100\n            after 80\n            set c [r get x]\n            after 120\n            set d [r get x]\n\n            r set x somevalue\n            r pexpireat x [expr ([clock seconds]*1000)+100]\n            after 80\n            set e [r get x]\n            after 120\n            set f [r get x]\n\n            if {$a eq {somevalue} && $b eq {} &&\n                $c eq {somevalue} && $d eq {} &&\n                $e eq {somevalue} && $f eq {}} break\n        }\n        list $a $b\n    } {somevalue {}}\n\n    test {TTL returns tiem to live in seconds} {\n        r del x\n        r setex x 10 somevalue\n        set ttl [r ttl x]\n        assert {$ttl > 8 && $ttl <= 10}\n    }\n\n    test {PTTL returns time to live in milliseconds} {\n        r del x\n        r setex x 1 somevalue\n        set ttl [r pttl x]\n        assert {$ttl > 900 && $ttl <= 1000}\n    }\n\n    test {TTL / PTTL return -1 if key has no expire} {\n        r del x\n        r set x hello\n        list [r ttl x] [r pttl x]\n    } {-1 -1}\n\n    test {TTL / PTTL return -2 if key does not exit} {\n        r del x\n        list [r ttl x] [r pttl x]\n    } {-2 -2}\n\n    test {Redis should actively expire keys incrementally} {\n        r flushdb\n        r psetex key1 500 a\n        r psetex key2 500 a\n        r psetex key3 500 a\n        set size1 [r dbsize]\n        # Redis expires random keys ten times every second so we are\n        # fairly sure that all the three keys should be evicted after\n        # one second.\n        after 1000\n        set size2 [r dbsize]\n        list $size1 $size2\n    } {3 0}\n\n    test {Redis should lazy expire keys} {\n        r flushdb\n        r debug set-active-expire 0\n        r psetex key1 500 a\n        r psetex key2 500 a\n        r psetex key3 500 a\n        set size1 [r dbsize]\n        # Redis expires random keys ten times every second so we are\n        # fairly sure that all the three keys should be evicted after\n        # one second.\n        after 1000\n        set size2 [r dbsize]\n        r mget key1 key2 key3\n        set size3 [r dbsize]\n        r debug set-active-expire 1\n        list $size1 $size2 $size3\n    } {3 3 0}\n\n    test {EXPIRE should not resurrect keys (issue #1026)} {\n        r debug set-active-expire 0\n        r set foo bar\n        r pexpire foo 500\n        after 1000\n        r expire foo 10\n        r debug set-active-expire 1\n        r exists foo\n    } {0}\n\n    test {5 keys in, 5 keys out} {\n        r flushdb\n        r set a c\n        r expire a 5\n        r set t c\n        r set e c\n        r set s c\n        r set foo b\n        lsort [r keys *]\n    } {a e foo s t}\n}\n"
  },
  {
    "path": "extern/deprecated/redis-2.8.21/tests/unit/hyperloglog.tcl",
    "content": "start_server {tags {\"hll\"}} {\n    test {HyperLogLog self test passes} {\n        catch {r pfselftest} e\n        set e\n    } {OK}\n\n    test {PFADD without arguments creates an HLL value} {\n        r pfadd hll\n        r exists hll\n    } {1}\n\n    test {Approximated cardinality after creation is zero} {\n        r pfcount hll\n    } {0}\n\n    test {PFADD returns 1 when at least 1 reg was modified} {\n        r pfadd hll a b c\n    } {1}\n\n    test {PFADD returns 0 when no reg was modified} {\n        r pfadd hll a b c\n    } {0}\n\n    test {PFADD works with empty string (regression)} {\n        r pfadd hll \"\"\n    }\n\n    # Note that the self test stresses much better the\n    # cardinality estimation error. We are testing just the\n    # command implementation itself here.\n    test {PFCOUNT returns approximated cardinality of set} {\n        r del hll\n        set res {}\n        r pfadd hll 1 2 3 4 5\n        lappend res [r pfcount hll]\n        # Call it again to test cached value invalidation.\n        r pfadd hll 6 7 8 8 9 10\n        lappend res [r pfcount hll]\n        set res\n    } {5 10}\n\n    test {HyperLogLogs are promote from sparse to dense} {\n        r del hll\n        r config set hll-sparse-max-bytes 3000\n        set n 0\n        while {$n < 100000} {\n            set elements {}\n            for {set j 0} {$j < 100} {incr j} {lappend elements [expr rand()]}\n            incr n 100\n            r pfadd hll {*}$elements\n            set card [r pfcount hll]\n            set err [expr {abs($card-$n)}]\n            assert {$err < (double($card)/100)*5}\n            if {$n < 1000} {\n                assert {[r pfdebug encoding hll] eq {sparse}}\n            } elseif {$n > 10000} {\n                assert {[r pfdebug encoding hll] eq {dense}}\n            }\n        }\n    }\n\n    test {HyperLogLog sparse encoding stress test} {\n        for {set x 0} {$x < 1000} {incr x} {\n            r del hll1 hll2\n            set numele [randomInt 100]\n            set elements {}\n            for {set j 0} {$j < $numele} {incr j} {\n                lappend elements [expr rand()]\n            }\n            # Force dense representation of hll2\n            r pfadd hll2\n            r pfdebug todense hll2\n            r pfadd hll1 {*}$elements\n            r pfadd hll2 {*}$elements\n            assert {[r pfdebug encoding hll1] eq {sparse}}\n            assert {[r pfdebug encoding hll2] eq {dense}}\n            # Cardinality estimated should match exactly.\n            assert {[r pfcount hll1] eq [r pfcount hll2]}\n        }\n    }\n\n    test {Corrupted sparse HyperLogLogs are detected: Additionl at tail} {\n        r del hll\n        r pfadd hll a b c\n        r append hll \"hello\"\n        set e {}\n        catch {r pfcount hll} e\n        set e\n    } {*INVALIDOBJ*}\n\n    test {Corrupted sparse HyperLogLogs are detected: Broken magic} {\n        r del hll\n        r pfadd hll a b c\n        r setrange hll 0 \"0123\"\n        set e {}\n        catch {r pfcount hll} e\n        set e\n    } {*WRONGTYPE*}\n\n    test {Corrupted sparse HyperLogLogs are detected: Invalid encoding} {\n        r del hll\n        r pfadd hll a b c\n        r setrange hll 4 \"x\"\n        set e {}\n        catch {r pfcount hll} e\n        set e\n    } {*WRONGTYPE*}\n\n    test {Corrupted dense HyperLogLogs are detected: Wrong length} {\n        r del hll\n        r pfadd hll a b c\n        r setrange hll 4 \"\\x00\"\n        set e {}\n        catch {r pfcount hll} e\n        set e\n    } {*WRONGTYPE*}\n\n    test {PFADD, PFCOUNT, PFMERGE type checking works} {\n        r set foo bar\n        catch {r pfadd foo 1} e\n        assert_match {*WRONGTYPE*} $e\n        catch {r pfcount foo} e\n        assert_match {*WRONGTYPE*} $e\n        catch {r pfmerge bar foo} e\n        assert_match {*WRONGTYPE*} $e\n        catch {r pfmerge foo bar} e\n        assert_match {*WRONGTYPE*} $e\n    }\n\n    test {PFMERGE results on the cardinality of union of sets} {\n        r del hll hll1 hll2 hll3\n        r pfadd hll1 a b c\n        r pfadd hll2 b c d\n        r pfadd hll3 c d e\n        r pfmerge hll hll1 hll2 hll3\n        r pfcount hll\n    } {5}\n\n    test {PFCOUNT multiple-keys merge returns cardinality of union} {\n        r del hll1 hll2 hll3\n        for {set x 1} {$x < 10000} {incr x} {\n            # Force dense representation of hll2\n            r pfadd hll1 \"foo-$x\"\n            r pfadd hll2 \"bar-$x\"\n            r pfadd hll3 \"zap-$x\"\n\n            set card [r pfcount hll1 hll2 hll3]\n            set realcard [expr {$x*3}]\n            set err [expr {abs($card-$realcard)}]\n            assert {$err < (double($card)/100)*5}\n        }\n    }\n\n    test {PFDEBUG GETREG returns the HyperLogLog raw registers} {\n        r del hll\n        r pfadd hll 1 2 3\n        llength [r pfdebug getreg hll]\n    } {16384}\n\n    test {PFADD / PFCOUNT cache invalidation works} {\n        r del hll\n        r pfadd hll a b c\n        r pfcount hll\n        assert {[r getrange hll 15 15] eq \"\\x00\"}\n        r pfadd hll a b c\n        assert {[r getrange hll 15 15] eq \"\\x00\"}\n        r pfadd hll 1 2 3\n        assert {[r getrange hll 15 15] eq \"\\x80\"}\n    }\n}\n"
  },
  {
    "path": "extern/deprecated/redis-2.8.21/tests/unit/introspection.tcl",
    "content": "start_server {tags {\"introspection\"}} {\n    test {CLIENT LIST} {\n        r client list\n    } {*addr=*:* fd=* age=* idle=* flags=N db=9 sub=0 psub=0 multi=-1 qbuf=0 qbuf-free=* obl=0 oll=0 omem=0 events=r cmd=client*}\n\n    test {MONITOR can log executed commands} {\n        set rd [redis_deferring_client]\n        $rd monitor\n        r set foo bar\n        r get foo\n        list [$rd read] [$rd read] [$rd read]\n    } {*OK*\"set\" \"foo\"*\"get\" \"foo\"*}\n\n    test {MONITOR can log commands issued by the scripting engine} {\n        set rd [redis_deferring_client]\n        $rd monitor\n        r eval {redis.call('set',KEYS[1],ARGV[1])} 1 foo bar\n        $rd read ;# Discard the OK\n        assert_match {*eval*} [$rd read]\n        assert_match {*lua*\"set\"*\"foo\"*\"bar\"*} [$rd read]\n    }\n\n    test {CLIENT GETNAME should return NIL if name is not assigned} {\n        r client getname\n    } {}\n\n    test {CLIENT LIST shows empty fields for unassigned names} {\n        r client list\n    } {*name= *}\n\n    test {CLIENT SETNAME does not accept spaces} {\n        catch {r client setname \"foo bar\"} e\n        set e\n    } {ERR*}\n\n    test {CLIENT SETNAME can assign a name to this connection} {\n        assert_equal [r client setname myname] {OK}\n        r client list\n    } {*name=myname*}\n\n    test {CLIENT SETNAME can change the name of an existing connection} {\n        assert_equal [r client setname someothername] {OK}\n        r client list\n    } {*name=someothername*}\n\n    test {After CLIENT SETNAME, connection can still be closed} {\n        set rd [redis_deferring_client]\n        $rd client setname foobar\n        assert_equal [$rd read] \"OK\"\n        assert_match {*foobar*} [r client list]\n        $rd close\n        # Now the client should no longer be listed\n        wait_for_condition 50 100 {\n            [string match {*foobar*} [r client list]] == 0\n        } else {\n            fail \"Client still listed in CLIENT LIST after SETNAME.\"\n        }\n    }\n}\n"
  },
  {
    "path": "extern/deprecated/redis-2.8.21/tests/unit/latency-monitor.tcl",
    "content": "start_server {tags {\"latency-monitor\"}} {\n    # Set a threshold high enough to avoid spurious latency events.\n    r config set latency-monitor-threshold 200\n    r latency reset\n\n    test {Test latency events logging} {\n        r debug sleep 0.3\n        after 1100\n        r debug sleep 0.4\n        after 1100\n        r debug sleep 0.5\n        assert {[r latency history command] >= 3}\n    }\n\n    test {LATENCY HISTORY output is ok} {\n        set min 250\n        set max 450\n        foreach event [r latency history command] {\n            lassign $event time latency\n            assert {$latency >= $min && $latency <= $max}\n            incr min 100\n            incr max 100\n            set last_time $time ; # Used in the next test\n        }\n    }\n\n    test {LATENCY LATEST output is ok} {\n        foreach event [r latency latest] {\n            lassign $event eventname time latency max\n            assert {$eventname eq \"command\"}\n            assert {$max >= 450 & $max <= 650}\n            assert {$time == $last_time}\n            break\n        }\n    }\n\n    test {LATENCY HISTORY / RESET with wrong event name is fine} {\n        assert {[llength [r latency history blabla]] == 0}\n        assert {[r latency reset blabla] == 0}\n    }\n\n    test {LATENCY DOCTOR produces some output} {\n        assert {[string length [r latency doctor]] > 0}\n    }\n\n    test {LATENCY RESET is able to reset events} {\n        assert {[r latency reset] > 0}\n        assert {[r latency latest] eq {}}\n    }\n}\n"
  },
  {
    "path": "extern/deprecated/redis-2.8.21/tests/unit/limits.tcl",
    "content": "start_server {tags {\"limits\"} overrides {maxclients 10}} {\n    test {Check if maxclients works refusing connections} {\n        set c 0\n        catch {\n            while {$c < 50} {\n                incr c\n                set rd [redis_deferring_client]\n                $rd ping\n                $rd read\n                after 100\n            }\n        } e\n        assert {$c > 8 && $c <= 10}\n        set e\n    } {*ERR max*reached*}\n}\n"
  },
  {
    "path": "extern/deprecated/redis-2.8.21/tests/unit/maxmemory.tcl",
    "content": "start_server {tags {\"maxmemory\"}} {\n    test \"Without maxmemory small integers are shared\" {\n        r config set maxmemory 0\n        r set a 1\n        assert {[r object refcount a] > 1}\n    }\n\n    test \"With maxmemory and non-LRU policy integers are still shared\" {\n        r config set maxmemory 1073741824\n        r config set maxmemory-policy allkeys-random\n        r set a 1\n        assert {[r object refcount a] > 1}\n    }\n\n    test \"With maxmemory and LRU policy integers are not shared\" {\n        r config set maxmemory 1073741824\n        r config set maxmemory-policy allkeys-lru\n        r set a 1\n        r config set maxmemory-policy volatile-lru\n        r set b 1\n        assert {[r object refcount a] == 1}\n        assert {[r object refcount b] == 1}\n        r config set maxmemory 0\n    }\n\n    foreach policy {\n        allkeys-random allkeys-lru volatile-lru volatile-random volatile-ttl\n    } {\n        test \"maxmemory - is the memory limit honoured? (policy $policy)\" {\n            # make sure to start with a blank instance\n            r flushall\n            # Get the current memory limit and calculate a new limit.\n            # We just add 100k to the current memory size so that it is\n            # fast for us to reach that limit.\n            set used [s used_memory]\n            set limit [expr {$used+100*1024}]\n            r config set maxmemory $limit\n            r config set maxmemory-policy $policy\n            # Now add keys until the limit is almost reached.\n            set numkeys 0\n            while 1 {\n                r setex [randomKey] 10000 x\n                incr numkeys\n                if {[s used_memory]+4096 > $limit} {\n                    assert {$numkeys > 10}\n                    break\n                }\n            }\n            # If we add the same number of keys already added again, we\n            # should still be under the limit.\n            for {set j 0} {$j < $numkeys} {incr j} {\n                r setex [randomKey] 10000 x\n            }\n            assert {[s used_memory] < ($limit+4096)}\n        }\n    }\n\n    foreach policy {\n        allkeys-random allkeys-lru volatile-lru volatile-random volatile-ttl\n    } {\n        test \"maxmemory - only allkeys-* should remove non-volatile keys ($policy)\" {\n            # make sure to start with a blank instance\n            r flushall\n            # Get the current memory limit and calculate a new limit.\n            # We just add 100k to the current memory size so that it is\n            # fast for us to reach that limit.\n            set used [s used_memory]\n            set limit [expr {$used+100*1024}]\n            r config set maxmemory $limit\n            r config set maxmemory-policy $policy\n            # Now add keys until the limit is almost reached.\n            set numkeys 0\n            while 1 {\n                r set [randomKey] x\n                incr numkeys\n                if {[s used_memory]+4096 > $limit} {\n                    assert {$numkeys > 10}\n                    break\n                }\n            }\n            # If we add the same number of keys already added again and\n            # the policy is allkeys-* we should still be under the limit.\n            # Otherwise we should see an error reported by Redis.\n            set err 0\n            for {set j 0} {$j < $numkeys} {incr j} {\n                if {[catch {r set [randomKey] x} e]} {\n                    if {[string match {*used memory*} $e]} {\n                        set err 1\n                    }\n                }\n            }\n            if {[string match allkeys-* $policy]} {\n                assert {[s used_memory] < ($limit+4096)}\n            } else {\n                assert {$err == 1}\n            }\n        }\n    }\n\n    foreach policy {\n        volatile-lru volatile-random volatile-ttl\n    } {\n        test \"maxmemory - policy $policy should only remove volatile keys.\" {\n            # make sure to start with a blank instance\n            r flushall\n            # Get the current memory limit and calculate a new limit.\n            # We just add 100k to the current memory size so that it is\n            # fast for us to reach that limit.\n            set used [s used_memory]\n            set limit [expr {$used+100*1024}]\n            r config set maxmemory $limit\n            r config set maxmemory-policy $policy\n            # Now add keys until the limit is almost reached.\n            set numkeys 0\n            while 1 {\n                # Odd keys are volatile\n                # Even keys are non volatile\n                if {$numkeys % 2} {\n                    r setex \"key:$numkeys\" 10000 x\n                } else {\n                    r set \"key:$numkeys\" x\n                }\n                if {[s used_memory]+4096 > $limit} {\n                    assert {$numkeys > 10}\n                    break\n                }\n                incr numkeys\n            }\n            # Now we add the same number of volatile keys already added.\n            # We expect Redis to evict only volatile keys in order to make\n            # space.\n            set err 0\n            for {set j 0} {$j < $numkeys} {incr j} {\n                catch {r setex \"foo:$j\" 10000 x}\n            }\n            # We should still be under the limit.\n            assert {[s used_memory] < ($limit+4096)}\n            # However all our non volatile keys should be here.\n            for {set j 0} {$j < $numkeys} {incr j 2} {\n                assert {[r exists \"key:$j\"]}\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "extern/deprecated/redis-2.8.21/tests/unit/memefficiency.tcl",
    "content": "proc test_memory_efficiency {range} {\n    r flushall\n    set rd [redis_deferring_client]\n    set base_mem [s used_memory]\n    set written 0\n    for {set j 0} {$j < 10000} {incr j} {\n        set key key:$j\n        set val [string repeat A [expr {int(rand()*$range)}]]\n        $rd set $key $val\n        incr written [string length $key]\n        incr written [string length $val]\n        incr written 2 ;# A separator is the minimum to store key-value data.\n    }\n    for {set j 0} {$j < 10000} {incr j} {\n        $rd read ; # Discard replies\n    }\n\n    set current_mem [s used_memory]\n    set used [expr {$current_mem-$base_mem}]\n    set efficiency [expr {double($written)/$used}]\n    return $efficiency\n}\n\nstart_server {tags {\"memefficiency\"}} {\n    foreach {size_range expected_min_efficiency} {\n        32    0.15\n        64    0.25\n        128   0.35\n        1024  0.75\n        16384 0.82\n    } {\n        test \"Memory efficiency with values in range $size_range\" {\n            set efficiency [test_memory_efficiency $size_range]\n            assert {$efficiency >= $expected_min_efficiency}\n        }\n    }\n}\n"
  },
  {
    "path": "extern/deprecated/redis-2.8.21/tests/unit/multi.tcl",
    "content": "start_server {tags {\"multi\"}} {\n    test {MUTLI / EXEC basics} {\n        r del mylist\n        r rpush mylist a\n        r rpush mylist b\n        r rpush mylist c\n        r multi\n        set v1 [r lrange mylist 0 -1]\n        set v2 [r ping]\n        set v3 [r exec]\n        list $v1 $v2 $v3\n    } {QUEUED QUEUED {{a b c} PONG}}\n\n    test {DISCARD} {\n        r del mylist\n        r rpush mylist a\n        r rpush mylist b\n        r rpush mylist c\n        r multi\n        set v1 [r del mylist]\n        set v2 [r discard]\n        set v3 [r lrange mylist 0 -1]\n        list $v1 $v2 $v3\n    } {QUEUED OK {a b c}}\n\n    test {Nested MULTI are not allowed} {\n        set err {}\n        r multi\n        catch {[r multi]} err\n        r exec\n        set _ $err\n    } {*ERR MULTI*}\n\n    test {MULTI where commands alter argc/argv} {\n        r sadd myset a\n        r multi\n        r spop myset\n        list [r exec] [r exists myset]\n    } {a 0}\n\n    test {WATCH inside MULTI is not allowed} {\n        set err {}\n        r multi\n        catch {[r watch x]} err\n        r exec\n        set _ $err\n    } {*ERR WATCH*}\n\n    test {EXEC fails if there are errors while queueing commands #1} {\n        r del foo1 foo2\n        r multi\n        r set foo1 bar1\n        catch {r non-existing-command}\n        r set foo2 bar2\n        catch {r exec} e\n        assert_match {EXECABORT*} $e\n        list [r exists foo1] [r exists foo2]\n    } {0 0}\n\n    test {EXEC fails if there are errors while queueing commands #2} {\n        set rd [redis_deferring_client]\n        r del foo1 foo2\n        r multi\n        r set foo1 bar1\n        $rd config set maxmemory 1\n        assert  {[$rd read] eq {OK}}\n        catch {r lpush mylist myvalue}\n        $rd config set maxmemory 0\n        assert  {[$rd read] eq {OK}}\n        r set foo2 bar2\n        catch {r exec} e\n        assert_match {EXECABORT*} $e\n        $rd close\n        list [r exists foo1] [r exists foo2]\n    } {0 0}\n\n    test {If EXEC aborts, the client MULTI state is cleared} {\n        r del foo1 foo2\n        r multi\n        r set foo1 bar1\n        catch {r non-existing-command}\n        r set foo2 bar2\n        catch {r exec} e\n        assert_match {EXECABORT*} $e\n        r ping\n    } {PONG}\n\n    test {EXEC works on WATCHed key not modified} {\n        r watch x y z\n        r watch k\n        r multi\n        r ping\n        r exec\n    } {PONG}\n\n    test {EXEC fail on WATCHed key modified (1 key of 1 watched)} {\n        r set x 30\n        r watch x\n        r set x 40\n        r multi\n        r ping\n        r exec\n    } {}\n\n    test {EXEC fail on WATCHed key modified (1 key of 5 watched)} {\n        r set x 30\n        r watch a b x k z\n        r set x 40\n        r multi\n        r ping\n        r exec\n    } {}\n\n    test {EXEC fail on WATCHed key modified by SORT with STORE even if the result is empty} {\n        r flushdb\n        r lpush foo bar\n        r watch foo\n        r sort emptylist store foo\n        r multi\n        r ping\n        r exec\n    } {}\n\n    test {After successful EXEC key is no longer watched} {\n        r set x 30\n        r watch x\n        r multi\n        r ping\n        r exec\n        r set x 40\n        r multi\n        r ping\n        r exec\n    } {PONG}\n\n    test {After failed EXEC key is no longer watched} {\n        r set x 30\n        r watch x\n        r set x 40\n        r multi\n        r ping\n        r exec\n        r set x 40\n        r multi\n        r ping\n        r exec\n    } {PONG}\n\n    test {It is possible to UNWATCH} {\n        r set x 30\n        r watch x\n        r set x 40\n        r unwatch\n        r multi\n        r ping\n        r exec\n    } {PONG}\n\n    test {UNWATCH when there is nothing watched works as expected} {\n        r unwatch\n    } {OK}\n\n    test {FLUSHALL is able to touch the watched keys} {\n        r set x 30\n        r watch x\n        r flushall\n        r multi\n        r ping\n        r exec\n    } {}\n\n    test {FLUSHALL does not touch non affected keys} {\n        r del x\n        r watch x\n        r flushall\n        r multi\n        r ping\n        r exec\n    } {PONG}\n\n    test {FLUSHDB is able to touch the watched keys} {\n        r set x 30\n        r watch x\n        r flushdb\n        r multi\n        r ping\n        r exec\n    } {}\n\n    test {FLUSHDB does not touch non affected keys} {\n        r del x\n        r watch x\n        r flushdb\n        r multi\n        r ping\n        r exec\n    } {PONG}\n\n    test {WATCH is able to remember the DB a key belongs to} {\n        r select 5\n        r set x 30\n        r watch x\n        r select 1\n        r set x 10\n        r select 5\n        r multi\n        r ping\n        set res [r exec]\n        # Restore original DB\n        r select 9\n        set res\n    } {PONG}\n\n    test {WATCH will consider touched keys target of EXPIRE} {\n        r del x\n        r set x foo\n        r watch x\n        r expire x 10\n        r multi\n        r ping\n        r exec\n    } {}\n\n    test {WATCH will not consider touched expired keys} {\n        r del x\n        r set x foo\n        r expire x 1\n        r watch x\n        after 1100\n        r multi\n        r ping\n        r exec\n    } {PONG}\n\n    test {DISCARD should clear the WATCH dirty flag on the client} {\n        r watch x\n        r set x 10\n        r multi\n        r discard\n        r multi\n        r incr x\n        r exec\n    } {11}\n\n    test {DISCARD should UNWATCH all the keys} {\n        r watch x\n        r set x 10\n        r multi\n        r discard\n        r set x 10\n        r multi\n        r incr x\n        r exec\n    } {11}\n\n    test {MULTI / EXEC is propagated correctly (single write command)} {\n        set repl [attach_to_replication_stream]\n        r multi\n        r set foo bar\n        r exec\n        assert_replication_stream $repl {\n            {select *}\n            {multi}\n            {set foo bar}\n            {exec}\n        }\n        close_replication_stream $repl\n    }\n\n    test {MULTI / EXEC is propagated correctly (empty transaction)} {\n        set repl [attach_to_replication_stream]\n        r multi\n        r exec\n        r set foo bar\n        assert_replication_stream $repl {\n            {select *}\n            {set foo bar}\n        }\n        close_replication_stream $repl\n    }\n\n    test {MULTI / EXEC is propagated correctly (read-only commands)} {\n        r set foo value1\n        set repl [attach_to_replication_stream]\n        r multi\n        r get foo\n        r exec\n        r set foo value2\n        assert_replication_stream $repl {\n            {select *}\n            {set foo value2}\n        }\n        close_replication_stream $repl\n    }\n\n    test {MULTI / EXEC is propagated correctly (write command, no effect)} {\n        r del bar foo bar\n        set repl [attach_to_replication_stream]\n        r multi\n        r del foo\n        r exec\n        assert_replication_stream $repl {\n            {select *}\n            {multi}\n            {exec}\n        }\n        close_replication_stream $repl\n    }\n}\n"
  },
  {
    "path": "extern/deprecated/redis-2.8.21/tests/unit/obuf-limits.tcl",
    "content": "start_server {tags {\"obuf-limits\"}} {\n    test {Client output buffer hard limit is enforced} {\n        r config set client-output-buffer-limit {pubsub 100000 0 0}\n        set rd1 [redis_deferring_client]\n\n        $rd1 subscribe foo\n        set reply [$rd1 read]\n        assert {$reply eq \"subscribe foo 1\"}\n\n        set omem 0\n        while 1 {\n            r publish foo bar\n            set clients [split [r client list] \"\\r\\n\"]\n            set c [split [lindex $clients 1] \" \"]\n            if {![regexp {omem=([0-9]+)} $c - omem]} break\n            if {$omem > 200000} break\n        }\n        assert {$omem >= 90000 && $omem < 200000}\n        $rd1 close\n    }\n\n    test {Client output buffer soft limit is not enforced if time is not overreached} {\n        r config set client-output-buffer-limit {pubsub 0 100000 10}\n        set rd1 [redis_deferring_client]\n\n        $rd1 subscribe foo\n        set reply [$rd1 read]\n        assert {$reply eq \"subscribe foo 1\"}\n\n        set omem 0\n        set start_time 0\n        set time_elapsed 0\n        while 1 {\n            r publish foo bar\n            set clients [split [r client list] \"\\r\\n\"]\n            set c [split [lindex $clients 1] \" \"]\n            if {![regexp {omem=([0-9]+)} $c - omem]} break\n            if {$omem > 100000} {\n                if {$start_time == 0} {set start_time [clock seconds]}\n                set time_elapsed [expr {[clock seconds]-$start_time}]\n                if {$time_elapsed >= 5} break\n            }\n        }\n        assert {$omem >= 100000 && $time_elapsed >= 5 && $time_elapsed <= 10}\n        $rd1 close\n    }\n\n    test {Client output buffer soft limit is enforced if time is overreached} {\n        r config set client-output-buffer-limit {pubsub 0 100000 3}\n        set rd1 [redis_deferring_client]\n\n        $rd1 subscribe foo\n        set reply [$rd1 read]\n        assert {$reply eq \"subscribe foo 1\"}\n\n        set omem 0\n        set start_time 0\n        set time_elapsed 0\n        while 1 {\n            r publish foo bar\n            set clients [split [r client list] \"\\r\\n\"]\n            set c [split [lindex $clients 1] \" \"]\n            if {![regexp {omem=([0-9]+)} $c - omem]} break\n            if {$omem > 100000} {\n                if {$start_time == 0} {set start_time [clock seconds]}\n                set time_elapsed [expr {[clock seconds]-$start_time}]\n                if {$time_elapsed >= 10} break\n            }\n        }\n        assert {$omem >= 100000 && $time_elapsed < 6}\n        $rd1 close\n    }\n}\n"
  },
  {
    "path": "extern/deprecated/redis-2.8.21/tests/unit/other.tcl",
    "content": "start_server {tags {\"other\"}} {\n    if {$::force_failure} {\n        # This is used just for test suite development purposes.\n        test {Failing test} {\n            format err\n        } {ok}\n    }\n\n    test {SAVE - make sure there are all the types as values} {\n        # Wait for a background saving in progress to terminate\n        waitForBgsave r\n        r lpush mysavelist hello\n        r lpush mysavelist world\n        r set myemptykey {}\n        r set mynormalkey {blablablba}\n        r zadd mytestzset 10 a\n        r zadd mytestzset 20 b\n        r zadd mytestzset 30 c\n        r save\n    } {OK}\n\n    tags {slow} {\n        if {$::accurate} {set iterations 10000} else {set iterations 1000}\n        foreach fuzztype {binary alpha compr} {\n            test \"FUZZ stresser with data model $fuzztype\" {\n                set err 0\n                for {set i 0} {$i < $iterations} {incr i} {\n                    set fuzz [randstring 0 512 $fuzztype]\n                    r set foo $fuzz\n                    set got [r get foo]\n                    if {$got ne $fuzz} {\n                        set err [list $fuzz $got]\n                        break\n                    }\n                }\n                set _ $err\n            } {0}\n        }\n    }\n\n    test {BGSAVE} {\n        waitForBgsave r\n        r flushdb\n        r save\n        r set x 10\n        r bgsave\n        waitForBgsave r\n        r debug reload\n        r get x\n    } {10}\n\n    test {SELECT an out of range DB} {\n        catch {r select 1000000} err\n        set _ $err\n    } {*invalid*}\n\n    tags {consistency} {\n        if {![catch {package require sha1}]} {\n            if {$::accurate} {set numops 10000} else {set numops 1000}\n            test {Check consistency of different data types after a reload} {\n                r flushdb\n                createComplexDataset r $numops\n                set dump [csvdump r]\n                set sha1 [r debug digest]\n                r debug reload\n                set sha1_after [r debug digest]\n                if {$sha1 eq $sha1_after} {\n                    set _ 1\n                } else {\n                    set newdump [csvdump r]\n                    puts \"Consistency test failed!\"\n                    puts \"You can inspect the two dumps in /tmp/repldump*.txt\"\n\n                    set fd [open /tmp/repldump1.txt w]\n                    puts $fd $dump\n                    close $fd\n                    set fd [open /tmp/repldump2.txt w]\n                    puts $fd $newdump\n                    close $fd\n\n                    set _ 0\n                }\n            } {1}\n\n            test {Same dataset digest if saving/reloading as AOF?} {\n                r bgrewriteaof\n                waitForBgrewriteaof r\n                r debug loadaof\n                set sha1_after [r debug digest]\n                if {$sha1 eq $sha1_after} {\n                    set _ 1\n                } else {\n                    set newdump [csvdump r]\n                    puts \"Consistency test failed!\"\n                    puts \"You can inspect the two dumps in /tmp/aofdump*.txt\"\n\n                    set fd [open /tmp/aofdump1.txt w]\n                    puts $fd $dump\n                    close $fd\n                    set fd [open /tmp/aofdump2.txt w]\n                    puts $fd $newdump\n                    close $fd\n\n                    set _ 0\n                }\n            } {1}\n        }\n    }\n\n    test {EXPIRES after a reload (snapshot + append only file rewrite)} {\n        r flushdb\n        r set x 10\n        r expire x 1000\n        r save\n        r debug reload\n        set ttl [r ttl x]\n        set e1 [expr {$ttl > 900 && $ttl <= 1000}]\n        r bgrewriteaof\n        waitForBgrewriteaof r\n        r debug loadaof\n        set ttl [r ttl x]\n        set e2 [expr {$ttl > 900 && $ttl <= 1000}]\n        list $e1 $e2\n    } {1 1}\n\n    test {EXPIRES after AOF reload (without rewrite)} {\n        r flushdb\n        r config set appendonly yes\n        r set x somevalue\n        r expire x 1000\n        r setex y 2000 somevalue\n        r set z somevalue\n        r expireat z [expr {[clock seconds]+3000}]\n\n        # Milliseconds variants\n        r set px somevalue\n        r pexpire px 1000000\n        r psetex py 2000000 somevalue\n        r set pz somevalue\n        r pexpireat pz [expr {([clock seconds]+3000)*1000}]\n\n        # Reload and check\n        waitForBgrewriteaof r\n        # We need to wait two seconds to avoid false positives here, otherwise\n        # the DEBUG LOADAOF command may read a partial file.\n        # Another solution would be to set the fsync policy to no, since this\n        # prevents write() to be delayed by the completion of fsync().\n        after 2000\n        r debug loadaof\n        set ttl [r ttl x]\n        assert {$ttl > 900 && $ttl <= 1000}\n        set ttl [r ttl y]\n        assert {$ttl > 1900 && $ttl <= 2000}\n        set ttl [r ttl z]\n        assert {$ttl > 2900 && $ttl <= 3000}\n        set ttl [r ttl px]\n        assert {$ttl > 900 && $ttl <= 1000}\n        set ttl [r ttl py]\n        assert {$ttl > 1900 && $ttl <= 2000}\n        set ttl [r ttl pz]\n        assert {$ttl > 2900 && $ttl <= 3000}\n        r config set appendonly no\n    }\n\n    tags {protocol} {\n        test {PIPELINING stresser (also a regression for the old epoll bug)} {\n            set fd2 [socket $::host $::port]\n            fconfigure $fd2 -encoding binary -translation binary\n            puts -nonewline $fd2 \"SELECT 9\\r\\n\"\n            flush $fd2\n            gets $fd2\n\n            for {set i 0} {$i < 100000} {incr i} {\n                set q {}\n                set val \"0000${i}0000\"\n                append q \"SET key:$i $val\\r\\n\"\n                puts -nonewline $fd2 $q\n                set q {}\n                append q \"GET key:$i\\r\\n\"\n                puts -nonewline $fd2 $q\n            }\n            flush $fd2\n\n            for {set i 0} {$i < 100000} {incr i} {\n                gets $fd2 line\n                gets $fd2 count\n                set count [string range $count 1 end]\n                set val [read $fd2 $count]\n                read $fd2 2\n            }\n            close $fd2\n            set _ 1\n        } {1}\n    }\n\n    test {APPEND basics} {\n        list [r append foo bar] [r get foo] \\\n             [r append foo 100] [r get foo]\n    } {3 bar 6 bar100}\n\n    test {APPEND basics, integer encoded values} {\n        set res {}\n        r del foo\n        r append foo 1\n        r append foo 2\n        lappend res [r get foo]\n        r set foo 1\n        r append foo 2\n        lappend res [r get foo]\n    } {12 12}\n\n    test {APPEND fuzzing} {\n        set err {}\n        foreach type {binary alpha compr} {\n            set buf {}\n            r del x\n            for {set i 0} {$i < 1000} {incr i} {\n                set bin [randstring 0 10 $type]\n                append buf $bin\n                r append x $bin\n            }\n            if {$buf != [r get x]} {\n                set err \"Expected '$buf' found '[r get x]'\"\n                break\n            }\n        }\n        set _ $err\n    } {}\n\n    # Leave the user with a clean DB before to exit\n    test {FLUSHDB} {\n        set aux {}\n        r select 9\n        r flushdb\n        lappend aux [r dbsize]\n        r select 10\n        r flushdb\n        lappend aux [r dbsize]\n    } {0 0}\n\n    test {Perform a final SAVE to leave a clean DB on disk} {\n        waitForBgsave r\n        r save\n    } {OK}\n}\n"
  },
  {
    "path": "extern/deprecated/redis-2.8.21/tests/unit/printver.tcl",
    "content": "start_server {} {\n    set i [r info]\n    regexp {redis_version:(.*?)\\r\\n} $i - version\n    regexp {redis_git_sha1:(.*?)\\r\\n} $i - sha1\n    puts \"Testing Redis version $version ($sha1)\"\n}\n"
  },
  {
    "path": "extern/deprecated/redis-2.8.21/tests/unit/protocol.tcl",
    "content": "start_server {tags {\"protocol\"}} {\n    test \"Handle an empty query\" {\n        reconnect\n        r write \"\\r\\n\"\n        r flush\n        assert_equal \"PONG\" [r ping]\n    }\n\n    test \"Negative multibulk length\" {\n        reconnect\n        r write \"*-10\\r\\n\"\n        r flush\n        assert_equal PONG [r ping]\n    }\n\n    test \"Out of range multibulk length\" {\n        reconnect\n        r write \"*20000000\\r\\n\"\n        r flush\n        assert_error \"*invalid multibulk length*\" {r read}\n    }\n\n    test \"Wrong multibulk payload header\" {\n        reconnect\n        r write \"*3\\r\\n\\$3\\r\\nSET\\r\\n\\$1\\r\\nx\\r\\nfooz\\r\\n\"\n        r flush\n        assert_error \"*expected '$', got 'f'*\" {r read}\n    }\n\n    test \"Negative multibulk payload length\" {\n        reconnect\n        r write \"*3\\r\\n\\$3\\r\\nSET\\r\\n\\$1\\r\\nx\\r\\n\\$-10\\r\\n\"\n        r flush\n        assert_error \"*invalid bulk length*\" {r read}\n    }\n\n    test \"Out of range multibulk payload length\" {\n        reconnect\n        r write \"*3\\r\\n\\$3\\r\\nSET\\r\\n\\$1\\r\\nx\\r\\n\\$2000000000\\r\\n\"\n        r flush\n        assert_error \"*invalid bulk length*\" {r read}\n    }\n\n    test \"Non-number multibulk payload length\" {\n        reconnect\n        r write \"*3\\r\\n\\$3\\r\\nSET\\r\\n\\$1\\r\\nx\\r\\n\\$blabla\\r\\n\"\n        r flush\n        assert_error \"*invalid bulk length*\" {r read}\n    }\n\n    test \"Multi bulk request not followed by bulk arguments\" {\n        reconnect\n        r write \"*1\\r\\nfoo\\r\\n\"\n        r flush\n        assert_error \"*expected '$', got 'f'*\" {r read}\n    }\n\n    test \"Generic wrong number of args\" {\n        reconnect\n        assert_error \"*wrong*arguments*ping*\" {r ping x y z}\n    }\n\n    test \"Unbalanced number of quotes\" {\n        reconnect\n        r write \"set \\\"\\\"\\\"test-key\\\"\\\"\\\" test-value\\r\\n\"\n        r write \"ping\\r\\n\"\n        r flush\n        assert_error \"*unbalanced*\" {r read}\n    }\n\n    set c 0\n    foreach seq [list \"\\x00\" \"*\\x00\" \"$\\x00\"] {\n        incr c\n        test \"Protocol desync regression test #$c\" {\n            set s [socket [srv 0 host] [srv 0 port]]\n            puts -nonewline $s $seq\n            set payload [string repeat A 1024]\"\\n\"\n            set test_start [clock seconds]\n            set test_time_limit 30\n            while 1 {\n                if {[catch {\n                    puts -nonewline $s payload\n                    flush $s\n                    incr payload_size [string length $payload]\n                }]} {\n                    set retval [gets $s]\n                    close $s\n                    break\n                } else {\n                    set elapsed [expr {[clock seconds]-$test_start}]\n                    if {$elapsed > $test_time_limit} {\n                        close $s\n                        error \"assertion:Redis did not closed connection after protocol desync\"\n                    }\n                }\n            }\n            set retval\n        } {*Protocol error*}\n    }\n    unset c\n}\n\nstart_server {tags {\"regression\"}} {\n    test \"Regression for a crash with blocking ops and pipelining\" {\n        set rd [redis_deferring_client]\n        set fd [r channel]\n        set proto \"*3\\r\\n\\$5\\r\\nBLPOP\\r\\n\\$6\\r\\nnolist\\r\\n\\$1\\r\\n0\\r\\n\"\n        puts -nonewline $fd $proto$proto\n        flush $fd\n        set res {}\n\n        $rd rpush nolist a\n        $rd read\n        $rd rpush nolist a\n        $rd read\n    }\n}\n"
  },
  {
    "path": "extern/deprecated/redis-2.8.21/tests/unit/pubsub.tcl",
    "content": "start_server {tags {\"pubsub\"}} {\n    proc __consume_subscribe_messages {client type channels} {\n        set numsub -1\n        set counts {}\n\n        for {set i [llength $channels]} {$i > 0} {incr i -1} {\n            set msg [$client read]\n            assert_equal $type [lindex $msg 0]\n\n            # when receiving subscribe messages the channels names\n            # are ordered. when receiving unsubscribe messages\n            # they are unordered\n            set idx [lsearch -exact $channels [lindex $msg 1]]\n            if {[string match \"*unsubscribe\" $type]} {\n                assert {$idx >= 0}\n            } else {\n                assert {$idx == 0}\n            }\n            set channels [lreplace $channels $idx $idx]\n\n            # aggregate the subscription count to return to the caller\n            lappend counts [lindex $msg 2]\n        }\n\n        # we should have received messages for channels\n        assert {[llength $channels] == 0}\n        return $counts\n    }\n\n    proc subscribe {client channels} {\n        $client subscribe {*}$channels\n        __consume_subscribe_messages $client subscribe $channels\n    }\n\n    proc unsubscribe {client {channels {}}} {\n        $client unsubscribe {*}$channels\n        __consume_subscribe_messages $client unsubscribe $channels\n    }\n\n    proc psubscribe {client channels} {\n        $client psubscribe {*}$channels\n        __consume_subscribe_messages $client psubscribe $channels\n    }\n\n    proc punsubscribe {client {channels {}}} {\n        $client punsubscribe {*}$channels\n        __consume_subscribe_messages $client punsubscribe $channels\n    }\n\n    test \"Pub/Sub PING\" {\n        set rd1 [redis_deferring_client]\n        subscribe $rd1 somechannel\n        # While subscribed to non-zero channels PING works in Pub/Sub mode.\n        $rd1 ping\n        $rd1 ping \"foo\"\n        set reply1 [$rd1 read]\n        set reply2 [$rd1 read]\n        unsubscribe $rd1 somechannel\n        # Now we are unsubscribed, PING should just return PONG.\n        $rd1 ping\n        set reply3 [$rd1 read]\n        $rd1 close\n        list $reply1 $reply2 $reply3\n    } {{pong {}} {pong foo} PONG}\n\n    test \"PUBLISH/SUBSCRIBE basics\" {\n        set rd1 [redis_deferring_client]\n\n        # subscribe to two channels\n        assert_equal {1 2} [subscribe $rd1 {chan1 chan2}]\n        assert_equal 1 [r publish chan1 hello]\n        assert_equal 1 [r publish chan2 world]\n        assert_equal {message chan1 hello} [$rd1 read]\n        assert_equal {message chan2 world} [$rd1 read]\n\n        # unsubscribe from one of the channels\n        unsubscribe $rd1 {chan1}\n        assert_equal 0 [r publish chan1 hello]\n        assert_equal 1 [r publish chan2 world]\n        assert_equal {message chan2 world} [$rd1 read]\n\n        # unsubscribe from the remaining channel\n        unsubscribe $rd1 {chan2}\n        assert_equal 0 [r publish chan1 hello]\n        assert_equal 0 [r publish chan2 world]\n\n        # clean up clients\n        $rd1 close\n    }\n\n    test \"PUBLISH/SUBSCRIBE with two clients\" {\n        set rd1 [redis_deferring_client]\n        set rd2 [redis_deferring_client]\n\n        assert_equal {1} [subscribe $rd1 {chan1}]\n        assert_equal {1} [subscribe $rd2 {chan1}]\n        assert_equal 2 [r publish chan1 hello]\n        assert_equal {message chan1 hello} [$rd1 read]\n        assert_equal {message chan1 hello} [$rd2 read]\n\n        # clean up clients\n        $rd1 close\n        $rd2 close\n    }\n\n    test \"PUBLISH/SUBSCRIBE after UNSUBSCRIBE without arguments\" {\n        set rd1 [redis_deferring_client]\n        assert_equal {1 2 3} [subscribe $rd1 {chan1 chan2 chan3}]\n        unsubscribe $rd1\n        assert_equal 0 [r publish chan1 hello]\n        assert_equal 0 [r publish chan2 hello]\n        assert_equal 0 [r publish chan3 hello]\n\n        # clean up clients\n        $rd1 close\n    }\n\n    test \"SUBSCRIBE to one channel more than once\" {\n        set rd1 [redis_deferring_client]\n        assert_equal {1 1 1} [subscribe $rd1 {chan1 chan1 chan1}]\n        assert_equal 1 [r publish chan1 hello]\n        assert_equal {message chan1 hello} [$rd1 read]\n\n        # clean up clients\n        $rd1 close\n    }\n\n    test \"UNSUBSCRIBE from non-subscribed channels\" {\n        set rd1 [redis_deferring_client]\n        assert_equal {0 0 0} [unsubscribe $rd1 {foo bar quux}]\n\n        # clean up clients\n        $rd1 close\n    }\n\n    test \"PUBLISH/PSUBSCRIBE basics\" {\n        set rd1 [redis_deferring_client]\n\n        # subscribe to two patterns\n        assert_equal {1 2} [psubscribe $rd1 {foo.* bar.*}]\n        assert_equal 1 [r publish foo.1 hello]\n        assert_equal 1 [r publish bar.1 hello]\n        assert_equal 0 [r publish foo1 hello]\n        assert_equal 0 [r publish barfoo.1 hello]\n        assert_equal 0 [r publish qux.1 hello]\n        assert_equal {pmessage foo.* foo.1 hello} [$rd1 read]\n        assert_equal {pmessage bar.* bar.1 hello} [$rd1 read]\n\n        # unsubscribe from one of the patterns\n        assert_equal {1} [punsubscribe $rd1 {foo.*}]\n        assert_equal 0 [r publish foo.1 hello]\n        assert_equal 1 [r publish bar.1 hello]\n        assert_equal {pmessage bar.* bar.1 hello} [$rd1 read]\n\n        # unsubscribe from the remaining pattern\n        assert_equal {0} [punsubscribe $rd1 {bar.*}]\n        assert_equal 0 [r publish foo.1 hello]\n        assert_equal 0 [r publish bar.1 hello]\n\n        # clean up clients\n        $rd1 close\n    }\n\n    test \"PUBLISH/PSUBSCRIBE with two clients\" {\n        set rd1 [redis_deferring_client]\n        set rd2 [redis_deferring_client]\n\n        assert_equal {1} [psubscribe $rd1 {chan.*}]\n        assert_equal {1} [psubscribe $rd2 {chan.*}]\n        assert_equal 2 [r publish chan.foo hello]\n        assert_equal {pmessage chan.* chan.foo hello} [$rd1 read]\n        assert_equal {pmessage chan.* chan.foo hello} [$rd2 read]\n\n        # clean up clients\n        $rd1 close\n        $rd2 close\n    }\n\n    test \"PUBLISH/PSUBSCRIBE after PUNSUBSCRIBE without arguments\" {\n        set rd1 [redis_deferring_client]\n        assert_equal {1 2 3} [psubscribe $rd1 {chan1.* chan2.* chan3.*}]\n        punsubscribe $rd1\n        assert_equal 0 [r publish chan1.hi hello]\n        assert_equal 0 [r publish chan2.hi hello]\n        assert_equal 0 [r publish chan3.hi hello]\n\n        # clean up clients\n        $rd1 close\n    }\n\n    test \"PUNSUBSCRIBE from non-subscribed channels\" {\n        set rd1 [redis_deferring_client]\n        assert_equal {0 0 0} [punsubscribe $rd1 {foo.* bar.* quux.*}]\n\n        # clean up clients\n        $rd1 close\n    }\n\n    test \"NUMSUB returns numbers, not strings (#1561)\" {\n        r pubsub numsub abc def\n    } {abc 0 def 0}\n\n    test \"Mix SUBSCRIBE and PSUBSCRIBE\" {\n        set rd1 [redis_deferring_client]\n        assert_equal {1} [subscribe $rd1 {foo.bar}]\n        assert_equal {2} [psubscribe $rd1 {foo.*}]\n\n        assert_equal 2 [r publish foo.bar hello]\n        assert_equal {message foo.bar hello} [$rd1 read]\n        assert_equal {pmessage foo.* foo.bar hello} [$rd1 read]\n\n        # clean up clients\n        $rd1 close\n    }\n\n    test \"PUNSUBSCRIBE and UNSUBSCRIBE should always reply\" {\n        # Make sure we are not subscribed to any channel at all.\n        r punsubscribe\n        r unsubscribe\n        # Now check if the commands still reply correctly.\n        set reply1 [r punsubscribe]\n        set reply2 [r unsubscribe]\n        concat $reply1 $reply2\n    } {punsubscribe {} 0 unsubscribe {} 0}\n\n    ### Keyspace events notification tests\n\n    test \"Keyspace notifications: we receive keyspace notifications\" {\n        r config set notify-keyspace-events KA\n        set rd1 [redis_deferring_client]\n        assert_equal {1} [psubscribe $rd1 *]\n        r set foo bar\n        assert_equal {pmessage * __keyspace@9__:foo set} [$rd1 read]\n        $rd1 close\n    }\n\n    test \"Keyspace notifications: we receive keyevent notifications\" {\n        r config set notify-keyspace-events EA\n        set rd1 [redis_deferring_client]\n        assert_equal {1} [psubscribe $rd1 *]\n        r set foo bar\n        assert_equal {pmessage * __keyevent@9__:set foo} [$rd1 read]\n        $rd1 close\n    }\n\n    test \"Keyspace notifications: we can receive both kind of events\" {\n        r config set notify-keyspace-events KEA\n        set rd1 [redis_deferring_client]\n        assert_equal {1} [psubscribe $rd1 *]\n        r set foo bar\n        assert_equal {pmessage * __keyspace@9__:foo set} [$rd1 read]\n        assert_equal {pmessage * __keyevent@9__:set foo} [$rd1 read]\n        $rd1 close\n    }\n\n    test \"Keyspace notifications: we are able to mask events\" {\n        r config set notify-keyspace-events KEl\n        r del mylist\n        set rd1 [redis_deferring_client]\n        assert_equal {1} [psubscribe $rd1 *]\n        r set foo bar\n        r lpush mylist a\n        # No notification for set, because only list commands are enabled.\n        assert_equal {pmessage * __keyspace@9__:mylist lpush} [$rd1 read]\n        assert_equal {pmessage * __keyevent@9__:lpush mylist} [$rd1 read]\n        $rd1 close\n    }\n\n    test \"Keyspace notifications: general events test\" {\n        r config set notify-keyspace-events KEg\n        set rd1 [redis_deferring_client]\n        assert_equal {1} [psubscribe $rd1 *]\n        r set foo bar\n        r expire foo 1\n        r del foo\n        assert_equal {pmessage * __keyspace@9__:foo expire} [$rd1 read]\n        assert_equal {pmessage * __keyevent@9__:expire foo} [$rd1 read]\n        assert_equal {pmessage * __keyspace@9__:foo del} [$rd1 read]\n        assert_equal {pmessage * __keyevent@9__:del foo} [$rd1 read]\n        $rd1 close\n    }\n\n    test \"Keyspace notifications: list events test\" {\n        r config set notify-keyspace-events KEl\n        r del mylist\n        set rd1 [redis_deferring_client]\n        assert_equal {1} [psubscribe $rd1 *]\n        r lpush mylist a\n        r rpush mylist a\n        r rpop mylist\n        assert_equal {pmessage * __keyspace@9__:mylist lpush} [$rd1 read]\n        assert_equal {pmessage * __keyevent@9__:lpush mylist} [$rd1 read]\n        assert_equal {pmessage * __keyspace@9__:mylist rpush} [$rd1 read]\n        assert_equal {pmessage * __keyevent@9__:rpush mylist} [$rd1 read]\n        assert_equal {pmessage * __keyspace@9__:mylist rpop} [$rd1 read]\n        assert_equal {pmessage * __keyevent@9__:rpop mylist} [$rd1 read]\n        $rd1 close\n    }\n\n    test \"Keyspace notifications: set events test\" {\n        r config set notify-keyspace-events Ks\n        r del myset\n        set rd1 [redis_deferring_client]\n        assert_equal {1} [psubscribe $rd1 *]\n        r sadd myset a b c d\n        r srem myset x\n        r sadd myset x y z\n        r srem myset x\n        assert_equal {pmessage * __keyspace@9__:myset sadd} [$rd1 read]\n        assert_equal {pmessage * __keyspace@9__:myset sadd} [$rd1 read]\n        assert_equal {pmessage * __keyspace@9__:myset srem} [$rd1 read]\n        $rd1 close\n    }\n\n    test \"Keyspace notifications: zset events test\" {\n        r config set notify-keyspace-events Kz\n        r del myzset\n        set rd1 [redis_deferring_client]\n        assert_equal {1} [psubscribe $rd1 *]\n        r zadd myzset 1 a 2 b\n        r zrem myzset x\n        r zadd myzset 3 x 4 y 5 z\n        r zrem myzset x\n        assert_equal {pmessage * __keyspace@9__:myzset zadd} [$rd1 read]\n        assert_equal {pmessage * __keyspace@9__:myzset zadd} [$rd1 read]\n        assert_equal {pmessage * __keyspace@9__:myzset zrem} [$rd1 read]\n        $rd1 close\n    }\n\n    test \"Keyspace notifications: hash events test\" {\n        r config set notify-keyspace-events Kh\n        r del myhash\n        set rd1 [redis_deferring_client]\n        assert_equal {1} [psubscribe $rd1 *]\n        r hmset myhash yes 1 no 0\n        r hincrby myhash yes 10\n        assert_equal {pmessage * __keyspace@9__:myhash hset} [$rd1 read]\n        assert_equal {pmessage * __keyspace@9__:myhash hincrby} [$rd1 read]\n        $rd1 close\n    }\n\n    test \"Keyspace notifications: expired events (triggered expire)\" {\n        r config set notify-keyspace-events Ex\n        r del foo\n        set rd1 [redis_deferring_client]\n        assert_equal {1} [psubscribe $rd1 *]\n        r psetex foo 100 1\n        wait_for_condition 50 100 {\n            [r exists foo] == 0\n        } else {\n            fail \"Key does not expire?!\"\n        }\n        assert_equal {pmessage * __keyevent@9__:expired foo} [$rd1 read]\n        $rd1 close\n    }\n\n    test \"Keyspace notifications: expired events (background expire)\" {\n        r config set notify-keyspace-events Ex\n        r del foo\n        set rd1 [redis_deferring_client]\n        assert_equal {1} [psubscribe $rd1 *]\n        r psetex foo 100 1\n        assert_equal {pmessage * __keyevent@9__:expired foo} [$rd1 read]\n        $rd1 close\n    }\n\n    test \"Keyspace notifications: evicted events\" {\n        r config set notify-keyspace-events Ee\n        r config set maxmemory-policy allkeys-lru\n        r flushdb\n        set rd1 [redis_deferring_client]\n        assert_equal {1} [psubscribe $rd1 *]\n        r set foo bar\n        r config set maxmemory 1\n        assert_equal {pmessage * __keyevent@9__:evicted foo} [$rd1 read]\n        r config set maxmemory 0\n        $rd1 close\n    }\n\n    test \"Keyspace notifications: test CONFIG GET/SET of event flags\" {\n        r config set notify-keyspace-events gKE\n        assert_equal {gKE} [lindex [r config get notify-keyspace-events] 1]\n        r config set notify-keyspace-events {$lshzxeKE}\n        assert_equal {$lshzxeKE} [lindex [r config get notify-keyspace-events] 1]\n        r config set notify-keyspace-events KA\n        assert_equal {AK} [lindex [r config get notify-keyspace-events] 1]\n        r config set notify-keyspace-events EA\n        assert_equal {AE} [lindex [r config get notify-keyspace-events] 1]\n    }\n}\n"
  },
  {
    "path": "extern/deprecated/redis-2.8.21/tests/unit/quit.tcl",
    "content": "start_server {tags {\"quit\"}} {\n    proc format_command {args} {\n        set cmd \"*[llength $args]\\r\\n\"\n        foreach a $args {\n            append cmd \"$[string length $a]\\r\\n$a\\r\\n\"\n        }\n        set _ $cmd\n    }\n\n    test \"QUIT returns OK\" {\n        reconnect\n        assert_equal OK [r quit]\n        assert_error * {r ping}\n    }\n\n    test \"Pipelined commands after QUIT must not be executed\" {\n        reconnect\n        r write [format_command quit]\n        r write [format_command set foo bar]\n        r flush\n        assert_equal OK [r read]\n        assert_error * {r read}\n\n        reconnect\n        assert_equal {} [r get foo]\n    }\n\n    test \"Pipelined commands after QUIT that exceed read buffer size\" {\n        reconnect\n        r write [format_command quit]\n        r write [format_command set foo [string repeat \"x\" 1024]]\n        r flush\n        assert_equal OK [r read]\n        assert_error * {r read}\n\n        reconnect\n        assert_equal {} [r get foo]\n\n    }\n}\n"
  },
  {
    "path": "extern/deprecated/redis-2.8.21/tests/unit/scan.tcl",
    "content": "start_server {tags {\"scan\"}} {\n    test \"SCAN basic\" {\n        r flushdb\n        r debug populate 1000\n\n        set cur 0\n        set keys {}\n        while 1 {\n            set res [r scan $cur]\n            set cur [lindex $res 0]\n            set k [lindex $res 1]\n            lappend keys {*}$k\n            if {$cur == 0} break\n        }\n\n        set keys [lsort -unique $keys]\n        assert_equal 1000 [llength $keys]\n    }\n\n    test \"SCAN COUNT\" {\n        r flushdb\n        r debug populate 1000\n\n        set cur 0\n        set keys {}\n        while 1 {\n            set res [r scan $cur count 5]\n            set cur [lindex $res 0]\n            set k [lindex $res 1]\n            lappend keys {*}$k\n            if {$cur == 0} break\n        }\n\n        set keys [lsort -unique $keys]\n        assert_equal 1000 [llength $keys]\n    }\n\n    test \"SCAN MATCH\" {\n        r flushdb\n        r debug populate 1000\n\n        set cur 0\n        set keys {}\n        while 1 {\n            set res [r scan $cur match \"key:1??\"]\n            set cur [lindex $res 0]\n            set k [lindex $res 1]\n            lappend keys {*}$k\n            if {$cur == 0} break\n        }\n\n        set keys [lsort -unique $keys]\n        assert_equal 100 [llength $keys]\n    }\n\n    foreach enc {intset hashtable} {\n        test \"SSCAN with encoding $enc\" {\n            # Create the Set\n            r del set\n            if {$enc eq {intset}} {\n                set prefix \"\"\n            } else {\n                set prefix \"ele:\"\n            }\n            set elements {}\n            for {set j 0} {$j < 100} {incr j} {\n                lappend elements ${prefix}${j}\n            }\n            r sadd set {*}$elements\n\n            # Verify that the encoding matches.\n            assert {[r object encoding set] eq $enc}\n\n            # Test SSCAN\n            set cur 0\n            set keys {}\n            while 1 {\n                set res [r sscan set $cur]\n                set cur [lindex $res 0]\n                set k [lindex $res 1]\n                lappend keys {*}$k\n                if {$cur == 0} break\n            }\n\n            set keys [lsort -unique $keys]\n            assert_equal 100 [llength $keys]\n        }\n    }\n\n    foreach enc {ziplist hashtable} {\n        test \"HSCAN with encoding $enc\" {\n            # Create the Hash\n            r del hash\n            if {$enc eq {ziplist}} {\n                set count 30\n            } else {\n                set count 1000\n            }\n            set elements {}\n            for {set j 0} {$j < $count} {incr j} {\n                lappend elements key:$j $j\n            }\n            r hmset hash {*}$elements\n\n            # Verify that the encoding matches.\n            assert {[r object encoding hash] eq $enc}\n\n            # Test HSCAN\n            set cur 0\n            set keys {}\n            while 1 {\n                set res [r hscan hash $cur]\n                set cur [lindex $res 0]\n                set k [lindex $res 1]\n                lappend keys {*}$k\n                if {$cur == 0} break\n            }\n\n            set keys2 {}\n            foreach {k v} $keys {\n                assert {$k eq \"key:$v\"}\n                lappend keys2 $k\n            }\n\n            set keys2 [lsort -unique $keys2]\n            assert_equal $count [llength $keys2]\n        }\n    }\n\n    foreach enc {ziplist skiplist} {\n        test \"ZSCAN with encoding $enc\" {\n            # Create the Sorted Set\n            r del zset\n            if {$enc eq {ziplist}} {\n                set count 30\n            } else {\n                set count 1000\n            }\n            set elements {}\n            for {set j 0} {$j < $count} {incr j} {\n                lappend elements $j key:$j\n            }\n            r zadd zset {*}$elements\n\n            # Verify that the encoding matches.\n            assert {[r object encoding zset] eq $enc}\n\n            # Test ZSCAN\n            set cur 0\n            set keys {}\n            while 1 {\n                set res [r zscan zset $cur]\n                set cur [lindex $res 0]\n                set k [lindex $res 1]\n                lappend keys {*}$k\n                if {$cur == 0} break\n            }\n\n            set keys2 {}\n            foreach {k v} $keys {\n                assert {$k eq \"key:$v\"}\n                lappend keys2 $k\n            }\n\n            set keys2 [lsort -unique $keys2]\n            assert_equal $count [llength $keys2]\n        }\n    }\n\n    test \"SCAN guarantees check under write load\" {\n        r flushdb\n        r debug populate 100\n\n        # We start scanning here, so keys from 0 to 99 should all be\n        # reported at the end of the iteration.\n        set keys {}\n        while 1 {\n            set res [r scan $cur]\n            set cur [lindex $res 0]\n            set k [lindex $res 1]\n            lappend keys {*}$k\n            if {$cur == 0} break\n            # Write 10 random keys at every SCAN iteration.\n            for {set j 0} {$j < 10} {incr j} {\n                r set addedkey:[randomInt 1000] foo\n            }\n        }\n\n        set keys2 {}\n        foreach k $keys {\n            if {[string length $k] > 6} continue\n            lappend keys2 $k\n        }\n\n        set keys2 [lsort -unique $keys2]\n        assert_equal 100 [llength $keys2]\n    }\n\n    test \"SSCAN with integer encoded object (issue #1345)\" {\n        set objects {1 a}\n        r del set\n        r sadd set {*}$objects\n        set res [r sscan set 0 MATCH *a* COUNT 100]\n        assert_equal [lsort -unique [lindex $res 1]] {a}\n        set res [r sscan set 0 MATCH *1* COUNT 100]\n        assert_equal [lsort -unique [lindex $res 1]] {1}\n    }\n\n    test \"SSCAN with PATTERN\" {\n        r del mykey\n        r sadd mykey foo fab fiz foobar 1 2 3 4\n        set res [r sscan mykey 0 MATCH foo* COUNT 10000]\n        lsort -unique [lindex $res 1]\n    } {foo foobar}\n\n    test \"HSCAN with PATTERN\" {\n        r del mykey\n        r hmset mykey foo 1 fab 2 fiz 3 foobar 10 1 a 2 b 3 c 4 d\n        set res [r hscan mykey 0 MATCH foo* COUNT 10000]\n        lsort -unique [lindex $res 1]\n    } {1 10 foo foobar}\n\n    test \"ZSCAN with PATTERN\" {\n        r del mykey\n        r zadd mykey 1 foo 2 fab 3 fiz 10 foobar\n        set res [r zscan mykey 0 MATCH foo* COUNT 10000]\n        lsort -unique [lindex $res 1]\n    }\n\n    test \"ZSCAN scores: regression test for issue #2175\" {\n        r del mykey\n        for {set j 0} {$j < 500} {incr j} {\n            r zadd mykey 9.8813129168249309e-323 $j\n        }\n        set res [lindex [r zscan mykey 0] 1]\n        set first_score [lindex $res 1]\n        assert {$first_score != 0}\n    }\n}\n"
  },
  {
    "path": "extern/deprecated/redis-2.8.21/tests/unit/scripting.tcl",
    "content": "start_server {tags {\"scripting\"}} {\n    test {EVAL - Does Lua interpreter replies to our requests?} {\n        r eval {return 'hello'} 0\n    } {hello}\n\n    test {EVAL - Lua integer -> Redis protocol type conversion} {\n        r eval {return 100.5} 0\n    } {100}\n\n    test {EVAL - Lua string -> Redis protocol type conversion} {\n        r eval {return 'hello world'} 0\n    } {hello world}\n\n    test {EVAL - Lua true boolean -> Redis protocol type conversion} {\n        r eval {return true} 0\n    } {1}\n\n    test {EVAL - Lua false boolean -> Redis protocol type conversion} {\n        r eval {return false} 0\n    } {}\n\n    test {EVAL - Lua status code reply -> Redis protocol type conversion} {\n        r eval {return {ok='fine'}} 0\n    } {fine}\n\n    test {EVAL - Lua error reply -> Redis protocol type conversion} {\n        catch {\n            r eval {return {err='this is an error'}} 0\n        } e\n        set _ $e\n    } {this is an error}\n\n    test {EVAL - Lua table -> Redis protocol type conversion} {\n        r eval {return {1,2,3,'ciao',{1,2}}} 0\n    } {1 2 3 ciao {1 2}}\n\n    test {EVAL - Are the KEYS and ARGV arrays populated correctly?} {\n        r eval {return {KEYS[1],KEYS[2],ARGV[1],ARGV[2]}} 2 a b c d\n    } {a b c d}\n\n    test {EVAL - is Lua able to call Redis API?} {\n        r set mykey myval\n        r eval {return redis.call('get',KEYS[1])} 1 mykey\n    } {myval}\n\n    test {EVALSHA - Can we call a SHA1 if already defined?} {\n        r evalsha fd758d1589d044dd850a6f05d52f2eefd27f033f 1 mykey\n    } {myval}\n\n    test {EVALSHA - Can we call a SHA1 in uppercase?} {\n        r evalsha FD758D1589D044DD850A6F05D52F2EEFD27F033F 1 mykey\n    } {myval}\n\n    test {EVALSHA - Do we get an error on invalid SHA1?} {\n        catch {r evalsha NotValidShaSUM 0} e\n        set _ $e\n    } {NOSCRIPT*}\n\n    test {EVALSHA - Do we get an error on non defined SHA1?} {\n        catch {r evalsha ffd632c7d33e571e9f24556ebed26c3479a87130 0} e\n        set _ $e\n    } {NOSCRIPT*}\n\n    test {EVAL - Redis integer -> Lua type conversion} {\n        r eval {\n            local foo = redis.pcall('incr','x')\n            return {type(foo),foo}\n        } 0\n    } {number 1}\n\n    test {EVAL - Redis bulk -> Lua type conversion} {\n        r set mykey myval\n        r eval {\n            local foo = redis.pcall('get','mykey')\n            return {type(foo),foo}\n        } 0\n    } {string myval}\n\n    test {EVAL - Redis multi bulk -> Lua type conversion} {\n        r del mylist\n        r rpush mylist a\n        r rpush mylist b\n        r rpush mylist c\n        r eval {\n            local foo = redis.pcall('lrange','mylist',0,-1)\n            return {type(foo),foo[1],foo[2],foo[3],# foo}\n        } 0\n    } {table a b c 3}\n\n    test {EVAL - Redis status reply -> Lua type conversion} {\n        r eval {\n            local foo = redis.pcall('set','mykey','myval')\n            return {type(foo),foo['ok']}\n        } 0\n    } {table OK}\n\n    test {EVAL - Redis error reply -> Lua type conversion} {\n        r set mykey myval\n        r eval {\n            local foo = redis.pcall('incr','mykey')\n            return {type(foo),foo['err']}\n        } 0\n    } {table {ERR value is not an integer or out of range}}\n\n    test {EVAL - Redis nil bulk reply -> Lua type conversion} {\n        r del mykey\n        r eval {\n            local foo = redis.pcall('get','mykey')\n            return {type(foo),foo == false}\n        } 0\n    } {boolean 1}\n\n    test {EVAL - Is the Lua client using the currently selected DB?} {\n        r set mykey \"this is DB 9\"\n        r select 10\n        r set mykey \"this is DB 10\"\n        r eval {return redis.pcall('get','mykey')} 0\n    } {this is DB 10}\n\n    test {EVAL - SELECT inside Lua should not affect the caller} {\n        # here we DB 10 is selected\n        r set mykey \"original value\"\n        r eval {return redis.pcall('select','9')} 0\n        set res [r get mykey]\n        r select 9\n        set res\n    } {original value}\n\n    if 0 {\n        test {EVAL - Script can't run more than configured time limit} {\n            r config set lua-time-limit 1\n            catch {\n                r eval {\n                    local i = 0\n                    while true do i=i+1 end\n                } 0\n            } e\n            set _ $e\n        } {*execution time*}\n    }\n\n    test {EVAL - Scripts can't run certain commands} {\n        set e {}\n        catch {r eval {return redis.pcall('spop','x')} 0} e\n        set e\n    } {*not allowed*}\n\n    test {EVAL - Scripts can't run certain commands} {\n        set e {}\n        catch {\n            r eval \"redis.pcall('randomkey'); return redis.pcall('set','x','ciao')\" 0\n        } e\n        set e\n    } {*not allowed after*}\n\n    test {EVAL - No arguments to redis.call/pcall is considered an error} {\n        set e {}\n        catch {r eval {return redis.call()} 0} e\n        set e\n    } {*one argument*}\n\n    test {EVAL - redis.call variant raises a Lua error on Redis cmd error (1)} {\n        set e {}\n        catch {\n            r eval \"redis.call('nosuchcommand')\" 0\n        } e\n        set e\n    } {*Unknown Redis*}\n\n    test {EVAL - redis.call variant raises a Lua error on Redis cmd error (1)} {\n        set e {}\n        catch {\n            r eval \"redis.call('get','a','b','c')\" 0\n        } e\n        set e\n    } {*number of args*}\n\n    test {EVAL - redis.call variant raises a Lua error on Redis cmd error (1)} {\n        set e {}\n        r set foo bar\n        catch {\n            r eval {redis.call('lpush',KEYS[1],'val')} 1 foo\n        } e\n        set e\n    } {*against a key*}\n\n    test {EVAL - JSON numeric decoding} {\n        # We must return the table as a string because otherwise\n        # Redis converts floats to ints and we get 0 and 1023 instead\n        # of 0.0003 and 1023.2 as the parsed output.\n        r eval {return\n                 table.concat(\n                   cjson.decode(\n                    \"[0.0, -5e3, -1, 0.3e-3, 1023.2, 0e10]\"), \" \")\n        } 0\n    } {0 -5000 -1 0.0003 1023.2 0}\n\n    test {EVAL - JSON string decoding} {\n        r eval {local decoded = cjson.decode('{\"keya\": \"a\", \"keyb\": \"b\"}')\n                return {decoded.keya, decoded.keyb}\n        } 0\n    } {a b}\n\n    test {EVAL - cmsgpack can pack double?} {\n        r eval {local encoded = cmsgpack.pack(0.1)\n                local h = \"\"\n                for i = 1, #encoded do\n                    h = h .. string.format(\"%02x\",string.byte(encoded,i))\n                end\n                return h\n        } 0\n    } {cb3fb999999999999a}\n\n    test {EVAL - cmsgpack can pack negative int64?} {\n        r eval {local encoded = cmsgpack.pack(-1099511627776)\n                local h = \"\"\n                for i = 1, #encoded do\n                    h = h .. string.format(\"%02x\",string.byte(encoded,i))\n                end\n                return h\n        } 0\n    } {d3ffffff0000000000}\n\n    test {EVAL - cmsgpack can pack and unpack circular references?} {\n        r eval {local a = {x=nil,y=5}\n                local b = {x=a}\n                a['x'] = b\n                local encoded = cmsgpack.pack(a)\n                local h = \"\"\n                -- cmsgpack encodes to a depth of 16, but can't encode\n                -- references, so the encoded object has a deep copy recusive\n                -- depth of 16.\n                for i = 1, #encoded do\n                    h = h .. string.format(\"%02x\",string.byte(encoded,i))\n                end\n                -- when unpacked, re.x.x != re because the unpack creates\n                -- individual tables down to a depth of 16.\n                -- (that's why the encoded output is so large)\n                local re = cmsgpack.unpack(encoded)\n                assert(re)\n                assert(re.x)\n                assert(re.x.x.y == re.y)\n                assert(re.x.x.x.x.y == re.y)\n                assert(re.x.x.x.x.x.x.y == re.y)\n                assert(re.x.x.x.x.x.x.x.x.x.x.y == re.y)\n                -- maximum working depth:\n                assert(re.x.x.x.x.x.x.x.x.x.x.x.x.x.x.y == re.y)\n                -- now the last x would be b above and has no y\n                assert(re.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x)\n                -- so, the final x.x is at the depth limit and was assigned nil\n                assert(re.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x == nil)\n                return {h, re.x.x.x.x.x.x.x.x.y == re.y, re.y == 5}\n        } 0\n    } {82a17905a17881a17882a17905a17881a17882a17905a17881a17882a17905a17881a17882a17905a17881a17882a17905a17881a17882a17905a17881a17882a17905a17881a178c0 1 1}\n\n    test {EVAL - Numerical sanity check from bitop} {\n        r eval {assert(0x7fffffff == 2147483647, \"broken hex literals\");\n                assert(0xffffffff == -1 or 0xffffffff == 2^32-1,\n                    \"broken hex literals\");\n                assert(tostring(-1) == \"-1\", \"broken tostring()\");\n                assert(tostring(0xffffffff) == \"-1\" or\n                    tostring(0xffffffff) == \"4294967295\",\n                    \"broken tostring()\")\n        } 0\n    } {}\n\n    test {EVAL - Verify minimal bitop functionality} {\n        r eval {assert(bit.tobit(1) == 1);\n                assert(bit.band(1) == 1);\n                assert(bit.bxor(1,2) == 3);\n                assert(bit.bor(1,2,4,8,16,32,64,128) == 255)\n        } 0\n    } {}\n\n    test {SCRIPTING FLUSH - is able to clear the scripts cache?} {\n        r set mykey myval\n        set v [r evalsha fd758d1589d044dd850a6f05d52f2eefd27f033f 1 mykey]\n        assert_equal $v myval\n        set e \"\"\n        r script flush\n        catch {r evalsha fd758d1589d044dd850a6f05d52f2eefd27f033f 1 mykey} e\n        set e\n    } {NOSCRIPT*}\n\n    test {SCRIPT EXISTS - can detect already defined scripts?} {\n        r eval \"return 1+1\" 0\n        r script exists a27e7e8a43702b7046d4f6a7ccf5b60cef6b9bd9 a27e7e8a43702b7046d4f6a7ccf5b60cef6b9bda\n    } {1 0}\n\n    test {SCRIPT LOAD - is able to register scripts in the scripting cache} {\n        list \\\n            [r script load \"return 'loaded'\"] \\\n            [r evalsha b534286061d4b9e4026607613b95c06c06015ae8 0]\n    } {b534286061d4b9e4026607613b95c06c06015ae8 loaded}\n\n    test \"In the context of Lua the output of random commands gets ordered\" {\n        r del myset\n        r sadd myset a b c d e f g h i l m n o p q r s t u v z aa aaa azz\n        r eval {return redis.call('smembers',KEYS[1])} 1 myset\n    } {a aa aaa azz b c d e f g h i l m n o p q r s t u v z}\n\n    test \"SORT is normally not alpha re-ordered for the scripting engine\" {\n        r del myset\n        r sadd myset 1 2 3 4 10\n        r eval {return redis.call('sort',KEYS[1],'desc')} 1 myset\n    } {10 4 3 2 1}\n\n    test \"SORT BY <constant> output gets ordered for scripting\" {\n        r del myset\n        r sadd myset a b c d e f g h i l m n o p q r s t u v z aa aaa azz\n        r eval {return redis.call('sort',KEYS[1],'by','_')} 1 myset\n    } {a aa aaa azz b c d e f g h i l m n o p q r s t u v z}\n\n    test \"SORT BY <constant> with GET gets ordered for scripting\" {\n        r del myset\n        r sadd myset a b c\n        r eval {return redis.call('sort',KEYS[1],'by','_','get','#','get','_:*')} 1 myset\n    } {a {} b {} c {}}\n\n    test \"redis.sha1hex() implementation\" {\n        list [r eval {return redis.sha1hex('')} 0] \\\n             [r eval {return redis.sha1hex('Pizza & Mandolino')} 0]\n    } {da39a3ee5e6b4b0d3255bfef95601890afd80709 74822d82031af7493c20eefa13bd07ec4fada82f}\n\n    test {Globals protection reading an undeclared global variable} {\n        catch {r eval {return a} 0} e\n        set e\n    } {*ERR*attempted to access unexisting global*}\n\n    test {Globals protection setting an undeclared global*} {\n        catch {r eval {a=10} 0} e\n        set e\n    } {*ERR*attempted to create global*}\n\n    test {Test an example script DECR_IF_GT} {\n        set decr_if_gt {\n            local current\n\n            current = redis.call('get',KEYS[1])\n            if not current then return nil end\n            if current > ARGV[1] then\n                return redis.call('decr',KEYS[1])\n            else\n                return redis.call('get',KEYS[1])\n            end\n        }\n        r set foo 5\n        set res {}\n        lappend res [r eval $decr_if_gt 1 foo 2]\n        lappend res [r eval $decr_if_gt 1 foo 2]\n        lappend res [r eval $decr_if_gt 1 foo 2]\n        lappend res [r eval $decr_if_gt 1 foo 2]\n        lappend res [r eval $decr_if_gt 1 foo 2]\n        set res\n    } {4 3 2 2 2}\n\n    test {Scripting engine resets PRNG at every script execution} {\n        set rand1 [r eval {return tostring(math.random())} 0]\n        set rand2 [r eval {return tostring(math.random())} 0]\n        assert_equal $rand1 $rand2\n    }\n\n    test {Scripting engine PRNG can be seeded correctly} {\n        set rand1 [r eval {\n            math.randomseed(ARGV[1]); return tostring(math.random())\n        } 0 10]\n        set rand2 [r eval {\n            math.randomseed(ARGV[1]); return tostring(math.random())\n        } 0 10]\n        set rand3 [r eval {\n            math.randomseed(ARGV[1]); return tostring(math.random())\n        } 0 20]\n        assert_equal $rand1 $rand2\n        assert {$rand2 ne $rand3}\n    }\n\n    test {EVAL does not leak in the Lua stack} {\n        r set x 0\n        # Use a non blocking client to speedup the loop.\n        set rd [redis_deferring_client]\n        for {set j 0} {$j < 10000} {incr j} {\n            $rd eval {return redis.call(\"incr\",KEYS[1])} 1 x\n        }\n        for {set j 0} {$j < 10000} {incr j} {\n            $rd read\n        }\n        assert {[s used_memory_lua] < 1024*100}\n        $rd close\n        r get x\n    } {10000}\n\n    test {EVAL processes writes from AOF in read-only slaves} {\n        r flushall\n        r config set appendonly yes\n        r eval {redis.call(\"set\",KEYS[1],\"100\")} 1 foo\n        r eval {redis.call(\"incr\",KEYS[1])} 1 foo\n        r eval {redis.call(\"incr\",KEYS[1])} 1 foo\n        wait_for_condition 50 100 {\n            [s aof_rewrite_in_progress] == 0\n        } else {\n            fail \"AOF rewrite can't complete after CONFIG SET appendonly yes.\"\n        }\n        r config set slave-read-only yes\n        r slaveof 127.0.0.1 0\n        r debug loadaof\n        set res [r get foo]\n        r slaveof no one\n        set res\n    } {102}\n\n    test {We can call scripts rewriting client->argv from Lua} {\n        r del myset\n        r sadd myset a b c\n        r mset a 1 b 2 c 3 d 4\n        assert {[r spop myset] ne {}}\n        assert {[r spop myset] ne {}}\n        assert {[r spop myset] ne {}}\n        assert {[r mget a b c d] eq {1 2 3 4}}\n        assert {[r spop myset] eq {}}\n    }\n\n    test {Call Redis command with many args from Lua (issue #1764)} {\n        r eval {\n            local i\n            local x={}\n            redis.call('del','mylist')\n            for i=1,100 do\n                table.insert(x,i)\n            end\n            redis.call('rpush','mylist',unpack(x))\n            return redis.call('lrange','mylist',0,-1)\n        } 0\n    } {1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100}\n\n    test {Number conversion precision test (issue #1118)} {\n        r eval {\n              local value = 9007199254740991\n              redis.call(\"set\",\"foo\",value)\n              return redis.call(\"get\",\"foo\")\n        } 0\n    } {9007199254740991}\n\n    test {String containing number precision test (regression of issue #1118)} {\n        r eval {\n            redis.call(\"set\", \"key\", \"12039611435714932082\")\n            return redis.call(\"get\", \"key\")\n        } 0\n    } {12039611435714932082}\n\n    test {Verify negative arg count is error instead of crash (issue #1842)} {\n        catch { r eval { return \"hello\" } -12 } e\n        set e\n    } {ERR Number of keys can't be negative}\n\n    test {Correct handling of reused argv (issue #1939)} {\n        r eval {\n              for i = 0, 10 do\n                  redis.call('SET', 'a', '1')\n                  redis.call('MGET', 'a', 'b', 'c')\n                  redis.call('EXPIRE', 'a', 0)\n                  redis.call('GET', 'a')\n                  redis.call('MGET', 'a', 'b', 'c')\n              end\n        } 0\n    }\n}\n\n# Start a new server since the last test in this stanza will kill the\n# instance at all.\nstart_server {tags {\"scripting\"}} {\n    test {Timedout read-only scripts can be killed by SCRIPT KILL} {\n        set rd [redis_deferring_client]\n        r config set lua-time-limit 10\n        $rd eval {while true do end} 0\n        after 200\n        catch {r ping} e\n        assert_match {BUSY*} $e\n        r script kill\n        after 200 ; # Give some time to Lua to call the hook again...\n        assert_equal [r ping] \"PONG\"\n    }\n\n    test {Timedout script link is still usable after Lua returns} {\n        r config set lua-time-limit 10\n        r eval {for i=1,100000 do redis.call('ping') end return 'ok'} 0\n        r ping\n    } {PONG}\n\n    test {Timedout scripts that modified data can't be killed by SCRIPT KILL} {\n        set rd [redis_deferring_client]\n        r config set lua-time-limit 10\n        $rd eval {redis.call('set',KEYS[1],'y'); while true do end} 1 x\n        after 200\n        catch {r ping} e\n        assert_match {BUSY*} $e\n        catch {r script kill} e\n        assert_match {UNKILLABLE*} $e\n        catch {r ping} e\n        assert_match {BUSY*} $e\n    }\n\n    # Note: keep this test at the end of this server stanza because it\n    # kills the server.\n    test {SHUTDOWN NOSAVE can kill a timedout script anyway} {\n        # The server sould be still unresponding to normal commands.\n        catch {r ping} e\n        assert_match {BUSY*} $e\n        catch {r shutdown nosave}\n        # Make sure the server was killed\n        catch {set rd [redis_deferring_client]} e\n        assert_match {*connection refused*} $e\n    }\n}\n\nstart_server {tags {\"scripting repl\"}} {\n    start_server {} {\n        test {Before the slave connects we issue two EVAL commands} {\n            # One with an error, but still executing a command.\n            # SHA is: 67164fc43fa971f76fd1aaeeaf60c1c178d25876\n            catch {\n                r eval {redis.call('incr',KEYS[1]); redis.call('nonexisting')} 1 x\n            }\n            # One command is correct:\n            # SHA is: 6f5ade10a69975e903c6d07b10ea44c6382381a5\n            r eval {return redis.call('incr',KEYS[1])} 1 x\n        } {2}\n\n        test {Connect a slave to the main instance} {\n            r -1 slaveof [srv 0 host] [srv 0 port]\n            wait_for_condition 50 100 {\n                [s -1 role] eq {slave} &&\n                [string match {*master_link_status:up*} [r -1 info replication]]\n            } else {\n                fail \"Can't turn the instance into a slave\"\n            }\n        }\n\n        test {Now use EVALSHA against the master, with both SHAs} {\n            # The server should replicate successful and unsuccessful\n            # commands as EVAL instead of EVALSHA.\n            catch {\n                r evalsha 67164fc43fa971f76fd1aaeeaf60c1c178d25876 1 x\n            }\n            r evalsha 6f5ade10a69975e903c6d07b10ea44c6382381a5 1 x\n        } {4}\n\n        test {If EVALSHA was replicated as EVAL, 'x' should be '4'} {\n            wait_for_condition 50 100 {\n                [r -1 get x] eq {4}\n            } else {\n                fail \"Expected 4 in x, but value is '[r -1 get x]'\"\n            }\n        }\n\n        test {Replication of script multiple pushes to list with BLPOP} {\n            set rd [redis_deferring_client]\n            $rd brpop a 0\n            r eval {\n                redis.call(\"lpush\",KEYS[1],\"1\");\n                redis.call(\"lpush\",KEYS[1],\"2\");\n            } 1 a\n            set res [$rd read]\n            $rd close\n            wait_for_condition 50 100 {\n                [r -1 lrange a 0 -1] eq [r lrange a 0 -1]\n            } else {\n                fail \"Expected list 'a' in slave and master to be the same, but they are respectively '[r -1 lrange a 0 -1]' and '[r lrange a 0 -1]'\"\n            }\n            set res\n        } {a 1}\n\n        test {EVALSHA replication when first call is readonly} {\n            r del x\n            r eval {if tonumber(ARGV[1]) > 0 then redis.call('incr', KEYS[1]) end} 1 x 0\n            r evalsha 6e0e2745aa546d0b50b801a20983b70710aef3ce 1 x 0\n            r evalsha 6e0e2745aa546d0b50b801a20983b70710aef3ce 1 x 1\n            wait_for_condition 50 100 {\n                [r -1 get x] eq {1}\n            } else {\n                fail \"Expected 1 in x, but value is '[r -1 get x]'\"\n            }\n        }\n\n        test {Lua scripts using SELECT are replicated correctly} {\n            r eval {\n                redis.call(\"set\",\"foo1\",\"bar1\")\n                redis.call(\"select\",\"10\")\n                redis.call(\"incr\",\"x\")\n                redis.call(\"select\",\"11\")\n                redis.call(\"incr\",\"z\")\n            } 0\n            r eval {\n                redis.call(\"set\",\"foo1\",\"bar1\")\n                redis.call(\"select\",\"10\")\n                redis.call(\"incr\",\"x\")\n                redis.call(\"select\",\"11\")\n                redis.call(\"incr\",\"z\")\n            } 0\n            wait_for_condition 50 100 {\n                [r -1 debug digest] eq [r debug digest]\n            } else {\n                fail \"Master-Slave desync after Lua script using SELECT.\"\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "extern/deprecated/redis-2.8.21/tests/unit/slowlog.tcl",
    "content": "start_server {tags {\"slowlog\"} overrides {slowlog-log-slower-than 1000000}} {\n    test {SLOWLOG - check that it starts with an empty log} {\n        r slowlog len\n    } {0}\n\n    test {SLOWLOG - only logs commands taking more time than specified} {\n        r config set slowlog-log-slower-than 100000\n        r ping\n        assert_equal [r slowlog len] 0\n        r debug sleep 0.2\n        assert_equal [r slowlog len] 1\n    }\n\n    test {SLOWLOG - max entries is correctly handled} {\n        r config set slowlog-log-slower-than 0\n        r config set slowlog-max-len 10\n        for {set i 0} {$i < 100} {incr i} {\n            r ping\n        }\n        r slowlog len\n    } {10}\n\n    test {SLOWLOG - GET optional argument to limit output len works} {\n        llength [r slowlog get 5]\n    } {5}\n\n    test {SLOWLOG - RESET subcommand works} {\n        r config set slowlog-log-slower-than 100000\n        r slowlog reset\n        r slowlog len\n    } {0}\n\n    test {SLOWLOG - logged entry sanity check} {\n        r debug sleep 0.2\n        set e [lindex [r slowlog get] 0]\n        assert_equal [llength $e] 4\n        assert_equal [lindex $e 0] 105\n        assert_equal [expr {[lindex $e 2] > 100000}] 1\n        assert_equal [lindex $e 3] {debug sleep 0.2}\n    }\n\n    test {SLOWLOG - commands with too many arguments are trimmed} {\n        r config set slowlog-log-slower-than 0\n        r slowlog reset\n        r sadd set 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33\n        set e [lindex [r slowlog get] 0]\n        lindex $e 3\n    } {sadd set 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 {... (2 more arguments)}}\n\n    test {SLOWLOG - too long arguments are trimmed} {\n        r config set slowlog-log-slower-than 0\n        r slowlog reset\n        set arg [string repeat A 129]\n        r sadd set foo $arg\n        set e [lindex [r slowlog get] 0]\n        lindex $e 3\n    } {sadd set foo {AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA... (1 more bytes)}}\n\n    test {SLOWLOG - EXEC is not logged, just executed commands} {\n        r config set slowlog-log-slower-than 100000\n        r slowlog reset\n        assert_equal [r slowlog len] 0\n        r multi\n        r debug sleep 0.2\n        r exec\n        assert_equal [r slowlog len] 1\n        set e [lindex [r slowlog get] 0]\n        assert_equal [lindex $e 3] {debug sleep 0.2}\n    }\n}\n"
  },
  {
    "path": "extern/deprecated/redis-2.8.21/tests/unit/sort.tcl",
    "content": "start_server {\n    tags {\"sort\"}\n    overrides {\n        \"list-max-ziplist-value\" 16\n        \"list-max-ziplist-entries\" 32\n        \"set-max-intset-entries\" 32\n    }\n} {\n    proc create_random_dataset {num cmd} {\n        set tosort {}\n        set result {}\n        array set seenrand {}\n        r del tosort\n        for {set i 0} {$i < $num} {incr i} {\n            # Make sure all the weights are different because\n            # Redis does not use a stable sort but Tcl does.\n            while 1 {\n                randpath {\n                    set rint [expr int(rand()*1000000)]\n                } {\n                    set rint [expr rand()]\n                }\n                if {![info exists seenrand($rint)]} break\n            }\n            set seenrand($rint) x\n            r $cmd tosort $i\n            r set weight_$i $rint\n            r hset wobj_$i weight $rint\n            lappend tosort [list $i $rint]\n        }\n        set sorted [lsort -index 1 -real $tosort]\n        for {set i 0} {$i < $num} {incr i} {\n            lappend result [lindex $sorted $i 0]\n        }\n        set _ $result\n    }\n\n    foreach {num cmd enc title} {\n        16 lpush ziplist \"Ziplist\"\n        1000 lpush linkedlist \"Linked list\"\n        10000 lpush linkedlist \"Big Linked list\"\n        16 sadd intset \"Intset\"\n        1000 sadd hashtable \"Hash table\"\n        10000 sadd hashtable \"Big Hash table\"\n    } {\n        set result [create_random_dataset $num $cmd]\n        assert_encoding $enc tosort\n\n        test \"$title: SORT BY key\" {\n            assert_equal $result [r sort tosort BY weight_*]\n        }\n\n        test \"$title: SORT BY key with limit\" {\n            assert_equal [lrange $result 5 9] [r sort tosort BY weight_* LIMIT 5 5]\n        }\n\n        test \"$title: SORT BY hash field\" {\n            assert_equal $result [r sort tosort BY wobj_*->weight]\n        }\n    }\n\n    set result [create_random_dataset 16 lpush]\n    test \"SORT GET #\" {\n        assert_equal [lsort -integer $result] [r sort tosort GET #]\n    }\n\n    test \"SORT GET <const>\" {\n        r del foo\n        set res [r sort tosort GET foo]\n        assert_equal 16 [llength $res]\n        foreach item $res { assert_equal {} $item }\n    }\n\n    test \"SORT GET (key and hash) with sanity check\" {\n        set l1 [r sort tosort GET # GET weight_*]\n        set l2 [r sort tosort GET # GET wobj_*->weight]\n        foreach {id1 w1} $l1 {id2 w2} $l2 {\n            assert_equal $id1 $id2\n            assert_equal $w1 [r get weight_$id1]\n            assert_equal $w2 [r get weight_$id1]\n        }\n    }\n\n    test \"SORT BY key STORE\" {\n        r sort tosort BY weight_* store sort-res\n        assert_equal $result [r lrange sort-res 0 -1]\n        assert_equal 16 [r llen sort-res]\n        assert_encoding ziplist sort-res\n    }\n\n    test \"SORT BY hash field STORE\" {\n        r sort tosort BY wobj_*->weight store sort-res\n        assert_equal $result [r lrange sort-res 0 -1]\n        assert_equal 16 [r llen sort-res]\n        assert_encoding ziplist sort-res\n    }\n\n    test \"SORT DESC\" {\n        assert_equal [lsort -decreasing -integer $result] [r sort tosort DESC]\n    }\n\n    test \"SORT ALPHA against integer encoded strings\" {\n        r del mylist\n        r lpush mylist 2\n        r lpush mylist 1\n        r lpush mylist 3\n        r lpush mylist 10\n        r sort mylist alpha\n    } {1 10 2 3}\n\n    test \"SORT sorted set\" {\n        r del zset\n        r zadd zset 1 a\n        r zadd zset 5 b\n        r zadd zset 2 c\n        r zadd zset 10 d\n        r zadd zset 3 e\n        r sort zset alpha desc\n    } {e d c b a}\n\n    test \"SORT sorted set BY nosort should retain ordering\" {\n        r del zset\n        r zadd zset 1 a\n        r zadd zset 5 b\n        r zadd zset 2 c\n        r zadd zset 10 d\n        r zadd zset 3 e\n        r multi\n        r sort zset by nosort asc\n        r sort zset by nosort desc\n        r exec\n    } {{a c e b d} {d b e c a}}\n\n    test \"SORT sorted set BY nosort + LIMIT\" {\n        r del zset\n        r zadd zset 1 a\n        r zadd zset 5 b\n        r zadd zset 2 c\n        r zadd zset 10 d\n        r zadd zset 3 e\n        assert_equal [r sort zset by nosort asc limit 0 1] {a}\n        assert_equal [r sort zset by nosort desc limit 0 1] {d}\n        assert_equal [r sort zset by nosort asc limit 0 2] {a c}\n        assert_equal [r sort zset by nosort desc limit 0 2] {d b}\n        assert_equal [r sort zset by nosort limit 5 10] {}\n        assert_equal [r sort zset by nosort limit -10 100] {a c e b d}\n    }\n\n    test \"SORT sorted set BY nosort works as expected from scripts\" {\n        r del zset\n        r zadd zset 1 a\n        r zadd zset 5 b\n        r zadd zset 2 c\n        r zadd zset 10 d\n        r zadd zset 3 e\n        r eval {\n            return {redis.call('sort',KEYS[1],'by','nosort','asc'),\n                    redis.call('sort',KEYS[1],'by','nosort','desc')}\n        } 1 zset\n    } {{a c e b d} {d b e c a}}\n\n    test \"SORT sorted set: +inf and -inf handling\" {\n        r del zset\n        r zadd zset -100 a\n        r zadd zset 200 b\n        r zadd zset -300 c\n        r zadd zset 1000000 d\n        r zadd zset +inf max\n        r zadd zset -inf min\n        r zrange zset 0 -1\n    } {min c a b d max}\n\n    test \"SORT regression for issue #19, sorting floats\" {\n        r flushdb\n        set floats {1.1 5.10 3.10 7.44 2.1 5.75 6.12 0.25 1.15}\n        foreach x $floats {\n            r lpush mylist $x\n        }\n        assert_equal [lsort -real $floats] [r sort mylist]\n    }\n\n    test \"SORT with STORE returns zero if result is empty (github issue 224)\" {\n        r flushdb\n        r sort foo store bar\n    } {0}\n\n    test \"SORT with STORE does not create empty lists (github issue 224)\" {\n        r flushdb\n        r lpush foo bar\n        r sort foo alpha limit 10 10 store zap\n        r exists zap\n    } {0}\n\n    test \"SORT with STORE removes key if result is empty (github issue 227)\" {\n        r flushdb\n        r lpush foo bar\n        r sort emptylist store foo\n        r exists foo\n    } {0}\n\n    test \"SORT with BY <constant> and STORE should still order output\" {\n        r del myset mylist\n        r sadd myset a b c d e f g h i l m n o p q r s t u v z aa aaa azz\n        r sort myset alpha by _ store mylist\n        r lrange mylist 0 -1\n    } {a aa aaa azz b c d e f g h i l m n o p q r s t u v z}\n\n    test \"SORT will complain with numerical sorting and bad doubles (1)\" {\n        r del myset\n        r sadd myset 1 2 3 4 not-a-double\n        set e {}\n        catch {r sort myset} e\n        set e\n    } {*ERR*double*}\n\n    test \"SORT will complain with numerical sorting and bad doubles (2)\" {\n        r del myset\n        r sadd myset 1 2 3 4\n        r mset score:1 10 score:2 20 score:3 30 score:4 not-a-double\n        set e {}\n        catch {r sort myset by score:*} e\n        set e\n    } {*ERR*double*}\n\n    test \"SORT BY sub-sorts lexicographically if score is the same\" {\n        r del myset\n        r sadd myset a b c d e f g h i l m n o p q r s t u v z aa aaa azz\n        foreach ele {a aa aaa azz b c d e f g h i l m n o p q r s t u v z} {\n            set score:$ele 100\n        }\n        r sort myset by score:*\n    } {a aa aaa azz b c d e f g h i l m n o p q r s t u v z}\n\n    test \"SORT GET with pattern ending with just -> does not get hash field\" {\n        r del mylist\n        r lpush mylist a\n        r set x:a-> 100\n        r sort mylist by num get x:*->\n    } {100}\n\n    test \"SORT by nosort retains native order for lists\" {\n        r del testa\n        r lpush testa 2 1 4 3 5\n        r sort testa by nosort\n    } {5 3 4 1 2}\n\n    test \"SORT by nosort plus store retains native order for lists\" {\n        r del testa\n        r lpush testa 2 1 4 3 5\n        r sort testa by nosort store testb\n        r lrange testb 0 -1\n    } {5 3 4 1 2}\n\n    test \"SORT by nosort with limit returns based on original list order\" {\n        r sort testa by nosort limit 0 3 store testb\n        r lrange testb 0 -1\n    } {5 3 4}\n\n    tags {\"slow\"} {\n        set num 100\n        set res [create_random_dataset $num lpush]\n\n        test \"SORT speed, $num element list BY key, 100 times\" {\n            set start [clock clicks -milliseconds]\n            for {set i 0} {$i < 100} {incr i} {\n                set sorted [r sort tosort BY weight_* LIMIT 0 10]\n            }\n            set elapsed [expr [clock clicks -milliseconds]-$start]\n            if {$::verbose} {\n                puts -nonewline \"\\n  Average time to sort: [expr double($elapsed)/100] milliseconds \"\n                flush stdout\n            }\n        }\n\n        test \"SORT speed, $num element list BY hash field, 100 times\" {\n            set start [clock clicks -milliseconds]\n            for {set i 0} {$i < 100} {incr i} {\n                set sorted [r sort tosort BY wobj_*->weight LIMIT 0 10]\n            }\n            set elapsed [expr [clock clicks -milliseconds]-$start]\n            if {$::verbose} {\n                puts -nonewline \"\\n  Average time to sort: [expr double($elapsed)/100] milliseconds \"\n                flush stdout\n            }\n        }\n\n        test \"SORT speed, $num element list directly, 100 times\" {\n            set start [clock clicks -milliseconds]\n            for {set i 0} {$i < 100} {incr i} {\n                set sorted [r sort tosort LIMIT 0 10]\n            }\n            set elapsed [expr [clock clicks -milliseconds]-$start]\n            if {$::verbose} {\n                puts -nonewline \"\\n  Average time to sort: [expr double($elapsed)/100] milliseconds \"\n                flush stdout\n            }\n        }\n\n        test \"SORT speed, $num element list BY <const>, 100 times\" {\n            set start [clock clicks -milliseconds]\n            for {set i 0} {$i < 100} {incr i} {\n                set sorted [r sort tosort BY nokey LIMIT 0 10]\n            }\n            set elapsed [expr [clock clicks -milliseconds]-$start]\n            if {$::verbose} {\n                puts -nonewline \"\\n  Average time to sort: [expr double($elapsed)/100] milliseconds \"\n                flush stdout\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "extern/deprecated/redis-2.8.21/tests/unit/type/hash.tcl",
    "content": "start_server {tags {\"hash\"}} {\n    test {HSET/HLEN - Small hash creation} {\n        array set smallhash {}\n        for {set i 0} {$i < 8} {incr i} {\n            set key [randstring 0 8 alpha]\n            set val [randstring 0 8 alpha]\n            if {[info exists smallhash($key)]} {\n                incr i -1\n                continue\n            }\n            r hset smallhash $key $val\n            set smallhash($key) $val\n        }\n        list [r hlen smallhash]\n    } {8}\n\n    test {Is the small hash encoded with a ziplist?} {\n        assert_encoding ziplist smallhash\n    }\n\n    test {HSET/HLEN - Big hash creation} {\n        array set bighash {}\n        for {set i 0} {$i < 1024} {incr i} {\n            set key [randstring 0 8 alpha]\n            set val [randstring 0 8 alpha]\n            if {[info exists bighash($key)]} {\n                incr i -1\n                continue\n            }\n            r hset bighash $key $val\n            set bighash($key) $val\n        }\n        list [r hlen bighash]\n    } {1024}\n\n    test {Is the big hash encoded with a ziplist?} {\n        assert_encoding hashtable bighash\n    }\n\n    test {HGET against the small hash} {\n        set err {}\n        foreach k [array names smallhash *] {\n            if {$smallhash($k) ne [r hget smallhash $k]} {\n                set err \"$smallhash($k) != [r hget smallhash $k]\"\n                break\n            }\n        }\n        set _ $err\n    } {}\n\n    test {HGET against the big hash} {\n        set err {}\n        foreach k [array names bighash *] {\n            if {$bighash($k) ne [r hget bighash $k]} {\n                set err \"$bighash($k) != [r hget bighash $k]\"\n                break\n            }\n        }\n        set _ $err\n    } {}\n\n    test {HGET against non existing key} {\n        set rv {}\n        lappend rv [r hget smallhash __123123123__]\n        lappend rv [r hget bighash __123123123__]\n        set _ $rv\n    } {{} {}}\n\n    test {HSET in update and insert mode} {\n        set rv {}\n        set k [lindex [array names smallhash *] 0]\n        lappend rv [r hset smallhash $k newval1]\n        set smallhash($k) newval1\n        lappend rv [r hget smallhash $k]\n        lappend rv [r hset smallhash __foobar123__ newval]\n        set k [lindex [array names bighash *] 0]\n        lappend rv [r hset bighash $k newval2]\n        set bighash($k) newval2\n        lappend rv [r hget bighash $k]\n        lappend rv [r hset bighash __foobar123__ newval]\n        lappend rv [r hdel smallhash __foobar123__]\n        lappend rv [r hdel bighash __foobar123__]\n        set _ $rv\n    } {0 newval1 1 0 newval2 1 1 1}\n\n    test {HSETNX target key missing - small hash} {\n        r hsetnx smallhash __123123123__ foo\n        r hget smallhash __123123123__\n    } {foo}\n\n    test {HSETNX target key exists - small hash} {\n        r hsetnx smallhash __123123123__ bar\n        set result [r hget smallhash __123123123__]\n        r hdel smallhash __123123123__\n        set _ $result\n    } {foo}\n\n    test {HSETNX target key missing - big hash} {\n        r hsetnx bighash __123123123__ foo\n        r hget bighash __123123123__\n    } {foo}\n\n    test {HSETNX target key exists - big hash} {\n        r hsetnx bighash __123123123__ bar\n        set result [r hget bighash __123123123__]\n        r hdel bighash __123123123__\n        set _ $result\n    } {foo}\n\n    test {HMSET wrong number of args} {\n        catch {r hmset smallhash key1 val1 key2} err\n        format $err\n    } {*wrong number*}\n\n    test {HMSET - small hash} {\n        set args {}\n        foreach {k v} [array get smallhash] {\n            set newval [randstring 0 8 alpha]\n            set smallhash($k) $newval\n            lappend args $k $newval\n        }\n        r hmset smallhash {*}$args\n    } {OK}\n\n    test {HMSET - big hash} {\n        set args {}\n        foreach {k v} [array get bighash] {\n            set newval [randstring 0 8 alpha]\n            set bighash($k) $newval\n            lappend args $k $newval\n        }\n        r hmset bighash {*}$args\n    } {OK}\n\n    test {HMGET against non existing key and fields} {\n        set rv {}\n        lappend rv [r hmget doesntexist __123123123__ __456456456__]\n        lappend rv [r hmget smallhash __123123123__ __456456456__]\n        lappend rv [r hmget bighash __123123123__ __456456456__]\n        set _ $rv\n    } {{{} {}} {{} {}} {{} {}}}\n\n    test {HMGET against wrong type} {\n        r set wrongtype somevalue\n        assert_error \"*wrong*\" {r hmget wrongtype field1 field2}\n    }\n\n    test {HMGET - small hash} {\n        set keys {}\n        set vals {}\n        foreach {k v} [array get smallhash] {\n            lappend keys $k\n            lappend vals $v\n        }\n        set err {}\n        set result [r hmget smallhash {*}$keys]\n        if {$vals ne $result} {\n            set err \"$vals != $result\"\n            break\n        }\n        set _ $err\n    } {}\n\n    test {HMGET - big hash} {\n        set keys {}\n        set vals {}\n        foreach {k v} [array get bighash] {\n            lappend keys $k\n            lappend vals $v\n        }\n        set err {}\n        set result [r hmget bighash {*}$keys]\n        if {$vals ne $result} {\n            set err \"$vals != $result\"\n            break\n        }\n        set _ $err\n    } {}\n\n    test {HKEYS - small hash} {\n        lsort [r hkeys smallhash]\n    } [lsort [array names smallhash *]]\n\n    test {HKEYS - big hash} {\n        lsort [r hkeys bighash]\n    } [lsort [array names bighash *]]\n\n    test {HVALS - small hash} {\n        set vals {}\n        foreach {k v} [array get smallhash] {\n            lappend vals $v\n        }\n        set _ [lsort $vals]\n    } [lsort [r hvals smallhash]]\n\n    test {HVALS - big hash} {\n        set vals {}\n        foreach {k v} [array get bighash] {\n            lappend vals $v\n        }\n        set _ [lsort $vals]\n    } [lsort [r hvals bighash]]\n\n    test {HGETALL - small hash} {\n        lsort [r hgetall smallhash]\n    } [lsort [array get smallhash]]\n\n    test {HGETALL - big hash} {\n        lsort [r hgetall bighash]\n    } [lsort [array get bighash]]\n\n    test {HDEL and return value} {\n        set rv {}\n        lappend rv [r hdel smallhash nokey]\n        lappend rv [r hdel bighash nokey]\n        set k [lindex [array names smallhash *] 0]\n        lappend rv [r hdel smallhash $k]\n        lappend rv [r hdel smallhash $k]\n        lappend rv [r hget smallhash $k]\n        unset smallhash($k)\n        set k [lindex [array names bighash *] 0]\n        lappend rv [r hdel bighash $k]\n        lappend rv [r hdel bighash $k]\n        lappend rv [r hget bighash $k]\n        unset bighash($k)\n        set _ $rv\n    } {0 0 1 0 {} 1 0 {}}\n\n    test {HDEL - more than a single value} {\n        set rv {}\n        r del myhash\n        r hmset myhash a 1 b 2 c 3\n        assert_equal 0 [r hdel myhash x y]\n        assert_equal 2 [r hdel myhash a c f]\n        r hgetall myhash\n    } {b 2}\n\n    test {HDEL - hash becomes empty before deleting all specified fields} {\n        r del myhash\n        r hmset myhash a 1 b 2 c 3\n        assert_equal 3 [r hdel myhash a b c d e]\n        assert_equal 0 [r exists myhash]\n    }\n\n    test {HEXISTS} {\n        set rv {}\n        set k [lindex [array names smallhash *] 0]\n        lappend rv [r hexists smallhash $k]\n        lappend rv [r hexists smallhash nokey]\n        set k [lindex [array names bighash *] 0]\n        lappend rv [r hexists bighash $k]\n        lappend rv [r hexists bighash nokey]\n    } {1 0 1 0}\n\n    test {Is a ziplist encoded Hash promoted on big payload?} {\n        r hset smallhash foo [string repeat a 1024]\n        r debug object smallhash\n    } {*hashtable*}\n\n    test {HINCRBY against non existing database key} {\n        r del htest\n        list [r hincrby htest foo 2]\n    } {2}\n\n    test {HINCRBY against non existing hash key} {\n        set rv {}\n        r hdel smallhash tmp\n        r hdel bighash tmp\n        lappend rv [r hincrby smallhash tmp 2]\n        lappend rv [r hget smallhash tmp]\n        lappend rv [r hincrby bighash tmp 2]\n        lappend rv [r hget bighash tmp]\n    } {2 2 2 2}\n\n    test {HINCRBY against hash key created by hincrby itself} {\n        set rv {}\n        lappend rv [r hincrby smallhash tmp 3]\n        lappend rv [r hget smallhash tmp]\n        lappend rv [r hincrby bighash tmp 3]\n        lappend rv [r hget bighash tmp]\n    } {5 5 5 5}\n\n    test {HINCRBY against hash key originally set with HSET} {\n        r hset smallhash tmp 100\n        r hset bighash tmp 100\n        list [r hincrby smallhash tmp 2] [r hincrby bighash tmp 2]\n    } {102 102}\n\n    test {HINCRBY over 32bit value} {\n        r hset smallhash tmp 17179869184\n        r hset bighash tmp 17179869184\n        list [r hincrby smallhash tmp 1] [r hincrby bighash tmp 1]\n    } {17179869185 17179869185}\n\n    test {HINCRBY over 32bit value with over 32bit increment} {\n        r hset smallhash tmp 17179869184\n        r hset bighash tmp 17179869184\n        list [r hincrby smallhash tmp 17179869184] [r hincrby bighash tmp 17179869184]\n    } {34359738368 34359738368}\n\n    test {HINCRBY fails against hash value with spaces (left)} {\n        r hset smallhash str \" 11\"\n        r hset bighash str \" 11\"\n        catch {r hincrby smallhash str 1} smallerr\n        catch {r hincrby smallhash str 1} bigerr\n        set rv {}\n        lappend rv [string match \"ERR*not an integer*\" $smallerr]\n        lappend rv [string match \"ERR*not an integer*\" $bigerr]\n    } {1 1}\n\n    test {HINCRBY fails against hash value with spaces (right)} {\n        r hset smallhash str \"11 \"\n        r hset bighash str \"11 \"\n        catch {r hincrby smallhash str 1} smallerr\n        catch {r hincrby smallhash str 1} bigerr\n        set rv {}\n        lappend rv [string match \"ERR*not an integer*\" $smallerr]\n        lappend rv [string match \"ERR*not an integer*\" $bigerr]\n    } {1 1}\n\n    test {HINCRBY can detect overflows} {\n        set e {}\n        r hset hash n -9223372036854775484\n        assert {[r hincrby hash n -1] == -9223372036854775485}\n        catch {r hincrby hash n -10000} e\n        set e\n    } {*overflow*}\n\n    test {HINCRBYFLOAT against non existing database key} {\n        r del htest\n        list [r hincrbyfloat htest foo 2.5]\n    } {2.5}\n\n    test {HINCRBYFLOAT against non existing hash key} {\n        set rv {}\n        r hdel smallhash tmp\n        r hdel bighash tmp\n        lappend rv [roundFloat [r hincrbyfloat smallhash tmp 2.5]]\n        lappend rv [roundFloat [r hget smallhash tmp]]\n        lappend rv [roundFloat [r hincrbyfloat bighash tmp 2.5]]\n        lappend rv [roundFloat [r hget bighash tmp]]\n    } {2.5 2.5 2.5 2.5}\n\n    test {HINCRBYFLOAT against hash key created by hincrby itself} {\n        set rv {}\n        lappend rv [roundFloat [r hincrbyfloat smallhash tmp 3.5]]\n        lappend rv [roundFloat [r hget smallhash tmp]]\n        lappend rv [roundFloat [r hincrbyfloat bighash tmp 3.5]]\n        lappend rv [roundFloat [r hget bighash tmp]]\n    } {6 6 6 6}\n\n    test {HINCRBYFLOAT against hash key originally set with HSET} {\n        r hset smallhash tmp 100\n        r hset bighash tmp 100\n        list [roundFloat [r hincrbyfloat smallhash tmp 2.5]] \\\n             [roundFloat [r hincrbyfloat bighash tmp 2.5]]\n    } {102.5 102.5}\n\n    test {HINCRBYFLOAT over 32bit value} {\n        r hset smallhash tmp 17179869184\n        r hset bighash tmp 17179869184\n        list [r hincrbyfloat smallhash tmp 1] \\\n             [r hincrbyfloat bighash tmp 1]\n    } {17179869185 17179869185}\n\n    test {HINCRBYFLOAT over 32bit value with over 32bit increment} {\n        r hset smallhash tmp 17179869184\n        r hset bighash tmp 17179869184\n        list [r hincrbyfloat smallhash tmp 17179869184] \\\n             [r hincrbyfloat bighash tmp 17179869184]\n    } {34359738368 34359738368}\n\n    test {HINCRBYFLOAT fails against hash value with spaces (left)} {\n        r hset smallhash str \" 11\"\n        r hset bighash str \" 11\"\n        catch {r hincrbyfloat smallhash str 1} smallerr\n        catch {r hincrbyfloat smallhash str 1} bigerr\n        set rv {}\n        lappend rv [string match \"ERR*not*float*\" $smallerr]\n        lappend rv [string match \"ERR*not*float*\" $bigerr]\n    } {1 1}\n\n    test {HINCRBYFLOAT fails against hash value with spaces (right)} {\n        r hset smallhash str \"11 \"\n        r hset bighash str \"11 \"\n        catch {r hincrbyfloat smallhash str 1} smallerr\n        catch {r hincrbyfloat smallhash str 1} bigerr\n        set rv {}\n        lappend rv [string match \"ERR*not*float*\" $smallerr]\n        lappend rv [string match \"ERR*not*float*\" $bigerr]\n    } {1 1}\n\n    test {Hash ziplist regression test for large keys} {\n        r hset hash kkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkk a\n        r hset hash kkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkk b\n        r hget hash kkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkk\n    } {b}\n\n    foreach size {10 512} {\n        test \"Hash fuzzing #1 - $size fields\" {\n            for {set times 0} {$times < 10} {incr times} {\n                catch {unset hash}\n                array set hash {}\n                r del hash\n\n                # Create\n                for {set j 0} {$j < $size} {incr j} {\n                    set field [randomValue]\n                    set value [randomValue]\n                    r hset hash $field $value\n                    set hash($field) $value\n                }\n\n                # Verify\n                foreach {k v} [array get hash] {\n                    assert_equal $v [r hget hash $k]\n                }\n                assert_equal [array size hash] [r hlen hash]\n            }\n        }\n\n        test \"Hash fuzzing #2 - $size fields\" {\n            for {set times 0} {$times < 10} {incr times} {\n                catch {unset hash}\n                array set hash {}\n                r del hash\n\n                # Create\n                for {set j 0} {$j < $size} {incr j} {\n                    randpath {\n                        set field [randomValue]\n                        set value [randomValue]\n                        r hset hash $field $value\n                        set hash($field) $value\n                    } {\n                        set field [randomSignedInt 512]\n                        set value [randomSignedInt 512]\n                        r hset hash $field $value\n                        set hash($field) $value\n                    } {\n                        randpath {\n                            set field [randomValue]\n                        } {\n                            set field [randomSignedInt 512]\n                        }\n                        r hdel hash $field\n                        unset -nocomplain hash($field)\n                    }\n                }\n\n                # Verify\n                foreach {k v} [array get hash] {\n                    assert_equal $v [r hget hash $k]\n                }\n                assert_equal [array size hash] [r hlen hash]\n            }\n        }\n    }\n\n    test {Stress test the hash ziplist -> hashtable encoding conversion} {\n        r config set hash-max-ziplist-entries 32\n        for {set j 0} {$j < 100} {incr j} {\n            r del myhash\n            for {set i 0} {$i < 64} {incr i} {\n                r hset myhash [randomValue] [randomValue]\n            }\n            assert {[r object encoding myhash] eq {hashtable}}\n        }\n    }\n}\n"
  },
  {
    "path": "extern/deprecated/redis-2.8.21/tests/unit/type/list-2.tcl",
    "content": "start_server {\n    tags {\"list\"}\n    overrides {\n        \"list-max-ziplist-value\" 16\n        \"list-max-ziplist-entries\" 256\n    }\n} {\n    source \"tests/unit/type/list-common.tcl\"\n\n    foreach {type large} [array get largevalue] {\n        tags {\"slow\"} {\n            test \"LTRIM stress testing - $type\" {\n                set mylist {}\n                set startlen 32\n                r del mylist\n\n                # Start with the large value to ensure the\n                # right encoding is used.\n                r rpush mylist $large\n                lappend mylist $large\n\n                for {set i 0} {$i < $startlen} {incr i} {\n                    set str [randomInt 9223372036854775807]\n                    r rpush mylist $str\n                    lappend mylist $str\n                }\n\n                for {set i 0} {$i < 1000} {incr i} {\n                    set min [expr {int(rand()*$startlen)}]\n                    set max [expr {$min+int(rand()*$startlen)}]\n                    set mylist [lrange $mylist $min $max]\n                    r ltrim mylist $min $max\n                    assert_equal $mylist [r lrange mylist 0 -1]\n\n                    for {set j [r llen mylist]} {$j < $startlen} {incr j} {\n                        set str [randomInt 9223372036854775807]\n                        r rpush mylist $str\n                        lappend mylist $str\n                    }\n                }\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "extern/deprecated/redis-2.8.21/tests/unit/type/list-3.tcl",
    "content": "start_server {\n    tags {list ziplist}\n    overrides {\n        \"list-max-ziplist-value\" 200000\n        \"list-max-ziplist-entries\" 256\n    }\n} {\n    test {Explicit regression for a list bug} {\n        set mylist {49376042582 {BkG2o\\pIC]4YYJa9cJ4GWZalG[4tin;1D2whSkCOW`mX;SFXGyS8sedcff3fQI^tgPCC@^Nu1J6o]meM@Lko]t_jRyo<xSJ1oObDYd`ppZuW6P@fS278YaOx=s6lvdFlMbP0[SbkI^Kr\\HBXtuFaA^mDx:yzS4a[skiiPWhT<nNfAf=aQVfclcuwDrfe;iVuKdNvB9kbfq>tK?tH[\\EvWqS]b`o2OCtjg:?nUTwdjpcUm]y:pg5q24q7LlCOwQE^}}\n        r del l\n        r rpush l [lindex $mylist 0]\n        r rpush l [lindex $mylist 1]\n        assert_equal [r lindex l 0] [lindex $mylist 0]\n        assert_equal [r lindex l 1] [lindex $mylist 1]\n    }\n\n    tags {slow} {\n        test {ziplist implementation: value encoding and backlink} {\n            if {$::accurate} {set iterations 100} else {set iterations 10}\n            for {set j 0} {$j < $iterations} {incr j} {\n                r del l\n                set l {}\n                for {set i 0} {$i < 200} {incr i} {\n                    randpath {\n                        set data [string repeat x [randomInt 100000]]\n                    } {\n                        set data [randomInt 65536]\n                    } {\n                        set data [randomInt 4294967296]\n                    } {\n                        set data [randomInt 18446744073709551616]\n                    } {\n                        set data -[randomInt 65536]\n                        if {$data eq {-0}} {set data 0}\n                    } {\n                        set data -[randomInt 4294967296]\n                        if {$data eq {-0}} {set data 0}\n                    } {\n                        set data -[randomInt 18446744073709551616]\n                        if {$data eq {-0}} {set data 0}\n                    }\n                    lappend l $data\n                    r rpush l $data\n                }\n                assert_equal [llength $l] [r llen l]\n                # Traverse backward\n                for {set i 199} {$i >= 0} {incr i -1} {\n                    if {[lindex $l $i] ne [r lindex l $i]} {\n                        assert_equal [lindex $l $i] [r lindex l $i]\n                    }\n                }\n            }\n        }\n\n        test {ziplist implementation: encoding stress testing} {\n            for {set j 0} {$j < 200} {incr j} {\n                r del l\n                set l {}\n                set len [randomInt 400]\n                for {set i 0} {$i < $len} {incr i} {\n                    set rv [randomValue]\n                    randpath {\n                        lappend l $rv\n                        r rpush l $rv\n                    } {\n                        set l [concat [list $rv] $l]\n                        r lpush l $rv\n                    }\n                }\n                assert_equal [llength $l] [r llen l]\n                for {set i 0} {$i < $len} {incr i} {\n                    if {[lindex $l $i] ne [r lindex l $i]} {\n                        assert_equal [lindex $l $i] [r lindex l $i]\n                    }\n                }\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "extern/deprecated/redis-2.8.21/tests/unit/type/list-common.tcl",
    "content": "# We need a value larger than list-max-ziplist-value to make sure\n# the list has the right encoding when it is swapped in again.\narray set largevalue {}\nset largevalue(ziplist) \"hello\"\nset largevalue(linkedlist) [string repeat \"hello\" 4]\n"
  },
  {
    "path": "extern/deprecated/redis-2.8.21/tests/unit/type/list.tcl",
    "content": "start_server {\n    tags {\"list\"}\n    overrides {\n        \"list-max-ziplist-value\" 16\n        \"list-max-ziplist-entries\" 256\n    }\n} {\n    source \"tests/unit/type/list-common.tcl\"\n\n    test {LPUSH, RPUSH, LLENGTH, LINDEX, LPOP - ziplist} {\n        # first lpush then rpush\n        assert_equal 1 [r lpush myziplist1 a]\n        assert_equal 2 [r rpush myziplist1 b]\n        assert_equal 3 [r rpush myziplist1 c]\n        assert_equal 3 [r llen myziplist1]\n        assert_equal a [r lindex myziplist1 0]\n        assert_equal b [r lindex myziplist1 1]\n        assert_equal c [r lindex myziplist1 2]\n        assert_equal {} [r lindex myziplist2 3]\n        assert_equal c [r rpop myziplist1]\n        assert_equal a [r lpop myziplist1]\n        assert_encoding ziplist myziplist1\n\n        # first rpush then lpush\n        assert_equal 1 [r rpush myziplist2 a]\n        assert_equal 2 [r lpush myziplist2 b]\n        assert_equal 3 [r lpush myziplist2 c]\n        assert_equal 3 [r llen myziplist2]\n        assert_equal c [r lindex myziplist2 0]\n        assert_equal b [r lindex myziplist2 1]\n        assert_equal a [r lindex myziplist2 2]\n        assert_equal {} [r lindex myziplist2 3]\n        assert_equal a [r rpop myziplist2]\n        assert_equal c [r lpop myziplist2]\n        assert_encoding ziplist myziplist2\n    }\n\n    test {LPUSH, RPUSH, LLENGTH, LINDEX, LPOP - regular list} {\n        # first lpush then rpush\n        assert_equal 1 [r lpush mylist1 $largevalue(linkedlist)]\n        assert_encoding linkedlist mylist1\n        assert_equal 2 [r rpush mylist1 b]\n        assert_equal 3 [r rpush mylist1 c]\n        assert_equal 3 [r llen mylist1]\n        assert_equal $largevalue(linkedlist) [r lindex mylist1 0]\n        assert_equal b [r lindex mylist1 1]\n        assert_equal c [r lindex mylist1 2]\n        assert_equal {} [r lindex mylist1 3]\n        assert_equal c [r rpop mylist1]\n        assert_equal $largevalue(linkedlist) [r lpop mylist1]\n\n        # first rpush then lpush\n        assert_equal 1 [r rpush mylist2 $largevalue(linkedlist)]\n        assert_encoding linkedlist mylist2\n        assert_equal 2 [r lpush mylist2 b]\n        assert_equal 3 [r lpush mylist2 c]\n        assert_equal 3 [r llen mylist2]\n        assert_equal c [r lindex mylist2 0]\n        assert_equal b [r lindex mylist2 1]\n        assert_equal $largevalue(linkedlist) [r lindex mylist2 2]\n        assert_equal {} [r lindex mylist2 3]\n        assert_equal $largevalue(linkedlist) [r rpop mylist2]\n        assert_equal c [r lpop mylist2]\n    }\n\n    test {R/LPOP against empty list} {\n        r lpop non-existing-list\n    } {}\n\n    test {Variadic RPUSH/LPUSH} {\n        r del mylist\n        assert_equal 4 [r lpush mylist a b c d]\n        assert_equal 8 [r rpush mylist 0 1 2 3]\n        assert_equal {d c b a 0 1 2 3} [r lrange mylist 0 -1]\n    }\n\n    test {DEL a list - ziplist} {\n        assert_equal 1 [r del myziplist2]\n        assert_equal 0 [r exists myziplist2]\n        assert_equal 0 [r llen myziplist2]\n    }\n\n    test {DEL a list - regular list} {\n        assert_equal 1 [r del mylist2]\n        assert_equal 0 [r exists mylist2]\n        assert_equal 0 [r llen mylist2]\n    }\n\n    proc create_ziplist {key entries} {\n        r del $key\n        foreach entry $entries { r rpush $key $entry }\n        assert_encoding ziplist $key\n    }\n\n    proc create_linkedlist {key entries} {\n        r del $key\n        foreach entry $entries { r rpush $key $entry }\n        assert_encoding linkedlist $key\n    }\n\n    foreach {type large} [array get largevalue] {\n        test \"BLPOP, BRPOP: single existing list - $type\" {\n            set rd [redis_deferring_client]\n            create_$type blist \"a b $large c d\"\n\n            $rd blpop blist 1\n            assert_equal {blist a} [$rd read]\n            $rd brpop blist 1\n            assert_equal {blist d} [$rd read]\n\n            $rd blpop blist 1\n            assert_equal {blist b} [$rd read]\n            $rd brpop blist 1\n            assert_equal {blist c} [$rd read]\n        }\n\n        test \"BLPOP, BRPOP: multiple existing lists - $type\" {\n            set rd [redis_deferring_client]\n            create_$type blist1 \"a $large c\"\n            create_$type blist2 \"d $large f\"\n\n            $rd blpop blist1 blist2 1\n            assert_equal {blist1 a} [$rd read]\n            $rd brpop blist1 blist2 1\n            assert_equal {blist1 c} [$rd read]\n            assert_equal 1 [r llen blist1]\n            assert_equal 3 [r llen blist2]\n\n            $rd blpop blist2 blist1 1\n            assert_equal {blist2 d} [$rd read]\n            $rd brpop blist2 blist1 1\n            assert_equal {blist2 f} [$rd read]\n            assert_equal 1 [r llen blist1]\n            assert_equal 1 [r llen blist2]\n        }\n\n        test \"BLPOP, BRPOP: second list has an entry - $type\" {\n            set rd [redis_deferring_client]\n            r del blist1\n            create_$type blist2 \"d $large f\"\n\n            $rd blpop blist1 blist2 1\n            assert_equal {blist2 d} [$rd read]\n            $rd brpop blist1 blist2 1\n            assert_equal {blist2 f} [$rd read]\n            assert_equal 0 [r llen blist1]\n            assert_equal 1 [r llen blist2]\n        }\n\n        test \"BRPOPLPUSH - $type\" {\n            r del target\n\n            set rd [redis_deferring_client]\n            create_$type blist \"a b $large c d\"\n\n            $rd brpoplpush blist target 1\n            assert_equal d [$rd read]\n\n            assert_equal d [r rpop target]\n            assert_equal \"a b $large c\" [r lrange blist 0 -1]\n        }\n    }\n\n    test \"BLPOP, LPUSH + DEL should not awake blocked client\" {\n        set rd [redis_deferring_client]\n        r del list\n\n        $rd blpop list 0\n        r multi\n        r lpush list a\n        r del list\n        r exec\n        r del list\n        r lpush list b\n        $rd read\n    } {list b}\n\n    test \"BLPOP, LPUSH + DEL + SET should not awake blocked client\" {\n        set rd [redis_deferring_client]\n        r del list\n\n        $rd blpop list 0\n        r multi\n        r lpush list a\n        r del list\n        r set list foo\n        r exec\n        r del list\n        r lpush list b\n        $rd read\n    } {list b}\n\n    test \"BLPOP with same key multiple times should work (issue #801)\" {\n        set rd [redis_deferring_client]\n        r del list1 list2\n\n        # Data arriving after the BLPOP.\n        $rd blpop list1 list2 list2 list1 0\n        r lpush list1 a\n        assert_equal [$rd read] {list1 a}\n        $rd blpop list1 list2 list2 list1 0\n        r lpush list2 b\n        assert_equal [$rd read] {list2 b}\n\n        # Data already there.\n        r lpush list1 a\n        r lpush list2 b\n        $rd blpop list1 list2 list2 list1 0\n        assert_equal [$rd read] {list1 a}\n        $rd blpop list1 list2 list2 list1 0\n        assert_equal [$rd read] {list2 b}\n    }\n\n    test \"MULTI/EXEC is isolated from the point of view of BLPOP\" {\n        set rd [redis_deferring_client]\n        r del list\n        $rd blpop list 0\n        r multi\n        r lpush list a\n        r lpush list b\n        r lpush list c\n        r exec\n        $rd read\n    } {list c}\n\n    test \"BLPOP with variadic LPUSH\" {\n        set rd [redis_deferring_client]\n        r del blist target\n        if {$::valgrind} {after 100}\n        $rd blpop blist 0\n        if {$::valgrind} {after 100}\n        assert_equal 2 [r lpush blist foo bar]\n        if {$::valgrind} {after 100}\n        assert_equal {blist bar} [$rd read]\n        assert_equal foo [lindex [r lrange blist 0 -1] 0]\n    }\n\n    test \"BRPOPLPUSH with zero timeout should block indefinitely\" {\n        set rd [redis_deferring_client]\n        r del blist target\n        $rd brpoplpush blist target 0\n        after 1000\n        r rpush blist foo\n        assert_equal foo [$rd read]\n        assert_equal {foo} [r lrange target 0 -1]\n    }\n\n    test \"BRPOPLPUSH with a client BLPOPing the target list\" {\n        set rd [redis_deferring_client]\n        set rd2 [redis_deferring_client]\n        r del blist target\n        $rd2 blpop target 0\n        $rd brpoplpush blist target 0\n        after 1000\n        r rpush blist foo\n        assert_equal foo [$rd read]\n        assert_equal {target foo} [$rd2 read]\n        assert_equal 0 [r exists target]\n    }\n\n    test \"BRPOPLPUSH with wrong source type\" {\n        set rd [redis_deferring_client]\n        r del blist target\n        r set blist nolist\n        $rd brpoplpush blist target 1\n        assert_error \"WRONGTYPE*\" {$rd read}\n    }\n\n    test \"BRPOPLPUSH with wrong destination type\" {\n        set rd [redis_deferring_client]\n        r del blist target\n        r set target nolist\n        r lpush blist foo\n        $rd brpoplpush blist target 1\n        assert_error \"WRONGTYPE*\" {$rd read}\n\n        set rd [redis_deferring_client]\n        r del blist target\n        r set target nolist\n        $rd brpoplpush blist target 0\n        after 1000\n        r rpush blist foo\n        assert_error \"WRONGTYPE*\" {$rd read}\n        assert_equal {foo} [r lrange blist 0 -1]\n    }\n\n    test \"BRPOPLPUSH maintains order of elements after failure\" {\n        set rd [redis_deferring_client]\n        r del blist target\n        r set target nolist\n        $rd brpoplpush blist target 0\n        r rpush blist a b c\n        assert_error \"WRONGTYPE*\" {$rd read}\n        r lrange blist 0 -1\n    } {a b c}\n\n    test \"BRPOPLPUSH with multiple blocked clients\" {\n        set rd1 [redis_deferring_client]\n        set rd2 [redis_deferring_client]\n        r del blist target1 target2\n        r set target1 nolist\n        $rd1 brpoplpush blist target1 0\n        $rd2 brpoplpush blist target2 0\n        r lpush blist foo\n\n        assert_error \"WRONGTYPE*\" {$rd1 read}\n        assert_equal {foo} [$rd2 read]\n        assert_equal {foo} [r lrange target2 0 -1]\n    }\n\n    test \"Linked BRPOPLPUSH\" {\n      set rd1 [redis_deferring_client]\n      set rd2 [redis_deferring_client]\n\n      r del list1 list2 list3\n\n      $rd1 brpoplpush list1 list2 0\n      $rd2 brpoplpush list2 list3 0\n\n      r rpush list1 foo\n\n      assert_equal {} [r lrange list1 0 -1]\n      assert_equal {} [r lrange list2 0 -1]\n      assert_equal {foo} [r lrange list3 0 -1]\n    }\n\n    test \"Circular BRPOPLPUSH\" {\n      set rd1 [redis_deferring_client]\n      set rd2 [redis_deferring_client]\n\n      r del list1 list2\n\n      $rd1 brpoplpush list1 list2 0\n      $rd2 brpoplpush list2 list1 0\n\n      r rpush list1 foo\n\n      assert_equal {foo} [r lrange list1 0 -1]\n      assert_equal {} [r lrange list2 0 -1]\n    }\n\n    test \"Self-referential BRPOPLPUSH\" {\n      set rd [redis_deferring_client]\n\n      r del blist\n\n      $rd brpoplpush blist blist 0\n\n      r rpush blist foo\n\n      assert_equal {foo} [r lrange blist 0 -1]\n    }\n\n    test \"BRPOPLPUSH inside a transaction\" {\n        r del xlist target\n        r lpush xlist foo\n        r lpush xlist bar\n\n        r multi\n        r brpoplpush xlist target 0\n        r brpoplpush xlist target 0\n        r brpoplpush xlist target 0\n        r lrange xlist 0 -1\n        r lrange target 0 -1\n        r exec\n    } {foo bar {} {} {bar foo}}\n\n    test \"PUSH resulting from BRPOPLPUSH affect WATCH\" {\n        set blocked_client [redis_deferring_client]\n        set watching_client [redis_deferring_client]\n        r del srclist dstlist somekey\n        r set somekey somevalue\n        $blocked_client brpoplpush srclist dstlist 0\n        $watching_client watch dstlist\n        $watching_client read\n        $watching_client multi\n        $watching_client read\n        $watching_client get somekey\n        $watching_client read\n        r lpush srclist element\n        $watching_client exec\n        $watching_client read\n    } {}\n\n    test \"BRPOPLPUSH does not affect WATCH while still blocked\" {\n        set blocked_client [redis_deferring_client]\n        set watching_client [redis_deferring_client]\n        r del srclist dstlist somekey\n        r set somekey somevalue\n        $blocked_client brpoplpush srclist dstlist 0\n        $watching_client watch dstlist\n        $watching_client read\n        $watching_client multi\n        $watching_client read\n        $watching_client get somekey\n        $watching_client read\n        $watching_client exec\n        # Blocked BLPOPLPUSH may create problems, unblock it.\n        r lpush srclist element\n        $watching_client read\n    } {somevalue}\n\n    test {BRPOPLPUSH timeout} {\n      set rd [redis_deferring_client]\n\n      $rd brpoplpush foo_list bar_list 1\n      after 2000\n      $rd read\n    } {}\n\n    test \"BLPOP when new key is moved into place\" {\n        set rd [redis_deferring_client]\n\n        $rd blpop foo 5\n        r lpush bob abc def hij\n        r rename bob foo\n        $rd read\n    } {foo hij}\n\n    test \"BLPOP when result key is created by SORT..STORE\" {\n        set rd [redis_deferring_client]\n\n        # zero out list from previous test without explicit delete\n        r lpop foo\n        r lpop foo\n        r lpop foo\n\n        $rd blpop foo 5\n        r lpush notfoo hello hola aguacate konichiwa zanzibar\n        r sort notfoo ALPHA store foo\n        $rd read\n    } {foo aguacate}\n\n    foreach {pop} {BLPOP BRPOP} {\n        test \"$pop: with single empty list argument\" {\n            set rd [redis_deferring_client]\n            r del blist1\n            $rd $pop blist1 1\n            r rpush blist1 foo\n            assert_equal {blist1 foo} [$rd read]\n            assert_equal 0 [r exists blist1]\n        }\n\n        test \"$pop: with negative timeout\" {\n            set rd [redis_deferring_client]\n            $rd $pop blist1 -1\n            assert_error \"ERR*is negative*\" {$rd read}\n        }\n\n        test \"$pop: with non-integer timeout\" {\n            set rd [redis_deferring_client]\n            $rd $pop blist1 1.1\n            assert_error \"ERR*not an integer*\" {$rd read}\n        }\n\n        test \"$pop: with zero timeout should block indefinitely\" {\n            # To test this, use a timeout of 0 and wait a second.\n            # The blocking pop should still be waiting for a push.\n            set rd [redis_deferring_client]\n            $rd $pop blist1 0\n            after 1000\n            r rpush blist1 foo\n            assert_equal {blist1 foo} [$rd read]\n        }\n\n        test \"$pop: second argument is not a list\" {\n            set rd [redis_deferring_client]\n            r del blist1 blist2\n            r set blist2 nolist\n            $rd $pop blist1 blist2 1\n            assert_error \"WRONGTYPE*\" {$rd read}\n        }\n\n        test \"$pop: timeout\" {\n            set rd [redis_deferring_client]\n            r del blist1 blist2\n            $rd $pop blist1 blist2 1\n            assert_equal {} [$rd read]\n        }\n\n        test \"$pop: arguments are empty\" {\n            set rd [redis_deferring_client]\n            r del blist1 blist2\n\n            $rd $pop blist1 blist2 1\n            r rpush blist1 foo\n            assert_equal {blist1 foo} [$rd read]\n            assert_equal 0 [r exists blist1]\n            assert_equal 0 [r exists blist2]\n\n            $rd $pop blist1 blist2 1\n            r rpush blist2 foo\n            assert_equal {blist2 foo} [$rd read]\n            assert_equal 0 [r exists blist1]\n            assert_equal 0 [r exists blist2]\n        }\n    }\n\n    test {BLPOP inside a transaction} {\n        r del xlist\n        r lpush xlist foo\n        r lpush xlist bar\n        r multi\n        r blpop xlist 0\n        r blpop xlist 0\n        r blpop xlist 0\n        r exec\n    } {{xlist bar} {xlist foo} {}}\n\n    test {LPUSHX, RPUSHX - generic} {\n        r del xlist\n        assert_equal 0 [r lpushx xlist a]\n        assert_equal 0 [r llen xlist]\n        assert_equal 0 [r rpushx xlist a]\n        assert_equal 0 [r llen xlist]\n    }\n\n    foreach {type large} [array get largevalue] {\n        test \"LPUSHX, RPUSHX - $type\" {\n            create_$type xlist \"$large c\"\n            assert_equal 3 [r rpushx xlist d]\n            assert_equal 4 [r lpushx xlist a]\n            assert_equal \"a $large c d\" [r lrange xlist 0 -1]\n        }\n\n        test \"LINSERT - $type\" {\n            create_$type xlist \"a $large c d\"\n            assert_equal 5 [r linsert xlist before c zz]\n            assert_equal \"a $large zz c d\" [r lrange xlist 0 10]\n            assert_equal 6 [r linsert xlist after c yy]\n            assert_equal \"a $large zz c yy d\" [r lrange xlist 0 10]\n            assert_equal 7 [r linsert xlist after d dd]\n            assert_equal -1 [r linsert xlist after bad ddd]\n            assert_equal \"a $large zz c yy d dd\" [r lrange xlist 0 10]\n            assert_equal 8 [r linsert xlist before a aa]\n            assert_equal -1 [r linsert xlist before bad aaa]\n            assert_equal \"aa a $large zz c yy d dd\" [r lrange xlist 0 10]\n\n            # check inserting integer encoded value\n            assert_equal 9 [r linsert xlist before aa 42]\n            assert_equal 42 [r lrange xlist 0 0]\n        }\n    }\n\n    test {LINSERT raise error on bad syntax} {\n        catch {[r linsert xlist aft3r aa 42]} e\n        set e\n    } {*ERR*syntax*error*}\n\n    test {LPUSHX, RPUSHX convert from ziplist to list} {\n        set large $largevalue(linkedlist)\n\n        # convert when a large value is pushed\n        create_ziplist xlist a\n        assert_equal 2 [r rpushx xlist $large]\n        assert_encoding linkedlist xlist\n        create_ziplist xlist a\n        assert_equal 2 [r lpushx xlist $large]\n        assert_encoding linkedlist xlist\n\n        # convert when the length threshold is exceeded\n        create_ziplist xlist [lrepeat 256 a]\n        assert_equal 257 [r rpushx xlist b]\n        assert_encoding linkedlist xlist\n        create_ziplist xlist [lrepeat 256 a]\n        assert_equal 257 [r lpushx xlist b]\n        assert_encoding linkedlist xlist\n    }\n\n    test {LINSERT convert from ziplist to list} {\n        set large $largevalue(linkedlist)\n\n        # convert when a large value is inserted\n        create_ziplist xlist a\n        assert_equal 2 [r linsert xlist before a $large]\n        assert_encoding linkedlist xlist\n        create_ziplist xlist a\n        assert_equal 2 [r linsert xlist after a $large]\n        assert_encoding linkedlist xlist\n\n        # convert when the length threshold is exceeded\n        create_ziplist xlist [lrepeat 256 a]\n        assert_equal 257 [r linsert xlist before a a]\n        assert_encoding linkedlist xlist\n        create_ziplist xlist [lrepeat 256 a]\n        assert_equal 257 [r linsert xlist after a a]\n        assert_encoding linkedlist xlist\n\n        # don't convert when the value could not be inserted\n        create_ziplist xlist [lrepeat 256 a]\n        assert_equal -1 [r linsert xlist before foo a]\n        assert_encoding ziplist xlist\n        create_ziplist xlist [lrepeat 256 a]\n        assert_equal -1 [r linsert xlist after foo a]\n        assert_encoding ziplist xlist\n    }\n\n    foreach {type num} {ziplist 250 linkedlist 500} {\n        proc check_numbered_list_consistency {key} {\n            set len [r llen $key]\n            for {set i 0} {$i < $len} {incr i} {\n                assert_equal $i [r lindex $key $i]\n                assert_equal [expr $len-1-$i] [r lindex $key [expr (-$i)-1]]\n            }\n        }\n\n        proc check_random_access_consistency {key} {\n            set len [r llen $key]\n            for {set i 0} {$i < $len} {incr i} {\n                set rint [expr int(rand()*$len)]\n                assert_equal $rint [r lindex $key $rint]\n                assert_equal [expr $len-1-$rint] [r lindex $key [expr (-$rint)-1]]\n            }\n        }\n\n        test \"LINDEX consistency test - $type\" {\n            r del mylist\n            for {set i 0} {$i < $num} {incr i} {\n                r rpush mylist $i\n            }\n            assert_encoding $type mylist\n            check_numbered_list_consistency mylist\n        }\n\n        test \"LINDEX random access - $type\" {\n            assert_encoding $type mylist\n            check_random_access_consistency mylist\n        }\n\n        test \"Check if list is still ok after a DEBUG RELOAD - $type\" {\n            r debug reload\n            assert_encoding $type mylist\n            check_numbered_list_consistency mylist\n            check_random_access_consistency mylist\n        }\n    }\n\n    test {LLEN against non-list value error} {\n        r del mylist\n        r set mylist foobar\n        assert_error WRONGTYPE* {r llen mylist}\n    }\n\n    test {LLEN against non existing key} {\n        assert_equal 0 [r llen not-a-key]\n    }\n\n    test {LINDEX against non-list value error} {\n        assert_error WRONGTYPE* {r lindex mylist 0}\n    }\n\n    test {LINDEX against non existing key} {\n        assert_equal \"\" [r lindex not-a-key 10]\n    }\n\n    test {LPUSH against non-list value error} {\n        assert_error WRONGTYPE* {r lpush mylist 0}\n    }\n\n    test {RPUSH against non-list value error} {\n        assert_error WRONGTYPE* {r rpush mylist 0}\n    }\n\n    foreach {type large} [array get largevalue] {\n        test \"RPOPLPUSH base case - $type\" {\n            r del mylist1 mylist2\n            create_$type mylist1 \"a $large c d\"\n            assert_equal d [r rpoplpush mylist1 mylist2]\n            assert_equal c [r rpoplpush mylist1 mylist2]\n            assert_equal \"a $large\" [r lrange mylist1 0 -1]\n            assert_equal \"c d\" [r lrange mylist2 0 -1]\n            assert_encoding ziplist mylist2\n        }\n\n        test \"RPOPLPUSH with the same list as src and dst - $type\" {\n            create_$type mylist \"a $large c\"\n            assert_equal \"a $large c\" [r lrange mylist 0 -1]\n            assert_equal c [r rpoplpush mylist mylist]\n            assert_equal \"c a $large\" [r lrange mylist 0 -1]\n        }\n\n        foreach {othertype otherlarge} [array get largevalue] {\n            test \"RPOPLPUSH with $type source and existing target $othertype\" {\n                create_$type srclist \"a b c $large\"\n                create_$othertype dstlist \"$otherlarge\"\n                assert_equal $large [r rpoplpush srclist dstlist]\n                assert_equal c [r rpoplpush srclist dstlist]\n                assert_equal \"a b\" [r lrange srclist 0 -1]\n                assert_equal \"c $large $otherlarge\" [r lrange dstlist 0 -1]\n\n                # When we rpoplpush'ed a large value, dstlist should be\n                # converted to the same encoding as srclist.\n                if {$type eq \"linkedlist\"} {\n                    assert_encoding linkedlist dstlist\n                }\n            }\n        }\n    }\n\n    test {RPOPLPUSH against non existing key} {\n        r del srclist dstlist\n        assert_equal {} [r rpoplpush srclist dstlist]\n        assert_equal 0 [r exists srclist]\n        assert_equal 0 [r exists dstlist]\n    }\n\n    test {RPOPLPUSH against non list src key} {\n        r del srclist dstlist\n        r set srclist x\n        assert_error WRONGTYPE* {r rpoplpush srclist dstlist}\n        assert_type string srclist\n        assert_equal 0 [r exists newlist]\n    }\n\n    test {RPOPLPUSH against non list dst key} {\n        create_ziplist srclist {a b c d}\n        r set dstlist x\n        assert_error WRONGTYPE* {r rpoplpush srclist dstlist}\n        assert_type string dstlist\n        assert_equal {a b c d} [r lrange srclist 0 -1]\n    }\n\n    test {RPOPLPUSH against non existing src key} {\n        r del srclist dstlist\n        assert_equal {} [r rpoplpush srclist dstlist]\n    } {}\n\n    foreach {type large} [array get largevalue] {\n        test \"Basic LPOP/RPOP - $type\" {\n            create_$type mylist \"$large 1 2\"\n            assert_equal $large [r lpop mylist]\n            assert_equal 2 [r rpop mylist]\n            assert_equal 1 [r lpop mylist]\n            assert_equal 0 [r llen mylist]\n\n            # pop on empty list\n            assert_equal {} [r lpop mylist]\n            assert_equal {} [r rpop mylist]\n        }\n    }\n\n    test {LPOP/RPOP against non list value} {\n        r set notalist foo\n        assert_error WRONGTYPE* {r lpop notalist}\n        assert_error WRONGTYPE* {r rpop notalist}\n    }\n\n    foreach {type num} {ziplist 250 linkedlist 500} {\n        test \"Mass RPOP/LPOP - $type\" {\n            r del mylist\n            set sum1 0\n            for {set i 0} {$i < $num} {incr i} {\n                r lpush mylist $i\n                incr sum1 $i\n            }\n            assert_encoding $type mylist\n            set sum2 0\n            for {set i 0} {$i < [expr $num/2]} {incr i} {\n                incr sum2 [r lpop mylist]\n                incr sum2 [r rpop mylist]\n            }\n            assert_equal $sum1 $sum2\n        }\n    }\n\n    foreach {type large} [array get largevalue] {\n        test \"LRANGE basics - $type\" {\n            create_$type mylist \"$large 1 2 3 4 5 6 7 8 9\"\n            assert_equal {1 2 3 4 5 6 7 8} [r lrange mylist 1 -2]\n            assert_equal {7 8 9} [r lrange mylist -3 -1]\n            assert_equal {4} [r lrange mylist 4 4]\n        }\n\n        test \"LRANGE inverted indexes - $type\" {\n            create_$type mylist \"$large 1 2 3 4 5 6 7 8 9\"\n            assert_equal {} [r lrange mylist 6 2]\n        }\n\n        test \"LRANGE out of range indexes including the full list - $type\" {\n            create_$type mylist \"$large 1 2 3\"\n            assert_equal \"$large 1 2 3\" [r lrange mylist -1000 1000]\n        }\n\n        test \"LRANGE out of range negative end index - $type\" {\n            create_$type mylist \"$large 1 2 3\"\n            assert_equal $large [r lrange mylist 0 -4]\n            assert_equal {} [r lrange mylist 0 -5]\n        }\n    }\n\n    test {LRANGE against non existing key} {\n        assert_equal {} [r lrange nosuchkey 0 1]\n    }\n\n    foreach {type large} [array get largevalue] {\n        proc trim_list {type min max} {\n            upvar 1 large large\n            r del mylist\n            create_$type mylist \"1 2 3 4 $large\"\n            r ltrim mylist $min $max\n            r lrange mylist 0 -1\n        }\n\n        test \"LTRIM basics - $type\" {\n            assert_equal \"1\" [trim_list $type 0 0]\n            assert_equal \"1 2\" [trim_list $type 0 1]\n            assert_equal \"1 2 3\" [trim_list $type 0 2]\n            assert_equal \"2 3\" [trim_list $type 1 2]\n            assert_equal \"2 3 4 $large\" [trim_list $type 1 -1]\n            assert_equal \"2 3 4\" [trim_list $type 1 -2]\n            assert_equal \"4 $large\" [trim_list $type -2 -1]\n            assert_equal \"$large\" [trim_list $type -1 -1]\n            assert_equal \"1 2 3 4 $large\" [trim_list $type -5 -1]\n            assert_equal \"1 2 3 4 $large\" [trim_list $type -10 10]\n            assert_equal \"1 2 3 4 $large\" [trim_list $type 0 5]\n            assert_equal \"1 2 3 4 $large\" [trim_list $type 0 10]\n        }\n\n        test \"LTRIM out of range negative end index - $type\" {\n            assert_equal {1} [trim_list $type 0 -5]\n            assert_equal {} [trim_list $type 0 -6]\n        }\n\n    }\n\n    foreach {type large} [array get largevalue] {\n        test \"LSET - $type\" {\n            create_$type mylist \"99 98 $large 96 95\"\n            r lset mylist 1 foo\n            r lset mylist -1 bar\n            assert_equal \"99 foo $large 96 bar\" [r lrange mylist 0 -1]\n        }\n\n        test \"LSET out of range index - $type\" {\n            assert_error ERR*range* {r lset mylist 10 foo}\n        }\n    }\n\n    test {LSET against non existing key} {\n        assert_error ERR*key* {r lset nosuchkey 10 foo}\n    }\n\n    test {LSET against non list value} {\n        r set nolist foobar\n        assert_error WRONGTYPE* {r lset nolist 0 foo}\n    }\n\n    foreach {type e} [array get largevalue] {\n        test \"LREM remove all the occurrences - $type\" {\n            create_$type mylist \"$e foo bar foobar foobared zap bar test foo\"\n            assert_equal 2 [r lrem mylist 0 bar]\n            assert_equal \"$e foo foobar foobared zap test foo\" [r lrange mylist 0 -1]\n        }\n\n        test \"LREM remove the first occurrence - $type\" {\n            assert_equal 1 [r lrem mylist 1 foo]\n            assert_equal \"$e foobar foobared zap test foo\" [r lrange mylist 0 -1]\n        }\n\n        test \"LREM remove non existing element - $type\" {\n            assert_equal 0 [r lrem mylist 1 nosuchelement]\n            assert_equal \"$e foobar foobared zap test foo\" [r lrange mylist 0 -1]\n        }\n\n        test \"LREM starting from tail with negative count - $type\" {\n            create_$type mylist \"$e foo bar foobar foobared zap bar test foo foo\"\n            assert_equal 1 [r lrem mylist -1 bar]\n            assert_equal \"$e foo bar foobar foobared zap test foo foo\" [r lrange mylist 0 -1]\n        }\n\n        test \"LREM starting from tail with negative count (2) - $type\" {\n            assert_equal 2 [r lrem mylist -2 foo]\n            assert_equal \"$e foo bar foobar foobared zap test\" [r lrange mylist 0 -1]\n        }\n\n        test \"LREM deleting objects that may be int encoded - $type\" {\n            create_$type myotherlist \"$e 1 2 3\"\n            assert_equal 1 [r lrem myotherlist 1 2]\n            assert_equal 3 [r llen myotherlist]\n        }\n    }\n\n    test \"Regression for bug 593 - chaining BRPOPLPUSH with other blocking cmds\" {\n        set rd1 [redis_deferring_client]\n        set rd2 [redis_deferring_client]\n\n        $rd1 brpoplpush a b 0\n        $rd1 brpoplpush a b 0\n        $rd2 brpoplpush b c 0\n        after 1000\n        r lpush a data\n        $rd1 close\n        $rd2 close\n        r ping\n    } {PONG}\n}\n"
  },
  {
    "path": "extern/deprecated/redis-2.8.21/tests/unit/type/set.tcl",
    "content": "start_server {\n    tags {\"set\"}\n    overrides {\n        \"set-max-intset-entries\" 512\n    }\n} {\n    proc create_set {key entries} {\n        r del $key\n        foreach entry $entries { r sadd $key $entry }\n    }\n\n    test {SADD, SCARD, SISMEMBER, SMEMBERS basics - regular set} {\n        create_set myset {foo}\n        assert_encoding hashtable myset\n        assert_equal 1 [r sadd myset bar]\n        assert_equal 0 [r sadd myset bar]\n        assert_equal 2 [r scard myset]\n        assert_equal 1 [r sismember myset foo]\n        assert_equal 1 [r sismember myset bar]\n        assert_equal 0 [r sismember myset bla]\n        assert_equal {bar foo} [lsort [r smembers myset]]\n    }\n\n    test {SADD, SCARD, SISMEMBER, SMEMBERS basics - intset} {\n        create_set myset {17}\n        assert_encoding intset myset\n        assert_equal 1 [r sadd myset 16]\n        assert_equal 0 [r sadd myset 16]\n        assert_equal 2 [r scard myset]\n        assert_equal 1 [r sismember myset 16]\n        assert_equal 1 [r sismember myset 17]\n        assert_equal 0 [r sismember myset 18]\n        assert_equal {16 17} [lsort [r smembers myset]]\n    }\n\n    test {SADD against non set} {\n        r lpush mylist foo\n        assert_error WRONGTYPE* {r sadd mylist bar}\n    }\n\n    test \"SADD a non-integer against an intset\" {\n        create_set myset {1 2 3}\n        assert_encoding intset myset\n        assert_equal 1 [r sadd myset a]\n        assert_encoding hashtable myset\n    }\n\n    test \"SADD an integer larger than 64 bits\" {\n        create_set myset {213244124402402314402033402}\n        assert_encoding hashtable myset\n        assert_equal 1 [r sismember myset 213244124402402314402033402]\n    }\n\n    test \"SADD overflows the maximum allowed integers in an intset\" {\n        r del myset\n        for {set i 0} {$i < 512} {incr i} { r sadd myset $i }\n        assert_encoding intset myset\n        assert_equal 1 [r sadd myset 512]\n        assert_encoding hashtable myset\n    }\n\n    test {Variadic SADD} {\n        r del myset\n        assert_equal 3 [r sadd myset a b c]\n        assert_equal 2 [r sadd myset A a b c B]\n        assert_equal [lsort {A a b c B}] [lsort [r smembers myset]]\n    }\n\n    test \"Set encoding after DEBUG RELOAD\" {\n        r del myintset myhashset mylargeintset\n        for {set i 0} {$i <  100} {incr i} { r sadd myintset $i }\n        for {set i 0} {$i < 1280} {incr i} { r sadd mylargeintset $i }\n        for {set i 0} {$i <  256} {incr i} { r sadd myhashset [format \"i%03d\" $i] }\n        assert_encoding intset myintset\n        assert_encoding hashtable mylargeintset\n        assert_encoding hashtable myhashset\n\n        r debug reload\n        assert_encoding intset myintset\n        assert_encoding hashtable mylargeintset\n        assert_encoding hashtable myhashset\n    }\n\n    test {SREM basics - regular set} {\n        create_set myset {foo bar ciao}\n        assert_encoding hashtable myset\n        assert_equal 0 [r srem myset qux]\n        assert_equal 1 [r srem myset foo]\n        assert_equal {bar ciao} [lsort [r smembers myset]]\n    }\n\n    test {SREM basics - intset} {\n        create_set myset {3 4 5}\n        assert_encoding intset myset\n        assert_equal 0 [r srem myset 6]\n        assert_equal 1 [r srem myset 4]\n        assert_equal {3 5} [lsort [r smembers myset]]\n    }\n\n    test {SREM with multiple arguments} {\n        r del myset\n        r sadd myset a b c d\n        assert_equal 0 [r srem myset k k k]\n        assert_equal 2 [r srem myset b d x y]\n        lsort [r smembers myset]\n    } {a c}\n\n    test {SREM variadic version with more args needed to destroy the key} {\n        r del myset\n        r sadd myset 1 2 3\n        r srem myset 1 2 3 4 5 6 7 8\n    } {3}\n\n    foreach {type} {hashtable intset} {\n        for {set i 1} {$i <= 5} {incr i} {\n            r del [format \"set%d\" $i]\n        }\n        for {set i 0} {$i < 200} {incr i} {\n            r sadd set1 $i\n            r sadd set2 [expr $i+195]\n        }\n        foreach i {199 195 1000 2000} {\n            r sadd set3 $i\n        }\n        for {set i 5} {$i < 200} {incr i} {\n            r sadd set4 $i\n        }\n        r sadd set5 0\n\n        # To make sure the sets are encoded as the type we are testing -- also\n        # when the VM is enabled and the values may be swapped in and out\n        # while the tests are running -- an extra element is added to every\n        # set that determines its encoding.\n        set large 200\n        if {$type eq \"hashtable\"} {\n            set large foo\n        }\n\n        for {set i 1} {$i <= 5} {incr i} {\n            r sadd [format \"set%d\" $i] $large\n        }\n\n        test \"Generated sets must be encoded as $type\" {\n            for {set i 1} {$i <= 5} {incr i} {\n                assert_encoding $type [format \"set%d\" $i]\n            }\n        }\n\n        test \"SINTER with two sets - $type\" {\n            assert_equal [list 195 196 197 198 199 $large] [lsort [r sinter set1 set2]]\n        }\n\n        test \"SINTERSTORE with two sets - $type\" {\n            r sinterstore setres set1 set2\n            assert_encoding $type setres\n            assert_equal [list 195 196 197 198 199 $large] [lsort [r smembers setres]]\n        }\n\n        test \"SINTERSTORE with two sets, after a DEBUG RELOAD - $type\" {\n            r debug reload\n            r sinterstore setres set1 set2\n            assert_encoding $type setres\n            assert_equal [list 195 196 197 198 199 $large] [lsort [r smembers setres]]\n        }\n\n        test \"SUNION with two sets - $type\" {\n            set expected [lsort -uniq \"[r smembers set1] [r smembers set2]\"]\n            assert_equal $expected [lsort [r sunion set1 set2]]\n        }\n\n        test \"SUNIONSTORE with two sets - $type\" {\n            r sunionstore setres set1 set2\n            assert_encoding $type setres\n            set expected [lsort -uniq \"[r smembers set1] [r smembers set2]\"]\n            assert_equal $expected [lsort [r smembers setres]]\n        }\n\n        test \"SINTER against three sets - $type\" {\n            assert_equal [list 195 199 $large] [lsort [r sinter set1 set2 set3]]\n        }\n\n        test \"SINTERSTORE with three sets - $type\" {\n            r sinterstore setres set1 set2 set3\n            assert_equal [list 195 199 $large] [lsort [r smembers setres]]\n        }\n\n        test \"SUNION with non existing keys - $type\" {\n            set expected [lsort -uniq \"[r smembers set1] [r smembers set2]\"]\n            assert_equal $expected [lsort [r sunion nokey1 set1 set2 nokey2]]\n        }\n\n        test \"SDIFF with two sets - $type\" {\n            assert_equal {0 1 2 3 4} [lsort [r sdiff set1 set4]]\n        }\n\n        test \"SDIFF with three sets - $type\" {\n            assert_equal {1 2 3 4} [lsort [r sdiff set1 set4 set5]]\n        }\n\n        test \"SDIFFSTORE with three sets - $type\" {\n            r sdiffstore setres set1 set4 set5\n            # When we start with intsets, we should always end with intsets.\n            if {$type eq {intset}} {\n                assert_encoding intset setres\n            }\n            assert_equal {1 2 3 4} [lsort [r smembers setres]]\n        }\n    }\n\n    test \"SDIFF with first set empty\" {\n        r del set1 set2 set3\n        r sadd set2 1 2 3 4\n        r sadd set3 a b c d\n        r sdiff set1 set2 set3\n    } {}\n\n    test \"SDIFF with same set two times\" {\n        r del set1\n        r sadd set1 a b c 1 2 3 4 5 6\n        r sdiff set1 set1\n    } {}\n\n    test \"SDIFF fuzzing\" {\n        for {set j 0} {$j < 100} {incr j} {\n            unset -nocomplain s\n            array set s {}\n            set args {}\n            set num_sets [expr {[randomInt 10]+1}]\n            for {set i 0} {$i < $num_sets} {incr i} {\n                set num_elements [randomInt 100]\n                r del set_$i\n                lappend args set_$i\n                while {$num_elements} {\n                    set ele [randomValue]\n                    r sadd set_$i $ele\n                    if {$i == 0} {\n                        set s($ele) x\n                    } else {\n                        unset -nocomplain s($ele)\n                    }\n                    incr num_elements -1\n                }\n            }\n            set result [lsort [r sdiff {*}$args]]\n            assert_equal $result [lsort [array names s]]\n        }\n    }\n\n    test \"SINTER against non-set should throw error\" {\n        r set key1 x\n        assert_error \"WRONGTYPE*\" {r sinter key1 noset}\n    }\n\n    test \"SUNION against non-set should throw error\" {\n        r set key1 x\n        assert_error \"WRONGTYPE*\" {r sunion key1 noset}\n    }\n\n    test \"SINTER should handle non existing key as empty\" {\n        r del set1 set2 set3\n        r sadd set1 a b c\n        r sadd set2 b c d\n        r sinter set1 set2 set3\n    } {}\n\n    test \"SINTER with same integer elements but different encoding\" {\n        r del set1 set2\n        r sadd set1 1 2 3\n        r sadd set2 1 2 3 a\n        r srem set2 a\n        assert_encoding intset set1\n        assert_encoding hashtable set2\n        lsort [r sinter set1 set2]\n    } {1 2 3}\n\n    test \"SINTERSTORE against non existing keys should delete dstkey\" {\n        r set setres xxx\n        assert_equal 0 [r sinterstore setres foo111 bar222]\n        assert_equal 0 [r exists setres]\n    }\n\n    test \"SUNIONSTORE against non existing keys should delete dstkey\" {\n        r set setres xxx\n        assert_equal 0 [r sunionstore setres foo111 bar222]\n        assert_equal 0 [r exists setres]\n    }\n\n    foreach {type contents} {hashtable {a b c} intset {1 2 3}} {\n        test \"SPOP basics - $type\" {\n            create_set myset $contents\n            assert_encoding $type myset\n            assert_equal $contents [lsort [list [r spop myset] [r spop myset] [r spop myset]]]\n            assert_equal 0 [r scard myset]\n        }\n\n        test \"SRANDMEMBER - $type\" {\n            create_set myset $contents\n            unset -nocomplain myset\n            array set myset {}\n            for {set i 0} {$i < 100} {incr i} {\n                set myset([r srandmember myset]) 1\n            }\n            assert_equal $contents [lsort [array names myset]]\n        }\n    }\n\n    test \"SRANDMEMBER with <count> against non existing key\" {\n        r srandmember nonexisting_key 100\n    } {}\n\n    foreach {type contents} {\n        hashtable {\n            1 5 10 50 125 50000 33959417 4775547 65434162\n            12098459 427716 483706 2726473884 72615637475\n            MARY PATRICIA LINDA BARBARA ELIZABETH JENNIFER MARIA\n            SUSAN MARGARET DOROTHY LISA NANCY KAREN BETTY HELEN\n            SANDRA DONNA CAROL RUTH SHARON MICHELLE LAURA SARAH\n            KIMBERLY DEBORAH JESSICA SHIRLEY CYNTHIA ANGELA MELISSA\n            BRENDA AMY ANNA REBECCA VIRGINIA KATHLEEN\n        }\n        intset {\n            0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19\n            20 21 22 23 24 25 26 27 28 29\n            30 31 32 33 34 35 36 37 38 39\n            40 41 42 43 44 45 46 47 48 49\n        }\n    } {\n        test \"SRANDMEMBER with <count> - $type\" {\n            create_set myset $contents\n            unset -nocomplain myset\n            array set myset {}\n            foreach ele [r smembers myset] {\n                set myset($ele) 1\n            }\n            assert_equal [lsort $contents] [lsort [array names myset]]\n\n            # Make sure that a count of 0 is handled correctly.\n            assert_equal [r srandmember myset 0] {}\n\n            # We'll stress different parts of the code, see the implementation\n            # of SRANDMEMBER for more information, but basically there are\n            # four different code paths.\n            #\n            # PATH 1: Use negative count.\n            #\n            # 1) Check that it returns repeated elements.\n            set res [r srandmember myset -100]\n            assert_equal [llength $res] 100\n\n            # 2) Check that all the elements actually belong to the\n            # original set.\n            foreach ele $res {\n                assert {[info exists myset($ele)]}\n            }\n\n            # 3) Check that eventually all the elements are returned.\n            unset -nocomplain auxset\n            set iterations 1000\n            while {$iterations != 0} {\n                incr iterations -1\n                set res [r srandmember myset -10]\n                foreach ele $res {\n                    set auxset($ele) 1\n                }\n                if {[lsort [array names myset]] eq\n                    [lsort [array names auxset]]} {\n                    break;\n                }\n            }\n            assert {$iterations != 0}\n\n            # PATH 2: positive count (unique behavior) with requested size\n            # equal or greater than set size.\n            foreach size {50 100} {\n                set res [r srandmember myset $size]\n                assert_equal [llength $res] 50\n                assert_equal [lsort $res] [lsort [array names myset]]\n            }\n\n            # PATH 3: Ask almost as elements as there are in the set.\n            # In this case the implementation will duplicate the original\n            # set and will remove random elements up to the requested size.\n            #\n            # PATH 4: Ask a number of elements definitely smaller than\n            # the set size.\n            #\n            # We can test both the code paths just changing the size but\n            # using the same code.\n\n            foreach size {45 5} {\n                set res [r srandmember myset $size]\n                assert_equal [llength $res] $size\n\n                # 1) Check that all the elements actually belong to the\n                # original set.\n                foreach ele $res {\n                    assert {[info exists myset($ele)]}\n                }\n\n                # 2) Check that eventually all the elements are returned.\n                unset -nocomplain auxset\n                set iterations 1000\n                while {$iterations != 0} {\n                    incr iterations -1\n                    set res [r srandmember myset -10]\n                    foreach ele $res {\n                        set auxset($ele) 1\n                    }\n                    if {[lsort [array names myset]] eq\n                        [lsort [array names auxset]]} {\n                        break;\n                    }\n                }\n                assert {$iterations != 0}\n            }\n        }\n    }\n\n    proc setup_move {} {\n        r del myset3 myset4\n        create_set myset1 {1 a b}\n        create_set myset2 {2 3 4}\n        assert_encoding hashtable myset1\n        assert_encoding intset myset2\n    }\n\n    test \"SMOVE basics - from regular set to intset\" {\n        # move a non-integer element to an intset should convert encoding\n        setup_move\n        assert_equal 1 [r smove myset1 myset2 a]\n        assert_equal {1 b} [lsort [r smembers myset1]]\n        assert_equal {2 3 4 a} [lsort [r smembers myset2]]\n        assert_encoding hashtable myset2\n\n        # move an integer element should not convert the encoding\n        setup_move\n        assert_equal 1 [r smove myset1 myset2 1]\n        assert_equal {a b} [lsort [r smembers myset1]]\n        assert_equal {1 2 3 4} [lsort [r smembers myset2]]\n        assert_encoding intset myset2\n    }\n\n    test \"SMOVE basics - from intset to regular set\" {\n        setup_move\n        assert_equal 1 [r smove myset2 myset1 2]\n        assert_equal {1 2 a b} [lsort [r smembers myset1]]\n        assert_equal {3 4} [lsort [r smembers myset2]]\n    }\n\n    test \"SMOVE non existing key\" {\n        setup_move\n        assert_equal 0 [r smove myset1 myset2 foo]\n        assert_equal 0 [r smove myset1 myset1 foo]\n        assert_equal {1 a b} [lsort [r smembers myset1]]\n        assert_equal {2 3 4} [lsort [r smembers myset2]]\n    }\n\n    test \"SMOVE non existing src set\" {\n        setup_move\n        assert_equal 0 [r smove noset myset2 foo]\n        assert_equal {2 3 4} [lsort [r smembers myset2]]\n    }\n\n    test \"SMOVE from regular set to non existing destination set\" {\n        setup_move\n        assert_equal 1 [r smove myset1 myset3 a]\n        assert_equal {1 b} [lsort [r smembers myset1]]\n        assert_equal {a} [lsort [r smembers myset3]]\n        assert_encoding hashtable myset3\n    }\n\n    test \"SMOVE from intset to non existing destination set\" {\n        setup_move\n        assert_equal 1 [r smove myset2 myset3 2]\n        assert_equal {3 4} [lsort [r smembers myset2]]\n        assert_equal {2} [lsort [r smembers myset3]]\n        assert_encoding intset myset3\n    }\n\n    test \"SMOVE wrong src key type\" {\n        r set x 10\n        assert_error \"WRONGTYPE*\" {r smove x myset2 foo}\n    }\n\n    test \"SMOVE wrong dst key type\" {\n        r set x 10\n        assert_error \"WRONGTYPE*\" {r smove myset2 x foo}\n    }\n\n    test \"SMOVE with identical source and destination\" {\n        r del set\n        r sadd set a b c\n        r smove set set b\n        lsort [r smembers set]\n    } {a b c}\n\n    tags {slow} {\n        test {intsets implementation stress testing} {\n            for {set j 0} {$j < 20} {incr j} {\n                unset -nocomplain s\n                array set s {}\n                r del s\n                set len [randomInt 1024]\n                for {set i 0} {$i < $len} {incr i} {\n                    randpath {\n                        set data [randomInt 65536]\n                    } {\n                        set data [randomInt 4294967296]\n                    } {\n                        set data [randomInt 18446744073709551616]\n                    }\n                    set s($data) {}\n                    r sadd s $data\n                }\n                assert_equal [lsort [r smembers s]] [lsort [array names s]]\n                set len [array size s]\n                for {set i 0} {$i < $len} {incr i} {\n                    set e [r spop s]\n                    if {![info exists s($e)]} {\n                        puts \"Can't find '$e' on local array\"\n                        puts \"Local array: [lsort [r smembers s]]\"\n                        puts \"Remote array: [lsort [array names s]]\"\n                        error \"exception\"\n                    }\n                    array unset s $e\n                }\n                assert_equal [r scard s] 0\n                assert_equal [array size s] 0\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "extern/deprecated/redis-2.8.21/tests/unit/type/zset.tcl",
    "content": "start_server {tags {\"zset\"}} {\n    proc create_zset {key items} {\n        r del $key\n        foreach {score entry} $items {\n            r zadd $key $score $entry\n        }\n    }\n\n    proc basics {encoding} {\n        if {$encoding == \"ziplist\"} {\n            r config set zset-max-ziplist-entries 128\n            r config set zset-max-ziplist-value 64\n        } elseif {$encoding == \"skiplist\"} {\n            r config set zset-max-ziplist-entries 0\n            r config set zset-max-ziplist-value 0\n        } else {\n            puts \"Unknown sorted set encoding\"\n            exit\n        }\n\n        test \"Check encoding - $encoding\" {\n            r del ztmp\n            r zadd ztmp 10 x\n            assert_encoding $encoding ztmp\n        }\n\n        test \"ZSET basic ZADD and score update - $encoding\" {\n            r del ztmp\n            r zadd ztmp 10 x\n            r zadd ztmp 20 y\n            r zadd ztmp 30 z\n            assert_equal {x y z} [r zrange ztmp 0 -1]\n\n            r zadd ztmp 1 y\n            assert_equal {y x z} [r zrange ztmp 0 -1]\n        }\n\n        test \"ZSET element can't be set to NaN with ZADD - $encoding\" {\n            assert_error \"*not*float*\" {r zadd myzset nan abc}\n        }\n\n        test \"ZSET element can't be set to NaN with ZINCRBY\" {\n            assert_error \"*not*float*\" {r zadd myzset nan abc}\n        }\n\n        test \"ZINCRBY calls leading to NaN result in error\" {\n            r zincrby myzset +inf abc\n            assert_error \"*NaN*\" {r zincrby myzset -inf abc}\n        }\n\n        test {ZADD - Variadic version base case} {\n            r del myzset\n            list [r zadd myzset 10 a 20 b 30 c] [r zrange myzset 0 -1 withscores]\n        } {3 {a 10 b 20 c 30}}\n\n        test {ZADD - Return value is the number of actually added items} {\n            list [r zadd myzset 5 x 20 b 30 c] [r zrange myzset 0 -1 withscores]\n        } {1 {x 5 a 10 b 20 c 30}}\n\n        test {ZADD - Variadic version does not add nothing on single parsing err} {\n            r del myzset\n            catch {r zadd myzset 10 a 20 b 30.badscore c} e\n            assert_match {*ERR*not*float*} $e\n            r exists myzset\n        } {0}\n\n        test {ZADD - Variadic version will raise error on missing arg} {\n            r del myzset\n            catch {r zadd myzset 10 a 20 b 30 c 40} e\n            assert_match {*ERR*syntax*} $e\n        }\n\n        test {ZINCRBY does not work variadic even if shares ZADD implementation} {\n            r del myzset\n            catch {r zincrby myzset 10 a 20 b 30 c} e\n            assert_match {*ERR*wrong*number*arg*} $e\n        }\n\n        test \"ZCARD basics - $encoding\" {\n            assert_equal 3 [r zcard ztmp]\n            assert_equal 0 [r zcard zdoesntexist]\n        }\n\n        test \"ZREM removes key after last element is removed\" {\n            r del ztmp\n            r zadd ztmp 10 x\n            r zadd ztmp 20 y\n\n            assert_equal 1 [r exists ztmp]\n            assert_equal 0 [r zrem ztmp z]\n            assert_equal 1 [r zrem ztmp y]\n            assert_equal 1 [r zrem ztmp x]\n            assert_equal 0 [r exists ztmp]\n        }\n\n        test \"ZREM variadic version\" {\n            r del ztmp\n            r zadd ztmp 10 a 20 b 30 c\n            assert_equal 2 [r zrem ztmp x y a b k]\n            assert_equal 0 [r zrem ztmp foo bar]\n            assert_equal 1 [r zrem ztmp c]\n            r exists ztmp\n        } {0}\n\n        test \"ZREM variadic version -- remove elements after key deletion\" {\n            r del ztmp\n            r zadd ztmp 10 a 20 b 30 c\n            r zrem ztmp a b c d e f g\n        } {3}\n\n        test \"ZRANGE basics - $encoding\" {\n            r del ztmp\n            r zadd ztmp 1 a\n            r zadd ztmp 2 b\n            r zadd ztmp 3 c\n            r zadd ztmp 4 d\n\n            assert_equal {a b c d} [r zrange ztmp 0 -1]\n            assert_equal {a b c} [r zrange ztmp 0 -2]\n            assert_equal {b c d} [r zrange ztmp 1 -1]\n            assert_equal {b c} [r zrange ztmp 1 -2]\n            assert_equal {c d} [r zrange ztmp -2 -1]\n            assert_equal {c} [r zrange ztmp -2 -2]\n\n            # out of range start index\n            assert_equal {a b c} [r zrange ztmp -5 2]\n            assert_equal {a b} [r zrange ztmp -5 1]\n            assert_equal {} [r zrange ztmp 5 -1]\n            assert_equal {} [r zrange ztmp 5 -2]\n\n            # out of range end index\n            assert_equal {a b c d} [r zrange ztmp 0 5]\n            assert_equal {b c d} [r zrange ztmp 1 5]\n            assert_equal {} [r zrange ztmp 0 -5]\n            assert_equal {} [r zrange ztmp 1 -5]\n\n            # withscores\n            assert_equal {a 1 b 2 c 3 d 4} [r zrange ztmp 0 -1 withscores]\n        }\n\n        test \"ZREVRANGE basics - $encoding\" {\n            r del ztmp\n            r zadd ztmp 1 a\n            r zadd ztmp 2 b\n            r zadd ztmp 3 c\n            r zadd ztmp 4 d\n\n            assert_equal {d c b a} [r zrevrange ztmp 0 -1]\n            assert_equal {d c b} [r zrevrange ztmp 0 -2]\n            assert_equal {c b a} [r zrevrange ztmp 1 -1]\n            assert_equal {c b} [r zrevrange ztmp 1 -2]\n            assert_equal {b a} [r zrevrange ztmp -2 -1]\n            assert_equal {b} [r zrevrange ztmp -2 -2]\n\n            # out of range start index\n            assert_equal {d c b} [r zrevrange ztmp -5 2]\n            assert_equal {d c} [r zrevrange ztmp -5 1]\n            assert_equal {} [r zrevrange ztmp 5 -1]\n            assert_equal {} [r zrevrange ztmp 5 -2]\n\n            # out of range end index\n            assert_equal {d c b a} [r zrevrange ztmp 0 5]\n            assert_equal {c b a} [r zrevrange ztmp 1 5]\n            assert_equal {} [r zrevrange ztmp 0 -5]\n            assert_equal {} [r zrevrange ztmp 1 -5]\n\n            # withscores\n            assert_equal {d 4 c 3 b 2 a 1} [r zrevrange ztmp 0 -1 withscores]\n        }\n\n        test \"ZRANK/ZREVRANK basics - $encoding\" {\n            r del zranktmp\n            r zadd zranktmp 10 x\n            r zadd zranktmp 20 y\n            r zadd zranktmp 30 z\n            assert_equal 0 [r zrank zranktmp x]\n            assert_equal 1 [r zrank zranktmp y]\n            assert_equal 2 [r zrank zranktmp z]\n            assert_equal \"\" [r zrank zranktmp foo]\n            assert_equal 2 [r zrevrank zranktmp x]\n            assert_equal 1 [r zrevrank zranktmp y]\n            assert_equal 0 [r zrevrank zranktmp z]\n            assert_equal \"\" [r zrevrank zranktmp foo]\n        }\n\n        test \"ZRANK - after deletion - $encoding\" {\n            r zrem zranktmp y\n            assert_equal 0 [r zrank zranktmp x]\n            assert_equal 1 [r zrank zranktmp z]\n        }\n\n        test \"ZINCRBY - can create a new sorted set - $encoding\" {\n            r del zset\n            r zincrby zset 1 foo\n            assert_equal {foo} [r zrange zset 0 -1]\n            assert_equal 1 [r zscore zset foo]\n        }\n\n        test \"ZINCRBY - increment and decrement - $encoding\" {\n            r zincrby zset 2 foo\n            r zincrby zset 1 bar\n            assert_equal {bar foo} [r zrange zset 0 -1]\n\n            r zincrby zset 10 bar\n            r zincrby zset -5 foo\n            r zincrby zset -5 bar\n            assert_equal {foo bar} [r zrange zset 0 -1]\n\n            assert_equal -2 [r zscore zset foo]\n            assert_equal  6 [r zscore zset bar]\n        }\n\n        proc create_default_zset {} {\n            create_zset zset {-inf a 1 b 2 c 3 d 4 e 5 f +inf g}\n        }\n\n        test \"ZRANGEBYSCORE/ZREVRANGEBYSCORE/ZCOUNT basics\" {\n            create_default_zset\n\n            # inclusive range\n            assert_equal {a b c} [r zrangebyscore zset -inf 2]\n            assert_equal {b c d} [r zrangebyscore zset 0 3]\n            assert_equal {d e f} [r zrangebyscore zset 3 6]\n            assert_equal {e f g} [r zrangebyscore zset 4 +inf]\n            assert_equal {c b a} [r zrevrangebyscore zset 2 -inf]\n            assert_equal {d c b} [r zrevrangebyscore zset 3 0]\n            assert_equal {f e d} [r zrevrangebyscore zset 6 3]\n            assert_equal {g f e} [r zrevrangebyscore zset +inf 4]\n            assert_equal 3 [r zcount zset 0 3]\n\n            # exclusive range\n            assert_equal {b}   [r zrangebyscore zset (-inf (2]\n            assert_equal {b c} [r zrangebyscore zset (0 (3]\n            assert_equal {e f} [r zrangebyscore zset (3 (6]\n            assert_equal {f}   [r zrangebyscore zset (4 (+inf]\n            assert_equal {b}   [r zrevrangebyscore zset (2 (-inf]\n            assert_equal {c b} [r zrevrangebyscore zset (3 (0]\n            assert_equal {f e} [r zrevrangebyscore zset (6 (3]\n            assert_equal {f}   [r zrevrangebyscore zset (+inf (4]\n            assert_equal 2 [r zcount zset (0 (3]\n\n            # test empty ranges\n            r zrem zset a\n            r zrem zset g\n\n            # inclusive\n            assert_equal {} [r zrangebyscore zset 4 2]\n            assert_equal {} [r zrangebyscore zset 6 +inf]\n            assert_equal {} [r zrangebyscore zset -inf -6]\n            assert_equal {} [r zrevrangebyscore zset +inf 6]\n            assert_equal {} [r zrevrangebyscore zset -6 -inf]\n\n            # exclusive\n            assert_equal {} [r zrangebyscore zset (4 (2]\n            assert_equal {} [r zrangebyscore zset 2 (2]\n            assert_equal {} [r zrangebyscore zset (2 2]\n            assert_equal {} [r zrangebyscore zset (6 (+inf]\n            assert_equal {} [r zrangebyscore zset (-inf (-6]\n            assert_equal {} [r zrevrangebyscore zset (+inf (6]\n            assert_equal {} [r zrevrangebyscore zset (-6 (-inf]\n\n            # empty inner range\n            assert_equal {} [r zrangebyscore zset 2.4 2.6]\n            assert_equal {} [r zrangebyscore zset (2.4 2.6]\n            assert_equal {} [r zrangebyscore zset 2.4 (2.6]\n            assert_equal {} [r zrangebyscore zset (2.4 (2.6]\n        }\n\n        test \"ZRANGEBYSCORE with WITHSCORES\" {\n            create_default_zset\n            assert_equal {b 1 c 2 d 3} [r zrangebyscore zset 0 3 withscores]\n            assert_equal {d 3 c 2 b 1} [r zrevrangebyscore zset 3 0 withscores]\n        }\n\n        test \"ZRANGEBYSCORE with LIMIT\" {\n            create_default_zset\n            assert_equal {b c}   [r zrangebyscore zset 0 10 LIMIT 0 2]\n            assert_equal {d e f} [r zrangebyscore zset 0 10 LIMIT 2 3]\n            assert_equal {d e f} [r zrangebyscore zset 0 10 LIMIT 2 10]\n            assert_equal {}      [r zrangebyscore zset 0 10 LIMIT 20 10]\n            assert_equal {f e}   [r zrevrangebyscore zset 10 0 LIMIT 0 2]\n            assert_equal {d c b} [r zrevrangebyscore zset 10 0 LIMIT 2 3]\n            assert_equal {d c b} [r zrevrangebyscore zset 10 0 LIMIT 2 10]\n            assert_equal {}      [r zrevrangebyscore zset 10 0 LIMIT 20 10]\n        }\n\n        test \"ZRANGEBYSCORE with LIMIT and WITHSCORES\" {\n            create_default_zset\n            assert_equal {e 4 f 5} [r zrangebyscore zset 2 5 LIMIT 2 3 WITHSCORES]\n            assert_equal {d 3 c 2} [r zrevrangebyscore zset 5 2 LIMIT 2 3 WITHSCORES]\n        }\n\n        test \"ZRANGEBYSCORE with non-value min or max\" {\n            assert_error \"*not*float*\" {r zrangebyscore fooz str 1}\n            assert_error \"*not*float*\" {r zrangebyscore fooz 1 str}\n            assert_error \"*not*float*\" {r zrangebyscore fooz 1 NaN}\n        }\n\n        proc create_default_lex_zset {} {\n            create_zset zset {0 alpha 0 bar 0 cool 0 down\n                              0 elephant 0 foo 0 great 0 hill\n                              0 omega}\n        }\n\n        test \"ZRANGEBYLEX/ZREVRANGEBYLEX/ZCOUNT basics\" {\n            create_default_lex_zset\n\n            # inclusive range\n            assert_equal {alpha bar cool} [r zrangebylex zset - \\[cool]\n            assert_equal {bar cool down} [r zrangebylex zset \\[bar \\[down]\n            assert_equal {great hill omega} [r zrangebylex zset \\[g +]\n            assert_equal {cool bar alpha} [r zrevrangebylex zset \\[cool -]\n            assert_equal {down cool bar} [r zrevrangebylex zset \\[down \\[bar]\n            assert_equal {omega hill great foo elephant down} [r zrevrangebylex zset + \\[d]\n            assert_equal 3 [r zlexcount zset \\[ele \\[h]\n\n            # exclusive range\n            assert_equal {alpha bar} [r zrangebylex zset - (cool]\n            assert_equal {cool} [r zrangebylex zset (bar (down]\n            assert_equal {hill omega} [r zrangebylex zset (great +]\n            assert_equal {bar alpha} [r zrevrangebylex zset (cool -]\n            assert_equal {cool} [r zrevrangebylex zset (down (bar]\n            assert_equal {omega hill} [r zrevrangebylex zset + (great]\n            assert_equal 2 [r zlexcount zset (ele (great]\n\n            # inclusive and exclusive\n            assert_equal {} [r zrangebylex zset (az (b]\n            assert_equal {} [r zrangebylex zset (z +]\n            assert_equal {} [r zrangebylex zset - \\[aaaa]\n            assert_equal {} [r zrevrangebylex zset \\[elez \\[elex]\n            assert_equal {} [r zrevrangebylex zset (hill (omega]\n        }\n\n        test \"ZRANGEBYSLEX with LIMIT\" {\n            create_default_lex_zset\n            assert_equal {alpha bar} [r zrangebylex zset - \\[cool LIMIT 0 2]\n            assert_equal {bar cool} [r zrangebylex zset - \\[cool LIMIT 1 2]\n            assert_equal {} [r zrangebylex zset \\[bar \\[down LIMIT 0 0]\n            assert_equal {} [r zrangebylex zset \\[bar \\[down LIMIT 2 0]\n            assert_equal {bar} [r zrangebylex zset \\[bar \\[down LIMIT 0 1]\n            assert_equal {cool} [r zrangebylex zset \\[bar \\[down LIMIT 1 1]\n            assert_equal {bar cool down} [r zrangebylex zset \\[bar \\[down LIMIT 0 100]\n            assert_equal {omega hill great foo elephant} [r zrevrangebylex zset + \\[d LIMIT 0 5]\n            assert_equal {omega hill great foo} [r zrevrangebylex zset + \\[d LIMIT 0 4]\n        }\n\n        test \"ZRANGEBYLEX with invalid lex range specifiers\" {\n            assert_error \"*not*string*\" {r zrangebylex fooz foo bar}\n            assert_error \"*not*string*\" {r zrangebylex fooz \\[foo bar}\n            assert_error \"*not*string*\" {r zrangebylex fooz foo \\[bar}\n            assert_error \"*not*string*\" {r zrangebylex fooz +x \\[bar}\n            assert_error \"*not*string*\" {r zrangebylex fooz -x \\[bar}\n        }\n\n        test \"ZREMRANGEBYSCORE basics\" {\n            proc remrangebyscore {min max} {\n                create_zset zset {1 a 2 b 3 c 4 d 5 e}\n                assert_equal 1 [r exists zset]\n                r zremrangebyscore zset $min $max\n            }\n\n            # inner range\n            assert_equal 3 [remrangebyscore 2 4]\n            assert_equal {a e} [r zrange zset 0 -1]\n\n            # start underflow\n            assert_equal 1 [remrangebyscore -10 1]\n            assert_equal {b c d e} [r zrange zset 0 -1]\n\n            # end overflow\n            assert_equal 1 [remrangebyscore 5 10]\n            assert_equal {a b c d} [r zrange zset 0 -1]\n\n            # switch min and max\n            assert_equal 0 [remrangebyscore 4 2]\n            assert_equal {a b c d e} [r zrange zset 0 -1]\n\n            # -inf to mid\n            assert_equal 3 [remrangebyscore -inf 3]\n            assert_equal {d e} [r zrange zset 0 -1]\n\n            # mid to +inf\n            assert_equal 3 [remrangebyscore 3 +inf]\n            assert_equal {a b} [r zrange zset 0 -1]\n\n            # -inf to +inf\n            assert_equal 5 [remrangebyscore -inf +inf]\n            assert_equal {} [r zrange zset 0 -1]\n\n            # exclusive min\n            assert_equal 4 [remrangebyscore (1 5]\n            assert_equal {a} [r zrange zset 0 -1]\n            assert_equal 3 [remrangebyscore (2 5]\n            assert_equal {a b} [r zrange zset 0 -1]\n\n            # exclusive max\n            assert_equal 4 [remrangebyscore 1 (5]\n            assert_equal {e} [r zrange zset 0 -1]\n            assert_equal 3 [remrangebyscore 1 (4]\n            assert_equal {d e} [r zrange zset 0 -1]\n\n            # exclusive min and max\n            assert_equal 3 [remrangebyscore (1 (5]\n            assert_equal {a e} [r zrange zset 0 -1]\n\n            # destroy when empty\n            assert_equal 5 [remrangebyscore 1 5]\n            assert_equal 0 [r exists zset]\n        }\n\n        test \"ZREMRANGEBYSCORE with non-value min or max\" {\n            assert_error \"*not*float*\" {r zremrangebyscore fooz str 1}\n            assert_error \"*not*float*\" {r zremrangebyscore fooz 1 str}\n            assert_error \"*not*float*\" {r zremrangebyscore fooz 1 NaN}\n        }\n\n        test \"ZREMRANGEBYRANK basics\" {\n            proc remrangebyrank {min max} {\n                create_zset zset {1 a 2 b 3 c 4 d 5 e}\n                assert_equal 1 [r exists zset]\n                r zremrangebyrank zset $min $max\n            }\n\n            # inner range\n            assert_equal 3 [remrangebyrank 1 3]\n            assert_equal {a e} [r zrange zset 0 -1]\n\n            # start underflow\n            assert_equal 1 [remrangebyrank -10 0]\n            assert_equal {b c d e} [r zrange zset 0 -1]\n\n            # start overflow\n            assert_equal 0 [remrangebyrank 10 -1]\n            assert_equal {a b c d e} [r zrange zset 0 -1]\n\n            # end underflow\n            assert_equal 0 [remrangebyrank 0 -10]\n            assert_equal {a b c d e} [r zrange zset 0 -1]\n\n            # end overflow\n            assert_equal 5 [remrangebyrank 0 10]\n            assert_equal {} [r zrange zset 0 -1]\n\n            # destroy when empty\n            assert_equal 5 [remrangebyrank 0 4]\n            assert_equal 0 [r exists zset]\n        }\n\n        test \"ZUNIONSTORE against non-existing key doesn't set destination - $encoding\" {\n            r del zseta\n            assert_equal 0 [r zunionstore dst_key 1 zseta]\n            assert_equal 0 [r exists dst_key]\n        }\n\n        test \"ZUNIONSTORE with empty set - $encoding\" {\n            r del zseta zsetb\n            r zadd zseta 1 a\n            r zadd zseta 2 b\n            r zunionstore zsetc 2 zseta zsetb\n            r zrange zsetc 0 -1 withscores\n        } {a 1 b 2}\n\n        test \"ZUNIONSTORE basics - $encoding\" {\n            r del zseta zsetb zsetc\n            r zadd zseta 1 a\n            r zadd zseta 2 b\n            r zadd zseta 3 c\n            r zadd zsetb 1 b\n            r zadd zsetb 2 c\n            r zadd zsetb 3 d\n\n            assert_equal 4 [r zunionstore zsetc 2 zseta zsetb]\n            assert_equal {a 1 b 3 d 3 c 5} [r zrange zsetc 0 -1 withscores]\n        }\n\n        test \"ZUNIONSTORE with weights - $encoding\" {\n            assert_equal 4 [r zunionstore zsetc 2 zseta zsetb weights 2 3]\n            assert_equal {a 2 b 7 d 9 c 12} [r zrange zsetc 0 -1 withscores]\n        }\n\n        test \"ZUNIONSTORE with a regular set and weights - $encoding\" {\n            r del seta\n            r sadd seta a\n            r sadd seta b\n            r sadd seta c\n\n            assert_equal 4 [r zunionstore zsetc 2 seta zsetb weights 2 3]\n            assert_equal {a 2 b 5 c 8 d 9} [r zrange zsetc 0 -1 withscores]\n        }\n\n        test \"ZUNIONSTORE with AGGREGATE MIN - $encoding\" {\n            assert_equal 4 [r zunionstore zsetc 2 zseta zsetb aggregate min]\n            assert_equal {a 1 b 1 c 2 d 3} [r zrange zsetc 0 -1 withscores]\n        }\n\n        test \"ZUNIONSTORE with AGGREGATE MAX - $encoding\" {\n            assert_equal 4 [r zunionstore zsetc 2 zseta zsetb aggregate max]\n            assert_equal {a 1 b 2 c 3 d 3} [r zrange zsetc 0 -1 withscores]\n        }\n\n        test \"ZINTERSTORE basics - $encoding\" {\n            assert_equal 2 [r zinterstore zsetc 2 zseta zsetb]\n            assert_equal {b 3 c 5} [r zrange zsetc 0 -1 withscores]\n        }\n\n        test \"ZINTERSTORE with weights - $encoding\" {\n            assert_equal 2 [r zinterstore zsetc 2 zseta zsetb weights 2 3]\n            assert_equal {b 7 c 12} [r zrange zsetc 0 -1 withscores]\n        }\n\n        test \"ZINTERSTORE with a regular set and weights - $encoding\" {\n            r del seta\n            r sadd seta a\n            r sadd seta b\n            r sadd seta c\n            assert_equal 2 [r zinterstore zsetc 2 seta zsetb weights 2 3]\n            assert_equal {b 5 c 8} [r zrange zsetc 0 -1 withscores]\n        }\n\n        test \"ZINTERSTORE with AGGREGATE MIN - $encoding\" {\n            assert_equal 2 [r zinterstore zsetc 2 zseta zsetb aggregate min]\n            assert_equal {b 1 c 2} [r zrange zsetc 0 -1 withscores]\n        }\n\n        test \"ZINTERSTORE with AGGREGATE MAX - $encoding\" {\n            assert_equal 2 [r zinterstore zsetc 2 zseta zsetb aggregate max]\n            assert_equal {b 2 c 3} [r zrange zsetc 0 -1 withscores]\n        }\n\n        foreach cmd {ZUNIONSTORE ZINTERSTORE} {\n            test \"$cmd with +inf/-inf scores - $encoding\" {\n                r del zsetinf1 zsetinf2\n\n                r zadd zsetinf1 +inf key\n                r zadd zsetinf2 +inf key\n                r $cmd zsetinf3 2 zsetinf1 zsetinf2\n                assert_equal inf [r zscore zsetinf3 key]\n\n                r zadd zsetinf1 -inf key\n                r zadd zsetinf2 +inf key\n                r $cmd zsetinf3 2 zsetinf1 zsetinf2\n                assert_equal 0 [r zscore zsetinf3 key]\n\n                r zadd zsetinf1 +inf key\n                r zadd zsetinf2 -inf key\n                r $cmd zsetinf3 2 zsetinf1 zsetinf2\n                assert_equal 0 [r zscore zsetinf3 key]\n\n                r zadd zsetinf1 -inf key\n                r zadd zsetinf2 -inf key\n                r $cmd zsetinf3 2 zsetinf1 zsetinf2\n                assert_equal -inf [r zscore zsetinf3 key]\n            }\n\n            test \"$cmd with NaN weights $encoding\" {\n                r del zsetinf1 zsetinf2\n\n                r zadd zsetinf1 1.0 key\n                r zadd zsetinf2 1.0 key\n                assert_error \"*weight*not*float*\" {\n                    r $cmd zsetinf3 2 zsetinf1 zsetinf2 weights nan nan\n                }\n            }\n        }\n    }\n\n    basics ziplist\n    basics skiplist\n\n    test {ZINTERSTORE regression with two sets, intset+hashtable} {\n        r del seta setb setc\n        r sadd set1 a\n        r sadd set2 10\n        r zinterstore set3 2 set1 set2\n    } {0}\n\n    test {ZUNIONSTORE regression, should not create NaN in scores} {\n        r zadd z -inf neginf\n        r zunionstore out 1 z weights 0\n        r zrange out 0 -1 withscores\n    } {neginf 0}\n\n    test {ZINTERSTORE #516 regression, mixed sets and ziplist zsets} {\n        r sadd one 100 101 102 103\n        r sadd two 100 200 201 202\n        r zadd three 1 500 1 501 1 502 1 503 1 100\n        r zinterstore to_here 3 one two three WEIGHTS 0 0 1\n        r zrange to_here 0 -1\n    } {100}\n\n    test {ZUNIONSTORE result is sorted} {\n        # Create two sets with common and not common elements, perform\n        # the UNION, check that elements are still sorted.\n        r del one two dest\n        set cmd1 [list r zadd one]\n        set cmd2 [list r zadd two]\n        for {set j 0} {$j < 1000} {incr j} {\n            lappend cmd1 [expr rand()] [randomInt 1000]\n            lappend cmd2 [expr rand()] [randomInt 1000]\n        }\n        {*}$cmd1\n        {*}$cmd2\n        assert {[r zcard one] > 100}\n        assert {[r zcard two] > 100}\n        r zunionstore dest 2 one two\n        set oldscore 0\n        foreach {ele score} [r zrange dest 0 -1 withscores] {\n            assert {$score >= $oldscore}\n            set oldscore $score\n        }\n    }\n\n    proc stressers {encoding} {\n        if {$encoding == \"ziplist\"} {\n            # Little extra to allow proper fuzzing in the sorting stresser\n            r config set zset-max-ziplist-entries 256\n            r config set zset-max-ziplist-value 64\n            set elements 128\n        } elseif {$encoding == \"skiplist\"} {\n            r config set zset-max-ziplist-entries 0\n            r config set zset-max-ziplist-value 0\n            if {$::accurate} {set elements 1000} else {set elements 100}\n        } else {\n            puts \"Unknown sorted set encoding\"\n            exit\n        }\n\n        test \"ZSCORE - $encoding\" {\n            r del zscoretest\n            set aux {}\n            for {set i 0} {$i < $elements} {incr i} {\n                set score [expr rand()]\n                lappend aux $score\n                r zadd zscoretest $score $i\n            }\n\n            assert_encoding $encoding zscoretest\n            for {set i 0} {$i < $elements} {incr i} {\n                assert_equal [lindex $aux $i] [r zscore zscoretest $i]\n            }\n        }\n\n        test \"ZSCORE after a DEBUG RELOAD - $encoding\" {\n            r del zscoretest\n            set aux {}\n            for {set i 0} {$i < $elements} {incr i} {\n                set score [expr rand()]\n                lappend aux $score\n                r zadd zscoretest $score $i\n            }\n\n            r debug reload\n            assert_encoding $encoding zscoretest\n            for {set i 0} {$i < $elements} {incr i} {\n                assert_equal [lindex $aux $i] [r zscore zscoretest $i]\n            }\n        }\n\n        test \"ZSET sorting stresser - $encoding\" {\n            set delta 0\n            for {set test 0} {$test < 2} {incr test} {\n                unset -nocomplain auxarray\n                array set auxarray {}\n                set auxlist {}\n                r del myzset\n                for {set i 0} {$i < $elements} {incr i} {\n                    if {$test == 0} {\n                        set score [expr rand()]\n                    } else {\n                        set score [expr int(rand()*10)]\n                    }\n                    set auxarray($i) $score\n                    r zadd myzset $score $i\n                    # Random update\n                    if {[expr rand()] < .2} {\n                        set j [expr int(rand()*1000)]\n                        if {$test == 0} {\n                            set score [expr rand()]\n                        } else {\n                            set score [expr int(rand()*10)]\n                        }\n                        set auxarray($j) $score\n                        r zadd myzset $score $j\n                    }\n                }\n                foreach {item score} [array get auxarray] {\n                    lappend auxlist [list $score $item]\n                }\n                set sorted [lsort -command zlistAlikeSort $auxlist]\n                set auxlist {}\n                foreach x $sorted {\n                    lappend auxlist [lindex $x 1]\n                }\n\n                assert_encoding $encoding myzset\n                set fromredis [r zrange myzset 0 -1]\n                set delta 0\n                for {set i 0} {$i < [llength $fromredis]} {incr i} {\n                    if {[lindex $fromredis $i] != [lindex $auxlist $i]} {\n                        incr delta\n                    }\n                }\n            }\n            assert_equal 0 $delta\n        }\n\n        test \"ZRANGEBYSCORE fuzzy test, 100 ranges in $elements element sorted set - $encoding\" {\n            set err {}\n            r del zset\n            for {set i 0} {$i < $elements} {incr i} {\n                r zadd zset [expr rand()] $i\n            }\n\n            assert_encoding $encoding zset\n            for {set i 0} {$i < 100} {incr i} {\n                set min [expr rand()]\n                set max [expr rand()]\n                if {$min > $max} {\n                    set aux $min\n                    set min $max\n                    set max $aux\n                }\n                set low [r zrangebyscore zset -inf $min]\n                set ok [r zrangebyscore zset $min $max]\n                set high [r zrangebyscore zset $max +inf]\n                set lowx [r zrangebyscore zset -inf ($min]\n                set okx [r zrangebyscore zset ($min ($max]\n                set highx [r zrangebyscore zset ($max +inf]\n\n                if {[r zcount zset -inf $min] != [llength $low]} {\n                    append err \"Error, len does not match zcount\\n\"\n                }\n                if {[r zcount zset $min $max] != [llength $ok]} {\n                    append err \"Error, len does not match zcount\\n\"\n                }\n                if {[r zcount zset $max +inf] != [llength $high]} {\n                    append err \"Error, len does not match zcount\\n\"\n                }\n                if {[r zcount zset -inf ($min] != [llength $lowx]} {\n                    append err \"Error, len does not match zcount\\n\"\n                }\n                if {[r zcount zset ($min ($max] != [llength $okx]} {\n                    append err \"Error, len does not match zcount\\n\"\n                }\n                if {[r zcount zset ($max +inf] != [llength $highx]} {\n                    append err \"Error, len does not match zcount\\n\"\n                }\n\n                foreach x $low {\n                    set score [r zscore zset $x]\n                    if {$score > $min} {\n                        append err \"Error, score for $x is $score > $min\\n\"\n                    }\n                }\n                foreach x $lowx {\n                    set score [r zscore zset $x]\n                    if {$score >= $min} {\n                        append err \"Error, score for $x is $score >= $min\\n\"\n                    }\n                }\n                foreach x $ok {\n                    set score [r zscore zset $x]\n                    if {$score < $min || $score > $max} {\n                        append err \"Error, score for $x is $score outside $min-$max range\\n\"\n                    }\n                }\n                foreach x $okx {\n                    set score [r zscore zset $x]\n                    if {$score <= $min || $score >= $max} {\n                        append err \"Error, score for $x is $score outside $min-$max open range\\n\"\n                    }\n                }\n                foreach x $high {\n                    set score [r zscore zset $x]\n                    if {$score < $max} {\n                        append err \"Error, score for $x is $score < $max\\n\"\n                    }\n                }\n                foreach x $highx {\n                    set score [r zscore zset $x]\n                    if {$score <= $max} {\n                        append err \"Error, score for $x is $score <= $max\\n\"\n                    }\n                }\n            }\n            assert_equal {} $err\n        }\n\n        test \"ZRANGEBYLEX fuzzy test, 100 ranges in $elements element sorted set - $encoding\" {\n            set lexset {}\n            r del zset\n            for {set j 0} {$j < $elements} {incr j} {\n                set e [randstring 0 30 alpha]\n                lappend lexset $e\n                r zadd zset 0 $e\n            }\n            set lexset [lsort -unique $lexset]\n            for {set j 0} {$j < 100} {incr j} {\n                set min [randstring 0 30 alpha]\n                set max [randstring 0 30 alpha]\n                set mininc [randomInt 2]\n                set maxinc [randomInt 2]\n                if {$mininc} {set cmin \"\\[$min\"} else {set cmin \"($min\"}\n                if {$maxinc} {set cmax \"\\[$max\"} else {set cmax \"($max\"}\n                set rev [randomInt 2]\n                if {$rev} {\n                    set cmd zrevrangebylex\n                } else {\n                    set cmd zrangebylex\n                }\n\n                # Make sure data is the same in both sides\n                assert {[r zrange zset 0 -1] eq $lexset}\n\n                # Get the Redis output\n                set output [r $cmd zset $cmin $cmax]\n                if {$rev} {\n                    set outlen [r zlexcount zset $cmax $cmin]\n                } else {\n                    set outlen [r zlexcount zset $cmin $cmax]\n                }\n\n                # Compute the same output via Tcl\n                set o {}\n                set copy $lexset\n                if {(!$rev && [string compare $min $max] > 0) ||\n                    ($rev && [string compare $max $min] > 0)} {\n                    # Empty output when ranges are inverted.\n                } else {\n                    if {$rev} {\n                        # Invert the Tcl array using Redis itself.\n                        set copy [r zrevrange zset 0 -1]\n                        # Invert min / max as well\n                        lassign [list $min $max $mininc $maxinc] \\\n                            max min maxinc mininc\n                    }\n                    foreach e $copy {\n                        set mincmp [string compare $e $min]\n                        set maxcmp [string compare $e $max]\n                        if {\n                             ($mininc && $mincmp >= 0 || !$mininc && $mincmp > 0)\n                             &&\n                             ($maxinc && $maxcmp <= 0 || !$maxinc && $maxcmp < 0)\n                        } {\n                            lappend o $e\n                        }\n                    }\n                }\n                assert {$o eq $output}\n                assert {$outlen eq [llength $output]}\n            }\n        }\n\n        test \"ZREMRANGEBYLEX fuzzy test, 100 ranges in $elements element sorted set - $encoding\" {\n            set lexset {}\n            r del zset zsetcopy\n            for {set j 0} {$j < $elements} {incr j} {\n                set e [randstring 0 30 alpha]\n                lappend lexset $e\n                r zadd zset 0 $e\n            }\n            set lexset [lsort -unique $lexset]\n            for {set j 0} {$j < 100} {incr j} {\n                # Copy...\n                r zunionstore zsetcopy 1 zset\n                set lexsetcopy $lexset\n\n                set min [randstring 0 30 alpha]\n                set max [randstring 0 30 alpha]\n                set mininc [randomInt 2]\n                set maxinc [randomInt 2]\n                if {$mininc} {set cmin \"\\[$min\"} else {set cmin \"($min\"}\n                if {$maxinc} {set cmax \"\\[$max\"} else {set cmax \"($max\"}\n\n                # Make sure data is the same in both sides\n                assert {[r zrange zset 0 -1] eq $lexset}\n\n                # Get the range we are going to remove\n                set torem [r zrangebylex zset $cmin $cmax]\n                set toremlen [r zlexcount zset $cmin $cmax]\n                r zremrangebylex zsetcopy $cmin $cmax\n                set output [r zrange zsetcopy 0 -1]\n\n                # Remove the range with Tcl from the original list\n                if {$toremlen} {\n                    set first [lsearch -exact $lexsetcopy [lindex $torem 0]]\n                    set last [expr {$first+$toremlen-1}]\n                    set lexsetcopy [lreplace $lexsetcopy $first $last]\n                }\n                assert {$lexsetcopy eq $output}\n            }\n        }\n\n        test \"ZSETs skiplist implementation backlink consistency test - $encoding\" {\n            set diff 0\n            for {set j 0} {$j < $elements} {incr j} {\n                r zadd myzset [expr rand()] \"Element-$j\"\n                r zrem myzset \"Element-[expr int(rand()*$elements)]\"\n            }\n\n            assert_encoding $encoding myzset\n            set l1 [r zrange myzset 0 -1]\n            set l2 [r zrevrange myzset 0 -1]\n            for {set j 0} {$j < [llength $l1]} {incr j} {\n                if {[lindex $l1 $j] ne [lindex $l2 end-$j]} {\n                    incr diff\n                }\n            }\n            assert_equal 0 $diff\n        }\n\n        test \"ZSETs ZRANK augmented skip list stress testing - $encoding\" {\n            set err {}\n            r del myzset\n            for {set k 0} {$k < 2000} {incr k} {\n                set i [expr {$k % $elements}]\n                if {[expr rand()] < .2} {\n                    r zrem myzset $i\n                } else {\n                    set score [expr rand()]\n                    r zadd myzset $score $i\n                    assert_encoding $encoding myzset\n                }\n\n                set card [r zcard myzset]\n                if {$card > 0} {\n                    set index [randomInt $card]\n                    set ele [lindex [r zrange myzset $index $index] 0]\n                    set rank [r zrank myzset $ele]\n                    if {$rank != $index} {\n                        set err \"$ele RANK is wrong! ($rank != $index)\"\n                        break\n                    }\n                }\n            }\n            assert_equal {} $err\n        }\n    }\n\n    tags {\"slow\"} {\n        stressers ziplist\n        stressers skiplist\n    }\n}\n"
  },
  {
    "path": "extern/deprecated/redis-2.8.21/utils/build-static-symbols.tcl",
    "content": "# Build a symbol table for static symbols of redis.c\n# Useful to get stack traces on segfault without a debugger. See redis.c\n# for more information.\n#\n# Copyright(C) 2009 Salvatore Sanfilippo, under the BSD license.\n\nset fd [open redis.c]\nset symlist {}\nwhile {[gets $fd line] != -1} {\n    if {[regexp {^static +[A-z0-9]+[ *]+([A-z0-9]*)\\(} $line - sym]} {\n        lappend symlist $sym\n    }\n}\nset symlist [lsort -unique $symlist]\nputs \"static struct redisFunctionSym symsTable\\[\\] = {\"\nforeach sym $symlist {\n    puts \"{\\\"$sym\\\",(unsigned long)$sym},\"\n}\nputs \"{NULL,0}\"\nputs \"};\"\n\nclose $fd\n"
  },
  {
    "path": "extern/deprecated/redis-2.8.21/utils/generate-command-help.rb",
    "content": "#!/usr/bin/env ruby\n\nGROUPS = [\n  \"generic\",\n  \"string\",\n  \"list\",\n  \"set\",\n  \"sorted_set\",\n  \"hash\",\n  \"pubsub\",\n  \"transactions\",\n  \"connection\",\n  \"server\",\n  \"scripting\",\n  \"hyperloglog\"\n].freeze\n\nGROUPS_BY_NAME = Hash[*\n  GROUPS.each_with_index.map do |n,i|\n    [n,i]\n  end.flatten\n].freeze\n\ndef argument arg\n  name = arg[\"name\"].is_a?(Array) ? arg[\"name\"].join(\" \") : arg[\"name\"]\n  name = arg[\"enum\"].join \"|\" if \"enum\" == arg[\"type\"]\n  name = arg[\"command\"] + \" \" + name if arg[\"command\"]\n  if arg[\"multiple\"]\n    name = \"#{name} [#{name} ...]\"\n  end\n  if arg[\"optional\"]\n    name = \"[#{name}]\"\n  end\n  name\nend\n\ndef arguments command\n  return \"-\" unless command[\"arguments\"]\n  command[\"arguments\"].map do |arg|\n    argument arg\n  end.join \" \"\nend\n\ndef commands\n  return @commands if @commands\n\n  require \"rubygems\"\n  require \"net/http\"\n  require \"net/https\"\n  require \"json\"\n  require \"uri\"\n\n  url = URI.parse \"https://raw.githubusercontent.com/antirez/redis-doc/master/commands.json\"\n  client = Net::HTTP.new url.host, url.port\n  client.use_ssl = true\n  response = client.get url.path\n  if response.is_a?(Net::HTTPSuccess)\n    @commands = JSON.parse(response.body)\n  else\n    response.error!\n  end\nend\n\ndef generate_groups\n  GROUPS.map do |n|\n    \"\\\"#{n}\\\"\"\n  end.join(\",\\n    \");\nend\n\ndef generate_commands\n  commands.to_a.sort do |x,y|\n    x[0] <=> y[0]\n  end.map do |key, command|\n    group = GROUPS_BY_NAME[command[\"group\"]]\n    if group.nil?\n      STDERR.puts \"Please update groups array in #{__FILE__}\"\n      raise \"Unknown group #{command[\"group\"]}\"\n    end\n\n    ret = <<-SPEC\n{ \"#{key}\",\n    \"#{arguments(command)}\",\n    \"#{command[\"summary\"]}\",\n    #{group},\n    \"#{command[\"since\"]}\" }\n    SPEC\n    ret.strip\n  end.join(\",\\n    \")\nend\n\n# Write to stdout\nputs <<-HELP_H\n/* Automatically generated by #{__FILE__}, do not edit. */\n\n#ifndef __REDIS_HELP_H\n#define __REDIS_HELP_H\n\nstatic char *commandGroups[] = {\n    #{generate_groups}\n};\n\nstruct commandHelp {\n  char *name;\n  char *params;\n  char *summary;\n  int group;\n  char *since;\n} commandHelp[] = {\n    #{generate_commands}\n};\n\n#endif\nHELP_H\n\n"
  },
  {
    "path": "extern/deprecated/redis-2.8.21/utils/hyperloglog/.gitignore",
    "content": "*.txt\n"
  },
  {
    "path": "extern/deprecated/redis-2.8.21/utils/hyperloglog/hll-err.rb",
    "content": "# hll-err.rb - Copyright (C) 2014 Salvatore Sanfilippo\n# BSD license, See the COPYING file for more information.\n#\n# Check error of HyperLogLog Redis implementation for different set sizes.\n\nrequire 'rubygems'\nrequire 'redis'\nrequire 'digest/sha1'\n\nr = Redis.new\nr.del('hll')\ni = 0\nwhile true do\n    100.times {\n        elements = []\n        1000.times {\n            ele = Digest::SHA1.hexdigest(i.to_s)\n            elements << ele\n            i += 1\n        }\n        r.pfadd('hll',*elements)\n    }\n    approx = r.pfcount('hll')\n    abs_err = (approx-i).abs\n    rel_err = 100.to_f*abs_err/i\n    puts \"#{i} vs #{approx}: #{rel_err}%\"\nend\n"
  },
  {
    "path": "extern/deprecated/redis-2.8.21/utils/hyperloglog/hll-gnuplot-graph.rb",
    "content": "# hll-err.rb - Copyright (C) 2014 Salvatore Sanfilippo\n# BSD license, See the COPYING file for more information.\n#\n# This program is suited to output average and maximum errors of\n# the Redis HyperLogLog implementation in a format suitable to print\n# graphs using gnuplot.\n\nrequire 'rubygems'\nrequire 'redis'\nrequire 'digest/sha1'\n\n# Generate an array of [cardinality,relative_error] pairs\n# in the 0 - max range, with the specified step.\n#\n# 'r' is the Redis object used to perform the queries.\n# 'seed' must be different every time you want a test performed\n# with a different set. The function guarantees that if 'seed' is the\n# same, exactly the same dataset is used, and when it is different,\n# a totally unrelated different data set is used (without any common\n# element in practice).\ndef run_experiment(r,seed,max,step)\n    r.del('hll')\n    i = 0\n    samples = []\n    step = 1000 if step > 1000\n    while i < max do\n        elements = []\n        step.times {\n            ele = Digest::SHA1.hexdigest(i.to_s+seed.to_s)\n            elements << ele\n            i += 1\n        }\n        r.pfadd('hll',*elements)\n        approx = r.pfcount('hll')\n        err = approx-i\n        rel_err = 100.to_f*err/i\n        samples << [i,rel_err]\n    end\n    samples\nend\n\ndef filter_samples(numsets,max,step,filter)\n    r = Redis.new\n    dataset = {}\n    (0...numsets).each{|i|\n        dataset[i] = run_experiment(r,i,max,step)\n        STDERR.puts \"Set #{i}\"\n    }\n    dataset[0].each_with_index{|ele,index|\n        if filter == :max\n            card=ele[0]\n            err=ele[1].abs\n            (1...numsets).each{|i|\n                err = dataset[i][index][1] if err < dataset[i][index][1]\n            }\n            puts \"#{card} #{err}\"\n        elsif filter == :avg\n            card=ele[0]\n            err = 0\n            (0...numsets).each{|i|\n                err += dataset[i][index][1]\n            }\n            err /= numsets\n            puts \"#{card} #{err}\"\n        elsif filter == :absavg\n            card=ele[0]\n            err = 0\n            (0...numsets).each{|i|\n                err += dataset[i][index][1].abs\n            }\n            err /= numsets\n            puts \"#{card} #{err}\"\n        elsif filter == :all\n            (0...numsets).each{|i|\n                card,err = dataset[i][index]\n                puts \"#{card} #{err}\"\n            }\n        else\n            raise \"Unknown filter #{filter}\"\n        end\n    }\nend\n\nif ARGV.length != 4\n    puts \"Usage: hll-gnuplot-graph <samples> <max> <step> (max|avg|absavg|all)\"\n    exit 1\nend\nfilter_samples(ARGV[0].to_i,ARGV[1].to_i,ARGV[2].to_i,ARGV[3].to_sym)\n"
  },
  {
    "path": "extern/deprecated/redis-2.8.21/utils/install_server.sh",
    "content": "#!/bin/sh\n\n# Copyright 2011 Dvir Volk <dvirsk at gmail dot com>. All rights reserved.\n#\n# Redistribution and use in source and binary forms, with or without\n# modification, are permitted provided that the following conditions are met:\n#\n#   1. Redistributions of source code must retain the above copyright notice,\n#   this list of conditions and the following disclaimer.\n#\n#   2. Redistributions in binary form must reproduce the above copyright\n#   notice, this list of conditions and the following disclaimer in the\n#   documentation and/or other materials provided with the distribution.\n#\n# THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED\n# WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF\n# MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO\n# EVENT SHALL Dvir Volk OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,\n# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\n# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,\n# OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF\n# LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING\n# NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,\n# EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n#\n################################################################################\n#\n# Interactive service installer for redis server\n# this generates a redis config file and an /etc/init.d script, and installs them\n# this scripts should be run as root\n\ndie () {\n\techo \"ERROR: $1. Aborting!\"\n\texit 1\n}\n\n\n#Absolute path to this script\nSCRIPT=$(readlink -f $0)\n#Absolute path this script is in\nSCRIPTPATH=$(dirname $SCRIPT)\n\n#Initial defaults\n_REDIS_PORT=6379\n\necho \"Welcome to the redis service installer\"\necho \"This script will help you easily set up a running redis server\"\necho\n\n#check for root user\nif [ \"$(id -u)\" -ne 0 ] ; then\n\techo \"You must run this script as root. Sorry!\"\n\texit 1\nfi\n\n#Read the redis port\nread  -p \"Please select the redis port for this instance: [$_REDIS_PORT] \" REDIS_PORT\nif ! echo $REDIS_PORT | egrep -q '^[0-9]+$' ; then\n\techo \"Selecting default: $_REDIS_PORT\"\n\tREDIS_PORT=$_REDIS_PORT\nfi\n\n#read the redis config file\n_REDIS_CONFIG_FILE=\"/etc/redis/$REDIS_PORT.conf\"\nread -p \"Please select the redis config file name [$_REDIS_CONFIG_FILE] \" REDIS_CONFIG_FILE\nif [ -z \"$REDIS_CONFIG_FILE\" ] ; then\n\tREDIS_CONFIG_FILE=$_REDIS_CONFIG_FILE\n\techo \"Selected default - $REDIS_CONFIG_FILE\"\nfi\n\n#read the redis log file path\n_REDIS_LOG_FILE=\"/var/log/redis_$REDIS_PORT.log\"\nread -p \"Please select the redis log file name [$_REDIS_LOG_FILE] \" REDIS_LOG_FILE\nif [ -z \"$REDIS_LOG_FILE\" ] ; then\n\tREDIS_LOG_FILE=$_REDIS_LOG_FILE\n\techo \"Selected default - $REDIS_LOG_FILE\"\nfi\n\n\n#get the redis data directory\n_REDIS_DATA_DIR=\"/var/lib/redis/$REDIS_PORT\"\nread -p \"Please select the data directory for this instance [$_REDIS_DATA_DIR] \" REDIS_DATA_DIR\nif [ -z \"$REDIS_DATA_DIR\" ] ; then\n\tREDIS_DATA_DIR=$_REDIS_DATA_DIR\n\techo \"Selected default - $REDIS_DATA_DIR\"\nfi\n\n#get the redis executable path\n_REDIS_EXECUTABLE=`command -v redis-server`\nread -p \"Please select the redis executable path [$_REDIS_EXECUTABLE] \" REDIS_EXECUTABLE\nif [ ! -x \"$REDIS_EXECUTABLE\" ] ; then\n\tREDIS_EXECUTABLE=$_REDIS_EXECUTABLE\n\n\tif [ ! -x \"$REDIS_EXECUTABLE\" ] ; then\n\t\techo \"Mmmmm...  it seems like you don't have a redis executable. Did you run make install yet?\"\n\t\texit 1\n\tfi\nfi\n\n#check the default for redis cli\nCLI_EXEC=`command -v redis-cli`\nif [ -z \"$CLI_EXEC\" ] ; then\n\tCLI_EXEC=`dirname $REDIS_EXECUTABLE`\"/redis-cli\"\nfi\n\necho \"Selected config:\"\n\necho \"Port           : $REDIS_PORT\"\necho \"Config file    : $REDIS_CONFIG_FILE\"\necho \"Log file       : $REDIS_LOG_FILE\"\necho \"Data dir       : $REDIS_DATA_DIR\"\necho \"Executable     : $REDIS_EXECUTABLE\"\necho \"Cli Executable : $CLI_EXEC\"\n\nread -p \"Is this ok? Then press ENTER to go on or Ctrl-C to abort.\" _UNUSED_\n\nmkdir -p `dirname \"$REDIS_CONFIG_FILE\"` || die \"Could not create redis config directory\"\nmkdir -p `dirname \"$REDIS_LOG_FILE\"` || die \"Could not create redis log dir\"\nmkdir -p \"$REDIS_DATA_DIR\" || die \"Could not create redis data directory\"\n\n#render the templates\nTMP_FILE=\"/tmp/${REDIS_PORT}.conf\"\nDEFAULT_CONFIG=\"${SCRIPTPATH}/../redis.conf\"\nINIT_TPL_FILE=\"${SCRIPTPATH}/redis_init_script.tpl\"\nINIT_SCRIPT_DEST=\"/etc/init.d/redis_${REDIS_PORT}\"\nPIDFILE=\"/var/run/redis_${REDIS_PORT}.pid\"\n\nif [ ! -f \"$DEFAULT_CONFIG\" ]; then\n\techo \"Mmmmm... the default config is missing. Did you switch to the utils directory?\"\n\texit 1\nfi\n\n#Generate config file from the default config file as template\n#changing only the stuff we're controlling from this script\necho \"## Generated by install_server.sh ##\" > $TMP_FILE\n\nread -r SED_EXPR <<-EOF\ns#^port [0-9]{4}\\$#port ${REDIS_PORT}#; \\\ns#^logfile .+\\$#logfile ${REDIS_LOG_FILE}#; \\\ns#^dir .+\\$#dir ${REDIS_DATA_DIR}#; \\\ns#^pidfile .+\\$#pidfile ${PIDFILE}#; \\\ns#^daemonize no\\$#daemonize yes#;\nEOF\nsed -r \"$SED_EXPR\" $DEFAULT_CONFIG  >> $TMP_FILE\n\n#cat $TPL_FILE | while read line; do eval \"echo \\\"$line\\\"\" >> $TMP_FILE; done\ncp $TMP_FILE $REDIS_CONFIG_FILE || die \"Could not write redis config file $REDIS_CONFIG_FILE\"\n\n#Generate sample script from template file\nrm -f $TMP_FILE\n\n#we hard code the configs here to avoid issues with templates containing env vars\n#kinda lame but works!\nREDIS_INIT_HEADER=\\\n\"#!/bin/sh\\n\n#Configurations injected by install_server below....\\n\\n\nEXEC=$REDIS_EXECUTABLE\\n\nCLIEXEC=$CLI_EXEC\\n\nPIDFILE=\\\"$PIDFILE\\\"\\n\nCONF=\\\"$REDIS_CONFIG_FILE\\\"\\n\\n\nREDISPORT=\\\"$REDIS_PORT\\\"\\n\\n\n###############\\n\\n\"\n\nREDIS_CHKCONFIG_INFO=\\\n\"# REDHAT chkconfig header\\n\\n\n# chkconfig: - 58 74\\n\n# description: redis_${REDIS_PORT} is the redis daemon.\\n\n### BEGIN INIT INFO\\n\n# Provides: redis_6379\\n\n# Required-Start: \\$network \\$local_fs \\$remote_fs\\n\n# Required-Stop: \\$network \\$local_fs \\$remote_fs\\n\n# Default-Start: 2 3 4 5\\n\n# Default-Stop: 0 1 6\\n\n# Should-Start: \\$syslog \\$named\\n\n# Should-Stop: \\$syslog \\$named\\n\n# Short-Description: start and stop redis_${REDIS_PORT}\\n\n# Description: Redis daemon\\n\n### END INIT INFO\\n\\n\"\n\nif command -v chkconfig >/dev/null; then\n\t#if we're a box with chkconfig on it we want to include info for chkconfig\n\techo \"$REDIS_INIT_HEADER\" \"$REDIS_CHKCONFIG_INFO\" > $TMP_FILE && cat $INIT_TPL_FILE >> $TMP_FILE || die \"Could not write init script to $TMP_FILE\"\nelse\n\t#combine the header and the template (which is actually a static footer)\n\techo \"$REDIS_INIT_HEADER\" > $TMP_FILE && cat $INIT_TPL_FILE >> $TMP_FILE || die \"Could not write init script to $TMP_FILE\"\nfi\n\n###\n# Generate sample script from template file\n# - No need to check which system we are on. The init info are comments and\n#   do not interfere with update_rc.d systems. Additionally:\n#     Ubuntu/debian by default does not come with chkconfig, but does issue a\n#     warning if init info is not available.\n\ncat > ${TMP_FILE} <<EOT\n#!/bin/sh\n#Configurations injected by install_server below....\n\nEXEC=$REDIS_EXECUTABLE\nCLIEXEC=$CLI_EXEC\nPIDFILE=$PIDFILE\nCONF=\"$REDIS_CONFIG_FILE\"\nREDISPORT=\"$REDIS_PORT\"\n###############\n# SysV Init Information\n# chkconfig: - 58 74\n# description: redis_${REDIS_PORT} is the redis daemon.\n### BEGIN INIT INFO\n# Provides: redis_${REDIS_PORT}\n# Required-Start: \\$network \\$local_fs \\$remote_fs\n# Required-Stop: \\$network \\$local_fs \\$remote_fs\n# Default-Start: 2 3 4 5\n# Default-Stop: 0 1 6\n# Should-Start: \\$syslog \\$named\n# Should-Stop: \\$syslog \\$named\n# Short-Description: start and stop redis_${REDIS_PORT}\n# Description: Redis daemon\n### END INIT INFO\n\nEOT\ncat ${INIT_TPL_FILE} >> ${TMP_FILE}\n\n#copy to /etc/init.d\ncp $TMP_FILE $INIT_SCRIPT_DEST && \\\n\tchmod +x $INIT_SCRIPT_DEST || die \"Could not copy redis init script to  $INIT_SCRIPT_DEST\"\necho \"Copied $TMP_FILE => $INIT_SCRIPT_DEST\"\n\n#Install the service\necho \"Installing service...\"\nif command -v chkconfig >/dev/null 2>&1; then\n\t# we're chkconfig, so lets add to chkconfig and put in runlevel 345\n\tchkconfig --add redis_${REDIS_PORT} && echo \"Successfully added to chkconfig!\"\n\tchkconfig --level 345 redis_${REDIS_PORT} on && echo \"Successfully added to runlevels 345!\"\nelif command -v update-rc.d >/dev/null 2>&1; then\n\t#if we're not a chkconfig box assume we're able to use update-rc.d\n\tupdate-rc.d redis_${REDIS_PORT} defaults && echo \"Success!\"\nelse\n\techo \"No supported init tool found.\"\nfi\n\n/etc/init.d/redis_$REDIS_PORT start || die \"Failed starting service...\"\n\n#tada\necho \"Installation successful!\"\nexit 0\n"
  },
  {
    "path": "extern/deprecated/redis-2.8.21/utils/mkrelease.sh",
    "content": "#!/bin/sh\nif [ $# != \"1\" ]\nthen\n    echo \"Usage: ./mkrelease.sh <git-ref>\"\n    exit 1\nfi\n\nTAG=$1\nTARNAME=\"redis-${TAG}.tar\"\necho \"Generating /tmp/${TARNAME}\"\ngit archive $TAG --prefix redis-${TAG}/ > /tmp/$TARNAME || exit 1\necho \"Gizipping the archive\"\nrm -f /tmp/$TARNAME.gz\ngzip -9 /tmp/$TARNAME\n"
  },
  {
    "path": "extern/deprecated/redis-2.8.21/utils/redis-copy.rb",
    "content": "# redis-copy.rb - Copyright (C) 2009-2010 Salvatore Sanfilippo\n# BSD license, See the COPYING file for more information.\n#\n# Copy the whole dataset from one Redis instance to another one\n#\n# WARNING: this utility is deprecated and serves as a legacy adapter\n#          for the more-robust redis-copy gem.\n\nrequire 'shellwords'\n\ndef redisCopy(opts={})\n  src = \"#{opts[:srchost]}:#{opts[:srcport]}\"\n  dst = \"#{opts[:dsthost]}:#{opts[:dstport]}\"\n  `redis-copy #{src.shellescape} #{dst.shellescape}`\nrescue Errno::ENOENT\n  $stderr.puts 'This utility requires the redis-copy executable',\n               'from the redis-copy gem on https://rubygems.org',\n               'To install it, run `gem install redis-copy`.'\n  exit 1\nend\n\n$stderr.puts \"This utility is deprecated. Use the redis-copy gem instead.\"\nif ARGV.length != 4\n    puts \"Usage: redis-copy.rb <srchost> <srcport> <dsthost> <dstport>\"\n    exit 1\nend\nputs \"WARNING: it's up to you to FLUSHDB the destination host before to continue, press any key when ready.\"\nSTDIN.gets\nsrchost = ARGV[0]\nsrcport = ARGV[1]\ndsthost = ARGV[2]\ndstport = ARGV[3]\nputs \"Copying #{srchost}:#{srcport} into #{dsthost}:#{dstport}\"\nredisCopy(:srchost => srchost, :srcport => srcport.to_i,\n          :dsthost => dsthost, :dstport => dstport.to_i)\n"
  },
  {
    "path": "extern/deprecated/redis-2.8.21/utils/redis-sha1.rb",
    "content": "# redis-sha1.rb - Copyright (C) 2009 Salvatore Sanfilippo\n# BSD license, See the COPYING file for more information.\n#\n# Performs the SHA1 sum of the whole datset.\n# This is useful to spot bugs in persistence related code and to make sure\n# Slaves and Masters are in SYNC.\n#\n# If you hack this code make sure to sort keys and set elements as this are\n# unsorted elements. Otherwise the sum may differ with equal dataset.\n\nrequire 'rubygems'\nrequire 'redis'\nrequire 'digest/sha1'\n\ndef redisSha1(opts={})\n    sha1=\"\"\n    r = Redis.new(opts)\n    r.keys('*').sort.each{|k|\n        vtype = r.type?(k)\n        if vtype == \"string\"\n            len = 1\n            sha1 = Digest::SHA1.hexdigest(sha1+k)\n            sha1 = Digest::SHA1.hexdigest(sha1+r.get(k))\n        elsif vtype == \"list\"\n            len = r.llen(k)\n            if len != 0\n                sha1 = Digest::SHA1.hexdigest(sha1+k)\n                sha1 = Digest::SHA1.hexdigest(sha1+r.list_range(k,0,-1).join(\"\\x01\"))\n            end\n        elsif vtype == \"set\"\n            len = r.scard(k)\n            if len != 0\n                sha1 = Digest::SHA1.hexdigest(sha1+k)\n                sha1 = Digest::SHA1.hexdigest(sha1+r.set_members(k).to_a.sort.join(\"\\x02\"))\n            end\n        elsif vtype == \"zset\"\n            len = r.zcard(k)\n            if len != 0\n                sha1 = Digest::SHA1.hexdigest(sha1+k)\n                sha1 = Digest::SHA1.hexdigest(sha1+r.zrange(k,0,-1).join(\"\\x01\"))\n            end\n        end\n        # puts \"#{k} => #{sha1}\" if len != 0\n    }\n    sha1\nend\n\nhost = ARGV[0] || \"127.0.0.1\"\nport = ARGV[1] || \"6379\"\ndb = ARGV[2] || \"0\"\nputs \"Performing SHA1 of Redis server #{host} #{port} DB: #{db}\"\np \"Dataset SHA1: #{redisSha1(:host => host, :port => port.to_i, :db => db)}\"\n"
  },
  {
    "path": "extern/deprecated/redis-2.8.21/utils/redis_init_script",
    "content": "#!/bin/sh\n#\n# Simple Redis init.d script conceived to work on Linux systems\n# as it does use of the /proc filesystem.\n\nREDISPORT=6379\nEXEC=/usr/local/bin/redis-server\nCLIEXEC=/usr/local/bin/redis-cli\n\nPIDFILE=/var/run/redis_${REDISPORT}.pid\nCONF=\"/etc/redis/${REDISPORT}.conf\"\n\ncase \"$1\" in\n    start)\n        if [ -f $PIDFILE ]\n        then\n                echo \"$PIDFILE exists, process is already running or crashed\"\n        else\n                echo \"Starting Redis server...\"\n                $EXEC $CONF\n        fi\n        ;;\n    stop)\n        if [ ! -f $PIDFILE ]\n        then\n                echo \"$PIDFILE does not exist, process is not running\"\n        else\n                PID=$(cat $PIDFILE)\n                echo \"Stopping ...\"\n                $CLIEXEC -p $REDISPORT shutdown\n                while [ -x /proc/${PID} ]\n                do\n                    echo \"Waiting for Redis to shutdown ...\"\n                    sleep 1\n                done\n                echo \"Redis stopped\"\n        fi\n        ;;\n    *)\n        echo \"Please use start or stop as first argument\"\n        ;;\nesac\n"
  },
  {
    "path": "extern/deprecated/redis-2.8.21/utils/redis_init_script.tpl",
    "content": "\ncase \"$1\" in\n    start)\n        if [ -f $PIDFILE ]\n        then\n            echo \"$PIDFILE exists, process is already running or crashed\"\n        else\n            echo \"Starting Redis server...\"\n            $EXEC $CONF\n        fi\n        ;;\n    stop)\n        if [ ! -f $PIDFILE ]\n        then\n            echo \"$PIDFILE does not exist, process is not running\"\n        else\n            PID=$(cat $PIDFILE)\n            echo \"Stopping ...\"\n            $CLIEXEC -p $REDISPORT shutdown\n            while [ -x /proc/${PID} ]\n            do\n                echo \"Waiting for Redis to shutdown ...\"\n                sleep 1\n            done\n            echo \"Redis stopped\"\n        fi\n        ;;\n    status)\n        PID=$(cat $PIDFILE)\n        if [ ! -x /proc/${PID} ]\n        then\n            echo 'Redis is not running'\n        else\n            echo \"Redis is running ($PID)\"\n        fi\n        ;;\n    restart)\n        $0 stop\n        $0 start\n        ;;\n    *)\n        echo \"Please use start, stop, restart or status as first argument\"\n        ;;\nesac\n"
  },
  {
    "path": "extern/deprecated/redis-2.8.21/utils/speed-regression.tcl",
    "content": "#!/usr/bin/env tclsh8.5\n# Copyright (C) 2011 Salvatore Sanfilippo\n# Released under the BSD license like Redis itself\n\nsource ../tests/support/redis.tcl\nset ::port 12123\nset ::tests {PING,SET,GET,INCR,LPUSH,LPOP,SADD,SPOP,LRANGE_100,LRANGE_600,MSET}\nset ::datasize 16\nset ::requests 100000\n\nproc run-tests branches {\n    set runs {}\n    set branch_id 0\n    foreach b $branches {\n        cd ../src\n        puts \"Benchmarking $b\"\n        exec -ignorestderr git checkout $b 2> /dev/null\n        exec -ignorestderr make clean 2> /dev/null\n        puts \"  compiling...\"\n        exec -ignorestderr make 2> /dev/null\n\n        if {$branch_id == 0} {\n            puts \"  copy redis-benchmark from unstable to /tmp...\"\n            exec -ignorestderr cp ./redis-benchmark /tmp\n            incr branch_id\n            continue\n        }\n\n        # Start the Redis server\n        puts \"  starting the server... [exec ./redis-server -v]\"\n        set pids [exec echo \"port $::port\\nloglevel warning\\n\" | ./redis-server - > /dev/null 2> /dev/null &]\n        puts \"  pids: $pids\"\n        after 1000\n        puts \"  running the benchmark\"\n\n        set r [redis 127.0.0.1 $::port]\n        set i [$r info]\n        puts \"  redis INFO shows version: [lindex [split $i] 0]\"\n        $r close\n\n        set output [exec /tmp/redis-benchmark -n $::requests -t $::tests -d $::datasize --csv -p $::port]\n        lappend runs $b $output\n        puts \"  killing server...\"\n        catch {exec kill -9 [lindex $pids 0]}\n        catch {exec kill -9 [lindex $pids 1]}\n        incr branch_id\n    }\n    return $runs\n}\n\nproc get-result-with-name {output name} {\n    foreach line [split $output \"\\n\"] {\n        lassign [split $line \",\"] key value\n        set key [string tolower [string range $key 1 end-1]]\n        set value [string range $value 1 end-1]\n        if {$key eq [string tolower $name]} {\n            return $value\n        }\n    }\n    return \"n/a\"\n}\n\nproc get-test-names output {\n    set names {}\n    foreach line [split $output \"\\n\"] {\n        lassign [split $line \",\"] key value\n        set key [string tolower [string range $key 1 end-1]]\n        lappend names $key\n    }\n    return $names\n}\n\nproc combine-results {results} {\n    set tests [get-test-names [lindex $results 1]]\n    foreach test $tests {\n        puts $test\n        foreach {branch output} $results {\n            puts [format \"%-20s %s\" \\\n                $branch [get-result-with-name $output $test]]\n        }\n        puts {}\n    }\n}\n\nproc main {} {\n    # Note: the first branch is only used in order to get the redis-benchmark\n    # executable. Tests are performed starting from the second branch.\n    set branches {\n        slowset 2.2.0 2.4.0 unstable slowset\n    }\n    set results [run-tests $branches]\n    puts \"\\n\"\n    puts \"# Test results: datasize=$::datasize requests=$::requests\"\n    puts [combine-results $results]\n}\n\n# Force the user to run the script from the 'utils' directory.\nif {![file exists speed-regression.tcl]} {\n    puts \"Please make sure to run speed-regression.tcl while inside /utils.\"\n    puts \"Example: cd utils; ./speed-regression.tcl\"\n    exit 1\n}\n\n# Make sure there is not already a server runnign on port 12123\nset is_not_running [catch {set r [redis 127.0.0.1 $::port]}]\nif {!$is_not_running} {\n    puts \"Sorry, you have a running server on port $::port\"\n    exit 1\n}\n\n# parse arguments\nfor {set j 0} {$j < [llength $argv]} {incr j} {\n    set opt [lindex $argv $j]\n    set arg [lindex $argv [expr $j+1]]\n    if {$opt eq {--tests}} {\n        set ::tests $arg\n        incr j\n    } elseif {$opt eq {--datasize}} {\n        set ::datasize $arg\n        incr j\n    } elseif {$opt eq {--requests}} {\n        set ::requests $arg\n        incr j\n    } else {\n        puts \"Wrong argument: $opt\"\n        exit 1\n    }\n}\n\nmain\n"
  },
  {
    "path": "extern/deprecated/redis-2.8.21/utils/whatisdoing.sh",
    "content": "# This script is from http://poormansprofiler.org/\n#\n# NOTE: Instead of using this script, you should use the Redis\n# Software Watchdog, which provides a similar functionality but in\n# a more reliable / easy to use way.\n#\n# Check http://redis.io/topics/latency for more information.\n\n#!/bin/bash\nnsamples=1\nsleeptime=0\npid=$(ps auxww | grep '[r]edis-server' | awk '{print $2}')\n\nfor x in $(seq 1 $nsamples)\n  do\n    gdb -ex \"set pagination 0\" -ex \"thread apply all bt\" -batch -p $pid\n    sleep $sleeptime\n  done | \\\nawk '\n  BEGIN { s = \"\"; } \n  /Thread/ { print s; s = \"\"; } \n  /^\\#/ { if (s != \"\" ) { s = s \",\" $4} else { s = $4 } } \n  END { print s }' | \\\nsort | uniq -c | sort -r -n -k 1,1\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/.gitignore",
    "content": ".*.swp\n*.o\n*.log\ndump.rdb\nredis-benchmark\nredis-check-aof\nredis-check-rdb\nredis-check-dump\nredis-cli\nredis-sentinel\nredis-server\ndoc-tools\nrelease\nmisc/*\nsrc/release.h\nappendonly.aof\nSHORT_TERM_TODO\nrelease.h\nsrc/transfer.sh\nsrc/configs\nredis.ds\nsrc/redis.conf\nsrc/nodes.conf\ndeps/lua/src/lua\ndeps/lua/src/luac\ndeps/lua/src/liblua.a\n.make-*\n.prerequisites\n*.dSYM\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/00-RELEASENOTES",
    "content": "Redis 3.2 release notes\n=======================\n\n--------------------------------------------------------------------------------\nUpgrade urgency levels:\n\nLOW:      No need to upgrade unless there are new features you want to use.\nMODERATE: Program an upgrade of the server, but it's not urgent.\nHIGH:     There is a critical bug that may affect a subset of users. Upgrade!\nCRITICAL: There is a critical bug affecting MOST USERS. Upgrade ASAP.\n--------------------------------------------------------------------------------\n\n================================================================================\nRedis 3.2.4     Released Mon Sep 26 08:58:21 CEST 2016\n================================================================================\n\nUpgrade urgency CRITICAL: Redis 3.2 and unstable contained a security\n                          vulnerability fixed by this release.\n\nHello Redis Wizards of the Memory Stores Empire,\n\nthis is a Redis critical release in order to fix a security issue\nwhich is documented clearly here:\n\n    https://github.com/antirez/redis/commit/6d9f8e2462fc2c426d48c941edeb78e5df7d2977\n\nThanks to Cory Duplantis of Cisco Talos for reporting the issue.\n\nThe gist is that using CONFIG SET calls (or by manipulating redis.conf)\nan attacker is able to compromise certain fields of the \"server\" global\nstructure, including the aof filename pointer, that could be made pointing\nto something else. In turn the AOF name is used in different contexts such\nas logging, rename(2) and open(2) syscalls, leading to potential problems.\n\nAll Redis 3.2.x versions are affected.\n\nThis release also includes other things:\n\n* TCP binding bug fixed when only certain addresses were available for\na given port.\n\n* A much better crash report that includes part of the Redis binary:\nthis will allow to fix bugs even when we just have a crash log and\nno other help from the original poster oft the issue.\n\n* A fix for Redis Cluster redis-trib displaying of info after creating\na new cluster.\n\nPlease check the following list of commits for credits about who did what.\nThanks to all the contributors and a special thank to Oran Agra for the\nhelp in this release.\n\nList of commits:\n\nantirez in commit 0539634:\n Security: CONFIG SET client-output-buffer-limit overflow fixed.\n 1 file changed, 5 insertions(+), 3 deletions(-)\n\nantirez in commit c01abcd:\n fix the fix for the TCP binding.\n 1 file changed, 15 insertions(+), 10 deletions(-)\n\noranagra in commit a6d0698:\n fix tcp binding when IPv6 is unsupported\n 2 files changed, 14 insertions(+), 10 deletions(-)\n\nantirez in commit 22b6c28:\n debug.c: no need to define _GNU_SOURCE, is defined in fmacros.h.\n 1 file changed, 1 deletion(-)\n\nantirez in commit 9e9d398:\n crash log - improve code dump with more info and called symbols.\n 1 file changed, 59 insertions(+), 20 deletions(-)\n\noranagra in commit 3745c5d:\n crash log - add hex dump of function code\n 1 file changed, 22 insertions(+)\n\nantirez in commit c1cc07b:\n Sentinel example config: warn about protected mode.\n 1 file changed, 16 insertions(+), 1 deletion(-)\n\nrojingeorge in commit 011dc9f:\n Display the nodes summary once the cluster is established using redis-trib.rb\n 1 file changed, 5 insertions(+)\n\nGuo Xiao in commit f4e3a94:\n Use the standard predefined identifier __func__ (since C99)\n 1 file changed, 1 insertion(+), 1 deletion(-)\n\n================================================================================\nRedis 3.2.3     Released Tue Aug 02 10:55:24 CEST 2016\n================================================================================\n\nUpgrade urgency MODERATE: Fix replication delay and redis-cli security issue.\n\nHello,\n\nthis is a minor release of Redis addressing two bugs:\n\n1. There was an inverted if statement logic problem in replication.c causing\n   a replication delay. This is not an actual problem since things work\n   as expected, but worth to fix ASAP anyway.\n\n2. Redis-cli created the history file with insecure permissions, allowing\n   reding from the file. This was actually a bug in linenoise which is\n   now fixed. The applied fix is from Chris Lamb.\n\nList of commits:\n\nQu Chen in commit e67ad1d:\n Fix a bug to delay bgsave while AOF rewrite in progress for replication\n 1 file changed, 1 insertion(+), 1 deletion(-)\n\nantirez in commit 7153668:\n Update linenoise to fix insecure redis-cli history file creation.\n 1 file changed, 6 insertions(+), 1 deletion(-)\n\n================================================================================\nRedis 3.2.2     Released Thu Jul 28 14:14:54 CEST 2016\n================================================================================\n\nUpgrade urgency MODERATE: A Redis server and a Sentinel crash are now fixed.\n                          GEORADIUS errors in reported entries are fixed.\n\nHi all! Redis 3.2.2 is finally out with non trivial bugfixes and a few new\nfeatures. Let's start from the bugs:\n\n1. There was a bug in the List type implementation, able to cause the\n   crash of the server under certain (non trivial to replicate) circumstances\n   when the LSET command was used. Now the bug is fixed and a new stress tester\n   that was able to easily trigger the bug was added to the test suite.\n\n2. Redis Sentinel, when monitoring multiple masters, could crash after\n   a Sentinel address update event.\n\n3. Redis Sentinel now checks slaves INFO state more often when disconnected.\n   This is not really a bug fix, but may allow to more easily detect that\n   a slave is able to fail over its master reducing certain delays.\n\n4. It was possible, under a variety of conditions, that the AOF and RDB children\n   process could spawn at the same time. This is known to trash disk I/O,\n   AOF performances, and to ultimately create latency in the Redis server.\n   Normally Redis avoids to have the two writing children at the same time, but\n   there were edge cases discovered by Oran Agra (that also co-authored the\n   fix with me) where the double-fork could happen. In order to fix this bug\n   non trivial changes to the replication code were operated, however it was\n   important to back port this fix into 3.2.2 because the bug could lead to\n   bad latency experiences in certain cases.\n\n5. Many GEORADIUS bugs are now fixed \\o/. This started as a failing CI\n   test. I grepped for more clues and there were a number of random failures\n   in the points reported by GEORADIUS. The errors were found to be related\n   to three different bugs (one of these was a bug in the test itself).\n   It's not a critical bug: the effect is to, sometimes, don't report objects\n   that are near the radius, but only with specific sets of coordinates\n   and radius settings. However now the issues are fixed and the error\n   vectors were added as regression tests.\n\nAnd now the good news (not that bug fixes are not good...), that is, the\nnew features!\n\n1. Now slaves support the slave-announce-ip and slave-announce-port options.\n   Using these features a slave can be reported by the master `INFO` output\n   and `ROLE` command as having arbitrary IP and port. This allows to have\n   Sentinel deployments when working with containers or NAT-ed environments\n   more easily.\n\n2. The RDB check utlity is now part of Redis and uses the same RDB code that\n   Redis uses in order to load the dataset in memory, so a given version\n   of Redis is always able to check the RDB it produced... without another\n   external check tool which is supposed to be taken in sync with the\n   rdb.c implementation. This in turn also means that the new RDB checking\n   is able to spot more complex bugs, since it really loads the dataset\n   instead of just skipping bytes.\n\nAbout the redis-check-dump utility, now it is also able to show certain\ninformation about the RDB file, like the version that produced it, when\nit was produced, and so forth. Example:\n\n    ./redis-check-rdb dump.rdb\n    [offset 0] Checking RDB file dump.rdb\n    [offset 32] AUX FIELD redis-ver = '3.2.2'\n    [offset 46] AUX FIELD redis-bits = '64'\n    [offset 58] AUX FIELD ctime = '1469710178'\n    [offset 73] AUX FIELD used-mem = '1186528'\n\nThe ability to check how much memory was used by the instance that produced\nthe RDB file can be especially useful.\n\nFor credits and the full change log, see the list of commits below, that was\nmodified in order to be a bit less verbose compared to the last releases.\n\nEnjoy!\nSalvatore\n\nantirez in commit 0a45fbc:\n Ability of slave to announce arbitrary ip/port to master.\n 6 files changed, 129 insertions(+), 17 deletions(-)\n\nantirez in commit c3982c0:\n redis-benchmark: new option to show server errors on stdout.\n 1 file changed, 17 insertions(+), 1 deletion(-)\n\nantirez in commit fdafe23:\n Multiple GEORADIUS bugs fixed.\n 6 files changed, 177 insertions(+), 21 deletions(-)\n\nantirez in commit a1bfe22:\n Replication: when possible start RDB saving ASAP.\n 1 file changed, 8 insertions(+), 2 deletions(-)\n\nantirez in commit 7ca69af:\n Sentinel: new test unit 07 that tests master down conditions.\n 1 file changed, 68 insertions(+)\n\nantirez in commit 5b5e652:\n Sentinel: check Slave INFO state more often when disconnected.\n 2 files changed, 10 insertions(+), 3 deletions(-)\n\nantirez in commit 21cffc2:\n Avoid simultaneous RDB and AOF child process.\n 4 files changed, 51 insertions(+), 8 deletions(-)\n\nantirez in commit 017378e:\n Replication: start BGSAVE for replication always in replicationCron().\n 1 file changed, 15 insertions(+), 12 deletions(-)\n\nantirez in commit 940be9a:\n Regression test for issue #3333.\n 1 file changed, 6 insertions(+)\n\nantirez in commit 21736b4:\n getLongLongFromObject: use string2ll() instead of strict_strtoll().\n 1 file changed, 1 insertion(+), 6 deletions(-)\n\nantirez in commit 0b748e9:\n redis-cli: check SELECT reply type just in state updated.\n 1 file changed, 1 insertion(+), 1 deletion(-)\n\nsskorgal in commit 1158386:\n Fix for redis_cli printing default DB when select command fails.\n 1 file changed, 1 insertion(+), 1 deletion(-)\n\nantirez in commit 026f9fc:\n Sentinel: fix cross-master Sentinel address update.\n 1 file changed, 9 insertions(+), 2 deletions(-)\n\nantirez in commit 11523b3:\n CONFIG GET is now no longer case sensitive.\n 1 file changed, 12 insertions(+), 12 deletions(-)\n\nantirez in commit f5a7f4f:\n Fix test for new RDB checksum failure message.\n 1 file changed, 1 insertion(+), 1 deletion(-)\n\nantirez in commit 4c6ff74:\n Make tcp-keepalive default to 300 in internal conf.\n 1 file changed, 1 insertion(+), 1 deletion(-)\n\nantirez in commit 27dbec2:\n In Redis RDB check: more details in error reportings.\n 1 file changed, 24 insertions(+), 13 deletions(-)\n\nantirez in commit 41f3004:\n In Redis RDB check: log decompression errors.\n 2 files changed, 23 insertions(+), 2 deletions(-)\n\nantirez in commit 278fe3e:\n In Redis RDB check: log object type on error.\n 1 file changed, 27 insertions(+), 2 deletions(-)\n\nantirez in commit a117dfa:\n Added a trivial program to randomly corrupt RDB files in /utils.\n 1 file changed, 44 insertions(+)\n\nantirez in commit f5110c3:\n In Redis RDB check: minor output message changes.\n 1 file changed, 4 insertions(+), 1 deletion(-)\n\nantirez in commit 35b18bf:\n In Redis RDB check: better error reporting.\n 4 files changed, 71 insertions(+), 14 deletions(-)\n\nantirez in commit f578f08:\n In Redis RDB check: initial POC.\n 2 files changed, 189 insertions(+), 647 deletions(-)\n\ntielei in commit 7f1e1ca:\n A string with 21 chars is not representable as a 64-bit integer.\n 1 file changed, 2 insertions(+), 2 deletions(-)\n\nantirez in commit 7a3a595:\n Test: new randomized stress tester for #3343 alike bugs.\n 1 file changed, 27 insertions(+), 2 deletions(-)\n\nantirez in commit c75ca10:\n Stress tester WIP.\n 1 file changed, 3 insertions(+)\n\nantirez in commit 2c3fcf8:\n Regression test for issue #3343 exact min crash sequence.\n 1 file changed, 16 insertions(+)\n\nantirez in commit 7041967:\n Fix quicklistReplaceAtIndex() by updating the quicklist ziplist size.\n 1 file changed, 1 insertion(+)\n\n================================================================================\nRedis 3.2.1     Released Fri Jun 17 15:01:56 CEST 2016\n================================================================================\n\nUpgrade urgency HIGH: Critical fix to Redis Sentinel, due to 3.2.0 regression\n                      compared to 3.0.\n\nHey, this is Redis 3.2.1, and this release should bring some grain of\nmaturity to Redis 3.2. The list of commits following this note will tell\nyou the details, but the main things addressed in this release are the\nfollowing:\n\n1. A critical bug in Sentinel was hopefully fixed. During the big 3.2\n   refactoring of Redis Sentinel, in order to implement connection sharing\n   to make Sentinel able to scale better (few Sentinels to monitor many\n   masters), a bug was introduced that mis-counted the number of pending\n   commands in the Redis link. This in turn resulted into an inability to talk\n   with certain Redis instances. A common result of this bug was the inability\n   of Redis Sentinel to reconfigure back the old master, after a failover,\n   when it is reachable again, as the slave of the new master. This was due\n   to the inability to talk with the old master at all.\n\n2. BITFIELD bugs fixed.\n\n3. GEO commands fixes on syntax errors and edge cases.\n\n4. RESTORE now accepts dumps generated by older Redis versions.\n\n5. Jemalloc now is really configured to save you memory, for a problem a\n   change in the jemalloc configuration did not really survived when the\n   3.2.0 release was finalized.\n\n6. TTL and TYPE command no longer alter the last access time of a key, for\n   LRU evictions purposes. A new TOUCH command was introduced *just* to\n   update the access time of a key.\n\n7. A bug was fixed in redis-cli, that connected to the instance running on the\n   port 6379 if there was one, regardless of what was specified.\n\n8. TCP keep alive is now enabled by default. This should fix most ghost\n   connections problems without resulting in any practical change in otherwise\n   sane deployments.\n\n9. A Sentinel crash that could happen during failovers was fixed.\n\nAnd of course, more minor things that you can read in the detailed log\nbelow. There are still reported bugs for 3.2 that were not fixed in this\nrelease, but nothing critical AFAIK, and I wanted to release this one ASAP,\nso likely a new release will not be too far.\n\nEnjoy,\nSalvatore\n\n+-------------------------------------------------------------------------------\n| config set list-max-ziplist-size didn't support negative values, unlike config file\n| By oranagra, 2016-05-22 20:35:14 +0300\n+--------------------------------------------------------------------------------\nhttps://github.com/antirez/redis/commit/8207e828043e37a0d7e058530d2886bb3ff395ff\n\n\n src/config.c | 6 +++---\n 1 file changed, 3 insertions(+), 3 deletions(-)\n\n+-------------------------------------------------------------------------------\n| Fix Sentinel pending commands counting.\n| By antirez, 2016-06-16 19:24:34 +0200\n+--------------------------------------------------------------------------------\nhttps://github.com/antirez/redis/commit/6ad0371c9b4206a7a6692d50c9a301457baf9b6d\n\nThis bug most experienced effect was an inability of Redis to\nreconfigure back old masters to slaves after they are reachable again\nafter a failover. This was due to failing to reset the count of the\npending commands properly, so the master appeared fovever down.\n\nWas introduced in Redis 3.2 new Sentinel connection sharing feature\nwhich is a lot more complex than the 3.0 code, but more scalable.\n\nMany thanks to people reporting the issue, and especially to\n@sskorgal for investigating the issue in depth.\n\nHopefully closes #3285.\n\n src/sentinel.c | 1 +\n 1 file changed, 1 insertion(+)\n\n+-------------------------------------------------------------------------------\n| redis-cli: really connect to the right server.\n| By antirez, 2016-06-16 17:23:31 +0200\n+--------------------------------------------------------------------------------\nhttps://github.com/antirez/redis/commit/58f1d446c35e8fe62df7c9ebe10f3c40a386c022\n\nI recently introduced populating the autocomplete help array with the\nCOMMAND command if available. However this was performed before parsing\nthe arguments, defaulting to instance 6379. After the connection is\nperformed it remains stable.\n\nThe effect is that if there is an instance running on port 6339,\nwhatever port you specify is ignored and 6379 is connected to instead.\nThe right port will be selected only after a reconnection.\n\nClose #3314.\n\n src/redis-cli.c | 7 +++++--\n 1 file changed, 5 insertions(+), 2 deletions(-)\n\n+-------------------------------------------------------------------------------\n| Remove debug printing\n| By Jan-Erik Rediger, 2016-05-21 13:50:01 +0200\n+--------------------------------------------------------------------------------\nhttps://github.com/antirez/redis/commit/b6007b324b81dbd4ffe519b3bdb19ab65fbb407f\n\n\n src/redis-cli.c | 3 ---\n 1 file changed, 3 deletions(-)\n\n+-------------------------------------------------------------------------------\n| RESTORE: accept RDB dumps with older versions.\n| By antirez, 2016-06-16 15:53:57 +0200\n+--------------------------------------------------------------------------------\nhttps://github.com/antirez/redis/commit/f592b4d3178963878084a522b4fd050772c335ae\n\nReference issue #3218.\n\nChecking the code I can't find a reason why the original RESTORE\ncode was so opinionated about restoring only the current version. The\ncode in to `rdb.c` appears to be capable as always to restore data from\nolder versions of Redis, and the only places where it is needed the\ncurrent version in order to correctly restore data, is while loading the\nopcodes, not the values itself as it happens in the case of RESTORE.\n\nFor the above reasons, this commit enables RESTORE to accept older\nversions of values payloads.\n\n src/cluster.c | 2 +-\n 1 file changed, 1 insertion(+), 1 deletion(-)\n\n+-------------------------------------------------------------------------------\n| CLIENT error message was out of date\n| By oranagra, 2016-05-23 11:42:21 +0300\n+--------------------------------------------------------------------------------\nhttps://github.com/antirez/redis/commit/047ced4473ee35485e22e45db8b8b4a272bf1177\n\n\n src/networking.c | 2 +-\n 1 file changed, 1 insertion(+), 1 deletion(-)\n\n+-------------------------------------------------------------------------------\n| fix georadius returns multiple replies\n| By oranagra, 2016-05-23 13:58:50 +0300\n+--------------------------------------------------------------------------------\nhttps://github.com/antirez/redis/commit/14e04847ac2960aefe31dccbec63d2503cf09ca5\n\n\n src/geo.c | 7 +++++--\n 1 file changed, 5 insertions(+), 2 deletions(-)\n\n+-------------------------------------------------------------------------------\n| Minor aesthetic fixes to PR #3264.\n| By antirez, 2016-06-16 12:54:33 +0200\n+--------------------------------------------------------------------------------\nhttps://github.com/antirez/redis/commit/bd23ea3f9f3defbbdf512864ee1a88fd02665a7f\n\nComment format fixed + local var modified from camel case to underscore\nseparators as Redis code base normally does (camel case is mostly used\nfor global symbols like structure names, function names, global vars,\n...).\n\n src/bitops.c | 10 +++++-----\n 1 file changed, 5 insertions(+), 5 deletions(-)\n\n+-------------------------------------------------------------------------------\n| check WRONGTYPE in BITFIELD before looping on the operations.\n| By oranagra, 2016-05-24 23:31:36 +0300\n+--------------------------------------------------------------------------------\nhttps://github.com/antirez/redis/commit/2a3ee58ec73b6abdeeb4890937b25191119bce35\n\noptimization: lookup key only once, and grow at once to the max need\nfixes #3259 and #3221, and also an early return if wrongtype is discovered by SET\n\n src/bitops.c | 27 ++++++++++++++++++---------\n 1 file changed, 18 insertions(+), 9 deletions(-)\n\n+-------------------------------------------------------------------------------\n| fix crash in BITFIELD GET on non existing key or wrong type see #3259\n| By oranagra, 2016-05-24 14:52:43 +0300\n+--------------------------------------------------------------------------------\nhttps://github.com/antirez/redis/commit/a2e27b810edfad18b3ecc9c176a4606f94a2f0e4\n\nthis was a bug in the recent refactoring: bee963c4459223d874e3294a0d8638a588d33c8e\n\n src/bitops.c | 8 +++++---\n 1 file changed, 5 insertions(+), 3 deletions(-)\n\n+-------------------------------------------------------------------------------\n| fix check when can't send the command to the promoted slave\n| By MOON_CLJ, 2016-05-26 13:10:12 +0800\n+--------------------------------------------------------------------------------\nhttps://github.com/antirez/redis/commit/26555f5e008b099b888ef39cabec632f4b31a038\n\n\n src/sentinel.c | 2 +-\n 1 file changed, 1 insertion(+), 1 deletion(-)\n\n+-------------------------------------------------------------------------------\n| Test TOUCH and new TTL / TYPE behavior about object access time.\n| By antirez, 2016-06-15 17:15:18 +0200\n+--------------------------------------------------------------------------------\nhttps://github.com/antirez/redis/commit/f1c237cb6a647ad5400b0ebce124fd9802ea7f89\n\n\n tests/test_helper.tcl          |  1 +\n tests/unit/introspection-2.tcl | 23 +++++++++++++++++++++++\n 2 files changed, 24 insertions(+)\n\n+-------------------------------------------------------------------------------\n| GETRANGE: return empty string with negative, inverted start/end.\n| By antirez, 2016-06-15 12:48:58 +0200\n+--------------------------------------------------------------------------------\nhttps://github.com/antirez/redis/commit/d4831e328759bf5bd07c2c6e6ce1d60e84ba196f\n\n\n src/bitops.c   | 4 ++--\n src/t_string.c | 4 ++++\n 2 files changed, 6 insertions(+), 2 deletions(-)\n\n+-------------------------------------------------------------------------------\n| Remove additional round brackets from fix for #3282.\n| By antirez, 2016-06-15 12:16:39 +0200\n+--------------------------------------------------------------------------------\nhttps://github.com/antirez/redis/commit/9942070f5a41fa3bc953e9628a7248aeb7c0befa\n\n\n src/bitops.c | 2 +-\n 1 file changed, 1 insertion(+), 1 deletion(-)\n\n+-------------------------------------------------------------------------------\n| bitcount bug:return non-zero value when start > end (both negative)\n| By wenduo, 2016-05-30 16:21:08 +0800\n+--------------------------------------------------------------------------------\nhttps://github.com/antirez/redis/commit/f45fa5d05f47a5729786a69962119c9b3dc12645\n\n\n src/bitops.c | 4 ++++\n 1 file changed, 4 insertions(+)\n\n+-------------------------------------------------------------------------------\n| Regression test for #3282.\n| By antirez, 2016-06-15 11:49:49 +0200\n+--------------------------------------------------------------------------------\nhttps://github.com/antirez/redis/commit/0cb86064e602a093a23b56943a7321fe1af64984\n\n\n tests/unit/bitops.tcl | 10 ++++++++++\n 1 file changed, 10 insertions(+)\n\n+-------------------------------------------------------------------------------\n| TTL and TYPE LRU access fixed. TOUCH implemented.\n| By antirez, 2016-06-14 15:33:59 +0200\n+--------------------------------------------------------------------------------\nhttps://github.com/antirez/redis/commit/b23aa6706ac79a1c86c64aef07bd35e38f10f842\n\n\n src/db.c     | 61 +++++++++++++++++++++++++++++++++++++++++++++++++++++-------\n src/server.c |  1 +\n src/server.h |  6 +++++-\n 3 files changed, 60 insertions(+), 8 deletions(-)\n\n+-------------------------------------------------------------------------------\n| redis-cli help.h updated.\n| By antirez, 2016-06-14 14:45:48 +0200\n+--------------------------------------------------------------------------------\nhttps://github.com/antirez/redis/commit/6e4204fec9c78f3300d887ebc3db014df2c8b33e\n\n\n src/help.h | 43 +++++++++++++++++++++++++++++--------------\n 1 file changed, 29 insertions(+), 14 deletions(-)\n\n+-------------------------------------------------------------------------------\n| Fix GEORADIUS wrong output with radius > Earth radius.\n| By antirez, 2016-05-30 12:45:49 +0200\n+--------------------------------------------------------------------------------\nhttps://github.com/antirez/redis/commit/bb43f4cab2f756c0412ca2b94d9e29c3db5025ab\n\nClose #3266\n\n deps/geohash-int/geohash_helper.c | 2 ++\n 1 file changed, 2 insertions(+)\n\n+-------------------------------------------------------------------------------\n| Geo: fix typo in geohashEstimateStepsByRadius().\n| By antirez, 2016-05-30 15:31:19 +0200\n+--------------------------------------------------------------------------------\nhttps://github.com/antirez/redis/commit/16102bc0af0912a0c9a92aedddf796eb24a80b9e\n\nI'm the author of this line but I can't see a good reason for it to\ndon't be a typo, a step of 26 should be valid with 52 bits per\ncoordinate, moreover the line was:\n\n    if (step > 26) step = 25;\n\nSo a step of 26 was actually already used, except when one of 27 was\ncomputed (which is invalid) only then it was trimmed to 25 instead of\n26.\n\nAll tests passing after the change.\n\n deps/geohash-int/geohash_helper.c | 2 +-\n 1 file changed, 1 insertion(+), 1 deletion(-)\n\n+-------------------------------------------------------------------------------\n| Avoid undefined behavior in BITFIELD implementation.\n| By antirez, 2016-05-31 11:52:07 +0200\n+--------------------------------------------------------------------------------\nhttps://github.com/antirez/redis/commit/014bf8044285c6d401d83e6e24829d276ab837f9\n\nProbably there is no compiler that will actaully break the code or raise\na signal for unsigned -> signed overflowing conversion, still it was\napparently possible to write it in a more correct way.\n\nAll tests passing.\n\n src/bitops.c | 23 +++++++++++++++--------\n 1 file changed, 15 insertions(+), 8 deletions(-)\n\n+-------------------------------------------------------------------------------\n| Now that SPOP can be called by scripts use BLPOP on 's' flag test.\n| By antirez, 2016-05-31 16:43:21 +0200\n+--------------------------------------------------------------------------------\nhttps://github.com/antirez/redis/commit/b4e5e2ec1ad7e9d1f4e7e559b61e0ecd4e50f2da\n\n\n tests/unit/scripting.tcl | 2 +-\n 1 file changed, 1 insertion(+), 1 deletion(-)\n\n+-------------------------------------------------------------------------------\n| Test: run GEO tests by default.\n| By antirez, 2016-05-31 16:43:49 +0200\n+--------------------------------------------------------------------------------\nhttps://github.com/antirez/redis/commit/df419281a19e13429b27814a3e384f6f029c3519\n\nThanks to @oranagra for noticing it was missing.\n\n tests/test_helper.tcl | 1 +\n 1 file changed, 1 insertion(+)\n\n+-------------------------------------------------------------------------------\n| Enable tcp-keepalive by default.\n| By antirez, 2016-06-13 12:03:14 +0200\n+--------------------------------------------------------------------------------\nhttps://github.com/antirez/redis/commit/40cfe13141c7178d22fd43e4ffbecc37686e0b43\n\n\n redis.conf | 5 +++--\n 1 file changed, 3 insertions(+), 2 deletions(-)\n\n+-------------------------------------------------------------------------------\n| fix some compiler warnings\n| By Pierre Chapuis, 2016-06-05 15:34:43 +0200\n+--------------------------------------------------------------------------------\nhttps://github.com/antirez/redis/commit/a650aaaf4f074ec428b450ef88799db1dcd34b0f\n\n\n src/bitops.c | 4 ++--\n 1 file changed, 2 insertions(+), 2 deletions(-)\n\n+-------------------------------------------------------------------------------\n| Fixed typo in Sentinel compareSlavesForPromotion() comment.\n| By antirez, 2016-06-10 09:15:01 +0200\n+--------------------------------------------------------------------------------\nhttps://github.com/antirez/redis/commit/3fd4baf1e77f125a306d57b788b72de5026c0564\n\n\n src/sentinel.c | 2 +-\n 1 file changed, 1 insertion(+), 1 deletion(-)\n\n+-------------------------------------------------------------------------------\n| fix comment \"b>a\" to \"a > b\"\n| By andyli, 2016-06-07 14:42:50 +0800\n+--------------------------------------------------------------------------------\nhttps://github.com/antirez/redis/commit/8d029a5950f4ef40723c02b5c486b171aff0189c\n\n\n src/sentinel.c | 2 +-\n 1 file changed, 1 insertion(+), 1 deletion(-)\n\n+-------------------------------------------------------------------------------\n| fix pidfile in redis.conf\n| By bogdanvlviv, 2016-04-19 14:43:06 +0300\n+--------------------------------------------------------------------------------\nhttps://github.com/antirez/redis/commit/6937f5960d1803ca0eda1ab6f4bc60023f50c914\n\n\n redis.conf | 2 +-\n 1 file changed, 1 insertion(+), 1 deletion(-)\n\n+-------------------------------------------------------------------------------\n| Include 'fd_set' type name\n| By jspraul, 2016-06-07 16:46:00 -0400\n+--------------------------------------------------------------------------------\nhttps://github.com/antirez/redis/commit/b5758cc5ce6c51ff75c86f9216214fe4d5e4c257\n\nFix an MSYS2-build-breaking error: unknown type name ‘fd_set’\n src/ae_select.c | 1 +\n 1 file changed, 1 insertion(+)\n\n+-------------------------------------------------------------------------------\n| Allow SPOP from Lua scripts\n| By Itamar Haber, 2016-05-28 20:01:46 +0300\n+--------------------------------------------------------------------------------\nhttps://github.com/antirez/redis/commit/620783e3b582e9ba6e1d8fbd47987281ce0b6317\n\nThe existing `R` flag appears to be sufficient and there's no apparent reason why the command should be blocked.\n src/server.c | 2 +-\n 1 file changed, 1 insertion(+), 1 deletion(-)\n\n+-------------------------------------------------------------------------------\n| minor fixes - mainly signalModifiedKey, and GEORADIUS\n| By oranagra, 2016-05-09 09:12:38 +0300\n+--------------------------------------------------------------------------------\nhttps://github.com/antirez/redis/commit/603234076f4e59967f331bc97de3c0db9947c8ef\n\n\n src/geo.c    |  1 +\n src/sds.c    |  8 ++++----\n src/server.c |  2 +-\n src/server.h |  3 +--\n src/t_set.c  |  9 ++++++---\n src/t_zset.c | 12 ++++++------\n 6 files changed, 19 insertions(+), 16 deletions(-)\n\n+-------------------------------------------------------------------------------\n| Code to access object string bytes repeated 3x refactored into 1 function.\n| By antirez, 2016-05-18 15:35:17 +0200\n+--------------------------------------------------------------------------------\nhttps://github.com/antirez/redis/commit/2e6b99499abb5ff1fbeee3bac4d064e5ff4ea256\n\n\n src/bitops.c | 74 ++++++++++++++++++++++++++++++++----------------------------\n 1 file changed, 39 insertions(+), 35 deletions(-)\n\n+-------------------------------------------------------------------------------\n| fix crash in BITFIELD GET when key is integer encoded\n| By oranagra, 2016-05-10 11:19:45 +0300\n+--------------------------------------------------------------------------------\nhttps://github.com/antirez/redis/commit/dcaeafc8280eb8329e7ce68e7ab02c67d98f0cf4\n\n\n src/bitops.c | 18 +++++++++++++++---\n 1 file changed, 15 insertions(+), 3 deletions(-)\n\n+-------------------------------------------------------------------------------\n| Clarify that the LOG_STR_SIZE includes null term.\n| By antirez, 2016-05-18 15:23:18 +0200\n+--------------------------------------------------------------------------------\nhttps://github.com/antirez/redis/commit/4ad088818a3353ebd619e8d43847b5d58108af20\n\n\n src/server.h | 2 +-\n 1 file changed, 1 insertion(+), 1 deletion(-)\n\n+-------------------------------------------------------------------------------\n| Test for BITFIELD regression #3221.\n| By antirez, 2016-05-18 14:53:30 +0200\n+--------------------------------------------------------------------------------\nhttps://github.com/antirez/redis/commit/f991cdc3e19c187035855355808575efd6b4c149\n\n\n tests/unit/bitfield.tcl | 5 +++++\n 1 file changed, 5 insertions(+)\n\n+-------------------------------------------------------------------------------\n| reduce struct padding by reordering members\n| By oranagra, 2016-05-16 20:12:11 +0300\n+--------------------------------------------------------------------------------\nhttps://github.com/antirez/redis/commit/cb3e89e2cb0753d2d111eaeadc9c73cbe24025ab\n\n\n src/quicklist.h | 2 +-\n 1 file changed, 1 insertion(+), 1 deletion(-)\n\n+-------------------------------------------------------------------------------\n| Actually use --with-lg-quantum=3 to build jemalloc.\n| By antirez, 2016-05-18 11:58:36 +0200\n+--------------------------------------------------------------------------------\nhttps://github.com/antirez/redis/commit/a7f0fb448c110e125eece44dc955d6939e494daa\n\nThis change is documented in deps/README.md but was lost in one way or\nthe other, neutralizing the benefits of 24 bytes size classes (and\nothers).\n\nClose #3208.\n\n deps/Makefile | 2 +-\n 1 file changed, 1 insertion(+), 1 deletion(-)\n\n+-------------------------------------------------------------------------------\n| redis-cli: integrate help.h with COMMAND output.\n| By antirez, 2016-05-07 13:03:25 +0200\n+--------------------------------------------------------------------------------\nhttps://github.com/antirez/redis/commit/029dc0d97fd492a2fd579796d4c1cc04053c7190\n\nUse the COMMAND output to fill with partial information the built-in\nhelp. This makes redis-cli able to at least complete commands that are\nexported by the Redis server it is connected to, but were not available\nin the help.h file when the redis-cli binary was compiled.\n\n src/redis-cli.c | 80 +++++++++++++++++++++++++++++++++++++++++++++++++--------\n 1 file changed, 70 insertions(+), 10 deletions(-)\n\n+-------------------------------------------------------------------------------\n| Removed dofile() from Lua\n| By Adam Baldwin, 2012-10-25 20:27:10 -0700\n+--------------------------------------------------------------------------------\nhttps://github.com/antirez/redis/commit/95def3aee044468504bb07633084afd49b085db3\n\n\n src/scripting.c | 2 ++\n 1 file changed, 2 insertions(+)\n\n\n================================================================================\nRedis 3.2.0     Released Fri May 06 08:47:10 CEST 2016\n================================================================================\n\nUpgrade urgency HIGH: 3.2-RC users should upgrade ASAP to this more\n                      stable release of Redis.\n\nHello, this is Redis 3.2.0 stable! And with the new release there is a new\nformat for the changelog. Now it is composed of a \"letter\" like the one\nyou are reading, followed by all the commits composing the release for people\ninterested in the details.\n\nThere are a few changes between the latest release candidate of Redis 3.2\nand the final 3.2.0 release. The main ones are the obvious bug fixes you\ncan find detailed below, also a few new things:\n\nCritical bugs fixed:\n\n* There was a problem in the way a cluster instance loaded the AOF that\n  could cause data written via scripts to be lost during reshardings.\n\nNew things:\n\n* There is a new very powerful BITFIELD command. Check the documentation\n  here: http://redis.io/commands/BITFIELD\n\n* CONFIG GET is allowed during the loading of the dataset.\n\n* The DEBUG command have new features and can show an help with DEBUG HELP.\n\n* redis-cli show hits about the commands arguments to the right.\n\n* GEORADIUS got a STORE / STOREDIST option to store the result into a target\n  key (as as orted set) instead of reporting it to the user.\n\n* Redis Cluster replicas migration now works in a slightly different way. In\n  the past a slave could migrate only to a master that used to have slaves\n  in the past (and if there was still trace of this information). Now instead\n  if a new slave gets at least a slot, and at least one other master in the\n  cluster has a slave, then the new master is considered a valid target for\n  replica migration. So if it will be orphaned and there is a spare slave\n  it will get one.\n\n* CLUSTER SLOTS output now includes the node ID (in a backward compatible\n  manner).\n\n* A lot of bug fixes you can read in the commits details below, with the\n  authors that kindly provided many useful patches. Thanks.\n\nAs usually what \"stable\" means is that we are confident the release is mature,\nhowever do your tests before putting it into production in your environemnt\nas it's fresh meat anyway.\n\nCheers,\nSalvatore\n\n+-------------------------------------------------------------------------------\n| Cluster: don't check scripts key slots during AOF loading.\n| By antirez, 2016-05-05 23:37:08 +0200\n+--------------------------------------------------------------------------------\nhttps://github.com/antirez/redis/commit/746e1bebb4baf876c1e8cd2fe2d468a1c41e5dc3\n\n\n src/scripting.c | 6 ++++--\n 1 file changed, 4 insertions(+), 2 deletions(-)\n\n+-------------------------------------------------------------------------------\n| redis-cli: remove debugging message.\n| By antirez, 2016-05-05 18:05:37 +0200\n+--------------------------------------------------------------------------------\nhttps://github.com/antirez/redis/commit/3907b059280898c6340b53982b3b65957535da7c\n\n\n src/redis-cli.c | 1 -\n 1 file changed, 1 deletion(-)\n\n+-------------------------------------------------------------------------------\n| Revert \"Fix commandCommand arity\"\n| By antirez, 2016-05-05 17:35:33 +0200\n+--------------------------------------------------------------------------------\nhttps://github.com/antirez/redis/commit/f01a2714582a9a916b41e6cb90e42474a104925d\n\nThis reverts commit 1189a4eae6d009fc0da8d50fd542ba1391542165.\n\nActually this is wrong, the command can be called without args at all.\n\n src/server.c | 2 +-\n 1 file changed, 1 insertion(+), 1 deletion(-)\n\n+-------------------------------------------------------------------------------\n| Fix commandCommand arity\n| By Ruben Bridgewater, 2016-01-04 11:39:45 +0100\n+--------------------------------------------------------------------------------\nhttps://github.com/antirez/redis/commit/1189a4eae6d009fc0da8d50fd542ba1391542165\n\n\n src/server.c | 2 +-\n 1 file changed, 1 insertion(+), 1 deletion(-)\n\n+-------------------------------------------------------------------------------\n| Fix a possible race condition of sdown detection if the connection to master/slave/sentinel decames disconnected just after the last PONG and before the next PING.\n| By Daniel Shih, 2016-01-12 17:06:47 +0800\n+--------------------------------------------------------------------------------\nhttps://github.com/antirez/redis/commit/d9dc0d777b775f2fe4f23f42e1b4130f4de1ed72\n\n\n src/sentinel.c | 2 ++\n 1 file changed, 2 insertions(+)\n\n+-------------------------------------------------------------------------------\n| Fix nanosecond conversion\n| By Jan-Erik Rediger, 2016-01-13 10:22:29 -0700\n+--------------------------------------------------------------------------------\nhttps://github.com/antirez/redis/commit/13bd702844eda7bccc7c672b6ff77f53e21ab841\n\n1 microsecond = 1000 nanoseconds\n1e3 = 1000\n10e3 = 10000\n\n src/redis-cli.c | 2 +-\n 1 file changed, 1 insertion(+), 1 deletion(-)\n\n+-------------------------------------------------------------------------------\n| redis-cli: don't free historyfile, is used later.\n| By antirez, 2016-05-05 13:57:57 +0200\n+--------------------------------------------------------------------------------\nhttps://github.com/antirez/redis/commit/f6b7df3aec1d8fddf3121c4315fea4bf45cc4cfe\n\n\n src/redis-cli.c | 2 +-\n 1 file changed, 1 insertion(+), 1 deletion(-)\n\n+-------------------------------------------------------------------------------\n| Cluster test 12: reshard back just a few slots to speedup the test.\n| By antirez, 2016-05-05 11:49:27 +0200\n+--------------------------------------------------------------------------------\nhttps://github.com/antirez/redis/commit/97ce72fa2d348f914fc40ccf0a32008c7362b817\n\n\n tests/cluster/tests/12-replica-migration-2.tcl | 14 +++++++-------\n 1 file changed, 7 insertions(+), 7 deletions(-)\n\n+-------------------------------------------------------------------------------\n| Cluster: make getNodeByQuery() responsible of -CLUSTERDOWN errors.\n| By antirez, 2016-05-05 11:33:43 +0200\n+--------------------------------------------------------------------------------\nhttps://github.com/antirez/redis/commit/708f486c77b455fa7ae1e87cf31278474eb9d432\n\nThis fixes a bug introduced by d827dbf, and makes the code consistent\nwith the logic of always allowing, while the cluster is down, commands\nthat don't target any key.\n\nAs a side effect the code is also simpler now.\n\n src/cluster.c | 13 +++++++++++--\n src/server.c  | 26 ++++++++++----------------\n 2 files changed, 21 insertions(+), 18 deletions(-)\n\n+-------------------------------------------------------------------------------\n| Fixes a typo\n| By Itamar Haber, 2016-01-28 21:47:18 +0200\n+--------------------------------------------------------------------------------\nhttps://github.com/antirez/redis/commit/1fc2ed61bec2f2bf266b48e566a197c5214b4350\n\n\n src/cluster.c | 2 +-\n 1 file changed, 1 insertion(+), 1 deletion(-)\n\n+-------------------------------------------------------------------------------\n| Reverse redirect address parse\n| By David Cavar, 2016-02-09 15:04:42 +0100\n+--------------------------------------------------------------------------------\nhttps://github.com/antirez/redis/commit/787d5ab9be45bf4feb6cfa8a227c185c93aaadae\n\nFix issue in case the redirect address is in ipv6 format. Parse from behind to extract last part of the response which represents actual port.\n src/redis-cli.c | 2 +-\n 1 file changed, 1 insertion(+), 1 deletion(-)\n\n+-------------------------------------------------------------------------------\n| Bind both IPv4 and IPv6 or exit with an error by default.\n| By antirez, 2016-05-05 10:02:42 +0200\n+--------------------------------------------------------------------------------\nhttps://github.com/antirez/redis/commit/0fda06225f19b18a370d63ac650a8bb61020235d\n\nThanks to @tushar2708 for the PR. I applied a slightly different fix.\nThanks to @cespare for reporting.\n\nClose #3024\nClose #3020\n\n src/server.c | 18 ++++++++++--------\n 1 file changed, 10 insertions(+), 8 deletions(-)\n\n+-------------------------------------------------------------------------------\n| Quick fix to avoid false positive in replica migration test.\n| By antirez, 2016-05-05 09:45:31 +0200\n+--------------------------------------------------------------------------------\nhttps://github.com/antirez/redis/commit/65707fa6b5bb38b5818af57ab93b9b1da47d708a\n\n\n tests/cluster/tests/12-replica-migration-2.tcl | 5 ++++-\n 1 file changed, 4 insertions(+), 1 deletion(-)\n\n+-------------------------------------------------------------------------------\n| Ensure slots are rechecked on EXEC.\n| By Chris Thunes, 2016-03-11 15:22:36 -0500\n+--------------------------------------------------------------------------------\nhttps://github.com/antirez/redis/commit/1f3ed652e2a6cfcbbd5300a31f5771f2ce842e98\n\nFixes #2515.\n\n src/server.c | 9 +++++++--\n 1 file changed, 7 insertions(+), 2 deletions(-)\n\n+-------------------------------------------------------------------------------\n| fix for #3187\n| By therealbill, 2016-04-22 10:43:48 -0500\n+--------------------------------------------------------------------------------\nhttps://github.com/antirez/redis/commit/3a4810678904af013901a896ab0bb3c71856644c\n\nI've renamed maxmemoryToString to evictPolicyToString since that is\nmore accurate (and easier to mentally connect with the correct data), as\nwell as updated the function to user server.maxmemory_policy rather than\nserver.maxmemory. Now with a default config it is actually returning\nthe correct policy rather than volatile-lru.\n\n src/config.c | 4 ++--\n src/server.c | 2 +-\n src/server.h | 2 +-\n 3 files changed, 4 insertions(+), 4 deletions(-)\n\n+-------------------------------------------------------------------------------\n| Fixed typo in README.md\n| By Seth Bergman, 2016-04-30 11:58:48 -0500\n+--------------------------------------------------------------------------------\nhttps://github.com/antirez/redis/commit/bba53d7fc7a759b53d72a7c3be17a00abe32039e\n\n\n README.md | 2 +-\n 1 file changed, 1 insertion(+), 1 deletion(-)\n\n+-------------------------------------------------------------------------------\n| fix variable\n| By Ryosuke Hasebe, 2016-03-30 23:09:36 +0900\n+--------------------------------------------------------------------------------\nhttps://github.com/antirez/redis/commit/ab7581489871eebcf0253915acc26efb27f5df23\n\n\n src/redis-trib.rb | 10 +++++-----\n 1 file changed, 5 insertions(+), 5 deletions(-)\n\n+-------------------------------------------------------------------------------\n| fix check_open_slots\n| By Ryosuke Hasebe, 2016-03-30 21:56:22 +0900\n+--------------------------------------------------------------------------------\nhttps://github.com/antirez/redis/commit/0fcf896ac14c6e5c57e3b79e836dd8bf7dad94b5\n\n\n src/redis-trib.rb | 3 ++-\n 1 file changed, 2 insertions(+), 1 deletion(-)\n\n+-------------------------------------------------------------------------------\n| Minor redis-cli wording change in --help output.\n| By antirez, 2016-05-04 22:34:17 +0200\n+--------------------------------------------------------------------------------\nhttps://github.com/antirez/redis/commit/b8a63635e39ce312b2c5664f2c2a59184849b8fb\n\n\n src/redis-cli.c | 3 ++-\n 1 file changed, 2 insertions(+), 1 deletion(-)\n\n+-------------------------------------------------------------------------------\n| Allow CONFIG GET during loading.\n| By antirez, 2016-05-04 15:45:38 +0200\n+--------------------------------------------------------------------------------\nhttps://github.com/antirez/redis/commit/ae95de93312d6bb2c8c365c31f2a3fd0b6d2c100\n\nThanks to @oranagra for the idea of allowing CONFIG GET during loading.\n\n src/config.c | 6 ++++++\n src/server.c | 2 +-\n 2 files changed, 7 insertions(+), 1 deletion(-)\n\n+-------------------------------------------------------------------------------\n| Command \"r\" flag removed from commands not accessing the key space.\n| By antirez, 2016-05-04 15:42:14 +0200\n+--------------------------------------------------------------------------------\nhttps://github.com/antirez/redis/commit/3ff8f57ef32e3b1ddd407b65d474f610881bef34\n\nThanks to @oranagra for the hint about misplaced 'r' flags.\n\n src/server.c | 70 ++++++++++++++++++++++++++++++------------------------------\n 1 file changed, 35 insertions(+), 35 deletions(-)\n\n+-------------------------------------------------------------------------------\n| DEBUG command self documentation.\n| By antirez, 2016-05-04 12:45:55 +0200\n+--------------------------------------------------------------------------------\nhttps://github.com/antirez/redis/commit/07b852d24ec8d7cb47044b096baf0af1410c69ed\n\n\n src/debug.c  | 49 ++++++++++++++++++++++++++++++++++++++++++++++++-\n src/server.c |  2 +-\n 2 files changed, 49 insertions(+), 2 deletions(-)\n\n+-------------------------------------------------------------------------------\n| various cleanups and minor fixes\n| By Oran Agra, 2016-04-25 16:49:57 +0300\n+--------------------------------------------------------------------------------\nhttps://github.com/antirez/redis/commit/cfc08b65b04cf972ebeadf3be9f39f2acd7672b3\n\n\n src/adlist.c             | 18 ++++++------------\n src/ae_epoll.c           |  6 ++----\n src/aof.c                |  5 ++++-\n src/db.c                 |  2 +-\n src/rdb.c                |  6 ++++--\n src/rio.c                |  5 +++--\n src/rio.h                |  2 ++\n src/server.h             |  3 +--\n tests/support/test.tcl   |  6 ------\n tests/unit/bitops.tcl    |  2 +-\n tests/unit/other.tcl     |  1 +\n tests/unit/scripting.tcl | 27 ++++++++++++++-------------\n 12 files changed, 39 insertions(+), 44 deletions(-)\n\n+-------------------------------------------------------------------------------\n| dict.c minor optimization\n| By Oran Agra, 2016-04-25 16:48:25 +0300\n+--------------------------------------------------------------------------------\nhttps://github.com/antirez/redis/commit/6710c8dc15680b756de26d1d45df110987b951b3\n\n\n src/dict.c | 8 ++++----\n 1 file changed, 4 insertions(+), 4 deletions(-)\n\n+-------------------------------------------------------------------------------\n| networking.c minor optimization\n| By Oran Agra, 2016-04-25 16:48:09 +0300\n+--------------------------------------------------------------------------------\nhttps://github.com/antirez/redis/commit/be5c0869821b16f18104d9ea62ab42bfa0615816\n\n\n src/networking.c | 11 +++++------\n 1 file changed, 5 insertions(+), 6 deletions(-)\n\n+-------------------------------------------------------------------------------\n| add DEBUG JEMALLC PURGE and JEMALLOC INFO cleanup\n| By Oran Agra, 2016-04-25 16:47:42 +0300\n+--------------------------------------------------------------------------------\nhttps://github.com/antirez/redis/commit/3ede6c7a506bcff3c7d2147c8af140dd4102a36e\n\n\n src/debug.c     | 17 ++++++++++++++++-\n src/redis-cli.c |  2 +-\n 2 files changed, 17 insertions(+), 2 deletions(-)\n\n+-------------------------------------------------------------------------------\n| fix small issues in redis 3.2\n| By Oran Agra, 2016-04-25 14:19:28 +0300\n+--------------------------------------------------------------------------------\nhttps://github.com/antirez/redis/commit/e2fab184efd01ffa0d510739f4d819a30b1d6787\n\n\n src/config.c | 2 ++\n src/rdb.c    | 2 +-\n 2 files changed, 3 insertions(+), 1 deletion(-)\n\n+-------------------------------------------------------------------------------\n| additional fix to issue #2948\n| By Oran Agra, 2016-04-25 14:18:40 +0300\n+--------------------------------------------------------------------------------\nhttps://github.com/antirez/redis/commit/9d57ceec08687545c2a63a2c18c28e2bcaf74664\n\n\n src/networking.c | 3 +++\n 1 file changed, 3 insertions(+)\n\n+-------------------------------------------------------------------------------\n| Reply with error on negative geo radius.\n| By antirez, 2016-05-04 08:59:56 +0200\n+--------------------------------------------------------------------------------\nhttps://github.com/antirez/redis/commit/7ba2cf5f8bea9cd125e773de147e3ea9b19ee2b0\n\nThanks to @tidwall for reporting.\nClose #3194.\n\n src/geo.c | 5 ++++-\n 1 file changed, 4 insertions(+), 1 deletion(-)\n\n+-------------------------------------------------------------------------------\n| Cluster regression test for #3043.\n| By antirez, 2016-05-02 18:36:09 +0200\n+--------------------------------------------------------------------------------\nhttps://github.com/antirez/redis/commit/38cf2bd257d09b360be6adf450d59592a359696d\n\nThe test works but is very slow so far, since it involves resharding\n1/5 of all the cluster slots from master 0 to the other 4 masters and\nback into the original master.\n\n tests/cluster/tests/12-replica-migration-2.tcl | 61 ++++++++++++++++++++++++++\n 1 file changed, 61 insertions(+)\n\n+-------------------------------------------------------------------------------\n| New masters with slots are now targets of migration if others are.\n| By antirez, 2016-05-02 16:41:56 +0200\n+--------------------------------------------------------------------------------\nhttps://github.com/antirez/redis/commit/7b618823c189c24313effbccda7022d167ea419c\n\nThis fixes issue #3043.\n\nBefore this fix, after a complete resharding of a master slots\nto other nodes, the master remains empty and the slaves migrate away\nto other masters with non-zero nodes. However the old master now empty,\nis no longer considered a target for migration, because the system has\nno way to tell it had slaves in the past.\n\nThis fix leaves the algorithm used in the past untouched, but adds a\nnew rule. When a new or old master which is empty and without slaves,\nare assigend with their first slot, if other masters in the cluster have\nslaves, they are automatically considered to be targets for replicas\nmigration.\n\n src/cluster.c | 36 +++++++++++++++++++++++++++++++++++-\n 1 file changed, 35 insertions(+), 1 deletion(-)\n\n+-------------------------------------------------------------------------------\n| Test ZINCRBY return value.\n| By antirez, 2016-05-02 08:57:30 +0200\n+--------------------------------------------------------------------------------\nhttps://github.com/antirez/redis/commit/1101b515c73dcb0ff4a868ba38a91dcebb5b85cc\n\n\n tests/unit/type/zset.tcl | 6 ++++++\n 1 file changed, 6 insertions(+)\n\n+-------------------------------------------------------------------------------\n| redis-cli preferences and rc file support.\n| By antirez, 2016-04-13 13:58:30 +0200\n+--------------------------------------------------------------------------------\nhttps://github.com/antirez/redis/commit/bbf93108ef2a7ac7bd53e26c96bf838f7c5e72df\n\n\n src/redis-cli.c | 102 ++++++++++++++++++++++++++++++++++++++++++++++----------\n 1 file changed, 85 insertions(+), 17 deletions(-)\n\n+-------------------------------------------------------------------------------\n| redis-cli hints.\n| By antirez, 2016-04-13 12:34:14 +0200\n+--------------------------------------------------------------------------------\nhttps://github.com/antirez/redis/commit/3fd3fca0dd38cb21c900e4ba98e3d41f333335aa\n\n\n deps/linenoise/linenoise.c |  8 +++++++\n deps/linenoise/linenoise.h |  2 +-\n src/redis-cli.c            | 53 ++++++++++++++++++++++++++++++++++++++++++++++\n 3 files changed, 62 insertions(+), 1 deletion(-)\n\n+-------------------------------------------------------------------------------\n| Linenoise updated again (hints support).\n| By antirez, 2016-04-12 23:39:18 +0200\n+--------------------------------------------------------------------------------\nhttps://github.com/antirez/redis/commit/34354473ffe8d60b80acdbc8c16b194f8bbd70a0\n\n\n deps/linenoise/README.markdown | 176 ++++++++++++++++++++++++++++++++++++++++-\n deps/linenoise/example.c       |  10 +++\n deps/linenoise/linenoise.c     |  55 ++++++++++++-\n deps/linenoise/linenoise.h     |  15 +++-\n 4 files changed, 248 insertions(+), 8 deletions(-)\n\n+-------------------------------------------------------------------------------\n| Linenoise updated.\n| By antirez, 2016-04-06 13:37:27 +0200\n+--------------------------------------------------------------------------------\nhttps://github.com/antirez/redis/commit/58229cd766fa02f399267310b5b488aac2c55a6a\n\nAs a side effect, cat commands.txt | redis-cli now is able to handle\nlines more than 4096 bytes.\n\n deps/linenoise/linenoise.c | 60 ++++++++++++++++++++++++++++++++++------------\n 1 file changed, 45 insertions(+), 15 deletions(-)\n\n+-------------------------------------------------------------------------------\n| ae.c: Fix delay until next timer event.\n| By antirez, 2016-04-04 14:08:16 +0200\n+--------------------------------------------------------------------------------\nhttps://github.com/antirez/redis/commit/29645f1f44926ac2662ed768fe1e369775a30b66\n\nThis fix was written by Anthony LaTorre.\nThe old code mis-calculated the amount of time to wait till next event.\n\n src/ae.c | 21 ++++++++++++---------\n 1 file changed, 12 insertions(+), 9 deletions(-)\n\n+-------------------------------------------------------------------------------\n| ae.c: comment to explain why we have a useless maxId check.\n| By antirez, 2016-04-04 12:23:10 +0200\n+--------------------------------------------------------------------------------\nhttps://github.com/antirez/redis/commit/aa79c1f1c1d288e4cc2c0f4689ad01488678bf9d\n\n\n src/ae.c | 6 +++++-\n 1 file changed, 5 insertions(+), 1 deletion(-)\n\n+-------------------------------------------------------------------------------\n| Fix ae.c to avoid timers infinite loop.\n| By antirez, 2016-01-08 15:05:14 +0100\n+--------------------------------------------------------------------------------\nhttps://github.com/antirez/redis/commit/0b69c9865619b54b75576e67aaafe7b018734bec\n\nThis fix was suggested by Anthony LaTorre, that provided also a good\ntest case that was used to verify the fix.\n\nThe problem with the old implementation is that, the time returned by\na timer event (that is the time after it want to run again) is added\nto the event *start time*. So if the event takes, in order to run, more\nthan the time it says it want to be scheduled again for running, an\ninfinite loop is triggered.\n\n src/ae.c          | 51 ++++++++++++++++++++++-----------------------------\n src/ae.h          |  3 +++\n src/anet.h        |  2 ++\n src/redis-trib.rb |  2 +-\n 4 files changed, 28 insertions(+), 30 deletions(-)\n\n+-------------------------------------------------------------------------------\n| BITFIELD: overflow wrap behavior fuzz tester.\n| By antirez, 2016-03-02 17:22:42 +0100\n+--------------------------------------------------------------------------------\nhttps://github.com/antirez/redis/commit/258857cd62e0eb70da32742651a55213fbc28a53\n\n\n tests/unit/bitfield.tcl | 51 +++++++++++++++++++++++++++++++++++++++++++++++++\n 1 file changed, 51 insertions(+)\n\n+-------------------------------------------------------------------------------\n| BITFIELD basic unit tests.\n| By antirez, 2016-03-02 16:31:02 +0100\n+--------------------------------------------------------------------------------\nhttps://github.com/antirez/redis/commit/35d05d6dc5d7fb810e732f9de7b05c6b14933fb6\n\n\n tests/unit/bitfield.tcl | 86 ++++++++++++++++++++++++++++++++++++++++++++++++-\n 1 file changed, 85 insertions(+), 1 deletion(-)\n\n+-------------------------------------------------------------------------------\n| BITFIELD: Farest bit set is offset+bits-1. Off by one error fixed.\n| By antirez, 2016-03-02 16:20:28 +0100\n+--------------------------------------------------------------------------------\nhttps://github.com/antirez/redis/commit/6cf83feffad7f7b7693a207a9d63278354769ece\n\n\n src/bitops.c | 6 ++++--\n 1 file changed, 4 insertions(+), 2 deletions(-)\n\n+-------------------------------------------------------------------------------\n| BITFIELD: overflow fuzzy testing.\n| By antirez, 2016-03-02 15:15:18 +0100\n+--------------------------------------------------------------------------------\nhttps://github.com/antirez/redis/commit/b4d65c9501be01531eb8fbeb4ba2b444e35d6494\n\n\n tests/test_helper.tcl   |  1 +\n tests/unit/bitfield.tcl | 52 +++++++++++++++++++++++++++++++++++++++++++++++++\n 2 files changed, 53 insertions(+)\n\n+-------------------------------------------------------------------------------\n| Fix typo in bitops.tcl comment.\n| By antirez, 2016-03-02 15:14:53 +0100\n+--------------------------------------------------------------------------------\nhttps://github.com/antirez/redis/commit/d75e0fdbe6ecf3074b18c4dd1e8b71a474254ccc\n\n\n tests/unit/bitops.tcl | 2 +-\n 1 file changed, 1 insertion(+), 1 deletion(-)\n\n+-------------------------------------------------------------------------------\n| More BITFIELD fixes. Overflow conditional simplified.\n| By antirez, 2016-03-02 15:13:45 +0100\n+--------------------------------------------------------------------------------\nhttps://github.com/antirez/redis/commit/5f3ef73ed41be6e051daad9fdb7efa91b4ca682d\n\nSee issue #3114.\n\n src/bitops.c | 17 ++++++++---------\n 1 file changed, 8 insertions(+), 9 deletions(-)\n\n+-------------------------------------------------------------------------------\n| bitops/bitfield: fix length, overflow condition and *sign\n| By Sun He, 2016-03-02 18:11:30 +0800\n+--------------------------------------------------------------------------------\nhttps://github.com/antirez/redis/commit/5b9aa5026204fb6c8b0098d4e47c2e001cf06151\n\n\n src/bitops.c | 13 ++++++++-----\n 1 file changed, 8 insertions(+), 5 deletions(-)\n\n+-------------------------------------------------------------------------------\n| Fix INFO commandstats reporting when argv is rewritten.\n| By antirez, 2016-03-02 08:51:27 +0100\n+--------------------------------------------------------------------------------\nhttps://github.com/antirez/redis/commit/ba9154d7e7bf959b002533384319a1e90545447b\n\nWe want to report the original command in the stats, for example GEOADD,\neven when what is actually executed is the ZADD implementation.\n\n src/scripting.c | 2 +-\n src/server.c    | 4 ++--\n 2 files changed, 3 insertions(+), 3 deletions(-)\n\n+-------------------------------------------------------------------------------\n| BITFIELD: refactoring & fix of retval on FAIL.\n| By antirez, 2016-02-29 09:08:46 +0100\n+--------------------------------------------------------------------------------\nhttps://github.com/antirez/redis/commit/76b22e3728e37fe11582b71802bf98a2be09623f\n\n\n src/bitops.c | 32 ++++++++++++++++++++++++--------\n 1 file changed, 24 insertions(+), 8 deletions(-)\n\n+-------------------------------------------------------------------------------\n| BITFIELD: Fix #<index> form parsing.\n| By antirez, 2016-02-26 15:53:29 +0100\n+--------------------------------------------------------------------------------\nhttps://github.com/antirez/redis/commit/c333a9e2d7873190b22aaee8835a188bc55b60dc\n\n\n src/bitops.c | 10 ++++------\n 1 file changed, 4 insertions(+), 6 deletions(-)\n\n+-------------------------------------------------------------------------------\n| BITFIELD: Support #<index> offsets form.\n| By antirez, 2016-02-26 15:16:24 +0100\n+--------------------------------------------------------------------------------\nhttps://github.com/antirez/redis/commit/f84871cb5dd3bb3c04bfd7ac53b6e06b246f511f\n\n\n src/bitops.c | 29 +++++++++++++++++++++++------\n 1 file changed, 23 insertions(+), 6 deletions(-)\n\n+-------------------------------------------------------------------------------\n| BITFIELD command initial implementation.\n| By antirez, 2016-02-25 23:31:45 +0100\n+--------------------------------------------------------------------------------\nhttps://github.com/antirez/redis/commit/761a77287107ce53dbf4755f1435cc9660b6c86d\n\nThe new bitfield command is an extension to the Redis bit operations,\nwhere not just single bit operations are performed, but the array of\nbits composing a string, can be addressed at random, not aligned\noffsets, with any width unsigned and signed integers like u8, s5, u10\n(up to 64 bit signed integers and 63 bit unsigned integers).\n\nThe BITFIELD command supports subcommands that can SET, GET, or INCRBY\nthose arbitrary bit counters, with multiple overflow semantics.\n\nTrivial and credits:\n\nA similar command was imagined a few times in the past, but for\nsome reason looked a bit far fetched or not well specified.\nFinally the command was proposed again in a clear form by\nYoav Steinberg from Redis Labs, that proposed a set of commands on\narbitrary sized integers stored at bit offsets.\n\nStarting from this proposal I wrote an initial specification of a single\ncommand with sub-commands similar to what Yoav envisioned, using short\nnames for types definitions, and adding control on the overflow.\n\nThis commit is the resulting implementation.\n\nExamples:\n\n    BITFIELD mykey OVERFLOW wrap INCRBY i2 10 -1 GET i2 10\n\n src/bitops.c | 506 +++++++++++++++++++++++++++++++++++++++++++++++++++++++----\n src/server.c |   1 +\n src/server.h |   1 +\n 3 files changed, 476 insertions(+), 32 deletions(-)\n\n+-------------------------------------------------------------------------------\n| Eliminates engineers near the equator & prime meridian\n| By Itamar Haber, 2016-02-18 15:11:30 -0800\n+--------------------------------------------------------------------------------\nhttps://github.com/antirez/redis/commit/4b89ea3a95ef72353e14e0eb5cbf293bf2dc8b48\n\n\n src/geo.c | 8 ++++----\n 1 file changed, 4 insertions(+), 4 deletions(-)\n\n+-------------------------------------------------------------------------------\n| Fixes a typo in a comment\n| By Itamar Haber, 2016-02-18 15:01:34 -0800\n+--------------------------------------------------------------------------------\nhttps://github.com/antirez/redis/commit/0f46f9bd423a146f96e1993aca6221e1305f9a28\n\n\n src/geo.c | 2 +-\n 1 file changed, 1 insertion(+), 1 deletion(-)\n\n+-------------------------------------------------------------------------------\n| Adjusts accuracy for GEODIST\n| By Itamar Haber, 2016-02-18 15:00:39 -0800\n+--------------------------------------------------------------------------------\nhttps://github.com/antirez/redis/commit/9de844603c5203ae6ff6e7882a3dcb47a9f79a85\n\n\n src/geo.c | 2 +-\n 1 file changed, 1 insertion(+), 1 deletion(-)\n\n+-------------------------------------------------------------------------------\n| addReplyHumanLongDouble() API added.\n| By antirez, 2016-02-18 22:08:47 +0100\n+--------------------------------------------------------------------------------\nhttps://github.com/antirez/redis/commit/79e553a58d7f814fd08482b118561fcf9854b1df\n\nSend a long double or double as a bulk reply, in a human friendly\nformat.\n\n src/networking.c | 9 +++++++++\n src/server.h     | 1 +\n 2 files changed, 10 insertions(+)\n\n+-------------------------------------------------------------------------------\n| Fix GEORADIUS STORE/DIST refcount after backport to 3.2.\n| By antirez, 2016-02-18 15:33:02 +0100\n+--------------------------------------------------------------------------------\nhttps://github.com/antirez/redis/commit/158d1e2fbf6badb881a4d78623fd1bffde34cc49\n\n\n src/geo.c | 2 ++\n 1 file changed, 2 insertions(+)\n\n+-------------------------------------------------------------------------------\n| GEOADD STORE/STOREDIST tests.\n| By antirez, 2016-02-18 14:42:42 +0100\n+--------------------------------------------------------------------------------\nhttps://github.com/antirez/redis/commit/123cd88286127cc20684bf0457cb51107a67cfa2\n\n\n tests/unit/geo.tcl | 54 ++++++++++++++++++++++++++++++++++++++++++++++++++++++\n 1 file changed, 54 insertions(+)\n\n+-------------------------------------------------------------------------------\n| New options for GEORADIUS: STORE and STOREDIST.\n| By antirez, 2016-02-18 10:24:11 +0100\n+--------------------------------------------------------------------------------\nhttps://github.com/antirez/redis/commit/0b6daf5a6b27447f03c76387b8b707ce0ab7b08d\n\nRelated to issue #3019.\n\n src/geo.c    | 143 +++++++++++++++++++++++++++++++++++++++++------------------\n src/server.c |   4 +-\n src/server.h |   1 +\n src/t_zset.c |  18 +++++---\n 4 files changed, 117 insertions(+), 49 deletions(-)\n\n+-------------------------------------------------------------------------------\n| Include full paths on RDB/AOF files errors.\n| By antirez, 2016-02-15 16:14:56 +0100\n+--------------------------------------------------------------------------------\nhttps://github.com/antirez/redis/commit/f7af1beaab938b7e319d1b91d7736f043b7ef682\n\nClose #3086.\n\n src/aof.c | 17 +++++++++++++++--\n src/rdb.c | 19 +++++++++++++++++--\n 2 files changed, 32 insertions(+), 4 deletions(-)\n\n+-------------------------------------------------------------------------------\n| Remove Lua state reference from buffers in lua_cmsgpack.\n| By antirez, 2016-02-10 09:12:17 +0100\n+--------------------------------------------------------------------------------\nhttps://github.com/antirez/redis/commit/0b4a628fc716ab6b88c9823b143de174601a790d\n\n\n deps/lua/src/lua_cmsgpack.c | 53 +++++++++++++++++++++------------------------\n 1 file changed, 25 insertions(+), 28 deletions(-)\n\n+-------------------------------------------------------------------------------\n| cmsgpack: pass correct osize values to lua allocator, update correct buf free space in cmsgpack\n| By yoav@monfort.co.il, 2016-02-07 20:24:28 +0200\n+--------------------------------------------------------------------------------\nhttps://github.com/antirez/redis/commit/43509f686452fba68966aa89b87d1be065b50e17\n\n\n deps/lua/src/lua_cmsgpack.c | 8 ++++----\n 1 file changed, 4 insertions(+), 4 deletions(-)\n\n+-------------------------------------------------------------------------------\n| Fixes a typo\n| By Itamar Haber, 2016-02-03 11:04:09 -0800\n+--------------------------------------------------------------------------------\nhttps://github.com/antirez/redis/commit/cd9f7c6976f81c0e9ffae9e34b31eda19384a7dd\n\n\n src/server.c | 4 ++--\n 1 file changed, 2 insertions(+), 2 deletions(-)\n\n+-------------------------------------------------------------------------------\n| Adds keyspace notifications for lrem\n| By Itamar Haber, 2016-02-02 09:58:19 -0800\n+--------------------------------------------------------------------------------\nhttps://github.com/antirez/redis/commit/bf30f5a73922e5111d6a39da7351e22357213134\n\n\n src/t_list.c | 7 ++++++-\n 1 file changed, 6 insertions(+), 1 deletion(-)\n\n+-------------------------------------------------------------------------------\n| Typo ASII -> ASCII fixed in comment.\n| By antirez, 2016-01-29 12:08:10 +0100\n+--------------------------------------------------------------------------------\nhttps://github.com/antirez/redis/commit/0c7c7631d206964b8bf1dae3db286a3acda4edad\n\n\n src/server.h | 2 +-\n 1 file changed, 1 insertion(+), 1 deletion(-)\n\n+-------------------------------------------------------------------------------\n| Cluster: include node IDs in SLOTS output.\n| By antirez, 2016-01-29 12:00:38 +0100\n+--------------------------------------------------------------------------------\nhttps://github.com/antirez/redis/commit/0f3fb0097ae70e36ee65468b79f0be4160934bb4\n\nCLUSTER SLOTS now includes IDs in the nodes description associated with\na given slot range. Certain client libraries implementations need a way\nto reference a node in an unique way, so they were relying on CLUSTER\nNODES, that is not a stable API and may change frequently depending on\nRedis Cluster future requirements.\n\n src/cluster.c | 8 ++++++--\n 1 file changed, 6 insertions(+), 2 deletions(-)\n\n\n~~~~~~~~~~~~~~~~~~~~~~~~~~ OLD STYLE CHANGELOG ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n\n--[ Redis 3.2.0 RC3 (version 3.1.103) ] Release date: 28 jan 2016\n\nUpgrade urgency MODERATE: this release fixes a non trivial Sentinel crash.\n\n* [FIX] avg_ttl reporting in INFO improved. (Salvatore Sanfilippo)\n* [FIX] Sentinel: improve handling of known Sentinel instances.\n        (Salvatore Sanfilippo, thanks to Paweł Kowalczykf or the original\n         crash report).\n* [FIX] Redis Cluster address update (via gossip section) processing improved\n        to avoid initiating inwanted handshakes.\n\n--[ Redis 3.2.0 RC2 (version 3.1.102) ] Release date: 25 jan 2016\n\nUpgrade urgency MODERATE: this release fixes important Redis Cluster bugs.\n\n* [FIX] Many fixes to MIGRATE multiple keys implementation. The command\n        could handle errors in a faulty way leading to crashes or other\n        unexpected behaviors. MIGRATE command refactoring.\n        (The analysis of the faulty conditions was conducted by\n         Kevin McGehee. The fix was developed by Salvatore Sanfilippo)\n* [FIX] A Redis Cluster node crash was fixed because of wrong handling of\n        node->slaveof pointers.\n        (Reported by JackyWoo, fixed by Salvatore Sanfilippo)\n* [FIX] Fix redis-trib rebalance when nodes need to be left empty because\n        the specified weight is zero.\n        (Reported by Shahar Mor, fixed by Salvatore Sanfilippo)\n* [FIX] MIGRATE: Never send -ASK redirections for MIGRATE when there are\n        open slots. Redis-trib and other cluster management utility must\n        always be free to move keys between nodes about open slots, in order\n        to reshard, fix the cluster configuration, and so forth.\n        (Salvatore Sanfilippo)\n* [FIX] Lua debugger crash when printing too deeply nested objects.\n        (Reported by Paul Kulchenko, fixed by Salvatore Sanfilippo)\n* [FIX] Redis-cli implementation of Lua debugging now allows to use the\n        SCRIPT DEBUG command directly, switching to debugging mode as needed.\n        (Reported by Paul Kulchenko, fixed by Salvatore Sanfilippo)\n* [FIX] Redis-trib is now able to fix more errors. A new CLUSTER subcommand\n        called BUMPEPOCH was introduced in order to support new modes\n        for the \"fix\" subcommand. (Salvatore Sanfilippo)\n* [NEW] Redis proctected mode: this feature improves Redis security and makes\n        harder to run Redis in a configuration that is unsecure because no\n        firewalling was used in order to protect Redis from external accesses.\n        See this Reddit post for more info: https://www.reddit.com/r/redis/comments/3zv85m/new_security_feature_redis_protected_mode/ (Salvatore Sanfilippo)\n* [NEW] Cluster/Sentinel tests now use OSX leak to perform leak detection\n        at the end of every unit. (Salvatore Sanfilippo)\n* [NEW] Detect and show server crashes during Cluster/Sentinel tests.\n        (Salvatore Sanfilippo)\n* [NEW] More reliable Cluster/Sentinel test becuase of timing errors and\n        -LOADING errors. (Salvatore Sanfilippo)\n\n--[ Redis 3.2.0 RC1 (version 3.1.101) ] Release date: 23 dec 2015\n\nThis is the first release candidate of Redis 3.2. The changelog above shows\nwhat's new in this release. In the next of the following weeks we'll test\nin depth every feature and we'll release new RCs as bugs are discovered\nand fixed. Note that while 3.2 looks solid already, it contains many changes\nto its internals. It's still fresh code compared to 3.0.\n\nGeneral changes:\n\n* [NEW] Lua scripts \"effect replication\". Makes possible to write scripts\n        with side effects, use of random commands, and so forth.\n        (Salvatore Sanfilippo)\n* [NEW] Lua scripts selective replication. Makes possible to replicate to\n        slaves and AOF only selected parts of a script. (Design by\n        Yossi Gottlieb and Salvatore Sanfilippo, implemented by Salvatore)\n* [NEW] Geo indexing support via GEOADD, GEORADIUS and other commands.\n        See http://redis.io/commands/geoadd for more information.\n        (Initially implemented in a fork of Redis called \"Ardb\".\n         Matt Stancliff \"imported back\" the work to Redis and created the\n         initial API and implementation. Salvatore Sanfilippo modified\n         the API and the implementation, fixed bugs, improved performances\n         and unified the duplicated code with t_zset.c)\n* [NEW] Lua debugger. A complete stepping, remote debugger for Lua scripts.\n        Video here: https://www.youtube.com/watch?v=IMvRfStaoyM\n        (Salvatore Sanfilippo with many feedbacks and testing from\n         Itamar Haber)\n* [NEW] SDS improvements for speed and maximum string length.\n        This makes Redis more memory efficient in different use cases.\n        (Design and implementation by Oran Agra, some additional work\n         by Salvatore Sanfilippo)\n* [NEW] Modify Jemalloc size classes to make certain Redis objects fit\n        better, improving memory efficiency. (Oran Agra)\n* [NEW] Better consistency behavior between masters and slaves for expired\n        keys. The slaves are only able to logically consider a key expired\n        even before receiving the `DEL` command from the master. This avoids\n        the delay there is sometimes between the natural expire of the key\n        and the moment the slave is notified. (Salvatore Sanfilippo)\n* [NEW] Support daemon supervision by upstart or systemd (Pierre-Yves Ritschard)\n* [NEW] New encoding for the List type: Quicklists. Very important memory\n        savings and storage space in RDB gains (up to 10x sometimes).\n        (Design and implementation by Matt Stancliff. RDB storage reworked\n         by Salvatore Sanfilippo)\n* [NEW] SPOP with optional count argument. (Initial implementation by\n        Alon Diamant, mostly reimplemented by Salvatore Sanfilippo for speed\n        and in order to make the replication of a this class of commands,\n        having as logical effect the execution of multiple commands, possible).\n* [NEW] Support for RDB AUX fields. Now RDB files contain additional info\n        like the creation date, version of Redis generating it and so forth.\n        (Salvatore Sanfilippo)\n* [NEW] Faster RDB loading via the RESIZEDB opcode to avoid useless hash tables\n        rehashings. (Salvatore Sanfilippo)\n* [NEW] HSTRLEN command. (@landmime and Salvatore Sanfilippo)\n* [NEW] CONFIG SET/GET implementations refactored, partially rewritten,\n        now exposing more config options. (Salvatore Sanfilippo)\n* [NEW] CLUSTER NODES major speedup. (Salvatore Sanfilippo)\n* [NEW] CLIENT KILL TYPE MASTER, to kill (disconnect) masters from slaves.\n        (Salvatore Sanfilippo)\n* [NEW] Jemalloc updated to 4.0.3 (Salvatore Sanfilippo)\n* [NEW] DEBUG RESTART/CRASH-AND-RECOVER [delay] (Salvatore Sanfilippo)\n* [NEW] CLIENT REPLY command implemented: ON, OFF and SKIP modes.\n        (Salvatore Sanfilippo)\n* [NEW] Crash report produced by Redis on crash improved. (Salvatore Sanfilippo)\n* [NEW] Better memory test on crash. (Salvatore Sanfilippo)\n\nRedis Cluster changes:\n\nAll the Redis Cluster changes in 3.2 were backported to 3.0, so there is\ntechnically nothing new for now in this release. The most important things\nare:\n\n* Cluster rebalancing.\n* A pipelined MIGRATE command which is 10x faster and makes resharding\n  and rebalancing faster.\n* Improved replicas migration.\n* As a side effect of quicklists encoding (see above items), moving big\n  lists between nodes is now a lot faster.\n\nRedis Sentinel changes:\n\n* [NEW] Sentinel connection sharing. Makes Sentinels able to scale to\n        monitor many masters. (Salvatore Sanfilippo)\n* [NEW] New SENTINEL INFO-CACHE command. (Matt Stancliff)\n* More things backported to Redis 3.0 in the past, so no longer news of 3.2.\n\nMigrating from 3.0 to 3.2\n=========================\n\nRedis 3.0 is mostly a strict subset of 3.2, you should not have any problem\nupgrading your application from 3.0 to 3.2. However this is a list of small\nnon-backward compatible changes introduced in the 3.2 release:\n\n* The default configuration file now binds to 127.0.0.1.\n* Slaves try to no longer expose stale data about already expired keys.\n* The RDB format changed. Redis 3.2 is still able to read 3.0 (and all the\n  past versions) files, but not the other way around.\n* Behavior on crash may be different. The crash log format changed and\n  the memory test executed is now different.\n\n--------------------------------------------------------------------------------\n\nCredits: For each release, a list of changes with the relative author is\nprovided. Where not specified the implementation and design is done by\nSalvatore Sanfilippo. Thanks to Redis Labs for making all this possible.\nAlso many thanks to all the other contributors and the amazing community\nwe have.\n\nCommit messages may contain additional credits.\n\nCheers,\nSalvatore\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/0000-redis.patch",
    "content": "diff --git a/extern/redis-3.2.4/src/Makefile b/extern/redis-3.2.4/src/Makefile\nindex 648127a..b9fc17e 100644\n--- a/extern/redis-3.2.4/src/Makefile\n+++ b/extern/redis-3.2.4/src/Makefile\n@@ -117,7 +117,7 @@ endif\n \n REDIS_SERVER_NAME=redis-server\n REDIS_SENTINEL_NAME=redis-sentinel\n-REDIS_SERVER_OBJ=adlist.o quicklist.o ae.o anet.o dict.o server.o sds.o zmalloc.o lzf_c.o lzf_d.o pqsort.o zipmap.o sha1.o ziplist.o release.o networking.o util.o object.o db.o replication.o rdb.o t_string.o t_list.o t_set.o t_zset.o t_hash.o config.o aof.o pubsub.o multi.o debug.o sort.o intset.o syncio.o cluster.o crc16.o endianconv.o slowlog.o scripting.o bio.o rio.o rand.o memtest.o crc64.o bitops.o sentinel.o notify.o setproctitle.o blocked.o hyperloglog.o latency.o sparkline.o redis-check-rdb.o geo.o\n+REDIS_SERVER_OBJ=adlist.o quicklist.o ae.o anet.o dict.o server.o sds.o zmalloc.o lzf_c.o lzf_d.o pqsort.o zipmap.o sha1.o ziplist.o release.o networking.o util.o object.o db.o replication.o rdb.o t_string.o t_list.o t_set.o t_zset.o t_hash.o config.o aof.o pubsub.o multi.o debug.o sort.o intset.o syncio.o cluster.o crc16.o endianconv.o slowlog.o scripting.o bio.o rio.o rand.o memtest.o crc64.o bitops.o sentinel.o notify.o setproctitle.o blocked.o hyperloglog.o latency.o sparkline.o redis-check-rdb.o geo.o slots.o crc32.o\n REDIS_GEOHASH_OBJ=../deps/geohash-int/geohash.o ../deps/geohash-int/geohash_helper.o\n REDIS_CLI_NAME=redis-cli\n REDIS_CLI_OBJ=anet.o adlist.o redis-cli.o zmalloc.o release.o anet.o ae.o crc64.o\ndiff --git a/extern/redis-3.2.4/src/Makefile.dep b/extern/redis-3.2.4/src/Makefile.dep\nindex 9af8331..ddedf6a 100644\n--- a/extern/redis-3.2.4/src/Makefile.dep\n+++ b/extern/redis-3.2.4/src/Makefile.dep\n@@ -67,6 +67,8 @@ latency.o: latency.c server.h fmacros.h config.h solarisfixes.h \\\n lzf_c.o: lzf_c.c lzfP.h\n lzf_d.o: lzf_d.c lzfP.h\n memtest.o: memtest.c config.h\n+crc32.o: crc32.c\n+slots.o: slots.c server.h\n multi.o: multi.c server.h fmacros.h config.h solarisfixes.h \\\n  ../deps/lua/src/lua.h ../deps/lua/src/luaconf.h ae.h sds.h dict.h \\\n  adlist.h zmalloc.h anet.h ziplist.h intset.h version.h util.h latency.h \\\ndiff --git a/extern/redis-3.2.4/src/crc32.c b/extern/redis-3.2.4/src/crc32.c\nnew file mode 100644\nindex 0000000..cc7ae86\n--- /dev/null\n+++ b/extern/redis-3.2.4/src/crc32.c\n@@ -0,0 +1,41 @@\n+#include <stdint.h>\n+\n+static const uint32_t IEEE_POLY = 0xedb88320;\n+\n+static uint32_t crc32tab[256];\n+\n+static void\n+crc32_tabinit(uint32_t poly) {\n+    int i, j;\n+    for (i = 0; i < 256; i ++) {\n+        uint32_t crc = i;\n+        for (j = 0; j < 8; j ++) {\n+            if (crc & 1) {\n+                crc = (crc >> 1) ^ poly;\n+            } else {\n+                crc = (crc >> 1);\n+            }\n+        }\n+        crc32tab[i] = crc;\n+    }\n+}\n+\n+void\n+crc32_init() {\n+    crc32_tabinit(IEEE_POLY);\n+}\n+\n+static uint32_t\n+crc32_update(uint32_t crc, const char *buf, int len) {\n+    int i;\n+    crc = ~crc;\n+    for (i = 0; i < len; i ++) {\n+        crc = crc32tab[(uint8_t)((char)crc ^ buf[i])] ^ (crc >> 8);\n+    }\n+    return ~crc;\n+}\n+\n+uint32_t\n+crc32_checksum(const char *buf, int len) {\n+    return crc32_update(0, buf, len);\n+}\ndiff --git a/extern/redis-3.2.4/src/db.c b/extern/redis-3.2.4/src/db.c\nindex fba731c..fa79e54 100644\n--- a/extern/redis-3.2.4/src/db.c\n+++ b/extern/redis-3.2.4/src/db.c\n@@ -158,6 +158,17 @@ void dbAdd(redisDb *db, robj *key, robj *val) {\n     sds copy = sdsdup(key->ptr);\n     int retval = dictAdd(db->dict, copy, val);\n \n+    do {\n+        uint32_t crc;\n+        int hastag;\n+        int slot = slots_num(key->ptr, &crc, &hastag);\n+        dictAdd(db->hash_slots[slot], copy, (void *)(long)crc);\n+        if (hastag) {\n+            incrRefCount(key);\n+            zslInsert(db->tagged_keys, (double)crc, key);\n+        }\n+    } while (0);\n+\n     serverAssertWithInfo(NULL,key,retval == DICT_OK);\n     if (val->type == OBJ_LIST) signalListAsReady(db, key);\n     if (server.cluster_enabled) slotToKeyAdd(key);\n@@ -227,6 +238,18 @@ int dbDelete(redisDb *db, robj *key) {\n     /* Deleting an entry from the expires dict will not free the sds of\n      * the key, because it is shared with the main dictionary. */\n     if (dictSize(db->expires) > 0) dictDelete(db->expires,key->ptr);\n+\n+    do {\n+        uint32_t crc;\n+        int hastag;\n+        int slot = slots_num(key->ptr, &crc, &hastag);\n+        if (dictDelete(db->hash_slots[slot], key->ptr) == DICT_OK) {\n+            if (hastag) {\n+                zslDelete(db->tagged_keys, (double)crc, key);\n+            }\n+        }\n+    } while (0);\n+\n     if (dictDelete(db->dict,key->ptr) == DICT_OK) {\n         if (server.cluster_enabled) slotToKeyDel(key);\n         return 1;\n@@ -274,11 +297,18 @@ robj *dbUnshareStringValue(redisDb *db, robj *key, robj *o) {\n }\n \n long long emptyDb(void(callback)(void*)) {\n-    int j;\n+    int i, j;\n     long long removed = 0;\n \n     for (j = 0; j < server.dbnum; j++) {\n         removed += dictSize(server.db[j].dict);\n+        for (i = 0; i < HASH_SLOTS_SIZE; i ++) {\n+            dictEmpty(server.db[j].hash_slots[i], NULL);\n+        }\n+        if (server.db[j].tagged_keys->length != 0) {\n+            zslFree(server.db[j].tagged_keys);\n+            server.db[j].tagged_keys = zslCreate();\n+        }\n         dictEmpty(server.db[j].dict,callback);\n         dictEmpty(server.db[j].expires,callback);\n     }\n@@ -315,8 +345,16 @@ void signalFlushedDb(int dbid) {\n  *----------------------------------------------------------------------------*/\n \n void flushdbCommand(client *c) {\n+    int i;\n     server.dirty += dictSize(c->db->dict);\n     signalFlushedDb(c->db->id);\n+    for (i = 0; i < HASH_SLOTS_SIZE; i ++) {\n+        dictEmpty(c->db->hash_slots[i], NULL);\n+    }\n+    if (c->db->tagged_keys->length != 0) {\n+        zslFree(c->db->tagged_keys);\n+        c->db->tagged_keys = zslCreate();\n+    }\n     dictEmpty(c->db->dict,NULL);\n     dictEmpty(c->db->expires,NULL);\n     if (server.cluster_enabled) slotToKeyFlush();\n@@ -724,7 +762,15 @@ void shutdownCommand(client *c) {\n      * Also when in Sentinel mode clear the SAVE flag and force NOSAVE. */\n     if (server.loading || server.sentinel_mode)\n         flags = (flags & ~SHUTDOWN_SAVE) | SHUTDOWN_NOSAVE;\n-    if (prepareForShutdown(flags) == C_OK) exit(0);\n+    if (prepareForShutdown(flags) == C_OK) {\n+        for (int j = 0; j < server.dbnum; j ++) {\n+            for (int i = 0; i < HASH_SLOTS_SIZE; i ++) {\n+                dictRelease(server.db[j].hash_slots[i]);\n+            }\n+            zslFree(server.db[j].tagged_keys);\n+        }\n+        exit(0);\n+    }\n     addReplyError(c,\"Errors trying to SHUTDOWN. Check logs.\");\n }\n \ndiff --git a/extern/redis-3.2.4/src/server.c b/extern/redis-3.2.4/src/server.c\nindex 408d03f..6ce92a1 100644\n--- a/extern/redis-3.2.4/src/server.c\n+++ b/extern/redis-3.2.4/src/server.c\n@@ -294,7 +294,16 @@ struct redisCommand redisCommandTable[] = {\n     {\"pfcount\",pfcountCommand,-2,\"r\",0,NULL,1,-1,1,0,0},\n     {\"pfmerge\",pfmergeCommand,-2,\"wm\",0,NULL,1,-1,1,0,0},\n     {\"pfdebug\",pfdebugCommand,-3,\"w\",0,NULL,0,0,0,0,0},\n-    {\"latency\",latencyCommand,-2,\"aslt\",0,NULL,0,0,0,0,0}\n+    {\"latency\",latencyCommand,-2,\"aslt\",0,NULL,0,0,0,0,0},\n+    {\"slotsinfo\",slotsinfoCommand,-1,\"rF\",0,NULL,0,0,0,0,0},\n+    {\"slotsdel\",slotsdelCommand,-2,\"w\",0,NULL,1,-1,1,0,0},\n+    {\"slotsmgrtslot\",slotsmgrtslotCommand,5,\"aw\",0,NULL,0,0,0,0,0},\n+    {\"slotsmgrtone\",slotsmgrtoneCommand,5,\"aw\",0,NULL,0,0,0,0,0},\n+    {\"slotsmgrttagslot\",slotsmgrttagslotCommand,5,\"aw\",0,NULL,0,0,0,0,0},\n+    {\"slotsmgrttagone\",slotsmgrttagoneCommand,5,\"aw\",0,NULL,0,0,0,0,0},\n+    {\"slotshashkey\",slotshashkeyCommand,-1,\"rF\",0,NULL,0,0,0,0,0},\n+    {\"slotscheck\",slotscheckCommand,0,\"r\",0,NULL,0,0,0,0,0},\n+    {\"slotsrestore\",slotsrestoreCommand,-4,\"awm\",0,NULL,1,1,1,0,0},\n };\n \n struct evictionPoolEntry *evictionPoolAlloc(void);\n@@ -562,6 +571,15 @@ dictType dbDictType = {\n     dictObjectDestructor   /* val destructor */\n };\n \n+dictType hashSlotType = {\n+    dictSdsHash,                /* hash function */\n+    NULL,                       /* key dup */\n+    NULL,                       /* val dup */\n+    dictSdsKeyCompare,          /* key compare */\n+    NULL,                       /* key destructor */\n+    NULL                        /* val destructor */\n+};\n+\n /* server.lua_scripts sha (as sds string) -> scripts (as robj) cache. */\n dictType shaScriptObjectDictType = {\n     dictSdsCaseHash,            /* hash function */\n@@ -671,8 +689,15 @@ int htNeedsResize(dict *dict) {\n /* If the percentage of used slots in the HT reaches HASHTABLE_MIN_FILL\n  * we resize the hash table to save memory */\n void tryResizeHashTables(int dbid) {\n-    if (htNeedsResize(server.db[dbid].dict))\n+    if (htNeedsResize(server.db[dbid].dict)) {\n         dictResize(server.db[dbid].dict);\n+        for (int i = 0; i < HASH_SLOTS_SIZE; i ++) {\n+            dict *d = server.db[dbid].hash_slots[i];\n+            if (htNeedsResize(d)) {\n+                dictResize(d);\n+            }\n+        }\n+    }\n     if (htNeedsResize(server.db[dbid].expires))\n         dictResize(server.db[dbid].expires);\n }\n@@ -688,6 +713,12 @@ int incrementallyRehash(int dbid) {\n     /* Keys dictionary */\n     if (dictIsRehashing(server.db[dbid].dict)) {\n         dictRehashMilliseconds(server.db[dbid].dict,1);\n+        for (int i = 0; i < HASH_SLOTS_SIZE; i ++) {\n+            dict *d = server.db[dbid].hash_slots[i];\n+            if (dictIsRehashing(d)) {\n+                dictRehashMilliseconds(d, 1);\n+            }\n+        }\n         return 1; /* already used our millisecond for this loop... */\n     }\n     /* Expires */\n@@ -1281,6 +1312,10 @@ int serverCron(struct aeEventLoop *eventLoop, long long id, void *clientData) {\n         if (server.sentinel_mode) sentinelTimer();\n     }\n \n+    run_with_period(1000) {\n+        slotsmgrt_cleanup();\n+    }\n+\n     /* Cleanup expired MIGRATE cached sockets. */\n     run_with_period(1000) {\n         migrateCloseTimedoutSockets();\n@@ -1532,6 +1567,8 @@ void initServerConfig(void) {\n     server.next_client_id = 1; /* Client IDs, start from 1 .*/\n     server.loading_process_events_interval_bytes = (1024*1024*2);\n \n+    server.slotsmgrt_cached_sockfds = dictCreate(&migrateCacheDictType, NULL);\n+\n     server.lruclock = getLRUClock();\n     resetServerSaveParams();\n \n@@ -1858,12 +1895,14 @@ void resetServerStats(void) {\n }\n \n void initServer(void) {\n-    int j;\n+    int i, j;\n \n     signal(SIGHUP, SIG_IGN);\n     signal(SIGPIPE, SIG_IGN);\n     setupSignalHandlers();\n \n+    crc32_init();\n+\n     if (server.syslog_enabled) {\n         openlog(server.syslog_ident, LOG_PID | LOG_NDELAY | LOG_NOWAIT,\n             server.syslog_facility);\n@@ -1922,6 +1961,10 @@ void initServer(void) {\n         server.db[j].eviction_pool = evictionPoolAlloc();\n         server.db[j].id = j;\n         server.db[j].avg_ttl = 0;\n+        for (i = 0; i < HASH_SLOTS_SIZE; i ++) {\n+            server.db[j].hash_slots[i] = dictCreate(&hashSlotType, NULL);\n+        }\n+        server.db[j].tagged_keys = zslCreate();\n     }\n     server.pubsub_channels = dictCreate(&keylistDictType,NULL);\n     server.pubsub_patterns = listCreate();\ndiff --git a/extern/redis-3.2.4/src/server.h b/extern/redis-3.2.4/src/server.h\nindex 1a26ec4..f811000 100644\n--- a/extern/redis-3.2.4/src/server.h\n+++ b/extern/redis-3.2.4/src/server.h\n@@ -498,6 +498,14 @@ struct evictionPoolEntry {\n     sds key;                    /* Key name. */\n };\n \n+void crc32_init();\n+uint32_t crc32_checksum(const char *buf, int len);\n+\n+#define HASH_SLOTS_MASK 0x000003ff\n+#define HASH_SLOTS_SIZE (HASH_SLOTS_MASK + 1)\n+\n+struct zskiplist;\n+\n /* Redis database representation. There are multiple databases identified\n  * by integers from 0 (the default database) up to the max configured\n  * database. The database number is the 'id' field in the structure. */\n@@ -507,6 +515,8 @@ typedef struct redisDb {\n     dict *blocking_keys;        /* Keys with clients waiting for data (BLPOP) */\n     dict *ready_keys;           /* Blocked keys that received a PUSH */\n     dict *watched_keys;         /* WATCHED keys for MULTI/EXEC CAS */\n+    dict *hash_slots[HASH_SLOTS_SIZE];\n+    struct zskiplist *tagged_keys;\n     struct evictionPoolEntry *eviction_pool;    /* Eviction pool of keys */\n     int id;                     /* Database ID */\n     long long avg_ttl;          /* Average TTL, just for stats */\n@@ -741,6 +751,7 @@ struct redisServer {\n     int clients_paused;         /* True if clients are currently paused */\n     mstime_t clients_pause_end_time; /* Time when we undo clients_paused */\n     char neterr[ANET_ERR_LEN];   /* Error buffer for anet.c */\n+    dict *slotsmgrt_cached_sockfds;\n     dict *migrate_cached_sockets;/* MIGRATE cached sockets */\n     uint64_t next_client_id;    /* Next client unique ID. Incremental. */\n     int protected_mode;         /* Don't accept external connections. */\n@@ -1645,6 +1656,19 @@ void pfcountCommand(client *c);\n void pfmergeCommand(client *c);\n void pfdebugCommand(client *c);\n void latencyCommand(client *c);\n+void slotsinfoCommand(client *c);\n+void slotsdelCommand(client *c);\n+void slotsmgrtslotCommand(client *c);\n+void slotsmgrtoneCommand(client *c);\n+void slotsmgrttagslotCommand(client *c);\n+void slotsmgrttagoneCommand(client *c);\n+void slotshashkeyCommand(client *c);\n+void slotscheckCommand(client *c);\n+void slotsrestoreCommand(client *c);\n+\n+void slotsmgrt_cleanup();\n+int slots_num(const sds s, uint32_t *pcrc, int *phastag);\n+\n \n #if defined(__GNUC__)\n void *calloc(size_t count, size_t size) __attribute__ ((deprecated));\ndiff --git a/extern/redis-3.2.4/src/slots.c b/extern/redis-3.2.4/src/slots.c\nnew file mode 100644\nindex 0000000..ff23492\n--- /dev/null\n+++ b/extern/redis-3.2.4/src/slots.c\n@@ -0,0 +1,817 @@\n+#include \"server.h\"\n+\n+extern void createDumpPayload(rio *payload, robj *o);\n+extern int verifyDumpPayload(unsigned char *p, size_t len);\n+\n+static void *\n+slots_tag(const sds s, int *plen) {\n+    int i, j, n = sdslen(s);\n+    for (i = 0; i < n && s[i] != '{'; i ++) {}\n+    if (i == n) {\n+        return NULL;\n+    }\n+    i ++;\n+    for (j = i; j < n && s[j] != '}'; j ++) {}\n+    if (j == n) {\n+        return NULL;\n+    }\n+    if (plen != NULL) {\n+        *plen = j - i;\n+    }\n+    return s + i;\n+}\n+\n+int\n+slots_num(const sds s, uint32_t *pcrc, int *phastag) {\n+    int taglen;\n+    int hastag = 0;\n+    void *tag = slots_tag(s, &taglen);\n+    if (tag == NULL) {\n+        tag = s, taglen = sdslen(s);\n+    } else {\n+        hastag = 1;\n+    }\n+    uint32_t crc = crc32_checksum(tag, taglen);\n+    if (pcrc != NULL) {\n+        *pcrc = crc;\n+    }\n+    if (phastag != NULL) {\n+        *phastag = hastag;\n+    }\n+    return crc & HASH_SLOTS_MASK;\n+}\n+\n+static int\n+parse_int(client *c, robj *obj, int *p) {\n+    long v;\n+    if (getLongFromObjectOrReply(c, obj, &v, NULL) != C_OK) {\n+        return -1;\n+    }\n+    *p = v;\n+    return 0;\n+}\n+\n+static int\n+parse_timeout(client *c, robj *obj, int *p) {\n+    int v;\n+    if (parse_int(c, obj, &v) != 0) {\n+        return -1;\n+    }\n+    if (v < 0) {\n+        addReplyErrorFormat(c, \"invalid timeout = %d\", v);\n+        return -1;\n+    }\n+    *p = (v == 0) ? 100 : v;\n+    return 0;\n+}\n+\n+static int\n+parse_slot(client *c, robj *obj, int *p) {\n+    int v;\n+    if (parse_int(c, obj, &v) != 0) {\n+        return -1;\n+    }\n+    if (v < 0 || v >= HASH_SLOTS_SIZE) {\n+        addReplyErrorFormat(c, \"invalid slot number = %d\", v);\n+        return -1;\n+    }\n+    *p = v;\n+    return 0;\n+}\n+\n+/* *\n+ * slotshashkey [key1 key2...]\n+ * */\n+void\n+slotshashkeyCommand(client *c) {\n+    int i;\n+    addReplyMultiBulkLen(c, c->argc - 1);\n+    for (i = 1; i < c->argc; i ++) {\n+        robj *key = c->argv[i];\n+        addReplyLongLong(c, slots_num(key->ptr, NULL, NULL));\n+    }\n+}\n+\n+/* *\n+ * slotsinfo [start] [count]\n+ * */\n+void\n+slotsinfoCommand(client *c) {\n+    int slots_slot[HASH_SLOTS_SIZE];\n+    int slots_size[HASH_SLOTS_SIZE];\n+    int n = 0, beg = 0, end = HASH_SLOTS_SIZE;\n+    if (c->argc >= 2) {\n+        if (parse_slot(c, c->argv[1], &beg) != 0) {\n+            return;\n+        }\n+    }\n+    if (c->argc >= 3) {\n+        int v;\n+        if (parse_int(c, c->argv[2], &v) != 0) {\n+            return;\n+        }\n+        if (v < 0) {\n+            addReplyErrorFormat(c, \"invalid slot count = %d\", v);\n+            return;\n+        }\n+        if (beg + v < end) {\n+            end = beg + v;\n+        }\n+    }\n+    if (c->argc >= 4) {\n+        addReplyErrorFormat(c, \"wrong number of arguments for 'slotsinfo' command\");\n+        return;\n+    }\n+    int i;\n+    for (i = beg; i < end; i ++) {\n+        int s = dictSize(c->db->hash_slots[i]);\n+        if (s == 0) {\n+            continue;\n+        }\n+        slots_slot[n] = i;\n+        slots_size[n] = s;\n+        n ++;\n+    }\n+    addReplyMultiBulkLen(c, n);\n+    for (i = 0; i < n; i ++) {\n+        addReplyMultiBulkLen(c, 2);\n+        addReplyLongLong(c, slots_slot[i]);\n+        addReplyLongLong(c, slots_size[i]);\n+    }\n+}\n+\n+typedef struct {\n+    int fd;\n+    int db;\n+    int authorized;\n+    time_t lasttime;\n+} slotsmgrt_sockfd;\n+\n+static slotsmgrt_sockfd *\n+slotsmgrt_get_sockfd(client *c, sds host, sds port, int timeout) {\n+    sds name = sdsempty();\n+    name = sdscatlen(name, host, sdslen(host));\n+    name = sdscatlen(name, \":\", 1);\n+    name = sdscatlen(name, port, sdslen(port));\n+\n+    slotsmgrt_sockfd *pfd = dictFetchValue(server.slotsmgrt_cached_sockfds, name);\n+    if (pfd != NULL) {\n+        sdsfree(name);\n+        pfd->lasttime = server.unixtime;\n+        return pfd;\n+    }\n+\n+    int fd = anetTcpNonBlockConnect(server.neterr, host, atoi(port));\n+    if (fd == -1) {\n+        serverLog(LL_WARNING, \"slotsmgrt: connect to target %s:%s, error = '%s'\",\n+                host, port, server.neterr);\n+        sdsfree(name);\n+        addReplyErrorFormat(c,\"Can't connect to target node: %s\", server.neterr);\n+        return NULL;\n+    }\n+    anetEnableTcpNoDelay(server.neterr, fd);\n+    if ((aeWait(fd, AE_WRITABLE, timeout) & AE_WRITABLE) == 0) {\n+        serverLog(LL_WARNING, \"slotsmgrt: connect to target %s:%s, aewait error = '%s'\",\n+                host, port, server.neterr);\n+        sdsfree(name);\n+        close(fd);\n+        addReplySds(c, sdsnew(\"-IOERR error or timeout connecting to the client\\r\\n\"));\n+        return NULL;\n+    }\n+    serverLog(LL_WARNING, \"slotsmgrt: connect to target %s:%s\", host, port);\n+\n+    pfd = zmalloc(sizeof(*pfd));\n+    pfd->fd = fd;\n+    pfd->db = -1;\n+    pfd->authorized = (server.requirepass == NULL) ? 1 : 0;\n+    pfd->lasttime = server.unixtime;\n+    dictAdd(server.slotsmgrt_cached_sockfds, name, pfd);\n+    return pfd;\n+}\n+\n+static void\n+slotsmgrt_close_socket(sds host, sds port) {\n+    sds name = sdsempty();\n+    name = sdscatlen(name, host, sdslen(host));\n+    name = sdscatlen(name, \":\", 1);\n+    name = sdscatlen(name, port, sdslen(port));\n+\n+    slotsmgrt_sockfd *pfd = dictFetchValue(server.slotsmgrt_cached_sockfds, name);\n+    if (pfd == NULL) {\n+        serverLog(LL_WARNING, \"slotsmgrt: close target %s:%s again\", host, port);\n+        sdsfree(name);\n+        return;\n+    } else {\n+        serverLog(LL_WARNING, \"slotsmgrt: close target %s:%s\", host, port);\n+    }\n+    dictDelete(server.slotsmgrt_cached_sockfds, name);\n+    close(pfd->fd);\n+    zfree(pfd);\n+    sdsfree(name);\n+}\n+\n+void\n+slotsmgrt_cleanup() {\n+    dictIterator *di = dictGetSafeIterator(server.slotsmgrt_cached_sockfds);\n+    dictEntry *de;\n+    while((de = dictNext(di)) != NULL) {\n+        slotsmgrt_sockfd *pfd = dictGetVal(de);\n+        if ((server.unixtime - pfd->lasttime) > 15) {\n+            serverLog(LL_WARNING, \"slotsmgrt: timeout target %s, lasttime = %ld, now = %ld\",\n+                   (char *)dictGetKey(de), pfd->lasttime, server.unixtime);\n+            dictDelete(server.slotsmgrt_cached_sockfds, dictGetKey(de));\n+            close(pfd->fd);\n+            zfree(pfd);\n+        }\n+    }\n+    dictReleaseIterator(di);\n+}\n+\n+static int\n+slotsmgrt(client *c, sds host, sds port, slotsmgrt_sockfd *pfd, int db, int timeout, robj *keys[], robj *vals[], int n) {\n+    rio cmd;\n+    rioInitWithBuffer(&cmd, sdsempty());\n+\n+    int needauth = 0;\n+    if (pfd->authorized == 0 && server.requirepass != NULL) {\n+        needauth = 1;\n+        serverAssertWithInfo(c, NULL, rioWriteBulkCount(&cmd, '*', 2));\n+        serverAssertWithInfo(c, NULL, rioWriteBulkString(&cmd, \"AUTH\", 4));\n+        serverAssertWithInfo(c, NULL, rioWriteBulkString(&cmd, server.requirepass, strlen(server.requirepass)));\n+    }\n+\n+    int selectdb = 0;\n+    if (pfd->db != db) {\n+        selectdb = 1;\n+        serverAssertWithInfo(c, NULL, rioWriteBulkCount(&cmd, '*', 2));\n+        serverAssertWithInfo(c, NULL, rioWriteBulkString(&cmd, \"SELECT\", 6));\n+        serverAssertWithInfo(c, NULL, rioWriteBulkLongLong(&cmd, db));\n+    }\n+\n+    serverAssertWithInfo(c, NULL, rioWriteBulkCount(&cmd, '*', 1 + 3 * n));\n+    serverAssertWithInfo(c, NULL, rioWriteBulkString(&cmd, \"SLOTSRESTORE\", 12));\n+\n+    sds onekey = NULL;\n+    for (int i = 0; i < n; i ++) {\n+        robj *key = keys[i], *val = vals[i];\n+        long long ttl = 0, expireat = getExpire(c->db, key);\n+        if (expireat != -1) {\n+            ttl = expireat - mstime();\n+            if (ttl < 1) {\n+                ttl = 1;\n+            }\n+        }\n+        sds skey = key->ptr;\n+        serverAssertWithInfo(c, NULL, rioWriteBulkString(&cmd, skey, sdslen(skey)));\n+        serverAssertWithInfo(c, NULL, rioWriteBulkLongLong(&cmd, ttl));\n+        do {\n+            rio pld;\n+            createDumpPayload(&pld, val);\n+            sds buf = pld.io.buffer.ptr;\n+            serverAssertWithInfo(c, NULL, rioWriteBulkString(&cmd, buf, sdslen(buf)));\n+            sdsfree(buf);\n+        } while (0);\n+        if (onekey == NULL) {\n+            onekey = skey;\n+        }\n+    }\n+\n+    do {\n+        sds buf = cmd.io.buffer.ptr;\n+        size_t pos = 0, towrite;\n+        int nwritten = 0;\n+        while ((towrite = sdslen(buf) - pos) > 0) {\n+            towrite = (towrite > (64 * 1024) ? (64 * 1024) : towrite);\n+            nwritten = syncWrite(pfd->fd, buf + pos, towrite, timeout);\n+            if (nwritten != (signed)towrite) {\n+                serverLog(LL_WARNING, \"slotsmgrt: writing to target %s:%s, error '%s', \"\n+                        \"nkeys = %d, onekey = '%s', cmd.len = %ld, pos = %ld, towrite = %ld\",\n+                        host, port, server.neterr, n, onekey, sdslen(buf), pos, towrite);\n+                addReplySds(c, sdsnew(\"-IOERR error or timeout writing to target\\r\\n\"));\n+                sdsfree(buf);\n+                return -1;\n+            }\n+            pos += nwritten;\n+        }\n+        sdsfree(buf);\n+    } while (0);\n+\n+    do {\n+        char buf[1024];\n+        if (needauth) {\n+            if (syncReadLine(pfd->fd, buf, sizeof(buf), timeout) <= 0) {\n+                serverLog(LL_WARNING, \"slotsmgrt: auth failed, reading from target %s:%s: nkeys = %d, onekey = '%s', error = '%s'\",\n+                        host, port, n, onekey, server.neterr);\n+                addReplySds(c, sdsnew(\"-IOERR error or timeout reading from target\\r\\n\"));\n+                return -1;\n+            }\n+            if (buf[0] != '+') {\n+                serverLog(LL_WARNING, \"slotsmgrt: auth failed, reading from target %s:%s: nkeys = %d, onekey = '%s', response = '%s'\",\n+                        host, port, n, onekey, buf);\n+                addReplyError(c, \"error on slotsrestore, auth failed\");\n+                return -1;\n+            }\n+            pfd->authorized = 1;\n+        }\n+\n+        if (selectdb) {\n+            if (syncReadLine(pfd->fd, buf, sizeof(buf), timeout) <= 0) {\n+                serverLog(LL_WARNING, \"slotsmgrt: select failed, reading from target %s:%s: nkeys = %d, onekey = '%s', error = '%s'\",\n+                        host, port, n, onekey, server.neterr);\n+                addReplySds(c, sdsnew(\"-IOERR error or timeout reading from target\\r\\n\"));\n+                return -1;\n+            }\n+            if (buf[0] != '+') {\n+                serverLog(LL_WARNING, \"slotsmgrt: select failed, reading from target %s:%s: nkeys = %d, onekey = '%s', response = '%s'\",\n+                        host, port, n, onekey, buf);\n+                addReplyError(c, \"error on slotsrestore, select failed\");\n+                return -1;\n+            }\n+            pfd->db = db;\n+        }\n+\n+        if (syncReadLine(pfd->fd, buf, sizeof(buf), timeout) <= 0) {\n+            serverLog(LL_WARNING, \"slotsmgrt: migration failed, reading from target %s:%s: nkeys = %d, onekey = '%s', error = '%s'\",\n+                    host, port, n, onekey, server.neterr);\n+            addReplySds(c, sdsnew(\"-IOERR error or timeout reading from target\\r\\n\"));\n+            return -1;\n+        }\n+        if (buf[0] == '-') {\n+            serverLog(LL_WARNING, \"slotsmgrt: migration failed, reading from target %s:%s: nkeys = %d, onekey = '%s', response = '%s'\",\n+                    host, port, n, onekey, buf);\n+            addReplyError(c, \"error on slotsrestore, migration failed\");\n+            return -1;\n+        }\n+    } while (0);\n+\n+    pfd->lasttime = server.unixtime;\n+\n+    serverLog(LL_VERBOSE, \"slotsmgrt: migrate to %s:%s, nkeys = %d, onekey = '%s'\", host, port, n, onekey);\n+    return 0;\n+}\n+\n+static void\n+slotsremove(client *c, robj **keys, int n, int rewrite) {\n+    for (int i = 0; i < n; i ++) {\n+        dbDelete(c->db, keys[i]);\n+        signalModifiedKey(c->db, keys[i]);\n+        server.dirty ++;\n+    }\n+    if (!rewrite) {\n+        return;\n+    }\n+    for (int i = 0; i < n; i ++) {\n+        incrRefCount(keys[i]);\n+    }\n+    for (int i = 0; i < c->argc; i ++) {\n+        decrRefCount(c->argv[i]);\n+    }\n+    zfree(c->argv);\n+    c->argc = n + 1;\n+    c->argv = zmalloc(sizeof(robj *) * c->argc);\n+    c->argv[0] = createStringObject(\"DEL\", 3);\n+    for (int i = 0; i < n; i ++) {\n+        c->argv[i + 1] = keys[i];\n+    }\n+    c->cmd = lookupCommandOrOriginal(c->argv[0]->ptr);\n+    serverAssertWithInfo(c, NULL, c->cmd != NULL);\n+}\n+\n+/* *\n+ * do migrate a key-value for slotsmgrt/slotsmgrtone commands\n+ * return value:\n+ *    -1 - error happens\n+ *   >=0 - # of success migration (0 or 1)\n+ * */\n+static int\n+slotsmgrtone_command(client *c, sds host, sds port, int timeout, robj *key) {\n+    slotsmgrt_sockfd *pfd = slotsmgrt_get_sockfd(c, host, port, timeout);\n+    if (pfd == NULL) {\n+        return -1;\n+    }\n+\n+    robj *val = lookupKeyWrite(c->db, key);\n+    if (val == NULL) {\n+        return 0;\n+    }\n+    robj *keys[] = {key};\n+    robj *vals[] = {val};\n+    if (slotsmgrt(c, host, port, pfd, c->db->id, timeout, keys, vals, 1) != 0) {\n+        slotsmgrt_close_socket(host, port);\n+        return -1;\n+    }\n+    slotsremove(c, keys, 1, 1);\n+    return 1;\n+}\n+\n+/* *\n+ * slotsmgrtslot host port timeout slot\n+ * */\n+void\n+slotsmgrtslotCommand(client *c) {\n+    sds host = c->argv[1]->ptr;\n+    sds port = c->argv[2]->ptr;\n+    int timeout, slot;\n+    if (parse_timeout(c, c->argv[3], &timeout) != 0) {\n+        return;\n+    }\n+    if (parse_slot(c, c->argv[4], &slot) != 0) {\n+        return;\n+    }\n+\n+    dict *d = c->db->hash_slots[slot];\n+    int succ = 0;\n+    do {\n+        const dictEntry *de = dictGetRandomKey(d);\n+        if (de == NULL) {\n+            break;\n+        }\n+        sds skey = dictGetKey(de);\n+        robj *key = createStringObject(skey, sdslen(skey));\n+        succ = slotsmgrtone_command(c, host, port, timeout, key);\n+        decrRefCount(key);\n+        if (succ < 0) {\n+            return;\n+        }\n+    } while (0);\n+    addReplyMultiBulkLen(c, 2);\n+    addReplyLongLong(c, succ);\n+    addReplyLongLong(c, dictSize(d));\n+}\n+\n+/* *\n+ * slotsmgrtone host port timeout key\n+ * */\n+void\n+slotsmgrtoneCommand(client *c) {\n+    sds host = c->argv[1]->ptr;\n+    sds port = c->argv[2]->ptr;\n+    int timeout;\n+    if (parse_timeout(c, c->argv[3], &timeout) != 0) {\n+        return;\n+    }\n+\n+    robj *key = c->argv[4];\n+    int succ = slotsmgrtone_command(c, host, port, timeout, key);\n+    if (succ < 0) {\n+        return;\n+    }\n+    addReplyLongLong(c, succ);\n+}\n+\n+static void\n+slotsScanSdsKeyCallback(void *l, const dictEntry *de) {\n+    sds skey = dictGetKey(de);\n+    robj *key = createStringObject(skey, sdslen(skey));\n+    listAddNodeTail((list *)l, key);\n+}\n+\n+/* *\n+ * slotsdel slot1 [slot2 ...]\n+ * */\n+void\n+slotsdelCommand(client *c) {\n+    int slots_slot[HASH_SLOTS_SIZE];\n+    int n = 0;\n+    if (c->argc <= 1) {\n+        addReplyErrorFormat(c, \"wrong number of arguments for 'slotsdel' command\");\n+        return;\n+    }\n+    int i;\n+    for (i = 1; i < c->argc; i ++) {\n+        int slot;\n+        if (parse_slot(c, c->argv[i], &slot) != 0) {\n+            return;\n+        }\n+        slots_slot[n] = slot;\n+        n ++;\n+    }\n+    for (i = 0; i < n; i ++) {\n+        dict *d = c->db->hash_slots[slots_slot[i]];\n+        int s = dictSize(d);\n+        if (s == 0) {\n+            continue;\n+        }\n+        list *l = listCreate();\n+        listSetFreeMethod(l, decrRefCountVoid);\n+        unsigned long cursor = 0;\n+        do {\n+            cursor = dictScan(d, cursor, slotsScanSdsKeyCallback, l);\n+        } while (cursor != 0);\n+        while (1) {\n+            listNode *head = listFirst(l);\n+            if (head == NULL) {\n+                break;\n+            }\n+            robj *key = listNodeValue(head);\n+            robj *keys[] = {key};\n+            slotsremove(c, keys, 1, 0);\n+            listDelNode(l, head);\n+        }\n+        listRelease(l);\n+    }\n+    addReplyMultiBulkLen(c, n);\n+    for (i = 0; i < n; i ++) {\n+        int n = slots_slot[i];\n+        int s = dictSize(c->db->hash_slots[n]);\n+        addReplyMultiBulkLen(c, 2);\n+        addReplyLongLong(c, n);\n+        addReplyLongLong(c, s);\n+    }\n+}\n+\n+/* *\n+ * slotscheck\n+ * */\n+void\n+slotscheckCommand(client *c) {\n+    sds bug = NULL;\n+    int i;\n+    for (i = 0; i < HASH_SLOTS_SIZE && bug == NULL; i ++) {\n+        dict *d = c->db->hash_slots[i];\n+        if (dictSize(d) == 0) {\n+            continue;\n+        }\n+        list *l = listCreate();\n+        listSetFreeMethod(l, decrRefCountVoid);\n+        unsigned long cursor = 0;\n+        do {\n+            cursor = dictScan(d, cursor, slotsScanSdsKeyCallback, l);\n+            while (1) {\n+                listNode *head = listFirst(l);\n+                if (head == NULL) {\n+                    break;\n+                }\n+                robj *key = listNodeValue(head);\n+                if (lookupKeyRead(c->db, key) == NULL) {\n+                    if (bug == NULL) {\n+                        bug = sdsdup(key->ptr);\n+                    }\n+                }\n+                listDelNode(l, head);\n+            }\n+        } while (cursor != 0 && bug == NULL);\n+        listRelease(l);\n+    }\n+    if (bug != NULL) {\n+        addReplyErrorFormat(c, \"step 1, miss = '%s'\", bug);\n+        sdsfree(bug);\n+        return;\n+    }\n+    do {\n+        dict *d = c->db->dict;\n+        if (dictSize(d) == 0) {\n+            break;\n+        }\n+        list *l = listCreate();\n+        listSetFreeMethod(l, decrRefCountVoid);\n+        unsigned long cursor = 0;\n+        do {\n+            cursor = dictScan(d, cursor, slotsScanSdsKeyCallback, l);\n+            while (1) {\n+                listNode *head = listFirst(l);\n+                if (head == NULL) {\n+                    break;\n+                }\n+                robj *key = listNodeValue(head);\n+                int slot = slots_num(key->ptr, NULL, NULL);\n+                if (dictFind(c->db->hash_slots[slot], key->ptr) == NULL) {\n+                    if (bug == NULL) {\n+                        bug = sdsdup(key->ptr);\n+                    }\n+                }\n+                listDelNode(l, head);\n+            }\n+        } while (cursor != 0 && bug == NULL);\n+        listRelease(l);\n+    } while (0);\n+    if (bug != NULL) {\n+        addReplyErrorFormat(c, \"step 2, miss = '%s'\", bug);\n+        sdsfree(bug);\n+        return;\n+    }\n+    zskiplistNode *node = c->db->tagged_keys->header->level[0].forward;\n+    while (node != NULL && bug == NULL) {\n+        if (lookupKeyRead(c->db, node->obj) == NULL) {\n+            bug = sdsdup(node->obj->ptr);\n+        }\n+        node = node->level[0].forward;\n+    }\n+    if (bug != NULL) {\n+        addReplyErrorFormat(c, \"step 3, miss = '%s'\", bug);\n+        sdsfree(bug);\n+        return;\n+    }\n+    addReply(c, shared.ok);\n+}\n+\n+/* *\n+ * slotsrestore key ttl val [key ttl val ...]\n+ * */\n+void\n+slotsrestoreCommand(client *c) {\n+    if (c->argc < 4 || (c->argc - 1) % 3 != 0) {\n+        addReplyErrorFormat(c, \"wrong number of arguments for 'slotsrestore' command\");\n+        return;\n+    }\n+    int n = (c->argc - 1) / 3;\n+\n+    long long *ttls = zmalloc(sizeof(long long) * n);\n+    robj **vals = zmalloc(sizeof(robj *) * n);\n+    for (int i = 0; i < n; i ++) {\n+        vals[i] = NULL;\n+    }\n+\n+    for (int i = 0; i < n; i ++) {\n+        robj *key = c->argv[i * 3 + 1];\n+        robj *ttl = c->argv[i * 3 + 2];\n+        robj *val = c->argv[i * 3 + 3];\n+        if (lookupKeyWrite(c->db, key) != NULL) {\n+            serverLog(LL_WARNING, \"slotsrestore: slot = %d, key = '%s' already exists\",\n+                    slots_num(key->ptr, NULL, NULL), (char *)key->ptr);\n+        }\n+        if (getLongLongFromObjectOrReply(c, ttl, &ttls[i], NULL) != C_OK) {\n+            goto cleanup;\n+        } else if (ttls[i] < 0) {\n+            addReplyError(c, \"invalid ttl value, must be >= 0\");\n+            goto cleanup;\n+        }\n+        rio payload;\n+        int type;\n+        if (verifyDumpPayload(val->ptr, sdslen(val->ptr)) != C_OK) {\n+            addReplyError(c, \"dump payload version or checksum are wrong\");\n+            goto cleanup;\n+        }\n+        rioInitWithBuffer(&payload, val->ptr);\n+        if (((type = rdbLoadObjectType(&payload)) == -1) ||\n+                ((vals[i] = rdbLoadObject(type, &payload)) == NULL)) {\n+            addReplyError(c, \"bad data format\");\n+            goto cleanup;\n+        }\n+    }\n+\n+    for (int i = 0; i < n; i ++) {\n+        robj *key = c->argv[i * 3 + 1];\n+        long long ttl = ttls[i];\n+        robj *val = vals[i];\n+        dbDelete(c->db, key);\n+        dbAdd(c->db, key, val);\n+        incrRefCount(val);\n+        if (ttl) {\n+            setExpire(c->db, key, mstime() + ttl);\n+        }\n+        signalModifiedKey(c->db, key);\n+        server.dirty ++;\n+    }\n+    addReply(c, shared.ok);\n+\n+cleanup:\n+    for (int i = 0; i < n; i ++) {\n+        if (vals[i] != NULL) {\n+            decrRefCount(vals[i]);\n+        }\n+    }\n+    zfree(vals);\n+    zfree(ttls);\n+}\n+\n+/* *\n+ * do migrate mutli key-value(s) for {slotsmgrt/slotsmgrtone}with tag commands\n+ * return value:\n+ *    -1 - error happens\n+ *   >=0 - # of success migration\n+ * */\n+static int\n+slotsmgrttag_command(client *c, sds host, sds port, int timeout, robj *key) {\n+    uint32_t crc;\n+    int hastag;\n+    int slot = slots_num(key->ptr, &crc, &hastag);\n+    if (!hastag) {\n+        return slotsmgrtone_command(c, host, port, timeout, key);\n+    }\n+\n+    slotsmgrt_sockfd *pfd = slotsmgrt_get_sockfd(c, host, port, timeout);\n+    if (pfd == NULL) {\n+        return -1;\n+    }\n+\n+    dict *d = c->db->hash_slots[slot];\n+    if (dictSize(d) == 0) {\n+        return 0;\n+    }\n+\n+    zrangespec range;\n+    range.min = (double)crc;\n+    range.minex = 0;\n+    range.max = (double)crc;\n+    range.maxex = 0;\n+\n+    list *l = listCreate();\n+    listSetFreeMethod(l, decrRefCountVoid);\n+\n+    zskiplistNode *node = zslFirstInRange(c->db->tagged_keys, &range);\n+    while (node != NULL && node->score == (double)crc) {\n+        listAddNodeTail(l, node->obj);\n+        incrRefCount(node->obj);\n+        node = node->level[0].forward;\n+    }\n+\n+    int max = listLength(l);\n+    if (max == 0) {\n+        listRelease(l);\n+        return 0;\n+    }\n+\n+    robj **keys = zmalloc(sizeof(robj *) * max);\n+    robj **vals = zmalloc(sizeof(robj *) * max);\n+\n+    int n = 0;\n+    for (int i = 0; i < max; i ++) {\n+        listNode *head = listFirst(l);\n+        robj *key = listNodeValue(head);\n+        robj *val = lookupKeyWrite(c->db, key);\n+        if (val != NULL) {\n+            keys[n] = key;\n+            vals[n] = val;\n+            n ++;\n+            incrRefCount(key);\n+            incrRefCount(val);\n+        }\n+        listDelNode(l, head);\n+    }\n+\n+    int ret = 0;\n+    if (n != 0) {\n+        if (slotsmgrt(c, host, port, pfd, c->db->id, timeout, keys, vals, n) != 0) {\n+            slotsmgrt_close_socket(host, port);\n+            ret = -1;\n+        } else {\n+            slotsremove(c, keys, n, 1);\n+            ret = n;\n+        }\n+    }\n+\n+    listRelease(l);\n+    for (int i = 0; i < n; i ++) {\n+        decrRefCount(keys[i]);\n+        decrRefCount(vals[i]);\n+    }\n+    zfree(keys);\n+    zfree(vals);\n+    return ret;\n+}\n+\n+/* *\n+ * slotsmgrttagslot host port timeout slot\n+ * */\n+void\n+slotsmgrttagslotCommand(client *c) {\n+    sds host = c->argv[1]->ptr;\n+    sds port = c->argv[2]->ptr;\n+    int timeout, slot;\n+    if (parse_timeout(c, c->argv[3], &timeout) != 0) {\n+        return;\n+    }\n+    if (parse_slot(c, c->argv[4], &slot) != 0) {\n+        return;\n+    }\n+\n+    dict *d = c->db->hash_slots[slot];\n+    int succ = 0;\n+    do {\n+        const dictEntry *de = dictGetRandomKey(d);\n+        if (de == NULL) {\n+            break;\n+        }\n+        sds skey = dictGetKey(de);\n+        robj *key = createStringObject(skey, sdslen(skey));\n+        succ = slotsmgrttag_command(c, host, port, timeout, key);\n+        decrRefCount(key);\n+        if (succ < 0) {\n+            return;\n+        }\n+    } while (0);\n+    addReplyMultiBulkLen(c, 2);\n+    addReplyLongLong(c, succ);\n+    addReplyLongLong(c, dictSize(d));\n+}\n+\n+/* *\n+ * slotsmgrttagone host port timeout key\n+ * */\n+void\n+slotsmgrttagoneCommand(client *c) {\n+    sds host = c->argv[1]->ptr;\n+    sds port = c->argv[2]->ptr;\n+    int timeout;\n+    if (parse_timeout(c, c->argv[3], &timeout) != 0) {\n+        return;\n+    }\n+\n+    robj *key = c->argv[4];\n+    int succ = slotsmgrttag_command(c, host, port, timeout, key);\n+    if (succ < 0) {\n+        return;\n+    }\n+    addReplyLongLong(c, succ);\n+}\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/0001-slotsscan.patch",
    "content": "diff --git a/extern/redis-3.2.4/src/server.c b/extern/redis-3.2.4/src/server.c\nindex 6ce92a1..1854c09 100644\n--- a/extern/redis-3.2.4/src/server.c\n+++ b/extern/redis-3.2.4/src/server.c\n@@ -296,6 +296,7 @@ struct redisCommand redisCommandTable[] = {\n     {\"pfdebug\",pfdebugCommand,-3,\"w\",0,NULL,0,0,0,0,0},\n     {\"latency\",latencyCommand,-2,\"aslt\",0,NULL,0,0,0,0,0},\n     {\"slotsinfo\",slotsinfoCommand,-1,\"rF\",0,NULL,0,0,0,0,0},\n+    {\"slotsscan\",slotsscanCommand,-3,\"rR\",0,NULL,0,0,0,0,0},\n     {\"slotsdel\",slotsdelCommand,-2,\"w\",0,NULL,1,-1,1,0,0},\n     {\"slotsmgrtslot\",slotsmgrtslotCommand,5,\"aw\",0,NULL,0,0,0,0,0},\n     {\"slotsmgrtone\",slotsmgrtoneCommand,5,\"aw\",0,NULL,0,0,0,0,0},\ndiff --git a/extern/redis-3.2.4/src/server.h b/extern/redis-3.2.4/src/server.h\nindex f811000..fc476ea 100644\n--- a/extern/redis-3.2.4/src/server.h\n+++ b/extern/redis-3.2.4/src/server.h\n@@ -1657,6 +1657,7 @@ void pfmergeCommand(client *c);\n void pfdebugCommand(client *c);\n void latencyCommand(client *c);\n void slotsinfoCommand(client *c);\n+void slotsscanCommand(client *c);\n void slotsdelCommand(client *c);\n void slotsmgrtslotCommand(client *c);\n void slotsmgrtoneCommand(client *c);\ndiff --git a/extern/redis-3.2.4/src/slots.c b/extern/redis-3.2.4/src/slots.c\nindex ff23492..90ff60a 100644\n--- a/extern/redis-3.2.4/src/slots.c\n+++ b/extern/redis-3.2.4/src/slots.c\n@@ -47,8 +47,13 @@ parse_int(client *c, robj *obj, int *p) {\n     if (getLongFromObjectOrReply(c, obj, &v, NULL) != C_OK) {\n         return -1;\n     }\n-    *p = v;\n-    return 0;\n+    if (v < INT_MIN || v > INT_MAX) {\n+        addReplyError(c, \"value is out of range\");\n+        return -1;\n+    } else {\n+        *p = v;\n+        return 0;\n+    }\n }\n \n static int\n@@ -815,3 +820,63 @@ slotsmgrttagoneCommand(client *c) {\n     }\n     addReplyLongLong(c, succ);\n }\n+\n+/* *\n+ * slotsscan slotnum cursor [COUNT count]\n+ * */\n+void\n+slotsscanCommand(client *c) {\n+    int slot;\n+    if (parse_slot(c, c->argv[1], &slot) != 0) {\n+        return;\n+    }\n+    unsigned long cursor;\n+    if (parseScanCursorOrReply(c, c->argv[2], &cursor) == C_ERR) {\n+        return;\n+    }\n+    unsigned long count = 10;\n+    if (c->argc != 3 && c->argc != 5) {\n+        addReplyErrorFormat(c, \"wrong number of arguments for 'slotsscan' command\");\n+        return;\n+    }\n+    if (c->argc == 5) {\n+        if (strcasecmp(c->argv[3]->ptr, \"count\") != 0) {\n+            addReply(c, shared.syntaxerr);\n+            return;\n+        }\n+        int v;\n+        if (parse_int(c, c->argv[4], &v) != 0) {\n+            return;\n+        }\n+        if (v < 1) {\n+            addReply(c, shared.syntaxerr);\n+            return;\n+        }\n+        count = v;\n+    }\n+    dict *d = c->db->hash_slots[slot];\n+    list *l = listCreate();\n+    listSetFreeMethod(l, decrRefCountVoid);\n+\n+    long loops = count * 10;\n+    do {\n+        cursor = dictScan(d, cursor, slotsScanSdsKeyCallback, l);\n+        loops --;\n+    } while (cursor != 0 && loops > 0 && listLength(l) < count);\n+\n+    addReplyMultiBulkLen(c, 2);\n+    addReplyBulkLongLong(c, cursor);\n+\n+    addReplyMultiBulkLen(c, listLength(l));\n+    while (1) {\n+        listNode *head = listFirst(l);\n+        if (head == NULL) {\n+            break;\n+        }\n+        robj *key = listNodeValue(head);\n+        addReplyBulk(c, key);\n+        listDelNode(l, head);\n+    }\n+\n+    listRelease(l);\n+}\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/0002-rehash.patch",
    "content": "diff --git a/extern/redis-3.2.4/src/server.c b/extern/redis-3.2.4/src/server.c\nindex 1854c09..4c9979c 100644\n--- a/extern/redis-3.2.4/src/server.c\n+++ b/extern/redis-3.2.4/src/server.c\n@@ -714,10 +714,16 @@ int incrementallyRehash(int dbid) {\n     /* Keys dictionary */\n     if (dictIsRehashing(server.db[dbid].dict)) {\n         dictRehashMilliseconds(server.db[dbid].dict,1);\n+\n+        long long start = timeInMilliseconds();\n         for (int i = 0; i < HASH_SLOTS_SIZE; i ++) {\n-            dict *d = server.db[dbid].hash_slots[i];\n+            int idx = ((i + start) & HASH_SLOTS_MASK);\n+            dict *d = server.db[dbid].hash_slots[idx];\n             if (dictIsRehashing(d)) {\n                 dictRehashMilliseconds(d, 1);\n+                if (timeInMilliseconds() != start) {\n+                    break;\n+                }\n             }\n         }\n         return 1; /* already used our millisecond for this loop... */\ndiff --git a/extern/redis-3.2.4/src/server.h b/extern/redis-3.2.4/src/server.h\nindex fc476ea..22c6551 100644\n--- a/extern/redis-3.2.4/src/server.h\n+++ b/extern/redis-3.2.4/src/server.h\n@@ -501,6 +501,8 @@ struct evictionPoolEntry {\n void crc32_init();\n uint32_t crc32_checksum(const char *buf, int len);\n \n+long long timeInMilliseconds(void);\n+\n #define HASH_SLOTS_MASK 0x000003ff\n #define HASH_SLOTS_SIZE (HASH_SLOTS_MASK + 1)\n \n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/BUGS",
    "content": "Please check https://github.com/antirez/redis/issues\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/CONTRIBUTING",
    "content": "Note: by contributing code to the Redis project in any form, including sending\na pull request via Github, a code fragment or patch via private email or\npublic discussion groups, you agree to release your code under the terms\nof the BSD license that you can find in the COPYING file included in the Redis\nsource distribution. You will include BSD license in the COPYING file within\neach source file that you contribute.\n\n# IMPORTANT: HOW TO USE REDIS GITHUB ISSUES\n\n* Github issues SHOULD ONLY BE USED to report bugs, and for DETAILED feature\n  requests. Everything else belongs to the Redis Google Group.\n\n  PLEASE DO NOT POST GENERAL QUESTIONS that are not about bugs or suspected\n  bugs in the Github issues system. We'll be very happy to help you and provide\n  all the support Reddit sub:\n\n      http://reddit.com/r/redis\n\n  There is also an active community of Redis users at Stack Overflow:\n\n      http://stackoverflow.com/questions/tagged/redis\n\n# How to provide a patch for a new feature\n\n1. If it is a major feature or a semantical change, please post it as a new submission in r/redis on Reddit at http://reddit.com/r/redis. Try to be passionate about why the feature is needed, make users upvote your proposal to gain traction and so forth. Read feedbacks about the community. But in this first step **please don't write code yet**.\n\n2. If in step 1 you get an acknowledge from the project leaders, use the\n   following procedure to submit a patch:\n\n    a. Fork Redis on github ( http://help.github.com/fork-a-repo/ )\n    b. Create a topic branch (git checkout -b my_branch)\n    c. Push to your branch (git push origin my_branch)\n    d. Initiate a pull request on github ( http://help.github.com/send-pull-requests/ )\n    e. Done :)\n\nFor minor fixes just open a pull request on Github.\n\nThanks!\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/COPYING",
    "content": "Copyright (c) 2006-2015, Salvatore Sanfilippo\nAll rights reserved.\n\nRedistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:\n\n    * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.\n    * 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.\n    * Neither the name of Redis nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.\n\nTHIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT OWNER 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.\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/INSTALL",
    "content": "See README\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/MANIFESTO",
    "content": "[Note: this is the Redis manifesto, for general information about\n       installing and running Redis read the README file instead.]\n\nRedis Manifesto\n===============\n\n1 - A DSL for Abstract Data Types. Redis is a DSL (Domain Specific Language)\n    that manipulates abstract data types and implemented as a TCP daemon.\n    Commands manipulate a key space where keys are binary-safe strings and\n    values are different kinds of abstract data types. Every data type\n    represents an abstract version of a fundamental data structure. For instance\n    Redis Lists are an abstract representation of linked lists. In Redis, the\n    essence of a data type isn't just the kind of operations that the data types\n    support, but also the space and time complexity of the data type and the\n    operations performed upon it.\n\n2 - Memory storage is #1. The Redis data set, composed of defined key-value\n    pairs, is primarily stored in the computer's memory. The amount of memory in\n    all kinds of computers, including entry-level servers, is increasing\n    significantly each year. Memory is fast, and allows Redis to have very\n    predictable performance. Datasets composed of 10k or 40 millions keys will\n    perform similarly. Complex data types like Redis Sorted Sets are easy to\n    implement and manipulate in memory with good performance, making Redis very\n    simple. Redis will continue to explore alternative options (where data can\n    be optionally stored on disk, say) but the main goal of the project remains\n    the development of an in-memory database.\n\n3 - Fundamental data structures for a fundamental API. The Redis API is a direct\n    consequence of fundamental data structures. APIs can often be arbitrary but\n    not an API that resembles the nature of fundamental data structures. If we\n    ever meet intelligent life forms from another part of the universe, they'll\n    likely know, understand and recognize the same basic data structures we have\n    in our computer science books. Redis will avoid intermediate layers in API,\n    so that the complexity is obvious and more complex operations can be\n    performed as the sum of the basic operations.\n\n4 - Code is like a poem; it's not just something we write to reach some\n    practical result. Sometimes people that are far from the Redis philosophy\n    suggest using other code written by other authors (frequently in other\n    languages) in order to implement something Redis currently lacks. But to us\n    this is like if Shakespeare decided to end Enrico IV using the Paradiso from\n    the Divina Commedia. Is using any external code a bad idea? Not at all. Like\n    in \"One Thousand and One Nights\" smaller self contained stories are embedded\n    in a bigger story, we'll be happy to use beautiful self contained libraries\n    when needed. At the same time, when writing the Redis story we're trying to\n    write smaller stories that will fit in to other code.\n\n5 - We're against complexity. We believe designing systems is a fight against\n    complexity. We'll accept to fight the complexity when it's worthwhile but\n    we'll try hard to recognize when a small feature is not worth 1000s of lines\n    of code. Most of the time the best way to fight complexity is by not\n    creating it at all.\n\n6 - Two levels of API. The Redis API has two levels: 1) a subset of the API fits\n    naturally into a distributed version of Redis and 2) a more complex API that\n    supports multi-key operations. Both are useful if used judiciously but\n    there's no way to make the more complex multi-keys API distributed in an\n    opaque way without violating our other principles. We don't want to provide\n    the illusion of something that will work magically when actually it can't in\n    all cases. Instead we'll provide commands to quickly migrate keys from one\n    instance to another to perform multi-key operations and expose the tradeoffs\n    to the user.\n\n7 - We optimize for joy. We believe writing code is a lot of hard work, and the\n    only way it can be worth is by enjoying it. When there is no longer joy in\n    writing code, the best thing to do is stop. To prevent this, we'll avoid\n    taking paths that will make Redis less of a joy to develop.\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/Makefile",
    "content": "# Top level makefile, the real shit is at src/Makefile\n\ndefault: all\n\n.DEFAULT:\n\tcd src && $(MAKE) $@\n\ninstall:\n\tcd src && $(MAKE) $@\n\n.PHONY: install\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/README.md",
    "content": "This README is just a fast *quick start* document. You can find more detailed documentation at http://redis.io.\n\nWhat is Redis?\n--------------\n\nRedis is often referred as a *data structures* server. What this means is that Redis provides access to mutable data structures via a set of commands, which are sent using a *server-client* model with TCP sockets and a simple protocol. So different processes can query and modify the same data structures in a shared way.\n\nData structures implemented into Redis have a few special properties:\n\n* Redis cares to store them on disk, even if they are always served and modified into the server memory. This means that Redis is fast, but that is also non-volatile.\n* Implementation of data structures stress on memory efficiency, so data structures inside Redis will likely use less memory compared to the same data structure modeled using an high level programming language.\n* Redis offers a number of features that are natural to find in a database, like replication, tunable levels of durability, cluster, high availability.\n\nAnother good example is to think of Redis as a more complex version of memcached, where the operations are not just SETs and GETs, but operations to work with complex data types like Lists, Sets, ordered data structures, and so forth.\n\nIf you want to know more, this is a list of selected starting points:\n\n* Introduction to Redis data types. http://redis.io/topics/data-types-intro\n* Try Redis directly inside your browser. http://try.redis.io\n* The full list of Redis commands. http://redis.io/commands\n* There is much more inside the Redis official documentation. http://redis.io/documentation\n\nBuilding Redis\n--------------\n\nRedis can be compiled and used on Linux, OSX, OpenBSD, NetBSD, FreeBSD.\nWe support big endian and little endian architectures, and both 32 bit\nand 64 bit systems.\n\nIt may compile on Solaris derived systems (for instance SmartOS) but our\nsupport for this platform is *best effort* and Redis is not guaranteed to\nwork as well as in Linux, OSX, and \\*BSD there.\n\nIt is as simple as:\n\n    % make\n\nYou can run a 32 bit Redis binary using:\n\n    % make 32bit\n\nAfter building Redis is a good idea to test it, using:\n\n    % make test\n\nFixing build problems with dependencies or cached build options\n---------\n\nRedis has some dependencies which are included into the `deps` directory.\n`make` does not rebuild dependencies automatically, even if something in the\nsource code of dependencies is changed.\n\nWhen you update the source code with `git pull` or when code inside the\ndependencies tree is modified in any other way, make sure to use the following\ncommand in order to really clean everything and rebuild from scratch:\n\n    make distclean\n\nThis will clean: jemalloc, lua, hiredis, linenoise.\n\nAlso if you force certain build options like 32bit target, no C compiler\noptimizations (for debugging purposes), and other similar build time options,\nthose options are cached indefinitely until you issue a `make distclean`\ncommand.\n\nFixing problems building 32 bit binaries\n---------\n\nIf after building Redis with a 32 bit target you need to rebuild it\nwith a 64 bit target, or the other way around, you need to perform a\n`make distclean` in the root directory of the Redis distribution.\n\nIn case of build errors when trying to build a 32 bit binary of Redis, try\nthe following steps:\n\n* Install the packages libc6-dev-i386 (also try g++-multilib).\n* Try using the following command line instead of `make 32bit`:\n  `make CFLAGS=\"-m32 -march=native\" LDFLAGS=\"-m32\"`\n\nAllocator\n---------\n\nSelecting a non-default memory allocator when building Redis is done by setting\nthe `MALLOC` environment variable. Redis is compiled and linked against libc\nmalloc by default, with the exception of jemalloc being the default on Linux\nsystems. This default was picked because jemalloc has proven to have fewer\nfragmentation problems than libc malloc.\n\nTo force compiling against libc malloc, use:\n\n    % make MALLOC=libc\n\nTo compile against jemalloc on Mac OS X systems, use:\n\n    % make MALLOC=jemalloc\n\nVerbose build\n-------------\n\nRedis will build with a user friendly colorized output by default.\nIf you want to see a more verbose output use the following:\n\n    % make V=1\n\nRunning Redis\n-------------\n\nTo run Redis with the default configuration just type:\n\n    % cd src\n    % ./redis-server\n    \nIf you want to provide your redis.conf, you have to run it using an additional\nparameter (the path of the configuration file):\n\n    % cd src\n    % ./redis-server /path/to/redis.conf\n\nIt is possible to alter the Redis configuration passing parameters directly\nas options using the command line. Examples:\n\n    % ./redis-server --port 9999 --slaveof 127.0.0.1 6379\n    % ./redis-server /etc/redis/6379.conf --loglevel debug\n\nAll the options in redis.conf are also supported as options using the command\nline, with exactly the same name.\n\nPlaying with Redis\n------------------\n\nYou can use redis-cli to play with Redis. Start a redis-server instance,\nthen in another terminal try the following:\n\n    % cd src\n    % ./redis-cli\n    redis> ping\n    PONG\n    redis> set foo bar\n    OK\n    redis> get foo\n    \"bar\"\n    redis> incr mycounter\n    (integer) 1\n    redis> incr mycounter\n    (integer) 2\n    redis>\n\nYou can find the list of all the available commands at http://redis.io/commands.\n\nInstalling Redis\n-----------------\n\nIn order to install Redis binaries into /usr/local/bin just use:\n\n    % make install\n\nYou can use `make PREFIX=/some/other/directory install` if you wish to use a\ndifferent destination.\n\nMake install will just install binaries in your system, but will not configure\ninit scripts and configuration files in the appropriate place. This is not\nneeded if you want just to play a bit with Redis, but if you are installing\nit the proper way for a production system, we have a script doing this\nfor Ubuntu and Debian systems:\n\n    % cd utils\n    % ./install_server.sh\n\nThe script will ask you a few questions and will setup everything you need\nto run Redis properly as a background daemon that will start again on\nsystem reboots.\n\nYou'll be able to stop and start Redis using the script named\n`/etc/init.d/redis_<portnumber>`, for instance `/etc/init.d/redis_6379`.\n\nCode contributions\n---\n\nNote: by contributing code to the Redis project in any form, including sending\na pull request via Github, a code fragment or patch via private email or\npublic discussion groups, you agree to release your code under the terms\nof the BSD license that you can find in the [COPYING][1] file included in the Redis\nsource distribution.\n\nPlease see the [CONTRIBUTING][2] file in this source distribution for more\ninformation.\n\nEnjoy!\n\n[1]: https://github.com/antirez/redis/blob/unstable/COPYING\n[2]: https://github.com/antirez/redis/blob/unstable/CONTRIBUTING\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/deps/Makefile",
    "content": "# Redis dependency Makefile\n\nuname_S:= $(shell sh -c 'uname -s 2>/dev/null || echo not')\n\nCCCOLOR=\"\\033[34m\"\nLINKCOLOR=\"\\033[34;1m\"\nSRCCOLOR=\"\\033[33m\"\nBINCOLOR=\"\\033[37;1m\"\nMAKECOLOR=\"\\033[32;1m\"\nENDCOLOR=\"\\033[0m\"\n\ndefault:\n\t@echo \"Explicit target required\"\n\n.PHONY: default\n\n# Prerequisites target\n.make-prerequisites:\n\t@touch $@\n\n# Clean everything when CFLAGS is different\nifneq ($(shell sh -c '[ -f .make-cflags ] && cat .make-cflags || echo none'), $(CFLAGS))\n.make-cflags: distclean\n\t-(echo \"$(CFLAGS)\" > .make-cflags)\n.make-prerequisites: .make-cflags\nendif\n\n# Clean everything when LDFLAGS is different\nifneq ($(shell sh -c '[ -f .make-ldflags ] && cat .make-ldflags || echo none'), $(LDFLAGS))\n.make-ldflags: distclean\n\t-(echo \"$(LDFLAGS)\" > .make-ldflags)\n.make-prerequisites: .make-ldflags\nendif\n\ndistclean:\n\t-(cd hiredis && $(MAKE) clean) > /dev/null || true\n\t-(cd linenoise && $(MAKE) clean) > /dev/null || true\n\t-(cd lua && $(MAKE) clean) > /dev/null || true\n\t-(cd geohash-int && $(MAKE) clean) > /dev/null || true\n\t-(cd jemalloc && [ -f Makefile ] && $(MAKE) distclean) > /dev/null || true\n\t-(rm -f .make-*)\n\n.PHONY: distclean\n\nhiredis: .make-prerequisites\n\t@printf '%b %b\\n' $(MAKECOLOR)MAKE$(ENDCOLOR) $(BINCOLOR)$@$(ENDCOLOR)\n\tcd hiredis && $(MAKE) static\n\n.PHONY: hiredis\n\nlinenoise: .make-prerequisites\n\t@printf '%b %b\\n' $(MAKECOLOR)MAKE$(ENDCOLOR) $(BINCOLOR)$@$(ENDCOLOR)\n\tcd linenoise && $(MAKE)\n\n.PHONY: linenoise\n\nifeq ($(uname_S),SunOS)\n\t# Make isinf() available\n\tLUA_CFLAGS= -D__C99FEATURES__=1\nendif\n\nLUA_CFLAGS+= -O2 -Wall -DLUA_ANSI -DENABLE_CJSON_GLOBAL -DREDIS_STATIC='' $(CFLAGS)\nLUA_LDFLAGS+= $(LDFLAGS)\n# lua's Makefile defines AR=\"ar rcu\", which is unusual, and makes it more\n# challenging to cross-compile lua (and redis).  These defines make it easier\n# to fit redis into cross-compilation environments, which typically set AR.\nAR=ar\nARFLAGS=rcu\n\nlua: .make-prerequisites\n\t@printf '%b %b\\n' $(MAKECOLOR)MAKE$(ENDCOLOR) $(BINCOLOR)$@$(ENDCOLOR)\n\tcd lua/src && $(MAKE) all CFLAGS=\"$(LUA_CFLAGS)\" MYLDFLAGS=\"$(LUA_LDFLAGS)\" AR=\"$(AR) $(ARFLAGS)\"\n\n.PHONY: lua\n\nJEMALLOC_CFLAGS= -std=gnu99 -Wall -pipe -g3 -O3 -funroll-loops $(CFLAGS)\nJEMALLOC_LDFLAGS= $(LDFLAGS)\n\njemalloc: .make-prerequisites\n\t@printf '%b %b\\n' $(MAKECOLOR)MAKE$(ENDCOLOR) $(BINCOLOR)$@$(ENDCOLOR)\n\tcd jemalloc && ./configure --with-lg-quantum=3 --with-jemalloc-prefix=je_ --enable-cc-silence CFLAGS=\"$(JEMALLOC_CFLAGS)\" LDFLAGS=\"$(JEMALLOC_LDFLAGS)\"\n\tcd jemalloc && $(MAKE) CFLAGS=\"$(JEMALLOC_CFLAGS)\" LDFLAGS=\"$(JEMALLOC_LDFLAGS)\" lib/libjemalloc.a\n\n.PHONY: jemalloc\n\ngeohash-int: .make-prerequisites\n\t@printf '%b %b\\n' $(MAKECOLOR)MAKE$(ENDCOLOR) $(BINCOLOR)$@$(ENDCOLOR)\n\tcd geohash-int && $(MAKE)\n\n.PHONY: geohash-int\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/deps/README.md",
    "content": "This directory contains all Redis dependencies, except for the libc that\nshould be provided by the operating system.\n\n* **Jemalloc** is our memory allocator, used as replacement for libc malloc on Linux by default. It has good performances and excellent fragmentation behavior. This component is upgraded from time to time.\n* **geohash-int** is inside the dependencies directory but is actually part of the Redis project, since it is our private fork (heavily modified) of a library initially developed for Ardb, which is in turn a fork of Redis.\n* **hiredis** is the official C client library for Redis. It is used by redis-cli, redis-benchmark and Redis Sentinel. It is part of the Redis official ecosystem but is developed externally from the Redis repository, so we just upgrade it as needed.\n* **linenoise** is a readline replacement. It is developed by the same authors of Redis but is managed as a separated project and updated as needed.\n* **lua** is Lua 5.1 with minor changes for security and additional libraries.\n\nHow to upgrade the above dependencies\n===\n\nJemalloc\n---\n\nJemalloc is unmodified. We only change settings via the `configure` script of Jemalloc using the `--with-lg-quantum` option, setting it to the value of 3 instead of 4. This provides us with more size classes that better suit the Redis data structures, in order to gain memory efficiency.\n\nSo in order to upgrade jemalloc:\n\n1. Remove the jemalloc directory.\n2. Substitute it with the new jemalloc source tree.\n\nGeohash\n---\n\nThis is never upgraded since it's part of the Redis project. If there are changes to merge from Ardb there is the need to manually check differences, but at this point the source code is pretty different.\n\nHiredis\n---\n\nHiredis uses the SDS string library, that must be the same version used inside Redis itself. Hiredis is also very critical for Sentinel. Historically Redis often used forked versions of hiredis in a way or the other. In order to upgrade it is adviced to take a lot of care:\n\n1. Check with diff if hiredis API changed and what impact it could have in Redis.\n2. Make sure thet the SDS library inside Hiredis and inside Redis are compatible.\n3. After the upgrade, run the Redis Sentinel test.\n4. Check manually that redis-cli and redis-benchmark behave as expecteed, since we have no tests for CLI utilities currently.\n\nLinenoise\n---\n\nLinenoise is rarely upgraded as needed. The upgrade process is trivial since\nRedis uses a non modified version of linenoise, so to upgrade just do the\nfollowing:\n\n1. Remove the linenoise directory.\n2. Substitute it with the new linenoise source tree.\n\nLua\n---\n\nWe use Lua 5.1 and no upgrade is planned currently, since we don't want to break\nLua scripts for new Lua features: in the context of Redis Lua scripts the\ncapabilities of 5.1 are usually more than enough, the release is rock solid,\nand we definitely don't want to break old scripts.\n\nSo upgrading of Lua is up to the Redis project maintainers and should be a\nmanual procedure performed by taking a diff between the different versions.\n\nCurrently we have at least the following differences between official Lua 5.1\nand our version:\n\n1. Makefile is modified to allow a different compiler than GCC.\n2. We have the implementation source code, and directly link to the following external libraries: `lua_cjson.o`, `lua_struct.o`, `lua_cmsgpack.o` and `lua_bit.o`.\n3. There is a security fix in `ldo.c`, line 498: The check for `LUA_SIGNATURE[0]` is removed in order toa void direct bytecode exectuion.\n\n\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/deps/geohash-int/Makefile",
    "content": "STD=\nWARN= -Wall\nOPT= -O2\n\nR_CFLAGS= $(STD) $(WARN) $(OPT) $(DEBUG) $(CFLAGS)\nR_LDFLAGS= $(LDFLAGS)\nDEBUG= -g\n\nR_CC=$(CC) $(R_CFLAGS)\nR_LD=$(CC) $(R_LDFLAGS)\n\nall: geohash.o geohash_helper.o\n\n.PHONY: all\n\ngeohash.o: geohash.h geohash.c\ngeohash_helper.o: geohash.h geohash_helper.h geohash_helper.c\n\n.c.o:\n\t$(R_CC) -c $<\n\nclean:\n\trm -f *.o\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/deps/geohash-int/geohash.c",
    "content": "/*\n * Copyright (c) 2013-2014, yinqiwen <yinqiwen@gmail.com>\n * Copyright (c) 2014, Matt Stancliff <matt@genges.com>.\n * Copyright (c) 2015-2016, Salvatore Sanfilippo <antirez@gmail.com>.\n * All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions are met:\n *\n *  * Redistributions of source code must retain the above copyright notice,\n *    this list of conditions and the following disclaimer.\n *  * Redistributions in binary form must reproduce the above copyright\n *    notice, this list of conditions and the following disclaimer in the\n *    documentation and/or other materials provided with the distribution.\n *  * Neither the name of Redis nor the names of its contributors may be used\n *    to endorse or promote products derived from this software without\n *    specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\"\n * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\n * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS\n * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR\n * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF\n * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS\n * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN\n * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)\n * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF\n * THE POSSIBILITY OF SUCH DAMAGE.\n */\n#include \"geohash.h\"\n\n/**\n * Hashing works like this:\n * Divide the world into 4 buckets.  Label each one as such:\n *  -----------------\n *  |       |       |\n *  |       |       |\n *  | 0,1   | 1,1   |\n *  -----------------\n *  |       |       |\n *  |       |       |\n *  | 0,0   | 1,0   |\n *  -----------------\n */\n\n/* Interleave lower bits of x and y, so the bits of x\n * are in the even positions and bits from y in the odd;\n * x and y must initially be less than 2**32 (65536).\n * From:  https://graphics.stanford.edu/~seander/bithacks.html#InterleaveBMN\n */\nstatic inline uint64_t interleave64(uint32_t xlo, uint32_t ylo) {\n    static const uint64_t B[] = {0x5555555555555555ULL, 0x3333333333333333ULL,\n                                 0x0F0F0F0F0F0F0F0FULL, 0x00FF00FF00FF00FFULL,\n                                 0x0000FFFF0000FFFFULL};\n    static const unsigned int S[] = {1, 2, 4, 8, 16};\n\n    uint64_t x = xlo;\n    uint64_t y = ylo;\n\n    x = (x | (x << S[4])) & B[4];\n    y = (y | (y << S[4])) & B[4];\n\n    x = (x | (x << S[3])) & B[3];\n    y = (y | (y << S[3])) & B[3];\n\n    x = (x | (x << S[2])) & B[2];\n    y = (y | (y << S[2])) & B[2];\n\n    x = (x | (x << S[1])) & B[1];\n    y = (y | (y << S[1])) & B[1];\n\n    x = (x | (x << S[0])) & B[0];\n    y = (y | (y << S[0])) & B[0];\n\n    return x | (y << 1);\n}\n\n/* reverse the interleave process\n * derived from http://stackoverflow.com/questions/4909263\n */\nstatic inline uint64_t deinterleave64(uint64_t interleaved) {\n    static const uint64_t B[] = {0x5555555555555555ULL, 0x3333333333333333ULL,\n                                 0x0F0F0F0F0F0F0F0FULL, 0x00FF00FF00FF00FFULL,\n                                 0x0000FFFF0000FFFFULL, 0x00000000FFFFFFFFULL};\n    static const unsigned int S[] = {0, 1, 2, 4, 8, 16};\n\n    uint64_t x = interleaved;\n    uint64_t y = interleaved >> 1;\n\n    x = (x | (x >> S[0])) & B[0];\n    y = (y | (y >> S[0])) & B[0];\n\n    x = (x | (x >> S[1])) & B[1];\n    y = (y | (y >> S[1])) & B[1];\n\n    x = (x | (x >> S[2])) & B[2];\n    y = (y | (y >> S[2])) & B[2];\n\n    x = (x | (x >> S[3])) & B[3];\n    y = (y | (y >> S[3])) & B[3];\n\n    x = (x | (x >> S[4])) & B[4];\n    y = (y | (y >> S[4])) & B[4];\n\n    x = (x | (x >> S[5])) & B[5];\n    y = (y | (y >> S[5])) & B[5];\n\n    return x | (y << 32);\n}\n\nvoid geohashGetCoordRange(GeoHashRange *long_range, GeoHashRange *lat_range) {\n    /* These are constraints from EPSG:900913 / EPSG:3785 / OSGEO:41001 */\n    /* We can't geocode at the north/south pole. */\n    long_range->max = GEO_LONG_MAX;\n    long_range->min = GEO_LONG_MIN;\n    lat_range->max = GEO_LAT_MAX;\n    lat_range->min = GEO_LAT_MIN;\n}\n\nint geohashEncode(const GeoHashRange *long_range, const GeoHashRange *lat_range,\n                  double longitude, double latitude, uint8_t step,\n                  GeoHashBits *hash) {\n    /* Check basic arguments sanity. */\n    if (hash == NULL || step > 32 || step == 0 ||\n        RANGEPISZERO(lat_range) || RANGEPISZERO(long_range)) return 0;\n\n    /* Return an error when trying to index outside the supported\n     * constraints. */\n    if (longitude > 180 || longitude < -180 ||\n        latitude > 85.05112878 || latitude < -85.05112878) return 0;\n\n    hash->bits = 0;\n    hash->step = step;\n\n    if (latitude < lat_range->min || latitude > lat_range->max ||\n        longitude < long_range->min || longitude > long_range->max) {\n        return 0;\n    }\n\n    double lat_offset =\n        (latitude - lat_range->min) / (lat_range->max - lat_range->min);\n    double long_offset =\n        (longitude - long_range->min) / (long_range->max - long_range->min);\n\n    /* convert to fixed point based on the step size */\n    lat_offset *= (1 << step);\n    long_offset *= (1 << step);\n    hash->bits = interleave64(lat_offset, long_offset);\n    return 1;\n}\n\nint geohashEncodeType(double longitude, double latitude, uint8_t step, GeoHashBits *hash) {\n    GeoHashRange r[2] = { { 0 } };\n    geohashGetCoordRange(&r[0], &r[1]);\n    return geohashEncode(&r[0], &r[1], longitude, latitude, step, hash);\n}\n\nint geohashEncodeWGS84(double longitude, double latitude, uint8_t step,\n                       GeoHashBits *hash) {\n    return geohashEncodeType(longitude, latitude, step, hash);\n}\n\nint geohashDecode(const GeoHashRange long_range, const GeoHashRange lat_range,\n                   const GeoHashBits hash, GeoHashArea *area) {\n    if (HASHISZERO(hash) || NULL == area || RANGEISZERO(lat_range) ||\n        RANGEISZERO(long_range)) {\n        return 0;\n    }\n\n    area->hash = hash;\n    uint8_t step = hash.step;\n    uint64_t hash_sep = deinterleave64(hash.bits); /* hash = [LAT][LONG] */\n\n    double lat_scale = lat_range.max - lat_range.min;\n    double long_scale = long_range.max - long_range.min;\n\n    uint32_t ilato = hash_sep;       /* get lat part of deinterleaved hash */\n    uint32_t ilono = hash_sep >> 32; /* shift over to get long part of hash */\n\n    /* divide by 2**step.\n     * Then, for 0-1 coordinate, multiply times scale and add\n       to the min to get the absolute coordinate. */\n    area->latitude.min =\n        lat_range.min + (ilato * 1.0 / (1ull << step)) * lat_scale;\n    area->latitude.max =\n        lat_range.min + ((ilato + 1) * 1.0 / (1ull << step)) * lat_scale;\n    area->longitude.min =\n        long_range.min + (ilono * 1.0 / (1ull << step)) * long_scale;\n    area->longitude.max =\n        long_range.min + ((ilono + 1) * 1.0 / (1ull << step)) * long_scale;\n\n    return 1;\n}\n\nint geohashDecodeType(const GeoHashBits hash, GeoHashArea *area) {\n    GeoHashRange r[2] = { { 0 } };\n    geohashGetCoordRange(&r[0], &r[1]);\n    return geohashDecode(r[0], r[1], hash, area);\n}\n\nint geohashDecodeWGS84(const GeoHashBits hash, GeoHashArea *area) {\n    return geohashDecodeType(hash, area);\n}\n\nint geohashDecodeAreaToLongLat(const GeoHashArea *area, double *xy) {\n    if (!xy) return 0;\n    xy[0] = (area->longitude.min + area->longitude.max) / 2;\n    xy[1] = (area->latitude.min + area->latitude.max) / 2;\n    return 1;\n}\n\nint geohashDecodeToLongLatType(const GeoHashBits hash, double *xy) {\n    GeoHashArea area = { { 0 } };\n    if (!xy || !geohashDecodeType(hash, &area))\n        return 0;\n    return geohashDecodeAreaToLongLat(&area, xy);\n}\n\nint geohashDecodeToLongLatWGS84(const GeoHashBits hash, double *xy) {\n    return geohashDecodeToLongLatType(hash, xy);\n}\n\nstatic void geohash_move_x(GeoHashBits *hash, int8_t d) {\n    if (d == 0)\n        return;\n\n    uint64_t x = hash->bits & 0xaaaaaaaaaaaaaaaaULL;\n    uint64_t y = hash->bits & 0x5555555555555555ULL;\n\n    uint64_t zz = 0x5555555555555555ULL >> (64 - hash->step * 2);\n\n    if (d > 0) {\n        x = x + (zz + 1);\n    } else {\n        x = x | zz;\n        x = x - (zz + 1);\n    }\n\n    x &= (0xaaaaaaaaaaaaaaaaULL >> (64 - hash->step * 2));\n    hash->bits = (x | y);\n}\n\nstatic void geohash_move_y(GeoHashBits *hash, int8_t d) {\n    if (d == 0)\n        return;\n\n    uint64_t x = hash->bits & 0xaaaaaaaaaaaaaaaaULL;\n    uint64_t y = hash->bits & 0x5555555555555555ULL;\n\n    uint64_t zz = 0xaaaaaaaaaaaaaaaaULL >> (64 - hash->step * 2);\n    if (d > 0) {\n        y = y + (zz + 1);\n    } else {\n        y = y | zz;\n        y = y - (zz + 1);\n    }\n    y &= (0x5555555555555555ULL >> (64 - hash->step * 2));\n    hash->bits = (x | y);\n}\n\nvoid geohashNeighbors(const GeoHashBits *hash, GeoHashNeighbors *neighbors) {\n    neighbors->east = *hash;\n    neighbors->west = *hash;\n    neighbors->north = *hash;\n    neighbors->south = *hash;\n    neighbors->south_east = *hash;\n    neighbors->south_west = *hash;\n    neighbors->north_east = *hash;\n    neighbors->north_west = *hash;\n\n    geohash_move_x(&neighbors->east, 1);\n    geohash_move_y(&neighbors->east, 0);\n\n    geohash_move_x(&neighbors->west, -1);\n    geohash_move_y(&neighbors->west, 0);\n\n    geohash_move_x(&neighbors->south, 0);\n    geohash_move_y(&neighbors->south, -1);\n\n    geohash_move_x(&neighbors->north, 0);\n    geohash_move_y(&neighbors->north, 1);\n\n    geohash_move_x(&neighbors->north_west, -1);\n    geohash_move_y(&neighbors->north_west, 1);\n\n    geohash_move_x(&neighbors->north_east, 1);\n    geohash_move_y(&neighbors->north_east, 1);\n\n    geohash_move_x(&neighbors->south_east, 1);\n    geohash_move_y(&neighbors->south_east, -1);\n\n    geohash_move_x(&neighbors->south_west, -1);\n    geohash_move_y(&neighbors->south_west, -1);\n}\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/deps/geohash-int/geohash.h",
    "content": "/*\n * Copyright (c) 2013-2014, yinqiwen <yinqiwen@gmail.com>\n * Copyright (c) 2014, Matt Stancliff <matt@genges.com>.\n * Copyright (c) 2015, Salvatore Sanfilippo <antirez@gmail.com>.\n * All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions are met:\n *\n *  * Redistributions of source code must retain the above copyright notice,\n *    this list of conditions and the following disclaimer.\n *  * Redistributions in binary form must reproduce the above copyright\n *    notice, this list of conditions and the following disclaimer in the\n *    documentation and/or other materials provided with the distribution.\n *  * Neither the name of Redis nor the names of its contributors may be used\n *    to endorse or promote products derived from this software without\n *    specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\"\n * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\n * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS\n * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR\n * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF\n * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS\n * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN\n * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)\n * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF\n * THE POSSIBILITY OF SUCH DAMAGE.\n */\n\n#ifndef GEOHASH_H_\n#define GEOHASH_H_\n\n#include <stddef.h>\n#include <stdint.h>\n#include <stdint.h>\n\n#if defined(__cplusplus)\nextern \"C\" {\n#endif\n\n#define HASHISZERO(r) (!(r).bits && !(r).step)\n#define RANGEISZERO(r) (!(r).max && !(r).min)\n#define RANGEPISZERO(r) (r == NULL || RANGEISZERO(*r))\n\n#define GEO_STEP_MAX 26 /* 26*2 = 52 bits. */\n\n/* Limits from EPSG:900913 / EPSG:3785 / OSGEO:41001 */\n#define GEO_LAT_MIN -85.05112878\n#define GEO_LAT_MAX 85.05112878\n#define GEO_LONG_MIN -180\n#define GEO_LONG_MAX 180\n\ntypedef enum {\n    GEOHASH_NORTH = 0,\n    GEOHASH_EAST,\n    GEOHASH_WEST,\n    GEOHASH_SOUTH,\n    GEOHASH_SOUTH_WEST,\n    GEOHASH_SOUTH_EAST,\n    GEOHASH_NORT_WEST,\n    GEOHASH_NORT_EAST\n} GeoDirection;\n\ntypedef struct {\n    uint64_t bits;\n    uint8_t step;\n} GeoHashBits;\n\ntypedef struct {\n    double min;\n    double max;\n} GeoHashRange;\n\ntypedef struct {\n    GeoHashBits hash;\n    GeoHashRange longitude;\n    GeoHashRange latitude;\n} GeoHashArea;\n\ntypedef struct {\n    GeoHashBits north;\n    GeoHashBits east;\n    GeoHashBits west;\n    GeoHashBits south;\n    GeoHashBits north_east;\n    GeoHashBits south_east;\n    GeoHashBits north_west;\n    GeoHashBits south_west;\n} GeoHashNeighbors;\n\n/*\n * 0:success\n * -1:failed\n */\nvoid geohashGetCoordRange(GeoHashRange *long_range, GeoHashRange *lat_range);\nint geohashEncode(const GeoHashRange *long_range, const GeoHashRange *lat_range,\n                  double longitude, double latitude, uint8_t step,\n                  GeoHashBits *hash);\nint geohashEncodeType(double longitude, double latitude,\n                      uint8_t step, GeoHashBits *hash);\nint geohashEncodeWGS84(double longitude, double latitude, uint8_t step,\n                       GeoHashBits *hash);\nint geohashDecode(const GeoHashRange long_range, const GeoHashRange lat_range,\n                  const GeoHashBits hash, GeoHashArea *area);\nint geohashDecodeType(const GeoHashBits hash, GeoHashArea *area);\nint geohashDecodeWGS84(const GeoHashBits hash, GeoHashArea *area);\nint geohashDecodeAreaToLongLat(const GeoHashArea *area, double *xy);\nint geohashDecodeToLongLatType(const GeoHashBits hash, double *xy);\nint geohashDecodeToLongLatWGS84(const GeoHashBits hash, double *xy);\nint geohashDecodeToLongLatMercator(const GeoHashBits hash, double *xy);\nvoid geohashNeighbors(const GeoHashBits *hash, GeoHashNeighbors *neighbors);\n\n#if defined(__cplusplus)\n}\n#endif\n#endif /* GEOHASH_H_ */\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/deps/geohash-int/geohash_helper.c",
    "content": "/*\n * Copyright (c) 2013-2014, yinqiwen <yinqiwen@gmail.com>\n * Copyright (c) 2014, Matt Stancliff <matt@genges.com>.\n * Copyright (c) 2015-2016, Salvatore Sanfilippo <antirez@gmail.com>.\n * All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions are met:\n *\n *  * Redistributions of source code must retain the above copyright notice,\n *    this list of conditions and the following disclaimer.\n *  * Redistributions in binary form must reproduce the above copyright\n *    notice, this list of conditions and the following disclaimer in the\n *    documentation and/or other materials provided with the distribution.\n *  * Neither the name of Redis nor the names of its contributors may be used\n *    to endorse or promote products derived from this software without\n *    specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\"\n * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\n * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS\n * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR\n * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF\n * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS\n * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN\n * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)\n * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF\n * THE POSSIBILITY OF SUCH DAMAGE.\n */\n\n/* This is a C++ to C conversion from the ardb project.\n * This file started out as:\n * https://github.com/yinqiwen/ardb/blob/d42503/src/geo/geohash_helper.cpp\n */\n\n#include \"geohash_helper.h\"\n#include <math.h>\n\n#define D_R (M_PI / 180.0)\n#define R_MAJOR 6378137.0\n#define R_MINOR 6356752.3142\n#define RATIO (R_MINOR / R_MAJOR)\n#define ECCENT (sqrt(1.0 - (RATIO *RATIO)))\n#define COM (0.5 * ECCENT)\n\n/// @brief The usual PI/180 constant\nconst double DEG_TO_RAD = 0.017453292519943295769236907684886;\n/// @brief Earth's quatratic mean radius for WGS-84\nconst double EARTH_RADIUS_IN_METERS = 6372797.560856;\n\nconst double MERCATOR_MAX = 20037726.37;\nconst double MERCATOR_MIN = -20037726.37;\n\nstatic inline double deg_rad(double ang) { return ang * D_R; }\nstatic inline double rad_deg(double ang) { return ang / D_R; }\n\n/* This function is used in order to estimate the step (bits precision)\n * of the 9 search area boxes during radius queries. */\nuint8_t geohashEstimateStepsByRadius(double range_meters, double lat) {\n    if (range_meters == 0) return 26;\n    int step = 1;\n    while (range_meters < MERCATOR_MAX) {\n        range_meters *= 2;\n        step++;\n    }\n    step -= 2; /* Make sure range is included in most of the base cases. */\n\n    /* Wider range torwards the poles... Note: it is possible to do better\n     * than this approximation by computing the distance between meridians\n     * at this latitude, but this does the trick for now. */\n    if (lat > 66 || lat < -66) {\n        step--;\n        if (lat > 80 || lat < -80) step--;\n    }\n\n    /* Frame to valid range. */\n    if (step < 1) step = 1;\n    if (step > 26) step = 26;\n    return step;\n}\n\nint geohashBitsComparator(const GeoHashBits *a, const GeoHashBits *b) {\n    /* If step not equal, compare on step.  Else, compare on bits. */\n    return a->step != b->step ? a->step - b->step : a->bits - b->bits;\n}\n\nint geohashBoundingBox(double longitude, double latitude, double radius_meters,\n                       double *bounds) {\n    if (!bounds) return 0;\n\n    double lonr, latr;\n    lonr = deg_rad(longitude);\n    latr = deg_rad(latitude);\n\n    if (radius_meters > EARTH_RADIUS_IN_METERS)\n        radius_meters = EARTH_RADIUS_IN_METERS;\n    double distance = radius_meters / EARTH_RADIUS_IN_METERS;\n    double min_latitude = latr - distance;\n    double max_latitude = latr + distance;\n\n    /* Note: we're being lazy and not accounting for coordinates near poles */\n    double min_longitude, max_longitude;\n    double difference_longitude = asin(sin(distance) / cos(latr));\n    min_longitude = lonr - difference_longitude;\n    max_longitude = lonr + difference_longitude;\n\n    bounds[0] = rad_deg(min_longitude);\n    bounds[1] = rad_deg(min_latitude);\n    bounds[2] = rad_deg(max_longitude);\n    bounds[3] = rad_deg(max_latitude);\n    return 1;\n}\n\n/* Return a set of areas (center + 8) that are able to cover a range query\n * for the specified position and radius. */\nGeoHashRadius geohashGetAreasByRadius(double longitude, double latitude, double radius_meters) {\n    GeoHashRange long_range, lat_range;\n    GeoHashRadius radius;\n    GeoHashBits hash;\n    GeoHashNeighbors neighbors;\n    GeoHashArea area;\n    double min_lon, max_lon, min_lat, max_lat;\n    double bounds[4];\n    int steps;\n\n    geohashBoundingBox(longitude, latitude, radius_meters, bounds);\n    min_lon = bounds[0];\n    min_lat = bounds[1];\n    max_lon = bounds[2];\n    max_lat = bounds[3];\n\n    steps = geohashEstimateStepsByRadius(radius_meters,latitude);\n\n    geohashGetCoordRange(&long_range,&lat_range);\n    geohashEncode(&long_range,&lat_range,longitude,latitude,steps,&hash);\n    geohashNeighbors(&hash,&neighbors);\n    geohashDecode(long_range,lat_range,hash,&area);\n\n    /* Check if the step is enough at the limits of the covered area.\n     * Sometimes when the search area is near an edge of the\n     * area, the estimated step is not small enough, since one of the\n     * north / south / west / east square is too near to the search area\n     * to cover everything. */\n    int decrease_step = 0;\n    {\n        GeoHashArea north, south, east, west;\n\n        geohashDecode(long_range, lat_range, neighbors.north, &north);\n        geohashDecode(long_range, lat_range, neighbors.south, &south);\n        geohashDecode(long_range, lat_range, neighbors.east, &east);\n        geohashDecode(long_range, lat_range, neighbors.west, &west);\n\n        if (geohashGetDistance(longitude,latitude,longitude,north.latitude.max)\n            < radius_meters) decrease_step = 1;\n        if (geohashGetDistance(longitude,latitude,longitude,south.latitude.min)\n            < radius_meters) decrease_step = 1;\n        if (geohashGetDistance(longitude,latitude,east.longitude.max,latitude)\n            < radius_meters) decrease_step = 1;\n        if (geohashGetDistance(longitude,latitude,west.longitude.min,latitude)\n            < radius_meters) decrease_step = 1;\n    }\n\n    if (decrease_step) {\n        steps--;\n        geohashEncode(&long_range,&lat_range,longitude,latitude,steps,&hash);\n        geohashNeighbors(&hash,&neighbors);\n        geohashDecode(long_range,lat_range,hash,&area);\n    }\n\n    /* Exclude the search areas that are useless. */\n    if (area.latitude.min < min_lat) {\n        GZERO(neighbors.south);\n        GZERO(neighbors.south_west);\n        GZERO(neighbors.south_east);\n    }\n    if (area.latitude.max > max_lat) {\n        GZERO(neighbors.north);\n        GZERO(neighbors.north_east);\n        GZERO(neighbors.north_west);\n    }\n    if (area.longitude.min < min_lon) {\n        GZERO(neighbors.west);\n        GZERO(neighbors.south_west);\n        GZERO(neighbors.north_west);\n    }\n    if (area.longitude.max > max_lon) {\n        GZERO(neighbors.east);\n        GZERO(neighbors.south_east);\n        GZERO(neighbors.north_east);\n    }\n    radius.hash = hash;\n    radius.neighbors = neighbors;\n    radius.area = area;\n    return radius;\n}\n\nGeoHashRadius geohashGetAreasByRadiusWGS84(double longitude, double latitude,\n                                           double radius_meters) {\n    return geohashGetAreasByRadius(longitude, latitude, radius_meters);\n}\n\nGeoHashFix52Bits geohashAlign52Bits(const GeoHashBits hash) {\n    uint64_t bits = hash.bits;\n    bits <<= (52 - hash.step * 2);\n    return bits;\n}\n\n/* Calculate distance using haversin great circle distance formula. */\ndouble geohashGetDistance(double lon1d, double lat1d, double lon2d, double lat2d) {\n    double lat1r, lon1r, lat2r, lon2r, u, v;\n    lat1r = deg_rad(lat1d);\n    lon1r = deg_rad(lon1d);\n    lat2r = deg_rad(lat2d);\n    lon2r = deg_rad(lon2d);\n    u = sin((lat2r - lat1r) / 2);\n    v = sin((lon2r - lon1r) / 2);\n    return 2.0 * EARTH_RADIUS_IN_METERS *\n           asin(sqrt(u * u + cos(lat1r) * cos(lat2r) * v * v));\n}\n\nint geohashGetDistanceIfInRadius(double x1, double y1,\n                                 double x2, double y2, double radius,\n                                 double *distance) {\n    *distance = geohashGetDistance(x1, y1, x2, y2);\n    if (*distance > radius) return 0;\n    return 1;\n}\n\nint geohashGetDistanceIfInRadiusWGS84(double x1, double y1, double x2,\n                                      double y2, double radius,\n                                      double *distance) {\n    return geohashGetDistanceIfInRadius(x1, y1, x2, y2, radius, distance);\n}\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/deps/geohash-int/geohash_helper.h",
    "content": "/*\n * Copyright (c) 2013-2014, yinqiwen <yinqiwen@gmail.com>\n * Copyright (c) 2014, Matt Stancliff <matt@genges.com>.\n * Copyright (c) 2015, Salvatore Sanfilippo <antirez@gmail.com>.\n * All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions are met:\n *\n *  * Redistributions of source code must retain the above copyright notice,\n *    this list of conditions and the following disclaimer.\n *  * Redistributions in binary form must reproduce the above copyright\n *    notice, this list of conditions and the following disclaimer in the\n *    documentation and/or other materials provided with the distribution.\n *  * Neither the name of Redis nor the names of its contributors may be used\n *    to endorse or promote products derived from this software without\n *    specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\"\n * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\n * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS\n * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR\n * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF\n * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS\n * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN\n * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)\n * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF\n * THE POSSIBILITY OF SUCH DAMAGE.\n */\n\n#ifndef GEOHASH_HELPER_HPP_\n#define GEOHASH_HELPER_HPP_\n\n#include <math.h>\n#include \"geohash.h\"\n\n#define GZERO(s) s.bits = s.step = 0;\n#define GISZERO(s) (!s.bits && !s.step)\n#define GISNOTZERO(s) (s.bits || s.step)\n\ntypedef uint64_t GeoHashFix52Bits;\ntypedef uint64_t GeoHashVarBits;\n\ntypedef struct {\n    GeoHashBits hash;\n    GeoHashArea area;\n    GeoHashNeighbors neighbors;\n} GeoHashRadius;\n\nint GeoHashBitsComparator(const GeoHashBits *a, const GeoHashBits *b);\nuint8_t geohashEstimateStepsByRadius(double range_meters, double lat);\nint geohashBoundingBox(double longitude, double latitude, double radius_meters,\n                        double *bounds);\nGeoHashRadius geohashGetAreasByRadius(double longitude,\n                                      double latitude, double radius_meters);\nGeoHashRadius geohashGetAreasByRadiusWGS84(double longitude, double latitude,\n                                           double radius_meters);\nGeoHashRadius geohashGetAreasByRadiusMercator(double longitude, double latitude,\n                                              double radius_meters);\nGeoHashFix52Bits geohashAlign52Bits(const GeoHashBits hash);\ndouble geohashGetDistance(double lon1d, double lat1d,\n                          double lon2d, double lat2d);\nint geohashGetDistanceIfInRadius(double x1, double y1,\n                                 double x2, double y2, double radius,\n                                 double *distance);\nint geohashGetDistanceIfInRadiusWGS84(double x1, double y1, double x2,\n                                      double y2, double radius,\n                                      double *distance);\n\n#endif /* GEOHASH_HELPER_HPP_ */\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/deps/hiredis/.gitignore",
    "content": "/hiredis-test\n/examples/hiredis-example*\n/*.o\n/*.so\n/*.dylib\n/*.a\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/deps/hiredis/.travis.yml",
    "content": "language: c\ncompiler:\n  - gcc\n  - clang\n\nscript: make && make check\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/deps/hiredis/CHANGELOG.md",
    "content": "### 0.11.0\n\n* Increase the maximum multi-bulk reply depth to 7.\n\n* Increase the read buffer size from 2k to 16k.\n\n* Use poll(2) instead of select(2) to support large fds (>= 1024).\n\n### 0.10.1\n\n* Makefile overhaul. Important to check out if you override one or more\n  variables using environment variables or via arguments to the \"make\" tool.\n\n* Issue #45: Fix potential memory leak for a multi bulk reply with 0 elements\n  being created by the default reply object functions.\n\n* Issue #43: Don't crash in an asynchronous context when Redis returns an error\n  reply after the connection has been made (this happens when the maximum\n  number of connections is reached).\n\n### 0.10.0\n\n* See commit log.\n\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/deps/hiredis/COPYING",
    "content": "Copyright (c) 2009-2011, Salvatore Sanfilippo <antirez at gmail dot com>\nCopyright (c) 2010-2011, Pieter Noordhuis <pcnoordhuis at gmail dot com>\n\nAll rights reserved.\n\nRedistribution and use in source and binary forms, with or without\nmodification, are permitted provided that the following conditions are met:\n\n* Redistributions of source code must retain the above copyright notice,\n  this list of conditions and the following disclaimer.\n\n* Redistributions in binary form must reproduce the above copyright notice,\n  this list of conditions and the following disclaimer in the documentation\n  and/or other materials provided with the distribution.\n\n* Neither the name of Redis nor the names of its contributors may be used\n  to endorse or promote products derived from this software without specific\n  prior written permission.\n\nTHIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND\nANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\nWARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\nDISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR\nANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\nLOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON\nANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\nSOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/deps/hiredis/Makefile",
    "content": "# Hiredis Makefile\n# Copyright (C) 2010-2011 Salvatore Sanfilippo <antirez at gmail dot com>\n# Copyright (C) 2010-2011 Pieter Noordhuis <pcnoordhuis at gmail dot com>\n# This file is released under the BSD license, see the COPYING file\n\nOBJ=net.o hiredis.o sds.o async.o\nEXAMPLES=hiredis-example hiredis-example-libevent hiredis-example-libev\nTESTS=hiredis-test\nLIBNAME=libhiredis\n\nHIREDIS_MAJOR=0\nHIREDIS_MINOR=11\n\n# redis-server configuration used for testing\nREDIS_PORT=56379\nREDIS_SERVER=redis-server\ndefine REDIS_TEST_CONFIG\n\tdaemonize yes\n\tpidfile /tmp/hiredis-test-redis.pid\n\tport $(REDIS_PORT)\n\tbind 127.0.0.1\n\tunixsocket /tmp/hiredis-test-redis.sock\nendef\nexport REDIS_TEST_CONFIG\n\n# Fallback to gcc when $CC is not in $PATH.\nCC:=$(shell sh -c 'type $(CC) >/dev/null 2>/dev/null && echo $(CC) || echo gcc')\nOPTIMIZATION?=-O3\nWARNINGS=-Wall -W -Wstrict-prototypes -Wwrite-strings\nDEBUG?= -g -ggdb\nREAL_CFLAGS=$(OPTIMIZATION) -fPIC $(CFLAGS) $(WARNINGS) $(DEBUG) $(ARCH)\nREAL_LDFLAGS=$(LDFLAGS) $(ARCH)\n\nDYLIBSUFFIX=so\nSTLIBSUFFIX=a\nDYLIB_MINOR_NAME=$(LIBNAME).$(DYLIBSUFFIX).$(HIREDIS_MAJOR).$(HIREDIS_MINOR)\nDYLIB_MAJOR_NAME=$(LIBNAME).$(DYLIBSUFFIX).$(HIREDIS_MAJOR)\nDYLIBNAME=$(LIBNAME).$(DYLIBSUFFIX)\nDYLIB_MAKE_CMD=$(CC) -shared -Wl,-soname,$(DYLIB_MINOR_NAME) -o $(DYLIBNAME) $(LDFLAGS)\nSTLIBNAME=$(LIBNAME).$(STLIBSUFFIX)\nSTLIB_MAKE_CMD=ar rcs $(STLIBNAME)\n\n# Platform-specific overrides\nuname_S := $(shell sh -c 'uname -s 2>/dev/null || echo not')\nifeq ($(uname_S),SunOS)\n  REAL_LDFLAGS+= -ldl -lnsl -lsocket\n  DYLIB_MAKE_CMD=$(CC) -G -o $(DYLIBNAME) -h $(DYLIB_MINOR_NAME) $(LDFLAGS)\n  INSTALL= cp -r\nendif\nifeq ($(uname_S),Darwin)\n  DYLIBSUFFIX=dylib\n  DYLIB_MINOR_NAME=$(LIBNAME).$(HIREDIS_MAJOR).$(HIREDIS_MINOR).$(DYLIBSUFFIX)\n  DYLIB_MAJOR_NAME=$(LIBNAME).$(HIREDIS_MAJOR).$(DYLIBSUFFIX)\n  DYLIB_MAKE_CMD=$(CC) -shared -Wl,-install_name,$(DYLIB_MINOR_NAME) -o $(DYLIBNAME) $(LDFLAGS)\nendif\n\nall: $(DYLIBNAME)\n\n# Deps (use make dep to generate this)\nnet.o: net.c fmacros.h net.h hiredis.h\nasync.o: async.c async.h hiredis.h sds.h dict.c dict.h\nhiredis.o: hiredis.c fmacros.h hiredis.h net.h sds.h\nsds.o: sds.c sds.h\ntest.o: test.c hiredis.h\n\n$(DYLIBNAME): $(OBJ)\n\t$(DYLIB_MAKE_CMD) $(OBJ)\n\n$(STLIBNAME): $(OBJ)\n\t$(STLIB_MAKE_CMD) $(OBJ)\n\ndynamic: $(DYLIBNAME)\nstatic: $(STLIBNAME)\n\n# Binaries:\nhiredis-example-libevent: examples/example-libevent.c adapters/libevent.h $(STLIBNAME)\n\t$(CC) -o examples/$@ $(REAL_CFLAGS) $(REAL_LDFLAGS) -I. $< -levent $(STLIBNAME)\n\nhiredis-example-libev: examples/example-libev.c adapters/libev.h $(STLIBNAME)\n\t$(CC) -o examples/$@ $(REAL_CFLAGS) $(REAL_LDFLAGS) -I. $< -lev $(STLIBNAME)\n\nifndef AE_DIR\nhiredis-example-ae:\n\t@echo \"Please specify AE_DIR (e.g. <redis repository>/src)\"\n\t@false\nelse\nhiredis-example-ae: examples/example-ae.c adapters/ae.h $(STLIBNAME)\n\t$(CC) -o examples/$@ $(REAL_CFLAGS) $(REAL_LDFLAGS) -I. -I$(AE_DIR) $< $(AE_DIR)/ae.o $(AE_DIR)/zmalloc.o $(AE_DIR)/../deps/jemalloc/lib/libjemalloc.a -pthread $(STLIBNAME)\nendif\n\nifndef LIBUV_DIR\nhiredis-example-libuv:\n\t@echo \"Please specify LIBUV_DIR (e.g. ../libuv/)\"\n\t@false\nelse\nhiredis-example-libuv: examples/example-libuv.c adapters/libuv.h $(STLIBNAME)\n\t$(CC) -o examples/$@ $(REAL_CFLAGS) $(REAL_LDFLAGS) -I. -I$(LIBUV_DIR)/include $< $(LIBUV_DIR)/.libs/libuv.a -lpthread $(STLIBNAME)\nendif\n\nhiredis-example: examples/example.c $(STLIBNAME)\n\t$(CC) -o examples/$@ $(REAL_CFLAGS) $(REAL_LDFLAGS) -I. $< $(STLIBNAME)\n\nexamples: $(EXAMPLES)\n\nhiredis-test: test.o $(STLIBNAME)\n\t$(CC) -o $@ $(REAL_LDFLAGS) $< $(STLIBNAME)\n\ntest: hiredis-test\n\t./hiredis-test\n\ncheck: hiredis-test\n\t@echo \"$$REDIS_TEST_CONFIG\" | $(REDIS_SERVER) -\n\t./hiredis-test -h 127.0.0.1 -p $(REDIS_PORT) -s /tmp/hiredis-test-redis.sock || \\\n\t\t\t( kill `cat /tmp/hiredis-test-redis.pid` && false )\n\tkill `cat /tmp/hiredis-test-redis.pid`\n\n.c.o:\n\t$(CC) -std=c99 -pedantic -c $(REAL_CFLAGS) $<\n\nclean:\n\trm -rf $(DYLIBNAME) $(STLIBNAME) $(TESTS) examples/hiredis-example* *.o *.gcda *.gcno *.gcov\n\ndep:\n\t$(CC) -MM *.c\n\n# Installation related variables and target\nPREFIX?=/usr/local\nINSTALL_INCLUDE_PATH= $(PREFIX)/include/hiredis\nINSTALL_LIBRARY_PATH= $(PREFIX)/lib\n\nifeq ($(uname_S),SunOS)\n  INSTALL?= cp -r\nendif\n\nINSTALL?= cp -a\n\ninstall: $(DYLIBNAME) $(STLIBNAME)\n\tmkdir -p $(INSTALL_INCLUDE_PATH) $(INSTALL_LIBRARY_PATH)\n\t$(INSTALL) hiredis.h async.h adapters $(INSTALL_INCLUDE_PATH)\n\t$(INSTALL) $(DYLIBNAME) $(INSTALL_LIBRARY_PATH)/$(DYLIB_MINOR_NAME)\n\tcd $(INSTALL_LIBRARY_PATH) && ln -sf $(DYLIB_MINOR_NAME) $(DYLIB_MAJOR_NAME)\n\tcd $(INSTALL_LIBRARY_PATH) && ln -sf $(DYLIB_MAJOR_NAME) $(DYLIBNAME)\n\t$(INSTALL) $(STLIBNAME) $(INSTALL_LIBRARY_PATH)\n\n32bit:\n\t@echo \"\"\n\t@echo \"WARNING: if this fails under Linux you probably need to install libc6-dev-i386\"\n\t@echo \"\"\n\t$(MAKE) CFLAGS=\"-m32\" LDFLAGS=\"-m32\"\n\ngprof:\n\t$(MAKE) CFLAGS=\"-pg\" LDFLAGS=\"-pg\"\n\ngcov:\n\t$(MAKE) CFLAGS=\"-fprofile-arcs -ftest-coverage\" LDFLAGS=\"-fprofile-arcs\"\n\ncoverage: gcov\n\tmake check\n\tmkdir -p tmp/lcov\n\tlcov -d . -c -o tmp/lcov/hiredis.info\n\tgenhtml --legend -o tmp/lcov/report tmp/lcov/hiredis.info\n\nnoopt:\n\t$(MAKE) OPTIMIZATION=\"\"\n\n.PHONY: all test check clean dep install 32bit gprof gcov noopt\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/deps/hiredis/README.md",
    "content": "[![Build Status](https://travis-ci.org/redis/hiredis.png)](https://travis-ci.org/redis/hiredis)\n\n# HIREDIS\n\nHiredis is a minimalistic C client library for the [Redis](http://redis.io/) database.\n\nIt is minimalistic because it just adds minimal support for the protocol, but\nat the same time it uses an high level printf-alike API in order to make it\nmuch higher level than otherwise suggested by its minimal code base and the\nlack of explicit bindings for every Redis command.\n\nApart from supporting sending commands and receiving replies, it comes with\na reply parser that is decoupled from the I/O layer. It\nis a stream parser designed for easy reusability, which can for instance be used\nin higher level language bindings for efficient reply parsing.\n\nHiredis only supports the binary-safe Redis protocol, so you can use it with any\nRedis version >= 1.2.0.\n\nThe library comes with multiple APIs. There is the\n*synchronous API*, the *asynchronous API* and the *reply parsing API*.\n\n## UPGRADING\n\nVersion 0.9.0 is a major overhaul of hiredis in every aspect. However, upgrading existing\ncode using hiredis should not be a big pain. The key thing to keep in mind when\nupgrading is that hiredis >= 0.9.0 uses a `redisContext*` to keep state, in contrast to\nthe stateless 0.0.1 that only has a file descriptor to work with.\n\n## Synchronous API\n\nTo consume the synchronous API, there are only a few function calls that need to be introduced:\n\n    redisContext *redisConnect(const char *ip, int port);\n    void *redisCommand(redisContext *c, const char *format, ...);\n    void freeReplyObject(void *reply);\n\n### Connecting\n\nThe function `redisConnect` is used to create a so-called `redisContext`. The\ncontext is where Hiredis holds state for a connection. The `redisContext`\nstruct has an integer `err` field that is non-zero when an the connection is in\nan error state. The field `errstr` will contain a string with a description of\nthe error. More information on errors can be found in the **Errors** section.\nAfter trying to connect to Redis using `redisConnect` you should\ncheck the `err` field to see if establishing the connection was successful:\n\n    redisContext *c = redisConnect(\"127.0.0.1\", 6379);\n    if (c != NULL && c->err) {\n        printf(\"Error: %s\\n\", c->errstr);\n        // handle error\n    }\n\n### Sending commands\n\nThere are several ways to issue commands to Redis. The first that will be introduced is\n`redisCommand`. This function takes a format similar to printf. In the simplest form,\nit is used like this:\n\n    reply = redisCommand(context, \"SET foo bar\");\n\nThe specifier `%s` interpolates a string in the command, and uses `strlen` to\ndetermine the length of the string:\n\n    reply = redisCommand(context, \"SET foo %s\", value);\n\nWhen you need to pass binary safe strings in a command, the `%b` specifier can be\nused. Together with a pointer to the string, it requires a `size_t` length argument\nof the string:\n\n    reply = redisCommand(context, \"SET foo %b\", value, (size_t) valuelen);\n\nInternally, Hiredis splits the command in different arguments and will\nconvert it to the protocol used to communicate with Redis.\nOne or more spaces separates arguments, so you can use the specifiers\nanywhere in an argument:\n\n    reply = redisCommand(context, \"SET key:%s %s\", myid, value);\n\n### Using replies\n\nThe return value of `redisCommand` holds a reply when the command was\nsuccessfully executed. When an error occurs, the return value is `NULL` and\nthe `err` field in the context will be set (see section on **Errors**).\nOnce an error is returned the context cannot be reused and you should set up\na new connection.\n\nThe standard replies that `redisCommand` are of the type `redisReply`. The\n`type` field in the `redisReply` should be used to test what kind of reply\nwas received:\n\n* **`REDIS_REPLY_STATUS`**:\n    * The command replied with a status reply. The status string can be accessed using `reply->str`.\n      The length of this string can be accessed using `reply->len`.\n\n* **`REDIS_REPLY_ERROR`**:\n    *  The command replied with an error. The error string can be accessed identical to `REDIS_REPLY_STATUS`.\n\n* **`REDIS_REPLY_INTEGER`**:\n    * The command replied with an integer. The integer value can be accessed using the\n      `reply->integer` field of type `long long`.\n\n* **`REDIS_REPLY_NIL`**:\n    * The command replied with a **nil** object. There is no data to access.\n\n* **`REDIS_REPLY_STRING`**:\n    * A bulk (string) reply. The value of the reply can be accessed using `reply->str`.\n      The length of this string can be accessed using `reply->len`.\n\n* **`REDIS_REPLY_ARRAY`**:\n    * A multi bulk reply. The number of elements in the multi bulk reply is stored in\n      `reply->elements`. Every element in the multi bulk reply is a `redisReply` object as well\n      and can be accessed via `reply->element[..index..]`.\n      Redis may reply with nested arrays but this is fully supported.\n\nReplies should be freed using the `freeReplyObject()` function.\nNote that this function will take care of freeing sub-replies objects\ncontained in arrays and nested arrays, so there is no need for the user to\nfree the sub replies (it is actually harmful and will corrupt the memory).\n\n**Important:** the current version of hiredis (0.10.0) free's replies when the\nasynchronous API is used. This means you should not call `freeReplyObject` when\nyou use this API. The reply is cleaned up by hiredis _after_ the callback\nreturns. This behavior will probably change in future releases, so make sure to\nkeep an eye on the changelog when upgrading (see issue #39).\n\n### Cleaning up\n\nTo disconnect and free the context the following function can be used:\n\n    void redisFree(redisContext *c);\n\nThis function immediately closes the socket and then free's the allocations done in\ncreating the context.\n\n### Sending commands (cont'd)\n\nTogether with `redisCommand`, the function `redisCommandArgv` can be used to issue commands.\nIt has the following prototype:\n\n    void *redisCommandArgv(redisContext *c, int argc, const char **argv, const size_t *argvlen);\n\nIt takes the number of arguments `argc`, an array of strings `argv` and the lengths of the\narguments `argvlen`. For convenience, `argvlen` may be set to `NULL` and the function will\nuse `strlen(3)` on every argument to determine its length. Obviously, when any of the arguments\nneed to be binary safe, the entire array of lengths `argvlen` should be provided.\n\nThe return value has the same semantic as `redisCommand`.\n\n### Pipelining\n\nTo explain how Hiredis supports pipelining in a blocking connection, there needs to be\nunderstanding of the internal execution flow.\n\nWhen any of the functions in the `redisCommand` family is called, Hiredis first formats the\ncommand according to the Redis protocol. The formatted command is then put in the output buffer\nof the context. This output buffer is dynamic, so it can hold any number of commands.\nAfter the command is put in the output buffer, `redisGetReply` is called. This function has the\nfollowing two execution paths:\n\n1. The input buffer is non-empty:\n    * Try to parse a single reply from the input buffer and return it\n    * If no reply could be parsed, continue at *2*\n2. The input buffer is empty:\n    * Write the **entire** output buffer to the socket\n    * Read from the socket until a single reply could be parsed\n\nThe function `redisGetReply` is exported as part of the Hiredis API and can be used when a reply\nis expected on the socket. To pipeline commands, the only things that needs to be done is\nfilling up the output buffer. For this cause, two commands can be used that are identical\nto the `redisCommand` family, apart from not returning a reply:\n\n    void redisAppendCommand(redisContext *c, const char *format, ...);\n    void redisAppendCommandArgv(redisContext *c, int argc, const char **argv, const size_t *argvlen);\n\nAfter calling either function one or more times, `redisGetReply` can be used to receive the\nsubsequent replies. The return value for this function is either `REDIS_OK` or `REDIS_ERR`, where\nthe latter means an error occurred while reading a reply. Just as with the other commands,\nthe `err` field in the context can be used to find out what the cause of this error is.\n\nThe following examples shows a simple pipeline (resulting in only a single call to `write(2)` and\na single call to `read(2)`):\n\n    redisReply *reply;\n    redisAppendCommand(context,\"SET foo bar\");\n    redisAppendCommand(context,\"GET foo\");\n    redisGetReply(context,&reply); // reply for SET\n    freeReplyObject(reply);\n    redisGetReply(context,&reply); // reply for GET\n    freeReplyObject(reply);\n\nThis API can also be used to implement a blocking subscriber:\n\n    reply = redisCommand(context,\"SUBSCRIBE foo\");\n    freeReplyObject(reply);\n    while(redisGetReply(context,&reply) == REDIS_OK) {\n        // consume message\n        freeReplyObject(reply);\n    }\n\n### Errors\n\nWhen a function call is not successful, depending on the function either `NULL` or `REDIS_ERR` is\nreturned. The `err` field inside the context will be non-zero and set to one of the\nfollowing constants:\n\n* **`REDIS_ERR_IO`**:\n    There was an I/O error while creating the connection, trying to write\n    to the socket or read from the socket. If you included `errno.h` in your\n    application, you can use the global `errno` variable to find out what is\n    wrong.\n\n* **`REDIS_ERR_EOF`**:\n    The server closed the connection which resulted in an empty read.\n\n* **`REDIS_ERR_PROTOCOL`**:\n    There was an error while parsing the protocol.\n\n* **`REDIS_ERR_OTHER`**:\n    Any other error. Currently, it is only used when a specified hostname to connect\n    to cannot be resolved.\n\nIn every case, the `errstr` field in the context will be set to hold a string representation\nof the error.\n\n## Asynchronous API\n\nHiredis comes with an asynchronous API that works easily with any event library.\nExamples are bundled that show using Hiredis with [libev](http://software.schmorp.de/pkg/libev.html)\nand [libevent](http://monkey.org/~provos/libevent/).\n\n### Connecting\n\nThe function `redisAsyncConnect` can be used to establish a non-blocking connection to\nRedis. It returns a pointer to the newly created `redisAsyncContext` struct. The `err` field\nshould be checked after creation to see if there were errors creating the connection.\nBecause the connection that will be created is non-blocking, the kernel is not able to\ninstantly return if the specified host and port is able to accept a connection.\n\n    redisAsyncContext *c = redisAsyncConnect(\"127.0.0.1\", 6379);\n    if (c->err) {\n        printf(\"Error: %s\\n\", c->errstr);\n        // handle error\n    }\n\nThe asynchronous context can hold a disconnect callback function that is called when the\nconnection is disconnected (either because of an error or per user request). This function should\nhave the following prototype:\n\n    void(const redisAsyncContext *c, int status);\n\nOn a disconnect, the `status` argument is set to `REDIS_OK` when disconnection was initiated by the\nuser, or `REDIS_ERR` when the disconnection was caused by an error. When it is `REDIS_ERR`, the `err`\nfield in the context can be accessed to find out the cause of the error.\n\nThe context object is always free'd after the disconnect callback fired. When a reconnect is needed,\nthe disconnect callback is a good point to do so.\n\nSetting the disconnect callback can only be done once per context. For subsequent calls it will\nreturn `REDIS_ERR`. The function to set the disconnect callback has the following prototype:\n\n    int redisAsyncSetDisconnectCallback(redisAsyncContext *ac, redisDisconnectCallback *fn);\n\n### Sending commands and their callbacks\n\nIn an asynchronous context, commands are automatically pipelined due to the nature of an event loop.\nTherefore, unlike the synchronous API, there is only a single way to send commands.\nBecause commands are sent to Redis asynchronously, issuing a command requires a callback function\nthat is called when the reply is received. Reply callbacks should have the following prototype:\n\n    void(redisAsyncContext *c, void *reply, void *privdata);\n\nThe `privdata` argument can be used to curry arbitrary data to the callback from the point where\nthe command is initially queued for execution.\n\nThe functions that can be used to issue commands in an asynchronous context are:\n\n    int redisAsyncCommand(\n      redisAsyncContext *ac, redisCallbackFn *fn, void *privdata,\n      const char *format, ...);\n    int redisAsyncCommandArgv(\n      redisAsyncContext *ac, redisCallbackFn *fn, void *privdata,\n      int argc, const char **argv, const size_t *argvlen);\n\nBoth functions work like their blocking counterparts. The return value is `REDIS_OK` when the command\nwas successfully added to the output buffer and `REDIS_ERR` otherwise. Example: when the connection\nis being disconnected per user-request, no new commands may be added to the output buffer and `REDIS_ERR` is\nreturned on calls to the `redisAsyncCommand` family.\n\nIf the reply for a command with a `NULL` callback is read, it is immediately free'd. When the callback\nfor a command is non-`NULL`, the memory is free'd immediately following the callback: the reply is only\nvalid for the duration of the callback.\n\nAll pending callbacks are called with a `NULL` reply when the context encountered an error.\n\n### Disconnecting\n\nAn asynchronous connection can be terminated using:\n\n    void redisAsyncDisconnect(redisAsyncContext *ac);\n\nWhen this function is called, the connection is **not** immediately terminated. Instead, new\ncommands are no longer accepted and the connection is only terminated when all pending commands\nhave been written to the socket, their respective replies have been read and their respective\ncallbacks have been executed. After this, the disconnection callback is executed with the\n`REDIS_OK` status and the context object is free'd.\n\n### Hooking it up to event library *X*\n\nThere are a few hooks that need to be set on the context object after it is created.\nSee the `adapters/` directory for bindings to *libev* and *libevent*.\n\n## Reply parsing API\n\nHiredis comes with a reply parsing API that makes it easy for writing higher\nlevel language bindings.\n\nThe reply parsing API consists of the following functions:\n\n    redisReader *redisReaderCreate(void);\n    void redisReaderFree(redisReader *reader);\n    int redisReaderFeed(redisReader *reader, const char *buf, size_t len);\n    int redisReaderGetReply(redisReader *reader, void **reply);\n\nThe same set of functions are used internally by hiredis when creating a\nnormal Redis context, the above API just exposes it to the user for a direct\nusage.\n\n### Usage\n\nThe function `redisReaderCreate` creates a `redisReader` structure that holds a\nbuffer with unparsed data and state for the protocol parser.\n\nIncoming data -- most likely from a socket -- can be placed in the internal\nbuffer of the `redisReader` using `redisReaderFeed`. This function will make a\ncopy of the buffer pointed to by `buf` for `len` bytes. This data is parsed\nwhen `redisReaderGetReply` is called. This function returns an integer status\nand a reply object (as described above) via `void **reply`. The returned status\ncan be either `REDIS_OK` or `REDIS_ERR`, where the latter means something went\nwrong (either a protocol error, or an out of memory error).\n\nThe parser limits the level of nesting for multi bulk payloads to 7. If the\nmulti bulk nesting level is higher than this, the parser returns an error.\n\n### Customizing replies\n\nThe function `redisReaderGetReply` creates `redisReply` and makes the function\nargument `reply` point to the created `redisReply` variable. For instance, if\nthe response of type `REDIS_REPLY_STATUS` then the `str` field of `redisReply`\nwill hold the status as a vanilla C string. However, the functions that are\nresponsible for creating instances of the `redisReply` can be customized by\nsetting the `fn` field on the `redisReader` struct. This should be done\nimmediately after creating the `redisReader`.\n\nFor example, [hiredis-rb](https://github.com/pietern/hiredis-rb/blob/master/ext/hiredis_ext/reader.c)\nuses customized reply object functions to create Ruby objects.\n\n### Reader max buffer\n\nBoth when using the Reader API directly or when using it indirectly via a\nnormal Redis context, the redisReader structure uses a buffer in order to\naccumulate data from the server.\nUsually this buffer is destroyed when it is empty and is larger than 16\nkb in order to avoid wasting memory in unused buffers\n\nHowever when working with very big payloads destroying the buffer may slow\ndown performances considerably, so it is possible to modify the max size of\nan idle buffer changing the value of the `maxbuf` field of the reader structure\nto the desired value. The special value of 0 means that there is no maximum\nvalue for an idle buffer, so the buffer will never get freed.\n\nFor instance if you have a normal Redis context you can set the maximum idle\nbuffer to zero (unlimited) just with:\n\n    context->reader->maxbuf = 0;\n\nThis should be done only in order to maximize performances when working with\nlarge payloads. The context should be set back to `REDIS_READER_MAX_BUF` again\nas soon as possible in order to prevent allocation of useless memory.\n\n## AUTHORS\n\nHiredis was written by Salvatore Sanfilippo (antirez at gmail) and\nPieter Noordhuis (pcnoordhuis at gmail) and is released under the BSD license.\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/deps/hiredis/adapters/ae.h",
    "content": "/*\n * Copyright (c) 2010-2011, Pieter Noordhuis <pcnoordhuis at gmail dot com>\n *\n * All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions are met:\n *\n *   * Redistributions of source code must retain the above copyright notice,\n *     this list of conditions and the following disclaimer.\n *   * Redistributions in binary form must reproduce the above copyright\n *     notice, this list of conditions and the following disclaimer in the\n *     documentation and/or other materials provided with the distribution.\n *   * Neither the name of Redis nor the names of its contributors may be used\n *     to endorse or promote products derived from this software without\n *     specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\"\n * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\n * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE\n * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR\n * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF\n * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS\n * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN\n * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)\n * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE\n * POSSIBILITY OF SUCH DAMAGE.\n */\n\n#ifndef __HIREDIS_AE_H__\n#define __HIREDIS_AE_H__\n#include <sys/types.h>\n#include <ae.h>\n#include \"../hiredis.h\"\n#include \"../async.h\"\n\ntypedef struct redisAeEvents {\n    redisAsyncContext *context;\n    aeEventLoop *loop;\n    int fd;\n    int reading, writing;\n} redisAeEvents;\n\nstatic void redisAeReadEvent(aeEventLoop *el, int fd, void *privdata, int mask) {\n    ((void)el); ((void)fd); ((void)mask);\n\n    redisAeEvents *e = (redisAeEvents*)privdata;\n    redisAsyncHandleRead(e->context);\n}\n\nstatic void redisAeWriteEvent(aeEventLoop *el, int fd, void *privdata, int mask) {\n    ((void)el); ((void)fd); ((void)mask);\n\n    redisAeEvents *e = (redisAeEvents*)privdata;\n    redisAsyncHandleWrite(e->context);\n}\n\nstatic void redisAeAddRead(void *privdata) {\n    redisAeEvents *e = (redisAeEvents*)privdata;\n    aeEventLoop *loop = e->loop;\n    if (!e->reading) {\n        e->reading = 1;\n        aeCreateFileEvent(loop,e->fd,AE_READABLE,redisAeReadEvent,e);\n    }\n}\n\nstatic void redisAeDelRead(void *privdata) {\n    redisAeEvents *e = (redisAeEvents*)privdata;\n    aeEventLoop *loop = e->loop;\n    if (e->reading) {\n        e->reading = 0;\n        aeDeleteFileEvent(loop,e->fd,AE_READABLE);\n    }\n}\n\nstatic void redisAeAddWrite(void *privdata) {\n    redisAeEvents *e = (redisAeEvents*)privdata;\n    aeEventLoop *loop = e->loop;\n    if (!e->writing) {\n        e->writing = 1;\n        aeCreateFileEvent(loop,e->fd,AE_WRITABLE,redisAeWriteEvent,e);\n    }\n}\n\nstatic void redisAeDelWrite(void *privdata) {\n    redisAeEvents *e = (redisAeEvents*)privdata;\n    aeEventLoop *loop = e->loop;\n    if (e->writing) {\n        e->writing = 0;\n        aeDeleteFileEvent(loop,e->fd,AE_WRITABLE);\n    }\n}\n\nstatic void redisAeCleanup(void *privdata) {\n    redisAeEvents *e = (redisAeEvents*)privdata;\n    redisAeDelRead(privdata);\n    redisAeDelWrite(privdata);\n    free(e);\n}\n\nstatic int redisAeAttach(aeEventLoop *loop, redisAsyncContext *ac) {\n    redisContext *c = &(ac->c);\n    redisAeEvents *e;\n\n    /* Nothing should be attached when something is already attached */\n    if (ac->ev.data != NULL)\n        return REDIS_ERR;\n\n    /* Create container for context and r/w events */\n    e = (redisAeEvents*)malloc(sizeof(*e));\n    e->context = ac;\n    e->loop = loop;\n    e->fd = c->fd;\n    e->reading = e->writing = 0;\n\n    /* Register functions to start/stop listening for events */\n    ac->ev.addRead = redisAeAddRead;\n    ac->ev.delRead = redisAeDelRead;\n    ac->ev.addWrite = redisAeAddWrite;\n    ac->ev.delWrite = redisAeDelWrite;\n    ac->ev.cleanup = redisAeCleanup;\n    ac->ev.data = e;\n\n    return REDIS_OK;\n}\n#endif\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/deps/hiredis/adapters/libev.h",
    "content": "/*\n * Copyright (c) 2010-2011, Pieter Noordhuis <pcnoordhuis at gmail dot com>\n *\n * All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions are met:\n *\n *   * Redistributions of source code must retain the above copyright notice,\n *     this list of conditions and the following disclaimer.\n *   * Redistributions in binary form must reproduce the above copyright\n *     notice, this list of conditions and the following disclaimer in the\n *     documentation and/or other materials provided with the distribution.\n *   * Neither the name of Redis nor the names of its contributors may be used\n *     to endorse or promote products derived from this software without\n *     specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\"\n * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\n * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE\n * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR\n * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF\n * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS\n * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN\n * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)\n * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE\n * POSSIBILITY OF SUCH DAMAGE.\n */\n\n#ifndef __HIREDIS_LIBEV_H__\n#define __HIREDIS_LIBEV_H__\n#include <stdlib.h>\n#include <sys/types.h>\n#include <ev.h>\n#include \"../hiredis.h\"\n#include \"../async.h\"\n\ntypedef struct redisLibevEvents {\n    redisAsyncContext *context;\n    struct ev_loop *loop;\n    int reading, writing;\n    ev_io rev, wev;\n} redisLibevEvents;\n\nstatic void redisLibevReadEvent(EV_P_ ev_io *watcher, int revents) {\n#if EV_MULTIPLICITY\n    ((void)loop);\n#endif\n    ((void)revents);\n\n    redisLibevEvents *e = (redisLibevEvents*)watcher->data;\n    redisAsyncHandleRead(e->context);\n}\n\nstatic void redisLibevWriteEvent(EV_P_ ev_io *watcher, int revents) {\n#if EV_MULTIPLICITY\n    ((void)loop);\n#endif\n    ((void)revents);\n\n    redisLibevEvents *e = (redisLibevEvents*)watcher->data;\n    redisAsyncHandleWrite(e->context);\n}\n\nstatic void redisLibevAddRead(void *privdata) {\n    redisLibevEvents *e = (redisLibevEvents*)privdata;\n    struct ev_loop *loop = e->loop;\n    ((void)loop);\n    if (!e->reading) {\n        e->reading = 1;\n        ev_io_start(EV_A_ &e->rev);\n    }\n}\n\nstatic void redisLibevDelRead(void *privdata) {\n    redisLibevEvents *e = (redisLibevEvents*)privdata;\n    struct ev_loop *loop = e->loop;\n    ((void)loop);\n    if (e->reading) {\n        e->reading = 0;\n        ev_io_stop(EV_A_ &e->rev);\n    }\n}\n\nstatic void redisLibevAddWrite(void *privdata) {\n    redisLibevEvents *e = (redisLibevEvents*)privdata;\n    struct ev_loop *loop = e->loop;\n    ((void)loop);\n    if (!e->writing) {\n        e->writing = 1;\n        ev_io_start(EV_A_ &e->wev);\n    }\n}\n\nstatic void redisLibevDelWrite(void *privdata) {\n    redisLibevEvents *e = (redisLibevEvents*)privdata;\n    struct ev_loop *loop = e->loop;\n    ((void)loop);\n    if (e->writing) {\n        e->writing = 0;\n        ev_io_stop(EV_A_ &e->wev);\n    }\n}\n\nstatic void redisLibevCleanup(void *privdata) {\n    redisLibevEvents *e = (redisLibevEvents*)privdata;\n    redisLibevDelRead(privdata);\n    redisLibevDelWrite(privdata);\n    free(e);\n}\n\nstatic int redisLibevAttach(EV_P_ redisAsyncContext *ac) {\n    redisContext *c = &(ac->c);\n    redisLibevEvents *e;\n\n    /* Nothing should be attached when something is already attached */\n    if (ac->ev.data != NULL)\n        return REDIS_ERR;\n\n    /* Create container for context and r/w events */\n    e = (redisLibevEvents*)malloc(sizeof(*e));\n    e->context = ac;\n#if EV_MULTIPLICITY\n    e->loop = loop;\n#else\n    e->loop = NULL;\n#endif\n    e->reading = e->writing = 0;\n    e->rev.data = e;\n    e->wev.data = e;\n\n    /* Register functions to start/stop listening for events */\n    ac->ev.addRead = redisLibevAddRead;\n    ac->ev.delRead = redisLibevDelRead;\n    ac->ev.addWrite = redisLibevAddWrite;\n    ac->ev.delWrite = redisLibevDelWrite;\n    ac->ev.cleanup = redisLibevCleanup;\n    ac->ev.data = e;\n\n    /* Initialize read/write events */\n    ev_io_init(&e->rev,redisLibevReadEvent,c->fd,EV_READ);\n    ev_io_init(&e->wev,redisLibevWriteEvent,c->fd,EV_WRITE);\n    return REDIS_OK;\n}\n\n#endif\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/deps/hiredis/adapters/libevent.h",
    "content": "/*\n * Copyright (c) 2010-2011, Pieter Noordhuis <pcnoordhuis at gmail dot com>\n *\n * All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions are met:\n *\n *   * Redistributions of source code must retain the above copyright notice,\n *     this list of conditions and the following disclaimer.\n *   * Redistributions in binary form must reproduce the above copyright\n *     notice, this list of conditions and the following disclaimer in the\n *     documentation and/or other materials provided with the distribution.\n *   * Neither the name of Redis nor the names of its contributors may be used\n *     to endorse or promote products derived from this software without\n *     specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\"\n * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\n * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE\n * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR\n * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF\n * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS\n * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN\n * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)\n * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE\n * POSSIBILITY OF SUCH DAMAGE.\n */\n\n#ifndef __HIREDIS_LIBEVENT_H__\n#define __HIREDIS_LIBEVENT_H__\n#include <event.h>\n#include \"../hiredis.h\"\n#include \"../async.h\"\n\ntypedef struct redisLibeventEvents {\n    redisAsyncContext *context;\n    struct event rev, wev;\n} redisLibeventEvents;\n\nstatic void redisLibeventReadEvent(int fd, short event, void *arg) {\n    ((void)fd); ((void)event);\n    redisLibeventEvents *e = (redisLibeventEvents*)arg;\n    redisAsyncHandleRead(e->context);\n}\n\nstatic void redisLibeventWriteEvent(int fd, short event, void *arg) {\n    ((void)fd); ((void)event);\n    redisLibeventEvents *e = (redisLibeventEvents*)arg;\n    redisAsyncHandleWrite(e->context);\n}\n\nstatic void redisLibeventAddRead(void *privdata) {\n    redisLibeventEvents *e = (redisLibeventEvents*)privdata;\n    event_add(&e->rev,NULL);\n}\n\nstatic void redisLibeventDelRead(void *privdata) {\n    redisLibeventEvents *e = (redisLibeventEvents*)privdata;\n    event_del(&e->rev);\n}\n\nstatic void redisLibeventAddWrite(void *privdata) {\n    redisLibeventEvents *e = (redisLibeventEvents*)privdata;\n    event_add(&e->wev,NULL);\n}\n\nstatic void redisLibeventDelWrite(void *privdata) {\n    redisLibeventEvents *e = (redisLibeventEvents*)privdata;\n    event_del(&e->wev);\n}\n\nstatic void redisLibeventCleanup(void *privdata) {\n    redisLibeventEvents *e = (redisLibeventEvents*)privdata;\n    event_del(&e->rev);\n    event_del(&e->wev);\n    free(e);\n}\n\nstatic int redisLibeventAttach(redisAsyncContext *ac, struct event_base *base) {\n    redisContext *c = &(ac->c);\n    redisLibeventEvents *e;\n\n    /* Nothing should be attached when something is already attached */\n    if (ac->ev.data != NULL)\n        return REDIS_ERR;\n\n    /* Create container for context and r/w events */\n    e = (redisLibeventEvents*)malloc(sizeof(*e));\n    e->context = ac;\n\n    /* Register functions to start/stop listening for events */\n    ac->ev.addRead = redisLibeventAddRead;\n    ac->ev.delRead = redisLibeventDelRead;\n    ac->ev.addWrite = redisLibeventAddWrite;\n    ac->ev.delWrite = redisLibeventDelWrite;\n    ac->ev.cleanup = redisLibeventCleanup;\n    ac->ev.data = e;\n\n    /* Initialize and install read/write events */\n    event_set(&e->rev,c->fd,EV_READ,redisLibeventReadEvent,e);\n    event_set(&e->wev,c->fd,EV_WRITE,redisLibeventWriteEvent,e);\n    event_base_set(base,&e->rev);\n    event_base_set(base,&e->wev);\n    return REDIS_OK;\n}\n#endif\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/deps/hiredis/adapters/libuv.h",
    "content": "#ifndef __HIREDIS_LIBUV_H__\n#define __HIREDIS_LIBUV_H__\n#include <uv.h>\n#include \"../hiredis.h\"\n#include \"../async.h\"\n#include <string.h>\n\ntypedef struct redisLibuvEvents {\n  redisAsyncContext* context;\n  uv_poll_t          handle;\n  int                events;\n} redisLibuvEvents;\n\nint redisLibuvAttach(redisAsyncContext*, uv_loop_t*);\n\nstatic void redisLibuvPoll(uv_poll_t* handle, int status, int events) {\n  redisLibuvEvents* p = (redisLibuvEvents*)handle->data;\n\n  if (status != 0) {\n    return;\n  }\n\n  if (events & UV_READABLE) {\n    redisAsyncHandleRead(p->context);\n  }\n  if (events & UV_WRITABLE) {\n    redisAsyncHandleWrite(p->context);\n  }\n}\n\n\nstatic void redisLibuvAddRead(void *privdata) {\n  redisLibuvEvents* p = (redisLibuvEvents*)privdata;\n\n  p->events |= UV_READABLE;\n\n  uv_poll_start(&p->handle, p->events, redisLibuvPoll);\n}\n\n\nstatic void redisLibuvDelRead(void *privdata) {\n  redisLibuvEvents* p = (redisLibuvEvents*)privdata;\n\n  p->events &= ~UV_READABLE;\n\n  if (p->events) {\n    uv_poll_start(&p->handle, p->events, redisLibuvPoll);\n  } else {\n    uv_poll_stop(&p->handle);\n  }\n}\n\n\nstatic void redisLibuvAddWrite(void *privdata) {\n  redisLibuvEvents* p = (redisLibuvEvents*)privdata;\n\n  p->events |= UV_WRITABLE;\n\n  uv_poll_start(&p->handle, p->events, redisLibuvPoll);\n}\n\n\nstatic void redisLibuvDelWrite(void *privdata) {\n  redisLibuvEvents* p = (redisLibuvEvents*)privdata;\n\n  p->events &= ~UV_WRITABLE;\n\n  if (p->events) {\n    uv_poll_start(&p->handle, p->events, redisLibuvPoll);\n  } else {\n    uv_poll_stop(&p->handle);\n  }\n}\n\n\nstatic void on_close(uv_handle_t* handle) {\n  redisLibuvEvents* p = (redisLibuvEvents*)handle->data;\n\n  free(p);\n}\n\n\nstatic void redisLibuvCleanup(void *privdata) {\n  redisLibuvEvents* p = (redisLibuvEvents*)privdata;\n\n  uv_close((uv_handle_t*)&p->handle, on_close);\n}\n\n\nstatic int redisLibuvAttach(redisAsyncContext* ac, uv_loop_t* loop) {\n  redisContext *c = &(ac->c);\n\n  if (ac->ev.data != NULL) {\n    return REDIS_ERR;\n  }\n\n  ac->ev.addRead  = redisLibuvAddRead;\n  ac->ev.delRead  = redisLibuvDelRead;\n  ac->ev.addWrite = redisLibuvAddWrite;\n  ac->ev.delWrite = redisLibuvDelWrite;\n  ac->ev.cleanup  = redisLibuvCleanup;\n\n  redisLibuvEvents* p = (redisLibuvEvents*)malloc(sizeof(*p));\n\n  if (!p) {\n    return REDIS_ERR;\n  }\n\n  memset(p, 0, sizeof(*p));\n\n  if (uv_poll_init(loop, &p->handle, c->fd) != 0) {\n    return REDIS_ERR;\n  }\n\n  ac->ev.data    = p;\n  p->handle.data = p;\n  p->context     = ac;\n\n  return REDIS_OK;\n}\n#endif\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/deps/hiredis/async.c",
    "content": "/*\n * Copyright (c) 2009-2011, Salvatore Sanfilippo <antirez at gmail dot com>\n * Copyright (c) 2010-2011, Pieter Noordhuis <pcnoordhuis at gmail dot com>\n *\n * All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions are met:\n *\n *   * Redistributions of source code must retain the above copyright notice,\n *     this list of conditions and the following disclaimer.\n *   * Redistributions in binary form must reproduce the above copyright\n *     notice, this list of conditions and the following disclaimer in the\n *     documentation and/or other materials provided with the distribution.\n *   * Neither the name of Redis nor the names of its contributors may be used\n *     to endorse or promote products derived from this software without\n *     specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\"\n * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\n * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE\n * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR\n * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF\n * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS\n * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN\n * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)\n * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE\n * POSSIBILITY OF SUCH DAMAGE.\n */\n\n#include \"fmacros.h\"\n#include <stdlib.h>\n#include <string.h>\n#include <strings.h>\n#include <assert.h>\n#include <ctype.h>\n#include <errno.h>\n#include \"async.h\"\n#include \"net.h\"\n#include \"dict.c\"\n#include \"sds.h\"\n\n#define _EL_ADD_READ(ctx) do { \\\n        if ((ctx)->ev.addRead) (ctx)->ev.addRead((ctx)->ev.data); \\\n    } while(0)\n#define _EL_DEL_READ(ctx) do { \\\n        if ((ctx)->ev.delRead) (ctx)->ev.delRead((ctx)->ev.data); \\\n    } while(0)\n#define _EL_ADD_WRITE(ctx) do { \\\n        if ((ctx)->ev.addWrite) (ctx)->ev.addWrite((ctx)->ev.data); \\\n    } while(0)\n#define _EL_DEL_WRITE(ctx) do { \\\n        if ((ctx)->ev.delWrite) (ctx)->ev.delWrite((ctx)->ev.data); \\\n    } while(0)\n#define _EL_CLEANUP(ctx) do { \\\n        if ((ctx)->ev.cleanup) (ctx)->ev.cleanup((ctx)->ev.data); \\\n    } while(0);\n\n/* Forward declaration of function in hiredis.c */\nvoid __redisAppendCommand(redisContext *c, char *cmd, size_t len);\n\n/* Functions managing dictionary of callbacks for pub/sub. */\nstatic unsigned int callbackHash(const void *key) {\n    return dictGenHashFunction((const unsigned char *)key,\n                               sdslen((const sds)key));\n}\n\nstatic void *callbackValDup(void *privdata, const void *src) {\n    ((void) privdata);\n    redisCallback *dup = malloc(sizeof(*dup));\n    memcpy(dup,src,sizeof(*dup));\n    return dup;\n}\n\nstatic int callbackKeyCompare(void *privdata, const void *key1, const void *key2) {\n    int l1, l2;\n    ((void) privdata);\n\n    l1 = sdslen((const sds)key1);\n    l2 = sdslen((const sds)key2);\n    if (l1 != l2) return 0;\n    return memcmp(key1,key2,l1) == 0;\n}\n\nstatic void callbackKeyDestructor(void *privdata, void *key) {\n    ((void) privdata);\n    sdsfree((sds)key);\n}\n\nstatic void callbackValDestructor(void *privdata, void *val) {\n    ((void) privdata);\n    free(val);\n}\n\nstatic dictType callbackDict = {\n    callbackHash,\n    NULL,\n    callbackValDup,\n    callbackKeyCompare,\n    callbackKeyDestructor,\n    callbackValDestructor\n};\n\nstatic redisAsyncContext *redisAsyncInitialize(redisContext *c) {\n    redisAsyncContext *ac;\n\n    ac = realloc(c,sizeof(redisAsyncContext));\n    if (ac == NULL)\n        return NULL;\n\n    c = &(ac->c);\n\n    /* The regular connect functions will always set the flag REDIS_CONNECTED.\n     * For the async API, we want to wait until the first write event is\n     * received up before setting this flag, so reset it here. */\n    c->flags &= ~REDIS_CONNECTED;\n\n    ac->err = 0;\n    ac->errstr = NULL;\n    ac->data = NULL;\n\n    ac->ev.data = NULL;\n    ac->ev.addRead = NULL;\n    ac->ev.delRead = NULL;\n    ac->ev.addWrite = NULL;\n    ac->ev.delWrite = NULL;\n    ac->ev.cleanup = NULL;\n\n    ac->onConnect = NULL;\n    ac->onDisconnect = NULL;\n\n    ac->replies.head = NULL;\n    ac->replies.tail = NULL;\n    ac->sub.invalid.head = NULL;\n    ac->sub.invalid.tail = NULL;\n    ac->sub.channels = dictCreate(&callbackDict,NULL);\n    ac->sub.patterns = dictCreate(&callbackDict,NULL);\n    return ac;\n}\n\n/* We want the error field to be accessible directly instead of requiring\n * an indirection to the redisContext struct. */\nstatic void __redisAsyncCopyError(redisAsyncContext *ac) {\n    redisContext *c = &(ac->c);\n    ac->err = c->err;\n    ac->errstr = c->errstr;\n}\n\nredisAsyncContext *redisAsyncConnect(const char *ip, int port) {\n    redisContext *c;\n    redisAsyncContext *ac;\n\n    c = redisConnectNonBlock(ip,port);\n    if (c == NULL)\n        return NULL;\n\n    ac = redisAsyncInitialize(c);\n    if (ac == NULL) {\n        redisFree(c);\n        return NULL;\n    }\n\n    __redisAsyncCopyError(ac);\n    return ac;\n}\n\nredisAsyncContext *redisAsyncConnectBind(const char *ip, int port,\n                                         const char *source_addr) {\n    redisContext *c = redisConnectBindNonBlock(ip,port,source_addr);\n    redisAsyncContext *ac = redisAsyncInitialize(c);\n    __redisAsyncCopyError(ac);\n    return ac;\n}\n\nredisAsyncContext *redisAsyncConnectUnix(const char *path) {\n    redisContext *c;\n    redisAsyncContext *ac;\n\n    c = redisConnectUnixNonBlock(path);\n    if (c == NULL)\n        return NULL;\n\n    ac = redisAsyncInitialize(c);\n    if (ac == NULL) {\n        redisFree(c);\n        return NULL;\n    }\n\n    __redisAsyncCopyError(ac);\n    return ac;\n}\n\nint redisAsyncSetConnectCallback(redisAsyncContext *ac, redisConnectCallback *fn) {\n    if (ac->onConnect == NULL) {\n        ac->onConnect = fn;\n\n        /* The common way to detect an established connection is to wait for\n         * the first write event to be fired. This assumes the related event\n         * library functions are already set. */\n        _EL_ADD_WRITE(ac);\n        return REDIS_OK;\n    }\n    return REDIS_ERR;\n}\n\nint redisAsyncSetDisconnectCallback(redisAsyncContext *ac, redisDisconnectCallback *fn) {\n    if (ac->onDisconnect == NULL) {\n        ac->onDisconnect = fn;\n        return REDIS_OK;\n    }\n    return REDIS_ERR;\n}\n\n/* Helper functions to push/shift callbacks */\nstatic int __redisPushCallback(redisCallbackList *list, redisCallback *source) {\n    redisCallback *cb;\n\n    /* Copy callback from stack to heap */\n    cb = malloc(sizeof(*cb));\n    if (cb == NULL)\n        return REDIS_ERR_OOM;\n\n    if (source != NULL) {\n        memcpy(cb,source,sizeof(*cb));\n        cb->next = NULL;\n    }\n\n    /* Store callback in list */\n    if (list->head == NULL)\n        list->head = cb;\n    if (list->tail != NULL)\n        list->tail->next = cb;\n    list->tail = cb;\n    return REDIS_OK;\n}\n\nstatic int __redisShiftCallback(redisCallbackList *list, redisCallback *target) {\n    redisCallback *cb = list->head;\n    if (cb != NULL) {\n        list->head = cb->next;\n        if (cb == list->tail)\n            list->tail = NULL;\n\n        /* Copy callback from heap to stack */\n        if (target != NULL)\n            memcpy(target,cb,sizeof(*cb));\n        free(cb);\n        return REDIS_OK;\n    }\n    return REDIS_ERR;\n}\n\nstatic void __redisRunCallback(redisAsyncContext *ac, redisCallback *cb, redisReply *reply) {\n    redisContext *c = &(ac->c);\n    if (cb->fn != NULL) {\n        c->flags |= REDIS_IN_CALLBACK;\n        cb->fn(ac,reply,cb->privdata);\n        c->flags &= ~REDIS_IN_CALLBACK;\n    }\n}\n\n/* Helper function to free the context. */\nstatic void __redisAsyncFree(redisAsyncContext *ac) {\n    redisContext *c = &(ac->c);\n    redisCallback cb;\n    dictIterator *it;\n    dictEntry *de;\n\n    /* Execute pending callbacks with NULL reply. */\n    while (__redisShiftCallback(&ac->replies,&cb) == REDIS_OK)\n        __redisRunCallback(ac,&cb,NULL);\n\n    /* Execute callbacks for invalid commands */\n    while (__redisShiftCallback(&ac->sub.invalid,&cb) == REDIS_OK)\n        __redisRunCallback(ac,&cb,NULL);\n\n    /* Run subscription callbacks callbacks with NULL reply */\n    it = dictGetIterator(ac->sub.channels);\n    while ((de = dictNext(it)) != NULL)\n        __redisRunCallback(ac,dictGetEntryVal(de),NULL);\n    dictReleaseIterator(it);\n    dictRelease(ac->sub.channels);\n\n    it = dictGetIterator(ac->sub.patterns);\n    while ((de = dictNext(it)) != NULL)\n        __redisRunCallback(ac,dictGetEntryVal(de),NULL);\n    dictReleaseIterator(it);\n    dictRelease(ac->sub.patterns);\n\n    /* Signal event lib to clean up */\n    _EL_CLEANUP(ac);\n\n    /* Execute disconnect callback. When redisAsyncFree() initiated destroying\n     * this context, the status will always be REDIS_OK. */\n    if (ac->onDisconnect && (c->flags & REDIS_CONNECTED)) {\n        if (c->flags & REDIS_FREEING) {\n            ac->onDisconnect(ac,REDIS_OK);\n        } else {\n            ac->onDisconnect(ac,(ac->err == 0) ? REDIS_OK : REDIS_ERR);\n        }\n    }\n\n    /* Cleanup self */\n    redisFree(c);\n}\n\n/* Free the async context. When this function is called from a callback,\n * control needs to be returned to redisProcessCallbacks() before actual\n * free'ing. To do so, a flag is set on the context which is picked up by\n * redisProcessCallbacks(). Otherwise, the context is immediately free'd. */\nvoid redisAsyncFree(redisAsyncContext *ac) {\n    redisContext *c = &(ac->c);\n    c->flags |= REDIS_FREEING;\n    if (!(c->flags & REDIS_IN_CALLBACK))\n        __redisAsyncFree(ac);\n}\n\n/* Helper function to make the disconnect happen and clean up. */\nstatic void __redisAsyncDisconnect(redisAsyncContext *ac) {\n    redisContext *c = &(ac->c);\n\n    /* Make sure error is accessible if there is any */\n    __redisAsyncCopyError(ac);\n\n    if (ac->err == 0) {\n        /* For clean disconnects, there should be no pending callbacks. */\n        assert(__redisShiftCallback(&ac->replies,NULL) == REDIS_ERR);\n    } else {\n        /* Disconnection is caused by an error, make sure that pending\n         * callbacks cannot call new commands. */\n        c->flags |= REDIS_DISCONNECTING;\n    }\n\n    /* For non-clean disconnects, __redisAsyncFree() will execute pending\n     * callbacks with a NULL-reply. */\n    __redisAsyncFree(ac);\n}\n\n/* Tries to do a clean disconnect from Redis, meaning it stops new commands\n * from being issued, but tries to flush the output buffer and execute\n * callbacks for all remaining replies. When this function is called from a\n * callback, there might be more replies and we can safely defer disconnecting\n * to redisProcessCallbacks(). Otherwise, we can only disconnect immediately\n * when there are no pending callbacks. */\nvoid redisAsyncDisconnect(redisAsyncContext *ac) {\n    redisContext *c = &(ac->c);\n    c->flags |= REDIS_DISCONNECTING;\n    if (!(c->flags & REDIS_IN_CALLBACK) && ac->replies.head == NULL)\n        __redisAsyncDisconnect(ac);\n}\n\nstatic int __redisGetSubscribeCallback(redisAsyncContext *ac, redisReply *reply, redisCallback *dstcb) {\n    redisContext *c = &(ac->c);\n    dict *callbacks;\n    dictEntry *de;\n    int pvariant;\n    char *stype;\n    sds sname;\n\n    /* Custom reply functions are not supported for pub/sub. This will fail\n     * very hard when they are used... */\n    if (reply->type == REDIS_REPLY_ARRAY) {\n        assert(reply->elements >= 2);\n        assert(reply->element[0]->type == REDIS_REPLY_STRING);\n        stype = reply->element[0]->str;\n        pvariant = (tolower(stype[0]) == 'p') ? 1 : 0;\n\n        if (pvariant)\n            callbacks = ac->sub.patterns;\n        else\n            callbacks = ac->sub.channels;\n\n        /* Locate the right callback */\n        assert(reply->element[1]->type == REDIS_REPLY_STRING);\n        sname = sdsnewlen(reply->element[1]->str,reply->element[1]->len);\n        de = dictFind(callbacks,sname);\n        if (de != NULL) {\n            memcpy(dstcb,dictGetEntryVal(de),sizeof(*dstcb));\n\n            /* If this is an unsubscribe message, remove it. */\n            if (strcasecmp(stype+pvariant,\"unsubscribe\") == 0) {\n                dictDelete(callbacks,sname);\n\n                /* If this was the last unsubscribe message, revert to\n                 * non-subscribe mode. */\n                assert(reply->element[2]->type == REDIS_REPLY_INTEGER);\n                if (reply->element[2]->integer == 0)\n                    c->flags &= ~REDIS_SUBSCRIBED;\n            }\n        }\n        sdsfree(sname);\n    } else {\n        /* Shift callback for invalid commands. */\n        __redisShiftCallback(&ac->sub.invalid,dstcb);\n    }\n    return REDIS_OK;\n}\n\nvoid redisProcessCallbacks(redisAsyncContext *ac) {\n    redisContext *c = &(ac->c);\n    redisCallback cb = {NULL, NULL, NULL};\n    void *reply = NULL;\n    int status;\n\n    while((status = redisGetReply(c,&reply)) == REDIS_OK) {\n        if (reply == NULL) {\n            /* When the connection is being disconnected and there are\n             * no more replies, this is the cue to really disconnect. */\n            if (c->flags & REDIS_DISCONNECTING && sdslen(c->obuf) == 0) {\n                __redisAsyncDisconnect(ac);\n                return;\n            }\n\n            /* If monitor mode, repush callback */\n            if(c->flags & REDIS_MONITORING) {\n                __redisPushCallback(&ac->replies,&cb);\n            }\n\n            /* When the connection is not being disconnected, simply stop\n             * trying to get replies and wait for the next loop tick. */\n            break;\n        }\n\n        /* Even if the context is subscribed, pending regular callbacks will\n         * get a reply before pub/sub messages arrive. */\n        if (__redisShiftCallback(&ac->replies,&cb) != REDIS_OK) {\n            /*\n             * A spontaneous reply in a not-subscribed context can be the error\n             * reply that is sent when a new connection exceeds the maximum\n             * number of allowed connections on the server side.\n             *\n             * This is seen as an error instead of a regular reply because the\n             * server closes the connection after sending it.\n             *\n             * To prevent the error from being overwritten by an EOF error the\n             * connection is closed here. See issue #43.\n             *\n             * Another possibility is that the server is loading its dataset.\n             * In this case we also want to close the connection, and have the\n             * user wait until the server is ready to take our request.\n             */\n            if (((redisReply*)reply)->type == REDIS_REPLY_ERROR) {\n                c->err = REDIS_ERR_OTHER;\n                snprintf(c->errstr,sizeof(c->errstr),\"%s\",((redisReply*)reply)->str);\n                c->reader->fn->freeObject(reply);\n                __redisAsyncDisconnect(ac);\n                return;\n            }\n            /* No more regular callbacks and no errors, the context *must* be subscribed or monitoring. */\n            assert((c->flags & REDIS_SUBSCRIBED || c->flags & REDIS_MONITORING));\n            if(c->flags & REDIS_SUBSCRIBED)\n                __redisGetSubscribeCallback(ac,reply,&cb);\n        }\n\n        if (cb.fn != NULL) {\n            __redisRunCallback(ac,&cb,reply);\n            c->reader->fn->freeObject(reply);\n\n            /* Proceed with free'ing when redisAsyncFree() was called. */\n            if (c->flags & REDIS_FREEING) {\n                __redisAsyncFree(ac);\n                return;\n            }\n        } else {\n            /* No callback for this reply. This can either be a NULL callback,\n             * or there were no callbacks to begin with. Either way, don't\n             * abort with an error, but simply ignore it because the client\n             * doesn't know what the server will spit out over the wire. */\n            c->reader->fn->freeObject(reply);\n        }\n    }\n\n    /* Disconnect when there was an error reading the reply */\n    if (status != REDIS_OK)\n        __redisAsyncDisconnect(ac);\n}\n\n/* Internal helper function to detect socket status the first time a read or\n * write event fires. When connecting was not succesful, the connect callback\n * is called with a REDIS_ERR status and the context is free'd. */\nstatic int __redisAsyncHandleConnect(redisAsyncContext *ac) {\n    redisContext *c = &(ac->c);\n\n    if (redisCheckSocketError(c) == REDIS_ERR) {\n        /* Try again later when connect(2) is still in progress. */\n        if (errno == EINPROGRESS)\n            return REDIS_OK;\n\n        if (ac->onConnect) ac->onConnect(ac,REDIS_ERR);\n        __redisAsyncDisconnect(ac);\n        return REDIS_ERR;\n    }\n\n    /* Mark context as connected. */\n    c->flags |= REDIS_CONNECTED;\n    if (ac->onConnect) ac->onConnect(ac,REDIS_OK);\n    return REDIS_OK;\n}\n\n/* This function should be called when the socket is readable.\n * It processes all replies that can be read and executes their callbacks.\n */\nvoid redisAsyncHandleRead(redisAsyncContext *ac) {\n    redisContext *c = &(ac->c);\n\n    if (!(c->flags & REDIS_CONNECTED)) {\n        /* Abort connect was not successful. */\n        if (__redisAsyncHandleConnect(ac) != REDIS_OK)\n            return;\n        /* Try again later when the context is still not connected. */\n        if (!(c->flags & REDIS_CONNECTED))\n            return;\n    }\n\n    if (redisBufferRead(c) == REDIS_ERR) {\n        __redisAsyncDisconnect(ac);\n    } else {\n        /* Always re-schedule reads */\n        _EL_ADD_READ(ac);\n        redisProcessCallbacks(ac);\n    }\n}\n\nvoid redisAsyncHandleWrite(redisAsyncContext *ac) {\n    redisContext *c = &(ac->c);\n    int done = 0;\n\n    if (!(c->flags & REDIS_CONNECTED)) {\n        /* Abort connect was not successful. */\n        if (__redisAsyncHandleConnect(ac) != REDIS_OK)\n            return;\n        /* Try again later when the context is still not connected. */\n        if (!(c->flags & REDIS_CONNECTED))\n            return;\n    }\n\n    if (redisBufferWrite(c,&done) == REDIS_ERR) {\n        __redisAsyncDisconnect(ac);\n    } else {\n        /* Continue writing when not done, stop writing otherwise */\n        if (!done)\n            _EL_ADD_WRITE(ac);\n        else\n            _EL_DEL_WRITE(ac);\n\n        /* Always schedule reads after writes */\n        _EL_ADD_READ(ac);\n    }\n}\n\n/* Sets a pointer to the first argument and its length starting at p. Returns\n * the number of bytes to skip to get to the following argument. */\nstatic char *nextArgument(char *start, char **str, size_t *len) {\n    char *p = start;\n    if (p[0] != '$') {\n        p = strchr(p,'$');\n        if (p == NULL) return NULL;\n    }\n\n    *len = (int)strtol(p+1,NULL,10);\n    p = strchr(p,'\\r');\n    assert(p);\n    *str = p+2;\n    return p+2+(*len)+2;\n}\n\n/* Helper function for the redisAsyncCommand* family of functions. Writes a\n * formatted command to the output buffer and registers the provided callback\n * function with the context. */\nstatic int __redisAsyncCommand(redisAsyncContext *ac, redisCallbackFn *fn, void *privdata, char *cmd, size_t len) {\n    redisContext *c = &(ac->c);\n    redisCallback cb;\n    int pvariant, hasnext;\n    char *cstr, *astr;\n    size_t clen, alen;\n    char *p;\n    sds sname;\n\n    /* Don't accept new commands when the connection is about to be closed. */\n    if (c->flags & (REDIS_DISCONNECTING | REDIS_FREEING)) return REDIS_ERR;\n\n    /* Setup callback */\n    cb.fn = fn;\n    cb.privdata = privdata;\n\n    /* Find out which command will be appended. */\n    p = nextArgument(cmd,&cstr,&clen);\n    assert(p != NULL);\n    hasnext = (p[0] == '$');\n    pvariant = (tolower(cstr[0]) == 'p') ? 1 : 0;\n    cstr += pvariant;\n    clen -= pvariant;\n\n    if (hasnext && strncasecmp(cstr,\"subscribe\\r\\n\",11) == 0) {\n        c->flags |= REDIS_SUBSCRIBED;\n\n        /* Add every channel/pattern to the list of subscription callbacks. */\n        while ((p = nextArgument(p,&astr,&alen)) != NULL) {\n            sname = sdsnewlen(astr,alen);\n            if (pvariant)\n                dictReplace(ac->sub.patterns,sname,&cb);\n            else\n                dictReplace(ac->sub.channels,sname,&cb);\n        }\n    } else if (strncasecmp(cstr,\"unsubscribe\\r\\n\",13) == 0) {\n        /* It is only useful to call (P)UNSUBSCRIBE when the context is\n         * subscribed to one or more channels or patterns. */\n        if (!(c->flags & REDIS_SUBSCRIBED)) return REDIS_ERR;\n\n        /* (P)UNSUBSCRIBE does not have its own response: every channel or\n         * pattern that is unsubscribed will receive a message. This means we\n         * should not append a callback function for this command. */\n     } else if(strncasecmp(cstr,\"monitor\\r\\n\",9) == 0) {\n         /* Set monitor flag and push callback */\n         c->flags |= REDIS_MONITORING;\n         __redisPushCallback(&ac->replies,&cb);\n    } else {\n        if (c->flags & REDIS_SUBSCRIBED)\n            /* This will likely result in an error reply, but it needs to be\n             * received and passed to the callback. */\n            __redisPushCallback(&ac->sub.invalid,&cb);\n        else\n            __redisPushCallback(&ac->replies,&cb);\n    }\n\n    __redisAppendCommand(c,cmd,len);\n\n    /* Always schedule a write when the write buffer is non-empty */\n    _EL_ADD_WRITE(ac);\n\n    return REDIS_OK;\n}\n\nint redisvAsyncCommand(redisAsyncContext *ac, redisCallbackFn *fn, void *privdata, const char *format, va_list ap) {\n    char *cmd;\n    int len;\n    int status;\n    len = redisvFormatCommand(&cmd,format,ap);\n    status = __redisAsyncCommand(ac,fn,privdata,cmd,len);\n    free(cmd);\n    return status;\n}\n\nint redisAsyncCommand(redisAsyncContext *ac, redisCallbackFn *fn, void *privdata, const char *format, ...) {\n    va_list ap;\n    int status;\n    va_start(ap,format);\n    status = redisvAsyncCommand(ac,fn,privdata,format,ap);\n    va_end(ap);\n    return status;\n}\n\nint redisAsyncCommandArgv(redisAsyncContext *ac, redisCallbackFn *fn, void *privdata, int argc, const char **argv, const size_t *argvlen) {\n    char *cmd;\n    int len;\n    int status;\n    len = redisFormatCommandArgv(&cmd,argc,argv,argvlen);\n    status = __redisAsyncCommand(ac,fn,privdata,cmd,len);\n    free(cmd);\n    return status;\n}\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/deps/hiredis/async.h",
    "content": "/*\n * Copyright (c) 2009-2011, Salvatore Sanfilippo <antirez at gmail dot com>\n * Copyright (c) 2010-2011, Pieter Noordhuis <pcnoordhuis at gmail dot com>\n *\n * All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions are met:\n *\n *   * Redistributions of source code must retain the above copyright notice,\n *     this list of conditions and the following disclaimer.\n *   * Redistributions in binary form must reproduce the above copyright\n *     notice, this list of conditions and the following disclaimer in the\n *     documentation and/or other materials provided with the distribution.\n *   * Neither the name of Redis nor the names of its contributors may be used\n *     to endorse or promote products derived from this software without\n *     specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\"\n * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\n * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE\n * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR\n * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF\n * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS\n * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN\n * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)\n * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE\n * POSSIBILITY OF SUCH DAMAGE.\n */\n\n#ifndef __HIREDIS_ASYNC_H\n#define __HIREDIS_ASYNC_H\n#include \"hiredis.h\"\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\nstruct redisAsyncContext; /* need forward declaration of redisAsyncContext */\nstruct dict; /* dictionary header is included in async.c */\n\n/* Reply callback prototype and container */\ntypedef void (redisCallbackFn)(struct redisAsyncContext*, void*, void*);\ntypedef struct redisCallback {\n    struct redisCallback *next; /* simple singly linked list */\n    redisCallbackFn *fn;\n    void *privdata;\n} redisCallback;\n\n/* List of callbacks for either regular replies or pub/sub */\ntypedef struct redisCallbackList {\n    redisCallback *head, *tail;\n} redisCallbackList;\n\n/* Connection callback prototypes */\ntypedef void (redisDisconnectCallback)(const struct redisAsyncContext*, int status);\ntypedef void (redisConnectCallback)(const struct redisAsyncContext*, int status);\n\n/* Context for an async connection to Redis */\ntypedef struct redisAsyncContext {\n    /* Hold the regular context, so it can be realloc'ed. */\n    redisContext c;\n\n    /* Setup error flags so they can be used directly. */\n    int err;\n    char *errstr;\n\n    /* Not used by hiredis */\n    void *data;\n\n    /* Event library data and hooks */\n    struct {\n        void *data;\n\n        /* Hooks that are called when the library expects to start\n         * reading/writing. These functions should be idempotent. */\n        void (*addRead)(void *privdata);\n        void (*delRead)(void *privdata);\n        void (*addWrite)(void *privdata);\n        void (*delWrite)(void *privdata);\n        void (*cleanup)(void *privdata);\n    } ev;\n\n    /* Called when either the connection is terminated due to an error or per\n     * user request. The status is set accordingly (REDIS_OK, REDIS_ERR). */\n    redisDisconnectCallback *onDisconnect;\n\n    /* Called when the first write event was received. */\n    redisConnectCallback *onConnect;\n\n    /* Regular command callbacks */\n    redisCallbackList replies;\n\n    /* Subscription callbacks */\n    struct {\n        redisCallbackList invalid;\n        struct dict *channels;\n        struct dict *patterns;\n    } sub;\n} redisAsyncContext;\n\n/* Functions that proxy to hiredis */\nredisAsyncContext *redisAsyncConnect(const char *ip, int port);\nredisAsyncContext *redisAsyncConnectBind(const char *ip, int port, const char *source_addr);\nredisAsyncContext *redisAsyncConnectUnix(const char *path);\nint redisAsyncSetConnectCallback(redisAsyncContext *ac, redisConnectCallback *fn);\nint redisAsyncSetDisconnectCallback(redisAsyncContext *ac, redisDisconnectCallback *fn);\nvoid redisAsyncDisconnect(redisAsyncContext *ac);\nvoid redisAsyncFree(redisAsyncContext *ac);\n\n/* Handle read/write events */\nvoid redisAsyncHandleRead(redisAsyncContext *ac);\nvoid redisAsyncHandleWrite(redisAsyncContext *ac);\n\n/* Command functions for an async context. Write the command to the\n * output buffer and register the provided callback. */\nint redisvAsyncCommand(redisAsyncContext *ac, redisCallbackFn *fn, void *privdata, const char *format, va_list ap);\nint redisAsyncCommand(redisAsyncContext *ac, redisCallbackFn *fn, void *privdata, const char *format, ...);\nint redisAsyncCommandArgv(redisAsyncContext *ac, redisCallbackFn *fn, void *privdata, int argc, const char **argv, const size_t *argvlen);\n\n#ifdef __cplusplus\n}\n#endif\n\n#endif\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/deps/hiredis/dict.c",
    "content": "/* Hash table implementation.\n *\n * This file implements in memory hash tables with insert/del/replace/find/\n * get-random-element operations. Hash tables will auto resize if needed\n * tables of power of two in size are used, collisions are handled by\n * chaining. See the source code for more information... :)\n *\n * Copyright (c) 2006-2010, Salvatore Sanfilippo <antirez at gmail dot com>\n * All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions are met:\n *\n *   * Redistributions of source code must retain the above copyright notice,\n *     this list of conditions and the following disclaimer.\n *   * Redistributions in binary form must reproduce the above copyright\n *     notice, this list of conditions and the following disclaimer in the\n *     documentation and/or other materials provided with the distribution.\n *   * Neither the name of Redis nor the names of its contributors may be used\n *     to endorse or promote products derived from this software without\n *     specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\"\n * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\n * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE\n * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR\n * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF\n * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS\n * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN\n * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)\n * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE\n * POSSIBILITY OF SUCH DAMAGE.\n */\n\n#include \"fmacros.h\"\n#include <stdlib.h>\n#include <assert.h>\n#include <limits.h>\n#include \"dict.h\"\n\n/* -------------------------- private prototypes ---------------------------- */\n\nstatic int _dictExpandIfNeeded(dict *ht);\nstatic unsigned long _dictNextPower(unsigned long size);\nstatic int _dictKeyIndex(dict *ht, const void *key);\nstatic int _dictInit(dict *ht, dictType *type, void *privDataPtr);\n\n/* -------------------------- hash functions -------------------------------- */\n\n/* Generic hash function (a popular one from Bernstein).\n * I tested a few and this was the best. */\nstatic unsigned int dictGenHashFunction(const unsigned char *buf, int len) {\n    unsigned int hash = 5381;\n\n    while (len--)\n        hash = ((hash << 5) + hash) + (*buf++); /* hash * 33 + c */\n    return hash;\n}\n\n/* ----------------------------- API implementation ------------------------- */\n\n/* Reset an hashtable already initialized with ht_init().\n * NOTE: This function should only called by ht_destroy(). */\nstatic void _dictReset(dict *ht) {\n    ht->table = NULL;\n    ht->size = 0;\n    ht->sizemask = 0;\n    ht->used = 0;\n}\n\n/* Create a new hash table */\nstatic dict *dictCreate(dictType *type, void *privDataPtr) {\n    dict *ht = malloc(sizeof(*ht));\n    _dictInit(ht,type,privDataPtr);\n    return ht;\n}\n\n/* Initialize the hash table */\nstatic int _dictInit(dict *ht, dictType *type, void *privDataPtr) {\n    _dictReset(ht);\n    ht->type = type;\n    ht->privdata = privDataPtr;\n    return DICT_OK;\n}\n\n/* Expand or create the hashtable */\nstatic int dictExpand(dict *ht, unsigned long size) {\n    dict n; /* the new hashtable */\n    unsigned long realsize = _dictNextPower(size), i;\n\n    /* the size is invalid if it is smaller than the number of\n     * elements already inside the hashtable */\n    if (ht->used > size)\n        return DICT_ERR;\n\n    _dictInit(&n, ht->type, ht->privdata);\n    n.size = realsize;\n    n.sizemask = realsize-1;\n    n.table = calloc(realsize,sizeof(dictEntry*));\n\n    /* Copy all the elements from the old to the new table:\n     * note that if the old hash table is empty ht->size is zero,\n     * so dictExpand just creates an hash table. */\n    n.used = ht->used;\n    for (i = 0; i < ht->size && ht->used > 0; i++) {\n        dictEntry *he, *nextHe;\n\n        if (ht->table[i] == NULL) continue;\n\n        /* For each hash entry on this slot... */\n        he = ht->table[i];\n        while(he) {\n            unsigned int h;\n\n            nextHe = he->next;\n            /* Get the new element index */\n            h = dictHashKey(ht, he->key) & n.sizemask;\n            he->next = n.table[h];\n            n.table[h] = he;\n            ht->used--;\n            /* Pass to the next element */\n            he = nextHe;\n        }\n    }\n    assert(ht->used == 0);\n    free(ht->table);\n\n    /* Remap the new hashtable in the old */\n    *ht = n;\n    return DICT_OK;\n}\n\n/* Add an element to the target hash table */\nstatic int dictAdd(dict *ht, void *key, void *val) {\n    int index;\n    dictEntry *entry;\n\n    /* Get the index of the new element, or -1 if\n     * the element already exists. */\n    if ((index = _dictKeyIndex(ht, key)) == -1)\n        return DICT_ERR;\n\n    /* Allocates the memory and stores key */\n    entry = malloc(sizeof(*entry));\n    entry->next = ht->table[index];\n    ht->table[index] = entry;\n\n    /* Set the hash entry fields. */\n    dictSetHashKey(ht, entry, key);\n    dictSetHashVal(ht, entry, val);\n    ht->used++;\n    return DICT_OK;\n}\n\n/* Add an element, discarding the old if the key already exists.\n * Return 1 if the key was added from scratch, 0 if there was already an\n * element with such key and dictReplace() just performed a value update\n * operation. */\nstatic int dictReplace(dict *ht, void *key, void *val) {\n    dictEntry *entry, auxentry;\n\n    /* Try to add the element. If the key\n     * does not exists dictAdd will suceed. */\n    if (dictAdd(ht, key, val) == DICT_OK)\n        return 1;\n    /* It already exists, get the entry */\n    entry = dictFind(ht, key);\n    /* Free the old value and set the new one */\n    /* Set the new value and free the old one. Note that it is important\n     * to do that in this order, as the value may just be exactly the same\n     * as the previous one. In this context, think to reference counting,\n     * you want to increment (set), and then decrement (free), and not the\n     * reverse. */\n    auxentry = *entry;\n    dictSetHashVal(ht, entry, val);\n    dictFreeEntryVal(ht, &auxentry);\n    return 0;\n}\n\n/* Search and remove an element */\nstatic int dictDelete(dict *ht, const void *key) {\n    unsigned int h;\n    dictEntry *de, *prevde;\n\n    if (ht->size == 0)\n        return DICT_ERR;\n    h = dictHashKey(ht, key) & ht->sizemask;\n    de = ht->table[h];\n\n    prevde = NULL;\n    while(de) {\n        if (dictCompareHashKeys(ht,key,de->key)) {\n            /* Unlink the element from the list */\n            if (prevde)\n                prevde->next = de->next;\n            else\n                ht->table[h] = de->next;\n\n            dictFreeEntryKey(ht,de);\n            dictFreeEntryVal(ht,de);\n            free(de);\n            ht->used--;\n            return DICT_OK;\n        }\n        prevde = de;\n        de = de->next;\n    }\n    return DICT_ERR; /* not found */\n}\n\n/* Destroy an entire hash table */\nstatic int _dictClear(dict *ht) {\n    unsigned long i;\n\n    /* Free all the elements */\n    for (i = 0; i < ht->size && ht->used > 0; i++) {\n        dictEntry *he, *nextHe;\n\n        if ((he = ht->table[i]) == NULL) continue;\n        while(he) {\n            nextHe = he->next;\n            dictFreeEntryKey(ht, he);\n            dictFreeEntryVal(ht, he);\n            free(he);\n            ht->used--;\n            he = nextHe;\n        }\n    }\n    /* Free the table and the allocated cache structure */\n    free(ht->table);\n    /* Re-initialize the table */\n    _dictReset(ht);\n    return DICT_OK; /* never fails */\n}\n\n/* Clear & Release the hash table */\nstatic void dictRelease(dict *ht) {\n    _dictClear(ht);\n    free(ht);\n}\n\nstatic dictEntry *dictFind(dict *ht, const void *key) {\n    dictEntry *he;\n    unsigned int h;\n\n    if (ht->size == 0) return NULL;\n    h = dictHashKey(ht, key) & ht->sizemask;\n    he = ht->table[h];\n    while(he) {\n        if (dictCompareHashKeys(ht, key, he->key))\n            return he;\n        he = he->next;\n    }\n    return NULL;\n}\n\nstatic dictIterator *dictGetIterator(dict *ht) {\n    dictIterator *iter = malloc(sizeof(*iter));\n\n    iter->ht = ht;\n    iter->index = -1;\n    iter->entry = NULL;\n    iter->nextEntry = NULL;\n    return iter;\n}\n\nstatic dictEntry *dictNext(dictIterator *iter) {\n    while (1) {\n        if (iter->entry == NULL) {\n            iter->index++;\n            if (iter->index >=\n                    (signed)iter->ht->size) break;\n            iter->entry = iter->ht->table[iter->index];\n        } else {\n            iter->entry = iter->nextEntry;\n        }\n        if (iter->entry) {\n            /* We need to save the 'next' here, the iterator user\n             * may delete the entry we are returning. */\n            iter->nextEntry = iter->entry->next;\n            return iter->entry;\n        }\n    }\n    return NULL;\n}\n\nstatic void dictReleaseIterator(dictIterator *iter) {\n    free(iter);\n}\n\n/* ------------------------- private functions ------------------------------ */\n\n/* Expand the hash table if needed */\nstatic int _dictExpandIfNeeded(dict *ht) {\n    /* If the hash table is empty expand it to the intial size,\n     * if the table is \"full\" dobule its size. */\n    if (ht->size == 0)\n        return dictExpand(ht, DICT_HT_INITIAL_SIZE);\n    if (ht->used == ht->size)\n        return dictExpand(ht, ht->size*2);\n    return DICT_OK;\n}\n\n/* Our hash table capability is a power of two */\nstatic unsigned long _dictNextPower(unsigned long size) {\n    unsigned long i = DICT_HT_INITIAL_SIZE;\n\n    if (size >= LONG_MAX) return LONG_MAX;\n    while(1) {\n        if (i >= size)\n            return i;\n        i *= 2;\n    }\n}\n\n/* Returns the index of a free slot that can be populated with\n * an hash entry for the given 'key'.\n * If the key already exists, -1 is returned. */\nstatic int _dictKeyIndex(dict *ht, const void *key) {\n    unsigned int h;\n    dictEntry *he;\n\n    /* Expand the hashtable if needed */\n    if (_dictExpandIfNeeded(ht) == DICT_ERR)\n        return -1;\n    /* Compute the key hash value */\n    h = dictHashKey(ht, key) & ht->sizemask;\n    /* Search if this slot does not already contain the given key */\n    he = ht->table[h];\n    while(he) {\n        if (dictCompareHashKeys(ht, key, he->key))\n            return -1;\n        he = he->next;\n    }\n    return h;\n}\n\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/deps/hiredis/dict.h",
    "content": "/* Hash table implementation.\n *\n * This file implements in memory hash tables with insert/del/replace/find/\n * get-random-element operations. Hash tables will auto resize if needed\n * tables of power of two in size are used, collisions are handled by\n * chaining. See the source code for more information... :)\n *\n * Copyright (c) 2006-2010, Salvatore Sanfilippo <antirez at gmail dot com>\n * All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions are met:\n *\n *   * Redistributions of source code must retain the above copyright notice,\n *     this list of conditions and the following disclaimer.\n *   * Redistributions in binary form must reproduce the above copyright\n *     notice, this list of conditions and the following disclaimer in the\n *     documentation and/or other materials provided with the distribution.\n *   * Neither the name of Redis nor the names of its contributors may be used\n *     to endorse or promote products derived from this software without\n *     specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\"\n * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\n * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE\n * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR\n * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF\n * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS\n * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN\n * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)\n * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE\n * POSSIBILITY OF SUCH DAMAGE.\n */\n\n#ifndef __DICT_H\n#define __DICT_H\n\n#define DICT_OK 0\n#define DICT_ERR 1\n\n/* Unused arguments generate annoying warnings... */\n#define DICT_NOTUSED(V) ((void) V)\n\ntypedef struct dictEntry {\n    void *key;\n    void *val;\n    struct dictEntry *next;\n} dictEntry;\n\ntypedef struct dictType {\n    unsigned int (*hashFunction)(const void *key);\n    void *(*keyDup)(void *privdata, const void *key);\n    void *(*valDup)(void *privdata, const void *obj);\n    int (*keyCompare)(void *privdata, const void *key1, const void *key2);\n    void (*keyDestructor)(void *privdata, void *key);\n    void (*valDestructor)(void *privdata, void *obj);\n} dictType;\n\ntypedef struct dict {\n    dictEntry **table;\n    dictType *type;\n    unsigned long size;\n    unsigned long sizemask;\n    unsigned long used;\n    void *privdata;\n} dict;\n\ntypedef struct dictIterator {\n    dict *ht;\n    int index;\n    dictEntry *entry, *nextEntry;\n} dictIterator;\n\n/* This is the initial size of every hash table */\n#define DICT_HT_INITIAL_SIZE     4\n\n/* ------------------------------- Macros ------------------------------------*/\n#define dictFreeEntryVal(ht, entry) \\\n    if ((ht)->type->valDestructor) \\\n        (ht)->type->valDestructor((ht)->privdata, (entry)->val)\n\n#define dictSetHashVal(ht, entry, _val_) do { \\\n    if ((ht)->type->valDup) \\\n        entry->val = (ht)->type->valDup((ht)->privdata, _val_); \\\n    else \\\n        entry->val = (_val_); \\\n} while(0)\n\n#define dictFreeEntryKey(ht, entry) \\\n    if ((ht)->type->keyDestructor) \\\n        (ht)->type->keyDestructor((ht)->privdata, (entry)->key)\n\n#define dictSetHashKey(ht, entry, _key_) do { \\\n    if ((ht)->type->keyDup) \\\n        entry->key = (ht)->type->keyDup((ht)->privdata, _key_); \\\n    else \\\n        entry->key = (_key_); \\\n} while(0)\n\n#define dictCompareHashKeys(ht, key1, key2) \\\n    (((ht)->type->keyCompare) ? \\\n        (ht)->type->keyCompare((ht)->privdata, key1, key2) : \\\n        (key1) == (key2))\n\n#define dictHashKey(ht, key) (ht)->type->hashFunction(key)\n\n#define dictGetEntryKey(he) ((he)->key)\n#define dictGetEntryVal(he) ((he)->val)\n#define dictSlots(ht) ((ht)->size)\n#define dictSize(ht) ((ht)->used)\n\n/* API */\nstatic unsigned int dictGenHashFunction(const unsigned char *buf, int len);\nstatic dict *dictCreate(dictType *type, void *privDataPtr);\nstatic int dictExpand(dict *ht, unsigned long size);\nstatic int dictAdd(dict *ht, void *key, void *val);\nstatic int dictReplace(dict *ht, void *key, void *val);\nstatic int dictDelete(dict *ht, const void *key);\nstatic void dictRelease(dict *ht);\nstatic dictEntry * dictFind(dict *ht, const void *key);\nstatic dictIterator *dictGetIterator(dict *ht);\nstatic dictEntry *dictNext(dictIterator *iter);\nstatic void dictReleaseIterator(dictIterator *iter);\n\n#endif /* __DICT_H */\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/deps/hiredis/examples/example-ae.c",
    "content": "#include <stdio.h>\n#include <stdlib.h>\n#include <string.h>\n#include <signal.h>\n\n#include <hiredis.h>\n#include <async.h>\n#include <adapters/ae.h>\n\n/* Put event loop in the global scope, so it can be explicitly stopped */\nstatic aeEventLoop *loop;\n\nvoid getCallback(redisAsyncContext *c, void *r, void *privdata) {\n    redisReply *reply = r;\n    if (reply == NULL) return;\n    printf(\"argv[%s]: %s\\n\", (char*)privdata, reply->str);\n\n    /* Disconnect after receiving the reply to GET */\n    redisAsyncDisconnect(c);\n}\n\nvoid connectCallback(const redisAsyncContext *c, int status) {\n    if (status != REDIS_OK) {\n        printf(\"Error: %s\\n\", c->errstr);\n        aeStop(loop);\n        return;\n    }\n\n    printf(\"Connected...\\n\");\n}\n\nvoid disconnectCallback(const redisAsyncContext *c, int status) {\n    if (status != REDIS_OK) {\n        printf(\"Error: %s\\n\", c->errstr);\n        aeStop(loop);\n        return;\n    }\n\n    printf(\"Disconnected...\\n\");\n    aeStop(loop);\n}\n\nint main (int argc, char **argv) {\n    signal(SIGPIPE, SIG_IGN);\n\n    redisAsyncContext *c = redisAsyncConnect(\"127.0.0.1\", 6379);\n    if (c->err) {\n        /* Let *c leak for now... */\n        printf(\"Error: %s\\n\", c->errstr);\n        return 1;\n    }\n\n    loop = aeCreateEventLoop(64);\n    redisAeAttach(loop, c);\n    redisAsyncSetConnectCallback(c,connectCallback);\n    redisAsyncSetDisconnectCallback(c,disconnectCallback);\n    redisAsyncCommand(c, NULL, NULL, \"SET key %b\", argv[argc-1], strlen(argv[argc-1]));\n    redisAsyncCommand(c, getCallback, (char*)\"end-1\", \"GET key\");\n    aeMain(loop);\n    return 0;\n}\n\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/deps/hiredis/examples/example-libev.c",
    "content": "#include <stdio.h>\n#include <stdlib.h>\n#include <string.h>\n#include <signal.h>\n\n#include <hiredis.h>\n#include <async.h>\n#include <adapters/libev.h>\n\nvoid getCallback(redisAsyncContext *c, void *r, void *privdata) {\n    redisReply *reply = r;\n    if (reply == NULL) return;\n    printf(\"argv[%s]: %s\\n\", (char*)privdata, reply->str);\n\n    /* Disconnect after receiving the reply to GET */\n    redisAsyncDisconnect(c);\n}\n\nvoid connectCallback(const redisAsyncContext *c, int status) {\n    if (status != REDIS_OK) {\n        printf(\"Error: %s\\n\", c->errstr);\n        return;\n    }\n    printf(\"Connected...\\n\");\n}\n\nvoid disconnectCallback(const redisAsyncContext *c, int status) {\n    if (status != REDIS_OK) {\n        printf(\"Error: %s\\n\", c->errstr);\n        return;\n    }\n    printf(\"Disconnected...\\n\");\n}\n\nint main (int argc, char **argv) {\n    signal(SIGPIPE, SIG_IGN);\n\n    redisAsyncContext *c = redisAsyncConnect(\"127.0.0.1\", 6379);\n    if (c->err) {\n        /* Let *c leak for now... */\n        printf(\"Error: %s\\n\", c->errstr);\n        return 1;\n    }\n\n    redisLibevAttach(EV_DEFAULT_ c);\n    redisAsyncSetConnectCallback(c,connectCallback);\n    redisAsyncSetDisconnectCallback(c,disconnectCallback);\n    redisAsyncCommand(c, NULL, NULL, \"SET key %b\", argv[argc-1], strlen(argv[argc-1]));\n    redisAsyncCommand(c, getCallback, (char*)\"end-1\", \"GET key\");\n    ev_loop(EV_DEFAULT_ 0);\n    return 0;\n}\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/deps/hiredis/examples/example-libevent.c",
    "content": "#include <stdio.h>\n#include <stdlib.h>\n#include <string.h>\n#include <signal.h>\n\n#include <hiredis.h>\n#include <async.h>\n#include <adapters/libevent.h>\n\nvoid getCallback(redisAsyncContext *c, void *r, void *privdata) {\n    redisReply *reply = r;\n    if (reply == NULL) return;\n    printf(\"argv[%s]: %s\\n\", (char*)privdata, reply->str);\n\n    /* Disconnect after receiving the reply to GET */\n    redisAsyncDisconnect(c);\n}\n\nvoid connectCallback(const redisAsyncContext *c, int status) {\n    if (status != REDIS_OK) {\n        printf(\"Error: %s\\n\", c->errstr);\n        return;\n    }\n    printf(\"Connected...\\n\");\n}\n\nvoid disconnectCallback(const redisAsyncContext *c, int status) {\n    if (status != REDIS_OK) {\n        printf(\"Error: %s\\n\", c->errstr);\n        return;\n    }\n    printf(\"Disconnected...\\n\");\n}\n\nint main (int argc, char **argv) {\n    signal(SIGPIPE, SIG_IGN);\n    struct event_base *base = event_base_new();\n\n    redisAsyncContext *c = redisAsyncConnect(\"127.0.0.1\", 6379);\n    if (c->err) {\n        /* Let *c leak for now... */\n        printf(\"Error: %s\\n\", c->errstr);\n        return 1;\n    }\n\n    redisLibeventAttach(c,base);\n    redisAsyncSetConnectCallback(c,connectCallback);\n    redisAsyncSetDisconnectCallback(c,disconnectCallback);\n    redisAsyncCommand(c, NULL, NULL, \"SET key %b\", argv[argc-1], strlen(argv[argc-1]));\n    redisAsyncCommand(c, getCallback, (char*)\"end-1\", \"GET key\");\n    event_base_dispatch(base);\n    return 0;\n}\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/deps/hiredis/examples/example-libuv.c",
    "content": "#include <stdio.h>\n#include <stdlib.h>\n#include <string.h>\n#include <signal.h>\n\n#include <hiredis.h>\n#include <async.h>\n#include <adapters/libuv.h>\n\nvoid getCallback(redisAsyncContext *c, void *r, void *privdata) {\n    redisReply *reply = r;\n    if (reply == NULL) return;\n    printf(\"argv[%s]: %s\\n\", (char*)privdata, reply->str);\n\n    /* Disconnect after receiving the reply to GET */\n    redisAsyncDisconnect(c);\n}\n\nvoid connectCallback(const redisAsyncContext *c, int status) {\n    if (status != REDIS_OK) {\n        printf(\"Error: %s\\n\", c->errstr);\n        return;\n    }\n    printf(\"Connected...\\n\");\n}\n\nvoid disconnectCallback(const redisAsyncContext *c, int status) {\n    if (status != REDIS_OK) {\n        printf(\"Error: %s\\n\", c->errstr);\n        return;\n    }\n    printf(\"Disconnected...\\n\");\n}\n\nint main (int argc, char **argv) {\n    signal(SIGPIPE, SIG_IGN);\n    uv_loop_t* loop = uv_default_loop();\n\n    redisAsyncContext *c = redisAsyncConnect(\"127.0.0.1\", 6379);\n    if (c->err) {\n        /* Let *c leak for now... */\n        printf(\"Error: %s\\n\", c->errstr);\n        return 1;\n    }\n\n    redisLibuvAttach(c,loop);\n    redisAsyncSetConnectCallback(c,connectCallback);\n    redisAsyncSetDisconnectCallback(c,disconnectCallback);\n    redisAsyncCommand(c, NULL, NULL, \"SET key %b\", argv[argc-1], strlen(argv[argc-1]));\n    redisAsyncCommand(c, getCallback, (char*)\"end-1\", \"GET key\");\n    uv_run(loop, UV_RUN_DEFAULT);\n    return 0;\n}\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/deps/hiredis/examples/example.c",
    "content": "#include <stdio.h>\n#include <stdlib.h>\n#include <string.h>\n\n#include <hiredis.h>\n\nint main(int argc, char **argv) {\n    unsigned int j;\n    redisContext *c;\n    redisReply *reply;\n    const char *hostname = (argc > 1) ? argv[1] : \"127.0.0.1\";\n    int port = (argc > 2) ? atoi(argv[2]) : 6379;\n\n    struct timeval timeout = { 1, 500000 }; // 1.5 seconds\n    c = redisConnectWithTimeout(hostname, port, timeout);\n    if (c == NULL || c->err) {\n        if (c) {\n            printf(\"Connection error: %s\\n\", c->errstr);\n            redisFree(c);\n        } else {\n            printf(\"Connection error: can't allocate redis context\\n\");\n        }\n        exit(1);\n    }\n\n    /* PING server */\n    reply = redisCommand(c,\"PING\");\n    printf(\"PING: %s\\n\", reply->str);\n    freeReplyObject(reply);\n\n    /* Set a key */\n    reply = redisCommand(c,\"SET %s %s\", \"foo\", \"hello world\");\n    printf(\"SET: %s\\n\", reply->str);\n    freeReplyObject(reply);\n\n    /* Set a key using binary safe API */\n    reply = redisCommand(c,\"SET %b %b\", \"bar\", (size_t) 3, \"hello\", (size_t) 5);\n    printf(\"SET (binary API): %s\\n\", reply->str);\n    freeReplyObject(reply);\n\n    /* Try a GET and two INCR */\n    reply = redisCommand(c,\"GET foo\");\n    printf(\"GET foo: %s\\n\", reply->str);\n    freeReplyObject(reply);\n\n    reply = redisCommand(c,\"INCR counter\");\n    printf(\"INCR counter: %lld\\n\", reply->integer);\n    freeReplyObject(reply);\n    /* again ... */\n    reply = redisCommand(c,\"INCR counter\");\n    printf(\"INCR counter: %lld\\n\", reply->integer);\n    freeReplyObject(reply);\n\n    /* Create a list of numbers, from 0 to 9 */\n    reply = redisCommand(c,\"DEL mylist\");\n    freeReplyObject(reply);\n    for (j = 0; j < 10; j++) {\n        char buf[64];\n\n        snprintf(buf,64,\"%d\",j);\n        reply = redisCommand(c,\"LPUSH mylist element-%s\", buf);\n        freeReplyObject(reply);\n    }\n\n    /* Let's check what we have inside the list */\n    reply = redisCommand(c,\"LRANGE mylist 0 -1\");\n    if (reply->type == REDIS_REPLY_ARRAY) {\n        for (j = 0; j < reply->elements; j++) {\n            printf(\"%u) %s\\n\", j, reply->element[j]->str);\n        }\n    }\n    freeReplyObject(reply);\n\n    /* Disconnects and frees the context */\n    redisFree(c);\n\n    return 0;\n}\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/deps/hiredis/fmacros.h",
    "content": "#ifndef __HIREDIS_FMACRO_H\n#define __HIREDIS_FMACRO_H\n\n#if !defined(_BSD_SOURCE)\n#define _BSD_SOURCE\n#endif\n\n#if defined(_AIX)\n#define _ALL_SOURCE\n#endif\n\n#if defined(__sun__)\n#define _POSIX_C_SOURCE 200112L\n#elif defined(__linux__) || defined(__OpenBSD__) || defined(__NetBSD__)\n#define _XOPEN_SOURCE 600\n#else\n#define _XOPEN_SOURCE\n#endif\n\n#if __APPLE__ && __MACH__\n#define _OSX\n#endif\n\n#endif\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/deps/hiredis/hiredis.c",
    "content": "/*\n * Copyright (c) 2009-2011, Salvatore Sanfilippo <antirez at gmail dot com>\n * Copyright (c) 2010-2011, Pieter Noordhuis <pcnoordhuis at gmail dot com>\n *\n * All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions are met:\n *\n *   * Redistributions of source code must retain the above copyright notice,\n *     this list of conditions and the following disclaimer.\n *   * Redistributions in binary form must reproduce the above copyright\n *     notice, this list of conditions and the following disclaimer in the\n *     documentation and/or other materials provided with the distribution.\n *   * Neither the name of Redis nor the names of its contributors may be used\n *     to endorse or promote products derived from this software without\n *     specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\"\n * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\n * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE\n * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR\n * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF\n * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS\n * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN\n * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)\n * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE\n * POSSIBILITY OF SUCH DAMAGE.\n */\n\n#include \"fmacros.h\"\n#include <string.h>\n#include <stdlib.h>\n#include <unistd.h>\n#include <assert.h>\n#include <errno.h>\n#include <ctype.h>\n\n#include \"hiredis.h\"\n#include \"net.h\"\n#include \"sds.h\"\n\nstatic redisReply *createReplyObject(int type);\nstatic void *createStringObject(const redisReadTask *task, char *str, size_t len);\nstatic void *createArrayObject(const redisReadTask *task, int elements);\nstatic void *createIntegerObject(const redisReadTask *task, long long value);\nstatic void *createNilObject(const redisReadTask *task);\n\n/* Default set of functions to build the reply. Keep in mind that such a\n * function returning NULL is interpreted as OOM. */\nstatic redisReplyObjectFunctions defaultFunctions = {\n    createStringObject,\n    createArrayObject,\n    createIntegerObject,\n    createNilObject,\n    freeReplyObject\n};\n\n/* Create a reply object */\nstatic redisReply *createReplyObject(int type) {\n    redisReply *r = calloc(1,sizeof(*r));\n\n    if (r == NULL)\n        return NULL;\n\n    r->type = type;\n    return r;\n}\n\n/* Free a reply object */\nvoid freeReplyObject(void *reply) {\n    redisReply *r = reply;\n    size_t j;\n\n    switch(r->type) {\n    case REDIS_REPLY_INTEGER:\n        break; /* Nothing to free */\n    case REDIS_REPLY_ARRAY:\n        if (r->element != NULL) {\n            for (j = 0; j < r->elements; j++)\n                if (r->element[j] != NULL)\n                    freeReplyObject(r->element[j]);\n            free(r->element);\n        }\n        break;\n    case REDIS_REPLY_ERROR:\n    case REDIS_REPLY_STATUS:\n    case REDIS_REPLY_STRING:\n        if (r->str != NULL)\n            free(r->str);\n        break;\n    }\n    free(r);\n}\n\nstatic void *createStringObject(const redisReadTask *task, char *str, size_t len) {\n    redisReply *r, *parent;\n    char *buf;\n\n    r = createReplyObject(task->type);\n    if (r == NULL)\n        return NULL;\n\n    buf = malloc(len+1);\n    if (buf == NULL) {\n        freeReplyObject(r);\n        return NULL;\n    }\n\n    assert(task->type == REDIS_REPLY_ERROR  ||\n           task->type == REDIS_REPLY_STATUS ||\n           task->type == REDIS_REPLY_STRING);\n\n    /* Copy string value */\n    memcpy(buf,str,len);\n    buf[len] = '\\0';\n    r->str = buf;\n    r->len = len;\n\n    if (task->parent) {\n        parent = task->parent->obj;\n        assert(parent->type == REDIS_REPLY_ARRAY);\n        parent->element[task->idx] = r;\n    }\n    return r;\n}\n\nstatic void *createArrayObject(const redisReadTask *task, int elements) {\n    redisReply *r, *parent;\n\n    r = createReplyObject(REDIS_REPLY_ARRAY);\n    if (r == NULL)\n        return NULL;\n\n    if (elements > 0) {\n        r->element = calloc(elements,sizeof(redisReply*));\n        if (r->element == NULL) {\n            freeReplyObject(r);\n            return NULL;\n        }\n    }\n\n    r->elements = elements;\n\n    if (task->parent) {\n        parent = task->parent->obj;\n        assert(parent->type == REDIS_REPLY_ARRAY);\n        parent->element[task->idx] = r;\n    }\n    return r;\n}\n\nstatic void *createIntegerObject(const redisReadTask *task, long long value) {\n    redisReply *r, *parent;\n\n    r = createReplyObject(REDIS_REPLY_INTEGER);\n    if (r == NULL)\n        return NULL;\n\n    r->integer = value;\n\n    if (task->parent) {\n        parent = task->parent->obj;\n        assert(parent->type == REDIS_REPLY_ARRAY);\n        parent->element[task->idx] = r;\n    }\n    return r;\n}\n\nstatic void *createNilObject(const redisReadTask *task) {\n    redisReply *r, *parent;\n\n    r = createReplyObject(REDIS_REPLY_NIL);\n    if (r == NULL)\n        return NULL;\n\n    if (task->parent) {\n        parent = task->parent->obj;\n        assert(parent->type == REDIS_REPLY_ARRAY);\n        parent->element[task->idx] = r;\n    }\n    return r;\n}\n\nstatic void __redisReaderSetError(redisReader *r, int type, const char *str) {\n    size_t len;\n\n    if (r->reply != NULL && r->fn && r->fn->freeObject) {\n        r->fn->freeObject(r->reply);\n        r->reply = NULL;\n    }\n\n    /* Clear input buffer on errors. */\n    if (r->buf != NULL) {\n        sdsfree(r->buf);\n        r->buf = NULL;\n        r->pos = r->len = 0;\n    }\n\n    /* Reset task stack. */\n    r->ridx = -1;\n\n    /* Set error. */\n    r->err = type;\n    len = strlen(str);\n    len = len < (sizeof(r->errstr)-1) ? len : (sizeof(r->errstr)-1);\n    memcpy(r->errstr,str,len);\n    r->errstr[len] = '\\0';\n}\n\nstatic size_t chrtos(char *buf, size_t size, char byte) {\n    size_t len = 0;\n\n    switch(byte) {\n    case '\\\\':\n    case '\"':\n        len = snprintf(buf,size,\"\\\"\\\\%c\\\"\",byte);\n        break;\n    case '\\n': len = snprintf(buf,size,\"\\\"\\\\n\\\"\"); break;\n    case '\\r': len = snprintf(buf,size,\"\\\"\\\\r\\\"\"); break;\n    case '\\t': len = snprintf(buf,size,\"\\\"\\\\t\\\"\"); break;\n    case '\\a': len = snprintf(buf,size,\"\\\"\\\\a\\\"\"); break;\n    case '\\b': len = snprintf(buf,size,\"\\\"\\\\b\\\"\"); break;\n    default:\n        if (isprint(byte))\n            len = snprintf(buf,size,\"\\\"%c\\\"\",byte);\n        else\n            len = snprintf(buf,size,\"\\\"\\\\x%02x\\\"\",(unsigned char)byte);\n        break;\n    }\n\n    return len;\n}\n\nstatic void __redisReaderSetErrorProtocolByte(redisReader *r, char byte) {\n    char cbuf[8], sbuf[128];\n\n    chrtos(cbuf,sizeof(cbuf),byte);\n    snprintf(sbuf,sizeof(sbuf),\n        \"Protocol error, got %s as reply type byte\", cbuf);\n    __redisReaderSetError(r,REDIS_ERR_PROTOCOL,sbuf);\n}\n\nstatic void __redisReaderSetErrorOOM(redisReader *r) {\n    __redisReaderSetError(r,REDIS_ERR_OOM,\"Out of memory\");\n}\n\nstatic char *readBytes(redisReader *r, unsigned int bytes) {\n    char *p;\n    if (r->len-r->pos >= bytes) {\n        p = r->buf+r->pos;\n        r->pos += bytes;\n        return p;\n    }\n    return NULL;\n}\n\n/* Find pointer to \\r\\n. */\nstatic char *seekNewline(char *s, size_t len) {\n    int pos = 0;\n    int _len = len-1;\n\n    /* Position should be < len-1 because the character at \"pos\" should be\n     * followed by a \\n. Note that strchr cannot be used because it doesn't\n     * allow to search a limited length and the buffer that is being searched\n     * might not have a trailing NULL character. */\n    while (pos < _len) {\n        while(pos < _len && s[pos] != '\\r') pos++;\n        if (s[pos] != '\\r') {\n            /* Not found. */\n            return NULL;\n        } else {\n            if (s[pos+1] == '\\n') {\n                /* Found. */\n                return s+pos;\n            } else {\n                /* Continue searching. */\n                pos++;\n            }\n        }\n    }\n    return NULL;\n}\n\n/* Read a long long value starting at *s, under the assumption that it will be\n * terminated by \\r\\n. Ambiguously returns -1 for unexpected input. */\nstatic long long readLongLong(char *s) {\n    long long v = 0;\n    int dec, mult = 1;\n    char c;\n\n    if (*s == '-') {\n        mult = -1;\n        s++;\n    } else if (*s == '+') {\n        mult = 1;\n        s++;\n    }\n\n    while ((c = *(s++)) != '\\r') {\n        dec = c - '0';\n        if (dec >= 0 && dec < 10) {\n            v *= 10;\n            v += dec;\n        } else {\n            /* Should not happen... */\n            return -1;\n        }\n    }\n\n    return mult*v;\n}\n\nstatic char *readLine(redisReader *r, int *_len) {\n    char *p, *s;\n    int len;\n\n    p = r->buf+r->pos;\n    s = seekNewline(p,(r->len-r->pos));\n    if (s != NULL) {\n        len = s-(r->buf+r->pos);\n        r->pos += len+2; /* skip \\r\\n */\n        if (_len) *_len = len;\n        return p;\n    }\n    return NULL;\n}\n\nstatic void moveToNextTask(redisReader *r) {\n    redisReadTask *cur, *prv;\n    while (r->ridx >= 0) {\n        /* Return a.s.a.p. when the stack is now empty. */\n        if (r->ridx == 0) {\n            r->ridx--;\n            return;\n        }\n\n        cur = &(r->rstack[r->ridx]);\n        prv = &(r->rstack[r->ridx-1]);\n        assert(prv->type == REDIS_REPLY_ARRAY);\n        if (cur->idx == prv->elements-1) {\n            r->ridx--;\n        } else {\n            /* Reset the type because the next item can be anything */\n            assert(cur->idx < prv->elements);\n            cur->type = -1;\n            cur->elements = -1;\n            cur->idx++;\n            return;\n        }\n    }\n}\n\nstatic int processLineItem(redisReader *r) {\n    redisReadTask *cur = &(r->rstack[r->ridx]);\n    void *obj;\n    char *p;\n    int len;\n\n    if ((p = readLine(r,&len)) != NULL) {\n        if (cur->type == REDIS_REPLY_INTEGER) {\n            if (r->fn && r->fn->createInteger)\n                obj = r->fn->createInteger(cur,readLongLong(p));\n            else\n                obj = (void*)REDIS_REPLY_INTEGER;\n        } else {\n            /* Type will be error or status. */\n            if (r->fn && r->fn->createString)\n                obj = r->fn->createString(cur,p,len);\n            else\n                obj = (void*)(size_t)(cur->type);\n        }\n\n        if (obj == NULL) {\n            __redisReaderSetErrorOOM(r);\n            return REDIS_ERR;\n        }\n\n        /* Set reply if this is the root object. */\n        if (r->ridx == 0) r->reply = obj;\n        moveToNextTask(r);\n        return REDIS_OK;\n    }\n\n    return REDIS_ERR;\n}\n\nstatic int processBulkItem(redisReader *r) {\n    redisReadTask *cur = &(r->rstack[r->ridx]);\n    void *obj = NULL;\n    char *p, *s;\n    long len;\n    unsigned long bytelen;\n    int success = 0;\n\n    p = r->buf+r->pos;\n    s = seekNewline(p,r->len-r->pos);\n    if (s != NULL) {\n        p = r->buf+r->pos;\n        bytelen = s-(r->buf+r->pos)+2; /* include \\r\\n */\n        len = readLongLong(p);\n\n        if (len < 0) {\n            /* The nil object can always be created. */\n            if (r->fn && r->fn->createNil)\n                obj = r->fn->createNil(cur);\n            else\n                obj = (void*)REDIS_REPLY_NIL;\n            success = 1;\n        } else {\n            /* Only continue when the buffer contains the entire bulk item. */\n            bytelen += len+2; /* include \\r\\n */\n            if (r->pos+bytelen <= r->len) {\n                if (r->fn && r->fn->createString)\n                    obj = r->fn->createString(cur,s+2,len);\n                else\n                    obj = (void*)REDIS_REPLY_STRING;\n                success = 1;\n            }\n        }\n\n        /* Proceed when obj was created. */\n        if (success) {\n            if (obj == NULL) {\n                __redisReaderSetErrorOOM(r);\n                return REDIS_ERR;\n            }\n\n            r->pos += bytelen;\n\n            /* Set reply if this is the root object. */\n            if (r->ridx == 0) r->reply = obj;\n            moveToNextTask(r);\n            return REDIS_OK;\n        }\n    }\n\n    return REDIS_ERR;\n}\n\nstatic int processMultiBulkItem(redisReader *r) {\n    redisReadTask *cur = &(r->rstack[r->ridx]);\n    void *obj;\n    char *p;\n    long elements;\n    int root = 0;\n\n    /* Set error for nested multi bulks with depth > 7 */\n    if (r->ridx == 8) {\n        __redisReaderSetError(r,REDIS_ERR_PROTOCOL,\n            \"No support for nested multi bulk replies with depth > 7\");\n        return REDIS_ERR;\n    }\n\n    if ((p = readLine(r,NULL)) != NULL) {\n        elements = readLongLong(p);\n        root = (r->ridx == 0);\n\n        if (elements == -1) {\n            if (r->fn && r->fn->createNil)\n                obj = r->fn->createNil(cur);\n            else\n                obj = (void*)REDIS_REPLY_NIL;\n\n            if (obj == NULL) {\n                __redisReaderSetErrorOOM(r);\n                return REDIS_ERR;\n            }\n\n            moveToNextTask(r);\n        } else {\n            if (r->fn && r->fn->createArray)\n                obj = r->fn->createArray(cur,elements);\n            else\n                obj = (void*)REDIS_REPLY_ARRAY;\n\n            if (obj == NULL) {\n                __redisReaderSetErrorOOM(r);\n                return REDIS_ERR;\n            }\n\n            /* Modify task stack when there are more than 0 elements. */\n            if (elements > 0) {\n                cur->elements = elements;\n                cur->obj = obj;\n                r->ridx++;\n                r->rstack[r->ridx].type = -1;\n                r->rstack[r->ridx].elements = -1;\n                r->rstack[r->ridx].idx = 0;\n                r->rstack[r->ridx].obj = NULL;\n                r->rstack[r->ridx].parent = cur;\n                r->rstack[r->ridx].privdata = r->privdata;\n            } else {\n                moveToNextTask(r);\n            }\n        }\n\n        /* Set reply if this is the root object. */\n        if (root) r->reply = obj;\n        return REDIS_OK;\n    }\n\n    return REDIS_ERR;\n}\n\nstatic int processItem(redisReader *r) {\n    redisReadTask *cur = &(r->rstack[r->ridx]);\n    char *p;\n\n    /* check if we need to read type */\n    if (cur->type < 0) {\n        if ((p = readBytes(r,1)) != NULL) {\n            switch (p[0]) {\n            case '-':\n                cur->type = REDIS_REPLY_ERROR;\n                break;\n            case '+':\n                cur->type = REDIS_REPLY_STATUS;\n                break;\n            case ':':\n                cur->type = REDIS_REPLY_INTEGER;\n                break;\n            case '$':\n                cur->type = REDIS_REPLY_STRING;\n                break;\n            case '*':\n                cur->type = REDIS_REPLY_ARRAY;\n                break;\n            default:\n                __redisReaderSetErrorProtocolByte(r,*p);\n                return REDIS_ERR;\n            }\n        } else {\n            /* could not consume 1 byte */\n            return REDIS_ERR;\n        }\n    }\n\n    /* process typed item */\n    switch(cur->type) {\n    case REDIS_REPLY_ERROR:\n    case REDIS_REPLY_STATUS:\n    case REDIS_REPLY_INTEGER:\n        return processLineItem(r);\n    case REDIS_REPLY_STRING:\n        return processBulkItem(r);\n    case REDIS_REPLY_ARRAY:\n        return processMultiBulkItem(r);\n    default:\n        assert(NULL);\n        return REDIS_ERR; /* Avoid warning. */\n    }\n}\n\nredisReader *redisReaderCreate(void) {\n    redisReader *r;\n\n    r = calloc(sizeof(redisReader),1);\n    if (r == NULL)\n        return NULL;\n\n    r->err = 0;\n    r->errstr[0] = '\\0';\n    r->fn = &defaultFunctions;\n    r->buf = sdsempty();\n    r->maxbuf = REDIS_READER_MAX_BUF;\n    if (r->buf == NULL) {\n        free(r);\n        return NULL;\n    }\n\n    r->ridx = -1;\n    return r;\n}\n\nvoid redisReaderFree(redisReader *r) {\n    if (r->reply != NULL && r->fn && r->fn->freeObject)\n        r->fn->freeObject(r->reply);\n    if (r->buf != NULL)\n        sdsfree(r->buf);\n    free(r);\n}\n\nint redisReaderFeed(redisReader *r, const char *buf, size_t len) {\n    sds newbuf;\n\n    /* Return early when this reader is in an erroneous state. */\n    if (r->err)\n        return REDIS_ERR;\n\n    /* Copy the provided buffer. */\n    if (buf != NULL && len >= 1) {\n        /* Destroy internal buffer when it is empty and is quite large. */\n        if (r->len == 0 && r->maxbuf != 0 && sdsavail(r->buf) > r->maxbuf) {\n            sdsfree(r->buf);\n            r->buf = sdsempty();\n            r->pos = 0;\n\n            /* r->buf should not be NULL since we just free'd a larger one. */\n            assert(r->buf != NULL);\n        }\n\n        newbuf = sdscatlen(r->buf,buf,len);\n        if (newbuf == NULL) {\n            __redisReaderSetErrorOOM(r);\n            return REDIS_ERR;\n        }\n\n        r->buf = newbuf;\n        r->len = sdslen(r->buf);\n    }\n\n    return REDIS_OK;\n}\n\nint redisReaderGetReply(redisReader *r, void **reply) {\n    /* Default target pointer to NULL. */\n    if (reply != NULL)\n        *reply = NULL;\n\n    /* Return early when this reader is in an erroneous state. */\n    if (r->err)\n        return REDIS_ERR;\n\n    /* When the buffer is empty, there will never be a reply. */\n    if (r->len == 0)\n        return REDIS_OK;\n\n    /* Set first item to process when the stack is empty. */\n    if (r->ridx == -1) {\n        r->rstack[0].type = -1;\n        r->rstack[0].elements = -1;\n        r->rstack[0].idx = -1;\n        r->rstack[0].obj = NULL;\n        r->rstack[0].parent = NULL;\n        r->rstack[0].privdata = r->privdata;\n        r->ridx = 0;\n    }\n\n    /* Process items in reply. */\n    while (r->ridx >= 0)\n        if (processItem(r) != REDIS_OK)\n            break;\n\n    /* Return ASAP when an error occurred. */\n    if (r->err)\n        return REDIS_ERR;\n\n    /* Discard part of the buffer when we've consumed at least 1k, to avoid\n     * doing unnecessary calls to memmove() in sds.c. */\n    if (r->pos >= 1024) {\n        sdsrange(r->buf,r->pos,-1);\n        r->pos = 0;\n        r->len = sdslen(r->buf);\n    }\n\n    /* Emit a reply when there is one. */\n    if (r->ridx == -1) {\n        if (reply != NULL)\n            *reply = r->reply;\n        r->reply = NULL;\n    }\n    return REDIS_OK;\n}\n\n/* Calculate the number of bytes needed to represent an integer as string. */\nstatic int intlen(int i) {\n    int len = 0;\n    if (i < 0) {\n        len++;\n        i = -i;\n    }\n    do {\n        len++;\n        i /= 10;\n    } while(i);\n    return len;\n}\n\n/* Helper that calculates the bulk length given a certain string length. */\nstatic size_t bulklen(size_t len) {\n    return 1+intlen(len)+2+len+2;\n}\n\nint redisvFormatCommand(char **target, const char *format, va_list ap) {\n    const char *c = format;\n    char *cmd = NULL; /* final command */\n    int pos; /* position in final command */\n    sds curarg, newarg; /* current argument */\n    int touched = 0; /* was the current argument touched? */\n    char **curargv = NULL, **newargv = NULL;\n    int argc = 0;\n    int totlen = 0;\n    int j;\n\n    /* Abort if there is not target to set */\n    if (target == NULL)\n        return -1;\n\n    /* Build the command string accordingly to protocol */\n    curarg = sdsempty();\n    if (curarg == NULL)\n        return -1;\n\n    while(*c != '\\0') {\n        if (*c != '%' || c[1] == '\\0') {\n            if (*c == ' ') {\n                if (touched) {\n                    newargv = realloc(curargv,sizeof(char*)*(argc+1));\n                    if (newargv == NULL) goto err;\n                    curargv = newargv;\n                    curargv[argc++] = curarg;\n                    totlen += bulklen(sdslen(curarg));\n\n                    /* curarg is put in argv so it can be overwritten. */\n                    curarg = sdsempty();\n                    if (curarg == NULL) goto err;\n                    touched = 0;\n                }\n            } else {\n                newarg = sdscatlen(curarg,c,1);\n                if (newarg == NULL) goto err;\n                curarg = newarg;\n                touched = 1;\n            }\n        } else {\n            char *arg;\n            size_t size;\n\n            /* Set newarg so it can be checked even if it is not touched. */\n            newarg = curarg;\n\n            switch(c[1]) {\n            case 's':\n                arg = va_arg(ap,char*);\n                size = strlen(arg);\n                if (size > 0)\n                    newarg = sdscatlen(curarg,arg,size);\n                break;\n            case 'b':\n                arg = va_arg(ap,char*);\n                size = va_arg(ap,size_t);\n                if (size > 0)\n                    newarg = sdscatlen(curarg,arg,size);\n                break;\n            case '%':\n                newarg = sdscat(curarg,\"%\");\n                break;\n            default:\n                /* Try to detect printf format */\n                {\n                    static const char intfmts[] = \"diouxX\";\n                    char _format[16];\n                    const char *_p = c+1;\n                    size_t _l = 0;\n                    va_list _cpy;\n\n                    /* Flags */\n                    if (*_p != '\\0' && *_p == '#') _p++;\n                    if (*_p != '\\0' && *_p == '0') _p++;\n                    if (*_p != '\\0' && *_p == '-') _p++;\n                    if (*_p != '\\0' && *_p == ' ') _p++;\n                    if (*_p != '\\0' && *_p == '+') _p++;\n\n                    /* Field width */\n                    while (*_p != '\\0' && isdigit(*_p)) _p++;\n\n                    /* Precision */\n                    if (*_p == '.') {\n                        _p++;\n                        while (*_p != '\\0' && isdigit(*_p)) _p++;\n                    }\n\n                    /* Copy va_list before consuming with va_arg */\n                    va_copy(_cpy,ap);\n\n                    /* Integer conversion (without modifiers) */\n                    if (strchr(intfmts,*_p) != NULL) {\n                        va_arg(ap,int);\n                        goto fmt_valid;\n                    }\n\n                    /* Double conversion (without modifiers) */\n                    if (strchr(\"eEfFgGaA\",*_p) != NULL) {\n                        va_arg(ap,double);\n                        goto fmt_valid;\n                    }\n\n                    /* Size: char */\n                    if (_p[0] == 'h' && _p[1] == 'h') {\n                        _p += 2;\n                        if (*_p != '\\0' && strchr(intfmts,*_p) != NULL) {\n                            va_arg(ap,int); /* char gets promoted to int */\n                            goto fmt_valid;\n                        }\n                        goto fmt_invalid;\n                    }\n\n                    /* Size: short */\n                    if (_p[0] == 'h') {\n                        _p += 1;\n                        if (*_p != '\\0' && strchr(intfmts,*_p) != NULL) {\n                            va_arg(ap,int); /* short gets promoted to int */\n                            goto fmt_valid;\n                        }\n                        goto fmt_invalid;\n                    }\n\n                    /* Size: long long */\n                    if (_p[0] == 'l' && _p[1] == 'l') {\n                        _p += 2;\n                        if (*_p != '\\0' && strchr(intfmts,*_p) != NULL) {\n                            va_arg(ap,long long);\n                            goto fmt_valid;\n                        }\n                        goto fmt_invalid;\n                    }\n\n                    /* Size: long */\n                    if (_p[0] == 'l') {\n                        _p += 1;\n                        if (*_p != '\\0' && strchr(intfmts,*_p) != NULL) {\n                            va_arg(ap,long);\n                            goto fmt_valid;\n                        }\n                        goto fmt_invalid;\n                    }\n\n                fmt_invalid:\n                    va_end(_cpy);\n                    goto err;\n\n                fmt_valid:\n                    _l = (_p+1)-c;\n                    if (_l < sizeof(_format)-2) {\n                        memcpy(_format,c,_l);\n                        _format[_l] = '\\0';\n                        newarg = sdscatvprintf(curarg,_format,_cpy);\n\n                        /* Update current position (note: outer blocks\n                         * increment c twice so compensate here) */\n                        c = _p-1;\n                    }\n\n                    va_end(_cpy);\n                    break;\n                }\n            }\n\n            if (newarg == NULL) goto err;\n            curarg = newarg;\n\n            touched = 1;\n            c++;\n        }\n        c++;\n    }\n\n    /* Add the last argument if needed */\n    if (touched) {\n        newargv = realloc(curargv,sizeof(char*)*(argc+1));\n        if (newargv == NULL) goto err;\n        curargv = newargv;\n        curargv[argc++] = curarg;\n        totlen += bulklen(sdslen(curarg));\n    } else {\n        sdsfree(curarg);\n    }\n\n    /* Clear curarg because it was put in curargv or was free'd. */\n    curarg = NULL;\n\n    /* Add bytes needed to hold multi bulk count */\n    totlen += 1+intlen(argc)+2;\n\n    /* Build the command at protocol level */\n    cmd = malloc(totlen+1);\n    if (cmd == NULL) goto err;\n\n    pos = sprintf(cmd,\"*%d\\r\\n\",argc);\n    for (j = 0; j < argc; j++) {\n        pos += sprintf(cmd+pos,\"$%zu\\r\\n\",sdslen(curargv[j]));\n        memcpy(cmd+pos,curargv[j],sdslen(curargv[j]));\n        pos += sdslen(curargv[j]);\n        sdsfree(curargv[j]);\n        cmd[pos++] = '\\r';\n        cmd[pos++] = '\\n';\n    }\n    assert(pos == totlen);\n    cmd[pos] = '\\0';\n\n    free(curargv);\n    *target = cmd;\n    return totlen;\n\nerr:\n    while(argc--)\n        sdsfree(curargv[argc]);\n    free(curargv);\n\n    if (curarg != NULL)\n        sdsfree(curarg);\n\n    /* No need to check cmd since it is the last statement that can fail,\n     * but do it anyway to be as defensive as possible. */\n    if (cmd != NULL)\n        free(cmd);\n\n    return -1;\n}\n\n/* Format a command according to the Redis protocol. This function\n * takes a format similar to printf:\n *\n * %s represents a C null terminated string you want to interpolate\n * %b represents a binary safe string\n *\n * When using %b you need to provide both the pointer to the string\n * and the length in bytes as a size_t. Examples:\n *\n * len = redisFormatCommand(target, \"GET %s\", mykey);\n * len = redisFormatCommand(target, \"SET %s %b\", mykey, myval, myvallen);\n */\nint redisFormatCommand(char **target, const char *format, ...) {\n    va_list ap;\n    int len;\n    va_start(ap,format);\n    len = redisvFormatCommand(target,format,ap);\n    va_end(ap);\n    return len;\n}\n\n/* Format a command according to the Redis protocol. This function takes the\n * number of arguments, an array with arguments and an array with their\n * lengths. If the latter is set to NULL, strlen will be used to compute the\n * argument lengths.\n */\nint redisFormatCommandArgv(char **target, int argc, const char **argv, const size_t *argvlen) {\n    char *cmd = NULL; /* final command */\n    int pos; /* position in final command */\n    size_t len;\n    int totlen, j;\n\n    /* Calculate number of bytes needed for the command */\n    totlen = 1+intlen(argc)+2;\n    for (j = 0; j < argc; j++) {\n        len = argvlen ? argvlen[j] : strlen(argv[j]);\n        totlen += bulklen(len);\n    }\n\n    /* Build the command at protocol level */\n    cmd = malloc(totlen+1);\n    if (cmd == NULL)\n        return -1;\n\n    pos = sprintf(cmd,\"*%d\\r\\n\",argc);\n    for (j = 0; j < argc; j++) {\n        len = argvlen ? argvlen[j] : strlen(argv[j]);\n        pos += sprintf(cmd+pos,\"$%zu\\r\\n\",len);\n        memcpy(cmd+pos,argv[j],len);\n        pos += len;\n        cmd[pos++] = '\\r';\n        cmd[pos++] = '\\n';\n    }\n    assert(pos == totlen);\n    cmd[pos] = '\\0';\n\n    *target = cmd;\n    return totlen;\n}\n\nvoid __redisSetError(redisContext *c, int type, const char *str) {\n    size_t len;\n\n    c->err = type;\n    if (str != NULL) {\n        len = strlen(str);\n        len = len < (sizeof(c->errstr)-1) ? len : (sizeof(c->errstr)-1);\n        memcpy(c->errstr,str,len);\n        c->errstr[len] = '\\0';\n    } else {\n        /* Only REDIS_ERR_IO may lack a description! */\n        assert(type == REDIS_ERR_IO);\n        strerror_r(errno,c->errstr,sizeof(c->errstr));\n    }\n}\n\nstatic redisContext *redisContextInit(void) {\n    redisContext *c;\n\n    c = calloc(1,sizeof(redisContext));\n    if (c == NULL)\n        return NULL;\n\n    c->err = 0;\n    c->errstr[0] = '\\0';\n    c->obuf = sdsempty();\n    c->reader = redisReaderCreate();\n    return c;\n}\n\nvoid redisFree(redisContext *c) {\n    if (c->fd > 0)\n        close(c->fd);\n    if (c->obuf != NULL)\n        sdsfree(c->obuf);\n    if (c->reader != NULL)\n        redisReaderFree(c->reader);\n    free(c);\n}\n\nint redisFreeKeepFd(redisContext *c) {\n\tint fd = c->fd;\n\tc->fd = -1;\n\tredisFree(c);\n\treturn fd;\n}\n\n/* Connect to a Redis instance. On error the field error in the returned\n * context will be set to the return value of the error function.\n * When no set of reply functions is given, the default set will be used. */\nredisContext *redisConnect(const char *ip, int port) {\n    redisContext *c;\n\n    c = redisContextInit();\n    if (c == NULL)\n        return NULL;\n\n    c->flags |= REDIS_BLOCK;\n    redisContextConnectTcp(c,ip,port,NULL);\n    return c;\n}\n\nredisContext *redisConnectWithTimeout(const char *ip, int port, const struct timeval tv) {\n    redisContext *c;\n\n    c = redisContextInit();\n    if (c == NULL)\n        return NULL;\n\n    c->flags |= REDIS_BLOCK;\n    redisContextConnectTcp(c,ip,port,&tv);\n    return c;\n}\n\nredisContext *redisConnectNonBlock(const char *ip, int port) {\n    redisContext *c;\n\n    c = redisContextInit();\n    if (c == NULL)\n        return NULL;\n\n    c->flags &= ~REDIS_BLOCK;\n    redisContextConnectTcp(c,ip,port,NULL);\n    return c;\n}\n\nredisContext *redisConnectBindNonBlock(const char *ip, int port,\n                                       const char *source_addr) {\n    redisContext *c = redisContextInit();\n    c->flags &= ~REDIS_BLOCK;\n    redisContextConnectBindTcp(c,ip,port,NULL,source_addr);\n    return c;\n}\n\nredisContext *redisConnectUnix(const char *path) {\n    redisContext *c;\n\n    c = redisContextInit();\n    if (c == NULL)\n        return NULL;\n\n    c->flags |= REDIS_BLOCK;\n    redisContextConnectUnix(c,path,NULL);\n    return c;\n}\n\nredisContext *redisConnectUnixWithTimeout(const char *path, const struct timeval tv) {\n    redisContext *c;\n\n    c = redisContextInit();\n    if (c == NULL)\n        return NULL;\n\n    c->flags |= REDIS_BLOCK;\n    redisContextConnectUnix(c,path,&tv);\n    return c;\n}\n\nredisContext *redisConnectUnixNonBlock(const char *path) {\n    redisContext *c;\n\n    c = redisContextInit();\n    if (c == NULL)\n        return NULL;\n\n    c->flags &= ~REDIS_BLOCK;\n    redisContextConnectUnix(c,path,NULL);\n    return c;\n}\n\nredisContext *redisConnectFd(int fd) {\n    redisContext *c;\n\n    c = redisContextInit();\n    if (c == NULL)\n        return NULL;\n\n    c->fd = fd;\n    c->flags |= REDIS_BLOCK | REDIS_CONNECTED;\n    return c;\n}\n\n/* Set read/write timeout on a blocking socket. */\nint redisSetTimeout(redisContext *c, const struct timeval tv) {\n    if (c->flags & REDIS_BLOCK)\n        return redisContextSetTimeout(c,tv);\n    return REDIS_ERR;\n}\n\n/* Enable connection KeepAlive. */\nint redisEnableKeepAlive(redisContext *c) {\n    if (redisKeepAlive(c, REDIS_KEEPALIVE_INTERVAL) != REDIS_OK)\n        return REDIS_ERR;\n    return REDIS_OK;\n}\n\n/* Use this function to handle a read event on the descriptor. It will try\n * and read some bytes from the socket and feed them to the reply parser.\n *\n * After this function is called, you may use redisContextReadReply to\n * see if there is a reply available. */\nint redisBufferRead(redisContext *c) {\n    char buf[1024*16];\n    int nread;\n\n    /* Return early when the context has seen an error. */\n    if (c->err)\n        return REDIS_ERR;\n\n    nread = read(c->fd,buf,sizeof(buf));\n    if (nread == -1) {\n        if ((errno == EAGAIN && !(c->flags & REDIS_BLOCK)) || (errno == EINTR)) {\n            /* Try again later */\n        } else {\n            __redisSetError(c,REDIS_ERR_IO,NULL);\n            return REDIS_ERR;\n        }\n    } else if (nread == 0) {\n        __redisSetError(c,REDIS_ERR_EOF,\"Server closed the connection\");\n        return REDIS_ERR;\n    } else {\n        if (redisReaderFeed(c->reader,buf,nread) != REDIS_OK) {\n            __redisSetError(c,c->reader->err,c->reader->errstr);\n            return REDIS_ERR;\n        }\n    }\n    return REDIS_OK;\n}\n\n/* Write the output buffer to the socket.\n *\n * Returns REDIS_OK when the buffer is empty, or (a part of) the buffer was\n * succesfully written to the socket. When the buffer is empty after the\n * write operation, \"done\" is set to 1 (if given).\n *\n * Returns REDIS_ERR if an error occured trying to write and sets\n * c->errstr to hold the appropriate error string.\n */\nint redisBufferWrite(redisContext *c, int *done) {\n    int nwritten;\n\n    /* Return early when the context has seen an error. */\n    if (c->err)\n        return REDIS_ERR;\n\n    if (sdslen(c->obuf) > 0) {\n        nwritten = write(c->fd,c->obuf,sdslen(c->obuf));\n        if (nwritten == -1) {\n            if ((errno == EAGAIN && !(c->flags & REDIS_BLOCK)) || (errno == EINTR)) {\n                /* Try again later */\n            } else {\n                __redisSetError(c,REDIS_ERR_IO,NULL);\n                return REDIS_ERR;\n            }\n        } else if (nwritten > 0) {\n            if (nwritten == (signed)sdslen(c->obuf)) {\n                sdsfree(c->obuf);\n                c->obuf = sdsempty();\n            } else {\n                sdsrange(c->obuf,nwritten,-1);\n            }\n        }\n    }\n    if (done != NULL) *done = (sdslen(c->obuf) == 0);\n    return REDIS_OK;\n}\n\n/* Internal helper function to try and get a reply from the reader,\n * or set an error in the context otherwise. */\nint redisGetReplyFromReader(redisContext *c, void **reply) {\n    if (redisReaderGetReply(c->reader,reply) == REDIS_ERR) {\n        __redisSetError(c,c->reader->err,c->reader->errstr);\n        return REDIS_ERR;\n    }\n    return REDIS_OK;\n}\n\nint redisGetReply(redisContext *c, void **reply) {\n    int wdone = 0;\n    void *aux = NULL;\n\n    /* Try to read pending replies */\n    if (redisGetReplyFromReader(c,&aux) == REDIS_ERR)\n        return REDIS_ERR;\n\n    /* For the blocking context, flush output buffer and read reply */\n    if (aux == NULL && c->flags & REDIS_BLOCK) {\n        /* Write until done */\n        do {\n            if (redisBufferWrite(c,&wdone) == REDIS_ERR)\n                return REDIS_ERR;\n        } while (!wdone);\n\n        /* Read until there is a reply */\n        do {\n            if (redisBufferRead(c) == REDIS_ERR)\n                return REDIS_ERR;\n            if (redisGetReplyFromReader(c,&aux) == REDIS_ERR)\n                return REDIS_ERR;\n        } while (aux == NULL);\n    }\n\n    /* Set reply object */\n    if (reply != NULL) *reply = aux;\n    return REDIS_OK;\n}\n\n\n/* Helper function for the redisAppendCommand* family of functions.\n *\n * Write a formatted command to the output buffer. When this family\n * is used, you need to call redisGetReply yourself to retrieve\n * the reply (or replies in pub/sub).\n */\nint __redisAppendCommand(redisContext *c, const char *cmd, size_t len) {\n    sds newbuf;\n\n    newbuf = sdscatlen(c->obuf,cmd,len);\n    if (newbuf == NULL) {\n        __redisSetError(c,REDIS_ERR_OOM,\"Out of memory\");\n        return REDIS_ERR;\n    }\n\n    c->obuf = newbuf;\n    return REDIS_OK;\n}\n\nint redisAppendFormattedCommand(redisContext *c, const char *cmd, size_t len) {\n\n    if (__redisAppendCommand(c, cmd, len) != REDIS_OK) {\n        return REDIS_ERR;\n    }\n\n    return REDIS_OK;\n}\n\nint redisvAppendCommand(redisContext *c, const char *format, va_list ap) {\n    char *cmd;\n    int len;\n\n    len = redisvFormatCommand(&cmd,format,ap);\n    if (len == -1) {\n        __redisSetError(c,REDIS_ERR_OOM,\"Out of memory\");\n        return REDIS_ERR;\n    }\n\n    if (__redisAppendCommand(c,cmd,len) != REDIS_OK) {\n        free(cmd);\n        return REDIS_ERR;\n    }\n\n    free(cmd);\n    return REDIS_OK;\n}\n\nint redisAppendCommand(redisContext *c, const char *format, ...) {\n    va_list ap;\n    int ret;\n\n    va_start(ap,format);\n    ret = redisvAppendCommand(c,format,ap);\n    va_end(ap);\n    return ret;\n}\n\nint redisAppendCommandArgv(redisContext *c, int argc, const char **argv, const size_t *argvlen) {\n    char *cmd;\n    int len;\n\n    len = redisFormatCommandArgv(&cmd,argc,argv,argvlen);\n    if (len == -1) {\n        __redisSetError(c,REDIS_ERR_OOM,\"Out of memory\");\n        return REDIS_ERR;\n    }\n\n    if (__redisAppendCommand(c,cmd,len) != REDIS_OK) {\n        free(cmd);\n        return REDIS_ERR;\n    }\n\n    free(cmd);\n    return REDIS_OK;\n}\n\n/* Helper function for the redisCommand* family of functions.\n *\n * Write a formatted command to the output buffer. If the given context is\n * blocking, immediately read the reply into the \"reply\" pointer. When the\n * context is non-blocking, the \"reply\" pointer will not be used and the\n * command is simply appended to the write buffer.\n *\n * Returns the reply when a reply was succesfully retrieved. Returns NULL\n * otherwise. When NULL is returned in a blocking context, the error field\n * in the context will be set.\n */\nstatic void *__redisBlockForReply(redisContext *c) {\n    void *reply;\n\n    if (c->flags & REDIS_BLOCK) {\n        if (redisGetReply(c,&reply) != REDIS_OK)\n            return NULL;\n        return reply;\n    }\n    return NULL;\n}\n\nvoid *redisvCommand(redisContext *c, const char *format, va_list ap) {\n    if (redisvAppendCommand(c,format,ap) != REDIS_OK)\n        return NULL;\n    return __redisBlockForReply(c);\n}\n\nvoid *redisCommand(redisContext *c, const char *format, ...) {\n    va_list ap;\n    void *reply = NULL;\n    va_start(ap,format);\n    reply = redisvCommand(c,format,ap);\n    va_end(ap);\n    return reply;\n}\n\nvoid *redisCommandArgv(redisContext *c, int argc, const char **argv, const size_t *argvlen) {\n    if (redisAppendCommandArgv(c,argc,argv,argvlen) != REDIS_OK)\n        return NULL;\n    return __redisBlockForReply(c);\n}\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/deps/hiredis/hiredis.h",
    "content": "/*\n * Copyright (c) 2009-2011, Salvatore Sanfilippo <antirez at gmail dot com>\n * Copyright (c) 2010-2011, Pieter Noordhuis <pcnoordhuis at gmail dot com>\n *\n * All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions are met:\n *\n *   * Redistributions of source code must retain the above copyright notice,\n *     this list of conditions and the following disclaimer.\n *   * Redistributions in binary form must reproduce the above copyright\n *     notice, this list of conditions and the following disclaimer in the\n *     documentation and/or other materials provided with the distribution.\n *   * Neither the name of Redis nor the names of its contributors may be used\n *     to endorse or promote products derived from this software without\n *     specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\"\n * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\n * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE\n * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR\n * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF\n * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS\n * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN\n * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)\n * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE\n * POSSIBILITY OF SUCH DAMAGE.\n */\n\n#ifndef __HIREDIS_H\n#define __HIREDIS_H\n#include <stdio.h> /* for size_t */\n#include <stdarg.h> /* for va_list */\n#include <sys/time.h> /* for struct timeval */\n\n#define HIREDIS_MAJOR 0\n#define HIREDIS_MINOR 11\n#define HIREDIS_PATCH 0\n\n#define REDIS_ERR -1\n#define REDIS_OK 0\n\n/* When an error occurs, the err flag in a context is set to hold the type of\n * error that occured. REDIS_ERR_IO means there was an I/O error and you\n * should use the \"errno\" variable to find out what is wrong.\n * For other values, the \"errstr\" field will hold a description. */\n#define REDIS_ERR_IO 1 /* Error in read or write */\n#define REDIS_ERR_EOF 3 /* End of file */\n#define REDIS_ERR_PROTOCOL 4 /* Protocol error */\n#define REDIS_ERR_OOM 5 /* Out of memory */\n#define REDIS_ERR_OTHER 2 /* Everything else... */\n\n/* Connection type can be blocking or non-blocking and is set in the\n * least significant bit of the flags field in redisContext. */\n#define REDIS_BLOCK 0x1\n\n/* Connection may be disconnected before being free'd. The second bit\n * in the flags field is set when the context is connected. */\n#define REDIS_CONNECTED 0x2\n\n/* The async API might try to disconnect cleanly and flush the output\n * buffer and read all subsequent replies before disconnecting.\n * This flag means no new commands can come in and the connection\n * should be terminated once all replies have been read. */\n#define REDIS_DISCONNECTING 0x4\n\n/* Flag specific to the async API which means that the context should be clean\n * up as soon as possible. */\n#define REDIS_FREEING 0x8\n\n/* Flag that is set when an async callback is executed. */\n#define REDIS_IN_CALLBACK 0x10\n\n/* Flag that is set when the async context has one or more subscriptions. */\n#define REDIS_SUBSCRIBED 0x20\n\n/* Flag that is set when monitor mode is active */\n#define REDIS_MONITORING 0x40\n\n#define REDIS_REPLY_STRING 1\n#define REDIS_REPLY_ARRAY 2\n#define REDIS_REPLY_INTEGER 3\n#define REDIS_REPLY_NIL 4\n#define REDIS_REPLY_STATUS 5\n#define REDIS_REPLY_ERROR 6\n\n#define REDIS_READER_MAX_BUF (1024*16)  /* Default max unused reader buffer. */\n\n#define REDIS_KEEPALIVE_INTERVAL 15 /* seconds */\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n/* This is the reply object returned by redisCommand() */\ntypedef struct redisReply {\n    int type; /* REDIS_REPLY_* */\n    long long integer; /* The integer when type is REDIS_REPLY_INTEGER */\n    int len; /* Length of string */\n    char *str; /* Used for both REDIS_REPLY_ERROR and REDIS_REPLY_STRING */\n    size_t elements; /* number of elements, for REDIS_REPLY_ARRAY */\n    struct redisReply **element; /* elements vector for REDIS_REPLY_ARRAY */\n} redisReply;\n\ntypedef struct redisReadTask {\n    int type;\n    int elements; /* number of elements in multibulk container */\n    int idx; /* index in parent (array) object */\n    void *obj; /* holds user-generated value for a read task */\n    struct redisReadTask *parent; /* parent task */\n    void *privdata; /* user-settable arbitrary field */\n} redisReadTask;\n\ntypedef struct redisReplyObjectFunctions {\n    void *(*createString)(const redisReadTask*, char*, size_t);\n    void *(*createArray)(const redisReadTask*, int);\n    void *(*createInteger)(const redisReadTask*, long long);\n    void *(*createNil)(const redisReadTask*);\n    void (*freeObject)(void*);\n} redisReplyObjectFunctions;\n\n/* State for the protocol parser */\ntypedef struct redisReader {\n    int err; /* Error flags, 0 when there is no error */\n    char errstr[128]; /* String representation of error when applicable */\n\n    char *buf; /* Read buffer */\n    size_t pos; /* Buffer cursor */\n    size_t len; /* Buffer length */\n    size_t maxbuf; /* Max length of unused buffer */\n\n    redisReadTask rstack[9];\n    int ridx; /* Index of current read task */\n    void *reply; /* Temporary reply pointer */\n\n    redisReplyObjectFunctions *fn;\n    void *privdata;\n} redisReader;\n\n/* Public API for the protocol parser. */\nredisReader *redisReaderCreate(void);\nvoid redisReaderFree(redisReader *r);\nint redisReaderFeed(redisReader *r, const char *buf, size_t len);\nint redisReaderGetReply(redisReader *r, void **reply);\n\n/* Backwards compatibility, can be removed on big version bump. */\n#define redisReplyReaderCreate redisReaderCreate\n#define redisReplyReaderFree redisReaderFree\n#define redisReplyReaderFeed redisReaderFeed\n#define redisReplyReaderGetReply redisReaderGetReply\n#define redisReplyReaderSetPrivdata(_r, _p) (int)(((redisReader*)(_r))->privdata = (_p))\n#define redisReplyReaderGetObject(_r) (((redisReader*)(_r))->reply)\n#define redisReplyReaderGetError(_r) (((redisReader*)(_r))->errstr)\n\n/* Function to free the reply objects hiredis returns by default. */\nvoid freeReplyObject(void *reply);\n\n/* Functions to format a command according to the protocol. */\nint redisvFormatCommand(char **target, const char *format, va_list ap);\nint redisFormatCommand(char **target, const char *format, ...);\nint redisFormatCommandArgv(char **target, int argc, const char **argv, const size_t *argvlen);\n\n/* Context for a connection to Redis */\ntypedef struct redisContext {\n    int err; /* Error flags, 0 when there is no error */\n    char errstr[128]; /* String representation of error when applicable */\n    int fd;\n    int flags;\n    char *obuf; /* Write buffer */\n    redisReader *reader; /* Protocol reader */\n} redisContext;\n\nredisContext *redisConnect(const char *ip, int port);\nredisContext *redisConnectWithTimeout(const char *ip, int port, const struct timeval tv);\nredisContext *redisConnectNonBlock(const char *ip, int port);\nredisContext *redisConnectBindNonBlock(const char *ip, int port, const char *source_addr);\nredisContext *redisConnectUnix(const char *path);\nredisContext *redisConnectUnixWithTimeout(const char *path, const struct timeval tv);\nredisContext *redisConnectUnixNonBlock(const char *path);\nredisContext *redisConnectFd(int fd);\nint redisSetTimeout(redisContext *c, const struct timeval tv);\nint redisEnableKeepAlive(redisContext *c);\nvoid redisFree(redisContext *c);\nint redisFreeKeepFd(redisContext *c);\nint redisBufferRead(redisContext *c);\nint redisBufferWrite(redisContext *c, int *done);\n\n/* In a blocking context, this function first checks if there are unconsumed\n * replies to return and returns one if so. Otherwise, it flushes the output\n * buffer to the socket and reads until it has a reply. In a non-blocking\n * context, it will return unconsumed replies until there are no more. */\nint redisGetReply(redisContext *c, void **reply);\nint redisGetReplyFromReader(redisContext *c, void **reply);\n\n/* Write a formatted command to the output buffer. Use these functions in blocking mode\n * to get a pipeline of commands. */\nint redisAppendFormattedCommand(redisContext *c, const char *cmd, size_t len);\n\n/* Write a command to the output buffer. Use these functions in blocking mode\n * to get a pipeline of commands. */\nint redisvAppendCommand(redisContext *c, const char *format, va_list ap);\nint redisAppendCommand(redisContext *c, const char *format, ...);\nint redisAppendCommandArgv(redisContext *c, int argc, const char **argv, const size_t *argvlen);\n\n/* Issue a command to Redis. In a blocking context, it is identical to calling\n * redisAppendCommand, followed by redisGetReply. The function will return\n * NULL if there was an error in performing the request, otherwise it will\n * return the reply. In a non-blocking context, it is identical to calling\n * only redisAppendCommand and will always return NULL. */\nvoid *redisvCommand(redisContext *c, const char *format, va_list ap);\nvoid *redisCommand(redisContext *c, const char *format, ...);\nvoid *redisCommandArgv(redisContext *c, int argc, const char **argv, const size_t *argvlen);\n\n#ifdef __cplusplus\n}\n#endif\n\n#endif\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/deps/hiredis/net.c",
    "content": "/* Extracted from anet.c to work properly with Hiredis error reporting.\n *\n * Copyright (c) 2006-2011, Salvatore Sanfilippo <antirez at gmail dot com>\n * Copyright (c) 2010-2011, Pieter Noordhuis <pcnoordhuis at gmail dot com>\n *\n * All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions are met:\n *\n *   * Redistributions of source code must retain the above copyright notice,\n *     this list of conditions and the following disclaimer.\n *   * Redistributions in binary form must reproduce the above copyright\n *     notice, this list of conditions and the following disclaimer in the\n *     documentation and/or other materials provided with the distribution.\n *   * Neither the name of Redis nor the names of its contributors may be used\n *     to endorse or promote products derived from this software without\n *     specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\"\n * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\n * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE\n * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR\n * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF\n * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS\n * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN\n * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)\n * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE\n * POSSIBILITY OF SUCH DAMAGE.\n */\n\n#include \"fmacros.h\"\n#include <sys/types.h>\n#include <sys/socket.h>\n#include <sys/select.h>\n#include <sys/un.h>\n#include <netinet/in.h>\n#include <netinet/tcp.h>\n#include <arpa/inet.h>\n#include <unistd.h>\n#include <fcntl.h>\n#include <string.h>\n#include <netdb.h>\n#include <errno.h>\n#include <stdarg.h>\n#include <stdio.h>\n#include <poll.h>\n#include <limits.h>\n\n#include \"net.h\"\n#include \"sds.h\"\n\n/* Defined in hiredis.c */\nvoid __redisSetError(redisContext *c, int type, const char *str);\n\nstatic void redisContextCloseFd(redisContext *c) {\n    if (c && c->fd >= 0) {\n        close(c->fd);\n        c->fd = -1;\n    }\n}\n\nstatic void __redisSetErrorFromErrno(redisContext *c, int type, const char *prefix) {\n    char buf[128] = { 0 };\n    size_t len = 0;\n\n    if (prefix != NULL)\n        len = snprintf(buf,sizeof(buf),\"%s: \",prefix);\n    strerror_r(errno,buf+len,sizeof(buf)-len);\n    __redisSetError(c,type,buf);\n}\n\nstatic int redisSetReuseAddr(redisContext *c) {\n    int on = 1;\n    if (setsockopt(c->fd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)) == -1) {\n        __redisSetErrorFromErrno(c,REDIS_ERR_IO,NULL);\n        redisContextCloseFd(c);\n        return REDIS_ERR;\n    }\n    return REDIS_OK;\n}\n\nstatic int redisCreateSocket(redisContext *c, int type) {\n    int s;\n    if ((s = socket(type, SOCK_STREAM, 0)) == -1) {\n        __redisSetErrorFromErrno(c,REDIS_ERR_IO,NULL);\n        return REDIS_ERR;\n    }\n    c->fd = s;\n    if (type == AF_INET) {\n        if (redisSetReuseAddr(c) == REDIS_ERR) {\n            return REDIS_ERR;\n        }\n    }\n    return REDIS_OK;\n}\n\nstatic int redisSetBlocking(redisContext *c, int blocking) {\n    int flags;\n\n    /* Set the socket nonblocking.\n     * Note that fcntl(2) for F_GETFL and F_SETFL can't be\n     * interrupted by a signal. */\n    if ((flags = fcntl(c->fd, F_GETFL)) == -1) {\n        __redisSetErrorFromErrno(c,REDIS_ERR_IO,\"fcntl(F_GETFL)\");\n        redisContextCloseFd(c);\n        return REDIS_ERR;\n    }\n\n    if (blocking)\n        flags &= ~O_NONBLOCK;\n    else\n        flags |= O_NONBLOCK;\n\n    if (fcntl(c->fd, F_SETFL, flags) == -1) {\n        __redisSetErrorFromErrno(c,REDIS_ERR_IO,\"fcntl(F_SETFL)\");\n        redisContextCloseFd(c);\n        return REDIS_ERR;\n    }\n    return REDIS_OK;\n}\n\nint redisKeepAlive(redisContext *c, int interval) {\n    int val = 1;\n    int fd = c->fd;\n\n    if (setsockopt(fd, SOL_SOCKET, SO_KEEPALIVE, &val, sizeof(val)) == -1){\n        __redisSetError(c,REDIS_ERR_OTHER,strerror(errno));\n        return REDIS_ERR;\n    }\n\n    val = interval;\n\n#ifdef _OSX\n    if (setsockopt(fd, IPPROTO_TCP, TCP_KEEPALIVE, &val, sizeof(val)) < 0) {\n        __redisSetError(c,REDIS_ERR_OTHER,strerror(errno));\n        return REDIS_ERR;\n    }\n#else\n#ifndef __sun\n    val = interval;\n    if (setsockopt(fd, IPPROTO_TCP, TCP_KEEPIDLE, &val, sizeof(val)) < 0) {\n        __redisSetError(c,REDIS_ERR_OTHER,strerror(errno));\n        return REDIS_ERR;\n    }\n\n    val = interval/3;\n    if (val == 0) val = 1;\n    if (setsockopt(fd, IPPROTO_TCP, TCP_KEEPINTVL, &val, sizeof(val)) < 0) {\n        __redisSetError(c,REDIS_ERR_OTHER,strerror(errno));\n        return REDIS_ERR;\n    }\n\n    val = 3;\n    if (setsockopt(fd, IPPROTO_TCP, TCP_KEEPCNT, &val, sizeof(val)) < 0) {\n        __redisSetError(c,REDIS_ERR_OTHER,strerror(errno));\n        return REDIS_ERR;\n    }\n#endif\n#endif\n\n    return REDIS_OK;\n}\n\nstatic int redisSetTcpNoDelay(redisContext *c) {\n    int yes = 1;\n    if (setsockopt(c->fd, IPPROTO_TCP, TCP_NODELAY, &yes, sizeof(yes)) == -1) {\n        __redisSetErrorFromErrno(c,REDIS_ERR_IO,\"setsockopt(TCP_NODELAY)\");\n        redisContextCloseFd(c);\n        return REDIS_ERR;\n    }\n    return REDIS_OK;\n}\n\n#define __MAX_MSEC (((LONG_MAX) - 999) / 1000)\n\nstatic int redisContextWaitReady(redisContext *c, const struct timeval *timeout) {\n    struct pollfd   wfd[1];\n    long msec;\n\n    msec          = -1;\n    wfd[0].fd     = c->fd;\n    wfd[0].events = POLLOUT;\n\n    /* Only use timeout when not NULL. */\n    if (timeout != NULL) {\n        if (timeout->tv_usec > 1000000 || timeout->tv_sec > __MAX_MSEC) {\n            __redisSetErrorFromErrno(c, REDIS_ERR_IO, NULL);\n            redisContextCloseFd(c);\n            return REDIS_ERR;\n        }\n\n        msec = (timeout->tv_sec * 1000) + ((timeout->tv_usec + 999) / 1000);\n\n        if (msec < 0 || msec > INT_MAX) {\n            msec = INT_MAX;\n        }\n    }\n\n    if (errno == EINPROGRESS) {\n        int res;\n\n        if ((res = poll(wfd, 1, msec)) == -1) {\n            __redisSetErrorFromErrno(c, REDIS_ERR_IO, \"poll(2)\");\n            redisContextCloseFd(c);\n            return REDIS_ERR;\n        } else if (res == 0) {\n            errno = ETIMEDOUT;\n            __redisSetErrorFromErrno(c,REDIS_ERR_IO,NULL);\n            redisContextCloseFd(c);\n            return REDIS_ERR;\n        }\n\n        if (redisCheckSocketError(c) != REDIS_OK)\n            return REDIS_ERR;\n\n        return REDIS_OK;\n    }\n\n    __redisSetErrorFromErrno(c,REDIS_ERR_IO,NULL);\n    redisContextCloseFd(c);\n    return REDIS_ERR;\n}\n\nint redisCheckSocketError(redisContext *c) {\n    int err = 0;\n    socklen_t errlen = sizeof(err);\n\n    if (getsockopt(c->fd, SOL_SOCKET, SO_ERROR, &err, &errlen) == -1) {\n        __redisSetErrorFromErrno(c,REDIS_ERR_IO,\"getsockopt(SO_ERROR)\");\n        return REDIS_ERR;\n    }\n\n    if (err) {\n        errno = err;\n        __redisSetErrorFromErrno(c,REDIS_ERR_IO,NULL);\n        return REDIS_ERR;\n    }\n\n    return REDIS_OK;\n}\n\nint redisContextSetTimeout(redisContext *c, const struct timeval tv) {\n    if (setsockopt(c->fd,SOL_SOCKET,SO_RCVTIMEO,&tv,sizeof(tv)) == -1) {\n        __redisSetErrorFromErrno(c,REDIS_ERR_IO,\"setsockopt(SO_RCVTIMEO)\");\n        return REDIS_ERR;\n    }\n    if (setsockopt(c->fd,SOL_SOCKET,SO_SNDTIMEO,&tv,sizeof(tv)) == -1) {\n        __redisSetErrorFromErrno(c,REDIS_ERR_IO,\"setsockopt(SO_SNDTIMEO)\");\n        return REDIS_ERR;\n    }\n    return REDIS_OK;\n}\n\nstatic int _redisContextConnectTcp(redisContext *c, const char *addr, int port,\n                                   const struct timeval *timeout,\n                                   const char *source_addr) {\n    int s, rv;\n    char _port[6];  /* strlen(\"65535\"); */\n    struct addrinfo hints, *servinfo, *bservinfo, *p, *b;\n    int blocking = (c->flags & REDIS_BLOCK);\n\n    snprintf(_port, 6, \"%d\", port);\n    memset(&hints,0,sizeof(hints));\n    hints.ai_family = AF_INET;\n    hints.ai_socktype = SOCK_STREAM;\n\n    /* Try with IPv6 if no IPv4 address was found. We do it in this order since\n     * in a Redis client you can't afford to test if you have IPv6 connectivity\n     * as this would add latency to every connect. Otherwise a more sensible\n     * route could be: Use IPv6 if both addresses are available and there is IPv6\n     * connectivity. */\n    if ((rv = getaddrinfo(addr,_port,&hints,&servinfo)) != 0) {\n         hints.ai_family = AF_INET6;\n         if ((rv = getaddrinfo(addr,_port,&hints,&servinfo)) != 0) {\n            __redisSetError(c,REDIS_ERR_OTHER,gai_strerror(rv));\n            return REDIS_ERR;\n        }\n    }\n    for (p = servinfo; p != NULL; p = p->ai_next) {\n        if ((s = socket(p->ai_family,p->ai_socktype,p->ai_protocol)) == -1)\n            continue;\n\n        c->fd = s;\n        if (redisSetBlocking(c,0) != REDIS_OK)\n            goto error;\n        if (source_addr) {\n            int bound = 0;\n            /* Using getaddrinfo saves us from self-determining IPv4 vs IPv6 */\n            if ((rv = getaddrinfo(source_addr, NULL, &hints, &bservinfo)) != 0) {\n                char buf[128];\n                snprintf(buf,sizeof(buf),\"Can't get addr: %s\",gai_strerror(rv));\n                __redisSetError(c,REDIS_ERR_OTHER,buf);\n                goto error;\n            }\n            for (b = bservinfo; b != NULL; b = b->ai_next) {\n                if (bind(s,b->ai_addr,b->ai_addrlen) != -1) {\n                    bound = 1;\n                    break;\n                }\n            }\n            freeaddrinfo(bservinfo);\n            if (!bound) {\n                char buf[128];\n                snprintf(buf,sizeof(buf),\"Can't bind socket: %s\",strerror(errno));\n                __redisSetError(c,REDIS_ERR_OTHER,buf);\n                goto error;\n            }\n        }\n        if (connect(s,p->ai_addr,p->ai_addrlen) == -1) {\n            if (errno == EHOSTUNREACH) {\n                redisContextCloseFd(c);\n                continue;\n            } else if (errno == EINPROGRESS && !blocking) {\n                /* This is ok. */\n            } else {\n                if (redisContextWaitReady(c,timeout) != REDIS_OK)\n                    goto error;\n            }\n        }\n        if (blocking && redisSetBlocking(c,1) != REDIS_OK)\n            goto error;\n        if (redisSetTcpNoDelay(c) != REDIS_OK)\n            goto error;\n\n        c->flags |= REDIS_CONNECTED;\n        rv = REDIS_OK;\n        goto end;\n    }\n    if (p == NULL) {\n        char buf[128];\n        snprintf(buf,sizeof(buf),\"Can't create socket: %s\",strerror(errno));\n        __redisSetError(c,REDIS_ERR_OTHER,buf);\n        goto error;\n    }\n\nerror:\n    rv = REDIS_ERR;\nend:\n    freeaddrinfo(servinfo);\n    return rv;  // Need to return REDIS_OK if alright\n}\n\nint redisContextConnectTcp(redisContext *c, const char *addr, int port,\n                           const struct timeval *timeout) {\n    return _redisContextConnectTcp(c, addr, port, timeout, NULL);\n}\n\nint redisContextConnectBindTcp(redisContext *c, const char *addr, int port,\n                               const struct timeval *timeout,\n                               const char *source_addr) {\n    return _redisContextConnectTcp(c, addr, port, timeout, source_addr);\n}\n\nint redisContextConnectUnix(redisContext *c, const char *path, const struct timeval *timeout) {\n    int blocking = (c->flags & REDIS_BLOCK);\n    struct sockaddr_un sa;\n\n    if (redisCreateSocket(c,AF_LOCAL) < 0)\n        return REDIS_ERR;\n    if (redisSetBlocking(c,0) != REDIS_OK)\n        return REDIS_ERR;\n\n    sa.sun_family = AF_LOCAL;\n    strncpy(sa.sun_path,path,sizeof(sa.sun_path)-1);\n    if (connect(c->fd, (struct sockaddr*)&sa, sizeof(sa)) == -1) {\n        if (errno == EINPROGRESS && !blocking) {\n            /* This is ok. */\n        } else {\n            if (redisContextWaitReady(c,timeout) != REDIS_OK)\n                return REDIS_ERR;\n        }\n    }\n\n    /* Reset socket to be blocking after connect(2). */\n    if (blocking && redisSetBlocking(c,1) != REDIS_OK)\n        return REDIS_ERR;\n\n    c->flags |= REDIS_CONNECTED;\n    return REDIS_OK;\n}\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/deps/hiredis/net.h",
    "content": "/* Extracted from anet.c to work properly with Hiredis error reporting.\n *\n * Copyright (c) 2006-2011, Salvatore Sanfilippo <antirez at gmail dot com>\n * Copyright (c) 2010-2011, Pieter Noordhuis <pcnoordhuis at gmail dot com>\n *\n * All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions are met:\n *\n *   * Redistributions of source code must retain the above copyright notice,\n *     this list of conditions and the following disclaimer.\n *   * Redistributions in binary form must reproduce the above copyright\n *     notice, this list of conditions and the following disclaimer in the\n *     documentation and/or other materials provided with the distribution.\n *   * Neither the name of Redis nor the names of its contributors may be used\n *     to endorse or promote products derived from this software without\n *     specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\"\n * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\n * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE\n * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR\n * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF\n * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS\n * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN\n * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)\n * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE\n * POSSIBILITY OF SUCH DAMAGE.\n */\n\n#ifndef __NET_H\n#define __NET_H\n\n#include \"hiredis.h\"\n\n#if defined(__sun) || defined(_AIX)\n#define AF_LOCAL AF_UNIX\n#endif\n\nint redisCheckSocketError(redisContext *c);\nint redisContextSetTimeout(redisContext *c, const struct timeval tv);\nint redisContextConnectTcp(redisContext *c, const char *addr, int port, const struct timeval *timeout);\nint redisContextConnectBindTcp(redisContext *c, const char *addr, int port,\n                               const struct timeval *timeout,\n                               const char *source_addr);\nint redisContextConnectUnix(redisContext *c, const char *path, const struct timeval *timeout);\nint redisKeepAlive(redisContext *c, int interval);\n\n#endif\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/deps/hiredis/sds.c",
    "content": "/* SDSLib 2.0 -- A C dynamic strings library\n *\n * Copyright (c) 2006-2015, Salvatore Sanfilippo <antirez at gmail dot com>\n * Copyright (c) 2015, Oran Agra\n * Copyright (c) 2015, Redis Labs, Inc\n * All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions are met:\n *\n *   * Redistributions of source code must retain the above copyright notice,\n *     this list of conditions and the following disclaimer.\n *   * Redistributions in binary form must reproduce the above copyright\n *     notice, this list of conditions and the following disclaimer in the\n *     documentation and/or other materials provided with the distribution.\n *   * Neither the name of Redis nor the names of its contributors may be used\n *     to endorse or promote products derived from this software without\n *     specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\"\n * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\n * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE\n * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR\n * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF\n * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS\n * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN\n * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)\n * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE\n * POSSIBILITY OF SUCH DAMAGE.\n */\n\n#include <stdio.h>\n#include <stdlib.h>\n#include <string.h>\n#include <ctype.h>\n#include <assert.h>\n#include \"sds.h\"\n#include \"sdsalloc.h\"\n\nstatic inline int sdsHdrSize(char type) {\n    switch(type&SDS_TYPE_MASK) {\n        case SDS_TYPE_5:\n            return sizeof(struct sdshdr5);\n        case SDS_TYPE_8:\n            return sizeof(struct sdshdr8);\n        case SDS_TYPE_16:\n            return sizeof(struct sdshdr16);\n        case SDS_TYPE_32:\n            return sizeof(struct sdshdr32);\n        case SDS_TYPE_64:\n            return sizeof(struct sdshdr64);\n    }\n    return 0;\n}\n\nstatic inline char sdsReqType(size_t string_size) {\n    if (string_size < 32)\n        return SDS_TYPE_5;\n    if (string_size < 0xff)\n        return SDS_TYPE_8;\n    if (string_size < 0xffff)\n        return SDS_TYPE_16;\n    if (string_size < 0xffffffff)\n        return SDS_TYPE_32;\n    return SDS_TYPE_64;\n}\n\n/* Create a new sds string with the content specified by the 'init' pointer\n * and 'initlen'.\n * If NULL is used for 'init' the string is initialized with zero bytes.\n *\n * The string is always null-termined (all the sds strings are, always) so\n * even if you create an sds string with:\n *\n * mystring = sdsnewlen(\"abc\",3);\n *\n * You can print the string with printf() as there is an implicit \\0 at the\n * end of the string. However the string is binary safe and can contain\n * \\0 characters in the middle, as the length is stored in the sds header. */\nsds sdsnewlen(const void *init, size_t initlen) {\n    void *sh;\n    sds s;\n    char type = sdsReqType(initlen);\n    /* Empty strings are usually created in order to append. Use type 8\n     * since type 5 is not good at this. */\n    if (type == SDS_TYPE_5 && initlen == 0) type = SDS_TYPE_8;\n    int hdrlen = sdsHdrSize(type);\n    unsigned char *fp; /* flags pointer. */\n\n    sh = s_malloc(hdrlen+initlen+1);\n    if (!init)\n        memset(sh, 0, hdrlen+initlen+1);\n    if (sh == NULL) return NULL;\n    s = (char*)sh+hdrlen;\n    fp = ((unsigned char*)s)-1;\n    switch(type) {\n        case SDS_TYPE_5: {\n            *fp = type | (initlen << SDS_TYPE_BITS);\n            break;\n        }\n        case SDS_TYPE_8: {\n            SDS_HDR_VAR(8,s);\n            sh->len = initlen;\n            sh->alloc = initlen;\n            *fp = type;\n            break;\n        }\n        case SDS_TYPE_16: {\n            SDS_HDR_VAR(16,s);\n            sh->len = initlen;\n            sh->alloc = initlen;\n            *fp = type;\n            break;\n        }\n        case SDS_TYPE_32: {\n            SDS_HDR_VAR(32,s);\n            sh->len = initlen;\n            sh->alloc = initlen;\n            *fp = type;\n            break;\n        }\n        case SDS_TYPE_64: {\n            SDS_HDR_VAR(64,s);\n            sh->len = initlen;\n            sh->alloc = initlen;\n            *fp = type;\n            break;\n        }\n    }\n    if (initlen && init)\n        memcpy(s, init, initlen);\n    s[initlen] = '\\0';\n    return s;\n}\n\n/* Create an empty (zero length) sds string. Even in this case the string\n * always has an implicit null term. */\nsds sdsempty(void) {\n    return sdsnewlen(\"\",0);\n}\n\n/* Create a new sds string starting from a null terminated C string. */\nsds sdsnew(const char *init) {\n    size_t initlen = (init == NULL) ? 0 : strlen(init);\n    return sdsnewlen(init, initlen);\n}\n\n/* Duplicate an sds string. */\nsds sdsdup(const sds s) {\n    return sdsnewlen(s, sdslen(s));\n}\n\n/* Free an sds string. No operation is performed if 's' is NULL. */\nvoid sdsfree(sds s) {\n    if (s == NULL) return;\n    s_free((char*)s-sdsHdrSize(s[-1]));\n}\n\n/* Set the sds string length to the length as obtained with strlen(), so\n * considering as content only up to the first null term character.\n *\n * This function is useful when the sds string is hacked manually in some\n * way, like in the following example:\n *\n * s = sdsnew(\"foobar\");\n * s[2] = '\\0';\n * sdsupdatelen(s);\n * printf(\"%d\\n\", sdslen(s));\n *\n * The output will be \"2\", but if we comment out the call to sdsupdatelen()\n * the output will be \"6\" as the string was modified but the logical length\n * remains 6 bytes. */\nvoid sdsupdatelen(sds s) {\n    int reallen = strlen(s);\n    sdssetlen(s, reallen);\n}\n\n/* Modify an sds string in-place to make it empty (zero length).\n * However all the existing buffer is not discarded but set as free space\n * so that next append operations will not require allocations up to the\n * number of bytes previously available. */\nvoid sdsclear(sds s) {\n    sdssetlen(s, 0);\n    s[0] = '\\0';\n}\n\n/* Enlarge the free space at the end of the sds string so that the caller\n * is sure that after calling this function can overwrite up to addlen\n * bytes after the end of the string, plus one more byte for nul term.\n *\n * Note: this does not change the *length* of the sds string as returned\n * by sdslen(), but only the free buffer space we have. */\nsds sdsMakeRoomFor(sds s, size_t addlen) {\n    void *sh, *newsh;\n    size_t avail = sdsavail(s);\n    size_t len, newlen;\n    char type, oldtype = s[-1] & SDS_TYPE_MASK;\n    int hdrlen;\n\n    /* Return ASAP if there is enough space left. */\n    if (avail >= addlen) return s;\n\n    len = sdslen(s);\n    sh = (char*)s-sdsHdrSize(oldtype);\n    newlen = (len+addlen);\n    if (newlen < SDS_MAX_PREALLOC)\n        newlen *= 2;\n    else\n        newlen += SDS_MAX_PREALLOC;\n\n    type = sdsReqType(newlen);\n\n    /* Don't use type 5: the user is appending to the string and type 5 is\n     * not able to remember empty space, so sdsMakeRoomFor() must be called\n     * at every appending operation. */\n    if (type == SDS_TYPE_5) type = SDS_TYPE_8;\n\n    hdrlen = sdsHdrSize(type);\n    if (oldtype==type) {\n        newsh = s_realloc(sh, hdrlen+newlen+1);\n        if (newsh == NULL) return NULL;\n        s = (char*)newsh+hdrlen;\n    } else {\n        /* Since the header size changes, need to move the string forward,\n         * and can't use realloc */\n        newsh = s_malloc(hdrlen+newlen+1);\n        if (newsh == NULL) return NULL;\n        memcpy((char*)newsh+hdrlen, s, len+1);\n        s_free(sh);\n        s = (char*)newsh+hdrlen;\n        s[-1] = type;\n        sdssetlen(s, len);\n    }\n    sdssetalloc(s, newlen);\n    return s;\n}\n\n/* Reallocate the sds string so that it has no free space at the end. The\n * contained string remains not altered, but next concatenation operations\n * will require a reallocation.\n *\n * After the call, the passed sds string is no longer valid and all the\n * references must be substituted with the new pointer returned by the call. */\nsds sdsRemoveFreeSpace(sds s) {\n    void *sh, *newsh;\n    char type, oldtype = s[-1] & SDS_TYPE_MASK;\n    int hdrlen;\n    size_t len = sdslen(s);\n    sh = (char*)s-sdsHdrSize(oldtype);\n\n    type = sdsReqType(len);\n    hdrlen = sdsHdrSize(type);\n    if (oldtype==type) {\n        newsh = s_realloc(sh, hdrlen+len+1);\n        if (newsh == NULL) return NULL;\n        s = (char*)newsh+hdrlen;\n    } else {\n        newsh = s_malloc(hdrlen+len+1);\n        if (newsh == NULL) return NULL;\n        memcpy((char*)newsh+hdrlen, s, len+1);\n        s_free(sh);\n        s = (char*)newsh+hdrlen;\n        s[-1] = type;\n        sdssetlen(s, len);\n    }\n    sdssetalloc(s, len);\n    return s;\n}\n\n/* Return the total size of the allocation of the specifed sds string,\n * including:\n * 1) The sds header before the pointer.\n * 2) The string.\n * 3) The free buffer at the end if any.\n * 4) The implicit null term.\n */\nsize_t sdsAllocSize(sds s) {\n    size_t alloc = sdsalloc(s);\n    return sdsHdrSize(s[-1])+alloc+1;\n}\n\n/* Return the pointer of the actual SDS allocation (normally SDS strings\n * are referenced by the start of the string buffer). */\nvoid *sdsAllocPtr(sds s) {\n    return (void*) (s-sdsHdrSize(s[-1]));\n}\n\n/* Increment the sds length and decrements the left free space at the\n * end of the string according to 'incr'. Also set the null term\n * in the new end of the string.\n *\n * This function is used in order to fix the string length after the\n * user calls sdsMakeRoomFor(), writes something after the end of\n * the current string, and finally needs to set the new length.\n *\n * Note: it is possible to use a negative increment in order to\n * right-trim the string.\n *\n * Usage example:\n *\n * Using sdsIncrLen() and sdsMakeRoomFor() it is possible to mount the\n * following schema, to cat bytes coming from the kernel to the end of an\n * sds string without copying into an intermediate buffer:\n *\n * oldlen = sdslen(s);\n * s = sdsMakeRoomFor(s, BUFFER_SIZE);\n * nread = read(fd, s+oldlen, BUFFER_SIZE);\n * ... check for nread <= 0 and handle it ...\n * sdsIncrLen(s, nread);\n */\nvoid sdsIncrLen(sds s, int incr) {\n    unsigned char flags = s[-1];\n    size_t len;\n    switch(flags&SDS_TYPE_MASK) {\n        case SDS_TYPE_5: {\n            unsigned char *fp = ((unsigned char*)s)-1;\n            unsigned char oldlen = SDS_TYPE_5_LEN(flags);\n            assert((incr > 0 && oldlen+incr < 32) || (incr < 0 && oldlen >= (unsigned int)(-incr)));\n            *fp = SDS_TYPE_5 | ((oldlen+incr) << SDS_TYPE_BITS);\n            len = oldlen+incr;\n            break;\n        }\n        case SDS_TYPE_8: {\n            SDS_HDR_VAR(8,s);\n            assert((incr >= 0 && sh->alloc-sh->len >= incr) || (incr < 0 && sh->len >= (unsigned int)(-incr)));\n            len = (sh->len += incr);\n            break;\n        }\n        case SDS_TYPE_16: {\n            SDS_HDR_VAR(16,s);\n            assert((incr >= 0 && sh->alloc-sh->len >= incr) || (incr < 0 && sh->len >= (unsigned int)(-incr)));\n            len = (sh->len += incr);\n            break;\n        }\n        case SDS_TYPE_32: {\n            SDS_HDR_VAR(32,s);\n            assert((incr >= 0 && sh->alloc-sh->len >= (unsigned int)incr) || (incr < 0 && sh->len >= (unsigned int)(-incr)));\n            len = (sh->len += incr);\n            break;\n        }\n        case SDS_TYPE_64: {\n            SDS_HDR_VAR(64,s);\n            assert((incr >= 0 && sh->alloc-sh->len >= (uint64_t)incr) || (incr < 0 && sh->len >= (uint64_t)(-incr)));\n            len = (sh->len += incr);\n            break;\n        }\n        default: len = 0; /* Just to avoid compilation warnings. */\n    }\n    s[len] = '\\0';\n}\n\n/* Grow the sds to have the specified length. Bytes that were not part of\n * the original length of the sds will be set to zero.\n *\n * if the specified length is smaller than the current length, no operation\n * is performed. */\nsds sdsgrowzero(sds s, size_t len) {\n    size_t curlen = sdslen(s);\n\n    if (len <= curlen) return s;\n    s = sdsMakeRoomFor(s,len-curlen);\n    if (s == NULL) return NULL;\n\n    /* Make sure added region doesn't contain garbage */\n    memset(s+curlen,0,(len-curlen+1)); /* also set trailing \\0 byte */\n    sdssetlen(s, len);\n    return s;\n}\n\n/* Append the specified binary-safe string pointed by 't' of 'len' bytes to the\n * end of the specified sds string 's'.\n *\n * After the call, the passed sds string is no longer valid and all the\n * references must be substituted with the new pointer returned by the call. */\nsds sdscatlen(sds s, const void *t, size_t len) {\n    size_t curlen = sdslen(s);\n\n    s = sdsMakeRoomFor(s,len);\n    if (s == NULL) return NULL;\n    memcpy(s+curlen, t, len);\n    sdssetlen(s, curlen+len);\n    s[curlen+len] = '\\0';\n    return s;\n}\n\n/* Append the specified null termianted C string to the sds string 's'.\n *\n * After the call, the passed sds string is no longer valid and all the\n * references must be substituted with the new pointer returned by the call. */\nsds sdscat(sds s, const char *t) {\n    return sdscatlen(s, t, strlen(t));\n}\n\n/* Append the specified sds 't' to the existing sds 's'.\n *\n * After the call, the modified sds string is no longer valid and all the\n * references must be substituted with the new pointer returned by the call. */\nsds sdscatsds(sds s, const sds t) {\n    return sdscatlen(s, t, sdslen(t));\n}\n\n/* Destructively modify the sds string 's' to hold the specified binary\n * safe string pointed by 't' of length 'len' bytes. */\nsds sdscpylen(sds s, const char *t, size_t len) {\n    if (sdsalloc(s) < len) {\n        s = sdsMakeRoomFor(s,len-sdslen(s));\n        if (s == NULL) return NULL;\n    }\n    memcpy(s, t, len);\n    s[len] = '\\0';\n    sdssetlen(s, len);\n    return s;\n}\n\n/* Like sdscpylen() but 't' must be a null-termined string so that the length\n * of the string is obtained with strlen(). */\nsds sdscpy(sds s, const char *t) {\n    return sdscpylen(s, t, strlen(t));\n}\n\n/* Helper for sdscatlonglong() doing the actual number -> string\n * conversion. 's' must point to a string with room for at least\n * SDS_LLSTR_SIZE bytes.\n *\n * The function returns the length of the null-terminated string\n * representation stored at 's'. */\n#define SDS_LLSTR_SIZE 21\nint sdsll2str(char *s, long long value) {\n    char *p, aux;\n    unsigned long long v;\n    size_t l;\n\n    /* Generate the string representation, this method produces\n     * an reversed string. */\n    v = (value < 0) ? -value : value;\n    p = s;\n    do {\n        *p++ = '0'+(v%10);\n        v /= 10;\n    } while(v);\n    if (value < 0) *p++ = '-';\n\n    /* Compute length and add null term. */\n    l = p-s;\n    *p = '\\0';\n\n    /* Reverse the string. */\n    p--;\n    while(s < p) {\n        aux = *s;\n        *s = *p;\n        *p = aux;\n        s++;\n        p--;\n    }\n    return l;\n}\n\n/* Identical sdsll2str(), but for unsigned long long type. */\nint sdsull2str(char *s, unsigned long long v) {\n    char *p, aux;\n    size_t l;\n\n    /* Generate the string representation, this method produces\n     * an reversed string. */\n    p = s;\n    do {\n        *p++ = '0'+(v%10);\n        v /= 10;\n    } while(v);\n\n    /* Compute length and add null term. */\n    l = p-s;\n    *p = '\\0';\n\n    /* Reverse the string. */\n    p--;\n    while(s < p) {\n        aux = *s;\n        *s = *p;\n        *p = aux;\n        s++;\n        p--;\n    }\n    return l;\n}\n\n/* Create an sds string from a long long value. It is much faster than:\n *\n * sdscatprintf(sdsempty(),\"%lld\\n\", value);\n */\nsds sdsfromlonglong(long long value) {\n    char buf[SDS_LLSTR_SIZE];\n    int len = sdsll2str(buf,value);\n\n    return sdsnewlen(buf,len);\n}\n\n/* Like sdscatprintf() but gets va_list instead of being variadic. */\nsds sdscatvprintf(sds s, const char *fmt, va_list ap) {\n    va_list cpy;\n    char staticbuf[1024], *buf = staticbuf, *t;\n    size_t buflen = strlen(fmt)*2;\n\n    /* We try to start using a static buffer for speed.\n     * If not possible we revert to heap allocation. */\n    if (buflen > sizeof(staticbuf)) {\n        buf = s_malloc(buflen);\n        if (buf == NULL) return NULL;\n    } else {\n        buflen = sizeof(staticbuf);\n    }\n\n    /* Try with buffers two times bigger every time we fail to\n     * fit the string in the current buffer size. */\n    while(1) {\n        buf[buflen-2] = '\\0';\n        va_copy(cpy,ap);\n        vsnprintf(buf, buflen, fmt, cpy);\n        va_end(cpy);\n        if (buf[buflen-2] != '\\0') {\n            if (buf != staticbuf) s_free(buf);\n            buflen *= 2;\n            buf = s_malloc(buflen);\n            if (buf == NULL) return NULL;\n            continue;\n        }\n        break;\n    }\n\n    /* Finally concat the obtained string to the SDS string and return it. */\n    t = sdscat(s, buf);\n    if (buf != staticbuf) s_free(buf);\n    return t;\n}\n\n/* Append to the sds string 's' a string obtained using printf-alike format\n * specifier.\n *\n * After the call, the modified sds string is no longer valid and all the\n * references must be substituted with the new pointer returned by the call.\n *\n * Example:\n *\n * s = sdsnew(\"Sum is: \");\n * s = sdscatprintf(s,\"%d+%d = %d\",a,b,a+b).\n *\n * Often you need to create a string from scratch with the printf-alike\n * format. When this is the need, just use sdsempty() as the target string:\n *\n * s = sdscatprintf(sdsempty(), \"... your format ...\", args);\n */\nsds sdscatprintf(sds s, const char *fmt, ...) {\n    va_list ap;\n    char *t;\n    va_start(ap, fmt);\n    t = sdscatvprintf(s,fmt,ap);\n    va_end(ap);\n    return t;\n}\n\n/* This function is similar to sdscatprintf, but much faster as it does\n * not rely on sprintf() family functions implemented by the libc that\n * are often very slow. Moreover directly handling the sds string as\n * new data is concatenated provides a performance improvement.\n *\n * However this function only handles an incompatible subset of printf-alike\n * format specifiers:\n *\n * %s - C String\n * %S - SDS string\n * %i - signed int\n * %I - 64 bit signed integer (long long, int64_t)\n * %u - unsigned int\n * %U - 64 bit unsigned integer (unsigned long long, uint64_t)\n * %% - Verbatim \"%\" character.\n */\nsds sdscatfmt(sds s, char const *fmt, ...) {\n    size_t initlen = sdslen(s);\n    const char *f = fmt;\n    int i;\n    va_list ap;\n\n    va_start(ap,fmt);\n    f = fmt;    /* Next format specifier byte to process. */\n    i = initlen; /* Position of the next byte to write to dest str. */\n    while(*f) {\n        char next, *str;\n        size_t l;\n        long long num;\n        unsigned long long unum;\n\n        /* Make sure there is always space for at least 1 char. */\n        if (sdsavail(s)==0) {\n            s = sdsMakeRoomFor(s,1);\n        }\n\n        switch(*f) {\n        case '%':\n            next = *(f+1);\n            f++;\n            switch(next) {\n            case 's':\n            case 'S':\n                str = va_arg(ap,char*);\n                l = (next == 's') ? strlen(str) : sdslen(str);\n                if (sdsavail(s) < l) {\n                    s = sdsMakeRoomFor(s,l);\n                }\n                memcpy(s+i,str,l);\n                sdsinclen(s,l);\n                i += l;\n                break;\n            case 'i':\n            case 'I':\n                if (next == 'i')\n                    num = va_arg(ap,int);\n                else\n                    num = va_arg(ap,long long);\n                {\n                    char buf[SDS_LLSTR_SIZE];\n                    l = sdsll2str(buf,num);\n                    if (sdsavail(s) < l) {\n                        s = sdsMakeRoomFor(s,l);\n                    }\n                    memcpy(s+i,buf,l);\n                    sdsinclen(s,l);\n                    i += l;\n                }\n                break;\n            case 'u':\n            case 'U':\n                if (next == 'u')\n                    unum = va_arg(ap,unsigned int);\n                else\n                    unum = va_arg(ap,unsigned long long);\n                {\n                    char buf[SDS_LLSTR_SIZE];\n                    l = sdsull2str(buf,unum);\n                    if (sdsavail(s) < l) {\n                        s = sdsMakeRoomFor(s,l);\n                    }\n                    memcpy(s+i,buf,l);\n                    sdsinclen(s,l);\n                    i += l;\n                }\n                break;\n            default: /* Handle %% and generally %<unknown>. */\n                s[i++] = next;\n                sdsinclen(s,1);\n                break;\n            }\n            break;\n        default:\n            s[i++] = *f;\n            sdsinclen(s,1);\n            break;\n        }\n        f++;\n    }\n    va_end(ap);\n\n    /* Add null-term */\n    s[i] = '\\0';\n    return s;\n}\n\n/* Remove the part of the string from left and from right composed just of\n * contiguous characters found in 'cset', that is a null terminted C string.\n *\n * After the call, the modified sds string is no longer valid and all the\n * references must be substituted with the new pointer returned by the call.\n *\n * Example:\n *\n * s = sdsnew(\"AA...AA.a.aa.aHelloWorld     :::\");\n * s = sdstrim(s,\"Aa. :\");\n * printf(\"%s\\n\", s);\n *\n * Output will be just \"Hello World\".\n */\nsds sdstrim(sds s, const char *cset) {\n    char *start, *end, *sp, *ep;\n    size_t len;\n\n    sp = start = s;\n    ep = end = s+sdslen(s)-1;\n    while(sp <= end && strchr(cset, *sp)) sp++;\n    while(ep > sp && strchr(cset, *ep)) ep--;\n    len = (sp > ep) ? 0 : ((ep-sp)+1);\n    if (s != sp) memmove(s, sp, len);\n    s[len] = '\\0';\n    sdssetlen(s,len);\n    return s;\n}\n\n/* Turn the string into a smaller (or equal) string containing only the\n * substring specified by the 'start' and 'end' indexes.\n *\n * start and end can be negative, where -1 means the last character of the\n * string, -2 the penultimate character, and so forth.\n *\n * The interval is inclusive, so the start and end characters will be part\n * of the resulting string.\n *\n * The string is modified in-place.\n *\n * Example:\n *\n * s = sdsnew(\"Hello World\");\n * sdsrange(s,1,-1); => \"ello World\"\n */\nvoid sdsrange(sds s, int start, int end) {\n    size_t newlen, len = sdslen(s);\n\n    if (len == 0) return;\n    if (start < 0) {\n        start = len+start;\n        if (start < 0) start = 0;\n    }\n    if (end < 0) {\n        end = len+end;\n        if (end < 0) end = 0;\n    }\n    newlen = (start > end) ? 0 : (end-start)+1;\n    if (newlen != 0) {\n        if (start >= (signed)len) {\n            newlen = 0;\n        } else if (end >= (signed)len) {\n            end = len-1;\n            newlen = (start > end) ? 0 : (end-start)+1;\n        }\n    } else {\n        start = 0;\n    }\n    if (start && newlen) memmove(s, s+start, newlen);\n    s[newlen] = 0;\n    sdssetlen(s,newlen);\n}\n\n/* Apply tolower() to every character of the sds string 's'. */\nvoid sdstolower(sds s) {\n    int len = sdslen(s), j;\n\n    for (j = 0; j < len; j++) s[j] = tolower(s[j]);\n}\n\n/* Apply toupper() to every character of the sds string 's'. */\nvoid sdstoupper(sds s) {\n    int len = sdslen(s), j;\n\n    for (j = 0; j < len; j++) s[j] = toupper(s[j]);\n}\n\n/* Compare two sds strings s1 and s2 with memcmp().\n *\n * Return value:\n *\n *     positive if s1 > s2.\n *     negative if s1 < s2.\n *     0 if s1 and s2 are exactly the same binary string.\n *\n * If two strings share exactly the same prefix, but one of the two has\n * additional characters, the longer string is considered to be greater than\n * the smaller one. */\nint sdscmp(const sds s1, const sds s2) {\n    size_t l1, l2, minlen;\n    int cmp;\n\n    l1 = sdslen(s1);\n    l2 = sdslen(s2);\n    minlen = (l1 < l2) ? l1 : l2;\n    cmp = memcmp(s1,s2,minlen);\n    if (cmp == 0) return l1-l2;\n    return cmp;\n}\n\n/* Split 's' with separator in 'sep'. An array\n * of sds strings is returned. *count will be set\n * by reference to the number of tokens returned.\n *\n * On out of memory, zero length string, zero length\n * separator, NULL is returned.\n *\n * Note that 'sep' is able to split a string using\n * a multi-character separator. For example\n * sdssplit(\"foo_-_bar\",\"_-_\"); will return two\n * elements \"foo\" and \"bar\".\n *\n * This version of the function is binary-safe but\n * requires length arguments. sdssplit() is just the\n * same function but for zero-terminated strings.\n */\nsds *sdssplitlen(const char *s, int len, const char *sep, int seplen, int *count) {\n    int elements = 0, slots = 5, start = 0, j;\n    sds *tokens;\n\n    if (seplen < 1 || len < 0) return NULL;\n\n    tokens = s_malloc(sizeof(sds)*slots);\n    if (tokens == NULL) return NULL;\n\n    if (len == 0) {\n        *count = 0;\n        return tokens;\n    }\n    for (j = 0; j < (len-(seplen-1)); j++) {\n        /* make sure there is room for the next element and the final one */\n        if (slots < elements+2) {\n            sds *newtokens;\n\n            slots *= 2;\n            newtokens = s_realloc(tokens,sizeof(sds)*slots);\n            if (newtokens == NULL) goto cleanup;\n            tokens = newtokens;\n        }\n        /* search the separator */\n        if ((seplen == 1 && *(s+j) == sep[0]) || (memcmp(s+j,sep,seplen) == 0)) {\n            tokens[elements] = sdsnewlen(s+start,j-start);\n            if (tokens[elements] == NULL) goto cleanup;\n            elements++;\n            start = j+seplen;\n            j = j+seplen-1; /* skip the separator */\n        }\n    }\n    /* Add the final element. We are sure there is room in the tokens array. */\n    tokens[elements] = sdsnewlen(s+start,len-start);\n    if (tokens[elements] == NULL) goto cleanup;\n    elements++;\n    *count = elements;\n    return tokens;\n\ncleanup:\n    {\n        int i;\n        for (i = 0; i < elements; i++) sdsfree(tokens[i]);\n        s_free(tokens);\n        *count = 0;\n        return NULL;\n    }\n}\n\n/* Free the result returned by sdssplitlen(), or do nothing if 'tokens' is NULL. */\nvoid sdsfreesplitres(sds *tokens, int count) {\n    if (!tokens) return;\n    while(count--)\n        sdsfree(tokens[count]);\n    s_free(tokens);\n}\n\n/* Append to the sds string \"s\" an escaped string representation where\n * all the non-printable characters (tested with isprint()) are turned into\n * escapes in the form \"\\n\\r\\a....\" or \"\\x<hex-number>\".\n *\n * After the call, the modified sds string is no longer valid and all the\n * references must be substituted with the new pointer returned by the call. */\nsds sdscatrepr(sds s, const char *p, size_t len) {\n    s = sdscatlen(s,\"\\\"\",1);\n    while(len--) {\n        switch(*p) {\n        case '\\\\':\n        case '\"':\n            s = sdscatprintf(s,\"\\\\%c\",*p);\n            break;\n        case '\\n': s = sdscatlen(s,\"\\\\n\",2); break;\n        case '\\r': s = sdscatlen(s,\"\\\\r\",2); break;\n        case '\\t': s = sdscatlen(s,\"\\\\t\",2); break;\n        case '\\a': s = sdscatlen(s,\"\\\\a\",2); break;\n        case '\\b': s = sdscatlen(s,\"\\\\b\",2); break;\n        default:\n            if (isprint(*p))\n                s = sdscatprintf(s,\"%c\",*p);\n            else\n                s = sdscatprintf(s,\"\\\\x%02x\",(unsigned char)*p);\n            break;\n        }\n        p++;\n    }\n    return sdscatlen(s,\"\\\"\",1);\n}\n\n/* Helper function for sdssplitargs() that returns non zero if 'c'\n * is a valid hex digit. */\nint is_hex_digit(char c) {\n    return (c >= '0' && c <= '9') || (c >= 'a' && c <= 'f') ||\n           (c >= 'A' && c <= 'F');\n}\n\n/* Helper function for sdssplitargs() that converts a hex digit into an\n * integer from 0 to 15 */\nint hex_digit_to_int(char c) {\n    switch(c) {\n    case '0': return 0;\n    case '1': return 1;\n    case '2': return 2;\n    case '3': return 3;\n    case '4': return 4;\n    case '5': return 5;\n    case '6': return 6;\n    case '7': return 7;\n    case '8': return 8;\n    case '9': return 9;\n    case 'a': case 'A': return 10;\n    case 'b': case 'B': return 11;\n    case 'c': case 'C': return 12;\n    case 'd': case 'D': return 13;\n    case 'e': case 'E': return 14;\n    case 'f': case 'F': return 15;\n    default: return 0;\n    }\n}\n\n/* Split a line into arguments, where every argument can be in the\n * following programming-language REPL-alike form:\n *\n * foo bar \"newline are supported\\n\" and \"\\xff\\x00otherstuff\"\n *\n * The number of arguments is stored into *argc, and an array\n * of sds is returned.\n *\n * The caller should free the resulting array of sds strings with\n * sdsfreesplitres().\n *\n * Note that sdscatrepr() is able to convert back a string into\n * a quoted string in the same format sdssplitargs() is able to parse.\n *\n * The function returns the allocated tokens on success, even when the\n * input string is empty, or NULL if the input contains unbalanced\n * quotes or closed quotes followed by non space characters\n * as in: \"foo\"bar or \"foo'\n */\nsds *sdssplitargs(const char *line, int *argc) {\n    const char *p = line;\n    char *current = NULL;\n    char **vector = NULL;\n\n    *argc = 0;\n    while(1) {\n        /* skip blanks */\n        while(*p && isspace(*p)) p++;\n        if (*p) {\n            /* get a token */\n            int inq=0;  /* set to 1 if we are in \"quotes\" */\n            int insq=0; /* set to 1 if we are in 'single quotes' */\n            int done=0;\n\n            if (current == NULL) current = sdsempty();\n            while(!done) {\n                if (inq) {\n                    if (*p == '\\\\' && *(p+1) == 'x' &&\n                                             is_hex_digit(*(p+2)) &&\n                                             is_hex_digit(*(p+3)))\n                    {\n                        unsigned char byte;\n\n                        byte = (hex_digit_to_int(*(p+2))*16)+\n                                hex_digit_to_int(*(p+3));\n                        current = sdscatlen(current,(char*)&byte,1);\n                        p += 3;\n                    } else if (*p == '\\\\' && *(p+1)) {\n                        char c;\n\n                        p++;\n                        switch(*p) {\n                        case 'n': c = '\\n'; break;\n                        case 'r': c = '\\r'; break;\n                        case 't': c = '\\t'; break;\n                        case 'b': c = '\\b'; break;\n                        case 'a': c = '\\a'; break;\n                        default: c = *p; break;\n                        }\n                        current = sdscatlen(current,&c,1);\n                    } else if (*p == '\"') {\n                        /* closing quote must be followed by a space or\n                         * nothing at all. */\n                        if (*(p+1) && !isspace(*(p+1))) goto err;\n                        done=1;\n                    } else if (!*p) {\n                        /* unterminated quotes */\n                        goto err;\n                    } else {\n                        current = sdscatlen(current,p,1);\n                    }\n                } else if (insq) {\n                    if (*p == '\\\\' && *(p+1) == '\\'') {\n                        p++;\n                        current = sdscatlen(current,\"'\",1);\n                    } else if (*p == '\\'') {\n                        /* closing quote must be followed by a space or\n                         * nothing at all. */\n                        if (*(p+1) && !isspace(*(p+1))) goto err;\n                        done=1;\n                    } else if (!*p) {\n                        /* unterminated quotes */\n                        goto err;\n                    } else {\n                        current = sdscatlen(current,p,1);\n                    }\n                } else {\n                    switch(*p) {\n                    case ' ':\n                    case '\\n':\n                    case '\\r':\n                    case '\\t':\n                    case '\\0':\n                        done=1;\n                        break;\n                    case '\"':\n                        inq=1;\n                        break;\n                    case '\\'':\n                        insq=1;\n                        break;\n                    default:\n                        current = sdscatlen(current,p,1);\n                        break;\n                    }\n                }\n                if (*p) p++;\n            }\n            /* add the token to the vector */\n            vector = s_realloc(vector,((*argc)+1)*sizeof(char*));\n            vector[*argc] = current;\n            (*argc)++;\n            current = NULL;\n        } else {\n            /* Even on empty input string return something not NULL. */\n            if (vector == NULL) vector = s_malloc(sizeof(void*));\n            return vector;\n        }\n    }\n\nerr:\n    while((*argc)--)\n        sdsfree(vector[*argc]);\n    s_free(vector);\n    if (current) sdsfree(current);\n    *argc = 0;\n    return NULL;\n}\n\n/* Modify the string substituting all the occurrences of the set of\n * characters specified in the 'from' string to the corresponding character\n * in the 'to' array.\n *\n * For instance: sdsmapchars(mystring, \"ho\", \"01\", 2)\n * will have the effect of turning the string \"hello\" into \"0ell1\".\n *\n * The function returns the sds string pointer, that is always the same\n * as the input pointer since no resize is needed. */\nsds sdsmapchars(sds s, const char *from, const char *to, size_t setlen) {\n    size_t j, i, l = sdslen(s);\n\n    for (j = 0; j < l; j++) {\n        for (i = 0; i < setlen; i++) {\n            if (s[j] == from[i]) {\n                s[j] = to[i];\n                break;\n            }\n        }\n    }\n    return s;\n}\n\n/* Join an array of C strings using the specified separator (also a C string).\n * Returns the result as an sds string. */\nsds sdsjoin(char **argv, int argc, char *sep) {\n    sds join = sdsempty();\n    int j;\n\n    for (j = 0; j < argc; j++) {\n        join = sdscat(join, argv[j]);\n        if (j != argc-1) join = sdscat(join,sep);\n    }\n    return join;\n}\n\n/* Like sdsjoin, but joins an array of SDS strings. */\nsds sdsjoinsds(sds *argv, int argc, const char *sep, size_t seplen) {\n    sds join = sdsempty();\n    int j;\n\n    for (j = 0; j < argc; j++) {\n        join = sdscatsds(join, argv[j]);\n        if (j != argc-1) join = sdscatlen(join,sep,seplen);\n    }\n    return join;\n}\n\n/* Wrappers to the allocators used by SDS. Note that SDS will actually\n * just use the macros defined into sdsalloc.h in order to avoid to pay\n * the overhead of function calls. Here we define these wrappers only for\n * the programs SDS is linked to, if they want to touch the SDS internals\n * even if they use a different allocator. */\nvoid *sds_malloc(size_t size) { return s_malloc(size); }\nvoid *sds_realloc(void *ptr, size_t size) { return s_realloc(ptr,size); }\nvoid sds_free(void *ptr) { s_free(ptr); }\n\n#if defined(SDS_TEST_MAIN)\n#include <stdio.h>\n#include \"testhelp.h\"\n#include \"limits.h\"\n\n#define UNUSED(x) (void)(x)\nint sdsTest(void) {\n    {\n        sds x = sdsnew(\"foo\"), y;\n\n        test_cond(\"Create a string and obtain the length\",\n            sdslen(x) == 3 && memcmp(x,\"foo\\0\",4) == 0)\n\n        sdsfree(x);\n        x = sdsnewlen(\"foo\",2);\n        test_cond(\"Create a string with specified length\",\n            sdslen(x) == 2 && memcmp(x,\"fo\\0\",3) == 0)\n\n        x = sdscat(x,\"bar\");\n        test_cond(\"Strings concatenation\",\n            sdslen(x) == 5 && memcmp(x,\"fobar\\0\",6) == 0);\n\n        x = sdscpy(x,\"a\");\n        test_cond(\"sdscpy() against an originally longer string\",\n            sdslen(x) == 1 && memcmp(x,\"a\\0\",2) == 0)\n\n        x = sdscpy(x,\"xyzxxxxxxxxxxyyyyyyyyyykkkkkkkkkk\");\n        test_cond(\"sdscpy() against an originally shorter string\",\n            sdslen(x) == 33 &&\n            memcmp(x,\"xyzxxxxxxxxxxyyyyyyyyyykkkkkkkkkk\\0\",33) == 0)\n\n        sdsfree(x);\n        x = sdscatprintf(sdsempty(),\"%d\",123);\n        test_cond(\"sdscatprintf() seems working in the base case\",\n            sdslen(x) == 3 && memcmp(x,\"123\\0\",4) == 0)\n\n        sdsfree(x);\n        x = sdsnew(\"--\");\n        x = sdscatfmt(x, \"Hello %s World %I,%I--\", \"Hi!\", LLONG_MIN,LLONG_MAX);\n        test_cond(\"sdscatfmt() seems working in the base case\",\n            sdslen(x) == 60 &&\n            memcmp(x,\"--Hello Hi! World -9223372036854775808,\"\n                     \"9223372036854775807--\",60) == 0)\n        printf(\"[%s]\\n\",x);\n\n        sdsfree(x);\n        x = sdsnew(\"--\");\n        x = sdscatfmt(x, \"%u,%U--\", UINT_MAX, ULLONG_MAX);\n        test_cond(\"sdscatfmt() seems working with unsigned numbers\",\n            sdslen(x) == 35 &&\n            memcmp(x,\"--4294967295,18446744073709551615--\",35) == 0)\n\n        sdsfree(x);\n        x = sdsnew(\" x \");\n        sdstrim(x,\" x\");\n        test_cond(\"sdstrim() works when all chars match\",\n            sdslen(x) == 0)\n\n        sdsfree(x);\n        x = sdsnew(\" x \");\n        sdstrim(x,\" \");\n        test_cond(\"sdstrim() works when a single char remains\",\n            sdslen(x) == 1 && x[0] == 'x')\n\n        sdsfree(x);\n        x = sdsnew(\"xxciaoyyy\");\n        sdstrim(x,\"xy\");\n        test_cond(\"sdstrim() correctly trims characters\",\n            sdslen(x) == 4 && memcmp(x,\"ciao\\0\",5) == 0)\n\n        y = sdsdup(x);\n        sdsrange(y,1,1);\n        test_cond(\"sdsrange(...,1,1)\",\n            sdslen(y) == 1 && memcmp(y,\"i\\0\",2) == 0)\n\n        sdsfree(y);\n        y = sdsdup(x);\n        sdsrange(y,1,-1);\n        test_cond(\"sdsrange(...,1,-1)\",\n            sdslen(y) == 3 && memcmp(y,\"iao\\0\",4) == 0)\n\n        sdsfree(y);\n        y = sdsdup(x);\n        sdsrange(y,-2,-1);\n        test_cond(\"sdsrange(...,-2,-1)\",\n            sdslen(y) == 2 && memcmp(y,\"ao\\0\",3) == 0)\n\n        sdsfree(y);\n        y = sdsdup(x);\n        sdsrange(y,2,1);\n        test_cond(\"sdsrange(...,2,1)\",\n            sdslen(y) == 0 && memcmp(y,\"\\0\",1) == 0)\n\n        sdsfree(y);\n        y = sdsdup(x);\n        sdsrange(y,1,100);\n        test_cond(\"sdsrange(...,1,100)\",\n            sdslen(y) == 3 && memcmp(y,\"iao\\0\",4) == 0)\n\n        sdsfree(y);\n        y = sdsdup(x);\n        sdsrange(y,100,100);\n        test_cond(\"sdsrange(...,100,100)\",\n            sdslen(y) == 0 && memcmp(y,\"\\0\",1) == 0)\n\n        sdsfree(y);\n        sdsfree(x);\n        x = sdsnew(\"foo\");\n        y = sdsnew(\"foa\");\n        test_cond(\"sdscmp(foo,foa)\", sdscmp(x,y) > 0)\n\n        sdsfree(y);\n        sdsfree(x);\n        x = sdsnew(\"bar\");\n        y = sdsnew(\"bar\");\n        test_cond(\"sdscmp(bar,bar)\", sdscmp(x,y) == 0)\n\n        sdsfree(y);\n        sdsfree(x);\n        x = sdsnew(\"aar\");\n        y = sdsnew(\"bar\");\n        test_cond(\"sdscmp(bar,bar)\", sdscmp(x,y) < 0)\n\n        sdsfree(y);\n        sdsfree(x);\n        x = sdsnewlen(\"\\a\\n\\0foo\\r\",7);\n        y = sdscatrepr(sdsempty(),x,sdslen(x));\n        test_cond(\"sdscatrepr(...data...)\",\n            memcmp(y,\"\\\"\\\\a\\\\n\\\\x00foo\\\\r\\\"\",15) == 0)\n\n        {\n            unsigned int oldfree;\n            char *p;\n            int step = 10, j, i;\n\n            sdsfree(x);\n            sdsfree(y);\n            x = sdsnew(\"0\");\n            test_cond(\"sdsnew() free/len buffers\", sdslen(x) == 1 && sdsavail(x) == 0);\n\n            /* Run the test a few times in order to hit the first two\n             * SDS header types. */\n            for (i = 0; i < 10; i++) {\n                int oldlen = sdslen(x);\n                x = sdsMakeRoomFor(x,step);\n                int type = x[-1]&SDS_TYPE_MASK;\n\n                test_cond(\"sdsMakeRoomFor() len\", sdslen(x) == oldlen);\n                if (type != SDS_TYPE_5) {\n                    test_cond(\"sdsMakeRoomFor() free\", sdsavail(x) >= step);\n                    oldfree = sdsavail(x);\n                }\n                p = x+oldlen;\n                for (j = 0; j < step; j++) {\n                    p[j] = 'A'+j;\n                }\n                sdsIncrLen(x,step);\n            }\n            test_cond(\"sdsMakeRoomFor() content\",\n                memcmp(\"0ABCDEFGHIJABCDEFGHIJABCDEFGHIJABCDEFGHIJABCDEFGHIJABCDEFGHIJABCDEFGHIJABCDEFGHIJABCDEFGHIJABCDEFGHIJ\",x,101) == 0);\n            test_cond(\"sdsMakeRoomFor() final length\",sdslen(x)==101);\n\n            sdsfree(x);\n        }\n    }\n    test_report()\n    return 0;\n}\n#endif\n\n#ifdef SDS_TEST_MAIN\nint main(void) {\n    return sdsTest();\n}\n#endif\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/deps/hiredis/sds.h",
    "content": "/* SDSLib 2.0 -- A C dynamic strings library\n *\n * Copyright (c) 2006-2015, Salvatore Sanfilippo <antirez at gmail dot com>\n * Copyright (c) 2015, Oran Agra\n * Copyright (c) 2015, Redis Labs, Inc\n * All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions are met:\n *\n *   * Redistributions of source code must retain the above copyright notice,\n *     this list of conditions and the following disclaimer.\n *   * Redistributions in binary form must reproduce the above copyright\n *     notice, this list of conditions and the following disclaimer in the\n *     documentation and/or other materials provided with the distribution.\n *   * Neither the name of Redis nor the names of its contributors may be used\n *     to endorse or promote products derived from this software without\n *     specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\"\n * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\n * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE\n * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR\n * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF\n * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS\n * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN\n * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)\n * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE\n * POSSIBILITY OF SUCH DAMAGE.\n */\n\n#ifndef __SDS_H\n#define __SDS_H\n\n#define SDS_MAX_PREALLOC (1024*1024)\n\n#include <sys/types.h>\n#include <stdarg.h>\n#include <stdint.h>\n\ntypedef char *sds;\n\n/* Note: sdshdr5 is never used, we just access the flags byte directly.\n * However is here to document the layout of type 5 SDS strings. */\nstruct __attribute__ ((__packed__)) sdshdr5 {\n    unsigned char flags; /* 3 lsb of type, and 5 msb of string length */\n    char buf[];\n};\nstruct __attribute__ ((__packed__)) sdshdr8 {\n    uint8_t len; /* used */\n    uint8_t alloc; /* excluding the header and null terminator */\n    unsigned char flags; /* 3 lsb of type, 5 unused bits */\n    char buf[];\n};\nstruct __attribute__ ((__packed__)) sdshdr16 {\n    uint16_t len; /* used */\n    uint16_t alloc; /* excluding the header and null terminator */\n    unsigned char flags; /* 3 lsb of type, 5 unused bits */\n    char buf[];\n};\nstruct __attribute__ ((__packed__)) sdshdr32 {\n    uint32_t len; /* used */\n    uint32_t alloc; /* excluding the header and null terminator */\n    unsigned char flags; /* 3 lsb of type, 5 unused bits */\n    char buf[];\n};\nstruct __attribute__ ((__packed__)) sdshdr64 {\n    uint64_t len; /* used */\n    uint64_t alloc; /* excluding the header and null terminator */\n    unsigned char flags; /* 3 lsb of type, 5 unused bits */\n    char buf[];\n};\n\n#define SDS_TYPE_5  0\n#define SDS_TYPE_8  1\n#define SDS_TYPE_16 2\n#define SDS_TYPE_32 3\n#define SDS_TYPE_64 4\n#define SDS_TYPE_MASK 7\n#define SDS_TYPE_BITS 3\n#define SDS_HDR_VAR(T,s) struct sdshdr##T *sh = (void*)((s)-(sizeof(struct sdshdr##T)));\n#define SDS_HDR(T,s) ((struct sdshdr##T *)((s)-(sizeof(struct sdshdr##T))))\n#define SDS_TYPE_5_LEN(f) ((f)>>SDS_TYPE_BITS)\n\nstatic inline size_t sdslen(const sds s) {\n    unsigned char flags = s[-1];\n    switch(flags&SDS_TYPE_MASK) {\n        case SDS_TYPE_5:\n            return SDS_TYPE_5_LEN(flags);\n        case SDS_TYPE_8:\n            return SDS_HDR(8,s)->len;\n        case SDS_TYPE_16:\n            return SDS_HDR(16,s)->len;\n        case SDS_TYPE_32:\n            return SDS_HDR(32,s)->len;\n        case SDS_TYPE_64:\n            return SDS_HDR(64,s)->len;\n    }\n    return 0;\n}\n\nstatic inline size_t sdsavail(const sds s) {\n    unsigned char flags = s[-1];\n    switch(flags&SDS_TYPE_MASK) {\n        case SDS_TYPE_5: {\n            return 0;\n        }\n        case SDS_TYPE_8: {\n            SDS_HDR_VAR(8,s);\n            return sh->alloc - sh->len;\n        }\n        case SDS_TYPE_16: {\n            SDS_HDR_VAR(16,s);\n            return sh->alloc - sh->len;\n        }\n        case SDS_TYPE_32: {\n            SDS_HDR_VAR(32,s);\n            return sh->alloc - sh->len;\n        }\n        case SDS_TYPE_64: {\n            SDS_HDR_VAR(64,s);\n            return sh->alloc - sh->len;\n        }\n    }\n    return 0;\n}\n\nstatic inline void sdssetlen(sds s, size_t newlen) {\n    unsigned char flags = s[-1];\n    switch(flags&SDS_TYPE_MASK) {\n        case SDS_TYPE_5:\n            {\n                unsigned char *fp = ((unsigned char*)s)-1;\n                *fp = SDS_TYPE_5 | (newlen << SDS_TYPE_BITS);\n            }\n            break;\n        case SDS_TYPE_8:\n            SDS_HDR(8,s)->len = newlen;\n            break;\n        case SDS_TYPE_16:\n            SDS_HDR(16,s)->len = newlen;\n            break;\n        case SDS_TYPE_32:\n            SDS_HDR(32,s)->len = newlen;\n            break;\n        case SDS_TYPE_64:\n            SDS_HDR(64,s)->len = newlen;\n            break;\n    }\n}\n\nstatic inline void sdsinclen(sds s, size_t inc) {\n    unsigned char flags = s[-1];\n    switch(flags&SDS_TYPE_MASK) {\n        case SDS_TYPE_5:\n            {\n                unsigned char *fp = ((unsigned char*)s)-1;\n                unsigned char newlen = SDS_TYPE_5_LEN(flags)+inc;\n                *fp = SDS_TYPE_5 | (newlen << SDS_TYPE_BITS);\n            }\n            break;\n        case SDS_TYPE_8:\n            SDS_HDR(8,s)->len += inc;\n            break;\n        case SDS_TYPE_16:\n            SDS_HDR(16,s)->len += inc;\n            break;\n        case SDS_TYPE_32:\n            SDS_HDR(32,s)->len += inc;\n            break;\n        case SDS_TYPE_64:\n            SDS_HDR(64,s)->len += inc;\n            break;\n    }\n}\n\n/* sdsalloc() = sdsavail() + sdslen() */\nstatic inline size_t sdsalloc(const sds s) {\n    unsigned char flags = s[-1];\n    switch(flags&SDS_TYPE_MASK) {\n        case SDS_TYPE_5:\n            return SDS_TYPE_5_LEN(flags);\n        case SDS_TYPE_8:\n            return SDS_HDR(8,s)->alloc;\n        case SDS_TYPE_16:\n            return SDS_HDR(16,s)->alloc;\n        case SDS_TYPE_32:\n            return SDS_HDR(32,s)->alloc;\n        case SDS_TYPE_64:\n            return SDS_HDR(64,s)->alloc;\n    }\n    return 0;\n}\n\nstatic inline void sdssetalloc(sds s, size_t newlen) {\n    unsigned char flags = s[-1];\n    switch(flags&SDS_TYPE_MASK) {\n        case SDS_TYPE_5:\n            /* Nothing to do, this type has no total allocation info. */\n            break;\n        case SDS_TYPE_8:\n            SDS_HDR(8,s)->alloc = newlen;\n            break;\n        case SDS_TYPE_16:\n            SDS_HDR(16,s)->alloc = newlen;\n            break;\n        case SDS_TYPE_32:\n            SDS_HDR(32,s)->alloc = newlen;\n            break;\n        case SDS_TYPE_64:\n            SDS_HDR(64,s)->alloc = newlen;\n            break;\n    }\n}\n\nsds sdsnewlen(const void *init, size_t initlen);\nsds sdsnew(const char *init);\nsds sdsempty(void);\nsds sdsdup(const sds s);\nvoid sdsfree(sds s);\nsds sdsgrowzero(sds s, size_t len);\nsds sdscatlen(sds s, const void *t, size_t len);\nsds sdscat(sds s, const char *t);\nsds sdscatsds(sds s, const sds t);\nsds sdscpylen(sds s, const char *t, size_t len);\nsds sdscpy(sds s, const char *t);\n\nsds sdscatvprintf(sds s, const char *fmt, va_list ap);\n#ifdef __GNUC__\nsds sdscatprintf(sds s, const char *fmt, ...)\n    __attribute__((format(printf, 2, 3)));\n#else\nsds sdscatprintf(sds s, const char *fmt, ...);\n#endif\n\nsds sdscatfmt(sds s, char const *fmt, ...);\nsds sdstrim(sds s, const char *cset);\nvoid sdsrange(sds s, int start, int end);\nvoid sdsupdatelen(sds s);\nvoid sdsclear(sds s);\nint sdscmp(const sds s1, const sds s2);\nsds *sdssplitlen(const char *s, int len, const char *sep, int seplen, int *count);\nvoid sdsfreesplitres(sds *tokens, int count);\nvoid sdstolower(sds s);\nvoid sdstoupper(sds s);\nsds sdsfromlonglong(long long value);\nsds sdscatrepr(sds s, const char *p, size_t len);\nsds *sdssplitargs(const char *line, int *argc);\nsds sdsmapchars(sds s, const char *from, const char *to, size_t setlen);\nsds sdsjoin(char **argv, int argc, char *sep);\nsds sdsjoinsds(sds *argv, int argc, const char *sep, size_t seplen);\n\n/* Low level functions exposed to the user API */\nsds sdsMakeRoomFor(sds s, size_t addlen);\nvoid sdsIncrLen(sds s, int incr);\nsds sdsRemoveFreeSpace(sds s);\nsize_t sdsAllocSize(sds s);\nvoid *sdsAllocPtr(sds s);\n\n/* Export the allocator used by SDS to the program using SDS.\n * Sometimes the program SDS is linked to, may use a different set of\n * allocators, but may want to allocate or free things that SDS will\n * respectively free or allocate. */\nvoid *sds_malloc(size_t size);\nvoid *sds_realloc(void *ptr, size_t size);\nvoid sds_free(void *ptr);\n\n#ifdef REDIS_TEST\nint sdsTest(int argc, char *argv[]);\n#endif\n\n#endif\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/deps/hiredis/sdsalloc.h",
    "content": "/* SDSLib 2.0 -- A C dynamic strings library\n *\n * Copyright (c) 2006-2015, Salvatore Sanfilippo <antirez at gmail dot com>\n * Copyright (c) 2015, Redis Labs, Inc\n * All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions are met:\n *\n *   * Redistributions of source code must retain the above copyright notice,\n *     this list of conditions and the following disclaimer.\n *   * Redistributions in binary form must reproduce the above copyright\n *     notice, this list of conditions and the following disclaimer in the\n *     documentation and/or other materials provided with the distribution.\n *   * Neither the name of Redis nor the names of its contributors may be used\n *     to endorse or promote products derived from this software without\n *     specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\"\n * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\n * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE\n * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR\n * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF\n * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS\n * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN\n * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)\n * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE\n * POSSIBILITY OF SUCH DAMAGE.\n */\n\n/* SDS allocator selection.\n *\n * This file is used in order to change the SDS allocator at compile time.\n * Just define the following defines to what you want to use. Also add\n * the include of your alternate allocator if needed (not needed in order\n * to use the default libc allocator). */\n\n#include \"zmalloc.h\"\n#define s_malloc zmalloc\n#define s_realloc zrealloc\n#define s_free zfree\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/deps/hiredis/test.c",
    "content": "#include \"fmacros.h\"\n#include <stdio.h>\n#include <stdlib.h>\n#include <string.h>\n#include <strings.h>\n#include <sys/time.h>\n#include <assert.h>\n#include <unistd.h>\n#include <signal.h>\n#include <errno.h>\n#include <limits.h>\n\n#include \"hiredis.h\"\n\nenum connection_type {\n    CONN_TCP,\n    CONN_UNIX,\n    CONN_FD\n};\n\nstruct config {\n    enum connection_type type;\n\n    struct {\n        const char *host;\n        int port;\n        struct timeval timeout;\n    } tcp;\n\n    struct {\n        const char *path;\n    } unix;\n};\n\n/* The following lines make up our testing \"framework\" :) */\nstatic int tests = 0, fails = 0;\n#define test(_s) { printf(\"#%02d \", ++tests); printf(_s); }\n#define test_cond(_c) if(_c) printf(\"\\033[0;32mPASSED\\033[0;0m\\n\"); else {printf(\"\\033[0;31mFAILED\\033[0;0m\\n\"); fails++;}\n\nstatic long long usec(void) {\n    struct timeval tv;\n    gettimeofday(&tv,NULL);\n    return (((long long)tv.tv_sec)*1000000)+tv.tv_usec;\n}\n\nstatic redisContext *select_database(redisContext *c) {\n    redisReply *reply;\n\n    /* Switch to DB 9 for testing, now that we know we can chat. */\n    reply = redisCommand(c,\"SELECT 9\");\n    assert(reply != NULL);\n    freeReplyObject(reply);\n\n    /* Make sure the DB is empty */\n    reply = redisCommand(c,\"DBSIZE\");\n    assert(reply != NULL);\n    if (reply->type == REDIS_REPLY_INTEGER && reply->integer == 0) {\n        /* Awesome, DB 9 is empty and we can continue. */\n        freeReplyObject(reply);\n    } else {\n        printf(\"Database #9 is not empty, test can not continue\\n\");\n        exit(1);\n    }\n\n    return c;\n}\n\nstatic int disconnect(redisContext *c, int keep_fd) {\n    redisReply *reply;\n\n    /* Make sure we're on DB 9. */\n    reply = redisCommand(c,\"SELECT 9\");\n    assert(reply != NULL);\n    freeReplyObject(reply);\n    reply = redisCommand(c,\"FLUSHDB\");\n    assert(reply != NULL);\n    freeReplyObject(reply);\n\n    /* Free the context as well, but keep the fd if requested. */\n    if (keep_fd)\n        return redisFreeKeepFd(c);\n    redisFree(c);\n    return -1;\n}\n\nstatic redisContext *connect(struct config config) {\n    redisContext *c = NULL;\n\n    if (config.type == CONN_TCP) {\n        c = redisConnect(config.tcp.host, config.tcp.port);\n    } else if (config.type == CONN_UNIX) {\n        c = redisConnectUnix(config.unix.path);\n    } else if (config.type == CONN_FD) {\n        /* Create a dummy connection just to get an fd to inherit */\n        redisContext *dummy_ctx = redisConnectUnix(config.unix.path);\n        if (dummy_ctx) {\n            int fd = disconnect(dummy_ctx, 1);\n            printf(\"Connecting to inherited fd %d\\n\", fd);\n            c = redisConnectFd(fd);\n        }\n    } else {\n        assert(NULL);\n    }\n\n    if (c == NULL) {\n        printf(\"Connection error: can't allocate redis context\\n\");\n        exit(1);\n    } else if (c->err) {\n        printf(\"Connection error: %s\\n\", c->errstr);\n        exit(1);\n    }\n\n    return select_database(c);\n}\n\nstatic void test_format_commands(void) {\n    char *cmd;\n    int len;\n\n    test(\"Format command without interpolation: \");\n    len = redisFormatCommand(&cmd,\"SET foo bar\");\n    test_cond(strncmp(cmd,\"*3\\r\\n$3\\r\\nSET\\r\\n$3\\r\\nfoo\\r\\n$3\\r\\nbar\\r\\n\",len) == 0 &&\n        len == 4+4+(3+2)+4+(3+2)+4+(3+2));\n    free(cmd);\n\n    test(\"Format command with %%s string interpolation: \");\n    len = redisFormatCommand(&cmd,\"SET %s %s\",\"foo\",\"bar\");\n    test_cond(strncmp(cmd,\"*3\\r\\n$3\\r\\nSET\\r\\n$3\\r\\nfoo\\r\\n$3\\r\\nbar\\r\\n\",len) == 0 &&\n        len == 4+4+(3+2)+4+(3+2)+4+(3+2));\n    free(cmd);\n\n    test(\"Format command with %%s and an empty string: \");\n    len = redisFormatCommand(&cmd,\"SET %s %s\",\"foo\",\"\");\n    test_cond(strncmp(cmd,\"*3\\r\\n$3\\r\\nSET\\r\\n$3\\r\\nfoo\\r\\n$0\\r\\n\\r\\n\",len) == 0 &&\n        len == 4+4+(3+2)+4+(3+2)+4+(0+2));\n    free(cmd);\n\n    test(\"Format command with an empty string in between proper interpolations: \");\n    len = redisFormatCommand(&cmd,\"SET %s %s\",\"\",\"foo\");\n    test_cond(strncmp(cmd,\"*3\\r\\n$3\\r\\nSET\\r\\n$0\\r\\n\\r\\n$3\\r\\nfoo\\r\\n\",len) == 0 &&\n        len == 4+4+(3+2)+4+(0+2)+4+(3+2));\n    free(cmd);\n\n    test(\"Format command with %%b string interpolation: \");\n    len = redisFormatCommand(&cmd,\"SET %b %b\",\"foo\",(size_t)3,\"b\\0r\",(size_t)3);\n    test_cond(strncmp(cmd,\"*3\\r\\n$3\\r\\nSET\\r\\n$3\\r\\nfoo\\r\\n$3\\r\\nb\\0r\\r\\n\",len) == 0 &&\n        len == 4+4+(3+2)+4+(3+2)+4+(3+2));\n    free(cmd);\n\n    test(\"Format command with %%b and an empty string: \");\n    len = redisFormatCommand(&cmd,\"SET %b %b\",\"foo\",(size_t)3,\"\",(size_t)0);\n    test_cond(strncmp(cmd,\"*3\\r\\n$3\\r\\nSET\\r\\n$3\\r\\nfoo\\r\\n$0\\r\\n\\r\\n\",len) == 0 &&\n        len == 4+4+(3+2)+4+(3+2)+4+(0+2));\n    free(cmd);\n\n    test(\"Format command with literal %%: \");\n    len = redisFormatCommand(&cmd,\"SET %% %%\");\n    test_cond(strncmp(cmd,\"*3\\r\\n$3\\r\\nSET\\r\\n$1\\r\\n%\\r\\n$1\\r\\n%\\r\\n\",len) == 0 &&\n        len == 4+4+(3+2)+4+(1+2)+4+(1+2));\n    free(cmd);\n\n    /* Vararg width depends on the type. These tests make sure that the\n     * width is correctly determined using the format and subsequent varargs\n     * can correctly be interpolated. */\n#define INTEGER_WIDTH_TEST(fmt, type) do {                                                \\\n    type value = 123;                                                                     \\\n    test(\"Format command with printf-delegation (\" #type \"): \");                          \\\n    len = redisFormatCommand(&cmd,\"key:%08\" fmt \" str:%s\", value, \"hello\");               \\\n    test_cond(strncmp(cmd,\"*2\\r\\n$12\\r\\nkey:00000123\\r\\n$9\\r\\nstr:hello\\r\\n\",len) == 0 && \\\n        len == 4+5+(12+2)+4+(9+2));                                                       \\\n    free(cmd);                                                                            \\\n} while(0)\n\n#define FLOAT_WIDTH_TEST(type) do {                                                       \\\n    type value = 123.0;                                                                   \\\n    test(\"Format command with printf-delegation (\" #type \"): \");                          \\\n    len = redisFormatCommand(&cmd,\"key:%08.3f str:%s\", value, \"hello\");                   \\\n    test_cond(strncmp(cmd,\"*2\\r\\n$12\\r\\nkey:0123.000\\r\\n$9\\r\\nstr:hello\\r\\n\",len) == 0 && \\\n        len == 4+5+(12+2)+4+(9+2));                                                       \\\n    free(cmd);                                                                            \\\n} while(0)\n\n    INTEGER_WIDTH_TEST(\"d\", int);\n    INTEGER_WIDTH_TEST(\"hhd\", char);\n    INTEGER_WIDTH_TEST(\"hd\", short);\n    INTEGER_WIDTH_TEST(\"ld\", long);\n    INTEGER_WIDTH_TEST(\"lld\", long long);\n    INTEGER_WIDTH_TEST(\"u\", unsigned int);\n    INTEGER_WIDTH_TEST(\"hhu\", unsigned char);\n    INTEGER_WIDTH_TEST(\"hu\", unsigned short);\n    INTEGER_WIDTH_TEST(\"lu\", unsigned long);\n    INTEGER_WIDTH_TEST(\"llu\", unsigned long long);\n    FLOAT_WIDTH_TEST(float);\n    FLOAT_WIDTH_TEST(double);\n\n    test(\"Format command with invalid printf format: \");\n    len = redisFormatCommand(&cmd,\"key:%08p %b\",(void*)1234,\"foo\",(size_t)3);\n    test_cond(len == -1);\n\n    const char *argv[3];\n    argv[0] = \"SET\";\n    argv[1] = \"foo\\0xxx\";\n    argv[2] = \"bar\";\n    size_t lens[3] = { 3, 7, 3 };\n    int argc = 3;\n\n    test(\"Format command by passing argc/argv without lengths: \");\n    len = redisFormatCommandArgv(&cmd,argc,argv,NULL);\n    test_cond(strncmp(cmd,\"*3\\r\\n$3\\r\\nSET\\r\\n$3\\r\\nfoo\\r\\n$3\\r\\nbar\\r\\n\",len) == 0 &&\n        len == 4+4+(3+2)+4+(3+2)+4+(3+2));\n    free(cmd);\n\n    test(\"Format command by passing argc/argv with lengths: \");\n    len = redisFormatCommandArgv(&cmd,argc,argv,lens);\n    test_cond(strncmp(cmd,\"*3\\r\\n$3\\r\\nSET\\r\\n$7\\r\\nfoo\\0xxx\\r\\n$3\\r\\nbar\\r\\n\",len) == 0 &&\n        len == 4+4+(3+2)+4+(7+2)+4+(3+2));\n    free(cmd);\n}\n\nstatic void test_append_formatted_commands(struct config config) {\n    redisContext *c;\n    redisReply *reply;\n    char *cmd;\n    int len;\n\n    c = connect(config);\n\n    test(\"Append format command: \");\n\n    len = redisFormatCommand(&cmd, \"SET foo bar\");\n\n    test_cond(redisAppendFormattedCommand(c, cmd, len) == REDIS_OK);\n\n    assert(redisGetReply(c, (void*)&reply) == REDIS_OK);\n\n    free(cmd);\n    freeReplyObject(reply);\n\n    disconnect(c, 0);\n}\n\nstatic void test_reply_reader(void) {\n    redisReader *reader;\n    void *reply;\n    int ret;\n    int i;\n\n    test(\"Error handling in reply parser: \");\n    reader = redisReaderCreate();\n    redisReaderFeed(reader,(char*)\"@foo\\r\\n\",6);\n    ret = redisReaderGetReply(reader,NULL);\n    test_cond(ret == REDIS_ERR &&\n              strcasecmp(reader->errstr,\"Protocol error, got \\\"@\\\" as reply type byte\") == 0);\n    redisReaderFree(reader);\n\n    /* when the reply already contains multiple items, they must be free'd\n     * on an error. valgrind will bark when this doesn't happen. */\n    test(\"Memory cleanup in reply parser: \");\n    reader = redisReaderCreate();\n    redisReaderFeed(reader,(char*)\"*2\\r\\n\",4);\n    redisReaderFeed(reader,(char*)\"$5\\r\\nhello\\r\\n\",11);\n    redisReaderFeed(reader,(char*)\"@foo\\r\\n\",6);\n    ret = redisReaderGetReply(reader,NULL);\n    test_cond(ret == REDIS_ERR &&\n              strcasecmp(reader->errstr,\"Protocol error, got \\\"@\\\" as reply type byte\") == 0);\n    redisReaderFree(reader);\n\n    test(\"Set error on nested multi bulks with depth > 7: \");\n    reader = redisReaderCreate();\n\n    for (i = 0; i < 9; i++) {\n        redisReaderFeed(reader,(char*)\"*1\\r\\n\",4);\n    }\n\n    ret = redisReaderGetReply(reader,NULL);\n    test_cond(ret == REDIS_ERR &&\n              strncasecmp(reader->errstr,\"No support for\",14) == 0);\n    redisReaderFree(reader);\n\n    test(\"Works with NULL functions for reply: \");\n    reader = redisReaderCreate();\n    reader->fn = NULL;\n    redisReaderFeed(reader,(char*)\"+OK\\r\\n\",5);\n    ret = redisReaderGetReply(reader,&reply);\n    test_cond(ret == REDIS_OK && reply == (void*)REDIS_REPLY_STATUS);\n    redisReaderFree(reader);\n\n    test(\"Works when a single newline (\\\\r\\\\n) covers two calls to feed: \");\n    reader = redisReaderCreate();\n    reader->fn = NULL;\n    redisReaderFeed(reader,(char*)\"+OK\\r\",4);\n    ret = redisReaderGetReply(reader,&reply);\n    assert(ret == REDIS_OK && reply == NULL);\n    redisReaderFeed(reader,(char*)\"\\n\",1);\n    ret = redisReaderGetReply(reader,&reply);\n    test_cond(ret == REDIS_OK && reply == (void*)REDIS_REPLY_STATUS);\n    redisReaderFree(reader);\n\n    test(\"Don't reset state after protocol error: \");\n    reader = redisReaderCreate();\n    reader->fn = NULL;\n    redisReaderFeed(reader,(char*)\"x\",1);\n    ret = redisReaderGetReply(reader,&reply);\n    assert(ret == REDIS_ERR);\n    ret = redisReaderGetReply(reader,&reply);\n    test_cond(ret == REDIS_ERR && reply == NULL);\n    redisReaderFree(reader);\n\n    /* Regression test for issue #45 on GitHub. */\n    test(\"Don't do empty allocation for empty multi bulk: \");\n    reader = redisReaderCreate();\n    redisReaderFeed(reader,(char*)\"*0\\r\\n\",4);\n    ret = redisReaderGetReply(reader,&reply);\n    test_cond(ret == REDIS_OK &&\n        ((redisReply*)reply)->type == REDIS_REPLY_ARRAY &&\n        ((redisReply*)reply)->elements == 0);\n    freeReplyObject(reply);\n    redisReaderFree(reader);\n}\n\nstatic void test_blocking_connection_errors(void) {\n    redisContext *c;\n\n    test(\"Returns error when host cannot be resolved: \");\n    c = redisConnect((char*)\"idontexist.local\", 6379);\n    test_cond(c->err == REDIS_ERR_OTHER &&\n        (strcmp(c->errstr,\"Name or service not known\") == 0 ||\n         strcmp(c->errstr,\"Can't resolve: idontexist.local\") == 0 ||\n         strcmp(c->errstr,\"nodename nor servname provided, or not known\") == 0 ||\n         strcmp(c->errstr,\"No address associated with hostname\") == 0 ||\n         strcmp(c->errstr,\"no address associated with name\") == 0));\n    redisFree(c);\n\n    test(\"Returns error when the port is not open: \");\n    c = redisConnect((char*)\"localhost\", 1);\n    test_cond(c->err == REDIS_ERR_IO &&\n        strcmp(c->errstr,\"Connection refused\") == 0);\n    redisFree(c);\n\n    test(\"Returns error when the unix socket path doesn't accept connections: \");\n    c = redisConnectUnix((char*)\"/tmp/idontexist.sock\");\n    test_cond(c->err == REDIS_ERR_IO); /* Don't care about the message... */\n    redisFree(c);\n}\n\nstatic void test_blocking_connection(struct config config) {\n    redisContext *c;\n    redisReply *reply;\n\n    c = connect(config);\n\n    test(\"Is able to deliver commands: \");\n    reply = redisCommand(c,\"PING\");\n    test_cond(reply->type == REDIS_REPLY_STATUS &&\n        strcasecmp(reply->str,\"pong\") == 0)\n    freeReplyObject(reply);\n\n    test(\"Is a able to send commands verbatim: \");\n    reply = redisCommand(c,\"SET foo bar\");\n    test_cond (reply->type == REDIS_REPLY_STATUS &&\n        strcasecmp(reply->str,\"ok\") == 0)\n    freeReplyObject(reply);\n\n    test(\"%%s String interpolation works: \");\n    reply = redisCommand(c,\"SET %s %s\",\"foo\",\"hello world\");\n    freeReplyObject(reply);\n    reply = redisCommand(c,\"GET foo\");\n    test_cond(reply->type == REDIS_REPLY_STRING &&\n        strcmp(reply->str,\"hello world\") == 0);\n    freeReplyObject(reply);\n\n    test(\"%%b String interpolation works: \");\n    reply = redisCommand(c,\"SET %b %b\",\"foo\",(size_t)3,\"hello\\x00world\",(size_t)11);\n    freeReplyObject(reply);\n    reply = redisCommand(c,\"GET foo\");\n    test_cond(reply->type == REDIS_REPLY_STRING &&\n        memcmp(reply->str,\"hello\\x00world\",11) == 0)\n\n    test(\"Binary reply length is correct: \");\n    test_cond(reply->len == 11)\n    freeReplyObject(reply);\n\n    test(\"Can parse nil replies: \");\n    reply = redisCommand(c,\"GET nokey\");\n    test_cond(reply->type == REDIS_REPLY_NIL)\n    freeReplyObject(reply);\n\n    /* test 7 */\n    test(\"Can parse integer replies: \");\n    reply = redisCommand(c,\"INCR mycounter\");\n    test_cond(reply->type == REDIS_REPLY_INTEGER && reply->integer == 1)\n    freeReplyObject(reply);\n\n    test(\"Can parse multi bulk replies: \");\n    freeReplyObject(redisCommand(c,\"LPUSH mylist foo\"));\n    freeReplyObject(redisCommand(c,\"LPUSH mylist bar\"));\n    reply = redisCommand(c,\"LRANGE mylist 0 -1\");\n    test_cond(reply->type == REDIS_REPLY_ARRAY &&\n              reply->elements == 2 &&\n              !memcmp(reply->element[0]->str,\"bar\",3) &&\n              !memcmp(reply->element[1]->str,\"foo\",3))\n    freeReplyObject(reply);\n\n    /* m/e with multi bulk reply *before* other reply.\n     * specifically test ordering of reply items to parse. */\n    test(\"Can handle nested multi bulk replies: \");\n    freeReplyObject(redisCommand(c,\"MULTI\"));\n    freeReplyObject(redisCommand(c,\"LRANGE mylist 0 -1\"));\n    freeReplyObject(redisCommand(c,\"PING\"));\n    reply = (redisCommand(c,\"EXEC\"));\n    test_cond(reply->type == REDIS_REPLY_ARRAY &&\n              reply->elements == 2 &&\n              reply->element[0]->type == REDIS_REPLY_ARRAY &&\n              reply->element[0]->elements == 2 &&\n              !memcmp(reply->element[0]->element[0]->str,\"bar\",3) &&\n              !memcmp(reply->element[0]->element[1]->str,\"foo\",3) &&\n              reply->element[1]->type == REDIS_REPLY_STATUS &&\n              strcasecmp(reply->element[1]->str,\"pong\") == 0);\n    freeReplyObject(reply);\n\n    disconnect(c, 0);\n}\n\nstatic void test_blocking_io_errors(struct config config) {\n    redisContext *c;\n    redisReply *reply;\n    void *_reply;\n    int major, minor;\n\n    /* Connect to target given by config. */\n    c = connect(config);\n    {\n        /* Find out Redis version to determine the path for the next test */\n        const char *field = \"redis_version:\";\n        char *p, *eptr;\n\n        reply = redisCommand(c,\"INFO\");\n        p = strstr(reply->str,field);\n        major = strtol(p+strlen(field),&eptr,10);\n        p = eptr+1; /* char next to the first \".\" */\n        minor = strtol(p,&eptr,10);\n        freeReplyObject(reply);\n    }\n\n    test(\"Returns I/O error when the connection is lost: \");\n    reply = redisCommand(c,\"QUIT\");\n    if (major >= 2 && minor > 0) {\n        /* > 2.0 returns OK on QUIT and read() should be issued once more\n         * to know the descriptor is at EOF. */\n        test_cond(strcasecmp(reply->str,\"OK\") == 0 &&\n            redisGetReply(c,&_reply) == REDIS_ERR);\n        freeReplyObject(reply);\n    } else {\n        test_cond(reply == NULL);\n    }\n\n    /* On 2.0, QUIT will cause the connection to be closed immediately and\n     * the read(2) for the reply on QUIT will set the error to EOF.\n     * On >2.0, QUIT will return with OK and another read(2) needed to be\n     * issued to find out the socket was closed by the server. In both\n     * conditions, the error will be set to EOF. */\n    assert(c->err == REDIS_ERR_EOF &&\n        strcmp(c->errstr,\"Server closed the connection\") == 0);\n    redisFree(c);\n\n    c = connect(config);\n    test(\"Returns I/O error on socket timeout: \");\n    struct timeval tv = { 0, 1000 };\n    assert(redisSetTimeout(c,tv) == REDIS_OK);\n    test_cond(redisGetReply(c,&_reply) == REDIS_ERR &&\n        c->err == REDIS_ERR_IO && errno == EAGAIN);\n    redisFree(c);\n}\n\nstatic void test_invalid_timeout_errors(struct config config) {\n    redisContext *c;\n\n    test(\"Set error when an invalid timeout usec value is given to redisConnectWithTimeout: \");\n\n    config.tcp.timeout.tv_sec = 0;\n    config.tcp.timeout.tv_usec = 10000001;\n\n    c = redisConnectWithTimeout(config.tcp.host, config.tcp.port, config.tcp.timeout);\n\n    test_cond(c->err == REDIS_ERR_IO);\n\n    test(\"Set error when an invalid timeout sec value is given to redisConnectWithTimeout: \");\n\n    config.tcp.timeout.tv_sec = (((LONG_MAX) - 999) / 1000) + 1;\n    config.tcp.timeout.tv_usec = 0;\n\n    c = redisConnectWithTimeout(config.tcp.host, config.tcp.port, config.tcp.timeout);\n\n    test_cond(c->err == REDIS_ERR_IO);\n\n    redisFree(c);\n}\n\nstatic void test_throughput(struct config config) {\n    redisContext *c = connect(config);\n    redisReply **replies;\n    int i, num;\n    long long t1, t2;\n\n    test(\"Throughput:\\n\");\n    for (i = 0; i < 500; i++)\n        freeReplyObject(redisCommand(c,\"LPUSH mylist foo\"));\n\n    num = 1000;\n    replies = malloc(sizeof(redisReply*)*num);\n    t1 = usec();\n    for (i = 0; i < num; i++) {\n        replies[i] = redisCommand(c,\"PING\");\n        assert(replies[i] != NULL && replies[i]->type == REDIS_REPLY_STATUS);\n    }\n    t2 = usec();\n    for (i = 0; i < num; i++) freeReplyObject(replies[i]);\n    free(replies);\n    printf(\"\\t(%dx PING: %.3fs)\\n\", num, (t2-t1)/1000000.0);\n\n    replies = malloc(sizeof(redisReply*)*num);\n    t1 = usec();\n    for (i = 0; i < num; i++) {\n        replies[i] = redisCommand(c,\"LRANGE mylist 0 499\");\n        assert(replies[i] != NULL && replies[i]->type == REDIS_REPLY_ARRAY);\n        assert(replies[i] != NULL && replies[i]->elements == 500);\n    }\n    t2 = usec();\n    for (i = 0; i < num; i++) freeReplyObject(replies[i]);\n    free(replies);\n    printf(\"\\t(%dx LRANGE with 500 elements: %.3fs)\\n\", num, (t2-t1)/1000000.0);\n\n    num = 10000;\n    replies = malloc(sizeof(redisReply*)*num);\n    for (i = 0; i < num; i++)\n        redisAppendCommand(c,\"PING\");\n    t1 = usec();\n    for (i = 0; i < num; i++) {\n        assert(redisGetReply(c, (void*)&replies[i]) == REDIS_OK);\n        assert(replies[i] != NULL && replies[i]->type == REDIS_REPLY_STATUS);\n    }\n    t2 = usec();\n    for (i = 0; i < num; i++) freeReplyObject(replies[i]);\n    free(replies);\n    printf(\"\\t(%dx PING (pipelined): %.3fs)\\n\", num, (t2-t1)/1000000.0);\n\n    replies = malloc(sizeof(redisReply*)*num);\n    for (i = 0; i < num; i++)\n        redisAppendCommand(c,\"LRANGE mylist 0 499\");\n    t1 = usec();\n    for (i = 0; i < num; i++) {\n        assert(redisGetReply(c, (void*)&replies[i]) == REDIS_OK);\n        assert(replies[i] != NULL && replies[i]->type == REDIS_REPLY_ARRAY);\n        assert(replies[i] != NULL && replies[i]->elements == 500);\n    }\n    t2 = usec();\n    for (i = 0; i < num; i++) freeReplyObject(replies[i]);\n    free(replies);\n    printf(\"\\t(%dx LRANGE with 500 elements (pipelined): %.3fs)\\n\", num, (t2-t1)/1000000.0);\n\n    disconnect(c, 0);\n}\n\n// static long __test_callback_flags = 0;\n// static void __test_callback(redisContext *c, void *privdata) {\n//     ((void)c);\n//     /* Shift to detect execution order */\n//     __test_callback_flags <<= 8;\n//     __test_callback_flags |= (long)privdata;\n// }\n//\n// static void __test_reply_callback(redisContext *c, redisReply *reply, void *privdata) {\n//     ((void)c);\n//     /* Shift to detect execution order */\n//     __test_callback_flags <<= 8;\n//     __test_callback_flags |= (long)privdata;\n//     if (reply) freeReplyObject(reply);\n// }\n//\n// static redisContext *__connect_nonblock() {\n//     /* Reset callback flags */\n//     __test_callback_flags = 0;\n//     return redisConnectNonBlock(\"127.0.0.1\", port, NULL);\n// }\n//\n// static void test_nonblocking_connection() {\n//     redisContext *c;\n//     int wdone = 0;\n//\n//     test(\"Calls command callback when command is issued: \");\n//     c = __connect_nonblock();\n//     redisSetCommandCallback(c,__test_callback,(void*)1);\n//     redisCommand(c,\"PING\");\n//     test_cond(__test_callback_flags == 1);\n//     redisFree(c);\n//\n//     test(\"Calls disconnect callback on redisDisconnect: \");\n//     c = __connect_nonblock();\n//     redisSetDisconnectCallback(c,__test_callback,(void*)2);\n//     redisDisconnect(c);\n//     test_cond(__test_callback_flags == 2);\n//     redisFree(c);\n//\n//     test(\"Calls disconnect callback and free callback on redisFree: \");\n//     c = __connect_nonblock();\n//     redisSetDisconnectCallback(c,__test_callback,(void*)2);\n//     redisSetFreeCallback(c,__test_callback,(void*)4);\n//     redisFree(c);\n//     test_cond(__test_callback_flags == ((2 << 8) | 4));\n//\n//     test(\"redisBufferWrite against empty write buffer: \");\n//     c = __connect_nonblock();\n//     test_cond(redisBufferWrite(c,&wdone) == REDIS_OK && wdone == 1);\n//     redisFree(c);\n//\n//     test(\"redisBufferWrite against not yet connected fd: \");\n//     c = __connect_nonblock();\n//     redisCommand(c,\"PING\");\n//     test_cond(redisBufferWrite(c,NULL) == REDIS_ERR &&\n//               strncmp(c->error,\"write:\",6) == 0);\n//     redisFree(c);\n//\n//     test(\"redisBufferWrite against closed fd: \");\n//     c = __connect_nonblock();\n//     redisCommand(c,\"PING\");\n//     redisDisconnect(c);\n//     test_cond(redisBufferWrite(c,NULL) == REDIS_ERR &&\n//               strncmp(c->error,\"write:\",6) == 0);\n//     redisFree(c);\n//\n//     test(\"Process callbacks in the right sequence: \");\n//     c = __connect_nonblock();\n//     redisCommandWithCallback(c,__test_reply_callback,(void*)1,\"PING\");\n//     redisCommandWithCallback(c,__test_reply_callback,(void*)2,\"PING\");\n//     redisCommandWithCallback(c,__test_reply_callback,(void*)3,\"PING\");\n//\n//     /* Write output buffer */\n//     wdone = 0;\n//     while(!wdone) {\n//         usleep(500);\n//         redisBufferWrite(c,&wdone);\n//     }\n//\n//     /* Read until at least one callback is executed (the 3 replies will\n//      * arrive in a single packet, causing all callbacks to be executed in\n//      * a single pass). */\n//     while(__test_callback_flags == 0) {\n//         assert(redisBufferRead(c) == REDIS_OK);\n//         redisProcessCallbacks(c);\n//     }\n//     test_cond(__test_callback_flags == 0x010203);\n//     redisFree(c);\n//\n//     test(\"redisDisconnect executes pending callbacks with NULL reply: \");\n//     c = __connect_nonblock();\n//     redisSetDisconnectCallback(c,__test_callback,(void*)1);\n//     redisCommandWithCallback(c,__test_reply_callback,(void*)2,\"PING\");\n//     redisDisconnect(c);\n//     test_cond(__test_callback_flags == 0x0201);\n//     redisFree(c);\n// }\n\nint main(int argc, char **argv) {\n    struct config cfg = {\n        .tcp = {\n            .host = \"127.0.0.1\",\n            .port = 6379\n        },\n        .unix = {\n            .path = \"/tmp/redis.sock\"\n        }\n    };\n    int throughput = 1;\n    int test_inherit_fd = 1;\n\n    /* Ignore broken pipe signal (for I/O error tests). */\n    signal(SIGPIPE, SIG_IGN);\n\n    /* Parse command line options. */\n    argv++; argc--;\n    while (argc) {\n        if (argc >= 2 && !strcmp(argv[0],\"-h\")) {\n            argv++; argc--;\n            cfg.tcp.host = argv[0];\n        } else if (argc >= 2 && !strcmp(argv[0],\"-p\")) {\n            argv++; argc--;\n            cfg.tcp.port = atoi(argv[0]);\n        } else if (argc >= 2 && !strcmp(argv[0],\"-s\")) {\n            argv++; argc--;\n            cfg.unix.path = argv[0];\n        } else if (argc >= 1 && !strcmp(argv[0],\"--skip-throughput\")) {\n            throughput = 0;\n        } else if (argc >= 1 && !strcmp(argv[0],\"--skip-inherit-fd\")) {\n            test_inherit_fd = 0;\n        } else {\n            fprintf(stderr, \"Invalid argument: %s\\n\", argv[0]);\n            exit(1);\n        }\n        argv++; argc--;\n    }\n\n    test_format_commands();\n    test_reply_reader();\n    test_blocking_connection_errors();\n\n    printf(\"\\nTesting against TCP connection (%s:%d):\\n\", cfg.tcp.host, cfg.tcp.port);\n    cfg.type = CONN_TCP;\n    test_blocking_connection(cfg);\n    test_blocking_io_errors(cfg);\n    test_invalid_timeout_errors(cfg);\n    test_append_formatted_commands(cfg);\n    if (throughput) test_throughput(cfg);\n\n    printf(\"\\nTesting against Unix socket connection (%s):\\n\", cfg.unix.path);\n    cfg.type = CONN_UNIX;\n    test_blocking_connection(cfg);\n    test_blocking_io_errors(cfg);\n    if (throughput) test_throughput(cfg);\n\n    if (test_inherit_fd) {\n        printf(\"\\nTesting against inherited fd (%s):\\n\", cfg.unix.path);\n        cfg.type = CONN_FD;\n        test_blocking_connection(cfg);\n    }\n\n    if (fails) {\n        printf(\"*** %d TESTS FAILED ***\\n\", fails);\n        return 1;\n    }\n\n    printf(\"ALL TESTS PASSED\\n\");\n    return 0;\n}\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/deps/hiredis/zmalloc.h",
    "content": "/* Drop in replacement for zmalloc.h in order to just use libc malloc without\n * any wrappering. */\n\n#ifndef ZMALLOC_H\n#define ZMALLOC_H\n\n#define zmalloc malloc\n#define zrealloc realloc\n#define zcalloc(x) calloc(x,1)\n#define zfree free\n#define zstrdup strdup\n\n#endif\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/deps/jemalloc/.autom4te.cfg",
    "content": "begin-language: \"Autoconf-without-aclocal-m4\"\nargs: --no-cache\nend-language: \"Autoconf-without-aclocal-m4\"\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/deps/jemalloc/.gitattributes",
    "content": "* text=auto eol=lf\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/deps/jemalloc/.gitignore",
    "content": "/*.gcov.*\n\n/bin/jemalloc-config\n/bin/jemalloc.sh\n/bin/jeprof\n\n/config.stamp\n/config.log\n/config.status\n/configure\n\n/doc/html.xsl\n/doc/manpages.xsl\n/doc/jemalloc.xml\n/doc/jemalloc.html\n/doc/jemalloc.3\n\n/jemalloc.pc\n\n/lib/\n\n/Makefile\n\n/include/jemalloc/internal/jemalloc_internal.h\n/include/jemalloc/internal/jemalloc_internal_defs.h\n/include/jemalloc/internal/private_namespace.h\n/include/jemalloc/internal/private_unnamespace.h\n/include/jemalloc/internal/public_namespace.h\n/include/jemalloc/internal/public_symbols.txt\n/include/jemalloc/internal/public_unnamespace.h\n/include/jemalloc/internal/size_classes.h\n/include/jemalloc/jemalloc.h\n/include/jemalloc/jemalloc_defs.h\n/include/jemalloc/jemalloc_macros.h\n/include/jemalloc/jemalloc_mangle.h\n/include/jemalloc/jemalloc_mangle_jet.h\n/include/jemalloc/jemalloc_protos.h\n/include/jemalloc/jemalloc_protos_jet.h\n/include/jemalloc/jemalloc_rename.h\n/include/jemalloc/jemalloc_typedefs.h\n\n/src/*.[od]\n/src/*.gcda\n/src/*.gcno\n\n/test/test.sh\ntest/include/test/jemalloc_test.h\ntest/include/test/jemalloc_test_defs.h\n\n/test/integration/[A-Za-z]*\n!/test/integration/[A-Za-z]*.*\n/test/integration/*.[od]\n/test/integration/*.gcda\n/test/integration/*.gcno\n/test/integration/*.out\n\n/test/src/*.[od]\n/test/src/*.gcda\n/test/src/*.gcno\n\n/test/stress/[A-Za-z]*\n!/test/stress/[A-Za-z]*.*\n/test/stress/*.[od]\n/test/stress/*.gcda\n/test/stress/*.gcno\n/test/stress/*.out\n\n/test/unit/[A-Za-z]*\n!/test/unit/[A-Za-z]*.*\n/test/unit/*.[od]\n/test/unit/*.gcda\n/test/unit/*.gcno\n/test/unit/*.out\n\n/VERSION\n\n*.pdb\n*.sdf\n*.opendb\n*.opensdf\n*.cachefile\n*.suo\n*.user\n*.sln.docstates\n*.tmp\n/msvc/Win32/\n/msvc/x64/\n/msvc/projects/*/*/Debug*/\n/msvc/projects/*/*/Release*/\n/msvc/projects/*/*/Win32/\n/msvc/projects/*/*/x64/\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/deps/jemalloc/COPYING",
    "content": "Unless otherwise specified, files in the jemalloc source distribution are\nsubject to the following license:\n--------------------------------------------------------------------------------\nCopyright (C) 2002-2016 Jason Evans <jasone@canonware.com>.\nAll rights reserved.\nCopyright (C) 2007-2012 Mozilla Foundation.  All rights reserved.\nCopyright (C) 2009-2016 Facebook, Inc.  All rights reserved.\n\nRedistribution and use in source and binary forms, with or without\nmodification, are permitted provided that the following conditions are met:\n1. Redistributions of source code must retain the above copyright notice(s),\n   this list of conditions and the following disclaimer.\n2. Redistributions in binary form must reproduce the above copyright notice(s),\n   this list of conditions and the following disclaimer in the documentation\n   and/or other materials provided with the distribution.\n\nTHIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER(S) ``AS IS'' AND ANY EXPRESS\nOR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF\nMERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO\nEVENT SHALL THE COPYRIGHT HOLDER(S) BE LIABLE FOR ANY DIRECT, INDIRECT,\nINCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\nLIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR\nPROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF\nLIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE\nOR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF\nADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n--------------------------------------------------------------------------------\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/deps/jemalloc/ChangeLog",
    "content": "Following are change highlights associated with official releases.  Important\nbug fixes are all mentioned, but some internal enhancements are omitted here for\nbrevity.  Much more detail can be found in the git revision history:\n\n    https://github.com/jemalloc/jemalloc\n\n* 4.2.1 (June 8, 2016)\n\n  Bug fixes:\n  - Fix bootstrapping issues for configurations that require allocation during\n    tsd initialization (e.g. --disable-tls).  (@cferris1000, @jasone)\n  - Fix gettimeofday() version of nstime_update().  (@ronawho)\n  - Fix Valgrind regressions in calloc() and chunk_alloc_wrapper().  (@ronawho)\n  - Fix potential VM map fragmentation regression.  (@jasone)\n  - Fix opt_zero-triggered in-place huge reallocation zeroing.  (@jasone)\n  - Fix heap profiling context leaks in reallocation edge cases.  (@jasone)\n\n* 4.2.0 (May 12, 2016)\n\n  New features:\n  - Add the arena.<i>.reset mallctl, which makes it possible to discard all of\n    an arena's allocations in a single operation.  (@jasone@)\n  - Add the stats.retained and stats.arenas.<i>.retained statistics.  (@jasone)\n  - Add the --with-version configure option.  (@jasone)\n  - Support --with-lg-page values larger than actual page size.  (@jasone)\n\n  Optimizations:\n  - Use pairing heaps rather than red-black trees for various hot data\n    structures.  (@djwatson, @jasone)\n  - Streamline fast paths of rtree operations.  (@jasone)\n  - Optimize the fast paths of calloc() and [m,d,sd]allocx().  (@jasone)\n  - Decommit unused virtual memory if the OS does not overcommit.  (@jasone)\n  - Specify MAP_NORESERVE on Linux if [heuristic] overcommit is active, in order\n    to avoid unfortunate interactions during fork(2).  (@jasone)\n\n  Bug fixes:\n  - Fix chunk accounting related to triggering gdump profiles.  (@jasone)\n  - Link against librt for clock_gettime(2) if glibc < 2.17.  (@jasone)\n  - Scale leak report summary according to sampling probability.  (@jasone)\n\n* 4.1.1 (May 3, 2016)\n\n  This bugfix release resolves a variety of mostly minor issues, though the\n  bitmap fix is critical for 64-bit Windows.\n\n  Bug fixes:\n  - Fix the linear scan version of bitmap_sfu() to shift by the proper amount\n    even when sizeof(long) is not the same as sizeof(void *), as on 64-bit\n    Windows.  (@jasone)\n  - Fix hashing functions to avoid unaligned memory accesses (and resulting\n    crashes).  This is relevant at least to some ARM-based platforms.\n    (@rkmisra)\n  - Fix fork()-related lock rank ordering reversals.  These reversals were\n    unlikely to cause deadlocks in practice except when heap profiling was\n    enabled and active.  (@jasone)\n  - Fix various chunk leaks in OOM code paths.  (@jasone)\n  - Fix malloc_stats_print() to print opt.narenas correctly.  (@jasone)\n  - Fix MSVC-specific build/test issues.  (@rustyx, @yuslepukhin)\n  - Fix a variety of test failures that were due to test fragility rather than\n    core bugs.  (@jasone)\n\n* 4.1.0 (February 28, 2016)\n\n  This release is primarily about optimizations, but it also incorporates a lot\n  of portability-motivated refactoring and enhancements.  Many people worked on\n  this release, to an extent that even with the omission here of minor changes\n  (see git revision history), and of the people who reported and diagnosed\n  issues, so much of the work was contributed that starting with this release,\n  changes are annotated with author credits to help reflect the collaborative\n  effort involved.\n\n  New features:\n  - Implement decay-based unused dirty page purging, a major optimization with\n    mallctl API impact.  This is an alternative to the existing ratio-based\n    unused dirty page purging, and is intended to eventually become the sole\n    purging mechanism.  New mallctls:\n    + opt.purge\n    + opt.decay_time\n    + arena.<i>.decay\n    + arena.<i>.decay_time\n    + arenas.decay_time\n    + stats.arenas.<i>.decay_time\n    (@jasone, @cevans87)\n  - Add --with-malloc-conf, which makes it possible to embed a default\n    options string during configuration.  This was motivated by the desire to\n    specify --with-malloc-conf=purge:decay , since the default must remain\n    purge:ratio until the 5.0.0 release.  (@jasone)\n  - Add MS Visual Studio 2015 support.  (@rustyx, @yuslepukhin)\n  - Make *allocx() size class overflow behavior defined.  The maximum\n    size class is now less than PTRDIFF_MAX to protect applications against\n    numerical overflow, and all allocation functions are guaranteed to indicate\n    errors rather than potentially crashing if the request size exceeds the\n    maximum size class.  (@jasone)\n  - jeprof:\n    + Add raw heap profile support.  (@jasone)\n    + Add --retain and --exclude for backtrace symbol filtering.  (@jasone)\n\n  Optimizations:\n  - Optimize the fast path to combine various bootstrapping and configuration\n    checks and execute more streamlined code in the common case.  (@interwq)\n  - Use linear scan for small bitmaps (used for small object tracking).  In\n    addition to speeding up bitmap operations on 64-bit systems, this reduces\n    allocator metadata overhead by approximately 0.2%.  (@djwatson)\n  - Separate arena_avail trees, which substantially speeds up run tree\n    operations.  (@djwatson)\n  - Use memoization (boot-time-computed table) for run quantization.  Separate\n    arena_avail trees reduced the importance of this optimization.  (@jasone)\n  - Attempt mmap-based in-place huge reallocation.  This can dramatically speed\n    up incremental huge reallocation.  (@jasone)\n\n  Incompatible changes:\n  - Make opt.narenas unsigned rather than size_t.  (@jasone)\n\n  Bug fixes:\n  - Fix stats.cactive accounting regression.  (@rustyx, @jasone)\n  - Handle unaligned keys in hash().  This caused problems for some ARM systems.\n    (@jasone, @cferris1000)\n  - Refactor arenas array.  In addition to fixing a fork-related deadlock, this\n    makes arena lookups faster and simpler.  (@jasone)\n  - Move retained memory allocation out of the default chunk allocation\n    function, to a location that gets executed even if the application installs\n    a custom chunk allocation function.  This resolves a virtual memory leak.\n    (@buchgr)\n  - Fix a potential tsd cleanup leak.  (@cferris1000, @jasone)\n  - Fix run quantization.  In practice this bug had no impact unless\n    applications requested memory with alignment exceeding one page.\n    (@jasone, @djwatson)\n  - Fix LinuxThreads-specific bootstrapping deadlock.  (Cosmin Paraschiv)\n  - jeprof:\n    + Don't discard curl options if timeout is not defined.  (@djwatson)\n    + Detect failed profile fetches.  (@djwatson)\n  - Fix stats.arenas.<i>.{dss,lg_dirty_mult,decay_time,pactive,pdirty} for\n    --disable-stats case.  (@jasone)\n\n* 4.0.4 (October 24, 2015)\n\n  This bugfix release fixes another xallocx() regression.  No other regressions\n  have come to light in over a month, so this is likely a good starting point\n  for people who prefer to wait for \"dot one\" releases with all the major issues\n  shaken out.\n\n  Bug fixes:\n  - Fix xallocx(..., MALLOCX_ZERO to zero the last full trailing page of large\n    allocations that have been randomly assigned an offset of 0 when\n    --enable-cache-oblivious configure option is enabled.\n\n* 4.0.3 (September 24, 2015)\n\n  This bugfix release continues the trend of xallocx() and heap profiling fixes.\n\n  Bug fixes:\n  - Fix xallocx(..., MALLOCX_ZERO) to zero all trailing bytes of large\n    allocations when --enable-cache-oblivious configure option is enabled.\n  - Fix xallocx(..., MALLOCX_ZERO) to zero trailing bytes of huge allocations\n    when resizing from/to a size class that is not a multiple of the chunk size.\n  - Fix prof_tctx_dump_iter() to filter out nodes that were created after heap\n    profile dumping started.\n  - Work around a potentially bad thread-specific data initialization\n    interaction with NPTL (glibc's pthreads implementation).\n\n* 4.0.2 (September 21, 2015)\n\n  This bugfix release addresses a few bugs specific to heap profiling.\n\n  Bug fixes:\n  - Fix ixallocx_prof_sample() to never modify nor create sampled small\n    allocations.  xallocx() is in general incapable of moving small allocations,\n    so this fix removes buggy code without loss of generality.\n  - Fix irallocx_prof_sample() to always allocate large regions, even when\n    alignment is non-zero.\n  - Fix prof_alloc_rollback() to read tdata from thread-specific data rather\n    than dereferencing a potentially invalid tctx.\n\n* 4.0.1 (September 15, 2015)\n\n  This is a bugfix release that is somewhat high risk due to the amount of\n  refactoring required to address deep xallocx() problems.  As a side effect of\n  these fixes, xallocx() now tries harder to partially fulfill requests for\n  optional extra space.  Note that a couple of minor heap profiling\n  optimizations are included, but these are better thought of as performance\n  fixes that were integral to disovering most of the other bugs.\n\n  Optimizations:\n  - Avoid a chunk metadata read in arena_prof_tctx_set(), since it is in the\n    fast path when heap profiling is enabled.  Additionally, split a special\n    case out into arena_prof_tctx_reset(), which also avoids chunk metadata\n    reads.\n  - Optimize irallocx_prof() to optimistically update the sampler state.  The\n    prior implementation appears to have been a holdover from when\n    rallocx()/xallocx() functionality was combined as rallocm().\n\n  Bug fixes:\n  - Fix TLS configuration such that it is enabled by default for platforms on\n    which it works correctly.\n  - Fix arenas_cache_cleanup() and arena_get_hard() to handle\n    allocation/deallocation within the application's thread-specific data\n    cleanup functions even after arenas_cache is torn down.\n  - Fix xallocx() bugs related to size+extra exceeding HUGE_MAXCLASS.\n  - Fix chunk purge hook calls for in-place huge shrinking reallocation to\n    specify the old chunk size rather than the new chunk size.  This bug caused\n    no correctness issues for the default chunk purge function, but was\n    visible to custom functions set via the \"arena.<i>.chunk_hooks\" mallctl.\n  - Fix heap profiling bugs:\n    + Fix heap profiling to distinguish among otherwise identical sample sites\n      with interposed resets (triggered via the \"prof.reset\" mallctl).  This bug\n      could cause data structure corruption that would most likely result in a\n      segfault.\n    + Fix irealloc_prof() to prof_alloc_rollback() on OOM.\n    + Make one call to prof_active_get_unlocked() per allocation event, and use\n      the result throughout the relevant functions that handle an allocation\n      event.  Also add a missing check in prof_realloc().  These fixes protect\n      allocation events against concurrent prof_active changes.\n    + Fix ixallocx_prof() to pass usize_max and zero to ixallocx_prof_sample()\n      in the correct order.\n    + Fix prof_realloc() to call prof_free_sampled_object() after calling\n      prof_malloc_sample_object().  Prior to this fix, if tctx and old_tctx were\n      the same, the tctx could have been prematurely destroyed.\n  - Fix portability bugs:\n    + Don't bitshift by negative amounts when encoding/decoding run sizes in\n      chunk header maps.  This affected systems with page sizes greater than 8\n      KiB.\n    + Rename index_t to szind_t to avoid an existing type on Solaris.\n    + Add JEMALLOC_CXX_THROW to the memalign() function prototype, in order to\n      match glibc and avoid compilation errors when including both\n      jemalloc/jemalloc.h and malloc.h in C++ code.\n    + Don't assume that /bin/sh is appropriate when running size_classes.sh\n      during configuration.\n    + Consider __sparcv9 a synonym for __sparc64__ when defining LG_QUANTUM.\n    + Link tests to librt if it contains clock_gettime(2).\n\n* 4.0.0 (August 17, 2015)\n\n  This version contains many speed and space optimizations, both minor and\n  major.  The major themes are generalization, unification, and simplification.\n  Although many of these optimizations cause no visible behavior change, their\n  cumulative effect is substantial.\n\n  New features:\n  - Normalize size class spacing to be consistent across the complete size\n    range.  By default there are four size classes per size doubling, but this\n    is now configurable via the --with-lg-size-class-group option.  Also add the\n    --with-lg-page, --with-lg-page-sizes, --with-lg-quantum, and\n    --with-lg-tiny-min options, which can be used to tweak page and size class\n    settings.  Impacts:\n    + Worst case performance for incrementally growing/shrinking reallocation\n      is improved because there are far fewer size classes, and therefore\n      copying happens less often.\n    + Internal fragmentation is limited to 20% for all but the smallest size\n      classes (those less than four times the quantum).  (1B + 4 KiB)\n      and (1B + 4 MiB) previously suffered nearly 50% internal fragmentation.\n    + Chunk fragmentation tends to be lower because there are fewer distinct run\n      sizes to pack.\n  - Add support for explicit tcaches.  The \"tcache.create\", \"tcache.flush\", and\n    \"tcache.destroy\" mallctls control tcache lifetime and flushing, and the\n    MALLOCX_TCACHE(tc) and MALLOCX_TCACHE_NONE flags to the *allocx() API\n    control which tcache is used for each operation.\n  - Implement per thread heap profiling, as well as the ability to\n    enable/disable heap profiling on a per thread basis.  Add the \"prof.reset\",\n    \"prof.lg_sample\", \"thread.prof.name\", \"thread.prof.active\",\n    \"opt.prof_thread_active_init\", \"prof.thread_active_init\", and\n    \"thread.prof.active\" mallctls.\n  - Add support for per arena application-specified chunk allocators, configured\n    via the \"arena.<i>.chunk_hooks\" mallctl.\n  - Refactor huge allocation to be managed by arenas, so that arenas now\n    function as general purpose independent allocators.  This is important in\n    the context of user-specified chunk allocators, aside from the scalability\n    benefits.  Related new statistics:\n    + The \"stats.arenas.<i>.huge.allocated\", \"stats.arenas.<i>.huge.nmalloc\",\n      \"stats.arenas.<i>.huge.ndalloc\", and \"stats.arenas.<i>.huge.nrequests\"\n      mallctls provide high level per arena huge allocation statistics.\n    + The \"arenas.nhchunks\", \"arenas.hchunk.<i>.size\",\n      \"stats.arenas.<i>.hchunks.<j>.nmalloc\",\n      \"stats.arenas.<i>.hchunks.<j>.ndalloc\",\n      \"stats.arenas.<i>.hchunks.<j>.nrequests\", and\n      \"stats.arenas.<i>.hchunks.<j>.curhchunks\" mallctls provide per size class\n      statistics.\n  - Add the 'util' column to malloc_stats_print() output, which reports the\n    proportion of available regions that are currently in use for each small\n    size class.\n  - Add \"alloc\" and \"free\" modes for for junk filling (see the \"opt.junk\"\n    mallctl), so that it is possible to separately enable junk filling for\n    allocation versus deallocation.\n  - Add the jemalloc-config script, which provides information about how\n    jemalloc was configured, and how to integrate it into application builds.\n  - Add metadata statistics, which are accessible via the \"stats.metadata\",\n    \"stats.arenas.<i>.metadata.mapped\", and\n    \"stats.arenas.<i>.metadata.allocated\" mallctls.\n  - Add the \"stats.resident\" mallctl, which reports the upper limit of\n    physically resident memory mapped by the allocator.\n  - Add per arena control over unused dirty page purging, via the\n    \"arenas.lg_dirty_mult\", \"arena.<i>.lg_dirty_mult\", and\n    \"stats.arenas.<i>.lg_dirty_mult\" mallctls.\n  - Add the \"prof.gdump\" mallctl, which makes it possible to toggle the gdump\n    feature on/off during program execution.\n  - Add sdallocx(), which implements sized deallocation.  The primary\n    optimization over dallocx() is the removal of a metadata read, which often\n    suffers an L1 cache miss.\n  - Add missing header includes in jemalloc/jemalloc.h, so that applications\n    only have to #include <jemalloc/jemalloc.h>.\n  - Add support for additional platforms:\n    + Bitrig\n    + Cygwin\n    + DragonFlyBSD\n    + iOS\n    + OpenBSD\n    + OpenRISC/or1k\n\n  Optimizations:\n  - Maintain dirty runs in per arena LRUs rather than in per arena trees of\n    dirty-run-containing chunks.  In practice this change significantly reduces\n    dirty page purging volume.\n  - Integrate whole chunks into the unused dirty page purging machinery.  This\n    reduces the cost of repeated huge allocation/deallocation, because it\n    effectively introduces a cache of chunks.\n  - Split the arena chunk map into two separate arrays, in order to increase\n    cache locality for the frequently accessed bits.\n  - Move small run metadata out of runs, into arena chunk headers.  This reduces\n    run fragmentation, smaller runs reduce external fragmentation for small size\n    classes, and packed (less uniformly aligned) metadata layout improves CPU\n    cache set distribution.\n  - Randomly distribute large allocation base pointer alignment relative to page\n    boundaries in order to more uniformly utilize CPU cache sets.  This can be\n    disabled via the --disable-cache-oblivious configure option, and queried via\n    the \"config.cache_oblivious\" mallctl.\n  - Micro-optimize the fast paths for the public API functions.\n  - Refactor thread-specific data to reside in a single structure.  This assures\n    that only a single TLS read is necessary per call into the public API.\n  - Implement in-place huge allocation growing and shrinking.\n  - Refactor rtree (radix tree for chunk lookups) to be lock-free, and make\n    additional optimizations that reduce maximum lookup depth to one or two\n    levels.  This resolves what was a concurrency bottleneck for per arena huge\n    allocation, because a global data structure is critical for determining\n    which arenas own which huge allocations.\n\n  Incompatible changes:\n  - Replace --enable-cc-silence with --disable-cc-silence to suppress spurious\n    warnings by default.\n  - Assure that the constness of malloc_usable_size()'s return type matches that\n    of the system implementation.\n  - Change the heap profile dump format to support per thread heap profiling,\n    rename pprof to jeprof, and enhance it with the --thread=<n> option.  As a\n    result, the bundled jeprof must now be used rather than the upstream\n    (gperftools) pprof.\n  - Disable \"opt.prof_final\" by default, in order to avoid atexit(3), which can\n    internally deadlock on some platforms.\n  - Change the \"arenas.nlruns\" mallctl type from size_t to unsigned.\n  - Replace the \"stats.arenas.<i>.bins.<j>.allocated\" mallctl with\n    \"stats.arenas.<i>.bins.<j>.curregs\".\n  - Ignore MALLOC_CONF in set{uid,gid,cap} binaries.\n  - Ignore MALLOCX_ARENA(a) in dallocx(), in favor of using the\n    MALLOCX_TCACHE(tc) and MALLOCX_TCACHE_NONE flags to control tcache usage.\n\n  Removed features:\n  - Remove the *allocm() API, which is superseded by the *allocx() API.\n  - Remove the --enable-dss options, and make dss non-optional on all platforms\n    which support sbrk(2).\n  - Remove the \"arenas.purge\" mallctl, which was obsoleted by the\n    \"arena.<i>.purge\" mallctl in 3.1.0.\n  - Remove the unnecessary \"opt.valgrind\" mallctl; jemalloc automatically\n    detects whether it is running inside Valgrind.\n  - Remove the \"stats.huge.allocated\", \"stats.huge.nmalloc\", and\n    \"stats.huge.ndalloc\" mallctls.\n  - Remove the --enable-mremap option.\n  - Remove the \"stats.chunks.current\", \"stats.chunks.total\", and\n    \"stats.chunks.high\" mallctls.\n\n  Bug fixes:\n  - Fix the cactive statistic to decrease (rather than increase) when active\n    memory decreases.  This regression was first released in 3.5.0.\n  - Fix OOM handling in memalign() and valloc().  A variant of this bug existed\n    in all releases since 2.0.0, which introduced these functions.\n  - Fix an OOM-related regression in arena_tcache_fill_small(), which could\n    cause cache corruption on OOM.  This regression was present in all releases\n    from 2.2.0 through 3.6.0.\n  - Fix size class overflow handling for malloc(), posix_memalign(), memalign(),\n    calloc(), and realloc() when profiling is enabled.\n  - Fix the \"arena.<i>.dss\" mallctl to return an error if \"primary\" or\n    \"secondary\" precedence is specified, but sbrk(2) is not supported.\n  - Fix fallback lg_floor() implementations to handle extremely large inputs.\n  - Ensure the default purgeable zone is after the default zone on OS X.\n  - Fix latent bugs in atomic_*().\n  - Fix the \"arena.<i>.dss\" mallctl to handle read-only calls.\n  - Fix tls_model configuration to enable the initial-exec model when possible.\n  - Mark malloc_conf as a weak symbol so that the application can override it.\n  - Correctly detect glibc's adaptive pthread mutexes.\n  - Fix the --without-export configure option.\n\n* 3.6.0 (March 31, 2014)\n\n  This version contains a critical bug fix for a regression present in 3.5.0 and\n  3.5.1.\n\n  Bug fixes:\n  - Fix a regression in arena_chunk_alloc() that caused crashes during\n    small/large allocation if chunk allocation failed.  In the absence of this\n    bug, chunk allocation failure would result in allocation failure, e.g.  NULL\n    return from malloc().  This regression was introduced in 3.5.0.\n  - Fix backtracing for gcc intrinsics-based backtracing by specifying\n    -fno-omit-frame-pointer to gcc.  Note that the application (and all the\n    libraries it links to) must also be compiled with this option for\n    backtracing to be reliable.\n  - Use dss allocation precedence for huge allocations as well as small/large\n    allocations.\n  - Fix test assertion failure message formatting.  This bug did not manifest on\n    x86_64 systems because of implementation subtleties in va_list.\n  - Fix inconsequential test failures for hash and SFMT code.\n\n  New features:\n  - Support heap profiling on FreeBSD.  This feature depends on the proc\n    filesystem being mounted during heap profile dumping.\n\n* 3.5.1 (February 25, 2014)\n\n  This version primarily addresses minor bugs in test code.\n\n  Bug fixes:\n  - Configure Solaris/Illumos to use MADV_FREE.\n  - Fix junk filling for mremap(2)-based huge reallocation.  This is only\n    relevant if configuring with the --enable-mremap option specified.\n  - Avoid compilation failure if 'restrict' C99 keyword is not supported by the\n    compiler.\n  - Add a configure test for SSE2 rather than assuming it is usable on i686\n    systems.  This fixes test compilation errors, especially on 32-bit Linux\n    systems.\n  - Fix mallctl argument size mismatches (size_t vs. uint64_t) in the stats unit\n    test.\n  - Fix/remove flawed alignment-related overflow tests.\n  - Prevent compiler optimizations that could change backtraces in the\n    prof_accum unit test.\n\n* 3.5.0 (January 22, 2014)\n\n  This version focuses on refactoring and automated testing, though it also\n  includes some non-trivial heap profiling optimizations not mentioned below.\n\n  New features:\n  - Add the *allocx() API, which is a successor to the experimental *allocm()\n    API.  The *allocx() functions are slightly simpler to use because they have\n    fewer parameters, they directly return the results of primary interest, and\n    mallocx()/rallocx() avoid the strict aliasing pitfall that\n    allocm()/rallocm() share with posix_memalign().  Note that *allocm() is\n    slated for removal in the next non-bugfix release.\n  - Add support for LinuxThreads.\n\n  Bug fixes:\n  - Unless heap profiling is enabled, disable floating point code and don't link\n    with libm.  This, in combination with e.g. EXTRA_CFLAGS=-mno-sse on x64\n    systems, makes it possible to completely disable floating point register\n    use.  Some versions of glibc neglect to save/restore caller-saved floating\n    point registers during dynamic lazy symbol loading, and the symbol loading\n    code uses whatever malloc the application happens to have linked/loaded\n    with, the result being potential floating point register corruption.\n  - Report ENOMEM rather than EINVAL if an OOM occurs during heap profiling\n    backtrace creation in imemalign().  This bug impacted posix_memalign() and\n    aligned_alloc().\n  - Fix a file descriptor leak in a prof_dump_maps() error path.\n  - Fix prof_dump() to close the dump file descriptor for all relevant error\n    paths.\n  - Fix rallocm() to use the arena specified by the ALLOCM_ARENA(s) flag for\n    allocation, not just deallocation.\n  - Fix a data race for large allocation stats counters.\n  - Fix a potential infinite loop during thread exit.  This bug occurred on\n    Solaris, and could affect other platforms with similar pthreads TSD\n    implementations.\n  - Don't junk-fill reallocations unless usable size changes.  This fixes a\n    violation of the *allocx()/*allocm() semantics.\n  - Fix growing large reallocation to junk fill new space.\n  - Fix huge deallocation to junk fill when munmap is disabled.\n  - Change the default private namespace prefix from empty to je_, and change\n    --with-private-namespace-prefix so that it prepends an additional prefix\n    rather than replacing je_.  This reduces the likelihood of applications\n    which statically link jemalloc experiencing symbol name collisions.\n  - Add missing private namespace mangling (relevant when\n    --with-private-namespace is specified).\n  - Add and use JEMALLOC_INLINE_C so that static inline functions are marked as\n    static even for debug builds.\n  - Add a missing mutex unlock in a malloc_init_hard() error path.  In practice\n    this error path is never executed.\n  - Fix numerous bugs in malloc_strotumax() error handling/reporting.  These\n    bugs had no impact except for malformed inputs.\n  - Fix numerous bugs in malloc_snprintf().  These bugs were not exercised by\n    existing calls, so they had no impact.\n\n* 3.4.1 (October 20, 2013)\n\n  Bug fixes:\n  - Fix a race in the \"arenas.extend\" mallctl that could cause memory corruption\n    of internal data structures and subsequent crashes.\n  - Fix Valgrind integration flaws that caused Valgrind warnings about reads of\n    uninitialized memory in:\n    + arena chunk headers\n    + internal zero-initialized data structures (relevant to tcache and prof\n      code)\n  - Preserve errno during the first allocation.  A readlink(2) call during\n    initialization fails unless /etc/malloc.conf exists, so errno was typically\n    set during the first allocation prior to this fix.\n  - Fix compilation warnings reported by gcc 4.8.1.\n\n* 3.4.0 (June 2, 2013)\n\n  This version is essentially a small bugfix release, but the addition of\n  aarch64 support requires that the minor version be incremented.\n\n  Bug fixes:\n  - Fix race-triggered deadlocks in chunk_record().  These deadlocks were\n    typically triggered by multiple threads concurrently deallocating huge\n    objects.\n\n  New features:\n  - Add support for the aarch64 architecture.\n\n* 3.3.1 (March 6, 2013)\n\n  This version fixes bugs that are typically encountered only when utilizing\n  custom run-time options.\n\n  Bug fixes:\n  - Fix a locking order bug that could cause deadlock during fork if heap\n    profiling were enabled.\n  - Fix a chunk recycling bug that could cause the allocator to lose track of\n    whether a chunk was zeroed.  On FreeBSD, NetBSD, and OS X, it could cause\n    corruption if allocating via sbrk(2) (unlikely unless running with the\n    \"dss:primary\" option specified).  This was completely harmless on Linux\n    unless using mlockall(2) (and unlikely even then, unless the\n    --disable-munmap configure option or the \"dss:primary\" option was\n    specified).  This regression was introduced in 3.1.0 by the\n    mlockall(2)/madvise(2) interaction fix.\n  - Fix TLS-related memory corruption that could occur during thread exit if the\n    thread never allocated memory.  Only the quarantine and prof facilities were\n    susceptible.\n  - Fix two quarantine bugs:\n    + Internal reallocation of the quarantined object array leaked the old\n      array.\n    + Reallocation failure for internal reallocation of the quarantined object\n      array (very unlikely) resulted in memory corruption.\n  - Fix Valgrind integration to annotate all internally allocated memory in a\n    way that keeps Valgrind happy about internal data structure access.\n  - Fix building for s390 systems.\n\n* 3.3.0 (January 23, 2013)\n\n  This version includes a few minor performance improvements in addition to the\n  listed new features and bug fixes.\n\n  New features:\n  - Add clipping support to lg_chunk option processing.\n  - Add the --enable-ivsalloc option.\n  - Add the --without-export option.\n  - Add the --disable-zone-allocator option.\n\n  Bug fixes:\n  - Fix \"arenas.extend\" mallctl to output the number of arenas.\n  - Fix chunk_recycle() to unconditionally inform Valgrind that returned memory\n    is undefined.\n  - Fix build break on FreeBSD related to alloca.h.\n\n* 3.2.0 (November 9, 2012)\n\n  In addition to a couple of bug fixes, this version modifies page run\n  allocation and dirty page purging algorithms in order to better control\n  page-level virtual memory fragmentation.\n\n  Incompatible changes:\n  - Change the \"opt.lg_dirty_mult\" default from 5 to 3 (32:1 to 8:1).\n\n  Bug fixes:\n  - Fix dss/mmap allocation precedence code to use recyclable mmap memory only\n    after primary dss allocation fails.\n  - Fix deadlock in the \"arenas.purge\" mallctl.  This regression was introduced\n    in 3.1.0 by the addition of the \"arena.<i>.purge\" mallctl.\n\n* 3.1.0 (October 16, 2012)\n\n  New features:\n  - Auto-detect whether running inside Valgrind, thus removing the need to\n    manually specify MALLOC_CONF=valgrind:true.\n  - Add the \"arenas.extend\" mallctl, which allows applications to create\n    manually managed arenas.\n  - Add the ALLOCM_ARENA() flag for {,r,d}allocm().\n  - Add the \"opt.dss\", \"arena.<i>.dss\", and \"stats.arenas.<i>.dss\" mallctls,\n    which provide control over dss/mmap precedence.\n  - Add the \"arena.<i>.purge\" mallctl, which obsoletes \"arenas.purge\".\n  - Define LG_QUANTUM for hppa.\n\n  Incompatible changes:\n  - Disable tcache by default if running inside Valgrind, in order to avoid\n    making unallocated objects appear reachable to Valgrind.\n  - Drop const from malloc_usable_size() argument on Linux.\n\n  Bug fixes:\n  - Fix heap profiling crash if sampled object is freed via realloc(p, 0).\n  - Remove const from __*_hook variable declarations, so that glibc can modify\n    them during process forking.\n  - Fix mlockall(2)/madvise(2) interaction.\n  - Fix fork(2)-related deadlocks.\n  - Fix error return value for \"thread.tcache.enabled\" mallctl.\n\n* 3.0.0 (May 11, 2012)\n\n  Although this version adds some major new features, the primary focus is on\n  internal code cleanup that facilitates maintainability and portability, most\n  of which is not reflected in the ChangeLog.  This is the first release to\n  incorporate substantial contributions from numerous other developers, and the\n  result is a more broadly useful allocator (see the git revision history for\n  contribution details).  Note that the license has been unified, thanks to\n  Facebook granting a license under the same terms as the other copyright\n  holders (see COPYING).\n\n  New features:\n  - Implement Valgrind support, redzones, and quarantine.\n  - Add support for additional platforms:\n    + FreeBSD\n    + Mac OS X Lion\n    + MinGW\n    + Windows (no support yet for replacing the system malloc)\n  - Add support for additional architectures:\n    + MIPS\n    + SH4\n    + Tilera\n  - Add support for cross compiling.\n  - Add nallocm(), which rounds a request size up to the nearest size class\n    without actually allocating.\n  - Implement aligned_alloc() (blame C11).\n  - Add the \"thread.tcache.enabled\" mallctl.\n  - Add the \"opt.prof_final\" mallctl.\n  - Update pprof (from gperftools 2.0).\n  - Add the --with-mangling option.\n  - Add the --disable-experimental option.\n  - Add the --disable-munmap option, and make it the default on Linux.\n  - Add the --enable-mremap option, which disables use of mremap(2) by default.\n\n  Incompatible changes:\n  - Enable stats by default.\n  - Enable fill by default.\n  - Disable lazy locking by default.\n  - Rename the \"tcache.flush\" mallctl to \"thread.tcache.flush\".\n  - Rename the \"arenas.pagesize\" mallctl to \"arenas.page\".\n  - Change the \"opt.lg_prof_sample\" default from 0 to 19 (1 B to 512 KiB).\n  - Change the \"opt.prof_accum\" default from true to false.\n\n  Removed features:\n  - Remove the swap feature, including the \"config.swap\", \"swap.avail\",\n    \"swap.prezeroed\", \"swap.nfds\", and \"swap.fds\" mallctls.\n  - Remove highruns statistics, including the\n    \"stats.arenas.<i>.bins.<j>.highruns\" and\n    \"stats.arenas.<i>.lruns.<j>.highruns\" mallctls.\n  - As part of small size class refactoring, remove the \"opt.lg_[qc]space_max\",\n    \"arenas.cacheline\", \"arenas.subpage\", \"arenas.[tqcs]space_{min,max}\", and\n    \"arenas.[tqcs]bins\" mallctls.\n  - Remove the \"arenas.chunksize\" mallctl.\n  - Remove the \"opt.lg_prof_tcmax\" option.\n  - Remove the \"opt.lg_prof_bt_max\" option.\n  - Remove the \"opt.lg_tcache_gc_sweep\" option.\n  - Remove the --disable-tiny option, including the \"config.tiny\" mallctl.\n  - Remove the --enable-dynamic-page-shift configure option.\n  - Remove the --enable-sysv configure option.\n\n  Bug fixes:\n  - Fix a statistics-related bug in the \"thread.arena\" mallctl that could cause\n    invalid statistics and crashes.\n  - Work around TLS deallocation via free() on Linux.  This bug could cause\n    write-after-free memory corruption.\n  - Fix a potential deadlock that could occur during interval- and\n    growth-triggered heap profile dumps.\n  - Fix large calloc() zeroing bugs due to dropping chunk map unzeroed flags.\n  - Fix chunk_alloc_dss() to stop claiming memory is zeroed.  This bug could\n    cause memory corruption and crashes with --enable-dss specified.\n  - Fix fork-related bugs that could cause deadlock in children between fork\n    and exec.\n  - Fix malloc_stats_print() to honor 'b' and 'l' in the opts parameter.\n  - Fix realloc(p, 0) to act like free(p).\n  - Do not enforce minimum alignment in memalign().\n  - Check for NULL pointer in malloc_usable_size().\n  - Fix an off-by-one heap profile statistics bug that could be observed in\n    interval- and growth-triggered heap profiles.\n  - Fix the \"epoch\" mallctl to update cached stats even if the passed in epoch\n    is 0.\n  - Fix bin->runcur management to fix a layout policy bug.  This bug did not\n    affect correctness.\n  - Fix a bug in choose_arena_hard() that potentially caused more arenas to be\n    initialized than necessary.\n  - Add missing \"opt.lg_tcache_max\" mallctl implementation.\n  - Use glibc allocator hooks to make mixed allocator usage less likely.\n  - Fix build issues for --disable-tcache.\n  - Don't mangle pthread_create() when --with-private-namespace is specified.\n\n* 2.2.5 (November 14, 2011)\n\n  Bug fixes:\n  - Fix huge_ralloc() race when using mremap(2).  This is a serious bug that\n    could cause memory corruption and/or crashes.\n  - Fix huge_ralloc() to maintain chunk statistics.\n  - Fix malloc_stats_print(..., \"a\") output.\n\n* 2.2.4 (November 5, 2011)\n\n  Bug fixes:\n  - Initialize arenas_tsd before using it.  This bug existed for 2.2.[0-3], as\n    well as for --disable-tls builds in earlier releases.\n  - Do not assume a 4 KiB page size in test/rallocm.c.\n\n* 2.2.3 (August 31, 2011)\n\n  This version fixes numerous bugs related to heap profiling.\n\n  Bug fixes:\n  - Fix a prof-related race condition.  This bug could cause memory corruption,\n    but only occurred in non-default configurations (prof_accum:false).\n  - Fix off-by-one backtracing issues (make sure that prof_alloc_prep() is\n    excluded from backtraces).\n  - Fix a prof-related bug in realloc() (only triggered by OOM errors).\n  - Fix prof-related bugs in allocm() and rallocm().\n  - Fix prof_tdata_cleanup() for --disable-tls builds.\n  - Fix a relative include path, to fix objdir builds.\n\n* 2.2.2 (July 30, 2011)\n\n  Bug fixes:\n  - Fix a build error for --disable-tcache.\n  - Fix assertions in arena_purge() (for real this time).\n  - Add the --with-private-namespace option.  This is a workaround for symbol\n    conflicts that can inadvertently arise when using static libraries.\n\n* 2.2.1 (March 30, 2011)\n\n  Bug fixes:\n  - Implement atomic operations for x86/x64.  This fixes compilation failures\n    for versions of gcc that are still in wide use.\n  - Fix an assertion in arena_purge().\n\n* 2.2.0 (March 22, 2011)\n\n  This version incorporates several improvements to algorithms and data\n  structures that tend to reduce fragmentation and increase speed.\n\n  New features:\n  - Add the \"stats.cactive\" mallctl.\n  - Update pprof (from google-perftools 1.7).\n  - Improve backtracing-related configuration logic, and add the\n    --disable-prof-libgcc option.\n\n  Bug fixes:\n  - Change default symbol visibility from \"internal\", to \"hidden\", which\n    decreases the overhead of library-internal function calls.\n  - Fix symbol visibility so that it is also set on OS X.\n  - Fix a build dependency regression caused by the introduction of the .pic.o\n    suffix for PIC object files.\n  - Add missing checks for mutex initialization failures.\n  - Don't use libgcc-based backtracing except on x64, where it is known to work.\n  - Fix deadlocks on OS X that were due to memory allocation in\n    pthread_mutex_lock().\n  - Heap profiling-specific fixes:\n    + Fix memory corruption due to integer overflow in small region index\n      computation, when using a small enough sample interval that profiling\n      context pointers are stored in small run headers.\n    + Fix a bootstrap ordering bug that only occurred with TLS disabled.\n    + Fix a rallocm() rsize bug.\n    + Fix error detection bugs for aligned memory allocation.\n\n* 2.1.3 (March 14, 2011)\n\n  Bug fixes:\n  - Fix a cpp logic regression (due to the \"thread.{de,}allocatedp\" mallctl fix\n    for OS X in 2.1.2).\n  - Fix a \"thread.arena\" mallctl bug.\n  - Fix a thread cache stats merging bug.\n\n* 2.1.2 (March 2, 2011)\n\n  Bug fixes:\n  - Fix \"thread.{de,}allocatedp\" mallctl for OS X.\n  - Add missing jemalloc.a to build system.\n\n* 2.1.1 (January 31, 2011)\n\n  Bug fixes:\n  - Fix aligned huge reallocation (affected allocm()).\n  - Fix the ALLOCM_LG_ALIGN macro definition.\n  - Fix a heap dumping deadlock.\n  - Fix a \"thread.arena\" mallctl bug.\n\n* 2.1.0 (December 3, 2010)\n\n  This version incorporates some optimizations that can't quite be considered\n  bug fixes.\n\n  New features:\n  - Use Linux's mremap(2) for huge object reallocation when possible.\n  - Avoid locking in mallctl*() when possible.\n  - Add the \"thread.[de]allocatedp\" mallctl's.\n  - Convert the manual page source from roff to DocBook, and generate both roff\n    and HTML manuals.\n\n  Bug fixes:\n  - Fix a crash due to incorrect bootstrap ordering.  This only impacted\n    --enable-debug --enable-dss configurations.\n  - Fix a minor statistics bug for mallctl(\"swap.avail\", ...).\n\n* 2.0.1 (October 29, 2010)\n\n  Bug fixes:\n  - Fix a race condition in heap profiling that could cause undefined behavior\n    if \"opt.prof_accum\" were disabled.\n  - Add missing mutex unlocks for some OOM error paths in the heap profiling\n    code.\n  - Fix a compilation error for non-C99 builds.\n\n* 2.0.0 (October 24, 2010)\n\n  This version focuses on the experimental *allocm() API, and on improved\n  run-time configuration/introspection.  Nonetheless, numerous performance\n  improvements are also included.\n\n  New features:\n  - Implement the experimental {,r,s,d}allocm() API, which provides a superset\n    of the functionality available via malloc(), calloc(), posix_memalign(),\n    realloc(), malloc_usable_size(), and free().  These functions can be used to\n    allocate/reallocate aligned zeroed memory, ask for optional extra memory\n    during reallocation, prevent object movement during reallocation, etc.\n  - Replace JEMALLOC_OPTIONS/JEMALLOC_PROF_PREFIX with MALLOC_CONF, which is\n    more human-readable, and more flexible.  For example:\n      JEMALLOC_OPTIONS=AJP\n    is now:\n      MALLOC_CONF=abort:true,fill:true,stats_print:true\n  - Port to Apple OS X.  Sponsored by Mozilla.\n  - Make it possible for the application to control thread-->arena mappings via\n    the \"thread.arena\" mallctl.\n  - Add compile-time support for all TLS-related functionality via pthreads TSD.\n    This is mainly of interest for OS X, which does not support TLS, but has a\n    TSD implementation with similar performance.\n  - Override memalign() and valloc() if they are provided by the system.\n  - Add the \"arenas.purge\" mallctl, which can be used to synchronously purge all\n    dirty unused pages.\n  - Make cumulative heap profiling data optional, so that it is possible to\n    limit the amount of memory consumed by heap profiling data structures.\n  - Add per thread allocation counters that can be accessed via the\n    \"thread.allocated\" and \"thread.deallocated\" mallctls.\n\n  Incompatible changes:\n  - Remove JEMALLOC_OPTIONS and malloc_options (see MALLOC_CONF above).\n  - Increase default backtrace depth from 4 to 128 for heap profiling.\n  - Disable interval-based profile dumps by default.\n\n  Bug fixes:\n  - Remove bad assertions in fork handler functions.  These assertions could\n    cause aborts for some combinations of configure settings.\n  - Fix strerror_r() usage to deal with non-standard semantics in GNU libc.\n  - Fix leak context reporting.  This bug tended to cause the number of contexts\n    to be underreported (though the reported number of objects and bytes were\n    correct).\n  - Fix a realloc() bug for large in-place growing reallocation.  This bug could\n    cause memory corruption, but it was hard to trigger.\n  - Fix an allocation bug for small allocations that could be triggered if\n    multiple threads raced to create a new run of backing pages.\n  - Enhance the heap profiler to trigger samples based on usable size, rather\n    than request size.\n  - Fix a heap profiling bug due to sometimes losing track of requested object\n    size for sampled objects.\n\n* 1.0.3 (August 12, 2010)\n\n  Bug fixes:\n  - Fix the libunwind-based implementation of stack backtracing (used for heap\n    profiling).  This bug could cause zero-length backtraces to be reported.\n  - Add a missing mutex unlock in library initialization code.  If multiple\n    threads raced to initialize malloc, some of them could end up permanently\n    blocked.\n\n* 1.0.2 (May 11, 2010)\n\n  Bug fixes:\n  - Fix junk filling of large objects, which could cause memory corruption.\n  - Add MAP_NORESERVE support for chunk mapping, because otherwise virtual\n    memory limits could cause swap file configuration to fail.  Contributed by\n    Jordan DeLong.\n\n* 1.0.1 (April 14, 2010)\n\n  Bug fixes:\n  - Fix compilation when --enable-fill is specified.\n  - Fix threads-related profiling bugs that affected accuracy and caused memory\n    to be leaked during thread exit.\n  - Fix dirty page purging race conditions that could cause crashes.\n  - Fix crash in tcache flushing code during thread destruction.\n\n* 1.0.0 (April 11, 2010)\n\n  This release focuses on speed and run-time introspection.  Numerous\n  algorithmic improvements make this release substantially faster than its\n  predecessors.\n\n  New features:\n  - Implement autoconf-based configuration system.\n  - Add mallctl*(), for the purposes of introspection and run-time\n    configuration.\n  - Make it possible for the application to manually flush a thread's cache, via\n    the \"tcache.flush\" mallctl.\n  - Base maximum dirty page count on proportion of active memory.\n  - Compute various additional run-time statistics, including per size class\n    statistics for large objects.\n  - Expose malloc_stats_print(), which can be called repeatedly by the\n    application.\n  - Simplify the malloc_message() signature to only take one string argument,\n    and incorporate an opaque data pointer argument for use by the application\n    in combination with malloc_stats_print().\n  - Add support for allocation backed by one or more swap files, and allow the\n    application to disable over-commit if swap files are in use.\n  - Implement allocation profiling and leak checking.\n\n  Removed features:\n  - Remove the dynamic arena rebalancing code, since thread-specific caching\n    reduces its utility.\n\n  Bug fixes:\n  - Modify chunk allocation to work when address space layout randomization\n    (ASLR) is in use.\n  - Fix thread cleanup bugs related to TLS destruction.\n  - Handle 0-size allocation requests in posix_memalign().\n  - Fix a chunk leak.  The leaked chunks were never touched, so this impacted\n    virtual memory usage, but not physical memory usage.\n\n* linux_2008082[78]a (August 27/28, 2008)\n\n  These snapshot releases are the simple result of incorporating Linux-specific\n  support into the FreeBSD malloc sources.\n\n--------------------------------------------------------------------------------\nvim:filetype=text:textwidth=80\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/deps/jemalloc/INSTALL",
    "content": "Building and installing a packaged release of jemalloc can be as simple as\ntyping the following while in the root directory of the source tree:\n\n    ./configure\n    make\n    make install\n\nIf building from unpackaged developer sources, the simplest command sequence\nthat might work is:\n\n    ./autogen.sh\n    make dist\n    make\n    make install\n\nNote that documentation is not built by the default target because doing so\nwould create a dependency on xsltproc in packaged releases, hence the\nrequirement to either run 'make dist' or avoid installing docs via the various\ninstall_* targets documented below.\n\n=== Advanced configuration =====================================================\n\nThe 'configure' script supports numerous options that allow control of which\nfunctionality is enabled, where jemalloc is installed, etc.  Optionally, pass\nany of the following arguments (not a definitive list) to 'configure':\n\n--help\n    Print a definitive list of options.\n\n--prefix=<install-root-dir>\n    Set the base directory in which to install.  For example:\n\n        ./configure --prefix=/usr/local\n\n    will cause files to be installed into /usr/local/include, /usr/local/lib,\n    and /usr/local/man.\n\n--with-version=<major>.<minor>.<bugfix>-<nrev>-g<gid>\n    Use the specified version string rather than trying to generate one (if in\n    a git repository) or use existing the VERSION file (if present).\n\n--with-rpath=<colon-separated-rpath>\n    Embed one or more library paths, so that libjemalloc can find the libraries\n    it is linked to.  This works only on ELF-based systems.\n\n--with-mangling=<map>\n    Mangle public symbols specified in <map> which is a comma-separated list of\n    name:mangled pairs.\n\n    For example, to use ld's --wrap option as an alternative method for\n    overriding libc's malloc implementation, specify something like:\n\n      --with-mangling=malloc:__wrap_malloc,free:__wrap_free[...]\n\n    Note that mangling happens prior to application of the prefix specified by\n    --with-jemalloc-prefix, and mangled symbols are then ignored when applying\n    the prefix.\n\n--with-jemalloc-prefix=<prefix>\n    Prefix all public APIs with <prefix>.  For example, if <prefix> is\n    \"prefix_\", API changes like the following occur:\n\n      malloc()         --> prefix_malloc()\n      malloc_conf      --> prefix_malloc_conf\n      /etc/malloc.conf --> /etc/prefix_malloc.conf\n      MALLOC_CONF      --> PREFIX_MALLOC_CONF\n\n    This makes it possible to use jemalloc at the same time as the system\n    allocator, or even to use multiple copies of jemalloc simultaneously.\n\n    By default, the prefix is \"\", except on OS X, where it is \"je_\".  On OS X,\n    jemalloc overlays the default malloc zone, but makes no attempt to actually\n    replace the \"malloc\", \"calloc\", etc. symbols.\n\n--without-export\n    Don't export public APIs.  This can be useful when building jemalloc as a\n    static library, or to avoid exporting public APIs when using the zone\n    allocator on OSX.\n\n--with-private-namespace=<prefix>\n    Prefix all library-private APIs with <prefix>je_.  For shared libraries,\n    symbol visibility mechanisms prevent these symbols from being exported, but\n    for static libraries, naming collisions are a real possibility.  By\n    default, <prefix> is empty, which results in a symbol prefix of je_ .\n\n--with-install-suffix=<suffix>\n    Append <suffix> to the base name of all installed files, such that multiple\n    versions of jemalloc can coexist in the same installation directory.  For\n    example, libjemalloc.so.0 becomes libjemalloc<suffix>.so.0.\n\n--with-malloc-conf=<malloc_conf>\n    Embed <malloc_conf> as a run-time options string that is processed prior to\n    the malloc_conf global variable, the /etc/malloc.conf symlink, and the\n    MALLOC_CONF environment variable.  For example, to change the default chunk\n    size to 256 KiB:\n\n      --with-malloc-conf=lg_chunk:18\n\n--disable-cc-silence\n    Disable code that silences non-useful compiler warnings.  This is mainly\n    useful during development when auditing the set of warnings that are being\n    silenced.\n\n--enable-debug\n    Enable assertions and validation code.  This incurs a substantial\n    performance hit, but is very useful during application development.\n    Implies --enable-ivsalloc.\n\n--enable-code-coverage\n    Enable code coverage support, for use during jemalloc test development.\n    Additional testing targets are available if this option is enabled:\n\n      coverage\n      coverage_unit\n      coverage_integration\n      coverage_stress\n\n    These targets do not clear code coverage results from previous runs, and\n    there are interactions between the various coverage targets, so it is\n    usually advisable to run 'make clean' between repeated code coverage runs.\n\n--disable-stats\n    Disable statistics gathering functionality.  See the \"opt.stats_print\"\n    option documentation for usage details.\n\n--enable-ivsalloc\n    Enable validation code, which verifies that pointers reside within\n    jemalloc-owned chunks before dereferencing them.  This incurs a minor\n    performance hit.\n\n--enable-prof\n    Enable heap profiling and leak detection functionality.  See the \"opt.prof\"\n    option documentation for usage details.  When enabled, there are several\n    approaches to backtracing, and the configure script chooses the first one\n    in the following list that appears to function correctly:\n\n    + libunwind      (requires --enable-prof-libunwind)\n    + libgcc         (unless --disable-prof-libgcc)\n    + gcc intrinsics (unless --disable-prof-gcc)\n\n--enable-prof-libunwind\n    Use the libunwind library (http://www.nongnu.org/libunwind/) for stack\n    backtracing.\n\n--disable-prof-libgcc\n    Disable the use of libgcc's backtracing functionality.\n\n--disable-prof-gcc\n    Disable the use of gcc intrinsics for backtracing.\n\n--with-static-libunwind=<libunwind.a>\n    Statically link against the specified libunwind.a rather than dynamically\n    linking with -lunwind.\n\n--disable-tcache\n    Disable thread-specific caches for small objects.  Objects are cached and\n    released in bulk, thus reducing the total number of mutex operations.  See\n    the \"opt.tcache\" option for usage details.\n\n--disable-munmap\n    Disable virtual memory deallocation via munmap(2); instead keep track of\n    the virtual memory for later use.  munmap() is disabled by default (i.e.\n    --disable-munmap is implied) on Linux, which has a quirk in its virtual\n    memory allocation algorithm that causes semi-permanent VM map holes under\n    normal jemalloc operation.\n\n--disable-fill\n    Disable support for junk/zero filling of memory, quarantine, and redzones.\n    See the \"opt.junk\", \"opt.zero\", \"opt.quarantine\", and \"opt.redzone\" option\n    documentation for usage details.\n\n--disable-valgrind\n    Disable support for Valgrind.\n\n--disable-zone-allocator\n    Disable zone allocator for Darwin.  This means jemalloc won't be hooked as\n    the default allocator on OSX/iOS.\n\n--enable-utrace\n    Enable utrace(2)-based allocation tracing.  This feature is not broadly\n    portable (FreeBSD has it, but Linux and OS X do not).\n\n--enable-xmalloc\n    Enable support for optional immediate termination due to out-of-memory\n    errors, as is commonly implemented by \"xmalloc\" wrapper function for malloc.\n    See the \"opt.xmalloc\" option documentation for usage details.\n\n--enable-lazy-lock\n    Enable code that wraps pthread_create() to detect when an application\n    switches from single-threaded to multi-threaded mode, so that it can avoid\n    mutex locking/unlocking operations while in single-threaded mode.  In\n    practice, this feature usually has little impact on performance unless\n    thread-specific caching is disabled.\n\n--disable-tls\n    Disable thread-local storage (TLS), which allows for fast access to\n    thread-local variables via the __thread keyword.  If TLS is available,\n    jemalloc uses it for several purposes.\n\n--disable-cache-oblivious\n    Disable cache-oblivious large allocation alignment for large allocation\n    requests with no alignment constraints.  If this feature is disabled, all\n    large allocations are page-aligned as an implementation artifact, which can\n    severely harm CPU cache utilization.  However, the cache-oblivious layout\n    comes at the cost of one extra page per large allocation, which in the\n    most extreme case increases physical memory usage for the 16 KiB size class\n    to 20 KiB.\n\n--with-xslroot=<path>\n    Specify where to find DocBook XSL stylesheets when building the\n    documentation.\n\n--with-lg-page=<lg-page>\n    Specify the base 2 log of the system page size.  This option is only useful\n    when cross compiling, since the configure script automatically determines\n    the host's page size by default.\n\n--with-lg-page-sizes=<lg-page-sizes>\n    Specify the comma-separated base 2 logs of the page sizes to support.  This\n    option may be useful when cross-compiling in combination with\n    --with-lg-page, but its primary use case is for integration with FreeBSD's\n    libc, wherein jemalloc is embedded.\n\n--with-lg-size-class-group=<lg-size-class-group>\n    Specify the base 2 log of how many size classes to use for each doubling in\n    size.  By default jemalloc uses <lg-size-class-group>=2, which results in\n    e.g. the following size classes:\n\n      [...], 64,\n      80, 96, 112, 128,\n      160, [...]\n\n    <lg-size-class-group>=3 results in e.g. the following size classes:\n\n      [...], 64,\n      72, 80, 88, 96, 104, 112, 120, 128,\n      144, [...]\n\n    The minimal <lg-size-class-group>=0 causes jemalloc to only provide size\n    classes that are powers of 2:\n\n      [...],\n      64,\n      128,\n      256,\n      [...]\n\n    An implementation detail currently limits the total number of small size\n    classes to 255, and a compilation error will result if the\n    <lg-size-class-group> you specify cannot be supported.  The limit is\n    roughly <lg-size-class-group>=4, depending on page size.\n\n--with-lg-quantum=<lg-quantum>\n    Specify the base 2 log of the minimum allocation alignment.  jemalloc needs\n    to know the minimum alignment that meets the following C standard\n    requirement (quoted from the April 12, 2011 draft of the C11 standard):\n\n      The pointer returned if the allocation succeeds is suitably aligned so\n      that it may be assigned to a pointer to any type of object with a\n      fundamental alignment requirement and then used to access such an object\n      or an array of such objects in the space allocated [...]\n\n    This setting is architecture-specific, and although jemalloc includes known\n    safe values for the most commonly used modern architectures, there is a\n    wrinkle related to GNU libc (glibc) that may impact your choice of\n    <lg-quantum>.  On most modern architectures, this mandates 16-byte alignment\n    (<lg-quantum>=4), but the glibc developers chose not to meet this\n    requirement for performance reasons.  An old discussion can be found at\n    https://sourceware.org/bugzilla/show_bug.cgi?id=206 .  Unlike glibc,\n    jemalloc does follow the C standard by default (caveat: jemalloc\n    technically cheats if --with-lg-tiny-min is smaller than\n    --with-lg-quantum), but the fact that Linux systems already work around\n    this allocator noncompliance means that it is generally safe in practice to\n    let jemalloc's minimum alignment follow glibc's lead.  If you specify\n    --with-lg-quantum=3 during configuration, jemalloc will provide additional\n    size classes that are not 16-byte-aligned (24, 40, and 56, assuming\n    --with-lg-size-class-group=2).\n\n--with-lg-tiny-min=<lg-tiny-min>\n    Specify the base 2 log of the minimum tiny size class to support.  Tiny\n    size classes are powers of 2 less than the quantum, and are only\n    incorporated if <lg-tiny-min> is less than <lg-quantum> (see\n    --with-lg-quantum).  Tiny size classes technically violate the C standard\n    requirement for minimum alignment, and crashes could conceivably result if\n    the compiler were to generate instructions that made alignment assumptions,\n    both because illegal instruction traps could result, and because accesses\n    could straddle page boundaries and cause segmentation faults due to\n    accessing unmapped addresses.\n\n    The default of <lg-tiny-min>=3 works well in practice even on architectures\n    that technically require 16-byte alignment, probably for the same reason\n    --with-lg-quantum=3 works.  Smaller tiny size classes can, and will, cause\n    crashes (see https://bugzilla.mozilla.org/show_bug.cgi?id=691003 for an\n    example).\n\n    This option is rarely useful, and is mainly provided as documentation of a\n    subtle implementation detail.  If you do use this option, specify a\n    value in [3, ..., <lg-quantum>].\n\nThe following environment variables (not a definitive list) impact configure's\nbehavior:\n\nCFLAGS=\"?\"\n    Pass these flags to the compiler.  You probably shouldn't define this unless\n    you know what you are doing.  (Use EXTRA_CFLAGS instead.)\n\nEXTRA_CFLAGS=\"?\"\n    Append these flags to CFLAGS.  This makes it possible to add flags such as\n    -Werror, while allowing the configure script to determine what other flags\n    are appropriate for the specified configuration.\n\n    The configure script specifically checks whether an optimization flag (-O*)\n    is specified in EXTRA_CFLAGS, and refrains from specifying an optimization\n    level if it finds that one has already been specified.\n\nCPPFLAGS=\"?\"\n    Pass these flags to the C preprocessor.  Note that CFLAGS is not passed to\n    'cpp' when 'configure' is looking for include files, so you must use\n    CPPFLAGS instead if you need to help 'configure' find header files.\n\nLD_LIBRARY_PATH=\"?\"\n    'ld' uses this colon-separated list to find libraries.\n\nLDFLAGS=\"?\"\n    Pass these flags when linking.\n\nPATH=\"?\"\n    'configure' uses this to find programs.\n\n=== Advanced compilation =======================================================\n\nTo build only parts of jemalloc, use the following targets:\n\n    build_lib_shared\n    build_lib_static\n    build_lib\n    build_doc_html\n    build_doc_man\n    build_doc\n\nTo install only parts of jemalloc, use the following targets:\n\n    install_bin\n    install_include\n    install_lib_shared\n    install_lib_static\n    install_lib\n    install_doc_html\n    install_doc_man\n    install_doc\n\nTo clean up build results to varying degrees, use the following make targets:\n\n    clean\n    distclean\n    relclean\n\n=== Advanced installation ======================================================\n\nOptionally, define make variables when invoking make, including (not\nexclusively):\n\nINCLUDEDIR=\"?\"\n    Use this as the installation prefix for header files.\n\nLIBDIR=\"?\"\n    Use this as the installation prefix for libraries.\n\nMANDIR=\"?\"\n    Use this as the installation prefix for man pages.\n\nDESTDIR=\"?\"\n    Prepend DESTDIR to INCLUDEDIR, LIBDIR, DATADIR, and MANDIR.  This is useful\n    when installing to a different path than was specified via --prefix.\n\nCC=\"?\"\n    Use this to invoke the C compiler.\n\nCFLAGS=\"?\"\n    Pass these flags to the compiler.\n\nCPPFLAGS=\"?\"\n    Pass these flags to the C preprocessor.\n\nLDFLAGS=\"?\"\n    Pass these flags when linking.\n\nPATH=\"?\"\n    Use this to search for programs used during configuration and building.\n\n=== Development ================================================================\n\nIf you intend to make non-trivial changes to jemalloc, use the 'autogen.sh'\nscript rather than 'configure'.  This re-generates 'configure', enables\nconfiguration dependency rules, and enables re-generation of automatically\ngenerated source files.\n\nThe build system supports using an object directory separate from the source\ntree.  For example, you can create an 'obj' directory, and from within that\ndirectory, issue configuration and build commands:\n\n    autoconf\n    mkdir obj\n    cd obj\n    ../configure --enable-autogen\n    make\n\n=== Documentation ==============================================================\n\nThe manual page is generated in both html and roff formats.  Any web browser\ncan be used to view the html manual.  The roff manual page can be formatted\nprior to installation via the following command:\n\n    nroff -man -t doc/jemalloc.3\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/deps/jemalloc/Makefile.in",
    "content": "# Clear out all vpaths, then set just one (default vpath) for the main build\n# directory.\nvpath\nvpath % .\n\n# Clear the default suffixes, so that built-in rules are not used.\n.SUFFIXES :\n\nSHELL := /bin/sh\n\nCC := @CC@\n\n# Configuration parameters.\nDESTDIR =\nBINDIR := $(DESTDIR)@BINDIR@\nINCLUDEDIR := $(DESTDIR)@INCLUDEDIR@\nLIBDIR := $(DESTDIR)@LIBDIR@\nDATADIR := $(DESTDIR)@DATADIR@\nMANDIR := $(DESTDIR)@MANDIR@\nsrcroot := @srcroot@\nobjroot := @objroot@\nabs_srcroot := @abs_srcroot@\nabs_objroot := @abs_objroot@\n\n# Build parameters.\nCPPFLAGS := @CPPFLAGS@ -I$(srcroot)include -I$(objroot)include\nCFLAGS := @CFLAGS@\nLDFLAGS := @LDFLAGS@\nEXTRA_LDFLAGS := @EXTRA_LDFLAGS@\nLIBS := @LIBS@\nRPATH_EXTRA := @RPATH_EXTRA@\nSO := @so@\nIMPORTLIB := @importlib@\nO := @o@\nA := @a@\nEXE := @exe@\nLIBPREFIX := @libprefix@\nREV := @rev@\ninstall_suffix := @install_suffix@\nABI := @abi@\nXSLTPROC := @XSLTPROC@\nAUTOCONF := @AUTOCONF@\n_RPATH = @RPATH@\nRPATH = $(if $(1),$(call _RPATH,$(1)))\ncfghdrs_in := $(addprefix $(srcroot),@cfghdrs_in@)\ncfghdrs_out := @cfghdrs_out@\ncfgoutputs_in := $(addprefix $(srcroot),@cfgoutputs_in@)\ncfgoutputs_out := @cfgoutputs_out@\nenable_autogen := @enable_autogen@\nenable_code_coverage := @enable_code_coverage@\nenable_prof := @enable_prof@\nenable_valgrind := @enable_valgrind@\nenable_zone_allocator := @enable_zone_allocator@\nMALLOC_CONF := @JEMALLOC_CPREFIX@MALLOC_CONF\nDSO_LDFLAGS = @DSO_LDFLAGS@\nSOREV = @SOREV@\nPIC_CFLAGS = @PIC_CFLAGS@\nCTARGET = @CTARGET@\nLDTARGET = @LDTARGET@\nMKLIB = @MKLIB@\nAR = @AR@\nARFLAGS = @ARFLAGS@\nCC_MM = @CC_MM@\n\nifeq (macho, $(ABI))\nTEST_LIBRARY_PATH := DYLD_FALLBACK_LIBRARY_PATH=\"$(objroot)lib\"\nelse\nifeq (pecoff, $(ABI))\nTEST_LIBRARY_PATH := PATH=\"$(PATH):$(objroot)lib\"\nelse\nTEST_LIBRARY_PATH :=\nendif\nendif\n\nLIBJEMALLOC := $(LIBPREFIX)jemalloc$(install_suffix)\n\n# Lists of files.\nBINS := $(objroot)bin/jemalloc-config $(objroot)bin/jemalloc.sh $(objroot)bin/jeprof\nC_HDRS := $(objroot)include/jemalloc/jemalloc$(install_suffix).h\nC_SRCS := $(srcroot)src/jemalloc.c \\\n\t$(srcroot)src/arena.c \\\n\t$(srcroot)src/atomic.c \\\n\t$(srcroot)src/base.c \\\n\t$(srcroot)src/bitmap.c \\\n\t$(srcroot)src/chunk.c \\\n\t$(srcroot)src/chunk_dss.c \\\n\t$(srcroot)src/chunk_mmap.c \\\n\t$(srcroot)src/ckh.c \\\n\t$(srcroot)src/ctl.c \\\n\t$(srcroot)src/extent.c \\\n\t$(srcroot)src/hash.c \\\n\t$(srcroot)src/huge.c \\\n\t$(srcroot)src/mb.c \\\n\t$(srcroot)src/mutex.c \\\n\t$(srcroot)src/nstime.c \\\n\t$(srcroot)src/pages.c \\\n\t$(srcroot)src/prng.c \\\n\t$(srcroot)src/prof.c \\\n\t$(srcroot)src/quarantine.c \\\n\t$(srcroot)src/rtree.c \\\n\t$(srcroot)src/stats.c \\\n\t$(srcroot)src/tcache.c \\\n\t$(srcroot)src/ticker.c \\\n\t$(srcroot)src/tsd.c \\\n\t$(srcroot)src/util.c \\\n\t$(srcroot)src/witness.c\nifeq ($(enable_valgrind), 1)\nC_SRCS += $(srcroot)src/valgrind.c\nendif\nifeq ($(enable_zone_allocator), 1)\nC_SRCS += $(srcroot)src/zone.c\nendif\nifeq ($(IMPORTLIB),$(SO))\nSTATIC_LIBS := $(objroot)lib/$(LIBJEMALLOC).$(A)\nendif\nifdef PIC_CFLAGS\nSTATIC_LIBS += $(objroot)lib/$(LIBJEMALLOC)_pic.$(A)\nelse\nSTATIC_LIBS += $(objroot)lib/$(LIBJEMALLOC)_s.$(A)\nendif\nDSOS := $(objroot)lib/$(LIBJEMALLOC).$(SOREV)\nifneq ($(SOREV),$(SO))\nDSOS += $(objroot)lib/$(LIBJEMALLOC).$(SO)\nendif\nPC := $(objroot)jemalloc.pc\nMAN3 := $(objroot)doc/jemalloc$(install_suffix).3\nDOCS_XML := $(objroot)doc/jemalloc$(install_suffix).xml\nDOCS_HTML := $(DOCS_XML:$(objroot)%.xml=$(objroot)%.html)\nDOCS_MAN3 := $(DOCS_XML:$(objroot)%.xml=$(objroot)%.3)\nDOCS := $(DOCS_HTML) $(DOCS_MAN3)\nC_TESTLIB_SRCS := $(srcroot)test/src/btalloc.c $(srcroot)test/src/btalloc_0.c \\\n\t$(srcroot)test/src/btalloc_1.c $(srcroot)test/src/math.c \\\n\t$(srcroot)test/src/mtx.c $(srcroot)test/src/mq.c \\\n\t$(srcroot)test/src/SFMT.c $(srcroot)test/src/test.c \\\n\t$(srcroot)test/src/thd.c $(srcroot)test/src/timer.c\nC_UTIL_INTEGRATION_SRCS := $(srcroot)src/nstime.c $(srcroot)src/util.c\nTESTS_UNIT := \\\n\t$(srcroot)test/unit/a0.c \\\n\t$(srcroot)test/unit/arena_reset.c \\\n\t$(srcroot)test/unit/atomic.c \\\n\t$(srcroot)test/unit/bitmap.c \\\n\t$(srcroot)test/unit/ckh.c \\\n\t$(srcroot)test/unit/decay.c \\\n\t$(srcroot)test/unit/fork.c \\\n\t$(srcroot)test/unit/hash.c \\\n\t$(srcroot)test/unit/junk.c \\\n\t$(srcroot)test/unit/junk_alloc.c \\\n\t$(srcroot)test/unit/junk_free.c \\\n\t$(srcroot)test/unit/lg_chunk.c \\\n\t$(srcroot)test/unit/mallctl.c \\\n\t$(srcroot)test/unit/math.c \\\n\t$(srcroot)test/unit/mq.c \\\n\t$(srcroot)test/unit/mtx.c \\\n\t$(srcroot)test/unit/ph.c \\\n\t$(srcroot)test/unit/prng.c \\\n\t$(srcroot)test/unit/prof_accum.c \\\n\t$(srcroot)test/unit/prof_active.c \\\n\t$(srcroot)test/unit/prof_gdump.c \\\n\t$(srcroot)test/unit/prof_idump.c \\\n\t$(srcroot)test/unit/prof_reset.c \\\n\t$(srcroot)test/unit/prof_thread_name.c \\\n\t$(srcroot)test/unit/ql.c \\\n\t$(srcroot)test/unit/qr.c \\\n\t$(srcroot)test/unit/quarantine.c \\\n\t$(srcroot)test/unit/rb.c \\\n\t$(srcroot)test/unit/rtree.c \\\n\t$(srcroot)test/unit/run_quantize.c \\\n\t$(srcroot)test/unit/SFMT.c \\\n\t$(srcroot)test/unit/size_classes.c \\\n\t$(srcroot)test/unit/smoothstep.c \\\n\t$(srcroot)test/unit/stats.c \\\n\t$(srcroot)test/unit/ticker.c \\\n\t$(srcroot)test/unit/nstime.c \\\n\t$(srcroot)test/unit/tsd.c \\\n\t$(srcroot)test/unit/util.c \\\n\t$(srcroot)test/unit/witness.c \\\n\t$(srcroot)test/unit/zero.c\nTESTS_INTEGRATION := $(srcroot)test/integration/aligned_alloc.c \\\n\t$(srcroot)test/integration/allocated.c \\\n\t$(srcroot)test/integration/sdallocx.c \\\n\t$(srcroot)test/integration/mallocx.c \\\n\t$(srcroot)test/integration/MALLOCX_ARENA.c \\\n\t$(srcroot)test/integration/overflow.c \\\n\t$(srcroot)test/integration/posix_memalign.c \\\n\t$(srcroot)test/integration/rallocx.c \\\n\t$(srcroot)test/integration/thread_arena.c \\\n\t$(srcroot)test/integration/thread_tcache_enabled.c \\\n\t$(srcroot)test/integration/xallocx.c \\\n\t$(srcroot)test/integration/chunk.c\nTESTS_STRESS := $(srcroot)test/stress/microbench.c\nTESTS := $(TESTS_UNIT) $(TESTS_INTEGRATION) $(TESTS_STRESS)\n\nC_OBJS := $(C_SRCS:$(srcroot)%.c=$(objroot)%.$(O))\nC_PIC_OBJS := $(C_SRCS:$(srcroot)%.c=$(objroot)%.pic.$(O))\nC_JET_OBJS := $(C_SRCS:$(srcroot)%.c=$(objroot)%.jet.$(O))\nC_TESTLIB_UNIT_OBJS := $(C_TESTLIB_SRCS:$(srcroot)%.c=$(objroot)%.unit.$(O))\nC_TESTLIB_INTEGRATION_OBJS := $(C_TESTLIB_SRCS:$(srcroot)%.c=$(objroot)%.integration.$(O))\nC_UTIL_INTEGRATION_OBJS := $(C_UTIL_INTEGRATION_SRCS:$(srcroot)%.c=$(objroot)%.integration.$(O))\nC_TESTLIB_STRESS_OBJS := $(C_TESTLIB_SRCS:$(srcroot)%.c=$(objroot)%.stress.$(O))\nC_TESTLIB_OBJS := $(C_TESTLIB_UNIT_OBJS) $(C_TESTLIB_INTEGRATION_OBJS) $(C_UTIL_INTEGRATION_OBJS) $(C_TESTLIB_STRESS_OBJS)\n\nTESTS_UNIT_OBJS := $(TESTS_UNIT:$(srcroot)%.c=$(objroot)%.$(O))\nTESTS_INTEGRATION_OBJS := $(TESTS_INTEGRATION:$(srcroot)%.c=$(objroot)%.$(O))\nTESTS_STRESS_OBJS := $(TESTS_STRESS:$(srcroot)%.c=$(objroot)%.$(O))\nTESTS_OBJS := $(TESTS_UNIT_OBJS) $(TESTS_INTEGRATION_OBJS) $(TESTS_STRESS_OBJS)\n\n.PHONY: all dist build_doc_html build_doc_man build_doc\n.PHONY: install_bin install_include install_lib\n.PHONY: install_doc_html install_doc_man install_doc install\n.PHONY: tests check clean distclean relclean\n\n.SECONDARY : $(TESTS_OBJS)\n\n# Default target.\nall: build_lib\n\ndist: build_doc\n\n$(objroot)doc/%.html : $(objroot)doc/%.xml $(srcroot)doc/stylesheet.xsl $(objroot)doc/html.xsl\n\t$(XSLTPROC) -o $@ $(objroot)doc/html.xsl $<\n\n$(objroot)doc/%.3 : $(objroot)doc/%.xml $(srcroot)doc/stylesheet.xsl $(objroot)doc/manpages.xsl\n\t$(XSLTPROC) -o $@ $(objroot)doc/manpages.xsl $<\n\nbuild_doc_html: $(DOCS_HTML)\nbuild_doc_man: $(DOCS_MAN3)\nbuild_doc: $(DOCS)\n\n#\n# Include generated dependency files.\n#\nifdef CC_MM\n-include $(C_OBJS:%.$(O)=%.d)\n-include $(C_PIC_OBJS:%.$(O)=%.d)\n-include $(C_JET_OBJS:%.$(O)=%.d)\n-include $(C_TESTLIB_OBJS:%.$(O)=%.d)\n-include $(TESTS_OBJS:%.$(O)=%.d)\nendif\n\n$(C_OBJS): $(objroot)src/%.$(O): $(srcroot)src/%.c\n$(C_PIC_OBJS): $(objroot)src/%.pic.$(O): $(srcroot)src/%.c\n$(C_PIC_OBJS): CFLAGS += $(PIC_CFLAGS)\n$(C_JET_OBJS): $(objroot)src/%.jet.$(O): $(srcroot)src/%.c\n$(C_JET_OBJS): CFLAGS += -DJEMALLOC_JET\n$(C_TESTLIB_UNIT_OBJS): $(objroot)test/src/%.unit.$(O): $(srcroot)test/src/%.c\n$(C_TESTLIB_UNIT_OBJS): CPPFLAGS += -DJEMALLOC_UNIT_TEST\n$(C_TESTLIB_INTEGRATION_OBJS): $(objroot)test/src/%.integration.$(O): $(srcroot)test/src/%.c\n$(C_TESTLIB_INTEGRATION_OBJS): CPPFLAGS += -DJEMALLOC_INTEGRATION_TEST\n$(C_UTIL_INTEGRATION_OBJS): $(objroot)src/%.integration.$(O): $(srcroot)src/%.c\n$(C_TESTLIB_STRESS_OBJS): $(objroot)test/src/%.stress.$(O): $(srcroot)test/src/%.c\n$(C_TESTLIB_STRESS_OBJS): CPPFLAGS += -DJEMALLOC_STRESS_TEST -DJEMALLOC_STRESS_TESTLIB\n$(C_TESTLIB_OBJS): CPPFLAGS += -I$(srcroot)test/include -I$(objroot)test/include\n$(TESTS_UNIT_OBJS): CPPFLAGS += -DJEMALLOC_UNIT_TEST\n$(TESTS_INTEGRATION_OBJS): CPPFLAGS += -DJEMALLOC_INTEGRATION_TEST\n$(TESTS_STRESS_OBJS): CPPFLAGS += -DJEMALLOC_STRESS_TEST\n$(TESTS_OBJS): $(objroot)test/%.$(O): $(srcroot)test/%.c\n$(TESTS_OBJS): CPPFLAGS += -I$(srcroot)test/include -I$(objroot)test/include\nifneq ($(IMPORTLIB),$(SO))\n$(C_OBJS) $(C_JET_OBJS): CPPFLAGS += -DDLLEXPORT\nendif\n\nifndef CC_MM\n# Dependencies.\nHEADER_DIRS = $(srcroot)include/jemalloc/internal \\\n\t$(objroot)include/jemalloc $(objroot)include/jemalloc/internal\nHEADERS = $(wildcard $(foreach dir,$(HEADER_DIRS),$(dir)/*.h))\n$(C_OBJS) $(C_PIC_OBJS) $(C_JET_OBJS) $(C_TESTLIB_OBJS) $(TESTS_OBJS): $(HEADERS)\n$(TESTS_OBJS): $(objroot)test/include/test/jemalloc_test.h\nendif\n\n$(C_OBJS) $(C_PIC_OBJS) $(C_JET_OBJS) $(C_TESTLIB_OBJS) $(TESTS_OBJS): %.$(O):\n\t@mkdir -p $(@D)\n\t$(CC) $(CFLAGS) -c $(CPPFLAGS) $(CTARGET) $<\nifdef CC_MM\n\t@$(CC) -MM $(CPPFLAGS) -MT $@ -o $(@:%.$(O)=%.d) $<\nendif\n\nifneq ($(SOREV),$(SO))\n%.$(SO) : %.$(SOREV)\n\t@mkdir -p $(@D)\n\tln -sf $(<F) $@\nendif\n\n$(objroot)lib/$(LIBJEMALLOC).$(SOREV) : $(if $(PIC_CFLAGS),$(C_PIC_OBJS),$(C_OBJS))\n\t@mkdir -p $(@D)\n\t$(CC) $(DSO_LDFLAGS) $(call RPATH,$(RPATH_EXTRA)) $(LDTARGET) $+ $(LDFLAGS) $(LIBS) $(EXTRA_LDFLAGS)\n\n$(objroot)lib/$(LIBJEMALLOC)_pic.$(A) : $(C_PIC_OBJS)\n$(objroot)lib/$(LIBJEMALLOC).$(A) : $(C_OBJS)\n$(objroot)lib/$(LIBJEMALLOC)_s.$(A) : $(C_OBJS)\n\n$(STATIC_LIBS):\n\t@mkdir -p $(@D)\n\t$(AR) $(ARFLAGS)@AROUT@ $+\n\n$(objroot)test/unit/%$(EXE): $(objroot)test/unit/%.$(O) $(TESTS_UNIT_LINK_OBJS) $(C_JET_OBJS) $(C_TESTLIB_UNIT_OBJS)\n\t@mkdir -p $(@D)\n\t$(CC) $(LDTARGET) $(filter %.$(O),$^) $(call RPATH,$(objroot)lib) $(LDFLAGS) $(filter-out -lm,$(LIBS)) -lm $(EXTRA_LDFLAGS)\n\n$(objroot)test/integration/%$(EXE): $(objroot)test/integration/%.$(O) $(C_TESTLIB_INTEGRATION_OBJS) $(C_UTIL_INTEGRATION_OBJS) $(objroot)lib/$(LIBJEMALLOC).$(IMPORTLIB)\n\t@mkdir -p $(@D)\n\t$(CC) $(LDTARGET) $(filter %.$(O),$^) $(call RPATH,$(objroot)lib) $(objroot)lib/$(LIBJEMALLOC).$(IMPORTLIB) $(LDFLAGS) $(filter-out -lm,$(filter -lpthread,$(LIBS))) -lm $(EXTRA_LDFLAGS)\n\n$(objroot)test/stress/%$(EXE): $(objroot)test/stress/%.$(O) $(C_JET_OBJS) $(C_TESTLIB_STRESS_OBJS) $(objroot)lib/$(LIBJEMALLOC).$(IMPORTLIB)\n\t@mkdir -p $(@D)\n\t$(CC) $(LDTARGET) $(filter %.$(O),$^) $(call RPATH,$(objroot)lib) $(objroot)lib/$(LIBJEMALLOC).$(IMPORTLIB) $(LDFLAGS) $(filter-out -lm,$(LIBS)) -lm $(EXTRA_LDFLAGS)\n\nbuild_lib_shared: $(DSOS)\nbuild_lib_static: $(STATIC_LIBS)\nbuild_lib: build_lib_shared build_lib_static\n\ninstall_bin:\n\tinstall -d $(BINDIR)\n\t@for b in $(BINS); do \\\n\techo \"install -m 755 $$b $(BINDIR)\"; \\\n\tinstall -m 755 $$b $(BINDIR); \\\ndone\n\ninstall_include:\n\tinstall -d $(INCLUDEDIR)/jemalloc\n\t@for h in $(C_HDRS); do \\\n\techo \"install -m 644 $$h $(INCLUDEDIR)/jemalloc\"; \\\n\tinstall -m 644 $$h $(INCLUDEDIR)/jemalloc; \\\ndone\n\ninstall_lib_shared: $(DSOS)\n\tinstall -d $(LIBDIR)\n\tinstall -m 755 $(objroot)lib/$(LIBJEMALLOC).$(SOREV) $(LIBDIR)\nifneq ($(SOREV),$(SO))\n\tln -sf $(LIBJEMALLOC).$(SOREV) $(LIBDIR)/$(LIBJEMALLOC).$(SO)\nendif\n\ninstall_lib_static: $(STATIC_LIBS)\n\tinstall -d $(LIBDIR)\n\t@for l in $(STATIC_LIBS); do \\\n\techo \"install -m 755 $$l $(LIBDIR)\"; \\\n\tinstall -m 755 $$l $(LIBDIR); \\\ndone\n\ninstall_lib_pc: $(PC)\n\tinstall -d $(LIBDIR)/pkgconfig\n\t@for l in $(PC); do \\\n\techo \"install -m 644 $$l $(LIBDIR)/pkgconfig\"; \\\n\tinstall -m 644 $$l $(LIBDIR)/pkgconfig; \\\ndone\n\ninstall_lib: install_lib_shared install_lib_static install_lib_pc\n\ninstall_doc_html:\n\tinstall -d $(DATADIR)/doc/jemalloc$(install_suffix)\n\t@for d in $(DOCS_HTML); do \\\n\techo \"install -m 644 $$d $(DATADIR)/doc/jemalloc$(install_suffix)\"; \\\n\tinstall -m 644 $$d $(DATADIR)/doc/jemalloc$(install_suffix); \\\ndone\n\ninstall_doc_man:\n\tinstall -d $(MANDIR)/man3\n\t@for d in $(DOCS_MAN3); do \\\n\techo \"install -m 644 $$d $(MANDIR)/man3\"; \\\n\tinstall -m 644 $$d $(MANDIR)/man3; \\\ndone\n\ninstall_doc: install_doc_html install_doc_man\n\ninstall: install_bin install_include install_lib install_doc\n\ntests_unit: $(TESTS_UNIT:$(srcroot)%.c=$(objroot)%$(EXE))\ntests_integration: $(TESTS_INTEGRATION:$(srcroot)%.c=$(objroot)%$(EXE))\ntests_stress: $(TESTS_STRESS:$(srcroot)%.c=$(objroot)%$(EXE))\ntests: tests_unit tests_integration tests_stress\n\ncheck_unit_dir:\n\t@mkdir -p $(objroot)test/unit\ncheck_integration_dir:\n\t@mkdir -p $(objroot)test/integration\nstress_dir:\n\t@mkdir -p $(objroot)test/stress\ncheck_dir: check_unit_dir check_integration_dir\n\ncheck_unit: tests_unit check_unit_dir\n\t$(MALLOC_CONF)=\"purge:ratio\" $(SHELL) $(objroot)test/test.sh $(TESTS_UNIT:$(srcroot)%.c=$(objroot)%)\n\t$(MALLOC_CONF)=\"purge:decay\" $(SHELL) $(objroot)test/test.sh $(TESTS_UNIT:$(srcroot)%.c=$(objroot)%)\ncheck_integration_prof: tests_integration check_integration_dir\nifeq ($(enable_prof), 1)\n\t$(MALLOC_CONF)=\"prof:true\" $(SHELL) $(objroot)test/test.sh $(TESTS_INTEGRATION:$(srcroot)%.c=$(objroot)%)\n\t$(MALLOC_CONF)=\"prof:true,prof_active:false\" $(SHELL) $(objroot)test/test.sh $(TESTS_INTEGRATION:$(srcroot)%.c=$(objroot)%)\nendif\ncheck_integration_decay: tests_integration check_integration_dir\n\t$(MALLOC_CONF)=\"purge:decay,decay_time:-1\" $(SHELL) $(objroot)test/test.sh $(TESTS_INTEGRATION:$(srcroot)%.c=$(objroot)%)\n\t$(MALLOC_CONF)=\"purge:decay,decay_time:0\" $(SHELL) $(objroot)test/test.sh $(TESTS_INTEGRATION:$(srcroot)%.c=$(objroot)%)\n\t$(MALLOC_CONF)=\"purge:decay\" $(SHELL) $(objroot)test/test.sh $(TESTS_INTEGRATION:$(srcroot)%.c=$(objroot)%)\ncheck_integration: tests_integration check_integration_dir\n\t$(SHELL) $(objroot)test/test.sh $(TESTS_INTEGRATION:$(srcroot)%.c=$(objroot)%)\nstress: tests_stress stress_dir\n\t$(SHELL) $(objroot)test/test.sh $(TESTS_STRESS:$(srcroot)%.c=$(objroot)%)\ncheck: check_unit check_integration check_integration_decay check_integration_prof\n\nifeq ($(enable_code_coverage), 1)\ncoverage_unit: check_unit\n\t$(SHELL) $(srcroot)coverage.sh $(srcroot)src jet $(C_JET_OBJS)\n\t$(SHELL) $(srcroot)coverage.sh $(srcroot)test/src unit $(C_TESTLIB_UNIT_OBJS)\n\t$(SHELL) $(srcroot)coverage.sh $(srcroot)test/unit unit $(TESTS_UNIT_OBJS)\n\ncoverage_integration: check_integration\n\t$(SHELL) $(srcroot)coverage.sh $(srcroot)src pic $(C_PIC_OBJS)\n\t$(SHELL) $(srcroot)coverage.sh $(srcroot)src integration $(C_UTIL_INTEGRATION_OBJS)\n\t$(SHELL) $(srcroot)coverage.sh $(srcroot)test/src integration $(C_TESTLIB_INTEGRATION_OBJS)\n\t$(SHELL) $(srcroot)coverage.sh $(srcroot)test/integration integration $(TESTS_INTEGRATION_OBJS)\n\ncoverage_stress: stress\n\t$(SHELL) $(srcroot)coverage.sh $(srcroot)src pic $(C_PIC_OBJS)\n\t$(SHELL) $(srcroot)coverage.sh $(srcroot)src jet $(C_JET_OBJS)\n\t$(SHELL) $(srcroot)coverage.sh $(srcroot)test/src stress $(C_TESTLIB_STRESS_OBJS)\n\t$(SHELL) $(srcroot)coverage.sh $(srcroot)test/stress stress $(TESTS_STRESS_OBJS)\n\ncoverage: check\n\t$(SHELL) $(srcroot)coverage.sh $(srcroot)src pic $(C_PIC_OBJS)\n\t$(SHELL) $(srcroot)coverage.sh $(srcroot)src jet $(C_JET_OBJS)\n\t$(SHELL) $(srcroot)coverage.sh $(srcroot)src integration $(C_UTIL_INTEGRATION_OBJS)\n\t$(SHELL) $(srcroot)coverage.sh $(srcroot)test/src unit $(C_TESTLIB_UNIT_OBJS)\n\t$(SHELL) $(srcroot)coverage.sh $(srcroot)test/src integration $(C_TESTLIB_INTEGRATION_OBJS)\n\t$(SHELL) $(srcroot)coverage.sh $(srcroot)test/src stress $(C_TESTLIB_STRESS_OBJS)\n\t$(SHELL) $(srcroot)coverage.sh $(srcroot)test/unit unit $(TESTS_UNIT_OBJS) $(TESTS_UNIT_AUX_OBJS)\n\t$(SHELL) $(srcroot)coverage.sh $(srcroot)test/integration integration $(TESTS_INTEGRATION_OBJS)\n\t$(SHELL) $(srcroot)coverage.sh $(srcroot)test/stress integration $(TESTS_STRESS_OBJS)\nendif\n\nclean:\n\trm -f $(C_OBJS)\n\trm -f $(C_PIC_OBJS)\n\trm -f $(C_JET_OBJS)\n\trm -f $(C_TESTLIB_OBJS)\n\trm -f $(C_OBJS:%.$(O)=%.d)\n\trm -f $(C_OBJS:%.$(O)=%.gcda)\n\trm -f $(C_OBJS:%.$(O)=%.gcno)\n\trm -f $(C_PIC_OBJS:%.$(O)=%.d)\n\trm -f $(C_PIC_OBJS:%.$(O)=%.gcda)\n\trm -f $(C_PIC_OBJS:%.$(O)=%.gcno)\n\trm -f $(C_JET_OBJS:%.$(O)=%.d)\n\trm -f $(C_JET_OBJS:%.$(O)=%.gcda)\n\trm -f $(C_JET_OBJS:%.$(O)=%.gcno)\n\trm -f $(C_TESTLIB_OBJS:%.$(O)=%.d)\n\trm -f $(C_TESTLIB_OBJS:%.$(O)=%.gcda)\n\trm -f $(C_TESTLIB_OBJS:%.$(O)=%.gcno)\n\trm -f $(TESTS_OBJS:%.$(O)=%$(EXE))\n\trm -f $(TESTS_OBJS)\n\trm -f $(TESTS_OBJS:%.$(O)=%.d)\n\trm -f $(TESTS_OBJS:%.$(O)=%.gcda)\n\trm -f $(TESTS_OBJS:%.$(O)=%.gcno)\n\trm -f $(TESTS_OBJS:%.$(O)=%.out)\n\trm -f $(DSOS) $(STATIC_LIBS)\n\trm -f $(objroot)*.gcov.*\n\ndistclean: clean\n\trm -f $(objroot)bin/jemalloc-config\n\trm -f $(objroot)bin/jemalloc.sh\n\trm -f $(objroot)bin/jeprof\n\trm -f $(objroot)config.log\n\trm -f $(objroot)config.status\n\trm -f $(objroot)config.stamp\n\trm -f $(cfghdrs_out)\n\trm -f $(cfgoutputs_out)\n\nrelclean: distclean\n\trm -f $(objroot)configure\n\trm -f $(objroot)VERSION\n\trm -f $(DOCS_HTML)\n\trm -f $(DOCS_MAN3)\n\n#===============================================================================\n# Re-configuration rules.\n\nifeq ($(enable_autogen), 1)\n$(srcroot)configure : $(srcroot)configure.ac\n\tcd ./$(srcroot) && $(AUTOCONF)\n\n$(objroot)config.status : $(srcroot)configure\n\t./$(objroot)config.status --recheck\n\n$(srcroot)config.stamp.in : $(srcroot)configure.ac\n\techo stamp > $(srcroot)config.stamp.in\n\n$(objroot)config.stamp : $(cfgoutputs_in) $(cfghdrs_in) $(srcroot)configure\n\t./$(objroot)config.status\n\t@touch $@\n\n# There must be some action in order for make to re-read Makefile when it is\n# out of date.\n$(cfgoutputs_out) $(cfghdrs_out) : $(objroot)config.stamp\n\t@true\nendif\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/deps/jemalloc/README",
    "content": "jemalloc is a general purpose malloc(3) implementation that emphasizes\nfragmentation avoidance and scalable concurrency support.  jemalloc first came\ninto use as the FreeBSD libc allocator in 2005, and since then it has found its\nway into numerous applications that rely on its predictable behavior.  In 2010\njemalloc development efforts broadened to include developer support features\nsuch as heap profiling, Valgrind integration, and extensive monitoring/tuning\nhooks.  Modern jemalloc releases continue to be integrated back into FreeBSD,\nand therefore versatility remains critical.  Ongoing development efforts trend\ntoward making jemalloc among the best allocators for a broad range of demanding\napplications, and eliminating/mitigating weaknesses that have practical\nrepercussions for real world applications.\n\nThe COPYING file contains copyright and licensing information.\n\nThe INSTALL file contains information on how to configure, build, and install\njemalloc.\n\nThe ChangeLog file contains a brief summary of changes for each release.\n\nURL: http://www.canonware.com/jemalloc/\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/deps/jemalloc/autogen.sh",
    "content": "#!/bin/sh\n\nfor i in autoconf; do\n    echo \"$i\"\n    $i\n    if [ $? -ne 0 ]; then\n\techo \"Error $? in $i\"\n\texit 1\n    fi\ndone\n\necho \"./configure --enable-autogen $@\"\n./configure --enable-autogen $@\nif [ $? -ne 0 ]; then\n    echo \"Error $? in ./configure\"\n    exit 1\nfi\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/deps/jemalloc/bin/jemalloc-config.in",
    "content": "#!/bin/sh\n\nusage() {\n\tcat <<EOF\nUsage:\n  @BINDIR@/jemalloc-config <option>\nOptions:\n  --help | -h  : Print usage.\n  --version    : Print jemalloc version.\n  --revision   : Print shared library revision number.\n  --config     : Print configure options used to build jemalloc.\n  --prefix     : Print installation directory prefix.\n  --bindir     : Print binary installation directory.\n  --datadir    : Print data installation directory.\n  --includedir : Print include installation directory.\n  --libdir     : Print library installation directory.\n  --mandir     : Print manual page installation directory.\n  --cc         : Print compiler used to build jemalloc.\n  --cflags     : Print compiler flags used to build jemalloc.\n  --cppflags   : Print preprocessor flags used to build jemalloc.\n  --ldflags    : Print library flags used to build jemalloc.\n  --libs       : Print libraries jemalloc was linked against.\nEOF\n}\n\nprefix=\"@prefix@\"\nexec_prefix=\"@exec_prefix@\"\n\ncase \"$1\" in\n--help | -h)\n\tusage\n\texit 0\n\t;;\n--version)\n\techo \"@jemalloc_version@\"\n\t;;\n--revision)\n\techo \"@rev@\"\n\t;;\n--config)\n\techo \"@CONFIG@\"\n\t;;\n--prefix)\n\techo \"@PREFIX@\"\n\t;;\n--bindir)\n\techo \"@BINDIR@\"\n\t;;\n--datadir)\n\techo \"@DATADIR@\"\n\t;;\n--includedir)\n\techo \"@INCLUDEDIR@\"\n\t;;\n--libdir)\n\techo \"@LIBDIR@\"\n\t;;\n--mandir)\n\techo \"@MANDIR@\"\n\t;;\n--cc)\n\techo \"@CC@\"\n\t;;\n--cflags)\n\techo \"@CFLAGS@\"\n\t;;\n--cppflags)\n\techo \"@CPPFLAGS@\"\n\t;;\n--ldflags)\n\techo \"@LDFLAGS@ @EXTRA_LDFLAGS@\"\n\t;;\n--libs)\n\techo \"@LIBS@\"\n\t;;\n*)\n\tusage\n\texit 1\nesac\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/deps/jemalloc/bin/jemalloc.sh.in",
    "content": "#!/bin/sh\n\nprefix=@prefix@\nexec_prefix=@exec_prefix@\nlibdir=@libdir@\n\n@LD_PRELOAD_VAR@=${libdir}/libjemalloc.@SOREV@\nexport @LD_PRELOAD_VAR@\nexec \"$@\"\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/deps/jemalloc/bin/jeprof.in",
    "content": "#! /usr/bin/env perl\n\n# Copyright (c) 1998-2007, Google Inc.\n# All rights reserved.\n#\n# Redistribution and use in source and binary forms, with or without\n# modification, are permitted provided that the following conditions are\n# met:\n#\n#     * Redistributions of source code must retain the above copyright\n# notice, this list of conditions and the following disclaimer.\n#     * Redistributions in binary form must reproduce the above\n# copyright notice, this list of conditions and the following disclaimer\n# in the documentation and/or other materials provided with the\n# distribution.\n#     * Neither the name of Google Inc. nor the names of its\n# contributors may be used to endorse or promote products derived from\n# this software without specific prior written permission.\n#\n# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n# \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\n# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\n# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\n# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\n# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n\n# ---\n# Program for printing the profile generated by common/profiler.cc,\n# or by the heap profiler (common/debugallocation.cc)\n#\n# The profile contains a sequence of entries of the form:\n#       <count> <stack trace>\n# This program parses the profile, and generates user-readable\n# output.\n#\n# Examples:\n#\n# % tools/jeprof \"program\" \"profile\"\n#   Enters \"interactive\" mode\n#\n# % tools/jeprof --text \"program\" \"profile\"\n#   Generates one line per procedure\n#\n# % tools/jeprof --gv \"program\" \"profile\"\n#   Generates annotated call-graph and displays via \"gv\"\n#\n# % tools/jeprof --gv --focus=Mutex \"program\" \"profile\"\n#   Restrict to code paths that involve an entry that matches \"Mutex\"\n#\n# % tools/jeprof --gv --focus=Mutex --ignore=string \"program\" \"profile\"\n#   Restrict to code paths that involve an entry that matches \"Mutex\"\n#   and does not match \"string\"\n#\n# % tools/jeprof --list=IBF_CheckDocid \"program\" \"profile\"\n#   Generates disassembly listing of all routines with at least one\n#   sample that match the --list=<regexp> pattern.  The listing is\n#   annotated with the flat and cumulative sample counts at each line.\n#\n# % tools/jeprof --disasm=IBF_CheckDocid \"program\" \"profile\"\n#   Generates disassembly listing of all routines with at least one\n#   sample that match the --disasm=<regexp> pattern.  The listing is\n#   annotated with the flat and cumulative sample counts at each PC value.\n#\n# TODO: Use color to indicate files?\n\nuse strict;\nuse warnings;\nuse Getopt::Long;\n\nmy $JEPROF_VERSION = \"@jemalloc_version@\";\nmy $PPROF_VERSION = \"2.0\";\n\n# These are the object tools we use which can come from a\n# user-specified location using --tools, from the JEPROF_TOOLS\n# environment variable, or from the environment.\nmy %obj_tool_map = (\n  \"objdump\" => \"objdump\",\n  \"nm\" => \"nm\",\n  \"addr2line\" => \"addr2line\",\n  \"c++filt\" => \"c++filt\",\n  ## ConfigureObjTools may add architecture-specific entries:\n  #\"nm_pdb\" => \"nm-pdb\",       # for reading windows (PDB-format) executables\n  #\"addr2line_pdb\" => \"addr2line-pdb\",                                # ditto\n  #\"otool\" => \"otool\",         # equivalent of objdump on OS X\n);\n# NOTE: these are lists, so you can put in commandline flags if you want.\nmy @DOT = (\"dot\");          # leave non-absolute, since it may be in /usr/local\nmy @GV = (\"gv\");\nmy @EVINCE = (\"evince\");    # could also be xpdf or perhaps acroread\nmy @KCACHEGRIND = (\"kcachegrind\");\nmy @PS2PDF = (\"ps2pdf\");\n# These are used for dynamic profiles\nmy @URL_FETCHER = (\"curl\", \"-s\", \"--fail\");\n\n# These are the web pages that servers need to support for dynamic profiles\nmy $HEAP_PAGE = \"/pprof/heap\";\nmy $PROFILE_PAGE = \"/pprof/profile\";   # must support cgi-param \"?seconds=#\"\nmy $PMUPROFILE_PAGE = \"/pprof/pmuprofile(?:\\\\?.*)?\"; # must support cgi-param\n                                                # ?seconds=#&event=x&period=n\nmy $GROWTH_PAGE = \"/pprof/growth\";\nmy $CONTENTION_PAGE = \"/pprof/contention\";\nmy $WALL_PAGE = \"/pprof/wall(?:\\\\?.*)?\";  # accepts options like namefilter\nmy $FILTEREDPROFILE_PAGE = \"/pprof/filteredprofile(?:\\\\?.*)?\";\nmy $CENSUSPROFILE_PAGE = \"/pprof/censusprofile(?:\\\\?.*)?\"; # must support cgi-param\n                                                       # \"?seconds=#\",\n                                                       # \"?tags_regexp=#\" and\n                                                       # \"?type=#\".\nmy $SYMBOL_PAGE = \"/pprof/symbol\";     # must support symbol lookup via POST\nmy $PROGRAM_NAME_PAGE = \"/pprof/cmdline\";\n\n# These are the web pages that can be named on the command line.\n# All the alternatives must begin with /.\nmy $PROFILES = \"($HEAP_PAGE|$PROFILE_PAGE|$PMUPROFILE_PAGE|\" .\n               \"$GROWTH_PAGE|$CONTENTION_PAGE|$WALL_PAGE|\" .\n               \"$FILTEREDPROFILE_PAGE|$CENSUSPROFILE_PAGE)\";\n\n# default binary name\nmy $UNKNOWN_BINARY = \"(unknown)\";\n\n# There is a pervasive dependency on the length (in hex characters,\n# i.e., nibbles) of an address, distinguishing between 32-bit and\n# 64-bit profiles.  To err on the safe size, default to 64-bit here:\nmy $address_length = 16;\n\nmy $dev_null = \"/dev/null\";\nif (! -e $dev_null && $^O =~ /MSWin/) {    # $^O is the OS perl was built for\n  $dev_null = \"nul\";\n}\n\n# A list of paths to search for shared object files\nmy @prefix_list = ();\n\n# Special routine name that should not have any symbols.\n# Used as separator to parse \"addr2line -i\" output.\nmy $sep_symbol = '_fini';\nmy $sep_address = undef;\n\n##### Argument parsing #####\n\nsub usage_string {\n  return <<EOF;\nUsage:\njeprof [options] <program> <profiles>\n   <profiles> is a space separated list of profile names.\njeprof [options] <symbolized-profiles>\n   <symbolized-profiles> is a list of profile files where each file contains\n   the necessary symbol mappings  as well as profile data (likely generated\n   with --raw).\njeprof [options] <profile>\n   <profile> is a remote form.  Symbols are obtained from host:port$SYMBOL_PAGE\n\n   Each name can be:\n   /path/to/profile        - a path to a profile file\n   host:port[/<service>]   - a location of a service to get profile from\n\n   The /<service> can be $HEAP_PAGE, $PROFILE_PAGE, /pprof/pmuprofile,\n                         $GROWTH_PAGE, $CONTENTION_PAGE, /pprof/wall,\n                         $CENSUSPROFILE_PAGE, or /pprof/filteredprofile.\n   For instance:\n     jeprof http://myserver.com:80$HEAP_PAGE\n   If /<service> is omitted, the service defaults to $PROFILE_PAGE (cpu profiling).\njeprof --symbols <program>\n   Maps addresses to symbol names.  In this mode, stdin should be a\n   list of library mappings, in the same format as is found in the heap-\n   and cpu-profile files (this loosely matches that of /proc/self/maps\n   on linux), followed by a list of hex addresses to map, one per line.\n\n   For more help with querying remote servers, including how to add the\n   necessary server-side support code, see this filename (or one like it):\n\n   /usr/doc/gperftools-$PPROF_VERSION/pprof_remote_servers.html\n\nOptions:\n   --cum               Sort by cumulative data\n   --base=<base>       Subtract <base> from <profile> before display\n   --interactive       Run in interactive mode (interactive \"help\" gives help) [default]\n   --seconds=<n>       Length of time for dynamic profiles [default=30 secs]\n   --add_lib=<file>    Read additional symbols and line info from the given library\n   --lib_prefix=<dir>  Comma separated list of library path prefixes\n\nReporting Granularity:\n   --addresses         Report at address level\n   --lines             Report at source line level\n   --functions         Report at function level [default]\n   --files             Report at source file level\n\nOutput type:\n   --text              Generate text report\n   --callgrind         Generate callgrind format to stdout\n   --gv                Generate Postscript and display\n   --evince            Generate PDF and display\n   --web               Generate SVG and display\n   --list=<regexp>     Generate source listing of matching routines\n   --disasm=<regexp>   Generate disassembly of matching routines\n   --symbols           Print demangled symbol names found at given addresses\n   --dot               Generate DOT file to stdout\n   --ps                Generate Postcript to stdout\n   --pdf               Generate PDF to stdout\n   --svg               Generate SVG to stdout\n   --gif               Generate GIF to stdout\n   --raw               Generate symbolized jeprof data (useful with remote fetch)\n\nHeap-Profile Options:\n   --inuse_space       Display in-use (mega)bytes [default]\n   --inuse_objects     Display in-use objects\n   --alloc_space       Display allocated (mega)bytes\n   --alloc_objects     Display allocated objects\n   --show_bytes        Display space in bytes\n   --drop_negative     Ignore negative differences\n\nContention-profile options:\n   --total_delay       Display total delay at each region [default]\n   --contentions       Display number of delays at each region\n   --mean_delay        Display mean delay at each region\n\nCall-graph Options:\n   --nodecount=<n>     Show at most so many nodes [default=80]\n   --nodefraction=<f>  Hide nodes below <f>*total [default=.005]\n   --edgefraction=<f>  Hide edges below <f>*total [default=.001]\n   --maxdegree=<n>     Max incoming/outgoing edges per node [default=8]\n   --focus=<regexp>    Focus on backtraces with nodes matching <regexp>\n   --thread=<n>        Show profile for thread <n>\n   --ignore=<regexp>   Ignore backtraces with nodes matching <regexp>\n   --scale=<n>         Set GV scaling [default=0]\n   --heapcheck         Make nodes with non-0 object counts\n                       (i.e. direct leak generators) more visible\n   --retain=<regexp>   Retain only nodes that match <regexp>\n   --exclude=<regexp>  Exclude all nodes that match <regexp>\n\nMiscellaneous:\n   --tools=<prefix or binary:fullpath>[,...]   \\$PATH for object tool pathnames\n   --test              Run unit tests\n   --help              This message\n   --version           Version information\n\nEnvironment Variables:\n   JEPROF_TMPDIR        Profiles directory. Defaults to \\$HOME/jeprof\n   JEPROF_TOOLS         Prefix for object tools pathnames\n\nExamples:\n\njeprof /bin/ls ls.prof\n                       Enters \"interactive\" mode\njeprof --text /bin/ls ls.prof\n                       Outputs one line per procedure\njeprof --web /bin/ls ls.prof\n                       Displays annotated call-graph in web browser\njeprof --gv /bin/ls ls.prof\n                       Displays annotated call-graph via 'gv'\njeprof --gv --focus=Mutex /bin/ls ls.prof\n                       Restricts to code paths including a .*Mutex.* entry\njeprof --gv --focus=Mutex --ignore=string /bin/ls ls.prof\n                       Code paths including Mutex but not string\njeprof --list=getdir /bin/ls ls.prof\n                       (Per-line) annotated source listing for getdir()\njeprof --disasm=getdir /bin/ls ls.prof\n                       (Per-PC) annotated disassembly for getdir()\n\njeprof http://localhost:1234/\n                       Enters \"interactive\" mode\njeprof --text localhost:1234\n                       Outputs one line per procedure for localhost:1234\njeprof --raw localhost:1234 > ./local.raw\njeprof --text ./local.raw\n                       Fetches a remote profile for later analysis and then\n                       analyzes it in text mode.\nEOF\n}\n\nsub version_string {\n  return <<EOF\njeprof (part of jemalloc $JEPROF_VERSION)\nbased on pprof (part of gperftools $PPROF_VERSION)\n\nCopyright 1998-2007 Google Inc.\n\nThis is BSD licensed software; see the source for copying conditions\nand license information.\nThere is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A\nPARTICULAR PURPOSE.\nEOF\n}\n\nsub usage {\n  my $msg = shift;\n  print STDERR \"$msg\\n\\n\";\n  print STDERR usage_string();\n  print STDERR \"\\nFATAL ERROR: $msg\\n\";    # just as a reminder\n  exit(1);\n}\n\nsub Init() {\n  # Setup tmp-file name and handler to clean it up.\n  # We do this in the very beginning so that we can use\n  # error() and cleanup() function anytime here after.\n  $main::tmpfile_sym = \"/tmp/jeprof$$.sym\";\n  $main::tmpfile_ps = \"/tmp/jeprof$$\";\n  $main::next_tmpfile = 0;\n  $SIG{'INT'} = \\&sighandler;\n\n  # Cache from filename/linenumber to source code\n  $main::source_cache = ();\n\n  $main::opt_help = 0;\n  $main::opt_version = 0;\n\n  $main::opt_cum = 0;\n  $main::opt_base = '';\n  $main::opt_addresses = 0;\n  $main::opt_lines = 0;\n  $main::opt_functions = 0;\n  $main::opt_files = 0;\n  $main::opt_lib_prefix = \"\";\n\n  $main::opt_text = 0;\n  $main::opt_callgrind = 0;\n  $main::opt_list = \"\";\n  $main::opt_disasm = \"\";\n  $main::opt_symbols = 0;\n  $main::opt_gv = 0;\n  $main::opt_evince = 0;\n  $main::opt_web = 0;\n  $main::opt_dot = 0;\n  $main::opt_ps = 0;\n  $main::opt_pdf = 0;\n  $main::opt_gif = 0;\n  $main::opt_svg = 0;\n  $main::opt_raw = 0;\n\n  $main::opt_nodecount = 80;\n  $main::opt_nodefraction = 0.005;\n  $main::opt_edgefraction = 0.001;\n  $main::opt_maxdegree = 8;\n  $main::opt_focus = '';\n  $main::opt_thread = undef;\n  $main::opt_ignore = '';\n  $main::opt_scale = 0;\n  $main::opt_heapcheck = 0;\n  $main::opt_retain = '';\n  $main::opt_exclude = '';\n  $main::opt_seconds = 30;\n  $main::opt_lib = \"\";\n\n  $main::opt_inuse_space   = 0;\n  $main::opt_inuse_objects = 0;\n  $main::opt_alloc_space   = 0;\n  $main::opt_alloc_objects = 0;\n  $main::opt_show_bytes    = 0;\n  $main::opt_drop_negative = 0;\n  $main::opt_interactive   = 0;\n\n  $main::opt_total_delay = 0;\n  $main::opt_contentions = 0;\n  $main::opt_mean_delay = 0;\n\n  $main::opt_tools   = \"\";\n  $main::opt_debug   = 0;\n  $main::opt_test    = 0;\n\n  # These are undocumented flags used only by unittests.\n  $main::opt_test_stride = 0;\n\n  # Are we using $SYMBOL_PAGE?\n  $main::use_symbol_page = 0;\n\n  # Files returned by TempName.\n  %main::tempnames = ();\n\n  # Type of profile we are dealing with\n  # Supported types:\n  #     cpu\n  #     heap\n  #     growth\n  #     contention\n  $main::profile_type = '';     # Empty type means \"unknown\"\n\n  GetOptions(\"help!\"          => \\$main::opt_help,\n             \"version!\"       => \\$main::opt_version,\n             \"cum!\"           => \\$main::opt_cum,\n             \"base=s\"         => \\$main::opt_base,\n             \"seconds=i\"      => \\$main::opt_seconds,\n             \"add_lib=s\"      => \\$main::opt_lib,\n             \"lib_prefix=s\"   => \\$main::opt_lib_prefix,\n             \"functions!\"     => \\$main::opt_functions,\n             \"lines!\"         => \\$main::opt_lines,\n             \"addresses!\"     => \\$main::opt_addresses,\n             \"files!\"         => \\$main::opt_files,\n             \"text!\"          => \\$main::opt_text,\n             \"callgrind!\"     => \\$main::opt_callgrind,\n             \"list=s\"         => \\$main::opt_list,\n             \"disasm=s\"       => \\$main::opt_disasm,\n             \"symbols!\"       => \\$main::opt_symbols,\n             \"gv!\"            => \\$main::opt_gv,\n             \"evince!\"        => \\$main::opt_evince,\n             \"web!\"           => \\$main::opt_web,\n             \"dot!\"           => \\$main::opt_dot,\n             \"ps!\"            => \\$main::opt_ps,\n             \"pdf!\"           => \\$main::opt_pdf,\n             \"svg!\"           => \\$main::opt_svg,\n             \"gif!\"           => \\$main::opt_gif,\n             \"raw!\"           => \\$main::opt_raw,\n             \"interactive!\"   => \\$main::opt_interactive,\n             \"nodecount=i\"    => \\$main::opt_nodecount,\n             \"nodefraction=f\" => \\$main::opt_nodefraction,\n             \"edgefraction=f\" => \\$main::opt_edgefraction,\n             \"maxdegree=i\"    => \\$main::opt_maxdegree,\n             \"focus=s\"        => \\$main::opt_focus,\n             \"thread=s\"       => \\$main::opt_thread,\n             \"ignore=s\"       => \\$main::opt_ignore,\n             \"scale=i\"        => \\$main::opt_scale,\n             \"heapcheck\"      => \\$main::opt_heapcheck,\n             \"retain=s\"       => \\$main::opt_retain,\n             \"exclude=s\"      => \\$main::opt_exclude,\n             \"inuse_space!\"   => \\$main::opt_inuse_space,\n             \"inuse_objects!\" => \\$main::opt_inuse_objects,\n             \"alloc_space!\"   => \\$main::opt_alloc_space,\n             \"alloc_objects!\" => \\$main::opt_alloc_objects,\n             \"show_bytes!\"    => \\$main::opt_show_bytes,\n             \"drop_negative!\" => \\$main::opt_drop_negative,\n             \"total_delay!\"   => \\$main::opt_total_delay,\n             \"contentions!\"   => \\$main::opt_contentions,\n             \"mean_delay!\"    => \\$main::opt_mean_delay,\n             \"tools=s\"        => \\$main::opt_tools,\n             \"test!\"          => \\$main::opt_test,\n             \"debug!\"         => \\$main::opt_debug,\n             # Undocumented flags used only by unittests:\n             \"test_stride=i\"  => \\$main::opt_test_stride,\n      ) || usage(\"Invalid option(s)\");\n\n  # Deal with the standard --help and --version\n  if ($main::opt_help) {\n    print usage_string();\n    exit(0);\n  }\n\n  if ($main::opt_version) {\n    print version_string();\n    exit(0);\n  }\n\n  # Disassembly/listing/symbols mode requires address-level info\n  if ($main::opt_disasm || $main::opt_list || $main::opt_symbols) {\n    $main::opt_functions = 0;\n    $main::opt_lines = 0;\n    $main::opt_addresses = 1;\n    $main::opt_files = 0;\n  }\n\n  # Check heap-profiling flags\n  if ($main::opt_inuse_space +\n      $main::opt_inuse_objects +\n      $main::opt_alloc_space +\n      $main::opt_alloc_objects > 1) {\n    usage(\"Specify at most on of --inuse/--alloc options\");\n  }\n\n  # Check output granularities\n  my $grains =\n      $main::opt_functions +\n      $main::opt_lines +\n      $main::opt_addresses +\n      $main::opt_files +\n      0;\n  if ($grains > 1) {\n    usage(\"Only specify one output granularity option\");\n  }\n  if ($grains == 0) {\n    $main::opt_functions = 1;\n  }\n\n  # Check output modes\n  my $modes =\n      $main::opt_text +\n      $main::opt_callgrind +\n      ($main::opt_list eq '' ? 0 : 1) +\n      ($main::opt_disasm eq '' ? 0 : 1) +\n      ($main::opt_symbols == 0 ? 0 : 1) +\n      $main::opt_gv +\n      $main::opt_evince +\n      $main::opt_web +\n      $main::opt_dot +\n      $main::opt_ps +\n      $main::opt_pdf +\n      $main::opt_svg +\n      $main::opt_gif +\n      $main::opt_raw +\n      $main::opt_interactive +\n      0;\n  if ($modes > 1) {\n    usage(\"Only specify one output mode\");\n  }\n  if ($modes == 0) {\n    if (-t STDOUT) {  # If STDOUT is a tty, activate interactive mode\n      $main::opt_interactive = 1;\n    } else {\n      $main::opt_text = 1;\n    }\n  }\n\n  if ($main::opt_test) {\n    RunUnitTests();\n    # Should not return\n    exit(1);\n  }\n\n  # Binary name and profile arguments list\n  $main::prog = \"\";\n  @main::pfile_args = ();\n\n  # Remote profiling without a binary (using $SYMBOL_PAGE instead)\n  if (@ARGV > 0) {\n    if (IsProfileURL($ARGV[0])) {\n      $main::use_symbol_page = 1;\n    } elsif (IsSymbolizedProfileFile($ARGV[0])) {\n      $main::use_symbolized_profile = 1;\n      $main::prog = $UNKNOWN_BINARY;  # will be set later from the profile file\n    }\n  }\n\n  if ($main::use_symbol_page || $main::use_symbolized_profile) {\n    # We don't need a binary!\n    my %disabled = ('--lines' => $main::opt_lines,\n                    '--disasm' => $main::opt_disasm);\n    for my $option (keys %disabled) {\n      usage(\"$option cannot be used without a binary\") if $disabled{$option};\n    }\n    # Set $main::prog later...\n    scalar(@ARGV) || usage(\"Did not specify profile file\");\n  } elsif ($main::opt_symbols) {\n    # --symbols needs a binary-name (to run nm on, etc) but not profiles\n    $main::prog = shift(@ARGV) || usage(\"Did not specify program\");\n  } else {\n    $main::prog = shift(@ARGV) || usage(\"Did not specify program\");\n    scalar(@ARGV) || usage(\"Did not specify profile file\");\n  }\n\n  # Parse profile file/location arguments\n  foreach my $farg (@ARGV) {\n    if ($farg =~ m/(.*)\\@([0-9]+)(|\\/.*)$/ ) {\n      my $machine = $1;\n      my $num_machines = $2;\n      my $path = $3;\n      for (my $i = 0; $i < $num_machines; $i++) {\n        unshift(@main::pfile_args, \"$i.$machine$path\");\n      }\n    } else {\n      unshift(@main::pfile_args, $farg);\n    }\n  }\n\n  if ($main::use_symbol_page) {\n    unless (IsProfileURL($main::pfile_args[0])) {\n      error(\"The first profile should be a remote form to use $SYMBOL_PAGE\\n\");\n    }\n    CheckSymbolPage();\n    $main::prog = FetchProgramName();\n  } elsif (!$main::use_symbolized_profile) {  # may not need objtools!\n    ConfigureObjTools($main::prog)\n  }\n\n  # Break the opt_lib_prefix into the prefix_list array\n  @prefix_list = split (',', $main::opt_lib_prefix);\n\n  # Remove trailing / from the prefixes, in the list to prevent\n  # searching things like /my/path//lib/mylib.so\n  foreach (@prefix_list) {\n    s|/+$||;\n  }\n}\n\nsub FilterAndPrint {\n  my ($profile, $symbols, $libs, $thread) = @_;\n\n  # Get total data in profile\n  my $total = TotalProfile($profile);\n\n  # Remove uniniteresting stack items\n  $profile = RemoveUninterestingFrames($symbols, $profile);\n\n  # Focus?\n  if ($main::opt_focus ne '') {\n    $profile = FocusProfile($symbols, $profile, $main::opt_focus);\n  }\n\n  # Ignore?\n  if ($main::opt_ignore ne '') {\n    $profile = IgnoreProfile($symbols, $profile, $main::opt_ignore);\n  }\n\n  my $calls = ExtractCalls($symbols, $profile);\n\n  # Reduce profiles to required output granularity, and also clean\n  # each stack trace so a given entry exists at most once.\n  my $reduced = ReduceProfile($symbols, $profile);\n\n  # Get derived profiles\n  my $flat = FlatProfile($reduced);\n  my $cumulative = CumulativeProfile($reduced);\n\n  # Print\n  if (!$main::opt_interactive) {\n    if ($main::opt_disasm) {\n      PrintDisassembly($libs, $flat, $cumulative, $main::opt_disasm);\n    } elsif ($main::opt_list) {\n      PrintListing($total, $libs, $flat, $cumulative, $main::opt_list, 0);\n    } elsif ($main::opt_text) {\n      # Make sure the output is empty when have nothing to report\n      # (only matters when --heapcheck is given but we must be\n      # compatible with old branches that did not pass --heapcheck always):\n      if ($total != 0) {\n        printf(\"Total%s: %s %s\\n\",\n               (defined($thread) ? \" (t$thread)\" : \"\"),\n               Unparse($total), Units());\n      }\n      PrintText($symbols, $flat, $cumulative, -1);\n    } elsif ($main::opt_raw) {\n      PrintSymbolizedProfile($symbols, $profile, $main::prog);\n    } elsif ($main::opt_callgrind) {\n      PrintCallgrind($calls);\n    } else {\n      if (PrintDot($main::prog, $symbols, $profile, $flat, $cumulative, $total)) {\n        if ($main::opt_gv) {\n          RunGV(TempName($main::next_tmpfile, \"ps\"), \"\");\n        } elsif ($main::opt_evince) {\n          RunEvince(TempName($main::next_tmpfile, \"pdf\"), \"\");\n        } elsif ($main::opt_web) {\n          my $tmp = TempName($main::next_tmpfile, \"svg\");\n          RunWeb($tmp);\n          # The command we run might hand the file name off\n          # to an already running browser instance and then exit.\n          # Normally, we'd remove $tmp on exit (right now),\n          # but fork a child to remove $tmp a little later, so that the\n          # browser has time to load it first.\n          delete $main::tempnames{$tmp};\n          if (fork() == 0) {\n            sleep 5;\n            unlink($tmp);\n            exit(0);\n          }\n        }\n      } else {\n        cleanup();\n        exit(1);\n      }\n    }\n  } else {\n    InteractiveMode($profile, $symbols, $libs, $total);\n  }\n}\n\nsub Main() {\n  Init();\n  $main::collected_profile = undef;\n  @main::profile_files = ();\n  $main::op_time = time();\n\n  # Printing symbols is special and requires a lot less info that most.\n  if ($main::opt_symbols) {\n    PrintSymbols(*STDIN);   # Get /proc/maps and symbols output from stdin\n    return;\n  }\n\n  # Fetch all profile data\n  FetchDynamicProfiles();\n\n  # this will hold symbols that we read from the profile files\n  my $symbol_map = {};\n\n  # Read one profile, pick the last item on the list\n  my $data = ReadProfile($main::prog, pop(@main::profile_files));\n  my $profile = $data->{profile};\n  my $pcs = $data->{pcs};\n  my $libs = $data->{libs};   # Info about main program and shared libraries\n  $symbol_map = MergeSymbols($symbol_map, $data->{symbols});\n\n  # Add additional profiles, if available.\n  if (scalar(@main::profile_files) > 0) {\n    foreach my $pname (@main::profile_files) {\n      my $data2 = ReadProfile($main::prog, $pname);\n      $profile = AddProfile($profile, $data2->{profile});\n      $pcs = AddPcs($pcs, $data2->{pcs});\n      $symbol_map = MergeSymbols($symbol_map, $data2->{symbols});\n    }\n  }\n\n  # Subtract base from profile, if specified\n  if ($main::opt_base ne '') {\n    my $base = ReadProfile($main::prog, $main::opt_base);\n    $profile = SubtractProfile($profile, $base->{profile});\n    $pcs = AddPcs($pcs, $base->{pcs});\n    $symbol_map = MergeSymbols($symbol_map, $base->{symbols});\n  }\n\n  # Collect symbols\n  my $symbols;\n  if ($main::use_symbolized_profile) {\n    $symbols = FetchSymbols($pcs, $symbol_map);\n  } elsif ($main::use_symbol_page) {\n    $symbols = FetchSymbols($pcs);\n  } else {\n    # TODO(csilvers): $libs uses the /proc/self/maps data from profile1,\n    # which may differ from the data from subsequent profiles, especially\n    # if they were run on different machines.  Use appropriate libs for\n    # each pc somehow.\n    $symbols = ExtractSymbols($libs, $pcs);\n  }\n\n  if (!defined($main::opt_thread)) {\n    FilterAndPrint($profile, $symbols, $libs);\n  }\n  if (defined($data->{threads})) {\n    foreach my $thread (sort { $a <=> $b } keys(%{$data->{threads}})) {\n      if (defined($main::opt_thread) &&\n          ($main::opt_thread eq '*' || $main::opt_thread == $thread)) {\n        my $thread_profile = $data->{threads}{$thread};\n        FilterAndPrint($thread_profile, $symbols, $libs, $thread);\n      }\n    }\n  }\n\n  cleanup();\n  exit(0);\n}\n\n##### Entry Point #####\n\nMain();\n\n# Temporary code to detect if we're running on a Goobuntu system.\n# These systems don't have the right stuff installed for the special\n# Readline libraries to work, so as a temporary workaround, we default\n# to using the normal stdio code, rather than the fancier readline-based\n# code\nsub ReadlineMightFail {\n  if (-e '/lib/libtermcap.so.2') {\n    return 0;  # libtermcap exists, so readline should be okay\n  } else {\n    return 1;\n  }\n}\n\nsub RunGV {\n  my $fname = shift;\n  my $bg = shift;       # \"\" or \" &\" if we should run in background\n  if (!system(ShellEscape(@GV, \"--version\") . \" >$dev_null 2>&1\")) {\n    # Options using double dash are supported by this gv version.\n    # Also, turn on noantialias to better handle bug in gv for\n    # postscript files with large dimensions.\n    # TODO: Maybe we should not pass the --noantialias flag\n    # if the gv version is known to work properly without the flag.\n    system(ShellEscape(@GV, \"--scale=$main::opt_scale\", \"--noantialias\", $fname)\n           . $bg);\n  } else {\n    # Old gv version - only supports options that use single dash.\n    print STDERR ShellEscape(@GV, \"-scale\", $main::opt_scale) . \"\\n\";\n    system(ShellEscape(@GV, \"-scale\", \"$main::opt_scale\", $fname) . $bg);\n  }\n}\n\nsub RunEvince {\n  my $fname = shift;\n  my $bg = shift;       # \"\" or \" &\" if we should run in background\n  system(ShellEscape(@EVINCE, $fname) . $bg);\n}\n\nsub RunWeb {\n  my $fname = shift;\n  print STDERR \"Loading web page file:///$fname\\n\";\n\n  if (`uname` =~ /Darwin/) {\n    # OS X: open will use standard preference for SVG files.\n    system(\"/usr/bin/open\", $fname);\n    return;\n  }\n\n  # Some kind of Unix; try generic symlinks, then specific browsers.\n  # (Stop once we find one.)\n  # Works best if the browser is already running.\n  my @alt = (\n    \"/etc/alternatives/gnome-www-browser\",\n    \"/etc/alternatives/x-www-browser\",\n    \"google-chrome\",\n    \"firefox\",\n  );\n  foreach my $b (@alt) {\n    if (system($b, $fname) == 0) {\n      return;\n    }\n  }\n\n  print STDERR \"Could not load web browser.\\n\";\n}\n\nsub RunKcachegrind {\n  my $fname = shift;\n  my $bg = shift;       # \"\" or \" &\" if we should run in background\n  print STDERR \"Starting '@KCACHEGRIND \" . $fname . $bg . \"'\\n\";\n  system(ShellEscape(@KCACHEGRIND, $fname) . $bg);\n}\n\n\n##### Interactive helper routines #####\n\nsub InteractiveMode {\n  $| = 1;  # Make output unbuffered for interactive mode\n  my ($orig_profile, $symbols, $libs, $total) = @_;\n\n  print STDERR \"Welcome to jeprof!  For help, type 'help'.\\n\";\n\n  # Use ReadLine if it's installed and input comes from a console.\n  if ( -t STDIN &&\n       !ReadlineMightFail() &&\n       defined(eval {require Term::ReadLine}) ) {\n    my $term = new Term::ReadLine 'jeprof';\n    while ( defined ($_ = $term->readline('(jeprof) '))) {\n      $term->addhistory($_) if /\\S/;\n      if (!InteractiveCommand($orig_profile, $symbols, $libs, $total, $_)) {\n        last;    # exit when we get an interactive command to quit\n      }\n    }\n  } else {       # don't have readline\n    while (1) {\n      print STDERR \"(jeprof) \";\n      $_ = <STDIN>;\n      last if ! defined $_ ;\n      s/\\r//g;         # turn windows-looking lines into unix-looking lines\n\n      # Save some flags that might be reset by InteractiveCommand()\n      my $save_opt_lines = $main::opt_lines;\n\n      if (!InteractiveCommand($orig_profile, $symbols, $libs, $total, $_)) {\n        last;    # exit when we get an interactive command to quit\n      }\n\n      # Restore flags\n      $main::opt_lines = $save_opt_lines;\n    }\n  }\n}\n\n# Takes two args: orig profile, and command to run.\n# Returns 1 if we should keep going, or 0 if we were asked to quit\nsub InteractiveCommand {\n  my($orig_profile, $symbols, $libs, $total, $command) = @_;\n  $_ = $command;                # just to make future m//'s easier\n  if (!defined($_)) {\n    print STDERR \"\\n\";\n    return 0;\n  }\n  if (m/^\\s*quit/) {\n    return 0;\n  }\n  if (m/^\\s*help/) {\n    InteractiveHelpMessage();\n    return 1;\n  }\n  # Clear all the mode options -- mode is controlled by \"$command\"\n  $main::opt_text = 0;\n  $main::opt_callgrind = 0;\n  $main::opt_disasm = 0;\n  $main::opt_list = 0;\n  $main::opt_gv = 0;\n  $main::opt_evince = 0;\n  $main::opt_cum = 0;\n\n  if (m/^\\s*(text|top)(\\d*)\\s*(.*)/) {\n    $main::opt_text = 1;\n\n    my $line_limit = ($2 ne \"\") ? int($2) : 10;\n\n    my $routine;\n    my $ignore;\n    ($routine, $ignore) = ParseInteractiveArgs($3);\n\n    my $profile = ProcessProfile($total, $orig_profile, $symbols, \"\", $ignore);\n    my $reduced = ReduceProfile($symbols, $profile);\n\n    # Get derived profiles\n    my $flat = FlatProfile($reduced);\n    my $cumulative = CumulativeProfile($reduced);\n\n    PrintText($symbols, $flat, $cumulative, $line_limit);\n    return 1;\n  }\n  if (m/^\\s*callgrind\\s*([^ \\n]*)/) {\n    $main::opt_callgrind = 1;\n\n    # Get derived profiles\n    my $calls = ExtractCalls($symbols, $orig_profile);\n    my $filename = $1;\n    if ( $1 eq '' ) {\n      $filename = TempName($main::next_tmpfile, \"callgrind\");\n    }\n    PrintCallgrind($calls, $filename);\n    if ( $1 eq '' ) {\n      RunKcachegrind($filename, \" & \");\n      $main::next_tmpfile++;\n    }\n\n    return 1;\n  }\n  if (m/^\\s*(web)?list\\s*(.+)/) {\n    my $html = (defined($1) && ($1 eq \"web\"));\n    $main::opt_list = 1;\n\n    my $routine;\n    my $ignore;\n    ($routine, $ignore) = ParseInteractiveArgs($2);\n\n    my $profile = ProcessProfile($total, $orig_profile, $symbols, \"\", $ignore);\n    my $reduced = ReduceProfile($symbols, $profile);\n\n    # Get derived profiles\n    my $flat = FlatProfile($reduced);\n    my $cumulative = CumulativeProfile($reduced);\n\n    PrintListing($total, $libs, $flat, $cumulative, $routine, $html);\n    return 1;\n  }\n  if (m/^\\s*disasm\\s*(.+)/) {\n    $main::opt_disasm = 1;\n\n    my $routine;\n    my $ignore;\n    ($routine, $ignore) = ParseInteractiveArgs($1);\n\n    # Process current profile to account for various settings\n    my $profile = ProcessProfile($total, $orig_profile, $symbols, \"\", $ignore);\n    my $reduced = ReduceProfile($symbols, $profile);\n\n    # Get derived profiles\n    my $flat = FlatProfile($reduced);\n    my $cumulative = CumulativeProfile($reduced);\n\n    PrintDisassembly($libs, $flat, $cumulative, $routine);\n    return 1;\n  }\n  if (m/^\\s*(gv|web|evince)\\s*(.*)/) {\n    $main::opt_gv = 0;\n    $main::opt_evince = 0;\n    $main::opt_web = 0;\n    if ($1 eq \"gv\") {\n      $main::opt_gv = 1;\n    } elsif ($1 eq \"evince\") {\n      $main::opt_evince = 1;\n    } elsif ($1 eq \"web\") {\n      $main::opt_web = 1;\n    }\n\n    my $focus;\n    my $ignore;\n    ($focus, $ignore) = ParseInteractiveArgs($2);\n\n    # Process current profile to account for various settings\n    my $profile = ProcessProfile($total, $orig_profile, $symbols,\n                                 $focus, $ignore);\n    my $reduced = ReduceProfile($symbols, $profile);\n\n    # Get derived profiles\n    my $flat = FlatProfile($reduced);\n    my $cumulative = CumulativeProfile($reduced);\n\n    if (PrintDot($main::prog, $symbols, $profile, $flat, $cumulative, $total)) {\n      if ($main::opt_gv) {\n        RunGV(TempName($main::next_tmpfile, \"ps\"), \" &\");\n      } elsif ($main::opt_evince) {\n        RunEvince(TempName($main::next_tmpfile, \"pdf\"), \" &\");\n      } elsif ($main::opt_web) {\n        RunWeb(TempName($main::next_tmpfile, \"svg\"));\n      }\n      $main::next_tmpfile++;\n    }\n    return 1;\n  }\n  if (m/^\\s*$/) {\n    return 1;\n  }\n  print STDERR \"Unknown command: try 'help'.\\n\";\n  return 1;\n}\n\n\nsub ProcessProfile {\n  my $total_count = shift;\n  my $orig_profile = shift;\n  my $symbols = shift;\n  my $focus = shift;\n  my $ignore = shift;\n\n  # Process current profile to account for various settings\n  my $profile = $orig_profile;\n  printf(\"Total: %s %s\\n\", Unparse($total_count), Units());\n  if ($focus ne '') {\n    $profile = FocusProfile($symbols, $profile, $focus);\n    my $focus_count = TotalProfile($profile);\n    printf(\"After focusing on '%s': %s %s of %s (%0.1f%%)\\n\",\n           $focus,\n           Unparse($focus_count), Units(),\n           Unparse($total_count), ($focus_count*100.0) / $total_count);\n  }\n  if ($ignore ne '') {\n    $profile = IgnoreProfile($symbols, $profile, $ignore);\n    my $ignore_count = TotalProfile($profile);\n    printf(\"After ignoring '%s': %s %s of %s (%0.1f%%)\\n\",\n           $ignore,\n           Unparse($ignore_count), Units(),\n           Unparse($total_count),\n           ($ignore_count*100.0) / $total_count);\n  }\n\n  return $profile;\n}\n\nsub InteractiveHelpMessage {\n  print STDERR <<ENDOFHELP;\nInteractive jeprof mode\n\nCommands:\n  gv\n  gv [focus] [-ignore1] [-ignore2]\n      Show graphical hierarchical display of current profile.  Without\n      any arguments, shows all samples in the profile.  With the optional\n      \"focus\" argument, restricts the samples shown to just those where\n      the \"focus\" regular expression matches a routine name on the stack\n      trace.\n\n  web\n  web [focus] [-ignore1] [-ignore2]\n      Like GV, but displays profile in your web browser instead of using\n      Ghostview. Works best if your web browser is already running.\n      To change the browser that gets used:\n      On Linux, set the /etc/alternatives/gnome-www-browser symlink.\n      On OS X, change the Finder association for SVG files.\n\n  list [routine_regexp] [-ignore1] [-ignore2]\n      Show source listing of routines whose names match \"routine_regexp\"\n\n  weblist [routine_regexp] [-ignore1] [-ignore2]\n     Displays a source listing of routines whose names match \"routine_regexp\"\n     in a web browser.  You can click on source lines to view the\n     corresponding disassembly.\n\n  top [--cum] [-ignore1] [-ignore2]\n  top20 [--cum] [-ignore1] [-ignore2]\n  top37 [--cum] [-ignore1] [-ignore2]\n      Show top lines ordered by flat profile count, or cumulative count\n      if --cum is specified.  If a number is present after 'top', the\n      top K routines will be shown (defaults to showing the top 10)\n\n  disasm [routine_regexp] [-ignore1] [-ignore2]\n      Show disassembly of routines whose names match \"routine_regexp\",\n      annotated with sample counts.\n\n  callgrind\n  callgrind [filename]\n      Generates callgrind file. If no filename is given, kcachegrind is called.\n\n  help - This listing\n  quit or ^D - End jeprof\n\nFor commands that accept optional -ignore tags, samples where any routine in\nthe stack trace matches the regular expression in any of the -ignore\nparameters will be ignored.\n\nFurther pprof details are available at this location (or one similar):\n\n /usr/doc/gperftools-$PPROF_VERSION/cpu_profiler.html\n /usr/doc/gperftools-$PPROF_VERSION/heap_profiler.html\n\nENDOFHELP\n}\nsub ParseInteractiveArgs {\n  my $args = shift;\n  my $focus = \"\";\n  my $ignore = \"\";\n  my @x = split(/ +/, $args);\n  foreach $a (@x) {\n    if ($a =~ m/^(--|-)lines$/) {\n      $main::opt_lines = 1;\n    } elsif ($a =~ m/^(--|-)cum$/) {\n      $main::opt_cum = 1;\n    } elsif ($a =~ m/^-(.*)/) {\n      $ignore .= (($ignore ne \"\") ? \"|\" : \"\" ) . $1;\n    } else {\n      $focus .= (($focus ne \"\") ? \"|\" : \"\" ) . $a;\n    }\n  }\n  if ($ignore ne \"\") {\n    print STDERR \"Ignoring samples in call stacks that match '$ignore'\\n\";\n  }\n  return ($focus, $ignore);\n}\n\n##### Output code #####\n\nsub TempName {\n  my $fnum = shift;\n  my $ext = shift;\n  my $file = \"$main::tmpfile_ps.$fnum.$ext\";\n  $main::tempnames{$file} = 1;\n  return $file;\n}\n\n# Print profile data in packed binary format (64-bit) to standard out\nsub PrintProfileData {\n  my $profile = shift;\n\n  # print header (64-bit style)\n  # (zero) (header-size) (version) (sample-period) (zero)\n  print pack('L*', 0, 0, 3, 0, 0, 0, 1, 0, 0, 0);\n\n  foreach my $k (keys(%{$profile})) {\n    my $count = $profile->{$k};\n    my @addrs = split(/\\n/, $k);\n    if ($#addrs >= 0) {\n      my $depth = $#addrs + 1;\n      # int(foo / 2**32) is the only reliable way to get rid of bottom\n      # 32 bits on both 32- and 64-bit systems.\n      print pack('L*', $count & 0xFFFFFFFF, int($count / 2**32));\n      print pack('L*', $depth & 0xFFFFFFFF, int($depth / 2**32));\n\n      foreach my $full_addr (@addrs) {\n        my $addr = $full_addr;\n        $addr =~ s/0x0*//;  # strip off leading 0x, zeroes\n        if (length($addr) > 16) {\n          print STDERR \"Invalid address in profile: $full_addr\\n\";\n          next;\n        }\n        my $low_addr = substr($addr, -8);       # get last 8 hex chars\n        my $high_addr = substr($addr, -16, 8);  # get up to 8 more hex chars\n        print pack('L*', hex('0x' . $low_addr), hex('0x' . $high_addr));\n      }\n    }\n  }\n}\n\n# Print symbols and profile data\nsub PrintSymbolizedProfile {\n  my $symbols = shift;\n  my $profile = shift;\n  my $prog = shift;\n\n  $SYMBOL_PAGE =~ m,[^/]+$,;    # matches everything after the last slash\n  my $symbol_marker = $&;\n\n  print '--- ', $symbol_marker, \"\\n\";\n  if (defined($prog)) {\n    print 'binary=', $prog, \"\\n\";\n  }\n  while (my ($pc, $name) = each(%{$symbols})) {\n    my $sep = ' ';\n    print '0x', $pc;\n    # We have a list of function names, which include the inlined\n    # calls.  They are separated (and terminated) by --, which is\n    # illegal in function names.\n    for (my $j = 2; $j <= $#{$name}; $j += 3) {\n      print $sep, $name->[$j];\n      $sep = '--';\n    }\n    print \"\\n\";\n  }\n  print '---', \"\\n\";\n\n  my $profile_marker;\n  if ($main::profile_type eq 'heap') {\n    $HEAP_PAGE =~ m,[^/]+$,;    # matches everything after the last slash\n    $profile_marker = $&;\n  } elsif ($main::profile_type eq 'growth') {\n    $GROWTH_PAGE =~ m,[^/]+$,;    # matches everything after the last slash\n    $profile_marker = $&;\n  } elsif ($main::profile_type eq 'contention') {\n    $CONTENTION_PAGE =~ m,[^/]+$,;    # matches everything after the last slash\n    $profile_marker = $&;\n  } else { # elsif ($main::profile_type eq 'cpu')\n    $PROFILE_PAGE =~ m,[^/]+$,;    # matches everything after the last slash\n    $profile_marker = $&;\n  }\n\n  print '--- ', $profile_marker, \"\\n\";\n  if (defined($main::collected_profile)) {\n    # if used with remote fetch, simply dump the collected profile to output.\n    open(SRC, \"<$main::collected_profile\");\n    while (<SRC>) {\n      print $_;\n    }\n    close(SRC);\n  } else {\n    # --raw/http: For everything to work correctly for non-remote profiles, we\n    # would need to extend PrintProfileData() to handle all possible profile\n    # types, re-enable the code that is currently disabled in ReadCPUProfile()\n    # and FixCallerAddresses(), and remove the remote profile dumping code in\n    # the block above.\n    die \"--raw/http: jeprof can only dump remote profiles for --raw\\n\";\n    # dump a cpu-format profile to standard out\n    PrintProfileData($profile);\n  }\n}\n\n# Print text output\nsub PrintText {\n  my $symbols = shift;\n  my $flat = shift;\n  my $cumulative = shift;\n  my $line_limit = shift;\n\n  my $total = TotalProfile($flat);\n\n  # Which profile to sort by?\n  my $s = $main::opt_cum ? $cumulative : $flat;\n\n  my $running_sum = 0;\n  my $lines = 0;\n  foreach my $k (sort { GetEntry($s, $b) <=> GetEntry($s, $a) || $a cmp $b }\n                 keys(%{$cumulative})) {\n    my $f = GetEntry($flat, $k);\n    my $c = GetEntry($cumulative, $k);\n    $running_sum += $f;\n\n    my $sym = $k;\n    if (exists($symbols->{$k})) {\n      $sym = $symbols->{$k}->[0] . \" \" . $symbols->{$k}->[1];\n      if ($main::opt_addresses) {\n        $sym = $k . \" \" . $sym;\n      }\n    }\n\n    if ($f != 0 || $c != 0) {\n      printf(\"%8s %6s %6s %8s %6s %s\\n\",\n             Unparse($f),\n             Percent($f, $total),\n             Percent($running_sum, $total),\n             Unparse($c),\n             Percent($c, $total),\n             $sym);\n    }\n    $lines++;\n    last if ($line_limit >= 0 && $lines >= $line_limit);\n  }\n}\n\n# Callgrind format has a compression for repeated function and file\n# names.  You show the name the first time, and just use its number\n# subsequently.  This can cut down the file to about a third or a\n# quarter of its uncompressed size.  $key and $val are the key/value\n# pair that would normally be printed by callgrind; $map is a map from\n# value to number.\nsub CompressedCGName {\n  my($key, $val, $map) = @_;\n  my $idx = $map->{$val};\n  # For very short keys, providing an index hurts rather than helps.\n  if (length($val) <= 3) {\n    return \"$key=$val\\n\";\n  } elsif (defined($idx)) {\n    return \"$key=($idx)\\n\";\n  } else {\n    # scalar(keys $map) gives the number of items in the map.\n    $idx = scalar(keys(%{$map})) + 1;\n    $map->{$val} = $idx;\n    return \"$key=($idx) $val\\n\";\n  }\n}\n\n# Print the call graph in a way that's suiteable for callgrind.\nsub PrintCallgrind {\n  my $calls = shift;\n  my $filename;\n  my %filename_to_index_map;\n  my %fnname_to_index_map;\n\n  if ($main::opt_interactive) {\n    $filename = shift;\n    print STDERR \"Writing callgrind file to '$filename'.\\n\"\n  } else {\n    $filename = \"&STDOUT\";\n  }\n  open(CG, \">$filename\");\n  printf CG (\"events: Hits\\n\\n\");\n  foreach my $call ( map { $_->[0] }\n                     sort { $a->[1] cmp $b ->[1] ||\n                            $a->[2] <=> $b->[2] }\n                     map { /([^:]+):(\\d+):([^ ]+)( -> ([^:]+):(\\d+):(.+))?/;\n                           [$_, $1, $2] }\n                     keys %$calls ) {\n    my $count = int($calls->{$call});\n    $call =~ /([^:]+):(\\d+):([^ ]+)( -> ([^:]+):(\\d+):(.+))?/;\n    my ( $caller_file, $caller_line, $caller_function,\n         $callee_file, $callee_line, $callee_function ) =\n       ( $1, $2, $3, $5, $6, $7 );\n\n    # TODO(csilvers): for better compression, collect all the\n    # caller/callee_files and functions first, before printing\n    # anything, and only compress those referenced more than once.\n    printf CG CompressedCGName(\"fl\", $caller_file, \\%filename_to_index_map);\n    printf CG CompressedCGName(\"fn\", $caller_function, \\%fnname_to_index_map);\n    if (defined $6) {\n      printf CG CompressedCGName(\"cfl\", $callee_file, \\%filename_to_index_map);\n      printf CG CompressedCGName(\"cfn\", $callee_function, \\%fnname_to_index_map);\n      printf CG (\"calls=$count $callee_line\\n\");\n    }\n    printf CG (\"$caller_line $count\\n\\n\");\n  }\n}\n\n# Print disassembly for all all routines that match $main::opt_disasm\nsub PrintDisassembly {\n  my $libs = shift;\n  my $flat = shift;\n  my $cumulative = shift;\n  my $disasm_opts = shift;\n\n  my $total = TotalProfile($flat);\n\n  foreach my $lib (@{$libs}) {\n    my $symbol_table = GetProcedureBoundaries($lib->[0], $disasm_opts);\n    my $offset = AddressSub($lib->[1], $lib->[3]);\n    foreach my $routine (sort ByName keys(%{$symbol_table})) {\n      my $start_addr = $symbol_table->{$routine}->[0];\n      my $end_addr = $symbol_table->{$routine}->[1];\n      # See if there are any samples in this routine\n      my $length = hex(AddressSub($end_addr, $start_addr));\n      my $addr = AddressAdd($start_addr, $offset);\n      for (my $i = 0; $i < $length; $i++) {\n        if (defined($cumulative->{$addr})) {\n          PrintDisassembledFunction($lib->[0], $offset,\n                                    $routine, $flat, $cumulative,\n                                    $start_addr, $end_addr, $total);\n          last;\n        }\n        $addr = AddressInc($addr);\n      }\n    }\n  }\n}\n\n# Return reference to array of tuples of the form:\n#       [start_address, filename, linenumber, instruction, limit_address]\n# E.g.,\n#       [\"0x806c43d\", \"/foo/bar.cc\", 131, \"ret\", \"0x806c440\"]\nsub Disassemble {\n  my $prog = shift;\n  my $offset = shift;\n  my $start_addr = shift;\n  my $end_addr = shift;\n\n  my $objdump = $obj_tool_map{\"objdump\"};\n  my $cmd = ShellEscape($objdump, \"-C\", \"-d\", \"-l\", \"--no-show-raw-insn\",\n                        \"--start-address=0x$start_addr\",\n                        \"--stop-address=0x$end_addr\", $prog);\n  open(OBJDUMP, \"$cmd |\") || error(\"$cmd: $!\\n\");\n  my @result = ();\n  my $filename = \"\";\n  my $linenumber = -1;\n  my $last = [\"\", \"\", \"\", \"\"];\n  while (<OBJDUMP>) {\n    s/\\r//g;         # turn windows-looking lines into unix-looking lines\n    chop;\n    if (m|\\s*([^:\\s]+):(\\d+)\\s*$|) {\n      # Location line of the form:\n      #   <filename>:<linenumber>\n      $filename = $1;\n      $linenumber = $2;\n    } elsif (m/^ +([0-9a-f]+):\\s*(.*)/) {\n      # Disassembly line -- zero-extend address to full length\n      my $addr = HexExtend($1);\n      my $k = AddressAdd($addr, $offset);\n      $last->[4] = $k;   # Store ending address for previous instruction\n      $last = [$k, $filename, $linenumber, $2, $end_addr];\n      push(@result, $last);\n    }\n  }\n  close(OBJDUMP);\n  return @result;\n}\n\n# The input file should contain lines of the form /proc/maps-like\n# output (same format as expected from the profiles) or that looks\n# like hex addresses (like \"0xDEADBEEF\").  We will parse all\n# /proc/maps output, and for all the hex addresses, we will output\n# \"short\" symbol names, one per line, in the same order as the input.\nsub PrintSymbols {\n  my $maps_and_symbols_file = shift;\n\n  # ParseLibraries expects pcs to be in a set.  Fine by us...\n  my @pclist = ();   # pcs in sorted order\n  my $pcs = {};\n  my $map = \"\";\n  foreach my $line (<$maps_and_symbols_file>) {\n    $line =~ s/\\r//g;    # turn windows-looking lines into unix-looking lines\n    if ($line =~ /\\b(0x[0-9a-f]+)\\b/i) {\n      push(@pclist, HexExtend($1));\n      $pcs->{$pclist[-1]} = 1;\n    } else {\n      $map .= $line;\n    }\n  }\n\n  my $libs = ParseLibraries($main::prog, $map, $pcs);\n  my $symbols = ExtractSymbols($libs, $pcs);\n\n  foreach my $pc (@pclist) {\n    # ->[0] is the shortname, ->[2] is the full name\n    print(($symbols->{$pc}->[0] || \"??\") . \"\\n\");\n  }\n}\n\n\n# For sorting functions by name\nsub ByName {\n  return ShortFunctionName($a) cmp ShortFunctionName($b);\n}\n\n# Print source-listing for all all routines that match $list_opts\nsub PrintListing {\n  my $total = shift;\n  my $libs = shift;\n  my $flat = shift;\n  my $cumulative = shift;\n  my $list_opts = shift;\n  my $html = shift;\n\n  my $output = \\*STDOUT;\n  my $fname = \"\";\n\n  if ($html) {\n    # Arrange to write the output to a temporary file\n    $fname = TempName($main::next_tmpfile, \"html\");\n    $main::next_tmpfile++;\n    if (!open(TEMP, \">$fname\")) {\n      print STDERR \"$fname: $!\\n\";\n      return;\n    }\n    $output = \\*TEMP;\n    print $output HtmlListingHeader();\n    printf $output (\"<div class=\\\"legend\\\">%s<br>Total: %s %s</div>\\n\",\n                    $main::prog, Unparse($total), Units());\n  }\n\n  my $listed = 0;\n  foreach my $lib (@{$libs}) {\n    my $symbol_table = GetProcedureBoundaries($lib->[0], $list_opts);\n    my $offset = AddressSub($lib->[1], $lib->[3]);\n    foreach my $routine (sort ByName keys(%{$symbol_table})) {\n      # Print if there are any samples in this routine\n      my $start_addr = $symbol_table->{$routine}->[0];\n      my $end_addr = $symbol_table->{$routine}->[1];\n      my $length = hex(AddressSub($end_addr, $start_addr));\n      my $addr = AddressAdd($start_addr, $offset);\n      for (my $i = 0; $i < $length; $i++) {\n        if (defined($cumulative->{$addr})) {\n          $listed += PrintSource(\n            $lib->[0], $offset,\n            $routine, $flat, $cumulative,\n            $start_addr, $end_addr,\n            $html,\n            $output);\n          last;\n        }\n        $addr = AddressInc($addr);\n      }\n    }\n  }\n\n  if ($html) {\n    if ($listed > 0) {\n      print $output HtmlListingFooter();\n      close($output);\n      RunWeb($fname);\n    } else {\n      close($output);\n      unlink($fname);\n    }\n  }\n}\n\nsub HtmlListingHeader {\n  return <<'EOF';\n<DOCTYPE html>\n<html>\n<head>\n<title>Pprof listing</title>\n<style type=\"text/css\">\nbody {\n  font-family: sans-serif;\n}\nh1 {\n  font-size: 1.5em;\n  margin-bottom: 4px;\n}\n.legend {\n  font-size: 1.25em;\n}\n.line {\n  color: #aaaaaa;\n}\n.nop {\n  color: #aaaaaa;\n}\n.unimportant {\n  color: #cccccc;\n}\n.disasmloc {\n  color: #000000;\n}\n.deadsrc {\n  cursor: pointer;\n}\n.deadsrc:hover {\n  background-color: #eeeeee;\n}\n.livesrc {\n  color: #0000ff;\n  cursor: pointer;\n}\n.livesrc:hover {\n  background-color: #eeeeee;\n}\n.asm {\n  color: #008800;\n  display: none;\n}\n</style>\n<script type=\"text/javascript\">\nfunction jeprof_toggle_asm(e) {\n  var target;\n  if (!e) e = window.event;\n  if (e.target) target = e.target;\n  else if (e.srcElement) target = e.srcElement;\n\n  if (target) {\n    var asm = target.nextSibling;\n    if (asm && asm.className == \"asm\") {\n      asm.style.display = (asm.style.display == \"block\" ? \"\" : \"block\");\n      e.preventDefault();\n      return false;\n    }\n  }\n}\n</script>\n</head>\n<body>\nEOF\n}\n\nsub HtmlListingFooter {\n  return <<'EOF';\n</body>\n</html>\nEOF\n}\n\nsub HtmlEscape {\n  my $text = shift;\n  $text =~ s/&/&amp;/g;\n  $text =~ s/</&lt;/g;\n  $text =~ s/>/&gt;/g;\n  return $text;\n}\n\n# Returns the indentation of the line, if it has any non-whitespace\n# characters.  Otherwise, returns -1.\nsub Indentation {\n  my $line = shift;\n  if (m/^(\\s*)\\S/) {\n    return length($1);\n  } else {\n    return -1;\n  }\n}\n\n# If the symbol table contains inlining info, Disassemble() may tag an\n# instruction with a location inside an inlined function.  But for\n# source listings, we prefer to use the location in the function we\n# are listing.  So use MapToSymbols() to fetch full location\n# information for each instruction and then pick out the first\n# location from a location list (location list contains callers before\n# callees in case of inlining).\n#\n# After this routine has run, each entry in $instructions contains:\n#   [0] start address\n#   [1] filename for function we are listing\n#   [2] line number for function we are listing\n#   [3] disassembly\n#   [4] limit address\n#   [5] most specific filename (may be different from [1] due to inlining)\n#   [6] most specific line number (may be different from [2] due to inlining)\nsub GetTopLevelLineNumbers {\n  my ($lib, $offset, $instructions) = @_;\n  my $pcs = [];\n  for (my $i = 0; $i <= $#{$instructions}; $i++) {\n    push(@{$pcs}, $instructions->[$i]->[0]);\n  }\n  my $symbols = {};\n  MapToSymbols($lib, $offset, $pcs, $symbols);\n  for (my $i = 0; $i <= $#{$instructions}; $i++) {\n    my $e = $instructions->[$i];\n    push(@{$e}, $e->[1]);\n    push(@{$e}, $e->[2]);\n    my $addr = $e->[0];\n    my $sym = $symbols->{$addr};\n    if (defined($sym)) {\n      if ($#{$sym} >= 2 && $sym->[1] =~ m/^(.*):(\\d+)$/) {\n        $e->[1] = $1;  # File name\n        $e->[2] = $2;  # Line number\n      }\n    }\n  }\n}\n\n# Print source-listing for one routine\nsub PrintSource {\n  my $prog = shift;\n  my $offset = shift;\n  my $routine = shift;\n  my $flat = shift;\n  my $cumulative = shift;\n  my $start_addr = shift;\n  my $end_addr = shift;\n  my $html = shift;\n  my $output = shift;\n\n  # Disassemble all instructions (just to get line numbers)\n  my @instructions = Disassemble($prog, $offset, $start_addr, $end_addr);\n  GetTopLevelLineNumbers($prog, $offset, \\@instructions);\n\n  # Hack 1: assume that the first source file encountered in the\n  # disassembly contains the routine\n  my $filename = undef;\n  for (my $i = 0; $i <= $#instructions; $i++) {\n    if ($instructions[$i]->[2] >= 0) {\n      $filename = $instructions[$i]->[1];\n      last;\n    }\n  }\n  if (!defined($filename)) {\n    print STDERR \"no filename found in $routine\\n\";\n    return 0;\n  }\n\n  # Hack 2: assume that the largest line number from $filename is the\n  # end of the procedure.  This is typically safe since if P1 contains\n  # an inlined call to P2, then P2 usually occurs earlier in the\n  # source file.  If this does not work, we might have to compute a\n  # density profile or just print all regions we find.\n  my $lastline = 0;\n  for (my $i = 0; $i <= $#instructions; $i++) {\n    my $f = $instructions[$i]->[1];\n    my $l = $instructions[$i]->[2];\n    if (($f eq $filename) && ($l > $lastline)) {\n      $lastline = $l;\n    }\n  }\n\n  # Hack 3: assume the first source location from \"filename\" is the start of\n  # the source code.\n  my $firstline = 1;\n  for (my $i = 0; $i <= $#instructions; $i++) {\n    if ($instructions[$i]->[1] eq $filename) {\n      $firstline = $instructions[$i]->[2];\n      last;\n    }\n  }\n\n  # Hack 4: Extend last line forward until its indentation is less than\n  # the indentation we saw on $firstline\n  my $oldlastline = $lastline;\n  {\n    if (!open(FILE, \"<$filename\")) {\n      print STDERR \"$filename: $!\\n\";\n      return 0;\n    }\n    my $l = 0;\n    my $first_indentation = -1;\n    while (<FILE>) {\n      s/\\r//g;         # turn windows-looking lines into unix-looking lines\n      $l++;\n      my $indent = Indentation($_);\n      if ($l >= $firstline) {\n        if ($first_indentation < 0 && $indent >= 0) {\n          $first_indentation = $indent;\n          last if ($first_indentation == 0);\n        }\n      }\n      if ($l >= $lastline && $indent >= 0) {\n        if ($indent >= $first_indentation) {\n          $lastline = $l+1;\n        } else {\n          last;\n        }\n      }\n    }\n    close(FILE);\n  }\n\n  # Assign all samples to the range $firstline,$lastline,\n  # Hack 4: If an instruction does not occur in the range, its samples\n  # are moved to the next instruction that occurs in the range.\n  my $samples1 = {};        # Map from line number to flat count\n  my $samples2 = {};        # Map from line number to cumulative count\n  my $running1 = 0;         # Unassigned flat counts\n  my $running2 = 0;         # Unassigned cumulative counts\n  my $total1 = 0;           # Total flat counts\n  my $total2 = 0;           # Total cumulative counts\n  my %disasm = ();          # Map from line number to disassembly\n  my $running_disasm = \"\";  # Unassigned disassembly\n  my $skip_marker = \"---\\n\";\n  if ($html) {\n    $skip_marker = \"\";\n    for (my $l = $firstline; $l <= $lastline; $l++) {\n      $disasm{$l} = \"\";\n    }\n  }\n  my $last_dis_filename = '';\n  my $last_dis_linenum = -1;\n  my $last_touched_line = -1;  # To detect gaps in disassembly for a line\n  foreach my $e (@instructions) {\n    # Add up counts for all address that fall inside this instruction\n    my $c1 = 0;\n    my $c2 = 0;\n    for (my $a = $e->[0]; $a lt $e->[4]; $a = AddressInc($a)) {\n      $c1 += GetEntry($flat, $a);\n      $c2 += GetEntry($cumulative, $a);\n    }\n\n    if ($html) {\n      my $dis = sprintf(\"      %6s %6s \\t\\t%8s: %s \",\n                        HtmlPrintNumber($c1),\n                        HtmlPrintNumber($c2),\n                        UnparseAddress($offset, $e->[0]),\n                        CleanDisassembly($e->[3]));\n\n      # Append the most specific source line associated with this instruction\n      if (length($dis) < 80) { $dis .= (' ' x (80 - length($dis))) };\n      $dis = HtmlEscape($dis);\n      my $f = $e->[5];\n      my $l = $e->[6];\n      if ($f ne $last_dis_filename) {\n        $dis .= sprintf(\"<span class=disasmloc>%s:%d</span>\",\n                        HtmlEscape(CleanFileName($f)), $l);\n      } elsif ($l ne $last_dis_linenum) {\n        # De-emphasize the unchanged file name portion\n        $dis .= sprintf(\"<span class=unimportant>%s</span>\" .\n                        \"<span class=disasmloc>:%d</span>\",\n                        HtmlEscape(CleanFileName($f)), $l);\n      } else {\n        # De-emphasize the entire location\n        $dis .= sprintf(\"<span class=unimportant>%s:%d</span>\",\n                        HtmlEscape(CleanFileName($f)), $l);\n      }\n      $last_dis_filename = $f;\n      $last_dis_linenum = $l;\n      $running_disasm .= $dis;\n      $running_disasm .= \"\\n\";\n    }\n\n    $running1 += $c1;\n    $running2 += $c2;\n    $total1 += $c1;\n    $total2 += $c2;\n    my $file = $e->[1];\n    my $line = $e->[2];\n    if (($file eq $filename) &&\n        ($line >= $firstline) &&\n        ($line <= $lastline)) {\n      # Assign all accumulated samples to this line\n      AddEntry($samples1, $line, $running1);\n      AddEntry($samples2, $line, $running2);\n      $running1 = 0;\n      $running2 = 0;\n      if ($html) {\n        if ($line != $last_touched_line && $disasm{$line} ne '') {\n          $disasm{$line} .= \"\\n\";\n        }\n        $disasm{$line} .= $running_disasm;\n        $running_disasm = '';\n        $last_touched_line = $line;\n      }\n    }\n  }\n\n  # Assign any leftover samples to $lastline\n  AddEntry($samples1, $lastline, $running1);\n  AddEntry($samples2, $lastline, $running2);\n  if ($html) {\n    if ($lastline != $last_touched_line && $disasm{$lastline} ne '') {\n      $disasm{$lastline} .= \"\\n\";\n    }\n    $disasm{$lastline} .= $running_disasm;\n  }\n\n  if ($html) {\n    printf $output (\n      \"<h1>%s</h1>%s\\n<pre onClick=\\\"jeprof_toggle_asm()\\\">\\n\" .\n      \"Total:%6s %6s (flat / cumulative %s)\\n\",\n      HtmlEscape(ShortFunctionName($routine)),\n      HtmlEscape(CleanFileName($filename)),\n      Unparse($total1),\n      Unparse($total2),\n      Units());\n  } else {\n    printf $output (\n      \"ROUTINE ====================== %s in %s\\n\" .\n      \"%6s %6s Total %s (flat / cumulative)\\n\",\n      ShortFunctionName($routine),\n      CleanFileName($filename),\n      Unparse($total1),\n      Unparse($total2),\n      Units());\n  }\n  if (!open(FILE, \"<$filename\")) {\n    print STDERR \"$filename: $!\\n\";\n    return 0;\n  }\n  my $l = 0;\n  while (<FILE>) {\n    s/\\r//g;         # turn windows-looking lines into unix-looking lines\n    $l++;\n    if ($l >= $firstline - 5 &&\n        (($l <= $oldlastline + 5) || ($l <= $lastline))) {\n      chop;\n      my $text = $_;\n      if ($l == $firstline) { print $output $skip_marker; }\n      my $n1 = GetEntry($samples1, $l);\n      my $n2 = GetEntry($samples2, $l);\n      if ($html) {\n        # Emit a span that has one of the following classes:\n        #    livesrc -- has samples\n        #    deadsrc -- has disassembly, but with no samples\n        #    nop     -- has no matching disasembly\n        # Also emit an optional span containing disassembly.\n        my $dis = $disasm{$l};\n        my $asm = \"\";\n        if (defined($dis) && $dis ne '') {\n          $asm = \"<span class=\\\"asm\\\">\" . $dis . \"</span>\";\n        }\n        my $source_class = (($n1 + $n2 > 0)\n                            ? \"livesrc\"\n                            : (($asm ne \"\") ? \"deadsrc\" : \"nop\"));\n        printf $output (\n          \"<span class=\\\"line\\\">%5d</span> \" .\n          \"<span class=\\\"%s\\\">%6s %6s %s</span>%s\\n\",\n          $l, $source_class,\n          HtmlPrintNumber($n1),\n          HtmlPrintNumber($n2),\n          HtmlEscape($text),\n          $asm);\n      } else {\n        printf $output(\n          \"%6s %6s %4d: %s\\n\",\n          UnparseAlt($n1),\n          UnparseAlt($n2),\n          $l,\n          $text);\n      }\n      if ($l == $lastline)  { print $output $skip_marker; }\n    };\n  }\n  close(FILE);\n  if ($html) {\n    print $output \"</pre>\\n\";\n  }\n  return 1;\n}\n\n# Return the source line for the specified file/linenumber.\n# Returns undef if not found.\nsub SourceLine {\n  my $file = shift;\n  my $line = shift;\n\n  # Look in cache\n  if (!defined($main::source_cache{$file})) {\n    if (100 < scalar keys(%main::source_cache)) {\n      # Clear the cache when it gets too big\n      $main::source_cache = ();\n    }\n\n    # Read all lines from the file\n    if (!open(FILE, \"<$file\")) {\n      print STDERR \"$file: $!\\n\";\n      $main::source_cache{$file} = [];  # Cache the negative result\n      return undef;\n    }\n    my $lines = [];\n    push(@{$lines}, \"\");        # So we can use 1-based line numbers as indices\n    while (<FILE>) {\n      push(@{$lines}, $_);\n    }\n    close(FILE);\n\n    # Save the lines in the cache\n    $main::source_cache{$file} = $lines;\n  }\n\n  my $lines = $main::source_cache{$file};\n  if (($line < 0) || ($line > $#{$lines})) {\n    return undef;\n  } else {\n    return $lines->[$line];\n  }\n}\n\n# Print disassembly for one routine with interspersed source if available\nsub PrintDisassembledFunction {\n  my $prog = shift;\n  my $offset = shift;\n  my $routine = shift;\n  my $flat = shift;\n  my $cumulative = shift;\n  my $start_addr = shift;\n  my $end_addr = shift;\n  my $total = shift;\n\n  # Disassemble all instructions\n  my @instructions = Disassemble($prog, $offset, $start_addr, $end_addr);\n\n  # Make array of counts per instruction\n  my @flat_count = ();\n  my @cum_count = ();\n  my $flat_total = 0;\n  my $cum_total = 0;\n  foreach my $e (@instructions) {\n    # Add up counts for all address that fall inside this instruction\n    my $c1 = 0;\n    my $c2 = 0;\n    for (my $a = $e->[0]; $a lt $e->[4]; $a = AddressInc($a)) {\n      $c1 += GetEntry($flat, $a);\n      $c2 += GetEntry($cumulative, $a);\n    }\n    push(@flat_count, $c1);\n    push(@cum_count, $c2);\n    $flat_total += $c1;\n    $cum_total += $c2;\n  }\n\n  # Print header with total counts\n  printf(\"ROUTINE ====================== %s\\n\" .\n         \"%6s %6s %s (flat, cumulative) %.1f%% of total\\n\",\n         ShortFunctionName($routine),\n         Unparse($flat_total),\n         Unparse($cum_total),\n         Units(),\n         ($cum_total * 100.0) / $total);\n\n  # Process instructions in order\n  my $current_file = \"\";\n  for (my $i = 0; $i <= $#instructions; ) {\n    my $e = $instructions[$i];\n\n    # Print the new file name whenever we switch files\n    if ($e->[1] ne $current_file) {\n      $current_file = $e->[1];\n      my $fname = $current_file;\n      $fname =~ s|^\\./||;   # Trim leading \"./\"\n\n      # Shorten long file names\n      if (length($fname) >= 58) {\n        $fname = \"...\" . substr($fname, -55);\n      }\n      printf(\"-------------------- %s\\n\", $fname);\n    }\n\n    # TODO: Compute range of lines to print together to deal with\n    # small reorderings.\n    my $first_line = $e->[2];\n    my $last_line = $first_line;\n    my %flat_sum = ();\n    my %cum_sum = ();\n    for (my $l = $first_line; $l <= $last_line; $l++) {\n      $flat_sum{$l} = 0;\n      $cum_sum{$l} = 0;\n    }\n\n    # Find run of instructions for this range of source lines\n    my $first_inst = $i;\n    while (($i <= $#instructions) &&\n           ($instructions[$i]->[2] >= $first_line) &&\n           ($instructions[$i]->[2] <= $last_line)) {\n      $e = $instructions[$i];\n      $flat_sum{$e->[2]} += $flat_count[$i];\n      $cum_sum{$e->[2]} += $cum_count[$i];\n      $i++;\n    }\n    my $last_inst = $i - 1;\n\n    # Print source lines\n    for (my $l = $first_line; $l <= $last_line; $l++) {\n      my $line = SourceLine($current_file, $l);\n      if (!defined($line)) {\n        $line = \"?\\n\";\n        next;\n      } else {\n        $line =~ s/^\\s+//;\n      }\n      printf(\"%6s %6s %5d: %s\",\n             UnparseAlt($flat_sum{$l}),\n             UnparseAlt($cum_sum{$l}),\n             $l,\n             $line);\n    }\n\n    # Print disassembly\n    for (my $x = $first_inst; $x <= $last_inst; $x++) {\n      my $e = $instructions[$x];\n      printf(\"%6s %6s    %8s: %6s\\n\",\n             UnparseAlt($flat_count[$x]),\n             UnparseAlt($cum_count[$x]),\n             UnparseAddress($offset, $e->[0]),\n             CleanDisassembly($e->[3]));\n    }\n  }\n}\n\n# Print DOT graph\nsub PrintDot {\n  my $prog = shift;\n  my $symbols = shift;\n  my $raw = shift;\n  my $flat = shift;\n  my $cumulative = shift;\n  my $overall_total = shift;\n\n  # Get total\n  my $local_total = TotalProfile($flat);\n  my $nodelimit = int($main::opt_nodefraction * $local_total);\n  my $edgelimit = int($main::opt_edgefraction * $local_total);\n  my $nodecount = $main::opt_nodecount;\n\n  # Find nodes to include\n  my @list = (sort { abs(GetEntry($cumulative, $b)) <=>\n                     abs(GetEntry($cumulative, $a))\n                     || $a cmp $b }\n              keys(%{$cumulative}));\n  my $last = $nodecount - 1;\n  if ($last > $#list) {\n    $last = $#list;\n  }\n  while (($last >= 0) &&\n         (abs(GetEntry($cumulative, $list[$last])) <= $nodelimit)) {\n    $last--;\n  }\n  if ($last < 0) {\n    print STDERR \"No nodes to print\\n\";\n    return 0;\n  }\n\n  if ($nodelimit > 0 || $edgelimit > 0) {\n    printf STDERR (\"Dropping nodes with <= %s %s; edges with <= %s abs(%s)\\n\",\n                   Unparse($nodelimit), Units(),\n                   Unparse($edgelimit), Units());\n  }\n\n  # Open DOT output file\n  my $output;\n  my $escaped_dot = ShellEscape(@DOT);\n  my $escaped_ps2pdf = ShellEscape(@PS2PDF);\n  if ($main::opt_gv) {\n    my $escaped_outfile = ShellEscape(TempName($main::next_tmpfile, \"ps\"));\n    $output = \"| $escaped_dot -Tps2 >$escaped_outfile\";\n  } elsif ($main::opt_evince) {\n    my $escaped_outfile = ShellEscape(TempName($main::next_tmpfile, \"pdf\"));\n    $output = \"| $escaped_dot -Tps2 | $escaped_ps2pdf - $escaped_outfile\";\n  } elsif ($main::opt_ps) {\n    $output = \"| $escaped_dot -Tps2\";\n  } elsif ($main::opt_pdf) {\n    $output = \"| $escaped_dot -Tps2 | $escaped_ps2pdf - -\";\n  } elsif ($main::opt_web || $main::opt_svg) {\n    # We need to post-process the SVG, so write to a temporary file always.\n    my $escaped_outfile = ShellEscape(TempName($main::next_tmpfile, \"svg\"));\n    $output = \"| $escaped_dot -Tsvg >$escaped_outfile\";\n  } elsif ($main::opt_gif) {\n    $output = \"| $escaped_dot -Tgif\";\n  } else {\n    $output = \">&STDOUT\";\n  }\n  open(DOT, $output) || error(\"$output: $!\\n\");\n\n  # Title\n  printf DOT (\"digraph \\\"%s; %s %s\\\" {\\n\",\n              $prog,\n              Unparse($overall_total),\n              Units());\n  if ($main::opt_pdf) {\n    # The output is more printable if we set the page size for dot.\n    printf DOT (\"size=\\\"8,11\\\"\\n\");\n  }\n  printf DOT (\"node [width=0.375,height=0.25];\\n\");\n\n  # Print legend\n  printf DOT (\"Legend [shape=box,fontsize=24,shape=plaintext,\" .\n              \"label=\\\"%s\\\\l%s\\\\l%s\\\\l%s\\\\l%s\\\\l\\\"];\\n\",\n              $prog,\n              sprintf(\"Total %s: %s\", Units(), Unparse($overall_total)),\n              sprintf(\"Focusing on: %s\", Unparse($local_total)),\n              sprintf(\"Dropped nodes with <= %s abs(%s)\",\n                      Unparse($nodelimit), Units()),\n              sprintf(\"Dropped edges with <= %s %s\",\n                      Unparse($edgelimit), Units())\n              );\n\n  # Print nodes\n  my %node = ();\n  my $nextnode = 1;\n  foreach my $a (@list[0..$last]) {\n    # Pick font size\n    my $f = GetEntry($flat, $a);\n    my $c = GetEntry($cumulative, $a);\n\n    my $fs = 8;\n    if ($local_total > 0) {\n      $fs = 8 + (50.0 * sqrt(abs($f * 1.0 / $local_total)));\n    }\n\n    $node{$a} = $nextnode++;\n    my $sym = $a;\n    $sym =~ s/\\s+/\\\\n/g;\n    $sym =~ s/::/\\\\n/g;\n\n    # Extra cumulative info to print for non-leaves\n    my $extra = \"\";\n    if ($f != $c) {\n      $extra = sprintf(\"\\\\rof %s (%s)\",\n                       Unparse($c),\n                       Percent($c, $local_total));\n    }\n    my $style = \"\";\n    if ($main::opt_heapcheck) {\n      if ($f > 0) {\n        # make leak-causing nodes more visible (add a background)\n        $style = \",style=filled,fillcolor=gray\"\n      } elsif ($f < 0) {\n        # make anti-leak-causing nodes (which almost never occur)\n        # stand out as well (triple border)\n        $style = \",peripheries=3\"\n      }\n    }\n\n    printf DOT (\"N%d [label=\\\"%s\\\\n%s (%s)%s\\\\r\" .\n                \"\\\",shape=box,fontsize=%.1f%s];\\n\",\n                $node{$a},\n                $sym,\n                Unparse($f),\n                Percent($f, $local_total),\n                $extra,\n                $fs,\n                $style,\n               );\n  }\n\n  # Get edges and counts per edge\n  my %edge = ();\n  my $n;\n  my $fullname_to_shortname_map = {};\n  FillFullnameToShortnameMap($symbols, $fullname_to_shortname_map);\n  foreach my $k (keys(%{$raw})) {\n    # TODO: omit low %age edges\n    $n = $raw->{$k};\n    my @translated = TranslateStack($symbols, $fullname_to_shortname_map, $k);\n    for (my $i = 1; $i <= $#translated; $i++) {\n      my $src = $translated[$i];\n      my $dst = $translated[$i-1];\n      #next if ($src eq $dst);  # Avoid self-edges?\n      if (exists($node{$src}) && exists($node{$dst})) {\n        my $edge_label = \"$src\\001$dst\";\n        if (!exists($edge{$edge_label})) {\n          $edge{$edge_label} = 0;\n        }\n        $edge{$edge_label} += $n;\n      }\n    }\n  }\n\n  # Print edges (process in order of decreasing counts)\n  my %indegree = ();   # Number of incoming edges added per node so far\n  my %outdegree = ();  # Number of outgoing edges added per node so far\n  foreach my $e (sort { $edge{$b} <=> $edge{$a} } keys(%edge)) {\n    my @x = split(/\\001/, $e);\n    $n = $edge{$e};\n\n    # Initialize degree of kept incoming and outgoing edges if necessary\n    my $src = $x[0];\n    my $dst = $x[1];\n    if (!exists($outdegree{$src})) { $outdegree{$src} = 0; }\n    if (!exists($indegree{$dst})) { $indegree{$dst} = 0; }\n\n    my $keep;\n    if ($indegree{$dst} == 0) {\n      # Keep edge if needed for reachability\n      $keep = 1;\n    } elsif (abs($n) <= $edgelimit) {\n      # Drop if we are below --edgefraction\n      $keep = 0;\n    } elsif ($outdegree{$src} >= $main::opt_maxdegree ||\n             $indegree{$dst} >= $main::opt_maxdegree) {\n      # Keep limited number of in/out edges per node\n      $keep = 0;\n    } else {\n      $keep = 1;\n    }\n\n    if ($keep) {\n      $outdegree{$src}++;\n      $indegree{$dst}++;\n\n      # Compute line width based on edge count\n      my $fraction = abs($local_total ? (3 * ($n / $local_total)) : 0);\n      if ($fraction > 1) { $fraction = 1; }\n      my $w = $fraction * 2;\n      if ($w < 1 && ($main::opt_web || $main::opt_svg)) {\n        # SVG output treats line widths < 1 poorly.\n        $w = 1;\n      }\n\n      # Dot sometimes segfaults if given edge weights that are too large, so\n      # we cap the weights at a large value\n      my $edgeweight = abs($n) ** 0.7;\n      if ($edgeweight > 100000) { $edgeweight = 100000; }\n      $edgeweight = int($edgeweight);\n\n      my $style = sprintf(\"setlinewidth(%f)\", $w);\n      if ($x[1] =~ m/\\(inline\\)/) {\n        $style .= \",dashed\";\n      }\n\n      # Use a slightly squashed function of the edge count as the weight\n      printf DOT (\"N%s -> N%s [label=%s, weight=%d, style=\\\"%s\\\"];\\n\",\n                  $node{$x[0]},\n                  $node{$x[1]},\n                  Unparse($n),\n                  $edgeweight,\n                  $style);\n    }\n  }\n\n  print DOT (\"}\\n\");\n  close(DOT);\n\n  if ($main::opt_web || $main::opt_svg) {\n    # Rewrite SVG to be more usable inside web browser.\n    RewriteSvg(TempName($main::next_tmpfile, \"svg\"));\n  }\n\n  return 1;\n}\n\nsub RewriteSvg {\n  my $svgfile = shift;\n\n  open(SVG, $svgfile) || die \"open temp svg: $!\";\n  my @svg = <SVG>;\n  close(SVG);\n  unlink $svgfile;\n  my $svg = join('', @svg);\n\n  # Dot's SVG output is\n  #\n  #    <svg width=\"___\" height=\"___\"\n  #     viewBox=\"___\" xmlns=...>\n  #    <g id=\"graph0\" transform=\"...\">\n  #    ...\n  #    </g>\n  #    </svg>\n  #\n  # Change it to\n  #\n  #    <svg width=\"100%\" height=\"100%\"\n  #     xmlns=...>\n  #    $svg_javascript\n  #    <g id=\"viewport\" transform=\"translate(0,0)\">\n  #    <g id=\"graph0\" transform=\"...\">\n  #    ...\n  #    </g>\n  #    </g>\n  #    </svg>\n\n  # Fix width, height; drop viewBox.\n  $svg =~ s/(?s)<svg width=\"[^\"]+\" height=\"[^\"]+\"(.*?)viewBox=\"[^\"]+\"/<svg width=\"100%\" height=\"100%\"$1/;\n\n  # Insert script, viewport <g> above first <g>\n  my $svg_javascript = SvgJavascript();\n  my $viewport = \"<g id=\\\"viewport\\\" transform=\\\"translate(0,0)\\\">\\n\";\n  $svg =~ s/<g id=\"graph\\d\"/$svg_javascript$viewport$&/;\n\n  # Insert final </g> above </svg>.\n  $svg =~ s/(.*)(<\\/svg>)/$1<\\/g>$2/;\n  $svg =~ s/<g id=\"graph\\d\"(.*?)/<g id=\"viewport\"$1/;\n\n  if ($main::opt_svg) {\n    # --svg: write to standard output.\n    print $svg;\n  } else {\n    # Write back to temporary file.\n    open(SVG, \">$svgfile\") || die \"open $svgfile: $!\";\n    print SVG $svg;\n    close(SVG);\n  }\n}\n\nsub SvgJavascript {\n  return <<'EOF';\n<script type=\"text/ecmascript\"><![CDATA[\n// SVGPan\n// http://www.cyberz.org/blog/2009/12/08/svgpan-a-javascript-svg-panzoomdrag-library/\n// Local modification: if(true || ...) below to force panning, never moving.\n\n/**\n *  SVGPan library 1.2\n * ====================\n *\n * Given an unique existing element with id \"viewport\", including the\n * the library into any SVG adds the following capabilities:\n *\n *  - Mouse panning\n *  - Mouse zooming (using the wheel)\n *  - Object dargging\n *\n * Known issues:\n *\n *  - Zooming (while panning) on Safari has still some issues\n *\n * Releases:\n *\n * 1.2, Sat Mar 20 08:42:50 GMT 2010, Zeng Xiaohui\n *\tFixed a bug with browser mouse handler interaction\n *\n * 1.1, Wed Feb  3 17:39:33 GMT 2010, Zeng Xiaohui\n *\tUpdated the zoom code to support the mouse wheel on Safari/Chrome\n *\n * 1.0, Andrea Leofreddi\n *\tFirst release\n *\n * This code is licensed under the following BSD license:\n *\n * Copyright 2009-2010 Andrea Leofreddi <a.leofreddi@itcharm.com>. All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without modification, are\n * permitted provided that the following conditions are met:\n *\n *    1. Redistributions of source code must retain the above copyright notice, this list of\n *       conditions and the following disclaimer.\n *\n *    2. Redistributions in binary form must reproduce the above copyright notice, this list\n *       of conditions and the following disclaimer in the documentation and/or other materials\n *       provided with the distribution.\n *\n * THIS SOFTWARE IS PROVIDED BY Andrea Leofreddi ``AS IS'' AND ANY EXPRESS OR IMPLIED\n * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND\n * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL Andrea Leofreddi OR\n * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR\n * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR\n * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON\n * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING\n * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF\n * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n *\n * The views and conclusions contained in the software and documentation are those of the\n * authors and should not be interpreted as representing official policies, either expressed\n * or implied, of Andrea Leofreddi.\n */\n\nvar root = document.documentElement;\n\nvar state = 'none', stateTarget, stateOrigin, stateTf;\n\nsetupHandlers(root);\n\n/**\n * Register handlers\n */\nfunction setupHandlers(root){\n\tsetAttributes(root, {\n\t\t\"onmouseup\" : \"add(evt)\",\n\t\t\"onmousedown\" : \"handleMouseDown(evt)\",\n\t\t\"onmousemove\" : \"handleMouseMove(evt)\",\n\t\t\"onmouseup\" : \"handleMouseUp(evt)\",\n\t\t//\"onmouseout\" : \"handleMouseUp(evt)\", // Decomment this to stop the pan functionality when dragging out of the SVG element\n\t});\n\n\tif(navigator.userAgent.toLowerCase().indexOf('webkit') >= 0)\n\t\twindow.addEventListener('mousewheel', handleMouseWheel, false); // Chrome/Safari\n\telse\n\t\twindow.addEventListener('DOMMouseScroll', handleMouseWheel, false); // Others\n\n\tvar g = svgDoc.getElementById(\"svg\");\n\tg.width = \"100%\";\n\tg.height = \"100%\";\n}\n\n/**\n * Instance an SVGPoint object with given event coordinates.\n */\nfunction getEventPoint(evt) {\n\tvar p = root.createSVGPoint();\n\n\tp.x = evt.clientX;\n\tp.y = evt.clientY;\n\n\treturn p;\n}\n\n/**\n * Sets the current transform matrix of an element.\n */\nfunction setCTM(element, matrix) {\n\tvar s = \"matrix(\" + matrix.a + \",\" + matrix.b + \",\" + matrix.c + \",\" + matrix.d + \",\" + matrix.e + \",\" + matrix.f + \")\";\n\n\telement.setAttribute(\"transform\", s);\n}\n\n/**\n * Dumps a matrix to a string (useful for debug).\n */\nfunction dumpMatrix(matrix) {\n\tvar s = \"[ \" + matrix.a + \", \" + matrix.c + \", \" + matrix.e + \"\\n  \" + matrix.b + \", \" + matrix.d + \", \" + matrix.f + \"\\n  0, 0, 1 ]\";\n\n\treturn s;\n}\n\n/**\n * Sets attributes of an element.\n */\nfunction setAttributes(element, attributes){\n\tfor (i in attributes)\n\t\telement.setAttributeNS(null, i, attributes[i]);\n}\n\n/**\n * Handle mouse move event.\n */\nfunction handleMouseWheel(evt) {\n\tif(evt.preventDefault)\n\t\tevt.preventDefault();\n\n\tevt.returnValue = false;\n\n\tvar svgDoc = evt.target.ownerDocument;\n\n\tvar delta;\n\n\tif(evt.wheelDelta)\n\t\tdelta = evt.wheelDelta / 3600; // Chrome/Safari\n\telse\n\t\tdelta = evt.detail / -90; // Mozilla\n\n\tvar z = 1 + delta; // Zoom factor: 0.9/1.1\n\n\tvar g = svgDoc.getElementById(\"viewport\");\n\n\tvar p = getEventPoint(evt);\n\n\tp = p.matrixTransform(g.getCTM().inverse());\n\n\t// Compute new scale matrix in current mouse position\n\tvar k = root.createSVGMatrix().translate(p.x, p.y).scale(z).translate(-p.x, -p.y);\n\n        setCTM(g, g.getCTM().multiply(k));\n\n\tstateTf = stateTf.multiply(k.inverse());\n}\n\n/**\n * Handle mouse move event.\n */\nfunction handleMouseMove(evt) {\n\tif(evt.preventDefault)\n\t\tevt.preventDefault();\n\n\tevt.returnValue = false;\n\n\tvar svgDoc = evt.target.ownerDocument;\n\n\tvar g = svgDoc.getElementById(\"viewport\");\n\n\tif(state == 'pan') {\n\t\t// Pan mode\n\t\tvar p = getEventPoint(evt).matrixTransform(stateTf);\n\n\t\tsetCTM(g, stateTf.inverse().translate(p.x - stateOrigin.x, p.y - stateOrigin.y));\n\t} else if(state == 'move') {\n\t\t// Move mode\n\t\tvar p = getEventPoint(evt).matrixTransform(g.getCTM().inverse());\n\n\t\tsetCTM(stateTarget, root.createSVGMatrix().translate(p.x - stateOrigin.x, p.y - stateOrigin.y).multiply(g.getCTM().inverse()).multiply(stateTarget.getCTM()));\n\n\t\tstateOrigin = p;\n\t}\n}\n\n/**\n * Handle click event.\n */\nfunction handleMouseDown(evt) {\n\tif(evt.preventDefault)\n\t\tevt.preventDefault();\n\n\tevt.returnValue = false;\n\n\tvar svgDoc = evt.target.ownerDocument;\n\n\tvar g = svgDoc.getElementById(\"viewport\");\n\n\tif(true || evt.target.tagName == \"svg\") {\n\t\t// Pan mode\n\t\tstate = 'pan';\n\n\t\tstateTf = g.getCTM().inverse();\n\n\t\tstateOrigin = getEventPoint(evt).matrixTransform(stateTf);\n\t} else {\n\t\t// Move mode\n\t\tstate = 'move';\n\n\t\tstateTarget = evt.target;\n\n\t\tstateTf = g.getCTM().inverse();\n\n\t\tstateOrigin = getEventPoint(evt).matrixTransform(stateTf);\n\t}\n}\n\n/**\n * Handle mouse button release event.\n */\nfunction handleMouseUp(evt) {\n\tif(evt.preventDefault)\n\t\tevt.preventDefault();\n\n\tevt.returnValue = false;\n\n\tvar svgDoc = evt.target.ownerDocument;\n\n\tif(state == 'pan' || state == 'move') {\n\t\t// Quit pan mode\n\t\tstate = '';\n\t}\n}\n\n]]></script>\nEOF\n}\n\n# Provides a map from fullname to shortname for cases where the\n# shortname is ambiguous.  The symlist has both the fullname and\n# shortname for all symbols, which is usually fine, but sometimes --\n# such as overloaded functions -- two different fullnames can map to\n# the same shortname.  In that case, we use the address of the\n# function to disambiguate the two.  This function fills in a map that\n# maps fullnames to modified shortnames in such cases.  If a fullname\n# is not present in the map, the 'normal' shortname provided by the\n# symlist is the appropriate one to use.\nsub FillFullnameToShortnameMap {\n  my $symbols = shift;\n  my $fullname_to_shortname_map = shift;\n  my $shortnames_seen_once = {};\n  my $shortnames_seen_more_than_once = {};\n\n  foreach my $symlist (values(%{$symbols})) {\n    # TODO(csilvers): deal with inlined symbols too.\n    my $shortname = $symlist->[0];\n    my $fullname = $symlist->[2];\n    if ($fullname !~ /<[0-9a-fA-F]+>$/) {  # fullname doesn't end in an address\n      next;       # the only collisions we care about are when addresses differ\n    }\n    if (defined($shortnames_seen_once->{$shortname}) &&\n        $shortnames_seen_once->{$shortname} ne $fullname) {\n      $shortnames_seen_more_than_once->{$shortname} = 1;\n    } else {\n      $shortnames_seen_once->{$shortname} = $fullname;\n    }\n  }\n\n  foreach my $symlist (values(%{$symbols})) {\n    my $shortname = $symlist->[0];\n    my $fullname = $symlist->[2];\n    # TODO(csilvers): take in a list of addresses we care about, and only\n    # store in the map if $symlist->[1] is in that list.  Saves space.\n    next if defined($fullname_to_shortname_map->{$fullname});\n    if (defined($shortnames_seen_more_than_once->{$shortname})) {\n      if ($fullname =~ /<0*([^>]*)>$/) {   # fullname has address at end of it\n        $fullname_to_shortname_map->{$fullname} = \"$shortname\\@$1\";\n      }\n    }\n  }\n}\n\n# Return a small number that identifies the argument.\n# Multiple calls with the same argument will return the same number.\n# Calls with different arguments will return different numbers.\nsub ShortIdFor {\n  my $key = shift;\n  my $id = $main::uniqueid{$key};\n  if (!defined($id)) {\n    $id = keys(%main::uniqueid) + 1;\n    $main::uniqueid{$key} = $id;\n  }\n  return $id;\n}\n\n# Translate a stack of addresses into a stack of symbols\nsub TranslateStack {\n  my $symbols = shift;\n  my $fullname_to_shortname_map = shift;\n  my $k = shift;\n\n  my @addrs = split(/\\n/, $k);\n  my @result = ();\n  for (my $i = 0; $i <= $#addrs; $i++) {\n    my $a = $addrs[$i];\n\n    # Skip large addresses since they sometimes show up as fake entries on RH9\n    if (length($a) > 8 && $a gt \"7fffffffffffffff\") {\n      next;\n    }\n\n    if ($main::opt_disasm || $main::opt_list) {\n      # We want just the address for the key\n      push(@result, $a);\n      next;\n    }\n\n    my $symlist = $symbols->{$a};\n    if (!defined($symlist)) {\n      $symlist = [$a, \"\", $a];\n    }\n\n    # We can have a sequence of symbols for a particular entry\n    # (more than one symbol in the case of inlining).  Callers\n    # come before callees in symlist, so walk backwards since\n    # the translated stack should contain callees before callers.\n    for (my $j = $#{$symlist}; $j >= 2; $j -= 3) {\n      my $func = $symlist->[$j-2];\n      my $fileline = $symlist->[$j-1];\n      my $fullfunc = $symlist->[$j];\n      if (defined($fullname_to_shortname_map->{$fullfunc})) {\n        $func = $fullname_to_shortname_map->{$fullfunc};\n      }\n      if ($j > 2) {\n        $func = \"$func (inline)\";\n      }\n\n      # Do not merge nodes corresponding to Callback::Run since that\n      # causes confusing cycles in dot display.  Instead, we synthesize\n      # a unique name for this frame per caller.\n      if ($func =~ m/Callback.*::Run$/) {\n        my $caller = ($i > 0) ? $addrs[$i-1] : 0;\n        $func = \"Run#\" . ShortIdFor($caller);\n      }\n\n      if ($main::opt_addresses) {\n        push(@result, \"$a $func $fileline\");\n      } elsif ($main::opt_lines) {\n        if ($func eq '??' && $fileline eq '??:0') {\n          push(@result, \"$a\");\n        } else {\n          push(@result, \"$func $fileline\");\n        }\n      } elsif ($main::opt_functions) {\n        if ($func eq '??') {\n          push(@result, \"$a\");\n        } else {\n          push(@result, $func);\n        }\n      } elsif ($main::opt_files) {\n        if ($fileline eq '??:0' || $fileline eq '') {\n          push(@result, \"$a\");\n        } else {\n          my $f = $fileline;\n          $f =~ s/:\\d+$//;\n          push(@result, $f);\n        }\n      } else {\n        push(@result, $a);\n        last;  # Do not print inlined info\n      }\n    }\n  }\n\n  # print join(\",\", @addrs), \" => \", join(\",\", @result), \"\\n\";\n  return @result;\n}\n\n# Generate percent string for a number and a total\nsub Percent {\n  my $num = shift;\n  my $tot = shift;\n  if ($tot != 0) {\n    return sprintf(\"%.1f%%\", $num * 100.0 / $tot);\n  } else {\n    return ($num == 0) ? \"nan\" : (($num > 0) ? \"+inf\" : \"-inf\");\n  }\n}\n\n# Generate pretty-printed form of number\nsub Unparse {\n  my $num = shift;\n  if ($main::profile_type eq 'heap' || $main::profile_type eq 'growth') {\n    if ($main::opt_inuse_objects || $main::opt_alloc_objects) {\n      return sprintf(\"%d\", $num);\n    } else {\n      if ($main::opt_show_bytes) {\n        return sprintf(\"%d\", $num);\n      } else {\n        return sprintf(\"%.1f\", $num / 1048576.0);\n      }\n    }\n  } elsif ($main::profile_type eq 'contention' && !$main::opt_contentions) {\n    return sprintf(\"%.3f\", $num / 1e9); # Convert nanoseconds to seconds\n  } else {\n    return sprintf(\"%d\", $num);\n  }\n}\n\n# Alternate pretty-printed form: 0 maps to \".\"\nsub UnparseAlt {\n  my $num = shift;\n  if ($num == 0) {\n    return \".\";\n  } else {\n    return Unparse($num);\n  }\n}\n\n# Alternate pretty-printed form: 0 maps to \"\"\nsub HtmlPrintNumber {\n  my $num = shift;\n  if ($num == 0) {\n    return \"\";\n  } else {\n    return Unparse($num);\n  }\n}\n\n# Return output units\nsub Units {\n  if ($main::profile_type eq 'heap' || $main::profile_type eq 'growth') {\n    if ($main::opt_inuse_objects || $main::opt_alloc_objects) {\n      return \"objects\";\n    } else {\n      if ($main::opt_show_bytes) {\n        return \"B\";\n      } else {\n        return \"MB\";\n      }\n    }\n  } elsif ($main::profile_type eq 'contention' && !$main::opt_contentions) {\n    return \"seconds\";\n  } else {\n    return \"samples\";\n  }\n}\n\n##### Profile manipulation code #####\n\n# Generate flattened profile:\n# If count is charged to stack [a,b,c,d], in generated profile,\n# it will be charged to [a]\nsub FlatProfile {\n  my $profile = shift;\n  my $result = {};\n  foreach my $k (keys(%{$profile})) {\n    my $count = $profile->{$k};\n    my @addrs = split(/\\n/, $k);\n    if ($#addrs >= 0) {\n      AddEntry($result, $addrs[0], $count);\n    }\n  }\n  return $result;\n}\n\n# Generate cumulative profile:\n# If count is charged to stack [a,b,c,d], in generated profile,\n# it will be charged to [a], [b], [c], [d]\nsub CumulativeProfile {\n  my $profile = shift;\n  my $result = {};\n  foreach my $k (keys(%{$profile})) {\n    my $count = $profile->{$k};\n    my @addrs = split(/\\n/, $k);\n    foreach my $a (@addrs) {\n      AddEntry($result, $a, $count);\n    }\n  }\n  return $result;\n}\n\n# If the second-youngest PC on the stack is always the same, returns\n# that pc.  Otherwise, returns undef.\nsub IsSecondPcAlwaysTheSame {\n  my $profile = shift;\n\n  my $second_pc = undef;\n  foreach my $k (keys(%{$profile})) {\n    my @addrs = split(/\\n/, $k);\n    if ($#addrs < 1) {\n      return undef;\n    }\n    if (not defined $second_pc) {\n      $second_pc = $addrs[1];\n    } else {\n      if ($second_pc ne $addrs[1]) {\n        return undef;\n      }\n    }\n  }\n  return $second_pc;\n}\n\nsub ExtractSymbolLocation {\n  my $symbols = shift;\n  my $address = shift;\n  # 'addr2line' outputs \"??:0\" for unknown locations; we do the\n  # same to be consistent.\n  my $location = \"??:0:unknown\";\n  if (exists $symbols->{$address}) {\n    my $file = $symbols->{$address}->[1];\n    if ($file eq \"?\") {\n      $file = \"??:0\"\n    }\n    $location = $file . \":\" . $symbols->{$address}->[0];\n  }\n  return $location;\n}\n\n# Extracts a graph of calls.\nsub ExtractCalls {\n  my $symbols = shift;\n  my $profile = shift;\n\n  my $calls = {};\n  while( my ($stack_trace, $count) = each %$profile ) {\n    my @address = split(/\\n/, $stack_trace);\n    my $destination = ExtractSymbolLocation($symbols, $address[0]);\n    AddEntry($calls, $destination, $count);\n    for (my $i = 1; $i <= $#address; $i++) {\n      my $source = ExtractSymbolLocation($symbols, $address[$i]);\n      my $call = \"$source -> $destination\";\n      AddEntry($calls, $call, $count);\n      $destination = $source;\n    }\n  }\n\n  return $calls;\n}\n\nsub FilterFrames {\n  my $symbols = shift;\n  my $profile = shift;\n\n  if ($main::opt_retain eq '' && $main::opt_exclude eq '') {\n    return $profile;\n  }\n\n  my $result = {};\n  foreach my $k (keys(%{$profile})) {\n    my $count = $profile->{$k};\n    my @addrs = split(/\\n/, $k);\n    my @path = ();\n    foreach my $a (@addrs) {\n      my $sym;\n      if (exists($symbols->{$a})) {\n        $sym = $symbols->{$a}->[0];\n      } else {\n        $sym = $a;\n      }\n      if ($main::opt_retain ne '' && $sym !~ m/$main::opt_retain/) {\n        next;\n      }\n      if ($main::opt_exclude ne '' && $sym =~ m/$main::opt_exclude/) {\n        next;\n      }\n      push(@path, $a);\n    }\n    if (scalar(@path) > 0) {\n      my $reduced_path = join(\"\\n\", @path);\n      AddEntry($result, $reduced_path, $count);\n    }\n  }\n\n  return $result;\n}\n\nsub RemoveUninterestingFrames {\n  my $symbols = shift;\n  my $profile = shift;\n\n  # List of function names to skip\n  my %skip = ();\n  my $skip_regexp = 'NOMATCH';\n  if ($main::profile_type eq 'heap' || $main::profile_type eq 'growth') {\n    foreach my $name ('calloc',\n                      'cfree',\n                      'malloc',\n                      'free',\n                      'memalign',\n                      'posix_memalign',\n                      'aligned_alloc',\n                      'pvalloc',\n                      'valloc',\n                      'realloc',\n                      'mallocx', # jemalloc\n                      'rallocx', # jemalloc\n                      'xallocx', # jemalloc\n                      'dallocx', # jemalloc\n                      'sdallocx', # jemalloc\n                      'tc_calloc',\n                      'tc_cfree',\n                      'tc_malloc',\n                      'tc_free',\n                      'tc_memalign',\n                      'tc_posix_memalign',\n                      'tc_pvalloc',\n                      'tc_valloc',\n                      'tc_realloc',\n                      'tc_new',\n                      'tc_delete',\n                      'tc_newarray',\n                      'tc_deletearray',\n                      'tc_new_nothrow',\n                      'tc_newarray_nothrow',\n                      'do_malloc',\n                      '::do_malloc',   # new name -- got moved to an unnamed ns\n                      '::do_malloc_or_cpp_alloc',\n                      'DoSampledAllocation',\n                      'simple_alloc::allocate',\n                      '__malloc_alloc_template::allocate',\n                      '__builtin_delete',\n                      '__builtin_new',\n                      '__builtin_vec_delete',\n                      '__builtin_vec_new',\n                      'operator new',\n                      'operator new[]',\n                      # The entry to our memory-allocation routines on OS X\n                      'malloc_zone_malloc',\n                      'malloc_zone_calloc',\n                      'malloc_zone_valloc',\n                      'malloc_zone_realloc',\n                      'malloc_zone_memalign',\n                      'malloc_zone_free',\n                      # These mark the beginning/end of our custom sections\n                      '__start_google_malloc',\n                      '__stop_google_malloc',\n                      '__start_malloc_hook',\n                      '__stop_malloc_hook') {\n      $skip{$name} = 1;\n      $skip{\"_\" . $name} = 1;   # Mach (OS X) adds a _ prefix to everything\n    }\n    # TODO: Remove TCMalloc once everything has been\n    # moved into the tcmalloc:: namespace and we have flushed\n    # old code out of the system.\n    $skip_regexp = \"TCMalloc|^tcmalloc::\";\n  } elsif ($main::profile_type eq 'contention') {\n    foreach my $vname ('base::RecordLockProfileData',\n                       'base::SubmitMutexProfileData',\n                       'base::SubmitSpinLockProfileData',\n                       'Mutex::Unlock',\n                       'Mutex::UnlockSlow',\n                       'Mutex::ReaderUnlock',\n                       'MutexLock::~MutexLock',\n                       'SpinLock::Unlock',\n                       'SpinLock::SlowUnlock',\n                       'SpinLockHolder::~SpinLockHolder') {\n      $skip{$vname} = 1;\n    }\n  } elsif ($main::profile_type eq 'cpu') {\n    # Drop signal handlers used for CPU profile collection\n    # TODO(dpeng): this should not be necessary; it's taken\n    # care of by the general 2nd-pc mechanism below.\n    foreach my $name ('ProfileData::Add',           # historical\n                      'ProfileData::prof_handler',  # historical\n                      'CpuProfiler::prof_handler',\n                      '__FRAME_END__',\n                      '__pthread_sighandler',\n                      '__restore') {\n      $skip{$name} = 1;\n    }\n  } else {\n    # Nothing skipped for unknown types\n  }\n\n  if ($main::profile_type eq 'cpu') {\n    # If all the second-youngest program counters are the same,\n    # this STRONGLY suggests that it is an artifact of measurement,\n    # i.e., stack frames pushed by the CPU profiler signal handler.\n    # Hence, we delete them.\n    # (The topmost PC is read from the signal structure, not from\n    # the stack, so it does not get involved.)\n    while (my $second_pc = IsSecondPcAlwaysTheSame($profile)) {\n      my $result = {};\n      my $func = '';\n      if (exists($symbols->{$second_pc})) {\n        $second_pc = $symbols->{$second_pc}->[0];\n      }\n      print STDERR \"Removing $second_pc from all stack traces.\\n\";\n      foreach my $k (keys(%{$profile})) {\n        my $count = $profile->{$k};\n        my @addrs = split(/\\n/, $k);\n        splice @addrs, 1, 1;\n        my $reduced_path = join(\"\\n\", @addrs);\n        AddEntry($result, $reduced_path, $count);\n      }\n      $profile = $result;\n    }\n  }\n\n  my $result = {};\n  foreach my $k (keys(%{$profile})) {\n    my $count = $profile->{$k};\n    my @addrs = split(/\\n/, $k);\n    my @path = ();\n    foreach my $a (@addrs) {\n      if (exists($symbols->{$a})) {\n        my $func = $symbols->{$a}->[0];\n        if ($skip{$func} || ($func =~ m/$skip_regexp/)) {\n          # Throw away the portion of the backtrace seen so far, under the\n          # assumption that previous frames were for functions internal to the\n          # allocator.\n          @path = ();\n          next;\n        }\n      }\n      push(@path, $a);\n    }\n    my $reduced_path = join(\"\\n\", @path);\n    AddEntry($result, $reduced_path, $count);\n  }\n\n  $result = FilterFrames($symbols, $result);\n\n  return $result;\n}\n\n# Reduce profile to granularity given by user\nsub ReduceProfile {\n  my $symbols = shift;\n  my $profile = shift;\n  my $result = {};\n  my $fullname_to_shortname_map = {};\n  FillFullnameToShortnameMap($symbols, $fullname_to_shortname_map);\n  foreach my $k (keys(%{$profile})) {\n    my $count = $profile->{$k};\n    my @translated = TranslateStack($symbols, $fullname_to_shortname_map, $k);\n    my @path = ();\n    my %seen = ();\n    $seen{''} = 1;      # So that empty keys are skipped\n    foreach my $e (@translated) {\n      # To avoid double-counting due to recursion, skip a stack-trace\n      # entry if it has already been seen\n      if (!$seen{$e}) {\n        $seen{$e} = 1;\n        push(@path, $e);\n      }\n    }\n    my $reduced_path = join(\"\\n\", @path);\n    AddEntry($result, $reduced_path, $count);\n  }\n  return $result;\n}\n\n# Does the specified symbol array match the regexp?\nsub SymbolMatches {\n  my $sym = shift;\n  my $re = shift;\n  if (defined($sym)) {\n    for (my $i = 0; $i < $#{$sym}; $i += 3) {\n      if ($sym->[$i] =~ m/$re/ || $sym->[$i+1] =~ m/$re/) {\n        return 1;\n      }\n    }\n  }\n  return 0;\n}\n\n# Focus only on paths involving specified regexps\nsub FocusProfile {\n  my $symbols = shift;\n  my $profile = shift;\n  my $focus = shift;\n  my $result = {};\n  foreach my $k (keys(%{$profile})) {\n    my $count = $profile->{$k};\n    my @addrs = split(/\\n/, $k);\n    foreach my $a (@addrs) {\n      # Reply if it matches either the address/shortname/fileline\n      if (($a =~ m/$focus/) || SymbolMatches($symbols->{$a}, $focus)) {\n        AddEntry($result, $k, $count);\n        last;\n      }\n    }\n  }\n  return $result;\n}\n\n# Focus only on paths not involving specified regexps\nsub IgnoreProfile {\n  my $symbols = shift;\n  my $profile = shift;\n  my $ignore = shift;\n  my $result = {};\n  foreach my $k (keys(%{$profile})) {\n    my $count = $profile->{$k};\n    my @addrs = split(/\\n/, $k);\n    my $matched = 0;\n    foreach my $a (@addrs) {\n      # Reply if it matches either the address/shortname/fileline\n      if (($a =~ m/$ignore/) || SymbolMatches($symbols->{$a}, $ignore)) {\n        $matched = 1;\n        last;\n      }\n    }\n    if (!$matched) {\n      AddEntry($result, $k, $count);\n    }\n  }\n  return $result;\n}\n\n# Get total count in profile\nsub TotalProfile {\n  my $profile = shift;\n  my $result = 0;\n  foreach my $k (keys(%{$profile})) {\n    $result += $profile->{$k};\n  }\n  return $result;\n}\n\n# Add A to B\nsub AddProfile {\n  my $A = shift;\n  my $B = shift;\n\n  my $R = {};\n  # add all keys in A\n  foreach my $k (keys(%{$A})) {\n    my $v = $A->{$k};\n    AddEntry($R, $k, $v);\n  }\n  # add all keys in B\n  foreach my $k (keys(%{$B})) {\n    my $v = $B->{$k};\n    AddEntry($R, $k, $v);\n  }\n  return $R;\n}\n\n# Merges symbol maps\nsub MergeSymbols {\n  my $A = shift;\n  my $B = shift;\n\n  my $R = {};\n  foreach my $k (keys(%{$A})) {\n    $R->{$k} = $A->{$k};\n  }\n  if (defined($B)) {\n    foreach my $k (keys(%{$B})) {\n      $R->{$k} = $B->{$k};\n    }\n  }\n  return $R;\n}\n\n\n# Add A to B\nsub AddPcs {\n  my $A = shift;\n  my $B = shift;\n\n  my $R = {};\n  # add all keys in A\n  foreach my $k (keys(%{$A})) {\n    $R->{$k} = 1\n  }\n  # add all keys in B\n  foreach my $k (keys(%{$B})) {\n    $R->{$k} = 1\n  }\n  return $R;\n}\n\n# Subtract B from A\nsub SubtractProfile {\n  my $A = shift;\n  my $B = shift;\n\n  my $R = {};\n  foreach my $k (keys(%{$A})) {\n    my $v = $A->{$k} - GetEntry($B, $k);\n    if ($v < 0 && $main::opt_drop_negative) {\n      $v = 0;\n    }\n    AddEntry($R, $k, $v);\n  }\n  if (!$main::opt_drop_negative) {\n    # Take care of when subtracted profile has more entries\n    foreach my $k (keys(%{$B})) {\n      if (!exists($A->{$k})) {\n        AddEntry($R, $k, 0 - $B->{$k});\n      }\n    }\n  }\n  return $R;\n}\n\n# Get entry from profile; zero if not present\nsub GetEntry {\n  my $profile = shift;\n  my $k = shift;\n  if (exists($profile->{$k})) {\n    return $profile->{$k};\n  } else {\n    return 0;\n  }\n}\n\n# Add entry to specified profile\nsub AddEntry {\n  my $profile = shift;\n  my $k = shift;\n  my $n = shift;\n  if (!exists($profile->{$k})) {\n    $profile->{$k} = 0;\n  }\n  $profile->{$k} += $n;\n}\n\n# Add a stack of entries to specified profile, and add them to the $pcs\n# list.\nsub AddEntries {\n  my $profile = shift;\n  my $pcs = shift;\n  my $stack = shift;\n  my $count = shift;\n  my @k = ();\n\n  foreach my $e (split(/\\s+/, $stack)) {\n    my $pc = HexExtend($e);\n    $pcs->{$pc} = 1;\n    push @k, $pc;\n  }\n  AddEntry($profile, (join \"\\n\", @k), $count);\n}\n\n##### Code to profile a server dynamically #####\n\nsub CheckSymbolPage {\n  my $url = SymbolPageURL();\n  my $command = ShellEscape(@URL_FETCHER, $url);\n  open(SYMBOL, \"$command |\") or error($command);\n  my $line = <SYMBOL>;\n  $line =~ s/\\r//g;         # turn windows-looking lines into unix-looking lines\n  close(SYMBOL);\n  unless (defined($line)) {\n    error(\"$url doesn't exist\\n\");\n  }\n\n  if ($line =~ /^num_symbols:\\s+(\\d+)$/) {\n    if ($1 == 0) {\n      error(\"Stripped binary. No symbols available.\\n\");\n    }\n  } else {\n    error(\"Failed to get the number of symbols from $url\\n\");\n  }\n}\n\nsub IsProfileURL {\n  my $profile_name = shift;\n  if (-f $profile_name) {\n    printf STDERR \"Using local file $profile_name.\\n\";\n    return 0;\n  }\n  return 1;\n}\n\nsub ParseProfileURL {\n  my $profile_name = shift;\n\n  if (!defined($profile_name) || $profile_name eq \"\") {\n    return ();\n  }\n\n  # Split profile URL - matches all non-empty strings, so no test.\n  $profile_name =~ m,^(https?://)?([^/]+)(.*?)(/|$PROFILES)?$,;\n\n  my $proto = $1 || \"http://\";\n  my $hostport = $2;\n  my $prefix = $3;\n  my $profile = $4 || \"/\";\n\n  my $host = $hostport;\n  $host =~ s/:.*//;\n\n  my $baseurl = \"$proto$hostport$prefix\";\n  return ($host, $baseurl, $profile);\n}\n\n# We fetch symbols from the first profile argument.\nsub SymbolPageURL {\n  my ($host, $baseURL, $path) = ParseProfileURL($main::pfile_args[0]);\n  return \"$baseURL$SYMBOL_PAGE\";\n}\n\nsub FetchProgramName() {\n  my ($host, $baseURL, $path) = ParseProfileURL($main::pfile_args[0]);\n  my $url = \"$baseURL$PROGRAM_NAME_PAGE\";\n  my $command_line = ShellEscape(@URL_FETCHER, $url);\n  open(CMDLINE, \"$command_line |\") or error($command_line);\n  my $cmdline = <CMDLINE>;\n  $cmdline =~ s/\\r//g;   # turn windows-looking lines into unix-looking lines\n  close(CMDLINE);\n  error(\"Failed to get program name from $url\\n\") unless defined($cmdline);\n  $cmdline =~ s/\\x00.+//;  # Remove argv[1] and latters.\n  $cmdline =~ s!\\n!!g;  # Remove LFs.\n  return $cmdline;\n}\n\n# Gee, curl's -L (--location) option isn't reliable at least\n# with its 7.12.3 version.  Curl will forget to post data if\n# there is a redirection.  This function is a workaround for\n# curl.  Redirection happens on borg hosts.\nsub ResolveRedirectionForCurl {\n  my $url = shift;\n  my $command_line = ShellEscape(@URL_FETCHER, \"--head\", $url);\n  open(CMDLINE, \"$command_line |\") or error($command_line);\n  while (<CMDLINE>) {\n    s/\\r//g;         # turn windows-looking lines into unix-looking lines\n    if (/^Location: (.*)/) {\n      $url = $1;\n    }\n  }\n  close(CMDLINE);\n  return $url;\n}\n\n# Add a timeout flat to URL_FETCHER.  Returns a new list.\nsub AddFetchTimeout {\n  my $timeout = shift;\n  my @fetcher = @_;\n  if (defined($timeout)) {\n    if (join(\" \", @fetcher) =~ m/\\bcurl -s/) {\n      push(@fetcher, \"--max-time\", sprintf(\"%d\", $timeout));\n    } elsif (join(\" \", @fetcher) =~ m/\\brpcget\\b/) {\n      push(@fetcher, sprintf(\"--deadline=%d\", $timeout));\n    }\n  }\n  return @fetcher;\n}\n\n# Reads a symbol map from the file handle name given as $1, returning\n# the resulting symbol map.  Also processes variables relating to symbols.\n# Currently, the only variable processed is 'binary=<value>' which updates\n# $main::prog to have the correct program name.\nsub ReadSymbols {\n  my $in = shift;\n  my $map = {};\n  while (<$in>) {\n    s/\\r//g;         # turn windows-looking lines into unix-looking lines\n    # Removes all the leading zeroes from the symbols, see comment below.\n    if (m/^0x0*([0-9a-f]+)\\s+(.+)/) {\n      $map->{$1} = $2;\n    } elsif (m/^---/) {\n      last;\n    } elsif (m/^([a-z][^=]*)=(.*)$/ ) {\n      my ($variable, $value) = ($1, $2);\n      for ($variable, $value) {\n        s/^\\s+//;\n        s/\\s+$//;\n      }\n      if ($variable eq \"binary\") {\n        if ($main::prog ne $UNKNOWN_BINARY && $main::prog ne $value) {\n          printf STDERR (\"Warning: Mismatched binary name '%s', using '%s'.\\n\",\n                         $main::prog, $value);\n        }\n        $main::prog = $value;\n      } else {\n        printf STDERR (\"Ignoring unknown variable in symbols list: \" .\n            \"'%s' = '%s'\\n\", $variable, $value);\n      }\n    }\n  }\n  return $map;\n}\n\nsub URLEncode {\n  my $str = shift;\n  $str =~ s/([^A-Za-z0-9\\-_.!~*'()])/ sprintf \"%%%02x\", ord $1 /eg;\n  return $str;\n}\n\nsub AppendSymbolFilterParams {\n  my $url = shift;\n  my @params = ();\n  if ($main::opt_retain ne '') {\n    push(@params, sprintf(\"retain=%s\", URLEncode($main::opt_retain)));\n  }\n  if ($main::opt_exclude ne '') {\n    push(@params, sprintf(\"exclude=%s\", URLEncode($main::opt_exclude)));\n  }\n  if (scalar @params > 0) {\n    $url = sprintf(\"%s?%s\", $url, join(\"&\", @params));\n  }\n  return $url;\n}\n\n# Fetches and processes symbols to prepare them for use in the profile output\n# code.  If the optional 'symbol_map' arg is not given, fetches symbols from\n# $SYMBOL_PAGE for all PC values found in profile.  Otherwise, the raw symbols\n# are assumed to have already been fetched into 'symbol_map' and are simply\n# extracted and processed.\nsub FetchSymbols {\n  my $pcset = shift;\n  my $symbol_map = shift;\n\n  my %seen = ();\n  my @pcs = grep { !$seen{$_}++ } keys(%$pcset);  # uniq\n\n  if (!defined($symbol_map)) {\n    my $post_data = join(\"+\", sort((map {\"0x\" . \"$_\"} @pcs)));\n\n    open(POSTFILE, \">$main::tmpfile_sym\");\n    print POSTFILE $post_data;\n    close(POSTFILE);\n\n    my $url = SymbolPageURL();\n\n    my $command_line;\n    if (join(\" \", @URL_FETCHER) =~ m/\\bcurl -s/) {\n      $url = ResolveRedirectionForCurl($url);\n      $url = AppendSymbolFilterParams($url);\n      $command_line = ShellEscape(@URL_FETCHER, \"-d\", \"\\@$main::tmpfile_sym\",\n                                  $url);\n    } else {\n      $url = AppendSymbolFilterParams($url);\n      $command_line = (ShellEscape(@URL_FETCHER, \"--post\", $url)\n                       . \" < \" . ShellEscape($main::tmpfile_sym));\n    }\n    # We use c++filt in case $SYMBOL_PAGE gives us mangled symbols.\n    my $escaped_cppfilt = ShellEscape($obj_tool_map{\"c++filt\"});\n    open(SYMBOL, \"$command_line | $escaped_cppfilt |\") or error($command_line);\n    $symbol_map = ReadSymbols(*SYMBOL{IO});\n    close(SYMBOL);\n  }\n\n  my $symbols = {};\n  foreach my $pc (@pcs) {\n    my $fullname;\n    # For 64 bits binaries, symbols are extracted with 8 leading zeroes.\n    # Then /symbol reads the long symbols in as uint64, and outputs\n    # the result with a \"0x%08llx\" format which get rid of the zeroes.\n    # By removing all the leading zeroes in both $pc and the symbols from\n    # /symbol, the symbols match and are retrievable from the map.\n    my $shortpc = $pc;\n    $shortpc =~ s/^0*//;\n    # Each line may have a list of names, which includes the function\n    # and also other functions it has inlined.  They are separated (in\n    # PrintSymbolizedProfile), by --, which is illegal in function names.\n    my $fullnames;\n    if (defined($symbol_map->{$shortpc})) {\n      $fullnames = $symbol_map->{$shortpc};\n    } else {\n      $fullnames = \"0x\" . $pc;  # Just use addresses\n    }\n    my $sym = [];\n    $symbols->{$pc} = $sym;\n    foreach my $fullname (split(\"--\", $fullnames)) {\n      my $name = ShortFunctionName($fullname);\n      push(@{$sym}, $name, \"?\", $fullname);\n    }\n  }\n  return $symbols;\n}\n\nsub BaseName {\n  my $file_name = shift;\n  $file_name =~ s!^.*/!!;  # Remove directory name\n  return $file_name;\n}\n\nsub MakeProfileBaseName {\n  my ($binary_name, $profile_name) = @_;\n  my ($host, $baseURL, $path) = ParseProfileURL($profile_name);\n  my $binary_shortname = BaseName($binary_name);\n  return sprintf(\"%s.%s.%s\",\n                 $binary_shortname, $main::op_time, $host);\n}\n\nsub FetchDynamicProfile {\n  my $binary_name = shift;\n  my $profile_name = shift;\n  my $fetch_name_only = shift;\n  my $encourage_patience = shift;\n\n  if (!IsProfileURL($profile_name)) {\n    return $profile_name;\n  } else {\n    my ($host, $baseURL, $path) = ParseProfileURL($profile_name);\n    if ($path eq \"\" || $path eq \"/\") {\n      # Missing type specifier defaults to cpu-profile\n      $path = $PROFILE_PAGE;\n    }\n\n    my $profile_file = MakeProfileBaseName($binary_name, $profile_name);\n\n    my $url = \"$baseURL$path\";\n    my $fetch_timeout = undef;\n    if ($path =~ m/$PROFILE_PAGE|$PMUPROFILE_PAGE/) {\n      if ($path =~ m/[?]/) {\n        $url .= \"&\";\n      } else {\n        $url .= \"?\";\n      }\n      $url .= sprintf(\"seconds=%d\", $main::opt_seconds);\n      $fetch_timeout = $main::opt_seconds * 1.01 + 60;\n      # Set $profile_type for consumption by PrintSymbolizedProfile.\n      $main::profile_type = 'cpu';\n    } else {\n      # For non-CPU profiles, we add a type-extension to\n      # the target profile file name.\n      my $suffix = $path;\n      $suffix =~ s,/,.,g;\n      $profile_file .= $suffix;\n      # Set $profile_type for consumption by PrintSymbolizedProfile.\n      if ($path =~ m/$HEAP_PAGE/) {\n        $main::profile_type = 'heap';\n      } elsif ($path =~ m/$GROWTH_PAGE/) {\n        $main::profile_type = 'growth';\n      } elsif ($path =~ m/$CONTENTION_PAGE/) {\n        $main::profile_type = 'contention';\n      }\n    }\n\n    my $profile_dir = $ENV{\"JEPROF_TMPDIR\"} || ($ENV{HOME} . \"/jeprof\");\n    if (! -d $profile_dir) {\n      mkdir($profile_dir)\n          || die(\"Unable to create profile directory $profile_dir: $!\\n\");\n    }\n    my $tmp_profile = \"$profile_dir/.tmp.$profile_file\";\n    my $real_profile = \"$profile_dir/$profile_file\";\n\n    if ($fetch_name_only > 0) {\n      return $real_profile;\n    }\n\n    my @fetcher = AddFetchTimeout($fetch_timeout, @URL_FETCHER);\n    my $cmd = ShellEscape(@fetcher, $url) . \" > \" . ShellEscape($tmp_profile);\n    if ($path =~ m/$PROFILE_PAGE|$PMUPROFILE_PAGE|$CENSUSPROFILE_PAGE/){\n      print STDERR \"Gathering CPU profile from $url for $main::opt_seconds seconds to\\n  ${real_profile}\\n\";\n      if ($encourage_patience) {\n        print STDERR \"Be patient...\\n\";\n      }\n    } else {\n      print STDERR \"Fetching $path profile from $url to\\n  ${real_profile}\\n\";\n    }\n\n    (system($cmd) == 0) || error(\"Failed to get profile: $cmd: $!\\n\");\n    (system(\"mv\", $tmp_profile, $real_profile) == 0) || error(\"Unable to rename profile\\n\");\n    print STDERR \"Wrote profile to $real_profile\\n\";\n    $main::collected_profile = $real_profile;\n    return $main::collected_profile;\n  }\n}\n\n# Collect profiles in parallel\nsub FetchDynamicProfiles {\n  my $items = scalar(@main::pfile_args);\n  my $levels = log($items) / log(2);\n\n  if ($items == 1) {\n    $main::profile_files[0] = FetchDynamicProfile($main::prog, $main::pfile_args[0], 0, 1);\n  } else {\n    # math rounding issues\n    if ((2 ** $levels) < $items) {\n     $levels++;\n    }\n    my $count = scalar(@main::pfile_args);\n    for (my $i = 0; $i < $count; $i++) {\n      $main::profile_files[$i] = FetchDynamicProfile($main::prog, $main::pfile_args[$i], 1, 0);\n    }\n    print STDERR \"Fetching $count profiles, Be patient...\\n\";\n    FetchDynamicProfilesRecurse($levels, 0, 0);\n    $main::collected_profile = join(\" \\\\\\n    \", @main::profile_files);\n  }\n}\n\n# Recursively fork a process to get enough processes\n# collecting profiles\nsub FetchDynamicProfilesRecurse {\n  my $maxlevel = shift;\n  my $level = shift;\n  my $position = shift;\n\n  if (my $pid = fork()) {\n    $position = 0 | ($position << 1);\n    TryCollectProfile($maxlevel, $level, $position);\n    wait;\n  } else {\n    $position = 1 | ($position << 1);\n    TryCollectProfile($maxlevel, $level, $position);\n    cleanup();\n    exit(0);\n  }\n}\n\n# Collect a single profile\nsub TryCollectProfile {\n  my $maxlevel = shift;\n  my $level = shift;\n  my $position = shift;\n\n  if ($level >= ($maxlevel - 1)) {\n    if ($position < scalar(@main::pfile_args)) {\n      FetchDynamicProfile($main::prog, $main::pfile_args[$position], 0, 0);\n    }\n  } else {\n    FetchDynamicProfilesRecurse($maxlevel, $level+1, $position);\n  }\n}\n\n##### Parsing code #####\n\n# Provide a small streaming-read module to handle very large\n# cpu-profile files.  Stream in chunks along a sliding window.\n# Provides an interface to get one 'slot', correctly handling\n# endian-ness differences.  A slot is one 32-bit or 64-bit word\n# (depending on the input profile).  We tell endianness and bit-size\n# for the profile by looking at the first 8 bytes: in cpu profiles,\n# the second slot is always 3 (we'll accept anything that's not 0).\nBEGIN {\n  package CpuProfileStream;\n\n  sub new {\n    my ($class, $file, $fname) = @_;\n    my $self = { file        => $file,\n                 base        => 0,\n                 stride      => 512 * 1024,   # must be a multiple of bitsize/8\n                 slots       => [],\n                 unpack_code => \"\",           # N for big-endian, V for little\n                 perl_is_64bit => 1,          # matters if profile is 64-bit\n    };\n    bless $self, $class;\n    # Let unittests adjust the stride\n    if ($main::opt_test_stride > 0) {\n      $self->{stride} = $main::opt_test_stride;\n    }\n    # Read the first two slots to figure out bitsize and endianness.\n    my $slots = $self->{slots};\n    my $str;\n    read($self->{file}, $str, 8);\n    # Set the global $address_length based on what we see here.\n    # 8 is 32-bit (8 hexadecimal chars); 16 is 64-bit (16 hexadecimal chars).\n    $address_length = ($str eq (chr(0)x8)) ? 16 : 8;\n    if ($address_length == 8) {\n      if (substr($str, 6, 2) eq chr(0)x2) {\n        $self->{unpack_code} = 'V';  # Little-endian.\n      } elsif (substr($str, 4, 2) eq chr(0)x2) {\n        $self->{unpack_code} = 'N';  # Big-endian\n      } else {\n        ::error(\"$fname: header size >= 2**16\\n\");\n      }\n      @$slots = unpack($self->{unpack_code} . \"*\", $str);\n    } else {\n      # If we're a 64-bit profile, check if we're a 64-bit-capable\n      # perl.  Otherwise, each slot will be represented as a float\n      # instead of an int64, losing precision and making all the\n      # 64-bit addresses wrong.  We won't complain yet, but will\n      # later if we ever see a value that doesn't fit in 32 bits.\n      my $has_q = 0;\n      eval { $has_q = pack(\"Q\", \"1\") ? 1 : 1; };\n      if (!$has_q) {\n        $self->{perl_is_64bit} = 0;\n      }\n      read($self->{file}, $str, 8);\n      if (substr($str, 4, 4) eq chr(0)x4) {\n        # We'd love to use 'Q', but it's a) not universal, b) not endian-proof.\n        $self->{unpack_code} = 'V';  # Little-endian.\n      } elsif (substr($str, 0, 4) eq chr(0)x4) {\n        $self->{unpack_code} = 'N';  # Big-endian\n      } else {\n        ::error(\"$fname: header size >= 2**32\\n\");\n      }\n      my @pair = unpack($self->{unpack_code} . \"*\", $str);\n      # Since we know one of the pair is 0, it's fine to just add them.\n      @$slots = (0, $pair[0] + $pair[1]);\n    }\n    return $self;\n  }\n\n  # Load more data when we access slots->get(X) which is not yet in memory.\n  sub overflow {\n    my ($self) = @_;\n    my $slots = $self->{slots};\n    $self->{base} += $#$slots + 1;   # skip over data we're replacing\n    my $str;\n    read($self->{file}, $str, $self->{stride});\n    if ($address_length == 8) {      # the 32-bit case\n      # This is the easy case: unpack provides 32-bit unpacking primitives.\n      @$slots = unpack($self->{unpack_code} . \"*\", $str);\n    } else {\n      # We need to unpack 32 bits at a time and combine.\n      my @b32_values = unpack($self->{unpack_code} . \"*\", $str);\n      my @b64_values = ();\n      for (my $i = 0; $i < $#b32_values; $i += 2) {\n        # TODO(csilvers): if this is a 32-bit perl, the math below\n        #    could end up in a too-large int, which perl will promote\n        #    to a double, losing necessary precision.  Deal with that.\n        #    Right now, we just die.\n        my ($lo, $hi) = ($b32_values[$i], $b32_values[$i+1]);\n        if ($self->{unpack_code} eq 'N') {    # big-endian\n          ($lo, $hi) = ($hi, $lo);\n        }\n        my $value = $lo + $hi * (2**32);\n        if (!$self->{perl_is_64bit} &&   # check value is exactly represented\n            (($value % (2**32)) != $lo || int($value / (2**32)) != $hi)) {\n          ::error(\"Need a 64-bit perl to process this 64-bit profile.\\n\");\n        }\n        push(@b64_values, $value);\n      }\n      @$slots = @b64_values;\n    }\n  }\n\n  # Access the i-th long in the file (logically), or -1 at EOF.\n  sub get {\n    my ($self, $idx) = @_;\n    my $slots = $self->{slots};\n    while ($#$slots >= 0) {\n      if ($idx < $self->{base}) {\n        # The only time we expect a reference to $slots[$i - something]\n        # after referencing $slots[$i] is reading the very first header.\n        # Since $stride > |header|, that shouldn't cause any lookback\n        # errors.  And everything after the header is sequential.\n        print STDERR \"Unexpected look-back reading CPU profile\";\n        return -1;   # shrug, don't know what better to return\n      } elsif ($idx > $self->{base} + $#$slots) {\n        $self->overflow();\n      } else {\n        return $slots->[$idx - $self->{base}];\n      }\n    }\n    # If we get here, $slots is [], which means we've reached EOF\n    return -1;  # unique since slots is supposed to hold unsigned numbers\n  }\n}\n\n# Reads the top, 'header' section of a profile, and returns the last\n# line of the header, commonly called a 'header line'.  The header\n# section of a profile consists of zero or more 'command' lines that\n# are instructions to jeprof, which jeprof executes when reading the\n# header.  All 'command' lines start with a %.  After the command\n# lines is the 'header line', which is a profile-specific line that\n# indicates what type of profile it is, and perhaps other global\n# information about the profile.  For instance, here's a header line\n# for a heap profile:\n#   heap profile:     53:    38236 [  5525:  1284029] @ heapprofile\n# For historical reasons, the CPU profile does not contain a text-\n# readable header line.  If the profile looks like a CPU profile,\n# this function returns \"\".  If no header line could be found, this\n# function returns undef.\n#\n# The following commands are recognized:\n#   %warn -- emit the rest of this line to stderr, prefixed by 'WARNING:'\n#\n# The input file should be in binmode.\nsub ReadProfileHeader {\n  local *PROFILE = shift;\n  my $firstchar = \"\";\n  my $line = \"\";\n  read(PROFILE, $firstchar, 1);\n  seek(PROFILE, -1, 1);                    # unread the firstchar\n  if ($firstchar !~ /[[:print:]]/) {       # is not a text character\n    return \"\";\n  }\n  while (defined($line = <PROFILE>)) {\n    $line =~ s/\\r//g;   # turn windows-looking lines into unix-looking lines\n    if ($line =~ /^%warn\\s+(.*)/) {        # 'warn' command\n      # Note this matches both '%warn blah\\n' and '%warn\\n'.\n      print STDERR \"WARNING: $1\\n\";        # print the rest of the line\n    } elsif ($line =~ /^%/) {\n      print STDERR \"Ignoring unknown command from profile header: $line\";\n    } else {\n      # End of commands, must be the header line.\n      return $line;\n    }\n  }\n  return undef;     # got to EOF without seeing a header line\n}\n\nsub IsSymbolizedProfileFile {\n  my $file_name = shift;\n  if (!(-e $file_name) || !(-r $file_name)) {\n    return 0;\n  }\n  # Check if the file contains a symbol-section marker.\n  open(TFILE, \"<$file_name\");\n  binmode TFILE;\n  my $firstline = ReadProfileHeader(*TFILE);\n  close(TFILE);\n  if (!$firstline) {\n    return 0;\n  }\n  $SYMBOL_PAGE =~ m,[^/]+$,;    # matches everything after the last slash\n  my $symbol_marker = $&;\n  return $firstline =~ /^--- *$symbol_marker/;\n}\n\n# Parse profile generated by common/profiler.cc and return a reference\n# to a map:\n#      $result->{version}     Version number of profile file\n#      $result->{period}      Sampling period (in microseconds)\n#      $result->{profile}     Profile object\n#      $result->{threads}     Map of thread IDs to profile objects\n#      $result->{map}         Memory map info from profile\n#      $result->{pcs}         Hash of all PC values seen, key is hex address\nsub ReadProfile {\n  my $prog = shift;\n  my $fname = shift;\n  my $result;            # return value\n\n  $CONTENTION_PAGE =~ m,[^/]+$,;    # matches everything after the last slash\n  my $contention_marker = $&;\n  $GROWTH_PAGE  =~ m,[^/]+$,;    # matches everything after the last slash\n  my $growth_marker = $&;\n  $SYMBOL_PAGE =~ m,[^/]+$,;    # matches everything after the last slash\n  my $symbol_marker = $&;\n  $PROFILE_PAGE =~ m,[^/]+$,;    # matches everything after the last slash\n  my $profile_marker = $&;\n  $HEAP_PAGE =~ m,[^/]+$,;    # matches everything after the last slash\n  my $heap_marker = $&;\n\n  # Look at first line to see if it is a heap or a CPU profile.\n  # CPU profile may start with no header at all, and just binary data\n  # (starting with \\0\\0\\0\\0) -- in that case, don't try to read the\n  # whole firstline, since it may be gigabytes(!) of data.\n  open(PROFILE, \"<$fname\") || error(\"$fname: $!\\n\");\n  binmode PROFILE;      # New perls do UTF-8 processing\n  my $header = ReadProfileHeader(*PROFILE);\n  if (!defined($header)) {   # means \"at EOF\"\n    error(\"Profile is empty.\\n\");\n  }\n\n  my $symbols;\n  if ($header =~ m/^--- *$symbol_marker/o) {\n    # Verify that the user asked for a symbolized profile\n    if (!$main::use_symbolized_profile) {\n      # we have both a binary and symbolized profiles, abort\n      error(\"FATAL ERROR: Symbolized profile\\n   $fname\\ncannot be used with \" .\n            \"a binary arg. Try again without passing\\n   $prog\\n\");\n    }\n    # Read the symbol section of the symbolized profile file.\n    $symbols = ReadSymbols(*PROFILE{IO});\n    # Read the next line to get the header for the remaining profile.\n    $header = ReadProfileHeader(*PROFILE) || \"\";\n  }\n\n  if ($header =~ m/^--- *($heap_marker|$growth_marker)/o) {\n    # Skip \"--- ...\" line for profile types that have their own headers.\n    $header = ReadProfileHeader(*PROFILE) || \"\";\n  }\n\n  $main::profile_type = '';\n\n  if ($header =~ m/^heap profile:.*$growth_marker/o) {\n    $main::profile_type = 'growth';\n    $result =  ReadHeapProfile($prog, *PROFILE, $header);\n  } elsif ($header =~ m/^heap profile:/) {\n    $main::profile_type = 'heap';\n    $result =  ReadHeapProfile($prog, *PROFILE, $header);\n  } elsif ($header =~ m/^heap/) {\n    $main::profile_type = 'heap';\n    $result = ReadThreadedHeapProfile($prog, $fname, $header);\n  } elsif ($header =~ m/^--- *$contention_marker/o) {\n    $main::profile_type = 'contention';\n    $result = ReadSynchProfile($prog, *PROFILE);\n  } elsif ($header =~ m/^--- *Stacks:/) {\n    print STDERR\n      \"Old format contention profile: mistakenly reports \" .\n      \"condition variable signals as lock contentions.\\n\";\n    $main::profile_type = 'contention';\n    $result = ReadSynchProfile($prog, *PROFILE);\n  } elsif ($header =~ m/^--- *$profile_marker/) {\n    # the binary cpu profile data starts immediately after this line\n    $main::profile_type = 'cpu';\n    $result = ReadCPUProfile($prog, $fname, *PROFILE);\n  } else {\n    if (defined($symbols)) {\n      # a symbolized profile contains a format we don't recognize, bail out\n      error(\"$fname: Cannot recognize profile section after symbols.\\n\");\n    }\n    # no ascii header present -- must be a CPU profile\n    $main::profile_type = 'cpu';\n    $result = ReadCPUProfile($prog, $fname, *PROFILE);\n  }\n\n  close(PROFILE);\n\n  # if we got symbols along with the profile, return those as well\n  if (defined($symbols)) {\n    $result->{symbols} = $symbols;\n  }\n\n  return $result;\n}\n\n# Subtract one from caller pc so we map back to call instr.\n# However, don't do this if we're reading a symbolized profile\n# file, in which case the subtract-one was done when the file\n# was written.\n#\n# We apply the same logic to all readers, though ReadCPUProfile uses an\n# independent implementation.\nsub FixCallerAddresses {\n  my $stack = shift;\n  # --raw/http: Always subtract one from pc's, because PrintSymbolizedProfile()\n  # dumps unadjusted profiles.\n  {\n    $stack =~ /(\\s)/;\n    my $delimiter = $1;\n    my @addrs = split(' ', $stack);\n    my @fixedaddrs;\n    $#fixedaddrs = $#addrs;\n    if ($#addrs >= 0) {\n      $fixedaddrs[0] = $addrs[0];\n    }\n    for (my $i = 1; $i <= $#addrs; $i++) {\n      $fixedaddrs[$i] = AddressSub($addrs[$i], \"0x1\");\n    }\n    return join $delimiter, @fixedaddrs;\n  }\n}\n\n# CPU profile reader\nsub ReadCPUProfile {\n  my $prog = shift;\n  my $fname = shift;       # just used for logging\n  local *PROFILE = shift;\n  my $version;\n  my $period;\n  my $i;\n  my $profile = {};\n  my $pcs = {};\n\n  # Parse string into array of slots.\n  my $slots = CpuProfileStream->new(*PROFILE, $fname);\n\n  # Read header.  The current header version is a 5-element structure\n  # containing:\n  #   0: header count (always 0)\n  #   1: header \"words\" (after this one: 3)\n  #   2: format version (0)\n  #   3: sampling period (usec)\n  #   4: unused padding (always 0)\n  if ($slots->get(0) != 0 ) {\n    error(\"$fname: not a profile file, or old format profile file\\n\");\n  }\n  $i = 2 + $slots->get(1);\n  $version = $slots->get(2);\n  $period = $slots->get(3);\n  # Do some sanity checking on these header values.\n  if ($version > (2**32) || $period > (2**32) || $i > (2**32) || $i < 5) {\n    error(\"$fname: not a profile file, or corrupted profile file\\n\");\n  }\n\n  # Parse profile\n  while ($slots->get($i) != -1) {\n    my $n = $slots->get($i++);\n    my $d = $slots->get($i++);\n    if ($d > (2**16)) {  # TODO(csilvers): what's a reasonable max-stack-depth?\n      my $addr = sprintf(\"0%o\", $i * ($address_length == 8 ? 4 : 8));\n      print STDERR \"At index $i (address $addr):\\n\";\n      error(\"$fname: stack trace depth >= 2**32\\n\");\n    }\n    if ($slots->get($i) == 0) {\n      # End of profile data marker\n      $i += $d;\n      last;\n    }\n\n    # Make key out of the stack entries\n    my @k = ();\n    for (my $j = 0; $j < $d; $j++) {\n      my $pc = $slots->get($i+$j);\n      # Subtract one from caller pc so we map back to call instr.\n      $pc--;\n      $pc = sprintf(\"%0*x\", $address_length, $pc);\n      $pcs->{$pc} = 1;\n      push @k, $pc;\n    }\n\n    AddEntry($profile, (join \"\\n\", @k), $n);\n    $i += $d;\n  }\n\n  # Parse map\n  my $map = '';\n  seek(PROFILE, $i * 4, 0);\n  read(PROFILE, $map, (stat PROFILE)[7]);\n\n  my $r = {};\n  $r->{version} = $version;\n  $r->{period} = $period;\n  $r->{profile} = $profile;\n  $r->{libs} = ParseLibraries($prog, $map, $pcs);\n  $r->{pcs} = $pcs;\n\n  return $r;\n}\n\nsub HeapProfileIndex {\n  my $index = 1;\n  if ($main::opt_inuse_space) {\n    $index = 1;\n  } elsif ($main::opt_inuse_objects) {\n    $index = 0;\n  } elsif ($main::opt_alloc_space) {\n    $index = 3;\n  } elsif ($main::opt_alloc_objects) {\n    $index = 2;\n  }\n  return $index;\n}\n\nsub ReadMappedLibraries {\n  my $fh = shift;\n  my $map = \"\";\n  # Read the /proc/self/maps data\n  while (<$fh>) {\n    s/\\r//g;         # turn windows-looking lines into unix-looking lines\n    $map .= $_;\n  }\n  return $map;\n}\n\nsub ReadMemoryMap {\n  my $fh = shift;\n  my $map = \"\";\n  # Read /proc/self/maps data as formatted by DumpAddressMap()\n  my $buildvar = \"\";\n  while (<PROFILE>) {\n    s/\\r//g;         # turn windows-looking lines into unix-looking lines\n    # Parse \"build=<dir>\" specification if supplied\n    if (m/^\\s*build=(.*)\\n/) {\n      $buildvar = $1;\n    }\n\n    # Expand \"$build\" variable if available\n    $_ =~ s/\\$build\\b/$buildvar/g;\n\n    $map .= $_;\n  }\n  return $map;\n}\n\nsub AdjustSamples {\n  my ($sample_adjustment, $sampling_algorithm, $n1, $s1, $n2, $s2) = @_;\n  if ($sample_adjustment) {\n    if ($sampling_algorithm == 2) {\n      # Remote-heap version 2\n      # The sampling frequency is the rate of a Poisson process.\n      # This means that the probability of sampling an allocation of\n      # size X with sampling rate Y is 1 - exp(-X/Y)\n      if ($n1 != 0) {\n        my $ratio = (($s1*1.0)/$n1)/($sample_adjustment);\n        my $scale_factor = 1/(1 - exp(-$ratio));\n        $n1 *= $scale_factor;\n        $s1 *= $scale_factor;\n      }\n      if ($n2 != 0) {\n        my $ratio = (($s2*1.0)/$n2)/($sample_adjustment);\n        my $scale_factor = 1/(1 - exp(-$ratio));\n        $n2 *= $scale_factor;\n        $s2 *= $scale_factor;\n      }\n    } else {\n      # Remote-heap version 1\n      my $ratio;\n      $ratio = (($s1*1.0)/$n1)/($sample_adjustment);\n      if ($ratio < 1) {\n        $n1 /= $ratio;\n        $s1 /= $ratio;\n      }\n      $ratio = (($s2*1.0)/$n2)/($sample_adjustment);\n      if ($ratio < 1) {\n        $n2 /= $ratio;\n        $s2 /= $ratio;\n      }\n    }\n  }\n  return ($n1, $s1, $n2, $s2);\n}\n\nsub ReadHeapProfile {\n  my $prog = shift;\n  local *PROFILE = shift;\n  my $header = shift;\n\n  my $index = HeapProfileIndex();\n\n  # Find the type of this profile.  The header line looks like:\n  #    heap profile:   1246:  8800744 [  1246:  8800744] @ <heap-url>/266053\n  # There are two pairs <count: size>, the first inuse objects/space, and the\n  # second allocated objects/space.  This is followed optionally by a profile\n  # type, and if that is present, optionally by a sampling frequency.\n  # For remote heap profiles (v1):\n  # The interpretation of the sampling frequency is that the profiler, for\n  # each sample, calculates a uniformly distributed random integer less than\n  # the given value, and records the next sample after that many bytes have\n  # been allocated.  Therefore, the expected sample interval is half of the\n  # given frequency.  By default, if not specified, the expected sample\n  # interval is 128KB.  Only remote-heap-page profiles are adjusted for\n  # sample size.\n  # For remote heap profiles (v2):\n  # The sampling frequency is the rate of a Poisson process. This means that\n  # the probability of sampling an allocation of size X with sampling rate Y\n  # is 1 - exp(-X/Y)\n  # For version 2, a typical header line might look like this:\n  # heap profile:   1922: 127792360 [  1922: 127792360] @ <heap-url>_v2/524288\n  # the trailing number (524288) is the sampling rate. (Version 1 showed\n  # double the 'rate' here)\n  my $sampling_algorithm = 0;\n  my $sample_adjustment = 0;\n  chomp($header);\n  my $type = \"unknown\";\n  if ($header =~ m\"^heap profile:\\s*(\\d+):\\s+(\\d+)\\s+\\[\\s*(\\d+):\\s+(\\d+)\\](\\s*@\\s*([^/]*)(/(\\d+))?)?\") {\n    if (defined($6) && ($6 ne '')) {\n      $type = $6;\n      my $sample_period = $8;\n      # $type is \"heapprofile\" for profiles generated by the\n      # heap-profiler, and either \"heap\" or \"heap_v2\" for profiles\n      # generated by sampling directly within tcmalloc.  It can also\n      # be \"growth\" for heap-growth profiles.  The first is typically\n      # found for profiles generated locally, and the others for\n      # remote profiles.\n      if (($type eq \"heapprofile\") || ($type !~ /heap/) ) {\n        # No need to adjust for the sampling rate with heap-profiler-derived data\n        $sampling_algorithm = 0;\n      } elsif ($type =~ /_v2/) {\n        $sampling_algorithm = 2;     # version 2 sampling\n        if (defined($sample_period) && ($sample_period ne '')) {\n          $sample_adjustment = int($sample_period);\n        }\n      } else {\n        $sampling_algorithm = 1;     # version 1 sampling\n        if (defined($sample_period) && ($sample_period ne '')) {\n          $sample_adjustment = int($sample_period)/2;\n        }\n      }\n    } else {\n      # We detect whether or not this is a remote-heap profile by checking\n      # that the total-allocated stats ($n2,$s2) are exactly the\n      # same as the in-use stats ($n1,$s1).  It is remotely conceivable\n      # that a non-remote-heap profile may pass this check, but it is hard\n      # to imagine how that could happen.\n      # In this case it's so old it's guaranteed to be remote-heap version 1.\n      my ($n1, $s1, $n2, $s2) = ($1, $2, $3, $4);\n      if (($n1 == $n2) && ($s1 == $s2)) {\n        # This is likely to be a remote-heap based sample profile\n        $sampling_algorithm = 1;\n      }\n    }\n  }\n\n  if ($sampling_algorithm > 0) {\n    # For remote-heap generated profiles, adjust the counts and sizes to\n    # account for the sample rate (we sample once every 128KB by default).\n    if ($sample_adjustment == 0) {\n      # Turn on profile adjustment.\n      $sample_adjustment = 128*1024;\n      print STDERR \"Adjusting heap profiles for 1-in-128KB sampling rate\\n\";\n    } else {\n      printf STDERR (\"Adjusting heap profiles for 1-in-%d sampling rate\\n\",\n                     $sample_adjustment);\n    }\n    if ($sampling_algorithm > 1) {\n      # We don't bother printing anything for the original version (version 1)\n      printf STDERR \"Heap version $sampling_algorithm\\n\";\n    }\n  }\n\n  my $profile = {};\n  my $pcs = {};\n  my $map = \"\";\n\n  while (<PROFILE>) {\n    s/\\r//g;         # turn windows-looking lines into unix-looking lines\n    if (/^MAPPED_LIBRARIES:/) {\n      $map .= ReadMappedLibraries(*PROFILE);\n      last;\n    }\n\n    if (/^--- Memory map:/) {\n      $map .= ReadMemoryMap(*PROFILE);\n      last;\n    }\n\n    # Read entry of the form:\n    #  <count1>: <bytes1> [<count2>: <bytes2>] @ a1 a2 a3 ... an\n    s/^\\s*//;\n    s/\\s*$//;\n    if (m/^\\s*(\\d+):\\s+(\\d+)\\s+\\[\\s*(\\d+):\\s+(\\d+)\\]\\s+@\\s+(.*)$/) {\n      my $stack = $5;\n      my ($n1, $s1, $n2, $s2) = ($1, $2, $3, $4);\n      my @counts = AdjustSamples($sample_adjustment, $sampling_algorithm,\n                                 $n1, $s1, $n2, $s2);\n      AddEntries($profile, $pcs, FixCallerAddresses($stack), $counts[$index]);\n    }\n  }\n\n  my $r = {};\n  $r->{version} = \"heap\";\n  $r->{period} = 1;\n  $r->{profile} = $profile;\n  $r->{libs} = ParseLibraries($prog, $map, $pcs);\n  $r->{pcs} = $pcs;\n  return $r;\n}\n\nsub ReadThreadedHeapProfile {\n  my ($prog, $fname, $header) = @_;\n\n  my $index = HeapProfileIndex();\n  my $sampling_algorithm = 0;\n  my $sample_adjustment = 0;\n  chomp($header);\n  my $type = \"unknown\";\n  # Assuming a very specific type of header for now.\n  if ($header =~ m\"^heap_v2/(\\d+)\") {\n    $type = \"_v2\";\n    $sampling_algorithm = 2;\n    $sample_adjustment = int($1);\n  }\n  if ($type ne \"_v2\" || !defined($sample_adjustment)) {\n    die \"Threaded heap profiles require v2 sampling with a sample rate\\n\";\n  }\n\n  my $profile = {};\n  my $thread_profiles = {};\n  my $pcs = {};\n  my $map = \"\";\n  my $stack = \"\";\n\n  while (<PROFILE>) {\n    s/\\r//g;\n    if (/^MAPPED_LIBRARIES:/) {\n      $map .= ReadMappedLibraries(*PROFILE);\n      last;\n    }\n\n    if (/^--- Memory map:/) {\n      $map .= ReadMemoryMap(*PROFILE);\n      last;\n    }\n\n    # Read entry of the form:\n    # @ a1 a2 ... an\n    #   t*: <count1>: <bytes1> [<count2>: <bytes2>]\n    #   t1: <count1>: <bytes1> [<count2>: <bytes2>]\n    #     ...\n    #   tn: <count1>: <bytes1> [<count2>: <bytes2>]\n    s/^\\s*//;\n    s/\\s*$//;\n    if (m/^@\\s+(.*)$/) {\n      $stack = $1;\n    } elsif (m/^\\s*(t(\\*|\\d+)):\\s+(\\d+):\\s+(\\d+)\\s+\\[\\s*(\\d+):\\s+(\\d+)\\]$/) {\n      if ($stack eq \"\") {\n        # Still in the header, so this is just a per-thread summary.\n        next;\n      }\n      my $thread = $2;\n      my ($n1, $s1, $n2, $s2) = ($3, $4, $5, $6);\n      my @counts = AdjustSamples($sample_adjustment, $sampling_algorithm,\n                                 $n1, $s1, $n2, $s2);\n      if ($thread eq \"*\") {\n        AddEntries($profile, $pcs, FixCallerAddresses($stack), $counts[$index]);\n      } else {\n        if (!exists($thread_profiles->{$thread})) {\n          $thread_profiles->{$thread} = {};\n        }\n        AddEntries($thread_profiles->{$thread}, $pcs,\n                   FixCallerAddresses($stack), $counts[$index]);\n      }\n    }\n  }\n\n  my $r = {};\n  $r->{version} = \"heap\";\n  $r->{period} = 1;\n  $r->{profile} = $profile;\n  $r->{threads} = $thread_profiles;\n  $r->{libs} = ParseLibraries($prog, $map, $pcs);\n  $r->{pcs} = $pcs;\n  return $r;\n}\n\nsub ReadSynchProfile {\n  my $prog = shift;\n  local *PROFILE = shift;\n  my $header = shift;\n\n  my $map = '';\n  my $profile = {};\n  my $pcs = {};\n  my $sampling_period = 1;\n  my $cyclespernanosec = 2.8;   # Default assumption for old binaries\n  my $seen_clockrate = 0;\n  my $line;\n\n  my $index = 0;\n  if ($main::opt_total_delay) {\n    $index = 0;\n  } elsif ($main::opt_contentions) {\n    $index = 1;\n  } elsif ($main::opt_mean_delay) {\n    $index = 2;\n  }\n\n  while ( $line = <PROFILE> ) {\n    $line =~ s/\\r//g;      # turn windows-looking lines into unix-looking lines\n    if ( $line =~ /^\\s*(\\d+)\\s+(\\d+) \\@\\s*(.*?)\\s*$/ ) {\n      my ($cycles, $count, $stack) = ($1, $2, $3);\n\n      # Convert cycles to nanoseconds\n      $cycles /= $cyclespernanosec;\n\n      # Adjust for sampling done by application\n      $cycles *= $sampling_period;\n      $count *= $sampling_period;\n\n      my @values = ($cycles, $count, $cycles / $count);\n      AddEntries($profile, $pcs, FixCallerAddresses($stack), $values[$index]);\n\n    } elsif ( $line =~ /^(slow release).*thread \\d+  \\@\\s*(.*?)\\s*$/ ||\n              $line =~ /^\\s*(\\d+) \\@\\s*(.*?)\\s*$/ ) {\n      my ($cycles, $stack) = ($1, $2);\n      if ($cycles !~ /^\\d+$/) {\n        next;\n      }\n\n      # Convert cycles to nanoseconds\n      $cycles /= $cyclespernanosec;\n\n      # Adjust for sampling done by application\n      $cycles *= $sampling_period;\n\n      AddEntries($profile, $pcs, FixCallerAddresses($stack), $cycles);\n\n    } elsif ( $line =~ m/^([a-z][^=]*)=(.*)$/ ) {\n      my ($variable, $value) = ($1,$2);\n      for ($variable, $value) {\n        s/^\\s+//;\n        s/\\s+$//;\n      }\n      if ($variable eq \"cycles/second\") {\n        $cyclespernanosec = $value / 1e9;\n        $seen_clockrate = 1;\n      } elsif ($variable eq \"sampling period\") {\n        $sampling_period = $value;\n      } elsif ($variable eq \"ms since reset\") {\n        # Currently nothing is done with this value in jeprof\n        # So we just silently ignore it for now\n      } elsif ($variable eq \"discarded samples\") {\n        # Currently nothing is done with this value in jeprof\n        # So we just silently ignore it for now\n      } else {\n        printf STDERR (\"Ignoring unnknown variable in /contention output: \" .\n                       \"'%s' = '%s'\\n\",$variable,$value);\n      }\n    } else {\n      # Memory map entry\n      $map .= $line;\n    }\n  }\n\n  if (!$seen_clockrate) {\n    printf STDERR (\"No cycles/second entry in profile; Guessing %.1f GHz\\n\",\n                   $cyclespernanosec);\n  }\n\n  my $r = {};\n  $r->{version} = 0;\n  $r->{period} = $sampling_period;\n  $r->{profile} = $profile;\n  $r->{libs} = ParseLibraries($prog, $map, $pcs);\n  $r->{pcs} = $pcs;\n  return $r;\n}\n\n# Given a hex value in the form \"0x1abcd\" or \"1abcd\", return either\n# \"0001abcd\" or \"000000000001abcd\", depending on the current (global)\n# address length.\nsub HexExtend {\n  my $addr = shift;\n\n  $addr =~ s/^(0x)?0*//;\n  my $zeros_needed = $address_length - length($addr);\n  if ($zeros_needed < 0) {\n    printf STDERR \"Warning: address $addr is longer than address length $address_length\\n\";\n    return $addr;\n  }\n  return (\"0\" x $zeros_needed) . $addr;\n}\n\n##### Symbol extraction #####\n\n# Aggressively search the lib_prefix values for the given library\n# If all else fails, just return the name of the library unmodified.\n# If the lib_prefix is \"/my/path,/other/path\" and $file is \"/lib/dir/mylib.so\"\n# it will search the following locations in this order, until it finds a file:\n#   /my/path/lib/dir/mylib.so\n#   /other/path/lib/dir/mylib.so\n#   /my/path/dir/mylib.so\n#   /other/path/dir/mylib.so\n#   /my/path/mylib.so\n#   /other/path/mylib.so\n#   /lib/dir/mylib.so              (returned as last resort)\nsub FindLibrary {\n  my $file = shift;\n  my $suffix = $file;\n\n  # Search for the library as described above\n  do {\n    foreach my $prefix (@prefix_list) {\n      my $fullpath = $prefix . $suffix;\n      if (-e $fullpath) {\n        return $fullpath;\n      }\n    }\n  } while ($suffix =~ s|^/[^/]+/|/|);\n  return $file;\n}\n\n# Return path to library with debugging symbols.\n# For libc libraries, the copy in /usr/lib/debug contains debugging symbols\nsub DebuggingLibrary {\n  my $file = shift;\n  if ($file =~ m|^/|) {\n      if (-f \"/usr/lib/debug$file\") {\n        return \"/usr/lib/debug$file\";\n      } elsif (-f \"/usr/lib/debug$file.debug\") {\n        return \"/usr/lib/debug$file.debug\";\n      }\n  }\n  return undef;\n}\n\n# Parse text section header of a library using objdump\nsub ParseTextSectionHeaderFromObjdump {\n  my $lib = shift;\n\n  my $size = undef;\n  my $vma;\n  my $file_offset;\n  # Get objdump output from the library file to figure out how to\n  # map between mapped addresses and addresses in the library.\n  my $cmd = ShellEscape($obj_tool_map{\"objdump\"}, \"-h\", $lib);\n  open(OBJDUMP, \"$cmd |\") || error(\"$cmd: $!\\n\");\n  while (<OBJDUMP>) {\n    s/\\r//g;         # turn windows-looking lines into unix-looking lines\n    # Idx Name          Size      VMA       LMA       File off  Algn\n    #  10 .text         00104b2c  420156f0  420156f0  000156f0  2**4\n    # For 64-bit objects, VMA and LMA will be 16 hex digits, size and file\n    # offset may still be 8.  But AddressSub below will still handle that.\n    my @x = split;\n    if (($#x >= 6) && ($x[1] eq '.text')) {\n      $size = $x[2];\n      $vma = $x[3];\n      $file_offset = $x[5];\n      last;\n    }\n  }\n  close(OBJDUMP);\n\n  if (!defined($size)) {\n    return undef;\n  }\n\n  my $r = {};\n  $r->{size} = $size;\n  $r->{vma} = $vma;\n  $r->{file_offset} = $file_offset;\n\n  return $r;\n}\n\n# Parse text section header of a library using otool (on OS X)\nsub ParseTextSectionHeaderFromOtool {\n  my $lib = shift;\n\n  my $size = undef;\n  my $vma = undef;\n  my $file_offset = undef;\n  # Get otool output from the library file to figure out how to\n  # map between mapped addresses and addresses in the library.\n  my $command = ShellEscape($obj_tool_map{\"otool\"}, \"-l\", $lib);\n  open(OTOOL, \"$command |\") || error(\"$command: $!\\n\");\n  my $cmd = \"\";\n  my $sectname = \"\";\n  my $segname = \"\";\n  foreach my $line (<OTOOL>) {\n    $line =~ s/\\r//g;      # turn windows-looking lines into unix-looking lines\n    # Load command <#>\n    #       cmd LC_SEGMENT\n    # [...]\n    # Section\n    #   sectname __text\n    #    segname __TEXT\n    #       addr 0x000009f8\n    #       size 0x00018b9e\n    #     offset 2552\n    #      align 2^2 (4)\n    # We will need to strip off the leading 0x from the hex addresses,\n    # and convert the offset into hex.\n    if ($line =~ /Load command/) {\n      $cmd = \"\";\n      $sectname = \"\";\n      $segname = \"\";\n    } elsif ($line =~ /Section/) {\n      $sectname = \"\";\n      $segname = \"\";\n    } elsif ($line =~ /cmd (\\w+)/) {\n      $cmd = $1;\n    } elsif ($line =~ /sectname (\\w+)/) {\n      $sectname = $1;\n    } elsif ($line =~ /segname (\\w+)/) {\n      $segname = $1;\n    } elsif (!(($cmd eq \"LC_SEGMENT\" || $cmd eq \"LC_SEGMENT_64\") &&\n               $sectname eq \"__text\" &&\n               $segname eq \"__TEXT\")) {\n      next;\n    } elsif ($line =~ /\\baddr 0x([0-9a-fA-F]+)/) {\n      $vma = $1;\n    } elsif ($line =~ /\\bsize 0x([0-9a-fA-F]+)/) {\n      $size = $1;\n    } elsif ($line =~ /\\boffset ([0-9]+)/) {\n      $file_offset = sprintf(\"%016x\", $1);\n    }\n    if (defined($vma) && defined($size) && defined($file_offset)) {\n      last;\n    }\n  }\n  close(OTOOL);\n\n  if (!defined($vma) || !defined($size) || !defined($file_offset)) {\n     return undef;\n  }\n\n  my $r = {};\n  $r->{size} = $size;\n  $r->{vma} = $vma;\n  $r->{file_offset} = $file_offset;\n\n  return $r;\n}\n\nsub ParseTextSectionHeader {\n  # obj_tool_map(\"otool\") is only defined if we're in a Mach-O environment\n  if (defined($obj_tool_map{\"otool\"})) {\n    my $r = ParseTextSectionHeaderFromOtool(@_);\n    if (defined($r)){\n      return $r;\n    }\n  }\n  # If otool doesn't work, or we don't have it, fall back to objdump\n  return ParseTextSectionHeaderFromObjdump(@_);\n}\n\n# Split /proc/pid/maps dump into a list of libraries\nsub ParseLibraries {\n  return if $main::use_symbol_page;  # We don't need libraries info.\n  my $prog = shift;\n  my $map = shift;\n  my $pcs = shift;\n\n  my $result = [];\n  my $h = \"[a-f0-9]+\";\n  my $zero_offset = HexExtend(\"0\");\n\n  my $buildvar = \"\";\n  foreach my $l (split(\"\\n\", $map)) {\n    if ($l =~ m/^\\s*build=(.*)$/) {\n      $buildvar = $1;\n    }\n\n    my $start;\n    my $finish;\n    my $offset;\n    my $lib;\n    if ($l =~ /^($h)-($h)\\s+..x.\\s+($h)\\s+\\S+:\\S+\\s+\\d+\\s+(\\S+\\.(so|dll|dylib|bundle)((\\.\\d+)+\\w*(\\.\\d+){0,3})?)$/i) {\n      # Full line from /proc/self/maps.  Example:\n      #   40000000-40015000 r-xp 00000000 03:01 12845071   /lib/ld-2.3.2.so\n      $start = HexExtend($1);\n      $finish = HexExtend($2);\n      $offset = HexExtend($3);\n      $lib = $4;\n      $lib =~ s|\\\\|/|g;     # turn windows-style paths into unix-style paths\n    } elsif ($l =~ /^\\s*($h)-($h):\\s*(\\S+\\.so(\\.\\d+)*)/) {\n      # Cooked line from DumpAddressMap.  Example:\n      #   40000000-40015000: /lib/ld-2.3.2.so\n      $start = HexExtend($1);\n      $finish = HexExtend($2);\n      $offset = $zero_offset;\n      $lib = $3;\n    }\n    # FreeBSD 10.0 virtual memory map /proc/curproc/map as defined in\n    # function procfs_doprocmap (sys/fs/procfs/procfs_map.c)\n    #\n    # Example:\n    # 0x800600000 0x80061a000 26 0 0xfffff800035a0000 r-x 75 33 0x1004 COW NC vnode /libexec/ld-elf.s\n    # o.1 NCH -1\n    elsif ($l =~ /^(0x$h)\\s(0x$h)\\s\\d+\\s\\d+\\s0x$h\\sr-x\\s\\d+\\s\\d+\\s0x\\d+\\s(COW|NCO)\\s(NC|NNC)\\svnode\\s(\\S+\\.so(\\.\\d+)*)/) {\n      $start = HexExtend($1);\n      $finish = HexExtend($2);\n      $offset = $zero_offset;\n      $lib = FindLibrary($5);\n\n    } else {\n      next;\n    }\n\n    # Expand \"$build\" variable if available\n    $lib =~ s/\\$build\\b/$buildvar/g;\n\n    $lib = FindLibrary($lib);\n\n    # Check for pre-relocated libraries, which use pre-relocated symbol tables\n    # and thus require adjusting the offset that we'll use to translate\n    # VM addresses into symbol table addresses.\n    # Only do this if we're not going to fetch the symbol table from a\n    # debugging copy of the library.\n    if (!DebuggingLibrary($lib)) {\n      my $text = ParseTextSectionHeader($lib);\n      if (defined($text)) {\n         my $vma_offset = AddressSub($text->{vma}, $text->{file_offset});\n         $offset = AddressAdd($offset, $vma_offset);\n      }\n    }\n\n    if($main::opt_debug) { printf STDERR \"$start:$finish ($offset) $lib\\n\"; }\n    push(@{$result}, [$lib, $start, $finish, $offset]);\n  }\n\n  # Append special entry for additional library (not relocated)\n  if ($main::opt_lib ne \"\") {\n    my $text = ParseTextSectionHeader($main::opt_lib);\n    if (defined($text)) {\n       my $start = $text->{vma};\n       my $finish = AddressAdd($start, $text->{size});\n\n       push(@{$result}, [$main::opt_lib, $start, $finish, $start]);\n    }\n  }\n\n  # Append special entry for the main program.  This covers\n  # 0..max_pc_value_seen, so that we assume pc values not found in one\n  # of the library ranges will be treated as coming from the main\n  # program binary.\n  my $min_pc = HexExtend(\"0\");\n  my $max_pc = $min_pc;          # find the maximal PC value in any sample\n  foreach my $pc (keys(%{$pcs})) {\n    if (HexExtend($pc) gt $max_pc) { $max_pc = HexExtend($pc); }\n  }\n  push(@{$result}, [$prog, $min_pc, $max_pc, $zero_offset]);\n\n  return $result;\n}\n\n# Add two hex addresses of length $address_length.\n# Run jeprof --test for unit test if this is changed.\nsub AddressAdd {\n  my $addr1 = shift;\n  my $addr2 = shift;\n  my $sum;\n\n  if ($address_length == 8) {\n    # Perl doesn't cope with wraparound arithmetic, so do it explicitly:\n    $sum = (hex($addr1)+hex($addr2)) % (0x10000000 * 16);\n    return sprintf(\"%08x\", $sum);\n\n  } else {\n    # Do the addition in 7-nibble chunks to trivialize carry handling.\n\n    if ($main::opt_debug and $main::opt_test) {\n      print STDERR \"AddressAdd $addr1 + $addr2 = \";\n    }\n\n    my $a1 = substr($addr1,-7);\n    $addr1 = substr($addr1,0,-7);\n    my $a2 = substr($addr2,-7);\n    $addr2 = substr($addr2,0,-7);\n    $sum = hex($a1) + hex($a2);\n    my $c = 0;\n    if ($sum > 0xfffffff) {\n      $c = 1;\n      $sum -= 0x10000000;\n    }\n    my $r = sprintf(\"%07x\", $sum);\n\n    $a1 = substr($addr1,-7);\n    $addr1 = substr($addr1,0,-7);\n    $a2 = substr($addr2,-7);\n    $addr2 = substr($addr2,0,-7);\n    $sum = hex($a1) + hex($a2) + $c;\n    $c = 0;\n    if ($sum > 0xfffffff) {\n      $c = 1;\n      $sum -= 0x10000000;\n    }\n    $r = sprintf(\"%07x\", $sum) . $r;\n\n    $sum = hex($addr1) + hex($addr2) + $c;\n    if ($sum > 0xff) { $sum -= 0x100; }\n    $r = sprintf(\"%02x\", $sum) . $r;\n\n    if ($main::opt_debug and $main::opt_test) { print STDERR \"$r\\n\"; }\n\n    return $r;\n  }\n}\n\n\n# Subtract two hex addresses of length $address_length.\n# Run jeprof --test for unit test if this is changed.\nsub AddressSub {\n  my $addr1 = shift;\n  my $addr2 = shift;\n  my $diff;\n\n  if ($address_length == 8) {\n    # Perl doesn't cope with wraparound arithmetic, so do it explicitly:\n    $diff = (hex($addr1)-hex($addr2)) % (0x10000000 * 16);\n    return sprintf(\"%08x\", $diff);\n\n  } else {\n    # Do the addition in 7-nibble chunks to trivialize borrow handling.\n    # if ($main::opt_debug) { print STDERR \"AddressSub $addr1 - $addr2 = \"; }\n\n    my $a1 = hex(substr($addr1,-7));\n    $addr1 = substr($addr1,0,-7);\n    my $a2 = hex(substr($addr2,-7));\n    $addr2 = substr($addr2,0,-7);\n    my $b = 0;\n    if ($a2 > $a1) {\n      $b = 1;\n      $a1 += 0x10000000;\n    }\n    $diff = $a1 - $a2;\n    my $r = sprintf(\"%07x\", $diff);\n\n    $a1 = hex(substr($addr1,-7));\n    $addr1 = substr($addr1,0,-7);\n    $a2 = hex(substr($addr2,-7)) + $b;\n    $addr2 = substr($addr2,0,-7);\n    $b = 0;\n    if ($a2 > $a1) {\n      $b = 1;\n      $a1 += 0x10000000;\n    }\n    $diff = $a1 - $a2;\n    $r = sprintf(\"%07x\", $diff) . $r;\n\n    $a1 = hex($addr1);\n    $a2 = hex($addr2) + $b;\n    if ($a2 > $a1) { $a1 += 0x100; }\n    $diff = $a1 - $a2;\n    $r = sprintf(\"%02x\", $diff) . $r;\n\n    # if ($main::opt_debug) { print STDERR \"$r\\n\"; }\n\n    return $r;\n  }\n}\n\n# Increment a hex addresses of length $address_length.\n# Run jeprof --test for unit test if this is changed.\nsub AddressInc {\n  my $addr = shift;\n  my $sum;\n\n  if ($address_length == 8) {\n    # Perl doesn't cope with wraparound arithmetic, so do it explicitly:\n    $sum = (hex($addr)+1) % (0x10000000 * 16);\n    return sprintf(\"%08x\", $sum);\n\n  } else {\n    # Do the addition in 7-nibble chunks to trivialize carry handling.\n    # We are always doing this to step through the addresses in a function,\n    # and will almost never overflow the first chunk, so we check for this\n    # case and exit early.\n\n    # if ($main::opt_debug) { print STDERR \"AddressInc $addr1 = \"; }\n\n    my $a1 = substr($addr,-7);\n    $addr = substr($addr,0,-7);\n    $sum = hex($a1) + 1;\n    my $r = sprintf(\"%07x\", $sum);\n    if ($sum <= 0xfffffff) {\n      $r = $addr . $r;\n      # if ($main::opt_debug) { print STDERR \"$r\\n\"; }\n      return HexExtend($r);\n    } else {\n      $r = \"0000000\";\n    }\n\n    $a1 = substr($addr,-7);\n    $addr = substr($addr,0,-7);\n    $sum = hex($a1) + 1;\n    $r = sprintf(\"%07x\", $sum) . $r;\n    if ($sum <= 0xfffffff) {\n      $r = $addr . $r;\n      # if ($main::opt_debug) { print STDERR \"$r\\n\"; }\n      return HexExtend($r);\n    } else {\n      $r = \"00000000000000\";\n    }\n\n    $sum = hex($addr) + 1;\n    if ($sum > 0xff) { $sum -= 0x100; }\n    $r = sprintf(\"%02x\", $sum) . $r;\n\n    # if ($main::opt_debug) { print STDERR \"$r\\n\"; }\n    return $r;\n  }\n}\n\n# Extract symbols for all PC values found in profile\nsub ExtractSymbols {\n  my $libs = shift;\n  my $pcset = shift;\n\n  my $symbols = {};\n\n  # Map each PC value to the containing library.  To make this faster,\n  # we sort libraries by their starting pc value (highest first), and\n  # advance through the libraries as we advance the pc.  Sometimes the\n  # addresses of libraries may overlap with the addresses of the main\n  # binary, so to make sure the libraries 'win', we iterate over the\n  # libraries in reverse order (which assumes the binary doesn't start\n  # in the middle of a library, which seems a fair assumption).\n  my @pcs = (sort { $a cmp $b } keys(%{$pcset}));  # pcset is 0-extended strings\n  foreach my $lib (sort {$b->[1] cmp $a->[1]} @{$libs}) {\n    my $libname = $lib->[0];\n    my $start = $lib->[1];\n    my $finish = $lib->[2];\n    my $offset = $lib->[3];\n\n    # Use debug library if it exists\n    my $debug_libname = DebuggingLibrary($libname);\n    if ($debug_libname) {\n        $libname = $debug_libname;\n    }\n\n    # Get list of pcs that belong in this library.\n    my $contained = [];\n    my ($start_pc_index, $finish_pc_index);\n    # Find smallest finish_pc_index such that $finish < $pc[$finish_pc_index].\n    for ($finish_pc_index = $#pcs + 1; $finish_pc_index > 0;\n         $finish_pc_index--) {\n      last if $pcs[$finish_pc_index - 1] le $finish;\n    }\n    # Find smallest start_pc_index such that $start <= $pc[$start_pc_index].\n    for ($start_pc_index = $finish_pc_index; $start_pc_index > 0;\n         $start_pc_index--) {\n      last if $pcs[$start_pc_index - 1] lt $start;\n    }\n    # This keeps PC values higher than $pc[$finish_pc_index] in @pcs,\n    # in case there are overlaps in libraries and the main binary.\n    @{$contained} = splice(@pcs, $start_pc_index,\n                           $finish_pc_index - $start_pc_index);\n    # Map to symbols\n    MapToSymbols($libname, AddressSub($start, $offset), $contained, $symbols);\n  }\n\n  return $symbols;\n}\n\n# Map list of PC values to symbols for a given image\nsub MapToSymbols {\n  my $image = shift;\n  my $offset = shift;\n  my $pclist = shift;\n  my $symbols = shift;\n\n  my $debug = 0;\n\n  # Ignore empty binaries\n  if ($#{$pclist} < 0) { return; }\n\n  # Figure out the addr2line command to use\n  my $addr2line = $obj_tool_map{\"addr2line\"};\n  my $cmd = ShellEscape($addr2line, \"-f\", \"-C\", \"-e\", $image);\n  if (exists $obj_tool_map{\"addr2line_pdb\"}) {\n    $addr2line = $obj_tool_map{\"addr2line_pdb\"};\n    $cmd = ShellEscape($addr2line, \"--demangle\", \"-f\", \"-C\", \"-e\", $image);\n  }\n\n  # If \"addr2line\" isn't installed on the system at all, just use\n  # nm to get what info we can (function names, but not line numbers).\n  if (system(ShellEscape($addr2line, \"--help\") . \" >$dev_null 2>&1\") != 0) {\n    MapSymbolsWithNM($image, $offset, $pclist, $symbols);\n    return;\n  }\n\n  # \"addr2line -i\" can produce a variable number of lines per input\n  # address, with no separator that allows us to tell when data for\n  # the next address starts.  So we find the address for a special\n  # symbol (_fini) and interleave this address between all real\n  # addresses passed to addr2line.  The name of this special symbol\n  # can then be used as a separator.\n  $sep_address = undef;  # May be filled in by MapSymbolsWithNM()\n  my $nm_symbols = {};\n  MapSymbolsWithNM($image, $offset, $pclist, $nm_symbols);\n  if (defined($sep_address)) {\n    # Only add \" -i\" to addr2line if the binary supports it.\n    # addr2line --help returns 0, but not if it sees an unknown flag first.\n    if (system(\"$cmd -i --help >$dev_null 2>&1\") == 0) {\n      $cmd .= \" -i\";\n    } else {\n      $sep_address = undef;   # no need for sep_address if we don't support -i\n    }\n  }\n\n  # Make file with all PC values with intervening 'sep_address' so\n  # that we can reliably detect the end of inlined function list\n  open(ADDRESSES, \">$main::tmpfile_sym\") || error(\"$main::tmpfile_sym: $!\\n\");\n  if ($debug) { print(\"---- $image ---\\n\"); }\n  for (my $i = 0; $i <= $#{$pclist}; $i++) {\n    # addr2line always reads hex addresses, and does not need '0x' prefix.\n    if ($debug) { printf STDERR (\"%s\\n\", $pclist->[$i]); }\n    printf ADDRESSES (\"%s\\n\", AddressSub($pclist->[$i], $offset));\n    if (defined($sep_address)) {\n      printf ADDRESSES (\"%s\\n\", $sep_address);\n    }\n  }\n  close(ADDRESSES);\n  if ($debug) {\n    print(\"----\\n\");\n    system(\"cat\", $main::tmpfile_sym);\n    print(\"----\\n\");\n    system(\"$cmd < \" . ShellEscape($main::tmpfile_sym));\n    print(\"----\\n\");\n  }\n\n  open(SYMBOLS, \"$cmd <\" . ShellEscape($main::tmpfile_sym) . \" |\")\n      || error(\"$cmd: $!\\n\");\n  my $count = 0;   # Index in pclist\n  while (<SYMBOLS>) {\n    # Read fullfunction and filelineinfo from next pair of lines\n    s/\\r?\\n$//g;\n    my $fullfunction = $_;\n    $_ = <SYMBOLS>;\n    s/\\r?\\n$//g;\n    my $filelinenum = $_;\n\n    if (defined($sep_address) && $fullfunction eq $sep_symbol) {\n      # Terminating marker for data for this address\n      $count++;\n      next;\n    }\n\n    $filelinenum =~ s|\\\\|/|g; # turn windows-style paths into unix-style paths\n\n    my $pcstr = $pclist->[$count];\n    my $function = ShortFunctionName($fullfunction);\n    my $nms = $nm_symbols->{$pcstr};\n    if (defined($nms)) {\n      if ($fullfunction eq '??') {\n        # nm found a symbol for us.\n        $function = $nms->[0];\n        $fullfunction = $nms->[2];\n      } else {\n\t# MapSymbolsWithNM tags each routine with its starting address,\n\t# useful in case the image has multiple occurrences of this\n\t# routine.  (It uses a syntax that resembles template paramters,\n\t# that are automatically stripped out by ShortFunctionName().)\n\t# addr2line does not provide the same information.  So we check\n\t# if nm disambiguated our symbol, and if so take the annotated\n\t# (nm) version of the routine-name.  TODO(csilvers): this won't\n\t# catch overloaded, inlined symbols, which nm doesn't see.\n\t# Better would be to do a check similar to nm's, in this fn.\n\tif ($nms->[2] =~ m/^\\Q$function\\E/) {  # sanity check it's the right fn\n\t  $function = $nms->[0];\n\t  $fullfunction = $nms->[2];\n\t}\n      }\n    }\n\n    # Prepend to accumulated symbols for pcstr\n    # (so that caller comes before callee)\n    my $sym = $symbols->{$pcstr};\n    if (!defined($sym)) {\n      $sym = [];\n      $symbols->{$pcstr} = $sym;\n    }\n    unshift(@{$sym}, $function, $filelinenum, $fullfunction);\n    if ($debug) { printf STDERR (\"%s => [%s]\\n\", $pcstr, join(\" \", @{$sym})); }\n    if (!defined($sep_address)) {\n      # Inlining is off, so this entry ends immediately\n      $count++;\n    }\n  }\n  close(SYMBOLS);\n}\n\n# Use nm to map the list of referenced PCs to symbols.  Return true iff we\n# are able to read procedure information via nm.\nsub MapSymbolsWithNM {\n  my $image = shift;\n  my $offset = shift;\n  my $pclist = shift;\n  my $symbols = shift;\n\n  # Get nm output sorted by increasing address\n  my $symbol_table = GetProcedureBoundaries($image, \".\");\n  if (!%{$symbol_table}) {\n    return 0;\n  }\n  # Start addresses are already the right length (8 or 16 hex digits).\n  my @names = sort { $symbol_table->{$a}->[0] cmp $symbol_table->{$b}->[0] }\n    keys(%{$symbol_table});\n\n  if ($#names < 0) {\n    # No symbols: just use addresses\n    foreach my $pc (@{$pclist}) {\n      my $pcstr = \"0x\" . $pc;\n      $symbols->{$pc} = [$pcstr, \"?\", $pcstr];\n    }\n    return 0;\n  }\n\n  # Sort addresses so we can do a join against nm output\n  my $index = 0;\n  my $fullname = $names[0];\n  my $name = ShortFunctionName($fullname);\n  foreach my $pc (sort { $a cmp $b } @{$pclist}) {\n    # Adjust for mapped offset\n    my $mpc = AddressSub($pc, $offset);\n    while (($index < $#names) && ($mpc ge $symbol_table->{$fullname}->[1])){\n      $index++;\n      $fullname = $names[$index];\n      $name = ShortFunctionName($fullname);\n    }\n    if ($mpc lt $symbol_table->{$fullname}->[1]) {\n      $symbols->{$pc} = [$name, \"?\", $fullname];\n    } else {\n      my $pcstr = \"0x\" . $pc;\n      $symbols->{$pc} = [$pcstr, \"?\", $pcstr];\n    }\n  }\n  return 1;\n}\n\nsub ShortFunctionName {\n  my $function = shift;\n  while ($function =~ s/\\([^()]*\\)(\\s*const)?//g) { }   # Argument types\n  while ($function =~ s/<[^<>]*>//g)  { }    # Remove template arguments\n  $function =~ s/^.*\\s+(\\w+::)/$1/;          # Remove leading type\n  return $function;\n}\n\n# Trim overly long symbols found in disassembler output\nsub CleanDisassembly {\n  my $d = shift;\n  while ($d =~ s/\\([^()%]*\\)(\\s*const)?//g) { } # Argument types, not (%rax)\n  while ($d =~ s/(\\w+)<[^<>]*>/$1/g)  { }       # Remove template arguments\n  return $d;\n}\n\n# Clean file name for display\nsub CleanFileName {\n  my ($f) = @_;\n  $f =~ s|^/proc/self/cwd/||;\n  $f =~ s|^\\./||;\n  return $f;\n}\n\n# Make address relative to section and clean up for display\nsub UnparseAddress {\n  my ($offset, $address) = @_;\n  $address = AddressSub($address, $offset);\n  $address =~ s/^0x//;\n  $address =~ s/^0*//;\n  return $address;\n}\n\n##### Miscellaneous #####\n\n# Find the right versions of the above object tools to use.  The\n# argument is the program file being analyzed, and should be an ELF\n# 32-bit or ELF 64-bit executable file.  The location of the tools\n# is determined by considering the following options in this order:\n#   1) --tools option, if set\n#   2) JEPROF_TOOLS environment variable, if set\n#   3) the environment\nsub ConfigureObjTools {\n  my $prog_file = shift;\n\n  # Check for the existence of $prog_file because /usr/bin/file does not\n  # predictably return error status in prod.\n  (-e $prog_file)  || error(\"$prog_file does not exist.\\n\");\n\n  my $file_type = undef;\n  if (-e \"/usr/bin/file\") {\n    # Follow symlinks (at least for systems where \"file\" supports that).\n    my $escaped_prog_file = ShellEscape($prog_file);\n    $file_type = `/usr/bin/file -L $escaped_prog_file 2>$dev_null ||\n                  /usr/bin/file $escaped_prog_file`;\n  } elsif ($^O == \"MSWin32\") {\n    $file_type = \"MS Windows\";\n  } else {\n    print STDERR \"WARNING: Can't determine the file type of $prog_file\";\n  }\n\n  if ($file_type =~ /64-bit/) {\n    # Change $address_length to 16 if the program file is ELF 64-bit.\n    # We can't detect this from many (most?) heap or lock contention\n    # profiles, since the actual addresses referenced are generally in low\n    # memory even for 64-bit programs.\n    $address_length = 16;\n  }\n\n  if ($file_type =~ /MS Windows/) {\n    # For windows, we provide a version of nm and addr2line as part of\n    # the opensource release, which is capable of parsing\n    # Windows-style PDB executables.  It should live in the path, or\n    # in the same directory as jeprof.\n    $obj_tool_map{\"nm_pdb\"} = \"nm-pdb\";\n    $obj_tool_map{\"addr2line_pdb\"} = \"addr2line-pdb\";\n  }\n\n  if ($file_type =~ /Mach-O/) {\n    # OS X uses otool to examine Mach-O files, rather than objdump.\n    $obj_tool_map{\"otool\"} = \"otool\";\n    $obj_tool_map{\"addr2line\"} = \"false\";  # no addr2line\n    $obj_tool_map{\"objdump\"} = \"false\";  # no objdump\n  }\n\n  # Go fill in %obj_tool_map with the pathnames to use:\n  foreach my $tool (keys %obj_tool_map) {\n    $obj_tool_map{$tool} = ConfigureTool($obj_tool_map{$tool});\n  }\n}\n\n# Returns the path of a caller-specified object tool.  If --tools or\n# JEPROF_TOOLS are specified, then returns the full path to the tool\n# with that prefix.  Otherwise, returns the path unmodified (which\n# means we will look for it on PATH).\nsub ConfigureTool {\n  my $tool = shift;\n  my $path;\n\n  # --tools (or $JEPROF_TOOLS) is a comma separated list, where each\n  # item is either a) a pathname prefix, or b) a map of the form\n  # <tool>:<path>.  First we look for an entry of type (b) for our\n  # tool.  If one is found, we use it.  Otherwise, we consider all the\n  # pathname prefixes in turn, until one yields an existing file.  If\n  # none does, we use a default path.\n  my $tools = $main::opt_tools || $ENV{\"JEPROF_TOOLS\"} || \"\";\n  if ($tools =~ m/(,|^)\\Q$tool\\E:([^,]*)/) {\n    $path = $2;\n    # TODO(csilvers): sanity-check that $path exists?  Hard if it's relative.\n  } elsif ($tools ne '') {\n    foreach my $prefix (split(',', $tools)) {\n      next if ($prefix =~ /:/);    # ignore \"tool:fullpath\" entries in the list\n      if (-x $prefix . $tool) {\n        $path = $prefix . $tool;\n        last;\n      }\n    }\n    if (!$path) {\n      error(\"No '$tool' found with prefix specified by \" .\n            \"--tools (or \\$JEPROF_TOOLS) '$tools'\\n\");\n    }\n  } else {\n    # ... otherwise use the version that exists in the same directory as\n    # jeprof.  If there's nothing there, use $PATH.\n    $0 =~ m,[^/]*$,;     # this is everything after the last slash\n    my $dirname = $`;    # this is everything up to and including the last slash\n    if (-x \"$dirname$tool\") {\n      $path = \"$dirname$tool\";\n    } else {\n      $path = $tool;\n    }\n  }\n  if ($main::opt_debug) { print STDERR \"Using '$path' for '$tool'.\\n\"; }\n  return $path;\n}\n\nsub ShellEscape {\n  my @escaped_words = ();\n  foreach my $word (@_) {\n    my $escaped_word = $word;\n    if ($word =~ m![^a-zA-Z0-9/.,_=-]!) {  # check for anything not in whitelist\n      $escaped_word =~ s/'/'\\\\''/;\n      $escaped_word = \"'$escaped_word'\";\n    }\n    push(@escaped_words, $escaped_word);\n  }\n  return join(\" \", @escaped_words);\n}\n\nsub cleanup {\n  unlink($main::tmpfile_sym);\n  unlink(keys %main::tempnames);\n\n  # We leave any collected profiles in $HOME/jeprof in case the user wants\n  # to look at them later.  We print a message informing them of this.\n  if ((scalar(@main::profile_files) > 0) &&\n      defined($main::collected_profile)) {\n    if (scalar(@main::profile_files) == 1) {\n      print STDERR \"Dynamically gathered profile is in $main::collected_profile\\n\";\n    }\n    print STDERR \"If you want to investigate this profile further, you can do:\\n\";\n    print STDERR \"\\n\";\n    print STDERR \"  jeprof \\\\\\n\";\n    print STDERR \"    $main::prog \\\\\\n\";\n    print STDERR \"    $main::collected_profile\\n\";\n    print STDERR \"\\n\";\n  }\n}\n\nsub sighandler {\n  cleanup();\n  exit(1);\n}\n\nsub error {\n  my $msg = shift;\n  print STDERR $msg;\n  cleanup();\n  exit(1);\n}\n\n\n# Run $nm_command and get all the resulting procedure boundaries whose\n# names match \"$regexp\" and returns them in a hashtable mapping from\n# procedure name to a two-element vector of [start address, end address]\nsub GetProcedureBoundariesViaNm {\n  my $escaped_nm_command = shift;    # shell-escaped\n  my $regexp = shift;\n\n  my $symbol_table = {};\n  open(NM, \"$escaped_nm_command |\") || error(\"$escaped_nm_command: $!\\n\");\n  my $last_start = \"0\";\n  my $routine = \"\";\n  while (<NM>) {\n    s/\\r//g;         # turn windows-looking lines into unix-looking lines\n    if (m/^\\s*([0-9a-f]+) (.) (..*)/) {\n      my $start_val = $1;\n      my $type = $2;\n      my $this_routine = $3;\n\n      # It's possible for two symbols to share the same address, if\n      # one is a zero-length variable (like __start_google_malloc) or\n      # one symbol is a weak alias to another (like __libc_malloc).\n      # In such cases, we want to ignore all values except for the\n      # actual symbol, which in nm-speak has type \"T\".  The logic\n      # below does this, though it's a bit tricky: what happens when\n      # we have a series of lines with the same address, is the first\n      # one gets queued up to be processed.  However, it won't\n      # *actually* be processed until later, when we read a line with\n      # a different address.  That means that as long as we're reading\n      # lines with the same address, we have a chance to replace that\n      # item in the queue, which we do whenever we see a 'T' entry --\n      # that is, a line with type 'T'.  If we never see a 'T' entry,\n      # we'll just go ahead and process the first entry (which never\n      # got touched in the queue), and ignore the others.\n      if ($start_val eq $last_start && $type =~ /t/i) {\n        # We are the 'T' symbol at this address, replace previous symbol.\n        $routine = $this_routine;\n        next;\n      } elsif ($start_val eq $last_start) {\n        # We're not the 'T' symbol at this address, so ignore us.\n        next;\n      }\n\n      if ($this_routine eq $sep_symbol) {\n        $sep_address = HexExtend($start_val);\n      }\n\n      # Tag this routine with the starting address in case the image\n      # has multiple occurrences of this routine.  We use a syntax\n      # that resembles template parameters that are automatically\n      # stripped out by ShortFunctionName()\n      $this_routine .= \"<$start_val>\";\n\n      if (defined($routine) && $routine =~ m/$regexp/) {\n        $symbol_table->{$routine} = [HexExtend($last_start),\n                                     HexExtend($start_val)];\n      }\n      $last_start = $start_val;\n      $routine = $this_routine;\n    } elsif (m/^Loaded image name: (.+)/) {\n      # The win32 nm workalike emits information about the binary it is using.\n      if ($main::opt_debug) { print STDERR \"Using Image $1\\n\"; }\n    } elsif (m/^PDB file name: (.+)/) {\n      # The win32 nm workalike emits information about the pdb it is using.\n      if ($main::opt_debug) { print STDERR \"Using PDB $1\\n\"; }\n    }\n  }\n  close(NM);\n  # Handle the last line in the nm output.  Unfortunately, we don't know\n  # how big this last symbol is, because we don't know how big the file\n  # is.  For now, we just give it a size of 0.\n  # TODO(csilvers): do better here.\n  if (defined($routine) && $routine =~ m/$regexp/) {\n    $symbol_table->{$routine} = [HexExtend($last_start),\n                                 HexExtend($last_start)];\n  }\n  return $symbol_table;\n}\n\n# Gets the procedure boundaries for all routines in \"$image\" whose names\n# match \"$regexp\" and returns them in a hashtable mapping from procedure\n# name to a two-element vector of [start address, end address].\n# Will return an empty map if nm is not installed or not working properly.\nsub GetProcedureBoundaries {\n  my $image = shift;\n  my $regexp = shift;\n\n  # If $image doesn't start with /, then put ./ in front of it.  This works\n  # around an obnoxious bug in our probing of nm -f behavior.\n  # \"nm -f $image\" is supposed to fail on GNU nm, but if:\n  #\n  # a. $image starts with [BbSsPp] (for example, bin/foo/bar), AND\n  # b. you have a.out in your current directory (a not uncommon occurence)\n  #\n  # then \"nm -f $image\" succeeds because -f only looks at the first letter of\n  # the argument, which looks valid because it's [BbSsPp], and then since\n  # there's no image provided, it looks for a.out and finds it.\n  #\n  # This regex makes sure that $image starts with . or /, forcing the -f\n  # parsing to fail since . and / are not valid formats.\n  $image =~ s#^[^/]#./$&#;\n\n  # For libc libraries, the copy in /usr/lib/debug contains debugging symbols\n  my $debugging = DebuggingLibrary($image);\n  if ($debugging) {\n    $image = $debugging;\n  }\n\n  my $nm = $obj_tool_map{\"nm\"};\n  my $cppfilt = $obj_tool_map{\"c++filt\"};\n\n  # nm can fail for two reasons: 1) $image isn't a debug library; 2) nm\n  # binary doesn't support --demangle.  In addition, for OS X we need\n  # to use the -f flag to get 'flat' nm output (otherwise we don't sort\n  # properly and get incorrect results).  Unfortunately, GNU nm uses -f\n  # in an incompatible way.  So first we test whether our nm supports\n  # --demangle and -f.\n  my $demangle_flag = \"\";\n  my $cppfilt_flag = \"\";\n  my $to_devnull = \">$dev_null 2>&1\";\n  if (system(ShellEscape($nm, \"--demangle\", \"image\") . $to_devnull) == 0) {\n    # In this mode, we do \"nm --demangle <foo>\"\n    $demangle_flag = \"--demangle\";\n    $cppfilt_flag = \"\";\n  } elsif (system(ShellEscape($cppfilt, $image) . $to_devnull) == 0) {\n    # In this mode, we do \"nm <foo> | c++filt\"\n    $cppfilt_flag = \" | \" . ShellEscape($cppfilt);\n  };\n  my $flatten_flag = \"\";\n  if (system(ShellEscape($nm, \"-f\", $image) . $to_devnull) == 0) {\n    $flatten_flag = \"-f\";\n  }\n\n  # Finally, in the case $imagie isn't a debug library, we try again with\n  # -D to at least get *exported* symbols.  If we can't use --demangle,\n  # we use c++filt instead, if it exists on this system.\n  my @nm_commands = (ShellEscape($nm, \"-n\", $flatten_flag, $demangle_flag,\n                                 $image) . \" 2>$dev_null $cppfilt_flag\",\n                     ShellEscape($nm, \"-D\", \"-n\", $flatten_flag, $demangle_flag,\n                                 $image) . \" 2>$dev_null $cppfilt_flag\",\n                     # 6nm is for Go binaries\n                     ShellEscape(\"6nm\", \"$image\") . \" 2>$dev_null | sort\",\n                     );\n\n  # If the executable is an MS Windows PDB-format executable, we'll\n  # have set up obj_tool_map(\"nm_pdb\").  In this case, we actually\n  # want to use both unix nm and windows-specific nm_pdb, since\n  # PDB-format executables can apparently include dwarf .o files.\n  if (exists $obj_tool_map{\"nm_pdb\"}) {\n    push(@nm_commands,\n         ShellEscape($obj_tool_map{\"nm_pdb\"}, \"--demangle\", $image)\n         . \" 2>$dev_null\");\n  }\n\n  foreach my $nm_command (@nm_commands) {\n    my $symbol_table = GetProcedureBoundariesViaNm($nm_command, $regexp);\n    return $symbol_table if (%{$symbol_table});\n  }\n  my $symbol_table = {};\n  return $symbol_table;\n}\n\n\n# The test vectors for AddressAdd/Sub/Inc are 8-16-nibble hex strings.\n# To make them more readable, we add underscores at interesting places.\n# This routine removes the underscores, producing the canonical representation\n# used by jeprof to represent addresses, particularly in the tested routines.\nsub CanonicalHex {\n  my $arg = shift;\n  return join '', (split '_',$arg);\n}\n\n\n# Unit test for AddressAdd:\nsub AddressAddUnitTest {\n  my $test_data_8 = shift;\n  my $test_data_16 = shift;\n  my $error_count = 0;\n  my $fail_count = 0;\n  my $pass_count = 0;\n  # print STDERR \"AddressAddUnitTest: \", 1+$#{$test_data_8}, \" tests\\n\";\n\n  # First a few 8-nibble addresses.  Note that this implementation uses\n  # plain old arithmetic, so a quick sanity check along with verifying what\n  # happens to overflow (we want it to wrap):\n  $address_length = 8;\n  foreach my $row (@{$test_data_8}) {\n    if ($main::opt_debug and $main::opt_test) { print STDERR \"@{$row}\\n\"; }\n    my $sum = AddressAdd ($row->[0], $row->[1]);\n    if ($sum ne $row->[2]) {\n      printf STDERR \"ERROR: %s != %s + %s = %s\\n\", $sum,\n             $row->[0], $row->[1], $row->[2];\n      ++$fail_count;\n    } else {\n      ++$pass_count;\n    }\n  }\n  printf STDERR \"AddressAdd 32-bit tests: %d passes, %d failures\\n\",\n         $pass_count, $fail_count;\n  $error_count = $fail_count;\n  $fail_count = 0;\n  $pass_count = 0;\n\n  # Now 16-nibble addresses.\n  $address_length = 16;\n  foreach my $row (@{$test_data_16}) {\n    if ($main::opt_debug and $main::opt_test) { print STDERR \"@{$row}\\n\"; }\n    my $sum = AddressAdd (CanonicalHex($row->[0]), CanonicalHex($row->[1]));\n    my $expected = join '', (split '_',$row->[2]);\n    if ($sum ne CanonicalHex($row->[2])) {\n      printf STDERR \"ERROR: %s != %s + %s = %s\\n\", $sum,\n             $row->[0], $row->[1], $row->[2];\n      ++$fail_count;\n    } else {\n      ++$pass_count;\n    }\n  }\n  printf STDERR \"AddressAdd 64-bit tests: %d passes, %d failures\\n\",\n         $pass_count, $fail_count;\n  $error_count += $fail_count;\n\n  return $error_count;\n}\n\n\n# Unit test for AddressSub:\nsub AddressSubUnitTest {\n  my $test_data_8 = shift;\n  my $test_data_16 = shift;\n  my $error_count = 0;\n  my $fail_count = 0;\n  my $pass_count = 0;\n  # print STDERR \"AddressSubUnitTest: \", 1+$#{$test_data_8}, \" tests\\n\";\n\n  # First a few 8-nibble addresses.  Note that this implementation uses\n  # plain old arithmetic, so a quick sanity check along with verifying what\n  # happens to overflow (we want it to wrap):\n  $address_length = 8;\n  foreach my $row (@{$test_data_8}) {\n    if ($main::opt_debug and $main::opt_test) { print STDERR \"@{$row}\\n\"; }\n    my $sum = AddressSub ($row->[0], $row->[1]);\n    if ($sum ne $row->[3]) {\n      printf STDERR \"ERROR: %s != %s - %s = %s\\n\", $sum,\n             $row->[0], $row->[1], $row->[3];\n      ++$fail_count;\n    } else {\n      ++$pass_count;\n    }\n  }\n  printf STDERR \"AddressSub 32-bit tests: %d passes, %d failures\\n\",\n         $pass_count, $fail_count;\n  $error_count = $fail_count;\n  $fail_count = 0;\n  $pass_count = 0;\n\n  # Now 16-nibble addresses.\n  $address_length = 16;\n  foreach my $row (@{$test_data_16}) {\n    if ($main::opt_debug and $main::opt_test) { print STDERR \"@{$row}\\n\"; }\n    my $sum = AddressSub (CanonicalHex($row->[0]), CanonicalHex($row->[1]));\n    if ($sum ne CanonicalHex($row->[3])) {\n      printf STDERR \"ERROR: %s != %s - %s = %s\\n\", $sum,\n             $row->[0], $row->[1], $row->[3];\n      ++$fail_count;\n    } else {\n      ++$pass_count;\n    }\n  }\n  printf STDERR \"AddressSub 64-bit tests: %d passes, %d failures\\n\",\n         $pass_count, $fail_count;\n  $error_count += $fail_count;\n\n  return $error_count;\n}\n\n\n# Unit test for AddressInc:\nsub AddressIncUnitTest {\n  my $test_data_8 = shift;\n  my $test_data_16 = shift;\n  my $error_count = 0;\n  my $fail_count = 0;\n  my $pass_count = 0;\n  # print STDERR \"AddressIncUnitTest: \", 1+$#{$test_data_8}, \" tests\\n\";\n\n  # First a few 8-nibble addresses.  Note that this implementation uses\n  # plain old arithmetic, so a quick sanity check along with verifying what\n  # happens to overflow (we want it to wrap):\n  $address_length = 8;\n  foreach my $row (@{$test_data_8}) {\n    if ($main::opt_debug and $main::opt_test) { print STDERR \"@{$row}\\n\"; }\n    my $sum = AddressInc ($row->[0]);\n    if ($sum ne $row->[4]) {\n      printf STDERR \"ERROR: %s != %s + 1 = %s\\n\", $sum,\n             $row->[0], $row->[4];\n      ++$fail_count;\n    } else {\n      ++$pass_count;\n    }\n  }\n  printf STDERR \"AddressInc 32-bit tests: %d passes, %d failures\\n\",\n         $pass_count, $fail_count;\n  $error_count = $fail_count;\n  $fail_count = 0;\n  $pass_count = 0;\n\n  # Now 16-nibble addresses.\n  $address_length = 16;\n  foreach my $row (@{$test_data_16}) {\n    if ($main::opt_debug and $main::opt_test) { print STDERR \"@{$row}\\n\"; }\n    my $sum = AddressInc (CanonicalHex($row->[0]));\n    if ($sum ne CanonicalHex($row->[4])) {\n      printf STDERR \"ERROR: %s != %s + 1 = %s\\n\", $sum,\n             $row->[0], $row->[4];\n      ++$fail_count;\n    } else {\n      ++$pass_count;\n    }\n  }\n  printf STDERR \"AddressInc 64-bit tests: %d passes, %d failures\\n\",\n         $pass_count, $fail_count;\n  $error_count += $fail_count;\n\n  return $error_count;\n}\n\n\n# Driver for unit tests.\n# Currently just the address add/subtract/increment routines for 64-bit.\nsub RunUnitTests {\n  my $error_count = 0;\n\n  # This is a list of tuples [a, b, a+b, a-b, a+1]\n  my $unit_test_data_8 = [\n    [qw(aaaaaaaa 50505050 fafafafa 5a5a5a5a aaaaaaab)],\n    [qw(50505050 aaaaaaaa fafafafa a5a5a5a6 50505051)],\n    [qw(ffffffff aaaaaaaa aaaaaaa9 55555555 00000000)],\n    [qw(00000001 ffffffff 00000000 00000002 00000002)],\n    [qw(00000001 fffffff0 fffffff1 00000011 00000002)],\n  ];\n  my $unit_test_data_16 = [\n    # The implementation handles data in 7-nibble chunks, so those are the\n    # interesting boundaries.\n    [qw(aaaaaaaa 50505050\n        00_000000f_afafafa 00_0000005_a5a5a5a 00_000000a_aaaaaab)],\n    [qw(50505050 aaaaaaaa\n        00_000000f_afafafa ff_ffffffa_5a5a5a6 00_0000005_0505051)],\n    [qw(ffffffff aaaaaaaa\n        00_000001a_aaaaaa9 00_0000005_5555555 00_0000010_0000000)],\n    [qw(00000001 ffffffff\n        00_0000010_0000000 ff_ffffff0_0000002 00_0000000_0000002)],\n    [qw(00000001 fffffff0\n        00_000000f_ffffff1 ff_ffffff0_0000011 00_0000000_0000002)],\n\n    [qw(00_a00000a_aaaaaaa 50505050\n        00_a00000f_afafafa 00_a000005_a5a5a5a 00_a00000a_aaaaaab)],\n    [qw(0f_fff0005_0505050 aaaaaaaa\n        0f_fff000f_afafafa 0f_ffefffa_5a5a5a6 0f_fff0005_0505051)],\n    [qw(00_000000f_fffffff 01_800000a_aaaaaaa\n        01_800001a_aaaaaa9 fe_8000005_5555555 00_0000010_0000000)],\n    [qw(00_0000000_0000001 ff_fffffff_fffffff\n        00_0000000_0000000 00_0000000_0000002 00_0000000_0000002)],\n    [qw(00_0000000_0000001 ff_fffffff_ffffff0\n        ff_fffffff_ffffff1 00_0000000_0000011 00_0000000_0000002)],\n  ];\n\n  $error_count += AddressAddUnitTest($unit_test_data_8, $unit_test_data_16);\n  $error_count += AddressSubUnitTest($unit_test_data_8, $unit_test_data_16);\n  $error_count += AddressIncUnitTest($unit_test_data_8, $unit_test_data_16);\n  if ($error_count > 0) {\n    print STDERR $error_count, \" errors: FAILED\\n\";\n  } else {\n    print STDERR \"PASS\\n\";\n  }\n  exit ($error_count);\n}\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/deps/jemalloc/build-aux/config.guess",
    "content": "#! /bin/sh\n# Attempt to guess a canonical system name.\n#   Copyright 1992-2014 Free Software Foundation, Inc.\n\ntimestamp='2014-03-23'\n\n# This file is free software; you can redistribute it and/or modify it\n# under the terms of the GNU General Public License as published by\n# the Free Software Foundation; either version 3 of the License, or\n# (at your option) any later version.\n#\n# This program is distributed in the hope that it will be useful, but\n# WITHOUT ANY WARRANTY; without even the implied warranty of\n# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n# General Public License for more details.\n#\n# You should have received a copy of the GNU General Public License\n# along with this program; if not, see <http://www.gnu.org/licenses/>.\n#\n# As a special exception to the GNU General Public License, if you\n# distribute this file as part of a program that contains a\n# configuration script generated by Autoconf, you may include it under\n# the same distribution terms that you use for the rest of that\n# program.  This Exception is an additional permission under section 7\n# of the GNU General Public License, version 3 (\"GPLv3\").\n#\n# Originally written by Per Bothner.\n#\n# You can get the latest version of this script from:\n# http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.guess;hb=HEAD\n#\n# Please send patches with a ChangeLog entry to config-patches@gnu.org.\n\n\nme=`echo \"$0\" | sed -e 's,.*/,,'`\n\nusage=\"\\\nUsage: $0 [OPTION]\n\nOutput the configuration name of the system \\`$me' is run on.\n\nOperation modes:\n  -h, --help         print this help, then exit\n  -t, --time-stamp   print date of last modification, then exit\n  -v, --version      print version number, then exit\n\nReport bugs and patches to <config-patches@gnu.org>.\"\n\nversion=\"\\\nGNU config.guess ($timestamp)\n\nOriginally written by Per Bothner.\nCopyright 1992-2014 Free Software Foundation, Inc.\n\nThis is free software; see the source for copying conditions.  There is NO\nwarranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\"\n\nhelp=\"\nTry \\`$me --help' for more information.\"\n\n# Parse command line\nwhile test $# -gt 0 ; do\n  case $1 in\n    --time-stamp | --time* | -t )\n       echo \"$timestamp\" ; exit ;;\n    --version | -v )\n       echo \"$version\" ; exit ;;\n    --help | --h* | -h )\n       echo \"$usage\"; exit ;;\n    -- )     # Stop option processing\n       shift; break ;;\n    - )\t# Use stdin as input.\n       break ;;\n    -* )\n       echo \"$me: invalid option $1$help\" >&2\n       exit 1 ;;\n    * )\n       break ;;\n  esac\ndone\n\nif test $# != 0; then\n  echo \"$me: too many arguments$help\" >&2\n  exit 1\nfi\n\ntrap 'exit 1' 1 2 15\n\n# CC_FOR_BUILD -- compiler used by this script. Note that the use of a\n# compiler to aid in system detection is discouraged as it requires\n# temporary files to be created and, as you can see below, it is a\n# headache to deal with in a portable fashion.\n\n# Historically, `CC_FOR_BUILD' used to be named `HOST_CC'. We still\n# use `HOST_CC' if defined, but it is deprecated.\n\n# Portable tmp directory creation inspired by the Autoconf team.\n\nset_cc_for_build='\ntrap \"exitcode=\\$?; (rm -f \\$tmpfiles 2>/dev/null; rmdir \\$tmp 2>/dev/null) && exit \\$exitcode\" 0 ;\ntrap \"rm -f \\$tmpfiles 2>/dev/null; rmdir \\$tmp 2>/dev/null; exit 1\" 1 2 13 15 ;\n: ${TMPDIR=/tmp} ;\n { tmp=`(umask 077 && mktemp -d \"$TMPDIR/cgXXXXXX\") 2>/dev/null` && test -n \"$tmp\" && test -d \"$tmp\" ; } ||\n { test -n \"$RANDOM\" && tmp=$TMPDIR/cg$$-$RANDOM && (umask 077 && mkdir $tmp) ; } ||\n { tmp=$TMPDIR/cg-$$ && (umask 077 && mkdir $tmp) && echo \"Warning: creating insecure temp directory\" >&2 ; } ||\n { echo \"$me: cannot create a temporary directory in $TMPDIR\" >&2 ; exit 1 ; } ;\ndummy=$tmp/dummy ;\ntmpfiles=\"$dummy.c $dummy.o $dummy.rel $dummy\" ;\ncase $CC_FOR_BUILD,$HOST_CC,$CC in\n ,,)    echo \"int x;\" > $dummy.c ;\n\tfor c in cc gcc c89 c99 ; do\n\t  if ($c -c -o $dummy.o $dummy.c) >/dev/null 2>&1 ; then\n\t     CC_FOR_BUILD=\"$c\"; break ;\n\t  fi ;\n\tdone ;\n\tif test x\"$CC_FOR_BUILD\" = x ; then\n\t  CC_FOR_BUILD=no_compiler_found ;\n\tfi\n\t;;\n ,,*)   CC_FOR_BUILD=$CC ;;\n ,*,*)  CC_FOR_BUILD=$HOST_CC ;;\nesac ; set_cc_for_build= ;'\n\n# This is needed to find uname on a Pyramid OSx when run in the BSD universe.\n# (ghazi@noc.rutgers.edu 1994-08-24)\nif (test -f /.attbin/uname) >/dev/null 2>&1 ; then\n\tPATH=$PATH:/.attbin ; export PATH\nfi\n\nUNAME_MACHINE=`(uname -m) 2>/dev/null` || UNAME_MACHINE=unknown\nUNAME_RELEASE=`(uname -r) 2>/dev/null` || UNAME_RELEASE=unknown\nUNAME_SYSTEM=`(uname -s) 2>/dev/null`  || UNAME_SYSTEM=unknown\nUNAME_VERSION=`(uname -v) 2>/dev/null` || UNAME_VERSION=unknown\n\ncase \"${UNAME_SYSTEM}\" in\nLinux|GNU|GNU/*)\n\t# If the system lacks a compiler, then just pick glibc.\n\t# We could probably try harder.\n\tLIBC=gnu\n\n\teval $set_cc_for_build\n\tcat <<-EOF > $dummy.c\n\t#include <features.h>\n\t#if defined(__UCLIBC__)\n\tLIBC=uclibc\n\t#elif defined(__dietlibc__)\n\tLIBC=dietlibc\n\t#else\n\tLIBC=gnu\n\t#endif\n\tEOF\n\teval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep '^LIBC' | sed 's, ,,g'`\n\t;;\nesac\n\n# Note: order is significant - the case branches are not exclusive.\n\ncase \"${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}\" in\n    *:NetBSD:*:*)\n\t# NetBSD (nbsd) targets should (where applicable) match one or\n\t# more of the tuples: *-*-netbsdelf*, *-*-netbsdaout*,\n\t# *-*-netbsdecoff* and *-*-netbsd*.  For targets that recently\n\t# switched to ELF, *-*-netbsd* would select the old\n\t# object file format.  This provides both forward\n\t# compatibility and a consistent mechanism for selecting the\n\t# object file format.\n\t#\n\t# Note: NetBSD doesn't particularly care about the vendor\n\t# portion of the name.  We always set it to \"unknown\".\n\tsysctl=\"sysctl -n hw.machine_arch\"\n\tUNAME_MACHINE_ARCH=`(/sbin/$sysctl 2>/dev/null || \\\n\t    /usr/sbin/$sysctl 2>/dev/null || echo unknown)`\n\tcase \"${UNAME_MACHINE_ARCH}\" in\n\t    armeb) machine=armeb-unknown ;;\n\t    arm*) machine=arm-unknown ;;\n\t    sh3el) machine=shl-unknown ;;\n\t    sh3eb) machine=sh-unknown ;;\n\t    sh5el) machine=sh5le-unknown ;;\n\t    *) machine=${UNAME_MACHINE_ARCH}-unknown ;;\n\tesac\n\t# The Operating System including object format, if it has switched\n\t# to ELF recently, or will in the future.\n\tcase \"${UNAME_MACHINE_ARCH}\" in\n\t    arm*|i386|m68k|ns32k|sh3*|sparc|vax)\n\t\teval $set_cc_for_build\n\t\tif echo __ELF__ | $CC_FOR_BUILD -E - 2>/dev/null \\\n\t\t\t| grep -q __ELF__\n\t\tthen\n\t\t    # Once all utilities can be ECOFF (netbsdecoff) or a.out (netbsdaout).\n\t\t    # Return netbsd for either.  FIX?\n\t\t    os=netbsd\n\t\telse\n\t\t    os=netbsdelf\n\t\tfi\n\t\t;;\n\t    *)\n\t\tos=netbsd\n\t\t;;\n\tesac\n\t# The OS release\n\t# Debian GNU/NetBSD machines have a different userland, and\n\t# thus, need a distinct triplet. However, they do not need\n\t# kernel version information, so it can be replaced with a\n\t# suitable tag, in the style of linux-gnu.\n\tcase \"${UNAME_VERSION}\" in\n\t    Debian*)\n\t\trelease='-gnu'\n\t\t;;\n\t    *)\n\t\trelease=`echo ${UNAME_RELEASE}|sed -e 's/[-_].*/\\./'`\n\t\t;;\n\tesac\n\t# Since CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM:\n\t# contains redundant information, the shorter form:\n\t# CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM is used.\n\techo \"${machine}-${os}${release}\"\n\texit ;;\n    *:Bitrig:*:*)\n\tUNAME_MACHINE_ARCH=`arch | sed 's/Bitrig.//'`\n\techo ${UNAME_MACHINE_ARCH}-unknown-bitrig${UNAME_RELEASE}\n\texit ;;\n    *:OpenBSD:*:*)\n\tUNAME_MACHINE_ARCH=`arch | sed 's/OpenBSD.//'`\n\techo ${UNAME_MACHINE_ARCH}-unknown-openbsd${UNAME_RELEASE}\n\texit ;;\n    *:ekkoBSD:*:*)\n\techo ${UNAME_MACHINE}-unknown-ekkobsd${UNAME_RELEASE}\n\texit ;;\n    *:SolidBSD:*:*)\n\techo ${UNAME_MACHINE}-unknown-solidbsd${UNAME_RELEASE}\n\texit ;;\n    macppc:MirBSD:*:*)\n\techo powerpc-unknown-mirbsd${UNAME_RELEASE}\n\texit ;;\n    *:MirBSD:*:*)\n\techo ${UNAME_MACHINE}-unknown-mirbsd${UNAME_RELEASE}\n\texit ;;\n    alpha:OSF1:*:*)\n\tcase $UNAME_RELEASE in\n\t*4.0)\n\t\tUNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $3}'`\n\t\t;;\n\t*5.*)\n\t\tUNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $4}'`\n\t\t;;\n\tesac\n\t# According to Compaq, /usr/sbin/psrinfo has been available on\n\t# OSF/1 and Tru64 systems produced since 1995.  I hope that\n\t# covers most systems running today.  This code pipes the CPU\n\t# types through head -n 1, so we only detect the type of CPU 0.\n\tALPHA_CPU_TYPE=`/usr/sbin/psrinfo -v | sed -n -e 's/^  The alpha \\(.*\\) processor.*$/\\1/p' | head -n 1`\n\tcase \"$ALPHA_CPU_TYPE\" in\n\t    \"EV4 (21064)\")\n\t\tUNAME_MACHINE=\"alpha\" ;;\n\t    \"EV4.5 (21064)\")\n\t\tUNAME_MACHINE=\"alpha\" ;;\n\t    \"LCA4 (21066/21068)\")\n\t\tUNAME_MACHINE=\"alpha\" ;;\n\t    \"EV5 (21164)\")\n\t\tUNAME_MACHINE=\"alphaev5\" ;;\n\t    \"EV5.6 (21164A)\")\n\t\tUNAME_MACHINE=\"alphaev56\" ;;\n\t    \"EV5.6 (21164PC)\")\n\t\tUNAME_MACHINE=\"alphapca56\" ;;\n\t    \"EV5.7 (21164PC)\")\n\t\tUNAME_MACHINE=\"alphapca57\" ;;\n\t    \"EV6 (21264)\")\n\t\tUNAME_MACHINE=\"alphaev6\" ;;\n\t    \"EV6.7 (21264A)\")\n\t\tUNAME_MACHINE=\"alphaev67\" ;;\n\t    \"EV6.8CB (21264C)\")\n\t\tUNAME_MACHINE=\"alphaev68\" ;;\n\t    \"EV6.8AL (21264B)\")\n\t\tUNAME_MACHINE=\"alphaev68\" ;;\n\t    \"EV6.8CX (21264D)\")\n\t\tUNAME_MACHINE=\"alphaev68\" ;;\n\t    \"EV6.9A (21264/EV69A)\")\n\t\tUNAME_MACHINE=\"alphaev69\" ;;\n\t    \"EV7 (21364)\")\n\t\tUNAME_MACHINE=\"alphaev7\" ;;\n\t    \"EV7.9 (21364A)\")\n\t\tUNAME_MACHINE=\"alphaev79\" ;;\n\tesac\n\t# A Pn.n version is a patched version.\n\t# A Vn.n version is a released version.\n\t# A Tn.n version is a released field test version.\n\t# A Xn.n version is an unreleased experimental baselevel.\n\t# 1.2 uses \"1.2\" for uname -r.\n\techo ${UNAME_MACHINE}-dec-osf`echo ${UNAME_RELEASE} | sed -e 's/^[PVTX]//' | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'`\n\t# Reset EXIT trap before exiting to avoid spurious non-zero exit code.\n\texitcode=$?\n\ttrap '' 0\n\texit $exitcode ;;\n    Alpha\\ *:Windows_NT*:*)\n\t# How do we know it's Interix rather than the generic POSIX subsystem?\n\t# Should we change UNAME_MACHINE based on the output of uname instead\n\t# of the specific Alpha model?\n\techo alpha-pc-interix\n\texit ;;\n    21064:Windows_NT:50:3)\n\techo alpha-dec-winnt3.5\n\texit ;;\n    Amiga*:UNIX_System_V:4.0:*)\n\techo m68k-unknown-sysv4\n\texit ;;\n    *:[Aa]miga[Oo][Ss]:*:*)\n\techo ${UNAME_MACHINE}-unknown-amigaos\n\texit ;;\n    *:[Mm]orph[Oo][Ss]:*:*)\n\techo ${UNAME_MACHINE}-unknown-morphos\n\texit ;;\n    *:OS/390:*:*)\n\techo i370-ibm-openedition\n\texit ;;\n    *:z/VM:*:*)\n\techo s390-ibm-zvmoe\n\texit ;;\n    *:OS400:*:*)\n\techo powerpc-ibm-os400\n\texit ;;\n    arm:RISC*:1.[012]*:*|arm:riscix:1.[012]*:*)\n\techo arm-acorn-riscix${UNAME_RELEASE}\n\texit ;;\n    arm*:riscos:*:*|arm*:RISCOS:*:*)\n\techo arm-unknown-riscos\n\texit ;;\n    SR2?01:HI-UX/MPP:*:* | SR8000:HI-UX/MPP:*:*)\n\techo hppa1.1-hitachi-hiuxmpp\n\texit ;;\n    Pyramid*:OSx*:*:* | MIS*:OSx*:*:* | MIS*:SMP_DC-OSx*:*:*)\n\t# akee@wpdis03.wpafb.af.mil (Earle F. Ake) contributed MIS and NILE.\n\tif test \"`(/bin/universe) 2>/dev/null`\" = att ; then\n\t\techo pyramid-pyramid-sysv3\n\telse\n\t\techo pyramid-pyramid-bsd\n\tfi\n\texit ;;\n    NILE*:*:*:dcosx)\n\techo pyramid-pyramid-svr4\n\texit ;;\n    DRS?6000:unix:4.0:6*)\n\techo sparc-icl-nx6\n\texit ;;\n    DRS?6000:UNIX_SV:4.2*:7* | DRS?6000:isis:4.2*:7*)\n\tcase `/usr/bin/uname -p` in\n\t    sparc) echo sparc-icl-nx7; exit ;;\n\tesac ;;\n    s390x:SunOS:*:*)\n\techo ${UNAME_MACHINE}-ibm-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`\n\texit ;;\n    sun4H:SunOS:5.*:*)\n\techo sparc-hal-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`\n\texit ;;\n    sun4*:SunOS:5.*:* | tadpole*:SunOS:5.*:*)\n\techo sparc-sun-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`\n\texit ;;\n    i86pc:AuroraUX:5.*:* | i86xen:AuroraUX:5.*:*)\n\techo i386-pc-auroraux${UNAME_RELEASE}\n\texit ;;\n    i86pc:SunOS:5.*:* | i86xen:SunOS:5.*:*)\n\teval $set_cc_for_build\n\tSUN_ARCH=\"i386\"\n\t# If there is a compiler, see if it is configured for 64-bit objects.\n\t# Note that the Sun cc does not turn __LP64__ into 1 like gcc does.\n\t# This test works for both compilers.\n\tif [ \"$CC_FOR_BUILD\" != 'no_compiler_found' ]; then\n\t    if (echo '#ifdef __amd64'; echo IS_64BIT_ARCH; echo '#endif') | \\\n\t\t(CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) | \\\n\t\tgrep IS_64BIT_ARCH >/dev/null\n\t    then\n\t\tSUN_ARCH=\"x86_64\"\n\t    fi\n\tfi\n\techo ${SUN_ARCH}-pc-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`\n\texit ;;\n    sun4*:SunOS:6*:*)\n\t# According to config.sub, this is the proper way to canonicalize\n\t# SunOS6.  Hard to guess exactly what SunOS6 will be like, but\n\t# it's likely to be more like Solaris than SunOS4.\n\techo sparc-sun-solaris3`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`\n\texit ;;\n    sun4*:SunOS:*:*)\n\tcase \"`/usr/bin/arch -k`\" in\n\t    Series*|S4*)\n\t\tUNAME_RELEASE=`uname -v`\n\t\t;;\n\tesac\n\t# Japanese Language versions have a version number like `4.1.3-JL'.\n\techo sparc-sun-sunos`echo ${UNAME_RELEASE}|sed -e 's/-/_/'`\n\texit ;;\n    sun3*:SunOS:*:*)\n\techo m68k-sun-sunos${UNAME_RELEASE}\n\texit ;;\n    sun*:*:4.2BSD:*)\n\tUNAME_RELEASE=`(sed 1q /etc/motd | awk '{print substr($5,1,3)}') 2>/dev/null`\n\ttest \"x${UNAME_RELEASE}\" = \"x\" && UNAME_RELEASE=3\n\tcase \"`/bin/arch`\" in\n\t    sun3)\n\t\techo m68k-sun-sunos${UNAME_RELEASE}\n\t\t;;\n\t    sun4)\n\t\techo sparc-sun-sunos${UNAME_RELEASE}\n\t\t;;\n\tesac\n\texit ;;\n    aushp:SunOS:*:*)\n\techo sparc-auspex-sunos${UNAME_RELEASE}\n\texit ;;\n    # The situation for MiNT is a little confusing.  The machine name\n    # can be virtually everything (everything which is not\n    # \"atarist\" or \"atariste\" at least should have a processor\n    # > m68000).  The system name ranges from \"MiNT\" over \"FreeMiNT\"\n    # to the lowercase version \"mint\" (or \"freemint\").  Finally\n    # the system name \"TOS\" denotes a system which is actually not\n    # MiNT.  But MiNT is downward compatible to TOS, so this should\n    # be no problem.\n    atarist[e]:*MiNT:*:* | atarist[e]:*mint:*:* | atarist[e]:*TOS:*:*)\n\techo m68k-atari-mint${UNAME_RELEASE}\n\texit ;;\n    atari*:*MiNT:*:* | atari*:*mint:*:* | atarist[e]:*TOS:*:*)\n\techo m68k-atari-mint${UNAME_RELEASE}\n\texit ;;\n    *falcon*:*MiNT:*:* | *falcon*:*mint:*:* | *falcon*:*TOS:*:*)\n\techo m68k-atari-mint${UNAME_RELEASE}\n\texit ;;\n    milan*:*MiNT:*:* | milan*:*mint:*:* | *milan*:*TOS:*:*)\n\techo m68k-milan-mint${UNAME_RELEASE}\n\texit ;;\n    hades*:*MiNT:*:* | hades*:*mint:*:* | *hades*:*TOS:*:*)\n\techo m68k-hades-mint${UNAME_RELEASE}\n\texit ;;\n    *:*MiNT:*:* | *:*mint:*:* | *:*TOS:*:*)\n\techo m68k-unknown-mint${UNAME_RELEASE}\n\texit ;;\n    m68k:machten:*:*)\n\techo m68k-apple-machten${UNAME_RELEASE}\n\texit ;;\n    powerpc:machten:*:*)\n\techo powerpc-apple-machten${UNAME_RELEASE}\n\texit ;;\n    RISC*:Mach:*:*)\n\techo mips-dec-mach_bsd4.3\n\texit ;;\n    RISC*:ULTRIX:*:*)\n\techo mips-dec-ultrix${UNAME_RELEASE}\n\texit ;;\n    VAX*:ULTRIX*:*:*)\n\techo vax-dec-ultrix${UNAME_RELEASE}\n\texit ;;\n    2020:CLIX:*:* | 2430:CLIX:*:*)\n\techo clipper-intergraph-clix${UNAME_RELEASE}\n\texit ;;\n    mips:*:*:UMIPS | mips:*:*:RISCos)\n\teval $set_cc_for_build\n\tsed 's/^\t//' << EOF >$dummy.c\n#ifdef __cplusplus\n#include <stdio.h>  /* for printf() prototype */\n\tint main (int argc, char *argv[]) {\n#else\n\tint main (argc, argv) int argc; char *argv[]; {\n#endif\n\t#if defined (host_mips) && defined (MIPSEB)\n\t#if defined (SYSTYPE_SYSV)\n\t  printf (\"mips-mips-riscos%ssysv\\n\", argv[1]); exit (0);\n\t#endif\n\t#if defined (SYSTYPE_SVR4)\n\t  printf (\"mips-mips-riscos%ssvr4\\n\", argv[1]); exit (0);\n\t#endif\n\t#if defined (SYSTYPE_BSD43) || defined(SYSTYPE_BSD)\n\t  printf (\"mips-mips-riscos%sbsd\\n\", argv[1]); exit (0);\n\t#endif\n\t#endif\n\t  exit (-1);\n\t}\nEOF\n\t$CC_FOR_BUILD -o $dummy $dummy.c &&\n\t  dummyarg=`echo \"${UNAME_RELEASE}\" | sed -n 's/\\([0-9]*\\).*/\\1/p'` &&\n\t  SYSTEM_NAME=`$dummy $dummyarg` &&\n\t    { echo \"$SYSTEM_NAME\"; exit; }\n\techo mips-mips-riscos${UNAME_RELEASE}\n\texit ;;\n    Motorola:PowerMAX_OS:*:*)\n\techo powerpc-motorola-powermax\n\texit ;;\n    Motorola:*:4.3:PL8-*)\n\techo powerpc-harris-powermax\n\texit ;;\n    Night_Hawk:*:*:PowerMAX_OS | Synergy:PowerMAX_OS:*:*)\n\techo powerpc-harris-powermax\n\texit ;;\n    Night_Hawk:Power_UNIX:*:*)\n\techo powerpc-harris-powerunix\n\texit ;;\n    m88k:CX/UX:7*:*)\n\techo m88k-harris-cxux7\n\texit ;;\n    m88k:*:4*:R4*)\n\techo m88k-motorola-sysv4\n\texit ;;\n    m88k:*:3*:R3*)\n\techo m88k-motorola-sysv3\n\texit ;;\n    AViiON:dgux:*:*)\n\t# DG/UX returns AViiON for all architectures\n\tUNAME_PROCESSOR=`/usr/bin/uname -p`\n\tif [ $UNAME_PROCESSOR = mc88100 ] || [ $UNAME_PROCESSOR = mc88110 ]\n\tthen\n\t    if [ ${TARGET_BINARY_INTERFACE}x = m88kdguxelfx ] || \\\n\t       [ ${TARGET_BINARY_INTERFACE}x = x ]\n\t    then\n\t\techo m88k-dg-dgux${UNAME_RELEASE}\n\t    else\n\t\techo m88k-dg-dguxbcs${UNAME_RELEASE}\n\t    fi\n\telse\n\t    echo i586-dg-dgux${UNAME_RELEASE}\n\tfi\n\texit ;;\n    M88*:DolphinOS:*:*)\t# DolphinOS (SVR3)\n\techo m88k-dolphin-sysv3\n\texit ;;\n    M88*:*:R3*:*)\n\t# Delta 88k system running SVR3\n\techo m88k-motorola-sysv3\n\texit ;;\n    XD88*:*:*:*) # Tektronix XD88 system running UTekV (SVR3)\n\techo m88k-tektronix-sysv3\n\texit ;;\n    Tek43[0-9][0-9]:UTek:*:*) # Tektronix 4300 system running UTek (BSD)\n\techo m68k-tektronix-bsd\n\texit ;;\n    *:IRIX*:*:*)\n\techo mips-sgi-irix`echo ${UNAME_RELEASE}|sed -e 's/-/_/g'`\n\texit ;;\n    ????????:AIX?:[12].1:2)   # AIX 2.2.1 or AIX 2.1.1 is RT/PC AIX.\n\techo romp-ibm-aix     # uname -m gives an 8 hex-code CPU id\n\texit ;;               # Note that: echo \"'`uname -s`'\" gives 'AIX '\n    i*86:AIX:*:*)\n\techo i386-ibm-aix\n\texit ;;\n    ia64:AIX:*:*)\n\tif [ -x /usr/bin/oslevel ] ; then\n\t\tIBM_REV=`/usr/bin/oslevel`\n\telse\n\t\tIBM_REV=${UNAME_VERSION}.${UNAME_RELEASE}\n\tfi\n\techo ${UNAME_MACHINE}-ibm-aix${IBM_REV}\n\texit ;;\n    *:AIX:2:3)\n\tif grep bos325 /usr/include/stdio.h >/dev/null 2>&1; then\n\t\teval $set_cc_for_build\n\t\tsed 's/^\t\t//' << EOF >$dummy.c\n\t\t#include <sys/systemcfg.h>\n\n\t\tmain()\n\t\t\t{\n\t\t\tif (!__power_pc())\n\t\t\t\texit(1);\n\t\t\tputs(\"powerpc-ibm-aix3.2.5\");\n\t\t\texit(0);\n\t\t\t}\nEOF\n\t\tif $CC_FOR_BUILD -o $dummy $dummy.c && SYSTEM_NAME=`$dummy`\n\t\tthen\n\t\t\techo \"$SYSTEM_NAME\"\n\t\telse\n\t\t\techo rs6000-ibm-aix3.2.5\n\t\tfi\n\telif grep bos324 /usr/include/stdio.h >/dev/null 2>&1; then\n\t\techo rs6000-ibm-aix3.2.4\n\telse\n\t\techo rs6000-ibm-aix3.2\n\tfi\n\texit ;;\n    *:AIX:*:[4567])\n\tIBM_CPU_ID=`/usr/sbin/lsdev -C -c processor -S available | sed 1q | awk '{ print $1 }'`\n\tif /usr/sbin/lsattr -El ${IBM_CPU_ID} | grep ' POWER' >/dev/null 2>&1; then\n\t\tIBM_ARCH=rs6000\n\telse\n\t\tIBM_ARCH=powerpc\n\tfi\n\tif [ -x /usr/bin/oslevel ] ; then\n\t\tIBM_REV=`/usr/bin/oslevel`\n\telse\n\t\tIBM_REV=${UNAME_VERSION}.${UNAME_RELEASE}\n\tfi\n\techo ${IBM_ARCH}-ibm-aix${IBM_REV}\n\texit ;;\n    *:AIX:*:*)\n\techo rs6000-ibm-aix\n\texit ;;\n    ibmrt:4.4BSD:*|romp-ibm:BSD:*)\n\techo romp-ibm-bsd4.4\n\texit ;;\n    ibmrt:*BSD:*|romp-ibm:BSD:*)            # covers RT/PC BSD and\n\techo romp-ibm-bsd${UNAME_RELEASE}   # 4.3 with uname added to\n\texit ;;                             # report: romp-ibm BSD 4.3\n    *:BOSX:*:*)\n\techo rs6000-bull-bosx\n\texit ;;\n    DPX/2?00:B.O.S.:*:*)\n\techo m68k-bull-sysv3\n\texit ;;\n    9000/[34]??:4.3bsd:1.*:*)\n\techo m68k-hp-bsd\n\texit ;;\n    hp300:4.4BSD:*:* | 9000/[34]??:4.3bsd:2.*:*)\n\techo m68k-hp-bsd4.4\n\texit ;;\n    9000/[34678]??:HP-UX:*:*)\n\tHPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'`\n\tcase \"${UNAME_MACHINE}\" in\n\t    9000/31? )            HP_ARCH=m68000 ;;\n\t    9000/[34]?? )         HP_ARCH=m68k ;;\n\t    9000/[678][0-9][0-9])\n\t\tif [ -x /usr/bin/getconf ]; then\n\t\t    sc_cpu_version=`/usr/bin/getconf SC_CPU_VERSION 2>/dev/null`\n\t\t    sc_kernel_bits=`/usr/bin/getconf SC_KERNEL_BITS 2>/dev/null`\n\t\t    case \"${sc_cpu_version}\" in\n\t\t      523) HP_ARCH=\"hppa1.0\" ;; # CPU_PA_RISC1_0\n\t\t      528) HP_ARCH=\"hppa1.1\" ;; # CPU_PA_RISC1_1\n\t\t      532)                      # CPU_PA_RISC2_0\n\t\t\tcase \"${sc_kernel_bits}\" in\n\t\t\t  32) HP_ARCH=\"hppa2.0n\" ;;\n\t\t\t  64) HP_ARCH=\"hppa2.0w\" ;;\n\t\t\t  '') HP_ARCH=\"hppa2.0\" ;;   # HP-UX 10.20\n\t\t\tesac ;;\n\t\t    esac\n\t\tfi\n\t\tif [ \"${HP_ARCH}\" = \"\" ]; then\n\t\t    eval $set_cc_for_build\n\t\t    sed 's/^\t\t//' << EOF >$dummy.c\n\n\t\t#define _HPUX_SOURCE\n\t\t#include <stdlib.h>\n\t\t#include <unistd.h>\n\n\t\tint main ()\n\t\t{\n\t\t#if defined(_SC_KERNEL_BITS)\n\t\t    long bits = sysconf(_SC_KERNEL_BITS);\n\t\t#endif\n\t\t    long cpu  = sysconf (_SC_CPU_VERSION);\n\n\t\t    switch (cpu)\n\t\t\t{\n\t\t\tcase CPU_PA_RISC1_0: puts (\"hppa1.0\"); break;\n\t\t\tcase CPU_PA_RISC1_1: puts (\"hppa1.1\"); break;\n\t\t\tcase CPU_PA_RISC2_0:\n\t\t#if defined(_SC_KERNEL_BITS)\n\t\t\t    switch (bits)\n\t\t\t\t{\n\t\t\t\tcase 64: puts (\"hppa2.0w\"); break;\n\t\t\t\tcase 32: puts (\"hppa2.0n\"); break;\n\t\t\t\tdefault: puts (\"hppa2.0\"); break;\n\t\t\t\t} break;\n\t\t#else  /* !defined(_SC_KERNEL_BITS) */\n\t\t\t    puts (\"hppa2.0\"); break;\n\t\t#endif\n\t\t\tdefault: puts (\"hppa1.0\"); break;\n\t\t\t}\n\t\t    exit (0);\n\t\t}\nEOF\n\t\t    (CCOPTS= $CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null) && HP_ARCH=`$dummy`\n\t\t    test -z \"$HP_ARCH\" && HP_ARCH=hppa\n\t\tfi ;;\n\tesac\n\tif [ ${HP_ARCH} = \"hppa2.0w\" ]\n\tthen\n\t    eval $set_cc_for_build\n\n\t    # hppa2.0w-hp-hpux* has a 64-bit kernel and a compiler generating\n\t    # 32-bit code.  hppa64-hp-hpux* has the same kernel and a compiler\n\t    # generating 64-bit code.  GNU and HP use different nomenclature:\n\t    #\n\t    # $ CC_FOR_BUILD=cc ./config.guess\n\t    # => hppa2.0w-hp-hpux11.23\n\t    # $ CC_FOR_BUILD=\"cc +DA2.0w\" ./config.guess\n\t    # => hppa64-hp-hpux11.23\n\n\t    if echo __LP64__ | (CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) |\n\t\tgrep -q __LP64__\n\t    then\n\t\tHP_ARCH=\"hppa2.0w\"\n\t    else\n\t\tHP_ARCH=\"hppa64\"\n\t    fi\n\tfi\n\techo ${HP_ARCH}-hp-hpux${HPUX_REV}\n\texit ;;\n    ia64:HP-UX:*:*)\n\tHPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'`\n\techo ia64-hp-hpux${HPUX_REV}\n\texit ;;\n    3050*:HI-UX:*:*)\n\teval $set_cc_for_build\n\tsed 's/^\t//' << EOF >$dummy.c\n\t#include <unistd.h>\n\tint\n\tmain ()\n\t{\n\t  long cpu = sysconf (_SC_CPU_VERSION);\n\t  /* The order matters, because CPU_IS_HP_MC68K erroneously returns\n\t     true for CPU_PA_RISC1_0.  CPU_IS_PA_RISC returns correct\n\t     results, however.  */\n\t  if (CPU_IS_PA_RISC (cpu))\n\t    {\n\t      switch (cpu)\n\t\t{\n\t\t  case CPU_PA_RISC1_0: puts (\"hppa1.0-hitachi-hiuxwe2\"); break;\n\t\t  case CPU_PA_RISC1_1: puts (\"hppa1.1-hitachi-hiuxwe2\"); break;\n\t\t  case CPU_PA_RISC2_0: puts (\"hppa2.0-hitachi-hiuxwe2\"); break;\n\t\t  default: puts (\"hppa-hitachi-hiuxwe2\"); break;\n\t\t}\n\t    }\n\t  else if (CPU_IS_HP_MC68K (cpu))\n\t    puts (\"m68k-hitachi-hiuxwe2\");\n\t  else puts (\"unknown-hitachi-hiuxwe2\");\n\t  exit (0);\n\t}\nEOF\n\t$CC_FOR_BUILD -o $dummy $dummy.c && SYSTEM_NAME=`$dummy` &&\n\t\t{ echo \"$SYSTEM_NAME\"; exit; }\n\techo unknown-hitachi-hiuxwe2\n\texit ;;\n    9000/7??:4.3bsd:*:* | 9000/8?[79]:4.3bsd:*:* )\n\techo hppa1.1-hp-bsd\n\texit ;;\n    9000/8??:4.3bsd:*:*)\n\techo hppa1.0-hp-bsd\n\texit ;;\n    *9??*:MPE/iX:*:* | *3000*:MPE/iX:*:*)\n\techo hppa1.0-hp-mpeix\n\texit ;;\n    hp7??:OSF1:*:* | hp8?[79]:OSF1:*:* )\n\techo hppa1.1-hp-osf\n\texit ;;\n    hp8??:OSF1:*:*)\n\techo hppa1.0-hp-osf\n\texit ;;\n    i*86:OSF1:*:*)\n\tif [ -x /usr/sbin/sysversion ] ; then\n\t    echo ${UNAME_MACHINE}-unknown-osf1mk\n\telse\n\t    echo ${UNAME_MACHINE}-unknown-osf1\n\tfi\n\texit ;;\n    parisc*:Lites*:*:*)\n\techo hppa1.1-hp-lites\n\texit ;;\n    C1*:ConvexOS:*:* | convex:ConvexOS:C1*:*)\n\techo c1-convex-bsd\n\texit ;;\n    C2*:ConvexOS:*:* | convex:ConvexOS:C2*:*)\n\tif getsysinfo -f scalar_acc\n\tthen echo c32-convex-bsd\n\telse echo c2-convex-bsd\n\tfi\n\texit ;;\n    C34*:ConvexOS:*:* | convex:ConvexOS:C34*:*)\n\techo c34-convex-bsd\n\texit ;;\n    C38*:ConvexOS:*:* | convex:ConvexOS:C38*:*)\n\techo c38-convex-bsd\n\texit ;;\n    C4*:ConvexOS:*:* | convex:ConvexOS:C4*:*)\n\techo c4-convex-bsd\n\texit ;;\n    CRAY*Y-MP:*:*:*)\n\techo ymp-cray-unicos${UNAME_RELEASE} | sed -e 's/\\.[^.]*$/.X/'\n\texit ;;\n    CRAY*[A-Z]90:*:*:*)\n\techo ${UNAME_MACHINE}-cray-unicos${UNAME_RELEASE} \\\n\t| sed -e 's/CRAY.*\\([A-Z]90\\)/\\1/' \\\n\t      -e y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/ \\\n\t      -e 's/\\.[^.]*$/.X/'\n\texit ;;\n    CRAY*TS:*:*:*)\n\techo t90-cray-unicos${UNAME_RELEASE} | sed -e 's/\\.[^.]*$/.X/'\n\texit ;;\n    CRAY*T3E:*:*:*)\n\techo alphaev5-cray-unicosmk${UNAME_RELEASE} | sed -e 's/\\.[^.]*$/.X/'\n\texit ;;\n    CRAY*SV1:*:*:*)\n\techo sv1-cray-unicos${UNAME_RELEASE} | sed -e 's/\\.[^.]*$/.X/'\n\texit ;;\n    *:UNICOS/mp:*:*)\n\techo craynv-cray-unicosmp${UNAME_RELEASE} | sed -e 's/\\.[^.]*$/.X/'\n\texit ;;\n    F30[01]:UNIX_System_V:*:* | F700:UNIX_System_V:*:*)\n\tFUJITSU_PROC=`uname -m | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'`\n\tFUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\\///'`\n\tFUJITSU_REL=`echo ${UNAME_RELEASE} | sed -e 's/ /_/'`\n\techo \"${FUJITSU_PROC}-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}\"\n\texit ;;\n    5000:UNIX_System_V:4.*:*)\n\tFUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\\///'`\n\tFUJITSU_REL=`echo ${UNAME_RELEASE} | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/ /_/'`\n\techo \"sparc-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}\"\n\texit ;;\n    i*86:BSD/386:*:* | i*86:BSD/OS:*:* | *:Ascend\\ Embedded/OS:*:*)\n\techo ${UNAME_MACHINE}-pc-bsdi${UNAME_RELEASE}\n\texit ;;\n    sparc*:BSD/OS:*:*)\n\techo sparc-unknown-bsdi${UNAME_RELEASE}\n\texit ;;\n    *:BSD/OS:*:*)\n\techo ${UNAME_MACHINE}-unknown-bsdi${UNAME_RELEASE}\n\texit ;;\n    *:FreeBSD:*:*)\n\tUNAME_PROCESSOR=`/usr/bin/uname -p`\n\tcase ${UNAME_PROCESSOR} in\n\t    amd64)\n\t\techo x86_64-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;;\n\t    *)\n\t\techo ${UNAME_PROCESSOR}-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;;\n\tesac\n\texit ;;\n    i*:CYGWIN*:*)\n\techo ${UNAME_MACHINE}-pc-cygwin\n\texit ;;\n    *:MINGW64*:*)\n\techo ${UNAME_MACHINE}-pc-mingw64\n\texit ;;\n    *:MINGW*:*)\n\techo ${UNAME_MACHINE}-pc-mingw32\n\texit ;;\n    *:MSYS*:*)\n\techo ${UNAME_MACHINE}-pc-msys\n\texit ;;\n    i*:windows32*:*)\n\t# uname -m includes \"-pc\" on this system.\n\techo ${UNAME_MACHINE}-mingw32\n\texit ;;\n    i*:PW*:*)\n\techo ${UNAME_MACHINE}-pc-pw32\n\texit ;;\n    *:Interix*:*)\n\tcase ${UNAME_MACHINE} in\n\t    x86)\n\t\techo i586-pc-interix${UNAME_RELEASE}\n\t\texit ;;\n\t    authenticamd | genuineintel | EM64T)\n\t\techo x86_64-unknown-interix${UNAME_RELEASE}\n\t\texit ;;\n\t    IA64)\n\t\techo ia64-unknown-interix${UNAME_RELEASE}\n\t\texit ;;\n\tesac ;;\n    [345]86:Windows_95:* | [345]86:Windows_98:* | [345]86:Windows_NT:*)\n\techo i${UNAME_MACHINE}-pc-mks\n\texit ;;\n    8664:Windows_NT:*)\n\techo x86_64-pc-mks\n\texit ;;\n    i*:Windows_NT*:* | Pentium*:Windows_NT*:*)\n\t# How do we know it's Interix rather than the generic POSIX subsystem?\n\t# It also conflicts with pre-2.0 versions of AT&T UWIN. Should we\n\t# UNAME_MACHINE based on the output of uname instead of i386?\n\techo i586-pc-interix\n\texit ;;\n    i*:UWIN*:*)\n\techo ${UNAME_MACHINE}-pc-uwin\n\texit ;;\n    amd64:CYGWIN*:*:* | x86_64:CYGWIN*:*:*)\n\techo x86_64-unknown-cygwin\n\texit ;;\n    p*:CYGWIN*:*)\n\techo powerpcle-unknown-cygwin\n\texit ;;\n    prep*:SunOS:5.*:*)\n\techo powerpcle-unknown-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`\n\texit ;;\n    *:GNU:*:*)\n\t# the GNU system\n\techo `echo ${UNAME_MACHINE}|sed -e 's,[-/].*$,,'`-unknown-${LIBC}`echo ${UNAME_RELEASE}|sed -e 's,/.*$,,'`\n\texit ;;\n    *:GNU/*:*:*)\n\t# other systems with GNU libc and userland\n\techo ${UNAME_MACHINE}-unknown-`echo ${UNAME_SYSTEM} | sed 's,^[^/]*/,,' | tr '[A-Z]' '[a-z]'``echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`-${LIBC}\n\texit ;;\n    i*86:Minix:*:*)\n\techo ${UNAME_MACHINE}-pc-minix\n\texit ;;\n    aarch64:Linux:*:*)\n\techo ${UNAME_MACHINE}-unknown-linux-${LIBC}\n\texit ;;\n    aarch64_be:Linux:*:*)\n\tUNAME_MACHINE=aarch64_be\n\techo ${UNAME_MACHINE}-unknown-linux-${LIBC}\n\texit ;;\n    alpha:Linux:*:*)\n\tcase `sed -n '/^cpu model/s/^.*: \\(.*\\)/\\1/p' < /proc/cpuinfo` in\n\t  EV5)   UNAME_MACHINE=alphaev5 ;;\n\t  EV56)  UNAME_MACHINE=alphaev56 ;;\n\t  PCA56) UNAME_MACHINE=alphapca56 ;;\n\t  PCA57) UNAME_MACHINE=alphapca56 ;;\n\t  EV6)   UNAME_MACHINE=alphaev6 ;;\n\t  EV67)  UNAME_MACHINE=alphaev67 ;;\n\t  EV68*) UNAME_MACHINE=alphaev68 ;;\n\tesac\n\tobjdump --private-headers /bin/sh | grep -q ld.so.1\n\tif test \"$?\" = 0 ; then LIBC=\"gnulibc1\" ; fi\n\techo ${UNAME_MACHINE}-unknown-linux-${LIBC}\n\texit ;;\n    arc:Linux:*:* | arceb:Linux:*:*)\n\techo ${UNAME_MACHINE}-unknown-linux-${LIBC}\n\texit ;;\n    arm*:Linux:*:*)\n\teval $set_cc_for_build\n\tif echo __ARM_EABI__ | $CC_FOR_BUILD -E - 2>/dev/null \\\n\t    | grep -q __ARM_EABI__\n\tthen\n\t    echo ${UNAME_MACHINE}-unknown-linux-${LIBC}\n\telse\n\t    if echo __ARM_PCS_VFP | $CC_FOR_BUILD -E - 2>/dev/null \\\n\t\t| grep -q __ARM_PCS_VFP\n\t    then\n\t\techo ${UNAME_MACHINE}-unknown-linux-${LIBC}eabi\n\t    else\n\t\techo ${UNAME_MACHINE}-unknown-linux-${LIBC}eabihf\n\t    fi\n\tfi\n\texit ;;\n    avr32*:Linux:*:*)\n\techo ${UNAME_MACHINE}-unknown-linux-${LIBC}\n\texit ;;\n    cris:Linux:*:*)\n\techo ${UNAME_MACHINE}-axis-linux-${LIBC}\n\texit ;;\n    crisv32:Linux:*:*)\n\techo ${UNAME_MACHINE}-axis-linux-${LIBC}\n\texit ;;\n    frv:Linux:*:*)\n\techo ${UNAME_MACHINE}-unknown-linux-${LIBC}\n\texit ;;\n    hexagon:Linux:*:*)\n\techo ${UNAME_MACHINE}-unknown-linux-${LIBC}\n\texit ;;\n    i*86:Linux:*:*)\n\techo ${UNAME_MACHINE}-pc-linux-${LIBC}\n\texit ;;\n    ia64:Linux:*:*)\n\techo ${UNAME_MACHINE}-unknown-linux-${LIBC}\n\texit ;;\n    m32r*:Linux:*:*)\n\techo ${UNAME_MACHINE}-unknown-linux-${LIBC}\n\texit ;;\n    m68*:Linux:*:*)\n\techo ${UNAME_MACHINE}-unknown-linux-${LIBC}\n\texit ;;\n    mips:Linux:*:* | mips64:Linux:*:*)\n\teval $set_cc_for_build\n\tsed 's/^\t//' << EOF >$dummy.c\n\t#undef CPU\n\t#undef ${UNAME_MACHINE}\n\t#undef ${UNAME_MACHINE}el\n\t#if defined(__MIPSEL__) || defined(__MIPSEL) || defined(_MIPSEL) || defined(MIPSEL)\n\tCPU=${UNAME_MACHINE}el\n\t#else\n\t#if defined(__MIPSEB__) || defined(__MIPSEB) || defined(_MIPSEB) || defined(MIPSEB)\n\tCPU=${UNAME_MACHINE}\n\t#else\n\tCPU=\n\t#endif\n\t#endif\nEOF\n\teval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep '^CPU'`\n\ttest x\"${CPU}\" != x && { echo \"${CPU}-unknown-linux-${LIBC}\"; exit; }\n\t;;\n    openrisc*:Linux:*:*)\n\techo or1k-unknown-linux-${LIBC}\n\texit ;;\n    or32:Linux:*:* | or1k*:Linux:*:*)\n\techo ${UNAME_MACHINE}-unknown-linux-${LIBC}\n\texit ;;\n    padre:Linux:*:*)\n\techo sparc-unknown-linux-${LIBC}\n\texit ;;\n    parisc64:Linux:*:* | hppa64:Linux:*:*)\n\techo hppa64-unknown-linux-${LIBC}\n\texit ;;\n    parisc:Linux:*:* | hppa:Linux:*:*)\n\t# Look for CPU level\n\tcase `grep '^cpu[^a-z]*:' /proc/cpuinfo 2>/dev/null | cut -d' ' -f2` in\n\t  PA7*) echo hppa1.1-unknown-linux-${LIBC} ;;\n\t  PA8*) echo hppa2.0-unknown-linux-${LIBC} ;;\n\t  *)    echo hppa-unknown-linux-${LIBC} ;;\n\tesac\n\texit ;;\n    ppc64:Linux:*:*)\n\techo powerpc64-unknown-linux-${LIBC}\n\texit ;;\n    ppc:Linux:*:*)\n\techo powerpc-unknown-linux-${LIBC}\n\texit ;;\n    ppc64le:Linux:*:*)\n\techo powerpc64le-unknown-linux-${LIBC}\n\texit ;;\n    ppcle:Linux:*:*)\n\techo powerpcle-unknown-linux-${LIBC}\n\texit ;;\n    s390:Linux:*:* | s390x:Linux:*:*)\n\techo ${UNAME_MACHINE}-ibm-linux-${LIBC}\n\texit ;;\n    sh64*:Linux:*:*)\n\techo ${UNAME_MACHINE}-unknown-linux-${LIBC}\n\texit ;;\n    sh*:Linux:*:*)\n\techo ${UNAME_MACHINE}-unknown-linux-${LIBC}\n\texit ;;\n    sparc:Linux:*:* | sparc64:Linux:*:*)\n\techo ${UNAME_MACHINE}-unknown-linux-${LIBC}\n\texit ;;\n    tile*:Linux:*:*)\n\techo ${UNAME_MACHINE}-unknown-linux-${LIBC}\n\texit ;;\n    vax:Linux:*:*)\n\techo ${UNAME_MACHINE}-dec-linux-${LIBC}\n\texit ;;\n    x86_64:Linux:*:*)\n\techo ${UNAME_MACHINE}-unknown-linux-${LIBC}\n\texit ;;\n    xtensa*:Linux:*:*)\n\techo ${UNAME_MACHINE}-unknown-linux-${LIBC}\n\texit ;;\n    i*86:DYNIX/ptx:4*:*)\n\t# ptx 4.0 does uname -s correctly, with DYNIX/ptx in there.\n\t# earlier versions are messed up and put the nodename in both\n\t# sysname and nodename.\n\techo i386-sequent-sysv4\n\texit ;;\n    i*86:UNIX_SV:4.2MP:2.*)\n\t# Unixware is an offshoot of SVR4, but it has its own version\n\t# number series starting with 2...\n\t# I am not positive that other SVR4 systems won't match this,\n\t# I just have to hope.  -- rms.\n\t# Use sysv4.2uw... so that sysv4* matches it.\n\techo ${UNAME_MACHINE}-pc-sysv4.2uw${UNAME_VERSION}\n\texit ;;\n    i*86:OS/2:*:*)\n\t# If we were able to find `uname', then EMX Unix compatibility\n\t# is probably installed.\n\techo ${UNAME_MACHINE}-pc-os2-emx\n\texit ;;\n    i*86:XTS-300:*:STOP)\n\techo ${UNAME_MACHINE}-unknown-stop\n\texit ;;\n    i*86:atheos:*:*)\n\techo ${UNAME_MACHINE}-unknown-atheos\n\texit ;;\n    i*86:syllable:*:*)\n\techo ${UNAME_MACHINE}-pc-syllable\n\texit ;;\n    i*86:LynxOS:2.*:* | i*86:LynxOS:3.[01]*:* | i*86:LynxOS:4.[02]*:*)\n\techo i386-unknown-lynxos${UNAME_RELEASE}\n\texit ;;\n    i*86:*DOS:*:*)\n\techo ${UNAME_MACHINE}-pc-msdosdjgpp\n\texit ;;\n    i*86:*:4.*:* | i*86:SYSTEM_V:4.*:*)\n\tUNAME_REL=`echo ${UNAME_RELEASE} | sed 's/\\/MP$//'`\n\tif grep Novell /usr/include/link.h >/dev/null 2>/dev/null; then\n\t\techo ${UNAME_MACHINE}-univel-sysv${UNAME_REL}\n\telse\n\t\techo ${UNAME_MACHINE}-pc-sysv${UNAME_REL}\n\tfi\n\texit ;;\n    i*86:*:5:[678]*)\n\t# UnixWare 7.x, OpenUNIX and OpenServer 6.\n\tcase `/bin/uname -X | grep \"^Machine\"` in\n\t    *486*)\t     UNAME_MACHINE=i486 ;;\n\t    *Pentium)\t     UNAME_MACHINE=i586 ;;\n\t    *Pent*|*Celeron) UNAME_MACHINE=i686 ;;\n\tesac\n\techo ${UNAME_MACHINE}-unknown-sysv${UNAME_RELEASE}${UNAME_SYSTEM}${UNAME_VERSION}\n\texit ;;\n    i*86:*:3.2:*)\n\tif test -f /usr/options/cb.name; then\n\t\tUNAME_REL=`sed -n 's/.*Version //p' </usr/options/cb.name`\n\t\techo ${UNAME_MACHINE}-pc-isc$UNAME_REL\n\telif /bin/uname -X 2>/dev/null >/dev/null ; then\n\t\tUNAME_REL=`(/bin/uname -X|grep Release|sed -e 's/.*= //')`\n\t\t(/bin/uname -X|grep i80486 >/dev/null) && UNAME_MACHINE=i486\n\t\t(/bin/uname -X|grep '^Machine.*Pentium' >/dev/null) \\\n\t\t\t&& UNAME_MACHINE=i586\n\t\t(/bin/uname -X|grep '^Machine.*Pent *II' >/dev/null) \\\n\t\t\t&& UNAME_MACHINE=i686\n\t\t(/bin/uname -X|grep '^Machine.*Pentium Pro' >/dev/null) \\\n\t\t\t&& UNAME_MACHINE=i686\n\t\techo ${UNAME_MACHINE}-pc-sco$UNAME_REL\n\telse\n\t\techo ${UNAME_MACHINE}-pc-sysv32\n\tfi\n\texit ;;\n    pc:*:*:*)\n\t# Left here for compatibility:\n\t# uname -m prints for DJGPP always 'pc', but it prints nothing about\n\t# the processor, so we play safe by assuming i586.\n\t# Note: whatever this is, it MUST be the same as what config.sub\n\t# prints for the \"djgpp\" host, or else GDB configury will decide that\n\t# this is a cross-build.\n\techo i586-pc-msdosdjgpp\n\texit ;;\n    Intel:Mach:3*:*)\n\techo i386-pc-mach3\n\texit ;;\n    paragon:*:*:*)\n\techo i860-intel-osf1\n\texit ;;\n    i860:*:4.*:*) # i860-SVR4\n\tif grep Stardent /usr/include/sys/uadmin.h >/dev/null 2>&1 ; then\n\t  echo i860-stardent-sysv${UNAME_RELEASE} # Stardent Vistra i860-SVR4\n\telse # Add other i860-SVR4 vendors below as they are discovered.\n\t  echo i860-unknown-sysv${UNAME_RELEASE}  # Unknown i860-SVR4\n\tfi\n\texit ;;\n    mini*:CTIX:SYS*5:*)\n\t# \"miniframe\"\n\techo m68010-convergent-sysv\n\texit ;;\n    mc68k:UNIX:SYSTEM5:3.51m)\n\techo m68k-convergent-sysv\n\texit ;;\n    M680?0:D-NIX:5.3:*)\n\techo m68k-diab-dnix\n\texit ;;\n    M68*:*:R3V[5678]*:*)\n\ttest -r /sysV68 && { echo 'm68k-motorola-sysv'; exit; } ;;\n    3[345]??:*:4.0:3.0 | 3[34]??A:*:4.0:3.0 | 3[34]??,*:*:4.0:3.0 | 3[34]??/*:*:4.0:3.0 | 4400:*:4.0:3.0 | 4850:*:4.0:3.0 | SKA40:*:4.0:3.0 | SDS2:*:4.0:3.0 | SHG2:*:4.0:3.0 | S7501*:*:4.0:3.0)\n\tOS_REL=''\n\ttest -r /etc/.relid \\\n\t&& OS_REL=.`sed -n 's/[^ ]* [^ ]* \\([0-9][0-9]\\).*/\\1/p' < /etc/.relid`\n\t/bin/uname -p 2>/dev/null | grep 86 >/dev/null \\\n\t  && { echo i486-ncr-sysv4.3${OS_REL}; exit; }\n\t/bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \\\n\t  && { echo i586-ncr-sysv4.3${OS_REL}; exit; } ;;\n    3[34]??:*:4.0:* | 3[34]??,*:*:4.0:*)\n\t/bin/uname -p 2>/dev/null | grep 86 >/dev/null \\\n\t  && { echo i486-ncr-sysv4; exit; } ;;\n    NCR*:*:4.2:* | MPRAS*:*:4.2:*)\n\tOS_REL='.3'\n\ttest -r /etc/.relid \\\n\t    && OS_REL=.`sed -n 's/[^ ]* [^ ]* \\([0-9][0-9]\\).*/\\1/p' < /etc/.relid`\n\t/bin/uname -p 2>/dev/null | grep 86 >/dev/null \\\n\t    && { echo i486-ncr-sysv4.3${OS_REL}; exit; }\n\t/bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \\\n\t    && { echo i586-ncr-sysv4.3${OS_REL}; exit; }\n\t/bin/uname -p 2>/dev/null | /bin/grep pteron >/dev/null \\\n\t    && { echo i586-ncr-sysv4.3${OS_REL}; exit; } ;;\n    m68*:LynxOS:2.*:* | m68*:LynxOS:3.0*:*)\n\techo m68k-unknown-lynxos${UNAME_RELEASE}\n\texit ;;\n    mc68030:UNIX_System_V:4.*:*)\n\techo m68k-atari-sysv4\n\texit ;;\n    TSUNAMI:LynxOS:2.*:*)\n\techo sparc-unknown-lynxos${UNAME_RELEASE}\n\texit ;;\n    rs6000:LynxOS:2.*:*)\n\techo rs6000-unknown-lynxos${UNAME_RELEASE}\n\texit ;;\n    PowerPC:LynxOS:2.*:* | PowerPC:LynxOS:3.[01]*:* | PowerPC:LynxOS:4.[02]*:*)\n\techo powerpc-unknown-lynxos${UNAME_RELEASE}\n\texit ;;\n    SM[BE]S:UNIX_SV:*:*)\n\techo mips-dde-sysv${UNAME_RELEASE}\n\texit ;;\n    RM*:ReliantUNIX-*:*:*)\n\techo mips-sni-sysv4\n\texit ;;\n    RM*:SINIX-*:*:*)\n\techo mips-sni-sysv4\n\texit ;;\n    *:SINIX-*:*:*)\n\tif uname -p 2>/dev/null >/dev/null ; then\n\t\tUNAME_MACHINE=`(uname -p) 2>/dev/null`\n\t\techo ${UNAME_MACHINE}-sni-sysv4\n\telse\n\t\techo ns32k-sni-sysv\n\tfi\n\texit ;;\n    PENTIUM:*:4.0*:*)\t# Unisys `ClearPath HMP IX 4000' SVR4/MP effort\n\t\t\t# says <Richard.M.Bartel@ccMail.Census.GOV>\n\techo i586-unisys-sysv4\n\texit ;;\n    *:UNIX_System_V:4*:FTX*)\n\t# From Gerald Hewes <hewes@openmarket.com>.\n\t# How about differentiating between stratus architectures? -djm\n\techo hppa1.1-stratus-sysv4\n\texit ;;\n    *:*:*:FTX*)\n\t# From seanf@swdc.stratus.com.\n\techo i860-stratus-sysv4\n\texit ;;\n    i*86:VOS:*:*)\n\t# From Paul.Green@stratus.com.\n\techo ${UNAME_MACHINE}-stratus-vos\n\texit ;;\n    *:VOS:*:*)\n\t# From Paul.Green@stratus.com.\n\techo hppa1.1-stratus-vos\n\texit ;;\n    mc68*:A/UX:*:*)\n\techo m68k-apple-aux${UNAME_RELEASE}\n\texit ;;\n    news*:NEWS-OS:6*:*)\n\techo mips-sony-newsos6\n\texit ;;\n    R[34]000:*System_V*:*:* | R4000:UNIX_SYSV:*:* | R*000:UNIX_SV:*:*)\n\tif [ -d /usr/nec ]; then\n\t\techo mips-nec-sysv${UNAME_RELEASE}\n\telse\n\t\techo mips-unknown-sysv${UNAME_RELEASE}\n\tfi\n\texit ;;\n    BeBox:BeOS:*:*)\t# BeOS running on hardware made by Be, PPC only.\n\techo powerpc-be-beos\n\texit ;;\n    BeMac:BeOS:*:*)\t# BeOS running on Mac or Mac clone, PPC only.\n\techo powerpc-apple-beos\n\texit ;;\n    BePC:BeOS:*:*)\t# BeOS running on Intel PC compatible.\n\techo i586-pc-beos\n\texit ;;\n    BePC:Haiku:*:*)\t# Haiku running on Intel PC compatible.\n\techo i586-pc-haiku\n\texit ;;\n    x86_64:Haiku:*:*)\n\techo x86_64-unknown-haiku\n\texit ;;\n    SX-4:SUPER-UX:*:*)\n\techo sx4-nec-superux${UNAME_RELEASE}\n\texit ;;\n    SX-5:SUPER-UX:*:*)\n\techo sx5-nec-superux${UNAME_RELEASE}\n\texit ;;\n    SX-6:SUPER-UX:*:*)\n\techo sx6-nec-superux${UNAME_RELEASE}\n\texit ;;\n    SX-7:SUPER-UX:*:*)\n\techo sx7-nec-superux${UNAME_RELEASE}\n\texit ;;\n    SX-8:SUPER-UX:*:*)\n\techo sx8-nec-superux${UNAME_RELEASE}\n\texit ;;\n    SX-8R:SUPER-UX:*:*)\n\techo sx8r-nec-superux${UNAME_RELEASE}\n\texit ;;\n    Power*:Rhapsody:*:*)\n\techo powerpc-apple-rhapsody${UNAME_RELEASE}\n\texit ;;\n    *:Rhapsody:*:*)\n\techo ${UNAME_MACHINE}-apple-rhapsody${UNAME_RELEASE}\n\texit ;;\n    *:Darwin:*:*)\n\tUNAME_PROCESSOR=`uname -p` || UNAME_PROCESSOR=unknown\n\teval $set_cc_for_build\n\tif test \"$UNAME_PROCESSOR\" = unknown ; then\n\t    UNAME_PROCESSOR=powerpc\n\tfi\n\tif test `echo \"$UNAME_RELEASE\" | sed -e 's/\\..*//'` -le 10 ; then\n\t    if [ \"$CC_FOR_BUILD\" != 'no_compiler_found' ]; then\n\t\tif (echo '#ifdef __LP64__'; echo IS_64BIT_ARCH; echo '#endif') | \\\n\t\t    (CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) | \\\n\t\t    grep IS_64BIT_ARCH >/dev/null\n\t\tthen\n\t\t    case $UNAME_PROCESSOR in\n\t\t\ti386) UNAME_PROCESSOR=x86_64 ;;\n\t\t\tpowerpc) UNAME_PROCESSOR=powerpc64 ;;\n\t\t    esac\n\t\tfi\n\t    fi\n\telif test \"$UNAME_PROCESSOR\" = i386 ; then\n\t    # Avoid executing cc on OS X 10.9, as it ships with a stub\n\t    # that puts up a graphical alert prompting to install\n\t    # developer tools.  Any system running Mac OS X 10.7 or\n\t    # later (Darwin 11 and later) is required to have a 64-bit\n\t    # processor. This is not true of the ARM version of Darwin\n\t    # that Apple uses in portable devices.\n\t    UNAME_PROCESSOR=x86_64\n\tfi\n\techo ${UNAME_PROCESSOR}-apple-darwin${UNAME_RELEASE}\n\texit ;;\n    *:procnto*:*:* | *:QNX:[0123456789]*:*)\n\tUNAME_PROCESSOR=`uname -p`\n\tif test \"$UNAME_PROCESSOR\" = \"x86\"; then\n\t\tUNAME_PROCESSOR=i386\n\t\tUNAME_MACHINE=pc\n\tfi\n\techo ${UNAME_PROCESSOR}-${UNAME_MACHINE}-nto-qnx${UNAME_RELEASE}\n\texit ;;\n    *:QNX:*:4*)\n\techo i386-pc-qnx\n\texit ;;\n    NEO-?:NONSTOP_KERNEL:*:*)\n\techo neo-tandem-nsk${UNAME_RELEASE}\n\texit ;;\n    NSE-*:NONSTOP_KERNEL:*:*)\n\techo nse-tandem-nsk${UNAME_RELEASE}\n\texit ;;\n    NSR-?:NONSTOP_KERNEL:*:*)\n\techo nsr-tandem-nsk${UNAME_RELEASE}\n\texit ;;\n    *:NonStop-UX:*:*)\n\techo mips-compaq-nonstopux\n\texit ;;\n    BS2000:POSIX*:*:*)\n\techo bs2000-siemens-sysv\n\texit ;;\n    DS/*:UNIX_System_V:*:*)\n\techo ${UNAME_MACHINE}-${UNAME_SYSTEM}-${UNAME_RELEASE}\n\texit ;;\n    *:Plan9:*:*)\n\t# \"uname -m\" is not consistent, so use $cputype instead. 386\n\t# is converted to i386 for consistency with other x86\n\t# operating systems.\n\tif test \"$cputype\" = \"386\"; then\n\t    UNAME_MACHINE=i386\n\telse\n\t    UNAME_MACHINE=\"$cputype\"\n\tfi\n\techo ${UNAME_MACHINE}-unknown-plan9\n\texit ;;\n    *:TOPS-10:*:*)\n\techo pdp10-unknown-tops10\n\texit ;;\n    *:TENEX:*:*)\n\techo pdp10-unknown-tenex\n\texit ;;\n    KS10:TOPS-20:*:* | KL10:TOPS-20:*:* | TYPE4:TOPS-20:*:*)\n\techo pdp10-dec-tops20\n\texit ;;\n    XKL-1:TOPS-20:*:* | TYPE5:TOPS-20:*:*)\n\techo pdp10-xkl-tops20\n\texit ;;\n    *:TOPS-20:*:*)\n\techo pdp10-unknown-tops20\n\texit ;;\n    *:ITS:*:*)\n\techo pdp10-unknown-its\n\texit ;;\n    SEI:*:*:SEIUX)\n\techo mips-sei-seiux${UNAME_RELEASE}\n\texit ;;\n    *:DragonFly:*:*)\n\techo ${UNAME_MACHINE}-unknown-dragonfly`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`\n\texit ;;\n    *:*VMS:*:*)\n\tUNAME_MACHINE=`(uname -p) 2>/dev/null`\n\tcase \"${UNAME_MACHINE}\" in\n\t    A*) echo alpha-dec-vms ; exit ;;\n\t    I*) echo ia64-dec-vms ; exit ;;\n\t    V*) echo vax-dec-vms ; exit ;;\n\tesac ;;\n    *:XENIX:*:SysV)\n\techo i386-pc-xenix\n\texit ;;\n    i*86:skyos:*:*)\n\techo ${UNAME_MACHINE}-pc-skyos`echo ${UNAME_RELEASE}` | sed -e 's/ .*$//'\n\texit ;;\n    i*86:rdos:*:*)\n\techo ${UNAME_MACHINE}-pc-rdos\n\texit ;;\n    i*86:AROS:*:*)\n\techo ${UNAME_MACHINE}-pc-aros\n\texit ;;\n    x86_64:VMkernel:*:*)\n\techo ${UNAME_MACHINE}-unknown-esx\n\texit ;;\nesac\n\ncat >&2 <<EOF\n$0: unable to guess system type\n\nThis script, last modified $timestamp, has failed to recognize\nthe operating system you are using. It is advised that you\ndownload the most up to date version of the config scripts from\n\n  http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.guess;hb=HEAD\nand\n  http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.sub;hb=HEAD\n\nIf the version you run ($0) is already up to date, please\nsend the following data and any information you think might be\npertinent to <config-patches@gnu.org> in order to provide the needed\ninformation to handle your system.\n\nconfig.guess timestamp = $timestamp\n\nuname -m = `(uname -m) 2>/dev/null || echo unknown`\nuname -r = `(uname -r) 2>/dev/null || echo unknown`\nuname -s = `(uname -s) 2>/dev/null || echo unknown`\nuname -v = `(uname -v) 2>/dev/null || echo unknown`\n\n/usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null`\n/bin/uname -X     = `(/bin/uname -X) 2>/dev/null`\n\nhostinfo               = `(hostinfo) 2>/dev/null`\n/bin/universe          = `(/bin/universe) 2>/dev/null`\n/usr/bin/arch -k       = `(/usr/bin/arch -k) 2>/dev/null`\n/bin/arch              = `(/bin/arch) 2>/dev/null`\n/usr/bin/oslevel       = `(/usr/bin/oslevel) 2>/dev/null`\n/usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null`\n\nUNAME_MACHINE = ${UNAME_MACHINE}\nUNAME_RELEASE = ${UNAME_RELEASE}\nUNAME_SYSTEM  = ${UNAME_SYSTEM}\nUNAME_VERSION = ${UNAME_VERSION}\nEOF\n\nexit 1\n\n# Local variables:\n# eval: (add-hook 'write-file-hooks 'time-stamp)\n# time-stamp-start: \"timestamp='\"\n# time-stamp-format: \"%:y-%02m-%02d\"\n# time-stamp-end: \"'\"\n# End:\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/deps/jemalloc/build-aux/config.sub",
    "content": "#! /bin/sh\n# Configuration validation subroutine script.\n#   Copyright 1992-2014 Free Software Foundation, Inc.\n\ntimestamp='2014-05-01'\n\n# This file is free software; you can redistribute it and/or modify it\n# under the terms of the GNU General Public License as published by\n# the Free Software Foundation; either version 3 of the License, or\n# (at your option) any later version.\n#\n# This program is distributed in the hope that it will be useful, but\n# WITHOUT ANY WARRANTY; without even the implied warranty of\n# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n# General Public License for more details.\n#\n# You should have received a copy of the GNU General Public License\n# along with this program; if not, see <http://www.gnu.org/licenses/>.\n#\n# As a special exception to the GNU General Public License, if you\n# distribute this file as part of a program that contains a\n# configuration script generated by Autoconf, you may include it under\n# the same distribution terms that you use for the rest of that\n# program.  This Exception is an additional permission under section 7\n# of the GNU General Public License, version 3 (\"GPLv3\").\n\n\n# Please send patches with a ChangeLog entry to config-patches@gnu.org.\n#\n# Configuration subroutine to validate and canonicalize a configuration type.\n# Supply the specified configuration type as an argument.\n# If it is invalid, we print an error message on stderr and exit with code 1.\n# Otherwise, we print the canonical config type on stdout and succeed.\n\n# You can get the latest version of this script from:\n# http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.sub;hb=HEAD\n\n# This file is supposed to be the same for all GNU packages\n# and recognize all the CPU types, system types and aliases\n# that are meaningful with *any* GNU software.\n# Each package is responsible for reporting which valid configurations\n# it does not support.  The user should be able to distinguish\n# a failure to support a valid configuration from a meaningless\n# configuration.\n\n# The goal of this file is to map all the various variations of a given\n# machine specification into a single specification in the form:\n#\tCPU_TYPE-MANUFACTURER-OPERATING_SYSTEM\n# or in some cases, the newer four-part form:\n#\tCPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM\n# It is wrong to echo any other type of specification.\n\nme=`echo \"$0\" | sed -e 's,.*/,,'`\n\nusage=\"\\\nUsage: $0 [OPTION] CPU-MFR-OPSYS\n       $0 [OPTION] ALIAS\n\nCanonicalize a configuration name.\n\nOperation modes:\n  -h, --help         print this help, then exit\n  -t, --time-stamp   print date of last modification, then exit\n  -v, --version      print version number, then exit\n\nReport bugs and patches to <config-patches@gnu.org>.\"\n\nversion=\"\\\nGNU config.sub ($timestamp)\n\nCopyright 1992-2014 Free Software Foundation, Inc.\n\nThis is free software; see the source for copying conditions.  There is NO\nwarranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\"\n\nhelp=\"\nTry \\`$me --help' for more information.\"\n\n# Parse command line\nwhile test $# -gt 0 ; do\n  case $1 in\n    --time-stamp | --time* | -t )\n       echo \"$timestamp\" ; exit ;;\n    --version | -v )\n       echo \"$version\" ; exit ;;\n    --help | --h* | -h )\n       echo \"$usage\"; exit ;;\n    -- )     # Stop option processing\n       shift; break ;;\n    - )\t# Use stdin as input.\n       break ;;\n    -* )\n       echo \"$me: invalid option $1$help\"\n       exit 1 ;;\n\n    *local*)\n       # First pass through any local machine types.\n       echo $1\n       exit ;;\n\n    * )\n       break ;;\n  esac\ndone\n\ncase $# in\n 0) echo \"$me: missing argument$help\" >&2\n    exit 1;;\n 1) ;;\n *) echo \"$me: too many arguments$help\" >&2\n    exit 1;;\nesac\n\n# Separate what the user gave into CPU-COMPANY and OS or KERNEL-OS (if any).\n# Here we must recognize all the valid KERNEL-OS combinations.\nmaybe_os=`echo $1 | sed 's/^\\(.*\\)-\\([^-]*-[^-]*\\)$/\\2/'`\ncase $maybe_os in\n  nto-qnx* | linux-gnu* | linux-android* | linux-dietlibc | linux-newlib* | \\\n  linux-musl* | linux-uclibc* | uclinux-uclibc* | uclinux-gnu* | kfreebsd*-gnu* | \\\n  knetbsd*-gnu* | netbsd*-gnu* | \\\n  kopensolaris*-gnu* | \\\n  storm-chaos* | os2-emx* | rtmk-nova*)\n    os=-$maybe_os\n    basic_machine=`echo $1 | sed 's/^\\(.*\\)-\\([^-]*-[^-]*\\)$/\\1/'`\n    ;;\n  android-linux)\n    os=-linux-android\n    basic_machine=`echo $1 | sed 's/^\\(.*\\)-\\([^-]*-[^-]*\\)$/\\1/'`-unknown\n    ;;\n  *)\n    basic_machine=`echo $1 | sed 's/-[^-]*$//'`\n    if [ $basic_machine != $1 ]\n    then os=`echo $1 | sed 's/.*-/-/'`\n    else os=; fi\n    ;;\nesac\n\n### Let's recognize common machines as not being operating systems so\n### that things like config.sub decstation-3100 work.  We also\n### recognize some manufacturers as not being operating systems, so we\n### can provide default operating systems below.\ncase $os in\n\t-sun*os*)\n\t\t# Prevent following clause from handling this invalid input.\n\t\t;;\n\t-dec* | -mips* | -sequent* | -encore* | -pc532* | -sgi* | -sony* | \\\n\t-att* | -7300* | -3300* | -delta* | -motorola* | -sun[234]* | \\\n\t-unicom* | -ibm* | -next | -hp | -isi* | -apollo | -altos* | \\\n\t-convergent* | -ncr* | -news | -32* | -3600* | -3100* | -hitachi* |\\\n\t-c[123]* | -convex* | -sun | -crds | -omron* | -dg | -ultra | -tti* | \\\n\t-harris | -dolphin | -highlevel | -gould | -cbm | -ns | -masscomp | \\\n\t-apple | -axis | -knuth | -cray | -microblaze*)\n\t\tos=\n\t\tbasic_machine=$1\n\t\t;;\n\t-bluegene*)\n\t\tos=-cnk\n\t\t;;\n\t-sim | -cisco | -oki | -wec | -winbond)\n\t\tos=\n\t\tbasic_machine=$1\n\t\t;;\n\t-scout)\n\t\t;;\n\t-wrs)\n\t\tos=-vxworks\n\t\tbasic_machine=$1\n\t\t;;\n\t-chorusos*)\n\t\tos=-chorusos\n\t\tbasic_machine=$1\n\t\t;;\n\t-chorusrdb)\n\t\tos=-chorusrdb\n\t\tbasic_machine=$1\n\t\t;;\n\t-hiux*)\n\t\tos=-hiuxwe2\n\t\t;;\n\t-sco6)\n\t\tos=-sco5v6\n\t\tbasic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`\n\t\t;;\n\t-sco5)\n\t\tos=-sco3.2v5\n\t\tbasic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`\n\t\t;;\n\t-sco4)\n\t\tos=-sco3.2v4\n\t\tbasic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`\n\t\t;;\n\t-sco3.2.[4-9]*)\n\t\tos=`echo $os | sed -e 's/sco3.2./sco3.2v/'`\n\t\tbasic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`\n\t\t;;\n\t-sco3.2v[4-9]*)\n\t\t# Don't forget version if it is 3.2v4 or newer.\n\t\tbasic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`\n\t\t;;\n\t-sco5v6*)\n\t\t# Don't forget version if it is 3.2v4 or newer.\n\t\tbasic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`\n\t\t;;\n\t-sco*)\n\t\tos=-sco3.2v2\n\t\tbasic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`\n\t\t;;\n\t-udk*)\n\t\tbasic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`\n\t\t;;\n\t-isc)\n\t\tos=-isc2.2\n\t\tbasic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`\n\t\t;;\n\t-clix*)\n\t\tbasic_machine=clipper-intergraph\n\t\t;;\n\t-isc*)\n\t\tbasic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`\n\t\t;;\n\t-lynx*178)\n\t\tos=-lynxos178\n\t\t;;\n\t-lynx*5)\n\t\tos=-lynxos5\n\t\t;;\n\t-lynx*)\n\t\tos=-lynxos\n\t\t;;\n\t-ptx*)\n\t\tbasic_machine=`echo $1 | sed -e 's/86-.*/86-sequent/'`\n\t\t;;\n\t-windowsnt*)\n\t\tos=`echo $os | sed -e 's/windowsnt/winnt/'`\n\t\t;;\n\t-psos*)\n\t\tos=-psos\n\t\t;;\n\t-mint | -mint[0-9]*)\n\t\tbasic_machine=m68k-atari\n\t\tos=-mint\n\t\t;;\nesac\n\n# Decode aliases for certain CPU-COMPANY combinations.\ncase $basic_machine in\n\t# Recognize the basic CPU types without company name.\n\t# Some are omitted here because they have special meanings below.\n\t1750a | 580 \\\n\t| a29k \\\n\t| aarch64 | aarch64_be \\\n\t| alpha | alphaev[4-8] | alphaev56 | alphaev6[78] | alphapca5[67] \\\n\t| alpha64 | alpha64ev[4-8] | alpha64ev56 | alpha64ev6[78] | alpha64pca5[67] \\\n\t| am33_2.0 \\\n\t| arc | arceb \\\n\t| arm | arm[bl]e | arme[lb] | armv[2-8] | armv[3-8][lb] | armv7[arm] \\\n\t| avr | avr32 \\\n\t| be32 | be64 \\\n\t| bfin \\\n\t| c4x | c8051 | clipper \\\n\t| d10v | d30v | dlx | dsp16xx \\\n\t| epiphany \\\n\t| fido | fr30 | frv \\\n\t| h8300 | h8500 | hppa | hppa1.[01] | hppa2.0 | hppa2.0[nw] | hppa64 \\\n\t| hexagon \\\n\t| i370 | i860 | i960 | ia64 \\\n\t| ip2k | iq2000 \\\n\t| k1om \\\n\t| le32 | le64 \\\n\t| lm32 \\\n\t| m32c | m32r | m32rle | m68000 | m68k | m88k \\\n\t| maxq | mb | microblaze | microblazeel | mcore | mep | metag \\\n\t| mips | mipsbe | mipseb | mipsel | mipsle \\\n\t| mips16 \\\n\t| mips64 | mips64el \\\n\t| mips64octeon | mips64octeonel \\\n\t| mips64orion | mips64orionel \\\n\t| mips64r5900 | mips64r5900el \\\n\t| mips64vr | mips64vrel \\\n\t| mips64vr4100 | mips64vr4100el \\\n\t| mips64vr4300 | mips64vr4300el \\\n\t| mips64vr5000 | mips64vr5000el \\\n\t| mips64vr5900 | mips64vr5900el \\\n\t| mipsisa32 | mipsisa32el \\\n\t| mipsisa32r2 | mipsisa32r2el \\\n\t| mipsisa32r6 | mipsisa32r6el \\\n\t| mipsisa64 | mipsisa64el \\\n\t| mipsisa64r2 | mipsisa64r2el \\\n\t| mipsisa64r6 | mipsisa64r6el \\\n\t| mipsisa64sb1 | mipsisa64sb1el \\\n\t| mipsisa64sr71k | mipsisa64sr71kel \\\n\t| mipsr5900 | mipsr5900el \\\n\t| mipstx39 | mipstx39el \\\n\t| mn10200 | mn10300 \\\n\t| moxie \\\n\t| mt \\\n\t| msp430 \\\n\t| nds32 | nds32le | nds32be \\\n\t| nios | nios2 | nios2eb | nios2el \\\n\t| ns16k | ns32k \\\n\t| open8 | or1k | or1knd | or32 \\\n\t| pdp10 | pdp11 | pj | pjl \\\n\t| powerpc | powerpc64 | powerpc64le | powerpcle \\\n\t| pyramid \\\n\t| rl78 | rx \\\n\t| score \\\n\t| sh | sh[1234] | sh[24]a | sh[24]aeb | sh[23]e | sh[34]eb | sheb | shbe | shle | sh[1234]le | sh3ele \\\n\t| sh64 | sh64le \\\n\t| sparc | sparc64 | sparc64b | sparc64v | sparc86x | sparclet | sparclite \\\n\t| sparcv8 | sparcv9 | sparcv9b | sparcv9v \\\n\t| spu \\\n\t| tahoe | tic4x | tic54x | tic55x | tic6x | tic80 | tron \\\n\t| ubicom32 \\\n\t| v850 | v850e | v850e1 | v850e2 | v850es | v850e2v3 \\\n\t| we32k \\\n\t| x86 | xc16x | xstormy16 | xtensa \\\n\t| z8k | z80)\n\t\tbasic_machine=$basic_machine-unknown\n\t\t;;\n\tc54x)\n\t\tbasic_machine=tic54x-unknown\n\t\t;;\n\tc55x)\n\t\tbasic_machine=tic55x-unknown\n\t\t;;\n\tc6x)\n\t\tbasic_machine=tic6x-unknown\n\t\t;;\n\tm6811 | m68hc11 | m6812 | m68hc12 | m68hcs12x | nvptx | picochip)\n\t\tbasic_machine=$basic_machine-unknown\n\t\tos=-none\n\t\t;;\n\tm88110 | m680[12346]0 | m683?2 | m68360 | m5200 | v70 | w65 | z8k)\n\t\t;;\n\tms1)\n\t\tbasic_machine=mt-unknown\n\t\t;;\n\n\tstrongarm | thumb | xscale)\n\t\tbasic_machine=arm-unknown\n\t\t;;\n\txgate)\n\t\tbasic_machine=$basic_machine-unknown\n\t\tos=-none\n\t\t;;\n\txscaleeb)\n\t\tbasic_machine=armeb-unknown\n\t\t;;\n\n\txscaleel)\n\t\tbasic_machine=armel-unknown\n\t\t;;\n\n\t# We use `pc' rather than `unknown'\n\t# because (1) that's what they normally are, and\n\t# (2) the word \"unknown\" tends to confuse beginning users.\n\ti*86 | x86_64)\n\t  basic_machine=$basic_machine-pc\n\t  ;;\n\t# Object if more than one company name word.\n\t*-*-*)\n\t\techo Invalid configuration \\`$1\\': machine \\`$basic_machine\\' not recognized 1>&2\n\t\texit 1\n\t\t;;\n\t# Recognize the basic CPU types with company name.\n\t580-* \\\n\t| a29k-* \\\n\t| aarch64-* | aarch64_be-* \\\n\t| alpha-* | alphaev[4-8]-* | alphaev56-* | alphaev6[78]-* \\\n\t| alpha64-* | alpha64ev[4-8]-* | alpha64ev56-* | alpha64ev6[78]-* \\\n\t| alphapca5[67]-* | alpha64pca5[67]-* | arc-* | arceb-* \\\n\t| arm-*  | armbe-* | armle-* | armeb-* | armv*-* \\\n\t| avr-* | avr32-* \\\n\t| be32-* | be64-* \\\n\t| bfin-* | bs2000-* \\\n\t| c[123]* | c30-* | [cjt]90-* | c4x-* \\\n\t| c8051-* | clipper-* | craynv-* | cydra-* \\\n\t| d10v-* | d30v-* | dlx-* \\\n\t| elxsi-* \\\n\t| f30[01]-* | f700-* | fido-* | fr30-* | frv-* | fx80-* \\\n\t| h8300-* | h8500-* \\\n\t| hppa-* | hppa1.[01]-* | hppa2.0-* | hppa2.0[nw]-* | hppa64-* \\\n\t| hexagon-* \\\n\t| i*86-* | i860-* | i960-* | ia64-* \\\n\t| ip2k-* | iq2000-* \\\n\t| k1om-* \\\n\t| le32-* | le64-* \\\n\t| lm32-* \\\n\t| m32c-* | m32r-* | m32rle-* \\\n\t| m68000-* | m680[012346]0-* | m68360-* | m683?2-* | m68k-* \\\n\t| m88110-* | m88k-* | maxq-* | mcore-* | metag-* \\\n\t| microblaze-* | microblazeel-* \\\n\t| mips-* | mipsbe-* | mipseb-* | mipsel-* | mipsle-* \\\n\t| mips16-* \\\n\t| mips64-* | mips64el-* \\\n\t| mips64octeon-* | mips64octeonel-* \\\n\t| mips64orion-* | mips64orionel-* \\\n\t| mips64r5900-* | mips64r5900el-* \\\n\t| mips64vr-* | mips64vrel-* \\\n\t| mips64vr4100-* | mips64vr4100el-* \\\n\t| mips64vr4300-* | mips64vr4300el-* \\\n\t| mips64vr5000-* | mips64vr5000el-* \\\n\t| mips64vr5900-* | mips64vr5900el-* \\\n\t| mipsisa32-* | mipsisa32el-* \\\n\t| mipsisa32r2-* | mipsisa32r2el-* \\\n\t| mipsisa32r6-* | mipsisa32r6el-* \\\n\t| mipsisa64-* | mipsisa64el-* \\\n\t| mipsisa64r2-* | mipsisa64r2el-* \\\n\t| mipsisa64r6-* | mipsisa64r6el-* \\\n\t| mipsisa64sb1-* | mipsisa64sb1el-* \\\n\t| mipsisa64sr71k-* | mipsisa64sr71kel-* \\\n\t| mipsr5900-* | mipsr5900el-* \\\n\t| mipstx39-* | mipstx39el-* \\\n\t| mmix-* \\\n\t| mt-* \\\n\t| msp430-* \\\n\t| nds32-* | nds32le-* | nds32be-* \\\n\t| nios-* | nios2-* | nios2eb-* | nios2el-* \\\n\t| none-* | np1-* | ns16k-* | ns32k-* \\\n\t| open8-* \\\n\t| or1k*-* \\\n\t| orion-* \\\n\t| pdp10-* | pdp11-* | pj-* | pjl-* | pn-* | power-* \\\n\t| powerpc-* | powerpc64-* | powerpc64le-* | powerpcle-* \\\n\t| pyramid-* \\\n\t| rl78-* | romp-* | rs6000-* | rx-* \\\n\t| sh-* | sh[1234]-* | sh[24]a-* | sh[24]aeb-* | sh[23]e-* | sh[34]eb-* | sheb-* | shbe-* \\\n\t| shle-* | sh[1234]le-* | sh3ele-* | sh64-* | sh64le-* \\\n\t| sparc-* | sparc64-* | sparc64b-* | sparc64v-* | sparc86x-* | sparclet-* \\\n\t| sparclite-* \\\n\t| sparcv8-* | sparcv9-* | sparcv9b-* | sparcv9v-* | sv1-* | sx?-* \\\n\t| tahoe-* \\\n\t| tic30-* | tic4x-* | tic54x-* | tic55x-* | tic6x-* | tic80-* \\\n\t| tile*-* \\\n\t| tron-* \\\n\t| ubicom32-* \\\n\t| v850-* | v850e-* | v850e1-* | v850es-* | v850e2-* | v850e2v3-* \\\n\t| vax-* \\\n\t| we32k-* \\\n\t| x86-* | x86_64-* | xc16x-* | xps100-* \\\n\t| xstormy16-* | xtensa*-* \\\n\t| ymp-* \\\n\t| z8k-* | z80-*)\n\t\t;;\n\t# Recognize the basic CPU types without company name, with glob match.\n\txtensa*)\n\t\tbasic_machine=$basic_machine-unknown\n\t\t;;\n\t# Recognize the various machine names and aliases which stand\n\t# for a CPU type and a company and sometimes even an OS.\n\t386bsd)\n\t\tbasic_machine=i386-unknown\n\t\tos=-bsd\n\t\t;;\n\t3b1 | 7300 | 7300-att | att-7300 | pc7300 | safari | unixpc)\n\t\tbasic_machine=m68000-att\n\t\t;;\n\t3b*)\n\t\tbasic_machine=we32k-att\n\t\t;;\n\ta29khif)\n\t\tbasic_machine=a29k-amd\n\t\tos=-udi\n\t\t;;\n\tabacus)\n\t\tbasic_machine=abacus-unknown\n\t\t;;\n\tadobe68k)\n\t\tbasic_machine=m68010-adobe\n\t\tos=-scout\n\t\t;;\n\talliant | fx80)\n\t\tbasic_machine=fx80-alliant\n\t\t;;\n\taltos | altos3068)\n\t\tbasic_machine=m68k-altos\n\t\t;;\n\tam29k)\n\t\tbasic_machine=a29k-none\n\t\tos=-bsd\n\t\t;;\n\tamd64)\n\t\tbasic_machine=x86_64-pc\n\t\t;;\n\tamd64-*)\n\t\tbasic_machine=x86_64-`echo $basic_machine | sed 's/^[^-]*-//'`\n\t\t;;\n\tamdahl)\n\t\tbasic_machine=580-amdahl\n\t\tos=-sysv\n\t\t;;\n\tamiga | amiga-*)\n\t\tbasic_machine=m68k-unknown\n\t\t;;\n\tamigaos | amigados)\n\t\tbasic_machine=m68k-unknown\n\t\tos=-amigaos\n\t\t;;\n\tamigaunix | amix)\n\t\tbasic_machine=m68k-unknown\n\t\tos=-sysv4\n\t\t;;\n\tapollo68)\n\t\tbasic_machine=m68k-apollo\n\t\tos=-sysv\n\t\t;;\n\tapollo68bsd)\n\t\tbasic_machine=m68k-apollo\n\t\tos=-bsd\n\t\t;;\n\taros)\n\t\tbasic_machine=i386-pc\n\t\tos=-aros\n\t\t;;\n\taux)\n\t\tbasic_machine=m68k-apple\n\t\tos=-aux\n\t\t;;\n\tbalance)\n\t\tbasic_machine=ns32k-sequent\n\t\tos=-dynix\n\t\t;;\n\tblackfin)\n\t\tbasic_machine=bfin-unknown\n\t\tos=-linux\n\t\t;;\n\tblackfin-*)\n\t\tbasic_machine=bfin-`echo $basic_machine | sed 's/^[^-]*-//'`\n\t\tos=-linux\n\t\t;;\n\tbluegene*)\n\t\tbasic_machine=powerpc-ibm\n\t\tos=-cnk\n\t\t;;\n\tc54x-*)\n\t\tbasic_machine=tic54x-`echo $basic_machine | sed 's/^[^-]*-//'`\n\t\t;;\n\tc55x-*)\n\t\tbasic_machine=tic55x-`echo $basic_machine | sed 's/^[^-]*-//'`\n\t\t;;\n\tc6x-*)\n\t\tbasic_machine=tic6x-`echo $basic_machine | sed 's/^[^-]*-//'`\n\t\t;;\n\tc90)\n\t\tbasic_machine=c90-cray\n\t\tos=-unicos\n\t\t;;\n\tcegcc)\n\t\tbasic_machine=arm-unknown\n\t\tos=-cegcc\n\t\t;;\n\tconvex-c1)\n\t\tbasic_machine=c1-convex\n\t\tos=-bsd\n\t\t;;\n\tconvex-c2)\n\t\tbasic_machine=c2-convex\n\t\tos=-bsd\n\t\t;;\n\tconvex-c32)\n\t\tbasic_machine=c32-convex\n\t\tos=-bsd\n\t\t;;\n\tconvex-c34)\n\t\tbasic_machine=c34-convex\n\t\tos=-bsd\n\t\t;;\n\tconvex-c38)\n\t\tbasic_machine=c38-convex\n\t\tos=-bsd\n\t\t;;\n\tcray | j90)\n\t\tbasic_machine=j90-cray\n\t\tos=-unicos\n\t\t;;\n\tcraynv)\n\t\tbasic_machine=craynv-cray\n\t\tos=-unicosmp\n\t\t;;\n\tcr16 | cr16-*)\n\t\tbasic_machine=cr16-unknown\n\t\tos=-elf\n\t\t;;\n\tcrds | unos)\n\t\tbasic_machine=m68k-crds\n\t\t;;\n\tcrisv32 | crisv32-* | etraxfs*)\n\t\tbasic_machine=crisv32-axis\n\t\t;;\n\tcris | cris-* | etrax*)\n\t\tbasic_machine=cris-axis\n\t\t;;\n\tcrx)\n\t\tbasic_machine=crx-unknown\n\t\tos=-elf\n\t\t;;\n\tda30 | da30-*)\n\t\tbasic_machine=m68k-da30\n\t\t;;\n\tdecstation | decstation-3100 | pmax | pmax-* | pmin | dec3100 | decstatn)\n\t\tbasic_machine=mips-dec\n\t\t;;\n\tdecsystem10* | dec10*)\n\t\tbasic_machine=pdp10-dec\n\t\tos=-tops10\n\t\t;;\n\tdecsystem20* | dec20*)\n\t\tbasic_machine=pdp10-dec\n\t\tos=-tops20\n\t\t;;\n\tdelta | 3300 | motorola-3300 | motorola-delta \\\n\t      | 3300-motorola | delta-motorola)\n\t\tbasic_machine=m68k-motorola\n\t\t;;\n\tdelta88)\n\t\tbasic_machine=m88k-motorola\n\t\tos=-sysv3\n\t\t;;\n\tdicos)\n\t\tbasic_machine=i686-pc\n\t\tos=-dicos\n\t\t;;\n\tdjgpp)\n\t\tbasic_machine=i586-pc\n\t\tos=-msdosdjgpp\n\t\t;;\n\tdpx20 | dpx20-*)\n\t\tbasic_machine=rs6000-bull\n\t\tos=-bosx\n\t\t;;\n\tdpx2* | dpx2*-bull)\n\t\tbasic_machine=m68k-bull\n\t\tos=-sysv3\n\t\t;;\n\tebmon29k)\n\t\tbasic_machine=a29k-amd\n\t\tos=-ebmon\n\t\t;;\n\telxsi)\n\t\tbasic_machine=elxsi-elxsi\n\t\tos=-bsd\n\t\t;;\n\tencore | umax | mmax)\n\t\tbasic_machine=ns32k-encore\n\t\t;;\n\tes1800 | OSE68k | ose68k | ose | OSE)\n\t\tbasic_machine=m68k-ericsson\n\t\tos=-ose\n\t\t;;\n\tfx2800)\n\t\tbasic_machine=i860-alliant\n\t\t;;\n\tgenix)\n\t\tbasic_machine=ns32k-ns\n\t\t;;\n\tgmicro)\n\t\tbasic_machine=tron-gmicro\n\t\tos=-sysv\n\t\t;;\n\tgo32)\n\t\tbasic_machine=i386-pc\n\t\tos=-go32\n\t\t;;\n\th3050r* | hiux*)\n\t\tbasic_machine=hppa1.1-hitachi\n\t\tos=-hiuxwe2\n\t\t;;\n\th8300hms)\n\t\tbasic_machine=h8300-hitachi\n\t\tos=-hms\n\t\t;;\n\th8300xray)\n\t\tbasic_machine=h8300-hitachi\n\t\tos=-xray\n\t\t;;\n\th8500hms)\n\t\tbasic_machine=h8500-hitachi\n\t\tos=-hms\n\t\t;;\n\tharris)\n\t\tbasic_machine=m88k-harris\n\t\tos=-sysv3\n\t\t;;\n\thp300-*)\n\t\tbasic_machine=m68k-hp\n\t\t;;\n\thp300bsd)\n\t\tbasic_machine=m68k-hp\n\t\tos=-bsd\n\t\t;;\n\thp300hpux)\n\t\tbasic_machine=m68k-hp\n\t\tos=-hpux\n\t\t;;\n\thp3k9[0-9][0-9] | hp9[0-9][0-9])\n\t\tbasic_machine=hppa1.0-hp\n\t\t;;\n\thp9k2[0-9][0-9] | hp9k31[0-9])\n\t\tbasic_machine=m68000-hp\n\t\t;;\n\thp9k3[2-9][0-9])\n\t\tbasic_machine=m68k-hp\n\t\t;;\n\thp9k6[0-9][0-9] | hp6[0-9][0-9])\n\t\tbasic_machine=hppa1.0-hp\n\t\t;;\n\thp9k7[0-79][0-9] | hp7[0-79][0-9])\n\t\tbasic_machine=hppa1.1-hp\n\t\t;;\n\thp9k78[0-9] | hp78[0-9])\n\t\t# FIXME: really hppa2.0-hp\n\t\tbasic_machine=hppa1.1-hp\n\t\t;;\n\thp9k8[67]1 | hp8[67]1 | hp9k80[24] | hp80[24] | hp9k8[78]9 | hp8[78]9 | hp9k893 | hp893)\n\t\t# FIXME: really hppa2.0-hp\n\t\tbasic_machine=hppa1.1-hp\n\t\t;;\n\thp9k8[0-9][13679] | hp8[0-9][13679])\n\t\tbasic_machine=hppa1.1-hp\n\t\t;;\n\thp9k8[0-9][0-9] | hp8[0-9][0-9])\n\t\tbasic_machine=hppa1.0-hp\n\t\t;;\n\thppa-next)\n\t\tos=-nextstep3\n\t\t;;\n\thppaosf)\n\t\tbasic_machine=hppa1.1-hp\n\t\tos=-osf\n\t\t;;\n\thppro)\n\t\tbasic_machine=hppa1.1-hp\n\t\tos=-proelf\n\t\t;;\n\ti370-ibm* | ibm*)\n\t\tbasic_machine=i370-ibm\n\t\t;;\n\ti*86v32)\n\t\tbasic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`\n\t\tos=-sysv32\n\t\t;;\n\ti*86v4*)\n\t\tbasic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`\n\t\tos=-sysv4\n\t\t;;\n\ti*86v)\n\t\tbasic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`\n\t\tos=-sysv\n\t\t;;\n\ti*86sol2)\n\t\tbasic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`\n\t\tos=-solaris2\n\t\t;;\n\ti386mach)\n\t\tbasic_machine=i386-mach\n\t\tos=-mach\n\t\t;;\n\ti386-vsta | vsta)\n\t\tbasic_machine=i386-unknown\n\t\tos=-vsta\n\t\t;;\n\tiris | iris4d)\n\t\tbasic_machine=mips-sgi\n\t\tcase $os in\n\t\t    -irix*)\n\t\t\t;;\n\t\t    *)\n\t\t\tos=-irix4\n\t\t\t;;\n\t\tesac\n\t\t;;\n\tisi68 | isi)\n\t\tbasic_machine=m68k-isi\n\t\tos=-sysv\n\t\t;;\n\tm68knommu)\n\t\tbasic_machine=m68k-unknown\n\t\tos=-linux\n\t\t;;\n\tm68knommu-*)\n\t\tbasic_machine=m68k-`echo $basic_machine | sed 's/^[^-]*-//'`\n\t\tos=-linux\n\t\t;;\n\tm88k-omron*)\n\t\tbasic_machine=m88k-omron\n\t\t;;\n\tmagnum | m3230)\n\t\tbasic_machine=mips-mips\n\t\tos=-sysv\n\t\t;;\n\tmerlin)\n\t\tbasic_machine=ns32k-utek\n\t\tos=-sysv\n\t\t;;\n\tmicroblaze*)\n\t\tbasic_machine=microblaze-xilinx\n\t\t;;\n\tmingw64)\n\t\tbasic_machine=x86_64-pc\n\t\tos=-mingw64\n\t\t;;\n\tmingw32)\n\t\tbasic_machine=i686-pc\n\t\tos=-mingw32\n\t\t;;\n\tmingw32ce)\n\t\tbasic_machine=arm-unknown\n\t\tos=-mingw32ce\n\t\t;;\n\tminiframe)\n\t\tbasic_machine=m68000-convergent\n\t\t;;\n\t*mint | -mint[0-9]* | *MiNT | *MiNT[0-9]*)\n\t\tbasic_machine=m68k-atari\n\t\tos=-mint\n\t\t;;\n\tmips3*-*)\n\t\tbasic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'`\n\t\t;;\n\tmips3*)\n\t\tbasic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'`-unknown\n\t\t;;\n\tmonitor)\n\t\tbasic_machine=m68k-rom68k\n\t\tos=-coff\n\t\t;;\n\tmorphos)\n\t\tbasic_machine=powerpc-unknown\n\t\tos=-morphos\n\t\t;;\n\tmsdos)\n\t\tbasic_machine=i386-pc\n\t\tos=-msdos\n\t\t;;\n\tms1-*)\n\t\tbasic_machine=`echo $basic_machine | sed -e 's/ms1-/mt-/'`\n\t\t;;\n\tmsys)\n\t\tbasic_machine=i686-pc\n\t\tos=-msys\n\t\t;;\n\tmvs)\n\t\tbasic_machine=i370-ibm\n\t\tos=-mvs\n\t\t;;\n\tnacl)\n\t\tbasic_machine=le32-unknown\n\t\tos=-nacl\n\t\t;;\n\tncr3000)\n\t\tbasic_machine=i486-ncr\n\t\tos=-sysv4\n\t\t;;\n\tnetbsd386)\n\t\tbasic_machine=i386-unknown\n\t\tos=-netbsd\n\t\t;;\n\tnetwinder)\n\t\tbasic_machine=armv4l-rebel\n\t\tos=-linux\n\t\t;;\n\tnews | news700 | news800 | news900)\n\t\tbasic_machine=m68k-sony\n\t\tos=-newsos\n\t\t;;\n\tnews1000)\n\t\tbasic_machine=m68030-sony\n\t\tos=-newsos\n\t\t;;\n\tnews-3600 | risc-news)\n\t\tbasic_machine=mips-sony\n\t\tos=-newsos\n\t\t;;\n\tnecv70)\n\t\tbasic_machine=v70-nec\n\t\tos=-sysv\n\t\t;;\n\tnext | m*-next )\n\t\tbasic_machine=m68k-next\n\t\tcase $os in\n\t\t    -nextstep* )\n\t\t\t;;\n\t\t    -ns2*)\n\t\t      os=-nextstep2\n\t\t\t;;\n\t\t    *)\n\t\t      os=-nextstep3\n\t\t\t;;\n\t\tesac\n\t\t;;\n\tnh3000)\n\t\tbasic_machine=m68k-harris\n\t\tos=-cxux\n\t\t;;\n\tnh[45]000)\n\t\tbasic_machine=m88k-harris\n\t\tos=-cxux\n\t\t;;\n\tnindy960)\n\t\tbasic_machine=i960-intel\n\t\tos=-nindy\n\t\t;;\n\tmon960)\n\t\tbasic_machine=i960-intel\n\t\tos=-mon960\n\t\t;;\n\tnonstopux)\n\t\tbasic_machine=mips-compaq\n\t\tos=-nonstopux\n\t\t;;\n\tnp1)\n\t\tbasic_machine=np1-gould\n\t\t;;\n\tneo-tandem)\n\t\tbasic_machine=neo-tandem\n\t\t;;\n\tnse-tandem)\n\t\tbasic_machine=nse-tandem\n\t\t;;\n\tnsr-tandem)\n\t\tbasic_machine=nsr-tandem\n\t\t;;\n\top50n-* | op60c-*)\n\t\tbasic_machine=hppa1.1-oki\n\t\tos=-proelf\n\t\t;;\n\topenrisc | openrisc-*)\n\t\tbasic_machine=or32-unknown\n\t\t;;\n\tos400)\n\t\tbasic_machine=powerpc-ibm\n\t\tos=-os400\n\t\t;;\n\tOSE68000 | ose68000)\n\t\tbasic_machine=m68000-ericsson\n\t\tos=-ose\n\t\t;;\n\tos68k)\n\t\tbasic_machine=m68k-none\n\t\tos=-os68k\n\t\t;;\n\tpa-hitachi)\n\t\tbasic_machine=hppa1.1-hitachi\n\t\tos=-hiuxwe2\n\t\t;;\n\tparagon)\n\t\tbasic_machine=i860-intel\n\t\tos=-osf\n\t\t;;\n\tparisc)\n\t\tbasic_machine=hppa-unknown\n\t\tos=-linux\n\t\t;;\n\tparisc-*)\n\t\tbasic_machine=hppa-`echo $basic_machine | sed 's/^[^-]*-//'`\n\t\tos=-linux\n\t\t;;\n\tpbd)\n\t\tbasic_machine=sparc-tti\n\t\t;;\n\tpbb)\n\t\tbasic_machine=m68k-tti\n\t\t;;\n\tpc532 | pc532-*)\n\t\tbasic_machine=ns32k-pc532\n\t\t;;\n\tpc98)\n\t\tbasic_machine=i386-pc\n\t\t;;\n\tpc98-*)\n\t\tbasic_machine=i386-`echo $basic_machine | sed 's/^[^-]*-//'`\n\t\t;;\n\tpentium | p5 | k5 | k6 | nexgen | viac3)\n\t\tbasic_machine=i586-pc\n\t\t;;\n\tpentiumpro | p6 | 6x86 | athlon | athlon_*)\n\t\tbasic_machine=i686-pc\n\t\t;;\n\tpentiumii | pentium2 | pentiumiii | pentium3)\n\t\tbasic_machine=i686-pc\n\t\t;;\n\tpentium4)\n\t\tbasic_machine=i786-pc\n\t\t;;\n\tpentium-* | p5-* | k5-* | k6-* | nexgen-* | viac3-*)\n\t\tbasic_machine=i586-`echo $basic_machine | sed 's/^[^-]*-//'`\n\t\t;;\n\tpentiumpro-* | p6-* | 6x86-* | athlon-*)\n\t\tbasic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'`\n\t\t;;\n\tpentiumii-* | pentium2-* | pentiumiii-* | pentium3-*)\n\t\tbasic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'`\n\t\t;;\n\tpentium4-*)\n\t\tbasic_machine=i786-`echo $basic_machine | sed 's/^[^-]*-//'`\n\t\t;;\n\tpn)\n\t\tbasic_machine=pn-gould\n\t\t;;\n\tpower)\tbasic_machine=power-ibm\n\t\t;;\n\tppc | ppcbe)\tbasic_machine=powerpc-unknown\n\t\t;;\n\tppc-* | ppcbe-*)\n\t\tbasic_machine=powerpc-`echo $basic_machine | sed 's/^[^-]*-//'`\n\t\t;;\n\tppcle | powerpclittle | ppc-le | powerpc-little)\n\t\tbasic_machine=powerpcle-unknown\n\t\t;;\n\tppcle-* | powerpclittle-*)\n\t\tbasic_machine=powerpcle-`echo $basic_machine | sed 's/^[^-]*-//'`\n\t\t;;\n\tppc64)\tbasic_machine=powerpc64-unknown\n\t\t;;\n\tppc64-*) basic_machine=powerpc64-`echo $basic_machine | sed 's/^[^-]*-//'`\n\t\t;;\n\tppc64le | powerpc64little | ppc64-le | powerpc64-little)\n\t\tbasic_machine=powerpc64le-unknown\n\t\t;;\n\tppc64le-* | powerpc64little-*)\n\t\tbasic_machine=powerpc64le-`echo $basic_machine | sed 's/^[^-]*-//'`\n\t\t;;\n\tps2)\n\t\tbasic_machine=i386-ibm\n\t\t;;\n\tpw32)\n\t\tbasic_machine=i586-unknown\n\t\tos=-pw32\n\t\t;;\n\trdos | rdos64)\n\t\tbasic_machine=x86_64-pc\n\t\tos=-rdos\n\t\t;;\n\trdos32)\n\t\tbasic_machine=i386-pc\n\t\tos=-rdos\n\t\t;;\n\trom68k)\n\t\tbasic_machine=m68k-rom68k\n\t\tos=-coff\n\t\t;;\n\trm[46]00)\n\t\tbasic_machine=mips-siemens\n\t\t;;\n\trtpc | rtpc-*)\n\t\tbasic_machine=romp-ibm\n\t\t;;\n\ts390 | s390-*)\n\t\tbasic_machine=s390-ibm\n\t\t;;\n\ts390x | s390x-*)\n\t\tbasic_machine=s390x-ibm\n\t\t;;\n\tsa29200)\n\t\tbasic_machine=a29k-amd\n\t\tos=-udi\n\t\t;;\n\tsb1)\n\t\tbasic_machine=mipsisa64sb1-unknown\n\t\t;;\n\tsb1el)\n\t\tbasic_machine=mipsisa64sb1el-unknown\n\t\t;;\n\tsde)\n\t\tbasic_machine=mipsisa32-sde\n\t\tos=-elf\n\t\t;;\n\tsei)\n\t\tbasic_machine=mips-sei\n\t\tos=-seiux\n\t\t;;\n\tsequent)\n\t\tbasic_machine=i386-sequent\n\t\t;;\n\tsh)\n\t\tbasic_machine=sh-hitachi\n\t\tos=-hms\n\t\t;;\n\tsh5el)\n\t\tbasic_machine=sh5le-unknown\n\t\t;;\n\tsh64)\n\t\tbasic_machine=sh64-unknown\n\t\t;;\n\tsparclite-wrs | simso-wrs)\n\t\tbasic_machine=sparclite-wrs\n\t\tos=-vxworks\n\t\t;;\n\tsps7)\n\t\tbasic_machine=m68k-bull\n\t\tos=-sysv2\n\t\t;;\n\tspur)\n\t\tbasic_machine=spur-unknown\n\t\t;;\n\tst2000)\n\t\tbasic_machine=m68k-tandem\n\t\t;;\n\tstratus)\n\t\tbasic_machine=i860-stratus\n\t\tos=-sysv4\n\t\t;;\n\tstrongarm-* | thumb-*)\n\t\tbasic_machine=arm-`echo $basic_machine | sed 's/^[^-]*-//'`\n\t\t;;\n\tsun2)\n\t\tbasic_machine=m68000-sun\n\t\t;;\n\tsun2os3)\n\t\tbasic_machine=m68000-sun\n\t\tos=-sunos3\n\t\t;;\n\tsun2os4)\n\t\tbasic_machine=m68000-sun\n\t\tos=-sunos4\n\t\t;;\n\tsun3os3)\n\t\tbasic_machine=m68k-sun\n\t\tos=-sunos3\n\t\t;;\n\tsun3os4)\n\t\tbasic_machine=m68k-sun\n\t\tos=-sunos4\n\t\t;;\n\tsun4os3)\n\t\tbasic_machine=sparc-sun\n\t\tos=-sunos3\n\t\t;;\n\tsun4os4)\n\t\tbasic_machine=sparc-sun\n\t\tos=-sunos4\n\t\t;;\n\tsun4sol2)\n\t\tbasic_machine=sparc-sun\n\t\tos=-solaris2\n\t\t;;\n\tsun3 | sun3-*)\n\t\tbasic_machine=m68k-sun\n\t\t;;\n\tsun4)\n\t\tbasic_machine=sparc-sun\n\t\t;;\n\tsun386 | sun386i | roadrunner)\n\t\tbasic_machine=i386-sun\n\t\t;;\n\tsv1)\n\t\tbasic_machine=sv1-cray\n\t\tos=-unicos\n\t\t;;\n\tsymmetry)\n\t\tbasic_machine=i386-sequent\n\t\tos=-dynix\n\t\t;;\n\tt3e)\n\t\tbasic_machine=alphaev5-cray\n\t\tos=-unicos\n\t\t;;\n\tt90)\n\t\tbasic_machine=t90-cray\n\t\tos=-unicos\n\t\t;;\n\ttile*)\n\t\tbasic_machine=$basic_machine-unknown\n\t\tos=-linux-gnu\n\t\t;;\n\ttx39)\n\t\tbasic_machine=mipstx39-unknown\n\t\t;;\n\ttx39el)\n\t\tbasic_machine=mipstx39el-unknown\n\t\t;;\n\ttoad1)\n\t\tbasic_machine=pdp10-xkl\n\t\tos=-tops20\n\t\t;;\n\ttower | tower-32)\n\t\tbasic_machine=m68k-ncr\n\t\t;;\n\ttpf)\n\t\tbasic_machine=s390x-ibm\n\t\tos=-tpf\n\t\t;;\n\tudi29k)\n\t\tbasic_machine=a29k-amd\n\t\tos=-udi\n\t\t;;\n\tultra3)\n\t\tbasic_machine=a29k-nyu\n\t\tos=-sym1\n\t\t;;\n\tv810 | necv810)\n\t\tbasic_machine=v810-nec\n\t\tos=-none\n\t\t;;\n\tvaxv)\n\t\tbasic_machine=vax-dec\n\t\tos=-sysv\n\t\t;;\n\tvms)\n\t\tbasic_machine=vax-dec\n\t\tos=-vms\n\t\t;;\n\tvpp*|vx|vx-*)\n\t\tbasic_machine=f301-fujitsu\n\t\t;;\n\tvxworks960)\n\t\tbasic_machine=i960-wrs\n\t\tos=-vxworks\n\t\t;;\n\tvxworks68)\n\t\tbasic_machine=m68k-wrs\n\t\tos=-vxworks\n\t\t;;\n\tvxworks29k)\n\t\tbasic_machine=a29k-wrs\n\t\tos=-vxworks\n\t\t;;\n\tw65*)\n\t\tbasic_machine=w65-wdc\n\t\tos=-none\n\t\t;;\n\tw89k-*)\n\t\tbasic_machine=hppa1.1-winbond\n\t\tos=-proelf\n\t\t;;\n\txbox)\n\t\tbasic_machine=i686-pc\n\t\tos=-mingw32\n\t\t;;\n\txps | xps100)\n\t\tbasic_machine=xps100-honeywell\n\t\t;;\n\txscale-* | xscalee[bl]-*)\n\t\tbasic_machine=`echo $basic_machine | sed 's/^xscale/arm/'`\n\t\t;;\n\tymp)\n\t\tbasic_machine=ymp-cray\n\t\tos=-unicos\n\t\t;;\n\tz8k-*-coff)\n\t\tbasic_machine=z8k-unknown\n\t\tos=-sim\n\t\t;;\n\tz80-*-coff)\n\t\tbasic_machine=z80-unknown\n\t\tos=-sim\n\t\t;;\n\tnone)\n\t\tbasic_machine=none-none\n\t\tos=-none\n\t\t;;\n\n# Here we handle the default manufacturer of certain CPU types.  It is in\n# some cases the only manufacturer, in others, it is the most popular.\n\tw89k)\n\t\tbasic_machine=hppa1.1-winbond\n\t\t;;\n\top50n)\n\t\tbasic_machine=hppa1.1-oki\n\t\t;;\n\top60c)\n\t\tbasic_machine=hppa1.1-oki\n\t\t;;\n\tromp)\n\t\tbasic_machine=romp-ibm\n\t\t;;\n\tmmix)\n\t\tbasic_machine=mmix-knuth\n\t\t;;\n\trs6000)\n\t\tbasic_machine=rs6000-ibm\n\t\t;;\n\tvax)\n\t\tbasic_machine=vax-dec\n\t\t;;\n\tpdp10)\n\t\t# there are many clones, so DEC is not a safe bet\n\t\tbasic_machine=pdp10-unknown\n\t\t;;\n\tpdp11)\n\t\tbasic_machine=pdp11-dec\n\t\t;;\n\twe32k)\n\t\tbasic_machine=we32k-att\n\t\t;;\n\tsh[1234] | sh[24]a | sh[24]aeb | sh[34]eb | sh[1234]le | sh[23]ele)\n\t\tbasic_machine=sh-unknown\n\t\t;;\n\tsparc | sparcv8 | sparcv9 | sparcv9b | sparcv9v)\n\t\tbasic_machine=sparc-sun\n\t\t;;\n\tcydra)\n\t\tbasic_machine=cydra-cydrome\n\t\t;;\n\torion)\n\t\tbasic_machine=orion-highlevel\n\t\t;;\n\torion105)\n\t\tbasic_machine=clipper-highlevel\n\t\t;;\n\tmac | mpw | mac-mpw)\n\t\tbasic_machine=m68k-apple\n\t\t;;\n\tpmac | pmac-mpw)\n\t\tbasic_machine=powerpc-apple\n\t\t;;\n\t*-unknown)\n\t\t# Make sure to match an already-canonicalized machine name.\n\t\t;;\n\t*)\n\t\techo Invalid configuration \\`$1\\': machine \\`$basic_machine\\' not recognized 1>&2\n\t\texit 1\n\t\t;;\nesac\n\n# Here we canonicalize certain aliases for manufacturers.\ncase $basic_machine in\n\t*-digital*)\n\t\tbasic_machine=`echo $basic_machine | sed 's/digital.*/dec/'`\n\t\t;;\n\t*-commodore*)\n\t\tbasic_machine=`echo $basic_machine | sed 's/commodore.*/cbm/'`\n\t\t;;\n\t*)\n\t\t;;\nesac\n\n# Decode manufacturer-specific aliases for certain operating systems.\n\nif [ x\"$os\" != x\"\" ]\nthen\ncase $os in\n\t# First match some system type aliases\n\t# that might get confused with valid system types.\n\t# -solaris* is a basic system type, with this one exception.\n\t-auroraux)\n\t\tos=-auroraux\n\t\t;;\n\t-solaris1 | -solaris1.*)\n\t\tos=`echo $os | sed -e 's|solaris1|sunos4|'`\n\t\t;;\n\t-solaris)\n\t\tos=-solaris2\n\t\t;;\n\t-svr4*)\n\t\tos=-sysv4\n\t\t;;\n\t-unixware*)\n\t\tos=-sysv4.2uw\n\t\t;;\n\t-gnu/linux*)\n\t\tos=`echo $os | sed -e 's|gnu/linux|linux-gnu|'`\n\t\t;;\n\t# First accept the basic system types.\n\t# The portable systems comes first.\n\t# Each alternative MUST END IN A *, to match a version number.\n\t# -sysv* is not here because it comes later, after sysvr4.\n\t-gnu* | -bsd* | -mach* | -minix* | -genix* | -ultrix* | -irix* \\\n\t      | -*vms* | -sco* | -esix* | -isc* | -aix* | -cnk* | -sunos | -sunos[34]*\\\n\t      | -hpux* | -unos* | -osf* | -luna* | -dgux* | -auroraux* | -solaris* \\\n\t      | -sym* | -kopensolaris* | -plan9* \\\n\t      | -amigaos* | -amigados* | -msdos* | -newsos* | -unicos* | -aof* \\\n\t      | -aos* | -aros* \\\n\t      | -nindy* | -vxsim* | -vxworks* | -ebmon* | -hms* | -mvs* \\\n\t      | -clix* | -riscos* | -uniplus* | -iris* | -rtu* | -xenix* \\\n\t      | -hiux* | -386bsd* | -knetbsd* | -mirbsd* | -netbsd* \\\n\t      | -bitrig* | -openbsd* | -solidbsd* \\\n\t      | -ekkobsd* | -kfreebsd* | -freebsd* | -riscix* | -lynxos* \\\n\t      | -bosx* | -nextstep* | -cxux* | -aout* | -elf* | -oabi* \\\n\t      | -ptx* | -coff* | -ecoff* | -winnt* | -domain* | -vsta* \\\n\t      | -udi* | -eabi* | -lites* | -ieee* | -go32* | -aux* \\\n\t      | -chorusos* | -chorusrdb* | -cegcc* \\\n\t      | -cygwin* | -msys* | -pe* | -psos* | -moss* | -proelf* | -rtems* \\\n\t      | -mingw32* | -mingw64* | -linux-gnu* | -linux-android* \\\n\t      | -linux-newlib* | -linux-musl* | -linux-uclibc* \\\n\t      | -uxpv* | -beos* | -mpeix* | -udk* \\\n\t      | -interix* | -uwin* | -mks* | -rhapsody* | -darwin* | -opened* \\\n\t      | -openstep* | -oskit* | -conix* | -pw32* | -nonstopux* \\\n\t      | -storm-chaos* | -tops10* | -tenex* | -tops20* | -its* \\\n\t      | -os2* | -vos* | -palmos* | -uclinux* | -nucleus* \\\n\t      | -morphos* | -superux* | -rtmk* | -rtmk-nova* | -windiss* \\\n\t      | -powermax* | -dnix* | -nx6 | -nx7 | -sei* | -dragonfly* \\\n\t      | -skyos* | -haiku* | -rdos* | -toppers* | -drops* | -es* | -tirtos*)\n\t# Remember, each alternative MUST END IN *, to match a version number.\n\t\t;;\n\t-qnx*)\n\t\tcase $basic_machine in\n\t\t    x86-* | i*86-*)\n\t\t\t;;\n\t\t    *)\n\t\t\tos=-nto$os\n\t\t\t;;\n\t\tesac\n\t\t;;\n\t-nto-qnx*)\n\t\t;;\n\t-nto*)\n\t\tos=`echo $os | sed -e 's|nto|nto-qnx|'`\n\t\t;;\n\t-sim | -es1800* | -hms* | -xray | -os68k* | -none* | -v88r* \\\n\t      | -windows* | -osx | -abug | -netware* | -os9* | -beos* | -haiku* \\\n\t      | -macos* | -mpw* | -magic* | -mmixware* | -mon960* | -lnews*)\n\t\t;;\n\t-mac*)\n\t\tos=`echo $os | sed -e 's|mac|macos|'`\n\t\t;;\n\t# Apple iOS\n\t-ios*)\n\t\t;;\n\t-linux-dietlibc)\n\t\tos=-linux-dietlibc\n\t\t;;\n\t-linux*)\n\t\tos=`echo $os | sed -e 's|linux|linux-gnu|'`\n\t\t;;\n\t-sunos5*)\n\t\tos=`echo $os | sed -e 's|sunos5|solaris2|'`\n\t\t;;\n\t-sunos6*)\n\t\tos=`echo $os | sed -e 's|sunos6|solaris3|'`\n\t\t;;\n\t-opened*)\n\t\tos=-openedition\n\t\t;;\n\t-os400*)\n\t\tos=-os400\n\t\t;;\n\t-wince*)\n\t\tos=-wince\n\t\t;;\n\t-osfrose*)\n\t\tos=-osfrose\n\t\t;;\n\t-osf*)\n\t\tos=-osf\n\t\t;;\n\t-utek*)\n\t\tos=-bsd\n\t\t;;\n\t-dynix*)\n\t\tos=-bsd\n\t\t;;\n\t-acis*)\n\t\tos=-aos\n\t\t;;\n\t-atheos*)\n\t\tos=-atheos\n\t\t;;\n\t-syllable*)\n\t\tos=-syllable\n\t\t;;\n\t-386bsd)\n\t\tos=-bsd\n\t\t;;\n\t-ctix* | -uts*)\n\t\tos=-sysv\n\t\t;;\n\t-nova*)\n\t\tos=-rtmk-nova\n\t\t;;\n\t-ns2 )\n\t\tos=-nextstep2\n\t\t;;\n\t-nsk*)\n\t\tos=-nsk\n\t\t;;\n\t# Preserve the version number of sinix5.\n\t-sinix5.*)\n\t\tos=`echo $os | sed -e 's|sinix|sysv|'`\n\t\t;;\n\t-sinix*)\n\t\tos=-sysv4\n\t\t;;\n\t-tpf*)\n\t\tos=-tpf\n\t\t;;\n\t-triton*)\n\t\tos=-sysv3\n\t\t;;\n\t-oss*)\n\t\tos=-sysv3\n\t\t;;\n\t-svr4)\n\t\tos=-sysv4\n\t\t;;\n\t-svr3)\n\t\tos=-sysv3\n\t\t;;\n\t-sysvr4)\n\t\tos=-sysv4\n\t\t;;\n\t# This must come after -sysvr4.\n\t-sysv*)\n\t\t;;\n\t-ose*)\n\t\tos=-ose\n\t\t;;\n\t-es1800*)\n\t\tos=-ose\n\t\t;;\n\t-xenix)\n\t\tos=-xenix\n\t\t;;\n\t-*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*)\n\t\tos=-mint\n\t\t;;\n\t-aros*)\n\t\tos=-aros\n\t\t;;\n\t-zvmoe)\n\t\tos=-zvmoe\n\t\t;;\n\t-dicos*)\n\t\tos=-dicos\n\t\t;;\n\t-nacl*)\n\t\t;;\n\t-none)\n\t\t;;\n\t*)\n\t\t# Get rid of the `-' at the beginning of $os.\n\t\tos=`echo $os | sed 's/[^-]*-//'`\n\t\techo Invalid configuration \\`$1\\': system \\`$os\\' not recognized 1>&2\n\t\texit 1\n\t\t;;\nesac\nelse\n\n# Here we handle the default operating systems that come with various machines.\n# The value should be what the vendor currently ships out the door with their\n# machine or put another way, the most popular os provided with the machine.\n\n# Note that if you're going to try to match \"-MANUFACTURER\" here (say,\n# \"-sun\"), then you have to tell the case statement up towards the top\n# that MANUFACTURER isn't an operating system.  Otherwise, code above\n# will signal an error saying that MANUFACTURER isn't an operating\n# system, and we'll never get to this point.\n\ncase $basic_machine in\n\tscore-*)\n\t\tos=-elf\n\t\t;;\n\tspu-*)\n\t\tos=-elf\n\t\t;;\n\t*-acorn)\n\t\tos=-riscix1.2\n\t\t;;\n\tarm*-rebel)\n\t\tos=-linux\n\t\t;;\n\tarm*-semi)\n\t\tos=-aout\n\t\t;;\n\tc4x-* | tic4x-*)\n\t\tos=-coff\n\t\t;;\n\tc8051-*)\n\t\tos=-elf\n\t\t;;\n\thexagon-*)\n\t\tos=-elf\n\t\t;;\n\ttic54x-*)\n\t\tos=-coff\n\t\t;;\n\ttic55x-*)\n\t\tos=-coff\n\t\t;;\n\ttic6x-*)\n\t\tos=-coff\n\t\t;;\n\t# This must come before the *-dec entry.\n\tpdp10-*)\n\t\tos=-tops20\n\t\t;;\n\tpdp11-*)\n\t\tos=-none\n\t\t;;\n\t*-dec | vax-*)\n\t\tos=-ultrix4.2\n\t\t;;\n\tm68*-apollo)\n\t\tos=-domain\n\t\t;;\n\ti386-sun)\n\t\tos=-sunos4.0.2\n\t\t;;\n\tm68000-sun)\n\t\tos=-sunos3\n\t\t;;\n\tm68*-cisco)\n\t\tos=-aout\n\t\t;;\n\tmep-*)\n\t\tos=-elf\n\t\t;;\n\tmips*-cisco)\n\t\tos=-elf\n\t\t;;\n\tmips*-*)\n\t\tos=-elf\n\t\t;;\n\tor32-*)\n\t\tos=-coff\n\t\t;;\n\t*-tti)\t# must be before sparc entry or we get the wrong os.\n\t\tos=-sysv3\n\t\t;;\n\tsparc-* | *-sun)\n\t\tos=-sunos4.1.1\n\t\t;;\n\t*-be)\n\t\tos=-beos\n\t\t;;\n\t*-haiku)\n\t\tos=-haiku\n\t\t;;\n\t*-ibm)\n\t\tos=-aix\n\t\t;;\n\t*-knuth)\n\t\tos=-mmixware\n\t\t;;\n\t*-wec)\n\t\tos=-proelf\n\t\t;;\n\t*-winbond)\n\t\tos=-proelf\n\t\t;;\n\t*-oki)\n\t\tos=-proelf\n\t\t;;\n\t*-hp)\n\t\tos=-hpux\n\t\t;;\n\t*-hitachi)\n\t\tos=-hiux\n\t\t;;\n\ti860-* | *-att | *-ncr | *-altos | *-motorola | *-convergent)\n\t\tos=-sysv\n\t\t;;\n\t*-cbm)\n\t\tos=-amigaos\n\t\t;;\n\t*-dg)\n\t\tos=-dgux\n\t\t;;\n\t*-dolphin)\n\t\tos=-sysv3\n\t\t;;\n\tm68k-ccur)\n\t\tos=-rtu\n\t\t;;\n\tm88k-omron*)\n\t\tos=-luna\n\t\t;;\n\t*-next )\n\t\tos=-nextstep\n\t\t;;\n\t*-sequent)\n\t\tos=-ptx\n\t\t;;\n\t*-crds)\n\t\tos=-unos\n\t\t;;\n\t*-ns)\n\t\tos=-genix\n\t\t;;\n\ti370-*)\n\t\tos=-mvs\n\t\t;;\n\t*-next)\n\t\tos=-nextstep3\n\t\t;;\n\t*-gould)\n\t\tos=-sysv\n\t\t;;\n\t*-highlevel)\n\t\tos=-bsd\n\t\t;;\n\t*-encore)\n\t\tos=-bsd\n\t\t;;\n\t*-sgi)\n\t\tos=-irix\n\t\t;;\n\t*-siemens)\n\t\tos=-sysv4\n\t\t;;\n\t*-masscomp)\n\t\tos=-rtu\n\t\t;;\n\tf30[01]-fujitsu | f700-fujitsu)\n\t\tos=-uxpv\n\t\t;;\n\t*-rom68k)\n\t\tos=-coff\n\t\t;;\n\t*-*bug)\n\t\tos=-coff\n\t\t;;\n\t*-apple)\n\t\tos=-macos\n\t\t;;\n\t*-atari*)\n\t\tos=-mint\n\t\t;;\n\t*)\n\t\tos=-none\n\t\t;;\nesac\nfi\n\n# Here we handle the case where we know the os, and the CPU type, but not the\n# manufacturer.  We pick the logical manufacturer.\nvendor=unknown\ncase $basic_machine in\n\t*-unknown)\n\t\tcase $os in\n\t\t\t-riscix*)\n\t\t\t\tvendor=acorn\n\t\t\t\t;;\n\t\t\t-sunos*)\n\t\t\t\tvendor=sun\n\t\t\t\t;;\n\t\t\t-cnk*|-aix*)\n\t\t\t\tvendor=ibm\n\t\t\t\t;;\n\t\t\t-beos*)\n\t\t\t\tvendor=be\n\t\t\t\t;;\n\t\t\t-hpux*)\n\t\t\t\tvendor=hp\n\t\t\t\t;;\n\t\t\t-mpeix*)\n\t\t\t\tvendor=hp\n\t\t\t\t;;\n\t\t\t-hiux*)\n\t\t\t\tvendor=hitachi\n\t\t\t\t;;\n\t\t\t-unos*)\n\t\t\t\tvendor=crds\n\t\t\t\t;;\n\t\t\t-dgux*)\n\t\t\t\tvendor=dg\n\t\t\t\t;;\n\t\t\t-luna*)\n\t\t\t\tvendor=omron\n\t\t\t\t;;\n\t\t\t-genix*)\n\t\t\t\tvendor=ns\n\t\t\t\t;;\n\t\t\t-mvs* | -opened*)\n\t\t\t\tvendor=ibm\n\t\t\t\t;;\n\t\t\t-os400*)\n\t\t\t\tvendor=ibm\n\t\t\t\t;;\n\t\t\t-ptx*)\n\t\t\t\tvendor=sequent\n\t\t\t\t;;\n\t\t\t-tpf*)\n\t\t\t\tvendor=ibm\n\t\t\t\t;;\n\t\t\t-vxsim* | -vxworks* | -windiss*)\n\t\t\t\tvendor=wrs\n\t\t\t\t;;\n\t\t\t-aux*)\n\t\t\t\tvendor=apple\n\t\t\t\t;;\n\t\t\t-hms*)\n\t\t\t\tvendor=hitachi\n\t\t\t\t;;\n\t\t\t-mpw* | -macos*)\n\t\t\t\tvendor=apple\n\t\t\t\t;;\n\t\t\t-*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*)\n\t\t\t\tvendor=atari\n\t\t\t\t;;\n\t\t\t-vos*)\n\t\t\t\tvendor=stratus\n\t\t\t\t;;\n\t\tesac\n\t\tbasic_machine=`echo $basic_machine | sed \"s/unknown/$vendor/\"`\n\t\t;;\nesac\n\necho $basic_machine$os\nexit\n\n# Local variables:\n# eval: (add-hook 'write-file-hooks 'time-stamp)\n# time-stamp-start: \"timestamp='\"\n# time-stamp-format: \"%:y-%02m-%02d\"\n# time-stamp-end: \"'\"\n# End:\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/deps/jemalloc/build-aux/install-sh",
    "content": "#! /bin/sh\n#\n# install - install a program, script, or datafile\n# This comes from X11R5 (mit/util/scripts/install.sh).\n#\n# Copyright 1991 by the Massachusetts Institute of Technology\n#\n# Permission to use, copy, modify, distribute, and sell this software and its\n# documentation for any purpose is hereby granted without fee, provided that\n# the above copyright notice appear in all copies and that both that\n# copyright notice and this permission notice appear in supporting\n# documentation, and that the name of M.I.T. not be used in advertising or\n# publicity pertaining to distribution of the software without specific,\n# written prior permission.  M.I.T. makes no representations about the\n# suitability of this software for any purpose.  It is provided \"as is\"\n# without express or implied warranty.\n#\n# Calling this script install-sh is preferred over install.sh, to prevent\n# `make' implicit rules from creating a file called install from it\n# when there is no Makefile.\n#\n# This script is compatible with the BSD install script, but was written\n# from scratch.  It can only install one file at a time, a restriction\n# shared with many OS's install programs.\n\n\n# set DOITPROG to echo to test this script\n\n# Don't use :- since 4.3BSD and earlier shells don't like it.\ndoit=\"${DOITPROG-}\"\n\n\n# put in absolute paths if you don't have them in your path; or use env. vars.\n\nmvprog=\"${MVPROG-mv}\"\ncpprog=\"${CPPROG-cp}\"\nchmodprog=\"${CHMODPROG-chmod}\"\nchownprog=\"${CHOWNPROG-chown}\"\nchgrpprog=\"${CHGRPPROG-chgrp}\"\nstripprog=\"${STRIPPROG-strip}\"\nrmprog=\"${RMPROG-rm}\"\nmkdirprog=\"${MKDIRPROG-mkdir}\"\n\ntransformbasename=\"\"\ntransform_arg=\"\"\ninstcmd=\"$mvprog\"\nchmodcmd=\"$chmodprog 0755\"\nchowncmd=\"\"\nchgrpcmd=\"\"\nstripcmd=\"\"\nrmcmd=\"$rmprog -f\"\nmvcmd=\"$mvprog\"\nsrc=\"\"\ndst=\"\"\ndir_arg=\"\"\n\nwhile [ x\"$1\" != x ]; do\n    case $1 in\n\t-c) instcmd=\"$cpprog\"\n\t    shift\n\t    continue;;\n\n\t-d) dir_arg=true\n\t    shift\n\t    continue;;\n\n\t-m) chmodcmd=\"$chmodprog $2\"\n\t    shift\n\t    shift\n\t    continue;;\n\n\t-o) chowncmd=\"$chownprog $2\"\n\t    shift\n\t    shift\n\t    continue;;\n\n\t-g) chgrpcmd=\"$chgrpprog $2\"\n\t    shift\n\t    shift\n\t    continue;;\n\n\t-s) stripcmd=\"$stripprog\"\n\t    shift\n\t    continue;;\n\n\t-t=*) transformarg=`echo $1 | sed 's/-t=//'`\n\t    shift\n\t    continue;;\n\n\t-b=*) transformbasename=`echo $1 | sed 's/-b=//'`\n\t    shift\n\t    continue;;\n\n\t*)  if [ x\"$src\" = x ]\n\t    then\n\t\tsrc=$1\n\t    else\n\t\t# this colon is to work around a 386BSD /bin/sh bug\n\t\t:\n\t\tdst=$1\n\t    fi\n\t    shift\n\t    continue;;\n    esac\ndone\n\nif [ x\"$src\" = x ]\nthen\n\techo \"install:\tno input file specified\"\n\texit 1\nelse\n\ttrue\nfi\n\nif [ x\"$dir_arg\" != x ]; then\n\tdst=$src\n\tsrc=\"\"\n\t\n\tif [ -d $dst ]; then\n\t\tinstcmd=:\n\telse\n\t\tinstcmd=mkdir\n\tfi\nelse\n\n# Waiting for this to be detected by the \"$instcmd $src $dsttmp\" command\n# might cause directories to be created, which would be especially bad \n# if $src (and thus $dsttmp) contains '*'.\n\n\tif [ -f $src -o -d $src ]\n\tthen\n\t\ttrue\n\telse\n\t\techo \"install:  $src does not exist\"\n\t\texit 1\n\tfi\n\t\n\tif [ x\"$dst\" = x ]\n\tthen\n\t\techo \"install:\tno destination specified\"\n\t\texit 1\n\telse\n\t\ttrue\n\tfi\n\n# If destination is a directory, append the input filename; if your system\n# does not like double slashes in filenames, you may need to add some logic\n\n\tif [ -d $dst ]\n\tthen\n\t\tdst=\"$dst\"/`basename $src`\n\telse\n\t\ttrue\n\tfi\nfi\n\n## this sed command emulates the dirname command\ndstdir=`echo $dst | sed -e 's,[^/]*$,,;s,/$,,;s,^$,.,'`\n\n# Make sure that the destination directory exists.\n#  this part is taken from Noah Friedman's mkinstalldirs script\n\n# Skip lots of stat calls in the usual case.\nif [ ! -d \"$dstdir\" ]; then\ndefaultIFS='\t\n'\nIFS=\"${IFS-${defaultIFS}}\"\n\noIFS=\"${IFS}\"\n# Some sh's can't handle IFS=/ for some reason.\nIFS='%'\nset - `echo ${dstdir} | sed -e 's@/@%@g' -e 's@^%@/@'`\nIFS=\"${oIFS}\"\n\npathcomp=''\n\nwhile [ $# -ne 0 ] ; do\n\tpathcomp=\"${pathcomp}${1}\"\n\tshift\n\n\tif [ ! -d \"${pathcomp}\" ] ;\n        then\n\t\t$mkdirprog \"${pathcomp}\"\n\telse\n\t\ttrue\n\tfi\n\n\tpathcomp=\"${pathcomp}/\"\ndone\nfi\n\nif [ x\"$dir_arg\" != x ]\nthen\n\t$doit $instcmd $dst &&\n\n\tif [ x\"$chowncmd\" != x ]; then $doit $chowncmd $dst; else true ; fi &&\n\tif [ x\"$chgrpcmd\" != x ]; then $doit $chgrpcmd $dst; else true ; fi &&\n\tif [ x\"$stripcmd\" != x ]; then $doit $stripcmd $dst; else true ; fi &&\n\tif [ x\"$chmodcmd\" != x ]; then $doit $chmodcmd $dst; else true ; fi\nelse\n\n# If we're going to rename the final executable, determine the name now.\n\n\tif [ x\"$transformarg\" = x ] \n\tthen\n\t\tdstfile=`basename $dst`\n\telse\n\t\tdstfile=`basename $dst $transformbasename | \n\t\t\tsed $transformarg`$transformbasename\n\tfi\n\n# don't allow the sed command to completely eliminate the filename\n\n\tif [ x\"$dstfile\" = x ] \n\tthen\n\t\tdstfile=`basename $dst`\n\telse\n\t\ttrue\n\tfi\n\n# Make a temp file name in the proper directory.\n\n\tdsttmp=$dstdir/#inst.$$#\n\n# Move or copy the file name to the temp name\n\n\t$doit $instcmd $src $dsttmp &&\n\n\ttrap \"rm -f ${dsttmp}\" 0 &&\n\n# and set any options; do chmod last to preserve setuid bits\n\n# If any of these fail, we abort the whole thing.  If we want to\n# ignore errors from any of these, just make sure not to ignore\n# errors from the above \"$doit $instcmd $src $dsttmp\" command.\n\n\tif [ x\"$chowncmd\" != x ]; then $doit $chowncmd $dsttmp; else true;fi &&\n\tif [ x\"$chgrpcmd\" != x ]; then $doit $chgrpcmd $dsttmp; else true;fi &&\n\tif [ x\"$stripcmd\" != x ]; then $doit $stripcmd $dsttmp; else true;fi &&\n\tif [ x\"$chmodcmd\" != x ]; then $doit $chmodcmd $dsttmp; else true;fi &&\n\n# Now rename the file to the real destination.\n\n\t$doit $rmcmd -f $dstdir/$dstfile &&\n\t$doit $mvcmd $dsttmp $dstdir/$dstfile \n\nfi &&\n\n\nexit 0\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/deps/jemalloc/config.stamp.in",
    "content": ""
  },
  {
    "path": "extern/deprecated/redis-3.2.4/deps/jemalloc/configure.ac",
    "content": "dnl Process this file with autoconf to produce a configure script.\nAC_INIT([Makefile.in])\n\nAC_CONFIG_AUX_DIR([build-aux])\n\ndnl ============================================================================\ndnl Custom macro definitions.\n\ndnl JE_CFLAGS_APPEND(cflag)\nAC_DEFUN([JE_CFLAGS_APPEND],\n[\nAC_MSG_CHECKING([whether compiler supports $1])\nTCFLAGS=\"${CFLAGS}\"\nif test \"x${CFLAGS}\" = \"x\" ; then\n  CFLAGS=\"$1\"\nelse\n  CFLAGS=\"${CFLAGS} $1\"\nfi\nAC_COMPILE_IFELSE([AC_LANG_PROGRAM(\n[[\n]], [[\n    return 0;\n]])],\n              [je_cv_cflags_appended=$1]\n              AC_MSG_RESULT([yes]),\n              [je_cv_cflags_appended=]\n              AC_MSG_RESULT([no])\n              [CFLAGS=\"${TCFLAGS}\"]\n)\n])\n\ndnl JE_COMPILABLE(label, hcode, mcode, rvar)\ndnl \ndnl Use AC_LINK_IFELSE() rather than AC_COMPILE_IFELSE() so that linker errors\ndnl cause failure.\nAC_DEFUN([JE_COMPILABLE],\n[\nAC_CACHE_CHECK([whether $1 is compilable],\n               [$4],\n               [AC_LINK_IFELSE([AC_LANG_PROGRAM([$2],\n                                                [$3])],\n                               [$4=yes],\n                               [$4=no])])\n])\n\ndnl ============================================================================\n\nCONFIG=`echo ${ac_configure_args} | sed -e 's#'\"'\"'\\([^ ]*\\)'\"'\"'#\\1#g'`\nAC_SUBST([CONFIG])\n\ndnl Library revision.\nrev=2\nAC_SUBST([rev])\n\nsrcroot=$srcdir\nif test \"x${srcroot}\" = \"x.\" ; then\n  srcroot=\"\"\nelse\n  srcroot=\"${srcroot}/\"\nfi\nAC_SUBST([srcroot])\nabs_srcroot=\"`cd \\\"${srcdir}\\\"; pwd`/\"\nAC_SUBST([abs_srcroot])\n\nobjroot=\"\"\nAC_SUBST([objroot])\nabs_objroot=\"`pwd`/\"\nAC_SUBST([abs_objroot])\n\ndnl Munge install path variables.\nif test \"x$prefix\" = \"xNONE\" ; then\n  prefix=\"/usr/local\"\nfi\nif test \"x$exec_prefix\" = \"xNONE\" ; then\n  exec_prefix=$prefix\nfi\nPREFIX=$prefix\nAC_SUBST([PREFIX])\nBINDIR=`eval echo $bindir`\nBINDIR=`eval echo $BINDIR`\nAC_SUBST([BINDIR])\nINCLUDEDIR=`eval echo $includedir`\nINCLUDEDIR=`eval echo $INCLUDEDIR`\nAC_SUBST([INCLUDEDIR])\nLIBDIR=`eval echo $libdir`\nLIBDIR=`eval echo $LIBDIR`\nAC_SUBST([LIBDIR])\nDATADIR=`eval echo $datadir`\nDATADIR=`eval echo $DATADIR`\nAC_SUBST([DATADIR])\nMANDIR=`eval echo $mandir`\nMANDIR=`eval echo $MANDIR`\nAC_SUBST([MANDIR])\n\ndnl Support for building documentation.\nAC_PATH_PROG([XSLTPROC], [xsltproc], [false], [$PATH])\nif test -d \"/usr/share/xml/docbook/stylesheet/docbook-xsl\" ; then\n  DEFAULT_XSLROOT=\"/usr/share/xml/docbook/stylesheet/docbook-xsl\"\nelif test -d \"/usr/share/sgml/docbook/xsl-stylesheets\" ; then\n  DEFAULT_XSLROOT=\"/usr/share/sgml/docbook/xsl-stylesheets\"\nelse\n  dnl Documentation building will fail if this default gets used.\n  DEFAULT_XSLROOT=\"\"\nfi\nAC_ARG_WITH([xslroot],\n  [AS_HELP_STRING([--with-xslroot=<path>], [XSL stylesheet root path])], [\nif test \"x$with_xslroot\" = \"xno\" ; then\n  XSLROOT=\"${DEFAULT_XSLROOT}\"\nelse\n  XSLROOT=\"${with_xslroot}\"\nfi\n],\n  XSLROOT=\"${DEFAULT_XSLROOT}\"\n)\nAC_SUBST([XSLROOT])\n\ndnl If CFLAGS isn't defined, set CFLAGS to something reasonable.  Otherwise,\ndnl just prevent autoconf from molesting CFLAGS.\nCFLAGS=$CFLAGS\nAC_PROG_CC\nif test \"x$GCC\" != \"xyes\" ; then\n  AC_CACHE_CHECK([whether compiler is MSVC],\n                 [je_cv_msvc],\n                 [AC_COMPILE_IFELSE([AC_LANG_PROGRAM([],\n                                                     [\n#ifndef _MSC_VER\n  int fail[-1];\n#endif\n])],\n                               [je_cv_msvc=yes],\n                               [je_cv_msvc=no])])\nfi\n\nif test \"x$CFLAGS\" = \"x\" ; then\n  no_CFLAGS=\"yes\"\n  if test \"x$GCC\" = \"xyes\" ; then\n    JE_CFLAGS_APPEND([-std=gnu99])\n    if test \"x$je_cv_cflags_appended\" = \"x-std=gnu99\" ; then\n      AC_DEFINE_UNQUOTED([JEMALLOC_HAS_RESTRICT])\n    fi\n    JE_CFLAGS_APPEND([-Wall])\n    JE_CFLAGS_APPEND([-Werror=declaration-after-statement])\n    JE_CFLAGS_APPEND([-Wshorten-64-to-32])\n    JE_CFLAGS_APPEND([-Wsign-compare])\n    JE_CFLAGS_APPEND([-pipe])\n    JE_CFLAGS_APPEND([-g3])\n  elif test \"x$je_cv_msvc\" = \"xyes\" ; then\n    CC=\"$CC -nologo\"\n    JE_CFLAGS_APPEND([-Zi])\n    JE_CFLAGS_APPEND([-MT])\n    JE_CFLAGS_APPEND([-W3])\n    JE_CFLAGS_APPEND([-FS])\n    CPPFLAGS=\"$CPPFLAGS -I${srcdir}/include/msvc_compat\"\n  fi\nfi\ndnl Append EXTRA_CFLAGS to CFLAGS, if defined.\nif test \"x$EXTRA_CFLAGS\" != \"x\" ; then\n  JE_CFLAGS_APPEND([$EXTRA_CFLAGS])\nfi\nAC_PROG_CPP\n\nAC_C_BIGENDIAN([ac_cv_big_endian=1], [ac_cv_big_endian=0])\nif test \"x${ac_cv_big_endian}\" = \"x1\" ; then\n  AC_DEFINE_UNQUOTED([JEMALLOC_BIG_ENDIAN], [ ])\nfi\n\nif test \"x${je_cv_msvc}\" = \"xyes\" -a \"x${ac_cv_header_inttypes_h}\" = \"xno\"; then\n  CPPFLAGS=\"$CPPFLAGS -I${srcdir}/include/msvc_compat/C99\"\nfi\n\nif test \"x${je_cv_msvc}\" = \"xyes\" ; then\n  LG_SIZEOF_PTR=LG_SIZEOF_PTR_WIN\n  AC_MSG_RESULT([Using a predefined value for sizeof(void *): 4 for 32-bit, 8 for 64-bit])\nelse\n  AC_CHECK_SIZEOF([void *])\n  if test \"x${ac_cv_sizeof_void_p}\" = \"x8\" ; then\n    LG_SIZEOF_PTR=3\n  elif test \"x${ac_cv_sizeof_void_p}\" = \"x4\" ; then\n    LG_SIZEOF_PTR=2\n  else\n    AC_MSG_ERROR([Unsupported pointer size: ${ac_cv_sizeof_void_p}])\n  fi\nfi\nAC_DEFINE_UNQUOTED([LG_SIZEOF_PTR], [$LG_SIZEOF_PTR])\n\nAC_CHECK_SIZEOF([int])\nif test \"x${ac_cv_sizeof_int}\" = \"x8\" ; then\n  LG_SIZEOF_INT=3\nelif test \"x${ac_cv_sizeof_int}\" = \"x4\" ; then\n  LG_SIZEOF_INT=2\nelse\n  AC_MSG_ERROR([Unsupported int size: ${ac_cv_sizeof_int}])\nfi\nAC_DEFINE_UNQUOTED([LG_SIZEOF_INT], [$LG_SIZEOF_INT])\n\nAC_CHECK_SIZEOF([long])\nif test \"x${ac_cv_sizeof_long}\" = \"x8\" ; then\n  LG_SIZEOF_LONG=3\nelif test \"x${ac_cv_sizeof_long}\" = \"x4\" ; then\n  LG_SIZEOF_LONG=2\nelse\n  AC_MSG_ERROR([Unsupported long size: ${ac_cv_sizeof_long}])\nfi\nAC_DEFINE_UNQUOTED([LG_SIZEOF_LONG], [$LG_SIZEOF_LONG])\n\nAC_CHECK_SIZEOF([long long])\nif test \"x${ac_cv_sizeof_long_long}\" = \"x8\" ; then\n  LG_SIZEOF_LONG_LONG=3\nelif test \"x${ac_cv_sizeof_long_long}\" = \"x4\" ; then\n  LG_SIZEOF_LONG_LONG=2\nelse\n  AC_MSG_ERROR([Unsupported long long size: ${ac_cv_sizeof_long_long}])\nfi\nAC_DEFINE_UNQUOTED([LG_SIZEOF_LONG_LONG], [$LG_SIZEOF_LONG_LONG])\n\nAC_CHECK_SIZEOF([intmax_t])\nif test \"x${ac_cv_sizeof_intmax_t}\" = \"x16\" ; then\n  LG_SIZEOF_INTMAX_T=4\nelif test \"x${ac_cv_sizeof_intmax_t}\" = \"x8\" ; then\n  LG_SIZEOF_INTMAX_T=3\nelif test \"x${ac_cv_sizeof_intmax_t}\" = \"x4\" ; then\n  LG_SIZEOF_INTMAX_T=2\nelse\n  AC_MSG_ERROR([Unsupported intmax_t size: ${ac_cv_sizeof_intmax_t}])\nfi\nAC_DEFINE_UNQUOTED([LG_SIZEOF_INTMAX_T], [$LG_SIZEOF_INTMAX_T])\n\nAC_CANONICAL_HOST\ndnl CPU-specific settings.\nCPU_SPINWAIT=\"\"\ncase \"${host_cpu}\" in\n  i686|x86_64)\n\tif test \"x${je_cv_msvc}\" = \"xyes\" ; then\n\t    AC_CACHE_VAL([je_cv_pause_msvc],\n\t      [JE_COMPILABLE([pause instruction MSVC], [],\n\t\t\t\t\t[[_mm_pause(); return 0;]],\n\t\t\t\t\t[je_cv_pause_msvc])])\n\t    if test \"x${je_cv_pause_msvc}\" = \"xyes\" ; then\n\t\tCPU_SPINWAIT='_mm_pause()'\n\t    fi\n\telse\n\t    AC_CACHE_VAL([je_cv_pause],\n\t      [JE_COMPILABLE([pause instruction], [],\n\t\t\t\t\t[[__asm__ volatile(\"pause\"); return 0;]],\n\t\t\t\t\t[je_cv_pause])])\n\t    if test \"x${je_cv_pause}\" = \"xyes\" ; then\n\t\tCPU_SPINWAIT='__asm__ volatile(\"pause\")'\n\t    fi\n\tfi\n\t;;\n  powerpc)\n\tAC_DEFINE_UNQUOTED([HAVE_ALTIVEC], [ ])\n\t;;\n  *)\n\t;;\nesac\nAC_DEFINE_UNQUOTED([CPU_SPINWAIT], [$CPU_SPINWAIT])\n\nLD_PRELOAD_VAR=\"LD_PRELOAD\"\nso=\"so\"\nimportlib=\"${so}\"\no=\"$ac_objext\"\na=\"a\"\nexe=\"$ac_exeext\"\nlibprefix=\"lib\"\nDSO_LDFLAGS='-shared -Wl,-soname,$(@F)'\nRPATH='-Wl,-rpath,$(1)'\nSOREV=\"${so}.${rev}\"\nPIC_CFLAGS='-fPIC -DPIC'\nCTARGET='-o $@'\nLDTARGET='-o $@'\nEXTRA_LDFLAGS=\nARFLAGS='crus'\nAROUT=' $@'\nCC_MM=1\n\nAN_MAKEVAR([AR], [AC_PROG_AR])\nAN_PROGRAM([ar], [AC_PROG_AR])\nAC_DEFUN([AC_PROG_AR], [AC_CHECK_TOOL(AR, ar, :)])\nAC_PROG_AR\n\ndnl Platform-specific settings.  abi and RPATH can probably be determined\ndnl programmatically, but doing so is error-prone, which makes it generally\ndnl not worth the trouble.\ndnl \ndnl Define cpp macros in CPPFLAGS, rather than doing AC_DEFINE(macro), since the\ndnl definitions need to be seen before any headers are included, which is a pain\ndnl to make happen otherwise.\ndefault_munmap=\"1\"\nmaps_coalesce=\"1\"\ncase \"${host}\" in\n  *-*-darwin* | *-*-ios*)\n\tCFLAGS=\"$CFLAGS\"\n\tabi=\"macho\"\n\tAC_DEFINE([JEMALLOC_PURGE_MADVISE_FREE], [ ])\n\tRPATH=\"\"\n\tLD_PRELOAD_VAR=\"DYLD_INSERT_LIBRARIES\"\n\tso=\"dylib\"\n\timportlib=\"${so}\"\n\tforce_tls=\"0\"\n\tDSO_LDFLAGS='-shared -Wl,-install_name,$(LIBDIR)/$(@F)'\n\tSOREV=\"${rev}.${so}\"\n\tsbrk_deprecated=\"1\"\n\t;;\n  *-*-freebsd*)\n\tCFLAGS=\"$CFLAGS\"\n\tabi=\"elf\"\n\tAC_DEFINE([JEMALLOC_SYSCTL_VM_OVERCOMMIT], [ ])\n\tAC_DEFINE([JEMALLOC_PURGE_MADVISE_FREE], [ ])\n\tforce_lazy_lock=\"1\"\n\t;;\n  *-*-dragonfly*)\n\tCFLAGS=\"$CFLAGS\"\n\tabi=\"elf\"\n\tAC_DEFINE([JEMALLOC_PURGE_MADVISE_FREE], [ ])\n\t;;\n  *-*-openbsd*)\n\tCFLAGS=\"$CFLAGS\"\n\tabi=\"elf\"\n\tAC_DEFINE([JEMALLOC_PURGE_MADVISE_FREE], [ ])\n\tforce_tls=\"0\"\n\t;;\n  *-*-bitrig*)\n\tCFLAGS=\"$CFLAGS\"\n\tabi=\"elf\"\n\tAC_DEFINE([JEMALLOC_PURGE_MADVISE_FREE], [ ])\n\t;;\n  *-*-linux*)\n\tCFLAGS=\"$CFLAGS\"\n\tCPPFLAGS=\"$CPPFLAGS -D_GNU_SOURCE\"\n\tabi=\"elf\"\n\tAC_DEFINE([JEMALLOC_HAS_ALLOCA_H])\n\tAC_DEFINE([JEMALLOC_PROC_SYS_VM_OVERCOMMIT_MEMORY], [ ])\n\tAC_DEFINE([JEMALLOC_PURGE_MADVISE_DONTNEED], [ ])\n\tAC_DEFINE([JEMALLOC_THREADED_INIT], [ ])\n\tAC_DEFINE([JEMALLOC_USE_CXX_THROW], [ ])\n\tdefault_munmap=\"0\"\n\t;;\n  *-*-netbsd*)\n\tAC_MSG_CHECKING([ABI])\n        AC_COMPILE_IFELSE([AC_LANG_PROGRAM(\n[[#ifdef __ELF__\n/* ELF */\n#else\n#error aout\n#endif\n]])],\n                          [CFLAGS=\"$CFLAGS\"; abi=\"elf\"],\n                          [abi=\"aout\"])\n\tAC_MSG_RESULT([$abi])\n\tAC_DEFINE([JEMALLOC_PURGE_MADVISE_FREE], [ ])\n\t;;\n  *-*-solaris2*)\n\tCFLAGS=\"$CFLAGS\"\n\tabi=\"elf\"\n\tAC_DEFINE([JEMALLOC_PURGE_MADVISE_FREE], [ ])\n\tRPATH='-Wl,-R,$(1)'\n\tdnl Solaris needs this for sigwait().\n\tCPPFLAGS=\"$CPPFLAGS -D_POSIX_PTHREAD_SEMANTICS\"\n\tLIBS=\"$LIBS -lposix4 -lsocket -lnsl\"\n\t;;\n  *-ibm-aix*)\n\tif \"$LG_SIZEOF_PTR\" = \"8\"; then\n\t  dnl 64bit AIX\n\t  LD_PRELOAD_VAR=\"LDR_PRELOAD64\"\n\telse\n\t  dnl 32bit AIX\n\t  LD_PRELOAD_VAR=\"LDR_PRELOAD\"\n\tfi\n\tabi=\"xcoff\"\n\t;;\n  *-*-mingw* | *-*-cygwin*)\n\tabi=\"pecoff\"\n\tforce_tls=\"0\"\n\tforce_lazy_lock=\"1\"\n\tmaps_coalesce=\"0\"\n\tRPATH=\"\"\n\tso=\"dll\"\n\tif test \"x$je_cv_msvc\" = \"xyes\" ; then\n\t  importlib=\"lib\"\n\t  DSO_LDFLAGS=\"-LD\"\n\t  EXTRA_LDFLAGS=\"-link -DEBUG\"\n\t  CTARGET='-Fo$@'\n\t  LDTARGET='-Fe$@'\n\t  AR='lib'\n\t  ARFLAGS='-nologo -out:'\n\t  AROUT='$@'\n\t  CC_MM=\n        else\n\t  importlib=\"${so}\"\n\t  DSO_LDFLAGS=\"-shared\"\n\tfi\n\ta=\"lib\"\n\tlibprefix=\"\"\n\tSOREV=\"${so}\"\n\tPIC_CFLAGS=\"\"\n\t;;\n  *)\n\tAC_MSG_RESULT([Unsupported operating system: ${host}])\n\tabi=\"elf\"\n\t;;\nesac\n\nJEMALLOC_USABLE_SIZE_CONST=const\nAC_CHECK_HEADERS([malloc.h], [\n  AC_MSG_CHECKING([whether malloc_usable_size definition can use const argument])\n  AC_COMPILE_IFELSE([AC_LANG_PROGRAM(\n    [#include <malloc.h>\n     #include <stddef.h>\n    size_t malloc_usable_size(const void *ptr);\n    ],\n    [])],[\n                AC_MSG_RESULT([yes])\n         ],[\n                JEMALLOC_USABLE_SIZE_CONST=\n                AC_MSG_RESULT([no])\n         ])\n])\nAC_DEFINE_UNQUOTED([JEMALLOC_USABLE_SIZE_CONST], [$JEMALLOC_USABLE_SIZE_CONST])\nAC_SUBST([abi])\nAC_SUBST([RPATH])\nAC_SUBST([LD_PRELOAD_VAR])\nAC_SUBST([so])\nAC_SUBST([importlib])\nAC_SUBST([o])\nAC_SUBST([a])\nAC_SUBST([exe])\nAC_SUBST([libprefix])\nAC_SUBST([DSO_LDFLAGS])\nAC_SUBST([EXTRA_LDFLAGS])\nAC_SUBST([SOREV])\nAC_SUBST([PIC_CFLAGS])\nAC_SUBST([CTARGET])\nAC_SUBST([LDTARGET])\nAC_SUBST([MKLIB])\nAC_SUBST([ARFLAGS])\nAC_SUBST([AROUT])\nAC_SUBST([CC_MM])\n\nJE_COMPILABLE([__attribute__ syntax],\n              [static __attribute__((unused)) void foo(void){}],\n              [],\n              [je_cv_attribute])\nif test \"x${je_cv_attribute}\" = \"xyes\" ; then\n  AC_DEFINE([JEMALLOC_HAVE_ATTR], [ ])\n  if test \"x${GCC}\" = \"xyes\" -a \"x${abi}\" = \"xelf\"; then\n    JE_CFLAGS_APPEND([-fvisibility=hidden])\n  fi\nfi\ndnl Check for tls_model attribute support (clang 3.0 still lacks support).\nSAVED_CFLAGS=\"${CFLAGS}\"\nJE_CFLAGS_APPEND([-Werror])\nJE_COMPILABLE([tls_model attribute], [],\n              [static __thread int\n               __attribute__((tls_model(\"initial-exec\"), unused)) foo;\n               foo = 0;],\n              [je_cv_tls_model])\nCFLAGS=\"${SAVED_CFLAGS}\"\nif test \"x${je_cv_tls_model}\" = \"xyes\" ; then\n  AC_DEFINE([JEMALLOC_TLS_MODEL],\n            [__attribute__((tls_model(\"initial-exec\")))])\nelse\n  AC_DEFINE([JEMALLOC_TLS_MODEL], [ ])\nfi\ndnl Check for alloc_size attribute support.\nSAVED_CFLAGS=\"${CFLAGS}\"\nJE_CFLAGS_APPEND([-Werror])\nJE_COMPILABLE([alloc_size attribute], [#include <stdlib.h>],\n              [void *foo(size_t size) __attribute__((alloc_size(1)));],\n              [je_cv_alloc_size])\nCFLAGS=\"${SAVED_CFLAGS}\"\nif test \"x${je_cv_alloc_size}\" = \"xyes\" ; then\n  AC_DEFINE([JEMALLOC_HAVE_ATTR_ALLOC_SIZE], [ ])\nfi\ndnl Check for format(gnu_printf, ...) attribute support.\nSAVED_CFLAGS=\"${CFLAGS}\"\nJE_CFLAGS_APPEND([-Werror])\nJE_COMPILABLE([format(gnu_printf, ...) attribute], [#include <stdlib.h>],\n              [void *foo(const char *format, ...) __attribute__((format(gnu_printf, 1, 2)));],\n              [je_cv_format_gnu_printf])\nCFLAGS=\"${SAVED_CFLAGS}\"\nif test \"x${je_cv_format_gnu_printf}\" = \"xyes\" ; then\n  AC_DEFINE([JEMALLOC_HAVE_ATTR_FORMAT_GNU_PRINTF], [ ])\nfi\ndnl Check for format(printf, ...) attribute support.\nSAVED_CFLAGS=\"${CFLAGS}\"\nJE_CFLAGS_APPEND([-Werror])\nJE_COMPILABLE([format(printf, ...) attribute], [#include <stdlib.h>],\n              [void *foo(const char *format, ...) __attribute__((format(printf, 1, 2)));],\n              [je_cv_format_printf])\nCFLAGS=\"${SAVED_CFLAGS}\"\nif test \"x${je_cv_format_printf}\" = \"xyes\" ; then\n  AC_DEFINE([JEMALLOC_HAVE_ATTR_FORMAT_PRINTF], [ ])\nfi\n\ndnl Support optional additions to rpath.\nAC_ARG_WITH([rpath],\n  [AS_HELP_STRING([--with-rpath=<rpath>], [Colon-separated rpath (ELF systems only)])],\nif test \"x$with_rpath\" = \"xno\" ; then\n  RPATH_EXTRA=\nelse\n  RPATH_EXTRA=\"`echo $with_rpath | tr \\\":\\\" \\\" \\\"`\"\nfi,\n  RPATH_EXTRA=\n)\nAC_SUBST([RPATH_EXTRA])\n\ndnl Disable rules that do automatic regeneration of configure output by default.\nAC_ARG_ENABLE([autogen],\n  [AS_HELP_STRING([--enable-autogen], [Automatically regenerate configure output])],\nif test \"x$enable_autogen\" = \"xno\" ; then\n  enable_autogen=\"0\"\nelse\n  enable_autogen=\"1\"\nfi\n,\nenable_autogen=\"0\"\n)\nAC_SUBST([enable_autogen])\n\nAC_PROG_INSTALL\nAC_PROG_RANLIB\nAC_PATH_PROG([LD], [ld], [false], [$PATH])\nAC_PATH_PROG([AUTOCONF], [autoconf], [false], [$PATH])\n\npublic_syms=\"malloc_conf malloc_message malloc calloc posix_memalign aligned_alloc realloc free mallocx rallocx xallocx sallocx dallocx sdallocx nallocx mallctl mallctlnametomib mallctlbymib malloc_stats_print malloc_usable_size\"\n\ndnl Check for allocator-related functions that should be wrapped.\nAC_CHECK_FUNC([memalign],\n\t      [AC_DEFINE([JEMALLOC_OVERRIDE_MEMALIGN], [ ])\n\t       public_syms=\"${public_syms} memalign\"])\nAC_CHECK_FUNC([valloc],\n\t      [AC_DEFINE([JEMALLOC_OVERRIDE_VALLOC], [ ])\n\t       public_syms=\"${public_syms} valloc\"])\n\ndnl Do not compute test code coverage by default.\nGCOV_FLAGS=\nAC_ARG_ENABLE([code-coverage],\n  [AS_HELP_STRING([--enable-code-coverage],\n   [Enable code coverage])],\n[if test \"x$enable_code_coverage\" = \"xno\" ; then\n  enable_code_coverage=\"0\"\nelse\n  enable_code_coverage=\"1\"\nfi\n],\n[enable_code_coverage=\"0\"]\n)\nif test \"x$enable_code_coverage\" = \"x1\" ; then\n  deoptimize=\"no\"\n  echo \"$CFLAGS $EXTRA_CFLAGS\" | grep '\\-O' >/dev/null || deoptimize=\"yes\"\n  if test \"x${deoptimize}\" = \"xyes\" ; then\n    JE_CFLAGS_APPEND([-O0])\n  fi\n  JE_CFLAGS_APPEND([-fprofile-arcs -ftest-coverage])\n  EXTRA_LDFLAGS=\"$EXTRA_LDFLAGS -fprofile-arcs -ftest-coverage\"\n  AC_DEFINE([JEMALLOC_CODE_COVERAGE], [ ])\nfi\nAC_SUBST([enable_code_coverage])\n\ndnl Perform no name mangling by default.\nAC_ARG_WITH([mangling],\n  [AS_HELP_STRING([--with-mangling=<map>], [Mangle symbols in <map>])],\n  [mangling_map=\"$with_mangling\"], [mangling_map=\"\"])\n\ndnl Do not prefix public APIs by default.\nAC_ARG_WITH([jemalloc_prefix],\n  [AS_HELP_STRING([--with-jemalloc-prefix=<prefix>], [Prefix to prepend to all public APIs])],\n  [JEMALLOC_PREFIX=\"$with_jemalloc_prefix\"],\n  [if test \"x$abi\" != \"xmacho\" -a \"x$abi\" != \"xpecoff\"; then\n  JEMALLOC_PREFIX=\"\"\nelse\n  JEMALLOC_PREFIX=\"je_\"\nfi]\n)\nif test \"x$JEMALLOC_PREFIX\" != \"x\" ; then\n  JEMALLOC_CPREFIX=`echo ${JEMALLOC_PREFIX} | tr \"a-z\" \"A-Z\"`\n  AC_DEFINE_UNQUOTED([JEMALLOC_PREFIX], [\"$JEMALLOC_PREFIX\"])\n  AC_DEFINE_UNQUOTED([JEMALLOC_CPREFIX], [\"$JEMALLOC_CPREFIX\"])\nfi\nAC_SUBST([JEMALLOC_CPREFIX])\n\nAC_ARG_WITH([export],\n  [AS_HELP_STRING([--without-export], [disable exporting jemalloc public APIs])],\n  [if test \"x$with_export\" = \"xno\"; then\n  AC_DEFINE([JEMALLOC_EXPORT],[])\nfi]\n)\n\ndnl Mangle library-private APIs.\nAC_ARG_WITH([private_namespace],\n  [AS_HELP_STRING([--with-private-namespace=<prefix>], [Prefix to prepend to all library-private APIs])],\n  [JEMALLOC_PRIVATE_NAMESPACE=\"${with_private_namespace}je_\"],\n  [JEMALLOC_PRIVATE_NAMESPACE=\"je_\"]\n)\nAC_DEFINE_UNQUOTED([JEMALLOC_PRIVATE_NAMESPACE], [$JEMALLOC_PRIVATE_NAMESPACE])\nprivate_namespace=\"$JEMALLOC_PRIVATE_NAMESPACE\"\nAC_SUBST([private_namespace])\n\ndnl Do not add suffix to installed files by default.\nAC_ARG_WITH([install_suffix],\n  [AS_HELP_STRING([--with-install-suffix=<suffix>], [Suffix to append to all installed files])],\n  [INSTALL_SUFFIX=\"$with_install_suffix\"],\n  [INSTALL_SUFFIX=]\n)\ninstall_suffix=\"$INSTALL_SUFFIX\"\nAC_SUBST([install_suffix])\n\ndnl Specify default malloc_conf.\nAC_ARG_WITH([malloc_conf],\n  [AS_HELP_STRING([--with-malloc-conf=<malloc_conf>], [config.malloc_conf options string])],\n  [JEMALLOC_CONFIG_MALLOC_CONF=\"$with_malloc_conf\"],\n  [JEMALLOC_CONFIG_MALLOC_CONF=\"\"]\n)\nconfig_malloc_conf=\"$JEMALLOC_CONFIG_MALLOC_CONF\"\nAC_DEFINE_UNQUOTED([JEMALLOC_CONFIG_MALLOC_CONF], [\"$config_malloc_conf\"])\n\ndnl Substitute @je_@ in jemalloc_protos.h.in, primarily to make generation of\ndnl jemalloc_protos_jet.h easy.\nje_=\"je_\"\nAC_SUBST([je_])\n\ncfgoutputs_in=\"Makefile.in\"\ncfgoutputs_in=\"${cfgoutputs_in} jemalloc.pc.in\"\ncfgoutputs_in=\"${cfgoutputs_in} doc/html.xsl.in\"\ncfgoutputs_in=\"${cfgoutputs_in} doc/manpages.xsl.in\"\ncfgoutputs_in=\"${cfgoutputs_in} doc/jemalloc.xml.in\"\ncfgoutputs_in=\"${cfgoutputs_in} include/jemalloc/jemalloc_macros.h.in\"\ncfgoutputs_in=\"${cfgoutputs_in} include/jemalloc/jemalloc_protos.h.in\"\ncfgoutputs_in=\"${cfgoutputs_in} include/jemalloc/jemalloc_typedefs.h.in\"\ncfgoutputs_in=\"${cfgoutputs_in} include/jemalloc/internal/jemalloc_internal.h.in\"\ncfgoutputs_in=\"${cfgoutputs_in} test/test.sh.in\"\ncfgoutputs_in=\"${cfgoutputs_in} test/include/test/jemalloc_test.h.in\"\n\ncfgoutputs_out=\"Makefile\"\ncfgoutputs_out=\"${cfgoutputs_out} jemalloc.pc\"\ncfgoutputs_out=\"${cfgoutputs_out} doc/html.xsl\"\ncfgoutputs_out=\"${cfgoutputs_out} doc/manpages.xsl\"\ncfgoutputs_out=\"${cfgoutputs_out} doc/jemalloc.xml\"\ncfgoutputs_out=\"${cfgoutputs_out} include/jemalloc/jemalloc_macros.h\"\ncfgoutputs_out=\"${cfgoutputs_out} include/jemalloc/jemalloc_protos.h\"\ncfgoutputs_out=\"${cfgoutputs_out} include/jemalloc/jemalloc_typedefs.h\"\ncfgoutputs_out=\"${cfgoutputs_out} include/jemalloc/internal/jemalloc_internal.h\"\ncfgoutputs_out=\"${cfgoutputs_out} test/test.sh\"\ncfgoutputs_out=\"${cfgoutputs_out} test/include/test/jemalloc_test.h\"\n\ncfgoutputs_tup=\"Makefile\"\ncfgoutputs_tup=\"${cfgoutputs_tup} jemalloc.pc:jemalloc.pc.in\"\ncfgoutputs_tup=\"${cfgoutputs_tup} doc/html.xsl:doc/html.xsl.in\"\ncfgoutputs_tup=\"${cfgoutputs_tup} doc/manpages.xsl:doc/manpages.xsl.in\"\ncfgoutputs_tup=\"${cfgoutputs_tup} doc/jemalloc.xml:doc/jemalloc.xml.in\"\ncfgoutputs_tup=\"${cfgoutputs_tup} include/jemalloc/jemalloc_macros.h:include/jemalloc/jemalloc_macros.h.in\"\ncfgoutputs_tup=\"${cfgoutputs_tup} include/jemalloc/jemalloc_protos.h:include/jemalloc/jemalloc_protos.h.in\"\ncfgoutputs_tup=\"${cfgoutputs_tup} include/jemalloc/jemalloc_typedefs.h:include/jemalloc/jemalloc_typedefs.h.in\"\ncfgoutputs_tup=\"${cfgoutputs_tup} include/jemalloc/internal/jemalloc_internal.h\"\ncfgoutputs_tup=\"${cfgoutputs_tup} test/test.sh:test/test.sh.in\"\ncfgoutputs_tup=\"${cfgoutputs_tup} test/include/test/jemalloc_test.h:test/include/test/jemalloc_test.h.in\"\n\ncfghdrs_in=\"include/jemalloc/jemalloc_defs.h.in\"\ncfghdrs_in=\"${cfghdrs_in} include/jemalloc/internal/jemalloc_internal_defs.h.in\"\ncfghdrs_in=\"${cfghdrs_in} include/jemalloc/internal/private_namespace.sh\"\ncfghdrs_in=\"${cfghdrs_in} include/jemalloc/internal/private_unnamespace.sh\"\ncfghdrs_in=\"${cfghdrs_in} include/jemalloc/internal/private_symbols.txt\"\ncfghdrs_in=\"${cfghdrs_in} include/jemalloc/internal/public_namespace.sh\"\ncfghdrs_in=\"${cfghdrs_in} include/jemalloc/internal/public_unnamespace.sh\"\ncfghdrs_in=\"${cfghdrs_in} include/jemalloc/internal/size_classes.sh\"\ncfghdrs_in=\"${cfghdrs_in} include/jemalloc/jemalloc_rename.sh\"\ncfghdrs_in=\"${cfghdrs_in} include/jemalloc/jemalloc_mangle.sh\"\ncfghdrs_in=\"${cfghdrs_in} include/jemalloc/jemalloc.sh\"\ncfghdrs_in=\"${cfghdrs_in} test/include/test/jemalloc_test_defs.h.in\"\n\ncfghdrs_out=\"include/jemalloc/jemalloc_defs.h\"\ncfghdrs_out=\"${cfghdrs_out} include/jemalloc/jemalloc${install_suffix}.h\"\ncfghdrs_out=\"${cfghdrs_out} include/jemalloc/internal/private_namespace.h\"\ncfghdrs_out=\"${cfghdrs_out} include/jemalloc/internal/private_unnamespace.h\"\ncfghdrs_out=\"${cfghdrs_out} include/jemalloc/internal/public_symbols.txt\"\ncfghdrs_out=\"${cfghdrs_out} include/jemalloc/internal/public_namespace.h\"\ncfghdrs_out=\"${cfghdrs_out} include/jemalloc/internal/public_unnamespace.h\"\ncfghdrs_out=\"${cfghdrs_out} include/jemalloc/internal/size_classes.h\"\ncfghdrs_out=\"${cfghdrs_out} include/jemalloc/jemalloc_protos_jet.h\"\ncfghdrs_out=\"${cfghdrs_out} include/jemalloc/jemalloc_rename.h\"\ncfghdrs_out=\"${cfghdrs_out} include/jemalloc/jemalloc_mangle.h\"\ncfghdrs_out=\"${cfghdrs_out} include/jemalloc/jemalloc_mangle_jet.h\"\ncfghdrs_out=\"${cfghdrs_out} include/jemalloc/internal/jemalloc_internal_defs.h\"\ncfghdrs_out=\"${cfghdrs_out} test/include/test/jemalloc_test_defs.h\"\n\ncfghdrs_tup=\"include/jemalloc/jemalloc_defs.h:include/jemalloc/jemalloc_defs.h.in\"\ncfghdrs_tup=\"${cfghdrs_tup} include/jemalloc/internal/jemalloc_internal_defs.h:include/jemalloc/internal/jemalloc_internal_defs.h.in\"\ncfghdrs_tup=\"${cfghdrs_tup} test/include/test/jemalloc_test_defs.h:test/include/test/jemalloc_test_defs.h.in\"\n\ndnl Silence irrelevant compiler warnings by default.\nAC_ARG_ENABLE([cc-silence],\n  [AS_HELP_STRING([--disable-cc-silence],\n                  [Do not silence irrelevant compiler warnings])],\n[if test \"x$enable_cc_silence\" = \"xno\" ; then\n  enable_cc_silence=\"0\"\nelse\n  enable_cc_silence=\"1\"\nfi\n],\n[enable_cc_silence=\"1\"]\n)\nif test \"x$enable_cc_silence\" = \"x1\" ; then\n  AC_DEFINE([JEMALLOC_CC_SILENCE], [ ])\nfi\n\ndnl Do not compile with debugging by default.\nAC_ARG_ENABLE([debug],\n  [AS_HELP_STRING([--enable-debug],\n                  [Build debugging code (implies --enable-ivsalloc)])],\n[if test \"x$enable_debug\" = \"xno\" ; then\n  enable_debug=\"0\"\nelse\n  enable_debug=\"1\"\nfi\n],\n[enable_debug=\"0\"]\n)\nif test \"x$enable_debug\" = \"x1\" ; then\n  AC_DEFINE([JEMALLOC_DEBUG], [ ])\nfi\nif test \"x$enable_debug\" = \"x1\" ; then\n  AC_DEFINE([JEMALLOC_DEBUG], [ ])\n  enable_ivsalloc=\"1\"\nfi\nAC_SUBST([enable_debug])\n\ndnl Do not validate pointers by default.\nAC_ARG_ENABLE([ivsalloc],\n  [AS_HELP_STRING([--enable-ivsalloc],\n                  [Validate pointers passed through the public API])],\n[if test \"x$enable_ivsalloc\" = \"xno\" ; then\n  enable_ivsalloc=\"0\"\nelse\n  enable_ivsalloc=\"1\"\nfi\n],\n[enable_ivsalloc=\"0\"]\n)\nif test \"x$enable_ivsalloc\" = \"x1\" ; then\n  AC_DEFINE([JEMALLOC_IVSALLOC], [ ])\nfi\n\ndnl Only optimize if not debugging.\nif test \"x$enable_debug\" = \"x0\" -a \"x$no_CFLAGS\" = \"xyes\" ; then\n  dnl Make sure that an optimization flag was not specified in EXTRA_CFLAGS.\n  optimize=\"no\"\n  echo \"$CFLAGS $EXTRA_CFLAGS\" | grep '\\-O' >/dev/null || optimize=\"yes\"\n  if test \"x${optimize}\" = \"xyes\" ; then\n    if test \"x$GCC\" = \"xyes\" ; then\n      JE_CFLAGS_APPEND([-O3])\n      JE_CFLAGS_APPEND([-funroll-loops])\n    elif test \"x$je_cv_msvc\" = \"xyes\" ; then\n      JE_CFLAGS_APPEND([-O2])\n    else\n      JE_CFLAGS_APPEND([-O])\n    fi\n  fi\nfi\n\ndnl Enable statistics calculation by default.\nAC_ARG_ENABLE([stats],\n  [AS_HELP_STRING([--disable-stats],\n                  [Disable statistics calculation/reporting])],\n[if test \"x$enable_stats\" = \"xno\" ; then\n  enable_stats=\"0\"\nelse\n  enable_stats=\"1\"\nfi\n],\n[enable_stats=\"1\"]\n)\nif test \"x$enable_stats\" = \"x1\" ; then\n  AC_DEFINE([JEMALLOC_STATS], [ ])\nfi\nAC_SUBST([enable_stats])\n\ndnl Do not enable profiling by default.\nAC_ARG_ENABLE([prof],\n  [AS_HELP_STRING([--enable-prof], [Enable allocation profiling])],\n[if test \"x$enable_prof\" = \"xno\" ; then\n  enable_prof=\"0\"\nelse\n  enable_prof=\"1\"\nfi\n],\n[enable_prof=\"0\"]\n)\nif test \"x$enable_prof\" = \"x1\" ; then\n  backtrace_method=\"\"\nelse\n  backtrace_method=\"N/A\"\nfi\n\nAC_ARG_ENABLE([prof-libunwind],\n  [AS_HELP_STRING([--enable-prof-libunwind], [Use libunwind for backtracing])],\n[if test \"x$enable_prof_libunwind\" = \"xno\" ; then\n  enable_prof_libunwind=\"0\"\nelse\n  enable_prof_libunwind=\"1\"\nfi\n],\n[enable_prof_libunwind=\"0\"]\n)\nAC_ARG_WITH([static_libunwind],\n  [AS_HELP_STRING([--with-static-libunwind=<libunwind.a>],\n  [Path to static libunwind library; use rather than dynamically linking])],\nif test \"x$with_static_libunwind\" = \"xno\" ; then\n  LUNWIND=\"-lunwind\"\nelse\n  if test ! -f \"$with_static_libunwind\" ; then\n    AC_MSG_ERROR([Static libunwind not found: $with_static_libunwind])\n  fi\n  LUNWIND=\"$with_static_libunwind\"\nfi,\n  LUNWIND=\"-lunwind\"\n)\nif test \"x$backtrace_method\" = \"x\" -a \"x$enable_prof_libunwind\" = \"x1\" ; then\n  AC_CHECK_HEADERS([libunwind.h], , [enable_prof_libunwind=\"0\"])\n  if test \"x$LUNWIND\" = \"x-lunwind\" ; then\n    AC_CHECK_LIB([unwind], [unw_backtrace], [LIBS=\"$LIBS $LUNWIND\"],\n                 [enable_prof_libunwind=\"0\"])\n  else\n    LIBS=\"$LIBS $LUNWIND\"\n  fi\n  if test \"x${enable_prof_libunwind}\" = \"x1\" ; then\n    backtrace_method=\"libunwind\"\n    AC_DEFINE([JEMALLOC_PROF_LIBUNWIND], [ ])\n  fi\nfi\n\nAC_ARG_ENABLE([prof-libgcc],\n  [AS_HELP_STRING([--disable-prof-libgcc],\n  [Do not use libgcc for backtracing])],\n[if test \"x$enable_prof_libgcc\" = \"xno\" ; then\n  enable_prof_libgcc=\"0\"\nelse\n  enable_prof_libgcc=\"1\"\nfi\n],\n[enable_prof_libgcc=\"1\"]\n)\nif test \"x$backtrace_method\" = \"x\" -a \"x$enable_prof_libgcc\" = \"x1\" \\\n     -a \"x$GCC\" = \"xyes\" ; then\n  AC_CHECK_HEADERS([unwind.h], , [enable_prof_libgcc=\"0\"])\n  AC_CHECK_LIB([gcc], [_Unwind_Backtrace], [LIBS=\"$LIBS -lgcc\"], [enable_prof_libgcc=\"0\"])\n  if test \"x${enable_prof_libgcc}\" = \"x1\" ; then\n    backtrace_method=\"libgcc\"\n    AC_DEFINE([JEMALLOC_PROF_LIBGCC], [ ])\n  fi\nelse\n  enable_prof_libgcc=\"0\"\nfi\n\nAC_ARG_ENABLE([prof-gcc],\n  [AS_HELP_STRING([--disable-prof-gcc],\n  [Do not use gcc intrinsics for backtracing])],\n[if test \"x$enable_prof_gcc\" = \"xno\" ; then\n  enable_prof_gcc=\"0\"\nelse\n  enable_prof_gcc=\"1\"\nfi\n],\n[enable_prof_gcc=\"1\"]\n)\nif test \"x$backtrace_method\" = \"x\" -a \"x$enable_prof_gcc\" = \"x1\" \\\n     -a \"x$GCC\" = \"xyes\" ; then\n  JE_CFLAGS_APPEND([-fno-omit-frame-pointer])\n  backtrace_method=\"gcc intrinsics\"\n  AC_DEFINE([JEMALLOC_PROF_GCC], [ ])\nelse\n  enable_prof_gcc=\"0\"\nfi\n\nif test \"x$backtrace_method\" = \"x\" ; then\n  backtrace_method=\"none (disabling profiling)\"\n  enable_prof=\"0\"\nfi\nAC_MSG_CHECKING([configured backtracing method])\nAC_MSG_RESULT([$backtrace_method])\nif test \"x$enable_prof\" = \"x1\" ; then\n  if test \"x$abi\" != \"xpecoff\"; then\n    dnl Heap profiling uses the log(3) function.\n    LIBS=\"$LIBS -lm\"\n  fi\n\n  AC_DEFINE([JEMALLOC_PROF], [ ])\nfi\nAC_SUBST([enable_prof])\n\ndnl Enable thread-specific caching by default.\nAC_ARG_ENABLE([tcache],\n  [AS_HELP_STRING([--disable-tcache], [Disable per thread caches])],\n[if test \"x$enable_tcache\" = \"xno\" ; then\n  enable_tcache=\"0\"\nelse\n  enable_tcache=\"1\"\nfi\n],\n[enable_tcache=\"1\"]\n)\nif test \"x$enable_tcache\" = \"x1\" ; then\n  AC_DEFINE([JEMALLOC_TCACHE], [ ])\nfi\nAC_SUBST([enable_tcache])\n\ndnl Indicate whether adjacent virtual memory mappings automatically coalesce\ndnl (and fragment on demand).\nif test \"x${maps_coalesce}\" = \"x1\" ; then\n  AC_DEFINE([JEMALLOC_MAPS_COALESCE], [ ])\nfi\n\ndnl Enable VM deallocation via munmap() by default.\nAC_ARG_ENABLE([munmap],\n  [AS_HELP_STRING([--disable-munmap], [Disable VM deallocation via munmap(2)])],\n[if test \"x$enable_munmap\" = \"xno\" ; then\n  enable_munmap=\"0\"\nelse\n  enable_munmap=\"1\"\nfi\n],\n[enable_munmap=\"${default_munmap}\"]\n)\nif test \"x$enable_munmap\" = \"x1\" ; then\n  AC_DEFINE([JEMALLOC_MUNMAP], [ ])\nfi\nAC_SUBST([enable_munmap])\n\ndnl Enable allocation from DSS if supported by the OS.\nhave_dss=\"1\"\ndnl Check whether the BSD/SUSv1 sbrk() exists.  If not, disable DSS support.\nAC_CHECK_FUNC([sbrk], [have_sbrk=\"1\"], [have_sbrk=\"0\"])\nif test \"x$have_sbrk\" = \"x1\" ; then\n  if test \"x$sbrk_deprecated\" = \"x1\" ; then\n    AC_MSG_RESULT([Disabling dss allocation because sbrk is deprecated])\n    have_dss=\"0\"\n  fi\nelse\n  have_dss=\"0\"\nfi\n\nif test \"x$have_dss\" = \"x1\" ; then\n  AC_DEFINE([JEMALLOC_DSS], [ ])\nfi\n\ndnl Support the junk/zero filling option by default.\nAC_ARG_ENABLE([fill],\n  [AS_HELP_STRING([--disable-fill],\n                  [Disable support for junk/zero filling, quarantine, and redzones])],\n[if test \"x$enable_fill\" = \"xno\" ; then\n  enable_fill=\"0\"\nelse\n  enable_fill=\"1\"\nfi\n],\n[enable_fill=\"1\"]\n)\nif test \"x$enable_fill\" = \"x1\" ; then\n  AC_DEFINE([JEMALLOC_FILL], [ ])\nfi\nAC_SUBST([enable_fill])\n\ndnl Disable utrace(2)-based tracing by default.\nAC_ARG_ENABLE([utrace],\n  [AS_HELP_STRING([--enable-utrace], [Enable utrace(2)-based tracing])],\n[if test \"x$enable_utrace\" = \"xno\" ; then\n  enable_utrace=\"0\"\nelse\n  enable_utrace=\"1\"\nfi\n],\n[enable_utrace=\"0\"]\n)\nJE_COMPILABLE([utrace(2)], [\n#include <sys/types.h>\n#include <sys/param.h>\n#include <sys/time.h>\n#include <sys/uio.h>\n#include <sys/ktrace.h>\n], [\n\tutrace((void *)0, 0);\n], [je_cv_utrace])\nif test \"x${je_cv_utrace}\" = \"xno\" ; then\n  enable_utrace=\"0\"\nfi\nif test \"x$enable_utrace\" = \"x1\" ; then\n  AC_DEFINE([JEMALLOC_UTRACE], [ ])\nfi\nAC_SUBST([enable_utrace])\n\ndnl Support Valgrind by default.\nAC_ARG_ENABLE([valgrind],\n  [AS_HELP_STRING([--disable-valgrind], [Disable support for Valgrind])],\n[if test \"x$enable_valgrind\" = \"xno\" ; then\n  enable_valgrind=\"0\"\nelse\n  enable_valgrind=\"1\"\nfi\n],\n[enable_valgrind=\"1\"]\n)\nif test \"x$enable_valgrind\" = \"x1\" ; then\n  JE_COMPILABLE([valgrind], [\n#include <valgrind/valgrind.h>\n#include <valgrind/memcheck.h>\n\n#if !defined(VALGRIND_RESIZEINPLACE_BLOCK)\n#  error \"Incompatible Valgrind version\"\n#endif\n], [], [je_cv_valgrind])\n  if test \"x${je_cv_valgrind}\" = \"xno\" ; then\n    enable_valgrind=\"0\"\n  fi\n  if test \"x$enable_valgrind\" = \"x1\" ; then\n    AC_DEFINE([JEMALLOC_VALGRIND], [ ])\n  fi\nfi\nAC_SUBST([enable_valgrind])\n\ndnl Do not support the xmalloc option by default.\nAC_ARG_ENABLE([xmalloc],\n  [AS_HELP_STRING([--enable-xmalloc], [Support xmalloc option])],\n[if test \"x$enable_xmalloc\" = \"xno\" ; then\n  enable_xmalloc=\"0\"\nelse\n  enable_xmalloc=\"1\"\nfi\n],\n[enable_xmalloc=\"0\"]\n)\nif test \"x$enable_xmalloc\" = \"x1\" ; then\n  AC_DEFINE([JEMALLOC_XMALLOC], [ ])\nfi\nAC_SUBST([enable_xmalloc])\n\ndnl Support cache-oblivious allocation alignment by default.\nAC_ARG_ENABLE([cache-oblivious],\n  [AS_HELP_STRING([--disable-cache-oblivious],\n                  [Disable support for cache-oblivious allocation alignment])],\n[if test \"x$enable_cache_oblivious\" = \"xno\" ; then\n  enable_cache_oblivious=\"0\"\nelse\n  enable_cache_oblivious=\"1\"\nfi\n],\n[enable_cache_oblivious=\"1\"]\n)\nif test \"x$enable_cache_oblivious\" = \"x1\" ; then\n  AC_DEFINE([JEMALLOC_CACHE_OBLIVIOUS], [ ])\nfi\nAC_SUBST([enable_cache_oblivious])\n\ndnl ============================================================================\ndnl Check for  __builtin_ffsl(), then ffsl(3), and fail if neither are found.\ndnl One of those two functions should (theoretically) exist on all platforms\ndnl that jemalloc currently has a chance of functioning on without modification.\ndnl We additionally assume ffs[ll]() or __builtin_ffs[ll]() are defined if\ndnl ffsl() or __builtin_ffsl() are defined, respectively.\nJE_COMPILABLE([a program using __builtin_ffsl], [\n#include <stdio.h>\n#include <strings.h>\n#include <string.h>\n], [\n\t{\n\t\tint rv = __builtin_ffsl(0x08);\n\t\tprintf(\"%d\\n\", rv);\n\t}\n], [je_cv_gcc_builtin_ffsl])\nif test \"x${je_cv_gcc_builtin_ffsl}\" = \"xyes\" ; then\n  AC_DEFINE([JEMALLOC_INTERNAL_FFSLL], [__builtin_ffsll])\n  AC_DEFINE([JEMALLOC_INTERNAL_FFSL], [__builtin_ffsl])\n  AC_DEFINE([JEMALLOC_INTERNAL_FFS], [__builtin_ffs])\nelse\n  JE_COMPILABLE([a program using ffsl], [\n  #include <stdio.h>\n  #include <strings.h>\n  #include <string.h>\n  ], [\n\t{\n\t\tint rv = ffsl(0x08);\n\t\tprintf(\"%d\\n\", rv);\n\t}\n  ], [je_cv_function_ffsl])\n  if test \"x${je_cv_function_ffsl}\" = \"xyes\" ; then\n    AC_DEFINE([JEMALLOC_INTERNAL_FFSLL], [ffsll])\n    AC_DEFINE([JEMALLOC_INTERNAL_FFSL], [ffsl])\n    AC_DEFINE([JEMALLOC_INTERNAL_FFS], [ffs])\n  else\n    AC_MSG_ERROR([Cannot build without ffsl(3) or __builtin_ffsl()])\n  fi\nfi\n\nAC_ARG_WITH([lg_tiny_min],\n  [AS_HELP_STRING([--with-lg-tiny-min=<lg-tiny-min>],\n   [Base 2 log of minimum tiny size class to support])],\n  [LG_TINY_MIN=\"$with_lg_tiny_min\"],\n  [LG_TINY_MIN=\"3\"])\nAC_DEFINE_UNQUOTED([LG_TINY_MIN], [$LG_TINY_MIN])\n\nAC_ARG_WITH([lg_quantum],\n  [AS_HELP_STRING([--with-lg-quantum=<lg-quantum>],\n   [Base 2 log of minimum allocation alignment])],\n  [LG_QUANTA=\"$with_lg_quantum\"],\n  [LG_QUANTA=\"3 4\"])\nif test \"x$with_lg_quantum\" != \"x\" ; then\n  AC_DEFINE_UNQUOTED([LG_QUANTUM], [$with_lg_quantum])\nfi\n\nAC_ARG_WITH([lg_page],\n  [AS_HELP_STRING([--with-lg-page=<lg-page>], [Base 2 log of system page size])],\n  [LG_PAGE=\"$with_lg_page\"], [LG_PAGE=\"detect\"])\nif test \"x$LG_PAGE\" = \"xdetect\"; then\n  AC_CACHE_CHECK([LG_PAGE],\n               [je_cv_lg_page],\n               AC_RUN_IFELSE([AC_LANG_PROGRAM(\n[[\n#include <strings.h>\n#ifdef _WIN32\n#include <windows.h>\n#else\n#include <unistd.h>\n#endif\n#include <stdio.h>\n]],\n[[\n    int result;\n    FILE *f;\n\n#ifdef _WIN32\n    SYSTEM_INFO si;\n    GetSystemInfo(&si);\n    result = si.dwPageSize;\n#else\n    result = sysconf(_SC_PAGESIZE);\n#endif\n    if (result == -1) {\n\treturn 1;\n    }\n    result = JEMALLOC_INTERNAL_FFSL(result) - 1;\n\n    f = fopen(\"conftest.out\", \"w\");\n    if (f == NULL) {\n\treturn 1;\n    }\n    fprintf(f, \"%d\", result);\n    fclose(f);\n\n    return 0;\n]])],\n                             [je_cv_lg_page=`cat conftest.out`],\n                             [je_cv_lg_page=undefined],\n                             [je_cv_lg_page=12]))\nfi\nif test \"x${je_cv_lg_page}\" != \"x\" ; then\n  LG_PAGE=\"${je_cv_lg_page}\"\nfi\nif test \"x${LG_PAGE}\" != \"xundefined\" ; then\n   AC_DEFINE_UNQUOTED([LG_PAGE], [$LG_PAGE])\nelse\n   AC_MSG_ERROR([cannot determine value for LG_PAGE])\nfi\n\nAC_ARG_WITH([lg_page_sizes],\n  [AS_HELP_STRING([--with-lg-page-sizes=<lg-page-sizes>],\n   [Base 2 logs of system page sizes to support])],\n  [LG_PAGE_SIZES=\"$with_lg_page_sizes\"], [LG_PAGE_SIZES=\"$LG_PAGE\"])\n\nAC_ARG_WITH([lg_size_class_group],\n  [AS_HELP_STRING([--with-lg-size-class-group=<lg-size-class-group>],\n   [Base 2 log of size classes per doubling])],\n  [LG_SIZE_CLASS_GROUP=\"$with_lg_size_class_group\"],\n  [LG_SIZE_CLASS_GROUP=\"2\"])\n\ndnl ============================================================================\ndnl jemalloc configuration.\ndnl \n\nAC_ARG_WITH([version],\n  [AS_HELP_STRING([--with-version=<major>.<minor>.<bugfix>-<nrev>-g<gid>],\n   [Version string])],\n  [\n    echo \"${with_version}\" | grep ['^[0-9]\\+\\.[0-9]\\+\\.[0-9]\\+-[0-9]\\+-g[0-9a-f]\\+$'] 2>&1 1>/dev/null\n    if test $? -ne 0 ; then\n      AC_MSG_ERROR([${with_version} does not match <major>.<minor>.<bugfix>-<nrev>-g<gid>])\n    fi\n    echo \"$with_version\" > \"${objroot}VERSION\"\n  ], [\n    dnl Set VERSION if source directory is inside a git repository.\n    if test \"x`test ! \\\"${srcroot}\\\" && cd \\\"${srcroot}\\\"; git rev-parse --is-inside-work-tree 2>/dev/null`\" = \"xtrue\" ; then\n      dnl Pattern globs aren't powerful enough to match both single- and\n      dnl double-digit version numbers, so iterate over patterns to support up\n      dnl to version 99.99.99 without any accidental matches.\n      for pattern in ['[0-9].[0-9].[0-9]' '[0-9].[0-9].[0-9][0-9]' \\\n                     '[0-9].[0-9][0-9].[0-9]' '[0-9].[0-9][0-9].[0-9][0-9]' \\\n                     '[0-9][0-9].[0-9].[0-9]' '[0-9][0-9].[0-9].[0-9][0-9]' \\\n                     '[0-9][0-9].[0-9][0-9].[0-9]' \\\n                     '[0-9][0-9].[0-9][0-9].[0-9][0-9]']; do\n        (test ! \"${srcroot}\" && cd \"${srcroot}\"; git describe --long --abbrev=40 --match=\"${pattern}\") > \"${objroot}VERSION.tmp\" 2>/dev/null\n        if test $? -eq 0 ; then\n          mv \"${objroot}VERSION.tmp\" \"${objroot}VERSION\"\n          break\n        fi\n      done\n    fi\n    rm -f \"${objroot}VERSION.tmp\"\n  ])\n\nif test ! -e \"${objroot}VERSION\" ; then\n  if test ! -e \"${srcroot}VERSION\" ; then\n    AC_MSG_RESULT(\n      [Missing VERSION file, and unable to generate it; creating bogus VERSION])\n    echo \"0.0.0-0-g0000000000000000000000000000000000000000\" > \"${objroot}VERSION\"\n  else\n    cp ${srcroot}VERSION ${objroot}VERSION\n  fi\nfi\njemalloc_version=`cat \"${objroot}VERSION\"`\njemalloc_version_major=`echo ${jemalloc_version} | tr \".g-\" \" \" | awk '{print [$]1}'`\njemalloc_version_minor=`echo ${jemalloc_version} | tr \".g-\" \" \" | awk '{print [$]2}'`\njemalloc_version_bugfix=`echo ${jemalloc_version} | tr \".g-\" \" \" | awk '{print [$]3}'`\njemalloc_version_nrev=`echo ${jemalloc_version} | tr \".g-\" \" \" | awk '{print [$]4}'`\njemalloc_version_gid=`echo ${jemalloc_version} | tr \".g-\" \" \" | awk '{print [$]5}'`\nAC_SUBST([jemalloc_version])\nAC_SUBST([jemalloc_version_major])\nAC_SUBST([jemalloc_version_minor])\nAC_SUBST([jemalloc_version_bugfix])\nAC_SUBST([jemalloc_version_nrev])\nAC_SUBST([jemalloc_version_gid])\n\ndnl ============================================================================\ndnl Configure pthreads.\n\nif test \"x$abi\" != \"xpecoff\" ; then\n  AC_CHECK_HEADERS([pthread.h], , [AC_MSG_ERROR([pthread.h is missing])])\n  dnl Some systems may embed pthreads functionality in libc; check for libpthread\n  dnl first, but try libc too before failing.\n  AC_CHECK_LIB([pthread], [pthread_create], [LIBS=\"$LIBS -lpthread\"],\n               [AC_SEARCH_LIBS([pthread_create], , ,\n                               AC_MSG_ERROR([libpthread is missing]))])\nfi\n\nCPPFLAGS=\"$CPPFLAGS -D_REENTRANT\"\n\ndnl Check whether clock_gettime(2) is in libc or librt.\nAC_SEARCH_LIBS([clock_gettime], [rt])\n\ndnl Check if the GNU-specific secure_getenv function exists.\nAC_CHECK_FUNC([secure_getenv],\n              [have_secure_getenv=\"1\"],\n              [have_secure_getenv=\"0\"]\n             )\nif test \"x$have_secure_getenv\" = \"x1\" ; then\n  AC_DEFINE([JEMALLOC_HAVE_SECURE_GETENV], [ ])\nfi\n\ndnl Check if the Solaris/BSD issetugid function exists.\nAC_CHECK_FUNC([issetugid],\n              [have_issetugid=\"1\"],\n              [have_issetugid=\"0\"]\n             )\nif test \"x$have_issetugid\" = \"x1\" ; then\n  AC_DEFINE([JEMALLOC_HAVE_ISSETUGID], [ ])\nfi\n\ndnl Check whether the BSD-specific _malloc_thread_cleanup() exists.  If so, use\ndnl it rather than pthreads TSD cleanup functions to support cleanup during\ndnl thread exit, in order to avoid pthreads library recursion during\ndnl bootstrapping.\nAC_CHECK_FUNC([_malloc_thread_cleanup],\n              [have__malloc_thread_cleanup=\"1\"],\n              [have__malloc_thread_cleanup=\"0\"]\n             )\nif test \"x$have__malloc_thread_cleanup\" = \"x1\" ; then\n  AC_DEFINE([JEMALLOC_MALLOC_THREAD_CLEANUP], [ ])\n  force_tls=\"1\"\nfi\n\ndnl Check whether the BSD-specific _pthread_mutex_init_calloc_cb() exists.  If\ndnl so, mutex initialization causes allocation, and we need to implement this\ndnl callback function in order to prevent recursive allocation.\nAC_CHECK_FUNC([_pthread_mutex_init_calloc_cb],\n              [have__pthread_mutex_init_calloc_cb=\"1\"],\n              [have__pthread_mutex_init_calloc_cb=\"0\"]\n             )\nif test \"x$have__pthread_mutex_init_calloc_cb\" = \"x1\" ; then\n  AC_DEFINE([JEMALLOC_MUTEX_INIT_CB])\nfi\n\ndnl Disable lazy locking by default.\nAC_ARG_ENABLE([lazy_lock],\n  [AS_HELP_STRING([--enable-lazy-lock],\n  [Enable lazy locking (only lock when multi-threaded)])],\n[if test \"x$enable_lazy_lock\" = \"xno\" ; then\n  enable_lazy_lock=\"0\"\nelse\n  enable_lazy_lock=\"1\"\nfi\n],\n[enable_lazy_lock=\"\"]\n)\nif test \"x$enable_lazy_lock\" = \"x\" -a \"x${force_lazy_lock}\" = \"x1\" ; then\n  AC_MSG_RESULT([Forcing lazy-lock to avoid allocator/threading bootstrap issues])\n  enable_lazy_lock=\"1\"\nfi\nif test \"x$enable_lazy_lock\" = \"x1\" ; then\n  if test \"x$abi\" != \"xpecoff\" ; then\n    AC_CHECK_HEADERS([dlfcn.h], , [AC_MSG_ERROR([dlfcn.h is missing])])\n    AC_CHECK_FUNC([dlsym], [],\n      [AC_CHECK_LIB([dl], [dlsym], [LIBS=\"$LIBS -ldl\"],\n                    [AC_MSG_ERROR([libdl is missing])])\n      ])\n  fi\n  AC_DEFINE([JEMALLOC_LAZY_LOCK], [ ])\nelse\n  enable_lazy_lock=\"0\"\nfi\nAC_SUBST([enable_lazy_lock])\n\nAC_ARG_ENABLE([tls],\n  [AS_HELP_STRING([--disable-tls], [Disable thread-local storage (__thread keyword)])],\nif test \"x$enable_tls\" = \"xno\" ; then\n  enable_tls=\"0\"\nelse\n  enable_tls=\"1\"\nfi\n,\nenable_tls=\"\"\n)\nif test \"x${enable_tls}\" = \"x\" ; then\n  if test \"x${force_tls}\" = \"x1\" ; then\n    AC_MSG_RESULT([Forcing TLS to avoid allocator/threading bootstrap issues])\n    enable_tls=\"1\"\n  elif test \"x${force_tls}\" = \"x0\" ; then\n    AC_MSG_RESULT([Forcing no TLS to avoid allocator/threading bootstrap issues])\n    enable_tls=\"0\"\n  else\n    enable_tls=\"1\"\n  fi\nfi\nif test \"x${enable_tls}\" = \"x1\" ; then\nAC_MSG_CHECKING([for TLS])\nAC_COMPILE_IFELSE([AC_LANG_PROGRAM(\n[[\n    __thread int x;\n]], [[\n    x = 42;\n\n    return 0;\n]])],\n              AC_MSG_RESULT([yes]),\n              AC_MSG_RESULT([no])\n              enable_tls=\"0\")\nelse\n  enable_tls=\"0\"\nfi\nAC_SUBST([enable_tls])\nif test \"x${enable_tls}\" = \"x1\" ; then\n  if test \"x${force_tls}\" = \"x0\" ; then\n    AC_MSG_WARN([TLS enabled despite being marked unusable on this platform])\n  fi\n  AC_DEFINE_UNQUOTED([JEMALLOC_TLS], [ ])\nelif test \"x${force_tls}\" = \"x1\" ; then\n  AC_MSG_WARN([TLS disabled despite being marked critical on this platform])\nfi\n\ndnl ============================================================================\ndnl Check for C11 atomics.\n\nJE_COMPILABLE([C11 atomics], [\n#include <stdint.h>\n#if (__STDC_VERSION__ >= 201112L) && !defined(__STDC_NO_ATOMICS__)\n#include <stdatomic.h>\n#else\n#error Atomics not available\n#endif\n], [\n    uint64_t *p = (uint64_t *)0;\n    uint64_t x = 1;\n    volatile atomic_uint_least64_t *a = (volatile atomic_uint_least64_t *)p;\n    uint64_t r = atomic_fetch_add(a, x) + x;\n    return (r == 0);\n], [je_cv_c11atomics])\nif test \"x${je_cv_c11atomics}\" = \"xyes\" ; then\n  AC_DEFINE([JEMALLOC_C11ATOMICS])\nfi\n\ndnl ============================================================================\ndnl Check for atomic(9) operations as provided on FreeBSD.\n\nJE_COMPILABLE([atomic(9)], [\n#include <sys/types.h>\n#include <machine/atomic.h>\n#include <inttypes.h>\n], [\n\t{\n\t\tuint32_t x32 = 0;\n\t\tvolatile uint32_t *x32p = &x32;\n\t\tatomic_fetchadd_32(x32p, 1);\n\t}\n\t{\n\t\tunsigned long xlong = 0;\n\t\tvolatile unsigned long *xlongp = &xlong;\n\t\tatomic_fetchadd_long(xlongp, 1);\n\t}\n], [je_cv_atomic9])\nif test \"x${je_cv_atomic9}\" = \"xyes\" ; then\n  AC_DEFINE([JEMALLOC_ATOMIC9])\nfi\n\ndnl ============================================================================\ndnl Check for atomic(3) operations as provided on Darwin.\n\nJE_COMPILABLE([Darwin OSAtomic*()], [\n#include <libkern/OSAtomic.h>\n#include <inttypes.h>\n], [\n\t{\n\t\tint32_t x32 = 0;\n\t\tvolatile int32_t *x32p = &x32;\n\t\tOSAtomicAdd32(1, x32p);\n\t}\n\t{\n\t\tint64_t x64 = 0;\n\t\tvolatile int64_t *x64p = &x64;\n\t\tOSAtomicAdd64(1, x64p);\n\t}\n], [je_cv_osatomic])\nif test \"x${je_cv_osatomic}\" = \"xyes\" ; then\n  AC_DEFINE([JEMALLOC_OSATOMIC], [ ])\nfi\n\ndnl ============================================================================\ndnl Check for madvise(2).\n\nJE_COMPILABLE([madvise(2)], [\n#include <sys/mman.h>\n], [\n\t{\n\t\tmadvise((void *)0, 0, 0);\n\t}\n], [je_cv_madvise])\nif test \"x${je_cv_madvise}\" = \"xyes\" ; then\n  AC_DEFINE([JEMALLOC_HAVE_MADVISE], [ ])\nfi\n\ndnl ============================================================================\ndnl Check whether __sync_{add,sub}_and_fetch() are available despite\ndnl __GCC_HAVE_SYNC_COMPARE_AND_SWAP_n macros being undefined.\n\nAC_DEFUN([JE_SYNC_COMPARE_AND_SWAP_CHECK],[\n  AC_CACHE_CHECK([whether to force $1-bit __sync_{add,sub}_and_fetch()],\n               [je_cv_sync_compare_and_swap_$2],\n               [AC_LINK_IFELSE([AC_LANG_PROGRAM([\n                                                 #include <stdint.h>\n                                                ],\n                                                [\n                                                 #ifndef __GCC_HAVE_SYNC_COMPARE_AND_SWAP_$2\n                                                 {\n                                                    uint$1_t x$1 = 0;\n                                                    __sync_add_and_fetch(&x$1, 42);\n                                                    __sync_sub_and_fetch(&x$1, 1);\n                                                 }\n                                                 #else\n                                                 #error __GCC_HAVE_SYNC_COMPARE_AND_SWAP_$2 is defined, no need to force\n                                                 #endif\n                                                ])],\n                               [je_cv_sync_compare_and_swap_$2=yes],\n                               [je_cv_sync_compare_and_swap_$2=no])])\n\n  if test \"x${je_cv_sync_compare_and_swap_$2}\" = \"xyes\" ; then\n    AC_DEFINE([JE_FORCE_SYNC_COMPARE_AND_SWAP_$2], [ ])\n  fi\n])\n\nif test \"x${je_cv_atomic9}\" != \"xyes\" -a \"x${je_cv_osatomic}\" != \"xyes\" ; then\n  JE_SYNC_COMPARE_AND_SWAP_CHECK(32, 4)\n  JE_SYNC_COMPARE_AND_SWAP_CHECK(64, 8)\nfi\n\ndnl ============================================================================\ndnl Check for __builtin_clz() and __builtin_clzl().\n\nAC_CACHE_CHECK([for __builtin_clz],\n               [je_cv_builtin_clz],\n               [AC_LINK_IFELSE([AC_LANG_PROGRAM([],\n                                                [\n                                                {\n                                                        unsigned x = 0;\n                                                        int y = __builtin_clz(x);\n                                                }\n                                                {\n                                                        unsigned long x = 0;\n                                                        int y = __builtin_clzl(x);\n                                                }\n                                                ])],\n                               [je_cv_builtin_clz=yes],\n                               [je_cv_builtin_clz=no])])\n\nif test \"x${je_cv_builtin_clz}\" = \"xyes\" ; then\n  AC_DEFINE([JEMALLOC_HAVE_BUILTIN_CLZ], [ ])\nfi\n\ndnl ============================================================================\ndnl Check for spinlock(3) operations as provided on Darwin.\n\nJE_COMPILABLE([Darwin OSSpin*()], [\n#include <libkern/OSAtomic.h>\n#include <inttypes.h>\n], [\n\tOSSpinLock lock = 0;\n\tOSSpinLockLock(&lock);\n\tOSSpinLockUnlock(&lock);\n], [je_cv_osspin])\nif test \"x${je_cv_osspin}\" = \"xyes\" ; then\n  AC_DEFINE([JEMALLOC_OSSPIN], [ ])\nfi\n\ndnl ============================================================================\ndnl Darwin-related configuration.\n\nAC_ARG_ENABLE([zone-allocator],\n  [AS_HELP_STRING([--disable-zone-allocator],\n                  [Disable zone allocator for Darwin])],\n[if test \"x$enable_zone_allocator\" = \"xno\" ; then\n  enable_zone_allocator=\"0\"\nelse\n  enable_zone_allocator=\"1\"\nfi\n],\n[if test \"x${abi}\" = \"xmacho\"; then\n  enable_zone_allocator=\"1\"\nfi\n]\n)\nAC_SUBST([enable_zone_allocator])\n\nif test \"x${enable_zone_allocator}\" = \"x1\" ; then\n  if test \"x${abi}\" != \"xmacho\"; then\n    AC_MSG_ERROR([--enable-zone-allocator is only supported on Darwin])\n  fi\n  AC_DEFINE([JEMALLOC_ZONE], [ ])\n\n  dnl The szone version jumped from 3 to 6 between the OS X 10.5.x and 10.6\n  dnl releases.  malloc_zone_t and malloc_introspection_t have new fields in\n  dnl 10.6, which is the only source-level indication of the change.\n  AC_MSG_CHECKING([malloc zone version])\n  AC_DEFUN([JE_ZONE_PROGRAM],\n    [AC_LANG_PROGRAM(\n      [#include <malloc/malloc.h>],\n      [static int foo[[sizeof($1) $2 sizeof(void *) * $3 ? 1 : -1]]]\n    )])\n\n  AC_COMPILE_IFELSE([JE_ZONE_PROGRAM(malloc_zone_t,==,14)],[JEMALLOC_ZONE_VERSION=3],[\n  AC_COMPILE_IFELSE([JE_ZONE_PROGRAM(malloc_zone_t,==,15)],[JEMALLOC_ZONE_VERSION=5],[\n  AC_COMPILE_IFELSE([JE_ZONE_PROGRAM(malloc_zone_t,==,16)],[\n    AC_COMPILE_IFELSE([JE_ZONE_PROGRAM(malloc_introspection_t,==,9)],[JEMALLOC_ZONE_VERSION=6],[\n    AC_COMPILE_IFELSE([JE_ZONE_PROGRAM(malloc_introspection_t,==,13)],[JEMALLOC_ZONE_VERSION=7],[JEMALLOC_ZONE_VERSION=]\n  )])],[\n  AC_COMPILE_IFELSE([JE_ZONE_PROGRAM(malloc_zone_t,==,17)],[JEMALLOC_ZONE_VERSION=8],[\n  AC_COMPILE_IFELSE([JE_ZONE_PROGRAM(malloc_zone_t,>,17)],[JEMALLOC_ZONE_VERSION=9],[JEMALLOC_ZONE_VERSION=]\n  )])])])])\n  if test \"x${JEMALLOC_ZONE_VERSION}\" = \"x\"; then\n    AC_MSG_RESULT([unsupported])\n    AC_MSG_ERROR([Unsupported malloc zone version])\n  fi\n  if test \"${JEMALLOC_ZONE_VERSION}\" = 9; then\n    JEMALLOC_ZONE_VERSION=8\n    AC_MSG_RESULT([> 8])\n  else\n    AC_MSG_RESULT([$JEMALLOC_ZONE_VERSION])\n  fi\n  AC_DEFINE_UNQUOTED(JEMALLOC_ZONE_VERSION, [$JEMALLOC_ZONE_VERSION])\nfi\n\ndnl ============================================================================\ndnl Check for glibc malloc hooks\n\nJE_COMPILABLE([glibc malloc hook], [\n#include <stddef.h>\n\nextern void (* __free_hook)(void *ptr);\nextern void *(* __malloc_hook)(size_t size);\nextern void *(* __realloc_hook)(void *ptr, size_t size);\n], [\n  void *ptr = 0L;\n  if (__malloc_hook) ptr = __malloc_hook(1);\n  if (__realloc_hook) ptr = __realloc_hook(ptr, 2);\n  if (__free_hook && ptr) __free_hook(ptr);\n], [je_cv_glibc_malloc_hook])\nif test \"x${je_cv_glibc_malloc_hook}\" = \"xyes\" ; then\n  AC_DEFINE([JEMALLOC_GLIBC_MALLOC_HOOK], [ ])\nfi\n\nJE_COMPILABLE([glibc memalign hook], [\n#include <stddef.h>\n\nextern void *(* __memalign_hook)(size_t alignment, size_t size);\n], [\n  void *ptr = 0L;\n  if (__memalign_hook) ptr = __memalign_hook(16, 7);\n], [je_cv_glibc_memalign_hook])\nif test \"x${je_cv_glibc_memalign_hook}\" = \"xyes\" ; then\n  AC_DEFINE([JEMALLOC_GLIBC_MEMALIGN_HOOK], [ ])\nfi\n\nJE_COMPILABLE([pthreads adaptive mutexes], [\n#include <pthread.h>\n], [\n  pthread_mutexattr_t attr;\n  pthread_mutexattr_init(&attr);\n  pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_ADAPTIVE_NP);\n  pthread_mutexattr_destroy(&attr);\n], [je_cv_pthread_mutex_adaptive_np])\nif test \"x${je_cv_pthread_mutex_adaptive_np}\" = \"xyes\" ; then\n  AC_DEFINE([JEMALLOC_HAVE_PTHREAD_MUTEX_ADAPTIVE_NP], [ ])\nfi\n\ndnl ============================================================================\ndnl Check for typedefs, structures, and compiler characteristics.\nAC_HEADER_STDBOOL\n\ndnl ============================================================================\ndnl Define commands that generate output files.\n\nAC_CONFIG_COMMANDS([include/jemalloc/internal/private_namespace.h], [\n  mkdir -p \"${objroot}include/jemalloc/internal\"\n  \"${srcdir}/include/jemalloc/internal/private_namespace.sh\" \"${srcdir}/include/jemalloc/internal/private_symbols.txt\" > \"${objroot}include/jemalloc/internal/private_namespace.h\"\n], [\n  srcdir=\"${srcdir}\"\n  objroot=\"${objroot}\"\n])\nAC_CONFIG_COMMANDS([include/jemalloc/internal/private_unnamespace.h], [\n  mkdir -p \"${objroot}include/jemalloc/internal\"\n  \"${srcdir}/include/jemalloc/internal/private_unnamespace.sh\" \"${srcdir}/include/jemalloc/internal/private_symbols.txt\" > \"${objroot}include/jemalloc/internal/private_unnamespace.h\"\n], [\n  srcdir=\"${srcdir}\"\n  objroot=\"${objroot}\"\n])\nAC_CONFIG_COMMANDS([include/jemalloc/internal/public_symbols.txt], [\n  f=\"${objroot}include/jemalloc/internal/public_symbols.txt\"\n  mkdir -p \"${objroot}include/jemalloc/internal\"\n  cp /dev/null \"${f}\"\n  for nm in `echo ${mangling_map} |tr ',' ' '` ; do\n    n=`echo ${nm} |tr ':' ' ' |awk '{print $[]1}'`\n    m=`echo ${nm} |tr ':' ' ' |awk '{print $[]2}'`\n    echo \"${n}:${m}\" >> \"${f}\"\n    dnl Remove name from public_syms so that it isn't redefined later.\n    public_syms=`for sym in ${public_syms}; do echo \"${sym}\"; done |grep -v \"^${n}\\$\" |tr '\\n' ' '`\n  done\n  for sym in ${public_syms} ; do\n    n=\"${sym}\"\n    m=\"${JEMALLOC_PREFIX}${sym}\"\n    echo \"${n}:${m}\" >> \"${f}\"\n  done\n], [\n  srcdir=\"${srcdir}\"\n  objroot=\"${objroot}\"\n  mangling_map=\"${mangling_map}\"\n  public_syms=\"${public_syms}\"\n  JEMALLOC_PREFIX=\"${JEMALLOC_PREFIX}\"\n])\nAC_CONFIG_COMMANDS([include/jemalloc/internal/public_namespace.h], [\n  mkdir -p \"${objroot}include/jemalloc/internal\"\n  \"${srcdir}/include/jemalloc/internal/public_namespace.sh\" \"${objroot}include/jemalloc/internal/public_symbols.txt\" > \"${objroot}include/jemalloc/internal/public_namespace.h\"\n], [\n  srcdir=\"${srcdir}\"\n  objroot=\"${objroot}\"\n])\nAC_CONFIG_COMMANDS([include/jemalloc/internal/public_unnamespace.h], [\n  mkdir -p \"${objroot}include/jemalloc/internal\"\n  \"${srcdir}/include/jemalloc/internal/public_unnamespace.sh\" \"${objroot}include/jemalloc/internal/public_symbols.txt\" > \"${objroot}include/jemalloc/internal/public_unnamespace.h\"\n], [\n  srcdir=\"${srcdir}\"\n  objroot=\"${objroot}\"\n])\nAC_CONFIG_COMMANDS([include/jemalloc/internal/size_classes.h], [\n  mkdir -p \"${objroot}include/jemalloc/internal\"\n  \"${SHELL}\" \"${srcdir}/include/jemalloc/internal/size_classes.sh\" \"${LG_QUANTA}\" ${LG_TINY_MIN} \"${LG_PAGE_SIZES}\" ${LG_SIZE_CLASS_GROUP} > \"${objroot}include/jemalloc/internal/size_classes.h\"\n], [\n  SHELL=\"${SHELL}\"\n  srcdir=\"${srcdir}\"\n  objroot=\"${objroot}\"\n  LG_QUANTA=\"${LG_QUANTA}\"\n  LG_TINY_MIN=${LG_TINY_MIN}\n  LG_PAGE_SIZES=\"${LG_PAGE_SIZES}\"\n  LG_SIZE_CLASS_GROUP=${LG_SIZE_CLASS_GROUP}\n])\nAC_CONFIG_COMMANDS([include/jemalloc/jemalloc_protos_jet.h], [\n  mkdir -p \"${objroot}include/jemalloc\"\n  cat \"${srcdir}/include/jemalloc/jemalloc_protos.h.in\" | sed -e 's/@je_@/jet_/g' > \"${objroot}include/jemalloc/jemalloc_protos_jet.h\"\n], [\n  srcdir=\"${srcdir}\"\n  objroot=\"${objroot}\"\n])\nAC_CONFIG_COMMANDS([include/jemalloc/jemalloc_rename.h], [\n  mkdir -p \"${objroot}include/jemalloc\"\n  \"${srcdir}/include/jemalloc/jemalloc_rename.sh\" \"${objroot}include/jemalloc/internal/public_symbols.txt\" > \"${objroot}include/jemalloc/jemalloc_rename.h\"\n], [\n  srcdir=\"${srcdir}\"\n  objroot=\"${objroot}\"\n])\nAC_CONFIG_COMMANDS([include/jemalloc/jemalloc_mangle.h], [\n  mkdir -p \"${objroot}include/jemalloc\"\n  \"${srcdir}/include/jemalloc/jemalloc_mangle.sh\" \"${objroot}include/jemalloc/internal/public_symbols.txt\" je_ > \"${objroot}include/jemalloc/jemalloc_mangle.h\"\n], [\n  srcdir=\"${srcdir}\"\n  objroot=\"${objroot}\"\n])\nAC_CONFIG_COMMANDS([include/jemalloc/jemalloc_mangle_jet.h], [\n  mkdir -p \"${objroot}include/jemalloc\"\n  \"${srcdir}/include/jemalloc/jemalloc_mangle.sh\" \"${objroot}include/jemalloc/internal/public_symbols.txt\" jet_ > \"${objroot}include/jemalloc/jemalloc_mangle_jet.h\"\n], [\n  srcdir=\"${srcdir}\"\n  objroot=\"${objroot}\"\n])\nAC_CONFIG_COMMANDS([include/jemalloc/jemalloc.h], [\n  mkdir -p \"${objroot}include/jemalloc\"\n  \"${srcdir}/include/jemalloc/jemalloc.sh\" \"${objroot}\" > \"${objroot}include/jemalloc/jemalloc${install_suffix}.h\"\n], [\n  srcdir=\"${srcdir}\"\n  objroot=\"${objroot}\"\n  install_suffix=\"${install_suffix}\"\n])\n\ndnl Process .in files.\nAC_SUBST([cfghdrs_in])\nAC_SUBST([cfghdrs_out])\nAC_CONFIG_HEADERS([$cfghdrs_tup])\n\ndnl ============================================================================\ndnl Generate outputs.\n\nAC_CONFIG_FILES([$cfgoutputs_tup config.stamp bin/jemalloc-config bin/jemalloc.sh bin/jeprof])\nAC_SUBST([cfgoutputs_in])\nAC_SUBST([cfgoutputs_out])\nAC_OUTPUT\n\ndnl ============================================================================\ndnl Print out the results of configuration.\nAC_MSG_RESULT([===============================================================================])\nAC_MSG_RESULT([jemalloc version   : ${jemalloc_version}])\nAC_MSG_RESULT([library revision   : ${rev}])\nAC_MSG_RESULT([])\nAC_MSG_RESULT([CONFIG             : ${CONFIG}])\nAC_MSG_RESULT([CC                 : ${CC}])\nAC_MSG_RESULT([CFLAGS             : ${CFLAGS}])\nAC_MSG_RESULT([CPPFLAGS           : ${CPPFLAGS}])\nAC_MSG_RESULT([LDFLAGS            : ${LDFLAGS}])\nAC_MSG_RESULT([EXTRA_LDFLAGS      : ${EXTRA_LDFLAGS}])\nAC_MSG_RESULT([LIBS               : ${LIBS}])\nAC_MSG_RESULT([RPATH_EXTRA        : ${RPATH_EXTRA}])\nAC_MSG_RESULT([])\nAC_MSG_RESULT([XSLTPROC           : ${XSLTPROC}])\nAC_MSG_RESULT([XSLROOT            : ${XSLROOT}])\nAC_MSG_RESULT([])\nAC_MSG_RESULT([PREFIX             : ${PREFIX}])\nAC_MSG_RESULT([BINDIR             : ${BINDIR}])\nAC_MSG_RESULT([DATADIR            : ${DATADIR}])\nAC_MSG_RESULT([INCLUDEDIR         : ${INCLUDEDIR}])\nAC_MSG_RESULT([LIBDIR             : ${LIBDIR}])\nAC_MSG_RESULT([MANDIR             : ${MANDIR}])\nAC_MSG_RESULT([])\nAC_MSG_RESULT([srcroot            : ${srcroot}])\nAC_MSG_RESULT([abs_srcroot        : ${abs_srcroot}])\nAC_MSG_RESULT([objroot            : ${objroot}])\nAC_MSG_RESULT([abs_objroot        : ${abs_objroot}])\nAC_MSG_RESULT([])\nAC_MSG_RESULT([JEMALLOC_PREFIX    : ${JEMALLOC_PREFIX}])\nAC_MSG_RESULT([JEMALLOC_PRIVATE_NAMESPACE])\nAC_MSG_RESULT([                   : ${JEMALLOC_PRIVATE_NAMESPACE}])\nAC_MSG_RESULT([install_suffix     : ${install_suffix}])\nAC_MSG_RESULT([malloc_conf        : ${config_malloc_conf}])\nAC_MSG_RESULT([autogen            : ${enable_autogen}])\nAC_MSG_RESULT([cc-silence         : ${enable_cc_silence}])\nAC_MSG_RESULT([debug              : ${enable_debug}])\nAC_MSG_RESULT([code-coverage      : ${enable_code_coverage}])\nAC_MSG_RESULT([stats              : ${enable_stats}])\nAC_MSG_RESULT([prof               : ${enable_prof}])\nAC_MSG_RESULT([prof-libunwind     : ${enable_prof_libunwind}])\nAC_MSG_RESULT([prof-libgcc        : ${enable_prof_libgcc}])\nAC_MSG_RESULT([prof-gcc           : ${enable_prof_gcc}])\nAC_MSG_RESULT([tcache             : ${enable_tcache}])\nAC_MSG_RESULT([fill               : ${enable_fill}])\nAC_MSG_RESULT([utrace             : ${enable_utrace}])\nAC_MSG_RESULT([valgrind           : ${enable_valgrind}])\nAC_MSG_RESULT([xmalloc            : ${enable_xmalloc}])\nAC_MSG_RESULT([munmap             : ${enable_munmap}])\nAC_MSG_RESULT([lazy_lock          : ${enable_lazy_lock}])\nAC_MSG_RESULT([tls                : ${enable_tls}])\nAC_MSG_RESULT([cache-oblivious    : ${enable_cache_oblivious}])\nAC_MSG_RESULT([===============================================================================])\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/deps/jemalloc/coverage.sh",
    "content": "#!/bin/sh\n\nset -e\n\nobjdir=$1\nsuffix=$2\nshift 2\nobjs=$@\n\ngcov -b -p -f -o \"${objdir}\" ${objs}\n\n# Move gcov outputs so that subsequent gcov invocations won't clobber results\n# for the same sources with different compilation flags.\nfor f in `find . -maxdepth 1 -type f -name '*.gcov'` ; do\n  mv \"${f}\" \"${f}.${suffix}\"\ndone\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/deps/jemalloc/doc/html.xsl.in",
    "content": "<xsl:stylesheet xmlns:xsl=\"http://www.w3.org/1999/XSL/Transform\" version=\"1.0\">\n  <xsl:import href=\"@XSLROOT@/html/docbook.xsl\"/>\n  <xsl:import href=\"@abs_srcroot@doc/stylesheet.xsl\"/>\n</xsl:stylesheet>\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/deps/jemalloc/doc/jemalloc.xml.in",
    "content": "<?xml version='1.0' encoding='UTF-8'?>\n<?xml-stylesheet type=\"text/xsl\"\n        href=\"http://docbook.sourceforge.net/release/xsl/current/manpages/docbook.xsl\"?>\n<!DOCTYPE refentry PUBLIC \"-//OASIS//DTD DocBook XML V4.4//EN\"\n        \"http://www.oasis-open.org/docbook/xml/4.4/docbookx.dtd\" [\n]>\n\n<refentry>\n  <refentryinfo>\n    <title>User Manual</title>\n    <productname>jemalloc</productname>\n    <releaseinfo role=\"version\">@jemalloc_version@</releaseinfo>\n    <authorgroup>\n      <author>\n        <firstname>Jason</firstname>\n        <surname>Evans</surname>\n        <personblurb>Author</personblurb>\n      </author>\n    </authorgroup>\n  </refentryinfo>\n  <refmeta>\n    <refentrytitle>JEMALLOC</refentrytitle>\n    <manvolnum>3</manvolnum>\n  </refmeta>\n  <refnamediv>\n    <refdescriptor>jemalloc</refdescriptor>\n    <refname>jemalloc</refname>\n    <!-- Each refname causes a man page file to be created.  Only if this were\n         the system malloc(3) implementation would these files be appropriate.\n    <refname>malloc</refname>\n    <refname>calloc</refname>\n    <refname>posix_memalign</refname>\n    <refname>aligned_alloc</refname>\n    <refname>realloc</refname>\n    <refname>free</refname>\n    <refname>mallocx</refname>\n    <refname>rallocx</refname>\n    <refname>xallocx</refname>\n    <refname>sallocx</refname>\n    <refname>dallocx</refname>\n    <refname>sdallocx</refname>\n    <refname>nallocx</refname>\n    <refname>mallctl</refname>\n    <refname>mallctlnametomib</refname>\n    <refname>mallctlbymib</refname>\n    <refname>malloc_stats_print</refname>\n    <refname>malloc_usable_size</refname>\n    -->\n    <refpurpose>general purpose memory allocation functions</refpurpose>\n  </refnamediv>\n  <refsect1 id=\"library\">\n    <title>LIBRARY</title>\n    <para>This manual describes jemalloc @jemalloc_version@.  More information\n    can be found at the <ulink\n    url=\"http://www.canonware.com/jemalloc/\">jemalloc website</ulink>.</para>\n  </refsect1>\n  <refsynopsisdiv>\n    <title>SYNOPSIS</title>\n    <funcsynopsis>\n      <funcsynopsisinfo>#include &lt;<filename class=\"headerfile\">jemalloc/jemalloc.h</filename>&gt;</funcsynopsisinfo>\n      <refsect2>\n        <title>Standard API</title>\n        <funcprototype>\n          <funcdef>void *<function>malloc</function></funcdef>\n          <paramdef>size_t <parameter>size</parameter></paramdef>\n        </funcprototype>\n        <funcprototype>\n          <funcdef>void *<function>calloc</function></funcdef>\n          <paramdef>size_t <parameter>number</parameter></paramdef>\n          <paramdef>size_t <parameter>size</parameter></paramdef>\n        </funcprototype>\n        <funcprototype>\n          <funcdef>int <function>posix_memalign</function></funcdef>\n          <paramdef>void **<parameter>ptr</parameter></paramdef>\n          <paramdef>size_t <parameter>alignment</parameter></paramdef>\n          <paramdef>size_t <parameter>size</parameter></paramdef>\n        </funcprototype>\n        <funcprototype>\n          <funcdef>void *<function>aligned_alloc</function></funcdef>\n          <paramdef>size_t <parameter>alignment</parameter></paramdef>\n          <paramdef>size_t <parameter>size</parameter></paramdef>\n        </funcprototype>\n        <funcprototype>\n          <funcdef>void *<function>realloc</function></funcdef>\n          <paramdef>void *<parameter>ptr</parameter></paramdef>\n          <paramdef>size_t <parameter>size</parameter></paramdef>\n        </funcprototype>\n        <funcprototype>\n          <funcdef>void <function>free</function></funcdef>\n          <paramdef>void *<parameter>ptr</parameter></paramdef>\n        </funcprototype>\n      </refsect2>\n      <refsect2>\n        <title>Non-standard API</title>\n        <funcprototype>\n          <funcdef>void *<function>mallocx</function></funcdef>\n          <paramdef>size_t <parameter>size</parameter></paramdef>\n          <paramdef>int <parameter>flags</parameter></paramdef>\n        </funcprototype>\n        <funcprototype>\n          <funcdef>void *<function>rallocx</function></funcdef>\n          <paramdef>void *<parameter>ptr</parameter></paramdef>\n          <paramdef>size_t <parameter>size</parameter></paramdef>\n          <paramdef>int <parameter>flags</parameter></paramdef>\n        </funcprototype>\n        <funcprototype>\n          <funcdef>size_t <function>xallocx</function></funcdef>\n          <paramdef>void *<parameter>ptr</parameter></paramdef>\n          <paramdef>size_t <parameter>size</parameter></paramdef>\n          <paramdef>size_t <parameter>extra</parameter></paramdef>\n          <paramdef>int <parameter>flags</parameter></paramdef>\n        </funcprototype>\n        <funcprototype>\n          <funcdef>size_t <function>sallocx</function></funcdef>\n          <paramdef>void *<parameter>ptr</parameter></paramdef>\n          <paramdef>int <parameter>flags</parameter></paramdef>\n        </funcprototype>\n        <funcprototype>\n          <funcdef>void <function>dallocx</function></funcdef>\n          <paramdef>void *<parameter>ptr</parameter></paramdef>\n          <paramdef>int <parameter>flags</parameter></paramdef>\n        </funcprototype>\n        <funcprototype>\n          <funcdef>void <function>sdallocx</function></funcdef>\n          <paramdef>void *<parameter>ptr</parameter></paramdef>\n          <paramdef>size_t <parameter>size</parameter></paramdef>\n          <paramdef>int <parameter>flags</parameter></paramdef>\n        </funcprototype>\n        <funcprototype>\n          <funcdef>size_t <function>nallocx</function></funcdef>\n          <paramdef>size_t <parameter>size</parameter></paramdef>\n          <paramdef>int <parameter>flags</parameter></paramdef>\n        </funcprototype>\n        <funcprototype>\n          <funcdef>int <function>mallctl</function></funcdef>\n          <paramdef>const char *<parameter>name</parameter></paramdef>\n          <paramdef>void *<parameter>oldp</parameter></paramdef>\n          <paramdef>size_t *<parameter>oldlenp</parameter></paramdef>\n          <paramdef>void *<parameter>newp</parameter></paramdef>\n          <paramdef>size_t <parameter>newlen</parameter></paramdef>\n        </funcprototype>\n        <funcprototype>\n          <funcdef>int <function>mallctlnametomib</function></funcdef>\n          <paramdef>const char *<parameter>name</parameter></paramdef>\n          <paramdef>size_t *<parameter>mibp</parameter></paramdef>\n          <paramdef>size_t *<parameter>miblenp</parameter></paramdef>\n        </funcprototype>\n        <funcprototype>\n          <funcdef>int <function>mallctlbymib</function></funcdef>\n          <paramdef>const size_t *<parameter>mib</parameter></paramdef>\n          <paramdef>size_t <parameter>miblen</parameter></paramdef>\n          <paramdef>void *<parameter>oldp</parameter></paramdef>\n          <paramdef>size_t *<parameter>oldlenp</parameter></paramdef>\n          <paramdef>void *<parameter>newp</parameter></paramdef>\n          <paramdef>size_t <parameter>newlen</parameter></paramdef>\n        </funcprototype>\n        <funcprototype>\n          <funcdef>void <function>malloc_stats_print</function></funcdef>\n          <paramdef>void <parameter>(*write_cb)</parameter>\n            <funcparams>void *, const char *</funcparams>\n          </paramdef>\n          <paramdef>void *<parameter>cbopaque</parameter></paramdef>\n          <paramdef>const char *<parameter>opts</parameter></paramdef>\n        </funcprototype>\n        <funcprototype>\n          <funcdef>size_t <function>malloc_usable_size</function></funcdef>\n          <paramdef>const void *<parameter>ptr</parameter></paramdef>\n        </funcprototype>\n        <funcprototype>\n          <funcdef>void <function>(*malloc_message)</function></funcdef>\n          <paramdef>void *<parameter>cbopaque</parameter></paramdef>\n          <paramdef>const char *<parameter>s</parameter></paramdef>\n        </funcprototype>\n        <para><type>const char *</type><varname>malloc_conf</varname>;</para>\n      </refsect2>\n    </funcsynopsis>\n  </refsynopsisdiv>\n  <refsect1 id=\"description\">\n    <title>DESCRIPTION</title>\n    <refsect2>\n      <title>Standard API</title>\n\n      <para>The <function>malloc<parameter/></function> function allocates\n      <parameter>size</parameter> bytes of uninitialized memory.  The allocated\n      space is suitably aligned (after possible pointer coercion) for storage\n      of any type of object.</para>\n\n      <para>The <function>calloc<parameter/></function> function allocates\n      space for <parameter>number</parameter> objects, each\n      <parameter>size</parameter> bytes in length.  The result is identical to\n      calling <function>malloc<parameter/></function> with an argument of\n      <parameter>number</parameter> * <parameter>size</parameter>, with the\n      exception that the allocated memory is explicitly initialized to zero\n      bytes.</para>\n\n      <para>The <function>posix_memalign<parameter/></function> function\n      allocates <parameter>size</parameter> bytes of memory such that the\n      allocation's base address is a multiple of\n      <parameter>alignment</parameter>, and returns the allocation in the value\n      pointed to by <parameter>ptr</parameter>.  The requested\n      <parameter>alignment</parameter> must be a power of 2 at least as large as\n      <code language=\"C\">sizeof(<type>void *</type>)</code>.</para>\n\n      <para>The <function>aligned_alloc<parameter/></function> function\n      allocates <parameter>size</parameter> bytes of memory such that the\n      allocation's base address is a multiple of\n      <parameter>alignment</parameter>.  The requested\n      <parameter>alignment</parameter> must be a power of 2.  Behavior is\n      undefined if <parameter>size</parameter> is not an integral multiple of\n      <parameter>alignment</parameter>.</para>\n\n      <para>The <function>realloc<parameter/></function> function changes the\n      size of the previously allocated memory referenced by\n      <parameter>ptr</parameter> to <parameter>size</parameter> bytes.  The\n      contents of the memory are unchanged up to the lesser of the new and old\n      sizes.  If the new size is larger, the contents of the newly allocated\n      portion of the memory are undefined.  Upon success, the memory referenced\n      by <parameter>ptr</parameter> is freed and a pointer to the newly\n      allocated memory is returned.  Note that\n      <function>realloc<parameter/></function> may move the memory allocation,\n      resulting in a different return value than <parameter>ptr</parameter>.\n      If <parameter>ptr</parameter> is <constant>NULL</constant>, the\n      <function>realloc<parameter/></function> function behaves identically to\n      <function>malloc<parameter/></function> for the specified size.</para>\n\n      <para>The <function>free<parameter/></function> function causes the\n      allocated memory referenced by <parameter>ptr</parameter> to be made\n      available for future allocations.  If <parameter>ptr</parameter> is\n      <constant>NULL</constant>, no action occurs.</para>\n    </refsect2>\n    <refsect2>\n      <title>Non-standard API</title>\n      <para>The <function>mallocx<parameter/></function>,\n      <function>rallocx<parameter/></function>,\n      <function>xallocx<parameter/></function>,\n      <function>sallocx<parameter/></function>,\n      <function>dallocx<parameter/></function>,\n      <function>sdallocx<parameter/></function>, and\n      <function>nallocx<parameter/></function> functions all have a\n      <parameter>flags</parameter> argument that can be used to specify\n      options.  The functions only check the options that are contextually\n      relevant.  Use bitwise or (<code language=\"C\">|</code>) operations to\n      specify one or more of the following:\n        <variablelist>\n          <varlistentry id=\"MALLOCX_LG_ALIGN\">\n            <term><constant>MALLOCX_LG_ALIGN(<parameter>la</parameter>)\n            </constant></term>\n\n            <listitem><para>Align the memory allocation to start at an address\n            that is a multiple of <code language=\"C\">(1 &lt;&lt;\n            <parameter>la</parameter>)</code>.  This macro does not validate\n            that <parameter>la</parameter> is within the valid\n            range.</para></listitem>\n          </varlistentry>\n          <varlistentry id=\"MALLOCX_ALIGN\">\n            <term><constant>MALLOCX_ALIGN(<parameter>a</parameter>)\n            </constant></term>\n\n            <listitem><para>Align the memory allocation to start at an address\n            that is a multiple of <parameter>a</parameter>, where\n            <parameter>a</parameter> is a power of two.  This macro does not\n            validate that <parameter>a</parameter> is a power of 2.\n            </para></listitem>\n          </varlistentry>\n          <varlistentry id=\"MALLOCX_ZERO\">\n            <term><constant>MALLOCX_ZERO</constant></term>\n\n            <listitem><para>Initialize newly allocated memory to contain zero\n            bytes.  In the growing reallocation case, the real size prior to\n            reallocation defines the boundary between untouched bytes and those\n            that are initialized to contain zero bytes.  If this macro is\n            absent, newly allocated memory is uninitialized.</para></listitem>\n          </varlistentry>\n          <varlistentry id=\"MALLOCX_TCACHE\">\n            <term><constant>MALLOCX_TCACHE(<parameter>tc</parameter>)\n            </constant></term>\n\n            <listitem><para>Use the thread-specific cache (tcache) specified by\n            the identifier <parameter>tc</parameter>, which must have been\n            acquired via the <link\n            linkend=\"tcache.create\"><mallctl>tcache.create</mallctl></link>\n            mallctl.  This macro does not validate that\n            <parameter>tc</parameter> specifies a valid\n            identifier.</para></listitem>\n          </varlistentry>\n          <varlistentry id=\"MALLOC_TCACHE_NONE\">\n            <term><constant>MALLOCX_TCACHE_NONE</constant></term>\n\n            <listitem><para>Do not use a thread-specific cache (tcache).  Unless\n            <constant>MALLOCX_TCACHE(<parameter>tc</parameter>)</constant> or\n            <constant>MALLOCX_TCACHE_NONE</constant> is specified, an\n            automatically managed tcache will be used under many circumstances.\n            This macro cannot be used in the same <parameter>flags</parameter>\n            argument as\n            <constant>MALLOCX_TCACHE(<parameter>tc</parameter>)</constant>.</para></listitem>\n          </varlistentry>\n          <varlistentry id=\"MALLOCX_ARENA\">\n            <term><constant>MALLOCX_ARENA(<parameter>a</parameter>)\n            </constant></term>\n\n            <listitem><para>Use the arena specified by the index\n            <parameter>a</parameter>.  This macro has no effect for regions that\n            were allocated via an arena other than the one specified.  This\n            macro does not validate that <parameter>a</parameter> specifies an\n            arena index in the valid range.</para></listitem>\n          </varlistentry>\n        </variablelist>\n      </para>\n\n      <para>The <function>mallocx<parameter/></function> function allocates at\n      least <parameter>size</parameter> bytes of memory, and returns a pointer\n      to the base address of the allocation.  Behavior is undefined if\n      <parameter>size</parameter> is <constant>0</constant>.</para>\n\n      <para>The <function>rallocx<parameter/></function> function resizes the\n      allocation at <parameter>ptr</parameter> to be at least\n      <parameter>size</parameter> bytes, and returns a pointer to the base\n      address of the resulting allocation, which may or may not have moved from\n      its original location.  Behavior is undefined if\n      <parameter>size</parameter> is <constant>0</constant>.</para>\n\n      <para>The <function>xallocx<parameter/></function> function resizes the\n      allocation at <parameter>ptr</parameter> in place to be at least\n      <parameter>size</parameter> bytes, and returns the real size of the\n      allocation.  If <parameter>extra</parameter> is non-zero, an attempt is\n      made to resize the allocation to be at least <code\n      language=\"C\">(<parameter>size</parameter> +\n      <parameter>extra</parameter>)</code> bytes, though inability to allocate\n      the extra byte(s) will not by itself result in failure to resize.\n      Behavior is undefined if <parameter>size</parameter> is\n      <constant>0</constant>, or if <code\n      language=\"C\">(<parameter>size</parameter> + <parameter>extra</parameter>\n      &gt; <constant>SIZE_T_MAX</constant>)</code>.</para>\n\n      <para>The <function>sallocx<parameter/></function> function returns the\n      real size of the allocation at <parameter>ptr</parameter>.</para>\n\n      <para>The <function>dallocx<parameter/></function> function causes the\n      memory referenced by <parameter>ptr</parameter> to be made available for\n      future allocations.</para>\n\n      <para>The <function>sdallocx<parameter/></function> function is an\n      extension of <function>dallocx<parameter/></function> with a\n      <parameter>size</parameter> parameter to allow the caller to pass in the\n      allocation size as an optimization.  The minimum valid input size is the\n      original requested size of the allocation, and the maximum valid input\n      size is the corresponding value returned by\n      <function>nallocx<parameter/></function> or\n      <function>sallocx<parameter/></function>.</para>\n\n      <para>The <function>nallocx<parameter/></function> function allocates no\n      memory, but it performs the same size computation as the\n      <function>mallocx<parameter/></function> function, and returns the real\n      size of the allocation that would result from the equivalent\n      <function>mallocx<parameter/></function> function call, or\n      <constant>0</constant> if the inputs exceed the maximum supported size\n      class and/or alignment.  Behavior is undefined if\n      <parameter>size</parameter> is <constant>0</constant>.</para>\n\n      <para>The <function>mallctl<parameter/></function> function provides a\n      general interface for introspecting the memory allocator, as well as\n      setting modifiable parameters and triggering actions.  The\n      period-separated <parameter>name</parameter> argument specifies a\n      location in a tree-structured namespace; see the <xref\n      linkend=\"mallctl_namespace\" xrefstyle=\"template:%t\"/> section for\n      documentation on the tree contents.  To read a value, pass a pointer via\n      <parameter>oldp</parameter> to adequate space to contain the value, and a\n      pointer to its length via <parameter>oldlenp</parameter>; otherwise pass\n      <constant>NULL</constant> and <constant>NULL</constant>.  Similarly, to\n      write a value, pass a pointer to the value via\n      <parameter>newp</parameter>, and its length via\n      <parameter>newlen</parameter>; otherwise pass <constant>NULL</constant>\n      and <constant>0</constant>.</para>\n\n      <para>The <function>mallctlnametomib<parameter/></function> function\n      provides a way to avoid repeated name lookups for applications that\n      repeatedly query the same portion of the namespace, by translating a name\n      to a &ldquo;Management Information Base&rdquo; (MIB) that can be passed\n      repeatedly to <function>mallctlbymib<parameter/></function>.  Upon\n      successful return from <function>mallctlnametomib<parameter/></function>,\n      <parameter>mibp</parameter> contains an array of\n      <parameter>*miblenp</parameter> integers, where\n      <parameter>*miblenp</parameter> is the lesser of the number of components\n      in <parameter>name</parameter> and the input value of\n      <parameter>*miblenp</parameter>.  Thus it is possible to pass a\n      <parameter>*miblenp</parameter> that is smaller than the number of\n      period-separated name components, which results in a partial MIB that can\n      be used as the basis for constructing a complete MIB.  For name\n      components that are integers (e.g. the 2 in\n      <link\n      linkend=\"arenas.bin.i.size\"><mallctl>arenas.bin.2.size</mallctl></link>),\n      the corresponding MIB component will always be that integer.  Therefore,\n      it is legitimate to construct code like the following: <programlisting\n      language=\"C\"><![CDATA[\nunsigned nbins, i;\nsize_t mib[4];\nsize_t len, miblen;\n\nlen = sizeof(nbins);\nmallctl(\"arenas.nbins\", &nbins, &len, NULL, 0);\n\nmiblen = 4;\nmallctlnametomib(\"arenas.bin.0.size\", mib, &miblen);\nfor (i = 0; i < nbins; i++) {\n\tsize_t bin_size;\n\n\tmib[2] = i;\n\tlen = sizeof(bin_size);\n\tmallctlbymib(mib, miblen, &bin_size, &len, NULL, 0);\n\t/* Do something with bin_size... */\n}]]></programlisting></para>\n\n      <para>The <function>malloc_stats_print<parameter/></function> function\n      writes human-readable summary statistics via the\n      <parameter>write_cb</parameter> callback function pointer and\n      <parameter>cbopaque</parameter> data passed to\n      <parameter>write_cb</parameter>, or\n      <function>malloc_message<parameter/></function> if\n      <parameter>write_cb</parameter> is <constant>NULL</constant>.  This\n      function can be called repeatedly.  General information that never\n      changes during execution can be omitted by specifying \"g\" as a character\n      within the <parameter>opts</parameter> string.  Note that\n      <function>malloc_message<parameter/></function> uses the\n      <function>mallctl*<parameter/></function> functions internally, so\n      inconsistent statistics can be reported if multiple threads use these\n      functions simultaneously.  If <option>--enable-stats</option> is\n      specified during configuration, &ldquo;m&rdquo; and &ldquo;a&rdquo; can\n      be specified to omit merged arena and per arena statistics, respectively;\n      &ldquo;b&rdquo;, &ldquo;l&rdquo;, and &ldquo;h&rdquo; can be specified to\n      omit per size class statistics for bins, large objects, and huge objects,\n      respectively.  Unrecognized characters are silently ignored.  Note that\n      thread caching may prevent some statistics from being completely up to\n      date, since extra locking would be required to merge counters that track\n      thread cache operations.\n      </para>\n\n      <para>The <function>malloc_usable_size<parameter/></function> function\n      returns the usable size of the allocation pointed to by\n      <parameter>ptr</parameter>.  The return value may be larger than the size\n      that was requested during allocation.  The\n      <function>malloc_usable_size<parameter/></function> function is not a\n      mechanism for in-place <function>realloc<parameter/></function>; rather\n      it is provided solely as a tool for introspection purposes.  Any\n      discrepancy between the requested allocation size and the size reported\n      by <function>malloc_usable_size<parameter/></function> should not be\n      depended on, since such behavior is entirely implementation-dependent.\n      </para>\n    </refsect2>\n  </refsect1>\n  <refsect1 id=\"tuning\">\n    <title>TUNING</title>\n    <para>Once, when the first call is made to one of the memory allocation\n    routines, the allocator initializes its internals based in part on various\n    options that can be specified at compile- or run-time.</para>\n\n    <para>The string specified via <option>--with-malloc-conf</option>, the\n    string pointed to by the global variable <varname>malloc_conf</varname>, the\n    &ldquo;name&rdquo; of the file referenced by the symbolic link named\n    <filename class=\"symlink\">/etc/malloc.conf</filename>, and the value of the\n    environment variable <envar>MALLOC_CONF</envar>, will be interpreted, in\n    that order, from left to right as options.  Note that\n    <varname>malloc_conf</varname> may be read before\n    <function>main<parameter/></function> is entered, so the declaration of\n    <varname>malloc_conf</varname> should specify an initializer that contains\n    the final value to be read by jemalloc.  <option>--with-malloc-conf</option>\n    and <varname>malloc_conf</varname> are compile-time mechanisms, whereas\n    <filename class=\"symlink\">/etc/malloc.conf</filename> and\n    <envar>MALLOC_CONF</envar> can be safely set any time prior to program\n    invocation.</para>\n\n    <para>An options string is a comma-separated list of option:value pairs.\n    There is one key corresponding to each <link\n    linkend=\"opt.abort\"><mallctl>opt.*</mallctl></link> mallctl (see the <xref\n    linkend=\"mallctl_namespace\" xrefstyle=\"template:%t\"/> section for options\n    documentation).  For example, <literal>abort:true,narenas:1</literal> sets\n    the <link linkend=\"opt.abort\"><mallctl>opt.abort</mallctl></link> and <link\n    linkend=\"opt.narenas\"><mallctl>opt.narenas</mallctl></link> options.  Some\n    options have boolean values (true/false), others have integer values (base\n    8, 10, or 16, depending on prefix), and yet others have raw string\n    values.</para>\n  </refsect1>\n  <refsect1 id=\"implementation_notes\">\n    <title>IMPLEMENTATION NOTES</title>\n    <para>Traditionally, allocators have used\n    <citerefentry><refentrytitle>sbrk</refentrytitle>\n    <manvolnum>2</manvolnum></citerefentry> to obtain memory, which is\n    suboptimal for several reasons, including race conditions, increased\n    fragmentation, and artificial limitations on maximum usable memory.  If\n    <citerefentry><refentrytitle>sbrk</refentrytitle>\n    <manvolnum>2</manvolnum></citerefentry> is supported by the operating\n    system, this allocator uses both\n    <citerefentry><refentrytitle>mmap</refentrytitle>\n    <manvolnum>2</manvolnum></citerefentry> and\n    <citerefentry><refentrytitle>sbrk</refentrytitle>\n    <manvolnum>2</manvolnum></citerefentry>, in that order of preference;\n    otherwise only <citerefentry><refentrytitle>mmap</refentrytitle>\n    <manvolnum>2</manvolnum></citerefentry> is used.</para>\n\n    <para>This allocator uses multiple arenas in order to reduce lock\n    contention for threaded programs on multi-processor systems.  This works\n    well with regard to threading scalability, but incurs some costs.  There is\n    a small fixed per-arena overhead, and additionally, arenas manage memory\n    completely independently of each other, which means a small fixed increase\n    in overall memory fragmentation.  These overheads are not generally an\n    issue, given the number of arenas normally used.  Note that using\n    substantially more arenas than the default is not likely to improve\n    performance, mainly due to reduced cache performance.  However, it may make\n    sense to reduce the number of arenas if an application does not make much\n    use of the allocation functions.</para>\n\n    <para>In addition to multiple arenas, unless\n    <option>--disable-tcache</option> is specified during configuration, this\n    allocator supports thread-specific caching for small and large objects, in\n    order to make it possible to completely avoid synchronization for most\n    allocation requests.  Such caching allows very fast allocation in the\n    common case, but it increases memory usage and fragmentation, since a\n    bounded number of objects can remain allocated in each thread cache.</para>\n\n    <para>Memory is conceptually broken into equal-sized chunks, where the chunk\n    size is a power of two that is greater than the page size.  Chunks are\n    always aligned to multiples of the chunk size.  This alignment makes it\n    possible to find metadata for user objects very quickly.  User objects are\n    broken into three categories according to size: small, large, and huge.\n    Multiple small and large objects can reside within a single chunk, whereas\n    huge objects each have one or more chunks backing them.  Each chunk that\n    contains small and/or large objects tracks its contents as runs of\n    contiguous pages (unused, backing a set of small objects, or backing one\n    large object).  The combination of chunk alignment and chunk page maps makes\n    it possible to determine all metadata regarding small and large allocations\n    in constant time.</para>\n\n    <para>Small objects are managed in groups by page runs.  Each run maintains\n    a bitmap to track which regions are in use.  Allocation requests that are no\n    more than half the quantum (8 or 16, depending on architecture) are rounded\n    up to the nearest power of two that is at least <code\n    language=\"C\">sizeof(<type>double</type>)</code>.  All other object size\n    classes are multiples of the quantum, spaced such that there are four size\n    classes for each doubling in size, which limits internal fragmentation to\n    approximately 20% for all but the smallest size classes.  Small size classes\n    are smaller than four times the page size, large size classes are smaller\n    than the chunk size (see the <link\n    linkend=\"opt.lg_chunk\"><mallctl>opt.lg_chunk</mallctl></link> option), and\n    huge size classes extend from the chunk size up to the largest size class\n    that does not exceed <constant>PTRDIFF_MAX</constant>.</para>\n\n    <para>Allocations are packed tightly together, which can be an issue for\n    multi-threaded applications.  If you need to assure that allocations do not\n    suffer from cacheline sharing, round your allocation requests up to the\n    nearest multiple of the cacheline size, or specify cacheline alignment when\n    allocating.</para>\n\n    <para>The <function>realloc<parameter/></function>,\n    <function>rallocx<parameter/></function>, and\n    <function>xallocx<parameter/></function> functions may resize allocations\n    without moving them under limited circumstances.  Unlike the\n    <function>*allocx<parameter/></function> API, the standard API does not\n    officially round up the usable size of an allocation to the nearest size\n    class, so technically it is necessary to call\n    <function>realloc<parameter/></function> to grow e.g. a 9-byte allocation to\n    16 bytes, or shrink a 16-byte allocation to 9 bytes.  Growth and shrinkage\n    trivially succeeds in place as long as the pre-size and post-size both round\n    up to the same size class.  No other API guarantees are made regarding\n    in-place resizing, but the current implementation also tries to resize large\n    and huge allocations in place, as long as the pre-size and post-size are\n    both large or both huge.  In such cases shrinkage always succeeds for large\n    size classes, but for huge size classes the chunk allocator must support\n    splitting (see <link\n    linkend=\"arena.i.chunk_hooks\"><mallctl>arena.&lt;i&gt;.chunk_hooks</mallctl></link>).\n    Growth only succeeds if the trailing memory is currently available, and\n    additionally for huge size classes the chunk allocator must support\n    merging.</para>\n\n    <para>Assuming 2 MiB chunks, 4 KiB pages, and a 16-byte quantum on a\n    64-bit system, the size classes in each category are as shown in <xref\n    linkend=\"size_classes\" xrefstyle=\"template:Table %n\"/>.</para>\n\n    <table xml:id=\"size_classes\" frame=\"all\">\n      <title>Size classes</title>\n      <tgroup cols=\"3\" colsep=\"1\" rowsep=\"1\">\n      <colspec colname=\"c1\" align=\"left\"/>\n      <colspec colname=\"c2\" align=\"right\"/>\n      <colspec colname=\"c3\" align=\"left\"/>\n      <thead>\n        <row>\n          <entry>Category</entry>\n          <entry>Spacing</entry>\n          <entry>Size</entry>\n        </row>\n      </thead>\n      <tbody>\n        <row>\n          <entry morerows=\"8\">Small</entry>\n          <entry>lg</entry>\n          <entry>[8]</entry>\n        </row>\n        <row>\n          <entry>16</entry>\n          <entry>[16, 32, 48, 64, 80, 96, 112, 128]</entry>\n        </row>\n        <row>\n          <entry>32</entry>\n          <entry>[160, 192, 224, 256]</entry>\n        </row>\n        <row>\n          <entry>64</entry>\n          <entry>[320, 384, 448, 512]</entry>\n        </row>\n        <row>\n          <entry>128</entry>\n          <entry>[640, 768, 896, 1024]</entry>\n        </row>\n        <row>\n          <entry>256</entry>\n          <entry>[1280, 1536, 1792, 2048]</entry>\n        </row>\n        <row>\n          <entry>512</entry>\n          <entry>[2560, 3072, 3584, 4096]</entry>\n        </row>\n        <row>\n          <entry>1 KiB</entry>\n          <entry>[5 KiB, 6 KiB, 7 KiB, 8 KiB]</entry>\n        </row>\n        <row>\n          <entry>2 KiB</entry>\n          <entry>[10 KiB, 12 KiB, 14 KiB]</entry>\n        </row>\n        <row>\n          <entry morerows=\"7\">Large</entry>\n          <entry>2 KiB</entry>\n          <entry>[16 KiB]</entry>\n        </row>\n        <row>\n          <entry>4 KiB</entry>\n          <entry>[20 KiB, 24 KiB, 28 KiB, 32 KiB]</entry>\n        </row>\n        <row>\n          <entry>8 KiB</entry>\n          <entry>[40 KiB, 48 KiB, 54 KiB, 64 KiB]</entry>\n        </row>\n        <row>\n          <entry>16 KiB</entry>\n          <entry>[80 KiB, 96 KiB, 112 KiB, 128 KiB]</entry>\n        </row>\n        <row>\n          <entry>32 KiB</entry>\n          <entry>[160 KiB, 192 KiB, 224 KiB, 256 KiB]</entry>\n        </row>\n        <row>\n          <entry>64 KiB</entry>\n          <entry>[320 KiB, 384 KiB, 448 KiB, 512 KiB]</entry>\n        </row>\n        <row>\n          <entry>128 KiB</entry>\n          <entry>[640 KiB, 768 KiB, 896 KiB, 1 MiB]</entry>\n        </row>\n        <row>\n          <entry>256 KiB</entry>\n          <entry>[1280 KiB, 1536 KiB, 1792 KiB]</entry>\n        </row>\n        <row>\n          <entry morerows=\"8\">Huge</entry>\n          <entry>256 KiB</entry>\n          <entry>[2 MiB]</entry>\n        </row>\n        <row>\n          <entry>512 KiB</entry>\n          <entry>[2560 KiB, 3 MiB, 3584 KiB, 4 MiB]</entry>\n        </row>\n        <row>\n          <entry>1 MiB</entry>\n          <entry>[5 MiB, 6 MiB, 7 MiB, 8 MiB]</entry>\n        </row>\n        <row>\n          <entry>2 MiB</entry>\n          <entry>[10 MiB, 12 MiB, 14 MiB, 16 MiB]</entry>\n        </row>\n        <row>\n          <entry>4 MiB</entry>\n          <entry>[20 MiB, 24 MiB, 28 MiB, 32 MiB]</entry>\n        </row>\n        <row>\n          <entry>8 MiB</entry>\n          <entry>[40 MiB, 48 MiB, 56 MiB, 64 MiB]</entry>\n        </row>\n        <row>\n          <entry>...</entry>\n          <entry>...</entry>\n        </row>\n        <row>\n          <entry>512 PiB</entry>\n          <entry>[2560 PiB, 3 EiB, 3584 PiB, 4 EiB]</entry>\n        </row>\n        <row>\n          <entry>1 EiB</entry>\n          <entry>[5 EiB, 6 EiB, 7 EiB]</entry>\n        </row>\n      </tbody>\n      </tgroup>\n    </table>\n  </refsect1>\n  <refsect1 id=\"mallctl_namespace\">\n    <title>MALLCTL NAMESPACE</title>\n    <para>The following names are defined in the namespace accessible via the\n    <function>mallctl*<parameter/></function> functions.  Value types are\n    specified in parentheses, their readable/writable statuses are encoded as\n    <literal>rw</literal>, <literal>r-</literal>, <literal>-w</literal>, or\n    <literal>--</literal>, and required build configuration flags follow, if\n    any.  A name element encoded as <literal>&lt;i&gt;</literal> or\n    <literal>&lt;j&gt;</literal> indicates an integer component, where the\n    integer varies from 0 to some upper value that must be determined via\n    introspection.  In the case of <mallctl>stats.arenas.&lt;i&gt;.*</mallctl>,\n    <literal>&lt;i&gt;</literal> equal to <link\n    linkend=\"arenas.narenas\"><mallctl>arenas.narenas</mallctl></link> can be\n    used to access the summation of statistics from all arenas.  Take special\n    note of the <link linkend=\"epoch\"><mallctl>epoch</mallctl></link> mallctl,\n    which controls refreshing of cached dynamic statistics.</para>\n\n    <variablelist>\n      <varlistentry id=\"version\">\n        <term>\n          <mallctl>version</mallctl>\n          (<type>const char *</type>)\n          <literal>r-</literal>\n        </term>\n        <listitem><para>Return the jemalloc version string.</para></listitem>\n      </varlistentry>\n\n      <varlistentry id=\"epoch\">\n        <term>\n          <mallctl>epoch</mallctl>\n          (<type>uint64_t</type>)\n          <literal>rw</literal>\n        </term>\n        <listitem><para>If a value is passed in, refresh the data from which\n        the <function>mallctl*<parameter/></function> functions report values,\n        and increment the epoch.  Return the current epoch.  This is useful for\n        detecting whether another thread caused a refresh.</para></listitem>\n      </varlistentry>\n\n      <varlistentry id=\"config.cache_oblivious\">\n        <term>\n          <mallctl>config.cache_oblivious</mallctl>\n          (<type>bool</type>)\n          <literal>r-</literal>\n        </term>\n        <listitem><para><option>--enable-cache-oblivious</option> was specified\n        during build configuration.</para></listitem>\n      </varlistentry>\n\n      <varlistentry id=\"config.debug\">\n        <term>\n          <mallctl>config.debug</mallctl>\n          (<type>bool</type>)\n          <literal>r-</literal>\n        </term>\n        <listitem><para><option>--enable-debug</option> was specified during\n        build configuration.</para></listitem>\n      </varlistentry>\n\n      <varlistentry id=\"config.fill\">\n        <term>\n          <mallctl>config.fill</mallctl>\n          (<type>bool</type>)\n          <literal>r-</literal>\n        </term>\n        <listitem><para><option>--enable-fill</option> was specified during\n        build configuration.</para></listitem>\n      </varlistentry>\n\n      <varlistentry id=\"config.lazy_lock\">\n        <term>\n          <mallctl>config.lazy_lock</mallctl>\n          (<type>bool</type>)\n          <literal>r-</literal>\n        </term>\n        <listitem><para><option>--enable-lazy-lock</option> was specified\n        during build configuration.</para></listitem>\n      </varlistentry>\n\n      <varlistentry id=\"config.malloc_conf\">\n        <term>\n          <mallctl>config.malloc_conf</mallctl>\n          (<type>const char *</type>)\n          <literal>r-</literal>\n        </term>\n        <listitem><para>Embedded configure-time-specified run-time options\n        string, empty unless <option>--with-malloc-conf</option> was specified\n        during build configuration.</para></listitem>\n      </varlistentry>\n\n      <varlistentry id=\"config.munmap\">\n        <term>\n          <mallctl>config.munmap</mallctl>\n          (<type>bool</type>)\n          <literal>r-</literal>\n        </term>\n        <listitem><para><option>--enable-munmap</option> was specified during\n        build configuration.</para></listitem>\n      </varlistentry>\n\n      <varlistentry id=\"config.prof\">\n        <term>\n          <mallctl>config.prof</mallctl>\n          (<type>bool</type>)\n          <literal>r-</literal>\n        </term>\n        <listitem><para><option>--enable-prof</option> was specified during\n        build configuration.</para></listitem>\n      </varlistentry>\n\n      <varlistentry id=\"config.prof_libgcc\">\n        <term>\n          <mallctl>config.prof_libgcc</mallctl>\n          (<type>bool</type>)\n          <literal>r-</literal>\n        </term>\n        <listitem><para><option>--disable-prof-libgcc</option> was not\n        specified during build configuration.</para></listitem>\n      </varlistentry>\n\n      <varlistentry id=\"config.prof_libunwind\">\n        <term>\n          <mallctl>config.prof_libunwind</mallctl>\n          (<type>bool</type>)\n          <literal>r-</literal>\n        </term>\n        <listitem><para><option>--enable-prof-libunwind</option> was specified\n        during build configuration.</para></listitem>\n      </varlistentry>\n\n      <varlistentry id=\"config.stats\">\n        <term>\n          <mallctl>config.stats</mallctl>\n          (<type>bool</type>)\n          <literal>r-</literal>\n        </term>\n        <listitem><para><option>--enable-stats</option> was specified during\n        build configuration.</para></listitem>\n      </varlistentry>\n\n      <varlistentry id=\"config.tcache\">\n        <term>\n          <mallctl>config.tcache</mallctl>\n          (<type>bool</type>)\n          <literal>r-</literal>\n        </term>\n        <listitem><para><option>--disable-tcache</option> was not specified\n        during build configuration.</para></listitem>\n      </varlistentry>\n\n      <varlistentry id=\"config.tls\">\n        <term>\n          <mallctl>config.tls</mallctl>\n          (<type>bool</type>)\n          <literal>r-</literal>\n        </term>\n        <listitem><para><option>--disable-tls</option> was not specified during\n        build configuration.</para></listitem>\n      </varlistentry>\n\n      <varlistentry id=\"config.utrace\">\n        <term>\n          <mallctl>config.utrace</mallctl>\n          (<type>bool</type>)\n          <literal>r-</literal>\n        </term>\n        <listitem><para><option>--enable-utrace</option> was specified during\n        build configuration.</para></listitem>\n      </varlistentry>\n\n      <varlistentry id=\"config.valgrind\">\n        <term>\n          <mallctl>config.valgrind</mallctl>\n          (<type>bool</type>)\n          <literal>r-</literal>\n        </term>\n        <listitem><para><option>--enable-valgrind</option> was specified during\n        build configuration.</para></listitem>\n      </varlistentry>\n\n      <varlistentry id=\"config.xmalloc\">\n        <term>\n          <mallctl>config.xmalloc</mallctl>\n          (<type>bool</type>)\n          <literal>r-</literal>\n        </term>\n        <listitem><para><option>--enable-xmalloc</option> was specified during\n        build configuration.</para></listitem>\n      </varlistentry>\n\n      <varlistentry id=\"opt.abort\">\n        <term>\n          <mallctl>opt.abort</mallctl>\n          (<type>bool</type>)\n          <literal>r-</literal>\n        </term>\n        <listitem><para>Abort-on-warning enabled/disabled.  If true, most\n        warnings are fatal.  The process will call\n        <citerefentry><refentrytitle>abort</refentrytitle>\n        <manvolnum>3</manvolnum></citerefentry> in these cases.  This option is\n        disabled by default unless <option>--enable-debug</option> is\n        specified during configuration, in which case it is enabled by default.\n        </para></listitem>\n      </varlistentry>\n\n      <varlistentry id=\"opt.dss\">\n        <term>\n          <mallctl>opt.dss</mallctl>\n          (<type>const char *</type>)\n          <literal>r-</literal>\n        </term>\n        <listitem><para>dss (<citerefentry><refentrytitle>sbrk</refentrytitle>\n        <manvolnum>2</manvolnum></citerefentry>) allocation precedence as\n        related to <citerefentry><refentrytitle>mmap</refentrytitle>\n        <manvolnum>2</manvolnum></citerefentry> allocation.  The following\n        settings are supported if\n        <citerefentry><refentrytitle>sbrk</refentrytitle>\n        <manvolnum>2</manvolnum></citerefentry> is supported by the operating\n        system: &ldquo;disabled&rdquo;, &ldquo;primary&rdquo;, and\n        &ldquo;secondary&rdquo;; otherwise only &ldquo;disabled&rdquo; is\n        supported.  The default is &ldquo;secondary&rdquo; if\n        <citerefentry><refentrytitle>sbrk</refentrytitle>\n        <manvolnum>2</manvolnum></citerefentry> is supported by the operating\n        system; &ldquo;disabled&rdquo; otherwise.\n        </para></listitem>\n      </varlistentry>\n\n      <varlistentry id=\"opt.lg_chunk\">\n        <term>\n          <mallctl>opt.lg_chunk</mallctl>\n          (<type>size_t</type>)\n          <literal>r-</literal>\n        </term>\n        <listitem><para>Virtual memory chunk size (log base 2).  If a chunk\n        size outside the supported size range is specified, the size is\n        silently clipped to the minimum/maximum supported size.  The default\n        chunk size is 2 MiB (2^21).\n        </para></listitem>\n      </varlistentry>\n\n      <varlistentry id=\"opt.narenas\">\n        <term>\n          <mallctl>opt.narenas</mallctl>\n          (<type>unsigned</type>)\n          <literal>r-</literal>\n        </term>\n        <listitem><para>Maximum number of arenas to use for automatic\n        multiplexing of threads and arenas.  The default is four times the\n        number of CPUs, or one if there is a single CPU.</para></listitem>\n      </varlistentry>\n\n      <varlistentry id=\"opt.purge\">\n        <term>\n          <mallctl>opt.purge</mallctl>\n          (<type>const char *</type>)\n          <literal>r-</literal>\n        </term>\n        <listitem><para>Purge mode is &ldquo;ratio&rdquo; (default) or\n        &ldquo;decay&rdquo;.  See <link\n        linkend=\"opt.lg_dirty_mult\"><mallctl>opt.lg_dirty_mult</mallctl></link>\n        for details of the ratio mode.  See <link\n        linkend=\"opt.decay_time\"><mallctl>opt.decay_time</mallctl></link> for\n        details of the decay mode.</para></listitem>\n      </varlistentry>\n\n      <varlistentry id=\"opt.lg_dirty_mult\">\n        <term>\n          <mallctl>opt.lg_dirty_mult</mallctl>\n          (<type>ssize_t</type>)\n          <literal>r-</literal>\n        </term>\n        <listitem><para>Per-arena minimum ratio (log base 2) of active to dirty\n        pages.  Some dirty unused pages may be allowed to accumulate, within\n        the limit set by the ratio (or one chunk worth of dirty pages,\n        whichever is greater), before informing the kernel about some of those\n        pages via <citerefentry><refentrytitle>madvise</refentrytitle>\n        <manvolnum>2</manvolnum></citerefentry> or a similar system call.  This\n        provides the kernel with sufficient information to recycle dirty pages\n        if physical memory becomes scarce and the pages remain unused.  The\n        default minimum ratio is 8:1 (2^3:1); an option value of -1 will\n        disable dirty page purging.  See <link\n        linkend=\"arenas.lg_dirty_mult\"><mallctl>arenas.lg_dirty_mult</mallctl></link>\n        and <link\n        linkend=\"arena.i.lg_dirty_mult\"><mallctl>arena.&lt;i&gt;.lg_dirty_mult</mallctl></link>\n        for related dynamic control options.</para></listitem>\n      </varlistentry>\n\n      <varlistentry id=\"opt.decay_time\">\n        <term>\n          <mallctl>opt.decay_time</mallctl>\n          (<type>ssize_t</type>)\n          <literal>r-</literal>\n        </term>\n        <listitem><para>Approximate time in seconds from the creation of a set\n        of unused dirty pages until an equivalent set of unused dirty pages is\n        purged and/or reused.  The pages are incrementally purged according to a\n        sigmoidal decay curve that starts and ends with zero purge rate.  A\n        decay time of 0 causes all unused dirty pages to be purged immediately\n        upon creation.  A decay time of -1 disables purging.  The default decay\n        time is 10 seconds.  See <link\n        linkend=\"arenas.decay_time\"><mallctl>arenas.decay_time</mallctl></link>\n        and <link\n        linkend=\"arena.i.decay_time\"><mallctl>arena.&lt;i&gt;.decay_time</mallctl></link>\n        for related dynamic control options.\n        </para></listitem>\n      </varlistentry>\n\n      <varlistentry id=\"opt.stats_print\">\n        <term>\n          <mallctl>opt.stats_print</mallctl>\n          (<type>bool</type>)\n          <literal>r-</literal>\n        </term>\n        <listitem><para>Enable/disable statistics printing at exit.  If\n        enabled, the <function>malloc_stats_print<parameter/></function>\n        function is called at program exit via an\n        <citerefentry><refentrytitle>atexit</refentrytitle>\n        <manvolnum>3</manvolnum></citerefentry> function.  If\n        <option>--enable-stats</option> is specified during configuration, this\n        has the potential to cause deadlock for a multi-threaded process that\n        exits while one or more threads are executing in the memory allocation\n        functions.  Furthermore, <function>atexit<parameter/></function> may\n        allocate memory during application initialization and then deadlock\n        internally when jemalloc in turn calls\n        <function>atexit<parameter/></function>, so this option is not\n        universally usable (though the application can register its own\n        <function>atexit<parameter/></function> function with equivalent\n        functionality).  Therefore, this option should only be used with care;\n        it is primarily intended as a performance tuning aid during application\n        development.  This option is disabled by default.</para></listitem>\n      </varlistentry>\n\n      <varlistentry id=\"opt.junk\">\n        <term>\n          <mallctl>opt.junk</mallctl>\n          (<type>const char *</type>)\n          <literal>r-</literal>\n          [<option>--enable-fill</option>]\n        </term>\n        <listitem><para>Junk filling.  If set to \"alloc\", each byte of\n        uninitialized allocated memory will be initialized to\n        <literal>0xa5</literal>.  If set to \"free\", all deallocated memory will\n        be initialized to <literal>0x5a</literal>.  If set to \"true\", both\n        allocated and deallocated memory will be initialized, and if set to\n        \"false\", junk filling be disabled entirely.  This is intended for\n        debugging and will impact performance negatively.  This option is\n        \"false\" by default unless <option>--enable-debug</option> is specified\n        during configuration, in which case it is \"true\" by default unless\n        running inside <ulink\n        url=\"http://valgrind.org/\">Valgrind</ulink>.</para></listitem>\n      </varlistentry>\n\n      <varlistentry id=\"opt.quarantine\">\n        <term>\n          <mallctl>opt.quarantine</mallctl>\n          (<type>size_t</type>)\n          <literal>r-</literal>\n          [<option>--enable-fill</option>]\n        </term>\n        <listitem><para>Per thread quarantine size in bytes.  If non-zero, each\n        thread maintains a FIFO object quarantine that stores up to the\n        specified number of bytes of memory.  The quarantined memory is not\n        freed until it is released from quarantine, though it is immediately\n        junk-filled if the <link\n        linkend=\"opt.junk\"><mallctl>opt.junk</mallctl></link> option is\n        enabled.  This feature is of particular use in combination with <ulink\n        url=\"http://valgrind.org/\">Valgrind</ulink>, which can detect attempts\n        to access quarantined objects.  This is intended for debugging and will\n        impact performance negatively.  The default quarantine size is 0 unless\n        running inside Valgrind, in which case the default is 16\n        MiB.</para></listitem>\n      </varlistentry>\n\n      <varlistentry id=\"opt.redzone\">\n        <term>\n          <mallctl>opt.redzone</mallctl>\n          (<type>bool</type>)\n          <literal>r-</literal>\n          [<option>--enable-fill</option>]\n        </term>\n        <listitem><para>Redzones enabled/disabled.  If enabled, small\n        allocations have redzones before and after them.  Furthermore, if the\n        <link linkend=\"opt.junk\"><mallctl>opt.junk</mallctl></link> option is\n        enabled, the redzones are checked for corruption during deallocation.\n        However, the primary intended purpose of this feature is to be used in\n        combination with <ulink url=\"http://valgrind.org/\">Valgrind</ulink>,\n        which needs redzones in order to do effective buffer overflow/underflow\n        detection.  This option is intended for debugging and will impact\n        performance negatively.  This option is disabled by\n        default unless running inside Valgrind.</para></listitem>\n      </varlistentry>\n\n      <varlistentry id=\"opt.zero\">\n        <term>\n          <mallctl>opt.zero</mallctl>\n          (<type>bool</type>)\n          <literal>r-</literal>\n          [<option>--enable-fill</option>]\n        </term>\n        <listitem><para>Zero filling enabled/disabled.  If enabled, each byte\n        of uninitialized allocated memory will be initialized to 0.  Note that\n        this initialization only happens once for each byte, so\n        <function>realloc<parameter/></function> and\n        <function>rallocx<parameter/></function> calls do not zero memory that\n        was previously allocated.  This is intended for debugging and will\n        impact performance negatively.  This option is disabled by default.\n        </para></listitem>\n      </varlistentry>\n\n      <varlistentry id=\"opt.utrace\">\n        <term>\n          <mallctl>opt.utrace</mallctl>\n          (<type>bool</type>)\n          <literal>r-</literal>\n          [<option>--enable-utrace</option>]\n        </term>\n        <listitem><para>Allocation tracing based on\n        <citerefentry><refentrytitle>utrace</refentrytitle>\n        <manvolnum>2</manvolnum></citerefentry> enabled/disabled.  This option\n        is disabled by default.</para></listitem>\n      </varlistentry>\n\n      <varlistentry id=\"opt.xmalloc\">\n        <term>\n          <mallctl>opt.xmalloc</mallctl>\n          (<type>bool</type>)\n          <literal>r-</literal>\n          [<option>--enable-xmalloc</option>]\n        </term>\n        <listitem><para>Abort-on-out-of-memory enabled/disabled.  If enabled,\n        rather than returning failure for any allocation function, display a\n        diagnostic message on <constant>STDERR_FILENO</constant> and cause the\n        program to drop core (using\n        <citerefentry><refentrytitle>abort</refentrytitle>\n        <manvolnum>3</manvolnum></citerefentry>).  If an application is\n        designed to depend on this behavior, set the option at compile time by\n        including the following in the source code:\n        <programlisting language=\"C\"><![CDATA[\nmalloc_conf = \"xmalloc:true\";]]></programlisting>\n        This option is disabled by default.</para></listitem>\n      </varlistentry>\n\n      <varlistentry id=\"opt.tcache\">\n        <term>\n          <mallctl>opt.tcache</mallctl>\n          (<type>bool</type>)\n          <literal>r-</literal>\n          [<option>--enable-tcache</option>]\n        </term>\n        <listitem><para>Thread-specific caching (tcache) enabled/disabled.  When\n        there are multiple threads, each thread uses a tcache for objects up to\n        a certain size.  Thread-specific caching allows many allocations to be\n        satisfied without performing any thread synchronization, at the cost of\n        increased memory use.  See the <link\n        linkend=\"opt.lg_tcache_max\"><mallctl>opt.lg_tcache_max</mallctl></link>\n        option for related tuning information.  This option is enabled by\n        default unless running inside <ulink\n        url=\"http://valgrind.org/\">Valgrind</ulink>, in which case it is\n        forcefully disabled.</para></listitem>\n      </varlistentry>\n\n      <varlistentry id=\"opt.lg_tcache_max\">\n        <term>\n          <mallctl>opt.lg_tcache_max</mallctl>\n          (<type>size_t</type>)\n          <literal>r-</literal>\n          [<option>--enable-tcache</option>]\n        </term>\n        <listitem><para>Maximum size class (log base 2) to cache in the\n        thread-specific cache (tcache).  At a minimum, all small size classes\n        are cached, and at a maximum all large size classes are cached.  The\n        default maximum is 32 KiB (2^15).</para></listitem>\n      </varlistentry>\n\n      <varlistentry id=\"opt.prof\">\n        <term>\n          <mallctl>opt.prof</mallctl>\n          (<type>bool</type>)\n          <literal>r-</literal>\n          [<option>--enable-prof</option>]\n        </term>\n        <listitem><para>Memory profiling enabled/disabled.  If enabled, profile\n        memory allocation activity.  See the <link\n        linkend=\"opt.prof_active\"><mallctl>opt.prof_active</mallctl></link>\n        option for on-the-fly activation/deactivation.  See the <link\n        linkend=\"opt.lg_prof_sample\"><mallctl>opt.lg_prof_sample</mallctl></link>\n        option for probabilistic sampling control.  See the <link\n        linkend=\"opt.prof_accum\"><mallctl>opt.prof_accum</mallctl></link>\n        option for control of cumulative sample reporting.  See the <link\n        linkend=\"opt.lg_prof_interval\"><mallctl>opt.lg_prof_interval</mallctl></link>\n        option for information on interval-triggered profile dumping, the <link\n        linkend=\"opt.prof_gdump\"><mallctl>opt.prof_gdump</mallctl></link>\n        option for information on high-water-triggered profile dumping, and the\n        <link linkend=\"opt.prof_final\"><mallctl>opt.prof_final</mallctl></link>\n        option for final profile dumping.  Profile output is compatible with\n        the <command>jeprof</command> command, which is based on the\n        <command>pprof</command> that is developed as part of the <ulink\n        url=\"http://code.google.com/p/gperftools/\">gperftools\n        package</ulink>.  See <link linkend=\"heap_profile_format\">HEAP PROFILE\n        FORMAT</link> for heap profile format documentation.</para></listitem>\n      </varlistentry>\n\n      <varlistentry id=\"opt.prof_prefix\">\n        <term>\n          <mallctl>opt.prof_prefix</mallctl>\n          (<type>const char *</type>)\n          <literal>r-</literal>\n          [<option>--enable-prof</option>]\n        </term>\n        <listitem><para>Filename prefix for profile dumps.  If the prefix is\n        set to the empty string, no automatic dumps will occur; this is\n        primarily useful for disabling the automatic final heap dump (which\n        also disables leak reporting, if enabled).  The default prefix is\n        <filename>jeprof</filename>.</para></listitem>\n      </varlistentry>\n\n      <varlistentry id=\"opt.prof_active\">\n        <term>\n          <mallctl>opt.prof_active</mallctl>\n          (<type>bool</type>)\n          <literal>r-</literal>\n          [<option>--enable-prof</option>]\n        </term>\n        <listitem><para>Profiling activated/deactivated.  This is a secondary\n        control mechanism that makes it possible to start the application with\n        profiling enabled (see the <link\n        linkend=\"opt.prof\"><mallctl>opt.prof</mallctl></link> option) but\n        inactive, then toggle profiling at any time during program execution\n        with the <link\n        linkend=\"prof.active\"><mallctl>prof.active</mallctl></link> mallctl.\n        This option is enabled by default.</para></listitem>\n      </varlistentry>\n\n      <varlistentry id=\"opt.prof_thread_active_init\">\n        <term>\n          <mallctl>opt.prof_thread_active_init</mallctl>\n          (<type>bool</type>)\n          <literal>r-</literal>\n          [<option>--enable-prof</option>]\n        </term>\n        <listitem><para>Initial setting for <link\n        linkend=\"thread.prof.active\"><mallctl>thread.prof.active</mallctl></link>\n        in newly created threads.  The initial setting for newly created threads\n        can also be changed during execution via the <link\n        linkend=\"prof.thread_active_init\"><mallctl>prof.thread_active_init</mallctl></link>\n        mallctl.  This option is enabled by default.</para></listitem>\n      </varlistentry>\n\n      <varlistentry id=\"opt.lg_prof_sample\">\n        <term>\n          <mallctl>opt.lg_prof_sample</mallctl>\n          (<type>size_t</type>)\n          <literal>r-</literal>\n          [<option>--enable-prof</option>]\n        </term>\n        <listitem><para>Average interval (log base 2) between allocation\n        samples, as measured in bytes of allocation activity.  Increasing the\n        sampling interval decreases profile fidelity, but also decreases the\n        computational overhead.  The default sample interval is 512 KiB (2^19\n        B).</para></listitem>\n      </varlistentry>\n\n      <varlistentry id=\"opt.prof_accum\">\n        <term>\n          <mallctl>opt.prof_accum</mallctl>\n          (<type>bool</type>)\n          <literal>r-</literal>\n          [<option>--enable-prof</option>]\n        </term>\n        <listitem><para>Reporting of cumulative object/byte counts in profile\n        dumps enabled/disabled.  If this option is enabled, every unique\n        backtrace must be stored for the duration of execution.  Depending on\n        the application, this can impose a large memory overhead, and the\n        cumulative counts are not always of interest.  This option is disabled\n        by default.</para></listitem>\n      </varlistentry>\n\n      <varlistentry id=\"opt.lg_prof_interval\">\n        <term>\n          <mallctl>opt.lg_prof_interval</mallctl>\n          (<type>ssize_t</type>)\n          <literal>r-</literal>\n          [<option>--enable-prof</option>]\n        </term>\n        <listitem><para>Average interval (log base 2) between memory profile\n        dumps, as measured in bytes of allocation activity.  The actual\n        interval between dumps may be sporadic because decentralized allocation\n        counters are used to avoid synchronization bottlenecks.  Profiles are\n        dumped to files named according to the pattern\n        <filename>&lt;prefix&gt;.&lt;pid&gt;.&lt;seq&gt;.i&lt;iseq&gt;.heap</filename>,\n        where <literal>&lt;prefix&gt;</literal> is controlled by the\n        <link\n        linkend=\"opt.prof_prefix\"><mallctl>opt.prof_prefix</mallctl></link>\n        option.  By default, interval-triggered profile dumping is disabled\n        (encoded as -1).\n        </para></listitem>\n      </varlistentry>\n\n      <varlistentry id=\"opt.prof_gdump\">\n        <term>\n          <mallctl>opt.prof_gdump</mallctl>\n          (<type>bool</type>)\n          <literal>r-</literal>\n          [<option>--enable-prof</option>]\n        </term>\n        <listitem><para>Set the initial state of <link\n        linkend=\"prof.gdump\"><mallctl>prof.gdump</mallctl></link>, which when\n        enabled triggers a memory profile dump every time the total virtual\n        memory exceeds the previous maximum.  This option is disabled by\n        default.</para></listitem>\n      </varlistentry>\n\n      <varlistentry id=\"opt.prof_final\">\n        <term>\n          <mallctl>opt.prof_final</mallctl>\n          (<type>bool</type>)\n          <literal>r-</literal>\n          [<option>--enable-prof</option>]\n        </term>\n        <listitem><para>Use an\n        <citerefentry><refentrytitle>atexit</refentrytitle>\n        <manvolnum>3</manvolnum></citerefentry> function to dump final memory\n        usage to a file named according to the pattern\n        <filename>&lt;prefix&gt;.&lt;pid&gt;.&lt;seq&gt;.f.heap</filename>,\n        where <literal>&lt;prefix&gt;</literal> is controlled by the <link\n        linkend=\"opt.prof_prefix\"><mallctl>opt.prof_prefix</mallctl></link>\n        option.  Note that <function>atexit<parameter/></function> may allocate\n        memory during application initialization and then deadlock internally\n        when jemalloc in turn calls <function>atexit<parameter/></function>, so\n        this option is not universally usable (though the application can\n        register its own <function>atexit<parameter/></function> function with\n        equivalent functionality).  This option is disabled by\n        default.</para></listitem>\n      </varlistentry>\n\n      <varlistentry id=\"opt.prof_leak\">\n        <term>\n          <mallctl>opt.prof_leak</mallctl>\n          (<type>bool</type>)\n          <literal>r-</literal>\n          [<option>--enable-prof</option>]\n        </term>\n        <listitem><para>Leak reporting enabled/disabled.  If enabled, use an\n        <citerefentry><refentrytitle>atexit</refentrytitle>\n        <manvolnum>3</manvolnum></citerefentry> function to report memory leaks\n        detected by allocation sampling.  See the\n        <link linkend=\"opt.prof\"><mallctl>opt.prof</mallctl></link> option for\n        information on analyzing heap profile output.  This option is disabled\n        by default.</para></listitem>\n      </varlistentry>\n\n      <varlistentry id=\"thread.arena\">\n        <term>\n          <mallctl>thread.arena</mallctl>\n          (<type>unsigned</type>)\n          <literal>rw</literal>\n        </term>\n        <listitem><para>Get or set the arena associated with the calling\n        thread.  If the specified arena was not initialized beforehand (see the\n        <link\n        linkend=\"arenas.initialized\"><mallctl>arenas.initialized</mallctl></link>\n        mallctl), it will be automatically initialized as a side effect of\n        calling this interface.</para></listitem>\n      </varlistentry>\n\n      <varlistentry id=\"thread.allocated\">\n        <term>\n          <mallctl>thread.allocated</mallctl>\n          (<type>uint64_t</type>)\n          <literal>r-</literal>\n          [<option>--enable-stats</option>]\n        </term>\n        <listitem><para>Get the total number of bytes ever allocated by the\n        calling thread.  This counter has the potential to wrap around; it is\n        up to the application to appropriately interpret the counter in such\n        cases.</para></listitem>\n      </varlistentry>\n\n      <varlistentry id=\"thread.allocatedp\">\n        <term>\n          <mallctl>thread.allocatedp</mallctl>\n          (<type>uint64_t *</type>)\n          <literal>r-</literal>\n          [<option>--enable-stats</option>]\n        </term>\n        <listitem><para>Get a pointer to the the value that is returned by the\n        <link\n        linkend=\"thread.allocated\"><mallctl>thread.allocated</mallctl></link>\n        mallctl.  This is useful for avoiding the overhead of repeated\n        <function>mallctl*<parameter/></function> calls.</para></listitem>\n      </varlistentry>\n\n      <varlistentry id=\"thread.deallocated\">\n        <term>\n          <mallctl>thread.deallocated</mallctl>\n          (<type>uint64_t</type>)\n          <literal>r-</literal>\n          [<option>--enable-stats</option>]\n        </term>\n        <listitem><para>Get the total number of bytes ever deallocated by the\n        calling thread.  This counter has the potential to wrap around; it is\n        up to the application to appropriately interpret the counter in such\n        cases.</para></listitem>\n      </varlistentry>\n\n      <varlistentry id=\"thread.deallocatedp\">\n        <term>\n          <mallctl>thread.deallocatedp</mallctl>\n          (<type>uint64_t *</type>)\n          <literal>r-</literal>\n          [<option>--enable-stats</option>]\n        </term>\n        <listitem><para>Get a pointer to the the value that is returned by the\n        <link\n        linkend=\"thread.deallocated\"><mallctl>thread.deallocated</mallctl></link>\n        mallctl.  This is useful for avoiding the overhead of repeated\n        <function>mallctl*<parameter/></function> calls.</para></listitem>\n      </varlistentry>\n\n      <varlistentry id=\"thread.tcache.enabled\">\n        <term>\n          <mallctl>thread.tcache.enabled</mallctl>\n          (<type>bool</type>)\n          <literal>rw</literal>\n          [<option>--enable-tcache</option>]\n        </term>\n        <listitem><para>Enable/disable calling thread's tcache.  The tcache is\n        implicitly flushed as a side effect of becoming\n        disabled (see <link\n        linkend=\"thread.tcache.flush\"><mallctl>thread.tcache.flush</mallctl></link>).\n        </para></listitem>\n      </varlistentry>\n\n      <varlistentry id=\"thread.tcache.flush\">\n        <term>\n          <mallctl>thread.tcache.flush</mallctl>\n          (<type>void</type>)\n          <literal>--</literal>\n          [<option>--enable-tcache</option>]\n        </term>\n        <listitem><para>Flush calling thread's thread-specific cache (tcache).\n        This interface releases all cached objects and internal data structures\n        associated with the calling thread's tcache.  Ordinarily, this interface\n        need not be called, since automatic periodic incremental garbage\n        collection occurs, and the thread cache is automatically discarded when\n        a thread exits.  However, garbage collection is triggered by allocation\n        activity, so it is possible for a thread that stops\n        allocating/deallocating to retain its cache indefinitely, in which case\n        the developer may find manual flushing useful.</para></listitem>\n      </varlistentry>\n\n      <varlistentry id=\"thread.prof.name\">\n        <term>\n          <mallctl>thread.prof.name</mallctl>\n          (<type>const char *</type>)\n          <literal>r-</literal> or\n          <literal>-w</literal>\n          [<option>--enable-prof</option>]\n        </term>\n        <listitem><para>Get/set the descriptive name associated with the calling\n        thread in memory profile dumps.  An internal copy of the name string is\n        created, so the input string need not be maintained after this interface\n        completes execution.  The output string of this interface should be\n        copied for non-ephemeral uses, because multiple implementation details\n        can cause asynchronous string deallocation.  Furthermore, each\n        invocation of this interface can only read or write; simultaneous\n        read/write is not supported due to string lifetime limitations.  The\n        name string must be nil-terminated and comprised only of characters in\n        the sets recognized\n        by <citerefentry><refentrytitle>isgraph</refentrytitle>\n        <manvolnum>3</manvolnum></citerefentry> and\n        <citerefentry><refentrytitle>isblank</refentrytitle>\n        <manvolnum>3</manvolnum></citerefentry>.</para></listitem>\n      </varlistentry>\n\n      <varlistentry id=\"thread.prof.active\">\n        <term>\n          <mallctl>thread.prof.active</mallctl>\n          (<type>bool</type>)\n          <literal>rw</literal>\n          [<option>--enable-prof</option>]\n        </term>\n        <listitem><para>Control whether sampling is currently active for the\n        calling thread.  This is an activation mechanism in addition to <link\n        linkend=\"prof.active\"><mallctl>prof.active</mallctl></link>; both must\n        be active for the calling thread to sample.  This flag is enabled by\n        default.</para></listitem>\n      </varlistentry>\n\n      <varlistentry id=\"tcache.create\">\n        <term>\n          <mallctl>tcache.create</mallctl>\n          (<type>unsigned</type>)\n          <literal>r-</literal>\n          [<option>--enable-tcache</option>]\n        </term>\n        <listitem><para>Create an explicit thread-specific cache (tcache) and\n        return an identifier that can be passed to the <link\n        linkend=\"MALLOCX_TCACHE\"><constant>MALLOCX_TCACHE(<parameter>tc</parameter>)</constant></link>\n        macro to explicitly use the specified cache rather than the\n        automatically managed one that is used by default.  Each explicit cache\n        can be used by only one thread at a time; the application must assure\n        that this constraint holds.\n        </para></listitem>\n      </varlistentry>\n\n      <varlistentry id=\"tcache.flush\">\n        <term>\n          <mallctl>tcache.flush</mallctl>\n          (<type>unsigned</type>)\n          <literal>-w</literal>\n          [<option>--enable-tcache</option>]\n        </term>\n        <listitem><para>Flush the specified thread-specific cache (tcache).  The\n        same considerations apply to this interface as to <link\n        linkend=\"thread.tcache.flush\"><mallctl>thread.tcache.flush</mallctl></link>,\n        except that the tcache will never be automatically discarded.\n        </para></listitem>\n      </varlistentry>\n\n      <varlistentry id=\"tcache.destroy\">\n        <term>\n          <mallctl>tcache.destroy</mallctl>\n          (<type>unsigned</type>)\n          <literal>-w</literal>\n          [<option>--enable-tcache</option>]\n        </term>\n        <listitem><para>Flush the specified thread-specific cache (tcache) and\n        make the identifier available for use during a future tcache creation.\n        </para></listitem>\n      </varlistentry>\n\n      <varlistentry id=\"arena.i.purge\">\n        <term>\n          <mallctl>arena.&lt;i&gt;.purge</mallctl>\n          (<type>void</type>)\n          <literal>--</literal>\n        </term>\n        <listitem><para>Purge all unused dirty pages for arena &lt;i&gt;, or for\n        all arenas if &lt;i&gt; equals <link\n        linkend=\"arenas.narenas\"><mallctl>arenas.narenas</mallctl></link>.\n        </para></listitem>\n      </varlistentry>\n\n      <varlistentry id=\"arena.i.decay\">\n        <term>\n          <mallctl>arena.&lt;i&gt;.decay</mallctl>\n          (<type>void</type>)\n          <literal>--</literal>\n        </term>\n        <listitem><para>Trigger decay-based purging of unused dirty pages for\n        arena &lt;i&gt;, or for all arenas if &lt;i&gt; equals <link\n        linkend=\"arenas.narenas\"><mallctl>arenas.narenas</mallctl></link>.\n        The proportion of unused dirty pages to be purged depends on the current\n        time; see <link\n        linkend=\"opt.decay_time\"><mallctl>opt.decay_time</mallctl></link> for\n        details.</para></listitem>\n      </varlistentry>\n\n      <varlistentry id=\"arena.i.reset\">\n        <term>\n          <mallctl>arena.&lt;i&gt;.reset</mallctl>\n          (<type>void</type>)\n          <literal>--</literal>\n        </term>\n        <listitem><para>Discard all of the arena's extant allocations.  This\n        interface can only be used with arenas created via <link\n        linkend=\"arenas.extend\"><mallctl>arenas.extend</mallctl></link>.  None\n        of the arena's discarded/cached allocations may accessed afterward.  As\n        part of this requirement, all thread caches which were used to\n        allocate/deallocate in conjunction with the arena must be flushed\n        beforehand.  This interface cannot be used if running inside Valgrind,\n        nor if the <link linkend=\"opt.quarantine\">quarantine</link> size is\n        non-zero.</para></listitem>\n      </varlistentry>\n\n      <varlistentry id=\"arena.i.dss\">\n        <term>\n          <mallctl>arena.&lt;i&gt;.dss</mallctl>\n          (<type>const char *</type>)\n          <literal>rw</literal>\n        </term>\n        <listitem><para>Set the precedence of dss allocation as related to mmap\n        allocation for arena &lt;i&gt;, or for all arenas if &lt;i&gt; equals\n        <link\n        linkend=\"arenas.narenas\"><mallctl>arenas.narenas</mallctl></link>.  See\n        <link linkend=\"opt.dss\"><mallctl>opt.dss</mallctl></link> for supported\n        settings.</para></listitem>\n      </varlistentry>\n\n      <varlistentry id=\"arena.i.lg_dirty_mult\">\n        <term>\n          <mallctl>arena.&lt;i&gt;.lg_dirty_mult</mallctl>\n          (<type>ssize_t</type>)\n          <literal>rw</literal>\n        </term>\n        <listitem><para>Current per-arena minimum ratio (log base 2) of active\n        to dirty pages for arena &lt;i&gt;.  Each time this interface is set and\n        the ratio is increased, pages are synchronously purged as necessary to\n        impose the new ratio.  See <link\n        linkend=\"opt.lg_dirty_mult\"><mallctl>opt.lg_dirty_mult</mallctl></link>\n        for additional information.</para></listitem>\n      </varlistentry>\n\n      <varlistentry id=\"arena.i.decay_time\">\n        <term>\n          <mallctl>arena.&lt;i&gt;.decay_time</mallctl>\n          (<type>ssize_t</type>)\n          <literal>rw</literal>\n        </term>\n        <listitem><para>Current per-arena approximate time in seconds from the\n        creation of a set of unused dirty pages until an equivalent set of\n        unused dirty pages is purged and/or reused.  Each time this interface is\n        set, all currently unused dirty pages are considered to have fully\n        decayed, which causes immediate purging of all unused dirty pages unless\n        the decay time is set to -1 (i.e. purging disabled).  See <link\n        linkend=\"opt.decay_time\"><mallctl>opt.decay_time</mallctl></link> for\n        additional information.</para></listitem>\n      </varlistentry>\n\n      <varlistentry id=\"arena.i.chunk_hooks\">\n        <term>\n          <mallctl>arena.&lt;i&gt;.chunk_hooks</mallctl>\n          (<type>chunk_hooks_t</type>)\n          <literal>rw</literal>\n        </term>\n        <listitem><para>Get or set the chunk management hook functions for arena\n        &lt;i&gt;.  The functions must be capable of operating on all extant\n        chunks associated with arena &lt;i&gt;, usually by passing unknown\n        chunks to the replaced functions.  In practice, it is feasible to\n        control allocation for arenas created via <link\n        linkend=\"arenas.extend\"><mallctl>arenas.extend</mallctl></link> such\n        that all chunks originate from an application-supplied chunk allocator\n        (by setting custom chunk hook functions just after arena creation), but\n        the automatically created arenas may have already created chunks prior\n        to the application having an opportunity to take over chunk\n        allocation.</para>\n\n        <programlisting language=\"C\"><![CDATA[\ntypedef struct {\n\tchunk_alloc_t\t\t*alloc;\n\tchunk_dalloc_t\t\t*dalloc;\n\tchunk_commit_t\t\t*commit;\n\tchunk_decommit_t\t*decommit;\n\tchunk_purge_t\t\t*purge;\n\tchunk_split_t\t\t*split;\n\tchunk_merge_t\t\t*merge;\n} chunk_hooks_t;]]></programlisting>\n        <para>The <type>chunk_hooks_t</type> structure comprises function\n        pointers which are described individually below.  jemalloc uses these\n        functions to manage chunk lifetime, which starts off with allocation of\n        mapped committed memory, in the simplest case followed by deallocation.\n        However, there are performance and platform reasons to retain chunks for\n        later reuse.  Cleanup attempts cascade from deallocation to decommit to\n        purging, which gives the chunk management functions opportunities to\n        reject the most permanent cleanup operations in favor of less permanent\n        (and often less costly) operations.  The chunk splitting and merging\n        operations can also be opted out of, but this is mainly intended to\n        support platforms on which virtual memory mappings provided by the\n        operating system kernel do not automatically coalesce and split, e.g.\n        Windows.</para>\n\n        <funcsynopsis><funcprototype>\n          <funcdef>typedef void *<function>(chunk_alloc_t)</function></funcdef>\n          <paramdef>void *<parameter>chunk</parameter></paramdef>\n          <paramdef>size_t <parameter>size</parameter></paramdef>\n          <paramdef>size_t <parameter>alignment</parameter></paramdef>\n          <paramdef>bool *<parameter>zero</parameter></paramdef>\n          <paramdef>bool *<parameter>commit</parameter></paramdef>\n          <paramdef>unsigned <parameter>arena_ind</parameter></paramdef>\n        </funcprototype></funcsynopsis>\n        <literallayout></literallayout>\n        <para>A chunk allocation function conforms to the\n        <type>chunk_alloc_t</type> type and upon success returns a pointer to\n        <parameter>size</parameter> bytes of mapped memory on behalf of arena\n        <parameter>arena_ind</parameter> such that the chunk's base address is a\n        multiple of <parameter>alignment</parameter>, as well as setting\n        <parameter>*zero</parameter> to indicate whether the chunk is zeroed and\n        <parameter>*commit</parameter> to indicate whether the chunk is\n        committed.  Upon error the function returns <constant>NULL</constant>\n        and leaves <parameter>*zero</parameter> and\n        <parameter>*commit</parameter> unmodified.  The\n        <parameter>size</parameter> parameter is always a multiple of the chunk\n        size.  The <parameter>alignment</parameter> parameter is always a power\n        of two at least as large as the chunk size.  Zeroing is mandatory if\n        <parameter>*zero</parameter> is true upon function entry.  Committing is\n        mandatory if <parameter>*commit</parameter> is true upon function entry.\n        If <parameter>chunk</parameter> is not <constant>NULL</constant>, the\n        returned pointer must be <parameter>chunk</parameter> on success or\n        <constant>NULL</constant> on error.  Committed memory may be committed\n        in absolute terms as on a system that does not overcommit, or in\n        implicit terms as on a system that overcommits and satisfies physical\n        memory needs on demand via soft page faults.  Note that replacing the\n        default chunk allocation function makes the arena's <link\n        linkend=\"arena.i.dss\"><mallctl>arena.&lt;i&gt;.dss</mallctl></link>\n        setting irrelevant.</para>\n\n        <funcsynopsis><funcprototype>\n          <funcdef>typedef bool <function>(chunk_dalloc_t)</function></funcdef>\n          <paramdef>void *<parameter>chunk</parameter></paramdef>\n          <paramdef>size_t <parameter>size</parameter></paramdef>\n          <paramdef>bool <parameter>committed</parameter></paramdef>\n          <paramdef>unsigned <parameter>arena_ind</parameter></paramdef>\n        </funcprototype></funcsynopsis>\n        <literallayout></literallayout>\n        <para>\n        A chunk deallocation function conforms to the\n        <type>chunk_dalloc_t</type> type and deallocates a\n        <parameter>chunk</parameter> of given <parameter>size</parameter> with\n        <parameter>committed</parameter>/decommited memory as indicated, on\n        behalf of arena <parameter>arena_ind</parameter>, returning false upon\n        success.  If the function returns true, this indicates opt-out from\n        deallocation; the virtual memory mapping associated with the chunk\n        remains mapped, in the same commit state, and available for future use,\n        in which case it will be automatically retained for later reuse.</para>\n\n        <funcsynopsis><funcprototype>\n          <funcdef>typedef bool <function>(chunk_commit_t)</function></funcdef>\n          <paramdef>void *<parameter>chunk</parameter></paramdef>\n          <paramdef>size_t <parameter>size</parameter></paramdef>\n          <paramdef>size_t <parameter>offset</parameter></paramdef>\n          <paramdef>size_t <parameter>length</parameter></paramdef>\n          <paramdef>unsigned <parameter>arena_ind</parameter></paramdef>\n        </funcprototype></funcsynopsis>\n        <literallayout></literallayout>\n        <para>A chunk commit function conforms to the\n        <type>chunk_commit_t</type> type and commits zeroed physical memory to\n        back pages within a <parameter>chunk</parameter> of given\n        <parameter>size</parameter> at <parameter>offset</parameter> bytes,\n        extending for <parameter>length</parameter> on behalf of arena\n        <parameter>arena_ind</parameter>, returning false upon success.\n        Committed memory may be committed in absolute terms as on a system that\n        does not overcommit, or in implicit terms as on a system that\n        overcommits and satisfies physical memory needs on demand via soft page\n        faults. If the function returns true, this indicates insufficient\n        physical memory to satisfy the request.</para>\n\n        <funcsynopsis><funcprototype>\n          <funcdef>typedef bool <function>(chunk_decommit_t)</function></funcdef>\n          <paramdef>void *<parameter>chunk</parameter></paramdef>\n          <paramdef>size_t <parameter>size</parameter></paramdef>\n          <paramdef>size_t <parameter>offset</parameter></paramdef>\n          <paramdef>size_t <parameter>length</parameter></paramdef>\n          <paramdef>unsigned <parameter>arena_ind</parameter></paramdef>\n        </funcprototype></funcsynopsis>\n        <literallayout></literallayout>\n        <para>A chunk decommit function conforms to the\n        <type>chunk_decommit_t</type> type and decommits any physical memory\n        that is backing pages within a <parameter>chunk</parameter> of given\n        <parameter>size</parameter> at <parameter>offset</parameter> bytes,\n        extending for <parameter>length</parameter> on behalf of arena\n        <parameter>arena_ind</parameter>, returning false upon success, in which\n        case the pages will be committed via the chunk commit function before\n        being reused.  If the function returns true, this indicates opt-out from\n        decommit; the memory remains committed and available for future use, in\n        which case it will be automatically retained for later reuse.</para>\n\n        <funcsynopsis><funcprototype>\n          <funcdef>typedef bool <function>(chunk_purge_t)</function></funcdef>\n          <paramdef>void *<parameter>chunk</parameter></paramdef>\n          <paramdef>size_t<parameter>size</parameter></paramdef>\n          <paramdef>size_t <parameter>offset</parameter></paramdef>\n          <paramdef>size_t <parameter>length</parameter></paramdef>\n          <paramdef>unsigned <parameter>arena_ind</parameter></paramdef>\n        </funcprototype></funcsynopsis>\n        <literallayout></literallayout>\n        <para>A chunk purge function conforms to the <type>chunk_purge_t</type>\n        type and optionally discards physical pages within the virtual memory\n        mapping associated with <parameter>chunk</parameter> of given\n        <parameter>size</parameter> at <parameter>offset</parameter> bytes,\n        extending for <parameter>length</parameter> on behalf of arena\n        <parameter>arena_ind</parameter>, returning false if pages within the\n        purged virtual memory range will be zero-filled the next time they are\n        accessed.</para>\n\n        <funcsynopsis><funcprototype>\n          <funcdef>typedef bool <function>(chunk_split_t)</function></funcdef>\n          <paramdef>void *<parameter>chunk</parameter></paramdef>\n          <paramdef>size_t <parameter>size</parameter></paramdef>\n          <paramdef>size_t <parameter>size_a</parameter></paramdef>\n          <paramdef>size_t <parameter>size_b</parameter></paramdef>\n          <paramdef>bool <parameter>committed</parameter></paramdef>\n          <paramdef>unsigned <parameter>arena_ind</parameter></paramdef>\n        </funcprototype></funcsynopsis>\n        <literallayout></literallayout>\n        <para>A chunk split function conforms to the <type>chunk_split_t</type>\n        type and optionally splits <parameter>chunk</parameter> of given\n        <parameter>size</parameter> into two adjacent chunks, the first of\n        <parameter>size_a</parameter> bytes, and the second of\n        <parameter>size_b</parameter> bytes, operating on\n        <parameter>committed</parameter>/decommitted memory as indicated, on\n        behalf of arena <parameter>arena_ind</parameter>, returning false upon\n        success.  If the function returns true, this indicates that the chunk\n        remains unsplit and therefore should continue to be operated on as a\n        whole.</para>\n\n        <funcsynopsis><funcprototype>\n          <funcdef>typedef bool <function>(chunk_merge_t)</function></funcdef>\n          <paramdef>void *<parameter>chunk_a</parameter></paramdef>\n          <paramdef>size_t <parameter>size_a</parameter></paramdef>\n          <paramdef>void *<parameter>chunk_b</parameter></paramdef>\n          <paramdef>size_t <parameter>size_b</parameter></paramdef>\n          <paramdef>bool <parameter>committed</parameter></paramdef>\n          <paramdef>unsigned <parameter>arena_ind</parameter></paramdef>\n        </funcprototype></funcsynopsis>\n        <literallayout></literallayout>\n        <para>A chunk merge function conforms to the <type>chunk_merge_t</type>\n        type and optionally merges adjacent chunks,\n        <parameter>chunk_a</parameter> of given <parameter>size_a</parameter>\n        and <parameter>chunk_b</parameter> of given\n        <parameter>size_b</parameter> into one contiguous chunk, operating on\n        <parameter>committed</parameter>/decommitted memory as indicated, on\n        behalf of arena <parameter>arena_ind</parameter>, returning false upon\n        success.  If the function returns true, this indicates that the chunks\n        remain distinct mappings and therefore should continue to be operated on\n        independently.</para>\n        </listitem>\n      </varlistentry>\n\n      <varlistentry id=\"arenas.narenas\">\n        <term>\n          <mallctl>arenas.narenas</mallctl>\n          (<type>unsigned</type>)\n          <literal>r-</literal>\n        </term>\n        <listitem><para>Current limit on number of arenas.</para></listitem>\n      </varlistentry>\n\n      <varlistentry id=\"arenas.initialized\">\n        <term>\n          <mallctl>arenas.initialized</mallctl>\n          (<type>bool *</type>)\n          <literal>r-</literal>\n        </term>\n        <listitem><para>An array of <link\n        linkend=\"arenas.narenas\"><mallctl>arenas.narenas</mallctl></link>\n        booleans.  Each boolean indicates whether the corresponding arena is\n        initialized.</para></listitem>\n      </varlistentry>\n\n      <varlistentry id=\"arenas.lg_dirty_mult\">\n        <term>\n          <mallctl>arenas.lg_dirty_mult</mallctl>\n          (<type>ssize_t</type>)\n          <literal>rw</literal>\n        </term>\n        <listitem><para>Current default per-arena minimum ratio (log base 2) of\n        active to dirty pages, used to initialize <link\n        linkend=\"arena.i.lg_dirty_mult\"><mallctl>arena.&lt;i&gt;.lg_dirty_mult</mallctl></link>\n        during arena creation.  See <link\n        linkend=\"opt.lg_dirty_mult\"><mallctl>opt.lg_dirty_mult</mallctl></link>\n        for additional information.</para></listitem>\n      </varlistentry>\n\n      <varlistentry id=\"arenas.decay_time\">\n        <term>\n          <mallctl>arenas.decay_time</mallctl>\n          (<type>ssize_t</type>)\n          <literal>rw</literal>\n        </term>\n        <listitem><para>Current default per-arena approximate time in seconds\n        from the creation of a set of unused dirty pages until an equivalent set\n        of unused dirty pages is purged and/or reused, used to initialize <link\n        linkend=\"arena.i.decay_time\"><mallctl>arena.&lt;i&gt;.decay_time</mallctl></link>\n        during arena creation.  See <link\n        linkend=\"opt.decay_time\"><mallctl>opt.decay_time</mallctl></link> for\n        additional information.</para></listitem>\n      </varlistentry>\n\n      <varlistentry id=\"arenas.quantum\">\n        <term>\n          <mallctl>arenas.quantum</mallctl>\n          (<type>size_t</type>)\n          <literal>r-</literal>\n        </term>\n        <listitem><para>Quantum size.</para></listitem>\n      </varlistentry>\n\n      <varlistentry id=\"arenas.page\">\n        <term>\n          <mallctl>arenas.page</mallctl>\n          (<type>size_t</type>)\n          <literal>r-</literal>\n        </term>\n        <listitem><para>Page size.</para></listitem>\n      </varlistentry>\n\n      <varlistentry id=\"arenas.tcache_max\">\n        <term>\n          <mallctl>arenas.tcache_max</mallctl>\n          (<type>size_t</type>)\n          <literal>r-</literal>\n          [<option>--enable-tcache</option>]\n        </term>\n        <listitem><para>Maximum thread-cached size class.</para></listitem>\n      </varlistentry>\n\n      <varlistentry id=\"arenas.nbins\">\n        <term>\n          <mallctl>arenas.nbins</mallctl>\n          (<type>unsigned</type>)\n          <literal>r-</literal>\n        </term>\n        <listitem><para>Number of bin size classes.</para></listitem>\n      </varlistentry>\n\n      <varlistentry id=\"arenas.nhbins\">\n        <term>\n          <mallctl>arenas.nhbins</mallctl>\n          (<type>unsigned</type>)\n          <literal>r-</literal>\n          [<option>--enable-tcache</option>]\n        </term>\n        <listitem><para>Total number of thread cache bin size\n        classes.</para></listitem>\n      </varlistentry>\n\n      <varlistentry id=\"arenas.bin.i.size\">\n        <term>\n          <mallctl>arenas.bin.&lt;i&gt;.size</mallctl>\n          (<type>size_t</type>)\n          <literal>r-</literal>\n        </term>\n        <listitem><para>Maximum size supported by size class.</para></listitem>\n      </varlistentry>\n\n      <varlistentry id=\"arenas.bin.i.nregs\">\n        <term>\n          <mallctl>arenas.bin.&lt;i&gt;.nregs</mallctl>\n          (<type>uint32_t</type>)\n          <literal>r-</literal>\n        </term>\n        <listitem><para>Number of regions per page run.</para></listitem>\n      </varlistentry>\n\n      <varlistentry id=\"arenas.bin.i.run_size\">\n        <term>\n          <mallctl>arenas.bin.&lt;i&gt;.run_size</mallctl>\n          (<type>size_t</type>)\n          <literal>r-</literal>\n        </term>\n        <listitem><para>Number of bytes per page run.</para></listitem>\n      </varlistentry>\n\n      <varlistentry id=\"arenas.nlruns\">\n        <term>\n          <mallctl>arenas.nlruns</mallctl>\n          (<type>unsigned</type>)\n          <literal>r-</literal>\n        </term>\n        <listitem><para>Total number of large size classes.</para></listitem>\n      </varlistentry>\n\n      <varlistentry id=\"arenas.lrun.i.size\">\n        <term>\n          <mallctl>arenas.lrun.&lt;i&gt;.size</mallctl>\n          (<type>size_t</type>)\n          <literal>r-</literal>\n        </term>\n        <listitem><para>Maximum size supported by this large size\n        class.</para></listitem>\n      </varlistentry>\n\n      <varlistentry id=\"arenas.nhchunks\">\n        <term>\n          <mallctl>arenas.nhchunks</mallctl>\n          (<type>unsigned</type>)\n          <literal>r-</literal>\n        </term>\n        <listitem><para>Total number of huge size classes.</para></listitem>\n      </varlistentry>\n\n      <varlistentry id=\"arenas.hchunk.i.size\">\n        <term>\n          <mallctl>arenas.hchunk.&lt;i&gt;.size</mallctl>\n          (<type>size_t</type>)\n          <literal>r-</literal>\n        </term>\n        <listitem><para>Maximum size supported by this huge size\n        class.</para></listitem>\n      </varlistentry>\n\n      <varlistentry id=\"arenas.extend\">\n        <term>\n          <mallctl>arenas.extend</mallctl>\n          (<type>unsigned</type>)\n          <literal>r-</literal>\n        </term>\n        <listitem><para>Extend the array of arenas by appending a new arena,\n        and returning the new arena index.</para></listitem>\n      </varlistentry>\n\n      <varlistentry id=\"prof.thread_active_init\">\n        <term>\n          <mallctl>prof.thread_active_init</mallctl>\n          (<type>bool</type>)\n          <literal>rw</literal>\n          [<option>--enable-prof</option>]\n        </term>\n        <listitem><para>Control the initial setting for <link\n        linkend=\"thread.prof.active\"><mallctl>thread.prof.active</mallctl></link>\n        in newly created threads.  See the <link\n        linkend=\"opt.prof_thread_active_init\"><mallctl>opt.prof_thread_active_init</mallctl></link>\n        option for additional information.</para></listitem>\n      </varlistentry>\n\n      <varlistentry id=\"prof.active\">\n        <term>\n          <mallctl>prof.active</mallctl>\n          (<type>bool</type>)\n          <literal>rw</literal>\n          [<option>--enable-prof</option>]\n        </term>\n        <listitem><para>Control whether sampling is currently active.  See the\n        <link\n        linkend=\"opt.prof_active\"><mallctl>opt.prof_active</mallctl></link>\n        option for additional information, as well as the interrelated <link\n        linkend=\"thread.prof.active\"><mallctl>thread.prof.active</mallctl></link>\n        mallctl.</para></listitem>\n      </varlistentry>\n\n      <varlistentry id=\"prof.dump\">\n        <term>\n          <mallctl>prof.dump</mallctl>\n          (<type>const char *</type>)\n          <literal>-w</literal>\n          [<option>--enable-prof</option>]\n        </term>\n        <listitem><para>Dump a memory profile to the specified file, or if NULL\n        is specified, to a file according to the pattern\n        <filename>&lt;prefix&gt;.&lt;pid&gt;.&lt;seq&gt;.m&lt;mseq&gt;.heap</filename>,\n        where <literal>&lt;prefix&gt;</literal> is controlled by the\n        <link\n        linkend=\"opt.prof_prefix\"><mallctl>opt.prof_prefix</mallctl></link>\n        option.</para></listitem>\n      </varlistentry>\n\n      <varlistentry id=\"prof.gdump\">\n        <term>\n          <mallctl>prof.gdump</mallctl>\n          (<type>bool</type>)\n          <literal>rw</literal>\n          [<option>--enable-prof</option>]\n        </term>\n        <listitem><para>When enabled, trigger a memory profile dump every time\n        the total virtual memory exceeds the previous maximum.  Profiles are\n        dumped to files named according to the pattern\n        <filename>&lt;prefix&gt;.&lt;pid&gt;.&lt;seq&gt;.u&lt;useq&gt;.heap</filename>,\n        where <literal>&lt;prefix&gt;</literal> is controlled by the <link\n        linkend=\"opt.prof_prefix\"><mallctl>opt.prof_prefix</mallctl></link>\n        option.</para></listitem>\n      </varlistentry>\n\n      <varlistentry id=\"prof.reset\">\n        <term>\n          <mallctl>prof.reset</mallctl>\n          (<type>size_t</type>)\n          <literal>-w</literal>\n          [<option>--enable-prof</option>]\n        </term>\n        <listitem><para>Reset all memory profile statistics, and optionally\n        update the sample rate (see <link\n        linkend=\"opt.lg_prof_sample\"><mallctl>opt.lg_prof_sample</mallctl></link>\n        and <link\n        linkend=\"prof.lg_sample\"><mallctl>prof.lg_sample</mallctl></link>).\n        </para></listitem>\n      </varlistentry>\n\n      <varlistentry id=\"prof.lg_sample\">\n        <term>\n          <mallctl>prof.lg_sample</mallctl>\n          (<type>size_t</type>)\n          <literal>r-</literal>\n          [<option>--enable-prof</option>]\n        </term>\n        <listitem><para>Get the current sample rate (see <link\n        linkend=\"opt.lg_prof_sample\"><mallctl>opt.lg_prof_sample</mallctl></link>).\n        </para></listitem>\n      </varlistentry>\n\n      <varlistentry id=\"prof.interval\">\n        <term>\n          <mallctl>prof.interval</mallctl>\n          (<type>uint64_t</type>)\n          <literal>r-</literal>\n          [<option>--enable-prof</option>]\n        </term>\n        <listitem><para>Average number of bytes allocated between\n        interval-based profile dumps.  See the\n        <link\n        linkend=\"opt.lg_prof_interval\"><mallctl>opt.lg_prof_interval</mallctl></link>\n        option for additional information.</para></listitem>\n      </varlistentry>\n\n      <varlistentry id=\"stats.cactive\">\n        <term>\n          <mallctl>stats.cactive</mallctl>\n          (<type>size_t *</type>)\n          <literal>r-</literal>\n          [<option>--enable-stats</option>]\n        </term>\n        <listitem><para>Pointer to a counter that contains an approximate count\n        of the current number of bytes in active pages.  The estimate may be\n        high, but never low, because each arena rounds up when computing its\n        contribution to the counter.  Note that the <link\n        linkend=\"epoch\"><mallctl>epoch</mallctl></link> mallctl has no bearing\n        on this counter.  Furthermore, counter consistency is maintained via\n        atomic operations, so it is necessary to use an atomic operation in\n        order to guarantee a consistent read when dereferencing the pointer.\n        </para></listitem>\n      </varlistentry>\n\n      <varlistentry id=\"stats.allocated\">\n        <term>\n          <mallctl>stats.allocated</mallctl>\n          (<type>size_t</type>)\n          <literal>r-</literal>\n          [<option>--enable-stats</option>]\n        </term>\n        <listitem><para>Total number of bytes allocated by the\n        application.</para></listitem>\n      </varlistentry>\n\n      <varlistentry id=\"stats.active\">\n        <term>\n          <mallctl>stats.active</mallctl>\n          (<type>size_t</type>)\n          <literal>r-</literal>\n          [<option>--enable-stats</option>]\n        </term>\n        <listitem><para>Total number of bytes in active pages allocated by the\n        application.  This is a multiple of the page size, and greater than or\n        equal to <link\n        linkend=\"stats.allocated\"><mallctl>stats.allocated</mallctl></link>.\n        This does not include <link linkend=\"stats.arenas.i.pdirty\">\n        <mallctl>stats.arenas.&lt;i&gt;.pdirty</mallctl></link>, nor pages\n        entirely devoted to allocator metadata.</para></listitem>\n      </varlistentry>\n\n      <varlistentry id=\"stats.metadata\">\n        <term>\n          <mallctl>stats.metadata</mallctl>\n          (<type>size_t</type>)\n          <literal>r-</literal>\n          [<option>--enable-stats</option>]\n        </term>\n        <listitem><para>Total number of bytes dedicated to metadata, which\n        comprise base allocations used for bootstrap-sensitive internal\n        allocator data structures, arena chunk headers (see <link\n        linkend=\"stats.arenas.i.metadata.mapped\"><mallctl>stats.arenas.&lt;i&gt;.metadata.mapped</mallctl></link>),\n        and internal allocations (see <link\n        linkend=\"stats.arenas.i.metadata.allocated\"><mallctl>stats.arenas.&lt;i&gt;.metadata.allocated</mallctl></link>).</para></listitem>\n      </varlistentry>\n\n      <varlistentry id=\"stats.resident\">\n        <term>\n          <mallctl>stats.resident</mallctl>\n          (<type>size_t</type>)\n          <literal>r-</literal>\n          [<option>--enable-stats</option>]\n        </term>\n        <listitem><para>Maximum number of bytes in physically resident data\n        pages mapped by the allocator, comprising all pages dedicated to\n        allocator metadata, pages backing active allocations, and unused dirty\n        pages.  This is a maximum rather than precise because pages may not\n        actually be physically resident if they correspond to demand-zeroed\n        virtual memory that has not yet been touched.  This is a multiple of the\n        page size, and is larger than <link\n        linkend=\"stats.active\"><mallctl>stats.active</mallctl></link>.</para></listitem>\n      </varlistentry>\n\n      <varlistentry id=\"stats.mapped\">\n        <term>\n          <mallctl>stats.mapped</mallctl>\n          (<type>size_t</type>)\n          <literal>r-</literal>\n          [<option>--enable-stats</option>]\n        </term>\n        <listitem><para>Total number of bytes in active chunks mapped by the\n        allocator.  This is a multiple of the chunk size, and is larger than\n        <link linkend=\"stats.active\"><mallctl>stats.active</mallctl></link>.\n        This does not include inactive chunks, even those that contain unused\n        dirty pages, which means that there is no strict ordering between this\n        and <link\n        linkend=\"stats.resident\"><mallctl>stats.resident</mallctl></link>.</para></listitem>\n      </varlistentry>\n\n      <varlistentry id=\"stats.retained\">\n        <term>\n          <mallctl>stats.retained</mallctl>\n          (<type>size_t</type>)\n          <literal>r-</literal>\n          [<option>--enable-stats</option>]\n        </term>\n        <listitem><para>Total number of bytes in virtual memory mappings that\n        were retained rather than being returned to the operating system via\n        e.g. <citerefentry><refentrytitle>munmap</refentrytitle>\n        <manvolnum>2</manvolnum></citerefentry>.  Retained virtual memory is\n        typically untouched, decommitted, or purged, so it has no strongly\n        associated physical memory (see <link\n        linkend=\"arena.i.chunk_hooks\">chunk hooks</link> for details).  Retained\n        memory is excluded from mapped memory statistics, e.g. <link\n        linkend=\"stats.mapped\"><mallctl>stats.mapped</mallctl></link>.\n        </para></listitem>\n      </varlistentry>\n\n      <varlistentry id=\"stats.arenas.i.dss\">\n        <term>\n          <mallctl>stats.arenas.&lt;i&gt;.dss</mallctl>\n          (<type>const char *</type>)\n          <literal>r-</literal>\n        </term>\n        <listitem><para>dss (<citerefentry><refentrytitle>sbrk</refentrytitle>\n        <manvolnum>2</manvolnum></citerefentry>) allocation precedence as\n        related to <citerefentry><refentrytitle>mmap</refentrytitle>\n        <manvolnum>2</manvolnum></citerefentry> allocation.  See <link\n        linkend=\"opt.dss\"><mallctl>opt.dss</mallctl></link> for details.\n        </para></listitem>\n      </varlistentry>\n\n      <varlistentry id=\"stats.arenas.i.lg_dirty_mult\">\n        <term>\n          <mallctl>stats.arenas.&lt;i&gt;.lg_dirty_mult</mallctl>\n          (<type>ssize_t</type>)\n          <literal>r-</literal>\n        </term>\n        <listitem><para>Minimum ratio (log base 2) of active to dirty pages.\n        See <link\n        linkend=\"opt.lg_dirty_mult\"><mallctl>opt.lg_dirty_mult</mallctl></link>\n        for details.</para></listitem>\n      </varlistentry>\n\n      <varlistentry id=\"stats.arenas.i.decay_time\">\n        <term>\n          <mallctl>stats.arenas.&lt;i&gt;.decay_time</mallctl>\n          (<type>ssize_t</type>)\n          <literal>r-</literal>\n        </term>\n        <listitem><para>Approximate time in seconds from the creation of a set\n        of unused dirty pages until an equivalent set of unused dirty pages is\n        purged and/or reused.  See <link\n        linkend=\"opt.decay_time\"><mallctl>opt.decay_time</mallctl></link>\n        for details.</para></listitem>\n      </varlistentry>\n\n      <varlistentry id=\"stats.arenas.i.nthreads\">\n        <term>\n          <mallctl>stats.arenas.&lt;i&gt;.nthreads</mallctl>\n          (<type>unsigned</type>)\n          <literal>r-</literal>\n        </term>\n        <listitem><para>Number of threads currently assigned to\n        arena.</para></listitem>\n      </varlistentry>\n\n      <varlistentry id=\"stats.arenas.i.pactive\">\n        <term>\n          <mallctl>stats.arenas.&lt;i&gt;.pactive</mallctl>\n          (<type>size_t</type>)\n          <literal>r-</literal>\n        </term>\n        <listitem><para>Number of pages in active runs.</para></listitem>\n      </varlistentry>\n\n      <varlistentry id=\"stats.arenas.i.pdirty\">\n        <term>\n          <mallctl>stats.arenas.&lt;i&gt;.pdirty</mallctl>\n          (<type>size_t</type>)\n          <literal>r-</literal>\n        </term>\n        <listitem><para>Number of pages within unused runs that are potentially\n        dirty, and for which <function>madvise<parameter>...</parameter>\n        <parameter><constant>MADV_DONTNEED</constant></parameter></function> or\n        similar has not been called.</para></listitem>\n      </varlistentry>\n\n      <varlistentry id=\"stats.arenas.i.mapped\">\n        <term>\n          <mallctl>stats.arenas.&lt;i&gt;.mapped</mallctl>\n          (<type>size_t</type>)\n          <literal>r-</literal>\n          [<option>--enable-stats</option>]\n        </term>\n        <listitem><para>Number of mapped bytes.</para></listitem>\n      </varlistentry>\n\n      <varlistentry id=\"stats.arenas.i.retained\">\n        <term>\n          <mallctl>stats.arenas.&lt;i&gt;.retained</mallctl>\n          (<type>size_t</type>)\n          <literal>r-</literal>\n          [<option>--enable-stats</option>]\n        </term>\n        <listitem><para>Number of retained bytes.  See <link\n        linkend=\"stats.retained\"><mallctl>stats.retained</mallctl></link> for\n        details.</para></listitem>\n      </varlistentry>\n\n      <varlistentry id=\"stats.arenas.i.metadata.mapped\">\n        <term>\n          <mallctl>stats.arenas.&lt;i&gt;.metadata.mapped</mallctl>\n          (<type>size_t</type>)\n          <literal>r-</literal>\n          [<option>--enable-stats</option>]\n        </term>\n        <listitem><para>Number of mapped bytes in arena chunk headers, which\n        track the states of the non-metadata pages.</para></listitem>\n      </varlistentry>\n\n      <varlistentry id=\"stats.arenas.i.metadata.allocated\">\n        <term>\n          <mallctl>stats.arenas.&lt;i&gt;.metadata.allocated</mallctl>\n          (<type>size_t</type>)\n          <literal>r-</literal>\n          [<option>--enable-stats</option>]\n        </term>\n        <listitem><para>Number of bytes dedicated to internal allocations.\n        Internal allocations differ from application-originated allocations in\n        that they are for internal use, and that they are omitted from heap\n        profiles.  This statistic is reported separately from <link\n        linkend=\"stats.metadata\"><mallctl>stats.metadata</mallctl></link> and\n        <link\n        linkend=\"stats.arenas.i.metadata.mapped\"><mallctl>stats.arenas.&lt;i&gt;.metadata.mapped</mallctl></link>\n        because it overlaps with e.g. the <link\n        linkend=\"stats.allocated\"><mallctl>stats.allocated</mallctl></link> and\n        <link linkend=\"stats.active\"><mallctl>stats.active</mallctl></link>\n        statistics, whereas the other metadata statistics do\n        not.</para></listitem>\n      </varlistentry>\n\n      <varlistentry id=\"stats.arenas.i.npurge\">\n        <term>\n          <mallctl>stats.arenas.&lt;i&gt;.npurge</mallctl>\n          (<type>uint64_t</type>)\n          <literal>r-</literal>\n          [<option>--enable-stats</option>]\n        </term>\n        <listitem><para>Number of dirty page purge sweeps performed.\n        </para></listitem>\n      </varlistentry>\n\n      <varlistentry id=\"stats.arenas.i.nmadvise\">\n        <term>\n          <mallctl>stats.arenas.&lt;i&gt;.nmadvise</mallctl>\n          (<type>uint64_t</type>)\n          <literal>r-</literal>\n          [<option>--enable-stats</option>]\n        </term>\n        <listitem><para>Number of <function>madvise<parameter>...</parameter>\n        <parameter><constant>MADV_DONTNEED</constant></parameter></function> or\n        similar calls made to purge dirty pages.</para></listitem>\n      </varlistentry>\n\n      <varlistentry id=\"stats.arenas.i.purged\">\n        <term>\n          <mallctl>stats.arenas.&lt;i&gt;.purged</mallctl>\n          (<type>uint64_t</type>)\n          <literal>r-</literal>\n          [<option>--enable-stats</option>]\n        </term>\n        <listitem><para>Number of pages purged.</para></listitem>\n      </varlistentry>\n\n      <varlistentry id=\"stats.arenas.i.small.allocated\">\n        <term>\n          <mallctl>stats.arenas.&lt;i&gt;.small.allocated</mallctl>\n          (<type>size_t</type>)\n          <literal>r-</literal>\n          [<option>--enable-stats</option>]\n        </term>\n        <listitem><para>Number of bytes currently allocated by small objects.\n        </para></listitem>\n      </varlistentry>\n\n      <varlistentry id=\"stats.arenas.i.small.nmalloc\">\n        <term>\n          <mallctl>stats.arenas.&lt;i&gt;.small.nmalloc</mallctl>\n          (<type>uint64_t</type>)\n          <literal>r-</literal>\n          [<option>--enable-stats</option>]\n        </term>\n        <listitem><para>Cumulative number of allocation requests served by\n        small bins.</para></listitem>\n      </varlistentry>\n\n      <varlistentry id=\"stats.arenas.i.small.ndalloc\">\n        <term>\n          <mallctl>stats.arenas.&lt;i&gt;.small.ndalloc</mallctl>\n          (<type>uint64_t</type>)\n          <literal>r-</literal>\n          [<option>--enable-stats</option>]\n        </term>\n        <listitem><para>Cumulative number of small objects returned to bins.\n        </para></listitem>\n      </varlistentry>\n\n      <varlistentry id=\"stats.arenas.i.small.nrequests\">\n        <term>\n          <mallctl>stats.arenas.&lt;i&gt;.small.nrequests</mallctl>\n          (<type>uint64_t</type>)\n          <literal>r-</literal>\n          [<option>--enable-stats</option>]\n        </term>\n        <listitem><para>Cumulative number of small allocation requests.\n        </para></listitem>\n      </varlistentry>\n\n      <varlistentry id=\"stats.arenas.i.large.allocated\">\n        <term>\n          <mallctl>stats.arenas.&lt;i&gt;.large.allocated</mallctl>\n          (<type>size_t</type>)\n          <literal>r-</literal>\n          [<option>--enable-stats</option>]\n        </term>\n        <listitem><para>Number of bytes currently allocated by large objects.\n        </para></listitem>\n      </varlistentry>\n\n      <varlistentry id=\"stats.arenas.i.large.nmalloc\">\n        <term>\n          <mallctl>stats.arenas.&lt;i&gt;.large.nmalloc</mallctl>\n          (<type>uint64_t</type>)\n          <literal>r-</literal>\n          [<option>--enable-stats</option>]\n        </term>\n        <listitem><para>Cumulative number of large allocation requests served\n        directly by the arena.</para></listitem>\n      </varlistentry>\n\n      <varlistentry id=\"stats.arenas.i.large.ndalloc\">\n        <term>\n          <mallctl>stats.arenas.&lt;i&gt;.large.ndalloc</mallctl>\n          (<type>uint64_t</type>)\n          <literal>r-</literal>\n          [<option>--enable-stats</option>]\n        </term>\n        <listitem><para>Cumulative number of large deallocation requests served\n        directly by the arena.</para></listitem>\n      </varlistentry>\n\n      <varlistentry id=\"stats.arenas.i.large.nrequests\">\n        <term>\n          <mallctl>stats.arenas.&lt;i&gt;.large.nrequests</mallctl>\n          (<type>uint64_t</type>)\n          <literal>r-</literal>\n          [<option>--enable-stats</option>]\n        </term>\n        <listitem><para>Cumulative number of large allocation requests.\n        </para></listitem>\n      </varlistentry>\n\n      <varlistentry id=\"stats.arenas.i.huge.allocated\">\n        <term>\n          <mallctl>stats.arenas.&lt;i&gt;.huge.allocated</mallctl>\n          (<type>size_t</type>)\n          <literal>r-</literal>\n          [<option>--enable-stats</option>]\n        </term>\n        <listitem><para>Number of bytes currently allocated by huge objects.\n        </para></listitem>\n      </varlistentry>\n\n      <varlistentry id=\"stats.arenas.i.huge.nmalloc\">\n        <term>\n          <mallctl>stats.arenas.&lt;i&gt;.huge.nmalloc</mallctl>\n          (<type>uint64_t</type>)\n          <literal>r-</literal>\n          [<option>--enable-stats</option>]\n        </term>\n        <listitem><para>Cumulative number of huge allocation requests served\n        directly by the arena.</para></listitem>\n      </varlistentry>\n\n      <varlistentry id=\"stats.arenas.i.huge.ndalloc\">\n        <term>\n          <mallctl>stats.arenas.&lt;i&gt;.huge.ndalloc</mallctl>\n          (<type>uint64_t</type>)\n          <literal>r-</literal>\n          [<option>--enable-stats</option>]\n        </term>\n        <listitem><para>Cumulative number of huge deallocation requests served\n        directly by the arena.</para></listitem>\n      </varlistentry>\n\n      <varlistentry id=\"stats.arenas.i.huge.nrequests\">\n        <term>\n          <mallctl>stats.arenas.&lt;i&gt;.huge.nrequests</mallctl>\n          (<type>uint64_t</type>)\n          <literal>r-</literal>\n          [<option>--enable-stats</option>]\n        </term>\n        <listitem><para>Cumulative number of huge allocation requests.\n        </para></listitem>\n      </varlistentry>\n\n      <varlistentry id=\"stats.arenas.i.bins.j.nmalloc\">\n        <term>\n          <mallctl>stats.arenas.&lt;i&gt;.bins.&lt;j&gt;.nmalloc</mallctl>\n          (<type>uint64_t</type>)\n          <literal>r-</literal>\n          [<option>--enable-stats</option>]\n        </term>\n        <listitem><para>Cumulative number of allocations served by bin.\n        </para></listitem>\n      </varlistentry>\n\n      <varlistentry id=\"stats.arenas.i.bins.j.ndalloc\">\n        <term>\n          <mallctl>stats.arenas.&lt;i&gt;.bins.&lt;j&gt;.ndalloc</mallctl>\n          (<type>uint64_t</type>)\n          <literal>r-</literal>\n          [<option>--enable-stats</option>]\n        </term>\n        <listitem><para>Cumulative number of allocations returned to bin.\n        </para></listitem>\n      </varlistentry>\n\n      <varlistentry id=\"stats.arenas.i.bins.j.nrequests\">\n        <term>\n          <mallctl>stats.arenas.&lt;i&gt;.bins.&lt;j&gt;.nrequests</mallctl>\n          (<type>uint64_t</type>)\n          <literal>r-</literal>\n          [<option>--enable-stats</option>]\n        </term>\n        <listitem><para>Cumulative number of allocation\n        requests.</para></listitem>\n      </varlistentry>\n\n      <varlistentry id=\"stats.arenas.i.bins.j.curregs\">\n        <term>\n          <mallctl>stats.arenas.&lt;i&gt;.bins.&lt;j&gt;.curregs</mallctl>\n          (<type>size_t</type>)\n          <literal>r-</literal>\n          [<option>--enable-stats</option>]\n        </term>\n        <listitem><para>Current number of regions for this size\n        class.</para></listitem>\n      </varlistentry>\n\n      <varlistentry id=\"stats.arenas.i.bins.j.nfills\">\n        <term>\n          <mallctl>stats.arenas.&lt;i&gt;.bins.&lt;j&gt;.nfills</mallctl>\n          (<type>uint64_t</type>)\n          <literal>r-</literal>\n          [<option>--enable-stats</option> <option>--enable-tcache</option>]\n        </term>\n        <listitem><para>Cumulative number of tcache fills.</para></listitem>\n      </varlistentry>\n\n      <varlistentry id=\"stats.arenas.i.bins.j.nflushes\">\n        <term>\n          <mallctl>stats.arenas.&lt;i&gt;.bins.&lt;j&gt;.nflushes</mallctl>\n          (<type>uint64_t</type>)\n          <literal>r-</literal>\n          [<option>--enable-stats</option> <option>--enable-tcache</option>]\n        </term>\n        <listitem><para>Cumulative number of tcache flushes.</para></listitem>\n      </varlistentry>\n\n      <varlistentry id=\"stats.arenas.i.bins.j.nruns\">\n        <term>\n          <mallctl>stats.arenas.&lt;i&gt;.bins.&lt;j&gt;.nruns</mallctl>\n          (<type>uint64_t</type>)\n          <literal>r-</literal>\n          [<option>--enable-stats</option>]\n        </term>\n        <listitem><para>Cumulative number of runs created.</para></listitem>\n      </varlistentry>\n\n      <varlistentry id=\"stats.arenas.i.bins.j.nreruns\">\n        <term>\n          <mallctl>stats.arenas.&lt;i&gt;.bins.&lt;j&gt;.nreruns</mallctl>\n          (<type>uint64_t</type>)\n          <literal>r-</literal>\n          [<option>--enable-stats</option>]\n        </term>\n        <listitem><para>Cumulative number of times the current run from which\n        to allocate changed.</para></listitem>\n      </varlistentry>\n\n      <varlistentry id=\"stats.arenas.i.bins.j.curruns\">\n        <term>\n          <mallctl>stats.arenas.&lt;i&gt;.bins.&lt;j&gt;.curruns</mallctl>\n          (<type>size_t</type>)\n          <literal>r-</literal>\n          [<option>--enable-stats</option>]\n        </term>\n        <listitem><para>Current number of runs.</para></listitem>\n      </varlistentry>\n\n      <varlistentry id=\"stats.arenas.i.lruns.j.nmalloc\">\n        <term>\n          <mallctl>stats.arenas.&lt;i&gt;.lruns.&lt;j&gt;.nmalloc</mallctl>\n          (<type>uint64_t</type>)\n          <literal>r-</literal>\n          [<option>--enable-stats</option>]\n        </term>\n        <listitem><para>Cumulative number of allocation requests for this size\n        class served directly by the arena.</para></listitem>\n      </varlistentry>\n\n      <varlistentry id=\"stats.arenas.i.lruns.j.ndalloc\">\n        <term>\n          <mallctl>stats.arenas.&lt;i&gt;.lruns.&lt;j&gt;.ndalloc</mallctl>\n          (<type>uint64_t</type>)\n          <literal>r-</literal>\n          [<option>--enable-stats</option>]\n        </term>\n        <listitem><para>Cumulative number of deallocation requests for this\n        size class served directly by the arena.</para></listitem>\n      </varlistentry>\n\n      <varlistentry id=\"stats.arenas.i.lruns.j.nrequests\">\n        <term>\n          <mallctl>stats.arenas.&lt;i&gt;.lruns.&lt;j&gt;.nrequests</mallctl>\n          (<type>uint64_t</type>)\n          <literal>r-</literal>\n          [<option>--enable-stats</option>]\n        </term>\n        <listitem><para>Cumulative number of allocation requests for this size\n        class.</para></listitem>\n      </varlistentry>\n\n      <varlistentry id=\"stats.arenas.i.lruns.j.curruns\">\n        <term>\n          <mallctl>stats.arenas.&lt;i&gt;.lruns.&lt;j&gt;.curruns</mallctl>\n          (<type>size_t</type>)\n          <literal>r-</literal>\n          [<option>--enable-stats</option>]\n        </term>\n        <listitem><para>Current number of runs for this size class.\n        </para></listitem>\n      </varlistentry>\n\n      <varlistentry id=\"stats.arenas.i.hchunks.j.nmalloc\">\n        <term>\n          <mallctl>stats.arenas.&lt;i&gt;.hchunks.&lt;j&gt;.nmalloc</mallctl>\n          (<type>uint64_t</type>)\n          <literal>r-</literal>\n          [<option>--enable-stats</option>]\n        </term>\n        <listitem><para>Cumulative number of allocation requests for this size\n        class served directly by the arena.</para></listitem>\n      </varlistentry>\n\n      <varlistentry id=\"stats.arenas.i.hchunks.j.ndalloc\">\n        <term>\n          <mallctl>stats.arenas.&lt;i&gt;.hchunks.&lt;j&gt;.ndalloc</mallctl>\n          (<type>uint64_t</type>)\n          <literal>r-</literal>\n          [<option>--enable-stats</option>]\n        </term>\n        <listitem><para>Cumulative number of deallocation requests for this\n        size class served directly by the arena.</para></listitem>\n      </varlistentry>\n\n      <varlistentry id=\"stats.arenas.i.hchunks.j.nrequests\">\n        <term>\n          <mallctl>stats.arenas.&lt;i&gt;.hchunks.&lt;j&gt;.nrequests</mallctl>\n          (<type>uint64_t</type>)\n          <literal>r-</literal>\n          [<option>--enable-stats</option>]\n        </term>\n        <listitem><para>Cumulative number of allocation requests for this size\n        class.</para></listitem>\n      </varlistentry>\n\n      <varlistentry id=\"stats.arenas.i.hchunks.j.curhchunks\">\n        <term>\n          <mallctl>stats.arenas.&lt;i&gt;.hchunks.&lt;j&gt;.curhchunks</mallctl>\n          (<type>size_t</type>)\n          <literal>r-</literal>\n          [<option>--enable-stats</option>]\n        </term>\n        <listitem><para>Current number of huge allocations for this size class.\n        </para></listitem>\n      </varlistentry>\n    </variablelist>\n  </refsect1>\n  <refsect1 id=\"heap_profile_format\">\n    <title>HEAP PROFILE FORMAT</title>\n    <para>Although the heap profiling functionality was originally designed to\n    be compatible with the\n    <command>pprof</command> command that is developed as part of the <ulink\n    url=\"http://code.google.com/p/gperftools/\">gperftools\n    package</ulink>, the addition of per thread heap profiling functionality\n    required a different heap profile format.  The <command>jeprof</command>\n    command is derived from <command>pprof</command>, with enhancements to\n    support the heap profile format described here.</para>\n\n    <para>In the following hypothetical heap profile, <constant>[...]</constant>\n    indicates elision for the sake of compactness.  <programlisting><![CDATA[\nheap_v2/524288\n  t*: 28106: 56637512 [0: 0]\n  [...]\n  t3: 352: 16777344 [0: 0]\n  [...]\n  t99: 17754: 29341640 [0: 0]\n  [...]\n@ 0x5f86da8 0x5f5a1dc [...] 0x29e4d4e 0xa200316 0xabb2988 [...]\n  t*: 13: 6688 [0: 0]\n  t3: 12: 6496 [0: ]\n  t99: 1: 192 [0: 0]\n[...]\n\nMAPPED_LIBRARIES:\n[...]]]></programlisting> The following matches the above heap profile, but most\ntokens are replaced with <constant>&lt;description&gt;</constant> to indicate\ndescriptions of the corresponding fields.  <programlisting><![CDATA[\n<heap_profile_format_version>/<mean_sample_interval>\n  <aggregate>: <curobjs>: <curbytes> [<cumobjs>: <cumbytes>]\n  [...]\n  <thread_3_aggregate>: <curobjs>: <curbytes>[<cumobjs>: <cumbytes>]\n  [...]\n  <thread_99_aggregate>: <curobjs>: <curbytes>[<cumobjs>: <cumbytes>]\n  [...]\n@ <top_frame> <frame> [...] <frame> <frame> <frame> [...]\n  <backtrace_aggregate>: <curobjs>: <curbytes> [<cumobjs>: <cumbytes>]\n  <backtrace_thread_3>: <curobjs>: <curbytes> [<cumobjs>: <cumbytes>]\n  <backtrace_thread_99>: <curobjs>: <curbytes> [<cumobjs>: <cumbytes>]\n[...]\n\nMAPPED_LIBRARIES:\n</proc/<pid>/maps>]]></programlisting></para>\n  </refsect1>\n\n  <refsect1 id=\"debugging_malloc_problems\">\n    <title>DEBUGGING MALLOC PROBLEMS</title>\n    <para>When debugging, it is a good idea to configure/build jemalloc with\n    the <option>--enable-debug</option> and <option>--enable-fill</option>\n    options, and recompile the program with suitable options and symbols for\n    debugger support.  When so configured, jemalloc incorporates a wide variety\n    of run-time assertions that catch application errors such as double-free,\n    write-after-free, etc.</para>\n\n    <para>Programs often accidentally depend on &ldquo;uninitialized&rdquo;\n    memory actually being filled with zero bytes.  Junk filling\n    (see the <link linkend=\"opt.junk\"><mallctl>opt.junk</mallctl></link>\n    option) tends to expose such bugs in the form of obviously incorrect\n    results and/or coredumps.  Conversely, zero\n    filling (see the <link\n    linkend=\"opt.zero\"><mallctl>opt.zero</mallctl></link> option) eliminates\n    the symptoms of such bugs.  Between these two options, it is usually\n    possible to quickly detect, diagnose, and eliminate such bugs.</para>\n\n    <para>This implementation does not provide much detail about the problems\n    it detects, because the performance impact for storing such information\n    would be prohibitive.  However, jemalloc does integrate with the most\n    excellent <ulink url=\"http://valgrind.org/\">Valgrind</ulink> tool if the\n    <option>--enable-valgrind</option> configuration option is enabled.</para>\n  </refsect1>\n  <refsect1 id=\"diagnostic_messages\">\n    <title>DIAGNOSTIC MESSAGES</title>\n    <para>If any of the memory allocation/deallocation functions detect an\n    error or warning condition, a message will be printed to file descriptor\n    <constant>STDERR_FILENO</constant>.  Errors will result in the process\n    dumping core.  If the <link\n    linkend=\"opt.abort\"><mallctl>opt.abort</mallctl></link> option is set, most\n    warnings are treated as errors.</para>\n\n    <para>The <varname>malloc_message</varname> variable allows the programmer\n    to override the function which emits the text strings forming the errors\n    and warnings if for some reason the <constant>STDERR_FILENO</constant> file\n    descriptor is not suitable for this.\n    <function>malloc_message<parameter/></function> takes the\n    <parameter>cbopaque</parameter> pointer argument that is\n    <constant>NULL</constant> unless overridden by the arguments in a call to\n    <function>malloc_stats_print<parameter/></function>, followed by a string\n    pointer.  Please note that doing anything which tries to allocate memory in\n    this function is likely to result in a crash or deadlock.</para>\n\n    <para>All messages are prefixed by\n    &ldquo;<computeroutput>&lt;jemalloc&gt;: </computeroutput>&rdquo;.</para>\n  </refsect1>\n  <refsect1 id=\"return_values\">\n    <title>RETURN VALUES</title>\n    <refsect2>\n      <title>Standard API</title>\n      <para>The <function>malloc<parameter/></function> and\n      <function>calloc<parameter/></function> functions return a pointer to the\n      allocated memory if successful; otherwise a <constant>NULL</constant>\n      pointer is returned and <varname>errno</varname> is set to\n      <errorname>ENOMEM</errorname>.</para>\n\n      <para>The <function>posix_memalign<parameter/></function> function\n      returns the value 0 if successful; otherwise it returns an error value.\n      The <function>posix_memalign<parameter/></function> function will fail\n      if:\n        <variablelist>\n          <varlistentry>\n            <term><errorname>EINVAL</errorname></term>\n\n            <listitem><para>The <parameter>alignment</parameter> parameter is\n            not a power of 2 at least as large as\n            <code language=\"C\">sizeof(<type>void *</type>)</code>.\n            </para></listitem>\n          </varlistentry>\n          <varlistentry>\n            <term><errorname>ENOMEM</errorname></term>\n\n            <listitem><para>Memory allocation error.</para></listitem>\n          </varlistentry>\n        </variablelist>\n      </para>\n\n      <para>The <function>aligned_alloc<parameter/></function> function returns\n      a pointer to the allocated memory if successful; otherwise a\n      <constant>NULL</constant> pointer is returned and\n      <varname>errno</varname> is set.  The\n      <function>aligned_alloc<parameter/></function> function will fail if:\n        <variablelist>\n          <varlistentry>\n            <term><errorname>EINVAL</errorname></term>\n\n            <listitem><para>The <parameter>alignment</parameter> parameter is\n            not a power of 2.\n            </para></listitem>\n          </varlistentry>\n          <varlistentry>\n            <term><errorname>ENOMEM</errorname></term>\n\n            <listitem><para>Memory allocation error.</para></listitem>\n          </varlistentry>\n        </variablelist>\n      </para>\n\n      <para>The <function>realloc<parameter/></function> function returns a\n      pointer, possibly identical to <parameter>ptr</parameter>, to the\n      allocated memory if successful; otherwise a <constant>NULL</constant>\n      pointer is returned, and <varname>errno</varname> is set to\n      <errorname>ENOMEM</errorname> if the error was the result of an\n      allocation failure.  The <function>realloc<parameter/></function>\n      function always leaves the original buffer intact when an error occurs.\n      </para>\n\n      <para>The <function>free<parameter/></function> function returns no\n      value.</para>\n    </refsect2>\n    <refsect2>\n      <title>Non-standard API</title>\n      <para>The <function>mallocx<parameter/></function> and\n      <function>rallocx<parameter/></function> functions return a pointer to\n      the allocated memory if successful; otherwise a <constant>NULL</constant>\n      pointer is returned to indicate insufficient contiguous memory was\n      available to service the allocation request.  </para>\n\n      <para>The <function>xallocx<parameter/></function> function returns the\n      real size of the resulting resized allocation pointed to by\n      <parameter>ptr</parameter>, which is a value less than\n      <parameter>size</parameter> if the allocation could not be adequately\n      grown in place.  </para>\n\n      <para>The <function>sallocx<parameter/></function> function returns the\n      real size of the allocation pointed to by <parameter>ptr</parameter>.\n      </para>\n\n      <para>The <function>nallocx<parameter/></function> returns the real size\n      that would result from a successful equivalent\n      <function>mallocx<parameter/></function> function call, or zero if\n      insufficient memory is available to perform the size computation.  </para>\n\n      <para>The <function>mallctl<parameter/></function>,\n      <function>mallctlnametomib<parameter/></function>, and\n      <function>mallctlbymib<parameter/></function> functions return 0 on\n      success; otherwise they return an error value.  The functions will fail\n      if:\n        <variablelist>\n          <varlistentry>\n            <term><errorname>EINVAL</errorname></term>\n\n            <listitem><para><parameter>newp</parameter> is not\n            <constant>NULL</constant>, and <parameter>newlen</parameter> is too\n            large or too small.  Alternatively, <parameter>*oldlenp</parameter>\n            is too large or too small; in this case as much data as possible\n            are read despite the error.</para></listitem>\n          </varlistentry>\n          <varlistentry>\n            <term><errorname>ENOENT</errorname></term>\n\n            <listitem><para><parameter>name</parameter> or\n            <parameter>mib</parameter> specifies an unknown/invalid\n            value.</para></listitem>\n          </varlistentry>\n          <varlistentry>\n            <term><errorname>EPERM</errorname></term>\n\n            <listitem><para>Attempt to read or write void value, or attempt to\n            write read-only value.</para></listitem>\n          </varlistentry>\n          <varlistentry>\n            <term><errorname>EAGAIN</errorname></term>\n\n            <listitem><para>A memory allocation failure\n            occurred.</para></listitem>\n          </varlistentry>\n          <varlistentry>\n            <term><errorname>EFAULT</errorname></term>\n\n            <listitem><para>An interface with side effects failed in some way\n            not directly related to <function>mallctl*<parameter/></function>\n            read/write processing.</para></listitem>\n          </varlistentry>\n        </variablelist>\n      </para>\n\n      <para>The <function>malloc_usable_size<parameter/></function> function\n      returns the usable size of the allocation pointed to by\n      <parameter>ptr</parameter>.  </para>\n    </refsect2>\n  </refsect1>\n  <refsect1 id=\"environment\">\n    <title>ENVIRONMENT</title>\n    <para>The following environment variable affects the execution of the\n    allocation functions:\n      <variablelist>\n        <varlistentry>\n          <term><envar>MALLOC_CONF</envar></term>\n\n          <listitem><para>If the environment variable\n          <envar>MALLOC_CONF</envar> is set, the characters it contains\n          will be interpreted as options.</para></listitem>\n        </varlistentry>\n      </variablelist>\n    </para>\n  </refsect1>\n  <refsect1 id=\"examples\">\n    <title>EXAMPLES</title>\n    <para>To dump core whenever a problem occurs:\n      <screen>ln -s 'abort:true' /etc/malloc.conf</screen>\n    </para>\n    <para>To specify in the source a chunk size that is 16 MiB:\n      <programlisting language=\"C\"><![CDATA[\nmalloc_conf = \"lg_chunk:24\";]]></programlisting></para>\n  </refsect1>\n  <refsect1 id=\"see_also\">\n    <title>SEE ALSO</title>\n    <para><citerefentry><refentrytitle>madvise</refentrytitle>\n    <manvolnum>2</manvolnum></citerefentry>,\n    <citerefentry><refentrytitle>mmap</refentrytitle>\n    <manvolnum>2</manvolnum></citerefentry>,\n    <citerefentry><refentrytitle>sbrk</refentrytitle>\n    <manvolnum>2</manvolnum></citerefentry>,\n    <citerefentry><refentrytitle>utrace</refentrytitle>\n    <manvolnum>2</manvolnum></citerefentry>,\n    <citerefentry><refentrytitle>alloca</refentrytitle>\n    <manvolnum>3</manvolnum></citerefentry>,\n    <citerefentry><refentrytitle>atexit</refentrytitle>\n    <manvolnum>3</manvolnum></citerefentry>,\n    <citerefentry><refentrytitle>getpagesize</refentrytitle>\n    <manvolnum>3</manvolnum></citerefentry></para>\n  </refsect1>\n  <refsect1 id=\"standards\">\n    <title>STANDARDS</title>\n    <para>The <function>malloc<parameter/></function>,\n    <function>calloc<parameter/></function>,\n    <function>realloc<parameter/></function>, and\n    <function>free<parameter/></function> functions conform to ISO/IEC\n    9899:1990 (&ldquo;ISO C90&rdquo;).</para>\n\n    <para>The <function>posix_memalign<parameter/></function> function conforms\n    to IEEE Std 1003.1-2001 (&ldquo;POSIX.1&rdquo;).</para>\n  </refsect1>\n</refentry>\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/deps/jemalloc/doc/manpages.xsl.in",
    "content": "<xsl:stylesheet xmlns:xsl=\"http://www.w3.org/1999/XSL/Transform\" version=\"1.0\">\n  <xsl:import href=\"@XSLROOT@/manpages/docbook.xsl\"/>\n  <xsl:import href=\"@abs_srcroot@doc/stylesheet.xsl\"/>\n</xsl:stylesheet>\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/deps/jemalloc/doc/stylesheet.xsl",
    "content": "<xsl:stylesheet xmlns:xsl=\"http://www.w3.org/1999/XSL/Transform\" version=\"1.0\">\n  <xsl:param name=\"funcsynopsis.style\">ansi</xsl:param>\n  <xsl:param name=\"function.parens\" select=\"1\"/>\n  <xsl:template match=\"mallctl\">\n    \"<xsl:call-template name=\"inline.monoseq\"/>\"\n  </xsl:template>\n</xsl:stylesheet>\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/deps/jemalloc/include/jemalloc/internal/arena.h",
    "content": "/******************************************************************************/\n#ifdef JEMALLOC_H_TYPES\n\n#define\tLARGE_MINCLASS\t\t(ZU(1) << LG_LARGE_MINCLASS)\n\n/* Maximum number of regions in one run. */\n#define\tLG_RUN_MAXREGS\t\t(LG_PAGE - LG_TINY_MIN)\n#define\tRUN_MAXREGS\t\t(1U << LG_RUN_MAXREGS)\n\n/*\n * Minimum redzone size.  Redzones may be larger than this if necessary to\n * preserve region alignment.\n */\n#define\tREDZONE_MINSIZE\t\t16\n\n/*\n * The minimum ratio of active:dirty pages per arena is computed as:\n *\n *   (nactive >> lg_dirty_mult) >= ndirty\n *\n * So, supposing that lg_dirty_mult is 3, there can be no less than 8 times as\n * many active pages as dirty pages.\n */\n#define\tLG_DIRTY_MULT_DEFAULT\t3\n\ntypedef enum {\n\tpurge_mode_ratio = 0,\n\tpurge_mode_decay = 1,\n\n\tpurge_mode_limit = 2\n} purge_mode_t;\n#define\tPURGE_DEFAULT\t\tpurge_mode_ratio\n/* Default decay time in seconds. */\n#define\tDECAY_TIME_DEFAULT\t10\n/* Number of event ticks between time checks. */\n#define\tDECAY_NTICKS_PER_UPDATE\t1000\n\ntypedef struct arena_runs_dirty_link_s arena_runs_dirty_link_t;\ntypedef struct arena_avail_links_s arena_avail_links_t;\ntypedef struct arena_run_s arena_run_t;\ntypedef struct arena_chunk_map_bits_s arena_chunk_map_bits_t;\ntypedef struct arena_chunk_map_misc_s arena_chunk_map_misc_t;\ntypedef struct arena_chunk_s arena_chunk_t;\ntypedef struct arena_bin_info_s arena_bin_info_t;\ntypedef struct arena_bin_s arena_bin_t;\ntypedef struct arena_s arena_t;\ntypedef struct arena_tdata_s arena_tdata_t;\n\n#endif /* JEMALLOC_H_TYPES */\n/******************************************************************************/\n#ifdef JEMALLOC_H_STRUCTS\n\n#ifdef JEMALLOC_ARENA_STRUCTS_A\nstruct arena_run_s {\n\t/* Index of bin this run is associated with. */\n\tszind_t\t\tbinind;\n\n\t/* Number of free regions in run. */\n\tunsigned\tnfree;\n\n\t/* Per region allocated/deallocated bitmap. */\n\tbitmap_t\tbitmap[BITMAP_GROUPS_MAX];\n};\n\n/* Each element of the chunk map corresponds to one page within the chunk. */\nstruct arena_chunk_map_bits_s {\n\t/*\n\t * Run address (or size) and various flags are stored together.  The bit\n\t * layout looks like (assuming 32-bit system):\n\t *\n\t *   ???????? ???????? ???nnnnn nnndumla\n\t *\n\t * ? : Unallocated: Run address for first/last pages, unset for internal\n\t *                  pages.\n\t *     Small: Run page offset.\n\t *     Large: Run page count for first page, unset for trailing pages.\n\t * n : binind for small size class, BININD_INVALID for large size class.\n\t * d : dirty?\n\t * u : unzeroed?\n\t * m : decommitted?\n\t * l : large?\n\t * a : allocated?\n\t *\n\t * Following are example bit patterns for the three types of runs.\n\t *\n\t * p : run page offset\n\t * s : run size\n\t * n : binind for size class; large objects set these to BININD_INVALID\n\t * x : don't care\n\t * - : 0\n\t * + : 1\n\t * [DUMLA] : bit set\n\t * [dumla] : bit unset\n\t *\n\t *   Unallocated (clean):\n\t *     ssssssss ssssssss sss+++++ +++dum-a\n\t *     xxxxxxxx xxxxxxxx xxxxxxxx xxx-Uxxx\n\t *     ssssssss ssssssss sss+++++ +++dUm-a\n\t *\n\t *   Unallocated (dirty):\n\t *     ssssssss ssssssss sss+++++ +++D-m-a\n\t *     xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx\n\t *     ssssssss ssssssss sss+++++ +++D-m-a\n\t *\n\t *   Small:\n\t *     pppppppp pppppppp pppnnnnn nnnd---A\n\t *     pppppppp pppppppp pppnnnnn nnn----A\n\t *     pppppppp pppppppp pppnnnnn nnnd---A\n\t *\n\t *   Large:\n\t *     ssssssss ssssssss sss+++++ +++D--LA\n\t *     xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx\n\t *     -------- -------- ---+++++ +++D--LA\n\t *\n\t *   Large (sampled, size <= LARGE_MINCLASS):\n\t *     ssssssss ssssssss sssnnnnn nnnD--LA\n\t *     xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx\n\t *     -------- -------- ---+++++ +++D--LA\n\t *\n\t *   Large (not sampled, size == LARGE_MINCLASS):\n\t *     ssssssss ssssssss sss+++++ +++D--LA\n\t *     xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx\n\t *     -------- -------- ---+++++ +++D--LA\n\t */\n\tsize_t\t\t\t\tbits;\n#define\tCHUNK_MAP_ALLOCATED\t((size_t)0x01U)\n#define\tCHUNK_MAP_LARGE\t\t((size_t)0x02U)\n#define\tCHUNK_MAP_STATE_MASK\t((size_t)0x3U)\n\n#define\tCHUNK_MAP_DECOMMITTED\t((size_t)0x04U)\n#define\tCHUNK_MAP_UNZEROED\t((size_t)0x08U)\n#define\tCHUNK_MAP_DIRTY\t\t((size_t)0x10U)\n#define\tCHUNK_MAP_FLAGS_MASK\t((size_t)0x1cU)\n\n#define\tCHUNK_MAP_BININD_SHIFT\t5\n#define\tBININD_INVALID\t\t((size_t)0xffU)\n#define\tCHUNK_MAP_BININD_MASK\t(BININD_INVALID << CHUNK_MAP_BININD_SHIFT)\n#define\tCHUNK_MAP_BININD_INVALID CHUNK_MAP_BININD_MASK\n\n#define\tCHUNK_MAP_RUNIND_SHIFT\t(CHUNK_MAP_BININD_SHIFT + 8)\n#define\tCHUNK_MAP_SIZE_SHIFT\t(CHUNK_MAP_RUNIND_SHIFT - LG_PAGE)\n#define\tCHUNK_MAP_SIZE_MASK\t\t\t\t\t\t\\\n    (~(CHUNK_MAP_BININD_MASK | CHUNK_MAP_FLAGS_MASK | CHUNK_MAP_STATE_MASK))\n};\n\nstruct arena_runs_dirty_link_s {\n\tqr(arena_runs_dirty_link_t)\trd_link;\n};\n\n/*\n * Each arena_chunk_map_misc_t corresponds to one page within the chunk, just\n * like arena_chunk_map_bits_t.  Two separate arrays are stored within each\n * chunk header in order to improve cache locality.\n */\nstruct arena_chunk_map_misc_s {\n\t/*\n\t * Linkage for run heaps.  There are two disjoint uses:\n\t *\n\t * 1) arena_t's runs_avail heaps.\n\t * 2) arena_run_t conceptually uses this linkage for in-use non-full\n\t *    runs, rather than directly embedding linkage.\n\t */\n\tphn(arena_chunk_map_misc_t)\t\tph_link;\n\n\tunion {\n\t\t/* Linkage for list of dirty runs. */\n\t\tarena_runs_dirty_link_t\t\trd;\n\n\t\t/* Profile counters, used for large object runs. */\n\t\tunion {\n\t\t\tvoid\t\t\t*prof_tctx_pun;\n\t\t\tprof_tctx_t\t\t*prof_tctx;\n\t\t};\n\n\t\t/* Small region run metadata. */\n\t\tarena_run_t\t\t\trun;\n\t};\n};\ntypedef ph(arena_chunk_map_misc_t) arena_run_heap_t;\n#endif /* JEMALLOC_ARENA_STRUCTS_A */\n\n#ifdef JEMALLOC_ARENA_STRUCTS_B\n/* Arena chunk header. */\nstruct arena_chunk_s {\n\t/*\n\t * A pointer to the arena that owns the chunk is stored within the node.\n\t * This field as a whole is used by chunks_rtree to support both\n\t * ivsalloc() and core-based debugging.\n\t */\n\textent_node_t\t\tnode;\n\n\t/*\n\t * Map of pages within chunk that keeps track of free/large/small.  The\n\t * first map_bias entries are omitted, since the chunk header does not\n\t * need to be tracked in the map.  This omission saves a header page\n\t * for common chunk sizes (e.g. 4 MiB).\n\t */\n\tarena_chunk_map_bits_t\tmap_bits[1]; /* Dynamically sized. */\n};\n\n/*\n * Read-only information associated with each element of arena_t's bins array\n * is stored separately, partly to reduce memory usage (only one copy, rather\n * than one per arena), but mainly to avoid false cacheline sharing.\n *\n * Each run has the following layout:\n *\n *               /--------------------\\\n *               | pad?               |\n *               |--------------------|\n *               | redzone            |\n *   reg0_offset | region 0           |\n *               | redzone            |\n *               |--------------------| \\\n *               | redzone            | |\n *               | region 1           |  > reg_interval\n *               | redzone            | /\n *               |--------------------|\n *               | ...                |\n *               | ...                |\n *               | ...                |\n *               |--------------------|\n *               | redzone            |\n *               | region nregs-1     |\n *               | redzone            |\n *               |--------------------|\n *               | alignment pad?     |\n *               \\--------------------/\n *\n * reg_interval has at least the same minimum alignment as reg_size; this\n * preserves the alignment constraint that sa2u() depends on.  Alignment pad is\n * either 0 or redzone_size; it is present only if needed to align reg0_offset.\n */\nstruct arena_bin_info_s {\n\t/* Size of regions in a run for this bin's size class. */\n\tsize_t\t\t\treg_size;\n\n\t/* Redzone size. */\n\tsize_t\t\t\tredzone_size;\n\n\t/* Interval between regions (reg_size + (redzone_size << 1)). */\n\tsize_t\t\t\treg_interval;\n\n\t/* Total size of a run for this bin's size class. */\n\tsize_t\t\t\trun_size;\n\n\t/* Total number of regions in a run for this bin's size class. */\n\tuint32_t\t\tnregs;\n\n\t/*\n\t * Metadata used to manipulate bitmaps for runs associated with this\n\t * bin.\n\t */\n\tbitmap_info_t\t\tbitmap_info;\n\n\t/* Offset of first region in a run for this bin's size class. */\n\tuint32_t\t\treg0_offset;\n};\n\nstruct arena_bin_s {\n\t/*\n\t * All operations on runcur, runs, and stats require that lock be\n\t * locked.  Run allocation/deallocation are protected by the arena lock,\n\t * which may be acquired while holding one or more bin locks, but not\n\t * vise versa.\n\t */\n\tmalloc_mutex_t\t\tlock;\n\n\t/*\n\t * Current run being used to service allocations of this bin's size\n\t * class.\n\t */\n\tarena_run_t\t\t*runcur;\n\n\t/*\n\t * Heap of non-full runs.  This heap is used when looking for an\n\t * existing run when runcur is no longer usable.  We choose the\n\t * non-full run that is lowest in memory; this policy tends to keep\n\t * objects packed well, and it can also help reduce the number of\n\t * almost-empty chunks.\n\t */\n\tarena_run_heap_t\truns;\n\n\t/* Bin statistics. */\n\tmalloc_bin_stats_t\tstats;\n};\n\nstruct arena_s {\n\t/* This arena's index within the arenas array. */\n\tunsigned\t\tind;\n\n\t/*\n\t * Number of threads currently assigned to this arena, synchronized via\n\t * atomic operations.  Each thread has two distinct assignments, one for\n\t * application-serving allocation, and the other for internal metadata\n\t * allocation.  Internal metadata must not be allocated from arenas\n\t * created via the arenas.extend mallctl, because the arena.<i>.reset\n\t * mallctl indiscriminately discards all allocations for the affected\n\t * arena.\n\t *\n\t *   0: Application allocation.\n\t *   1: Internal metadata allocation.\n\t */\n\tunsigned\t\tnthreads[2];\n\n\t/*\n\t * There are three classes of arena operations from a locking\n\t * perspective:\n\t * 1) Thread assignment (modifies nthreads) is synchronized via atomics.\n\t * 2) Bin-related operations are protected by bin locks.\n\t * 3) Chunk- and run-related operations are protected by this mutex.\n\t */\n\tmalloc_mutex_t\t\tlock;\n\n\tarena_stats_t\t\tstats;\n\t/*\n\t * List of tcaches for extant threads associated with this arena.\n\t * Stats from these are merged incrementally, and at exit if\n\t * opt_stats_print is enabled.\n\t */\n\tql_head(tcache_t)\ttcache_ql;\n\n\tuint64_t\t\tprof_accumbytes;\n\n\t/*\n\t * PRNG state for cache index randomization of large allocation base\n\t * pointers.\n\t */\n\tuint64_t\t\toffset_state;\n\n\tdss_prec_t\t\tdss_prec;\n\n\n\t/* Extant arena chunks. */\n\tql_head(extent_node_t)\tachunks;\n\n\t/*\n\t * In order to avoid rapid chunk allocation/deallocation when an arena\n\t * oscillates right on the cusp of needing a new chunk, cache the most\n\t * recently freed chunk.  The spare is left in the arena's chunk trees\n\t * until it is deleted.\n\t *\n\t * There is one spare chunk per arena, rather than one spare total, in\n\t * order to avoid interactions between multiple threads that could make\n\t * a single spare inadequate.\n\t */\n\tarena_chunk_t\t\t*spare;\n\n\t/* Minimum ratio (log base 2) of nactive:ndirty. */\n\tssize_t\t\t\tlg_dirty_mult;\n\n\t/* True if a thread is currently executing arena_purge_to_limit(). */\n\tbool\t\t\tpurging;\n\n\t/* Number of pages in active runs and huge regions. */\n\tsize_t\t\t\tnactive;\n\n\t/*\n\t * Current count of pages within unused runs that are potentially\n\t * dirty, and for which madvise(... MADV_DONTNEED) has not been called.\n\t * By tracking this, we can institute a limit on how much dirty unused\n\t * memory is mapped for each arena.\n\t */\n\tsize_t\t\t\tndirty;\n\n\t/*\n\t * Unused dirty memory this arena manages.  Dirty memory is conceptually\n\t * tracked as an arbitrarily interleaved LRU of dirty runs and cached\n\t * chunks, but the list linkage is actually semi-duplicated in order to\n\t * avoid extra arena_chunk_map_misc_t space overhead.\n\t *\n\t *   LRU-----------------------------------------------------------MRU\n\t *\n\t *        /-- arena ---\\\n\t *        |            |\n\t *        |            |\n\t *        |------------|                             /- chunk -\\\n\t *   ...->|chunks_cache|<--------------------------->|  /----\\ |<--...\n\t *        |------------|                             |  |node| |\n\t *        |            |                             |  |    | |\n\t *        |            |    /- run -\\    /- run -\\   |  |    | |\n\t *        |            |    |       |    |       |   |  |    | |\n\t *        |            |    |       |    |       |   |  |    | |\n\t *        |------------|    |-------|    |-------|   |  |----| |\n\t *   ...->|runs_dirty  |<-->|rd     |<-->|rd     |<---->|rd  |<----...\n\t *        |------------|    |-------|    |-------|   |  |----| |\n\t *        |            |    |       |    |       |   |  |    | |\n\t *        |            |    |       |    |       |   |  \\----/ |\n\t *        |            |    \\-------/    \\-------/   |         |\n\t *        |            |                             |         |\n\t *        |            |                             |         |\n\t *        \\------------/                             \\---------/\n\t */\n\tarena_runs_dirty_link_t\truns_dirty;\n\textent_node_t\t\tchunks_cache;\n\n\t/*\n\t * Approximate time in seconds from the creation of a set of unused\n\t * dirty pages until an equivalent set of unused dirty pages is purged\n\t * and/or reused.\n\t */\n\tssize_t\t\t\tdecay_time;\n\t/* decay_time / SMOOTHSTEP_NSTEPS. */\n\tnstime_t\t\tdecay_interval;\n\t/*\n\t * Time at which the current decay interval logically started.  We do\n\t * not actually advance to a new epoch until sometime after it starts\n\t * because of scheduling and computation delays, and it is even possible\n\t * to completely skip epochs.  In all cases, during epoch advancement we\n\t * merge all relevant activity into the most recently recorded epoch.\n\t */\n\tnstime_t\t\tdecay_epoch;\n\t/* decay_deadline randomness generator. */\n\tuint64_t\t\tdecay_jitter_state;\n\t/*\n\t * Deadline for current epoch.  This is the sum of decay_interval and\n\t * per epoch jitter which is a uniform random variable in\n\t * [0..decay_interval).  Epochs always advance by precise multiples of\n\t * decay_interval, but we randomize the deadline to reduce the\n\t * likelihood of arenas purging in lockstep.\n\t */\n\tnstime_t\t\tdecay_deadline;\n\t/*\n\t * Number of dirty pages at beginning of current epoch.  During epoch\n\t * advancement we use the delta between decay_ndirty and ndirty to\n\t * determine how many dirty pages, if any, were generated, and record\n\t * the result in decay_backlog.\n\t */\n\tsize_t\t\t\tdecay_ndirty;\n\t/*\n\t * Memoized result of arena_decay_backlog_npages_limit() corresponding\n\t * to the current contents of decay_backlog, i.e. the limit on how many\n\t * pages are allowed to exist for the decay epochs.\n\t */\n\tsize_t\t\t\tdecay_backlog_npages_limit;\n\t/*\n\t * Trailing log of how many unused dirty pages were generated during\n\t * each of the past SMOOTHSTEP_NSTEPS decay epochs, where the last\n\t * element is the most recent epoch.  Corresponding epoch times are\n\t * relative to decay_epoch.\n\t */\n\tsize_t\t\t\tdecay_backlog[SMOOTHSTEP_NSTEPS];\n\n\t/* Extant huge allocations. */\n\tql_head(extent_node_t)\thuge;\n\t/* Synchronizes all huge allocation/update/deallocation. */\n\tmalloc_mutex_t\t\thuge_mtx;\n\n\t/*\n\t * Trees of chunks that were previously allocated (trees differ only in\n\t * node ordering).  These are used when allocating chunks, in an attempt\n\t * to re-use address space.  Depending on function, different tree\n\t * orderings are needed, which is why there are two trees with the same\n\t * contents.\n\t */\n\textent_tree_t\t\tchunks_szad_cached;\n\textent_tree_t\t\tchunks_ad_cached;\n\textent_tree_t\t\tchunks_szad_retained;\n\textent_tree_t\t\tchunks_ad_retained;\n\n\tmalloc_mutex_t\t\tchunks_mtx;\n\t/* Cache of nodes that were allocated via base_alloc(). */\n\tql_head(extent_node_t)\tnode_cache;\n\tmalloc_mutex_t\t\tnode_cache_mtx;\n\n\t/* User-configurable chunk hook functions. */\n\tchunk_hooks_t\t\tchunk_hooks;\n\n\t/* bins is used to store trees of free regions. */\n\tarena_bin_t\t\tbins[NBINS];\n\n\t/*\n\t * Quantized address-ordered heaps of this arena's available runs.  The\n\t * heaps are used for first-best-fit run allocation.\n\t */\n\tarena_run_heap_t\truns_avail[1]; /* Dynamically sized. */\n};\n\n/* Used in conjunction with tsd for fast arena-related context lookup. */\nstruct arena_tdata_s {\n\tticker_t\t\tdecay_ticker;\n};\n#endif /* JEMALLOC_ARENA_STRUCTS_B */\n\n#endif /* JEMALLOC_H_STRUCTS */\n/******************************************************************************/\n#ifdef JEMALLOC_H_EXTERNS\n\nstatic const size_t\tlarge_pad =\n#ifdef JEMALLOC_CACHE_OBLIVIOUS\n    PAGE\n#else\n    0\n#endif\n    ;\n\nextern purge_mode_t\topt_purge;\nextern const char\t*purge_mode_names[];\nextern ssize_t\t\topt_lg_dirty_mult;\nextern ssize_t\t\topt_decay_time;\n\nextern arena_bin_info_t\tarena_bin_info[NBINS];\n\nextern size_t\t\tmap_bias; /* Number of arena chunk header pages. */\nextern size_t\t\tmap_misc_offset;\nextern size_t\t\tarena_maxrun; /* Max run size for arenas. */\nextern size_t\t\tlarge_maxclass; /* Max large size class. */\nextern size_t\t\trun_quantize_max; /* Max run_quantize_*() input. */\nextern unsigned\t\tnlclasses; /* Number of large size classes. */\nextern unsigned\t\tnhclasses; /* Number of huge size classes. */\n\n#ifdef JEMALLOC_JET\ntypedef size_t (run_quantize_t)(size_t);\nextern run_quantize_t *run_quantize_floor;\nextern run_quantize_t *run_quantize_ceil;\n#endif\nvoid\tarena_chunk_cache_maybe_insert(arena_t *arena, extent_node_t *node,\n    bool cache);\nvoid\tarena_chunk_cache_maybe_remove(arena_t *arena, extent_node_t *node,\n    bool cache);\nextent_node_t\t*arena_node_alloc(tsdn_t *tsdn, arena_t *arena);\nvoid\tarena_node_dalloc(tsdn_t *tsdn, arena_t *arena, extent_node_t *node);\nvoid\t*arena_chunk_alloc_huge(tsdn_t *tsdn, arena_t *arena, size_t usize,\n    size_t alignment, bool *zero);\nvoid\tarena_chunk_dalloc_huge(tsdn_t *tsdn, arena_t *arena, void *chunk,\n    size_t usize);\nvoid\tarena_chunk_ralloc_huge_similar(tsdn_t *tsdn, arena_t *arena,\n    void *chunk, size_t oldsize, size_t usize);\nvoid\tarena_chunk_ralloc_huge_shrink(tsdn_t *tsdn, arena_t *arena,\n    void *chunk, size_t oldsize, size_t usize);\nbool\tarena_chunk_ralloc_huge_expand(tsdn_t *tsdn, arena_t *arena,\n    void *chunk, size_t oldsize, size_t usize, bool *zero);\nssize_t\tarena_lg_dirty_mult_get(tsdn_t *tsdn, arena_t *arena);\nbool\tarena_lg_dirty_mult_set(tsdn_t *tsdn, arena_t *arena,\n    ssize_t lg_dirty_mult);\nssize_t\tarena_decay_time_get(tsdn_t *tsdn, arena_t *arena);\nbool\tarena_decay_time_set(tsdn_t *tsdn, arena_t *arena, ssize_t decay_time);\nvoid\tarena_purge(tsdn_t *tsdn, arena_t *arena, bool all);\nvoid\tarena_maybe_purge(tsdn_t *tsdn, arena_t *arena);\nvoid\tarena_reset(tsd_t *tsd, arena_t *arena);\nvoid\tarena_tcache_fill_small(tsdn_t *tsdn, arena_t *arena,\n    tcache_bin_t *tbin, szind_t binind, uint64_t prof_accumbytes);\nvoid\tarena_alloc_junk_small(void *ptr, arena_bin_info_t *bin_info,\n    bool zero);\n#ifdef JEMALLOC_JET\ntypedef void (arena_redzone_corruption_t)(void *, size_t, bool, size_t,\n    uint8_t);\nextern arena_redzone_corruption_t *arena_redzone_corruption;\ntypedef void (arena_dalloc_junk_small_t)(void *, arena_bin_info_t *);\nextern arena_dalloc_junk_small_t *arena_dalloc_junk_small;\n#else\nvoid\tarena_dalloc_junk_small(void *ptr, arena_bin_info_t *bin_info);\n#endif\nvoid\tarena_quarantine_junk_small(void *ptr, size_t usize);\nvoid\t*arena_malloc_large(tsdn_t *tsdn, arena_t *arena, szind_t ind,\n    bool zero);\nvoid\t*arena_malloc_hard(tsdn_t *tsdn, arena_t *arena, size_t size,\n    szind_t ind, bool zero);\nvoid\t*arena_palloc(tsdn_t *tsdn, arena_t *arena, size_t usize,\n    size_t alignment, bool zero, tcache_t *tcache);\nvoid\tarena_prof_promoted(tsdn_t *tsdn, const void *ptr, size_t size);\nvoid\tarena_dalloc_bin_junked_locked(tsdn_t *tsdn, arena_t *arena,\n    arena_chunk_t *chunk, void *ptr, arena_chunk_map_bits_t *bitselm);\nvoid\tarena_dalloc_bin(tsdn_t *tsdn, arena_t *arena, arena_chunk_t *chunk,\n    void *ptr, size_t pageind, arena_chunk_map_bits_t *bitselm);\nvoid\tarena_dalloc_small(tsdn_t *tsdn, arena_t *arena, arena_chunk_t *chunk,\n    void *ptr, size_t pageind);\n#ifdef JEMALLOC_JET\ntypedef void (arena_dalloc_junk_large_t)(void *, size_t);\nextern arena_dalloc_junk_large_t *arena_dalloc_junk_large;\n#else\nvoid\tarena_dalloc_junk_large(void *ptr, size_t usize);\n#endif\nvoid\tarena_dalloc_large_junked_locked(tsdn_t *tsdn, arena_t *arena,\n    arena_chunk_t *chunk, void *ptr);\nvoid\tarena_dalloc_large(tsdn_t *tsdn, arena_t *arena, arena_chunk_t *chunk,\n    void *ptr);\n#ifdef JEMALLOC_JET\ntypedef void (arena_ralloc_junk_large_t)(void *, size_t, size_t);\nextern arena_ralloc_junk_large_t *arena_ralloc_junk_large;\n#endif\nbool\tarena_ralloc_no_move(tsdn_t *tsdn, void *ptr, size_t oldsize,\n    size_t size, size_t extra, bool zero);\nvoid\t*arena_ralloc(tsd_t *tsd, arena_t *arena, void *ptr, size_t oldsize,\n    size_t size, size_t alignment, bool zero, tcache_t *tcache);\ndss_prec_t\tarena_dss_prec_get(tsdn_t *tsdn, arena_t *arena);\nbool\tarena_dss_prec_set(tsdn_t *tsdn, arena_t *arena, dss_prec_t dss_prec);\nssize_t\tarena_lg_dirty_mult_default_get(void);\nbool\tarena_lg_dirty_mult_default_set(ssize_t lg_dirty_mult);\nssize_t\tarena_decay_time_default_get(void);\nbool\tarena_decay_time_default_set(ssize_t decay_time);\nvoid\tarena_basic_stats_merge(tsdn_t *tsdn, arena_t *arena,\n    unsigned *nthreads, const char **dss, ssize_t *lg_dirty_mult,\n    ssize_t *decay_time, size_t *nactive, size_t *ndirty);\nvoid\tarena_stats_merge(tsdn_t *tsdn, arena_t *arena, unsigned *nthreads,\n    const char **dss, ssize_t *lg_dirty_mult, ssize_t *decay_time,\n    size_t *nactive, size_t *ndirty, arena_stats_t *astats,\n    malloc_bin_stats_t *bstats, malloc_large_stats_t *lstats,\n    malloc_huge_stats_t *hstats);\nunsigned\tarena_nthreads_get(arena_t *arena, bool internal);\nvoid\tarena_nthreads_inc(arena_t *arena, bool internal);\nvoid\tarena_nthreads_dec(arena_t *arena, bool internal);\narena_t\t*arena_new(tsdn_t *tsdn, unsigned ind);\nbool\tarena_boot(void);\nvoid\tarena_prefork0(tsdn_t *tsdn, arena_t *arena);\nvoid\tarena_prefork1(tsdn_t *tsdn, arena_t *arena);\nvoid\tarena_prefork2(tsdn_t *tsdn, arena_t *arena);\nvoid\tarena_prefork3(tsdn_t *tsdn, arena_t *arena);\nvoid\tarena_postfork_parent(tsdn_t *tsdn, arena_t *arena);\nvoid\tarena_postfork_child(tsdn_t *tsdn, arena_t *arena);\n\n#endif /* JEMALLOC_H_EXTERNS */\n/******************************************************************************/\n#ifdef JEMALLOC_H_INLINES\n\n#ifndef JEMALLOC_ENABLE_INLINE\narena_chunk_map_bits_t\t*arena_bitselm_get_mutable(arena_chunk_t *chunk,\n    size_t pageind);\nconst arena_chunk_map_bits_t\t*arena_bitselm_get_const(\n    const arena_chunk_t *chunk, size_t pageind);\narena_chunk_map_misc_t\t*arena_miscelm_get_mutable(arena_chunk_t *chunk,\n    size_t pageind);\nconst arena_chunk_map_misc_t\t*arena_miscelm_get_const(\n    const arena_chunk_t *chunk, size_t pageind);\nsize_t\tarena_miscelm_to_pageind(const arena_chunk_map_misc_t *miscelm);\nvoid\t*arena_miscelm_to_rpages(const arena_chunk_map_misc_t *miscelm);\narena_chunk_map_misc_t\t*arena_rd_to_miscelm(arena_runs_dirty_link_t *rd);\narena_chunk_map_misc_t\t*arena_run_to_miscelm(arena_run_t *run);\nsize_t\t*arena_mapbitsp_get_mutable(arena_chunk_t *chunk, size_t pageind);\nconst size_t\t*arena_mapbitsp_get_const(const arena_chunk_t *chunk,\n    size_t pageind);\nsize_t\tarena_mapbitsp_read(const size_t *mapbitsp);\nsize_t\tarena_mapbits_get(const arena_chunk_t *chunk, size_t pageind);\nsize_t\tarena_mapbits_size_decode(size_t mapbits);\nsize_t\tarena_mapbits_unallocated_size_get(const arena_chunk_t *chunk,\n    size_t pageind);\nsize_t\tarena_mapbits_large_size_get(const arena_chunk_t *chunk,\n    size_t pageind);\nsize_t\tarena_mapbits_small_runind_get(const arena_chunk_t *chunk,\n    size_t pageind);\nszind_t\tarena_mapbits_binind_get(const arena_chunk_t *chunk, size_t pageind);\nsize_t\tarena_mapbits_dirty_get(const arena_chunk_t *chunk, size_t pageind);\nsize_t\tarena_mapbits_unzeroed_get(const arena_chunk_t *chunk, size_t pageind);\nsize_t\tarena_mapbits_decommitted_get(const arena_chunk_t *chunk,\n    size_t pageind);\nsize_t\tarena_mapbits_large_get(const arena_chunk_t *chunk, size_t pageind);\nsize_t\tarena_mapbits_allocated_get(const arena_chunk_t *chunk, size_t pageind);\nvoid\tarena_mapbitsp_write(size_t *mapbitsp, size_t mapbits);\nsize_t\tarena_mapbits_size_encode(size_t size);\nvoid\tarena_mapbits_unallocated_set(arena_chunk_t *chunk, size_t pageind,\n    size_t size, size_t flags);\nvoid\tarena_mapbits_unallocated_size_set(arena_chunk_t *chunk, size_t pageind,\n    size_t size);\nvoid\tarena_mapbits_internal_set(arena_chunk_t *chunk, size_t pageind,\n    size_t flags);\nvoid\tarena_mapbits_large_set(arena_chunk_t *chunk, size_t pageind,\n    size_t size, size_t flags);\nvoid\tarena_mapbits_large_binind_set(arena_chunk_t *chunk, size_t pageind,\n    szind_t binind);\nvoid\tarena_mapbits_small_set(arena_chunk_t *chunk, size_t pageind,\n    size_t runind, szind_t binind, size_t flags);\nvoid\tarena_metadata_allocated_add(arena_t *arena, size_t size);\nvoid\tarena_metadata_allocated_sub(arena_t *arena, size_t size);\nsize_t\tarena_metadata_allocated_get(arena_t *arena);\nbool\tarena_prof_accum_impl(arena_t *arena, uint64_t accumbytes);\nbool\tarena_prof_accum_locked(arena_t *arena, uint64_t accumbytes);\nbool\tarena_prof_accum(tsdn_t *tsdn, arena_t *arena, uint64_t accumbytes);\nszind_t\tarena_ptr_small_binind_get(const void *ptr, size_t mapbits);\nszind_t\tarena_bin_index(arena_t *arena, arena_bin_t *bin);\nsize_t\tarena_run_regind(arena_run_t *run, arena_bin_info_t *bin_info,\n    const void *ptr);\nprof_tctx_t\t*arena_prof_tctx_get(tsdn_t *tsdn, const void *ptr);\nvoid\tarena_prof_tctx_set(tsdn_t *tsdn, const void *ptr, size_t usize,\n    prof_tctx_t *tctx);\nvoid\tarena_prof_tctx_reset(tsdn_t *tsdn, const void *ptr, size_t usize,\n    const void *old_ptr, prof_tctx_t *old_tctx);\nvoid\tarena_decay_ticks(tsdn_t *tsdn, arena_t *arena, unsigned nticks);\nvoid\tarena_decay_tick(tsdn_t *tsdn, arena_t *arena);\nvoid\t*arena_malloc(tsdn_t *tsdn, arena_t *arena, size_t size, szind_t ind,\n    bool zero, tcache_t *tcache, bool slow_path);\narena_t\t*arena_aalloc(const void *ptr);\nsize_t\tarena_salloc(tsdn_t *tsdn, const void *ptr, bool demote);\nvoid\tarena_dalloc(tsdn_t *tsdn, void *ptr, tcache_t *tcache, bool slow_path);\nvoid\tarena_sdalloc(tsdn_t *tsdn, void *ptr, size_t size, tcache_t *tcache,\n    bool slow_path);\n#endif\n\n#if (defined(JEMALLOC_ENABLE_INLINE) || defined(JEMALLOC_ARENA_C_))\n#  ifdef JEMALLOC_ARENA_INLINE_A\nJEMALLOC_ALWAYS_INLINE arena_chunk_map_bits_t *\narena_bitselm_get_mutable(arena_chunk_t *chunk, size_t pageind)\n{\n\n\tassert(pageind >= map_bias);\n\tassert(pageind < chunk_npages);\n\n\treturn (&chunk->map_bits[pageind-map_bias]);\n}\n\nJEMALLOC_ALWAYS_INLINE const arena_chunk_map_bits_t *\narena_bitselm_get_const(const arena_chunk_t *chunk, size_t pageind)\n{\n\n\treturn (arena_bitselm_get_mutable((arena_chunk_t *)chunk, pageind));\n}\n\nJEMALLOC_ALWAYS_INLINE arena_chunk_map_misc_t *\narena_miscelm_get_mutable(arena_chunk_t *chunk, size_t pageind)\n{\n\n\tassert(pageind >= map_bias);\n\tassert(pageind < chunk_npages);\n\n\treturn ((arena_chunk_map_misc_t *)((uintptr_t)chunk +\n\t    (uintptr_t)map_misc_offset) + pageind-map_bias);\n}\n\nJEMALLOC_ALWAYS_INLINE const arena_chunk_map_misc_t *\narena_miscelm_get_const(const arena_chunk_t *chunk, size_t pageind)\n{\n\n\treturn (arena_miscelm_get_mutable((arena_chunk_t *)chunk, pageind));\n}\n\nJEMALLOC_ALWAYS_INLINE size_t\narena_miscelm_to_pageind(const arena_chunk_map_misc_t *miscelm)\n{\n\tarena_chunk_t *chunk = (arena_chunk_t *)CHUNK_ADDR2BASE(miscelm);\n\tsize_t pageind = ((uintptr_t)miscelm - ((uintptr_t)chunk +\n\t    map_misc_offset)) / sizeof(arena_chunk_map_misc_t) + map_bias;\n\n\tassert(pageind >= map_bias);\n\tassert(pageind < chunk_npages);\n\n\treturn (pageind);\n}\n\nJEMALLOC_ALWAYS_INLINE void *\narena_miscelm_to_rpages(const arena_chunk_map_misc_t *miscelm)\n{\n\tarena_chunk_t *chunk = (arena_chunk_t *)CHUNK_ADDR2BASE(miscelm);\n\tsize_t pageind = arena_miscelm_to_pageind(miscelm);\n\n\treturn ((void *)((uintptr_t)chunk + (pageind << LG_PAGE)));\n}\n\nJEMALLOC_ALWAYS_INLINE arena_chunk_map_misc_t *\narena_rd_to_miscelm(arena_runs_dirty_link_t *rd)\n{\n\tarena_chunk_map_misc_t *miscelm = (arena_chunk_map_misc_t\n\t    *)((uintptr_t)rd - offsetof(arena_chunk_map_misc_t, rd));\n\n\tassert(arena_miscelm_to_pageind(miscelm) >= map_bias);\n\tassert(arena_miscelm_to_pageind(miscelm) < chunk_npages);\n\n\treturn (miscelm);\n}\n\nJEMALLOC_ALWAYS_INLINE arena_chunk_map_misc_t *\narena_run_to_miscelm(arena_run_t *run)\n{\n\tarena_chunk_map_misc_t *miscelm = (arena_chunk_map_misc_t\n\t    *)((uintptr_t)run - offsetof(arena_chunk_map_misc_t, run));\n\n\tassert(arena_miscelm_to_pageind(miscelm) >= map_bias);\n\tassert(arena_miscelm_to_pageind(miscelm) < chunk_npages);\n\n\treturn (miscelm);\n}\n\nJEMALLOC_ALWAYS_INLINE size_t *\narena_mapbitsp_get_mutable(arena_chunk_t *chunk, size_t pageind)\n{\n\n\treturn (&arena_bitselm_get_mutable(chunk, pageind)->bits);\n}\n\nJEMALLOC_ALWAYS_INLINE const size_t *\narena_mapbitsp_get_const(const arena_chunk_t *chunk, size_t pageind)\n{\n\n\treturn (arena_mapbitsp_get_mutable((arena_chunk_t *)chunk, pageind));\n}\n\nJEMALLOC_ALWAYS_INLINE size_t\narena_mapbitsp_read(const size_t *mapbitsp)\n{\n\n\treturn (*mapbitsp);\n}\n\nJEMALLOC_ALWAYS_INLINE size_t\narena_mapbits_get(const arena_chunk_t *chunk, size_t pageind)\n{\n\n\treturn (arena_mapbitsp_read(arena_mapbitsp_get_const(chunk, pageind)));\n}\n\nJEMALLOC_ALWAYS_INLINE size_t\narena_mapbits_size_decode(size_t mapbits)\n{\n\tsize_t size;\n\n#if CHUNK_MAP_SIZE_SHIFT > 0\n\tsize = (mapbits & CHUNK_MAP_SIZE_MASK) >> CHUNK_MAP_SIZE_SHIFT;\n#elif CHUNK_MAP_SIZE_SHIFT == 0\n\tsize = mapbits & CHUNK_MAP_SIZE_MASK;\n#else\n\tsize = (mapbits & CHUNK_MAP_SIZE_MASK) << -CHUNK_MAP_SIZE_SHIFT;\n#endif\n\n\treturn (size);\n}\n\nJEMALLOC_ALWAYS_INLINE size_t\narena_mapbits_unallocated_size_get(const arena_chunk_t *chunk, size_t pageind)\n{\n\tsize_t mapbits;\n\n\tmapbits = arena_mapbits_get(chunk, pageind);\n\tassert((mapbits & (CHUNK_MAP_LARGE|CHUNK_MAP_ALLOCATED)) == 0);\n\treturn (arena_mapbits_size_decode(mapbits));\n}\n\nJEMALLOC_ALWAYS_INLINE size_t\narena_mapbits_large_size_get(const arena_chunk_t *chunk, size_t pageind)\n{\n\tsize_t mapbits;\n\n\tmapbits = arena_mapbits_get(chunk, pageind);\n\tassert((mapbits & (CHUNK_MAP_LARGE|CHUNK_MAP_ALLOCATED)) ==\n\t    (CHUNK_MAP_LARGE|CHUNK_MAP_ALLOCATED));\n\treturn (arena_mapbits_size_decode(mapbits));\n}\n\nJEMALLOC_ALWAYS_INLINE size_t\narena_mapbits_small_runind_get(const arena_chunk_t *chunk, size_t pageind)\n{\n\tsize_t mapbits;\n\n\tmapbits = arena_mapbits_get(chunk, pageind);\n\tassert((mapbits & (CHUNK_MAP_LARGE|CHUNK_MAP_ALLOCATED)) ==\n\t    CHUNK_MAP_ALLOCATED);\n\treturn (mapbits >> CHUNK_MAP_RUNIND_SHIFT);\n}\n\nJEMALLOC_ALWAYS_INLINE szind_t\narena_mapbits_binind_get(const arena_chunk_t *chunk, size_t pageind)\n{\n\tsize_t mapbits;\n\tszind_t binind;\n\n\tmapbits = arena_mapbits_get(chunk, pageind);\n\tbinind = (mapbits & CHUNK_MAP_BININD_MASK) >> CHUNK_MAP_BININD_SHIFT;\n\tassert(binind < NBINS || binind == BININD_INVALID);\n\treturn (binind);\n}\n\nJEMALLOC_ALWAYS_INLINE size_t\narena_mapbits_dirty_get(const arena_chunk_t *chunk, size_t pageind)\n{\n\tsize_t mapbits;\n\n\tmapbits = arena_mapbits_get(chunk, pageind);\n\tassert((mapbits & CHUNK_MAP_DECOMMITTED) == 0 || (mapbits &\n\t    (CHUNK_MAP_DIRTY|CHUNK_MAP_UNZEROED)) == 0);\n\treturn (mapbits & CHUNK_MAP_DIRTY);\n}\n\nJEMALLOC_ALWAYS_INLINE size_t\narena_mapbits_unzeroed_get(const arena_chunk_t *chunk, size_t pageind)\n{\n\tsize_t mapbits;\n\n\tmapbits = arena_mapbits_get(chunk, pageind);\n\tassert((mapbits & CHUNK_MAP_DECOMMITTED) == 0 || (mapbits &\n\t    (CHUNK_MAP_DIRTY|CHUNK_MAP_UNZEROED)) == 0);\n\treturn (mapbits & CHUNK_MAP_UNZEROED);\n}\n\nJEMALLOC_ALWAYS_INLINE size_t\narena_mapbits_decommitted_get(const arena_chunk_t *chunk, size_t pageind)\n{\n\tsize_t mapbits;\n\n\tmapbits = arena_mapbits_get(chunk, pageind);\n\tassert((mapbits & CHUNK_MAP_DECOMMITTED) == 0 || (mapbits &\n\t    (CHUNK_MAP_DIRTY|CHUNK_MAP_UNZEROED)) == 0);\n\treturn (mapbits & CHUNK_MAP_DECOMMITTED);\n}\n\nJEMALLOC_ALWAYS_INLINE size_t\narena_mapbits_large_get(const arena_chunk_t *chunk, size_t pageind)\n{\n\tsize_t mapbits;\n\n\tmapbits = arena_mapbits_get(chunk, pageind);\n\treturn (mapbits & CHUNK_MAP_LARGE);\n}\n\nJEMALLOC_ALWAYS_INLINE size_t\narena_mapbits_allocated_get(const arena_chunk_t *chunk, size_t pageind)\n{\n\tsize_t mapbits;\n\n\tmapbits = arena_mapbits_get(chunk, pageind);\n\treturn (mapbits & CHUNK_MAP_ALLOCATED);\n}\n\nJEMALLOC_ALWAYS_INLINE void\narena_mapbitsp_write(size_t *mapbitsp, size_t mapbits)\n{\n\n\t*mapbitsp = mapbits;\n}\n\nJEMALLOC_ALWAYS_INLINE size_t\narena_mapbits_size_encode(size_t size)\n{\n\tsize_t mapbits;\n\n#if CHUNK_MAP_SIZE_SHIFT > 0\n\tmapbits = size << CHUNK_MAP_SIZE_SHIFT;\n#elif CHUNK_MAP_SIZE_SHIFT == 0\n\tmapbits = size;\n#else\n\tmapbits = size >> -CHUNK_MAP_SIZE_SHIFT;\n#endif\n\n\tassert((mapbits & ~CHUNK_MAP_SIZE_MASK) == 0);\n\treturn (mapbits);\n}\n\nJEMALLOC_ALWAYS_INLINE void\narena_mapbits_unallocated_set(arena_chunk_t *chunk, size_t pageind, size_t size,\n    size_t flags)\n{\n\tsize_t *mapbitsp = arena_mapbitsp_get_mutable(chunk, pageind);\n\n\tassert((size & PAGE_MASK) == 0);\n\tassert((flags & CHUNK_MAP_FLAGS_MASK) == flags);\n\tassert((flags & CHUNK_MAP_DECOMMITTED) == 0 || (flags &\n\t    (CHUNK_MAP_DIRTY|CHUNK_MAP_UNZEROED)) == 0);\n\tarena_mapbitsp_write(mapbitsp, arena_mapbits_size_encode(size) |\n\t    CHUNK_MAP_BININD_INVALID | flags);\n}\n\nJEMALLOC_ALWAYS_INLINE void\narena_mapbits_unallocated_size_set(arena_chunk_t *chunk, size_t pageind,\n    size_t size)\n{\n\tsize_t *mapbitsp = arena_mapbitsp_get_mutable(chunk, pageind);\n\tsize_t mapbits = arena_mapbitsp_read(mapbitsp);\n\n\tassert((size & PAGE_MASK) == 0);\n\tassert((mapbits & (CHUNK_MAP_LARGE|CHUNK_MAP_ALLOCATED)) == 0);\n\tarena_mapbitsp_write(mapbitsp, arena_mapbits_size_encode(size) |\n\t    (mapbits & ~CHUNK_MAP_SIZE_MASK));\n}\n\nJEMALLOC_ALWAYS_INLINE void\narena_mapbits_internal_set(arena_chunk_t *chunk, size_t pageind, size_t flags)\n{\n\tsize_t *mapbitsp = arena_mapbitsp_get_mutable(chunk, pageind);\n\n\tassert((flags & CHUNK_MAP_UNZEROED) == flags);\n\tarena_mapbitsp_write(mapbitsp, flags);\n}\n\nJEMALLOC_ALWAYS_INLINE void\narena_mapbits_large_set(arena_chunk_t *chunk, size_t pageind, size_t size,\n    size_t flags)\n{\n\tsize_t *mapbitsp = arena_mapbitsp_get_mutable(chunk, pageind);\n\n\tassert((size & PAGE_MASK) == 0);\n\tassert((flags & CHUNK_MAP_FLAGS_MASK) == flags);\n\tassert((flags & CHUNK_MAP_DECOMMITTED) == 0 || (flags &\n\t    (CHUNK_MAP_DIRTY|CHUNK_MAP_UNZEROED)) == 0);\n\tarena_mapbitsp_write(mapbitsp, arena_mapbits_size_encode(size) |\n\t    CHUNK_MAP_BININD_INVALID | flags | CHUNK_MAP_LARGE |\n\t    CHUNK_MAP_ALLOCATED);\n}\n\nJEMALLOC_ALWAYS_INLINE void\narena_mapbits_large_binind_set(arena_chunk_t *chunk, size_t pageind,\n    szind_t binind)\n{\n\tsize_t *mapbitsp = arena_mapbitsp_get_mutable(chunk, pageind);\n\tsize_t mapbits = arena_mapbitsp_read(mapbitsp);\n\n\tassert(binind <= BININD_INVALID);\n\tassert(arena_mapbits_large_size_get(chunk, pageind) == LARGE_MINCLASS +\n\t    large_pad);\n\tarena_mapbitsp_write(mapbitsp, (mapbits & ~CHUNK_MAP_BININD_MASK) |\n\t    (binind << CHUNK_MAP_BININD_SHIFT));\n}\n\nJEMALLOC_ALWAYS_INLINE void\narena_mapbits_small_set(arena_chunk_t *chunk, size_t pageind, size_t runind,\n    szind_t binind, size_t flags)\n{\n\tsize_t *mapbitsp = arena_mapbitsp_get_mutable(chunk, pageind);\n\n\tassert(binind < BININD_INVALID);\n\tassert(pageind - runind >= map_bias);\n\tassert((flags & CHUNK_MAP_UNZEROED) == flags);\n\tarena_mapbitsp_write(mapbitsp, (runind << CHUNK_MAP_RUNIND_SHIFT) |\n\t    (binind << CHUNK_MAP_BININD_SHIFT) | flags | CHUNK_MAP_ALLOCATED);\n}\n\nJEMALLOC_INLINE void\narena_metadata_allocated_add(arena_t *arena, size_t size)\n{\n\n\tatomic_add_z(&arena->stats.metadata_allocated, size);\n}\n\nJEMALLOC_INLINE void\narena_metadata_allocated_sub(arena_t *arena, size_t size)\n{\n\n\tatomic_sub_z(&arena->stats.metadata_allocated, size);\n}\n\nJEMALLOC_INLINE size_t\narena_metadata_allocated_get(arena_t *arena)\n{\n\n\treturn (atomic_read_z(&arena->stats.metadata_allocated));\n}\n\nJEMALLOC_INLINE bool\narena_prof_accum_impl(arena_t *arena, uint64_t accumbytes)\n{\n\n\tcassert(config_prof);\n\tassert(prof_interval != 0);\n\n\tarena->prof_accumbytes += accumbytes;\n\tif (arena->prof_accumbytes >= prof_interval) {\n\t\tarena->prof_accumbytes -= prof_interval;\n\t\treturn (true);\n\t}\n\treturn (false);\n}\n\nJEMALLOC_INLINE bool\narena_prof_accum_locked(arena_t *arena, uint64_t accumbytes)\n{\n\n\tcassert(config_prof);\n\n\tif (likely(prof_interval == 0))\n\t\treturn (false);\n\treturn (arena_prof_accum_impl(arena, accumbytes));\n}\n\nJEMALLOC_INLINE bool\narena_prof_accum(tsdn_t *tsdn, arena_t *arena, uint64_t accumbytes)\n{\n\n\tcassert(config_prof);\n\n\tif (likely(prof_interval == 0))\n\t\treturn (false);\n\n\t{\n\t\tbool ret;\n\n\t\tmalloc_mutex_lock(tsdn, &arena->lock);\n\t\tret = arena_prof_accum_impl(arena, accumbytes);\n\t\tmalloc_mutex_unlock(tsdn, &arena->lock);\n\t\treturn (ret);\n\t}\n}\n\nJEMALLOC_ALWAYS_INLINE szind_t\narena_ptr_small_binind_get(const void *ptr, size_t mapbits)\n{\n\tszind_t binind;\n\n\tbinind = (mapbits & CHUNK_MAP_BININD_MASK) >> CHUNK_MAP_BININD_SHIFT;\n\n\tif (config_debug) {\n\t\tarena_chunk_t *chunk;\n\t\tarena_t *arena;\n\t\tsize_t pageind;\n\t\tsize_t actual_mapbits;\n\t\tsize_t rpages_ind;\n\t\tconst arena_run_t *run;\n\t\tarena_bin_t *bin;\n\t\tszind_t run_binind, actual_binind;\n\t\tarena_bin_info_t *bin_info;\n\t\tconst arena_chunk_map_misc_t *miscelm;\n\t\tconst void *rpages;\n\n\t\tassert(binind != BININD_INVALID);\n\t\tassert(binind < NBINS);\n\t\tchunk = (arena_chunk_t *)CHUNK_ADDR2BASE(ptr);\n\t\tarena = extent_node_arena_get(&chunk->node);\n\t\tpageind = ((uintptr_t)ptr - (uintptr_t)chunk) >> LG_PAGE;\n\t\tactual_mapbits = arena_mapbits_get(chunk, pageind);\n\t\tassert(mapbits == actual_mapbits);\n\t\tassert(arena_mapbits_large_get(chunk, pageind) == 0);\n\t\tassert(arena_mapbits_allocated_get(chunk, pageind) != 0);\n\t\trpages_ind = pageind - arena_mapbits_small_runind_get(chunk,\n\t\t    pageind);\n\t\tmiscelm = arena_miscelm_get_const(chunk, rpages_ind);\n\t\trun = &miscelm->run;\n\t\trun_binind = run->binind;\n\t\tbin = &arena->bins[run_binind];\n\t\tactual_binind = (szind_t)(bin - arena->bins);\n\t\tassert(run_binind == actual_binind);\n\t\tbin_info = &arena_bin_info[actual_binind];\n\t\trpages = arena_miscelm_to_rpages(miscelm);\n\t\tassert(((uintptr_t)ptr - ((uintptr_t)rpages +\n\t\t    (uintptr_t)bin_info->reg0_offset)) % bin_info->reg_interval\n\t\t    == 0);\n\t}\n\n\treturn (binind);\n}\n#  endif /* JEMALLOC_ARENA_INLINE_A */\n\n#  ifdef JEMALLOC_ARENA_INLINE_B\nJEMALLOC_INLINE szind_t\narena_bin_index(arena_t *arena, arena_bin_t *bin)\n{\n\tszind_t binind = (szind_t)(bin - arena->bins);\n\tassert(binind < NBINS);\n\treturn (binind);\n}\n\nJEMALLOC_INLINE size_t\narena_run_regind(arena_run_t *run, arena_bin_info_t *bin_info, const void *ptr)\n{\n\tsize_t diff, interval, shift, regind;\n\tarena_chunk_map_misc_t *miscelm = arena_run_to_miscelm(run);\n\tvoid *rpages = arena_miscelm_to_rpages(miscelm);\n\n\t/*\n\t * Freeing a pointer lower than region zero can cause assertion\n\t * failure.\n\t */\n\tassert((uintptr_t)ptr >= (uintptr_t)rpages +\n\t    (uintptr_t)bin_info->reg0_offset);\n\n\t/*\n\t * Avoid doing division with a variable divisor if possible.  Using\n\t * actual division here can reduce allocator throughput by over 20%!\n\t */\n\tdiff = (size_t)((uintptr_t)ptr - (uintptr_t)rpages -\n\t    bin_info->reg0_offset);\n\n\t/* Rescale (factor powers of 2 out of the numerator and denominator). */\n\tinterval = bin_info->reg_interval;\n\tshift = ffs_zu(interval) - 1;\n\tdiff >>= shift;\n\tinterval >>= shift;\n\n\tif (interval == 1) {\n\t\t/* The divisor was a power of 2. */\n\t\tregind = diff;\n\t} else {\n\t\t/*\n\t\t * To divide by a number D that is not a power of two we\n\t\t * multiply by (2^21 / D) and then right shift by 21 positions.\n\t\t *\n\t\t *   X / D\n\t\t *\n\t\t * becomes\n\t\t *\n\t\t *   (X * interval_invs[D - 3]) >> SIZE_INV_SHIFT\n\t\t *\n\t\t * We can omit the first three elements, because we never\n\t\t * divide by 0, and 1 and 2 are both powers of two, which are\n\t\t * handled above.\n\t\t */\n#define\tSIZE_INV_SHIFT\t((sizeof(size_t) << 3) - LG_RUN_MAXREGS)\n#define\tSIZE_INV(s)\t(((ZU(1) << SIZE_INV_SHIFT) / (s)) + 1)\n\t\tstatic const size_t interval_invs[] = {\n\t\t    SIZE_INV(3),\n\t\t    SIZE_INV(4), SIZE_INV(5), SIZE_INV(6), SIZE_INV(7),\n\t\t    SIZE_INV(8), SIZE_INV(9), SIZE_INV(10), SIZE_INV(11),\n\t\t    SIZE_INV(12), SIZE_INV(13), SIZE_INV(14), SIZE_INV(15),\n\t\t    SIZE_INV(16), SIZE_INV(17), SIZE_INV(18), SIZE_INV(19),\n\t\t    SIZE_INV(20), SIZE_INV(21), SIZE_INV(22), SIZE_INV(23),\n\t\t    SIZE_INV(24), SIZE_INV(25), SIZE_INV(26), SIZE_INV(27),\n\t\t    SIZE_INV(28), SIZE_INV(29), SIZE_INV(30), SIZE_INV(31)\n\t\t};\n\n\t\tif (likely(interval <= ((sizeof(interval_invs) / sizeof(size_t))\n\t\t    + 2))) {\n\t\t\tregind = (diff * interval_invs[interval - 3]) >>\n\t\t\t    SIZE_INV_SHIFT;\n\t\t} else\n\t\t\tregind = diff / interval;\n#undef SIZE_INV\n#undef SIZE_INV_SHIFT\n\t}\n\tassert(diff == regind * interval);\n\tassert(regind < bin_info->nregs);\n\n\treturn (regind);\n}\n\nJEMALLOC_INLINE prof_tctx_t *\narena_prof_tctx_get(tsdn_t *tsdn, const void *ptr)\n{\n\tprof_tctx_t *ret;\n\tarena_chunk_t *chunk;\n\n\tcassert(config_prof);\n\tassert(ptr != NULL);\n\n\tchunk = (arena_chunk_t *)CHUNK_ADDR2BASE(ptr);\n\tif (likely(chunk != ptr)) {\n\t\tsize_t pageind = ((uintptr_t)ptr - (uintptr_t)chunk) >> LG_PAGE;\n\t\tsize_t mapbits = arena_mapbits_get(chunk, pageind);\n\t\tassert((mapbits & CHUNK_MAP_ALLOCATED) != 0);\n\t\tif (likely((mapbits & CHUNK_MAP_LARGE) == 0))\n\t\t\tret = (prof_tctx_t *)(uintptr_t)1U;\n\t\telse {\n\t\t\tarena_chunk_map_misc_t *elm =\n\t\t\t    arena_miscelm_get_mutable(chunk, pageind);\n\t\t\tret = atomic_read_p(&elm->prof_tctx_pun);\n\t\t}\n\t} else\n\t\tret = huge_prof_tctx_get(tsdn, ptr);\n\n\treturn (ret);\n}\n\nJEMALLOC_INLINE void\narena_prof_tctx_set(tsdn_t *tsdn, const void *ptr, size_t usize,\n    prof_tctx_t *tctx)\n{\n\tarena_chunk_t *chunk;\n\n\tcassert(config_prof);\n\tassert(ptr != NULL);\n\n\tchunk = (arena_chunk_t *)CHUNK_ADDR2BASE(ptr);\n\tif (likely(chunk != ptr)) {\n\t\tsize_t pageind = ((uintptr_t)ptr - (uintptr_t)chunk) >> LG_PAGE;\n\n\t\tassert(arena_mapbits_allocated_get(chunk, pageind) != 0);\n\n\t\tif (unlikely(usize > SMALL_MAXCLASS || (uintptr_t)tctx >\n\t\t    (uintptr_t)1U)) {\n\t\t\tarena_chunk_map_misc_t *elm;\n\n\t\t\tassert(arena_mapbits_large_get(chunk, pageind) != 0);\n\n\t\t\telm = arena_miscelm_get_mutable(chunk, pageind);\n\t\t\tatomic_write_p(&elm->prof_tctx_pun, tctx);\n\t\t} else {\n\t\t\t/*\n\t\t\t * tctx must always be initialized for large runs.\n\t\t\t * Assert that the surrounding conditional logic is\n\t\t\t * equivalent to checking whether ptr refers to a large\n\t\t\t * run.\n\t\t\t */\n\t\t\tassert(arena_mapbits_large_get(chunk, pageind) == 0);\n\t\t}\n\t} else\n\t\thuge_prof_tctx_set(tsdn, ptr, tctx);\n}\n\nJEMALLOC_INLINE void\narena_prof_tctx_reset(tsdn_t *tsdn, const void *ptr, size_t usize,\n    const void *old_ptr, prof_tctx_t *old_tctx)\n{\n\n\tcassert(config_prof);\n\tassert(ptr != NULL);\n\n\tif (unlikely(usize > SMALL_MAXCLASS || (ptr == old_ptr &&\n\t    (uintptr_t)old_tctx > (uintptr_t)1U))) {\n\t\tarena_chunk_t *chunk = (arena_chunk_t *)CHUNK_ADDR2BASE(ptr);\n\t\tif (likely(chunk != ptr)) {\n\t\t\tsize_t pageind;\n\t\t\tarena_chunk_map_misc_t *elm;\n\n\t\t\tpageind = ((uintptr_t)ptr - (uintptr_t)chunk) >>\n\t\t\t    LG_PAGE;\n\t\t\tassert(arena_mapbits_allocated_get(chunk, pageind) !=\n\t\t\t    0);\n\t\t\tassert(arena_mapbits_large_get(chunk, pageind) != 0);\n\n\t\t\telm = arena_miscelm_get_mutable(chunk, pageind);\n\t\t\tatomic_write_p(&elm->prof_tctx_pun,\n\t\t\t    (prof_tctx_t *)(uintptr_t)1U);\n\t\t} else\n\t\t\thuge_prof_tctx_reset(tsdn, ptr);\n\t}\n}\n\nJEMALLOC_ALWAYS_INLINE void\narena_decay_ticks(tsdn_t *tsdn, arena_t *arena, unsigned nticks)\n{\n\ttsd_t *tsd;\n\tticker_t *decay_ticker;\n\n\tif (unlikely(tsdn_null(tsdn)))\n\t\treturn;\n\ttsd = tsdn_tsd(tsdn);\n\tdecay_ticker = decay_ticker_get(tsd, arena->ind);\n\tif (unlikely(decay_ticker == NULL))\n\t\treturn;\n\tif (unlikely(ticker_ticks(decay_ticker, nticks)))\n\t\tarena_purge(tsdn, arena, false);\n}\n\nJEMALLOC_ALWAYS_INLINE void\narena_decay_tick(tsdn_t *tsdn, arena_t *arena)\n{\n\n\tarena_decay_ticks(tsdn, arena, 1);\n}\n\nJEMALLOC_ALWAYS_INLINE void *\narena_malloc(tsdn_t *tsdn, arena_t *arena, size_t size, szind_t ind, bool zero,\n    tcache_t *tcache, bool slow_path)\n{\n\n\tassert(!tsdn_null(tsdn) || tcache == NULL);\n\tassert(size != 0);\n\n\tif (likely(tcache != NULL)) {\n\t\tif (likely(size <= SMALL_MAXCLASS)) {\n\t\t\treturn (tcache_alloc_small(tsdn_tsd(tsdn), arena,\n\t\t\t    tcache, size, ind, zero, slow_path));\n\t\t}\n\t\tif (likely(size <= tcache_maxclass)) {\n\t\t\treturn (tcache_alloc_large(tsdn_tsd(tsdn), arena,\n\t\t\t    tcache, size, ind, zero, slow_path));\n\t\t}\n\t\t/* (size > tcache_maxclass) case falls through. */\n\t\tassert(size > tcache_maxclass);\n\t}\n\n\treturn (arena_malloc_hard(tsdn, arena, size, ind, zero));\n}\n\nJEMALLOC_ALWAYS_INLINE arena_t *\narena_aalloc(const void *ptr)\n{\n\tarena_chunk_t *chunk;\n\n\tchunk = (arena_chunk_t *)CHUNK_ADDR2BASE(ptr);\n\tif (likely(chunk != ptr))\n\t\treturn (extent_node_arena_get(&chunk->node));\n\telse\n\t\treturn (huge_aalloc(ptr));\n}\n\n/* Return the size of the allocation pointed to by ptr. */\nJEMALLOC_ALWAYS_INLINE size_t\narena_salloc(tsdn_t *tsdn, const void *ptr, bool demote)\n{\n\tsize_t ret;\n\tarena_chunk_t *chunk;\n\tsize_t pageind;\n\tszind_t binind;\n\n\tassert(ptr != NULL);\n\n\tchunk = (arena_chunk_t *)CHUNK_ADDR2BASE(ptr);\n\tif (likely(chunk != ptr)) {\n\t\tpageind = ((uintptr_t)ptr - (uintptr_t)chunk) >> LG_PAGE;\n\t\tassert(arena_mapbits_allocated_get(chunk, pageind) != 0);\n\t\tbinind = arena_mapbits_binind_get(chunk, pageind);\n\t\tif (unlikely(binind == BININD_INVALID || (config_prof && !demote\n\t\t    && arena_mapbits_large_get(chunk, pageind) != 0))) {\n\t\t\t/*\n\t\t\t * Large allocation.  In the common case (demote), and\n\t\t\t * as this is an inline function, most callers will only\n\t\t\t * end up looking at binind to determine that ptr is a\n\t\t\t * small allocation.\n\t\t\t */\n\t\t\tassert(config_cache_oblivious || ((uintptr_t)ptr &\n\t\t\t    PAGE_MASK) == 0);\n\t\t\tret = arena_mapbits_large_size_get(chunk, pageind) -\n\t\t\t    large_pad;\n\t\t\tassert(ret != 0);\n\t\t\tassert(pageind + ((ret+large_pad)>>LG_PAGE) <=\n\t\t\t    chunk_npages);\n\t\t\tassert(arena_mapbits_dirty_get(chunk, pageind) ==\n\t\t\t    arena_mapbits_dirty_get(chunk,\n\t\t\t    pageind+((ret+large_pad)>>LG_PAGE)-1));\n\t\t} else {\n\t\t\t/*\n\t\t\t * Small allocation (possibly promoted to a large\n\t\t\t * object).\n\t\t\t */\n\t\t\tassert(arena_mapbits_large_get(chunk, pageind) != 0 ||\n\t\t\t    arena_ptr_small_binind_get(ptr,\n\t\t\t    arena_mapbits_get(chunk, pageind)) == binind);\n\t\t\tret = index2size(binind);\n\t\t}\n\t} else\n\t\tret = huge_salloc(tsdn, ptr);\n\n\treturn (ret);\n}\n\nJEMALLOC_ALWAYS_INLINE void\narena_dalloc(tsdn_t *tsdn, void *ptr, tcache_t *tcache, bool slow_path)\n{\n\tarena_chunk_t *chunk;\n\tsize_t pageind, mapbits;\n\n\tassert(!tsdn_null(tsdn) || tcache == NULL);\n\tassert(ptr != NULL);\n\n\tchunk = (arena_chunk_t *)CHUNK_ADDR2BASE(ptr);\n\tif (likely(chunk != ptr)) {\n\t\tpageind = ((uintptr_t)ptr - (uintptr_t)chunk) >> LG_PAGE;\n\t\tmapbits = arena_mapbits_get(chunk, pageind);\n\t\tassert(arena_mapbits_allocated_get(chunk, pageind) != 0);\n\t\tif (likely((mapbits & CHUNK_MAP_LARGE) == 0)) {\n\t\t\t/* Small allocation. */\n\t\t\tif (likely(tcache != NULL)) {\n\t\t\t\tszind_t binind = arena_ptr_small_binind_get(ptr,\n\t\t\t\t    mapbits);\n\t\t\t\ttcache_dalloc_small(tsdn_tsd(tsdn), tcache, ptr,\n\t\t\t\t    binind, slow_path);\n\t\t\t} else {\n\t\t\t\tarena_dalloc_small(tsdn,\n\t\t\t\t    extent_node_arena_get(&chunk->node), chunk,\n\t\t\t\t    ptr, pageind);\n\t\t\t}\n\t\t} else {\n\t\t\tsize_t size = arena_mapbits_large_size_get(chunk,\n\t\t\t    pageind);\n\n\t\t\tassert(config_cache_oblivious || ((uintptr_t)ptr &\n\t\t\t    PAGE_MASK) == 0);\n\n\t\t\tif (likely(tcache != NULL) && size - large_pad <=\n\t\t\t    tcache_maxclass) {\n\t\t\t\ttcache_dalloc_large(tsdn_tsd(tsdn), tcache, ptr,\n\t\t\t\t    size - large_pad, slow_path);\n\t\t\t} else {\n\t\t\t\tarena_dalloc_large(tsdn,\n\t\t\t\t    extent_node_arena_get(&chunk->node), chunk,\n\t\t\t\t    ptr);\n\t\t\t}\n\t\t}\n\t} else\n\t\thuge_dalloc(tsdn, ptr);\n}\n\nJEMALLOC_ALWAYS_INLINE void\narena_sdalloc(tsdn_t *tsdn, void *ptr, size_t size, tcache_t *tcache,\n    bool slow_path)\n{\n\tarena_chunk_t *chunk;\n\n\tassert(!tsdn_null(tsdn) || tcache == NULL);\n\n\tchunk = (arena_chunk_t *)CHUNK_ADDR2BASE(ptr);\n\tif (likely(chunk != ptr)) {\n\t\tif (config_prof && opt_prof) {\n\t\t\tsize_t pageind = ((uintptr_t)ptr - (uintptr_t)chunk) >>\n\t\t\t    LG_PAGE;\n\t\t\tassert(arena_mapbits_allocated_get(chunk, pageind) !=\n\t\t\t    0);\n\t\t\tif (arena_mapbits_large_get(chunk, pageind) != 0) {\n\t\t\t\t/*\n\t\t\t\t * Make sure to use promoted size, not request\n\t\t\t\t * size.\n\t\t\t\t */\n\t\t\t\tsize = arena_mapbits_large_size_get(chunk,\n\t\t\t\t    pageind) - large_pad;\n\t\t\t}\n\t\t}\n\t\tassert(s2u(size) == s2u(arena_salloc(tsdn, ptr, false)));\n\n\t\tif (likely(size <= SMALL_MAXCLASS)) {\n\t\t\t/* Small allocation. */\n\t\t\tif (likely(tcache != NULL)) {\n\t\t\t\tszind_t binind = size2index(size);\n\t\t\t\ttcache_dalloc_small(tsdn_tsd(tsdn), tcache, ptr,\n\t\t\t\t    binind, slow_path);\n\t\t\t} else {\n\t\t\t\tsize_t pageind = ((uintptr_t)ptr -\n\t\t\t\t    (uintptr_t)chunk) >> LG_PAGE;\n\t\t\t\tarena_dalloc_small(tsdn,\n\t\t\t\t    extent_node_arena_get(&chunk->node), chunk,\n\t\t\t\t    ptr, pageind);\n\t\t\t}\n\t\t} else {\n\t\t\tassert(config_cache_oblivious || ((uintptr_t)ptr &\n\t\t\t    PAGE_MASK) == 0);\n\n\t\t\tif (likely(tcache != NULL) && size <= tcache_maxclass) {\n\t\t\t\ttcache_dalloc_large(tsdn_tsd(tsdn), tcache, ptr,\n\t\t\t\t    size, slow_path);\n\t\t\t} else {\n\t\t\t\tarena_dalloc_large(tsdn,\n\t\t\t\t    extent_node_arena_get(&chunk->node), chunk,\n\t\t\t\t    ptr);\n\t\t\t}\n\t\t}\n\t} else\n\t\thuge_dalloc(tsdn, ptr);\n}\n#  endif /* JEMALLOC_ARENA_INLINE_B */\n#endif\n\n#endif /* JEMALLOC_H_INLINES */\n/******************************************************************************/\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/deps/jemalloc/include/jemalloc/internal/assert.h",
    "content": "/*\n * Define a custom assert() in order to reduce the chances of deadlock during\n * assertion failure.\n */\n#ifndef assert\n#define\tassert(e) do {\t\t\t\t\t\t\t\\\n\tif (unlikely(config_debug && !(e))) {\t\t\t\t\\\n\t\tmalloc_printf(\t\t\t\t\t\t\\\n\t\t    \"<jemalloc>: %s:%d: Failed assertion: \\\"%s\\\"\\n\",\t\\\n\t\t    __FILE__, __LINE__, #e);\t\t\t\t\\\n\t\tabort();\t\t\t\t\t\t\\\n\t}\t\t\t\t\t\t\t\t\\\n} while (0)\n#endif\n\n#ifndef not_reached\n#define\tnot_reached() do {\t\t\t\t\t\t\\\n\tif (config_debug) {\t\t\t\t\t\t\\\n\t\tmalloc_printf(\t\t\t\t\t\t\\\n\t\t    \"<jemalloc>: %s:%d: Unreachable code reached\\n\",\t\\\n\t\t    __FILE__, __LINE__);\t\t\t\t\\\n\t\tabort();\t\t\t\t\t\t\\\n\t}\t\t\t\t\t\t\t\t\\\n\tunreachable();\t\t\t\t\t\t\t\\\n} while (0)\n#endif\n\n#ifndef not_implemented\n#define\tnot_implemented() do {\t\t\t\t\t\t\\\n\tif (config_debug) {\t\t\t\t\t\t\\\n\t\tmalloc_printf(\"<jemalloc>: %s:%d: Not implemented\\n\",\t\\\n\t\t    __FILE__, __LINE__);\t\t\t\t\\\n\t\tabort();\t\t\t\t\t\t\\\n\t}\t\t\t\t\t\t\t\t\\\n} while (0)\n#endif\n\n#ifndef assert_not_implemented\n#define\tassert_not_implemented(e) do {\t\t\t\t\t\\\n\tif (unlikely(config_debug && !(e)))\t\t\t\t\\\n\t\tnot_implemented();\t\t\t\t\t\\\n} while (0)\n#endif\n\n\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/deps/jemalloc/include/jemalloc/internal/atomic.h",
    "content": "/******************************************************************************/\n#ifdef JEMALLOC_H_TYPES\n\n#endif /* JEMALLOC_H_TYPES */\n/******************************************************************************/\n#ifdef JEMALLOC_H_STRUCTS\n\n#endif /* JEMALLOC_H_STRUCTS */\n/******************************************************************************/\n#ifdef JEMALLOC_H_EXTERNS\n\n#define\tatomic_read_uint64(p)\tatomic_add_uint64(p, 0)\n#define\tatomic_read_uint32(p)\tatomic_add_uint32(p, 0)\n#define\tatomic_read_p(p)\tatomic_add_p(p, NULL)\n#define\tatomic_read_z(p)\tatomic_add_z(p, 0)\n#define\tatomic_read_u(p)\tatomic_add_u(p, 0)\n\n#endif /* JEMALLOC_H_EXTERNS */\n/******************************************************************************/\n#ifdef JEMALLOC_H_INLINES\n\n/*\n * All arithmetic functions return the arithmetic result of the atomic\n * operation.  Some atomic operation APIs return the value prior to mutation, in\n * which case the following functions must redundantly compute the result so\n * that it can be returned.  These functions are normally inlined, so the extra\n * operations can be optimized away if the return values aren't used by the\n * callers.\n *\n *   <t> atomic_read_<t>(<t> *p) { return (*p); }\n *   <t> atomic_add_<t>(<t> *p, <t> x) { return (*p += x); }\n *   <t> atomic_sub_<t>(<t> *p, <t> x) { return (*p -= x); }\n *   bool atomic_cas_<t>(<t> *p, <t> c, <t> s)\n *   {\n *     if (*p != c)\n *       return (true);\n *     *p = s;\n *     return (false);\n *   }\n *   void atomic_write_<t>(<t> *p, <t> x) { *p = x; }\n */\n\n#ifndef JEMALLOC_ENABLE_INLINE\nuint64_t\tatomic_add_uint64(uint64_t *p, uint64_t x);\nuint64_t\tatomic_sub_uint64(uint64_t *p, uint64_t x);\nbool\tatomic_cas_uint64(uint64_t *p, uint64_t c, uint64_t s);\nvoid\tatomic_write_uint64(uint64_t *p, uint64_t x);\nuint32_t\tatomic_add_uint32(uint32_t *p, uint32_t x);\nuint32_t\tatomic_sub_uint32(uint32_t *p, uint32_t x);\nbool\tatomic_cas_uint32(uint32_t *p, uint32_t c, uint32_t s);\nvoid\tatomic_write_uint32(uint32_t *p, uint32_t x);\nvoid\t*atomic_add_p(void **p, void *x);\nvoid\t*atomic_sub_p(void **p, void *x);\nbool\tatomic_cas_p(void **p, void *c, void *s);\nvoid\tatomic_write_p(void **p, const void *x);\nsize_t\tatomic_add_z(size_t *p, size_t x);\nsize_t\tatomic_sub_z(size_t *p, size_t x);\nbool\tatomic_cas_z(size_t *p, size_t c, size_t s);\nvoid\tatomic_write_z(size_t *p, size_t x);\nunsigned\tatomic_add_u(unsigned *p, unsigned x);\nunsigned\tatomic_sub_u(unsigned *p, unsigned x);\nbool\tatomic_cas_u(unsigned *p, unsigned c, unsigned s);\nvoid\tatomic_write_u(unsigned *p, unsigned x);\n#endif\n\n#if (defined(JEMALLOC_ENABLE_INLINE) || defined(JEMALLOC_ATOMIC_C_))\n/******************************************************************************/\n/* 64-bit operations. */\n#if (LG_SIZEOF_PTR == 3 || LG_SIZEOF_INT == 3)\n#  if (defined(__amd64__) || defined(__x86_64__))\nJEMALLOC_INLINE uint64_t\natomic_add_uint64(uint64_t *p, uint64_t x)\n{\n\tuint64_t t = x;\n\n\tasm volatile (\n\t    \"lock; xaddq %0, %1;\"\n\t    : \"+r\" (t), \"=m\" (*p) /* Outputs. */\n\t    : \"m\" (*p) /* Inputs. */\n\t    );\n\n\treturn (t + x);\n}\n\nJEMALLOC_INLINE uint64_t\natomic_sub_uint64(uint64_t *p, uint64_t x)\n{\n\tuint64_t t;\n\n\tx = (uint64_t)(-(int64_t)x);\n\tt = x;\n\tasm volatile (\n\t    \"lock; xaddq %0, %1;\"\n\t    : \"+r\" (t), \"=m\" (*p) /* Outputs. */\n\t    : \"m\" (*p) /* Inputs. */\n\t    );\n\n\treturn (t + x);\n}\n\nJEMALLOC_INLINE bool\natomic_cas_uint64(uint64_t *p, uint64_t c, uint64_t s)\n{\n\tuint8_t success;\n\n\tasm volatile (\n\t    \"lock; cmpxchgq %4, %0;\"\n\t    \"sete %1;\"\n\t    : \"=m\" (*p), \"=a\" (success) /* Outputs. */\n\t    : \"m\" (*p), \"a\" (c), \"r\" (s) /* Inputs. */\n\t    : \"memory\" /* Clobbers. */\n\t    );\n\n\treturn (!(bool)success);\n}\n\nJEMALLOC_INLINE void\natomic_write_uint64(uint64_t *p, uint64_t x)\n{\n\n\tasm volatile (\n\t    \"xchgq %1, %0;\" /* Lock is implied by xchgq. */\n\t    : \"=m\" (*p), \"+r\" (x) /* Outputs. */\n\t    : \"m\" (*p) /* Inputs. */\n\t    : \"memory\" /* Clobbers. */\n\t    );\n}\n#  elif (defined(JEMALLOC_C11ATOMICS))\nJEMALLOC_INLINE uint64_t\natomic_add_uint64(uint64_t *p, uint64_t x)\n{\n\tvolatile atomic_uint_least64_t *a = (volatile atomic_uint_least64_t *)p;\n\treturn (atomic_fetch_add(a, x) + x);\n}\n\nJEMALLOC_INLINE uint64_t\natomic_sub_uint64(uint64_t *p, uint64_t x)\n{\n\tvolatile atomic_uint_least64_t *a = (volatile atomic_uint_least64_t *)p;\n\treturn (atomic_fetch_sub(a, x) - x);\n}\n\nJEMALLOC_INLINE bool\natomic_cas_uint64(uint64_t *p, uint64_t c, uint64_t s)\n{\n\tvolatile atomic_uint_least64_t *a = (volatile atomic_uint_least64_t *)p;\n\treturn (!atomic_compare_exchange_strong(a, &c, s));\n}\n\nJEMALLOC_INLINE void\natomic_write_uint64(uint64_t *p, uint64_t x)\n{\n\tvolatile atomic_uint_least64_t *a = (volatile atomic_uint_least64_t *)p;\n\tatomic_store(a, x);\n}\n#  elif (defined(JEMALLOC_ATOMIC9))\nJEMALLOC_INLINE uint64_t\natomic_add_uint64(uint64_t *p, uint64_t x)\n{\n\n\t/*\n\t * atomic_fetchadd_64() doesn't exist, but we only ever use this\n\t * function on LP64 systems, so atomic_fetchadd_long() will do.\n\t */\n\tassert(sizeof(uint64_t) == sizeof(unsigned long));\n\n\treturn (atomic_fetchadd_long(p, (unsigned long)x) + x);\n}\n\nJEMALLOC_INLINE uint64_t\natomic_sub_uint64(uint64_t *p, uint64_t x)\n{\n\n\tassert(sizeof(uint64_t) == sizeof(unsigned long));\n\n\treturn (atomic_fetchadd_long(p, (unsigned long)(-(long)x)) - x);\n}\n\nJEMALLOC_INLINE bool\natomic_cas_uint64(uint64_t *p, uint64_t c, uint64_t s)\n{\n\n\tassert(sizeof(uint64_t) == sizeof(unsigned long));\n\n\treturn (!atomic_cmpset_long(p, (unsigned long)c, (unsigned long)s));\n}\n\nJEMALLOC_INLINE void\natomic_write_uint64(uint64_t *p, uint64_t x)\n{\n\n\tassert(sizeof(uint64_t) == sizeof(unsigned long));\n\n\tatomic_store_rel_long(p, x);\n}\n#  elif (defined(JEMALLOC_OSATOMIC))\nJEMALLOC_INLINE uint64_t\natomic_add_uint64(uint64_t *p, uint64_t x)\n{\n\n\treturn (OSAtomicAdd64((int64_t)x, (int64_t *)p));\n}\n\nJEMALLOC_INLINE uint64_t\natomic_sub_uint64(uint64_t *p, uint64_t x)\n{\n\n\treturn (OSAtomicAdd64(-((int64_t)x), (int64_t *)p));\n}\n\nJEMALLOC_INLINE bool\natomic_cas_uint64(uint64_t *p, uint64_t c, uint64_t s)\n{\n\n\treturn (!OSAtomicCompareAndSwap64(c, s, (int64_t *)p));\n}\n\nJEMALLOC_INLINE void\natomic_write_uint64(uint64_t *p, uint64_t x)\n{\n\tuint64_t o;\n\n\t/*The documented OSAtomic*() API does not expose an atomic exchange. */\n\tdo {\n\t\to = atomic_read_uint64(p);\n\t} while (atomic_cas_uint64(p, o, x));\n}\n#  elif (defined(_MSC_VER))\nJEMALLOC_INLINE uint64_t\natomic_add_uint64(uint64_t *p, uint64_t x)\n{\n\n\treturn (InterlockedExchangeAdd64(p, x) + x);\n}\n\nJEMALLOC_INLINE uint64_t\natomic_sub_uint64(uint64_t *p, uint64_t x)\n{\n\n\treturn (InterlockedExchangeAdd64(p, -((int64_t)x)) - x);\n}\n\nJEMALLOC_INLINE bool\natomic_cas_uint64(uint64_t *p, uint64_t c, uint64_t s)\n{\n\tuint64_t o;\n\n\to = InterlockedCompareExchange64(p, s, c);\n\treturn (o != c);\n}\n\nJEMALLOC_INLINE void\natomic_write_uint64(uint64_t *p, uint64_t x)\n{\n\n\tInterlockedExchange64(p, x);\n}\n#  elif (defined(__GCC_HAVE_SYNC_COMPARE_AND_SWAP_8) || \\\n    defined(JE_FORCE_SYNC_COMPARE_AND_SWAP_8))\nJEMALLOC_INLINE uint64_t\natomic_add_uint64(uint64_t *p, uint64_t x)\n{\n\n\treturn (__sync_add_and_fetch(p, x));\n}\n\nJEMALLOC_INLINE uint64_t\natomic_sub_uint64(uint64_t *p, uint64_t x)\n{\n\n\treturn (__sync_sub_and_fetch(p, x));\n}\n\nJEMALLOC_INLINE bool\natomic_cas_uint64(uint64_t *p, uint64_t c, uint64_t s)\n{\n\n\treturn (!__sync_bool_compare_and_swap(p, c, s));\n}\n\nJEMALLOC_INLINE void\natomic_write_uint64(uint64_t *p, uint64_t x)\n{\n\n\t__sync_lock_test_and_set(p, x);\n}\n#  else\n#    error \"Missing implementation for 64-bit atomic operations\"\n#  endif\n#endif\n\n/******************************************************************************/\n/* 32-bit operations. */\n#if (defined(__i386__) || defined(__amd64__) || defined(__x86_64__))\nJEMALLOC_INLINE uint32_t\natomic_add_uint32(uint32_t *p, uint32_t x)\n{\n\tuint32_t t = x;\n\n\tasm volatile (\n\t    \"lock; xaddl %0, %1;\"\n\t    : \"+r\" (t), \"=m\" (*p) /* Outputs. */\n\t    : \"m\" (*p) /* Inputs. */\n\t    );\n\n\treturn (t + x);\n}\n\nJEMALLOC_INLINE uint32_t\natomic_sub_uint32(uint32_t *p, uint32_t x)\n{\n\tuint32_t t;\n\n\tx = (uint32_t)(-(int32_t)x);\n\tt = x;\n\tasm volatile (\n\t    \"lock; xaddl %0, %1;\"\n\t    : \"+r\" (t), \"=m\" (*p) /* Outputs. */\n\t    : \"m\" (*p) /* Inputs. */\n\t    );\n\n\treturn (t + x);\n}\n\nJEMALLOC_INLINE bool\natomic_cas_uint32(uint32_t *p, uint32_t c, uint32_t s)\n{\n\tuint8_t success;\n\n\tasm volatile (\n\t    \"lock; cmpxchgl %4, %0;\"\n\t    \"sete %1;\"\n\t    : \"=m\" (*p), \"=a\" (success) /* Outputs. */\n\t    : \"m\" (*p), \"a\" (c), \"r\" (s) /* Inputs. */\n\t    : \"memory\"\n\t    );\n\n\treturn (!(bool)success);\n}\n\nJEMALLOC_INLINE void\natomic_write_uint32(uint32_t *p, uint32_t x)\n{\n\n\tasm volatile (\n\t    \"xchgl %1, %0;\" /* Lock is implied by xchgl. */\n\t    : \"=m\" (*p), \"+r\" (x) /* Outputs. */\n\t    : \"m\" (*p) /* Inputs. */\n\t    : \"memory\" /* Clobbers. */\n\t    );\n}\n#  elif (defined(JEMALLOC_C11ATOMICS))\nJEMALLOC_INLINE uint32_t\natomic_add_uint32(uint32_t *p, uint32_t x)\n{\n\tvolatile atomic_uint_least32_t *a = (volatile atomic_uint_least32_t *)p;\n\treturn (atomic_fetch_add(a, x) + x);\n}\n\nJEMALLOC_INLINE uint32_t\natomic_sub_uint32(uint32_t *p, uint32_t x)\n{\n\tvolatile atomic_uint_least32_t *a = (volatile atomic_uint_least32_t *)p;\n\treturn (atomic_fetch_sub(a, x) - x);\n}\n\nJEMALLOC_INLINE bool\natomic_cas_uint32(uint32_t *p, uint32_t c, uint32_t s)\n{\n\tvolatile atomic_uint_least32_t *a = (volatile atomic_uint_least32_t *)p;\n\treturn (!atomic_compare_exchange_strong(a, &c, s));\n}\n\nJEMALLOC_INLINE void\natomic_write_uint32(uint32_t *p, uint32_t x)\n{\n\tvolatile atomic_uint_least32_t *a = (volatile atomic_uint_least32_t *)p;\n\tatomic_store(a, x);\n}\n#elif (defined(JEMALLOC_ATOMIC9))\nJEMALLOC_INLINE uint32_t\natomic_add_uint32(uint32_t *p, uint32_t x)\n{\n\n\treturn (atomic_fetchadd_32(p, x) + x);\n}\n\nJEMALLOC_INLINE uint32_t\natomic_sub_uint32(uint32_t *p, uint32_t x)\n{\n\n\treturn (atomic_fetchadd_32(p, (uint32_t)(-(int32_t)x)) - x);\n}\n\nJEMALLOC_INLINE bool\natomic_cas_uint32(uint32_t *p, uint32_t c, uint32_t s)\n{\n\n\treturn (!atomic_cmpset_32(p, c, s));\n}\n\nJEMALLOC_INLINE void\natomic_write_uint32(uint32_t *p, uint32_t x)\n{\n\n\tatomic_store_rel_32(p, x);\n}\n#elif (defined(JEMALLOC_OSATOMIC))\nJEMALLOC_INLINE uint32_t\natomic_add_uint32(uint32_t *p, uint32_t x)\n{\n\n\treturn (OSAtomicAdd32((int32_t)x, (int32_t *)p));\n}\n\nJEMALLOC_INLINE uint32_t\natomic_sub_uint32(uint32_t *p, uint32_t x)\n{\n\n\treturn (OSAtomicAdd32(-((int32_t)x), (int32_t *)p));\n}\n\nJEMALLOC_INLINE bool\natomic_cas_uint32(uint32_t *p, uint32_t c, uint32_t s)\n{\n\n\treturn (!OSAtomicCompareAndSwap32(c, s, (int32_t *)p));\n}\n\nJEMALLOC_INLINE void\natomic_write_uint32(uint32_t *p, uint32_t x)\n{\n\tuint32_t o;\n\n\t/*The documented OSAtomic*() API does not expose an atomic exchange. */\n\tdo {\n\t\to = atomic_read_uint32(p);\n\t} while (atomic_cas_uint32(p, o, x));\n}\n#elif (defined(_MSC_VER))\nJEMALLOC_INLINE uint32_t\natomic_add_uint32(uint32_t *p, uint32_t x)\n{\n\n\treturn (InterlockedExchangeAdd(p, x) + x);\n}\n\nJEMALLOC_INLINE uint32_t\natomic_sub_uint32(uint32_t *p, uint32_t x)\n{\n\n\treturn (InterlockedExchangeAdd(p, -((int32_t)x)) - x);\n}\n\nJEMALLOC_INLINE bool\natomic_cas_uint32(uint32_t *p, uint32_t c, uint32_t s)\n{\n\tuint32_t o;\n\n\to = InterlockedCompareExchange(p, s, c);\n\treturn (o != c);\n}\n\nJEMALLOC_INLINE void\natomic_write_uint32(uint32_t *p, uint32_t x)\n{\n\n\tInterlockedExchange(p, x);\n}\n#elif (defined(__GCC_HAVE_SYNC_COMPARE_AND_SWAP_4) || \\\n defined(JE_FORCE_SYNC_COMPARE_AND_SWAP_4))\nJEMALLOC_INLINE uint32_t\natomic_add_uint32(uint32_t *p, uint32_t x)\n{\n\n\treturn (__sync_add_and_fetch(p, x));\n}\n\nJEMALLOC_INLINE uint32_t\natomic_sub_uint32(uint32_t *p, uint32_t x)\n{\n\n\treturn (__sync_sub_and_fetch(p, x));\n}\n\nJEMALLOC_INLINE bool\natomic_cas_uint32(uint32_t *p, uint32_t c, uint32_t s)\n{\n\n\treturn (!__sync_bool_compare_and_swap(p, c, s));\n}\n\nJEMALLOC_INLINE void\natomic_write_uint32(uint32_t *p, uint32_t x)\n{\n\n\t__sync_lock_test_and_set(p, x);\n}\n#else\n#  error \"Missing implementation for 32-bit atomic operations\"\n#endif\n\n/******************************************************************************/\n/* Pointer operations. */\nJEMALLOC_INLINE void *\natomic_add_p(void **p, void *x)\n{\n\n#if (LG_SIZEOF_PTR == 3)\n\treturn ((void *)atomic_add_uint64((uint64_t *)p, (uint64_t)x));\n#elif (LG_SIZEOF_PTR == 2)\n\treturn ((void *)atomic_add_uint32((uint32_t *)p, (uint32_t)x));\n#endif\n}\n\nJEMALLOC_INLINE void *\natomic_sub_p(void **p, void *x)\n{\n\n#if (LG_SIZEOF_PTR == 3)\n\treturn ((void *)atomic_add_uint64((uint64_t *)p,\n\t    (uint64_t)-((int64_t)x)));\n#elif (LG_SIZEOF_PTR == 2)\n\treturn ((void *)atomic_add_uint32((uint32_t *)p,\n\t    (uint32_t)-((int32_t)x)));\n#endif\n}\n\nJEMALLOC_INLINE bool\natomic_cas_p(void **p, void *c, void *s)\n{\n\n#if (LG_SIZEOF_PTR == 3)\n\treturn (atomic_cas_uint64((uint64_t *)p, (uint64_t)c, (uint64_t)s));\n#elif (LG_SIZEOF_PTR == 2)\n\treturn (atomic_cas_uint32((uint32_t *)p, (uint32_t)c, (uint32_t)s));\n#endif\n}\n\nJEMALLOC_INLINE void\natomic_write_p(void **p, const void *x)\n{\n\n#if (LG_SIZEOF_PTR == 3)\n\tatomic_write_uint64((uint64_t *)p, (uint64_t)x);\n#elif (LG_SIZEOF_PTR == 2)\n\tatomic_write_uint32((uint32_t *)p, (uint32_t)x);\n#endif\n}\n\n/******************************************************************************/\n/* size_t operations. */\nJEMALLOC_INLINE size_t\natomic_add_z(size_t *p, size_t x)\n{\n\n#if (LG_SIZEOF_PTR == 3)\n\treturn ((size_t)atomic_add_uint64((uint64_t *)p, (uint64_t)x));\n#elif (LG_SIZEOF_PTR == 2)\n\treturn ((size_t)atomic_add_uint32((uint32_t *)p, (uint32_t)x));\n#endif\n}\n\nJEMALLOC_INLINE size_t\natomic_sub_z(size_t *p, size_t x)\n{\n\n#if (LG_SIZEOF_PTR == 3)\n\treturn ((size_t)atomic_add_uint64((uint64_t *)p,\n\t    (uint64_t)-((int64_t)x)));\n#elif (LG_SIZEOF_PTR == 2)\n\treturn ((size_t)atomic_add_uint32((uint32_t *)p,\n\t    (uint32_t)-((int32_t)x)));\n#endif\n}\n\nJEMALLOC_INLINE bool\natomic_cas_z(size_t *p, size_t c, size_t s)\n{\n\n#if (LG_SIZEOF_PTR == 3)\n\treturn (atomic_cas_uint64((uint64_t *)p, (uint64_t)c, (uint64_t)s));\n#elif (LG_SIZEOF_PTR == 2)\n\treturn (atomic_cas_uint32((uint32_t *)p, (uint32_t)c, (uint32_t)s));\n#endif\n}\n\nJEMALLOC_INLINE void\natomic_write_z(size_t *p, size_t x)\n{\n\n#if (LG_SIZEOF_PTR == 3)\n\tatomic_write_uint64((uint64_t *)p, (uint64_t)x);\n#elif (LG_SIZEOF_PTR == 2)\n\tatomic_write_uint32((uint32_t *)p, (uint32_t)x);\n#endif\n}\n\n/******************************************************************************/\n/* unsigned operations. */\nJEMALLOC_INLINE unsigned\natomic_add_u(unsigned *p, unsigned x)\n{\n\n#if (LG_SIZEOF_INT == 3)\n\treturn ((unsigned)atomic_add_uint64((uint64_t *)p, (uint64_t)x));\n#elif (LG_SIZEOF_INT == 2)\n\treturn ((unsigned)atomic_add_uint32((uint32_t *)p, (uint32_t)x));\n#endif\n}\n\nJEMALLOC_INLINE unsigned\natomic_sub_u(unsigned *p, unsigned x)\n{\n\n#if (LG_SIZEOF_INT == 3)\n\treturn ((unsigned)atomic_add_uint64((uint64_t *)p,\n\t    (uint64_t)-((int64_t)x)));\n#elif (LG_SIZEOF_INT == 2)\n\treturn ((unsigned)atomic_add_uint32((uint32_t *)p,\n\t    (uint32_t)-((int32_t)x)));\n#endif\n}\n\nJEMALLOC_INLINE bool\natomic_cas_u(unsigned *p, unsigned c, unsigned s)\n{\n\n#if (LG_SIZEOF_INT == 3)\n\treturn (atomic_cas_uint64((uint64_t *)p, (uint64_t)c, (uint64_t)s));\n#elif (LG_SIZEOF_INT == 2)\n\treturn (atomic_cas_uint32((uint32_t *)p, (uint32_t)c, (uint32_t)s));\n#endif\n}\n\nJEMALLOC_INLINE void\natomic_write_u(unsigned *p, unsigned x)\n{\n\n#if (LG_SIZEOF_INT == 3)\n\tatomic_write_uint64((uint64_t *)p, (uint64_t)x);\n#elif (LG_SIZEOF_INT == 2)\n\tatomic_write_uint32((uint32_t *)p, (uint32_t)x);\n#endif\n}\n\n/******************************************************************************/\n#endif\n\n#endif /* JEMALLOC_H_INLINES */\n/******************************************************************************/\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/deps/jemalloc/include/jemalloc/internal/base.h",
    "content": "/******************************************************************************/\n#ifdef JEMALLOC_H_TYPES\n\n#endif /* JEMALLOC_H_TYPES */\n/******************************************************************************/\n#ifdef JEMALLOC_H_STRUCTS\n\n#endif /* JEMALLOC_H_STRUCTS */\n/******************************************************************************/\n#ifdef JEMALLOC_H_EXTERNS\n\nvoid\t*base_alloc(tsdn_t *tsdn, size_t size);\nvoid\tbase_stats_get(tsdn_t *tsdn, size_t *allocated, size_t *resident,\n    size_t *mapped);\nbool\tbase_boot(void);\nvoid\tbase_prefork(tsdn_t *tsdn);\nvoid\tbase_postfork_parent(tsdn_t *tsdn);\nvoid\tbase_postfork_child(tsdn_t *tsdn);\n\n#endif /* JEMALLOC_H_EXTERNS */\n/******************************************************************************/\n#ifdef JEMALLOC_H_INLINES\n\n#endif /* JEMALLOC_H_INLINES */\n/******************************************************************************/\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/deps/jemalloc/include/jemalloc/internal/bitmap.h",
    "content": "/******************************************************************************/\n#ifdef JEMALLOC_H_TYPES\n\n/* Maximum bitmap bit count is 2^LG_BITMAP_MAXBITS. */\n#define\tLG_BITMAP_MAXBITS\tLG_RUN_MAXREGS\n#define\tBITMAP_MAXBITS\t\t(ZU(1) << LG_BITMAP_MAXBITS)\n\ntypedef struct bitmap_level_s bitmap_level_t;\ntypedef struct bitmap_info_s bitmap_info_t;\ntypedef unsigned long bitmap_t;\n#define\tLG_SIZEOF_BITMAP\tLG_SIZEOF_LONG\n\n/* Number of bits per group. */\n#define\tLG_BITMAP_GROUP_NBITS\t\t(LG_SIZEOF_BITMAP + 3)\n#define\tBITMAP_GROUP_NBITS\t\t(ZU(1) << LG_BITMAP_GROUP_NBITS)\n#define\tBITMAP_GROUP_NBITS_MASK\t\t(BITMAP_GROUP_NBITS-1)\n\n/*\n * Do some analysis on how big the bitmap is before we use a tree.  For a brute\n * force linear search, if we would have to call ffs_lu() more than 2^3 times,\n * use a tree instead.\n */\n#if LG_BITMAP_MAXBITS - LG_BITMAP_GROUP_NBITS > 3\n#  define USE_TREE\n#endif\n\n/* Number of groups required to store a given number of bits. */\n#define\tBITMAP_BITS2GROUPS(nbits)\t\t\t\t\t\\\n    ((nbits + BITMAP_GROUP_NBITS_MASK) >> LG_BITMAP_GROUP_NBITS)\n\n/*\n * Number of groups required at a particular level for a given number of bits.\n */\n#define\tBITMAP_GROUPS_L0(nbits)\t\t\t\t\t\t\\\n    BITMAP_BITS2GROUPS(nbits)\n#define\tBITMAP_GROUPS_L1(nbits)\t\t\t\t\t\t\\\n    BITMAP_BITS2GROUPS(BITMAP_BITS2GROUPS(nbits))\n#define\tBITMAP_GROUPS_L2(nbits)\t\t\t\t\t\t\\\n    BITMAP_BITS2GROUPS(BITMAP_BITS2GROUPS(BITMAP_BITS2GROUPS((nbits))))\n#define\tBITMAP_GROUPS_L3(nbits)\t\t\t\t\t\t\\\n    BITMAP_BITS2GROUPS(BITMAP_BITS2GROUPS(BITMAP_BITS2GROUPS(\t\t\\\n\tBITMAP_BITS2GROUPS((nbits)))))\n\n/*\n * Assuming the number of levels, number of groups required for a given number\n * of bits.\n */\n#define\tBITMAP_GROUPS_1_LEVEL(nbits)\t\t\t\t\t\\\n    BITMAP_GROUPS_L0(nbits)\n#define\tBITMAP_GROUPS_2_LEVEL(nbits)\t\t\t\t\t\\\n    (BITMAP_GROUPS_1_LEVEL(nbits) + BITMAP_GROUPS_L1(nbits))\n#define\tBITMAP_GROUPS_3_LEVEL(nbits)\t\t\t\t\t\\\n    (BITMAP_GROUPS_2_LEVEL(nbits) + BITMAP_GROUPS_L2(nbits))\n#define\tBITMAP_GROUPS_4_LEVEL(nbits)\t\t\t\t\t\\\n    (BITMAP_GROUPS_3_LEVEL(nbits) + BITMAP_GROUPS_L3(nbits))\n\n/*\n * Maximum number of groups required to support LG_BITMAP_MAXBITS.\n */\n#ifdef USE_TREE\n\n#if LG_BITMAP_MAXBITS <= LG_BITMAP_GROUP_NBITS\n#  define BITMAP_GROUPS_MAX\tBITMAP_GROUPS_1_LEVEL(BITMAP_MAXBITS)\n#elif LG_BITMAP_MAXBITS <= LG_BITMAP_GROUP_NBITS * 2\n#  define BITMAP_GROUPS_MAX\tBITMAP_GROUPS_2_LEVEL(BITMAP_MAXBITS)\n#elif LG_BITMAP_MAXBITS <= LG_BITMAP_GROUP_NBITS * 3\n#  define BITMAP_GROUPS_MAX\tBITMAP_GROUPS_3_LEVEL(BITMAP_MAXBITS)\n#elif LG_BITMAP_MAXBITS <= LG_BITMAP_GROUP_NBITS * 4\n#  define BITMAP_GROUPS_MAX\tBITMAP_GROUPS_4_LEVEL(BITMAP_MAXBITS)\n#else\n#  error \"Unsupported bitmap size\"\n#endif\n\n/* Maximum number of levels possible. */\n#define\tBITMAP_MAX_LEVELS\t\t\t\t\t\t\\\n    (LG_BITMAP_MAXBITS / LG_SIZEOF_BITMAP)\t\t\t\t\\\n    + !!(LG_BITMAP_MAXBITS % LG_SIZEOF_BITMAP)\n\n#else /* USE_TREE */\n\n#define\tBITMAP_GROUPS_MAX BITMAP_BITS2GROUPS(BITMAP_MAXBITS)\n\n#endif /* USE_TREE */\n\n#endif /* JEMALLOC_H_TYPES */\n/******************************************************************************/\n#ifdef JEMALLOC_H_STRUCTS\n\nstruct bitmap_level_s {\n\t/* Offset of this level's groups within the array of groups. */\n\tsize_t group_offset;\n};\n\nstruct bitmap_info_s {\n\t/* Logical number of bits in bitmap (stored at bottom level). */\n\tsize_t nbits;\n\n#ifdef USE_TREE\n\t/* Number of levels necessary for nbits. */\n\tunsigned nlevels;\n\n\t/*\n\t * Only the first (nlevels+1) elements are used, and levels are ordered\n\t * bottom to top (e.g. the bottom level is stored in levels[0]).\n\t */\n\tbitmap_level_t levels[BITMAP_MAX_LEVELS+1];\n#else /* USE_TREE */\n\t/* Number of groups necessary for nbits. */\n\tsize_t ngroups;\n#endif /* USE_TREE */\n};\n\n#endif /* JEMALLOC_H_STRUCTS */\n/******************************************************************************/\n#ifdef JEMALLOC_H_EXTERNS\n\nvoid\tbitmap_info_init(bitmap_info_t *binfo, size_t nbits);\nvoid\tbitmap_init(bitmap_t *bitmap, const bitmap_info_t *binfo);\nsize_t\tbitmap_size(const bitmap_info_t *binfo);\n\n#endif /* JEMALLOC_H_EXTERNS */\n/******************************************************************************/\n#ifdef JEMALLOC_H_INLINES\n\n#ifndef JEMALLOC_ENABLE_INLINE\nbool\tbitmap_full(bitmap_t *bitmap, const bitmap_info_t *binfo);\nbool\tbitmap_get(bitmap_t *bitmap, const bitmap_info_t *binfo, size_t bit);\nvoid\tbitmap_set(bitmap_t *bitmap, const bitmap_info_t *binfo, size_t bit);\nsize_t\tbitmap_sfu(bitmap_t *bitmap, const bitmap_info_t *binfo);\nvoid\tbitmap_unset(bitmap_t *bitmap, const bitmap_info_t *binfo, size_t bit);\n#endif\n\n#if (defined(JEMALLOC_ENABLE_INLINE) || defined(JEMALLOC_BITMAP_C_))\nJEMALLOC_INLINE bool\nbitmap_full(bitmap_t *bitmap, const bitmap_info_t *binfo)\n{\n#ifdef USE_TREE\n\tsize_t rgoff = binfo->levels[binfo->nlevels].group_offset - 1;\n\tbitmap_t rg = bitmap[rgoff];\n\t/* The bitmap is full iff the root group is 0. */\n\treturn (rg == 0);\n#else\n\tsize_t i;\n\n\tfor (i = 0; i < binfo->ngroups; i++) {\n\t\tif (bitmap[i] != 0)\n\t\t\treturn (false);\n\t}\n\treturn (true);\n#endif\n}\n\nJEMALLOC_INLINE bool\nbitmap_get(bitmap_t *bitmap, const bitmap_info_t *binfo, size_t bit)\n{\n\tsize_t goff;\n\tbitmap_t g;\n\n\tassert(bit < binfo->nbits);\n\tgoff = bit >> LG_BITMAP_GROUP_NBITS;\n\tg = bitmap[goff];\n\treturn (!(g & (ZU(1) << (bit & BITMAP_GROUP_NBITS_MASK))));\n}\n\nJEMALLOC_INLINE void\nbitmap_set(bitmap_t *bitmap, const bitmap_info_t *binfo, size_t bit)\n{\n\tsize_t goff;\n\tbitmap_t *gp;\n\tbitmap_t g;\n\n\tassert(bit < binfo->nbits);\n\tassert(!bitmap_get(bitmap, binfo, bit));\n\tgoff = bit >> LG_BITMAP_GROUP_NBITS;\n\tgp = &bitmap[goff];\n\tg = *gp;\n\tassert(g & (ZU(1) << (bit & BITMAP_GROUP_NBITS_MASK)));\n\tg ^= ZU(1) << (bit & BITMAP_GROUP_NBITS_MASK);\n\t*gp = g;\n\tassert(bitmap_get(bitmap, binfo, bit));\n#ifdef USE_TREE\n\t/* Propagate group state transitions up the tree. */\n\tif (g == 0) {\n\t\tunsigned i;\n\t\tfor (i = 1; i < binfo->nlevels; i++) {\n\t\t\tbit = goff;\n\t\t\tgoff = bit >> LG_BITMAP_GROUP_NBITS;\n\t\t\tgp = &bitmap[binfo->levels[i].group_offset + goff];\n\t\t\tg = *gp;\n\t\t\tassert(g & (ZU(1) << (bit & BITMAP_GROUP_NBITS_MASK)));\n\t\t\tg ^= ZU(1) << (bit & BITMAP_GROUP_NBITS_MASK);\n\t\t\t*gp = g;\n\t\t\tif (g != 0)\n\t\t\t\tbreak;\n\t\t}\n\t}\n#endif\n}\n\n/* sfu: set first unset. */\nJEMALLOC_INLINE size_t\nbitmap_sfu(bitmap_t *bitmap, const bitmap_info_t *binfo)\n{\n\tsize_t bit;\n\tbitmap_t g;\n\tunsigned i;\n\n\tassert(!bitmap_full(bitmap, binfo));\n\n#ifdef USE_TREE\n\ti = binfo->nlevels - 1;\n\tg = bitmap[binfo->levels[i].group_offset];\n\tbit = ffs_lu(g) - 1;\n\twhile (i > 0) {\n\t\ti--;\n\t\tg = bitmap[binfo->levels[i].group_offset + bit];\n\t\tbit = (bit << LG_BITMAP_GROUP_NBITS) + (ffs_lu(g) - 1);\n\t}\n#else\n\ti = 0;\n\tg = bitmap[0];\n\twhile ((bit = ffs_lu(g)) == 0) {\n\t\ti++;\n\t\tg = bitmap[i];\n\t}\n\tbit = (i << LG_BITMAP_GROUP_NBITS) + (bit - 1);\n#endif\n\tbitmap_set(bitmap, binfo, bit);\n\treturn (bit);\n}\n\nJEMALLOC_INLINE void\nbitmap_unset(bitmap_t *bitmap, const bitmap_info_t *binfo, size_t bit)\n{\n\tsize_t goff;\n\tbitmap_t *gp;\n\tbitmap_t g;\n\tUNUSED bool propagate;\n\n\tassert(bit < binfo->nbits);\n\tassert(bitmap_get(bitmap, binfo, bit));\n\tgoff = bit >> LG_BITMAP_GROUP_NBITS;\n\tgp = &bitmap[goff];\n\tg = *gp;\n\tpropagate = (g == 0);\n\tassert((g & (ZU(1) << (bit & BITMAP_GROUP_NBITS_MASK))) == 0);\n\tg ^= ZU(1) << (bit & BITMAP_GROUP_NBITS_MASK);\n\t*gp = g;\n\tassert(!bitmap_get(bitmap, binfo, bit));\n#ifdef USE_TREE\n\t/* Propagate group state transitions up the tree. */\n\tif (propagate) {\n\t\tunsigned i;\n\t\tfor (i = 1; i < binfo->nlevels; i++) {\n\t\t\tbit = goff;\n\t\t\tgoff = bit >> LG_BITMAP_GROUP_NBITS;\n\t\t\tgp = &bitmap[binfo->levels[i].group_offset + goff];\n\t\t\tg = *gp;\n\t\t\tpropagate = (g == 0);\n\t\t\tassert((g & (ZU(1) << (bit & BITMAP_GROUP_NBITS_MASK)))\n\t\t\t    == 0);\n\t\t\tg ^= ZU(1) << (bit & BITMAP_GROUP_NBITS_MASK);\n\t\t\t*gp = g;\n\t\t\tif (!propagate)\n\t\t\t\tbreak;\n\t\t}\n\t}\n#endif /* USE_TREE */\n}\n\n#endif\n\n#endif /* JEMALLOC_H_INLINES */\n/******************************************************************************/\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/deps/jemalloc/include/jemalloc/internal/chunk.h",
    "content": "/******************************************************************************/\n#ifdef JEMALLOC_H_TYPES\n\n/*\n * Size and alignment of memory chunks that are allocated by the OS's virtual\n * memory system.\n */\n#define\tLG_CHUNK_DEFAULT\t21\n\n/* Return the chunk address for allocation address a. */\n#define\tCHUNK_ADDR2BASE(a)\t\t\t\t\t\t\\\n\t((void *)((uintptr_t)(a) & ~chunksize_mask))\n\n/* Return the chunk offset of address a. */\n#define\tCHUNK_ADDR2OFFSET(a)\t\t\t\t\t\t\\\n\t((size_t)((uintptr_t)(a) & chunksize_mask))\n\n/* Return the smallest chunk multiple that is >= s. */\n#define\tCHUNK_CEILING(s)\t\t\t\t\t\t\\\n\t(((s) + chunksize_mask) & ~chunksize_mask)\n\n#define\tCHUNK_HOOKS_INITIALIZER {\t\t\t\t\t\\\n    NULL,\t\t\t\t\t\t\t\t\\\n    NULL,\t\t\t\t\t\t\t\t\\\n    NULL,\t\t\t\t\t\t\t\t\\\n    NULL,\t\t\t\t\t\t\t\t\\\n    NULL,\t\t\t\t\t\t\t\t\\\n    NULL,\t\t\t\t\t\t\t\t\\\n    NULL\t\t\t\t\t\t\t\t\\\n}\n\n#endif /* JEMALLOC_H_TYPES */\n/******************************************************************************/\n#ifdef JEMALLOC_H_STRUCTS\n\n#endif /* JEMALLOC_H_STRUCTS */\n/******************************************************************************/\n#ifdef JEMALLOC_H_EXTERNS\n\nextern size_t\t\topt_lg_chunk;\nextern const char\t*opt_dss;\n\nextern rtree_t\t\tchunks_rtree;\n\nextern size_t\t\tchunksize;\nextern size_t\t\tchunksize_mask; /* (chunksize - 1). */\nextern size_t\t\tchunk_npages;\n\nextern const chunk_hooks_t\tchunk_hooks_default;\n\nchunk_hooks_t\tchunk_hooks_get(tsdn_t *tsdn, arena_t *arena);\nchunk_hooks_t\tchunk_hooks_set(tsdn_t *tsdn, arena_t *arena,\n    const chunk_hooks_t *chunk_hooks);\n\nbool\tchunk_register(tsdn_t *tsdn, const void *chunk,\n    const extent_node_t *node);\nvoid\tchunk_deregister(const void *chunk, const extent_node_t *node);\nvoid\t*chunk_alloc_base(size_t size);\nvoid\t*chunk_alloc_cache(tsdn_t *tsdn, arena_t *arena,\n    chunk_hooks_t *chunk_hooks, void *new_addr, size_t size, size_t alignment,\n    bool *zero, bool dalloc_node);\nvoid\t*chunk_alloc_wrapper(tsdn_t *tsdn, arena_t *arena,\n    chunk_hooks_t *chunk_hooks, void *new_addr, size_t size, size_t alignment,\n    bool *zero, bool *commit);\nvoid\tchunk_dalloc_cache(tsdn_t *tsdn, arena_t *arena,\n    chunk_hooks_t *chunk_hooks, void *chunk, size_t size, bool committed);\nvoid\tchunk_dalloc_wrapper(tsdn_t *tsdn, arena_t *arena,\n    chunk_hooks_t *chunk_hooks, void *chunk, size_t size, bool zeroed,\n    bool committed);\nbool\tchunk_purge_wrapper(tsdn_t *tsdn, arena_t *arena,\n    chunk_hooks_t *chunk_hooks, void *chunk, size_t size, size_t offset,\n    size_t length);\nbool\tchunk_boot(void);\nvoid\tchunk_prefork(tsdn_t *tsdn);\nvoid\tchunk_postfork_parent(tsdn_t *tsdn);\nvoid\tchunk_postfork_child(tsdn_t *tsdn);\n\n#endif /* JEMALLOC_H_EXTERNS */\n/******************************************************************************/\n#ifdef JEMALLOC_H_INLINES\n\n#ifndef JEMALLOC_ENABLE_INLINE\nextent_node_t\t*chunk_lookup(const void *chunk, bool dependent);\n#endif\n\n#if (defined(JEMALLOC_ENABLE_INLINE) || defined(JEMALLOC_CHUNK_C_))\nJEMALLOC_INLINE extent_node_t *\nchunk_lookup(const void *ptr, bool dependent)\n{\n\n\treturn (rtree_get(&chunks_rtree, (uintptr_t)ptr, dependent));\n}\n#endif\n\n#endif /* JEMALLOC_H_INLINES */\n/******************************************************************************/\n\n#include \"jemalloc/internal/chunk_dss.h\"\n#include \"jemalloc/internal/chunk_mmap.h\"\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/deps/jemalloc/include/jemalloc/internal/chunk_dss.h",
    "content": "/******************************************************************************/\n#ifdef JEMALLOC_H_TYPES\n\ntypedef enum {\n\tdss_prec_disabled  = 0,\n\tdss_prec_primary   = 1,\n\tdss_prec_secondary = 2,\n\n\tdss_prec_limit     = 3\n} dss_prec_t;\n#define\tDSS_PREC_DEFAULT\tdss_prec_secondary\n#define\tDSS_DEFAULT\t\t\"secondary\"\n\n#endif /* JEMALLOC_H_TYPES */\n/******************************************************************************/\n#ifdef JEMALLOC_H_STRUCTS\n\nextern const char *dss_prec_names[];\n\n#endif /* JEMALLOC_H_STRUCTS */\n/******************************************************************************/\n#ifdef JEMALLOC_H_EXTERNS\n\ndss_prec_t\tchunk_dss_prec_get(tsdn_t *tsdn);\nbool\tchunk_dss_prec_set(tsdn_t *tsdn, dss_prec_t dss_prec);\nvoid\t*chunk_alloc_dss(tsdn_t *tsdn, arena_t *arena, void *new_addr,\n    size_t size, size_t alignment, bool *zero, bool *commit);\nbool\tchunk_in_dss(tsdn_t *tsdn, void *chunk);\nbool\tchunk_dss_boot(void);\nvoid\tchunk_dss_prefork(tsdn_t *tsdn);\nvoid\tchunk_dss_postfork_parent(tsdn_t *tsdn);\nvoid\tchunk_dss_postfork_child(tsdn_t *tsdn);\n\n#endif /* JEMALLOC_H_EXTERNS */\n/******************************************************************************/\n#ifdef JEMALLOC_H_INLINES\n\n#endif /* JEMALLOC_H_INLINES */\n/******************************************************************************/\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/deps/jemalloc/include/jemalloc/internal/chunk_mmap.h",
    "content": "/******************************************************************************/\n#ifdef JEMALLOC_H_TYPES\n\n#endif /* JEMALLOC_H_TYPES */\n/******************************************************************************/\n#ifdef JEMALLOC_H_STRUCTS\n\n#endif /* JEMALLOC_H_STRUCTS */\n/******************************************************************************/\n#ifdef JEMALLOC_H_EXTERNS\n\nvoid\t*chunk_alloc_mmap(void *new_addr, size_t size, size_t alignment,\n    bool *zero, bool *commit);\nbool\tchunk_dalloc_mmap(void *chunk, size_t size);\n\n#endif /* JEMALLOC_H_EXTERNS */\n/******************************************************************************/\n#ifdef JEMALLOC_H_INLINES\n\n#endif /* JEMALLOC_H_INLINES */\n/******************************************************************************/\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/deps/jemalloc/include/jemalloc/internal/ckh.h",
    "content": "/******************************************************************************/\n#ifdef JEMALLOC_H_TYPES\n\ntypedef struct ckh_s ckh_t;\ntypedef struct ckhc_s ckhc_t;\n\n/* Typedefs to allow easy function pointer passing. */\ntypedef void ckh_hash_t (const void *, size_t[2]);\ntypedef bool ckh_keycomp_t (const void *, const void *);\n\n/* Maintain counters used to get an idea of performance. */\n/* #define\tCKH_COUNT */\n/* Print counter values in ckh_delete() (requires CKH_COUNT). */\n/* #define\tCKH_VERBOSE */\n\n/*\n * There are 2^LG_CKH_BUCKET_CELLS cells in each hash table bucket.  Try to fit\n * one bucket per L1 cache line.\n */\n#define\tLG_CKH_BUCKET_CELLS (LG_CACHELINE - LG_SIZEOF_PTR - 1)\n\n#endif /* JEMALLOC_H_TYPES */\n/******************************************************************************/\n#ifdef JEMALLOC_H_STRUCTS\n\n/* Hash table cell. */\nstruct ckhc_s {\n\tconst void\t*key;\n\tconst void\t*data;\n};\n\nstruct ckh_s {\n#ifdef CKH_COUNT\n\t/* Counters used to get an idea of performance. */\n\tuint64_t\tngrows;\n\tuint64_t\tnshrinks;\n\tuint64_t\tnshrinkfails;\n\tuint64_t\tninserts;\n\tuint64_t\tnrelocs;\n#endif\n\n\t/* Used for pseudo-random number generation. */\n\tuint64_t\tprng_state;\n\n\t/* Total number of items. */\n\tsize_t\t\tcount;\n\n\t/*\n\t * Minimum and current number of hash table buckets.  There are\n\t * 2^LG_CKH_BUCKET_CELLS cells per bucket.\n\t */\n\tunsigned\tlg_minbuckets;\n\tunsigned\tlg_curbuckets;\n\n\t/* Hash and comparison functions. */\n\tckh_hash_t\t*hash;\n\tckh_keycomp_t\t*keycomp;\n\n\t/* Hash table with 2^lg_curbuckets buckets. */\n\tckhc_t\t\t*tab;\n};\n\n#endif /* JEMALLOC_H_STRUCTS */\n/******************************************************************************/\n#ifdef JEMALLOC_H_EXTERNS\n\nbool\tckh_new(tsdn_t *tsdn, ckh_t *ckh, size_t minitems, ckh_hash_t *hash,\n    ckh_keycomp_t *keycomp);\nvoid\tckh_delete(tsdn_t *tsdn, ckh_t *ckh);\nsize_t\tckh_count(ckh_t *ckh);\nbool\tckh_iter(ckh_t *ckh, size_t *tabind, void **key, void **data);\nbool\tckh_insert(tsdn_t *tsdn, ckh_t *ckh, const void *key, const void *data);\nbool\tckh_remove(tsdn_t *tsdn, ckh_t *ckh, const void *searchkey, void **key,\n    void **data);\nbool\tckh_search(ckh_t *ckh, const void *searchkey, void **key, void **data);\nvoid\tckh_string_hash(const void *key, size_t r_hash[2]);\nbool\tckh_string_keycomp(const void *k1, const void *k2);\nvoid\tckh_pointer_hash(const void *key, size_t r_hash[2]);\nbool\tckh_pointer_keycomp(const void *k1, const void *k2);\n\n#endif /* JEMALLOC_H_EXTERNS */\n/******************************************************************************/\n#ifdef JEMALLOC_H_INLINES\n\n#endif /* JEMALLOC_H_INLINES */\n/******************************************************************************/\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/deps/jemalloc/include/jemalloc/internal/ctl.h",
    "content": "/******************************************************************************/\n#ifdef JEMALLOC_H_TYPES\n\ntypedef struct ctl_node_s ctl_node_t;\ntypedef struct ctl_named_node_s ctl_named_node_t;\ntypedef struct ctl_indexed_node_s ctl_indexed_node_t;\ntypedef struct ctl_arena_stats_s ctl_arena_stats_t;\ntypedef struct ctl_stats_s ctl_stats_t;\n\n#endif /* JEMALLOC_H_TYPES */\n/******************************************************************************/\n#ifdef JEMALLOC_H_STRUCTS\n\nstruct ctl_node_s {\n\tbool\t\t\tnamed;\n};\n\nstruct ctl_named_node_s {\n\tstruct ctl_node_s\tnode;\n\tconst char\t\t*name;\n\t/* If (nchildren == 0), this is a terminal node. */\n\tunsigned\t\tnchildren;\n\tconst\t\t\tctl_node_t *children;\n\tint\t\t\t(*ctl)(tsd_t *, const size_t *, size_t, void *,\n\t    size_t *, void *, size_t);\n};\n\nstruct ctl_indexed_node_s {\n\tstruct ctl_node_s\tnode;\n\tconst ctl_named_node_t\t*(*index)(tsdn_t *, const size_t *, size_t,\n\t    size_t);\n};\n\nstruct ctl_arena_stats_s {\n\tbool\t\t\tinitialized;\n\tunsigned\t\tnthreads;\n\tconst char\t\t*dss;\n\tssize_t\t\t\tlg_dirty_mult;\n\tssize_t\t\t\tdecay_time;\n\tsize_t\t\t\tpactive;\n\tsize_t\t\t\tpdirty;\n\n\t/* The remainder are only populated if config_stats is true. */\n\n\tarena_stats_t\t\tastats;\n\n\t/* Aggregate stats for small size classes, based on bin stats. */\n\tsize_t\t\t\tallocated_small;\n\tuint64_t\t\tnmalloc_small;\n\tuint64_t\t\tndalloc_small;\n\tuint64_t\t\tnrequests_small;\n\n\tmalloc_bin_stats_t\tbstats[NBINS];\n\tmalloc_large_stats_t\t*lstats;\t/* nlclasses elements. */\n\tmalloc_huge_stats_t\t*hstats;\t/* nhclasses elements. */\n};\n\nstruct ctl_stats_s {\n\tsize_t\t\t\tallocated;\n\tsize_t\t\t\tactive;\n\tsize_t\t\t\tmetadata;\n\tsize_t\t\t\tresident;\n\tsize_t\t\t\tmapped;\n\tsize_t\t\t\tretained;\n\tunsigned\t\tnarenas;\n\tctl_arena_stats_t\t*arenas;\t/* (narenas + 1) elements. */\n};\n\n#endif /* JEMALLOC_H_STRUCTS */\n/******************************************************************************/\n#ifdef JEMALLOC_H_EXTERNS\n\nint\tctl_byname(tsd_t *tsd, const char *name, void *oldp, size_t *oldlenp,\n    void *newp, size_t newlen);\nint\tctl_nametomib(tsdn_t *tsdn, const char *name, size_t *mibp,\n    size_t *miblenp);\n\nint\tctl_bymib(tsd_t *tsd, const size_t *mib, size_t miblen, void *oldp,\n    size_t *oldlenp, void *newp, size_t newlen);\nbool\tctl_boot(void);\nvoid\tctl_prefork(tsdn_t *tsdn);\nvoid\tctl_postfork_parent(tsdn_t *tsdn);\nvoid\tctl_postfork_child(tsdn_t *tsdn);\n\n#define\txmallctl(name, oldp, oldlenp, newp, newlen) do {\t\t\\\n\tif (je_mallctl(name, oldp, oldlenp, newp, newlen)\t\t\\\n\t    != 0) {\t\t\t\t\t\t\t\\\n\t\tmalloc_printf(\t\t\t\t\t\t\\\n\t\t    \"<jemalloc>: Failure in xmallctl(\\\"%s\\\", ...)\\n\",\t\\\n\t\t    name);\t\t\t\t\t\t\\\n\t\tabort();\t\t\t\t\t\t\\\n\t}\t\t\t\t\t\t\t\t\\\n} while (0)\n\n#define\txmallctlnametomib(name, mibp, miblenp) do {\t\t\t\\\n\tif (je_mallctlnametomib(name, mibp, miblenp) != 0) {\t\t\\\n\t\tmalloc_printf(\"<jemalloc>: Failure in \"\t\t\t\\\n\t\t    \"xmallctlnametomib(\\\"%s\\\", ...)\\n\", name);\t\t\\\n\t\tabort();\t\t\t\t\t\t\\\n\t}\t\t\t\t\t\t\t\t\\\n} while (0)\n\n#define\txmallctlbymib(mib, miblen, oldp, oldlenp, newp, newlen) do {\t\\\n\tif (je_mallctlbymib(mib, miblen, oldp, oldlenp, newp,\t\t\\\n\t    newlen) != 0) {\t\t\t\t\t\t\\\n\t\tmalloc_write(\t\t\t\t\t\t\\\n\t\t    \"<jemalloc>: Failure in xmallctlbymib()\\n\");\t\\\n\t\tabort();\t\t\t\t\t\t\\\n\t}\t\t\t\t\t\t\t\t\\\n} while (0)\n\n#endif /* JEMALLOC_H_EXTERNS */\n/******************************************************************************/\n#ifdef JEMALLOC_H_INLINES\n\n#endif /* JEMALLOC_H_INLINES */\n/******************************************************************************/\n\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/deps/jemalloc/include/jemalloc/internal/extent.h",
    "content": "/******************************************************************************/\n#ifdef JEMALLOC_H_TYPES\n\ntypedef struct extent_node_s extent_node_t;\n\n#endif /* JEMALLOC_H_TYPES */\n/******************************************************************************/\n#ifdef JEMALLOC_H_STRUCTS\n\n/* Tree of extents.  Use accessor functions for en_* fields. */\nstruct extent_node_s {\n\t/* Arena from which this extent came, if any. */\n\tarena_t\t\t\t*en_arena;\n\n\t/* Pointer to the extent that this tree node is responsible for. */\n\tvoid\t\t\t*en_addr;\n\n\t/* Total region size. */\n\tsize_t\t\t\ten_size;\n\n\t/*\n\t * The zeroed flag is used by chunk recycling code to track whether\n\t * memory is zero-filled.\n\t */\n\tbool\t\t\ten_zeroed;\n\n\t/*\n\t * True if physical memory is committed to the extent, whether\n\t * explicitly or implicitly as on a system that overcommits and\n\t * satisfies physical memory needs on demand via soft page faults.\n\t */\n\tbool\t\t\ten_committed;\n\n\t/*\n\t * The achunk flag is used to validate that huge allocation lookups\n\t * don't return arena chunks.\n\t */\n\tbool\t\t\ten_achunk;\n\n\t/* Profile counters, used for huge objects. */\n\tprof_tctx_t\t\t*en_prof_tctx;\n\n\t/* Linkage for arena's runs_dirty and chunks_cache rings. */\n\tarena_runs_dirty_link_t\trd;\n\tqr(extent_node_t)\tcc_link;\n\n\tunion {\n\t\t/* Linkage for the size/address-ordered tree. */\n\t\trb_node(extent_node_t)\tszad_link;\n\n\t\t/* Linkage for arena's achunks, huge, and node_cache lists. */\n\t\tql_elm(extent_node_t)\tql_link;\n\t};\n\n\t/* Linkage for the address-ordered tree. */\n\trb_node(extent_node_t)\tad_link;\n};\ntypedef rb_tree(extent_node_t) extent_tree_t;\n\n#endif /* JEMALLOC_H_STRUCTS */\n/******************************************************************************/\n#ifdef JEMALLOC_H_EXTERNS\n\nrb_proto(, extent_tree_szad_, extent_tree_t, extent_node_t)\n\nrb_proto(, extent_tree_ad_, extent_tree_t, extent_node_t)\n\n#endif /* JEMALLOC_H_EXTERNS */\n/******************************************************************************/\n#ifdef JEMALLOC_H_INLINES\n\n#ifndef JEMALLOC_ENABLE_INLINE\narena_t\t*extent_node_arena_get(const extent_node_t *node);\nvoid\t*extent_node_addr_get(const extent_node_t *node);\nsize_t\textent_node_size_get(const extent_node_t *node);\nbool\textent_node_zeroed_get(const extent_node_t *node);\nbool\textent_node_committed_get(const extent_node_t *node);\nbool\textent_node_achunk_get(const extent_node_t *node);\nprof_tctx_t\t*extent_node_prof_tctx_get(const extent_node_t *node);\nvoid\textent_node_arena_set(extent_node_t *node, arena_t *arena);\nvoid\textent_node_addr_set(extent_node_t *node, void *addr);\nvoid\textent_node_size_set(extent_node_t *node, size_t size);\nvoid\textent_node_zeroed_set(extent_node_t *node, bool zeroed);\nvoid\textent_node_committed_set(extent_node_t *node, bool committed);\nvoid\textent_node_achunk_set(extent_node_t *node, bool achunk);\nvoid\textent_node_prof_tctx_set(extent_node_t *node, prof_tctx_t *tctx);\nvoid\textent_node_init(extent_node_t *node, arena_t *arena, void *addr,\n    size_t size, bool zeroed, bool committed);\nvoid\textent_node_dirty_linkage_init(extent_node_t *node);\nvoid\textent_node_dirty_insert(extent_node_t *node,\n    arena_runs_dirty_link_t *runs_dirty, extent_node_t *chunks_dirty);\nvoid\textent_node_dirty_remove(extent_node_t *node);\n#endif\n\n#if (defined(JEMALLOC_ENABLE_INLINE) || defined(JEMALLOC_EXTENT_C_))\nJEMALLOC_INLINE arena_t *\nextent_node_arena_get(const extent_node_t *node)\n{\n\n\treturn (node->en_arena);\n}\n\nJEMALLOC_INLINE void *\nextent_node_addr_get(const extent_node_t *node)\n{\n\n\treturn (node->en_addr);\n}\n\nJEMALLOC_INLINE size_t\nextent_node_size_get(const extent_node_t *node)\n{\n\n\treturn (node->en_size);\n}\n\nJEMALLOC_INLINE bool\nextent_node_zeroed_get(const extent_node_t *node)\n{\n\n\treturn (node->en_zeroed);\n}\n\nJEMALLOC_INLINE bool\nextent_node_committed_get(const extent_node_t *node)\n{\n\n\tassert(!node->en_achunk);\n\treturn (node->en_committed);\n}\n\nJEMALLOC_INLINE bool\nextent_node_achunk_get(const extent_node_t *node)\n{\n\n\treturn (node->en_achunk);\n}\n\nJEMALLOC_INLINE prof_tctx_t *\nextent_node_prof_tctx_get(const extent_node_t *node)\n{\n\n\treturn (node->en_prof_tctx);\n}\n\nJEMALLOC_INLINE void\nextent_node_arena_set(extent_node_t *node, arena_t *arena)\n{\n\n\tnode->en_arena = arena;\n}\n\nJEMALLOC_INLINE void\nextent_node_addr_set(extent_node_t *node, void *addr)\n{\n\n\tnode->en_addr = addr;\n}\n\nJEMALLOC_INLINE void\nextent_node_size_set(extent_node_t *node, size_t size)\n{\n\n\tnode->en_size = size;\n}\n\nJEMALLOC_INLINE void\nextent_node_zeroed_set(extent_node_t *node, bool zeroed)\n{\n\n\tnode->en_zeroed = zeroed;\n}\n\nJEMALLOC_INLINE void\nextent_node_committed_set(extent_node_t *node, bool committed)\n{\n\n\tnode->en_committed = committed;\n}\n\nJEMALLOC_INLINE void\nextent_node_achunk_set(extent_node_t *node, bool achunk)\n{\n\n\tnode->en_achunk = achunk;\n}\n\nJEMALLOC_INLINE void\nextent_node_prof_tctx_set(extent_node_t *node, prof_tctx_t *tctx)\n{\n\n\tnode->en_prof_tctx = tctx;\n}\n\nJEMALLOC_INLINE void\nextent_node_init(extent_node_t *node, arena_t *arena, void *addr, size_t size,\n    bool zeroed, bool committed)\n{\n\n\textent_node_arena_set(node, arena);\n\textent_node_addr_set(node, addr);\n\textent_node_size_set(node, size);\n\textent_node_zeroed_set(node, zeroed);\n\textent_node_committed_set(node, committed);\n\textent_node_achunk_set(node, false);\n\tif (config_prof)\n\t\textent_node_prof_tctx_set(node, NULL);\n}\n\nJEMALLOC_INLINE void\nextent_node_dirty_linkage_init(extent_node_t *node)\n{\n\n\tqr_new(&node->rd, rd_link);\n\tqr_new(node, cc_link);\n}\n\nJEMALLOC_INLINE void\nextent_node_dirty_insert(extent_node_t *node,\n    arena_runs_dirty_link_t *runs_dirty, extent_node_t *chunks_dirty)\n{\n\n\tqr_meld(runs_dirty, &node->rd, rd_link);\n\tqr_meld(chunks_dirty, node, cc_link);\n}\n\nJEMALLOC_INLINE void\nextent_node_dirty_remove(extent_node_t *node)\n{\n\n\tqr_remove(&node->rd, rd_link);\n\tqr_remove(node, cc_link);\n}\n\n#endif\n\n#endif /* JEMALLOC_H_INLINES */\n/******************************************************************************/\n\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/deps/jemalloc/include/jemalloc/internal/hash.h",
    "content": "/*\n * The following hash function is based on MurmurHash3, placed into the public\n * domain by Austin Appleby.  See https://github.com/aappleby/smhasher for\n * details.\n */\n/******************************************************************************/\n#ifdef JEMALLOC_H_TYPES\n\n#endif /* JEMALLOC_H_TYPES */\n/******************************************************************************/\n#ifdef JEMALLOC_H_STRUCTS\n\n#endif /* JEMALLOC_H_STRUCTS */\n/******************************************************************************/\n#ifdef JEMALLOC_H_EXTERNS\n\n#endif /* JEMALLOC_H_EXTERNS */\n/******************************************************************************/\n#ifdef JEMALLOC_H_INLINES\n\n#ifndef JEMALLOC_ENABLE_INLINE\nuint32_t\thash_x86_32(const void *key, int len, uint32_t seed);\nvoid\thash_x86_128(const void *key, const int len, uint32_t seed,\n    uint64_t r_out[2]);\nvoid\thash_x64_128(const void *key, const int len, const uint32_t seed,\n    uint64_t r_out[2]);\nvoid\thash(const void *key, size_t len, const uint32_t seed,\n    size_t r_hash[2]);\n#endif\n\n#if (defined(JEMALLOC_ENABLE_INLINE) || defined(JEMALLOC_HASH_C_))\n/******************************************************************************/\n/* Internal implementation. */\nJEMALLOC_INLINE uint32_t\nhash_rotl_32(uint32_t x, int8_t r)\n{\n\n\treturn ((x << r) | (x >> (32 - r)));\n}\n\nJEMALLOC_INLINE uint64_t\nhash_rotl_64(uint64_t x, int8_t r)\n{\n\n\treturn ((x << r) | (x >> (64 - r)));\n}\n\nJEMALLOC_INLINE uint32_t\nhash_get_block_32(const uint32_t *p, int i)\n{\n\n\t/* Handle unaligned read. */\n\tif (unlikely((uintptr_t)p & (sizeof(uint32_t)-1)) != 0) {\n\t\tuint32_t ret;\n\n\t\tmemcpy(&ret, (uint8_t *)(p + i), sizeof(uint32_t));\n\t\treturn (ret);\n\t}\n\n\treturn (p[i]);\n}\n\nJEMALLOC_INLINE uint64_t\nhash_get_block_64(const uint64_t *p, int i)\n{\n\n\t/* Handle unaligned read. */\n\tif (unlikely((uintptr_t)p & (sizeof(uint64_t)-1)) != 0) {\n\t\tuint64_t ret;\n\n\t\tmemcpy(&ret, (uint8_t *)(p + i), sizeof(uint64_t));\n\t\treturn (ret);\n\t}\n\n\treturn (p[i]);\n}\n\nJEMALLOC_INLINE uint32_t\nhash_fmix_32(uint32_t h)\n{\n\n\th ^= h >> 16;\n\th *= 0x85ebca6b;\n\th ^= h >> 13;\n\th *= 0xc2b2ae35;\n\th ^= h >> 16;\n\n\treturn (h);\n}\n\nJEMALLOC_INLINE uint64_t\nhash_fmix_64(uint64_t k)\n{\n\n\tk ^= k >> 33;\n\tk *= KQU(0xff51afd7ed558ccd);\n\tk ^= k >> 33;\n\tk *= KQU(0xc4ceb9fe1a85ec53);\n\tk ^= k >> 33;\n\n\treturn (k);\n}\n\nJEMALLOC_INLINE uint32_t\nhash_x86_32(const void *key, int len, uint32_t seed)\n{\n\tconst uint8_t *data = (const uint8_t *) key;\n\tconst int nblocks = len / 4;\n\n\tuint32_t h1 = seed;\n\n\tconst uint32_t c1 = 0xcc9e2d51;\n\tconst uint32_t c2 = 0x1b873593;\n\n\t/* body */\n\t{\n\t\tconst uint32_t *blocks = (const uint32_t *) (data + nblocks*4);\n\t\tint i;\n\n\t\tfor (i = -nblocks; i; i++) {\n\t\t\tuint32_t k1 = hash_get_block_32(blocks, i);\n\n\t\t\tk1 *= c1;\n\t\t\tk1 = hash_rotl_32(k1, 15);\n\t\t\tk1 *= c2;\n\n\t\t\th1 ^= k1;\n\t\t\th1 = hash_rotl_32(h1, 13);\n\t\t\th1 = h1*5 + 0xe6546b64;\n\t\t}\n\t}\n\n\t/* tail */\n\t{\n\t\tconst uint8_t *tail = (const uint8_t *) (data + nblocks*4);\n\n\t\tuint32_t k1 = 0;\n\n\t\tswitch (len & 3) {\n\t\tcase 3: k1 ^= tail[2] << 16;\n\t\tcase 2: k1 ^= tail[1] << 8;\n\t\tcase 1: k1 ^= tail[0]; k1 *= c1; k1 = hash_rotl_32(k1, 15);\n\t\t\tk1 *= c2; h1 ^= k1;\n\t\t}\n\t}\n\n\t/* finalization */\n\th1 ^= len;\n\n\th1 = hash_fmix_32(h1);\n\n\treturn (h1);\n}\n\nUNUSED JEMALLOC_INLINE void\nhash_x86_128(const void *key, const int len, uint32_t seed,\n    uint64_t r_out[2])\n{\n\tconst uint8_t * data = (const uint8_t *) key;\n\tconst int nblocks = len / 16;\n\n\tuint32_t h1 = seed;\n\tuint32_t h2 = seed;\n\tuint32_t h3 = seed;\n\tuint32_t h4 = seed;\n\n\tconst uint32_t c1 = 0x239b961b;\n\tconst uint32_t c2 = 0xab0e9789;\n\tconst uint32_t c3 = 0x38b34ae5;\n\tconst uint32_t c4 = 0xa1e38b93;\n\n\t/* body */\n\t{\n\t\tconst uint32_t *blocks = (const uint32_t *) (data + nblocks*16);\n\t\tint i;\n\n\t\tfor (i = -nblocks; i; i++) {\n\t\t\tuint32_t k1 = hash_get_block_32(blocks, i*4 + 0);\n\t\t\tuint32_t k2 = hash_get_block_32(blocks, i*4 + 1);\n\t\t\tuint32_t k3 = hash_get_block_32(blocks, i*4 + 2);\n\t\t\tuint32_t k4 = hash_get_block_32(blocks, i*4 + 3);\n\n\t\t\tk1 *= c1; k1 = hash_rotl_32(k1, 15); k1 *= c2; h1 ^= k1;\n\n\t\t\th1 = hash_rotl_32(h1, 19); h1 += h2;\n\t\t\th1 = h1*5 + 0x561ccd1b;\n\n\t\t\tk2 *= c2; k2 = hash_rotl_32(k2, 16); k2 *= c3; h2 ^= k2;\n\n\t\t\th2 = hash_rotl_32(h2, 17); h2 += h3;\n\t\t\th2 = h2*5 + 0x0bcaa747;\n\n\t\t\tk3 *= c3; k3 = hash_rotl_32(k3, 17); k3 *= c4; h3 ^= k3;\n\n\t\t\th3 = hash_rotl_32(h3, 15); h3 += h4;\n\t\t\th3 = h3*5 + 0x96cd1c35;\n\n\t\t\tk4 *= c4; k4 = hash_rotl_32(k4, 18); k4 *= c1; h4 ^= k4;\n\n\t\t\th4 = hash_rotl_32(h4, 13); h4 += h1;\n\t\t\th4 = h4*5 + 0x32ac3b17;\n\t\t}\n\t}\n\n\t/* tail */\n\t{\n\t\tconst uint8_t *tail = (const uint8_t *) (data + nblocks*16);\n\t\tuint32_t k1 = 0;\n\t\tuint32_t k2 = 0;\n\t\tuint32_t k3 = 0;\n\t\tuint32_t k4 = 0;\n\n\t\tswitch (len & 15) {\n\t\tcase 15: k4 ^= tail[14] << 16;\n\t\tcase 14: k4 ^= tail[13] << 8;\n\t\tcase 13: k4 ^= tail[12] << 0;\n\t\t\tk4 *= c4; k4 = hash_rotl_32(k4, 18); k4 *= c1; h4 ^= k4;\n\n\t\tcase 12: k3 ^= tail[11] << 24;\n\t\tcase 11: k3 ^= tail[10] << 16;\n\t\tcase 10: k3 ^= tail[ 9] << 8;\n\t\tcase  9: k3 ^= tail[ 8] << 0;\n\t\t     k3 *= c3; k3 = hash_rotl_32(k3, 17); k3 *= c4; h3 ^= k3;\n\n\t\tcase  8: k2 ^= tail[ 7] << 24;\n\t\tcase  7: k2 ^= tail[ 6] << 16;\n\t\tcase  6: k2 ^= tail[ 5] << 8;\n\t\tcase  5: k2 ^= tail[ 4] << 0;\n\t\t\tk2 *= c2; k2 = hash_rotl_32(k2, 16); k2 *= c3; h2 ^= k2;\n\n\t\tcase  4: k1 ^= tail[ 3] << 24;\n\t\tcase  3: k1 ^= tail[ 2] << 16;\n\t\tcase  2: k1 ^= tail[ 1] << 8;\n\t\tcase  1: k1 ^= tail[ 0] << 0;\n\t\t\tk1 *= c1; k1 = hash_rotl_32(k1, 15); k1 *= c2; h1 ^= k1;\n\t\t}\n\t}\n\n\t/* finalization */\n\th1 ^= len; h2 ^= len; h3 ^= len; h4 ^= len;\n\n\th1 += h2; h1 += h3; h1 += h4;\n\th2 += h1; h3 += h1; h4 += h1;\n\n\th1 = hash_fmix_32(h1);\n\th2 = hash_fmix_32(h2);\n\th3 = hash_fmix_32(h3);\n\th4 = hash_fmix_32(h4);\n\n\th1 += h2; h1 += h3; h1 += h4;\n\th2 += h1; h3 += h1; h4 += h1;\n\n\tr_out[0] = (((uint64_t) h2) << 32) | h1;\n\tr_out[1] = (((uint64_t) h4) << 32) | h3;\n}\n\nUNUSED JEMALLOC_INLINE void\nhash_x64_128(const void *key, const int len, const uint32_t seed,\n    uint64_t r_out[2])\n{\n\tconst uint8_t *data = (const uint8_t *) key;\n\tconst int nblocks = len / 16;\n\n\tuint64_t h1 = seed;\n\tuint64_t h2 = seed;\n\n\tconst uint64_t c1 = KQU(0x87c37b91114253d5);\n\tconst uint64_t c2 = KQU(0x4cf5ad432745937f);\n\n\t/* body */\n\t{\n\t\tconst uint64_t *blocks = (const uint64_t *) (data);\n\t\tint i;\n\n\t\tfor (i = 0; i < nblocks; i++) {\n\t\t\tuint64_t k1 = hash_get_block_64(blocks, i*2 + 0);\n\t\t\tuint64_t k2 = hash_get_block_64(blocks, i*2 + 1);\n\n\t\t\tk1 *= c1; k1 = hash_rotl_64(k1, 31); k1 *= c2; h1 ^= k1;\n\n\t\t\th1 = hash_rotl_64(h1, 27); h1 += h2;\n\t\t\th1 = h1*5 + 0x52dce729;\n\n\t\t\tk2 *= c2; k2 = hash_rotl_64(k2, 33); k2 *= c1; h2 ^= k2;\n\n\t\t\th2 = hash_rotl_64(h2, 31); h2 += h1;\n\t\t\th2 = h2*5 + 0x38495ab5;\n\t\t}\n\t}\n\n\t/* tail */\n\t{\n\t\tconst uint8_t *tail = (const uint8_t*)(data + nblocks*16);\n\t\tuint64_t k1 = 0;\n\t\tuint64_t k2 = 0;\n\n\t\tswitch (len & 15) {\n\t\tcase 15: k2 ^= ((uint64_t)(tail[14])) << 48;\n\t\tcase 14: k2 ^= ((uint64_t)(tail[13])) << 40;\n\t\tcase 13: k2 ^= ((uint64_t)(tail[12])) << 32;\n\t\tcase 12: k2 ^= ((uint64_t)(tail[11])) << 24;\n\t\tcase 11: k2 ^= ((uint64_t)(tail[10])) << 16;\n\t\tcase 10: k2 ^= ((uint64_t)(tail[ 9])) << 8;\n\t\tcase  9: k2 ^= ((uint64_t)(tail[ 8])) << 0;\n\t\t\tk2 *= c2; k2 = hash_rotl_64(k2, 33); k2 *= c1; h2 ^= k2;\n\n\t\tcase  8: k1 ^= ((uint64_t)(tail[ 7])) << 56;\n\t\tcase  7: k1 ^= ((uint64_t)(tail[ 6])) << 48;\n\t\tcase  6: k1 ^= ((uint64_t)(tail[ 5])) << 40;\n\t\tcase  5: k1 ^= ((uint64_t)(tail[ 4])) << 32;\n\t\tcase  4: k1 ^= ((uint64_t)(tail[ 3])) << 24;\n\t\tcase  3: k1 ^= ((uint64_t)(tail[ 2])) << 16;\n\t\tcase  2: k1 ^= ((uint64_t)(tail[ 1])) << 8;\n\t\tcase  1: k1 ^= ((uint64_t)(tail[ 0])) << 0;\n\t\t\tk1 *= c1; k1 = hash_rotl_64(k1, 31); k1 *= c2; h1 ^= k1;\n\t\t}\n\t}\n\n\t/* finalization */\n\th1 ^= len; h2 ^= len;\n\n\th1 += h2;\n\th2 += h1;\n\n\th1 = hash_fmix_64(h1);\n\th2 = hash_fmix_64(h2);\n\n\th1 += h2;\n\th2 += h1;\n\n\tr_out[0] = h1;\n\tr_out[1] = h2;\n}\n\n/******************************************************************************/\n/* API. */\nJEMALLOC_INLINE void\nhash(const void *key, size_t len, const uint32_t seed, size_t r_hash[2])\n{\n\n\tassert(len <= INT_MAX); /* Unfortunate implementation limitation. */\n\n#if (LG_SIZEOF_PTR == 3 && !defined(JEMALLOC_BIG_ENDIAN))\n\thash_x64_128(key, (int)len, seed, (uint64_t *)r_hash);\n#else\n\t{\n\t\tuint64_t hashes[2];\n\t\thash_x86_128(key, (int)len, seed, hashes);\n\t\tr_hash[0] = (size_t)hashes[0];\n\t\tr_hash[1] = (size_t)hashes[1];\n\t}\n#endif\n}\n#endif\n\n#endif /* JEMALLOC_H_INLINES */\n/******************************************************************************/\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/deps/jemalloc/include/jemalloc/internal/huge.h",
    "content": "/******************************************************************************/\n#ifdef JEMALLOC_H_TYPES\n\n#endif /* JEMALLOC_H_TYPES */\n/******************************************************************************/\n#ifdef JEMALLOC_H_STRUCTS\n\n#endif /* JEMALLOC_H_STRUCTS */\n/******************************************************************************/\n#ifdef JEMALLOC_H_EXTERNS\n\nvoid\t*huge_malloc(tsdn_t *tsdn, arena_t *arena, size_t usize, bool zero);\nvoid\t*huge_palloc(tsdn_t *tsdn, arena_t *arena, size_t usize,\n    size_t alignment, bool zero);\nbool\thuge_ralloc_no_move(tsdn_t *tsdn, void *ptr, size_t oldsize,\n    size_t usize_min, size_t usize_max, bool zero);\nvoid\t*huge_ralloc(tsd_t *tsd, arena_t *arena, void *ptr, size_t oldsize,\n    size_t usize, size_t alignment, bool zero, tcache_t *tcache);\n#ifdef JEMALLOC_JET\ntypedef void (huge_dalloc_junk_t)(tsdn_t *, void *, size_t);\nextern huge_dalloc_junk_t *huge_dalloc_junk;\n#endif\nvoid\thuge_dalloc(tsdn_t *tsdn, void *ptr);\narena_t\t*huge_aalloc(const void *ptr);\nsize_t\thuge_salloc(tsdn_t *tsdn, const void *ptr);\nprof_tctx_t\t*huge_prof_tctx_get(tsdn_t *tsdn, const void *ptr);\nvoid\thuge_prof_tctx_set(tsdn_t *tsdn, const void *ptr, prof_tctx_t *tctx);\nvoid\thuge_prof_tctx_reset(tsdn_t *tsdn, const void *ptr);\n\n#endif /* JEMALLOC_H_EXTERNS */\n/******************************************************************************/\n#ifdef JEMALLOC_H_INLINES\n\n#endif /* JEMALLOC_H_INLINES */\n/******************************************************************************/\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/deps/jemalloc/include/jemalloc/internal/jemalloc_internal.h.in",
    "content": "#ifndef JEMALLOC_INTERNAL_H\n#define\tJEMALLOC_INTERNAL_H\n\n#include \"jemalloc_internal_defs.h\"\n#include \"jemalloc/internal/jemalloc_internal_decls.h\"\n\n#ifdef JEMALLOC_UTRACE\n#include <sys/ktrace.h>\n#endif\n\n#define\tJEMALLOC_NO_DEMANGLE\n#ifdef JEMALLOC_JET\n#  define JEMALLOC_N(n) jet_##n\n#  include \"jemalloc/internal/public_namespace.h\"\n#  define JEMALLOC_NO_RENAME\n#  include \"../jemalloc@install_suffix@.h\"\n#  undef JEMALLOC_NO_RENAME\n#else\n#  define JEMALLOC_N(n) @private_namespace@##n\n#  include \"../jemalloc@install_suffix@.h\"\n#endif\n#include \"jemalloc/internal/private_namespace.h\"\n\nstatic const bool config_debug =\n#ifdef JEMALLOC_DEBUG\n    true\n#else\n    false\n#endif\n    ;\nstatic const bool have_dss =\n#ifdef JEMALLOC_DSS\n    true\n#else\n    false\n#endif\n    ;\nstatic const bool config_fill =\n#ifdef JEMALLOC_FILL\n    true\n#else\n    false\n#endif\n    ;\nstatic const bool config_lazy_lock =\n#ifdef JEMALLOC_LAZY_LOCK\n    true\n#else\n    false\n#endif\n    ;\nstatic const char * const config_malloc_conf = JEMALLOC_CONFIG_MALLOC_CONF;\nstatic const bool config_prof =\n#ifdef JEMALLOC_PROF\n    true\n#else\n    false\n#endif\n    ;\nstatic const bool config_prof_libgcc =\n#ifdef JEMALLOC_PROF_LIBGCC\n    true\n#else\n    false\n#endif\n    ;\nstatic const bool config_prof_libunwind =\n#ifdef JEMALLOC_PROF_LIBUNWIND\n    true\n#else\n    false\n#endif\n    ;\nstatic const bool maps_coalesce =\n#ifdef JEMALLOC_MAPS_COALESCE\n    true\n#else\n    false\n#endif\n    ;\nstatic const bool config_munmap =\n#ifdef JEMALLOC_MUNMAP\n    true\n#else\n    false\n#endif\n    ;\nstatic const bool config_stats =\n#ifdef JEMALLOC_STATS\n    true\n#else\n    false\n#endif\n    ;\nstatic const bool config_tcache =\n#ifdef JEMALLOC_TCACHE\n    true\n#else\n    false\n#endif\n    ;\nstatic const bool config_tls =\n#ifdef JEMALLOC_TLS\n    true\n#else\n    false\n#endif\n    ;\nstatic const bool config_utrace =\n#ifdef JEMALLOC_UTRACE\n    true\n#else\n    false\n#endif\n    ;\nstatic const bool config_valgrind =\n#ifdef JEMALLOC_VALGRIND\n    true\n#else\n    false\n#endif\n    ;\nstatic const bool config_xmalloc =\n#ifdef JEMALLOC_XMALLOC\n    true\n#else\n    false\n#endif\n    ;\nstatic const bool config_ivsalloc =\n#ifdef JEMALLOC_IVSALLOC\n    true\n#else\n    false\n#endif\n    ;\nstatic const bool config_cache_oblivious =\n#ifdef JEMALLOC_CACHE_OBLIVIOUS\n    true\n#else\n    false\n#endif\n    ;\n\n#ifdef JEMALLOC_C11ATOMICS\n#include <stdatomic.h>\n#endif\n\n#ifdef JEMALLOC_ATOMIC9\n#include <machine/atomic.h>\n#endif\n\n#if (defined(JEMALLOC_OSATOMIC) || defined(JEMALLOC_OSSPIN))\n#include <libkern/OSAtomic.h>\n#endif\n\n#ifdef JEMALLOC_ZONE\n#include <mach/mach_error.h>\n#include <mach/mach_init.h>\n#include <mach/vm_map.h>\n#include <malloc/malloc.h>\n#endif\n\n#include \"jemalloc/internal/ph.h\"\n#define\tRB_COMPACT\n#include \"jemalloc/internal/rb.h\"\n#include \"jemalloc/internal/qr.h\"\n#include \"jemalloc/internal/ql.h\"\n\n/*\n * jemalloc can conceptually be broken into components (arena, tcache, etc.),\n * but there are circular dependencies that cannot be broken without\n * substantial performance degradation.  In order to reduce the effect on\n * visual code flow, read the header files in multiple passes, with one of the\n * following cpp variables defined during each pass:\n *\n *   JEMALLOC_H_TYPES   : Preprocessor-defined constants and psuedo-opaque data\n *                        types.\n *   JEMALLOC_H_STRUCTS : Data structures.\n *   JEMALLOC_H_EXTERNS : Extern data declarations and function prototypes.\n *   JEMALLOC_H_INLINES : Inline functions.\n */\n/******************************************************************************/\n#define\tJEMALLOC_H_TYPES\n\n#include \"jemalloc/internal/jemalloc_internal_macros.h\"\n\n/* Size class index type. */\ntypedef unsigned szind_t;\n\n/*\n * Flags bits:\n *\n * a: arena\n * t: tcache\n * 0: unused\n * z: zero\n * n: alignment\n *\n * aaaaaaaa aaaatttt tttttttt 0znnnnnn\n */\n#define\tMALLOCX_ARENA_MASK\t((int)~0xfffff)\n#define\tMALLOCX_ARENA_MAX\t0xffe\n#define\tMALLOCX_TCACHE_MASK\t((int)~0xfff000ffU)\n#define\tMALLOCX_TCACHE_MAX\t0xffd\n#define\tMALLOCX_LG_ALIGN_MASK\t((int)0x3f)\n/* Use MALLOCX_ALIGN_GET() if alignment may not be specified in flags. */\n#define\tMALLOCX_ALIGN_GET_SPECIFIED(flags)\t\t\t\t\\\n    (ZU(1) << (flags & MALLOCX_LG_ALIGN_MASK))\n#define\tMALLOCX_ALIGN_GET(flags)\t\t\t\t\t\\\n    (MALLOCX_ALIGN_GET_SPECIFIED(flags) & (SIZE_T_MAX-1))\n#define\tMALLOCX_ZERO_GET(flags)\t\t\t\t\t\t\\\n    ((bool)(flags & MALLOCX_ZERO))\n\n#define\tMALLOCX_TCACHE_GET(flags)\t\t\t\t\t\\\n    (((unsigned)((flags & MALLOCX_TCACHE_MASK) >> 8)) - 2)\n#define\tMALLOCX_ARENA_GET(flags)\t\t\t\t\t\\\n    (((unsigned)(((unsigned)flags) >> 20)) - 1)\n\n/* Smallest size class to support. */\n#define\tTINY_MIN\t\t(1U << LG_TINY_MIN)\n\n/*\n * Minimum allocation alignment is 2^LG_QUANTUM bytes (ignoring tiny size\n * classes).\n */\n#ifndef LG_QUANTUM\n#  if (defined(__i386__) || defined(_M_IX86))\n#    define LG_QUANTUM\t\t4\n#  endif\n#  ifdef __ia64__\n#    define LG_QUANTUM\t\t4\n#  endif\n#  ifdef __alpha__\n#    define LG_QUANTUM\t\t4\n#  endif\n#  if (defined(__sparc64__) || defined(__sparcv9))\n#    define LG_QUANTUM\t\t4\n#  endif\n#  if (defined(__amd64__) || defined(__x86_64__) || defined(_M_X64))\n#    define LG_QUANTUM\t\t4\n#  endif\n#  ifdef __arm__\n#    define LG_QUANTUM\t\t3\n#  endif\n#  ifdef __aarch64__\n#    define LG_QUANTUM\t\t4\n#  endif\n#  ifdef __hppa__\n#    define LG_QUANTUM\t\t4\n#  endif\n#  ifdef __mips__\n#    define LG_QUANTUM\t\t3\n#  endif\n#  ifdef __or1k__\n#    define LG_QUANTUM\t\t3\n#  endif\n#  ifdef __powerpc__\n#    define LG_QUANTUM\t\t4\n#  endif\n#  ifdef __riscv__\n#    define LG_QUANTUM\t\t4\n#  endif\n#  ifdef __s390__\n#    define LG_QUANTUM\t\t4\n#  endif\n#  ifdef __SH4__\n#    define LG_QUANTUM\t\t4\n#  endif\n#  ifdef __tile__\n#    define LG_QUANTUM\t\t4\n#  endif\n#  ifdef __le32__\n#    define LG_QUANTUM\t\t4\n#  endif\n#  ifndef LG_QUANTUM\n#    error \"Unknown minimum alignment for architecture; specify via \"\n\t \"--with-lg-quantum\"\n#  endif\n#endif\n\n#define\tQUANTUM\t\t\t((size_t)(1U << LG_QUANTUM))\n#define\tQUANTUM_MASK\t\t(QUANTUM - 1)\n\n/* Return the smallest quantum multiple that is >= a. */\n#define\tQUANTUM_CEILING(a)\t\t\t\t\t\t\\\n\t(((a) + QUANTUM_MASK) & ~QUANTUM_MASK)\n\n#define\tLONG\t\t\t((size_t)(1U << LG_SIZEOF_LONG))\n#define\tLONG_MASK\t\t(LONG - 1)\n\n/* Return the smallest long multiple that is >= a. */\n#define\tLONG_CEILING(a)\t\t\t\t\t\t\t\\\n\t(((a) + LONG_MASK) & ~LONG_MASK)\n\n#define\tSIZEOF_PTR\t\t(1U << LG_SIZEOF_PTR)\n#define\tPTR_MASK\t\t(SIZEOF_PTR - 1)\n\n/* Return the smallest (void *) multiple that is >= a. */\n#define\tPTR_CEILING(a)\t\t\t\t\t\t\t\\\n\t(((a) + PTR_MASK) & ~PTR_MASK)\n\n/*\n * Maximum size of L1 cache line.  This is used to avoid cache line aliasing.\n * In addition, this controls the spacing of cacheline-spaced size classes.\n *\n * CACHELINE cannot be based on LG_CACHELINE because __declspec(align()) can\n * only handle raw constants.\n */\n#define\tLG_CACHELINE\t\t6\n#define\tCACHELINE\t\t64\n#define\tCACHELINE_MASK\t\t(CACHELINE - 1)\n\n/* Return the smallest cacheline multiple that is >= s. */\n#define\tCACHELINE_CEILING(s)\t\t\t\t\t\t\\\n\t(((s) + CACHELINE_MASK) & ~CACHELINE_MASK)\n\n/* Page size.  LG_PAGE is determined by the configure script. */\n#ifdef PAGE_MASK\n#  undef PAGE_MASK\n#endif\n#define\tPAGE\t\t((size_t)(1U << LG_PAGE))\n#define\tPAGE_MASK\t((size_t)(PAGE - 1))\n\n/* Return the page base address for the page containing address a. */\n#define\tPAGE_ADDR2BASE(a)\t\t\t\t\t\t\\\n\t((void *)((uintptr_t)(a) & ~PAGE_MASK))\n\n/* Return the smallest pagesize multiple that is >= s. */\n#define\tPAGE_CEILING(s)\t\t\t\t\t\t\t\\\n\t(((s) + PAGE_MASK) & ~PAGE_MASK)\n\n/* Return the nearest aligned address at or below a. */\n#define\tALIGNMENT_ADDR2BASE(a, alignment)\t\t\t\t\\\n\t((void *)((uintptr_t)(a) & (-(alignment))))\n\n/* Return the offset between a and the nearest aligned address at or below a. */\n#define\tALIGNMENT_ADDR2OFFSET(a, alignment)\t\t\t\t\\\n\t((size_t)((uintptr_t)(a) & (alignment - 1)))\n\n/* Return the smallest alignment multiple that is >= s. */\n#define\tALIGNMENT_CEILING(s, alignment)\t\t\t\t\t\\\n\t(((s) + (alignment - 1)) & (-(alignment)))\n\n/* Declare a variable-length array. */\n#if __STDC_VERSION__ < 199901L\n#  ifdef _MSC_VER\n#    include <malloc.h>\n#    define alloca _alloca\n#  else\n#    ifdef JEMALLOC_HAS_ALLOCA_H\n#      include <alloca.h>\n#    else\n#      include <stdlib.h>\n#    endif\n#  endif\n#  define VARIABLE_ARRAY(type, name, count) \\\n\ttype *name = alloca(sizeof(type) * (count))\n#else\n#  define VARIABLE_ARRAY(type, name, count) type name[(count)]\n#endif\n\n#include \"jemalloc/internal/nstime.h\"\n#include \"jemalloc/internal/valgrind.h\"\n#include \"jemalloc/internal/util.h\"\n#include \"jemalloc/internal/atomic.h\"\n#include \"jemalloc/internal/prng.h\"\n#include \"jemalloc/internal/ticker.h\"\n#include \"jemalloc/internal/ckh.h\"\n#include \"jemalloc/internal/size_classes.h\"\n#include \"jemalloc/internal/smoothstep.h\"\n#include \"jemalloc/internal/stats.h\"\n#include \"jemalloc/internal/ctl.h\"\n#include \"jemalloc/internal/witness.h\"\n#include \"jemalloc/internal/mutex.h\"\n#include \"jemalloc/internal/tsd.h\"\n#include \"jemalloc/internal/mb.h\"\n#include \"jemalloc/internal/extent.h\"\n#include \"jemalloc/internal/arena.h\"\n#include \"jemalloc/internal/bitmap.h\"\n#include \"jemalloc/internal/base.h\"\n#include \"jemalloc/internal/rtree.h\"\n#include \"jemalloc/internal/pages.h\"\n#include \"jemalloc/internal/chunk.h\"\n#include \"jemalloc/internal/huge.h\"\n#include \"jemalloc/internal/tcache.h\"\n#include \"jemalloc/internal/hash.h\"\n#include \"jemalloc/internal/quarantine.h\"\n#include \"jemalloc/internal/prof.h\"\n\n#undef JEMALLOC_H_TYPES\n/******************************************************************************/\n#define\tJEMALLOC_H_STRUCTS\n\n#include \"jemalloc/internal/nstime.h\"\n#include \"jemalloc/internal/valgrind.h\"\n#include \"jemalloc/internal/util.h\"\n#include \"jemalloc/internal/atomic.h\"\n#include \"jemalloc/internal/prng.h\"\n#include \"jemalloc/internal/ticker.h\"\n#include \"jemalloc/internal/ckh.h\"\n#include \"jemalloc/internal/size_classes.h\"\n#include \"jemalloc/internal/smoothstep.h\"\n#include \"jemalloc/internal/stats.h\"\n#include \"jemalloc/internal/ctl.h\"\n#include \"jemalloc/internal/witness.h\"\n#include \"jemalloc/internal/mutex.h\"\n#include \"jemalloc/internal/mb.h\"\n#include \"jemalloc/internal/bitmap.h\"\n#define\tJEMALLOC_ARENA_STRUCTS_A\n#include \"jemalloc/internal/arena.h\"\n#undef JEMALLOC_ARENA_STRUCTS_A\n#include \"jemalloc/internal/extent.h\"\n#define\tJEMALLOC_ARENA_STRUCTS_B\n#include \"jemalloc/internal/arena.h\"\n#undef JEMALLOC_ARENA_STRUCTS_B\n#include \"jemalloc/internal/base.h\"\n#include \"jemalloc/internal/rtree.h\"\n#include \"jemalloc/internal/pages.h\"\n#include \"jemalloc/internal/chunk.h\"\n#include \"jemalloc/internal/huge.h\"\n#include \"jemalloc/internal/tcache.h\"\n#include \"jemalloc/internal/hash.h\"\n#include \"jemalloc/internal/quarantine.h\"\n#include \"jemalloc/internal/prof.h\"\n\n#include \"jemalloc/internal/tsd.h\"\n\n#undef JEMALLOC_H_STRUCTS\n/******************************************************************************/\n#define\tJEMALLOC_H_EXTERNS\n\nextern bool\topt_abort;\nextern const char\t*opt_junk;\nextern bool\topt_junk_alloc;\nextern bool\topt_junk_free;\nextern size_t\topt_quarantine;\nextern bool\topt_redzone;\nextern bool\topt_utrace;\nextern bool\topt_xmalloc;\nextern bool\topt_zero;\nextern unsigned\topt_narenas;\n\nextern bool\tin_valgrind;\n\n/* Number of CPUs. */\nextern unsigned\tncpus;\n\n/* Number of arenas used for automatic multiplexing of threads and arenas. */\nextern unsigned\tnarenas_auto;\n\n/*\n * Arenas that are used to service external requests.  Not all elements of the\n * arenas array are necessarily used; arenas are created lazily as needed.\n */\nextern arena_t\t**arenas;\n\n/*\n * index2size_tab encodes the same information as could be computed (at\n * unacceptable cost in some code paths) by index2size_compute().\n */\nextern size_t const\tindex2size_tab[NSIZES+1];\n/*\n * size2index_tab is a compact lookup table that rounds request sizes up to\n * size classes.  In order to reduce cache footprint, the table is compressed,\n * and all accesses are via size2index().\n */\nextern uint8_t const\tsize2index_tab[];\n\nvoid\t*a0malloc(size_t size);\nvoid\ta0dalloc(void *ptr);\nvoid\t*bootstrap_malloc(size_t size);\nvoid\t*bootstrap_calloc(size_t num, size_t size);\nvoid\tbootstrap_free(void *ptr);\nunsigned\tnarenas_total_get(void);\narena_t\t*arena_init(tsdn_t *tsdn, unsigned ind);\narena_tdata_t\t*arena_tdata_get_hard(tsd_t *tsd, unsigned ind);\narena_t\t*arena_choose_hard(tsd_t *tsd, bool internal);\nvoid\tarena_migrate(tsd_t *tsd, unsigned oldind, unsigned newind);\nvoid\tthread_allocated_cleanup(tsd_t *tsd);\nvoid\tthread_deallocated_cleanup(tsd_t *tsd);\nvoid\tiarena_cleanup(tsd_t *tsd);\nvoid\tarena_cleanup(tsd_t *tsd);\nvoid\tarenas_tdata_cleanup(tsd_t *tsd);\nvoid\tnarenas_tdata_cleanup(tsd_t *tsd);\nvoid\tarenas_tdata_bypass_cleanup(tsd_t *tsd);\nvoid\tjemalloc_prefork(void);\nvoid\tjemalloc_postfork_parent(void);\nvoid\tjemalloc_postfork_child(void);\n\n#include \"jemalloc/internal/nstime.h\"\n#include \"jemalloc/internal/valgrind.h\"\n#include \"jemalloc/internal/util.h\"\n#include \"jemalloc/internal/atomic.h\"\n#include \"jemalloc/internal/prng.h\"\n#include \"jemalloc/internal/ticker.h\"\n#include \"jemalloc/internal/ckh.h\"\n#include \"jemalloc/internal/size_classes.h\"\n#include \"jemalloc/internal/smoothstep.h\"\n#include \"jemalloc/internal/stats.h\"\n#include \"jemalloc/internal/ctl.h\"\n#include \"jemalloc/internal/witness.h\"\n#include \"jemalloc/internal/mutex.h\"\n#include \"jemalloc/internal/mb.h\"\n#include \"jemalloc/internal/bitmap.h\"\n#include \"jemalloc/internal/extent.h\"\n#include \"jemalloc/internal/arena.h\"\n#include \"jemalloc/internal/base.h\"\n#include \"jemalloc/internal/rtree.h\"\n#include \"jemalloc/internal/pages.h\"\n#include \"jemalloc/internal/chunk.h\"\n#include \"jemalloc/internal/huge.h\"\n#include \"jemalloc/internal/tcache.h\"\n#include \"jemalloc/internal/hash.h\"\n#include \"jemalloc/internal/quarantine.h\"\n#include \"jemalloc/internal/prof.h\"\n#include \"jemalloc/internal/tsd.h\"\n\n#undef JEMALLOC_H_EXTERNS\n/******************************************************************************/\n#define\tJEMALLOC_H_INLINES\n\n#include \"jemalloc/internal/nstime.h\"\n#include \"jemalloc/internal/valgrind.h\"\n#include \"jemalloc/internal/util.h\"\n#include \"jemalloc/internal/atomic.h\"\n#include \"jemalloc/internal/prng.h\"\n#include \"jemalloc/internal/ticker.h\"\n#include \"jemalloc/internal/ckh.h\"\n#include \"jemalloc/internal/size_classes.h\"\n#include \"jemalloc/internal/smoothstep.h\"\n#include \"jemalloc/internal/stats.h\"\n#include \"jemalloc/internal/ctl.h\"\n#include \"jemalloc/internal/tsd.h\"\n#include \"jemalloc/internal/witness.h\"\n#include \"jemalloc/internal/mutex.h\"\n#include \"jemalloc/internal/mb.h\"\n#include \"jemalloc/internal/extent.h\"\n#include \"jemalloc/internal/base.h\"\n#include \"jemalloc/internal/rtree.h\"\n#include \"jemalloc/internal/pages.h\"\n#include \"jemalloc/internal/chunk.h\"\n#include \"jemalloc/internal/huge.h\"\n\n#ifndef JEMALLOC_ENABLE_INLINE\nszind_t\tsize2index_compute(size_t size);\nszind_t\tsize2index_lookup(size_t size);\nszind_t\tsize2index(size_t size);\nsize_t\tindex2size_compute(szind_t index);\nsize_t\tindex2size_lookup(szind_t index);\nsize_t\tindex2size(szind_t index);\nsize_t\ts2u_compute(size_t size);\nsize_t\ts2u_lookup(size_t size);\nsize_t\ts2u(size_t size);\nsize_t\tsa2u(size_t size, size_t alignment);\narena_t\t*arena_choose_impl(tsd_t *tsd, arena_t *arena, bool internal);\narena_t\t*arena_choose(tsd_t *tsd, arena_t *arena);\narena_t\t*arena_ichoose(tsdn_t *tsdn, arena_t *arena);\narena_tdata_t\t*arena_tdata_get(tsd_t *tsd, unsigned ind,\n    bool refresh_if_missing);\narena_t\t*arena_get(tsdn_t *tsdn, unsigned ind, bool init_if_missing);\nticker_t\t*decay_ticker_get(tsd_t *tsd, unsigned ind);\n#endif\n\n#if (defined(JEMALLOC_ENABLE_INLINE) || defined(JEMALLOC_C_))\nJEMALLOC_INLINE szind_t\nsize2index_compute(size_t size)\n{\n\n#if (NTBINS != 0)\n\tif (size <= (ZU(1) << LG_TINY_MAXCLASS)) {\n\t\tszind_t lg_tmin = LG_TINY_MAXCLASS - NTBINS + 1;\n\t\tszind_t lg_ceil = lg_floor(pow2_ceil_zu(size));\n\t\treturn (lg_ceil < lg_tmin ? 0 : lg_ceil - lg_tmin);\n\t}\n#endif\n\t{\n\t\tszind_t x = unlikely(ZI(size) < 0) ? ((size<<1) ?\n\t\t    (ZU(1)<<(LG_SIZEOF_PTR+3)) : ((ZU(1)<<(LG_SIZEOF_PTR+3))-1))\n\t\t    : lg_floor((size<<1)-1);\n\t\tszind_t shift = (x < LG_SIZE_CLASS_GROUP + LG_QUANTUM) ? 0 :\n\t\t    x - (LG_SIZE_CLASS_GROUP + LG_QUANTUM);\n\t\tszind_t grp = shift << LG_SIZE_CLASS_GROUP;\n\n\t\tszind_t lg_delta = (x < LG_SIZE_CLASS_GROUP + LG_QUANTUM + 1)\n\t\t    ? LG_QUANTUM : x - LG_SIZE_CLASS_GROUP - 1;\n\n\t\tsize_t delta_inverse_mask = ZI(-1) << lg_delta;\n\t\tszind_t mod = ((((size-1) & delta_inverse_mask) >> lg_delta)) &\n\t\t    ((ZU(1) << LG_SIZE_CLASS_GROUP) - 1);\n\n\t\tszind_t index = NTBINS + grp + mod;\n\t\treturn (index);\n\t}\n}\n\nJEMALLOC_ALWAYS_INLINE szind_t\nsize2index_lookup(size_t size)\n{\n\n\tassert(size <= LOOKUP_MAXCLASS);\n\t{\n\t\tszind_t ret = (size2index_tab[(size-1) >> LG_TINY_MIN]);\n\t\tassert(ret == size2index_compute(size));\n\t\treturn (ret);\n\t}\n}\n\nJEMALLOC_ALWAYS_INLINE szind_t\nsize2index(size_t size)\n{\n\n\tassert(size > 0);\n\tif (likely(size <= LOOKUP_MAXCLASS))\n\t\treturn (size2index_lookup(size));\n\treturn (size2index_compute(size));\n}\n\nJEMALLOC_INLINE size_t\nindex2size_compute(szind_t index)\n{\n\n#if (NTBINS > 0)\n\tif (index < NTBINS)\n\t\treturn (ZU(1) << (LG_TINY_MAXCLASS - NTBINS + 1 + index));\n#endif\n\t{\n\t\tsize_t reduced_index = index - NTBINS;\n\t\tsize_t grp = reduced_index >> LG_SIZE_CLASS_GROUP;\n\t\tsize_t mod = reduced_index & ((ZU(1) << LG_SIZE_CLASS_GROUP) -\n\t\t    1);\n\n\t\tsize_t grp_size_mask = ~((!!grp)-1);\n\t\tsize_t grp_size = ((ZU(1) << (LG_QUANTUM +\n\t\t    (LG_SIZE_CLASS_GROUP-1))) << grp) & grp_size_mask;\n\n\t\tsize_t shift = (grp == 0) ? 1 : grp;\n\t\tsize_t lg_delta = shift + (LG_QUANTUM-1);\n\t\tsize_t mod_size = (mod+1) << lg_delta;\n\n\t\tsize_t usize = grp_size + mod_size;\n\t\treturn (usize);\n\t}\n}\n\nJEMALLOC_ALWAYS_INLINE size_t\nindex2size_lookup(szind_t index)\n{\n\tsize_t ret = (size_t)index2size_tab[index];\n\tassert(ret == index2size_compute(index));\n\treturn (ret);\n}\n\nJEMALLOC_ALWAYS_INLINE size_t\nindex2size(szind_t index)\n{\n\n\tassert(index < NSIZES);\n\treturn (index2size_lookup(index));\n}\n\nJEMALLOC_ALWAYS_INLINE size_t\ns2u_compute(size_t size)\n{\n\n#if (NTBINS > 0)\n\tif (size <= (ZU(1) << LG_TINY_MAXCLASS)) {\n\t\tsize_t lg_tmin = LG_TINY_MAXCLASS - NTBINS + 1;\n\t\tsize_t lg_ceil = lg_floor(pow2_ceil_zu(size));\n\t\treturn (lg_ceil < lg_tmin ? (ZU(1) << lg_tmin) :\n\t\t    (ZU(1) << lg_ceil));\n\t}\n#endif\n\t{\n\t\tsize_t x = unlikely(ZI(size) < 0) ? ((size<<1) ?\n\t\t    (ZU(1)<<(LG_SIZEOF_PTR+3)) : ((ZU(1)<<(LG_SIZEOF_PTR+3))-1))\n\t\t    : lg_floor((size<<1)-1);\n\t\tsize_t lg_delta = (x < LG_SIZE_CLASS_GROUP + LG_QUANTUM + 1)\n\t\t    ?  LG_QUANTUM : x - LG_SIZE_CLASS_GROUP - 1;\n\t\tsize_t delta = ZU(1) << lg_delta;\n\t\tsize_t delta_mask = delta - 1;\n\t\tsize_t usize = (size + delta_mask) & ~delta_mask;\n\t\treturn (usize);\n\t}\n}\n\nJEMALLOC_ALWAYS_INLINE size_t\ns2u_lookup(size_t size)\n{\n\tsize_t ret = index2size_lookup(size2index_lookup(size));\n\n\tassert(ret == s2u_compute(size));\n\treturn (ret);\n}\n\n/*\n * Compute usable size that would result from allocating an object with the\n * specified size.\n */\nJEMALLOC_ALWAYS_INLINE size_t\ns2u(size_t size)\n{\n\n\tassert(size > 0);\n\tif (likely(size <= LOOKUP_MAXCLASS))\n\t\treturn (s2u_lookup(size));\n\treturn (s2u_compute(size));\n}\n\n/*\n * Compute usable size that would result from allocating an object with the\n * specified size and alignment.\n */\nJEMALLOC_ALWAYS_INLINE size_t\nsa2u(size_t size, size_t alignment)\n{\n\tsize_t usize;\n\n\tassert(alignment != 0 && ((alignment - 1) & alignment) == 0);\n\n\t/* Try for a small size class. */\n\tif (size <= SMALL_MAXCLASS && alignment < PAGE) {\n\t\t/*\n\t\t * Round size up to the nearest multiple of alignment.\n\t\t *\n\t\t * This done, we can take advantage of the fact that for each\n\t\t * small size class, every object is aligned at the smallest\n\t\t * power of two that is non-zero in the base two representation\n\t\t * of the size.  For example:\n\t\t *\n\t\t *   Size |   Base 2 | Minimum alignment\n\t\t *   -----+----------+------------------\n\t\t *     96 |  1100000 |  32\n\t\t *    144 | 10100000 |  32\n\t\t *    192 | 11000000 |  64\n\t\t */\n\t\tusize = s2u(ALIGNMENT_CEILING(size, alignment));\n\t\tif (usize < LARGE_MINCLASS)\n\t\t\treturn (usize);\n\t}\n\n\t/* Try for a large size class. */\n\tif (likely(size <= large_maxclass) && likely(alignment < chunksize)) {\n\t\t/*\n\t\t * We can't achieve subpage alignment, so round up alignment\n\t\t * to the minimum that can actually be supported.\n\t\t */\n\t\talignment = PAGE_CEILING(alignment);\n\n\t\t/* Make sure result is a large size class. */\n\t\tusize = (size <= LARGE_MINCLASS) ? LARGE_MINCLASS : s2u(size);\n\n\t\t/*\n\t\t * Calculate the size of the over-size run that arena_palloc()\n\t\t * would need to allocate in order to guarantee the alignment.\n\t\t */\n\t\tif (usize + large_pad + alignment - PAGE <= arena_maxrun)\n\t\t\treturn (usize);\n\t}\n\n\t/* Huge size class.  Beware of overflow. */\n\n\tif (unlikely(alignment > HUGE_MAXCLASS))\n\t\treturn (0);\n\n\t/*\n\t * We can't achieve subchunk alignment, so round up alignment to the\n\t * minimum that can actually be supported.\n\t */\n\talignment = CHUNK_CEILING(alignment);\n\n\t/* Make sure result is a huge size class. */\n\tif (size <= chunksize)\n\t\tusize = chunksize;\n\telse {\n\t\tusize = s2u(size);\n\t\tif (usize < size) {\n\t\t\t/* size_t overflow. */\n\t\t\treturn (0);\n\t\t}\n\t}\n\n\t/*\n\t * Calculate the multi-chunk mapping that huge_palloc() would need in\n\t * order to guarantee the alignment.\n\t */\n\tif (usize + alignment - PAGE < usize) {\n\t\t/* size_t overflow. */\n\t\treturn (0);\n\t}\n\treturn (usize);\n}\n\n/* Choose an arena based on a per-thread value. */\nJEMALLOC_INLINE arena_t *\narena_choose_impl(tsd_t *tsd, arena_t *arena, bool internal)\n{\n\tarena_t *ret;\n\n\tif (arena != NULL)\n\t\treturn (arena);\n\n\tret = internal ? tsd_iarena_get(tsd) : tsd_arena_get(tsd);\n\tif (unlikely(ret == NULL))\n\t\tret = arena_choose_hard(tsd, internal);\n\n\treturn (ret);\n}\n\nJEMALLOC_INLINE arena_t *\narena_choose(tsd_t *tsd, arena_t *arena)\n{\n\n\treturn (arena_choose_impl(tsd, arena, false));\n}\n\nJEMALLOC_INLINE arena_t *\narena_ichoose(tsdn_t *tsdn, arena_t *arena)\n{\n\n\tassert(!tsdn_null(tsdn) || arena != NULL);\n\n\tif (!tsdn_null(tsdn))\n\t\treturn (arena_choose_impl(tsdn_tsd(tsdn), NULL, true));\n\treturn (arena);\n}\n\nJEMALLOC_INLINE arena_tdata_t *\narena_tdata_get(tsd_t *tsd, unsigned ind, bool refresh_if_missing)\n{\n\tarena_tdata_t *tdata;\n\tarena_tdata_t *arenas_tdata = tsd_arenas_tdata_get(tsd);\n\n\tif (unlikely(arenas_tdata == NULL)) {\n\t\t/* arenas_tdata hasn't been initialized yet. */\n\t\treturn (arena_tdata_get_hard(tsd, ind));\n\t}\n\tif (unlikely(ind >= tsd_narenas_tdata_get(tsd))) {\n\t\t/*\n\t\t * ind is invalid, cache is old (too small), or tdata to be\n\t\t * initialized.\n\t\t */\n\t\treturn (refresh_if_missing ? arena_tdata_get_hard(tsd, ind) :\n\t\t    NULL);\n\t}\n\n\ttdata = &arenas_tdata[ind];\n\tif (likely(tdata != NULL) || !refresh_if_missing)\n\t\treturn (tdata);\n\treturn (arena_tdata_get_hard(tsd, ind));\n}\n\nJEMALLOC_INLINE arena_t *\narena_get(tsdn_t *tsdn, unsigned ind, bool init_if_missing)\n{\n\tarena_t *ret;\n\n\tassert(ind <= MALLOCX_ARENA_MAX);\n\n\tret = arenas[ind];\n\tif (unlikely(ret == NULL)) {\n\t\tret = atomic_read_p((void *)&arenas[ind]);\n\t\tif (init_if_missing && unlikely(ret == NULL))\n\t\t\tret = arena_init(tsdn, ind);\n\t}\n\treturn (ret);\n}\n\nJEMALLOC_INLINE ticker_t *\ndecay_ticker_get(tsd_t *tsd, unsigned ind)\n{\n\tarena_tdata_t *tdata;\n\n\ttdata = arena_tdata_get(tsd, ind, true);\n\tif (unlikely(tdata == NULL))\n\t\treturn (NULL);\n\treturn (&tdata->decay_ticker);\n}\n#endif\n\n#include \"jemalloc/internal/bitmap.h\"\n/*\n * Include portions of arena.h interleaved with tcache.h in order to resolve\n * circular dependencies.\n */\n#define\tJEMALLOC_ARENA_INLINE_A\n#include \"jemalloc/internal/arena.h\"\n#undef JEMALLOC_ARENA_INLINE_A\n#include \"jemalloc/internal/tcache.h\"\n#define\tJEMALLOC_ARENA_INLINE_B\n#include \"jemalloc/internal/arena.h\"\n#undef JEMALLOC_ARENA_INLINE_B\n#include \"jemalloc/internal/hash.h\"\n#include \"jemalloc/internal/quarantine.h\"\n\n#ifndef JEMALLOC_ENABLE_INLINE\narena_t\t*iaalloc(const void *ptr);\nsize_t\tisalloc(tsdn_t *tsdn, const void *ptr, bool demote);\nvoid\t*iallocztm(tsdn_t *tsdn, size_t size, szind_t ind, bool zero,\n    tcache_t *tcache, bool is_metadata, arena_t *arena, bool slow_path);\nvoid\t*ialloc(tsd_t *tsd, size_t size, szind_t ind, bool zero,\n    bool slow_path);\nvoid\t*ipallocztm(tsdn_t *tsdn, size_t usize, size_t alignment, bool zero,\n    tcache_t *tcache, bool is_metadata, arena_t *arena);\nvoid\t*ipalloct(tsdn_t *tsdn, size_t usize, size_t alignment, bool zero,\n    tcache_t *tcache, arena_t *arena);\nvoid\t*ipalloc(tsd_t *tsd, size_t usize, size_t alignment, bool zero);\nsize_t\tivsalloc(tsdn_t *tsdn, const void *ptr, bool demote);\nsize_t\tu2rz(size_t usize);\nsize_t\tp2rz(tsdn_t *tsdn, const void *ptr);\nvoid\tidalloctm(tsdn_t *tsdn, void *ptr, tcache_t *tcache, bool is_metadata,\n    bool slow_path);\nvoid\tidalloc(tsd_t *tsd, void *ptr);\nvoid\tiqalloc(tsd_t *tsd, void *ptr, tcache_t *tcache, bool slow_path);\nvoid\tisdalloct(tsdn_t *tsdn, void *ptr, size_t size, tcache_t *tcache,\n    bool slow_path);\nvoid\tisqalloc(tsd_t *tsd, void *ptr, size_t size, tcache_t *tcache,\n    bool slow_path);\nvoid\t*iralloct_realign(tsd_t *tsd, void *ptr, size_t oldsize, size_t size,\n    size_t extra, size_t alignment, bool zero, tcache_t *tcache,\n    arena_t *arena);\nvoid\t*iralloct(tsd_t *tsd, void *ptr, size_t oldsize, size_t size,\n    size_t alignment, bool zero, tcache_t *tcache, arena_t *arena);\nvoid\t*iralloc(tsd_t *tsd, void *ptr, size_t oldsize, size_t size,\n    size_t alignment, bool zero);\nbool\tixalloc(tsdn_t *tsdn, void *ptr, size_t oldsize, size_t size,\n    size_t extra, size_t alignment, bool zero);\n#endif\n\n#if (defined(JEMALLOC_ENABLE_INLINE) || defined(JEMALLOC_C_))\nJEMALLOC_ALWAYS_INLINE arena_t *\niaalloc(const void *ptr)\n{\n\n\tassert(ptr != NULL);\n\n\treturn (arena_aalloc(ptr));\n}\n\n/*\n * Typical usage:\n *   tsdn_t *tsdn = [...]\n *   void *ptr = [...]\n *   size_t sz = isalloc(tsdn, ptr, config_prof);\n */\nJEMALLOC_ALWAYS_INLINE size_t\nisalloc(tsdn_t *tsdn, const void *ptr, bool demote)\n{\n\n\tassert(ptr != NULL);\n\t/* Demotion only makes sense if config_prof is true. */\n\tassert(config_prof || !demote);\n\n\treturn (arena_salloc(tsdn, ptr, demote));\n}\n\nJEMALLOC_ALWAYS_INLINE void *\niallocztm(tsdn_t *tsdn, size_t size, szind_t ind, bool zero, tcache_t *tcache,\n    bool is_metadata, arena_t *arena, bool slow_path)\n{\n\tvoid *ret;\n\n\tassert(size != 0);\n\tassert(!is_metadata || tcache == NULL);\n\tassert(!is_metadata || arena == NULL || arena->ind < narenas_auto);\n\n\tret = arena_malloc(tsdn, arena, size, ind, zero, tcache, slow_path);\n\tif (config_stats && is_metadata && likely(ret != NULL)) {\n\t\tarena_metadata_allocated_add(iaalloc(ret),\n\t\t    isalloc(tsdn, ret, config_prof));\n\t}\n\treturn (ret);\n}\n\nJEMALLOC_ALWAYS_INLINE void *\nialloc(tsd_t *tsd, size_t size, szind_t ind, bool zero, bool slow_path)\n{\n\n\treturn (iallocztm(tsd_tsdn(tsd), size, ind, zero, tcache_get(tsd, true),\n\t    false, NULL, slow_path));\n}\n\nJEMALLOC_ALWAYS_INLINE void *\nipallocztm(tsdn_t *tsdn, size_t usize, size_t alignment, bool zero,\n    tcache_t *tcache, bool is_metadata, arena_t *arena)\n{\n\tvoid *ret;\n\n\tassert(usize != 0);\n\tassert(usize == sa2u(usize, alignment));\n\tassert(!is_metadata || tcache == NULL);\n\tassert(!is_metadata || arena == NULL || arena->ind < narenas_auto);\n\n\tret = arena_palloc(tsdn, arena, usize, alignment, zero, tcache);\n\tassert(ALIGNMENT_ADDR2BASE(ret, alignment) == ret);\n\tif (config_stats && is_metadata && likely(ret != NULL)) {\n\t\tarena_metadata_allocated_add(iaalloc(ret), isalloc(tsdn, ret,\n\t\t    config_prof));\n\t}\n\treturn (ret);\n}\n\nJEMALLOC_ALWAYS_INLINE void *\nipalloct(tsdn_t *tsdn, size_t usize, size_t alignment, bool zero,\n    tcache_t *tcache, arena_t *arena)\n{\n\n\treturn (ipallocztm(tsdn, usize, alignment, zero, tcache, false, arena));\n}\n\nJEMALLOC_ALWAYS_INLINE void *\nipalloc(tsd_t *tsd, size_t usize, size_t alignment, bool zero)\n{\n\n\treturn (ipallocztm(tsd_tsdn(tsd), usize, alignment, zero,\n\t    tcache_get(tsd, true), false, NULL));\n}\n\nJEMALLOC_ALWAYS_INLINE size_t\nivsalloc(tsdn_t *tsdn, const void *ptr, bool demote)\n{\n\textent_node_t *node;\n\n\t/* Return 0 if ptr is not within a chunk managed by jemalloc. */\n\tnode = chunk_lookup(ptr, false);\n\tif (node == NULL)\n\t\treturn (0);\n\t/* Only arena chunks should be looked up via interior pointers. */\n\tassert(extent_node_addr_get(node) == ptr ||\n\t    extent_node_achunk_get(node));\n\n\treturn (isalloc(tsdn, ptr, demote));\n}\n\nJEMALLOC_INLINE size_t\nu2rz(size_t usize)\n{\n\tsize_t ret;\n\n\tif (usize <= SMALL_MAXCLASS) {\n\t\tszind_t binind = size2index(usize);\n\t\tret = arena_bin_info[binind].redzone_size;\n\t} else\n\t\tret = 0;\n\n\treturn (ret);\n}\n\nJEMALLOC_INLINE size_t\np2rz(tsdn_t *tsdn, const void *ptr)\n{\n\tsize_t usize = isalloc(tsdn, ptr, false);\n\n\treturn (u2rz(usize));\n}\n\nJEMALLOC_ALWAYS_INLINE void\nidalloctm(tsdn_t *tsdn, void *ptr, tcache_t *tcache, bool is_metadata,\n    bool slow_path)\n{\n\n\tassert(ptr != NULL);\n\tassert(!is_metadata || tcache == NULL);\n\tassert(!is_metadata || iaalloc(ptr)->ind < narenas_auto);\n\tif (config_stats && is_metadata) {\n\t\tarena_metadata_allocated_sub(iaalloc(ptr), isalloc(tsdn, ptr,\n\t\t    config_prof));\n\t}\n\n\tarena_dalloc(tsdn, ptr, tcache, slow_path);\n}\n\nJEMALLOC_ALWAYS_INLINE void\nidalloc(tsd_t *tsd, void *ptr)\n{\n\n\tidalloctm(tsd_tsdn(tsd), ptr, tcache_get(tsd, false), false, true);\n}\n\nJEMALLOC_ALWAYS_INLINE void\niqalloc(tsd_t *tsd, void *ptr, tcache_t *tcache, bool slow_path)\n{\n\n\tif (slow_path && config_fill && unlikely(opt_quarantine))\n\t\tquarantine(tsd, ptr);\n\telse\n\t\tidalloctm(tsd_tsdn(tsd), ptr, tcache, false, slow_path);\n}\n\nJEMALLOC_ALWAYS_INLINE void\nisdalloct(tsdn_t *tsdn, void *ptr, size_t size, tcache_t *tcache,\n    bool slow_path)\n{\n\n\tarena_sdalloc(tsdn, ptr, size, tcache, slow_path);\n}\n\nJEMALLOC_ALWAYS_INLINE void\nisqalloc(tsd_t *tsd, void *ptr, size_t size, tcache_t *tcache, bool slow_path)\n{\n\n\tif (slow_path && config_fill && unlikely(opt_quarantine))\n\t\tquarantine(tsd, ptr);\n\telse\n\t\tisdalloct(tsd_tsdn(tsd), ptr, size, tcache, slow_path);\n}\n\nJEMALLOC_ALWAYS_INLINE void *\niralloct_realign(tsd_t *tsd, void *ptr, size_t oldsize, size_t size,\n    size_t extra, size_t alignment, bool zero, tcache_t *tcache, arena_t *arena)\n{\n\tvoid *p;\n\tsize_t usize, copysize;\n\n\tusize = sa2u(size + extra, alignment);\n\tif (unlikely(usize == 0 || usize > HUGE_MAXCLASS))\n\t\treturn (NULL);\n\tp = ipalloct(tsd_tsdn(tsd), usize, alignment, zero, tcache, arena);\n\tif (p == NULL) {\n\t\tif (extra == 0)\n\t\t\treturn (NULL);\n\t\t/* Try again, without extra this time. */\n\t\tusize = sa2u(size, alignment);\n\t\tif (unlikely(usize == 0 || usize > HUGE_MAXCLASS))\n\t\t\treturn (NULL);\n\t\tp = ipalloct(tsd_tsdn(tsd), usize, alignment, zero, tcache,\n\t\t    arena);\n\t\tif (p == NULL)\n\t\t\treturn (NULL);\n\t}\n\t/*\n\t * Copy at most size bytes (not size+extra), since the caller has no\n\t * expectation that the extra bytes will be reliably preserved.\n\t */\n\tcopysize = (size < oldsize) ? size : oldsize;\n\tmemcpy(p, ptr, copysize);\n\tisqalloc(tsd, ptr, oldsize, tcache, true);\n\treturn (p);\n}\n\nJEMALLOC_ALWAYS_INLINE void *\niralloct(tsd_t *tsd, void *ptr, size_t oldsize, size_t size, size_t alignment,\n    bool zero, tcache_t *tcache, arena_t *arena)\n{\n\n\tassert(ptr != NULL);\n\tassert(size != 0);\n\n\tif (alignment != 0 && ((uintptr_t)ptr & ((uintptr_t)alignment-1))\n\t    != 0) {\n\t\t/*\n\t\t * Existing object alignment is inadequate; allocate new space\n\t\t * and copy.\n\t\t */\n\t\treturn (iralloct_realign(tsd, ptr, oldsize, size, 0, alignment,\n\t\t    zero, tcache, arena));\n\t}\n\n\treturn (arena_ralloc(tsd, arena, ptr, oldsize, size, alignment, zero,\n\t    tcache));\n}\n\nJEMALLOC_ALWAYS_INLINE void *\niralloc(tsd_t *tsd, void *ptr, size_t oldsize, size_t size, size_t alignment,\n    bool zero)\n{\n\n\treturn (iralloct(tsd, ptr, oldsize, size, alignment, zero,\n\t    tcache_get(tsd, true), NULL));\n}\n\nJEMALLOC_ALWAYS_INLINE bool\nixalloc(tsdn_t *tsdn, void *ptr, size_t oldsize, size_t size, size_t extra,\n    size_t alignment, bool zero)\n{\n\n\tassert(ptr != NULL);\n\tassert(size != 0);\n\n\tif (alignment != 0 && ((uintptr_t)ptr & ((uintptr_t)alignment-1))\n\t    != 0) {\n\t\t/* Existing object alignment is inadequate. */\n\t\treturn (true);\n\t}\n\n\treturn (arena_ralloc_no_move(tsdn, ptr, oldsize, size, extra, zero));\n}\n#endif\n\n#include \"jemalloc/internal/prof.h\"\n\n#undef JEMALLOC_H_INLINES\n/******************************************************************************/\n#endif /* JEMALLOC_INTERNAL_H */\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/deps/jemalloc/include/jemalloc/internal/jemalloc_internal_decls.h",
    "content": "#ifndef JEMALLOC_INTERNAL_DECLS_H\n#define\tJEMALLOC_INTERNAL_DECLS_H\n\n#include <math.h>\n#ifdef _WIN32\n#  include <windows.h>\n#  include \"msvc_compat/windows_extra.h\"\n\n#else\n#  include <sys/param.h>\n#  include <sys/mman.h>\n#  if !defined(__pnacl__) && !defined(__native_client__)\n#    include <sys/syscall.h>\n#    if !defined(SYS_write) && defined(__NR_write)\n#      define SYS_write __NR_write\n#    endif\n#    include <sys/uio.h>\n#  endif\n#  include <pthread.h>\n#  include <errno.h>\n#  include <sys/time.h>\n#endif\n#include <sys/types.h>\n\n#include <limits.h>\n#ifndef SIZE_T_MAX\n#  define SIZE_T_MAX\tSIZE_MAX\n#endif\n#include <stdarg.h>\n#include <stdbool.h>\n#include <stdio.h>\n#include <stdlib.h>\n#include <stdint.h>\n#include <stddef.h>\n#ifndef offsetof\n#  define offsetof(type, member)\t((size_t)&(((type *)NULL)->member))\n#endif\n#include <string.h>\n#include <strings.h>\n#include <ctype.h>\n#ifdef _MSC_VER\n#  include <io.h>\ntypedef intptr_t ssize_t;\n#  define PATH_MAX 1024\n#  define STDERR_FILENO 2\n#  define __func__ __FUNCTION__\n#  ifdef JEMALLOC_HAS_RESTRICT\n#    define restrict __restrict\n#  endif\n/* Disable warnings about deprecated system functions. */\n#  pragma warning(disable: 4996)\n#if _MSC_VER < 1800\nstatic int\nisblank(int c)\n{\n\n\treturn (c == '\\t' || c == ' ');\n}\n#endif\n#else\n#  include <unistd.h>\n#endif\n#include <fcntl.h>\n\n#endif /* JEMALLOC_INTERNAL_H */\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/deps/jemalloc/include/jemalloc/internal/jemalloc_internal_defs.h.in",
    "content": "#ifndef JEMALLOC_INTERNAL_DEFS_H_\n#define\tJEMALLOC_INTERNAL_DEFS_H_\n/*\n * If JEMALLOC_PREFIX is defined via --with-jemalloc-prefix, it will cause all\n * public APIs to be prefixed.  This makes it possible, with some care, to use\n * multiple allocators simultaneously.\n */\n#undef JEMALLOC_PREFIX\n#undef JEMALLOC_CPREFIX\n\n/*\n * JEMALLOC_PRIVATE_NAMESPACE is used as a prefix for all library-private APIs.\n * For shared libraries, symbol visibility mechanisms prevent these symbols\n * from being exported, but for static libraries, naming collisions are a real\n * possibility.\n */\n#undef JEMALLOC_PRIVATE_NAMESPACE\n\n/*\n * Hyper-threaded CPUs may need a special instruction inside spin loops in\n * order to yield to another virtual CPU.\n */\n#undef CPU_SPINWAIT\n\n/* Defined if C11 atomics are available. */\n#undef JEMALLOC_C11ATOMICS\n\n/* Defined if the equivalent of FreeBSD's atomic(9) functions are available. */\n#undef JEMALLOC_ATOMIC9\n\n/*\n * Defined if OSAtomic*() functions are available, as provided by Darwin, and\n * documented in the atomic(3) manual page.\n */\n#undef JEMALLOC_OSATOMIC\n\n/*\n * Defined if __sync_add_and_fetch(uint32_t *, uint32_t) and\n * __sync_sub_and_fetch(uint32_t *, uint32_t) are available, despite\n * __GCC_HAVE_SYNC_COMPARE_AND_SWAP_4 not being defined (which means the\n * functions are defined in libgcc instead of being inlines).\n */\n#undef JE_FORCE_SYNC_COMPARE_AND_SWAP_4\n\n/*\n * Defined if __sync_add_and_fetch(uint64_t *, uint64_t) and\n * __sync_sub_and_fetch(uint64_t *, uint64_t) are available, despite\n * __GCC_HAVE_SYNC_COMPARE_AND_SWAP_8 not being defined (which means the\n * functions are defined in libgcc instead of being inlines).\n */\n#undef JE_FORCE_SYNC_COMPARE_AND_SWAP_8\n\n/*\n * Defined if __builtin_clz() and __builtin_clzl() are available.\n */\n#undef JEMALLOC_HAVE_BUILTIN_CLZ\n\n/*\n * Defined if madvise(2) is available.\n */\n#undef JEMALLOC_HAVE_MADVISE\n\n/*\n * Defined if OSSpin*() functions are available, as provided by Darwin, and\n * documented in the spinlock(3) manual page.\n */\n#undef JEMALLOC_OSSPIN\n\n/*\n * Defined if secure_getenv(3) is available.\n */\n#undef JEMALLOC_HAVE_SECURE_GETENV\n\n/*\n * Defined if issetugid(2) is available.\n */\n#undef JEMALLOC_HAVE_ISSETUGID\n\n/*\n * Defined if _malloc_thread_cleanup() exists.  At least in the case of\n * FreeBSD, pthread_key_create() allocates, which if used during malloc\n * bootstrapping will cause recursion into the pthreads library.  Therefore, if\n * _malloc_thread_cleanup() exists, use it as the basis for thread cleanup in\n * malloc_tsd.\n */\n#undef JEMALLOC_MALLOC_THREAD_CLEANUP\n\n/*\n * Defined if threaded initialization is known to be safe on this platform.\n * Among other things, it must be possible to initialize a mutex without\n * triggering allocation in order for threaded allocation to be safe.\n */\n#undef JEMALLOC_THREADED_INIT\n\n/*\n * Defined if the pthreads implementation defines\n * _pthread_mutex_init_calloc_cb(), in which case the function is used in order\n * to avoid recursive allocation during mutex initialization.\n */\n#undef JEMALLOC_MUTEX_INIT_CB\n\n/* Non-empty if the tls_model attribute is supported. */\n#undef JEMALLOC_TLS_MODEL\n\n/* JEMALLOC_CC_SILENCE enables code that silences unuseful compiler warnings. */\n#undef JEMALLOC_CC_SILENCE\n\n/* JEMALLOC_CODE_COVERAGE enables test code coverage analysis. */\n#undef JEMALLOC_CODE_COVERAGE\n\n/*\n * JEMALLOC_DEBUG enables assertions and other sanity checks, and disables\n * inline functions.\n */\n#undef JEMALLOC_DEBUG\n\n/* JEMALLOC_STATS enables statistics calculation. */\n#undef JEMALLOC_STATS\n\n/* JEMALLOC_PROF enables allocation profiling. */\n#undef JEMALLOC_PROF\n\n/* Use libunwind for profile backtracing if defined. */\n#undef JEMALLOC_PROF_LIBUNWIND\n\n/* Use libgcc for profile backtracing if defined. */\n#undef JEMALLOC_PROF_LIBGCC\n\n/* Use gcc intrinsics for profile backtracing if defined. */\n#undef JEMALLOC_PROF_GCC\n\n/*\n * JEMALLOC_TCACHE enables a thread-specific caching layer for small objects.\n * This makes it possible to allocate/deallocate objects without any locking\n * when the cache is in the steady state.\n */\n#undef JEMALLOC_TCACHE\n\n/*\n * JEMALLOC_DSS enables use of sbrk(2) to allocate chunks from the data storage\n * segment (DSS).\n */\n#undef JEMALLOC_DSS\n\n/* Support memory filling (junk/zero/quarantine/redzone). */\n#undef JEMALLOC_FILL\n\n/* Support utrace(2)-based tracing. */\n#undef JEMALLOC_UTRACE\n\n/* Support Valgrind. */\n#undef JEMALLOC_VALGRIND\n\n/* Support optional abort() on OOM. */\n#undef JEMALLOC_XMALLOC\n\n/* Support lazy locking (avoid locking unless a second thread is launched). */\n#undef JEMALLOC_LAZY_LOCK\n\n/* Minimum size class to support is 2^LG_TINY_MIN bytes. */\n#undef LG_TINY_MIN\n\n/*\n * Minimum allocation alignment is 2^LG_QUANTUM bytes (ignoring tiny size\n * classes).\n */\n#undef LG_QUANTUM\n\n/* One page is 2^LG_PAGE bytes. */\n#undef LG_PAGE\n\n/*\n * If defined, adjacent virtual memory mappings with identical attributes\n * automatically coalesce, and they fragment when changes are made to subranges.\n * This is the normal order of things for mmap()/munmap(), but on Windows\n * VirtualAlloc()/VirtualFree() operations must be precisely matched, i.e.\n * mappings do *not* coalesce/fragment.\n */\n#undef JEMALLOC_MAPS_COALESCE\n\n/*\n * If defined, use munmap() to unmap freed chunks, rather than storing them for\n * later reuse.  This is disabled by default on Linux because common sequences\n * of mmap()/munmap() calls will cause virtual memory map holes.\n */\n#undef JEMALLOC_MUNMAP\n\n/* TLS is used to map arenas and magazine caches to threads. */\n#undef JEMALLOC_TLS\n\n/*\n * ffs*() functions to use for bitmapping.  Don't use these directly; instead,\n * use ffs_*() from util.h.\n */\n#undef JEMALLOC_INTERNAL_FFSLL\n#undef JEMALLOC_INTERNAL_FFSL\n#undef JEMALLOC_INTERNAL_FFS\n\n/*\n * JEMALLOC_IVSALLOC enables ivsalloc(), which verifies that pointers reside\n * within jemalloc-owned chunks before dereferencing them.\n */\n#undef JEMALLOC_IVSALLOC\n\n/*\n * If defined, explicitly attempt to more uniformly distribute large allocation\n * pointer alignments across all cache indices.\n */\n#undef JEMALLOC_CACHE_OBLIVIOUS\n\n/*\n * Darwin (OS X) uses zones to work around Mach-O symbol override shortcomings.\n */\n#undef JEMALLOC_ZONE\n#undef JEMALLOC_ZONE_VERSION\n\n/*\n * Methods for determining whether the OS overcommits.\n * JEMALLOC_PROC_SYS_VM_OVERCOMMIT_MEMORY: Linux's\n *                                         /proc/sys/vm.overcommit_memory file.\n * JEMALLOC_SYSCTL_VM_OVERCOMMIT: FreeBSD's vm.overcommit sysctl.\n */\n#undef JEMALLOC_SYSCTL_VM_OVERCOMMIT\n#undef JEMALLOC_PROC_SYS_VM_OVERCOMMIT_MEMORY\n\n/*\n * Methods for purging unused pages differ between operating systems.\n *\n *   madvise(..., MADV_DONTNEED) : On Linux, this immediately discards pages,\n *                                 such that new pages will be demand-zeroed if\n *                                 the address region is later touched.\n *   madvise(..., MADV_FREE) : On FreeBSD and Darwin, this marks pages as being\n *                             unused, such that they will be discarded rather\n *                             than swapped out.\n */\n#undef JEMALLOC_PURGE_MADVISE_DONTNEED\n#undef JEMALLOC_PURGE_MADVISE_FREE\n\n/* Define if operating system has alloca.h header. */\n#undef JEMALLOC_HAS_ALLOCA_H\n\n/* C99 restrict keyword supported. */\n#undef JEMALLOC_HAS_RESTRICT\n\n/* For use by hash code. */\n#undef JEMALLOC_BIG_ENDIAN\n\n/* sizeof(int) == 2^LG_SIZEOF_INT. */\n#undef LG_SIZEOF_INT\n\n/* sizeof(long) == 2^LG_SIZEOF_LONG. */\n#undef LG_SIZEOF_LONG\n\n/* sizeof(long long) == 2^LG_SIZEOF_LONG_LONG. */\n#undef LG_SIZEOF_LONG_LONG\n\n/* sizeof(intmax_t) == 2^LG_SIZEOF_INTMAX_T. */\n#undef LG_SIZEOF_INTMAX_T\n\n/* glibc malloc hooks (__malloc_hook, __realloc_hook, __free_hook). */\n#undef JEMALLOC_GLIBC_MALLOC_HOOK\n\n/* glibc memalign hook. */\n#undef JEMALLOC_GLIBC_MEMALIGN_HOOK\n\n/* Adaptive mutex support in pthreads. */\n#undef JEMALLOC_HAVE_PTHREAD_MUTEX_ADAPTIVE_NP\n\n/*\n * If defined, jemalloc symbols are not exported (doesn't work when\n * JEMALLOC_PREFIX is not defined).\n */\n#undef JEMALLOC_EXPORT\n\n/* config.malloc_conf options string. */\n#undef JEMALLOC_CONFIG_MALLOC_CONF\n\n#endif /* JEMALLOC_INTERNAL_DEFS_H_ */\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/deps/jemalloc/include/jemalloc/internal/jemalloc_internal_macros.h",
    "content": "/*\n * JEMALLOC_ALWAYS_INLINE and JEMALLOC_INLINE are used within header files for\n * functions that are static inline functions if inlining is enabled, and\n * single-definition library-private functions if inlining is disabled.\n *\n * JEMALLOC_ALWAYS_INLINE_C and JEMALLOC_INLINE_C are for use in .c files, in\n * which case the denoted functions are always static, regardless of whether\n * inlining is enabled.\n */\n#if defined(JEMALLOC_DEBUG) || defined(JEMALLOC_CODE_COVERAGE)\n   /* Disable inlining to make debugging/profiling easier. */\n#  define JEMALLOC_ALWAYS_INLINE\n#  define JEMALLOC_ALWAYS_INLINE_C static\n#  define JEMALLOC_INLINE\n#  define JEMALLOC_INLINE_C static\n#  define inline\n#else\n#  define JEMALLOC_ENABLE_INLINE\n#  ifdef JEMALLOC_HAVE_ATTR\n#    define JEMALLOC_ALWAYS_INLINE \\\n\t static inline JEMALLOC_ATTR(unused) JEMALLOC_ATTR(always_inline)\n#    define JEMALLOC_ALWAYS_INLINE_C \\\n\t static inline JEMALLOC_ATTR(always_inline)\n#  else\n#    define JEMALLOC_ALWAYS_INLINE static inline\n#    define JEMALLOC_ALWAYS_INLINE_C static inline\n#  endif\n#  define JEMALLOC_INLINE static inline\n#  define JEMALLOC_INLINE_C static inline\n#  ifdef _MSC_VER\n#    define inline _inline\n#  endif\n#endif\n\n#ifdef JEMALLOC_CC_SILENCE\n#  define UNUSED JEMALLOC_ATTR(unused)\n#else\n#  define UNUSED\n#endif\n\n#define\tZU(z)\t((size_t)z)\n#define\tZI(z)\t((ssize_t)z)\n#define\tQU(q)\t((uint64_t)q)\n#define\tQI(q)\t((int64_t)q)\n\n#define\tKZU(z)\tZU(z##ULL)\n#define\tKZI(z)\tZI(z##LL)\n#define\tKQU(q)\tQU(q##ULL)\n#define\tKQI(q)\tQI(q##LL)\n\n#ifndef __DECONST\n#  define\t__DECONST(type, var)\t((type)(uintptr_t)(const void *)(var))\n#endif\n\n#ifndef JEMALLOC_HAS_RESTRICT\n#  define restrict\n#endif\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/deps/jemalloc/include/jemalloc/internal/mb.h",
    "content": "/******************************************************************************/\n#ifdef JEMALLOC_H_TYPES\n\n#endif /* JEMALLOC_H_TYPES */\n/******************************************************************************/\n#ifdef JEMALLOC_H_STRUCTS\n\n#endif /* JEMALLOC_H_STRUCTS */\n/******************************************************************************/\n#ifdef JEMALLOC_H_EXTERNS\n\n#endif /* JEMALLOC_H_EXTERNS */\n/******************************************************************************/\n#ifdef JEMALLOC_H_INLINES\n\n#ifndef JEMALLOC_ENABLE_INLINE\nvoid\tmb_write(void);\n#endif\n\n#if (defined(JEMALLOC_ENABLE_INLINE) || defined(JEMALLOC_MB_C_))\n#ifdef __i386__\n/*\n * According to the Intel Architecture Software Developer's Manual, current\n * processors execute instructions in order from the perspective of other\n * processors in a multiprocessor system, but 1) Intel reserves the right to\n * change that, and 2) the compiler's optimizer could re-order instructions if\n * there weren't some form of barrier.  Therefore, even if running on an\n * architecture that does not need memory barriers (everything through at least\n * i686), an \"optimizer barrier\" is necessary.\n */\nJEMALLOC_INLINE void\nmb_write(void)\n{\n\n#  if 0\n\t/* This is a true memory barrier. */\n\tasm volatile (\"pusha;\"\n\t    \"xor  %%eax,%%eax;\"\n\t    \"cpuid;\"\n\t    \"popa;\"\n\t    : /* Outputs. */\n\t    : /* Inputs. */\n\t    : \"memory\" /* Clobbers. */\n\t    );\n#  else\n\t/*\n\t * This is hopefully enough to keep the compiler from reordering\n\t * instructions around this one.\n\t */\n\tasm volatile (\"nop;\"\n\t    : /* Outputs. */\n\t    : /* Inputs. */\n\t    : \"memory\" /* Clobbers. */\n\t    );\n#  endif\n}\n#elif (defined(__amd64__) || defined(__x86_64__))\nJEMALLOC_INLINE void\nmb_write(void)\n{\n\n\tasm volatile (\"sfence\"\n\t    : /* Outputs. */\n\t    : /* Inputs. */\n\t    : \"memory\" /* Clobbers. */\n\t    );\n}\n#elif defined(__powerpc__)\nJEMALLOC_INLINE void\nmb_write(void)\n{\n\n\tasm volatile (\"eieio\"\n\t    : /* Outputs. */\n\t    : /* Inputs. */\n\t    : \"memory\" /* Clobbers. */\n\t    );\n}\n#elif defined(__sparc64__)\nJEMALLOC_INLINE void\nmb_write(void)\n{\n\n\tasm volatile (\"membar #StoreStore\"\n\t    : /* Outputs. */\n\t    : /* Inputs. */\n\t    : \"memory\" /* Clobbers. */\n\t    );\n}\n#elif defined(__tile__)\nJEMALLOC_INLINE void\nmb_write(void)\n{\n\n\t__sync_synchronize();\n}\n#else\n/*\n * This is much slower than a simple memory barrier, but the semantics of mutex\n * unlock make this work.\n */\nJEMALLOC_INLINE void\nmb_write(void)\n{\n\tmalloc_mutex_t mtx;\n\n\tmalloc_mutex_init(&mtx, \"mb\", WITNESS_RANK_OMIT);\n\tmalloc_mutex_lock(NULL, &mtx);\n\tmalloc_mutex_unlock(NULL, &mtx);\n}\n#endif\n#endif\n\n#endif /* JEMALLOC_H_INLINES */\n/******************************************************************************/\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/deps/jemalloc/include/jemalloc/internal/mutex.h",
    "content": "/******************************************************************************/\n#ifdef JEMALLOC_H_TYPES\n\ntypedef struct malloc_mutex_s malloc_mutex_t;\n\n#ifdef _WIN32\n#  define MALLOC_MUTEX_INITIALIZER\n#elif (defined(JEMALLOC_OSSPIN))\n#  define MALLOC_MUTEX_INITIALIZER {0, WITNESS_INITIALIZER(WITNESS_RANK_OMIT)}\n#elif (defined(JEMALLOC_MUTEX_INIT_CB))\n#  define MALLOC_MUTEX_INITIALIZER\t\t\t\t\t\\\n    {PTHREAD_MUTEX_INITIALIZER, NULL, WITNESS_INITIALIZER(WITNESS_RANK_OMIT)}\n#else\n#  if (defined(JEMALLOC_HAVE_PTHREAD_MUTEX_ADAPTIVE_NP) &&\t\t\\\n       defined(PTHREAD_ADAPTIVE_MUTEX_INITIALIZER_NP))\n#    define MALLOC_MUTEX_TYPE PTHREAD_MUTEX_ADAPTIVE_NP\n#    define MALLOC_MUTEX_INITIALIZER\t\t\t\t\t\\\n       {PTHREAD_ADAPTIVE_MUTEX_INITIALIZER_NP,\t\t\t\t\\\n        WITNESS_INITIALIZER(WITNESS_RANK_OMIT)}\n#  else\n#    define MALLOC_MUTEX_TYPE PTHREAD_MUTEX_DEFAULT\n#    define MALLOC_MUTEX_INITIALIZER\t\t\t\t\t\\\n       {PTHREAD_MUTEX_INITIALIZER, WITNESS_INITIALIZER(WITNESS_RANK_OMIT)}\n#  endif\n#endif\n\n#endif /* JEMALLOC_H_TYPES */\n/******************************************************************************/\n#ifdef JEMALLOC_H_STRUCTS\n\nstruct malloc_mutex_s {\n#ifdef _WIN32\n#  if _WIN32_WINNT >= 0x0600\n\tSRWLOCK         \tlock;\n#  else\n\tCRITICAL_SECTION\tlock;\n#  endif\n#elif (defined(JEMALLOC_OSSPIN))\n\tOSSpinLock\t\tlock;\n#elif (defined(JEMALLOC_MUTEX_INIT_CB))\n\tpthread_mutex_t\t\tlock;\n\tmalloc_mutex_t\t\t*postponed_next;\n#else\n\tpthread_mutex_t\t\tlock;\n#endif\n\twitness_t\t\twitness;\n};\n\n#endif /* JEMALLOC_H_STRUCTS */\n/******************************************************************************/\n#ifdef JEMALLOC_H_EXTERNS\n\n#ifdef JEMALLOC_LAZY_LOCK\nextern bool isthreaded;\n#else\n#  undef isthreaded /* Undo private_namespace.h definition. */\n#  define isthreaded true\n#endif\n\nbool\tmalloc_mutex_init(malloc_mutex_t *mutex, const char *name,\n    witness_rank_t rank);\nvoid\tmalloc_mutex_prefork(tsdn_t *tsdn, malloc_mutex_t *mutex);\nvoid\tmalloc_mutex_postfork_parent(tsdn_t *tsdn, malloc_mutex_t *mutex);\nvoid\tmalloc_mutex_postfork_child(tsdn_t *tsdn, malloc_mutex_t *mutex);\nbool\tmalloc_mutex_boot(void);\n\n#endif /* JEMALLOC_H_EXTERNS */\n/******************************************************************************/\n#ifdef JEMALLOC_H_INLINES\n\n#ifndef JEMALLOC_ENABLE_INLINE\nvoid\tmalloc_mutex_lock(tsdn_t *tsdn, malloc_mutex_t *mutex);\nvoid\tmalloc_mutex_unlock(tsdn_t *tsdn, malloc_mutex_t *mutex);\nvoid\tmalloc_mutex_assert_owner(tsdn_t *tsdn, malloc_mutex_t *mutex);\nvoid\tmalloc_mutex_assert_not_owner(tsdn_t *tsdn, malloc_mutex_t *mutex);\n#endif\n\n#if (defined(JEMALLOC_ENABLE_INLINE) || defined(JEMALLOC_MUTEX_C_))\nJEMALLOC_INLINE void\nmalloc_mutex_lock(tsdn_t *tsdn, malloc_mutex_t *mutex)\n{\n\n\tif (isthreaded) {\n\t\twitness_assert_not_owner(tsdn, &mutex->witness);\n#ifdef _WIN32\n#  if _WIN32_WINNT >= 0x0600\n\t\tAcquireSRWLockExclusive(&mutex->lock);\n#  else\n\t\tEnterCriticalSection(&mutex->lock);\n#  endif\n#elif (defined(JEMALLOC_OSSPIN))\n\t\tOSSpinLockLock(&mutex->lock);\n#else\n\t\tpthread_mutex_lock(&mutex->lock);\n#endif\n\t\twitness_lock(tsdn, &mutex->witness);\n\t}\n}\n\nJEMALLOC_INLINE void\nmalloc_mutex_unlock(tsdn_t *tsdn, malloc_mutex_t *mutex)\n{\n\n\tif (isthreaded) {\n\t\twitness_unlock(tsdn, &mutex->witness);\n#ifdef _WIN32\n#  if _WIN32_WINNT >= 0x0600\n\t\tReleaseSRWLockExclusive(&mutex->lock);\n#  else\n\t\tLeaveCriticalSection(&mutex->lock);\n#  endif\n#elif (defined(JEMALLOC_OSSPIN))\n\t\tOSSpinLockUnlock(&mutex->lock);\n#else\n\t\tpthread_mutex_unlock(&mutex->lock);\n#endif\n\t}\n}\n\nJEMALLOC_INLINE void\nmalloc_mutex_assert_owner(tsdn_t *tsdn, malloc_mutex_t *mutex)\n{\n\n\tif (isthreaded)\n\t\twitness_assert_owner(tsdn, &mutex->witness);\n}\n\nJEMALLOC_INLINE void\nmalloc_mutex_assert_not_owner(tsdn_t *tsdn, malloc_mutex_t *mutex)\n{\n\n\tif (isthreaded)\n\t\twitness_assert_not_owner(tsdn, &mutex->witness);\n}\n#endif\n\n#endif /* JEMALLOC_H_INLINES */\n/******************************************************************************/\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/deps/jemalloc/include/jemalloc/internal/nstime.h",
    "content": "/******************************************************************************/\n#ifdef JEMALLOC_H_TYPES\n\n#define\tJEMALLOC_CLOCK_GETTIME defined(_POSIX_MONOTONIC_CLOCK) \\\n    && _POSIX_MONOTONIC_CLOCK >= 0\n\ntypedef struct nstime_s nstime_t;\n\n/* Maximum supported number of seconds (~584 years). */\n#define\tNSTIME_SEC_MAX\tKQU(18446744072)\n\n#endif /* JEMALLOC_H_TYPES */\n/******************************************************************************/\n#ifdef JEMALLOC_H_STRUCTS\n\nstruct nstime_s {\n\tuint64_t\tns;\n};\n\n#endif /* JEMALLOC_H_STRUCTS */\n/******************************************************************************/\n#ifdef JEMALLOC_H_EXTERNS\n\nvoid\tnstime_init(nstime_t *time, uint64_t ns);\nvoid\tnstime_init2(nstime_t *time, uint64_t sec, uint64_t nsec);\nuint64_t\tnstime_ns(const nstime_t *time);\nuint64_t\tnstime_sec(const nstime_t *time);\nuint64_t\tnstime_nsec(const nstime_t *time);\nvoid\tnstime_copy(nstime_t *time, const nstime_t *source);\nint\tnstime_compare(const nstime_t *a, const nstime_t *b);\nvoid\tnstime_add(nstime_t *time, const nstime_t *addend);\nvoid\tnstime_subtract(nstime_t *time, const nstime_t *subtrahend);\nvoid\tnstime_imultiply(nstime_t *time, uint64_t multiplier);\nvoid\tnstime_idivide(nstime_t *time, uint64_t divisor);\nuint64_t\tnstime_divide(const nstime_t *time, const nstime_t *divisor);\n#ifdef JEMALLOC_JET\ntypedef bool (nstime_update_t)(nstime_t *);\nextern nstime_update_t *nstime_update;\n#else\nbool\tnstime_update(nstime_t *time);\n#endif\n\n#endif /* JEMALLOC_H_EXTERNS */\n/******************************************************************************/\n#ifdef JEMALLOC_H_INLINES\n\n#endif /* JEMALLOC_H_INLINES */\n/******************************************************************************/\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/deps/jemalloc/include/jemalloc/internal/pages.h",
    "content": "/******************************************************************************/\n#ifdef JEMALLOC_H_TYPES\n\n#endif /* JEMALLOC_H_TYPES */\n/******************************************************************************/\n#ifdef JEMALLOC_H_STRUCTS\n\n#endif /* JEMALLOC_H_STRUCTS */\n/******************************************************************************/\n#ifdef JEMALLOC_H_EXTERNS\n\nvoid\t*pages_map(void *addr, size_t size, bool *commit);\nvoid\tpages_unmap(void *addr, size_t size);\nvoid\t*pages_trim(void *addr, size_t alloc_size, size_t leadsize,\n    size_t size, bool *commit);\nbool\tpages_commit(void *addr, size_t size);\nbool\tpages_decommit(void *addr, size_t size);\nbool\tpages_purge(void *addr, size_t size);\nvoid\tpages_boot(void);\n\n#endif /* JEMALLOC_H_EXTERNS */\n/******************************************************************************/\n#ifdef JEMALLOC_H_INLINES\n\n#endif /* JEMALLOC_H_INLINES */\n/******************************************************************************/\n\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/deps/jemalloc/include/jemalloc/internal/ph.h",
    "content": "/*\n * A Pairing Heap implementation.\n *\n * \"The Pairing Heap: A New Form of Self-Adjusting Heap\"\n * https://www.cs.cmu.edu/~sleator/papers/pairing-heaps.pdf\n *\n * With auxiliary twopass list, described in a follow on paper.\n *\n * \"Pairing Heaps: Experiments and Analysis\"\n * http://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.106.2988&rep=rep1&type=pdf\n *\n *******************************************************************************\n */\n\n#ifndef PH_H_\n#define\tPH_H_\n\n/* Node structure. */\n#define\tphn(a_type)\t\t\t\t\t\t\t\\\nstruct {\t\t\t\t\t\t\t\t\\\n\ta_type\t*phn_prev;\t\t\t\t\t\t\\\n\ta_type\t*phn_next;\t\t\t\t\t\t\\\n\ta_type\t*phn_lchild;\t\t\t\t\t\t\\\n}\n\n/* Root structure. */\n#define\tph(a_type)\t\t\t\t\t\t\t\\\nstruct {\t\t\t\t\t\t\t\t\\\n\ta_type\t*ph_root;\t\t\t\t\t\t\\\n}\n\n/* Internal utility macros. */\n#define\tphn_lchild_get(a_type, a_field, a_phn)\t\t\t\t\\\n\t(a_phn->a_field.phn_lchild)\n#define\tphn_lchild_set(a_type, a_field, a_phn, a_lchild) do {\t\t\\\n\ta_phn->a_field.phn_lchild = a_lchild;\t\t\t\t\\\n} while (0)\n\n#define\tphn_next_get(a_type, a_field, a_phn)\t\t\t\t\\\n\t(a_phn->a_field.phn_next)\n#define\tphn_prev_set(a_type, a_field, a_phn, a_prev) do {\t\t\\\n\ta_phn->a_field.phn_prev = a_prev;\t\t\t\t\\\n} while (0)\n\n#define\tphn_prev_get(a_type, a_field, a_phn)\t\t\t\t\\\n\t(a_phn->a_field.phn_prev)\n#define\tphn_next_set(a_type, a_field, a_phn, a_next) do {\t\t\\\n\ta_phn->a_field.phn_next = a_next;\t\t\t\t\\\n} while (0)\n\n#define\tphn_merge_ordered(a_type, a_field, a_phn0, a_phn1, a_cmp) do {\t\\\n\ta_type *phn0child;\t\t\t\t\t\t\\\n\t\t\t\t\t\t\t\t\t\\\n\tassert(a_phn0 != NULL);\t\t\t\t\t\t\\\n\tassert(a_phn1 != NULL);\t\t\t\t\t\t\\\n\tassert(a_cmp(a_phn0, a_phn1) <= 0);\t\t\t\t\\\n\t\t\t\t\t\t\t\t\t\\\n\tphn_prev_set(a_type, a_field, a_phn1, a_phn0);\t\t\t\\\n\tphn0child = phn_lchild_get(a_type, a_field, a_phn0);\t\t\\\n\tphn_next_set(a_type, a_field, a_phn1, phn0child);\t\t\\\n\tif (phn0child != NULL)\t\t\t\t\t\t\\\n\t\tphn_prev_set(a_type, a_field, phn0child, a_phn1);\t\\\n\tphn_lchild_set(a_type, a_field, a_phn0, a_phn1);\t\t\\\n} while (0)\n\n#define\tphn_merge(a_type, a_field, a_phn0, a_phn1, a_cmp, r_phn) do {\t\\\n\tif (a_phn0 == NULL)\t\t\t\t\t\t\\\n\t\tr_phn = a_phn1;\t\t\t\t\t\t\\\n\telse if (a_phn1 == NULL)\t\t\t\t\t\\\n\t\tr_phn = a_phn0;\t\t\t\t\t\t\\\n\telse if (a_cmp(a_phn0, a_phn1) < 0) {\t\t\t\t\\\n\t\tphn_merge_ordered(a_type, a_field, a_phn0, a_phn1,\t\\\n\t\t    a_cmp);\t\t\t\t\t\t\\\n\t\tr_phn = a_phn0;\t\t\t\t\t\t\\\n\t} else {\t\t\t\t\t\t\t\\\n\t\tphn_merge_ordered(a_type, a_field, a_phn1, a_phn0,\t\\\n\t\t    a_cmp);\t\t\t\t\t\t\\\n\t\tr_phn = a_phn1;\t\t\t\t\t\t\\\n\t}\t\t\t\t\t\t\t\t\\\n} while (0)\n\n#define\tph_merge_siblings(a_type, a_field, a_phn, a_cmp, r_phn) do {\t\\\n\ta_type *head = NULL;\t\t\t\t\t\t\\\n\ta_type *tail = NULL;\t\t\t\t\t\t\\\n\ta_type *phn0 = a_phn;\t\t\t\t\t\t\\\n\ta_type *phn1 = phn_next_get(a_type, a_field, phn0);\t\t\\\n\t\t\t\t\t\t\t\t\t\\\n\t/*\t\t\t\t\t\t\t\t\\\n\t * Multipass merge, wherein the first two elements of a FIFO\t\\\n\t * are repeatedly merged, and each result is appended to the\t\\\n\t * singly linked FIFO, until the FIFO contains only a single\t\\\n\t * element.  We start with a sibling list but no reference to\t\\\n\t * its tail, so we do a single pass over the sibling list to\t\\\n\t * populate the FIFO.\t\t\t\t\t\t\\\n\t */\t\t\t\t\t\t\t\t\\\n\tif (phn1 != NULL) {\t\t\t\t\t\t\\\n\t\ta_type *phnrest = phn_next_get(a_type, a_field, phn1);\t\\\n\t\tif (phnrest != NULL)\t\t\t\t\t\\\n\t\t\tphn_prev_set(a_type, a_field, phnrest, NULL);\t\\\n\t\tphn_prev_set(a_type, a_field, phn0, NULL);\t\t\\\n\t\tphn_next_set(a_type, a_field, phn0, NULL);\t\t\\\n\t\tphn_prev_set(a_type, a_field, phn1, NULL);\t\t\\\n\t\tphn_next_set(a_type, a_field, phn1, NULL);\t\t\\\n\t\tphn_merge(a_type, a_field, phn0, phn1, a_cmp, phn0);\t\\\n\t\thead = tail = phn0;\t\t\t\t\t\\\n\t\tphn0 = phnrest;\t\t\t\t\t\t\\\n\t\twhile (phn0 != NULL) {\t\t\t\t\t\\\n\t\t\tphn1 = phn_next_get(a_type, a_field, phn0);\t\\\n\t\t\tif (phn1 != NULL) {\t\t\t\t\\\n\t\t\t\tphnrest = phn_next_get(a_type, a_field,\t\\\n\t\t\t\t    phn1);\t\t\t\t\\\n\t\t\t\tif (phnrest != NULL) {\t\t\t\\\n\t\t\t\t\tphn_prev_set(a_type, a_field,\t\\\n\t\t\t\t\t    phnrest, NULL);\t\t\\\n\t\t\t\t}\t\t\t\t\t\\\n\t\t\t\tphn_prev_set(a_type, a_field, phn0,\t\\\n\t\t\t\t    NULL);\t\t\t\t\\\n\t\t\t\tphn_next_set(a_type, a_field, phn0,\t\\\n\t\t\t\t    NULL);\t\t\t\t\\\n\t\t\t\tphn_prev_set(a_type, a_field, phn1,\t\\\n\t\t\t\t    NULL);\t\t\t\t\\\n\t\t\t\tphn_next_set(a_type, a_field, phn1,\t\\\n\t\t\t\t    NULL);\t\t\t\t\\\n\t\t\t\tphn_merge(a_type, a_field, phn0, phn1,\t\\\n\t\t\t\t    a_cmp, phn0);\t\t\t\\\n\t\t\t\tphn_next_set(a_type, a_field, tail,\t\\\n\t\t\t\t    phn0);\t\t\t\t\\\n\t\t\t\ttail = phn0;\t\t\t\t\\\n\t\t\t\tphn0 = phnrest;\t\t\t\t\\\n\t\t\t} else {\t\t\t\t\t\\\n\t\t\t\tphn_next_set(a_type, a_field, tail,\t\\\n\t\t\t\t    phn0);\t\t\t\t\\\n\t\t\t\ttail = phn0;\t\t\t\t\\\n\t\t\t\tphn0 = NULL;\t\t\t\t\\\n\t\t\t}\t\t\t\t\t\t\\\n\t\t}\t\t\t\t\t\t\t\\\n\t\tphn0 = head;\t\t\t\t\t\t\\\n\t\tphn1 = phn_next_get(a_type, a_field, phn0);\t\t\\\n\t\tif (phn1 != NULL) {\t\t\t\t\t\\\n\t\t\twhile (true) {\t\t\t\t\t\\\n\t\t\t\thead = phn_next_get(a_type, a_field,\t\\\n\t\t\t\t    phn1);\t\t\t\t\\\n\t\t\t\tassert(phn_prev_get(a_type, a_field,\t\\\n\t\t\t\t    phn0) == NULL);\t\t\t\\\n\t\t\t\tphn_next_set(a_type, a_field, phn0,\t\\\n\t\t\t\t    NULL);\t\t\t\t\\\n\t\t\t\tassert(phn_prev_get(a_type, a_field,\t\\\n\t\t\t\t    phn1) == NULL);\t\t\t\\\n\t\t\t\tphn_next_set(a_type, a_field, phn1,\t\\\n\t\t\t\t    NULL);\t\t\t\t\\\n\t\t\t\tphn_merge(a_type, a_field, phn0, phn1,\t\\\n\t\t\t\t    a_cmp, phn0);\t\t\t\\\n\t\t\t\tif (head == NULL)\t\t\t\\\n\t\t\t\t\tbreak;\t\t\t\t\\\n\t\t\t\tphn_next_set(a_type, a_field, tail,\t\\\n\t\t\t\t    phn0);\t\t\t\t\\\n\t\t\t\ttail = phn0;\t\t\t\t\\\n\t\t\t\tphn0 = head;\t\t\t\t\\\n\t\t\t\tphn1 = phn_next_get(a_type, a_field,\t\\\n\t\t\t\t    phn0);\t\t\t\t\\\n\t\t\t}\t\t\t\t\t\t\\\n\t\t}\t\t\t\t\t\t\t\\\n\t}\t\t\t\t\t\t\t\t\\\n\tr_phn = phn0;\t\t\t\t\t\t\t\\\n} while (0)\n\n#define\tph_merge_aux(a_type, a_field, a_ph, a_cmp) do {\t\t\t\\\n\ta_type *phn = phn_next_get(a_type, a_field, a_ph->ph_root);\t\\\n\tif (phn != NULL) {\t\t\t\t\t\t\\\n\t\tphn_prev_set(a_type, a_field, a_ph->ph_root, NULL);\t\\\n\t\tphn_next_set(a_type, a_field, a_ph->ph_root, NULL);\t\\\n\t\tphn_prev_set(a_type, a_field, phn, NULL);\t\t\\\n\t\tph_merge_siblings(a_type, a_field, phn, a_cmp, phn);\t\\\n\t\tassert(phn_next_get(a_type, a_field, phn) == NULL);\t\\\n\t\tphn_merge(a_type, a_field, a_ph->ph_root, phn, a_cmp,\t\\\n\t\t    a_ph->ph_root);\t\t\t\t\t\\\n\t}\t\t\t\t\t\t\t\t\\\n} while (0)\n\n#define\tph_merge_children(a_type, a_field, a_phn, a_cmp, r_phn) do {\t\\\n\ta_type *lchild = phn_lchild_get(a_type, a_field, a_phn);\t\\\n\tif (lchild == NULL)\t\t\t\t\t\t\\\n\t\tr_phn = NULL;\t\t\t\t\t\t\\\n\telse {\t\t\t\t\t\t\t\t\\\n\t\tph_merge_siblings(a_type, a_field, lchild, a_cmp,\t\\\n\t\t    r_phn);\t\t\t\t\t\t\\\n\t}\t\t\t\t\t\t\t\t\\\n} while (0)\n\n/*\n * The ph_proto() macro generates function prototypes that correspond to the\n * functions generated by an equivalently parameterized call to ph_gen().\n */\n#define\tph_proto(a_attr, a_prefix, a_ph_type, a_type)\t\t\t\\\na_attr void\ta_prefix##new(a_ph_type *ph);\t\t\t\t\\\na_attr bool\ta_prefix##empty(a_ph_type *ph);\t\t\t\t\\\na_attr a_type\t*a_prefix##first(a_ph_type *ph);\t\t\t\\\na_attr void\ta_prefix##insert(a_ph_type *ph, a_type *phn);\t\t\\\na_attr a_type\t*a_prefix##remove_first(a_ph_type *ph);\t\t\t\\\na_attr void\ta_prefix##remove(a_ph_type *ph, a_type *phn);\n\n/*\n * The ph_gen() macro generates a type-specific pairing heap implementation,\n * based on the above cpp macros.\n */\n#define\tph_gen(a_attr, a_prefix, a_ph_type, a_type, a_field, a_cmp)\t\\\na_attr void\t\t\t\t\t\t\t\t\\\na_prefix##new(a_ph_type *ph)\t\t\t\t\t\t\\\n{\t\t\t\t\t\t\t\t\t\\\n\t\t\t\t\t\t\t\t\t\\\n\tmemset(ph, 0, sizeof(ph(a_type)));\t\t\t\t\\\n}\t\t\t\t\t\t\t\t\t\\\na_attr bool\t\t\t\t\t\t\t\t\\\na_prefix##empty(a_ph_type *ph)\t\t\t\t\t\t\\\n{\t\t\t\t\t\t\t\t\t\\\n\t\t\t\t\t\t\t\t\t\\\n\treturn (ph->ph_root == NULL);\t\t\t\t\t\\\n}\t\t\t\t\t\t\t\t\t\\\na_attr a_type *\t\t\t\t\t\t\t\t\\\na_prefix##first(a_ph_type *ph)\t\t\t\t\t\t\\\n{\t\t\t\t\t\t\t\t\t\\\n\t\t\t\t\t\t\t\t\t\\\n\tif (ph->ph_root == NULL)\t\t\t\t\t\\\n\t\treturn (NULL);\t\t\t\t\t\t\\\n\tph_merge_aux(a_type, a_field, ph, a_cmp);\t\t\t\\\n\treturn (ph->ph_root);\t\t\t\t\t\t\\\n}\t\t\t\t\t\t\t\t\t\\\na_attr void\t\t\t\t\t\t\t\t\\\na_prefix##insert(a_ph_type *ph, a_type *phn)\t\t\t\t\\\n{\t\t\t\t\t\t\t\t\t\\\n\t\t\t\t\t\t\t\t\t\\\n\tmemset(&phn->a_field, 0, sizeof(phn(a_type)));\t\t\t\\\n\t\t\t\t\t\t\t\t\t\\\n\t/*\t\t\t\t\t\t\t\t\\\n\t * Treat the root as an aux list during insertion, and lazily\t\\\n\t * merge during a_prefix##remove_first().  For elements that\t\\\n\t * are inserted, then removed via a_prefix##remove() before the\t\\\n\t * aux list is ever processed, this makes insert/remove\t\t\\\n\t * constant-time, whereas eager merging would make insert\t\\\n\t * O(log n).\t\t\t\t\t\t\t\\\n\t */\t\t\t\t\t\t\t\t\\\n\tif (ph->ph_root == NULL)\t\t\t\t\t\\\n\t\tph->ph_root = phn;\t\t\t\t\t\\\n\telse {\t\t\t\t\t\t\t\t\\\n\t\tphn_next_set(a_type, a_field, phn, phn_next_get(a_type,\t\\\n\t\t    a_field, ph->ph_root));\t\t\t\t\\\n\t\tif (phn_next_get(a_type, a_field, ph->ph_root) !=\t\\\n\t\t    NULL) {\t\t\t\t\t\t\\\n\t\t\tphn_prev_set(a_type, a_field,\t\t\t\\\n\t\t\t    phn_next_get(a_type, a_field, ph->ph_root),\t\\\n\t\t\t    phn);\t\t\t\t\t\\\n\t\t}\t\t\t\t\t\t\t\\\n\t\tphn_prev_set(a_type, a_field, phn, ph->ph_root);\t\\\n\t\tphn_next_set(a_type, a_field, ph->ph_root, phn);\t\\\n\t}\t\t\t\t\t\t\t\t\\\n}\t\t\t\t\t\t\t\t\t\\\na_attr a_type *\t\t\t\t\t\t\t\t\\\na_prefix##remove_first(a_ph_type *ph)\t\t\t\t\t\\\n{\t\t\t\t\t\t\t\t\t\\\n\ta_type *ret;\t\t\t\t\t\t\t\\\n\t\t\t\t\t\t\t\t\t\\\n\tif (ph->ph_root == NULL)\t\t\t\t\t\\\n\t\treturn (NULL);\t\t\t\t\t\t\\\n\tph_merge_aux(a_type, a_field, ph, a_cmp);\t\t\t\\\n\t\t\t\t\t\t\t\t\t\\\n\tret = ph->ph_root;\t\t\t\t\t\t\\\n\t\t\t\t\t\t\t\t\t\\\n\tph_merge_children(a_type, a_field, ph->ph_root, a_cmp,\t\t\\\n\t    ph->ph_root);\t\t\t\t\t\t\\\n\t\t\t\t\t\t\t\t\t\\\n\treturn (ret);\t\t\t\t\t\t\t\\\n}\t\t\t\t\t\t\t\t\t\\\na_attr void\t\t\t\t\t\t\t\t\\\na_prefix##remove(a_ph_type *ph, a_type *phn)\t\t\t\t\\\n{\t\t\t\t\t\t\t\t\t\\\n\ta_type *replace, *parent;\t\t\t\t\t\\\n\t\t\t\t\t\t\t\t\t\\\n\t/*\t\t\t\t\t\t\t\t\\\n\t * We can delete from aux list without merging it, but we need\t\\\n\t * to merge if we are dealing with the root node.\t\t\\\n\t */\t\t\t\t\t\t\t\t\\\n\tif (ph->ph_root == phn) {\t\t\t\t\t\\\n\t\tph_merge_aux(a_type, a_field, ph, a_cmp);\t\t\\\n\t\tif (ph->ph_root == phn) {\t\t\t\t\\\n\t\t\tph_merge_children(a_type, a_field, ph->ph_root,\t\\\n\t\t\t    a_cmp, ph->ph_root);\t\t\t\\\n\t\t\treturn;\t\t\t\t\t\t\\\n\t\t}\t\t\t\t\t\t\t\\\n\t}\t\t\t\t\t\t\t\t\\\n\t\t\t\t\t\t\t\t\t\\\n\t/* Get parent (if phn is leftmost child) before mutating. */\t\\\n\tif ((parent = phn_prev_get(a_type, a_field, phn)) != NULL) {\t\\\n\t\tif (phn_lchild_get(a_type, a_field, parent) != phn)\t\\\n\t\t\tparent = NULL;\t\t\t\t\t\\\n\t}\t\t\t\t\t\t\t\t\\\n\t/* Find a possible replacement node, and link to parent. */\t\\\n\tph_merge_children(a_type, a_field, phn, a_cmp, replace);\t\\\n\t/* Set next/prev for sibling linked list. */\t\t\t\\\n\tif (replace != NULL) {\t\t\t\t\t\t\\\n\t\tif (parent != NULL) {\t\t\t\t\t\\\n\t\t\tphn_prev_set(a_type, a_field, replace, parent);\t\\\n\t\t\tphn_lchild_set(a_type, a_field, parent,\t\t\\\n\t\t\t    replace);\t\t\t\t\t\\\n\t\t} else {\t\t\t\t\t\t\\\n\t\t\tphn_prev_set(a_type, a_field, replace,\t\t\\\n\t\t\t    phn_prev_get(a_type, a_field, phn));\t\\\n\t\t\tif (phn_prev_get(a_type, a_field, phn) !=\t\\\n\t\t\t    NULL) {\t\t\t\t\t\\\n\t\t\t\tphn_next_set(a_type, a_field,\t\t\\\n\t\t\t\t    phn_prev_get(a_type, a_field, phn),\t\\\n\t\t\t\t    replace);\t\t\t\t\\\n\t\t\t}\t\t\t\t\t\t\\\n\t\t}\t\t\t\t\t\t\t\\\n\t\tphn_next_set(a_type, a_field, replace,\t\t\t\\\n\t\t    phn_next_get(a_type, a_field, phn));\t\t\\\n\t\tif (phn_next_get(a_type, a_field, phn) != NULL) {\t\\\n\t\t\tphn_prev_set(a_type, a_field,\t\t\t\\\n\t\t\t    phn_next_get(a_type, a_field, phn),\t\t\\\n\t\t\t    replace);\t\t\t\t\t\\\n\t\t}\t\t\t\t\t\t\t\\\n\t} else {\t\t\t\t\t\t\t\\\n\t\tif (parent != NULL) {\t\t\t\t\t\\\n\t\t\ta_type *next = phn_next_get(a_type, a_field,\t\\\n\t\t\t    phn);\t\t\t\t\t\\\n\t\t\tphn_lchild_set(a_type, a_field, parent, next);\t\\\n\t\t\tif (next != NULL) {\t\t\t\t\\\n\t\t\t\tphn_prev_set(a_type, a_field, next,\t\\\n\t\t\t\t    parent);\t\t\t\t\\\n\t\t\t}\t\t\t\t\t\t\\\n\t\t} else {\t\t\t\t\t\t\\\n\t\t\tassert(phn_prev_get(a_type, a_field, phn) !=\t\\\n\t\t\t    NULL);\t\t\t\t\t\\\n\t\t\tphn_next_set(a_type, a_field,\t\t\t\\\n\t\t\t    phn_prev_get(a_type, a_field, phn),\t\t\\\n\t\t\t    phn_next_get(a_type, a_field, phn));\t\\\n\t\t}\t\t\t\t\t\t\t\\\n\t\tif (phn_next_get(a_type, a_field, phn) != NULL) {\t\\\n\t\t\tphn_prev_set(a_type, a_field,\t\t\t\\\n\t\t\t    phn_next_get(a_type, a_field, phn),\t\t\\\n\t\t\t    phn_prev_get(a_type, a_field, phn));\t\\\n\t\t}\t\t\t\t\t\t\t\\\n\t}\t\t\t\t\t\t\t\t\\\n}\n\n#endif /* PH_H_ */\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/deps/jemalloc/include/jemalloc/internal/private_namespace.sh",
    "content": "#!/bin/sh\n\nfor symbol in `cat $1` ; do\n  echo \"#define\t${symbol} JEMALLOC_N(${symbol})\"\ndone\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/deps/jemalloc/include/jemalloc/internal/private_symbols.txt",
    "content": "a0dalloc\na0malloc\narena_aalloc\narena_alloc_junk_small\narena_basic_stats_merge\narena_bin_index\narena_bin_info\narena_bitselm_get_const\narena_bitselm_get_mutable\narena_boot\narena_choose\narena_choose_hard\narena_choose_impl\narena_chunk_alloc_huge\narena_chunk_cache_maybe_insert\narena_chunk_cache_maybe_remove\narena_chunk_dalloc_huge\narena_chunk_ralloc_huge_expand\narena_chunk_ralloc_huge_shrink\narena_chunk_ralloc_huge_similar\narena_cleanup\narena_dalloc\narena_dalloc_bin\narena_dalloc_bin_junked_locked\narena_dalloc_junk_large\narena_dalloc_junk_small\narena_dalloc_large\narena_dalloc_large_junked_locked\narena_dalloc_small\narena_decay_tick\narena_decay_ticks\narena_decay_time_default_get\narena_decay_time_default_set\narena_decay_time_get\narena_decay_time_set\narena_dss_prec_get\narena_dss_prec_set\narena_get\narena_ichoose\narena_init\narena_lg_dirty_mult_default_get\narena_lg_dirty_mult_default_set\narena_lg_dirty_mult_get\narena_lg_dirty_mult_set\narena_malloc\narena_malloc_hard\narena_malloc_large\narena_mapbits_allocated_get\narena_mapbits_binind_get\narena_mapbits_decommitted_get\narena_mapbits_dirty_get\narena_mapbits_get\narena_mapbits_internal_set\narena_mapbits_large_binind_set\narena_mapbits_large_get\narena_mapbits_large_set\narena_mapbits_large_size_get\narena_mapbits_size_decode\narena_mapbits_size_encode\narena_mapbits_small_runind_get\narena_mapbits_small_set\narena_mapbits_unallocated_set\narena_mapbits_unallocated_size_get\narena_mapbits_unallocated_size_set\narena_mapbits_unzeroed_get\narena_mapbitsp_get_const\narena_mapbitsp_get_mutable\narena_mapbitsp_read\narena_mapbitsp_write\narena_maxrun\narena_maybe_purge\narena_metadata_allocated_add\narena_metadata_allocated_get\narena_metadata_allocated_sub\narena_migrate\narena_miscelm_get_const\narena_miscelm_get_mutable\narena_miscelm_to_pageind\narena_miscelm_to_rpages\narena_new\narena_node_alloc\narena_node_dalloc\narena_nthreads_dec\narena_nthreads_get\narena_nthreads_inc\narena_palloc\narena_postfork_child\narena_postfork_parent\narena_prefork0\narena_prefork1\narena_prefork2\narena_prefork3\narena_prof_accum\narena_prof_accum_impl\narena_prof_accum_locked\narena_prof_promoted\narena_prof_tctx_get\narena_prof_tctx_reset\narena_prof_tctx_set\narena_ptr_small_binind_get\narena_purge\narena_quarantine_junk_small\narena_ralloc\narena_ralloc_junk_large\narena_ralloc_no_move\narena_rd_to_miscelm\narena_redzone_corruption\narena_reset\narena_run_regind\narena_run_to_miscelm\narena_salloc\narena_sdalloc\narena_stats_merge\narena_tcache_fill_small\narena_tdata_get\narena_tdata_get_hard\narenas\narenas_tdata_bypass_cleanup\narenas_tdata_cleanup\natomic_add_p\natomic_add_u\natomic_add_uint32\natomic_add_uint64\natomic_add_z\natomic_cas_p\natomic_cas_u\natomic_cas_uint32\natomic_cas_uint64\natomic_cas_z\natomic_sub_p\natomic_sub_u\natomic_sub_uint32\natomic_sub_uint64\natomic_sub_z\natomic_write_p\natomic_write_u\natomic_write_uint32\natomic_write_uint64\natomic_write_z\nbase_alloc\nbase_boot\nbase_postfork_child\nbase_postfork_parent\nbase_prefork\nbase_stats_get\nbitmap_full\nbitmap_get\nbitmap_info_init\nbitmap_init\nbitmap_set\nbitmap_sfu\nbitmap_size\nbitmap_unset\nbootstrap_calloc\nbootstrap_free\nbootstrap_malloc\nbt_init\nbuferror\nchunk_alloc_base\nchunk_alloc_cache\nchunk_alloc_dss\nchunk_alloc_mmap\nchunk_alloc_wrapper\nchunk_boot\nchunk_dalloc_cache\nchunk_dalloc_mmap\nchunk_dalloc_wrapper\nchunk_deregister\nchunk_dss_boot\nchunk_dss_postfork_child\nchunk_dss_postfork_parent\nchunk_dss_prec_get\nchunk_dss_prec_set\nchunk_dss_prefork\nchunk_hooks_default\nchunk_hooks_get\nchunk_hooks_set\nchunk_in_dss\nchunk_lookup\nchunk_npages\nchunk_postfork_child\nchunk_postfork_parent\nchunk_prefork\nchunk_purge_wrapper\nchunk_register\nchunks_rtree\nchunksize\nchunksize_mask\nckh_count\nckh_delete\nckh_insert\nckh_iter\nckh_new\nckh_pointer_hash\nckh_pointer_keycomp\nckh_remove\nckh_search\nckh_string_hash\nckh_string_keycomp\nctl_boot\nctl_bymib\nctl_byname\nctl_nametomib\nctl_postfork_child\nctl_postfork_parent\nctl_prefork\ndecay_ticker_get\ndss_prec_names\nextent_node_achunk_get\nextent_node_achunk_set\nextent_node_addr_get\nextent_node_addr_set\nextent_node_arena_get\nextent_node_arena_set\nextent_node_committed_get\nextent_node_committed_set\nextent_node_dirty_insert\nextent_node_dirty_linkage_init\nextent_node_dirty_remove\nextent_node_init\nextent_node_prof_tctx_get\nextent_node_prof_tctx_set\nextent_node_size_get\nextent_node_size_set\nextent_node_zeroed_get\nextent_node_zeroed_set\nextent_tree_ad_destroy\nextent_tree_ad_destroy_recurse\nextent_tree_ad_empty\nextent_tree_ad_first\nextent_tree_ad_insert\nextent_tree_ad_iter\nextent_tree_ad_iter_recurse\nextent_tree_ad_iter_start\nextent_tree_ad_last\nextent_tree_ad_new\nextent_tree_ad_next\nextent_tree_ad_nsearch\nextent_tree_ad_prev\nextent_tree_ad_psearch\nextent_tree_ad_remove\nextent_tree_ad_reverse_iter\nextent_tree_ad_reverse_iter_recurse\nextent_tree_ad_reverse_iter_start\nextent_tree_ad_search\nextent_tree_szad_destroy\nextent_tree_szad_destroy_recurse\nextent_tree_szad_empty\nextent_tree_szad_first\nextent_tree_szad_insert\nextent_tree_szad_iter\nextent_tree_szad_iter_recurse\nextent_tree_szad_iter_start\nextent_tree_szad_last\nextent_tree_szad_new\nextent_tree_szad_next\nextent_tree_szad_nsearch\nextent_tree_szad_prev\nextent_tree_szad_psearch\nextent_tree_szad_remove\nextent_tree_szad_reverse_iter\nextent_tree_szad_reverse_iter_recurse\nextent_tree_szad_reverse_iter_start\nextent_tree_szad_search\nffs_llu\nffs_lu\nffs_u\nffs_u32\nffs_u64\nffs_zu\nget_errno\nhash\nhash_fmix_32\nhash_fmix_64\nhash_get_block_32\nhash_get_block_64\nhash_rotl_32\nhash_rotl_64\nhash_x64_128\nhash_x86_128\nhash_x86_32\nhuge_aalloc\nhuge_dalloc\nhuge_dalloc_junk\nhuge_malloc\nhuge_palloc\nhuge_prof_tctx_get\nhuge_prof_tctx_reset\nhuge_prof_tctx_set\nhuge_ralloc\nhuge_ralloc_no_move\nhuge_salloc\niaalloc\nialloc\niallocztm\niarena_cleanup\nidalloc\nidalloctm\nin_valgrind\nindex2size\nindex2size_compute\nindex2size_lookup\nindex2size_tab\nipalloc\nipalloct\nipallocztm\niqalloc\niralloc\niralloct\niralloct_realign\nisalloc\nisdalloct\nisqalloc\nisthreaded\nivsalloc\nixalloc\njemalloc_postfork_child\njemalloc_postfork_parent\njemalloc_prefork\nlarge_maxclass\nlg_floor\nlg_prof_sample\nmalloc_cprintf\nmalloc_mutex_assert_not_owner\nmalloc_mutex_assert_owner\nmalloc_mutex_boot\nmalloc_mutex_init\nmalloc_mutex_lock\nmalloc_mutex_postfork_child\nmalloc_mutex_postfork_parent\nmalloc_mutex_prefork\nmalloc_mutex_unlock\nmalloc_printf\nmalloc_snprintf\nmalloc_strtoumax\nmalloc_tsd_boot0\nmalloc_tsd_boot1\nmalloc_tsd_cleanup_register\nmalloc_tsd_dalloc\nmalloc_tsd_malloc\nmalloc_tsd_no_cleanup\nmalloc_vcprintf\nmalloc_vsnprintf\nmalloc_write\nmap_bias\nmap_misc_offset\nmb_write\nnarenas_auto\nnarenas_tdata_cleanup\nnarenas_total_get\nncpus\nnhbins\nnhclasses\nnlclasses\nnstime_add\nnstime_compare\nnstime_copy\nnstime_divide\nnstime_idivide\nnstime_imultiply\nnstime_init\nnstime_init2\nnstime_ns\nnstime_nsec\nnstime_sec\nnstime_subtract\nnstime_update\nopt_abort\nopt_decay_time\nopt_dss\nopt_junk\nopt_junk_alloc\nopt_junk_free\nopt_lg_chunk\nopt_lg_dirty_mult\nopt_lg_prof_interval\nopt_lg_prof_sample\nopt_lg_tcache_max\nopt_narenas\nopt_prof\nopt_prof_accum\nopt_prof_active\nopt_prof_final\nopt_prof_gdump\nopt_prof_leak\nopt_prof_prefix\nopt_prof_thread_active_init\nopt_purge\nopt_quarantine\nopt_redzone\nopt_stats_print\nopt_tcache\nopt_utrace\nopt_xmalloc\nopt_zero\np2rz\npages_boot\npages_commit\npages_decommit\npages_map\npages_purge\npages_trim\npages_unmap\npow2_ceil_u32\npow2_ceil_u64\npow2_ceil_zu\nprng_lg_range\nprng_range\nprof_active\nprof_active_get\nprof_active_get_unlocked\nprof_active_set\nprof_alloc_prep\nprof_alloc_rollback\nprof_backtrace\nprof_boot0\nprof_boot1\nprof_boot2\nprof_bt_count\nprof_dump_header\nprof_dump_open\nprof_free\nprof_free_sampled_object\nprof_gdump\nprof_gdump_get\nprof_gdump_get_unlocked\nprof_gdump_set\nprof_gdump_val\nprof_idump\nprof_interval\nprof_lookup\nprof_malloc\nprof_malloc_sample_object\nprof_mdump\nprof_postfork_child\nprof_postfork_parent\nprof_prefork0\nprof_prefork1\nprof_realloc\nprof_reset\nprof_sample_accum_update\nprof_sample_threshold_update\nprof_tctx_get\nprof_tctx_reset\nprof_tctx_set\nprof_tdata_cleanup\nprof_tdata_count\nprof_tdata_get\nprof_tdata_init\nprof_tdata_reinit\nprof_thread_active_get\nprof_thread_active_init_get\nprof_thread_active_init_set\nprof_thread_active_set\nprof_thread_name_get\nprof_thread_name_set\npurge_mode_names\nquarantine\nquarantine_alloc_hook\nquarantine_alloc_hook_work\nquarantine_cleanup\nregister_zone\nrtree_child_read\nrtree_child_read_hard\nrtree_child_tryread\nrtree_delete\nrtree_get\nrtree_new\nrtree_node_valid\nrtree_set\nrtree_start_level\nrtree_subkey\nrtree_subtree_read\nrtree_subtree_read_hard\nrtree_subtree_tryread\nrtree_val_read\nrtree_val_write\nrun_quantize_ceil\nrun_quantize_floor\nrun_quantize_max\ns2u\ns2u_compute\ns2u_lookup\nsa2u\nset_errno\nsize2index\nsize2index_compute\nsize2index_lookup\nsize2index_tab\nstats_cactive\nstats_cactive_add\nstats_cactive_get\nstats_cactive_sub\nstats_print\ntcache_alloc_easy\ntcache_alloc_large\ntcache_alloc_small\ntcache_alloc_small_hard\ntcache_arena_reassociate\ntcache_bin_flush_large\ntcache_bin_flush_small\ntcache_bin_info\ntcache_boot\ntcache_cleanup\ntcache_create\ntcache_dalloc_large\ntcache_dalloc_small\ntcache_enabled_cleanup\ntcache_enabled_get\ntcache_enabled_set\ntcache_event\ntcache_event_hard\ntcache_flush\ntcache_get\ntcache_get_hard\ntcache_maxclass\ntcache_salloc\ntcache_stats_merge\ntcaches\ntcaches_create\ntcaches_destroy\ntcaches_flush\ntcaches_get\nthread_allocated_cleanup\nthread_deallocated_cleanup\nticker_copy\nticker_init\nticker_read\nticker_tick\nticker_ticks\ntsd_arena_get\ntsd_arena_set\ntsd_arenap_get\ntsd_arenas_tdata_bypass_get\ntsd_arenas_tdata_bypass_set\ntsd_arenas_tdata_bypassp_get\ntsd_arenas_tdata_get\ntsd_arenas_tdata_set\ntsd_arenas_tdatap_get\ntsd_boot\ntsd_boot0\ntsd_boot1\ntsd_booted\ntsd_booted_get\ntsd_cleanup\ntsd_cleanup_wrapper\ntsd_fetch\ntsd_get\ntsd_iarena_get\ntsd_iarena_set\ntsd_iarenap_get\ntsd_initialized\ntsd_init_check_recursion\ntsd_init_finish\ntsd_init_head\ntsd_narenas_tdata_get\ntsd_narenas_tdata_set\ntsd_narenas_tdatap_get\ntsd_wrapper_get\ntsd_wrapper_set\ntsd_nominal\ntsd_prof_tdata_get\ntsd_prof_tdata_set\ntsd_prof_tdatap_get\ntsd_quarantine_get\ntsd_quarantine_set\ntsd_quarantinep_get\ntsd_set\ntsd_tcache_enabled_get\ntsd_tcache_enabled_set\ntsd_tcache_enabledp_get\ntsd_tcache_get\ntsd_tcache_set\ntsd_tcachep_get\ntsd_thread_allocated_get\ntsd_thread_allocated_set\ntsd_thread_allocatedp_get\ntsd_thread_deallocated_get\ntsd_thread_deallocated_set\ntsd_thread_deallocatedp_get\ntsd_tls\ntsd_tsd\ntsd_tsdn\ntsd_witness_fork_get\ntsd_witness_fork_set\ntsd_witness_forkp_get\ntsd_witnesses_get\ntsd_witnesses_set\ntsd_witnessesp_get\ntsdn_fetch\ntsdn_null\ntsdn_tsd\nu2rz\nvalgrind_freelike_block\nvalgrind_make_mem_defined\nvalgrind_make_mem_noaccess\nvalgrind_make_mem_undefined\nwitness_assert_lockless\nwitness_assert_not_owner\nwitness_assert_owner\nwitness_fork_cleanup\nwitness_init\nwitness_lock\nwitness_lock_error\nwitness_lockless_error\nwitness_not_owner_error\nwitness_owner_error\nwitness_postfork_child\nwitness_postfork_parent\nwitness_prefork\nwitness_unlock\nwitnesses_cleanup\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/deps/jemalloc/include/jemalloc/internal/private_unnamespace.sh",
    "content": "#!/bin/sh\n\nfor symbol in `cat $1` ; do\n  echo \"#undef ${symbol}\"\ndone\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/deps/jemalloc/include/jemalloc/internal/prng.h",
    "content": "/******************************************************************************/\n#ifdef JEMALLOC_H_TYPES\n\n/*\n * Simple linear congruential pseudo-random number generator:\n *\n *   prng(y) = (a*x + c) % m\n *\n * where the following constants ensure maximal period:\n *\n *   a == Odd number (relatively prime to 2^n), and (a-1) is a multiple of 4.\n *   c == Odd number (relatively prime to 2^n).\n *   m == 2^32\n *\n * See Knuth's TAOCP 3rd Ed., Vol. 2, pg. 17 for details on these constraints.\n *\n * This choice of m has the disadvantage that the quality of the bits is\n * proportional to bit position.  For example, the lowest bit has a cycle of 2,\n * the next has a cycle of 4, etc.  For this reason, we prefer to use the upper\n * bits.\n */\n#define\tPRNG_A\tUINT64_C(6364136223846793005)\n#define\tPRNG_C\tUINT64_C(1442695040888963407)\n\n#endif /* JEMALLOC_H_TYPES */\n/******************************************************************************/\n#ifdef JEMALLOC_H_STRUCTS\n\n#endif /* JEMALLOC_H_STRUCTS */\n/******************************************************************************/\n#ifdef JEMALLOC_H_EXTERNS\n\n#endif /* JEMALLOC_H_EXTERNS */\n/******************************************************************************/\n#ifdef JEMALLOC_H_INLINES\n\n#ifndef JEMALLOC_ENABLE_INLINE\nuint64_t\tprng_lg_range(uint64_t *state, unsigned lg_range);\nuint64_t\tprng_range(uint64_t *state, uint64_t range);\n#endif\n\n#if (defined(JEMALLOC_ENABLE_INLINE) || defined(JEMALLOC_PRNG_C_))\nJEMALLOC_ALWAYS_INLINE uint64_t\nprng_lg_range(uint64_t *state, unsigned lg_range)\n{\n\tuint64_t ret;\n\n\tassert(lg_range > 0);\n\tassert(lg_range <= 64);\n\n\tret = (*state * PRNG_A) + PRNG_C;\n\t*state = ret;\n\tret >>= (64 - lg_range);\n\n\treturn (ret);\n}\n\nJEMALLOC_ALWAYS_INLINE uint64_t\nprng_range(uint64_t *state, uint64_t range)\n{\n\tuint64_t ret;\n\tunsigned lg_range;\n\n\tassert(range > 1);\n\n\t/* Compute the ceiling of lg(range). */\n\tlg_range = ffs_u64(pow2_ceil_u64(range)) - 1;\n\n\t/* Generate a result in [0..range) via repeated trial. */\n\tdo {\n\t\tret = prng_lg_range(state, lg_range);\n\t} while (ret >= range);\n\n\treturn (ret);\n}\n#endif\n\n#endif /* JEMALLOC_H_INLINES */\n/******************************************************************************/\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/deps/jemalloc/include/jemalloc/internal/prof.h",
    "content": "/******************************************************************************/\n#ifdef JEMALLOC_H_TYPES\n\ntypedef struct prof_bt_s prof_bt_t;\ntypedef struct prof_cnt_s prof_cnt_t;\ntypedef struct prof_tctx_s prof_tctx_t;\ntypedef struct prof_gctx_s prof_gctx_t;\ntypedef struct prof_tdata_s prof_tdata_t;\n\n/* Option defaults. */\n#ifdef JEMALLOC_PROF\n#  define PROF_PREFIX_DEFAULT\t\t\"jeprof\"\n#else\n#  define PROF_PREFIX_DEFAULT\t\t\"\"\n#endif\n#define\tLG_PROF_SAMPLE_DEFAULT\t\t19\n#define\tLG_PROF_INTERVAL_DEFAULT\t-1\n\n/*\n * Hard limit on stack backtrace depth.  The version of prof_backtrace() that\n * is based on __builtin_return_address() necessarily has a hard-coded number\n * of backtrace frame handlers, and should be kept in sync with this setting.\n */\n#define\tPROF_BT_MAX\t\t\t128\n\n/* Initial hash table size. */\n#define\tPROF_CKH_MINITEMS\t\t64\n\n/* Size of memory buffer to use when writing dump files. */\n#define\tPROF_DUMP_BUFSIZE\t\t65536\n\n/* Size of stack-allocated buffer used by prof_printf(). */\n#define\tPROF_PRINTF_BUFSIZE\t\t128\n\n/*\n * Number of mutexes shared among all gctx's.  No space is allocated for these\n * unless profiling is enabled, so it's okay to over-provision.\n */\n#define\tPROF_NCTX_LOCKS\t\t\t1024\n\n/*\n * Number of mutexes shared among all tdata's.  No space is allocated for these\n * unless profiling is enabled, so it's okay to over-provision.\n */\n#define\tPROF_NTDATA_LOCKS\t\t256\n\n/*\n * prof_tdata pointers close to NULL are used to encode state information that\n * is used for cleaning up during thread shutdown.\n */\n#define\tPROF_TDATA_STATE_REINCARNATED\t((prof_tdata_t *)(uintptr_t)1)\n#define\tPROF_TDATA_STATE_PURGATORY\t((prof_tdata_t *)(uintptr_t)2)\n#define\tPROF_TDATA_STATE_MAX\t\tPROF_TDATA_STATE_PURGATORY\n\n#endif /* JEMALLOC_H_TYPES */\n/******************************************************************************/\n#ifdef JEMALLOC_H_STRUCTS\n\nstruct prof_bt_s {\n\t/* Backtrace, stored as len program counters. */\n\tvoid\t\t**vec;\n\tunsigned\tlen;\n};\n\n#ifdef JEMALLOC_PROF_LIBGCC\n/* Data structure passed to libgcc _Unwind_Backtrace() callback functions. */\ntypedef struct {\n\tprof_bt_t\t*bt;\n\tunsigned\tmax;\n} prof_unwind_data_t;\n#endif\n\nstruct prof_cnt_s {\n\t/* Profiling counters. */\n\tuint64_t\tcurobjs;\n\tuint64_t\tcurbytes;\n\tuint64_t\taccumobjs;\n\tuint64_t\taccumbytes;\n};\n\ntypedef enum {\n\tprof_tctx_state_initializing,\n\tprof_tctx_state_nominal,\n\tprof_tctx_state_dumping,\n\tprof_tctx_state_purgatory /* Dumper must finish destroying. */\n} prof_tctx_state_t;\n\nstruct prof_tctx_s {\n\t/* Thread data for thread that performed the allocation. */\n\tprof_tdata_t\t\t*tdata;\n\n\t/*\n\t * Copy of tdata->thr_{uid,discrim}, necessary because tdata may be\n\t * defunct during teardown.\n\t */\n\tuint64_t\t\tthr_uid;\n\tuint64_t\t\tthr_discrim;\n\n\t/* Profiling counters, protected by tdata->lock. */\n\tprof_cnt_t\t\tcnts;\n\n\t/* Associated global context. */\n\tprof_gctx_t\t\t*gctx;\n\n\t/*\n\t * UID that distinguishes multiple tctx's created by the same thread,\n\t * but coexisting in gctx->tctxs.  There are two ways that such\n\t * coexistence can occur:\n\t * - A dumper thread can cause a tctx to be retained in the purgatory\n\t *   state.\n\t * - Although a single \"producer\" thread must create all tctx's which\n\t *   share the same thr_uid, multiple \"consumers\" can each concurrently\n\t *   execute portions of prof_tctx_destroy().  prof_tctx_destroy() only\n\t *   gets called once each time cnts.cur{objs,bytes} drop to 0, but this\n\t *   threshold can be hit again before the first consumer finishes\n\t *   executing prof_tctx_destroy().\n\t */\n\tuint64_t\t\ttctx_uid;\n\n\t/* Linkage into gctx's tctxs. */\n\trb_node(prof_tctx_t)\ttctx_link;\n\n\t/*\n\t * True during prof_alloc_prep()..prof_malloc_sample_object(), prevents\n\t * sample vs destroy race.\n\t */\n\tbool\t\t\tprepared;\n\n\t/* Current dump-related state, protected by gctx->lock. */\n\tprof_tctx_state_t\tstate;\n\n\t/*\n\t * Copy of cnts snapshotted during early dump phase, protected by\n\t * dump_mtx.\n\t */\n\tprof_cnt_t\t\tdump_cnts;\n};\ntypedef rb_tree(prof_tctx_t) prof_tctx_tree_t;\n\nstruct prof_gctx_s {\n\t/* Protects nlimbo, cnt_summed, and tctxs. */\n\tmalloc_mutex_t\t\t*lock;\n\n\t/*\n\t * Number of threads that currently cause this gctx to be in a state of\n\t * limbo due to one of:\n\t *   - Initializing this gctx.\n\t *   - Initializing per thread counters associated with this gctx.\n\t *   - Preparing to destroy this gctx.\n\t *   - Dumping a heap profile that includes this gctx.\n\t * nlimbo must be 1 (single destroyer) in order to safely destroy the\n\t * gctx.\n\t */\n\tunsigned\t\tnlimbo;\n\n\t/*\n\t * Tree of profile counters, one for each thread that has allocated in\n\t * this context.\n\t */\n\tprof_tctx_tree_t\ttctxs;\n\n\t/* Linkage for tree of contexts to be dumped. */\n\trb_node(prof_gctx_t)\tdump_link;\n\n\t/* Temporary storage for summation during dump. */\n\tprof_cnt_t\t\tcnt_summed;\n\n\t/* Associated backtrace. */\n\tprof_bt_t\t\tbt;\n\n\t/* Backtrace vector, variable size, referred to by bt. */\n\tvoid\t\t\t*vec[1];\n};\ntypedef rb_tree(prof_gctx_t) prof_gctx_tree_t;\n\nstruct prof_tdata_s {\n\tmalloc_mutex_t\t\t*lock;\n\n\t/* Monotonically increasing unique thread identifier. */\n\tuint64_t\t\tthr_uid;\n\n\t/*\n\t * Monotonically increasing discriminator among tdata structures\n\t * associated with the same thr_uid.\n\t */\n\tuint64_t\t\tthr_discrim;\n\n\t/* Included in heap profile dumps if non-NULL. */\n\tchar\t\t\t*thread_name;\n\n\tbool\t\t\tattached;\n\tbool\t\t\texpired;\n\n\trb_node(prof_tdata_t)\ttdata_link;\n\n\t/*\n\t * Counter used to initialize prof_tctx_t's tctx_uid.  No locking is\n\t * necessary when incrementing this field, because only one thread ever\n\t * does so.\n\t */\n\tuint64_t\t\ttctx_uid_next;\n\n\t/*\n\t * Hash of (prof_bt_t *)-->(prof_tctx_t *).  Each thread tracks\n\t * backtraces for which it has non-zero allocation/deallocation counters\n\t * associated with thread-specific prof_tctx_t objects.  Other threads\n\t * may write to prof_tctx_t contents when freeing associated objects.\n\t */\n\tckh_t\t\t\tbt2tctx;\n\n\t/* Sampling state. */\n\tuint64_t\t\tprng_state;\n\tuint64_t\t\tbytes_until_sample;\n\n\t/* State used to avoid dumping while operating on prof internals. */\n\tbool\t\t\tenq;\n\tbool\t\t\tenq_idump;\n\tbool\t\t\tenq_gdump;\n\n\t/*\n\t * Set to true during an early dump phase for tdata's which are\n\t * currently being dumped.  New threads' tdata's have this initialized\n\t * to false so that they aren't accidentally included in later dump\n\t * phases.\n\t */\n\tbool\t\t\tdumping;\n\n\t/*\n\t * True if profiling is active for this tdata's thread\n\t * (thread.prof.active mallctl).\n\t */\n\tbool\t\t\tactive;\n\n\t/* Temporary storage for summation during dump. */\n\tprof_cnt_t\t\tcnt_summed;\n\n\t/* Backtrace vector, used for calls to prof_backtrace(). */\n\tvoid\t\t\t*vec[PROF_BT_MAX];\n};\ntypedef rb_tree(prof_tdata_t) prof_tdata_tree_t;\n\n#endif /* JEMALLOC_H_STRUCTS */\n/******************************************************************************/\n#ifdef JEMALLOC_H_EXTERNS\n\nextern bool\topt_prof;\nextern bool\topt_prof_active;\nextern bool\topt_prof_thread_active_init;\nextern size_t\topt_lg_prof_sample;   /* Mean bytes between samples. */\nextern ssize_t\topt_lg_prof_interval; /* lg(prof_interval). */\nextern bool\topt_prof_gdump;       /* High-water memory dumping. */\nextern bool\topt_prof_final;       /* Final profile dumping. */\nextern bool\topt_prof_leak;        /* Dump leak summary at exit. */\nextern bool\topt_prof_accum;       /* Report cumulative bytes. */\nextern char\topt_prof_prefix[\n    /* Minimize memory bloat for non-prof builds. */\n#ifdef JEMALLOC_PROF\n    PATH_MAX +\n#endif\n    1];\n\n/* Accessed via prof_active_[gs]et{_unlocked,}(). */\nextern bool\tprof_active;\n\n/* Accessed via prof_gdump_[gs]et{_unlocked,}(). */\nextern bool\tprof_gdump_val;\n\n/*\n * Profile dump interval, measured in bytes allocated.  Each arena triggers a\n * profile dump when it reaches this threshold.  The effect is that the\n * interval between profile dumps averages prof_interval, though the actual\n * interval between dumps will tend to be sporadic, and the interval will be a\n * maximum of approximately (prof_interval * narenas).\n */\nextern uint64_t\tprof_interval;\n\n/*\n * Initialized as opt_lg_prof_sample, and potentially modified during profiling\n * resets.\n */\nextern size_t\tlg_prof_sample;\n\nvoid\tprof_alloc_rollback(tsd_t *tsd, prof_tctx_t *tctx, bool updated);\nvoid\tprof_malloc_sample_object(tsdn_t *tsdn, const void *ptr, size_t usize,\n    prof_tctx_t *tctx);\nvoid\tprof_free_sampled_object(tsd_t *tsd, size_t usize, prof_tctx_t *tctx);\nvoid\tbt_init(prof_bt_t *bt, void **vec);\nvoid\tprof_backtrace(prof_bt_t *bt);\nprof_tctx_t\t*prof_lookup(tsd_t *tsd, prof_bt_t *bt);\n#ifdef JEMALLOC_JET\nsize_t\tprof_tdata_count(void);\nsize_t\tprof_bt_count(void);\nconst prof_cnt_t *prof_cnt_all(void);\ntypedef int (prof_dump_open_t)(bool, const char *);\nextern prof_dump_open_t *prof_dump_open;\ntypedef bool (prof_dump_header_t)(tsdn_t *, bool, const prof_cnt_t *);\nextern prof_dump_header_t *prof_dump_header;\n#endif\nvoid\tprof_idump(tsdn_t *tsdn);\nbool\tprof_mdump(tsd_t *tsd, const char *filename);\nvoid\tprof_gdump(tsdn_t *tsdn);\nprof_tdata_t\t*prof_tdata_init(tsdn_t *tsdn);\nprof_tdata_t\t*prof_tdata_reinit(tsd_t *tsd, prof_tdata_t *tdata);\nvoid\tprof_reset(tsdn_t *tsdn, size_t lg_sample);\nvoid\tprof_tdata_cleanup(tsd_t *tsd);\nbool\tprof_active_get(tsdn_t *tsdn);\nbool\tprof_active_set(tsdn_t *tsdn, bool active);\nconst char\t*prof_thread_name_get(tsd_t *tsd);\nint\tprof_thread_name_set(tsd_t *tsd, const char *thread_name);\nbool\tprof_thread_active_get(tsd_t *tsd);\nbool\tprof_thread_active_set(tsd_t *tsd, bool active);\nbool\tprof_thread_active_init_get(tsdn_t *tsdn);\nbool\tprof_thread_active_init_set(tsdn_t *tsdn, bool active_init);\nbool\tprof_gdump_get(tsdn_t *tsdn);\nbool\tprof_gdump_set(tsdn_t *tsdn, bool active);\nvoid\tprof_boot0(void);\nvoid\tprof_boot1(void);\nbool\tprof_boot2(tsdn_t *tsdn);\nvoid\tprof_prefork0(tsdn_t *tsdn);\nvoid\tprof_prefork1(tsdn_t *tsdn);\nvoid\tprof_postfork_parent(tsdn_t *tsdn);\nvoid\tprof_postfork_child(tsdn_t *tsdn);\nvoid\tprof_sample_threshold_update(prof_tdata_t *tdata);\n\n#endif /* JEMALLOC_H_EXTERNS */\n/******************************************************************************/\n#ifdef JEMALLOC_H_INLINES\n\n#ifndef JEMALLOC_ENABLE_INLINE\nbool\tprof_active_get_unlocked(void);\nbool\tprof_gdump_get_unlocked(void);\nprof_tdata_t\t*prof_tdata_get(tsd_t *tsd, bool create);\nprof_tctx_t\t*prof_tctx_get(tsdn_t *tsdn, const void *ptr);\nvoid\tprof_tctx_set(tsdn_t *tsdn, const void *ptr, size_t usize,\n    prof_tctx_t *tctx);\nvoid\tprof_tctx_reset(tsdn_t *tsdn, const void *ptr, size_t usize,\n    const void *old_ptr, prof_tctx_t *tctx);\nbool\tprof_sample_accum_update(tsd_t *tsd, size_t usize, bool commit,\n    prof_tdata_t **tdata_out);\nprof_tctx_t\t*prof_alloc_prep(tsd_t *tsd, size_t usize, bool prof_active,\n    bool update);\nvoid\tprof_malloc(tsdn_t *tsdn, const void *ptr, size_t usize,\n    prof_tctx_t *tctx);\nvoid\tprof_realloc(tsd_t *tsd, const void *ptr, size_t usize,\n    prof_tctx_t *tctx, bool prof_active, bool updated, const void *old_ptr,\n    size_t old_usize, prof_tctx_t *old_tctx);\nvoid\tprof_free(tsd_t *tsd, const void *ptr, size_t usize);\n#endif\n\n#if (defined(JEMALLOC_ENABLE_INLINE) || defined(JEMALLOC_PROF_C_))\nJEMALLOC_ALWAYS_INLINE bool\nprof_active_get_unlocked(void)\n{\n\n\t/*\n\t * Even if opt_prof is true, sampling can be temporarily disabled by\n\t * setting prof_active to false.  No locking is used when reading\n\t * prof_active in the fast path, so there are no guarantees regarding\n\t * how long it will take for all threads to notice state changes.\n\t */\n\treturn (prof_active);\n}\n\nJEMALLOC_ALWAYS_INLINE bool\nprof_gdump_get_unlocked(void)\n{\n\n\t/*\n\t * No locking is used when reading prof_gdump_val in the fast path, so\n\t * there are no guarantees regarding how long it will take for all\n\t * threads to notice state changes.\n\t */\n\treturn (prof_gdump_val);\n}\n\nJEMALLOC_ALWAYS_INLINE prof_tdata_t *\nprof_tdata_get(tsd_t *tsd, bool create)\n{\n\tprof_tdata_t *tdata;\n\n\tcassert(config_prof);\n\n\ttdata = tsd_prof_tdata_get(tsd);\n\tif (create) {\n\t\tif (unlikely(tdata == NULL)) {\n\t\t\tif (tsd_nominal(tsd)) {\n\t\t\t\ttdata = prof_tdata_init(tsd_tsdn(tsd));\n\t\t\t\ttsd_prof_tdata_set(tsd, tdata);\n\t\t\t}\n\t\t} else if (unlikely(tdata->expired)) {\n\t\t\ttdata = prof_tdata_reinit(tsd, tdata);\n\t\t\ttsd_prof_tdata_set(tsd, tdata);\n\t\t}\n\t\tassert(tdata == NULL || tdata->attached);\n\t}\n\n\treturn (tdata);\n}\n\nJEMALLOC_ALWAYS_INLINE prof_tctx_t *\nprof_tctx_get(tsdn_t *tsdn, const void *ptr)\n{\n\n\tcassert(config_prof);\n\tassert(ptr != NULL);\n\n\treturn (arena_prof_tctx_get(tsdn, ptr));\n}\n\nJEMALLOC_ALWAYS_INLINE void\nprof_tctx_set(tsdn_t *tsdn, const void *ptr, size_t usize, prof_tctx_t *tctx)\n{\n\n\tcassert(config_prof);\n\tassert(ptr != NULL);\n\n\tarena_prof_tctx_set(tsdn, ptr, usize, tctx);\n}\n\nJEMALLOC_ALWAYS_INLINE void\nprof_tctx_reset(tsdn_t *tsdn, const void *ptr, size_t usize, const void *old_ptr,\n    prof_tctx_t *old_tctx)\n{\n\n\tcassert(config_prof);\n\tassert(ptr != NULL);\n\n\tarena_prof_tctx_reset(tsdn, ptr, usize, old_ptr, old_tctx);\n}\n\nJEMALLOC_ALWAYS_INLINE bool\nprof_sample_accum_update(tsd_t *tsd, size_t usize, bool update,\n    prof_tdata_t **tdata_out)\n{\n\tprof_tdata_t *tdata;\n\n\tcassert(config_prof);\n\n\ttdata = prof_tdata_get(tsd, true);\n\tif (unlikely((uintptr_t)tdata <= (uintptr_t)PROF_TDATA_STATE_MAX))\n\t\ttdata = NULL;\n\n\tif (tdata_out != NULL)\n\t\t*tdata_out = tdata;\n\n\tif (unlikely(tdata == NULL))\n\t\treturn (true);\n\n\tif (likely(tdata->bytes_until_sample >= usize)) {\n\t\tif (update)\n\t\t\ttdata->bytes_until_sample -= usize;\n\t\treturn (true);\n\t} else {\n\t\t/* Compute new sample threshold. */\n\t\tif (update)\n\t\t\tprof_sample_threshold_update(tdata);\n\t\treturn (!tdata->active);\n\t}\n}\n\nJEMALLOC_ALWAYS_INLINE prof_tctx_t *\nprof_alloc_prep(tsd_t *tsd, size_t usize, bool prof_active, bool update)\n{\n\tprof_tctx_t *ret;\n\tprof_tdata_t *tdata;\n\tprof_bt_t bt;\n\n\tassert(usize == s2u(usize));\n\n\tif (!prof_active || likely(prof_sample_accum_update(tsd, usize, update,\n\t    &tdata)))\n\t\tret = (prof_tctx_t *)(uintptr_t)1U;\n\telse {\n\t\tbt_init(&bt, tdata->vec);\n\t\tprof_backtrace(&bt);\n\t\tret = prof_lookup(tsd, &bt);\n\t}\n\n\treturn (ret);\n}\n\nJEMALLOC_ALWAYS_INLINE void\nprof_malloc(tsdn_t *tsdn, const void *ptr, size_t usize, prof_tctx_t *tctx)\n{\n\n\tcassert(config_prof);\n\tassert(ptr != NULL);\n\tassert(usize == isalloc(tsdn, ptr, true));\n\n\tif (unlikely((uintptr_t)tctx > (uintptr_t)1U))\n\t\tprof_malloc_sample_object(tsdn, ptr, usize, tctx);\n\telse\n\t\tprof_tctx_set(tsdn, ptr, usize, (prof_tctx_t *)(uintptr_t)1U);\n}\n\nJEMALLOC_ALWAYS_INLINE void\nprof_realloc(tsd_t *tsd, const void *ptr, size_t usize, prof_tctx_t *tctx,\n    bool prof_active, bool updated, const void *old_ptr, size_t old_usize,\n    prof_tctx_t *old_tctx)\n{\n\tbool sampled, old_sampled;\n\n\tcassert(config_prof);\n\tassert(ptr != NULL || (uintptr_t)tctx <= (uintptr_t)1U);\n\n\tif (prof_active && !updated && ptr != NULL) {\n\t\tassert(usize == isalloc(tsd_tsdn(tsd), ptr, true));\n\t\tif (prof_sample_accum_update(tsd, usize, true, NULL)) {\n\t\t\t/*\n\t\t\t * Don't sample.  The usize passed to prof_alloc_prep()\n\t\t\t * was larger than what actually got allocated, so a\n\t\t\t * backtrace was captured for this allocation, even\n\t\t\t * though its actual usize was insufficient to cross the\n\t\t\t * sample threshold.\n\t\t\t */\n\t\t\tprof_alloc_rollback(tsd, tctx, true);\n\t\t\ttctx = (prof_tctx_t *)(uintptr_t)1U;\n\t\t}\n\t}\n\n\tsampled = ((uintptr_t)tctx > (uintptr_t)1U);\n\told_sampled = ((uintptr_t)old_tctx > (uintptr_t)1U);\n\n\tif (unlikely(sampled))\n\t\tprof_malloc_sample_object(tsd_tsdn(tsd), ptr, usize, tctx);\n\telse\n\t\tprof_tctx_reset(tsd_tsdn(tsd), ptr, usize, old_ptr, old_tctx);\n\n\tif (unlikely(old_sampled))\n\t\tprof_free_sampled_object(tsd, old_usize, old_tctx);\n}\n\nJEMALLOC_ALWAYS_INLINE void\nprof_free(tsd_t *tsd, const void *ptr, size_t usize)\n{\n\tprof_tctx_t *tctx = prof_tctx_get(tsd_tsdn(tsd), ptr);\n\n\tcassert(config_prof);\n\tassert(usize == isalloc(tsd_tsdn(tsd), ptr, true));\n\n\tif (unlikely((uintptr_t)tctx > (uintptr_t)1U))\n\t\tprof_free_sampled_object(tsd, usize, tctx);\n}\n#endif\n\n#endif /* JEMALLOC_H_INLINES */\n/******************************************************************************/\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/deps/jemalloc/include/jemalloc/internal/public_namespace.sh",
    "content": "#!/bin/sh\n\nfor nm in `cat $1` ; do\n  n=`echo ${nm} |tr ':' ' ' |awk '{print $1}'`\n  echo \"#define\tje_${n} JEMALLOC_N(${n})\"\ndone\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/deps/jemalloc/include/jemalloc/internal/public_unnamespace.sh",
    "content": "#!/bin/sh\n\nfor nm in `cat $1` ; do\n  n=`echo ${nm} |tr ':' ' ' |awk '{print $1}'`\n  echo \"#undef je_${n}\"\ndone\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/deps/jemalloc/include/jemalloc/internal/ql.h",
    "content": "/* List definitions. */\n#define\tql_head(a_type)\t\t\t\t\t\t\t\\\nstruct {\t\t\t\t\t\t\t\t\\\n\ta_type *qlh_first;\t\t\t\t\t\t\\\n}\n\n#define\tql_head_initializer(a_head) {NULL}\n\n#define\tql_elm(a_type)\tqr(a_type)\n\n/* List functions. */\n#define\tql_new(a_head) do {\t\t\t\t\t\t\\\n\t(a_head)->qlh_first = NULL;\t\t\t\t\t\\\n} while (0)\n\n#define\tql_elm_new(a_elm, a_field) qr_new((a_elm), a_field)\n\n#define\tql_first(a_head) ((a_head)->qlh_first)\n\n#define\tql_last(a_head, a_field)\t\t\t\t\t\\\n\t((ql_first(a_head) != NULL)\t\t\t\t\t\\\n\t    ? qr_prev(ql_first(a_head), a_field) : NULL)\n\n#define\tql_next(a_head, a_elm, a_field)\t\t\t\t\t\\\n\t((ql_last(a_head, a_field) != (a_elm))\t\t\t\t\\\n\t    ? qr_next((a_elm), a_field)\t: NULL)\n\n#define\tql_prev(a_head, a_elm, a_field)\t\t\t\t\t\\\n\t((ql_first(a_head) != (a_elm)) ? qr_prev((a_elm), a_field)\t\\\n\t\t\t\t       : NULL)\n\n#define\tql_before_insert(a_head, a_qlelm, a_elm, a_field) do {\t\t\\\n\tqr_before_insert((a_qlelm), (a_elm), a_field);\t\t\t\\\n\tif (ql_first(a_head) == (a_qlelm)) {\t\t\t\t\\\n\t\tql_first(a_head) = (a_elm);\t\t\t\t\\\n\t}\t\t\t\t\t\t\t\t\\\n} while (0)\n\n#define\tql_after_insert(a_qlelm, a_elm, a_field)\t\t\t\\\n\tqr_after_insert((a_qlelm), (a_elm), a_field)\n\n#define\tql_head_insert(a_head, a_elm, a_field) do {\t\t\t\\\n\tif (ql_first(a_head) != NULL) {\t\t\t\t\t\\\n\t\tqr_before_insert(ql_first(a_head), (a_elm), a_field);\t\\\n\t}\t\t\t\t\t\t\t\t\\\n\tql_first(a_head) = (a_elm);\t\t\t\t\t\\\n} while (0)\n\n#define\tql_tail_insert(a_head, a_elm, a_field) do {\t\t\t\\\n\tif (ql_first(a_head) != NULL) {\t\t\t\t\t\\\n\t\tqr_before_insert(ql_first(a_head), (a_elm), a_field);\t\\\n\t}\t\t\t\t\t\t\t\t\\\n\tql_first(a_head) = qr_next((a_elm), a_field);\t\t\t\\\n} while (0)\n\n#define\tql_remove(a_head, a_elm, a_field) do {\t\t\t\t\\\n\tif (ql_first(a_head) == (a_elm)) {\t\t\t\t\\\n\t\tql_first(a_head) = qr_next(ql_first(a_head), a_field);\t\\\n\t}\t\t\t\t\t\t\t\t\\\n\tif (ql_first(a_head) != (a_elm)) {\t\t\t\t\\\n\t\tqr_remove((a_elm), a_field);\t\t\t\t\\\n\t} else {\t\t\t\t\t\t\t\\\n\t\tql_first(a_head) = NULL;\t\t\t\t\\\n\t}\t\t\t\t\t\t\t\t\\\n} while (0)\n\n#define\tql_head_remove(a_head, a_type, a_field) do {\t\t\t\\\n\ta_type *t = ql_first(a_head);\t\t\t\t\t\\\n\tql_remove((a_head), t, a_field);\t\t\t\t\\\n} while (0)\n\n#define\tql_tail_remove(a_head, a_type, a_field) do {\t\t\t\\\n\ta_type *t = ql_last(a_head, a_field);\t\t\t\t\\\n\tql_remove((a_head), t, a_field);\t\t\t\t\\\n} while (0)\n\n#define\tql_foreach(a_var, a_head, a_field)\t\t\t\t\\\n\tqr_foreach((a_var), ql_first(a_head), a_field)\n\n#define\tql_reverse_foreach(a_var, a_head, a_field)\t\t\t\\\n\tqr_reverse_foreach((a_var), ql_first(a_head), a_field)\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/deps/jemalloc/include/jemalloc/internal/qr.h",
    "content": "/* Ring definitions. */\n#define\tqr(a_type)\t\t\t\t\t\t\t\\\nstruct {\t\t\t\t\t\t\t\t\\\n\ta_type\t*qre_next;\t\t\t\t\t\t\\\n\ta_type\t*qre_prev;\t\t\t\t\t\t\\\n}\n\n/* Ring functions. */\n#define\tqr_new(a_qr, a_field) do {\t\t\t\t\t\\\n\t(a_qr)->a_field.qre_next = (a_qr);\t\t\t\t\\\n\t(a_qr)->a_field.qre_prev = (a_qr);\t\t\t\t\\\n} while (0)\n\n#define\tqr_next(a_qr, a_field) ((a_qr)->a_field.qre_next)\n\n#define\tqr_prev(a_qr, a_field) ((a_qr)->a_field.qre_prev)\n\n#define\tqr_before_insert(a_qrelm, a_qr, a_field) do {\t\t\t\\\n\t(a_qr)->a_field.qre_prev = (a_qrelm)->a_field.qre_prev;\t\t\\\n\t(a_qr)->a_field.qre_next = (a_qrelm);\t\t\t\t\\\n\t(a_qr)->a_field.qre_prev->a_field.qre_next = (a_qr);\t\t\\\n\t(a_qrelm)->a_field.qre_prev = (a_qr);\t\t\t\t\\\n} while (0)\n\n#define\tqr_after_insert(a_qrelm, a_qr, a_field)\t\t\t\t\\\n    do\t\t\t\t\t\t\t\t\t\\\n    {\t\t\t\t\t\t\t\t\t\\\n\t(a_qr)->a_field.qre_next = (a_qrelm)->a_field.qre_next;\t\t\\\n\t(a_qr)->a_field.qre_prev = (a_qrelm);\t\t\t\t\\\n\t(a_qr)->a_field.qre_next->a_field.qre_prev = (a_qr);\t\t\\\n\t(a_qrelm)->a_field.qre_next = (a_qr);\t\t\t\t\\\n    } while (0)\n\n#define\tqr_meld(a_qr_a, a_qr_b, a_field) do {\t\t\t\t\\\n\tvoid *t;\t\t\t\t\t\t\t\\\n\t(a_qr_a)->a_field.qre_prev->a_field.qre_next = (a_qr_b);\t\\\n\t(a_qr_b)->a_field.qre_prev->a_field.qre_next = (a_qr_a);\t\\\n\tt = (a_qr_a)->a_field.qre_prev;\t\t\t\t\t\\\n\t(a_qr_a)->a_field.qre_prev = (a_qr_b)->a_field.qre_prev;\t\\\n\t(a_qr_b)->a_field.qre_prev = t;\t\t\t\t\t\\\n} while (0)\n\n/*\n * qr_meld() and qr_split() are functionally equivalent, so there's no need to\n * have two copies of the code.\n */\n#define\tqr_split(a_qr_a, a_qr_b, a_field)\t\t\t\t\\\n\tqr_meld((a_qr_a), (a_qr_b), a_field)\n\n#define\tqr_remove(a_qr, a_field) do {\t\t\t\t\t\\\n\t(a_qr)->a_field.qre_prev->a_field.qre_next\t\t\t\\\n\t    = (a_qr)->a_field.qre_next;\t\t\t\t\t\\\n\t(a_qr)->a_field.qre_next->a_field.qre_prev\t\t\t\\\n\t    = (a_qr)->a_field.qre_prev;\t\t\t\t\t\\\n\t(a_qr)->a_field.qre_next = (a_qr);\t\t\t\t\\\n\t(a_qr)->a_field.qre_prev = (a_qr);\t\t\t\t\\\n} while (0)\n\n#define\tqr_foreach(var, a_qr, a_field)\t\t\t\t\t\\\n\tfor ((var) = (a_qr);\t\t\t\t\t\t\\\n\t    (var) != NULL;\t\t\t\t\t\t\\\n\t    (var) = (((var)->a_field.qre_next != (a_qr))\t\t\\\n\t    ? (var)->a_field.qre_next : NULL))\n\n#define\tqr_reverse_foreach(var, a_qr, a_field)\t\t\t\t\\\n\tfor ((var) = ((a_qr) != NULL) ? qr_prev(a_qr, a_field) : NULL;\t\\\n\t    (var) != NULL;\t\t\t\t\t\t\\\n\t    (var) = (((var) != (a_qr))\t\t\t\t\t\\\n\t    ? (var)->a_field.qre_prev : NULL))\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/deps/jemalloc/include/jemalloc/internal/quarantine.h",
    "content": "/******************************************************************************/\n#ifdef JEMALLOC_H_TYPES\n\ntypedef struct quarantine_obj_s quarantine_obj_t;\ntypedef struct quarantine_s quarantine_t;\n\n/* Default per thread quarantine size if valgrind is enabled. */\n#define\tJEMALLOC_VALGRIND_QUARANTINE_DEFAULT\t(ZU(1) << 24)\n\n#endif /* JEMALLOC_H_TYPES */\n/******************************************************************************/\n#ifdef JEMALLOC_H_STRUCTS\n\nstruct quarantine_obj_s {\n\tvoid\t*ptr;\n\tsize_t\tusize;\n};\n\nstruct quarantine_s {\n\tsize_t\t\t\tcurbytes;\n\tsize_t\t\t\tcurobjs;\n\tsize_t\t\t\tfirst;\n#define\tLG_MAXOBJS_INIT 10\n\tsize_t\t\t\tlg_maxobjs;\n\tquarantine_obj_t\tobjs[1]; /* Dynamically sized ring buffer. */\n};\n\n#endif /* JEMALLOC_H_STRUCTS */\n/******************************************************************************/\n#ifdef JEMALLOC_H_EXTERNS\n\nvoid\tquarantine_alloc_hook_work(tsd_t *tsd);\nvoid\tquarantine(tsd_t *tsd, void *ptr);\nvoid\tquarantine_cleanup(tsd_t *tsd);\n\n#endif /* JEMALLOC_H_EXTERNS */\n/******************************************************************************/\n#ifdef JEMALLOC_H_INLINES\n\n#ifndef JEMALLOC_ENABLE_INLINE\nvoid\tquarantine_alloc_hook(void);\n#endif\n\n#if (defined(JEMALLOC_ENABLE_INLINE) || defined(JEMALLOC_QUARANTINE_C_))\nJEMALLOC_ALWAYS_INLINE void\nquarantine_alloc_hook(void)\n{\n\ttsd_t *tsd;\n\n\tassert(config_fill && opt_quarantine);\n\n\ttsd = tsd_fetch();\n\tif (tsd_quarantine_get(tsd) == NULL)\n\t\tquarantine_alloc_hook_work(tsd);\n}\n#endif\n\n#endif /* JEMALLOC_H_INLINES */\n/******************************************************************************/\n\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/deps/jemalloc/include/jemalloc/internal/rb.h",
    "content": "/*-\n *******************************************************************************\n *\n * cpp macro implementation of left-leaning 2-3 red-black trees.  Parent\n * pointers are not used, and color bits are stored in the least significant\n * bit of right-child pointers (if RB_COMPACT is defined), thus making node\n * linkage as compact as is possible for red-black trees.\n *\n * Usage:\n *\n *   #include <stdint.h>\n *   #include <stdbool.h>\n *   #define NDEBUG // (Optional, see assert(3).)\n *   #include <assert.h>\n *   #define RB_COMPACT // (Optional, embed color bits in right-child pointers.)\n *   #include <rb.h>\n *   ...\n *\n *******************************************************************************\n */\n\n#ifndef RB_H_\n#define\tRB_H_\n\n#ifdef RB_COMPACT\n/* Node structure. */\n#define\trb_node(a_type)\t\t\t\t\t\t\t\\\nstruct {\t\t\t\t\t\t\t\t\\\n    a_type *rbn_left;\t\t\t\t\t\t\t\\\n    a_type *rbn_right_red;\t\t\t\t\t\t\\\n}\n#else\n#define\trb_node(a_type)\t\t\t\t\t\t\t\\\nstruct {\t\t\t\t\t\t\t\t\\\n    a_type *rbn_left;\t\t\t\t\t\t\t\\\n    a_type *rbn_right;\t\t\t\t\t\t\t\\\n    bool rbn_red;\t\t\t\t\t\t\t\\\n}\n#endif\n\n/* Root structure. */\n#define\trb_tree(a_type)\t\t\t\t\t\t\t\\\nstruct {\t\t\t\t\t\t\t\t\\\n    a_type *rbt_root;\t\t\t\t\t\t\t\\\n}\n\n/* Left accessors. */\n#define\trbtn_left_get(a_type, a_field, a_node)\t\t\t\t\\\n    ((a_node)->a_field.rbn_left)\n#define\trbtn_left_set(a_type, a_field, a_node, a_left) do {\t\t\\\n    (a_node)->a_field.rbn_left = a_left;\t\t\t\t\\\n} while (0)\n\n#ifdef RB_COMPACT\n/* Right accessors. */\n#define\trbtn_right_get(a_type, a_field, a_node)\t\t\t\t\\\n    ((a_type *) (((intptr_t) (a_node)->a_field.rbn_right_red)\t\t\\\n      & ((ssize_t)-2)))\n#define\trbtn_right_set(a_type, a_field, a_node, a_right) do {\t\t\\\n    (a_node)->a_field.rbn_right_red = (a_type *) (((uintptr_t) a_right)\t\\\n      | (((uintptr_t) (a_node)->a_field.rbn_right_red) & ((size_t)1)));\t\\\n} while (0)\n\n/* Color accessors. */\n#define\trbtn_red_get(a_type, a_field, a_node)\t\t\t\t\\\n    ((bool) (((uintptr_t) (a_node)->a_field.rbn_right_red)\t\t\\\n      & ((size_t)1)))\n#define\trbtn_color_set(a_type, a_field, a_node, a_red) do {\t\t\\\n    (a_node)->a_field.rbn_right_red = (a_type *) ((((intptr_t)\t\t\\\n      (a_node)->a_field.rbn_right_red) & ((ssize_t)-2))\t\t\t\\\n      | ((ssize_t)a_red));\t\t\t\t\t\t\\\n} while (0)\n#define\trbtn_red_set(a_type, a_field, a_node) do {\t\t\t\\\n    (a_node)->a_field.rbn_right_red = (a_type *) (((uintptr_t)\t\t\\\n      (a_node)->a_field.rbn_right_red) | ((size_t)1));\t\t\t\\\n} while (0)\n#define\trbtn_black_set(a_type, a_field, a_node) do {\t\t\t\\\n    (a_node)->a_field.rbn_right_red = (a_type *) (((intptr_t)\t\t\\\n      (a_node)->a_field.rbn_right_red) & ((ssize_t)-2));\t\t\\\n} while (0)\n\n/* Node initializer. */\n#define\trbt_node_new(a_type, a_field, a_rbt, a_node) do {\t\t\\\n    /* Bookkeeping bit cannot be used by node pointer. */\t\t\\\n    assert(((uintptr_t)(a_node) & 0x1) == 0);\t\t\t\t\\\n    rbtn_left_set(a_type, a_field, (a_node), NULL);\t\\\n    rbtn_right_set(a_type, a_field, (a_node), NULL);\t\\\n    rbtn_red_set(a_type, a_field, (a_node));\t\t\t\t\\\n} while (0)\n#else\n/* Right accessors. */\n#define\trbtn_right_get(a_type, a_field, a_node)\t\t\t\t\\\n    ((a_node)->a_field.rbn_right)\n#define\trbtn_right_set(a_type, a_field, a_node, a_right) do {\t\t\\\n    (a_node)->a_field.rbn_right = a_right;\t\t\t\t\\\n} while (0)\n\n/* Color accessors. */\n#define\trbtn_red_get(a_type, a_field, a_node)\t\t\t\t\\\n    ((a_node)->a_field.rbn_red)\n#define\trbtn_color_set(a_type, a_field, a_node, a_red) do {\t\t\\\n    (a_node)->a_field.rbn_red = (a_red);\t\t\t\t\\\n} while (0)\n#define\trbtn_red_set(a_type, a_field, a_node) do {\t\t\t\\\n    (a_node)->a_field.rbn_red = true;\t\t\t\t\t\\\n} while (0)\n#define\trbtn_black_set(a_type, a_field, a_node) do {\t\t\t\\\n    (a_node)->a_field.rbn_red = false;\t\t\t\t\t\\\n} while (0)\n\n/* Node initializer. */\n#define\trbt_node_new(a_type, a_field, a_rbt, a_node) do {\t\t\\\n    rbtn_left_set(a_type, a_field, (a_node), NULL);\t\\\n    rbtn_right_set(a_type, a_field, (a_node), NULL);\t\\\n    rbtn_red_set(a_type, a_field, (a_node));\t\t\t\t\\\n} while (0)\n#endif\n\n/* Tree initializer. */\n#define\trb_new(a_type, a_field, a_rbt) do {\t\t\t\t\\\n    (a_rbt)->rbt_root = NULL;\t\t\t\t\t\t\\\n} while (0)\n\n/* Internal utility macros. */\n#define\trbtn_first(a_type, a_field, a_rbt, a_root, r_node) do {\t\t\\\n    (r_node) = (a_root);\t\t\t\t\t\t\\\n    if ((r_node) != NULL) {\t\t\t\t\t\t\\\n\tfor (;\t\t\t\t\t\t\t\t\\\n\t  rbtn_left_get(a_type, a_field, (r_node)) != NULL;\t\t\\\n\t  (r_node) = rbtn_left_get(a_type, a_field, (r_node))) {\t\\\n\t}\t\t\t\t\t\t\t\t\\\n    }\t\t\t\t\t\t\t\t\t\\\n} while (0)\n\n#define\trbtn_last(a_type, a_field, a_rbt, a_root, r_node) do {\t\t\\\n    (r_node) = (a_root);\t\t\t\t\t\t\\\n    if ((r_node) != NULL) {\t\t\t\t\t\t\\\n\tfor (; rbtn_right_get(a_type, a_field, (r_node)) != NULL;\t\\\n\t  (r_node) = rbtn_right_get(a_type, a_field, (r_node))) {\t\\\n\t}\t\t\t\t\t\t\t\t\\\n    }\t\t\t\t\t\t\t\t\t\\\n} while (0)\n\n#define\trbtn_rotate_left(a_type, a_field, a_node, r_node) do {\t\t\\\n    (r_node) = rbtn_right_get(a_type, a_field, (a_node));\t\t\\\n    rbtn_right_set(a_type, a_field, (a_node),\t\t\t\t\\\n      rbtn_left_get(a_type, a_field, (r_node)));\t\t\t\\\n    rbtn_left_set(a_type, a_field, (r_node), (a_node));\t\t\t\\\n} while (0)\n\n#define\trbtn_rotate_right(a_type, a_field, a_node, r_node) do {\t\t\\\n    (r_node) = rbtn_left_get(a_type, a_field, (a_node));\t\t\\\n    rbtn_left_set(a_type, a_field, (a_node),\t\t\t\t\\\n      rbtn_right_get(a_type, a_field, (r_node)));\t\t\t\\\n    rbtn_right_set(a_type, a_field, (r_node), (a_node));\t\t\\\n} while (0)\n\n/*\n * The rb_proto() macro generates function prototypes that correspond to the\n * functions generated by an equivalently parameterized call to rb_gen().\n */\n\n#define\trb_proto(a_attr, a_prefix, a_rbt_type, a_type)\t\t\t\\\na_attr void\t\t\t\t\t\t\t\t\\\na_prefix##new(a_rbt_type *rbtree);\t\t\t\t\t\\\na_attr bool\t\t\t\t\t\t\t\t\\\na_prefix##empty(a_rbt_type *rbtree);\t\t\t\t\t\\\na_attr a_type *\t\t\t\t\t\t\t\t\\\na_prefix##first(a_rbt_type *rbtree);\t\t\t\t\t\\\na_attr a_type *\t\t\t\t\t\t\t\t\\\na_prefix##last(a_rbt_type *rbtree);\t\t\t\t\t\\\na_attr a_type *\t\t\t\t\t\t\t\t\\\na_prefix##next(a_rbt_type *rbtree, a_type *node);\t\t\t\\\na_attr a_type *\t\t\t\t\t\t\t\t\\\na_prefix##prev(a_rbt_type *rbtree, a_type *node);\t\t\t\\\na_attr a_type *\t\t\t\t\t\t\t\t\\\na_prefix##search(a_rbt_type *rbtree, const a_type *key);\t\t\\\na_attr a_type *\t\t\t\t\t\t\t\t\\\na_prefix##nsearch(a_rbt_type *rbtree, const a_type *key);\t\t\\\na_attr a_type *\t\t\t\t\t\t\t\t\\\na_prefix##psearch(a_rbt_type *rbtree, const a_type *key);\t\t\\\na_attr void\t\t\t\t\t\t\t\t\\\na_prefix##insert(a_rbt_type *rbtree, a_type *node);\t\t\t\\\na_attr void\t\t\t\t\t\t\t\t\\\na_prefix##remove(a_rbt_type *rbtree, a_type *node);\t\t\t\\\na_attr a_type *\t\t\t\t\t\t\t\t\\\na_prefix##iter(a_rbt_type *rbtree, a_type *start, a_type *(*cb)(\t\\\n  a_rbt_type *, a_type *, void *), void *arg);\t\t\t\t\\\na_attr a_type *\t\t\t\t\t\t\t\t\\\na_prefix##reverse_iter(a_rbt_type *rbtree, a_type *start,\t\t\\\n  a_type *(*cb)(a_rbt_type *, a_type *, void *), void *arg);\t\t\\\na_attr void\t\t\t\t\t\t\t\t\\\na_prefix##destroy(a_rbt_type *rbtree, void (*cb)(a_type *, void *),\t\\\n  void *arg);\n\n/*\n * The rb_gen() macro generates a type-specific red-black tree implementation,\n * based on the above cpp macros.\n *\n * Arguments:\n *\n *   a_attr    : Function attribute for generated functions (ex: static).\n *   a_prefix  : Prefix for generated functions (ex: ex_).\n *   a_rb_type : Type for red-black tree data structure (ex: ex_t).\n *   a_type    : Type for red-black tree node data structure (ex: ex_node_t).\n *   a_field   : Name of red-black tree node linkage (ex: ex_link).\n *   a_cmp     : Node comparison function name, with the following prototype:\n *                 int (a_cmp *)(a_type *a_node, a_type *a_other);\n *                                       ^^^^^^\n *                                    or a_key\n *               Interpretation of comparison function return values:\n *                 -1 : a_node <  a_other\n *                  0 : a_node == a_other\n *                  1 : a_node >  a_other\n *               In all cases, the a_node or a_key macro argument is the first\n *               argument to the comparison function, which makes it possible\n *               to write comparison functions that treat the first argument\n *               specially.\n *\n * Assuming the following setup:\n *\n *   typedef struct ex_node_s ex_node_t;\n *   struct ex_node_s {\n *       rb_node(ex_node_t) ex_link;\n *   };\n *   typedef rb_tree(ex_node_t) ex_t;\n *   rb_gen(static, ex_, ex_t, ex_node_t, ex_link, ex_cmp)\n *\n * The following API is generated:\n *\n *   static void\n *   ex_new(ex_t *tree);\n *       Description: Initialize a red-black tree structure.\n *       Args:\n *         tree: Pointer to an uninitialized red-black tree object.\n *\n *   static bool\n *   ex_empty(ex_t *tree);\n *       Description: Determine whether tree is empty.\n *       Args:\n *         tree: Pointer to an initialized red-black tree object.\n *       Ret: True if tree is empty, false otherwise.\n *\n *   static ex_node_t *\n *   ex_first(ex_t *tree);\n *   static ex_node_t *\n *   ex_last(ex_t *tree);\n *       Description: Get the first/last node in tree.\n *       Args:\n *         tree: Pointer to an initialized red-black tree object.\n *       Ret: First/last node in tree, or NULL if tree is empty.\n *\n *   static ex_node_t *\n *   ex_next(ex_t *tree, ex_node_t *node);\n *   static ex_node_t *\n *   ex_prev(ex_t *tree, ex_node_t *node);\n *       Description: Get node's successor/predecessor.\n *       Args:\n *         tree: Pointer to an initialized red-black tree object.\n *         node: A node in tree.\n *       Ret: node's successor/predecessor in tree, or NULL if node is\n *            last/first.\n *\n *   static ex_node_t *\n *   ex_search(ex_t *tree, const ex_node_t *key);\n *       Description: Search for node that matches key.\n *       Args:\n *         tree: Pointer to an initialized red-black tree object.\n *         key : Search key.\n *       Ret: Node in tree that matches key, or NULL if no match.\n *\n *   static ex_node_t *\n *   ex_nsearch(ex_t *tree, const ex_node_t *key);\n *   static ex_node_t *\n *   ex_psearch(ex_t *tree, const ex_node_t *key);\n *       Description: Search for node that matches key.  If no match is found,\n *                    return what would be key's successor/predecessor, were\n *                    key in tree.\n *       Args:\n *         tree: Pointer to an initialized red-black tree object.\n *         key : Search key.\n *       Ret: Node in tree that matches key, or if no match, hypothetical node's\n *            successor/predecessor (NULL if no successor/predecessor).\n *\n *   static void\n *   ex_insert(ex_t *tree, ex_node_t *node);\n *       Description: Insert node into tree.\n *       Args:\n *         tree: Pointer to an initialized red-black tree object.\n *         node: Node to be inserted into tree.\n *\n *   static void\n *   ex_remove(ex_t *tree, ex_node_t *node);\n *       Description: Remove node from tree.\n *       Args:\n *         tree: Pointer to an initialized red-black tree object.\n *         node: Node in tree to be removed.\n *\n *   static ex_node_t *\n *   ex_iter(ex_t *tree, ex_node_t *start, ex_node_t *(*cb)(ex_t *,\n *     ex_node_t *, void *), void *arg);\n *   static ex_node_t *\n *   ex_reverse_iter(ex_t *tree, ex_node_t *start, ex_node *(*cb)(ex_t *,\n *     ex_node_t *, void *), void *arg);\n *       Description: Iterate forward/backward over tree, starting at node.  If\n *                    tree is modified, iteration must be immediately\n *                    terminated by the callback function that causes the\n *                    modification.\n *       Args:\n *         tree : Pointer to an initialized red-black tree object.\n *         start: Node at which to start iteration, or NULL to start at\n *                first/last node.\n *         cb   : Callback function, which is called for each node during\n *                iteration.  Under normal circumstances the callback function\n *                should return NULL, which causes iteration to continue.  If a\n *                callback function returns non-NULL, iteration is immediately\n *                terminated and the non-NULL return value is returned by the\n *                iterator.  This is useful for re-starting iteration after\n *                modifying tree.\n *         arg  : Opaque pointer passed to cb().\n *       Ret: NULL if iteration completed, or the non-NULL callback return value\n *            that caused termination of the iteration.\n *\n *   static void\n *   ex_destroy(ex_t *tree, void (*cb)(ex_node_t *, void *), void *arg);\n *       Description: Iterate over the tree with post-order traversal, remove\n *                    each node, and run the callback if non-null.  This is\n *                    used for destroying a tree without paying the cost to\n *                    rebalance it.  The tree must not be otherwise altered\n *                    during traversal.\n *       Args:\n *         tree: Pointer to an initialized red-black tree object.\n *         cb  : Callback function, which, if non-null, is called for each node\n *               during iteration.  There is no way to stop iteration once it\n *               has begun.\n *         arg : Opaque pointer passed to cb().\n */\n#define\trb_gen(a_attr, a_prefix, a_rbt_type, a_type, a_field, a_cmp)\t\\\na_attr void\t\t\t\t\t\t\t\t\\\na_prefix##new(a_rbt_type *rbtree) {\t\t\t\t\t\\\n    rb_new(a_type, a_field, rbtree);\t\t\t\t\t\\\n}\t\t\t\t\t\t\t\t\t\\\na_attr bool\t\t\t\t\t\t\t\t\\\na_prefix##empty(a_rbt_type *rbtree) {\t\t\t\t\t\\\n    return (rbtree->rbt_root == NULL);\t\t\t\t\t\\\n}\t\t\t\t\t\t\t\t\t\\\na_attr a_type *\t\t\t\t\t\t\t\t\\\na_prefix##first(a_rbt_type *rbtree) {\t\t\t\t\t\\\n    a_type *ret;\t\t\t\t\t\t\t\\\n    rbtn_first(a_type, a_field, rbtree, rbtree->rbt_root, ret);\t\t\\\n    return (ret);\t\t\t\t\t\t\t\\\n}\t\t\t\t\t\t\t\t\t\\\na_attr a_type *\t\t\t\t\t\t\t\t\\\na_prefix##last(a_rbt_type *rbtree) {\t\t\t\t\t\\\n    a_type *ret;\t\t\t\t\t\t\t\\\n    rbtn_last(a_type, a_field, rbtree, rbtree->rbt_root, ret);\t\t\\\n    return (ret);\t\t\t\t\t\t\t\\\n}\t\t\t\t\t\t\t\t\t\\\na_attr a_type *\t\t\t\t\t\t\t\t\\\na_prefix##next(a_rbt_type *rbtree, a_type *node) {\t\t\t\\\n    a_type *ret;\t\t\t\t\t\t\t\\\n    if (rbtn_right_get(a_type, a_field, node) != NULL) {\t\t\\\n\trbtn_first(a_type, a_field, rbtree, rbtn_right_get(a_type,\t\\\n\t  a_field, node), ret);\t\t\t\t\t\t\\\n    } else {\t\t\t\t\t\t\t\t\\\n\ta_type *tnode = rbtree->rbt_root;\t\t\t\t\\\n\tassert(tnode != NULL);\t\t\t\t\t\t\\\n\tret = NULL;\t\t\t\t\t\t\t\\\n\twhile (true) {\t\t\t\t\t\t\t\\\n\t    int cmp = (a_cmp)(node, tnode);\t\t\t\t\\\n\t    if (cmp < 0) {\t\t\t\t\t\t\\\n\t\tret = tnode;\t\t\t\t\t\t\\\n\t\ttnode = rbtn_left_get(a_type, a_field, tnode);\t\t\\\n\t    } else if (cmp > 0) {\t\t\t\t\t\\\n\t\ttnode = rbtn_right_get(a_type, a_field, tnode);\t\t\\\n\t    } else {\t\t\t\t\t\t\t\\\n\t\tbreak;\t\t\t\t\t\t\t\\\n\t    }\t\t\t\t\t\t\t\t\\\n\t    assert(tnode != NULL);\t\t\t\t\t\\\n\t}\t\t\t\t\t\t\t\t\\\n    }\t\t\t\t\t\t\t\t\t\\\n    return (ret);\t\t\t\t\t\t\t\\\n}\t\t\t\t\t\t\t\t\t\\\na_attr a_type *\t\t\t\t\t\t\t\t\\\na_prefix##prev(a_rbt_type *rbtree, a_type *node) {\t\t\t\\\n    a_type *ret;\t\t\t\t\t\t\t\\\n    if (rbtn_left_get(a_type, a_field, node) != NULL) {\t\t\t\\\n\trbtn_last(a_type, a_field, rbtree, rbtn_left_get(a_type,\t\\\n\t  a_field, node), ret);\t\t\t\t\t\t\\\n    } else {\t\t\t\t\t\t\t\t\\\n\ta_type *tnode = rbtree->rbt_root;\t\t\t\t\\\n\tassert(tnode != NULL);\t\t\t\t\t\t\\\n\tret = NULL;\t\t\t\t\t\t\t\\\n\twhile (true) {\t\t\t\t\t\t\t\\\n\t    int cmp = (a_cmp)(node, tnode);\t\t\t\t\\\n\t    if (cmp < 0) {\t\t\t\t\t\t\\\n\t\ttnode = rbtn_left_get(a_type, a_field, tnode);\t\t\\\n\t    } else if (cmp > 0) {\t\t\t\t\t\\\n\t\tret = tnode;\t\t\t\t\t\t\\\n\t\ttnode = rbtn_right_get(a_type, a_field, tnode);\t\t\\\n\t    } else {\t\t\t\t\t\t\t\\\n\t\tbreak;\t\t\t\t\t\t\t\\\n\t    }\t\t\t\t\t\t\t\t\\\n\t    assert(tnode != NULL);\t\t\t\t\t\\\n\t}\t\t\t\t\t\t\t\t\\\n    }\t\t\t\t\t\t\t\t\t\\\n    return (ret);\t\t\t\t\t\t\t\\\n}\t\t\t\t\t\t\t\t\t\\\na_attr a_type *\t\t\t\t\t\t\t\t\\\na_prefix##search(a_rbt_type *rbtree, const a_type *key) {\t\t\\\n    a_type *ret;\t\t\t\t\t\t\t\\\n    int cmp;\t\t\t\t\t\t\t\t\\\n    ret = rbtree->rbt_root;\t\t\t\t\t\t\\\n    while (ret != NULL\t\t\t\t\t\t\t\\\n      && (cmp = (a_cmp)(key, ret)) != 0) {\t\t\t\t\\\n\tif (cmp < 0) {\t\t\t\t\t\t\t\\\n\t    ret = rbtn_left_get(a_type, a_field, ret);\t\t\t\\\n\t} else {\t\t\t\t\t\t\t\\\n\t    ret = rbtn_right_get(a_type, a_field, ret);\t\t\t\\\n\t}\t\t\t\t\t\t\t\t\\\n    }\t\t\t\t\t\t\t\t\t\\\n    return (ret);\t\t\t\t\t\t\t\\\n}\t\t\t\t\t\t\t\t\t\\\na_attr a_type *\t\t\t\t\t\t\t\t\\\na_prefix##nsearch(a_rbt_type *rbtree, const a_type *key) {\t\t\\\n    a_type *ret;\t\t\t\t\t\t\t\\\n    a_type *tnode = rbtree->rbt_root;\t\t\t\t\t\\\n    ret = NULL;\t\t\t\t\t\t\t\t\\\n    while (tnode != NULL) {\t\t\t\t\t\t\\\n\tint cmp = (a_cmp)(key, tnode);\t\t\t\t\t\\\n\tif (cmp < 0) {\t\t\t\t\t\t\t\\\n\t    ret = tnode;\t\t\t\t\t\t\\\n\t    tnode = rbtn_left_get(a_type, a_field, tnode);\t\t\\\n\t} else if (cmp > 0) {\t\t\t\t\t\t\\\n\t    tnode = rbtn_right_get(a_type, a_field, tnode);\t\t\\\n\t} else {\t\t\t\t\t\t\t\\\n\t    ret = tnode;\t\t\t\t\t\t\\\n\t    break;\t\t\t\t\t\t\t\\\n\t}\t\t\t\t\t\t\t\t\\\n    }\t\t\t\t\t\t\t\t\t\\\n    return (ret);\t\t\t\t\t\t\t\\\n}\t\t\t\t\t\t\t\t\t\\\na_attr a_type *\t\t\t\t\t\t\t\t\\\na_prefix##psearch(a_rbt_type *rbtree, const a_type *key) {\t\t\\\n    a_type *ret;\t\t\t\t\t\t\t\\\n    a_type *tnode = rbtree->rbt_root;\t\t\t\t\t\\\n    ret = NULL;\t\t\t\t\t\t\t\t\\\n    while (tnode != NULL) {\t\t\t\t\t\t\\\n\tint cmp = (a_cmp)(key, tnode);\t\t\t\t\t\\\n\tif (cmp < 0) {\t\t\t\t\t\t\t\\\n\t    tnode = rbtn_left_get(a_type, a_field, tnode);\t\t\\\n\t} else if (cmp > 0) {\t\t\t\t\t\t\\\n\t    ret = tnode;\t\t\t\t\t\t\\\n\t    tnode = rbtn_right_get(a_type, a_field, tnode);\t\t\\\n\t} else {\t\t\t\t\t\t\t\\\n\t    ret = tnode;\t\t\t\t\t\t\\\n\t    break;\t\t\t\t\t\t\t\\\n\t}\t\t\t\t\t\t\t\t\\\n    }\t\t\t\t\t\t\t\t\t\\\n    return (ret);\t\t\t\t\t\t\t\\\n}\t\t\t\t\t\t\t\t\t\\\na_attr void\t\t\t\t\t\t\t\t\\\na_prefix##insert(a_rbt_type *rbtree, a_type *node) {\t\t\t\\\n    struct {\t\t\t\t\t\t\t\t\\\n\ta_type *node;\t\t\t\t\t\t\t\\\n\tint cmp;\t\t\t\t\t\t\t\\\n    } path[sizeof(void *) << 4], *pathp;\t\t\t\t\\\n    rbt_node_new(a_type, a_field, rbtree, node);\t\t\t\\\n    /* Wind. */\t\t\t\t\t\t\t\t\\\n    path->node = rbtree->rbt_root;\t\t\t\t\t\\\n    for (pathp = path; pathp->node != NULL; pathp++) {\t\t\t\\\n\tint cmp = pathp->cmp = a_cmp(node, pathp->node);\t\t\\\n\tassert(cmp != 0);\t\t\t\t\t\t\\\n\tif (cmp < 0) {\t\t\t\t\t\t\t\\\n\t    pathp[1].node = rbtn_left_get(a_type, a_field,\t\t\\\n\t      pathp->node);\t\t\t\t\t\t\\\n\t} else {\t\t\t\t\t\t\t\\\n\t    pathp[1].node = rbtn_right_get(a_type, a_field,\t\t\\\n\t      pathp->node);\t\t\t\t\t\t\\\n\t}\t\t\t\t\t\t\t\t\\\n    }\t\t\t\t\t\t\t\t\t\\\n    pathp->node = node;\t\t\t\t\t\t\t\\\n    /* Unwind. */\t\t\t\t\t\t\t\\\n    for (pathp--; (uintptr_t)pathp >= (uintptr_t)path; pathp--) {\t\\\n\ta_type *cnode = pathp->node;\t\t\t\t\t\\\n\tif (pathp->cmp < 0) {\t\t\t\t\t\t\\\n\t    a_type *left = pathp[1].node;\t\t\t\t\\\n\t    rbtn_left_set(a_type, a_field, cnode, left);\t\t\\\n\t    if (rbtn_red_get(a_type, a_field, left)) {\t\t\t\\\n\t\ta_type *leftleft = rbtn_left_get(a_type, a_field, left);\\\n\t\tif (leftleft != NULL && rbtn_red_get(a_type, a_field,\t\\\n\t\t  leftleft)) {\t\t\t\t\t\t\\\n\t\t    /* Fix up 4-node. */\t\t\t\t\\\n\t\t    a_type *tnode;\t\t\t\t\t\\\n\t\t    rbtn_black_set(a_type, a_field, leftleft);\t\t\\\n\t\t    rbtn_rotate_right(a_type, a_field, cnode, tnode);\t\\\n\t\t    cnode = tnode;\t\t\t\t\t\\\n\t\t}\t\t\t\t\t\t\t\\\n\t    } else {\t\t\t\t\t\t\t\\\n\t\treturn;\t\t\t\t\t\t\t\\\n\t    }\t\t\t\t\t\t\t\t\\\n\t} else {\t\t\t\t\t\t\t\\\n\t    a_type *right = pathp[1].node;\t\t\t\t\\\n\t    rbtn_right_set(a_type, a_field, cnode, right);\t\t\\\n\t    if (rbtn_red_get(a_type, a_field, right)) {\t\t\t\\\n\t\ta_type *left = rbtn_left_get(a_type, a_field, cnode);\t\\\n\t\tif (left != NULL && rbtn_red_get(a_type, a_field,\t\\\n\t\t  left)) {\t\t\t\t\t\t\\\n\t\t    /* Split 4-node. */\t\t\t\t\t\\\n\t\t    rbtn_black_set(a_type, a_field, left);\t\t\\\n\t\t    rbtn_black_set(a_type, a_field, right);\t\t\\\n\t\t    rbtn_red_set(a_type, a_field, cnode);\t\t\\\n\t\t} else {\t\t\t\t\t\t\\\n\t\t    /* Lean left. */\t\t\t\t\t\\\n\t\t    a_type *tnode;\t\t\t\t\t\\\n\t\t    bool tred = rbtn_red_get(a_type, a_field, cnode);\t\\\n\t\t    rbtn_rotate_left(a_type, a_field, cnode, tnode);\t\\\n\t\t    rbtn_color_set(a_type, a_field, tnode, tred);\t\\\n\t\t    rbtn_red_set(a_type, a_field, cnode);\t\t\\\n\t\t    cnode = tnode;\t\t\t\t\t\\\n\t\t}\t\t\t\t\t\t\t\\\n\t    } else {\t\t\t\t\t\t\t\\\n\t\treturn;\t\t\t\t\t\t\t\\\n\t    }\t\t\t\t\t\t\t\t\\\n\t}\t\t\t\t\t\t\t\t\\\n\tpathp->node = cnode;\t\t\t\t\t\t\\\n    }\t\t\t\t\t\t\t\t\t\\\n    /* Set root, and make it black. */\t\t\t\t\t\\\n    rbtree->rbt_root = path->node;\t\t\t\t\t\\\n    rbtn_black_set(a_type, a_field, rbtree->rbt_root);\t\t\t\\\n}\t\t\t\t\t\t\t\t\t\\\na_attr void\t\t\t\t\t\t\t\t\\\na_prefix##remove(a_rbt_type *rbtree, a_type *node) {\t\t\t\\\n    struct {\t\t\t\t\t\t\t\t\\\n\ta_type *node;\t\t\t\t\t\t\t\\\n\tint cmp;\t\t\t\t\t\t\t\\\n    } *pathp, *nodep, path[sizeof(void *) << 4];\t\t\t\\\n    /* Wind. */\t\t\t\t\t\t\t\t\\\n    nodep = NULL; /* Silence compiler warning. */\t\t\t\\\n    path->node = rbtree->rbt_root;\t\t\t\t\t\\\n    for (pathp = path; pathp->node != NULL; pathp++) {\t\t\t\\\n\tint cmp = pathp->cmp = a_cmp(node, pathp->node);\t\t\\\n\tif (cmp < 0) {\t\t\t\t\t\t\t\\\n\t    pathp[1].node = rbtn_left_get(a_type, a_field,\t\t\\\n\t      pathp->node);\t\t\t\t\t\t\\\n\t} else {\t\t\t\t\t\t\t\\\n\t    pathp[1].node = rbtn_right_get(a_type, a_field,\t\t\\\n\t      pathp->node);\t\t\t\t\t\t\\\n\t    if (cmp == 0) {\t\t\t\t\t\t\\\n\t        /* Find node's successor, in preparation for swap. */\t\\\n\t\tpathp->cmp = 1;\t\t\t\t\t\t\\\n\t\tnodep = pathp;\t\t\t\t\t\t\\\n\t\tfor (pathp++; pathp->node != NULL;\t\t\t\\\n\t\t  pathp++) {\t\t\t\t\t\t\\\n\t\t    pathp->cmp = -1;\t\t\t\t\t\\\n\t\t    pathp[1].node = rbtn_left_get(a_type, a_field,\t\\\n\t\t      pathp->node);\t\t\t\t\t\\\n\t\t}\t\t\t\t\t\t\t\\\n\t\tbreak;\t\t\t\t\t\t\t\\\n\t    }\t\t\t\t\t\t\t\t\\\n\t}\t\t\t\t\t\t\t\t\\\n    }\t\t\t\t\t\t\t\t\t\\\n    assert(nodep->node == node);\t\t\t\t\t\\\n    pathp--;\t\t\t\t\t\t\t\t\\\n    if (pathp->node != node) {\t\t\t\t\t\t\\\n\t/* Swap node with its successor. */\t\t\t\t\\\n\tbool tred = rbtn_red_get(a_type, a_field, pathp->node);\t\t\\\n\trbtn_color_set(a_type, a_field, pathp->node,\t\t\t\\\n\t  rbtn_red_get(a_type, a_field, node));\t\t\t\t\\\n\trbtn_left_set(a_type, a_field, pathp->node,\t\t\t\\\n\t  rbtn_left_get(a_type, a_field, node));\t\t\t\\\n\t/* If node's successor is its right child, the following code */\\\n\t/* will do the wrong thing for the right child pointer.       */\\\n\t/* However, it doesn't matter, because the pointer will be    */\\\n\t/* properly set when the successor is pruned.                 */\\\n\trbtn_right_set(a_type, a_field, pathp->node,\t\t\t\\\n\t  rbtn_right_get(a_type, a_field, node));\t\t\t\\\n\trbtn_color_set(a_type, a_field, node, tred);\t\t\t\\\n\t/* The pruned leaf node's child pointers are never accessed   */\\\n\t/* again, so don't bother setting them to nil.                */\\\n\tnodep->node = pathp->node;\t\t\t\t\t\\\n\tpathp->node = node;\t\t\t\t\t\t\\\n\tif (nodep == path) {\t\t\t\t\t\t\\\n\t    rbtree->rbt_root = nodep->node;\t\t\t\t\\\n\t} else {\t\t\t\t\t\t\t\\\n\t    if (nodep[-1].cmp < 0) {\t\t\t\t\t\\\n\t\trbtn_left_set(a_type, a_field, nodep[-1].node,\t\t\\\n\t\t  nodep->node);\t\t\t\t\t\t\\\n\t    } else {\t\t\t\t\t\t\t\\\n\t\trbtn_right_set(a_type, a_field, nodep[-1].node,\t\t\\\n\t\t  nodep->node);\t\t\t\t\t\t\\\n\t    }\t\t\t\t\t\t\t\t\\\n\t}\t\t\t\t\t\t\t\t\\\n    } else {\t\t\t\t\t\t\t\t\\\n\ta_type *left = rbtn_left_get(a_type, a_field, node);\t\t\\\n\tif (left != NULL) {\t\t\t\t\t\t\\\n\t    /* node has no successor, but it has a left child.        */\\\n\t    /* Splice node out, without losing the left child.        */\\\n\t    assert(!rbtn_red_get(a_type, a_field, node));\t\t\\\n\t    assert(rbtn_red_get(a_type, a_field, left));\t\t\\\n\t    rbtn_black_set(a_type, a_field, left);\t\t\t\\\n\t    if (pathp == path) {\t\t\t\t\t\\\n\t\trbtree->rbt_root = left;\t\t\t\t\\\n\t    } else {\t\t\t\t\t\t\t\\\n\t\tif (pathp[-1].cmp < 0) {\t\t\t\t\\\n\t\t    rbtn_left_set(a_type, a_field, pathp[-1].node,\t\\\n\t\t      left);\t\t\t\t\t\t\\\n\t\t} else {\t\t\t\t\t\t\\\n\t\t    rbtn_right_set(a_type, a_field, pathp[-1].node,\t\\\n\t\t      left);\t\t\t\t\t\t\\\n\t\t}\t\t\t\t\t\t\t\\\n\t    }\t\t\t\t\t\t\t\t\\\n\t    return;\t\t\t\t\t\t\t\\\n\t} else if (pathp == path) {\t\t\t\t\t\\\n\t    /* The tree only contained one node. */\t\t\t\\\n\t    rbtree->rbt_root = NULL;\t\t\t\t\t\\\n\t    return;\t\t\t\t\t\t\t\\\n\t}\t\t\t\t\t\t\t\t\\\n    }\t\t\t\t\t\t\t\t\t\\\n    if (rbtn_red_get(a_type, a_field, pathp->node)) {\t\t\t\\\n\t/* Prune red node, which requires no fixup. */\t\t\t\\\n\tassert(pathp[-1].cmp < 0);\t\t\t\t\t\\\n\trbtn_left_set(a_type, a_field, pathp[-1].node, NULL);\t\t\\\n\treturn;\t\t\t\t\t\t\t\t\\\n    }\t\t\t\t\t\t\t\t\t\\\n    /* The node to be pruned is black, so unwind until balance is     */\\\n    /* restored.                                                      */\\\n    pathp->node = NULL;\t\t\t\t\t\t\t\\\n    for (pathp--; (uintptr_t)pathp >= (uintptr_t)path; pathp--) {\t\\\n\tassert(pathp->cmp != 0);\t\t\t\t\t\\\n\tif (pathp->cmp < 0) {\t\t\t\t\t\t\\\n\t    rbtn_left_set(a_type, a_field, pathp->node,\t\t\t\\\n\t      pathp[1].node);\t\t\t\t\t\t\\\n\t    if (rbtn_red_get(a_type, a_field, pathp->node)) {\t\t\\\n\t\ta_type *right = rbtn_right_get(a_type, a_field,\t\t\\\n\t\t  pathp->node);\t\t\t\t\t\t\\\n\t\ta_type *rightleft = rbtn_left_get(a_type, a_field,\t\\\n\t\t  right);\t\t\t\t\t\t\\\n\t\ta_type *tnode;\t\t\t\t\t\t\\\n\t\tif (rightleft != NULL && rbtn_red_get(a_type, a_field,\t\\\n\t\t  rightleft)) {\t\t\t\t\t\t\\\n\t\t    /* In the following diagrams, ||, //, and \\\\      */\\\n\t\t    /* indicate the path to the removed node.         */\\\n\t\t    /*                                                */\\\n\t\t    /*      ||                                        */\\\n\t\t    /*    pathp(r)                                    */\\\n\t\t    /*  //        \\                                   */\\\n\t\t    /* (b)        (b)                                 */\\\n\t\t    /*           /                                    */\\\n\t\t    /*          (r)                                   */\\\n\t\t    /*                                                */\\\n\t\t    rbtn_black_set(a_type, a_field, pathp->node);\t\\\n\t\t    rbtn_rotate_right(a_type, a_field, right, tnode);\t\\\n\t\t    rbtn_right_set(a_type, a_field, pathp->node, tnode);\\\n\t\t    rbtn_rotate_left(a_type, a_field, pathp->node,\t\\\n\t\t      tnode);\t\t\t\t\t\t\\\n\t\t} else {\t\t\t\t\t\t\\\n\t\t    /*      ||                                        */\\\n\t\t    /*    pathp(r)                                    */\\\n\t\t    /*  //        \\                                   */\\\n\t\t    /* (b)        (b)                                 */\\\n\t\t    /*           /                                    */\\\n\t\t    /*          (b)                                   */\\\n\t\t    /*                                                */\\\n\t\t    rbtn_rotate_left(a_type, a_field, pathp->node,\t\\\n\t\t      tnode);\t\t\t\t\t\t\\\n\t\t}\t\t\t\t\t\t\t\\\n\t\t/* Balance restored, but rotation modified subtree    */\\\n\t\t/* root.                                              */\\\n\t\tassert((uintptr_t)pathp > (uintptr_t)path);\t\t\\\n\t\tif (pathp[-1].cmp < 0) {\t\t\t\t\\\n\t\t    rbtn_left_set(a_type, a_field, pathp[-1].node,\t\\\n\t\t      tnode);\t\t\t\t\t\t\\\n\t\t} else {\t\t\t\t\t\t\\\n\t\t    rbtn_right_set(a_type, a_field, pathp[-1].node,\t\\\n\t\t      tnode);\t\t\t\t\t\t\\\n\t\t}\t\t\t\t\t\t\t\\\n\t\treturn;\t\t\t\t\t\t\t\\\n\t    } else {\t\t\t\t\t\t\t\\\n\t\ta_type *right = rbtn_right_get(a_type, a_field,\t\t\\\n\t\t  pathp->node);\t\t\t\t\t\t\\\n\t\ta_type *rightleft = rbtn_left_get(a_type, a_field,\t\\\n\t\t  right);\t\t\t\t\t\t\\\n\t\tif (rightleft != NULL && rbtn_red_get(a_type, a_field,\t\\\n\t\t  rightleft)) {\t\t\t\t\t\t\\\n\t\t    /*      ||                                        */\\\n\t\t    /*    pathp(b)                                    */\\\n\t\t    /*  //        \\                                   */\\\n\t\t    /* (b)        (b)                                 */\\\n\t\t    /*           /                                    */\\\n\t\t    /*          (r)                                   */\\\n\t\t    a_type *tnode;\t\t\t\t\t\\\n\t\t    rbtn_black_set(a_type, a_field, rightleft);\t\t\\\n\t\t    rbtn_rotate_right(a_type, a_field, right, tnode);\t\\\n\t\t    rbtn_right_set(a_type, a_field, pathp->node, tnode);\\\n\t\t    rbtn_rotate_left(a_type, a_field, pathp->node,\t\\\n\t\t      tnode);\t\t\t\t\t\t\\\n\t\t    /* Balance restored, but rotation modified        */\\\n\t\t    /* subtree root, which may actually be the tree   */\\\n\t\t    /* root.                                          */\\\n\t\t    if (pathp == path) {\t\t\t\t\\\n\t\t\t/* Set root. */\t\t\t\t\t\\\n\t\t\trbtree->rbt_root = tnode;\t\t\t\\\n\t\t    } else {\t\t\t\t\t\t\\\n\t\t\tif (pathp[-1].cmp < 0) {\t\t\t\\\n\t\t\t    rbtn_left_set(a_type, a_field,\t\t\\\n\t\t\t      pathp[-1].node, tnode);\t\t\t\\\n\t\t\t} else {\t\t\t\t\t\\\n\t\t\t    rbtn_right_set(a_type, a_field,\t\t\\\n\t\t\t      pathp[-1].node, tnode);\t\t\t\\\n\t\t\t}\t\t\t\t\t\t\\\n\t\t    }\t\t\t\t\t\t\t\\\n\t\t    return;\t\t\t\t\t\t\\\n\t\t} else {\t\t\t\t\t\t\\\n\t\t    /*      ||                                        */\\\n\t\t    /*    pathp(b)                                    */\\\n\t\t    /*  //        \\                                   */\\\n\t\t    /* (b)        (b)                                 */\\\n\t\t    /*           /                                    */\\\n\t\t    /*          (b)                                   */\\\n\t\t    a_type *tnode;\t\t\t\t\t\\\n\t\t    rbtn_red_set(a_type, a_field, pathp->node);\t\t\\\n\t\t    rbtn_rotate_left(a_type, a_field, pathp->node,\t\\\n\t\t      tnode);\t\t\t\t\t\t\\\n\t\t    pathp->node = tnode;\t\t\t\t\\\n\t\t}\t\t\t\t\t\t\t\\\n\t    }\t\t\t\t\t\t\t\t\\\n\t} else {\t\t\t\t\t\t\t\\\n\t    a_type *left;\t\t\t\t\t\t\\\n\t    rbtn_right_set(a_type, a_field, pathp->node,\t\t\\\n\t      pathp[1].node);\t\t\t\t\t\t\\\n\t    left = rbtn_left_get(a_type, a_field, pathp->node);\t\t\\\n\t    if (rbtn_red_get(a_type, a_field, left)) {\t\t\t\\\n\t\ta_type *tnode;\t\t\t\t\t\t\\\n\t\ta_type *leftright = rbtn_right_get(a_type, a_field,\t\\\n\t\t  left);\t\t\t\t\t\t\\\n\t\ta_type *leftrightleft = rbtn_left_get(a_type, a_field,\t\\\n\t\t  leftright);\t\t\t\t\t\t\\\n\t\tif (leftrightleft != NULL && rbtn_red_get(a_type,\t\\\n\t\t  a_field, leftrightleft)) {\t\t\t\t\\\n\t\t    /*      ||                                        */\\\n\t\t    /*    pathp(b)                                    */\\\n\t\t    /*   /        \\\\                                  */\\\n\t\t    /* (r)        (b)                                 */\\\n\t\t    /*   \\                                            */\\\n\t\t    /*   (b)                                          */\\\n\t\t    /*   /                                            */\\\n\t\t    /* (r)                                            */\\\n\t\t    a_type *unode;\t\t\t\t\t\\\n\t\t    rbtn_black_set(a_type, a_field, leftrightleft);\t\\\n\t\t    rbtn_rotate_right(a_type, a_field, pathp->node,\t\\\n\t\t      unode);\t\t\t\t\t\t\\\n\t\t    rbtn_rotate_right(a_type, a_field, pathp->node,\t\\\n\t\t      tnode);\t\t\t\t\t\t\\\n\t\t    rbtn_right_set(a_type, a_field, unode, tnode);\t\\\n\t\t    rbtn_rotate_left(a_type, a_field, unode, tnode);\t\\\n\t\t} else {\t\t\t\t\t\t\\\n\t\t    /*      ||                                        */\\\n\t\t    /*    pathp(b)                                    */\\\n\t\t    /*   /        \\\\                                  */\\\n\t\t    /* (r)        (b)                                 */\\\n\t\t    /*   \\                                            */\\\n\t\t    /*   (b)                                          */\\\n\t\t    /*   /                                            */\\\n\t\t    /* (b)                                            */\\\n\t\t    assert(leftright != NULL);\t\t\t\t\\\n\t\t    rbtn_red_set(a_type, a_field, leftright);\t\t\\\n\t\t    rbtn_rotate_right(a_type, a_field, pathp->node,\t\\\n\t\t      tnode);\t\t\t\t\t\t\\\n\t\t    rbtn_black_set(a_type, a_field, tnode);\t\t\\\n\t\t}\t\t\t\t\t\t\t\\\n\t\t/* Balance restored, but rotation modified subtree    */\\\n\t\t/* root, which may actually be the tree root.         */\\\n\t\tif (pathp == path) {\t\t\t\t\t\\\n\t\t    /* Set root. */\t\t\t\t\t\\\n\t\t    rbtree->rbt_root = tnode;\t\t\t\t\\\n\t\t} else {\t\t\t\t\t\t\\\n\t\t    if (pathp[-1].cmp < 0) {\t\t\t\t\\\n\t\t\trbtn_left_set(a_type, a_field, pathp[-1].node,\t\\\n\t\t\t  tnode);\t\t\t\t\t\\\n\t\t    } else {\t\t\t\t\t\t\\\n\t\t\trbtn_right_set(a_type, a_field, pathp[-1].node,\t\\\n\t\t\t  tnode);\t\t\t\t\t\\\n\t\t    }\t\t\t\t\t\t\t\\\n\t\t}\t\t\t\t\t\t\t\\\n\t\treturn;\t\t\t\t\t\t\t\\\n\t    } else if (rbtn_red_get(a_type, a_field, pathp->node)) {\t\\\n\t\ta_type *leftleft = rbtn_left_get(a_type, a_field, left);\\\n\t\tif (leftleft != NULL && rbtn_red_get(a_type, a_field,\t\\\n\t\t  leftleft)) {\t\t\t\t\t\t\\\n\t\t    /*        ||                                      */\\\n\t\t    /*      pathp(r)                                  */\\\n\t\t    /*     /        \\\\                                */\\\n\t\t    /*   (b)        (b)                               */\\\n\t\t    /*   /                                            */\\\n\t\t    /* (r)                                            */\\\n\t\t    a_type *tnode;\t\t\t\t\t\\\n\t\t    rbtn_black_set(a_type, a_field, pathp->node);\t\\\n\t\t    rbtn_red_set(a_type, a_field, left);\t\t\\\n\t\t    rbtn_black_set(a_type, a_field, leftleft);\t\t\\\n\t\t    rbtn_rotate_right(a_type, a_field, pathp->node,\t\\\n\t\t      tnode);\t\t\t\t\t\t\\\n\t\t    /* Balance restored, but rotation modified        */\\\n\t\t    /* subtree root.                                  */\\\n\t\t    assert((uintptr_t)pathp > (uintptr_t)path);\t\t\\\n\t\t    if (pathp[-1].cmp < 0) {\t\t\t\t\\\n\t\t\trbtn_left_set(a_type, a_field, pathp[-1].node,\t\\\n\t\t\t  tnode);\t\t\t\t\t\\\n\t\t    } else {\t\t\t\t\t\t\\\n\t\t\trbtn_right_set(a_type, a_field, pathp[-1].node,\t\\\n\t\t\t  tnode);\t\t\t\t\t\\\n\t\t    }\t\t\t\t\t\t\t\\\n\t\t    return;\t\t\t\t\t\t\\\n\t\t} else {\t\t\t\t\t\t\\\n\t\t    /*        ||                                      */\\\n\t\t    /*      pathp(r)                                  */\\\n\t\t    /*     /        \\\\                                */\\\n\t\t    /*   (b)        (b)                               */\\\n\t\t    /*   /                                            */\\\n\t\t    /* (b)                                            */\\\n\t\t    rbtn_red_set(a_type, a_field, left);\t\t\\\n\t\t    rbtn_black_set(a_type, a_field, pathp->node);\t\\\n\t\t    /* Balance restored. */\t\t\t\t\\\n\t\t    return;\t\t\t\t\t\t\\\n\t\t}\t\t\t\t\t\t\t\\\n\t    } else {\t\t\t\t\t\t\t\\\n\t\ta_type *leftleft = rbtn_left_get(a_type, a_field, left);\\\n\t\tif (leftleft != NULL && rbtn_red_get(a_type, a_field,\t\\\n\t\t  leftleft)) {\t\t\t\t\t\t\\\n\t\t    /*               ||                               */\\\n\t\t    /*             pathp(b)                           */\\\n\t\t    /*            /        \\\\                         */\\\n\t\t    /*          (b)        (b)                        */\\\n\t\t    /*          /                                     */\\\n\t\t    /*        (r)                                     */\\\n\t\t    a_type *tnode;\t\t\t\t\t\\\n\t\t    rbtn_black_set(a_type, a_field, leftleft);\t\t\\\n\t\t    rbtn_rotate_right(a_type, a_field, pathp->node,\t\\\n\t\t      tnode);\t\t\t\t\t\t\\\n\t\t    /* Balance restored, but rotation modified        */\\\n\t\t    /* subtree root, which may actually be the tree   */\\\n\t\t    /* root.                                          */\\\n\t\t    if (pathp == path) {\t\t\t\t\\\n\t\t\t/* Set root. */\t\t\t\t\t\\\n\t\t\trbtree->rbt_root = tnode;\t\t\t\\\n\t\t    } else {\t\t\t\t\t\t\\\n\t\t\tif (pathp[-1].cmp < 0) {\t\t\t\\\n\t\t\t    rbtn_left_set(a_type, a_field,\t\t\\\n\t\t\t      pathp[-1].node, tnode);\t\t\t\\\n\t\t\t} else {\t\t\t\t\t\\\n\t\t\t    rbtn_right_set(a_type, a_field,\t\t\\\n\t\t\t      pathp[-1].node, tnode);\t\t\t\\\n\t\t\t}\t\t\t\t\t\t\\\n\t\t    }\t\t\t\t\t\t\t\\\n\t\t    return;\t\t\t\t\t\t\\\n\t\t} else {\t\t\t\t\t\t\\\n\t\t    /*               ||                               */\\\n\t\t    /*             pathp(b)                           */\\\n\t\t    /*            /        \\\\                         */\\\n\t\t    /*          (b)        (b)                        */\\\n\t\t    /*          /                                     */\\\n\t\t    /*        (b)                                     */\\\n\t\t    rbtn_red_set(a_type, a_field, left);\t\t\\\n\t\t}\t\t\t\t\t\t\t\\\n\t    }\t\t\t\t\t\t\t\t\\\n\t}\t\t\t\t\t\t\t\t\\\n    }\t\t\t\t\t\t\t\t\t\\\n    /* Set root. */\t\t\t\t\t\t\t\\\n    rbtree->rbt_root = path->node;\t\t\t\t\t\\\n    assert(!rbtn_red_get(a_type, a_field, rbtree->rbt_root));\t\t\\\n}\t\t\t\t\t\t\t\t\t\\\na_attr a_type *\t\t\t\t\t\t\t\t\\\na_prefix##iter_recurse(a_rbt_type *rbtree, a_type *node,\t\t\\\n  a_type *(*cb)(a_rbt_type *, a_type *, void *), void *arg) {\t\t\\\n    if (node == NULL) {\t\t\t\t\t\t\t\\\n\treturn (NULL);\t\t\t\t\t\t\t\\\n    } else {\t\t\t\t\t\t\t\t\\\n\ta_type *ret;\t\t\t\t\t\t\t\\\n\tif ((ret = a_prefix##iter_recurse(rbtree, rbtn_left_get(a_type,\t\\\n\t  a_field, node), cb, arg)) != NULL || (ret = cb(rbtree, node,\t\\\n\t  arg)) != NULL) {\t\t\t\t\t\t\\\n\t    return (ret);\t\t\t\t\t\t\\\n\t}\t\t\t\t\t\t\t\t\\\n\treturn (a_prefix##iter_recurse(rbtree, rbtn_right_get(a_type,\t\\\n\t  a_field, node), cb, arg));\t\t\t\t\t\\\n    }\t\t\t\t\t\t\t\t\t\\\n}\t\t\t\t\t\t\t\t\t\\\na_attr a_type *\t\t\t\t\t\t\t\t\\\na_prefix##iter_start(a_rbt_type *rbtree, a_type *start, a_type *node,\t\\\n  a_type *(*cb)(a_rbt_type *, a_type *, void *), void *arg) {\t\t\\\n    int cmp = a_cmp(start, node);\t\t\t\t\t\\\n    if (cmp < 0) {\t\t\t\t\t\t\t\\\n\ta_type *ret;\t\t\t\t\t\t\t\\\n\tif ((ret = a_prefix##iter_start(rbtree, start,\t\t\t\\\n\t  rbtn_left_get(a_type, a_field, node), cb, arg)) != NULL ||\t\\\n\t  (ret = cb(rbtree, node, arg)) != NULL) {\t\t\t\\\n\t    return (ret);\t\t\t\t\t\t\\\n\t}\t\t\t\t\t\t\t\t\\\n\treturn (a_prefix##iter_recurse(rbtree, rbtn_right_get(a_type,\t\\\n\t  a_field, node), cb, arg));\t\t\t\t\t\\\n    } else if (cmp > 0) {\t\t\t\t\t\t\\\n\treturn (a_prefix##iter_start(rbtree, start,\t\t\t\\\n\t  rbtn_right_get(a_type, a_field, node), cb, arg));\t\t\\\n    } else {\t\t\t\t\t\t\t\t\\\n\ta_type *ret;\t\t\t\t\t\t\t\\\n\tif ((ret = cb(rbtree, node, arg)) != NULL) {\t\t\t\\\n\t    return (ret);\t\t\t\t\t\t\\\n\t}\t\t\t\t\t\t\t\t\\\n\treturn (a_prefix##iter_recurse(rbtree, rbtn_right_get(a_type,\t\\\n\t  a_field, node), cb, arg));\t\t\t\t\t\\\n    }\t\t\t\t\t\t\t\t\t\\\n}\t\t\t\t\t\t\t\t\t\\\na_attr a_type *\t\t\t\t\t\t\t\t\\\na_prefix##iter(a_rbt_type *rbtree, a_type *start, a_type *(*cb)(\t\\\n  a_rbt_type *, a_type *, void *), void *arg) {\t\t\t\t\\\n    a_type *ret;\t\t\t\t\t\t\t\\\n    if (start != NULL) {\t\t\t\t\t\t\\\n\tret = a_prefix##iter_start(rbtree, start, rbtree->rbt_root,\t\\\n\t  cb, arg);\t\t\t\t\t\t\t\\\n    } else {\t\t\t\t\t\t\t\t\\\n\tret = a_prefix##iter_recurse(rbtree, rbtree->rbt_root, cb, arg);\\\n    }\t\t\t\t\t\t\t\t\t\\\n    return (ret);\t\t\t\t\t\t\t\\\n}\t\t\t\t\t\t\t\t\t\\\na_attr a_type *\t\t\t\t\t\t\t\t\\\na_prefix##reverse_iter_recurse(a_rbt_type *rbtree, a_type *node,\t\\\n  a_type *(*cb)(a_rbt_type *, a_type *, void *), void *arg) {\t\t\\\n    if (node == NULL) {\t\t\t\t\t\t\t\\\n\treturn (NULL);\t\t\t\t\t\t\t\\\n    } else {\t\t\t\t\t\t\t\t\\\n\ta_type *ret;\t\t\t\t\t\t\t\\\n\tif ((ret = a_prefix##reverse_iter_recurse(rbtree,\t\t\\\n\t  rbtn_right_get(a_type, a_field, node), cb, arg)) != NULL ||\t\\\n\t  (ret = cb(rbtree, node, arg)) != NULL) {\t\t\t\\\n\t    return (ret);\t\t\t\t\t\t\\\n\t}\t\t\t\t\t\t\t\t\\\n\treturn (a_prefix##reverse_iter_recurse(rbtree,\t\t\t\\\n\t  rbtn_left_get(a_type, a_field, node), cb, arg));\t\t\\\n    }\t\t\t\t\t\t\t\t\t\\\n}\t\t\t\t\t\t\t\t\t\\\na_attr a_type *\t\t\t\t\t\t\t\t\\\na_prefix##reverse_iter_start(a_rbt_type *rbtree, a_type *start,\t\t\\\n  a_type *node, a_type *(*cb)(a_rbt_type *, a_type *, void *),\t\t\\\n  void *arg) {\t\t\t\t\t\t\t\t\\\n    int cmp = a_cmp(start, node);\t\t\t\t\t\\\n    if (cmp > 0) {\t\t\t\t\t\t\t\\\n\ta_type *ret;\t\t\t\t\t\t\t\\\n\tif ((ret = a_prefix##reverse_iter_start(rbtree, start,\t\t\\\n\t  rbtn_right_get(a_type, a_field, node), cb, arg)) != NULL ||\t\\\n\t  (ret = cb(rbtree, node, arg)) != NULL) {\t\t\t\\\n\t    return (ret);\t\t\t\t\t\t\\\n\t}\t\t\t\t\t\t\t\t\\\n\treturn (a_prefix##reverse_iter_recurse(rbtree,\t\t\t\\\n\t  rbtn_left_get(a_type, a_field, node), cb, arg));\t\t\\\n    } else if (cmp < 0) {\t\t\t\t\t\t\\\n\treturn (a_prefix##reverse_iter_start(rbtree, start,\t\t\\\n\t  rbtn_left_get(a_type, a_field, node), cb, arg));\t\t\\\n    } else {\t\t\t\t\t\t\t\t\\\n\ta_type *ret;\t\t\t\t\t\t\t\\\n\tif ((ret = cb(rbtree, node, arg)) != NULL) {\t\t\t\\\n\t    return (ret);\t\t\t\t\t\t\\\n\t}\t\t\t\t\t\t\t\t\\\n\treturn (a_prefix##reverse_iter_recurse(rbtree,\t\t\t\\\n\t  rbtn_left_get(a_type, a_field, node), cb, arg));\t\t\\\n    }\t\t\t\t\t\t\t\t\t\\\n}\t\t\t\t\t\t\t\t\t\\\na_attr a_type *\t\t\t\t\t\t\t\t\\\na_prefix##reverse_iter(a_rbt_type *rbtree, a_type *start,\t\t\\\n  a_type *(*cb)(a_rbt_type *, a_type *, void *), void *arg) {\t\t\\\n    a_type *ret;\t\t\t\t\t\t\t\\\n    if (start != NULL) {\t\t\t\t\t\t\\\n\tret = a_prefix##reverse_iter_start(rbtree, start,\t\t\\\n\t  rbtree->rbt_root, cb, arg);\t\t\t\t\t\\\n    } else {\t\t\t\t\t\t\t\t\\\n\tret = a_prefix##reverse_iter_recurse(rbtree, rbtree->rbt_root,\t\\\n\t  cb, arg);\t\t\t\t\t\t\t\\\n    }\t\t\t\t\t\t\t\t\t\\\n    return (ret);\t\t\t\t\t\t\t\\\n}\t\t\t\t\t\t\t\t\t\\\na_attr void\t\t\t\t\t\t\t\t\\\na_prefix##destroy_recurse(a_rbt_type *rbtree, a_type *node, void (*cb)(\t\\\n  a_type *, void *), void *arg) {\t\t\t\t\t\\\n    if (node == NULL) {\t\t\t\t\t\t\t\\\n\treturn;\t\t\t\t\t\t\t\t\\\n    }\t\t\t\t\t\t\t\t\t\\\n    a_prefix##destroy_recurse(rbtree, rbtn_left_get(a_type, a_field,\t\\\n      node), cb, arg);\t\t\t\t\t\t\t\\\n    rbtn_left_set(a_type, a_field, (node), NULL);\t\t\t\\\n    a_prefix##destroy_recurse(rbtree, rbtn_right_get(a_type, a_field,\t\\\n      node), cb, arg);\t\t\t\t\t\t\t\\\n    rbtn_right_set(a_type, a_field, (node), NULL);\t\t\t\\\n    if (cb) {\t\t\t\t\t\t\t\t\\\n\tcb(node, arg);\t\t\t\t\t\t\t\\\n    }\t\t\t\t\t\t\t\t\t\\\n}\t\t\t\t\t\t\t\t\t\\\na_attr void\t\t\t\t\t\t\t\t\\\na_prefix##destroy(a_rbt_type *rbtree, void (*cb)(a_type *, void *),\t\\\n  void *arg) {\t\t\t\t\t\t\t\t\\\n    a_prefix##destroy_recurse(rbtree, rbtree->rbt_root, cb, arg);\t\\\n    rbtree->rbt_root = NULL;\t\t\t\t\t\t\\\n}\n\n#endif /* RB_H_ */\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/deps/jemalloc/include/jemalloc/internal/rtree.h",
    "content": "/*\n * This radix tree implementation is tailored to the singular purpose of\n * associating metadata with chunks that are currently owned by jemalloc.\n *\n *******************************************************************************\n */\n#ifdef JEMALLOC_H_TYPES\n\ntypedef struct rtree_node_elm_s rtree_node_elm_t;\ntypedef struct rtree_level_s rtree_level_t;\ntypedef struct rtree_s rtree_t;\n\n/*\n * RTREE_BITS_PER_LEVEL must be a power of two that is no larger than the\n * machine address width.\n */\n#define\tLG_RTREE_BITS_PER_LEVEL\t4\n#define\tRTREE_BITS_PER_LEVEL\t(1U << LG_RTREE_BITS_PER_LEVEL)\n/* Maximum rtree height. */\n#define\tRTREE_HEIGHT_MAX\t\t\t\t\t\t\\\n    ((1U << (LG_SIZEOF_PTR+3)) / RTREE_BITS_PER_LEVEL)\n\n/* Used for two-stage lock-free node initialization. */\n#define\tRTREE_NODE_INITIALIZING\t((rtree_node_elm_t *)0x1)\n\n/*\n * The node allocation callback function's argument is the number of contiguous\n * rtree_node_elm_t structures to allocate, and the resulting memory must be\n * zeroed.\n */\ntypedef rtree_node_elm_t *(rtree_node_alloc_t)(size_t);\ntypedef void (rtree_node_dalloc_t)(rtree_node_elm_t *);\n\n#endif /* JEMALLOC_H_TYPES */\n/******************************************************************************/\n#ifdef JEMALLOC_H_STRUCTS\n\nstruct rtree_node_elm_s {\n\tunion {\n\t\tvoid\t\t\t*pun;\n\t\trtree_node_elm_t\t*child;\n\t\textent_node_t\t\t*val;\n\t};\n};\n\nstruct rtree_level_s {\n\t/*\n\t * A non-NULL subtree points to a subtree rooted along the hypothetical\n\t * path to the leaf node corresponding to key 0.  Depending on what keys\n\t * have been used to store to the tree, an arbitrary combination of\n\t * subtree pointers may remain NULL.\n\t *\n\t * Suppose keys comprise 48 bits, and LG_RTREE_BITS_PER_LEVEL is 4.\n\t * This results in a 3-level tree, and the leftmost leaf can be directly\n\t * accessed via subtrees[2], the subtree prefixed by 0x0000 (excluding\n\t * 0x00000000) can be accessed via subtrees[1], and the remainder of the\n\t * tree can be accessed via subtrees[0].\n\t *\n\t *   levels[0] : [<unused> | 0x0001******** | 0x0002******** | ...]\n\t *\n\t *   levels[1] : [<unused> | 0x00000001**** | 0x00000002**** | ... ]\n\t *\n\t *   levels[2] : [val(0x000000000000) | val(0x000000000001) | ...]\n\t *\n\t * This has practical implications on x64, which currently uses only the\n\t * lower 47 bits of virtual address space in userland, thus leaving\n\t * subtrees[0] unused and avoiding a level of tree traversal.\n\t */\n\tunion {\n\t\tvoid\t\t\t*subtree_pun;\n\t\trtree_node_elm_t\t*subtree;\n\t};\n\t/* Number of key bits distinguished by this level. */\n\tunsigned\t\tbits;\n\t/*\n\t * Cumulative number of key bits distinguished by traversing to\n\t * corresponding tree level.\n\t */\n\tunsigned\t\tcumbits;\n};\n\nstruct rtree_s {\n\trtree_node_alloc_t\t*alloc;\n\trtree_node_dalloc_t\t*dalloc;\n\tunsigned\t\theight;\n\t/*\n\t * Precomputed table used to convert from the number of leading 0 key\n\t * bits to which subtree level to start at.\n\t */\n\tunsigned\t\tstart_level[RTREE_HEIGHT_MAX];\n\trtree_level_t\t\tlevels[RTREE_HEIGHT_MAX];\n};\n\n#endif /* JEMALLOC_H_STRUCTS */\n/******************************************************************************/\n#ifdef JEMALLOC_H_EXTERNS\n\nbool rtree_new(rtree_t *rtree, unsigned bits, rtree_node_alloc_t *alloc,\n    rtree_node_dalloc_t *dalloc);\nvoid\trtree_delete(rtree_t *rtree);\nrtree_node_elm_t\t*rtree_subtree_read_hard(rtree_t *rtree,\n    unsigned level);\nrtree_node_elm_t\t*rtree_child_read_hard(rtree_t *rtree,\n    rtree_node_elm_t *elm, unsigned level);\n\n#endif /* JEMALLOC_H_EXTERNS */\n/******************************************************************************/\n#ifdef JEMALLOC_H_INLINES\n\n#ifndef JEMALLOC_ENABLE_INLINE\nunsigned\trtree_start_level(rtree_t *rtree, uintptr_t key);\nuintptr_t\trtree_subkey(rtree_t *rtree, uintptr_t key, unsigned level);\n\nbool\trtree_node_valid(rtree_node_elm_t *node);\nrtree_node_elm_t\t*rtree_child_tryread(rtree_node_elm_t *elm,\n    bool dependent);\nrtree_node_elm_t\t*rtree_child_read(rtree_t *rtree, rtree_node_elm_t *elm,\n    unsigned level, bool dependent);\nextent_node_t\t*rtree_val_read(rtree_t *rtree, rtree_node_elm_t *elm,\n    bool dependent);\nvoid\trtree_val_write(rtree_t *rtree, rtree_node_elm_t *elm,\n    const extent_node_t *val);\nrtree_node_elm_t\t*rtree_subtree_tryread(rtree_t *rtree, unsigned level,\n    bool dependent);\nrtree_node_elm_t\t*rtree_subtree_read(rtree_t *rtree, unsigned level,\n    bool dependent);\n\nextent_node_t\t*rtree_get(rtree_t *rtree, uintptr_t key, bool dependent);\nbool\trtree_set(rtree_t *rtree, uintptr_t key, const extent_node_t *val);\n#endif\n\n#if (defined(JEMALLOC_ENABLE_INLINE) || defined(JEMALLOC_RTREE_C_))\nJEMALLOC_ALWAYS_INLINE unsigned\nrtree_start_level(rtree_t *rtree, uintptr_t key)\n{\n\tunsigned start_level;\n\n\tif (unlikely(key == 0))\n\t\treturn (rtree->height - 1);\n\n\tstart_level = rtree->start_level[lg_floor(key) >>\n\t    LG_RTREE_BITS_PER_LEVEL];\n\tassert(start_level < rtree->height);\n\treturn (start_level);\n}\n\nJEMALLOC_ALWAYS_INLINE uintptr_t\nrtree_subkey(rtree_t *rtree, uintptr_t key, unsigned level)\n{\n\n\treturn ((key >> ((ZU(1) << (LG_SIZEOF_PTR+3)) -\n\t    rtree->levels[level].cumbits)) & ((ZU(1) <<\n\t    rtree->levels[level].bits) - 1));\n}\n\nJEMALLOC_ALWAYS_INLINE bool\nrtree_node_valid(rtree_node_elm_t *node)\n{\n\n\treturn ((uintptr_t)node > (uintptr_t)RTREE_NODE_INITIALIZING);\n}\n\nJEMALLOC_ALWAYS_INLINE rtree_node_elm_t *\nrtree_child_tryread(rtree_node_elm_t *elm, bool dependent)\n{\n\trtree_node_elm_t *child;\n\n\t/* Double-checked read (first read may be stale. */\n\tchild = elm->child;\n\tif (!dependent && !rtree_node_valid(child))\n\t\tchild = atomic_read_p(&elm->pun);\n\tassert(!dependent || child != NULL);\n\treturn (child);\n}\n\nJEMALLOC_ALWAYS_INLINE rtree_node_elm_t *\nrtree_child_read(rtree_t *rtree, rtree_node_elm_t *elm, unsigned level,\n    bool dependent)\n{\n\trtree_node_elm_t *child;\n\n\tchild = rtree_child_tryread(elm, dependent);\n\tif (!dependent && unlikely(!rtree_node_valid(child)))\n\t\tchild = rtree_child_read_hard(rtree, elm, level);\n\tassert(!dependent || child != NULL);\n\treturn (child);\n}\n\nJEMALLOC_ALWAYS_INLINE extent_node_t *\nrtree_val_read(rtree_t *rtree, rtree_node_elm_t *elm, bool dependent)\n{\n\n\tif (dependent) {\n\t\t/*\n\t\t * Reading a val on behalf of a pointer to a valid allocation is\n\t\t * guaranteed to be a clean read even without synchronization,\n\t\t * because the rtree update became visible in memory before the\n\t\t * pointer came into existence.\n\t\t */\n\t\treturn (elm->val);\n\t} else {\n\t\t/*\n\t\t * An arbitrary read, e.g. on behalf of ivsalloc(), may not be\n\t\t * dependent on a previous rtree write, which means a stale read\n\t\t * could result if synchronization were omitted here.\n\t\t */\n\t\treturn (atomic_read_p(&elm->pun));\n\t}\n}\n\nJEMALLOC_INLINE void\nrtree_val_write(rtree_t *rtree, rtree_node_elm_t *elm, const extent_node_t *val)\n{\n\n\tatomic_write_p(&elm->pun, val);\n}\n\nJEMALLOC_ALWAYS_INLINE rtree_node_elm_t *\nrtree_subtree_tryread(rtree_t *rtree, unsigned level, bool dependent)\n{\n\trtree_node_elm_t *subtree;\n\n\t/* Double-checked read (first read may be stale. */\n\tsubtree = rtree->levels[level].subtree;\n\tif (!dependent && unlikely(!rtree_node_valid(subtree)))\n\t\tsubtree = atomic_read_p(&rtree->levels[level].subtree_pun);\n\tassert(!dependent || subtree != NULL);\n\treturn (subtree);\n}\n\nJEMALLOC_ALWAYS_INLINE rtree_node_elm_t *\nrtree_subtree_read(rtree_t *rtree, unsigned level, bool dependent)\n{\n\trtree_node_elm_t *subtree;\n\n\tsubtree = rtree_subtree_tryread(rtree, level, dependent);\n\tif (!dependent && unlikely(!rtree_node_valid(subtree)))\n\t\tsubtree = rtree_subtree_read_hard(rtree, level);\n\tassert(!dependent || subtree != NULL);\n\treturn (subtree);\n}\n\nJEMALLOC_ALWAYS_INLINE extent_node_t *\nrtree_get(rtree_t *rtree, uintptr_t key, bool dependent)\n{\n\tuintptr_t subkey;\n\tunsigned start_level;\n\trtree_node_elm_t *node;\n\n\tstart_level = rtree_start_level(rtree, key);\n\n\tnode = rtree_subtree_tryread(rtree, start_level, dependent);\n#define\tRTREE_GET_BIAS\t(RTREE_HEIGHT_MAX - rtree->height)\n\tswitch (start_level + RTREE_GET_BIAS) {\n#define\tRTREE_GET_SUBTREE(level)\t\t\t\t\t\\\n\tcase level:\t\t\t\t\t\t\t\\\n\t\tassert(level < (RTREE_HEIGHT_MAX-1));\t\t\t\\\n\t\tif (!dependent && unlikely(!rtree_node_valid(node)))\t\\\n\t\t\treturn (NULL);\t\t\t\t\t\\\n\t\tsubkey = rtree_subkey(rtree, key, level -\t\t\\\n\t\t    RTREE_GET_BIAS);\t\t\t\t\t\\\n\t\tnode = rtree_child_tryread(&node[subkey], dependent);\t\\\n\t\t/* Fall through. */\n#define\tRTREE_GET_LEAF(level)\t\t\t\t\t\t\\\n\tcase level:\t\t\t\t\t\t\t\\\n\t\tassert(level == (RTREE_HEIGHT_MAX-1));\t\t\t\\\n\t\tif (!dependent && unlikely(!rtree_node_valid(node)))\t\\\n\t\t\treturn (NULL);\t\t\t\t\t\\\n\t\tsubkey = rtree_subkey(rtree, key, level -\t\t\\\n\t\t    RTREE_GET_BIAS);\t\t\t\t\t\\\n\t\t/*\t\t\t\t\t\t\t\\\n\t\t * node is a leaf, so it contains values rather than\t\\\n\t\t * child pointers.\t\t\t\t\t\\\n\t\t */\t\t\t\t\t\t\t\\\n\t\treturn (rtree_val_read(rtree, &node[subkey],\t\t\\\n\t\t    dependent));\n#if RTREE_HEIGHT_MAX > 1\n\tRTREE_GET_SUBTREE(0)\n#endif\n#if RTREE_HEIGHT_MAX > 2\n\tRTREE_GET_SUBTREE(1)\n#endif\n#if RTREE_HEIGHT_MAX > 3\n\tRTREE_GET_SUBTREE(2)\n#endif\n#if RTREE_HEIGHT_MAX > 4\n\tRTREE_GET_SUBTREE(3)\n#endif\n#if RTREE_HEIGHT_MAX > 5\n\tRTREE_GET_SUBTREE(4)\n#endif\n#if RTREE_HEIGHT_MAX > 6\n\tRTREE_GET_SUBTREE(5)\n#endif\n#if RTREE_HEIGHT_MAX > 7\n\tRTREE_GET_SUBTREE(6)\n#endif\n#if RTREE_HEIGHT_MAX > 8\n\tRTREE_GET_SUBTREE(7)\n#endif\n#if RTREE_HEIGHT_MAX > 9\n\tRTREE_GET_SUBTREE(8)\n#endif\n#if RTREE_HEIGHT_MAX > 10\n\tRTREE_GET_SUBTREE(9)\n#endif\n#if RTREE_HEIGHT_MAX > 11\n\tRTREE_GET_SUBTREE(10)\n#endif\n#if RTREE_HEIGHT_MAX > 12\n\tRTREE_GET_SUBTREE(11)\n#endif\n#if RTREE_HEIGHT_MAX > 13\n\tRTREE_GET_SUBTREE(12)\n#endif\n#if RTREE_HEIGHT_MAX > 14\n\tRTREE_GET_SUBTREE(13)\n#endif\n#if RTREE_HEIGHT_MAX > 15\n\tRTREE_GET_SUBTREE(14)\n#endif\n#if RTREE_HEIGHT_MAX > 16\n#  error Unsupported RTREE_HEIGHT_MAX\n#endif\n\tRTREE_GET_LEAF(RTREE_HEIGHT_MAX-1)\n#undef RTREE_GET_SUBTREE\n#undef RTREE_GET_LEAF\n\tdefault: not_reached();\n\t}\n#undef RTREE_GET_BIAS\n\tnot_reached();\n}\n\nJEMALLOC_INLINE bool\nrtree_set(rtree_t *rtree, uintptr_t key, const extent_node_t *val)\n{\n\tuintptr_t subkey;\n\tunsigned i, start_level;\n\trtree_node_elm_t *node, *child;\n\n\tstart_level = rtree_start_level(rtree, key);\n\n\tnode = rtree_subtree_read(rtree, start_level, false);\n\tif (node == NULL)\n\t\treturn (true);\n\tfor (i = start_level; /**/; i++, node = child) {\n\t\tsubkey = rtree_subkey(rtree, key, i);\n\t\tif (i == rtree->height - 1) {\n\t\t\t/*\n\t\t\t * node is a leaf, so it contains values rather than\n\t\t\t * child pointers.\n\t\t\t */\n\t\t\trtree_val_write(rtree, &node[subkey], val);\n\t\t\treturn (false);\n\t\t}\n\t\tassert(i + 1 < rtree->height);\n\t\tchild = rtree_child_read(rtree, &node[subkey], i, false);\n\t\tif (child == NULL)\n\t\t\treturn (true);\n\t}\n\tnot_reached();\n}\n#endif\n\n#endif /* JEMALLOC_H_INLINES */\n/******************************************************************************/\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/deps/jemalloc/include/jemalloc/internal/size_classes.sh",
    "content": "#!/bin/sh\n#\n# Usage: size_classes.sh <lg_qarr> <lg_tmin> <lg_parr> <lg_g>\n\n# The following limits are chosen such that they cover all supported platforms.\n\n# Pointer sizes.\nlg_zarr=\"2 3\"\n\n# Quanta.\nlg_qarr=$1\n\n# The range of tiny size classes is [2^lg_tmin..2^(lg_q-1)].\nlg_tmin=$2\n\n# Maximum lookup size.\nlg_kmax=12\n\n# Page sizes.\nlg_parr=`echo $3 | tr ',' ' '`\n\n# Size class group size (number of size classes for each size doubling).\nlg_g=$4\n\npow2() {\n  e=$1\n  pow2_result=1\n  while [ ${e} -gt 0 ] ; do\n    pow2_result=$((${pow2_result} + ${pow2_result}))\n    e=$((${e} - 1))\n  done\n}\n\nlg() {\n  x=$1\n  lg_result=0\n  while [ ${x} -gt 1 ] ; do\n    lg_result=$((${lg_result} + 1))\n    x=$((${x} / 2))\n  done\n}\n\nsize_class() {\n  index=$1\n  lg_grp=$2\n  lg_delta=$3\n  ndelta=$4\n  lg_p=$5\n  lg_kmax=$6\n\n  lg ${ndelta}; lg_ndelta=${lg_result}; pow2 ${lg_ndelta}\n  if [ ${pow2_result} -lt ${ndelta} ] ; then\n    rem=\"yes\"\n  else\n    rem=\"no\"\n  fi\n\n  lg_size=${lg_grp}\n  if [ $((${lg_delta} + ${lg_ndelta})) -eq ${lg_grp} ] ; then\n    lg_size=$((${lg_grp} + 1))\n  else\n    lg_size=${lg_grp}\n    rem=\"yes\"\n  fi\n\n  if [ ${lg_size} -lt $((${lg_p} + ${lg_g})) ] ; then\n    bin=\"yes\"\n  else\n    bin=\"no\"\n  fi\n  if [ ${lg_size} -lt ${lg_kmax} \\\n      -o ${lg_size} -eq ${lg_kmax} -a ${rem} = \"no\" ] ; then\n    lg_delta_lookup=${lg_delta}\n  else\n    lg_delta_lookup=\"no\"\n  fi\n  printf '    SC(%3d, %6d, %8d, %6d, %3s, %2s) \\\\\\n' ${index} ${lg_grp} ${lg_delta} ${ndelta} ${bin} ${lg_delta_lookup}\n  # Defined upon return:\n  # - lg_delta_lookup (${lg_delta} or \"no\")\n  # - bin (\"yes\" or \"no\")\n}\n\nsep_line() {\n  echo \"                                               \\\\\"\n}\n\nsize_classes() {\n  lg_z=$1\n  lg_q=$2\n  lg_t=$3\n  lg_p=$4\n  lg_g=$5\n\n  pow2 $((${lg_z} + 3)); ptr_bits=${pow2_result}\n  pow2 ${lg_g}; g=${pow2_result}\n\n  echo \"#define\tSIZE_CLASSES \\\\\"\n  echo \"  /* index, lg_grp, lg_delta, ndelta, bin, lg_delta_lookup */ \\\\\"\n\n  ntbins=0\n  nlbins=0\n  lg_tiny_maxclass='\"NA\"'\n  nbins=0\n\n  # Tiny size classes.\n  ndelta=0\n  index=0\n  lg_grp=${lg_t}\n  lg_delta=${lg_grp}\n  while [ ${lg_grp} -lt ${lg_q} ] ; do\n    size_class ${index} ${lg_grp} ${lg_delta} ${ndelta} ${lg_p} ${lg_kmax}\n    if [ ${lg_delta_lookup} != \"no\" ] ; then\n      nlbins=$((${index} + 1))\n    fi\n    if [ ${bin} != \"no\" ] ; then\n      nbins=$((${index} + 1))\n    fi\n    ntbins=$((${ntbins} + 1))\n    lg_tiny_maxclass=${lg_grp} # Final written value is correct.\n    index=$((${index} + 1))\n    lg_delta=${lg_grp}\n    lg_grp=$((${lg_grp} + 1))\n  done\n\n  # First non-tiny group.\n  if [ ${ntbins} -gt 0 ] ; then\n    sep_line\n    # The first size class has an unusual encoding, because the size has to be\n    # split between grp and delta*ndelta.\n    lg_grp=$((${lg_grp} - 1))\n    ndelta=1\n    size_class ${index} ${lg_grp} ${lg_delta} ${ndelta} ${lg_p} ${lg_kmax}\n    index=$((${index} + 1))\n    lg_grp=$((${lg_grp} + 1))\n    lg_delta=$((${lg_delta} + 1))\n  fi\n  while [ ${ndelta} -lt ${g} ] ; do\n    size_class ${index} ${lg_grp} ${lg_delta} ${ndelta} ${lg_p} ${lg_kmax}\n    index=$((${index} + 1))\n    ndelta=$((${ndelta} + 1))\n  done\n\n  # All remaining groups.\n  lg_grp=$((${lg_grp} + ${lg_g}))\n  while [ ${lg_grp} -lt $((${ptr_bits} - 1)) ] ; do\n    sep_line\n    ndelta=1\n    if [ ${lg_grp} -eq $((${ptr_bits} - 2)) ] ; then\n      ndelta_limit=$((${g} - 1))\n    else\n      ndelta_limit=${g}\n    fi\n    while [ ${ndelta} -le ${ndelta_limit} ] ; do\n      size_class ${index} ${lg_grp} ${lg_delta} ${ndelta} ${lg_p} ${lg_kmax}\n      if [ ${lg_delta_lookup} != \"no\" ] ; then\n        nlbins=$((${index} + 1))\n        # Final written value is correct:\n        lookup_maxclass=\"((((size_t)1) << ${lg_grp}) + (((size_t)${ndelta}) << ${lg_delta}))\"\n      fi\n      if [ ${bin} != \"no\" ] ; then\n        nbins=$((${index} + 1))\n        # Final written value is correct:\n        small_maxclass=\"((((size_t)1) << ${lg_grp}) + (((size_t)${ndelta}) << ${lg_delta}))\"\n        if [ ${lg_g} -gt 0 ] ; then\n          lg_large_minclass=$((${lg_grp} + 1))\n        else\n          lg_large_minclass=$((${lg_grp} + 2))\n        fi\n      fi\n      # Final written value is correct:\n      huge_maxclass=\"((((size_t)1) << ${lg_grp}) + (((size_t)${ndelta}) << ${lg_delta}))\"\n      index=$((${index} + 1))\n      ndelta=$((${ndelta} + 1))\n    done\n    lg_grp=$((${lg_grp} + 1))\n    lg_delta=$((${lg_delta} + 1))\n  done\n  echo\n  nsizes=${index}\n\n  # Defined upon completion:\n  # - ntbins\n  # - nlbins\n  # - nbins\n  # - nsizes\n  # - lg_tiny_maxclass\n  # - lookup_maxclass\n  # - small_maxclass\n  # - lg_large_minclass\n  # - huge_maxclass\n}\n\ncat <<EOF\n/* This file was automatically generated by size_classes.sh. */\n/******************************************************************************/\n#ifdef JEMALLOC_H_TYPES\n\n/*\n * This header requires LG_SIZEOF_PTR, LG_TINY_MIN, LG_QUANTUM, and LG_PAGE to\n * be defined prior to inclusion, and it in turn defines:\n *\n *   LG_SIZE_CLASS_GROUP: Lg of size class count for each size doubling.\n *   SIZE_CLASSES: Complete table of\n *                 SC(index, lg_grp, lg_delta, ndelta, bin, lg_delta_lookup)\n *                 tuples.\n *     index: Size class index.\n *     lg_grp: Lg group base size (no deltas added).\n *     lg_delta: Lg delta to previous size class.\n *     ndelta: Delta multiplier.  size == 1<<lg_grp + ndelta<<lg_delta\n *     bin: 'yes' if a small bin size class, 'no' otherwise.\n *     lg_delta_lookup: Same as lg_delta if a lookup table size class, 'no'\n *                      otherwise.\n *   NTBINS: Number of tiny bins.\n *   NLBINS: Number of bins supported by the lookup table.\n *   NBINS: Number of small size class bins.\n *   NSIZES: Number of size classes.\n *   LG_TINY_MAXCLASS: Lg of maximum tiny size class.\n *   LOOKUP_MAXCLASS: Maximum size class included in lookup table.\n *   SMALL_MAXCLASS: Maximum small size class.\n *   LG_LARGE_MINCLASS: Lg of minimum large size class.\n *   HUGE_MAXCLASS: Maximum (huge) size class.\n */\n\n#define\tLG_SIZE_CLASS_GROUP\t${lg_g}\n\nEOF\n\nfor lg_z in ${lg_zarr} ; do\n  for lg_q in ${lg_qarr} ; do\n    lg_t=${lg_tmin}\n    while [ ${lg_t} -le ${lg_q} ] ; do\n      # Iterate through page sizes and compute how many bins there are.\n      for lg_p in ${lg_parr} ; do\n        echo \"#if (LG_SIZEOF_PTR == ${lg_z} && LG_TINY_MIN == ${lg_t} && LG_QUANTUM == ${lg_q} && LG_PAGE == ${lg_p})\"\n        size_classes ${lg_z} ${lg_q} ${lg_t} ${lg_p} ${lg_g}\n        echo \"#define\tSIZE_CLASSES_DEFINED\"\n        echo \"#define\tNTBINS\t\t\t${ntbins}\"\n        echo \"#define\tNLBINS\t\t\t${nlbins}\"\n        echo \"#define\tNBINS\t\t\t${nbins}\"\n        echo \"#define\tNSIZES\t\t\t${nsizes}\"\n        echo \"#define\tLG_TINY_MAXCLASS\t${lg_tiny_maxclass}\"\n        echo \"#define\tLOOKUP_MAXCLASS\t\t${lookup_maxclass}\"\n        echo \"#define\tSMALL_MAXCLASS\t\t${small_maxclass}\"\n        echo \"#define\tLG_LARGE_MINCLASS\t${lg_large_minclass}\"\n        echo \"#define\tHUGE_MAXCLASS\t\t${huge_maxclass}\"\n        echo \"#endif\"\n        echo\n      done\n      lg_t=$((${lg_t} + 1))\n    done\n  done\ndone\n\ncat <<EOF\n#ifndef SIZE_CLASSES_DEFINED\n#  error \"No size class definitions match configuration\"\n#endif\n#undef SIZE_CLASSES_DEFINED\n/*\n * The size2index_tab lookup table uses uint8_t to encode each bin index, so we\n * cannot support more than 256 small size classes.  Further constrain NBINS to\n * 255 since all small size classes, plus a \"not small\" size class must be\n * stored in 8 bits of arena_chunk_map_bits_t's bits field.\n */\n#if (NBINS > 255)\n#  error \"Too many small size classes\"\n#endif\n\n#endif /* JEMALLOC_H_TYPES */\n/******************************************************************************/\n#ifdef JEMALLOC_H_STRUCTS\n\n\n#endif /* JEMALLOC_H_STRUCTS */\n/******************************************************************************/\n#ifdef JEMALLOC_H_EXTERNS\n\n\n#endif /* JEMALLOC_H_EXTERNS */\n/******************************************************************************/\n#ifdef JEMALLOC_H_INLINES\n\n\n#endif /* JEMALLOC_H_INLINES */\n/******************************************************************************/\nEOF\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/deps/jemalloc/include/jemalloc/internal/smoothstep.h",
    "content": "/*\n * This file was generated by the following command:\n *   sh smoothstep.sh smoother 200 24 3 15\n */\n/******************************************************************************/\n#ifdef JEMALLOC_H_TYPES\n\n/*\n * This header defines a precomputed table based on the smoothstep family of\n * sigmoidal curves (https://en.wikipedia.org/wiki/Smoothstep) that grow from 0\n * to 1 in 0 <= x <= 1.  The table is stored as integer fixed point values so\n * that floating point math can be avoided.\n *\n *                      3     2\n *   smoothstep(x) = -2x  + 3x\n *\n *                       5      4      3\n *   smootherstep(x) = 6x  - 15x  + 10x\n *\n *                          7      6      5      4\n *   smootheststep(x) = -20x  + 70x  - 84x  + 35x\n */\n\n#define\tSMOOTHSTEP_VARIANT\t\"smoother\"\n#define\tSMOOTHSTEP_NSTEPS\t200\n#define\tSMOOTHSTEP_BFP\t\t24\n#define\tSMOOTHSTEP \\\n /* STEP(step, h,                            x,     y) */ \\\n    STEP(   1, UINT64_C(0x0000000000000014), 0.005, 0.000001240643750) \\\n    STEP(   2, UINT64_C(0x00000000000000a5), 0.010, 0.000009850600000) \\\n    STEP(   3, UINT64_C(0x0000000000000229), 0.015, 0.000032995181250) \\\n    STEP(   4, UINT64_C(0x0000000000000516), 0.020, 0.000077619200000) \\\n    STEP(   5, UINT64_C(0x00000000000009dc), 0.025, 0.000150449218750) \\\n    STEP(   6, UINT64_C(0x00000000000010e8), 0.030, 0.000257995800000) \\\n    STEP(   7, UINT64_C(0x0000000000001aa4), 0.035, 0.000406555756250) \\\n    STEP(   8, UINT64_C(0x0000000000002777), 0.040, 0.000602214400000) \\\n    STEP(   9, UINT64_C(0x00000000000037c2), 0.045, 0.000850847793750) \\\n    STEP(  10, UINT64_C(0x0000000000004be6), 0.050, 0.001158125000000) \\\n    STEP(  11, UINT64_C(0x000000000000643c), 0.055, 0.001529510331250) \\\n    STEP(  12, UINT64_C(0x000000000000811f), 0.060, 0.001970265600000) \\\n    STEP(  13, UINT64_C(0x000000000000a2e2), 0.065, 0.002485452368750) \\\n    STEP(  14, UINT64_C(0x000000000000c9d8), 0.070, 0.003079934200000) \\\n    STEP(  15, UINT64_C(0x000000000000f64f), 0.075, 0.003758378906250) \\\n    STEP(  16, UINT64_C(0x0000000000012891), 0.080, 0.004525260800000) \\\n    STEP(  17, UINT64_C(0x00000000000160e7), 0.085, 0.005384862943750) \\\n    STEP(  18, UINT64_C(0x0000000000019f95), 0.090, 0.006341279400000) \\\n    STEP(  19, UINT64_C(0x000000000001e4dc), 0.095, 0.007398417481250) \\\n    STEP(  20, UINT64_C(0x00000000000230fc), 0.100, 0.008560000000000) \\\n    STEP(  21, UINT64_C(0x0000000000028430), 0.105, 0.009829567518750) \\\n    STEP(  22, UINT64_C(0x000000000002deb0), 0.110, 0.011210480600000) \\\n    STEP(  23, UINT64_C(0x00000000000340b1), 0.115, 0.012705922056250) \\\n    STEP(  24, UINT64_C(0x000000000003aa67), 0.120, 0.014318899200000) \\\n    STEP(  25, UINT64_C(0x0000000000041c00), 0.125, 0.016052246093750) \\\n    STEP(  26, UINT64_C(0x00000000000495a8), 0.130, 0.017908625800000) \\\n    STEP(  27, UINT64_C(0x000000000005178b), 0.135, 0.019890532631250) \\\n    STEP(  28, UINT64_C(0x000000000005a1cf), 0.140, 0.022000294400000) \\\n    STEP(  29, UINT64_C(0x0000000000063498), 0.145, 0.024240074668750) \\\n    STEP(  30, UINT64_C(0x000000000006d009), 0.150, 0.026611875000000) \\\n    STEP(  31, UINT64_C(0x000000000007743f), 0.155, 0.029117537206250) \\\n    STEP(  32, UINT64_C(0x0000000000082157), 0.160, 0.031758745600000) \\\n    STEP(  33, UINT64_C(0x000000000008d76b), 0.165, 0.034537029243750) \\\n    STEP(  34, UINT64_C(0x0000000000099691), 0.170, 0.037453764200000) \\\n    STEP(  35, UINT64_C(0x00000000000a5edf), 0.175, 0.040510175781250) \\\n    STEP(  36, UINT64_C(0x00000000000b3067), 0.180, 0.043707340800000) \\\n    STEP(  37, UINT64_C(0x00000000000c0b38), 0.185, 0.047046189818750) \\\n    STEP(  38, UINT64_C(0x00000000000cef5e), 0.190, 0.050527509400000) \\\n    STEP(  39, UINT64_C(0x00000000000ddce6), 0.195, 0.054151944356250) \\\n    STEP(  40, UINT64_C(0x00000000000ed3d8), 0.200, 0.057920000000000) \\\n    STEP(  41, UINT64_C(0x00000000000fd439), 0.205, 0.061832044393750) \\\n    STEP(  42, UINT64_C(0x000000000010de0e), 0.210, 0.065888310600000) \\\n    STEP(  43, UINT64_C(0x000000000011f158), 0.215, 0.070088898931250) \\\n    STEP(  44, UINT64_C(0x0000000000130e17), 0.220, 0.074433779200000) \\\n    STEP(  45, UINT64_C(0x0000000000143448), 0.225, 0.078922792968750) \\\n    STEP(  46, UINT64_C(0x00000000001563e7), 0.230, 0.083555655800000) \\\n    STEP(  47, UINT64_C(0x0000000000169cec), 0.235, 0.088331959506250) \\\n    STEP(  48, UINT64_C(0x000000000017df4f), 0.240, 0.093251174400000) \\\n    STEP(  49, UINT64_C(0x0000000000192b04), 0.245, 0.098312651543750) \\\n    STEP(  50, UINT64_C(0x00000000001a8000), 0.250, 0.103515625000000) \\\n    STEP(  51, UINT64_C(0x00000000001bde32), 0.255, 0.108859214081250) \\\n    STEP(  52, UINT64_C(0x00000000001d458b), 0.260, 0.114342425600000) \\\n    STEP(  53, UINT64_C(0x00000000001eb5f8), 0.265, 0.119964156118750) \\\n    STEP(  54, UINT64_C(0x0000000000202f65), 0.270, 0.125723194200000) \\\n    STEP(  55, UINT64_C(0x000000000021b1bb), 0.275, 0.131618222656250) \\\n    STEP(  56, UINT64_C(0x0000000000233ce3), 0.280, 0.137647820800000) \\\n    STEP(  57, UINT64_C(0x000000000024d0c3), 0.285, 0.143810466693750) \\\n    STEP(  58, UINT64_C(0x0000000000266d40), 0.290, 0.150104539400000) \\\n    STEP(  59, UINT64_C(0x000000000028123d), 0.295, 0.156528321231250) \\\n    STEP(  60, UINT64_C(0x000000000029bf9c), 0.300, 0.163080000000000) \\\n    STEP(  61, UINT64_C(0x00000000002b753d), 0.305, 0.169757671268750) \\\n    STEP(  62, UINT64_C(0x00000000002d32fe), 0.310, 0.176559340600000) \\\n    STEP(  63, UINT64_C(0x00000000002ef8bc), 0.315, 0.183482925806250) \\\n    STEP(  64, UINT64_C(0x000000000030c654), 0.320, 0.190526259200000) \\\n    STEP(  65, UINT64_C(0x0000000000329b9f), 0.325, 0.197687089843750) \\\n    STEP(  66, UINT64_C(0x0000000000347875), 0.330, 0.204963085800000) \\\n    STEP(  67, UINT64_C(0x0000000000365cb0), 0.335, 0.212351836381250) \\\n    STEP(  68, UINT64_C(0x0000000000384825), 0.340, 0.219850854400000) \\\n    STEP(  69, UINT64_C(0x00000000003a3aa8), 0.345, 0.227457578418750) \\\n    STEP(  70, UINT64_C(0x00000000003c340f), 0.350, 0.235169375000000) \\\n    STEP(  71, UINT64_C(0x00000000003e342b), 0.355, 0.242983540956250) \\\n    STEP(  72, UINT64_C(0x0000000000403ace), 0.360, 0.250897305600000) \\\n    STEP(  73, UINT64_C(0x00000000004247c8), 0.365, 0.258907832993750) \\\n    STEP(  74, UINT64_C(0x0000000000445ae9), 0.370, 0.267012224200000) \\\n    STEP(  75, UINT64_C(0x0000000000467400), 0.375, 0.275207519531250) \\\n    STEP(  76, UINT64_C(0x00000000004892d8), 0.380, 0.283490700800000) \\\n    STEP(  77, UINT64_C(0x00000000004ab740), 0.385, 0.291858693568750) \\\n    STEP(  78, UINT64_C(0x00000000004ce102), 0.390, 0.300308369400000) \\\n    STEP(  79, UINT64_C(0x00000000004f0fe9), 0.395, 0.308836548106250) \\\n    STEP(  80, UINT64_C(0x00000000005143bf), 0.400, 0.317440000000000) \\\n    STEP(  81, UINT64_C(0x0000000000537c4d), 0.405, 0.326115448143750) \\\n    STEP(  82, UINT64_C(0x000000000055b95b), 0.410, 0.334859570600000) \\\n    STEP(  83, UINT64_C(0x000000000057fab1), 0.415, 0.343669002681250) \\\n    STEP(  84, UINT64_C(0x00000000005a4015), 0.420, 0.352540339200000) \\\n    STEP(  85, UINT64_C(0x00000000005c894e), 0.425, 0.361470136718750) \\\n    STEP(  86, UINT64_C(0x00000000005ed622), 0.430, 0.370454915800000) \\\n    STEP(  87, UINT64_C(0x0000000000612655), 0.435, 0.379491163256250) \\\n    STEP(  88, UINT64_C(0x00000000006379ac), 0.440, 0.388575334400000) \\\n    STEP(  89, UINT64_C(0x000000000065cfeb), 0.445, 0.397703855293750) \\\n    STEP(  90, UINT64_C(0x00000000006828d6), 0.450, 0.406873125000000) \\\n    STEP(  91, UINT64_C(0x00000000006a842f), 0.455, 0.416079517831250) \\\n    STEP(  92, UINT64_C(0x00000000006ce1bb), 0.460, 0.425319385600000) \\\n    STEP(  93, UINT64_C(0x00000000006f413a), 0.465, 0.434589059868750) \\\n    STEP(  94, UINT64_C(0x000000000071a270), 0.470, 0.443884854200000) \\\n    STEP(  95, UINT64_C(0x000000000074051d), 0.475, 0.453203066406250) \\\n    STEP(  96, UINT64_C(0x0000000000766905), 0.480, 0.462539980800000) \\\n    STEP(  97, UINT64_C(0x000000000078cde7), 0.485, 0.471891870443750) \\\n    STEP(  98, UINT64_C(0x00000000007b3387), 0.490, 0.481254999400000) \\\n    STEP(  99, UINT64_C(0x00000000007d99a4), 0.495, 0.490625624981250) \\\n    STEP( 100, UINT64_C(0x0000000000800000), 0.500, 0.500000000000000) \\\n    STEP( 101, UINT64_C(0x000000000082665b), 0.505, 0.509374375018750) \\\n    STEP( 102, UINT64_C(0x000000000084cc78), 0.510, 0.518745000600000) \\\n    STEP( 103, UINT64_C(0x0000000000873218), 0.515, 0.528108129556250) \\\n    STEP( 104, UINT64_C(0x00000000008996fa), 0.520, 0.537460019200000) \\\n    STEP( 105, UINT64_C(0x00000000008bfae2), 0.525, 0.546796933593750) \\\n    STEP( 106, UINT64_C(0x00000000008e5d8f), 0.530, 0.556115145800000) \\\n    STEP( 107, UINT64_C(0x000000000090bec5), 0.535, 0.565410940131250) \\\n    STEP( 108, UINT64_C(0x0000000000931e44), 0.540, 0.574680614400000) \\\n    STEP( 109, UINT64_C(0x0000000000957bd0), 0.545, 0.583920482168750) \\\n    STEP( 110, UINT64_C(0x000000000097d729), 0.550, 0.593126875000000) \\\n    STEP( 111, UINT64_C(0x00000000009a3014), 0.555, 0.602296144706250) \\\n    STEP( 112, UINT64_C(0x00000000009c8653), 0.560, 0.611424665600000) \\\n    STEP( 113, UINT64_C(0x00000000009ed9aa), 0.565, 0.620508836743750) \\\n    STEP( 114, UINT64_C(0x0000000000a129dd), 0.570, 0.629545084200000) \\\n    STEP( 115, UINT64_C(0x0000000000a376b1), 0.575, 0.638529863281250) \\\n    STEP( 116, UINT64_C(0x0000000000a5bfea), 0.580, 0.647459660800000) \\\n    STEP( 117, UINT64_C(0x0000000000a8054e), 0.585, 0.656330997318750) \\\n    STEP( 118, UINT64_C(0x0000000000aa46a4), 0.590, 0.665140429400000) \\\n    STEP( 119, UINT64_C(0x0000000000ac83b2), 0.595, 0.673884551856250) \\\n    STEP( 120, UINT64_C(0x0000000000aebc40), 0.600, 0.682560000000000) \\\n    STEP( 121, UINT64_C(0x0000000000b0f016), 0.605, 0.691163451893750) \\\n    STEP( 122, UINT64_C(0x0000000000b31efd), 0.610, 0.699691630600000) \\\n    STEP( 123, UINT64_C(0x0000000000b548bf), 0.615, 0.708141306431250) \\\n    STEP( 124, UINT64_C(0x0000000000b76d27), 0.620, 0.716509299200000) \\\n    STEP( 125, UINT64_C(0x0000000000b98c00), 0.625, 0.724792480468750) \\\n    STEP( 126, UINT64_C(0x0000000000bba516), 0.630, 0.732987775800000) \\\n    STEP( 127, UINT64_C(0x0000000000bdb837), 0.635, 0.741092167006250) \\\n    STEP( 128, UINT64_C(0x0000000000bfc531), 0.640, 0.749102694400000) \\\n    STEP( 129, UINT64_C(0x0000000000c1cbd4), 0.645, 0.757016459043750) \\\n    STEP( 130, UINT64_C(0x0000000000c3cbf0), 0.650, 0.764830625000000) \\\n    STEP( 131, UINT64_C(0x0000000000c5c557), 0.655, 0.772542421581250) \\\n    STEP( 132, UINT64_C(0x0000000000c7b7da), 0.660, 0.780149145600000) \\\n    STEP( 133, UINT64_C(0x0000000000c9a34f), 0.665, 0.787648163618750) \\\n    STEP( 134, UINT64_C(0x0000000000cb878a), 0.670, 0.795036914200000) \\\n    STEP( 135, UINT64_C(0x0000000000cd6460), 0.675, 0.802312910156250) \\\n    STEP( 136, UINT64_C(0x0000000000cf39ab), 0.680, 0.809473740800000) \\\n    STEP( 137, UINT64_C(0x0000000000d10743), 0.685, 0.816517074193750) \\\n    STEP( 138, UINT64_C(0x0000000000d2cd01), 0.690, 0.823440659400000) \\\n    STEP( 139, UINT64_C(0x0000000000d48ac2), 0.695, 0.830242328731250) \\\n    STEP( 140, UINT64_C(0x0000000000d64063), 0.700, 0.836920000000000) \\\n    STEP( 141, UINT64_C(0x0000000000d7edc2), 0.705, 0.843471678768750) \\\n    STEP( 142, UINT64_C(0x0000000000d992bf), 0.710, 0.849895460600000) \\\n    STEP( 143, UINT64_C(0x0000000000db2f3c), 0.715, 0.856189533306250) \\\n    STEP( 144, UINT64_C(0x0000000000dcc31c), 0.720, 0.862352179200000) \\\n    STEP( 145, UINT64_C(0x0000000000de4e44), 0.725, 0.868381777343750) \\\n    STEP( 146, UINT64_C(0x0000000000dfd09a), 0.730, 0.874276805800000) \\\n    STEP( 147, UINT64_C(0x0000000000e14a07), 0.735, 0.880035843881250) \\\n    STEP( 148, UINT64_C(0x0000000000e2ba74), 0.740, 0.885657574400000) \\\n    STEP( 149, UINT64_C(0x0000000000e421cd), 0.745, 0.891140785918750) \\\n    STEP( 150, UINT64_C(0x0000000000e58000), 0.750, 0.896484375000000) \\\n    STEP( 151, UINT64_C(0x0000000000e6d4fb), 0.755, 0.901687348456250) \\\n    STEP( 152, UINT64_C(0x0000000000e820b0), 0.760, 0.906748825600000) \\\n    STEP( 153, UINT64_C(0x0000000000e96313), 0.765, 0.911668040493750) \\\n    STEP( 154, UINT64_C(0x0000000000ea9c18), 0.770, 0.916444344200000) \\\n    STEP( 155, UINT64_C(0x0000000000ebcbb7), 0.775, 0.921077207031250) \\\n    STEP( 156, UINT64_C(0x0000000000ecf1e8), 0.780, 0.925566220800000) \\\n    STEP( 157, UINT64_C(0x0000000000ee0ea7), 0.785, 0.929911101068750) \\\n    STEP( 158, UINT64_C(0x0000000000ef21f1), 0.790, 0.934111689400000) \\\n    STEP( 159, UINT64_C(0x0000000000f02bc6), 0.795, 0.938167955606250) \\\n    STEP( 160, UINT64_C(0x0000000000f12c27), 0.800, 0.942080000000000) \\\n    STEP( 161, UINT64_C(0x0000000000f22319), 0.805, 0.945848055643750) \\\n    STEP( 162, UINT64_C(0x0000000000f310a1), 0.810, 0.949472490600000) \\\n    STEP( 163, UINT64_C(0x0000000000f3f4c7), 0.815, 0.952953810181250) \\\n    STEP( 164, UINT64_C(0x0000000000f4cf98), 0.820, 0.956292659200000) \\\n    STEP( 165, UINT64_C(0x0000000000f5a120), 0.825, 0.959489824218750) \\\n    STEP( 166, UINT64_C(0x0000000000f6696e), 0.830, 0.962546235800000) \\\n    STEP( 167, UINT64_C(0x0000000000f72894), 0.835, 0.965462970756250) \\\n    STEP( 168, UINT64_C(0x0000000000f7dea8), 0.840, 0.968241254400000) \\\n    STEP( 169, UINT64_C(0x0000000000f88bc0), 0.845, 0.970882462793750) \\\n    STEP( 170, UINT64_C(0x0000000000f92ff6), 0.850, 0.973388125000000) \\\n    STEP( 171, UINT64_C(0x0000000000f9cb67), 0.855, 0.975759925331250) \\\n    STEP( 172, UINT64_C(0x0000000000fa5e30), 0.860, 0.977999705600000) \\\n    STEP( 173, UINT64_C(0x0000000000fae874), 0.865, 0.980109467368750) \\\n    STEP( 174, UINT64_C(0x0000000000fb6a57), 0.870, 0.982091374200000) \\\n    STEP( 175, UINT64_C(0x0000000000fbe400), 0.875, 0.983947753906250) \\\n    STEP( 176, UINT64_C(0x0000000000fc5598), 0.880, 0.985681100800000) \\\n    STEP( 177, UINT64_C(0x0000000000fcbf4e), 0.885, 0.987294077943750) \\\n    STEP( 178, UINT64_C(0x0000000000fd214f), 0.890, 0.988789519400000) \\\n    STEP( 179, UINT64_C(0x0000000000fd7bcf), 0.895, 0.990170432481250) \\\n    STEP( 180, UINT64_C(0x0000000000fdcf03), 0.900, 0.991440000000000) \\\n    STEP( 181, UINT64_C(0x0000000000fe1b23), 0.905, 0.992601582518750) \\\n    STEP( 182, UINT64_C(0x0000000000fe606a), 0.910, 0.993658720600000) \\\n    STEP( 183, UINT64_C(0x0000000000fe9f18), 0.915, 0.994615137056250) \\\n    STEP( 184, UINT64_C(0x0000000000fed76e), 0.920, 0.995474739200000) \\\n    STEP( 185, UINT64_C(0x0000000000ff09b0), 0.925, 0.996241621093750) \\\n    STEP( 186, UINT64_C(0x0000000000ff3627), 0.930, 0.996920065800000) \\\n    STEP( 187, UINT64_C(0x0000000000ff5d1d), 0.935, 0.997514547631250) \\\n    STEP( 188, UINT64_C(0x0000000000ff7ee0), 0.940, 0.998029734400000) \\\n    STEP( 189, UINT64_C(0x0000000000ff9bc3), 0.945, 0.998470489668750) \\\n    STEP( 190, UINT64_C(0x0000000000ffb419), 0.950, 0.998841875000000) \\\n    STEP( 191, UINT64_C(0x0000000000ffc83d), 0.955, 0.999149152206250) \\\n    STEP( 192, UINT64_C(0x0000000000ffd888), 0.960, 0.999397785600000) \\\n    STEP( 193, UINT64_C(0x0000000000ffe55b), 0.965, 0.999593444243750) \\\n    STEP( 194, UINT64_C(0x0000000000ffef17), 0.970, 0.999742004200000) \\\n    STEP( 195, UINT64_C(0x0000000000fff623), 0.975, 0.999849550781250) \\\n    STEP( 196, UINT64_C(0x0000000000fffae9), 0.980, 0.999922380800000) \\\n    STEP( 197, UINT64_C(0x0000000000fffdd6), 0.985, 0.999967004818750) \\\n    STEP( 198, UINT64_C(0x0000000000ffff5a), 0.990, 0.999990149400000) \\\n    STEP( 199, UINT64_C(0x0000000000ffffeb), 0.995, 0.999998759356250) \\\n    STEP( 200, UINT64_C(0x0000000001000000), 1.000, 1.000000000000000) \\\n\n#endif /* JEMALLOC_H_TYPES */\n/******************************************************************************/\n#ifdef JEMALLOC_H_STRUCTS\n\n\n#endif /* JEMALLOC_H_STRUCTS */\n/******************************************************************************/\n#ifdef JEMALLOC_H_EXTERNS\n\n\n#endif /* JEMALLOC_H_EXTERNS */\n/******************************************************************************/\n#ifdef JEMALLOC_H_INLINES\n\n\n#endif /* JEMALLOC_H_INLINES */\n/******************************************************************************/\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/deps/jemalloc/include/jemalloc/internal/smoothstep.sh",
    "content": "#!/bin/sh\n#\n# Generate a discrete lookup table for a sigmoid function in the smoothstep\n# family (https://en.wikipedia.org/wiki/Smoothstep), where the lookup table\n# entries correspond to x in [1/nsteps, 2/nsteps, ..., nsteps/nsteps].  Encode\n# the entries using a binary fixed point representation.\n#\n# Usage: smoothstep.sh <variant> <nsteps> <bfp> <xprec> <yprec>\n#\n#        <variant> is in {smooth, smoother, smoothest}.\n#        <nsteps> must be greater than zero.\n#        <bfp> must be in [0..62]; reasonable values are roughly [10..30].\n#        <xprec> is x decimal precision.\n#        <yprec> is y decimal precision.\n\n#set -x\n\ncmd=\"sh smoothstep.sh $*\"\nvariant=$1\nnsteps=$2\nbfp=$3\nxprec=$4\nyprec=$5\n\ncase \"${variant}\" in\n  smooth)\n    ;;\n  smoother)\n    ;;\n  smoothest)\n    ;;\n  *)\n    echo \"Unsupported variant\"\n    exit 1\n    ;;\nesac\n\nsmooth() {\n  step=$1\n  y=`echo ${yprec} k ${step} ${nsteps} / sx _2 lx 3 ^ '*' 3 lx 2 ^ '*' + p | dc | tr -d '\\\\\\\\\\n' | sed -e 's#^\\.#0.#g'`\n  h=`echo ${yprec} k 2 ${bfp} ^ ${y} '*' p | dc | tr -d '\\\\\\\\\\n' | sed -e 's#^\\.#0.#g' | tr '.' ' ' | awk '{print $1}' `\n}\n\nsmoother() {\n  step=$1\n  y=`echo ${yprec} k ${step} ${nsteps} / sx 6 lx 5 ^ '*' _15 lx 4 ^ '*' + 10 lx 3 ^ '*' + p | dc | tr -d '\\\\\\\\\\n' | sed -e 's#^\\.#0.#g'`\n  h=`echo ${yprec} k 2 ${bfp} ^ ${y} '*' p | dc | tr -d '\\\\\\\\\\n' | sed -e 's#^\\.#0.#g' | tr '.' ' ' | awk '{print $1}' `\n}\n\nsmoothest() {\n  step=$1\n  y=`echo ${yprec} k ${step} ${nsteps} / sx _20 lx 7 ^ '*' 70 lx 6 ^ '*' + _84 lx 5 ^ '*' + 35 lx 4 ^ '*' + p | dc | tr -d '\\\\\\\\\\n' | sed -e 's#^\\.#0.#g'`\n  h=`echo ${yprec} k 2 ${bfp} ^ ${y} '*' p | dc | tr -d '\\\\\\\\\\n' | sed -e 's#^\\.#0.#g' | tr '.' ' ' | awk '{print $1}' `\n}\n\ncat <<EOF\n/*\n * This file was generated by the following command:\n *   $cmd\n */\n/******************************************************************************/\n#ifdef JEMALLOC_H_TYPES\n\n/*\n * This header defines a precomputed table based on the smoothstep family of\n * sigmoidal curves (https://en.wikipedia.org/wiki/Smoothstep) that grow from 0\n * to 1 in 0 <= x <= 1.  The table is stored as integer fixed point values so\n * that floating point math can be avoided.\n *\n *                      3     2\n *   smoothstep(x) = -2x  + 3x\n *\n *                       5      4      3\n *   smootherstep(x) = 6x  - 15x  + 10x\n *\n *                          7      6      5      4\n *   smootheststep(x) = -20x  + 70x  - 84x  + 35x\n */\n\n#define\tSMOOTHSTEP_VARIANT\t\"${variant}\"\n#define\tSMOOTHSTEP_NSTEPS\t${nsteps}\n#define\tSMOOTHSTEP_BFP\t\t${bfp}\n#define\tSMOOTHSTEP \\\\\n /* STEP(step, h,                            x,     y) */ \\\\\nEOF\n\ns=1\nwhile [ $s -le $nsteps ] ; do\n  $variant ${s}\n  x=`echo ${xprec} k ${s} ${nsteps} / p | dc | tr -d '\\\\\\\\\\n' | sed -e 's#^\\.#0.#g'`\n  printf '    STEP(%4d, UINT64_C(0x%016x), %s, %s) \\\\\\n' ${s} ${h} ${x} ${y}\n\n  s=$((s+1))\ndone\necho\n\ncat <<EOF\n#endif /* JEMALLOC_H_TYPES */\n/******************************************************************************/\n#ifdef JEMALLOC_H_STRUCTS\n\n\n#endif /* JEMALLOC_H_STRUCTS */\n/******************************************************************************/\n#ifdef JEMALLOC_H_EXTERNS\n\n\n#endif /* JEMALLOC_H_EXTERNS */\n/******************************************************************************/\n#ifdef JEMALLOC_H_INLINES\n\n\n#endif /* JEMALLOC_H_INLINES */\n/******************************************************************************/\nEOF\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/deps/jemalloc/include/jemalloc/internal/stats.h",
    "content": "/******************************************************************************/\n#ifdef JEMALLOC_H_TYPES\n\ntypedef struct tcache_bin_stats_s tcache_bin_stats_t;\ntypedef struct malloc_bin_stats_s malloc_bin_stats_t;\ntypedef struct malloc_large_stats_s malloc_large_stats_t;\ntypedef struct malloc_huge_stats_s malloc_huge_stats_t;\ntypedef struct arena_stats_s arena_stats_t;\ntypedef struct chunk_stats_s chunk_stats_t;\n\n#endif /* JEMALLOC_H_TYPES */\n/******************************************************************************/\n#ifdef JEMALLOC_H_STRUCTS\n\nstruct tcache_bin_stats_s {\n\t/*\n\t * Number of allocation requests that corresponded to the size of this\n\t * bin.\n\t */\n\tuint64_t\tnrequests;\n};\n\nstruct malloc_bin_stats_s {\n\t/*\n\t * Total number of allocation/deallocation requests served directly by\n\t * the bin.  Note that tcache may allocate an object, then recycle it\n\t * many times, resulting many increments to nrequests, but only one\n\t * each to nmalloc and ndalloc.\n\t */\n\tuint64_t\tnmalloc;\n\tuint64_t\tndalloc;\n\n\t/*\n\t * Number of allocation requests that correspond to the size of this\n\t * bin.  This includes requests served by tcache, though tcache only\n\t * periodically merges into this counter.\n\t */\n\tuint64_t\tnrequests;\n\n\t/*\n\t * Current number of regions of this size class, including regions\n\t * currently cached by tcache.\n\t */\n\tsize_t\t\tcurregs;\n\n\t/* Number of tcache fills from this bin. */\n\tuint64_t\tnfills;\n\n\t/* Number of tcache flushes to this bin. */\n\tuint64_t\tnflushes;\n\n\t/* Total number of runs created for this bin's size class. */\n\tuint64_t\tnruns;\n\n\t/*\n\t * Total number of runs reused by extracting them from the runs tree for\n\t * this bin's size class.\n\t */\n\tuint64_t\treruns;\n\n\t/* Current number of runs in this bin. */\n\tsize_t\t\tcurruns;\n};\n\nstruct malloc_large_stats_s {\n\t/*\n\t * Total number of allocation/deallocation requests served directly by\n\t * the arena.  Note that tcache may allocate an object, then recycle it\n\t * many times, resulting many increments to nrequests, but only one\n\t * each to nmalloc and ndalloc.\n\t */\n\tuint64_t\tnmalloc;\n\tuint64_t\tndalloc;\n\n\t/*\n\t * Number of allocation requests that correspond to this size class.\n\t * This includes requests served by tcache, though tcache only\n\t * periodically merges into this counter.\n\t */\n\tuint64_t\tnrequests;\n\n\t/*\n\t * Current number of runs of this size class, including runs currently\n\t * cached by tcache.\n\t */\n\tsize_t\t\tcurruns;\n};\n\nstruct malloc_huge_stats_s {\n\t/*\n\t * Total number of allocation/deallocation requests served directly by\n\t * the arena.\n\t */\n\tuint64_t\tnmalloc;\n\tuint64_t\tndalloc;\n\n\t/* Current number of (multi-)chunk allocations of this size class. */\n\tsize_t\t\tcurhchunks;\n};\n\nstruct arena_stats_s {\n\t/* Number of bytes currently mapped. */\n\tsize_t\t\tmapped;\n\n\t/*\n\t * Number of bytes currently retained as a side effect of munmap() being\n\t * disabled/bypassed.  Retained bytes are technically mapped (though\n\t * always decommitted or purged), but they are excluded from the mapped\n\t * statistic (above).\n\t */\n\tsize_t\t\tretained;\n\n\t/*\n\t * Total number of purge sweeps, total number of madvise calls made,\n\t * and total pages purged in order to keep dirty unused memory under\n\t * control.\n\t */\n\tuint64_t\tnpurge;\n\tuint64_t\tnmadvise;\n\tuint64_t\tpurged;\n\n\t/*\n\t * Number of bytes currently mapped purely for metadata purposes, and\n\t * number of bytes currently allocated for internal metadata.\n\t */\n\tsize_t\t\tmetadata_mapped;\n\tsize_t\t\tmetadata_allocated; /* Protected via atomic_*_z(). */\n\n\t/* Per-size-category statistics. */\n\tsize_t\t\tallocated_large;\n\tuint64_t\tnmalloc_large;\n\tuint64_t\tndalloc_large;\n\tuint64_t\tnrequests_large;\n\n\tsize_t\t\tallocated_huge;\n\tuint64_t\tnmalloc_huge;\n\tuint64_t\tndalloc_huge;\n\n\t/* One element for each large size class. */\n\tmalloc_large_stats_t\t*lstats;\n\n\t/* One element for each huge size class. */\n\tmalloc_huge_stats_t\t*hstats;\n};\n\n#endif /* JEMALLOC_H_STRUCTS */\n/******************************************************************************/\n#ifdef JEMALLOC_H_EXTERNS\n\nextern bool\topt_stats_print;\n\nextern size_t\tstats_cactive;\n\nvoid\tstats_print(void (*write)(void *, const char *), void *cbopaque,\n    const char *opts);\n\n#endif /* JEMALLOC_H_EXTERNS */\n/******************************************************************************/\n#ifdef JEMALLOC_H_INLINES\n\n#ifndef JEMALLOC_ENABLE_INLINE\nsize_t\tstats_cactive_get(void);\nvoid\tstats_cactive_add(size_t size);\nvoid\tstats_cactive_sub(size_t size);\n#endif\n\n#if (defined(JEMALLOC_ENABLE_INLINE) || defined(JEMALLOC_STATS_C_))\nJEMALLOC_INLINE size_t\nstats_cactive_get(void)\n{\n\n\treturn (atomic_read_z(&stats_cactive));\n}\n\nJEMALLOC_INLINE void\nstats_cactive_add(size_t size)\n{\n\tUNUSED size_t cactive;\n\n\tassert(size > 0);\n\tassert((size & chunksize_mask) == 0);\n\n\tcactive = atomic_add_z(&stats_cactive, size);\n\tassert(cactive - size < cactive);\n}\n\nJEMALLOC_INLINE void\nstats_cactive_sub(size_t size)\n{\n\tUNUSED size_t cactive;\n\n\tassert(size > 0);\n\tassert((size & chunksize_mask) == 0);\n\n\tcactive = atomic_sub_z(&stats_cactive, size);\n\tassert(cactive + size > cactive);\n}\n#endif\n\n#endif /* JEMALLOC_H_INLINES */\n/******************************************************************************/\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/deps/jemalloc/include/jemalloc/internal/tcache.h",
    "content": "/******************************************************************************/\n#ifdef JEMALLOC_H_TYPES\n\ntypedef struct tcache_bin_info_s tcache_bin_info_t;\ntypedef struct tcache_bin_s tcache_bin_t;\ntypedef struct tcache_s tcache_t;\ntypedef struct tcaches_s tcaches_t;\n\n/*\n * tcache pointers close to NULL are used to encode state information that is\n * used for two purposes: preventing thread caching on a per thread basis and\n * cleaning up during thread shutdown.\n */\n#define\tTCACHE_STATE_DISABLED\t\t((tcache_t *)(uintptr_t)1)\n#define\tTCACHE_STATE_REINCARNATED\t((tcache_t *)(uintptr_t)2)\n#define\tTCACHE_STATE_PURGATORY\t\t((tcache_t *)(uintptr_t)3)\n#define\tTCACHE_STATE_MAX\t\tTCACHE_STATE_PURGATORY\n\n/*\n * Absolute minimum number of cache slots for each small bin.\n */\n#define\tTCACHE_NSLOTS_SMALL_MIN\t\t20\n\n/*\n * Absolute maximum number of cache slots for each small bin in the thread\n * cache.  This is an additional constraint beyond that imposed as: twice the\n * number of regions per run for this size class.\n *\n * This constant must be an even number.\n */\n#define\tTCACHE_NSLOTS_SMALL_MAX\t\t200\n\n/* Number of cache slots for large size classes. */\n#define\tTCACHE_NSLOTS_LARGE\t\t20\n\n/* (1U << opt_lg_tcache_max) is used to compute tcache_maxclass. */\n#define\tLG_TCACHE_MAXCLASS_DEFAULT\t15\n\n/*\n * TCACHE_GC_SWEEP is the approximate number of allocation events between\n * full GC sweeps.  Integer rounding may cause the actual number to be\n * slightly higher, since GC is performed incrementally.\n */\n#define\tTCACHE_GC_SWEEP\t\t\t8192\n\n/* Number of tcache allocation/deallocation events between incremental GCs. */\n#define\tTCACHE_GC_INCR\t\t\t\t\t\t\t\\\n    ((TCACHE_GC_SWEEP / NBINS) + ((TCACHE_GC_SWEEP / NBINS == 0) ? 0 : 1))\n\n#endif /* JEMALLOC_H_TYPES */\n/******************************************************************************/\n#ifdef JEMALLOC_H_STRUCTS\n\ntypedef enum {\n\ttcache_enabled_false   = 0, /* Enable cast to/from bool. */\n\ttcache_enabled_true    = 1,\n\ttcache_enabled_default = 2\n} tcache_enabled_t;\n\n/*\n * Read-only information associated with each element of tcache_t's tbins array\n * is stored separately, mainly to reduce memory usage.\n */\nstruct tcache_bin_info_s {\n\tunsigned\tncached_max;\t/* Upper limit on ncached. */\n};\n\nstruct tcache_bin_s {\n\ttcache_bin_stats_t tstats;\n\tint\t\tlow_water;\t/* Min # cached since last GC. */\n\tunsigned\tlg_fill_div;\t/* Fill (ncached_max >> lg_fill_div). */\n\tunsigned\tncached;\t/* # of cached objects. */\n\t/*\n\t * To make use of adjacent cacheline prefetch, the items in the avail\n\t * stack goes to higher address for newer allocations.  avail points\n\t * just above the available space, which means that\n\t * avail[-ncached, ... -1] are available items and the lowest item will\n\t * be allocated first.\n\t */\n\tvoid\t\t**avail;\t/* Stack of available objects. */\n};\n\nstruct tcache_s {\n\tql_elm(tcache_t) link;\t\t/* Used for aggregating stats. */\n\tuint64_t\tprof_accumbytes;/* Cleared after arena_prof_accum(). */\n\tticker_t\tgc_ticker;\t/* Drives incremental GC. */\n\tszind_t\t\tnext_gc_bin;\t/* Next bin to GC. */\n\ttcache_bin_t\ttbins[1];\t/* Dynamically sized. */\n\t/*\n\t * The pointer stacks associated with tbins follow as a contiguous\n\t * array.  During tcache initialization, the avail pointer in each\n\t * element of tbins is initialized to point to the proper offset within\n\t * this array.\n\t */\n};\n\n/* Linkage for list of available (previously used) explicit tcache IDs. */\nstruct tcaches_s {\n\tunion {\n\t\ttcache_t\t*tcache;\n\t\ttcaches_t\t*next;\n\t};\n};\n\n#endif /* JEMALLOC_H_STRUCTS */\n/******************************************************************************/\n#ifdef JEMALLOC_H_EXTERNS\n\nextern bool\topt_tcache;\nextern ssize_t\topt_lg_tcache_max;\n\nextern tcache_bin_info_t\t*tcache_bin_info;\n\n/*\n * Number of tcache bins.  There are NBINS small-object bins, plus 0 or more\n * large-object bins.\n */\nextern unsigned\tnhbins;\n\n/* Maximum cached size class. */\nextern size_t\ttcache_maxclass;\n\n/*\n * Explicit tcaches, managed via the tcache.{create,flush,destroy} mallctls and\n * usable via the MALLOCX_TCACHE() flag.  The automatic per thread tcaches are\n * completely disjoint from this data structure.  tcaches starts off as a sparse\n * array, so it has no physical memory footprint until individual pages are\n * touched.  This allows the entire array to be allocated the first time an\n * explicit tcache is created without a disproportionate impact on memory usage.\n */\nextern tcaches_t\t*tcaches;\n\nsize_t\ttcache_salloc(tsdn_t *tsdn, const void *ptr);\nvoid\ttcache_event_hard(tsd_t *tsd, tcache_t *tcache);\nvoid\t*tcache_alloc_small_hard(tsdn_t *tsdn, arena_t *arena, tcache_t *tcache,\n    tcache_bin_t *tbin, szind_t binind, bool *tcache_success);\nvoid\ttcache_bin_flush_small(tsd_t *tsd, tcache_t *tcache, tcache_bin_t *tbin,\n    szind_t binind, unsigned rem);\nvoid\ttcache_bin_flush_large(tsd_t *tsd, tcache_bin_t *tbin, szind_t binind,\n    unsigned rem, tcache_t *tcache);\nvoid\ttcache_arena_reassociate(tsdn_t *tsdn, tcache_t *tcache,\n    arena_t *oldarena, arena_t *newarena);\ntcache_t *tcache_get_hard(tsd_t *tsd);\ntcache_t *tcache_create(tsdn_t *tsdn, arena_t *arena);\nvoid\ttcache_cleanup(tsd_t *tsd);\nvoid\ttcache_enabled_cleanup(tsd_t *tsd);\nvoid\ttcache_stats_merge(tsdn_t *tsdn, tcache_t *tcache, arena_t *arena);\nbool\ttcaches_create(tsdn_t *tsdn, unsigned *r_ind);\nvoid\ttcaches_flush(tsd_t *tsd, unsigned ind);\nvoid\ttcaches_destroy(tsd_t *tsd, unsigned ind);\nbool\ttcache_boot(tsdn_t *tsdn);\n\n#endif /* JEMALLOC_H_EXTERNS */\n/******************************************************************************/\n#ifdef JEMALLOC_H_INLINES\n\n#ifndef JEMALLOC_ENABLE_INLINE\nvoid\ttcache_event(tsd_t *tsd, tcache_t *tcache);\nvoid\ttcache_flush(void);\nbool\ttcache_enabled_get(void);\ntcache_t *tcache_get(tsd_t *tsd, bool create);\nvoid\ttcache_enabled_set(bool enabled);\nvoid\t*tcache_alloc_easy(tcache_bin_t *tbin, bool *tcache_success);\nvoid\t*tcache_alloc_small(tsd_t *tsd, arena_t *arena, tcache_t *tcache,\n    size_t size, szind_t ind, bool zero, bool slow_path);\nvoid\t*tcache_alloc_large(tsd_t *tsd, arena_t *arena, tcache_t *tcache,\n    size_t size, szind_t ind, bool zero, bool slow_path);\nvoid\ttcache_dalloc_small(tsd_t *tsd, tcache_t *tcache, void *ptr,\n    szind_t binind, bool slow_path);\nvoid\ttcache_dalloc_large(tsd_t *tsd, tcache_t *tcache, void *ptr,\n    size_t size, bool slow_path);\ntcache_t\t*tcaches_get(tsd_t *tsd, unsigned ind);\n#endif\n\n#if (defined(JEMALLOC_ENABLE_INLINE) || defined(JEMALLOC_TCACHE_C_))\nJEMALLOC_INLINE void\ntcache_flush(void)\n{\n\ttsd_t *tsd;\n\n\tcassert(config_tcache);\n\n\ttsd = tsd_fetch();\n\ttcache_cleanup(tsd);\n}\n\nJEMALLOC_INLINE bool\ntcache_enabled_get(void)\n{\n\ttsd_t *tsd;\n\ttcache_enabled_t tcache_enabled;\n\n\tcassert(config_tcache);\n\n\ttsd = tsd_fetch();\n\ttcache_enabled = tsd_tcache_enabled_get(tsd);\n\tif (tcache_enabled == tcache_enabled_default) {\n\t\ttcache_enabled = (tcache_enabled_t)opt_tcache;\n\t\ttsd_tcache_enabled_set(tsd, tcache_enabled);\n\t}\n\n\treturn ((bool)tcache_enabled);\n}\n\nJEMALLOC_INLINE void\ntcache_enabled_set(bool enabled)\n{\n\ttsd_t *tsd;\n\ttcache_enabled_t tcache_enabled;\n\n\tcassert(config_tcache);\n\n\ttsd = tsd_fetch();\n\n\ttcache_enabled = (tcache_enabled_t)enabled;\n\ttsd_tcache_enabled_set(tsd, tcache_enabled);\n\n\tif (!enabled)\n\t\ttcache_cleanup(tsd);\n}\n\nJEMALLOC_ALWAYS_INLINE tcache_t *\ntcache_get(tsd_t *tsd, bool create)\n{\n\ttcache_t *tcache;\n\n\tif (!config_tcache)\n\t\treturn (NULL);\n\n\ttcache = tsd_tcache_get(tsd);\n\tif (!create)\n\t\treturn (tcache);\n\tif (unlikely(tcache == NULL) && tsd_nominal(tsd)) {\n\t\ttcache = tcache_get_hard(tsd);\n\t\ttsd_tcache_set(tsd, tcache);\n\t}\n\n\treturn (tcache);\n}\n\nJEMALLOC_ALWAYS_INLINE void\ntcache_event(tsd_t *tsd, tcache_t *tcache)\n{\n\n\tif (TCACHE_GC_INCR == 0)\n\t\treturn;\n\n\tif (unlikely(ticker_tick(&tcache->gc_ticker)))\n\t\ttcache_event_hard(tsd, tcache);\n}\n\nJEMALLOC_ALWAYS_INLINE void *\ntcache_alloc_easy(tcache_bin_t *tbin, bool *tcache_success)\n{\n\tvoid *ret;\n\n\tif (unlikely(tbin->ncached == 0)) {\n\t\ttbin->low_water = -1;\n\t\t*tcache_success = false;\n\t\treturn (NULL);\n\t}\n\t/*\n\t * tcache_success (instead of ret) should be checked upon the return of\n\t * this function.  We avoid checking (ret == NULL) because there is\n\t * never a null stored on the avail stack (which is unknown to the\n\t * compiler), and eagerly checking ret would cause pipeline stall\n\t * (waiting for the cacheline).\n\t */\n\t*tcache_success = true;\n\tret = *(tbin->avail - tbin->ncached);\n\ttbin->ncached--;\n\n\tif (unlikely((int)tbin->ncached < tbin->low_water))\n\t\ttbin->low_water = tbin->ncached;\n\n\treturn (ret);\n}\n\nJEMALLOC_ALWAYS_INLINE void *\ntcache_alloc_small(tsd_t *tsd, arena_t *arena, tcache_t *tcache, size_t size,\n    szind_t binind, bool zero, bool slow_path)\n{\n\tvoid *ret;\n\ttcache_bin_t *tbin;\n\tbool tcache_success;\n\tsize_t usize JEMALLOC_CC_SILENCE_INIT(0);\n\n\tassert(binind < NBINS);\n\ttbin = &tcache->tbins[binind];\n\tret = tcache_alloc_easy(tbin, &tcache_success);\n\tassert(tcache_success == (ret != NULL));\n\tif (unlikely(!tcache_success)) {\n\t\tbool tcache_hard_success;\n\t\tarena = arena_choose(tsd, arena);\n\t\tif (unlikely(arena == NULL))\n\t\t\treturn (NULL);\n\n\t\tret = tcache_alloc_small_hard(tsd_tsdn(tsd), arena, tcache,\n\t\t    tbin, binind, &tcache_hard_success);\n\t\tif (tcache_hard_success == false)\n\t\t\treturn (NULL);\n\t}\n\n\tassert(ret);\n\t/*\n\t * Only compute usize if required.  The checks in the following if\n\t * statement are all static.\n\t */\n\tif (config_prof || (slow_path && config_fill) || unlikely(zero)) {\n\t\tusize = index2size(binind);\n\t\tassert(tcache_salloc(tsd_tsdn(tsd), ret) == usize);\n\t}\n\n\tif (likely(!zero)) {\n\t\tif (slow_path && config_fill) {\n\t\t\tif (unlikely(opt_junk_alloc)) {\n\t\t\t\tarena_alloc_junk_small(ret,\n\t\t\t\t    &arena_bin_info[binind], false);\n\t\t\t} else if (unlikely(opt_zero))\n\t\t\t\tmemset(ret, 0, usize);\n\t\t}\n\t} else {\n\t\tif (slow_path && config_fill && unlikely(opt_junk_alloc)) {\n\t\t\tarena_alloc_junk_small(ret, &arena_bin_info[binind],\n\t\t\t    true);\n\t\t}\n\t\tmemset(ret, 0, usize);\n\t}\n\n\tif (config_stats)\n\t\ttbin->tstats.nrequests++;\n\tif (config_prof)\n\t\ttcache->prof_accumbytes += usize;\n\ttcache_event(tsd, tcache);\n\treturn (ret);\n}\n\nJEMALLOC_ALWAYS_INLINE void *\ntcache_alloc_large(tsd_t *tsd, arena_t *arena, tcache_t *tcache, size_t size,\n    szind_t binind, bool zero, bool slow_path)\n{\n\tvoid *ret;\n\ttcache_bin_t *tbin;\n\tbool tcache_success;\n\n\tassert(binind < nhbins);\n\ttbin = &tcache->tbins[binind];\n\tret = tcache_alloc_easy(tbin, &tcache_success);\n\tassert(tcache_success == (ret != NULL));\n\tif (unlikely(!tcache_success)) {\n\t\t/*\n\t\t * Only allocate one large object at a time, because it's quite\n\t\t * expensive to create one and not use it.\n\t\t */\n\t\tarena = arena_choose(tsd, arena);\n\t\tif (unlikely(arena == NULL))\n\t\t\treturn (NULL);\n\n\t\tret = arena_malloc_large(tsd_tsdn(tsd), arena, binind, zero);\n\t\tif (ret == NULL)\n\t\t\treturn (NULL);\n\t} else {\n\t\tsize_t usize JEMALLOC_CC_SILENCE_INIT(0);\n\n\t\t/* Only compute usize on demand */\n\t\tif (config_prof || (slow_path && config_fill) ||\n\t\t    unlikely(zero)) {\n\t\t\tusize = index2size(binind);\n\t\t\tassert(usize <= tcache_maxclass);\n\t\t}\n\n\t\tif (config_prof && usize == LARGE_MINCLASS) {\n\t\t\tarena_chunk_t *chunk =\n\t\t\t    (arena_chunk_t *)CHUNK_ADDR2BASE(ret);\n\t\t\tsize_t pageind = (((uintptr_t)ret - (uintptr_t)chunk) >>\n\t\t\t    LG_PAGE);\n\t\t\tarena_mapbits_large_binind_set(chunk, pageind,\n\t\t\t    BININD_INVALID);\n\t\t}\n\t\tif (likely(!zero)) {\n\t\t\tif (slow_path && config_fill) {\n\t\t\t\tif (unlikely(opt_junk_alloc)) {\n\t\t\t\t\tmemset(ret, JEMALLOC_ALLOC_JUNK,\n\t\t\t\t\t    usize);\n\t\t\t\t} else if (unlikely(opt_zero))\n\t\t\t\t\tmemset(ret, 0, usize);\n\t\t\t}\n\t\t} else\n\t\t\tmemset(ret, 0, usize);\n\n\t\tif (config_stats)\n\t\t\ttbin->tstats.nrequests++;\n\t\tif (config_prof)\n\t\t\ttcache->prof_accumbytes += usize;\n\t}\n\n\ttcache_event(tsd, tcache);\n\treturn (ret);\n}\n\nJEMALLOC_ALWAYS_INLINE void\ntcache_dalloc_small(tsd_t *tsd, tcache_t *tcache, void *ptr, szind_t binind,\n    bool slow_path)\n{\n\ttcache_bin_t *tbin;\n\ttcache_bin_info_t *tbin_info;\n\n\tassert(tcache_salloc(tsd_tsdn(tsd), ptr) <= SMALL_MAXCLASS);\n\n\tif (slow_path && config_fill && unlikely(opt_junk_free))\n\t\tarena_dalloc_junk_small(ptr, &arena_bin_info[binind]);\n\n\ttbin = &tcache->tbins[binind];\n\ttbin_info = &tcache_bin_info[binind];\n\tif (unlikely(tbin->ncached == tbin_info->ncached_max)) {\n\t\ttcache_bin_flush_small(tsd, tcache, tbin, binind,\n\t\t    (tbin_info->ncached_max >> 1));\n\t}\n\tassert(tbin->ncached < tbin_info->ncached_max);\n\ttbin->ncached++;\n\t*(tbin->avail - tbin->ncached) = ptr;\n\n\ttcache_event(tsd, tcache);\n}\n\nJEMALLOC_ALWAYS_INLINE void\ntcache_dalloc_large(tsd_t *tsd, tcache_t *tcache, void *ptr, size_t size,\n    bool slow_path)\n{\n\tszind_t binind;\n\ttcache_bin_t *tbin;\n\ttcache_bin_info_t *tbin_info;\n\n\tassert((size & PAGE_MASK) == 0);\n\tassert(tcache_salloc(tsd_tsdn(tsd), ptr) > SMALL_MAXCLASS);\n\tassert(tcache_salloc(tsd_tsdn(tsd), ptr) <= tcache_maxclass);\n\n\tbinind = size2index(size);\n\n\tif (slow_path && config_fill && unlikely(opt_junk_free))\n\t\tarena_dalloc_junk_large(ptr, size);\n\n\ttbin = &tcache->tbins[binind];\n\ttbin_info = &tcache_bin_info[binind];\n\tif (unlikely(tbin->ncached == tbin_info->ncached_max)) {\n\t\ttcache_bin_flush_large(tsd, tbin, binind,\n\t\t    (tbin_info->ncached_max >> 1), tcache);\n\t}\n\tassert(tbin->ncached < tbin_info->ncached_max);\n\ttbin->ncached++;\n\t*(tbin->avail - tbin->ncached) = ptr;\n\n\ttcache_event(tsd, tcache);\n}\n\nJEMALLOC_ALWAYS_INLINE tcache_t *\ntcaches_get(tsd_t *tsd, unsigned ind)\n{\n\ttcaches_t *elm = &tcaches[ind];\n\tif (unlikely(elm->tcache == NULL)) {\n\t\telm->tcache = tcache_create(tsd_tsdn(tsd), arena_choose(tsd,\n\t\t    NULL));\n\t}\n\treturn (elm->tcache);\n}\n#endif\n\n#endif /* JEMALLOC_H_INLINES */\n/******************************************************************************/\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/deps/jemalloc/include/jemalloc/internal/ticker.h",
    "content": "/******************************************************************************/\n#ifdef JEMALLOC_H_TYPES\n\ntypedef struct ticker_s ticker_t;\n\n#endif /* JEMALLOC_H_TYPES */\n/******************************************************************************/\n#ifdef JEMALLOC_H_STRUCTS\n\nstruct ticker_s {\n\tint32_t\ttick;\n\tint32_t\tnticks;\n};\n\n#endif /* JEMALLOC_H_STRUCTS */\n/******************************************************************************/\n#ifdef JEMALLOC_H_EXTERNS\n\n#endif /* JEMALLOC_H_EXTERNS */\n/******************************************************************************/\n#ifdef JEMALLOC_H_INLINES\n\n#ifndef JEMALLOC_ENABLE_INLINE\nvoid\tticker_init(ticker_t *ticker, int32_t nticks);\nvoid\tticker_copy(ticker_t *ticker, const ticker_t *other);\nint32_t\tticker_read(const ticker_t *ticker);\nbool\tticker_ticks(ticker_t *ticker, int32_t nticks);\nbool\tticker_tick(ticker_t *ticker);\n#endif\n\n#if (defined(JEMALLOC_ENABLE_INLINE) || defined(JEMALLOC_TICKER_C_))\nJEMALLOC_INLINE void\nticker_init(ticker_t *ticker, int32_t nticks)\n{\n\n\tticker->tick = nticks;\n\tticker->nticks = nticks;\n}\n\nJEMALLOC_INLINE void\nticker_copy(ticker_t *ticker, const ticker_t *other)\n{\n\n\t*ticker = *other;\n}\n\nJEMALLOC_INLINE int32_t\nticker_read(const ticker_t *ticker)\n{\n\n\treturn (ticker->tick);\n}\n\nJEMALLOC_INLINE bool\nticker_ticks(ticker_t *ticker, int32_t nticks)\n{\n\n\tif (unlikely(ticker->tick < nticks)) {\n\t\tticker->tick = ticker->nticks;\n\t\treturn (true);\n\t}\n\tticker->tick -= nticks;\n\treturn(false);\n}\n\nJEMALLOC_INLINE bool\nticker_tick(ticker_t *ticker)\n{\n\n\treturn (ticker_ticks(ticker, 1));\n}\n#endif\n\n#endif /* JEMALLOC_H_INLINES */\n/******************************************************************************/\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/deps/jemalloc/include/jemalloc/internal/tsd.h",
    "content": "/******************************************************************************/\n#ifdef JEMALLOC_H_TYPES\n\n/* Maximum number of malloc_tsd users with cleanup functions. */\n#define\tMALLOC_TSD_CLEANUPS_MAX\t2\n\ntypedef bool (*malloc_tsd_cleanup_t)(void);\n\n#if (!defined(JEMALLOC_MALLOC_THREAD_CLEANUP) && !defined(JEMALLOC_TLS) && \\\n    !defined(_WIN32))\ntypedef struct tsd_init_block_s tsd_init_block_t;\ntypedef struct tsd_init_head_s tsd_init_head_t;\n#endif\n\ntypedef struct tsd_s tsd_t;\ntypedef struct tsdn_s tsdn_t;\n\n#define\tTSDN_NULL\t((tsdn_t *)0)\n\ntypedef enum {\n\ttsd_state_uninitialized,\n\ttsd_state_nominal,\n\ttsd_state_purgatory,\n\ttsd_state_reincarnated\n} tsd_state_t;\n\n/*\n * TLS/TSD-agnostic macro-based implementation of thread-specific data.  There\n * are five macros that support (at least) three use cases: file-private,\n * library-private, and library-private inlined.  Following is an example\n * library-private tsd variable:\n *\n * In example.h:\n *   typedef struct {\n *           int x;\n *           int y;\n *   } example_t;\n *   #define EX_INITIALIZER JEMALLOC_CONCAT({0, 0})\n *   malloc_tsd_types(example_, example_t)\n *   malloc_tsd_protos(, example_, example_t)\n *   malloc_tsd_externs(example_, example_t)\n * In example.c:\n *   malloc_tsd_data(, example_, example_t, EX_INITIALIZER)\n *   malloc_tsd_funcs(, example_, example_t, EX_INITIALIZER,\n *       example_tsd_cleanup)\n *\n * The result is a set of generated functions, e.g.:\n *\n *   bool example_tsd_boot(void) {...}\n *   bool example_tsd_booted_get(void) {...}\n *   example_t *example_tsd_get() {...}\n *   void example_tsd_set(example_t *val) {...}\n *\n * Note that all of the functions deal in terms of (a_type *) rather than\n * (a_type) so that it is possible to support non-pointer types (unlike\n * pthreads TSD).  example_tsd_cleanup() is passed an (a_type *) pointer that is\n * cast to (void *).  This means that the cleanup function needs to cast the\n * function argument to (a_type *), then dereference the resulting pointer to\n * access fields, e.g.\n *\n *   void\n *   example_tsd_cleanup(void *arg)\n *   {\n *           example_t *example = (example_t *)arg;\n *\n *           example->x = 42;\n *           [...]\n *           if ([want the cleanup function to be called again])\n *                   example_tsd_set(example);\n *   }\n *\n * If example_tsd_set() is called within example_tsd_cleanup(), it will be\n * called again.  This is similar to how pthreads TSD destruction works, except\n * that pthreads only calls the cleanup function again if the value was set to\n * non-NULL.\n */\n\n/* malloc_tsd_types(). */\n#ifdef JEMALLOC_MALLOC_THREAD_CLEANUP\n#define\tmalloc_tsd_types(a_name, a_type)\n#elif (defined(JEMALLOC_TLS))\n#define\tmalloc_tsd_types(a_name, a_type)\n#elif (defined(_WIN32))\n#define\tmalloc_tsd_types(a_name, a_type)\t\t\t\t\\\ntypedef struct {\t\t\t\t\t\t\t\\\n\tbool\tinitialized;\t\t\t\t\t\t\\\n\ta_type\tval;\t\t\t\t\t\t\t\\\n} a_name##tsd_wrapper_t;\n#else\n#define\tmalloc_tsd_types(a_name, a_type)\t\t\t\t\\\ntypedef struct {\t\t\t\t\t\t\t\\\n\tbool\tinitialized;\t\t\t\t\t\t\\\n\ta_type\tval;\t\t\t\t\t\t\t\\\n} a_name##tsd_wrapper_t;\n#endif\n\n/* malloc_tsd_protos(). */\n#define\tmalloc_tsd_protos(a_attr, a_name, a_type)\t\t\t\\\na_attr bool\t\t\t\t\t\t\t\t\\\na_name##tsd_boot0(void);\t\t\t\t\t\t\\\na_attr void\t\t\t\t\t\t\t\t\\\na_name##tsd_boot1(void);\t\t\t\t\t\t\\\na_attr bool\t\t\t\t\t\t\t\t\\\na_name##tsd_boot(void);\t\t\t\t\t\t\t\\\na_attr bool\t\t\t\t\t\t\t\t\\\na_name##tsd_booted_get(void);\t\t\t\t\t\t\\\na_attr a_type *\t\t\t\t\t\t\t\t\\\na_name##tsd_get(void);\t\t\t\t\t\t\t\\\na_attr void\t\t\t\t\t\t\t\t\\\na_name##tsd_set(a_type *val);\n\n/* malloc_tsd_externs(). */\n#ifdef JEMALLOC_MALLOC_THREAD_CLEANUP\n#define\tmalloc_tsd_externs(a_name, a_type)\t\t\t\t\\\nextern __thread a_type\ta_name##tsd_tls;\t\t\t\t\\\nextern __thread bool\ta_name##tsd_initialized;\t\t\t\\\nextern bool\t\ta_name##tsd_booted;\n#elif (defined(JEMALLOC_TLS))\n#define\tmalloc_tsd_externs(a_name, a_type)\t\t\t\t\\\nextern __thread a_type\ta_name##tsd_tls;\t\t\t\t\\\nextern pthread_key_t\ta_name##tsd_tsd;\t\t\t\t\\\nextern bool\t\ta_name##tsd_booted;\n#elif (defined(_WIN32))\n#define\tmalloc_tsd_externs(a_name, a_type)\t\t\t\t\\\nextern DWORD\t\ta_name##tsd_tsd;\t\t\t\t\\\nextern a_name##tsd_wrapper_t\ta_name##tsd_boot_wrapper;\t\t\\\nextern bool\t\ta_name##tsd_booted;\n#else\n#define\tmalloc_tsd_externs(a_name, a_type)\t\t\t\t\\\nextern pthread_key_t\ta_name##tsd_tsd;\t\t\t\t\\\nextern tsd_init_head_t\ta_name##tsd_init_head;\t\t\t\t\\\nextern a_name##tsd_wrapper_t\ta_name##tsd_boot_wrapper;\t\t\\\nextern bool\t\ta_name##tsd_booted;\n#endif\n\n/* malloc_tsd_data(). */\n#ifdef JEMALLOC_MALLOC_THREAD_CLEANUP\n#define\tmalloc_tsd_data(a_attr, a_name, a_type, a_initializer)\t\t\\\na_attr __thread a_type JEMALLOC_TLS_MODEL\t\t\t\t\\\n    a_name##tsd_tls = a_initializer;\t\t\t\t\t\\\na_attr __thread bool JEMALLOC_TLS_MODEL\t\t\t\t\t\\\n    a_name##tsd_initialized = false;\t\t\t\t\t\\\na_attr bool\t\ta_name##tsd_booted = false;\n#elif (defined(JEMALLOC_TLS))\n#define\tmalloc_tsd_data(a_attr, a_name, a_type, a_initializer)\t\t\\\na_attr __thread a_type JEMALLOC_TLS_MODEL\t\t\t\t\\\n    a_name##tsd_tls = a_initializer;\t\t\t\t\t\\\na_attr pthread_key_t\ta_name##tsd_tsd;\t\t\t\t\\\na_attr bool\t\ta_name##tsd_booted = false;\n#elif (defined(_WIN32))\n#define\tmalloc_tsd_data(a_attr, a_name, a_type, a_initializer)\t\t\\\na_attr DWORD\t\ta_name##tsd_tsd;\t\t\t\t\\\na_attr a_name##tsd_wrapper_t a_name##tsd_boot_wrapper = {\t\t\\\n\tfalse,\t\t\t\t\t\t\t\t\\\n\ta_initializer\t\t\t\t\t\t\t\\\n};\t\t\t\t\t\t\t\t\t\\\na_attr bool\t\ta_name##tsd_booted = false;\n#else\n#define\tmalloc_tsd_data(a_attr, a_name, a_type, a_initializer)\t\t\\\na_attr pthread_key_t\ta_name##tsd_tsd;\t\t\t\t\\\na_attr tsd_init_head_t\ta_name##tsd_init_head = {\t\t\t\\\n\tql_head_initializer(blocks),\t\t\t\t\t\\\n\tMALLOC_MUTEX_INITIALIZER\t\t\t\t\t\\\n};\t\t\t\t\t\t\t\t\t\\\na_attr a_name##tsd_wrapper_t a_name##tsd_boot_wrapper = {\t\t\\\n\tfalse,\t\t\t\t\t\t\t\t\\\n\ta_initializer\t\t\t\t\t\t\t\\\n};\t\t\t\t\t\t\t\t\t\\\na_attr bool\t\ta_name##tsd_booted = false;\n#endif\n\n/* malloc_tsd_funcs(). */\n#ifdef JEMALLOC_MALLOC_THREAD_CLEANUP\n#define\tmalloc_tsd_funcs(a_attr, a_name, a_type, a_initializer,\t\t\\\n    a_cleanup)\t\t\t\t\t\t\t\t\\\n/* Initialization/cleanup. */\t\t\t\t\t\t\\\na_attr bool\t\t\t\t\t\t\t\t\\\na_name##tsd_cleanup_wrapper(void)\t\t\t\t\t\\\n{\t\t\t\t\t\t\t\t\t\\\n\t\t\t\t\t\t\t\t\t\\\n\tif (a_name##tsd_initialized) {\t\t\t\t\t\\\n\t\ta_name##tsd_initialized = false;\t\t\t\\\n\t\ta_cleanup(&a_name##tsd_tls);\t\t\t\t\\\n\t}\t\t\t\t\t\t\t\t\\\n\treturn (a_name##tsd_initialized);\t\t\t\t\\\n}\t\t\t\t\t\t\t\t\t\\\na_attr bool\t\t\t\t\t\t\t\t\\\na_name##tsd_boot0(void)\t\t\t\t\t\t\t\\\n{\t\t\t\t\t\t\t\t\t\\\n\t\t\t\t\t\t\t\t\t\\\n\tif (a_cleanup != malloc_tsd_no_cleanup) {\t\t\t\\\n\t\tmalloc_tsd_cleanup_register(\t\t\t\t\\\n\t\t    &a_name##tsd_cleanup_wrapper);\t\t\t\\\n\t}\t\t\t\t\t\t\t\t\\\n\ta_name##tsd_booted = true;\t\t\t\t\t\\\n\treturn (false);\t\t\t\t\t\t\t\\\n}\t\t\t\t\t\t\t\t\t\\\na_attr void\t\t\t\t\t\t\t\t\\\na_name##tsd_boot1(void)\t\t\t\t\t\t\t\\\n{\t\t\t\t\t\t\t\t\t\\\n\t\t\t\t\t\t\t\t\t\\\n\t/* Do nothing. */\t\t\t\t\t\t\\\n}\t\t\t\t\t\t\t\t\t\\\na_attr bool\t\t\t\t\t\t\t\t\\\na_name##tsd_boot(void)\t\t\t\t\t\t\t\\\n{\t\t\t\t\t\t\t\t\t\\\n\t\t\t\t\t\t\t\t\t\\\n\treturn (a_name##tsd_boot0());\t\t\t\t\t\\\n}\t\t\t\t\t\t\t\t\t\\\na_attr bool\t\t\t\t\t\t\t\t\\\na_name##tsd_booted_get(void)\t\t\t\t\t\t\\\n{\t\t\t\t\t\t\t\t\t\\\n\t\t\t\t\t\t\t\t\t\\\n\treturn (a_name##tsd_booted);\t\t\t\t\t\\\n}\t\t\t\t\t\t\t\t\t\\\n/* Get/set. */\t\t\t\t\t\t\t\t\\\na_attr a_type *\t\t\t\t\t\t\t\t\\\na_name##tsd_get(void)\t\t\t\t\t\t\t\\\n{\t\t\t\t\t\t\t\t\t\\\n\t\t\t\t\t\t\t\t\t\\\n\tassert(a_name##tsd_booted);\t\t\t\t\t\\\n\treturn (&a_name##tsd_tls);\t\t\t\t\t\\\n}\t\t\t\t\t\t\t\t\t\\\na_attr void\t\t\t\t\t\t\t\t\\\na_name##tsd_set(a_type *val)\t\t\t\t\t\t\\\n{\t\t\t\t\t\t\t\t\t\\\n\t\t\t\t\t\t\t\t\t\\\n\tassert(a_name##tsd_booted);\t\t\t\t\t\\\n\ta_name##tsd_tls = (*val);\t\t\t\t\t\\\n\tif (a_cleanup != malloc_tsd_no_cleanup)\t\t\t\t\\\n\t\ta_name##tsd_initialized = true;\t\t\t\t\\\n}\n#elif (defined(JEMALLOC_TLS))\n#define\tmalloc_tsd_funcs(a_attr, a_name, a_type, a_initializer,\t\t\\\n    a_cleanup)\t\t\t\t\t\t\t\t\\\n/* Initialization/cleanup. */\t\t\t\t\t\t\\\na_attr bool\t\t\t\t\t\t\t\t\\\na_name##tsd_boot0(void)\t\t\t\t\t\t\t\\\n{\t\t\t\t\t\t\t\t\t\\\n\t\t\t\t\t\t\t\t\t\\\n\tif (a_cleanup != malloc_tsd_no_cleanup) {\t\t\t\\\n\t\tif (pthread_key_create(&a_name##tsd_tsd, a_cleanup) !=\t\\\n\t\t    0)\t\t\t\t\t\t\t\\\n\t\t\treturn (true);\t\t\t\t\t\\\n\t}\t\t\t\t\t\t\t\t\\\n\ta_name##tsd_booted = true;\t\t\t\t\t\\\n\treturn (false);\t\t\t\t\t\t\t\\\n}\t\t\t\t\t\t\t\t\t\\\na_attr void\t\t\t\t\t\t\t\t\\\na_name##tsd_boot1(void)\t\t\t\t\t\t\t\\\n{\t\t\t\t\t\t\t\t\t\\\n\t\t\t\t\t\t\t\t\t\\\n\t/* Do nothing. */\t\t\t\t\t\t\\\n}\t\t\t\t\t\t\t\t\t\\\na_attr bool\t\t\t\t\t\t\t\t\\\na_name##tsd_boot(void)\t\t\t\t\t\t\t\\\n{\t\t\t\t\t\t\t\t\t\\\n\t\t\t\t\t\t\t\t\t\\\n\treturn (a_name##tsd_boot0());\t\t\t\t\t\\\n}\t\t\t\t\t\t\t\t\t\\\na_attr bool\t\t\t\t\t\t\t\t\\\na_name##tsd_booted_get(void)\t\t\t\t\t\t\\\n{\t\t\t\t\t\t\t\t\t\\\n\t\t\t\t\t\t\t\t\t\\\n\treturn (a_name##tsd_booted);\t\t\t\t\t\\\n}\t\t\t\t\t\t\t\t\t\\\n/* Get/set. */\t\t\t\t\t\t\t\t\\\na_attr a_type *\t\t\t\t\t\t\t\t\\\na_name##tsd_get(void)\t\t\t\t\t\t\t\\\n{\t\t\t\t\t\t\t\t\t\\\n\t\t\t\t\t\t\t\t\t\\\n\tassert(a_name##tsd_booted);\t\t\t\t\t\\\n\treturn (&a_name##tsd_tls);\t\t\t\t\t\\\n}\t\t\t\t\t\t\t\t\t\\\na_attr void\t\t\t\t\t\t\t\t\\\na_name##tsd_set(a_type *val)\t\t\t\t\t\t\\\n{\t\t\t\t\t\t\t\t\t\\\n\t\t\t\t\t\t\t\t\t\\\n\tassert(a_name##tsd_booted);\t\t\t\t\t\\\n\ta_name##tsd_tls = (*val);\t\t\t\t\t\\\n\tif (a_cleanup != malloc_tsd_no_cleanup) {\t\t\t\\\n\t\tif (pthread_setspecific(a_name##tsd_tsd,\t\t\\\n\t\t    (void *)(&a_name##tsd_tls))) {\t\t\t\\\n\t\t\tmalloc_write(\"<jemalloc>: Error\"\t\t\\\n\t\t\t    \" setting TSD for \"#a_name\"\\n\");\t\t\\\n\t\t\tif (opt_abort)\t\t\t\t\t\\\n\t\t\t\tabort();\t\t\t\t\\\n\t\t}\t\t\t\t\t\t\t\\\n\t}\t\t\t\t\t\t\t\t\\\n}\n#elif (defined(_WIN32))\n#define\tmalloc_tsd_funcs(a_attr, a_name, a_type, a_initializer,\t\t\\\n    a_cleanup)\t\t\t\t\t\t\t\t\\\n/* Initialization/cleanup. */\t\t\t\t\t\t\\\na_attr bool\t\t\t\t\t\t\t\t\\\na_name##tsd_cleanup_wrapper(void)\t\t\t\t\t\\\n{\t\t\t\t\t\t\t\t\t\\\n\tDWORD error = GetLastError();\t\t\t\t\t\\\n\ta_name##tsd_wrapper_t *wrapper = (a_name##tsd_wrapper_t *)\t\\\n\t    TlsGetValue(a_name##tsd_tsd);\t\t\t\t\\\n\tSetLastError(error);\t\t\t\t\t\t\\\n\t\t\t\t\t\t\t\t\t\\\n\tif (wrapper == NULL)\t\t\t\t\t\t\\\n\t\treturn (false);\t\t\t\t\t\t\\\n\tif (a_cleanup != malloc_tsd_no_cleanup &&\t\t\t\\\n\t    wrapper->initialized) {\t\t\t\t\t\\\n\t\twrapper->initialized = false;\t\t\t\t\\\n\t\ta_cleanup(&wrapper->val);\t\t\t\t\\\n\t\tif (wrapper->initialized) {\t\t\t\t\\\n\t\t\t/* Trigger another cleanup round. */\t\t\\\n\t\t\treturn (true);\t\t\t\t\t\\\n\t\t}\t\t\t\t\t\t\t\\\n\t}\t\t\t\t\t\t\t\t\\\n\tmalloc_tsd_dalloc(wrapper);\t\t\t\t\t\\\n\treturn (false);\t\t\t\t\t\t\t\\\n}\t\t\t\t\t\t\t\t\t\\\na_attr void\t\t\t\t\t\t\t\t\\\na_name##tsd_wrapper_set(a_name##tsd_wrapper_t *wrapper)\t\t\t\\\n{\t\t\t\t\t\t\t\t\t\\\n\t\t\t\t\t\t\t\t\t\\\n\tif (!TlsSetValue(a_name##tsd_tsd, (void *)wrapper)) {\t\t\\\n\t\tmalloc_write(\"<jemalloc>: Error setting\"\t\t\\\n\t\t    \" TSD for \"#a_name\"\\n\");\t\t\t\t\\\n\t\tabort();\t\t\t\t\t\t\\\n\t}\t\t\t\t\t\t\t\t\\\n}\t\t\t\t\t\t\t\t\t\\\na_attr a_name##tsd_wrapper_t *\t\t\t\t\t\t\\\na_name##tsd_wrapper_get(void)\t\t\t\t\t\t\\\n{\t\t\t\t\t\t\t\t\t\\\n\tDWORD error = GetLastError();\t\t\t\t\t\\\n\ta_name##tsd_wrapper_t *wrapper = (a_name##tsd_wrapper_t *)\t\\\n\t    TlsGetValue(a_name##tsd_tsd);\t\t\t\t\\\n\tSetLastError(error);\t\t\t\t\t\t\\\n\t\t\t\t\t\t\t\t\t\\\n\tif (unlikely(wrapper == NULL)) {\t\t\t\t\\\n\t\twrapper = (a_name##tsd_wrapper_t *)\t\t\t\\\n\t\t    malloc_tsd_malloc(sizeof(a_name##tsd_wrapper_t));\t\\\n\t\tif (wrapper == NULL) {\t\t\t\t\t\\\n\t\t\tmalloc_write(\"<jemalloc>: Error allocating\"\t\\\n\t\t\t    \" TSD for \"#a_name\"\\n\");\t\t\t\\\n\t\t\tabort();\t\t\t\t\t\\\n\t\t} else {\t\t\t\t\t\t\\\n\t\t\twrapper->initialized = false;\t\t\t\\\n\t\t\twrapper->val = a_initializer;\t\t\t\\\n\t\t}\t\t\t\t\t\t\t\\\n\t\ta_name##tsd_wrapper_set(wrapper);\t\t\t\\\n\t}\t\t\t\t\t\t\t\t\\\n\treturn (wrapper);\t\t\t\t\t\t\\\n}\t\t\t\t\t\t\t\t\t\\\na_attr bool\t\t\t\t\t\t\t\t\\\na_name##tsd_boot0(void)\t\t\t\t\t\t\t\\\n{\t\t\t\t\t\t\t\t\t\\\n\t\t\t\t\t\t\t\t\t\\\n\ta_name##tsd_tsd = TlsAlloc();\t\t\t\t\t\\\n\tif (a_name##tsd_tsd == TLS_OUT_OF_INDEXES)\t\t\t\\\n\t\treturn (true);\t\t\t\t\t\t\\\n\tif (a_cleanup != malloc_tsd_no_cleanup) {\t\t\t\\\n\t\tmalloc_tsd_cleanup_register(\t\t\t\t\\\n\t\t    &a_name##tsd_cleanup_wrapper);\t\t\t\\\n\t}\t\t\t\t\t\t\t\t\\\n\ta_name##tsd_wrapper_set(&a_name##tsd_boot_wrapper);\t\t\\\n\ta_name##tsd_booted = true;\t\t\t\t\t\\\n\treturn (false);\t\t\t\t\t\t\t\\\n}\t\t\t\t\t\t\t\t\t\\\na_attr void\t\t\t\t\t\t\t\t\\\na_name##tsd_boot1(void)\t\t\t\t\t\t\t\\\n{\t\t\t\t\t\t\t\t\t\\\n\ta_name##tsd_wrapper_t *wrapper;\t\t\t\t\t\\\n\twrapper = (a_name##tsd_wrapper_t *)\t\t\t\t\\\n\t    malloc_tsd_malloc(sizeof(a_name##tsd_wrapper_t));\t\t\\\n\tif (wrapper == NULL) {\t\t\t\t\t\t\\\n\t\tmalloc_write(\"<jemalloc>: Error allocating\"\t\t\\\n\t\t    \" TSD for \"#a_name\"\\n\");\t\t\t\t\\\n\t\tabort();\t\t\t\t\t\t\\\n\t}\t\t\t\t\t\t\t\t\\\n\tmemcpy(wrapper, &a_name##tsd_boot_wrapper,\t\t\t\\\n\t    sizeof(a_name##tsd_wrapper_t));\t\t\t\t\\\n\ta_name##tsd_wrapper_set(wrapper);\t\t\t\t\\\n}\t\t\t\t\t\t\t\t\t\\\na_attr bool\t\t\t\t\t\t\t\t\\\na_name##tsd_boot(void)\t\t\t\t\t\t\t\\\n{\t\t\t\t\t\t\t\t\t\\\n\t\t\t\t\t\t\t\t\t\\\n\tif (a_name##tsd_boot0())\t\t\t\t\t\\\n\t\treturn (true);\t\t\t\t\t\t\\\n\ta_name##tsd_boot1();\t\t\t\t\t\t\\\n\treturn (false);\t\t\t\t\t\t\t\\\n}\t\t\t\t\t\t\t\t\t\\\na_attr bool\t\t\t\t\t\t\t\t\\\na_name##tsd_booted_get(void)\t\t\t\t\t\t\\\n{\t\t\t\t\t\t\t\t\t\\\n\t\t\t\t\t\t\t\t\t\\\n\treturn (a_name##tsd_booted);\t\t\t\t\t\\\n}\t\t\t\t\t\t\t\t\t\\\n/* Get/set. */\t\t\t\t\t\t\t\t\\\na_attr a_type *\t\t\t\t\t\t\t\t\\\na_name##tsd_get(void)\t\t\t\t\t\t\t\\\n{\t\t\t\t\t\t\t\t\t\\\n\ta_name##tsd_wrapper_t *wrapper;\t\t\t\t\t\\\n\t\t\t\t\t\t\t\t\t\\\n\tassert(a_name##tsd_booted);\t\t\t\t\t\\\n\twrapper = a_name##tsd_wrapper_get();\t\t\t\t\\\n\treturn (&wrapper->val);\t\t\t\t\t\t\\\n}\t\t\t\t\t\t\t\t\t\\\na_attr void\t\t\t\t\t\t\t\t\\\na_name##tsd_set(a_type *val)\t\t\t\t\t\t\\\n{\t\t\t\t\t\t\t\t\t\\\n\ta_name##tsd_wrapper_t *wrapper;\t\t\t\t\t\\\n\t\t\t\t\t\t\t\t\t\\\n\tassert(a_name##tsd_booted);\t\t\t\t\t\\\n\twrapper = a_name##tsd_wrapper_get();\t\t\t\t\\\n\twrapper->val = *(val);\t\t\t\t\t\t\\\n\tif (a_cleanup != malloc_tsd_no_cleanup)\t\t\t\t\\\n\t\twrapper->initialized = true;\t\t\t\t\\\n}\n#else\n#define\tmalloc_tsd_funcs(a_attr, a_name, a_type, a_initializer,\t\t\\\n    a_cleanup)\t\t\t\t\t\t\t\t\\\n/* Initialization/cleanup. */\t\t\t\t\t\t\\\na_attr void\t\t\t\t\t\t\t\t\\\na_name##tsd_cleanup_wrapper(void *arg)\t\t\t\t\t\\\n{\t\t\t\t\t\t\t\t\t\\\n\ta_name##tsd_wrapper_t *wrapper = (a_name##tsd_wrapper_t *)arg;\t\\\n\t\t\t\t\t\t\t\t\t\\\n\tif (a_cleanup != malloc_tsd_no_cleanup &&\t\t\t\\\n\t    wrapper->initialized) {\t\t\t\t\t\\\n\t\twrapper->initialized = false;\t\t\t\t\\\n\t\ta_cleanup(&wrapper->val);\t\t\t\t\\\n\t\tif (wrapper->initialized) {\t\t\t\t\\\n\t\t\t/* Trigger another cleanup round. */\t\t\\\n\t\t\tif (pthread_setspecific(a_name##tsd_tsd,\t\\\n\t\t\t    (void *)wrapper)) {\t\t\t\t\\\n\t\t\t\tmalloc_write(\"<jemalloc>: Error\"\t\\\n\t\t\t\t    \" setting TSD for \"#a_name\"\\n\");\t\\\n\t\t\t\tif (opt_abort)\t\t\t\t\\\n\t\t\t\t\tabort();\t\t\t\\\n\t\t\t}\t\t\t\t\t\t\\\n\t\t\treturn;\t\t\t\t\t\t\\\n\t\t}\t\t\t\t\t\t\t\\\n\t}\t\t\t\t\t\t\t\t\\\n\tmalloc_tsd_dalloc(wrapper);\t\t\t\t\t\\\n}\t\t\t\t\t\t\t\t\t\\\na_attr void\t\t\t\t\t\t\t\t\\\na_name##tsd_wrapper_set(a_name##tsd_wrapper_t *wrapper)\t\t\t\\\n{\t\t\t\t\t\t\t\t\t\\\n\t\t\t\t\t\t\t\t\t\\\n\tif (pthread_setspecific(a_name##tsd_tsd,\t\t\t\\\n\t    (void *)wrapper)) {\t\t\t\t\t\t\\\n\t\tmalloc_write(\"<jemalloc>: Error setting\"\t\t\\\n\t\t    \" TSD for \"#a_name\"\\n\");\t\t\t\t\\\n\t\tabort();\t\t\t\t\t\t\\\n\t}\t\t\t\t\t\t\t\t\\\n}\t\t\t\t\t\t\t\t\t\\\na_attr a_name##tsd_wrapper_t *\t\t\t\t\t\t\\\na_name##tsd_wrapper_get(void)\t\t\t\t\t\t\\\n{\t\t\t\t\t\t\t\t\t\\\n\ta_name##tsd_wrapper_t *wrapper = (a_name##tsd_wrapper_t *)\t\\\n\t    pthread_getspecific(a_name##tsd_tsd);\t\t\t\\\n\t\t\t\t\t\t\t\t\t\\\n\tif (unlikely(wrapper == NULL)) {\t\t\t\t\\\n\t\ttsd_init_block_t block;\t\t\t\t\t\\\n\t\twrapper = tsd_init_check_recursion(\t\t\t\\\n\t\t    &a_name##tsd_init_head, &block);\t\t\t\\\n\t\tif (wrapper)\t\t\t\t\t\t\\\n\t\t    return (wrapper);\t\t\t\t\t\\\n\t\twrapper = (a_name##tsd_wrapper_t *)\t\t\t\\\n\t\t    malloc_tsd_malloc(sizeof(a_name##tsd_wrapper_t));\t\\\n\t\tblock.data = wrapper;\t\t\t\t\t\\\n\t\tif (wrapper == NULL) {\t\t\t\t\t\\\n\t\t\tmalloc_write(\"<jemalloc>: Error allocating\"\t\\\n\t\t\t    \" TSD for \"#a_name\"\\n\");\t\t\t\\\n\t\t\tabort();\t\t\t\t\t\\\n\t\t} else {\t\t\t\t\t\t\\\n\t\t\twrapper->initialized = false;\t\t\t\\\n\t\t\twrapper->val = a_initializer;\t\t\t\\\n\t\t}\t\t\t\t\t\t\t\\\n\t\ta_name##tsd_wrapper_set(wrapper);\t\t\t\\\n\t\ttsd_init_finish(&a_name##tsd_init_head, &block);\t\\\n\t}\t\t\t\t\t\t\t\t\\\n\treturn (wrapper);\t\t\t\t\t\t\\\n}\t\t\t\t\t\t\t\t\t\\\na_attr bool\t\t\t\t\t\t\t\t\\\na_name##tsd_boot0(void)\t\t\t\t\t\t\t\\\n{\t\t\t\t\t\t\t\t\t\\\n\t\t\t\t\t\t\t\t\t\\\n\tif (pthread_key_create(&a_name##tsd_tsd,\t\t\t\\\n\t    a_name##tsd_cleanup_wrapper) != 0)\t\t\t\t\\\n\t\treturn (true);\t\t\t\t\t\t\\\n\ta_name##tsd_wrapper_set(&a_name##tsd_boot_wrapper);\t\t\\\n\ta_name##tsd_booted = true;\t\t\t\t\t\\\n\treturn (false);\t\t\t\t\t\t\t\\\n}\t\t\t\t\t\t\t\t\t\\\na_attr void\t\t\t\t\t\t\t\t\\\na_name##tsd_boot1(void)\t\t\t\t\t\t\t\\\n{\t\t\t\t\t\t\t\t\t\\\n\ta_name##tsd_wrapper_t *wrapper;\t\t\t\t\t\\\n\twrapper = (a_name##tsd_wrapper_t *)\t\t\t\t\\\n\t    malloc_tsd_malloc(sizeof(a_name##tsd_wrapper_t));\t\t\\\n\tif (wrapper == NULL) {\t\t\t\t\t\t\\\n\t\tmalloc_write(\"<jemalloc>: Error allocating\"\t\t\\\n\t\t    \" TSD for \"#a_name\"\\n\");\t\t\t\t\\\n\t\tabort();\t\t\t\t\t\t\\\n\t}\t\t\t\t\t\t\t\t\\\n\tmemcpy(wrapper, &a_name##tsd_boot_wrapper,\t\t\t\\\n\t    sizeof(a_name##tsd_wrapper_t));\t\t\t\t\\\n\ta_name##tsd_wrapper_set(wrapper);\t\t\t\t\\\n}\t\t\t\t\t\t\t\t\t\\\na_attr bool\t\t\t\t\t\t\t\t\\\na_name##tsd_boot(void)\t\t\t\t\t\t\t\\\n{\t\t\t\t\t\t\t\t\t\\\n\t\t\t\t\t\t\t\t\t\\\n\tif (a_name##tsd_boot0())\t\t\t\t\t\\\n\t\treturn (true);\t\t\t\t\t\t\\\n\ta_name##tsd_boot1();\t\t\t\t\t\t\\\n\treturn (false);\t\t\t\t\t\t\t\\\n}\t\t\t\t\t\t\t\t\t\\\na_attr bool\t\t\t\t\t\t\t\t\\\na_name##tsd_booted_get(void)\t\t\t\t\t\t\\\n{\t\t\t\t\t\t\t\t\t\\\n\t\t\t\t\t\t\t\t\t\\\n\treturn (a_name##tsd_booted);\t\t\t\t\t\\\n}\t\t\t\t\t\t\t\t\t\\\n/* Get/set. */\t\t\t\t\t\t\t\t\\\na_attr a_type *\t\t\t\t\t\t\t\t\\\na_name##tsd_get(void)\t\t\t\t\t\t\t\\\n{\t\t\t\t\t\t\t\t\t\\\n\ta_name##tsd_wrapper_t *wrapper;\t\t\t\t\t\\\n\t\t\t\t\t\t\t\t\t\\\n\tassert(a_name##tsd_booted);\t\t\t\t\t\\\n\twrapper = a_name##tsd_wrapper_get();\t\t\t\t\\\n\treturn (&wrapper->val);\t\t\t\t\t\t\\\n}\t\t\t\t\t\t\t\t\t\\\na_attr void\t\t\t\t\t\t\t\t\\\na_name##tsd_set(a_type *val)\t\t\t\t\t\t\\\n{\t\t\t\t\t\t\t\t\t\\\n\ta_name##tsd_wrapper_t *wrapper;\t\t\t\t\t\\\n\t\t\t\t\t\t\t\t\t\\\n\tassert(a_name##tsd_booted);\t\t\t\t\t\\\n\twrapper = a_name##tsd_wrapper_get();\t\t\t\t\\\n\twrapper->val = *(val);\t\t\t\t\t\t\\\n\tif (a_cleanup != malloc_tsd_no_cleanup)\t\t\t\t\\\n\t\twrapper->initialized = true;\t\t\t\t\\\n}\n#endif\n\n#endif /* JEMALLOC_H_TYPES */\n/******************************************************************************/\n#ifdef JEMALLOC_H_STRUCTS\n\n#if (!defined(JEMALLOC_MALLOC_THREAD_CLEANUP) && !defined(JEMALLOC_TLS) && \\\n    !defined(_WIN32))\nstruct tsd_init_block_s {\n\tql_elm(tsd_init_block_t)\tlink;\n\tpthread_t\t\t\tthread;\n\tvoid\t\t\t\t*data;\n};\nstruct tsd_init_head_s {\n\tql_head(tsd_init_block_t)\tblocks;\n\tmalloc_mutex_t\t\t\tlock;\n};\n#endif\n\n#define\tMALLOC_TSD\t\t\t\t\t\t\t\\\n/*  O(name,\t\t\ttype) */\t\t\t\t\\\n    O(tcache,\t\t\ttcache_t *)\t\t\t\t\\\n    O(thread_allocated,\t\tuint64_t)\t\t\t\t\\\n    O(thread_deallocated,\tuint64_t)\t\t\t\t\\\n    O(prof_tdata,\t\tprof_tdata_t *)\t\t\t\t\\\n    O(iarena,\t\t\tarena_t *)\t\t\t\t\\\n    O(arena,\t\t\tarena_t *)\t\t\t\t\\\n    O(arenas_tdata,\t\tarena_tdata_t *)\t\t\t\\\n    O(narenas_tdata,\t\tunsigned)\t\t\t\t\\\n    O(arenas_tdata_bypass,\tbool)\t\t\t\t\t\\\n    O(tcache_enabled,\t\ttcache_enabled_t)\t\t\t\\\n    O(quarantine,\t\tquarantine_t *)\t\t\t\t\\\n    O(witnesses,\t\twitness_list_t)\t\t\t\t\\\n    O(witness_fork,\t\tbool)\t\t\t\t\t\\\n\n#define\tTSD_INITIALIZER {\t\t\t\t\t\t\\\n    tsd_state_uninitialized,\t\t\t\t\t\t\\\n    NULL,\t\t\t\t\t\t\t\t\\\n    0,\t\t\t\t\t\t\t\t\t\\\n    0,\t\t\t\t\t\t\t\t\t\\\n    NULL,\t\t\t\t\t\t\t\t\\\n    NULL,\t\t\t\t\t\t\t\t\\\n    NULL,\t\t\t\t\t\t\t\t\\\n    NULL,\t\t\t\t\t\t\t\t\\\n    0,\t\t\t\t\t\t\t\t\t\\\n    false,\t\t\t\t\t\t\t\t\\\n    tcache_enabled_default,\t\t\t\t\t\t\\\n    NULL,\t\t\t\t\t\t\t\t\\\n    ql_head_initializer(witnesses),\t\t\t\t\t\\\n    false\t\t\t\t\t\t\t\t\\\n}\n\nstruct tsd_s {\n\ttsd_state_t\tstate;\n#define\tO(n, t)\t\t\t\t\t\t\t\t\\\n\tt\t\tn;\nMALLOC_TSD\n#undef O\n};\n\n/*\n * Wrapper around tsd_t that makes it possible to avoid implicit conversion\n * between tsd_t and tsdn_t, where tsdn_t is \"nullable\" and has to be\n * explicitly converted to tsd_t, which is non-nullable.\n */\nstruct tsdn_s {\n\ttsd_t\ttsd;\n};\n\nstatic const tsd_t tsd_initializer = TSD_INITIALIZER;\n\nmalloc_tsd_types(, tsd_t)\n\n#endif /* JEMALLOC_H_STRUCTS */\n/******************************************************************************/\n#ifdef JEMALLOC_H_EXTERNS\n\nvoid\t*malloc_tsd_malloc(size_t size);\nvoid\tmalloc_tsd_dalloc(void *wrapper);\nvoid\tmalloc_tsd_no_cleanup(void *arg);\nvoid\tmalloc_tsd_cleanup_register(bool (*f)(void));\ntsd_t\t*malloc_tsd_boot0(void);\nvoid\tmalloc_tsd_boot1(void);\n#if (!defined(JEMALLOC_MALLOC_THREAD_CLEANUP) && !defined(JEMALLOC_TLS) && \\\n    !defined(_WIN32))\nvoid\t*tsd_init_check_recursion(tsd_init_head_t *head,\n    tsd_init_block_t *block);\nvoid\ttsd_init_finish(tsd_init_head_t *head, tsd_init_block_t *block);\n#endif\nvoid\ttsd_cleanup(void *arg);\n\n#endif /* JEMALLOC_H_EXTERNS */\n/******************************************************************************/\n#ifdef JEMALLOC_H_INLINES\n\n#ifndef JEMALLOC_ENABLE_INLINE\nmalloc_tsd_protos(JEMALLOC_ATTR(unused), , tsd_t)\n\ntsd_t\t*tsd_fetch(void);\ntsdn_t\t*tsd_tsdn(tsd_t *tsd);\nbool\ttsd_nominal(tsd_t *tsd);\n#define\tO(n, t)\t\t\t\t\t\t\t\t\\\nt\t*tsd_##n##p_get(tsd_t *tsd);\t\t\t\t\t\\\nt\ttsd_##n##_get(tsd_t *tsd);\t\t\t\t\t\\\nvoid\ttsd_##n##_set(tsd_t *tsd, t n);\nMALLOC_TSD\n#undef O\ntsdn_t\t*tsdn_fetch(void);\nbool\ttsdn_null(const tsdn_t *tsdn);\ntsd_t\t*tsdn_tsd(tsdn_t *tsdn);\n#endif\n\n#if (defined(JEMALLOC_ENABLE_INLINE) || defined(JEMALLOC_TSD_C_))\nmalloc_tsd_externs(, tsd_t)\nmalloc_tsd_funcs(JEMALLOC_ALWAYS_INLINE, , tsd_t, tsd_initializer, tsd_cleanup)\n\nJEMALLOC_ALWAYS_INLINE tsd_t *\ntsd_fetch(void)\n{\n\ttsd_t *tsd = tsd_get();\n\n\tif (unlikely(tsd->state != tsd_state_nominal)) {\n\t\tif (tsd->state == tsd_state_uninitialized) {\n\t\t\ttsd->state = tsd_state_nominal;\n\t\t\t/* Trigger cleanup handler registration. */\n\t\t\ttsd_set(tsd);\n\t\t} else if (tsd->state == tsd_state_purgatory) {\n\t\t\ttsd->state = tsd_state_reincarnated;\n\t\t\ttsd_set(tsd);\n\t\t} else\n\t\t\tassert(tsd->state == tsd_state_reincarnated);\n\t}\n\n\treturn (tsd);\n}\n\nJEMALLOC_ALWAYS_INLINE tsdn_t *\ntsd_tsdn(tsd_t *tsd)\n{\n\n\treturn ((tsdn_t *)tsd);\n}\n\nJEMALLOC_INLINE bool\ntsd_nominal(tsd_t *tsd)\n{\n\n\treturn (tsd->state == tsd_state_nominal);\n}\n\n#define\tO(n, t)\t\t\t\t\t\t\t\t\\\nJEMALLOC_ALWAYS_INLINE t *\t\t\t\t\t\t\\\ntsd_##n##p_get(tsd_t *tsd)\t\t\t\t\t\t\\\n{\t\t\t\t\t\t\t\t\t\\\n\t\t\t\t\t\t\t\t\t\\\n\treturn (&tsd->n);\t\t\t\t\t\t\\\n}\t\t\t\t\t\t\t\t\t\\\n\t\t\t\t\t\t\t\t\t\\\nJEMALLOC_ALWAYS_INLINE t\t\t\t\t\t\t\\\ntsd_##n##_get(tsd_t *tsd)\t\t\t\t\t\t\\\n{\t\t\t\t\t\t\t\t\t\\\n\t\t\t\t\t\t\t\t\t\\\n\treturn (*tsd_##n##p_get(tsd));\t\t\t\t\t\\\n}\t\t\t\t\t\t\t\t\t\\\n\t\t\t\t\t\t\t\t\t\\\nJEMALLOC_ALWAYS_INLINE void\t\t\t\t\t\t\\\ntsd_##n##_set(tsd_t *tsd, t n)\t\t\t\t\t\t\\\n{\t\t\t\t\t\t\t\t\t\\\n\t\t\t\t\t\t\t\t\t\\\n\tassert(tsd->state == tsd_state_nominal);\t\t\t\\\n\ttsd->n = n;\t\t\t\t\t\t\t\\\n}\nMALLOC_TSD\n#undef O\n\nJEMALLOC_ALWAYS_INLINE tsdn_t *\ntsdn_fetch(void)\n{\n\n\tif (!tsd_booted_get())\n\t\treturn (NULL);\n\n\treturn (tsd_tsdn(tsd_fetch()));\n}\n\nJEMALLOC_ALWAYS_INLINE bool\ntsdn_null(const tsdn_t *tsdn)\n{\n\n\treturn (tsdn == NULL);\n}\n\nJEMALLOC_ALWAYS_INLINE tsd_t *\ntsdn_tsd(tsdn_t *tsdn)\n{\n\n\tassert(!tsdn_null(tsdn));\n\n\treturn (&tsdn->tsd);\n}\n#endif\n\n#endif /* JEMALLOC_H_INLINES */\n/******************************************************************************/\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/deps/jemalloc/include/jemalloc/internal/util.h",
    "content": "/******************************************************************************/\n#ifdef JEMALLOC_H_TYPES\n\n#ifdef _WIN32\n#  ifdef _WIN64\n#    define FMT64_PREFIX \"ll\"\n#    define FMTPTR_PREFIX \"ll\"\n#  else\n#    define FMT64_PREFIX \"ll\"\n#    define FMTPTR_PREFIX \"\"\n#  endif\n#  define FMTd32 \"d\"\n#  define FMTu32 \"u\"\n#  define FMTx32 \"x\"\n#  define FMTd64 FMT64_PREFIX \"d\"\n#  define FMTu64 FMT64_PREFIX \"u\"\n#  define FMTx64 FMT64_PREFIX \"x\"\n#  define FMTdPTR FMTPTR_PREFIX \"d\"\n#  define FMTuPTR FMTPTR_PREFIX \"u\"\n#  define FMTxPTR FMTPTR_PREFIX \"x\"\n#else\n#  include <inttypes.h>\n#  define FMTd32 PRId32\n#  define FMTu32 PRIu32\n#  define FMTx32 PRIx32\n#  define FMTd64 PRId64\n#  define FMTu64 PRIu64\n#  define FMTx64 PRIx64\n#  define FMTdPTR PRIdPTR\n#  define FMTuPTR PRIuPTR\n#  define FMTxPTR PRIxPTR\n#endif\n\n/* Size of stack-allocated buffer passed to buferror(). */\n#define\tBUFERROR_BUF\t\t64\n\n/*\n * Size of stack-allocated buffer used by malloc_{,v,vc}printf().  This must be\n * large enough for all possible uses within jemalloc.\n */\n#define\tMALLOC_PRINTF_BUFSIZE\t4096\n\n/* Junk fill patterns. */\n#define\tJEMALLOC_ALLOC_JUNK\t((uint8_t)0xa5)\n#define\tJEMALLOC_FREE_JUNK\t((uint8_t)0x5a)\n\n/*\n * Wrap a cpp argument that contains commas such that it isn't broken up into\n * multiple arguments.\n */\n#define\tJEMALLOC_ARG_CONCAT(...) __VA_ARGS__\n\n/*\n * Silence compiler warnings due to uninitialized values.  This is used\n * wherever the compiler fails to recognize that the variable is never used\n * uninitialized.\n */\n#ifdef JEMALLOC_CC_SILENCE\n#\tdefine JEMALLOC_CC_SILENCE_INIT(v) = v\n#else\n#\tdefine JEMALLOC_CC_SILENCE_INIT(v)\n#endif\n\n#define\tJEMALLOC_GNUC_PREREQ(major, minor)\t\t\t\t\\\n    (!defined(__clang__) &&\t\t\t\t\t\t\\\n    (__GNUC__ > (major) || (__GNUC__ == (major) && __GNUC_MINOR__ >= (minor))))\n#ifndef __has_builtin\n#  define __has_builtin(builtin) (0)\n#endif\n#define\tJEMALLOC_CLANG_HAS_BUILTIN(builtin)\t\t\t\t\\\n    (defined(__clang__) && __has_builtin(builtin))\n\n#ifdef __GNUC__\n#\tdefine likely(x)   __builtin_expect(!!(x), 1)\n#\tdefine unlikely(x) __builtin_expect(!!(x), 0)\n#  if JEMALLOC_GNUC_PREREQ(4, 6) ||\t\t\t\t\t\\\n      JEMALLOC_CLANG_HAS_BUILTIN(__builtin_unreachable)\n#\tdefine unreachable() __builtin_unreachable()\n#  else\n#\tdefine unreachable() abort()\n#  endif\n#else\n#\tdefine likely(x)   !!(x)\n#\tdefine unlikely(x) !!(x)\n#\tdefine unreachable() abort()\n#endif\n\n#include \"jemalloc/internal/assert.h\"\n\n/* Use to assert a particular configuration, e.g., cassert(config_debug). */\n#define\tcassert(c) do {\t\t\t\t\t\t\t\\\n\tif (unlikely(!(c)))\t\t\t\t\t\t\\\n\t\tnot_reached();\t\t\t\t\t\t\\\n} while (0)\n\n#endif /* JEMALLOC_H_TYPES */\n/******************************************************************************/\n#ifdef JEMALLOC_H_STRUCTS\n\n#endif /* JEMALLOC_H_STRUCTS */\n/******************************************************************************/\n#ifdef JEMALLOC_H_EXTERNS\n\nint\tbuferror(int err, char *buf, size_t buflen);\nuintmax_t\tmalloc_strtoumax(const char *restrict nptr,\n    char **restrict endptr, int base);\nvoid\tmalloc_write(const char *s);\n\n/*\n * malloc_vsnprintf() supports a subset of snprintf(3) that avoids floating\n * point math.\n */\nsize_t\tmalloc_vsnprintf(char *str, size_t size, const char *format,\n    va_list ap);\nsize_t\tmalloc_snprintf(char *str, size_t size, const char *format, ...)\n    JEMALLOC_FORMAT_PRINTF(3, 4);\nvoid\tmalloc_vcprintf(void (*write_cb)(void *, const char *), void *cbopaque,\n    const char *format, va_list ap);\nvoid malloc_cprintf(void (*write)(void *, const char *), void *cbopaque,\n    const char *format, ...) JEMALLOC_FORMAT_PRINTF(3, 4);\nvoid\tmalloc_printf(const char *format, ...) JEMALLOC_FORMAT_PRINTF(1, 2);\n\n#endif /* JEMALLOC_H_EXTERNS */\n/******************************************************************************/\n#ifdef JEMALLOC_H_INLINES\n\n#ifndef JEMALLOC_ENABLE_INLINE\nunsigned\tffs_llu(unsigned long long bitmap);\nunsigned\tffs_lu(unsigned long bitmap);\nunsigned\tffs_u(unsigned bitmap);\nunsigned\tffs_zu(size_t bitmap);\nunsigned\tffs_u64(uint64_t bitmap);\nunsigned\tffs_u32(uint32_t bitmap);\nuint64_t\tpow2_ceil_u64(uint64_t x);\nuint32_t\tpow2_ceil_u32(uint32_t x);\nsize_t\tpow2_ceil_zu(size_t x);\nunsigned\tlg_floor(size_t x);\nvoid\tset_errno(int errnum);\nint\tget_errno(void);\n#endif\n\n#if (defined(JEMALLOC_ENABLE_INLINE) || defined(JEMALLOC_UTIL_C_))\n\n/* Sanity check. */\n#if !defined(JEMALLOC_INTERNAL_FFSLL) || !defined(JEMALLOC_INTERNAL_FFSL) \\\n    || !defined(JEMALLOC_INTERNAL_FFS)\n#  error JEMALLOC_INTERNAL_FFS{,L,LL} should have been defined by configure\n#endif\n\nJEMALLOC_ALWAYS_INLINE unsigned\nffs_llu(unsigned long long bitmap)\n{\n\n\treturn (JEMALLOC_INTERNAL_FFSLL(bitmap));\n}\n\nJEMALLOC_ALWAYS_INLINE unsigned\nffs_lu(unsigned long bitmap)\n{\n\n\treturn (JEMALLOC_INTERNAL_FFSL(bitmap));\n}\n\nJEMALLOC_ALWAYS_INLINE unsigned\nffs_u(unsigned bitmap)\n{\n\n\treturn (JEMALLOC_INTERNAL_FFS(bitmap));\n}\n\nJEMALLOC_ALWAYS_INLINE unsigned\nffs_zu(size_t bitmap)\n{\n\n#if LG_SIZEOF_PTR == LG_SIZEOF_INT\n\treturn (ffs_u(bitmap));\n#elif LG_SIZEOF_PTR == LG_SIZEOF_LONG\n\treturn (ffs_lu(bitmap));\n#elif LG_SIZEOF_PTR == LG_SIZEOF_LONG_LONG\n\treturn (ffs_llu(bitmap));\n#else\n#error No implementation for size_t ffs()\n#endif\n}\n\nJEMALLOC_ALWAYS_INLINE unsigned\nffs_u64(uint64_t bitmap)\n{\n\n#if LG_SIZEOF_LONG == 3\n\treturn (ffs_lu(bitmap));\n#elif LG_SIZEOF_LONG_LONG == 3\n\treturn (ffs_llu(bitmap));\n#else\n#error No implementation for 64-bit ffs()\n#endif\n}\n\nJEMALLOC_ALWAYS_INLINE unsigned\nffs_u32(uint32_t bitmap)\n{\n\n#if LG_SIZEOF_INT == 2\n\treturn (ffs_u(bitmap));\n#else\n#error No implementation for 32-bit ffs()\n#endif\n\treturn (ffs_u(bitmap));\n}\n\nJEMALLOC_INLINE uint64_t\npow2_ceil_u64(uint64_t x)\n{\n\n\tx--;\n\tx |= x >> 1;\n\tx |= x >> 2;\n\tx |= x >> 4;\n\tx |= x >> 8;\n\tx |= x >> 16;\n\tx |= x >> 32;\n\tx++;\n\treturn (x);\n}\n\nJEMALLOC_INLINE uint32_t\npow2_ceil_u32(uint32_t x)\n{\n\n\tx--;\n\tx |= x >> 1;\n\tx |= x >> 2;\n\tx |= x >> 4;\n\tx |= x >> 8;\n\tx |= x >> 16;\n\tx++;\n\treturn (x);\n}\n\n/* Compute the smallest power of 2 that is >= x. */\nJEMALLOC_INLINE size_t\npow2_ceil_zu(size_t x)\n{\n\n#if (LG_SIZEOF_PTR == 3)\n\treturn (pow2_ceil_u64(x));\n#else\n\treturn (pow2_ceil_u32(x));\n#endif\n}\n\n#if (defined(__i386__) || defined(__amd64__) || defined(__x86_64__))\nJEMALLOC_INLINE unsigned\nlg_floor(size_t x)\n{\n\tsize_t ret;\n\n\tassert(x != 0);\n\n\tasm (\"bsr %1, %0\"\n\t    : \"=r\"(ret) // Outputs.\n\t    : \"r\"(x)    // Inputs.\n\t    );\n\tassert(ret < UINT_MAX);\n\treturn ((unsigned)ret);\n}\n#elif (defined(_MSC_VER))\nJEMALLOC_INLINE unsigned\nlg_floor(size_t x)\n{\n\tunsigned long ret;\n\n\tassert(x != 0);\n\n#if (LG_SIZEOF_PTR == 3)\n\t_BitScanReverse64(&ret, x);\n#elif (LG_SIZEOF_PTR == 2)\n\t_BitScanReverse(&ret, x);\n#else\n#  error \"Unsupported type size for lg_floor()\"\n#endif\n\tassert(ret < UINT_MAX);\n\treturn ((unsigned)ret);\n}\n#elif (defined(JEMALLOC_HAVE_BUILTIN_CLZ))\nJEMALLOC_INLINE unsigned\nlg_floor(size_t x)\n{\n\n\tassert(x != 0);\n\n#if (LG_SIZEOF_PTR == LG_SIZEOF_INT)\n\treturn (((8 << LG_SIZEOF_PTR) - 1) - __builtin_clz(x));\n#elif (LG_SIZEOF_PTR == LG_SIZEOF_LONG)\n\treturn (((8 << LG_SIZEOF_PTR) - 1) - __builtin_clzl(x));\n#else\n#  error \"Unsupported type size for lg_floor()\"\n#endif\n}\n#else\nJEMALLOC_INLINE unsigned\nlg_floor(size_t x)\n{\n\n\tassert(x != 0);\n\n\tx |= (x >> 1);\n\tx |= (x >> 2);\n\tx |= (x >> 4);\n\tx |= (x >> 8);\n\tx |= (x >> 16);\n#if (LG_SIZEOF_PTR == 3)\n\tx |= (x >> 32);\n#endif\n\tif (x == SIZE_T_MAX)\n\t\treturn ((8 << LG_SIZEOF_PTR) - 1);\n\tx++;\n\treturn (ffs_zu(x) - 2);\n}\n#endif\n\n/* Set error code. */\nJEMALLOC_INLINE void\nset_errno(int errnum)\n{\n\n#ifdef _WIN32\n\tSetLastError(errnum);\n#else\n\terrno = errnum;\n#endif\n}\n\n/* Get last error code. */\nJEMALLOC_INLINE int\nget_errno(void)\n{\n\n#ifdef _WIN32\n\treturn (GetLastError());\n#else\n\treturn (errno);\n#endif\n}\n#endif\n\n#endif /* JEMALLOC_H_INLINES */\n/******************************************************************************/\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/deps/jemalloc/include/jemalloc/internal/valgrind.h",
    "content": "/******************************************************************************/\n#ifdef JEMALLOC_H_TYPES\n\n#ifdef JEMALLOC_VALGRIND\n#include <valgrind/valgrind.h>\n\n/*\n * The size that is reported to Valgrind must be consistent through a chain of\n * malloc..realloc..realloc calls.  Request size isn't recorded anywhere in\n * jemalloc, so it is critical that all callers of these macros provide usize\n * rather than request size.  As a result, buffer overflow detection is\n * technically weakened for the standard API, though it is generally accepted\n * practice to consider any extra bytes reported by malloc_usable_size() as\n * usable space.\n */\n#define\tJEMALLOC_VALGRIND_MAKE_MEM_NOACCESS(ptr, usize) do {\t\t\\\n\tif (unlikely(in_valgrind))\t\t\t\t\t\\\n\t\tvalgrind_make_mem_noaccess(ptr, usize);\t\t\t\\\n} while (0)\n#define\tJEMALLOC_VALGRIND_MAKE_MEM_UNDEFINED(ptr, usize) do {\t\t\\\n\tif (unlikely(in_valgrind))\t\t\t\t\t\\\n\t\tvalgrind_make_mem_undefined(ptr, usize);\t\t\\\n} while (0)\n#define\tJEMALLOC_VALGRIND_MAKE_MEM_DEFINED(ptr, usize) do {\t\t\\\n\tif (unlikely(in_valgrind))\t\t\t\t\t\\\n\t\tvalgrind_make_mem_defined(ptr, usize);\t\t\t\\\n} while (0)\n/*\n * The VALGRIND_MALLOCLIKE_BLOCK() and VALGRIND_RESIZEINPLACE_BLOCK() macro\n * calls must be embedded in macros rather than in functions so that when\n * Valgrind reports errors, there are no extra stack frames in the backtraces.\n */\n#define\tJEMALLOC_VALGRIND_MALLOC(cond, tsdn, ptr, usize, zero) do {\t\\\n\tif (unlikely(in_valgrind && cond)) {\t\t\t\t\\\n\t\tVALGRIND_MALLOCLIKE_BLOCK(ptr, usize, p2rz(tsdn, ptr),\t\\\n\t\t    zero);\t\t\t\t\t\t\\\n\t}\t\t\t\t\t\t\t\t\\\n} while (0)\n#define\tJEMALLOC_VALGRIND_REALLOC(maybe_moved, tsdn, ptr, usize,\t\\\n    ptr_maybe_null, old_ptr, old_usize, old_rzsize, old_ptr_maybe_null,\t\\\n    zero) do {\t\t\t\t\t\t\t\t\\\n\tif (unlikely(in_valgrind)) {\t\t\t\t\t\\\n\t\tsize_t rzsize = p2rz(tsdn, ptr);\t\t\t\\\n\t\t\t\t\t\t\t\t\t\\\n\t\tif (!maybe_moved || ptr == old_ptr) {\t\t\t\\\n\t\t\tVALGRIND_RESIZEINPLACE_BLOCK(ptr, old_usize,\t\\\n\t\t\t    usize, rzsize);\t\t\t\t\\\n\t\t\tif (zero && old_usize < usize) {\t\t\\\n\t\t\t\tvalgrind_make_mem_defined(\t\t\\\n\t\t\t\t    (void *)((uintptr_t)ptr +\t\t\\\n\t\t\t\t    old_usize), usize - old_usize);\t\\\n\t\t\t}\t\t\t\t\t\t\\\n\t\t} else {\t\t\t\t\t\t\\\n\t\t\tif (!old_ptr_maybe_null || old_ptr != NULL) {\t\\\n\t\t\t\tvalgrind_freelike_block(old_ptr,\t\\\n\t\t\t\t    old_rzsize);\t\t\t\\\n\t\t\t}\t\t\t\t\t\t\\\n\t\t\tif (!ptr_maybe_null || ptr != NULL) {\t\t\\\n\t\t\t\tsize_t copy_size = (old_usize < usize)\t\\\n\t\t\t\t    ?  old_usize : usize;\t\t\\\n\t\t\t\tsize_t tail_size = usize - copy_size;\t\\\n\t\t\t\tVALGRIND_MALLOCLIKE_BLOCK(ptr, usize,\t\\\n\t\t\t\t    rzsize, false);\t\t\t\\\n\t\t\t\tif (copy_size > 0) {\t\t\t\\\n\t\t\t\t\tvalgrind_make_mem_defined(ptr,\t\\\n\t\t\t\t\tcopy_size);\t\t\t\\\n\t\t\t\t}\t\t\t\t\t\\\n\t\t\t\tif (zero && tail_size > 0) {\t\t\\\n\t\t\t\t\tvalgrind_make_mem_defined(\t\\\n\t\t\t\t\t    (void *)((uintptr_t)ptr +\t\\\n\t\t\t\t\t    copy_size), tail_size);\t\\\n\t\t\t\t}\t\t\t\t\t\\\n\t\t\t}\t\t\t\t\t\t\\\n\t\t}\t\t\t\t\t\t\t\\\n\t}\t\t\t\t\t\t\t\t\\\n} while (0)\n#define\tJEMALLOC_VALGRIND_FREE(ptr, rzsize) do {\t\t\t\\\n\tif (unlikely(in_valgrind))\t\t\t\t\t\\\n\t\tvalgrind_freelike_block(ptr, rzsize);\t\t\t\\\n} while (0)\n#else\n#define\tRUNNING_ON_VALGRIND\t((unsigned)0)\n#define\tJEMALLOC_VALGRIND_MAKE_MEM_NOACCESS(ptr, usize) do {} while (0)\n#define\tJEMALLOC_VALGRIND_MAKE_MEM_UNDEFINED(ptr, usize) do {} while (0)\n#define\tJEMALLOC_VALGRIND_MAKE_MEM_DEFINED(ptr, usize) do {} while (0)\n#define\tJEMALLOC_VALGRIND_MALLOC(cond, tsdn, ptr, usize, zero) do {} while (0)\n#define\tJEMALLOC_VALGRIND_REALLOC(maybe_moved, tsdn, ptr, usize,\t\\\n    ptr_maybe_null, old_ptr, old_usize, old_rzsize, old_ptr_maybe_null,\t\\\n    zero) do {} while (0)\n#define\tJEMALLOC_VALGRIND_FREE(ptr, rzsize) do {} while (0)\n#endif\n\n#endif /* JEMALLOC_H_TYPES */\n/******************************************************************************/\n#ifdef JEMALLOC_H_STRUCTS\n\n#endif /* JEMALLOC_H_STRUCTS */\n/******************************************************************************/\n#ifdef JEMALLOC_H_EXTERNS\n\n#ifdef JEMALLOC_VALGRIND\nvoid\tvalgrind_make_mem_noaccess(void *ptr, size_t usize);\nvoid\tvalgrind_make_mem_undefined(void *ptr, size_t usize);\nvoid\tvalgrind_make_mem_defined(void *ptr, size_t usize);\nvoid\tvalgrind_freelike_block(void *ptr, size_t usize);\n#endif\n\n#endif /* JEMALLOC_H_EXTERNS */\n/******************************************************************************/\n#ifdef JEMALLOC_H_INLINES\n\n#endif /* JEMALLOC_H_INLINES */\n/******************************************************************************/\n\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/deps/jemalloc/include/jemalloc/internal/witness.h",
    "content": "/******************************************************************************/\n#ifdef JEMALLOC_H_TYPES\n\ntypedef struct witness_s witness_t;\ntypedef unsigned witness_rank_t;\ntypedef ql_head(witness_t) witness_list_t;\ntypedef int witness_comp_t (const witness_t *, const witness_t *);\n\n/*\n * Lock ranks.  Witnesses with rank WITNESS_RANK_OMIT are completely ignored by\n * the witness machinery.\n */\n#define\tWITNESS_RANK_OMIT\t\t0U\n\n#define\tWITNESS_RANK_INIT\t\t1U\n#define\tWITNESS_RANK_CTL\t\t1U\n#define\tWITNESS_RANK_ARENAS\t\t2U\n\n#define\tWITNESS_RANK_PROF_DUMP\t\t3U\n#define\tWITNESS_RANK_PROF_BT2GCTX\t4U\n#define\tWITNESS_RANK_PROF_TDATAS\t5U\n#define\tWITNESS_RANK_PROF_TDATA\t\t6U\n#define\tWITNESS_RANK_PROF_GCTX\t\t7U\n\n#define\tWITNESS_RANK_ARENA\t\t8U\n#define\tWITNESS_RANK_ARENA_CHUNKS\t9U\n#define\tWITNESS_RANK_ARENA_NODE_CACHE\t10\n\n#define\tWITNESS_RANK_BASE\t\t11U\n\n#define\tWITNESS_RANK_LEAF\t\t0xffffffffU\n#define\tWITNESS_RANK_ARENA_BIN\t\tWITNESS_RANK_LEAF\n#define\tWITNESS_RANK_ARENA_HUGE\t\tWITNESS_RANK_LEAF\n#define\tWITNESS_RANK_DSS\t\tWITNESS_RANK_LEAF\n#define\tWITNESS_RANK_PROF_ACTIVE\tWITNESS_RANK_LEAF\n#define\tWITNESS_RANK_PROF_DUMP_SEQ\tWITNESS_RANK_LEAF\n#define\tWITNESS_RANK_PROF_GDUMP\t\tWITNESS_RANK_LEAF\n#define\tWITNESS_RANK_PROF_NEXT_THR_UID\tWITNESS_RANK_LEAF\n#define\tWITNESS_RANK_PROF_THREAD_ACTIVE_INIT\tWITNESS_RANK_LEAF\n\n#define\tWITNESS_INITIALIZER(rank) {\"initializer\", rank, NULL, {NULL, NULL}}\n\n#endif /* JEMALLOC_H_TYPES */\n/******************************************************************************/\n#ifdef JEMALLOC_H_STRUCTS\n\nstruct witness_s {\n\t/* Name, used for printing lock order reversal messages. */\n\tconst char\t\t*name;\n\n\t/*\n\t * Witness rank, where 0 is lowest and UINT_MAX is highest.  Witnesses\n\t * must be acquired in order of increasing rank.\n\t */\n\twitness_rank_t\t\trank;\n\n\t/*\n\t * If two witnesses are of equal rank and they have the samp comp\n\t * function pointer, it is called as a last attempt to differentiate\n\t * between witnesses of equal rank.\n\t */\n\twitness_comp_t\t\t*comp;\n\n\t/* Linkage for thread's currently owned locks. */\n\tql_elm(witness_t)\tlink;\n};\n\n#endif /* JEMALLOC_H_STRUCTS */\n/******************************************************************************/\n#ifdef JEMALLOC_H_EXTERNS\n\nvoid\twitness_init(witness_t *witness, const char *name, witness_rank_t rank,\n    witness_comp_t *comp);\n#ifdef JEMALLOC_JET\ntypedef void (witness_lock_error_t)(const witness_list_t *, const witness_t *);\nextern witness_lock_error_t *witness_lock_error;\n#else\nvoid\twitness_lock_error(const witness_list_t *witnesses,\n    const witness_t *witness);\n#endif\n#ifdef JEMALLOC_JET\ntypedef void (witness_owner_error_t)(const witness_t *);\nextern witness_owner_error_t *witness_owner_error;\n#else\nvoid\twitness_owner_error(const witness_t *witness);\n#endif\n#ifdef JEMALLOC_JET\ntypedef void (witness_not_owner_error_t)(const witness_t *);\nextern witness_not_owner_error_t *witness_not_owner_error;\n#else\nvoid\twitness_not_owner_error(const witness_t *witness);\n#endif\n#ifdef JEMALLOC_JET\ntypedef void (witness_lockless_error_t)(const witness_list_t *);\nextern witness_lockless_error_t *witness_lockless_error;\n#else\nvoid\twitness_lockless_error(const witness_list_t *witnesses);\n#endif\n\nvoid\twitnesses_cleanup(tsd_t *tsd);\nvoid\twitness_fork_cleanup(tsd_t *tsd);\nvoid\twitness_prefork(tsd_t *tsd);\nvoid\twitness_postfork_parent(tsd_t *tsd);\nvoid\twitness_postfork_child(tsd_t *tsd);\n\n#endif /* JEMALLOC_H_EXTERNS */\n/******************************************************************************/\n#ifdef JEMALLOC_H_INLINES\n\n#ifndef JEMALLOC_ENABLE_INLINE\nvoid\twitness_assert_owner(tsdn_t *tsdn, const witness_t *witness);\nvoid\twitness_assert_not_owner(tsdn_t *tsdn, const witness_t *witness);\nvoid\twitness_assert_lockless(tsdn_t *tsdn);\nvoid\twitness_lock(tsdn_t *tsdn, witness_t *witness);\nvoid\twitness_unlock(tsdn_t *tsdn, witness_t *witness);\n#endif\n\n#if (defined(JEMALLOC_ENABLE_INLINE) || defined(JEMALLOC_MUTEX_C_))\nJEMALLOC_INLINE void\nwitness_assert_owner(tsdn_t *tsdn, const witness_t *witness)\n{\n\ttsd_t *tsd;\n\twitness_list_t *witnesses;\n\twitness_t *w;\n\n\tif (!config_debug)\n\t\treturn;\n\n\tif (tsdn_null(tsdn))\n\t\treturn;\n\ttsd = tsdn_tsd(tsdn);\n\tif (witness->rank == WITNESS_RANK_OMIT)\n\t\treturn;\n\n\twitnesses = tsd_witnessesp_get(tsd);\n\tql_foreach(w, witnesses, link) {\n\t\tif (w == witness)\n\t\t\treturn;\n\t}\n\twitness_owner_error(witness);\n}\n\nJEMALLOC_INLINE void\nwitness_assert_not_owner(tsdn_t *tsdn, const witness_t *witness)\n{\n\ttsd_t *tsd;\n\twitness_list_t *witnesses;\n\twitness_t *w;\n\n\tif (!config_debug)\n\t\treturn;\n\n\tif (tsdn_null(tsdn))\n\t\treturn;\n\ttsd = tsdn_tsd(tsdn);\n\tif (witness->rank == WITNESS_RANK_OMIT)\n\t\treturn;\n\n\twitnesses = tsd_witnessesp_get(tsd);\n\tql_foreach(w, witnesses, link) {\n\t\tif (w == witness)\n\t\t\twitness_not_owner_error(witness);\n\t}\n}\n\nJEMALLOC_INLINE void\nwitness_assert_lockless(tsdn_t *tsdn)\n{\n\ttsd_t *tsd;\n\twitness_list_t *witnesses;\n\twitness_t *w;\n\n\tif (!config_debug)\n\t\treturn;\n\n\tif (tsdn_null(tsdn))\n\t\treturn;\n\ttsd = tsdn_tsd(tsdn);\n\n\twitnesses = tsd_witnessesp_get(tsd);\n\tw = ql_last(witnesses, link);\n\tif (w != NULL)\n\t\twitness_lockless_error(witnesses);\n}\n\nJEMALLOC_INLINE void\nwitness_lock(tsdn_t *tsdn, witness_t *witness)\n{\n\ttsd_t *tsd;\n\twitness_list_t *witnesses;\n\twitness_t *w;\n\n\tif (!config_debug)\n\t\treturn;\n\n\tif (tsdn_null(tsdn))\n\t\treturn;\n\ttsd = tsdn_tsd(tsdn);\n\tif (witness->rank == WITNESS_RANK_OMIT)\n\t\treturn;\n\n\twitness_assert_not_owner(tsdn, witness);\n\n\twitnesses = tsd_witnessesp_get(tsd);\n\tw = ql_last(witnesses, link);\n\tif (w == NULL) {\n\t\t/* No other locks; do nothing. */\n\t} else if (tsd_witness_fork_get(tsd) && w->rank <= witness->rank) {\n\t\t/* Forking, and relaxed ranking satisfied. */\n\t} else if (w->rank > witness->rank) {\n\t\t/* Not forking, rank order reversal. */\n\t\twitness_lock_error(witnesses, witness);\n\t} else if (w->rank == witness->rank && (w->comp == NULL || w->comp !=\n\t    witness->comp || w->comp(w, witness) > 0)) {\n\t\t/*\n\t\t * Missing/incompatible comparison function, or comparison\n\t\t * function indicates rank order reversal.\n\t\t */\n\t\twitness_lock_error(witnesses, witness);\n\t}\n\n\tql_elm_new(witness, link);\n\tql_tail_insert(witnesses, witness, link);\n}\n\nJEMALLOC_INLINE void\nwitness_unlock(tsdn_t *tsdn, witness_t *witness)\n{\n\ttsd_t *tsd;\n\twitness_list_t *witnesses;\n\n\tif (!config_debug)\n\t\treturn;\n\n\tif (tsdn_null(tsdn))\n\t\treturn;\n\ttsd = tsdn_tsd(tsdn);\n\tif (witness->rank == WITNESS_RANK_OMIT)\n\t\treturn;\n\n\twitness_assert_owner(tsdn, witness);\n\n\twitnesses = tsd_witnessesp_get(tsd);\n\tql_remove(witnesses, witness, link);\n}\n#endif\n\n#endif /* JEMALLOC_H_INLINES */\n/******************************************************************************/\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/deps/jemalloc/include/jemalloc/jemalloc.sh",
    "content": "#!/bin/sh\n\nobjroot=$1\n\ncat <<EOF\n#ifndef JEMALLOC_H_\n#define\tJEMALLOC_H_\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\nEOF\n\nfor hdr in jemalloc_defs.h jemalloc_rename.h jemalloc_macros.h \\\n           jemalloc_protos.h jemalloc_typedefs.h jemalloc_mangle.h ; do\n  cat \"${objroot}include/jemalloc/${hdr}\" \\\n      | grep -v 'Generated from .* by configure\\.' \\\n      | sed -e 's/^#define /#define\t/g' \\\n      | sed -e 's/ $//g'\n  echo\ndone\n\ncat <<EOF\n#ifdef __cplusplus\n}\n#endif\n#endif /* JEMALLOC_H_ */\nEOF\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/deps/jemalloc/include/jemalloc/jemalloc_defs.h.in",
    "content": "/* Defined if __attribute__((...)) syntax is supported. */\n#undef JEMALLOC_HAVE_ATTR\n\n/* Defined if alloc_size attribute is supported. */\n#undef JEMALLOC_HAVE_ATTR_ALLOC_SIZE\n\n/* Defined if format(gnu_printf, ...) attribute is supported. */\n#undef JEMALLOC_HAVE_ATTR_FORMAT_GNU_PRINTF\n\n/* Defined if format(printf, ...) attribute is supported. */\n#undef JEMALLOC_HAVE_ATTR_FORMAT_PRINTF\n\n/*\n * Define overrides for non-standard allocator-related functions if they are\n * present on the system.\n */\n#undef JEMALLOC_OVERRIDE_MEMALIGN\n#undef JEMALLOC_OVERRIDE_VALLOC\n\n/*\n * At least Linux omits the \"const\" in:\n *\n *   size_t malloc_usable_size(const void *ptr);\n *\n * Match the operating system's prototype.\n */\n#undef JEMALLOC_USABLE_SIZE_CONST\n\n/*\n * If defined, specify throw() for the public function prototypes when compiling\n * with C++.  The only justification for this is to match the prototypes that\n * glibc defines.\n */\n#undef JEMALLOC_USE_CXX_THROW\n\n#ifdef _MSC_VER\n#  ifdef _WIN64\n#    define LG_SIZEOF_PTR_WIN 3\n#  else\n#    define LG_SIZEOF_PTR_WIN 2\n#  endif\n#endif\n\n/* sizeof(void *) == 2^LG_SIZEOF_PTR. */\n#undef LG_SIZEOF_PTR\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/deps/jemalloc/include/jemalloc/jemalloc_macros.h.in",
    "content": "#include <stdlib.h>\n#include <stdbool.h>\n#include <stdint.h>\n#include <limits.h>\n#include <strings.h>\n\n#define\tJEMALLOC_VERSION \"@jemalloc_version@\"\n#define\tJEMALLOC_VERSION_MAJOR @jemalloc_version_major@\n#define\tJEMALLOC_VERSION_MINOR @jemalloc_version_minor@\n#define\tJEMALLOC_VERSION_BUGFIX @jemalloc_version_bugfix@\n#define\tJEMALLOC_VERSION_NREV @jemalloc_version_nrev@\n#define\tJEMALLOC_VERSION_GID \"@jemalloc_version_gid@\"\n\n#  define MALLOCX_LG_ALIGN(la)\t((int)(la))\n#  if LG_SIZEOF_PTR == 2\n#    define MALLOCX_ALIGN(a)\t((int)(ffs((int)(a))-1))\n#  else\n#    define MALLOCX_ALIGN(a)\t\t\t\t\t\t\\\n       ((int)(((size_t)(a) < (size_t)INT_MAX) ? ffs((int)(a))-1 :\t\\\n       ffs((int)(((size_t)(a))>>32))+31))\n#  endif\n#  define MALLOCX_ZERO\t((int)0x40)\n/*\n * Bias tcache index bits so that 0 encodes \"automatic tcache management\", and 1\n * encodes MALLOCX_TCACHE_NONE.\n */\n#  define MALLOCX_TCACHE(tc)\t((int)(((tc)+2) << 8))\n#  define MALLOCX_TCACHE_NONE\tMALLOCX_TCACHE(-1)\n/*\n * Bias arena index bits so that 0 encodes \"use an automatically chosen arena\".\n */\n#  define MALLOCX_ARENA(a)\t((((int)(a))+1) << 20)\n\n#if defined(__cplusplus) && defined(JEMALLOC_USE_CXX_THROW)\n#  define JEMALLOC_CXX_THROW throw()\n#else\n#  define JEMALLOC_CXX_THROW\n#endif\n\n#if _MSC_VER\n#  define JEMALLOC_ATTR(s)\n#  define JEMALLOC_ALIGNED(s) __declspec(align(s))\n#  define JEMALLOC_ALLOC_SIZE(s)\n#  define JEMALLOC_ALLOC_SIZE2(s1, s2)\n#  ifndef JEMALLOC_EXPORT\n#    ifdef DLLEXPORT\n#      define JEMALLOC_EXPORT __declspec(dllexport)\n#    else\n#      define JEMALLOC_EXPORT __declspec(dllimport)\n#    endif\n#  endif\n#  define JEMALLOC_FORMAT_PRINTF(s, i)\n#  define JEMALLOC_NOINLINE __declspec(noinline)\n#  ifdef __cplusplus\n#    define JEMALLOC_NOTHROW __declspec(nothrow)\n#  else\n#    define JEMALLOC_NOTHROW\n#  endif\n#  define JEMALLOC_SECTION(s) __declspec(allocate(s))\n#  define JEMALLOC_RESTRICT_RETURN __declspec(restrict)\n#  if _MSC_VER >= 1900 && !defined(__EDG__)\n#    define JEMALLOC_ALLOCATOR __declspec(allocator)\n#  else\n#    define JEMALLOC_ALLOCATOR\n#  endif\n#elif defined(JEMALLOC_HAVE_ATTR)\n#  define JEMALLOC_ATTR(s) __attribute__((s))\n#  define JEMALLOC_ALIGNED(s) JEMALLOC_ATTR(aligned(s))\n#  ifdef JEMALLOC_HAVE_ATTR_ALLOC_SIZE\n#    define JEMALLOC_ALLOC_SIZE(s) JEMALLOC_ATTR(alloc_size(s))\n#    define JEMALLOC_ALLOC_SIZE2(s1, s2) JEMALLOC_ATTR(alloc_size(s1, s2))\n#  else\n#    define JEMALLOC_ALLOC_SIZE(s)\n#    define JEMALLOC_ALLOC_SIZE2(s1, s2)\n#  endif\n#  ifndef JEMALLOC_EXPORT\n#    define JEMALLOC_EXPORT JEMALLOC_ATTR(visibility(\"default\"))\n#  endif\n#  ifdef JEMALLOC_HAVE_ATTR_FORMAT_GNU_PRINTF\n#    define JEMALLOC_FORMAT_PRINTF(s, i) JEMALLOC_ATTR(format(gnu_printf, s, i))\n#  elif defined(JEMALLOC_HAVE_ATTR_FORMAT_PRINTF)\n#    define JEMALLOC_FORMAT_PRINTF(s, i) JEMALLOC_ATTR(format(printf, s, i))\n#  else\n#    define JEMALLOC_FORMAT_PRINTF(s, i)\n#  endif\n#  define JEMALLOC_NOINLINE JEMALLOC_ATTR(noinline)\n#  define JEMALLOC_NOTHROW JEMALLOC_ATTR(nothrow)\n#  define JEMALLOC_SECTION(s) JEMALLOC_ATTR(section(s))\n#  define JEMALLOC_RESTRICT_RETURN\n#  define JEMALLOC_ALLOCATOR\n#else\n#  define JEMALLOC_ATTR(s)\n#  define JEMALLOC_ALIGNED(s)\n#  define JEMALLOC_ALLOC_SIZE(s)\n#  define JEMALLOC_ALLOC_SIZE2(s1, s2)\n#  define JEMALLOC_EXPORT\n#  define JEMALLOC_FORMAT_PRINTF(s, i)\n#  define JEMALLOC_NOINLINE\n#  define JEMALLOC_NOTHROW\n#  define JEMALLOC_SECTION(s)\n#  define JEMALLOC_RESTRICT_RETURN\n#  define JEMALLOC_ALLOCATOR\n#endif\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/deps/jemalloc/include/jemalloc/jemalloc_mangle.sh",
    "content": "#!/bin/sh\n\npublic_symbols_txt=$1\nsymbol_prefix=$2\n\ncat <<EOF\n/*\n * By default application code must explicitly refer to mangled symbol names,\n * so that it is possible to use jemalloc in conjunction with another allocator\n * in the same application.  Define JEMALLOC_MANGLE in order to cause automatic\n * name mangling that matches the API prefixing that happened as a result of\n * --with-mangling and/or --with-jemalloc-prefix configuration settings.\n */\n#ifdef JEMALLOC_MANGLE\n#  ifndef JEMALLOC_NO_DEMANGLE\n#    define JEMALLOC_NO_DEMANGLE\n#  endif\nEOF\n\nfor nm in `cat ${public_symbols_txt}` ; do\n  n=`echo ${nm} |tr ':' ' ' |awk '{print $1}'`\n  echo \"#  define ${n} ${symbol_prefix}${n}\"\ndone\n\ncat <<EOF\n#endif\n\n/*\n * The ${symbol_prefix}* macros can be used as stable alternative names for the\n * public jemalloc API if JEMALLOC_NO_DEMANGLE is defined.  This is primarily\n * meant for use in jemalloc itself, but it can be used by application code to\n * provide isolation from the name mangling specified via --with-mangling\n * and/or --with-jemalloc-prefix.\n */\n#ifndef JEMALLOC_NO_DEMANGLE\nEOF\n\nfor nm in `cat ${public_symbols_txt}` ; do\n  n=`echo ${nm} |tr ':' ' ' |awk '{print $1}'`\n  echo \"#  undef ${symbol_prefix}${n}\"\ndone\n\ncat <<EOF\n#endif\nEOF\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/deps/jemalloc/include/jemalloc/jemalloc_protos.h.in",
    "content": "/*\n * The @je_@ prefix on the following public symbol declarations is an artifact\n * of namespace management, and should be omitted in application code unless\n * JEMALLOC_NO_DEMANGLE is defined (see jemalloc_mangle@install_suffix@.h).\n */\nextern JEMALLOC_EXPORT const char\t*@je_@malloc_conf;\nextern JEMALLOC_EXPORT void\t\t(*@je_@malloc_message)(void *cbopaque,\n    const char *s);\n\nJEMALLOC_EXPORT JEMALLOC_ALLOCATOR JEMALLOC_RESTRICT_RETURN\n    void JEMALLOC_NOTHROW\t*@je_@malloc(size_t size)\n    JEMALLOC_CXX_THROW JEMALLOC_ATTR(malloc) JEMALLOC_ALLOC_SIZE(1);\nJEMALLOC_EXPORT JEMALLOC_ALLOCATOR JEMALLOC_RESTRICT_RETURN\n    void JEMALLOC_NOTHROW\t*@je_@calloc(size_t num, size_t size)\n    JEMALLOC_CXX_THROW JEMALLOC_ATTR(malloc) JEMALLOC_ALLOC_SIZE2(1, 2);\nJEMALLOC_EXPORT int JEMALLOC_NOTHROW\t@je_@posix_memalign(void **memptr,\n    size_t alignment, size_t size) JEMALLOC_CXX_THROW JEMALLOC_ATTR(nonnull(1));\nJEMALLOC_EXPORT JEMALLOC_ALLOCATOR JEMALLOC_RESTRICT_RETURN\n    void JEMALLOC_NOTHROW\t*@je_@aligned_alloc(size_t alignment,\n    size_t size) JEMALLOC_CXX_THROW JEMALLOC_ATTR(malloc)\n    JEMALLOC_ALLOC_SIZE(2);\nJEMALLOC_EXPORT JEMALLOC_ALLOCATOR JEMALLOC_RESTRICT_RETURN\n    void JEMALLOC_NOTHROW\t*@je_@realloc(void *ptr, size_t size)\n    JEMALLOC_CXX_THROW JEMALLOC_ALLOC_SIZE(2);\nJEMALLOC_EXPORT void JEMALLOC_NOTHROW\t@je_@free(void *ptr)\n    JEMALLOC_CXX_THROW;\n\nJEMALLOC_EXPORT JEMALLOC_ALLOCATOR JEMALLOC_RESTRICT_RETURN\n    void JEMALLOC_NOTHROW\t*@je_@mallocx(size_t size, int flags)\n    JEMALLOC_ATTR(malloc) JEMALLOC_ALLOC_SIZE(1);\nJEMALLOC_EXPORT JEMALLOC_ALLOCATOR JEMALLOC_RESTRICT_RETURN\n    void JEMALLOC_NOTHROW\t*@je_@rallocx(void *ptr, size_t size,\n    int flags) JEMALLOC_ALLOC_SIZE(2);\nJEMALLOC_EXPORT size_t JEMALLOC_NOTHROW\t@je_@xallocx(void *ptr, size_t size,\n    size_t extra, int flags);\nJEMALLOC_EXPORT size_t JEMALLOC_NOTHROW\t@je_@sallocx(const void *ptr,\n    int flags) JEMALLOC_ATTR(pure);\nJEMALLOC_EXPORT void JEMALLOC_NOTHROW\t@je_@dallocx(void *ptr, int flags);\nJEMALLOC_EXPORT void JEMALLOC_NOTHROW\t@je_@sdallocx(void *ptr, size_t size,\n    int flags);\nJEMALLOC_EXPORT size_t JEMALLOC_NOTHROW\t@je_@nallocx(size_t size, int flags)\n    JEMALLOC_ATTR(pure);\n\nJEMALLOC_EXPORT int JEMALLOC_NOTHROW\t@je_@mallctl(const char *name,\n    void *oldp, size_t *oldlenp, void *newp, size_t newlen);\nJEMALLOC_EXPORT int JEMALLOC_NOTHROW\t@je_@mallctlnametomib(const char *name,\n    size_t *mibp, size_t *miblenp);\nJEMALLOC_EXPORT int JEMALLOC_NOTHROW\t@je_@mallctlbymib(const size_t *mib,\n    size_t miblen, void *oldp, size_t *oldlenp, void *newp, size_t newlen);\nJEMALLOC_EXPORT void JEMALLOC_NOTHROW\t@je_@malloc_stats_print(\n    void (*write_cb)(void *, const char *), void *@je_@cbopaque,\n    const char *opts);\nJEMALLOC_EXPORT size_t JEMALLOC_NOTHROW\t@je_@malloc_usable_size(\n    JEMALLOC_USABLE_SIZE_CONST void *ptr) JEMALLOC_CXX_THROW;\n\n#ifdef JEMALLOC_OVERRIDE_MEMALIGN\nJEMALLOC_EXPORT JEMALLOC_ALLOCATOR JEMALLOC_RESTRICT_RETURN\n    void JEMALLOC_NOTHROW\t*@je_@memalign(size_t alignment, size_t size)\n    JEMALLOC_CXX_THROW JEMALLOC_ATTR(malloc);\n#endif\n\n#ifdef JEMALLOC_OVERRIDE_VALLOC\nJEMALLOC_EXPORT JEMALLOC_ALLOCATOR JEMALLOC_RESTRICT_RETURN\n    void JEMALLOC_NOTHROW\t*@je_@valloc(size_t size) JEMALLOC_CXX_THROW\n    JEMALLOC_ATTR(malloc);\n#endif\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/deps/jemalloc/include/jemalloc/jemalloc_rename.sh",
    "content": "#!/bin/sh\n\npublic_symbols_txt=$1\n\ncat <<EOF\n/*\n * Name mangling for public symbols is controlled by --with-mangling and\n * --with-jemalloc-prefix.  With default settings the je_ prefix is stripped by\n * these macro definitions.\n */\n#ifndef JEMALLOC_NO_RENAME\nEOF\n\nfor nm in `cat ${public_symbols_txt}` ; do\n  n=`echo ${nm} |tr ':' ' ' |awk '{print $1}'`\n  m=`echo ${nm} |tr ':' ' ' |awk '{print $2}'`\n  echo \"#  define je_${n} ${m}\"\ndone\n\ncat <<EOF\n#endif\nEOF\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/deps/jemalloc/include/jemalloc/jemalloc_typedefs.h.in",
    "content": "/*\n * void *\n * chunk_alloc(void *new_addr, size_t size, size_t alignment, bool *zero,\n *     bool *commit, unsigned arena_ind);\n */\ntypedef void *(chunk_alloc_t)(void *, size_t, size_t, bool *, bool *, unsigned);\n\n/*\n * bool\n * chunk_dalloc(void *chunk, size_t size, bool committed, unsigned arena_ind);\n */\ntypedef bool (chunk_dalloc_t)(void *, size_t, bool, unsigned);\n\n/*\n * bool\n * chunk_commit(void *chunk, size_t size, size_t offset, size_t length,\n *     unsigned arena_ind);\n */\ntypedef bool (chunk_commit_t)(void *, size_t, size_t, size_t, unsigned);\n\n/*\n * bool\n * chunk_decommit(void *chunk, size_t size, size_t offset, size_t length,\n *     unsigned arena_ind);\n */\ntypedef bool (chunk_decommit_t)(void *, size_t, size_t, size_t, unsigned);\n\n/*\n * bool\n * chunk_purge(void *chunk, size_t size, size_t offset, size_t length,\n *     unsigned arena_ind);\n */\ntypedef bool (chunk_purge_t)(void *, size_t, size_t, size_t, unsigned);\n\n/*\n * bool\n * chunk_split(void *chunk, size_t size, size_t size_a, size_t size_b,\n *     bool committed, unsigned arena_ind);\n */\ntypedef bool (chunk_split_t)(void *, size_t, size_t, size_t, bool, unsigned);\n\n/*\n * bool\n * chunk_merge(void *chunk_a, size_t size_a, void *chunk_b, size_t size_b,\n *     bool committed, unsigned arena_ind);\n */\ntypedef bool (chunk_merge_t)(void *, size_t, void *, size_t, bool, unsigned);\n\ntypedef struct {\n\tchunk_alloc_t\t\t*alloc;\n\tchunk_dalloc_t\t\t*dalloc;\n\tchunk_commit_t\t\t*commit;\n\tchunk_decommit_t\t*decommit;\n\tchunk_purge_t\t\t*purge;\n\tchunk_split_t\t\t*split;\n\tchunk_merge_t\t\t*merge;\n} chunk_hooks_t;\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/deps/jemalloc/include/msvc_compat/C99/stdbool.h",
    "content": "#ifndef stdbool_h\n#define stdbool_h\n\n#include <wtypes.h>\n\n/* MSVC doesn't define _Bool or bool in C, but does have BOOL */\n/* Note this doesn't pass autoconf's test because (bool) 0.5 != true */\n/* Clang-cl uses MSVC headers, so needs msvc_compat, but has _Bool as\n * a built-in type. */\n#ifndef __clang__\ntypedef BOOL _Bool;\n#endif\n\n#define bool _Bool\n#define true 1\n#define false 0\n\n#define __bool_true_false_are_defined 1\n\n#endif /* stdbool_h */\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/deps/jemalloc/include/msvc_compat/C99/stdint.h",
    "content": "// ISO C9x  compliant stdint.h for Microsoft Visual Studio\n// Based on ISO/IEC 9899:TC2 Committee draft (May 6, 2005) WG14/N1124 \n// \n//  Copyright (c) 2006-2008 Alexander Chemeris\n// \n// Redistribution and use in source and binary forms, with or without\n// modification, are permitted provided that the following conditions are met:\n// \n//   1. Redistributions of source code must retain the above copyright notice,\n//      this list of conditions and the following disclaimer.\n// \n//   2. Redistributions in binary form must reproduce the above copyright\n//      notice, this list of conditions and the following disclaimer in the\n//      documentation and/or other materials provided with the distribution.\n// \n//   3. The name of the author may be used to endorse or promote products\n//      derived from this software without specific prior written permission.\n// \n// THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED\n// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF\n// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO\n// EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,\n// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;\n// OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, \n// WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR\n// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF\n// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n// \n///////////////////////////////////////////////////////////////////////////////\n\n#ifndef _MSC_VER // [\n#error \"Use this header only with Microsoft Visual C++ compilers!\"\n#endif // _MSC_VER ]\n\n#ifndef _MSC_STDINT_H_ // [\n#define _MSC_STDINT_H_\n\n#if _MSC_VER > 1000\n#pragma once\n#endif\n\n#include <limits.h>\n\n// For Visual Studio 6 in C++ mode and for many Visual Studio versions when\n// compiling for ARM we should wrap <wchar.h> include with 'extern \"C++\" {}'\n// or compiler give many errors like this:\n//   error C2733: second C linkage of overloaded function 'wmemchr' not allowed\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n#  include <wchar.h>\n#ifdef __cplusplus\n}\n#endif\n\n// Define _W64 macros to mark types changing their size, like intptr_t.\n#ifndef _W64\n#  if !defined(__midl) && (defined(_X86_) || defined(_M_IX86)) && _MSC_VER >= 1300\n#     define _W64 __w64\n#  else\n#     define _W64\n#  endif\n#endif\n\n\n// 7.18.1 Integer types\n\n// 7.18.1.1 Exact-width integer types\n\n// Visual Studio 6 and Embedded Visual C++ 4 doesn't\n// realize that, e.g. char has the same size as __int8\n// so we give up on __intX for them.\n#if (_MSC_VER < 1300)\n   typedef signed char       int8_t;\n   typedef signed short      int16_t;\n   typedef signed int        int32_t;\n   typedef unsigned char     uint8_t;\n   typedef unsigned short    uint16_t;\n   typedef unsigned int      uint32_t;\n#else\n   typedef signed __int8     int8_t;\n   typedef signed __int16    int16_t;\n   typedef signed __int32    int32_t;\n   typedef unsigned __int8   uint8_t;\n   typedef unsigned __int16  uint16_t;\n   typedef unsigned __int32  uint32_t;\n#endif\ntypedef signed __int64       int64_t;\ntypedef unsigned __int64     uint64_t;\n\n\n// 7.18.1.2 Minimum-width integer types\ntypedef int8_t    int_least8_t;\ntypedef int16_t   int_least16_t;\ntypedef int32_t   int_least32_t;\ntypedef int64_t   int_least64_t;\ntypedef uint8_t   uint_least8_t;\ntypedef uint16_t  uint_least16_t;\ntypedef uint32_t  uint_least32_t;\ntypedef uint64_t  uint_least64_t;\n\n// 7.18.1.3 Fastest minimum-width integer types\ntypedef int8_t    int_fast8_t;\ntypedef int16_t   int_fast16_t;\ntypedef int32_t   int_fast32_t;\ntypedef int64_t   int_fast64_t;\ntypedef uint8_t   uint_fast8_t;\ntypedef uint16_t  uint_fast16_t;\ntypedef uint32_t  uint_fast32_t;\ntypedef uint64_t  uint_fast64_t;\n\n// 7.18.1.4 Integer types capable of holding object pointers\n#ifdef _WIN64 // [\n   typedef signed __int64    intptr_t;\n   typedef unsigned __int64  uintptr_t;\n#else // _WIN64 ][\n   typedef _W64 signed int   intptr_t;\n   typedef _W64 unsigned int uintptr_t;\n#endif // _WIN64 ]\n\n// 7.18.1.5 Greatest-width integer types\ntypedef int64_t   intmax_t;\ntypedef uint64_t  uintmax_t;\n\n\n// 7.18.2 Limits of specified-width integer types\n\n#if !defined(__cplusplus) || defined(__STDC_LIMIT_MACROS) // [   See footnote 220 at page 257 and footnote 221 at page 259\n\n// 7.18.2.1 Limits of exact-width integer types\n#define INT8_MIN     ((int8_t)_I8_MIN)\n#define INT8_MAX     _I8_MAX\n#define INT16_MIN    ((int16_t)_I16_MIN)\n#define INT16_MAX    _I16_MAX\n#define INT32_MIN    ((int32_t)_I32_MIN)\n#define INT32_MAX    _I32_MAX\n#define INT64_MIN    ((int64_t)_I64_MIN)\n#define INT64_MAX    _I64_MAX\n#define UINT8_MAX    _UI8_MAX\n#define UINT16_MAX   _UI16_MAX\n#define UINT32_MAX   _UI32_MAX\n#define UINT64_MAX   _UI64_MAX\n\n// 7.18.2.2 Limits of minimum-width integer types\n#define INT_LEAST8_MIN    INT8_MIN\n#define INT_LEAST8_MAX    INT8_MAX\n#define INT_LEAST16_MIN   INT16_MIN\n#define INT_LEAST16_MAX   INT16_MAX\n#define INT_LEAST32_MIN   INT32_MIN\n#define INT_LEAST32_MAX   INT32_MAX\n#define INT_LEAST64_MIN   INT64_MIN\n#define INT_LEAST64_MAX   INT64_MAX\n#define UINT_LEAST8_MAX   UINT8_MAX\n#define UINT_LEAST16_MAX  UINT16_MAX\n#define UINT_LEAST32_MAX  UINT32_MAX\n#define UINT_LEAST64_MAX  UINT64_MAX\n\n// 7.18.2.3 Limits of fastest minimum-width integer types\n#define INT_FAST8_MIN    INT8_MIN\n#define INT_FAST8_MAX    INT8_MAX\n#define INT_FAST16_MIN   INT16_MIN\n#define INT_FAST16_MAX   INT16_MAX\n#define INT_FAST32_MIN   INT32_MIN\n#define INT_FAST32_MAX   INT32_MAX\n#define INT_FAST64_MIN   INT64_MIN\n#define INT_FAST64_MAX   INT64_MAX\n#define UINT_FAST8_MAX   UINT8_MAX\n#define UINT_FAST16_MAX  UINT16_MAX\n#define UINT_FAST32_MAX  UINT32_MAX\n#define UINT_FAST64_MAX  UINT64_MAX\n\n// 7.18.2.4 Limits of integer types capable of holding object pointers\n#ifdef _WIN64 // [\n#  define INTPTR_MIN   INT64_MIN\n#  define INTPTR_MAX   INT64_MAX\n#  define UINTPTR_MAX  UINT64_MAX\n#else // _WIN64 ][\n#  define INTPTR_MIN   INT32_MIN\n#  define INTPTR_MAX   INT32_MAX\n#  define UINTPTR_MAX  UINT32_MAX\n#endif // _WIN64 ]\n\n// 7.18.2.5 Limits of greatest-width integer types\n#define INTMAX_MIN   INT64_MIN\n#define INTMAX_MAX   INT64_MAX\n#define UINTMAX_MAX  UINT64_MAX\n\n// 7.18.3 Limits of other integer types\n\n#ifdef _WIN64 // [\n#  define PTRDIFF_MIN  _I64_MIN\n#  define PTRDIFF_MAX  _I64_MAX\n#else  // _WIN64 ][\n#  define PTRDIFF_MIN  _I32_MIN\n#  define PTRDIFF_MAX  _I32_MAX\n#endif  // _WIN64 ]\n\n#define SIG_ATOMIC_MIN  INT_MIN\n#define SIG_ATOMIC_MAX  INT_MAX\n\n#ifndef SIZE_MAX // [\n#  ifdef _WIN64 // [\n#     define SIZE_MAX  _UI64_MAX\n#  else // _WIN64 ][\n#     define SIZE_MAX  _UI32_MAX\n#  endif // _WIN64 ]\n#endif // SIZE_MAX ]\n\n// WCHAR_MIN and WCHAR_MAX are also defined in <wchar.h>\n#ifndef WCHAR_MIN // [\n#  define WCHAR_MIN  0\n#endif  // WCHAR_MIN ]\n#ifndef WCHAR_MAX // [\n#  define WCHAR_MAX  _UI16_MAX\n#endif  // WCHAR_MAX ]\n\n#define WINT_MIN  0\n#define WINT_MAX  _UI16_MAX\n\n#endif // __STDC_LIMIT_MACROS ]\n\n\n// 7.18.4 Limits of other integer types\n\n#if !defined(__cplusplus) || defined(__STDC_CONSTANT_MACROS) // [   See footnote 224 at page 260\n\n// 7.18.4.1 Macros for minimum-width integer constants\n\n#define INT8_C(val)  val##i8\n#define INT16_C(val) val##i16\n#define INT32_C(val) val##i32\n#define INT64_C(val) val##i64\n\n#define UINT8_C(val)  val##ui8\n#define UINT16_C(val) val##ui16\n#define UINT32_C(val) val##ui32\n#define UINT64_C(val) val##ui64\n\n// 7.18.4.2 Macros for greatest-width integer constants\n#define INTMAX_C   INT64_C\n#define UINTMAX_C  UINT64_C\n\n#endif // __STDC_CONSTANT_MACROS ]\n\n\n#endif // _MSC_STDINT_H_ ]\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/deps/jemalloc/include/msvc_compat/strings.h",
    "content": "#ifndef strings_h\n#define strings_h\n\n/* MSVC doesn't define ffs/ffsl. This dummy strings.h header is provided\n * for both */\n#ifdef _MSC_VER\n#  include <intrin.h>\n#  pragma intrinsic(_BitScanForward)\nstatic __forceinline int ffsl(long x)\n{\n\tunsigned long i;\n\n\tif (_BitScanForward(&i, x))\n\t\treturn (i + 1);\n\treturn (0);\n}\n\nstatic __forceinline int ffs(int x)\n{\n\n\treturn (ffsl(x));\n}\n\n#  ifdef  _M_X64\n#    pragma intrinsic(_BitScanForward64)\n#  endif\n\nstatic __forceinline int ffsll(unsigned __int64 x)\n{\n\tunsigned long i;\n#ifdef  _M_X64\n\tif (_BitScanForward64(&i, x))\n\t\treturn (i + 1);\n\treturn (0);\n#else\n// Fallback for 32-bit build where 64-bit version not available\n// assuming little endian\n\tunion {\n\t\tunsigned __int64 ll;\n\t\tunsigned   long l[2];\n\t} s;\n\n\ts.ll = x;\n\n\tif (_BitScanForward(&i, s.l[0]))\n\t\treturn (i + 1);\n\telse if(_BitScanForward(&i, s.l[1]))\n\t\treturn (i + 33);\n\treturn (0);\n#endif\n}\n\n#else\n#  define ffsll(x) __builtin_ffsll(x)\n#  define ffsl(x) __builtin_ffsl(x)\n#  define ffs(x) __builtin_ffs(x)\n#endif\n\n#endif /* strings_h */\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/deps/jemalloc/include/msvc_compat/windows_extra.h",
    "content": "#ifndef MSVC_COMPAT_WINDOWS_EXTRA_H\n#define\tMSVC_COMPAT_WINDOWS_EXTRA_H\n\n#include <errno.h>\n\n#endif /* MSVC_COMPAT_WINDOWS_EXTRA_H */\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/deps/jemalloc/jemalloc.pc.in",
    "content": "prefix=@prefix@\nexec_prefix=@exec_prefix@\nlibdir=@libdir@\nincludedir=@includedir@\ninstall_suffix=@install_suffix@\n\nName: jemalloc\nDescription: A general purpose malloc(3) implementation that emphasizes fragmentation avoidance and scalable concurrency support.\nURL: http://www.canonware.com/jemalloc\nVersion: @jemalloc_version@\nCflags: -I${includedir}\nLibs: -L${libdir} -ljemalloc${install_suffix}\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/deps/jemalloc/msvc/ReadMe.txt",
    "content": "\nHow to build jemalloc for Windows\n=================================\n\n1. Install Cygwin with at least the following packages:\n   * autoconf\n   * autogen\n   * gawk\n   * grep\n   * sed\n\n2. Install Visual Studio 2015 with Visual C++\n\n3. Add Cygwin\\bin to the PATH environment variable\n\n4. Open \"VS2015 x86 Native Tools Command Prompt\"\n   (note: x86/x64 doesn't matter at this point)\n\n5. Generate header files:\n   sh -c \"./autogen.sh CC=cl --enable-lazy-lock=no\"\n\n6. Now the project can be opened and built in Visual Studio:\n   msvc\\jemalloc_vc2015.sln\n\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/deps/jemalloc/msvc/jemalloc_vc2015.sln",
    "content": "﻿\nMicrosoft Visual Studio Solution File, Format Version 12.00\n# Visual Studio 14\nVisualStudioVersion = 14.0.24720.0\nMinimumVisualStudioVersion = 10.0.40219.1\nProject(\"{2150E333-8FDC-42A3-9474-1A3956D46DE8}\") = \"Solution Items\", \"Solution Items\", \"{70A99006-6DE9-472B-8F83-4CEE6C616DF3}\"\n\tProjectSection(SolutionItems) = preProject\n\t\tReadMe.txt = ReadMe.txt\n\tEndProjectSection\nEndProject\nProject(\"{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}\") = \"jemalloc\", \"projects\\vc2015\\jemalloc\\jemalloc.vcxproj\", \"{8D6BB292-9E1C-413D-9F98-4864BDC1514A}\"\nEndProject\nProject(\"{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}\") = \"test_threads\", \"projects\\vc2015\\test_threads\\test_threads.vcxproj\", \"{09028CFD-4EB7-491D-869C-0708DB97ED44}\"\nEndProject\nGlobal\n\tGlobalSection(SolutionConfigurationPlatforms) = preSolution\n\t\tDebug|x64 = Debug|x64\n\t\tDebug|x86 = Debug|x86\n\t\tDebug-static|x64 = Debug-static|x64\n\t\tDebug-static|x86 = Debug-static|x86\n\t\tRelease|x64 = Release|x64\n\t\tRelease|x86 = Release|x86\n\t\tRelease-static|x64 = Release-static|x64\n\t\tRelease-static|x86 = Release-static|x86\n\tEndGlobalSection\n\tGlobalSection(ProjectConfigurationPlatforms) = postSolution\n\t\t{8D6BB292-9E1C-413D-9F98-4864BDC1514A}.Debug|x64.ActiveCfg = Debug|x64\n\t\t{8D6BB292-9E1C-413D-9F98-4864BDC1514A}.Debug|x64.Build.0 = Debug|x64\n\t\t{8D6BB292-9E1C-413D-9F98-4864BDC1514A}.Debug|x86.ActiveCfg = Debug|Win32\n\t\t{8D6BB292-9E1C-413D-9F98-4864BDC1514A}.Debug|x86.Build.0 = Debug|Win32\n\t\t{8D6BB292-9E1C-413D-9F98-4864BDC1514A}.Debug-static|x64.ActiveCfg = Debug-static|x64\n\t\t{8D6BB292-9E1C-413D-9F98-4864BDC1514A}.Debug-static|x64.Build.0 = Debug-static|x64\n\t\t{8D6BB292-9E1C-413D-9F98-4864BDC1514A}.Debug-static|x86.ActiveCfg = Debug-static|Win32\n\t\t{8D6BB292-9E1C-413D-9F98-4864BDC1514A}.Debug-static|x86.Build.0 = Debug-static|Win32\n\t\t{8D6BB292-9E1C-413D-9F98-4864BDC1514A}.Release|x64.ActiveCfg = Release|x64\n\t\t{8D6BB292-9E1C-413D-9F98-4864BDC1514A}.Release|x64.Build.0 = Release|x64\n\t\t{8D6BB292-9E1C-413D-9F98-4864BDC1514A}.Release|x86.ActiveCfg = Release|Win32\n\t\t{8D6BB292-9E1C-413D-9F98-4864BDC1514A}.Release|x86.Build.0 = Release|Win32\n\t\t{8D6BB292-9E1C-413D-9F98-4864BDC1514A}.Release-static|x64.ActiveCfg = Release-static|x64\n\t\t{8D6BB292-9E1C-413D-9F98-4864BDC1514A}.Release-static|x64.Build.0 = Release-static|x64\n\t\t{8D6BB292-9E1C-413D-9F98-4864BDC1514A}.Release-static|x86.ActiveCfg = Release-static|Win32\n\t\t{8D6BB292-9E1C-413D-9F98-4864BDC1514A}.Release-static|x86.Build.0 = Release-static|Win32\n\t\t{09028CFD-4EB7-491D-869C-0708DB97ED44}.Debug|x64.ActiveCfg = Debug|x64\n\t\t{09028CFD-4EB7-491D-869C-0708DB97ED44}.Debug|x64.Build.0 = Debug|x64\n\t\t{09028CFD-4EB7-491D-869C-0708DB97ED44}.Debug|x86.ActiveCfg = Debug|Win32\n\t\t{09028CFD-4EB7-491D-869C-0708DB97ED44}.Debug|x86.Build.0 = Debug|Win32\n\t\t{09028CFD-4EB7-491D-869C-0708DB97ED44}.Debug-static|x64.ActiveCfg = Debug-static|x64\n\t\t{09028CFD-4EB7-491D-869C-0708DB97ED44}.Debug-static|x64.Build.0 = Debug-static|x64\n\t\t{09028CFD-4EB7-491D-869C-0708DB97ED44}.Debug-static|x86.ActiveCfg = Debug-static|Win32\n\t\t{09028CFD-4EB7-491D-869C-0708DB97ED44}.Debug-static|x86.Build.0 = Debug-static|Win32\n\t\t{09028CFD-4EB7-491D-869C-0708DB97ED44}.Release|x64.ActiveCfg = Release|x64\n\t\t{09028CFD-4EB7-491D-869C-0708DB97ED44}.Release|x64.Build.0 = Release|x64\n\t\t{09028CFD-4EB7-491D-869C-0708DB97ED44}.Release|x86.ActiveCfg = Release|Win32\n\t\t{09028CFD-4EB7-491D-869C-0708DB97ED44}.Release|x86.Build.0 = Release|Win32\n\t\t{09028CFD-4EB7-491D-869C-0708DB97ED44}.Release-static|x64.ActiveCfg = Release-static|x64\n\t\t{09028CFD-4EB7-491D-869C-0708DB97ED44}.Release-static|x64.Build.0 = Release-static|x64\n\t\t{09028CFD-4EB7-491D-869C-0708DB97ED44}.Release-static|x86.ActiveCfg = Release-static|Win32\n\t\t{09028CFD-4EB7-491D-869C-0708DB97ED44}.Release-static|x86.Build.0 = Release-static|Win32\n\tEndGlobalSection\n\tGlobalSection(SolutionProperties) = preSolution\n\t\tHideSolutionNode = FALSE\n\tEndGlobalSection\nEndGlobal\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/deps/jemalloc/msvc/projects/vc2015/jemalloc/jemalloc.vcxproj",
    "content": "﻿<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<Project DefaultTargets=\"Build\" ToolsVersion=\"14.0\" xmlns=\"http://schemas.microsoft.com/developer/msbuild/2003\">\n  <ItemGroup Label=\"ProjectConfigurations\">\n    <ProjectConfiguration Include=\"Debug-static|Win32\">\n      <Configuration>Debug-static</Configuration>\n      <Platform>Win32</Platform>\n    </ProjectConfiguration>\n    <ProjectConfiguration Include=\"Debug-static|x64\">\n      <Configuration>Debug-static</Configuration>\n      <Platform>x64</Platform>\n    </ProjectConfiguration>\n    <ProjectConfiguration Include=\"Debug|Win32\">\n      <Configuration>Debug</Configuration>\n      <Platform>Win32</Platform>\n    </ProjectConfiguration>\n    <ProjectConfiguration Include=\"Release-static|Win32\">\n      <Configuration>Release-static</Configuration>\n      <Platform>Win32</Platform>\n    </ProjectConfiguration>\n    <ProjectConfiguration Include=\"Release-static|x64\">\n      <Configuration>Release-static</Configuration>\n      <Platform>x64</Platform>\n    </ProjectConfiguration>\n    <ProjectConfiguration Include=\"Release|Win32\">\n      <Configuration>Release</Configuration>\n      <Platform>Win32</Platform>\n    </ProjectConfiguration>\n    <ProjectConfiguration Include=\"Debug|x64\">\n      <Configuration>Debug</Configuration>\n      <Platform>x64</Platform>\n    </ProjectConfiguration>\n    <ProjectConfiguration Include=\"Release|x64\">\n      <Configuration>Release</Configuration>\n      <Platform>x64</Platform>\n    </ProjectConfiguration>\n  </ItemGroup>\n  <ItemGroup>\n    <ClInclude Include=\"..\\..\\..\\..\\include\\jemalloc\\internal\\arena.h\" />\n    <ClInclude Include=\"..\\..\\..\\..\\include\\jemalloc\\internal\\assert.h\" />\n    <ClInclude Include=\"..\\..\\..\\..\\include\\jemalloc\\internal\\atomic.h\" />\n    <ClInclude Include=\"..\\..\\..\\..\\include\\jemalloc\\internal\\base.h\" />\n    <ClInclude Include=\"..\\..\\..\\..\\include\\jemalloc\\internal\\bitmap.h\" />\n    <ClInclude Include=\"..\\..\\..\\..\\include\\jemalloc\\internal\\chunk.h\" />\n    <ClInclude Include=\"..\\..\\..\\..\\include\\jemalloc\\internal\\chunk_dss.h\" />\n    <ClInclude Include=\"..\\..\\..\\..\\include\\jemalloc\\internal\\chunk_mmap.h\" />\n    <ClInclude Include=\"..\\..\\..\\..\\include\\jemalloc\\internal\\ckh.h\" />\n    <ClInclude Include=\"..\\..\\..\\..\\include\\jemalloc\\internal\\ctl.h\" />\n    <ClInclude Include=\"..\\..\\..\\..\\include\\jemalloc\\internal\\extent.h\" />\n    <ClInclude Include=\"..\\..\\..\\..\\include\\jemalloc\\internal\\hash.h\" />\n    <ClInclude Include=\"..\\..\\..\\..\\include\\jemalloc\\internal\\huge.h\" />\n    <ClInclude Include=\"..\\..\\..\\..\\include\\jemalloc\\internal\\jemalloc_internal.h\" />\n    <ClInclude Include=\"..\\..\\..\\..\\include\\jemalloc\\internal\\jemalloc_internal_decls.h\" />\n    <ClInclude Include=\"..\\..\\..\\..\\include\\jemalloc\\internal\\jemalloc_internal_defs.h\" />\n    <ClInclude Include=\"..\\..\\..\\..\\include\\jemalloc\\internal\\jemalloc_internal_macros.h\" />\n    <ClInclude Include=\"..\\..\\..\\..\\include\\jemalloc\\internal\\mb.h\" />\n    <ClInclude Include=\"..\\..\\..\\..\\include\\jemalloc\\internal\\mutex.h\" />\n    <ClInclude Include=\"..\\..\\..\\..\\include\\jemalloc\\internal\\nstime.h\" />\n    <ClInclude Include=\"..\\..\\..\\..\\include\\jemalloc\\internal\\pages.h\" />\n    <ClInclude Include=\"..\\..\\..\\..\\include\\jemalloc\\internal\\ph.h\" />\n    <ClInclude Include=\"..\\..\\..\\..\\include\\jemalloc\\internal\\private_namespace.h\" />\n    <ClInclude Include=\"..\\..\\..\\..\\include\\jemalloc\\internal\\private_unnamespace.h\" />\n    <ClInclude Include=\"..\\..\\..\\..\\include\\jemalloc\\internal\\prng.h\" />\n    <ClInclude Include=\"..\\..\\..\\..\\include\\jemalloc\\internal\\prof.h\" />\n    <ClInclude Include=\"..\\..\\..\\..\\include\\jemalloc\\internal\\public_namespace.h\" />\n    <ClInclude Include=\"..\\..\\..\\..\\include\\jemalloc\\internal\\public_unnamespace.h\" />\n    <ClInclude Include=\"..\\..\\..\\..\\include\\jemalloc\\internal\\ql.h\" />\n    <ClInclude Include=\"..\\..\\..\\..\\include\\jemalloc\\internal\\qr.h\" />\n    <ClInclude Include=\"..\\..\\..\\..\\include\\jemalloc\\internal\\quarantine.h\" />\n    <ClInclude Include=\"..\\..\\..\\..\\include\\jemalloc\\internal\\rb.h\" />\n    <ClInclude Include=\"..\\..\\..\\..\\include\\jemalloc\\internal\\rtree.h\" />\n    <ClInclude Include=\"..\\..\\..\\..\\include\\jemalloc\\internal\\size_classes.h\" />\n    <ClInclude Include=\"..\\..\\..\\..\\include\\jemalloc\\internal\\stats.h\" />\n    <ClInclude Include=\"..\\..\\..\\..\\include\\jemalloc\\internal\\tcache.h\" />\n    <ClInclude Include=\"..\\..\\..\\..\\include\\jemalloc\\internal\\ticker.h\" />\n    <ClInclude Include=\"..\\..\\..\\..\\include\\jemalloc\\internal\\tsd.h\" />\n    <ClInclude Include=\"..\\..\\..\\..\\include\\jemalloc\\internal\\util.h\" />\n    <ClInclude Include=\"..\\..\\..\\..\\include\\jemalloc\\internal\\valgrind.h\" />\n    <ClInclude Include=\"..\\..\\..\\..\\include\\jemalloc\\jemalloc.h\" />\n    <ClInclude Include=\"..\\..\\..\\..\\include\\jemalloc\\jemalloc_defs.h\" />\n    <ClInclude Include=\"..\\..\\..\\..\\include\\jemalloc\\jemalloc_macros.h\" />\n    <ClInclude Include=\"..\\..\\..\\..\\include\\jemalloc\\jemalloc_mangle.h\" />\n    <ClInclude Include=\"..\\..\\..\\..\\include\\jemalloc\\jemalloc_protos.h\" />\n    <ClInclude Include=\"..\\..\\..\\..\\include\\jemalloc\\jemalloc_protos_jet.h\" />\n    <ClInclude Include=\"..\\..\\..\\..\\include\\jemalloc\\jemalloc_rename.h\" />\n    <ClInclude Include=\"..\\..\\..\\..\\include\\jemalloc\\jemalloc_typedefs.h\" />\n    <ClInclude Include=\"..\\..\\..\\..\\include\\msvc_compat\\C99\\stdbool.h\" />\n    <ClInclude Include=\"..\\..\\..\\..\\include\\msvc_compat\\C99\\stdint.h\" />\n    <ClInclude Include=\"..\\..\\..\\..\\include\\msvc_compat\\strings.h\" />\n    <ClInclude Include=\"..\\..\\..\\..\\include\\msvc_compat\\windows_extra.h\" />\n  </ItemGroup>\n  <ItemGroup>\n    <ClCompile Include=\"..\\..\\..\\..\\src\\arena.c\" />\n    <ClCompile Include=\"..\\..\\..\\..\\src\\atomic.c\" />\n    <ClCompile Include=\"..\\..\\..\\..\\src\\base.c\" />\n    <ClCompile Include=\"..\\..\\..\\..\\src\\bitmap.c\" />\n    <ClCompile Include=\"..\\..\\..\\..\\src\\chunk.c\" />\n    <ClCompile Include=\"..\\..\\..\\..\\src\\chunk_dss.c\" />\n    <ClCompile Include=\"..\\..\\..\\..\\src\\chunk_mmap.c\" />\n    <ClCompile Include=\"..\\..\\..\\..\\src\\ckh.c\" />\n    <ClCompile Include=\"..\\..\\..\\..\\src\\ctl.c\" />\n    <ClCompile Include=\"..\\..\\..\\..\\src\\extent.c\" />\n    <ClCompile Include=\"..\\..\\..\\..\\src\\hash.c\" />\n    <ClCompile Include=\"..\\..\\..\\..\\src\\huge.c\" />\n    <ClCompile Include=\"..\\..\\..\\..\\src\\jemalloc.c\" />\n    <ClCompile Include=\"..\\..\\..\\..\\src\\mb.c\" />\n    <ClCompile Include=\"..\\..\\..\\..\\src\\mutex.c\" />\n    <ClCompile Include=\"..\\..\\..\\..\\src\\nstime.c\" />\n    <ClCompile Include=\"..\\..\\..\\..\\src\\pages.c\" />\n    <ClCompile Include=\"..\\..\\..\\..\\src\\prng.c\" />\n    <ClCompile Include=\"..\\..\\..\\..\\src\\prof.c\" />\n    <ClCompile Include=\"..\\..\\..\\..\\src\\quarantine.c\" />\n    <ClCompile Include=\"..\\..\\..\\..\\src\\rtree.c\" />\n    <ClCompile Include=\"..\\..\\..\\..\\src\\stats.c\" />\n    <ClCompile Include=\"..\\..\\..\\..\\src\\tcache.c\" />\n    <ClCompile Include=\"..\\..\\..\\..\\src\\ticker.c\" />\n    <ClCompile Include=\"..\\..\\..\\..\\src\\tsd.c\" />\n    <ClCompile Include=\"..\\..\\..\\..\\src\\util.c\" />\n  </ItemGroup>\n  <PropertyGroup Label=\"Globals\">\n    <ProjectGuid>{8D6BB292-9E1C-413D-9F98-4864BDC1514A}</ProjectGuid>\n    <Keyword>Win32Proj</Keyword>\n    <RootNamespace>jemalloc</RootNamespace>\n    <WindowsTargetPlatformVersion>8.1</WindowsTargetPlatformVersion>\n  </PropertyGroup>\n  <Import Project=\"$(VCTargetsPath)\\Microsoft.Cpp.Default.props\" />\n  <PropertyGroup Condition=\"'$(Configuration)|$(Platform)'=='Debug|Win32'\" Label=\"Configuration\">\n    <ConfigurationType>DynamicLibrary</ConfigurationType>\n    <UseDebugLibraries>true</UseDebugLibraries>\n    <PlatformToolset>v140</PlatformToolset>\n    <CharacterSet>MultiByte</CharacterSet>\n  </PropertyGroup>\n  <PropertyGroup Condition=\"'$(Configuration)|$(Platform)'=='Debug-static|Win32'\" Label=\"Configuration\">\n    <ConfigurationType>StaticLibrary</ConfigurationType>\n    <UseDebugLibraries>true</UseDebugLibraries>\n    <PlatformToolset>v140</PlatformToolset>\n    <CharacterSet>MultiByte</CharacterSet>\n  </PropertyGroup>\n  <PropertyGroup Condition=\"'$(Configuration)|$(Platform)'=='Release|Win32'\" Label=\"Configuration\">\n    <ConfigurationType>DynamicLibrary</ConfigurationType>\n    <UseDebugLibraries>false</UseDebugLibraries>\n    <PlatformToolset>v140</PlatformToolset>\n    <WholeProgramOptimization>true</WholeProgramOptimization>\n    <CharacterSet>MultiByte</CharacterSet>\n  </PropertyGroup>\n  <PropertyGroup Condition=\"'$(Configuration)|$(Platform)'=='Release-static|Win32'\" Label=\"Configuration\">\n    <ConfigurationType>StaticLibrary</ConfigurationType>\n    <UseDebugLibraries>false</UseDebugLibraries>\n    <PlatformToolset>v140</PlatformToolset>\n    <WholeProgramOptimization>true</WholeProgramOptimization>\n    <CharacterSet>MultiByte</CharacterSet>\n  </PropertyGroup>\n  <PropertyGroup Condition=\"'$(Configuration)|$(Platform)'=='Debug|x64'\" Label=\"Configuration\">\n    <ConfigurationType>DynamicLibrary</ConfigurationType>\n    <UseDebugLibraries>true</UseDebugLibraries>\n    <PlatformToolset>v140</PlatformToolset>\n    <CharacterSet>MultiByte</CharacterSet>\n  </PropertyGroup>\n  <PropertyGroup Condition=\"'$(Configuration)|$(Platform)'=='Debug-static|x64'\" Label=\"Configuration\">\n    <ConfigurationType>StaticLibrary</ConfigurationType>\n    <UseDebugLibraries>true</UseDebugLibraries>\n    <PlatformToolset>v140</PlatformToolset>\n    <CharacterSet>MultiByte</CharacterSet>\n  </PropertyGroup>\n  <PropertyGroup Condition=\"'$(Configuration)|$(Platform)'=='Release|x64'\" Label=\"Configuration\">\n    <ConfigurationType>DynamicLibrary</ConfigurationType>\n    <UseDebugLibraries>false</UseDebugLibraries>\n    <PlatformToolset>v140</PlatformToolset>\n    <WholeProgramOptimization>true</WholeProgramOptimization>\n    <CharacterSet>MultiByte</CharacterSet>\n  </PropertyGroup>\n  <PropertyGroup Condition=\"'$(Configuration)|$(Platform)'=='Release-static|x64'\" Label=\"Configuration\">\n    <ConfigurationType>StaticLibrary</ConfigurationType>\n    <UseDebugLibraries>false</UseDebugLibraries>\n    <PlatformToolset>v140</PlatformToolset>\n    <WholeProgramOptimization>true</WholeProgramOptimization>\n    <CharacterSet>MultiByte</CharacterSet>\n  </PropertyGroup>\n  <Import Project=\"$(VCTargetsPath)\\Microsoft.Cpp.props\" />\n  <ImportGroup Label=\"ExtensionSettings\">\n  </ImportGroup>\n  <ImportGroup Label=\"Shared\">\n  </ImportGroup>\n  <ImportGroup Label=\"PropertySheets\" Condition=\"'$(Configuration)|$(Platform)'=='Debug|Win32'\">\n    <Import Project=\"$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props\" Condition=\"exists('$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props')\" Label=\"LocalAppDataPlatform\" />\n  </ImportGroup>\n  <ImportGroup Condition=\"'$(Configuration)|$(Platform)'=='Debug-static|Win32'\" Label=\"PropertySheets\">\n    <Import Project=\"$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props\" Condition=\"exists('$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props')\" Label=\"LocalAppDataPlatform\" />\n  </ImportGroup>\n  <ImportGroup Label=\"PropertySheets\" Condition=\"'$(Configuration)|$(Platform)'=='Release|Win32'\">\n    <Import Project=\"$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props\" Condition=\"exists('$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props')\" Label=\"LocalAppDataPlatform\" />\n  </ImportGroup>\n  <ImportGroup Condition=\"'$(Configuration)|$(Platform)'=='Release-static|Win32'\" Label=\"PropertySheets\">\n    <Import Project=\"$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props\" Condition=\"exists('$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props')\" Label=\"LocalAppDataPlatform\" />\n  </ImportGroup>\n  <ImportGroup Label=\"PropertySheets\" Condition=\"'$(Configuration)|$(Platform)'=='Debug|x64'\">\n    <Import Project=\"$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props\" Condition=\"exists('$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props')\" Label=\"LocalAppDataPlatform\" />\n  </ImportGroup>\n  <ImportGroup Condition=\"'$(Configuration)|$(Platform)'=='Debug-static|x64'\" Label=\"PropertySheets\">\n    <Import Project=\"$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props\" Condition=\"exists('$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props')\" Label=\"LocalAppDataPlatform\" />\n  </ImportGroup>\n  <ImportGroup Label=\"PropertySheets\" Condition=\"'$(Configuration)|$(Platform)'=='Release|x64'\">\n    <Import Project=\"$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props\" Condition=\"exists('$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props')\" Label=\"LocalAppDataPlatform\" />\n  </ImportGroup>\n  <ImportGroup Condition=\"'$(Configuration)|$(Platform)'=='Release-static|x64'\" Label=\"PropertySheets\">\n    <Import Project=\"$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props\" Condition=\"exists('$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props')\" Label=\"LocalAppDataPlatform\" />\n  </ImportGroup>\n  <PropertyGroup Label=\"UserMacros\" />\n  <PropertyGroup Condition=\"'$(Configuration)|$(Platform)'=='Debug|Win32'\">\n    <OutDir>$(SolutionDir)$(Platform)\\$(Configuration)\\</OutDir>\n    <IntDir>$(Platform)\\$(Configuration)\\</IntDir>\n    <TargetName>$(ProjectName)d</TargetName>\n  </PropertyGroup>\n  <PropertyGroup Condition=\"'$(Configuration)|$(Platform)'=='Debug-static|Win32'\">\n    <OutDir>$(SolutionDir)$(Platform)\\$(Configuration)\\</OutDir>\n    <IntDir>$(Platform)\\$(Configuration)\\</IntDir>\n    <TargetName>$(ProjectName)-$(PlatformToolset)-$(Configuration)</TargetName>\n  </PropertyGroup>\n  <PropertyGroup Condition=\"'$(Configuration)|$(Platform)'=='Release|Win32'\">\n    <OutDir>$(SolutionDir)$(Platform)\\$(Configuration)\\</OutDir>\n    <IntDir>$(Platform)\\$(Configuration)\\</IntDir>\n  </PropertyGroup>\n  <PropertyGroup Condition=\"'$(Configuration)|$(Platform)'=='Release-static|Win32'\">\n    <OutDir>$(SolutionDir)$(Platform)\\$(Configuration)\\</OutDir>\n    <IntDir>$(Platform)\\$(Configuration)\\</IntDir>\n    <TargetName>$(ProjectName)-$(PlatformToolset)-$(Configuration)</TargetName>\n  </PropertyGroup>\n  <PropertyGroup Condition=\"'$(Configuration)|$(Platform)'=='Debug|x64'\">\n    <OutDir>$(SolutionDir)$(Platform)\\$(Configuration)\\</OutDir>\n    <IntDir>$(Platform)\\$(Configuration)\\</IntDir>\n    <TargetName>$(ProjectName)d</TargetName>\n  </PropertyGroup>\n  <PropertyGroup Condition=\"'$(Configuration)|$(Platform)'=='Debug-static|x64'\">\n    <OutDir>$(SolutionDir)$(Platform)\\$(Configuration)\\</OutDir>\n    <IntDir>$(Platform)\\$(Configuration)\\</IntDir>\n    <TargetName>$(ProjectName)-vc$(PlatformToolsetVersion)-$(Configuration)</TargetName>\n  </PropertyGroup>\n  <PropertyGroup Condition=\"'$(Configuration)|$(Platform)'=='Release|x64'\">\n    <OutDir>$(SolutionDir)$(Platform)\\$(Configuration)\\</OutDir>\n    <IntDir>$(Platform)\\$(Configuration)\\</IntDir>\n  </PropertyGroup>\n  <PropertyGroup Condition=\"'$(Configuration)|$(Platform)'=='Release-static|x64'\">\n    <OutDir>$(SolutionDir)$(Platform)\\$(Configuration)\\</OutDir>\n    <IntDir>$(Platform)\\$(Configuration)\\</IntDir>\n    <TargetName>$(ProjectName)-vc$(PlatformToolsetVersion)-$(Configuration)</TargetName>\n  </PropertyGroup>\n  <ItemDefinitionGroup Condition=\"'$(Configuration)|$(Platform)'=='Debug|Win32'\">\n    <ClCompile>\n      <PrecompiledHeader>\n      </PrecompiledHeader>\n      <WarningLevel>Level3</WarningLevel>\n      <Optimization>Disabled</Optimization>\n      <PreprocessorDefinitions>_REENTRANT;_WINDLL;DLLEXPORT;JEMALLOC_DEBUG;_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>\n      <AdditionalIncludeDirectories>..\\..\\..\\..\\include;..\\..\\..\\..\\include\\msvc_compat;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\n      <DisableSpecificWarnings>4090;4146;4267;4334</DisableSpecificWarnings>\n      <ProgramDataBaseFileName>$(OutputPath)$(TargetName).pdb</ProgramDataBaseFileName>\n    </ClCompile>\n    <Link>\n      <SubSystem>Windows</SubSystem>\n      <GenerateDebugInformation>true</GenerateDebugInformation>\n    </Link>\n  </ItemDefinitionGroup>\n  <ItemDefinitionGroup Condition=\"'$(Configuration)|$(Platform)'=='Debug-static|Win32'\">\n    <ClCompile>\n      <PrecompiledHeader>\n      </PrecompiledHeader>\n      <WarningLevel>Level3</WarningLevel>\n      <Optimization>Disabled</Optimization>\n      <PreprocessorDefinitions>JEMALLOC_DEBUG;_REENTRANT;JEMALLOC_EXPORT=;_DEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>\n      <AdditionalIncludeDirectories>..\\..\\..\\..\\include;..\\..\\..\\..\\include\\msvc_compat;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\n      <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>\n      <DisableSpecificWarnings>4090;4146;4267;4334</DisableSpecificWarnings>\n      <ProgramDataBaseFileName>$(OutputPath)$(TargetName).pdb</ProgramDataBaseFileName>\n    </ClCompile>\n    <Link>\n      <SubSystem>Windows</SubSystem>\n      <GenerateDebugInformation>true</GenerateDebugInformation>\n    </Link>\n  </ItemDefinitionGroup>\n  <ItemDefinitionGroup Condition=\"'$(Configuration)|$(Platform)'=='Debug|x64'\">\n    <ClCompile>\n      <PrecompiledHeader>\n      </PrecompiledHeader>\n      <WarningLevel>Level3</WarningLevel>\n      <Optimization>Disabled</Optimization>\n      <PreprocessorDefinitions>_REENTRANT;_WINDLL;DLLEXPORT;JEMALLOC_DEBUG;_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>\n      <AdditionalIncludeDirectories>..\\..\\..\\..\\include;..\\..\\..\\..\\include\\msvc_compat;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\n      <DisableSpecificWarnings>4090;4146;4267;4334</DisableSpecificWarnings>\n      <ProgramDataBaseFileName>$(OutputPath)$(TargetName).pdb</ProgramDataBaseFileName>\n    </ClCompile>\n    <Link>\n      <SubSystem>Windows</SubSystem>\n      <GenerateDebugInformation>true</GenerateDebugInformation>\n    </Link>\n  </ItemDefinitionGroup>\n  <ItemDefinitionGroup Condition=\"'$(Configuration)|$(Platform)'=='Debug-static|x64'\">\n    <ClCompile>\n      <PrecompiledHeader>\n      </PrecompiledHeader>\n      <WarningLevel>Level3</WarningLevel>\n      <Optimization>Disabled</Optimization>\n      <PreprocessorDefinitions>JEMALLOC_DEBUG;_REENTRANT;JEMALLOC_EXPORT=;_DEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>\n      <AdditionalIncludeDirectories>..\\..\\..\\..\\include;..\\..\\..\\..\\include\\msvc_compat;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\n      <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>\n      <DisableSpecificWarnings>4090;4146;4267;4334</DisableSpecificWarnings>\n      <DebugInformationFormat>OldStyle</DebugInformationFormat>\n      <MinimalRebuild>false</MinimalRebuild>\n    </ClCompile>\n    <Link>\n      <SubSystem>Windows</SubSystem>\n      <GenerateDebugInformation>true</GenerateDebugInformation>\n    </Link>\n  </ItemDefinitionGroup>\n  <ItemDefinitionGroup Condition=\"'$(Configuration)|$(Platform)'=='Release|Win32'\">\n    <ClCompile>\n      <WarningLevel>Level3</WarningLevel>\n      <PrecompiledHeader>\n      </PrecompiledHeader>\n      <Optimization>MaxSpeed</Optimization>\n      <FunctionLevelLinking>true</FunctionLevelLinking>\n      <IntrinsicFunctions>true</IntrinsicFunctions>\n      <PreprocessorDefinitions>_REENTRANT;_WINDLL;DLLEXPORT;NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>\n      <AdditionalIncludeDirectories>..\\..\\..\\..\\include;..\\..\\..\\..\\include\\msvc_compat;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\n      <DisableSpecificWarnings>4090;4146;4267;4334</DisableSpecificWarnings>\n      <ProgramDataBaseFileName>$(OutputPath)$(TargetName).pdb</ProgramDataBaseFileName>\n    </ClCompile>\n    <Link>\n      <SubSystem>Windows</SubSystem>\n      <GenerateDebugInformation>true</GenerateDebugInformation>\n      <EnableCOMDATFolding>true</EnableCOMDATFolding>\n      <OptimizeReferences>true</OptimizeReferences>\n    </Link>\n  </ItemDefinitionGroup>\n  <ItemDefinitionGroup Condition=\"'$(Configuration)|$(Platform)'=='Release-static|Win32'\">\n    <ClCompile>\n      <WarningLevel>Level3</WarningLevel>\n      <PrecompiledHeader>\n      </PrecompiledHeader>\n      <Optimization>MaxSpeed</Optimization>\n      <FunctionLevelLinking>true</FunctionLevelLinking>\n      <IntrinsicFunctions>true</IntrinsicFunctions>\n      <PreprocessorDefinitions>_REENTRANT;JEMALLOC_EXPORT=;NDEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>\n      <AdditionalIncludeDirectories>..\\..\\..\\..\\include;..\\..\\..\\..\\include\\msvc_compat;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\n      <RuntimeLibrary>MultiThreaded</RuntimeLibrary>\n      <DisableSpecificWarnings>4090;4146;4267;4334</DisableSpecificWarnings>\n      <ProgramDataBaseFileName>$(OutputPath)$(TargetName).pdb</ProgramDataBaseFileName>\n    </ClCompile>\n    <Link>\n      <SubSystem>Windows</SubSystem>\n      <GenerateDebugInformation>true</GenerateDebugInformation>\n      <EnableCOMDATFolding>true</EnableCOMDATFolding>\n      <OptimizeReferences>true</OptimizeReferences>\n    </Link>\n  </ItemDefinitionGroup>\n  <ItemDefinitionGroup Condition=\"'$(Configuration)|$(Platform)'=='Release|x64'\">\n    <ClCompile>\n      <WarningLevel>Level3</WarningLevel>\n      <PrecompiledHeader>\n      </PrecompiledHeader>\n      <Optimization>MaxSpeed</Optimization>\n      <FunctionLevelLinking>true</FunctionLevelLinking>\n      <IntrinsicFunctions>true</IntrinsicFunctions>\n      <AdditionalIncludeDirectories>..\\..\\..\\..\\include;..\\..\\..\\..\\include\\msvc_compat;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\n      <PreprocessorDefinitions>_REENTRANT;_WINDLL;DLLEXPORT;NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>\n      <DisableSpecificWarnings>4090;4146;4267;4334</DisableSpecificWarnings>\n      <ProgramDataBaseFileName>$(OutputPath)$(TargetName).pdb</ProgramDataBaseFileName>\n    </ClCompile>\n    <Link>\n      <SubSystem>Windows</SubSystem>\n      <GenerateDebugInformation>true</GenerateDebugInformation>\n      <EnableCOMDATFolding>true</EnableCOMDATFolding>\n      <OptimizeReferences>true</OptimizeReferences>\n    </Link>\n  </ItemDefinitionGroup>\n  <ItemDefinitionGroup Condition=\"'$(Configuration)|$(Platform)'=='Release-static|x64'\">\n    <ClCompile>\n      <WarningLevel>Level3</WarningLevel>\n      <PrecompiledHeader>\n      </PrecompiledHeader>\n      <Optimization>MaxSpeed</Optimization>\n      <FunctionLevelLinking>true</FunctionLevelLinking>\n      <IntrinsicFunctions>true</IntrinsicFunctions>\n      <PreprocessorDefinitions>_REENTRANT;JEMALLOC_EXPORT=;NDEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>\n      <AdditionalIncludeDirectories>..\\..\\..\\..\\include;..\\..\\..\\..\\include\\msvc_compat;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\n      <RuntimeLibrary>MultiThreaded</RuntimeLibrary>\n      <DisableSpecificWarnings>4090;4146;4267;4334</DisableSpecificWarnings>\n      <DebugInformationFormat>OldStyle</DebugInformationFormat>\n    </ClCompile>\n    <Link>\n      <SubSystem>Windows</SubSystem>\n      <GenerateDebugInformation>true</GenerateDebugInformation>\n      <EnableCOMDATFolding>true</EnableCOMDATFolding>\n      <OptimizeReferences>true</OptimizeReferences>\n    </Link>\n  </ItemDefinitionGroup>\n  <Import Project=\"$(VCTargetsPath)\\Microsoft.Cpp.targets\" />\n  <ImportGroup Label=\"ExtensionTargets\">\n  </ImportGroup>\n</Project>"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/deps/jemalloc/msvc/projects/vc2015/jemalloc/jemalloc.vcxproj.filters",
    "content": "﻿<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<Project ToolsVersion=\"4.0\" xmlns=\"http://schemas.microsoft.com/developer/msbuild/2003\">\n  <ItemGroup>\n    <Filter Include=\"Source Files\">\n      <UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>\n      <Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>\n    </Filter>\n    <Filter Include=\"Header Files\">\n      <UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>\n      <Extensions>h;hh;hpp;hxx;hm;inl;inc;xsd</Extensions>\n    </Filter>\n    <Filter Include=\"Header Files\\internal\">\n      <UniqueIdentifier>{5697dfa3-16cf-4932-b428-6e0ec6e9f98e}</UniqueIdentifier>\n    </Filter>\n    <Filter Include=\"Header Files\\msvc_compat\">\n      <UniqueIdentifier>{0cbd2ca6-42a7-4f82-8517-d7e7a14fd986}</UniqueIdentifier>\n    </Filter>\n    <Filter Include=\"Header Files\\msvc_compat\\C99\">\n      <UniqueIdentifier>{0abe6f30-49b5-46dd-8aca-6e33363fa52c}</UniqueIdentifier>\n    </Filter>\n  </ItemGroup>\n  <ItemGroup>\n    <ClInclude Include=\"..\\..\\..\\..\\include\\jemalloc\\jemalloc.h\">\n      <Filter>Header Files</Filter>\n    </ClInclude>\n    <ClInclude Include=\"..\\..\\..\\..\\include\\jemalloc\\jemalloc_defs.h\">\n      <Filter>Header Files</Filter>\n    </ClInclude>\n    <ClInclude Include=\"..\\..\\..\\..\\include\\jemalloc\\jemalloc_macros.h\">\n      <Filter>Header Files</Filter>\n    </ClInclude>\n    <ClInclude Include=\"..\\..\\..\\..\\include\\jemalloc\\jemalloc_mangle.h\">\n      <Filter>Header Files</Filter>\n    </ClInclude>\n    <ClInclude Include=\"..\\..\\..\\..\\include\\jemalloc\\jemalloc_protos.h\">\n      <Filter>Header Files</Filter>\n    </ClInclude>\n    <ClInclude Include=\"..\\..\\..\\..\\include\\jemalloc\\jemalloc_protos_jet.h\">\n      <Filter>Header Files</Filter>\n    </ClInclude>\n    <ClInclude Include=\"..\\..\\..\\..\\include\\jemalloc\\jemalloc_rename.h\">\n      <Filter>Header Files</Filter>\n    </ClInclude>\n    <ClInclude Include=\"..\\..\\..\\..\\include\\jemalloc\\jemalloc_typedefs.h\">\n      <Filter>Header Files</Filter>\n    </ClInclude>\n    <ClInclude Include=\"..\\..\\..\\..\\include\\jemalloc\\internal\\arena.h\">\n      <Filter>Header Files\\internal</Filter>\n    </ClInclude>\n    <ClInclude Include=\"..\\..\\..\\..\\include\\jemalloc\\internal\\assert.h\">\n      <Filter>Header Files\\internal</Filter>\n    </ClInclude>\n    <ClInclude Include=\"..\\..\\..\\..\\include\\jemalloc\\internal\\atomic.h\">\n      <Filter>Header Files\\internal</Filter>\n    </ClInclude>\n    <ClInclude Include=\"..\\..\\..\\..\\include\\jemalloc\\internal\\base.h\">\n      <Filter>Header Files\\internal</Filter>\n    </ClInclude>\n    <ClInclude Include=\"..\\..\\..\\..\\include\\jemalloc\\internal\\bitmap.h\">\n      <Filter>Header Files\\internal</Filter>\n    </ClInclude>\n    <ClInclude Include=\"..\\..\\..\\..\\include\\jemalloc\\internal\\chunk.h\">\n      <Filter>Header Files\\internal</Filter>\n    </ClInclude>\n    <ClInclude Include=\"..\\..\\..\\..\\include\\jemalloc\\internal\\chunk_dss.h\">\n      <Filter>Header Files\\internal</Filter>\n    </ClInclude>\n    <ClInclude Include=\"..\\..\\..\\..\\include\\jemalloc\\internal\\chunk_mmap.h\">\n      <Filter>Header Files\\internal</Filter>\n    </ClInclude>\n    <ClInclude Include=\"..\\..\\..\\..\\include\\jemalloc\\internal\\ckh.h\">\n      <Filter>Header Files\\internal</Filter>\n    </ClInclude>\n    <ClInclude Include=\"..\\..\\..\\..\\include\\jemalloc\\internal\\ctl.h\">\n      <Filter>Header Files\\internal</Filter>\n    </ClInclude>\n    <ClInclude Include=\"..\\..\\..\\..\\include\\jemalloc\\internal\\extent.h\">\n      <Filter>Header Files\\internal</Filter>\n    </ClInclude>\n    <ClInclude Include=\"..\\..\\..\\..\\include\\jemalloc\\internal\\hash.h\">\n      <Filter>Header Files\\internal</Filter>\n    </ClInclude>\n    <ClInclude Include=\"..\\..\\..\\..\\include\\jemalloc\\internal\\huge.h\">\n      <Filter>Header Files\\internal</Filter>\n    </ClInclude>\n    <ClInclude Include=\"..\\..\\..\\..\\include\\jemalloc\\internal\\jemalloc_internal.h\">\n      <Filter>Header Files\\internal</Filter>\n    </ClInclude>\n    <ClInclude Include=\"..\\..\\..\\..\\include\\jemalloc\\internal\\jemalloc_internal_decls.h\">\n      <Filter>Header Files\\internal</Filter>\n    </ClInclude>\n    <ClInclude Include=\"..\\..\\..\\..\\include\\jemalloc\\internal\\jemalloc_internal_defs.h\">\n      <Filter>Header Files\\internal</Filter>\n    </ClInclude>\n    <ClInclude Include=\"..\\..\\..\\..\\include\\jemalloc\\internal\\jemalloc_internal_macros.h\">\n      <Filter>Header Files\\internal</Filter>\n    </ClInclude>\n    <ClInclude Include=\"..\\..\\..\\..\\include\\jemalloc\\internal\\mb.h\">\n      <Filter>Header Files\\internal</Filter>\n    </ClInclude>\n    <ClInclude Include=\"..\\..\\..\\..\\include\\jemalloc\\internal\\mutex.h\">\n      <Filter>Header Files\\internal</Filter>\n    </ClInclude>\n    <ClInclude Include=\"..\\..\\..\\..\\include\\jemalloc\\internal\\nstime.h\">\n      <Filter>Header Files\\internal</Filter>\n    </ClInclude>\n    <ClInclude Include=\"..\\..\\..\\..\\include\\jemalloc\\internal\\pages.h\">\n      <Filter>Header Files\\internal</Filter>\n    </ClInclude>\n    <ClInclude Include=\"..\\..\\..\\..\\include\\jemalloc\\internal\\ph.h\">\n      <Filter>Header Files\\internal</Filter>\n    </ClInclude>\n    <ClInclude Include=\"..\\..\\..\\..\\include\\jemalloc\\internal\\private_namespace.h\">\n      <Filter>Header Files\\internal</Filter>\n    </ClInclude>\n    <ClInclude Include=\"..\\..\\..\\..\\include\\jemalloc\\internal\\private_unnamespace.h\">\n      <Filter>Header Files\\internal</Filter>\n    </ClInclude>\n    <ClInclude Include=\"..\\..\\..\\..\\include\\jemalloc\\internal\\prng.h\">\n      <Filter>Header Files\\internal</Filter>\n    </ClInclude>\n    <ClInclude Include=\"..\\..\\..\\..\\include\\jemalloc\\internal\\prof.h\">\n      <Filter>Header Files\\internal</Filter>\n    </ClInclude>\n    <ClInclude Include=\"..\\..\\..\\..\\include\\jemalloc\\internal\\public_namespace.h\">\n      <Filter>Header Files\\internal</Filter>\n    </ClInclude>\n    <ClInclude Include=\"..\\..\\..\\..\\include\\jemalloc\\internal\\public_unnamespace.h\">\n      <Filter>Header Files\\internal</Filter>\n    </ClInclude>\n    <ClInclude Include=\"..\\..\\..\\..\\include\\jemalloc\\internal\\ql.h\">\n      <Filter>Header Files\\internal</Filter>\n    </ClInclude>\n    <ClInclude Include=\"..\\..\\..\\..\\include\\jemalloc\\internal\\qr.h\">\n      <Filter>Header Files\\internal</Filter>\n    </ClInclude>\n    <ClInclude Include=\"..\\..\\..\\..\\include\\jemalloc\\internal\\quarantine.h\">\n      <Filter>Header Files\\internal</Filter>\n    </ClInclude>\n    <ClInclude Include=\"..\\..\\..\\..\\include\\jemalloc\\internal\\rb.h\">\n      <Filter>Header Files\\internal</Filter>\n    </ClInclude>\n    <ClInclude Include=\"..\\..\\..\\..\\include\\jemalloc\\internal\\rtree.h\">\n      <Filter>Header Files\\internal</Filter>\n    </ClInclude>\n    <ClInclude Include=\"..\\..\\..\\..\\include\\jemalloc\\internal\\size_classes.h\">\n      <Filter>Header Files\\internal</Filter>\n    </ClInclude>\n    <ClInclude Include=\"..\\..\\..\\..\\include\\jemalloc\\internal\\stats.h\">\n      <Filter>Header Files\\internal</Filter>\n    </ClInclude>\n    <ClInclude Include=\"..\\..\\..\\..\\include\\jemalloc\\internal\\tcache.h\">\n      <Filter>Header Files\\internal</Filter>\n    </ClInclude>\n    <ClInclude Include=\"..\\..\\..\\..\\include\\jemalloc\\internal\\ticker.h\">\n      <Filter>Header Files\\internal</Filter>\n    </ClInclude>\n    <ClInclude Include=\"..\\..\\..\\..\\include\\jemalloc\\internal\\tsd.h\">\n      <Filter>Header Files\\internal</Filter>\n    </ClInclude>\n    <ClInclude Include=\"..\\..\\..\\..\\include\\jemalloc\\internal\\util.h\">\n      <Filter>Header Files\\internal</Filter>\n    </ClInclude>\n    <ClInclude Include=\"..\\..\\..\\..\\include\\jemalloc\\internal\\valgrind.h\">\n      <Filter>Header Files\\internal</Filter>\n    </ClInclude>\n    <ClInclude Include=\"..\\..\\..\\..\\include\\msvc_compat\\strings.h\">\n      <Filter>Header Files\\msvc_compat</Filter>\n    </ClInclude>\n    <ClInclude Include=\"..\\..\\..\\..\\include\\msvc_compat\\windows_extra.h\">\n      <Filter>Header Files\\msvc_compat</Filter>\n    </ClInclude>\n    <ClInclude Include=\"..\\..\\..\\..\\include\\msvc_compat\\C99\\stdbool.h\">\n      <Filter>Header Files\\msvc_compat\\C99</Filter>\n    </ClInclude>\n    <ClInclude Include=\"..\\..\\..\\..\\include\\msvc_compat\\C99\\stdint.h\">\n      <Filter>Header Files\\msvc_compat\\C99</Filter>\n    </ClInclude>\n  </ItemGroup>\n  <ItemGroup>\n    <ClCompile Include=\"..\\..\\..\\..\\src\\arena.c\">\n      <Filter>Source Files</Filter>\n    </ClCompile>\n    <ClCompile Include=\"..\\..\\..\\..\\src\\atomic.c\">\n      <Filter>Source Files</Filter>\n    </ClCompile>\n    <ClCompile Include=\"..\\..\\..\\..\\src\\base.c\">\n      <Filter>Source Files</Filter>\n    </ClCompile>\n    <ClCompile Include=\"..\\..\\..\\..\\src\\bitmap.c\">\n      <Filter>Source Files</Filter>\n    </ClCompile>\n    <ClCompile Include=\"..\\..\\..\\..\\src\\chunk.c\">\n      <Filter>Source Files</Filter>\n    </ClCompile>\n    <ClCompile Include=\"..\\..\\..\\..\\src\\chunk_dss.c\">\n      <Filter>Source Files</Filter>\n    </ClCompile>\n    <ClCompile Include=\"..\\..\\..\\..\\src\\chunk_mmap.c\">\n      <Filter>Source Files</Filter>\n    </ClCompile>\n    <ClCompile Include=\"..\\..\\..\\..\\src\\ckh.c\">\n      <Filter>Source Files</Filter>\n    </ClCompile>\n    <ClCompile Include=\"..\\..\\..\\..\\src\\ctl.c\">\n      <Filter>Source Files</Filter>\n    </ClCompile>\n    <ClCompile Include=\"..\\..\\..\\..\\src\\extent.c\">\n      <Filter>Source Files</Filter>\n    </ClCompile>\n    <ClCompile Include=\"..\\..\\..\\..\\src\\hash.c\">\n      <Filter>Source Files</Filter>\n    </ClCompile>\n    <ClCompile Include=\"..\\..\\..\\..\\src\\huge.c\">\n      <Filter>Source Files</Filter>\n    </ClCompile>\n    <ClCompile Include=\"..\\..\\..\\..\\src\\jemalloc.c\">\n      <Filter>Source Files</Filter>\n    </ClCompile>\n    <ClCompile Include=\"..\\..\\..\\..\\src\\mb.c\">\n      <Filter>Source Files</Filter>\n    </ClCompile>\n    <ClCompile Include=\"..\\..\\..\\..\\src\\mutex.c\">\n      <Filter>Source Files</Filter>\n    </ClCompile>\n    <ClCompile Include=\"..\\..\\..\\..\\src\\nstime.c\">\n      <Filter>Source Files</Filter>\n    </ClCompile>\n    <ClCompile Include=\"..\\..\\..\\..\\src\\pages.c\">\n      <Filter>Source Files</Filter>\n    </ClCompile>\n    <ClCompile Include=\"..\\..\\..\\..\\src\\prng.c\">\n      <Filter>Source Files</Filter>\n    </ClCompile>\n    <ClCompile Include=\"..\\..\\..\\..\\src\\prof.c\">\n      <Filter>Source Files</Filter>\n    </ClCompile>\n    <ClCompile Include=\"..\\..\\..\\..\\src\\quarantine.c\">\n      <Filter>Source Files</Filter>\n    </ClCompile>\n    <ClCompile Include=\"..\\..\\..\\..\\src\\rtree.c\">\n      <Filter>Source Files</Filter>\n    </ClCompile>\n    <ClCompile Include=\"..\\..\\..\\..\\src\\stats.c\">\n      <Filter>Source Files</Filter>\n    </ClCompile>\n    <ClCompile Include=\"..\\..\\..\\..\\src\\tcache.c\">\n      <Filter>Source Files</Filter>\n    </ClCompile>\n    <ClCompile Include=\"..\\..\\..\\..\\src\\ticker.c\">\n      <Filter>Source Files</Filter>\n    </ClCompile>\n    <ClCompile Include=\"..\\..\\..\\..\\src\\tsd.c\">\n      <Filter>Source Files</Filter>\n    </ClCompile>\n    <ClCompile Include=\"..\\..\\..\\..\\src\\util.c\">\n      <Filter>Source Files</Filter>\n    </ClCompile>\n  </ItemGroup>\n</Project>"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/deps/jemalloc/msvc/projects/vc2015/test_threads/test_threads.cpp",
    "content": "// jemalloc C++ threaded test\n// Author: Rustam Abdullaev\n// Public Domain\n\n#include <atomic>\n#include <functional>\n#include <future>\n#include <random>\n#include <thread>\n#include <vector>\n#include <stdio.h>\n#include <jemalloc/jemalloc.h>\n\nusing std::vector;\nusing std::thread;\nusing std::uniform_int_distribution;\nusing std::minstd_rand;\n\nint test_threads()\n{\n  je_malloc_conf = \"narenas:3\";\n  int narenas = 0;\n  size_t sz = sizeof(narenas);\n  je_mallctl(\"opt.narenas\", &narenas, &sz, NULL, 0);\n  if (narenas != 3) {\n    printf(\"Error: unexpected number of arenas: %d\\n\", narenas);\n    return 1;\n  }\n  static const int sizes[] = { 7, 16, 32, 60, 91, 100, 120, 144, 169, 199, 255, 400, 670, 900, 917, 1025, 3333, 5190, 13131, 49192, 99999, 123123, 255265, 2333111 };\n  static const int numSizes = (int)(sizeof(sizes) / sizeof(sizes[0]));\n  vector<thread> workers;\n  static const int numThreads = narenas + 1, numAllocsMax = 25, numIter1 = 50, numIter2 = 50;\n  je_malloc_stats_print(NULL, NULL, NULL);\n  size_t allocated1;\n  size_t sz1 = sizeof(allocated1);\n  je_mallctl(\"stats.active\", &allocated1, &sz1, NULL, 0);\n  printf(\"\\nPress Enter to start threads...\\n\");\n  getchar();\n  printf(\"Starting %d threads x %d x %d iterations...\\n\", numThreads, numIter1, numIter2);\n  for (int i = 0; i < numThreads; i++) {\n    workers.emplace_back([tid=i]() {\n      uniform_int_distribution<int> sizeDist(0, numSizes - 1);\n      minstd_rand rnd(tid * 17);\n      uint8_t* ptrs[numAllocsMax];\n      int ptrsz[numAllocsMax];\n      for (int i = 0; i < numIter1; ++i) {\n        thread t([&]() {\n          for (int i = 0; i < numIter2; ++i) {\n            const int numAllocs = numAllocsMax - sizeDist(rnd);\n            for (int j = 0; j < numAllocs; j += 64) {\n              const int x = sizeDist(rnd);\n              const int sz = sizes[x];\n              ptrsz[j] = sz;\n              ptrs[j] = (uint8_t*)je_malloc(sz);\n              if (!ptrs[j]) {\n                printf(\"Unable to allocate %d bytes in thread %d, iter %d, alloc %d. %d\\n\", sz, tid, i, j, x);\n                exit(1);\n              }\n              for (int k = 0; k < sz; k++)\n                ptrs[j][k] = tid + k;\n            }\n            for (int j = 0; j < numAllocs; j += 64) {\n              for (int k = 0, sz = ptrsz[j]; k < sz; k++)\n                if (ptrs[j][k] != (uint8_t)(tid + k)) {\n                  printf(\"Memory error in thread %d, iter %d, alloc %d @ %d : %02X!=%02X\\n\", tid, i, j, k, ptrs[j][k], (uint8_t)(tid + k));\n                  exit(1);\n                }\n              je_free(ptrs[j]);\n            }\n          }\n        });\n        t.join();\n      }\n    });\n  }\n  for (thread& t : workers) {\n    t.join();\n  }\n  je_malloc_stats_print(NULL, NULL, NULL);\n  size_t allocated2;\n  je_mallctl(\"stats.active\", &allocated2, &sz1, NULL, 0);\n  size_t leaked = allocated2 - allocated1;\n  printf(\"\\nDone. Leaked: %zd bytes\\n\", leaked);\n  bool failed = leaked > 65536; // in case C++ runtime allocated something (e.g. iostream locale or facet)\n  printf(\"\\nTest %s!\\n\", (failed ? \"FAILED\" : \"successful\"));\n  printf(\"\\nPress Enter to continue...\\n\");\n  getchar();\n  return failed ? 1 : 0;\n}\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/deps/jemalloc/msvc/projects/vc2015/test_threads/test_threads.h",
    "content": "#pragma once\n\nint test_threads();\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/deps/jemalloc/msvc/projects/vc2015/test_threads/test_threads.vcxproj",
    "content": "﻿<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<Project DefaultTargets=\"Build\" ToolsVersion=\"14.0\" xmlns=\"http://schemas.microsoft.com/developer/msbuild/2003\">\n  <ItemGroup Label=\"ProjectConfigurations\">\n    <ProjectConfiguration Include=\"Debug-static|Win32\">\n      <Configuration>Debug-static</Configuration>\n      <Platform>Win32</Platform>\n    </ProjectConfiguration>\n    <ProjectConfiguration Include=\"Debug-static|x64\">\n      <Configuration>Debug-static</Configuration>\n      <Platform>x64</Platform>\n    </ProjectConfiguration>\n    <ProjectConfiguration Include=\"Debug|Win32\">\n      <Configuration>Debug</Configuration>\n      <Platform>Win32</Platform>\n    </ProjectConfiguration>\n    <ProjectConfiguration Include=\"Release-static|Win32\">\n      <Configuration>Release-static</Configuration>\n      <Platform>Win32</Platform>\n    </ProjectConfiguration>\n    <ProjectConfiguration Include=\"Release-static|x64\">\n      <Configuration>Release-static</Configuration>\n      <Platform>x64</Platform>\n    </ProjectConfiguration>\n    <ProjectConfiguration Include=\"Release|Win32\">\n      <Configuration>Release</Configuration>\n      <Platform>Win32</Platform>\n    </ProjectConfiguration>\n    <ProjectConfiguration Include=\"Debug|x64\">\n      <Configuration>Debug</Configuration>\n      <Platform>x64</Platform>\n    </ProjectConfiguration>\n    <ProjectConfiguration Include=\"Release|x64\">\n      <Configuration>Release</Configuration>\n      <Platform>x64</Platform>\n    </ProjectConfiguration>\n  </ItemGroup>\n  <PropertyGroup Label=\"Globals\">\n    <ProjectGuid>{09028CFD-4EB7-491D-869C-0708DB97ED44}</ProjectGuid>\n    <Keyword>Win32Proj</Keyword>\n    <RootNamespace>test_threads</RootNamespace>\n    <WindowsTargetPlatformVersion>8.1</WindowsTargetPlatformVersion>\n  </PropertyGroup>\n  <Import Project=\"$(VCTargetsPath)\\Microsoft.Cpp.Default.props\" />\n  <PropertyGroup Condition=\"'$(Configuration)|$(Platform)'=='Debug|Win32'\" Label=\"Configuration\">\n    <ConfigurationType>Application</ConfigurationType>\n    <UseDebugLibraries>true</UseDebugLibraries>\n    <PlatformToolset>v140</PlatformToolset>\n    <CharacterSet>MultiByte</CharacterSet>\n  </PropertyGroup>\n  <PropertyGroup Condition=\"'$(Configuration)|$(Platform)'=='Debug-static|Win32'\" Label=\"Configuration\">\n    <ConfigurationType>Application</ConfigurationType>\n    <UseDebugLibraries>true</UseDebugLibraries>\n    <PlatformToolset>v140</PlatformToolset>\n    <CharacterSet>MultiByte</CharacterSet>\n  </PropertyGroup>\n  <PropertyGroup Condition=\"'$(Configuration)|$(Platform)'=='Release|Win32'\" Label=\"Configuration\">\n    <ConfigurationType>Application</ConfigurationType>\n    <UseDebugLibraries>false</UseDebugLibraries>\n    <PlatformToolset>v140</PlatformToolset>\n    <WholeProgramOptimization>true</WholeProgramOptimization>\n    <CharacterSet>MultiByte</CharacterSet>\n  </PropertyGroup>\n  <PropertyGroup Condition=\"'$(Configuration)|$(Platform)'=='Release-static|Win32'\" Label=\"Configuration\">\n    <ConfigurationType>Application</ConfigurationType>\n    <UseDebugLibraries>false</UseDebugLibraries>\n    <PlatformToolset>v140</PlatformToolset>\n    <WholeProgramOptimization>true</WholeProgramOptimization>\n    <CharacterSet>MultiByte</CharacterSet>\n  </PropertyGroup>\n  <PropertyGroup Condition=\"'$(Configuration)|$(Platform)'=='Debug|x64'\" Label=\"Configuration\">\n    <ConfigurationType>Application</ConfigurationType>\n    <UseDebugLibraries>true</UseDebugLibraries>\n    <PlatformToolset>v140</PlatformToolset>\n    <CharacterSet>MultiByte</CharacterSet>\n  </PropertyGroup>\n  <PropertyGroup Condition=\"'$(Configuration)|$(Platform)'=='Debug-static|x64'\" Label=\"Configuration\">\n    <ConfigurationType>Application</ConfigurationType>\n    <UseDebugLibraries>true</UseDebugLibraries>\n    <PlatformToolset>v140</PlatformToolset>\n    <CharacterSet>MultiByte</CharacterSet>\n  </PropertyGroup>\n  <PropertyGroup Condition=\"'$(Configuration)|$(Platform)'=='Release|x64'\" Label=\"Configuration\">\n    <ConfigurationType>Application</ConfigurationType>\n    <UseDebugLibraries>false</UseDebugLibraries>\n    <PlatformToolset>v140</PlatformToolset>\n    <WholeProgramOptimization>true</WholeProgramOptimization>\n    <CharacterSet>MultiByte</CharacterSet>\n  </PropertyGroup>\n  <PropertyGroup Condition=\"'$(Configuration)|$(Platform)'=='Release-static|x64'\" Label=\"Configuration\">\n    <ConfigurationType>Application</ConfigurationType>\n    <UseDebugLibraries>false</UseDebugLibraries>\n    <PlatformToolset>v140</PlatformToolset>\n    <WholeProgramOptimization>true</WholeProgramOptimization>\n    <CharacterSet>MultiByte</CharacterSet>\n  </PropertyGroup>\n  <Import Project=\"$(VCTargetsPath)\\Microsoft.Cpp.props\" />\n  <ImportGroup Label=\"ExtensionSettings\">\n  </ImportGroup>\n  <ImportGroup Label=\"Shared\">\n  </ImportGroup>\n  <ImportGroup Label=\"PropertySheets\" Condition=\"'$(Configuration)|$(Platform)'=='Debug|Win32'\">\n    <Import Project=\"$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props\" Condition=\"exists('$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props')\" Label=\"LocalAppDataPlatform\" />\n  </ImportGroup>\n  <ImportGroup Condition=\"'$(Configuration)|$(Platform)'=='Debug-static|Win32'\" Label=\"PropertySheets\">\n    <Import Project=\"$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props\" Condition=\"exists('$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props')\" Label=\"LocalAppDataPlatform\" />\n  </ImportGroup>\n  <ImportGroup Label=\"PropertySheets\" Condition=\"'$(Configuration)|$(Platform)'=='Release|Win32'\">\n    <Import Project=\"$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props\" Condition=\"exists('$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props')\" Label=\"LocalAppDataPlatform\" />\n  </ImportGroup>\n  <ImportGroup Condition=\"'$(Configuration)|$(Platform)'=='Release-static|Win32'\" Label=\"PropertySheets\">\n    <Import Project=\"$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props\" Condition=\"exists('$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props')\" Label=\"LocalAppDataPlatform\" />\n  </ImportGroup>\n  <ImportGroup Label=\"PropertySheets\" Condition=\"'$(Configuration)|$(Platform)'=='Debug|x64'\">\n    <Import Project=\"$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props\" Condition=\"exists('$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props')\" Label=\"LocalAppDataPlatform\" />\n  </ImportGroup>\n  <ImportGroup Condition=\"'$(Configuration)|$(Platform)'=='Debug-static|x64'\" Label=\"PropertySheets\">\n    <Import Project=\"$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props\" Condition=\"exists('$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props')\" Label=\"LocalAppDataPlatform\" />\n  </ImportGroup>\n  <ImportGroup Label=\"PropertySheets\" Condition=\"'$(Configuration)|$(Platform)'=='Release|x64'\">\n    <Import Project=\"$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props\" Condition=\"exists('$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props')\" Label=\"LocalAppDataPlatform\" />\n  </ImportGroup>\n  <ImportGroup Condition=\"'$(Configuration)|$(Platform)'=='Release-static|x64'\" Label=\"PropertySheets\">\n    <Import Project=\"$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props\" Condition=\"exists('$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props')\" Label=\"LocalAppDataPlatform\" />\n  </ImportGroup>\n  <PropertyGroup Label=\"UserMacros\" />\n  <PropertyGroup Condition=\"'$(Configuration)|$(Platform)'=='Debug|Win32'\">\n    <OutDir>$(SolutionDir)$(Platform)\\$(Configuration)\\</OutDir>\n    <IntDir>$(Platform)\\$(Configuration)\\</IntDir>\n    <LinkIncremental>true</LinkIncremental>\n  </PropertyGroup>\n  <PropertyGroup Condition=\"'$(Configuration)|$(Platform)'=='Debug-static|Win32'\">\n    <OutDir>$(SolutionDir)$(Platform)\\$(Configuration)\\</OutDir>\n    <IntDir>$(Platform)\\$(Configuration)\\</IntDir>\n    <LinkIncremental>true</LinkIncremental>\n  </PropertyGroup>\n  <PropertyGroup Condition=\"'$(Configuration)|$(Platform)'=='Debug|x64'\">\n    <LinkIncremental>true</LinkIncremental>\n    <OutDir>$(SolutionDir)$(Platform)\\$(Configuration)\\</OutDir>\n  </PropertyGroup>\n  <PropertyGroup Condition=\"'$(Configuration)|$(Platform)'=='Debug-static|x64'\">\n    <LinkIncremental>true</LinkIncremental>\n    <OutDir>$(SolutionDir)$(Platform)\\$(Configuration)\\</OutDir>\n  </PropertyGroup>\n  <PropertyGroup Condition=\"'$(Configuration)|$(Platform)'=='Release|Win32'\">\n    <OutDir>$(SolutionDir)$(Platform)\\$(Configuration)\\</OutDir>\n    <IntDir>$(Platform)\\$(Configuration)\\</IntDir>\n    <LinkIncremental>false</LinkIncremental>\n  </PropertyGroup>\n  <PropertyGroup Condition=\"'$(Configuration)|$(Platform)'=='Release-static|Win32'\">\n    <OutDir>$(SolutionDir)$(Platform)\\$(Configuration)\\</OutDir>\n    <IntDir>$(Platform)\\$(Configuration)\\</IntDir>\n    <LinkIncremental>false</LinkIncremental>\n  </PropertyGroup>\n  <PropertyGroup Condition=\"'$(Configuration)|$(Platform)'=='Release|x64'\">\n    <OutDir>$(SolutionDir)$(Platform)\\$(Configuration)\\</OutDir>\n    <IntDir>$(Platform)\\$(Configuration)\\</IntDir>\n    <LinkIncremental>false</LinkIncremental>\n  </PropertyGroup>\n  <PropertyGroup Condition=\"'$(Configuration)|$(Platform)'=='Release-static|x64'\">\n    <OutDir>$(SolutionDir)$(Platform)\\$(Configuration)\\</OutDir>\n    <IntDir>$(Platform)\\$(Configuration)\\</IntDir>\n    <LinkIncremental>false</LinkIncremental>\n  </PropertyGroup>\n  <ItemDefinitionGroup Condition=\"'$(Configuration)|$(Platform)'=='Debug|Win32'\">\n    <ClCompile>\n      <PrecompiledHeader>\n      </PrecompiledHeader>\n      <WarningLevel>Level3</WarningLevel>\n      <Optimization>Disabled</Optimization>\n      <PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>\n      <AdditionalIncludeDirectories>..\\..\\..\\..\\test\\include;..\\..\\..\\..\\include;..\\..\\..\\..\\include\\msvc_compat;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\n    </ClCompile>\n    <Link>\n      <SubSystem>Console</SubSystem>\n      <GenerateDebugInformation>true</GenerateDebugInformation>\n      <AdditionalLibraryDirectories>$(SolutionDir)$(Platform)\\$(Configuration)</AdditionalLibraryDirectories>\n      <AdditionalDependencies>jemallocd.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>\n    </Link>\n  </ItemDefinitionGroup>\n  <ItemDefinitionGroup Condition=\"'$(Configuration)|$(Platform)'=='Debug-static|Win32'\">\n    <ClCompile>\n      <PrecompiledHeader>\n      </PrecompiledHeader>\n      <WarningLevel>Level3</WarningLevel>\n      <Optimization>Disabled</Optimization>\n      <PreprocessorDefinitions>JEMALLOC_EXPORT=;JEMALLOC_STATIC;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>\n      <AdditionalIncludeDirectories>..\\..\\..\\..\\test\\include;..\\..\\..\\..\\include;..\\..\\..\\..\\include\\msvc_compat;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\n      <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>\n    </ClCompile>\n    <Link>\n      <SubSystem>Console</SubSystem>\n      <GenerateDebugInformation>true</GenerateDebugInformation>\n      <AdditionalLibraryDirectories>$(SolutionDir)$(Platform)\\$(Configuration)</AdditionalLibraryDirectories>\n      <AdditionalDependencies>jemalloc-$(PlatformToolset)-$(Configuration).lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>\n    </Link>\n  </ItemDefinitionGroup>\n  <ItemDefinitionGroup Condition=\"'$(Configuration)|$(Platform)'=='Debug|x64'\">\n    <ClCompile>\n      <PrecompiledHeader>\n      </PrecompiledHeader>\n      <WarningLevel>Level3</WarningLevel>\n      <Optimization>Disabled</Optimization>\n      <PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>\n      <AdditionalIncludeDirectories>..\\..\\..\\..\\test\\include;..\\..\\..\\..\\include;..\\..\\..\\..\\include\\msvc_compat;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\n    </ClCompile>\n    <Link>\n      <SubSystem>Console</SubSystem>\n      <GenerateDebugInformation>true</GenerateDebugInformation>\n      <AdditionalDependencies>jemallocd.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>\n      <AdditionalLibraryDirectories>$(SolutionDir)$(Platform)\\$(Configuration)</AdditionalLibraryDirectories>\n    </Link>\n  </ItemDefinitionGroup>\n  <ItemDefinitionGroup Condition=\"'$(Configuration)|$(Platform)'=='Debug-static|x64'\">\n    <ClCompile>\n      <PrecompiledHeader>\n      </PrecompiledHeader>\n      <WarningLevel>Level3</WarningLevel>\n      <Optimization>Disabled</Optimization>\n      <PreprocessorDefinitions>JEMALLOC_EXPORT=;JEMALLOC_STATIC;_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>\n      <AdditionalIncludeDirectories>..\\..\\..\\..\\test\\include;..\\..\\..\\..\\include;..\\..\\..\\..\\include\\msvc_compat;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\n      <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>\n    </ClCompile>\n    <Link>\n      <SubSystem>Console</SubSystem>\n      <GenerateDebugInformation>true</GenerateDebugInformation>\n      <AdditionalDependencies>jemalloc-vc$(PlatformToolsetVersion)-$(Configuration).lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>\n      <AdditionalLibraryDirectories>$(SolutionDir)$(Platform)\\$(Configuration)</AdditionalLibraryDirectories>\n    </Link>\n  </ItemDefinitionGroup>\n  <ItemDefinitionGroup Condition=\"'$(Configuration)|$(Platform)'=='Release|Win32'\">\n    <ClCompile>\n      <WarningLevel>Level3</WarningLevel>\n      <PrecompiledHeader>\n      </PrecompiledHeader>\n      <Optimization>MaxSpeed</Optimization>\n      <FunctionLevelLinking>true</FunctionLevelLinking>\n      <IntrinsicFunctions>true</IntrinsicFunctions>\n      <PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>\n      <AdditionalIncludeDirectories>..\\..\\..\\..\\test\\include;..\\..\\..\\..\\include;..\\..\\..\\..\\include\\msvc_compat;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\n    </ClCompile>\n    <Link>\n      <SubSystem>Console</SubSystem>\n      <GenerateDebugInformation>true</GenerateDebugInformation>\n      <EnableCOMDATFolding>true</EnableCOMDATFolding>\n      <OptimizeReferences>true</OptimizeReferences>\n      <AdditionalLibraryDirectories>$(SolutionDir)$(Platform)\\$(Configuration)</AdditionalLibraryDirectories>\n      <AdditionalDependencies>jemalloc.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>\n    </Link>\n  </ItemDefinitionGroup>\n  <ItemDefinitionGroup Condition=\"'$(Configuration)|$(Platform)'=='Release-static|Win32'\">\n    <ClCompile>\n      <WarningLevel>Level3</WarningLevel>\n      <PrecompiledHeader>\n      </PrecompiledHeader>\n      <Optimization>MaxSpeed</Optimization>\n      <FunctionLevelLinking>true</FunctionLevelLinking>\n      <IntrinsicFunctions>true</IntrinsicFunctions>\n      <PreprocessorDefinitions>JEMALLOC_EXPORT=;JEMALLOC_STATIC;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>\n      <AdditionalIncludeDirectories>..\\..\\..\\..\\test\\include;..\\..\\..\\..\\include;..\\..\\..\\..\\include\\msvc_compat;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\n      <RuntimeLibrary>MultiThreaded</RuntimeLibrary>\n    </ClCompile>\n    <Link>\n      <SubSystem>Console</SubSystem>\n      <GenerateDebugInformation>true</GenerateDebugInformation>\n      <EnableCOMDATFolding>true</EnableCOMDATFolding>\n      <OptimizeReferences>true</OptimizeReferences>\n      <AdditionalLibraryDirectories>$(SolutionDir)$(Platform)\\$(Configuration)</AdditionalLibraryDirectories>\n      <AdditionalDependencies>jemalloc-$(PlatformToolset)-$(Configuration).lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>\n    </Link>\n  </ItemDefinitionGroup>\n  <ItemDefinitionGroup Condition=\"'$(Configuration)|$(Platform)'=='Release|x64'\">\n    <ClCompile>\n      <WarningLevel>Level3</WarningLevel>\n      <PrecompiledHeader>\n      </PrecompiledHeader>\n      <Optimization>MaxSpeed</Optimization>\n      <FunctionLevelLinking>true</FunctionLevelLinking>\n      <IntrinsicFunctions>true</IntrinsicFunctions>\n      <PreprocessorDefinitions>NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>\n      <AdditionalIncludeDirectories>..\\..\\..\\..\\test\\include;..\\..\\..\\..\\include;..\\..\\..\\..\\include\\msvc_compat;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\n    </ClCompile>\n    <Link>\n      <SubSystem>Console</SubSystem>\n      <GenerateDebugInformation>true</GenerateDebugInformation>\n      <EnableCOMDATFolding>true</EnableCOMDATFolding>\n      <OptimizeReferences>true</OptimizeReferences>\n      <AdditionalLibraryDirectories>$(SolutionDir)$(Platform)\\$(Configuration)</AdditionalLibraryDirectories>\n      <AdditionalDependencies>jemalloc.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>\n    </Link>\n  </ItemDefinitionGroup>\n  <ItemDefinitionGroup Condition=\"'$(Configuration)|$(Platform)'=='Release-static|x64'\">\n    <ClCompile>\n      <WarningLevel>Level3</WarningLevel>\n      <PrecompiledHeader>\n      </PrecompiledHeader>\n      <Optimization>MaxSpeed</Optimization>\n      <FunctionLevelLinking>true</FunctionLevelLinking>\n      <IntrinsicFunctions>true</IntrinsicFunctions>\n      <PreprocessorDefinitions>JEMALLOC_EXPORT=;JEMALLOC_STATIC;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>\n      <AdditionalIncludeDirectories>..\\..\\..\\..\\test\\include;..\\..\\..\\..\\include;..\\..\\..\\..\\include\\msvc_compat;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\n      <RuntimeLibrary>MultiThreaded</RuntimeLibrary>\n    </ClCompile>\n    <Link>\n      <SubSystem>Console</SubSystem>\n      <GenerateDebugInformation>true</GenerateDebugInformation>\n      <EnableCOMDATFolding>true</EnableCOMDATFolding>\n      <OptimizeReferences>true</OptimizeReferences>\n      <AdditionalLibraryDirectories>$(SolutionDir)$(Platform)\\$(Configuration)</AdditionalLibraryDirectories>\n      <AdditionalDependencies>jemalloc-vc$(PlatformToolsetVersion)-$(Configuration).lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>\n    </Link>\n  </ItemDefinitionGroup>\n  <ItemGroup>\n    <ClCompile Include=\"test_threads.cpp\" />\n    <ClCompile Include=\"test_threads_main.cpp\" />\n  </ItemGroup>\n  <ItemGroup>\n    <ProjectReference Include=\"..\\jemalloc\\jemalloc.vcxproj\">\n      <Project>{8d6bb292-9e1c-413d-9f98-4864bdc1514a}</Project>\n    </ProjectReference>\n  </ItemGroup>\n  <ItemGroup>\n    <ClInclude Include=\"test_threads.h\" />\n  </ItemGroup>\n  <Import Project=\"$(VCTargetsPath)\\Microsoft.Cpp.targets\" />\n  <ImportGroup Label=\"ExtensionTargets\">\n  </ImportGroup>\n</Project>"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/deps/jemalloc/msvc/projects/vc2015/test_threads/test_threads.vcxproj.filters",
    "content": "﻿<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<Project ToolsVersion=\"4.0\" xmlns=\"http://schemas.microsoft.com/developer/msbuild/2003\">\n  <ItemGroup>\n    <Filter Include=\"Source Files\">\n      <UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>\n      <Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>\n    </Filter>\n    <Filter Include=\"Header Files\">\n      <UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>\n      <Extensions>h;hh;hpp;hxx;hm;inl;inc;xsd</Extensions>\n    </Filter>\n  </ItemGroup>\n  <ItemGroup>\n    <ClCompile Include=\"test_threads.cpp\">\n      <Filter>Source Files</Filter>\n    </ClCompile>\n    <ClCompile Include=\"test_threads_main.cpp\">\n      <Filter>Source Files</Filter>\n    </ClCompile>\n  </ItemGroup>\n  <ItemGroup>\n    <ClInclude Include=\"test_threads.h\">\n      <Filter>Header Files</Filter>\n    </ClInclude>\n  </ItemGroup>\n</Project>"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/deps/jemalloc/msvc/projects/vc2015/test_threads/test_threads_main.cpp",
    "content": "#include \"test_threads.h\"\n#include <future>\n#include <functional>\n#include <chrono>\n\nusing namespace std::chrono_literals;\n\nint main(int argc, char** argv)\n{\n  int rc = test_threads();\n  return rc;\n}\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/deps/jemalloc/src/arena.c",
    "content": "#define\tJEMALLOC_ARENA_C_\n#include \"jemalloc/internal/jemalloc_internal.h\"\n\n/******************************************************************************/\n/* Data. */\n\npurge_mode_t\topt_purge = PURGE_DEFAULT;\nconst char\t*purge_mode_names[] = {\n\t\"ratio\",\n\t\"decay\",\n\t\"N/A\"\n};\nssize_t\t\topt_lg_dirty_mult = LG_DIRTY_MULT_DEFAULT;\nstatic ssize_t\tlg_dirty_mult_default;\nssize_t\t\topt_decay_time = DECAY_TIME_DEFAULT;\nstatic ssize_t\tdecay_time_default;\n\narena_bin_info_t\tarena_bin_info[NBINS];\n\nsize_t\t\tmap_bias;\nsize_t\t\tmap_misc_offset;\nsize_t\t\tarena_maxrun; /* Max run size for arenas. */\nsize_t\t\tlarge_maxclass; /* Max large size class. */\nsize_t\t\trun_quantize_max; /* Max run_quantize_*() input. */\nstatic size_t\tsmall_maxrun; /* Max run size for small size classes. */\nstatic bool\t*small_run_tab; /* Valid small run page multiples. */\nstatic size_t\t*run_quantize_floor_tab; /* run_quantize_floor() memoization. */\nstatic size_t\t*run_quantize_ceil_tab; /* run_quantize_ceil() memoization. */\nunsigned\tnlclasses; /* Number of large size classes. */\nunsigned\tnhclasses; /* Number of huge size classes. */\nstatic szind_t\truns_avail_bias; /* Size index for first runs_avail tree. */\nstatic szind_t\truns_avail_nclasses; /* Number of runs_avail trees. */\n\n/******************************************************************************/\n/*\n * Function prototypes for static functions that are referenced prior to\n * definition.\n */\n\nstatic void\tarena_purge_to_limit(tsdn_t *tsdn, arena_t *arena,\n    size_t ndirty_limit);\nstatic void\tarena_run_dalloc(tsdn_t *tsdn, arena_t *arena, arena_run_t *run,\n    bool dirty, bool cleaned, bool decommitted);\nstatic void\tarena_dalloc_bin_run(tsdn_t *tsdn, arena_t *arena,\n    arena_chunk_t *chunk, arena_run_t *run, arena_bin_t *bin);\nstatic void\tarena_bin_lower_run(arena_t *arena, arena_chunk_t *chunk,\n    arena_run_t *run, arena_bin_t *bin);\n\n/******************************************************************************/\n\nJEMALLOC_INLINE_C size_t\narena_miscelm_size_get(const arena_chunk_map_misc_t *miscelm)\n{\n\tarena_chunk_t *chunk;\n\tsize_t pageind, mapbits;\n\n\tchunk = (arena_chunk_t *)CHUNK_ADDR2BASE(miscelm);\n\tpageind = arena_miscelm_to_pageind(miscelm);\n\tmapbits = arena_mapbits_get(chunk, pageind);\n\treturn (arena_mapbits_size_decode(mapbits));\n}\n\nJEMALLOC_INLINE_C int\narena_run_addr_comp(const arena_chunk_map_misc_t *a,\n    const arena_chunk_map_misc_t *b)\n{\n\tuintptr_t a_miscelm = (uintptr_t)a;\n\tuintptr_t b_miscelm = (uintptr_t)b;\n\n\tassert(a != NULL);\n\tassert(b != NULL);\n\n\treturn ((a_miscelm > b_miscelm) - (a_miscelm < b_miscelm));\n}\n\n/* Generate pairing heap functions. */\nph_gen(static UNUSED, arena_run_heap_, arena_run_heap_t, arena_chunk_map_misc_t,\n    ph_link, arena_run_addr_comp)\n\nstatic size_t\nrun_quantize_floor_compute(size_t size)\n{\n\tsize_t qsize;\n\n\tassert(size != 0);\n\tassert(size == PAGE_CEILING(size));\n\n\t/* Don't change sizes that are valid small run sizes. */\n\tif (size <= small_maxrun && small_run_tab[size >> LG_PAGE])\n\t\treturn (size);\n\n\t/*\n\t * Round down to the nearest run size that can actually be requested\n\t * during normal large allocation.  Add large_pad so that cache index\n\t * randomization can offset the allocation from the page boundary.\n\t */\n\tqsize = index2size(size2index(size - large_pad + 1) - 1) + large_pad;\n\tif (qsize <= SMALL_MAXCLASS + large_pad)\n\t\treturn (run_quantize_floor_compute(size - large_pad));\n\tassert(qsize <= size);\n\treturn (qsize);\n}\n\nstatic size_t\nrun_quantize_ceil_compute_hard(size_t size)\n{\n\tsize_t large_run_size_next;\n\n\tassert(size != 0);\n\tassert(size == PAGE_CEILING(size));\n\n\t/*\n\t * Return the next quantized size greater than the input size.\n\t * Quantized sizes comprise the union of run sizes that back small\n\t * region runs, and run sizes that back large regions with no explicit\n\t * alignment constraints.\n\t */\n\n\tif (size > SMALL_MAXCLASS) {\n\t\tlarge_run_size_next = PAGE_CEILING(index2size(size2index(size -\n\t\t    large_pad) + 1) + large_pad);\n\t} else\n\t\tlarge_run_size_next = SIZE_T_MAX;\n\tif (size >= small_maxrun)\n\t\treturn (large_run_size_next);\n\n\twhile (true) {\n\t\tsize += PAGE;\n\t\tassert(size <= small_maxrun);\n\t\tif (small_run_tab[size >> LG_PAGE]) {\n\t\t\tif (large_run_size_next < size)\n\t\t\t\treturn (large_run_size_next);\n\t\t\treturn (size);\n\t\t}\n\t}\n}\n\nstatic size_t\nrun_quantize_ceil_compute(size_t size)\n{\n\tsize_t qsize = run_quantize_floor_compute(size);\n\n\tif (qsize < size) {\n\t\t/*\n\t\t * Skip a quantization that may have an adequately large run,\n\t\t * because under-sized runs may be mixed in.  This only happens\n\t\t * when an unusual size is requested, i.e. for aligned\n\t\t * allocation, and is just one of several places where linear\n\t\t * search would potentially find sufficiently aligned available\n\t\t * memory somewhere lower.\n\t\t */\n\t\tqsize = run_quantize_ceil_compute_hard(qsize);\n\t}\n\treturn (qsize);\n}\n\n#ifdef JEMALLOC_JET\n#undef run_quantize_floor\n#define\trun_quantize_floor JEMALLOC_N(n_run_quantize_floor)\n#endif\nstatic size_t\nrun_quantize_floor(size_t size)\n{\n\tsize_t ret;\n\n\tassert(size > 0);\n\tassert(size <= run_quantize_max);\n\tassert((size & PAGE_MASK) == 0);\n\n\tret = run_quantize_floor_tab[(size >> LG_PAGE) - 1];\n\tassert(ret == run_quantize_floor_compute(size));\n\treturn (ret);\n}\n#ifdef JEMALLOC_JET\n#undef run_quantize_floor\n#define\trun_quantize_floor JEMALLOC_N(run_quantize_floor)\nrun_quantize_t *run_quantize_floor = JEMALLOC_N(n_run_quantize_floor);\n#endif\n\n#ifdef JEMALLOC_JET\n#undef run_quantize_ceil\n#define\trun_quantize_ceil JEMALLOC_N(n_run_quantize_ceil)\n#endif\nstatic size_t\nrun_quantize_ceil(size_t size)\n{\n\tsize_t ret;\n\n\tassert(size > 0);\n\tassert(size <= run_quantize_max);\n\tassert((size & PAGE_MASK) == 0);\n\n\tret = run_quantize_ceil_tab[(size >> LG_PAGE) - 1];\n\tassert(ret == run_quantize_ceil_compute(size));\n\treturn (ret);\n}\n#ifdef JEMALLOC_JET\n#undef run_quantize_ceil\n#define\trun_quantize_ceil JEMALLOC_N(run_quantize_ceil)\nrun_quantize_t *run_quantize_ceil = JEMALLOC_N(n_run_quantize_ceil);\n#endif\n\nstatic arena_run_heap_t *\narena_runs_avail_get(arena_t *arena, szind_t ind)\n{\n\n\tassert(ind >= runs_avail_bias);\n\tassert(ind - runs_avail_bias < runs_avail_nclasses);\n\n\treturn (&arena->runs_avail[ind - runs_avail_bias]);\n}\n\nstatic void\narena_avail_insert(arena_t *arena, arena_chunk_t *chunk, size_t pageind,\n    size_t npages)\n{\n\tszind_t ind = size2index(run_quantize_floor(arena_miscelm_size_get(\n\t    arena_miscelm_get_const(chunk, pageind))));\n\tassert(npages == (arena_mapbits_unallocated_size_get(chunk, pageind) >>\n\t    LG_PAGE));\n\tarena_run_heap_insert(arena_runs_avail_get(arena, ind),\n\t    arena_miscelm_get_mutable(chunk, pageind));\n}\n\nstatic void\narena_avail_remove(arena_t *arena, arena_chunk_t *chunk, size_t pageind,\n    size_t npages)\n{\n\tszind_t ind = size2index(run_quantize_floor(arena_miscelm_size_get(\n\t    arena_miscelm_get_const(chunk, pageind))));\n\tassert(npages == (arena_mapbits_unallocated_size_get(chunk, pageind) >>\n\t    LG_PAGE));\n\tarena_run_heap_remove(arena_runs_avail_get(arena, ind),\n\t    arena_miscelm_get_mutable(chunk, pageind));\n}\n\nstatic void\narena_run_dirty_insert(arena_t *arena, arena_chunk_t *chunk, size_t pageind,\n    size_t npages)\n{\n\tarena_chunk_map_misc_t *miscelm = arena_miscelm_get_mutable(chunk,\n\t    pageind);\n\n\tassert(npages == (arena_mapbits_unallocated_size_get(chunk, pageind) >>\n\t    LG_PAGE));\n\tassert(arena_mapbits_dirty_get(chunk, pageind) == CHUNK_MAP_DIRTY);\n\tassert(arena_mapbits_dirty_get(chunk, pageind+npages-1) ==\n\t    CHUNK_MAP_DIRTY);\n\n\tqr_new(&miscelm->rd, rd_link);\n\tqr_meld(&arena->runs_dirty, &miscelm->rd, rd_link);\n\tarena->ndirty += npages;\n}\n\nstatic void\narena_run_dirty_remove(arena_t *arena, arena_chunk_t *chunk, size_t pageind,\n    size_t npages)\n{\n\tarena_chunk_map_misc_t *miscelm = arena_miscelm_get_mutable(chunk,\n\t    pageind);\n\n\tassert(npages == (arena_mapbits_unallocated_size_get(chunk, pageind) >>\n\t    LG_PAGE));\n\tassert(arena_mapbits_dirty_get(chunk, pageind) == CHUNK_MAP_DIRTY);\n\tassert(arena_mapbits_dirty_get(chunk, pageind+npages-1) ==\n\t    CHUNK_MAP_DIRTY);\n\n\tqr_remove(&miscelm->rd, rd_link);\n\tassert(arena->ndirty >= npages);\n\tarena->ndirty -= npages;\n}\n\nstatic size_t\narena_chunk_dirty_npages(const extent_node_t *node)\n{\n\n\treturn (extent_node_size_get(node) >> LG_PAGE);\n}\n\nvoid\narena_chunk_cache_maybe_insert(arena_t *arena, extent_node_t *node, bool cache)\n{\n\n\tif (cache) {\n\t\textent_node_dirty_linkage_init(node);\n\t\textent_node_dirty_insert(node, &arena->runs_dirty,\n\t\t    &arena->chunks_cache);\n\t\tarena->ndirty += arena_chunk_dirty_npages(node);\n\t}\n}\n\nvoid\narena_chunk_cache_maybe_remove(arena_t *arena, extent_node_t *node, bool dirty)\n{\n\n\tif (dirty) {\n\t\textent_node_dirty_remove(node);\n\t\tassert(arena->ndirty >= arena_chunk_dirty_npages(node));\n\t\tarena->ndirty -= arena_chunk_dirty_npages(node);\n\t}\n}\n\nJEMALLOC_INLINE_C void *\narena_run_reg_alloc(arena_run_t *run, arena_bin_info_t *bin_info)\n{\n\tvoid *ret;\n\tsize_t regind;\n\tarena_chunk_map_misc_t *miscelm;\n\tvoid *rpages;\n\n\tassert(run->nfree > 0);\n\tassert(!bitmap_full(run->bitmap, &bin_info->bitmap_info));\n\n\tregind = (unsigned)bitmap_sfu(run->bitmap, &bin_info->bitmap_info);\n\tmiscelm = arena_run_to_miscelm(run);\n\trpages = arena_miscelm_to_rpages(miscelm);\n\tret = (void *)((uintptr_t)rpages + (uintptr_t)bin_info->reg0_offset +\n\t    (uintptr_t)(bin_info->reg_interval * regind));\n\trun->nfree--;\n\treturn (ret);\n}\n\nJEMALLOC_INLINE_C void\narena_run_reg_dalloc(arena_run_t *run, void *ptr)\n{\n\tarena_chunk_t *chunk = (arena_chunk_t *)CHUNK_ADDR2BASE(run);\n\tsize_t pageind = ((uintptr_t)ptr - (uintptr_t)chunk) >> LG_PAGE;\n\tsize_t mapbits = arena_mapbits_get(chunk, pageind);\n\tszind_t binind = arena_ptr_small_binind_get(ptr, mapbits);\n\tarena_bin_info_t *bin_info = &arena_bin_info[binind];\n\tsize_t regind = arena_run_regind(run, bin_info, ptr);\n\n\tassert(run->nfree < bin_info->nregs);\n\t/* Freeing an interior pointer can cause assertion failure. */\n\tassert(((uintptr_t)ptr -\n\t    ((uintptr_t)arena_miscelm_to_rpages(arena_run_to_miscelm(run)) +\n\t    (uintptr_t)bin_info->reg0_offset)) %\n\t    (uintptr_t)bin_info->reg_interval == 0);\n\tassert((uintptr_t)ptr >=\n\t    (uintptr_t)arena_miscelm_to_rpages(arena_run_to_miscelm(run)) +\n\t    (uintptr_t)bin_info->reg0_offset);\n\t/* Freeing an unallocated pointer can cause assertion failure. */\n\tassert(bitmap_get(run->bitmap, &bin_info->bitmap_info, regind));\n\n\tbitmap_unset(run->bitmap, &bin_info->bitmap_info, regind);\n\trun->nfree++;\n}\n\nJEMALLOC_INLINE_C void\narena_run_zero(arena_chunk_t *chunk, size_t run_ind, size_t npages)\n{\n\n\tJEMALLOC_VALGRIND_MAKE_MEM_UNDEFINED((void *)((uintptr_t)chunk +\n\t    (run_ind << LG_PAGE)), (npages << LG_PAGE));\n\tmemset((void *)((uintptr_t)chunk + (run_ind << LG_PAGE)), 0,\n\t    (npages << LG_PAGE));\n}\n\nJEMALLOC_INLINE_C void\narena_run_page_mark_zeroed(arena_chunk_t *chunk, size_t run_ind)\n{\n\n\tJEMALLOC_VALGRIND_MAKE_MEM_DEFINED((void *)((uintptr_t)chunk + (run_ind\n\t    << LG_PAGE)), PAGE);\n}\n\nJEMALLOC_INLINE_C void\narena_run_page_validate_zeroed(arena_chunk_t *chunk, size_t run_ind)\n{\n\tsize_t i;\n\tUNUSED size_t *p = (size_t *)((uintptr_t)chunk + (run_ind << LG_PAGE));\n\n\tarena_run_page_mark_zeroed(chunk, run_ind);\n\tfor (i = 0; i < PAGE / sizeof(size_t); i++)\n\t\tassert(p[i] == 0);\n}\n\nstatic void\narena_nactive_add(arena_t *arena, size_t add_pages)\n{\n\n\tif (config_stats) {\n\t\tsize_t cactive_add = CHUNK_CEILING((arena->nactive +\n\t\t    add_pages) << LG_PAGE) - CHUNK_CEILING(arena->nactive <<\n\t\t    LG_PAGE);\n\t\tif (cactive_add != 0)\n\t\t\tstats_cactive_add(cactive_add);\n\t}\n\tarena->nactive += add_pages;\n}\n\nstatic void\narena_nactive_sub(arena_t *arena, size_t sub_pages)\n{\n\n\tif (config_stats) {\n\t\tsize_t cactive_sub = CHUNK_CEILING(arena->nactive << LG_PAGE) -\n\t\t    CHUNK_CEILING((arena->nactive - sub_pages) << LG_PAGE);\n\t\tif (cactive_sub != 0)\n\t\t\tstats_cactive_sub(cactive_sub);\n\t}\n\tarena->nactive -= sub_pages;\n}\n\nstatic void\narena_run_split_remove(arena_t *arena, arena_chunk_t *chunk, size_t run_ind,\n    size_t flag_dirty, size_t flag_decommitted, size_t need_pages)\n{\n\tsize_t total_pages, rem_pages;\n\n\tassert(flag_dirty == 0 || flag_decommitted == 0);\n\n\ttotal_pages = arena_mapbits_unallocated_size_get(chunk, run_ind) >>\n\t    LG_PAGE;\n\tassert(arena_mapbits_dirty_get(chunk, run_ind+total_pages-1) ==\n\t    flag_dirty);\n\tassert(need_pages <= total_pages);\n\trem_pages = total_pages - need_pages;\n\n\tarena_avail_remove(arena, chunk, run_ind, total_pages);\n\tif (flag_dirty != 0)\n\t\tarena_run_dirty_remove(arena, chunk, run_ind, total_pages);\n\tarena_nactive_add(arena, need_pages);\n\n\t/* Keep track of trailing unused pages for later use. */\n\tif (rem_pages > 0) {\n\t\tsize_t flags = flag_dirty | flag_decommitted;\n\t\tsize_t flag_unzeroed_mask = (flags == 0) ?  CHUNK_MAP_UNZEROED :\n\t\t    0;\n\n\t\tarena_mapbits_unallocated_set(chunk, run_ind+need_pages,\n\t\t    (rem_pages << LG_PAGE), flags |\n\t\t    (arena_mapbits_unzeroed_get(chunk, run_ind+need_pages) &\n\t\t    flag_unzeroed_mask));\n\t\tarena_mapbits_unallocated_set(chunk, run_ind+total_pages-1,\n\t\t    (rem_pages << LG_PAGE), flags |\n\t\t    (arena_mapbits_unzeroed_get(chunk, run_ind+total_pages-1) &\n\t\t    flag_unzeroed_mask));\n\t\tif (flag_dirty != 0) {\n\t\t\tarena_run_dirty_insert(arena, chunk, run_ind+need_pages,\n\t\t\t    rem_pages);\n\t\t}\n\t\tarena_avail_insert(arena, chunk, run_ind+need_pages, rem_pages);\n\t}\n}\n\nstatic bool\narena_run_split_large_helper(arena_t *arena, arena_run_t *run, size_t size,\n    bool remove, bool zero)\n{\n\tarena_chunk_t *chunk;\n\tarena_chunk_map_misc_t *miscelm;\n\tsize_t flag_dirty, flag_decommitted, run_ind, need_pages;\n\tsize_t flag_unzeroed_mask;\n\n\tchunk = (arena_chunk_t *)CHUNK_ADDR2BASE(run);\n\tmiscelm = arena_run_to_miscelm(run);\n\trun_ind = arena_miscelm_to_pageind(miscelm);\n\tflag_dirty = arena_mapbits_dirty_get(chunk, run_ind);\n\tflag_decommitted = arena_mapbits_decommitted_get(chunk, run_ind);\n\tneed_pages = (size >> LG_PAGE);\n\tassert(need_pages > 0);\n\n\tif (flag_decommitted != 0 && arena->chunk_hooks.commit(chunk, chunksize,\n\t    run_ind << LG_PAGE, size, arena->ind))\n\t\treturn (true);\n\n\tif (remove) {\n\t\tarena_run_split_remove(arena, chunk, run_ind, flag_dirty,\n\t\t    flag_decommitted, need_pages);\n\t}\n\n\tif (zero) {\n\t\tif (flag_decommitted != 0) {\n\t\t\t/* The run is untouched, and therefore zeroed. */\n\t\t\tJEMALLOC_VALGRIND_MAKE_MEM_DEFINED((void\n\t\t\t    *)((uintptr_t)chunk + (run_ind << LG_PAGE)),\n\t\t\t    (need_pages << LG_PAGE));\n\t\t} else if (flag_dirty != 0) {\n\t\t\t/* The run is dirty, so all pages must be zeroed. */\n\t\t\tarena_run_zero(chunk, run_ind, need_pages);\n\t\t} else {\n\t\t\t/*\n\t\t\t * The run is clean, so some pages may be zeroed (i.e.\n\t\t\t * never before touched).\n\t\t\t */\n\t\t\tsize_t i;\n\t\t\tfor (i = 0; i < need_pages; i++) {\n\t\t\t\tif (arena_mapbits_unzeroed_get(chunk, run_ind+i)\n\t\t\t\t    != 0)\n\t\t\t\t\tarena_run_zero(chunk, run_ind+i, 1);\n\t\t\t\telse if (config_debug) {\n\t\t\t\t\tarena_run_page_validate_zeroed(chunk,\n\t\t\t\t\t    run_ind+i);\n\t\t\t\t} else {\n\t\t\t\t\tarena_run_page_mark_zeroed(chunk,\n\t\t\t\t\t    run_ind+i);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t} else {\n\t\tJEMALLOC_VALGRIND_MAKE_MEM_UNDEFINED((void *)((uintptr_t)chunk +\n\t\t    (run_ind << LG_PAGE)), (need_pages << LG_PAGE));\n\t}\n\n\t/*\n\t * Set the last element first, in case the run only contains one page\n\t * (i.e. both statements set the same element).\n\t */\n\tflag_unzeroed_mask = (flag_dirty | flag_decommitted) == 0 ?\n\t    CHUNK_MAP_UNZEROED : 0;\n\tarena_mapbits_large_set(chunk, run_ind+need_pages-1, 0, flag_dirty |\n\t    (flag_unzeroed_mask & arena_mapbits_unzeroed_get(chunk,\n\t    run_ind+need_pages-1)));\n\tarena_mapbits_large_set(chunk, run_ind, size, flag_dirty |\n\t    (flag_unzeroed_mask & arena_mapbits_unzeroed_get(chunk, run_ind)));\n\treturn (false);\n}\n\nstatic bool\narena_run_split_large(arena_t *arena, arena_run_t *run, size_t size, bool zero)\n{\n\n\treturn (arena_run_split_large_helper(arena, run, size, true, zero));\n}\n\nstatic bool\narena_run_init_large(arena_t *arena, arena_run_t *run, size_t size, bool zero)\n{\n\n\treturn (arena_run_split_large_helper(arena, run, size, false, zero));\n}\n\nstatic bool\narena_run_split_small(arena_t *arena, arena_run_t *run, size_t size,\n    szind_t binind)\n{\n\tarena_chunk_t *chunk;\n\tarena_chunk_map_misc_t *miscelm;\n\tsize_t flag_dirty, flag_decommitted, run_ind, need_pages, i;\n\n\tassert(binind != BININD_INVALID);\n\n\tchunk = (arena_chunk_t *)CHUNK_ADDR2BASE(run);\n\tmiscelm = arena_run_to_miscelm(run);\n\trun_ind = arena_miscelm_to_pageind(miscelm);\n\tflag_dirty = arena_mapbits_dirty_get(chunk, run_ind);\n\tflag_decommitted = arena_mapbits_decommitted_get(chunk, run_ind);\n\tneed_pages = (size >> LG_PAGE);\n\tassert(need_pages > 0);\n\n\tif (flag_decommitted != 0 && arena->chunk_hooks.commit(chunk, chunksize,\n\t    run_ind << LG_PAGE, size, arena->ind))\n\t\treturn (true);\n\n\tarena_run_split_remove(arena, chunk, run_ind, flag_dirty,\n\t    flag_decommitted, need_pages);\n\n\tfor (i = 0; i < need_pages; i++) {\n\t\tsize_t flag_unzeroed = arena_mapbits_unzeroed_get(chunk,\n\t\t    run_ind+i);\n\t\tarena_mapbits_small_set(chunk, run_ind+i, i, binind,\n\t\t    flag_unzeroed);\n\t\tif (config_debug && flag_dirty == 0 && flag_unzeroed == 0)\n\t\t\tarena_run_page_validate_zeroed(chunk, run_ind+i);\n\t}\n\tJEMALLOC_VALGRIND_MAKE_MEM_UNDEFINED((void *)((uintptr_t)chunk +\n\t    (run_ind << LG_PAGE)), (need_pages << LG_PAGE));\n\treturn (false);\n}\n\nstatic arena_chunk_t *\narena_chunk_init_spare(arena_t *arena)\n{\n\tarena_chunk_t *chunk;\n\n\tassert(arena->spare != NULL);\n\n\tchunk = arena->spare;\n\tarena->spare = NULL;\n\n\tassert(arena_mapbits_allocated_get(chunk, map_bias) == 0);\n\tassert(arena_mapbits_allocated_get(chunk, chunk_npages-1) == 0);\n\tassert(arena_mapbits_unallocated_size_get(chunk, map_bias) ==\n\t    arena_maxrun);\n\tassert(arena_mapbits_unallocated_size_get(chunk, chunk_npages-1) ==\n\t    arena_maxrun);\n\tassert(arena_mapbits_dirty_get(chunk, map_bias) ==\n\t    arena_mapbits_dirty_get(chunk, chunk_npages-1));\n\n\treturn (chunk);\n}\n\nstatic bool\narena_chunk_register(tsdn_t *tsdn, arena_t *arena, arena_chunk_t *chunk,\n    bool zero)\n{\n\n\t/*\n\t * The extent node notion of \"committed\" doesn't directly apply to\n\t * arena chunks.  Arbitrarily mark them as committed.  The commit state\n\t * of runs is tracked individually, and upon chunk deallocation the\n\t * entire chunk is in a consistent commit state.\n\t */\n\textent_node_init(&chunk->node, arena, chunk, chunksize, zero, true);\n\textent_node_achunk_set(&chunk->node, true);\n\treturn (chunk_register(tsdn, chunk, &chunk->node));\n}\n\nstatic arena_chunk_t *\narena_chunk_alloc_internal_hard(tsdn_t *tsdn, arena_t *arena,\n    chunk_hooks_t *chunk_hooks, bool *zero, bool *commit)\n{\n\tarena_chunk_t *chunk;\n\n\tmalloc_mutex_unlock(tsdn, &arena->lock);\n\n\tchunk = (arena_chunk_t *)chunk_alloc_wrapper(tsdn, arena, chunk_hooks,\n\t    NULL, chunksize, chunksize, zero, commit);\n\tif (chunk != NULL && !*commit) {\n\t\t/* Commit header. */\n\t\tif (chunk_hooks->commit(chunk, chunksize, 0, map_bias <<\n\t\t    LG_PAGE, arena->ind)) {\n\t\t\tchunk_dalloc_wrapper(tsdn, arena, chunk_hooks,\n\t\t\t    (void *)chunk, chunksize, *zero, *commit);\n\t\t\tchunk = NULL;\n\t\t}\n\t}\n\tif (chunk != NULL && arena_chunk_register(tsdn, arena, chunk, *zero)) {\n\t\tif (!*commit) {\n\t\t\t/* Undo commit of header. */\n\t\t\tchunk_hooks->decommit(chunk, chunksize, 0, map_bias <<\n\t\t\t    LG_PAGE, arena->ind);\n\t\t}\n\t\tchunk_dalloc_wrapper(tsdn, arena, chunk_hooks, (void *)chunk,\n\t\t    chunksize, *zero, *commit);\n\t\tchunk = NULL;\n\t}\n\n\tmalloc_mutex_lock(tsdn, &arena->lock);\n\treturn (chunk);\n}\n\nstatic arena_chunk_t *\narena_chunk_alloc_internal(tsdn_t *tsdn, arena_t *arena, bool *zero,\n    bool *commit)\n{\n\tarena_chunk_t *chunk;\n\tchunk_hooks_t chunk_hooks = CHUNK_HOOKS_INITIALIZER;\n\n\tchunk = chunk_alloc_cache(tsdn, arena, &chunk_hooks, NULL, chunksize,\n\t    chunksize, zero, true);\n\tif (chunk != NULL) {\n\t\tif (arena_chunk_register(tsdn, arena, chunk, *zero)) {\n\t\t\tchunk_dalloc_cache(tsdn, arena, &chunk_hooks, chunk,\n\t\t\t    chunksize, true);\n\t\t\treturn (NULL);\n\t\t}\n\t\t*commit = true;\n\t}\n\tif (chunk == NULL) {\n\t\tchunk = arena_chunk_alloc_internal_hard(tsdn, arena,\n\t\t    &chunk_hooks, zero, commit);\n\t}\n\n\tif (config_stats && chunk != NULL) {\n\t\tarena->stats.mapped += chunksize;\n\t\tarena->stats.metadata_mapped += (map_bias << LG_PAGE);\n\t}\n\n\treturn (chunk);\n}\n\nstatic arena_chunk_t *\narena_chunk_init_hard(tsdn_t *tsdn, arena_t *arena)\n{\n\tarena_chunk_t *chunk;\n\tbool zero, commit;\n\tsize_t flag_unzeroed, flag_decommitted, i;\n\n\tassert(arena->spare == NULL);\n\n\tzero = false;\n\tcommit = false;\n\tchunk = arena_chunk_alloc_internal(tsdn, arena, &zero, &commit);\n\tif (chunk == NULL)\n\t\treturn (NULL);\n\n\t/*\n\t * Initialize the map to contain one maximal free untouched run.  Mark\n\t * the pages as zeroed if arena_chunk_alloc_internal() returned a zeroed\n\t * or decommitted chunk.\n\t */\n\tflag_unzeroed = (zero || !commit) ? 0 : CHUNK_MAP_UNZEROED;\n\tflag_decommitted = commit ? 0 : CHUNK_MAP_DECOMMITTED;\n\tarena_mapbits_unallocated_set(chunk, map_bias, arena_maxrun,\n\t    flag_unzeroed | flag_decommitted);\n\t/*\n\t * There is no need to initialize the internal page map entries unless\n\t * the chunk is not zeroed.\n\t */\n\tif (!zero) {\n\t\tJEMALLOC_VALGRIND_MAKE_MEM_UNDEFINED(\n\t\t    (void *)arena_bitselm_get_const(chunk, map_bias+1),\n\t\t    (size_t)((uintptr_t)arena_bitselm_get_const(chunk,\n\t\t    chunk_npages-1) -\n\t\t    (uintptr_t)arena_bitselm_get_const(chunk, map_bias+1)));\n\t\tfor (i = map_bias+1; i < chunk_npages-1; i++)\n\t\t\tarena_mapbits_internal_set(chunk, i, flag_unzeroed);\n\t} else {\n\t\tJEMALLOC_VALGRIND_MAKE_MEM_DEFINED((void\n\t\t    *)arena_bitselm_get_const(chunk, map_bias+1),\n\t\t    (size_t)((uintptr_t)arena_bitselm_get_const(chunk,\n\t\t    chunk_npages-1) -\n\t\t    (uintptr_t)arena_bitselm_get_const(chunk, map_bias+1)));\n\t\tif (config_debug) {\n\t\t\tfor (i = map_bias+1; i < chunk_npages-1; i++) {\n\t\t\t\tassert(arena_mapbits_unzeroed_get(chunk, i) ==\n\t\t\t\t    flag_unzeroed);\n\t\t\t}\n\t\t}\n\t}\n\tarena_mapbits_unallocated_set(chunk, chunk_npages-1, arena_maxrun,\n\t    flag_unzeroed);\n\n\treturn (chunk);\n}\n\nstatic arena_chunk_t *\narena_chunk_alloc(tsdn_t *tsdn, arena_t *arena)\n{\n\tarena_chunk_t *chunk;\n\n\tif (arena->spare != NULL)\n\t\tchunk = arena_chunk_init_spare(arena);\n\telse {\n\t\tchunk = arena_chunk_init_hard(tsdn, arena);\n\t\tif (chunk == NULL)\n\t\t\treturn (NULL);\n\t}\n\n\tql_elm_new(&chunk->node, ql_link);\n\tql_tail_insert(&arena->achunks, &chunk->node, ql_link);\n\tarena_avail_insert(arena, chunk, map_bias, chunk_npages-map_bias);\n\n\treturn (chunk);\n}\n\nstatic void\narena_chunk_discard(tsdn_t *tsdn, arena_t *arena, arena_chunk_t *chunk)\n{\n\tbool committed;\n\tchunk_hooks_t chunk_hooks = CHUNK_HOOKS_INITIALIZER;\n\n\tchunk_deregister(chunk, &chunk->node);\n\n\tcommitted = (arena_mapbits_decommitted_get(chunk, map_bias) == 0);\n\tif (!committed) {\n\t\t/*\n\t\t * Decommit the header.  Mark the chunk as decommitted even if\n\t\t * header decommit fails, since treating a partially committed\n\t\t * chunk as committed has a high potential for causing later\n\t\t * access of decommitted memory.\n\t\t */\n\t\tchunk_hooks = chunk_hooks_get(tsdn, arena);\n\t\tchunk_hooks.decommit(chunk, chunksize, 0, map_bias << LG_PAGE,\n\t\t    arena->ind);\n\t}\n\n\tchunk_dalloc_cache(tsdn, arena, &chunk_hooks, (void *)chunk, chunksize,\n\t    committed);\n\n\tif (config_stats) {\n\t\tarena->stats.mapped -= chunksize;\n\t\tarena->stats.metadata_mapped -= (map_bias << LG_PAGE);\n\t}\n}\n\nstatic void\narena_spare_discard(tsdn_t *tsdn, arena_t *arena, arena_chunk_t *spare)\n{\n\n\tassert(arena->spare != spare);\n\n\tif (arena_mapbits_dirty_get(spare, map_bias) != 0) {\n\t\tarena_run_dirty_remove(arena, spare, map_bias,\n\t\t    chunk_npages-map_bias);\n\t}\n\n\tarena_chunk_discard(tsdn, arena, spare);\n}\n\nstatic void\narena_chunk_dalloc(tsdn_t *tsdn, arena_t *arena, arena_chunk_t *chunk)\n{\n\tarena_chunk_t *spare;\n\n\tassert(arena_mapbits_allocated_get(chunk, map_bias) == 0);\n\tassert(arena_mapbits_allocated_get(chunk, chunk_npages-1) == 0);\n\tassert(arena_mapbits_unallocated_size_get(chunk, map_bias) ==\n\t    arena_maxrun);\n\tassert(arena_mapbits_unallocated_size_get(chunk, chunk_npages-1) ==\n\t    arena_maxrun);\n\tassert(arena_mapbits_dirty_get(chunk, map_bias) ==\n\t    arena_mapbits_dirty_get(chunk, chunk_npages-1));\n\tassert(arena_mapbits_decommitted_get(chunk, map_bias) ==\n\t    arena_mapbits_decommitted_get(chunk, chunk_npages-1));\n\n\t/* Remove run from runs_avail, so that the arena does not use it. */\n\tarena_avail_remove(arena, chunk, map_bias, chunk_npages-map_bias);\n\n\tql_remove(&arena->achunks, &chunk->node, ql_link);\n\tspare = arena->spare;\n\tarena->spare = chunk;\n\tif (spare != NULL)\n\t\tarena_spare_discard(tsdn, arena, spare);\n}\n\nstatic void\narena_huge_malloc_stats_update(arena_t *arena, size_t usize)\n{\n\tszind_t index = size2index(usize) - nlclasses - NBINS;\n\n\tcassert(config_stats);\n\n\tarena->stats.nmalloc_huge++;\n\tarena->stats.allocated_huge += usize;\n\tarena->stats.hstats[index].nmalloc++;\n\tarena->stats.hstats[index].curhchunks++;\n}\n\nstatic void\narena_huge_malloc_stats_update_undo(arena_t *arena, size_t usize)\n{\n\tszind_t index = size2index(usize) - nlclasses - NBINS;\n\n\tcassert(config_stats);\n\n\tarena->stats.nmalloc_huge--;\n\tarena->stats.allocated_huge -= usize;\n\tarena->stats.hstats[index].nmalloc--;\n\tarena->stats.hstats[index].curhchunks--;\n}\n\nstatic void\narena_huge_dalloc_stats_update(arena_t *arena, size_t usize)\n{\n\tszind_t index = size2index(usize) - nlclasses - NBINS;\n\n\tcassert(config_stats);\n\n\tarena->stats.ndalloc_huge++;\n\tarena->stats.allocated_huge -= usize;\n\tarena->stats.hstats[index].ndalloc++;\n\tarena->stats.hstats[index].curhchunks--;\n}\n\nstatic void\narena_huge_reset_stats_cancel(arena_t *arena, size_t usize)\n{\n\tszind_t index = size2index(usize) - nlclasses - NBINS;\n\n\tcassert(config_stats);\n\n\tarena->stats.ndalloc_huge++;\n\tarena->stats.hstats[index].ndalloc--;\n}\n\nstatic void\narena_huge_dalloc_stats_update_undo(arena_t *arena, size_t usize)\n{\n\tszind_t index = size2index(usize) - nlclasses - NBINS;\n\n\tcassert(config_stats);\n\n\tarena->stats.ndalloc_huge--;\n\tarena->stats.allocated_huge += usize;\n\tarena->stats.hstats[index].ndalloc--;\n\tarena->stats.hstats[index].curhchunks++;\n}\n\nstatic void\narena_huge_ralloc_stats_update(arena_t *arena, size_t oldsize, size_t usize)\n{\n\n\tarena_huge_dalloc_stats_update(arena, oldsize);\n\tarena_huge_malloc_stats_update(arena, usize);\n}\n\nstatic void\narena_huge_ralloc_stats_update_undo(arena_t *arena, size_t oldsize,\n    size_t usize)\n{\n\n\tarena_huge_dalloc_stats_update_undo(arena, oldsize);\n\tarena_huge_malloc_stats_update_undo(arena, usize);\n}\n\nextent_node_t *\narena_node_alloc(tsdn_t *tsdn, arena_t *arena)\n{\n\textent_node_t *node;\n\n\tmalloc_mutex_lock(tsdn, &arena->node_cache_mtx);\n\tnode = ql_last(&arena->node_cache, ql_link);\n\tif (node == NULL) {\n\t\tmalloc_mutex_unlock(tsdn, &arena->node_cache_mtx);\n\t\treturn (base_alloc(tsdn, sizeof(extent_node_t)));\n\t}\n\tql_tail_remove(&arena->node_cache, extent_node_t, ql_link);\n\tmalloc_mutex_unlock(tsdn, &arena->node_cache_mtx);\n\treturn (node);\n}\n\nvoid\narena_node_dalloc(tsdn_t *tsdn, arena_t *arena, extent_node_t *node)\n{\n\n\tmalloc_mutex_lock(tsdn, &arena->node_cache_mtx);\n\tql_elm_new(node, ql_link);\n\tql_tail_insert(&arena->node_cache, node, ql_link);\n\tmalloc_mutex_unlock(tsdn, &arena->node_cache_mtx);\n}\n\nstatic void *\narena_chunk_alloc_huge_hard(tsdn_t *tsdn, arena_t *arena,\n    chunk_hooks_t *chunk_hooks, size_t usize, size_t alignment, bool *zero,\n    size_t csize)\n{\n\tvoid *ret;\n\tbool commit = true;\n\n\tret = chunk_alloc_wrapper(tsdn, arena, chunk_hooks, NULL, csize,\n\t    alignment, zero, &commit);\n\tif (ret == NULL) {\n\t\t/* Revert optimistic stats updates. */\n\t\tmalloc_mutex_lock(tsdn, &arena->lock);\n\t\tif (config_stats) {\n\t\t\tarena_huge_malloc_stats_update_undo(arena, usize);\n\t\t\tarena->stats.mapped -= usize;\n\t\t}\n\t\tarena_nactive_sub(arena, usize >> LG_PAGE);\n\t\tmalloc_mutex_unlock(tsdn, &arena->lock);\n\t}\n\n\treturn (ret);\n}\n\nvoid *\narena_chunk_alloc_huge(tsdn_t *tsdn, arena_t *arena, size_t usize,\n    size_t alignment, bool *zero)\n{\n\tvoid *ret;\n\tchunk_hooks_t chunk_hooks = CHUNK_HOOKS_INITIALIZER;\n\tsize_t csize = CHUNK_CEILING(usize);\n\n\tmalloc_mutex_lock(tsdn, &arena->lock);\n\n\t/* Optimistically update stats. */\n\tif (config_stats) {\n\t\tarena_huge_malloc_stats_update(arena, usize);\n\t\tarena->stats.mapped += usize;\n\t}\n\tarena_nactive_add(arena, usize >> LG_PAGE);\n\n\tret = chunk_alloc_cache(tsdn, arena, &chunk_hooks, NULL, csize,\n\t    alignment, zero, true);\n\tmalloc_mutex_unlock(tsdn, &arena->lock);\n\tif (ret == NULL) {\n\t\tret = arena_chunk_alloc_huge_hard(tsdn, arena, &chunk_hooks,\n\t\t    usize, alignment, zero, csize);\n\t}\n\n\treturn (ret);\n}\n\nvoid\narena_chunk_dalloc_huge(tsdn_t *tsdn, arena_t *arena, void *chunk, size_t usize)\n{\n\tchunk_hooks_t chunk_hooks = CHUNK_HOOKS_INITIALIZER;\n\tsize_t csize;\n\n\tcsize = CHUNK_CEILING(usize);\n\tmalloc_mutex_lock(tsdn, &arena->lock);\n\tif (config_stats) {\n\t\tarena_huge_dalloc_stats_update(arena, usize);\n\t\tarena->stats.mapped -= usize;\n\t}\n\tarena_nactive_sub(arena, usize >> LG_PAGE);\n\n\tchunk_dalloc_cache(tsdn, arena, &chunk_hooks, chunk, csize, true);\n\tmalloc_mutex_unlock(tsdn, &arena->lock);\n}\n\nvoid\narena_chunk_ralloc_huge_similar(tsdn_t *tsdn, arena_t *arena, void *chunk,\n    size_t oldsize, size_t usize)\n{\n\n\tassert(CHUNK_CEILING(oldsize) == CHUNK_CEILING(usize));\n\tassert(oldsize != usize);\n\n\tmalloc_mutex_lock(tsdn, &arena->lock);\n\tif (config_stats)\n\t\tarena_huge_ralloc_stats_update(arena, oldsize, usize);\n\tif (oldsize < usize)\n\t\tarena_nactive_add(arena, (usize - oldsize) >> LG_PAGE);\n\telse\n\t\tarena_nactive_sub(arena, (oldsize - usize) >> LG_PAGE);\n\tmalloc_mutex_unlock(tsdn, &arena->lock);\n}\n\nvoid\narena_chunk_ralloc_huge_shrink(tsdn_t *tsdn, arena_t *arena, void *chunk,\n    size_t oldsize, size_t usize)\n{\n\tsize_t udiff = oldsize - usize;\n\tsize_t cdiff = CHUNK_CEILING(oldsize) - CHUNK_CEILING(usize);\n\n\tmalloc_mutex_lock(tsdn, &arena->lock);\n\tif (config_stats) {\n\t\tarena_huge_ralloc_stats_update(arena, oldsize, usize);\n\t\tif (cdiff != 0)\n\t\t\tarena->stats.mapped -= cdiff;\n\t}\n\tarena_nactive_sub(arena, udiff >> LG_PAGE);\n\n\tif (cdiff != 0) {\n\t\tchunk_hooks_t chunk_hooks = CHUNK_HOOKS_INITIALIZER;\n\t\tvoid *nchunk = (void *)((uintptr_t)chunk +\n\t\t    CHUNK_CEILING(usize));\n\n\t\tchunk_dalloc_cache(tsdn, arena, &chunk_hooks, nchunk, cdiff,\n\t\t    true);\n\t}\n\tmalloc_mutex_unlock(tsdn, &arena->lock);\n}\n\nstatic bool\narena_chunk_ralloc_huge_expand_hard(tsdn_t *tsdn, arena_t *arena,\n    chunk_hooks_t *chunk_hooks, void *chunk, size_t oldsize, size_t usize,\n    bool *zero, void *nchunk, size_t udiff, size_t cdiff)\n{\n\tbool err;\n\tbool commit = true;\n\n\terr = (chunk_alloc_wrapper(tsdn, arena, chunk_hooks, nchunk, cdiff,\n\t    chunksize, zero, &commit) == NULL);\n\tif (err) {\n\t\t/* Revert optimistic stats updates. */\n\t\tmalloc_mutex_lock(tsdn, &arena->lock);\n\t\tif (config_stats) {\n\t\t\tarena_huge_ralloc_stats_update_undo(arena, oldsize,\n\t\t\t    usize);\n\t\t\tarena->stats.mapped -= cdiff;\n\t\t}\n\t\tarena_nactive_sub(arena, udiff >> LG_PAGE);\n\t\tmalloc_mutex_unlock(tsdn, &arena->lock);\n\t} else if (chunk_hooks->merge(chunk, CHUNK_CEILING(oldsize), nchunk,\n\t    cdiff, true, arena->ind)) {\n\t\tchunk_dalloc_wrapper(tsdn, arena, chunk_hooks, nchunk, cdiff,\n\t\t    *zero, true);\n\t\terr = true;\n\t}\n\treturn (err);\n}\n\nbool\narena_chunk_ralloc_huge_expand(tsdn_t *tsdn, arena_t *arena, void *chunk,\n    size_t oldsize, size_t usize, bool *zero)\n{\n\tbool err;\n\tchunk_hooks_t chunk_hooks = chunk_hooks_get(tsdn, arena);\n\tvoid *nchunk = (void *)((uintptr_t)chunk + CHUNK_CEILING(oldsize));\n\tsize_t udiff = usize - oldsize;\n\tsize_t cdiff = CHUNK_CEILING(usize) - CHUNK_CEILING(oldsize);\n\n\tmalloc_mutex_lock(tsdn, &arena->lock);\n\n\t/* Optimistically update stats. */\n\tif (config_stats) {\n\t\tarena_huge_ralloc_stats_update(arena, oldsize, usize);\n\t\tarena->stats.mapped += cdiff;\n\t}\n\tarena_nactive_add(arena, udiff >> LG_PAGE);\n\n\terr = (chunk_alloc_cache(tsdn, arena, &chunk_hooks, nchunk, cdiff,\n\t    chunksize, zero, true) == NULL);\n\tmalloc_mutex_unlock(tsdn, &arena->lock);\n\tif (err) {\n\t\terr = arena_chunk_ralloc_huge_expand_hard(tsdn, arena,\n\t\t    &chunk_hooks, chunk, oldsize, usize, zero, nchunk, udiff,\n\t\t    cdiff);\n\t} else if (chunk_hooks.merge(chunk, CHUNK_CEILING(oldsize), nchunk,\n\t    cdiff, true, arena->ind)) {\n\t\tchunk_dalloc_wrapper(tsdn, arena, &chunk_hooks, nchunk, cdiff,\n\t\t    *zero, true);\n\t\terr = true;\n\t}\n\n\treturn (err);\n}\n\n/*\n * Do first-best-fit run selection, i.e. select the lowest run that best fits.\n * Run sizes are indexed, so not all candidate runs are necessarily exactly the\n * same size.\n */\nstatic arena_run_t *\narena_run_first_best_fit(arena_t *arena, size_t size)\n{\n\tszind_t ind, i;\n\n\tind = size2index(run_quantize_ceil(size));\n\tfor (i = ind; i < runs_avail_nclasses + runs_avail_bias; i++) {\n\t\tarena_chunk_map_misc_t *miscelm = arena_run_heap_first(\n\t\t    arena_runs_avail_get(arena, i));\n\t\tif (miscelm != NULL)\n\t\t\treturn (&miscelm->run);\n\t}\n\n\treturn (NULL);\n}\n\nstatic arena_run_t *\narena_run_alloc_large_helper(arena_t *arena, size_t size, bool zero)\n{\n\tarena_run_t *run = arena_run_first_best_fit(arena, s2u(size));\n\tif (run != NULL) {\n\t\tif (arena_run_split_large(arena, run, size, zero))\n\t\t\trun = NULL;\n\t}\n\treturn (run);\n}\n\nstatic arena_run_t *\narena_run_alloc_large(tsdn_t *tsdn, arena_t *arena, size_t size, bool zero)\n{\n\tarena_chunk_t *chunk;\n\tarena_run_t *run;\n\n\tassert(size <= arena_maxrun);\n\tassert(size == PAGE_CEILING(size));\n\n\t/* Search the arena's chunks for the lowest best fit. */\n\trun = arena_run_alloc_large_helper(arena, size, zero);\n\tif (run != NULL)\n\t\treturn (run);\n\n\t/*\n\t * No usable runs.  Create a new chunk from which to allocate the run.\n\t */\n\tchunk = arena_chunk_alloc(tsdn, arena);\n\tif (chunk != NULL) {\n\t\trun = &arena_miscelm_get_mutable(chunk, map_bias)->run;\n\t\tif (arena_run_split_large(arena, run, size, zero))\n\t\t\trun = NULL;\n\t\treturn (run);\n\t}\n\n\t/*\n\t * arena_chunk_alloc() failed, but another thread may have made\n\t * sufficient memory available while this one dropped arena->lock in\n\t * arena_chunk_alloc(), so search one more time.\n\t */\n\treturn (arena_run_alloc_large_helper(arena, size, zero));\n}\n\nstatic arena_run_t *\narena_run_alloc_small_helper(arena_t *arena, size_t size, szind_t binind)\n{\n\tarena_run_t *run = arena_run_first_best_fit(arena, size);\n\tif (run != NULL) {\n\t\tif (arena_run_split_small(arena, run, size, binind))\n\t\t\trun = NULL;\n\t}\n\treturn (run);\n}\n\nstatic arena_run_t *\narena_run_alloc_small(tsdn_t *tsdn, arena_t *arena, size_t size, szind_t binind)\n{\n\tarena_chunk_t *chunk;\n\tarena_run_t *run;\n\n\tassert(size <= arena_maxrun);\n\tassert(size == PAGE_CEILING(size));\n\tassert(binind != BININD_INVALID);\n\n\t/* Search the arena's chunks for the lowest best fit. */\n\trun = arena_run_alloc_small_helper(arena, size, binind);\n\tif (run != NULL)\n\t\treturn (run);\n\n\t/*\n\t * No usable runs.  Create a new chunk from which to allocate the run.\n\t */\n\tchunk = arena_chunk_alloc(tsdn, arena);\n\tif (chunk != NULL) {\n\t\trun = &arena_miscelm_get_mutable(chunk, map_bias)->run;\n\t\tif (arena_run_split_small(arena, run, size, binind))\n\t\t\trun = NULL;\n\t\treturn (run);\n\t}\n\n\t/*\n\t * arena_chunk_alloc() failed, but another thread may have made\n\t * sufficient memory available while this one dropped arena->lock in\n\t * arena_chunk_alloc(), so search one more time.\n\t */\n\treturn (arena_run_alloc_small_helper(arena, size, binind));\n}\n\nstatic bool\narena_lg_dirty_mult_valid(ssize_t lg_dirty_mult)\n{\n\n\treturn (lg_dirty_mult >= -1 && lg_dirty_mult < (ssize_t)(sizeof(size_t)\n\t    << 3));\n}\n\nssize_t\narena_lg_dirty_mult_get(tsdn_t *tsdn, arena_t *arena)\n{\n\tssize_t lg_dirty_mult;\n\n\tmalloc_mutex_lock(tsdn, &arena->lock);\n\tlg_dirty_mult = arena->lg_dirty_mult;\n\tmalloc_mutex_unlock(tsdn, &arena->lock);\n\n\treturn (lg_dirty_mult);\n}\n\nbool\narena_lg_dirty_mult_set(tsdn_t *tsdn, arena_t *arena, ssize_t lg_dirty_mult)\n{\n\n\tif (!arena_lg_dirty_mult_valid(lg_dirty_mult))\n\t\treturn (true);\n\n\tmalloc_mutex_lock(tsdn, &arena->lock);\n\tarena->lg_dirty_mult = lg_dirty_mult;\n\tarena_maybe_purge(tsdn, arena);\n\tmalloc_mutex_unlock(tsdn, &arena->lock);\n\n\treturn (false);\n}\n\nstatic void\narena_decay_deadline_init(arena_t *arena)\n{\n\n\tassert(opt_purge == purge_mode_decay);\n\n\t/*\n\t * Generate a new deadline that is uniformly random within the next\n\t * epoch after the current one.\n\t */\n\tnstime_copy(&arena->decay_deadline, &arena->decay_epoch);\n\tnstime_add(&arena->decay_deadline, &arena->decay_interval);\n\tif (arena->decay_time > 0) {\n\t\tnstime_t jitter;\n\n\t\tnstime_init(&jitter, prng_range(&arena->decay_jitter_state,\n\t\t    nstime_ns(&arena->decay_interval)));\n\t\tnstime_add(&arena->decay_deadline, &jitter);\n\t}\n}\n\nstatic bool\narena_decay_deadline_reached(const arena_t *arena, const nstime_t *time)\n{\n\n\tassert(opt_purge == purge_mode_decay);\n\n\treturn (nstime_compare(&arena->decay_deadline, time) <= 0);\n}\n\nstatic size_t\narena_decay_backlog_npages_limit(const arena_t *arena)\n{\n\tstatic const uint64_t h_steps[] = {\n#define\tSTEP(step, h, x, y) \\\n\t\th,\n\t\tSMOOTHSTEP\n#undef STEP\n\t};\n\tuint64_t sum;\n\tsize_t npages_limit_backlog;\n\tunsigned i;\n\n\tassert(opt_purge == purge_mode_decay);\n\n\t/*\n\t * For each element of decay_backlog, multiply by the corresponding\n\t * fixed-point smoothstep decay factor.  Sum the products, then divide\n\t * to round down to the nearest whole number of pages.\n\t */\n\tsum = 0;\n\tfor (i = 0; i < SMOOTHSTEP_NSTEPS; i++)\n\t\tsum += arena->decay_backlog[i] * h_steps[i];\n\tnpages_limit_backlog = (size_t)(sum >> SMOOTHSTEP_BFP);\n\n\treturn (npages_limit_backlog);\n}\n\nstatic void\narena_decay_epoch_advance(arena_t *arena, const nstime_t *time)\n{\n\tuint64_t nadvance_u64;\n\tnstime_t delta;\n\tsize_t ndirty_delta;\n\n\tassert(opt_purge == purge_mode_decay);\n\tassert(arena_decay_deadline_reached(arena, time));\n\n\tnstime_copy(&delta, time);\n\tnstime_subtract(&delta, &arena->decay_epoch);\n\tnadvance_u64 = nstime_divide(&delta, &arena->decay_interval);\n\tassert(nadvance_u64 > 0);\n\n\t/* Add nadvance_u64 decay intervals to epoch. */\n\tnstime_copy(&delta, &arena->decay_interval);\n\tnstime_imultiply(&delta, nadvance_u64);\n\tnstime_add(&arena->decay_epoch, &delta);\n\n\t/* Set a new deadline. */\n\tarena_decay_deadline_init(arena);\n\n\t/* Update the backlog. */\n\tif (nadvance_u64 >= SMOOTHSTEP_NSTEPS) {\n\t\tmemset(arena->decay_backlog, 0, (SMOOTHSTEP_NSTEPS-1) *\n\t\t    sizeof(size_t));\n\t} else {\n\t\tsize_t nadvance_z = (size_t)nadvance_u64;\n\n\t\tassert((uint64_t)nadvance_z == nadvance_u64);\n\n\t\tmemmove(arena->decay_backlog, &arena->decay_backlog[nadvance_z],\n\t\t    (SMOOTHSTEP_NSTEPS - nadvance_z) * sizeof(size_t));\n\t\tif (nadvance_z > 1) {\n\t\t\tmemset(&arena->decay_backlog[SMOOTHSTEP_NSTEPS -\n\t\t\t    nadvance_z], 0, (nadvance_z-1) * sizeof(size_t));\n\t\t}\n\t}\n\tndirty_delta = (arena->ndirty > arena->decay_ndirty) ? arena->ndirty -\n\t    arena->decay_ndirty : 0;\n\tarena->decay_ndirty = arena->ndirty;\n\tarena->decay_backlog[SMOOTHSTEP_NSTEPS-1] = ndirty_delta;\n\tarena->decay_backlog_npages_limit =\n\t    arena_decay_backlog_npages_limit(arena);\n}\n\nstatic size_t\narena_decay_npages_limit(arena_t *arena)\n{\n\tsize_t npages_limit;\n\n\tassert(opt_purge == purge_mode_decay);\n\n\tnpages_limit = arena->decay_backlog_npages_limit;\n\n\t/* Add in any dirty pages created during the current epoch. */\n\tif (arena->ndirty > arena->decay_ndirty)\n\t\tnpages_limit += arena->ndirty - arena->decay_ndirty;\n\n\treturn (npages_limit);\n}\n\nstatic void\narena_decay_init(arena_t *arena, ssize_t decay_time)\n{\n\n\tarena->decay_time = decay_time;\n\tif (decay_time > 0) {\n\t\tnstime_init2(&arena->decay_interval, decay_time, 0);\n\t\tnstime_idivide(&arena->decay_interval, SMOOTHSTEP_NSTEPS);\n\t}\n\n\tnstime_init(&arena->decay_epoch, 0);\n\tnstime_update(&arena->decay_epoch);\n\tarena->decay_jitter_state = (uint64_t)(uintptr_t)arena;\n\tarena_decay_deadline_init(arena);\n\tarena->decay_ndirty = arena->ndirty;\n\tarena->decay_backlog_npages_limit = 0;\n\tmemset(arena->decay_backlog, 0, SMOOTHSTEP_NSTEPS * sizeof(size_t));\n}\n\nstatic bool\narena_decay_time_valid(ssize_t decay_time)\n{\n\n\tif (decay_time < -1)\n\t\treturn (false);\n\tif (decay_time == -1 || (uint64_t)decay_time <= NSTIME_SEC_MAX)\n\t\treturn (true);\n\treturn (false);\n}\n\nssize_t\narena_decay_time_get(tsdn_t *tsdn, arena_t *arena)\n{\n\tssize_t decay_time;\n\n\tmalloc_mutex_lock(tsdn, &arena->lock);\n\tdecay_time = arena->decay_time;\n\tmalloc_mutex_unlock(tsdn, &arena->lock);\n\n\treturn (decay_time);\n}\n\nbool\narena_decay_time_set(tsdn_t *tsdn, arena_t *arena, ssize_t decay_time)\n{\n\n\tif (!arena_decay_time_valid(decay_time))\n\t\treturn (true);\n\n\tmalloc_mutex_lock(tsdn, &arena->lock);\n\t/*\n\t * Restart decay backlog from scratch, which may cause many dirty pages\n\t * to be immediately purged.  It would conceptually be possible to map\n\t * the old backlog onto the new backlog, but there is no justification\n\t * for such complexity since decay_time changes are intended to be\n\t * infrequent, either between the {-1, 0, >0} states, or a one-time\n\t * arbitrary change during initial arena configuration.\n\t */\n\tarena_decay_init(arena, decay_time);\n\tarena_maybe_purge(tsdn, arena);\n\tmalloc_mutex_unlock(tsdn, &arena->lock);\n\n\treturn (false);\n}\n\nstatic void\narena_maybe_purge_ratio(tsdn_t *tsdn, arena_t *arena)\n{\n\n\tassert(opt_purge == purge_mode_ratio);\n\n\t/* Don't purge if the option is disabled. */\n\tif (arena->lg_dirty_mult < 0)\n\t\treturn;\n\n\t/*\n\t * Iterate, since preventing recursive purging could otherwise leave too\n\t * many dirty pages.\n\t */\n\twhile (true) {\n\t\tsize_t threshold = (arena->nactive >> arena->lg_dirty_mult);\n\t\tif (threshold < chunk_npages)\n\t\t\tthreshold = chunk_npages;\n\t\t/*\n\t\t * Don't purge unless the number of purgeable pages exceeds the\n\t\t * threshold.\n\t\t */\n\t\tif (arena->ndirty <= threshold)\n\t\t\treturn;\n\t\tarena_purge_to_limit(tsdn, arena, threshold);\n\t}\n}\n\nstatic void\narena_maybe_purge_decay(tsdn_t *tsdn, arena_t *arena)\n{\n\tnstime_t time;\n\tsize_t ndirty_limit;\n\n\tassert(opt_purge == purge_mode_decay);\n\n\t/* Purge all or nothing if the option is disabled. */\n\tif (arena->decay_time <= 0) {\n\t\tif (arena->decay_time == 0)\n\t\t\tarena_purge_to_limit(tsdn, arena, 0);\n\t\treturn;\n\t}\n\n\tnstime_copy(&time, &arena->decay_epoch);\n\tif (unlikely(nstime_update(&time))) {\n\t\t/* Time went backwards.  Force an epoch advance. */\n\t\tnstime_copy(&time, &arena->decay_deadline);\n\t}\n\n\tif (arena_decay_deadline_reached(arena, &time))\n\t\tarena_decay_epoch_advance(arena, &time);\n\n\tndirty_limit = arena_decay_npages_limit(arena);\n\n\t/*\n\t * Don't try to purge unless the number of purgeable pages exceeds the\n\t * current limit.\n\t */\n\tif (arena->ndirty <= ndirty_limit)\n\t\treturn;\n\tarena_purge_to_limit(tsdn, arena, ndirty_limit);\n}\n\nvoid\narena_maybe_purge(tsdn_t *tsdn, arena_t *arena)\n{\n\n\t/* Don't recursively purge. */\n\tif (arena->purging)\n\t\treturn;\n\n\tif (opt_purge == purge_mode_ratio)\n\t\tarena_maybe_purge_ratio(tsdn, arena);\n\telse\n\t\tarena_maybe_purge_decay(tsdn, arena);\n}\n\nstatic size_t\narena_dirty_count(arena_t *arena)\n{\n\tsize_t ndirty = 0;\n\tarena_runs_dirty_link_t *rdelm;\n\textent_node_t *chunkselm;\n\n\tfor (rdelm = qr_next(&arena->runs_dirty, rd_link),\n\t    chunkselm = qr_next(&arena->chunks_cache, cc_link);\n\t    rdelm != &arena->runs_dirty; rdelm = qr_next(rdelm, rd_link)) {\n\t\tsize_t npages;\n\n\t\tif (rdelm == &chunkselm->rd) {\n\t\t\tnpages = extent_node_size_get(chunkselm) >> LG_PAGE;\n\t\t\tchunkselm = qr_next(chunkselm, cc_link);\n\t\t} else {\n\t\t\tarena_chunk_t *chunk = (arena_chunk_t *)CHUNK_ADDR2BASE(\n\t\t\t    rdelm);\n\t\t\tarena_chunk_map_misc_t *miscelm =\n\t\t\t    arena_rd_to_miscelm(rdelm);\n\t\t\tsize_t pageind = arena_miscelm_to_pageind(miscelm);\n\t\t\tassert(arena_mapbits_allocated_get(chunk, pageind) ==\n\t\t\t    0);\n\t\t\tassert(arena_mapbits_large_get(chunk, pageind) == 0);\n\t\t\tassert(arena_mapbits_dirty_get(chunk, pageind) != 0);\n\t\t\tnpages = arena_mapbits_unallocated_size_get(chunk,\n\t\t\t    pageind) >> LG_PAGE;\n\t\t}\n\t\tndirty += npages;\n\t}\n\n\treturn (ndirty);\n}\n\nstatic size_t\narena_stash_dirty(tsdn_t *tsdn, arena_t *arena, chunk_hooks_t *chunk_hooks,\n    size_t ndirty_limit, arena_runs_dirty_link_t *purge_runs_sentinel,\n    extent_node_t *purge_chunks_sentinel)\n{\n\tarena_runs_dirty_link_t *rdelm, *rdelm_next;\n\textent_node_t *chunkselm;\n\tsize_t nstashed = 0;\n\n\t/* Stash runs/chunks according to ndirty_limit. */\n\tfor (rdelm = qr_next(&arena->runs_dirty, rd_link),\n\t    chunkselm = qr_next(&arena->chunks_cache, cc_link);\n\t    rdelm != &arena->runs_dirty; rdelm = rdelm_next) {\n\t\tsize_t npages;\n\t\trdelm_next = qr_next(rdelm, rd_link);\n\n\t\tif (rdelm == &chunkselm->rd) {\n\t\t\textent_node_t *chunkselm_next;\n\t\t\tbool zero;\n\t\t\tUNUSED void *chunk;\n\n\t\t\tnpages = extent_node_size_get(chunkselm) >> LG_PAGE;\n\t\t\tif (opt_purge == purge_mode_decay && arena->ndirty -\n\t\t\t    (nstashed + npages) < ndirty_limit)\n\t\t\t\tbreak;\n\n\t\t\tchunkselm_next = qr_next(chunkselm, cc_link);\n\t\t\t/*\n\t\t\t * Allocate.  chunkselm remains valid due to the\n\t\t\t * dalloc_node=false argument to chunk_alloc_cache().\n\t\t\t */\n\t\t\tzero = false;\n\t\t\tchunk = chunk_alloc_cache(tsdn, arena, chunk_hooks,\n\t\t\t    extent_node_addr_get(chunkselm),\n\t\t\t    extent_node_size_get(chunkselm), chunksize, &zero,\n\t\t\t    false);\n\t\t\tassert(chunk == extent_node_addr_get(chunkselm));\n\t\t\tassert(zero == extent_node_zeroed_get(chunkselm));\n\t\t\textent_node_dirty_insert(chunkselm, purge_runs_sentinel,\n\t\t\t    purge_chunks_sentinel);\n\t\t\tassert(npages == (extent_node_size_get(chunkselm) >>\n\t\t\t    LG_PAGE));\n\t\t\tchunkselm = chunkselm_next;\n\t\t} else {\n\t\t\tarena_chunk_t *chunk =\n\t\t\t    (arena_chunk_t *)CHUNK_ADDR2BASE(rdelm);\n\t\t\tarena_chunk_map_misc_t *miscelm =\n\t\t\t    arena_rd_to_miscelm(rdelm);\n\t\t\tsize_t pageind = arena_miscelm_to_pageind(miscelm);\n\t\t\tarena_run_t *run = &miscelm->run;\n\t\t\tsize_t run_size =\n\t\t\t    arena_mapbits_unallocated_size_get(chunk, pageind);\n\n\t\t\tnpages = run_size >> LG_PAGE;\n\t\t\tif (opt_purge == purge_mode_decay && arena->ndirty -\n\t\t\t    (nstashed + npages) < ndirty_limit)\n\t\t\t\tbreak;\n\n\t\t\tassert(pageind + npages <= chunk_npages);\n\t\t\tassert(arena_mapbits_dirty_get(chunk, pageind) ==\n\t\t\t    arena_mapbits_dirty_get(chunk, pageind+npages-1));\n\n\t\t\t/*\n\t\t\t * If purging the spare chunk's run, make it available\n\t\t\t * prior to allocation.\n\t\t\t */\n\t\t\tif (chunk == arena->spare)\n\t\t\t\tarena_chunk_alloc(tsdn, arena);\n\n\t\t\t/* Temporarily allocate the free dirty run. */\n\t\t\tarena_run_split_large(arena, run, run_size, false);\n\t\t\t/* Stash. */\n\t\t\tif (false)\n\t\t\t\tqr_new(rdelm, rd_link); /* Redundant. */\n\t\t\telse {\n\t\t\t\tassert(qr_next(rdelm, rd_link) == rdelm);\n\t\t\t\tassert(qr_prev(rdelm, rd_link) == rdelm);\n\t\t\t}\n\t\t\tqr_meld(purge_runs_sentinel, rdelm, rd_link);\n\t\t}\n\n\t\tnstashed += npages;\n\t\tif (opt_purge == purge_mode_ratio && arena->ndirty - nstashed <=\n\t\t    ndirty_limit)\n\t\t\tbreak;\n\t}\n\n\treturn (nstashed);\n}\n\nstatic size_t\narena_purge_stashed(tsdn_t *tsdn, arena_t *arena, chunk_hooks_t *chunk_hooks,\n    arena_runs_dirty_link_t *purge_runs_sentinel,\n    extent_node_t *purge_chunks_sentinel)\n{\n\tsize_t npurged, nmadvise;\n\tarena_runs_dirty_link_t *rdelm;\n\textent_node_t *chunkselm;\n\n\tif (config_stats)\n\t\tnmadvise = 0;\n\tnpurged = 0;\n\n\tmalloc_mutex_unlock(tsdn, &arena->lock);\n\tfor (rdelm = qr_next(purge_runs_sentinel, rd_link),\n\t    chunkselm = qr_next(purge_chunks_sentinel, cc_link);\n\t    rdelm != purge_runs_sentinel; rdelm = qr_next(rdelm, rd_link)) {\n\t\tsize_t npages;\n\n\t\tif (rdelm == &chunkselm->rd) {\n\t\t\t/*\n\t\t\t * Don't actually purge the chunk here because 1)\n\t\t\t * chunkselm is embedded in the chunk and must remain\n\t\t\t * valid, and 2) we deallocate the chunk in\n\t\t\t * arena_unstash_purged(), where it is destroyed,\n\t\t\t * decommitted, or purged, depending on chunk\n\t\t\t * deallocation policy.\n\t\t\t */\n\t\t\tsize_t size = extent_node_size_get(chunkselm);\n\t\t\tnpages = size >> LG_PAGE;\n\t\t\tchunkselm = qr_next(chunkselm, cc_link);\n\t\t} else {\n\t\t\tsize_t pageind, run_size, flag_unzeroed, flags, i;\n\t\t\tbool decommitted;\n\t\t\tarena_chunk_t *chunk =\n\t\t\t    (arena_chunk_t *)CHUNK_ADDR2BASE(rdelm);\n\t\t\tarena_chunk_map_misc_t *miscelm =\n\t\t\t    arena_rd_to_miscelm(rdelm);\n\t\t\tpageind = arena_miscelm_to_pageind(miscelm);\n\t\t\trun_size = arena_mapbits_large_size_get(chunk, pageind);\n\t\t\tnpages = run_size >> LG_PAGE;\n\n\t\t\tassert(pageind + npages <= chunk_npages);\n\t\t\tassert(!arena_mapbits_decommitted_get(chunk, pageind));\n\t\t\tassert(!arena_mapbits_decommitted_get(chunk,\n\t\t\t    pageind+npages-1));\n\t\t\tdecommitted = !chunk_hooks->decommit(chunk, chunksize,\n\t\t\t    pageind << LG_PAGE, npages << LG_PAGE, arena->ind);\n\t\t\tif (decommitted) {\n\t\t\t\tflag_unzeroed = 0;\n\t\t\t\tflags = CHUNK_MAP_DECOMMITTED;\n\t\t\t} else {\n\t\t\t\tflag_unzeroed = chunk_purge_wrapper(tsdn, arena,\n\t\t\t\t    chunk_hooks, chunk, chunksize, pageind <<\n\t\t\t\t    LG_PAGE, run_size) ? CHUNK_MAP_UNZEROED : 0;\n\t\t\t\tflags = flag_unzeroed;\n\t\t\t}\n\t\t\tarena_mapbits_large_set(chunk, pageind+npages-1, 0,\n\t\t\t    flags);\n\t\t\tarena_mapbits_large_set(chunk, pageind, run_size,\n\t\t\t    flags);\n\n\t\t\t/*\n\t\t\t * Set the unzeroed flag for internal pages, now that\n\t\t\t * chunk_purge_wrapper() has returned whether the pages\n\t\t\t * were zeroed as a side effect of purging.  This chunk\n\t\t\t * map modification is safe even though the arena mutex\n\t\t\t * isn't currently owned by this thread, because the run\n\t\t\t * is marked as allocated, thus protecting it from being\n\t\t\t * modified by any other thread.  As long as these\n\t\t\t * writes don't perturb the first and last elements'\n\t\t\t * CHUNK_MAP_ALLOCATED bits, behavior is well defined.\n\t\t\t */\n\t\t\tfor (i = 1; i < npages-1; i++) {\n\t\t\t\tarena_mapbits_internal_set(chunk, pageind+i,\n\t\t\t\t    flag_unzeroed);\n\t\t\t}\n\t\t}\n\n\t\tnpurged += npages;\n\t\tif (config_stats)\n\t\t\tnmadvise++;\n\t}\n\tmalloc_mutex_lock(tsdn, &arena->lock);\n\n\tif (config_stats) {\n\t\tarena->stats.nmadvise += nmadvise;\n\t\tarena->stats.purged += npurged;\n\t}\n\n\treturn (npurged);\n}\n\nstatic void\narena_unstash_purged(tsdn_t *tsdn, arena_t *arena, chunk_hooks_t *chunk_hooks,\n    arena_runs_dirty_link_t *purge_runs_sentinel,\n    extent_node_t *purge_chunks_sentinel)\n{\n\tarena_runs_dirty_link_t *rdelm, *rdelm_next;\n\textent_node_t *chunkselm;\n\n\t/* Deallocate chunks/runs. */\n\tfor (rdelm = qr_next(purge_runs_sentinel, rd_link),\n\t    chunkselm = qr_next(purge_chunks_sentinel, cc_link);\n\t    rdelm != purge_runs_sentinel; rdelm = rdelm_next) {\n\t\trdelm_next = qr_next(rdelm, rd_link);\n\t\tif (rdelm == &chunkselm->rd) {\n\t\t\textent_node_t *chunkselm_next = qr_next(chunkselm,\n\t\t\t    cc_link);\n\t\t\tvoid *addr = extent_node_addr_get(chunkselm);\n\t\t\tsize_t size = extent_node_size_get(chunkselm);\n\t\t\tbool zeroed = extent_node_zeroed_get(chunkselm);\n\t\t\tbool committed = extent_node_committed_get(chunkselm);\n\t\t\textent_node_dirty_remove(chunkselm);\n\t\t\tarena_node_dalloc(tsdn, arena, chunkselm);\n\t\t\tchunkselm = chunkselm_next;\n\t\t\tchunk_dalloc_wrapper(tsdn, arena, chunk_hooks, addr,\n\t\t\t    size, zeroed, committed);\n\t\t} else {\n\t\t\tarena_chunk_t *chunk =\n\t\t\t    (arena_chunk_t *)CHUNK_ADDR2BASE(rdelm);\n\t\t\tarena_chunk_map_misc_t *miscelm =\n\t\t\t    arena_rd_to_miscelm(rdelm);\n\t\t\tsize_t pageind = arena_miscelm_to_pageind(miscelm);\n\t\t\tbool decommitted = (arena_mapbits_decommitted_get(chunk,\n\t\t\t    pageind) != 0);\n\t\t\tarena_run_t *run = &miscelm->run;\n\t\t\tqr_remove(rdelm, rd_link);\n\t\t\tarena_run_dalloc(tsdn, arena, run, false, true,\n\t\t\t    decommitted);\n\t\t}\n\t}\n}\n\n/*\n * NB: ndirty_limit is interpreted differently depending on opt_purge:\n *   - purge_mode_ratio: Purge as few dirty run/chunks as possible to reach the\n *                       desired state:\n *                       (arena->ndirty <= ndirty_limit)\n *   - purge_mode_decay: Purge as many dirty runs/chunks as possible without\n *                       violating the invariant:\n *                       (arena->ndirty >= ndirty_limit)\n */\nstatic void\narena_purge_to_limit(tsdn_t *tsdn, arena_t *arena, size_t ndirty_limit)\n{\n\tchunk_hooks_t chunk_hooks = chunk_hooks_get(tsdn, arena);\n\tsize_t npurge, npurged;\n\tarena_runs_dirty_link_t purge_runs_sentinel;\n\textent_node_t purge_chunks_sentinel;\n\n\tarena->purging = true;\n\n\t/*\n\t * Calls to arena_dirty_count() are disabled even for debug builds\n\t * because overhead grows nonlinearly as memory usage increases.\n\t */\n\tif (false && config_debug) {\n\t\tsize_t ndirty = arena_dirty_count(arena);\n\t\tassert(ndirty == arena->ndirty);\n\t}\n\tassert(opt_purge != purge_mode_ratio || (arena->nactive >>\n\t    arena->lg_dirty_mult) < arena->ndirty || ndirty_limit == 0);\n\n\tqr_new(&purge_runs_sentinel, rd_link);\n\textent_node_dirty_linkage_init(&purge_chunks_sentinel);\n\n\tnpurge = arena_stash_dirty(tsdn, arena, &chunk_hooks, ndirty_limit,\n\t    &purge_runs_sentinel, &purge_chunks_sentinel);\n\tif (npurge == 0)\n\t\tgoto label_return;\n\tnpurged = arena_purge_stashed(tsdn, arena, &chunk_hooks,\n\t    &purge_runs_sentinel, &purge_chunks_sentinel);\n\tassert(npurged == npurge);\n\tarena_unstash_purged(tsdn, arena, &chunk_hooks, &purge_runs_sentinel,\n\t    &purge_chunks_sentinel);\n\n\tif (config_stats)\n\t\tarena->stats.npurge++;\n\nlabel_return:\n\tarena->purging = false;\n}\n\nvoid\narena_purge(tsdn_t *tsdn, arena_t *arena, bool all)\n{\n\n\tmalloc_mutex_lock(tsdn, &arena->lock);\n\tif (all)\n\t\tarena_purge_to_limit(tsdn, arena, 0);\n\telse\n\t\tarena_maybe_purge(tsdn, arena);\n\tmalloc_mutex_unlock(tsdn, &arena->lock);\n}\n\nstatic void\narena_achunk_prof_reset(tsd_t *tsd, arena_t *arena, arena_chunk_t *chunk)\n{\n\tsize_t pageind, npages;\n\n\tcassert(config_prof);\n\tassert(opt_prof);\n\n\t/*\n\t * Iterate over the allocated runs and remove profiled allocations from\n\t * the sample set.\n\t */\n\tfor (pageind = map_bias; pageind < chunk_npages; pageind += npages) {\n\t\tif (arena_mapbits_allocated_get(chunk, pageind) != 0) {\n\t\t\tif (arena_mapbits_large_get(chunk, pageind) != 0) {\n\t\t\t\tvoid *ptr = (void *)((uintptr_t)chunk + (pageind\n\t\t\t\t    << LG_PAGE));\n\t\t\t\tsize_t usize = isalloc(tsd_tsdn(tsd), ptr,\n\t\t\t\t    config_prof);\n\n\t\t\t\tprof_free(tsd, ptr, usize);\n\t\t\t\tnpages = arena_mapbits_large_size_get(chunk,\n\t\t\t\t    pageind) >> LG_PAGE;\n\t\t\t} else {\n\t\t\t\t/* Skip small run. */\n\t\t\t\tsize_t binind = arena_mapbits_binind_get(chunk,\n\t\t\t\t    pageind);\n\t\t\t\tarena_bin_info_t *bin_info =\n\t\t\t\t    &arena_bin_info[binind];\n\t\t\t\tnpages = bin_info->run_size >> LG_PAGE;\n\t\t\t}\n\t\t} else {\n\t\t\t/* Skip unallocated run. */\n\t\t\tnpages = arena_mapbits_unallocated_size_get(chunk,\n\t\t\t    pageind) >> LG_PAGE;\n\t\t}\n\t\tassert(pageind + npages <= chunk_npages);\n\t}\n}\n\nvoid\narena_reset(tsd_t *tsd, arena_t *arena)\n{\n\tunsigned i;\n\textent_node_t *node;\n\n\t/*\n\t * Locking in this function is unintuitive.  The caller guarantees that\n\t * no concurrent operations are happening in this arena, but there are\n\t * still reasons that some locking is necessary:\n\t *\n\t * - Some of the functions in the transitive closure of calls assume\n\t *   appropriate locks are held, and in some cases these locks are\n\t *   temporarily dropped to avoid lock order reversal or deadlock due to\n\t *   reentry.\n\t * - mallctl(\"epoch\", ...) may concurrently refresh stats.  While\n\t *   strictly speaking this is a \"concurrent operation\", disallowing\n\t *   stats refreshes would impose an inconvenient burden.\n\t */\n\n\t/* Remove large allocations from prof sample set. */\n\tif (config_prof && opt_prof) {\n\t\tql_foreach(node, &arena->achunks, ql_link) {\n\t\t\tarena_achunk_prof_reset(tsd, arena,\n\t\t\t    extent_node_addr_get(node));\n\t\t}\n\t}\n\n\t/* Reset curruns for large size classes. */\n\tif (config_stats) {\n\t\tfor (i = 0; i < nlclasses; i++)\n\t\t\tarena->stats.lstats[i].curruns = 0;\n\t}\n\n\t/* Huge allocations. */\n\tmalloc_mutex_lock(tsd_tsdn(tsd), &arena->huge_mtx);\n\tfor (node = ql_last(&arena->huge, ql_link); node != NULL; node =\n\t    ql_last(&arena->huge, ql_link)) {\n\t\tvoid *ptr = extent_node_addr_get(node);\n\t\tsize_t usize;\n\n\t\tmalloc_mutex_unlock(tsd_tsdn(tsd), &arena->huge_mtx);\n\t\tif (config_stats || (config_prof && opt_prof))\n\t\t\tusize = isalloc(tsd_tsdn(tsd), ptr, config_prof);\n\t\t/* Remove huge allocation from prof sample set. */\n\t\tif (config_prof && opt_prof)\n\t\t\tprof_free(tsd, ptr, usize);\n\t\thuge_dalloc(tsd_tsdn(tsd), ptr);\n\t\tmalloc_mutex_lock(tsd_tsdn(tsd), &arena->huge_mtx);\n\t\t/* Cancel out unwanted effects on stats. */\n\t\tif (config_stats)\n\t\t\tarena_huge_reset_stats_cancel(arena, usize);\n\t}\n\tmalloc_mutex_unlock(tsd_tsdn(tsd), &arena->huge_mtx);\n\n\tmalloc_mutex_lock(tsd_tsdn(tsd), &arena->lock);\n\n\t/* Bins. */\n\tfor (i = 0; i < NBINS; i++) {\n\t\tarena_bin_t *bin = &arena->bins[i];\n\t\tmalloc_mutex_lock(tsd_tsdn(tsd), &bin->lock);\n\t\tbin->runcur = NULL;\n\t\tarena_run_heap_new(&bin->runs);\n\t\tif (config_stats) {\n\t\t\tbin->stats.curregs = 0;\n\t\t\tbin->stats.curruns = 0;\n\t\t}\n\t\tmalloc_mutex_unlock(tsd_tsdn(tsd), &bin->lock);\n\t}\n\n\t/*\n\t * Re-initialize runs_dirty such that the chunks_cache and runs_dirty\n\t * chains directly correspond.\n\t */\n\tqr_new(&arena->runs_dirty, rd_link);\n\tfor (node = qr_next(&arena->chunks_cache, cc_link);\n\t    node != &arena->chunks_cache; node = qr_next(node, cc_link)) {\n\t\tqr_new(&node->rd, rd_link);\n\t\tqr_meld(&arena->runs_dirty, &node->rd, rd_link);\n\t}\n\n\t/* Arena chunks. */\n\tfor (node = ql_last(&arena->achunks, ql_link); node != NULL; node =\n\t    ql_last(&arena->achunks, ql_link)) {\n\t\tql_remove(&arena->achunks, node, ql_link);\n\t\tarena_chunk_discard(tsd_tsdn(tsd), arena,\n\t\t    extent_node_addr_get(node));\n\t}\n\n\t/* Spare. */\n\tif (arena->spare != NULL) {\n\t\tarena_chunk_discard(tsd_tsdn(tsd), arena, arena->spare);\n\t\tarena->spare = NULL;\n\t}\n\n\tassert(!arena->purging);\n\tarena->nactive = 0;\n\n\tfor(i = 0; i < runs_avail_nclasses; i++)\n\t\tarena_run_heap_new(&arena->runs_avail[i]);\n\n\tmalloc_mutex_unlock(tsd_tsdn(tsd), &arena->lock);\n}\n\nstatic void\narena_run_coalesce(arena_t *arena, arena_chunk_t *chunk, size_t *p_size,\n    size_t *p_run_ind, size_t *p_run_pages, size_t flag_dirty,\n    size_t flag_decommitted)\n{\n\tsize_t size = *p_size;\n\tsize_t run_ind = *p_run_ind;\n\tsize_t run_pages = *p_run_pages;\n\n\t/* Try to coalesce forward. */\n\tif (run_ind + run_pages < chunk_npages &&\n\t    arena_mapbits_allocated_get(chunk, run_ind+run_pages) == 0 &&\n\t    arena_mapbits_dirty_get(chunk, run_ind+run_pages) == flag_dirty &&\n\t    arena_mapbits_decommitted_get(chunk, run_ind+run_pages) ==\n\t    flag_decommitted) {\n\t\tsize_t nrun_size = arena_mapbits_unallocated_size_get(chunk,\n\t\t    run_ind+run_pages);\n\t\tsize_t nrun_pages = nrun_size >> LG_PAGE;\n\n\t\t/*\n\t\t * Remove successor from runs_avail; the coalesced run is\n\t\t * inserted later.\n\t\t */\n\t\tassert(arena_mapbits_unallocated_size_get(chunk,\n\t\t    run_ind+run_pages+nrun_pages-1) == nrun_size);\n\t\tassert(arena_mapbits_dirty_get(chunk,\n\t\t    run_ind+run_pages+nrun_pages-1) == flag_dirty);\n\t\tassert(arena_mapbits_decommitted_get(chunk,\n\t\t    run_ind+run_pages+nrun_pages-1) == flag_decommitted);\n\t\tarena_avail_remove(arena, chunk, run_ind+run_pages, nrun_pages);\n\n\t\t/*\n\t\t * If the successor is dirty, remove it from the set of dirty\n\t\t * pages.\n\t\t */\n\t\tif (flag_dirty != 0) {\n\t\t\tarena_run_dirty_remove(arena, chunk, run_ind+run_pages,\n\t\t\t    nrun_pages);\n\t\t}\n\n\t\tsize += nrun_size;\n\t\trun_pages += nrun_pages;\n\n\t\tarena_mapbits_unallocated_size_set(chunk, run_ind, size);\n\t\tarena_mapbits_unallocated_size_set(chunk, run_ind+run_pages-1,\n\t\t    size);\n\t}\n\n\t/* Try to coalesce backward. */\n\tif (run_ind > map_bias && arena_mapbits_allocated_get(chunk,\n\t    run_ind-1) == 0 && arena_mapbits_dirty_get(chunk, run_ind-1) ==\n\t    flag_dirty && arena_mapbits_decommitted_get(chunk, run_ind-1) ==\n\t    flag_decommitted) {\n\t\tsize_t prun_size = arena_mapbits_unallocated_size_get(chunk,\n\t\t    run_ind-1);\n\t\tsize_t prun_pages = prun_size >> LG_PAGE;\n\n\t\trun_ind -= prun_pages;\n\n\t\t/*\n\t\t * Remove predecessor from runs_avail; the coalesced run is\n\t\t * inserted later.\n\t\t */\n\t\tassert(arena_mapbits_unallocated_size_get(chunk, run_ind) ==\n\t\t    prun_size);\n\t\tassert(arena_mapbits_dirty_get(chunk, run_ind) == flag_dirty);\n\t\tassert(arena_mapbits_decommitted_get(chunk, run_ind) ==\n\t\t    flag_decommitted);\n\t\tarena_avail_remove(arena, chunk, run_ind, prun_pages);\n\n\t\t/*\n\t\t * If the predecessor is dirty, remove it from the set of dirty\n\t\t * pages.\n\t\t */\n\t\tif (flag_dirty != 0) {\n\t\t\tarena_run_dirty_remove(arena, chunk, run_ind,\n\t\t\t    prun_pages);\n\t\t}\n\n\t\tsize += prun_size;\n\t\trun_pages += prun_pages;\n\n\t\tarena_mapbits_unallocated_size_set(chunk, run_ind, size);\n\t\tarena_mapbits_unallocated_size_set(chunk, run_ind+run_pages-1,\n\t\t    size);\n\t}\n\n\t*p_size = size;\n\t*p_run_ind = run_ind;\n\t*p_run_pages = run_pages;\n}\n\nstatic size_t\narena_run_size_get(arena_t *arena, arena_chunk_t *chunk, arena_run_t *run,\n    size_t run_ind)\n{\n\tsize_t size;\n\n\tassert(run_ind >= map_bias);\n\tassert(run_ind < chunk_npages);\n\n\tif (arena_mapbits_large_get(chunk, run_ind) != 0) {\n\t\tsize = arena_mapbits_large_size_get(chunk, run_ind);\n\t\tassert(size == PAGE || arena_mapbits_large_size_get(chunk,\n\t\t    run_ind+(size>>LG_PAGE)-1) == 0);\n\t} else {\n\t\tarena_bin_info_t *bin_info = &arena_bin_info[run->binind];\n\t\tsize = bin_info->run_size;\n\t}\n\n\treturn (size);\n}\n\nstatic void\narena_run_dalloc(tsdn_t *tsdn, arena_t *arena, arena_run_t *run, bool dirty,\n    bool cleaned, bool decommitted)\n{\n\tarena_chunk_t *chunk;\n\tarena_chunk_map_misc_t *miscelm;\n\tsize_t size, run_ind, run_pages, flag_dirty, flag_decommitted;\n\n\tchunk = (arena_chunk_t *)CHUNK_ADDR2BASE(run);\n\tmiscelm = arena_run_to_miscelm(run);\n\trun_ind = arena_miscelm_to_pageind(miscelm);\n\tassert(run_ind >= map_bias);\n\tassert(run_ind < chunk_npages);\n\tsize = arena_run_size_get(arena, chunk, run, run_ind);\n\trun_pages = (size >> LG_PAGE);\n\tarena_nactive_sub(arena, run_pages);\n\n\t/*\n\t * The run is dirty if the caller claims to have dirtied it, as well as\n\t * if it was already dirty before being allocated and the caller\n\t * doesn't claim to have cleaned it.\n\t */\n\tassert(arena_mapbits_dirty_get(chunk, run_ind) ==\n\t    arena_mapbits_dirty_get(chunk, run_ind+run_pages-1));\n\tif (!cleaned && !decommitted && arena_mapbits_dirty_get(chunk, run_ind)\n\t    != 0)\n\t\tdirty = true;\n\tflag_dirty = dirty ? CHUNK_MAP_DIRTY : 0;\n\tflag_decommitted = decommitted ? CHUNK_MAP_DECOMMITTED : 0;\n\n\t/* Mark pages as unallocated in the chunk map. */\n\tif (dirty || decommitted) {\n\t\tsize_t flags = flag_dirty | flag_decommitted;\n\t\tarena_mapbits_unallocated_set(chunk, run_ind, size, flags);\n\t\tarena_mapbits_unallocated_set(chunk, run_ind+run_pages-1, size,\n\t\t    flags);\n\t} else {\n\t\tarena_mapbits_unallocated_set(chunk, run_ind, size,\n\t\t    arena_mapbits_unzeroed_get(chunk, run_ind));\n\t\tarena_mapbits_unallocated_set(chunk, run_ind+run_pages-1, size,\n\t\t    arena_mapbits_unzeroed_get(chunk, run_ind+run_pages-1));\n\t}\n\n\tarena_run_coalesce(arena, chunk, &size, &run_ind, &run_pages,\n\t    flag_dirty, flag_decommitted);\n\n\t/* Insert into runs_avail, now that coalescing is complete. */\n\tassert(arena_mapbits_unallocated_size_get(chunk, run_ind) ==\n\t    arena_mapbits_unallocated_size_get(chunk, run_ind+run_pages-1));\n\tassert(arena_mapbits_dirty_get(chunk, run_ind) ==\n\t    arena_mapbits_dirty_get(chunk, run_ind+run_pages-1));\n\tassert(arena_mapbits_decommitted_get(chunk, run_ind) ==\n\t    arena_mapbits_decommitted_get(chunk, run_ind+run_pages-1));\n\tarena_avail_insert(arena, chunk, run_ind, run_pages);\n\n\tif (dirty)\n\t\tarena_run_dirty_insert(arena, chunk, run_ind, run_pages);\n\n\t/* Deallocate chunk if it is now completely unused. */\n\tif (size == arena_maxrun) {\n\t\tassert(run_ind == map_bias);\n\t\tassert(run_pages == (arena_maxrun >> LG_PAGE));\n\t\tarena_chunk_dalloc(tsdn, arena, chunk);\n\t}\n\n\t/*\n\t * It is okay to do dirty page processing here even if the chunk was\n\t * deallocated above, since in that case it is the spare.  Waiting\n\t * until after possible chunk deallocation to do dirty processing\n\t * allows for an old spare to be fully deallocated, thus decreasing the\n\t * chances of spuriously crossing the dirty page purging threshold.\n\t */\n\tif (dirty)\n\t\tarena_maybe_purge(tsdn, arena);\n}\n\nstatic void\narena_run_trim_head(tsdn_t *tsdn, arena_t *arena, arena_chunk_t *chunk,\n    arena_run_t *run, size_t oldsize, size_t newsize)\n{\n\tarena_chunk_map_misc_t *miscelm = arena_run_to_miscelm(run);\n\tsize_t pageind = arena_miscelm_to_pageind(miscelm);\n\tsize_t head_npages = (oldsize - newsize) >> LG_PAGE;\n\tsize_t flag_dirty = arena_mapbits_dirty_get(chunk, pageind);\n\tsize_t flag_decommitted = arena_mapbits_decommitted_get(chunk, pageind);\n\tsize_t flag_unzeroed_mask = (flag_dirty | flag_decommitted) == 0 ?\n\t    CHUNK_MAP_UNZEROED : 0;\n\n\tassert(oldsize > newsize);\n\n\t/*\n\t * Update the chunk map so that arena_run_dalloc() can treat the\n\t * leading run as separately allocated.  Set the last element of each\n\t * run first, in case of single-page runs.\n\t */\n\tassert(arena_mapbits_large_size_get(chunk, pageind) == oldsize);\n\tarena_mapbits_large_set(chunk, pageind+head_npages-1, 0, flag_dirty |\n\t    (flag_unzeroed_mask & arena_mapbits_unzeroed_get(chunk,\n\t    pageind+head_npages-1)));\n\tarena_mapbits_large_set(chunk, pageind, oldsize-newsize, flag_dirty |\n\t    (flag_unzeroed_mask & arena_mapbits_unzeroed_get(chunk, pageind)));\n\n\tif (config_debug) {\n\t\tUNUSED size_t tail_npages = newsize >> LG_PAGE;\n\t\tassert(arena_mapbits_large_size_get(chunk,\n\t\t    pageind+head_npages+tail_npages-1) == 0);\n\t\tassert(arena_mapbits_dirty_get(chunk,\n\t\t    pageind+head_npages+tail_npages-1) == flag_dirty);\n\t}\n\tarena_mapbits_large_set(chunk, pageind+head_npages, newsize,\n\t    flag_dirty | (flag_unzeroed_mask & arena_mapbits_unzeroed_get(chunk,\n\t    pageind+head_npages)));\n\n\tarena_run_dalloc(tsdn, arena, run, false, false, (flag_decommitted !=\n\t    0));\n}\n\nstatic void\narena_run_trim_tail(tsdn_t *tsdn, arena_t *arena, arena_chunk_t *chunk,\n    arena_run_t *run, size_t oldsize, size_t newsize, bool dirty)\n{\n\tarena_chunk_map_misc_t *miscelm = arena_run_to_miscelm(run);\n\tsize_t pageind = arena_miscelm_to_pageind(miscelm);\n\tsize_t head_npages = newsize >> LG_PAGE;\n\tsize_t flag_dirty = arena_mapbits_dirty_get(chunk, pageind);\n\tsize_t flag_decommitted = arena_mapbits_decommitted_get(chunk, pageind);\n\tsize_t flag_unzeroed_mask = (flag_dirty | flag_decommitted) == 0 ?\n\t    CHUNK_MAP_UNZEROED : 0;\n\tarena_chunk_map_misc_t *tail_miscelm;\n\tarena_run_t *tail_run;\n\n\tassert(oldsize > newsize);\n\n\t/*\n\t * Update the chunk map so that arena_run_dalloc() can treat the\n\t * trailing run as separately allocated.  Set the last element of each\n\t * run first, in case of single-page runs.\n\t */\n\tassert(arena_mapbits_large_size_get(chunk, pageind) == oldsize);\n\tarena_mapbits_large_set(chunk, pageind+head_npages-1, 0, flag_dirty |\n\t    (flag_unzeroed_mask & arena_mapbits_unzeroed_get(chunk,\n\t    pageind+head_npages-1)));\n\tarena_mapbits_large_set(chunk, pageind, newsize, flag_dirty |\n\t    (flag_unzeroed_mask & arena_mapbits_unzeroed_get(chunk, pageind)));\n\n\tif (config_debug) {\n\t\tUNUSED size_t tail_npages = (oldsize - newsize) >> LG_PAGE;\n\t\tassert(arena_mapbits_large_size_get(chunk,\n\t\t    pageind+head_npages+tail_npages-1) == 0);\n\t\tassert(arena_mapbits_dirty_get(chunk,\n\t\t    pageind+head_npages+tail_npages-1) == flag_dirty);\n\t}\n\tarena_mapbits_large_set(chunk, pageind+head_npages, oldsize-newsize,\n\t    flag_dirty | (flag_unzeroed_mask & arena_mapbits_unzeroed_get(chunk,\n\t    pageind+head_npages)));\n\n\ttail_miscelm = arena_miscelm_get_mutable(chunk, pageind + head_npages);\n\ttail_run = &tail_miscelm->run;\n\tarena_run_dalloc(tsdn, arena, tail_run, dirty, false, (flag_decommitted\n\t    != 0));\n}\n\nstatic void\narena_bin_runs_insert(arena_bin_t *bin, arena_run_t *run)\n{\n\tarena_chunk_map_misc_t *miscelm = arena_run_to_miscelm(run);\n\n\tarena_run_heap_insert(&bin->runs, miscelm);\n}\n\nstatic arena_run_t *\narena_bin_nonfull_run_tryget(arena_bin_t *bin)\n{\n\tarena_chunk_map_misc_t *miscelm;\n\n\tmiscelm = arena_run_heap_remove_first(&bin->runs);\n\tif (miscelm == NULL)\n\t\treturn (NULL);\n\tif (config_stats)\n\t\tbin->stats.reruns++;\n\n\treturn (&miscelm->run);\n}\n\nstatic arena_run_t *\narena_bin_nonfull_run_get(tsdn_t *tsdn, arena_t *arena, arena_bin_t *bin)\n{\n\tarena_run_t *run;\n\tszind_t binind;\n\tarena_bin_info_t *bin_info;\n\n\t/* Look for a usable run. */\n\trun = arena_bin_nonfull_run_tryget(bin);\n\tif (run != NULL)\n\t\treturn (run);\n\t/* No existing runs have any space available. */\n\n\tbinind = arena_bin_index(arena, bin);\n\tbin_info = &arena_bin_info[binind];\n\n\t/* Allocate a new run. */\n\tmalloc_mutex_unlock(tsdn, &bin->lock);\n\t/******************************/\n\tmalloc_mutex_lock(tsdn, &arena->lock);\n\trun = arena_run_alloc_small(tsdn, arena, bin_info->run_size, binind);\n\tif (run != NULL) {\n\t\t/* Initialize run internals. */\n\t\trun->binind = binind;\n\t\trun->nfree = bin_info->nregs;\n\t\tbitmap_init(run->bitmap, &bin_info->bitmap_info);\n\t}\n\tmalloc_mutex_unlock(tsdn, &arena->lock);\n\t/********************************/\n\tmalloc_mutex_lock(tsdn, &bin->lock);\n\tif (run != NULL) {\n\t\tif (config_stats) {\n\t\t\tbin->stats.nruns++;\n\t\t\tbin->stats.curruns++;\n\t\t}\n\t\treturn (run);\n\t}\n\n\t/*\n\t * arena_run_alloc_small() failed, but another thread may have made\n\t * sufficient memory available while this one dropped bin->lock above,\n\t * so search one more time.\n\t */\n\trun = arena_bin_nonfull_run_tryget(bin);\n\tif (run != NULL)\n\t\treturn (run);\n\n\treturn (NULL);\n}\n\n/* Re-fill bin->runcur, then call arena_run_reg_alloc(). */\nstatic void *\narena_bin_malloc_hard(tsdn_t *tsdn, arena_t *arena, arena_bin_t *bin)\n{\n\tszind_t binind;\n\tarena_bin_info_t *bin_info;\n\tarena_run_t *run;\n\n\tbinind = arena_bin_index(arena, bin);\n\tbin_info = &arena_bin_info[binind];\n\tbin->runcur = NULL;\n\trun = arena_bin_nonfull_run_get(tsdn, arena, bin);\n\tif (bin->runcur != NULL && bin->runcur->nfree > 0) {\n\t\t/*\n\t\t * Another thread updated runcur while this one ran without the\n\t\t * bin lock in arena_bin_nonfull_run_get().\n\t\t */\n\t\tvoid *ret;\n\t\tassert(bin->runcur->nfree > 0);\n\t\tret = arena_run_reg_alloc(bin->runcur, bin_info);\n\t\tif (run != NULL) {\n\t\t\tarena_chunk_t *chunk;\n\n\t\t\t/*\n\t\t\t * arena_run_alloc_small() may have allocated run, or\n\t\t\t * it may have pulled run from the bin's run tree.\n\t\t\t * Therefore it is unsafe to make any assumptions about\n\t\t\t * how run has previously been used, and\n\t\t\t * arena_bin_lower_run() must be called, as if a region\n\t\t\t * were just deallocated from the run.\n\t\t\t */\n\t\t\tchunk = (arena_chunk_t *)CHUNK_ADDR2BASE(run);\n\t\t\tif (run->nfree == bin_info->nregs) {\n\t\t\t\tarena_dalloc_bin_run(tsdn, arena, chunk, run,\n\t\t\t\t    bin);\n\t\t\t} else\n\t\t\t\tarena_bin_lower_run(arena, chunk, run, bin);\n\t\t}\n\t\treturn (ret);\n\t}\n\n\tif (run == NULL)\n\t\treturn (NULL);\n\n\tbin->runcur = run;\n\n\tassert(bin->runcur->nfree > 0);\n\n\treturn (arena_run_reg_alloc(bin->runcur, bin_info));\n}\n\nvoid\narena_tcache_fill_small(tsdn_t *tsdn, arena_t *arena, tcache_bin_t *tbin,\n    szind_t binind, uint64_t prof_accumbytes)\n{\n\tunsigned i, nfill;\n\tarena_bin_t *bin;\n\n\tassert(tbin->ncached == 0);\n\n\tif (config_prof && arena_prof_accum(tsdn, arena, prof_accumbytes))\n\t\tprof_idump(tsdn);\n\tbin = &arena->bins[binind];\n\tmalloc_mutex_lock(tsdn, &bin->lock);\n\tfor (i = 0, nfill = (tcache_bin_info[binind].ncached_max >>\n\t    tbin->lg_fill_div); i < nfill; i++) {\n\t\tarena_run_t *run;\n\t\tvoid *ptr;\n\t\tif ((run = bin->runcur) != NULL && run->nfree > 0)\n\t\t\tptr = arena_run_reg_alloc(run, &arena_bin_info[binind]);\n\t\telse\n\t\t\tptr = arena_bin_malloc_hard(tsdn, arena, bin);\n\t\tif (ptr == NULL) {\n\t\t\t/*\n\t\t\t * OOM.  tbin->avail isn't yet filled down to its first\n\t\t\t * element, so the successful allocations (if any) must\n\t\t\t * be moved just before tbin->avail before bailing out.\n\t\t\t */\n\t\t\tif (i > 0) {\n\t\t\t\tmemmove(tbin->avail - i, tbin->avail - nfill,\n\t\t\t\t    i * sizeof(void *));\n\t\t\t}\n\t\t\tbreak;\n\t\t}\n\t\tif (config_fill && unlikely(opt_junk_alloc)) {\n\t\t\tarena_alloc_junk_small(ptr, &arena_bin_info[binind],\n\t\t\t    true);\n\t\t}\n\t\t/* Insert such that low regions get used first. */\n\t\t*(tbin->avail - nfill + i) = ptr;\n\t}\n\tif (config_stats) {\n\t\tbin->stats.nmalloc += i;\n\t\tbin->stats.nrequests += tbin->tstats.nrequests;\n\t\tbin->stats.curregs += i;\n\t\tbin->stats.nfills++;\n\t\ttbin->tstats.nrequests = 0;\n\t}\n\tmalloc_mutex_unlock(tsdn, &bin->lock);\n\ttbin->ncached = i;\n\tarena_decay_tick(tsdn, arena);\n}\n\nvoid\narena_alloc_junk_small(void *ptr, arena_bin_info_t *bin_info, bool zero)\n{\n\n\tsize_t redzone_size = bin_info->redzone_size;\n\n\tif (zero) {\n\t\tmemset((void *)((uintptr_t)ptr - redzone_size),\n\t\t    JEMALLOC_ALLOC_JUNK, redzone_size);\n\t\tmemset((void *)((uintptr_t)ptr + bin_info->reg_size),\n\t\t    JEMALLOC_ALLOC_JUNK, redzone_size);\n\t} else {\n\t\tmemset((void *)((uintptr_t)ptr - redzone_size),\n\t\t    JEMALLOC_ALLOC_JUNK, bin_info->reg_interval);\n\t}\n}\n\n#ifdef JEMALLOC_JET\n#undef arena_redzone_corruption\n#define\tarena_redzone_corruption JEMALLOC_N(n_arena_redzone_corruption)\n#endif\nstatic void\narena_redzone_corruption(void *ptr, size_t usize, bool after,\n    size_t offset, uint8_t byte)\n{\n\n\tmalloc_printf(\"<jemalloc>: Corrupt redzone %zu byte%s %s %p \"\n\t    \"(size %zu), byte=%#x\\n\", offset, (offset == 1) ? \"\" : \"s\",\n\t    after ? \"after\" : \"before\", ptr, usize, byte);\n}\n#ifdef JEMALLOC_JET\n#undef arena_redzone_corruption\n#define\tarena_redzone_corruption JEMALLOC_N(arena_redzone_corruption)\narena_redzone_corruption_t *arena_redzone_corruption =\n    JEMALLOC_N(n_arena_redzone_corruption);\n#endif\n\nstatic void\narena_redzones_validate(void *ptr, arena_bin_info_t *bin_info, bool reset)\n{\n\tbool error = false;\n\n\tif (opt_junk_alloc) {\n\t\tsize_t size = bin_info->reg_size;\n\t\tsize_t redzone_size = bin_info->redzone_size;\n\t\tsize_t i;\n\n\t\tfor (i = 1; i <= redzone_size; i++) {\n\t\t\tuint8_t *byte = (uint8_t *)((uintptr_t)ptr - i);\n\t\t\tif (*byte != JEMALLOC_ALLOC_JUNK) {\n\t\t\t\terror = true;\n\t\t\t\tarena_redzone_corruption(ptr, size, false, i,\n\t\t\t\t    *byte);\n\t\t\t\tif (reset)\n\t\t\t\t\t*byte = JEMALLOC_ALLOC_JUNK;\n\t\t\t}\n\t\t}\n\t\tfor (i = 0; i < redzone_size; i++) {\n\t\t\tuint8_t *byte = (uint8_t *)((uintptr_t)ptr + size + i);\n\t\t\tif (*byte != JEMALLOC_ALLOC_JUNK) {\n\t\t\t\terror = true;\n\t\t\t\tarena_redzone_corruption(ptr, size, true, i,\n\t\t\t\t    *byte);\n\t\t\t\tif (reset)\n\t\t\t\t\t*byte = JEMALLOC_ALLOC_JUNK;\n\t\t\t}\n\t\t}\n\t}\n\n\tif (opt_abort && error)\n\t\tabort();\n}\n\n#ifdef JEMALLOC_JET\n#undef arena_dalloc_junk_small\n#define\tarena_dalloc_junk_small JEMALLOC_N(n_arena_dalloc_junk_small)\n#endif\nvoid\narena_dalloc_junk_small(void *ptr, arena_bin_info_t *bin_info)\n{\n\tsize_t redzone_size = bin_info->redzone_size;\n\n\tarena_redzones_validate(ptr, bin_info, false);\n\tmemset((void *)((uintptr_t)ptr - redzone_size), JEMALLOC_FREE_JUNK,\n\t    bin_info->reg_interval);\n}\n#ifdef JEMALLOC_JET\n#undef arena_dalloc_junk_small\n#define\tarena_dalloc_junk_small JEMALLOC_N(arena_dalloc_junk_small)\narena_dalloc_junk_small_t *arena_dalloc_junk_small =\n    JEMALLOC_N(n_arena_dalloc_junk_small);\n#endif\n\nvoid\narena_quarantine_junk_small(void *ptr, size_t usize)\n{\n\tszind_t binind;\n\tarena_bin_info_t *bin_info;\n\tcassert(config_fill);\n\tassert(opt_junk_free);\n\tassert(opt_quarantine);\n\tassert(usize <= SMALL_MAXCLASS);\n\n\tbinind = size2index(usize);\n\tbin_info = &arena_bin_info[binind];\n\tarena_redzones_validate(ptr, bin_info, true);\n}\n\nstatic void *\narena_malloc_small(tsdn_t *tsdn, arena_t *arena, szind_t binind, bool zero)\n{\n\tvoid *ret;\n\tarena_bin_t *bin;\n\tsize_t usize;\n\tarena_run_t *run;\n\n\tassert(binind < NBINS);\n\tbin = &arena->bins[binind];\n\tusize = index2size(binind);\n\n\tmalloc_mutex_lock(tsdn, &bin->lock);\n\tif ((run = bin->runcur) != NULL && run->nfree > 0)\n\t\tret = arena_run_reg_alloc(run, &arena_bin_info[binind]);\n\telse\n\t\tret = arena_bin_malloc_hard(tsdn, arena, bin);\n\n\tif (ret == NULL) {\n\t\tmalloc_mutex_unlock(tsdn, &bin->lock);\n\t\treturn (NULL);\n\t}\n\n\tif (config_stats) {\n\t\tbin->stats.nmalloc++;\n\t\tbin->stats.nrequests++;\n\t\tbin->stats.curregs++;\n\t}\n\tmalloc_mutex_unlock(tsdn, &bin->lock);\n\tif (config_prof && !isthreaded && arena_prof_accum(tsdn, arena, usize))\n\t\tprof_idump(tsdn);\n\n\tif (!zero) {\n\t\tif (config_fill) {\n\t\t\tif (unlikely(opt_junk_alloc)) {\n\t\t\t\tarena_alloc_junk_small(ret,\n\t\t\t\t    &arena_bin_info[binind], false);\n\t\t\t} else if (unlikely(opt_zero))\n\t\t\t\tmemset(ret, 0, usize);\n\t\t}\n\t\tJEMALLOC_VALGRIND_MAKE_MEM_UNDEFINED(ret, usize);\n\t} else {\n\t\tif (config_fill && unlikely(opt_junk_alloc)) {\n\t\t\tarena_alloc_junk_small(ret, &arena_bin_info[binind],\n\t\t\t    true);\n\t\t}\n\t\tJEMALLOC_VALGRIND_MAKE_MEM_UNDEFINED(ret, usize);\n\t\tmemset(ret, 0, usize);\n\t}\n\n\tarena_decay_tick(tsdn, arena);\n\treturn (ret);\n}\n\nvoid *\narena_malloc_large(tsdn_t *tsdn, arena_t *arena, szind_t binind, bool zero)\n{\n\tvoid *ret;\n\tsize_t usize;\n\tuintptr_t random_offset;\n\tarena_run_t *run;\n\tarena_chunk_map_misc_t *miscelm;\n\tUNUSED bool idump JEMALLOC_CC_SILENCE_INIT(false);\n\n\t/* Large allocation. */\n\tusize = index2size(binind);\n\tmalloc_mutex_lock(tsdn, &arena->lock);\n\tif (config_cache_oblivious) {\n\t\tuint64_t r;\n\n\t\t/*\n\t\t * Compute a uniformly distributed offset within the first page\n\t\t * that is a multiple of the cacheline size, e.g. [0 .. 63) * 64\n\t\t * for 4 KiB pages and 64-byte cachelines.\n\t\t */\n\t\tr = prng_lg_range(&arena->offset_state, LG_PAGE - LG_CACHELINE);\n\t\trandom_offset = ((uintptr_t)r) << LG_CACHELINE;\n\t} else\n\t\trandom_offset = 0;\n\trun = arena_run_alloc_large(tsdn, arena, usize + large_pad, zero);\n\tif (run == NULL) {\n\t\tmalloc_mutex_unlock(tsdn, &arena->lock);\n\t\treturn (NULL);\n\t}\n\tmiscelm = arena_run_to_miscelm(run);\n\tret = (void *)((uintptr_t)arena_miscelm_to_rpages(miscelm) +\n\t    random_offset);\n\tif (config_stats) {\n\t\tszind_t index = binind - NBINS;\n\n\t\tarena->stats.nmalloc_large++;\n\t\tarena->stats.nrequests_large++;\n\t\tarena->stats.allocated_large += usize;\n\t\tarena->stats.lstats[index].nmalloc++;\n\t\tarena->stats.lstats[index].nrequests++;\n\t\tarena->stats.lstats[index].curruns++;\n\t}\n\tif (config_prof)\n\t\tidump = arena_prof_accum_locked(arena, usize);\n\tmalloc_mutex_unlock(tsdn, &arena->lock);\n\tif (config_prof && idump)\n\t\tprof_idump(tsdn);\n\n\tif (!zero) {\n\t\tif (config_fill) {\n\t\t\tif (unlikely(opt_junk_alloc))\n\t\t\t\tmemset(ret, JEMALLOC_ALLOC_JUNK, usize);\n\t\t\telse if (unlikely(opt_zero))\n\t\t\t\tmemset(ret, 0, usize);\n\t\t}\n\t}\n\n\tarena_decay_tick(tsdn, arena);\n\treturn (ret);\n}\n\nvoid *\narena_malloc_hard(tsdn_t *tsdn, arena_t *arena, size_t size, szind_t ind,\n    bool zero)\n{\n\n\tassert(!tsdn_null(tsdn) || arena != NULL);\n\n\tif (likely(!tsdn_null(tsdn)))\n\t\tarena = arena_choose(tsdn_tsd(tsdn), arena);\n\tif (unlikely(arena == NULL))\n\t\treturn (NULL);\n\n\tif (likely(size <= SMALL_MAXCLASS))\n\t\treturn (arena_malloc_small(tsdn, arena, ind, zero));\n\tif (likely(size <= large_maxclass))\n\t\treturn (arena_malloc_large(tsdn, arena, ind, zero));\n\treturn (huge_malloc(tsdn, arena, index2size(ind), zero));\n}\n\n/* Only handles large allocations that require more than page alignment. */\nstatic void *\narena_palloc_large(tsdn_t *tsdn, arena_t *arena, size_t usize, size_t alignment,\n    bool zero)\n{\n\tvoid *ret;\n\tsize_t alloc_size, leadsize, trailsize;\n\tarena_run_t *run;\n\tarena_chunk_t *chunk;\n\tarena_chunk_map_misc_t *miscelm;\n\tvoid *rpages;\n\n\tassert(!tsdn_null(tsdn) || arena != NULL);\n\tassert(usize == PAGE_CEILING(usize));\n\n\tif (likely(!tsdn_null(tsdn)))\n\t\tarena = arena_choose(tsdn_tsd(tsdn), arena);\n\tif (unlikely(arena == NULL))\n\t\treturn (NULL);\n\n\talignment = PAGE_CEILING(alignment);\n\talloc_size = usize + large_pad + alignment - PAGE;\n\n\tmalloc_mutex_lock(tsdn, &arena->lock);\n\trun = arena_run_alloc_large(tsdn, arena, alloc_size, false);\n\tif (run == NULL) {\n\t\tmalloc_mutex_unlock(tsdn, &arena->lock);\n\t\treturn (NULL);\n\t}\n\tchunk = (arena_chunk_t *)CHUNK_ADDR2BASE(run);\n\tmiscelm = arena_run_to_miscelm(run);\n\trpages = arena_miscelm_to_rpages(miscelm);\n\n\tleadsize = ALIGNMENT_CEILING((uintptr_t)rpages, alignment) -\n\t    (uintptr_t)rpages;\n\tassert(alloc_size >= leadsize + usize);\n\ttrailsize = alloc_size - leadsize - usize - large_pad;\n\tif (leadsize != 0) {\n\t\tarena_chunk_map_misc_t *head_miscelm = miscelm;\n\t\tarena_run_t *head_run = run;\n\n\t\tmiscelm = arena_miscelm_get_mutable(chunk,\n\t\t    arena_miscelm_to_pageind(head_miscelm) + (leadsize >>\n\t\t    LG_PAGE));\n\t\trun = &miscelm->run;\n\n\t\tarena_run_trim_head(tsdn, arena, chunk, head_run, alloc_size,\n\t\t    alloc_size - leadsize);\n\t}\n\tif (trailsize != 0) {\n\t\tarena_run_trim_tail(tsdn, arena, chunk, run, usize + large_pad +\n\t\t    trailsize, usize + large_pad, false);\n\t}\n\tif (arena_run_init_large(arena, run, usize + large_pad, zero)) {\n\t\tsize_t run_ind =\n\t\t    arena_miscelm_to_pageind(arena_run_to_miscelm(run));\n\t\tbool dirty = (arena_mapbits_dirty_get(chunk, run_ind) != 0);\n\t\tbool decommitted = (arena_mapbits_decommitted_get(chunk,\n\t\t    run_ind) != 0);\n\n\t\tassert(decommitted); /* Cause of OOM. */\n\t\tarena_run_dalloc(tsdn, arena, run, dirty, false, decommitted);\n\t\tmalloc_mutex_unlock(tsdn, &arena->lock);\n\t\treturn (NULL);\n\t}\n\tret = arena_miscelm_to_rpages(miscelm);\n\n\tif (config_stats) {\n\t\tszind_t index = size2index(usize) - NBINS;\n\n\t\tarena->stats.nmalloc_large++;\n\t\tarena->stats.nrequests_large++;\n\t\tarena->stats.allocated_large += usize;\n\t\tarena->stats.lstats[index].nmalloc++;\n\t\tarena->stats.lstats[index].nrequests++;\n\t\tarena->stats.lstats[index].curruns++;\n\t}\n\tmalloc_mutex_unlock(tsdn, &arena->lock);\n\n\tif (config_fill && !zero) {\n\t\tif (unlikely(opt_junk_alloc))\n\t\t\tmemset(ret, JEMALLOC_ALLOC_JUNK, usize);\n\t\telse if (unlikely(opt_zero))\n\t\t\tmemset(ret, 0, usize);\n\t}\n\tarena_decay_tick(tsdn, arena);\n\treturn (ret);\n}\n\nvoid *\narena_palloc(tsdn_t *tsdn, arena_t *arena, size_t usize, size_t alignment,\n    bool zero, tcache_t *tcache)\n{\n\tvoid *ret;\n\n\tif (usize <= SMALL_MAXCLASS && (alignment < PAGE || (alignment == PAGE\n\t    && (usize & PAGE_MASK) == 0))) {\n\t\t/* Small; alignment doesn't require special run placement. */\n\t\tret = arena_malloc(tsdn, arena, usize, size2index(usize), zero,\n\t\t    tcache, true);\n\t} else if (usize <= large_maxclass && alignment <= PAGE) {\n\t\t/*\n\t\t * Large; alignment doesn't require special run placement.\n\t\t * However, the cached pointer may be at a random offset from\n\t\t * the base of the run, so do some bit manipulation to retrieve\n\t\t * the base.\n\t\t */\n\t\tret = arena_malloc(tsdn, arena, usize, size2index(usize), zero,\n\t\t    tcache, true);\n\t\tif (config_cache_oblivious)\n\t\t\tret = (void *)((uintptr_t)ret & ~PAGE_MASK);\n\t} else {\n\t\tif (likely(usize <= large_maxclass)) {\n\t\t\tret = arena_palloc_large(tsdn, arena, usize, alignment,\n\t\t\t    zero);\n\t\t} else if (likely(alignment <= chunksize))\n\t\t\tret = huge_malloc(tsdn, arena, usize, zero);\n\t\telse {\n\t\t\tret = huge_palloc(tsdn, arena, usize, alignment, zero);\n\t\t}\n\t}\n\treturn (ret);\n}\n\nvoid\narena_prof_promoted(tsdn_t *tsdn, const void *ptr, size_t size)\n{\n\tarena_chunk_t *chunk;\n\tsize_t pageind;\n\tszind_t binind;\n\n\tcassert(config_prof);\n\tassert(ptr != NULL);\n\tassert(CHUNK_ADDR2BASE(ptr) != ptr);\n\tassert(isalloc(tsdn, ptr, false) == LARGE_MINCLASS);\n\tassert(isalloc(tsdn, ptr, true) == LARGE_MINCLASS);\n\tassert(size <= SMALL_MAXCLASS);\n\n\tchunk = (arena_chunk_t *)CHUNK_ADDR2BASE(ptr);\n\tpageind = ((uintptr_t)ptr - (uintptr_t)chunk) >> LG_PAGE;\n\tbinind = size2index(size);\n\tassert(binind < NBINS);\n\tarena_mapbits_large_binind_set(chunk, pageind, binind);\n\n\tassert(isalloc(tsdn, ptr, false) == LARGE_MINCLASS);\n\tassert(isalloc(tsdn, ptr, true) == size);\n}\n\nstatic void\narena_dissociate_bin_run(arena_chunk_t *chunk, arena_run_t *run,\n    arena_bin_t *bin)\n{\n\n\t/* Dissociate run from bin. */\n\tif (run == bin->runcur)\n\t\tbin->runcur = NULL;\n\telse {\n\t\tszind_t binind = arena_bin_index(extent_node_arena_get(\n\t\t    &chunk->node), bin);\n\t\tarena_bin_info_t *bin_info = &arena_bin_info[binind];\n\n\t\t/*\n\t\t * The following block's conditional is necessary because if the\n\t\t * run only contains one region, then it never gets inserted\n\t\t * into the non-full runs tree.\n\t\t */\n\t\tif (bin_info->nregs != 1) {\n\t\t\tarena_chunk_map_misc_t *miscelm =\n\t\t\t    arena_run_to_miscelm(run);\n\n\t\t\tarena_run_heap_remove(&bin->runs, miscelm);\n\t\t}\n\t}\n}\n\nstatic void\narena_dalloc_bin_run(tsdn_t *tsdn, arena_t *arena, arena_chunk_t *chunk,\n    arena_run_t *run, arena_bin_t *bin)\n{\n\n\tassert(run != bin->runcur);\n\n\tmalloc_mutex_unlock(tsdn, &bin->lock);\n\t/******************************/\n\tmalloc_mutex_lock(tsdn, &arena->lock);\n\tarena_run_dalloc(tsdn, arena, run, true, false, false);\n\tmalloc_mutex_unlock(tsdn, &arena->lock);\n\t/****************************/\n\tmalloc_mutex_lock(tsdn, &bin->lock);\n\tif (config_stats)\n\t\tbin->stats.curruns--;\n}\n\nstatic void\narena_bin_lower_run(arena_t *arena, arena_chunk_t *chunk, arena_run_t *run,\n    arena_bin_t *bin)\n{\n\n\t/*\n\t * Make sure that if bin->runcur is non-NULL, it refers to the lowest\n\t * non-full run.  It is okay to NULL runcur out rather than proactively\n\t * keeping it pointing at the lowest non-full run.\n\t */\n\tif ((uintptr_t)run < (uintptr_t)bin->runcur) {\n\t\t/* Switch runcur. */\n\t\tif (bin->runcur->nfree > 0)\n\t\t\tarena_bin_runs_insert(bin, bin->runcur);\n\t\tbin->runcur = run;\n\t\tif (config_stats)\n\t\t\tbin->stats.reruns++;\n\t} else\n\t\tarena_bin_runs_insert(bin, run);\n}\n\nstatic void\narena_dalloc_bin_locked_impl(tsdn_t *tsdn, arena_t *arena, arena_chunk_t *chunk,\n    void *ptr, arena_chunk_map_bits_t *bitselm, bool junked)\n{\n\tsize_t pageind, rpages_ind;\n\tarena_run_t *run;\n\tarena_bin_t *bin;\n\tarena_bin_info_t *bin_info;\n\tszind_t binind;\n\n\tpageind = ((uintptr_t)ptr - (uintptr_t)chunk) >> LG_PAGE;\n\trpages_ind = pageind - arena_mapbits_small_runind_get(chunk, pageind);\n\trun = &arena_miscelm_get_mutable(chunk, rpages_ind)->run;\n\tbinind = run->binind;\n\tbin = &arena->bins[binind];\n\tbin_info = &arena_bin_info[binind];\n\n\tif (!junked && config_fill && unlikely(opt_junk_free))\n\t\tarena_dalloc_junk_small(ptr, bin_info);\n\n\tarena_run_reg_dalloc(run, ptr);\n\tif (run->nfree == bin_info->nregs) {\n\t\tarena_dissociate_bin_run(chunk, run, bin);\n\t\tarena_dalloc_bin_run(tsdn, arena, chunk, run, bin);\n\t} else if (run->nfree == 1 && run != bin->runcur)\n\t\tarena_bin_lower_run(arena, chunk, run, bin);\n\n\tif (config_stats) {\n\t\tbin->stats.ndalloc++;\n\t\tbin->stats.curregs--;\n\t}\n}\n\nvoid\narena_dalloc_bin_junked_locked(tsdn_t *tsdn, arena_t *arena,\n    arena_chunk_t *chunk, void *ptr, arena_chunk_map_bits_t *bitselm)\n{\n\n\tarena_dalloc_bin_locked_impl(tsdn, arena, chunk, ptr, bitselm, true);\n}\n\nvoid\narena_dalloc_bin(tsdn_t *tsdn, arena_t *arena, arena_chunk_t *chunk, void *ptr,\n    size_t pageind, arena_chunk_map_bits_t *bitselm)\n{\n\tarena_run_t *run;\n\tarena_bin_t *bin;\n\tsize_t rpages_ind;\n\n\trpages_ind = pageind - arena_mapbits_small_runind_get(chunk, pageind);\n\trun = &arena_miscelm_get_mutable(chunk, rpages_ind)->run;\n\tbin = &arena->bins[run->binind];\n\tmalloc_mutex_lock(tsdn, &bin->lock);\n\tarena_dalloc_bin_locked_impl(tsdn, arena, chunk, ptr, bitselm, false);\n\tmalloc_mutex_unlock(tsdn, &bin->lock);\n}\n\nvoid\narena_dalloc_small(tsdn_t *tsdn, arena_t *arena, arena_chunk_t *chunk,\n    void *ptr, size_t pageind)\n{\n\tarena_chunk_map_bits_t *bitselm;\n\n\tif (config_debug) {\n\t\t/* arena_ptr_small_binind_get() does extra sanity checking. */\n\t\tassert(arena_ptr_small_binind_get(ptr, arena_mapbits_get(chunk,\n\t\t    pageind)) != BININD_INVALID);\n\t}\n\tbitselm = arena_bitselm_get_mutable(chunk, pageind);\n\tarena_dalloc_bin(tsdn, arena, chunk, ptr, pageind, bitselm);\n\tarena_decay_tick(tsdn, arena);\n}\n\n#ifdef JEMALLOC_JET\n#undef arena_dalloc_junk_large\n#define\tarena_dalloc_junk_large JEMALLOC_N(n_arena_dalloc_junk_large)\n#endif\nvoid\narena_dalloc_junk_large(void *ptr, size_t usize)\n{\n\n\tif (config_fill && unlikely(opt_junk_free))\n\t\tmemset(ptr, JEMALLOC_FREE_JUNK, usize);\n}\n#ifdef JEMALLOC_JET\n#undef arena_dalloc_junk_large\n#define\tarena_dalloc_junk_large JEMALLOC_N(arena_dalloc_junk_large)\narena_dalloc_junk_large_t *arena_dalloc_junk_large =\n    JEMALLOC_N(n_arena_dalloc_junk_large);\n#endif\n\nstatic void\narena_dalloc_large_locked_impl(tsdn_t *tsdn, arena_t *arena,\n    arena_chunk_t *chunk, void *ptr, bool junked)\n{\n\tsize_t pageind = ((uintptr_t)ptr - (uintptr_t)chunk) >> LG_PAGE;\n\tarena_chunk_map_misc_t *miscelm = arena_miscelm_get_mutable(chunk,\n\t    pageind);\n\tarena_run_t *run = &miscelm->run;\n\n\tif (config_fill || config_stats) {\n\t\tsize_t usize = arena_mapbits_large_size_get(chunk, pageind) -\n\t\t    large_pad;\n\n\t\tif (!junked)\n\t\t\tarena_dalloc_junk_large(ptr, usize);\n\t\tif (config_stats) {\n\t\t\tszind_t index = size2index(usize) - NBINS;\n\n\t\t\tarena->stats.ndalloc_large++;\n\t\t\tarena->stats.allocated_large -= usize;\n\t\t\tarena->stats.lstats[index].ndalloc++;\n\t\t\tarena->stats.lstats[index].curruns--;\n\t\t}\n\t}\n\n\tarena_run_dalloc(tsdn, arena, run, true, false, false);\n}\n\nvoid\narena_dalloc_large_junked_locked(tsdn_t *tsdn, arena_t *arena,\n    arena_chunk_t *chunk, void *ptr)\n{\n\n\tarena_dalloc_large_locked_impl(tsdn, arena, chunk, ptr, true);\n}\n\nvoid\narena_dalloc_large(tsdn_t *tsdn, arena_t *arena, arena_chunk_t *chunk,\n    void *ptr)\n{\n\n\tmalloc_mutex_lock(tsdn, &arena->lock);\n\tarena_dalloc_large_locked_impl(tsdn, arena, chunk, ptr, false);\n\tmalloc_mutex_unlock(tsdn, &arena->lock);\n\tarena_decay_tick(tsdn, arena);\n}\n\nstatic void\narena_ralloc_large_shrink(tsdn_t *tsdn, arena_t *arena, arena_chunk_t *chunk,\n    void *ptr, size_t oldsize, size_t size)\n{\n\tsize_t pageind = ((uintptr_t)ptr - (uintptr_t)chunk) >> LG_PAGE;\n\tarena_chunk_map_misc_t *miscelm = arena_miscelm_get_mutable(chunk,\n\t    pageind);\n\tarena_run_t *run = &miscelm->run;\n\n\tassert(size < oldsize);\n\n\t/*\n\t * Shrink the run, and make trailing pages available for other\n\t * allocations.\n\t */\n\tmalloc_mutex_lock(tsdn, &arena->lock);\n\tarena_run_trim_tail(tsdn, arena, chunk, run, oldsize + large_pad, size +\n\t    large_pad, true);\n\tif (config_stats) {\n\t\tszind_t oldindex = size2index(oldsize) - NBINS;\n\t\tszind_t index = size2index(size) - NBINS;\n\n\t\tarena->stats.ndalloc_large++;\n\t\tarena->stats.allocated_large -= oldsize;\n\t\tarena->stats.lstats[oldindex].ndalloc++;\n\t\tarena->stats.lstats[oldindex].curruns--;\n\n\t\tarena->stats.nmalloc_large++;\n\t\tarena->stats.nrequests_large++;\n\t\tarena->stats.allocated_large += size;\n\t\tarena->stats.lstats[index].nmalloc++;\n\t\tarena->stats.lstats[index].nrequests++;\n\t\tarena->stats.lstats[index].curruns++;\n\t}\n\tmalloc_mutex_unlock(tsdn, &arena->lock);\n}\n\nstatic bool\narena_ralloc_large_grow(tsdn_t *tsdn, arena_t *arena, arena_chunk_t *chunk,\n    void *ptr, size_t oldsize, size_t usize_min, size_t usize_max, bool zero)\n{\n\tsize_t pageind = ((uintptr_t)ptr - (uintptr_t)chunk) >> LG_PAGE;\n\tsize_t npages = (oldsize + large_pad) >> LG_PAGE;\n\tsize_t followsize;\n\n\tassert(oldsize == arena_mapbits_large_size_get(chunk, pageind) -\n\t    large_pad);\n\n\t/* Try to extend the run. */\n\tmalloc_mutex_lock(tsdn, &arena->lock);\n\tif (pageind+npages >= chunk_npages || arena_mapbits_allocated_get(chunk,\n\t    pageind+npages) != 0)\n\t\tgoto label_fail;\n\tfollowsize = arena_mapbits_unallocated_size_get(chunk, pageind+npages);\n\tif (oldsize + followsize >= usize_min) {\n\t\t/*\n\t\t * The next run is available and sufficiently large.  Split the\n\t\t * following run, then merge the first part with the existing\n\t\t * allocation.\n\t\t */\n\t\tarena_run_t *run;\n\t\tsize_t usize, splitsize, size, flag_dirty, flag_unzeroed_mask;\n\n\t\tusize = usize_max;\n\t\twhile (oldsize + followsize < usize)\n\t\t\tusize = index2size(size2index(usize)-1);\n\t\tassert(usize >= usize_min);\n\t\tassert(usize >= oldsize);\n\t\tsplitsize = usize - oldsize;\n\t\tif (splitsize == 0)\n\t\t\tgoto label_fail;\n\n\t\trun = &arena_miscelm_get_mutable(chunk, pageind+npages)->run;\n\t\tif (arena_run_split_large(arena, run, splitsize, zero))\n\t\t\tgoto label_fail;\n\n\t\tif (config_cache_oblivious && zero) {\n\t\t\t/*\n\t\t\t * Zero the trailing bytes of the original allocation's\n\t\t\t * last page, since they are in an indeterminate state.\n\t\t\t * There will always be trailing bytes, because ptr's\n\t\t\t * offset from the beginning of the run is a multiple of\n\t\t\t * CACHELINE in [0 .. PAGE).\n\t\t\t */\n\t\t\tvoid *zbase = (void *)((uintptr_t)ptr + oldsize);\n\t\t\tvoid *zpast = PAGE_ADDR2BASE((void *)((uintptr_t)zbase +\n\t\t\t    PAGE));\n\t\t\tsize_t nzero = (uintptr_t)zpast - (uintptr_t)zbase;\n\t\t\tassert(nzero > 0);\n\t\t\tmemset(zbase, 0, nzero);\n\t\t}\n\n\t\tsize = oldsize + splitsize;\n\t\tnpages = (size + large_pad) >> LG_PAGE;\n\n\t\t/*\n\t\t * Mark the extended run as dirty if either portion of the run\n\t\t * was dirty before allocation.  This is rather pedantic,\n\t\t * because there's not actually any sequence of events that\n\t\t * could cause the resulting run to be passed to\n\t\t * arena_run_dalloc() with the dirty argument set to false\n\t\t * (which is when dirty flag consistency would really matter).\n\t\t */\n\t\tflag_dirty = arena_mapbits_dirty_get(chunk, pageind) |\n\t\t    arena_mapbits_dirty_get(chunk, pageind+npages-1);\n\t\tflag_unzeroed_mask = flag_dirty == 0 ? CHUNK_MAP_UNZEROED : 0;\n\t\tarena_mapbits_large_set(chunk, pageind, size + large_pad,\n\t\t    flag_dirty | (flag_unzeroed_mask &\n\t\t    arena_mapbits_unzeroed_get(chunk, pageind)));\n\t\tarena_mapbits_large_set(chunk, pageind+npages-1, 0, flag_dirty |\n\t\t    (flag_unzeroed_mask & arena_mapbits_unzeroed_get(chunk,\n\t\t    pageind+npages-1)));\n\n\t\tif (config_stats) {\n\t\t\tszind_t oldindex = size2index(oldsize) - NBINS;\n\t\t\tszind_t index = size2index(size) - NBINS;\n\n\t\t\tarena->stats.ndalloc_large++;\n\t\t\tarena->stats.allocated_large -= oldsize;\n\t\t\tarena->stats.lstats[oldindex].ndalloc++;\n\t\t\tarena->stats.lstats[oldindex].curruns--;\n\n\t\t\tarena->stats.nmalloc_large++;\n\t\t\tarena->stats.nrequests_large++;\n\t\t\tarena->stats.allocated_large += size;\n\t\t\tarena->stats.lstats[index].nmalloc++;\n\t\t\tarena->stats.lstats[index].nrequests++;\n\t\t\tarena->stats.lstats[index].curruns++;\n\t\t}\n\t\tmalloc_mutex_unlock(tsdn, &arena->lock);\n\t\treturn (false);\n\t}\nlabel_fail:\n\tmalloc_mutex_unlock(tsdn, &arena->lock);\n\treturn (true);\n}\n\n#ifdef JEMALLOC_JET\n#undef arena_ralloc_junk_large\n#define\tarena_ralloc_junk_large JEMALLOC_N(n_arena_ralloc_junk_large)\n#endif\nstatic void\narena_ralloc_junk_large(void *ptr, size_t old_usize, size_t usize)\n{\n\n\tif (config_fill && unlikely(opt_junk_free)) {\n\t\tmemset((void *)((uintptr_t)ptr + usize), JEMALLOC_FREE_JUNK,\n\t\t    old_usize - usize);\n\t}\n}\n#ifdef JEMALLOC_JET\n#undef arena_ralloc_junk_large\n#define\tarena_ralloc_junk_large JEMALLOC_N(arena_ralloc_junk_large)\narena_ralloc_junk_large_t *arena_ralloc_junk_large =\n    JEMALLOC_N(n_arena_ralloc_junk_large);\n#endif\n\n/*\n * Try to resize a large allocation, in order to avoid copying.  This will\n * always fail if growing an object, and the following run is already in use.\n */\nstatic bool\narena_ralloc_large(tsdn_t *tsdn, void *ptr, size_t oldsize, size_t usize_min,\n    size_t usize_max, bool zero)\n{\n\tarena_chunk_t *chunk;\n\tarena_t *arena;\n\n\tif (oldsize == usize_max) {\n\t\t/* Current size class is compatible and maximal. */\n\t\treturn (false);\n\t}\n\n\tchunk = (arena_chunk_t *)CHUNK_ADDR2BASE(ptr);\n\tarena = extent_node_arena_get(&chunk->node);\n\n\tif (oldsize < usize_max) {\n\t\tbool ret = arena_ralloc_large_grow(tsdn, arena, chunk, ptr,\n\t\t    oldsize, usize_min, usize_max, zero);\n\t\tif (config_fill && !ret && !zero) {\n\t\t\tif (unlikely(opt_junk_alloc)) {\n\t\t\t\tmemset((void *)((uintptr_t)ptr + oldsize),\n\t\t\t\t    JEMALLOC_ALLOC_JUNK,\n\t\t\t\t    isalloc(tsdn, ptr, config_prof) - oldsize);\n\t\t\t} else if (unlikely(opt_zero)) {\n\t\t\t\tmemset((void *)((uintptr_t)ptr + oldsize), 0,\n\t\t\t\t    isalloc(tsdn, ptr, config_prof) - oldsize);\n\t\t\t}\n\t\t}\n\t\treturn (ret);\n\t}\n\n\tassert(oldsize > usize_max);\n\t/* Fill before shrinking in order avoid a race. */\n\tarena_ralloc_junk_large(ptr, oldsize, usize_max);\n\tarena_ralloc_large_shrink(tsdn, arena, chunk, ptr, oldsize, usize_max);\n\treturn (false);\n}\n\nbool\narena_ralloc_no_move(tsdn_t *tsdn, void *ptr, size_t oldsize, size_t size,\n    size_t extra, bool zero)\n{\n\tsize_t usize_min, usize_max;\n\n\t/* Calls with non-zero extra had to clamp extra. */\n\tassert(extra == 0 || size + extra <= HUGE_MAXCLASS);\n\n\tif (unlikely(size > HUGE_MAXCLASS))\n\t\treturn (true);\n\n\tusize_min = s2u(size);\n\tusize_max = s2u(size + extra);\n\tif (likely(oldsize <= large_maxclass && usize_min <= large_maxclass)) {\n\t\tarena_chunk_t *chunk;\n\n\t\t/*\n\t\t * Avoid moving the allocation if the size class can be left the\n\t\t * same.\n\t\t */\n\t\tif (oldsize <= SMALL_MAXCLASS) {\n\t\t\tassert(arena_bin_info[size2index(oldsize)].reg_size ==\n\t\t\t    oldsize);\n\t\t\tif ((usize_max > SMALL_MAXCLASS ||\n\t\t\t    size2index(usize_max) != size2index(oldsize)) &&\n\t\t\t    (size > oldsize || usize_max < oldsize))\n\t\t\t\treturn (true);\n\t\t} else {\n\t\t\tif (usize_max <= SMALL_MAXCLASS)\n\t\t\t\treturn (true);\n\t\t\tif (arena_ralloc_large(tsdn, ptr, oldsize, usize_min,\n\t\t\t    usize_max, zero))\n\t\t\t\treturn (true);\n\t\t}\n\n\t\tchunk = (arena_chunk_t *)CHUNK_ADDR2BASE(ptr);\n\t\tarena_decay_tick(tsdn, extent_node_arena_get(&chunk->node));\n\t\treturn (false);\n\t} else {\n\t\treturn (huge_ralloc_no_move(tsdn, ptr, oldsize, usize_min,\n\t\t    usize_max, zero));\n\t}\n}\n\nstatic void *\narena_ralloc_move_helper(tsdn_t *tsdn, arena_t *arena, size_t usize,\n    size_t alignment, bool zero, tcache_t *tcache)\n{\n\n\tif (alignment == 0)\n\t\treturn (arena_malloc(tsdn, arena, usize, size2index(usize),\n\t\t    zero, tcache, true));\n\tusize = sa2u(usize, alignment);\n\tif (unlikely(usize == 0 || usize > HUGE_MAXCLASS))\n\t\treturn (NULL);\n\treturn (ipalloct(tsdn, usize, alignment, zero, tcache, arena));\n}\n\nvoid *\narena_ralloc(tsd_t *tsd, arena_t *arena, void *ptr, size_t oldsize, size_t size,\n    size_t alignment, bool zero, tcache_t *tcache)\n{\n\tvoid *ret;\n\tsize_t usize;\n\n\tusize = s2u(size);\n\tif (unlikely(usize == 0 || size > HUGE_MAXCLASS))\n\t\treturn (NULL);\n\n\tif (likely(usize <= large_maxclass)) {\n\t\tsize_t copysize;\n\n\t\t/* Try to avoid moving the allocation. */\n\t\tif (!arena_ralloc_no_move(tsd_tsdn(tsd), ptr, oldsize, usize, 0,\n\t\t    zero))\n\t\t\treturn (ptr);\n\n\t\t/*\n\t\t * size and oldsize are different enough that we need to move\n\t\t * the object.  In that case, fall back to allocating new space\n\t\t * and copying.\n\t\t */\n\t\tret = arena_ralloc_move_helper(tsd_tsdn(tsd), arena, usize,\n\t\t    alignment, zero, tcache);\n\t\tif (ret == NULL)\n\t\t\treturn (NULL);\n\n\t\t/*\n\t\t * Junk/zero-filling were already done by\n\t\t * ipalloc()/arena_malloc().\n\t\t */\n\n\t\tcopysize = (usize < oldsize) ? usize : oldsize;\n\t\tJEMALLOC_VALGRIND_MAKE_MEM_UNDEFINED(ret, copysize);\n\t\tmemcpy(ret, ptr, copysize);\n\t\tisqalloc(tsd, ptr, oldsize, tcache, true);\n\t} else {\n\t\tret = huge_ralloc(tsd, arena, ptr, oldsize, usize, alignment,\n\t\t    zero, tcache);\n\t}\n\treturn (ret);\n}\n\ndss_prec_t\narena_dss_prec_get(tsdn_t *tsdn, arena_t *arena)\n{\n\tdss_prec_t ret;\n\n\tmalloc_mutex_lock(tsdn, &arena->lock);\n\tret = arena->dss_prec;\n\tmalloc_mutex_unlock(tsdn, &arena->lock);\n\treturn (ret);\n}\n\nbool\narena_dss_prec_set(tsdn_t *tsdn, arena_t *arena, dss_prec_t dss_prec)\n{\n\n\tif (!have_dss)\n\t\treturn (dss_prec != dss_prec_disabled);\n\tmalloc_mutex_lock(tsdn, &arena->lock);\n\tarena->dss_prec = dss_prec;\n\tmalloc_mutex_unlock(tsdn, &arena->lock);\n\treturn (false);\n}\n\nssize_t\narena_lg_dirty_mult_default_get(void)\n{\n\n\treturn ((ssize_t)atomic_read_z((size_t *)&lg_dirty_mult_default));\n}\n\nbool\narena_lg_dirty_mult_default_set(ssize_t lg_dirty_mult)\n{\n\n\tif (opt_purge != purge_mode_ratio)\n\t\treturn (true);\n\tif (!arena_lg_dirty_mult_valid(lg_dirty_mult))\n\t\treturn (true);\n\tatomic_write_z((size_t *)&lg_dirty_mult_default, (size_t)lg_dirty_mult);\n\treturn (false);\n}\n\nssize_t\narena_decay_time_default_get(void)\n{\n\n\treturn ((ssize_t)atomic_read_z((size_t *)&decay_time_default));\n}\n\nbool\narena_decay_time_default_set(ssize_t decay_time)\n{\n\n\tif (opt_purge != purge_mode_decay)\n\t\treturn (true);\n\tif (!arena_decay_time_valid(decay_time))\n\t\treturn (true);\n\tatomic_write_z((size_t *)&decay_time_default, (size_t)decay_time);\n\treturn (false);\n}\n\nstatic void\narena_basic_stats_merge_locked(arena_t *arena, unsigned *nthreads,\n    const char **dss, ssize_t *lg_dirty_mult, ssize_t *decay_time,\n    size_t *nactive, size_t *ndirty)\n{\n\n\t*nthreads += arena_nthreads_get(arena, false);\n\t*dss = dss_prec_names[arena->dss_prec];\n\t*lg_dirty_mult = arena->lg_dirty_mult;\n\t*decay_time = arena->decay_time;\n\t*nactive += arena->nactive;\n\t*ndirty += arena->ndirty;\n}\n\nvoid\narena_basic_stats_merge(tsdn_t *tsdn, arena_t *arena, unsigned *nthreads,\n    const char **dss, ssize_t *lg_dirty_mult, ssize_t *decay_time,\n    size_t *nactive, size_t *ndirty)\n{\n\n\tmalloc_mutex_lock(tsdn, &arena->lock);\n\tarena_basic_stats_merge_locked(arena, nthreads, dss, lg_dirty_mult,\n\t    decay_time, nactive, ndirty);\n\tmalloc_mutex_unlock(tsdn, &arena->lock);\n}\n\nvoid\narena_stats_merge(tsdn_t *tsdn, arena_t *arena, unsigned *nthreads,\n    const char **dss, ssize_t *lg_dirty_mult, ssize_t *decay_time,\n    size_t *nactive, size_t *ndirty, arena_stats_t *astats,\n    malloc_bin_stats_t *bstats, malloc_large_stats_t *lstats,\n    malloc_huge_stats_t *hstats)\n{\n\tunsigned i;\n\n\tcassert(config_stats);\n\n\tmalloc_mutex_lock(tsdn, &arena->lock);\n\tarena_basic_stats_merge_locked(arena, nthreads, dss, lg_dirty_mult,\n\t    decay_time, nactive, ndirty);\n\n\tastats->mapped += arena->stats.mapped;\n\tastats->retained += arena->stats.retained;\n\tastats->npurge += arena->stats.npurge;\n\tastats->nmadvise += arena->stats.nmadvise;\n\tastats->purged += arena->stats.purged;\n\tastats->metadata_mapped += arena->stats.metadata_mapped;\n\tastats->metadata_allocated += arena_metadata_allocated_get(arena);\n\tastats->allocated_large += arena->stats.allocated_large;\n\tastats->nmalloc_large += arena->stats.nmalloc_large;\n\tastats->ndalloc_large += arena->stats.ndalloc_large;\n\tastats->nrequests_large += arena->stats.nrequests_large;\n\tastats->allocated_huge += arena->stats.allocated_huge;\n\tastats->nmalloc_huge += arena->stats.nmalloc_huge;\n\tastats->ndalloc_huge += arena->stats.ndalloc_huge;\n\n\tfor (i = 0; i < nlclasses; i++) {\n\t\tlstats[i].nmalloc += arena->stats.lstats[i].nmalloc;\n\t\tlstats[i].ndalloc += arena->stats.lstats[i].ndalloc;\n\t\tlstats[i].nrequests += arena->stats.lstats[i].nrequests;\n\t\tlstats[i].curruns += arena->stats.lstats[i].curruns;\n\t}\n\n\tfor (i = 0; i < nhclasses; i++) {\n\t\thstats[i].nmalloc += arena->stats.hstats[i].nmalloc;\n\t\thstats[i].ndalloc += arena->stats.hstats[i].ndalloc;\n\t\thstats[i].curhchunks += arena->stats.hstats[i].curhchunks;\n\t}\n\tmalloc_mutex_unlock(tsdn, &arena->lock);\n\n\tfor (i = 0; i < NBINS; i++) {\n\t\tarena_bin_t *bin = &arena->bins[i];\n\n\t\tmalloc_mutex_lock(tsdn, &bin->lock);\n\t\tbstats[i].nmalloc += bin->stats.nmalloc;\n\t\tbstats[i].ndalloc += bin->stats.ndalloc;\n\t\tbstats[i].nrequests += bin->stats.nrequests;\n\t\tbstats[i].curregs += bin->stats.curregs;\n\t\tif (config_tcache) {\n\t\t\tbstats[i].nfills += bin->stats.nfills;\n\t\t\tbstats[i].nflushes += bin->stats.nflushes;\n\t\t}\n\t\tbstats[i].nruns += bin->stats.nruns;\n\t\tbstats[i].reruns += bin->stats.reruns;\n\t\tbstats[i].curruns += bin->stats.curruns;\n\t\tmalloc_mutex_unlock(tsdn, &bin->lock);\n\t}\n}\n\nunsigned\narena_nthreads_get(arena_t *arena, bool internal)\n{\n\n\treturn (atomic_read_u(&arena->nthreads[internal]));\n}\n\nvoid\narena_nthreads_inc(arena_t *arena, bool internal)\n{\n\n\tatomic_add_u(&arena->nthreads[internal], 1);\n}\n\nvoid\narena_nthreads_dec(arena_t *arena, bool internal)\n{\n\n\tatomic_sub_u(&arena->nthreads[internal], 1);\n}\n\narena_t *\narena_new(tsdn_t *tsdn, unsigned ind)\n{\n\tarena_t *arena;\n\tsize_t arena_size;\n\tunsigned i;\n\n\t/* Compute arena size to incorporate sufficient runs_avail elements. */\n\tarena_size = offsetof(arena_t, runs_avail) + (sizeof(arena_run_heap_t) *\n\t    runs_avail_nclasses);\n\t/*\n\t * Allocate arena, arena->lstats, and arena->hstats contiguously, mainly\n\t * because there is no way to clean up if base_alloc() OOMs.\n\t */\n\tif (config_stats) {\n\t\tarena = (arena_t *)base_alloc(tsdn,\n\t\t    CACHELINE_CEILING(arena_size) + QUANTUM_CEILING(nlclasses *\n\t\t    sizeof(malloc_large_stats_t) + nhclasses) *\n\t\t    sizeof(malloc_huge_stats_t));\n\t} else\n\t\tarena = (arena_t *)base_alloc(tsdn, arena_size);\n\tif (arena == NULL)\n\t\treturn (NULL);\n\n\tarena->ind = ind;\n\tarena->nthreads[0] = arena->nthreads[1] = 0;\n\tif (malloc_mutex_init(&arena->lock, \"arena\", WITNESS_RANK_ARENA))\n\t\treturn (NULL);\n\n\tif (config_stats) {\n\t\tmemset(&arena->stats, 0, sizeof(arena_stats_t));\n\t\tarena->stats.lstats = (malloc_large_stats_t *)((uintptr_t)arena\n\t\t    + CACHELINE_CEILING(arena_size));\n\t\tmemset(arena->stats.lstats, 0, nlclasses *\n\t\t    sizeof(malloc_large_stats_t));\n\t\tarena->stats.hstats = (malloc_huge_stats_t *)((uintptr_t)arena\n\t\t    + CACHELINE_CEILING(arena_size) +\n\t\t    QUANTUM_CEILING(nlclasses * sizeof(malloc_large_stats_t)));\n\t\tmemset(arena->stats.hstats, 0, nhclasses *\n\t\t    sizeof(malloc_huge_stats_t));\n\t\tif (config_tcache)\n\t\t\tql_new(&arena->tcache_ql);\n\t}\n\n\tif (config_prof)\n\t\tarena->prof_accumbytes = 0;\n\n\tif (config_cache_oblivious) {\n\t\t/*\n\t\t * A nondeterministic seed based on the address of arena reduces\n\t\t * the likelihood of lockstep non-uniform cache index\n\t\t * utilization among identical concurrent processes, but at the\n\t\t * cost of test repeatability.  For debug builds, instead use a\n\t\t * deterministic seed.\n\t\t */\n\t\tarena->offset_state = config_debug ? ind :\n\t\t    (uint64_t)(uintptr_t)arena;\n\t}\n\n\tarena->dss_prec = chunk_dss_prec_get(tsdn);\n\n\tql_new(&arena->achunks);\n\n\tarena->spare = NULL;\n\n\tarena->lg_dirty_mult = arena_lg_dirty_mult_default_get();\n\tarena->purging = false;\n\tarena->nactive = 0;\n\tarena->ndirty = 0;\n\n\tfor(i = 0; i < runs_avail_nclasses; i++)\n\t\tarena_run_heap_new(&arena->runs_avail[i]);\n\tqr_new(&arena->runs_dirty, rd_link);\n\tqr_new(&arena->chunks_cache, cc_link);\n\n\tif (opt_purge == purge_mode_decay)\n\t\tarena_decay_init(arena, arena_decay_time_default_get());\n\n\tql_new(&arena->huge);\n\tif (malloc_mutex_init(&arena->huge_mtx, \"arena_huge\",\n\t    WITNESS_RANK_ARENA_HUGE))\n\t\treturn (NULL);\n\n\textent_tree_szad_new(&arena->chunks_szad_cached);\n\textent_tree_ad_new(&arena->chunks_ad_cached);\n\textent_tree_szad_new(&arena->chunks_szad_retained);\n\textent_tree_ad_new(&arena->chunks_ad_retained);\n\tif (malloc_mutex_init(&arena->chunks_mtx, \"arena_chunks\",\n\t    WITNESS_RANK_ARENA_CHUNKS))\n\t\treturn (NULL);\n\tql_new(&arena->node_cache);\n\tif (malloc_mutex_init(&arena->node_cache_mtx, \"arena_node_cache\",\n\t    WITNESS_RANK_ARENA_NODE_CACHE))\n\t\treturn (NULL);\n\n\tarena->chunk_hooks = chunk_hooks_default;\n\n\t/* Initialize bins. */\n\tfor (i = 0; i < NBINS; i++) {\n\t\tarena_bin_t *bin = &arena->bins[i];\n\t\tif (malloc_mutex_init(&bin->lock, \"arena_bin\",\n\t\t    WITNESS_RANK_ARENA_BIN))\n\t\t\treturn (NULL);\n\t\tbin->runcur = NULL;\n\t\tarena_run_heap_new(&bin->runs);\n\t\tif (config_stats)\n\t\t\tmemset(&bin->stats, 0, sizeof(malloc_bin_stats_t));\n\t}\n\n\treturn (arena);\n}\n\n/*\n * Calculate bin_info->run_size such that it meets the following constraints:\n *\n *   *) bin_info->run_size <= arena_maxrun\n *   *) bin_info->nregs <= RUN_MAXREGS\n *\n * bin_info->nregs and bin_info->reg0_offset are also calculated here, since\n * these settings are all interdependent.\n */\nstatic void\nbin_info_run_size_calc(arena_bin_info_t *bin_info)\n{\n\tsize_t pad_size;\n\tsize_t try_run_size, perfect_run_size, actual_run_size;\n\tuint32_t try_nregs, perfect_nregs, actual_nregs;\n\n\t/*\n\t * Determine redzone size based on minimum alignment and minimum\n\t * redzone size.  Add padding to the end of the run if it is needed to\n\t * align the regions.  The padding allows each redzone to be half the\n\t * minimum alignment; without the padding, each redzone would have to\n\t * be twice as large in order to maintain alignment.\n\t */\n\tif (config_fill && unlikely(opt_redzone)) {\n\t\tsize_t align_min = ZU(1) << (ffs_zu(bin_info->reg_size) - 1);\n\t\tif (align_min <= REDZONE_MINSIZE) {\n\t\t\tbin_info->redzone_size = REDZONE_MINSIZE;\n\t\t\tpad_size = 0;\n\t\t} else {\n\t\t\tbin_info->redzone_size = align_min >> 1;\n\t\t\tpad_size = bin_info->redzone_size;\n\t\t}\n\t} else {\n\t\tbin_info->redzone_size = 0;\n\t\tpad_size = 0;\n\t}\n\tbin_info->reg_interval = bin_info->reg_size +\n\t    (bin_info->redzone_size << 1);\n\n\t/*\n\t * Compute run size under ideal conditions (no redzones, no limit on run\n\t * size).\n\t */\n\ttry_run_size = PAGE;\n\ttry_nregs = (uint32_t)(try_run_size / bin_info->reg_size);\n\tdo {\n\t\tperfect_run_size = try_run_size;\n\t\tperfect_nregs = try_nregs;\n\n\t\ttry_run_size += PAGE;\n\t\ttry_nregs = (uint32_t)(try_run_size / bin_info->reg_size);\n\t} while (perfect_run_size != perfect_nregs * bin_info->reg_size);\n\tassert(perfect_nregs <= RUN_MAXREGS);\n\n\tactual_run_size = perfect_run_size;\n\tactual_nregs = (uint32_t)((actual_run_size - pad_size) /\n\t    bin_info->reg_interval);\n\n\t/*\n\t * Redzones can require enough padding that not even a single region can\n\t * fit within the number of pages that would normally be dedicated to a\n\t * run for this size class.  Increase the run size until at least one\n\t * region fits.\n\t */\n\twhile (actual_nregs == 0) {\n\t\tassert(config_fill && unlikely(opt_redzone));\n\n\t\tactual_run_size += PAGE;\n\t\tactual_nregs = (uint32_t)((actual_run_size - pad_size) /\n\t\t    bin_info->reg_interval);\n\t}\n\n\t/*\n\t * Make sure that the run will fit within an arena chunk.\n\t */\n\twhile (actual_run_size > arena_maxrun) {\n\t\tactual_run_size -= PAGE;\n\t\tactual_nregs = (uint32_t)((actual_run_size - pad_size) /\n\t\t    bin_info->reg_interval);\n\t}\n\tassert(actual_nregs > 0);\n\tassert(actual_run_size == s2u(actual_run_size));\n\n\t/* Copy final settings. */\n\tbin_info->run_size = actual_run_size;\n\tbin_info->nregs = actual_nregs;\n\tbin_info->reg0_offset = (uint32_t)(actual_run_size - (actual_nregs *\n\t    bin_info->reg_interval) - pad_size + bin_info->redzone_size);\n\n\tif (actual_run_size > small_maxrun)\n\t\tsmall_maxrun = actual_run_size;\n\n\tassert(bin_info->reg0_offset - bin_info->redzone_size + (bin_info->nregs\n\t    * bin_info->reg_interval) + pad_size == bin_info->run_size);\n}\n\nstatic void\nbin_info_init(void)\n{\n\tarena_bin_info_t *bin_info;\n\n#define\tBIN_INFO_INIT_bin_yes(index, size)\t\t\t\t\\\n\tbin_info = &arena_bin_info[index];\t\t\t\t\\\n\tbin_info->reg_size = size;\t\t\t\t\t\\\n\tbin_info_run_size_calc(bin_info);\t\t\t\t\\\n\tbitmap_info_init(&bin_info->bitmap_info, bin_info->nregs);\n#define\tBIN_INFO_INIT_bin_no(index, size)\n#define\tSC(index, lg_grp, lg_delta, ndelta, bin, lg_delta_lookup)\t\\\n\tBIN_INFO_INIT_bin_##bin(index, (ZU(1)<<lg_grp) + (ZU(ndelta)<<lg_delta))\n\tSIZE_CLASSES\n#undef BIN_INFO_INIT_bin_yes\n#undef BIN_INFO_INIT_bin_no\n#undef SC\n}\n\nstatic bool\nsmall_run_size_init(void)\n{\n\n\tassert(small_maxrun != 0);\n\n\tsmall_run_tab = (bool *)base_alloc(NULL, sizeof(bool) * (small_maxrun >>\n\t    LG_PAGE));\n\tif (small_run_tab == NULL)\n\t\treturn (true);\n\n#define\tTAB_INIT_bin_yes(index, size) {\t\t\t\t\t\\\n\t\tarena_bin_info_t *bin_info = &arena_bin_info[index];\t\\\n\t\tsmall_run_tab[bin_info->run_size >> LG_PAGE] = true;\t\\\n\t}\n#define\tTAB_INIT_bin_no(index, size)\n#define\tSC(index, lg_grp, lg_delta, ndelta, bin, lg_delta_lookup)\t\\\n\tTAB_INIT_bin_##bin(index, (ZU(1)<<lg_grp) + (ZU(ndelta)<<lg_delta))\n\tSIZE_CLASSES\n#undef TAB_INIT_bin_yes\n#undef TAB_INIT_bin_no\n#undef SC\n\n\treturn (false);\n}\n\nstatic bool\nrun_quantize_init(void)\n{\n\tunsigned i;\n\n\trun_quantize_max = chunksize + large_pad;\n\n\trun_quantize_floor_tab = (size_t *)base_alloc(NULL, sizeof(size_t) *\n\t    (run_quantize_max >> LG_PAGE));\n\tif (run_quantize_floor_tab == NULL)\n\t\treturn (true);\n\n\trun_quantize_ceil_tab = (size_t *)base_alloc(NULL, sizeof(size_t) *\n\t    (run_quantize_max >> LG_PAGE));\n\tif (run_quantize_ceil_tab == NULL)\n\t\treturn (true);\n\n\tfor (i = 1; i <= run_quantize_max >> LG_PAGE; i++) {\n\t\tsize_t run_size = i << LG_PAGE;\n\n\t\trun_quantize_floor_tab[i-1] =\n\t\t    run_quantize_floor_compute(run_size);\n\t\trun_quantize_ceil_tab[i-1] =\n\t\t    run_quantize_ceil_compute(run_size);\n\t}\n\n\treturn (false);\n}\n\nbool\narena_boot(void)\n{\n\tunsigned i;\n\n\tarena_lg_dirty_mult_default_set(opt_lg_dirty_mult);\n\tarena_decay_time_default_set(opt_decay_time);\n\n\t/*\n\t * Compute the header size such that it is large enough to contain the\n\t * page map.  The page map is biased to omit entries for the header\n\t * itself, so some iteration is necessary to compute the map bias.\n\t *\n\t * 1) Compute safe header_size and map_bias values that include enough\n\t *    space for an unbiased page map.\n\t * 2) Refine map_bias based on (1) to omit the header pages in the page\n\t *    map.  The resulting map_bias may be one too small.\n\t * 3) Refine map_bias based on (2).  The result will be >= the result\n\t *    from (2), and will always be correct.\n\t */\n\tmap_bias = 0;\n\tfor (i = 0; i < 3; i++) {\n\t\tsize_t header_size = offsetof(arena_chunk_t, map_bits) +\n\t\t    ((sizeof(arena_chunk_map_bits_t) +\n\t\t    sizeof(arena_chunk_map_misc_t)) * (chunk_npages-map_bias));\n\t\tmap_bias = (header_size + PAGE_MASK) >> LG_PAGE;\n\t}\n\tassert(map_bias > 0);\n\n\tmap_misc_offset = offsetof(arena_chunk_t, map_bits) +\n\t    sizeof(arena_chunk_map_bits_t) * (chunk_npages-map_bias);\n\n\tarena_maxrun = chunksize - (map_bias << LG_PAGE);\n\tassert(arena_maxrun > 0);\n\tlarge_maxclass = index2size(size2index(chunksize)-1);\n\tif (large_maxclass > arena_maxrun) {\n\t\t/*\n\t\t * For small chunk sizes it's possible for there to be fewer\n\t\t * non-header pages available than are necessary to serve the\n\t\t * size classes just below chunksize.\n\t\t */\n\t\tlarge_maxclass = arena_maxrun;\n\t}\n\tassert(large_maxclass > 0);\n\tnlclasses = size2index(large_maxclass) - size2index(SMALL_MAXCLASS);\n\tnhclasses = NSIZES - nlclasses - NBINS;\n\n\tbin_info_init();\n\tif (small_run_size_init())\n\t\treturn (true);\n\tif (run_quantize_init())\n\t\treturn (true);\n\n\truns_avail_bias = size2index(PAGE);\n\truns_avail_nclasses = size2index(run_quantize_max)+1 - runs_avail_bias;\n\n\treturn (false);\n}\n\nvoid\narena_prefork0(tsdn_t *tsdn, arena_t *arena)\n{\n\n\tmalloc_mutex_prefork(tsdn, &arena->lock);\n}\n\nvoid\narena_prefork1(tsdn_t *tsdn, arena_t *arena)\n{\n\n\tmalloc_mutex_prefork(tsdn, &arena->chunks_mtx);\n}\n\nvoid\narena_prefork2(tsdn_t *tsdn, arena_t *arena)\n{\n\n\tmalloc_mutex_prefork(tsdn, &arena->node_cache_mtx);\n}\n\nvoid\narena_prefork3(tsdn_t *tsdn, arena_t *arena)\n{\n\tunsigned i;\n\n\tfor (i = 0; i < NBINS; i++)\n\t\tmalloc_mutex_prefork(tsdn, &arena->bins[i].lock);\n\tmalloc_mutex_prefork(tsdn, &arena->huge_mtx);\n}\n\nvoid\narena_postfork_parent(tsdn_t *tsdn, arena_t *arena)\n{\n\tunsigned i;\n\n\tmalloc_mutex_postfork_parent(tsdn, &arena->huge_mtx);\n\tfor (i = 0; i < NBINS; i++)\n\t\tmalloc_mutex_postfork_parent(tsdn, &arena->bins[i].lock);\n\tmalloc_mutex_postfork_parent(tsdn, &arena->node_cache_mtx);\n\tmalloc_mutex_postfork_parent(tsdn, &arena->chunks_mtx);\n\tmalloc_mutex_postfork_parent(tsdn, &arena->lock);\n}\n\nvoid\narena_postfork_child(tsdn_t *tsdn, arena_t *arena)\n{\n\tunsigned i;\n\n\tmalloc_mutex_postfork_child(tsdn, &arena->huge_mtx);\n\tfor (i = 0; i < NBINS; i++)\n\t\tmalloc_mutex_postfork_child(tsdn, &arena->bins[i].lock);\n\tmalloc_mutex_postfork_child(tsdn, &arena->node_cache_mtx);\n\tmalloc_mutex_postfork_child(tsdn, &arena->chunks_mtx);\n\tmalloc_mutex_postfork_child(tsdn, &arena->lock);\n}\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/deps/jemalloc/src/atomic.c",
    "content": "#define\tJEMALLOC_ATOMIC_C_\n#include \"jemalloc/internal/jemalloc_internal.h\"\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/deps/jemalloc/src/base.c",
    "content": "#define\tJEMALLOC_BASE_C_\n#include \"jemalloc/internal/jemalloc_internal.h\"\n\n/******************************************************************************/\n/* Data. */\n\nstatic malloc_mutex_t\tbase_mtx;\nstatic extent_tree_t\tbase_avail_szad;\nstatic extent_node_t\t*base_nodes;\nstatic size_t\t\tbase_allocated;\nstatic size_t\t\tbase_resident;\nstatic size_t\t\tbase_mapped;\n\n/******************************************************************************/\n\nstatic extent_node_t *\nbase_node_try_alloc(tsdn_t *tsdn)\n{\n\textent_node_t *node;\n\n\tmalloc_mutex_assert_owner(tsdn, &base_mtx);\n\n\tif (base_nodes == NULL)\n\t\treturn (NULL);\n\tnode = base_nodes;\n\tbase_nodes = *(extent_node_t **)node;\n\tJEMALLOC_VALGRIND_MAKE_MEM_UNDEFINED(node, sizeof(extent_node_t));\n\treturn (node);\n}\n\nstatic void\nbase_node_dalloc(tsdn_t *tsdn, extent_node_t *node)\n{\n\n\tmalloc_mutex_assert_owner(tsdn, &base_mtx);\n\n\tJEMALLOC_VALGRIND_MAKE_MEM_UNDEFINED(node, sizeof(extent_node_t));\n\t*(extent_node_t **)node = base_nodes;\n\tbase_nodes = node;\n}\n\nstatic extent_node_t *\nbase_chunk_alloc(tsdn_t *tsdn, size_t minsize)\n{\n\textent_node_t *node;\n\tsize_t csize, nsize;\n\tvoid *addr;\n\n\tmalloc_mutex_assert_owner(tsdn, &base_mtx);\n\tassert(minsize != 0);\n\tnode = base_node_try_alloc(tsdn);\n\t/* Allocate enough space to also carve a node out if necessary. */\n\tnsize = (node == NULL) ? CACHELINE_CEILING(sizeof(extent_node_t)) : 0;\n\tcsize = CHUNK_CEILING(minsize + nsize);\n\taddr = chunk_alloc_base(csize);\n\tif (addr == NULL) {\n\t\tif (node != NULL)\n\t\t\tbase_node_dalloc(tsdn, node);\n\t\treturn (NULL);\n\t}\n\tbase_mapped += csize;\n\tif (node == NULL) {\n\t\tnode = (extent_node_t *)addr;\n\t\taddr = (void *)((uintptr_t)addr + nsize);\n\t\tcsize -= nsize;\n\t\tif (config_stats) {\n\t\t\tbase_allocated += nsize;\n\t\t\tbase_resident += PAGE_CEILING(nsize);\n\t\t}\n\t}\n\textent_node_init(node, NULL, addr, csize, true, true);\n\treturn (node);\n}\n\n/*\n * base_alloc() guarantees demand-zeroed memory, in order to make multi-page\n * sparse data structures such as radix tree nodes efficient with respect to\n * physical memory usage.\n */\nvoid *\nbase_alloc(tsdn_t *tsdn, size_t size)\n{\n\tvoid *ret;\n\tsize_t csize, usize;\n\textent_node_t *node;\n\textent_node_t key;\n\n\t/*\n\t * Round size up to nearest multiple of the cacheline size, so that\n\t * there is no chance of false cache line sharing.\n\t */\n\tcsize = CACHELINE_CEILING(size);\n\n\tusize = s2u(csize);\n\textent_node_init(&key, NULL, NULL, usize, false, false);\n\tmalloc_mutex_lock(tsdn, &base_mtx);\n\tnode = extent_tree_szad_nsearch(&base_avail_szad, &key);\n\tif (node != NULL) {\n\t\t/* Use existing space. */\n\t\textent_tree_szad_remove(&base_avail_szad, node);\n\t} else {\n\t\t/* Try to allocate more space. */\n\t\tnode = base_chunk_alloc(tsdn, csize);\n\t}\n\tif (node == NULL) {\n\t\tret = NULL;\n\t\tgoto label_return;\n\t}\n\n\tret = extent_node_addr_get(node);\n\tif (extent_node_size_get(node) > csize) {\n\t\textent_node_addr_set(node, (void *)((uintptr_t)ret + csize));\n\t\textent_node_size_set(node, extent_node_size_get(node) - csize);\n\t\textent_tree_szad_insert(&base_avail_szad, node);\n\t} else\n\t\tbase_node_dalloc(tsdn, node);\n\tif (config_stats) {\n\t\tbase_allocated += csize;\n\t\t/*\n\t\t * Add one PAGE to base_resident for every page boundary that is\n\t\t * crossed by the new allocation.\n\t\t */\n\t\tbase_resident += PAGE_CEILING((uintptr_t)ret + csize) -\n\t\t    PAGE_CEILING((uintptr_t)ret);\n\t}\n\tJEMALLOC_VALGRIND_MAKE_MEM_DEFINED(ret, csize);\nlabel_return:\n\tmalloc_mutex_unlock(tsdn, &base_mtx);\n\treturn (ret);\n}\n\nvoid\nbase_stats_get(tsdn_t *tsdn, size_t *allocated, size_t *resident,\n    size_t *mapped)\n{\n\n\tmalloc_mutex_lock(tsdn, &base_mtx);\n\tassert(base_allocated <= base_resident);\n\tassert(base_resident <= base_mapped);\n\t*allocated = base_allocated;\n\t*resident = base_resident;\n\t*mapped = base_mapped;\n\tmalloc_mutex_unlock(tsdn, &base_mtx);\n}\n\nbool\nbase_boot(void)\n{\n\n\tif (malloc_mutex_init(&base_mtx, \"base\", WITNESS_RANK_BASE))\n\t\treturn (true);\n\textent_tree_szad_new(&base_avail_szad);\n\tbase_nodes = NULL;\n\n\treturn (false);\n}\n\nvoid\nbase_prefork(tsdn_t *tsdn)\n{\n\n\tmalloc_mutex_prefork(tsdn, &base_mtx);\n}\n\nvoid\nbase_postfork_parent(tsdn_t *tsdn)\n{\n\n\tmalloc_mutex_postfork_parent(tsdn, &base_mtx);\n}\n\nvoid\nbase_postfork_child(tsdn_t *tsdn)\n{\n\n\tmalloc_mutex_postfork_child(tsdn, &base_mtx);\n}\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/deps/jemalloc/src/bitmap.c",
    "content": "#define\tJEMALLOC_BITMAP_C_\n#include \"jemalloc/internal/jemalloc_internal.h\"\n\n/******************************************************************************/\n\n#ifdef USE_TREE\n\nvoid\nbitmap_info_init(bitmap_info_t *binfo, size_t nbits)\n{\n\tunsigned i;\n\tsize_t group_count;\n\n\tassert(nbits > 0);\n\tassert(nbits <= (ZU(1) << LG_BITMAP_MAXBITS));\n\n\t/*\n\t * Compute the number of groups necessary to store nbits bits, and\n\t * progressively work upward through the levels until reaching a level\n\t * that requires only one group.\n\t */\n\tbinfo->levels[0].group_offset = 0;\n\tgroup_count = BITMAP_BITS2GROUPS(nbits);\n\tfor (i = 1; group_count > 1; i++) {\n\t\tassert(i < BITMAP_MAX_LEVELS);\n\t\tbinfo->levels[i].group_offset = binfo->levels[i-1].group_offset\n\t\t    + group_count;\n\t\tgroup_count = BITMAP_BITS2GROUPS(group_count);\n\t}\n\tbinfo->levels[i].group_offset = binfo->levels[i-1].group_offset\n\t    + group_count;\n\tassert(binfo->levels[i].group_offset <= BITMAP_GROUPS_MAX);\n\tbinfo->nlevels = i;\n\tbinfo->nbits = nbits;\n}\n\nstatic size_t\nbitmap_info_ngroups(const bitmap_info_t *binfo)\n{\n\n\treturn (binfo->levels[binfo->nlevels].group_offset);\n}\n\nvoid\nbitmap_init(bitmap_t *bitmap, const bitmap_info_t *binfo)\n{\n\tsize_t extra;\n\tunsigned i;\n\n\t/*\n\t * Bits are actually inverted with regard to the external bitmap\n\t * interface, so the bitmap starts out with all 1 bits, except for\n\t * trailing unused bits (if any).  Note that each group uses bit 0 to\n\t * correspond to the first logical bit in the group, so extra bits\n\t * are the most significant bits of the last group.\n\t */\n\tmemset(bitmap, 0xffU, bitmap_size(binfo));\n\textra = (BITMAP_GROUP_NBITS - (binfo->nbits & BITMAP_GROUP_NBITS_MASK))\n\t    & BITMAP_GROUP_NBITS_MASK;\n\tif (extra != 0)\n\t\tbitmap[binfo->levels[1].group_offset - 1] >>= extra;\n\tfor (i = 1; i < binfo->nlevels; i++) {\n\t\tsize_t group_count = binfo->levels[i].group_offset -\n\t\t    binfo->levels[i-1].group_offset;\n\t\textra = (BITMAP_GROUP_NBITS - (group_count &\n\t\t    BITMAP_GROUP_NBITS_MASK)) & BITMAP_GROUP_NBITS_MASK;\n\t\tif (extra != 0)\n\t\t\tbitmap[binfo->levels[i+1].group_offset - 1] >>= extra;\n\t}\n}\n\n#else /* USE_TREE */\n\nvoid\nbitmap_info_init(bitmap_info_t *binfo, size_t nbits)\n{\n\n\tassert(nbits > 0);\n\tassert(nbits <= (ZU(1) << LG_BITMAP_MAXBITS));\n\n\tbinfo->ngroups = BITMAP_BITS2GROUPS(nbits);\n\tbinfo->nbits = nbits;\n}\n\nstatic size_t\nbitmap_info_ngroups(const bitmap_info_t *binfo)\n{\n\n\treturn (binfo->ngroups);\n}\n\nvoid\nbitmap_init(bitmap_t *bitmap, const bitmap_info_t *binfo)\n{\n\tsize_t extra;\n\n\tmemset(bitmap, 0xffU, bitmap_size(binfo));\n\textra = (BITMAP_GROUP_NBITS - (binfo->nbits & BITMAP_GROUP_NBITS_MASK))\n\t    & BITMAP_GROUP_NBITS_MASK;\n\tif (extra != 0)\n\t\tbitmap[binfo->ngroups - 1] >>= extra;\n}\n\n#endif /* USE_TREE */\n\nsize_t\nbitmap_size(const bitmap_info_t *binfo)\n{\n\n\treturn (bitmap_info_ngroups(binfo) << LG_SIZEOF_BITMAP);\n}\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/deps/jemalloc/src/chunk.c",
    "content": "#define\tJEMALLOC_CHUNK_C_\n#include \"jemalloc/internal/jemalloc_internal.h\"\n\n/******************************************************************************/\n/* Data. */\n\nconst char\t*opt_dss = DSS_DEFAULT;\nsize_t\t\topt_lg_chunk = 0;\n\n/* Used exclusively for gdump triggering. */\nstatic size_t\tcurchunks;\nstatic size_t\thighchunks;\n\nrtree_t\t\tchunks_rtree;\n\n/* Various chunk-related settings. */\nsize_t\t\tchunksize;\nsize_t\t\tchunksize_mask; /* (chunksize - 1). */\nsize_t\t\tchunk_npages;\n\nstatic void\t*chunk_alloc_default(void *new_addr, size_t size,\n    size_t alignment, bool *zero, bool *commit, unsigned arena_ind);\nstatic bool\tchunk_dalloc_default(void *chunk, size_t size, bool committed,\n    unsigned arena_ind);\nstatic bool\tchunk_commit_default(void *chunk, size_t size, size_t offset,\n    size_t length, unsigned arena_ind);\nstatic bool\tchunk_decommit_default(void *chunk, size_t size, size_t offset,\n    size_t length, unsigned arena_ind);\nstatic bool\tchunk_purge_default(void *chunk, size_t size, size_t offset,\n    size_t length, unsigned arena_ind);\nstatic bool\tchunk_split_default(void *chunk, size_t size, size_t size_a,\n    size_t size_b, bool committed, unsigned arena_ind);\nstatic bool\tchunk_merge_default(void *chunk_a, size_t size_a, void *chunk_b,\n    size_t size_b, bool committed, unsigned arena_ind);\n\nconst chunk_hooks_t\tchunk_hooks_default = {\n\tchunk_alloc_default,\n\tchunk_dalloc_default,\n\tchunk_commit_default,\n\tchunk_decommit_default,\n\tchunk_purge_default,\n\tchunk_split_default,\n\tchunk_merge_default\n};\n\n/******************************************************************************/\n/*\n * Function prototypes for static functions that are referenced prior to\n * definition.\n */\n\nstatic void\tchunk_record(tsdn_t *tsdn, arena_t *arena,\n    chunk_hooks_t *chunk_hooks, extent_tree_t *chunks_szad,\n    extent_tree_t *chunks_ad, bool cache, void *chunk, size_t size, bool zeroed,\n    bool committed);\n\n/******************************************************************************/\n\nstatic chunk_hooks_t\nchunk_hooks_get_locked(arena_t *arena)\n{\n\n\treturn (arena->chunk_hooks);\n}\n\nchunk_hooks_t\nchunk_hooks_get(tsdn_t *tsdn, arena_t *arena)\n{\n\tchunk_hooks_t chunk_hooks;\n\n\tmalloc_mutex_lock(tsdn, &arena->chunks_mtx);\n\tchunk_hooks = chunk_hooks_get_locked(arena);\n\tmalloc_mutex_unlock(tsdn, &arena->chunks_mtx);\n\n\treturn (chunk_hooks);\n}\n\nchunk_hooks_t\nchunk_hooks_set(tsdn_t *tsdn, arena_t *arena, const chunk_hooks_t *chunk_hooks)\n{\n\tchunk_hooks_t old_chunk_hooks;\n\n\tmalloc_mutex_lock(tsdn, &arena->chunks_mtx);\n\told_chunk_hooks = arena->chunk_hooks;\n\t/*\n\t * Copy each field atomically so that it is impossible for readers to\n\t * see partially updated pointers.  There are places where readers only\n\t * need one hook function pointer (therefore no need to copy the\n\t * entirety of arena->chunk_hooks), and stale reads do not affect\n\t * correctness, so they perform unlocked reads.\n\t */\n#define\tATOMIC_COPY_HOOK(n) do {\t\t\t\t\t\\\n\tunion {\t\t\t\t\t\t\t\t\\\n\t\tchunk_##n##_t\t**n;\t\t\t\t\t\\\n\t\tvoid\t\t**v;\t\t\t\t\t\\\n\t} u;\t\t\t\t\t\t\t\t\\\n\tu.n = &arena->chunk_hooks.n;\t\t\t\t\t\\\n\tatomic_write_p(u.v, chunk_hooks->n);\t\t\t\t\\\n} while (0)\n\tATOMIC_COPY_HOOK(alloc);\n\tATOMIC_COPY_HOOK(dalloc);\n\tATOMIC_COPY_HOOK(commit);\n\tATOMIC_COPY_HOOK(decommit);\n\tATOMIC_COPY_HOOK(purge);\n\tATOMIC_COPY_HOOK(split);\n\tATOMIC_COPY_HOOK(merge);\n#undef ATOMIC_COPY_HOOK\n\tmalloc_mutex_unlock(tsdn, &arena->chunks_mtx);\n\n\treturn (old_chunk_hooks);\n}\n\nstatic void\nchunk_hooks_assure_initialized_impl(tsdn_t *tsdn, arena_t *arena,\n    chunk_hooks_t *chunk_hooks, bool locked)\n{\n\tstatic const chunk_hooks_t uninitialized_hooks =\n\t    CHUNK_HOOKS_INITIALIZER;\n\n\tif (memcmp(chunk_hooks, &uninitialized_hooks, sizeof(chunk_hooks_t)) ==\n\t    0) {\n\t\t*chunk_hooks = locked ? chunk_hooks_get_locked(arena) :\n\t\t    chunk_hooks_get(tsdn, arena);\n\t}\n}\n\nstatic void\nchunk_hooks_assure_initialized_locked(tsdn_t *tsdn, arena_t *arena,\n    chunk_hooks_t *chunk_hooks)\n{\n\n\tchunk_hooks_assure_initialized_impl(tsdn, arena, chunk_hooks, true);\n}\n\nstatic void\nchunk_hooks_assure_initialized(tsdn_t *tsdn, arena_t *arena,\n    chunk_hooks_t *chunk_hooks)\n{\n\n\tchunk_hooks_assure_initialized_impl(tsdn, arena, chunk_hooks, false);\n}\n\nbool\nchunk_register(tsdn_t *tsdn, const void *chunk, const extent_node_t *node)\n{\n\n\tassert(extent_node_addr_get(node) == chunk);\n\n\tif (rtree_set(&chunks_rtree, (uintptr_t)chunk, node))\n\t\treturn (true);\n\tif (config_prof && opt_prof) {\n\t\tsize_t size = extent_node_size_get(node);\n\t\tsize_t nadd = (size == 0) ? 1 : size / chunksize;\n\t\tsize_t cur = atomic_add_z(&curchunks, nadd);\n\t\tsize_t high = atomic_read_z(&highchunks);\n\t\twhile (cur > high && atomic_cas_z(&highchunks, high, cur)) {\n\t\t\t/*\n\t\t\t * Don't refresh cur, because it may have decreased\n\t\t\t * since this thread lost the highchunks update race.\n\t\t\t */\n\t\t\thigh = atomic_read_z(&highchunks);\n\t\t}\n\t\tif (cur > high && prof_gdump_get_unlocked())\n\t\t\tprof_gdump(tsdn);\n\t}\n\n\treturn (false);\n}\n\nvoid\nchunk_deregister(const void *chunk, const extent_node_t *node)\n{\n\tbool err;\n\n\terr = rtree_set(&chunks_rtree, (uintptr_t)chunk, NULL);\n\tassert(!err);\n\tif (config_prof && opt_prof) {\n\t\tsize_t size = extent_node_size_get(node);\n\t\tsize_t nsub = (size == 0) ? 1 : size / chunksize;\n\t\tassert(atomic_read_z(&curchunks) >= nsub);\n\t\tatomic_sub_z(&curchunks, nsub);\n\t}\n}\n\n/*\n * Do first-best-fit chunk selection, i.e. select the lowest chunk that best\n * fits.\n */\nstatic extent_node_t *\nchunk_first_best_fit(arena_t *arena, extent_tree_t *chunks_szad,\n    extent_tree_t *chunks_ad, size_t size)\n{\n\textent_node_t key;\n\n\tassert(size == CHUNK_CEILING(size));\n\n\textent_node_init(&key, arena, NULL, size, false, false);\n\treturn (extent_tree_szad_nsearch(chunks_szad, &key));\n}\n\nstatic void *\nchunk_recycle(tsdn_t *tsdn, arena_t *arena, chunk_hooks_t *chunk_hooks,\n    extent_tree_t *chunks_szad, extent_tree_t *chunks_ad, bool cache,\n    void *new_addr, size_t size, size_t alignment, bool *zero, bool *commit,\n    bool dalloc_node)\n{\n\tvoid *ret;\n\textent_node_t *node;\n\tsize_t alloc_size, leadsize, trailsize;\n\tbool zeroed, committed;\n\n\tassert(new_addr == NULL || alignment == chunksize);\n\t/*\n\t * Cached chunks use the node linkage embedded in their headers, in\n\t * which case dalloc_node is true, and new_addr is non-NULL because\n\t * we're operating on a specific chunk.\n\t */\n\tassert(dalloc_node || new_addr != NULL);\n\n\talloc_size = CHUNK_CEILING(s2u(size + alignment - chunksize));\n\t/* Beware size_t wrap-around. */\n\tif (alloc_size < size)\n\t\treturn (NULL);\n\tmalloc_mutex_lock(tsdn, &arena->chunks_mtx);\n\tchunk_hooks_assure_initialized_locked(tsdn, arena, chunk_hooks);\n\tif (new_addr != NULL) {\n\t\textent_node_t key;\n\t\textent_node_init(&key, arena, new_addr, alloc_size, false,\n\t\t    false);\n\t\tnode = extent_tree_ad_search(chunks_ad, &key);\n\t} else {\n\t\tnode = chunk_first_best_fit(arena, chunks_szad, chunks_ad,\n\t\t    alloc_size);\n\t}\n\tif (node == NULL || (new_addr != NULL && extent_node_size_get(node) <\n\t    size)) {\n\t\tmalloc_mutex_unlock(tsdn, &arena->chunks_mtx);\n\t\treturn (NULL);\n\t}\n\tleadsize = ALIGNMENT_CEILING((uintptr_t)extent_node_addr_get(node),\n\t    alignment) - (uintptr_t)extent_node_addr_get(node);\n\tassert(new_addr == NULL || leadsize == 0);\n\tassert(extent_node_size_get(node) >= leadsize + size);\n\ttrailsize = extent_node_size_get(node) - leadsize - size;\n\tret = (void *)((uintptr_t)extent_node_addr_get(node) + leadsize);\n\tzeroed = extent_node_zeroed_get(node);\n\tif (zeroed)\n\t\t*zero = true;\n\tcommitted = extent_node_committed_get(node);\n\tif (committed)\n\t\t*commit = true;\n\t/* Split the lead. */\n\tif (leadsize != 0 &&\n\t    chunk_hooks->split(extent_node_addr_get(node),\n\t    extent_node_size_get(node), leadsize, size, false, arena->ind)) {\n\t\tmalloc_mutex_unlock(tsdn, &arena->chunks_mtx);\n\t\treturn (NULL);\n\t}\n\t/* Remove node from the tree. */\n\textent_tree_szad_remove(chunks_szad, node);\n\textent_tree_ad_remove(chunks_ad, node);\n\tarena_chunk_cache_maybe_remove(arena, node, cache);\n\tif (leadsize != 0) {\n\t\t/* Insert the leading space as a smaller chunk. */\n\t\textent_node_size_set(node, leadsize);\n\t\textent_tree_szad_insert(chunks_szad, node);\n\t\textent_tree_ad_insert(chunks_ad, node);\n\t\tarena_chunk_cache_maybe_insert(arena, node, cache);\n\t\tnode = NULL;\n\t}\n\tif (trailsize != 0) {\n\t\t/* Split the trail. */\n\t\tif (chunk_hooks->split(ret, size + trailsize, size,\n\t\t    trailsize, false, arena->ind)) {\n\t\t\tif (dalloc_node && node != NULL)\n\t\t\t\tarena_node_dalloc(tsdn, arena, node);\n\t\t\tmalloc_mutex_unlock(tsdn, &arena->chunks_mtx);\n\t\t\tchunk_record(tsdn, arena, chunk_hooks, chunks_szad,\n\t\t\t    chunks_ad, cache, ret, size + trailsize, zeroed,\n\t\t\t    committed);\n\t\t\treturn (NULL);\n\t\t}\n\t\t/* Insert the trailing space as a smaller chunk. */\n\t\tif (node == NULL) {\n\t\t\tnode = arena_node_alloc(tsdn, arena);\n\t\t\tif (node == NULL) {\n\t\t\t\tmalloc_mutex_unlock(tsdn, &arena->chunks_mtx);\n\t\t\t\tchunk_record(tsdn, arena, chunk_hooks,\n\t\t\t\t    chunks_szad, chunks_ad, cache, ret, size +\n\t\t\t\t    trailsize, zeroed, committed);\n\t\t\t\treturn (NULL);\n\t\t\t}\n\t\t}\n\t\textent_node_init(node, arena, (void *)((uintptr_t)(ret) + size),\n\t\t    trailsize, zeroed, committed);\n\t\textent_tree_szad_insert(chunks_szad, node);\n\t\textent_tree_ad_insert(chunks_ad, node);\n\t\tarena_chunk_cache_maybe_insert(arena, node, cache);\n\t\tnode = NULL;\n\t}\n\tif (!committed && chunk_hooks->commit(ret, size, 0, size, arena->ind)) {\n\t\tmalloc_mutex_unlock(tsdn, &arena->chunks_mtx);\n\t\tchunk_record(tsdn, arena, chunk_hooks, chunks_szad, chunks_ad,\n\t\t    cache, ret, size, zeroed, committed);\n\t\treturn (NULL);\n\t}\n\tmalloc_mutex_unlock(tsdn, &arena->chunks_mtx);\n\n\tassert(dalloc_node || node != NULL);\n\tif (dalloc_node && node != NULL)\n\t\tarena_node_dalloc(tsdn, arena, node);\n\tif (*zero) {\n\t\tif (!zeroed)\n\t\t\tmemset(ret, 0, size);\n\t\telse if (config_debug) {\n\t\t\tsize_t i;\n\t\t\tsize_t *p = (size_t *)(uintptr_t)ret;\n\n\t\t\tJEMALLOC_VALGRIND_MAKE_MEM_DEFINED(ret, size);\n\t\t\tfor (i = 0; i < size / sizeof(size_t); i++)\n\t\t\t\tassert(p[i] == 0);\n\t\t}\n\t}\n\treturn (ret);\n}\n\n/*\n * If the caller specifies (!*zero), it is still possible to receive zeroed\n * memory, in which case *zero is toggled to true.  arena_chunk_alloc() takes\n * advantage of this to avoid demanding zeroed chunks, but taking advantage of\n * them if they are returned.\n */\nstatic void *\nchunk_alloc_core(tsdn_t *tsdn, arena_t *arena, void *new_addr, size_t size,\n    size_t alignment, bool *zero, bool *commit, dss_prec_t dss_prec)\n{\n\tvoid *ret;\n\n\tassert(size != 0);\n\tassert((size & chunksize_mask) == 0);\n\tassert(alignment != 0);\n\tassert((alignment & chunksize_mask) == 0);\n\n\t/* \"primary\" dss. */\n\tif (have_dss && dss_prec == dss_prec_primary && (ret =\n\t    chunk_alloc_dss(tsdn, arena, new_addr, size, alignment, zero,\n\t    commit)) != NULL)\n\t\treturn (ret);\n\t/* mmap. */\n\tif ((ret = chunk_alloc_mmap(new_addr, size, alignment, zero, commit)) !=\n\t    NULL)\n\t\treturn (ret);\n\t/* \"secondary\" dss. */\n\tif (have_dss && dss_prec == dss_prec_secondary && (ret =\n\t    chunk_alloc_dss(tsdn, arena, new_addr, size, alignment, zero,\n\t    commit)) != NULL)\n\t\treturn (ret);\n\n\t/* All strategies for allocation failed. */\n\treturn (NULL);\n}\n\nvoid *\nchunk_alloc_base(size_t size)\n{\n\tvoid *ret;\n\tbool zero, commit;\n\n\t/*\n\t * Directly call chunk_alloc_mmap() rather than chunk_alloc_core()\n\t * because it's critical that chunk_alloc_base() return untouched\n\t * demand-zeroed virtual memory.\n\t */\n\tzero = true;\n\tcommit = true;\n\tret = chunk_alloc_mmap(NULL, size, chunksize, &zero, &commit);\n\tif (ret == NULL)\n\t\treturn (NULL);\n\tif (config_valgrind)\n\t\tJEMALLOC_VALGRIND_MAKE_MEM_UNDEFINED(ret, size);\n\n\treturn (ret);\n}\n\nvoid *\nchunk_alloc_cache(tsdn_t *tsdn, arena_t *arena, chunk_hooks_t *chunk_hooks,\n    void *new_addr, size_t size, size_t alignment, bool *zero, bool dalloc_node)\n{\n\tvoid *ret;\n\tbool commit;\n\n\tassert(size != 0);\n\tassert((size & chunksize_mask) == 0);\n\tassert(alignment != 0);\n\tassert((alignment & chunksize_mask) == 0);\n\n\tcommit = true;\n\tret = chunk_recycle(tsdn, arena, chunk_hooks,\n\t    &arena->chunks_szad_cached, &arena->chunks_ad_cached, true,\n\t    new_addr, size, alignment, zero, &commit, dalloc_node);\n\tif (ret == NULL)\n\t\treturn (NULL);\n\tassert(commit);\n\tif (config_valgrind)\n\t\tJEMALLOC_VALGRIND_MAKE_MEM_UNDEFINED(ret, size);\n\treturn (ret);\n}\n\nstatic arena_t *\nchunk_arena_get(tsdn_t *tsdn, unsigned arena_ind)\n{\n\tarena_t *arena;\n\n\tarena = arena_get(tsdn, arena_ind, false);\n\t/*\n\t * The arena we're allocating on behalf of must have been initialized\n\t * already.\n\t */\n\tassert(arena != NULL);\n\treturn (arena);\n}\n\nstatic void *\nchunk_alloc_default_impl(tsdn_t *tsdn, arena_t *arena, void *new_addr,\n    size_t size, size_t alignment, bool *zero, bool *commit)\n{\n\tvoid *ret;\n\n\tret = chunk_alloc_core(tsdn, arena, new_addr, size, alignment, zero,\n\t    commit, arena->dss_prec);\n\tif (ret == NULL)\n\t\treturn (NULL);\n\tif (config_valgrind)\n\t\tJEMALLOC_VALGRIND_MAKE_MEM_UNDEFINED(ret, size);\n\n\treturn (ret);\n}\n\nstatic void *\nchunk_alloc_default(void *new_addr, size_t size, size_t alignment, bool *zero,\n    bool *commit, unsigned arena_ind)\n{\n\ttsdn_t *tsdn;\n\tarena_t *arena;\n\n\ttsdn = tsdn_fetch();\n\tarena = chunk_arena_get(tsdn, arena_ind);\n\n\treturn (chunk_alloc_default_impl(tsdn, arena, new_addr, size, alignment,\n\t    zero, commit));\n}\n\nstatic void *\nchunk_alloc_retained(tsdn_t *tsdn, arena_t *arena, chunk_hooks_t *chunk_hooks,\n    void *new_addr, size_t size, size_t alignment, bool *zero, bool *commit)\n{\n\tvoid *ret;\n\n\tassert(size != 0);\n\tassert((size & chunksize_mask) == 0);\n\tassert(alignment != 0);\n\tassert((alignment & chunksize_mask) == 0);\n\n\tret = chunk_recycle(tsdn, arena, chunk_hooks,\n\t    &arena->chunks_szad_retained, &arena->chunks_ad_retained, false,\n\t    new_addr, size, alignment, zero, commit, true);\n\n\tif (config_stats && ret != NULL)\n\t\tarena->stats.retained -= size;\n\n\treturn (ret);\n}\n\nvoid *\nchunk_alloc_wrapper(tsdn_t *tsdn, arena_t *arena, chunk_hooks_t *chunk_hooks,\n    void *new_addr, size_t size, size_t alignment, bool *zero, bool *commit)\n{\n\tvoid *ret;\n\n\tchunk_hooks_assure_initialized(tsdn, arena, chunk_hooks);\n\n\tret = chunk_alloc_retained(tsdn, arena, chunk_hooks, new_addr, size,\n\t    alignment, zero, commit);\n\tif (ret == NULL) {\n\t\tif (chunk_hooks->alloc == chunk_alloc_default) {\n\t\t\t/* Call directly to propagate tsdn. */\n\t\t\tret = chunk_alloc_default_impl(tsdn, arena, new_addr,\n\t\t\t    size, alignment, zero, commit);\n\t\t} else {\n\t\t\tret = chunk_hooks->alloc(new_addr, size, alignment,\n\t\t\t    zero, commit, arena->ind);\n\t\t}\n\n\t\tif (ret == NULL)\n\t\t\treturn (NULL);\n\n\t\tif (config_valgrind && chunk_hooks->alloc !=\n\t\t    chunk_alloc_default)\n\t\t\tJEMALLOC_VALGRIND_MAKE_MEM_UNDEFINED(ret, chunksize);\n\t}\n\n\treturn (ret);\n}\n\nstatic void\nchunk_record(tsdn_t *tsdn, arena_t *arena, chunk_hooks_t *chunk_hooks,\n    extent_tree_t *chunks_szad, extent_tree_t *chunks_ad, bool cache,\n    void *chunk, size_t size, bool zeroed, bool committed)\n{\n\tbool unzeroed;\n\textent_node_t *node, *prev;\n\textent_node_t key;\n\n\tassert(!cache || !zeroed);\n\tunzeroed = cache || !zeroed;\n\tJEMALLOC_VALGRIND_MAKE_MEM_NOACCESS(chunk, size);\n\n\tmalloc_mutex_lock(tsdn, &arena->chunks_mtx);\n\tchunk_hooks_assure_initialized_locked(tsdn, arena, chunk_hooks);\n\textent_node_init(&key, arena, (void *)((uintptr_t)chunk + size), 0,\n\t    false, false);\n\tnode = extent_tree_ad_nsearch(chunks_ad, &key);\n\t/* Try to coalesce forward. */\n\tif (node != NULL && extent_node_addr_get(node) ==\n\t    extent_node_addr_get(&key) && extent_node_committed_get(node) ==\n\t    committed && !chunk_hooks->merge(chunk, size,\n\t    extent_node_addr_get(node), extent_node_size_get(node), false,\n\t    arena->ind)) {\n\t\t/*\n\t\t * Coalesce chunk with the following address range.  This does\n\t\t * not change the position within chunks_ad, so only\n\t\t * remove/insert from/into chunks_szad.\n\t\t */\n\t\textent_tree_szad_remove(chunks_szad, node);\n\t\tarena_chunk_cache_maybe_remove(arena, node, cache);\n\t\textent_node_addr_set(node, chunk);\n\t\textent_node_size_set(node, size + extent_node_size_get(node));\n\t\textent_node_zeroed_set(node, extent_node_zeroed_get(node) &&\n\t\t    !unzeroed);\n\t\textent_tree_szad_insert(chunks_szad, node);\n\t\tarena_chunk_cache_maybe_insert(arena, node, cache);\n\t} else {\n\t\t/* Coalescing forward failed, so insert a new node. */\n\t\tnode = arena_node_alloc(tsdn, arena);\n\t\tif (node == NULL) {\n\t\t\t/*\n\t\t\t * Node allocation failed, which is an exceedingly\n\t\t\t * unlikely failure.  Leak chunk after making sure its\n\t\t\t * pages have already been purged, so that this is only\n\t\t\t * a virtual memory leak.\n\t\t\t */\n\t\t\tif (cache) {\n\t\t\t\tchunk_purge_wrapper(tsdn, arena, chunk_hooks,\n\t\t\t\t    chunk, size, 0, size);\n\t\t\t}\n\t\t\tgoto label_return;\n\t\t}\n\t\textent_node_init(node, arena, chunk, size, !unzeroed,\n\t\t    committed);\n\t\textent_tree_ad_insert(chunks_ad, node);\n\t\textent_tree_szad_insert(chunks_szad, node);\n\t\tarena_chunk_cache_maybe_insert(arena, node, cache);\n\t}\n\n\t/* Try to coalesce backward. */\n\tprev = extent_tree_ad_prev(chunks_ad, node);\n\tif (prev != NULL && (void *)((uintptr_t)extent_node_addr_get(prev) +\n\t    extent_node_size_get(prev)) == chunk &&\n\t    extent_node_committed_get(prev) == committed &&\n\t    !chunk_hooks->merge(extent_node_addr_get(prev),\n\t    extent_node_size_get(prev), chunk, size, false, arena->ind)) {\n\t\t/*\n\t\t * Coalesce chunk with the previous address range.  This does\n\t\t * not change the position within chunks_ad, so only\n\t\t * remove/insert node from/into chunks_szad.\n\t\t */\n\t\textent_tree_szad_remove(chunks_szad, prev);\n\t\textent_tree_ad_remove(chunks_ad, prev);\n\t\tarena_chunk_cache_maybe_remove(arena, prev, cache);\n\t\textent_tree_szad_remove(chunks_szad, node);\n\t\tarena_chunk_cache_maybe_remove(arena, node, cache);\n\t\textent_node_addr_set(node, extent_node_addr_get(prev));\n\t\textent_node_size_set(node, extent_node_size_get(prev) +\n\t\t    extent_node_size_get(node));\n\t\textent_node_zeroed_set(node, extent_node_zeroed_get(prev) &&\n\t\t    extent_node_zeroed_get(node));\n\t\textent_tree_szad_insert(chunks_szad, node);\n\t\tarena_chunk_cache_maybe_insert(arena, node, cache);\n\n\t\tarena_node_dalloc(tsdn, arena, prev);\n\t}\n\nlabel_return:\n\tmalloc_mutex_unlock(tsdn, &arena->chunks_mtx);\n}\n\nvoid\nchunk_dalloc_cache(tsdn_t *tsdn, arena_t *arena, chunk_hooks_t *chunk_hooks,\n    void *chunk, size_t size, bool committed)\n{\n\n\tassert(chunk != NULL);\n\tassert(CHUNK_ADDR2BASE(chunk) == chunk);\n\tassert(size != 0);\n\tassert((size & chunksize_mask) == 0);\n\n\tchunk_record(tsdn, arena, chunk_hooks, &arena->chunks_szad_cached,\n\t    &arena->chunks_ad_cached, true, chunk, size, false, committed);\n\tarena_maybe_purge(tsdn, arena);\n}\n\nstatic bool\nchunk_dalloc_default_impl(tsdn_t *tsdn, void *chunk, size_t size)\n{\n\n\tif (!have_dss || !chunk_in_dss(tsdn, chunk))\n\t\treturn (chunk_dalloc_mmap(chunk, size));\n\treturn (true);\n}\n\nstatic bool\nchunk_dalloc_default(void *chunk, size_t size, bool committed,\n    unsigned arena_ind)\n{\n\ttsdn_t *tsdn;\n\n\ttsdn = tsdn_fetch();\n\n\treturn (chunk_dalloc_default_impl(tsdn, chunk, size));\n}\n\nvoid\nchunk_dalloc_wrapper(tsdn_t *tsdn, arena_t *arena, chunk_hooks_t *chunk_hooks,\n    void *chunk, size_t size, bool zeroed, bool committed)\n{\n\tbool err;\n\n\tassert(chunk != NULL);\n\tassert(CHUNK_ADDR2BASE(chunk) == chunk);\n\tassert(size != 0);\n\tassert((size & chunksize_mask) == 0);\n\n\tchunk_hooks_assure_initialized(tsdn, arena, chunk_hooks);\n\t/* Try to deallocate. */\n\tif (chunk_hooks->dalloc == chunk_dalloc_default) {\n\t\t/* Call directly to propagate tsdn. */\n\t\terr = chunk_dalloc_default_impl(tsdn, chunk, size);\n\t} else\n\t\terr = chunk_hooks->dalloc(chunk, size, committed, arena->ind);\n\n\tif (!err)\n\t\treturn;\n\t/* Try to decommit; purge if that fails. */\n\tif (committed) {\n\t\tcommitted = chunk_hooks->decommit(chunk, size, 0, size,\n\t\t    arena->ind);\n\t}\n\tzeroed = !committed || !chunk_hooks->purge(chunk, size, 0, size,\n\t    arena->ind);\n\tchunk_record(tsdn, arena, chunk_hooks, &arena->chunks_szad_retained,\n\t    &arena->chunks_ad_retained, false, chunk, size, zeroed, committed);\n\n\tif (config_stats)\n\t\tarena->stats.retained += size;\n}\n\nstatic bool\nchunk_commit_default(void *chunk, size_t size, size_t offset, size_t length,\n    unsigned arena_ind)\n{\n\n\treturn (pages_commit((void *)((uintptr_t)chunk + (uintptr_t)offset),\n\t    length));\n}\n\nstatic bool\nchunk_decommit_default(void *chunk, size_t size, size_t offset, size_t length,\n    unsigned arena_ind)\n{\n\n\treturn (pages_decommit((void *)((uintptr_t)chunk + (uintptr_t)offset),\n\t    length));\n}\n\nstatic bool\nchunk_purge_default(void *chunk, size_t size, size_t offset, size_t length,\n    unsigned arena_ind)\n{\n\n\tassert(chunk != NULL);\n\tassert(CHUNK_ADDR2BASE(chunk) == chunk);\n\tassert((offset & PAGE_MASK) == 0);\n\tassert(length != 0);\n\tassert((length & PAGE_MASK) == 0);\n\n\treturn (pages_purge((void *)((uintptr_t)chunk + (uintptr_t)offset),\n\t    length));\n}\n\nbool\nchunk_purge_wrapper(tsdn_t *tsdn, arena_t *arena, chunk_hooks_t *chunk_hooks,\n    void *chunk, size_t size, size_t offset, size_t length)\n{\n\n\tchunk_hooks_assure_initialized(tsdn, arena, chunk_hooks);\n\treturn (chunk_hooks->purge(chunk, size, offset, length, arena->ind));\n}\n\nstatic bool\nchunk_split_default(void *chunk, size_t size, size_t size_a, size_t size_b,\n    bool committed, unsigned arena_ind)\n{\n\n\tif (!maps_coalesce)\n\t\treturn (true);\n\treturn (false);\n}\n\nstatic bool\nchunk_merge_default_impl(tsdn_t *tsdn, void *chunk_a, void *chunk_b)\n{\n\n\tif (!maps_coalesce)\n\t\treturn (true);\n\tif (have_dss && chunk_in_dss(tsdn, chunk_a) != chunk_in_dss(tsdn,\n\t    chunk_b))\n\t\treturn (true);\n\n\treturn (false);\n}\n\nstatic bool\nchunk_merge_default(void *chunk_a, size_t size_a, void *chunk_b, size_t size_b,\n    bool committed, unsigned arena_ind)\n{\n\ttsdn_t *tsdn;\n\n\ttsdn = tsdn_fetch();\n\n\treturn (chunk_merge_default_impl(tsdn, chunk_a, chunk_b));\n}\n\nstatic rtree_node_elm_t *\nchunks_rtree_node_alloc(size_t nelms)\n{\n\n\treturn ((rtree_node_elm_t *)base_alloc(TSDN_NULL, nelms *\n\t    sizeof(rtree_node_elm_t)));\n}\n\nbool\nchunk_boot(void)\n{\n#ifdef _WIN32\n\tSYSTEM_INFO info;\n\tGetSystemInfo(&info);\n\n\t/*\n\t * Verify actual page size is equal to or an integral multiple of\n\t * configured page size.\n\t */\n\tif (info.dwPageSize & ((1U << LG_PAGE) - 1))\n\t\treturn (true);\n\n\t/*\n\t * Configure chunksize (if not set) to match granularity (usually 64K),\n\t * so pages_map will always take fast path.\n\t */\n\tif (!opt_lg_chunk) {\n\t\topt_lg_chunk = ffs_u((unsigned)info.dwAllocationGranularity)\n\t\t    - 1;\n\t}\n#else\n\tif (!opt_lg_chunk)\n\t\topt_lg_chunk = LG_CHUNK_DEFAULT;\n#endif\n\n\t/* Set variables according to the value of opt_lg_chunk. */\n\tchunksize = (ZU(1) << opt_lg_chunk);\n\tassert(chunksize >= PAGE);\n\tchunksize_mask = chunksize - 1;\n\tchunk_npages = (chunksize >> LG_PAGE);\n\n\tif (have_dss && chunk_dss_boot())\n\t\treturn (true);\n\tif (rtree_new(&chunks_rtree, (unsigned)((ZU(1) << (LG_SIZEOF_PTR+3)) -\n\t    opt_lg_chunk), chunks_rtree_node_alloc, NULL))\n\t\treturn (true);\n\n\treturn (false);\n}\n\nvoid\nchunk_prefork(tsdn_t *tsdn)\n{\n\n\tchunk_dss_prefork(tsdn);\n}\n\nvoid\nchunk_postfork_parent(tsdn_t *tsdn)\n{\n\n\tchunk_dss_postfork_parent(tsdn);\n}\n\nvoid\nchunk_postfork_child(tsdn_t *tsdn)\n{\n\n\tchunk_dss_postfork_child(tsdn);\n}\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/deps/jemalloc/src/chunk_dss.c",
    "content": "#define\tJEMALLOC_CHUNK_DSS_C_\n#include \"jemalloc/internal/jemalloc_internal.h\"\n/******************************************************************************/\n/* Data. */\n\nconst char\t*dss_prec_names[] = {\n\t\"disabled\",\n\t\"primary\",\n\t\"secondary\",\n\t\"N/A\"\n};\n\n/* Current dss precedence default, used when creating new arenas. */\nstatic dss_prec_t\tdss_prec_default = DSS_PREC_DEFAULT;\n\n/*\n * Protects sbrk() calls.  This avoids malloc races among threads, though it\n * does not protect against races with threads that call sbrk() directly.\n */\nstatic malloc_mutex_t\tdss_mtx;\n\n/* Base address of the DSS. */\nstatic void\t\t*dss_base;\n/* Current end of the DSS, or ((void *)-1) if the DSS is exhausted. */\nstatic void\t\t*dss_prev;\n/* Current upper limit on DSS addresses. */\nstatic void\t\t*dss_max;\n\n/******************************************************************************/\n\nstatic void *\nchunk_dss_sbrk(intptr_t increment)\n{\n\n#ifdef JEMALLOC_DSS\n\treturn (sbrk(increment));\n#else\n\tnot_implemented();\n\treturn (NULL);\n#endif\n}\n\ndss_prec_t\nchunk_dss_prec_get(tsdn_t *tsdn)\n{\n\tdss_prec_t ret;\n\n\tif (!have_dss)\n\t\treturn (dss_prec_disabled);\n\tmalloc_mutex_lock(tsdn, &dss_mtx);\n\tret = dss_prec_default;\n\tmalloc_mutex_unlock(tsdn, &dss_mtx);\n\treturn (ret);\n}\n\nbool\nchunk_dss_prec_set(tsdn_t *tsdn, dss_prec_t dss_prec)\n{\n\n\tif (!have_dss)\n\t\treturn (dss_prec != dss_prec_disabled);\n\tmalloc_mutex_lock(tsdn, &dss_mtx);\n\tdss_prec_default = dss_prec;\n\tmalloc_mutex_unlock(tsdn, &dss_mtx);\n\treturn (false);\n}\n\nvoid *\nchunk_alloc_dss(tsdn_t *tsdn, arena_t *arena, void *new_addr, size_t size,\n    size_t alignment, bool *zero, bool *commit)\n{\n\tcassert(have_dss);\n\tassert(size > 0 && (size & chunksize_mask) == 0);\n\tassert(alignment > 0 && (alignment & chunksize_mask) == 0);\n\n\t/*\n\t * sbrk() uses a signed increment argument, so take care not to\n\t * interpret a huge allocation request as a negative increment.\n\t */\n\tif ((intptr_t)size < 0)\n\t\treturn (NULL);\n\n\tmalloc_mutex_lock(tsdn, &dss_mtx);\n\tif (dss_prev != (void *)-1) {\n\n\t\t/*\n\t\t * The loop is necessary to recover from races with other\n\t\t * threads that are using the DSS for something other than\n\t\t * malloc.\n\t\t */\n\t\tdo {\n\t\t\tvoid *ret, *cpad, *dss_next;\n\t\t\tsize_t gap_size, cpad_size;\n\t\t\tintptr_t incr;\n\t\t\t/* Avoid an unnecessary system call. */\n\t\t\tif (new_addr != NULL && dss_max != new_addr)\n\t\t\t\tbreak;\n\n\t\t\t/* Get the current end of the DSS. */\n\t\t\tdss_max = chunk_dss_sbrk(0);\n\n\t\t\t/* Make sure the earlier condition still holds. */\n\t\t\tif (new_addr != NULL && dss_max != new_addr)\n\t\t\t\tbreak;\n\n\t\t\t/*\n\t\t\t * Calculate how much padding is necessary to\n\t\t\t * chunk-align the end of the DSS.\n\t\t\t */\n\t\t\tgap_size = (chunksize - CHUNK_ADDR2OFFSET(dss_max)) &\n\t\t\t    chunksize_mask;\n\t\t\t/*\n\t\t\t * Compute how much chunk-aligned pad space (if any) is\n\t\t\t * necessary to satisfy alignment.  This space can be\n\t\t\t * recycled for later use.\n\t\t\t */\n\t\t\tcpad = (void *)((uintptr_t)dss_max + gap_size);\n\t\t\tret = (void *)ALIGNMENT_CEILING((uintptr_t)dss_max,\n\t\t\t    alignment);\n\t\t\tcpad_size = (uintptr_t)ret - (uintptr_t)cpad;\n\t\t\tdss_next = (void *)((uintptr_t)ret + size);\n\t\t\tif ((uintptr_t)ret < (uintptr_t)dss_max ||\n\t\t\t    (uintptr_t)dss_next < (uintptr_t)dss_max) {\n\t\t\t\t/* Wrap-around. */\n\t\t\t\tmalloc_mutex_unlock(tsdn, &dss_mtx);\n\t\t\t\treturn (NULL);\n\t\t\t}\n\t\t\tincr = gap_size + cpad_size + size;\n\t\t\tdss_prev = chunk_dss_sbrk(incr);\n\t\t\tif (dss_prev == dss_max) {\n\t\t\t\t/* Success. */\n\t\t\t\tdss_max = dss_next;\n\t\t\t\tmalloc_mutex_unlock(tsdn, &dss_mtx);\n\t\t\t\tif (cpad_size != 0) {\n\t\t\t\t\tchunk_hooks_t chunk_hooks =\n\t\t\t\t\t    CHUNK_HOOKS_INITIALIZER;\n\t\t\t\t\tchunk_dalloc_wrapper(tsdn, arena,\n\t\t\t\t\t    &chunk_hooks, cpad, cpad_size,\n\t\t\t\t\t    false, true);\n\t\t\t\t}\n\t\t\t\tif (*zero) {\n\t\t\t\t\tJEMALLOC_VALGRIND_MAKE_MEM_UNDEFINED(\n\t\t\t\t\t    ret, size);\n\t\t\t\t\tmemset(ret, 0, size);\n\t\t\t\t}\n\t\t\t\tif (!*commit)\n\t\t\t\t\t*commit = pages_decommit(ret, size);\n\t\t\t\treturn (ret);\n\t\t\t}\n\t\t} while (dss_prev != (void *)-1);\n\t}\n\tmalloc_mutex_unlock(tsdn, &dss_mtx);\n\n\treturn (NULL);\n}\n\nbool\nchunk_in_dss(tsdn_t *tsdn, void *chunk)\n{\n\tbool ret;\n\n\tcassert(have_dss);\n\n\tmalloc_mutex_lock(tsdn, &dss_mtx);\n\tif ((uintptr_t)chunk >= (uintptr_t)dss_base\n\t    && (uintptr_t)chunk < (uintptr_t)dss_max)\n\t\tret = true;\n\telse\n\t\tret = false;\n\tmalloc_mutex_unlock(tsdn, &dss_mtx);\n\n\treturn (ret);\n}\n\nbool\nchunk_dss_boot(void)\n{\n\n\tcassert(have_dss);\n\n\tif (malloc_mutex_init(&dss_mtx, \"dss\", WITNESS_RANK_DSS))\n\t\treturn (true);\n\tdss_base = chunk_dss_sbrk(0);\n\tdss_prev = dss_base;\n\tdss_max = dss_base;\n\n\treturn (false);\n}\n\nvoid\nchunk_dss_prefork(tsdn_t *tsdn)\n{\n\n\tif (have_dss)\n\t\tmalloc_mutex_prefork(tsdn, &dss_mtx);\n}\n\nvoid\nchunk_dss_postfork_parent(tsdn_t *tsdn)\n{\n\n\tif (have_dss)\n\t\tmalloc_mutex_postfork_parent(tsdn, &dss_mtx);\n}\n\nvoid\nchunk_dss_postfork_child(tsdn_t *tsdn)\n{\n\n\tif (have_dss)\n\t\tmalloc_mutex_postfork_child(tsdn, &dss_mtx);\n}\n\n/******************************************************************************/\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/deps/jemalloc/src/chunk_mmap.c",
    "content": "#define\tJEMALLOC_CHUNK_MMAP_C_\n#include \"jemalloc/internal/jemalloc_internal.h\"\n\n/******************************************************************************/\n\nstatic void *\nchunk_alloc_mmap_slow(size_t size, size_t alignment, bool *zero, bool *commit)\n{\n\tvoid *ret;\n\tsize_t alloc_size;\n\n\talloc_size = size + alignment - PAGE;\n\t/* Beware size_t wrap-around. */\n\tif (alloc_size < size)\n\t\treturn (NULL);\n\tdo {\n\t\tvoid *pages;\n\t\tsize_t leadsize;\n\t\tpages = pages_map(NULL, alloc_size, commit);\n\t\tif (pages == NULL)\n\t\t\treturn (NULL);\n\t\tleadsize = ALIGNMENT_CEILING((uintptr_t)pages, alignment) -\n\t\t    (uintptr_t)pages;\n\t\tret = pages_trim(pages, alloc_size, leadsize, size, commit);\n\t} while (ret == NULL);\n\n\tassert(ret != NULL);\n\t*zero = true;\n\treturn (ret);\n}\n\nvoid *\nchunk_alloc_mmap(void *new_addr, size_t size, size_t alignment, bool *zero,\n    bool *commit)\n{\n\tvoid *ret;\n\tsize_t offset;\n\n\t/*\n\t * Ideally, there would be a way to specify alignment to mmap() (like\n\t * NetBSD has), but in the absence of such a feature, we have to work\n\t * hard to efficiently create aligned mappings.  The reliable, but\n\t * slow method is to create a mapping that is over-sized, then trim the\n\t * excess.  However, that always results in one or two calls to\n\t * pages_unmap().\n\t *\n\t * Optimistically try mapping precisely the right amount before falling\n\t * back to the slow method, with the expectation that the optimistic\n\t * approach works most of the time.\n\t */\n\n\tassert(alignment != 0);\n\tassert((alignment & chunksize_mask) == 0);\n\n\tret = pages_map(new_addr, size, commit);\n\tif (ret == NULL || ret == new_addr)\n\t\treturn (ret);\n\tassert(new_addr == NULL);\n\toffset = ALIGNMENT_ADDR2OFFSET(ret, alignment);\n\tif (offset != 0) {\n\t\tpages_unmap(ret, size);\n\t\treturn (chunk_alloc_mmap_slow(size, alignment, zero, commit));\n\t}\n\n\tassert(ret != NULL);\n\t*zero = true;\n\treturn (ret);\n}\n\nbool\nchunk_dalloc_mmap(void *chunk, size_t size)\n{\n\n\tif (config_munmap)\n\t\tpages_unmap(chunk, size);\n\n\treturn (!config_munmap);\n}\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/deps/jemalloc/src/ckh.c",
    "content": "/*\n *******************************************************************************\n * Implementation of (2^1+,2) cuckoo hashing, where 2^1+ indicates that each\n * hash bucket contains 2^n cells, for n >= 1, and 2 indicates that two hash\n * functions are employed.  The original cuckoo hashing algorithm was described\n * in:\n *\n *   Pagh, R., F.F. Rodler (2004) Cuckoo Hashing.  Journal of Algorithms\n *     51(2):122-144.\n *\n * Generalization of cuckoo hashing was discussed in:\n *\n *   Erlingsson, U., M. Manasse, F. McSherry (2006) A cool and practical\n *     alternative to traditional hash tables.  In Proceedings of the 7th\n *     Workshop on Distributed Data and Structures (WDAS'06), Santa Clara, CA,\n *     January 2006.\n *\n * This implementation uses precisely two hash functions because that is the\n * fewest that can work, and supporting multiple hashes is an implementation\n * burden.  Here is a reproduction of Figure 1 from Erlingsson et al. (2006)\n * that shows approximate expected maximum load factors for various\n * configurations:\n *\n *           |         #cells/bucket         |\n *   #hashes |   1   |   2   |   4   |   8   |\n *   --------+-------+-------+-------+-------+\n *         1 | 0.006 | 0.006 | 0.03  | 0.12  |\n *         2 | 0.49  | 0.86  |>0.93< |>0.96< |\n *         3 | 0.91  | 0.97  | 0.98  | 0.999 |\n *         4 | 0.97  | 0.99  | 0.999 |       |\n *\n * The number of cells per bucket is chosen such that a bucket fits in one cache\n * line.  So, on 32- and 64-bit systems, we use (8,2) and (4,2) cuckoo hashing,\n * respectively.\n *\n ******************************************************************************/\n#define\tJEMALLOC_CKH_C_\n#include \"jemalloc/internal/jemalloc_internal.h\"\n\n/******************************************************************************/\n/* Function prototypes for non-inline static functions. */\n\nstatic bool\tckh_grow(tsdn_t *tsdn, ckh_t *ckh);\nstatic void\tckh_shrink(tsdn_t *tsdn, ckh_t *ckh);\n\n/******************************************************************************/\n\n/*\n * Search bucket for key and return the cell number if found; SIZE_T_MAX\n * otherwise.\n */\nJEMALLOC_INLINE_C size_t\nckh_bucket_search(ckh_t *ckh, size_t bucket, const void *key)\n{\n\tckhc_t *cell;\n\tunsigned i;\n\n\tfor (i = 0; i < (ZU(1) << LG_CKH_BUCKET_CELLS); i++) {\n\t\tcell = &ckh->tab[(bucket << LG_CKH_BUCKET_CELLS) + i];\n\t\tif (cell->key != NULL && ckh->keycomp(key, cell->key))\n\t\t\treturn ((bucket << LG_CKH_BUCKET_CELLS) + i);\n\t}\n\n\treturn (SIZE_T_MAX);\n}\n\n/*\n * Search table for key and return cell number if found; SIZE_T_MAX otherwise.\n */\nJEMALLOC_INLINE_C size_t\nckh_isearch(ckh_t *ckh, const void *key)\n{\n\tsize_t hashes[2], bucket, cell;\n\n\tassert(ckh != NULL);\n\n\tckh->hash(key, hashes);\n\n\t/* Search primary bucket. */\n\tbucket = hashes[0] & ((ZU(1) << ckh->lg_curbuckets) - 1);\n\tcell = ckh_bucket_search(ckh, bucket, key);\n\tif (cell != SIZE_T_MAX)\n\t\treturn (cell);\n\n\t/* Search secondary bucket. */\n\tbucket = hashes[1] & ((ZU(1) << ckh->lg_curbuckets) - 1);\n\tcell = ckh_bucket_search(ckh, bucket, key);\n\treturn (cell);\n}\n\nJEMALLOC_INLINE_C bool\nckh_try_bucket_insert(ckh_t *ckh, size_t bucket, const void *key,\n    const void *data)\n{\n\tckhc_t *cell;\n\tunsigned offset, i;\n\n\t/*\n\t * Cycle through the cells in the bucket, starting at a random position.\n\t * The randomness avoids worst-case search overhead as buckets fill up.\n\t */\n\toffset = (unsigned)prng_lg_range(&ckh->prng_state, LG_CKH_BUCKET_CELLS);\n\tfor (i = 0; i < (ZU(1) << LG_CKH_BUCKET_CELLS); i++) {\n\t\tcell = &ckh->tab[(bucket << LG_CKH_BUCKET_CELLS) +\n\t\t    ((i + offset) & ((ZU(1) << LG_CKH_BUCKET_CELLS) - 1))];\n\t\tif (cell->key == NULL) {\n\t\t\tcell->key = key;\n\t\t\tcell->data = data;\n\t\t\tckh->count++;\n\t\t\treturn (false);\n\t\t}\n\t}\n\n\treturn (true);\n}\n\n/*\n * No space is available in bucket.  Randomly evict an item, then try to find an\n * alternate location for that item.  Iteratively repeat this\n * eviction/relocation procedure until either success or detection of an\n * eviction/relocation bucket cycle.\n */\nJEMALLOC_INLINE_C bool\nckh_evict_reloc_insert(ckh_t *ckh, size_t argbucket, void const **argkey,\n    void const **argdata)\n{\n\tconst void *key, *data, *tkey, *tdata;\n\tckhc_t *cell;\n\tsize_t hashes[2], bucket, tbucket;\n\tunsigned i;\n\n\tbucket = argbucket;\n\tkey = *argkey;\n\tdata = *argdata;\n\twhile (true) {\n\t\t/*\n\t\t * Choose a random item within the bucket to evict.  This is\n\t\t * critical to correct function, because without (eventually)\n\t\t * evicting all items within a bucket during iteration, it\n\t\t * would be possible to get stuck in an infinite loop if there\n\t\t * were an item for which both hashes indicated the same\n\t\t * bucket.\n\t\t */\n\t\ti = (unsigned)prng_lg_range(&ckh->prng_state,\n\t\t    LG_CKH_BUCKET_CELLS);\n\t\tcell = &ckh->tab[(bucket << LG_CKH_BUCKET_CELLS) + i];\n\t\tassert(cell->key != NULL);\n\n\t\t/* Swap cell->{key,data} and {key,data} (evict). */\n\t\ttkey = cell->key; tdata = cell->data;\n\t\tcell->key = key; cell->data = data;\n\t\tkey = tkey; data = tdata;\n\n#ifdef CKH_COUNT\n\t\tckh->nrelocs++;\n#endif\n\n\t\t/* Find the alternate bucket for the evicted item. */\n\t\tckh->hash(key, hashes);\n\t\ttbucket = hashes[1] & ((ZU(1) << ckh->lg_curbuckets) - 1);\n\t\tif (tbucket == bucket) {\n\t\t\ttbucket = hashes[0] & ((ZU(1) << ckh->lg_curbuckets)\n\t\t\t    - 1);\n\t\t\t/*\n\t\t\t * It may be that (tbucket == bucket) still, if the\n\t\t\t * item's hashes both indicate this bucket.  However,\n\t\t\t * we are guaranteed to eventually escape this bucket\n\t\t\t * during iteration, assuming pseudo-random item\n\t\t\t * selection (true randomness would make infinite\n\t\t\t * looping a remote possibility).  The reason we can\n\t\t\t * never get trapped forever is that there are two\n\t\t\t * cases:\n\t\t\t *\n\t\t\t * 1) This bucket == argbucket, so we will quickly\n\t\t\t *    detect an eviction cycle and terminate.\n\t\t\t * 2) An item was evicted to this bucket from another,\n\t\t\t *    which means that at least one item in this bucket\n\t\t\t *    has hashes that indicate distinct buckets.\n\t\t\t */\n\t\t}\n\t\t/* Check for a cycle. */\n\t\tif (tbucket == argbucket) {\n\t\t\t*argkey = key;\n\t\t\t*argdata = data;\n\t\t\treturn (true);\n\t\t}\n\n\t\tbucket = tbucket;\n\t\tif (!ckh_try_bucket_insert(ckh, bucket, key, data))\n\t\t\treturn (false);\n\t}\n}\n\nJEMALLOC_INLINE_C bool\nckh_try_insert(ckh_t *ckh, void const**argkey, void const**argdata)\n{\n\tsize_t hashes[2], bucket;\n\tconst void *key = *argkey;\n\tconst void *data = *argdata;\n\n\tckh->hash(key, hashes);\n\n\t/* Try to insert in primary bucket. */\n\tbucket = hashes[0] & ((ZU(1) << ckh->lg_curbuckets) - 1);\n\tif (!ckh_try_bucket_insert(ckh, bucket, key, data))\n\t\treturn (false);\n\n\t/* Try to insert in secondary bucket. */\n\tbucket = hashes[1] & ((ZU(1) << ckh->lg_curbuckets) - 1);\n\tif (!ckh_try_bucket_insert(ckh, bucket, key, data))\n\t\treturn (false);\n\n\t/*\n\t * Try to find a place for this item via iterative eviction/relocation.\n\t */\n\treturn (ckh_evict_reloc_insert(ckh, bucket, argkey, argdata));\n}\n\n/*\n * Try to rebuild the hash table from scratch by inserting all items from the\n * old table into the new.\n */\nJEMALLOC_INLINE_C bool\nckh_rebuild(ckh_t *ckh, ckhc_t *aTab)\n{\n\tsize_t count, i, nins;\n\tconst void *key, *data;\n\n\tcount = ckh->count;\n\tckh->count = 0;\n\tfor (i = nins = 0; nins < count; i++) {\n\t\tif (aTab[i].key != NULL) {\n\t\t\tkey = aTab[i].key;\n\t\t\tdata = aTab[i].data;\n\t\t\tif (ckh_try_insert(ckh, &key, &data)) {\n\t\t\t\tckh->count = count;\n\t\t\t\treturn (true);\n\t\t\t}\n\t\t\tnins++;\n\t\t}\n\t}\n\n\treturn (false);\n}\n\nstatic bool\nckh_grow(tsdn_t *tsdn, ckh_t *ckh)\n{\n\tbool ret;\n\tckhc_t *tab, *ttab;\n\tunsigned lg_prevbuckets, lg_curcells;\n\n#ifdef CKH_COUNT\n\tckh->ngrows++;\n#endif\n\n\t/*\n\t * It is possible (though unlikely, given well behaved hashes) that the\n\t * table will have to be doubled more than once in order to create a\n\t * usable table.\n\t */\n\tlg_prevbuckets = ckh->lg_curbuckets;\n\tlg_curcells = ckh->lg_curbuckets + LG_CKH_BUCKET_CELLS;\n\twhile (true) {\n\t\tsize_t usize;\n\n\t\tlg_curcells++;\n\t\tusize = sa2u(sizeof(ckhc_t) << lg_curcells, CACHELINE);\n\t\tif (unlikely(usize == 0 || usize > HUGE_MAXCLASS)) {\n\t\t\tret = true;\n\t\t\tgoto label_return;\n\t\t}\n\t\ttab = (ckhc_t *)ipallocztm(tsdn, usize, CACHELINE, true, NULL,\n\t\t    true, arena_ichoose(tsdn, NULL));\n\t\tif (tab == NULL) {\n\t\t\tret = true;\n\t\t\tgoto label_return;\n\t\t}\n\t\t/* Swap in new table. */\n\t\tttab = ckh->tab;\n\t\tckh->tab = tab;\n\t\ttab = ttab;\n\t\tckh->lg_curbuckets = lg_curcells - LG_CKH_BUCKET_CELLS;\n\n\t\tif (!ckh_rebuild(ckh, tab)) {\n\t\t\tidalloctm(tsdn, tab, NULL, true, true);\n\t\t\tbreak;\n\t\t}\n\n\t\t/* Rebuilding failed, so back out partially rebuilt table. */\n\t\tidalloctm(tsdn, ckh->tab, NULL, true, true);\n\t\tckh->tab = tab;\n\t\tckh->lg_curbuckets = lg_prevbuckets;\n\t}\n\n\tret = false;\nlabel_return:\n\treturn (ret);\n}\n\nstatic void\nckh_shrink(tsdn_t *tsdn, ckh_t *ckh)\n{\n\tckhc_t *tab, *ttab;\n\tsize_t usize;\n\tunsigned lg_prevbuckets, lg_curcells;\n\n\t/*\n\t * It is possible (though unlikely, given well behaved hashes) that the\n\t * table rebuild will fail.\n\t */\n\tlg_prevbuckets = ckh->lg_curbuckets;\n\tlg_curcells = ckh->lg_curbuckets + LG_CKH_BUCKET_CELLS - 1;\n\tusize = sa2u(sizeof(ckhc_t) << lg_curcells, CACHELINE);\n\tif (unlikely(usize == 0 || usize > HUGE_MAXCLASS))\n\t\treturn;\n\ttab = (ckhc_t *)ipallocztm(tsdn, usize, CACHELINE, true, NULL, true,\n\t    arena_ichoose(tsdn, NULL));\n\tif (tab == NULL) {\n\t\t/*\n\t\t * An OOM error isn't worth propagating, since it doesn't\n\t\t * prevent this or future operations from proceeding.\n\t\t */\n\t\treturn;\n\t}\n\t/* Swap in new table. */\n\tttab = ckh->tab;\n\tckh->tab = tab;\n\ttab = ttab;\n\tckh->lg_curbuckets = lg_curcells - LG_CKH_BUCKET_CELLS;\n\n\tif (!ckh_rebuild(ckh, tab)) {\n\t\tidalloctm(tsdn, tab, NULL, true, true);\n#ifdef CKH_COUNT\n\t\tckh->nshrinks++;\n#endif\n\t\treturn;\n\t}\n\n\t/* Rebuilding failed, so back out partially rebuilt table. */\n\tidalloctm(tsdn, ckh->tab, NULL, true, true);\n\tckh->tab = tab;\n\tckh->lg_curbuckets = lg_prevbuckets;\n#ifdef CKH_COUNT\n\tckh->nshrinkfails++;\n#endif\n}\n\nbool\nckh_new(tsdn_t *tsdn, ckh_t *ckh, size_t minitems, ckh_hash_t *hash,\n    ckh_keycomp_t *keycomp)\n{\n\tbool ret;\n\tsize_t mincells, usize;\n\tunsigned lg_mincells;\n\n\tassert(minitems > 0);\n\tassert(hash != NULL);\n\tassert(keycomp != NULL);\n\n#ifdef CKH_COUNT\n\tckh->ngrows = 0;\n\tckh->nshrinks = 0;\n\tckh->nshrinkfails = 0;\n\tckh->ninserts = 0;\n\tckh->nrelocs = 0;\n#endif\n\tckh->prng_state = 42; /* Value doesn't really matter. */\n\tckh->count = 0;\n\n\t/*\n\t * Find the minimum power of 2 that is large enough to fit minitems\n\t * entries.  We are using (2+,2) cuckoo hashing, which has an expected\n\t * maximum load factor of at least ~0.86, so 0.75 is a conservative load\n\t * factor that will typically allow mincells items to fit without ever\n\t * growing the table.\n\t */\n\tassert(LG_CKH_BUCKET_CELLS > 0);\n\tmincells = ((minitems + (3 - (minitems % 3))) / 3) << 2;\n\tfor (lg_mincells = LG_CKH_BUCKET_CELLS;\n\t    (ZU(1) << lg_mincells) < mincells;\n\t    lg_mincells++)\n\t\t; /* Do nothing. */\n\tckh->lg_minbuckets = lg_mincells - LG_CKH_BUCKET_CELLS;\n\tckh->lg_curbuckets = lg_mincells - LG_CKH_BUCKET_CELLS;\n\tckh->hash = hash;\n\tckh->keycomp = keycomp;\n\n\tusize = sa2u(sizeof(ckhc_t) << lg_mincells, CACHELINE);\n\tif (unlikely(usize == 0 || usize > HUGE_MAXCLASS)) {\n\t\tret = true;\n\t\tgoto label_return;\n\t}\n\tckh->tab = (ckhc_t *)ipallocztm(tsdn, usize, CACHELINE, true, NULL,\n\t    true, arena_ichoose(tsdn, NULL));\n\tif (ckh->tab == NULL) {\n\t\tret = true;\n\t\tgoto label_return;\n\t}\n\n\tret = false;\nlabel_return:\n\treturn (ret);\n}\n\nvoid\nckh_delete(tsdn_t *tsdn, ckh_t *ckh)\n{\n\n\tassert(ckh != NULL);\n\n#ifdef CKH_VERBOSE\n\tmalloc_printf(\n\t    \"%s(%p): ngrows: %\"FMTu64\", nshrinks: %\"FMTu64\",\"\n\t    \" nshrinkfails: %\"FMTu64\", ninserts: %\"FMTu64\",\"\n\t    \" nrelocs: %\"FMTu64\"\\n\", __func__, ckh,\n\t    (unsigned long long)ckh->ngrows,\n\t    (unsigned long long)ckh->nshrinks,\n\t    (unsigned long long)ckh->nshrinkfails,\n\t    (unsigned long long)ckh->ninserts,\n\t    (unsigned long long)ckh->nrelocs);\n#endif\n\n\tidalloctm(tsdn, ckh->tab, NULL, true, true);\n\tif (config_debug)\n\t\tmemset(ckh, JEMALLOC_FREE_JUNK, sizeof(ckh_t));\n}\n\nsize_t\nckh_count(ckh_t *ckh)\n{\n\n\tassert(ckh != NULL);\n\n\treturn (ckh->count);\n}\n\nbool\nckh_iter(ckh_t *ckh, size_t *tabind, void **key, void **data)\n{\n\tsize_t i, ncells;\n\n\tfor (i = *tabind, ncells = (ZU(1) << (ckh->lg_curbuckets +\n\t    LG_CKH_BUCKET_CELLS)); i < ncells; i++) {\n\t\tif (ckh->tab[i].key != NULL) {\n\t\t\tif (key != NULL)\n\t\t\t\t*key = (void *)ckh->tab[i].key;\n\t\t\tif (data != NULL)\n\t\t\t\t*data = (void *)ckh->tab[i].data;\n\t\t\t*tabind = i + 1;\n\t\t\treturn (false);\n\t\t}\n\t}\n\n\treturn (true);\n}\n\nbool\nckh_insert(tsdn_t *tsdn, ckh_t *ckh, const void *key, const void *data)\n{\n\tbool ret;\n\n\tassert(ckh != NULL);\n\tassert(ckh_search(ckh, key, NULL, NULL));\n\n#ifdef CKH_COUNT\n\tckh->ninserts++;\n#endif\n\n\twhile (ckh_try_insert(ckh, &key, &data)) {\n\t\tif (ckh_grow(tsdn, ckh)) {\n\t\t\tret = true;\n\t\t\tgoto label_return;\n\t\t}\n\t}\n\n\tret = false;\nlabel_return:\n\treturn (ret);\n}\n\nbool\nckh_remove(tsdn_t *tsdn, ckh_t *ckh, const void *searchkey, void **key,\n    void **data)\n{\n\tsize_t cell;\n\n\tassert(ckh != NULL);\n\n\tcell = ckh_isearch(ckh, searchkey);\n\tif (cell != SIZE_T_MAX) {\n\t\tif (key != NULL)\n\t\t\t*key = (void *)ckh->tab[cell].key;\n\t\tif (data != NULL)\n\t\t\t*data = (void *)ckh->tab[cell].data;\n\t\tckh->tab[cell].key = NULL;\n\t\tckh->tab[cell].data = NULL; /* Not necessary. */\n\n\t\tckh->count--;\n\t\t/* Try to halve the table if it is less than 1/4 full. */\n\t\tif (ckh->count < (ZU(1) << (ckh->lg_curbuckets\n\t\t    + LG_CKH_BUCKET_CELLS - 2)) && ckh->lg_curbuckets\n\t\t    > ckh->lg_minbuckets) {\n\t\t\t/* Ignore error due to OOM. */\n\t\t\tckh_shrink(tsdn, ckh);\n\t\t}\n\n\t\treturn (false);\n\t}\n\n\treturn (true);\n}\n\nbool\nckh_search(ckh_t *ckh, const void *searchkey, void **key, void **data)\n{\n\tsize_t cell;\n\n\tassert(ckh != NULL);\n\n\tcell = ckh_isearch(ckh, searchkey);\n\tif (cell != SIZE_T_MAX) {\n\t\tif (key != NULL)\n\t\t\t*key = (void *)ckh->tab[cell].key;\n\t\tif (data != NULL)\n\t\t\t*data = (void *)ckh->tab[cell].data;\n\t\treturn (false);\n\t}\n\n\treturn (true);\n}\n\nvoid\nckh_string_hash(const void *key, size_t r_hash[2])\n{\n\n\thash(key, strlen((const char *)key), 0x94122f33U, r_hash);\n}\n\nbool\nckh_string_keycomp(const void *k1, const void *k2)\n{\n\n    assert(k1 != NULL);\n    assert(k2 != NULL);\n\n    return (strcmp((char *)k1, (char *)k2) ? false : true);\n}\n\nvoid\nckh_pointer_hash(const void *key, size_t r_hash[2])\n{\n\tunion {\n\t\tconst void\t*v;\n\t\tsize_t\t\ti;\n\t} u;\n\n\tassert(sizeof(u.v) == sizeof(u.i));\n\tu.v = key;\n\thash(&u.i, sizeof(u.i), 0xd983396eU, r_hash);\n}\n\nbool\nckh_pointer_keycomp(const void *k1, const void *k2)\n{\n\n\treturn ((k1 == k2) ? true : false);\n}\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/deps/jemalloc/src/ctl.c",
    "content": "#define\tJEMALLOC_CTL_C_\n#include \"jemalloc/internal/jemalloc_internal.h\"\n\n/******************************************************************************/\n/* Data. */\n\n/*\n * ctl_mtx protects the following:\n * - ctl_stats.*\n */\nstatic malloc_mutex_t\tctl_mtx;\nstatic bool\t\tctl_initialized;\nstatic uint64_t\t\tctl_epoch;\nstatic ctl_stats_t\tctl_stats;\n\n/******************************************************************************/\n/* Helpers for named and indexed nodes. */\n\nJEMALLOC_INLINE_C const ctl_named_node_t *\nctl_named_node(const ctl_node_t *node)\n{\n\n\treturn ((node->named) ? (const ctl_named_node_t *)node : NULL);\n}\n\nJEMALLOC_INLINE_C const ctl_named_node_t *\nctl_named_children(const ctl_named_node_t *node, size_t index)\n{\n\tconst ctl_named_node_t *children = ctl_named_node(node->children);\n\n\treturn (children ? &children[index] : NULL);\n}\n\nJEMALLOC_INLINE_C const ctl_indexed_node_t *\nctl_indexed_node(const ctl_node_t *node)\n{\n\n\treturn (!node->named ? (const ctl_indexed_node_t *)node : NULL);\n}\n\n/******************************************************************************/\n/* Function prototypes for non-inline static functions. */\n\n#define\tCTL_PROTO(n)\t\t\t\t\t\t\t\\\nstatic int\tn##_ctl(tsd_t *tsd, const size_t *mib, size_t miblen,\t\\\n    void *oldp, size_t *oldlenp, void *newp, size_t newlen);\n\n#define\tINDEX_PROTO(n)\t\t\t\t\t\t\t\\\nstatic const ctl_named_node_t\t*n##_index(tsdn_t *tsdn,\t\t\\\n    const size_t *mib, size_t miblen, size_t i);\n\nstatic bool\tctl_arena_init(ctl_arena_stats_t *astats);\nstatic void\tctl_arena_clear(ctl_arena_stats_t *astats);\nstatic void\tctl_arena_stats_amerge(tsdn_t *tsdn, ctl_arena_stats_t *cstats,\n    arena_t *arena);\nstatic void\tctl_arena_stats_smerge(ctl_arena_stats_t *sstats,\n    ctl_arena_stats_t *astats);\nstatic void\tctl_arena_refresh(tsdn_t *tsdn, arena_t *arena, unsigned i);\nstatic bool\tctl_grow(tsdn_t *tsdn);\nstatic void\tctl_refresh(tsdn_t *tsdn);\nstatic bool\tctl_init(tsdn_t *tsdn);\nstatic int\tctl_lookup(tsdn_t *tsdn, const char *name,\n    ctl_node_t const **nodesp, size_t *mibp, size_t *depthp);\n\nCTL_PROTO(version)\nCTL_PROTO(epoch)\nCTL_PROTO(thread_tcache_enabled)\nCTL_PROTO(thread_tcache_flush)\nCTL_PROTO(thread_prof_name)\nCTL_PROTO(thread_prof_active)\nCTL_PROTO(thread_arena)\nCTL_PROTO(thread_allocated)\nCTL_PROTO(thread_allocatedp)\nCTL_PROTO(thread_deallocated)\nCTL_PROTO(thread_deallocatedp)\nCTL_PROTO(config_cache_oblivious)\nCTL_PROTO(config_debug)\nCTL_PROTO(config_fill)\nCTL_PROTO(config_lazy_lock)\nCTL_PROTO(config_malloc_conf)\nCTL_PROTO(config_munmap)\nCTL_PROTO(config_prof)\nCTL_PROTO(config_prof_libgcc)\nCTL_PROTO(config_prof_libunwind)\nCTL_PROTO(config_stats)\nCTL_PROTO(config_tcache)\nCTL_PROTO(config_tls)\nCTL_PROTO(config_utrace)\nCTL_PROTO(config_valgrind)\nCTL_PROTO(config_xmalloc)\nCTL_PROTO(opt_abort)\nCTL_PROTO(opt_dss)\nCTL_PROTO(opt_lg_chunk)\nCTL_PROTO(opt_narenas)\nCTL_PROTO(opt_purge)\nCTL_PROTO(opt_lg_dirty_mult)\nCTL_PROTO(opt_decay_time)\nCTL_PROTO(opt_stats_print)\nCTL_PROTO(opt_junk)\nCTL_PROTO(opt_zero)\nCTL_PROTO(opt_quarantine)\nCTL_PROTO(opt_redzone)\nCTL_PROTO(opt_utrace)\nCTL_PROTO(opt_xmalloc)\nCTL_PROTO(opt_tcache)\nCTL_PROTO(opt_lg_tcache_max)\nCTL_PROTO(opt_prof)\nCTL_PROTO(opt_prof_prefix)\nCTL_PROTO(opt_prof_active)\nCTL_PROTO(opt_prof_thread_active_init)\nCTL_PROTO(opt_lg_prof_sample)\nCTL_PROTO(opt_lg_prof_interval)\nCTL_PROTO(opt_prof_gdump)\nCTL_PROTO(opt_prof_final)\nCTL_PROTO(opt_prof_leak)\nCTL_PROTO(opt_prof_accum)\nCTL_PROTO(tcache_create)\nCTL_PROTO(tcache_flush)\nCTL_PROTO(tcache_destroy)\nstatic void\tarena_i_purge(tsdn_t *tsdn, unsigned arena_ind, bool all);\nCTL_PROTO(arena_i_purge)\nCTL_PROTO(arena_i_decay)\nCTL_PROTO(arena_i_reset)\nCTL_PROTO(arena_i_dss)\nCTL_PROTO(arena_i_lg_dirty_mult)\nCTL_PROTO(arena_i_decay_time)\nCTL_PROTO(arena_i_chunk_hooks)\nINDEX_PROTO(arena_i)\nCTL_PROTO(arenas_bin_i_size)\nCTL_PROTO(arenas_bin_i_nregs)\nCTL_PROTO(arenas_bin_i_run_size)\nINDEX_PROTO(arenas_bin_i)\nCTL_PROTO(arenas_lrun_i_size)\nINDEX_PROTO(arenas_lrun_i)\nCTL_PROTO(arenas_hchunk_i_size)\nINDEX_PROTO(arenas_hchunk_i)\nCTL_PROTO(arenas_narenas)\nCTL_PROTO(arenas_initialized)\nCTL_PROTO(arenas_lg_dirty_mult)\nCTL_PROTO(arenas_decay_time)\nCTL_PROTO(arenas_quantum)\nCTL_PROTO(arenas_page)\nCTL_PROTO(arenas_tcache_max)\nCTL_PROTO(arenas_nbins)\nCTL_PROTO(arenas_nhbins)\nCTL_PROTO(arenas_nlruns)\nCTL_PROTO(arenas_nhchunks)\nCTL_PROTO(arenas_extend)\nCTL_PROTO(prof_thread_active_init)\nCTL_PROTO(prof_active)\nCTL_PROTO(prof_dump)\nCTL_PROTO(prof_gdump)\nCTL_PROTO(prof_reset)\nCTL_PROTO(prof_interval)\nCTL_PROTO(lg_prof_sample)\nCTL_PROTO(stats_arenas_i_small_allocated)\nCTL_PROTO(stats_arenas_i_small_nmalloc)\nCTL_PROTO(stats_arenas_i_small_ndalloc)\nCTL_PROTO(stats_arenas_i_small_nrequests)\nCTL_PROTO(stats_arenas_i_large_allocated)\nCTL_PROTO(stats_arenas_i_large_nmalloc)\nCTL_PROTO(stats_arenas_i_large_ndalloc)\nCTL_PROTO(stats_arenas_i_large_nrequests)\nCTL_PROTO(stats_arenas_i_huge_allocated)\nCTL_PROTO(stats_arenas_i_huge_nmalloc)\nCTL_PROTO(stats_arenas_i_huge_ndalloc)\nCTL_PROTO(stats_arenas_i_huge_nrequests)\nCTL_PROTO(stats_arenas_i_bins_j_nmalloc)\nCTL_PROTO(stats_arenas_i_bins_j_ndalloc)\nCTL_PROTO(stats_arenas_i_bins_j_nrequests)\nCTL_PROTO(stats_arenas_i_bins_j_curregs)\nCTL_PROTO(stats_arenas_i_bins_j_nfills)\nCTL_PROTO(stats_arenas_i_bins_j_nflushes)\nCTL_PROTO(stats_arenas_i_bins_j_nruns)\nCTL_PROTO(stats_arenas_i_bins_j_nreruns)\nCTL_PROTO(stats_arenas_i_bins_j_curruns)\nINDEX_PROTO(stats_arenas_i_bins_j)\nCTL_PROTO(stats_arenas_i_lruns_j_nmalloc)\nCTL_PROTO(stats_arenas_i_lruns_j_ndalloc)\nCTL_PROTO(stats_arenas_i_lruns_j_nrequests)\nCTL_PROTO(stats_arenas_i_lruns_j_curruns)\nINDEX_PROTO(stats_arenas_i_lruns_j)\nCTL_PROTO(stats_arenas_i_hchunks_j_nmalloc)\nCTL_PROTO(stats_arenas_i_hchunks_j_ndalloc)\nCTL_PROTO(stats_arenas_i_hchunks_j_nrequests)\nCTL_PROTO(stats_arenas_i_hchunks_j_curhchunks)\nINDEX_PROTO(stats_arenas_i_hchunks_j)\nCTL_PROTO(stats_arenas_i_nthreads)\nCTL_PROTO(stats_arenas_i_dss)\nCTL_PROTO(stats_arenas_i_lg_dirty_mult)\nCTL_PROTO(stats_arenas_i_decay_time)\nCTL_PROTO(stats_arenas_i_pactive)\nCTL_PROTO(stats_arenas_i_pdirty)\nCTL_PROTO(stats_arenas_i_mapped)\nCTL_PROTO(stats_arenas_i_retained)\nCTL_PROTO(stats_arenas_i_npurge)\nCTL_PROTO(stats_arenas_i_nmadvise)\nCTL_PROTO(stats_arenas_i_purged)\nCTL_PROTO(stats_arenas_i_metadata_mapped)\nCTL_PROTO(stats_arenas_i_metadata_allocated)\nINDEX_PROTO(stats_arenas_i)\nCTL_PROTO(stats_cactive)\nCTL_PROTO(stats_allocated)\nCTL_PROTO(stats_active)\nCTL_PROTO(stats_metadata)\nCTL_PROTO(stats_resident)\nCTL_PROTO(stats_mapped)\nCTL_PROTO(stats_retained)\n\n/******************************************************************************/\n/* mallctl tree. */\n\n/* Maximum tree depth. */\n#define\tCTL_MAX_DEPTH\t6\n\n#define\tNAME(n)\t{true},\tn\n#define\tCHILD(t, c)\t\t\t\t\t\t\t\\\n\tsizeof(c##_node) / sizeof(ctl_##t##_node_t),\t\t\t\\\n\t(ctl_node_t *)c##_node,\t\t\t\t\t\t\\\n\tNULL\n#define\tCTL(c)\t0, NULL, c##_ctl\n\n/*\n * Only handles internal indexed nodes, since there are currently no external\n * ones.\n */\n#define\tINDEX(i)\t{false},\ti##_index\n\nstatic const ctl_named_node_t\tthread_tcache_node[] = {\n\t{NAME(\"enabled\"),\tCTL(thread_tcache_enabled)},\n\t{NAME(\"flush\"),\t\tCTL(thread_tcache_flush)}\n};\n\nstatic const ctl_named_node_t\tthread_prof_node[] = {\n\t{NAME(\"name\"),\t\tCTL(thread_prof_name)},\n\t{NAME(\"active\"),\tCTL(thread_prof_active)}\n};\n\nstatic const ctl_named_node_t\tthread_node[] = {\n\t{NAME(\"arena\"),\t\tCTL(thread_arena)},\n\t{NAME(\"allocated\"),\tCTL(thread_allocated)},\n\t{NAME(\"allocatedp\"),\tCTL(thread_allocatedp)},\n\t{NAME(\"deallocated\"),\tCTL(thread_deallocated)},\n\t{NAME(\"deallocatedp\"),\tCTL(thread_deallocatedp)},\n\t{NAME(\"tcache\"),\tCHILD(named, thread_tcache)},\n\t{NAME(\"prof\"),\t\tCHILD(named, thread_prof)}\n};\n\nstatic const ctl_named_node_t\tconfig_node[] = {\n\t{NAME(\"cache_oblivious\"), CTL(config_cache_oblivious)},\n\t{NAME(\"debug\"),\t\tCTL(config_debug)},\n\t{NAME(\"fill\"),\t\tCTL(config_fill)},\n\t{NAME(\"lazy_lock\"),\tCTL(config_lazy_lock)},\n\t{NAME(\"malloc_conf\"),\tCTL(config_malloc_conf)},\n\t{NAME(\"munmap\"),\tCTL(config_munmap)},\n\t{NAME(\"prof\"),\t\tCTL(config_prof)},\n\t{NAME(\"prof_libgcc\"),\tCTL(config_prof_libgcc)},\n\t{NAME(\"prof_libunwind\"), CTL(config_prof_libunwind)},\n\t{NAME(\"stats\"),\t\tCTL(config_stats)},\n\t{NAME(\"tcache\"),\tCTL(config_tcache)},\n\t{NAME(\"tls\"),\t\tCTL(config_tls)},\n\t{NAME(\"utrace\"),\tCTL(config_utrace)},\n\t{NAME(\"valgrind\"),\tCTL(config_valgrind)},\n\t{NAME(\"xmalloc\"),\tCTL(config_xmalloc)}\n};\n\nstatic const ctl_named_node_t opt_node[] = {\n\t{NAME(\"abort\"),\t\tCTL(opt_abort)},\n\t{NAME(\"dss\"),\t\tCTL(opt_dss)},\n\t{NAME(\"lg_chunk\"),\tCTL(opt_lg_chunk)},\n\t{NAME(\"narenas\"),\tCTL(opt_narenas)},\n\t{NAME(\"purge\"),\t\tCTL(opt_purge)},\n\t{NAME(\"lg_dirty_mult\"),\tCTL(opt_lg_dirty_mult)},\n\t{NAME(\"decay_time\"),\tCTL(opt_decay_time)},\n\t{NAME(\"stats_print\"),\tCTL(opt_stats_print)},\n\t{NAME(\"junk\"),\t\tCTL(opt_junk)},\n\t{NAME(\"zero\"),\t\tCTL(opt_zero)},\n\t{NAME(\"quarantine\"),\tCTL(opt_quarantine)},\n\t{NAME(\"redzone\"),\tCTL(opt_redzone)},\n\t{NAME(\"utrace\"),\tCTL(opt_utrace)},\n\t{NAME(\"xmalloc\"),\tCTL(opt_xmalloc)},\n\t{NAME(\"tcache\"),\tCTL(opt_tcache)},\n\t{NAME(\"lg_tcache_max\"),\tCTL(opt_lg_tcache_max)},\n\t{NAME(\"prof\"),\t\tCTL(opt_prof)},\n\t{NAME(\"prof_prefix\"),\tCTL(opt_prof_prefix)},\n\t{NAME(\"prof_active\"),\tCTL(opt_prof_active)},\n\t{NAME(\"prof_thread_active_init\"), CTL(opt_prof_thread_active_init)},\n\t{NAME(\"lg_prof_sample\"), CTL(opt_lg_prof_sample)},\n\t{NAME(\"lg_prof_interval\"), CTL(opt_lg_prof_interval)},\n\t{NAME(\"prof_gdump\"),\tCTL(opt_prof_gdump)},\n\t{NAME(\"prof_final\"),\tCTL(opt_prof_final)},\n\t{NAME(\"prof_leak\"),\tCTL(opt_prof_leak)},\n\t{NAME(\"prof_accum\"),\tCTL(opt_prof_accum)}\n};\n\nstatic const ctl_named_node_t\ttcache_node[] = {\n\t{NAME(\"create\"),\tCTL(tcache_create)},\n\t{NAME(\"flush\"),\t\tCTL(tcache_flush)},\n\t{NAME(\"destroy\"),\tCTL(tcache_destroy)}\n};\n\nstatic const ctl_named_node_t arena_i_node[] = {\n\t{NAME(\"purge\"),\t\tCTL(arena_i_purge)},\n\t{NAME(\"decay\"),\t\tCTL(arena_i_decay)},\n\t{NAME(\"reset\"),\t\tCTL(arena_i_reset)},\n\t{NAME(\"dss\"),\t\tCTL(arena_i_dss)},\n\t{NAME(\"lg_dirty_mult\"),\tCTL(arena_i_lg_dirty_mult)},\n\t{NAME(\"decay_time\"),\tCTL(arena_i_decay_time)},\n\t{NAME(\"chunk_hooks\"),\tCTL(arena_i_chunk_hooks)}\n};\nstatic const ctl_named_node_t super_arena_i_node[] = {\n\t{NAME(\"\"),\t\tCHILD(named, arena_i)}\n};\n\nstatic const ctl_indexed_node_t arena_node[] = {\n\t{INDEX(arena_i)}\n};\n\nstatic const ctl_named_node_t arenas_bin_i_node[] = {\n\t{NAME(\"size\"),\t\tCTL(arenas_bin_i_size)},\n\t{NAME(\"nregs\"),\t\tCTL(arenas_bin_i_nregs)},\n\t{NAME(\"run_size\"),\tCTL(arenas_bin_i_run_size)}\n};\nstatic const ctl_named_node_t super_arenas_bin_i_node[] = {\n\t{NAME(\"\"),\t\tCHILD(named, arenas_bin_i)}\n};\n\nstatic const ctl_indexed_node_t arenas_bin_node[] = {\n\t{INDEX(arenas_bin_i)}\n};\n\nstatic const ctl_named_node_t arenas_lrun_i_node[] = {\n\t{NAME(\"size\"),\t\tCTL(arenas_lrun_i_size)}\n};\nstatic const ctl_named_node_t super_arenas_lrun_i_node[] = {\n\t{NAME(\"\"),\t\tCHILD(named, arenas_lrun_i)}\n};\n\nstatic const ctl_indexed_node_t arenas_lrun_node[] = {\n\t{INDEX(arenas_lrun_i)}\n};\n\nstatic const ctl_named_node_t arenas_hchunk_i_node[] = {\n\t{NAME(\"size\"),\t\tCTL(arenas_hchunk_i_size)}\n};\nstatic const ctl_named_node_t super_arenas_hchunk_i_node[] = {\n\t{NAME(\"\"),\t\tCHILD(named, arenas_hchunk_i)}\n};\n\nstatic const ctl_indexed_node_t arenas_hchunk_node[] = {\n\t{INDEX(arenas_hchunk_i)}\n};\n\nstatic const ctl_named_node_t arenas_node[] = {\n\t{NAME(\"narenas\"),\tCTL(arenas_narenas)},\n\t{NAME(\"initialized\"),\tCTL(arenas_initialized)},\n\t{NAME(\"lg_dirty_mult\"),\tCTL(arenas_lg_dirty_mult)},\n\t{NAME(\"decay_time\"),\tCTL(arenas_decay_time)},\n\t{NAME(\"quantum\"),\tCTL(arenas_quantum)},\n\t{NAME(\"page\"),\t\tCTL(arenas_page)},\n\t{NAME(\"tcache_max\"),\tCTL(arenas_tcache_max)},\n\t{NAME(\"nbins\"),\t\tCTL(arenas_nbins)},\n\t{NAME(\"nhbins\"),\tCTL(arenas_nhbins)},\n\t{NAME(\"bin\"),\t\tCHILD(indexed, arenas_bin)},\n\t{NAME(\"nlruns\"),\tCTL(arenas_nlruns)},\n\t{NAME(\"lrun\"),\t\tCHILD(indexed, arenas_lrun)},\n\t{NAME(\"nhchunks\"),\tCTL(arenas_nhchunks)},\n\t{NAME(\"hchunk\"),\tCHILD(indexed, arenas_hchunk)},\n\t{NAME(\"extend\"),\tCTL(arenas_extend)}\n};\n\nstatic const ctl_named_node_t\tprof_node[] = {\n\t{NAME(\"thread_active_init\"), CTL(prof_thread_active_init)},\n\t{NAME(\"active\"),\tCTL(prof_active)},\n\t{NAME(\"dump\"),\t\tCTL(prof_dump)},\n\t{NAME(\"gdump\"),\t\tCTL(prof_gdump)},\n\t{NAME(\"reset\"),\t\tCTL(prof_reset)},\n\t{NAME(\"interval\"),\tCTL(prof_interval)},\n\t{NAME(\"lg_sample\"),\tCTL(lg_prof_sample)}\n};\n\nstatic const ctl_named_node_t stats_arenas_i_metadata_node[] = {\n\t{NAME(\"mapped\"),\tCTL(stats_arenas_i_metadata_mapped)},\n\t{NAME(\"allocated\"),\tCTL(stats_arenas_i_metadata_allocated)}\n};\n\nstatic const ctl_named_node_t stats_arenas_i_small_node[] = {\n\t{NAME(\"allocated\"),\tCTL(stats_arenas_i_small_allocated)},\n\t{NAME(\"nmalloc\"),\tCTL(stats_arenas_i_small_nmalloc)},\n\t{NAME(\"ndalloc\"),\tCTL(stats_arenas_i_small_ndalloc)},\n\t{NAME(\"nrequests\"),\tCTL(stats_arenas_i_small_nrequests)}\n};\n\nstatic const ctl_named_node_t stats_arenas_i_large_node[] = {\n\t{NAME(\"allocated\"),\tCTL(stats_arenas_i_large_allocated)},\n\t{NAME(\"nmalloc\"),\tCTL(stats_arenas_i_large_nmalloc)},\n\t{NAME(\"ndalloc\"),\tCTL(stats_arenas_i_large_ndalloc)},\n\t{NAME(\"nrequests\"),\tCTL(stats_arenas_i_large_nrequests)}\n};\n\nstatic const ctl_named_node_t stats_arenas_i_huge_node[] = {\n\t{NAME(\"allocated\"),\tCTL(stats_arenas_i_huge_allocated)},\n\t{NAME(\"nmalloc\"),\tCTL(stats_arenas_i_huge_nmalloc)},\n\t{NAME(\"ndalloc\"),\tCTL(stats_arenas_i_huge_ndalloc)},\n\t{NAME(\"nrequests\"),\tCTL(stats_arenas_i_huge_nrequests)}\n};\n\nstatic const ctl_named_node_t stats_arenas_i_bins_j_node[] = {\n\t{NAME(\"nmalloc\"),\tCTL(stats_arenas_i_bins_j_nmalloc)},\n\t{NAME(\"ndalloc\"),\tCTL(stats_arenas_i_bins_j_ndalloc)},\n\t{NAME(\"nrequests\"),\tCTL(stats_arenas_i_bins_j_nrequests)},\n\t{NAME(\"curregs\"),\tCTL(stats_arenas_i_bins_j_curregs)},\n\t{NAME(\"nfills\"),\tCTL(stats_arenas_i_bins_j_nfills)},\n\t{NAME(\"nflushes\"),\tCTL(stats_arenas_i_bins_j_nflushes)},\n\t{NAME(\"nruns\"),\t\tCTL(stats_arenas_i_bins_j_nruns)},\n\t{NAME(\"nreruns\"),\tCTL(stats_arenas_i_bins_j_nreruns)},\n\t{NAME(\"curruns\"),\tCTL(stats_arenas_i_bins_j_curruns)}\n};\nstatic const ctl_named_node_t super_stats_arenas_i_bins_j_node[] = {\n\t{NAME(\"\"),\t\tCHILD(named, stats_arenas_i_bins_j)}\n};\n\nstatic const ctl_indexed_node_t stats_arenas_i_bins_node[] = {\n\t{INDEX(stats_arenas_i_bins_j)}\n};\n\nstatic const ctl_named_node_t stats_arenas_i_lruns_j_node[] = {\n\t{NAME(\"nmalloc\"),\tCTL(stats_arenas_i_lruns_j_nmalloc)},\n\t{NAME(\"ndalloc\"),\tCTL(stats_arenas_i_lruns_j_ndalloc)},\n\t{NAME(\"nrequests\"),\tCTL(stats_arenas_i_lruns_j_nrequests)},\n\t{NAME(\"curruns\"),\tCTL(stats_arenas_i_lruns_j_curruns)}\n};\nstatic const ctl_named_node_t super_stats_arenas_i_lruns_j_node[] = {\n\t{NAME(\"\"),\t\tCHILD(named, stats_arenas_i_lruns_j)}\n};\n\nstatic const ctl_indexed_node_t stats_arenas_i_lruns_node[] = {\n\t{INDEX(stats_arenas_i_lruns_j)}\n};\n\nstatic const ctl_named_node_t stats_arenas_i_hchunks_j_node[] = {\n\t{NAME(\"nmalloc\"),\tCTL(stats_arenas_i_hchunks_j_nmalloc)},\n\t{NAME(\"ndalloc\"),\tCTL(stats_arenas_i_hchunks_j_ndalloc)},\n\t{NAME(\"nrequests\"),\tCTL(stats_arenas_i_hchunks_j_nrequests)},\n\t{NAME(\"curhchunks\"),\tCTL(stats_arenas_i_hchunks_j_curhchunks)}\n};\nstatic const ctl_named_node_t super_stats_arenas_i_hchunks_j_node[] = {\n\t{NAME(\"\"),\t\tCHILD(named, stats_arenas_i_hchunks_j)}\n};\n\nstatic const ctl_indexed_node_t stats_arenas_i_hchunks_node[] = {\n\t{INDEX(stats_arenas_i_hchunks_j)}\n};\n\nstatic const ctl_named_node_t stats_arenas_i_node[] = {\n\t{NAME(\"nthreads\"),\tCTL(stats_arenas_i_nthreads)},\n\t{NAME(\"dss\"),\t\tCTL(stats_arenas_i_dss)},\n\t{NAME(\"lg_dirty_mult\"),\tCTL(stats_arenas_i_lg_dirty_mult)},\n\t{NAME(\"decay_time\"),\tCTL(stats_arenas_i_decay_time)},\n\t{NAME(\"pactive\"),\tCTL(stats_arenas_i_pactive)},\n\t{NAME(\"pdirty\"),\tCTL(stats_arenas_i_pdirty)},\n\t{NAME(\"mapped\"),\tCTL(stats_arenas_i_mapped)},\n\t{NAME(\"retained\"),\tCTL(stats_arenas_i_retained)},\n\t{NAME(\"npurge\"),\tCTL(stats_arenas_i_npurge)},\n\t{NAME(\"nmadvise\"),\tCTL(stats_arenas_i_nmadvise)},\n\t{NAME(\"purged\"),\tCTL(stats_arenas_i_purged)},\n\t{NAME(\"metadata\"),\tCHILD(named, stats_arenas_i_metadata)},\n\t{NAME(\"small\"),\t\tCHILD(named, stats_arenas_i_small)},\n\t{NAME(\"large\"),\t\tCHILD(named, stats_arenas_i_large)},\n\t{NAME(\"huge\"),\t\tCHILD(named, stats_arenas_i_huge)},\n\t{NAME(\"bins\"),\t\tCHILD(indexed, stats_arenas_i_bins)},\n\t{NAME(\"lruns\"),\t\tCHILD(indexed, stats_arenas_i_lruns)},\n\t{NAME(\"hchunks\"),\tCHILD(indexed, stats_arenas_i_hchunks)}\n};\nstatic const ctl_named_node_t super_stats_arenas_i_node[] = {\n\t{NAME(\"\"),\t\tCHILD(named, stats_arenas_i)}\n};\n\nstatic const ctl_indexed_node_t stats_arenas_node[] = {\n\t{INDEX(stats_arenas_i)}\n};\n\nstatic const ctl_named_node_t stats_node[] = {\n\t{NAME(\"cactive\"),\tCTL(stats_cactive)},\n\t{NAME(\"allocated\"),\tCTL(stats_allocated)},\n\t{NAME(\"active\"),\tCTL(stats_active)},\n\t{NAME(\"metadata\"),\tCTL(stats_metadata)},\n\t{NAME(\"resident\"),\tCTL(stats_resident)},\n\t{NAME(\"mapped\"),\tCTL(stats_mapped)},\n\t{NAME(\"retained\"),\tCTL(stats_retained)},\n\t{NAME(\"arenas\"),\tCHILD(indexed, stats_arenas)}\n};\n\nstatic const ctl_named_node_t\troot_node[] = {\n\t{NAME(\"version\"),\tCTL(version)},\n\t{NAME(\"epoch\"),\t\tCTL(epoch)},\n\t{NAME(\"thread\"),\tCHILD(named, thread)},\n\t{NAME(\"config\"),\tCHILD(named, config)},\n\t{NAME(\"opt\"),\t\tCHILD(named, opt)},\n\t{NAME(\"tcache\"),\tCHILD(named, tcache)},\n\t{NAME(\"arena\"),\t\tCHILD(indexed, arena)},\n\t{NAME(\"arenas\"),\tCHILD(named, arenas)},\n\t{NAME(\"prof\"),\t\tCHILD(named, prof)},\n\t{NAME(\"stats\"),\t\tCHILD(named, stats)}\n};\nstatic const ctl_named_node_t super_root_node[] = {\n\t{NAME(\"\"),\t\tCHILD(named, root)}\n};\n\n#undef NAME\n#undef CHILD\n#undef CTL\n#undef INDEX\n\n/******************************************************************************/\n\nstatic bool\nctl_arena_init(ctl_arena_stats_t *astats)\n{\n\n\tif (astats->lstats == NULL) {\n\t\tastats->lstats = (malloc_large_stats_t *)a0malloc(nlclasses *\n\t\t    sizeof(malloc_large_stats_t));\n\t\tif (astats->lstats == NULL)\n\t\t\treturn (true);\n\t}\n\n\tif (astats->hstats == NULL) {\n\t\tastats->hstats = (malloc_huge_stats_t *)a0malloc(nhclasses *\n\t\t    sizeof(malloc_huge_stats_t));\n\t\tif (astats->hstats == NULL)\n\t\t\treturn (true);\n\t}\n\n\treturn (false);\n}\n\nstatic void\nctl_arena_clear(ctl_arena_stats_t *astats)\n{\n\n\tastats->nthreads = 0;\n\tastats->dss = dss_prec_names[dss_prec_limit];\n\tastats->lg_dirty_mult = -1;\n\tastats->decay_time = -1;\n\tastats->pactive = 0;\n\tastats->pdirty = 0;\n\tif (config_stats) {\n\t\tmemset(&astats->astats, 0, sizeof(arena_stats_t));\n\t\tastats->allocated_small = 0;\n\t\tastats->nmalloc_small = 0;\n\t\tastats->ndalloc_small = 0;\n\t\tastats->nrequests_small = 0;\n\t\tmemset(astats->bstats, 0, NBINS * sizeof(malloc_bin_stats_t));\n\t\tmemset(astats->lstats, 0, nlclasses *\n\t\t    sizeof(malloc_large_stats_t));\n\t\tmemset(astats->hstats, 0, nhclasses *\n\t\t    sizeof(malloc_huge_stats_t));\n\t}\n}\n\nstatic void\nctl_arena_stats_amerge(tsdn_t *tsdn, ctl_arena_stats_t *cstats, arena_t *arena)\n{\n\tunsigned i;\n\n\tif (config_stats) {\n\t\tarena_stats_merge(tsdn, arena, &cstats->nthreads, &cstats->dss,\n\t\t    &cstats->lg_dirty_mult, &cstats->decay_time,\n\t\t    &cstats->pactive, &cstats->pdirty, &cstats->astats,\n\t\t    cstats->bstats, cstats->lstats, cstats->hstats);\n\n\t\tfor (i = 0; i < NBINS; i++) {\n\t\t\tcstats->allocated_small += cstats->bstats[i].curregs *\n\t\t\t    index2size(i);\n\t\t\tcstats->nmalloc_small += cstats->bstats[i].nmalloc;\n\t\t\tcstats->ndalloc_small += cstats->bstats[i].ndalloc;\n\t\t\tcstats->nrequests_small += cstats->bstats[i].nrequests;\n\t\t}\n\t} else {\n\t\tarena_basic_stats_merge(tsdn, arena, &cstats->nthreads,\n\t\t    &cstats->dss, &cstats->lg_dirty_mult, &cstats->decay_time,\n\t\t    &cstats->pactive, &cstats->pdirty);\n\t}\n}\n\nstatic void\nctl_arena_stats_smerge(ctl_arena_stats_t *sstats, ctl_arena_stats_t *astats)\n{\n\tunsigned i;\n\n\tsstats->nthreads += astats->nthreads;\n\tsstats->pactive += astats->pactive;\n\tsstats->pdirty += astats->pdirty;\n\n\tif (config_stats) {\n\t\tsstats->astats.mapped += astats->astats.mapped;\n\t\tsstats->astats.retained += astats->astats.retained;\n\t\tsstats->astats.npurge += astats->astats.npurge;\n\t\tsstats->astats.nmadvise += astats->astats.nmadvise;\n\t\tsstats->astats.purged += astats->astats.purged;\n\n\t\tsstats->astats.metadata_mapped +=\n\t\t    astats->astats.metadata_mapped;\n\t\tsstats->astats.metadata_allocated +=\n\t\t    astats->astats.metadata_allocated;\n\n\t\tsstats->allocated_small += astats->allocated_small;\n\t\tsstats->nmalloc_small += astats->nmalloc_small;\n\t\tsstats->ndalloc_small += astats->ndalloc_small;\n\t\tsstats->nrequests_small += astats->nrequests_small;\n\n\t\tsstats->astats.allocated_large +=\n\t\t    astats->astats.allocated_large;\n\t\tsstats->astats.nmalloc_large += astats->astats.nmalloc_large;\n\t\tsstats->astats.ndalloc_large += astats->astats.ndalloc_large;\n\t\tsstats->astats.nrequests_large +=\n\t\t    astats->astats.nrequests_large;\n\n\t\tsstats->astats.allocated_huge += astats->astats.allocated_huge;\n\t\tsstats->astats.nmalloc_huge += astats->astats.nmalloc_huge;\n\t\tsstats->astats.ndalloc_huge += astats->astats.ndalloc_huge;\n\n\t\tfor (i = 0; i < NBINS; i++) {\n\t\t\tsstats->bstats[i].nmalloc += astats->bstats[i].nmalloc;\n\t\t\tsstats->bstats[i].ndalloc += astats->bstats[i].ndalloc;\n\t\t\tsstats->bstats[i].nrequests +=\n\t\t\t    astats->bstats[i].nrequests;\n\t\t\tsstats->bstats[i].curregs += astats->bstats[i].curregs;\n\t\t\tif (config_tcache) {\n\t\t\t\tsstats->bstats[i].nfills +=\n\t\t\t\t    astats->bstats[i].nfills;\n\t\t\t\tsstats->bstats[i].nflushes +=\n\t\t\t\t    astats->bstats[i].nflushes;\n\t\t\t}\n\t\t\tsstats->bstats[i].nruns += astats->bstats[i].nruns;\n\t\t\tsstats->bstats[i].reruns += astats->bstats[i].reruns;\n\t\t\tsstats->bstats[i].curruns += astats->bstats[i].curruns;\n\t\t}\n\n\t\tfor (i = 0; i < nlclasses; i++) {\n\t\t\tsstats->lstats[i].nmalloc += astats->lstats[i].nmalloc;\n\t\t\tsstats->lstats[i].ndalloc += astats->lstats[i].ndalloc;\n\t\t\tsstats->lstats[i].nrequests +=\n\t\t\t    astats->lstats[i].nrequests;\n\t\t\tsstats->lstats[i].curruns += astats->lstats[i].curruns;\n\t\t}\n\n\t\tfor (i = 0; i < nhclasses; i++) {\n\t\t\tsstats->hstats[i].nmalloc += astats->hstats[i].nmalloc;\n\t\t\tsstats->hstats[i].ndalloc += astats->hstats[i].ndalloc;\n\t\t\tsstats->hstats[i].curhchunks +=\n\t\t\t    astats->hstats[i].curhchunks;\n\t\t}\n\t}\n}\n\nstatic void\nctl_arena_refresh(tsdn_t *tsdn, arena_t *arena, unsigned i)\n{\n\tctl_arena_stats_t *astats = &ctl_stats.arenas[i];\n\tctl_arena_stats_t *sstats = &ctl_stats.arenas[ctl_stats.narenas];\n\n\tctl_arena_clear(astats);\n\tctl_arena_stats_amerge(tsdn, astats, arena);\n\t/* Merge into sum stats as well. */\n\tctl_arena_stats_smerge(sstats, astats);\n}\n\nstatic bool\nctl_grow(tsdn_t *tsdn)\n{\n\tctl_arena_stats_t *astats;\n\n\t/* Initialize new arena. */\n\tif (arena_init(tsdn, ctl_stats.narenas) == NULL)\n\t\treturn (true);\n\n\t/* Allocate extended arena stats. */\n\tastats = (ctl_arena_stats_t *)a0malloc((ctl_stats.narenas + 2) *\n\t    sizeof(ctl_arena_stats_t));\n\tif (astats == NULL)\n\t\treturn (true);\n\n\t/* Initialize the new astats element. */\n\tmemcpy(astats, ctl_stats.arenas, (ctl_stats.narenas + 1) *\n\t    sizeof(ctl_arena_stats_t));\n\tmemset(&astats[ctl_stats.narenas + 1], 0, sizeof(ctl_arena_stats_t));\n\tif (ctl_arena_init(&astats[ctl_stats.narenas + 1])) {\n\t\ta0dalloc(astats);\n\t\treturn (true);\n\t}\n\t/* Swap merged stats to their new location. */\n\t{\n\t\tctl_arena_stats_t tstats;\n\t\tmemcpy(&tstats, &astats[ctl_stats.narenas],\n\t\t    sizeof(ctl_arena_stats_t));\n\t\tmemcpy(&astats[ctl_stats.narenas],\n\t\t    &astats[ctl_stats.narenas + 1], sizeof(ctl_arena_stats_t));\n\t\tmemcpy(&astats[ctl_stats.narenas + 1], &tstats,\n\t\t    sizeof(ctl_arena_stats_t));\n\t}\n\ta0dalloc(ctl_stats.arenas);\n\tctl_stats.arenas = astats;\n\tctl_stats.narenas++;\n\n\treturn (false);\n}\n\nstatic void\nctl_refresh(tsdn_t *tsdn)\n{\n\tunsigned i;\n\tVARIABLE_ARRAY(arena_t *, tarenas, ctl_stats.narenas);\n\n\t/*\n\t * Clear sum stats, since they will be merged into by\n\t * ctl_arena_refresh().\n\t */\n\tctl_arena_clear(&ctl_stats.arenas[ctl_stats.narenas]);\n\n\tfor (i = 0; i < ctl_stats.narenas; i++)\n\t\ttarenas[i] = arena_get(tsdn, i, false);\n\n\tfor (i = 0; i < ctl_stats.narenas; i++) {\n\t\tbool initialized = (tarenas[i] != NULL);\n\n\t\tctl_stats.arenas[i].initialized = initialized;\n\t\tif (initialized)\n\t\t\tctl_arena_refresh(tsdn, tarenas[i], i);\n\t}\n\n\tif (config_stats) {\n\t\tsize_t base_allocated, base_resident, base_mapped;\n\t\tbase_stats_get(tsdn, &base_allocated, &base_resident,\n\t\t    &base_mapped);\n\t\tctl_stats.allocated =\n\t\t    ctl_stats.arenas[ctl_stats.narenas].allocated_small +\n\t\t    ctl_stats.arenas[ctl_stats.narenas].astats.allocated_large +\n\t\t    ctl_stats.arenas[ctl_stats.narenas].astats.allocated_huge;\n\t\tctl_stats.active =\n\t\t    (ctl_stats.arenas[ctl_stats.narenas].pactive << LG_PAGE);\n\t\tctl_stats.metadata = base_allocated +\n\t\t    ctl_stats.arenas[ctl_stats.narenas].astats.metadata_mapped +\n\t\t    ctl_stats.arenas[ctl_stats.narenas].astats\n\t\t    .metadata_allocated;\n\t\tctl_stats.resident = base_resident +\n\t\t    ctl_stats.arenas[ctl_stats.narenas].astats.metadata_mapped +\n\t\t    ((ctl_stats.arenas[ctl_stats.narenas].pactive +\n\t\t    ctl_stats.arenas[ctl_stats.narenas].pdirty) << LG_PAGE);\n\t\tctl_stats.mapped = base_mapped +\n\t\t    ctl_stats.arenas[ctl_stats.narenas].astats.mapped;\n\t\tctl_stats.retained =\n\t\t    ctl_stats.arenas[ctl_stats.narenas].astats.retained;\n\t}\n\n\tctl_epoch++;\n}\n\nstatic bool\nctl_init(tsdn_t *tsdn)\n{\n\tbool ret;\n\n\tmalloc_mutex_lock(tsdn, &ctl_mtx);\n\tif (!ctl_initialized) {\n\t\t/*\n\t\t * Allocate space for one extra arena stats element, which\n\t\t * contains summed stats across all arenas.\n\t\t */\n\t\tctl_stats.narenas = narenas_total_get();\n\t\tctl_stats.arenas = (ctl_arena_stats_t *)a0malloc(\n\t\t    (ctl_stats.narenas + 1) * sizeof(ctl_arena_stats_t));\n\t\tif (ctl_stats.arenas == NULL) {\n\t\t\tret = true;\n\t\t\tgoto label_return;\n\t\t}\n\t\tmemset(ctl_stats.arenas, 0, (ctl_stats.narenas + 1) *\n\t\t    sizeof(ctl_arena_stats_t));\n\n\t\t/*\n\t\t * Initialize all stats structures, regardless of whether they\n\t\t * ever get used.  Lazy initialization would allow errors to\n\t\t * cause inconsistent state to be viewable by the application.\n\t\t */\n\t\tif (config_stats) {\n\t\t\tunsigned i;\n\t\t\tfor (i = 0; i <= ctl_stats.narenas; i++) {\n\t\t\t\tif (ctl_arena_init(&ctl_stats.arenas[i])) {\n\t\t\t\t\tunsigned j;\n\t\t\t\t\tfor (j = 0; j < i; j++) {\n\t\t\t\t\t\ta0dalloc(\n\t\t\t\t\t\t    ctl_stats.arenas[j].lstats);\n\t\t\t\t\t\ta0dalloc(\n\t\t\t\t\t\t    ctl_stats.arenas[j].hstats);\n\t\t\t\t\t}\n\t\t\t\t\ta0dalloc(ctl_stats.arenas);\n\t\t\t\t\tctl_stats.arenas = NULL;\n\t\t\t\t\tret = true;\n\t\t\t\t\tgoto label_return;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tctl_stats.arenas[ctl_stats.narenas].initialized = true;\n\n\t\tctl_epoch = 0;\n\t\tctl_refresh(tsdn);\n\t\tctl_initialized = true;\n\t}\n\n\tret = false;\nlabel_return:\n\tmalloc_mutex_unlock(tsdn, &ctl_mtx);\n\treturn (ret);\n}\n\nstatic int\nctl_lookup(tsdn_t *tsdn, const char *name, ctl_node_t const **nodesp,\n    size_t *mibp, size_t *depthp)\n{\n\tint ret;\n\tconst char *elm, *tdot, *dot;\n\tsize_t elen, i, j;\n\tconst ctl_named_node_t *node;\n\n\telm = name;\n\t/* Equivalent to strchrnul(). */\n\tdot = ((tdot = strchr(elm, '.')) != NULL) ? tdot : strchr(elm, '\\0');\n\telen = (size_t)((uintptr_t)dot - (uintptr_t)elm);\n\tif (elen == 0) {\n\t\tret = ENOENT;\n\t\tgoto label_return;\n\t}\n\tnode = super_root_node;\n\tfor (i = 0; i < *depthp; i++) {\n\t\tassert(node);\n\t\tassert(node->nchildren > 0);\n\t\tif (ctl_named_node(node->children) != NULL) {\n\t\t\tconst ctl_named_node_t *pnode = node;\n\n\t\t\t/* Children are named. */\n\t\t\tfor (j = 0; j < node->nchildren; j++) {\n\t\t\t\tconst ctl_named_node_t *child =\n\t\t\t\t    ctl_named_children(node, j);\n\t\t\t\tif (strlen(child->name) == elen &&\n\t\t\t\t    strncmp(elm, child->name, elen) == 0) {\n\t\t\t\t\tnode = child;\n\t\t\t\t\tif (nodesp != NULL)\n\t\t\t\t\t\tnodesp[i] =\n\t\t\t\t\t\t    (const ctl_node_t *)node;\n\t\t\t\t\tmibp[i] = j;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (node == pnode) {\n\t\t\t\tret = ENOENT;\n\t\t\t\tgoto label_return;\n\t\t\t}\n\t\t} else {\n\t\t\tuintmax_t index;\n\t\t\tconst ctl_indexed_node_t *inode;\n\n\t\t\t/* Children are indexed. */\n\t\t\tindex = malloc_strtoumax(elm, NULL, 10);\n\t\t\tif (index == UINTMAX_MAX || index > SIZE_T_MAX) {\n\t\t\t\tret = ENOENT;\n\t\t\t\tgoto label_return;\n\t\t\t}\n\n\t\t\tinode = ctl_indexed_node(node->children);\n\t\t\tnode = inode->index(tsdn, mibp, *depthp, (size_t)index);\n\t\t\tif (node == NULL) {\n\t\t\t\tret = ENOENT;\n\t\t\t\tgoto label_return;\n\t\t\t}\n\n\t\t\tif (nodesp != NULL)\n\t\t\t\tnodesp[i] = (const ctl_node_t *)node;\n\t\t\tmibp[i] = (size_t)index;\n\t\t}\n\n\t\tif (node->ctl != NULL) {\n\t\t\t/* Terminal node. */\n\t\t\tif (*dot != '\\0') {\n\t\t\t\t/*\n\t\t\t\t * The name contains more elements than are\n\t\t\t\t * in this path through the tree.\n\t\t\t\t */\n\t\t\t\tret = ENOENT;\n\t\t\t\tgoto label_return;\n\t\t\t}\n\t\t\t/* Complete lookup successful. */\n\t\t\t*depthp = i + 1;\n\t\t\tbreak;\n\t\t}\n\n\t\t/* Update elm. */\n\t\tif (*dot == '\\0') {\n\t\t\t/* No more elements. */\n\t\t\tret = ENOENT;\n\t\t\tgoto label_return;\n\t\t}\n\t\telm = &dot[1];\n\t\tdot = ((tdot = strchr(elm, '.')) != NULL) ? tdot :\n\t\t    strchr(elm, '\\0');\n\t\telen = (size_t)((uintptr_t)dot - (uintptr_t)elm);\n\t}\n\n\tret = 0;\nlabel_return:\n\treturn (ret);\n}\n\nint\nctl_byname(tsd_t *tsd, const char *name, void *oldp, size_t *oldlenp,\n    void *newp, size_t newlen)\n{\n\tint ret;\n\tsize_t depth;\n\tctl_node_t const *nodes[CTL_MAX_DEPTH];\n\tsize_t mib[CTL_MAX_DEPTH];\n\tconst ctl_named_node_t *node;\n\n\tif (!ctl_initialized && ctl_init(tsd_tsdn(tsd))) {\n\t\tret = EAGAIN;\n\t\tgoto label_return;\n\t}\n\n\tdepth = CTL_MAX_DEPTH;\n\tret = ctl_lookup(tsd_tsdn(tsd), name, nodes, mib, &depth);\n\tif (ret != 0)\n\t\tgoto label_return;\n\n\tnode = ctl_named_node(nodes[depth-1]);\n\tif (node != NULL && node->ctl)\n\t\tret = node->ctl(tsd, mib, depth, oldp, oldlenp, newp, newlen);\n\telse {\n\t\t/* The name refers to a partial path through the ctl tree. */\n\t\tret = ENOENT;\n\t}\n\nlabel_return:\n\treturn(ret);\n}\n\nint\nctl_nametomib(tsdn_t *tsdn, const char *name, size_t *mibp, size_t *miblenp)\n{\n\tint ret;\n\n\tif (!ctl_initialized && ctl_init(tsdn)) {\n\t\tret = EAGAIN;\n\t\tgoto label_return;\n\t}\n\n\tret = ctl_lookup(tsdn, name, NULL, mibp, miblenp);\nlabel_return:\n\treturn(ret);\n}\n\nint\nctl_bymib(tsd_t *tsd, const size_t *mib, size_t miblen, void *oldp,\n    size_t *oldlenp, void *newp, size_t newlen)\n{\n\tint ret;\n\tconst ctl_named_node_t *node;\n\tsize_t i;\n\n\tif (!ctl_initialized && ctl_init(tsd_tsdn(tsd))) {\n\t\tret = EAGAIN;\n\t\tgoto label_return;\n\t}\n\n\t/* Iterate down the tree. */\n\tnode = super_root_node;\n\tfor (i = 0; i < miblen; i++) {\n\t\tassert(node);\n\t\tassert(node->nchildren > 0);\n\t\tif (ctl_named_node(node->children) != NULL) {\n\t\t\t/* Children are named. */\n\t\t\tif (node->nchildren <= (unsigned)mib[i]) {\n\t\t\t\tret = ENOENT;\n\t\t\t\tgoto label_return;\n\t\t\t}\n\t\t\tnode = ctl_named_children(node, mib[i]);\n\t\t} else {\n\t\t\tconst ctl_indexed_node_t *inode;\n\n\t\t\t/* Indexed element. */\n\t\t\tinode = ctl_indexed_node(node->children);\n\t\t\tnode = inode->index(tsd_tsdn(tsd), mib, miblen, mib[i]);\n\t\t\tif (node == NULL) {\n\t\t\t\tret = ENOENT;\n\t\t\t\tgoto label_return;\n\t\t\t}\n\t\t}\n\t}\n\n\t/* Call the ctl function. */\n\tif (node && node->ctl)\n\t\tret = node->ctl(tsd, mib, miblen, oldp, oldlenp, newp, newlen);\n\telse {\n\t\t/* Partial MIB. */\n\t\tret = ENOENT;\n\t}\n\nlabel_return:\n\treturn(ret);\n}\n\nbool\nctl_boot(void)\n{\n\n\tif (malloc_mutex_init(&ctl_mtx, \"ctl\", WITNESS_RANK_CTL))\n\t\treturn (true);\n\n\tctl_initialized = false;\n\n\treturn (false);\n}\n\nvoid\nctl_prefork(tsdn_t *tsdn)\n{\n\n\tmalloc_mutex_prefork(tsdn, &ctl_mtx);\n}\n\nvoid\nctl_postfork_parent(tsdn_t *tsdn)\n{\n\n\tmalloc_mutex_postfork_parent(tsdn, &ctl_mtx);\n}\n\nvoid\nctl_postfork_child(tsdn_t *tsdn)\n{\n\n\tmalloc_mutex_postfork_child(tsdn, &ctl_mtx);\n}\n\n/******************************************************************************/\n/* *_ctl() functions. */\n\n#define\tREADONLY()\tdo {\t\t\t\t\t\t\\\n\tif (newp != NULL || newlen != 0) {\t\t\t\t\\\n\t\tret = EPERM;\t\t\t\t\t\t\\\n\t\tgoto label_return;\t\t\t\t\t\\\n\t}\t\t\t\t\t\t\t\t\\\n} while (0)\n\n#define\tWRITEONLY()\tdo {\t\t\t\t\t\t\\\n\tif (oldp != NULL || oldlenp != NULL) {\t\t\t\t\\\n\t\tret = EPERM;\t\t\t\t\t\t\\\n\t\tgoto label_return;\t\t\t\t\t\\\n\t}\t\t\t\t\t\t\t\t\\\n} while (0)\n\n#define\tREAD_XOR_WRITE()\tdo {\t\t\t\t\t\\\n\tif ((oldp != NULL && oldlenp != NULL) && (newp != NULL ||\t\\\n\t    newlen != 0)) {\t\t\t\t\t\t\\\n\t\tret = EPERM;\t\t\t\t\t\t\\\n\t\tgoto label_return;\t\t\t\t\t\\\n\t}\t\t\t\t\t\t\t\t\\\n} while (0)\n\n#define\tREAD(v, t)\tdo {\t\t\t\t\t\t\\\n\tif (oldp != NULL && oldlenp != NULL) {\t\t\t\t\\\n\t\tif (*oldlenp != sizeof(t)) {\t\t\t\t\\\n\t\t\tsize_t\tcopylen = (sizeof(t) <= *oldlenp)\t\\\n\t\t\t    ? sizeof(t) : *oldlenp;\t\t\t\\\n\t\t\tmemcpy(oldp, (void *)&(v), copylen);\t\t\\\n\t\t\tret = EINVAL;\t\t\t\t\t\\\n\t\t\tgoto label_return;\t\t\t\t\\\n\t\t}\t\t\t\t\t\t\t\\\n\t\t*(t *)oldp = (v);\t\t\t\t\t\\\n\t}\t\t\t\t\t\t\t\t\\\n} while (0)\n\n#define\tWRITE(v, t)\tdo {\t\t\t\t\t\t\\\n\tif (newp != NULL) {\t\t\t\t\t\t\\\n\t\tif (newlen != sizeof(t)) {\t\t\t\t\\\n\t\t\tret = EINVAL;\t\t\t\t\t\\\n\t\t\tgoto label_return;\t\t\t\t\\\n\t\t}\t\t\t\t\t\t\t\\\n\t\t(v) = *(t *)newp;\t\t\t\t\t\\\n\t}\t\t\t\t\t\t\t\t\\\n} while (0)\n\n/*\n * There's a lot of code duplication in the following macros due to limitations\n * in how nested cpp macros are expanded.\n */\n#define\tCTL_RO_CLGEN(c, l, n, v, t)\t\t\t\t\t\\\nstatic int\t\t\t\t\t\t\t\t\\\nn##_ctl(tsd_t *tsd, const size_t *mib, size_t miblen, void *oldp,\t\\\n    size_t *oldlenp, void *newp, size_t newlen)\t\t\t\t\\\n{\t\t\t\t\t\t\t\t\t\\\n\tint ret;\t\t\t\t\t\t\t\\\n\tt oldval;\t\t\t\t\t\t\t\\\n\t\t\t\t\t\t\t\t\t\\\n\tif (!(c))\t\t\t\t\t\t\t\\\n\t\treturn (ENOENT);\t\t\t\t\t\\\n\tif (l)\t\t\t\t\t\t\t\t\\\n\t\tmalloc_mutex_lock(tsd_tsdn(tsd), &ctl_mtx);\t\t\\\n\tREADONLY();\t\t\t\t\t\t\t\\\n\toldval = (v);\t\t\t\t\t\t\t\\\n\tREAD(oldval, t);\t\t\t\t\t\t\\\n\t\t\t\t\t\t\t\t\t\\\n\tret = 0;\t\t\t\t\t\t\t\\\nlabel_return:\t\t\t\t\t\t\t\t\\\n\tif (l)\t\t\t\t\t\t\t\t\\\n\t\tmalloc_mutex_unlock(tsd_tsdn(tsd), &ctl_mtx);\t\t\\\n\treturn (ret);\t\t\t\t\t\t\t\\\n}\n\n#define\tCTL_RO_CGEN(c, n, v, t)\t\t\t\t\t\t\\\nstatic int\t\t\t\t\t\t\t\t\\\nn##_ctl(tsd_t *tsd, const size_t *mib, size_t miblen, void *oldp,\t\\\n    size_t *oldlenp, void *newp, size_t newlen)\t\t\t\t\\\n{\t\t\t\t\t\t\t\t\t\\\n\tint ret;\t\t\t\t\t\t\t\\\n\tt oldval;\t\t\t\t\t\t\t\\\n\t\t\t\t\t\t\t\t\t\\\n\tif (!(c))\t\t\t\t\t\t\t\\\n\t\treturn (ENOENT);\t\t\t\t\t\\\n\tmalloc_mutex_lock(tsd_tsdn(tsd), &ctl_mtx);\t\t\t\\\n\tREADONLY();\t\t\t\t\t\t\t\\\n\toldval = (v);\t\t\t\t\t\t\t\\\n\tREAD(oldval, t);\t\t\t\t\t\t\\\n\t\t\t\t\t\t\t\t\t\\\n\tret = 0;\t\t\t\t\t\t\t\\\nlabel_return:\t\t\t\t\t\t\t\t\\\n\tmalloc_mutex_unlock(tsd_tsdn(tsd), &ctl_mtx);\t\t\t\\\n\treturn (ret);\t\t\t\t\t\t\t\\\n}\n\n#define\tCTL_RO_GEN(n, v, t)\t\t\t\t\t\t\\\nstatic int\t\t\t\t\t\t\t\t\\\nn##_ctl(tsd_t *tsd, const size_t *mib, size_t miblen, void *oldp,\t\\\n    size_t *oldlenp, void *newp, size_t newlen)\t\t\t\t\\\n{\t\t\t\t\t\t\t\t\t\\\n\tint ret;\t\t\t\t\t\t\t\\\n\tt oldval;\t\t\t\t\t\t\t\\\n\t\t\t\t\t\t\t\t\t\\\n\tmalloc_mutex_lock(tsd_tsdn(tsd), &ctl_mtx);\t\t\t\\\n\tREADONLY();\t\t\t\t\t\t\t\\\n\toldval = (v);\t\t\t\t\t\t\t\\\n\tREAD(oldval, t);\t\t\t\t\t\t\\\n\t\t\t\t\t\t\t\t\t\\\n\tret = 0;\t\t\t\t\t\t\t\\\nlabel_return:\t\t\t\t\t\t\t\t\\\n\tmalloc_mutex_unlock(tsd_tsdn(tsd), &ctl_mtx);\t\t\t\\\n\treturn (ret);\t\t\t\t\t\t\t\\\n}\n\n/*\n * ctl_mtx is not acquired, under the assumption that no pertinent data will\n * mutate during the call.\n */\n#define\tCTL_RO_NL_CGEN(c, n, v, t)\t\t\t\t\t\\\nstatic int\t\t\t\t\t\t\t\t\\\nn##_ctl(tsd_t *tsd, const size_t *mib, size_t miblen, void *oldp,\t\\\n    size_t *oldlenp, void *newp, size_t newlen)\t\t\t\t\\\n{\t\t\t\t\t\t\t\t\t\\\n\tint ret;\t\t\t\t\t\t\t\\\n\tt oldval;\t\t\t\t\t\t\t\\\n\t\t\t\t\t\t\t\t\t\\\n\tif (!(c))\t\t\t\t\t\t\t\\\n\t\treturn (ENOENT);\t\t\t\t\t\\\n\tREADONLY();\t\t\t\t\t\t\t\\\n\toldval = (v);\t\t\t\t\t\t\t\\\n\tREAD(oldval, t);\t\t\t\t\t\t\\\n\t\t\t\t\t\t\t\t\t\\\n\tret = 0;\t\t\t\t\t\t\t\\\nlabel_return:\t\t\t\t\t\t\t\t\\\n\treturn (ret);\t\t\t\t\t\t\t\\\n}\n\n#define\tCTL_RO_NL_GEN(n, v, t)\t\t\t\t\t\t\\\nstatic int\t\t\t\t\t\t\t\t\\\nn##_ctl(tsd_t *tsd, const size_t *mib, size_t miblen, void *oldp,\t\\\n    size_t *oldlenp, void *newp, size_t newlen)\t\t\t\t\\\n{\t\t\t\t\t\t\t\t\t\\\n\tint ret;\t\t\t\t\t\t\t\\\n\tt oldval;\t\t\t\t\t\t\t\\\n\t\t\t\t\t\t\t\t\t\\\n\tREADONLY();\t\t\t\t\t\t\t\\\n\toldval = (v);\t\t\t\t\t\t\t\\\n\tREAD(oldval, t);\t\t\t\t\t\t\\\n\t\t\t\t\t\t\t\t\t\\\n\tret = 0;\t\t\t\t\t\t\t\\\nlabel_return:\t\t\t\t\t\t\t\t\\\n\treturn (ret);\t\t\t\t\t\t\t\\\n}\n\n#define\tCTL_TSD_RO_NL_CGEN(c, n, m, t)\t\t\t\t\t\\\nstatic int\t\t\t\t\t\t\t\t\\\nn##_ctl(tsd_t *tsd, const size_t *mib, size_t miblen, void *oldp,\t\\\n    size_t *oldlenp, void *newp, size_t newlen)\t\t\t\t\\\n{\t\t\t\t\t\t\t\t\t\\\n\tint ret;\t\t\t\t\t\t\t\\\n\tt oldval;\t\t\t\t\t\t\t\\\n\t\t\t\t\t\t\t\t\t\\\n\tif (!(c))\t\t\t\t\t\t\t\\\n\t\treturn (ENOENT);\t\t\t\t\t\\\n\tREADONLY();\t\t\t\t\t\t\t\\\n\toldval = (m(tsd));\t\t\t\t\t\t\\\n\tREAD(oldval, t);\t\t\t\t\t\t\\\n\t\t\t\t\t\t\t\t\t\\\n\tret = 0;\t\t\t\t\t\t\t\\\nlabel_return:\t\t\t\t\t\t\t\t\\\n\treturn (ret);\t\t\t\t\t\t\t\\\n}\n\n#define\tCTL_RO_CONFIG_GEN(n, t)\t\t\t\t\t\t\\\nstatic int\t\t\t\t\t\t\t\t\\\nn##_ctl(tsd_t *tsd, const size_t *mib, size_t miblen, void *oldp,\t\\\n    size_t *oldlenp, void *newp, size_t newlen)\t\t\t\t\\\n{\t\t\t\t\t\t\t\t\t\\\n\tint ret;\t\t\t\t\t\t\t\\\n\tt oldval;\t\t\t\t\t\t\t\\\n\t\t\t\t\t\t\t\t\t\\\n\tREADONLY();\t\t\t\t\t\t\t\\\n\toldval = n;\t\t\t\t\t\t\t\\\n\tREAD(oldval, t);\t\t\t\t\t\t\\\n\t\t\t\t\t\t\t\t\t\\\n\tret = 0;\t\t\t\t\t\t\t\\\nlabel_return:\t\t\t\t\t\t\t\t\\\n\treturn (ret);\t\t\t\t\t\t\t\\\n}\n\n/******************************************************************************/\n\nCTL_RO_NL_GEN(version, JEMALLOC_VERSION, const char *)\n\nstatic int\nepoch_ctl(tsd_t *tsd, const size_t *mib, size_t miblen, void *oldp,\n    size_t *oldlenp, void *newp, size_t newlen)\n{\n\tint ret;\n\tUNUSED uint64_t newval;\n\n\tmalloc_mutex_lock(tsd_tsdn(tsd), &ctl_mtx);\n\tWRITE(newval, uint64_t);\n\tif (newp != NULL)\n\t\tctl_refresh(tsd_tsdn(tsd));\n\tREAD(ctl_epoch, uint64_t);\n\n\tret = 0;\nlabel_return:\n\tmalloc_mutex_unlock(tsd_tsdn(tsd), &ctl_mtx);\n\treturn (ret);\n}\n\n/******************************************************************************/\n\nCTL_RO_CONFIG_GEN(config_cache_oblivious, bool)\nCTL_RO_CONFIG_GEN(config_debug, bool)\nCTL_RO_CONFIG_GEN(config_fill, bool)\nCTL_RO_CONFIG_GEN(config_lazy_lock, bool)\nCTL_RO_CONFIG_GEN(config_malloc_conf, const char *)\nCTL_RO_CONFIG_GEN(config_munmap, bool)\nCTL_RO_CONFIG_GEN(config_prof, bool)\nCTL_RO_CONFIG_GEN(config_prof_libgcc, bool)\nCTL_RO_CONFIG_GEN(config_prof_libunwind, bool)\nCTL_RO_CONFIG_GEN(config_stats, bool)\nCTL_RO_CONFIG_GEN(config_tcache, bool)\nCTL_RO_CONFIG_GEN(config_tls, bool)\nCTL_RO_CONFIG_GEN(config_utrace, bool)\nCTL_RO_CONFIG_GEN(config_valgrind, bool)\nCTL_RO_CONFIG_GEN(config_xmalloc, bool)\n\n/******************************************************************************/\n\nCTL_RO_NL_GEN(opt_abort, opt_abort, bool)\nCTL_RO_NL_GEN(opt_dss, opt_dss, const char *)\nCTL_RO_NL_GEN(opt_lg_chunk, opt_lg_chunk, size_t)\nCTL_RO_NL_GEN(opt_narenas, opt_narenas, unsigned)\nCTL_RO_NL_GEN(opt_purge, purge_mode_names[opt_purge], const char *)\nCTL_RO_NL_GEN(opt_lg_dirty_mult, opt_lg_dirty_mult, ssize_t)\nCTL_RO_NL_GEN(opt_decay_time, opt_decay_time, ssize_t)\nCTL_RO_NL_GEN(opt_stats_print, opt_stats_print, bool)\nCTL_RO_NL_CGEN(config_fill, opt_junk, opt_junk, const char *)\nCTL_RO_NL_CGEN(config_fill, opt_quarantine, opt_quarantine, size_t)\nCTL_RO_NL_CGEN(config_fill, opt_redzone, opt_redzone, bool)\nCTL_RO_NL_CGEN(config_fill, opt_zero, opt_zero, bool)\nCTL_RO_NL_CGEN(config_utrace, opt_utrace, opt_utrace, bool)\nCTL_RO_NL_CGEN(config_xmalloc, opt_xmalloc, opt_xmalloc, bool)\nCTL_RO_NL_CGEN(config_tcache, opt_tcache, opt_tcache, bool)\nCTL_RO_NL_CGEN(config_tcache, opt_lg_tcache_max, opt_lg_tcache_max, ssize_t)\nCTL_RO_NL_CGEN(config_prof, opt_prof, opt_prof, bool)\nCTL_RO_NL_CGEN(config_prof, opt_prof_prefix, opt_prof_prefix, const char *)\nCTL_RO_NL_CGEN(config_prof, opt_prof_active, opt_prof_active, bool)\nCTL_RO_NL_CGEN(config_prof, opt_prof_thread_active_init,\n    opt_prof_thread_active_init, bool)\nCTL_RO_NL_CGEN(config_prof, opt_lg_prof_sample, opt_lg_prof_sample, size_t)\nCTL_RO_NL_CGEN(config_prof, opt_prof_accum, opt_prof_accum, bool)\nCTL_RO_NL_CGEN(config_prof, opt_lg_prof_interval, opt_lg_prof_interval, ssize_t)\nCTL_RO_NL_CGEN(config_prof, opt_prof_gdump, opt_prof_gdump, bool)\nCTL_RO_NL_CGEN(config_prof, opt_prof_final, opt_prof_final, bool)\nCTL_RO_NL_CGEN(config_prof, opt_prof_leak, opt_prof_leak, bool)\n\n/******************************************************************************/\n\nstatic int\nthread_arena_ctl(tsd_t *tsd, const size_t *mib, size_t miblen, void *oldp,\n    size_t *oldlenp, void *newp, size_t newlen)\n{\n\tint ret;\n\tarena_t *oldarena;\n\tunsigned newind, oldind;\n\n\toldarena = arena_choose(tsd, NULL);\n\tif (oldarena == NULL)\n\t\treturn (EAGAIN);\n\n\tmalloc_mutex_lock(tsd_tsdn(tsd), &ctl_mtx);\n\tnewind = oldind = oldarena->ind;\n\tWRITE(newind, unsigned);\n\tREAD(oldind, unsigned);\n\tif (newind != oldind) {\n\t\tarena_t *newarena;\n\n\t\tif (newind >= ctl_stats.narenas) {\n\t\t\t/* New arena index is out of range. */\n\t\t\tret = EFAULT;\n\t\t\tgoto label_return;\n\t\t}\n\n\t\t/* Initialize arena if necessary. */\n\t\tnewarena = arena_get(tsd_tsdn(tsd), newind, true);\n\t\tif (newarena == NULL) {\n\t\t\tret = EAGAIN;\n\t\t\tgoto label_return;\n\t\t}\n\t\t/* Set new arena/tcache associations. */\n\t\tarena_migrate(tsd, oldind, newind);\n\t\tif (config_tcache) {\n\t\t\ttcache_t *tcache = tsd_tcache_get(tsd);\n\t\t\tif (tcache != NULL) {\n\t\t\t\ttcache_arena_reassociate(tsd_tsdn(tsd), tcache,\n\t\t\t\t    oldarena, newarena);\n\t\t\t}\n\t\t}\n\t}\n\n\tret = 0;\nlabel_return:\n\tmalloc_mutex_unlock(tsd_tsdn(tsd), &ctl_mtx);\n\treturn (ret);\n}\n\nCTL_TSD_RO_NL_CGEN(config_stats, thread_allocated, tsd_thread_allocated_get,\n    uint64_t)\nCTL_TSD_RO_NL_CGEN(config_stats, thread_allocatedp, tsd_thread_allocatedp_get,\n    uint64_t *)\nCTL_TSD_RO_NL_CGEN(config_stats, thread_deallocated, tsd_thread_deallocated_get,\n    uint64_t)\nCTL_TSD_RO_NL_CGEN(config_stats, thread_deallocatedp,\n    tsd_thread_deallocatedp_get, uint64_t *)\n\nstatic int\nthread_tcache_enabled_ctl(tsd_t *tsd, const size_t *mib, size_t miblen,\n    void *oldp, size_t *oldlenp, void *newp, size_t newlen)\n{\n\tint ret;\n\tbool oldval;\n\n\tif (!config_tcache)\n\t\treturn (ENOENT);\n\n\toldval = tcache_enabled_get();\n\tif (newp != NULL) {\n\t\tif (newlen != sizeof(bool)) {\n\t\t\tret = EINVAL;\n\t\t\tgoto label_return;\n\t\t}\n\t\ttcache_enabled_set(*(bool *)newp);\n\t}\n\tREAD(oldval, bool);\n\n\tret = 0;\nlabel_return:\n\treturn (ret);\n}\n\nstatic int\nthread_tcache_flush_ctl(tsd_t *tsd, const size_t *mib, size_t miblen,\n    void *oldp, size_t *oldlenp, void *newp, size_t newlen)\n{\n\tint ret;\n\n\tif (!config_tcache)\n\t\treturn (ENOENT);\n\n\tREADONLY();\n\tWRITEONLY();\n\n\ttcache_flush();\n\n\tret = 0;\nlabel_return:\n\treturn (ret);\n}\n\nstatic int\nthread_prof_name_ctl(tsd_t *tsd, const size_t *mib, size_t miblen, void *oldp,\n    size_t *oldlenp, void *newp, size_t newlen)\n{\n\tint ret;\n\n\tif (!config_prof)\n\t\treturn (ENOENT);\n\n\tREAD_XOR_WRITE();\n\n\tif (newp != NULL) {\n\t\tif (newlen != sizeof(const char *)) {\n\t\t\tret = EINVAL;\n\t\t\tgoto label_return;\n\t\t}\n\n\t\tif ((ret = prof_thread_name_set(tsd, *(const char **)newp)) !=\n\t\t    0)\n\t\t\tgoto label_return;\n\t} else {\n\t\tconst char *oldname = prof_thread_name_get(tsd);\n\t\tREAD(oldname, const char *);\n\t}\n\n\tret = 0;\nlabel_return:\n\treturn (ret);\n}\n\nstatic int\nthread_prof_active_ctl(tsd_t *tsd, const size_t *mib, size_t miblen, void *oldp,\n    size_t *oldlenp, void *newp, size_t newlen)\n{\n\tint ret;\n\tbool oldval;\n\n\tif (!config_prof)\n\t\treturn (ENOENT);\n\n\toldval = prof_thread_active_get(tsd);\n\tif (newp != NULL) {\n\t\tif (newlen != sizeof(bool)) {\n\t\t\tret = EINVAL;\n\t\t\tgoto label_return;\n\t\t}\n\t\tif (prof_thread_active_set(tsd, *(bool *)newp)) {\n\t\t\tret = EAGAIN;\n\t\t\tgoto label_return;\n\t\t}\n\t}\n\tREAD(oldval, bool);\n\n\tret = 0;\nlabel_return:\n\treturn (ret);\n}\n\n/******************************************************************************/\n\nstatic int\ntcache_create_ctl(tsd_t *tsd, const size_t *mib, size_t miblen, void *oldp,\n    size_t *oldlenp, void *newp, size_t newlen)\n{\n\tint ret;\n\tunsigned tcache_ind;\n\n\tif (!config_tcache)\n\t\treturn (ENOENT);\n\n\tmalloc_mutex_lock(tsd_tsdn(tsd), &ctl_mtx);\n\tREADONLY();\n\tif (tcaches_create(tsd_tsdn(tsd), &tcache_ind)) {\n\t\tret = EFAULT;\n\t\tgoto label_return;\n\t}\n\tREAD(tcache_ind, unsigned);\n\n\tret = 0;\nlabel_return:\n\tmalloc_mutex_unlock(tsd_tsdn(tsd), &ctl_mtx);\n\treturn (ret);\n}\n\nstatic int\ntcache_flush_ctl(tsd_t *tsd, const size_t *mib, size_t miblen, void *oldp,\n    size_t *oldlenp, void *newp, size_t newlen)\n{\n\tint ret;\n\tunsigned tcache_ind;\n\n\tif (!config_tcache)\n\t\treturn (ENOENT);\n\n\tWRITEONLY();\n\ttcache_ind = UINT_MAX;\n\tWRITE(tcache_ind, unsigned);\n\tif (tcache_ind == UINT_MAX) {\n\t\tret = EFAULT;\n\t\tgoto label_return;\n\t}\n\ttcaches_flush(tsd, tcache_ind);\n\n\tret = 0;\nlabel_return:\n\treturn (ret);\n}\n\nstatic int\ntcache_destroy_ctl(tsd_t *tsd, const size_t *mib, size_t miblen, void *oldp,\n    size_t *oldlenp, void *newp, size_t newlen)\n{\n\tint ret;\n\tunsigned tcache_ind;\n\n\tif (!config_tcache)\n\t\treturn (ENOENT);\n\n\tWRITEONLY();\n\ttcache_ind = UINT_MAX;\n\tWRITE(tcache_ind, unsigned);\n\tif (tcache_ind == UINT_MAX) {\n\t\tret = EFAULT;\n\t\tgoto label_return;\n\t}\n\ttcaches_destroy(tsd, tcache_ind);\n\n\tret = 0;\nlabel_return:\n\treturn (ret);\n}\n\n/******************************************************************************/\n\nstatic void\narena_i_purge(tsdn_t *tsdn, unsigned arena_ind, bool all)\n{\n\n\tmalloc_mutex_lock(tsdn, &ctl_mtx);\n\t{\n\t\tunsigned narenas = ctl_stats.narenas;\n\n\t\tif (arena_ind == narenas) {\n\t\t\tunsigned i;\n\t\t\tVARIABLE_ARRAY(arena_t *, tarenas, narenas);\n\n\t\t\tfor (i = 0; i < narenas; i++)\n\t\t\t\ttarenas[i] = arena_get(tsdn, i, false);\n\n\t\t\t/*\n\t\t\t * No further need to hold ctl_mtx, since narenas and\n\t\t\t * tarenas contain everything needed below.\n\t\t\t */\n\t\t\tmalloc_mutex_unlock(tsdn, &ctl_mtx);\n\n\t\t\tfor (i = 0; i < narenas; i++) {\n\t\t\t\tif (tarenas[i] != NULL)\n\t\t\t\t\tarena_purge(tsdn, tarenas[i], all);\n\t\t\t}\n\t\t} else {\n\t\t\tarena_t *tarena;\n\n\t\t\tassert(arena_ind < narenas);\n\n\t\t\ttarena = arena_get(tsdn, arena_ind, false);\n\n\t\t\t/* No further need to hold ctl_mtx. */\n\t\t\tmalloc_mutex_unlock(tsdn, &ctl_mtx);\n\n\t\t\tif (tarena != NULL)\n\t\t\t\tarena_purge(tsdn, tarena, all);\n\t\t}\n\t}\n}\n\nstatic int\narena_i_purge_ctl(tsd_t *tsd, const size_t *mib, size_t miblen, void *oldp,\n    size_t *oldlenp, void *newp, size_t newlen)\n{\n\tint ret;\n\n\tREADONLY();\n\tWRITEONLY();\n\tarena_i_purge(tsd_tsdn(tsd), (unsigned)mib[1], true);\n\n\tret = 0;\nlabel_return:\n\treturn (ret);\n}\n\nstatic int\narena_i_decay_ctl(tsd_t *tsd, const size_t *mib, size_t miblen, void *oldp,\n    size_t *oldlenp, void *newp, size_t newlen)\n{\n\tint ret;\n\n\tREADONLY();\n\tWRITEONLY();\n\tarena_i_purge(tsd_tsdn(tsd), (unsigned)mib[1], false);\n\n\tret = 0;\nlabel_return:\n\treturn (ret);\n}\n\nstatic int\narena_i_reset_ctl(tsd_t *tsd, const size_t *mib, size_t miblen, void *oldp,\n    size_t *oldlenp, void *newp, size_t newlen)\n{\n\tint ret;\n\tunsigned arena_ind;\n\tarena_t *arena;\n\n\tREADONLY();\n\tWRITEONLY();\n\n\tif ((config_valgrind && unlikely(in_valgrind)) || (config_fill &&\n\t    unlikely(opt_quarantine))) {\n\t\tret = EFAULT;\n\t\tgoto label_return;\n\t}\n\n\tarena_ind = (unsigned)mib[1];\n\tif (config_debug) {\n\t\tmalloc_mutex_lock(tsd_tsdn(tsd), &ctl_mtx);\n\t\tassert(arena_ind < ctl_stats.narenas);\n\t\tmalloc_mutex_unlock(tsd_tsdn(tsd), &ctl_mtx);\n\t}\n\tassert(arena_ind >= opt_narenas);\n\n\tarena = arena_get(tsd_tsdn(tsd), arena_ind, false);\n\n\tarena_reset(tsd, arena);\n\n\tret = 0;\nlabel_return:\n\treturn (ret);\n}\n\nstatic int\narena_i_dss_ctl(tsd_t *tsd, const size_t *mib, size_t miblen, void *oldp,\n    size_t *oldlenp, void *newp, size_t newlen)\n{\n\tint ret;\n\tconst char *dss = NULL;\n\tunsigned arena_ind = (unsigned)mib[1];\n\tdss_prec_t dss_prec_old = dss_prec_limit;\n\tdss_prec_t dss_prec = dss_prec_limit;\n\n\tmalloc_mutex_lock(tsd_tsdn(tsd), &ctl_mtx);\n\tWRITE(dss, const char *);\n\tif (dss != NULL) {\n\t\tint i;\n\t\tbool match = false;\n\n\t\tfor (i = 0; i < dss_prec_limit; i++) {\n\t\t\tif (strcmp(dss_prec_names[i], dss) == 0) {\n\t\t\t\tdss_prec = i;\n\t\t\t\tmatch = true;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\n\t\tif (!match) {\n\t\t\tret = EINVAL;\n\t\t\tgoto label_return;\n\t\t}\n\t}\n\n\tif (arena_ind < ctl_stats.narenas) {\n\t\tarena_t *arena = arena_get(tsd_tsdn(tsd), arena_ind, false);\n\t\tif (arena == NULL || (dss_prec != dss_prec_limit &&\n\t\t    arena_dss_prec_set(tsd_tsdn(tsd), arena, dss_prec))) {\n\t\t\tret = EFAULT;\n\t\t\tgoto label_return;\n\t\t}\n\t\tdss_prec_old = arena_dss_prec_get(tsd_tsdn(tsd), arena);\n\t} else {\n\t\tif (dss_prec != dss_prec_limit &&\n\t\t    chunk_dss_prec_set(tsd_tsdn(tsd), dss_prec)) {\n\t\t\tret = EFAULT;\n\t\t\tgoto label_return;\n\t\t}\n\t\tdss_prec_old = chunk_dss_prec_get(tsd_tsdn(tsd));\n\t}\n\n\tdss = dss_prec_names[dss_prec_old];\n\tREAD(dss, const char *);\n\n\tret = 0;\nlabel_return:\n\tmalloc_mutex_unlock(tsd_tsdn(tsd), &ctl_mtx);\n\treturn (ret);\n}\n\nstatic int\narena_i_lg_dirty_mult_ctl(tsd_t *tsd, const size_t *mib, size_t miblen,\n    void *oldp, size_t *oldlenp, void *newp, size_t newlen)\n{\n\tint ret;\n\tunsigned arena_ind = (unsigned)mib[1];\n\tarena_t *arena;\n\n\tarena = arena_get(tsd_tsdn(tsd), arena_ind, false);\n\tif (arena == NULL) {\n\t\tret = EFAULT;\n\t\tgoto label_return;\n\t}\n\n\tif (oldp != NULL && oldlenp != NULL) {\n\t\tsize_t oldval = arena_lg_dirty_mult_get(tsd_tsdn(tsd), arena);\n\t\tREAD(oldval, ssize_t);\n\t}\n\tif (newp != NULL) {\n\t\tif (newlen != sizeof(ssize_t)) {\n\t\t\tret = EINVAL;\n\t\t\tgoto label_return;\n\t\t}\n\t\tif (arena_lg_dirty_mult_set(tsd_tsdn(tsd), arena,\n\t\t    *(ssize_t *)newp)) {\n\t\t\tret = EFAULT;\n\t\t\tgoto label_return;\n\t\t}\n\t}\n\n\tret = 0;\nlabel_return:\n\treturn (ret);\n}\n\nstatic int\narena_i_decay_time_ctl(tsd_t *tsd, const size_t *mib, size_t miblen, void *oldp,\n    size_t *oldlenp, void *newp, size_t newlen)\n{\n\tint ret;\n\tunsigned arena_ind = (unsigned)mib[1];\n\tarena_t *arena;\n\n\tarena = arena_get(tsd_tsdn(tsd), arena_ind, false);\n\tif (arena == NULL) {\n\t\tret = EFAULT;\n\t\tgoto label_return;\n\t}\n\n\tif (oldp != NULL && oldlenp != NULL) {\n\t\tsize_t oldval = arena_decay_time_get(tsd_tsdn(tsd), arena);\n\t\tREAD(oldval, ssize_t);\n\t}\n\tif (newp != NULL) {\n\t\tif (newlen != sizeof(ssize_t)) {\n\t\t\tret = EINVAL;\n\t\t\tgoto label_return;\n\t\t}\n\t\tif (arena_decay_time_set(tsd_tsdn(tsd), arena,\n\t\t    *(ssize_t *)newp)) {\n\t\t\tret = EFAULT;\n\t\t\tgoto label_return;\n\t\t}\n\t}\n\n\tret = 0;\nlabel_return:\n\treturn (ret);\n}\n\nstatic int\narena_i_chunk_hooks_ctl(tsd_t *tsd, const size_t *mib, size_t miblen,\n    void *oldp, size_t *oldlenp, void *newp, size_t newlen)\n{\n\tint ret;\n\tunsigned arena_ind = (unsigned)mib[1];\n\tarena_t *arena;\n\n\tmalloc_mutex_lock(tsd_tsdn(tsd), &ctl_mtx);\n\tif (arena_ind < narenas_total_get() && (arena =\n\t    arena_get(tsd_tsdn(tsd), arena_ind, false)) != NULL) {\n\t\tif (newp != NULL) {\n\t\t\tchunk_hooks_t old_chunk_hooks, new_chunk_hooks;\n\t\t\tWRITE(new_chunk_hooks, chunk_hooks_t);\n\t\t\told_chunk_hooks = chunk_hooks_set(tsd_tsdn(tsd), arena,\n\t\t\t    &new_chunk_hooks);\n\t\t\tREAD(old_chunk_hooks, chunk_hooks_t);\n\t\t} else {\n\t\t\tchunk_hooks_t old_chunk_hooks =\n\t\t\t    chunk_hooks_get(tsd_tsdn(tsd), arena);\n\t\t\tREAD(old_chunk_hooks, chunk_hooks_t);\n\t\t}\n\t} else {\n\t\tret = EFAULT;\n\t\tgoto label_return;\n\t}\n\tret = 0;\nlabel_return:\n\tmalloc_mutex_unlock(tsd_tsdn(tsd), &ctl_mtx);\n\treturn (ret);\n}\n\nstatic const ctl_named_node_t *\narena_i_index(tsdn_t *tsdn, const size_t *mib, size_t miblen, size_t i)\n{\n\tconst ctl_named_node_t *ret;\n\n\tmalloc_mutex_lock(tsdn, &ctl_mtx);\n\tif (i > ctl_stats.narenas) {\n\t\tret = NULL;\n\t\tgoto label_return;\n\t}\n\n\tret = super_arena_i_node;\nlabel_return:\n\tmalloc_mutex_unlock(tsdn, &ctl_mtx);\n\treturn (ret);\n}\n\n/******************************************************************************/\n\nstatic int\narenas_narenas_ctl(tsd_t *tsd, const size_t *mib, size_t miblen, void *oldp,\n    size_t *oldlenp, void *newp, size_t newlen)\n{\n\tint ret;\n\tunsigned narenas;\n\n\tmalloc_mutex_lock(tsd_tsdn(tsd), &ctl_mtx);\n\tREADONLY();\n\tif (*oldlenp != sizeof(unsigned)) {\n\t\tret = EINVAL;\n\t\tgoto label_return;\n\t}\n\tnarenas = ctl_stats.narenas;\n\tREAD(narenas, unsigned);\n\n\tret = 0;\nlabel_return:\n\tmalloc_mutex_unlock(tsd_tsdn(tsd), &ctl_mtx);\n\treturn (ret);\n}\n\nstatic int\narenas_initialized_ctl(tsd_t *tsd, const size_t *mib, size_t miblen, void *oldp,\n    size_t *oldlenp, void *newp, size_t newlen)\n{\n\tint ret;\n\tunsigned nread, i;\n\n\tmalloc_mutex_lock(tsd_tsdn(tsd), &ctl_mtx);\n\tREADONLY();\n\tif (*oldlenp != ctl_stats.narenas * sizeof(bool)) {\n\t\tret = EINVAL;\n\t\tnread = (*oldlenp < ctl_stats.narenas * sizeof(bool))\n\t\t    ? (unsigned)(*oldlenp / sizeof(bool)) : ctl_stats.narenas;\n\t} else {\n\t\tret = 0;\n\t\tnread = ctl_stats.narenas;\n\t}\n\n\tfor (i = 0; i < nread; i++)\n\t\t((bool *)oldp)[i] = ctl_stats.arenas[i].initialized;\n\nlabel_return:\n\tmalloc_mutex_unlock(tsd_tsdn(tsd), &ctl_mtx);\n\treturn (ret);\n}\n\nstatic int\narenas_lg_dirty_mult_ctl(tsd_t *tsd, const size_t *mib, size_t miblen,\n    void *oldp, size_t *oldlenp, void *newp, size_t newlen)\n{\n\tint ret;\n\n\tif (oldp != NULL && oldlenp != NULL) {\n\t\tsize_t oldval = arena_lg_dirty_mult_default_get();\n\t\tREAD(oldval, ssize_t);\n\t}\n\tif (newp != NULL) {\n\t\tif (newlen != sizeof(ssize_t)) {\n\t\t\tret = EINVAL;\n\t\t\tgoto label_return;\n\t\t}\n\t\tif (arena_lg_dirty_mult_default_set(*(ssize_t *)newp)) {\n\t\t\tret = EFAULT;\n\t\t\tgoto label_return;\n\t\t}\n\t}\n\n\tret = 0;\nlabel_return:\n\treturn (ret);\n}\n\nstatic int\narenas_decay_time_ctl(tsd_t *tsd, const size_t *mib, size_t miblen, void *oldp,\n    size_t *oldlenp, void *newp, size_t newlen)\n{\n\tint ret;\n\n\tif (oldp != NULL && oldlenp != NULL) {\n\t\tsize_t oldval = arena_decay_time_default_get();\n\t\tREAD(oldval, ssize_t);\n\t}\n\tif (newp != NULL) {\n\t\tif (newlen != sizeof(ssize_t)) {\n\t\t\tret = EINVAL;\n\t\t\tgoto label_return;\n\t\t}\n\t\tif (arena_decay_time_default_set(*(ssize_t *)newp)) {\n\t\t\tret = EFAULT;\n\t\t\tgoto label_return;\n\t\t}\n\t}\n\n\tret = 0;\nlabel_return:\n\treturn (ret);\n}\n\nCTL_RO_NL_GEN(arenas_quantum, QUANTUM, size_t)\nCTL_RO_NL_GEN(arenas_page, PAGE, size_t)\nCTL_RO_NL_CGEN(config_tcache, arenas_tcache_max, tcache_maxclass, size_t)\nCTL_RO_NL_GEN(arenas_nbins, NBINS, unsigned)\nCTL_RO_NL_CGEN(config_tcache, arenas_nhbins, nhbins, unsigned)\nCTL_RO_NL_GEN(arenas_bin_i_size, arena_bin_info[mib[2]].reg_size, size_t)\nCTL_RO_NL_GEN(arenas_bin_i_nregs, arena_bin_info[mib[2]].nregs, uint32_t)\nCTL_RO_NL_GEN(arenas_bin_i_run_size, arena_bin_info[mib[2]].run_size, size_t)\nstatic const ctl_named_node_t *\narenas_bin_i_index(tsdn_t *tsdn, const size_t *mib, size_t miblen, size_t i)\n{\n\n\tif (i > NBINS)\n\t\treturn (NULL);\n\treturn (super_arenas_bin_i_node);\n}\n\nCTL_RO_NL_GEN(arenas_nlruns, nlclasses, unsigned)\nCTL_RO_NL_GEN(arenas_lrun_i_size, index2size(NBINS+(szind_t)mib[2]), size_t)\nstatic const ctl_named_node_t *\narenas_lrun_i_index(tsdn_t *tsdn, const size_t *mib, size_t miblen, size_t i)\n{\n\n\tif (i > nlclasses)\n\t\treturn (NULL);\n\treturn (super_arenas_lrun_i_node);\n}\n\nCTL_RO_NL_GEN(arenas_nhchunks, nhclasses, unsigned)\nCTL_RO_NL_GEN(arenas_hchunk_i_size, index2size(NBINS+nlclasses+(szind_t)mib[2]),\n    size_t)\nstatic const ctl_named_node_t *\narenas_hchunk_i_index(tsdn_t *tsdn, const size_t *mib, size_t miblen, size_t i)\n{\n\n\tif (i > nhclasses)\n\t\treturn (NULL);\n\treturn (super_arenas_hchunk_i_node);\n}\n\nstatic int\narenas_extend_ctl(tsd_t *tsd, const size_t *mib, size_t miblen, void *oldp,\n    size_t *oldlenp, void *newp, size_t newlen)\n{\n\tint ret;\n\tunsigned narenas;\n\n\tmalloc_mutex_lock(tsd_tsdn(tsd), &ctl_mtx);\n\tREADONLY();\n\tif (ctl_grow(tsd_tsdn(tsd))) {\n\t\tret = EAGAIN;\n\t\tgoto label_return;\n\t}\n\tnarenas = ctl_stats.narenas - 1;\n\tREAD(narenas, unsigned);\n\n\tret = 0;\nlabel_return:\n\tmalloc_mutex_unlock(tsd_tsdn(tsd), &ctl_mtx);\n\treturn (ret);\n}\n\n/******************************************************************************/\n\nstatic int\nprof_thread_active_init_ctl(tsd_t *tsd, const size_t *mib, size_t miblen,\n    void *oldp, size_t *oldlenp, void *newp, size_t newlen)\n{\n\tint ret;\n\tbool oldval;\n\n\tif (!config_prof)\n\t\treturn (ENOENT);\n\n\tif (newp != NULL) {\n\t\tif (newlen != sizeof(bool)) {\n\t\t\tret = EINVAL;\n\t\t\tgoto label_return;\n\t\t}\n\t\toldval = prof_thread_active_init_set(tsd_tsdn(tsd),\n\t\t    *(bool *)newp);\n\t} else\n\t\toldval = prof_thread_active_init_get(tsd_tsdn(tsd));\n\tREAD(oldval, bool);\n\n\tret = 0;\nlabel_return:\n\treturn (ret);\n}\n\nstatic int\nprof_active_ctl(tsd_t *tsd, const size_t *mib, size_t miblen, void *oldp,\n    size_t *oldlenp, void *newp, size_t newlen)\n{\n\tint ret;\n\tbool oldval;\n\n\tif (!config_prof)\n\t\treturn (ENOENT);\n\n\tif (newp != NULL) {\n\t\tif (newlen != sizeof(bool)) {\n\t\t\tret = EINVAL;\n\t\t\tgoto label_return;\n\t\t}\n\t\toldval = prof_active_set(tsd_tsdn(tsd), *(bool *)newp);\n\t} else\n\t\toldval = prof_active_get(tsd_tsdn(tsd));\n\tREAD(oldval, bool);\n\n\tret = 0;\nlabel_return:\n\treturn (ret);\n}\n\nstatic int\nprof_dump_ctl(tsd_t *tsd, const size_t *mib, size_t miblen, void *oldp,\n    size_t *oldlenp, void *newp, size_t newlen)\n{\n\tint ret;\n\tconst char *filename = NULL;\n\n\tif (!config_prof)\n\t\treturn (ENOENT);\n\n\tWRITEONLY();\n\tWRITE(filename, const char *);\n\n\tif (prof_mdump(tsd, filename)) {\n\t\tret = EFAULT;\n\t\tgoto label_return;\n\t}\n\n\tret = 0;\nlabel_return:\n\treturn (ret);\n}\n\nstatic int\nprof_gdump_ctl(tsd_t *tsd, const size_t *mib, size_t miblen, void *oldp,\n    size_t *oldlenp, void *newp, size_t newlen)\n{\n\tint ret;\n\tbool oldval;\n\n\tif (!config_prof)\n\t\treturn (ENOENT);\n\n\tif (newp != NULL) {\n\t\tif (newlen != sizeof(bool)) {\n\t\t\tret = EINVAL;\n\t\t\tgoto label_return;\n\t\t}\n\t\toldval = prof_gdump_set(tsd_tsdn(tsd), *(bool *)newp);\n\t} else\n\t\toldval = prof_gdump_get(tsd_tsdn(tsd));\n\tREAD(oldval, bool);\n\n\tret = 0;\nlabel_return:\n\treturn (ret);\n}\n\nstatic int\nprof_reset_ctl(tsd_t *tsd, const size_t *mib, size_t miblen, void *oldp,\n    size_t *oldlenp, void *newp, size_t newlen)\n{\n\tint ret;\n\tsize_t lg_sample = lg_prof_sample;\n\n\tif (!config_prof)\n\t\treturn (ENOENT);\n\n\tWRITEONLY();\n\tWRITE(lg_sample, size_t);\n\tif (lg_sample >= (sizeof(uint64_t) << 3))\n\t\tlg_sample = (sizeof(uint64_t) << 3) - 1;\n\n\tprof_reset(tsd_tsdn(tsd), lg_sample);\n\n\tret = 0;\nlabel_return:\n\treturn (ret);\n}\n\nCTL_RO_NL_CGEN(config_prof, prof_interval, prof_interval, uint64_t)\nCTL_RO_NL_CGEN(config_prof, lg_prof_sample, lg_prof_sample, size_t)\n\n/******************************************************************************/\n\nCTL_RO_CGEN(config_stats, stats_cactive, &stats_cactive, size_t *)\nCTL_RO_CGEN(config_stats, stats_allocated, ctl_stats.allocated, size_t)\nCTL_RO_CGEN(config_stats, stats_active, ctl_stats.active, size_t)\nCTL_RO_CGEN(config_stats, stats_metadata, ctl_stats.metadata, size_t)\nCTL_RO_CGEN(config_stats, stats_resident, ctl_stats.resident, size_t)\nCTL_RO_CGEN(config_stats, stats_mapped, ctl_stats.mapped, size_t)\nCTL_RO_CGEN(config_stats, stats_retained, ctl_stats.retained, size_t)\n\nCTL_RO_GEN(stats_arenas_i_dss, ctl_stats.arenas[mib[2]].dss, const char *)\nCTL_RO_GEN(stats_arenas_i_lg_dirty_mult, ctl_stats.arenas[mib[2]].lg_dirty_mult,\n    ssize_t)\nCTL_RO_GEN(stats_arenas_i_decay_time, ctl_stats.arenas[mib[2]].decay_time,\n    ssize_t)\nCTL_RO_GEN(stats_arenas_i_nthreads, ctl_stats.arenas[mib[2]].nthreads, unsigned)\nCTL_RO_GEN(stats_arenas_i_pactive, ctl_stats.arenas[mib[2]].pactive, size_t)\nCTL_RO_GEN(stats_arenas_i_pdirty, ctl_stats.arenas[mib[2]].pdirty, size_t)\nCTL_RO_CGEN(config_stats, stats_arenas_i_mapped,\n    ctl_stats.arenas[mib[2]].astats.mapped, size_t)\nCTL_RO_CGEN(config_stats, stats_arenas_i_retained,\n    ctl_stats.arenas[mib[2]].astats.retained, size_t)\nCTL_RO_CGEN(config_stats, stats_arenas_i_npurge,\n    ctl_stats.arenas[mib[2]].astats.npurge, uint64_t)\nCTL_RO_CGEN(config_stats, stats_arenas_i_nmadvise,\n    ctl_stats.arenas[mib[2]].astats.nmadvise, uint64_t)\nCTL_RO_CGEN(config_stats, stats_arenas_i_purged,\n    ctl_stats.arenas[mib[2]].astats.purged, uint64_t)\nCTL_RO_CGEN(config_stats, stats_arenas_i_metadata_mapped,\n    ctl_stats.arenas[mib[2]].astats.metadata_mapped, size_t)\nCTL_RO_CGEN(config_stats, stats_arenas_i_metadata_allocated,\n    ctl_stats.arenas[mib[2]].astats.metadata_allocated, size_t)\n\nCTL_RO_CGEN(config_stats, stats_arenas_i_small_allocated,\n    ctl_stats.arenas[mib[2]].allocated_small, size_t)\nCTL_RO_CGEN(config_stats, stats_arenas_i_small_nmalloc,\n    ctl_stats.arenas[mib[2]].nmalloc_small, uint64_t)\nCTL_RO_CGEN(config_stats, stats_arenas_i_small_ndalloc,\n    ctl_stats.arenas[mib[2]].ndalloc_small, uint64_t)\nCTL_RO_CGEN(config_stats, stats_arenas_i_small_nrequests,\n    ctl_stats.arenas[mib[2]].nrequests_small, uint64_t)\nCTL_RO_CGEN(config_stats, stats_arenas_i_large_allocated,\n    ctl_stats.arenas[mib[2]].astats.allocated_large, size_t)\nCTL_RO_CGEN(config_stats, stats_arenas_i_large_nmalloc,\n    ctl_stats.arenas[mib[2]].astats.nmalloc_large, uint64_t)\nCTL_RO_CGEN(config_stats, stats_arenas_i_large_ndalloc,\n    ctl_stats.arenas[mib[2]].astats.ndalloc_large, uint64_t)\nCTL_RO_CGEN(config_stats, stats_arenas_i_large_nrequests,\n    ctl_stats.arenas[mib[2]].astats.nrequests_large, uint64_t)\nCTL_RO_CGEN(config_stats, stats_arenas_i_huge_allocated,\n    ctl_stats.arenas[mib[2]].astats.allocated_huge, size_t)\nCTL_RO_CGEN(config_stats, stats_arenas_i_huge_nmalloc,\n    ctl_stats.arenas[mib[2]].astats.nmalloc_huge, uint64_t)\nCTL_RO_CGEN(config_stats, stats_arenas_i_huge_ndalloc,\n    ctl_stats.arenas[mib[2]].astats.ndalloc_huge, uint64_t)\nCTL_RO_CGEN(config_stats, stats_arenas_i_huge_nrequests,\n    ctl_stats.arenas[mib[2]].astats.nmalloc_huge, uint64_t) /* Intentional. */\n\nCTL_RO_CGEN(config_stats, stats_arenas_i_bins_j_nmalloc,\n    ctl_stats.arenas[mib[2]].bstats[mib[4]].nmalloc, uint64_t)\nCTL_RO_CGEN(config_stats, stats_arenas_i_bins_j_ndalloc,\n    ctl_stats.arenas[mib[2]].bstats[mib[4]].ndalloc, uint64_t)\nCTL_RO_CGEN(config_stats, stats_arenas_i_bins_j_nrequests,\n    ctl_stats.arenas[mib[2]].bstats[mib[4]].nrequests, uint64_t)\nCTL_RO_CGEN(config_stats, stats_arenas_i_bins_j_curregs,\n    ctl_stats.arenas[mib[2]].bstats[mib[4]].curregs, size_t)\nCTL_RO_CGEN(config_stats && config_tcache, stats_arenas_i_bins_j_nfills,\n    ctl_stats.arenas[mib[2]].bstats[mib[4]].nfills, uint64_t)\nCTL_RO_CGEN(config_stats && config_tcache, stats_arenas_i_bins_j_nflushes,\n    ctl_stats.arenas[mib[2]].bstats[mib[4]].nflushes, uint64_t)\nCTL_RO_CGEN(config_stats, stats_arenas_i_bins_j_nruns,\n    ctl_stats.arenas[mib[2]].bstats[mib[4]].nruns, uint64_t)\nCTL_RO_CGEN(config_stats, stats_arenas_i_bins_j_nreruns,\n    ctl_stats.arenas[mib[2]].bstats[mib[4]].reruns, uint64_t)\nCTL_RO_CGEN(config_stats, stats_arenas_i_bins_j_curruns,\n    ctl_stats.arenas[mib[2]].bstats[mib[4]].curruns, size_t)\n\nstatic const ctl_named_node_t *\nstats_arenas_i_bins_j_index(tsdn_t *tsdn, const size_t *mib, size_t miblen,\n    size_t j)\n{\n\n\tif (j > NBINS)\n\t\treturn (NULL);\n\treturn (super_stats_arenas_i_bins_j_node);\n}\n\nCTL_RO_CGEN(config_stats, stats_arenas_i_lruns_j_nmalloc,\n    ctl_stats.arenas[mib[2]].lstats[mib[4]].nmalloc, uint64_t)\nCTL_RO_CGEN(config_stats, stats_arenas_i_lruns_j_ndalloc,\n    ctl_stats.arenas[mib[2]].lstats[mib[4]].ndalloc, uint64_t)\nCTL_RO_CGEN(config_stats, stats_arenas_i_lruns_j_nrequests,\n    ctl_stats.arenas[mib[2]].lstats[mib[4]].nrequests, uint64_t)\nCTL_RO_CGEN(config_stats, stats_arenas_i_lruns_j_curruns,\n    ctl_stats.arenas[mib[2]].lstats[mib[4]].curruns, size_t)\n\nstatic const ctl_named_node_t *\nstats_arenas_i_lruns_j_index(tsdn_t *tsdn, const size_t *mib, size_t miblen,\n    size_t j)\n{\n\n\tif (j > nlclasses)\n\t\treturn (NULL);\n\treturn (super_stats_arenas_i_lruns_j_node);\n}\n\nCTL_RO_CGEN(config_stats, stats_arenas_i_hchunks_j_nmalloc,\n    ctl_stats.arenas[mib[2]].hstats[mib[4]].nmalloc, uint64_t)\nCTL_RO_CGEN(config_stats, stats_arenas_i_hchunks_j_ndalloc,\n    ctl_stats.arenas[mib[2]].hstats[mib[4]].ndalloc, uint64_t)\nCTL_RO_CGEN(config_stats, stats_arenas_i_hchunks_j_nrequests,\n    ctl_stats.arenas[mib[2]].hstats[mib[4]].nmalloc, /* Intentional. */\n    uint64_t)\nCTL_RO_CGEN(config_stats, stats_arenas_i_hchunks_j_curhchunks,\n    ctl_stats.arenas[mib[2]].hstats[mib[4]].curhchunks, size_t)\n\nstatic const ctl_named_node_t *\nstats_arenas_i_hchunks_j_index(tsdn_t *tsdn, const size_t *mib, size_t miblen,\n    size_t j)\n{\n\n\tif (j > nhclasses)\n\t\treturn (NULL);\n\treturn (super_stats_arenas_i_hchunks_j_node);\n}\n\nstatic const ctl_named_node_t *\nstats_arenas_i_index(tsdn_t *tsdn, const size_t *mib, size_t miblen, size_t i)\n{\n\tconst ctl_named_node_t * ret;\n\n\tmalloc_mutex_lock(tsdn, &ctl_mtx);\n\tif (i > ctl_stats.narenas || !ctl_stats.arenas[i].initialized) {\n\t\tret = NULL;\n\t\tgoto label_return;\n\t}\n\n\tret = super_stats_arenas_i_node;\nlabel_return:\n\tmalloc_mutex_unlock(tsdn, &ctl_mtx);\n\treturn (ret);\n}\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/deps/jemalloc/src/extent.c",
    "content": "#define\tJEMALLOC_EXTENT_C_\n#include \"jemalloc/internal/jemalloc_internal.h\"\n\n/******************************************************************************/\n\nJEMALLOC_INLINE_C size_t\nextent_quantize(size_t size)\n{\n\n\t/*\n\t * Round down to the nearest chunk size that can actually be requested\n\t * during normal huge allocation.\n\t */\n\treturn (index2size(size2index(size + 1) - 1));\n}\n\nJEMALLOC_INLINE_C int\nextent_szad_comp(const extent_node_t *a, const extent_node_t *b)\n{\n\tint ret;\n\tsize_t a_qsize = extent_quantize(extent_node_size_get(a));\n\tsize_t b_qsize = extent_quantize(extent_node_size_get(b));\n\n\t/*\n\t * Compare based on quantized size rather than size, in order to sort\n\t * equally useful extents only by address.\n\t */\n\tret = (a_qsize > b_qsize) - (a_qsize < b_qsize);\n\tif (ret == 0) {\n\t\tuintptr_t a_addr = (uintptr_t)extent_node_addr_get(a);\n\t\tuintptr_t b_addr = (uintptr_t)extent_node_addr_get(b);\n\n\t\tret = (a_addr > b_addr) - (a_addr < b_addr);\n\t}\n\n\treturn (ret);\n}\n\n/* Generate red-black tree functions. */\nrb_gen(, extent_tree_szad_, extent_tree_t, extent_node_t, szad_link,\n    extent_szad_comp)\n\nJEMALLOC_INLINE_C int\nextent_ad_comp(const extent_node_t *a, const extent_node_t *b)\n{\n\tuintptr_t a_addr = (uintptr_t)extent_node_addr_get(a);\n\tuintptr_t b_addr = (uintptr_t)extent_node_addr_get(b);\n\n\treturn ((a_addr > b_addr) - (a_addr < b_addr));\n}\n\n/* Generate red-black tree functions. */\nrb_gen(, extent_tree_ad_, extent_tree_t, extent_node_t, ad_link, extent_ad_comp)\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/deps/jemalloc/src/hash.c",
    "content": "#define\tJEMALLOC_HASH_C_\n#include \"jemalloc/internal/jemalloc_internal.h\"\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/deps/jemalloc/src/huge.c",
    "content": "#define\tJEMALLOC_HUGE_C_\n#include \"jemalloc/internal/jemalloc_internal.h\"\n\n/******************************************************************************/\n\nstatic extent_node_t *\nhuge_node_get(const void *ptr)\n{\n\textent_node_t *node;\n\n\tnode = chunk_lookup(ptr, true);\n\tassert(!extent_node_achunk_get(node));\n\n\treturn (node);\n}\n\nstatic bool\nhuge_node_set(tsdn_t *tsdn, const void *ptr, extent_node_t *node)\n{\n\n\tassert(extent_node_addr_get(node) == ptr);\n\tassert(!extent_node_achunk_get(node));\n\treturn (chunk_register(tsdn, ptr, node));\n}\n\nstatic void\nhuge_node_reset(tsdn_t *tsdn, const void *ptr, extent_node_t *node)\n{\n\tbool err;\n\n\terr = huge_node_set(tsdn, ptr, node);\n\tassert(!err);\n}\n\nstatic void\nhuge_node_unset(const void *ptr, const extent_node_t *node)\n{\n\n\tchunk_deregister(ptr, node);\n}\n\nvoid *\nhuge_malloc(tsdn_t *tsdn, arena_t *arena, size_t usize, bool zero)\n{\n\n\tassert(usize == s2u(usize));\n\n\treturn (huge_palloc(tsdn, arena, usize, chunksize, zero));\n}\n\nvoid *\nhuge_palloc(tsdn_t *tsdn, arena_t *arena, size_t usize, size_t alignment,\n    bool zero)\n{\n\tvoid *ret;\n\tsize_t ausize;\n\textent_node_t *node;\n\tbool is_zeroed;\n\n\t/* Allocate one or more contiguous chunks for this request. */\n\n\tassert(!tsdn_null(tsdn) || arena != NULL);\n\n\tausize = sa2u(usize, alignment);\n\tif (unlikely(ausize == 0 || ausize > HUGE_MAXCLASS))\n\t\treturn (NULL);\n\tassert(ausize >= chunksize);\n\n\t/* Allocate an extent node with which to track the chunk. */\n\tnode = ipallocztm(tsdn, CACHELINE_CEILING(sizeof(extent_node_t)),\n\t    CACHELINE, false, NULL, true, arena_ichoose(tsdn, arena));\n\tif (node == NULL)\n\t\treturn (NULL);\n\n\t/*\n\t * Copy zero into is_zeroed and pass the copy to chunk_alloc(), so that\n\t * it is possible to make correct junk/zero fill decisions below.\n\t */\n\tis_zeroed = zero;\n\tif (likely(!tsdn_null(tsdn)))\n\t\tarena = arena_choose(tsdn_tsd(tsdn), arena);\n\tif (unlikely(arena == NULL) || (ret = arena_chunk_alloc_huge(tsdn,\n\t    arena, usize, alignment, &is_zeroed)) == NULL) {\n\t\tidalloctm(tsdn, node, NULL, true, true);\n\t\treturn (NULL);\n\t}\n\n\textent_node_init(node, arena, ret, usize, is_zeroed, true);\n\n\tif (huge_node_set(tsdn, ret, node)) {\n\t\tarena_chunk_dalloc_huge(tsdn, arena, ret, usize);\n\t\tidalloctm(tsdn, node, NULL, true, true);\n\t\treturn (NULL);\n\t}\n\n\t/* Insert node into huge. */\n\tmalloc_mutex_lock(tsdn, &arena->huge_mtx);\n\tql_elm_new(node, ql_link);\n\tql_tail_insert(&arena->huge, node, ql_link);\n\tmalloc_mutex_unlock(tsdn, &arena->huge_mtx);\n\n\tif (zero || (config_fill && unlikely(opt_zero))) {\n\t\tif (!is_zeroed)\n\t\t\tmemset(ret, 0, usize);\n\t} else if (config_fill && unlikely(opt_junk_alloc))\n\t\tmemset(ret, JEMALLOC_ALLOC_JUNK, usize);\n\n\tarena_decay_tick(tsdn, arena);\n\treturn (ret);\n}\n\n#ifdef JEMALLOC_JET\n#undef huge_dalloc_junk\n#define\thuge_dalloc_junk JEMALLOC_N(huge_dalloc_junk_impl)\n#endif\nstatic void\nhuge_dalloc_junk(tsdn_t *tsdn, void *ptr, size_t usize)\n{\n\n\tif (config_fill && have_dss && unlikely(opt_junk_free)) {\n\t\t/*\n\t\t * Only bother junk filling if the chunk isn't about to be\n\t\t * unmapped.\n\t\t */\n\t\tif (!config_munmap || (have_dss && chunk_in_dss(tsdn, ptr)))\n\t\t\tmemset(ptr, JEMALLOC_FREE_JUNK, usize);\n\t}\n}\n#ifdef JEMALLOC_JET\n#undef huge_dalloc_junk\n#define\thuge_dalloc_junk JEMALLOC_N(huge_dalloc_junk)\nhuge_dalloc_junk_t *huge_dalloc_junk = JEMALLOC_N(huge_dalloc_junk_impl);\n#endif\n\nstatic void\nhuge_ralloc_no_move_similar(tsdn_t *tsdn, void *ptr, size_t oldsize,\n    size_t usize_min, size_t usize_max, bool zero)\n{\n\tsize_t usize, usize_next;\n\textent_node_t *node;\n\tarena_t *arena;\n\tchunk_hooks_t chunk_hooks = CHUNK_HOOKS_INITIALIZER;\n\tbool pre_zeroed, post_zeroed;\n\n\t/* Increase usize to incorporate extra. */\n\tfor (usize = usize_min; usize < usize_max && (usize_next = s2u(usize+1))\n\t    <= oldsize; usize = usize_next)\n\t\t; /* Do nothing. */\n\n\tif (oldsize == usize)\n\t\treturn;\n\n\tnode = huge_node_get(ptr);\n\tarena = extent_node_arena_get(node);\n\tpre_zeroed = extent_node_zeroed_get(node);\n\n\t/* Fill if necessary (shrinking). */\n\tif (oldsize > usize) {\n\t\tsize_t sdiff = oldsize - usize;\n\t\tif (config_fill && unlikely(opt_junk_free)) {\n\t\t\tmemset((void *)((uintptr_t)ptr + usize),\n\t\t\t    JEMALLOC_FREE_JUNK, sdiff);\n\t\t\tpost_zeroed = false;\n\t\t} else {\n\t\t\tpost_zeroed = !chunk_purge_wrapper(tsdn, arena,\n\t\t\t    &chunk_hooks, ptr, CHUNK_CEILING(oldsize), usize,\n\t\t\t    sdiff);\n\t\t}\n\t} else\n\t\tpost_zeroed = pre_zeroed;\n\n\tmalloc_mutex_lock(tsdn, &arena->huge_mtx);\n\t/* Update the size of the huge allocation. */\n\thuge_node_unset(ptr, node);\n\tassert(extent_node_size_get(node) != usize);\n\textent_node_size_set(node, usize);\n\thuge_node_reset(tsdn, ptr, node);\n\t/* Update zeroed. */\n\textent_node_zeroed_set(node, post_zeroed);\n\tmalloc_mutex_unlock(tsdn, &arena->huge_mtx);\n\n\tarena_chunk_ralloc_huge_similar(tsdn, arena, ptr, oldsize, usize);\n\n\t/* Fill if necessary (growing). */\n\tif (oldsize < usize) {\n\t\tif (zero || (config_fill && unlikely(opt_zero))) {\n\t\t\tif (!pre_zeroed) {\n\t\t\t\tmemset((void *)((uintptr_t)ptr + oldsize), 0,\n\t\t\t\t    usize - oldsize);\n\t\t\t}\n\t\t} else if (config_fill && unlikely(opt_junk_alloc)) {\n\t\t\tmemset((void *)((uintptr_t)ptr + oldsize),\n\t\t\t    JEMALLOC_ALLOC_JUNK, usize - oldsize);\n\t\t}\n\t}\n}\n\nstatic bool\nhuge_ralloc_no_move_shrink(tsdn_t *tsdn, void *ptr, size_t oldsize,\n    size_t usize)\n{\n\textent_node_t *node;\n\tarena_t *arena;\n\tchunk_hooks_t chunk_hooks;\n\tsize_t cdiff;\n\tbool pre_zeroed, post_zeroed;\n\n\tnode = huge_node_get(ptr);\n\tarena = extent_node_arena_get(node);\n\tpre_zeroed = extent_node_zeroed_get(node);\n\tchunk_hooks = chunk_hooks_get(tsdn, arena);\n\n\tassert(oldsize > usize);\n\n\t/* Split excess chunks. */\n\tcdiff = CHUNK_CEILING(oldsize) - CHUNK_CEILING(usize);\n\tif (cdiff != 0 && chunk_hooks.split(ptr, CHUNK_CEILING(oldsize),\n\t    CHUNK_CEILING(usize), cdiff, true, arena->ind))\n\t\treturn (true);\n\n\tif (oldsize > usize) {\n\t\tsize_t sdiff = oldsize - usize;\n\t\tif (config_fill && unlikely(opt_junk_free)) {\n\t\t\thuge_dalloc_junk(tsdn, (void *)((uintptr_t)ptr + usize),\n\t\t\t    sdiff);\n\t\t\tpost_zeroed = false;\n\t\t} else {\n\t\t\tpost_zeroed = !chunk_purge_wrapper(tsdn, arena,\n\t\t\t    &chunk_hooks, CHUNK_ADDR2BASE((uintptr_t)ptr +\n\t\t\t    usize), CHUNK_CEILING(oldsize),\n\t\t\t    CHUNK_ADDR2OFFSET((uintptr_t)ptr + usize), sdiff);\n\t\t}\n\t} else\n\t\tpost_zeroed = pre_zeroed;\n\n\tmalloc_mutex_lock(tsdn, &arena->huge_mtx);\n\t/* Update the size of the huge allocation. */\n\thuge_node_unset(ptr, node);\n\textent_node_size_set(node, usize);\n\thuge_node_reset(tsdn, ptr, node);\n\t/* Update zeroed. */\n\textent_node_zeroed_set(node, post_zeroed);\n\tmalloc_mutex_unlock(tsdn, &arena->huge_mtx);\n\n\t/* Zap the excess chunks. */\n\tarena_chunk_ralloc_huge_shrink(tsdn, arena, ptr, oldsize, usize);\n\n\treturn (false);\n}\n\nstatic bool\nhuge_ralloc_no_move_expand(tsdn_t *tsdn, void *ptr, size_t oldsize,\n    size_t usize, bool zero) {\n\textent_node_t *node;\n\tarena_t *arena;\n\tbool is_zeroed_subchunk, is_zeroed_chunk;\n\n\tnode = huge_node_get(ptr);\n\tarena = extent_node_arena_get(node);\n\tmalloc_mutex_lock(tsdn, &arena->huge_mtx);\n\tis_zeroed_subchunk = extent_node_zeroed_get(node);\n\tmalloc_mutex_unlock(tsdn, &arena->huge_mtx);\n\n\t/*\n\t * Use is_zeroed_chunk to detect whether the trailing memory is zeroed,\n\t * update extent's zeroed field, and zero as necessary.\n\t */\n\tis_zeroed_chunk = false;\n\tif (arena_chunk_ralloc_huge_expand(tsdn, arena, ptr, oldsize, usize,\n\t     &is_zeroed_chunk))\n\t\treturn (true);\n\n\tmalloc_mutex_lock(tsdn, &arena->huge_mtx);\n\thuge_node_unset(ptr, node);\n\textent_node_size_set(node, usize);\n\textent_node_zeroed_set(node, extent_node_zeroed_get(node) &&\n\t    is_zeroed_chunk);\n\thuge_node_reset(tsdn, ptr, node);\n\tmalloc_mutex_unlock(tsdn, &arena->huge_mtx);\n\n\tif (zero || (config_fill && unlikely(opt_zero))) {\n\t\tif (!is_zeroed_subchunk) {\n\t\t\tmemset((void *)((uintptr_t)ptr + oldsize), 0,\n\t\t\t    CHUNK_CEILING(oldsize) - oldsize);\n\t\t}\n\t\tif (!is_zeroed_chunk) {\n\t\t\tmemset((void *)((uintptr_t)ptr +\n\t\t\t    CHUNK_CEILING(oldsize)), 0, usize -\n\t\t\t    CHUNK_CEILING(oldsize));\n\t\t}\n\t} else if (config_fill && unlikely(opt_junk_alloc)) {\n\t\tmemset((void *)((uintptr_t)ptr + oldsize), JEMALLOC_ALLOC_JUNK,\n\t\t    usize - oldsize);\n\t}\n\n\treturn (false);\n}\n\nbool\nhuge_ralloc_no_move(tsdn_t *tsdn, void *ptr, size_t oldsize, size_t usize_min,\n    size_t usize_max, bool zero)\n{\n\n\tassert(s2u(oldsize) == oldsize);\n\t/* The following should have been caught by callers. */\n\tassert(usize_min > 0 && usize_max <= HUGE_MAXCLASS);\n\n\t/* Both allocations must be huge to avoid a move. */\n\tif (oldsize < chunksize || usize_max < chunksize)\n\t\treturn (true);\n\n\tif (CHUNK_CEILING(usize_max) > CHUNK_CEILING(oldsize)) {\n\t\t/* Attempt to expand the allocation in-place. */\n\t\tif (!huge_ralloc_no_move_expand(tsdn, ptr, oldsize, usize_max,\n\t\t    zero)) {\n\t\t\tarena_decay_tick(tsdn, huge_aalloc(ptr));\n\t\t\treturn (false);\n\t\t}\n\t\t/* Try again, this time with usize_min. */\n\t\tif (usize_min < usize_max && CHUNK_CEILING(usize_min) >\n\t\t    CHUNK_CEILING(oldsize) && huge_ralloc_no_move_expand(tsdn,\n\t\t    ptr, oldsize, usize_min, zero)) {\n\t\t\tarena_decay_tick(tsdn, huge_aalloc(ptr));\n\t\t\treturn (false);\n\t\t}\n\t}\n\n\t/*\n\t * Avoid moving the allocation if the existing chunk size accommodates\n\t * the new size.\n\t */\n\tif (CHUNK_CEILING(oldsize) >= CHUNK_CEILING(usize_min)\n\t    && CHUNK_CEILING(oldsize) <= CHUNK_CEILING(usize_max)) {\n\t\thuge_ralloc_no_move_similar(tsdn, ptr, oldsize, usize_min,\n\t\t    usize_max, zero);\n\t\tarena_decay_tick(tsdn, huge_aalloc(ptr));\n\t\treturn (false);\n\t}\n\n\t/* Attempt to shrink the allocation in-place. */\n\tif (CHUNK_CEILING(oldsize) > CHUNK_CEILING(usize_max)) {\n\t\tif (!huge_ralloc_no_move_shrink(tsdn, ptr, oldsize,\n\t\t    usize_max)) {\n\t\t\tarena_decay_tick(tsdn, huge_aalloc(ptr));\n\t\t\treturn (false);\n\t\t}\n\t}\n\treturn (true);\n}\n\nstatic void *\nhuge_ralloc_move_helper(tsdn_t *tsdn, arena_t *arena, size_t usize,\n    size_t alignment, bool zero)\n{\n\n\tif (alignment <= chunksize)\n\t\treturn (huge_malloc(tsdn, arena, usize, zero));\n\treturn (huge_palloc(tsdn, arena, usize, alignment, zero));\n}\n\nvoid *\nhuge_ralloc(tsd_t *tsd, arena_t *arena, void *ptr, size_t oldsize,\n    size_t usize, size_t alignment, bool zero, tcache_t *tcache)\n{\n\tvoid *ret;\n\tsize_t copysize;\n\n\t/* The following should have been caught by callers. */\n\tassert(usize > 0 && usize <= HUGE_MAXCLASS);\n\n\t/* Try to avoid moving the allocation. */\n\tif (!huge_ralloc_no_move(tsd_tsdn(tsd), ptr, oldsize, usize, usize,\n\t    zero))\n\t\treturn (ptr);\n\n\t/*\n\t * usize and oldsize are different enough that we need to use a\n\t * different size class.  In that case, fall back to allocating new\n\t * space and copying.\n\t */\n\tret = huge_ralloc_move_helper(tsd_tsdn(tsd), arena, usize, alignment,\n\t    zero);\n\tif (ret == NULL)\n\t\treturn (NULL);\n\n\tcopysize = (usize < oldsize) ? usize : oldsize;\n\tmemcpy(ret, ptr, copysize);\n\tisqalloc(tsd, ptr, oldsize, tcache, true);\n\treturn (ret);\n}\n\nvoid\nhuge_dalloc(tsdn_t *tsdn, void *ptr)\n{\n\textent_node_t *node;\n\tarena_t *arena;\n\n\tnode = huge_node_get(ptr);\n\tarena = extent_node_arena_get(node);\n\thuge_node_unset(ptr, node);\n\tmalloc_mutex_lock(tsdn, &arena->huge_mtx);\n\tql_remove(&arena->huge, node, ql_link);\n\tmalloc_mutex_unlock(tsdn, &arena->huge_mtx);\n\n\thuge_dalloc_junk(tsdn, extent_node_addr_get(node),\n\t    extent_node_size_get(node));\n\tarena_chunk_dalloc_huge(tsdn, extent_node_arena_get(node),\n\t    extent_node_addr_get(node), extent_node_size_get(node));\n\tidalloctm(tsdn, node, NULL, true, true);\n\n\tarena_decay_tick(tsdn, arena);\n}\n\narena_t *\nhuge_aalloc(const void *ptr)\n{\n\n\treturn (extent_node_arena_get(huge_node_get(ptr)));\n}\n\nsize_t\nhuge_salloc(tsdn_t *tsdn, const void *ptr)\n{\n\tsize_t size;\n\textent_node_t *node;\n\tarena_t *arena;\n\n\tnode = huge_node_get(ptr);\n\tarena = extent_node_arena_get(node);\n\tmalloc_mutex_lock(tsdn, &arena->huge_mtx);\n\tsize = extent_node_size_get(node);\n\tmalloc_mutex_unlock(tsdn, &arena->huge_mtx);\n\n\treturn (size);\n}\n\nprof_tctx_t *\nhuge_prof_tctx_get(tsdn_t *tsdn, const void *ptr)\n{\n\tprof_tctx_t *tctx;\n\textent_node_t *node;\n\tarena_t *arena;\n\n\tnode = huge_node_get(ptr);\n\tarena = extent_node_arena_get(node);\n\tmalloc_mutex_lock(tsdn, &arena->huge_mtx);\n\ttctx = extent_node_prof_tctx_get(node);\n\tmalloc_mutex_unlock(tsdn, &arena->huge_mtx);\n\n\treturn (tctx);\n}\n\nvoid\nhuge_prof_tctx_set(tsdn_t *tsdn, const void *ptr, prof_tctx_t *tctx)\n{\n\textent_node_t *node;\n\tarena_t *arena;\n\n\tnode = huge_node_get(ptr);\n\tarena = extent_node_arena_get(node);\n\tmalloc_mutex_lock(tsdn, &arena->huge_mtx);\n\textent_node_prof_tctx_set(node, tctx);\n\tmalloc_mutex_unlock(tsdn, &arena->huge_mtx);\n}\n\nvoid\nhuge_prof_tctx_reset(tsdn_t *tsdn, const void *ptr)\n{\n\n\thuge_prof_tctx_set(tsdn, ptr, (prof_tctx_t *)(uintptr_t)1U);\n}\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/deps/jemalloc/src/jemalloc.c",
    "content": "#define\tJEMALLOC_C_\n#include \"jemalloc/internal/jemalloc_internal.h\"\n\n/******************************************************************************/\n/* Data. */\n\n/* Runtime configuration options. */\nconst char\t*je_malloc_conf JEMALLOC_ATTR(weak);\nbool\topt_abort =\n#ifdef JEMALLOC_DEBUG\n    true\n#else\n    false\n#endif\n    ;\nconst char\t*opt_junk =\n#if (defined(JEMALLOC_DEBUG) && defined(JEMALLOC_FILL))\n    \"true\"\n#else\n    \"false\"\n#endif\n    ;\nbool\topt_junk_alloc =\n#if (defined(JEMALLOC_DEBUG) && defined(JEMALLOC_FILL))\n    true\n#else\n    false\n#endif\n    ;\nbool\topt_junk_free =\n#if (defined(JEMALLOC_DEBUG) && defined(JEMALLOC_FILL))\n    true\n#else\n    false\n#endif\n    ;\n\nsize_t\topt_quarantine = ZU(0);\nbool\topt_redzone = false;\nbool\topt_utrace = false;\nbool\topt_xmalloc = false;\nbool\topt_zero = false;\nunsigned\topt_narenas = 0;\n\n/* Initialized to true if the process is running inside Valgrind. */\nbool\tin_valgrind;\n\nunsigned\tncpus;\n\n/* Protects arenas initialization. */\nstatic malloc_mutex_t\tarenas_lock;\n/*\n * Arenas that are used to service external requests.  Not all elements of the\n * arenas array are necessarily used; arenas are created lazily as needed.\n *\n * arenas[0..narenas_auto) are used for automatic multiplexing of threads and\n * arenas.  arenas[narenas_auto..narenas_total) are only used if the application\n * takes some action to create them and allocate from them.\n */\narena_t\t\t\t**arenas;\nstatic unsigned\t\tnarenas_total; /* Use narenas_total_*(). */\nstatic arena_t\t\t*a0; /* arenas[0]; read-only after initialization. */\nunsigned\t\tnarenas_auto; /* Read-only after initialization. */\n\ntypedef enum {\n\tmalloc_init_uninitialized\t= 3,\n\tmalloc_init_a0_initialized\t= 2,\n\tmalloc_init_recursible\t\t= 1,\n\tmalloc_init_initialized\t\t= 0 /* Common case --> jnz. */\n} malloc_init_t;\nstatic malloc_init_t\tmalloc_init_state = malloc_init_uninitialized;\n\n/* False should be the common case.  Set to true to trigger initialization. */\nstatic bool\tmalloc_slow = true;\n\n/* When malloc_slow is true, set the corresponding bits for sanity check. */\nenum {\n\tflag_opt_junk_alloc\t= (1U),\n\tflag_opt_junk_free\t= (1U << 1),\n\tflag_opt_quarantine\t= (1U << 2),\n\tflag_opt_zero\t\t= (1U << 3),\n\tflag_opt_utrace\t\t= (1U << 4),\n\tflag_in_valgrind\t= (1U << 5),\n\tflag_opt_xmalloc\t= (1U << 6)\n};\nstatic uint8_t\tmalloc_slow_flags;\n\n/* Last entry for overflow detection only.  */\nJEMALLOC_ALIGNED(CACHELINE)\nconst size_t\tindex2size_tab[NSIZES+1] = {\n#define\tSC(index, lg_grp, lg_delta, ndelta, bin, lg_delta_lookup) \\\n\t((ZU(1)<<lg_grp) + (ZU(ndelta)<<lg_delta)),\n\tSIZE_CLASSES\n#undef SC\n\tZU(0)\n};\n\nJEMALLOC_ALIGNED(CACHELINE)\nconst uint8_t\tsize2index_tab[] = {\n#if LG_TINY_MIN == 0\n#warning \"Dangerous LG_TINY_MIN\"\n#define\tS2B_0(i)\ti,\n#elif LG_TINY_MIN == 1\n#warning \"Dangerous LG_TINY_MIN\"\n#define\tS2B_1(i)\ti,\n#elif LG_TINY_MIN == 2\n#warning \"Dangerous LG_TINY_MIN\"\n#define\tS2B_2(i)\ti,\n#elif LG_TINY_MIN == 3\n#define\tS2B_3(i)\ti,\n#elif LG_TINY_MIN == 4\n#define\tS2B_4(i)\ti,\n#elif LG_TINY_MIN == 5\n#define\tS2B_5(i)\ti,\n#elif LG_TINY_MIN == 6\n#define\tS2B_6(i)\ti,\n#elif LG_TINY_MIN == 7\n#define\tS2B_7(i)\ti,\n#elif LG_TINY_MIN == 8\n#define\tS2B_8(i)\ti,\n#elif LG_TINY_MIN == 9\n#define\tS2B_9(i)\ti,\n#elif LG_TINY_MIN == 10\n#define\tS2B_10(i)\ti,\n#elif LG_TINY_MIN == 11\n#define\tS2B_11(i)\ti,\n#else\n#error \"Unsupported LG_TINY_MIN\"\n#endif\n#if LG_TINY_MIN < 1\n#define\tS2B_1(i)\tS2B_0(i) S2B_0(i)\n#endif\n#if LG_TINY_MIN < 2\n#define\tS2B_2(i)\tS2B_1(i) S2B_1(i)\n#endif\n#if LG_TINY_MIN < 3\n#define\tS2B_3(i)\tS2B_2(i) S2B_2(i)\n#endif\n#if LG_TINY_MIN < 4\n#define\tS2B_4(i)\tS2B_3(i) S2B_3(i)\n#endif\n#if LG_TINY_MIN < 5\n#define\tS2B_5(i)\tS2B_4(i) S2B_4(i)\n#endif\n#if LG_TINY_MIN < 6\n#define\tS2B_6(i)\tS2B_5(i) S2B_5(i)\n#endif\n#if LG_TINY_MIN < 7\n#define\tS2B_7(i)\tS2B_6(i) S2B_6(i)\n#endif\n#if LG_TINY_MIN < 8\n#define\tS2B_8(i)\tS2B_7(i) S2B_7(i)\n#endif\n#if LG_TINY_MIN < 9\n#define\tS2B_9(i)\tS2B_8(i) S2B_8(i)\n#endif\n#if LG_TINY_MIN < 10\n#define\tS2B_10(i)\tS2B_9(i) S2B_9(i)\n#endif\n#if LG_TINY_MIN < 11\n#define\tS2B_11(i)\tS2B_10(i) S2B_10(i)\n#endif\n#define\tS2B_no(i)\n#define\tSC(index, lg_grp, lg_delta, ndelta, bin, lg_delta_lookup) \\\n\tS2B_##lg_delta_lookup(index)\n\tSIZE_CLASSES\n#undef S2B_3\n#undef S2B_4\n#undef S2B_5\n#undef S2B_6\n#undef S2B_7\n#undef S2B_8\n#undef S2B_9\n#undef S2B_10\n#undef S2B_11\n#undef S2B_no\n#undef SC\n};\n\n#ifdef JEMALLOC_THREADED_INIT\n/* Used to let the initializing thread recursively allocate. */\n#  define NO_INITIALIZER\t((unsigned long)0)\n#  define INITIALIZER\t\tpthread_self()\n#  define IS_INITIALIZER\t(malloc_initializer == pthread_self())\nstatic pthread_t\t\tmalloc_initializer = NO_INITIALIZER;\n#else\n#  define NO_INITIALIZER\tfalse\n#  define INITIALIZER\t\ttrue\n#  define IS_INITIALIZER\tmalloc_initializer\nstatic bool\t\t\tmalloc_initializer = NO_INITIALIZER;\n#endif\n\n/* Used to avoid initialization races. */\n#ifdef _WIN32\n#if _WIN32_WINNT >= 0x0600\nstatic malloc_mutex_t\tinit_lock = SRWLOCK_INIT;\n#else\nstatic malloc_mutex_t\tinit_lock;\nstatic bool init_lock_initialized = false;\n\nJEMALLOC_ATTR(constructor)\nstatic void WINAPI\n_init_init_lock(void)\n{\n\n\t/* If another constructor in the same binary is using mallctl to\n\t * e.g. setup chunk hooks, it may end up running before this one,\n\t * and malloc_init_hard will crash trying to lock the uninitialized\n\t * lock. So we force an initialization of the lock in\n\t * malloc_init_hard as well. We don't try to care about atomicity\n\t * of the accessed to the init_lock_initialized boolean, since it\n\t * really only matters early in the process creation, before any\n\t * separate thread normally starts doing anything. */\n\tif (!init_lock_initialized)\n\t\tmalloc_mutex_init(&init_lock, \"init\", WITNESS_RANK_INIT);\n\tinit_lock_initialized = true;\n}\n\n#ifdef _MSC_VER\n#  pragma section(\".CRT$XCU\", read)\nJEMALLOC_SECTION(\".CRT$XCU\") JEMALLOC_ATTR(used)\nstatic const void (WINAPI *init_init_lock)(void) = _init_init_lock;\n#endif\n#endif\n#else\nstatic malloc_mutex_t\tinit_lock = MALLOC_MUTEX_INITIALIZER;\n#endif\n\ntypedef struct {\n\tvoid\t*p;\t/* Input pointer (as in realloc(p, s)). */\n\tsize_t\ts;\t/* Request size. */\n\tvoid\t*r;\t/* Result pointer. */\n} malloc_utrace_t;\n\n#ifdef JEMALLOC_UTRACE\n#  define UTRACE(a, b, c) do {\t\t\t\t\t\t\\\n\tif (unlikely(opt_utrace)) {\t\t\t\t\t\\\n\t\tint utrace_serrno = errno;\t\t\t\t\\\n\t\tmalloc_utrace_t ut;\t\t\t\t\t\\\n\t\tut.p = (a);\t\t\t\t\t\t\\\n\t\tut.s = (b);\t\t\t\t\t\t\\\n\t\tut.r = (c);\t\t\t\t\t\t\\\n\t\tutrace(&ut, sizeof(ut));\t\t\t\t\\\n\t\terrno = utrace_serrno;\t\t\t\t\t\\\n\t}\t\t\t\t\t\t\t\t\\\n} while (0)\n#else\n#  define UTRACE(a, b, c)\n#endif\n\n/******************************************************************************/\n/*\n * Function prototypes for static functions that are referenced prior to\n * definition.\n */\n\nstatic bool\tmalloc_init_hard_a0(void);\nstatic bool\tmalloc_init_hard(void);\n\n/******************************************************************************/\n/*\n * Begin miscellaneous support functions.\n */\n\nJEMALLOC_ALWAYS_INLINE_C bool\nmalloc_initialized(void)\n{\n\n\treturn (malloc_init_state == malloc_init_initialized);\n}\n\nJEMALLOC_ALWAYS_INLINE_C void\nmalloc_thread_init(void)\n{\n\n\t/*\n\t * TSD initialization can't be safely done as a side effect of\n\t * deallocation, because it is possible for a thread to do nothing but\n\t * deallocate its TLS data via free(), in which case writing to TLS\n\t * would cause write-after-free memory corruption.  The quarantine\n\t * facility *only* gets used as a side effect of deallocation, so make\n\t * a best effort attempt at initializing its TSD by hooking all\n\t * allocation events.\n\t */\n\tif (config_fill && unlikely(opt_quarantine))\n\t\tquarantine_alloc_hook();\n}\n\nJEMALLOC_ALWAYS_INLINE_C bool\nmalloc_init_a0(void)\n{\n\n\tif (unlikely(malloc_init_state == malloc_init_uninitialized))\n\t\treturn (malloc_init_hard_a0());\n\treturn (false);\n}\n\nJEMALLOC_ALWAYS_INLINE_C bool\nmalloc_init(void)\n{\n\n\tif (unlikely(!malloc_initialized()) && malloc_init_hard())\n\t\treturn (true);\n\tmalloc_thread_init();\n\n\treturn (false);\n}\n\n/*\n * The a0*() functions are used instead of i{d,}alloc() in situations that\n * cannot tolerate TLS variable access.\n */\n\nstatic void *\na0ialloc(size_t size, bool zero, bool is_metadata)\n{\n\n\tif (unlikely(malloc_init_a0()))\n\t\treturn (NULL);\n\n\treturn (iallocztm(TSDN_NULL, size, size2index(size), zero, NULL,\n\t    is_metadata, arena_get(TSDN_NULL, 0, true), true));\n}\n\nstatic void\na0idalloc(void *ptr, bool is_metadata)\n{\n\n\tidalloctm(TSDN_NULL, ptr, false, is_metadata, true);\n}\n\nvoid *\na0malloc(size_t size)\n{\n\n\treturn (a0ialloc(size, false, true));\n}\n\nvoid\na0dalloc(void *ptr)\n{\n\n\ta0idalloc(ptr, true);\n}\n\n/*\n * FreeBSD's libc uses the bootstrap_*() functions in bootstrap-senstive\n * situations that cannot tolerate TLS variable access (TLS allocation and very\n * early internal data structure initialization).\n */\n\nvoid *\nbootstrap_malloc(size_t size)\n{\n\n\tif (unlikely(size == 0))\n\t\tsize = 1;\n\n\treturn (a0ialloc(size, false, false));\n}\n\nvoid *\nbootstrap_calloc(size_t num, size_t size)\n{\n\tsize_t num_size;\n\n\tnum_size = num * size;\n\tif (unlikely(num_size == 0)) {\n\t\tassert(num == 0 || size == 0);\n\t\tnum_size = 1;\n\t}\n\n\treturn (a0ialloc(num_size, true, false));\n}\n\nvoid\nbootstrap_free(void *ptr)\n{\n\n\tif (unlikely(ptr == NULL))\n\t\treturn;\n\n\ta0idalloc(ptr, false);\n}\n\nstatic void\narena_set(unsigned ind, arena_t *arena)\n{\n\n\tatomic_write_p((void **)&arenas[ind], arena);\n}\n\nstatic void\nnarenas_total_set(unsigned narenas)\n{\n\n\tatomic_write_u(&narenas_total, narenas);\n}\n\nstatic void\nnarenas_total_inc(void)\n{\n\n\tatomic_add_u(&narenas_total, 1);\n}\n\nunsigned\nnarenas_total_get(void)\n{\n\n\treturn (atomic_read_u(&narenas_total));\n}\n\n/* Create a new arena and insert it into the arenas array at index ind. */\nstatic arena_t *\narena_init_locked(tsdn_t *tsdn, unsigned ind)\n{\n\tarena_t *arena;\n\n\tassert(ind <= narenas_total_get());\n\tif (ind > MALLOCX_ARENA_MAX)\n\t\treturn (NULL);\n\tif (ind == narenas_total_get())\n\t\tnarenas_total_inc();\n\n\t/*\n\t * Another thread may have already initialized arenas[ind] if it's an\n\t * auto arena.\n\t */\n\tarena = arena_get(tsdn, ind, false);\n\tif (arena != NULL) {\n\t\tassert(ind < narenas_auto);\n\t\treturn (arena);\n\t}\n\n\t/* Actually initialize the arena. */\n\tarena = arena_new(tsdn, ind);\n\tarena_set(ind, arena);\n\treturn (arena);\n}\n\narena_t *\narena_init(tsdn_t *tsdn, unsigned ind)\n{\n\tarena_t *arena;\n\n\tmalloc_mutex_lock(tsdn, &arenas_lock);\n\tarena = arena_init_locked(tsdn, ind);\n\tmalloc_mutex_unlock(tsdn, &arenas_lock);\n\treturn (arena);\n}\n\nstatic void\narena_bind(tsd_t *tsd, unsigned ind, bool internal)\n{\n\tarena_t *arena;\n\n\tarena = arena_get(tsd_tsdn(tsd), ind, false);\n\tarena_nthreads_inc(arena, internal);\n\n\tif (tsd_nominal(tsd)) {\n\t\tif (internal)\n\t\t\ttsd_iarena_set(tsd, arena);\n\t\telse\n\t\t\ttsd_arena_set(tsd, arena);\n\t}\n}\n\nvoid\narena_migrate(tsd_t *tsd, unsigned oldind, unsigned newind)\n{\n\tarena_t *oldarena, *newarena;\n\n\toldarena = arena_get(tsd_tsdn(tsd), oldind, false);\n\tnewarena = arena_get(tsd_tsdn(tsd), newind, false);\n\tarena_nthreads_dec(oldarena, false);\n\tarena_nthreads_inc(newarena, false);\n\ttsd_arena_set(tsd, newarena);\n}\n\nstatic void\narena_unbind(tsd_t *tsd, unsigned ind, bool internal)\n{\n\tarena_t *arena;\n\n\tarena = arena_get(tsd_tsdn(tsd), ind, false);\n\tarena_nthreads_dec(arena, internal);\n\tif (internal)\n\t\ttsd_iarena_set(tsd, NULL);\n\telse\n\t\ttsd_arena_set(tsd, NULL);\n}\n\narena_tdata_t *\narena_tdata_get_hard(tsd_t *tsd, unsigned ind)\n{\n\tarena_tdata_t *tdata, *arenas_tdata_old;\n\tarena_tdata_t *arenas_tdata = tsd_arenas_tdata_get(tsd);\n\tunsigned narenas_tdata_old, i;\n\tunsigned narenas_tdata = tsd_narenas_tdata_get(tsd);\n\tunsigned narenas_actual = narenas_total_get();\n\n\t/*\n\t * Dissociate old tdata array (and set up for deallocation upon return)\n\t * if it's too small.\n\t */\n\tif (arenas_tdata != NULL && narenas_tdata < narenas_actual) {\n\t\tarenas_tdata_old = arenas_tdata;\n\t\tnarenas_tdata_old = narenas_tdata;\n\t\tarenas_tdata = NULL;\n\t\tnarenas_tdata = 0;\n\t\ttsd_arenas_tdata_set(tsd, arenas_tdata);\n\t\ttsd_narenas_tdata_set(tsd, narenas_tdata);\n\t} else {\n\t\tarenas_tdata_old = NULL;\n\t\tnarenas_tdata_old = 0;\n\t}\n\n\t/* Allocate tdata array if it's missing. */\n\tif (arenas_tdata == NULL) {\n\t\tbool *arenas_tdata_bypassp = tsd_arenas_tdata_bypassp_get(tsd);\n\t\tnarenas_tdata = (ind < narenas_actual) ? narenas_actual : ind+1;\n\n\t\tif (tsd_nominal(tsd) && !*arenas_tdata_bypassp) {\n\t\t\t*arenas_tdata_bypassp = true;\n\t\t\tarenas_tdata = (arena_tdata_t *)a0malloc(\n\t\t\t    sizeof(arena_tdata_t) * narenas_tdata);\n\t\t\t*arenas_tdata_bypassp = false;\n\t\t}\n\t\tif (arenas_tdata == NULL) {\n\t\t\ttdata = NULL;\n\t\t\tgoto label_return;\n\t\t}\n\t\tassert(tsd_nominal(tsd) && !*arenas_tdata_bypassp);\n\t\ttsd_arenas_tdata_set(tsd, arenas_tdata);\n\t\ttsd_narenas_tdata_set(tsd, narenas_tdata);\n\t}\n\n\t/*\n\t * Copy to tdata array.  It's possible that the actual number of arenas\n\t * has increased since narenas_total_get() was called above, but that\n\t * causes no correctness issues unless two threads concurrently execute\n\t * the arenas.extend mallctl, which we trust mallctl synchronization to\n\t * prevent.\n\t */\n\n\t/* Copy/initialize tickers. */\n\tfor (i = 0; i < narenas_actual; i++) {\n\t\tif (i < narenas_tdata_old) {\n\t\t\tticker_copy(&arenas_tdata[i].decay_ticker,\n\t\t\t    &arenas_tdata_old[i].decay_ticker);\n\t\t} else {\n\t\t\tticker_init(&arenas_tdata[i].decay_ticker,\n\t\t\t    DECAY_NTICKS_PER_UPDATE);\n\t\t}\n\t}\n\tif (narenas_tdata > narenas_actual) {\n\t\tmemset(&arenas_tdata[narenas_actual], 0, sizeof(arena_tdata_t)\n\t\t    * (narenas_tdata - narenas_actual));\n\t}\n\n\t/* Read the refreshed tdata array. */\n\ttdata = &arenas_tdata[ind];\nlabel_return:\n\tif (arenas_tdata_old != NULL)\n\t\ta0dalloc(arenas_tdata_old);\n\treturn (tdata);\n}\n\n/* Slow path, called only by arena_choose(). */\narena_t *\narena_choose_hard(tsd_t *tsd, bool internal)\n{\n\tarena_t *ret JEMALLOC_CC_SILENCE_INIT(NULL);\n\n\tif (narenas_auto > 1) {\n\t\tunsigned i, j, choose[2], first_null;\n\n\t\t/*\n\t\t * Determine binding for both non-internal and internal\n\t\t * allocation.\n\t\t *\n\t\t *   choose[0]: For application allocation.\n\t\t *   choose[1]: For internal metadata allocation.\n\t\t */\n\n\t\tfor (j = 0; j < 2; j++)\n\t\t\tchoose[j] = 0;\n\n\t\tfirst_null = narenas_auto;\n\t\tmalloc_mutex_lock(tsd_tsdn(tsd), &arenas_lock);\n\t\tassert(arena_get(tsd_tsdn(tsd), 0, false) != NULL);\n\t\tfor (i = 1; i < narenas_auto; i++) {\n\t\t\tif (arena_get(tsd_tsdn(tsd), i, false) != NULL) {\n\t\t\t\t/*\n\t\t\t\t * Choose the first arena that has the lowest\n\t\t\t\t * number of threads assigned to it.\n\t\t\t\t */\n\t\t\t\tfor (j = 0; j < 2; j++) {\n\t\t\t\t\tif (arena_nthreads_get(arena_get(\n\t\t\t\t\t    tsd_tsdn(tsd), i, false), !!j) <\n\t\t\t\t\t    arena_nthreads_get(arena_get(\n\t\t\t\t\t    tsd_tsdn(tsd), choose[j], false),\n\t\t\t\t\t    !!j))\n\t\t\t\t\t\tchoose[j] = i;\n\t\t\t\t}\n\t\t\t} else if (first_null == narenas_auto) {\n\t\t\t\t/*\n\t\t\t\t * Record the index of the first uninitialized\n\t\t\t\t * arena, in case all extant arenas are in use.\n\t\t\t\t *\n\t\t\t\t * NB: It is possible for there to be\n\t\t\t\t * discontinuities in terms of initialized\n\t\t\t\t * versus uninitialized arenas, due to the\n\t\t\t\t * \"thread.arena\" mallctl.\n\t\t\t\t */\n\t\t\t\tfirst_null = i;\n\t\t\t}\n\t\t}\n\n\t\tfor (j = 0; j < 2; j++) {\n\t\t\tif (arena_nthreads_get(arena_get(tsd_tsdn(tsd),\n\t\t\t    choose[j], false), !!j) == 0 || first_null ==\n\t\t\t    narenas_auto) {\n\t\t\t\t/*\n\t\t\t\t * Use an unloaded arena, or the least loaded\n\t\t\t\t * arena if all arenas are already initialized.\n\t\t\t\t */\n\t\t\t\tif (!!j == internal) {\n\t\t\t\t\tret = arena_get(tsd_tsdn(tsd),\n\t\t\t\t\t    choose[j], false);\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tarena_t *arena;\n\n\t\t\t\t/* Initialize a new arena. */\n\t\t\t\tchoose[j] = first_null;\n\t\t\t\tarena = arena_init_locked(tsd_tsdn(tsd),\n\t\t\t\t    choose[j]);\n\t\t\t\tif (arena == NULL) {\n\t\t\t\t\tmalloc_mutex_unlock(tsd_tsdn(tsd),\n\t\t\t\t\t    &arenas_lock);\n\t\t\t\t\treturn (NULL);\n\t\t\t\t}\n\t\t\t\tif (!!j == internal)\n\t\t\t\t\tret = arena;\n\t\t\t}\n\t\t\tarena_bind(tsd, choose[j], !!j);\n\t\t}\n\t\tmalloc_mutex_unlock(tsd_tsdn(tsd), &arenas_lock);\n\t} else {\n\t\tret = arena_get(tsd_tsdn(tsd), 0, false);\n\t\tarena_bind(tsd, 0, false);\n\t\tarena_bind(tsd, 0, true);\n\t}\n\n\treturn (ret);\n}\n\nvoid\nthread_allocated_cleanup(tsd_t *tsd)\n{\n\n\t/* Do nothing. */\n}\n\nvoid\nthread_deallocated_cleanup(tsd_t *tsd)\n{\n\n\t/* Do nothing. */\n}\n\nvoid\niarena_cleanup(tsd_t *tsd)\n{\n\tarena_t *iarena;\n\n\tiarena = tsd_iarena_get(tsd);\n\tif (iarena != NULL)\n\t\tarena_unbind(tsd, iarena->ind, true);\n}\n\nvoid\narena_cleanup(tsd_t *tsd)\n{\n\tarena_t *arena;\n\n\tarena = tsd_arena_get(tsd);\n\tif (arena != NULL)\n\t\tarena_unbind(tsd, arena->ind, false);\n}\n\nvoid\narenas_tdata_cleanup(tsd_t *tsd)\n{\n\tarena_tdata_t *arenas_tdata;\n\n\t/* Prevent tsd->arenas_tdata from being (re)created. */\n\t*tsd_arenas_tdata_bypassp_get(tsd) = true;\n\n\tarenas_tdata = tsd_arenas_tdata_get(tsd);\n\tif (arenas_tdata != NULL) {\n\t\ttsd_arenas_tdata_set(tsd, NULL);\n\t\ta0dalloc(arenas_tdata);\n\t}\n}\n\nvoid\nnarenas_tdata_cleanup(tsd_t *tsd)\n{\n\n\t/* Do nothing. */\n}\n\nvoid\narenas_tdata_bypass_cleanup(tsd_t *tsd)\n{\n\n\t/* Do nothing. */\n}\n\nstatic void\nstats_print_atexit(void)\n{\n\n\tif (config_tcache && config_stats) {\n\t\ttsdn_t *tsdn;\n\t\tunsigned narenas, i;\n\n\t\ttsdn = tsdn_fetch();\n\n\t\t/*\n\t\t * Merge stats from extant threads.  This is racy, since\n\t\t * individual threads do not lock when recording tcache stats\n\t\t * events.  As a consequence, the final stats may be slightly\n\t\t * out of date by the time they are reported, if other threads\n\t\t * continue to allocate.\n\t\t */\n\t\tfor (i = 0, narenas = narenas_total_get(); i < narenas; i++) {\n\t\t\tarena_t *arena = arena_get(tsdn, i, false);\n\t\t\tif (arena != NULL) {\n\t\t\t\ttcache_t *tcache;\n\n\t\t\t\t/*\n\t\t\t\t * tcache_stats_merge() locks bins, so if any\n\t\t\t\t * code is introduced that acquires both arena\n\t\t\t\t * and bin locks in the opposite order,\n\t\t\t\t * deadlocks may result.\n\t\t\t\t */\n\t\t\t\tmalloc_mutex_lock(tsdn, &arena->lock);\n\t\t\t\tql_foreach(tcache, &arena->tcache_ql, link) {\n\t\t\t\t\ttcache_stats_merge(tsdn, tcache, arena);\n\t\t\t\t}\n\t\t\t\tmalloc_mutex_unlock(tsdn, &arena->lock);\n\t\t\t}\n\t\t}\n\t}\n\tje_malloc_stats_print(NULL, NULL, NULL);\n}\n\n/*\n * End miscellaneous support functions.\n */\n/******************************************************************************/\n/*\n * Begin initialization functions.\n */\n\n#ifndef JEMALLOC_HAVE_SECURE_GETENV\nstatic char *\nsecure_getenv(const char *name)\n{\n\n#  ifdef JEMALLOC_HAVE_ISSETUGID\n\tif (issetugid() != 0)\n\t\treturn (NULL);\n#  endif\n\treturn (getenv(name));\n}\n#endif\n\nstatic unsigned\nmalloc_ncpus(void)\n{\n\tlong result;\n\n#ifdef _WIN32\n\tSYSTEM_INFO si;\n\tGetSystemInfo(&si);\n\tresult = si.dwNumberOfProcessors;\n#else\n\tresult = sysconf(_SC_NPROCESSORS_ONLN);\n#endif\n\treturn ((result == -1) ? 1 : (unsigned)result);\n}\n\nstatic bool\nmalloc_conf_next(char const **opts_p, char const **k_p, size_t *klen_p,\n    char const **v_p, size_t *vlen_p)\n{\n\tbool accept;\n\tconst char *opts = *opts_p;\n\n\t*k_p = opts;\n\n\tfor (accept = false; !accept;) {\n\t\tswitch (*opts) {\n\t\tcase 'A': case 'B': case 'C': case 'D': case 'E': case 'F':\n\t\tcase 'G': case 'H': case 'I': case 'J': case 'K': case 'L':\n\t\tcase 'M': case 'N': case 'O': case 'P': case 'Q': case 'R':\n\t\tcase 'S': case 'T': case 'U': case 'V': case 'W': case 'X':\n\t\tcase 'Y': case 'Z':\n\t\tcase 'a': case 'b': case 'c': case 'd': case 'e': case 'f':\n\t\tcase 'g': case 'h': case 'i': case 'j': case 'k': case 'l':\n\t\tcase 'm': case 'n': case 'o': case 'p': case 'q': case 'r':\n\t\tcase 's': case 't': case 'u': case 'v': case 'w': case 'x':\n\t\tcase 'y': case 'z':\n\t\tcase '0': case '1': case '2': case '3': case '4': case '5':\n\t\tcase '6': case '7': case '8': case '9':\n\t\tcase '_':\n\t\t\topts++;\n\t\t\tbreak;\n\t\tcase ':':\n\t\t\topts++;\n\t\t\t*klen_p = (uintptr_t)opts - 1 - (uintptr_t)*k_p;\n\t\t\t*v_p = opts;\n\t\t\taccept = true;\n\t\t\tbreak;\n\t\tcase '\\0':\n\t\t\tif (opts != *opts_p) {\n\t\t\t\tmalloc_write(\"<jemalloc>: Conf string ends \"\n\t\t\t\t    \"with key\\n\");\n\t\t\t}\n\t\t\treturn (true);\n\t\tdefault:\n\t\t\tmalloc_write(\"<jemalloc>: Malformed conf string\\n\");\n\t\t\treturn (true);\n\t\t}\n\t}\n\n\tfor (accept = false; !accept;) {\n\t\tswitch (*opts) {\n\t\tcase ',':\n\t\t\topts++;\n\t\t\t/*\n\t\t\t * Look ahead one character here, because the next time\n\t\t\t * this function is called, it will assume that end of\n\t\t\t * input has been cleanly reached if no input remains,\n\t\t\t * but we have optimistically already consumed the\n\t\t\t * comma if one exists.\n\t\t\t */\n\t\t\tif (*opts == '\\0') {\n\t\t\t\tmalloc_write(\"<jemalloc>: Conf string ends \"\n\t\t\t\t    \"with comma\\n\");\n\t\t\t}\n\t\t\t*vlen_p = (uintptr_t)opts - 1 - (uintptr_t)*v_p;\n\t\t\taccept = true;\n\t\t\tbreak;\n\t\tcase '\\0':\n\t\t\t*vlen_p = (uintptr_t)opts - (uintptr_t)*v_p;\n\t\t\taccept = true;\n\t\t\tbreak;\n\t\tdefault:\n\t\t\topts++;\n\t\t\tbreak;\n\t\t}\n\t}\n\n\t*opts_p = opts;\n\treturn (false);\n}\n\nstatic void\nmalloc_conf_error(const char *msg, const char *k, size_t klen, const char *v,\n    size_t vlen)\n{\n\n\tmalloc_printf(\"<jemalloc>: %s: %.*s:%.*s\\n\", msg, (int)klen, k,\n\t    (int)vlen, v);\n}\n\nstatic void\nmalloc_slow_flag_init(void)\n{\n\t/*\n\t * Combine the runtime options into malloc_slow for fast path.  Called\n\t * after processing all the options.\n\t */\n\tmalloc_slow_flags |= (opt_junk_alloc ? flag_opt_junk_alloc : 0)\n\t    | (opt_junk_free ? flag_opt_junk_free : 0)\n\t    | (opt_quarantine ? flag_opt_quarantine : 0)\n\t    | (opt_zero ? flag_opt_zero : 0)\n\t    | (opt_utrace ? flag_opt_utrace : 0)\n\t    | (opt_xmalloc ? flag_opt_xmalloc : 0);\n\n\tif (config_valgrind)\n\t\tmalloc_slow_flags |= (in_valgrind ? flag_in_valgrind : 0);\n\n\tmalloc_slow = (malloc_slow_flags != 0);\n}\n\nstatic void\nmalloc_conf_init(void)\n{\n\tunsigned i;\n\tchar buf[PATH_MAX + 1];\n\tconst char *opts, *k, *v;\n\tsize_t klen, vlen;\n\n\t/*\n\t * Automatically configure valgrind before processing options.  The\n\t * valgrind option remains in jemalloc 3.x for compatibility reasons.\n\t */\n\tif (config_valgrind) {\n\t\tin_valgrind = (RUNNING_ON_VALGRIND != 0) ? true : false;\n\t\tif (config_fill && unlikely(in_valgrind)) {\n\t\t\topt_junk = \"false\";\n\t\t\topt_junk_alloc = false;\n\t\t\topt_junk_free = false;\n\t\t\tassert(!opt_zero);\n\t\t\topt_quarantine = JEMALLOC_VALGRIND_QUARANTINE_DEFAULT;\n\t\t\topt_redzone = true;\n\t\t}\n\t\tif (config_tcache && unlikely(in_valgrind))\n\t\t\topt_tcache = false;\n\t}\n\n\tfor (i = 0; i < 4; i++) {\n\t\t/* Get runtime configuration. */\n\t\tswitch (i) {\n\t\tcase 0:\n\t\t\topts = config_malloc_conf;\n\t\t\tbreak;\n\t\tcase 1:\n\t\t\tif (je_malloc_conf != NULL) {\n\t\t\t\t/*\n\t\t\t\t * Use options that were compiled into the\n\t\t\t\t * program.\n\t\t\t\t */\n\t\t\t\topts = je_malloc_conf;\n\t\t\t} else {\n\t\t\t\t/* No configuration specified. */\n\t\t\t\tbuf[0] = '\\0';\n\t\t\t\topts = buf;\n\t\t\t}\n\t\t\tbreak;\n\t\tcase 2: {\n\t\t\tssize_t linklen = 0;\n#ifndef _WIN32\n\t\t\tint saved_errno = errno;\n\t\t\tconst char *linkname =\n#  ifdef JEMALLOC_PREFIX\n\t\t\t    \"/etc/\"JEMALLOC_PREFIX\"malloc.conf\"\n#  else\n\t\t\t    \"/etc/malloc.conf\"\n#  endif\n\t\t\t    ;\n\n\t\t\t/*\n\t\t\t * Try to use the contents of the \"/etc/malloc.conf\"\n\t\t\t * symbolic link's name.\n\t\t\t */\n\t\t\tlinklen = readlink(linkname, buf, sizeof(buf) - 1);\n\t\t\tif (linklen == -1) {\n\t\t\t\t/* No configuration specified. */\n\t\t\t\tlinklen = 0;\n\t\t\t\t/* Restore errno. */\n\t\t\t\tset_errno(saved_errno);\n\t\t\t}\n#endif\n\t\t\tbuf[linklen] = '\\0';\n\t\t\topts = buf;\n\t\t\tbreak;\n\t\t} case 3: {\n\t\t\tconst char *envname =\n#ifdef JEMALLOC_PREFIX\n\t\t\t    JEMALLOC_CPREFIX\"MALLOC_CONF\"\n#else\n\t\t\t    \"MALLOC_CONF\"\n#endif\n\t\t\t    ;\n\n\t\t\tif ((opts = secure_getenv(envname)) != NULL) {\n\t\t\t\t/*\n\t\t\t\t * Do nothing; opts is already initialized to\n\t\t\t\t * the value of the MALLOC_CONF environment\n\t\t\t\t * variable.\n\t\t\t\t */\n\t\t\t} else {\n\t\t\t\t/* No configuration specified. */\n\t\t\t\tbuf[0] = '\\0';\n\t\t\t\topts = buf;\n\t\t\t}\n\t\t\tbreak;\n\t\t} default:\n\t\t\tnot_reached();\n\t\t\tbuf[0] = '\\0';\n\t\t\topts = buf;\n\t\t}\n\n\t\twhile (*opts != '\\0' && !malloc_conf_next(&opts, &k, &klen, &v,\n\t\t    &vlen)) {\n#define\tCONF_MATCH(n)\t\t\t\t\t\t\t\\\n\t(sizeof(n)-1 == klen && strncmp(n, k, klen) == 0)\n#define\tCONF_MATCH_VALUE(n)\t\t\t\t\t\t\\\n\t(sizeof(n)-1 == vlen && strncmp(n, v, vlen) == 0)\n#define\tCONF_HANDLE_BOOL(o, n, cont)\t\t\t\t\t\\\n\t\t\tif (CONF_MATCH(n)) {\t\t\t\t\\\n\t\t\t\tif (CONF_MATCH_VALUE(\"true\"))\t\t\\\n\t\t\t\t\to = true;\t\t\t\\\n\t\t\t\telse if (CONF_MATCH_VALUE(\"false\"))\t\\\n\t\t\t\t\to = false;\t\t\t\\\n\t\t\t\telse {\t\t\t\t\t\\\n\t\t\t\t\tmalloc_conf_error(\t\t\\\n\t\t\t\t\t    \"Invalid conf value\",\t\\\n\t\t\t\t\t    k, klen, v, vlen);\t\t\\\n\t\t\t\t}\t\t\t\t\t\\\n\t\t\t\tif (cont)\t\t\t\t\\\n\t\t\t\t\tcontinue;\t\t\t\\\n\t\t\t}\n#define\tCONF_HANDLE_T_U(t, o, n, min, max, clip)\t\t\t\\\n\t\t\tif (CONF_MATCH(n)) {\t\t\t\t\\\n\t\t\t\tuintmax_t um;\t\t\t\t\\\n\t\t\t\tchar *end;\t\t\t\t\\\n\t\t\t\t\t\t\t\t\t\\\n\t\t\t\tset_errno(0);\t\t\t\t\\\n\t\t\t\tum = malloc_strtoumax(v, &end, 0);\t\\\n\t\t\t\tif (get_errno() != 0 || (uintptr_t)end -\\\n\t\t\t\t    (uintptr_t)v != vlen) {\t\t\\\n\t\t\t\t\tmalloc_conf_error(\t\t\\\n\t\t\t\t\t    \"Invalid conf value\",\t\\\n\t\t\t\t\t    k, klen, v, vlen);\t\t\\\n\t\t\t\t} else if (clip) {\t\t\t\\\n\t\t\t\t\tif ((min) != 0 && um < (min))\t\\\n\t\t\t\t\t\to = (t)(min);\t\t\\\n\t\t\t\t\telse if (um > (max))\t\t\\\n\t\t\t\t\t\to = (t)(max);\t\t\\\n\t\t\t\t\telse\t\t\t\t\\\n\t\t\t\t\t\to = (t)um;\t\t\\\n\t\t\t\t} else {\t\t\t\t\\\n\t\t\t\t\tif (((min) != 0 && um < (min))\t\\\n\t\t\t\t\t    || um > (max)) {\t\t\\\n\t\t\t\t\t\tmalloc_conf_error(\t\\\n\t\t\t\t\t\t    \"Out-of-range \"\t\\\n\t\t\t\t\t\t    \"conf value\",\t\\\n\t\t\t\t\t\t    k, klen, v, vlen);\t\\\n\t\t\t\t\t} else\t\t\t\t\\\n\t\t\t\t\t\to = (t)um;\t\t\\\n\t\t\t\t}\t\t\t\t\t\\\n\t\t\t\tcontinue;\t\t\t\t\\\n\t\t\t}\n#define\tCONF_HANDLE_UNSIGNED(o, n, min, max, clip)\t\t\t\\\n\t\t\tCONF_HANDLE_T_U(unsigned, o, n, min, max, clip)\n#define\tCONF_HANDLE_SIZE_T(o, n, min, max, clip)\t\t\t\\\n\t\t\tCONF_HANDLE_T_U(size_t, o, n, min, max, clip)\n#define\tCONF_HANDLE_SSIZE_T(o, n, min, max)\t\t\t\t\\\n\t\t\tif (CONF_MATCH(n)) {\t\t\t\t\\\n\t\t\t\tlong l;\t\t\t\t\t\\\n\t\t\t\tchar *end;\t\t\t\t\\\n\t\t\t\t\t\t\t\t\t\\\n\t\t\t\tset_errno(0);\t\t\t\t\\\n\t\t\t\tl = strtol(v, &end, 0);\t\t\t\\\n\t\t\t\tif (get_errno() != 0 || (uintptr_t)end -\\\n\t\t\t\t    (uintptr_t)v != vlen) {\t\t\\\n\t\t\t\t\tmalloc_conf_error(\t\t\\\n\t\t\t\t\t    \"Invalid conf value\",\t\\\n\t\t\t\t\t    k, klen, v, vlen);\t\t\\\n\t\t\t\t} else if (l < (ssize_t)(min) || l >\t\\\n\t\t\t\t    (ssize_t)(max)) {\t\t\t\\\n\t\t\t\t\tmalloc_conf_error(\t\t\\\n\t\t\t\t\t    \"Out-of-range conf value\",\t\\\n\t\t\t\t\t    k, klen, v, vlen);\t\t\\\n\t\t\t\t} else\t\t\t\t\t\\\n\t\t\t\t\to = l;\t\t\t\t\\\n\t\t\t\tcontinue;\t\t\t\t\\\n\t\t\t}\n#define\tCONF_HANDLE_CHAR_P(o, n, d)\t\t\t\t\t\\\n\t\t\tif (CONF_MATCH(n)) {\t\t\t\t\\\n\t\t\t\tsize_t cpylen = (vlen <=\t\t\\\n\t\t\t\t    sizeof(o)-1) ? vlen :\t\t\\\n\t\t\t\t    sizeof(o)-1;\t\t\t\\\n\t\t\t\tstrncpy(o, v, cpylen);\t\t\t\\\n\t\t\t\to[cpylen] = '\\0';\t\t\t\\\n\t\t\t\tcontinue;\t\t\t\t\\\n\t\t\t}\n\n\t\t\tCONF_HANDLE_BOOL(opt_abort, \"abort\", true)\n\t\t\t/*\n\t\t\t * Chunks always require at least one header page,\n\t\t\t * as many as 2^(LG_SIZE_CLASS_GROUP+1) data pages, and\n\t\t\t * possibly an additional page in the presence of\n\t\t\t * redzones.  In order to simplify options processing,\n\t\t\t * use a conservative bound that accommodates all these\n\t\t\t * constraints.\n\t\t\t */\n\t\t\tCONF_HANDLE_SIZE_T(opt_lg_chunk, \"lg_chunk\", LG_PAGE +\n\t\t\t    LG_SIZE_CLASS_GROUP + (config_fill ? 2 : 1),\n\t\t\t    (sizeof(size_t) << 3) - 1, true)\n\t\t\tif (strncmp(\"dss\", k, klen) == 0) {\n\t\t\t\tint i;\n\t\t\t\tbool match = false;\n\t\t\t\tfor (i = 0; i < dss_prec_limit; i++) {\n\t\t\t\t\tif (strncmp(dss_prec_names[i], v, vlen)\n\t\t\t\t\t    == 0) {\n\t\t\t\t\t\tif (chunk_dss_prec_set(NULL,\n\t\t\t\t\t\t   i)) {\n\t\t\t\t\t\t\tmalloc_conf_error(\n\t\t\t\t\t\t\t    \"Error setting dss\",\n\t\t\t\t\t\t\t    k, klen, v, vlen);\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\topt_dss =\n\t\t\t\t\t\t\t    dss_prec_names[i];\n\t\t\t\t\t\t\tmatch = true;\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tif (!match) {\n\t\t\t\t\tmalloc_conf_error(\"Invalid conf value\",\n\t\t\t\t\t    k, klen, v, vlen);\n\t\t\t\t}\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tCONF_HANDLE_UNSIGNED(opt_narenas, \"narenas\", 1,\n\t\t\t    UINT_MAX, false)\n\t\t\tif (strncmp(\"purge\", k, klen) == 0) {\n\t\t\t\tint i;\n\t\t\t\tbool match = false;\n\t\t\t\tfor (i = 0; i < purge_mode_limit; i++) {\n\t\t\t\t\tif (strncmp(purge_mode_names[i], v,\n\t\t\t\t\t    vlen) == 0) {\n\t\t\t\t\t\topt_purge = (purge_mode_t)i;\n\t\t\t\t\t\tmatch = true;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tif (!match) {\n\t\t\t\t\tmalloc_conf_error(\"Invalid conf value\",\n\t\t\t\t\t    k, klen, v, vlen);\n\t\t\t\t}\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tCONF_HANDLE_SSIZE_T(opt_lg_dirty_mult, \"lg_dirty_mult\",\n\t\t\t    -1, (sizeof(size_t) << 3) - 1)\n\t\t\tCONF_HANDLE_SSIZE_T(opt_decay_time, \"decay_time\", -1,\n\t\t\t    NSTIME_SEC_MAX);\n\t\t\tCONF_HANDLE_BOOL(opt_stats_print, \"stats_print\", true)\n\t\t\tif (config_fill) {\n\t\t\t\tif (CONF_MATCH(\"junk\")) {\n\t\t\t\t\tif (CONF_MATCH_VALUE(\"true\")) {\n\t\t\t\t\t\topt_junk = \"true\";\n\t\t\t\t\t\topt_junk_alloc = opt_junk_free =\n\t\t\t\t\t\t    true;\n\t\t\t\t\t} else if (CONF_MATCH_VALUE(\"false\")) {\n\t\t\t\t\t\topt_junk = \"false\";\n\t\t\t\t\t\topt_junk_alloc = opt_junk_free =\n\t\t\t\t\t\t    false;\n\t\t\t\t\t} else if (CONF_MATCH_VALUE(\"alloc\")) {\n\t\t\t\t\t\topt_junk = \"alloc\";\n\t\t\t\t\t\topt_junk_alloc = true;\n\t\t\t\t\t\topt_junk_free = false;\n\t\t\t\t\t} else if (CONF_MATCH_VALUE(\"free\")) {\n\t\t\t\t\t\topt_junk = \"free\";\n\t\t\t\t\t\topt_junk_alloc = false;\n\t\t\t\t\t\topt_junk_free = true;\n\t\t\t\t\t} else {\n\t\t\t\t\t\tmalloc_conf_error(\n\t\t\t\t\t\t    \"Invalid conf value\", k,\n\t\t\t\t\t\t    klen, v, vlen);\n\t\t\t\t\t}\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t\tCONF_HANDLE_SIZE_T(opt_quarantine, \"quarantine\",\n\t\t\t\t    0, SIZE_T_MAX, false)\n\t\t\t\tCONF_HANDLE_BOOL(opt_redzone, \"redzone\", true)\n\t\t\t\tCONF_HANDLE_BOOL(opt_zero, \"zero\", true)\n\t\t\t}\n\t\t\tif (config_utrace) {\n\t\t\t\tCONF_HANDLE_BOOL(opt_utrace, \"utrace\", true)\n\t\t\t}\n\t\t\tif (config_xmalloc) {\n\t\t\t\tCONF_HANDLE_BOOL(opt_xmalloc, \"xmalloc\", true)\n\t\t\t}\n\t\t\tif (config_tcache) {\n\t\t\t\tCONF_HANDLE_BOOL(opt_tcache, \"tcache\",\n\t\t\t\t    !config_valgrind || !in_valgrind)\n\t\t\t\tif (CONF_MATCH(\"tcache\")) {\n\t\t\t\t\tassert(config_valgrind && in_valgrind);\n\t\t\t\t\tif (opt_tcache) {\n\t\t\t\t\t\topt_tcache = false;\n\t\t\t\t\t\tmalloc_conf_error(\n\t\t\t\t\t\t\"tcache cannot be enabled \"\n\t\t\t\t\t\t\"while running inside Valgrind\",\n\t\t\t\t\t\tk, klen, v, vlen);\n\t\t\t\t\t}\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t\tCONF_HANDLE_SSIZE_T(opt_lg_tcache_max,\n\t\t\t\t    \"lg_tcache_max\", -1,\n\t\t\t\t    (sizeof(size_t) << 3) - 1)\n\t\t\t}\n\t\t\tif (config_prof) {\n\t\t\t\tCONF_HANDLE_BOOL(opt_prof, \"prof\", true)\n\t\t\t\tCONF_HANDLE_CHAR_P(opt_prof_prefix,\n\t\t\t\t    \"prof_prefix\", \"jeprof\")\n\t\t\t\tCONF_HANDLE_BOOL(opt_prof_active, \"prof_active\",\n\t\t\t\t    true)\n\t\t\t\tCONF_HANDLE_BOOL(opt_prof_thread_active_init,\n\t\t\t\t    \"prof_thread_active_init\", true)\n\t\t\t\tCONF_HANDLE_SIZE_T(opt_lg_prof_sample,\n\t\t\t\t    \"lg_prof_sample\", 0,\n\t\t\t\t    (sizeof(uint64_t) << 3) - 1, true)\n\t\t\t\tCONF_HANDLE_BOOL(opt_prof_accum, \"prof_accum\",\n\t\t\t\t    true)\n\t\t\t\tCONF_HANDLE_SSIZE_T(opt_lg_prof_interval,\n\t\t\t\t    \"lg_prof_interval\", -1,\n\t\t\t\t    (sizeof(uint64_t) << 3) - 1)\n\t\t\t\tCONF_HANDLE_BOOL(opt_prof_gdump, \"prof_gdump\",\n\t\t\t\t    true)\n\t\t\t\tCONF_HANDLE_BOOL(opt_prof_final, \"prof_final\",\n\t\t\t\t    true)\n\t\t\t\tCONF_HANDLE_BOOL(opt_prof_leak, \"prof_leak\",\n\t\t\t\t    true)\n\t\t\t}\n\t\t\tmalloc_conf_error(\"Invalid conf pair\", k, klen, v,\n\t\t\t    vlen);\n#undef CONF_MATCH\n#undef CONF_HANDLE_BOOL\n#undef CONF_HANDLE_SIZE_T\n#undef CONF_HANDLE_SSIZE_T\n#undef CONF_HANDLE_CHAR_P\n\t\t}\n\t}\n}\n\nstatic bool\nmalloc_init_hard_needed(void)\n{\n\n\tif (malloc_initialized() || (IS_INITIALIZER && malloc_init_state ==\n\t    malloc_init_recursible)) {\n\t\t/*\n\t\t * Another thread initialized the allocator before this one\n\t\t * acquired init_lock, or this thread is the initializing\n\t\t * thread, and it is recursively allocating.\n\t\t */\n\t\treturn (false);\n\t}\n#ifdef JEMALLOC_THREADED_INIT\n\tif (malloc_initializer != NO_INITIALIZER && !IS_INITIALIZER) {\n\t\t/* Busy-wait until the initializing thread completes. */\n\t\tdo {\n\t\t\tmalloc_mutex_unlock(NULL, &init_lock);\n\t\t\tCPU_SPINWAIT;\n\t\t\tmalloc_mutex_lock(NULL, &init_lock);\n\t\t} while (!malloc_initialized());\n\t\treturn (false);\n\t}\n#endif\n\treturn (true);\n}\n\nstatic bool\nmalloc_init_hard_a0_locked()\n{\n\n\tmalloc_initializer = INITIALIZER;\n\n\tif (config_prof)\n\t\tprof_boot0();\n\tmalloc_conf_init();\n\tif (opt_stats_print) {\n\t\t/* Print statistics at exit. */\n\t\tif (atexit(stats_print_atexit) != 0) {\n\t\t\tmalloc_write(\"<jemalloc>: Error in atexit()\\n\");\n\t\t\tif (opt_abort)\n\t\t\t\tabort();\n\t\t}\n\t}\n\tpages_boot();\n\tif (base_boot())\n\t\treturn (true);\n\tif (chunk_boot())\n\t\treturn (true);\n\tif (ctl_boot())\n\t\treturn (true);\n\tif (config_prof)\n\t\tprof_boot1();\n\tif (arena_boot())\n\t\treturn (true);\n\tif (config_tcache && tcache_boot(TSDN_NULL))\n\t\treturn (true);\n\tif (malloc_mutex_init(&arenas_lock, \"arenas\", WITNESS_RANK_ARENAS))\n\t\treturn (true);\n\t/*\n\t * Create enough scaffolding to allow recursive allocation in\n\t * malloc_ncpus().\n\t */\n\tnarenas_auto = 1;\n\tnarenas_total_set(narenas_auto);\n\tarenas = &a0;\n\tmemset(arenas, 0, sizeof(arena_t *) * narenas_auto);\n\t/*\n\t * Initialize one arena here.  The rest are lazily created in\n\t * arena_choose_hard().\n\t */\n\tif (arena_init(TSDN_NULL, 0) == NULL)\n\t\treturn (true);\n\n\tmalloc_init_state = malloc_init_a0_initialized;\n\n\treturn (false);\n}\n\nstatic bool\nmalloc_init_hard_a0(void)\n{\n\tbool ret;\n\n\tmalloc_mutex_lock(TSDN_NULL, &init_lock);\n\tret = malloc_init_hard_a0_locked();\n\tmalloc_mutex_unlock(TSDN_NULL, &init_lock);\n\treturn (ret);\n}\n\n/* Initialize data structures which may trigger recursive allocation. */\nstatic bool\nmalloc_init_hard_recursible(void)\n{\n\n\tmalloc_init_state = malloc_init_recursible;\n\n\tncpus = malloc_ncpus();\n\n#if (!defined(JEMALLOC_MUTEX_INIT_CB) && !defined(JEMALLOC_ZONE) \\\n    && !defined(_WIN32) && !defined(__native_client__))\n\t/* LinuxThreads' pthread_atfork() allocates. */\n\tif (pthread_atfork(jemalloc_prefork, jemalloc_postfork_parent,\n\t    jemalloc_postfork_child) != 0) {\n\t\tmalloc_write(\"<jemalloc>: Error in pthread_atfork()\\n\");\n\t\tif (opt_abort)\n\t\t\tabort();\n\t\treturn (true);\n\t}\n#endif\n\n\treturn (false);\n}\n\nstatic bool\nmalloc_init_hard_finish(tsdn_t *tsdn)\n{\n\n\tif (malloc_mutex_boot())\n\t\treturn (true);\n\n\tif (opt_narenas == 0) {\n\t\t/*\n\t\t * For SMP systems, create more than one arena per CPU by\n\t\t * default.\n\t\t */\n\t\tif (ncpus > 1)\n\t\t\topt_narenas = ncpus << 2;\n\t\telse\n\t\t\topt_narenas = 1;\n\t}\n\tnarenas_auto = opt_narenas;\n\t/*\n\t * Limit the number of arenas to the indexing range of MALLOCX_ARENA().\n\t */\n\tif (narenas_auto > MALLOCX_ARENA_MAX) {\n\t\tnarenas_auto = MALLOCX_ARENA_MAX;\n\t\tmalloc_printf(\"<jemalloc>: Reducing narenas to limit (%d)\\n\",\n\t\t    narenas_auto);\n\t}\n\tnarenas_total_set(narenas_auto);\n\n\t/* Allocate and initialize arenas. */\n\tarenas = (arena_t **)base_alloc(tsdn, sizeof(arena_t *) *\n\t    (MALLOCX_ARENA_MAX+1));\n\tif (arenas == NULL)\n\t\treturn (true);\n\t/* Copy the pointer to the one arena that was already initialized. */\n\tarena_set(0, a0);\n\n\tmalloc_init_state = malloc_init_initialized;\n\tmalloc_slow_flag_init();\n\n\treturn (false);\n}\n\nstatic bool\nmalloc_init_hard(void)\n{\n\ttsd_t *tsd;\n\n#if defined(_WIN32) && _WIN32_WINNT < 0x0600\n\t_init_init_lock();\n#endif\n\tmalloc_mutex_lock(TSDN_NULL, &init_lock);\n\tif (!malloc_init_hard_needed()) {\n\t\tmalloc_mutex_unlock(TSDN_NULL, &init_lock);\n\t\treturn (false);\n\t}\n\n\tif (malloc_init_state != malloc_init_a0_initialized &&\n\t    malloc_init_hard_a0_locked()) {\n\t\tmalloc_mutex_unlock(TSDN_NULL, &init_lock);\n\t\treturn (true);\n\t}\n\n\tmalloc_mutex_unlock(TSDN_NULL, &init_lock);\n\t/* Recursive allocation relies on functional tsd. */\n\ttsd = malloc_tsd_boot0();\n\tif (tsd == NULL)\n\t\treturn (true);\n\tif (malloc_init_hard_recursible())\n\t\treturn (true);\n\tmalloc_mutex_lock(tsd_tsdn(tsd), &init_lock);\n\n\tif (config_prof && prof_boot2(tsd_tsdn(tsd))) {\n\t\tmalloc_mutex_unlock(tsd_tsdn(tsd), &init_lock);\n\t\treturn (true);\n\t}\n\n\tif (malloc_init_hard_finish(tsd_tsdn(tsd))) {\n\t\tmalloc_mutex_unlock(tsd_tsdn(tsd), &init_lock);\n\t\treturn (true);\n\t}\n\n\tmalloc_mutex_unlock(tsd_tsdn(tsd), &init_lock);\n\tmalloc_tsd_boot1();\n\treturn (false);\n}\n\n/*\n * End initialization functions.\n */\n/******************************************************************************/\n/*\n * Begin malloc(3)-compatible functions.\n */\n\nstatic void *\nialloc_prof_sample(tsd_t *tsd, size_t usize, szind_t ind, bool zero,\n    prof_tctx_t *tctx, bool slow_path)\n{\n\tvoid *p;\n\n\tif (tctx == NULL)\n\t\treturn (NULL);\n\tif (usize <= SMALL_MAXCLASS) {\n\t\tszind_t ind_large = size2index(LARGE_MINCLASS);\n\t\tp = ialloc(tsd, LARGE_MINCLASS, ind_large, zero, slow_path);\n\t\tif (p == NULL)\n\t\t\treturn (NULL);\n\t\tarena_prof_promoted(tsd_tsdn(tsd), p, usize);\n\t} else\n\t\tp = ialloc(tsd, usize, ind, zero, slow_path);\n\n\treturn (p);\n}\n\nJEMALLOC_ALWAYS_INLINE_C void *\nialloc_prof(tsd_t *tsd, size_t usize, szind_t ind, bool zero, bool slow_path)\n{\n\tvoid *p;\n\tprof_tctx_t *tctx;\n\n\ttctx = prof_alloc_prep(tsd, usize, prof_active_get_unlocked(), true);\n\tif (unlikely((uintptr_t)tctx != (uintptr_t)1U))\n\t\tp = ialloc_prof_sample(tsd, usize, ind, zero, tctx, slow_path);\n\telse\n\t\tp = ialloc(tsd, usize, ind, zero, slow_path);\n\tif (unlikely(p == NULL)) {\n\t\tprof_alloc_rollback(tsd, tctx, true);\n\t\treturn (NULL);\n\t}\n\tprof_malloc(tsd_tsdn(tsd), p, usize, tctx);\n\n\treturn (p);\n}\n\n/*\n * ialloc_body() is inlined so that fast and slow paths are generated separately\n * with statically known slow_path.\n *\n * This function guarantees that *tsdn is non-NULL on success.\n */\nJEMALLOC_ALWAYS_INLINE_C void *\nialloc_body(size_t size, bool zero, tsdn_t **tsdn, size_t *usize,\n    bool slow_path)\n{\n\ttsd_t *tsd;\n\tszind_t ind;\n\n\tif (slow_path && unlikely(malloc_init())) {\n\t\t*tsdn = NULL;\n\t\treturn (NULL);\n\t}\n\n\ttsd = tsd_fetch();\n\t*tsdn = tsd_tsdn(tsd);\n\twitness_assert_lockless(tsd_tsdn(tsd));\n\n\tind = size2index(size);\n\tif (unlikely(ind >= NSIZES))\n\t\treturn (NULL);\n\n\tif (config_stats || (config_prof && opt_prof) || (slow_path &&\n\t    config_valgrind && unlikely(in_valgrind))) {\n\t\t*usize = index2size(ind);\n\t\tassert(*usize > 0 && *usize <= HUGE_MAXCLASS);\n\t}\n\n\tif (config_prof && opt_prof)\n\t\treturn (ialloc_prof(tsd, *usize, ind, zero, slow_path));\n\n\treturn (ialloc(tsd, size, ind, zero, slow_path));\n}\n\nJEMALLOC_ALWAYS_INLINE_C void\nialloc_post_check(void *ret, tsdn_t *tsdn, size_t usize, const char *func,\n    bool update_errno, bool slow_path)\n{\n\n\tassert(!tsdn_null(tsdn) || ret == NULL);\n\n\tif (unlikely(ret == NULL)) {\n\t\tif (slow_path && config_xmalloc && unlikely(opt_xmalloc)) {\n\t\t\tmalloc_printf(\"<jemalloc>: Error in %s(): out of \"\n\t\t\t    \"memory\\n\", func);\n\t\t\tabort();\n\t\t}\n\t\tif (update_errno)\n\t\t\tset_errno(ENOMEM);\n\t}\n\tif (config_stats && likely(ret != NULL)) {\n\t\tassert(usize == isalloc(tsdn, ret, config_prof));\n\t\t*tsd_thread_allocatedp_get(tsdn_tsd(tsdn)) += usize;\n\t}\n\twitness_assert_lockless(tsdn);\n}\n\nJEMALLOC_EXPORT JEMALLOC_ALLOCATOR JEMALLOC_RESTRICT_RETURN\nvoid JEMALLOC_NOTHROW *\nJEMALLOC_ATTR(malloc) JEMALLOC_ALLOC_SIZE(1)\nje_malloc(size_t size)\n{\n\tvoid *ret;\n\ttsdn_t *tsdn;\n\tsize_t usize JEMALLOC_CC_SILENCE_INIT(0);\n\n\tif (size == 0)\n\t\tsize = 1;\n\n\tif (likely(!malloc_slow)) {\n\t\tret = ialloc_body(size, false, &tsdn, &usize, false);\n\t\tialloc_post_check(ret, tsdn, usize, \"malloc\", true, false);\n\t} else {\n\t\tret = ialloc_body(size, false, &tsdn, &usize, true);\n\t\tialloc_post_check(ret, tsdn, usize, \"malloc\", true, true);\n\t\tUTRACE(0, size, ret);\n\t\tJEMALLOC_VALGRIND_MALLOC(ret != NULL, tsdn, ret, usize, false);\n\t}\n\n\treturn (ret);\n}\n\nstatic void *\nimemalign_prof_sample(tsd_t *tsd, size_t alignment, size_t usize,\n    prof_tctx_t *tctx)\n{\n\tvoid *p;\n\n\tif (tctx == NULL)\n\t\treturn (NULL);\n\tif (usize <= SMALL_MAXCLASS) {\n\t\tassert(sa2u(LARGE_MINCLASS, alignment) == LARGE_MINCLASS);\n\t\tp = ipalloc(tsd, LARGE_MINCLASS, alignment, false);\n\t\tif (p == NULL)\n\t\t\treturn (NULL);\n\t\tarena_prof_promoted(tsd_tsdn(tsd), p, usize);\n\t} else\n\t\tp = ipalloc(tsd, usize, alignment, false);\n\n\treturn (p);\n}\n\nJEMALLOC_ALWAYS_INLINE_C void *\nimemalign_prof(tsd_t *tsd, size_t alignment, size_t usize)\n{\n\tvoid *p;\n\tprof_tctx_t *tctx;\n\n\ttctx = prof_alloc_prep(tsd, usize, prof_active_get_unlocked(), true);\n\tif (unlikely((uintptr_t)tctx != (uintptr_t)1U))\n\t\tp = imemalign_prof_sample(tsd, alignment, usize, tctx);\n\telse\n\t\tp = ipalloc(tsd, usize, alignment, false);\n\tif (unlikely(p == NULL)) {\n\t\tprof_alloc_rollback(tsd, tctx, true);\n\t\treturn (NULL);\n\t}\n\tprof_malloc(tsd_tsdn(tsd), p, usize, tctx);\n\n\treturn (p);\n}\n\nJEMALLOC_ATTR(nonnull(1))\nstatic int\nimemalign(void **memptr, size_t alignment, size_t size, size_t min_alignment)\n{\n\tint ret;\n\ttsd_t *tsd;\n\tsize_t usize;\n\tvoid *result;\n\n\tassert(min_alignment != 0);\n\n\tif (unlikely(malloc_init())) {\n\t\ttsd = NULL;\n\t\tresult = NULL;\n\t\tgoto label_oom;\n\t}\n\ttsd = tsd_fetch();\n\twitness_assert_lockless(tsd_tsdn(tsd));\n\tif (size == 0)\n\t\tsize = 1;\n\n\t/* Make sure that alignment is a large enough power of 2. */\n\tif (unlikely(((alignment - 1) & alignment) != 0\n\t    || (alignment < min_alignment))) {\n\t\tif (config_xmalloc && unlikely(opt_xmalloc)) {\n\t\t\tmalloc_write(\"<jemalloc>: Error allocating \"\n\t\t\t    \"aligned memory: invalid alignment\\n\");\n\t\t\tabort();\n\t\t}\n\t\tresult = NULL;\n\t\tret = EINVAL;\n\t\tgoto label_return;\n\t}\n\n\tusize = sa2u(size, alignment);\n\tif (unlikely(usize == 0 || usize > HUGE_MAXCLASS)) {\n\t\tresult = NULL;\n\t\tgoto label_oom;\n\t}\n\n\tif (config_prof && opt_prof)\n\t\tresult = imemalign_prof(tsd, alignment, usize);\n\telse\n\t\tresult = ipalloc(tsd, usize, alignment, false);\n\tif (unlikely(result == NULL))\n\t\tgoto label_oom;\n\tassert(((uintptr_t)result & (alignment - 1)) == ZU(0));\n\n\t*memptr = result;\n\tret = 0;\nlabel_return:\n\tif (config_stats && likely(result != NULL)) {\n\t\tassert(usize == isalloc(tsd_tsdn(tsd), result, config_prof));\n\t\t*tsd_thread_allocatedp_get(tsd) += usize;\n\t}\n\tUTRACE(0, size, result);\n\tJEMALLOC_VALGRIND_MALLOC(result != NULL, tsd_tsdn(tsd), result, usize,\n\t    false);\n\twitness_assert_lockless(tsd_tsdn(tsd));\n\treturn (ret);\nlabel_oom:\n\tassert(result == NULL);\n\tif (config_xmalloc && unlikely(opt_xmalloc)) {\n\t\tmalloc_write(\"<jemalloc>: Error allocating aligned memory: \"\n\t\t    \"out of memory\\n\");\n\t\tabort();\n\t}\n\tret = ENOMEM;\n\twitness_assert_lockless(tsd_tsdn(tsd));\n\tgoto label_return;\n}\n\nJEMALLOC_EXPORT int JEMALLOC_NOTHROW\nJEMALLOC_ATTR(nonnull(1))\nje_posix_memalign(void **memptr, size_t alignment, size_t size)\n{\n\tint ret;\n\n\tret = imemalign(memptr, alignment, size, sizeof(void *));\n\n\treturn (ret);\n}\n\nJEMALLOC_EXPORT JEMALLOC_ALLOCATOR JEMALLOC_RESTRICT_RETURN\nvoid JEMALLOC_NOTHROW *\nJEMALLOC_ATTR(malloc) JEMALLOC_ALLOC_SIZE(2)\nje_aligned_alloc(size_t alignment, size_t size)\n{\n\tvoid *ret;\n\tint err;\n\n\tif (unlikely((err = imemalign(&ret, alignment, size, 1)) != 0)) {\n\t\tret = NULL;\n\t\tset_errno(err);\n\t}\n\n\treturn (ret);\n}\n\nJEMALLOC_EXPORT JEMALLOC_ALLOCATOR JEMALLOC_RESTRICT_RETURN\nvoid JEMALLOC_NOTHROW *\nJEMALLOC_ATTR(malloc) JEMALLOC_ALLOC_SIZE2(1, 2)\nje_calloc(size_t num, size_t size)\n{\n\tvoid *ret;\n\ttsdn_t *tsdn;\n\tsize_t num_size;\n\tsize_t usize JEMALLOC_CC_SILENCE_INIT(0);\n\n\tnum_size = num * size;\n\tif (unlikely(num_size == 0)) {\n\t\tif (num == 0 || size == 0)\n\t\t\tnum_size = 1;\n\t\telse\n\t\t\tnum_size = HUGE_MAXCLASS + 1; /* Trigger OOM. */\n\t/*\n\t * Try to avoid division here.  We know that it isn't possible to\n\t * overflow during multiplication if neither operand uses any of the\n\t * most significant half of the bits in a size_t.\n\t */\n\t} else if (unlikely(((num | size) & (SIZE_T_MAX << (sizeof(size_t) <<\n\t    2))) && (num_size / size != num)))\n\t\tnum_size = HUGE_MAXCLASS + 1; /* size_t overflow. */\n\n\tif (likely(!malloc_slow)) {\n\t\tret = ialloc_body(num_size, true, &tsdn, &usize, false);\n\t\tialloc_post_check(ret, tsdn, usize, \"calloc\", true, false);\n\t} else {\n\t\tret = ialloc_body(num_size, true, &tsdn, &usize, true);\n\t\tialloc_post_check(ret, tsdn, usize, \"calloc\", true, true);\n\t\tUTRACE(0, num_size, ret);\n\t\tJEMALLOC_VALGRIND_MALLOC(ret != NULL, tsdn, ret, usize, true);\n\t}\n\n\treturn (ret);\n}\n\nstatic void *\nirealloc_prof_sample(tsd_t *tsd, void *old_ptr, size_t old_usize, size_t usize,\n    prof_tctx_t *tctx)\n{\n\tvoid *p;\n\n\tif (tctx == NULL)\n\t\treturn (NULL);\n\tif (usize <= SMALL_MAXCLASS) {\n\t\tp = iralloc(tsd, old_ptr, old_usize, LARGE_MINCLASS, 0, false);\n\t\tif (p == NULL)\n\t\t\treturn (NULL);\n\t\tarena_prof_promoted(tsd_tsdn(tsd), p, usize);\n\t} else\n\t\tp = iralloc(tsd, old_ptr, old_usize, usize, 0, false);\n\n\treturn (p);\n}\n\nJEMALLOC_ALWAYS_INLINE_C void *\nirealloc_prof(tsd_t *tsd, void *old_ptr, size_t old_usize, size_t usize)\n{\n\tvoid *p;\n\tbool prof_active;\n\tprof_tctx_t *old_tctx, *tctx;\n\n\tprof_active = prof_active_get_unlocked();\n\told_tctx = prof_tctx_get(tsd_tsdn(tsd), old_ptr);\n\ttctx = prof_alloc_prep(tsd, usize, prof_active, true);\n\tif (unlikely((uintptr_t)tctx != (uintptr_t)1U))\n\t\tp = irealloc_prof_sample(tsd, old_ptr, old_usize, usize, tctx);\n\telse\n\t\tp = iralloc(tsd, old_ptr, old_usize, usize, 0, false);\n\tif (unlikely(p == NULL)) {\n\t\tprof_alloc_rollback(tsd, tctx, true);\n\t\treturn (NULL);\n\t}\n\tprof_realloc(tsd, p, usize, tctx, prof_active, true, old_ptr, old_usize,\n\t    old_tctx);\n\n\treturn (p);\n}\n\nJEMALLOC_INLINE_C void\nifree(tsd_t *tsd, void *ptr, tcache_t *tcache, bool slow_path)\n{\n\tsize_t usize;\n\tUNUSED size_t rzsize JEMALLOC_CC_SILENCE_INIT(0);\n\n\twitness_assert_lockless(tsd_tsdn(tsd));\n\n\tassert(ptr != NULL);\n\tassert(malloc_initialized() || IS_INITIALIZER);\n\n\tif (config_prof && opt_prof) {\n\t\tusize = isalloc(tsd_tsdn(tsd), ptr, config_prof);\n\t\tprof_free(tsd, ptr, usize);\n\t} else if (config_stats || config_valgrind)\n\t\tusize = isalloc(tsd_tsdn(tsd), ptr, config_prof);\n\tif (config_stats)\n\t\t*tsd_thread_deallocatedp_get(tsd) += usize;\n\n\tif (likely(!slow_path))\n\t\tiqalloc(tsd, ptr, tcache, false);\n\telse {\n\t\tif (config_valgrind && unlikely(in_valgrind))\n\t\t\trzsize = p2rz(tsd_tsdn(tsd), ptr);\n\t\tiqalloc(tsd, ptr, tcache, true);\n\t\tJEMALLOC_VALGRIND_FREE(ptr, rzsize);\n\t}\n}\n\nJEMALLOC_INLINE_C void\nisfree(tsd_t *tsd, void *ptr, size_t usize, tcache_t *tcache, bool slow_path)\n{\n\tUNUSED size_t rzsize JEMALLOC_CC_SILENCE_INIT(0);\n\n\twitness_assert_lockless(tsd_tsdn(tsd));\n\n\tassert(ptr != NULL);\n\tassert(malloc_initialized() || IS_INITIALIZER);\n\n\tif (config_prof && opt_prof)\n\t\tprof_free(tsd, ptr, usize);\n\tif (config_stats)\n\t\t*tsd_thread_deallocatedp_get(tsd) += usize;\n\tif (config_valgrind && unlikely(in_valgrind))\n\t\trzsize = p2rz(tsd_tsdn(tsd), ptr);\n\tisqalloc(tsd, ptr, usize, tcache, slow_path);\n\tJEMALLOC_VALGRIND_FREE(ptr, rzsize);\n}\n\nJEMALLOC_EXPORT JEMALLOC_ALLOCATOR JEMALLOC_RESTRICT_RETURN\nvoid JEMALLOC_NOTHROW *\nJEMALLOC_ALLOC_SIZE(2)\nje_realloc(void *ptr, size_t size)\n{\n\tvoid *ret;\n\ttsdn_t *tsdn JEMALLOC_CC_SILENCE_INIT(NULL);\n\tsize_t usize JEMALLOC_CC_SILENCE_INIT(0);\n\tsize_t old_usize = 0;\n\tUNUSED size_t old_rzsize JEMALLOC_CC_SILENCE_INIT(0);\n\n\tif (unlikely(size == 0)) {\n\t\tif (ptr != NULL) {\n\t\t\ttsd_t *tsd;\n\n\t\t\t/* realloc(ptr, 0) is equivalent to free(ptr). */\n\t\t\tUTRACE(ptr, 0, 0);\n\t\t\ttsd = tsd_fetch();\n\t\t\tifree(tsd, ptr, tcache_get(tsd, false), true);\n\t\t\treturn (NULL);\n\t\t}\n\t\tsize = 1;\n\t}\n\n\tif (likely(ptr != NULL)) {\n\t\ttsd_t *tsd;\n\n\t\tassert(malloc_initialized() || IS_INITIALIZER);\n\t\tmalloc_thread_init();\n\t\ttsd = tsd_fetch();\n\n\t\twitness_assert_lockless(tsd_tsdn(tsd));\n\n\t\told_usize = isalloc(tsd_tsdn(tsd), ptr, config_prof);\n\t\tif (config_valgrind && unlikely(in_valgrind)) {\n\t\t\told_rzsize = config_prof ? p2rz(tsd_tsdn(tsd), ptr) :\n\t\t\t    u2rz(old_usize);\n\t\t}\n\n\t\tif (config_prof && opt_prof) {\n\t\t\tusize = s2u(size);\n\t\t\tret = unlikely(usize == 0 || usize > HUGE_MAXCLASS) ?\n\t\t\t    NULL : irealloc_prof(tsd, ptr, old_usize, usize);\n\t\t} else {\n\t\t\tif (config_stats || (config_valgrind &&\n\t\t\t    unlikely(in_valgrind)))\n\t\t\t\tusize = s2u(size);\n\t\t\tret = iralloc(tsd, ptr, old_usize, size, 0, false);\n\t\t}\n\t\ttsdn = tsd_tsdn(tsd);\n\t} else {\n\t\t/* realloc(NULL, size) is equivalent to malloc(size). */\n\t\tif (likely(!malloc_slow))\n\t\t\tret = ialloc_body(size, false, &tsdn, &usize, false);\n\t\telse\n\t\t\tret = ialloc_body(size, false, &tsdn, &usize, true);\n\t\tassert(!tsdn_null(tsdn) || ret == NULL);\n\t}\n\n\tif (unlikely(ret == NULL)) {\n\t\tif (config_xmalloc && unlikely(opt_xmalloc)) {\n\t\t\tmalloc_write(\"<jemalloc>: Error in realloc(): \"\n\t\t\t    \"out of memory\\n\");\n\t\t\tabort();\n\t\t}\n\t\tset_errno(ENOMEM);\n\t}\n\tif (config_stats && likely(ret != NULL)) {\n\t\ttsd_t *tsd;\n\n\t\tassert(usize == isalloc(tsdn, ret, config_prof));\n\t\ttsd = tsdn_tsd(tsdn);\n\t\t*tsd_thread_allocatedp_get(tsd) += usize;\n\t\t*tsd_thread_deallocatedp_get(tsd) += old_usize;\n\t}\n\tUTRACE(ptr, size, ret);\n\tJEMALLOC_VALGRIND_REALLOC(true, tsdn, ret, usize, true, ptr, old_usize,\n\t    old_rzsize, true, false);\n\twitness_assert_lockless(tsdn);\n\treturn (ret);\n}\n\nJEMALLOC_EXPORT void JEMALLOC_NOTHROW\nje_free(void *ptr)\n{\n\n\tUTRACE(ptr, 0, 0);\n\tif (likely(ptr != NULL)) {\n\t\ttsd_t *tsd = tsd_fetch();\n\t\twitness_assert_lockless(tsd_tsdn(tsd));\n\t\tif (likely(!malloc_slow))\n\t\t\tifree(tsd, ptr, tcache_get(tsd, false), false);\n\t\telse\n\t\t\tifree(tsd, ptr, tcache_get(tsd, false), true);\n\t\twitness_assert_lockless(tsd_tsdn(tsd));\n\t}\n}\n\n/*\n * End malloc(3)-compatible functions.\n */\n/******************************************************************************/\n/*\n * Begin non-standard override functions.\n */\n\n#ifdef JEMALLOC_OVERRIDE_MEMALIGN\nJEMALLOC_EXPORT JEMALLOC_ALLOCATOR JEMALLOC_RESTRICT_RETURN\nvoid JEMALLOC_NOTHROW *\nJEMALLOC_ATTR(malloc)\nje_memalign(size_t alignment, size_t size)\n{\n\tvoid *ret JEMALLOC_CC_SILENCE_INIT(NULL);\n\tif (unlikely(imemalign(&ret, alignment, size, 1) != 0))\n\t\tret = NULL;\n\treturn (ret);\n}\n#endif\n\n#ifdef JEMALLOC_OVERRIDE_VALLOC\nJEMALLOC_EXPORT JEMALLOC_ALLOCATOR JEMALLOC_RESTRICT_RETURN\nvoid JEMALLOC_NOTHROW *\nJEMALLOC_ATTR(malloc)\nje_valloc(size_t size)\n{\n\tvoid *ret JEMALLOC_CC_SILENCE_INIT(NULL);\n\tif (unlikely(imemalign(&ret, PAGE, size, 1) != 0))\n\t\tret = NULL;\n\treturn (ret);\n}\n#endif\n\n/*\n * is_malloc(je_malloc) is some macro magic to detect if jemalloc_defs.h has\n * #define je_malloc malloc\n */\n#define\tmalloc_is_malloc 1\n#define\tis_malloc_(a) malloc_is_ ## a\n#define\tis_malloc(a) is_malloc_(a)\n\n#if ((is_malloc(je_malloc) == 1) && defined(JEMALLOC_GLIBC_MALLOC_HOOK))\n/*\n * glibc provides the RTLD_DEEPBIND flag for dlopen which can make it possible\n * to inconsistently reference libc's malloc(3)-compatible functions\n * (https://bugzilla.mozilla.org/show_bug.cgi?id=493541).\n *\n * These definitions interpose hooks in glibc.  The functions are actually\n * passed an extra argument for the caller return address, which will be\n * ignored.\n */\nJEMALLOC_EXPORT void (*__free_hook)(void *ptr) = je_free;\nJEMALLOC_EXPORT void *(*__malloc_hook)(size_t size) = je_malloc;\nJEMALLOC_EXPORT void *(*__realloc_hook)(void *ptr, size_t size) = je_realloc;\n# ifdef JEMALLOC_GLIBC_MEMALIGN_HOOK\nJEMALLOC_EXPORT void *(*__memalign_hook)(size_t alignment, size_t size) =\n    je_memalign;\n# endif\n#endif\n\n/*\n * End non-standard override functions.\n */\n/******************************************************************************/\n/*\n * Begin non-standard functions.\n */\n\nJEMALLOC_ALWAYS_INLINE_C bool\nimallocx_flags_decode(tsd_t *tsd, size_t size, int flags, size_t *usize,\n    size_t *alignment, bool *zero, tcache_t **tcache, arena_t **arena)\n{\n\n\tif ((flags & MALLOCX_LG_ALIGN_MASK) == 0) {\n\t\t*alignment = 0;\n\t\t*usize = s2u(size);\n\t} else {\n\t\t*alignment = MALLOCX_ALIGN_GET_SPECIFIED(flags);\n\t\t*usize = sa2u(size, *alignment);\n\t}\n\tif (unlikely(*usize == 0 || *usize > HUGE_MAXCLASS))\n\t\treturn (true);\n\t*zero = MALLOCX_ZERO_GET(flags);\n\tif ((flags & MALLOCX_TCACHE_MASK) != 0) {\n\t\tif ((flags & MALLOCX_TCACHE_MASK) == MALLOCX_TCACHE_NONE)\n\t\t\t*tcache = NULL;\n\t\telse\n\t\t\t*tcache = tcaches_get(tsd, MALLOCX_TCACHE_GET(flags));\n\t} else\n\t\t*tcache = tcache_get(tsd, true);\n\tif ((flags & MALLOCX_ARENA_MASK) != 0) {\n\t\tunsigned arena_ind = MALLOCX_ARENA_GET(flags);\n\t\t*arena = arena_get(tsd_tsdn(tsd), arena_ind, true);\n\t\tif (unlikely(*arena == NULL))\n\t\t\treturn (true);\n\t} else\n\t\t*arena = NULL;\n\treturn (false);\n}\n\nJEMALLOC_ALWAYS_INLINE_C void *\nimallocx_flags(tsdn_t *tsdn, size_t usize, size_t alignment, bool zero,\n    tcache_t *tcache, arena_t *arena, bool slow_path)\n{\n\tszind_t ind;\n\n\tif (unlikely(alignment != 0))\n\t\treturn (ipalloct(tsdn, usize, alignment, zero, tcache, arena));\n\tind = size2index(usize);\n\tassert(ind < NSIZES);\n\treturn (iallocztm(tsdn, usize, ind, zero, tcache, false, arena,\n\t    slow_path));\n}\n\nstatic void *\nimallocx_prof_sample(tsdn_t *tsdn, size_t usize, size_t alignment, bool zero,\n    tcache_t *tcache, arena_t *arena, bool slow_path)\n{\n\tvoid *p;\n\n\tif (usize <= SMALL_MAXCLASS) {\n\t\tassert(((alignment == 0) ? s2u(LARGE_MINCLASS) :\n\t\t    sa2u(LARGE_MINCLASS, alignment)) == LARGE_MINCLASS);\n\t\tp = imallocx_flags(tsdn, LARGE_MINCLASS, alignment, zero,\n\t\t    tcache, arena, slow_path);\n\t\tif (p == NULL)\n\t\t\treturn (NULL);\n\t\tarena_prof_promoted(tsdn, p, usize);\n\t} else {\n\t\tp = imallocx_flags(tsdn, usize, alignment, zero, tcache, arena,\n\t\t    slow_path);\n\t}\n\n\treturn (p);\n}\n\nJEMALLOC_ALWAYS_INLINE_C void *\nimallocx_prof(tsd_t *tsd, size_t size, int flags, size_t *usize, bool slow_path)\n{\n\tvoid *p;\n\tsize_t alignment;\n\tbool zero;\n\ttcache_t *tcache;\n\tarena_t *arena;\n\tprof_tctx_t *tctx;\n\n\tif (unlikely(imallocx_flags_decode(tsd, size, flags, usize, &alignment,\n\t    &zero, &tcache, &arena)))\n\t\treturn (NULL);\n\ttctx = prof_alloc_prep(tsd, *usize, prof_active_get_unlocked(), true);\n\tif (likely((uintptr_t)tctx == (uintptr_t)1U)) {\n\t\tp = imallocx_flags(tsd_tsdn(tsd), *usize, alignment, zero,\n\t\t    tcache, arena, slow_path);\n\t} else if ((uintptr_t)tctx > (uintptr_t)1U) {\n\t\tp = imallocx_prof_sample(tsd_tsdn(tsd), *usize, alignment, zero,\n\t\t    tcache, arena, slow_path);\n\t} else\n\t\tp = NULL;\n\tif (unlikely(p == NULL)) {\n\t\tprof_alloc_rollback(tsd, tctx, true);\n\t\treturn (NULL);\n\t}\n\tprof_malloc(tsd_tsdn(tsd), p, *usize, tctx);\n\n\tassert(alignment == 0 || ((uintptr_t)p & (alignment - 1)) == ZU(0));\n\treturn (p);\n}\n\nJEMALLOC_ALWAYS_INLINE_C void *\nimallocx_no_prof(tsd_t *tsd, size_t size, int flags, size_t *usize,\n    bool slow_path)\n{\n\tvoid *p;\n\tsize_t alignment;\n\tbool zero;\n\ttcache_t *tcache;\n\tarena_t *arena;\n\n\tif (unlikely(imallocx_flags_decode(tsd, size, flags, usize, &alignment,\n\t    &zero, &tcache, &arena)))\n\t\treturn (NULL);\n\tp = imallocx_flags(tsd_tsdn(tsd), *usize, alignment, zero, tcache,\n\t    arena, slow_path);\n\tassert(alignment == 0 || ((uintptr_t)p & (alignment - 1)) == ZU(0));\n\treturn (p);\n}\n\n/* This function guarantees that *tsdn is non-NULL on success. */\nJEMALLOC_ALWAYS_INLINE_C void *\nimallocx_body(size_t size, int flags, tsdn_t **tsdn, size_t *usize,\n    bool slow_path)\n{\n\ttsd_t *tsd;\n\n\tif (slow_path && unlikely(malloc_init())) {\n\t\t*tsdn = NULL;\n\t\treturn (NULL);\n\t}\n\n\ttsd = tsd_fetch();\n\t*tsdn = tsd_tsdn(tsd);\n\twitness_assert_lockless(tsd_tsdn(tsd));\n\n\tif (likely(flags == 0)) {\n\t\tszind_t ind = size2index(size);\n\t\tif (unlikely(ind >= NSIZES))\n\t\t\treturn (NULL);\n\t\tif (config_stats || (config_prof && opt_prof) || (slow_path &&\n\t\t    config_valgrind && unlikely(in_valgrind))) {\n\t\t\t*usize = index2size(ind);\n\t\t\tassert(*usize > 0 && *usize <= HUGE_MAXCLASS);\n\t\t}\n\n\t\tif (config_prof && opt_prof) {\n\t\t\treturn (ialloc_prof(tsd, *usize, ind, false,\n\t\t\t    slow_path));\n\t\t}\n\n\t\treturn (ialloc(tsd, size, ind, false, slow_path));\n\t}\n\n\tif (config_prof && opt_prof)\n\t\treturn (imallocx_prof(tsd, size, flags, usize, slow_path));\n\n\treturn (imallocx_no_prof(tsd, size, flags, usize, slow_path));\n}\n\nJEMALLOC_EXPORT JEMALLOC_ALLOCATOR JEMALLOC_RESTRICT_RETURN\nvoid JEMALLOC_NOTHROW *\nJEMALLOC_ATTR(malloc) JEMALLOC_ALLOC_SIZE(1)\nje_mallocx(size_t size, int flags)\n{\n\ttsdn_t *tsdn;\n\tvoid *p;\n\tsize_t usize;\n\n\tassert(size != 0);\n\n\tif (likely(!malloc_slow)) {\n\t\tp = imallocx_body(size, flags, &tsdn, &usize, false);\n\t\tialloc_post_check(p, tsdn, usize, \"mallocx\", false, false);\n\t} else {\n\t\tp = imallocx_body(size, flags, &tsdn, &usize, true);\n\t\tialloc_post_check(p, tsdn, usize, \"mallocx\", false, true);\n\t\tUTRACE(0, size, p);\n\t\tJEMALLOC_VALGRIND_MALLOC(p != NULL, tsdn, p, usize,\n\t\t    MALLOCX_ZERO_GET(flags));\n\t}\n\n\treturn (p);\n}\n\nstatic void *\nirallocx_prof_sample(tsd_t *tsd, void *old_ptr, size_t old_usize,\n    size_t usize, size_t alignment, bool zero, tcache_t *tcache, arena_t *arena,\n    prof_tctx_t *tctx)\n{\n\tvoid *p;\n\n\tif (tctx == NULL)\n\t\treturn (NULL);\n\tif (usize <= SMALL_MAXCLASS) {\n\t\tp = iralloct(tsd, old_ptr, old_usize, LARGE_MINCLASS, alignment,\n\t\t    zero, tcache, arena);\n\t\tif (p == NULL)\n\t\t\treturn (NULL);\n\t\tarena_prof_promoted(tsd_tsdn(tsd), p, usize);\n\t} else {\n\t\tp = iralloct(tsd, old_ptr, old_usize, usize, alignment, zero,\n\t\t    tcache, arena);\n\t}\n\n\treturn (p);\n}\n\nJEMALLOC_ALWAYS_INLINE_C void *\nirallocx_prof(tsd_t *tsd, void *old_ptr, size_t old_usize, size_t size,\n    size_t alignment, size_t *usize, bool zero, tcache_t *tcache,\n    arena_t *arena)\n{\n\tvoid *p;\n\tbool prof_active;\n\tprof_tctx_t *old_tctx, *tctx;\n\n\tprof_active = prof_active_get_unlocked();\n\told_tctx = prof_tctx_get(tsd_tsdn(tsd), old_ptr);\n\ttctx = prof_alloc_prep(tsd, *usize, prof_active, false);\n\tif (unlikely((uintptr_t)tctx != (uintptr_t)1U)) {\n\t\tp = irallocx_prof_sample(tsd, old_ptr, old_usize, *usize,\n\t\t    alignment, zero, tcache, arena, tctx);\n\t} else {\n\t\tp = iralloct(tsd, old_ptr, old_usize, size, alignment, zero,\n\t\t    tcache, arena);\n\t}\n\tif (unlikely(p == NULL)) {\n\t\tprof_alloc_rollback(tsd, tctx, false);\n\t\treturn (NULL);\n\t}\n\n\tif (p == old_ptr && alignment != 0) {\n\t\t/*\n\t\t * The allocation did not move, so it is possible that the size\n\t\t * class is smaller than would guarantee the requested\n\t\t * alignment, and that the alignment constraint was\n\t\t * serendipitously satisfied.  Additionally, old_usize may not\n\t\t * be the same as the current usize because of in-place large\n\t\t * reallocation.  Therefore, query the actual value of usize.\n\t\t */\n\t\t*usize = isalloc(tsd_tsdn(tsd), p, config_prof);\n\t}\n\tprof_realloc(tsd, p, *usize, tctx, prof_active, false, old_ptr,\n\t    old_usize, old_tctx);\n\n\treturn (p);\n}\n\nJEMALLOC_EXPORT JEMALLOC_ALLOCATOR JEMALLOC_RESTRICT_RETURN\nvoid JEMALLOC_NOTHROW *\nJEMALLOC_ALLOC_SIZE(2)\nje_rallocx(void *ptr, size_t size, int flags)\n{\n\tvoid *p;\n\ttsd_t *tsd;\n\tsize_t usize;\n\tsize_t old_usize;\n\tUNUSED size_t old_rzsize JEMALLOC_CC_SILENCE_INIT(0);\n\tsize_t alignment = MALLOCX_ALIGN_GET(flags);\n\tbool zero = flags & MALLOCX_ZERO;\n\tarena_t *arena;\n\ttcache_t *tcache;\n\n\tassert(ptr != NULL);\n\tassert(size != 0);\n\tassert(malloc_initialized() || IS_INITIALIZER);\n\tmalloc_thread_init();\n\ttsd = tsd_fetch();\n\twitness_assert_lockless(tsd_tsdn(tsd));\n\n\tif (unlikely((flags & MALLOCX_ARENA_MASK) != 0)) {\n\t\tunsigned arena_ind = MALLOCX_ARENA_GET(flags);\n\t\tarena = arena_get(tsd_tsdn(tsd), arena_ind, true);\n\t\tif (unlikely(arena == NULL))\n\t\t\tgoto label_oom;\n\t} else\n\t\tarena = NULL;\n\n\tif (unlikely((flags & MALLOCX_TCACHE_MASK) != 0)) {\n\t\tif ((flags & MALLOCX_TCACHE_MASK) == MALLOCX_TCACHE_NONE)\n\t\t\ttcache = NULL;\n\t\telse\n\t\t\ttcache = tcaches_get(tsd, MALLOCX_TCACHE_GET(flags));\n\t} else\n\t\ttcache = tcache_get(tsd, true);\n\n\told_usize = isalloc(tsd_tsdn(tsd), ptr, config_prof);\n\tif (config_valgrind && unlikely(in_valgrind))\n\t\told_rzsize = u2rz(old_usize);\n\n\tif (config_prof && opt_prof) {\n\t\tusize = (alignment == 0) ? s2u(size) : sa2u(size, alignment);\n\t\tif (unlikely(usize == 0 || usize > HUGE_MAXCLASS))\n\t\t\tgoto label_oom;\n\t\tp = irallocx_prof(tsd, ptr, old_usize, size, alignment, &usize,\n\t\t    zero, tcache, arena);\n\t\tif (unlikely(p == NULL))\n\t\t\tgoto label_oom;\n\t} else {\n\t\tp = iralloct(tsd, ptr, old_usize, size, alignment, zero,\n\t\t     tcache, arena);\n\t\tif (unlikely(p == NULL))\n\t\t\tgoto label_oom;\n\t\tif (config_stats || (config_valgrind && unlikely(in_valgrind)))\n\t\t\tusize = isalloc(tsd_tsdn(tsd), p, config_prof);\n\t}\n\tassert(alignment == 0 || ((uintptr_t)p & (alignment - 1)) == ZU(0));\n\n\tif (config_stats) {\n\t\t*tsd_thread_allocatedp_get(tsd) += usize;\n\t\t*tsd_thread_deallocatedp_get(tsd) += old_usize;\n\t}\n\tUTRACE(ptr, size, p);\n\tJEMALLOC_VALGRIND_REALLOC(true, tsd_tsdn(tsd), p, usize, false, ptr,\n\t    old_usize, old_rzsize, false, zero);\n\twitness_assert_lockless(tsd_tsdn(tsd));\n\treturn (p);\nlabel_oom:\n\tif (config_xmalloc && unlikely(opt_xmalloc)) {\n\t\tmalloc_write(\"<jemalloc>: Error in rallocx(): out of memory\\n\");\n\t\tabort();\n\t}\n\tUTRACE(ptr, size, 0);\n\twitness_assert_lockless(tsd_tsdn(tsd));\n\treturn (NULL);\n}\n\nJEMALLOC_ALWAYS_INLINE_C size_t\nixallocx_helper(tsdn_t *tsdn, void *ptr, size_t old_usize, size_t size,\n    size_t extra, size_t alignment, bool zero)\n{\n\tsize_t usize;\n\n\tif (ixalloc(tsdn, ptr, old_usize, size, extra, alignment, zero))\n\t\treturn (old_usize);\n\tusize = isalloc(tsdn, ptr, config_prof);\n\n\treturn (usize);\n}\n\nstatic size_t\nixallocx_prof_sample(tsdn_t *tsdn, void *ptr, size_t old_usize, size_t size,\n    size_t extra, size_t alignment, bool zero, prof_tctx_t *tctx)\n{\n\tsize_t usize;\n\n\tif (tctx == NULL)\n\t\treturn (old_usize);\n\tusize = ixallocx_helper(tsdn, ptr, old_usize, size, extra, alignment,\n\t    zero);\n\n\treturn (usize);\n}\n\nJEMALLOC_ALWAYS_INLINE_C size_t\nixallocx_prof(tsd_t *tsd, void *ptr, size_t old_usize, size_t size,\n    size_t extra, size_t alignment, bool zero)\n{\n\tsize_t usize_max, usize;\n\tbool prof_active;\n\tprof_tctx_t *old_tctx, *tctx;\n\n\tprof_active = prof_active_get_unlocked();\n\told_tctx = prof_tctx_get(tsd_tsdn(tsd), ptr);\n\t/*\n\t * usize isn't knowable before ixalloc() returns when extra is non-zero.\n\t * Therefore, compute its maximum possible value and use that in\n\t * prof_alloc_prep() to decide whether to capture a backtrace.\n\t * prof_realloc() will use the actual usize to decide whether to sample.\n\t */\n\tif (alignment == 0) {\n\t\tusize_max = s2u(size+extra);\n\t\tassert(usize_max > 0 && usize_max <= HUGE_MAXCLASS);\n\t} else {\n\t\tusize_max = sa2u(size+extra, alignment);\n\t\tif (unlikely(usize_max == 0 || usize_max > HUGE_MAXCLASS)) {\n\t\t\t/*\n\t\t\t * usize_max is out of range, and chances are that\n\t\t\t * allocation will fail, but use the maximum possible\n\t\t\t * value and carry on with prof_alloc_prep(), just in\n\t\t\t * case allocation succeeds.\n\t\t\t */\n\t\t\tusize_max = HUGE_MAXCLASS;\n\t\t}\n\t}\n\ttctx = prof_alloc_prep(tsd, usize_max, prof_active, false);\n\n\tif (unlikely((uintptr_t)tctx != (uintptr_t)1U)) {\n\t\tusize = ixallocx_prof_sample(tsd_tsdn(tsd), ptr, old_usize,\n\t\t    size, extra, alignment, zero, tctx);\n\t} else {\n\t\tusize = ixallocx_helper(tsd_tsdn(tsd), ptr, old_usize, size,\n\t\t    extra, alignment, zero);\n\t}\n\tif (usize == old_usize) {\n\t\tprof_alloc_rollback(tsd, tctx, false);\n\t\treturn (usize);\n\t}\n\tprof_realloc(tsd, ptr, usize, tctx, prof_active, false, ptr, old_usize,\n\t    old_tctx);\n\n\treturn (usize);\n}\n\nJEMALLOC_EXPORT size_t JEMALLOC_NOTHROW\nje_xallocx(void *ptr, size_t size, size_t extra, int flags)\n{\n\ttsd_t *tsd;\n\tsize_t usize, old_usize;\n\tUNUSED size_t old_rzsize JEMALLOC_CC_SILENCE_INIT(0);\n\tsize_t alignment = MALLOCX_ALIGN_GET(flags);\n\tbool zero = flags & MALLOCX_ZERO;\n\n\tassert(ptr != NULL);\n\tassert(size != 0);\n\tassert(SIZE_T_MAX - size >= extra);\n\tassert(malloc_initialized() || IS_INITIALIZER);\n\tmalloc_thread_init();\n\ttsd = tsd_fetch();\n\twitness_assert_lockless(tsd_tsdn(tsd));\n\n\told_usize = isalloc(tsd_tsdn(tsd), ptr, config_prof);\n\n\t/*\n\t * The API explicitly absolves itself of protecting against (size +\n\t * extra) numerical overflow, but we may need to clamp extra to avoid\n\t * exceeding HUGE_MAXCLASS.\n\t *\n\t * Ordinarily, size limit checking is handled deeper down, but here we\n\t * have to check as part of (size + extra) clamping, since we need the\n\t * clamped value in the above helper functions.\n\t */\n\tif (unlikely(size > HUGE_MAXCLASS)) {\n\t\tusize = old_usize;\n\t\tgoto label_not_resized;\n\t}\n\tif (unlikely(HUGE_MAXCLASS - size < extra))\n\t\textra = HUGE_MAXCLASS - size;\n\n\tif (config_valgrind && unlikely(in_valgrind))\n\t\told_rzsize = u2rz(old_usize);\n\n\tif (config_prof && opt_prof) {\n\t\tusize = ixallocx_prof(tsd, ptr, old_usize, size, extra,\n\t\t    alignment, zero);\n\t} else {\n\t\tusize = ixallocx_helper(tsd_tsdn(tsd), ptr, old_usize, size,\n\t\t    extra, alignment, zero);\n\t}\n\tif (unlikely(usize == old_usize))\n\t\tgoto label_not_resized;\n\n\tif (config_stats) {\n\t\t*tsd_thread_allocatedp_get(tsd) += usize;\n\t\t*tsd_thread_deallocatedp_get(tsd) += old_usize;\n\t}\n\tJEMALLOC_VALGRIND_REALLOC(false, tsd_tsdn(tsd), ptr, usize, false, ptr,\n\t    old_usize, old_rzsize, false, zero);\nlabel_not_resized:\n\tUTRACE(ptr, size, ptr);\n\twitness_assert_lockless(tsd_tsdn(tsd));\n\treturn (usize);\n}\n\nJEMALLOC_EXPORT size_t JEMALLOC_NOTHROW\nJEMALLOC_ATTR(pure)\nje_sallocx(const void *ptr, int flags)\n{\n\tsize_t usize;\n\ttsdn_t *tsdn;\n\n\tassert(malloc_initialized() || IS_INITIALIZER);\n\tmalloc_thread_init();\n\n\ttsdn = tsdn_fetch();\n\twitness_assert_lockless(tsdn);\n\n\tif (config_ivsalloc)\n\t\tusize = ivsalloc(tsdn, ptr, config_prof);\n\telse\n\t\tusize = isalloc(tsdn, ptr, config_prof);\n\n\twitness_assert_lockless(tsdn);\n\treturn (usize);\n}\n\nJEMALLOC_EXPORT void JEMALLOC_NOTHROW\nje_dallocx(void *ptr, int flags)\n{\n\ttsd_t *tsd;\n\ttcache_t *tcache;\n\n\tassert(ptr != NULL);\n\tassert(malloc_initialized() || IS_INITIALIZER);\n\n\ttsd = tsd_fetch();\n\twitness_assert_lockless(tsd_tsdn(tsd));\n\tif (unlikely((flags & MALLOCX_TCACHE_MASK) != 0)) {\n\t\tif ((flags & MALLOCX_TCACHE_MASK) == MALLOCX_TCACHE_NONE)\n\t\t\ttcache = NULL;\n\t\telse\n\t\t\ttcache = tcaches_get(tsd, MALLOCX_TCACHE_GET(flags));\n\t} else\n\t\ttcache = tcache_get(tsd, false);\n\n\tUTRACE(ptr, 0, 0);\n\tif (likely(!malloc_slow))\n\t\tifree(tsd, ptr, tcache, false);\n\telse\n\t\tifree(tsd, ptr, tcache, true);\n\twitness_assert_lockless(tsd_tsdn(tsd));\n}\n\nJEMALLOC_ALWAYS_INLINE_C size_t\ninallocx(tsdn_t *tsdn, size_t size, int flags)\n{\n\tsize_t usize;\n\n\twitness_assert_lockless(tsdn);\n\n\tif (likely((flags & MALLOCX_LG_ALIGN_MASK) == 0))\n\t\tusize = s2u(size);\n\telse\n\t\tusize = sa2u(size, MALLOCX_ALIGN_GET_SPECIFIED(flags));\n\twitness_assert_lockless(tsdn);\n\treturn (usize);\n}\n\nJEMALLOC_EXPORT void JEMALLOC_NOTHROW\nje_sdallocx(void *ptr, size_t size, int flags)\n{\n\ttsd_t *tsd;\n\ttcache_t *tcache;\n\tsize_t usize;\n\n\tassert(ptr != NULL);\n\tassert(malloc_initialized() || IS_INITIALIZER);\n\ttsd = tsd_fetch();\n\tusize = inallocx(tsd_tsdn(tsd), size, flags);\n\tassert(usize == isalloc(tsd_tsdn(tsd), ptr, config_prof));\n\n\twitness_assert_lockless(tsd_tsdn(tsd));\n\tif (unlikely((flags & MALLOCX_TCACHE_MASK) != 0)) {\n\t\tif ((flags & MALLOCX_TCACHE_MASK) == MALLOCX_TCACHE_NONE)\n\t\t\ttcache = NULL;\n\t\telse\n\t\t\ttcache = tcaches_get(tsd, MALLOCX_TCACHE_GET(flags));\n\t} else\n\t\ttcache = tcache_get(tsd, false);\n\n\tUTRACE(ptr, 0, 0);\n\tif (likely(!malloc_slow))\n\t\tisfree(tsd, ptr, usize, tcache, false);\n\telse\n\t\tisfree(tsd, ptr, usize, tcache, true);\n\twitness_assert_lockless(tsd_tsdn(tsd));\n}\n\nJEMALLOC_EXPORT size_t JEMALLOC_NOTHROW\nJEMALLOC_ATTR(pure)\nje_nallocx(size_t size, int flags)\n{\n\tsize_t usize;\n\ttsdn_t *tsdn;\n\n\tassert(size != 0);\n\n\tif (unlikely(malloc_init()))\n\t\treturn (0);\n\n\ttsdn = tsdn_fetch();\n\twitness_assert_lockless(tsdn);\n\n\tusize = inallocx(tsdn, size, flags);\n\tif (unlikely(usize > HUGE_MAXCLASS))\n\t\treturn (0);\n\n\twitness_assert_lockless(tsdn);\n\treturn (usize);\n}\n\nJEMALLOC_EXPORT int JEMALLOC_NOTHROW\nje_mallctl(const char *name, void *oldp, size_t *oldlenp, void *newp,\n    size_t newlen)\n{\n\tint ret;\n\ttsd_t *tsd;\n\n\tif (unlikely(malloc_init()))\n\t\treturn (EAGAIN);\n\n\ttsd = tsd_fetch();\n\twitness_assert_lockless(tsd_tsdn(tsd));\n\tret = ctl_byname(tsd, name, oldp, oldlenp, newp, newlen);\n\twitness_assert_lockless(tsd_tsdn(tsd));\n\treturn (ret);\n}\n\nJEMALLOC_EXPORT int JEMALLOC_NOTHROW\nje_mallctlnametomib(const char *name, size_t *mibp, size_t *miblenp)\n{\n\tint ret;\n\ttsdn_t *tsdn;\n\n\tif (unlikely(malloc_init()))\n\t\treturn (EAGAIN);\n\n\ttsdn = tsdn_fetch();\n\twitness_assert_lockless(tsdn);\n\tret = ctl_nametomib(tsdn, name, mibp, miblenp);\n\twitness_assert_lockless(tsdn);\n\treturn (ret);\n}\n\nJEMALLOC_EXPORT int JEMALLOC_NOTHROW\nje_mallctlbymib(const size_t *mib, size_t miblen, void *oldp, size_t *oldlenp,\n  void *newp, size_t newlen)\n{\n\tint ret;\n\ttsd_t *tsd;\n\n\tif (unlikely(malloc_init()))\n\t\treturn (EAGAIN);\n\n\ttsd = tsd_fetch();\n\twitness_assert_lockless(tsd_tsdn(tsd));\n\tret = ctl_bymib(tsd, mib, miblen, oldp, oldlenp, newp, newlen);\n\twitness_assert_lockless(tsd_tsdn(tsd));\n\treturn (ret);\n}\n\nJEMALLOC_EXPORT void JEMALLOC_NOTHROW\nje_malloc_stats_print(void (*write_cb)(void *, const char *), void *cbopaque,\n    const char *opts)\n{\n\ttsdn_t *tsdn;\n\n\ttsdn = tsdn_fetch();\n\twitness_assert_lockless(tsdn);\n\tstats_print(write_cb, cbopaque, opts);\n\twitness_assert_lockless(tsdn);\n}\n\nJEMALLOC_EXPORT size_t JEMALLOC_NOTHROW\nje_malloc_usable_size(JEMALLOC_USABLE_SIZE_CONST void *ptr)\n{\n\tsize_t ret;\n\ttsdn_t *tsdn;\n\n\tassert(malloc_initialized() || IS_INITIALIZER);\n\tmalloc_thread_init();\n\n\ttsdn = tsdn_fetch();\n\twitness_assert_lockless(tsdn);\n\n\tif (config_ivsalloc)\n\t\tret = ivsalloc(tsdn, ptr, config_prof);\n\telse\n\t\tret = (ptr == NULL) ? 0 : isalloc(tsdn, ptr, config_prof);\n\n\twitness_assert_lockless(tsdn);\n\treturn (ret);\n}\n\n/*\n * End non-standard functions.\n */\n/******************************************************************************/\n/*\n * The following functions are used by threading libraries for protection of\n * malloc during fork().\n */\n\n/*\n * If an application creates a thread before doing any allocation in the main\n * thread, then calls fork(2) in the main thread followed by memory allocation\n * in the child process, a race can occur that results in deadlock within the\n * child: the main thread may have forked while the created thread had\n * partially initialized the allocator.  Ordinarily jemalloc prevents\n * fork/malloc races via the following functions it registers during\n * initialization using pthread_atfork(), but of course that does no good if\n * the allocator isn't fully initialized at fork time.  The following library\n * constructor is a partial solution to this problem.  It may still be possible\n * to trigger the deadlock described above, but doing so would involve forking\n * via a library constructor that runs before jemalloc's runs.\n */\n#ifndef JEMALLOC_JET\nJEMALLOC_ATTR(constructor)\nstatic void\njemalloc_constructor(void)\n{\n\n\tmalloc_init();\n}\n#endif\n\n#ifndef JEMALLOC_MUTEX_INIT_CB\nvoid\njemalloc_prefork(void)\n#else\nJEMALLOC_EXPORT void\n_malloc_prefork(void)\n#endif\n{\n\ttsd_t *tsd;\n\tunsigned i, j, narenas;\n\tarena_t *arena;\n\n#ifdef JEMALLOC_MUTEX_INIT_CB\n\tif (!malloc_initialized())\n\t\treturn;\n#endif\n\tassert(malloc_initialized());\n\n\ttsd = tsd_fetch();\n\n\tnarenas = narenas_total_get();\n\n\twitness_prefork(tsd);\n\t/* Acquire all mutexes in a safe order. */\n\tctl_prefork(tsd_tsdn(tsd));\n\tmalloc_mutex_prefork(tsd_tsdn(tsd), &arenas_lock);\n\tprof_prefork0(tsd_tsdn(tsd));\n\tfor (i = 0; i < 3; i++) {\n\t\tfor (j = 0; j < narenas; j++) {\n\t\t\tif ((arena = arena_get(tsd_tsdn(tsd), j, false)) !=\n\t\t\t    NULL) {\n\t\t\t\tswitch (i) {\n\t\t\t\tcase 0:\n\t\t\t\t\tarena_prefork0(tsd_tsdn(tsd), arena);\n\t\t\t\t\tbreak;\n\t\t\t\tcase 1:\n\t\t\t\t\tarena_prefork1(tsd_tsdn(tsd), arena);\n\t\t\t\t\tbreak;\n\t\t\t\tcase 2:\n\t\t\t\t\tarena_prefork2(tsd_tsdn(tsd), arena);\n\t\t\t\t\tbreak;\n\t\t\t\tdefault: not_reached();\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\tbase_prefork(tsd_tsdn(tsd));\n\tchunk_prefork(tsd_tsdn(tsd));\n\tfor (i = 0; i < narenas; i++) {\n\t\tif ((arena = arena_get(tsd_tsdn(tsd), i, false)) != NULL)\n\t\t\tarena_prefork3(tsd_tsdn(tsd), arena);\n\t}\n\tprof_prefork1(tsd_tsdn(tsd));\n}\n\n#ifndef JEMALLOC_MUTEX_INIT_CB\nvoid\njemalloc_postfork_parent(void)\n#else\nJEMALLOC_EXPORT void\n_malloc_postfork(void)\n#endif\n{\n\ttsd_t *tsd;\n\tunsigned i, narenas;\n\n#ifdef JEMALLOC_MUTEX_INIT_CB\n\tif (!malloc_initialized())\n\t\treturn;\n#endif\n\tassert(malloc_initialized());\n\n\ttsd = tsd_fetch();\n\n\twitness_postfork_parent(tsd);\n\t/* Release all mutexes, now that fork() has completed. */\n\tchunk_postfork_parent(tsd_tsdn(tsd));\n\tbase_postfork_parent(tsd_tsdn(tsd));\n\tfor (i = 0, narenas = narenas_total_get(); i < narenas; i++) {\n\t\tarena_t *arena;\n\n\t\tif ((arena = arena_get(tsd_tsdn(tsd), i, false)) != NULL)\n\t\t\tarena_postfork_parent(tsd_tsdn(tsd), arena);\n\t}\n\tprof_postfork_parent(tsd_tsdn(tsd));\n\tmalloc_mutex_postfork_parent(tsd_tsdn(tsd), &arenas_lock);\n\tctl_postfork_parent(tsd_tsdn(tsd));\n}\n\nvoid\njemalloc_postfork_child(void)\n{\n\ttsd_t *tsd;\n\tunsigned i, narenas;\n\n\tassert(malloc_initialized());\n\n\ttsd = tsd_fetch();\n\n\twitness_postfork_child(tsd);\n\t/* Release all mutexes, now that fork() has completed. */\n\tchunk_postfork_child(tsd_tsdn(tsd));\n\tbase_postfork_child(tsd_tsdn(tsd));\n\tfor (i = 0, narenas = narenas_total_get(); i < narenas; i++) {\n\t\tarena_t *arena;\n\n\t\tif ((arena = arena_get(tsd_tsdn(tsd), i, false)) != NULL)\n\t\t\tarena_postfork_child(tsd_tsdn(tsd), arena);\n\t}\n\tprof_postfork_child(tsd_tsdn(tsd));\n\tmalloc_mutex_postfork_child(tsd_tsdn(tsd), &arenas_lock);\n\tctl_postfork_child(tsd_tsdn(tsd));\n}\n\n/******************************************************************************/\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/deps/jemalloc/src/mb.c",
    "content": "#define\tJEMALLOC_MB_C_\n#include \"jemalloc/internal/jemalloc_internal.h\"\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/deps/jemalloc/src/mutex.c",
    "content": "#define\tJEMALLOC_MUTEX_C_\n#include \"jemalloc/internal/jemalloc_internal.h\"\n\n#if defined(JEMALLOC_LAZY_LOCK) && !defined(_WIN32)\n#include <dlfcn.h>\n#endif\n\n#ifndef _CRT_SPINCOUNT\n#define\t_CRT_SPINCOUNT 4000\n#endif\n\n/******************************************************************************/\n/* Data. */\n\n#ifdef JEMALLOC_LAZY_LOCK\nbool isthreaded = false;\n#endif\n#ifdef JEMALLOC_MUTEX_INIT_CB\nstatic bool\t\tpostpone_init = true;\nstatic malloc_mutex_t\t*postponed_mutexes = NULL;\n#endif\n\n#if defined(JEMALLOC_LAZY_LOCK) && !defined(_WIN32)\nstatic void\tpthread_create_once(void);\n#endif\n\n/******************************************************************************/\n/*\n * We intercept pthread_create() calls in order to toggle isthreaded if the\n * process goes multi-threaded.\n */\n\n#if defined(JEMALLOC_LAZY_LOCK) && !defined(_WIN32)\nstatic int (*pthread_create_fptr)(pthread_t *__restrict, const pthread_attr_t *,\n    void *(*)(void *), void *__restrict);\n\nstatic void\npthread_create_once(void)\n{\n\n\tpthread_create_fptr = dlsym(RTLD_NEXT, \"pthread_create\");\n\tif (pthread_create_fptr == NULL) {\n\t\tmalloc_write(\"<jemalloc>: Error in dlsym(RTLD_NEXT, \"\n\t\t    \"\\\"pthread_create\\\")\\n\");\n\t\tabort();\n\t}\n\n\tisthreaded = true;\n}\n\nJEMALLOC_EXPORT int\npthread_create(pthread_t *__restrict thread,\n    const pthread_attr_t *__restrict attr, void *(*start_routine)(void *),\n    void *__restrict arg)\n{\n\tstatic pthread_once_t once_control = PTHREAD_ONCE_INIT;\n\n\tpthread_once(&once_control, pthread_create_once);\n\n\treturn (pthread_create_fptr(thread, attr, start_routine, arg));\n}\n#endif\n\n/******************************************************************************/\n\n#ifdef JEMALLOC_MUTEX_INIT_CB\nJEMALLOC_EXPORT int\t_pthread_mutex_init_calloc_cb(pthread_mutex_t *mutex,\n    void *(calloc_cb)(size_t, size_t));\n#endif\n\nbool\nmalloc_mutex_init(malloc_mutex_t *mutex, const char *name, witness_rank_t rank)\n{\n\n#ifdef _WIN32\n#  if _WIN32_WINNT >= 0x0600\n\tInitializeSRWLock(&mutex->lock);\n#  else\n\tif (!InitializeCriticalSectionAndSpinCount(&mutex->lock,\n\t    _CRT_SPINCOUNT))\n\t\treturn (true);\n#  endif\n#elif (defined(JEMALLOC_OSSPIN))\n\tmutex->lock = 0;\n#elif (defined(JEMALLOC_MUTEX_INIT_CB))\n\tif (postpone_init) {\n\t\tmutex->postponed_next = postponed_mutexes;\n\t\tpostponed_mutexes = mutex;\n\t} else {\n\t\tif (_pthread_mutex_init_calloc_cb(&mutex->lock,\n\t\t    bootstrap_calloc) != 0)\n\t\t\treturn (true);\n\t}\n#else\n\tpthread_mutexattr_t attr;\n\n\tif (pthread_mutexattr_init(&attr) != 0)\n\t\treturn (true);\n\tpthread_mutexattr_settype(&attr, MALLOC_MUTEX_TYPE);\n\tif (pthread_mutex_init(&mutex->lock, &attr) != 0) {\n\t\tpthread_mutexattr_destroy(&attr);\n\t\treturn (true);\n\t}\n\tpthread_mutexattr_destroy(&attr);\n#endif\n\tif (config_debug)\n\t\twitness_init(&mutex->witness, name, rank, NULL);\n\treturn (false);\n}\n\nvoid\nmalloc_mutex_prefork(tsdn_t *tsdn, malloc_mutex_t *mutex)\n{\n\n\tmalloc_mutex_lock(tsdn, mutex);\n}\n\nvoid\nmalloc_mutex_postfork_parent(tsdn_t *tsdn, malloc_mutex_t *mutex)\n{\n\n\tmalloc_mutex_unlock(tsdn, mutex);\n}\n\nvoid\nmalloc_mutex_postfork_child(tsdn_t *tsdn, malloc_mutex_t *mutex)\n{\n\n#ifdef JEMALLOC_MUTEX_INIT_CB\n\tmalloc_mutex_unlock(tsdn, mutex);\n#else\n\tif (malloc_mutex_init(mutex, mutex->witness.name,\n\t    mutex->witness.rank)) {\n\t\tmalloc_printf(\"<jemalloc>: Error re-initializing mutex in \"\n\t\t    \"child\\n\");\n\t\tif (opt_abort)\n\t\t\tabort();\n\t}\n#endif\n}\n\nbool\nmalloc_mutex_boot(void)\n{\n\n#ifdef JEMALLOC_MUTEX_INIT_CB\n\tpostpone_init = false;\n\twhile (postponed_mutexes != NULL) {\n\t\tif (_pthread_mutex_init_calloc_cb(&postponed_mutexes->lock,\n\t\t    bootstrap_calloc) != 0)\n\t\t\treturn (true);\n\t\tpostponed_mutexes = postponed_mutexes->postponed_next;\n\t}\n#endif\n\treturn (false);\n}\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/deps/jemalloc/src/nstime.c",
    "content": "#include \"jemalloc/internal/jemalloc_internal.h\"\n\n#define\tBILLION\tUINT64_C(1000000000)\n\nvoid\nnstime_init(nstime_t *time, uint64_t ns)\n{\n\n\ttime->ns = ns;\n}\n\nvoid\nnstime_init2(nstime_t *time, uint64_t sec, uint64_t nsec)\n{\n\n\ttime->ns = sec * BILLION + nsec;\n}\n\nuint64_t\nnstime_ns(const nstime_t *time)\n{\n\n\treturn (time->ns);\n}\n\nuint64_t\nnstime_sec(const nstime_t *time)\n{\n\n\treturn (time->ns / BILLION);\n}\n\nuint64_t\nnstime_nsec(const nstime_t *time)\n{\n\n\treturn (time->ns % BILLION);\n}\n\nvoid\nnstime_copy(nstime_t *time, const nstime_t *source)\n{\n\n\t*time = *source;\n}\n\nint\nnstime_compare(const nstime_t *a, const nstime_t *b)\n{\n\n\treturn ((a->ns > b->ns) - (a->ns < b->ns));\n}\n\nvoid\nnstime_add(nstime_t *time, const nstime_t *addend)\n{\n\n\tassert(UINT64_MAX - time->ns >= addend->ns);\n\n\ttime->ns += addend->ns;\n}\n\nvoid\nnstime_subtract(nstime_t *time, const nstime_t *subtrahend)\n{\n\n\tassert(nstime_compare(time, subtrahend) >= 0);\n\n\ttime->ns -= subtrahend->ns;\n}\n\nvoid\nnstime_imultiply(nstime_t *time, uint64_t multiplier)\n{\n\n\tassert((((time->ns | multiplier) & (UINT64_MAX << (sizeof(uint64_t) <<\n\t    2))) == 0) || ((time->ns * multiplier) / multiplier == time->ns));\n\n\ttime->ns *= multiplier;\n}\n\nvoid\nnstime_idivide(nstime_t *time, uint64_t divisor)\n{\n\n\tassert(divisor != 0);\n\n\ttime->ns /= divisor;\n}\n\nuint64_t\nnstime_divide(const nstime_t *time, const nstime_t *divisor)\n{\n\n\tassert(divisor->ns != 0);\n\n\treturn (time->ns / divisor->ns);\n}\n\n#ifdef JEMALLOC_JET\n#undef nstime_update\n#define\tnstime_update JEMALLOC_N(n_nstime_update)\n#endif\nbool\nnstime_update(nstime_t *time)\n{\n\tnstime_t old_time;\n\n\tnstime_copy(&old_time, time);\n\n#ifdef _WIN32\n\t{\n\t\tFILETIME ft;\n\t\tuint64_t ticks;\n\t\tGetSystemTimeAsFileTime(&ft);\n\t\tticks = (((uint64_t)ft.dwHighDateTime) << 32) |\n\t\t    ft.dwLowDateTime;\n\t\ttime->ns = ticks * 100;\n\t}\n#elif JEMALLOC_CLOCK_GETTIME\n\t{\n\t\tstruct timespec ts;\n\n\t\tif (sysconf(_SC_MONOTONIC_CLOCK) > 0)\n\t\t\tclock_gettime(CLOCK_MONOTONIC, &ts);\n\t\telse\n\t\t\tclock_gettime(CLOCK_REALTIME, &ts);\n\t\ttime->ns = ts.tv_sec * BILLION + ts.tv_nsec;\n\t}\n#else\n\t{\n\t\tstruct timeval tv;\n\t\tgettimeofday(&tv, NULL);\n\t\ttime->ns = tv.tv_sec * BILLION + tv.tv_usec * 1000;\n\t}\n#endif\n\n\t/* Handle non-monotonic clocks. */\n\tif (unlikely(nstime_compare(&old_time, time) > 0)) {\n\t\tnstime_copy(time, &old_time);\n\t\treturn (true);\n\t}\n\n\treturn (false);\n}\n#ifdef JEMALLOC_JET\n#undef nstime_update\n#define\tnstime_update JEMALLOC_N(nstime_update)\nnstime_update_t *nstime_update = JEMALLOC_N(n_nstime_update);\n#endif\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/deps/jemalloc/src/pages.c",
    "content": "#define\tJEMALLOC_PAGES_C_\n#include \"jemalloc/internal/jemalloc_internal.h\"\n\n#ifdef JEMALLOC_SYSCTL_VM_OVERCOMMIT\n#include <sys/sysctl.h>\n#endif\n\n/******************************************************************************/\n/* Data. */\n\n#ifndef _WIN32\n#  define PAGES_PROT_COMMIT (PROT_READ | PROT_WRITE)\n#  define PAGES_PROT_DECOMMIT (PROT_NONE)\nstatic int\tmmap_flags;\n#endif\nstatic bool\tos_overcommits;\n\n/******************************************************************************/\n\nvoid *\npages_map(void *addr, size_t size, bool *commit)\n{\n\tvoid *ret;\n\n\tassert(size != 0);\n\n\tif (os_overcommits)\n\t\t*commit = true;\n\n#ifdef _WIN32\n\t/*\n\t * If VirtualAlloc can't allocate at the given address when one is\n\t * given, it fails and returns NULL.\n\t */\n\tret = VirtualAlloc(addr, size, MEM_RESERVE | (*commit ? MEM_COMMIT : 0),\n\t    PAGE_READWRITE);\n#else\n\t/*\n\t * We don't use MAP_FIXED here, because it can cause the *replacement*\n\t * of existing mappings, and we only want to create new mappings.\n\t */\n\t{\n\t\tint prot = *commit ? PAGES_PROT_COMMIT : PAGES_PROT_DECOMMIT;\n\n\t\tret = mmap(addr, size, prot, mmap_flags, -1, 0);\n\t}\n\tassert(ret != NULL);\n\n\tif (ret == MAP_FAILED)\n\t\tret = NULL;\n\telse if (addr != NULL && ret != addr) {\n\t\t/*\n\t\t * We succeeded in mapping memory, but not in the right place.\n\t\t */\n\t\tpages_unmap(ret, size);\n\t\tret = NULL;\n\t}\n#endif\n\tassert(ret == NULL || (addr == NULL && ret != addr)\n\t    || (addr != NULL && ret == addr));\n\treturn (ret);\n}\n\nvoid\npages_unmap(void *addr, size_t size)\n{\n\n#ifdef _WIN32\n\tif (VirtualFree(addr, 0, MEM_RELEASE) == 0)\n#else\n\tif (munmap(addr, size) == -1)\n#endif\n\t{\n\t\tchar buf[BUFERROR_BUF];\n\n\t\tbuferror(get_errno(), buf, sizeof(buf));\n\t\tmalloc_printf(\"<jemalloc>: Error in \"\n#ifdef _WIN32\n\t\t              \"VirtualFree\"\n#else\n\t\t              \"munmap\"\n#endif\n\t\t              \"(): %s\\n\", buf);\n\t\tif (opt_abort)\n\t\t\tabort();\n\t}\n}\n\nvoid *\npages_trim(void *addr, size_t alloc_size, size_t leadsize, size_t size,\n    bool *commit)\n{\n\tvoid *ret = (void *)((uintptr_t)addr + leadsize);\n\n\tassert(alloc_size >= leadsize + size);\n#ifdef _WIN32\n\t{\n\t\tvoid *new_addr;\n\n\t\tpages_unmap(addr, alloc_size);\n\t\tnew_addr = pages_map(ret, size, commit);\n\t\tif (new_addr == ret)\n\t\t\treturn (ret);\n\t\tif (new_addr)\n\t\t\tpages_unmap(new_addr, size);\n\t\treturn (NULL);\n\t}\n#else\n\t{\n\t\tsize_t trailsize = alloc_size - leadsize - size;\n\n\t\tif (leadsize != 0)\n\t\t\tpages_unmap(addr, leadsize);\n\t\tif (trailsize != 0)\n\t\t\tpages_unmap((void *)((uintptr_t)ret + size), trailsize);\n\t\treturn (ret);\n\t}\n#endif\n}\n\nstatic bool\npages_commit_impl(void *addr, size_t size, bool commit)\n{\n\n\tif (os_overcommits)\n\t\treturn (true);\n\n#ifdef _WIN32\n\treturn (commit ? (addr != VirtualAlloc(addr, size, MEM_COMMIT,\n\t    PAGE_READWRITE)) : (!VirtualFree(addr, size, MEM_DECOMMIT)));\n#else\n\t{\n\t\tint prot = commit ? PAGES_PROT_COMMIT : PAGES_PROT_DECOMMIT;\n\t\tvoid *result = mmap(addr, size, prot, mmap_flags | MAP_FIXED,\n\t\t    -1, 0);\n\t\tif (result == MAP_FAILED)\n\t\t\treturn (true);\n\t\tif (result != addr) {\n\t\t\t/*\n\t\t\t * We succeeded in mapping memory, but not in the right\n\t\t\t * place.\n\t\t\t */\n\t\t\tpages_unmap(result, size);\n\t\t\treturn (true);\n\t\t}\n\t\treturn (false);\n\t}\n#endif\n}\n\nbool\npages_commit(void *addr, size_t size)\n{\n\n\treturn (pages_commit_impl(addr, size, true));\n}\n\nbool\npages_decommit(void *addr, size_t size)\n{\n\n\treturn (pages_commit_impl(addr, size, false));\n}\n\nbool\npages_purge(void *addr, size_t size)\n{\n\tbool unzeroed;\n\n#ifdef _WIN32\n\tVirtualAlloc(addr, size, MEM_RESET, PAGE_READWRITE);\n\tunzeroed = true;\n#elif defined(JEMALLOC_HAVE_MADVISE)\n#  ifdef JEMALLOC_PURGE_MADVISE_DONTNEED\n#    define JEMALLOC_MADV_PURGE MADV_DONTNEED\n#    define JEMALLOC_MADV_ZEROS true\n#  elif defined(JEMALLOC_PURGE_MADVISE_FREE)\n#    define JEMALLOC_MADV_PURGE MADV_FREE\n#    define JEMALLOC_MADV_ZEROS false\n#  else\n#    error \"No madvise(2) flag defined for purging unused dirty pages.\"\n#  endif\n\tint err = madvise(addr, size, JEMALLOC_MADV_PURGE);\n\tunzeroed = (!JEMALLOC_MADV_ZEROS || err != 0);\n#  undef JEMALLOC_MADV_PURGE\n#  undef JEMALLOC_MADV_ZEROS\n#else\n\t/* Last resort no-op. */\n\tunzeroed = true;\n#endif\n\treturn (unzeroed);\n}\n\n#ifdef JEMALLOC_SYSCTL_VM_OVERCOMMIT\nstatic bool\nos_overcommits_sysctl(void)\n{\n\tint vm_overcommit;\n\tsize_t sz;\n\n\tsz = sizeof(vm_overcommit);\n\tif (sysctlbyname(\"vm.overcommit\", &vm_overcommit, &sz, NULL, 0) != 0)\n\t\treturn (false); /* Error. */\n\n\treturn ((vm_overcommit & 0x3) == 0);\n}\n#endif\n\n#ifdef JEMALLOC_PROC_SYS_VM_OVERCOMMIT_MEMORY\nstatic bool\nos_overcommits_proc(void)\n{\n\tint fd;\n\tchar buf[1];\n\tssize_t nread;\n\n\tfd = open(\"/proc/sys/vm/overcommit_memory\", O_RDONLY);\n\tif (fd == -1)\n\t\treturn (false); /* Error. */\n\n\tnread = read(fd, &buf, sizeof(buf));\n\tif (nread < 1)\n\t\treturn (false); /* Error. */\n\t/*\n\t * /proc/sys/vm/overcommit_memory meanings:\n\t * 0: Heuristic overcommit.\n\t * 1: Always overcommit.\n\t * 2: Never overcommit.\n\t */\n\treturn (buf[0] == '0' || buf[0] == '1');\n}\n#endif\n\nvoid\npages_boot(void)\n{\n\n#ifndef _WIN32\n\tmmap_flags = MAP_PRIVATE | MAP_ANON;\n#endif\n\n#ifdef JEMALLOC_SYSCTL_VM_OVERCOMMIT\n\tos_overcommits = os_overcommits_sysctl();\n#elif defined(JEMALLOC_PROC_SYS_VM_OVERCOMMIT_MEMORY)\n\tos_overcommits = os_overcommits_proc();\n#  ifdef MAP_NORESERVE\n\tif (os_overcommits)\n\t\tmmap_flags |= MAP_NORESERVE;\n#  endif\n#else\n\tos_overcommits = false;\n#endif\n}\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/deps/jemalloc/src/prng.c",
    "content": "#define\tJEMALLOC_PRNG_C_\n#include \"jemalloc/internal/jemalloc_internal.h\"\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/deps/jemalloc/src/prof.c",
    "content": "#define\tJEMALLOC_PROF_C_\n#include \"jemalloc/internal/jemalloc_internal.h\"\n/******************************************************************************/\n\n#ifdef JEMALLOC_PROF_LIBUNWIND\n#define\tUNW_LOCAL_ONLY\n#include <libunwind.h>\n#endif\n\n#ifdef JEMALLOC_PROF_LIBGCC\n#include <unwind.h>\n#endif\n\n/******************************************************************************/\n/* Data. */\n\nbool\t\topt_prof = false;\nbool\t\topt_prof_active = true;\nbool\t\topt_prof_thread_active_init = true;\nsize_t\t\topt_lg_prof_sample = LG_PROF_SAMPLE_DEFAULT;\nssize_t\t\topt_lg_prof_interval = LG_PROF_INTERVAL_DEFAULT;\nbool\t\topt_prof_gdump = false;\nbool\t\topt_prof_final = false;\nbool\t\topt_prof_leak = false;\nbool\t\topt_prof_accum = false;\nchar\t\topt_prof_prefix[\n    /* Minimize memory bloat for non-prof builds. */\n#ifdef JEMALLOC_PROF\n    PATH_MAX +\n#endif\n    1];\n\n/*\n * Initialized as opt_prof_active, and accessed via\n * prof_active_[gs]et{_unlocked,}().\n */\nbool\t\t\tprof_active;\nstatic malloc_mutex_t\tprof_active_mtx;\n\n/*\n * Initialized as opt_prof_thread_active_init, and accessed via\n * prof_thread_active_init_[gs]et().\n */\nstatic bool\t\tprof_thread_active_init;\nstatic malloc_mutex_t\tprof_thread_active_init_mtx;\n\n/*\n * Initialized as opt_prof_gdump, and accessed via\n * prof_gdump_[gs]et{_unlocked,}().\n */\nbool\t\t\tprof_gdump_val;\nstatic malloc_mutex_t\tprof_gdump_mtx;\n\nuint64_t\tprof_interval = 0;\n\nsize_t\t\tlg_prof_sample;\n\n/*\n * Table of mutexes that are shared among gctx's.  These are leaf locks, so\n * there is no problem with using them for more than one gctx at the same time.\n * The primary motivation for this sharing though is that gctx's are ephemeral,\n * and destroying mutexes causes complications for systems that allocate when\n * creating/destroying mutexes.\n */\nstatic malloc_mutex_t\t*gctx_locks;\nstatic unsigned\t\tcum_gctxs; /* Atomic counter. */\n\n/*\n * Table of mutexes that are shared among tdata's.  No operations require\n * holding multiple tdata locks, so there is no problem with using them for more\n * than one tdata at the same time, even though a gctx lock may be acquired\n * while holding a tdata lock.\n */\nstatic malloc_mutex_t\t*tdata_locks;\n\n/*\n * Global hash of (prof_bt_t *)-->(prof_gctx_t *).  This is the master data\n * structure that knows about all backtraces currently captured.\n */\nstatic ckh_t\t\tbt2gctx;\nstatic malloc_mutex_t\tbt2gctx_mtx;\n\n/*\n * Tree of all extant prof_tdata_t structures, regardless of state,\n * {attached,detached,expired}.\n */\nstatic prof_tdata_tree_t\ttdatas;\nstatic malloc_mutex_t\ttdatas_mtx;\n\nstatic uint64_t\t\tnext_thr_uid;\nstatic malloc_mutex_t\tnext_thr_uid_mtx;\n\nstatic malloc_mutex_t\tprof_dump_seq_mtx;\nstatic uint64_t\t\tprof_dump_seq;\nstatic uint64_t\t\tprof_dump_iseq;\nstatic uint64_t\t\tprof_dump_mseq;\nstatic uint64_t\t\tprof_dump_useq;\n\n/*\n * This buffer is rather large for stack allocation, so use a single buffer for\n * all profile dumps.\n */\nstatic malloc_mutex_t\tprof_dump_mtx;\nstatic char\t\tprof_dump_buf[\n    /* Minimize memory bloat for non-prof builds. */\n#ifdef JEMALLOC_PROF\n    PROF_DUMP_BUFSIZE\n#else\n    1\n#endif\n];\nstatic size_t\t\tprof_dump_buf_end;\nstatic int\t\tprof_dump_fd;\n\n/* Do not dump any profiles until bootstrapping is complete. */\nstatic bool\t\tprof_booted = false;\n\n/******************************************************************************/\n/*\n * Function prototypes for static functions that are referenced prior to\n * definition.\n */\n\nstatic bool\tprof_tctx_should_destroy(tsdn_t *tsdn, prof_tctx_t *tctx);\nstatic void\tprof_tctx_destroy(tsd_t *tsd, prof_tctx_t *tctx);\nstatic bool\tprof_tdata_should_destroy(tsdn_t *tsdn, prof_tdata_t *tdata,\n    bool even_if_attached);\nstatic void\tprof_tdata_destroy(tsdn_t *tsdn, prof_tdata_t *tdata,\n    bool even_if_attached);\nstatic char\t*prof_thread_name_alloc(tsdn_t *tsdn, const char *thread_name);\n\n/******************************************************************************/\n/* Red-black trees. */\n\nJEMALLOC_INLINE_C int\nprof_tctx_comp(const prof_tctx_t *a, const prof_tctx_t *b)\n{\n\tuint64_t a_thr_uid = a->thr_uid;\n\tuint64_t b_thr_uid = b->thr_uid;\n\tint ret = (a_thr_uid > b_thr_uid) - (a_thr_uid < b_thr_uid);\n\tif (ret == 0) {\n\t\tuint64_t a_thr_discrim = a->thr_discrim;\n\t\tuint64_t b_thr_discrim = b->thr_discrim;\n\t\tret = (a_thr_discrim > b_thr_discrim) - (a_thr_discrim <\n\t\t    b_thr_discrim);\n\t\tif (ret == 0) {\n\t\t\tuint64_t a_tctx_uid = a->tctx_uid;\n\t\t\tuint64_t b_tctx_uid = b->tctx_uid;\n\t\t\tret = (a_tctx_uid > b_tctx_uid) - (a_tctx_uid <\n\t\t\t    b_tctx_uid);\n\t\t}\n\t}\n\treturn (ret);\n}\n\nrb_gen(static UNUSED, tctx_tree_, prof_tctx_tree_t, prof_tctx_t,\n    tctx_link, prof_tctx_comp)\n\nJEMALLOC_INLINE_C int\nprof_gctx_comp(const prof_gctx_t *a, const prof_gctx_t *b)\n{\n\tunsigned a_len = a->bt.len;\n\tunsigned b_len = b->bt.len;\n\tunsigned comp_len = (a_len < b_len) ? a_len : b_len;\n\tint ret = memcmp(a->bt.vec, b->bt.vec, comp_len * sizeof(void *));\n\tif (ret == 0)\n\t\tret = (a_len > b_len) - (a_len < b_len);\n\treturn (ret);\n}\n\nrb_gen(static UNUSED, gctx_tree_, prof_gctx_tree_t, prof_gctx_t, dump_link,\n    prof_gctx_comp)\n\nJEMALLOC_INLINE_C int\nprof_tdata_comp(const prof_tdata_t *a, const prof_tdata_t *b)\n{\n\tint ret;\n\tuint64_t a_uid = a->thr_uid;\n\tuint64_t b_uid = b->thr_uid;\n\n\tret = ((a_uid > b_uid) - (a_uid < b_uid));\n\tif (ret == 0) {\n\t\tuint64_t a_discrim = a->thr_discrim;\n\t\tuint64_t b_discrim = b->thr_discrim;\n\n\t\tret = ((a_discrim > b_discrim) - (a_discrim < b_discrim));\n\t}\n\treturn (ret);\n}\n\nrb_gen(static UNUSED, tdata_tree_, prof_tdata_tree_t, prof_tdata_t, tdata_link,\n    prof_tdata_comp)\n\n/******************************************************************************/\n\nvoid\nprof_alloc_rollback(tsd_t *tsd, prof_tctx_t *tctx, bool updated)\n{\n\tprof_tdata_t *tdata;\n\n\tcassert(config_prof);\n\n\tif (updated) {\n\t\t/*\n\t\t * Compute a new sample threshold.  This isn't very important in\n\t\t * practice, because this function is rarely executed, so the\n\t\t * potential for sample bias is minimal except in contrived\n\t\t * programs.\n\t\t */\n\t\ttdata = prof_tdata_get(tsd, true);\n\t\tif (tdata != NULL)\n\t\t\tprof_sample_threshold_update(tdata);\n\t}\n\n\tif ((uintptr_t)tctx > (uintptr_t)1U) {\n\t\tmalloc_mutex_lock(tsd_tsdn(tsd), tctx->tdata->lock);\n\t\ttctx->prepared = false;\n\t\tif (prof_tctx_should_destroy(tsd_tsdn(tsd), tctx))\n\t\t\tprof_tctx_destroy(tsd, tctx);\n\t\telse\n\t\t\tmalloc_mutex_unlock(tsd_tsdn(tsd), tctx->tdata->lock);\n\t}\n}\n\nvoid\nprof_malloc_sample_object(tsdn_t *tsdn, const void *ptr, size_t usize,\n    prof_tctx_t *tctx)\n{\n\n\tprof_tctx_set(tsdn, ptr, usize, tctx);\n\n\tmalloc_mutex_lock(tsdn, tctx->tdata->lock);\n\ttctx->cnts.curobjs++;\n\ttctx->cnts.curbytes += usize;\n\tif (opt_prof_accum) {\n\t\ttctx->cnts.accumobjs++;\n\t\ttctx->cnts.accumbytes += usize;\n\t}\n\ttctx->prepared = false;\n\tmalloc_mutex_unlock(tsdn, tctx->tdata->lock);\n}\n\nvoid\nprof_free_sampled_object(tsd_t *tsd, size_t usize, prof_tctx_t *tctx)\n{\n\n\tmalloc_mutex_lock(tsd_tsdn(tsd), tctx->tdata->lock);\n\tassert(tctx->cnts.curobjs > 0);\n\tassert(tctx->cnts.curbytes >= usize);\n\ttctx->cnts.curobjs--;\n\ttctx->cnts.curbytes -= usize;\n\n\tif (prof_tctx_should_destroy(tsd_tsdn(tsd), tctx))\n\t\tprof_tctx_destroy(tsd, tctx);\n\telse\n\t\tmalloc_mutex_unlock(tsd_tsdn(tsd), tctx->tdata->lock);\n}\n\nvoid\nbt_init(prof_bt_t *bt, void **vec)\n{\n\n\tcassert(config_prof);\n\n\tbt->vec = vec;\n\tbt->len = 0;\n}\n\nJEMALLOC_INLINE_C void\nprof_enter(tsd_t *tsd, prof_tdata_t *tdata)\n{\n\n\tcassert(config_prof);\n\tassert(tdata == prof_tdata_get(tsd, false));\n\n\tif (tdata != NULL) {\n\t\tassert(!tdata->enq);\n\t\ttdata->enq = true;\n\t}\n\n\tmalloc_mutex_lock(tsd_tsdn(tsd), &bt2gctx_mtx);\n}\n\nJEMALLOC_INLINE_C void\nprof_leave(tsd_t *tsd, prof_tdata_t *tdata)\n{\n\n\tcassert(config_prof);\n\tassert(tdata == prof_tdata_get(tsd, false));\n\n\tmalloc_mutex_unlock(tsd_tsdn(tsd), &bt2gctx_mtx);\n\n\tif (tdata != NULL) {\n\t\tbool idump, gdump;\n\n\t\tassert(tdata->enq);\n\t\ttdata->enq = false;\n\t\tidump = tdata->enq_idump;\n\t\ttdata->enq_idump = false;\n\t\tgdump = tdata->enq_gdump;\n\t\ttdata->enq_gdump = false;\n\n\t\tif (idump)\n\t\t\tprof_idump(tsd_tsdn(tsd));\n\t\tif (gdump)\n\t\t\tprof_gdump(tsd_tsdn(tsd));\n\t}\n}\n\n#ifdef JEMALLOC_PROF_LIBUNWIND\nvoid\nprof_backtrace(prof_bt_t *bt)\n{\n\tint nframes;\n\n\tcassert(config_prof);\n\tassert(bt->len == 0);\n\tassert(bt->vec != NULL);\n\n\tnframes = unw_backtrace(bt->vec, PROF_BT_MAX);\n\tif (nframes <= 0)\n\t\treturn;\n\tbt->len = nframes;\n}\n#elif (defined(JEMALLOC_PROF_LIBGCC))\nstatic _Unwind_Reason_Code\nprof_unwind_init_callback(struct _Unwind_Context *context, void *arg)\n{\n\n\tcassert(config_prof);\n\n\treturn (_URC_NO_REASON);\n}\n\nstatic _Unwind_Reason_Code\nprof_unwind_callback(struct _Unwind_Context *context, void *arg)\n{\n\tprof_unwind_data_t *data = (prof_unwind_data_t *)arg;\n\tvoid *ip;\n\n\tcassert(config_prof);\n\n\tip = (void *)_Unwind_GetIP(context);\n\tif (ip == NULL)\n\t\treturn (_URC_END_OF_STACK);\n\tdata->bt->vec[data->bt->len] = ip;\n\tdata->bt->len++;\n\tif (data->bt->len == data->max)\n\t\treturn (_URC_END_OF_STACK);\n\n\treturn (_URC_NO_REASON);\n}\n\nvoid\nprof_backtrace(prof_bt_t *bt)\n{\n\tprof_unwind_data_t data = {bt, PROF_BT_MAX};\n\n\tcassert(config_prof);\n\n\t_Unwind_Backtrace(prof_unwind_callback, &data);\n}\n#elif (defined(JEMALLOC_PROF_GCC))\nvoid\nprof_backtrace(prof_bt_t *bt)\n{\n#define\tBT_FRAME(i)\t\t\t\t\t\t\t\\\n\tif ((i) < PROF_BT_MAX) {\t\t\t\t\t\\\n\t\tvoid *p;\t\t\t\t\t\t\\\n\t\tif (__builtin_frame_address(i) == 0)\t\t\t\\\n\t\t\treturn;\t\t\t\t\t\t\\\n\t\tp = __builtin_return_address(i);\t\t\t\\\n\t\tif (p == NULL)\t\t\t\t\t\t\\\n\t\t\treturn;\t\t\t\t\t\t\\\n\t\tbt->vec[(i)] = p;\t\t\t\t\t\\\n\t\tbt->len = (i) + 1;\t\t\t\t\t\\\n\t} else\t\t\t\t\t\t\t\t\\\n\t\treturn;\n\n\tcassert(config_prof);\n\n\tBT_FRAME(0)\n\tBT_FRAME(1)\n\tBT_FRAME(2)\n\tBT_FRAME(3)\n\tBT_FRAME(4)\n\tBT_FRAME(5)\n\tBT_FRAME(6)\n\tBT_FRAME(7)\n\tBT_FRAME(8)\n\tBT_FRAME(9)\n\n\tBT_FRAME(10)\n\tBT_FRAME(11)\n\tBT_FRAME(12)\n\tBT_FRAME(13)\n\tBT_FRAME(14)\n\tBT_FRAME(15)\n\tBT_FRAME(16)\n\tBT_FRAME(17)\n\tBT_FRAME(18)\n\tBT_FRAME(19)\n\n\tBT_FRAME(20)\n\tBT_FRAME(21)\n\tBT_FRAME(22)\n\tBT_FRAME(23)\n\tBT_FRAME(24)\n\tBT_FRAME(25)\n\tBT_FRAME(26)\n\tBT_FRAME(27)\n\tBT_FRAME(28)\n\tBT_FRAME(29)\n\n\tBT_FRAME(30)\n\tBT_FRAME(31)\n\tBT_FRAME(32)\n\tBT_FRAME(33)\n\tBT_FRAME(34)\n\tBT_FRAME(35)\n\tBT_FRAME(36)\n\tBT_FRAME(37)\n\tBT_FRAME(38)\n\tBT_FRAME(39)\n\n\tBT_FRAME(40)\n\tBT_FRAME(41)\n\tBT_FRAME(42)\n\tBT_FRAME(43)\n\tBT_FRAME(44)\n\tBT_FRAME(45)\n\tBT_FRAME(46)\n\tBT_FRAME(47)\n\tBT_FRAME(48)\n\tBT_FRAME(49)\n\n\tBT_FRAME(50)\n\tBT_FRAME(51)\n\tBT_FRAME(52)\n\tBT_FRAME(53)\n\tBT_FRAME(54)\n\tBT_FRAME(55)\n\tBT_FRAME(56)\n\tBT_FRAME(57)\n\tBT_FRAME(58)\n\tBT_FRAME(59)\n\n\tBT_FRAME(60)\n\tBT_FRAME(61)\n\tBT_FRAME(62)\n\tBT_FRAME(63)\n\tBT_FRAME(64)\n\tBT_FRAME(65)\n\tBT_FRAME(66)\n\tBT_FRAME(67)\n\tBT_FRAME(68)\n\tBT_FRAME(69)\n\n\tBT_FRAME(70)\n\tBT_FRAME(71)\n\tBT_FRAME(72)\n\tBT_FRAME(73)\n\tBT_FRAME(74)\n\tBT_FRAME(75)\n\tBT_FRAME(76)\n\tBT_FRAME(77)\n\tBT_FRAME(78)\n\tBT_FRAME(79)\n\n\tBT_FRAME(80)\n\tBT_FRAME(81)\n\tBT_FRAME(82)\n\tBT_FRAME(83)\n\tBT_FRAME(84)\n\tBT_FRAME(85)\n\tBT_FRAME(86)\n\tBT_FRAME(87)\n\tBT_FRAME(88)\n\tBT_FRAME(89)\n\n\tBT_FRAME(90)\n\tBT_FRAME(91)\n\tBT_FRAME(92)\n\tBT_FRAME(93)\n\tBT_FRAME(94)\n\tBT_FRAME(95)\n\tBT_FRAME(96)\n\tBT_FRAME(97)\n\tBT_FRAME(98)\n\tBT_FRAME(99)\n\n\tBT_FRAME(100)\n\tBT_FRAME(101)\n\tBT_FRAME(102)\n\tBT_FRAME(103)\n\tBT_FRAME(104)\n\tBT_FRAME(105)\n\tBT_FRAME(106)\n\tBT_FRAME(107)\n\tBT_FRAME(108)\n\tBT_FRAME(109)\n\n\tBT_FRAME(110)\n\tBT_FRAME(111)\n\tBT_FRAME(112)\n\tBT_FRAME(113)\n\tBT_FRAME(114)\n\tBT_FRAME(115)\n\tBT_FRAME(116)\n\tBT_FRAME(117)\n\tBT_FRAME(118)\n\tBT_FRAME(119)\n\n\tBT_FRAME(120)\n\tBT_FRAME(121)\n\tBT_FRAME(122)\n\tBT_FRAME(123)\n\tBT_FRAME(124)\n\tBT_FRAME(125)\n\tBT_FRAME(126)\n\tBT_FRAME(127)\n#undef BT_FRAME\n}\n#else\nvoid\nprof_backtrace(prof_bt_t *bt)\n{\n\n\tcassert(config_prof);\n\tnot_reached();\n}\n#endif\n\nstatic malloc_mutex_t *\nprof_gctx_mutex_choose(void)\n{\n\tunsigned ngctxs = atomic_add_u(&cum_gctxs, 1);\n\n\treturn (&gctx_locks[(ngctxs - 1) % PROF_NCTX_LOCKS]);\n}\n\nstatic malloc_mutex_t *\nprof_tdata_mutex_choose(uint64_t thr_uid)\n{\n\n\treturn (&tdata_locks[thr_uid % PROF_NTDATA_LOCKS]);\n}\n\nstatic prof_gctx_t *\nprof_gctx_create(tsdn_t *tsdn, prof_bt_t *bt)\n{\n\t/*\n\t * Create a single allocation that has space for vec of length bt->len.\n\t */\n\tsize_t size = offsetof(prof_gctx_t, vec) + (bt->len * sizeof(void *));\n\tprof_gctx_t *gctx = (prof_gctx_t *)iallocztm(tsdn, size,\n\t    size2index(size), false, NULL, true, arena_get(TSDN_NULL, 0, true),\n\t    true);\n\tif (gctx == NULL)\n\t\treturn (NULL);\n\tgctx->lock = prof_gctx_mutex_choose();\n\t/*\n\t * Set nlimbo to 1, in order to avoid a race condition with\n\t * prof_tctx_destroy()/prof_gctx_try_destroy().\n\t */\n\tgctx->nlimbo = 1;\n\ttctx_tree_new(&gctx->tctxs);\n\t/* Duplicate bt. */\n\tmemcpy(gctx->vec, bt->vec, bt->len * sizeof(void *));\n\tgctx->bt.vec = gctx->vec;\n\tgctx->bt.len = bt->len;\n\treturn (gctx);\n}\n\nstatic void\nprof_gctx_try_destroy(tsd_t *tsd, prof_tdata_t *tdata_self, prof_gctx_t *gctx,\n    prof_tdata_t *tdata)\n{\n\n\tcassert(config_prof);\n\n\t/*\n\t * Check that gctx is still unused by any thread cache before destroying\n\t * it.  prof_lookup() increments gctx->nlimbo in order to avoid a race\n\t * condition with this function, as does prof_tctx_destroy() in order to\n\t * avoid a race between the main body of prof_tctx_destroy() and entry\n\t * into this function.\n\t */\n\tprof_enter(tsd, tdata_self);\n\tmalloc_mutex_lock(tsd_tsdn(tsd), gctx->lock);\n\tassert(gctx->nlimbo != 0);\n\tif (tctx_tree_empty(&gctx->tctxs) && gctx->nlimbo == 1) {\n\t\t/* Remove gctx from bt2gctx. */\n\t\tif (ckh_remove(tsd_tsdn(tsd), &bt2gctx, &gctx->bt, NULL, NULL))\n\t\t\tnot_reached();\n\t\tprof_leave(tsd, tdata_self);\n\t\t/* Destroy gctx. */\n\t\tmalloc_mutex_unlock(tsd_tsdn(tsd), gctx->lock);\n\t\tidalloctm(tsd_tsdn(tsd), gctx, NULL, true, true);\n\t} else {\n\t\t/*\n\t\t * Compensate for increment in prof_tctx_destroy() or\n\t\t * prof_lookup().\n\t\t */\n\t\tgctx->nlimbo--;\n\t\tmalloc_mutex_unlock(tsd_tsdn(tsd), gctx->lock);\n\t\tprof_leave(tsd, tdata_self);\n\t}\n}\n\nstatic bool\nprof_tctx_should_destroy(tsdn_t *tsdn, prof_tctx_t *tctx)\n{\n\n\tmalloc_mutex_assert_owner(tsdn, tctx->tdata->lock);\n\n\tif (opt_prof_accum)\n\t\treturn (false);\n\tif (tctx->cnts.curobjs != 0)\n\t\treturn (false);\n\tif (tctx->prepared)\n\t\treturn (false);\n\treturn (true);\n}\n\nstatic bool\nprof_gctx_should_destroy(prof_gctx_t *gctx)\n{\n\n\tif (opt_prof_accum)\n\t\treturn (false);\n\tif (!tctx_tree_empty(&gctx->tctxs))\n\t\treturn (false);\n\tif (gctx->nlimbo != 0)\n\t\treturn (false);\n\treturn (true);\n}\n\nstatic void\nprof_tctx_destroy(tsd_t *tsd, prof_tctx_t *tctx)\n{\n\tprof_tdata_t *tdata = tctx->tdata;\n\tprof_gctx_t *gctx = tctx->gctx;\n\tbool destroy_tdata, destroy_tctx, destroy_gctx;\n\n\tmalloc_mutex_assert_owner(tsd_tsdn(tsd), tctx->tdata->lock);\n\n\tassert(tctx->cnts.curobjs == 0);\n\tassert(tctx->cnts.curbytes == 0);\n\tassert(!opt_prof_accum);\n\tassert(tctx->cnts.accumobjs == 0);\n\tassert(tctx->cnts.accumbytes == 0);\n\n\tckh_remove(tsd_tsdn(tsd), &tdata->bt2tctx, &gctx->bt, NULL, NULL);\n\tdestroy_tdata = prof_tdata_should_destroy(tsd_tsdn(tsd), tdata, false);\n\tmalloc_mutex_unlock(tsd_tsdn(tsd), tdata->lock);\n\n\tmalloc_mutex_lock(tsd_tsdn(tsd), gctx->lock);\n\tswitch (tctx->state) {\n\tcase prof_tctx_state_nominal:\n\t\ttctx_tree_remove(&gctx->tctxs, tctx);\n\t\tdestroy_tctx = true;\n\t\tif (prof_gctx_should_destroy(gctx)) {\n\t\t\t/*\n\t\t\t * Increment gctx->nlimbo in order to keep another\n\t\t\t * thread from winning the race to destroy gctx while\n\t\t\t * this one has gctx->lock dropped.  Without this, it\n\t\t\t * would be possible for another thread to:\n\t\t\t *\n\t\t\t * 1) Sample an allocation associated with gctx.\n\t\t\t * 2) Deallocate the sampled object.\n\t\t\t * 3) Successfully prof_gctx_try_destroy(gctx).\n\t\t\t *\n\t\t\t * The result would be that gctx no longer exists by the\n\t\t\t * time this thread accesses it in\n\t\t\t * prof_gctx_try_destroy().\n\t\t\t */\n\t\t\tgctx->nlimbo++;\n\t\t\tdestroy_gctx = true;\n\t\t} else\n\t\t\tdestroy_gctx = false;\n\t\tbreak;\n\tcase prof_tctx_state_dumping:\n\t\t/*\n\t\t * A dumping thread needs tctx to remain valid until dumping\n\t\t * has finished.  Change state such that the dumping thread will\n\t\t * complete destruction during a late dump iteration phase.\n\t\t */\n\t\ttctx->state = prof_tctx_state_purgatory;\n\t\tdestroy_tctx = false;\n\t\tdestroy_gctx = false;\n\t\tbreak;\n\tdefault:\n\t\tnot_reached();\n\t\tdestroy_tctx = false;\n\t\tdestroy_gctx = false;\n\t}\n\tmalloc_mutex_unlock(tsd_tsdn(tsd), gctx->lock);\n\tif (destroy_gctx) {\n\t\tprof_gctx_try_destroy(tsd, prof_tdata_get(tsd, false), gctx,\n\t\t    tdata);\n\t}\n\n\tmalloc_mutex_assert_not_owner(tsd_tsdn(tsd), tctx->tdata->lock);\n\n\tif (destroy_tdata)\n\t\tprof_tdata_destroy(tsd_tsdn(tsd), tdata, false);\n\n\tif (destroy_tctx)\n\t\tidalloctm(tsd_tsdn(tsd), tctx, NULL, true, true);\n}\n\nstatic bool\nprof_lookup_global(tsd_t *tsd, prof_bt_t *bt, prof_tdata_t *tdata,\n    void **p_btkey, prof_gctx_t **p_gctx, bool *p_new_gctx)\n{\n\tunion {\n\t\tprof_gctx_t\t*p;\n\t\tvoid\t\t*v;\n\t} gctx;\n\tunion {\n\t\tprof_bt_t\t*p;\n\t\tvoid\t\t*v;\n\t} btkey;\n\tbool new_gctx;\n\n\tprof_enter(tsd, tdata);\n\tif (ckh_search(&bt2gctx, bt, &btkey.v, &gctx.v)) {\n\t\t/* bt has never been seen before.  Insert it. */\n\t\tgctx.p = prof_gctx_create(tsd_tsdn(tsd), bt);\n\t\tif (gctx.v == NULL) {\n\t\t\tprof_leave(tsd, tdata);\n\t\t\treturn (true);\n\t\t}\n\t\tbtkey.p = &gctx.p->bt;\n\t\tif (ckh_insert(tsd_tsdn(tsd), &bt2gctx, btkey.v, gctx.v)) {\n\t\t\t/* OOM. */\n\t\t\tprof_leave(tsd, tdata);\n\t\t\tidalloctm(tsd_tsdn(tsd), gctx.v, NULL, true, true);\n\t\t\treturn (true);\n\t\t}\n\t\tnew_gctx = true;\n\t} else {\n\t\t/*\n\t\t * Increment nlimbo, in order to avoid a race condition with\n\t\t * prof_tctx_destroy()/prof_gctx_try_destroy().\n\t\t */\n\t\tmalloc_mutex_lock(tsd_tsdn(tsd), gctx.p->lock);\n\t\tgctx.p->nlimbo++;\n\t\tmalloc_mutex_unlock(tsd_tsdn(tsd), gctx.p->lock);\n\t\tnew_gctx = false;\n\t}\n\tprof_leave(tsd, tdata);\n\n\t*p_btkey = btkey.v;\n\t*p_gctx = gctx.p;\n\t*p_new_gctx = new_gctx;\n\treturn (false);\n}\n\nprof_tctx_t *\nprof_lookup(tsd_t *tsd, prof_bt_t *bt)\n{\n\tunion {\n\t\tprof_tctx_t\t*p;\n\t\tvoid\t\t*v;\n\t} ret;\n\tprof_tdata_t *tdata;\n\tbool not_found;\n\n\tcassert(config_prof);\n\n\ttdata = prof_tdata_get(tsd, false);\n\tif (tdata == NULL)\n\t\treturn (NULL);\n\n\tmalloc_mutex_lock(tsd_tsdn(tsd), tdata->lock);\n\tnot_found = ckh_search(&tdata->bt2tctx, bt, NULL, &ret.v);\n\tif (!not_found) /* Note double negative! */\n\t\tret.p->prepared = true;\n\tmalloc_mutex_unlock(tsd_tsdn(tsd), tdata->lock);\n\tif (not_found) {\n\t\tvoid *btkey;\n\t\tprof_gctx_t *gctx;\n\t\tbool new_gctx, error;\n\n\t\t/*\n\t\t * This thread's cache lacks bt.  Look for it in the global\n\t\t * cache.\n\t\t */\n\t\tif (prof_lookup_global(tsd, bt, tdata, &btkey, &gctx,\n\t\t    &new_gctx))\n\t\t\treturn (NULL);\n\n\t\t/* Link a prof_tctx_t into gctx for this thread. */\n\t\tret.v = iallocztm(tsd_tsdn(tsd), sizeof(prof_tctx_t),\n\t\t    size2index(sizeof(prof_tctx_t)), false, NULL, true,\n\t\t    arena_ichoose(tsd_tsdn(tsd), NULL), true);\n\t\tif (ret.p == NULL) {\n\t\t\tif (new_gctx)\n\t\t\t\tprof_gctx_try_destroy(tsd, tdata, gctx, tdata);\n\t\t\treturn (NULL);\n\t\t}\n\t\tret.p->tdata = tdata;\n\t\tret.p->thr_uid = tdata->thr_uid;\n\t\tret.p->thr_discrim = tdata->thr_discrim;\n\t\tmemset(&ret.p->cnts, 0, sizeof(prof_cnt_t));\n\t\tret.p->gctx = gctx;\n\t\tret.p->tctx_uid = tdata->tctx_uid_next++;\n\t\tret.p->prepared = true;\n\t\tret.p->state = prof_tctx_state_initializing;\n\t\tmalloc_mutex_lock(tsd_tsdn(tsd), tdata->lock);\n\t\terror = ckh_insert(tsd_tsdn(tsd), &tdata->bt2tctx, btkey,\n\t\t    ret.v);\n\t\tmalloc_mutex_unlock(tsd_tsdn(tsd), tdata->lock);\n\t\tif (error) {\n\t\t\tif (new_gctx)\n\t\t\t\tprof_gctx_try_destroy(tsd, tdata, gctx, tdata);\n\t\t\tidalloctm(tsd_tsdn(tsd), ret.v, NULL, true, true);\n\t\t\treturn (NULL);\n\t\t}\n\t\tmalloc_mutex_lock(tsd_tsdn(tsd), gctx->lock);\n\t\tret.p->state = prof_tctx_state_nominal;\n\t\ttctx_tree_insert(&gctx->tctxs, ret.p);\n\t\tgctx->nlimbo--;\n\t\tmalloc_mutex_unlock(tsd_tsdn(tsd), gctx->lock);\n\t}\n\n\treturn (ret.p);\n}\n\n/*\n * The bodies of this function and prof_leakcheck() are compiled out unless heap\n * profiling is enabled, so that it is possible to compile jemalloc with\n * floating point support completely disabled.  Avoiding floating point code is\n * important on memory-constrained systems, but it also enables a workaround for\n * versions of glibc that don't properly save/restore floating point registers\n * during dynamic lazy symbol loading (which internally calls into whatever\n * malloc implementation happens to be integrated into the application).  Note\n * that some compilers (e.g.  gcc 4.8) may use floating point registers for fast\n * memory moves, so jemalloc must be compiled with such optimizations disabled\n * (e.g.\n * -mno-sse) in order for the workaround to be complete.\n */\nvoid\nprof_sample_threshold_update(prof_tdata_t *tdata)\n{\n#ifdef JEMALLOC_PROF\n\tuint64_t r;\n\tdouble u;\n\n\tif (!config_prof)\n\t\treturn;\n\n\tif (lg_prof_sample == 0) {\n\t\ttdata->bytes_until_sample = 0;\n\t\treturn;\n\t}\n\n\t/*\n\t * Compute sample interval as a geometrically distributed random\n\t * variable with mean (2^lg_prof_sample).\n\t *\n\t *                             __        __\n\t *                             |  log(u)  |                     1\n\t * tdata->bytes_until_sample = | -------- |, where p = ---------------\n\t *                             | log(1-p) |             lg_prof_sample\n\t *                                                     2\n\t *\n\t * For more information on the math, see:\n\t *\n\t *   Non-Uniform Random Variate Generation\n\t *   Luc Devroye\n\t *   Springer-Verlag, New York, 1986\n\t *   pp 500\n\t *   (http://luc.devroye.org/rnbookindex.html)\n\t */\n\tr = prng_lg_range(&tdata->prng_state, 53);\n\tu = (double)r * (1.0/9007199254740992.0L);\n\ttdata->bytes_until_sample = (uint64_t)(log(u) /\n\t    log(1.0 - (1.0 / (double)((uint64_t)1U << lg_prof_sample))))\n\t    + (uint64_t)1U;\n#endif\n}\n\n#ifdef JEMALLOC_JET\nstatic prof_tdata_t *\nprof_tdata_count_iter(prof_tdata_tree_t *tdatas, prof_tdata_t *tdata, void *arg)\n{\n\tsize_t *tdata_count = (size_t *)arg;\n\n\t(*tdata_count)++;\n\n\treturn (NULL);\n}\n\nsize_t\nprof_tdata_count(void)\n{\n\tsize_t tdata_count = 0;\n\ttsdn_t *tsdn;\n\n\ttsdn = tsdn_fetch();\n\tmalloc_mutex_lock(tsdn, &tdatas_mtx);\n\ttdata_tree_iter(&tdatas, NULL, prof_tdata_count_iter,\n\t    (void *)&tdata_count);\n\tmalloc_mutex_unlock(tsdn, &tdatas_mtx);\n\n\treturn (tdata_count);\n}\n#endif\n\n#ifdef JEMALLOC_JET\nsize_t\nprof_bt_count(void)\n{\n\tsize_t bt_count;\n\ttsd_t *tsd;\n\tprof_tdata_t *tdata;\n\n\ttsd = tsd_fetch();\n\ttdata = prof_tdata_get(tsd, false);\n\tif (tdata == NULL)\n\t\treturn (0);\n\n\tmalloc_mutex_lock(tsd_tsdn(tsd), &bt2gctx_mtx);\n\tbt_count = ckh_count(&bt2gctx);\n\tmalloc_mutex_unlock(tsd_tsdn(tsd), &bt2gctx_mtx);\n\n\treturn (bt_count);\n}\n#endif\n\n#ifdef JEMALLOC_JET\n#undef prof_dump_open\n#define\tprof_dump_open JEMALLOC_N(prof_dump_open_impl)\n#endif\nstatic int\nprof_dump_open(bool propagate_err, const char *filename)\n{\n\tint fd;\n\n\tfd = creat(filename, 0644);\n\tif (fd == -1 && !propagate_err) {\n\t\tmalloc_printf(\"<jemalloc>: creat(\\\"%s\\\"), 0644) failed\\n\",\n\t\t    filename);\n\t\tif (opt_abort)\n\t\t\tabort();\n\t}\n\n\treturn (fd);\n}\n#ifdef JEMALLOC_JET\n#undef prof_dump_open\n#define\tprof_dump_open JEMALLOC_N(prof_dump_open)\nprof_dump_open_t *prof_dump_open = JEMALLOC_N(prof_dump_open_impl);\n#endif\n\nstatic bool\nprof_dump_flush(bool propagate_err)\n{\n\tbool ret = false;\n\tssize_t err;\n\n\tcassert(config_prof);\n\n\terr = write(prof_dump_fd, prof_dump_buf, prof_dump_buf_end);\n\tif (err == -1) {\n\t\tif (!propagate_err) {\n\t\t\tmalloc_write(\"<jemalloc>: write() failed during heap \"\n\t\t\t    \"profile flush\\n\");\n\t\t\tif (opt_abort)\n\t\t\t\tabort();\n\t\t}\n\t\tret = true;\n\t}\n\tprof_dump_buf_end = 0;\n\n\treturn (ret);\n}\n\nstatic bool\nprof_dump_close(bool propagate_err)\n{\n\tbool ret;\n\n\tassert(prof_dump_fd != -1);\n\tret = prof_dump_flush(propagate_err);\n\tclose(prof_dump_fd);\n\tprof_dump_fd = -1;\n\n\treturn (ret);\n}\n\nstatic bool\nprof_dump_write(bool propagate_err, const char *s)\n{\n\tsize_t i, slen, n;\n\n\tcassert(config_prof);\n\n\ti = 0;\n\tslen = strlen(s);\n\twhile (i < slen) {\n\t\t/* Flush the buffer if it is full. */\n\t\tif (prof_dump_buf_end == PROF_DUMP_BUFSIZE)\n\t\t\tif (prof_dump_flush(propagate_err) && propagate_err)\n\t\t\t\treturn (true);\n\n\t\tif (prof_dump_buf_end + slen <= PROF_DUMP_BUFSIZE) {\n\t\t\t/* Finish writing. */\n\t\t\tn = slen - i;\n\t\t} else {\n\t\t\t/* Write as much of s as will fit. */\n\t\t\tn = PROF_DUMP_BUFSIZE - prof_dump_buf_end;\n\t\t}\n\t\tmemcpy(&prof_dump_buf[prof_dump_buf_end], &s[i], n);\n\t\tprof_dump_buf_end += n;\n\t\ti += n;\n\t}\n\n\treturn (false);\n}\n\nJEMALLOC_FORMAT_PRINTF(2, 3)\nstatic bool\nprof_dump_printf(bool propagate_err, const char *format, ...)\n{\n\tbool ret;\n\tva_list ap;\n\tchar buf[PROF_PRINTF_BUFSIZE];\n\n\tva_start(ap, format);\n\tmalloc_vsnprintf(buf, sizeof(buf), format, ap);\n\tva_end(ap);\n\tret = prof_dump_write(propagate_err, buf);\n\n\treturn (ret);\n}\n\nstatic void\nprof_tctx_merge_tdata(tsdn_t *tsdn, prof_tctx_t *tctx, prof_tdata_t *tdata)\n{\n\n\tmalloc_mutex_assert_owner(tsdn, tctx->tdata->lock);\n\n\tmalloc_mutex_lock(tsdn, tctx->gctx->lock);\n\n\tswitch (tctx->state) {\n\tcase prof_tctx_state_initializing:\n\t\tmalloc_mutex_unlock(tsdn, tctx->gctx->lock);\n\t\treturn;\n\tcase prof_tctx_state_nominal:\n\t\ttctx->state = prof_tctx_state_dumping;\n\t\tmalloc_mutex_unlock(tsdn, tctx->gctx->lock);\n\n\t\tmemcpy(&tctx->dump_cnts, &tctx->cnts, sizeof(prof_cnt_t));\n\n\t\ttdata->cnt_summed.curobjs += tctx->dump_cnts.curobjs;\n\t\ttdata->cnt_summed.curbytes += tctx->dump_cnts.curbytes;\n\t\tif (opt_prof_accum) {\n\t\t\ttdata->cnt_summed.accumobjs +=\n\t\t\t    tctx->dump_cnts.accumobjs;\n\t\t\ttdata->cnt_summed.accumbytes +=\n\t\t\t    tctx->dump_cnts.accumbytes;\n\t\t}\n\t\tbreak;\n\tcase prof_tctx_state_dumping:\n\tcase prof_tctx_state_purgatory:\n\t\tnot_reached();\n\t}\n}\n\nstatic void\nprof_tctx_merge_gctx(tsdn_t *tsdn, prof_tctx_t *tctx, prof_gctx_t *gctx)\n{\n\n\tmalloc_mutex_assert_owner(tsdn, gctx->lock);\n\n\tgctx->cnt_summed.curobjs += tctx->dump_cnts.curobjs;\n\tgctx->cnt_summed.curbytes += tctx->dump_cnts.curbytes;\n\tif (opt_prof_accum) {\n\t\tgctx->cnt_summed.accumobjs += tctx->dump_cnts.accumobjs;\n\t\tgctx->cnt_summed.accumbytes += tctx->dump_cnts.accumbytes;\n\t}\n}\n\nstatic prof_tctx_t *\nprof_tctx_merge_iter(prof_tctx_tree_t *tctxs, prof_tctx_t *tctx, void *arg)\n{\n\ttsdn_t *tsdn = (tsdn_t *)arg;\n\n\tmalloc_mutex_assert_owner(tsdn, tctx->gctx->lock);\n\n\tswitch (tctx->state) {\n\tcase prof_tctx_state_nominal:\n\t\t/* New since dumping started; ignore. */\n\t\tbreak;\n\tcase prof_tctx_state_dumping:\n\tcase prof_tctx_state_purgatory:\n\t\tprof_tctx_merge_gctx(tsdn, tctx, tctx->gctx);\n\t\tbreak;\n\tdefault:\n\t\tnot_reached();\n\t}\n\n\treturn (NULL);\n}\n\nstruct prof_tctx_dump_iter_arg_s {\n\ttsdn_t\t*tsdn;\n\tbool\tpropagate_err;\n};\n\nstatic prof_tctx_t *\nprof_tctx_dump_iter(prof_tctx_tree_t *tctxs, prof_tctx_t *tctx, void *opaque)\n{\n\tstruct prof_tctx_dump_iter_arg_s *arg =\n\t    (struct prof_tctx_dump_iter_arg_s *)opaque;\n\n\tmalloc_mutex_assert_owner(arg->tsdn, tctx->gctx->lock);\n\n\tswitch (tctx->state) {\n\tcase prof_tctx_state_initializing:\n\tcase prof_tctx_state_nominal:\n\t\t/* Not captured by this dump. */\n\t\tbreak;\n\tcase prof_tctx_state_dumping:\n\tcase prof_tctx_state_purgatory:\n\t\tif (prof_dump_printf(arg->propagate_err,\n\t\t    \"  t%\"FMTu64\": %\"FMTu64\": %\"FMTu64\" [%\"FMTu64\": \"\n\t\t    \"%\"FMTu64\"]\\n\", tctx->thr_uid, tctx->dump_cnts.curobjs,\n\t\t    tctx->dump_cnts.curbytes, tctx->dump_cnts.accumobjs,\n\t\t    tctx->dump_cnts.accumbytes))\n\t\t\treturn (tctx);\n\t\tbreak;\n\tdefault:\n\t\tnot_reached();\n\t}\n\treturn (NULL);\n}\n\nstatic prof_tctx_t *\nprof_tctx_finish_iter(prof_tctx_tree_t *tctxs, prof_tctx_t *tctx, void *arg)\n{\n\ttsdn_t *tsdn = (tsdn_t *)arg;\n\tprof_tctx_t *ret;\n\n\tmalloc_mutex_assert_owner(tsdn, tctx->gctx->lock);\n\n\tswitch (tctx->state) {\n\tcase prof_tctx_state_nominal:\n\t\t/* New since dumping started; ignore. */\n\t\tbreak;\n\tcase prof_tctx_state_dumping:\n\t\ttctx->state = prof_tctx_state_nominal;\n\t\tbreak;\n\tcase prof_tctx_state_purgatory:\n\t\tret = tctx;\n\t\tgoto label_return;\n\tdefault:\n\t\tnot_reached();\n\t}\n\n\tret = NULL;\nlabel_return:\n\treturn (ret);\n}\n\nstatic void\nprof_dump_gctx_prep(tsdn_t *tsdn, prof_gctx_t *gctx, prof_gctx_tree_t *gctxs)\n{\n\n\tcassert(config_prof);\n\n\tmalloc_mutex_lock(tsdn, gctx->lock);\n\n\t/*\n\t * Increment nlimbo so that gctx won't go away before dump.\n\t * Additionally, link gctx into the dump list so that it is included in\n\t * prof_dump()'s second pass.\n\t */\n\tgctx->nlimbo++;\n\tgctx_tree_insert(gctxs, gctx);\n\n\tmemset(&gctx->cnt_summed, 0, sizeof(prof_cnt_t));\n\n\tmalloc_mutex_unlock(tsdn, gctx->lock);\n}\n\nstruct prof_gctx_merge_iter_arg_s {\n\ttsdn_t\t*tsdn;\n\tsize_t\tleak_ngctx;\n};\n\nstatic prof_gctx_t *\nprof_gctx_merge_iter(prof_gctx_tree_t *gctxs, prof_gctx_t *gctx, void *opaque)\n{\n\tstruct prof_gctx_merge_iter_arg_s *arg =\n\t    (struct prof_gctx_merge_iter_arg_s *)opaque;\n\n\tmalloc_mutex_lock(arg->tsdn, gctx->lock);\n\ttctx_tree_iter(&gctx->tctxs, NULL, prof_tctx_merge_iter,\n\t    (void *)arg->tsdn);\n\tif (gctx->cnt_summed.curobjs != 0)\n\t\targ->leak_ngctx++;\n\tmalloc_mutex_unlock(arg->tsdn, gctx->lock);\n\n\treturn (NULL);\n}\n\nstatic void\nprof_gctx_finish(tsd_t *tsd, prof_gctx_tree_t *gctxs)\n{\n\tprof_tdata_t *tdata = prof_tdata_get(tsd, false);\n\tprof_gctx_t *gctx;\n\n\t/*\n\t * Standard tree iteration won't work here, because as soon as we\n\t * decrement gctx->nlimbo and unlock gctx, another thread can\n\t * concurrently destroy it, which will corrupt the tree.  Therefore,\n\t * tear down the tree one node at a time during iteration.\n\t */\n\twhile ((gctx = gctx_tree_first(gctxs)) != NULL) {\n\t\tgctx_tree_remove(gctxs, gctx);\n\t\tmalloc_mutex_lock(tsd_tsdn(tsd), gctx->lock);\n\t\t{\n\t\t\tprof_tctx_t *next;\n\n\t\t\tnext = NULL;\n\t\t\tdo {\n\t\t\t\tprof_tctx_t *to_destroy =\n\t\t\t\t    tctx_tree_iter(&gctx->tctxs, next,\n\t\t\t\t    prof_tctx_finish_iter,\n\t\t\t\t    (void *)tsd_tsdn(tsd));\n\t\t\t\tif (to_destroy != NULL) {\n\t\t\t\t\tnext = tctx_tree_next(&gctx->tctxs,\n\t\t\t\t\t    to_destroy);\n\t\t\t\t\ttctx_tree_remove(&gctx->tctxs,\n\t\t\t\t\t    to_destroy);\n\t\t\t\t\tidalloctm(tsd_tsdn(tsd), to_destroy,\n\t\t\t\t\t    NULL, true, true);\n\t\t\t\t} else\n\t\t\t\t\tnext = NULL;\n\t\t\t} while (next != NULL);\n\t\t}\n\t\tgctx->nlimbo--;\n\t\tif (prof_gctx_should_destroy(gctx)) {\n\t\t\tgctx->nlimbo++;\n\t\t\tmalloc_mutex_unlock(tsd_tsdn(tsd), gctx->lock);\n\t\t\tprof_gctx_try_destroy(tsd, tdata, gctx, tdata);\n\t\t} else\n\t\t\tmalloc_mutex_unlock(tsd_tsdn(tsd), gctx->lock);\n\t}\n}\n\nstruct prof_tdata_merge_iter_arg_s {\n\ttsdn_t\t\t*tsdn;\n\tprof_cnt_t\tcnt_all;\n};\n\nstatic prof_tdata_t *\nprof_tdata_merge_iter(prof_tdata_tree_t *tdatas, prof_tdata_t *tdata,\n    void *opaque)\n{\n\tstruct prof_tdata_merge_iter_arg_s *arg =\n\t    (struct prof_tdata_merge_iter_arg_s *)opaque;\n\n\tmalloc_mutex_lock(arg->tsdn, tdata->lock);\n\tif (!tdata->expired) {\n\t\tsize_t tabind;\n\t\tunion {\n\t\t\tprof_tctx_t\t*p;\n\t\t\tvoid\t\t*v;\n\t\t} tctx;\n\n\t\ttdata->dumping = true;\n\t\tmemset(&tdata->cnt_summed, 0, sizeof(prof_cnt_t));\n\t\tfor (tabind = 0; !ckh_iter(&tdata->bt2tctx, &tabind, NULL,\n\t\t    &tctx.v);)\n\t\t\tprof_tctx_merge_tdata(arg->tsdn, tctx.p, tdata);\n\n\t\targ->cnt_all.curobjs += tdata->cnt_summed.curobjs;\n\t\targ->cnt_all.curbytes += tdata->cnt_summed.curbytes;\n\t\tif (opt_prof_accum) {\n\t\t\targ->cnt_all.accumobjs += tdata->cnt_summed.accumobjs;\n\t\t\targ->cnt_all.accumbytes += tdata->cnt_summed.accumbytes;\n\t\t}\n\t} else\n\t\ttdata->dumping = false;\n\tmalloc_mutex_unlock(arg->tsdn, tdata->lock);\n\n\treturn (NULL);\n}\n\nstatic prof_tdata_t *\nprof_tdata_dump_iter(prof_tdata_tree_t *tdatas, prof_tdata_t *tdata, void *arg)\n{\n\tbool propagate_err = *(bool *)arg;\n\n\tif (!tdata->dumping)\n\t\treturn (NULL);\n\n\tif (prof_dump_printf(propagate_err,\n\t    \"  t%\"FMTu64\": %\"FMTu64\": %\"FMTu64\" [%\"FMTu64\": %\"FMTu64\"]%s%s\\n\",\n\t    tdata->thr_uid, tdata->cnt_summed.curobjs,\n\t    tdata->cnt_summed.curbytes, tdata->cnt_summed.accumobjs,\n\t    tdata->cnt_summed.accumbytes,\n\t    (tdata->thread_name != NULL) ? \" \" : \"\",\n\t    (tdata->thread_name != NULL) ? tdata->thread_name : \"\"))\n\t\treturn (tdata);\n\treturn (NULL);\n}\n\n#ifdef JEMALLOC_JET\n#undef prof_dump_header\n#define\tprof_dump_header JEMALLOC_N(prof_dump_header_impl)\n#endif\nstatic bool\nprof_dump_header(tsdn_t *tsdn, bool propagate_err, const prof_cnt_t *cnt_all)\n{\n\tbool ret;\n\n\tif (prof_dump_printf(propagate_err,\n\t    \"heap_v2/%\"FMTu64\"\\n\"\n\t    \"  t*: %\"FMTu64\": %\"FMTu64\" [%\"FMTu64\": %\"FMTu64\"]\\n\",\n\t    ((uint64_t)1U << lg_prof_sample), cnt_all->curobjs,\n\t    cnt_all->curbytes, cnt_all->accumobjs, cnt_all->accumbytes))\n\t\treturn (true);\n\n\tmalloc_mutex_lock(tsdn, &tdatas_mtx);\n\tret = (tdata_tree_iter(&tdatas, NULL, prof_tdata_dump_iter,\n\t    (void *)&propagate_err) != NULL);\n\tmalloc_mutex_unlock(tsdn, &tdatas_mtx);\n\treturn (ret);\n}\n#ifdef JEMALLOC_JET\n#undef prof_dump_header\n#define\tprof_dump_header JEMALLOC_N(prof_dump_header)\nprof_dump_header_t *prof_dump_header = JEMALLOC_N(prof_dump_header_impl);\n#endif\n\nstatic bool\nprof_dump_gctx(tsdn_t *tsdn, bool propagate_err, prof_gctx_t *gctx,\n    const prof_bt_t *bt, prof_gctx_tree_t *gctxs)\n{\n\tbool ret;\n\tunsigned i;\n\tstruct prof_tctx_dump_iter_arg_s prof_tctx_dump_iter_arg;\n\n\tcassert(config_prof);\n\tmalloc_mutex_assert_owner(tsdn, gctx->lock);\n\n\t/* Avoid dumping such gctx's that have no useful data. */\n\tif ((!opt_prof_accum && gctx->cnt_summed.curobjs == 0) ||\n\t    (opt_prof_accum && gctx->cnt_summed.accumobjs == 0)) {\n\t\tassert(gctx->cnt_summed.curobjs == 0);\n\t\tassert(gctx->cnt_summed.curbytes == 0);\n\t\tassert(gctx->cnt_summed.accumobjs == 0);\n\t\tassert(gctx->cnt_summed.accumbytes == 0);\n\t\tret = false;\n\t\tgoto label_return;\n\t}\n\n\tif (prof_dump_printf(propagate_err, \"@\")) {\n\t\tret = true;\n\t\tgoto label_return;\n\t}\n\tfor (i = 0; i < bt->len; i++) {\n\t\tif (prof_dump_printf(propagate_err, \" %#\"FMTxPTR,\n\t\t    (uintptr_t)bt->vec[i])) {\n\t\t\tret = true;\n\t\t\tgoto label_return;\n\t\t}\n\t}\n\n\tif (prof_dump_printf(propagate_err,\n\t    \"\\n\"\n\t    \"  t*: %\"FMTu64\": %\"FMTu64\" [%\"FMTu64\": %\"FMTu64\"]\\n\",\n\t    gctx->cnt_summed.curobjs, gctx->cnt_summed.curbytes,\n\t    gctx->cnt_summed.accumobjs, gctx->cnt_summed.accumbytes)) {\n\t\tret = true;\n\t\tgoto label_return;\n\t}\n\n\tprof_tctx_dump_iter_arg.tsdn = tsdn;\n\tprof_tctx_dump_iter_arg.propagate_err = propagate_err;\n\tif (tctx_tree_iter(&gctx->tctxs, NULL, prof_tctx_dump_iter,\n\t    (void *)&prof_tctx_dump_iter_arg) != NULL) {\n\t\tret = true;\n\t\tgoto label_return;\n\t}\n\n\tret = false;\nlabel_return:\n\treturn (ret);\n}\n\n#ifndef _WIN32\nJEMALLOC_FORMAT_PRINTF(1, 2)\nstatic int\nprof_open_maps(const char *format, ...)\n{\n\tint mfd;\n\tva_list ap;\n\tchar filename[PATH_MAX + 1];\n\n\tva_start(ap, format);\n\tmalloc_vsnprintf(filename, sizeof(filename), format, ap);\n\tva_end(ap);\n\tmfd = open(filename, O_RDONLY);\n\n\treturn (mfd);\n}\n#endif\n\nstatic int\nprof_getpid(void)\n{\n\n#ifdef _WIN32\n\treturn (GetCurrentProcessId());\n#else\n\treturn (getpid());\n#endif\n}\n\nstatic bool\nprof_dump_maps(bool propagate_err)\n{\n\tbool ret;\n\tint mfd;\n\n\tcassert(config_prof);\n#ifdef __FreeBSD__\n\tmfd = prof_open_maps(\"/proc/curproc/map\");\n#elif defined(_WIN32)\n\tmfd = -1; // Not implemented\n#else\n\t{\n\t\tint pid = prof_getpid();\n\n\t\tmfd = prof_open_maps(\"/proc/%d/task/%d/maps\", pid, pid);\n\t\tif (mfd == -1)\n\t\t\tmfd = prof_open_maps(\"/proc/%d/maps\", pid);\n\t}\n#endif\n\tif (mfd != -1) {\n\t\tssize_t nread;\n\n\t\tif (prof_dump_write(propagate_err, \"\\nMAPPED_LIBRARIES:\\n\") &&\n\t\t    propagate_err) {\n\t\t\tret = true;\n\t\t\tgoto label_return;\n\t\t}\n\t\tnread = 0;\n\t\tdo {\n\t\t\tprof_dump_buf_end += nread;\n\t\t\tif (prof_dump_buf_end == PROF_DUMP_BUFSIZE) {\n\t\t\t\t/* Make space in prof_dump_buf before read(). */\n\t\t\t\tif (prof_dump_flush(propagate_err) &&\n\t\t\t\t    propagate_err) {\n\t\t\t\t\tret = true;\n\t\t\t\t\tgoto label_return;\n\t\t\t\t}\n\t\t\t}\n\t\t\tnread = read(mfd, &prof_dump_buf[prof_dump_buf_end],\n\t\t\t    PROF_DUMP_BUFSIZE - prof_dump_buf_end);\n\t\t} while (nread > 0);\n\t} else {\n\t\tret = true;\n\t\tgoto label_return;\n\t}\n\n\tret = false;\nlabel_return:\n\tif (mfd != -1)\n\t\tclose(mfd);\n\treturn (ret);\n}\n\n/*\n * See prof_sample_threshold_update() comment for why the body of this function\n * is conditionally compiled.\n */\nstatic void\nprof_leakcheck(const prof_cnt_t *cnt_all, size_t leak_ngctx,\n    const char *filename)\n{\n\n#ifdef JEMALLOC_PROF\n\t/*\n\t * Scaling is equivalent AdjustSamples() in jeprof, but the result may\n\t * differ slightly from what jeprof reports, because here we scale the\n\t * summary values, whereas jeprof scales each context individually and\n\t * reports the sums of the scaled values.\n\t */\n\tif (cnt_all->curbytes != 0) {\n\t\tdouble sample_period = (double)((uint64_t)1 << lg_prof_sample);\n\t\tdouble ratio = (((double)cnt_all->curbytes) /\n\t\t    (double)cnt_all->curobjs) / sample_period;\n\t\tdouble scale_factor = 1.0 / (1.0 - exp(-ratio));\n\t\tuint64_t curbytes = (uint64_t)round(((double)cnt_all->curbytes)\n\t\t    * scale_factor);\n\t\tuint64_t curobjs = (uint64_t)round(((double)cnt_all->curobjs) *\n\t\t    scale_factor);\n\n\t\tmalloc_printf(\"<jemalloc>: Leak approximation summary: ~%\"FMTu64\n\t\t    \" byte%s, ~%\"FMTu64\" object%s, >= %zu context%s\\n\",\n\t\t    curbytes, (curbytes != 1) ? \"s\" : \"\", curobjs, (curobjs !=\n\t\t    1) ? \"s\" : \"\", leak_ngctx, (leak_ngctx != 1) ? \"s\" : \"\");\n\t\tmalloc_printf(\n\t\t    \"<jemalloc>: Run jeprof on \\\"%s\\\" for leak detail\\n\",\n\t\t    filename);\n\t}\n#endif\n}\n\nstruct prof_gctx_dump_iter_arg_s {\n\ttsdn_t\t*tsdn;\n\tbool\tpropagate_err;\n};\n\nstatic prof_gctx_t *\nprof_gctx_dump_iter(prof_gctx_tree_t *gctxs, prof_gctx_t *gctx, void *opaque)\n{\n\tprof_gctx_t *ret;\n\tstruct prof_gctx_dump_iter_arg_s *arg =\n\t    (struct prof_gctx_dump_iter_arg_s *)opaque;\n\n\tmalloc_mutex_lock(arg->tsdn, gctx->lock);\n\n\tif (prof_dump_gctx(arg->tsdn, arg->propagate_err, gctx, &gctx->bt,\n\t    gctxs)) {\n\t\tret = gctx;\n\t\tgoto label_return;\n\t}\n\n\tret = NULL;\nlabel_return:\n\tmalloc_mutex_unlock(arg->tsdn, gctx->lock);\n\treturn (ret);\n}\n\nstatic bool\nprof_dump(tsd_t *tsd, bool propagate_err, const char *filename, bool leakcheck)\n{\n\tprof_tdata_t *tdata;\n\tstruct prof_tdata_merge_iter_arg_s prof_tdata_merge_iter_arg;\n\tsize_t tabind;\n\tunion {\n\t\tprof_gctx_t\t*p;\n\t\tvoid\t\t*v;\n\t} gctx;\n\tstruct prof_gctx_merge_iter_arg_s prof_gctx_merge_iter_arg;\n\tstruct prof_gctx_dump_iter_arg_s prof_gctx_dump_iter_arg;\n\tprof_gctx_tree_t gctxs;\n\n\tcassert(config_prof);\n\n\ttdata = prof_tdata_get(tsd, true);\n\tif (tdata == NULL)\n\t\treturn (true);\n\n\tmalloc_mutex_lock(tsd_tsdn(tsd), &prof_dump_mtx);\n\tprof_enter(tsd, tdata);\n\n\t/*\n\t * Put gctx's in limbo and clear their counters in preparation for\n\t * summing.\n\t */\n\tgctx_tree_new(&gctxs);\n\tfor (tabind = 0; !ckh_iter(&bt2gctx, &tabind, NULL, &gctx.v);)\n\t\tprof_dump_gctx_prep(tsd_tsdn(tsd), gctx.p, &gctxs);\n\n\t/*\n\t * Iterate over tdatas, and for the non-expired ones snapshot their tctx\n\t * stats and merge them into the associated gctx's.\n\t */\n\tprof_tdata_merge_iter_arg.tsdn = tsd_tsdn(tsd);\n\tmemset(&prof_tdata_merge_iter_arg.cnt_all, 0, sizeof(prof_cnt_t));\n\tmalloc_mutex_lock(tsd_tsdn(tsd), &tdatas_mtx);\n\ttdata_tree_iter(&tdatas, NULL, prof_tdata_merge_iter,\n\t    (void *)&prof_tdata_merge_iter_arg);\n\tmalloc_mutex_unlock(tsd_tsdn(tsd), &tdatas_mtx);\n\n\t/* Merge tctx stats into gctx's. */\n\tprof_gctx_merge_iter_arg.tsdn = tsd_tsdn(tsd);\n\tprof_gctx_merge_iter_arg.leak_ngctx = 0;\n\tgctx_tree_iter(&gctxs, NULL, prof_gctx_merge_iter,\n\t    (void *)&prof_gctx_merge_iter_arg);\n\n\tprof_leave(tsd, tdata);\n\n\t/* Create dump file. */\n\tif ((prof_dump_fd = prof_dump_open(propagate_err, filename)) == -1)\n\t\tgoto label_open_close_error;\n\n\t/* Dump profile header. */\n\tif (prof_dump_header(tsd_tsdn(tsd), propagate_err,\n\t    &prof_tdata_merge_iter_arg.cnt_all))\n\t\tgoto label_write_error;\n\n\t/* Dump per gctx profile stats. */\n\tprof_gctx_dump_iter_arg.tsdn = tsd_tsdn(tsd);\n\tprof_gctx_dump_iter_arg.propagate_err = propagate_err;\n\tif (gctx_tree_iter(&gctxs, NULL, prof_gctx_dump_iter,\n\t    (void *)&prof_gctx_dump_iter_arg) != NULL)\n\t\tgoto label_write_error;\n\n\t/* Dump /proc/<pid>/maps if possible. */\n\tif (prof_dump_maps(propagate_err))\n\t\tgoto label_write_error;\n\n\tif (prof_dump_close(propagate_err))\n\t\tgoto label_open_close_error;\n\n\tprof_gctx_finish(tsd, &gctxs);\n\tmalloc_mutex_unlock(tsd_tsdn(tsd), &prof_dump_mtx);\n\n\tif (leakcheck) {\n\t\tprof_leakcheck(&prof_tdata_merge_iter_arg.cnt_all,\n\t\t    prof_gctx_merge_iter_arg.leak_ngctx, filename);\n\t}\n\treturn (false);\nlabel_write_error:\n\tprof_dump_close(propagate_err);\nlabel_open_close_error:\n\tprof_gctx_finish(tsd, &gctxs);\n\tmalloc_mutex_unlock(tsd_tsdn(tsd), &prof_dump_mtx);\n\treturn (true);\n}\n\n#define\tDUMP_FILENAME_BUFSIZE\t(PATH_MAX + 1)\n#define\tVSEQ_INVALID\t\tUINT64_C(0xffffffffffffffff)\nstatic void\nprof_dump_filename(char *filename, char v, uint64_t vseq)\n{\n\n\tcassert(config_prof);\n\n\tif (vseq != VSEQ_INVALID) {\n\t        /* \"<prefix>.<pid>.<seq>.v<vseq>.heap\" */\n\t\tmalloc_snprintf(filename, DUMP_FILENAME_BUFSIZE,\n\t\t    \"%s.%d.%\"FMTu64\".%c%\"FMTu64\".heap\",\n\t\t    opt_prof_prefix, prof_getpid(), prof_dump_seq, v, vseq);\n\t} else {\n\t        /* \"<prefix>.<pid>.<seq>.<v>.heap\" */\n\t\tmalloc_snprintf(filename, DUMP_FILENAME_BUFSIZE,\n\t\t    \"%s.%d.%\"FMTu64\".%c.heap\",\n\t\t    opt_prof_prefix, prof_getpid(), prof_dump_seq, v);\n\t}\n\tprof_dump_seq++;\n}\n\nstatic void\nprof_fdump(void)\n{\n\ttsd_t *tsd;\n\tchar filename[DUMP_FILENAME_BUFSIZE];\n\n\tcassert(config_prof);\n\tassert(opt_prof_final);\n\tassert(opt_prof_prefix[0] != '\\0');\n\n\tif (!prof_booted)\n\t\treturn;\n\ttsd = tsd_fetch();\n\n\tmalloc_mutex_lock(tsd_tsdn(tsd), &prof_dump_seq_mtx);\n\tprof_dump_filename(filename, 'f', VSEQ_INVALID);\n\tmalloc_mutex_unlock(tsd_tsdn(tsd), &prof_dump_seq_mtx);\n\tprof_dump(tsd, false, filename, opt_prof_leak);\n}\n\nvoid\nprof_idump(tsdn_t *tsdn)\n{\n\ttsd_t *tsd;\n\tprof_tdata_t *tdata;\n\n\tcassert(config_prof);\n\n\tif (!prof_booted || tsdn_null(tsdn))\n\t\treturn;\n\ttsd = tsdn_tsd(tsdn);\n\ttdata = prof_tdata_get(tsd, false);\n\tif (tdata == NULL)\n\t\treturn;\n\tif (tdata->enq) {\n\t\ttdata->enq_idump = true;\n\t\treturn;\n\t}\n\n\tif (opt_prof_prefix[0] != '\\0') {\n\t\tchar filename[PATH_MAX + 1];\n\t\tmalloc_mutex_lock(tsd_tsdn(tsd), &prof_dump_seq_mtx);\n\t\tprof_dump_filename(filename, 'i', prof_dump_iseq);\n\t\tprof_dump_iseq++;\n\t\tmalloc_mutex_unlock(tsd_tsdn(tsd), &prof_dump_seq_mtx);\n\t\tprof_dump(tsd, false, filename, false);\n\t}\n}\n\nbool\nprof_mdump(tsd_t *tsd, const char *filename)\n{\n\tchar filename_buf[DUMP_FILENAME_BUFSIZE];\n\n\tcassert(config_prof);\n\n\tif (!opt_prof || !prof_booted)\n\t\treturn (true);\n\n\tif (filename == NULL) {\n\t\t/* No filename specified, so automatically generate one. */\n\t\tif (opt_prof_prefix[0] == '\\0')\n\t\t\treturn (true);\n\t\tmalloc_mutex_lock(tsd_tsdn(tsd), &prof_dump_seq_mtx);\n\t\tprof_dump_filename(filename_buf, 'm', prof_dump_mseq);\n\t\tprof_dump_mseq++;\n\t\tmalloc_mutex_unlock(tsd_tsdn(tsd), &prof_dump_seq_mtx);\n\t\tfilename = filename_buf;\n\t}\n\treturn (prof_dump(tsd, true, filename, false));\n}\n\nvoid\nprof_gdump(tsdn_t *tsdn)\n{\n\ttsd_t *tsd;\n\tprof_tdata_t *tdata;\n\n\tcassert(config_prof);\n\n\tif (!prof_booted || tsdn_null(tsdn))\n\t\treturn;\n\ttsd = tsdn_tsd(tsdn);\n\ttdata = prof_tdata_get(tsd, false);\n\tif (tdata == NULL)\n\t\treturn;\n\tif (tdata->enq) {\n\t\ttdata->enq_gdump = true;\n\t\treturn;\n\t}\n\n\tif (opt_prof_prefix[0] != '\\0') {\n\t\tchar filename[DUMP_FILENAME_BUFSIZE];\n\t\tmalloc_mutex_lock(tsdn, &prof_dump_seq_mtx);\n\t\tprof_dump_filename(filename, 'u', prof_dump_useq);\n\t\tprof_dump_useq++;\n\t\tmalloc_mutex_unlock(tsdn, &prof_dump_seq_mtx);\n\t\tprof_dump(tsd, false, filename, false);\n\t}\n}\n\nstatic void\nprof_bt_hash(const void *key, size_t r_hash[2])\n{\n\tprof_bt_t *bt = (prof_bt_t *)key;\n\n\tcassert(config_prof);\n\n\thash(bt->vec, bt->len * sizeof(void *), 0x94122f33U, r_hash);\n}\n\nstatic bool\nprof_bt_keycomp(const void *k1, const void *k2)\n{\n\tconst prof_bt_t *bt1 = (prof_bt_t *)k1;\n\tconst prof_bt_t *bt2 = (prof_bt_t *)k2;\n\n\tcassert(config_prof);\n\n\tif (bt1->len != bt2->len)\n\t\treturn (false);\n\treturn (memcmp(bt1->vec, bt2->vec, bt1->len * sizeof(void *)) == 0);\n}\n\nJEMALLOC_INLINE_C uint64_t\nprof_thr_uid_alloc(tsdn_t *tsdn)\n{\n\tuint64_t thr_uid;\n\n\tmalloc_mutex_lock(tsdn, &next_thr_uid_mtx);\n\tthr_uid = next_thr_uid;\n\tnext_thr_uid++;\n\tmalloc_mutex_unlock(tsdn, &next_thr_uid_mtx);\n\n\treturn (thr_uid);\n}\n\nstatic prof_tdata_t *\nprof_tdata_init_impl(tsdn_t *tsdn, uint64_t thr_uid, uint64_t thr_discrim,\n    char *thread_name, bool active)\n{\n\tprof_tdata_t *tdata;\n\n\tcassert(config_prof);\n\n\t/* Initialize an empty cache for this thread. */\n\ttdata = (prof_tdata_t *)iallocztm(tsdn, sizeof(prof_tdata_t),\n\t    size2index(sizeof(prof_tdata_t)), false, NULL, true,\n\t    arena_get(TSDN_NULL, 0, true), true);\n\tif (tdata == NULL)\n\t\treturn (NULL);\n\n\ttdata->lock = prof_tdata_mutex_choose(thr_uid);\n\ttdata->thr_uid = thr_uid;\n\ttdata->thr_discrim = thr_discrim;\n\ttdata->thread_name = thread_name;\n\ttdata->attached = true;\n\ttdata->expired = false;\n\ttdata->tctx_uid_next = 0;\n\n\tif (ckh_new(tsdn, &tdata->bt2tctx, PROF_CKH_MINITEMS,\n\t    prof_bt_hash, prof_bt_keycomp)) {\n\t\tidalloctm(tsdn, tdata, NULL, true, true);\n\t\treturn (NULL);\n\t}\n\n\ttdata->prng_state = (uint64_t)(uintptr_t)tdata;\n\tprof_sample_threshold_update(tdata);\n\n\ttdata->enq = false;\n\ttdata->enq_idump = false;\n\ttdata->enq_gdump = false;\n\n\ttdata->dumping = false;\n\ttdata->active = active;\n\n\tmalloc_mutex_lock(tsdn, &tdatas_mtx);\n\ttdata_tree_insert(&tdatas, tdata);\n\tmalloc_mutex_unlock(tsdn, &tdatas_mtx);\n\n\treturn (tdata);\n}\n\nprof_tdata_t *\nprof_tdata_init(tsdn_t *tsdn)\n{\n\n\treturn (prof_tdata_init_impl(tsdn, prof_thr_uid_alloc(tsdn), 0, NULL,\n\t    prof_thread_active_init_get(tsdn)));\n}\n\nstatic bool\nprof_tdata_should_destroy_unlocked(prof_tdata_t *tdata, bool even_if_attached)\n{\n\n\tif (tdata->attached && !even_if_attached)\n\t\treturn (false);\n\tif (ckh_count(&tdata->bt2tctx) != 0)\n\t\treturn (false);\n\treturn (true);\n}\n\nstatic bool\nprof_tdata_should_destroy(tsdn_t *tsdn, prof_tdata_t *tdata,\n    bool even_if_attached)\n{\n\n\tmalloc_mutex_assert_owner(tsdn, tdata->lock);\n\n\treturn (prof_tdata_should_destroy_unlocked(tdata, even_if_attached));\n}\n\nstatic void\nprof_tdata_destroy_locked(tsdn_t *tsdn, prof_tdata_t *tdata,\n    bool even_if_attached)\n{\n\n\tmalloc_mutex_assert_owner(tsdn, &tdatas_mtx);\n\n\tassert(tsdn_null(tsdn) || tsd_prof_tdata_get(tsdn_tsd(tsdn)) != tdata);\n\n\ttdata_tree_remove(&tdatas, tdata);\n\n\tassert(prof_tdata_should_destroy_unlocked(tdata, even_if_attached));\n\n\tif (tdata->thread_name != NULL)\n\t\tidalloctm(tsdn, tdata->thread_name, NULL, true, true);\n\tckh_delete(tsdn, &tdata->bt2tctx);\n\tidalloctm(tsdn, tdata, NULL, true, true);\n}\n\nstatic void\nprof_tdata_destroy(tsdn_t *tsdn, prof_tdata_t *tdata, bool even_if_attached)\n{\n\n\tmalloc_mutex_lock(tsdn, &tdatas_mtx);\n\tprof_tdata_destroy_locked(tsdn, tdata, even_if_attached);\n\tmalloc_mutex_unlock(tsdn, &tdatas_mtx);\n}\n\nstatic void\nprof_tdata_detach(tsd_t *tsd, prof_tdata_t *tdata)\n{\n\tbool destroy_tdata;\n\n\tmalloc_mutex_lock(tsd_tsdn(tsd), tdata->lock);\n\tif (tdata->attached) {\n\t\tdestroy_tdata = prof_tdata_should_destroy(tsd_tsdn(tsd), tdata,\n\t\t    true);\n\t\t/*\n\t\t * Only detach if !destroy_tdata, because detaching would allow\n\t\t * another thread to win the race to destroy tdata.\n\t\t */\n\t\tif (!destroy_tdata)\n\t\t\ttdata->attached = false;\n\t\ttsd_prof_tdata_set(tsd, NULL);\n\t} else\n\t\tdestroy_tdata = false;\n\tmalloc_mutex_unlock(tsd_tsdn(tsd), tdata->lock);\n\tif (destroy_tdata)\n\t\tprof_tdata_destroy(tsd_tsdn(tsd), tdata, true);\n}\n\nprof_tdata_t *\nprof_tdata_reinit(tsd_t *tsd, prof_tdata_t *tdata)\n{\n\tuint64_t thr_uid = tdata->thr_uid;\n\tuint64_t thr_discrim = tdata->thr_discrim + 1;\n\tchar *thread_name = (tdata->thread_name != NULL) ?\n\t    prof_thread_name_alloc(tsd_tsdn(tsd), tdata->thread_name) : NULL;\n\tbool active = tdata->active;\n\n\tprof_tdata_detach(tsd, tdata);\n\treturn (prof_tdata_init_impl(tsd_tsdn(tsd), thr_uid, thr_discrim,\n\t    thread_name, active));\n}\n\nstatic bool\nprof_tdata_expire(tsdn_t *tsdn, prof_tdata_t *tdata)\n{\n\tbool destroy_tdata;\n\n\tmalloc_mutex_lock(tsdn, tdata->lock);\n\tif (!tdata->expired) {\n\t\ttdata->expired = true;\n\t\tdestroy_tdata = tdata->attached ? false :\n\t\t    prof_tdata_should_destroy(tsdn, tdata, false);\n\t} else\n\t\tdestroy_tdata = false;\n\tmalloc_mutex_unlock(tsdn, tdata->lock);\n\n\treturn (destroy_tdata);\n}\n\nstatic prof_tdata_t *\nprof_tdata_reset_iter(prof_tdata_tree_t *tdatas, prof_tdata_t *tdata, void *arg)\n{\n\ttsdn_t *tsdn = (tsdn_t *)arg;\n\n\treturn (prof_tdata_expire(tsdn, tdata) ? tdata : NULL);\n}\n\nvoid\nprof_reset(tsdn_t *tsdn, size_t lg_sample)\n{\n\tprof_tdata_t *next;\n\n\tassert(lg_sample < (sizeof(uint64_t) << 3));\n\n\tmalloc_mutex_lock(tsdn, &prof_dump_mtx);\n\tmalloc_mutex_lock(tsdn, &tdatas_mtx);\n\n\tlg_prof_sample = lg_sample;\n\n\tnext = NULL;\n\tdo {\n\t\tprof_tdata_t *to_destroy = tdata_tree_iter(&tdatas, next,\n\t\t    prof_tdata_reset_iter, (void *)tsdn);\n\t\tif (to_destroy != NULL) {\n\t\t\tnext = tdata_tree_next(&tdatas, to_destroy);\n\t\t\tprof_tdata_destroy_locked(tsdn, to_destroy, false);\n\t\t} else\n\t\t\tnext = NULL;\n\t} while (next != NULL);\n\n\tmalloc_mutex_unlock(tsdn, &tdatas_mtx);\n\tmalloc_mutex_unlock(tsdn, &prof_dump_mtx);\n}\n\nvoid\nprof_tdata_cleanup(tsd_t *tsd)\n{\n\tprof_tdata_t *tdata;\n\n\tif (!config_prof)\n\t\treturn;\n\n\ttdata = tsd_prof_tdata_get(tsd);\n\tif (tdata != NULL)\n\t\tprof_tdata_detach(tsd, tdata);\n}\n\nbool\nprof_active_get(tsdn_t *tsdn)\n{\n\tbool prof_active_current;\n\n\tmalloc_mutex_lock(tsdn, &prof_active_mtx);\n\tprof_active_current = prof_active;\n\tmalloc_mutex_unlock(tsdn, &prof_active_mtx);\n\treturn (prof_active_current);\n}\n\nbool\nprof_active_set(tsdn_t *tsdn, bool active)\n{\n\tbool prof_active_old;\n\n\tmalloc_mutex_lock(tsdn, &prof_active_mtx);\n\tprof_active_old = prof_active;\n\tprof_active = active;\n\tmalloc_mutex_unlock(tsdn, &prof_active_mtx);\n\treturn (prof_active_old);\n}\n\nconst char *\nprof_thread_name_get(tsd_t *tsd)\n{\n\tprof_tdata_t *tdata;\n\n\ttdata = prof_tdata_get(tsd, true);\n\tif (tdata == NULL)\n\t\treturn (\"\");\n\treturn (tdata->thread_name != NULL ? tdata->thread_name : \"\");\n}\n\nstatic char *\nprof_thread_name_alloc(tsdn_t *tsdn, const char *thread_name)\n{\n\tchar *ret;\n\tsize_t size;\n\n\tif (thread_name == NULL)\n\t\treturn (NULL);\n\n\tsize = strlen(thread_name) + 1;\n\tif (size == 1)\n\t\treturn (\"\");\n\n\tret = iallocztm(tsdn, size, size2index(size), false, NULL, true,\n\t    arena_get(TSDN_NULL, 0, true), true);\n\tif (ret == NULL)\n\t\treturn (NULL);\n\tmemcpy(ret, thread_name, size);\n\treturn (ret);\n}\n\nint\nprof_thread_name_set(tsd_t *tsd, const char *thread_name)\n{\n\tprof_tdata_t *tdata;\n\tunsigned i;\n\tchar *s;\n\n\ttdata = prof_tdata_get(tsd, true);\n\tif (tdata == NULL)\n\t\treturn (EAGAIN);\n\n\t/* Validate input. */\n\tif (thread_name == NULL)\n\t\treturn (EFAULT);\n\tfor (i = 0; thread_name[i] != '\\0'; i++) {\n\t\tchar c = thread_name[i];\n\t\tif (!isgraph(c) && !isblank(c))\n\t\t\treturn (EFAULT);\n\t}\n\n\ts = prof_thread_name_alloc(tsd_tsdn(tsd), thread_name);\n\tif (s == NULL)\n\t\treturn (EAGAIN);\n\n\tif (tdata->thread_name != NULL) {\n\t\tidalloctm(tsd_tsdn(tsd), tdata->thread_name, NULL, true, true);\n\t\ttdata->thread_name = NULL;\n\t}\n\tif (strlen(s) > 0)\n\t\ttdata->thread_name = s;\n\treturn (0);\n}\n\nbool\nprof_thread_active_get(tsd_t *tsd)\n{\n\tprof_tdata_t *tdata;\n\n\ttdata = prof_tdata_get(tsd, true);\n\tif (tdata == NULL)\n\t\treturn (false);\n\treturn (tdata->active);\n}\n\nbool\nprof_thread_active_set(tsd_t *tsd, bool active)\n{\n\tprof_tdata_t *tdata;\n\n\ttdata = prof_tdata_get(tsd, true);\n\tif (tdata == NULL)\n\t\treturn (true);\n\ttdata->active = active;\n\treturn (false);\n}\n\nbool\nprof_thread_active_init_get(tsdn_t *tsdn)\n{\n\tbool active_init;\n\n\tmalloc_mutex_lock(tsdn, &prof_thread_active_init_mtx);\n\tactive_init = prof_thread_active_init;\n\tmalloc_mutex_unlock(tsdn, &prof_thread_active_init_mtx);\n\treturn (active_init);\n}\n\nbool\nprof_thread_active_init_set(tsdn_t *tsdn, bool active_init)\n{\n\tbool active_init_old;\n\n\tmalloc_mutex_lock(tsdn, &prof_thread_active_init_mtx);\n\tactive_init_old = prof_thread_active_init;\n\tprof_thread_active_init = active_init;\n\tmalloc_mutex_unlock(tsdn, &prof_thread_active_init_mtx);\n\treturn (active_init_old);\n}\n\nbool\nprof_gdump_get(tsdn_t *tsdn)\n{\n\tbool prof_gdump_current;\n\n\tmalloc_mutex_lock(tsdn, &prof_gdump_mtx);\n\tprof_gdump_current = prof_gdump_val;\n\tmalloc_mutex_unlock(tsdn, &prof_gdump_mtx);\n\treturn (prof_gdump_current);\n}\n\nbool\nprof_gdump_set(tsdn_t *tsdn, bool gdump)\n{\n\tbool prof_gdump_old;\n\n\tmalloc_mutex_lock(tsdn, &prof_gdump_mtx);\n\tprof_gdump_old = prof_gdump_val;\n\tprof_gdump_val = gdump;\n\tmalloc_mutex_unlock(tsdn, &prof_gdump_mtx);\n\treturn (prof_gdump_old);\n}\n\nvoid\nprof_boot0(void)\n{\n\n\tcassert(config_prof);\n\n\tmemcpy(opt_prof_prefix, PROF_PREFIX_DEFAULT,\n\t    sizeof(PROF_PREFIX_DEFAULT));\n}\n\nvoid\nprof_boot1(void)\n{\n\n\tcassert(config_prof);\n\n\t/*\n\t * opt_prof must be in its final state before any arenas are\n\t * initialized, so this function must be executed early.\n\t */\n\n\tif (opt_prof_leak && !opt_prof) {\n\t\t/*\n\t\t * Enable opt_prof, but in such a way that profiles are never\n\t\t * automatically dumped.\n\t\t */\n\t\topt_prof = true;\n\t\topt_prof_gdump = false;\n\t} else if (opt_prof) {\n\t\tif (opt_lg_prof_interval >= 0) {\n\t\t\tprof_interval = (((uint64_t)1U) <<\n\t\t\t    opt_lg_prof_interval);\n\t\t}\n\t}\n}\n\nbool\nprof_boot2(tsdn_t *tsdn)\n{\n\n\tcassert(config_prof);\n\n\tif (opt_prof) {\n\t\tunsigned i;\n\n\t\tlg_prof_sample = opt_lg_prof_sample;\n\n\t\tprof_active = opt_prof_active;\n\t\tif (malloc_mutex_init(&prof_active_mtx, \"prof_active\",\n\t\t    WITNESS_RANK_PROF_ACTIVE))\n\t\t\treturn (true);\n\n\t\tprof_gdump_val = opt_prof_gdump;\n\t\tif (malloc_mutex_init(&prof_gdump_mtx, \"prof_gdump\",\n\t\t    WITNESS_RANK_PROF_GDUMP))\n\t\t\treturn (true);\n\n\t\tprof_thread_active_init = opt_prof_thread_active_init;\n\t\tif (malloc_mutex_init(&prof_thread_active_init_mtx,\n\t\t    \"prof_thread_active_init\",\n\t\t    WITNESS_RANK_PROF_THREAD_ACTIVE_INIT))\n\t\t\treturn (true);\n\n\t\tif (ckh_new(tsdn, &bt2gctx, PROF_CKH_MINITEMS, prof_bt_hash,\n\t\t    prof_bt_keycomp))\n\t\t\treturn (true);\n\t\tif (malloc_mutex_init(&bt2gctx_mtx, \"prof_bt2gctx\",\n\t\t    WITNESS_RANK_PROF_BT2GCTX))\n\t\t\treturn (true);\n\n\t\ttdata_tree_new(&tdatas);\n\t\tif (malloc_mutex_init(&tdatas_mtx, \"prof_tdatas\",\n\t\t    WITNESS_RANK_PROF_TDATAS))\n\t\t\treturn (true);\n\n\t\tnext_thr_uid = 0;\n\t\tif (malloc_mutex_init(&next_thr_uid_mtx, \"prof_next_thr_uid\",\n\t\t    WITNESS_RANK_PROF_NEXT_THR_UID))\n\t\t\treturn (true);\n\n\t\tif (malloc_mutex_init(&prof_dump_seq_mtx, \"prof_dump_seq\",\n\t\t    WITNESS_RANK_PROF_DUMP_SEQ))\n\t\t\treturn (true);\n\t\tif (malloc_mutex_init(&prof_dump_mtx, \"prof_dump\",\n\t\t    WITNESS_RANK_PROF_DUMP))\n\t\t\treturn (true);\n\n\t\tif (opt_prof_final && opt_prof_prefix[0] != '\\0' &&\n\t\t    atexit(prof_fdump) != 0) {\n\t\t\tmalloc_write(\"<jemalloc>: Error in atexit()\\n\");\n\t\t\tif (opt_abort)\n\t\t\t\tabort();\n\t\t}\n\n\t\tgctx_locks = (malloc_mutex_t *)base_alloc(tsdn, PROF_NCTX_LOCKS\n\t\t    * sizeof(malloc_mutex_t));\n\t\tif (gctx_locks == NULL)\n\t\t\treturn (true);\n\t\tfor (i = 0; i < PROF_NCTX_LOCKS; i++) {\n\t\t\tif (malloc_mutex_init(&gctx_locks[i], \"prof_gctx\",\n\t\t\t    WITNESS_RANK_PROF_GCTX))\n\t\t\t\treturn (true);\n\t\t}\n\n\t\ttdata_locks = (malloc_mutex_t *)base_alloc(tsdn,\n\t\t    PROF_NTDATA_LOCKS * sizeof(malloc_mutex_t));\n\t\tif (tdata_locks == NULL)\n\t\t\treturn (true);\n\t\tfor (i = 0; i < PROF_NTDATA_LOCKS; i++) {\n\t\t\tif (malloc_mutex_init(&tdata_locks[i], \"prof_tdata\",\n\t\t\t    WITNESS_RANK_PROF_TDATA))\n\t\t\t\treturn (true);\n\t\t}\n\t}\n\n#ifdef JEMALLOC_PROF_LIBGCC\n\t/*\n\t * Cause the backtracing machinery to allocate its internal state\n\t * before enabling profiling.\n\t */\n\t_Unwind_Backtrace(prof_unwind_init_callback, NULL);\n#endif\n\n\tprof_booted = true;\n\n\treturn (false);\n}\n\nvoid\nprof_prefork0(tsdn_t *tsdn)\n{\n\n\tif (opt_prof) {\n\t\tunsigned i;\n\n\t\tmalloc_mutex_prefork(tsdn, &prof_dump_mtx);\n\t\tmalloc_mutex_prefork(tsdn, &bt2gctx_mtx);\n\t\tmalloc_mutex_prefork(tsdn, &tdatas_mtx);\n\t\tfor (i = 0; i < PROF_NTDATA_LOCKS; i++)\n\t\t\tmalloc_mutex_prefork(tsdn, &tdata_locks[i]);\n\t\tfor (i = 0; i < PROF_NCTX_LOCKS; i++)\n\t\t\tmalloc_mutex_prefork(tsdn, &gctx_locks[i]);\n\t}\n}\n\nvoid\nprof_prefork1(tsdn_t *tsdn)\n{\n\n\tif (opt_prof) {\n\t\tmalloc_mutex_prefork(tsdn, &prof_active_mtx);\n\t\tmalloc_mutex_prefork(tsdn, &prof_dump_seq_mtx);\n\t\tmalloc_mutex_prefork(tsdn, &prof_gdump_mtx);\n\t\tmalloc_mutex_prefork(tsdn, &next_thr_uid_mtx);\n\t\tmalloc_mutex_prefork(tsdn, &prof_thread_active_init_mtx);\n\t}\n}\n\nvoid\nprof_postfork_parent(tsdn_t *tsdn)\n{\n\n\tif (opt_prof) {\n\t\tunsigned i;\n\n\t\tmalloc_mutex_postfork_parent(tsdn,\n\t\t    &prof_thread_active_init_mtx);\n\t\tmalloc_mutex_postfork_parent(tsdn, &next_thr_uid_mtx);\n\t\tmalloc_mutex_postfork_parent(tsdn, &prof_gdump_mtx);\n\t\tmalloc_mutex_postfork_parent(tsdn, &prof_dump_seq_mtx);\n\t\tmalloc_mutex_postfork_parent(tsdn, &prof_active_mtx);\n\t\tfor (i = 0; i < PROF_NCTX_LOCKS; i++)\n\t\t\tmalloc_mutex_postfork_parent(tsdn, &gctx_locks[i]);\n\t\tfor (i = 0; i < PROF_NTDATA_LOCKS; i++)\n\t\t\tmalloc_mutex_postfork_parent(tsdn, &tdata_locks[i]);\n\t\tmalloc_mutex_postfork_parent(tsdn, &tdatas_mtx);\n\t\tmalloc_mutex_postfork_parent(tsdn, &bt2gctx_mtx);\n\t\tmalloc_mutex_postfork_parent(tsdn, &prof_dump_mtx);\n\t}\n}\n\nvoid\nprof_postfork_child(tsdn_t *tsdn)\n{\n\n\tif (opt_prof) {\n\t\tunsigned i;\n\n\t\tmalloc_mutex_postfork_child(tsdn, &prof_thread_active_init_mtx);\n\t\tmalloc_mutex_postfork_child(tsdn, &next_thr_uid_mtx);\n\t\tmalloc_mutex_postfork_child(tsdn, &prof_gdump_mtx);\n\t\tmalloc_mutex_postfork_child(tsdn, &prof_dump_seq_mtx);\n\t\tmalloc_mutex_postfork_child(tsdn, &prof_active_mtx);\n\t\tfor (i = 0; i < PROF_NCTX_LOCKS; i++)\n\t\t\tmalloc_mutex_postfork_child(tsdn, &gctx_locks[i]);\n\t\tfor (i = 0; i < PROF_NTDATA_LOCKS; i++)\n\t\t\tmalloc_mutex_postfork_child(tsdn, &tdata_locks[i]);\n\t\tmalloc_mutex_postfork_child(tsdn, &tdatas_mtx);\n\t\tmalloc_mutex_postfork_child(tsdn, &bt2gctx_mtx);\n\t\tmalloc_mutex_postfork_child(tsdn, &prof_dump_mtx);\n\t}\n}\n\n/******************************************************************************/\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/deps/jemalloc/src/quarantine.c",
    "content": "#define\tJEMALLOC_QUARANTINE_C_\n#include \"jemalloc/internal/jemalloc_internal.h\"\n\n/*\n * Quarantine pointers close to NULL are used to encode state information that\n * is used for cleaning up during thread shutdown.\n */\n#define\tQUARANTINE_STATE_REINCARNATED\t((quarantine_t *)(uintptr_t)1)\n#define\tQUARANTINE_STATE_PURGATORY\t((quarantine_t *)(uintptr_t)2)\n#define\tQUARANTINE_STATE_MAX\t\tQUARANTINE_STATE_PURGATORY\n\n/******************************************************************************/\n/* Function prototypes for non-inline static functions. */\n\nstatic quarantine_t\t*quarantine_grow(tsd_t *tsd, quarantine_t *quarantine);\nstatic void\tquarantine_drain_one(tsdn_t *tsdn, quarantine_t *quarantine);\nstatic void\tquarantine_drain(tsdn_t *tsdn, quarantine_t *quarantine,\n    size_t upper_bound);\n\n/******************************************************************************/\n\nstatic quarantine_t *\nquarantine_init(tsdn_t *tsdn, size_t lg_maxobjs)\n{\n\tquarantine_t *quarantine;\n\tsize_t size;\n\n\tsize = offsetof(quarantine_t, objs) + ((ZU(1) << lg_maxobjs) *\n\t    sizeof(quarantine_obj_t));\n\tquarantine = (quarantine_t *)iallocztm(tsdn, size, size2index(size),\n\t    false, NULL, true, arena_get(TSDN_NULL, 0, true), true);\n\tif (quarantine == NULL)\n\t\treturn (NULL);\n\tquarantine->curbytes = 0;\n\tquarantine->curobjs = 0;\n\tquarantine->first = 0;\n\tquarantine->lg_maxobjs = lg_maxobjs;\n\n\treturn (quarantine);\n}\n\nvoid\nquarantine_alloc_hook_work(tsd_t *tsd)\n{\n\tquarantine_t *quarantine;\n\n\tif (!tsd_nominal(tsd))\n\t\treturn;\n\n\tquarantine = quarantine_init(tsd_tsdn(tsd), LG_MAXOBJS_INIT);\n\t/*\n\t * Check again whether quarantine has been initialized, because\n\t * quarantine_init() may have triggered recursive initialization.\n\t */\n\tif (tsd_quarantine_get(tsd) == NULL)\n\t\ttsd_quarantine_set(tsd, quarantine);\n\telse\n\t\tidalloctm(tsd_tsdn(tsd), quarantine, NULL, true, true);\n}\n\nstatic quarantine_t *\nquarantine_grow(tsd_t *tsd, quarantine_t *quarantine)\n{\n\tquarantine_t *ret;\n\n\tret = quarantine_init(tsd_tsdn(tsd), quarantine->lg_maxobjs + 1);\n\tif (ret == NULL) {\n\t\tquarantine_drain_one(tsd_tsdn(tsd), quarantine);\n\t\treturn (quarantine);\n\t}\n\n\tret->curbytes = quarantine->curbytes;\n\tret->curobjs = quarantine->curobjs;\n\tif (quarantine->first + quarantine->curobjs <= (ZU(1) <<\n\t    quarantine->lg_maxobjs)) {\n\t\t/* objs ring buffer data are contiguous. */\n\t\tmemcpy(ret->objs, &quarantine->objs[quarantine->first],\n\t\t    quarantine->curobjs * sizeof(quarantine_obj_t));\n\t} else {\n\t\t/* objs ring buffer data wrap around. */\n\t\tsize_t ncopy_a = (ZU(1) << quarantine->lg_maxobjs) -\n\t\t    quarantine->first;\n\t\tsize_t ncopy_b = quarantine->curobjs - ncopy_a;\n\n\t\tmemcpy(ret->objs, &quarantine->objs[quarantine->first], ncopy_a\n\t\t    * sizeof(quarantine_obj_t));\n\t\tmemcpy(&ret->objs[ncopy_a], quarantine->objs, ncopy_b *\n\t\t    sizeof(quarantine_obj_t));\n\t}\n\tidalloctm(tsd_tsdn(tsd), quarantine, NULL, true, true);\n\n\ttsd_quarantine_set(tsd, ret);\n\treturn (ret);\n}\n\nstatic void\nquarantine_drain_one(tsdn_t *tsdn, quarantine_t *quarantine)\n{\n\tquarantine_obj_t *obj = &quarantine->objs[quarantine->first];\n\tassert(obj->usize == isalloc(tsdn, obj->ptr, config_prof));\n\tidalloctm(tsdn, obj->ptr, NULL, false, true);\n\tquarantine->curbytes -= obj->usize;\n\tquarantine->curobjs--;\n\tquarantine->first = (quarantine->first + 1) & ((ZU(1) <<\n\t    quarantine->lg_maxobjs) - 1);\n}\n\nstatic void\nquarantine_drain(tsdn_t *tsdn, quarantine_t *quarantine, size_t upper_bound)\n{\n\n\twhile (quarantine->curbytes > upper_bound && quarantine->curobjs > 0)\n\t\tquarantine_drain_one(tsdn, quarantine);\n}\n\nvoid\nquarantine(tsd_t *tsd, void *ptr)\n{\n\tquarantine_t *quarantine;\n\tsize_t usize = isalloc(tsd_tsdn(tsd), ptr, config_prof);\n\n\tcassert(config_fill);\n\tassert(opt_quarantine);\n\n\tif ((quarantine = tsd_quarantine_get(tsd)) == NULL) {\n\t\tidalloctm(tsd_tsdn(tsd), ptr, NULL, false, true);\n\t\treturn;\n\t}\n\t/*\n\t * Drain one or more objects if the quarantine size limit would be\n\t * exceeded by appending ptr.\n\t */\n\tif (quarantine->curbytes + usize > opt_quarantine) {\n\t\tsize_t upper_bound = (opt_quarantine >= usize) ? opt_quarantine\n\t\t    - usize : 0;\n\t\tquarantine_drain(tsd_tsdn(tsd), quarantine, upper_bound);\n\t}\n\t/* Grow the quarantine ring buffer if it's full. */\n\tif (quarantine->curobjs == (ZU(1) << quarantine->lg_maxobjs))\n\t\tquarantine = quarantine_grow(tsd, quarantine);\n\t/* quarantine_grow() must free a slot if it fails to grow. */\n\tassert(quarantine->curobjs < (ZU(1) << quarantine->lg_maxobjs));\n\t/* Append ptr if its size doesn't exceed the quarantine size. */\n\tif (quarantine->curbytes + usize <= opt_quarantine) {\n\t\tsize_t offset = (quarantine->first + quarantine->curobjs) &\n\t\t    ((ZU(1) << quarantine->lg_maxobjs) - 1);\n\t\tquarantine_obj_t *obj = &quarantine->objs[offset];\n\t\tobj->ptr = ptr;\n\t\tobj->usize = usize;\n\t\tquarantine->curbytes += usize;\n\t\tquarantine->curobjs++;\n\t\tif (config_fill && unlikely(opt_junk_free)) {\n\t\t\t/*\n\t\t\t * Only do redzone validation if Valgrind isn't in\n\t\t\t * operation.\n\t\t\t */\n\t\t\tif ((!config_valgrind || likely(!in_valgrind))\n\t\t\t    && usize <= SMALL_MAXCLASS)\n\t\t\t\tarena_quarantine_junk_small(ptr, usize);\n\t\t\telse\n\t\t\t\tmemset(ptr, JEMALLOC_FREE_JUNK, usize);\n\t\t}\n\t} else {\n\t\tassert(quarantine->curbytes == 0);\n\t\tidalloctm(tsd_tsdn(tsd), ptr, NULL, false, true);\n\t}\n}\n\nvoid\nquarantine_cleanup(tsd_t *tsd)\n{\n\tquarantine_t *quarantine;\n\n\tif (!config_fill)\n\t\treturn;\n\n\tquarantine = tsd_quarantine_get(tsd);\n\tif (quarantine != NULL) {\n\t\tquarantine_drain(tsd_tsdn(tsd), quarantine, 0);\n\t\tidalloctm(tsd_tsdn(tsd), quarantine, NULL, true, true);\n\t\ttsd_quarantine_set(tsd, NULL);\n\t}\n}\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/deps/jemalloc/src/rtree.c",
    "content": "#define\tJEMALLOC_RTREE_C_\n#include \"jemalloc/internal/jemalloc_internal.h\"\n\nstatic unsigned\nhmin(unsigned ha, unsigned hb)\n{\n\n\treturn (ha < hb ? ha : hb);\n}\n\n/* Only the most significant bits of keys passed to rtree_[gs]et() are used. */\nbool\nrtree_new(rtree_t *rtree, unsigned bits, rtree_node_alloc_t *alloc,\n    rtree_node_dalloc_t *dalloc)\n{\n\tunsigned bits_in_leaf, height, i;\n\n\tassert(RTREE_HEIGHT_MAX == ((ZU(1) << (LG_SIZEOF_PTR+3)) /\n\t    RTREE_BITS_PER_LEVEL));\n\tassert(bits > 0 && bits <= (sizeof(uintptr_t) << 3));\n\n\tbits_in_leaf = (bits % RTREE_BITS_PER_LEVEL) == 0 ? RTREE_BITS_PER_LEVEL\n\t    : (bits % RTREE_BITS_PER_LEVEL);\n\tif (bits > bits_in_leaf) {\n\t\theight = 1 + (bits - bits_in_leaf) / RTREE_BITS_PER_LEVEL;\n\t\tif ((height-1) * RTREE_BITS_PER_LEVEL + bits_in_leaf != bits)\n\t\t\theight++;\n\t} else\n\t\theight = 1;\n\tassert((height-1) * RTREE_BITS_PER_LEVEL + bits_in_leaf == bits);\n\n\trtree->alloc = alloc;\n\trtree->dalloc = dalloc;\n\trtree->height = height;\n\n\t/* Root level. */\n\trtree->levels[0].subtree = NULL;\n\trtree->levels[0].bits = (height > 1) ? RTREE_BITS_PER_LEVEL :\n\t    bits_in_leaf;\n\trtree->levels[0].cumbits = rtree->levels[0].bits;\n\t/* Interior levels. */\n\tfor (i = 1; i < height-1; i++) {\n\t\trtree->levels[i].subtree = NULL;\n\t\trtree->levels[i].bits = RTREE_BITS_PER_LEVEL;\n\t\trtree->levels[i].cumbits = rtree->levels[i-1].cumbits +\n\t\t    RTREE_BITS_PER_LEVEL;\n\t}\n\t/* Leaf level. */\n\tif (height > 1) {\n\t\trtree->levels[height-1].subtree = NULL;\n\t\trtree->levels[height-1].bits = bits_in_leaf;\n\t\trtree->levels[height-1].cumbits = bits;\n\t}\n\n\t/* Compute lookup table to be used by rtree_start_level(). */\n\tfor (i = 0; i < RTREE_HEIGHT_MAX; i++) {\n\t\trtree->start_level[i] = hmin(RTREE_HEIGHT_MAX - 1 - i, height -\n\t\t    1);\n\t}\n\n\treturn (false);\n}\n\nstatic void\nrtree_delete_subtree(rtree_t *rtree, rtree_node_elm_t *node, unsigned level)\n{\n\n\tif (level + 1 < rtree->height) {\n\t\tsize_t nchildren, i;\n\n\t\tnchildren = ZU(1) << rtree->levels[level].bits;\n\t\tfor (i = 0; i < nchildren; i++) {\n\t\t\trtree_node_elm_t *child = node[i].child;\n\t\t\tif (child != NULL)\n\t\t\t\trtree_delete_subtree(rtree, child, level + 1);\n\t\t}\n\t}\n\trtree->dalloc(node);\n}\n\nvoid\nrtree_delete(rtree_t *rtree)\n{\n\tunsigned i;\n\n\tfor (i = 0; i < rtree->height; i++) {\n\t\trtree_node_elm_t *subtree = rtree->levels[i].subtree;\n\t\tif (subtree != NULL)\n\t\t\trtree_delete_subtree(rtree, subtree, i);\n\t}\n}\n\nstatic rtree_node_elm_t *\nrtree_node_init(rtree_t *rtree, unsigned level, rtree_node_elm_t **elmp)\n{\n\trtree_node_elm_t *node;\n\n\tif (atomic_cas_p((void **)elmp, NULL, RTREE_NODE_INITIALIZING)) {\n\t\t/*\n\t\t * Another thread is already in the process of initializing.\n\t\t * Spin-wait until initialization is complete.\n\t\t */\n\t\tdo {\n\t\t\tCPU_SPINWAIT;\n\t\t\tnode = atomic_read_p((void **)elmp);\n\t\t} while (node == RTREE_NODE_INITIALIZING);\n\t} else {\n\t\tnode = rtree->alloc(ZU(1) << rtree->levels[level].bits);\n\t\tif (node == NULL)\n\t\t\treturn (NULL);\n\t\tatomic_write_p((void **)elmp, node);\n\t}\n\n\treturn (node);\n}\n\nrtree_node_elm_t *\nrtree_subtree_read_hard(rtree_t *rtree, unsigned level)\n{\n\n\treturn (rtree_node_init(rtree, level, &rtree->levels[level].subtree));\n}\n\nrtree_node_elm_t *\nrtree_child_read_hard(rtree_t *rtree, rtree_node_elm_t *elm, unsigned level)\n{\n\n\treturn (rtree_node_init(rtree, level, &elm->child));\n}\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/deps/jemalloc/src/stats.c",
    "content": "#define\tJEMALLOC_STATS_C_\n#include \"jemalloc/internal/jemalloc_internal.h\"\n\n#define\tCTL_GET(n, v, t) do {\t\t\t\t\t\t\\\n\tsize_t sz = sizeof(t);\t\t\t\t\t\t\\\n\txmallctl(n, v, &sz, NULL, 0);\t\t\t\t\t\\\n} while (0)\n\n#define\tCTL_M2_GET(n, i, v, t) do {\t\t\t\t\t\\\n\tsize_t mib[6];\t\t\t\t\t\t\t\\\n\tsize_t miblen = sizeof(mib) / sizeof(size_t);\t\t\t\\\n\tsize_t sz = sizeof(t);\t\t\t\t\t\t\\\n\txmallctlnametomib(n, mib, &miblen);\t\t\t\t\\\n\tmib[2] = (i);\t\t\t\t\t\t\t\\\n\txmallctlbymib(mib, miblen, v, &sz, NULL, 0);\t\t\t\\\n} while (0)\n\n#define\tCTL_M2_M4_GET(n, i, j, v, t) do {\t\t\t\t\\\n\tsize_t mib[6];\t\t\t\t\t\t\t\\\n\tsize_t miblen = sizeof(mib) / sizeof(size_t);\t\t\t\\\n\tsize_t sz = sizeof(t);\t\t\t\t\t\t\\\n\txmallctlnametomib(n, mib, &miblen);\t\t\t\t\\\n\tmib[2] = (i);\t\t\t\t\t\t\t\\\n\tmib[4] = (j);\t\t\t\t\t\t\t\\\n\txmallctlbymib(mib, miblen, v, &sz, NULL, 0);\t\t\t\\\n} while (0)\n\n/******************************************************************************/\n/* Data. */\n\nbool\topt_stats_print = false;\n\nsize_t\tstats_cactive = 0;\n\n/******************************************************************************/\n/* Function prototypes for non-inline static functions. */\n\nstatic void\tstats_arena_bins_print(void (*write_cb)(void *, const char *),\n    void *cbopaque, unsigned i);\nstatic void\tstats_arena_lruns_print(void (*write_cb)(void *, const char *),\n    void *cbopaque, unsigned i);\nstatic void\tstats_arena_hchunks_print(\n    void (*write_cb)(void *, const char *), void *cbopaque, unsigned i);\nstatic void\tstats_arena_print(void (*write_cb)(void *, const char *),\n    void *cbopaque, unsigned i, bool bins, bool large, bool huge);\n\n/******************************************************************************/\n\nstatic void\nstats_arena_bins_print(void (*write_cb)(void *, const char *), void *cbopaque,\n    unsigned i)\n{\n\tsize_t page;\n\tbool config_tcache, in_gap;\n\tunsigned nbins, j;\n\n\tCTL_GET(\"arenas.page\", &page, size_t);\n\n\tCTL_GET(\"config.tcache\", &config_tcache, bool);\n\tif (config_tcache) {\n\t\tmalloc_cprintf(write_cb, cbopaque,\n\t\t    \"bins:           size ind    allocated      nmalloc\"\n\t\t    \"      ndalloc    nrequests      curregs      curruns regs\"\n\t\t    \" pgs  util       nfills     nflushes      newruns\"\n\t\t    \"       reruns\\n\");\n\t} else {\n\t\tmalloc_cprintf(write_cb, cbopaque,\n\t\t    \"bins:           size ind    allocated      nmalloc\"\n\t\t    \"      ndalloc    nrequests      curregs      curruns regs\"\n\t\t    \" pgs  util      newruns       reruns\\n\");\n\t}\n\tCTL_GET(\"arenas.nbins\", &nbins, unsigned);\n\tfor (j = 0, in_gap = false; j < nbins; j++) {\n\t\tuint64_t nruns;\n\n\t\tCTL_M2_M4_GET(\"stats.arenas.0.bins.0.nruns\", i, j, &nruns,\n\t\t    uint64_t);\n\t\tif (nruns == 0)\n\t\t\tin_gap = true;\n\t\telse {\n\t\t\tsize_t reg_size, run_size, curregs, availregs, milli;\n\t\t\tsize_t curruns;\n\t\t\tuint32_t nregs;\n\t\t\tuint64_t nmalloc, ndalloc, nrequests, nfills, nflushes;\n\t\t\tuint64_t reruns;\n\t\t\tchar util[6]; /* \"x.yyy\". */\n\n\t\t\tif (in_gap) {\n\t\t\t\tmalloc_cprintf(write_cb, cbopaque,\n\t\t\t\t    \"                     ---\\n\");\n\t\t\t\tin_gap = false;\n\t\t\t}\n\t\t\tCTL_M2_GET(\"arenas.bin.0.size\", j, &reg_size, size_t);\n\t\t\tCTL_M2_GET(\"arenas.bin.0.nregs\", j, &nregs, uint32_t);\n\t\t\tCTL_M2_GET(\"arenas.bin.0.run_size\", j, &run_size,\n\t\t\t    size_t);\n\t\t\tCTL_M2_M4_GET(\"stats.arenas.0.bins.0.nmalloc\", i, j,\n\t\t\t    &nmalloc, uint64_t);\n\t\t\tCTL_M2_M4_GET(\"stats.arenas.0.bins.0.ndalloc\", i, j,\n\t\t\t    &ndalloc, uint64_t);\n\t\t\tCTL_M2_M4_GET(\"stats.arenas.0.bins.0.curregs\", i, j,\n\t\t\t    &curregs, size_t);\n\t\t\tCTL_M2_M4_GET(\"stats.arenas.0.bins.0.nrequests\", i, j,\n\t\t\t    &nrequests, uint64_t);\n\t\t\tif (config_tcache) {\n\t\t\t\tCTL_M2_M4_GET(\"stats.arenas.0.bins.0.nfills\", i,\n\t\t\t\t    j, &nfills, uint64_t);\n\t\t\t\tCTL_M2_M4_GET(\"stats.arenas.0.bins.0.nflushes\",\n\t\t\t\t    i, j, &nflushes, uint64_t);\n\t\t\t}\n\t\t\tCTL_M2_M4_GET(\"stats.arenas.0.bins.0.nreruns\", i, j,\n\t\t\t    &reruns, uint64_t);\n\t\t\tCTL_M2_M4_GET(\"stats.arenas.0.bins.0.curruns\", i, j,\n\t\t\t    &curruns, size_t);\n\n\t\t\tavailregs = nregs * curruns;\n\t\t\tmilli = (availregs != 0) ? (1000 * curregs) / availregs\n\t\t\t    : 1000;\n\t\t\tassert(milli <= 1000);\n\t\t\tif (milli < 10) {\n\t\t\t\tmalloc_snprintf(util, sizeof(util),\n\t\t\t\t    \"0.00%zu\", milli);\n\t\t\t} else if (milli < 100) {\n\t\t\t\tmalloc_snprintf(util, sizeof(util), \"0.0%zu\",\n\t\t\t\t    milli);\n\t\t\t} else if (milli < 1000) {\n\t\t\t\tmalloc_snprintf(util, sizeof(util), \"0.%zu\",\n\t\t\t\t    milli);\n\t\t\t} else\n\t\t\t\tmalloc_snprintf(util, sizeof(util), \"1\");\n\n\t\t\tif (config_tcache) {\n\t\t\t\tmalloc_cprintf(write_cb, cbopaque,\n\t\t\t\t    \"%20zu %3u %12zu %12\"FMTu64\n\t\t\t\t    \" %12\"FMTu64\" %12\"FMTu64\" %12zu\"\n\t\t\t\t    \" %12zu %4u %3zu %-5s %12\"FMTu64\n\t\t\t\t    \" %12\"FMTu64\" %12\"FMTu64\" %12\"FMTu64\"\\n\",\n\t\t\t\t    reg_size, j, curregs * reg_size, nmalloc,\n\t\t\t\t    ndalloc, nrequests, curregs, curruns, nregs,\n\t\t\t\t    run_size / page, util, nfills, nflushes,\n\t\t\t\t    nruns, reruns);\n\t\t\t} else {\n\t\t\t\tmalloc_cprintf(write_cb, cbopaque,\n\t\t\t\t    \"%20zu %3u %12zu %12\"FMTu64\n\t\t\t\t    \" %12\"FMTu64\" %12\"FMTu64\" %12zu\"\n\t\t\t\t    \" %12zu %4u %3zu %-5s %12\"FMTu64\n\t\t\t\t    \" %12\"FMTu64\"\\n\",\n\t\t\t\t    reg_size, j, curregs * reg_size, nmalloc,\n\t\t\t\t    ndalloc, nrequests, curregs, curruns, nregs,\n\t\t\t\t    run_size / page, util, nruns, reruns);\n\t\t\t}\n\t\t}\n\t}\n\tif (in_gap) {\n\t\tmalloc_cprintf(write_cb, cbopaque,\n\t\t    \"                     ---\\n\");\n\t}\n}\n\nstatic void\nstats_arena_lruns_print(void (*write_cb)(void *, const char *), void *cbopaque,\n    unsigned i)\n{\n\tunsigned nbins, nlruns, j;\n\tbool in_gap;\n\n\tmalloc_cprintf(write_cb, cbopaque,\n\t    \"large:          size ind    allocated      nmalloc      ndalloc\"\n\t    \"    nrequests      curruns\\n\");\n\tCTL_GET(\"arenas.nbins\", &nbins, unsigned);\n\tCTL_GET(\"arenas.nlruns\", &nlruns, unsigned);\n\tfor (j = 0, in_gap = false; j < nlruns; j++) {\n\t\tuint64_t nmalloc, ndalloc, nrequests;\n\t\tsize_t run_size, curruns;\n\n\t\tCTL_M2_M4_GET(\"stats.arenas.0.lruns.0.nmalloc\", i, j, &nmalloc,\n\t\t    uint64_t);\n\t\tCTL_M2_M4_GET(\"stats.arenas.0.lruns.0.ndalloc\", i, j, &ndalloc,\n\t\t    uint64_t);\n\t\tCTL_M2_M4_GET(\"stats.arenas.0.lruns.0.nrequests\", i, j,\n\t\t    &nrequests, uint64_t);\n\t\tif (nrequests == 0)\n\t\t\tin_gap = true;\n\t\telse {\n\t\t\tCTL_M2_GET(\"arenas.lrun.0.size\", j, &run_size, size_t);\n\t\t\tCTL_M2_M4_GET(\"stats.arenas.0.lruns.0.curruns\", i, j,\n\t\t\t    &curruns, size_t);\n\t\t\tif (in_gap) {\n\t\t\t\tmalloc_cprintf(write_cb, cbopaque,\n\t\t\t\t    \"                     ---\\n\");\n\t\t\t\tin_gap = false;\n\t\t\t}\n\t\t\tmalloc_cprintf(write_cb, cbopaque,\n\t\t\t    \"%20zu %3u %12zu %12\"FMTu64\" %12\"FMTu64\n\t\t\t    \" %12\"FMTu64\" %12zu\\n\",\n\t\t\t    run_size, nbins + j, curruns * run_size, nmalloc,\n\t\t\t    ndalloc, nrequests, curruns);\n\t\t}\n\t}\n\tif (in_gap) {\n\t\tmalloc_cprintf(write_cb, cbopaque,\n\t\t    \"                     ---\\n\");\n\t}\n}\n\nstatic void\nstats_arena_hchunks_print(void (*write_cb)(void *, const char *),\n    void *cbopaque, unsigned i)\n{\n\tunsigned nbins, nlruns, nhchunks, j;\n\tbool in_gap;\n\n\tmalloc_cprintf(write_cb, cbopaque,\n\t    \"huge:           size ind    allocated      nmalloc      ndalloc\"\n\t    \"    nrequests   curhchunks\\n\");\n\tCTL_GET(\"arenas.nbins\", &nbins, unsigned);\n\tCTL_GET(\"arenas.nlruns\", &nlruns, unsigned);\n\tCTL_GET(\"arenas.nhchunks\", &nhchunks, unsigned);\n\tfor (j = 0, in_gap = false; j < nhchunks; j++) {\n\t\tuint64_t nmalloc, ndalloc, nrequests;\n\t\tsize_t hchunk_size, curhchunks;\n\n\t\tCTL_M2_M4_GET(\"stats.arenas.0.hchunks.0.nmalloc\", i, j,\n\t\t    &nmalloc, uint64_t);\n\t\tCTL_M2_M4_GET(\"stats.arenas.0.hchunks.0.ndalloc\", i, j,\n\t\t    &ndalloc, uint64_t);\n\t\tCTL_M2_M4_GET(\"stats.arenas.0.hchunks.0.nrequests\", i, j,\n\t\t    &nrequests, uint64_t);\n\t\tif (nrequests == 0)\n\t\t\tin_gap = true;\n\t\telse {\n\t\t\tCTL_M2_GET(\"arenas.hchunk.0.size\", j, &hchunk_size,\n\t\t\t    size_t);\n\t\t\tCTL_M2_M4_GET(\"stats.arenas.0.hchunks.0.curhchunks\", i,\n\t\t\t    j, &curhchunks, size_t);\n\t\t\tif (in_gap) {\n\t\t\t\tmalloc_cprintf(write_cb, cbopaque,\n\t\t\t\t    \"                     ---\\n\");\n\t\t\t\tin_gap = false;\n\t\t\t}\n\t\t\tmalloc_cprintf(write_cb, cbopaque,\n\t\t\t    \"%20zu %3u %12zu %12\"FMTu64\" %12\"FMTu64\n\t\t\t    \" %12\"FMTu64\" %12zu\\n\",\n\t\t\t    hchunk_size, nbins + nlruns + j,\n\t\t\t    curhchunks * hchunk_size, nmalloc, ndalloc,\n\t\t\t    nrequests, curhchunks);\n\t\t}\n\t}\n\tif (in_gap) {\n\t\tmalloc_cprintf(write_cb, cbopaque,\n\t\t    \"                     ---\\n\");\n\t}\n}\n\nstatic void\nstats_arena_print(void (*write_cb)(void *, const char *), void *cbopaque,\n    unsigned i, bool bins, bool large, bool huge)\n{\n\tunsigned nthreads;\n\tconst char *dss;\n\tssize_t lg_dirty_mult, decay_time;\n\tsize_t page, pactive, pdirty, mapped, retained;\n\tsize_t metadata_mapped, metadata_allocated;\n\tuint64_t npurge, nmadvise, purged;\n\tsize_t small_allocated;\n\tuint64_t small_nmalloc, small_ndalloc, small_nrequests;\n\tsize_t large_allocated;\n\tuint64_t large_nmalloc, large_ndalloc, large_nrequests;\n\tsize_t huge_allocated;\n\tuint64_t huge_nmalloc, huge_ndalloc, huge_nrequests;\n\n\tCTL_GET(\"arenas.page\", &page, size_t);\n\n\tCTL_M2_GET(\"stats.arenas.0.nthreads\", i, &nthreads, unsigned);\n\tmalloc_cprintf(write_cb, cbopaque,\n\t    \"assigned threads: %u\\n\", nthreads);\n\tCTL_M2_GET(\"stats.arenas.0.dss\", i, &dss, const char *);\n\tmalloc_cprintf(write_cb, cbopaque, \"dss allocation precedence: %s\\n\",\n\t    dss);\n\tCTL_M2_GET(\"stats.arenas.0.lg_dirty_mult\", i, &lg_dirty_mult, ssize_t);\n\tif (opt_purge == purge_mode_ratio) {\n\t\tif (lg_dirty_mult >= 0) {\n\t\t\tmalloc_cprintf(write_cb, cbopaque,\n\t\t\t    \"min active:dirty page ratio: %u:1\\n\",\n\t\t\t    (1U << lg_dirty_mult));\n\t\t} else {\n\t\t\tmalloc_cprintf(write_cb, cbopaque,\n\t\t\t    \"min active:dirty page ratio: N/A\\n\");\n\t\t}\n\t}\n\tCTL_M2_GET(\"stats.arenas.0.decay_time\", i, &decay_time, ssize_t);\n\tif (opt_purge == purge_mode_decay) {\n\t\tif (decay_time >= 0) {\n\t\t\tmalloc_cprintf(write_cb, cbopaque, \"decay time: %zd\\n\",\n\t\t\t    decay_time);\n\t\t} else\n\t\t\tmalloc_cprintf(write_cb, cbopaque, \"decay time: N/A\\n\");\n\t}\n\tCTL_M2_GET(\"stats.arenas.0.pactive\", i, &pactive, size_t);\n\tCTL_M2_GET(\"stats.arenas.0.pdirty\", i, &pdirty, size_t);\n\tCTL_M2_GET(\"stats.arenas.0.npurge\", i, &npurge, uint64_t);\n\tCTL_M2_GET(\"stats.arenas.0.nmadvise\", i, &nmadvise, uint64_t);\n\tCTL_M2_GET(\"stats.arenas.0.purged\", i, &purged, uint64_t);\n\tmalloc_cprintf(write_cb, cbopaque,\n\t    \"purging: dirty: %zu, sweeps: %\"FMTu64\", madvises: %\"FMTu64\", \"\n\t    \"purged: %\"FMTu64\"\\n\", pdirty, npurge, nmadvise, purged);\n\n\tmalloc_cprintf(write_cb, cbopaque,\n\t    \"                            allocated      nmalloc      ndalloc\"\n\t    \"    nrequests\\n\");\n\tCTL_M2_GET(\"stats.arenas.0.small.allocated\", i, &small_allocated,\n\t    size_t);\n\tCTL_M2_GET(\"stats.arenas.0.small.nmalloc\", i, &small_nmalloc, uint64_t);\n\tCTL_M2_GET(\"stats.arenas.0.small.ndalloc\", i, &small_ndalloc, uint64_t);\n\tCTL_M2_GET(\"stats.arenas.0.small.nrequests\", i, &small_nrequests,\n\t    uint64_t);\n\tmalloc_cprintf(write_cb, cbopaque,\n\t    \"small:                   %12zu %12\"FMTu64\" %12\"FMTu64\n\t    \" %12\"FMTu64\"\\n\",\n\t    small_allocated, small_nmalloc, small_ndalloc, small_nrequests);\n\tCTL_M2_GET(\"stats.arenas.0.large.allocated\", i, &large_allocated,\n\t    size_t);\n\tCTL_M2_GET(\"stats.arenas.0.large.nmalloc\", i, &large_nmalloc, uint64_t);\n\tCTL_M2_GET(\"stats.arenas.0.large.ndalloc\", i, &large_ndalloc, uint64_t);\n\tCTL_M2_GET(\"stats.arenas.0.large.nrequests\", i, &large_nrequests,\n\t    uint64_t);\n\tmalloc_cprintf(write_cb, cbopaque,\n\t    \"large:                   %12zu %12\"FMTu64\" %12\"FMTu64\n\t    \" %12\"FMTu64\"\\n\",\n\t    large_allocated, large_nmalloc, large_ndalloc, large_nrequests);\n\tCTL_M2_GET(\"stats.arenas.0.huge.allocated\", i, &huge_allocated, size_t);\n\tCTL_M2_GET(\"stats.arenas.0.huge.nmalloc\", i, &huge_nmalloc, uint64_t);\n\tCTL_M2_GET(\"stats.arenas.0.huge.ndalloc\", i, &huge_ndalloc, uint64_t);\n\tCTL_M2_GET(\"stats.arenas.0.huge.nrequests\", i, &huge_nrequests,\n\t    uint64_t);\n\tmalloc_cprintf(write_cb, cbopaque,\n\t    \"huge:                    %12zu %12\"FMTu64\" %12\"FMTu64\n\t    \" %12\"FMTu64\"\\n\",\n\t    huge_allocated, huge_nmalloc, huge_ndalloc, huge_nrequests);\n\tmalloc_cprintf(write_cb, cbopaque,\n\t    \"total:                   %12zu %12\"FMTu64\" %12\"FMTu64\n\t    \" %12\"FMTu64\"\\n\",\n\t    small_allocated + large_allocated + huge_allocated,\n\t    small_nmalloc + large_nmalloc + huge_nmalloc,\n\t    small_ndalloc + large_ndalloc + huge_ndalloc,\n\t    small_nrequests + large_nrequests + huge_nrequests);\n\tmalloc_cprintf(write_cb, cbopaque,\n\t    \"active:                  %12zu\\n\", pactive * page);\n\tCTL_M2_GET(\"stats.arenas.0.mapped\", i, &mapped, size_t);\n\tmalloc_cprintf(write_cb, cbopaque,\n\t    \"mapped:                  %12zu\\n\", mapped);\n\tCTL_M2_GET(\"stats.arenas.0.retained\", i, &retained, size_t);\n\tmalloc_cprintf(write_cb, cbopaque,\n\t    \"retained:                %12zu\\n\", retained);\n\tCTL_M2_GET(\"stats.arenas.0.metadata.mapped\", i, &metadata_mapped,\n\t    size_t);\n\tCTL_M2_GET(\"stats.arenas.0.metadata.allocated\", i, &metadata_allocated,\n\t    size_t);\n\tmalloc_cprintf(write_cb, cbopaque,\n\t    \"metadata: mapped: %zu, allocated: %zu\\n\",\n\t    metadata_mapped, metadata_allocated);\n\n\tif (bins)\n\t\tstats_arena_bins_print(write_cb, cbopaque, i);\n\tif (large)\n\t\tstats_arena_lruns_print(write_cb, cbopaque, i);\n\tif (huge)\n\t\tstats_arena_hchunks_print(write_cb, cbopaque, i);\n}\n\nvoid\nstats_print(void (*write_cb)(void *, const char *), void *cbopaque,\n    const char *opts)\n{\n\tint err;\n\tuint64_t epoch;\n\tsize_t u64sz;\n\tbool general = true;\n\tbool merged = true;\n\tbool unmerged = true;\n\tbool bins = true;\n\tbool large = true;\n\tbool huge = true;\n\n\t/*\n\t * Refresh stats, in case mallctl() was called by the application.\n\t *\n\t * Check for OOM here, since refreshing the ctl cache can trigger\n\t * allocation.  In practice, none of the subsequent mallctl()-related\n\t * calls in this function will cause OOM if this one succeeds.\n\t * */\n\tepoch = 1;\n\tu64sz = sizeof(uint64_t);\n\terr = je_mallctl(\"epoch\", &epoch, &u64sz, &epoch, sizeof(uint64_t));\n\tif (err != 0) {\n\t\tif (err == EAGAIN) {\n\t\t\tmalloc_write(\"<jemalloc>: Memory allocation failure in \"\n\t\t\t    \"mallctl(\\\"epoch\\\", ...)\\n\");\n\t\t\treturn;\n\t\t}\n\t\tmalloc_write(\"<jemalloc>: Failure in mallctl(\\\"epoch\\\", \"\n\t\t    \"...)\\n\");\n\t\tabort();\n\t}\n\n\tif (opts != NULL) {\n\t\tunsigned i;\n\n\t\tfor (i = 0; opts[i] != '\\0'; i++) {\n\t\t\tswitch (opts[i]) {\n\t\t\tcase 'g':\n\t\t\t\tgeneral = false;\n\t\t\t\tbreak;\n\t\t\tcase 'm':\n\t\t\t\tmerged = false;\n\t\t\t\tbreak;\n\t\t\tcase 'a':\n\t\t\t\tunmerged = false;\n\t\t\t\tbreak;\n\t\t\tcase 'b':\n\t\t\t\tbins = false;\n\t\t\t\tbreak;\n\t\t\tcase 'l':\n\t\t\t\tlarge = false;\n\t\t\t\tbreak;\n\t\t\tcase 'h':\n\t\t\t\thuge = false;\n\t\t\t\tbreak;\n\t\t\tdefault:;\n\t\t\t}\n\t\t}\n\t}\n\n\tmalloc_cprintf(write_cb, cbopaque,\n\t    \"___ Begin jemalloc statistics ___\\n\");\n\tif (general) {\n\t\tconst char *cpv;\n\t\tbool bv;\n\t\tunsigned uv;\n\t\tssize_t ssv;\n\t\tsize_t sv, bsz, usz, ssz, sssz, cpsz;\n\n\t\tbsz = sizeof(bool);\n\t\tusz = sizeof(unsigned);\n\t\tssz = sizeof(size_t);\n\t\tsssz = sizeof(ssize_t);\n\t\tcpsz = sizeof(const char *);\n\n\t\tCTL_GET(\"version\", &cpv, const char *);\n\t\tmalloc_cprintf(write_cb, cbopaque, \"Version: %s\\n\", cpv);\n\t\tCTL_GET(\"config.debug\", &bv, bool);\n\t\tmalloc_cprintf(write_cb, cbopaque, \"Assertions %s\\n\",\n\t\t    bv ? \"enabled\" : \"disabled\");\n\t\tmalloc_cprintf(write_cb, cbopaque,\n\t\t    \"config.malloc_conf: \\\"%s\\\"\\n\", config_malloc_conf);\n\n#define\tOPT_WRITE_BOOL(n)\t\t\t\t\t\t\\\n\t\tif (je_mallctl(\"opt.\"#n, &bv, &bsz, NULL, 0) == 0) {\t\\\n\t\t\tmalloc_cprintf(write_cb, cbopaque,\t\t\\\n\t\t\t    \"  opt.\"#n\": %s\\n\", bv ? \"true\" : \"false\");\t\\\n\t\t}\n#define\tOPT_WRITE_BOOL_MUTABLE(n, m) {\t\t\t\t\t\\\n\t\tbool bv2;\t\t\t\t\t\t\\\n\t\tif (je_mallctl(\"opt.\"#n, &bv, &bsz, NULL, 0) == 0 &&\t\\\n\t\t    je_mallctl(#m, &bv2, &bsz, NULL, 0) == 0) {\t\t\\\n\t\t\tmalloc_cprintf(write_cb, cbopaque,\t\t\\\n\t\t\t    \"  opt.\"#n\": %s (\"#m\": %s)\\n\", bv ? \"true\"\t\\\n\t\t\t    : \"false\", bv2 ? \"true\" : \"false\");\t\t\\\n\t\t}\t\t\t\t\t\t\t\\\n}\n#define\tOPT_WRITE_UNSIGNED(n)\t\t\t\t\t\t\\\n\t\tif (je_mallctl(\"opt.\"#n, &uv, &usz, NULL, 0) == 0) {\t\\\n\t\t\tmalloc_cprintf(write_cb, cbopaque,\t\t\\\n\t\t\t\"  opt.\"#n\": %u\\n\", uv);\t\t\t\\\n\t\t}\n#define\tOPT_WRITE_SIZE_T(n)\t\t\t\t\t\t\\\n\t\tif (je_mallctl(\"opt.\"#n, &sv, &ssz, NULL, 0) == 0) {\t\\\n\t\t\tmalloc_cprintf(write_cb, cbopaque,\t\t\\\n\t\t\t\"  opt.\"#n\": %zu\\n\", sv);\t\t\t\\\n\t\t}\n#define\tOPT_WRITE_SSIZE_T(n)\t\t\t\t\t\t\\\n\t\tif (je_mallctl(\"opt.\"#n, &ssv, &sssz, NULL, 0) == 0) {\t\\\n\t\t\tmalloc_cprintf(write_cb, cbopaque,\t\t\\\n\t\t\t    \"  opt.\"#n\": %zd\\n\", ssv);\t\t\t\\\n\t\t}\n#define\tOPT_WRITE_SSIZE_T_MUTABLE(n, m) {\t\t\t\t\\\n\t\tssize_t ssv2;\t\t\t\t\t\t\\\n\t\tif (je_mallctl(\"opt.\"#n, &ssv, &sssz, NULL, 0) == 0 &&\t\\\n\t\t    je_mallctl(#m, &ssv2, &sssz, NULL, 0) == 0) {\t\\\n\t\t\tmalloc_cprintf(write_cb, cbopaque,\t\t\\\n\t\t\t    \"  opt.\"#n\": %zd (\"#m\": %zd)\\n\",\t\t\\\n\t\t\t    ssv, ssv2);\t\t\t\t\t\\\n\t\t}\t\t\t\t\t\t\t\\\n}\n#define\tOPT_WRITE_CHAR_P(n)\t\t\t\t\t\t\\\n\t\tif (je_mallctl(\"opt.\"#n, &cpv, &cpsz, NULL, 0) == 0) {\t\\\n\t\t\tmalloc_cprintf(write_cb, cbopaque,\t\t\\\n\t\t\t    \"  opt.\"#n\": \\\"%s\\\"\\n\", cpv);\t\t\\\n\t\t}\n\n\t\tmalloc_cprintf(write_cb, cbopaque,\n\t\t    \"Run-time option settings:\\n\");\n\t\tOPT_WRITE_BOOL(abort)\n\t\tOPT_WRITE_SIZE_T(lg_chunk)\n\t\tOPT_WRITE_CHAR_P(dss)\n\t\tOPT_WRITE_UNSIGNED(narenas)\n\t\tOPT_WRITE_CHAR_P(purge)\n\t\tif (opt_purge == purge_mode_ratio) {\n\t\t\tOPT_WRITE_SSIZE_T_MUTABLE(lg_dirty_mult,\n\t\t\t    arenas.lg_dirty_mult)\n\t\t}\n\t\tif (opt_purge == purge_mode_decay)\n\t\t\tOPT_WRITE_SSIZE_T_MUTABLE(decay_time, arenas.decay_time)\n\t\tOPT_WRITE_BOOL(stats_print)\n\t\tOPT_WRITE_CHAR_P(junk)\n\t\tOPT_WRITE_SIZE_T(quarantine)\n\t\tOPT_WRITE_BOOL(redzone)\n\t\tOPT_WRITE_BOOL(zero)\n\t\tOPT_WRITE_BOOL(utrace)\n\t\tOPT_WRITE_BOOL(valgrind)\n\t\tOPT_WRITE_BOOL(xmalloc)\n\t\tOPT_WRITE_BOOL(tcache)\n\t\tOPT_WRITE_SSIZE_T(lg_tcache_max)\n\t\tOPT_WRITE_BOOL(prof)\n\t\tOPT_WRITE_CHAR_P(prof_prefix)\n\t\tOPT_WRITE_BOOL_MUTABLE(prof_active, prof.active)\n\t\tOPT_WRITE_BOOL_MUTABLE(prof_thread_active_init,\n\t\t    prof.thread_active_init)\n\t\tOPT_WRITE_SSIZE_T(lg_prof_sample)\n\t\tOPT_WRITE_BOOL(prof_accum)\n\t\tOPT_WRITE_SSIZE_T(lg_prof_interval)\n\t\tOPT_WRITE_BOOL(prof_gdump)\n\t\tOPT_WRITE_BOOL(prof_final)\n\t\tOPT_WRITE_BOOL(prof_leak)\n\n#undef OPT_WRITE_BOOL\n#undef OPT_WRITE_BOOL_MUTABLE\n#undef OPT_WRITE_SIZE_T\n#undef OPT_WRITE_SSIZE_T\n#undef OPT_WRITE_CHAR_P\n\n\t\tmalloc_cprintf(write_cb, cbopaque, \"CPUs: %u\\n\", ncpus);\n\n\t\tCTL_GET(\"arenas.narenas\", &uv, unsigned);\n\t\tmalloc_cprintf(write_cb, cbopaque, \"Arenas: %u\\n\", uv);\n\n\t\tmalloc_cprintf(write_cb, cbopaque, \"Pointer size: %zu\\n\",\n\t\t    sizeof(void *));\n\n\t\tCTL_GET(\"arenas.quantum\", &sv, size_t);\n\t\tmalloc_cprintf(write_cb, cbopaque, \"Quantum size: %zu\\n\",\n\t\t    sv);\n\n\t\tCTL_GET(\"arenas.page\", &sv, size_t);\n\t\tmalloc_cprintf(write_cb, cbopaque, \"Page size: %zu\\n\", sv);\n\n\t\tCTL_GET(\"arenas.lg_dirty_mult\", &ssv, ssize_t);\n\t\tif (opt_purge == purge_mode_ratio) {\n\t\t\tif (ssv >= 0) {\n\t\t\t\tmalloc_cprintf(write_cb, cbopaque,\n\t\t\t\t    \"Min active:dirty page ratio per arena: \"\n\t\t\t\t    \"%u:1\\n\", (1U << ssv));\n\t\t\t} else {\n\t\t\t\tmalloc_cprintf(write_cb, cbopaque,\n\t\t\t\t    \"Min active:dirty page ratio per arena: \"\n\t\t\t\t    \"N/A\\n\");\n\t\t\t}\n\t\t}\n\t\tCTL_GET(\"arenas.decay_time\", &ssv, ssize_t);\n\t\tif (opt_purge == purge_mode_decay) {\n\t\t\tmalloc_cprintf(write_cb, cbopaque,\n\t\t\t    \"Unused dirty page decay time: %zd%s\\n\",\n\t\t\t    ssv, (ssv < 0) ? \" (no decay)\" : \"\");\n\t\t}\n\t\tif (je_mallctl(\"arenas.tcache_max\", &sv, &ssz, NULL, 0) == 0) {\n\t\t\tmalloc_cprintf(write_cb, cbopaque,\n\t\t\t    \"Maximum thread-cached size class: %zu\\n\", sv);\n\t\t}\n\t\tif (je_mallctl(\"opt.prof\", &bv, &bsz, NULL, 0) == 0 && bv) {\n\t\t\tCTL_GET(\"prof.lg_sample\", &sv, size_t);\n\t\t\tmalloc_cprintf(write_cb, cbopaque,\n\t\t\t    \"Average profile sample interval: %\"FMTu64\n\t\t\t    \" (2^%zu)\\n\", (((uint64_t)1U) << sv), sv);\n\n\t\t\tCTL_GET(\"opt.lg_prof_interval\", &ssv, ssize_t);\n\t\t\tif (ssv >= 0) {\n\t\t\t\tmalloc_cprintf(write_cb, cbopaque,\n\t\t\t\t    \"Average profile dump interval: %\"FMTu64\n\t\t\t\t    \" (2^%zd)\\n\",\n\t\t\t\t    (((uint64_t)1U) << ssv), ssv);\n\t\t\t} else {\n\t\t\t\tmalloc_cprintf(write_cb, cbopaque,\n\t\t\t\t    \"Average profile dump interval: N/A\\n\");\n\t\t\t}\n\t\t}\n\t\tCTL_GET(\"opt.lg_chunk\", &sv, size_t);\n\t\tmalloc_cprintf(write_cb, cbopaque,\n\t\t    \"Chunk size: %zu (2^%zu)\\n\", (ZU(1) << sv), sv);\n\t}\n\n\tif (config_stats) {\n\t\tsize_t *cactive;\n\t\tsize_t allocated, active, metadata, resident, mapped, retained;\n\n\t\tCTL_GET(\"stats.cactive\", &cactive, size_t *);\n\t\tCTL_GET(\"stats.allocated\", &allocated, size_t);\n\t\tCTL_GET(\"stats.active\", &active, size_t);\n\t\tCTL_GET(\"stats.metadata\", &metadata, size_t);\n\t\tCTL_GET(\"stats.resident\", &resident, size_t);\n\t\tCTL_GET(\"stats.mapped\", &mapped, size_t);\n\t\tCTL_GET(\"stats.retained\", &retained, size_t);\n\t\tmalloc_cprintf(write_cb, cbopaque,\n\t\t    \"Allocated: %zu, active: %zu, metadata: %zu,\"\n\t\t    \" resident: %zu, mapped: %zu, retained: %zu\\n\",\n\t\t    allocated, active, metadata, resident, mapped, retained);\n\t\tmalloc_cprintf(write_cb, cbopaque,\n\t\t    \"Current active ceiling: %zu\\n\",\n\t\t    atomic_read_z(cactive));\n\n\t\tif (merged) {\n\t\t\tunsigned narenas;\n\n\t\t\tCTL_GET(\"arenas.narenas\", &narenas, unsigned);\n\t\t\t{\n\t\t\t\tVARIABLE_ARRAY(bool, initialized, narenas);\n\t\t\t\tsize_t isz;\n\t\t\t\tunsigned i, ninitialized;\n\n\t\t\t\tisz = sizeof(bool) * narenas;\n\t\t\t\txmallctl(\"arenas.initialized\", initialized,\n\t\t\t\t    &isz, NULL, 0);\n\t\t\t\tfor (i = ninitialized = 0; i < narenas; i++) {\n\t\t\t\t\tif (initialized[i])\n\t\t\t\t\t\tninitialized++;\n\t\t\t\t}\n\n\t\t\t\tif (ninitialized > 1 || !unmerged) {\n\t\t\t\t\t/* Print merged arena stats. */\n\t\t\t\t\tmalloc_cprintf(write_cb, cbopaque,\n\t\t\t\t\t    \"\\nMerged arenas stats:\\n\");\n\t\t\t\t\tstats_arena_print(write_cb, cbopaque,\n\t\t\t\t\t    narenas, bins, large, huge);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tif (unmerged) {\n\t\t\tunsigned narenas;\n\n\t\t\t/* Print stats for each arena. */\n\n\t\t\tCTL_GET(\"arenas.narenas\", &narenas, unsigned);\n\t\t\t{\n\t\t\t\tVARIABLE_ARRAY(bool, initialized, narenas);\n\t\t\t\tsize_t isz;\n\t\t\t\tunsigned i;\n\n\t\t\t\tisz = sizeof(bool) * narenas;\n\t\t\t\txmallctl(\"arenas.initialized\", initialized,\n\t\t\t\t    &isz, NULL, 0);\n\n\t\t\t\tfor (i = 0; i < narenas; i++) {\n\t\t\t\t\tif (initialized[i]) {\n\t\t\t\t\t\tmalloc_cprintf(write_cb,\n\t\t\t\t\t\t    cbopaque,\n\t\t\t\t\t\t    \"\\narenas[%u]:\\n\", i);\n\t\t\t\t\t\tstats_arena_print(write_cb,\n\t\t\t\t\t\t    cbopaque, i, bins, large,\n\t\t\t\t\t\t    huge);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\tmalloc_cprintf(write_cb, cbopaque, \"--- End jemalloc statistics ---\\n\");\n}\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/deps/jemalloc/src/tcache.c",
    "content": "#define\tJEMALLOC_TCACHE_C_\n#include \"jemalloc/internal/jemalloc_internal.h\"\n\n/******************************************************************************/\n/* Data. */\n\nbool\topt_tcache = true;\nssize_t\topt_lg_tcache_max = LG_TCACHE_MAXCLASS_DEFAULT;\n\ntcache_bin_info_t\t*tcache_bin_info;\nstatic unsigned\t\tstack_nelms; /* Total stack elms per tcache. */\n\nunsigned\t\tnhbins;\nsize_t\t\t\ttcache_maxclass;\n\ntcaches_t\t\t*tcaches;\n\n/* Index of first element within tcaches that has never been used. */\nstatic unsigned\t\ttcaches_past;\n\n/* Head of singly linked list tracking available tcaches elements. */\nstatic tcaches_t\t*tcaches_avail;\n\n/******************************************************************************/\n\nsize_t\ntcache_salloc(tsdn_t *tsdn, const void *ptr)\n{\n\n\treturn (arena_salloc(tsdn, ptr, false));\n}\n\nvoid\ntcache_event_hard(tsd_t *tsd, tcache_t *tcache)\n{\n\tszind_t binind = tcache->next_gc_bin;\n\ttcache_bin_t *tbin = &tcache->tbins[binind];\n\ttcache_bin_info_t *tbin_info = &tcache_bin_info[binind];\n\n\tif (tbin->low_water > 0) {\n\t\t/*\n\t\t * Flush (ceiling) 3/4 of the objects below the low water mark.\n\t\t */\n\t\tif (binind < NBINS) {\n\t\t\ttcache_bin_flush_small(tsd, tcache, tbin, binind,\n\t\t\t    tbin->ncached - tbin->low_water + (tbin->low_water\n\t\t\t    >> 2));\n\t\t} else {\n\t\t\ttcache_bin_flush_large(tsd, tbin, binind, tbin->ncached\n\t\t\t    - tbin->low_water + (tbin->low_water >> 2), tcache);\n\t\t}\n\t\t/*\n\t\t * Reduce fill count by 2X.  Limit lg_fill_div such that the\n\t\t * fill count is always at least 1.\n\t\t */\n\t\tif ((tbin_info->ncached_max >> (tbin->lg_fill_div+1)) >= 1)\n\t\t\ttbin->lg_fill_div++;\n\t} else if (tbin->low_water < 0) {\n\t\t/*\n\t\t * Increase fill count by 2X.  Make sure lg_fill_div stays\n\t\t * greater than 0.\n\t\t */\n\t\tif (tbin->lg_fill_div > 1)\n\t\t\ttbin->lg_fill_div--;\n\t}\n\ttbin->low_water = tbin->ncached;\n\n\ttcache->next_gc_bin++;\n\tif (tcache->next_gc_bin == nhbins)\n\t\ttcache->next_gc_bin = 0;\n}\n\nvoid *\ntcache_alloc_small_hard(tsdn_t *tsdn, arena_t *arena, tcache_t *tcache,\n    tcache_bin_t *tbin, szind_t binind, bool *tcache_success)\n{\n\tvoid *ret;\n\n\tarena_tcache_fill_small(tsdn, arena, tbin, binind, config_prof ?\n\t    tcache->prof_accumbytes : 0);\n\tif (config_prof)\n\t\ttcache->prof_accumbytes = 0;\n\tret = tcache_alloc_easy(tbin, tcache_success);\n\n\treturn (ret);\n}\n\nvoid\ntcache_bin_flush_small(tsd_t *tsd, tcache_t *tcache, tcache_bin_t *tbin,\n    szind_t binind, unsigned rem)\n{\n\tarena_t *arena;\n\tvoid *ptr;\n\tunsigned i, nflush, ndeferred;\n\tbool merged_stats = false;\n\n\tassert(binind < NBINS);\n\tassert(rem <= tbin->ncached);\n\n\tarena = arena_choose(tsd, NULL);\n\tassert(arena != NULL);\n\tfor (nflush = tbin->ncached - rem; nflush > 0; nflush = ndeferred) {\n\t\t/* Lock the arena bin associated with the first object. */\n\t\tarena_chunk_t *chunk = (arena_chunk_t *)CHUNK_ADDR2BASE(\n\t\t    *(tbin->avail - 1));\n\t\tarena_t *bin_arena = extent_node_arena_get(&chunk->node);\n\t\tarena_bin_t *bin = &bin_arena->bins[binind];\n\n\t\tif (config_prof && bin_arena == arena) {\n\t\t\tif (arena_prof_accum(tsd_tsdn(tsd), arena,\n\t\t\t    tcache->prof_accumbytes))\n\t\t\t\tprof_idump(tsd_tsdn(tsd));\n\t\t\ttcache->prof_accumbytes = 0;\n\t\t}\n\n\t\tmalloc_mutex_lock(tsd_tsdn(tsd), &bin->lock);\n\t\tif (config_stats && bin_arena == arena) {\n\t\t\tassert(!merged_stats);\n\t\t\tmerged_stats = true;\n\t\t\tbin->stats.nflushes++;\n\t\t\tbin->stats.nrequests += tbin->tstats.nrequests;\n\t\t\ttbin->tstats.nrequests = 0;\n\t\t}\n\t\tndeferred = 0;\n\t\tfor (i = 0; i < nflush; i++) {\n\t\t\tptr = *(tbin->avail - 1 - i);\n\t\t\tassert(ptr != NULL);\n\t\t\tchunk = (arena_chunk_t *)CHUNK_ADDR2BASE(ptr);\n\t\t\tif (extent_node_arena_get(&chunk->node) == bin_arena) {\n\t\t\t\tsize_t pageind = ((uintptr_t)ptr -\n\t\t\t\t    (uintptr_t)chunk) >> LG_PAGE;\n\t\t\t\tarena_chunk_map_bits_t *bitselm =\n\t\t\t\t    arena_bitselm_get_mutable(chunk, pageind);\n\t\t\t\tarena_dalloc_bin_junked_locked(tsd_tsdn(tsd),\n\t\t\t\t    bin_arena, chunk, ptr, bitselm);\n\t\t\t} else {\n\t\t\t\t/*\n\t\t\t\t * This object was allocated via a different\n\t\t\t\t * arena bin than the one that is currently\n\t\t\t\t * locked.  Stash the object, so that it can be\n\t\t\t\t * handled in a future pass.\n\t\t\t\t */\n\t\t\t\t*(tbin->avail - 1 - ndeferred) = ptr;\n\t\t\t\tndeferred++;\n\t\t\t}\n\t\t}\n\t\tmalloc_mutex_unlock(tsd_tsdn(tsd), &bin->lock);\n\t\tarena_decay_ticks(tsd_tsdn(tsd), bin_arena, nflush - ndeferred);\n\t}\n\tif (config_stats && !merged_stats) {\n\t\t/*\n\t\t * The flush loop didn't happen to flush to this thread's\n\t\t * arena, so the stats didn't get merged.  Manually do so now.\n\t\t */\n\t\tarena_bin_t *bin = &arena->bins[binind];\n\t\tmalloc_mutex_lock(tsd_tsdn(tsd), &bin->lock);\n\t\tbin->stats.nflushes++;\n\t\tbin->stats.nrequests += tbin->tstats.nrequests;\n\t\ttbin->tstats.nrequests = 0;\n\t\tmalloc_mutex_unlock(tsd_tsdn(tsd), &bin->lock);\n\t}\n\n\tmemmove(tbin->avail - rem, tbin->avail - tbin->ncached, rem *\n\t    sizeof(void *));\n\ttbin->ncached = rem;\n\tif ((int)tbin->ncached < tbin->low_water)\n\t\ttbin->low_water = tbin->ncached;\n}\n\nvoid\ntcache_bin_flush_large(tsd_t *tsd, tcache_bin_t *tbin, szind_t binind,\n    unsigned rem, tcache_t *tcache)\n{\n\tarena_t *arena;\n\tvoid *ptr;\n\tunsigned i, nflush, ndeferred;\n\tbool merged_stats = false;\n\n\tassert(binind < nhbins);\n\tassert(rem <= tbin->ncached);\n\n\tarena = arena_choose(tsd, NULL);\n\tassert(arena != NULL);\n\tfor (nflush = tbin->ncached - rem; nflush > 0; nflush = ndeferred) {\n\t\t/* Lock the arena associated with the first object. */\n\t\tarena_chunk_t *chunk = (arena_chunk_t *)CHUNK_ADDR2BASE(\n\t\t    *(tbin->avail - 1));\n\t\tarena_t *locked_arena = extent_node_arena_get(&chunk->node);\n\t\tUNUSED bool idump;\n\n\t\tif (config_prof)\n\t\t\tidump = false;\n\t\tmalloc_mutex_lock(tsd_tsdn(tsd), &locked_arena->lock);\n\t\tif ((config_prof || config_stats) && locked_arena == arena) {\n\t\t\tif (config_prof) {\n\t\t\t\tidump = arena_prof_accum_locked(arena,\n\t\t\t\t    tcache->prof_accumbytes);\n\t\t\t\ttcache->prof_accumbytes = 0;\n\t\t\t}\n\t\t\tif (config_stats) {\n\t\t\t\tmerged_stats = true;\n\t\t\t\tarena->stats.nrequests_large +=\n\t\t\t\t    tbin->tstats.nrequests;\n\t\t\t\tarena->stats.lstats[binind - NBINS].nrequests +=\n\t\t\t\t    tbin->tstats.nrequests;\n\t\t\t\ttbin->tstats.nrequests = 0;\n\t\t\t}\n\t\t}\n\t\tndeferred = 0;\n\t\tfor (i = 0; i < nflush; i++) {\n\t\t\tptr = *(tbin->avail - 1 - i);\n\t\t\tassert(ptr != NULL);\n\t\t\tchunk = (arena_chunk_t *)CHUNK_ADDR2BASE(ptr);\n\t\t\tif (extent_node_arena_get(&chunk->node) ==\n\t\t\t    locked_arena) {\n\t\t\t\tarena_dalloc_large_junked_locked(tsd_tsdn(tsd),\n\t\t\t\t    locked_arena, chunk, ptr);\n\t\t\t} else {\n\t\t\t\t/*\n\t\t\t\t * This object was allocated via a different\n\t\t\t\t * arena than the one that is currently locked.\n\t\t\t\t * Stash the object, so that it can be handled\n\t\t\t\t * in a future pass.\n\t\t\t\t */\n\t\t\t\t*(tbin->avail - 1 - ndeferred) = ptr;\n\t\t\t\tndeferred++;\n\t\t\t}\n\t\t}\n\t\tmalloc_mutex_unlock(tsd_tsdn(tsd), &locked_arena->lock);\n\t\tif (config_prof && idump)\n\t\t\tprof_idump(tsd_tsdn(tsd));\n\t\tarena_decay_ticks(tsd_tsdn(tsd), locked_arena, nflush -\n\t\t    ndeferred);\n\t}\n\tif (config_stats && !merged_stats) {\n\t\t/*\n\t\t * The flush loop didn't happen to flush to this thread's\n\t\t * arena, so the stats didn't get merged.  Manually do so now.\n\t\t */\n\t\tmalloc_mutex_lock(tsd_tsdn(tsd), &arena->lock);\n\t\tarena->stats.nrequests_large += tbin->tstats.nrequests;\n\t\tarena->stats.lstats[binind - NBINS].nrequests +=\n\t\t    tbin->tstats.nrequests;\n\t\ttbin->tstats.nrequests = 0;\n\t\tmalloc_mutex_unlock(tsd_tsdn(tsd), &arena->lock);\n\t}\n\n\tmemmove(tbin->avail - rem, tbin->avail - tbin->ncached, rem *\n\t    sizeof(void *));\n\ttbin->ncached = rem;\n\tif ((int)tbin->ncached < tbin->low_water)\n\t\ttbin->low_water = tbin->ncached;\n}\n\nstatic void\ntcache_arena_associate(tsdn_t *tsdn, tcache_t *tcache, arena_t *arena)\n{\n\n\tif (config_stats) {\n\t\t/* Link into list of extant tcaches. */\n\t\tmalloc_mutex_lock(tsdn, &arena->lock);\n\t\tql_elm_new(tcache, link);\n\t\tql_tail_insert(&arena->tcache_ql, tcache, link);\n\t\tmalloc_mutex_unlock(tsdn, &arena->lock);\n\t}\n}\n\nstatic void\ntcache_arena_dissociate(tsdn_t *tsdn, tcache_t *tcache, arena_t *arena)\n{\n\n\tif (config_stats) {\n\t\t/* Unlink from list of extant tcaches. */\n\t\tmalloc_mutex_lock(tsdn, &arena->lock);\n\t\tif (config_debug) {\n\t\t\tbool in_ql = false;\n\t\t\ttcache_t *iter;\n\t\t\tql_foreach(iter, &arena->tcache_ql, link) {\n\t\t\t\tif (iter == tcache) {\n\t\t\t\t\tin_ql = true;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t\tassert(in_ql);\n\t\t}\n\t\tql_remove(&arena->tcache_ql, tcache, link);\n\t\ttcache_stats_merge(tsdn, tcache, arena);\n\t\tmalloc_mutex_unlock(tsdn, &arena->lock);\n\t}\n}\n\nvoid\ntcache_arena_reassociate(tsdn_t *tsdn, tcache_t *tcache, arena_t *oldarena,\n    arena_t *newarena)\n{\n\n\ttcache_arena_dissociate(tsdn, tcache, oldarena);\n\ttcache_arena_associate(tsdn, tcache, newarena);\n}\n\ntcache_t *\ntcache_get_hard(tsd_t *tsd)\n{\n\tarena_t *arena;\n\n\tif (!tcache_enabled_get()) {\n\t\tif (tsd_nominal(tsd))\n\t\t\ttcache_enabled_set(false); /* Memoize. */\n\t\treturn (NULL);\n\t}\n\tarena = arena_choose(tsd, NULL);\n\tif (unlikely(arena == NULL))\n\t\treturn (NULL);\n\treturn (tcache_create(tsd_tsdn(tsd), arena));\n}\n\ntcache_t *\ntcache_create(tsdn_t *tsdn, arena_t *arena)\n{\n\ttcache_t *tcache;\n\tsize_t size, stack_offset;\n\tunsigned i;\n\n\tsize = offsetof(tcache_t, tbins) + (sizeof(tcache_bin_t) * nhbins);\n\t/* Naturally align the pointer stacks. */\n\tsize = PTR_CEILING(size);\n\tstack_offset = size;\n\tsize += stack_nelms * sizeof(void *);\n\t/* Avoid false cacheline sharing. */\n\tsize = sa2u(size, CACHELINE);\n\n\ttcache = ipallocztm(tsdn, size, CACHELINE, true, NULL, true,\n\t    arena_get(TSDN_NULL, 0, true));\n\tif (tcache == NULL)\n\t\treturn (NULL);\n\n\ttcache_arena_associate(tsdn, tcache, arena);\n\n\tticker_init(&tcache->gc_ticker, TCACHE_GC_INCR);\n\n\tassert((TCACHE_NSLOTS_SMALL_MAX & 1U) == 0);\n\tfor (i = 0; i < nhbins; i++) {\n\t\ttcache->tbins[i].lg_fill_div = 1;\n\t\tstack_offset += tcache_bin_info[i].ncached_max * sizeof(void *);\n\t\t/*\n\t\t * avail points past the available space.  Allocations will\n\t\t * access the slots toward higher addresses (for the benefit of\n\t\t * prefetch).\n\t\t */\n\t\ttcache->tbins[i].avail = (void **)((uintptr_t)tcache +\n\t\t    (uintptr_t)stack_offset);\n\t}\n\n\treturn (tcache);\n}\n\nstatic void\ntcache_destroy(tsd_t *tsd, tcache_t *tcache)\n{\n\tarena_t *arena;\n\tunsigned i;\n\n\tarena = arena_choose(tsd, NULL);\n\ttcache_arena_dissociate(tsd_tsdn(tsd), tcache, arena);\n\n\tfor (i = 0; i < NBINS; i++) {\n\t\ttcache_bin_t *tbin = &tcache->tbins[i];\n\t\ttcache_bin_flush_small(tsd, tcache, tbin, i, 0);\n\n\t\tif (config_stats && tbin->tstats.nrequests != 0) {\n\t\t\tarena_bin_t *bin = &arena->bins[i];\n\t\t\tmalloc_mutex_lock(tsd_tsdn(tsd), &bin->lock);\n\t\t\tbin->stats.nrequests += tbin->tstats.nrequests;\n\t\t\tmalloc_mutex_unlock(tsd_tsdn(tsd), &bin->lock);\n\t\t}\n\t}\n\n\tfor (; i < nhbins; i++) {\n\t\ttcache_bin_t *tbin = &tcache->tbins[i];\n\t\ttcache_bin_flush_large(tsd, tbin, i, 0, tcache);\n\n\t\tif (config_stats && tbin->tstats.nrequests != 0) {\n\t\t\tmalloc_mutex_lock(tsd_tsdn(tsd), &arena->lock);\n\t\t\tarena->stats.nrequests_large += tbin->tstats.nrequests;\n\t\t\tarena->stats.lstats[i - NBINS].nrequests +=\n\t\t\t    tbin->tstats.nrequests;\n\t\t\tmalloc_mutex_unlock(tsd_tsdn(tsd), &arena->lock);\n\t\t}\n\t}\n\n\tif (config_prof && tcache->prof_accumbytes > 0 &&\n\t    arena_prof_accum(tsd_tsdn(tsd), arena, tcache->prof_accumbytes))\n\t\tprof_idump(tsd_tsdn(tsd));\n\n\tidalloctm(tsd_tsdn(tsd), tcache, NULL, true, true);\n}\n\nvoid\ntcache_cleanup(tsd_t *tsd)\n{\n\ttcache_t *tcache;\n\n\tif (!config_tcache)\n\t\treturn;\n\n\tif ((tcache = tsd_tcache_get(tsd)) != NULL) {\n\t\ttcache_destroy(tsd, tcache);\n\t\ttsd_tcache_set(tsd, NULL);\n\t}\n}\n\nvoid\ntcache_enabled_cleanup(tsd_t *tsd)\n{\n\n\t/* Do nothing. */\n}\n\nvoid\ntcache_stats_merge(tsdn_t *tsdn, tcache_t *tcache, arena_t *arena)\n{\n\tunsigned i;\n\n\tcassert(config_stats);\n\n\tmalloc_mutex_assert_owner(tsdn, &arena->lock);\n\n\t/* Merge and reset tcache stats. */\n\tfor (i = 0; i < NBINS; i++) {\n\t\tarena_bin_t *bin = &arena->bins[i];\n\t\ttcache_bin_t *tbin = &tcache->tbins[i];\n\t\tmalloc_mutex_lock(tsdn, &bin->lock);\n\t\tbin->stats.nrequests += tbin->tstats.nrequests;\n\t\tmalloc_mutex_unlock(tsdn, &bin->lock);\n\t\ttbin->tstats.nrequests = 0;\n\t}\n\n\tfor (; i < nhbins; i++) {\n\t\tmalloc_large_stats_t *lstats = &arena->stats.lstats[i - NBINS];\n\t\ttcache_bin_t *tbin = &tcache->tbins[i];\n\t\tarena->stats.nrequests_large += tbin->tstats.nrequests;\n\t\tlstats->nrequests += tbin->tstats.nrequests;\n\t\ttbin->tstats.nrequests = 0;\n\t}\n}\n\nbool\ntcaches_create(tsdn_t *tsdn, unsigned *r_ind)\n{\n\tarena_t *arena;\n\ttcache_t *tcache;\n\ttcaches_t *elm;\n\n\tif (tcaches == NULL) {\n\t\ttcaches = base_alloc(tsdn, sizeof(tcache_t *) *\n\t\t    (MALLOCX_TCACHE_MAX+1));\n\t\tif (tcaches == NULL)\n\t\t\treturn (true);\n\t}\n\n\tif (tcaches_avail == NULL && tcaches_past > MALLOCX_TCACHE_MAX)\n\t\treturn (true);\n\tarena = arena_ichoose(tsdn, NULL);\n\tif (unlikely(arena == NULL))\n\t\treturn (true);\n\ttcache = tcache_create(tsdn, arena);\n\tif (tcache == NULL)\n\t\treturn (true);\n\n\tif (tcaches_avail != NULL) {\n\t\telm = tcaches_avail;\n\t\ttcaches_avail = tcaches_avail->next;\n\t\telm->tcache = tcache;\n\t\t*r_ind = (unsigned)(elm - tcaches);\n\t} else {\n\t\telm = &tcaches[tcaches_past];\n\t\telm->tcache = tcache;\n\t\t*r_ind = tcaches_past;\n\t\ttcaches_past++;\n\t}\n\n\treturn (false);\n}\n\nstatic void\ntcaches_elm_flush(tsd_t *tsd, tcaches_t *elm)\n{\n\n\tif (elm->tcache == NULL)\n\t\treturn;\n\ttcache_destroy(tsd, elm->tcache);\n\telm->tcache = NULL;\n}\n\nvoid\ntcaches_flush(tsd_t *tsd, unsigned ind)\n{\n\n\ttcaches_elm_flush(tsd, &tcaches[ind]);\n}\n\nvoid\ntcaches_destroy(tsd_t *tsd, unsigned ind)\n{\n\ttcaches_t *elm = &tcaches[ind];\n\ttcaches_elm_flush(tsd, elm);\n\telm->next = tcaches_avail;\n\ttcaches_avail = elm;\n}\n\nbool\ntcache_boot(tsdn_t *tsdn)\n{\n\tunsigned i;\n\n\t/*\n\t * If necessary, clamp opt_lg_tcache_max, now that large_maxclass is\n\t * known.\n\t */\n\tif (opt_lg_tcache_max < 0 || (1U << opt_lg_tcache_max) < SMALL_MAXCLASS)\n\t\ttcache_maxclass = SMALL_MAXCLASS;\n\telse if ((1U << opt_lg_tcache_max) > large_maxclass)\n\t\ttcache_maxclass = large_maxclass;\n\telse\n\t\ttcache_maxclass = (1U << opt_lg_tcache_max);\n\n\tnhbins = size2index(tcache_maxclass) + 1;\n\n\t/* Initialize tcache_bin_info. */\n\ttcache_bin_info = (tcache_bin_info_t *)base_alloc(tsdn, nhbins *\n\t    sizeof(tcache_bin_info_t));\n\tif (tcache_bin_info == NULL)\n\t\treturn (true);\n\tstack_nelms = 0;\n\tfor (i = 0; i < NBINS; i++) {\n\t\tif ((arena_bin_info[i].nregs << 1) <= TCACHE_NSLOTS_SMALL_MIN) {\n\t\t\ttcache_bin_info[i].ncached_max =\n\t\t\t    TCACHE_NSLOTS_SMALL_MIN;\n\t\t} else if ((arena_bin_info[i].nregs << 1) <=\n\t\t    TCACHE_NSLOTS_SMALL_MAX) {\n\t\t\ttcache_bin_info[i].ncached_max =\n\t\t\t    (arena_bin_info[i].nregs << 1);\n\t\t} else {\n\t\t\ttcache_bin_info[i].ncached_max =\n\t\t\t    TCACHE_NSLOTS_SMALL_MAX;\n\t\t}\n\t\tstack_nelms += tcache_bin_info[i].ncached_max;\n\t}\n\tfor (; i < nhbins; i++) {\n\t\ttcache_bin_info[i].ncached_max = TCACHE_NSLOTS_LARGE;\n\t\tstack_nelms += tcache_bin_info[i].ncached_max;\n\t}\n\n\treturn (false);\n}\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/deps/jemalloc/src/ticker.c",
    "content": "#define\tJEMALLOC_TICKER_C_\n#include \"jemalloc/internal/jemalloc_internal.h\"\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/deps/jemalloc/src/tsd.c",
    "content": "#define\tJEMALLOC_TSD_C_\n#include \"jemalloc/internal/jemalloc_internal.h\"\n\n/******************************************************************************/\n/* Data. */\n\nstatic unsigned ncleanups;\nstatic malloc_tsd_cleanup_t cleanups[MALLOC_TSD_CLEANUPS_MAX];\n\nmalloc_tsd_data(, , tsd_t, TSD_INITIALIZER)\n\n/******************************************************************************/\n\nvoid *\nmalloc_tsd_malloc(size_t size)\n{\n\n\treturn (a0malloc(CACHELINE_CEILING(size)));\n}\n\nvoid\nmalloc_tsd_dalloc(void *wrapper)\n{\n\n\ta0dalloc(wrapper);\n}\n\nvoid\nmalloc_tsd_no_cleanup(void *arg)\n{\n\n\tnot_reached();\n}\n\n#if defined(JEMALLOC_MALLOC_THREAD_CLEANUP) || defined(_WIN32)\n#ifndef _WIN32\nJEMALLOC_EXPORT\n#endif\nvoid\n_malloc_thread_cleanup(void)\n{\n\tbool pending[MALLOC_TSD_CLEANUPS_MAX], again;\n\tunsigned i;\n\n\tfor (i = 0; i < ncleanups; i++)\n\t\tpending[i] = true;\n\n\tdo {\n\t\tagain = false;\n\t\tfor (i = 0; i < ncleanups; i++) {\n\t\t\tif (pending[i]) {\n\t\t\t\tpending[i] = cleanups[i]();\n\t\t\t\tif (pending[i])\n\t\t\t\t\tagain = true;\n\t\t\t}\n\t\t}\n\t} while (again);\n}\n#endif\n\nvoid\nmalloc_tsd_cleanup_register(bool (*f)(void))\n{\n\n\tassert(ncleanups < MALLOC_TSD_CLEANUPS_MAX);\n\tcleanups[ncleanups] = f;\n\tncleanups++;\n}\n\nvoid\ntsd_cleanup(void *arg)\n{\n\ttsd_t *tsd = (tsd_t *)arg;\n\n\tswitch (tsd->state) {\n\tcase tsd_state_uninitialized:\n\t\t/* Do nothing. */\n\t\tbreak;\n\tcase tsd_state_nominal:\n#define\tO(n, t)\t\t\t\t\t\t\t\t\\\n\t\tn##_cleanup(tsd);\nMALLOC_TSD\n#undef O\n\t\ttsd->state = tsd_state_purgatory;\n\t\ttsd_set(tsd);\n\t\tbreak;\n\tcase tsd_state_purgatory:\n\t\t/*\n\t\t * The previous time this destructor was called, we set the\n\t\t * state to tsd_state_purgatory so that other destructors\n\t\t * wouldn't cause re-creation of the tsd.  This time, do\n\t\t * nothing, and do not request another callback.\n\t\t */\n\t\tbreak;\n\tcase tsd_state_reincarnated:\n\t\t/*\n\t\t * Another destructor deallocated memory after this destructor\n\t\t * was called.  Reset state to tsd_state_purgatory and request\n\t\t * another callback.\n\t\t */\n\t\ttsd->state = tsd_state_purgatory;\n\t\ttsd_set(tsd);\n\t\tbreak;\n\tdefault:\n\t\tnot_reached();\n\t}\n}\n\ntsd_t *\nmalloc_tsd_boot0(void)\n{\n\ttsd_t *tsd;\n\n\tncleanups = 0;\n\tif (tsd_boot0())\n\t\treturn (NULL);\n\ttsd = tsd_fetch();\n\t*tsd_arenas_tdata_bypassp_get(tsd) = true;\n\treturn (tsd);\n}\n\nvoid\nmalloc_tsd_boot1(void)\n{\n\n\ttsd_boot1();\n\t*tsd_arenas_tdata_bypassp_get(tsd_fetch()) = false;\n}\n\n#ifdef _WIN32\nstatic BOOL WINAPI\n_tls_callback(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)\n{\n\n\tswitch (fdwReason) {\n#ifdef JEMALLOC_LAZY_LOCK\n\tcase DLL_THREAD_ATTACH:\n\t\tisthreaded = true;\n\t\tbreak;\n#endif\n\tcase DLL_THREAD_DETACH:\n\t\t_malloc_thread_cleanup();\n\t\tbreak;\n\tdefault:\n\t\tbreak;\n\t}\n\treturn (true);\n}\n\n#ifdef _MSC_VER\n#  ifdef _M_IX86\n#    pragma comment(linker, \"/INCLUDE:__tls_used\")\n#    pragma comment(linker, \"/INCLUDE:_tls_callback\")\n#  else\n#    pragma comment(linker, \"/INCLUDE:_tls_used\")\n#    pragma comment(linker, \"/INCLUDE:tls_callback\")\n#  endif\n#  pragma section(\".CRT$XLY\",long,read)\n#endif\nJEMALLOC_SECTION(\".CRT$XLY\") JEMALLOC_ATTR(used)\nBOOL\t(WINAPI *const tls_callback)(HINSTANCE hinstDLL,\n    DWORD fdwReason, LPVOID lpvReserved) = _tls_callback;\n#endif\n\n#if (!defined(JEMALLOC_MALLOC_THREAD_CLEANUP) && !defined(JEMALLOC_TLS) && \\\n    !defined(_WIN32))\nvoid *\ntsd_init_check_recursion(tsd_init_head_t *head, tsd_init_block_t *block)\n{\n\tpthread_t self = pthread_self();\n\ttsd_init_block_t *iter;\n\n\t/* Check whether this thread has already inserted into the list. */\n\tmalloc_mutex_lock(NULL, &head->lock);\n\tql_foreach(iter, &head->blocks, link) {\n\t\tif (iter->thread == self) {\n\t\t\tmalloc_mutex_unlock(NULL, &head->lock);\n\t\t\treturn (iter->data);\n\t\t}\n\t}\n\t/* Insert block into list. */\n\tql_elm_new(block, link);\n\tblock->thread = self;\n\tql_tail_insert(&head->blocks, block, link);\n\tmalloc_mutex_unlock(NULL, &head->lock);\n\treturn (NULL);\n}\n\nvoid\ntsd_init_finish(tsd_init_head_t *head, tsd_init_block_t *block)\n{\n\n\tmalloc_mutex_lock(NULL, &head->lock);\n\tql_remove(&head->blocks, block, link);\n\tmalloc_mutex_unlock(NULL, &head->lock);\n}\n#endif\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/deps/jemalloc/src/util.c",
    "content": "/*\n * Define simple versions of assertion macros that won't recurse in case\n * of assertion failures in malloc_*printf().\n */\n#define\tassert(e) do {\t\t\t\t\t\t\t\\\n\tif (config_debug && !(e)) {\t\t\t\t\t\\\n\t\tmalloc_write(\"<jemalloc>: Failed assertion\\n\");\t\t\\\n\t\tabort();\t\t\t\t\t\t\\\n\t}\t\t\t\t\t\t\t\t\\\n} while (0)\n\n#define\tnot_reached() do {\t\t\t\t\t\t\\\n\tif (config_debug) {\t\t\t\t\t\t\\\n\t\tmalloc_write(\"<jemalloc>: Unreachable code reached\\n\");\t\\\n\t\tabort();\t\t\t\t\t\t\\\n\t}\t\t\t\t\t\t\t\t\\\n\tunreachable();\t\t\t\t\t\t\t\\\n} while (0)\n\n#define\tnot_implemented() do {\t\t\t\t\t\t\\\n\tif (config_debug) {\t\t\t\t\t\t\\\n\t\tmalloc_write(\"<jemalloc>: Not implemented\\n\");\t\t\\\n\t\tabort();\t\t\t\t\t\t\\\n\t}\t\t\t\t\t\t\t\t\\\n} while (0)\n\n#define\tJEMALLOC_UTIL_C_\n#include \"jemalloc/internal/jemalloc_internal.h\"\n\n/******************************************************************************/\n/* Function prototypes for non-inline static functions. */\n\nstatic void\twrtmessage(void *cbopaque, const char *s);\n#define\tU2S_BUFSIZE\t((1U << (LG_SIZEOF_INTMAX_T + 3)) + 1)\nstatic char\t*u2s(uintmax_t x, unsigned base, bool uppercase, char *s,\n    size_t *slen_p);\n#define\tD2S_BUFSIZE\t(1 + U2S_BUFSIZE)\nstatic char\t*d2s(intmax_t x, char sign, char *s, size_t *slen_p);\n#define\tO2S_BUFSIZE\t(1 + U2S_BUFSIZE)\nstatic char\t*o2s(uintmax_t x, bool alt_form, char *s, size_t *slen_p);\n#define\tX2S_BUFSIZE\t(2 + U2S_BUFSIZE)\nstatic char\t*x2s(uintmax_t x, bool alt_form, bool uppercase, char *s,\n    size_t *slen_p);\n\n/******************************************************************************/\n\n/* malloc_message() setup. */\nstatic void\nwrtmessage(void *cbopaque, const char *s)\n{\n\n#ifdef SYS_write\n\t/*\n\t * Use syscall(2) rather than write(2) when possible in order to avoid\n\t * the possibility of memory allocation within libc.  This is necessary\n\t * on FreeBSD; most operating systems do not have this problem though.\n\t *\n\t * syscall() returns long or int, depending on platform, so capture the\n\t * unused result in the widest plausible type to avoid compiler\n\t * warnings.\n\t */\n\tUNUSED long result = syscall(SYS_write, STDERR_FILENO, s, strlen(s));\n#else\n\tUNUSED ssize_t result = write(STDERR_FILENO, s, strlen(s));\n#endif\n}\n\nJEMALLOC_EXPORT void\t(*je_malloc_message)(void *, const char *s);\n\n/*\n * Wrapper around malloc_message() that avoids the need for\n * je_malloc_message(...) throughout the code.\n */\nvoid\nmalloc_write(const char *s)\n{\n\n\tif (je_malloc_message != NULL)\n\t\tje_malloc_message(NULL, s);\n\telse\n\t\twrtmessage(NULL, s);\n}\n\n/*\n * glibc provides a non-standard strerror_r() when _GNU_SOURCE is defined, so\n * provide a wrapper.\n */\nint\nbuferror(int err, char *buf, size_t buflen)\n{\n\n#ifdef _WIN32\n\tFormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM, NULL, err, 0,\n\t    (LPSTR)buf, (DWORD)buflen, NULL);\n\treturn (0);\n#elif defined(__GLIBC__) && defined(_GNU_SOURCE)\n\tchar *b = strerror_r(err, buf, buflen);\n\tif (b != buf) {\n\t\tstrncpy(buf, b, buflen);\n\t\tbuf[buflen-1] = '\\0';\n\t}\n\treturn (0);\n#else\n\treturn (strerror_r(err, buf, buflen));\n#endif\n}\n\nuintmax_t\nmalloc_strtoumax(const char *restrict nptr, char **restrict endptr, int base)\n{\n\tuintmax_t ret, digit;\n\tunsigned b;\n\tbool neg;\n\tconst char *p, *ns;\n\n\tp = nptr;\n\tif (base < 0 || base == 1 || base > 36) {\n\t\tns = p;\n\t\tset_errno(EINVAL);\n\t\tret = UINTMAX_MAX;\n\t\tgoto label_return;\n\t}\n\tb = base;\n\n\t/* Swallow leading whitespace and get sign, if any. */\n\tneg = false;\n\twhile (true) {\n\t\tswitch (*p) {\n\t\tcase '\\t': case '\\n': case '\\v': case '\\f': case '\\r': case ' ':\n\t\t\tp++;\n\t\t\tbreak;\n\t\tcase '-':\n\t\t\tneg = true;\n\t\t\t/* Fall through. */\n\t\tcase '+':\n\t\t\tp++;\n\t\t\t/* Fall through. */\n\t\tdefault:\n\t\t\tgoto label_prefix;\n\t\t}\n\t}\n\n\t/* Get prefix, if any. */\n\tlabel_prefix:\n\t/*\n\t * Note where the first non-whitespace/sign character is so that it is\n\t * possible to tell whether any digits are consumed (e.g., \"  0\" vs.\n\t * \"  -x\").\n\t */\n\tns = p;\n\tif (*p == '0') {\n\t\tswitch (p[1]) {\n\t\tcase '0': case '1': case '2': case '3': case '4': case '5':\n\t\tcase '6': case '7':\n\t\t\tif (b == 0)\n\t\t\t\tb = 8;\n\t\t\tif (b == 8)\n\t\t\t\tp++;\n\t\t\tbreak;\n\t\tcase 'X': case 'x':\n\t\t\tswitch (p[2]) {\n\t\t\tcase '0': case '1': case '2': case '3': case '4':\n\t\t\tcase '5': case '6': case '7': case '8': case '9':\n\t\t\tcase 'A': case 'B': case 'C': case 'D': case 'E':\n\t\t\tcase 'F':\n\t\t\tcase 'a': case 'b': case 'c': case 'd': case 'e':\n\t\t\tcase 'f':\n\t\t\t\tif (b == 0)\n\t\t\t\t\tb = 16;\n\t\t\t\tif (b == 16)\n\t\t\t\t\tp += 2;\n\t\t\t\tbreak;\n\t\t\tdefault:\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tbreak;\n\t\tdefault:\n\t\t\tp++;\n\t\t\tret = 0;\n\t\t\tgoto label_return;\n\t\t}\n\t}\n\tif (b == 0)\n\t\tb = 10;\n\n\t/* Convert. */\n\tret = 0;\n\twhile ((*p >= '0' && *p <= '9' && (digit = *p - '0') < b)\n\t    || (*p >= 'A' && *p <= 'Z' && (digit = 10 + *p - 'A') < b)\n\t    || (*p >= 'a' && *p <= 'z' && (digit = 10 + *p - 'a') < b)) {\n\t\tuintmax_t pret = ret;\n\t\tret *= b;\n\t\tret += digit;\n\t\tif (ret < pret) {\n\t\t\t/* Overflow. */\n\t\t\tset_errno(ERANGE);\n\t\t\tret = UINTMAX_MAX;\n\t\t\tgoto label_return;\n\t\t}\n\t\tp++;\n\t}\n\tif (neg)\n\t\tret = -ret;\n\n\tif (p == ns) {\n\t\t/* No conversion performed. */\n\t\tset_errno(EINVAL);\n\t\tret = UINTMAX_MAX;\n\t\tgoto label_return;\n\t}\n\nlabel_return:\n\tif (endptr != NULL) {\n\t\tif (p == ns) {\n\t\t\t/* No characters were converted. */\n\t\t\t*endptr = (char *)nptr;\n\t\t} else\n\t\t\t*endptr = (char *)p;\n\t}\n\treturn (ret);\n}\n\nstatic char *\nu2s(uintmax_t x, unsigned base, bool uppercase, char *s, size_t *slen_p)\n{\n\tunsigned i;\n\n\ti = U2S_BUFSIZE - 1;\n\ts[i] = '\\0';\n\tswitch (base) {\n\tcase 10:\n\t\tdo {\n\t\t\ti--;\n\t\t\ts[i] = \"0123456789\"[x % (uint64_t)10];\n\t\t\tx /= (uint64_t)10;\n\t\t} while (x > 0);\n\t\tbreak;\n\tcase 16: {\n\t\tconst char *digits = (uppercase)\n\t\t    ? \"0123456789ABCDEF\"\n\t\t    : \"0123456789abcdef\";\n\n\t\tdo {\n\t\t\ti--;\n\t\t\ts[i] = digits[x & 0xf];\n\t\t\tx >>= 4;\n\t\t} while (x > 0);\n\t\tbreak;\n\t} default: {\n\t\tconst char *digits = (uppercase)\n\t\t    ? \"0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ\"\n\t\t    : \"0123456789abcdefghijklmnopqrstuvwxyz\";\n\n\t\tassert(base >= 2 && base <= 36);\n\t\tdo {\n\t\t\ti--;\n\t\t\ts[i] = digits[x % (uint64_t)base];\n\t\t\tx /= (uint64_t)base;\n\t\t} while (x > 0);\n\t}}\n\n\t*slen_p = U2S_BUFSIZE - 1 - i;\n\treturn (&s[i]);\n}\n\nstatic char *\nd2s(intmax_t x, char sign, char *s, size_t *slen_p)\n{\n\tbool neg;\n\n\tif ((neg = (x < 0)))\n\t\tx = -x;\n\ts = u2s(x, 10, false, s, slen_p);\n\tif (neg)\n\t\tsign = '-';\n\tswitch (sign) {\n\tcase '-':\n\t\tif (!neg)\n\t\t\tbreak;\n\t\t/* Fall through. */\n\tcase ' ':\n\tcase '+':\n\t\ts--;\n\t\t(*slen_p)++;\n\t\t*s = sign;\n\t\tbreak;\n\tdefault: not_reached();\n\t}\n\treturn (s);\n}\n\nstatic char *\no2s(uintmax_t x, bool alt_form, char *s, size_t *slen_p)\n{\n\n\ts = u2s(x, 8, false, s, slen_p);\n\tif (alt_form && *s != '0') {\n\t\ts--;\n\t\t(*slen_p)++;\n\t\t*s = '0';\n\t}\n\treturn (s);\n}\n\nstatic char *\nx2s(uintmax_t x, bool alt_form, bool uppercase, char *s, size_t *slen_p)\n{\n\n\ts = u2s(x, 16, uppercase, s, slen_p);\n\tif (alt_form) {\n\t\ts -= 2;\n\t\t(*slen_p) += 2;\n\t\tmemcpy(s, uppercase ? \"0X\" : \"0x\", 2);\n\t}\n\treturn (s);\n}\n\nsize_t\nmalloc_vsnprintf(char *str, size_t size, const char *format, va_list ap)\n{\n\tsize_t i;\n\tconst char *f;\n\n#define\tAPPEND_C(c) do {\t\t\t\t\t\t\\\n\tif (i < size)\t\t\t\t\t\t\t\\\n\t\tstr[i] = (c);\t\t\t\t\t\t\\\n\ti++;\t\t\t\t\t\t\t\t\\\n} while (0)\n#define\tAPPEND_S(s, slen) do {\t\t\t\t\t\t\\\n\tif (i < size) {\t\t\t\t\t\t\t\\\n\t\tsize_t cpylen = (slen <= size - i) ? slen : size - i;\t\\\n\t\tmemcpy(&str[i], s, cpylen);\t\t\t\t\\\n\t}\t\t\t\t\t\t\t\t\\\n\ti += slen;\t\t\t\t\t\t\t\\\n} while (0)\n#define\tAPPEND_PADDED_S(s, slen, width, left_justify) do {\t\t\\\n\t/* Left padding. */\t\t\t\t\t\t\\\n\tsize_t pad_len = (width == -1) ? 0 : ((slen < (size_t)width) ?\t\\\n\t    (size_t)width - slen : 0);\t\t\t\t\t\\\n\tif (!left_justify && pad_len != 0) {\t\t\t\t\\\n\t\tsize_t j;\t\t\t\t\t\t\\\n\t\tfor (j = 0; j < pad_len; j++)\t\t\t\t\\\n\t\t\tAPPEND_C(' ');\t\t\t\t\t\\\n\t}\t\t\t\t\t\t\t\t\\\n\t/* Value. */\t\t\t\t\t\t\t\\\n\tAPPEND_S(s, slen);\t\t\t\t\t\t\\\n\t/* Right padding. */\t\t\t\t\t\t\\\n\tif (left_justify && pad_len != 0) {\t\t\t\t\\\n\t\tsize_t j;\t\t\t\t\t\t\\\n\t\tfor (j = 0; j < pad_len; j++)\t\t\t\t\\\n\t\t\tAPPEND_C(' ');\t\t\t\t\t\\\n\t}\t\t\t\t\t\t\t\t\\\n} while (0)\n#define\tGET_ARG_NUMERIC(val, len) do {\t\t\t\t\t\\\n\tswitch (len) {\t\t\t\t\t\t\t\\\n\tcase '?':\t\t\t\t\t\t\t\\\n\t\tval = va_arg(ap, int);\t\t\t\t\t\\\n\t\tbreak;\t\t\t\t\t\t\t\\\n\tcase '?' | 0x80:\t\t\t\t\t\t\\\n\t\tval = va_arg(ap, unsigned int);\t\t\t\t\\\n\t\tbreak;\t\t\t\t\t\t\t\\\n\tcase 'l':\t\t\t\t\t\t\t\\\n\t\tval = va_arg(ap, long);\t\t\t\t\t\\\n\t\tbreak;\t\t\t\t\t\t\t\\\n\tcase 'l' | 0x80:\t\t\t\t\t\t\\\n\t\tval = va_arg(ap, unsigned long);\t\t\t\\\n\t\tbreak;\t\t\t\t\t\t\t\\\n\tcase 'q':\t\t\t\t\t\t\t\\\n\t\tval = va_arg(ap, long long);\t\t\t\t\\\n\t\tbreak;\t\t\t\t\t\t\t\\\n\tcase 'q' | 0x80:\t\t\t\t\t\t\\\n\t\tval = va_arg(ap, unsigned long long);\t\t\t\\\n\t\tbreak;\t\t\t\t\t\t\t\\\n\tcase 'j':\t\t\t\t\t\t\t\\\n\t\tval = va_arg(ap, intmax_t);\t\t\t\t\\\n\t\tbreak;\t\t\t\t\t\t\t\\\n\tcase 'j' | 0x80:\t\t\t\t\t\t\\\n\t\tval = va_arg(ap, uintmax_t);\t\t\t\t\\\n\t\tbreak;\t\t\t\t\t\t\t\\\n\tcase 't':\t\t\t\t\t\t\t\\\n\t\tval = va_arg(ap, ptrdiff_t);\t\t\t\t\\\n\t\tbreak;\t\t\t\t\t\t\t\\\n\tcase 'z':\t\t\t\t\t\t\t\\\n\t\tval = va_arg(ap, ssize_t);\t\t\t\t\\\n\t\tbreak;\t\t\t\t\t\t\t\\\n\tcase 'z' | 0x80:\t\t\t\t\t\t\\\n\t\tval = va_arg(ap, size_t);\t\t\t\t\\\n\t\tbreak;\t\t\t\t\t\t\t\\\n\tcase 'p': /* Synthetic; used for %p. */\t\t\t\t\\\n\t\tval = va_arg(ap, uintptr_t);\t\t\t\t\\\n\t\tbreak;\t\t\t\t\t\t\t\\\n\tdefault:\t\t\t\t\t\t\t\\\n\t\tnot_reached();\t\t\t\t\t\t\\\n\t\tval = 0;\t\t\t\t\t\t\\\n\t}\t\t\t\t\t\t\t\t\\\n} while (0)\n\n\ti = 0;\n\tf = format;\n\twhile (true) {\n\t\tswitch (*f) {\n\t\tcase '\\0': goto label_out;\n\t\tcase '%': {\n\t\t\tbool alt_form = false;\n\t\t\tbool left_justify = false;\n\t\t\tbool plus_space = false;\n\t\t\tbool plus_plus = false;\n\t\t\tint prec = -1;\n\t\t\tint width = -1;\n\t\t\tunsigned char len = '?';\n\t\t\tchar *s;\n\t\t\tsize_t slen;\n\n\t\t\tf++;\n\t\t\t/* Flags. */\n\t\t\twhile (true) {\n\t\t\t\tswitch (*f) {\n\t\t\t\tcase '#':\n\t\t\t\t\tassert(!alt_form);\n\t\t\t\t\talt_form = true;\n\t\t\t\t\tbreak;\n\t\t\t\tcase '-':\n\t\t\t\t\tassert(!left_justify);\n\t\t\t\t\tleft_justify = true;\n\t\t\t\t\tbreak;\n\t\t\t\tcase ' ':\n\t\t\t\t\tassert(!plus_space);\n\t\t\t\t\tplus_space = true;\n\t\t\t\t\tbreak;\n\t\t\t\tcase '+':\n\t\t\t\t\tassert(!plus_plus);\n\t\t\t\t\tplus_plus = true;\n\t\t\t\t\tbreak;\n\t\t\t\tdefault: goto label_width;\n\t\t\t\t}\n\t\t\t\tf++;\n\t\t\t}\n\t\t\t/* Width. */\n\t\t\tlabel_width:\n\t\t\tswitch (*f) {\n\t\t\tcase '*':\n\t\t\t\twidth = va_arg(ap, int);\n\t\t\t\tf++;\n\t\t\t\tif (width < 0) {\n\t\t\t\t\tleft_justify = true;\n\t\t\t\t\twidth = -width;\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\tcase '0': case '1': case '2': case '3': case '4':\n\t\t\tcase '5': case '6': case '7': case '8': case '9': {\n\t\t\t\tuintmax_t uwidth;\n\t\t\t\tset_errno(0);\n\t\t\t\tuwidth = malloc_strtoumax(f, (char **)&f, 10);\n\t\t\t\tassert(uwidth != UINTMAX_MAX || get_errno() !=\n\t\t\t\t    ERANGE);\n\t\t\t\twidth = (int)uwidth;\n\t\t\t\tbreak;\n\t\t\t} default:\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\t/* Width/precision separator. */\n\t\t\tif (*f == '.')\n\t\t\t\tf++;\n\t\t\telse\n\t\t\t\tgoto label_length;\n\t\t\t/* Precision. */\n\t\t\tswitch (*f) {\n\t\t\tcase '*':\n\t\t\t\tprec = va_arg(ap, int);\n\t\t\t\tf++;\n\t\t\t\tbreak;\n\t\t\tcase '0': case '1': case '2': case '3': case '4':\n\t\t\tcase '5': case '6': case '7': case '8': case '9': {\n\t\t\t\tuintmax_t uprec;\n\t\t\t\tset_errno(0);\n\t\t\t\tuprec = malloc_strtoumax(f, (char **)&f, 10);\n\t\t\t\tassert(uprec != UINTMAX_MAX || get_errno() !=\n\t\t\t\t    ERANGE);\n\t\t\t\tprec = (int)uprec;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tdefault: break;\n\t\t\t}\n\t\t\t/* Length. */\n\t\t\tlabel_length:\n\t\t\tswitch (*f) {\n\t\t\tcase 'l':\n\t\t\t\tf++;\n\t\t\t\tif (*f == 'l') {\n\t\t\t\t\tlen = 'q';\n\t\t\t\t\tf++;\n\t\t\t\t} else\n\t\t\t\t\tlen = 'l';\n\t\t\t\tbreak;\n\t\t\tcase 'q': case 'j': case 't': case 'z':\n\t\t\t\tlen = *f;\n\t\t\t\tf++;\n\t\t\t\tbreak;\n\t\t\tdefault: break;\n\t\t\t}\n\t\t\t/* Conversion specifier. */\n\t\t\tswitch (*f) {\n\t\t\tcase '%':\n\t\t\t\t/* %% */\n\t\t\t\tAPPEND_C(*f);\n\t\t\t\tf++;\n\t\t\t\tbreak;\n\t\t\tcase 'd': case 'i': {\n\t\t\t\tintmax_t val JEMALLOC_CC_SILENCE_INIT(0);\n\t\t\t\tchar buf[D2S_BUFSIZE];\n\n\t\t\t\tGET_ARG_NUMERIC(val, len);\n\t\t\t\ts = d2s(val, (plus_plus ? '+' : (plus_space ?\n\t\t\t\t    ' ' : '-')), buf, &slen);\n\t\t\t\tAPPEND_PADDED_S(s, slen, width, left_justify);\n\t\t\t\tf++;\n\t\t\t\tbreak;\n\t\t\t} case 'o': {\n\t\t\t\tuintmax_t val JEMALLOC_CC_SILENCE_INIT(0);\n\t\t\t\tchar buf[O2S_BUFSIZE];\n\n\t\t\t\tGET_ARG_NUMERIC(val, len | 0x80);\n\t\t\t\ts = o2s(val, alt_form, buf, &slen);\n\t\t\t\tAPPEND_PADDED_S(s, slen, width, left_justify);\n\t\t\t\tf++;\n\t\t\t\tbreak;\n\t\t\t} case 'u': {\n\t\t\t\tuintmax_t val JEMALLOC_CC_SILENCE_INIT(0);\n\t\t\t\tchar buf[U2S_BUFSIZE];\n\n\t\t\t\tGET_ARG_NUMERIC(val, len | 0x80);\n\t\t\t\ts = u2s(val, 10, false, buf, &slen);\n\t\t\t\tAPPEND_PADDED_S(s, slen, width, left_justify);\n\t\t\t\tf++;\n\t\t\t\tbreak;\n\t\t\t} case 'x': case 'X': {\n\t\t\t\tuintmax_t val JEMALLOC_CC_SILENCE_INIT(0);\n\t\t\t\tchar buf[X2S_BUFSIZE];\n\n\t\t\t\tGET_ARG_NUMERIC(val, len | 0x80);\n\t\t\t\ts = x2s(val, alt_form, *f == 'X', buf, &slen);\n\t\t\t\tAPPEND_PADDED_S(s, slen, width, left_justify);\n\t\t\t\tf++;\n\t\t\t\tbreak;\n\t\t\t} case 'c': {\n\t\t\t\tunsigned char val;\n\t\t\t\tchar buf[2];\n\n\t\t\t\tassert(len == '?' || len == 'l');\n\t\t\t\tassert_not_implemented(len != 'l');\n\t\t\t\tval = va_arg(ap, int);\n\t\t\t\tbuf[0] = val;\n\t\t\t\tbuf[1] = '\\0';\n\t\t\t\tAPPEND_PADDED_S(buf, 1, width, left_justify);\n\t\t\t\tf++;\n\t\t\t\tbreak;\n\t\t\t} case 's':\n\t\t\t\tassert(len == '?' || len == 'l');\n\t\t\t\tassert_not_implemented(len != 'l');\n\t\t\t\ts = va_arg(ap, char *);\n\t\t\t\tslen = (prec < 0) ? strlen(s) : (size_t)prec;\n\t\t\t\tAPPEND_PADDED_S(s, slen, width, left_justify);\n\t\t\t\tf++;\n\t\t\t\tbreak;\n\t\t\tcase 'p': {\n\t\t\t\tuintmax_t val;\n\t\t\t\tchar buf[X2S_BUFSIZE];\n\n\t\t\t\tGET_ARG_NUMERIC(val, 'p');\n\t\t\t\ts = x2s(val, true, false, buf, &slen);\n\t\t\t\tAPPEND_PADDED_S(s, slen, width, left_justify);\n\t\t\t\tf++;\n\t\t\t\tbreak;\n\t\t\t} default: not_reached();\n\t\t\t}\n\t\t\tbreak;\n\t\t} default: {\n\t\t\tAPPEND_C(*f);\n\t\t\tf++;\n\t\t\tbreak;\n\t\t}}\n\t}\n\tlabel_out:\n\tif (i < size)\n\t\tstr[i] = '\\0';\n\telse\n\t\tstr[size - 1] = '\\0';\n\n#undef APPEND_C\n#undef APPEND_S\n#undef APPEND_PADDED_S\n#undef GET_ARG_NUMERIC\n\treturn (i);\n}\n\nJEMALLOC_FORMAT_PRINTF(3, 4)\nsize_t\nmalloc_snprintf(char *str, size_t size, const char *format, ...)\n{\n\tsize_t ret;\n\tva_list ap;\n\n\tva_start(ap, format);\n\tret = malloc_vsnprintf(str, size, format, ap);\n\tva_end(ap);\n\n\treturn (ret);\n}\n\nvoid\nmalloc_vcprintf(void (*write_cb)(void *, const char *), void *cbopaque,\n    const char *format, va_list ap)\n{\n\tchar buf[MALLOC_PRINTF_BUFSIZE];\n\n\tif (write_cb == NULL) {\n\t\t/*\n\t\t * The caller did not provide an alternate write_cb callback\n\t\t * function, so use the default one.  malloc_write() is an\n\t\t * inline function, so use malloc_message() directly here.\n\t\t */\n\t\twrite_cb = (je_malloc_message != NULL) ? je_malloc_message :\n\t\t    wrtmessage;\n\t\tcbopaque = NULL;\n\t}\n\n\tmalloc_vsnprintf(buf, sizeof(buf), format, ap);\n\twrite_cb(cbopaque, buf);\n}\n\n/*\n * Print to a callback function in such a way as to (hopefully) avoid memory\n * allocation.\n */\nJEMALLOC_FORMAT_PRINTF(3, 4)\nvoid\nmalloc_cprintf(void (*write_cb)(void *, const char *), void *cbopaque,\n    const char *format, ...)\n{\n\tva_list ap;\n\n\tva_start(ap, format);\n\tmalloc_vcprintf(write_cb, cbopaque, format, ap);\n\tva_end(ap);\n}\n\n/* Print to stderr in such a way as to avoid memory allocation. */\nJEMALLOC_FORMAT_PRINTF(1, 2)\nvoid\nmalloc_printf(const char *format, ...)\n{\n\tva_list ap;\n\n\tva_start(ap, format);\n\tmalloc_vcprintf(NULL, NULL, format, ap);\n\tva_end(ap);\n}\n\n/*\n * Restore normal assertion macros, in order to make it possible to compile all\n * C files as a single concatenation.\n */\n#undef assert\n#undef not_reached\n#undef not_implemented\n#include \"jemalloc/internal/assert.h\"\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/deps/jemalloc/src/valgrind.c",
    "content": "#include \"jemalloc/internal/jemalloc_internal.h\"\n#ifndef JEMALLOC_VALGRIND\n#  error \"This source file is for Valgrind integration.\"\n#endif\n\n#include <valgrind/memcheck.h>\n\nvoid\nvalgrind_make_mem_noaccess(void *ptr, size_t usize)\n{\n\n\tVALGRIND_MAKE_MEM_NOACCESS(ptr, usize);\n}\n\nvoid\nvalgrind_make_mem_undefined(void *ptr, size_t usize)\n{\n\n\tVALGRIND_MAKE_MEM_UNDEFINED(ptr, usize);\n}\n\nvoid\nvalgrind_make_mem_defined(void *ptr, size_t usize)\n{\n\n\tVALGRIND_MAKE_MEM_DEFINED(ptr, usize);\n}\n\nvoid\nvalgrind_freelike_block(void *ptr, size_t usize)\n{\n\n\tVALGRIND_FREELIKE_BLOCK(ptr, usize);\n}\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/deps/jemalloc/src/witness.c",
    "content": "#define\tJEMALLOC_WITNESS_C_\n#include \"jemalloc/internal/jemalloc_internal.h\"\n\nvoid\nwitness_init(witness_t *witness, const char *name, witness_rank_t rank,\n    witness_comp_t *comp)\n{\n\n\twitness->name = name;\n\twitness->rank = rank;\n\twitness->comp = comp;\n}\n\n#ifdef JEMALLOC_JET\n#undef witness_lock_error\n#define\twitness_lock_error JEMALLOC_N(n_witness_lock_error)\n#endif\nvoid\nwitness_lock_error(const witness_list_t *witnesses, const witness_t *witness)\n{\n\twitness_t *w;\n\n\tmalloc_printf(\"<jemalloc>: Lock rank order reversal:\");\n\tql_foreach(w, witnesses, link) {\n\t\tmalloc_printf(\" %s(%u)\", w->name, w->rank);\n\t}\n\tmalloc_printf(\" %s(%u)\\n\", witness->name, witness->rank);\n\tabort();\n}\n#ifdef JEMALLOC_JET\n#undef witness_lock_error\n#define\twitness_lock_error JEMALLOC_N(witness_lock_error)\nwitness_lock_error_t *witness_lock_error = JEMALLOC_N(n_witness_lock_error);\n#endif\n\n#ifdef JEMALLOC_JET\n#undef witness_owner_error\n#define\twitness_owner_error JEMALLOC_N(n_witness_owner_error)\n#endif\nvoid\nwitness_owner_error(const witness_t *witness)\n{\n\n\tmalloc_printf(\"<jemalloc>: Should own %s(%u)\\n\", witness->name,\n\t    witness->rank);\n\tabort();\n}\n#ifdef JEMALLOC_JET\n#undef witness_owner_error\n#define\twitness_owner_error JEMALLOC_N(witness_owner_error)\nwitness_owner_error_t *witness_owner_error = JEMALLOC_N(n_witness_owner_error);\n#endif\n\n#ifdef JEMALLOC_JET\n#undef witness_not_owner_error\n#define\twitness_not_owner_error JEMALLOC_N(n_witness_not_owner_error)\n#endif\nvoid\nwitness_not_owner_error(const witness_t *witness)\n{\n\n\tmalloc_printf(\"<jemalloc>: Should not own %s(%u)\\n\", witness->name,\n\t    witness->rank);\n\tabort();\n}\n#ifdef JEMALLOC_JET\n#undef witness_not_owner_error\n#define\twitness_not_owner_error JEMALLOC_N(witness_not_owner_error)\nwitness_not_owner_error_t *witness_not_owner_error =\n    JEMALLOC_N(n_witness_not_owner_error);\n#endif\n\n#ifdef JEMALLOC_JET\n#undef witness_lockless_error\n#define\twitness_lockless_error JEMALLOC_N(n_witness_lockless_error)\n#endif\nvoid\nwitness_lockless_error(const witness_list_t *witnesses)\n{\n\twitness_t *w;\n\n\tmalloc_printf(\"<jemalloc>: Should not own any locks:\");\n\tql_foreach(w, witnesses, link) {\n\t\tmalloc_printf(\" %s(%u)\", w->name, w->rank);\n\t}\n\tmalloc_printf(\"\\n\");\n\tabort();\n}\n#ifdef JEMALLOC_JET\n#undef witness_lockless_error\n#define\twitness_lockless_error JEMALLOC_N(witness_lockless_error)\nwitness_lockless_error_t *witness_lockless_error =\n    JEMALLOC_N(n_witness_lockless_error);\n#endif\n\nvoid\nwitnesses_cleanup(tsd_t *tsd)\n{\n\n\twitness_assert_lockless(tsd_tsdn(tsd));\n\n\t/* Do nothing. */\n}\n\nvoid\nwitness_fork_cleanup(tsd_t *tsd)\n{\n\n\t/* Do nothing. */\n}\n\nvoid\nwitness_prefork(tsd_t *tsd)\n{\n\n\ttsd_witness_fork_set(tsd, true);\n}\n\nvoid\nwitness_postfork_parent(tsd_t *tsd)\n{\n\n\ttsd_witness_fork_set(tsd, false);\n}\n\nvoid\nwitness_postfork_child(tsd_t *tsd)\n{\n#ifndef JEMALLOC_MUTEX_INIT_CB\n\twitness_list_t *witnesses;\n\n\twitnesses = tsd_witnessesp_get(tsd);\n\tql_new(witnesses);\n#endif\n\ttsd_witness_fork_set(tsd, false);\n}\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/deps/jemalloc/src/zone.c",
    "content": "#include \"jemalloc/internal/jemalloc_internal.h\"\n#ifndef JEMALLOC_ZONE\n#  error \"This source file is for zones on Darwin (OS X).\"\n#endif\n\n/*\n * The malloc_default_purgeable_zone function is only available on >= 10.6.\n * We need to check whether it is present at runtime, thus the weak_import.\n */\nextern malloc_zone_t *malloc_default_purgeable_zone(void)\nJEMALLOC_ATTR(weak_import);\n\n/******************************************************************************/\n/* Data. */\n\nstatic malloc_zone_t zone;\nstatic struct malloc_introspection_t zone_introspect;\n\n/******************************************************************************/\n/* Function prototypes for non-inline static functions. */\n\nstatic size_t\tzone_size(malloc_zone_t *zone, void *ptr);\nstatic void\t*zone_malloc(malloc_zone_t *zone, size_t size);\nstatic void\t*zone_calloc(malloc_zone_t *zone, size_t num, size_t size);\nstatic void\t*zone_valloc(malloc_zone_t *zone, size_t size);\nstatic void\tzone_free(malloc_zone_t *zone, void *ptr);\nstatic void\t*zone_realloc(malloc_zone_t *zone, void *ptr, size_t size);\n#if (JEMALLOC_ZONE_VERSION >= 5)\nstatic void\t*zone_memalign(malloc_zone_t *zone, size_t alignment,\n#endif\n#if (JEMALLOC_ZONE_VERSION >= 6)\n    size_t size);\nstatic void\tzone_free_definite_size(malloc_zone_t *zone, void *ptr,\n    size_t size);\n#endif\nstatic void\t*zone_destroy(malloc_zone_t *zone);\nstatic size_t\tzone_good_size(malloc_zone_t *zone, size_t size);\nstatic void\tzone_force_lock(malloc_zone_t *zone);\nstatic void\tzone_force_unlock(malloc_zone_t *zone);\n\n/******************************************************************************/\n/*\n * Functions.\n */\n\nstatic size_t\nzone_size(malloc_zone_t *zone, void *ptr)\n{\n\n\t/*\n\t * There appear to be places within Darwin (such as setenv(3)) that\n\t * cause calls to this function with pointers that *no* zone owns.  If\n\t * we knew that all pointers were owned by *some* zone, we could split\n\t * our zone into two parts, and use one as the default allocator and\n\t * the other as the default deallocator/reallocator.  Since that will\n\t * not work in practice, we must check all pointers to assure that they\n\t * reside within a mapped chunk before determining size.\n\t */\n\treturn (ivsalloc(tsdn_fetch(), ptr, config_prof));\n}\n\nstatic void *\nzone_malloc(malloc_zone_t *zone, size_t size)\n{\n\n\treturn (je_malloc(size));\n}\n\nstatic void *\nzone_calloc(malloc_zone_t *zone, size_t num, size_t size)\n{\n\n\treturn (je_calloc(num, size));\n}\n\nstatic void *\nzone_valloc(malloc_zone_t *zone, size_t size)\n{\n\tvoid *ret = NULL; /* Assignment avoids useless compiler warning. */\n\n\tje_posix_memalign(&ret, PAGE, size);\n\n\treturn (ret);\n}\n\nstatic void\nzone_free(malloc_zone_t *zone, void *ptr)\n{\n\n\tif (ivsalloc(tsdn_fetch(), ptr, config_prof) != 0) {\n\t\tje_free(ptr);\n\t\treturn;\n\t}\n\n\tfree(ptr);\n}\n\nstatic void *\nzone_realloc(malloc_zone_t *zone, void *ptr, size_t size)\n{\n\n\tif (ivsalloc(tsdn_fetch(), ptr, config_prof) != 0)\n\t\treturn (je_realloc(ptr, size));\n\n\treturn (realloc(ptr, size));\n}\n\n#if (JEMALLOC_ZONE_VERSION >= 5)\nstatic void *\nzone_memalign(malloc_zone_t *zone, size_t alignment, size_t size)\n{\n\tvoid *ret = NULL; /* Assignment avoids useless compiler warning. */\n\n\tje_posix_memalign(&ret, alignment, size);\n\n\treturn (ret);\n}\n#endif\n\n#if (JEMALLOC_ZONE_VERSION >= 6)\nstatic void\nzone_free_definite_size(malloc_zone_t *zone, void *ptr, size_t size)\n{\n\tsize_t alloc_size;\n\n\talloc_size = ivsalloc(tsdn_fetch(), ptr, config_prof);\n\tif (alloc_size != 0) {\n\t\tassert(alloc_size == size);\n\t\tje_free(ptr);\n\t\treturn;\n\t}\n\n\tfree(ptr);\n}\n#endif\n\nstatic void *\nzone_destroy(malloc_zone_t *zone)\n{\n\n\t/* This function should never be called. */\n\tnot_reached();\n\treturn (NULL);\n}\n\nstatic size_t\nzone_good_size(malloc_zone_t *zone, size_t size)\n{\n\n\tif (size == 0)\n\t\tsize = 1;\n\treturn (s2u(size));\n}\n\nstatic void\nzone_force_lock(malloc_zone_t *zone)\n{\n\n\tif (isthreaded)\n\t\tjemalloc_prefork();\n}\n\nstatic void\nzone_force_unlock(malloc_zone_t *zone)\n{\n\n\tif (isthreaded)\n\t\tjemalloc_postfork_parent();\n}\n\nJEMALLOC_ATTR(constructor)\nvoid\nregister_zone(void)\n{\n\n\t/*\n\t * If something else replaced the system default zone allocator, don't\n\t * register jemalloc's.\n\t */\n\tmalloc_zone_t *default_zone = malloc_default_zone();\n\tmalloc_zone_t *purgeable_zone = NULL;\n\tif (!default_zone->zone_name ||\n\t    strcmp(default_zone->zone_name, \"DefaultMallocZone\") != 0) {\n\t\treturn;\n\t}\n\n\tzone.size = (void *)zone_size;\n\tzone.malloc = (void *)zone_malloc;\n\tzone.calloc = (void *)zone_calloc;\n\tzone.valloc = (void *)zone_valloc;\n\tzone.free = (void *)zone_free;\n\tzone.realloc = (void *)zone_realloc;\n\tzone.destroy = (void *)zone_destroy;\n\tzone.zone_name = \"jemalloc_zone\";\n\tzone.batch_malloc = NULL;\n\tzone.batch_free = NULL;\n\tzone.introspect = &zone_introspect;\n\tzone.version = JEMALLOC_ZONE_VERSION;\n#if (JEMALLOC_ZONE_VERSION >= 5)\n\tzone.memalign = zone_memalign;\n#endif\n#if (JEMALLOC_ZONE_VERSION >= 6)\n\tzone.free_definite_size = zone_free_definite_size;\n#endif\n#if (JEMALLOC_ZONE_VERSION >= 8)\n\tzone.pressure_relief = NULL;\n#endif\n\n\tzone_introspect.enumerator = NULL;\n\tzone_introspect.good_size = (void *)zone_good_size;\n\tzone_introspect.check = NULL;\n\tzone_introspect.print = NULL;\n\tzone_introspect.log = NULL;\n\tzone_introspect.force_lock = (void *)zone_force_lock;\n\tzone_introspect.force_unlock = (void *)zone_force_unlock;\n\tzone_introspect.statistics = NULL;\n#if (JEMALLOC_ZONE_VERSION >= 6)\n\tzone_introspect.zone_locked = NULL;\n#endif\n#if (JEMALLOC_ZONE_VERSION >= 7)\n\tzone_introspect.enable_discharge_checking = NULL;\n\tzone_introspect.disable_discharge_checking = NULL;\n\tzone_introspect.discharge = NULL;\n#ifdef __BLOCKS__\n\tzone_introspect.enumerate_discharged_pointers = NULL;\n#else\n\tzone_introspect.enumerate_unavailable_without_blocks = NULL;\n#endif\n#endif\n\n\t/*\n\t * The default purgeable zone is created lazily by OSX's libc.  It uses\n\t * the default zone when it is created for \"small\" allocations\n\t * (< 15 KiB), but assumes the default zone is a scalable_zone.  This\n\t * obviously fails when the default zone is the jemalloc zone, so\n\t * malloc_default_purgeable_zone is called beforehand so that the\n\t * default purgeable zone is created when the default zone is still\n\t * a scalable_zone.  As purgeable zones only exist on >= 10.6, we need\n\t * to check for the existence of malloc_default_purgeable_zone() at\n\t * run time.\n\t */\n\tif (malloc_default_purgeable_zone != NULL)\n\t\tpurgeable_zone = malloc_default_purgeable_zone();\n\n\t/* Register the custom zone.  At this point it won't be the default. */\n\tmalloc_zone_register(&zone);\n\n\tdo {\n\t\tdefault_zone = malloc_default_zone();\n\t\t/*\n\t\t * Unregister and reregister the default zone.  On OSX >= 10.6,\n\t\t * unregistering takes the last registered zone and places it\n\t\t * at the location of the specified zone.  Unregistering the\n\t\t * default zone thus makes the last registered one the default.\n\t\t * On OSX < 10.6, unregistering shifts all registered zones.\n\t\t * The first registered zone then becomes the default.\n\t\t */\n\t\tmalloc_zone_unregister(default_zone);\n\t\tmalloc_zone_register(default_zone);\n\t\t/*\n\t\t * On OSX 10.6, having the default purgeable zone appear before\n\t\t * the default zone makes some things crash because it thinks it\n\t\t * owns the default zone allocated pointers.  We thus\n\t\t * unregister/re-register it in order to ensure it's always\n\t\t * after the default zone.  On OSX < 10.6, there is no purgeable\n\t\t * zone, so this does nothing.  On OSX >= 10.6, unregistering\n\t\t * replaces the purgeable zone with the last registered zone\n\t\t * above, i.e. the default zone.  Registering it again then puts\n\t\t * it at the end, obviously after the default zone.\n\t\t */\n\t\tif (purgeable_zone) {\n\t\t\tmalloc_zone_unregister(purgeable_zone);\n\t\t\tmalloc_zone_register(purgeable_zone);\n\t\t}\n\t} while (malloc_default_zone() != &zone);\n}\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/deps/jemalloc/test/include/test/SFMT-alti.h",
    "content": "/*\n * This file derives from SFMT 1.3.3\n * (http://www.math.sci.hiroshima-u.ac.jp/~m-mat/MT/SFMT/index.html), which was\n * released under the terms of the following license:\n *\n *   Copyright (c) 2006,2007 Mutsuo Saito, Makoto Matsumoto and Hiroshima\n *   University. All rights reserved.\n *\n *   Redistribution and use in source and binary forms, with or without\n *   modification, are permitted provided that the following conditions are\n *   met:\n *\n *       * Redistributions of source code must retain the above copyright\n *         notice, this list of conditions and the following disclaimer.\n *       * Redistributions in binary form must reproduce the above\n *         copyright notice, this list of conditions and the following\n *         disclaimer in the documentation and/or other materials provided\n *         with the distribution.\n *       * Neither the name of the Hiroshima University nor the names of\n *         its contributors may be used to endorse or promote products\n *         derived from this software without specific prior written\n *         permission.\n *\n *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n *   \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\n *   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\n *   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\n *   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n *   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\n *   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n *   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n *   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n *   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n *   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n/** \n * @file SFMT-alti.h \n *\n * @brief SIMD oriented Fast Mersenne Twister(SFMT)\n * pseudorandom number generator\n *\n * @author Mutsuo Saito (Hiroshima University)\n * @author Makoto Matsumoto (Hiroshima University)\n *\n * Copyright (C) 2007 Mutsuo Saito, Makoto Matsumoto and Hiroshima\n * University. All rights reserved.\n *\n * The new BSD License is applied to this software.\n * see LICENSE.txt\n */\n\n#ifndef SFMT_ALTI_H\n#define SFMT_ALTI_H\n\n/**\n * This function represents the recursion formula in AltiVec and BIG ENDIAN.\n * @param a a 128-bit part of the interal state array\n * @param b a 128-bit part of the interal state array\n * @param c a 128-bit part of the interal state array\n * @param d a 128-bit part of the interal state array\n * @return output\n */\nJEMALLOC_ALWAYS_INLINE\nvector unsigned int vec_recursion(vector unsigned int a,\n\t\t\t\t\t\tvector unsigned int b,\n\t\t\t\t\t\tvector unsigned int c,\n\t\t\t\t\t\tvector unsigned int d) {\n\n    const vector unsigned int sl1 = ALTI_SL1;\n    const vector unsigned int sr1 = ALTI_SR1;\n#ifdef ONLY64\n    const vector unsigned int mask = ALTI_MSK64;\n    const vector unsigned char perm_sl = ALTI_SL2_PERM64;\n    const vector unsigned char perm_sr = ALTI_SR2_PERM64;\n#else\n    const vector unsigned int mask = ALTI_MSK;\n    const vector unsigned char perm_sl = ALTI_SL2_PERM;\n    const vector unsigned char perm_sr = ALTI_SR2_PERM;\n#endif\n    vector unsigned int v, w, x, y, z;\n    x = vec_perm(a, (vector unsigned int)perm_sl, perm_sl);\n    v = a;\n    y = vec_sr(b, sr1);\n    z = vec_perm(c, (vector unsigned int)perm_sr, perm_sr);\n    w = vec_sl(d, sl1);\n    z = vec_xor(z, w);\n    y = vec_and(y, mask);\n    v = vec_xor(v, x);\n    z = vec_xor(z, y);\n    z = vec_xor(z, v);\n    return z;\n}\n\n/**\n * This function fills the internal state array with pseudorandom\n * integers.\n */\nJEMALLOC_INLINE void gen_rand_all(sfmt_t *ctx) {\n    int i;\n    vector unsigned int r, r1, r2;\n\n    r1 = ctx->sfmt[N - 2].s;\n    r2 = ctx->sfmt[N - 1].s;\n    for (i = 0; i < N - POS1; i++) {\n\tr = vec_recursion(ctx->sfmt[i].s, ctx->sfmt[i + POS1].s, r1, r2);\n\tctx->sfmt[i].s = r;\n\tr1 = r2;\n\tr2 = r;\n    }\n    for (; i < N; i++) {\n\tr = vec_recursion(ctx->sfmt[i].s, ctx->sfmt[i + POS1 - N].s, r1, r2);\n\tctx->sfmt[i].s = r;\n\tr1 = r2;\n\tr2 = r;\n    }\n}\n\n/**\n * This function fills the user-specified array with pseudorandom\n * integers.\n *\n * @param array an 128-bit array to be filled by pseudorandom numbers.  \n * @param size number of 128-bit pesudorandom numbers to be generated.\n */\nJEMALLOC_INLINE void gen_rand_array(sfmt_t *ctx, w128_t *array, int size) {\n    int i, j;\n    vector unsigned int r, r1, r2;\n\n    r1 = ctx->sfmt[N - 2].s;\n    r2 = ctx->sfmt[N - 1].s;\n    for (i = 0; i < N - POS1; i++) {\n\tr = vec_recursion(ctx->sfmt[i].s, ctx->sfmt[i + POS1].s, r1, r2);\n\tarray[i].s = r;\n\tr1 = r2;\n\tr2 = r;\n    }\n    for (; i < N; i++) {\n\tr = vec_recursion(ctx->sfmt[i].s, array[i + POS1 - N].s, r1, r2);\n\tarray[i].s = r;\n\tr1 = r2;\n\tr2 = r;\n    }\n    /* main loop */\n    for (; i < size - N; i++) {\n\tr = vec_recursion(array[i - N].s, array[i + POS1 - N].s, r1, r2);\n\tarray[i].s = r;\n\tr1 = r2;\n\tr2 = r;\n    }\n    for (j = 0; j < 2 * N - size; j++) {\n\tctx->sfmt[j].s = array[j + size - N].s;\n    }\n    for (; i < size; i++) {\n\tr = vec_recursion(array[i - N].s, array[i + POS1 - N].s, r1, r2);\n\tarray[i].s = r;\n\tctx->sfmt[j++].s = r;\n\tr1 = r2;\n\tr2 = r;\n    }\n}\n\n#ifndef ONLY64\n#if defined(__APPLE__)\n#define ALTI_SWAP (vector unsigned char) \\\n\t(4, 5, 6, 7, 0, 1, 2, 3, 12, 13, 14, 15, 8, 9, 10, 11)\n#else\n#define ALTI_SWAP {4, 5, 6, 7, 0, 1, 2, 3, 12, 13, 14, 15, 8, 9, 10, 11}\n#endif\n/**\n * This function swaps high and low 32-bit of 64-bit integers in user\n * specified array.\n *\n * @param array an 128-bit array to be swaped.\n * @param size size of 128-bit array.\n */\nJEMALLOC_INLINE void swap(w128_t *array, int size) {\n    int i;\n    const vector unsigned char perm = ALTI_SWAP;\n\n    for (i = 0; i < size; i++) {\n\tarray[i].s = vec_perm(array[i].s, (vector unsigned int)perm, perm);\n    }\n}\n#endif\n\n#endif\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/deps/jemalloc/test/include/test/SFMT-params.h",
    "content": "/*\n * This file derives from SFMT 1.3.3\n * (http://www.math.sci.hiroshima-u.ac.jp/~m-mat/MT/SFMT/index.html), which was\n * released under the terms of the following license:\n *\n *   Copyright (c) 2006,2007 Mutsuo Saito, Makoto Matsumoto and Hiroshima\n *   University. All rights reserved.\n *\n *   Redistribution and use in source and binary forms, with or without\n *   modification, are permitted provided that the following conditions are\n *   met:\n *\n *       * Redistributions of source code must retain the above copyright\n *         notice, this list of conditions and the following disclaimer.\n *       * Redistributions in binary form must reproduce the above\n *         copyright notice, this list of conditions and the following\n *         disclaimer in the documentation and/or other materials provided\n *         with the distribution.\n *       * Neither the name of the Hiroshima University nor the names of\n *         its contributors may be used to endorse or promote products\n *         derived from this software without specific prior written\n *         permission.\n *\n *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n *   \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\n *   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\n *   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\n *   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n *   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\n *   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n *   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n *   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n *   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n *   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n#ifndef SFMT_PARAMS_H\n#define SFMT_PARAMS_H\n\n#if !defined(MEXP)\n#ifdef __GNUC__\n  #warning \"MEXP is not defined. I assume MEXP is 19937.\"\n#endif\n  #define MEXP 19937\n#endif\n/*-----------------\n  BASIC DEFINITIONS\n  -----------------*/\n/** Mersenne Exponent. The period of the sequence \n *  is a multiple of 2^MEXP-1.\n * #define MEXP 19937 */\n/** SFMT generator has an internal state array of 128-bit integers,\n * and N is its size. */\n#define N (MEXP / 128 + 1)\n/** N32 is the size of internal state array when regarded as an array\n * of 32-bit integers.*/\n#define N32 (N * 4)\n/** N64 is the size of internal state array when regarded as an array\n * of 64-bit integers.*/\n#define N64 (N * 2)\n\n/*----------------------\n  the parameters of SFMT\n  following definitions are in paramsXXXX.h file.\n  ----------------------*/\n/** the pick up position of the array.\n#define POS1 122 \n*/\n\n/** the parameter of shift left as four 32-bit registers.\n#define SL1 18\n */\n\n/** the parameter of shift left as one 128-bit register. \n * The 128-bit integer is shifted by (SL2 * 8) bits. \n#define SL2 1 \n*/\n\n/** the parameter of shift right as four 32-bit registers.\n#define SR1 11\n*/\n\n/** the parameter of shift right as one 128-bit register. \n * The 128-bit integer is shifted by (SL2 * 8) bits. \n#define SR2 1 \n*/\n\n/** A bitmask, used in the recursion.  These parameters are introduced\n * to break symmetry of SIMD.\n#define MSK1 0xdfffffefU\n#define MSK2 0xddfecb7fU\n#define MSK3 0xbffaffffU\n#define MSK4 0xbffffff6U \n*/\n\n/** These definitions are part of a 128-bit period certification vector.\n#define PARITY1\t0x00000001U\n#define PARITY2\t0x00000000U\n#define PARITY3\t0x00000000U\n#define PARITY4\t0xc98e126aU\n*/\n\n#if MEXP == 607\n  #include \"test/SFMT-params607.h\"\n#elif MEXP == 1279\n  #include \"test/SFMT-params1279.h\"\n#elif MEXP == 2281\n  #include \"test/SFMT-params2281.h\"\n#elif MEXP == 4253\n  #include \"test/SFMT-params4253.h\"\n#elif MEXP == 11213\n  #include \"test/SFMT-params11213.h\"\n#elif MEXP == 19937\n  #include \"test/SFMT-params19937.h\"\n#elif MEXP == 44497\n  #include \"test/SFMT-params44497.h\"\n#elif MEXP == 86243\n  #include \"test/SFMT-params86243.h\"\n#elif MEXP == 132049\n  #include \"test/SFMT-params132049.h\"\n#elif MEXP == 216091\n  #include \"test/SFMT-params216091.h\"\n#else\n#ifdef __GNUC__\n  #error \"MEXP is not valid.\"\n  #undef MEXP\n#else\n  #undef MEXP\n#endif\n\n#endif\n\n#endif /* SFMT_PARAMS_H */\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/deps/jemalloc/test/include/test/SFMT-params11213.h",
    "content": "/*\n * This file derives from SFMT 1.3.3\n * (http://www.math.sci.hiroshima-u.ac.jp/~m-mat/MT/SFMT/index.html), which was\n * released under the terms of the following license:\n *\n *   Copyright (c) 2006,2007 Mutsuo Saito, Makoto Matsumoto and Hiroshima\n *   University. All rights reserved.\n *\n *   Redistribution and use in source and binary forms, with or without\n *   modification, are permitted provided that the following conditions are\n *   met:\n *\n *       * Redistributions of source code must retain the above copyright\n *         notice, this list of conditions and the following disclaimer.\n *       * Redistributions in binary form must reproduce the above\n *         copyright notice, this list of conditions and the following\n *         disclaimer in the documentation and/or other materials provided\n *         with the distribution.\n *       * Neither the name of the Hiroshima University nor the names of\n *         its contributors may be used to endorse or promote products\n *         derived from this software without specific prior written\n *         permission.\n *\n *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n *   \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\n *   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\n *   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\n *   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n *   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\n *   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n *   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n *   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n *   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n *   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n#ifndef SFMT_PARAMS11213_H\n#define SFMT_PARAMS11213_H\n\n#define POS1\t68\n#define SL1\t14\n#define SL2\t3\n#define SR1\t7\n#define SR2\t3\n#define MSK1\t0xeffff7fbU\n#define MSK2\t0xffffffefU\n#define MSK3\t0xdfdfbfffU\n#define MSK4\t0x7fffdbfdU\n#define PARITY1\t0x00000001U\n#define PARITY2\t0x00000000U\n#define PARITY3\t0xe8148000U\n#define PARITY4\t0xd0c7afa3U\n\n\n/* PARAMETERS FOR ALTIVEC */\n#if defined(__APPLE__)\t/* For OSX */\n    #define ALTI_SL1\t(vector unsigned int)(SL1, SL1, SL1, SL1)\n    #define ALTI_SR1\t(vector unsigned int)(SR1, SR1, SR1, SR1)\n    #define ALTI_MSK\t(vector unsigned int)(MSK1, MSK2, MSK3, MSK4)\n    #define ALTI_MSK64 \\\n\t(vector unsigned int)(MSK2, MSK1, MSK4, MSK3)\n    #define ALTI_SL2_PERM \\\n\t(vector unsigned char)(3,21,21,21,7,0,1,2,11,4,5,6,15,8,9,10)\n    #define ALTI_SL2_PERM64 \\\n\t(vector unsigned char)(3,4,5,6,7,29,29,29,11,12,13,14,15,0,1,2)\n    #define ALTI_SR2_PERM \\\n\t(vector unsigned char)(5,6,7,0,9,10,11,4,13,14,15,8,19,19,19,12)\n    #define ALTI_SR2_PERM64 \\\n\t(vector unsigned char)(13,14,15,0,1,2,3,4,19,19,19,8,9,10,11,12)\n#else\t/* For OTHER OSs(Linux?) */\n    #define ALTI_SL1\t{SL1, SL1, SL1, SL1}\n    #define ALTI_SR1\t{SR1, SR1, SR1, SR1}\n    #define ALTI_MSK\t{MSK1, MSK2, MSK3, MSK4}\n    #define ALTI_MSK64\t{MSK2, MSK1, MSK4, MSK3}\n    #define ALTI_SL2_PERM\t{3,21,21,21,7,0,1,2,11,4,5,6,15,8,9,10}\n    #define ALTI_SL2_PERM64\t{3,4,5,6,7,29,29,29,11,12,13,14,15,0,1,2}\n    #define ALTI_SR2_PERM\t{5,6,7,0,9,10,11,4,13,14,15,8,19,19,19,12}\n    #define ALTI_SR2_PERM64\t{13,14,15,0,1,2,3,4,19,19,19,8,9,10,11,12}\n#endif\t/* For OSX */\n#define IDSTR\t\"SFMT-11213:68-14-3-7-3:effff7fb-ffffffef-dfdfbfff-7fffdbfd\"\n\n#endif /* SFMT_PARAMS11213_H */\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/deps/jemalloc/test/include/test/SFMT-params1279.h",
    "content": "/*\n * This file derives from SFMT 1.3.3\n * (http://www.math.sci.hiroshima-u.ac.jp/~m-mat/MT/SFMT/index.html), which was\n * released under the terms of the following license:\n *\n *   Copyright (c) 2006,2007 Mutsuo Saito, Makoto Matsumoto and Hiroshima\n *   University. All rights reserved.\n *\n *   Redistribution and use in source and binary forms, with or without\n *   modification, are permitted provided that the following conditions are\n *   met:\n *\n *       * Redistributions of source code must retain the above copyright\n *         notice, this list of conditions and the following disclaimer.\n *       * Redistributions in binary form must reproduce the above\n *         copyright notice, this list of conditions and the following\n *         disclaimer in the documentation and/or other materials provided\n *         with the distribution.\n *       * Neither the name of the Hiroshima University nor the names of\n *         its contributors may be used to endorse or promote products\n *         derived from this software without specific prior written\n *         permission.\n *\n *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n *   \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\n *   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\n *   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\n *   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n *   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\n *   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n *   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n *   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n *   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n *   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n#ifndef SFMT_PARAMS1279_H\n#define SFMT_PARAMS1279_H\n\n#define POS1\t7\n#define SL1\t14\n#define SL2\t3\n#define SR1\t5\n#define SR2\t1\n#define MSK1\t0xf7fefffdU\n#define MSK2\t0x7fefcfffU\n#define MSK3\t0xaff3ef3fU\n#define MSK4\t0xb5ffff7fU\n#define PARITY1\t0x00000001U\n#define PARITY2\t0x00000000U\n#define PARITY3\t0x00000000U\n#define PARITY4\t0x20000000U\n\n\n/* PARAMETERS FOR ALTIVEC */\n#if defined(__APPLE__)\t/* For OSX */\n    #define ALTI_SL1\t(vector unsigned int)(SL1, SL1, SL1, SL1)\n    #define ALTI_SR1\t(vector unsigned int)(SR1, SR1, SR1, SR1)\n    #define ALTI_MSK\t(vector unsigned int)(MSK1, MSK2, MSK3, MSK4)\n    #define ALTI_MSK64 \\\n\t(vector unsigned int)(MSK2, MSK1, MSK4, MSK3)\n    #define ALTI_SL2_PERM \\\n\t(vector unsigned char)(3,21,21,21,7,0,1,2,11,4,5,6,15,8,9,10)\n    #define ALTI_SL2_PERM64 \\\n\t(vector unsigned char)(3,4,5,6,7,29,29,29,11,12,13,14,15,0,1,2)\n    #define ALTI_SR2_PERM \\\n\t(vector unsigned char)(7,0,1,2,11,4,5,6,15,8,9,10,17,12,13,14)\n    #define ALTI_SR2_PERM64 \\\n\t(vector unsigned char)(15,0,1,2,3,4,5,6,17,8,9,10,11,12,13,14)\n#else\t/* For OTHER OSs(Linux?) */\n    #define ALTI_SL1\t{SL1, SL1, SL1, SL1}\n    #define ALTI_SR1\t{SR1, SR1, SR1, SR1}\n    #define ALTI_MSK\t{MSK1, MSK2, MSK3, MSK4}\n    #define ALTI_MSK64\t{MSK2, MSK1, MSK4, MSK3}\n    #define ALTI_SL2_PERM\t{3,21,21,21,7,0,1,2,11,4,5,6,15,8,9,10}\n    #define ALTI_SL2_PERM64\t{3,4,5,6,7,29,29,29,11,12,13,14,15,0,1,2}\n    #define ALTI_SR2_PERM\t{7,0,1,2,11,4,5,6,15,8,9,10,17,12,13,14}\n    #define ALTI_SR2_PERM64\t{15,0,1,2,3,4,5,6,17,8,9,10,11,12,13,14}\n#endif\t/* For OSX */\n#define IDSTR\t\"SFMT-1279:7-14-3-5-1:f7fefffd-7fefcfff-aff3ef3f-b5ffff7f\"\n\n#endif /* SFMT_PARAMS1279_H */\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/deps/jemalloc/test/include/test/SFMT-params132049.h",
    "content": "/*\n * This file derives from SFMT 1.3.3\n * (http://www.math.sci.hiroshima-u.ac.jp/~m-mat/MT/SFMT/index.html), which was\n * released under the terms of the following license:\n *\n *   Copyright (c) 2006,2007 Mutsuo Saito, Makoto Matsumoto and Hiroshima\n *   University. All rights reserved.\n *\n *   Redistribution and use in source and binary forms, with or without\n *   modification, are permitted provided that the following conditions are\n *   met:\n *\n *       * Redistributions of source code must retain the above copyright\n *         notice, this list of conditions and the following disclaimer.\n *       * Redistributions in binary form must reproduce the above\n *         copyright notice, this list of conditions and the following\n *         disclaimer in the documentation and/or other materials provided\n *         with the distribution.\n *       * Neither the name of the Hiroshima University nor the names of\n *         its contributors may be used to endorse or promote products\n *         derived from this software without specific prior written\n *         permission.\n *\n *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n *   \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\n *   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\n *   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\n *   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n *   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\n *   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n *   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n *   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n *   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n *   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n#ifndef SFMT_PARAMS132049_H\n#define SFMT_PARAMS132049_H\n\n#define POS1\t110\n#define SL1\t19\n#define SL2\t1\n#define SR1\t21\n#define SR2\t1\n#define MSK1\t0xffffbb5fU\n#define MSK2\t0xfb6ebf95U\n#define MSK3\t0xfffefffaU\n#define MSK4\t0xcff77fffU\n#define PARITY1\t0x00000001U\n#define PARITY2\t0x00000000U\n#define PARITY3\t0xcb520000U\n#define PARITY4\t0xc7e91c7dU\n\n\n/* PARAMETERS FOR ALTIVEC */\n#if defined(__APPLE__)\t/* For OSX */\n    #define ALTI_SL1\t(vector unsigned int)(SL1, SL1, SL1, SL1)\n    #define ALTI_SR1\t(vector unsigned int)(SR1, SR1, SR1, SR1)\n    #define ALTI_MSK\t(vector unsigned int)(MSK1, MSK2, MSK3, MSK4)\n    #define ALTI_MSK64 \\\n\t(vector unsigned int)(MSK2, MSK1, MSK4, MSK3)\n    #define ALTI_SL2_PERM \\\n\t(vector unsigned char)(1,2,3,23,5,6,7,0,9,10,11,4,13,14,15,8)\n    #define ALTI_SL2_PERM64 \\\n\t(vector unsigned char)(1,2,3,4,5,6,7,31,9,10,11,12,13,14,15,0)\n    #define ALTI_SR2_PERM \\\n\t(vector unsigned char)(7,0,1,2,11,4,5,6,15,8,9,10,17,12,13,14)\n    #define ALTI_SR2_PERM64 \\\n\t(vector unsigned char)(15,0,1,2,3,4,5,6,17,8,9,10,11,12,13,14)\n#else\t/* For OTHER OSs(Linux?) */\n    #define ALTI_SL1\t{SL1, SL1, SL1, SL1}\n    #define ALTI_SR1\t{SR1, SR1, SR1, SR1}\n    #define ALTI_MSK\t{MSK1, MSK2, MSK3, MSK4}\n    #define ALTI_MSK64\t{MSK2, MSK1, MSK4, MSK3}\n    #define ALTI_SL2_PERM\t{1,2,3,23,5,6,7,0,9,10,11,4,13,14,15,8}\n    #define ALTI_SL2_PERM64\t{1,2,3,4,5,6,7,31,9,10,11,12,13,14,15,0}\n    #define ALTI_SR2_PERM\t{7,0,1,2,11,4,5,6,15,8,9,10,17,12,13,14}\n    #define ALTI_SR2_PERM64\t{15,0,1,2,3,4,5,6,17,8,9,10,11,12,13,14}\n#endif\t/* For OSX */\n#define IDSTR\t\"SFMT-132049:110-19-1-21-1:ffffbb5f-fb6ebf95-fffefffa-cff77fff\"\n\n#endif /* SFMT_PARAMS132049_H */\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/deps/jemalloc/test/include/test/SFMT-params19937.h",
    "content": "/*\n * This file derives from SFMT 1.3.3\n * (http://www.math.sci.hiroshima-u.ac.jp/~m-mat/MT/SFMT/index.html), which was\n * released under the terms of the following license:\n *\n *   Copyright (c) 2006,2007 Mutsuo Saito, Makoto Matsumoto and Hiroshima\n *   University. All rights reserved.\n *\n *   Redistribution and use in source and binary forms, with or without\n *   modification, are permitted provided that the following conditions are\n *   met:\n *\n *       * Redistributions of source code must retain the above copyright\n *         notice, this list of conditions and the following disclaimer.\n *       * Redistributions in binary form must reproduce the above\n *         copyright notice, this list of conditions and the following\n *         disclaimer in the documentation and/or other materials provided\n *         with the distribution.\n *       * Neither the name of the Hiroshima University nor the names of\n *         its contributors may be used to endorse or promote products\n *         derived from this software without specific prior written\n *         permission.\n *\n *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n *   \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\n *   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\n *   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\n *   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n *   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\n *   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n *   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n *   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n *   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n *   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n#ifndef SFMT_PARAMS19937_H\n#define SFMT_PARAMS19937_H\n\n#define POS1\t122\n#define SL1\t18\n#define SL2\t1\n#define SR1\t11\n#define SR2\t1\n#define MSK1\t0xdfffffefU\n#define MSK2\t0xddfecb7fU\n#define MSK3\t0xbffaffffU\n#define MSK4\t0xbffffff6U\n#define PARITY1\t0x00000001U\n#define PARITY2\t0x00000000U\n#define PARITY3\t0x00000000U\n#define PARITY4\t0x13c9e684U\n\n\n/* PARAMETERS FOR ALTIVEC */\n#if defined(__APPLE__)\t/* For OSX */\n    #define ALTI_SL1\t(vector unsigned int)(SL1, SL1, SL1, SL1)\n    #define ALTI_SR1\t(vector unsigned int)(SR1, SR1, SR1, SR1)\n    #define ALTI_MSK\t(vector unsigned int)(MSK1, MSK2, MSK3, MSK4)\n    #define ALTI_MSK64 \\\n\t(vector unsigned int)(MSK2, MSK1, MSK4, MSK3)\n    #define ALTI_SL2_PERM \\\n\t(vector unsigned char)(1,2,3,23,5,6,7,0,9,10,11,4,13,14,15,8)\n    #define ALTI_SL2_PERM64 \\\n\t(vector unsigned char)(1,2,3,4,5,6,7,31,9,10,11,12,13,14,15,0)\n    #define ALTI_SR2_PERM \\\n\t(vector unsigned char)(7,0,1,2,11,4,5,6,15,8,9,10,17,12,13,14)\n    #define ALTI_SR2_PERM64 \\\n\t(vector unsigned char)(15,0,1,2,3,4,5,6,17,8,9,10,11,12,13,14)\n#else\t/* For OTHER OSs(Linux?) */\n    #define ALTI_SL1\t{SL1, SL1, SL1, SL1}\n    #define ALTI_SR1\t{SR1, SR1, SR1, SR1}\n    #define ALTI_MSK\t{MSK1, MSK2, MSK3, MSK4}\n    #define ALTI_MSK64\t{MSK2, MSK1, MSK4, MSK3}\n    #define ALTI_SL2_PERM\t{1,2,3,23,5,6,7,0,9,10,11,4,13,14,15,8}\n    #define ALTI_SL2_PERM64\t{1,2,3,4,5,6,7,31,9,10,11,12,13,14,15,0}\n    #define ALTI_SR2_PERM\t{7,0,1,2,11,4,5,6,15,8,9,10,17,12,13,14}\n    #define ALTI_SR2_PERM64\t{15,0,1,2,3,4,5,6,17,8,9,10,11,12,13,14}\n#endif\t/* For OSX */\n#define IDSTR\t\"SFMT-19937:122-18-1-11-1:dfffffef-ddfecb7f-bffaffff-bffffff6\"\n\n#endif /* SFMT_PARAMS19937_H */\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/deps/jemalloc/test/include/test/SFMT-params216091.h",
    "content": "/*\n * This file derives from SFMT 1.3.3\n * (http://www.math.sci.hiroshima-u.ac.jp/~m-mat/MT/SFMT/index.html), which was\n * released under the terms of the following license:\n *\n *   Copyright (c) 2006,2007 Mutsuo Saito, Makoto Matsumoto and Hiroshima\n *   University. All rights reserved.\n *\n *   Redistribution and use in source and binary forms, with or without\n *   modification, are permitted provided that the following conditions are\n *   met:\n *\n *       * Redistributions of source code must retain the above copyright\n *         notice, this list of conditions and the following disclaimer.\n *       * Redistributions in binary form must reproduce the above\n *         copyright notice, this list of conditions and the following\n *         disclaimer in the documentation and/or other materials provided\n *         with the distribution.\n *       * Neither the name of the Hiroshima University nor the names of\n *         its contributors may be used to endorse or promote products\n *         derived from this software without specific prior written\n *         permission.\n *\n *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n *   \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\n *   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\n *   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\n *   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n *   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\n *   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n *   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n *   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n *   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n *   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n#ifndef SFMT_PARAMS216091_H\n#define SFMT_PARAMS216091_H\n\n#define POS1\t627\n#define SL1\t11\n#define SL2\t3\n#define SR1\t10\n#define SR2\t1\n#define MSK1\t0xbff7bff7U\n#define MSK2\t0xbfffffffU\n#define MSK3\t0xbffffa7fU\n#define MSK4\t0xffddfbfbU\n#define PARITY1\t0xf8000001U\n#define PARITY2\t0x89e80709U\n#define PARITY3\t0x3bd2b64bU\n#define PARITY4\t0x0c64b1e4U\n\n\n/* PARAMETERS FOR ALTIVEC */\n#if defined(__APPLE__)\t/* For OSX */\n    #define ALTI_SL1\t(vector unsigned int)(SL1, SL1, SL1, SL1)\n    #define ALTI_SR1\t(vector unsigned int)(SR1, SR1, SR1, SR1)\n    #define ALTI_MSK\t(vector unsigned int)(MSK1, MSK2, MSK3, MSK4)\n    #define ALTI_MSK64 \\\n\t(vector unsigned int)(MSK2, MSK1, MSK4, MSK3)\n    #define ALTI_SL2_PERM \\\n\t(vector unsigned char)(3,21,21,21,7,0,1,2,11,4,5,6,15,8,9,10)\n    #define ALTI_SL2_PERM64 \\\n\t(vector unsigned char)(3,4,5,6,7,29,29,29,11,12,13,14,15,0,1,2)\n    #define ALTI_SR2_PERM \\\n\t(vector unsigned char)(7,0,1,2,11,4,5,6,15,8,9,10,17,12,13,14)\n    #define ALTI_SR2_PERM64 \\\n\t(vector unsigned char)(15,0,1,2,3,4,5,6,17,8,9,10,11,12,13,14)\n#else\t/* For OTHER OSs(Linux?) */\n    #define ALTI_SL1\t{SL1, SL1, SL1, SL1}\n    #define ALTI_SR1\t{SR1, SR1, SR1, SR1}\n    #define ALTI_MSK\t{MSK1, MSK2, MSK3, MSK4}\n    #define ALTI_MSK64\t{MSK2, MSK1, MSK4, MSK3}\n    #define ALTI_SL2_PERM\t{3,21,21,21,7,0,1,2,11,4,5,6,15,8,9,10}\n    #define ALTI_SL2_PERM64\t{3,4,5,6,7,29,29,29,11,12,13,14,15,0,1,2}\n    #define ALTI_SR2_PERM\t{7,0,1,2,11,4,5,6,15,8,9,10,17,12,13,14}\n    #define ALTI_SR2_PERM64\t{15,0,1,2,3,4,5,6,17,8,9,10,11,12,13,14}\n#endif\t/* For OSX */\n#define IDSTR\t\"SFMT-216091:627-11-3-10-1:bff7bff7-bfffffff-bffffa7f-ffddfbfb\"\n\n#endif /* SFMT_PARAMS216091_H */\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/deps/jemalloc/test/include/test/SFMT-params2281.h",
    "content": "/*\n * This file derives from SFMT 1.3.3\n * (http://www.math.sci.hiroshima-u.ac.jp/~m-mat/MT/SFMT/index.html), which was\n * released under the terms of the following license:\n *\n *   Copyright (c) 2006,2007 Mutsuo Saito, Makoto Matsumoto and Hiroshima\n *   University. All rights reserved.\n *\n *   Redistribution and use in source and binary forms, with or without\n *   modification, are permitted provided that the following conditions are\n *   met:\n *\n *       * Redistributions of source code must retain the above copyright\n *         notice, this list of conditions and the following disclaimer.\n *       * Redistributions in binary form must reproduce the above\n *         copyright notice, this list of conditions and the following\n *         disclaimer in the documentation and/or other materials provided\n *         with the distribution.\n *       * Neither the name of the Hiroshima University nor the names of\n *         its contributors may be used to endorse or promote products\n *         derived from this software without specific prior written\n *         permission.\n *\n *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n *   \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\n *   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\n *   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\n *   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n *   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\n *   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n *   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n *   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n *   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n *   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n#ifndef SFMT_PARAMS2281_H\n#define SFMT_PARAMS2281_H\n\n#define POS1\t12\n#define SL1\t19\n#define SL2\t1\n#define SR1\t5\n#define SR2\t1\n#define MSK1\t0xbff7ffbfU\n#define MSK2\t0xfdfffffeU\n#define MSK3\t0xf7ffef7fU\n#define MSK4\t0xf2f7cbbfU\n#define PARITY1\t0x00000001U\n#define PARITY2\t0x00000000U\n#define PARITY3\t0x00000000U\n#define PARITY4\t0x41dfa600U\n\n\n/* PARAMETERS FOR ALTIVEC */\n#if defined(__APPLE__)\t/* For OSX */\n    #define ALTI_SL1\t(vector unsigned int)(SL1, SL1, SL1, SL1)\n    #define ALTI_SR1\t(vector unsigned int)(SR1, SR1, SR1, SR1)\n    #define ALTI_MSK\t(vector unsigned int)(MSK1, MSK2, MSK3, MSK4)\n    #define ALTI_MSK64 \\\n\t(vector unsigned int)(MSK2, MSK1, MSK4, MSK3)\n    #define ALTI_SL2_PERM \\\n\t(vector unsigned char)(1,2,3,23,5,6,7,0,9,10,11,4,13,14,15,8)\n    #define ALTI_SL2_PERM64 \\\n\t(vector unsigned char)(1,2,3,4,5,6,7,31,9,10,11,12,13,14,15,0)\n    #define ALTI_SR2_PERM \\\n\t(vector unsigned char)(7,0,1,2,11,4,5,6,15,8,9,10,17,12,13,14)\n    #define ALTI_SR2_PERM64 \\\n\t(vector unsigned char)(15,0,1,2,3,4,5,6,17,8,9,10,11,12,13,14)\n#else\t/* For OTHER OSs(Linux?) */\n    #define ALTI_SL1\t{SL1, SL1, SL1, SL1}\n    #define ALTI_SR1\t{SR1, SR1, SR1, SR1}\n    #define ALTI_MSK\t{MSK1, MSK2, MSK3, MSK4}\n    #define ALTI_MSK64\t{MSK2, MSK1, MSK4, MSK3}\n    #define ALTI_SL2_PERM\t{1,2,3,23,5,6,7,0,9,10,11,4,13,14,15,8}\n    #define ALTI_SL2_PERM64\t{1,2,3,4,5,6,7,31,9,10,11,12,13,14,15,0}\n    #define ALTI_SR2_PERM\t{7,0,1,2,11,4,5,6,15,8,9,10,17,12,13,14}\n    #define ALTI_SR2_PERM64\t{15,0,1,2,3,4,5,6,17,8,9,10,11,12,13,14}\n#endif\t/* For OSX */\n#define IDSTR\t\"SFMT-2281:12-19-1-5-1:bff7ffbf-fdfffffe-f7ffef7f-f2f7cbbf\"\n\n#endif /* SFMT_PARAMS2281_H */\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/deps/jemalloc/test/include/test/SFMT-params4253.h",
    "content": "/*\n * This file derives from SFMT 1.3.3\n * (http://www.math.sci.hiroshima-u.ac.jp/~m-mat/MT/SFMT/index.html), which was\n * released under the terms of the following license:\n *\n *   Copyright (c) 2006,2007 Mutsuo Saito, Makoto Matsumoto and Hiroshima\n *   University. All rights reserved.\n *\n *   Redistribution and use in source and binary forms, with or without\n *   modification, are permitted provided that the following conditions are\n *   met:\n *\n *       * Redistributions of source code must retain the above copyright\n *         notice, this list of conditions and the following disclaimer.\n *       * Redistributions in binary form must reproduce the above\n *         copyright notice, this list of conditions and the following\n *         disclaimer in the documentation and/or other materials provided\n *         with the distribution.\n *       * Neither the name of the Hiroshima University nor the names of\n *         its contributors may be used to endorse or promote products\n *         derived from this software without specific prior written\n *         permission.\n *\n *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n *   \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\n *   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\n *   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\n *   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n *   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\n *   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n *   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n *   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n *   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n *   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n#ifndef SFMT_PARAMS4253_H\n#define SFMT_PARAMS4253_H\n\n#define POS1\t17\n#define SL1\t20\n#define SL2\t1\n#define SR1\t7\n#define SR2\t1\n#define MSK1\t0x9f7bffffU\n#define MSK2\t0x9fffff5fU\n#define MSK3\t0x3efffffbU\n#define MSK4\t0xfffff7bbU\n#define PARITY1\t0xa8000001U\n#define PARITY2\t0xaf5390a3U\n#define PARITY3\t0xb740b3f8U\n#define PARITY4\t0x6c11486dU\n\n\n/* PARAMETERS FOR ALTIVEC */\n#if defined(__APPLE__)\t/* For OSX */\n    #define ALTI_SL1\t(vector unsigned int)(SL1, SL1, SL1, SL1)\n    #define ALTI_SR1\t(vector unsigned int)(SR1, SR1, SR1, SR1)\n    #define ALTI_MSK\t(vector unsigned int)(MSK1, MSK2, MSK3, MSK4)\n    #define ALTI_MSK64 \\\n\t(vector unsigned int)(MSK2, MSK1, MSK4, MSK3)\n    #define ALTI_SL2_PERM \\\n\t(vector unsigned char)(1,2,3,23,5,6,7,0,9,10,11,4,13,14,15,8)\n    #define ALTI_SL2_PERM64 \\\n\t(vector unsigned char)(1,2,3,4,5,6,7,31,9,10,11,12,13,14,15,0)\n    #define ALTI_SR2_PERM \\\n\t(vector unsigned char)(7,0,1,2,11,4,5,6,15,8,9,10,17,12,13,14)\n    #define ALTI_SR2_PERM64 \\\n\t(vector unsigned char)(15,0,1,2,3,4,5,6,17,8,9,10,11,12,13,14)\n#else\t/* For OTHER OSs(Linux?) */\n    #define ALTI_SL1\t{SL1, SL1, SL1, SL1}\n    #define ALTI_SR1\t{SR1, SR1, SR1, SR1}\n    #define ALTI_MSK\t{MSK1, MSK2, MSK3, MSK4}\n    #define ALTI_MSK64\t{MSK2, MSK1, MSK4, MSK3}\n    #define ALTI_SL2_PERM\t{1,2,3,23,5,6,7,0,9,10,11,4,13,14,15,8}\n    #define ALTI_SL2_PERM64\t{1,2,3,4,5,6,7,31,9,10,11,12,13,14,15,0}\n    #define ALTI_SR2_PERM\t{7,0,1,2,11,4,5,6,15,8,9,10,17,12,13,14}\n    #define ALTI_SR2_PERM64\t{15,0,1,2,3,4,5,6,17,8,9,10,11,12,13,14}\n#endif\t/* For OSX */\n#define IDSTR\t\"SFMT-4253:17-20-1-7-1:9f7bffff-9fffff5f-3efffffb-fffff7bb\"\n\n#endif /* SFMT_PARAMS4253_H */\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/deps/jemalloc/test/include/test/SFMT-params44497.h",
    "content": "/*\n * This file derives from SFMT 1.3.3\n * (http://www.math.sci.hiroshima-u.ac.jp/~m-mat/MT/SFMT/index.html), which was\n * released under the terms of the following license:\n *\n *   Copyright (c) 2006,2007 Mutsuo Saito, Makoto Matsumoto and Hiroshima\n *   University. All rights reserved.\n *\n *   Redistribution and use in source and binary forms, with or without\n *   modification, are permitted provided that the following conditions are\n *   met:\n *\n *       * Redistributions of source code must retain the above copyright\n *         notice, this list of conditions and the following disclaimer.\n *       * Redistributions in binary form must reproduce the above\n *         copyright notice, this list of conditions and the following\n *         disclaimer in the documentation and/or other materials provided\n *         with the distribution.\n *       * Neither the name of the Hiroshima University nor the names of\n *         its contributors may be used to endorse or promote products\n *         derived from this software without specific prior written\n *         permission.\n *\n *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n *   \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\n *   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\n *   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\n *   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n *   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\n *   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n *   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n *   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n *   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n *   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n#ifndef SFMT_PARAMS44497_H\n#define SFMT_PARAMS44497_H\n\n#define POS1\t330\n#define SL1\t5\n#define SL2\t3\n#define SR1\t9\n#define SR2\t3\n#define MSK1\t0xeffffffbU\n#define MSK2\t0xdfbebfffU\n#define MSK3\t0xbfbf7befU\n#define MSK4\t0x9ffd7bffU\n#define PARITY1\t0x00000001U\n#define PARITY2\t0x00000000U\n#define PARITY3\t0xa3ac4000U\n#define PARITY4\t0xecc1327aU\n\n\n/* PARAMETERS FOR ALTIVEC */\n#if defined(__APPLE__)\t/* For OSX */\n    #define ALTI_SL1\t(vector unsigned int)(SL1, SL1, SL1, SL1)\n    #define ALTI_SR1\t(vector unsigned int)(SR1, SR1, SR1, SR1)\n    #define ALTI_MSK\t(vector unsigned int)(MSK1, MSK2, MSK3, MSK4)\n    #define ALTI_MSK64 \\\n\t(vector unsigned int)(MSK2, MSK1, MSK4, MSK3)\n    #define ALTI_SL2_PERM \\\n\t(vector unsigned char)(3,21,21,21,7,0,1,2,11,4,5,6,15,8,9,10)\n    #define ALTI_SL2_PERM64 \\\n\t(vector unsigned char)(3,4,5,6,7,29,29,29,11,12,13,14,15,0,1,2)\n    #define ALTI_SR2_PERM \\\n\t(vector unsigned char)(5,6,7,0,9,10,11,4,13,14,15,8,19,19,19,12)\n    #define ALTI_SR2_PERM64 \\\n\t(vector unsigned char)(13,14,15,0,1,2,3,4,19,19,19,8,9,10,11,12)\n#else\t/* For OTHER OSs(Linux?) */\n    #define ALTI_SL1\t{SL1, SL1, SL1, SL1}\n    #define ALTI_SR1\t{SR1, SR1, SR1, SR1}\n    #define ALTI_MSK\t{MSK1, MSK2, MSK3, MSK4}\n    #define ALTI_MSK64\t{MSK2, MSK1, MSK4, MSK3}\n    #define ALTI_SL2_PERM\t{3,21,21,21,7,0,1,2,11,4,5,6,15,8,9,10}\n    #define ALTI_SL2_PERM64\t{3,4,5,6,7,29,29,29,11,12,13,14,15,0,1,2}\n    #define ALTI_SR2_PERM\t{5,6,7,0,9,10,11,4,13,14,15,8,19,19,19,12}\n    #define ALTI_SR2_PERM64\t{13,14,15,0,1,2,3,4,19,19,19,8,9,10,11,12}\n#endif\t/* For OSX */\n#define IDSTR\t\"SFMT-44497:330-5-3-9-3:effffffb-dfbebfff-bfbf7bef-9ffd7bff\"\n\n#endif /* SFMT_PARAMS44497_H */\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/deps/jemalloc/test/include/test/SFMT-params607.h",
    "content": "/*\n * This file derives from SFMT 1.3.3\n * (http://www.math.sci.hiroshima-u.ac.jp/~m-mat/MT/SFMT/index.html), which was\n * released under the terms of the following license:\n *\n *   Copyright (c) 2006,2007 Mutsuo Saito, Makoto Matsumoto and Hiroshima\n *   University. All rights reserved.\n *\n *   Redistribution and use in source and binary forms, with or without\n *   modification, are permitted provided that the following conditions are\n *   met:\n *\n *       * Redistributions of source code must retain the above copyright\n *         notice, this list of conditions and the following disclaimer.\n *       * Redistributions in binary form must reproduce the above\n *         copyright notice, this list of conditions and the following\n *         disclaimer in the documentation and/or other materials provided\n *         with the distribution.\n *       * Neither the name of the Hiroshima University nor the names of\n *         its contributors may be used to endorse or promote products\n *         derived from this software without specific prior written\n *         permission.\n *\n *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n *   \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\n *   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\n *   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\n *   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n *   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\n *   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n *   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n *   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n *   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n *   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n#ifndef SFMT_PARAMS607_H\n#define SFMT_PARAMS607_H\n\n#define POS1\t2\n#define SL1\t15\n#define SL2\t3\n#define SR1\t13\n#define SR2\t3\n#define MSK1\t0xfdff37ffU\n#define MSK2\t0xef7f3f7dU\n#define MSK3\t0xff777b7dU\n#define MSK4\t0x7ff7fb2fU\n#define PARITY1\t0x00000001U\n#define PARITY2\t0x00000000U\n#define PARITY3\t0x00000000U\n#define PARITY4\t0x5986f054U\n\n\n/* PARAMETERS FOR ALTIVEC */\n#if defined(__APPLE__)\t/* For OSX */\n    #define ALTI_SL1\t(vector unsigned int)(SL1, SL1, SL1, SL1)\n    #define ALTI_SR1\t(vector unsigned int)(SR1, SR1, SR1, SR1)\n    #define ALTI_MSK\t(vector unsigned int)(MSK1, MSK2, MSK3, MSK4)\n    #define ALTI_MSK64 \\\n\t(vector unsigned int)(MSK2, MSK1, MSK4, MSK3)\n    #define ALTI_SL2_PERM \\\n\t(vector unsigned char)(3,21,21,21,7,0,1,2,11,4,5,6,15,8,9,10)\n    #define ALTI_SL2_PERM64 \\\n\t(vector unsigned char)(3,4,5,6,7,29,29,29,11,12,13,14,15,0,1,2)\n    #define ALTI_SR2_PERM \\\n\t(vector unsigned char)(5,6,7,0,9,10,11,4,13,14,15,8,19,19,19,12)\n    #define ALTI_SR2_PERM64 \\\n\t(vector unsigned char)(13,14,15,0,1,2,3,4,19,19,19,8,9,10,11,12)\n#else\t/* For OTHER OSs(Linux?) */\n    #define ALTI_SL1\t{SL1, SL1, SL1, SL1}\n    #define ALTI_SR1\t{SR1, SR1, SR1, SR1}\n    #define ALTI_MSK\t{MSK1, MSK2, MSK3, MSK4}\n    #define ALTI_MSK64\t{MSK2, MSK1, MSK4, MSK3}\n    #define ALTI_SL2_PERM\t{3,21,21,21,7,0,1,2,11,4,5,6,15,8,9,10}\n    #define ALTI_SL2_PERM64\t{3,4,5,6,7,29,29,29,11,12,13,14,15,0,1,2}\n    #define ALTI_SR2_PERM\t{5,6,7,0,9,10,11,4,13,14,15,8,19,19,19,12}\n    #define ALTI_SR2_PERM64\t{13,14,15,0,1,2,3,4,19,19,19,8,9,10,11,12}\n#endif\t/* For OSX */\n#define IDSTR\t\"SFMT-607:2-15-3-13-3:fdff37ff-ef7f3f7d-ff777b7d-7ff7fb2f\"\n\n#endif /* SFMT_PARAMS607_H */\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/deps/jemalloc/test/include/test/SFMT-params86243.h",
    "content": "/*\n * This file derives from SFMT 1.3.3\n * (http://www.math.sci.hiroshima-u.ac.jp/~m-mat/MT/SFMT/index.html), which was\n * released under the terms of the following license:\n *\n *   Copyright (c) 2006,2007 Mutsuo Saito, Makoto Matsumoto and Hiroshima\n *   University. All rights reserved.\n *\n *   Redistribution and use in source and binary forms, with or without\n *   modification, are permitted provided that the following conditions are\n *   met:\n *\n *       * Redistributions of source code must retain the above copyright\n *         notice, this list of conditions and the following disclaimer.\n *       * Redistributions in binary form must reproduce the above\n *         copyright notice, this list of conditions and the following\n *         disclaimer in the documentation and/or other materials provided\n *         with the distribution.\n *       * Neither the name of the Hiroshima University nor the names of\n *         its contributors may be used to endorse or promote products\n *         derived from this software without specific prior written\n *         permission.\n *\n *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n *   \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\n *   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\n *   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\n *   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n *   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\n *   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n *   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n *   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n *   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n *   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n#ifndef SFMT_PARAMS86243_H\n#define SFMT_PARAMS86243_H\n\n#define POS1\t366\n#define SL1\t6\n#define SL2\t7\n#define SR1\t19\n#define SR2\t1\n#define MSK1\t0xfdbffbffU\n#define MSK2\t0xbff7ff3fU\n#define MSK3\t0xfd77efffU\n#define MSK4\t0xbf9ff3ffU\n#define PARITY1\t0x00000001U\n#define PARITY2\t0x00000000U\n#define PARITY3\t0x00000000U\n#define PARITY4\t0xe9528d85U\n\n\n/* PARAMETERS FOR ALTIVEC */\n#if defined(__APPLE__)\t/* For OSX */\n    #define ALTI_SL1\t(vector unsigned int)(SL1, SL1, SL1, SL1)\n    #define ALTI_SR1\t(vector unsigned int)(SR1, SR1, SR1, SR1)\n    #define ALTI_MSK\t(vector unsigned int)(MSK1, MSK2, MSK3, MSK4)\n    #define ALTI_MSK64 \\\n\t(vector unsigned int)(MSK2, MSK1, MSK4, MSK3)\n    #define ALTI_SL2_PERM \\\n\t(vector unsigned char)(25,25,25,25,3,25,25,25,7,0,1,2,11,4,5,6)\n    #define ALTI_SL2_PERM64 \\\n\t(vector unsigned char)(7,25,25,25,25,25,25,25,15,0,1,2,3,4,5,6)\n    #define ALTI_SR2_PERM \\\n\t(vector unsigned char)(7,0,1,2,11,4,5,6,15,8,9,10,17,12,13,14)\n    #define ALTI_SR2_PERM64 \\\n\t(vector unsigned char)(15,0,1,2,3,4,5,6,17,8,9,10,11,12,13,14)\n#else\t/* For OTHER OSs(Linux?) */\n    #define ALTI_SL1\t{SL1, SL1, SL1, SL1}\n    #define ALTI_SR1\t{SR1, SR1, SR1, SR1}\n    #define ALTI_MSK\t{MSK1, MSK2, MSK3, MSK4}\n    #define ALTI_MSK64\t{MSK2, MSK1, MSK4, MSK3}\n    #define ALTI_SL2_PERM\t{25,25,25,25,3,25,25,25,7,0,1,2,11,4,5,6}\n    #define ALTI_SL2_PERM64\t{7,25,25,25,25,25,25,25,15,0,1,2,3,4,5,6}\n    #define ALTI_SR2_PERM\t{7,0,1,2,11,4,5,6,15,8,9,10,17,12,13,14}\n    #define ALTI_SR2_PERM64\t{15,0,1,2,3,4,5,6,17,8,9,10,11,12,13,14}\n#endif\t/* For OSX */\n#define IDSTR\t\"SFMT-86243:366-6-7-19-1:fdbffbff-bff7ff3f-fd77efff-bf9ff3ff\"\n\n#endif /* SFMT_PARAMS86243_H */\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/deps/jemalloc/test/include/test/SFMT-sse2.h",
    "content": "/*\n * This file derives from SFMT 1.3.3\n * (http://www.math.sci.hiroshima-u.ac.jp/~m-mat/MT/SFMT/index.html), which was\n * released under the terms of the following license:\n *\n *   Copyright (c) 2006,2007 Mutsuo Saito, Makoto Matsumoto and Hiroshima\n *   University. All rights reserved.\n *\n *   Redistribution and use in source and binary forms, with or without\n *   modification, are permitted provided that the following conditions are\n *   met:\n *\n *       * Redistributions of source code must retain the above copyright\n *         notice, this list of conditions and the following disclaimer.\n *       * Redistributions in binary form must reproduce the above\n *         copyright notice, this list of conditions and the following\n *         disclaimer in the documentation and/or other materials provided\n *         with the distribution.\n *       * Neither the name of the Hiroshima University nor the names of\n *         its contributors may be used to endorse or promote products\n *         derived from this software without specific prior written\n *         permission.\n *\n *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n *   \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\n *   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\n *   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\n *   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n *   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\n *   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n *   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n *   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n *   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n *   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n/** \n * @file  SFMT-sse2.h\n * @brief SIMD oriented Fast Mersenne Twister(SFMT) for Intel SSE2\n *\n * @author Mutsuo Saito (Hiroshima University)\n * @author Makoto Matsumoto (Hiroshima University)\n *\n * @note We assume LITTLE ENDIAN in this file\n *\n * Copyright (C) 2006, 2007 Mutsuo Saito, Makoto Matsumoto and Hiroshima\n * University. All rights reserved.\n *\n * The new BSD License is applied to this software, see LICENSE.txt\n */\n\n#ifndef SFMT_SSE2_H\n#define SFMT_SSE2_H\n\n/**\n * This function represents the recursion formula.\n * @param a a 128-bit part of the interal state array\n * @param b a 128-bit part of the interal state array\n * @param c a 128-bit part of the interal state array\n * @param d a 128-bit part of the interal state array\n * @param mask 128-bit mask\n * @return output\n */\nJEMALLOC_ALWAYS_INLINE __m128i mm_recursion(__m128i *a, __m128i *b, \n\t\t\t\t   __m128i c, __m128i d, __m128i mask) {\n    __m128i v, x, y, z;\n    \n    x = _mm_load_si128(a);\n    y = _mm_srli_epi32(*b, SR1);\n    z = _mm_srli_si128(c, SR2);\n    v = _mm_slli_epi32(d, SL1);\n    z = _mm_xor_si128(z, x);\n    z = _mm_xor_si128(z, v);\n    x = _mm_slli_si128(x, SL2);\n    y = _mm_and_si128(y, mask);\n    z = _mm_xor_si128(z, x);\n    z = _mm_xor_si128(z, y);\n    return z;\n}\n\n/**\n * This function fills the internal state array with pseudorandom\n * integers.\n */\nJEMALLOC_INLINE void gen_rand_all(sfmt_t *ctx) {\n    int i;\n    __m128i r, r1, r2, mask;\n    mask = _mm_set_epi32(MSK4, MSK3, MSK2, MSK1);\n\n    r1 = _mm_load_si128(&ctx->sfmt[N - 2].si);\n    r2 = _mm_load_si128(&ctx->sfmt[N - 1].si);\n    for (i = 0; i < N - POS1; i++) {\n\tr = mm_recursion(&ctx->sfmt[i].si, &ctx->sfmt[i + POS1].si, r1, r2,\n\t  mask);\n\t_mm_store_si128(&ctx->sfmt[i].si, r);\n\tr1 = r2;\n\tr2 = r;\n    }\n    for (; i < N; i++) {\n\tr = mm_recursion(&ctx->sfmt[i].si, &ctx->sfmt[i + POS1 - N].si, r1, r2,\n\t  mask);\n\t_mm_store_si128(&ctx->sfmt[i].si, r);\n\tr1 = r2;\n\tr2 = r;\n    }\n}\n\n/**\n * This function fills the user-specified array with pseudorandom\n * integers.\n *\n * @param array an 128-bit array to be filled by pseudorandom numbers.  \n * @param size number of 128-bit pesudorandom numbers to be generated.\n */\nJEMALLOC_INLINE void gen_rand_array(sfmt_t *ctx, w128_t *array, int size) {\n    int i, j;\n    __m128i r, r1, r2, mask;\n    mask = _mm_set_epi32(MSK4, MSK3, MSK2, MSK1);\n\n    r1 = _mm_load_si128(&ctx->sfmt[N - 2].si);\n    r2 = _mm_load_si128(&ctx->sfmt[N - 1].si);\n    for (i = 0; i < N - POS1; i++) {\n\tr = mm_recursion(&ctx->sfmt[i].si, &ctx->sfmt[i + POS1].si, r1, r2,\n\t  mask);\n\t_mm_store_si128(&array[i].si, r);\n\tr1 = r2;\n\tr2 = r;\n    }\n    for (; i < N; i++) {\n\tr = mm_recursion(&ctx->sfmt[i].si, &array[i + POS1 - N].si, r1, r2,\n\t  mask);\n\t_mm_store_si128(&array[i].si, r);\n\tr1 = r2;\n\tr2 = r;\n    }\n    /* main loop */\n    for (; i < size - N; i++) {\n\tr = mm_recursion(&array[i - N].si, &array[i + POS1 - N].si, r1, r2,\n\t\t\t mask);\n\t_mm_store_si128(&array[i].si, r);\n\tr1 = r2;\n\tr2 = r;\n    }\n    for (j = 0; j < 2 * N - size; j++) {\n\tr = _mm_load_si128(&array[j + size - N].si);\n\t_mm_store_si128(&ctx->sfmt[j].si, r);\n    }\n    for (; i < size; i++) {\n\tr = mm_recursion(&array[i - N].si, &array[i + POS1 - N].si, r1, r2,\n\t\t\t mask);\n\t_mm_store_si128(&array[i].si, r);\n\t_mm_store_si128(&ctx->sfmt[j++].si, r);\n\tr1 = r2;\n\tr2 = r;\n    }\n}\n\n#endif\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/deps/jemalloc/test/include/test/SFMT.h",
    "content": "/*\n * This file derives from SFMT 1.3.3\n * (http://www.math.sci.hiroshima-u.ac.jp/~m-mat/MT/SFMT/index.html), which was\n * released under the terms of the following license:\n *\n *   Copyright (c) 2006,2007 Mutsuo Saito, Makoto Matsumoto and Hiroshima\n *   University. All rights reserved.\n *\n *   Redistribution and use in source and binary forms, with or without\n *   modification, are permitted provided that the following conditions are\n *   met:\n *\n *       * Redistributions of source code must retain the above copyright\n *         notice, this list of conditions and the following disclaimer.\n *       * Redistributions in binary form must reproduce the above\n *         copyright notice, this list of conditions and the following\n *         disclaimer in the documentation and/or other materials provided\n *         with the distribution.\n *       * Neither the name of the Hiroshima University nor the names of\n *         its contributors may be used to endorse or promote products\n *         derived from this software without specific prior written\n *         permission.\n *\n *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n *   \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\n *   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\n *   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\n *   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n *   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\n *   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n *   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n *   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n *   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n *   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n/** \n * @file SFMT.h \n *\n * @brief SIMD oriented Fast Mersenne Twister(SFMT) pseudorandom\n * number generator\n *\n * @author Mutsuo Saito (Hiroshima University)\n * @author Makoto Matsumoto (Hiroshima University)\n *\n * Copyright (C) 2006, 2007 Mutsuo Saito, Makoto Matsumoto and Hiroshima\n * University. All rights reserved.\n *\n * The new BSD License is applied to this software.\n * see LICENSE.txt\n *\n * @note We assume that your system has inttypes.h.  If your system\n * doesn't have inttypes.h, you have to typedef uint32_t and uint64_t,\n * and you have to define PRIu64 and PRIx64 in this file as follows:\n * @verbatim\n typedef unsigned int uint32_t\n typedef unsigned long long uint64_t  \n #define PRIu64 \"llu\"\n #define PRIx64 \"llx\"\n@endverbatim\n * uint32_t must be exactly 32-bit unsigned integer type (no more, no\n * less), and uint64_t must be exactly 64-bit unsigned integer type.\n * PRIu64 and PRIx64 are used for printf function to print 64-bit\n * unsigned int and 64-bit unsigned int in hexadecimal format.\n */\n\n#ifndef SFMT_H\n#define SFMT_H\n\ntypedef struct sfmt_s sfmt_t;\n\nuint32_t gen_rand32(sfmt_t *ctx);\nuint32_t gen_rand32_range(sfmt_t *ctx, uint32_t limit);\nuint64_t gen_rand64(sfmt_t *ctx);\nuint64_t gen_rand64_range(sfmt_t *ctx, uint64_t limit);\nvoid fill_array32(sfmt_t *ctx, uint32_t *array, int size);\nvoid fill_array64(sfmt_t *ctx, uint64_t *array, int size);\nsfmt_t *init_gen_rand(uint32_t seed);\nsfmt_t *init_by_array(uint32_t *init_key, int key_length);\nvoid fini_gen_rand(sfmt_t *ctx);\nconst char *get_idstring(void);\nint get_min_array_size32(void);\nint get_min_array_size64(void);\n\n#ifndef JEMALLOC_ENABLE_INLINE\ndouble to_real1(uint32_t v);\ndouble genrand_real1(sfmt_t *ctx);\ndouble to_real2(uint32_t v);\ndouble genrand_real2(sfmt_t *ctx);\ndouble to_real3(uint32_t v);\ndouble genrand_real3(sfmt_t *ctx);\ndouble to_res53(uint64_t v);\ndouble to_res53_mix(uint32_t x, uint32_t y);\ndouble genrand_res53(sfmt_t *ctx);\ndouble genrand_res53_mix(sfmt_t *ctx);\n#endif\n\n#if (defined(JEMALLOC_ENABLE_INLINE) || defined(SFMT_C_))\n/* These real versions are due to Isaku Wada */\n/** generates a random number on [0,1]-real-interval */\nJEMALLOC_INLINE double to_real1(uint32_t v)\n{\n    return v * (1.0/4294967295.0); \n    /* divided by 2^32-1 */ \n}\n\n/** generates a random number on [0,1]-real-interval */\nJEMALLOC_INLINE double genrand_real1(sfmt_t *ctx)\n{\n    return to_real1(gen_rand32(ctx));\n}\n\n/** generates a random number on [0,1)-real-interval */\nJEMALLOC_INLINE double to_real2(uint32_t v)\n{\n    return v * (1.0/4294967296.0); \n    /* divided by 2^32 */\n}\n\n/** generates a random number on [0,1)-real-interval */\nJEMALLOC_INLINE double genrand_real2(sfmt_t *ctx)\n{\n    return to_real2(gen_rand32(ctx));\n}\n\n/** generates a random number on (0,1)-real-interval */\nJEMALLOC_INLINE double to_real3(uint32_t v)\n{\n    return (((double)v) + 0.5)*(1.0/4294967296.0); \n    /* divided by 2^32 */\n}\n\n/** generates a random number on (0,1)-real-interval */\nJEMALLOC_INLINE double genrand_real3(sfmt_t *ctx)\n{\n    return to_real3(gen_rand32(ctx));\n}\n/** These real versions are due to Isaku Wada */\n\n/** generates a random number on [0,1) with 53-bit resolution*/\nJEMALLOC_INLINE double to_res53(uint64_t v) \n{ \n    return v * (1.0/18446744073709551616.0L);\n}\n\n/** generates a random number on [0,1) with 53-bit resolution from two\n * 32 bit integers */\nJEMALLOC_INLINE double to_res53_mix(uint32_t x, uint32_t y) \n{ \n    return to_res53(x | ((uint64_t)y << 32));\n}\n\n/** generates a random number on [0,1) with 53-bit resolution\n */\nJEMALLOC_INLINE double genrand_res53(sfmt_t *ctx) \n{ \n    return to_res53(gen_rand64(ctx));\n} \n\n/** generates a random number on [0,1) with 53-bit resolution\n    using 32bit integer.\n */\nJEMALLOC_INLINE double genrand_res53_mix(sfmt_t *ctx) \n{ \n    uint32_t x, y;\n\n    x = gen_rand32(ctx);\n    y = gen_rand32(ctx);\n    return to_res53_mix(x, y);\n} \n#endif\n#endif\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/deps/jemalloc/test/include/test/btalloc.h",
    "content": "/* btalloc() provides a mechanism for allocating via permuted backtraces. */\nvoid\t*btalloc(size_t size, unsigned bits);\n\n#define\tbtalloc_n_proto(n)\t\t\t\t\t\t\\\nvoid\t*btalloc_##n(size_t size, unsigned bits);\nbtalloc_n_proto(0)\nbtalloc_n_proto(1)\n\n#define\tbtalloc_n_gen(n)\t\t\t\t\t\t\\\nvoid *\t\t\t\t\t\t\t\t\t\\\nbtalloc_##n(size_t size, unsigned bits)\t\t\t\t\t\\\n{\t\t\t\t\t\t\t\t\t\\\n\tvoid *p;\t\t\t\t\t\t\t\\\n\t\t\t\t\t\t\t\t\t\\\n\tif (bits == 0)\t\t\t\t\t\t\t\\\n\t\tp = mallocx(size, 0);\t\t\t\t\t\\\n\telse {\t\t\t\t\t\t\t\t\\\n\t\tswitch (bits & 0x1U) {\t\t\t\t\t\\\n\t\tcase 0:\t\t\t\t\t\t\t\\\n\t\t\tp = (btalloc_0(size, bits >> 1));\t\t\\\n\t\t\tbreak;\t\t\t\t\t\t\\\n\t\tcase 1:\t\t\t\t\t\t\t\\\n\t\t\tp = (btalloc_1(size, bits >> 1));\t\t\\\n\t\t\tbreak;\t\t\t\t\t\t\\\n\t\tdefault: not_reached();\t\t\t\t\t\\\n\t\t}\t\t\t\t\t\t\t\\\n\t}\t\t\t\t\t\t\t\t\\\n\t/* Intentionally sabotage tail call optimization. */\t\t\\\n\tassert_ptr_not_null(p, \"Unexpected mallocx() failure\");\t\t\\\n\treturn (p);\t\t\t\t\t\t\t\\\n}\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/deps/jemalloc/test/include/test/jemalloc_test.h.in",
    "content": "#include <limits.h>\n#ifndef SIZE_T_MAX\n#  define SIZE_T_MAX\tSIZE_MAX\n#endif\n#include <stdlib.h>\n#include <stdarg.h>\n#include <stdbool.h>\n#include <errno.h>\n#include <math.h>\n#include <string.h>\n#ifdef _WIN32\n#  include \"msvc_compat/strings.h\"\n#endif\n\n#ifdef _WIN32\n#  include <windows.h>\n#  include \"msvc_compat/windows_extra.h\"\n#else\n#  include <pthread.h>\n#endif\n\n#include \"test/jemalloc_test_defs.h\"\n\n#ifdef JEMALLOC_OSSPIN\n#  include <libkern/OSAtomic.h>\n#endif\n\n#if defined(HAVE_ALTIVEC) && !defined(__APPLE__)\n#  include <altivec.h>\n#endif\n#ifdef HAVE_SSE2\n#  include <emmintrin.h>\n#endif\n\n/******************************************************************************/\n/*\n * For unit tests, expose all public and private interfaces.\n */\n#ifdef JEMALLOC_UNIT_TEST\n#  define JEMALLOC_JET\n#  define JEMALLOC_MANGLE\n#  include \"jemalloc/internal/jemalloc_internal.h\"\n\n/******************************************************************************/\n/*\n * For integration tests, expose the public jemalloc interfaces, but only\n * expose the minimum necessary internal utility code (to avoid re-implementing\n * essentially identical code within the test infrastructure).\n */\n#elif defined(JEMALLOC_INTEGRATION_TEST)\n#  define JEMALLOC_MANGLE\n#  include \"jemalloc/jemalloc@install_suffix@.h\"\n#  include \"jemalloc/internal/jemalloc_internal_defs.h\"\n#  include \"jemalloc/internal/jemalloc_internal_macros.h\"\n\nstatic const bool config_debug =\n#ifdef JEMALLOC_DEBUG\n    true\n#else\n    false\n#endif\n    ;\n\n#  define JEMALLOC_N(n) @private_namespace@##n\n#  include \"jemalloc/internal/private_namespace.h\"\n\n#  define JEMALLOC_H_TYPES\n#  define JEMALLOC_H_STRUCTS\n#  define JEMALLOC_H_EXTERNS\n#  define JEMALLOC_H_INLINES\n#  include \"jemalloc/internal/nstime.h\"\n#  include \"jemalloc/internal/util.h\"\n#  include \"jemalloc/internal/qr.h\"\n#  include \"jemalloc/internal/ql.h\"\n#  undef JEMALLOC_H_TYPES\n#  undef JEMALLOC_H_STRUCTS\n#  undef JEMALLOC_H_EXTERNS\n#  undef JEMALLOC_H_INLINES\n\n/******************************************************************************/\n/*\n * For stress tests, expose the public jemalloc interfaces with name mangling\n * so that they can be tested as e.g. malloc() and free().  Also expose the\n * public jemalloc interfaces with jet_ prefixes, so that stress tests can use\n * a separate allocator for their internal data structures.\n */\n#elif defined(JEMALLOC_STRESS_TEST)\n#  include \"jemalloc/jemalloc@install_suffix@.h\"\n\n#  include \"jemalloc/jemalloc_protos_jet.h\"\n\n#  define JEMALLOC_JET\n#  include \"jemalloc/internal/jemalloc_internal.h\"\n#  include \"jemalloc/internal/public_unnamespace.h\"\n#  undef JEMALLOC_JET\n\n#  include \"jemalloc/jemalloc_rename.h\"\n#  define JEMALLOC_MANGLE\n#  ifdef JEMALLOC_STRESS_TESTLIB\n#    include \"jemalloc/jemalloc_mangle_jet.h\"\n#  else\n#    include \"jemalloc/jemalloc_mangle.h\"\n#  endif\n\n/******************************************************************************/\n/*\n * This header does dangerous things, the effects of which only test code\n * should be subject to.\n */\n#else\n#  error \"This header cannot be included outside a testing context\"\n#endif\n\n/******************************************************************************/\n/*\n * Common test utilities.\n */\n#include \"test/btalloc.h\"\n#include \"test/math.h\"\n#include \"test/mtx.h\"\n#include \"test/mq.h\"\n#include \"test/test.h\"\n#include \"test/timer.h\"\n#include \"test/thd.h\"\n#define\tMEXP 19937\n#include \"test/SFMT.h\"\n\n/******************************************************************************/\n/*\n * Define always-enabled assertion macros, so that test assertions execute even\n * if assertions are disabled in the library code.\n */\n#undef assert\n#undef not_reached\n#undef not_implemented\n#undef assert_not_implemented\n\n#define\tassert(e) do {\t\t\t\t\t\t\t\\\n\tif (!(e)) {\t\t\t\t\t\t\t\\\n\t\tmalloc_printf(\t\t\t\t\t\t\\\n\t\t    \"<jemalloc>: %s:%d: Failed assertion: \\\"%s\\\"\\n\",\t\\\n\t\t    __FILE__, __LINE__, #e);\t\t\t\t\\\n\t\tabort();\t\t\t\t\t\t\\\n\t}\t\t\t\t\t\t\t\t\\\n} while (0)\n\n#define\tnot_reached() do {\t\t\t\t\t\t\\\n\tmalloc_printf(\t\t\t\t\t\t\t\\\n\t    \"<jemalloc>: %s:%d: Unreachable code reached\\n\",\t\t\\\n\t    __FILE__, __LINE__);\t\t\t\t\t\\\n\tabort();\t\t\t\t\t\t\t\\\n} while (0)\n\n#define\tnot_implemented() do {\t\t\t\t\t\t\\\n\tmalloc_printf(\"<jemalloc>: %s:%d: Not implemented\\n\",\t\t\\\n\t    __FILE__, __LINE__);\t\t\t\t\t\\\n\tabort();\t\t\t\t\t\t\t\\\n} while (0)\n\n#define\tassert_not_implemented(e) do {\t\t\t\t\t\\\n\tif (!(e))\t\t\t\t\t\t\t\\\n\t\tnot_implemented();\t\t\t\t\t\\\n} while (0)\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/deps/jemalloc/test/include/test/jemalloc_test_defs.h.in",
    "content": "#include \"jemalloc/internal/jemalloc_internal_defs.h\"\n#include \"jemalloc/internal/jemalloc_internal_decls.h\"\n\n/*\n * For use by SFMT.  configure.ac doesn't actually define HAVE_SSE2 because its\n * dependencies are notoriously unportable in practice.\n */\n#undef HAVE_SSE2\n#undef HAVE_ALTIVEC\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/deps/jemalloc/test/include/test/math.h",
    "content": "#ifndef JEMALLOC_ENABLE_INLINE\ndouble\tln_gamma(double x);\ndouble\ti_gamma(double x, double p, double ln_gamma_p);\ndouble\tpt_norm(double p);\ndouble\tpt_chi2(double p, double df, double ln_gamma_df_2);\ndouble\tpt_gamma(double p, double shape, double scale, double ln_gamma_shape);\n#endif\n\n#if (defined(JEMALLOC_ENABLE_INLINE) || defined(MATH_C_))\n/*\n * Compute the natural log of Gamma(x), accurate to 10 decimal places.\n *\n * This implementation is based on:\n *\n *   Pike, M.C., I.D. Hill (1966) Algorithm 291: Logarithm of Gamma function\n *   [S14].  Communications of the ACM 9(9):684.\n */\nJEMALLOC_INLINE double\nln_gamma(double x)\n{\n\tdouble f, z;\n\n\tassert(x > 0.0);\n\n\tif (x < 7.0) {\n\t\tf = 1.0;\n\t\tz = x;\n\t\twhile (z < 7.0) {\n\t\t\tf *= z;\n\t\t\tz += 1.0;\n\t\t}\n\t\tx = z;\n\t\tf = -log(f);\n\t} else\n\t\tf = 0.0;\n\n\tz = 1.0 / (x * x);\n\n\treturn (f + (x-0.5) * log(x) - x + 0.918938533204673 +\n\t    (((-0.000595238095238 * z + 0.000793650793651) * z -\n\t    0.002777777777778) * z + 0.083333333333333) / x);\n}\n\n/*\n * Compute the incomplete Gamma ratio for [0..x], where p is the shape\n * parameter, and ln_gamma_p is ln_gamma(p).\n *\n * This implementation is based on:\n *\n *   Bhattacharjee, G.P. (1970) Algorithm AS 32: The incomplete Gamma integral.\n *   Applied Statistics 19:285-287.\n */\nJEMALLOC_INLINE double\ni_gamma(double x, double p, double ln_gamma_p)\n{\n\tdouble acu, factor, oflo, gin, term, rn, a, b, an, dif;\n\tdouble pn[6];\n\tunsigned i;\n\n\tassert(p > 0.0);\n\tassert(x >= 0.0);\n\n\tif (x == 0.0)\n\t\treturn (0.0);\n\n\tacu = 1.0e-10;\n\toflo = 1.0e30;\n\tgin = 0.0;\n\tfactor = exp(p * log(x) - x - ln_gamma_p);\n\n\tif (x <= 1.0 || x < p) {\n\t\t/* Calculation by series expansion. */\n\t\tgin = 1.0;\n\t\tterm = 1.0;\n\t\trn = p;\n\n\t\twhile (true) {\n\t\t\trn += 1.0;\n\t\t\tterm *= x / rn;\n\t\t\tgin += term;\n\t\t\tif (term <= acu) {\n\t\t\t\tgin *= factor / p;\n\t\t\t\treturn (gin);\n\t\t\t}\n\t\t}\n\t} else {\n\t\t/* Calculation by continued fraction. */\n\t\ta = 1.0 - p;\n\t\tb = a + x + 1.0;\n\t\tterm = 0.0;\n\t\tpn[0] = 1.0;\n\t\tpn[1] = x;\n\t\tpn[2] = x + 1.0;\n\t\tpn[3] = x * b;\n\t\tgin = pn[2] / pn[3];\n\n\t\twhile (true) {\n\t\t\ta += 1.0;\n\t\t\tb += 2.0;\n\t\t\tterm += 1.0;\n\t\t\tan = a * term;\n\t\t\tfor (i = 0; i < 2; i++)\n\t\t\t\tpn[i+4] = b * pn[i+2] - an * pn[i];\n\t\t\tif (pn[5] != 0.0) {\n\t\t\t\trn = pn[4] / pn[5];\n\t\t\t\tdif = fabs(gin - rn);\n\t\t\t\tif (dif <= acu && dif <= acu * rn) {\n\t\t\t\t\tgin = 1.0 - factor * gin;\n\t\t\t\t\treturn (gin);\n\t\t\t\t}\n\t\t\t\tgin = rn;\n\t\t\t}\n\t\t\tfor (i = 0; i < 4; i++)\n\t\t\t\tpn[i] = pn[i+2];\n\n\t\t\tif (fabs(pn[4]) >= oflo) {\n\t\t\t\tfor (i = 0; i < 4; i++)\n\t\t\t\t\tpn[i] /= oflo;\n\t\t\t}\n\t\t}\n\t}\n}\n\n/*\n * Given a value p in [0..1] of the lower tail area of the normal distribution,\n * compute the limit on the definite integral from [-inf..z] that satisfies p,\n * accurate to 16 decimal places.\n *\n * This implementation is based on:\n *\n *   Wichura, M.J. (1988) Algorithm AS 241: The percentage points of the normal\n *   distribution.  Applied Statistics 37(3):477-484.\n */\nJEMALLOC_INLINE double\npt_norm(double p)\n{\n\tdouble q, r, ret;\n\n\tassert(p > 0.0 && p < 1.0);\n\n\tq = p - 0.5;\n\tif (fabs(q) <= 0.425) {\n\t\t/* p close to 1/2. */\n\t\tr = 0.180625 - q * q;\n\t\treturn (q * (((((((2.5090809287301226727e3 * r +\n\t\t    3.3430575583588128105e4) * r + 6.7265770927008700853e4) * r\n\t\t    + 4.5921953931549871457e4) * r + 1.3731693765509461125e4) *\n\t\t    r + 1.9715909503065514427e3) * r + 1.3314166789178437745e2)\n\t\t    * r + 3.3871328727963666080e0) /\n\t\t    (((((((5.2264952788528545610e3 * r +\n\t\t    2.8729085735721942674e4) * r + 3.9307895800092710610e4) * r\n\t\t    + 2.1213794301586595867e4) * r + 5.3941960214247511077e3) *\n\t\t    r + 6.8718700749205790830e2) * r + 4.2313330701600911252e1)\n\t\t    * r + 1.0));\n\t} else {\n\t\tif (q < 0.0)\n\t\t\tr = p;\n\t\telse\n\t\t\tr = 1.0 - p;\n\t\tassert(r > 0.0);\n\n\t\tr = sqrt(-log(r));\n\t\tif (r <= 5.0) {\n\t\t\t/* p neither close to 1/2 nor 0 or 1. */\n\t\t\tr -= 1.6;\n\t\t\tret = ((((((((7.74545014278341407640e-4 * r +\n\t\t\t    2.27238449892691845833e-2) * r +\n\t\t\t    2.41780725177450611770e-1) * r +\n\t\t\t    1.27045825245236838258e0) * r +\n\t\t\t    3.64784832476320460504e0) * r +\n\t\t\t    5.76949722146069140550e0) * r +\n\t\t\t    4.63033784615654529590e0) * r +\n\t\t\t    1.42343711074968357734e0) /\n\t\t\t    (((((((1.05075007164441684324e-9 * r +\n\t\t\t    5.47593808499534494600e-4) * r +\n\t\t\t    1.51986665636164571966e-2)\n\t\t\t    * r + 1.48103976427480074590e-1) * r +\n\t\t\t    6.89767334985100004550e-1) * r +\n\t\t\t    1.67638483018380384940e0) * r +\n\t\t\t    2.05319162663775882187e0) * r + 1.0));\n\t\t} else {\n\t\t\t/* p near 0 or 1. */\n\t\t\tr -= 5.0;\n\t\t\tret = ((((((((2.01033439929228813265e-7 * r +\n\t\t\t    2.71155556874348757815e-5) * r +\n\t\t\t    1.24266094738807843860e-3) * r +\n\t\t\t    2.65321895265761230930e-2) * r +\n\t\t\t    2.96560571828504891230e-1) * r +\n\t\t\t    1.78482653991729133580e0) * r +\n\t\t\t    5.46378491116411436990e0) * r +\n\t\t\t    6.65790464350110377720e0) /\n\t\t\t    (((((((2.04426310338993978564e-15 * r +\n\t\t\t    1.42151175831644588870e-7) * r +\n\t\t\t    1.84631831751005468180e-5) * r +\n\t\t\t    7.86869131145613259100e-4) * r +\n\t\t\t    1.48753612908506148525e-2) * r +\n\t\t\t    1.36929880922735805310e-1) * r +\n\t\t\t    5.99832206555887937690e-1)\n\t\t\t    * r + 1.0));\n\t\t}\n\t\tif (q < 0.0)\n\t\t\tret = -ret;\n\t\treturn (ret);\n\t}\n}\n\n/*\n * Given a value p in [0..1] of the lower tail area of the Chi^2 distribution\n * with df degrees of freedom, where ln_gamma_df_2 is ln_gamma(df/2.0), compute\n * the upper limit on the definite integral from [0..z] that satisfies p,\n * accurate to 12 decimal places.\n *\n * This implementation is based on:\n *\n *   Best, D.J., D.E. Roberts (1975) Algorithm AS 91: The percentage points of\n *   the Chi^2 distribution.  Applied Statistics 24(3):385-388.\n *\n *   Shea, B.L. (1991) Algorithm AS R85: A remark on AS 91: The percentage\n *   points of the Chi^2 distribution.  Applied Statistics 40(1):233-235.\n */\nJEMALLOC_INLINE double\npt_chi2(double p, double df, double ln_gamma_df_2)\n{\n\tdouble e, aa, xx, c, ch, a, q, p1, p2, t, x, b, s1, s2, s3, s4, s5, s6;\n\tunsigned i;\n\n\tassert(p >= 0.0 && p < 1.0);\n\tassert(df > 0.0);\n\n\te = 5.0e-7;\n\taa = 0.6931471805;\n\n\txx = 0.5 * df;\n\tc = xx - 1.0;\n\n\tif (df < -1.24 * log(p)) {\n\t\t/* Starting approximation for small Chi^2. */\n\t\tch = pow(p * xx * exp(ln_gamma_df_2 + xx * aa), 1.0 / xx);\n\t\tif (ch - e < 0.0)\n\t\t\treturn (ch);\n\t} else {\n\t\tif (df > 0.32) {\n\t\t\tx = pt_norm(p);\n\t\t\t/*\n\t\t\t * Starting approximation using Wilson and Hilferty\n\t\t\t * estimate.\n\t\t\t */\n\t\t\tp1 = 0.222222 / df;\n\t\t\tch = df * pow(x * sqrt(p1) + 1.0 - p1, 3.0);\n\t\t\t/* Starting approximation for p tending to 1. */\n\t\t\tif (ch > 2.2 * df + 6.0) {\n\t\t\t\tch = -2.0 * (log(1.0 - p) - c * log(0.5 * ch) +\n\t\t\t\t    ln_gamma_df_2);\n\t\t\t}\n\t\t} else {\n\t\t\tch = 0.4;\n\t\t\ta = log(1.0 - p);\n\t\t\twhile (true) {\n\t\t\t\tq = ch;\n\t\t\t\tp1 = 1.0 + ch * (4.67 + ch);\n\t\t\t\tp2 = ch * (6.73 + ch * (6.66 + ch));\n\t\t\t\tt = -0.5 + (4.67 + 2.0 * ch) / p1 - (6.73 + ch\n\t\t\t\t    * (13.32 + 3.0 * ch)) / p2;\n\t\t\t\tch -= (1.0 - exp(a + ln_gamma_df_2 + 0.5 * ch +\n\t\t\t\t    c * aa) * p2 / p1) / t;\n\t\t\t\tif (fabs(q / ch - 1.0) - 0.01 <= 0.0)\n\t\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t}\n\n\tfor (i = 0; i < 20; i++) {\n\t\t/* Calculation of seven-term Taylor series. */\n\t\tq = ch;\n\t\tp1 = 0.5 * ch;\n\t\tif (p1 < 0.0)\n\t\t\treturn (-1.0);\n\t\tp2 = p - i_gamma(p1, xx, ln_gamma_df_2);\n\t\tt = p2 * exp(xx * aa + ln_gamma_df_2 + p1 - c * log(ch));\n\t\tb = t / ch;\n\t\ta = 0.5 * t - b * c;\n\t\ts1 = (210.0 + a * (140.0 + a * (105.0 + a * (84.0 + a * (70.0 +\n\t\t    60.0 * a))))) / 420.0;\n\t\ts2 = (420.0 + a * (735.0 + a * (966.0 + a * (1141.0 + 1278.0 *\n\t\t    a)))) / 2520.0;\n\t\ts3 = (210.0 + a * (462.0 + a * (707.0 + 932.0 * a))) / 2520.0;\n\t\ts4 = (252.0 + a * (672.0 + 1182.0 * a) + c * (294.0 + a *\n\t\t    (889.0 + 1740.0 * a))) / 5040.0;\n\t\ts5 = (84.0 + 264.0 * a + c * (175.0 + 606.0 * a)) / 2520.0;\n\t\ts6 = (120.0 + c * (346.0 + 127.0 * c)) / 5040.0;\n\t\tch += t * (1.0 + 0.5 * t * s1 - b * c * (s1 - b * (s2 - b * (s3\n\t\t    - b * (s4 - b * (s5 - b * s6))))));\n\t\tif (fabs(q / ch - 1.0) <= e)\n\t\t\tbreak;\n\t}\n\n\treturn (ch);\n}\n\n/*\n * Given a value p in [0..1] and Gamma distribution shape and scale parameters,\n * compute the upper limit on the definite integral from [0..z] that satisfies\n * p.\n */\nJEMALLOC_INLINE double\npt_gamma(double p, double shape, double scale, double ln_gamma_shape)\n{\n\n\treturn (pt_chi2(p, shape * 2.0, ln_gamma_shape) * 0.5 * scale);\n}\n#endif\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/deps/jemalloc/test/include/test/mq.h",
    "content": "void\tmq_nanosleep(unsigned ns);\n\n/*\n * Simple templated message queue implementation that relies on only mutexes for\n * synchronization (which reduces portability issues).  Given the following\n * setup:\n *\n *   typedef struct mq_msg_s mq_msg_t;\n *   struct mq_msg_s {\n *           mq_msg(mq_msg_t) link;\n *           [message data]\n *   };\n *   mq_gen(, mq_, mq_t, mq_msg_t, link)\n *\n * The API is as follows:\n *\n *   bool mq_init(mq_t *mq);\n *   void mq_fini(mq_t *mq);\n *   unsigned mq_count(mq_t *mq);\n *   mq_msg_t *mq_tryget(mq_t *mq);\n *   mq_msg_t *mq_get(mq_t *mq);\n *   void mq_put(mq_t *mq, mq_msg_t *msg);\n *\n * The message queue linkage embedded in each message is to be treated as\n * externally opaque (no need to initialize or clean up externally).  mq_fini()\n * does not perform any cleanup of messages, since it knows nothing of their\n * payloads.\n */\n#define\tmq_msg(a_mq_msg_type)\tql_elm(a_mq_msg_type)\n\n#define\tmq_gen(a_attr, a_prefix, a_mq_type, a_mq_msg_type, a_field)\t\\\ntypedef struct {\t\t\t\t\t\t\t\\\n\tmtx_t\t\t\tlock;\t\t\t\t\t\\\n\tql_head(a_mq_msg_type)\tmsgs;\t\t\t\t\t\\\n\tunsigned\t\tcount;\t\t\t\t\t\\\n} a_mq_type;\t\t\t\t\t\t\t\t\\\na_attr bool\t\t\t\t\t\t\t\t\\\na_prefix##init(a_mq_type *mq) {\t\t\t\t\t\t\\\n\t\t\t\t\t\t\t\t\t\\\n\tif (mtx_init(&mq->lock))\t\t\t\t\t\\\n\t\treturn (true);\t\t\t\t\t\t\\\n\tql_new(&mq->msgs);\t\t\t\t\t\t\\\n\tmq->count = 0;\t\t\t\t\t\t\t\\\n\treturn (false);\t\t\t\t\t\t\t\\\n}\t\t\t\t\t\t\t\t\t\\\na_attr void\t\t\t\t\t\t\t\t\\\na_prefix##fini(a_mq_type *mq)\t\t\t\t\t\t\\\n{\t\t\t\t\t\t\t\t\t\\\n\t\t\t\t\t\t\t\t\t\\\n\tmtx_fini(&mq->lock);\t\t\t\t\t\t\\\n}\t\t\t\t\t\t\t\t\t\\\na_attr unsigned\t\t\t\t\t\t\t\t\\\na_prefix##count(a_mq_type *mq)\t\t\t\t\t\t\\\n{\t\t\t\t\t\t\t\t\t\\\n\tunsigned count;\t\t\t\t\t\t\t\\\n\t\t\t\t\t\t\t\t\t\\\n\tmtx_lock(&mq->lock);\t\t\t\t\t\t\\\n\tcount = mq->count;\t\t\t\t\t\t\\\n\tmtx_unlock(&mq->lock);\t\t\t\t\t\t\\\n\treturn (count);\t\t\t\t\t\t\t\\\n}\t\t\t\t\t\t\t\t\t\\\na_attr a_mq_msg_type *\t\t\t\t\t\t\t\\\na_prefix##tryget(a_mq_type *mq)\t\t\t\t\t\t\\\n{\t\t\t\t\t\t\t\t\t\\\n\ta_mq_msg_type *msg;\t\t\t\t\t\t\\\n\t\t\t\t\t\t\t\t\t\\\n\tmtx_lock(&mq->lock);\t\t\t\t\t\t\\\n\tmsg = ql_first(&mq->msgs);\t\t\t\t\t\\\n\tif (msg != NULL) {\t\t\t\t\t\t\\\n\t\tql_head_remove(&mq->msgs, a_mq_msg_type, a_field);\t\\\n\t\tmq->count--;\t\t\t\t\t\t\\\n\t}\t\t\t\t\t\t\t\t\\\n\tmtx_unlock(&mq->lock);\t\t\t\t\t\t\\\n\treturn (msg);\t\t\t\t\t\t\t\\\n}\t\t\t\t\t\t\t\t\t\\\na_attr a_mq_msg_type *\t\t\t\t\t\t\t\\\na_prefix##get(a_mq_type *mq)\t\t\t\t\t\t\\\n{\t\t\t\t\t\t\t\t\t\\\n\ta_mq_msg_type *msg;\t\t\t\t\t\t\\\n\tunsigned ns;\t\t\t\t\t\t\t\\\n\t\t\t\t\t\t\t\t\t\\\n\tmsg = a_prefix##tryget(mq);\t\t\t\t\t\\\n\tif (msg != NULL)\t\t\t\t\t\t\\\n\t\treturn (msg);\t\t\t\t\t\t\\\n\t\t\t\t\t\t\t\t\t\\\n\tns = 1;\t\t\t\t\t\t\t\t\\\n\twhile (true) {\t\t\t\t\t\t\t\\\n\t\tmq_nanosleep(ns);\t\t\t\t\t\\\n\t\tmsg = a_prefix##tryget(mq);\t\t\t\t\\\n\t\tif (msg != NULL)\t\t\t\t\t\\\n\t\t\treturn (msg);\t\t\t\t\t\\\n\t\tif (ns < 1000*1000*1000) {\t\t\t\t\\\n\t\t\t/* Double sleep time, up to max 1 second. */\t\\\n\t\t\tns <<= 1;\t\t\t\t\t\\\n\t\t\tif (ns > 1000*1000*1000)\t\t\t\\\n\t\t\t\tns = 1000*1000*1000;\t\t\t\\\n\t\t}\t\t\t\t\t\t\t\\\n\t}\t\t\t\t\t\t\t\t\\\n}\t\t\t\t\t\t\t\t\t\\\na_attr void\t\t\t\t\t\t\t\t\\\na_prefix##put(a_mq_type *mq, a_mq_msg_type *msg)\t\t\t\\\n{\t\t\t\t\t\t\t\t\t\\\n\t\t\t\t\t\t\t\t\t\\\n\tmtx_lock(&mq->lock);\t\t\t\t\t\t\\\n\tql_elm_new(msg, a_field);\t\t\t\t\t\\\n\tql_tail_insert(&mq->msgs, msg, a_field);\t\t\t\\\n\tmq->count++;\t\t\t\t\t\t\t\\\n\tmtx_unlock(&mq->lock);\t\t\t\t\t\t\\\n}\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/deps/jemalloc/test/include/test/mtx.h",
    "content": "/*\n * mtx is a slightly simplified version of malloc_mutex.  This code duplication\n * is unfortunate, but there are allocator bootstrapping considerations that\n * would leak into the test infrastructure if malloc_mutex were used directly\n * in tests.\n */\n\ntypedef struct {\n#ifdef _WIN32\n\tCRITICAL_SECTION\tlock;\n#elif (defined(JEMALLOC_OSSPIN))\n\tOSSpinLock\t\tlock;\n#else\n\tpthread_mutex_t\t\tlock;\n#endif\n} mtx_t;\n\nbool\tmtx_init(mtx_t *mtx);\nvoid\tmtx_fini(mtx_t *mtx);\nvoid\tmtx_lock(mtx_t *mtx);\nvoid\tmtx_unlock(mtx_t *mtx);\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/deps/jemalloc/test/include/test/test.h",
    "content": "#define\tASSERT_BUFSIZE\t256\n\n#define\tassert_cmp(t, a, b, cmp, neg_cmp, pri, ...) do {\t\t\\\n\tt a_ = (a);\t\t\t\t\t\t\t\\\n\tt b_ = (b);\t\t\t\t\t\t\t\\\n\tif (!(a_ cmp b_)) {\t\t\t\t\t\t\\\n\t\tchar prefix[ASSERT_BUFSIZE];\t\t\t\t\\\n\t\tchar message[ASSERT_BUFSIZE];\t\t\t\t\\\n\t\tmalloc_snprintf(prefix, sizeof(prefix),\t\t\t\\\n\t\t    \"%s:%s:%d: Failed assertion: \"\t\t\t\\\n\t\t    \"(%s) \"#cmp\" (%s) --> \"\t\t\t\t\\\n\t\t    \"%\"pri\" \"#neg_cmp\" %\"pri\": \",\t\t\t\\\n\t\t    __func__, __FILE__, __LINE__,\t\t\t\\\n\t\t    #a, #b, a_, b_);\t\t\t\t\t\\\n\t\tmalloc_snprintf(message, sizeof(message), __VA_ARGS__);\t\\\n\t\tp_test_fail(prefix, message);\t\t\t\t\\\n\t}\t\t\t\t\t\t\t\t\\\n} while (0)\n\n#define\tassert_ptr_eq(a, b, ...)\tassert_cmp(void *, a, b, ==,\t\\\n    !=, \"p\", __VA_ARGS__)\n#define\tassert_ptr_ne(a, b, ...)\tassert_cmp(void *, a, b, !=,\t\\\n    ==, \"p\", __VA_ARGS__)\n#define\tassert_ptr_null(a, ...)\t\tassert_cmp(void *, a, NULL, ==,\t\\\n    !=, \"p\", __VA_ARGS__)\n#define\tassert_ptr_not_null(a, ...)\tassert_cmp(void *, a, NULL, !=,\t\\\n    ==, \"p\", __VA_ARGS__)\n\n#define\tassert_c_eq(a, b, ...)\tassert_cmp(char, a, b, ==, !=, \"c\", __VA_ARGS__)\n#define\tassert_c_ne(a, b, ...)\tassert_cmp(char, a, b, !=, ==, \"c\", __VA_ARGS__)\n#define\tassert_c_lt(a, b, ...)\tassert_cmp(char, a, b, <, >=, \"c\", __VA_ARGS__)\n#define\tassert_c_le(a, b, ...)\tassert_cmp(char, a, b, <=, >, \"c\", __VA_ARGS__)\n#define\tassert_c_ge(a, b, ...)\tassert_cmp(char, a, b, >=, <, \"c\", __VA_ARGS__)\n#define\tassert_c_gt(a, b, ...)\tassert_cmp(char, a, b, >, <=, \"c\", __VA_ARGS__)\n\n#define\tassert_x_eq(a, b, ...)\tassert_cmp(int, a, b, ==, !=, \"#x\", __VA_ARGS__)\n#define\tassert_x_ne(a, b, ...)\tassert_cmp(int, a, b, !=, ==, \"#x\", __VA_ARGS__)\n#define\tassert_x_lt(a, b, ...)\tassert_cmp(int, a, b, <, >=, \"#x\", __VA_ARGS__)\n#define\tassert_x_le(a, b, ...)\tassert_cmp(int, a, b, <=, >, \"#x\", __VA_ARGS__)\n#define\tassert_x_ge(a, b, ...)\tassert_cmp(int, a, b, >=, <, \"#x\", __VA_ARGS__)\n#define\tassert_x_gt(a, b, ...)\tassert_cmp(int, a, b, >, <=, \"#x\", __VA_ARGS__)\n\n#define\tassert_d_eq(a, b, ...)\tassert_cmp(int, a, b, ==, !=, \"d\", __VA_ARGS__)\n#define\tassert_d_ne(a, b, ...)\tassert_cmp(int, a, b, !=, ==, \"d\", __VA_ARGS__)\n#define\tassert_d_lt(a, b, ...)\tassert_cmp(int, a, b, <, >=, \"d\", __VA_ARGS__)\n#define\tassert_d_le(a, b, ...)\tassert_cmp(int, a, b, <=, >, \"d\", __VA_ARGS__)\n#define\tassert_d_ge(a, b, ...)\tassert_cmp(int, a, b, >=, <, \"d\", __VA_ARGS__)\n#define\tassert_d_gt(a, b, ...)\tassert_cmp(int, a, b, >, <=, \"d\", __VA_ARGS__)\n\n#define\tassert_u_eq(a, b, ...)\tassert_cmp(int, a, b, ==, !=, \"u\", __VA_ARGS__)\n#define\tassert_u_ne(a, b, ...)\tassert_cmp(int, a, b, !=, ==, \"u\", __VA_ARGS__)\n#define\tassert_u_lt(a, b, ...)\tassert_cmp(int, a, b, <, >=, \"u\", __VA_ARGS__)\n#define\tassert_u_le(a, b, ...)\tassert_cmp(int, a, b, <=, >, \"u\", __VA_ARGS__)\n#define\tassert_u_ge(a, b, ...)\tassert_cmp(int, a, b, >=, <, \"u\", __VA_ARGS__)\n#define\tassert_u_gt(a, b, ...)\tassert_cmp(int, a, b, >, <=, \"u\", __VA_ARGS__)\n\n#define\tassert_ld_eq(a, b, ...)\tassert_cmp(long, a, b, ==,\t\\\n    !=, \"ld\", __VA_ARGS__)\n#define\tassert_ld_ne(a, b, ...)\tassert_cmp(long, a, b, !=,\t\\\n    ==, \"ld\", __VA_ARGS__)\n#define\tassert_ld_lt(a, b, ...)\tassert_cmp(long, a, b, <,\t\\\n    >=, \"ld\", __VA_ARGS__)\n#define\tassert_ld_le(a, b, ...)\tassert_cmp(long, a, b, <=,\t\\\n    >, \"ld\", __VA_ARGS__)\n#define\tassert_ld_ge(a, b, ...)\tassert_cmp(long, a, b, >=,\t\\\n    <, \"ld\", __VA_ARGS__)\n#define\tassert_ld_gt(a, b, ...)\tassert_cmp(long, a, b, >,\t\\\n    <=, \"ld\", __VA_ARGS__)\n\n#define\tassert_lu_eq(a, b, ...)\tassert_cmp(unsigned long,\t\\\n    a, b, ==, !=, \"lu\", __VA_ARGS__)\n#define\tassert_lu_ne(a, b, ...)\tassert_cmp(unsigned long,\t\\\n    a, b, !=, ==, \"lu\", __VA_ARGS__)\n#define\tassert_lu_lt(a, b, ...)\tassert_cmp(unsigned long,\t\\\n    a, b, <, >=, \"lu\", __VA_ARGS__)\n#define\tassert_lu_le(a, b, ...)\tassert_cmp(unsigned long,\t\\\n    a, b, <=, >, \"lu\", __VA_ARGS__)\n#define\tassert_lu_ge(a, b, ...)\tassert_cmp(unsigned long,\t\\\n    a, b, >=, <, \"lu\", __VA_ARGS__)\n#define\tassert_lu_gt(a, b, ...)\tassert_cmp(unsigned long,\t\\\n    a, b, >, <=, \"lu\", __VA_ARGS__)\n\n#define\tassert_qd_eq(a, b, ...)\tassert_cmp(long long, a, b, ==,\t\\\n    !=, \"qd\", __VA_ARGS__)\n#define\tassert_qd_ne(a, b, ...)\tassert_cmp(long long, a, b, !=,\t\\\n    ==, \"qd\", __VA_ARGS__)\n#define\tassert_qd_lt(a, b, ...)\tassert_cmp(long long, a, b, <,\t\\\n    >=, \"qd\", __VA_ARGS__)\n#define\tassert_qd_le(a, b, ...)\tassert_cmp(long long, a, b, <=,\t\\\n    >, \"qd\", __VA_ARGS__)\n#define\tassert_qd_ge(a, b, ...)\tassert_cmp(long long, a, b, >=,\t\\\n    <, \"qd\", __VA_ARGS__)\n#define\tassert_qd_gt(a, b, ...)\tassert_cmp(long long, a, b, >,\t\\\n    <=, \"qd\", __VA_ARGS__)\n\n#define\tassert_qu_eq(a, b, ...)\tassert_cmp(unsigned long long,\t\\\n    a, b, ==, !=, \"qu\", __VA_ARGS__)\n#define\tassert_qu_ne(a, b, ...)\tassert_cmp(unsigned long long,\t\\\n    a, b, !=, ==, \"qu\", __VA_ARGS__)\n#define\tassert_qu_lt(a, b, ...)\tassert_cmp(unsigned long long,\t\\\n    a, b, <, >=, \"qu\", __VA_ARGS__)\n#define\tassert_qu_le(a, b, ...)\tassert_cmp(unsigned long long,\t\\\n    a, b, <=, >, \"qu\", __VA_ARGS__)\n#define\tassert_qu_ge(a, b, ...)\tassert_cmp(unsigned long long,\t\\\n    a, b, >=, <, \"qu\", __VA_ARGS__)\n#define\tassert_qu_gt(a, b, ...)\tassert_cmp(unsigned long long,\t\\\n    a, b, >, <=, \"qu\", __VA_ARGS__)\n\n#define\tassert_jd_eq(a, b, ...)\tassert_cmp(intmax_t, a, b, ==,\t\\\n    !=, \"jd\", __VA_ARGS__)\n#define\tassert_jd_ne(a, b, ...)\tassert_cmp(intmax_t, a, b, !=,\t\\\n    ==, \"jd\", __VA_ARGS__)\n#define\tassert_jd_lt(a, b, ...)\tassert_cmp(intmax_t, a, b, <,\t\\\n    >=, \"jd\", __VA_ARGS__)\n#define\tassert_jd_le(a, b, ...)\tassert_cmp(intmax_t, a, b, <=,\t\\\n    >, \"jd\", __VA_ARGS__)\n#define\tassert_jd_ge(a, b, ...)\tassert_cmp(intmax_t, a, b, >=,\t\\\n    <, \"jd\", __VA_ARGS__)\n#define\tassert_jd_gt(a, b, ...)\tassert_cmp(intmax_t, a, b, >,\t\\\n    <=, \"jd\", __VA_ARGS__)\n\n#define\tassert_ju_eq(a, b, ...)\tassert_cmp(uintmax_t, a, b, ==,\t\\\n    !=, \"ju\", __VA_ARGS__)\n#define\tassert_ju_ne(a, b, ...)\tassert_cmp(uintmax_t, a, b, !=,\t\\\n    ==, \"ju\", __VA_ARGS__)\n#define\tassert_ju_lt(a, b, ...)\tassert_cmp(uintmax_t, a, b, <,\t\\\n    >=, \"ju\", __VA_ARGS__)\n#define\tassert_ju_le(a, b, ...)\tassert_cmp(uintmax_t, a, b, <=,\t\\\n    >, \"ju\", __VA_ARGS__)\n#define\tassert_ju_ge(a, b, ...)\tassert_cmp(uintmax_t, a, b, >=,\t\\\n    <, \"ju\", __VA_ARGS__)\n#define\tassert_ju_gt(a, b, ...)\tassert_cmp(uintmax_t, a, b, >,\t\\\n    <=, \"ju\", __VA_ARGS__)\n\n#define\tassert_zd_eq(a, b, ...)\tassert_cmp(ssize_t, a, b, ==,\t\\\n    !=, \"zd\", __VA_ARGS__)\n#define\tassert_zd_ne(a, b, ...)\tassert_cmp(ssize_t, a, b, !=,\t\\\n    ==, \"zd\", __VA_ARGS__)\n#define\tassert_zd_lt(a, b, ...)\tassert_cmp(ssize_t, a, b, <,\t\\\n    >=, \"zd\", __VA_ARGS__)\n#define\tassert_zd_le(a, b, ...)\tassert_cmp(ssize_t, a, b, <=,\t\\\n    >, \"zd\", __VA_ARGS__)\n#define\tassert_zd_ge(a, b, ...)\tassert_cmp(ssize_t, a, b, >=,\t\\\n    <, \"zd\", __VA_ARGS__)\n#define\tassert_zd_gt(a, b, ...)\tassert_cmp(ssize_t, a, b, >,\t\\\n    <=, \"zd\", __VA_ARGS__)\n\n#define\tassert_zu_eq(a, b, ...)\tassert_cmp(size_t, a, b, ==,\t\\\n    !=, \"zu\", __VA_ARGS__)\n#define\tassert_zu_ne(a, b, ...)\tassert_cmp(size_t, a, b, !=,\t\\\n    ==, \"zu\", __VA_ARGS__)\n#define\tassert_zu_lt(a, b, ...)\tassert_cmp(size_t, a, b, <,\t\\\n    >=, \"zu\", __VA_ARGS__)\n#define\tassert_zu_le(a, b, ...)\tassert_cmp(size_t, a, b, <=,\t\\\n    >, \"zu\", __VA_ARGS__)\n#define\tassert_zu_ge(a, b, ...)\tassert_cmp(size_t, a, b, >=,\t\\\n    <, \"zu\", __VA_ARGS__)\n#define\tassert_zu_gt(a, b, ...)\tassert_cmp(size_t, a, b, >,\t\\\n    <=, \"zu\", __VA_ARGS__)\n\n#define\tassert_d32_eq(a, b, ...)\tassert_cmp(int32_t, a, b, ==,\t\\\n    !=, FMTd32, __VA_ARGS__)\n#define\tassert_d32_ne(a, b, ...)\tassert_cmp(int32_t, a, b, !=,\t\\\n    ==, FMTd32, __VA_ARGS__)\n#define\tassert_d32_lt(a, b, ...)\tassert_cmp(int32_t, a, b, <,\t\\\n    >=, FMTd32, __VA_ARGS__)\n#define\tassert_d32_le(a, b, ...)\tassert_cmp(int32_t, a, b, <=,\t\\\n    >, FMTd32, __VA_ARGS__)\n#define\tassert_d32_ge(a, b, ...)\tassert_cmp(int32_t, a, b, >=,\t\\\n    <, FMTd32, __VA_ARGS__)\n#define\tassert_d32_gt(a, b, ...)\tassert_cmp(int32_t, a, b, >,\t\\\n    <=, FMTd32, __VA_ARGS__)\n\n#define\tassert_u32_eq(a, b, ...)\tassert_cmp(uint32_t, a, b, ==,\t\\\n    !=, FMTu32, __VA_ARGS__)\n#define\tassert_u32_ne(a, b, ...)\tassert_cmp(uint32_t, a, b, !=,\t\\\n    ==, FMTu32, __VA_ARGS__)\n#define\tassert_u32_lt(a, b, ...)\tassert_cmp(uint32_t, a, b, <,\t\\\n    >=, FMTu32, __VA_ARGS__)\n#define\tassert_u32_le(a, b, ...)\tassert_cmp(uint32_t, a, b, <=,\t\\\n    >, FMTu32, __VA_ARGS__)\n#define\tassert_u32_ge(a, b, ...)\tassert_cmp(uint32_t, a, b, >=,\t\\\n    <, FMTu32, __VA_ARGS__)\n#define\tassert_u32_gt(a, b, ...)\tassert_cmp(uint32_t, a, b, >,\t\\\n    <=, FMTu32, __VA_ARGS__)\n\n#define\tassert_d64_eq(a, b, ...)\tassert_cmp(int64_t, a, b, ==,\t\\\n    !=, FMTd64, __VA_ARGS__)\n#define\tassert_d64_ne(a, b, ...)\tassert_cmp(int64_t, a, b, !=,\t\\\n    ==, FMTd64, __VA_ARGS__)\n#define\tassert_d64_lt(a, b, ...)\tassert_cmp(int64_t, a, b, <,\t\\\n    >=, FMTd64, __VA_ARGS__)\n#define\tassert_d64_le(a, b, ...)\tassert_cmp(int64_t, a, b, <=,\t\\\n    >, FMTd64, __VA_ARGS__)\n#define\tassert_d64_ge(a, b, ...)\tassert_cmp(int64_t, a, b, >=,\t\\\n    <, FMTd64, __VA_ARGS__)\n#define\tassert_d64_gt(a, b, ...)\tassert_cmp(int64_t, a, b, >,\t\\\n    <=, FMTd64, __VA_ARGS__)\n\n#define\tassert_u64_eq(a, b, ...)\tassert_cmp(uint64_t, a, b, ==,\t\\\n    !=, FMTu64, __VA_ARGS__)\n#define\tassert_u64_ne(a, b, ...)\tassert_cmp(uint64_t, a, b, !=,\t\\\n    ==, FMTu64, __VA_ARGS__)\n#define\tassert_u64_lt(a, b, ...)\tassert_cmp(uint64_t, a, b, <,\t\\\n    >=, FMTu64, __VA_ARGS__)\n#define\tassert_u64_le(a, b, ...)\tassert_cmp(uint64_t, a, b, <=,\t\\\n    >, FMTu64, __VA_ARGS__)\n#define\tassert_u64_ge(a, b, ...)\tassert_cmp(uint64_t, a, b, >=,\t\\\n    <, FMTu64, __VA_ARGS__)\n#define\tassert_u64_gt(a, b, ...)\tassert_cmp(uint64_t, a, b, >,\t\\\n    <=, FMTu64, __VA_ARGS__)\n\n#define\tassert_b_eq(a, b, ...) do {\t\t\t\t\t\\\n\tbool a_ = (a);\t\t\t\t\t\t\t\\\n\tbool b_ = (b);\t\t\t\t\t\t\t\\\n\tif (!(a_ == b_)) {\t\t\t\t\t\t\\\n\t\tchar prefix[ASSERT_BUFSIZE];\t\t\t\t\\\n\t\tchar message[ASSERT_BUFSIZE];\t\t\t\t\\\n\t\tmalloc_snprintf(prefix, sizeof(prefix),\t\t\t\\\n\t\t    \"%s:%s:%d: Failed assertion: \"\t\t\t\\\n\t\t    \"(%s) == (%s) --> %s != %s: \",\t\t\t\\\n\t\t    __func__, __FILE__, __LINE__,\t\t\t\\\n\t\t    #a, #b, a_ ? \"true\" : \"false\",\t\t\t\\\n\t\t    b_ ? \"true\" : \"false\");\t\t\t\t\\\n\t\tmalloc_snprintf(message, sizeof(message), __VA_ARGS__);\t\\\n\t\tp_test_fail(prefix, message);\t\t\t\t\\\n\t}\t\t\t\t\t\t\t\t\\\n} while (0)\n#define\tassert_b_ne(a, b, ...) do {\t\t\t\t\t\\\n\tbool a_ = (a);\t\t\t\t\t\t\t\\\n\tbool b_ = (b);\t\t\t\t\t\t\t\\\n\tif (!(a_ != b_)) {\t\t\t\t\t\t\\\n\t\tchar prefix[ASSERT_BUFSIZE];\t\t\t\t\\\n\t\tchar message[ASSERT_BUFSIZE];\t\t\t\t\\\n\t\tmalloc_snprintf(prefix, sizeof(prefix),\t\t\t\\\n\t\t    \"%s:%s:%d: Failed assertion: \"\t\t\t\\\n\t\t    \"(%s) != (%s) --> %s == %s: \",\t\t\t\\\n\t\t    __func__, __FILE__, __LINE__,\t\t\t\\\n\t\t    #a, #b, a_ ? \"true\" : \"false\",\t\t\t\\\n\t\t    b_ ? \"true\" : \"false\");\t\t\t\t\\\n\t\tmalloc_snprintf(message, sizeof(message), __VA_ARGS__);\t\\\n\t\tp_test_fail(prefix, message);\t\t\t\t\\\n\t}\t\t\t\t\t\t\t\t\\\n} while (0)\n#define\tassert_true(a, ...)\tassert_b_eq(a, true, __VA_ARGS__)\n#define\tassert_false(a, ...)\tassert_b_eq(a, false, __VA_ARGS__)\n\n#define\tassert_str_eq(a, b, ...) do {\t\t\t\t\\\n\tif (strcmp((a), (b))) {\t\t\t\t\t\t\\\n\t\tchar prefix[ASSERT_BUFSIZE];\t\t\t\t\\\n\t\tchar message[ASSERT_BUFSIZE];\t\t\t\t\\\n\t\tmalloc_snprintf(prefix, sizeof(prefix),\t\t\t\\\n\t\t    \"%s:%s:%d: Failed assertion: \"\t\t\t\\\n\t\t    \"(%s) same as (%s) --> \"\t\t\t\t\\\n\t\t    \"\\\"%s\\\" differs from \\\"%s\\\": \",\t\t\t\\\n\t\t    __func__, __FILE__, __LINE__, #a, #b, a, b);\t\\\n\t\tmalloc_snprintf(message, sizeof(message), __VA_ARGS__);\t\\\n\t\tp_test_fail(prefix, message);\t\t\t\t\\\n\t}\t\t\t\t\t\t\t\t\\\n} while (0)\n#define\tassert_str_ne(a, b, ...) do {\t\t\t\t\\\n\tif (!strcmp((a), (b))) {\t\t\t\t\t\\\n\t\tchar prefix[ASSERT_BUFSIZE];\t\t\t\t\\\n\t\tchar message[ASSERT_BUFSIZE];\t\t\t\t\\\n\t\tmalloc_snprintf(prefix, sizeof(prefix),\t\t\t\\\n\t\t    \"%s:%s:%d: Failed assertion: \"\t\t\t\\\n\t\t    \"(%s) differs from (%s) --> \"\t\t\t\\\n\t\t    \"\\\"%s\\\" same as \\\"%s\\\": \",\t\t\t\t\\\n\t\t    __func__, __FILE__, __LINE__, #a, #b, a, b);\t\\\n\t\tmalloc_snprintf(message, sizeof(message), __VA_ARGS__);\t\\\n\t\tp_test_fail(prefix, message);\t\t\t\t\\\n\t}\t\t\t\t\t\t\t\t\\\n} while (0)\n\n#define\tassert_not_reached(...) do {\t\t\t\t\t\\\n\tchar prefix[ASSERT_BUFSIZE];\t\t\t\t\t\\\n\tchar message[ASSERT_BUFSIZE];\t\t\t\t\t\\\n\tmalloc_snprintf(prefix, sizeof(prefix),\t\t\t\t\\\n\t    \"%s:%s:%d: Unreachable code reached: \",\t\t\t\\\n\t    __func__, __FILE__, __LINE__);\t\t\t\t\\\n\tmalloc_snprintf(message, sizeof(message), __VA_ARGS__);\t\t\\\n\tp_test_fail(prefix, message);\t\t\t\t\t\\\n} while (0)\n\n/*\n * If this enum changes, corresponding changes in test/test.sh.in are also\n * necessary.\n */\ntypedef enum {\n\ttest_status_pass = 0,\n\ttest_status_skip = 1,\n\ttest_status_fail = 2,\n\n\ttest_status_count = 3\n} test_status_t;\n\ntypedef void (test_t)(void);\n\n#define\tTEST_BEGIN(f)\t\t\t\t\t\t\t\\\nstatic void\t\t\t\t\t\t\t\t\\\nf(void)\t\t\t\t\t\t\t\t\t\\\n{\t\t\t\t\t\t\t\t\t\\\n\tp_test_init(#f);\n\n#define\tTEST_END\t\t\t\t\t\t\t\\\n\tgoto label_test_end;\t\t\t\t\t\t\\\nlabel_test_end:\t\t\t\t\t\t\t\t\\\n\tp_test_fini();\t\t\t\t\t\t\t\\\n}\n\n#define\ttest(...)\t\t\t\t\t\t\t\\\n\tp_test(__VA_ARGS__, NULL)\n\n#define\ttest_no_malloc_init(...)\t\t\t\t\t\\\n\tp_test_no_malloc_init(__VA_ARGS__, NULL)\n\n#define\ttest_skip_if(e) do {\t\t\t\t\t\t\\\n\tif (e) {\t\t\t\t\t\t\t\\\n\t\ttest_skip(\"%s:%s:%d: Test skipped: (%s)\",\t\t\\\n\t\t    __func__, __FILE__, __LINE__, #e);\t\t\t\\\n\t\tgoto label_test_end;\t\t\t\t\t\\\n\t}\t\t\t\t\t\t\t\t\\\n} while (0)\n\nvoid\ttest_skip(const char *format, ...) JEMALLOC_FORMAT_PRINTF(1, 2);\nvoid\ttest_fail(const char *format, ...) JEMALLOC_FORMAT_PRINTF(1, 2);\n\n/* For private use by macros. */\ntest_status_t\tp_test(test_t *t, ...);\ntest_status_t\tp_test_no_malloc_init(test_t *t, ...);\nvoid\tp_test_init(const char *name);\nvoid\tp_test_fini(void);\nvoid\tp_test_fail(const char *prefix, const char *message);\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/deps/jemalloc/test/include/test/thd.h",
    "content": "/* Abstraction layer for threading in tests. */\n#ifdef _WIN32\ntypedef HANDLE thd_t;\n#else\ntypedef pthread_t thd_t;\n#endif\n\nvoid\tthd_create(thd_t *thd, void *(*proc)(void *), void *arg);\nvoid\tthd_join(thd_t thd, void **ret);\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/deps/jemalloc/test/include/test/timer.h",
    "content": "/* Simple timer, for use in benchmark reporting. */\n\ntypedef struct {\n\tnstime_t t0;\n\tnstime_t t1;\n} timedelta_t;\n\nvoid\ttimer_start(timedelta_t *timer);\nvoid\ttimer_stop(timedelta_t *timer);\nuint64_t\ttimer_usec(const timedelta_t *timer);\nvoid\ttimer_ratio(timedelta_t *a, timedelta_t *b, char *buf, size_t buflen);\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/deps/jemalloc/test/integration/MALLOCX_ARENA.c",
    "content": "#include \"test/jemalloc_test.h\"\n\n#define\tNTHREADS 10\n\nstatic bool have_dss =\n#ifdef JEMALLOC_DSS\n    true\n#else\n    false\n#endif\n    ;\n\nvoid *\nthd_start(void *arg)\n{\n\tunsigned thread_ind = (unsigned)(uintptr_t)arg;\n\tunsigned arena_ind;\n\tvoid *p;\n\tsize_t sz;\n\n\tsz = sizeof(arena_ind);\n\tassert_d_eq(mallctl(\"arenas.extend\", &arena_ind, &sz, NULL, 0), 0,\n\t    \"Error in arenas.extend\");\n\n\tif (thread_ind % 4 != 3) {\n\t\tsize_t mib[3];\n\t\tsize_t miblen = sizeof(mib) / sizeof(size_t);\n\t\tconst char *dss_precs[] = {\"disabled\", \"primary\", \"secondary\"};\n\t\tunsigned prec_ind = thread_ind %\n\t\t    (sizeof(dss_precs)/sizeof(char*));\n\t\tconst char *dss = dss_precs[prec_ind];\n\t\tint expected_err = (have_dss || prec_ind == 0) ? 0 : EFAULT;\n\t\tassert_d_eq(mallctlnametomib(\"arena.0.dss\", mib, &miblen), 0,\n\t\t    \"Error in mallctlnametomib()\");\n\t\tmib[1] = arena_ind;\n\t\tassert_d_eq(mallctlbymib(mib, miblen, NULL, NULL, (void *)&dss,\n\t\t    sizeof(const char *)), expected_err,\n\t\t    \"Error in mallctlbymib()\");\n\t}\n\n\tp = mallocx(1, MALLOCX_ARENA(arena_ind));\n\tassert_ptr_not_null(p, \"Unexpected mallocx() error\");\n\tdallocx(p, 0);\n\n\treturn (NULL);\n}\n\nTEST_BEGIN(test_MALLOCX_ARENA)\n{\n\tthd_t thds[NTHREADS];\n\tunsigned i;\n\n\tfor (i = 0; i < NTHREADS; i++) {\n\t\tthd_create(&thds[i], thd_start,\n\t\t    (void *)(uintptr_t)i);\n\t}\n\n\tfor (i = 0; i < NTHREADS; i++)\n\t\tthd_join(thds[i], NULL);\n}\nTEST_END\n\nint\nmain(void)\n{\n\n\treturn (test(\n\t    test_MALLOCX_ARENA));\n}\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/deps/jemalloc/test/integration/aligned_alloc.c",
    "content": "#include \"test/jemalloc_test.h\"\n\n#define\tCHUNK 0x400000\n/* #define MAXALIGN ((size_t)UINT64_C(0x80000000000)) */\n#define\tMAXALIGN ((size_t)0x2000000LU)\n#define\tNITER 4\n\nTEST_BEGIN(test_alignment_errors)\n{\n\tsize_t alignment;\n\tvoid *p;\n\n\talignment = 0;\n\tset_errno(0);\n\tp = aligned_alloc(alignment, 1);\n\tassert_false(p != NULL || get_errno() != EINVAL,\n\t    \"Expected error for invalid alignment %zu\", alignment);\n\n\tfor (alignment = sizeof(size_t); alignment < MAXALIGN;\n\t    alignment <<= 1) {\n\t\tset_errno(0);\n\t\tp = aligned_alloc(alignment + 1, 1);\n\t\tassert_false(p != NULL || get_errno() != EINVAL,\n\t\t    \"Expected error for invalid alignment %zu\",\n\t\t    alignment + 1);\n\t}\n}\nTEST_END\n\nTEST_BEGIN(test_oom_errors)\n{\n\tsize_t alignment, size;\n\tvoid *p;\n\n#if LG_SIZEOF_PTR == 3\n\talignment = UINT64_C(0x8000000000000000);\n\tsize      = UINT64_C(0x8000000000000000);\n#else\n\talignment = 0x80000000LU;\n\tsize      = 0x80000000LU;\n#endif\n\tset_errno(0);\n\tp = aligned_alloc(alignment, size);\n\tassert_false(p != NULL || get_errno() != ENOMEM,\n\t    \"Expected error for aligned_alloc(%zu, %zu)\",\n\t    alignment, size);\n\n#if LG_SIZEOF_PTR == 3\n\talignment = UINT64_C(0x4000000000000000);\n\tsize      = UINT64_C(0xc000000000000001);\n#else\n\talignment = 0x40000000LU;\n\tsize      = 0xc0000001LU;\n#endif\n\tset_errno(0);\n\tp = aligned_alloc(alignment, size);\n\tassert_false(p != NULL || get_errno() != ENOMEM,\n\t    \"Expected error for aligned_alloc(%zu, %zu)\",\n\t    alignment, size);\n\n\talignment = 0x10LU;\n#if LG_SIZEOF_PTR == 3\n\tsize = UINT64_C(0xfffffffffffffff0);\n#else\n\tsize = 0xfffffff0LU;\n#endif\n\tset_errno(0);\n\tp = aligned_alloc(alignment, size);\n\tassert_false(p != NULL || get_errno() != ENOMEM,\n\t    \"Expected error for aligned_alloc(&p, %zu, %zu)\",\n\t    alignment, size);\n}\nTEST_END\n\nTEST_BEGIN(test_alignment_and_size)\n{\n\tsize_t alignment, size, total;\n\tunsigned i;\n\tvoid *ps[NITER];\n\n\tfor (i = 0; i < NITER; i++)\n\t\tps[i] = NULL;\n\n\tfor (alignment = 8;\n\t    alignment <= MAXALIGN;\n\t    alignment <<= 1) {\n\t\ttotal = 0;\n\t\tfor (size = 1;\n\t\t    size < 3 * alignment && size < (1U << 31);\n\t\t    size += (alignment >> (LG_SIZEOF_PTR-1)) - 1) {\n\t\t\tfor (i = 0; i < NITER; i++) {\n\t\t\t\tps[i] = aligned_alloc(alignment, size);\n\t\t\t\tif (ps[i] == NULL) {\n\t\t\t\t\tchar buf[BUFERROR_BUF];\n\n\t\t\t\t\tbuferror(get_errno(), buf, sizeof(buf));\n\t\t\t\t\ttest_fail(\n\t\t\t\t\t    \"Error for alignment=%zu, \"\n\t\t\t\t\t    \"size=%zu (%#zx): %s\",\n\t\t\t\t\t    alignment, size, size, buf);\n\t\t\t\t}\n\t\t\t\ttotal += malloc_usable_size(ps[i]);\n\t\t\t\tif (total >= (MAXALIGN << 1))\n\t\t\t\t\tbreak;\n\t\t\t}\n\t\t\tfor (i = 0; i < NITER; i++) {\n\t\t\t\tif (ps[i] != NULL) {\n\t\t\t\t\tfree(ps[i]);\n\t\t\t\t\tps[i] = NULL;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}\nTEST_END\n\nint\nmain(void)\n{\n\n\treturn (test(\n\t    test_alignment_errors,\n\t    test_oom_errors,\n\t    test_alignment_and_size));\n}\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/deps/jemalloc/test/integration/allocated.c",
    "content": "#include \"test/jemalloc_test.h\"\n\nstatic const bool config_stats =\n#ifdef JEMALLOC_STATS\n    true\n#else\n    false\n#endif\n    ;\n\nvoid *\nthd_start(void *arg)\n{\n\tint err;\n\tvoid *p;\n\tuint64_t a0, a1, d0, d1;\n\tuint64_t *ap0, *ap1, *dp0, *dp1;\n\tsize_t sz, usize;\n\n\tsz = sizeof(a0);\n\tif ((err = mallctl(\"thread.allocated\", &a0, &sz, NULL, 0))) {\n\t\tif (err == ENOENT)\n\t\t\tgoto label_ENOENT;\n\t\ttest_fail(\"%s(): Error in mallctl(): %s\", __func__,\n\t\t    strerror(err));\n\t}\n\tsz = sizeof(ap0);\n\tif ((err = mallctl(\"thread.allocatedp\", &ap0, &sz, NULL, 0))) {\n\t\tif (err == ENOENT)\n\t\t\tgoto label_ENOENT;\n\t\ttest_fail(\"%s(): Error in mallctl(): %s\", __func__,\n\t\t    strerror(err));\n\t}\n\tassert_u64_eq(*ap0, a0,\n\t    \"\\\"thread.allocatedp\\\" should provide a pointer to internal \"\n\t    \"storage\");\n\n\tsz = sizeof(d0);\n\tif ((err = mallctl(\"thread.deallocated\", &d0, &sz, NULL, 0))) {\n\t\tif (err == ENOENT)\n\t\t\tgoto label_ENOENT;\n\t\ttest_fail(\"%s(): Error in mallctl(): %s\", __func__,\n\t\t    strerror(err));\n\t}\n\tsz = sizeof(dp0);\n\tif ((err = mallctl(\"thread.deallocatedp\", &dp0, &sz, NULL, 0))) {\n\t\tif (err == ENOENT)\n\t\t\tgoto label_ENOENT;\n\t\ttest_fail(\"%s(): Error in mallctl(): %s\", __func__,\n\t\t    strerror(err));\n\t}\n\tassert_u64_eq(*dp0, d0,\n\t    \"\\\"thread.deallocatedp\\\" should provide a pointer to internal \"\n\t    \"storage\");\n\n\tp = malloc(1);\n\tassert_ptr_not_null(p, \"Unexpected malloc() error\");\n\n\tsz = sizeof(a1);\n\tmallctl(\"thread.allocated\", &a1, &sz, NULL, 0);\n\tsz = sizeof(ap1);\n\tmallctl(\"thread.allocatedp\", &ap1, &sz, NULL, 0);\n\tassert_u64_eq(*ap1, a1,\n\t    \"Dereferenced \\\"thread.allocatedp\\\" value should equal \"\n\t    \"\\\"thread.allocated\\\" value\");\n\tassert_ptr_eq(ap0, ap1,\n\t    \"Pointer returned by \\\"thread.allocatedp\\\" should not change\");\n\n\tusize = malloc_usable_size(p);\n\tassert_u64_le(a0 + usize, a1,\n\t    \"Allocated memory counter should increase by at least the amount \"\n\t    \"explicitly allocated\");\n\n\tfree(p);\n\n\tsz = sizeof(d1);\n\tmallctl(\"thread.deallocated\", &d1, &sz, NULL, 0);\n\tsz = sizeof(dp1);\n\tmallctl(\"thread.deallocatedp\", &dp1, &sz, NULL, 0);\n\tassert_u64_eq(*dp1, d1,\n\t    \"Dereferenced \\\"thread.deallocatedp\\\" value should equal \"\n\t    \"\\\"thread.deallocated\\\" value\");\n\tassert_ptr_eq(dp0, dp1,\n\t    \"Pointer returned by \\\"thread.deallocatedp\\\" should not change\");\n\n\tassert_u64_le(d0 + usize, d1,\n\t    \"Deallocated memory counter should increase by at least the amount \"\n\t    \"explicitly deallocated\");\n\n\treturn (NULL);\nlabel_ENOENT:\n\tassert_false(config_stats,\n\t    \"ENOENT should only be returned if stats are disabled\");\n\ttest_skip(\"\\\"thread.allocated\\\" mallctl not available\");\n\treturn (NULL);\n}\n\nTEST_BEGIN(test_main_thread)\n{\n\n\tthd_start(NULL);\n}\nTEST_END\n\nTEST_BEGIN(test_subthread)\n{\n\tthd_t thd;\n\n\tthd_create(&thd, thd_start, NULL);\n\tthd_join(thd, NULL);\n}\nTEST_END\n\nint\nmain(void)\n{\n\n\t/* Run tests multiple times to check for bad interactions. */\n\treturn (test(\n\t    test_main_thread,\n\t    test_subthread,\n\t    test_main_thread,\n\t    test_subthread,\n\t    test_main_thread));\n}\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/deps/jemalloc/test/integration/chunk.c",
    "content": "#include \"test/jemalloc_test.h\"\n\n#ifdef JEMALLOC_FILL\nconst char *malloc_conf = \"junk:false\";\n#endif\n\nstatic chunk_hooks_t orig_hooks;\nstatic chunk_hooks_t old_hooks;\n\nstatic bool do_dalloc = true;\nstatic bool do_decommit;\n\nstatic bool did_alloc;\nstatic bool did_dalloc;\nstatic bool did_commit;\nstatic bool did_decommit;\nstatic bool did_purge;\nstatic bool did_split;\nstatic bool did_merge;\n\n#if 0\n#  define TRACE_HOOK(fmt, ...) malloc_printf(fmt, __VA_ARGS__)\n#else\n#  define TRACE_HOOK(fmt, ...)\n#endif\n\nvoid *\nchunk_alloc(void *new_addr, size_t size, size_t alignment, bool *zero,\n    bool *commit, unsigned arena_ind)\n{\n\n\tTRACE_HOOK(\"%s(new_addr=%p, size=%zu, alignment=%zu, *zero=%s, \"\n\t    \"*commit=%s, arena_ind=%u)\\n\", __func__, new_addr, size, alignment,\n\t    *zero ?  \"true\" : \"false\", *commit ? \"true\" : \"false\", arena_ind);\n\tdid_alloc = true;\n\treturn (old_hooks.alloc(new_addr, size, alignment, zero, commit,\n\t    arena_ind));\n}\n\nbool\nchunk_dalloc(void *chunk, size_t size, bool committed, unsigned arena_ind)\n{\n\n\tTRACE_HOOK(\"%s(chunk=%p, size=%zu, committed=%s, arena_ind=%u)\\n\",\n\t    __func__, chunk, size, committed ? \"true\" : \"false\", arena_ind);\n\tdid_dalloc = true;\n\tif (!do_dalloc)\n\t\treturn (true);\n\treturn (old_hooks.dalloc(chunk, size, committed, arena_ind));\n}\n\nbool\nchunk_commit(void *chunk, size_t size, size_t offset, size_t length,\n    unsigned arena_ind)\n{\n\tbool err;\n\n\tTRACE_HOOK(\"%s(chunk=%p, size=%zu, offset=%zu, length=%zu, \"\n\t    \"arena_ind=%u)\\n\", __func__, chunk, size, offset, length,\n\t    arena_ind);\n\terr = old_hooks.commit(chunk, size, offset, length, arena_ind);\n\tdid_commit = !err;\n\treturn (err);\n}\n\nbool\nchunk_decommit(void *chunk, size_t size, size_t offset, size_t length,\n    unsigned arena_ind)\n{\n\tbool err;\n\n\tTRACE_HOOK(\"%s(chunk=%p, size=%zu, offset=%zu, length=%zu, \"\n\t    \"arena_ind=%u)\\n\", __func__, chunk, size, offset, length,\n\t    arena_ind);\n\tif (!do_decommit)\n\t\treturn (true);\n\terr = old_hooks.decommit(chunk, size, offset, length, arena_ind);\n\tdid_decommit = !err;\n\treturn (err);\n}\n\nbool\nchunk_purge(void *chunk, size_t size, size_t offset, size_t length,\n    unsigned arena_ind)\n{\n\n\tTRACE_HOOK(\"%s(chunk=%p, size=%zu, offset=%zu, length=%zu \"\n\t    \"arena_ind=%u)\\n\", __func__, chunk, size, offset, length,\n\t    arena_ind);\n\tdid_purge = true;\n\treturn (old_hooks.purge(chunk, size, offset, length, arena_ind));\n}\n\nbool\nchunk_split(void *chunk, size_t size, size_t size_a, size_t size_b,\n    bool committed, unsigned arena_ind)\n{\n\n\tTRACE_HOOK(\"%s(chunk=%p, size=%zu, size_a=%zu, size_b=%zu, \"\n\t    \"committed=%s, arena_ind=%u)\\n\", __func__, chunk, size, size_a,\n\t    size_b, committed ? \"true\" : \"false\", arena_ind);\n\tdid_split = true;\n\treturn (old_hooks.split(chunk, size, size_a, size_b, committed,\n\t    arena_ind));\n}\n\nbool\nchunk_merge(void *chunk_a, size_t size_a, void *chunk_b, size_t size_b,\n    bool committed, unsigned arena_ind)\n{\n\n\tTRACE_HOOK(\"%s(chunk_a=%p, size_a=%zu, chunk_b=%p size_b=%zu, \"\n\t    \"committed=%s, arena_ind=%u)\\n\", __func__, chunk_a, size_a, chunk_b,\n\t    size_b, committed ? \"true\" : \"false\", arena_ind);\n\tdid_merge = true;\n\treturn (old_hooks.merge(chunk_a, size_a, chunk_b, size_b,\n\t    committed, arena_ind));\n}\n\nTEST_BEGIN(test_chunk)\n{\n\tvoid *p;\n\tsize_t old_size, new_size, large0, large1, huge0, huge1, huge2, sz;\n\tunsigned arena_ind;\n\tint flags;\n\tsize_t hooks_mib[3], purge_mib[3];\n\tsize_t hooks_miblen, purge_miblen;\n\tchunk_hooks_t new_hooks = {\n\t\tchunk_alloc,\n\t\tchunk_dalloc,\n\t\tchunk_commit,\n\t\tchunk_decommit,\n\t\tchunk_purge,\n\t\tchunk_split,\n\t\tchunk_merge\n\t};\n\tbool xallocx_success_a, xallocx_success_b, xallocx_success_c;\n\n\tsz = sizeof(unsigned);\n\tassert_d_eq(mallctl(\"arenas.extend\", &arena_ind, &sz, NULL, 0), 0,\n\t    \"Unexpected mallctl() failure\");\n\tflags = MALLOCX_ARENA(arena_ind) | MALLOCX_TCACHE_NONE;\n\n\t/* Install custom chunk hooks. */\n\thooks_miblen = sizeof(hooks_mib)/sizeof(size_t);\n\tassert_d_eq(mallctlnametomib(\"arena.0.chunk_hooks\", hooks_mib,\n\t    &hooks_miblen), 0, \"Unexpected mallctlnametomib() failure\");\n\thooks_mib[1] = (size_t)arena_ind;\n\told_size = sizeof(chunk_hooks_t);\n\tnew_size = sizeof(chunk_hooks_t);\n\tassert_d_eq(mallctlbymib(hooks_mib, hooks_miblen, &old_hooks, &old_size,\n\t    &new_hooks, new_size), 0, \"Unexpected chunk_hooks error\");\n\torig_hooks = old_hooks;\n\tassert_ptr_ne(old_hooks.alloc, chunk_alloc, \"Unexpected alloc error\");\n\tassert_ptr_ne(old_hooks.dalloc, chunk_dalloc,\n\t    \"Unexpected dalloc error\");\n\tassert_ptr_ne(old_hooks.commit, chunk_commit,\n\t    \"Unexpected commit error\");\n\tassert_ptr_ne(old_hooks.decommit, chunk_decommit,\n\t    \"Unexpected decommit error\");\n\tassert_ptr_ne(old_hooks.purge, chunk_purge, \"Unexpected purge error\");\n\tassert_ptr_ne(old_hooks.split, chunk_split, \"Unexpected split error\");\n\tassert_ptr_ne(old_hooks.merge, chunk_merge, \"Unexpected merge error\");\n\n\t/* Get large size classes. */\n\tsz = sizeof(size_t);\n\tassert_d_eq(mallctl(\"arenas.lrun.0.size\", &large0, &sz, NULL, 0), 0,\n\t    \"Unexpected arenas.lrun.0.size failure\");\n\tassert_d_eq(mallctl(\"arenas.lrun.1.size\", &large1, &sz, NULL, 0), 0,\n\t    \"Unexpected arenas.lrun.1.size failure\");\n\n\t/* Get huge size classes. */\n\tassert_d_eq(mallctl(\"arenas.hchunk.0.size\", &huge0, &sz, NULL, 0), 0,\n\t    \"Unexpected arenas.hchunk.0.size failure\");\n\tassert_d_eq(mallctl(\"arenas.hchunk.1.size\", &huge1, &sz, NULL, 0), 0,\n\t    \"Unexpected arenas.hchunk.1.size failure\");\n\tassert_d_eq(mallctl(\"arenas.hchunk.2.size\", &huge2, &sz, NULL, 0), 0,\n\t    \"Unexpected arenas.hchunk.2.size failure\");\n\n\t/* Test dalloc/decommit/purge cascade. */\n\tpurge_miblen = sizeof(purge_mib)/sizeof(size_t);\n\tassert_d_eq(mallctlnametomib(\"arena.0.purge\", purge_mib, &purge_miblen),\n\t    0, \"Unexpected mallctlnametomib() failure\");\n\tpurge_mib[1] = (size_t)arena_ind;\n\tdo_dalloc = false;\n\tdo_decommit = false;\n\tp = mallocx(huge0 * 2, flags);\n\tassert_ptr_not_null(p, \"Unexpected mallocx() error\");\n\tdid_dalloc = false;\n\tdid_decommit = false;\n\tdid_purge = false;\n\tdid_split = false;\n\txallocx_success_a = (xallocx(p, huge0, 0, flags) == huge0);\n\tassert_d_eq(mallctlbymib(purge_mib, purge_miblen, NULL, NULL, NULL, 0),\n\t    0, \"Unexpected arena.%u.purge error\", arena_ind);\n\tif (xallocx_success_a) {\n\t\tassert_true(did_dalloc, \"Expected dalloc\");\n\t\tassert_false(did_decommit, \"Unexpected decommit\");\n\t\tassert_true(did_purge, \"Expected purge\");\n\t}\n\tassert_true(did_split, \"Expected split\");\n\tdallocx(p, flags);\n\tdo_dalloc = true;\n\n\t/* Test decommit/commit and observe split/merge. */\n\tdo_dalloc = false;\n\tdo_decommit = true;\n\tp = mallocx(huge0 * 2, flags);\n\tassert_ptr_not_null(p, \"Unexpected mallocx() error\");\n\tdid_decommit = false;\n\tdid_commit = false;\n\tdid_split = false;\n\tdid_merge = false;\n\txallocx_success_b = (xallocx(p, huge0, 0, flags) == huge0);\n\tassert_d_eq(mallctlbymib(purge_mib, purge_miblen, NULL, NULL, NULL, 0),\n\t    0, \"Unexpected arena.%u.purge error\", arena_ind);\n\tif (xallocx_success_b)\n\t\tassert_true(did_split, \"Expected split\");\n\txallocx_success_c = (xallocx(p, huge0 * 2, 0, flags) == huge0 * 2);\n\tassert_b_eq(did_decommit, did_commit, \"Expected decommit/commit match\");\n\tif (xallocx_success_b && xallocx_success_c)\n\t\tassert_true(did_merge, \"Expected merge\");\n\tdallocx(p, flags);\n\tdo_dalloc = true;\n\tdo_decommit = false;\n\n\t/* Test purge for partial-chunk huge allocations. */\n\tif (huge0 * 2 > huge2) {\n\t\t/*\n\t\t * There are at least four size classes per doubling, so a\n\t\t * successful xallocx() from size=huge2 to size=huge1 is\n\t\t * guaranteed to leave trailing purgeable memory.\n\t\t */\n\t\tp = mallocx(huge2, flags);\n\t\tassert_ptr_not_null(p, \"Unexpected mallocx() error\");\n\t\tdid_purge = false;\n\t\tassert_zu_eq(xallocx(p, huge1, 0, flags), huge1,\n\t\t    \"Unexpected xallocx() failure\");\n\t\tassert_true(did_purge, \"Expected purge\");\n\t\tdallocx(p, flags);\n\t}\n\n\t/* Test decommit for large allocations. */\n\tdo_decommit = true;\n\tp = mallocx(large1, flags);\n\tassert_ptr_not_null(p, \"Unexpected mallocx() error\");\n\tassert_d_eq(mallctlbymib(purge_mib, purge_miblen, NULL, NULL, NULL, 0),\n\t    0, \"Unexpected arena.%u.purge error\", arena_ind);\n\tdid_decommit = false;\n\tassert_zu_eq(xallocx(p, large0, 0, flags), large0,\n\t    \"Unexpected xallocx() failure\");\n\tassert_d_eq(mallctlbymib(purge_mib, purge_miblen, NULL, NULL, NULL, 0),\n\t    0, \"Unexpected arena.%u.purge error\", arena_ind);\n\tdid_commit = false;\n\tassert_zu_eq(xallocx(p, large1, 0, flags), large1,\n\t    \"Unexpected xallocx() failure\");\n\tassert_b_eq(did_decommit, did_commit, \"Expected decommit/commit match\");\n\tdallocx(p, flags);\n\tdo_decommit = false;\n\n\t/* Make sure non-huge allocation succeeds. */\n\tp = mallocx(42, flags);\n\tassert_ptr_not_null(p, \"Unexpected mallocx() error\");\n\tdallocx(p, flags);\n\n\t/* Restore chunk hooks. */\n\tassert_d_eq(mallctlbymib(hooks_mib, hooks_miblen, NULL, NULL,\n\t    &old_hooks, new_size), 0, \"Unexpected chunk_hooks error\");\n\tassert_d_eq(mallctlbymib(hooks_mib, hooks_miblen, &old_hooks, &old_size,\n\t    NULL, 0), 0, \"Unexpected chunk_hooks error\");\n\tassert_ptr_eq(old_hooks.alloc, orig_hooks.alloc,\n\t    \"Unexpected alloc error\");\n\tassert_ptr_eq(old_hooks.dalloc, orig_hooks.dalloc,\n\t    \"Unexpected dalloc error\");\n\tassert_ptr_eq(old_hooks.commit, orig_hooks.commit,\n\t    \"Unexpected commit error\");\n\tassert_ptr_eq(old_hooks.decommit, orig_hooks.decommit,\n\t    \"Unexpected decommit error\");\n\tassert_ptr_eq(old_hooks.purge, orig_hooks.purge,\n\t    \"Unexpected purge error\");\n\tassert_ptr_eq(old_hooks.split, orig_hooks.split,\n\t    \"Unexpected split error\");\n\tassert_ptr_eq(old_hooks.merge, orig_hooks.merge,\n\t    \"Unexpected merge error\");\n}\nTEST_END\n\nint\nmain(void)\n{\n\n\treturn (test(test_chunk));\n}\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/deps/jemalloc/test/integration/mallocx.c",
    "content": "#include \"test/jemalloc_test.h\"\n\n#ifdef JEMALLOC_FILL\nconst char *malloc_conf = \"junk:false\";\n#endif\n\nstatic unsigned\nget_nsizes_impl(const char *cmd)\n{\n\tunsigned ret;\n\tsize_t z;\n\n\tz = sizeof(unsigned);\n\tassert_d_eq(mallctl(cmd, &ret, &z, NULL, 0), 0,\n\t    \"Unexpected mallctl(\\\"%s\\\", ...) failure\", cmd);\n\n\treturn (ret);\n}\n\nstatic unsigned\nget_nhuge(void)\n{\n\n\treturn (get_nsizes_impl(\"arenas.nhchunks\"));\n}\n\nstatic size_t\nget_size_impl(const char *cmd, size_t ind)\n{\n\tsize_t ret;\n\tsize_t z;\n\tsize_t mib[4];\n\tsize_t miblen = 4;\n\n\tz = sizeof(size_t);\n\tassert_d_eq(mallctlnametomib(cmd, mib, &miblen),\n\t    0, \"Unexpected mallctlnametomib(\\\"%s\\\", ...) failure\", cmd);\n\tmib[2] = ind;\n\tz = sizeof(size_t);\n\tassert_d_eq(mallctlbymib(mib, miblen, &ret, &z, NULL, 0),\n\t    0, \"Unexpected mallctlbymib([\\\"%s\\\", %zu], ...) failure\", cmd, ind);\n\n\treturn (ret);\n}\n\nstatic size_t\nget_huge_size(size_t ind)\n{\n\n\treturn (get_size_impl(\"arenas.hchunk.0.size\", ind));\n}\n\nTEST_BEGIN(test_overflow)\n{\n\tsize_t hugemax;\n\n\thugemax = get_huge_size(get_nhuge()-1);\n\n\tassert_ptr_null(mallocx(hugemax+1, 0),\n\t    \"Expected OOM for mallocx(size=%#zx, 0)\", hugemax+1);\n\n\tassert_ptr_null(mallocx(ZU(PTRDIFF_MAX)+1, 0),\n\t    \"Expected OOM for mallocx(size=%#zx, 0)\", ZU(PTRDIFF_MAX)+1);\n\n\tassert_ptr_null(mallocx(SIZE_T_MAX, 0),\n\t    \"Expected OOM for mallocx(size=%#zx, 0)\", SIZE_T_MAX);\n\n\tassert_ptr_null(mallocx(1, MALLOCX_ALIGN(ZU(PTRDIFF_MAX)+1)),\n\t    \"Expected OOM for mallocx(size=1, MALLOCX_ALIGN(%#zx))\",\n\t    ZU(PTRDIFF_MAX)+1);\n}\nTEST_END\n\nTEST_BEGIN(test_oom)\n{\n\tsize_t hugemax;\n\tbool oom;\n\tvoid *ptrs[3];\n\tunsigned i;\n\n\t/*\n\t * It should be impossible to allocate three objects that each consume\n\t * nearly half the virtual address space.\n\t */\n\thugemax = get_huge_size(get_nhuge()-1);\n\toom = false;\n\tfor (i = 0; i < sizeof(ptrs) / sizeof(void *); i++) {\n\t\tptrs[i] = mallocx(hugemax, 0);\n\t\tif (ptrs[i] == NULL)\n\t\t\toom = true;\n\t}\n\tassert_true(oom,\n\t    \"Expected OOM during series of calls to mallocx(size=%zu, 0)\",\n\t    hugemax);\n\tfor (i = 0; i < sizeof(ptrs) / sizeof(void *); i++) {\n\t\tif (ptrs[i] != NULL)\n\t\t\tdallocx(ptrs[i], 0);\n\t}\n\n#if LG_SIZEOF_PTR == 3\n\tassert_ptr_null(mallocx(0x8000000000000000ULL,\n\t    MALLOCX_ALIGN(0x8000000000000000ULL)),\n\t    \"Expected OOM for mallocx()\");\n\tassert_ptr_null(mallocx(0x8000000000000000ULL,\n\t    MALLOCX_ALIGN(0x80000000)),\n\t    \"Expected OOM for mallocx()\");\n#else\n\tassert_ptr_null(mallocx(0x80000000UL, MALLOCX_ALIGN(0x80000000UL)),\n\t    \"Expected OOM for mallocx()\");\n#endif\n}\nTEST_END\n\nTEST_BEGIN(test_basic)\n{\n#define\tMAXSZ (((size_t)1) << 26)\n\tsize_t sz;\n\n\tfor (sz = 1; sz < MAXSZ; sz = nallocx(sz, 0) + 1) {\n\t\tsize_t nsz, rsz;\n\t\tvoid *p;\n\t\tnsz = nallocx(sz, 0);\n\t\tassert_zu_ne(nsz, 0, \"Unexpected nallocx() error\");\n\t\tp = mallocx(sz, 0);\n\t\tassert_ptr_not_null(p, \"Unexpected mallocx() error\");\n\t\trsz = sallocx(p, 0);\n\t\tassert_zu_ge(rsz, sz, \"Real size smaller than expected\");\n\t\tassert_zu_eq(nsz, rsz, \"nallocx()/sallocx() size mismatch\");\n\t\tdallocx(p, 0);\n\n\t\tp = mallocx(sz, 0);\n\t\tassert_ptr_not_null(p, \"Unexpected mallocx() error\");\n\t\tdallocx(p, 0);\n\n\t\tnsz = nallocx(sz, MALLOCX_ZERO);\n\t\tassert_zu_ne(nsz, 0, \"Unexpected nallocx() error\");\n\t\tp = mallocx(sz, MALLOCX_ZERO);\n\t\tassert_ptr_not_null(p, \"Unexpected mallocx() error\");\n\t\trsz = sallocx(p, 0);\n\t\tassert_zu_eq(nsz, rsz, \"nallocx()/sallocx() rsize mismatch\");\n\t\tdallocx(p, 0);\n\t}\n#undef MAXSZ\n}\nTEST_END\n\nTEST_BEGIN(test_alignment_and_size)\n{\n#define\tMAXALIGN (((size_t)1) << 25)\n#define\tNITER 4\n\tsize_t nsz, rsz, sz, alignment, total;\n\tunsigned i;\n\tvoid *ps[NITER];\n\n\tfor (i = 0; i < NITER; i++)\n\t\tps[i] = NULL;\n\n\tfor (alignment = 8;\n\t    alignment <= MAXALIGN;\n\t    alignment <<= 1) {\n\t\ttotal = 0;\n\t\tfor (sz = 1;\n\t\t    sz < 3 * alignment && sz < (1U << 31);\n\t\t    sz += (alignment >> (LG_SIZEOF_PTR-1)) - 1) {\n\t\t\tfor (i = 0; i < NITER; i++) {\n\t\t\t\tnsz = nallocx(sz, MALLOCX_ALIGN(alignment) |\n\t\t\t\t    MALLOCX_ZERO);\n\t\t\t\tassert_zu_ne(nsz, 0,\n\t\t\t\t    \"nallocx() error for alignment=%zu, \"\n\t\t\t\t    \"size=%zu (%#zx)\", alignment, sz, sz);\n\t\t\t\tps[i] = mallocx(sz, MALLOCX_ALIGN(alignment) |\n\t\t\t\t    MALLOCX_ZERO);\n\t\t\t\tassert_ptr_not_null(ps[i],\n\t\t\t\t    \"mallocx() error for alignment=%zu, \"\n\t\t\t\t    \"size=%zu (%#zx)\", alignment, sz, sz);\n\t\t\t\trsz = sallocx(ps[i], 0);\n\t\t\t\tassert_zu_ge(rsz, sz,\n\t\t\t\t    \"Real size smaller than expected for \"\n\t\t\t\t    \"alignment=%zu, size=%zu\", alignment, sz);\n\t\t\t\tassert_zu_eq(nsz, rsz,\n\t\t\t\t    \"nallocx()/sallocx() size mismatch for \"\n\t\t\t\t    \"alignment=%zu, size=%zu\", alignment, sz);\n\t\t\t\tassert_ptr_null(\n\t\t\t\t    (void *)((uintptr_t)ps[i] & (alignment-1)),\n\t\t\t\t    \"%p inadequately aligned for\"\n\t\t\t\t    \" alignment=%zu, size=%zu\", ps[i],\n\t\t\t\t    alignment, sz);\n\t\t\t\ttotal += rsz;\n\t\t\t\tif (total >= (MAXALIGN << 1))\n\t\t\t\t\tbreak;\n\t\t\t}\n\t\t\tfor (i = 0; i < NITER; i++) {\n\t\t\t\tif (ps[i] != NULL) {\n\t\t\t\t\tdallocx(ps[i], 0);\n\t\t\t\t\tps[i] = NULL;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n#undef MAXALIGN\n#undef NITER\n}\nTEST_END\n\nint\nmain(void)\n{\n\n\treturn (test(\n\t    test_overflow,\n\t    test_oom,\n\t    test_basic,\n\t    test_alignment_and_size));\n}\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/deps/jemalloc/test/integration/overflow.c",
    "content": "#include \"test/jemalloc_test.h\"\n\nTEST_BEGIN(test_overflow)\n{\n\tunsigned nhchunks;\n\tsize_t mib[4];\n\tsize_t sz, miblen, max_size_class;\n\tvoid *p;\n\n\tsz = sizeof(unsigned);\n\tassert_d_eq(mallctl(\"arenas.nhchunks\", &nhchunks, &sz, NULL, 0), 0,\n\t    \"Unexpected mallctl() error\");\n\n\tmiblen = sizeof(mib) / sizeof(size_t);\n\tassert_d_eq(mallctlnametomib(\"arenas.hchunk.0.size\", mib, &miblen), 0,\n\t    \"Unexpected mallctlnametomib() error\");\n\tmib[2] = nhchunks - 1;\n\n\tsz = sizeof(size_t);\n\tassert_d_eq(mallctlbymib(mib, miblen, &max_size_class, &sz, NULL, 0), 0,\n\t    \"Unexpected mallctlbymib() error\");\n\n\tassert_ptr_null(malloc(max_size_class + 1),\n\t    \"Expected OOM due to over-sized allocation request\");\n\tassert_ptr_null(malloc(SIZE_T_MAX),\n\t    \"Expected OOM due to over-sized allocation request\");\n\n\tassert_ptr_null(calloc(1, max_size_class + 1),\n\t    \"Expected OOM due to over-sized allocation request\");\n\tassert_ptr_null(calloc(1, SIZE_T_MAX),\n\t    \"Expected OOM due to over-sized allocation request\");\n\n\tp = malloc(1);\n\tassert_ptr_not_null(p, \"Unexpected malloc() OOM\");\n\tassert_ptr_null(realloc(p, max_size_class + 1),\n\t    \"Expected OOM due to over-sized allocation request\");\n\tassert_ptr_null(realloc(p, SIZE_T_MAX),\n\t    \"Expected OOM due to over-sized allocation request\");\n\tfree(p);\n}\nTEST_END\n\nint\nmain(void)\n{\n\n\treturn (test(\n\t    test_overflow));\n}\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/deps/jemalloc/test/integration/posix_memalign.c",
    "content": "#include \"test/jemalloc_test.h\"\n\n#define\tCHUNK 0x400000\n/* #define MAXALIGN ((size_t)UINT64_C(0x80000000000)) */\n#define\tMAXALIGN ((size_t)0x2000000LU)\n#define\tNITER 4\n\nTEST_BEGIN(test_alignment_errors)\n{\n\tsize_t alignment;\n\tvoid *p;\n\n\tfor (alignment = 0; alignment < sizeof(void *); alignment++) {\n\t\tassert_d_eq(posix_memalign(&p, alignment, 1), EINVAL,\n\t\t    \"Expected error for invalid alignment %zu\",\n\t\t    alignment);\n\t}\n\n\tfor (alignment = sizeof(size_t); alignment < MAXALIGN;\n\t    alignment <<= 1) {\n\t\tassert_d_ne(posix_memalign(&p, alignment + 1, 1), 0,\n\t\t    \"Expected error for invalid alignment %zu\",\n\t\t    alignment + 1);\n\t}\n}\nTEST_END\n\nTEST_BEGIN(test_oom_errors)\n{\n\tsize_t alignment, size;\n\tvoid *p;\n\n#if LG_SIZEOF_PTR == 3\n\talignment = UINT64_C(0x8000000000000000);\n\tsize      = UINT64_C(0x8000000000000000);\n#else\n\talignment = 0x80000000LU;\n\tsize      = 0x80000000LU;\n#endif\n\tassert_d_ne(posix_memalign(&p, alignment, size), 0,\n\t    \"Expected error for posix_memalign(&p, %zu, %zu)\",\n\t    alignment, size);\n\n#if LG_SIZEOF_PTR == 3\n\talignment = UINT64_C(0x4000000000000000);\n\tsize      = UINT64_C(0xc000000000000001);\n#else\n\talignment = 0x40000000LU;\n\tsize      = 0xc0000001LU;\n#endif\n\tassert_d_ne(posix_memalign(&p, alignment, size), 0,\n\t    \"Expected error for posix_memalign(&p, %zu, %zu)\",\n\t    alignment, size);\n\n\talignment = 0x10LU;\n#if LG_SIZEOF_PTR == 3\n\tsize = UINT64_C(0xfffffffffffffff0);\n#else\n\tsize = 0xfffffff0LU;\n#endif\n\tassert_d_ne(posix_memalign(&p, alignment, size), 0,\n\t    \"Expected error for posix_memalign(&p, %zu, %zu)\",\n\t    alignment, size);\n}\nTEST_END\n\nTEST_BEGIN(test_alignment_and_size)\n{\n\tsize_t alignment, size, total;\n\tunsigned i;\n\tint err;\n\tvoid *ps[NITER];\n\n\tfor (i = 0; i < NITER; i++)\n\t\tps[i] = NULL;\n\n\tfor (alignment = 8;\n\t    alignment <= MAXALIGN;\n\t    alignment <<= 1) {\n\t\ttotal = 0;\n\t\tfor (size = 1;\n\t\t    size < 3 * alignment && size < (1U << 31);\n\t\t    size += (alignment >> (LG_SIZEOF_PTR-1)) - 1) {\n\t\t\tfor (i = 0; i < NITER; i++) {\n\t\t\t\terr = posix_memalign(&ps[i],\n\t\t\t\t    alignment, size);\n\t\t\t\tif (err) {\n\t\t\t\t\tchar buf[BUFERROR_BUF];\n\n\t\t\t\t\tbuferror(get_errno(), buf, sizeof(buf));\n\t\t\t\t\ttest_fail(\n\t\t\t\t\t    \"Error for alignment=%zu, \"\n\t\t\t\t\t    \"size=%zu (%#zx): %s\",\n\t\t\t\t\t    alignment, size, size, buf);\n\t\t\t\t}\n\t\t\t\ttotal += malloc_usable_size(ps[i]);\n\t\t\t\tif (total >= (MAXALIGN << 1))\n\t\t\t\t\tbreak;\n\t\t\t}\n\t\t\tfor (i = 0; i < NITER; i++) {\n\t\t\t\tif (ps[i] != NULL) {\n\t\t\t\t\tfree(ps[i]);\n\t\t\t\t\tps[i] = NULL;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}\nTEST_END\n\nint\nmain(void)\n{\n\n\treturn (test(\n\t    test_alignment_errors,\n\t    test_oom_errors,\n\t    test_alignment_and_size));\n}\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/deps/jemalloc/test/integration/rallocx.c",
    "content": "#include \"test/jemalloc_test.h\"\n\nstatic unsigned\nget_nsizes_impl(const char *cmd)\n{\n\tunsigned ret;\n\tsize_t z;\n\n\tz = sizeof(unsigned);\n\tassert_d_eq(mallctl(cmd, &ret, &z, NULL, 0), 0,\n\t    \"Unexpected mallctl(\\\"%s\\\", ...) failure\", cmd);\n\n\treturn (ret);\n}\n\nstatic unsigned\nget_nhuge(void)\n{\n\n\treturn (get_nsizes_impl(\"arenas.nhchunks\"));\n}\n\nstatic size_t\nget_size_impl(const char *cmd, size_t ind)\n{\n\tsize_t ret;\n\tsize_t z;\n\tsize_t mib[4];\n\tsize_t miblen = 4;\n\n\tz = sizeof(size_t);\n\tassert_d_eq(mallctlnametomib(cmd, mib, &miblen),\n\t    0, \"Unexpected mallctlnametomib(\\\"%s\\\", ...) failure\", cmd);\n\tmib[2] = ind;\n\tz = sizeof(size_t);\n\tassert_d_eq(mallctlbymib(mib, miblen, &ret, &z, NULL, 0),\n\t    0, \"Unexpected mallctlbymib([\\\"%s\\\", %zu], ...) failure\", cmd, ind);\n\n\treturn (ret);\n}\n\nstatic size_t\nget_huge_size(size_t ind)\n{\n\n\treturn (get_size_impl(\"arenas.hchunk.0.size\", ind));\n}\n\nTEST_BEGIN(test_grow_and_shrink)\n{\n\tvoid *p, *q;\n\tsize_t tsz;\n#define\tNCYCLES 3\n\tunsigned i, j;\n#define\tNSZS 2500\n\tsize_t szs[NSZS];\n#define\tMAXSZ ZU(12 * 1024 * 1024)\n\n\tp = mallocx(1, 0);\n\tassert_ptr_not_null(p, \"Unexpected mallocx() error\");\n\tszs[0] = sallocx(p, 0);\n\n\tfor (i = 0; i < NCYCLES; i++) {\n\t\tfor (j = 1; j < NSZS && szs[j-1] < MAXSZ; j++) {\n\t\t\tq = rallocx(p, szs[j-1]+1, 0);\n\t\t\tassert_ptr_not_null(q,\n\t\t\t    \"Unexpected rallocx() error for size=%zu-->%zu\",\n\t\t\t    szs[j-1], szs[j-1]+1);\n\t\t\tszs[j] = sallocx(q, 0);\n\t\t\tassert_zu_ne(szs[j], szs[j-1]+1,\n\t\t\t    \"Expected size to be at least: %zu\", szs[j-1]+1);\n\t\t\tp = q;\n\t\t}\n\n\t\tfor (j--; j > 0; j--) {\n\t\t\tq = rallocx(p, szs[j-1], 0);\n\t\t\tassert_ptr_not_null(q,\n\t\t\t    \"Unexpected rallocx() error for size=%zu-->%zu\",\n\t\t\t    szs[j], szs[j-1]);\n\t\t\ttsz = sallocx(q, 0);\n\t\t\tassert_zu_eq(tsz, szs[j-1],\n\t\t\t    \"Expected size=%zu, got size=%zu\", szs[j-1], tsz);\n\t\t\tp = q;\n\t\t}\n\t}\n\n\tdallocx(p, 0);\n#undef MAXSZ\n#undef NSZS\n#undef NCYCLES\n}\nTEST_END\n\nstatic bool\nvalidate_fill(const void *p, uint8_t c, size_t offset, size_t len)\n{\n\tbool ret = false;\n\tconst uint8_t *buf = (const uint8_t *)p;\n\tsize_t i;\n\n\tfor (i = 0; i < len; i++) {\n\t\tuint8_t b = buf[offset+i];\n\t\tif (b != c) {\n\t\t\ttest_fail(\"Allocation at %p (len=%zu) contains %#x \"\n\t\t\t    \"rather than %#x at offset %zu\", p, len, b, c,\n\t\t\t    offset+i);\n\t\t\tret = true;\n\t\t}\n\t}\n\n\treturn (ret);\n}\n\nTEST_BEGIN(test_zero)\n{\n\tvoid *p, *q;\n\tsize_t psz, qsz, i, j;\n\tsize_t start_sizes[] = {1, 3*1024, 63*1024, 4095*1024};\n#define\tFILL_BYTE 0xaaU\n#define\tRANGE 2048\n\n\tfor (i = 0; i < sizeof(start_sizes)/sizeof(size_t); i++) {\n\t\tsize_t start_size = start_sizes[i];\n\t\tp = mallocx(start_size, MALLOCX_ZERO);\n\t\tassert_ptr_not_null(p, \"Unexpected mallocx() error\");\n\t\tpsz = sallocx(p, 0);\n\n\t\tassert_false(validate_fill(p, 0, 0, psz),\n\t\t    \"Expected zeroed memory\");\n\t\tmemset(p, FILL_BYTE, psz);\n\t\tassert_false(validate_fill(p, FILL_BYTE, 0, psz),\n\t\t    \"Expected filled memory\");\n\n\t\tfor (j = 1; j < RANGE; j++) {\n\t\t\tq = rallocx(p, start_size+j, MALLOCX_ZERO);\n\t\t\tassert_ptr_not_null(q, \"Unexpected rallocx() error\");\n\t\t\tqsz = sallocx(q, 0);\n\t\t\tif (q != p || qsz != psz) {\n\t\t\t\tassert_false(validate_fill(q, FILL_BYTE, 0,\n\t\t\t\t    psz), \"Expected filled memory\");\n\t\t\t\tassert_false(validate_fill(q, 0, psz, qsz-psz),\n\t\t\t\t    \"Expected zeroed memory\");\n\t\t\t}\n\t\t\tif (psz != qsz) {\n\t\t\t\tmemset((void *)((uintptr_t)q+psz), FILL_BYTE,\n\t\t\t\t    qsz-psz);\n\t\t\t\tpsz = qsz;\n\t\t\t}\n\t\t\tp = q;\n\t\t}\n\t\tassert_false(validate_fill(p, FILL_BYTE, 0, psz),\n\t\t    \"Expected filled memory\");\n\t\tdallocx(p, 0);\n\t}\n#undef FILL_BYTE\n}\nTEST_END\n\nTEST_BEGIN(test_align)\n{\n\tvoid *p, *q;\n\tsize_t align;\n#define\tMAX_ALIGN (ZU(1) << 25)\n\n\talign = ZU(1);\n\tp = mallocx(1, MALLOCX_ALIGN(align));\n\tassert_ptr_not_null(p, \"Unexpected mallocx() error\");\n\n\tfor (align <<= 1; align <= MAX_ALIGN; align <<= 1) {\n\t\tq = rallocx(p, 1, MALLOCX_ALIGN(align));\n\t\tassert_ptr_not_null(q,\n\t\t    \"Unexpected rallocx() error for align=%zu\", align);\n\t\tassert_ptr_null(\n\t\t    (void *)((uintptr_t)q & (align-1)),\n\t\t    \"%p inadequately aligned for align=%zu\",\n\t\t    q, align);\n\t\tp = q;\n\t}\n\tdallocx(p, 0);\n#undef MAX_ALIGN\n}\nTEST_END\n\nTEST_BEGIN(test_lg_align_and_zero)\n{\n\tvoid *p, *q;\n\tunsigned lg_align;\n\tsize_t sz;\n#define\tMAX_LG_ALIGN 25\n#define\tMAX_VALIDATE (ZU(1) << 22)\n\n\tlg_align = 0;\n\tp = mallocx(1, MALLOCX_LG_ALIGN(lg_align)|MALLOCX_ZERO);\n\tassert_ptr_not_null(p, \"Unexpected mallocx() error\");\n\n\tfor (lg_align++; lg_align <= MAX_LG_ALIGN; lg_align++) {\n\t\tq = rallocx(p, 1, MALLOCX_LG_ALIGN(lg_align)|MALLOCX_ZERO);\n\t\tassert_ptr_not_null(q,\n\t\t    \"Unexpected rallocx() error for lg_align=%u\", lg_align);\n\t\tassert_ptr_null(\n\t\t    (void *)((uintptr_t)q & ((ZU(1) << lg_align)-1)),\n\t\t    \"%p inadequately aligned for lg_align=%u\", q, lg_align);\n\t\tsz = sallocx(q, 0);\n\t\tif ((sz << 1) <= MAX_VALIDATE) {\n\t\t\tassert_false(validate_fill(q, 0, 0, sz),\n\t\t\t    \"Expected zeroed memory\");\n\t\t} else {\n\t\t\tassert_false(validate_fill(q, 0, 0, MAX_VALIDATE),\n\t\t\t    \"Expected zeroed memory\");\n\t\t\tassert_false(validate_fill(\n\t\t\t    (void *)((uintptr_t)q+sz-MAX_VALIDATE),\n\t\t\t    0, 0, MAX_VALIDATE), \"Expected zeroed memory\");\n\t\t}\n\t\tp = q;\n\t}\n\tdallocx(p, 0);\n#undef MAX_VALIDATE\n#undef MAX_LG_ALIGN\n}\nTEST_END\n\nTEST_BEGIN(test_overflow)\n{\n\tsize_t hugemax;\n\tvoid *p;\n\n\thugemax = get_huge_size(get_nhuge()-1);\n\n\tp = mallocx(1, 0);\n\tassert_ptr_not_null(p, \"Unexpected mallocx() failure\");\n\n\tassert_ptr_null(rallocx(p, hugemax+1, 0),\n\t    \"Expected OOM for rallocx(p, size=%#zx, 0)\", hugemax+1);\n\n\tassert_ptr_null(rallocx(p, ZU(PTRDIFF_MAX)+1, 0),\n\t    \"Expected OOM for rallocx(p, size=%#zx, 0)\", ZU(PTRDIFF_MAX)+1);\n\n\tassert_ptr_null(rallocx(p, SIZE_T_MAX, 0),\n\t    \"Expected OOM for rallocx(p, size=%#zx, 0)\", SIZE_T_MAX);\n\n\tassert_ptr_null(rallocx(p, 1, MALLOCX_ALIGN(ZU(PTRDIFF_MAX)+1)),\n\t    \"Expected OOM for rallocx(p, size=1, MALLOCX_ALIGN(%#zx))\",\n\t    ZU(PTRDIFF_MAX)+1);\n\n\tdallocx(p, 0);\n}\nTEST_END\n\nint\nmain(void)\n{\n\n\treturn (test(\n\t    test_grow_and_shrink,\n\t    test_zero,\n\t    test_align,\n\t    test_lg_align_and_zero,\n\t    test_overflow));\n}\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/deps/jemalloc/test/integration/sdallocx.c",
    "content": "#include \"test/jemalloc_test.h\"\n\n#define\tMAXALIGN (((size_t)1) << 25)\n#define\tNITER 4\n\nTEST_BEGIN(test_basic)\n{\n\tvoid *ptr = mallocx(64, 0);\n\tsdallocx(ptr, 64, 0);\n}\nTEST_END\n\nTEST_BEGIN(test_alignment_and_size)\n{\n\tsize_t nsz, sz, alignment, total;\n\tunsigned i;\n\tvoid *ps[NITER];\n\n\tfor (i = 0; i < NITER; i++)\n\t\tps[i] = NULL;\n\n\tfor (alignment = 8;\n\t    alignment <= MAXALIGN;\n\t    alignment <<= 1) {\n\t\ttotal = 0;\n\t\tfor (sz = 1;\n\t\t    sz < 3 * alignment && sz < (1U << 31);\n\t\t    sz += (alignment >> (LG_SIZEOF_PTR-1)) - 1) {\n\t\t\tfor (i = 0; i < NITER; i++) {\n\t\t\t\tnsz = nallocx(sz, MALLOCX_ALIGN(alignment) |\n\t\t\t\t    MALLOCX_ZERO);\n\t\t\t\tps[i] = mallocx(sz, MALLOCX_ALIGN(alignment) |\n\t\t\t\t    MALLOCX_ZERO);\n\t\t\t\ttotal += nsz;\n\t\t\t\tif (total >= (MAXALIGN << 1))\n\t\t\t\t\tbreak;\n\t\t\t}\n\t\t\tfor (i = 0; i < NITER; i++) {\n\t\t\t\tif (ps[i] != NULL) {\n\t\t\t\t\tsdallocx(ps[i], sz,\n\t\t\t\t\t    MALLOCX_ALIGN(alignment));\n\t\t\t\t\tps[i] = NULL;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}\nTEST_END\n\nint\nmain(void)\n{\n\n\treturn (test(\n\t    test_basic,\n\t    test_alignment_and_size));\n}\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/deps/jemalloc/test/integration/thread_arena.c",
    "content": "#include \"test/jemalloc_test.h\"\n\n#define\tNTHREADS 10\n\nvoid *\nthd_start(void *arg)\n{\n\tunsigned main_arena_ind = *(unsigned *)arg;\n\tvoid *p;\n\tunsigned arena_ind;\n\tsize_t size;\n\tint err;\n\n\tp = malloc(1);\n\tassert_ptr_not_null(p, \"Error in malloc()\");\n\tfree(p);\n\n\tsize = sizeof(arena_ind);\n\tif ((err = mallctl(\"thread.arena\", &arena_ind, &size, &main_arena_ind,\n\t    sizeof(main_arena_ind)))) {\n\t\tchar buf[BUFERROR_BUF];\n\n\t\tbuferror(err, buf, sizeof(buf));\n\t\ttest_fail(\"Error in mallctl(): %s\", buf);\n\t}\n\n\tsize = sizeof(arena_ind);\n\tif ((err = mallctl(\"thread.arena\", &arena_ind, &size, NULL, 0))) {\n\t\tchar buf[BUFERROR_BUF];\n\n\t\tbuferror(err, buf, sizeof(buf));\n\t\ttest_fail(\"Error in mallctl(): %s\", buf);\n\t}\n\tassert_u_eq(arena_ind, main_arena_ind,\n\t    \"Arena index should be same as for main thread\");\n\n\treturn (NULL);\n}\n\nTEST_BEGIN(test_thread_arena)\n{\n\tvoid *p;\n\tunsigned arena_ind;\n\tsize_t size;\n\tint err;\n\tthd_t thds[NTHREADS];\n\tunsigned i;\n\n\tp = malloc(1);\n\tassert_ptr_not_null(p, \"Error in malloc()\");\n\n\tsize = sizeof(arena_ind);\n\tif ((err = mallctl(\"thread.arena\", &arena_ind, &size, NULL, 0))) {\n\t\tchar buf[BUFERROR_BUF];\n\n\t\tbuferror(err, buf, sizeof(buf));\n\t\ttest_fail(\"Error in mallctl(): %s\", buf);\n\t}\n\n\tfor (i = 0; i < NTHREADS; i++) {\n\t\tthd_create(&thds[i], thd_start,\n\t\t    (void *)&arena_ind);\n\t}\n\n\tfor (i = 0; i < NTHREADS; i++) {\n\t\tintptr_t join_ret;\n\t\tthd_join(thds[i], (void *)&join_ret);\n\t\tassert_zd_eq(join_ret, 0, \"Unexpected thread join error\");\n\t}\n}\nTEST_END\n\nint\nmain(void)\n{\n\n\treturn (test(\n\t    test_thread_arena));\n}\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/deps/jemalloc/test/integration/thread_tcache_enabled.c",
    "content": "#include \"test/jemalloc_test.h\"\n\nstatic const bool config_tcache =\n#ifdef JEMALLOC_TCACHE\n    true\n#else\n    false\n#endif\n    ;\n\nvoid *\nthd_start(void *arg)\n{\n\tint err;\n\tsize_t sz;\n\tbool e0, e1;\n\n\tsz = sizeof(bool);\n\tif ((err = mallctl(\"thread.tcache.enabled\", &e0, &sz, NULL, 0))) {\n\t\tif (err == ENOENT) {\n\t\t\tassert_false(config_tcache,\n\t\t\t    \"ENOENT should only be returned if tcache is \"\n\t\t\t    \"disabled\");\n\t\t}\n\t\tgoto label_ENOENT;\n\t}\n\n\tif (e0) {\n\t\te1 = false;\n\t\tassert_d_eq(mallctl(\"thread.tcache.enabled\", &e0, &sz, &e1, sz),\n\t\t    0, \"Unexpected mallctl() error\");\n\t\tassert_true(e0, \"tcache should be enabled\");\n\t}\n\n\te1 = true;\n\tassert_d_eq(mallctl(\"thread.tcache.enabled\", &e0, &sz, &e1, sz), 0,\n\t    \"Unexpected mallctl() error\");\n\tassert_false(e0, \"tcache should be disabled\");\n\n\te1 = true;\n\tassert_d_eq(mallctl(\"thread.tcache.enabled\", &e0, &sz, &e1, sz), 0,\n\t    \"Unexpected mallctl() error\");\n\tassert_true(e0, \"tcache should be enabled\");\n\n\te1 = false;\n\tassert_d_eq(mallctl(\"thread.tcache.enabled\", &e0, &sz, &e1, sz), 0,\n\t    \"Unexpected mallctl() error\");\n\tassert_true(e0, \"tcache should be enabled\");\n\n\te1 = false;\n\tassert_d_eq(mallctl(\"thread.tcache.enabled\", &e0, &sz, &e1, sz), 0,\n\t    \"Unexpected mallctl() error\");\n\tassert_false(e0, \"tcache should be disabled\");\n\n\tfree(malloc(1));\n\te1 = true;\n\tassert_d_eq(mallctl(\"thread.tcache.enabled\", &e0, &sz, &e1, sz), 0,\n\t    \"Unexpected mallctl() error\");\n\tassert_false(e0, \"tcache should be disabled\");\n\n\tfree(malloc(1));\n\te1 = true;\n\tassert_d_eq(mallctl(\"thread.tcache.enabled\", &e0, &sz, &e1, sz), 0,\n\t    \"Unexpected mallctl() error\");\n\tassert_true(e0, \"tcache should be enabled\");\n\n\tfree(malloc(1));\n\te1 = false;\n\tassert_d_eq(mallctl(\"thread.tcache.enabled\", &e0, &sz, &e1, sz), 0,\n\t    \"Unexpected mallctl() error\");\n\tassert_true(e0, \"tcache should be enabled\");\n\n\tfree(malloc(1));\n\te1 = false;\n\tassert_d_eq(mallctl(\"thread.tcache.enabled\", &e0, &sz, &e1, sz), 0,\n\t    \"Unexpected mallctl() error\");\n\tassert_false(e0, \"tcache should be disabled\");\n\n\tfree(malloc(1));\n\treturn (NULL);\nlabel_ENOENT:\n\ttest_skip(\"\\\"thread.tcache.enabled\\\" mallctl not available\");\n\treturn (NULL);\n}\n\nTEST_BEGIN(test_main_thread)\n{\n\n\tthd_start(NULL);\n}\nTEST_END\n\nTEST_BEGIN(test_subthread)\n{\n\tthd_t thd;\n\n\tthd_create(&thd, thd_start, NULL);\n\tthd_join(thd, NULL);\n}\nTEST_END\n\nint\nmain(void)\n{\n\n\t/* Run tests multiple times to check for bad interactions. */\n\treturn (test(\n\t    test_main_thread,\n\t    test_subthread,\n\t    test_main_thread,\n\t    test_subthread,\n\t    test_main_thread));\n}\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/deps/jemalloc/test/integration/xallocx.c",
    "content": "#include \"test/jemalloc_test.h\"\n\n#ifdef JEMALLOC_FILL\nconst char *malloc_conf = \"junk:false\";\n#endif\n\n/*\n * Use a separate arena for xallocx() extension/contraction tests so that\n * internal allocation e.g. by heap profiling can't interpose allocations where\n * xallocx() would ordinarily be able to extend.\n */\nstatic unsigned\narena_ind(void)\n{\n\tstatic unsigned ind = 0;\n\n\tif (ind == 0) {\n\t\tsize_t sz = sizeof(ind);\n\t\tassert_d_eq(mallctl(\"arenas.extend\", &ind, &sz, NULL, 0), 0,\n\t\t    \"Unexpected mallctl failure creating arena\");\n\t}\n\n\treturn (ind);\n}\n\nTEST_BEGIN(test_same_size)\n{\n\tvoid *p;\n\tsize_t sz, tsz;\n\n\tp = mallocx(42, 0);\n\tassert_ptr_not_null(p, \"Unexpected mallocx() error\");\n\tsz = sallocx(p, 0);\n\n\ttsz = xallocx(p, sz, 0, 0);\n\tassert_zu_eq(tsz, sz, \"Unexpected size change: %zu --> %zu\", sz, tsz);\n\n\tdallocx(p, 0);\n}\nTEST_END\n\nTEST_BEGIN(test_extra_no_move)\n{\n\tvoid *p;\n\tsize_t sz, tsz;\n\n\tp = mallocx(42, 0);\n\tassert_ptr_not_null(p, \"Unexpected mallocx() error\");\n\tsz = sallocx(p, 0);\n\n\ttsz = xallocx(p, sz, sz-42, 0);\n\tassert_zu_eq(tsz, sz, \"Unexpected size change: %zu --> %zu\", sz, tsz);\n\n\tdallocx(p, 0);\n}\nTEST_END\n\nTEST_BEGIN(test_no_move_fail)\n{\n\tvoid *p;\n\tsize_t sz, tsz;\n\n\tp = mallocx(42, 0);\n\tassert_ptr_not_null(p, \"Unexpected mallocx() error\");\n\tsz = sallocx(p, 0);\n\n\ttsz = xallocx(p, sz + 5, 0, 0);\n\tassert_zu_eq(tsz, sz, \"Unexpected size change: %zu --> %zu\", sz, tsz);\n\n\tdallocx(p, 0);\n}\nTEST_END\n\nstatic unsigned\nget_nsizes_impl(const char *cmd)\n{\n\tunsigned ret;\n\tsize_t z;\n\n\tz = sizeof(unsigned);\n\tassert_d_eq(mallctl(cmd, &ret, &z, NULL, 0), 0,\n\t    \"Unexpected mallctl(\\\"%s\\\", ...) failure\", cmd);\n\n\treturn (ret);\n}\n\nstatic unsigned\nget_nsmall(void)\n{\n\n\treturn (get_nsizes_impl(\"arenas.nbins\"));\n}\n\nstatic unsigned\nget_nlarge(void)\n{\n\n\treturn (get_nsizes_impl(\"arenas.nlruns\"));\n}\n\nstatic unsigned\nget_nhuge(void)\n{\n\n\treturn (get_nsizes_impl(\"arenas.nhchunks\"));\n}\n\nstatic size_t\nget_size_impl(const char *cmd, size_t ind)\n{\n\tsize_t ret;\n\tsize_t z;\n\tsize_t mib[4];\n\tsize_t miblen = 4;\n\n\tz = sizeof(size_t);\n\tassert_d_eq(mallctlnametomib(cmd, mib, &miblen),\n\t    0, \"Unexpected mallctlnametomib(\\\"%s\\\", ...) failure\", cmd);\n\tmib[2] = ind;\n\tz = sizeof(size_t);\n\tassert_d_eq(mallctlbymib(mib, miblen, &ret, &z, NULL, 0),\n\t    0, \"Unexpected mallctlbymib([\\\"%s\\\", %zu], ...) failure\", cmd, ind);\n\n\treturn (ret);\n}\n\nstatic size_t\nget_small_size(size_t ind)\n{\n\n\treturn (get_size_impl(\"arenas.bin.0.size\", ind));\n}\n\nstatic size_t\nget_large_size(size_t ind)\n{\n\n\treturn (get_size_impl(\"arenas.lrun.0.size\", ind));\n}\n\nstatic size_t\nget_huge_size(size_t ind)\n{\n\n\treturn (get_size_impl(\"arenas.hchunk.0.size\", ind));\n}\n\nTEST_BEGIN(test_size)\n{\n\tsize_t small0, hugemax;\n\tvoid *p;\n\n\t/* Get size classes. */\n\tsmall0 = get_small_size(0);\n\thugemax = get_huge_size(get_nhuge()-1);\n\n\tp = mallocx(small0, 0);\n\tassert_ptr_not_null(p, \"Unexpected mallocx() error\");\n\n\t/* Test smallest supported size. */\n\tassert_zu_eq(xallocx(p, 1, 0, 0), small0,\n\t    \"Unexpected xallocx() behavior\");\n\n\t/* Test largest supported size. */\n\tassert_zu_le(xallocx(p, hugemax, 0, 0), hugemax,\n\t    \"Unexpected xallocx() behavior\");\n\n\t/* Test size overflow. */\n\tassert_zu_le(xallocx(p, hugemax+1, 0, 0), hugemax,\n\t    \"Unexpected xallocx() behavior\");\n\tassert_zu_le(xallocx(p, SIZE_T_MAX, 0, 0), hugemax,\n\t    \"Unexpected xallocx() behavior\");\n\n\tdallocx(p, 0);\n}\nTEST_END\n\nTEST_BEGIN(test_size_extra_overflow)\n{\n\tsize_t small0, hugemax;\n\tvoid *p;\n\n\t/* Get size classes. */\n\tsmall0 = get_small_size(0);\n\thugemax = get_huge_size(get_nhuge()-1);\n\n\tp = mallocx(small0, 0);\n\tassert_ptr_not_null(p, \"Unexpected mallocx() error\");\n\n\t/* Test overflows that can be resolved by clamping extra. */\n\tassert_zu_le(xallocx(p, hugemax-1, 2, 0), hugemax,\n\t    \"Unexpected xallocx() behavior\");\n\tassert_zu_le(xallocx(p, hugemax, 1, 0), hugemax,\n\t    \"Unexpected xallocx() behavior\");\n\n\t/* Test overflow such that hugemax-size underflows. */\n\tassert_zu_le(xallocx(p, hugemax+1, 2, 0), hugemax,\n\t    \"Unexpected xallocx() behavior\");\n\tassert_zu_le(xallocx(p, hugemax+2, 3, 0), hugemax,\n\t    \"Unexpected xallocx() behavior\");\n\tassert_zu_le(xallocx(p, SIZE_T_MAX-2, 2, 0), hugemax,\n\t    \"Unexpected xallocx() behavior\");\n\tassert_zu_le(xallocx(p, SIZE_T_MAX-1, 1, 0), hugemax,\n\t    \"Unexpected xallocx() behavior\");\n\n\tdallocx(p, 0);\n}\nTEST_END\n\nTEST_BEGIN(test_extra_small)\n{\n\tsize_t small0, small1, hugemax;\n\tvoid *p;\n\n\t/* Get size classes. */\n\tsmall0 = get_small_size(0);\n\tsmall1 = get_small_size(1);\n\thugemax = get_huge_size(get_nhuge()-1);\n\n\tp = mallocx(small0, 0);\n\tassert_ptr_not_null(p, \"Unexpected mallocx() error\");\n\n\tassert_zu_eq(xallocx(p, small1, 0, 0), small0,\n\t    \"Unexpected xallocx() behavior\");\n\n\tassert_zu_eq(xallocx(p, small1, 0, 0), small0,\n\t    \"Unexpected xallocx() behavior\");\n\n\tassert_zu_eq(xallocx(p, small0, small1 - small0, 0), small0,\n\t    \"Unexpected xallocx() behavior\");\n\n\t/* Test size+extra overflow. */\n\tassert_zu_eq(xallocx(p, small0, hugemax - small0 + 1, 0), small0,\n\t    \"Unexpected xallocx() behavior\");\n\tassert_zu_eq(xallocx(p, small0, SIZE_T_MAX - small0, 0), small0,\n\t    \"Unexpected xallocx() behavior\");\n\n\tdallocx(p, 0);\n}\nTEST_END\n\nTEST_BEGIN(test_extra_large)\n{\n\tint flags = MALLOCX_ARENA(arena_ind());\n\tsize_t smallmax, large0, large1, large2, huge0, hugemax;\n\tvoid *p;\n\n\t/* Get size classes. */\n\tsmallmax = get_small_size(get_nsmall()-1);\n\tlarge0 = get_large_size(0);\n\tlarge1 = get_large_size(1);\n\tlarge2 = get_large_size(2);\n\thuge0 = get_huge_size(0);\n\thugemax = get_huge_size(get_nhuge()-1);\n\n\tp = mallocx(large2, flags);\n\tassert_ptr_not_null(p, \"Unexpected mallocx() error\");\n\n\tassert_zu_eq(xallocx(p, large2, 0, flags), large2,\n\t    \"Unexpected xallocx() behavior\");\n\t/* Test size decrease with zero extra. */\n\tassert_zu_eq(xallocx(p, large0, 0, flags), large0,\n\t    \"Unexpected xallocx() behavior\");\n\tassert_zu_eq(xallocx(p, smallmax, 0, flags), large0,\n\t    \"Unexpected xallocx() behavior\");\n\n\tassert_zu_eq(xallocx(p, large2, 0, flags), large2,\n\t    \"Unexpected xallocx() behavior\");\n\t/* Test size decrease with non-zero extra. */\n\tassert_zu_eq(xallocx(p, large0, large2 - large0, flags), large2,\n\t    \"Unexpected xallocx() behavior\");\n\tassert_zu_eq(xallocx(p, large1, large2 - large1, flags), large2,\n\t    \"Unexpected xallocx() behavior\");\n\tassert_zu_eq(xallocx(p, large0, large1 - large0, flags), large1,\n\t    \"Unexpected xallocx() behavior\");\n\tassert_zu_eq(xallocx(p, smallmax, large0 - smallmax, flags), large0,\n\t    \"Unexpected xallocx() behavior\");\n\n\tassert_zu_eq(xallocx(p, large0, 0, flags), large0,\n\t    \"Unexpected xallocx() behavior\");\n\t/* Test size increase with zero extra. */\n\tassert_zu_eq(xallocx(p, large2, 0, flags), large2,\n\t    \"Unexpected xallocx() behavior\");\n\tassert_zu_eq(xallocx(p, huge0, 0, flags), large2,\n\t    \"Unexpected xallocx() behavior\");\n\n\tassert_zu_eq(xallocx(p, large0, 0, flags), large0,\n\t    \"Unexpected xallocx() behavior\");\n\t/* Test size increase with non-zero extra. */\n\tassert_zu_lt(xallocx(p, large0, huge0 - large0, flags), huge0,\n\t    \"Unexpected xallocx() behavior\");\n\n\tassert_zu_eq(xallocx(p, large0, 0, flags), large0,\n\t    \"Unexpected xallocx() behavior\");\n\t/* Test size increase with non-zero extra. */\n\tassert_zu_eq(xallocx(p, large0, large2 - large0, flags), large2,\n\t    \"Unexpected xallocx() behavior\");\n\n\tassert_zu_eq(xallocx(p, large2, 0, flags), large2,\n\t    \"Unexpected xallocx() behavior\");\n\t/* Test size+extra overflow. */\n\tassert_zu_lt(xallocx(p, large2, hugemax - large2 + 1, flags), huge0,\n\t    \"Unexpected xallocx() behavior\");\n\n\tdallocx(p, flags);\n}\nTEST_END\n\nTEST_BEGIN(test_extra_huge)\n{\n\tint flags = MALLOCX_ARENA(arena_ind());\n\tsize_t largemax, huge1, huge2, huge3, hugemax;\n\tvoid *p;\n\n\t/* Get size classes. */\n\tlargemax = get_large_size(get_nlarge()-1);\n\thuge1 = get_huge_size(1);\n\thuge2 = get_huge_size(2);\n\thuge3 = get_huge_size(3);\n\thugemax = get_huge_size(get_nhuge()-1);\n\n\tp = mallocx(huge3, flags);\n\tassert_ptr_not_null(p, \"Unexpected mallocx() error\");\n\n\tassert_zu_eq(xallocx(p, huge3, 0, flags), huge3,\n\t    \"Unexpected xallocx() behavior\");\n\t/* Test size decrease with zero extra. */\n\tassert_zu_ge(xallocx(p, huge1, 0, flags), huge1,\n\t    \"Unexpected xallocx() behavior\");\n\tassert_zu_ge(xallocx(p, largemax, 0, flags), huge1,\n\t    \"Unexpected xallocx() behavior\");\n\n\tassert_zu_eq(xallocx(p, huge3, 0, flags), huge3,\n\t    \"Unexpected xallocx() behavior\");\n\t/* Test size decrease with non-zero extra. */\n\tassert_zu_eq(xallocx(p, huge1, huge3 - huge1, flags), huge3,\n\t    \"Unexpected xallocx() behavior\");\n\tassert_zu_eq(xallocx(p, huge2, huge3 - huge2, flags), huge3,\n\t    \"Unexpected xallocx() behavior\");\n\tassert_zu_eq(xallocx(p, huge1, huge2 - huge1, flags), huge2,\n\t    \"Unexpected xallocx() behavior\");\n\tassert_zu_ge(xallocx(p, largemax, huge1 - largemax, flags), huge1,\n\t    \"Unexpected xallocx() behavior\");\n\n\tassert_zu_ge(xallocx(p, huge1, 0, flags), huge1,\n\t    \"Unexpected xallocx() behavior\");\n\t/* Test size increase with zero extra. */\n\tassert_zu_le(xallocx(p, huge3, 0, flags), huge3,\n\t    \"Unexpected xallocx() behavior\");\n\tassert_zu_le(xallocx(p, hugemax+1, 0, flags), huge3,\n\t    \"Unexpected xallocx() behavior\");\n\n\tassert_zu_ge(xallocx(p, huge1, 0, flags), huge1,\n\t    \"Unexpected xallocx() behavior\");\n\t/* Test size increase with non-zero extra. */\n\tassert_zu_le(xallocx(p, huge1, SIZE_T_MAX - huge1, flags), hugemax,\n\t    \"Unexpected xallocx() behavior\");\n\n\tassert_zu_ge(xallocx(p, huge1, 0, flags), huge1,\n\t    \"Unexpected xallocx() behavior\");\n\t/* Test size increase with non-zero extra. */\n\tassert_zu_le(xallocx(p, huge1, huge3 - huge1, flags), huge3,\n\t    \"Unexpected xallocx() behavior\");\n\n\tassert_zu_eq(xallocx(p, huge3, 0, flags), huge3,\n\t    \"Unexpected xallocx() behavior\");\n\t/* Test size+extra overflow. */\n\tassert_zu_le(xallocx(p, huge3, hugemax - huge3 + 1, flags), hugemax,\n\t    \"Unexpected xallocx() behavior\");\n\n\tdallocx(p, flags);\n}\nTEST_END\n\nstatic void\nprint_filled_extents(const void *p, uint8_t c, size_t len)\n{\n\tconst uint8_t *pc = (const uint8_t *)p;\n\tsize_t i, range0;\n\tuint8_t c0;\n\n\tmalloc_printf(\"  p=%p, c=%#x, len=%zu:\", p, c, len);\n\trange0 = 0;\n\tc0 = pc[0];\n\tfor (i = 0; i < len; i++) {\n\t\tif (pc[i] != c0) {\n\t\t\tmalloc_printf(\" %#x[%zu..%zu)\", c0, range0, i);\n\t\t\trange0 = i;\n\t\t\tc0 = pc[i];\n\t\t}\n\t}\n\tmalloc_printf(\" %#x[%zu..%zu)\\n\", c0, range0, i);\n}\n\nstatic bool\nvalidate_fill(const void *p, uint8_t c, size_t offset, size_t len)\n{\n\tconst uint8_t *pc = (const uint8_t *)p;\n\tbool err;\n\tsize_t i;\n\n\tfor (i = offset, err = false; i < offset+len; i++) {\n\t\tif (pc[i] != c)\n\t\t\terr = true;\n\t}\n\n\tif (err)\n\t\tprint_filled_extents(p, c, offset + len);\n\n\treturn (err);\n}\n\nstatic void\ntest_zero(size_t szmin, size_t szmax)\n{\n\tint flags = MALLOCX_ARENA(arena_ind()) | MALLOCX_ZERO;\n\tsize_t sz, nsz;\n\tvoid *p;\n#define\tFILL_BYTE 0x7aU\n\n\tsz = szmax;\n\tp = mallocx(sz, flags);\n\tassert_ptr_not_null(p, \"Unexpected mallocx() error\");\n\tassert_false(validate_fill(p, 0x00, 0, sz), \"Memory not filled: sz=%zu\",\n\t    sz);\n\n\t/*\n\t * Fill with non-zero so that non-debug builds are more likely to detect\n\t * errors.\n\t */\n\tmemset(p, FILL_BYTE, sz);\n\tassert_false(validate_fill(p, FILL_BYTE, 0, sz),\n\t    \"Memory not filled: sz=%zu\", sz);\n\n\t/* Shrink in place so that we can expect growing in place to succeed. */\n\tsz = szmin;\n\tassert_zu_eq(xallocx(p, sz, 0, flags), sz,\n\t    \"Unexpected xallocx() error\");\n\tassert_false(validate_fill(p, FILL_BYTE, 0, sz),\n\t    \"Memory not filled: sz=%zu\", sz);\n\n\tfor (sz = szmin; sz < szmax; sz = nsz) {\n\t\tnsz = nallocx(sz+1, flags);\n\t\tassert_zu_eq(xallocx(p, sz+1, 0, flags), nsz,\n\t\t    \"Unexpected xallocx() failure\");\n\t\tassert_false(validate_fill(p, FILL_BYTE, 0, sz),\n\t\t    \"Memory not filled: sz=%zu\", sz);\n\t\tassert_false(validate_fill(p, 0x00, sz, nsz-sz),\n\t\t    \"Memory not filled: sz=%zu, nsz-sz=%zu\", sz, nsz-sz);\n\t\tmemset((void *)((uintptr_t)p + sz), FILL_BYTE, nsz-sz);\n\t\tassert_false(validate_fill(p, FILL_BYTE, 0, nsz),\n\t\t    \"Memory not filled: nsz=%zu\", nsz);\n\t}\n\n\tdallocx(p, flags);\n}\n\nTEST_BEGIN(test_zero_large)\n{\n\tsize_t large0, largemax;\n\n\t/* Get size classes. */\n\tlarge0 = get_large_size(0);\n\tlargemax = get_large_size(get_nlarge()-1);\n\n\ttest_zero(large0, largemax);\n}\nTEST_END\n\nTEST_BEGIN(test_zero_huge)\n{\n\tsize_t huge0, huge1;\n\n\t/* Get size classes. */\n\thuge0 = get_huge_size(0);\n\thuge1 = get_huge_size(1);\n\n\ttest_zero(huge1, huge0 * 2);\n}\nTEST_END\n\nint\nmain(void)\n{\n\n\treturn (test(\n\t    test_same_size,\n\t    test_extra_no_move,\n\t    test_no_move_fail,\n\t    test_size,\n\t    test_size_extra_overflow,\n\t    test_extra_small,\n\t    test_extra_large,\n\t    test_extra_huge,\n\t    test_zero_large,\n\t    test_zero_huge));\n}\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/deps/jemalloc/test/src/SFMT.c",
    "content": "/*\n * This file derives from SFMT 1.3.3\n * (http://www.math.sci.hiroshima-u.ac.jp/~m-mat/MT/SFMT/index.html), which was\n * released under the terms of the following license:\n *\n *   Copyright (c) 2006,2007 Mutsuo Saito, Makoto Matsumoto and Hiroshima\n *   University. All rights reserved.\n *\n *   Redistribution and use in source and binary forms, with or without\n *   modification, are permitted provided that the following conditions are\n *   met:\n *\n *       * Redistributions of source code must retain the above copyright\n *         notice, this list of conditions and the following disclaimer.\n *       * Redistributions in binary form must reproduce the above\n *         copyright notice, this list of conditions and the following\n *         disclaimer in the documentation and/or other materials provided\n *         with the distribution.\n *       * Neither the name of the Hiroshima University nor the names of\n *         its contributors may be used to endorse or promote products\n *         derived from this software without specific prior written\n *         permission.\n *\n *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n *   \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\n *   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\n *   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\n *   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n *   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\n *   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n *   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n *   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n *   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n *   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n/** \n * @file  SFMT.c\n * @brief SIMD oriented Fast Mersenne Twister(SFMT)\n *\n * @author Mutsuo Saito (Hiroshima University)\n * @author Makoto Matsumoto (Hiroshima University)\n *\n * Copyright (C) 2006,2007 Mutsuo Saito, Makoto Matsumoto and Hiroshima\n * University. All rights reserved.\n *\n * The new BSD License is applied to this software, see LICENSE.txt\n */\n#define\tSFMT_C_\n#include \"test/jemalloc_test.h\"\n#include \"test/SFMT-params.h\"\n\n#if defined(JEMALLOC_BIG_ENDIAN) && !defined(BIG_ENDIAN64)\n#define BIG_ENDIAN64 1\n#endif\n#if defined(__BIG_ENDIAN__) && !defined(__amd64) && !defined(BIG_ENDIAN64)\n#define BIG_ENDIAN64 1\n#endif\n#if defined(HAVE_ALTIVEC) && !defined(BIG_ENDIAN64)\n#define BIG_ENDIAN64 1\n#endif\n#if defined(ONLY64) && !defined(BIG_ENDIAN64)\n  #if defined(__GNUC__)\n    #error \"-DONLY64 must be specified with -DBIG_ENDIAN64\"\n  #endif\n#undef ONLY64\n#endif\n/*------------------------------------------------------\n  128-bit SIMD data type for Altivec, SSE2 or standard C\n  ------------------------------------------------------*/\n#if defined(HAVE_ALTIVEC)\n/** 128-bit data structure */\nunion W128_T {\n    vector unsigned int s;\n    uint32_t u[4];\n};\n/** 128-bit data type */\ntypedef union W128_T w128_t;\n\n#elif defined(HAVE_SSE2)\n/** 128-bit data structure */\nunion W128_T {\n    __m128i si;\n    uint32_t u[4];\n};\n/** 128-bit data type */\ntypedef union W128_T w128_t;\n\n#else\n\n/** 128-bit data structure */\nstruct W128_T {\n    uint32_t u[4];\n};\n/** 128-bit data type */\ntypedef struct W128_T w128_t;\n\n#endif\n\nstruct sfmt_s {\n    /** the 128-bit internal state array */\n    w128_t sfmt[N];\n    /** index counter to the 32-bit internal state array */\n    int idx;\n    /** a flag: it is 0 if and only if the internal state is not yet\n     * initialized. */\n    int initialized;\n};\n\n/*--------------------------------------\n  FILE GLOBAL VARIABLES\n  internal state, index counter and flag \n  --------------------------------------*/\n\n/** a parity check vector which certificate the period of 2^{MEXP} */\nstatic uint32_t parity[4] = {PARITY1, PARITY2, PARITY3, PARITY4};\n\n/*----------------\n  STATIC FUNCTIONS\n  ----------------*/\nJEMALLOC_INLINE_C int idxof(int i);\n#if (!defined(HAVE_ALTIVEC)) && (!defined(HAVE_SSE2))\nJEMALLOC_INLINE_C void rshift128(w128_t *out,  w128_t const *in, int shift);\nJEMALLOC_INLINE_C void lshift128(w128_t *out,  w128_t const *in, int shift);\n#endif\nJEMALLOC_INLINE_C void gen_rand_all(sfmt_t *ctx);\nJEMALLOC_INLINE_C void gen_rand_array(sfmt_t *ctx, w128_t *array, int size);\nJEMALLOC_INLINE_C uint32_t func1(uint32_t x);\nJEMALLOC_INLINE_C uint32_t func2(uint32_t x);\nstatic void period_certification(sfmt_t *ctx);\n#if defined(BIG_ENDIAN64) && !defined(ONLY64)\nJEMALLOC_INLINE_C void swap(w128_t *array, int size);\n#endif\n\n#if defined(HAVE_ALTIVEC)\n  #include \"test/SFMT-alti.h\"\n#elif defined(HAVE_SSE2)\n  #include \"test/SFMT-sse2.h\"\n#endif\n\n/**\n * This function simulate a 64-bit index of LITTLE ENDIAN \n * in BIG ENDIAN machine.\n */\n#ifdef ONLY64\nJEMALLOC_INLINE_C int idxof(int i) {\n    return i ^ 1;\n}\n#else\nJEMALLOC_INLINE_C int idxof(int i) {\n    return i;\n}\n#endif\n/**\n * This function simulates SIMD 128-bit right shift by the standard C.\n * The 128-bit integer given in in is shifted by (shift * 8) bits.\n * This function simulates the LITTLE ENDIAN SIMD.\n * @param out the output of this function\n * @param in the 128-bit data to be shifted\n * @param shift the shift value\n */\n#if (!defined(HAVE_ALTIVEC)) && (!defined(HAVE_SSE2))\n#ifdef ONLY64\nJEMALLOC_INLINE_C void rshift128(w128_t *out, w128_t const *in, int shift) {\n    uint64_t th, tl, oh, ol;\n\n    th = ((uint64_t)in->u[2] << 32) | ((uint64_t)in->u[3]);\n    tl = ((uint64_t)in->u[0] << 32) | ((uint64_t)in->u[1]);\n\n    oh = th >> (shift * 8);\n    ol = tl >> (shift * 8);\n    ol |= th << (64 - shift * 8);\n    out->u[0] = (uint32_t)(ol >> 32);\n    out->u[1] = (uint32_t)ol;\n    out->u[2] = (uint32_t)(oh >> 32);\n    out->u[3] = (uint32_t)oh;\n}\n#else\nJEMALLOC_INLINE_C void rshift128(w128_t *out, w128_t const *in, int shift) {\n    uint64_t th, tl, oh, ol;\n\n    th = ((uint64_t)in->u[3] << 32) | ((uint64_t)in->u[2]);\n    tl = ((uint64_t)in->u[1] << 32) | ((uint64_t)in->u[0]);\n\n    oh = th >> (shift * 8);\n    ol = tl >> (shift * 8);\n    ol |= th << (64 - shift * 8);\n    out->u[1] = (uint32_t)(ol >> 32);\n    out->u[0] = (uint32_t)ol;\n    out->u[3] = (uint32_t)(oh >> 32);\n    out->u[2] = (uint32_t)oh;\n}\n#endif\n/**\n * This function simulates SIMD 128-bit left shift by the standard C.\n * The 128-bit integer given in in is shifted by (shift * 8) bits.\n * This function simulates the LITTLE ENDIAN SIMD.\n * @param out the output of this function\n * @param in the 128-bit data to be shifted\n * @param shift the shift value\n */\n#ifdef ONLY64\nJEMALLOC_INLINE_C void lshift128(w128_t *out, w128_t const *in, int shift) {\n    uint64_t th, tl, oh, ol;\n\n    th = ((uint64_t)in->u[2] << 32) | ((uint64_t)in->u[3]);\n    tl = ((uint64_t)in->u[0] << 32) | ((uint64_t)in->u[1]);\n\n    oh = th << (shift * 8);\n    ol = tl << (shift * 8);\n    oh |= tl >> (64 - shift * 8);\n    out->u[0] = (uint32_t)(ol >> 32);\n    out->u[1] = (uint32_t)ol;\n    out->u[2] = (uint32_t)(oh >> 32);\n    out->u[3] = (uint32_t)oh;\n}\n#else\nJEMALLOC_INLINE_C void lshift128(w128_t *out, w128_t const *in, int shift) {\n    uint64_t th, tl, oh, ol;\n\n    th = ((uint64_t)in->u[3] << 32) | ((uint64_t)in->u[2]);\n    tl = ((uint64_t)in->u[1] << 32) | ((uint64_t)in->u[0]);\n\n    oh = th << (shift * 8);\n    ol = tl << (shift * 8);\n    oh |= tl >> (64 - shift * 8);\n    out->u[1] = (uint32_t)(ol >> 32);\n    out->u[0] = (uint32_t)ol;\n    out->u[3] = (uint32_t)(oh >> 32);\n    out->u[2] = (uint32_t)oh;\n}\n#endif\n#endif\n\n/**\n * This function represents the recursion formula.\n * @param r output\n * @param a a 128-bit part of the internal state array\n * @param b a 128-bit part of the internal state array\n * @param c a 128-bit part of the internal state array\n * @param d a 128-bit part of the internal state array\n */\n#if (!defined(HAVE_ALTIVEC)) && (!defined(HAVE_SSE2))\n#ifdef ONLY64\nJEMALLOC_INLINE_C void do_recursion(w128_t *r, w128_t *a, w128_t *b, w128_t *c,\n\t\t\t\tw128_t *d) {\n    w128_t x;\n    w128_t y;\n\n    lshift128(&x, a, SL2);\n    rshift128(&y, c, SR2);\n    r->u[0] = a->u[0] ^ x.u[0] ^ ((b->u[0] >> SR1) & MSK2) ^ y.u[0] \n\t^ (d->u[0] << SL1);\n    r->u[1] = a->u[1] ^ x.u[1] ^ ((b->u[1] >> SR1) & MSK1) ^ y.u[1] \n\t^ (d->u[1] << SL1);\n    r->u[2] = a->u[2] ^ x.u[2] ^ ((b->u[2] >> SR1) & MSK4) ^ y.u[2] \n\t^ (d->u[2] << SL1);\n    r->u[3] = a->u[3] ^ x.u[3] ^ ((b->u[3] >> SR1) & MSK3) ^ y.u[3] \n\t^ (d->u[3] << SL1);\n}\n#else\nJEMALLOC_INLINE_C void do_recursion(w128_t *r, w128_t *a, w128_t *b, w128_t *c,\n\t\t\t\tw128_t *d) {\n    w128_t x;\n    w128_t y;\n\n    lshift128(&x, a, SL2);\n    rshift128(&y, c, SR2);\n    r->u[0] = a->u[0] ^ x.u[0] ^ ((b->u[0] >> SR1) & MSK1) ^ y.u[0] \n\t^ (d->u[0] << SL1);\n    r->u[1] = a->u[1] ^ x.u[1] ^ ((b->u[1] >> SR1) & MSK2) ^ y.u[1] \n\t^ (d->u[1] << SL1);\n    r->u[2] = a->u[2] ^ x.u[2] ^ ((b->u[2] >> SR1) & MSK3) ^ y.u[2] \n\t^ (d->u[2] << SL1);\n    r->u[3] = a->u[3] ^ x.u[3] ^ ((b->u[3] >> SR1) & MSK4) ^ y.u[3] \n\t^ (d->u[3] << SL1);\n}\n#endif\n#endif\n\n#if (!defined(HAVE_ALTIVEC)) && (!defined(HAVE_SSE2))\n/**\n * This function fills the internal state array with pseudorandom\n * integers.\n */\nJEMALLOC_INLINE_C void gen_rand_all(sfmt_t *ctx) {\n    int i;\n    w128_t *r1, *r2;\n\n    r1 = &ctx->sfmt[N - 2];\n    r2 = &ctx->sfmt[N - 1];\n    for (i = 0; i < N - POS1; i++) {\n\tdo_recursion(&ctx->sfmt[i], &ctx->sfmt[i], &ctx->sfmt[i + POS1], r1,\n\t  r2);\n\tr1 = r2;\n\tr2 = &ctx->sfmt[i];\n    }\n    for (; i < N; i++) {\n\tdo_recursion(&ctx->sfmt[i], &ctx->sfmt[i], &ctx->sfmt[i + POS1 - N], r1,\n\t  r2);\n\tr1 = r2;\n\tr2 = &ctx->sfmt[i];\n    }\n}\n\n/**\n * This function fills the user-specified array with pseudorandom\n * integers.\n *\n * @param array an 128-bit array to be filled by pseudorandom numbers.  \n * @param size number of 128-bit pseudorandom numbers to be generated.\n */\nJEMALLOC_INLINE_C void gen_rand_array(sfmt_t *ctx, w128_t *array, int size) {\n    int i, j;\n    w128_t *r1, *r2;\n\n    r1 = &ctx->sfmt[N - 2];\n    r2 = &ctx->sfmt[N - 1];\n    for (i = 0; i < N - POS1; i++) {\n\tdo_recursion(&array[i], &ctx->sfmt[i], &ctx->sfmt[i + POS1], r1, r2);\n\tr1 = r2;\n\tr2 = &array[i];\n    }\n    for (; i < N; i++) {\n\tdo_recursion(&array[i], &ctx->sfmt[i], &array[i + POS1 - N], r1, r2);\n\tr1 = r2;\n\tr2 = &array[i];\n    }\n    for (; i < size - N; i++) {\n\tdo_recursion(&array[i], &array[i - N], &array[i + POS1 - N], r1, r2);\n\tr1 = r2;\n\tr2 = &array[i];\n    }\n    for (j = 0; j < 2 * N - size; j++) {\n\tctx->sfmt[j] = array[j + size - N];\n    }\n    for (; i < size; i++, j++) {\n\tdo_recursion(&array[i], &array[i - N], &array[i + POS1 - N], r1, r2);\n\tr1 = r2;\n\tr2 = &array[i];\n\tctx->sfmt[j] = array[i];\n    }\n}\n#endif\n\n#if defined(BIG_ENDIAN64) && !defined(ONLY64) && !defined(HAVE_ALTIVEC)\nJEMALLOC_INLINE_C void swap(w128_t *array, int size) {\n    int i;\n    uint32_t x, y;\n\n    for (i = 0; i < size; i++) {\n\tx = array[i].u[0];\n\ty = array[i].u[2];\n\tarray[i].u[0] = array[i].u[1];\n\tarray[i].u[2] = array[i].u[3];\n\tarray[i].u[1] = x;\n\tarray[i].u[3] = y;\n    }\n}\n#endif\n/**\n * This function represents a function used in the initialization\n * by init_by_array\n * @param x 32-bit integer\n * @return 32-bit integer\n */\nstatic uint32_t func1(uint32_t x) {\n    return (x ^ (x >> 27)) * (uint32_t)1664525UL;\n}\n\n/**\n * This function represents a function used in the initialization\n * by init_by_array\n * @param x 32-bit integer\n * @return 32-bit integer\n */\nstatic uint32_t func2(uint32_t x) {\n    return (x ^ (x >> 27)) * (uint32_t)1566083941UL;\n}\n\n/**\n * This function certificate the period of 2^{MEXP}\n */\nstatic void period_certification(sfmt_t *ctx) {\n    int inner = 0;\n    int i, j;\n    uint32_t work;\n    uint32_t *psfmt32 = &ctx->sfmt[0].u[0];\n\n    for (i = 0; i < 4; i++)\n\tinner ^= psfmt32[idxof(i)] & parity[i];\n    for (i = 16; i > 0; i >>= 1)\n\tinner ^= inner >> i;\n    inner &= 1;\n    /* check OK */\n    if (inner == 1) {\n\treturn;\n    }\n    /* check NG, and modification */\n    for (i = 0; i < 4; i++) {\n\twork = 1;\n\tfor (j = 0; j < 32; j++) {\n\t    if ((work & parity[i]) != 0) {\n\t\tpsfmt32[idxof(i)] ^= work;\n\t\treturn;\n\t    }\n\t    work = work << 1;\n\t}\n    }\n}\n\n/*----------------\n  PUBLIC FUNCTIONS\n  ----------------*/\n/**\n * This function returns the identification string.\n * The string shows the word size, the Mersenne exponent,\n * and all parameters of this generator.\n */\nconst char *get_idstring(void) {\n    return IDSTR;\n}\n\n/**\n * This function returns the minimum size of array used for \\b\n * fill_array32() function.\n * @return minimum size of array used for fill_array32() function.\n */\nint get_min_array_size32(void) {\n    return N32;\n}\n\n/**\n * This function returns the minimum size of array used for \\b\n * fill_array64() function.\n * @return minimum size of array used for fill_array64() function.\n */\nint get_min_array_size64(void) {\n    return N64;\n}\n\n#ifndef ONLY64\n/**\n * This function generates and returns 32-bit pseudorandom number.\n * init_gen_rand or init_by_array must be called before this function.\n * @return 32-bit pseudorandom number\n */\nuint32_t gen_rand32(sfmt_t *ctx) {\n    uint32_t r;\n    uint32_t *psfmt32 = &ctx->sfmt[0].u[0];\n\n    assert(ctx->initialized);\n    if (ctx->idx >= N32) {\n\tgen_rand_all(ctx);\n\tctx->idx = 0;\n    }\n    r = psfmt32[ctx->idx++];\n    return r;\n}\n\n/* Generate a random integer in [0..limit). */\nuint32_t gen_rand32_range(sfmt_t *ctx, uint32_t limit) {\n    uint32_t ret, above;\n\n    above = 0xffffffffU - (0xffffffffU % limit);\n    while (1) {\n\tret = gen_rand32(ctx);\n\tif (ret < above) {\n\t    ret %= limit;\n\t    break;\n\t}\n    }\n    return ret;\n}\n#endif\n/**\n * This function generates and returns 64-bit pseudorandom number.\n * init_gen_rand or init_by_array must be called before this function.\n * The function gen_rand64 should not be called after gen_rand32,\n * unless an initialization is again executed. \n * @return 64-bit pseudorandom number\n */\nuint64_t gen_rand64(sfmt_t *ctx) {\n#if defined(BIG_ENDIAN64) && !defined(ONLY64)\n    uint32_t r1, r2;\n    uint32_t *psfmt32 = &ctx->sfmt[0].u[0];\n#else\n    uint64_t r;\n    uint64_t *psfmt64 = (uint64_t *)&ctx->sfmt[0].u[0];\n#endif\n\n    assert(ctx->initialized);\n    assert(ctx->idx % 2 == 0);\n\n    if (ctx->idx >= N32) {\n\tgen_rand_all(ctx);\n\tctx->idx = 0;\n    }\n#if defined(BIG_ENDIAN64) && !defined(ONLY64)\n    r1 = psfmt32[ctx->idx];\n    r2 = psfmt32[ctx->idx + 1];\n    ctx->idx += 2;\n    return ((uint64_t)r2 << 32) | r1;\n#else\n    r = psfmt64[ctx->idx / 2];\n    ctx->idx += 2;\n    return r;\n#endif\n}\n\n/* Generate a random integer in [0..limit). */\nuint64_t gen_rand64_range(sfmt_t *ctx, uint64_t limit) {\n    uint64_t ret, above;\n\n    above = KQU(0xffffffffffffffff) - (KQU(0xffffffffffffffff) % limit);\n    while (1) {\n\tret = gen_rand64(ctx);\n\tif (ret < above) {\n\t    ret %= limit;\n\t    break;\n\t}\n    }\n    return ret;\n}\n\n#ifndef ONLY64\n/**\n * This function generates pseudorandom 32-bit integers in the\n * specified array[] by one call. The number of pseudorandom integers\n * is specified by the argument size, which must be at least 624 and a\n * multiple of four.  The generation by this function is much faster\n * than the following gen_rand function.\n *\n * For initialization, init_gen_rand or init_by_array must be called\n * before the first call of this function. This function can not be\n * used after calling gen_rand function, without initialization.\n *\n * @param array an array where pseudorandom 32-bit integers are filled\n * by this function.  The pointer to the array must be \\b \"aligned\"\n * (namely, must be a multiple of 16) in the SIMD version, since it\n * refers to the address of a 128-bit integer.  In the standard C\n * version, the pointer is arbitrary.\n *\n * @param size the number of 32-bit pseudorandom integers to be\n * generated.  size must be a multiple of 4, and greater than or equal\n * to (MEXP / 128 + 1) * 4.\n *\n * @note \\b memalign or \\b posix_memalign is available to get aligned\n * memory. Mac OSX doesn't have these functions, but \\b malloc of OSX\n * returns the pointer to the aligned memory block.\n */\nvoid fill_array32(sfmt_t *ctx, uint32_t *array, int size) {\n    assert(ctx->initialized);\n    assert(ctx->idx == N32);\n    assert(size % 4 == 0);\n    assert(size >= N32);\n\n    gen_rand_array(ctx, (w128_t *)array, size / 4);\n    ctx->idx = N32;\n}\n#endif\n\n/**\n * This function generates pseudorandom 64-bit integers in the\n * specified array[] by one call. The number of pseudorandom integers\n * is specified by the argument size, which must be at least 312 and a\n * multiple of two.  The generation by this function is much faster\n * than the following gen_rand function.\n *\n * For initialization, init_gen_rand or init_by_array must be called\n * before the first call of this function. This function can not be\n * used after calling gen_rand function, without initialization.\n *\n * @param array an array where pseudorandom 64-bit integers are filled\n * by this function.  The pointer to the array must be \"aligned\"\n * (namely, must be a multiple of 16) in the SIMD version, since it\n * refers to the address of a 128-bit integer.  In the standard C\n * version, the pointer is arbitrary.\n *\n * @param size the number of 64-bit pseudorandom integers to be\n * generated.  size must be a multiple of 2, and greater than or equal\n * to (MEXP / 128 + 1) * 2\n *\n * @note \\b memalign or \\b posix_memalign is available to get aligned\n * memory. Mac OSX doesn't have these functions, but \\b malloc of OSX\n * returns the pointer to the aligned memory block.\n */\nvoid fill_array64(sfmt_t *ctx, uint64_t *array, int size) {\n    assert(ctx->initialized);\n    assert(ctx->idx == N32);\n    assert(size % 2 == 0);\n    assert(size >= N64);\n\n    gen_rand_array(ctx, (w128_t *)array, size / 2);\n    ctx->idx = N32;\n\n#if defined(BIG_ENDIAN64) && !defined(ONLY64)\n    swap((w128_t *)array, size /2);\n#endif\n}\n\n/**\n * This function initializes the internal state array with a 32-bit\n * integer seed.\n *\n * @param seed a 32-bit integer used as the seed.\n */\nsfmt_t *init_gen_rand(uint32_t seed) {\n    void *p;\n    sfmt_t *ctx;\n    int i;\n    uint32_t *psfmt32;\n\n    if (posix_memalign(&p, sizeof(w128_t), sizeof(sfmt_t)) != 0) {\n\treturn NULL;\n    }\n    ctx = (sfmt_t *)p;\n    psfmt32 = &ctx->sfmt[0].u[0];\n\n    psfmt32[idxof(0)] = seed;\n    for (i = 1; i < N32; i++) {\n\tpsfmt32[idxof(i)] = 1812433253UL * (psfmt32[idxof(i - 1)] \n\t\t\t\t\t    ^ (psfmt32[idxof(i - 1)] >> 30))\n\t    + i;\n    }\n    ctx->idx = N32;\n    period_certification(ctx);\n    ctx->initialized = 1;\n\n    return ctx;\n}\n\n/**\n * This function initializes the internal state array,\n * with an array of 32-bit integers used as the seeds\n * @param init_key the array of 32-bit integers, used as a seed.\n * @param key_length the length of init_key.\n */\nsfmt_t *init_by_array(uint32_t *init_key, int key_length) {\n    void *p;\n    sfmt_t *ctx;\n    int i, j, count;\n    uint32_t r;\n    int lag;\n    int mid;\n    int size = N * 4;\n    uint32_t *psfmt32;\n\n    if (posix_memalign(&p, sizeof(w128_t), sizeof(sfmt_t)) != 0) {\n\treturn NULL;\n    }\n    ctx = (sfmt_t *)p;\n    psfmt32 = &ctx->sfmt[0].u[0];\n\n    if (size >= 623) {\n\tlag = 11;\n    } else if (size >= 68) {\n\tlag = 7;\n    } else if (size >= 39) {\n\tlag = 5;\n    } else {\n\tlag = 3;\n    }\n    mid = (size - lag) / 2;\n\n    memset(ctx->sfmt, 0x8b, sizeof(ctx->sfmt));\n    if (key_length + 1 > N32) {\n\tcount = key_length + 1;\n    } else {\n\tcount = N32;\n    }\n    r = func1(psfmt32[idxof(0)] ^ psfmt32[idxof(mid)] \n\t      ^ psfmt32[idxof(N32 - 1)]);\n    psfmt32[idxof(mid)] += r;\n    r += key_length;\n    psfmt32[idxof(mid + lag)] += r;\n    psfmt32[idxof(0)] = r;\n\n    count--;\n    for (i = 1, j = 0; (j < count) && (j < key_length); j++) {\n\tr = func1(psfmt32[idxof(i)] ^ psfmt32[idxof((i + mid) % N32)] \n\t\t  ^ psfmt32[idxof((i + N32 - 1) % N32)]);\n\tpsfmt32[idxof((i + mid) % N32)] += r;\n\tr += init_key[j] + i;\n\tpsfmt32[idxof((i + mid + lag) % N32)] += r;\n\tpsfmt32[idxof(i)] = r;\n\ti = (i + 1) % N32;\n    }\n    for (; j < count; j++) {\n\tr = func1(psfmt32[idxof(i)] ^ psfmt32[idxof((i + mid) % N32)] \n\t\t  ^ psfmt32[idxof((i + N32 - 1) % N32)]);\n\tpsfmt32[idxof((i + mid) % N32)] += r;\n\tr += i;\n\tpsfmt32[idxof((i + mid + lag) % N32)] += r;\n\tpsfmt32[idxof(i)] = r;\n\ti = (i + 1) % N32;\n    }\n    for (j = 0; j < N32; j++) {\n\tr = func2(psfmt32[idxof(i)] + psfmt32[idxof((i + mid) % N32)] \n\t\t  + psfmt32[idxof((i + N32 - 1) % N32)]);\n\tpsfmt32[idxof((i + mid) % N32)] ^= r;\n\tr -= i;\n\tpsfmt32[idxof((i + mid + lag) % N32)] ^= r;\n\tpsfmt32[idxof(i)] = r;\n\ti = (i + 1) % N32;\n    }\n\n    ctx->idx = N32;\n    period_certification(ctx);\n    ctx->initialized = 1;\n\n    return ctx;\n}\n\nvoid fini_gen_rand(sfmt_t *ctx) {\n    assert(ctx != NULL);\n\n    ctx->initialized = 0;\n    free(ctx);\n}\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/deps/jemalloc/test/src/btalloc.c",
    "content": "#include \"test/jemalloc_test.h\"\n\nvoid *\nbtalloc(size_t size, unsigned bits)\n{\n\n\treturn (btalloc_0(size, bits));\n}\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/deps/jemalloc/test/src/btalloc_0.c",
    "content": "#include \"test/jemalloc_test.h\"\n\nbtalloc_n_gen(0)\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/deps/jemalloc/test/src/btalloc_1.c",
    "content": "#include \"test/jemalloc_test.h\"\n\nbtalloc_n_gen(1)\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/deps/jemalloc/test/src/math.c",
    "content": "#define\tMATH_C_\n#include \"test/jemalloc_test.h\"\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/deps/jemalloc/test/src/mq.c",
    "content": "#include \"test/jemalloc_test.h\"\n\n/*\n * Sleep for approximately ns nanoseconds.  No lower *nor* upper bound on sleep\n * time is guaranteed.\n */\nvoid\nmq_nanosleep(unsigned ns)\n{\n\n\tassert(ns <= 1000*1000*1000);\n\n#ifdef _WIN32\n\tSleep(ns / 1000);\n#else\n\t{\n\t\tstruct timespec timeout;\n\n\t\tif (ns < 1000*1000*1000) {\n\t\t\ttimeout.tv_sec = 0;\n\t\t\ttimeout.tv_nsec = ns;\n\t\t} else {\n\t\t\ttimeout.tv_sec = 1;\n\t\t\ttimeout.tv_nsec = 0;\n\t\t}\n\t\tnanosleep(&timeout, NULL);\n\t}\n#endif\n}\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/deps/jemalloc/test/src/mtx.c",
    "content": "#include \"test/jemalloc_test.h\"\n\n#ifndef _CRT_SPINCOUNT\n#define\t_CRT_SPINCOUNT 4000\n#endif\n\nbool\nmtx_init(mtx_t *mtx)\n{\n\n#ifdef _WIN32\n\tif (!InitializeCriticalSectionAndSpinCount(&mtx->lock, _CRT_SPINCOUNT))\n\t\treturn (true);\n#elif (defined(JEMALLOC_OSSPIN))\n\tmtx->lock = 0;\n#else\n\tpthread_mutexattr_t attr;\n\n\tif (pthread_mutexattr_init(&attr) != 0)\n\t\treturn (true);\n\tpthread_mutexattr_settype(&attr, PTHREAD_MUTEX_DEFAULT);\n\tif (pthread_mutex_init(&mtx->lock, &attr) != 0) {\n\t\tpthread_mutexattr_destroy(&attr);\n\t\treturn (true);\n\t}\n\tpthread_mutexattr_destroy(&attr);\n#endif\n\treturn (false);\n}\n\nvoid\nmtx_fini(mtx_t *mtx)\n{\n\n#ifdef _WIN32\n#elif (defined(JEMALLOC_OSSPIN))\n#else\n\tpthread_mutex_destroy(&mtx->lock);\n#endif\n}\n\nvoid\nmtx_lock(mtx_t *mtx)\n{\n\n#ifdef _WIN32\n\tEnterCriticalSection(&mtx->lock);\n#elif (defined(JEMALLOC_OSSPIN))\n\tOSSpinLockLock(&mtx->lock);\n#else\n\tpthread_mutex_lock(&mtx->lock);\n#endif\n}\n\nvoid\nmtx_unlock(mtx_t *mtx)\n{\n\n#ifdef _WIN32\n\tLeaveCriticalSection(&mtx->lock);\n#elif (defined(JEMALLOC_OSSPIN))\n\tOSSpinLockUnlock(&mtx->lock);\n#else\n\tpthread_mutex_unlock(&mtx->lock);\n#endif\n}\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/deps/jemalloc/test/src/test.c",
    "content": "#include \"test/jemalloc_test.h\"\n\nstatic unsigned\t\ttest_count = 0;\nstatic test_status_t\ttest_counts[test_status_count] = {0, 0, 0};\nstatic test_status_t\ttest_status = test_status_pass;\nstatic const char *\ttest_name = \"\";\n\nJEMALLOC_FORMAT_PRINTF(1, 2)\nvoid\ntest_skip(const char *format, ...)\n{\n\tva_list ap;\n\n\tva_start(ap, format);\n\tmalloc_vcprintf(NULL, NULL, format, ap);\n\tva_end(ap);\n\tmalloc_printf(\"\\n\");\n\ttest_status = test_status_skip;\n}\n\nJEMALLOC_FORMAT_PRINTF(1, 2)\nvoid\ntest_fail(const char *format, ...)\n{\n\tva_list ap;\n\n\tva_start(ap, format);\n\tmalloc_vcprintf(NULL, NULL, format, ap);\n\tva_end(ap);\n\tmalloc_printf(\"\\n\");\n\ttest_status = test_status_fail;\n}\n\nstatic const char *\ntest_status_string(test_status_t test_status)\n{\n\n\tswitch (test_status) {\n\tcase test_status_pass: return \"pass\";\n\tcase test_status_skip: return \"skip\";\n\tcase test_status_fail: return \"fail\";\n\tdefault: not_reached();\n\t}\n}\n\nvoid\np_test_init(const char *name)\n{\n\n\ttest_count++;\n\ttest_status = test_status_pass;\n\ttest_name = name;\n}\n\nvoid\np_test_fini(void)\n{\n\n\ttest_counts[test_status]++;\n\tmalloc_printf(\"%s: %s\\n\", test_name, test_status_string(test_status));\n}\n\nstatic test_status_t\np_test_impl(bool do_malloc_init, test_t *t, va_list ap)\n{\n\ttest_status_t ret;\n\n\tif (do_malloc_init) {\n\t\t/*\n\t\t * Make sure initialization occurs prior to running tests.\n\t\t * Tests are special because they may use internal facilities\n\t\t * prior to triggering initialization as a side effect of\n\t\t * calling into the public API.\n\t\t */\n\t\tif (nallocx(1, 0) == 0) {\n\t\t\tmalloc_printf(\"Initialization error\");\n\t\t\treturn (test_status_fail);\n\t\t}\n\t}\n\n\tret = test_status_pass;\n\tfor (; t != NULL; t = va_arg(ap, test_t *)) {\n\t\tt();\n\t\tif (test_status > ret)\n\t\t\tret = test_status;\n\t}\n\n\tmalloc_printf(\"--- %s: %u/%u, %s: %u/%u, %s: %u/%u ---\\n\",\n\t    test_status_string(test_status_pass),\n\t    test_counts[test_status_pass], test_count,\n\t    test_status_string(test_status_skip),\n\t    test_counts[test_status_skip], test_count,\n\t    test_status_string(test_status_fail),\n\t    test_counts[test_status_fail], test_count);\n\n\treturn (ret);\n}\n\ntest_status_t\np_test(test_t *t, ...)\n{\n\ttest_status_t ret;\n\tva_list ap;\n\n\tret = test_status_pass;\n\tva_start(ap, t);\n\tret = p_test_impl(true, t, ap);\n\tva_end(ap);\n\n\treturn (ret);\n}\n\ntest_status_t\np_test_no_malloc_init(test_t *t, ...)\n{\n\ttest_status_t ret;\n\tva_list ap;\n\n\tret = test_status_pass;\n\tva_start(ap, t);\n\tret = p_test_impl(false, t, ap);\n\tva_end(ap);\n\n\treturn (ret);\n}\n\nvoid\np_test_fail(const char *prefix, const char *message)\n{\n\n\tmalloc_cprintf(NULL, NULL, \"%s%s\\n\", prefix, message);\n\ttest_status = test_status_fail;\n}\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/deps/jemalloc/test/src/thd.c",
    "content": "#include \"test/jemalloc_test.h\"\n\n#ifdef _WIN32\nvoid\nthd_create(thd_t *thd, void *(*proc)(void *), void *arg)\n{\n\tLPTHREAD_START_ROUTINE routine = (LPTHREAD_START_ROUTINE)proc;\n\t*thd = CreateThread(NULL, 0, routine, arg, 0, NULL);\n\tif (*thd == NULL)\n\t\ttest_fail(\"Error in CreateThread()\\n\");\n}\n\nvoid\nthd_join(thd_t thd, void **ret)\n{\n\n\tif (WaitForSingleObject(thd, INFINITE) == WAIT_OBJECT_0 && ret) {\n\t\tDWORD exit_code;\n\t\tGetExitCodeThread(thd, (LPDWORD) &exit_code);\n\t\t*ret = (void *)(uintptr_t)exit_code;\n\t}\n}\n\n#else\nvoid\nthd_create(thd_t *thd, void *(*proc)(void *), void *arg)\n{\n\n\tif (pthread_create(thd, NULL, proc, arg) != 0)\n\t\ttest_fail(\"Error in pthread_create()\\n\");\n}\n\nvoid\nthd_join(thd_t thd, void **ret)\n{\n\n\tpthread_join(thd, ret);\n}\n#endif\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/deps/jemalloc/test/src/timer.c",
    "content": "#include \"test/jemalloc_test.h\"\n\nvoid\ntimer_start(timedelta_t *timer)\n{\n\n\tnstime_init(&timer->t0, 0);\n\tnstime_update(&timer->t0);\n}\n\nvoid\ntimer_stop(timedelta_t *timer)\n{\n\n\tnstime_copy(&timer->t1, &timer->t0);\n\tnstime_update(&timer->t1);\n}\n\nuint64_t\ntimer_usec(const timedelta_t *timer)\n{\n\tnstime_t delta;\n\n\tnstime_copy(&delta, &timer->t1);\n\tnstime_subtract(&delta, &timer->t0);\n\treturn (nstime_ns(&delta) / 1000);\n}\n\nvoid\ntimer_ratio(timedelta_t *a, timedelta_t *b, char *buf, size_t buflen)\n{\n\tuint64_t t0 = timer_usec(a);\n\tuint64_t t1 = timer_usec(b);\n\tuint64_t mult;\n\tsize_t i = 0;\n\tsize_t j, n;\n\n\t/* Whole. */\n\tn = malloc_snprintf(&buf[i], buflen-i, \"%\"FMTu64, t0 / t1);\n\ti += n;\n\tif (i >= buflen)\n\t\treturn;\n\tmult = 1;\n\tfor (j = 0; j < n; j++)\n\t\tmult *= 10;\n\n\t/* Decimal. */\n\tn = malloc_snprintf(&buf[i], buflen-i, \".\");\n\ti += n;\n\n\t/* Fraction. */\n\twhile (i < buflen-1) {\n\t\tuint64_t round = (i+1 == buflen-1 && ((t0 * mult * 10 / t1) % 10\n\t\t    >= 5)) ? 1 : 0;\n\t\tn = malloc_snprintf(&buf[i], buflen-i,\n\t\t    \"%\"FMTu64, (t0 * mult / t1) % 10 + round);\n\t\ti += n;\n\t\tmult *= 10;\n\t}\n}\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/deps/jemalloc/test/stress/microbench.c",
    "content": "#include \"test/jemalloc_test.h\"\n\nJEMALLOC_INLINE_C void\ntime_func(timedelta_t *timer, uint64_t nwarmup, uint64_t niter,\n    void (*func)(void))\n{\n\tuint64_t i;\n\n\tfor (i = 0; i < nwarmup; i++)\n\t\tfunc();\n\ttimer_start(timer);\n\tfor (i = 0; i < niter; i++)\n\t\tfunc();\n\ttimer_stop(timer);\n}\n\nvoid\ncompare_funcs(uint64_t nwarmup, uint64_t niter, const char *name_a,\n    void (*func_a), const char *name_b, void (*func_b))\n{\n\ttimedelta_t timer_a, timer_b;\n\tchar ratio_buf[6];\n\tvoid *p;\n\n\tp = mallocx(1, 0);\n\tif (p == NULL) {\n\t\ttest_fail(\"Unexpected mallocx() failure\");\n\t\treturn;\n\t}\n\n\ttime_func(&timer_a, nwarmup, niter, func_a);\n\ttime_func(&timer_b, nwarmup, niter, func_b);\n\n\ttimer_ratio(&timer_a, &timer_b, ratio_buf, sizeof(ratio_buf));\n\tmalloc_printf(\"%\"FMTu64\" iterations, %s=%\"FMTu64\"us, \"\n\t    \"%s=%\"FMTu64\"us, ratio=1:%s\\n\",\n\t    niter, name_a, timer_usec(&timer_a), name_b, timer_usec(&timer_b),\n\t    ratio_buf);\n\n\tdallocx(p, 0);\n}\n\nstatic void\nmalloc_free(void)\n{\n\t/* The compiler can optimize away free(malloc(1))! */\n\tvoid *p = malloc(1);\n\tif (p == NULL) {\n\t\ttest_fail(\"Unexpected malloc() failure\");\n\t\treturn;\n\t}\n\tfree(p);\n}\n\nstatic void\nmallocx_free(void)\n{\n\tvoid *p = mallocx(1, 0);\n\tif (p == NULL) {\n\t\ttest_fail(\"Unexpected mallocx() failure\");\n\t\treturn;\n\t}\n\tfree(p);\n}\n\nTEST_BEGIN(test_malloc_vs_mallocx)\n{\n\n\tcompare_funcs(10*1000*1000, 100*1000*1000, \"malloc\",\n\t    malloc_free, \"mallocx\", mallocx_free);\n}\nTEST_END\n\nstatic void\nmalloc_dallocx(void)\n{\n\tvoid *p = malloc(1);\n\tif (p == NULL) {\n\t\ttest_fail(\"Unexpected malloc() failure\");\n\t\treturn;\n\t}\n\tdallocx(p, 0);\n}\n\nstatic void\nmalloc_sdallocx(void)\n{\n\tvoid *p = malloc(1);\n\tif (p == NULL) {\n\t\ttest_fail(\"Unexpected malloc() failure\");\n\t\treturn;\n\t}\n\tsdallocx(p, 1, 0);\n}\n\nTEST_BEGIN(test_free_vs_dallocx)\n{\n\n\tcompare_funcs(10*1000*1000, 100*1000*1000, \"free\", malloc_free,\n\t    \"dallocx\", malloc_dallocx);\n}\nTEST_END\n\nTEST_BEGIN(test_dallocx_vs_sdallocx)\n{\n\n\tcompare_funcs(10*1000*1000, 100*1000*1000, \"dallocx\", malloc_dallocx,\n\t    \"sdallocx\", malloc_sdallocx);\n}\nTEST_END\n\nstatic void\nmalloc_mus_free(void)\n{\n\tvoid *p;\n\n\tp = malloc(1);\n\tif (p == NULL) {\n\t\ttest_fail(\"Unexpected malloc() failure\");\n\t\treturn;\n\t}\n\tmalloc_usable_size(p);\n\tfree(p);\n}\n\nstatic void\nmalloc_sallocx_free(void)\n{\n\tvoid *p;\n\n\tp = malloc(1);\n\tif (p == NULL) {\n\t\ttest_fail(\"Unexpected malloc() failure\");\n\t\treturn;\n\t}\n\tif (sallocx(p, 0) < 1)\n\t\ttest_fail(\"Unexpected sallocx() failure\");\n\tfree(p);\n}\n\nTEST_BEGIN(test_mus_vs_sallocx)\n{\n\n\tcompare_funcs(10*1000*1000, 100*1000*1000, \"malloc_usable_size\",\n\t    malloc_mus_free, \"sallocx\", malloc_sallocx_free);\n}\nTEST_END\n\nstatic void\nmalloc_nallocx_free(void)\n{\n\tvoid *p;\n\n\tp = malloc(1);\n\tif (p == NULL) {\n\t\ttest_fail(\"Unexpected malloc() failure\");\n\t\treturn;\n\t}\n\tif (nallocx(1, 0) < 1)\n\t\ttest_fail(\"Unexpected nallocx() failure\");\n\tfree(p);\n}\n\nTEST_BEGIN(test_sallocx_vs_nallocx)\n{\n\n\tcompare_funcs(10*1000*1000, 100*1000*1000, \"sallocx\",\n\t    malloc_sallocx_free, \"nallocx\", malloc_nallocx_free);\n}\nTEST_END\n\nint\nmain(void)\n{\n\n\treturn (test(\n\t    test_malloc_vs_mallocx,\n\t    test_free_vs_dallocx,\n\t    test_dallocx_vs_sdallocx,\n\t    test_mus_vs_sallocx,\n\t    test_sallocx_vs_nallocx));\n}\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/deps/jemalloc/test/test.sh.in",
    "content": "#!/bin/sh\n\ncase @abi@ in\n  macho)\n    export DYLD_FALLBACK_LIBRARY_PATH=\"@objroot@lib\"\n    ;;\n  pecoff)\n    export PATH=\"${PATH}:@objroot@lib\"\n    ;;\n  *)\n    ;;\nesac\n\n# Corresponds to test_status_t.\npass_code=0\nskip_code=1\nfail_code=2\n\npass_count=0\nskip_count=0\nfail_count=0\nfor t in $@; do\n  if [ $pass_count -ne 0 -o $skip_count -ne 0 -o $fail_count != 0 ] ; then\n    echo\n  fi\n  echo \"=== ${t} ===\"\n  ${t}@exe@ @abs_srcroot@ @abs_objroot@\n  result_code=$?\n  case ${result_code} in\n    ${pass_code})\n      pass_count=$((pass_count+1))\n      ;;\n    ${skip_code})\n      skip_count=$((skip_count+1))\n      ;;\n    ${fail_code})\n      fail_count=$((fail_count+1))\n      ;;\n    *)\n      echo \"Test harness error\" 1>&2\n      exit 1\n  esac\ndone\n\ntotal_count=`expr ${pass_count} + ${skip_count} + ${fail_count}`\necho\necho \"Test suite summary: pass: ${pass_count}/${total_count}, skip: ${skip_count}/${total_count}, fail: ${fail_count}/${total_count}\"\n\nif [ ${fail_count} -eq 0 ] ; then\n  exit 0\nelse\n  exit 1\nfi\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/deps/jemalloc/test/unit/SFMT.c",
    "content": "/*\n * This file derives from SFMT 1.3.3\n * (http://www.math.sci.hiroshima-u.ac.jp/~m-mat/MT/SFMT/index.html), which was\n * released under the terms of the following license:\n *\n *   Copyright (c) 2006,2007 Mutsuo Saito, Makoto Matsumoto and Hiroshima\n *   University. All rights reserved.\n *\n *   Redistribution and use in source and binary forms, with or without\n *   modification, are permitted provided that the following conditions are\n *   met:\n *\n *       * Redistributions of source code must retain the above copyright\n *         notice, this list of conditions and the following disclaimer.\n *       * Redistributions in binary form must reproduce the above\n *         copyright notice, this list of conditions and the following\n *         disclaimer in the documentation and/or other materials provided\n *         with the distribution.\n *       * Neither the name of the Hiroshima University nor the names of\n *         its contributors may be used to endorse or promote products\n *         derived from this software without specific prior written\n *         permission.\n *\n *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n *   \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\n *   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\n *   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\n *   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n *   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\n *   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n *   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n *   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n *   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n *   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n#include \"test/jemalloc_test.h\"\n\n#define\tBLOCK_SIZE 10000\n#define\tBLOCK_SIZE64 (BLOCK_SIZE / 2)\n#define\tCOUNT_1 1000\n#define\tCOUNT_2 700\n\nstatic const uint32_t init_gen_rand_32_expected[] = {\n\t3440181298U, 1564997079U, 1510669302U, 2930277156U, 1452439940U,\n\t3796268453U,  423124208U, 2143818589U, 3827219408U, 2987036003U,\n\t2674978610U, 1536842514U, 2027035537U, 2534897563U, 1686527725U,\n\t 545368292U, 1489013321U, 1370534252U, 4231012796U, 3994803019U,\n\t1764869045U,  824597505U,  862581900U, 2469764249U,  812862514U,\n\t 359318673U,  116957936U, 3367389672U, 2327178354U, 1898245200U,\n\t3206507879U, 2378925033U, 1040214787U, 2524778605U, 3088428700U,\n\t1417665896U,  964324147U, 2282797708U, 2456269299U,  313400376U,\n\t2245093271U, 1015729427U, 2694465011U, 3246975184U, 1992793635U,\n\t 463679346U, 3721104591U, 3475064196U,  856141236U, 1499559719U,\n\t3522818941U, 3721533109U, 1954826617U, 1282044024U, 1543279136U,\n\t1301863085U, 2669145051U, 4221477354U, 3896016841U, 3392740262U,\n\t 462466863U, 1037679449U, 1228140306U,  922298197U, 1205109853U,\n\t1872938061U, 3102547608U, 2742766808U, 1888626088U, 4028039414U,\n\t 157593879U, 1136901695U, 4038377686U, 3572517236U, 4231706728U,\n\t2997311961U, 1189931652U, 3981543765U, 2826166703U,   87159245U,\n\t1721379072U, 3897926942U, 1790395498U, 2569178939U, 1047368729U,\n\t2340259131U, 3144212906U, 2301169789U, 2442885464U, 3034046771U,\n\t3667880593U, 3935928400U, 2372805237U, 1666397115U, 2460584504U,\n\t 513866770U, 3810869743U, 2147400037U, 2792078025U, 2941761810U,\n\t3212265810U,  984692259U,  346590253U, 1804179199U, 3298543443U,\n\t 750108141U, 2880257022U,  243310542U, 1869036465U, 1588062513U,\n\t2983949551U, 1931450364U, 4034505847U, 2735030199U, 1628461061U,\n\t2539522841U,  127965585U, 3992448871U,  913388237U,  559130076U,\n\t1202933193U, 4087643167U, 2590021067U, 2256240196U, 1746697293U,\n\t1013913783U, 1155864921U, 2715773730U,  915061862U, 1948766573U,\n\t2322882854U, 3761119102U, 1343405684U, 3078711943U, 3067431651U,\n\t3245156316U, 3588354584U, 3484623306U, 3899621563U, 4156689741U,\n\t3237090058U, 3880063844U,  862416318U, 4039923869U, 2303788317U,\n\t3073590536U,  701653667U, 2131530884U, 3169309950U, 2028486980U,\n\t 747196777U, 3620218225U,  432016035U, 1449580595U, 2772266392U,\n\t 444224948U, 1662832057U, 3184055582U, 3028331792U, 1861686254U,\n\t1104864179U,  342430307U, 1350510923U, 3024656237U, 1028417492U,\n\t2870772950U,  290847558U, 3675663500U,  508431529U, 4264340390U,\n\t2263569913U, 1669302976U,  519511383U, 2706411211U, 3764615828U,\n\t3883162495U, 4051445305U, 2412729798U, 3299405164U, 3991911166U,\n\t2348767304U, 2664054906U, 3763609282U,  593943581U, 3757090046U,\n\t2075338894U, 2020550814U, 4287452920U, 4290140003U, 1422957317U,\n\t2512716667U, 2003485045U, 2307520103U, 2288472169U, 3940751663U,\n\t4204638664U, 2892583423U, 1710068300U, 3904755993U, 2363243951U,\n\t3038334120U,  547099465U,  771105860U, 3199983734U, 4282046461U,\n\t2298388363U,  934810218U, 2837827901U, 3952500708U, 2095130248U,\n\t3083335297U,   26885281U, 3932155283U, 1531751116U, 1425227133U,\n\t 495654159U, 3279634176U, 3855562207U, 3957195338U, 4159985527U,\n\t 893375062U, 1875515536U, 1327247422U, 3754140693U, 1028923197U,\n\t1729880440U,  805571298U,  448971099U, 2726757106U, 2749436461U,\n\t2485987104U,  175337042U, 3235477922U, 3882114302U, 2020970972U,\n\t 943926109U, 2762587195U, 1904195558U, 3452650564U,  108432281U,\n\t3893463573U, 3977583081U, 2636504348U, 1110673525U, 3548479841U,\n\t4258854744U,  980047703U, 4057175418U, 3890008292U,  145653646U,\n\t3141868989U, 3293216228U, 1194331837U, 1254570642U, 3049934521U,\n\t2868313360U, 2886032750U, 1110873820U,  279553524U, 3007258565U,\n\t1104807822U, 3186961098U,  315764646U, 2163680838U, 3574508994U,\n\t3099755655U,  191957684U, 3642656737U, 3317946149U, 3522087636U,\n\t 444526410U,  779157624U, 1088229627U, 1092460223U, 1856013765U,\n\t3659877367U,  368270451U,  503570716U, 3000984671U, 2742789647U,\n\t 928097709U, 2914109539U,  308843566U, 2816161253U, 3667192079U,\n\t2762679057U, 3395240989U, 2928925038U, 1491465914U, 3458702834U,\n\t3787782576U, 2894104823U, 1296880455U, 1253636503U,  989959407U,\n\t2291560361U, 2776790436U, 1913178042U, 1584677829U,  689637520U,\n\t1898406878U,  688391508U, 3385234998U,  845493284U, 1943591856U,\n\t2720472050U,  222695101U, 1653320868U, 2904632120U, 4084936008U,\n\t1080720688U, 3938032556U,  387896427U, 2650839632U,   99042991U,\n\t1720913794U, 1047186003U, 1877048040U, 2090457659U,  517087501U,\n\t4172014665U, 2129713163U, 2413533132U, 2760285054U, 4129272496U,\n\t1317737175U, 2309566414U, 2228873332U, 3889671280U, 1110864630U,\n\t3576797776U, 2074552772U,  832002644U, 3097122623U, 2464859298U,\n\t2679603822U, 1667489885U, 3237652716U, 1478413938U, 1719340335U,\n\t2306631119U,  639727358U, 3369698270U,  226902796U, 2099920751U,\n\t1892289957U, 2201594097U, 3508197013U, 3495811856U, 3900381493U,\n\t 841660320U, 3974501451U, 3360949056U, 1676829340U,  728899254U,\n\t2047809627U, 2390948962U,  670165943U, 3412951831U, 4189320049U,\n\t1911595255U, 2055363086U,  507170575U,  418219594U, 4141495280U,\n\t2692088692U, 4203630654U, 3540093932U,  791986533U, 2237921051U,\n\t2526864324U, 2956616642U, 1394958700U, 1983768223U, 1893373266U,\n\t 591653646U,  228432437U, 1611046598U, 3007736357U, 1040040725U,\n\t2726180733U, 2789804360U, 4263568405U,  829098158U, 3847722805U,\n\t1123578029U, 1804276347U,  997971319U, 4203797076U, 4185199713U,\n\t2811733626U, 2343642194U, 2985262313U, 1417930827U, 3759587724U,\n\t1967077982U, 1585223204U, 1097475516U, 1903944948U,  740382444U,\n\t1114142065U, 1541796065U, 1718384172U, 1544076191U, 1134682254U,\n\t3519754455U, 2866243923U,  341865437U,  645498576U, 2690735853U,\n\t1046963033U, 2493178460U, 1187604696U, 1619577821U,  488503634U,\n\t3255768161U, 2306666149U, 1630514044U, 2377698367U, 2751503746U,\n\t3794467088U, 1796415981U, 3657173746U,  409136296U, 1387122342U,\n\t1297726519U,  219544855U, 4270285558U,  437578827U, 1444698679U,\n\t2258519491U,  963109892U, 3982244073U, 3351535275U,  385328496U,\n\t1804784013U,  698059346U, 3920535147U,  708331212U,  784338163U,\n\t 785678147U, 1238376158U, 1557298846U, 2037809321U,  271576218U,\n\t4145155269U, 1913481602U, 2763691931U,  588981080U, 1201098051U,\n\t3717640232U, 1509206239U,  662536967U, 3180523616U, 1133105435U,\n\t2963500837U, 2253971215U, 3153642623U, 1066925709U, 2582781958U,\n\t3034720222U, 1090798544U, 2942170004U, 4036187520U,  686972531U,\n\t2610990302U, 2641437026U, 1837562420U,  722096247U, 1315333033U,\n\t2102231203U, 3402389208U, 3403698140U, 1312402831U, 2898426558U,\n\t 814384596U,  385649582U, 1916643285U, 1924625106U, 2512905582U,\n\t2501170304U, 4275223366U, 2841225246U, 1467663688U, 3563567847U,\n\t2969208552U,  884750901U,  102992576U,  227844301U, 3681442994U,\n\t3502881894U, 4034693299U, 1166727018U, 1697460687U, 1737778332U,\n\t1787161139U, 1053003655U, 1215024478U, 2791616766U, 2525841204U,\n\t1629323443U,    3233815U, 2003823032U, 3083834263U, 2379264872U,\n\t3752392312U, 1287475550U, 3770904171U, 3004244617U, 1502117784U,\n\t 918698423U, 2419857538U, 3864502062U, 1751322107U, 2188775056U,\n\t4018728324U,  983712955U,  440071928U, 3710838677U, 2001027698U,\n\t3994702151U,   22493119U, 3584400918U, 3446253670U, 4254789085U,\n\t1405447860U, 1240245579U, 1800644159U, 1661363424U, 3278326132U,\n\t3403623451U,   67092802U, 2609352193U, 3914150340U, 1814842761U,\n\t3610830847U,  591531412U, 3880232807U, 1673505890U, 2585326991U,\n\t1678544474U, 3148435887U, 3457217359U, 1193226330U, 2816576908U,\n\t 154025329U,  121678860U, 1164915738U,  973873761U,  269116100U,\n\t  52087970U,  744015362U,  498556057U,   94298882U, 1563271621U,\n\t2383059628U, 4197367290U, 3958472990U, 2592083636U, 2906408439U,\n\t1097742433U, 3924840517U,  264557272U, 2292287003U, 3203307984U,\n\t4047038857U, 3820609705U, 2333416067U, 1839206046U, 3600944252U,\n\t3412254904U,  583538222U, 2390557166U, 4140459427U, 2810357445U,\n\t 226777499U, 2496151295U, 2207301712U, 3283683112U,  611630281U,\n\t1933218215U, 3315610954U, 3889441987U, 3719454256U, 3957190521U,\n\t1313998161U, 2365383016U, 3146941060U, 1801206260U,  796124080U,\n\t2076248581U, 1747472464U, 3254365145U,  595543130U, 3573909503U,\n\t3758250204U, 2020768540U, 2439254210U,   93368951U, 3155792250U,\n\t2600232980U, 3709198295U, 3894900440U, 2971850836U, 1578909644U,\n\t1443493395U, 2581621665U, 3086506297U, 2443465861U,  558107211U,\n\t1519367835U,  249149686U,  908102264U, 2588765675U, 1232743965U,\n\t1001330373U, 3561331654U, 2259301289U, 1564977624U, 3835077093U,\n\t 727244906U, 4255738067U, 1214133513U, 2570786021U, 3899704621U,\n\t1633861986U, 1636979509U, 1438500431U,   58463278U, 2823485629U,\n\t2297430187U, 2926781924U, 3371352948U, 1864009023U, 2722267973U,\n\t1444292075U,  437703973U, 1060414512U,  189705863U,  910018135U,\n\t4077357964U,  884213423U, 2644986052U, 3973488374U, 1187906116U,\n\t2331207875U,  780463700U, 3713351662U, 3854611290U,  412805574U,\n\t2978462572U, 2176222820U,  829424696U, 2790788332U, 2750819108U,\n\t1594611657U, 3899878394U, 3032870364U, 1702887682U, 1948167778U,\n\t  14130042U,  192292500U,  947227076U,   90719497U, 3854230320U,\n\t 784028434U, 2142399787U, 1563449646U, 2844400217U,  819143172U,\n\t2883302356U, 2328055304U, 1328532246U, 2603885363U, 3375188924U,\n\t 933941291U, 3627039714U, 2129697284U, 2167253953U, 2506905438U,\n\t1412424497U, 2981395985U, 1418359660U, 2925902456U,   52752784U,\n\t3713667988U, 3924669405U,  648975707U, 1145520213U, 4018650664U,\n\t3805915440U, 2380542088U, 2013260958U, 3262572197U, 2465078101U,\n\t1114540067U, 3728768081U, 2396958768U,  590672271U,  904818725U,\n\t4263660715U,  700754408U, 1042601829U, 4094111823U, 4274838909U,\n\t2512692617U, 2774300207U, 2057306915U, 3470942453U,   99333088U,\n\t1142661026U, 2889931380U,   14316674U, 2201179167U,  415289459U,\n\t 448265759U, 3515142743U, 3254903683U,  246633281U, 1184307224U,\n\t2418347830U, 2092967314U, 2682072314U, 2558750234U, 2000352263U,\n\t1544150531U,  399010405U, 1513946097U,  499682937U,  461167460U,\n\t3045570638U, 1633669705U,  851492362U, 4052801922U, 2055266765U,\n\t 635556996U,  368266356U, 2385737383U, 3218202352U, 2603772408U,\n\t 349178792U,  226482567U, 3102426060U, 3575998268U, 2103001871U,\n\t3243137071U,  225500688U, 1634718593U, 4283311431U, 4292122923U,\n\t3842802787U,  811735523U,  105712518U,  663434053U, 1855889273U,\n\t2847972595U, 1196355421U, 2552150115U, 4254510614U, 3752181265U,\n\t3430721819U, 3828705396U, 3436287905U, 3441964937U, 4123670631U,\n\t 353001539U,  459496439U, 3799690868U, 1293777660U, 2761079737U,\n\t 498096339U, 3398433374U, 4080378380U, 2304691596U, 2995729055U,\n\t4134660419U, 3903444024U, 3576494993U,  203682175U, 3321164857U,\n\t2747963611U,   79749085U, 2992890370U, 1240278549U, 1772175713U,\n\t2111331972U, 2655023449U, 1683896345U, 2836027212U, 3482868021U,\n\t2489884874U,  756853961U, 2298874501U, 4013448667U, 4143996022U,\n\t2948306858U, 4132920035U, 1283299272U,  995592228U, 3450508595U,\n\t1027845759U, 1766942720U, 3861411826U, 1446861231U,   95974993U,\n\t3502263554U, 1487532194U,  601502472U, 4129619129U,  250131773U,\n\t2050079547U, 3198903947U, 3105589778U, 4066481316U, 3026383978U,\n\t2276901713U,  365637751U, 2260718426U, 1394775634U, 1791172338U,\n\t2690503163U, 2952737846U, 1568710462U,  732623190U, 2980358000U,\n\t1053631832U, 1432426951U, 3229149635U, 1854113985U, 3719733532U,\n\t3204031934U,  735775531U,  107468620U, 3734611984U,  631009402U,\n\t3083622457U, 4109580626U,  159373458U, 1301970201U, 4132389302U,\n\t1293255004U,  847182752U, 4170022737U,   96712900U, 2641406755U,\n\t1381727755U,  405608287U, 4287919625U, 1703554290U, 3589580244U,\n\t2911403488U,    2166565U, 2647306451U, 2330535117U, 1200815358U,\n\t1165916754U,  245060911U, 4040679071U, 3684908771U, 2452834126U,\n\t2486872773U, 2318678365U, 2940627908U, 1837837240U, 3447897409U,\n\t4270484676U, 1495388728U, 3754288477U, 4204167884U, 1386977705U,\n\t2692224733U, 3076249689U, 4109568048U, 4170955115U, 4167531356U,\n\t4020189950U, 4261855038U, 3036907575U, 3410399885U, 3076395737U,\n\t1046178638U,  144496770U,  230725846U, 3349637149U,   17065717U,\n\t2809932048U, 2054581785U, 3608424964U, 3259628808U,  134897388U,\n\t3743067463U,  257685904U, 3795656590U, 1562468719U, 3589103904U,\n\t3120404710U,  254684547U, 2653661580U, 3663904795U, 2631942758U,\n\t1063234347U, 2609732900U, 2332080715U, 3521125233U, 1180599599U,\n\t1935868586U, 4110970440U,  296706371U, 2128666368U, 1319875791U,\n\t1570900197U, 3096025483U, 1799882517U, 1928302007U, 1163707758U,\n\t1244491489U, 3533770203U,  567496053U, 2757924305U, 2781639343U,\n\t2818420107U,  560404889U, 2619609724U, 4176035430U, 2511289753U,\n\t2521842019U, 3910553502U, 2926149387U, 3302078172U, 4237118867U,\n\t 330725126U,  367400677U,  888239854U,  545570454U, 4259590525U,\n\t 134343617U, 1102169784U, 1647463719U, 3260979784U, 1518840883U,\n\t3631537963U, 3342671457U, 1301549147U, 2083739356U,  146593792U,\n\t3217959080U,  652755743U, 2032187193U, 3898758414U, 1021358093U,\n\t4037409230U, 2176407931U, 3427391950U, 2883553603U,  985613827U,\n\t3105265092U, 3423168427U, 3387507672U,  467170288U, 2141266163U,\n\t3723870208U,  916410914U, 1293987799U, 2652584950U,  769160137U,\n\t3205292896U, 1561287359U, 1684510084U, 3136055621U, 3765171391U,\n\t 639683232U, 2639569327U, 1218546948U, 4263586685U, 3058215773U,\n\t2352279820U,  401870217U, 2625822463U, 1529125296U, 2981801895U,\n\t1191285226U, 4027725437U, 3432700217U, 4098835661U,  971182783U,\n\t2443861173U, 3881457123U, 3874386651U,  457276199U, 2638294160U,\n\t4002809368U,  421169044U, 1112642589U, 3076213779U, 3387033971U,\n\t2499610950U, 3057240914U, 1662679783U,  461224431U, 1168395933U\n};\nstatic const uint32_t init_by_array_32_expected[] = {\n\t2920711183U, 3885745737U, 3501893680U,  856470934U, 1421864068U,\n\t 277361036U, 1518638004U, 2328404353U, 3355513634U,   64329189U,\n\t1624587673U, 3508467182U, 2481792141U, 3706480799U, 1925859037U,\n\t2913275699U,  882658412U,  384641219U,  422202002U, 1873384891U,\n\t2006084383U, 3924929912U, 1636718106U, 3108838742U, 1245465724U,\n\t4195470535U,  779207191U, 1577721373U, 1390469554U, 2928648150U,\n\t 121399709U, 3170839019U, 4044347501U,  953953814U, 3821710850U,\n\t3085591323U, 3666535579U, 3577837737U, 2012008410U, 3565417471U,\n\t4044408017U,  433600965U, 1637785608U, 1798509764U,  860770589U,\n\t3081466273U, 3982393409U, 2451928325U, 3437124742U, 4093828739U,\n\t3357389386U, 2154596123U,  496568176U, 2650035164U, 2472361850U,\n\t   3438299U, 2150366101U, 1577256676U, 3802546413U, 1787774626U,\n\t4078331588U, 3706103141U,  170391138U, 3806085154U, 1680970100U,\n\t1961637521U, 3316029766U,  890610272U, 1453751581U, 1430283664U,\n\t3051057411U, 3597003186U,  542563954U, 3796490244U, 1690016688U,\n\t3448752238U,  440702173U,  347290497U, 1121336647U, 2540588620U,\n\t 280881896U, 2495136428U,  213707396U,   15104824U, 2946180358U,\n\t 659000016U,  566379385U, 2614030979U, 2855760170U,  334526548U,\n\t2315569495U, 2729518615U,  564745877U, 1263517638U, 3157185798U,\n\t1604852056U, 1011639885U, 2950579535U, 2524219188U,  312951012U,\n\t1528896652U, 1327861054U, 2846910138U, 3966855905U, 2536721582U,\n\t 855353911U, 1685434729U, 3303978929U, 1624872055U, 4020329649U,\n\t3164802143U, 1642802700U, 1957727869U, 1792352426U, 3334618929U,\n\t2631577923U, 3027156164U,  842334259U, 3353446843U, 1226432104U,\n\t1742801369U, 3552852535U, 3471698828U, 1653910186U, 3380330939U,\n\t2313782701U, 3351007196U, 2129839995U, 1800682418U, 4085884420U,\n\t1625156629U, 3669701987U,  615211810U, 3294791649U, 4131143784U,\n\t2590843588U, 3207422808U, 3275066464U,  561592872U, 3957205738U,\n\t3396578098U,   48410678U, 3505556445U, 1005764855U, 3920606528U,\n\t2936980473U, 2378918600U, 2404449845U, 1649515163U,  701203563U,\n\t3705256349U,   83714199U, 3586854132U,  922978446U, 2863406304U,\n\t3523398907U, 2606864832U, 2385399361U, 3171757816U, 4262841009U,\n\t3645837721U, 1169579486U, 3666433897U, 3174689479U, 1457866976U,\n\t3803895110U, 3346639145U, 1907224409U, 1978473712U, 1036712794U,\n\t 980754888U, 1302782359U, 1765252468U,  459245755U, 3728923860U,\n\t1512894209U, 2046491914U,  207860527U,  514188684U, 2288713615U,\n\t1597354672U, 3349636117U, 2357291114U, 3995796221U,  945364213U,\n\t1893326518U, 3770814016U, 1691552714U, 2397527410U,  967486361U,\n\t 776416472U, 4197661421U,  951150819U, 1852770983U, 4044624181U,\n\t1399439738U, 4194455275U, 2284037669U, 1550734958U, 3321078108U,\n\t1865235926U, 2912129961U, 2664980877U, 1357572033U, 2600196436U,\n\t2486728200U, 2372668724U, 1567316966U, 2374111491U, 1839843570U,\n\t  20815612U, 3727008608U, 3871996229U,  824061249U, 1932503978U,\n\t3404541726U,  758428924U, 2609331364U, 1223966026U, 1299179808U,\n\t 648499352U, 2180134401U,  880821170U, 3781130950U,  113491270U,\n\t1032413764U, 4185884695U, 2490396037U, 1201932817U, 4060951446U,\n\t4165586898U, 1629813212U, 2887821158U,  415045333U,  628926856U,\n\t2193466079U, 3391843445U, 2227540681U, 1907099846U, 2848448395U,\n\t1717828221U, 1372704537U, 1707549841U, 2294058813U, 2101214437U,\n\t2052479531U, 1695809164U, 3176587306U, 2632770465U,   81634404U,\n\t1603220563U,  644238487U,  302857763U,  897352968U, 2613146653U,\n\t1391730149U, 4245717312U, 4191828749U, 1948492526U, 2618174230U,\n\t3992984522U, 2178852787U, 3596044509U, 3445573503U, 2026614616U,\n\t 915763564U, 3415689334U, 2532153403U, 3879661562U, 2215027417U,\n\t3111154986U, 2929478371U,  668346391U, 1152241381U, 2632029711U,\n\t3004150659U, 2135025926U,  948690501U, 2799119116U, 4228829406U,\n\t1981197489U, 4209064138U,  684318751U, 3459397845U,  201790843U,\n\t4022541136U, 3043635877U,  492509624U, 3263466772U, 1509148086U,\n\t 921459029U, 3198857146U,  705479721U, 3835966910U, 3603356465U,\n\t 576159741U, 1742849431U,  594214882U, 2055294343U, 3634861861U,\n\t 449571793U, 3246390646U, 3868232151U, 1479156585U, 2900125656U,\n\t2464815318U, 3960178104U, 1784261920U,   18311476U, 3627135050U,\n\t 644609697U,  424968996U,  919890700U, 2986824110U,  816423214U,\n\t4003562844U, 1392714305U, 1757384428U, 2569030598U,  995949559U,\n\t3875659880U, 2933807823U, 2752536860U, 2993858466U, 4030558899U,\n\t2770783427U, 2775406005U, 2777781742U, 1931292655U,  472147933U,\n\t3865853827U, 2726470545U, 2668412860U, 2887008249U,  408979190U,\n\t3578063323U, 3242082049U, 1778193530U,   27981909U, 2362826515U,\n\t 389875677U, 1043878156U,  581653903U, 3830568952U,  389535942U,\n\t3713523185U, 2768373359U, 2526101582U, 1998618197U, 1160859704U,\n\t3951172488U, 1098005003U,  906275699U, 3446228002U, 2220677963U,\n\t2059306445U,  132199571U,  476838790U, 1868039399U, 3097344807U,\n\t 857300945U,  396345050U, 2835919916U, 1782168828U, 1419519470U,\n\t4288137521U,  819087232U,  596301494U,  872823172U, 1526888217U,\n\t 805161465U, 1116186205U, 2829002754U, 2352620120U,  620121516U,\n\t 354159268U, 3601949785U,  209568138U, 1352371732U, 2145977349U,\n\t4236871834U, 1539414078U, 3558126206U, 3224857093U, 4164166682U,\n\t3817553440U, 3301780278U, 2682696837U, 3734994768U, 1370950260U,\n\t1477421202U, 2521315749U, 1330148125U, 1261554731U, 2769143688U,\n\t3554756293U, 4235882678U, 3254686059U, 3530579953U, 1215452615U,\n\t3574970923U, 4057131421U,  589224178U, 1000098193U,  171190718U,\n\t2521852045U, 2351447494U, 2284441580U, 2646685513U, 3486933563U,\n\t3789864960U, 1190528160U, 1702536782U, 1534105589U, 4262946827U,\n\t2726686826U, 3584544841U, 2348270128U, 2145092281U, 2502718509U,\n\t1027832411U, 3571171153U, 1287361161U, 4011474411U, 3241215351U,\n\t2419700818U,  971242709U, 1361975763U, 1096842482U, 3271045537U,\n\t  81165449U,  612438025U, 3912966678U, 1356929810U,  733545735U,\n\t 537003843U, 1282953084U,  884458241U,  588930090U, 3930269801U,\n\t2961472450U, 1219535534U, 3632251943U,  268183903U, 1441240533U,\n\t3653903360U, 3854473319U, 2259087390U, 2548293048U, 2022641195U,\n\t2105543911U, 1764085217U, 3246183186U,  482438805U,  888317895U,\n\t2628314765U, 2466219854U,  717546004U, 2322237039U,  416725234U,\n\t1544049923U, 1797944973U, 3398652364U, 3111909456U,  485742908U,\n\t2277491072U, 1056355088U, 3181001278U,  129695079U, 2693624550U,\n\t1764438564U, 3797785470U,  195503713U, 3266519725U, 2053389444U,\n\t1961527818U, 3400226523U, 3777903038U, 2597274307U, 4235851091U,\n\t4094406648U, 2171410785U, 1781151386U, 1378577117U,  654643266U,\n\t3424024173U, 3385813322U,  679385799U,  479380913U,  681715441U,\n\t3096225905U,  276813409U, 3854398070U, 2721105350U,  831263315U,\n\t3276280337U, 2628301522U, 3984868494U, 1466099834U, 2104922114U,\n\t1412672743U,  820330404U, 3491501010U,  942735832U,  710652807U,\n\t3972652090U,  679881088U,   40577009U, 3705286397U, 2815423480U,\n\t3566262429U,  663396513U, 3777887429U, 4016670678U,  404539370U,\n\t1142712925U, 1140173408U, 2913248352U, 2872321286U,  263751841U,\n\t3175196073U, 3162557581U, 2878996619U,   75498548U, 3836833140U,\n\t3284664959U, 1157523805U,  112847376U,  207855609U, 1337979698U,\n\t1222578451U,  157107174U,  901174378U, 3883717063U, 1618632639U,\n\t1767889440U, 4264698824U, 1582999313U,  884471997U, 2508825098U,\n\t3756370771U, 2457213553U, 3565776881U, 3709583214U,  915609601U,\n\t 460833524U, 1091049576U,   85522880U,    2553251U,  132102809U,\n\t2429882442U, 2562084610U, 1386507633U, 4112471229U,   21965213U,\n\t1981516006U, 2418435617U, 3054872091U, 4251511224U, 2025783543U,\n\t1916911512U, 2454491136U, 3938440891U, 3825869115U, 1121698605U,\n\t3463052265U,  802340101U, 1912886800U, 4031997367U, 3550640406U,\n\t1596096923U,  610150600U,  431464457U, 2541325046U,  486478003U,\n\t 739704936U, 2862696430U, 3037903166U, 1129749694U, 2611481261U,\n\t1228993498U,  510075548U, 3424962587U, 2458689681U,  818934833U,\n\t4233309125U, 1608196251U, 3419476016U, 1858543939U, 2682166524U,\n\t3317854285U,  631986188U, 3008214764U,  613826412U, 3567358221U,\n\t3512343882U, 1552467474U, 3316162670U, 1275841024U, 4142173454U,\n\t 565267881U,  768644821U,  198310105U, 2396688616U, 1837659011U,\n\t 203429334U,  854539004U, 4235811518U, 3338304926U, 3730418692U,\n\t3852254981U, 3032046452U, 2329811860U, 2303590566U, 2696092212U,\n\t3894665932U,  145835667U,  249563655U, 1932210840U, 2431696407U,\n\t3312636759U,  214962629U, 2092026914U, 3020145527U, 4073039873U,\n\t2739105705U, 1308336752U,  855104522U, 2391715321U,   67448785U,\n\t 547989482U,  854411802U, 3608633740U,  431731530U,  537375589U,\n\t3888005760U,  696099141U,  397343236U, 1864511780U,   44029739U,\n\t1729526891U, 1993398655U, 2010173426U, 2591546756U,  275223291U,\n\t1503900299U, 4217765081U, 2185635252U, 1122436015U, 3550155364U,\n\t 681707194U, 3260479338U,  933579397U, 2983029282U, 2505504587U,\n\t2667410393U, 2962684490U, 4139721708U, 2658172284U, 2452602383U,\n\t2607631612U, 1344296217U, 3075398709U, 2949785295U, 1049956168U,\n\t3917185129U, 2155660174U, 3280524475U, 1503827867U,  674380765U,\n\t1918468193U, 3843983676U,  634358221U, 2538335643U, 1873351298U,\n\t3368723763U, 2129144130U, 3203528633U, 3087174986U, 2691698871U,\n\t2516284287U,   24437745U, 1118381474U, 2816314867U, 2448576035U,\n\t4281989654U,  217287825U,  165872888U, 2628995722U, 3533525116U,\n\t2721669106U,  872340568U, 3429930655U, 3309047304U, 3916704967U,\n\t3270160355U, 1348884255U, 1634797670U,  881214967U, 4259633554U,\n\t 174613027U, 1103974314U, 1625224232U, 2678368291U, 1133866707U,\n\t3853082619U, 4073196549U, 1189620777U,  637238656U,  930241537U,\n\t4042750792U, 3842136042U, 2417007212U, 2524907510U, 1243036827U,\n\t1282059441U, 3764588774U, 1394459615U, 2323620015U, 1166152231U,\n\t3307479609U, 3849322257U, 3507445699U, 4247696636U,  758393720U,\n\t 967665141U, 1095244571U, 1319812152U,  407678762U, 2640605208U,\n\t2170766134U, 3663594275U, 4039329364U, 2512175520U,  725523154U,\n\t2249807004U, 3312617979U, 2414634172U, 1278482215U,  349206484U,\n\t1573063308U, 1196429124U, 3873264116U, 2400067801U,  268795167U,\n\t 226175489U, 2961367263U, 1968719665U,   42656370U, 1010790699U,\n\t 561600615U, 2422453992U, 3082197735U, 1636700484U, 3977715296U,\n\t3125350482U, 3478021514U, 2227819446U, 1540868045U, 3061908980U,\n\t1087362407U, 3625200291U,  361937537U,  580441897U, 1520043666U,\n\t2270875402U, 1009161260U, 2502355842U, 4278769785U,  473902412U,\n\t1057239083U, 1905829039U, 1483781177U, 2080011417U, 1207494246U,\n\t1806991954U, 2194674403U, 3455972205U,  807207678U, 3655655687U,\n\t 674112918U,  195425752U, 3917890095U, 1874364234U, 1837892715U,\n\t3663478166U, 1548892014U, 2570748714U, 2049929836U, 2167029704U,\n\t 697543767U, 3499545023U, 3342496315U, 1725251190U, 3561387469U,\n\t2905606616U, 1580182447U, 3934525927U, 4103172792U, 1365672522U,\n\t1534795737U, 3308667416U, 2841911405U, 3943182730U, 4072020313U,\n\t3494770452U, 3332626671U,   55327267U,  478030603U,  411080625U,\n\t3419529010U, 1604767823U, 3513468014U,  570668510U,  913790824U,\n\t2283967995U,  695159462U, 3825542932U, 4150698144U, 1829758699U,\n\t 202895590U, 1609122645U, 1267651008U, 2910315509U, 2511475445U,\n\t2477423819U, 3932081579U,  900879979U, 2145588390U, 2670007504U,\n\t 580819444U, 1864996828U, 2526325979U, 1019124258U,  815508628U,\n\t2765933989U, 1277301341U, 3006021786U,  855540956U,  288025710U,\n\t1919594237U, 2331223864U,  177452412U, 2475870369U, 2689291749U,\n\t 865194284U,  253432152U, 2628531804U, 2861208555U, 2361597573U,\n\t1653952120U, 1039661024U, 2159959078U, 3709040440U, 3564718533U,\n\t2596878672U, 2041442161U,   31164696U, 2662962485U, 3665637339U,\n\t1678115244U, 2699839832U, 3651968520U, 3521595541U,  458433303U,\n\t2423096824U,   21831741U,  380011703U, 2498168716U,  861806087U,\n\t1673574843U, 4188794405U, 2520563651U, 2632279153U, 2170465525U,\n\t4171949898U, 3886039621U, 1661344005U, 3424285243U,  992588372U,\n\t2500984144U, 2993248497U, 3590193895U, 1535327365U,  515645636U,\n\t 131633450U, 3729760261U, 1613045101U, 3254194278U,   15889678U,\n\t1493590689U,  244148718U, 2991472662U, 1401629333U,  777349878U,\n\t2501401703U, 4285518317U, 3794656178U,  955526526U, 3442142820U,\n\t3970298374U,  736025417U, 2737370764U, 1271509744U,  440570731U,\n\t 136141826U, 1596189518U,  923399175U,  257541519U, 3505774281U,\n\t2194358432U, 2518162991U, 1379893637U, 2667767062U, 3748146247U,\n\t1821712620U, 3923161384U, 1947811444U, 2392527197U, 4127419685U,\n\t1423694998U, 4156576871U, 1382885582U, 3420127279U, 3617499534U,\n\t2994377493U, 4038063986U, 1918458672U, 2983166794U, 4200449033U,\n\t 353294540U, 1609232588U,  243926648U, 2332803291U,  507996832U,\n\t2392838793U, 4075145196U, 2060984340U, 4287475136U,   88232602U,\n\t2491531140U, 4159725633U, 2272075455U,  759298618U,  201384554U,\n\t 838356250U, 1416268324U,  674476934U,   90795364U,  141672229U,\n\t3660399588U, 4196417251U, 3249270244U, 3774530247U,   59587265U,\n\t3683164208U,   19392575U, 1463123697U, 1882205379U,  293780489U,\n\t2553160622U, 2933904694U,  675638239U, 2851336944U, 1435238743U,\n\t2448730183U,  804436302U, 2119845972U,  322560608U, 4097732704U,\n\t2987802540U,  641492617U, 2575442710U, 4217822703U, 3271835300U,\n\t2836418300U, 3739921620U, 2138378768U, 2879771855U, 4294903423U,\n\t3121097946U, 2603440486U, 2560820391U, 1012930944U, 2313499967U,\n\t 584489368U, 3431165766U,  897384869U, 2062537737U, 2847889234U,\n\t3742362450U, 2951174585U, 4204621084U, 1109373893U, 3668075775U,\n\t2750138839U, 3518055702U,  733072558U, 4169325400U,  788493625U\n};\nstatic const uint64_t init_gen_rand_64_expected[] = {\n\tKQU(16924766246869039260), KQU( 8201438687333352714),\n\tKQU( 2265290287015001750), KQU(18397264611805473832),\n\tKQU( 3375255223302384358), KQU( 6345559975416828796),\n\tKQU(18229739242790328073), KQU( 7596792742098800905),\n\tKQU(  255338647169685981), KQU( 2052747240048610300),\n\tKQU(18328151576097299343), KQU(12472905421133796567),\n\tKQU(11315245349717600863), KQU(16594110197775871209),\n\tKQU(15708751964632456450), KQU(10452031272054632535),\n\tKQU(11097646720811454386), KQU( 4556090668445745441),\n\tKQU(17116187693090663106), KQU(14931526836144510645),\n\tKQU( 9190752218020552591), KQU( 9625800285771901401),\n\tKQU(13995141077659972832), KQU( 5194209094927829625),\n\tKQU( 4156788379151063303), KQU( 8523452593770139494),\n\tKQU(14082382103049296727), KQU( 2462601863986088483),\n\tKQU( 3030583461592840678), KQU( 5221622077872827681),\n\tKQU( 3084210671228981236), KQU(13956758381389953823),\n\tKQU(13503889856213423831), KQU(15696904024189836170),\n\tKQU( 4612584152877036206), KQU( 6231135538447867881),\n\tKQU(10172457294158869468), KQU( 6452258628466708150),\n\tKQU(14044432824917330221), KQU(  370168364480044279),\n\tKQU(10102144686427193359), KQU(  667870489994776076),\n\tKQU( 2732271956925885858), KQU(18027788905977284151),\n\tKQU(15009842788582923859), KQU( 7136357960180199542),\n\tKQU(15901736243475578127), KQU(16951293785352615701),\n\tKQU(10551492125243691632), KQU(17668869969146434804),\n\tKQU(13646002971174390445), KQU( 9804471050759613248),\n\tKQU( 5511670439655935493), KQU(18103342091070400926),\n\tKQU(17224512747665137533), KQU(15534627482992618168),\n\tKQU( 1423813266186582647), KQU(15821176807932930024),\n\tKQU(   30323369733607156), KQU(11599382494723479403),\n\tKQU(  653856076586810062), KQU( 3176437395144899659),\n\tKQU(14028076268147963917), KQU(16156398271809666195),\n\tKQU( 3166955484848201676), KQU( 5746805620136919390),\n\tKQU(17297845208891256593), KQU(11691653183226428483),\n\tKQU(17900026146506981577), KQU(15387382115755971042),\n\tKQU(16923567681040845943), KQU( 8039057517199388606),\n\tKQU(11748409241468629263), KQU(  794358245539076095),\n\tKQU(13438501964693401242), KQU(14036803236515618962),\n\tKQU( 5252311215205424721), KQU(17806589612915509081),\n\tKQU( 6802767092397596006), KQU(14212120431184557140),\n\tKQU( 1072951366761385712), KQU(13098491780722836296),\n\tKQU( 9466676828710797353), KQU(12673056849042830081),\n\tKQU(12763726623645357580), KQU(16468961652999309493),\n\tKQU(15305979875636438926), KQU(17444713151223449734),\n\tKQU( 5692214267627883674), KQU(13049589139196151505),\n\tKQU(  880115207831670745), KQU( 1776529075789695498),\n\tKQU(16695225897801466485), KQU(10666901778795346845),\n\tKQU( 6164389346722833869), KQU( 2863817793264300475),\n\tKQU( 9464049921886304754), KQU( 3993566636740015468),\n\tKQU( 9983749692528514136), KQU(16375286075057755211),\n\tKQU(16042643417005440820), KQU(11445419662923489877),\n\tKQU( 7999038846885158836), KQU( 6721913661721511535),\n\tKQU( 5363052654139357320), KQU( 1817788761173584205),\n\tKQU(13290974386445856444), KQU( 4650350818937984680),\n\tKQU( 8219183528102484836), KQU( 1569862923500819899),\n\tKQU( 4189359732136641860), KQU(14202822961683148583),\n\tKQU( 4457498315309429058), KQU(13089067387019074834),\n\tKQU(11075517153328927293), KQU(10277016248336668389),\n\tKQU( 7070509725324401122), KQU(17808892017780289380),\n\tKQU(13143367339909287349), KQU( 1377743745360085151),\n\tKQU( 5749341807421286485), KQU(14832814616770931325),\n\tKQU( 7688820635324359492), KQU(10960474011539770045),\n\tKQU(   81970066653179790), KQU(12619476072607878022),\n\tKQU( 4419566616271201744), KQU(15147917311750568503),\n\tKQU( 5549739182852706345), KQU( 7308198397975204770),\n\tKQU(13580425496671289278), KQU(17070764785210130301),\n\tKQU( 8202832846285604405), KQU( 6873046287640887249),\n\tKQU( 6927424434308206114), KQU( 6139014645937224874),\n\tKQU(10290373645978487639), KQU(15904261291701523804),\n\tKQU( 9628743442057826883), KQU(18383429096255546714),\n\tKQU( 4977413265753686967), KQU( 7714317492425012869),\n\tKQU( 9025232586309926193), KQU(14627338359776709107),\n\tKQU(14759849896467790763), KQU(10931129435864423252),\n\tKQU( 4588456988775014359), KQU(10699388531797056724),\n\tKQU(  468652268869238792), KQU( 5755943035328078086),\n\tKQU( 2102437379988580216), KQU( 9986312786506674028),\n\tKQU( 2654207180040945604), KQU( 8726634790559960062),\n\tKQU(  100497234871808137), KQU( 2800137176951425819),\n\tKQU( 6076627612918553487), KQU( 5780186919186152796),\n\tKQU( 8179183595769929098), KQU( 6009426283716221169),\n\tKQU( 2796662551397449358), KQU( 1756961367041986764),\n\tKQU( 6972897917355606205), KQU(14524774345368968243),\n\tKQU( 2773529684745706940), KQU( 4853632376213075959),\n\tKQU( 4198177923731358102), KQU( 8271224913084139776),\n\tKQU( 2741753121611092226), KQU(16782366145996731181),\n\tKQU(15426125238972640790), KQU(13595497100671260342),\n\tKQU( 3173531022836259898), KQU( 6573264560319511662),\n\tKQU(18041111951511157441), KQU( 2351433581833135952),\n\tKQU( 3113255578908173487), KQU( 1739371330877858784),\n\tKQU(16046126562789165480), KQU( 8072101652214192925),\n\tKQU(15267091584090664910), KQU( 9309579200403648940),\n\tKQU( 5218892439752408722), KQU(14492477246004337115),\n\tKQU(17431037586679770619), KQU( 7385248135963250480),\n\tKQU( 9580144956565560660), KQU( 4919546228040008720),\n\tKQU(15261542469145035584), KQU(18233297270822253102),\n\tKQU( 5453248417992302857), KQU( 9309519155931460285),\n\tKQU(10342813012345291756), KQU(15676085186784762381),\n\tKQU(15912092950691300645), KQU( 9371053121499003195),\n\tKQU( 9897186478226866746), KQU(14061858287188196327),\n\tKQU(  122575971620788119), KQU(12146750969116317754),\n\tKQU( 4438317272813245201), KQU( 8332576791009527119),\n\tKQU(13907785691786542057), KQU(10374194887283287467),\n\tKQU( 2098798755649059566), KQU( 3416235197748288894),\n\tKQU( 8688269957320773484), KQU( 7503964602397371571),\n\tKQU(16724977015147478236), KQU( 9461512855439858184),\n\tKQU(13259049744534534727), KQU( 3583094952542899294),\n\tKQU( 8764245731305528292), KQU(13240823595462088985),\n\tKQU(13716141617617910448), KQU(18114969519935960955),\n\tKQU( 2297553615798302206), KQU( 4585521442944663362),\n\tKQU(17776858680630198686), KQU( 4685873229192163363),\n\tKQU(  152558080671135627), KQU(15424900540842670088),\n\tKQU(13229630297130024108), KQU(17530268788245718717),\n\tKQU(16675633913065714144), KQU( 3158912717897568068),\n\tKQU(15399132185380087288), KQU( 7401418744515677872),\n\tKQU(13135412922344398535), KQU( 6385314346100509511),\n\tKQU(13962867001134161139), KQU(10272780155442671999),\n\tKQU(12894856086597769142), KQU(13340877795287554994),\n\tKQU(12913630602094607396), KQU(12543167911119793857),\n\tKQU(17343570372251873096), KQU(10959487764494150545),\n\tKQU( 6966737953093821128), KQU(13780699135496988601),\n\tKQU( 4405070719380142046), KQU(14923788365607284982),\n\tKQU( 2869487678905148380), KQU( 6416272754197188403),\n\tKQU(15017380475943612591), KQU( 1995636220918429487),\n\tKQU( 3402016804620122716), KQU(15800188663407057080),\n\tKQU(11362369990390932882), KQU(15262183501637986147),\n\tKQU(10239175385387371494), KQU( 9352042420365748334),\n\tKQU( 1682457034285119875), KQU( 1724710651376289644),\n\tKQU( 2038157098893817966), KQU( 9897825558324608773),\n\tKQU( 1477666236519164736), KQU(16835397314511233640),\n\tKQU(10370866327005346508), KQU(10157504370660621982),\n\tKQU(12113904045335882069), KQU(13326444439742783008),\n\tKQU(11302769043000765804), KQU(13594979923955228484),\n\tKQU(11779351762613475968), KQU( 3786101619539298383),\n\tKQU( 8021122969180846063), KQU(15745904401162500495),\n\tKQU(10762168465993897267), KQU(13552058957896319026),\n\tKQU(11200228655252462013), KQU( 5035370357337441226),\n\tKQU( 7593918984545500013), KQU( 5418554918361528700),\n\tKQU( 4858270799405446371), KQU( 9974659566876282544),\n\tKQU(18227595922273957859), KQU( 2772778443635656220),\n\tKQU(14285143053182085385), KQU( 9939700992429600469),\n\tKQU(12756185904545598068), KQU( 2020783375367345262),\n\tKQU(   57026775058331227), KQU(  950827867930065454),\n\tKQU( 6602279670145371217), KQU( 2291171535443566929),\n\tKQU( 5832380724425010313), KQU( 1220343904715982285),\n\tKQU(17045542598598037633), KQU(15460481779702820971),\n\tKQU(13948388779949365130), KQU(13975040175430829518),\n\tKQU(17477538238425541763), KQU(11104663041851745725),\n\tKQU(15860992957141157587), KQU(14529434633012950138),\n\tKQU( 2504838019075394203), KQU( 7512113882611121886),\n\tKQU( 4859973559980886617), KQU( 1258601555703250219),\n\tKQU(15594548157514316394), KQU( 4516730171963773048),\n\tKQU(11380103193905031983), KQU( 6809282239982353344),\n\tKQU(18045256930420065002), KQU( 2453702683108791859),\n\tKQU(  977214582986981460), KQU( 2006410402232713466),\n\tKQU( 6192236267216378358), KQU( 3429468402195675253),\n\tKQU(18146933153017348921), KQU(17369978576367231139),\n\tKQU( 1246940717230386603), KQU(11335758870083327110),\n\tKQU(14166488801730353682), KQU( 9008573127269635732),\n\tKQU(10776025389820643815), KQU(15087605441903942962),\n\tKQU( 1359542462712147922), KQU(13898874411226454206),\n\tKQU(17911176066536804411), KQU( 9435590428600085274),\n\tKQU(  294488509967864007), KQU( 8890111397567922046),\n\tKQU( 7987823476034328778), KQU(13263827582440967651),\n\tKQU( 7503774813106751573), KQU(14974747296185646837),\n\tKQU( 8504765037032103375), KQU(17340303357444536213),\n\tKQU( 7704610912964485743), KQU( 8107533670327205061),\n\tKQU( 9062969835083315985), KQU(16968963142126734184),\n\tKQU(12958041214190810180), KQU( 2720170147759570200),\n\tKQU( 2986358963942189566), KQU(14884226322219356580),\n\tKQU(  286224325144368520), KQU(11313800433154279797),\n\tKQU(18366849528439673248), KQU(17899725929482368789),\n\tKQU( 3730004284609106799), KQU( 1654474302052767205),\n\tKQU( 5006698007047077032), KQU( 8196893913601182838),\n\tKQU(15214541774425211640), KQU(17391346045606626073),\n\tKQU( 8369003584076969089), KQU( 3939046733368550293),\n\tKQU(10178639720308707785), KQU( 2180248669304388697),\n\tKQU(   62894391300126322), KQU( 9205708961736223191),\n\tKQU( 6837431058165360438), KQU( 3150743890848308214),\n\tKQU(17849330658111464583), KQU(12214815643135450865),\n\tKQU(13410713840519603402), KQU( 3200778126692046802),\n\tKQU(13354780043041779313), KQU(  800850022756886036),\n\tKQU(15660052933953067433), KQU( 6572823544154375676),\n\tKQU(11030281857015819266), KQU(12682241941471433835),\n\tKQU(11654136407300274693), KQU( 4517795492388641109),\n\tKQU( 9757017371504524244), KQU(17833043400781889277),\n\tKQU(12685085201747792227), KQU(10408057728835019573),\n\tKQU(   98370418513455221), KQU( 6732663555696848598),\n\tKQU(13248530959948529780), KQU( 3530441401230622826),\n\tKQU(18188251992895660615), KQU( 1847918354186383756),\n\tKQU( 1127392190402660921), KQU(11293734643143819463),\n\tKQU( 3015506344578682982), KQU(13852645444071153329),\n\tKQU( 2121359659091349142), KQU( 1294604376116677694),\n\tKQU( 5616576231286352318), KQU( 7112502442954235625),\n\tKQU(11676228199551561689), KQU(12925182803007305359),\n\tKQU( 7852375518160493082), KQU( 1136513130539296154),\n\tKQU( 5636923900916593195), KQU( 3221077517612607747),\n\tKQU(17784790465798152513), KQU( 3554210049056995938),\n\tKQU(17476839685878225874), KQU( 3206836372585575732),\n\tKQU( 2765333945644823430), KQU(10080070903718799528),\n\tKQU( 5412370818878286353), KQU( 9689685887726257728),\n\tKQU( 8236117509123533998), KQU( 1951139137165040214),\n\tKQU( 4492205209227980349), KQU(16541291230861602967),\n\tKQU( 1424371548301437940), KQU( 9117562079669206794),\n\tKQU(14374681563251691625), KQU(13873164030199921303),\n\tKQU( 6680317946770936731), KQU(15586334026918276214),\n\tKQU(10896213950976109802), KQU( 9506261949596413689),\n\tKQU( 9903949574308040616), KQU( 6038397344557204470),\n\tKQU(  174601465422373648), KQU(15946141191338238030),\n\tKQU(17142225620992044937), KQU( 7552030283784477064),\n\tKQU( 2947372384532947997), KQU(  510797021688197711),\n\tKQU( 4962499439249363461), KQU(   23770320158385357),\n\tKQU(  959774499105138124), KQU( 1468396011518788276),\n\tKQU( 2015698006852312308), KQU( 4149400718489980136),\n\tKQU( 5992916099522371188), KQU(10819182935265531076),\n\tKQU(16189787999192351131), KQU(  342833961790261950),\n\tKQU(12470830319550495336), KQU(18128495041912812501),\n\tKQU( 1193600899723524337), KQU( 9056793666590079770),\n\tKQU( 2154021227041669041), KQU( 4963570213951235735),\n\tKQU( 4865075960209211409), KQU( 2097724599039942963),\n\tKQU( 2024080278583179845), KQU(11527054549196576736),\n\tKQU(10650256084182390252), KQU( 4808408648695766755),\n\tKQU( 1642839215013788844), KQU(10607187948250398390),\n\tKQU( 7076868166085913508), KQU(  730522571106887032),\n\tKQU(12500579240208524895), KQU( 4484390097311355324),\n\tKQU(15145801330700623870), KQU( 8055827661392944028),\n\tKQU( 5865092976832712268), KQU(15159212508053625143),\n\tKQU( 3560964582876483341), KQU( 4070052741344438280),\n\tKQU( 6032585709886855634), KQU(15643262320904604873),\n\tKQU( 2565119772293371111), KQU(  318314293065348260),\n\tKQU(15047458749141511872), KQU( 7772788389811528730),\n\tKQU( 7081187494343801976), KQU( 6465136009467253947),\n\tKQU(10425940692543362069), KQU(  554608190318339115),\n\tKQU(14796699860302125214), KQU( 1638153134431111443),\n\tKQU(10336967447052276248), KQU( 8412308070396592958),\n\tKQU( 4004557277152051226), KQU( 8143598997278774834),\n\tKQU(16413323996508783221), KQU(13139418758033994949),\n\tKQU( 9772709138335006667), KQU( 2818167159287157659),\n\tKQU(17091740573832523669), KQU(14629199013130751608),\n\tKQU(18268322711500338185), KQU( 8290963415675493063),\n\tKQU( 8830864907452542588), KQU( 1614839084637494849),\n\tKQU(14855358500870422231), KQU( 3472996748392519937),\n\tKQU(15317151166268877716), KQU( 5825895018698400362),\n\tKQU(16730208429367544129), KQU(10481156578141202800),\n\tKQU( 4746166512382823750), KQU(12720876014472464998),\n\tKQU( 8825177124486735972), KQU(13733447296837467838),\n\tKQU( 6412293741681359625), KQU( 8313213138756135033),\n\tKQU(11421481194803712517), KQU( 7997007691544174032),\n\tKQU( 6812963847917605930), KQU( 9683091901227558641),\n\tKQU(14703594165860324713), KQU( 1775476144519618309),\n\tKQU( 2724283288516469519), KQU(  717642555185856868),\n\tKQU( 8736402192215092346), KQU(11878800336431381021),\n\tKQU( 4348816066017061293), KQU( 6115112756583631307),\n\tKQU( 9176597239667142976), KQU(12615622714894259204),\n\tKQU(10283406711301385987), KQU( 5111762509485379420),\n\tKQU( 3118290051198688449), KQU( 7345123071632232145),\n\tKQU( 9176423451688682359), KQU( 4843865456157868971),\n\tKQU(12008036363752566088), KQU(12058837181919397720),\n\tKQU( 2145073958457347366), KQU( 1526504881672818067),\n\tKQU( 3488830105567134848), KQU(13208362960674805143),\n\tKQU( 4077549672899572192), KQU( 7770995684693818365),\n\tKQU( 1398532341546313593), KQU(12711859908703927840),\n\tKQU( 1417561172594446813), KQU(17045191024194170604),\n\tKQU( 4101933177604931713), KQU(14708428834203480320),\n\tKQU(17447509264469407724), KQU(14314821973983434255),\n\tKQU(17990472271061617265), KQU( 5087756685841673942),\n\tKQU(12797820586893859939), KQU( 1778128952671092879),\n\tKQU( 3535918530508665898), KQU( 9035729701042481301),\n\tKQU(14808661568277079962), KQU(14587345077537747914),\n\tKQU(11920080002323122708), KQU( 6426515805197278753),\n\tKQU( 3295612216725984831), KQU(11040722532100876120),\n\tKQU(12305952936387598754), KQU(16097391899742004253),\n\tKQU( 4908537335606182208), KQU(12446674552196795504),\n\tKQU(16010497855816895177), KQU( 9194378874788615551),\n\tKQU( 3382957529567613384), KQU( 5154647600754974077),\n\tKQU( 9801822865328396141), KQU( 9023662173919288143),\n\tKQU(17623115353825147868), KQU( 8238115767443015816),\n\tKQU(15811444159859002560), KQU( 9085612528904059661),\n\tKQU( 6888601089398614254), KQU(  258252992894160189),\n\tKQU( 6704363880792428622), KQU( 6114966032147235763),\n\tKQU(11075393882690261875), KQU( 8797664238933620407),\n\tKQU( 5901892006476726920), KQU( 5309780159285518958),\n\tKQU(14940808387240817367), KQU(14642032021449656698),\n\tKQU( 9808256672068504139), KQU( 3670135111380607658),\n\tKQU(11211211097845960152), KQU( 1474304506716695808),\n\tKQU(15843166204506876239), KQU( 7661051252471780561),\n\tKQU(10170905502249418476), KQU( 7801416045582028589),\n\tKQU( 2763981484737053050), KQU( 9491377905499253054),\n\tKQU(16201395896336915095), KQU( 9256513756442782198),\n\tKQU( 5411283157972456034), KQU( 5059433122288321676),\n\tKQU( 4327408006721123357), KQU( 9278544078834433377),\n\tKQU( 7601527110882281612), KQU(11848295896975505251),\n\tKQU(12096998801094735560), KQU(14773480339823506413),\n\tKQU(15586227433895802149), KQU(12786541257830242872),\n\tKQU( 6904692985140503067), KQU( 5309011515263103959),\n\tKQU(12105257191179371066), KQU(14654380212442225037),\n\tKQU( 2556774974190695009), KQU( 4461297399927600261),\n\tKQU(14888225660915118646), KQU(14915459341148291824),\n\tKQU( 2738802166252327631), KQU( 6047155789239131512),\n\tKQU(12920545353217010338), KQU(10697617257007840205),\n\tKQU( 2751585253158203504), KQU(13252729159780047496),\n\tKQU(14700326134672815469), KQU(14082527904374600529),\n\tKQU(16852962273496542070), KQU(17446675504235853907),\n\tKQU(15019600398527572311), KQU(12312781346344081551),\n\tKQU(14524667935039810450), KQU( 5634005663377195738),\n\tKQU(11375574739525000569), KQU( 2423665396433260040),\n\tKQU( 5222836914796015410), KQU( 4397666386492647387),\n\tKQU( 4619294441691707638), KQU(  665088602354770716),\n\tKQU(13246495665281593610), KQU( 6564144270549729409),\n\tKQU(10223216188145661688), KQU( 3961556907299230585),\n\tKQU(11543262515492439914), KQU(16118031437285993790),\n\tKQU( 7143417964520166465), KQU(13295053515909486772),\n\tKQU(   40434666004899675), KQU(17127804194038347164),\n\tKQU( 8599165966560586269), KQU( 8214016749011284903),\n\tKQU(13725130352140465239), KQU( 5467254474431726291),\n\tKQU( 7748584297438219877), KQU(16933551114829772472),\n\tKQU( 2169618439506799400), KQU( 2169787627665113463),\n\tKQU(17314493571267943764), KQU(18053575102911354912),\n\tKQU(11928303275378476973), KQU(11593850925061715550),\n\tKQU(17782269923473589362), KQU( 3280235307704747039),\n\tKQU( 6145343578598685149), KQU(17080117031114086090),\n\tKQU(18066839902983594755), KQU( 6517508430331020706),\n\tKQU( 8092908893950411541), KQU(12558378233386153732),\n\tKQU( 4476532167973132976), KQU(16081642430367025016),\n\tKQU( 4233154094369139361), KQU( 8693630486693161027),\n\tKQU(11244959343027742285), KQU(12273503967768513508),\n\tKQU(14108978636385284876), KQU( 7242414665378826984),\n\tKQU( 6561316938846562432), KQU( 8601038474994665795),\n\tKQU(17532942353612365904), KQU(17940076637020912186),\n\tKQU( 7340260368823171304), KQU( 7061807613916067905),\n\tKQU(10561734935039519326), KQU(17990796503724650862),\n\tKQU( 6208732943911827159), KQU(  359077562804090617),\n\tKQU(14177751537784403113), KQU(10659599444915362902),\n\tKQU(15081727220615085833), KQU(13417573895659757486),\n\tKQU(15513842342017811524), KQU(11814141516204288231),\n\tKQU( 1827312513875101814), KQU( 2804611699894603103),\n\tKQU(17116500469975602763), KQU(12270191815211952087),\n\tKQU(12256358467786024988), KQU(18435021722453971267),\n\tKQU(  671330264390865618), KQU(  476504300460286050),\n\tKQU(16465470901027093441), KQU( 4047724406247136402),\n\tKQU( 1322305451411883346), KQU( 1388308688834322280),\n\tKQU( 7303989085269758176), KQU( 9323792664765233642),\n\tKQU( 4542762575316368936), KQU(17342696132794337618),\n\tKQU( 4588025054768498379), KQU(13415475057390330804),\n\tKQU(17880279491733405570), KQU(10610553400618620353),\n\tKQU( 3180842072658960139), KQU(13002966655454270120),\n\tKQU( 1665301181064982826), KQU( 7083673946791258979),\n\tKQU(  190522247122496820), KQU(17388280237250677740),\n\tKQU( 8430770379923642945), KQU(12987180971921668584),\n\tKQU( 2311086108365390642), KQU( 2870984383579822345),\n\tKQU(14014682609164653318), KQU(14467187293062251484),\n\tKQU(  192186361147413298), KQU(15171951713531796524),\n\tKQU( 9900305495015948728), KQU(17958004775615466344),\n\tKQU(14346380954498606514), KQU(18040047357617407096),\n\tKQU( 5035237584833424532), KQU(15089555460613972287),\n\tKQU( 4131411873749729831), KQU( 1329013581168250330),\n\tKQU(10095353333051193949), KQU(10749518561022462716),\n\tKQU( 9050611429810755847), KQU(15022028840236655649),\n\tKQU( 8775554279239748298), KQU(13105754025489230502),\n\tKQU(15471300118574167585), KQU(   89864764002355628),\n\tKQU( 8776416323420466637), KQU( 5280258630612040891),\n\tKQU( 2719174488591862912), KQU( 7599309137399661994),\n\tKQU(15012887256778039979), KQU(14062981725630928925),\n\tKQU(12038536286991689603), KQU( 7089756544681775245),\n\tKQU(10376661532744718039), KQU( 1265198725901533130),\n\tKQU(13807996727081142408), KQU( 2935019626765036403),\n\tKQU( 7651672460680700141), KQU( 3644093016200370795),\n\tKQU( 2840982578090080674), KQU(17956262740157449201),\n\tKQU(18267979450492880548), KQU(11799503659796848070),\n\tKQU( 9942537025669672388), KQU(11886606816406990297),\n\tKQU( 5488594946437447576), KQU( 7226714353282744302),\n\tKQU( 3784851653123877043), KQU(  878018453244803041),\n\tKQU(12110022586268616085), KQU(  734072179404675123),\n\tKQU(11869573627998248542), KQU(  469150421297783998),\n\tKQU(  260151124912803804), KQU(11639179410120968649),\n\tKQU( 9318165193840846253), KQU(12795671722734758075),\n\tKQU(15318410297267253933), KQU(  691524703570062620),\n\tKQU( 5837129010576994601), KQU(15045963859726941052),\n\tKQU( 5850056944932238169), KQU(12017434144750943807),\n\tKQU( 7447139064928956574), KQU( 3101711812658245019),\n\tKQU(16052940704474982954), KQU(18195745945986994042),\n\tKQU( 8932252132785575659), KQU(13390817488106794834),\n\tKQU(11582771836502517453), KQU( 4964411326683611686),\n\tKQU( 2195093981702694011), KQU(14145229538389675669),\n\tKQU(16459605532062271798), KQU(  866316924816482864),\n\tKQU( 4593041209937286377), KQU( 8415491391910972138),\n\tKQU( 4171236715600528969), KQU(16637569303336782889),\n\tKQU( 2002011073439212680), KQU(17695124661097601411),\n\tKQU( 4627687053598611702), KQU( 7895831936020190403),\n\tKQU( 8455951300917267802), KQU( 2923861649108534854),\n\tKQU( 8344557563927786255), KQU( 6408671940373352556),\n\tKQU(12210227354536675772), KQU(14294804157294222295),\n\tKQU(10103022425071085127), KQU(10092959489504123771),\n\tKQU( 6554774405376736268), KQU(12629917718410641774),\n\tKQU( 6260933257596067126), KQU( 2460827021439369673),\n\tKQU( 2541962996717103668), KQU(  597377203127351475),\n\tKQU( 5316984203117315309), KQU( 4811211393563241961),\n\tKQU(13119698597255811641), KQU( 8048691512862388981),\n\tKQU(10216818971194073842), KQU( 4612229970165291764),\n\tKQU(10000980798419974770), KQU( 6877640812402540687),\n\tKQU( 1488727563290436992), KQU( 2227774069895697318),\n\tKQU(11237754507523316593), KQU(13478948605382290972),\n\tKQU( 1963583846976858124), KQU( 5512309205269276457),\n\tKQU( 3972770164717652347), KQU( 3841751276198975037),\n\tKQU(10283343042181903117), KQU( 8564001259792872199),\n\tKQU(16472187244722489221), KQU( 8953493499268945921),\n\tKQU( 3518747340357279580), KQU( 4003157546223963073),\n\tKQU( 3270305958289814590), KQU( 3966704458129482496),\n\tKQU( 8122141865926661939), KQU(14627734748099506653),\n\tKQU(13064426990862560568), KQU( 2414079187889870829),\n\tKQU( 5378461209354225306), KQU(10841985740128255566),\n\tKQU(  538582442885401738), KQU( 7535089183482905946),\n\tKQU(16117559957598879095), KQU( 8477890721414539741),\n\tKQU( 1459127491209533386), KQU(17035126360733620462),\n\tKQU( 8517668552872379126), KQU(10292151468337355014),\n\tKQU(17081267732745344157), KQU(13751455337946087178),\n\tKQU(14026945459523832966), KQU( 6653278775061723516),\n\tKQU(10619085543856390441), KQU( 2196343631481122885),\n\tKQU(10045966074702826136), KQU(10082317330452718282),\n\tKQU( 5920859259504831242), KQU( 9951879073426540617),\n\tKQU( 7074696649151414158), KQU(15808193543879464318),\n\tKQU( 7385247772746953374), KQU( 3192003544283864292),\n\tKQU(18153684490917593847), KQU(12423498260668568905),\n\tKQU(10957758099756378169), KQU(11488762179911016040),\n\tKQU( 2099931186465333782), KQU(11180979581250294432),\n\tKQU( 8098916250668367933), KQU( 3529200436790763465),\n\tKQU(12988418908674681745), KQU( 6147567275954808580),\n\tKQU( 3207503344604030989), KQU(10761592604898615360),\n\tKQU(  229854861031893504), KQU( 8809853962667144291),\n\tKQU(13957364469005693860), KQU( 7634287665224495886),\n\tKQU(12353487366976556874), KQU( 1134423796317152034),\n\tKQU( 2088992471334107068), KQU( 7393372127190799698),\n\tKQU( 1845367839871058391), KQU(  207922563987322884),\n\tKQU(11960870813159944976), KQU(12182120053317317363),\n\tKQU(17307358132571709283), KQU(13871081155552824936),\n\tKQU(18304446751741566262), KQU( 7178705220184302849),\n\tKQU(10929605677758824425), KQU(16446976977835806844),\n\tKQU(13723874412159769044), KQU( 6942854352100915216),\n\tKQU( 1726308474365729390), KQU( 2150078766445323155),\n\tKQU(15345558947919656626), KQU(12145453828874527201),\n\tKQU( 2054448620739726849), KQU( 2740102003352628137),\n\tKQU(11294462163577610655), KQU(  756164283387413743),\n\tKQU(17841144758438810880), KQU(10802406021185415861),\n\tKQU( 8716455530476737846), KQU( 6321788834517649606),\n\tKQU(14681322910577468426), KQU(17330043563884336387),\n\tKQU(12701802180050071614), KQU(14695105111079727151),\n\tKQU( 5112098511654172830), KQU( 4957505496794139973),\n\tKQU( 8270979451952045982), KQU(12307685939199120969),\n\tKQU(12425799408953443032), KQU( 8376410143634796588),\n\tKQU(16621778679680060464), KQU( 3580497854566660073),\n\tKQU( 1122515747803382416), KQU(  857664980960597599),\n\tKQU( 6343640119895925918), KQU(12878473260854462891),\n\tKQU(10036813920765722626), KQU(14451335468363173812),\n\tKQU( 5476809692401102807), KQU(16442255173514366342),\n\tKQU(13060203194757167104), KQU(14354124071243177715),\n\tKQU(15961249405696125227), KQU(13703893649690872584),\n\tKQU(  363907326340340064), KQU( 6247455540491754842),\n\tKQU(12242249332757832361), KQU(  156065475679796717),\n\tKQU( 9351116235749732355), KQU( 4590350628677701405),\n\tKQU( 1671195940982350389), KQU(13501398458898451905),\n\tKQU( 6526341991225002255), KQU( 1689782913778157592),\n\tKQU( 7439222350869010334), KQU(13975150263226478308),\n\tKQU(11411961169932682710), KQU(17204271834833847277),\n\tKQU(  541534742544435367), KQU( 6591191931218949684),\n\tKQU( 2645454775478232486), KQU( 4322857481256485321),\n\tKQU( 8477416487553065110), KQU(12902505428548435048),\n\tKQU(  971445777981341415), KQU(14995104682744976712),\n\tKQU( 4243341648807158063), KQU( 8695061252721927661),\n\tKQU( 5028202003270177222), KQU( 2289257340915567840),\n\tKQU(13870416345121866007), KQU(13994481698072092233),\n\tKQU( 6912785400753196481), KQU( 2278309315841980139),\n\tKQU( 4329765449648304839), KQU( 5963108095785485298),\n\tKQU( 4880024847478722478), KQU(16015608779890240947),\n\tKQU( 1866679034261393544), KQU(  914821179919731519),\n\tKQU( 9643404035648760131), KQU( 2418114953615593915),\n\tKQU(  944756836073702374), KQU(15186388048737296834),\n\tKQU( 7723355336128442206), KQU( 7500747479679599691),\n\tKQU(18013961306453293634), KQU( 2315274808095756456),\n\tKQU(13655308255424029566), KQU(17203800273561677098),\n\tKQU( 1382158694422087756), KQU( 5090390250309588976),\n\tKQU(  517170818384213989), KQU( 1612709252627729621),\n\tKQU( 1330118955572449606), KQU(  300922478056709885),\n\tKQU(18115693291289091987), KQU(13491407109725238321),\n\tKQU(15293714633593827320), KQU( 5151539373053314504),\n\tKQU( 5951523243743139207), KQU(14459112015249527975),\n\tKQU( 5456113959000700739), KQU( 3877918438464873016),\n\tKQU(12534071654260163555), KQU(15871678376893555041),\n\tKQU(11005484805712025549), KQU(16353066973143374252),\n\tKQU( 4358331472063256685), KQU( 8268349332210859288),\n\tKQU(12485161590939658075), KQU(13955993592854471343),\n\tKQU( 5911446886848367039), KQU(14925834086813706974),\n\tKQU( 6590362597857994805), KQU( 1280544923533661875),\n\tKQU( 1637756018947988164), KQU( 4734090064512686329),\n\tKQU(16693705263131485912), KQU( 6834882340494360958),\n\tKQU( 8120732176159658505), KQU( 2244371958905329346),\n\tKQU(10447499707729734021), KQU( 7318742361446942194),\n\tKQU( 8032857516355555296), KQU(14023605983059313116),\n\tKQU( 1032336061815461376), KQU( 9840995337876562612),\n\tKQU( 9869256223029203587), KQU(12227975697177267636),\n\tKQU(12728115115844186033), KQU( 7752058479783205470),\n\tKQU(  729733219713393087), KQU(12954017801239007622)\n};\nstatic const uint64_t init_by_array_64_expected[] = {\n\tKQU( 2100341266307895239), KQU( 8344256300489757943),\n\tKQU(15687933285484243894), KQU( 8268620370277076319),\n\tKQU(12371852309826545459), KQU( 8800491541730110238),\n\tKQU(18113268950100835773), KQU( 2886823658884438119),\n\tKQU( 3293667307248180724), KQU( 9307928143300172731),\n\tKQU( 7688082017574293629), KQU(  900986224735166665),\n\tKQU( 9977972710722265039), KQU( 6008205004994830552),\n\tKQU(  546909104521689292), KQU( 7428471521869107594),\n\tKQU(14777563419314721179), KQU(16116143076567350053),\n\tKQU( 5322685342003142329), KQU( 4200427048445863473),\n\tKQU( 4693092150132559146), KQU(13671425863759338582),\n\tKQU( 6747117460737639916), KQU( 4732666080236551150),\n\tKQU( 5912839950611941263), KQU( 3903717554504704909),\n\tKQU( 2615667650256786818), KQU(10844129913887006352),\n\tKQU(13786467861810997820), KQU(14267853002994021570),\n\tKQU(13767807302847237439), KQU(16407963253707224617),\n\tKQU( 4802498363698583497), KQU( 2523802839317209764),\n\tKQU( 3822579397797475589), KQU( 8950320572212130610),\n\tKQU( 3745623504978342534), KQU(16092609066068482806),\n\tKQU( 9817016950274642398), KQU(10591660660323829098),\n\tKQU(11751606650792815920), KQU( 5122873818577122211),\n\tKQU(17209553764913936624), KQU( 6249057709284380343),\n\tKQU(15088791264695071830), KQU(15344673071709851930),\n\tKQU( 4345751415293646084), KQU( 2542865750703067928),\n\tKQU(13520525127852368784), KQU(18294188662880997241),\n\tKQU( 3871781938044881523), KQU( 2873487268122812184),\n\tKQU(15099676759482679005), KQU(15442599127239350490),\n\tKQU( 6311893274367710888), KQU( 3286118760484672933),\n\tKQU( 4146067961333542189), KQU(13303942567897208770),\n\tKQU( 8196013722255630418), KQU( 4437815439340979989),\n\tKQU(15433791533450605135), KQU( 4254828956815687049),\n\tKQU( 1310903207708286015), KQU(10529182764462398549),\n\tKQU(14900231311660638810), KQU( 9727017277104609793),\n\tKQU( 1821308310948199033), KQU(11628861435066772084),\n\tKQU( 9469019138491546924), KQU( 3145812670532604988),\n\tKQU( 9938468915045491919), KQU( 1562447430672662142),\n\tKQU(13963995266697989134), KQU( 3356884357625028695),\n\tKQU( 4499850304584309747), KQU( 8456825817023658122),\n\tKQU(10859039922814285279), KQU( 8099512337972526555),\n\tKQU(  348006375109672149), KQU(11919893998241688603),\n\tKQU( 1104199577402948826), KQU(16689191854356060289),\n\tKQU(10992552041730168078), KQU( 7243733172705465836),\n\tKQU( 5668075606180319560), KQU(18182847037333286970),\n\tKQU( 4290215357664631322), KQU( 4061414220791828613),\n\tKQU(13006291061652989604), KQU( 7140491178917128798),\n\tKQU(12703446217663283481), KQU( 5500220597564558267),\n\tKQU(10330551509971296358), KQU(15958554768648714492),\n\tKQU( 5174555954515360045), KQU( 1731318837687577735),\n\tKQU( 3557700801048354857), KQU(13764012341928616198),\n\tKQU(13115166194379119043), KQU( 7989321021560255519),\n\tKQU( 2103584280905877040), KQU( 9230788662155228488),\n\tKQU(16396629323325547654), KQU(  657926409811318051),\n\tKQU(15046700264391400727), KQU( 5120132858771880830),\n\tKQU( 7934160097989028561), KQU( 6963121488531976245),\n\tKQU(17412329602621742089), KQU(15144843053931774092),\n\tKQU(17204176651763054532), KQU(13166595387554065870),\n\tKQU( 8590377810513960213), KQU( 5834365135373991938),\n\tKQU( 7640913007182226243), KQU( 3479394703859418425),\n\tKQU(16402784452644521040), KQU( 4993979809687083980),\n\tKQU(13254522168097688865), KQU(15643659095244365219),\n\tKQU( 5881437660538424982), KQU(11174892200618987379),\n\tKQU(  254409966159711077), KQU(17158413043140549909),\n\tKQU( 3638048789290376272), KQU( 1376816930299489190),\n\tKQU( 4622462095217761923), KQU(15086407973010263515),\n\tKQU(13253971772784692238), KQU( 5270549043541649236),\n\tKQU(11182714186805411604), KQU(12283846437495577140),\n\tKQU( 5297647149908953219), KQU(10047451738316836654),\n\tKQU( 4938228100367874746), KQU(12328523025304077923),\n\tKQU( 3601049438595312361), KQU( 9313624118352733770),\n\tKQU(13322966086117661798), KQU(16660005705644029394),\n\tKQU(11337677526988872373), KQU(13869299102574417795),\n\tKQU(15642043183045645437), KQU( 3021755569085880019),\n\tKQU( 4979741767761188161), KQU(13679979092079279587),\n\tKQU( 3344685842861071743), KQU(13947960059899588104),\n\tKQU(  305806934293368007), KQU( 5749173929201650029),\n\tKQU(11123724852118844098), KQU(15128987688788879802),\n\tKQU(15251651211024665009), KQU( 7689925933816577776),\n\tKQU(16732804392695859449), KQU(17087345401014078468),\n\tKQU(14315108589159048871), KQU( 4820700266619778917),\n\tKQU(16709637539357958441), KQU( 4936227875177351374),\n\tKQU( 2137907697912987247), KQU(11628565601408395420),\n\tKQU( 2333250549241556786), KQU( 5711200379577778637),\n\tKQU( 5170680131529031729), KQU(12620392043061335164),\n\tKQU(   95363390101096078), KQU( 5487981914081709462),\n\tKQU( 1763109823981838620), KQU( 3395861271473224396),\n\tKQU( 1300496844282213595), KQU( 6894316212820232902),\n\tKQU(10673859651135576674), KQU( 5911839658857903252),\n\tKQU(17407110743387299102), KQU( 8257427154623140385),\n\tKQU(11389003026741800267), KQU( 4070043211095013717),\n\tKQU(11663806997145259025), KQU(15265598950648798210),\n\tKQU(  630585789434030934), KQU( 3524446529213587334),\n\tKQU( 7186424168495184211), KQU(10806585451386379021),\n\tKQU(11120017753500499273), KQU( 1586837651387701301),\n\tKQU(17530454400954415544), KQU( 9991670045077880430),\n\tKQU( 7550997268990730180), KQU( 8640249196597379304),\n\tKQU( 3522203892786893823), KQU(10401116549878854788),\n\tKQU(13690285544733124852), KQU( 8295785675455774586),\n\tKQU(15535716172155117603), KQU( 3112108583723722511),\n\tKQU(17633179955339271113), KQU(18154208056063759375),\n\tKQU( 1866409236285815666), KQU(13326075895396412882),\n\tKQU( 8756261842948020025), KQU( 6281852999868439131),\n\tKQU(15087653361275292858), KQU(10333923911152949397),\n\tKQU( 5265567645757408500), KQU(12728041843210352184),\n\tKQU( 6347959327507828759), KQU(  154112802625564758),\n\tKQU(18235228308679780218), KQU( 3253805274673352418),\n\tKQU( 4849171610689031197), KQU(17948529398340432518),\n\tKQU(13803510475637409167), KQU(13506570190409883095),\n\tKQU(15870801273282960805), KQU( 8451286481299170773),\n\tKQU( 9562190620034457541), KQU( 8518905387449138364),\n\tKQU(12681306401363385655), KQU( 3788073690559762558),\n\tKQU( 5256820289573487769), KQU( 2752021372314875467),\n\tKQU( 6354035166862520716), KQU( 4328956378309739069),\n\tKQU(  449087441228269600), KQU( 5533508742653090868),\n\tKQU( 1260389420404746988), KQU(18175394473289055097),\n\tKQU( 1535467109660399420), KQU( 8818894282874061442),\n\tKQU(12140873243824811213), KQU(15031386653823014946),\n\tKQU( 1286028221456149232), KQU( 6329608889367858784),\n\tKQU( 9419654354945132725), KQU( 6094576547061672379),\n\tKQU(17706217251847450255), KQU( 1733495073065878126),\n\tKQU(16918923754607552663), KQU( 8881949849954945044),\n\tKQU(12938977706896313891), KQU(14043628638299793407),\n\tKQU(18393874581723718233), KQU( 6886318534846892044),\n\tKQU(14577870878038334081), KQU(13541558383439414119),\n\tKQU(13570472158807588273), KQU(18300760537910283361),\n\tKQU(  818368572800609205), KQU( 1417000585112573219),\n\tKQU(12337533143867683655), KQU(12433180994702314480),\n\tKQU(  778190005829189083), KQU(13667356216206524711),\n\tKQU( 9866149895295225230), KQU(11043240490417111999),\n\tKQU( 1123933826541378598), KQU( 6469631933605123610),\n\tKQU(14508554074431980040), KQU(13918931242962026714),\n\tKQU( 2870785929342348285), KQU(14786362626740736974),\n\tKQU(13176680060902695786), KQU( 9591778613541679456),\n\tKQU( 9097662885117436706), KQU(  749262234240924947),\n\tKQU( 1944844067793307093), KQU( 4339214904577487742),\n\tKQU( 8009584152961946551), KQU(16073159501225501777),\n\tKQU( 3335870590499306217), KQU(17088312653151202847),\n\tKQU( 3108893142681931848), KQU(16636841767202792021),\n\tKQU(10423316431118400637), KQU( 8008357368674443506),\n\tKQU(11340015231914677875), KQU(17687896501594936090),\n\tKQU(15173627921763199958), KQU(  542569482243721959),\n\tKQU(15071714982769812975), KQU( 4466624872151386956),\n\tKQU( 1901780715602332461), KQU( 9822227742154351098),\n\tKQU( 1479332892928648780), KQU( 6981611948382474400),\n\tKQU( 7620824924456077376), KQU(14095973329429406782),\n\tKQU( 7902744005696185404), KQU(15830577219375036920),\n\tKQU(10287076667317764416), KQU(12334872764071724025),\n\tKQU( 4419302088133544331), KQU(14455842851266090520),\n\tKQU(12488077416504654222), KQU( 7953892017701886766),\n\tKQU( 6331484925529519007), KQU( 4902145853785030022),\n\tKQU(17010159216096443073), KQU(11945354668653886087),\n\tKQU(15112022728645230829), KQU(17363484484522986742),\n\tKQU( 4423497825896692887), KQU( 8155489510809067471),\n\tKQU(  258966605622576285), KQU( 5462958075742020534),\n\tKQU( 6763710214913276228), KQU( 2368935183451109054),\n\tKQU(14209506165246453811), KQU( 2646257040978514881),\n\tKQU( 3776001911922207672), KQU( 1419304601390147631),\n\tKQU(14987366598022458284), KQU( 3977770701065815721),\n\tKQU(  730820417451838898), KQU( 3982991703612885327),\n\tKQU( 2803544519671388477), KQU(17067667221114424649),\n\tKQU( 2922555119737867166), KQU( 1989477584121460932),\n\tKQU(15020387605892337354), KQU( 9293277796427533547),\n\tKQU(10722181424063557247), KQU(16704542332047511651),\n\tKQU( 5008286236142089514), KQU(16174732308747382540),\n\tKQU(17597019485798338402), KQU(13081745199110622093),\n\tKQU( 8850305883842258115), KQU(12723629125624589005),\n\tKQU( 8140566453402805978), KQU(15356684607680935061),\n\tKQU(14222190387342648650), KQU(11134610460665975178),\n\tKQU( 1259799058620984266), KQU(13281656268025610041),\n\tKQU(  298262561068153992), KQU(12277871700239212922),\n\tKQU(13911297774719779438), KQU(16556727962761474934),\n\tKQU(17903010316654728010), KQU( 9682617699648434744),\n\tKQU(14757681836838592850), KQU( 1327242446558524473),\n\tKQU(11126645098780572792), KQU( 1883602329313221774),\n\tKQU( 2543897783922776873), KQU(15029168513767772842),\n\tKQU(12710270651039129878), KQU(16118202956069604504),\n\tKQU(15010759372168680524), KQU( 2296827082251923948),\n\tKQU(10793729742623518101), KQU(13829764151845413046),\n\tKQU(17769301223184451213), KQU( 3118268169210783372),\n\tKQU(17626204544105123127), KQU( 7416718488974352644),\n\tKQU(10450751996212925994), KQU( 9352529519128770586),\n\tKQU(  259347569641110140), KQU( 8048588892269692697),\n\tKQU( 1774414152306494058), KQU(10669548347214355622),\n\tKQU(13061992253816795081), KQU(18432677803063861659),\n\tKQU( 8879191055593984333), KQU(12433753195199268041),\n\tKQU(14919392415439730602), KQU( 6612848378595332963),\n\tKQU( 6320986812036143628), KQU(10465592420226092859),\n\tKQU( 4196009278962570808), KQU( 3747816564473572224),\n\tKQU(17941203486133732898), KQU( 2350310037040505198),\n\tKQU( 5811779859134370113), KQU(10492109599506195126),\n\tKQU( 7699650690179541274), KQU( 1954338494306022961),\n\tKQU(14095816969027231152), KQU( 5841346919964852061),\n\tKQU(14945969510148214735), KQU( 3680200305887550992),\n\tKQU( 6218047466131695792), KQU( 8242165745175775096),\n\tKQU(11021371934053307357), KQU( 1265099502753169797),\n\tKQU( 4644347436111321718), KQU( 3609296916782832859),\n\tKQU( 8109807992218521571), KQU(18387884215648662020),\n\tKQU(14656324896296392902), KQU(17386819091238216751),\n\tKQU(17788300878582317152), KQU( 7919446259742399591),\n\tKQU( 4466613134576358004), KQU(12928181023667938509),\n\tKQU(13147446154454932030), KQU(16552129038252734620),\n\tKQU( 8395299403738822450), KQU(11313817655275361164),\n\tKQU(  434258809499511718), KQU( 2074882104954788676),\n\tKQU( 7929892178759395518), KQU( 9006461629105745388),\n\tKQU( 5176475650000323086), KQU(11128357033468341069),\n\tKQU(12026158851559118955), KQU(14699716249471156500),\n\tKQU(  448982497120206757), KQU( 4156475356685519900),\n\tKQU( 6063816103417215727), KQU(10073289387954971479),\n\tKQU( 8174466846138590962), KQU( 2675777452363449006),\n\tKQU( 9090685420572474281), KQU( 6659652652765562060),\n\tKQU(12923120304018106621), KQU(11117480560334526775),\n\tKQU(  937910473424587511), KQU( 1838692113502346645),\n\tKQU(11133914074648726180), KQU( 7922600945143884053),\n\tKQU(13435287702700959550), KQU( 5287964921251123332),\n\tKQU(11354875374575318947), KQU(17955724760748238133),\n\tKQU(13728617396297106512), KQU( 4107449660118101255),\n\tKQU( 1210269794886589623), KQU(11408687205733456282),\n\tKQU( 4538354710392677887), KQU(13566803319341319267),\n\tKQU(17870798107734050771), KQU( 3354318982568089135),\n\tKQU( 9034450839405133651), KQU(13087431795753424314),\n\tKQU(  950333102820688239), KQU( 1968360654535604116),\n\tKQU(16840551645563314995), KQU( 8867501803892924995),\n\tKQU(11395388644490626845), KQU( 1529815836300732204),\n\tKQU(13330848522996608842), KQU( 1813432878817504265),\n\tKQU( 2336867432693429560), KQU(15192805445973385902),\n\tKQU( 2528593071076407877), KQU(  128459777936689248),\n\tKQU( 9976345382867214866), KQU( 6208885766767996043),\n\tKQU(14982349522273141706), KQU( 3099654362410737822),\n\tKQU(13776700761947297661), KQU( 8806185470684925550),\n\tKQU( 8151717890410585321), KQU(  640860591588072925),\n\tKQU(14592096303937307465), KQU( 9056472419613564846),\n\tKQU(14861544647742266352), KQU(12703771500398470216),\n\tKQU( 3142372800384138465), KQU( 6201105606917248196),\n\tKQU(18337516409359270184), KQU(15042268695665115339),\n\tKQU(15188246541383283846), KQU(12800028693090114519),\n\tKQU( 5992859621101493472), KQU(18278043971816803521),\n\tKQU( 9002773075219424560), KQU( 7325707116943598353),\n\tKQU( 7930571931248040822), KQU( 5645275869617023448),\n\tKQU( 7266107455295958487), KQU( 4363664528273524411),\n\tKQU(14313875763787479809), KQU(17059695613553486802),\n\tKQU( 9247761425889940932), KQU(13704726459237593128),\n\tKQU( 2701312427328909832), KQU(17235532008287243115),\n\tKQU(14093147761491729538), KQU( 6247352273768386516),\n\tKQU( 8268710048153268415), KQU( 7985295214477182083),\n\tKQU(15624495190888896807), KQU( 3772753430045262788),\n\tKQU( 9133991620474991698), KQU( 5665791943316256028),\n\tKQU( 7551996832462193473), KQU(13163729206798953877),\n\tKQU( 9263532074153846374), KQU( 1015460703698618353),\n\tKQU(17929874696989519390), KQU(18257884721466153847),\n\tKQU(16271867543011222991), KQU( 3905971519021791941),\n\tKQU(16814488397137052085), KQU( 1321197685504621613),\n\tKQU( 2870359191894002181), KQU(14317282970323395450),\n\tKQU(13663920845511074366), KQU( 2052463995796539594),\n\tKQU(14126345686431444337), KQU( 1727572121947022534),\n\tKQU(17793552254485594241), KQU( 6738857418849205750),\n\tKQU( 1282987123157442952), KQU(16655480021581159251),\n\tKQU( 6784587032080183866), KQU(14726758805359965162),\n\tKQU( 7577995933961987349), KQU(12539609320311114036),\n\tKQU(10789773033385439494), KQU( 8517001497411158227),\n\tKQU(10075543932136339710), KQU(14838152340938811081),\n\tKQU( 9560840631794044194), KQU(17445736541454117475),\n\tKQU(10633026464336393186), KQU(15705729708242246293),\n\tKQU( 1117517596891411098), KQU( 4305657943415886942),\n\tKQU( 4948856840533979263), KQU(16071681989041789593),\n\tKQU(13723031429272486527), KQU( 7639567622306509462),\n\tKQU(12670424537483090390), KQU( 9715223453097197134),\n\tKQU( 5457173389992686394), KQU(  289857129276135145),\n\tKQU(17048610270521972512), KQU(  692768013309835485),\n\tKQU(14823232360546632057), KQU(18218002361317895936),\n\tKQU( 3281724260212650204), KQU(16453957266549513795),\n\tKQU( 8592711109774511881), KQU(  929825123473369579),\n\tKQU(15966784769764367791), KQU( 9627344291450607588),\n\tKQU(10849555504977813287), KQU( 9234566913936339275),\n\tKQU( 6413807690366911210), KQU(10862389016184219267),\n\tKQU(13842504799335374048), KQU( 1531994113376881174),\n\tKQU( 2081314867544364459), KQU(16430628791616959932),\n\tKQU( 8314714038654394368), KQU( 9155473892098431813),\n\tKQU(12577843786670475704), KQU( 4399161106452401017),\n\tKQU( 1668083091682623186), KQU( 1741383777203714216),\n\tKQU( 2162597285417794374), KQU(15841980159165218736),\n\tKQU( 1971354603551467079), KQU( 1206714764913205968),\n\tKQU( 4790860439591272330), KQU(14699375615594055799),\n\tKQU( 8374423871657449988), KQU(10950685736472937738),\n\tKQU(  697344331343267176), KQU(10084998763118059810),\n\tKQU(12897369539795983124), KQU(12351260292144383605),\n\tKQU( 1268810970176811234), KQU( 7406287800414582768),\n\tKQU(  516169557043807831), KQU( 5077568278710520380),\n\tKQU( 3828791738309039304), KQU( 7721974069946943610),\n\tKQU( 3534670260981096460), KQU( 4865792189600584891),\n\tKQU(16892578493734337298), KQU( 9161499464278042590),\n\tKQU(11976149624067055931), KQU(13219479887277343990),\n\tKQU(14161556738111500680), KQU(14670715255011223056),\n\tKQU( 4671205678403576558), KQU(12633022931454259781),\n\tKQU(14821376219869187646), KQU(  751181776484317028),\n\tKQU( 2192211308839047070), KQU(11787306362361245189),\n\tKQU(10672375120744095707), KQU( 4601972328345244467),\n\tKQU(15457217788831125879), KQU( 8464345256775460809),\n\tKQU(10191938789487159478), KQU( 6184348739615197613),\n\tKQU(11425436778806882100), KQU( 2739227089124319793),\n\tKQU(  461464518456000551), KQU( 4689850170029177442),\n\tKQU( 6120307814374078625), KQU(11153579230681708671),\n\tKQU( 7891721473905347926), KQU(10281646937824872400),\n\tKQU( 3026099648191332248), KQU( 8666750296953273818),\n\tKQU(14978499698844363232), KQU(13303395102890132065),\n\tKQU( 8182358205292864080), KQU(10560547713972971291),\n\tKQU(11981635489418959093), KQU( 3134621354935288409),\n\tKQU(11580681977404383968), KQU(14205530317404088650),\n\tKQU( 5997789011854923157), KQU(13659151593432238041),\n\tKQU(11664332114338865086), KQU( 7490351383220929386),\n\tKQU( 7189290499881530378), KQU(15039262734271020220),\n\tKQU( 2057217285976980055), KQU(  555570804905355739),\n\tKQU(11235311968348555110), KQU(13824557146269603217),\n\tKQU(16906788840653099693), KQU( 7222878245455661677),\n\tKQU( 5245139444332423756), KQU( 4723748462805674292),\n\tKQU(12216509815698568612), KQU(17402362976648951187),\n\tKQU(17389614836810366768), KQU( 4880936484146667711),\n\tKQU( 9085007839292639880), KQU(13837353458498535449),\n\tKQU(11914419854360366677), KQU(16595890135313864103),\n\tKQU( 6313969847197627222), KQU(18296909792163910431),\n\tKQU(10041780113382084042), KQU( 2499478551172884794),\n\tKQU(11057894246241189489), KQU( 9742243032389068555),\n\tKQU(12838934582673196228), KQU(13437023235248490367),\n\tKQU(13372420669446163240), KQU( 6752564244716909224),\n\tKQU( 7157333073400313737), KQU(12230281516370654308),\n\tKQU( 1182884552219419117), KQU( 2955125381312499218),\n\tKQU(10308827097079443249), KQU( 1337648572986534958),\n\tKQU(16378788590020343939), KQU(  108619126514420935),\n\tKQU( 3990981009621629188), KQU( 5460953070230946410),\n\tKQU( 9703328329366531883), KQU(13166631489188077236),\n\tKQU( 1104768831213675170), KQU( 3447930458553877908),\n\tKQU( 8067172487769945676), KQU( 5445802098190775347),\n\tKQU( 3244840981648973873), KQU(17314668322981950060),\n\tKQU( 5006812527827763807), KQU(18158695070225526260),\n\tKQU( 2824536478852417853), KQU(13974775809127519886),\n\tKQU( 9814362769074067392), KQU(17276205156374862128),\n\tKQU(11361680725379306967), KQU( 3422581970382012542),\n\tKQU(11003189603753241266), KQU(11194292945277862261),\n\tKQU( 6839623313908521348), KQU(11935326462707324634),\n\tKQU( 1611456788685878444), KQU(13112620989475558907),\n\tKQU(  517659108904450427), KQU(13558114318574407624),\n\tKQU(15699089742731633077), KQU( 4988979278862685458),\n\tKQU( 8111373583056521297), KQU( 3891258746615399627),\n\tKQU( 8137298251469718086), KQU(12748663295624701649),\n\tKQU( 4389835683495292062), KQU( 5775217872128831729),\n\tKQU( 9462091896405534927), KQU( 8498124108820263989),\n\tKQU( 8059131278842839525), KQU(10503167994254090892),\n\tKQU(11613153541070396656), KQU(18069248738504647790),\n\tKQU(  570657419109768508), KQU( 3950574167771159665),\n\tKQU( 5514655599604313077), KQU( 2908460854428484165),\n\tKQU(10777722615935663114), KQU(12007363304839279486),\n\tKQU( 9800646187569484767), KQU( 8795423564889864287),\n\tKQU(14257396680131028419), KQU( 6405465117315096498),\n\tKQU( 7939411072208774878), KQU(17577572378528990006),\n\tKQU(14785873806715994850), KQU(16770572680854747390),\n\tKQU(18127549474419396481), KQU(11637013449455757750),\n\tKQU(14371851933996761086), KQU( 3601181063650110280),\n\tKQU( 4126442845019316144), KQU(10198287239244320669),\n\tKQU(18000169628555379659), KQU(18392482400739978269),\n\tKQU( 6219919037686919957), KQU( 3610085377719446052),\n\tKQU( 2513925039981776336), KQU(16679413537926716955),\n\tKQU(12903302131714909434), KQU( 5581145789762985009),\n\tKQU(12325955044293303233), KQU(17216111180742141204),\n\tKQU( 6321919595276545740), KQU( 3507521147216174501),\n\tKQU( 9659194593319481840), KQU(11473976005975358326),\n\tKQU(14742730101435987026), KQU(  492845897709954780),\n\tKQU(16976371186162599676), KQU(17712703422837648655),\n\tKQU( 9881254778587061697), KQU( 8413223156302299551),\n\tKQU( 1563841828254089168), KQU( 9996032758786671975),\n\tKQU(  138877700583772667), KQU(13003043368574995989),\n\tKQU( 4390573668650456587), KQU( 8610287390568126755),\n\tKQU(15126904974266642199), KQU( 6703637238986057662),\n\tKQU( 2873075592956810157), KQU( 6035080933946049418),\n\tKQU(13382846581202353014), KQU( 7303971031814642463),\n\tKQU(18418024405307444267), KQU( 5847096731675404647),\n\tKQU( 4035880699639842500), KQU(11525348625112218478),\n\tKQU( 3041162365459574102), KQU( 2604734487727986558),\n\tKQU(15526341771636983145), KQU(14556052310697370254),\n\tKQU(12997787077930808155), KQU( 9601806501755554499),\n\tKQU(11349677952521423389), KQU(14956777807644899350),\n\tKQU(16559736957742852721), KQU(12360828274778140726),\n\tKQU( 6685373272009662513), KQU(16932258748055324130),\n\tKQU(15918051131954158508), KQU( 1692312913140790144),\n\tKQU(  546653826801637367), KQU( 5341587076045986652),\n\tKQU(14975057236342585662), KQU(12374976357340622412),\n\tKQU(10328833995181940552), KQU(12831807101710443149),\n\tKQU(10548514914382545716), KQU( 2217806727199715993),\n\tKQU(12627067369242845138), KQU( 4598965364035438158),\n\tKQU(  150923352751318171), KQU(14274109544442257283),\n\tKQU( 4696661475093863031), KQU( 1505764114384654516),\n\tKQU(10699185831891495147), KQU( 2392353847713620519),\n\tKQU( 3652870166711788383), KQU( 8640653276221911108),\n\tKQU( 3894077592275889704), KQU( 4918592872135964845),\n\tKQU(16379121273281400789), KQU(12058465483591683656),\n\tKQU(11250106829302924945), KQU( 1147537556296983005),\n\tKQU( 6376342756004613268), KQU(14967128191709280506),\n\tKQU(18007449949790627628), KQU( 9497178279316537841),\n\tKQU( 7920174844809394893), KQU(10037752595255719907),\n\tKQU(15875342784985217697), KQU(15311615921712850696),\n\tKQU( 9552902652110992950), KQU(14054979450099721140),\n\tKQU( 5998709773566417349), KQU(18027910339276320187),\n\tKQU( 8223099053868585554), KQU( 7842270354824999767),\n\tKQU( 4896315688770080292), KQU(12969320296569787895),\n\tKQU( 2674321489185759961), KQU( 4053615936864718439),\n\tKQU(11349775270588617578), KQU( 4743019256284553975),\n\tKQU( 5602100217469723769), KQU(14398995691411527813),\n\tKQU( 7412170493796825470), KQU(  836262406131744846),\n\tKQU( 8231086633845153022), KQU( 5161377920438552287),\n\tKQU( 8828731196169924949), KQU(16211142246465502680),\n\tKQU( 3307990879253687818), KQU( 5193405406899782022),\n\tKQU( 8510842117467566693), KQU( 6070955181022405365),\n\tKQU(14482950231361409799), KQU(12585159371331138077),\n\tKQU( 3511537678933588148), KQU( 2041849474531116417),\n\tKQU(10944936685095345792), KQU(18303116923079107729),\n\tKQU( 2720566371239725320), KQU( 4958672473562397622),\n\tKQU( 3032326668253243412), KQU(13689418691726908338),\n\tKQU( 1895205511728843996), KQU( 8146303515271990527),\n\tKQU(16507343500056113480), KQU(  473996939105902919),\n\tKQU( 9897686885246881481), KQU(14606433762712790575),\n\tKQU( 6732796251605566368), KQU( 1399778120855368916),\n\tKQU(  935023885182833777), KQU(16066282816186753477),\n\tKQU( 7291270991820612055), KQU(17530230393129853844),\n\tKQU(10223493623477451366), KQU(15841725630495676683),\n\tKQU(17379567246435515824), KQU( 8588251429375561971),\n\tKQU(18339511210887206423), KQU(17349587430725976100),\n\tKQU(12244876521394838088), KQU( 6382187714147161259),\n\tKQU(12335807181848950831), KQU(16948885622305460665),\n\tKQU(13755097796371520506), KQU(14806740373324947801),\n\tKQU( 4828699633859287703), KQU( 8209879281452301604),\n\tKQU(12435716669553736437), KQU(13970976859588452131),\n\tKQU( 6233960842566773148), KQU(12507096267900505759),\n\tKQU( 1198713114381279421), KQU(14989862731124149015),\n\tKQU(15932189508707978949), KQU( 2526406641432708722),\n\tKQU(   29187427817271982), KQU( 1499802773054556353),\n\tKQU(10816638187021897173), KQU( 5436139270839738132),\n\tKQU( 6659882287036010082), KQU( 2154048955317173697),\n\tKQU(10887317019333757642), KQU(16281091802634424955),\n\tKQU(10754549879915384901), KQU(10760611745769249815),\n\tKQU( 2161505946972504002), KQU( 5243132808986265107),\n\tKQU(10129852179873415416), KQU(  710339480008649081),\n\tKQU( 7802129453068808528), KQU(17967213567178907213),\n\tKQU(15730859124668605599), KQU(13058356168962376502),\n\tKQU( 3701224985413645909), KQU(14464065869149109264),\n\tKQU( 9959272418844311646), KQU(10157426099515958752),\n\tKQU(14013736814538268528), KQU(17797456992065653951),\n\tKQU(17418878140257344806), KQU(15457429073540561521),\n\tKQU( 2184426881360949378), KQU( 2062193041154712416),\n\tKQU( 8553463347406931661), KQU( 4913057625202871854),\n\tKQU( 2668943682126618425), KQU(17064444737891172288),\n\tKQU( 4997115903913298637), KQU(12019402608892327416),\n\tKQU(17603584559765897352), KQU(11367529582073647975),\n\tKQU( 8211476043518436050), KQU( 8676849804070323674),\n\tKQU(18431829230394475730), KQU(10490177861361247904),\n\tKQU( 9508720602025651349), KQU( 7409627448555722700),\n\tKQU( 5804047018862729008), KQU(11943858176893142594),\n\tKQU(11908095418933847092), KQU( 5415449345715887652),\n\tKQU( 1554022699166156407), KQU( 9073322106406017161),\n\tKQU( 7080630967969047082), KQU(18049736940860732943),\n\tKQU(12748714242594196794), KQU( 1226992415735156741),\n\tKQU(17900981019609531193), KQU(11720739744008710999),\n\tKQU( 3006400683394775434), KQU(11347974011751996028),\n\tKQU( 3316999628257954608), KQU( 8384484563557639101),\n\tKQU(18117794685961729767), KQU( 1900145025596618194),\n\tKQU(17459527840632892676), KQU( 5634784101865710994),\n\tKQU( 7918619300292897158), KQU( 3146577625026301350),\n\tKQU( 9955212856499068767), KQU( 1873995843681746975),\n\tKQU( 1561487759967972194), KQU( 8322718804375878474),\n\tKQU(11300284215327028366), KQU( 4667391032508998982),\n\tKQU( 9820104494306625580), KQU(17922397968599970610),\n\tKQU( 1784690461886786712), KQU(14940365084341346821),\n\tKQU( 5348719575594186181), KQU(10720419084507855261),\n\tKQU(14210394354145143274), KQU( 2426468692164000131),\n\tKQU(16271062114607059202), KQU(14851904092357070247),\n\tKQU( 6524493015693121897), KQU( 9825473835127138531),\n\tKQU(14222500616268569578), KQU(15521484052007487468),\n\tKQU(14462579404124614699), KQU(11012375590820665520),\n\tKQU(11625327350536084927), KQU(14452017765243785417),\n\tKQU( 9989342263518766305), KQU( 3640105471101803790),\n\tKQU( 4749866455897513242), KQU(13963064946736312044),\n\tKQU(10007416591973223791), KQU(18314132234717431115),\n\tKQU( 3286596588617483450), KQU( 7726163455370818765),\n\tKQU( 7575454721115379328), KQU( 5308331576437663422),\n\tKQU(18288821894903530934), KQU( 8028405805410554106),\n\tKQU(15744019832103296628), KQU(  149765559630932100),\n\tKQU( 6137705557200071977), KQU(14513416315434803615),\n\tKQU(11665702820128984473), KQU(  218926670505601386),\n\tKQU( 6868675028717769519), KQU(15282016569441512302),\n\tKQU( 5707000497782960236), KQU( 6671120586555079567),\n\tKQU( 2194098052618985448), KQU(16849577895477330978),\n\tKQU(12957148471017466283), KQU( 1997805535404859393),\n\tKQU( 1180721060263860490), KQU(13206391310193756958),\n\tKQU(12980208674461861797), KQU( 3825967775058875366),\n\tKQU(17543433670782042631), KQU( 1518339070120322730),\n\tKQU(16344584340890991669), KQU( 2611327165318529819),\n\tKQU(11265022723283422529), KQU( 4001552800373196817),\n\tKQU(14509595890079346161), KQU( 3528717165416234562),\n\tKQU(18153222571501914072), KQU( 9387182977209744425),\n\tKQU(10064342315985580021), KQU(11373678413215253977),\n\tKQU( 2308457853228798099), KQU( 9729042942839545302),\n\tKQU( 7833785471140127746), KQU( 6351049900319844436),\n\tKQU(14454610627133496067), KQU(12533175683634819111),\n\tKQU(15570163926716513029), KQU(13356980519185762498)\n};\n\nTEST_BEGIN(test_gen_rand_32)\n{\n\tuint32_t array32[BLOCK_SIZE] JEMALLOC_ATTR(aligned(16));\n\tuint32_t array32_2[BLOCK_SIZE] JEMALLOC_ATTR(aligned(16));\n\tint i;\n\tuint32_t r32;\n\tsfmt_t *ctx;\n\n\tassert_d_le(get_min_array_size32(), BLOCK_SIZE,\n\t    \"Array size too small\");\n\tctx = init_gen_rand(1234);\n\tfill_array32(ctx, array32, BLOCK_SIZE);\n\tfill_array32(ctx, array32_2, BLOCK_SIZE);\n\tfini_gen_rand(ctx);\n\n\tctx = init_gen_rand(1234);\n\tfor (i = 0; i < BLOCK_SIZE; i++) {\n\t\tif (i < COUNT_1) {\n\t\t\tassert_u32_eq(array32[i], init_gen_rand_32_expected[i],\n\t\t\t    \"Output mismatch for i=%d\", i);\n\t\t}\n\t\tr32 = gen_rand32(ctx);\n\t\tassert_u32_eq(r32, array32[i],\n\t\t    \"Mismatch at array32[%d]=%x, gen=%x\", i, array32[i], r32);\n\t}\n\tfor (i = 0; i < COUNT_2; i++) {\n\t\tr32 = gen_rand32(ctx);\n\t\tassert_u32_eq(r32, array32_2[i],\n\t\t    \"Mismatch at array32_2[%d]=%x, gen=%x\", i, array32_2[i],\n\t\t    r32);\n\t}\n\tfini_gen_rand(ctx);\n}\nTEST_END\n\nTEST_BEGIN(test_by_array_32)\n{\n\tuint32_t array32[BLOCK_SIZE] JEMALLOC_ATTR(aligned(16));\n\tuint32_t array32_2[BLOCK_SIZE] JEMALLOC_ATTR(aligned(16));\n\tint i;\n\tuint32_t ini[4] = {0x1234, 0x5678, 0x9abc, 0xdef0};\n\tuint32_t r32;\n\tsfmt_t *ctx;\n\n\tassert_d_le(get_min_array_size32(), BLOCK_SIZE,\n\t    \"Array size too small\");\n\tctx = init_by_array(ini, 4);\n\tfill_array32(ctx, array32, BLOCK_SIZE);\n\tfill_array32(ctx, array32_2, BLOCK_SIZE);\n\tfini_gen_rand(ctx);\n\n\tctx = init_by_array(ini, 4);\n\tfor (i = 0; i < BLOCK_SIZE; i++) {\n\t\tif (i < COUNT_1) {\n\t\t\tassert_u32_eq(array32[i], init_by_array_32_expected[i],\n\t\t\t    \"Output mismatch for i=%d\", i);\n\t\t}\n\t\tr32 = gen_rand32(ctx);\n\t\tassert_u32_eq(r32, array32[i],\n\t\t    \"Mismatch at array32[%d]=%x, gen=%x\", i, array32[i], r32);\n\t}\n\tfor (i = 0; i < COUNT_2; i++) {\n\t\tr32 = gen_rand32(ctx);\n\t\tassert_u32_eq(r32, array32_2[i],\n\t\t    \"Mismatch at array32_2[%d]=%x, gen=%x\", i, array32_2[i],\n\t\t    r32);\n\t}\n\tfini_gen_rand(ctx);\n}\nTEST_END\n\nTEST_BEGIN(test_gen_rand_64)\n{\n\tuint64_t array64[BLOCK_SIZE64] JEMALLOC_ATTR(aligned(16));\n\tuint64_t array64_2[BLOCK_SIZE64] JEMALLOC_ATTR(aligned(16));\n\tint i;\n\tuint64_t r;\n\tsfmt_t *ctx;\n\n\tassert_d_le(get_min_array_size64(), BLOCK_SIZE64,\n\t    \"Array size too small\");\n\tctx = init_gen_rand(4321);\n\tfill_array64(ctx, array64, BLOCK_SIZE64);\n\tfill_array64(ctx, array64_2, BLOCK_SIZE64);\n\tfini_gen_rand(ctx);\n\n\tctx = init_gen_rand(4321);\n\tfor (i = 0; i < BLOCK_SIZE64; i++) {\n\t\tif (i < COUNT_1) {\n\t\t\tassert_u64_eq(array64[i], init_gen_rand_64_expected[i],\n\t\t\t    \"Output mismatch for i=%d\", i);\n\t\t}\n\t\tr = gen_rand64(ctx);\n\t\tassert_u64_eq(r, array64[i],\n\t\t    \"Mismatch at array64[%d]=%\"FMTx64\", gen=%\"FMTx64, i,\n\t\t    array64[i], r);\n\t}\n\tfor (i = 0; i < COUNT_2; i++) {\n\t\tr = gen_rand64(ctx);\n\t\tassert_u64_eq(r, array64_2[i],\n\t\t    \"Mismatch at array64_2[%d]=%\"FMTx64\" gen=%\"FMTx64\"\", i,\n\t\t    array64_2[i], r);\n\t}\n\tfini_gen_rand(ctx);\n}\nTEST_END\n\nTEST_BEGIN(test_by_array_64)\n{\n\tuint64_t array64[BLOCK_SIZE64] JEMALLOC_ATTR(aligned(16));\n\tuint64_t array64_2[BLOCK_SIZE64] JEMALLOC_ATTR(aligned(16));\n\tint i;\n\tuint64_t r;\n\tuint32_t ini[] = {5, 4, 3, 2, 1};\n\tsfmt_t *ctx;\n\n\tassert_d_le(get_min_array_size64(), BLOCK_SIZE64,\n\t    \"Array size too small\");\n\tctx = init_by_array(ini, 5);\n\tfill_array64(ctx, array64, BLOCK_SIZE64);\n\tfill_array64(ctx, array64_2, BLOCK_SIZE64);\n\tfini_gen_rand(ctx);\n\n\tctx = init_by_array(ini, 5);\n\tfor (i = 0; i < BLOCK_SIZE64; i++) {\n\t\tif (i < COUNT_1) {\n\t\t\tassert_u64_eq(array64[i], init_by_array_64_expected[i],\n\t\t\t    \"Output mismatch for i=%d\", i);\n\t\t}\n\t\tr = gen_rand64(ctx);\n\t\tassert_u64_eq(r, array64[i],\n\t\t    \"Mismatch at array64[%d]=%\"FMTx64\" gen=%\"FMTx64, i,\n\t\t    array64[i], r);\n\t}\n\tfor (i = 0; i < COUNT_2; i++) {\n\t\tr = gen_rand64(ctx);\n\t\tassert_u64_eq(r, array64_2[i],\n\t\t    \"Mismatch at array64_2[%d]=%\"FMTx64\" gen=%\"FMTx64, i,\n\t\t    array64_2[i], r);\n\t}\n\tfini_gen_rand(ctx);\n}\nTEST_END\n\nint\nmain(void)\n{\n\n\treturn (test(\n\t    test_gen_rand_32,\n\t    test_by_array_32,\n\t    test_gen_rand_64,\n\t    test_by_array_64));\n}\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/deps/jemalloc/test/unit/a0.c",
    "content": "#include \"test/jemalloc_test.h\"\n\nTEST_BEGIN(test_a0)\n{\n\tvoid *p;\n\n\tp = a0malloc(1);\n\tassert_ptr_not_null(p, \"Unexpected a0malloc() error\");\n\ta0dalloc(p);\n}\nTEST_END\n\nint\nmain(void)\n{\n\n\treturn (test_no_malloc_init(\n\t    test_a0));\n}\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/deps/jemalloc/test/unit/arena_reset.c",
    "content": "#include \"test/jemalloc_test.h\"\n\n#ifdef JEMALLOC_PROF\nconst char *malloc_conf = \"prof:true,lg_prof_sample:0\";\n#endif\n\nstatic unsigned\nget_nsizes_impl(const char *cmd)\n{\n\tunsigned ret;\n\tsize_t z;\n\n\tz = sizeof(unsigned);\n\tassert_d_eq(mallctl(cmd, &ret, &z, NULL, 0), 0,\n\t    \"Unexpected mallctl(\\\"%s\\\", ...) failure\", cmd);\n\n\treturn (ret);\n}\n\nstatic unsigned\nget_nsmall(void)\n{\n\n\treturn (get_nsizes_impl(\"arenas.nbins\"));\n}\n\nstatic unsigned\nget_nlarge(void)\n{\n\n\treturn (get_nsizes_impl(\"arenas.nlruns\"));\n}\n\nstatic unsigned\nget_nhuge(void)\n{\n\n\treturn (get_nsizes_impl(\"arenas.nhchunks\"));\n}\n\nstatic size_t\nget_size_impl(const char *cmd, size_t ind)\n{\n\tsize_t ret;\n\tsize_t z;\n\tsize_t mib[4];\n\tsize_t miblen = 4;\n\n\tz = sizeof(size_t);\n\tassert_d_eq(mallctlnametomib(cmd, mib, &miblen),\n\t    0, \"Unexpected mallctlnametomib(\\\"%s\\\", ...) failure\", cmd);\n\tmib[2] = ind;\n\tz = sizeof(size_t);\n\tassert_d_eq(mallctlbymib(mib, miblen, &ret, &z, NULL, 0),\n\t    0, \"Unexpected mallctlbymib([\\\"%s\\\", %zu], ...) failure\", cmd, ind);\n\n\treturn (ret);\n}\n\nstatic size_t\nget_small_size(size_t ind)\n{\n\n\treturn (get_size_impl(\"arenas.bin.0.size\", ind));\n}\n\nstatic size_t\nget_large_size(size_t ind)\n{\n\n\treturn (get_size_impl(\"arenas.lrun.0.size\", ind));\n}\n\nstatic size_t\nget_huge_size(size_t ind)\n{\n\n\treturn (get_size_impl(\"arenas.hchunk.0.size\", ind));\n}\n\nTEST_BEGIN(test_arena_reset)\n{\n#define\tNHUGE\t4\n\tunsigned arena_ind, nsmall, nlarge, nhuge, nptrs, i;\n\tsize_t sz, miblen;\n\tvoid **ptrs;\n\tint flags;\n\tsize_t mib[3];\n\ttsdn_t *tsdn;\n\n\ttest_skip_if((config_valgrind && unlikely(in_valgrind)) || (config_fill\n\t    && unlikely(opt_quarantine)));\n\n\tsz = sizeof(unsigned);\n\tassert_d_eq(mallctl(\"arenas.extend\", &arena_ind, &sz, NULL, 0), 0,\n\t    \"Unexpected mallctl() failure\");\n\n\tflags = MALLOCX_ARENA(arena_ind) | MALLOCX_TCACHE_NONE;\n\n\tnsmall = get_nsmall();\n\tnlarge = get_nlarge();\n\tnhuge = get_nhuge() > NHUGE ? NHUGE : get_nhuge();\n\tnptrs = nsmall + nlarge + nhuge;\n\tptrs = (void **)malloc(nptrs * sizeof(void *));\n\tassert_ptr_not_null(ptrs, \"Unexpected malloc() failure\");\n\n\t/* Allocate objects with a wide range of sizes. */\n\tfor (i = 0; i < nsmall; i++) {\n\t\tsz = get_small_size(i);\n\t\tptrs[i] = mallocx(sz, flags);\n\t\tassert_ptr_not_null(ptrs[i],\n\t\t    \"Unexpected mallocx(%zu, %#x) failure\", sz, flags);\n\t}\n\tfor (i = 0; i < nlarge; i++) {\n\t\tsz = get_large_size(i);\n\t\tptrs[nsmall + i] = mallocx(sz, flags);\n\t\tassert_ptr_not_null(ptrs[i],\n\t\t    \"Unexpected mallocx(%zu, %#x) failure\", sz, flags);\n\t}\n\tfor (i = 0; i < nhuge; i++) {\n\t\tsz = get_huge_size(i);\n\t\tptrs[nsmall + nlarge + i] = mallocx(sz, flags);\n\t\tassert_ptr_not_null(ptrs[i],\n\t\t    \"Unexpected mallocx(%zu, %#x) failure\", sz, flags);\n\t}\n\n\ttsdn = tsdn_fetch();\n\n\t/* Verify allocations. */\n\tfor (i = 0; i < nptrs; i++) {\n\t\tassert_zu_gt(ivsalloc(tsdn, ptrs[i], false), 0,\n\t\t    \"Allocation should have queryable size\");\n\t}\n\n\t/* Reset. */\n\tmiblen = sizeof(mib)/sizeof(size_t);\n\tassert_d_eq(mallctlnametomib(\"arena.0.reset\", mib, &miblen), 0,\n\t    \"Unexpected mallctlnametomib() failure\");\n\tmib[1] = (size_t)arena_ind;\n\tassert_d_eq(mallctlbymib(mib, miblen, NULL, NULL, NULL, 0), 0,\n\t    \"Unexpected mallctlbymib() failure\");\n\n\t/* Verify allocations no longer exist. */\n\tfor (i = 0; i < nptrs; i++) {\n\t\tassert_zu_eq(ivsalloc(tsdn, ptrs[i], false), 0,\n\t\t    \"Allocation should no longer exist\");\n\t}\n\n\tfree(ptrs);\n}\nTEST_END\n\nint\nmain(void)\n{\n\n\treturn (test(\n\t    test_arena_reset));\n}\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/deps/jemalloc/test/unit/atomic.c",
    "content": "#include \"test/jemalloc_test.h\"\n\n#define\tTEST_STRUCT(p, t)\t\t\t\t\t\t\\\nstruct p##_test_s {\t\t\t\t\t\t\t\\\n\tt\taccum0;\t\t\t\t\t\t\t\\\n\tt\tx;\t\t\t\t\t\t\t\\\n\tt\ts;\t\t\t\t\t\t\t\\\n};\t\t\t\t\t\t\t\t\t\\\ntypedef struct p##_test_s p##_test_t;\n\n#define\tTEST_BODY(p, t, tc, ta, FMT) do {\t\t\t\t\\\n\tconst p##_test_t tests[] = {\t\t\t\t\t\\\n\t\t{(t)-1, (t)-1, (t)-2},\t\t\t\t\t\\\n\t\t{(t)-1, (t) 0, (t)-2},\t\t\t\t\t\\\n\t\t{(t)-1, (t) 1, (t)-2},\t\t\t\t\t\\\n\t\t\t\t\t\t\t\t\t\\\n\t\t{(t) 0, (t)-1, (t)-2},\t\t\t\t\t\\\n\t\t{(t) 0, (t) 0, (t)-2},\t\t\t\t\t\\\n\t\t{(t) 0, (t) 1, (t)-2},\t\t\t\t\t\\\n\t\t\t\t\t\t\t\t\t\\\n\t\t{(t) 1, (t)-1, (t)-2},\t\t\t\t\t\\\n\t\t{(t) 1, (t) 0, (t)-2},\t\t\t\t\t\\\n\t\t{(t) 1, (t) 1, (t)-2},\t\t\t\t\t\\\n\t\t\t\t\t\t\t\t\t\\\n\t\t{(t)0, (t)-(1 << 22), (t)-2},\t\t\t\t\\\n\t\t{(t)0, (t)(1 << 22), (t)-2},\t\t\t\t\\\n\t\t{(t)(1 << 22), (t)-(1 << 22), (t)-2},\t\t\t\\\n\t\t{(t)(1 << 22), (t)(1 << 22), (t)-2}\t\t\t\\\n\t};\t\t\t\t\t\t\t\t\\\n\tunsigned i;\t\t\t\t\t\t\t\\\n\t\t\t\t\t\t\t\t\t\\\n\tfor (i = 0; i < sizeof(tests)/sizeof(p##_test_t); i++) {\t\\\n\t\tbool err;\t\t\t\t\t\t\\\n\t\tt accum = tests[i].accum0;\t\t\t\t\\\n\t\tassert_##ta##_eq(atomic_read_##p(&accum),\t\t\\\n\t\t    tests[i].accum0,\t\t\t\t\t\\\n\t\t    \"Erroneous read, i=%u\", i);\t\t\t\t\\\n\t\t\t\t\t\t\t\t\t\\\n\t\tassert_##ta##_eq(atomic_add_##p(&accum, tests[i].x),\t\\\n\t\t    (t)((tc)tests[i].accum0 + (tc)tests[i].x),\t\t\\\n\t\t    \"i=%u, accum=%\"FMT\", x=%\"FMT,\t\t\t\\\n\t\t    i, tests[i].accum0, tests[i].x);\t\t\t\\\n\t\tassert_##ta##_eq(atomic_read_##p(&accum), accum,\t\\\n\t\t    \"Erroneous add, i=%u\", i);\t\t\t\t\\\n\t\t\t\t\t\t\t\t\t\\\n\t\taccum = tests[i].accum0;\t\t\t\t\\\n\t\tassert_##ta##_eq(atomic_sub_##p(&accum, tests[i].x),\t\\\n\t\t    (t)((tc)tests[i].accum0 - (tc)tests[i].x),\t\t\\\n\t\t    \"i=%u, accum=%\"FMT\", x=%\"FMT,\t\t\t\\\n\t\t    i, tests[i].accum0, tests[i].x);\t\t\t\\\n\t\tassert_##ta##_eq(atomic_read_##p(&accum), accum,\t\\\n\t\t    \"Erroneous sub, i=%u\", i);\t\t\t\t\\\n\t\t\t\t\t\t\t\t\t\\\n\t\taccum = tests[i].accum0;\t\t\t\t\\\n\t\terr = atomic_cas_##p(&accum, tests[i].x, tests[i].s);\t\\\n\t\tassert_b_eq(err, tests[i].accum0 != tests[i].x,\t\t\\\n\t\t    \"Erroneous cas success/failure result\");\t\t\\\n\t\tassert_##ta##_eq(accum, err ? tests[i].accum0 :\t\t\\\n\t\t    tests[i].s, \"Erroneous cas effect, i=%u\", i);\t\\\n\t\t\t\t\t\t\t\t\t\\\n\t\taccum = tests[i].accum0;\t\t\t\t\\\n\t\tatomic_write_##p(&accum, tests[i].s);\t\t\t\\\n\t\tassert_##ta##_eq(accum, tests[i].s,\t\t\t\\\n\t\t    \"Erroneous write, i=%u\", i);\t\t\t\\\n\t}\t\t\t\t\t\t\t\t\\\n} while (0)\n\nTEST_STRUCT(uint64, uint64_t)\nTEST_BEGIN(test_atomic_uint64)\n{\n\n#if !(LG_SIZEOF_PTR == 3 || LG_SIZEOF_INT == 3)\n\ttest_skip(\"64-bit atomic operations not supported\");\n#else\n\tTEST_BODY(uint64, uint64_t, uint64_t, u64, FMTx64);\n#endif\n}\nTEST_END\n\nTEST_STRUCT(uint32, uint32_t)\nTEST_BEGIN(test_atomic_uint32)\n{\n\n\tTEST_BODY(uint32, uint32_t, uint32_t, u32, \"#\"FMTx32);\n}\nTEST_END\n\nTEST_STRUCT(p, void *)\nTEST_BEGIN(test_atomic_p)\n{\n\n\tTEST_BODY(p, void *, uintptr_t, ptr, \"p\");\n}\nTEST_END\n\nTEST_STRUCT(z, size_t)\nTEST_BEGIN(test_atomic_z)\n{\n\n\tTEST_BODY(z, size_t, size_t, zu, \"#zx\");\n}\nTEST_END\n\nTEST_STRUCT(u, unsigned)\nTEST_BEGIN(test_atomic_u)\n{\n\n\tTEST_BODY(u, unsigned, unsigned, u, \"#x\");\n}\nTEST_END\n\nint\nmain(void)\n{\n\n\treturn (test(\n\t    test_atomic_uint64,\n\t    test_atomic_uint32,\n\t    test_atomic_p,\n\t    test_atomic_z,\n\t    test_atomic_u));\n}\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/deps/jemalloc/test/unit/bitmap.c",
    "content": "#include \"test/jemalloc_test.h\"\n\nTEST_BEGIN(test_bitmap_size)\n{\n\tsize_t i, prev_size;\n\n\tprev_size = 0;\n\tfor (i = 1; i <= BITMAP_MAXBITS; i++) {\n\t\tbitmap_info_t binfo;\n\t\tsize_t size;\n\n\t\tbitmap_info_init(&binfo, i);\n\t\tsize = bitmap_size(&binfo);\n\t\tassert_true(size >= prev_size,\n\t\t    \"Bitmap size is smaller than expected\");\n\t\tprev_size = size;\n\t}\n}\nTEST_END\n\nTEST_BEGIN(test_bitmap_init)\n{\n\tsize_t i;\n\n\tfor (i = 1; i <= BITMAP_MAXBITS; i++) {\n\t\tbitmap_info_t binfo;\n\t\tbitmap_info_init(&binfo, i);\n\t\t{\n\t\t\tsize_t j;\n\t\t\tbitmap_t *bitmap = (bitmap_t *)malloc(\n\t\t\t    bitmap_size(&binfo));\n\t\t\tbitmap_init(bitmap, &binfo);\n\n\t\t\tfor (j = 0; j < i; j++) {\n\t\t\t\tassert_false(bitmap_get(bitmap, &binfo, j),\n\t\t\t\t    \"Bit should be unset\");\n\t\t\t}\n\t\t\tfree(bitmap);\n\t\t}\n\t}\n}\nTEST_END\n\nTEST_BEGIN(test_bitmap_set)\n{\n\tsize_t i;\n\n\tfor (i = 1; i <= BITMAP_MAXBITS; i++) {\n\t\tbitmap_info_t binfo;\n\t\tbitmap_info_init(&binfo, i);\n\t\t{\n\t\t\tsize_t j;\n\t\t\tbitmap_t *bitmap = (bitmap_t *)malloc(\n\t\t\t    bitmap_size(&binfo));\n\t\t\tbitmap_init(bitmap, &binfo);\n\n\t\t\tfor (j = 0; j < i; j++)\n\t\t\t\tbitmap_set(bitmap, &binfo, j);\n\t\t\tassert_true(bitmap_full(bitmap, &binfo),\n\t\t\t    \"All bits should be set\");\n\t\t\tfree(bitmap);\n\t\t}\n\t}\n}\nTEST_END\n\nTEST_BEGIN(test_bitmap_unset)\n{\n\tsize_t i;\n\n\tfor (i = 1; i <= BITMAP_MAXBITS; i++) {\n\t\tbitmap_info_t binfo;\n\t\tbitmap_info_init(&binfo, i);\n\t\t{\n\t\t\tsize_t j;\n\t\t\tbitmap_t *bitmap = (bitmap_t *)malloc(\n\t\t\t    bitmap_size(&binfo));\n\t\t\tbitmap_init(bitmap, &binfo);\n\n\t\t\tfor (j = 0; j < i; j++)\n\t\t\t\tbitmap_set(bitmap, &binfo, j);\n\t\t\tassert_true(bitmap_full(bitmap, &binfo),\n\t\t\t    \"All bits should be set\");\n\t\t\tfor (j = 0; j < i; j++)\n\t\t\t\tbitmap_unset(bitmap, &binfo, j);\n\t\t\tfor (j = 0; j < i; j++)\n\t\t\t\tbitmap_set(bitmap, &binfo, j);\n\t\t\tassert_true(bitmap_full(bitmap, &binfo),\n\t\t\t    \"All bits should be set\");\n\t\t\tfree(bitmap);\n\t\t}\n\t}\n}\nTEST_END\n\nTEST_BEGIN(test_bitmap_sfu)\n{\n\tsize_t i;\n\n\tfor (i = 1; i <= BITMAP_MAXBITS; i++) {\n\t\tbitmap_info_t binfo;\n\t\tbitmap_info_init(&binfo, i);\n\t\t{\n\t\t\tsize_t j;\n\t\t\tbitmap_t *bitmap = (bitmap_t *)malloc(\n\t\t\t    bitmap_size(&binfo));\n\t\t\tbitmap_init(bitmap, &binfo);\n\n\t\t\t/* Iteratively set bits starting at the beginning. */\n\t\t\tfor (j = 0; j < i; j++) {\n\t\t\t\tassert_zd_eq(bitmap_sfu(bitmap, &binfo), j,\n\t\t\t\t    \"First unset bit should be just after \"\n\t\t\t\t    \"previous first unset bit\");\n\t\t\t}\n\t\t\tassert_true(bitmap_full(bitmap, &binfo),\n\t\t\t    \"All bits should be set\");\n\n\t\t\t/*\n\t\t\t * Iteratively unset bits starting at the end, and\n\t\t\t * verify that bitmap_sfu() reaches the unset bits.\n\t\t\t */\n\t\t\tfor (j = i - 1; j < i; j--) { /* (i..0] */\n\t\t\t\tbitmap_unset(bitmap, &binfo, j);\n\t\t\t\tassert_zd_eq(bitmap_sfu(bitmap, &binfo), j,\n\t\t\t\t    \"First unset bit should the bit previously \"\n\t\t\t\t    \"unset\");\n\t\t\t\tbitmap_unset(bitmap, &binfo, j);\n\t\t\t}\n\t\t\tassert_false(bitmap_get(bitmap, &binfo, 0),\n\t\t\t    \"Bit should be unset\");\n\n\t\t\t/*\n\t\t\t * Iteratively set bits starting at the beginning, and\n\t\t\t * verify that bitmap_sfu() looks past them.\n\t\t\t */\n\t\t\tfor (j = 1; j < i; j++) {\n\t\t\t\tbitmap_set(bitmap, &binfo, j - 1);\n\t\t\t\tassert_zd_eq(bitmap_sfu(bitmap, &binfo), j,\n\t\t\t\t    \"First unset bit should be just after the \"\n\t\t\t\t    \"bit previously set\");\n\t\t\t\tbitmap_unset(bitmap, &binfo, j);\n\t\t\t}\n\t\t\tassert_zd_eq(bitmap_sfu(bitmap, &binfo), i - 1,\n\t\t\t    \"First unset bit should be the last bit\");\n\t\t\tassert_true(bitmap_full(bitmap, &binfo),\n\t\t\t    \"All bits should be set\");\n\t\t\tfree(bitmap);\n\t\t}\n\t}\n}\nTEST_END\n\nint\nmain(void)\n{\n\n\treturn (test(\n\t    test_bitmap_size,\n\t    test_bitmap_init,\n\t    test_bitmap_set,\n\t    test_bitmap_unset,\n\t    test_bitmap_sfu));\n}\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/deps/jemalloc/test/unit/ckh.c",
    "content": "#include \"test/jemalloc_test.h\"\n\nTEST_BEGIN(test_new_delete)\n{\n\ttsdn_t *tsdn;\n\tckh_t ckh;\n\n\ttsdn = tsdn_fetch();\n\n\tassert_false(ckh_new(tsdn, &ckh, 2, ckh_string_hash,\n\t    ckh_string_keycomp), \"Unexpected ckh_new() error\");\n\tckh_delete(tsdn, &ckh);\n\n\tassert_false(ckh_new(tsdn, &ckh, 3, ckh_pointer_hash,\n\t    ckh_pointer_keycomp), \"Unexpected ckh_new() error\");\n\tckh_delete(tsdn, &ckh);\n}\nTEST_END\n\nTEST_BEGIN(test_count_insert_search_remove)\n{\n\ttsdn_t *tsdn;\n\tckh_t ckh;\n\tconst char *strs[] = {\n\t    \"a string\",\n\t    \"A string\",\n\t    \"a string.\",\n\t    \"A string.\"\n\t};\n\tconst char *missing = \"A string not in the hash table.\";\n\tsize_t i;\n\n\ttsdn = tsdn_fetch();\n\n\tassert_false(ckh_new(tsdn, &ckh, 2, ckh_string_hash,\n\t    ckh_string_keycomp), \"Unexpected ckh_new() error\");\n\tassert_zu_eq(ckh_count(&ckh), 0,\n\t    \"ckh_count() should return %zu, but it returned %zu\", ZU(0),\n\t    ckh_count(&ckh));\n\n\t/* Insert. */\n\tfor (i = 0; i < sizeof(strs)/sizeof(const char *); i++) {\n\t\tckh_insert(tsdn, &ckh, strs[i], strs[i]);\n\t\tassert_zu_eq(ckh_count(&ckh), i+1,\n\t\t    \"ckh_count() should return %zu, but it returned %zu\", i+1,\n\t\t    ckh_count(&ckh));\n\t}\n\n\t/* Search. */\n\tfor (i = 0; i < sizeof(strs)/sizeof(const char *); i++) {\n\t\tunion {\n\t\t\tvoid *p;\n\t\t\tconst char *s;\n\t\t} k, v;\n\t\tvoid **kp, **vp;\n\t\tconst char *ks, *vs;\n\n\t\tkp = (i & 1) ? &k.p : NULL;\n\t\tvp = (i & 2) ? &v.p : NULL;\n\t\tk.p = NULL;\n\t\tv.p = NULL;\n\t\tassert_false(ckh_search(&ckh, strs[i], kp, vp),\n\t\t    \"Unexpected ckh_search() error\");\n\n\t\tks = (i & 1) ? strs[i] : (const char *)NULL;\n\t\tvs = (i & 2) ? strs[i] : (const char *)NULL;\n\t\tassert_ptr_eq((void *)ks, (void *)k.s, \"Key mismatch, i=%zu\",\n\t\t    i);\n\t\tassert_ptr_eq((void *)vs, (void *)v.s, \"Value mismatch, i=%zu\",\n\t\t    i);\n\t}\n\tassert_true(ckh_search(&ckh, missing, NULL, NULL),\n\t    \"Unexpected ckh_search() success\");\n\n\t/* Remove. */\n\tfor (i = 0; i < sizeof(strs)/sizeof(const char *); i++) {\n\t\tunion {\n\t\t\tvoid *p;\n\t\t\tconst char *s;\n\t\t} k, v;\n\t\tvoid **kp, **vp;\n\t\tconst char *ks, *vs;\n\n\t\tkp = (i & 1) ? &k.p : NULL;\n\t\tvp = (i & 2) ? &v.p : NULL;\n\t\tk.p = NULL;\n\t\tv.p = NULL;\n\t\tassert_false(ckh_remove(tsdn, &ckh, strs[i], kp, vp),\n\t\t    \"Unexpected ckh_remove() error\");\n\n\t\tks = (i & 1) ? strs[i] : (const char *)NULL;\n\t\tvs = (i & 2) ? strs[i] : (const char *)NULL;\n\t\tassert_ptr_eq((void *)ks, (void *)k.s, \"Key mismatch, i=%zu\",\n\t\t    i);\n\t\tassert_ptr_eq((void *)vs, (void *)v.s, \"Value mismatch, i=%zu\",\n\t\t    i);\n\t\tassert_zu_eq(ckh_count(&ckh),\n\t\t    sizeof(strs)/sizeof(const char *) - i - 1,\n\t\t    \"ckh_count() should return %zu, but it returned %zu\",\n\t\t        sizeof(strs)/sizeof(const char *) - i - 1,\n\t\t    ckh_count(&ckh));\n\t}\n\n\tckh_delete(tsdn, &ckh);\n}\nTEST_END\n\nTEST_BEGIN(test_insert_iter_remove)\n{\n#define\tNITEMS ZU(1000)\n\ttsdn_t *tsdn;\n\tckh_t ckh;\n\tvoid **p[NITEMS];\n\tvoid *q, *r;\n\tsize_t i;\n\n\ttsdn = tsdn_fetch();\n\n\tassert_false(ckh_new(tsdn, &ckh, 2, ckh_pointer_hash,\n\t    ckh_pointer_keycomp), \"Unexpected ckh_new() error\");\n\n\tfor (i = 0; i < NITEMS; i++) {\n\t\tp[i] = mallocx(i+1, 0);\n\t\tassert_ptr_not_null(p[i], \"Unexpected mallocx() failure\");\n\t}\n\n\tfor (i = 0; i < NITEMS; i++) {\n\t\tsize_t j;\n\n\t\tfor (j = i; j < NITEMS; j++) {\n\t\t\tassert_false(ckh_insert(tsdn, &ckh, p[j], p[j]),\n\t\t\t    \"Unexpected ckh_insert() failure\");\n\t\t\tassert_false(ckh_search(&ckh, p[j], &q, &r),\n\t\t\t    \"Unexpected ckh_search() failure\");\n\t\t\tassert_ptr_eq(p[j], q, \"Key pointer mismatch\");\n\t\t\tassert_ptr_eq(p[j], r, \"Value pointer mismatch\");\n\t\t}\n\n\t\tassert_zu_eq(ckh_count(&ckh), NITEMS,\n\t\t    \"ckh_count() should return %zu, but it returned %zu\",\n\t\t    NITEMS, ckh_count(&ckh));\n\n\t\tfor (j = i + 1; j < NITEMS; j++) {\n\t\t\tassert_false(ckh_search(&ckh, p[j], NULL, NULL),\n\t\t\t    \"Unexpected ckh_search() failure\");\n\t\t\tassert_false(ckh_remove(tsdn, &ckh, p[j], &q, &r),\n\t\t\t    \"Unexpected ckh_remove() failure\");\n\t\t\tassert_ptr_eq(p[j], q, \"Key pointer mismatch\");\n\t\t\tassert_ptr_eq(p[j], r, \"Value pointer mismatch\");\n\t\t\tassert_true(ckh_search(&ckh, p[j], NULL, NULL),\n\t\t\t    \"Unexpected ckh_search() success\");\n\t\t\tassert_true(ckh_remove(tsdn, &ckh, p[j], &q, &r),\n\t\t\t    \"Unexpected ckh_remove() success\");\n\t\t}\n\n\t\t{\n\t\t\tbool seen[NITEMS];\n\t\t\tsize_t tabind;\n\n\t\t\tmemset(seen, 0, sizeof(seen));\n\n\t\t\tfor (tabind = 0; !ckh_iter(&ckh, &tabind, &q, &r);) {\n\t\t\t\tsize_t k;\n\n\t\t\t\tassert_ptr_eq(q, r, \"Key and val not equal\");\n\n\t\t\t\tfor (k = 0; k < NITEMS; k++) {\n\t\t\t\t\tif (p[k] == q) {\n\t\t\t\t\t\tassert_false(seen[k],\n\t\t\t\t\t\t    \"Item %zu already seen\", k);\n\t\t\t\t\t\tseen[k] = true;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tfor (j = 0; j < i + 1; j++)\n\t\t\t\tassert_true(seen[j], \"Item %zu not seen\", j);\n\t\t\tfor (; j < NITEMS; j++)\n\t\t\t\tassert_false(seen[j], \"Item %zu seen\", j);\n\t\t}\n\t}\n\n\tfor (i = 0; i < NITEMS; i++) {\n\t\tassert_false(ckh_search(&ckh, p[i], NULL, NULL),\n\t\t    \"Unexpected ckh_search() failure\");\n\t\tassert_false(ckh_remove(tsdn, &ckh, p[i], &q, &r),\n\t\t    \"Unexpected ckh_remove() failure\");\n\t\tassert_ptr_eq(p[i], q, \"Key pointer mismatch\");\n\t\tassert_ptr_eq(p[i], r, \"Value pointer mismatch\");\n\t\tassert_true(ckh_search(&ckh, p[i], NULL, NULL),\n\t\t    \"Unexpected ckh_search() success\");\n\t\tassert_true(ckh_remove(tsdn, &ckh, p[i], &q, &r),\n\t\t    \"Unexpected ckh_remove() success\");\n\t\tdallocx(p[i], 0);\n\t}\n\n\tassert_zu_eq(ckh_count(&ckh), 0,\n\t    \"ckh_count() should return %zu, but it returned %zu\",\n\t    ZU(0), ckh_count(&ckh));\n\tckh_delete(tsdn, &ckh);\n#undef NITEMS\n}\nTEST_END\n\nint\nmain(void)\n{\n\n\treturn (test(\n\t    test_new_delete,\n\t    test_count_insert_search_remove,\n\t    test_insert_iter_remove));\n}\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/deps/jemalloc/test/unit/decay.c",
    "content": "#include \"test/jemalloc_test.h\"\n\nconst char *malloc_conf = \"purge:decay,decay_time:1\";\n\nstatic nstime_update_t *nstime_update_orig;\n\nstatic unsigned nupdates_mock;\nstatic nstime_t time_mock;\nstatic bool nonmonotonic_mock;\n\nstatic bool\nnstime_update_mock(nstime_t *time)\n{\n\n\tnupdates_mock++;\n\tif (!nonmonotonic_mock)\n\t\tnstime_copy(time, &time_mock);\n\treturn (nonmonotonic_mock);\n}\n\nTEST_BEGIN(test_decay_ticks)\n{\n\tticker_t *decay_ticker;\n\tunsigned tick0, tick1;\n\tsize_t sz, huge0, large0;\n\tvoid *p;\n\n\ttest_skip_if(opt_purge != purge_mode_decay);\n\n\tdecay_ticker = decay_ticker_get(tsd_fetch(), 0);\n\tassert_ptr_not_null(decay_ticker,\n\t    \"Unexpected failure getting decay ticker\");\n\n\tsz = sizeof(size_t);\n\tassert_d_eq(mallctl(\"arenas.hchunk.0.size\", &huge0, &sz, NULL, 0), 0,\n\t    \"Unexpected mallctl failure\");\n\tassert_d_eq(mallctl(\"arenas.lrun.0.size\", &large0, &sz, NULL, 0), 0,\n\t    \"Unexpected mallctl failure\");\n\n\t/*\n\t * Test the standard APIs using a huge size class, since we can't\n\t * control tcache interactions (except by completely disabling tcache\n\t * for the entire test program).\n\t */\n\n\t/* malloc(). */\n\ttick0 = ticker_read(decay_ticker);\n\tp = malloc(huge0);\n\tassert_ptr_not_null(p, \"Unexpected malloc() failure\");\n\ttick1 = ticker_read(decay_ticker);\n\tassert_u32_ne(tick1, tick0, \"Expected ticker to tick during malloc()\");\n\t/* free(). */\n\ttick0 = ticker_read(decay_ticker);\n\tfree(p);\n\ttick1 = ticker_read(decay_ticker);\n\tassert_u32_ne(tick1, tick0, \"Expected ticker to tick during free()\");\n\n\t/* calloc(). */\n\ttick0 = ticker_read(decay_ticker);\n\tp = calloc(1, huge0);\n\tassert_ptr_not_null(p, \"Unexpected calloc() failure\");\n\ttick1 = ticker_read(decay_ticker);\n\tassert_u32_ne(tick1, tick0, \"Expected ticker to tick during calloc()\");\n\tfree(p);\n\n\t/* posix_memalign(). */\n\ttick0 = ticker_read(decay_ticker);\n\tassert_d_eq(posix_memalign(&p, sizeof(size_t), huge0), 0,\n\t    \"Unexpected posix_memalign() failure\");\n\ttick1 = ticker_read(decay_ticker);\n\tassert_u32_ne(tick1, tick0,\n\t    \"Expected ticker to tick during posix_memalign()\");\n\tfree(p);\n\n\t/* aligned_alloc(). */\n\ttick0 = ticker_read(decay_ticker);\n\tp = aligned_alloc(sizeof(size_t), huge0);\n\tassert_ptr_not_null(p, \"Unexpected aligned_alloc() failure\");\n\ttick1 = ticker_read(decay_ticker);\n\tassert_u32_ne(tick1, tick0,\n\t    \"Expected ticker to tick during aligned_alloc()\");\n\tfree(p);\n\n\t/* realloc(). */\n\t/* Allocate. */\n\ttick0 = ticker_read(decay_ticker);\n\tp = realloc(NULL, huge0);\n\tassert_ptr_not_null(p, \"Unexpected realloc() failure\");\n\ttick1 = ticker_read(decay_ticker);\n\tassert_u32_ne(tick1, tick0, \"Expected ticker to tick during realloc()\");\n\t/* Reallocate. */\n\ttick0 = ticker_read(decay_ticker);\n\tp = realloc(p, huge0);\n\tassert_ptr_not_null(p, \"Unexpected realloc() failure\");\n\ttick1 = ticker_read(decay_ticker);\n\tassert_u32_ne(tick1, tick0, \"Expected ticker to tick during realloc()\");\n\t/* Deallocate. */\n\ttick0 = ticker_read(decay_ticker);\n\trealloc(p, 0);\n\ttick1 = ticker_read(decay_ticker);\n\tassert_u32_ne(tick1, tick0, \"Expected ticker to tick during realloc()\");\n\n\t/*\n\t * Test the *allocx() APIs using huge, large, and small size classes,\n\t * with tcache explicitly disabled.\n\t */\n\t{\n\t\tunsigned i;\n\t\tsize_t allocx_sizes[3];\n\t\tallocx_sizes[0] = huge0;\n\t\tallocx_sizes[1] = large0;\n\t\tallocx_sizes[2] = 1;\n\n\t\tfor (i = 0; i < sizeof(allocx_sizes) / sizeof(size_t); i++) {\n\t\t\tsz = allocx_sizes[i];\n\n\t\t\t/* mallocx(). */\n\t\t\ttick0 = ticker_read(decay_ticker);\n\t\t\tp = mallocx(sz, MALLOCX_TCACHE_NONE);\n\t\t\tassert_ptr_not_null(p, \"Unexpected mallocx() failure\");\n\t\t\ttick1 = ticker_read(decay_ticker);\n\t\t\tassert_u32_ne(tick1, tick0,\n\t\t\t    \"Expected ticker to tick during mallocx() (sz=%zu)\",\n\t\t\t    sz);\n\t\t\t/* rallocx(). */\n\t\t\ttick0 = ticker_read(decay_ticker);\n\t\t\tp = rallocx(p, sz, MALLOCX_TCACHE_NONE);\n\t\t\tassert_ptr_not_null(p, \"Unexpected rallocx() failure\");\n\t\t\ttick1 = ticker_read(decay_ticker);\n\t\t\tassert_u32_ne(tick1, tick0,\n\t\t\t    \"Expected ticker to tick during rallocx() (sz=%zu)\",\n\t\t\t    sz);\n\t\t\t/* xallocx(). */\n\t\t\ttick0 = ticker_read(decay_ticker);\n\t\t\txallocx(p, sz, 0, MALLOCX_TCACHE_NONE);\n\t\t\ttick1 = ticker_read(decay_ticker);\n\t\t\tassert_u32_ne(tick1, tick0,\n\t\t\t    \"Expected ticker to tick during xallocx() (sz=%zu)\",\n\t\t\t    sz);\n\t\t\t/* dallocx(). */\n\t\t\ttick0 = ticker_read(decay_ticker);\n\t\t\tdallocx(p, MALLOCX_TCACHE_NONE);\n\t\t\ttick1 = ticker_read(decay_ticker);\n\t\t\tassert_u32_ne(tick1, tick0,\n\t\t\t    \"Expected ticker to tick during dallocx() (sz=%zu)\",\n\t\t\t    sz);\n\t\t\t/* sdallocx(). */\n\t\t\tp = mallocx(sz, MALLOCX_TCACHE_NONE);\n\t\t\tassert_ptr_not_null(p, \"Unexpected mallocx() failure\");\n\t\t\ttick0 = ticker_read(decay_ticker);\n\t\t\tsdallocx(p, sz, MALLOCX_TCACHE_NONE);\n\t\t\ttick1 = ticker_read(decay_ticker);\n\t\t\tassert_u32_ne(tick1, tick0,\n\t\t\t    \"Expected ticker to tick during sdallocx() \"\n\t\t\t    \"(sz=%zu)\", sz);\n\t\t}\n\t}\n\n\t/*\n\t * Test tcache fill/flush interactions for large and small size classes,\n\t * using an explicit tcache.\n\t */\n\tif (config_tcache) {\n\t\tunsigned tcache_ind, i;\n\t\tsize_t tcache_sizes[2];\n\t\ttcache_sizes[0] = large0;\n\t\ttcache_sizes[1] = 1;\n\n\t\tsz = sizeof(unsigned);\n\t\tassert_d_eq(mallctl(\"tcache.create\", &tcache_ind, &sz, NULL, 0),\n\t\t    0, \"Unexpected mallctl failure\");\n\n\t\tfor (i = 0; i < sizeof(tcache_sizes) / sizeof(size_t); i++) {\n\t\t\tsz = tcache_sizes[i];\n\n\t\t\t/* tcache fill. */\n\t\t\ttick0 = ticker_read(decay_ticker);\n\t\t\tp = mallocx(sz, MALLOCX_TCACHE(tcache_ind));\n\t\t\tassert_ptr_not_null(p, \"Unexpected mallocx() failure\");\n\t\t\ttick1 = ticker_read(decay_ticker);\n\t\t\tassert_u32_ne(tick1, tick0,\n\t\t\t    \"Expected ticker to tick during tcache fill \"\n\t\t\t    \"(sz=%zu)\", sz);\n\t\t\t/* tcache flush. */\n\t\t\tdallocx(p, MALLOCX_TCACHE(tcache_ind));\n\t\t\ttick0 = ticker_read(decay_ticker);\n\t\t\tassert_d_eq(mallctl(\"tcache.flush\", NULL, NULL,\n\t\t\t    &tcache_ind, sizeof(unsigned)), 0,\n\t\t\t    \"Unexpected mallctl failure\");\n\t\t\ttick1 = ticker_read(decay_ticker);\n\t\t\tassert_u32_ne(tick1, tick0,\n\t\t\t    \"Expected ticker to tick during tcache flush \"\n\t\t\t    \"(sz=%zu)\", sz);\n\t\t}\n\t}\n}\nTEST_END\n\nTEST_BEGIN(test_decay_ticker)\n{\n#define\tNPS 1024\n\tint flags = (MALLOCX_ARENA(0) | MALLOCX_TCACHE_NONE);\n\tvoid *ps[NPS];\n\tuint64_t epoch;\n\tuint64_t npurge0 = 0;\n\tuint64_t npurge1 = 0;\n\tsize_t sz, large;\n\tunsigned i, nupdates0;\n\tnstime_t time, decay_time, deadline;\n\n\ttest_skip_if(opt_purge != purge_mode_decay);\n\n\t/*\n\t * Allocate a bunch of large objects, pause the clock, deallocate the\n\t * objects, restore the clock, then [md]allocx() in a tight loop to\n\t * verify the ticker triggers purging.\n\t */\n\n\tif (config_tcache) {\n\t\tsize_t tcache_max;\n\n\t\tsz = sizeof(size_t);\n\t\tassert_d_eq(mallctl(\"arenas.tcache_max\", &tcache_max, &sz, NULL,\n\t\t    0), 0, \"Unexpected mallctl failure\");\n\t\tlarge = nallocx(tcache_max + 1, flags);\n\t}  else {\n\t\tsz = sizeof(size_t);\n\t\tassert_d_eq(mallctl(\"arenas.lrun.0.size\", &large, &sz, NULL, 0),\n\t\t    0, \"Unexpected mallctl failure\");\n\t}\n\n\tassert_d_eq(mallctl(\"arena.0.purge\", NULL, NULL, NULL, 0), 0,\n\t    \"Unexpected mallctl failure\");\n\tassert_d_eq(mallctl(\"epoch\", NULL, NULL, &epoch, sizeof(uint64_t)), 0,\n\t    \"Unexpected mallctl failure\");\n\tsz = sizeof(uint64_t);\n\tassert_d_eq(mallctl(\"stats.arenas.0.npurge\", &npurge0, &sz, NULL, 0),\n\t    config_stats ? 0 : ENOENT, \"Unexpected mallctl result\");\n\n\tfor (i = 0; i < NPS; i++) {\n\t\tps[i] = mallocx(large, flags);\n\t\tassert_ptr_not_null(ps[i], \"Unexpected mallocx() failure\");\n\t}\n\n\tnupdates_mock = 0;\n\tnstime_init(&time_mock, 0);\n\tnstime_update(&time_mock);\n\tnonmonotonic_mock = false;\n\n\tnstime_update_orig = nstime_update;\n\tnstime_update = nstime_update_mock;\n\n\tfor (i = 0; i < NPS; i++) {\n\t\tdallocx(ps[i], flags);\n\t\tnupdates0 = nupdates_mock;\n\t\tassert_d_eq(mallctl(\"arena.0.decay\", NULL, NULL, NULL, 0), 0,\n\t\t    \"Unexpected arena.0.decay failure\");\n\t\tassert_u_gt(nupdates_mock, nupdates0,\n\t\t    \"Expected nstime_update() to be called\");\n\t}\n\n\tnstime_update = nstime_update_orig;\n\n\tnstime_init(&time, 0);\n\tnstime_update(&time);\n\tnstime_init2(&decay_time, opt_decay_time, 0);\n\tnstime_copy(&deadline, &time);\n\tnstime_add(&deadline, &decay_time);\n\tdo {\n\t\tfor (i = 0; i < DECAY_NTICKS_PER_UPDATE / 2; i++) {\n\t\t\tvoid *p = mallocx(1, flags);\n\t\t\tassert_ptr_not_null(p, \"Unexpected mallocx() failure\");\n\t\t\tdallocx(p, flags);\n\t\t}\n\t\tassert_d_eq(mallctl(\"epoch\", NULL, NULL, &epoch,\n\t\t    sizeof(uint64_t)), 0, \"Unexpected mallctl failure\");\n\t\tsz = sizeof(uint64_t);\n\t\tassert_d_eq(mallctl(\"stats.arenas.0.npurge\", &npurge1, &sz,\n\t\t    NULL, 0), config_stats ? 0 : ENOENT,\n\t\t    \"Unexpected mallctl result\");\n\n\t\tnstime_update(&time);\n\t} while (nstime_compare(&time, &deadline) <= 0 && npurge1 == npurge0);\n\n\tif (config_stats)\n\t\tassert_u64_gt(npurge1, npurge0, \"Expected purging to occur\");\n#undef NPS\n}\nTEST_END\n\nTEST_BEGIN(test_decay_nonmonotonic)\n{\n#define\tNPS (SMOOTHSTEP_NSTEPS + 1)\n\tint flags = (MALLOCX_ARENA(0) | MALLOCX_TCACHE_NONE);\n\tvoid *ps[NPS];\n\tuint64_t epoch;\n\tuint64_t npurge0 = 0;\n\tuint64_t npurge1 = 0;\n\tsize_t sz, large0;\n\tunsigned i, nupdates0;\n\n\ttest_skip_if(opt_purge != purge_mode_decay);\n\n\tsz = sizeof(size_t);\n\tassert_d_eq(mallctl(\"arenas.lrun.0.size\", &large0, &sz, NULL, 0), 0,\n\t    \"Unexpected mallctl failure\");\n\n\tassert_d_eq(mallctl(\"arena.0.purge\", NULL, NULL, NULL, 0), 0,\n\t    \"Unexpected mallctl failure\");\n\tassert_d_eq(mallctl(\"epoch\", NULL, NULL, &epoch, sizeof(uint64_t)), 0,\n\t    \"Unexpected mallctl failure\");\n\tsz = sizeof(uint64_t);\n\tassert_d_eq(mallctl(\"stats.arenas.0.npurge\", &npurge0, &sz, NULL, 0),\n\t    config_stats ? 0 : ENOENT, \"Unexpected mallctl result\");\n\n\tnupdates_mock = 0;\n\tnstime_init(&time_mock, 0);\n\tnstime_update(&time_mock);\n\tnonmonotonic_mock = true;\n\n\tnstime_update_orig = nstime_update;\n\tnstime_update = nstime_update_mock;\n\n\tfor (i = 0; i < NPS; i++) {\n\t\tps[i] = mallocx(large0, flags);\n\t\tassert_ptr_not_null(ps[i], \"Unexpected mallocx() failure\");\n\t}\n\n\tfor (i = 0; i < NPS; i++) {\n\t\tdallocx(ps[i], flags);\n\t\tnupdates0 = nupdates_mock;\n\t\tassert_d_eq(mallctl(\"arena.0.decay\", NULL, NULL, NULL, 0), 0,\n\t\t    \"Unexpected arena.0.decay failure\");\n\t\tassert_u_gt(nupdates_mock, nupdates0,\n\t\t    \"Expected nstime_update() to be called\");\n\t}\n\n\tassert_d_eq(mallctl(\"epoch\", NULL, NULL, &epoch, sizeof(uint64_t)), 0,\n\t    \"Unexpected mallctl failure\");\n\tsz = sizeof(uint64_t);\n\tassert_d_eq(mallctl(\"stats.arenas.0.npurge\", &npurge1, &sz, NULL, 0),\n\t    config_stats ? 0 : ENOENT, \"Unexpected mallctl result\");\n\n\tif (config_stats)\n\t\tassert_u64_gt(npurge1, npurge0, \"Expected purging to occur\");\n\n\tnstime_update = nstime_update_orig;\n#undef NPS\n}\nTEST_END\n\nint\nmain(void)\n{\n\n\treturn (test(\n\t    test_decay_ticks,\n\t    test_decay_ticker,\n\t    test_decay_nonmonotonic));\n}\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/deps/jemalloc/test/unit/fork.c",
    "content": "#include \"test/jemalloc_test.h\"\n\n#ifndef _WIN32\n#include <sys/wait.h>\n#endif\n\nTEST_BEGIN(test_fork)\n{\n#ifndef _WIN32\n\tvoid *p;\n\tpid_t pid;\n\n\tp = malloc(1);\n\tassert_ptr_not_null(p, \"Unexpected malloc() failure\");\n\n\tpid = fork();\n\n\tfree(p);\n\n\tp = malloc(64);\n\tassert_ptr_not_null(p, \"Unexpected malloc() failure\");\n\tfree(p);\n\n\tif (pid == -1) {\n\t\t/* Error. */\n\t\ttest_fail(\"Unexpected fork() failure\");\n\t} else if (pid == 0) {\n\t\t/* Child. */\n\t\texit(0);\n\t} else {\n\t\tint status;\n\n\t\t/* Parent. */\n\t\twhile (true) {\n\t\t\tif (waitpid(pid, &status, 0) == -1)\n\t\t\t\ttest_fail(\"Unexpected waitpid() failure\");\n\t\t\tif (WIFSIGNALED(status)) {\n\t\t\t\ttest_fail(\"Unexpected child termination due to \"\n\t\t\t\t    \"signal %d\", WTERMSIG(status));\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tif (WIFEXITED(status)) {\n\t\t\t\tif (WEXITSTATUS(status) != 0) {\n\t\t\t\t\ttest_fail(\n\t\t\t\t\t    \"Unexpected child exit value %d\",\n\t\t\t\t\t    WEXITSTATUS(status));\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t}\n#else\n\ttest_skip(\"fork(2) is irrelevant to Windows\");\n#endif\n}\nTEST_END\n\nint\nmain(void)\n{\n\n\treturn (test(\n\t    test_fork));\n}\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/deps/jemalloc/test/unit/hash.c",
    "content": "/*\n * This file is based on code that is part of SMHasher\n * (https://code.google.com/p/smhasher/), and is subject to the MIT license\n * (http://www.opensource.org/licenses/mit-license.php).  Both email addresses\n * associated with the source code's revision history belong to Austin Appleby,\n * and the revision history ranges from 2010 to 2012.  Therefore the copyright\n * and license are here taken to be:\n *\n * Copyright (c) 2010-2012 Austin Appleby\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n\n#include \"test/jemalloc_test.h\"\n\ntypedef enum {\n\thash_variant_x86_32,\n\thash_variant_x86_128,\n\thash_variant_x64_128\n} hash_variant_t;\n\nstatic int\nhash_variant_bits(hash_variant_t variant)\n{\n\n\tswitch (variant) {\n\tcase hash_variant_x86_32: return (32);\n\tcase hash_variant_x86_128: return (128);\n\tcase hash_variant_x64_128: return (128);\n\tdefault: not_reached();\n\t}\n}\n\nstatic const char *\nhash_variant_string(hash_variant_t variant)\n{\n\n\tswitch (variant) {\n\tcase hash_variant_x86_32: return (\"hash_x86_32\");\n\tcase hash_variant_x86_128: return (\"hash_x86_128\");\n\tcase hash_variant_x64_128: return (\"hash_x64_128\");\n\tdefault: not_reached();\n\t}\n}\n\n#define\tKEY_SIZE\t256\nstatic void\nhash_variant_verify_key(hash_variant_t variant, uint8_t *key)\n{\n\tconst int hashbytes = hash_variant_bits(variant) / 8;\n\tconst int hashes_size = hashbytes * 256;\n\tVARIABLE_ARRAY(uint8_t, hashes, hashes_size);\n\tVARIABLE_ARRAY(uint8_t, final, hashbytes);\n\tunsigned i;\n\tuint32_t computed, expected;\n\n\tmemset(key, 0, KEY_SIZE);\n\tmemset(hashes, 0, hashes_size);\n\tmemset(final, 0, hashbytes);\n\n\t/*\n\t * Hash keys of the form {0}, {0,1}, {0,1,2}, ..., {0,1,...,255} as the\n\t * seed.\n\t */\n\tfor (i = 0; i < 256; i++) {\n\t\tkey[i] = (uint8_t)i;\n\t\tswitch (variant) {\n\t\tcase hash_variant_x86_32: {\n\t\t\tuint32_t out;\n\t\t\tout = hash_x86_32(key, i, 256-i);\n\t\t\tmemcpy(&hashes[i*hashbytes], &out, hashbytes);\n\t\t\tbreak;\n\t\t} case hash_variant_x86_128: {\n\t\t\tuint64_t out[2];\n\t\t\thash_x86_128(key, i, 256-i, out);\n\t\t\tmemcpy(&hashes[i*hashbytes], out, hashbytes);\n\t\t\tbreak;\n\t\t} case hash_variant_x64_128: {\n\t\t\tuint64_t out[2];\n\t\t\thash_x64_128(key, i, 256-i, out);\n\t\t\tmemcpy(&hashes[i*hashbytes], out, hashbytes);\n\t\t\tbreak;\n\t\t} default: not_reached();\n\t\t}\n\t}\n\n\t/* Hash the result array. */\n\tswitch (variant) {\n\tcase hash_variant_x86_32: {\n\t\tuint32_t out = hash_x86_32(hashes, hashes_size, 0);\n\t\tmemcpy(final, &out, sizeof(out));\n\t\tbreak;\n\t} case hash_variant_x86_128: {\n\t\tuint64_t out[2];\n\t\thash_x86_128(hashes, hashes_size, 0, out);\n\t\tmemcpy(final, out, sizeof(out));\n\t\tbreak;\n\t} case hash_variant_x64_128: {\n\t\tuint64_t out[2];\n\t\thash_x64_128(hashes, hashes_size, 0, out);\n\t\tmemcpy(final, out, sizeof(out));\n\t\tbreak;\n\t} default: not_reached();\n\t}\n\n\tcomputed = (final[0] << 0) | (final[1] << 8) | (final[2] << 16) |\n\t    (final[3] << 24);\n\n\tswitch (variant) {\n#ifdef JEMALLOC_BIG_ENDIAN\n\tcase hash_variant_x86_32: expected = 0x6213303eU; break;\n\tcase hash_variant_x86_128: expected = 0x266820caU; break;\n\tcase hash_variant_x64_128: expected = 0xcc622b6fU; break;\n#else\n\tcase hash_variant_x86_32: expected = 0xb0f57ee3U; break;\n\tcase hash_variant_x86_128: expected = 0xb3ece62aU; break;\n\tcase hash_variant_x64_128: expected = 0x6384ba69U; break;\n#endif\n\tdefault: not_reached();\n\t}\n\n\tassert_u32_eq(computed, expected,\n\t    \"Hash mismatch for %s(): expected %#x but got %#x\",\n\t    hash_variant_string(variant), expected, computed);\n}\n\nstatic void\nhash_variant_verify(hash_variant_t variant)\n{\n#define\tMAX_ALIGN\t16\n\tuint8_t key[KEY_SIZE + (MAX_ALIGN - 1)];\n\tunsigned i;\n\n\tfor (i = 0; i < MAX_ALIGN; i++)\n\t\thash_variant_verify_key(variant, &key[i]);\n#undef MAX_ALIGN\n}\n#undef KEY_SIZE\n\nTEST_BEGIN(test_hash_x86_32)\n{\n\n\thash_variant_verify(hash_variant_x86_32);\n}\nTEST_END\n\nTEST_BEGIN(test_hash_x86_128)\n{\n\n\thash_variant_verify(hash_variant_x86_128);\n}\nTEST_END\n\nTEST_BEGIN(test_hash_x64_128)\n{\n\n\thash_variant_verify(hash_variant_x64_128);\n}\nTEST_END\n\nint\nmain(void)\n{\n\n\treturn (test(\n\t    test_hash_x86_32,\n\t    test_hash_x86_128,\n\t    test_hash_x64_128));\n}\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/deps/jemalloc/test/unit/junk.c",
    "content": "#include \"test/jemalloc_test.h\"\n\n#ifdef JEMALLOC_FILL\n#  ifndef JEMALLOC_TEST_JUNK_OPT\n#    define JEMALLOC_TEST_JUNK_OPT \"junk:true\"\n#  endif\nconst char *malloc_conf =\n    \"abort:false,zero:false,redzone:true,quarantine:0,\" JEMALLOC_TEST_JUNK_OPT;\n#endif\n\nstatic arena_dalloc_junk_small_t *arena_dalloc_junk_small_orig;\nstatic arena_dalloc_junk_large_t *arena_dalloc_junk_large_orig;\nstatic huge_dalloc_junk_t *huge_dalloc_junk_orig;\nstatic void *watch_for_junking;\nstatic bool saw_junking;\n\nstatic void\nwatch_junking(void *p)\n{\n\n\twatch_for_junking = p;\n\tsaw_junking = false;\n}\n\nstatic void\narena_dalloc_junk_small_intercept(void *ptr, arena_bin_info_t *bin_info)\n{\n\tsize_t i;\n\n\tarena_dalloc_junk_small_orig(ptr, bin_info);\n\tfor (i = 0; i < bin_info->reg_size; i++) {\n\t\tassert_u_eq(((uint8_t *)ptr)[i], JEMALLOC_FREE_JUNK,\n\t\t    \"Missing junk fill for byte %zu/%zu of deallocated region\",\n\t\t    i, bin_info->reg_size);\n\t}\n\tif (ptr == watch_for_junking)\n\t\tsaw_junking = true;\n}\n\nstatic void\narena_dalloc_junk_large_intercept(void *ptr, size_t usize)\n{\n\tsize_t i;\n\n\tarena_dalloc_junk_large_orig(ptr, usize);\n\tfor (i = 0; i < usize; i++) {\n\t\tassert_u_eq(((uint8_t *)ptr)[i], JEMALLOC_FREE_JUNK,\n\t\t    \"Missing junk fill for byte %zu/%zu of deallocated region\",\n\t\t    i, usize);\n\t}\n\tif (ptr == watch_for_junking)\n\t\tsaw_junking = true;\n}\n\nstatic void\nhuge_dalloc_junk_intercept(tsdn_t *tsdn, void *ptr, size_t usize)\n{\n\n\thuge_dalloc_junk_orig(tsdn, ptr, usize);\n\t/*\n\t * The conditions under which junk filling actually occurs are nuanced\n\t * enough that it doesn't make sense to duplicate the decision logic in\n\t * test code, so don't actually check that the region is junk-filled.\n\t */\n\tif (ptr == watch_for_junking)\n\t\tsaw_junking = true;\n}\n\nstatic void\ntest_junk(size_t sz_min, size_t sz_max)\n{\n\tuint8_t *s;\n\tsize_t sz_prev, sz, i;\n\n\tif (opt_junk_free) {\n\t\tarena_dalloc_junk_small_orig = arena_dalloc_junk_small;\n\t\tarena_dalloc_junk_small = arena_dalloc_junk_small_intercept;\n\t\tarena_dalloc_junk_large_orig = arena_dalloc_junk_large;\n\t\tarena_dalloc_junk_large = arena_dalloc_junk_large_intercept;\n\t\thuge_dalloc_junk_orig = huge_dalloc_junk;\n\t\thuge_dalloc_junk = huge_dalloc_junk_intercept;\n\t}\n\n\tsz_prev = 0;\n\ts = (uint8_t *)mallocx(sz_min, 0);\n\tassert_ptr_not_null((void *)s, \"Unexpected mallocx() failure\");\n\n\tfor (sz = sallocx(s, 0); sz <= sz_max;\n\t    sz_prev = sz, sz = sallocx(s, 0)) {\n\t\tif (sz_prev > 0) {\n\t\t\tassert_u_eq(s[0], 'a',\n\t\t\t    \"Previously allocated byte %zu/%zu is corrupted\",\n\t\t\t    ZU(0), sz_prev);\n\t\t\tassert_u_eq(s[sz_prev-1], 'a',\n\t\t\t    \"Previously allocated byte %zu/%zu is corrupted\",\n\t\t\t    sz_prev-1, sz_prev);\n\t\t}\n\n\t\tfor (i = sz_prev; i < sz; i++) {\n\t\t\tif (opt_junk_alloc) {\n\t\t\t\tassert_u_eq(s[i], JEMALLOC_ALLOC_JUNK,\n\t\t\t\t    \"Newly allocated byte %zu/%zu isn't \"\n\t\t\t\t    \"junk-filled\", i, sz);\n\t\t\t}\n\t\t\ts[i] = 'a';\n\t\t}\n\n\t\tif (xallocx(s, sz+1, 0, 0) == sz) {\n\t\t\twatch_junking(s);\n\t\t\ts = (uint8_t *)rallocx(s, sz+1, 0);\n\t\t\tassert_ptr_not_null((void *)s,\n\t\t\t    \"Unexpected rallocx() failure\");\n\t\t\tassert_true(!opt_junk_free || saw_junking,\n\t\t\t    \"Expected region of size %zu to be junk-filled\",\n\t\t\t    sz);\n\t\t}\n\t}\n\n\twatch_junking(s);\n\tdallocx(s, 0);\n\tassert_true(!opt_junk_free || saw_junking,\n\t    \"Expected region of size %zu to be junk-filled\", sz);\n\n\tif (opt_junk_free) {\n\t\tarena_dalloc_junk_small = arena_dalloc_junk_small_orig;\n\t\tarena_dalloc_junk_large = arena_dalloc_junk_large_orig;\n\t\thuge_dalloc_junk = huge_dalloc_junk_orig;\n\t}\n}\n\nTEST_BEGIN(test_junk_small)\n{\n\n\ttest_skip_if(!config_fill);\n\ttest_junk(1, SMALL_MAXCLASS-1);\n}\nTEST_END\n\nTEST_BEGIN(test_junk_large)\n{\n\n\ttest_skip_if(!config_fill);\n\ttest_junk(SMALL_MAXCLASS+1, large_maxclass);\n}\nTEST_END\n\nTEST_BEGIN(test_junk_huge)\n{\n\n\ttest_skip_if(!config_fill);\n\ttest_junk(large_maxclass+1, chunksize*2);\n}\nTEST_END\n\narena_ralloc_junk_large_t *arena_ralloc_junk_large_orig;\nstatic void *most_recently_trimmed;\n\nstatic size_t\nshrink_size(size_t size)\n{\n\tsize_t shrink_size;\n\n\tfor (shrink_size = size - 1; nallocx(shrink_size, 0) == size;\n\t    shrink_size--)\n\t\t; /* Do nothing. */\n\n\treturn (shrink_size);\n}\n\nstatic void\narena_ralloc_junk_large_intercept(void *ptr, size_t old_usize, size_t usize)\n{\n\n\tarena_ralloc_junk_large_orig(ptr, old_usize, usize);\n\tassert_zu_eq(old_usize, large_maxclass, \"Unexpected old_usize\");\n\tassert_zu_eq(usize, shrink_size(large_maxclass), \"Unexpected usize\");\n\tmost_recently_trimmed = ptr;\n}\n\nTEST_BEGIN(test_junk_large_ralloc_shrink)\n{\n\tvoid *p1, *p2;\n\n\tp1 = mallocx(large_maxclass, 0);\n\tassert_ptr_not_null(p1, \"Unexpected mallocx() failure\");\n\n\tarena_ralloc_junk_large_orig = arena_ralloc_junk_large;\n\tarena_ralloc_junk_large = arena_ralloc_junk_large_intercept;\n\n\tp2 = rallocx(p1, shrink_size(large_maxclass), 0);\n\tassert_ptr_eq(p1, p2, \"Unexpected move during shrink\");\n\n\tarena_ralloc_junk_large = arena_ralloc_junk_large_orig;\n\n\tassert_ptr_eq(most_recently_trimmed, p1,\n\t    \"Expected trimmed portion of region to be junk-filled\");\n}\nTEST_END\n\nstatic bool detected_redzone_corruption;\n\nstatic void\narena_redzone_corruption_replacement(void *ptr, size_t usize, bool after,\n    size_t offset, uint8_t byte)\n{\n\n\tdetected_redzone_corruption = true;\n}\n\nTEST_BEGIN(test_junk_redzone)\n{\n\tchar *s;\n\tarena_redzone_corruption_t *arena_redzone_corruption_orig;\n\n\ttest_skip_if(!config_fill);\n\ttest_skip_if(!opt_junk_alloc || !opt_junk_free);\n\n\tarena_redzone_corruption_orig = arena_redzone_corruption;\n\tarena_redzone_corruption = arena_redzone_corruption_replacement;\n\n\t/* Test underflow. */\n\tdetected_redzone_corruption = false;\n\ts = (char *)mallocx(1, 0);\n\tassert_ptr_not_null((void *)s, \"Unexpected mallocx() failure\");\n\ts[-1] = 0xbb;\n\tdallocx(s, 0);\n\tassert_true(detected_redzone_corruption,\n\t    \"Did not detect redzone corruption\");\n\n\t/* Test overflow. */\n\tdetected_redzone_corruption = false;\n\ts = (char *)mallocx(1, 0);\n\tassert_ptr_not_null((void *)s, \"Unexpected mallocx() failure\");\n\ts[sallocx(s, 0)] = 0xbb;\n\tdallocx(s, 0);\n\tassert_true(detected_redzone_corruption,\n\t    \"Did not detect redzone corruption\");\n\n\tarena_redzone_corruption = arena_redzone_corruption_orig;\n}\nTEST_END\n\nint\nmain(void)\n{\n\n\treturn (test(\n\t    test_junk_small,\n\t    test_junk_large,\n\t    test_junk_huge,\n\t    test_junk_large_ralloc_shrink,\n\t    test_junk_redzone));\n}\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/deps/jemalloc/test/unit/junk_alloc.c",
    "content": "#define\tJEMALLOC_TEST_JUNK_OPT \"junk:alloc\"\n#include \"junk.c\"\n#undef JEMALLOC_TEST_JUNK_OPT\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/deps/jemalloc/test/unit/junk_free.c",
    "content": "#define\tJEMALLOC_TEST_JUNK_OPT \"junk:free\"\n#include \"junk.c\"\n#undef JEMALLOC_TEST_JUNK_OPT\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/deps/jemalloc/test/unit/lg_chunk.c",
    "content": "#include \"test/jemalloc_test.h\"\n\n/*\n * Make sure that opt.lg_chunk clamping is sufficient.  In practice, this test\n * program will fail a debug assertion during initialization and abort (rather\n * than the test soft-failing) if clamping is insufficient.\n */\nconst char *malloc_conf = \"lg_chunk:0\";\n\nTEST_BEGIN(test_lg_chunk_clamp)\n{\n\tvoid *p;\n\n\tp = mallocx(1, 0);\n\tassert_ptr_not_null(p, \"Unexpected mallocx() failure\");\n\tdallocx(p, 0);\n}\nTEST_END\n\nint\nmain(void)\n{\n\n\treturn (test(\n\t    test_lg_chunk_clamp));\n}\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/deps/jemalloc/test/unit/mallctl.c",
    "content": "#include \"test/jemalloc_test.h\"\n\nTEST_BEGIN(test_mallctl_errors)\n{\n\tuint64_t epoch;\n\tsize_t sz;\n\n\tassert_d_eq(mallctl(\"no_such_name\", NULL, NULL, NULL, 0), ENOENT,\n\t    \"mallctl() should return ENOENT for non-existent names\");\n\n\tassert_d_eq(mallctl(\"version\", NULL, NULL, \"0.0.0\", strlen(\"0.0.0\")),\n\t    EPERM, \"mallctl() should return EPERM on attempt to write \"\n\t    \"read-only value\");\n\n\tassert_d_eq(mallctl(\"epoch\", NULL, NULL, &epoch, sizeof(epoch)-1),\n\t    EINVAL, \"mallctl() should return EINVAL for input size mismatch\");\n\tassert_d_eq(mallctl(\"epoch\", NULL, NULL, &epoch, sizeof(epoch)+1),\n\t    EINVAL, \"mallctl() should return EINVAL for input size mismatch\");\n\n\tsz = sizeof(epoch)-1;\n\tassert_d_eq(mallctl(\"epoch\", &epoch, &sz, NULL, 0), EINVAL,\n\t    \"mallctl() should return EINVAL for output size mismatch\");\n\tsz = sizeof(epoch)+1;\n\tassert_d_eq(mallctl(\"epoch\", &epoch, &sz, NULL, 0), EINVAL,\n\t    \"mallctl() should return EINVAL for output size mismatch\");\n}\nTEST_END\n\nTEST_BEGIN(test_mallctlnametomib_errors)\n{\n\tsize_t mib[1];\n\tsize_t miblen;\n\n\tmiblen = sizeof(mib)/sizeof(size_t);\n\tassert_d_eq(mallctlnametomib(\"no_such_name\", mib, &miblen), ENOENT,\n\t    \"mallctlnametomib() should return ENOENT for non-existent names\");\n}\nTEST_END\n\nTEST_BEGIN(test_mallctlbymib_errors)\n{\n\tuint64_t epoch;\n\tsize_t sz;\n\tsize_t mib[1];\n\tsize_t miblen;\n\n\tmiblen = sizeof(mib)/sizeof(size_t);\n\tassert_d_eq(mallctlnametomib(\"version\", mib, &miblen), 0,\n\t    \"Unexpected mallctlnametomib() failure\");\n\n\tassert_d_eq(mallctlbymib(mib, miblen, NULL, NULL, \"0.0.0\",\n\t    strlen(\"0.0.0\")), EPERM, \"mallctl() should return EPERM on \"\n\t    \"attempt to write read-only value\");\n\n\tmiblen = sizeof(mib)/sizeof(size_t);\n\tassert_d_eq(mallctlnametomib(\"epoch\", mib, &miblen), 0,\n\t    \"Unexpected mallctlnametomib() failure\");\n\n\tassert_d_eq(mallctlbymib(mib, miblen, NULL, NULL, &epoch,\n\t    sizeof(epoch)-1), EINVAL,\n\t    \"mallctlbymib() should return EINVAL for input size mismatch\");\n\tassert_d_eq(mallctlbymib(mib, miblen, NULL, NULL, &epoch,\n\t    sizeof(epoch)+1), EINVAL,\n\t    \"mallctlbymib() should return EINVAL for input size mismatch\");\n\n\tsz = sizeof(epoch)-1;\n\tassert_d_eq(mallctlbymib(mib, miblen, &epoch, &sz, NULL, 0), EINVAL,\n\t    \"mallctlbymib() should return EINVAL for output size mismatch\");\n\tsz = sizeof(epoch)+1;\n\tassert_d_eq(mallctlbymib(mib, miblen, &epoch, &sz, NULL, 0), EINVAL,\n\t    \"mallctlbymib() should return EINVAL for output size mismatch\");\n}\nTEST_END\n\nTEST_BEGIN(test_mallctl_read_write)\n{\n\tuint64_t old_epoch, new_epoch;\n\tsize_t sz = sizeof(old_epoch);\n\n\t/* Blind. */\n\tassert_d_eq(mallctl(\"epoch\", NULL, NULL, NULL, 0), 0,\n\t    \"Unexpected mallctl() failure\");\n\tassert_zu_eq(sz, sizeof(old_epoch), \"Unexpected output size\");\n\n\t/* Read. */\n\tassert_d_eq(mallctl(\"epoch\", &old_epoch, &sz, NULL, 0), 0,\n\t    \"Unexpected mallctl() failure\");\n\tassert_zu_eq(sz, sizeof(old_epoch), \"Unexpected output size\");\n\n\t/* Write. */\n\tassert_d_eq(mallctl(\"epoch\", NULL, NULL, &new_epoch, sizeof(new_epoch)),\n\t    0, \"Unexpected mallctl() failure\");\n\tassert_zu_eq(sz, sizeof(old_epoch), \"Unexpected output size\");\n\n\t/* Read+write. */\n\tassert_d_eq(mallctl(\"epoch\", &old_epoch, &sz, &new_epoch,\n\t    sizeof(new_epoch)), 0, \"Unexpected mallctl() failure\");\n\tassert_zu_eq(sz, sizeof(old_epoch), \"Unexpected output size\");\n}\nTEST_END\n\nTEST_BEGIN(test_mallctlnametomib_short_mib)\n{\n\tsize_t mib[4];\n\tsize_t miblen;\n\n\tmiblen = 3;\n\tmib[3] = 42;\n\tassert_d_eq(mallctlnametomib(\"arenas.bin.0.nregs\", mib, &miblen), 0,\n\t    \"Unexpected mallctlnametomib() failure\");\n\tassert_zu_eq(miblen, 3, \"Unexpected mib output length\");\n\tassert_zu_eq(mib[3], 42,\n\t    \"mallctlnametomib() wrote past the end of the input mib\");\n}\nTEST_END\n\nTEST_BEGIN(test_mallctl_config)\n{\n\n#define\tTEST_MALLCTL_CONFIG(config, t) do {\t\t\t\t\\\n\tt oldval;\t\t\t\t\t\t\t\\\n\tsize_t sz = sizeof(oldval);\t\t\t\t\t\\\n\tassert_d_eq(mallctl(\"config.\"#config, &oldval, &sz, NULL, 0),\t\\\n\t    0, \"Unexpected mallctl() failure\");\t\t\t\t\\\n\tassert_b_eq(oldval, config_##config, \"Incorrect config value\");\t\\\n\tassert_zu_eq(sz, sizeof(oldval), \"Unexpected output size\");\t\\\n} while (0)\n\n\tTEST_MALLCTL_CONFIG(cache_oblivious, bool);\n\tTEST_MALLCTL_CONFIG(debug, bool);\n\tTEST_MALLCTL_CONFIG(fill, bool);\n\tTEST_MALLCTL_CONFIG(lazy_lock, bool);\n\tTEST_MALLCTL_CONFIG(malloc_conf, const char *);\n\tTEST_MALLCTL_CONFIG(munmap, bool);\n\tTEST_MALLCTL_CONFIG(prof, bool);\n\tTEST_MALLCTL_CONFIG(prof_libgcc, bool);\n\tTEST_MALLCTL_CONFIG(prof_libunwind, bool);\n\tTEST_MALLCTL_CONFIG(stats, bool);\n\tTEST_MALLCTL_CONFIG(tcache, bool);\n\tTEST_MALLCTL_CONFIG(tls, bool);\n\tTEST_MALLCTL_CONFIG(utrace, bool);\n\tTEST_MALLCTL_CONFIG(valgrind, bool);\n\tTEST_MALLCTL_CONFIG(xmalloc, bool);\n\n#undef TEST_MALLCTL_CONFIG\n}\nTEST_END\n\nTEST_BEGIN(test_mallctl_opt)\n{\n\tbool config_always = true;\n\n#define\tTEST_MALLCTL_OPT(t, opt, config) do {\t\t\t\t\\\n\tt oldval;\t\t\t\t\t\t\t\\\n\tsize_t sz = sizeof(oldval);\t\t\t\t\t\\\n\tint expected = config_##config ? 0 : ENOENT;\t\t\t\\\n\tint result = mallctl(\"opt.\"#opt, &oldval, &sz, NULL, 0);\t\\\n\tassert_d_eq(result, expected,\t\t\t\t\t\\\n\t    \"Unexpected mallctl() result for opt.\"#opt);\t\t\\\n\tassert_zu_eq(sz, sizeof(oldval), \"Unexpected output size\");\t\\\n} while (0)\n\n\tTEST_MALLCTL_OPT(bool, abort, always);\n\tTEST_MALLCTL_OPT(size_t, lg_chunk, always);\n\tTEST_MALLCTL_OPT(const char *, dss, always);\n\tTEST_MALLCTL_OPT(unsigned, narenas, always);\n\tTEST_MALLCTL_OPT(const char *, purge, always);\n\tTEST_MALLCTL_OPT(ssize_t, lg_dirty_mult, always);\n\tTEST_MALLCTL_OPT(ssize_t, decay_time, always);\n\tTEST_MALLCTL_OPT(bool, stats_print, always);\n\tTEST_MALLCTL_OPT(const char *, junk, fill);\n\tTEST_MALLCTL_OPT(size_t, quarantine, fill);\n\tTEST_MALLCTL_OPT(bool, redzone, fill);\n\tTEST_MALLCTL_OPT(bool, zero, fill);\n\tTEST_MALLCTL_OPT(bool, utrace, utrace);\n\tTEST_MALLCTL_OPT(bool, xmalloc, xmalloc);\n\tTEST_MALLCTL_OPT(bool, tcache, tcache);\n\tTEST_MALLCTL_OPT(size_t, lg_tcache_max, tcache);\n\tTEST_MALLCTL_OPT(bool, prof, prof);\n\tTEST_MALLCTL_OPT(const char *, prof_prefix, prof);\n\tTEST_MALLCTL_OPT(bool, prof_active, prof);\n\tTEST_MALLCTL_OPT(ssize_t, lg_prof_sample, prof);\n\tTEST_MALLCTL_OPT(bool, prof_accum, prof);\n\tTEST_MALLCTL_OPT(ssize_t, lg_prof_interval, prof);\n\tTEST_MALLCTL_OPT(bool, prof_gdump, prof);\n\tTEST_MALLCTL_OPT(bool, prof_final, prof);\n\tTEST_MALLCTL_OPT(bool, prof_leak, prof);\n\n#undef TEST_MALLCTL_OPT\n}\nTEST_END\n\nTEST_BEGIN(test_manpage_example)\n{\n\tunsigned nbins, i;\n\tsize_t mib[4];\n\tsize_t len, miblen;\n\n\tlen = sizeof(nbins);\n\tassert_d_eq(mallctl(\"arenas.nbins\", &nbins, &len, NULL, 0), 0,\n\t    \"Unexpected mallctl() failure\");\n\n\tmiblen = 4;\n\tassert_d_eq(mallctlnametomib(\"arenas.bin.0.size\", mib, &miblen), 0,\n\t    \"Unexpected mallctlnametomib() failure\");\n\tfor (i = 0; i < nbins; i++) {\n\t\tsize_t bin_size;\n\n\t\tmib[2] = i;\n\t\tlen = sizeof(bin_size);\n\t\tassert_d_eq(mallctlbymib(mib, miblen, &bin_size, &len, NULL, 0),\n\t\t    0, \"Unexpected mallctlbymib() failure\");\n\t\t/* Do something with bin_size... */\n\t}\n}\nTEST_END\n\nTEST_BEGIN(test_tcache_none)\n{\n\tvoid *p0, *q, *p1;\n\n\ttest_skip_if(!config_tcache);\n\n\t/* Allocate p and q. */\n\tp0 = mallocx(42, 0);\n\tassert_ptr_not_null(p0, \"Unexpected mallocx() failure\");\n\tq = mallocx(42, 0);\n\tassert_ptr_not_null(q, \"Unexpected mallocx() failure\");\n\n\t/* Deallocate p and q, but bypass the tcache for q. */\n\tdallocx(p0, 0);\n\tdallocx(q, MALLOCX_TCACHE_NONE);\n\n\t/* Make sure that tcache-based allocation returns p, not q. */\n\tp1 = mallocx(42, 0);\n\tassert_ptr_not_null(p1, \"Unexpected mallocx() failure\");\n\tassert_ptr_eq(p0, p1, \"Expected tcache to allocate cached region\");\n\n\t/* Clean up. */\n\tdallocx(p1, MALLOCX_TCACHE_NONE);\n}\nTEST_END\n\nTEST_BEGIN(test_tcache)\n{\n#define\tNTCACHES\t10\n\tunsigned tis[NTCACHES];\n\tvoid *ps[NTCACHES];\n\tvoid *qs[NTCACHES];\n\tunsigned i;\n\tsize_t sz, psz, qsz;\n\n\ttest_skip_if(!config_tcache);\n\n\tpsz = 42;\n\tqsz = nallocx(psz, 0) + 1;\n\n\t/* Create tcaches. */\n\tfor (i = 0; i < NTCACHES; i++) {\n\t\tsz = sizeof(unsigned);\n\t\tassert_d_eq(mallctl(\"tcache.create\", &tis[i], &sz, NULL, 0), 0,\n\t\t    \"Unexpected mallctl() failure, i=%u\", i);\n\t}\n\n\t/* Exercise tcache ID recycling. */\n\tfor (i = 0; i < NTCACHES; i++) {\n\t\tassert_d_eq(mallctl(\"tcache.destroy\", NULL, NULL, &tis[i],\n\t\t    sizeof(unsigned)), 0, \"Unexpected mallctl() failure, i=%u\",\n\t\t    i);\n\t}\n\tfor (i = 0; i < NTCACHES; i++) {\n\t\tsz = sizeof(unsigned);\n\t\tassert_d_eq(mallctl(\"tcache.create\", &tis[i], &sz, NULL, 0), 0,\n\t\t    \"Unexpected mallctl() failure, i=%u\", i);\n\t}\n\n\t/* Flush empty tcaches. */\n\tfor (i = 0; i < NTCACHES; i++) {\n\t\tassert_d_eq(mallctl(\"tcache.flush\", NULL, NULL, &tis[i],\n\t\t    sizeof(unsigned)), 0, \"Unexpected mallctl() failure, i=%u\",\n\t\t    i);\n\t}\n\n\t/* Cache some allocations. */\n\tfor (i = 0; i < NTCACHES; i++) {\n\t\tps[i] = mallocx(psz, MALLOCX_TCACHE(tis[i]));\n\t\tassert_ptr_not_null(ps[i], \"Unexpected mallocx() failure, i=%u\",\n\t\t    i);\n\t\tdallocx(ps[i], MALLOCX_TCACHE(tis[i]));\n\n\t\tqs[i] = mallocx(qsz, MALLOCX_TCACHE(tis[i]));\n\t\tassert_ptr_not_null(qs[i], \"Unexpected mallocx() failure, i=%u\",\n\t\t    i);\n\t\tdallocx(qs[i], MALLOCX_TCACHE(tis[i]));\n\t}\n\n\t/* Verify that tcaches allocate cached regions. */\n\tfor (i = 0; i < NTCACHES; i++) {\n\t\tvoid *p0 = ps[i];\n\t\tps[i] = mallocx(psz, MALLOCX_TCACHE(tis[i]));\n\t\tassert_ptr_not_null(ps[i], \"Unexpected mallocx() failure, i=%u\",\n\t\t    i);\n\t\tassert_ptr_eq(ps[i], p0,\n\t\t    \"Expected mallocx() to allocate cached region, i=%u\", i);\n\t}\n\n\t/* Verify that reallocation uses cached regions. */\n\tfor (i = 0; i < NTCACHES; i++) {\n\t\tvoid *q0 = qs[i];\n\t\tqs[i] = rallocx(ps[i], qsz, MALLOCX_TCACHE(tis[i]));\n\t\tassert_ptr_not_null(qs[i], \"Unexpected rallocx() failure, i=%u\",\n\t\t    i);\n\t\tassert_ptr_eq(qs[i], q0,\n\t\t    \"Expected rallocx() to allocate cached region, i=%u\", i);\n\t\t/* Avoid undefined behavior in case of test failure. */\n\t\tif (qs[i] == NULL)\n\t\t\tqs[i] = ps[i];\n\t}\n\tfor (i = 0; i < NTCACHES; i++)\n\t\tdallocx(qs[i], MALLOCX_TCACHE(tis[i]));\n\n\t/* Flush some non-empty tcaches. */\n\tfor (i = 0; i < NTCACHES/2; i++) {\n\t\tassert_d_eq(mallctl(\"tcache.flush\", NULL, NULL, &tis[i],\n\t\t    sizeof(unsigned)), 0, \"Unexpected mallctl() failure, i=%u\",\n\t\t    i);\n\t}\n\n\t/* Destroy tcaches. */\n\tfor (i = 0; i < NTCACHES; i++) {\n\t\tassert_d_eq(mallctl(\"tcache.destroy\", NULL, NULL, &tis[i],\n\t\t    sizeof(unsigned)), 0, \"Unexpected mallctl() failure, i=%u\",\n\t\t    i);\n\t}\n}\nTEST_END\n\nTEST_BEGIN(test_thread_arena)\n{\n\tunsigned arena_old, arena_new, narenas;\n\tsize_t sz = sizeof(unsigned);\n\n\tassert_d_eq(mallctl(\"arenas.narenas\", &narenas, &sz, NULL, 0), 0,\n\t    \"Unexpected mallctl() failure\");\n\tassert_u_eq(narenas, opt_narenas, \"Number of arenas incorrect\");\n\tarena_new = narenas - 1;\n\tassert_d_eq(mallctl(\"thread.arena\", &arena_old, &sz, &arena_new,\n\t    sizeof(unsigned)), 0, \"Unexpected mallctl() failure\");\n\tarena_new = 0;\n\tassert_d_eq(mallctl(\"thread.arena\", &arena_old, &sz, &arena_new,\n\t    sizeof(unsigned)), 0, \"Unexpected mallctl() failure\");\n}\nTEST_END\n\nTEST_BEGIN(test_arena_i_lg_dirty_mult)\n{\n\tssize_t lg_dirty_mult, orig_lg_dirty_mult, prev_lg_dirty_mult;\n\tsize_t sz = sizeof(ssize_t);\n\n\ttest_skip_if(opt_purge != purge_mode_ratio);\n\n\tassert_d_eq(mallctl(\"arena.0.lg_dirty_mult\", &orig_lg_dirty_mult, &sz,\n\t    NULL, 0), 0, \"Unexpected mallctl() failure\");\n\n\tlg_dirty_mult = -2;\n\tassert_d_eq(mallctl(\"arena.0.lg_dirty_mult\", NULL, NULL,\n\t    &lg_dirty_mult, sizeof(ssize_t)), EFAULT,\n\t    \"Unexpected mallctl() success\");\n\n\tlg_dirty_mult = (sizeof(size_t) << 3);\n\tassert_d_eq(mallctl(\"arena.0.lg_dirty_mult\", NULL, NULL,\n\t    &lg_dirty_mult, sizeof(ssize_t)), EFAULT,\n\t    \"Unexpected mallctl() success\");\n\n\tfor (prev_lg_dirty_mult = orig_lg_dirty_mult, lg_dirty_mult = -1;\n\t    lg_dirty_mult < (ssize_t)(sizeof(size_t) << 3); prev_lg_dirty_mult\n\t    = lg_dirty_mult, lg_dirty_mult++) {\n\t\tssize_t old_lg_dirty_mult;\n\n\t\tassert_d_eq(mallctl(\"arena.0.lg_dirty_mult\", &old_lg_dirty_mult,\n\t\t    &sz, &lg_dirty_mult, sizeof(ssize_t)), 0,\n\t\t    \"Unexpected mallctl() failure\");\n\t\tassert_zd_eq(old_lg_dirty_mult, prev_lg_dirty_mult,\n\t\t    \"Unexpected old arena.0.lg_dirty_mult\");\n\t}\n}\nTEST_END\n\nTEST_BEGIN(test_arena_i_decay_time)\n{\n\tssize_t decay_time, orig_decay_time, prev_decay_time;\n\tsize_t sz = sizeof(ssize_t);\n\n\ttest_skip_if(opt_purge != purge_mode_decay);\n\n\tassert_d_eq(mallctl(\"arena.0.decay_time\", &orig_decay_time, &sz,\n\t    NULL, 0), 0, \"Unexpected mallctl() failure\");\n\n\tdecay_time = -2;\n\tassert_d_eq(mallctl(\"arena.0.decay_time\", NULL, NULL,\n\t    &decay_time, sizeof(ssize_t)), EFAULT,\n\t    \"Unexpected mallctl() success\");\n\n\tdecay_time = 0x7fffffff;\n\tassert_d_eq(mallctl(\"arena.0.decay_time\", NULL, NULL,\n\t    &decay_time, sizeof(ssize_t)), 0,\n\t    \"Unexpected mallctl() failure\");\n\n\tfor (prev_decay_time = decay_time, decay_time = -1;\n\t    decay_time < 20; prev_decay_time = decay_time, decay_time++) {\n\t\tssize_t old_decay_time;\n\n\t\tassert_d_eq(mallctl(\"arena.0.decay_time\", &old_decay_time,\n\t\t    &sz, &decay_time, sizeof(ssize_t)), 0,\n\t\t    \"Unexpected mallctl() failure\");\n\t\tassert_zd_eq(old_decay_time, prev_decay_time,\n\t\t    \"Unexpected old arena.0.decay_time\");\n\t}\n}\nTEST_END\n\nTEST_BEGIN(test_arena_i_purge)\n{\n\tunsigned narenas;\n\tsize_t sz = sizeof(unsigned);\n\tsize_t mib[3];\n\tsize_t miblen = 3;\n\n\tassert_d_eq(mallctl(\"arena.0.purge\", NULL, NULL, NULL, 0), 0,\n\t    \"Unexpected mallctl() failure\");\n\n\tassert_d_eq(mallctl(\"arenas.narenas\", &narenas, &sz, NULL, 0), 0,\n\t    \"Unexpected mallctl() failure\");\n\tassert_d_eq(mallctlnametomib(\"arena.0.purge\", mib, &miblen), 0,\n\t    \"Unexpected mallctlnametomib() failure\");\n\tmib[1] = narenas;\n\tassert_d_eq(mallctlbymib(mib, miblen, NULL, NULL, NULL, 0), 0,\n\t    \"Unexpected mallctlbymib() failure\");\n}\nTEST_END\n\nTEST_BEGIN(test_arena_i_decay)\n{\n\tunsigned narenas;\n\tsize_t sz = sizeof(unsigned);\n\tsize_t mib[3];\n\tsize_t miblen = 3;\n\n\tassert_d_eq(mallctl(\"arena.0.decay\", NULL, NULL, NULL, 0), 0,\n\t    \"Unexpected mallctl() failure\");\n\n\tassert_d_eq(mallctl(\"arenas.narenas\", &narenas, &sz, NULL, 0), 0,\n\t    \"Unexpected mallctl() failure\");\n\tassert_d_eq(mallctlnametomib(\"arena.0.decay\", mib, &miblen), 0,\n\t    \"Unexpected mallctlnametomib() failure\");\n\tmib[1] = narenas;\n\tassert_d_eq(mallctlbymib(mib, miblen, NULL, NULL, NULL, 0), 0,\n\t    \"Unexpected mallctlbymib() failure\");\n}\nTEST_END\n\nTEST_BEGIN(test_arena_i_dss)\n{\n\tconst char *dss_prec_old, *dss_prec_new;\n\tsize_t sz = sizeof(dss_prec_old);\n\tsize_t mib[3];\n\tsize_t miblen;\n\n\tmiblen = sizeof(mib)/sizeof(size_t);\n\tassert_d_eq(mallctlnametomib(\"arena.0.dss\", mib, &miblen), 0,\n\t    \"Unexpected mallctlnametomib() error\");\n\n\tdss_prec_new = \"disabled\";\n\tassert_d_eq(mallctlbymib(mib, miblen, &dss_prec_old, &sz, &dss_prec_new,\n\t    sizeof(dss_prec_new)), 0, \"Unexpected mallctl() failure\");\n\tassert_str_ne(dss_prec_old, \"primary\",\n\t    \"Unexpected default for dss precedence\");\n\n\tassert_d_eq(mallctlbymib(mib, miblen, &dss_prec_new, &sz, &dss_prec_old,\n\t    sizeof(dss_prec_old)), 0, \"Unexpected mallctl() failure\");\n\n\tassert_d_eq(mallctlbymib(mib, miblen, &dss_prec_old, &sz, NULL, 0), 0,\n\t    \"Unexpected mallctl() failure\");\n\tassert_str_ne(dss_prec_old, \"primary\",\n\t    \"Unexpected value for dss precedence\");\n\n\tmib[1] = narenas_total_get();\n\tdss_prec_new = \"disabled\";\n\tassert_d_eq(mallctlbymib(mib, miblen, &dss_prec_old, &sz, &dss_prec_new,\n\t    sizeof(dss_prec_new)), 0, \"Unexpected mallctl() failure\");\n\tassert_str_ne(dss_prec_old, \"primary\",\n\t    \"Unexpected default for dss precedence\");\n\n\tassert_d_eq(mallctlbymib(mib, miblen, &dss_prec_new, &sz, &dss_prec_old,\n\t    sizeof(dss_prec_new)), 0, \"Unexpected mallctl() failure\");\n\n\tassert_d_eq(mallctlbymib(mib, miblen, &dss_prec_old, &sz, NULL, 0), 0,\n\t    \"Unexpected mallctl() failure\");\n\tassert_str_ne(dss_prec_old, \"primary\",\n\t    \"Unexpected value for dss precedence\");\n}\nTEST_END\n\nTEST_BEGIN(test_arenas_initialized)\n{\n\tunsigned narenas;\n\tsize_t sz = sizeof(narenas);\n\n\tassert_d_eq(mallctl(\"arenas.narenas\", &narenas, &sz, NULL, 0), 0,\n\t    \"Unexpected mallctl() failure\");\n\t{\n\t\tVARIABLE_ARRAY(bool, initialized, narenas);\n\n\t\tsz = narenas * sizeof(bool);\n\t\tassert_d_eq(mallctl(\"arenas.initialized\", initialized, &sz,\n\t\t    NULL, 0), 0, \"Unexpected mallctl() failure\");\n\t}\n}\nTEST_END\n\nTEST_BEGIN(test_arenas_lg_dirty_mult)\n{\n\tssize_t lg_dirty_mult, orig_lg_dirty_mult, prev_lg_dirty_mult;\n\tsize_t sz = sizeof(ssize_t);\n\n\ttest_skip_if(opt_purge != purge_mode_ratio);\n\n\tassert_d_eq(mallctl(\"arenas.lg_dirty_mult\", &orig_lg_dirty_mult, &sz,\n\t    NULL, 0), 0, \"Unexpected mallctl() failure\");\n\n\tlg_dirty_mult = -2;\n\tassert_d_eq(mallctl(\"arenas.lg_dirty_mult\", NULL, NULL,\n\t    &lg_dirty_mult, sizeof(ssize_t)), EFAULT,\n\t    \"Unexpected mallctl() success\");\n\n\tlg_dirty_mult = (sizeof(size_t) << 3);\n\tassert_d_eq(mallctl(\"arenas.lg_dirty_mult\", NULL, NULL,\n\t    &lg_dirty_mult, sizeof(ssize_t)), EFAULT,\n\t    \"Unexpected mallctl() success\");\n\n\tfor (prev_lg_dirty_mult = orig_lg_dirty_mult, lg_dirty_mult = -1;\n\t    lg_dirty_mult < (ssize_t)(sizeof(size_t) << 3); prev_lg_dirty_mult =\n\t    lg_dirty_mult, lg_dirty_mult++) {\n\t\tssize_t old_lg_dirty_mult;\n\n\t\tassert_d_eq(mallctl(\"arenas.lg_dirty_mult\", &old_lg_dirty_mult,\n\t\t    &sz, &lg_dirty_mult, sizeof(ssize_t)), 0,\n\t\t    \"Unexpected mallctl() failure\");\n\t\tassert_zd_eq(old_lg_dirty_mult, prev_lg_dirty_mult,\n\t\t    \"Unexpected old arenas.lg_dirty_mult\");\n\t}\n}\nTEST_END\n\nTEST_BEGIN(test_arenas_decay_time)\n{\n\tssize_t decay_time, orig_decay_time, prev_decay_time;\n\tsize_t sz = sizeof(ssize_t);\n\n\ttest_skip_if(opt_purge != purge_mode_decay);\n\n\tassert_d_eq(mallctl(\"arenas.decay_time\", &orig_decay_time, &sz,\n\t    NULL, 0), 0, \"Unexpected mallctl() failure\");\n\n\tdecay_time = -2;\n\tassert_d_eq(mallctl(\"arenas.decay_time\", NULL, NULL,\n\t    &decay_time, sizeof(ssize_t)), EFAULT,\n\t    \"Unexpected mallctl() success\");\n\n\tdecay_time = 0x7fffffff;\n\tassert_d_eq(mallctl(\"arenas.decay_time\", NULL, NULL,\n\t    &decay_time, sizeof(ssize_t)), 0,\n\t    \"Expected mallctl() failure\");\n\n\tfor (prev_decay_time = decay_time, decay_time = -1;\n\t    decay_time < 20; prev_decay_time = decay_time, decay_time++) {\n\t\tssize_t old_decay_time;\n\n\t\tassert_d_eq(mallctl(\"arenas.decay_time\", &old_decay_time,\n\t\t    &sz, &decay_time, sizeof(ssize_t)), 0,\n\t\t    \"Unexpected mallctl() failure\");\n\t\tassert_zd_eq(old_decay_time, prev_decay_time,\n\t\t    \"Unexpected old arenas.decay_time\");\n\t}\n}\nTEST_END\n\nTEST_BEGIN(test_arenas_constants)\n{\n\n#define\tTEST_ARENAS_CONSTANT(t, name, expected) do {\t\t\t\\\n\tt name;\t\t\t\t\t\t\t\t\\\n\tsize_t sz = sizeof(t);\t\t\t\t\t\t\\\n\tassert_d_eq(mallctl(\"arenas.\"#name, &name, &sz, NULL, 0), 0,\t\\\n\t    \"Unexpected mallctl() failure\");\t\t\t\t\\\n\tassert_zu_eq(name, expected, \"Incorrect \"#name\" size\");\t\t\\\n} while (0)\n\n\tTEST_ARENAS_CONSTANT(size_t, quantum, QUANTUM);\n\tTEST_ARENAS_CONSTANT(size_t, page, PAGE);\n\tTEST_ARENAS_CONSTANT(unsigned, nbins, NBINS);\n\tTEST_ARENAS_CONSTANT(unsigned, nlruns, nlclasses);\n\tTEST_ARENAS_CONSTANT(unsigned, nhchunks, nhclasses);\n\n#undef TEST_ARENAS_CONSTANT\n}\nTEST_END\n\nTEST_BEGIN(test_arenas_bin_constants)\n{\n\n#define\tTEST_ARENAS_BIN_CONSTANT(t, name, expected) do {\t\t\\\n\tt name;\t\t\t\t\t\t\t\t\\\n\tsize_t sz = sizeof(t);\t\t\t\t\t\t\\\n\tassert_d_eq(mallctl(\"arenas.bin.0.\"#name, &name, &sz, NULL, 0),\t\\\n\t    0, \"Unexpected mallctl() failure\");\t\t\t\t\\\n\tassert_zu_eq(name, expected, \"Incorrect \"#name\" size\");\t\t\\\n} while (0)\n\n\tTEST_ARENAS_BIN_CONSTANT(size_t, size, arena_bin_info[0].reg_size);\n\tTEST_ARENAS_BIN_CONSTANT(uint32_t, nregs, arena_bin_info[0].nregs);\n\tTEST_ARENAS_BIN_CONSTANT(size_t, run_size, arena_bin_info[0].run_size);\n\n#undef TEST_ARENAS_BIN_CONSTANT\n}\nTEST_END\n\nTEST_BEGIN(test_arenas_lrun_constants)\n{\n\n#define\tTEST_ARENAS_LRUN_CONSTANT(t, name, expected) do {\t\t\\\n\tt name;\t\t\t\t\t\t\t\t\\\n\tsize_t sz = sizeof(t);\t\t\t\t\t\t\\\n\tassert_d_eq(mallctl(\"arenas.lrun.0.\"#name, &name, &sz, NULL,\t\\\n\t    0), 0, \"Unexpected mallctl() failure\");\t\t\t\\\n\tassert_zu_eq(name, expected, \"Incorrect \"#name\" size\");\t\t\\\n} while (0)\n\n\tTEST_ARENAS_LRUN_CONSTANT(size_t, size, LARGE_MINCLASS);\n\n#undef TEST_ARENAS_LRUN_CONSTANT\n}\nTEST_END\n\nTEST_BEGIN(test_arenas_hchunk_constants)\n{\n\n#define\tTEST_ARENAS_HCHUNK_CONSTANT(t, name, expected) do {\t\t\\\n\tt name;\t\t\t\t\t\t\t\t\\\n\tsize_t sz = sizeof(t);\t\t\t\t\t\t\\\n\tassert_d_eq(mallctl(\"arenas.hchunk.0.\"#name, &name, &sz, NULL,\t\\\n\t    0), 0, \"Unexpected mallctl() failure\");\t\t\t\\\n\tassert_zu_eq(name, expected, \"Incorrect \"#name\" size\");\t\t\\\n} while (0)\n\n\tTEST_ARENAS_HCHUNK_CONSTANT(size_t, size, chunksize);\n\n#undef TEST_ARENAS_HCHUNK_CONSTANT\n}\nTEST_END\n\nTEST_BEGIN(test_arenas_extend)\n{\n\tunsigned narenas_before, arena, narenas_after;\n\tsize_t sz = sizeof(unsigned);\n\n\tassert_d_eq(mallctl(\"arenas.narenas\", &narenas_before, &sz, NULL, 0), 0,\n\t    \"Unexpected mallctl() failure\");\n\tassert_d_eq(mallctl(\"arenas.extend\", &arena, &sz, NULL, 0), 0,\n\t    \"Unexpected mallctl() failure\");\n\tassert_d_eq(mallctl(\"arenas.narenas\", &narenas_after, &sz, NULL, 0), 0,\n\t    \"Unexpected mallctl() failure\");\n\n\tassert_u_eq(narenas_before+1, narenas_after,\n\t    \"Unexpected number of arenas before versus after extension\");\n\tassert_u_eq(arena, narenas_after-1, \"Unexpected arena index\");\n}\nTEST_END\n\nTEST_BEGIN(test_stats_arenas)\n{\n\n#define\tTEST_STATS_ARENAS(t, name) do {\t\t\t\t\t\\\n\tt name;\t\t\t\t\t\t\t\t\\\n\tsize_t sz = sizeof(t);\t\t\t\t\t\t\\\n\tassert_d_eq(mallctl(\"stats.arenas.0.\"#name, &name, &sz, NULL,\t\\\n\t    0), 0, \"Unexpected mallctl() failure\");\t\t\t\\\n} while (0)\n\n\tTEST_STATS_ARENAS(unsigned, nthreads);\n\tTEST_STATS_ARENAS(const char *, dss);\n\tTEST_STATS_ARENAS(ssize_t, lg_dirty_mult);\n\tTEST_STATS_ARENAS(ssize_t, decay_time);\n\tTEST_STATS_ARENAS(size_t, pactive);\n\tTEST_STATS_ARENAS(size_t, pdirty);\n\n#undef TEST_STATS_ARENAS\n}\nTEST_END\n\nint\nmain(void)\n{\n\n\treturn (test(\n\t    test_mallctl_errors,\n\t    test_mallctlnametomib_errors,\n\t    test_mallctlbymib_errors,\n\t    test_mallctl_read_write,\n\t    test_mallctlnametomib_short_mib,\n\t    test_mallctl_config,\n\t    test_mallctl_opt,\n\t    test_manpage_example,\n\t    test_tcache_none,\n\t    test_tcache,\n\t    test_thread_arena,\n\t    test_arena_i_lg_dirty_mult,\n\t    test_arena_i_decay_time,\n\t    test_arena_i_purge,\n\t    test_arena_i_decay,\n\t    test_arena_i_dss,\n\t    test_arenas_initialized,\n\t    test_arenas_lg_dirty_mult,\n\t    test_arenas_decay_time,\n\t    test_arenas_constants,\n\t    test_arenas_bin_constants,\n\t    test_arenas_lrun_constants,\n\t    test_arenas_hchunk_constants,\n\t    test_arenas_extend,\n\t    test_stats_arenas));\n}\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/deps/jemalloc/test/unit/math.c",
    "content": "#include \"test/jemalloc_test.h\"\n\n#define\tMAX_REL_ERR 1.0e-9\n#define\tMAX_ABS_ERR 1.0e-9\n\n#include <float.h>\n\n#ifndef INFINITY\n#define\tINFINITY (DBL_MAX + DBL_MAX)\n#endif\n\nstatic bool\ndouble_eq_rel(double a, double b, double max_rel_err, double max_abs_err)\n{\n\tdouble rel_err;\n\n\tif (fabs(a - b) < max_abs_err)\n\t\treturn (true);\n\trel_err = (fabs(b) > fabs(a)) ? fabs((a-b)/b) : fabs((a-b)/a);\n\treturn (rel_err < max_rel_err);\n}\n\nstatic uint64_t\nfactorial(unsigned x)\n{\n\tuint64_t ret = 1;\n\tunsigned i;\n\n\tfor (i = 2; i <= x; i++)\n\t\tret *= (uint64_t)i;\n\n\treturn (ret);\n}\n\nTEST_BEGIN(test_ln_gamma_factorial)\n{\n\tunsigned x;\n\n\t/* exp(ln_gamma(x)) == (x-1)! for integer x. */\n\tfor (x = 1; x <= 21; x++) {\n\t\tassert_true(double_eq_rel(exp(ln_gamma(x)),\n\t\t    (double)factorial(x-1), MAX_REL_ERR, MAX_ABS_ERR),\n\t\t    \"Incorrect factorial result for x=%u\", x);\n\t}\n}\nTEST_END\n\n/* Expected ln_gamma([0.0..100.0] increment=0.25). */\nstatic const double ln_gamma_misc_expected[] = {\n\tINFINITY,\n\t1.28802252469807743, 0.57236494292470008, 0.20328095143129538,\n\t0.00000000000000000, -0.09827183642181320, -0.12078223763524518,\n\t-0.08440112102048555, 0.00000000000000000, 0.12487171489239651,\n\t0.28468287047291918, 0.47521466691493719, 0.69314718055994529,\n\t0.93580193110872523, 1.20097360234707429, 1.48681557859341718,\n\t1.79175946922805496, 2.11445692745037128, 2.45373657084244234,\n\t2.80857141857573644, 3.17805383034794575, 3.56137591038669710,\n\t3.95781396761871651, 4.36671603662228680, 4.78749174278204581,\n\t5.21960398699022932, 5.66256205985714178, 6.11591589143154568,\n\t6.57925121201010121, 7.05218545073853953, 7.53436423675873268,\n\t8.02545839631598312, 8.52516136106541467, 9.03318691960512332,\n\t9.54926725730099690, 10.07315123968123949, 10.60460290274525086,\n\t11.14340011995171231, 11.68933342079726856, 12.24220494005076176,\n\t12.80182748008146909, 13.36802367147604720, 13.94062521940376342,\n\t14.51947222506051816, 15.10441257307551943, 15.69530137706046524,\n\t16.29200047656724237, 16.89437797963419285, 17.50230784587389010,\n\t18.11566950571089407, 18.73434751193644843, 19.35823122022435427,\n\t19.98721449566188468, 20.62119544270163018, 21.26007615624470048,\n\t21.90376249182879320, 22.55216385312342098, 23.20519299513386002,\n\t23.86276584168908954, 24.52480131594137802, 25.19122118273868338,\n\t25.86194990184851861, 26.53691449111561340, 27.21604439872720604,\n\t27.89927138384089389, 28.58652940490193828, 29.27775451504081516,\n\t29.97288476399884871, 30.67186010608067548, 31.37462231367769050,\n\t32.08111489594735843, 32.79128302226991565, 33.50507345013689076,\n\t34.22243445715505317, 34.94331577687681545, 35.66766853819134298,\n\t36.39544520803305261, 37.12659953718355865, 37.86108650896109395,\n\t38.59886229060776230, 39.33988418719949465, 40.08411059791735198,\n\t40.83150097453079752, 41.58201578195490100, 42.33561646075348506,\n\t43.09226539146988699, 43.85192586067515208, 44.61456202863158893,\n\t45.38013889847690052, 46.14862228684032885, 46.91997879580877395,\n\t47.69417578616628361, 48.47118135183522014, 49.25096429545256882,\n\t50.03349410501914463, 50.81874093156324790, 51.60667556776436982,\n\t52.39726942748592364, 53.19049452616926743, 53.98632346204390586,\n\t54.78472939811231157, 55.58568604486942633, 56.38916764371992940,\n\t57.19514895105859864, 58.00360522298051080, 58.81451220059079787,\n\t59.62784609588432261, 60.44358357816834371, 61.26170176100199427,\n\t62.08217818962842927, 62.90499082887649962, 63.73011805151035958,\n\t64.55753862700632340, 65.38723171073768015, 66.21917683354901385,\n\t67.05335389170279825, 67.88974313718154008, 68.72832516833013017,\n\t69.56908092082363737, 70.41199165894616385, 71.25703896716800045,\n\t72.10420474200799390, 72.95347118416940191, 73.80482079093779646,\n\t74.65823634883015814, 75.51370092648485866, 76.37119786778275454,\n\t77.23071078519033961, 78.09222355331530707, 78.95572030266725960,\n\t79.82118541361435859, 80.68860351052903468, 81.55795945611502873,\n\t82.42923834590904164, 83.30242550295004378, 84.17750647261028973,\n\t85.05446701758152983, 85.93329311301090456, 86.81397094178107920,\n\t87.69648688992882057, 88.58082754219766741, 89.46697967771913795,\n\t90.35493026581838194, 91.24466646193963015, 92.13617560368709292,\n\t93.02944520697742803, 93.92446296229978486, 94.82121673107967297,\n\t95.71969454214321615, 96.61988458827809723, 97.52177522288820910,\n\t98.42535495673848800, 99.33061245478741341, 100.23753653310367895,\n\t101.14611615586458981, 102.05634043243354370, 102.96819861451382394,\n\t103.88168009337621811, 104.79677439715833032, 105.71347118823287303,\n\t106.63176026064346047, 107.55163153760463501, 108.47307506906540198,\n\t109.39608102933323153, 110.32063971475740516, 111.24674154146920557,\n\t112.17437704317786995, 113.10353686902013237, 114.03421178146170689,\n\t114.96639265424990128, 115.90007047041454769, 116.83523632031698014,\n\t117.77188139974506953, 118.70999700805310795, 119.64957454634490830,\n\t120.59060551569974962, 121.53308151543865279, 122.47699424143097247,\n\t123.42233548443955726, 124.36909712850338394, 125.31727114935689826,\n\t126.26684961288492559, 127.21782467361175861, 128.17018857322420899,\n\t129.12393363912724453, 130.07905228303084755, 131.03553699956862033,\n\t131.99338036494577864, 132.95257503561629164, 133.91311374698926784,\n\t134.87498931216194364, 135.83819462068046846, 136.80272263732638294,\n\t137.76856640092901785, 138.73571902320256299, 139.70417368760718091,\n\t140.67392364823425055, 141.64496222871400732, 142.61728282114600574,\n\t143.59087888505104047, 144.56574394634486680, 145.54187159633210058,\n\t146.51925549072063859, 147.49788934865566148, 148.47776695177302031,\n\t149.45888214327129617, 150.44122882700193600, 151.42480096657754984,\n\t152.40959258449737490, 153.39559776128982094, 154.38281063467164245,\n\t155.37122539872302696, 156.36083630307879844, 157.35163765213474107,\n\t158.34362380426921391, 159.33678917107920370, 160.33112821663092973,\n\t161.32663545672428995, 162.32330545817117695, 163.32113283808695314,\n\t164.32011226319519892, 165.32023844914485267, 166.32150615984036790,\n\t167.32391020678358018, 168.32744544842768164, 169.33210678954270634,\n\t170.33788918059275375, 171.34478761712384198, 172.35279713916281707,\n\t173.36191283062726143, 174.37212981874515094, 175.38344327348534080,\n\t176.39584840699734514, 177.40934047306160437, 178.42391476654847793,\n\t179.43956662288721304, 180.45629141754378111, 181.47408456550741107,\n\t182.49294152078630304, 183.51285777591152737, 184.53382886144947861,\n\t185.55585034552262869, 186.57891783333786861, 187.60302696672312095,\n\t188.62817342367162610, 189.65435291789341932, 190.68156119837468054,\n\t191.70979404894376330, 192.73904728784492590, 193.76931676731820176,\n\t194.80059837318714244, 195.83288802445184729, 196.86618167288995096,\n\t197.90047530266301123, 198.93576492992946214, 199.97204660246373464,\n\t201.00931639928148797, 202.04757043027063901, 203.08680483582807597,\n\t204.12701578650228385, 205.16819948264117102, 206.21035215404597807,\n\t207.25347005962987623, 208.29754948708190909, 209.34258675253678916,\n\t210.38857820024875878, 211.43552020227099320, 212.48340915813977858,\n\t213.53224149456323744, 214.58201366511514152, 215.63272214993284592,\n\t216.68436345542014010, 217.73693411395422004, 218.79043068359703739,\n\t219.84484974781133815, 220.90018791517996988, 221.95644181913033322,\n\t223.01360811766215875, 224.07168349307951871, 225.13066465172661879,\n\t226.19054832372759734, 227.25133126272962159, 228.31301024565024704,\n\t229.37558207242807384, 230.43904356577689896, 231.50339157094342113,\n\t232.56862295546847008, 233.63473460895144740, 234.70172344281823484,\n\t235.76958639009222907, 236.83832040516844586, 237.90792246359117712,\n\t238.97838956183431947, 240.04971871708477238, 241.12190696702904802,\n\t242.19495136964280846, 243.26884900298270509, 244.34359696498191283,\n\t245.41919237324782443, 246.49563236486270057, 247.57291409618682110,\n\t248.65103474266476269, 249.72999149863338175, 250.80978157713354904,\n\t251.89040220972316320, 252.97185064629374551, 254.05412415488834199,\n\t255.13722002152300661, 256.22113555000953511, 257.30586806178126835,\n\t258.39141489572085675, 259.47777340799029844, 260.56494097186322279,\n\t261.65291497755913497, 262.74169283208021852, 263.83127195904967266,\n\t264.92164979855277807, 266.01282380697938379, 267.10479145686849733,\n\t268.19755023675537586, 269.29109765101975427, 270.38543121973674488,\n\t271.48054847852881721, 272.57644697842033565, 273.67312428569374561,\n\t274.77057798174683967, 275.86880566295326389, 276.96780494052313770,\n\t278.06757344036617496, 279.16810880295668085, 280.26940868320008349,\n\t281.37147075030043197, 282.47429268763045229, 283.57787219260217171,\n\t284.68220697654078322, 285.78729476455760050, 286.89313329542699194,\n\t287.99972032146268930, 289.10705360839756395, 290.21513093526289140,\n\t291.32395009427028754, 292.43350889069523646, 293.54380514276073200,\n\t294.65483668152336350, 295.76660135076059532, 296.87909700685889902,\n\t297.99232151870342022, 299.10627276756946458, 300.22094864701409733,\n\t301.33634706277030091, 302.45246593264130297, 303.56930318639643929,\n\t304.68685676566872189, 305.80512462385280514, 306.92410472600477078,\n\t308.04379504874236773, 309.16419358014690033, 310.28529831966631036,\n\t311.40710727801865687, 312.52961847709792664, 313.65282994987899201,\n\t314.77673974032603610, 315.90134590329950015, 317.02664650446632777,\n\t318.15263962020929966, 319.27932333753892635, 320.40669575400545455,\n\t321.53475497761127144, 322.66349912672620803, 323.79292633000159185,\n\t324.92303472628691452, 326.05382246454587403, 327.18528770377525916,\n\t328.31742861292224234, 329.45024337080525356, 330.58373016603343331,\n\t331.71788719692847280, 332.85271267144611329, 333.98820480709991898,\n\t335.12436183088397001, 336.26118197919845443, 337.39866349777429377,\n\t338.53680464159958774, 339.67560367484657036, 340.81505887079896411,\n\t341.95516851178109619, 343.09593088908627578, 344.23734430290727460,\n\t345.37940706226686416, 346.52211748494903532, 347.66547389743118401,\n\t348.80947463481720661, 349.95411804077025408, 351.09940246744753267,\n\t352.24532627543504759, 353.39188783368263103, 354.53908551944078908,\n\t355.68691771819692349, 356.83538282361303118, 357.98447923746385868,\n\t359.13420536957539753\n};\n\nTEST_BEGIN(test_ln_gamma_misc)\n{\n\tunsigned i;\n\n\tfor (i = 1; i < sizeof(ln_gamma_misc_expected)/sizeof(double); i++) {\n\t\tdouble x = (double)i * 0.25;\n\t\tassert_true(double_eq_rel(ln_gamma(x),\n\t\t    ln_gamma_misc_expected[i], MAX_REL_ERR, MAX_ABS_ERR),\n\t\t    \"Incorrect ln_gamma result for i=%u\", i);\n\t}\n}\nTEST_END\n\n/* Expected pt_norm([0.01..0.99] increment=0.01). */\nstatic const double pt_norm_expected[] = {\n\t-INFINITY,\n\t-2.32634787404084076, -2.05374891063182252, -1.88079360815125085,\n\t-1.75068607125216946, -1.64485362695147264, -1.55477359459685305,\n\t-1.47579102817917063, -1.40507156030963221, -1.34075503369021654,\n\t-1.28155156554460081, -1.22652812003661049, -1.17498679206608991,\n\t-1.12639112903880045, -1.08031934081495606, -1.03643338949378938,\n\t-0.99445788320975281, -0.95416525314619416, -0.91536508784281390,\n\t-0.87789629505122846, -0.84162123357291418, -0.80642124701824025,\n\t-0.77219321418868492, -0.73884684918521371, -0.70630256284008752,\n\t-0.67448975019608171, -0.64334540539291685, -0.61281299101662701,\n\t-0.58284150727121620, -0.55338471955567281, -0.52440051270804067,\n\t-0.49585034734745320, -0.46769879911450812, -0.43991316567323380,\n\t-0.41246312944140462, -0.38532046640756751, -0.35845879325119373,\n\t-0.33185334643681652, -0.30548078809939738, -0.27931903444745404,\n\t-0.25334710313579978, -0.22754497664114931, -0.20189347914185077,\n\t-0.17637416478086135, -0.15096921549677725, -0.12566134685507399,\n\t-0.10043372051146975, -0.07526986209982976, -0.05015358346473352,\n\t-0.02506890825871106, 0.00000000000000000, 0.02506890825871106,\n\t0.05015358346473366, 0.07526986209982990, 0.10043372051146990,\n\t0.12566134685507413, 0.15096921549677739, 0.17637416478086146,\n\t0.20189347914185105, 0.22754497664114931, 0.25334710313579978,\n\t0.27931903444745404, 0.30548078809939738, 0.33185334643681652,\n\t0.35845879325119373, 0.38532046640756762, 0.41246312944140484,\n\t0.43991316567323391, 0.46769879911450835, 0.49585034734745348,\n\t0.52440051270804111, 0.55338471955567303, 0.58284150727121620,\n\t0.61281299101662701, 0.64334540539291685, 0.67448975019608171,\n\t0.70630256284008752, 0.73884684918521371, 0.77219321418868492,\n\t0.80642124701824036, 0.84162123357291441, 0.87789629505122879,\n\t0.91536508784281423, 0.95416525314619460, 0.99445788320975348,\n\t1.03643338949378938, 1.08031934081495606, 1.12639112903880045,\n\t1.17498679206608991, 1.22652812003661049, 1.28155156554460081,\n\t1.34075503369021654, 1.40507156030963265, 1.47579102817917085,\n\t1.55477359459685394, 1.64485362695147308, 1.75068607125217102,\n\t1.88079360815125041, 2.05374891063182208, 2.32634787404084076\n};\n\nTEST_BEGIN(test_pt_norm)\n{\n\tunsigned i;\n\n\tfor (i = 1; i < sizeof(pt_norm_expected)/sizeof(double); i++) {\n\t\tdouble p = (double)i * 0.01;\n\t\tassert_true(double_eq_rel(pt_norm(p), pt_norm_expected[i],\n\t\t    MAX_REL_ERR, MAX_ABS_ERR),\n\t\t    \"Incorrect pt_norm result for i=%u\", i);\n\t}\n}\nTEST_END\n\n/*\n * Expected pt_chi2(p=[0.01..0.99] increment=0.07,\n *                  df={0.1, 1.1, 10.1, 100.1, 1000.1}).\n */\nstatic const double pt_chi2_df[] = {0.1, 1.1, 10.1, 100.1, 1000.1};\nstatic const double pt_chi2_expected[] = {\n\t1.168926411457320e-40, 1.347680397072034e-22, 3.886980416666260e-17,\n\t8.245951724356564e-14, 2.068936347497604e-11, 1.562561743309233e-09,\n\t5.459543043426564e-08, 1.114775688149252e-06, 1.532101202364371e-05,\n\t1.553884683726585e-04, 1.239396954915939e-03, 8.153872320255721e-03,\n\t4.631183739647523e-02, 2.473187311701327e-01, 2.175254800183617e+00,\n\n\t0.0003729887888876379, 0.0164409238228929513, 0.0521523015190650113,\n\t0.1064701372271216612, 0.1800913735793082115, 0.2748704281195626931,\n\t0.3939246282787986497, 0.5420727552260817816, 0.7267265822221973259,\n\t0.9596554296000253670, 1.2607440376386165326, 1.6671185084541604304,\n\t2.2604828984738705167, 3.2868613342148607082, 6.9298574921692139839,\n\n\t2.606673548632508, 4.602913725294877, 5.646152813924212,\n\t6.488971315540869, 7.249823275816285, 7.977314231410841,\n\t8.700354939944047, 9.441728024225892, 10.224338321374127,\n\t11.076435368801061, 12.039320937038386, 13.183878752697167,\n\t14.657791935084575, 16.885728216339373, 23.361991680031817,\n\n\t70.14844087392152, 80.92379498849355, 85.53325420085891,\n\t88.94433120715347, 91.83732712857017, 94.46719943606301,\n\t96.96896479994635, 99.43412843510363, 101.94074719829733,\n\t104.57228644307247, 107.43900093448734, 110.71844673417287,\n\t114.76616819871325, 120.57422505959563, 135.92318818757556,\n\n\t899.0072447849649, 937.9271278858220, 953.8117189560207,\n\t965.3079371501154, 974.8974061207954, 983.4936235182347,\n\t991.5691170518946, 999.4334123954690, 1007.3391826856553,\n\t1015.5445154999951, 1024.3777075619569, 1034.3538789836223,\n\t1046.4872561869577, 1063.5717461999654, 1107.0741966053859\n};\n\nTEST_BEGIN(test_pt_chi2)\n{\n\tunsigned i, j;\n\tunsigned e = 0;\n\n\tfor (i = 0; i < sizeof(pt_chi2_df)/sizeof(double); i++) {\n\t\tdouble df = pt_chi2_df[i];\n\t\tdouble ln_gamma_df = ln_gamma(df * 0.5);\n\t\tfor (j = 1; j < 100; j += 7) {\n\t\t\tdouble p = (double)j * 0.01;\n\t\t\tassert_true(double_eq_rel(pt_chi2(p, df, ln_gamma_df),\n\t\t\t    pt_chi2_expected[e], MAX_REL_ERR, MAX_ABS_ERR),\n\t\t\t    \"Incorrect pt_chi2 result for i=%u, j=%u\", i, j);\n\t\t\te++;\n\t\t}\n\t}\n}\nTEST_END\n\n/*\n * Expected pt_gamma(p=[0.1..0.99] increment=0.07,\n *                   shape=[0.5..3.0] increment=0.5).\n */\nstatic const double pt_gamma_shape[] = {0.5, 1.0, 1.5, 2.0, 2.5, 3.0};\nstatic const double pt_gamma_expected[] = {\n\t7.854392895485103e-05, 5.043466107888016e-03, 1.788288957794883e-02,\n\t3.900956150232906e-02, 6.913847560638034e-02, 1.093710833465766e-01,\n\t1.613412523825817e-01, 2.274682115597864e-01, 3.114117323127083e-01,\n\t4.189466220207417e-01, 5.598106789059246e-01, 7.521856146202706e-01,\n\t1.036125427911119e+00, 1.532450860038180e+00, 3.317448300510606e+00,\n\n\t0.01005033585350144, 0.08338160893905107, 0.16251892949777497,\n\t0.24846135929849966, 0.34249030894677596, 0.44628710262841947,\n\t0.56211891815354142, 0.69314718055994529, 0.84397007029452920,\n\t1.02165124753198167, 1.23787435600161766, 1.51412773262977574,\n\t1.89711998488588196, 2.52572864430825783, 4.60517018598809091,\n\n\t0.05741590094955853, 0.24747378084860744, 0.39888572212236084,\n\t0.54394139997444901, 0.69048812513915159, 0.84311389861296104,\n\t1.00580622221479898, 1.18298694218766931, 1.38038096305861213,\n\t1.60627736383027453, 1.87396970522337947, 2.20749220408081070,\n\t2.65852391865854942, 3.37934630984842244, 5.67243336507218476,\n\n\t0.1485547402532659, 0.4657458011640391, 0.6832386130709406,\n\t0.8794297834672100, 1.0700752852474524, 1.2629614217350744,\n\t1.4638400448580779, 1.6783469900166610, 1.9132338090606940,\n\t2.1778589228618777, 2.4868823970010991, 2.8664695666264195,\n\t3.3724415436062114, 4.1682658512758071, 6.6383520679938108,\n\n\t0.2771490383641385, 0.7195001279643727, 0.9969081732265243,\n\t1.2383497880608061, 1.4675206597269927, 1.6953064251816552,\n\t1.9291243435606809, 2.1757300955477641, 2.4428032131216391,\n\t2.7406534569230616, 3.0851445039665513, 3.5043101122033367,\n\t4.0575997065264637, 4.9182956424675286, 7.5431362346944937,\n\n\t0.4360451650782932, 0.9983600902486267, 1.3306365880734528,\n\t1.6129750834753802, 1.8767241606994294, 2.1357032436097660,\n\t2.3988853336865565, 2.6740603137235603, 2.9697561737517959,\n\t3.2971457713883265, 3.6731795898504660, 4.1275751617770631,\n\t4.7230515633946677, 5.6417477865306020, 8.4059469148854635\n};\n\nTEST_BEGIN(test_pt_gamma_shape)\n{\n\tunsigned i, j;\n\tunsigned e = 0;\n\n\tfor (i = 0; i < sizeof(pt_gamma_shape)/sizeof(double); i++) {\n\t\tdouble shape = pt_gamma_shape[i];\n\t\tdouble ln_gamma_shape = ln_gamma(shape);\n\t\tfor (j = 1; j < 100; j += 7) {\n\t\t\tdouble p = (double)j * 0.01;\n\t\t\tassert_true(double_eq_rel(pt_gamma(p, shape, 1.0,\n\t\t\t    ln_gamma_shape), pt_gamma_expected[e], MAX_REL_ERR,\n\t\t\t    MAX_ABS_ERR),\n\t\t\t    \"Incorrect pt_gamma result for i=%u, j=%u\", i, j);\n\t\t\te++;\n\t\t}\n\t}\n}\nTEST_END\n\nTEST_BEGIN(test_pt_gamma_scale)\n{\n\tdouble shape = 1.0;\n\tdouble ln_gamma_shape = ln_gamma(shape);\n\n\tassert_true(double_eq_rel(\n\t    pt_gamma(0.5, shape, 1.0, ln_gamma_shape) * 10.0,\n\t    pt_gamma(0.5, shape, 10.0, ln_gamma_shape), MAX_REL_ERR,\n\t    MAX_ABS_ERR),\n\t    \"Scale should be trivially equivalent to external multiplication\");\n}\nTEST_END\n\nint\nmain(void)\n{\n\n\treturn (test(\n\t    test_ln_gamma_factorial,\n\t    test_ln_gamma_misc,\n\t    test_pt_norm,\n\t    test_pt_chi2,\n\t    test_pt_gamma_shape,\n\t    test_pt_gamma_scale));\n}\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/deps/jemalloc/test/unit/mq.c",
    "content": "#include \"test/jemalloc_test.h\"\n\n#define\tNSENDERS\t3\n#define\tNMSGS\t\t100000\n\ntypedef struct mq_msg_s mq_msg_t;\nstruct mq_msg_s {\n\tmq_msg(mq_msg_t)\tlink;\n};\nmq_gen(static, mq_, mq_t, mq_msg_t, link)\n\nTEST_BEGIN(test_mq_basic)\n{\n\tmq_t mq;\n\tmq_msg_t msg;\n\n\tassert_false(mq_init(&mq), \"Unexpected mq_init() failure\");\n\tassert_u_eq(mq_count(&mq), 0, \"mq should be empty\");\n\tassert_ptr_null(mq_tryget(&mq),\n\t    \"mq_tryget() should fail when the queue is empty\");\n\n\tmq_put(&mq, &msg);\n\tassert_u_eq(mq_count(&mq), 1, \"mq should contain one message\");\n\tassert_ptr_eq(mq_tryget(&mq), &msg, \"mq_tryget() should return msg\");\n\n\tmq_put(&mq, &msg);\n\tassert_ptr_eq(mq_get(&mq), &msg, \"mq_get() should return msg\");\n\n\tmq_fini(&mq);\n}\nTEST_END\n\nstatic void *\nthd_receiver_start(void *arg)\n{\n\tmq_t *mq = (mq_t *)arg;\n\tunsigned i;\n\n\tfor (i = 0; i < (NSENDERS * NMSGS); i++) {\n\t\tmq_msg_t *msg = mq_get(mq);\n\t\tassert_ptr_not_null(msg, \"mq_get() should never return NULL\");\n\t\tdallocx(msg, 0);\n\t}\n\treturn (NULL);\n}\n\nstatic void *\nthd_sender_start(void *arg)\n{\n\tmq_t *mq = (mq_t *)arg;\n\tunsigned i;\n\n\tfor (i = 0; i < NMSGS; i++) {\n\t\tmq_msg_t *msg;\n\t\tvoid *p;\n\t\tp = mallocx(sizeof(mq_msg_t), 0);\n\t\tassert_ptr_not_null(p, \"Unexpected mallocx() failure\");\n\t\tmsg = (mq_msg_t *)p;\n\t\tmq_put(mq, msg);\n\t}\n\treturn (NULL);\n}\n\nTEST_BEGIN(test_mq_threaded)\n{\n\tmq_t mq;\n\tthd_t receiver;\n\tthd_t senders[NSENDERS];\n\tunsigned i;\n\n\tassert_false(mq_init(&mq), \"Unexpected mq_init() failure\");\n\n\tthd_create(&receiver, thd_receiver_start, (void *)&mq);\n\tfor (i = 0; i < NSENDERS; i++)\n\t\tthd_create(&senders[i], thd_sender_start, (void *)&mq);\n\n\tthd_join(receiver, NULL);\n\tfor (i = 0; i < NSENDERS; i++)\n\t\tthd_join(senders[i], NULL);\n\n\tmq_fini(&mq);\n}\nTEST_END\n\nint\nmain(void)\n{\n\n\treturn (test(\n\t    test_mq_basic,\n\t    test_mq_threaded));\n}\n\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/deps/jemalloc/test/unit/mtx.c",
    "content": "#include \"test/jemalloc_test.h\"\n\n#define\tNTHREADS\t2\n#define\tNINCRS\t\t2000000\n\nTEST_BEGIN(test_mtx_basic)\n{\n\tmtx_t mtx;\n\n\tassert_false(mtx_init(&mtx), \"Unexpected mtx_init() failure\");\n\tmtx_lock(&mtx);\n\tmtx_unlock(&mtx);\n\tmtx_fini(&mtx);\n}\nTEST_END\n\ntypedef struct {\n\tmtx_t\t\tmtx;\n\tunsigned\tx;\n} thd_start_arg_t;\n\nstatic void *\nthd_start(void *varg)\n{\n\tthd_start_arg_t *arg = (thd_start_arg_t *)varg;\n\tunsigned i;\n\n\tfor (i = 0; i < NINCRS; i++) {\n\t\tmtx_lock(&arg->mtx);\n\t\targ->x++;\n\t\tmtx_unlock(&arg->mtx);\n\t}\n\treturn (NULL);\n}\n\nTEST_BEGIN(test_mtx_race)\n{\n\tthd_start_arg_t arg;\n\tthd_t thds[NTHREADS];\n\tunsigned i;\n\n\tassert_false(mtx_init(&arg.mtx), \"Unexpected mtx_init() failure\");\n\targ.x = 0;\n\tfor (i = 0; i < NTHREADS; i++)\n\t\tthd_create(&thds[i], thd_start, (void *)&arg);\n\tfor (i = 0; i < NTHREADS; i++)\n\t\tthd_join(thds[i], NULL);\n\tassert_u_eq(arg.x, NTHREADS * NINCRS,\n\t    \"Race-related counter corruption\");\n}\nTEST_END\n\nint\nmain(void)\n{\n\n\treturn (test(\n\t    test_mtx_basic,\n\t    test_mtx_race));\n}\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/deps/jemalloc/test/unit/nstime.c",
    "content": "#include \"test/jemalloc_test.h\"\n\n#define\tBILLION\tUINT64_C(1000000000)\n\nTEST_BEGIN(test_nstime_init)\n{\n\tnstime_t nst;\n\n\tnstime_init(&nst, 42000000043);\n\tassert_u64_eq(nstime_ns(&nst), 42000000043, \"ns incorrectly read\");\n\tassert_u64_eq(nstime_sec(&nst), 42, \"sec incorrectly read\");\n\tassert_u64_eq(nstime_nsec(&nst), 43, \"nsec incorrectly read\");\n}\nTEST_END\n\nTEST_BEGIN(test_nstime_init2)\n{\n\tnstime_t nst;\n\n\tnstime_init2(&nst, 42, 43);\n\tassert_u64_eq(nstime_sec(&nst), 42, \"sec incorrectly read\");\n\tassert_u64_eq(nstime_nsec(&nst), 43, \"nsec incorrectly read\");\n}\nTEST_END\n\nTEST_BEGIN(test_nstime_copy)\n{\n\tnstime_t nsta, nstb;\n\n\tnstime_init2(&nsta, 42, 43);\n\tnstime_init(&nstb, 0);\n\tnstime_copy(&nstb, &nsta);\n\tassert_u64_eq(nstime_sec(&nstb), 42, \"sec incorrectly copied\");\n\tassert_u64_eq(nstime_nsec(&nstb), 43, \"nsec incorrectly copied\");\n}\nTEST_END\n\nTEST_BEGIN(test_nstime_compare)\n{\n\tnstime_t nsta, nstb;\n\n\tnstime_init2(&nsta, 42, 43);\n\tnstime_copy(&nstb, &nsta);\n\tassert_d_eq(nstime_compare(&nsta, &nstb), 0, \"Times should be equal\");\n\tassert_d_eq(nstime_compare(&nstb, &nsta), 0, \"Times should be equal\");\n\n\tnstime_init2(&nstb, 42, 42);\n\tassert_d_eq(nstime_compare(&nsta, &nstb), 1,\n\t    \"nsta should be greater than nstb\");\n\tassert_d_eq(nstime_compare(&nstb, &nsta), -1,\n\t    \"nstb should be less than nsta\");\n\n\tnstime_init2(&nstb, 42, 44);\n\tassert_d_eq(nstime_compare(&nsta, &nstb), -1,\n\t    \"nsta should be less than nstb\");\n\tassert_d_eq(nstime_compare(&nstb, &nsta), 1,\n\t    \"nstb should be greater than nsta\");\n\n\tnstime_init2(&nstb, 41, BILLION - 1);\n\tassert_d_eq(nstime_compare(&nsta, &nstb), 1,\n\t    \"nsta should be greater than nstb\");\n\tassert_d_eq(nstime_compare(&nstb, &nsta), -1,\n\t    \"nstb should be less than nsta\");\n\n\tnstime_init2(&nstb, 43, 0);\n\tassert_d_eq(nstime_compare(&nsta, &nstb), -1,\n\t    \"nsta should be less than nstb\");\n\tassert_d_eq(nstime_compare(&nstb, &nsta), 1,\n\t    \"nstb should be greater than nsta\");\n}\nTEST_END\n\nTEST_BEGIN(test_nstime_add)\n{\n\tnstime_t nsta, nstb;\n\n\tnstime_init2(&nsta, 42, 43);\n\tnstime_copy(&nstb, &nsta);\n\tnstime_add(&nsta, &nstb);\n\tnstime_init2(&nstb, 84, 86);\n\tassert_d_eq(nstime_compare(&nsta, &nstb), 0,\n\t    \"Incorrect addition result\");\n\n\tnstime_init2(&nsta, 42, BILLION - 1);\n\tnstime_copy(&nstb, &nsta);\n\tnstime_add(&nsta, &nstb);\n\tnstime_init2(&nstb, 85, BILLION - 2);\n\tassert_d_eq(nstime_compare(&nsta, &nstb), 0,\n\t    \"Incorrect addition result\");\n}\nTEST_END\n\nTEST_BEGIN(test_nstime_subtract)\n{\n\tnstime_t nsta, nstb;\n\n\tnstime_init2(&nsta, 42, 43);\n\tnstime_copy(&nstb, &nsta);\n\tnstime_subtract(&nsta, &nstb);\n\tnstime_init(&nstb, 0);\n\tassert_d_eq(nstime_compare(&nsta, &nstb), 0,\n\t    \"Incorrect subtraction result\");\n\n\tnstime_init2(&nsta, 42, 43);\n\tnstime_init2(&nstb, 41, 44);\n\tnstime_subtract(&nsta, &nstb);\n\tnstime_init2(&nstb, 0, BILLION - 1);\n\tassert_d_eq(nstime_compare(&nsta, &nstb), 0,\n\t    \"Incorrect subtraction result\");\n}\nTEST_END\n\nTEST_BEGIN(test_nstime_imultiply)\n{\n\tnstime_t nsta, nstb;\n\n\tnstime_init2(&nsta, 42, 43);\n\tnstime_imultiply(&nsta, 10);\n\tnstime_init2(&nstb, 420, 430);\n\tassert_d_eq(nstime_compare(&nsta, &nstb), 0,\n\t    \"Incorrect multiplication result\");\n\n\tnstime_init2(&nsta, 42, 666666666);\n\tnstime_imultiply(&nsta, 3);\n\tnstime_init2(&nstb, 127, 999999998);\n\tassert_d_eq(nstime_compare(&nsta, &nstb), 0,\n\t    \"Incorrect multiplication result\");\n}\nTEST_END\n\nTEST_BEGIN(test_nstime_idivide)\n{\n\tnstime_t nsta, nstb;\n\n\tnstime_init2(&nsta, 42, 43);\n\tnstime_copy(&nstb, &nsta);\n\tnstime_imultiply(&nsta, 10);\n\tnstime_idivide(&nsta, 10);\n\tassert_d_eq(nstime_compare(&nsta, &nstb), 0,\n\t    \"Incorrect division result\");\n\n\tnstime_init2(&nsta, 42, 666666666);\n\tnstime_copy(&nstb, &nsta);\n\tnstime_imultiply(&nsta, 3);\n\tnstime_idivide(&nsta, 3);\n\tassert_d_eq(nstime_compare(&nsta, &nstb), 0,\n\t    \"Incorrect division result\");\n}\nTEST_END\n\nTEST_BEGIN(test_nstime_divide)\n{\n\tnstime_t nsta, nstb, nstc;\n\n\tnstime_init2(&nsta, 42, 43);\n\tnstime_copy(&nstb, &nsta);\n\tnstime_imultiply(&nsta, 10);\n\tassert_u64_eq(nstime_divide(&nsta, &nstb), 10,\n\t    \"Incorrect division result\");\n\n\tnstime_init2(&nsta, 42, 43);\n\tnstime_copy(&nstb, &nsta);\n\tnstime_imultiply(&nsta, 10);\n\tnstime_init(&nstc, 1);\n\tnstime_add(&nsta, &nstc);\n\tassert_u64_eq(nstime_divide(&nsta, &nstb), 10,\n\t    \"Incorrect division result\");\n\n\tnstime_init2(&nsta, 42, 43);\n\tnstime_copy(&nstb, &nsta);\n\tnstime_imultiply(&nsta, 10);\n\tnstime_init(&nstc, 1);\n\tnstime_subtract(&nsta, &nstc);\n\tassert_u64_eq(nstime_divide(&nsta, &nstb), 9,\n\t    \"Incorrect division result\");\n}\nTEST_END\n\nTEST_BEGIN(test_nstime_update)\n{\n\tnstime_t nst;\n\n\tnstime_init(&nst, 0);\n\n\tassert_false(nstime_update(&nst), \"Basic time update failed.\");\n\n\t/* Only Rip Van Winkle sleeps this long. */\n\t{\n\t\tnstime_t addend;\n\t\tnstime_init2(&addend, 631152000, 0);\n\t\tnstime_add(&nst, &addend);\n\t}\n\t{\n\t\tnstime_t nst0;\n\t\tnstime_copy(&nst0, &nst);\n\t\tassert_true(nstime_update(&nst),\n\t\t    \"Update should detect time roll-back.\");\n\t\tassert_d_eq(nstime_compare(&nst, &nst0), 0,\n\t\t    \"Time should not have been modified\");\n\t}\n\n}\nTEST_END\n\nint\nmain(void)\n{\n\n\treturn (test(\n\t    test_nstime_init,\n\t    test_nstime_init2,\n\t    test_nstime_copy,\n\t    test_nstime_compare,\n\t    test_nstime_add,\n\t    test_nstime_subtract,\n\t    test_nstime_imultiply,\n\t    test_nstime_idivide,\n\t    test_nstime_divide,\n\t    test_nstime_update));\n}\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/deps/jemalloc/test/unit/ph.c",
    "content": "#include \"test/jemalloc_test.h\"\n\ntypedef struct node_s node_t;\n\nstruct node_s {\n#define\tNODE_MAGIC 0x9823af7e\n\tuint32_t magic;\n\tphn(node_t) link;\n\tuint64_t key;\n};\n\nstatic int\nnode_cmp(const node_t *a, const node_t *b)\n{\n\tint ret;\n\n\tret = (a->key > b->key) - (a->key < b->key);\n\tif (ret == 0) {\n\t\t/*\n\t\t * Duplicates are not allowed in the heap, so force an\n\t\t * arbitrary ordering for non-identical items with equal keys.\n\t\t */\n\t\tret = (((uintptr_t)a) > ((uintptr_t)b))\n\t\t    - (((uintptr_t)a) < ((uintptr_t)b));\n\t}\n\treturn (ret);\n}\n\nstatic int\nnode_cmp_magic(const node_t *a, const node_t *b) {\n\n\tassert_u32_eq(a->magic, NODE_MAGIC, \"Bad magic\");\n\tassert_u32_eq(b->magic, NODE_MAGIC, \"Bad magic\");\n\n\treturn (node_cmp(a, b));\n}\n\ntypedef ph(node_t) heap_t;\nph_gen(static, heap_, heap_t, node_t, link, node_cmp_magic);\n\nstatic void\nnode_print(const node_t *node, unsigned depth)\n{\n\tunsigned i;\n\tnode_t *leftmost_child, *sibling;\n\n\tfor (i = 0; i < depth; i++)\n\t\tmalloc_printf(\"\\t\");\n\tmalloc_printf(\"%2\"FMTu64\"\\n\", node->key);\n\n\tleftmost_child = phn_lchild_get(node_t, link, node);\n\tif (leftmost_child == NULL)\n\t\treturn;\n\tnode_print(leftmost_child, depth + 1);\n\n\tfor (sibling = phn_next_get(node_t, link, leftmost_child); sibling !=\n\t    NULL; sibling = phn_next_get(node_t, link, sibling)) {\n\t\tnode_print(sibling, depth + 1);\n\t}\n}\n\nstatic void\nheap_print(const heap_t *heap)\n{\n\tnode_t *auxelm;\n\n\tmalloc_printf(\"vvv heap %p vvv\\n\", heap);\n\tif (heap->ph_root == NULL)\n\t\tgoto label_return;\n\n\tnode_print(heap->ph_root, 0);\n\n\tfor (auxelm = phn_next_get(node_t, link, heap->ph_root); auxelm != NULL;\n\t    auxelm = phn_next_get(node_t, link, auxelm)) {\n\t\tassert_ptr_eq(phn_next_get(node_t, link, phn_prev_get(node_t,\n\t\t    link, auxelm)), auxelm,\n\t\t    \"auxelm's prev doesn't link to auxelm\");\n\t\tnode_print(auxelm, 0);\n\t}\n\nlabel_return:\n\tmalloc_printf(\"^^^ heap %p ^^^\\n\", heap);\n}\n\nstatic unsigned\nnode_validate(const node_t *node, const node_t *parent)\n{\n\tunsigned nnodes = 1;\n\tnode_t *leftmost_child, *sibling;\n\n\tif (parent != NULL) {\n\t\tassert_d_ge(node_cmp_magic(node, parent), 0,\n\t\t    \"Child is less than parent\");\n\t}\n\n\tleftmost_child = phn_lchild_get(node_t, link, node);\n\tif (leftmost_child == NULL)\n\t\treturn (nnodes);\n\tassert_ptr_eq((void *)phn_prev_get(node_t, link, leftmost_child),\n\t    (void *)node, \"Leftmost child does not link to node\");\n\tnnodes += node_validate(leftmost_child, node);\n\n\tfor (sibling = phn_next_get(node_t, link, leftmost_child); sibling !=\n\t    NULL; sibling = phn_next_get(node_t, link, sibling)) {\n\t\tassert_ptr_eq(phn_next_get(node_t, link, phn_prev_get(node_t,\n\t\t    link, sibling)), sibling,\n\t\t    \"sibling's prev doesn't link to sibling\");\n\t\tnnodes += node_validate(sibling, node);\n\t}\n\treturn (nnodes);\n}\n\nstatic unsigned\nheap_validate(const heap_t *heap)\n{\n\tunsigned nnodes = 0;\n\tnode_t *auxelm;\n\n\tif (heap->ph_root == NULL)\n\t\tgoto label_return;\n\n\tnnodes += node_validate(heap->ph_root, NULL);\n\n\tfor (auxelm = phn_next_get(node_t, link, heap->ph_root); auxelm != NULL;\n\t    auxelm = phn_next_get(node_t, link, auxelm)) {\n\t\tassert_ptr_eq(phn_next_get(node_t, link, phn_prev_get(node_t,\n\t\t    link, auxelm)), auxelm,\n\t\t    \"auxelm's prev doesn't link to auxelm\");\n\t\tnnodes += node_validate(auxelm, NULL);\n\t}\n\nlabel_return:\n\tif (false)\n\t\theap_print(heap);\n\treturn (nnodes);\n}\n\nTEST_BEGIN(test_ph_empty)\n{\n\theap_t heap;\n\n\theap_new(&heap);\n\tassert_true(heap_empty(&heap), \"Heap should be empty\");\n\tassert_ptr_null(heap_first(&heap), \"Unexpected node\");\n}\nTEST_END\n\nstatic void\nnode_remove(heap_t *heap, node_t *node)\n{\n\n\theap_remove(heap, node);\n\n\tnode->magic = 0;\n}\n\nstatic node_t *\nnode_remove_first(heap_t *heap)\n{\n\tnode_t *node = heap_remove_first(heap);\n\tnode->magic = 0;\n\treturn (node);\n}\n\nTEST_BEGIN(test_ph_random)\n{\n#define\tNNODES 25\n#define\tNBAGS 250\n#define\tSEED 42\n\tsfmt_t *sfmt;\n\tuint64_t bag[NNODES];\n\theap_t heap;\n\tnode_t nodes[NNODES];\n\tunsigned i, j, k;\n\n\tsfmt = init_gen_rand(SEED);\n\tfor (i = 0; i < NBAGS; i++) {\n\t\tswitch (i) {\n\t\tcase 0:\n\t\t\t/* Insert in order. */\n\t\t\tfor (j = 0; j < NNODES; j++)\n\t\t\t\tbag[j] = j;\n\t\t\tbreak;\n\t\tcase 1:\n\t\t\t/* Insert in reverse order. */\n\t\t\tfor (j = 0; j < NNODES; j++)\n\t\t\t\tbag[j] = NNODES - j - 1;\n\t\t\tbreak;\n\t\tdefault:\n\t\t\tfor (j = 0; j < NNODES; j++)\n\t\t\t\tbag[j] = gen_rand64_range(sfmt, NNODES);\n\t\t}\n\n\t\tfor (j = 1; j <= NNODES; j++) {\n\t\t\t/* Initialize heap and nodes. */\n\t\t\theap_new(&heap);\n\t\t\tassert_u_eq(heap_validate(&heap), 0,\n\t\t\t    \"Incorrect node count\");\n\t\t\tfor (k = 0; k < j; k++) {\n\t\t\t\tnodes[k].magic = NODE_MAGIC;\n\t\t\t\tnodes[k].key = bag[k];\n\t\t\t}\n\n\t\t\t/* Insert nodes. */\n\t\t\tfor (k = 0; k < j; k++) {\n\t\t\t\theap_insert(&heap, &nodes[k]);\n\t\t\t\tif (i % 13 == 12) {\n\t\t\t\t\t/* Trigger merging. */\n\t\t\t\t\tassert_ptr_not_null(heap_first(&heap),\n\t\t\t\t\t    \"Heap should not be empty\");\n\t\t\t\t}\n\t\t\t\tassert_u_eq(heap_validate(&heap), k + 1,\n\t\t\t\t    \"Incorrect node count\");\n\t\t\t}\n\n\t\t\tassert_false(heap_empty(&heap),\n\t\t\t    \"Heap should not be empty\");\n\n\t\t\t/* Remove nodes. */\n\t\t\tswitch (i % 4) {\n\t\t\tcase 0:\n\t\t\t\tfor (k = 0; k < j; k++) {\n\t\t\t\t\tassert_u_eq(heap_validate(&heap), j - k,\n\t\t\t\t\t    \"Incorrect node count\");\n\t\t\t\t\tnode_remove(&heap, &nodes[k]);\n\t\t\t\t\tassert_u_eq(heap_validate(&heap), j - k\n\t\t\t\t\t    - 1, \"Incorrect node count\");\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\tcase 1:\n\t\t\t\tfor (k = j; k > 0; k--) {\n\t\t\t\t\tnode_remove(&heap, &nodes[k-1]);\n\t\t\t\t\tassert_u_eq(heap_validate(&heap), k - 1,\n\t\t\t\t\t    \"Incorrect node count\");\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\tcase 2: {\n\t\t\t\tnode_t *prev = NULL;\n\t\t\t\tfor (k = 0; k < j; k++) {\n\t\t\t\t\tnode_t *node = node_remove_first(&heap);\n\t\t\t\t\tassert_u_eq(heap_validate(&heap), j - k\n\t\t\t\t\t    - 1, \"Incorrect node count\");\n\t\t\t\t\tif (prev != NULL) {\n\t\t\t\t\t\tassert_d_ge(node_cmp(node,\n\t\t\t\t\t\t    prev), 0,\n\t\t\t\t\t\t    \"Bad removal order\");\n\t\t\t\t\t}\n\t\t\t\t\tprev = node;\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\t} case 3: {\n\t\t\t\tnode_t *prev = NULL;\n\t\t\t\tfor (k = 0; k < j; k++) {\n\t\t\t\t\tnode_t *node = heap_first(&heap);\n\t\t\t\t\tassert_u_eq(heap_validate(&heap), j - k,\n\t\t\t\t\t    \"Incorrect node count\");\n\t\t\t\t\tif (prev != NULL) {\n\t\t\t\t\t\tassert_d_ge(node_cmp(node,\n\t\t\t\t\t\t    prev), 0,\n\t\t\t\t\t\t    \"Bad removal order\");\n\t\t\t\t\t}\n\t\t\t\t\tnode_remove(&heap, node);\n\t\t\t\t\tassert_u_eq(heap_validate(&heap), j - k\n\t\t\t\t\t    - 1, \"Incorrect node count\");\n\t\t\t\t\tprev = node;\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\t} default:\n\t\t\t\tnot_reached();\n\t\t\t}\n\n\t\t\tassert_ptr_null(heap_first(&heap),\n\t\t\t    \"Heap should be empty\");\n\t\t\tassert_true(heap_empty(&heap), \"Heap should be empty\");\n\t\t}\n\t}\n\tfini_gen_rand(sfmt);\n#undef NNODES\n#undef SEED\n}\nTEST_END\n\nint\nmain(void)\n{\n\n\treturn (test(\n\t    test_ph_empty,\n\t    test_ph_random));\n}\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/deps/jemalloc/test/unit/prng.c",
    "content": "#include \"test/jemalloc_test.h\"\n\nTEST_BEGIN(test_prng_lg_range)\n{\n\tuint64_t sa, sb, ra, rb;\n\tunsigned lg_range;\n\n\tsa = 42;\n\tra = prng_lg_range(&sa, 64);\n\tsa = 42;\n\trb = prng_lg_range(&sa, 64);\n\tassert_u64_eq(ra, rb,\n\t    \"Repeated generation should produce repeated results\");\n\n\tsb = 42;\n\trb = prng_lg_range(&sb, 64);\n\tassert_u64_eq(ra, rb,\n\t    \"Equivalent generation should produce equivalent results\");\n\n\tsa = 42;\n\tra = prng_lg_range(&sa, 64);\n\trb = prng_lg_range(&sa, 64);\n\tassert_u64_ne(ra, rb,\n\t    \"Full-width results must not immediately repeat\");\n\n\tsa = 42;\n\tra = prng_lg_range(&sa, 64);\n\tfor (lg_range = 63; lg_range > 0; lg_range--) {\n\t\tsb = 42;\n\t\trb = prng_lg_range(&sb, lg_range);\n\t\tassert_u64_eq((rb & (UINT64_C(0xffffffffffffffff) << lg_range)),\n\t\t    0, \"High order bits should be 0, lg_range=%u\", lg_range);\n\t\tassert_u64_eq(rb, (ra >> (64 - lg_range)),\n\t\t    \"Expected high order bits of full-width result, \"\n\t\t    \"lg_range=%u\", lg_range);\n\t}\n}\nTEST_END\n\nTEST_BEGIN(test_prng_range)\n{\n\tuint64_t range;\n#define\tMAX_RANGE\t10000000\n#define\tRANGE_STEP\t97\n#define\tNREPS\t\t10\n\n\tfor (range = 2; range < MAX_RANGE; range += RANGE_STEP) {\n\t\tuint64_t s;\n\t\tunsigned rep;\n\n\t\ts = range;\n\t\tfor (rep = 0; rep < NREPS; rep++) {\n\t\t\tuint64_t r = prng_range(&s, range);\n\n\t\t\tassert_u64_lt(r, range, \"Out of range\");\n\t\t}\n\t}\n}\nTEST_END\n\nint\nmain(void)\n{\n\n\treturn (test(\n\t    test_prng_lg_range,\n\t    test_prng_range));\n}\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/deps/jemalloc/test/unit/prof_accum.c",
    "content": "#include \"test/jemalloc_test.h\"\n\n#define\tNTHREADS\t\t4\n#define\tNALLOCS_PER_THREAD\t50\n#define\tDUMP_INTERVAL\t\t1\n#define\tBT_COUNT_CHECK_INTERVAL\t5\n\n#ifdef JEMALLOC_PROF\nconst char *malloc_conf =\n    \"prof:true,prof_accum:true,prof_active:false,lg_prof_sample:0\";\n#endif\n\nstatic int\nprof_dump_open_intercept(bool propagate_err, const char *filename)\n{\n\tint fd;\n\n\tfd = open(\"/dev/null\", O_WRONLY);\n\tassert_d_ne(fd, -1, \"Unexpected open() failure\");\n\n\treturn (fd);\n}\n\nstatic void *\nalloc_from_permuted_backtrace(unsigned thd_ind, unsigned iteration)\n{\n\n\treturn (btalloc(1, thd_ind*NALLOCS_PER_THREAD + iteration));\n}\n\nstatic void *\nthd_start(void *varg)\n{\n\tunsigned thd_ind = *(unsigned *)varg;\n\tsize_t bt_count_prev, bt_count;\n\tunsigned i_prev, i;\n\n\ti_prev = 0;\n\tbt_count_prev = 0;\n\tfor (i = 0; i < NALLOCS_PER_THREAD; i++) {\n\t\tvoid *p = alloc_from_permuted_backtrace(thd_ind, i);\n\t\tdallocx(p, 0);\n\t\tif (i % DUMP_INTERVAL == 0) {\n\t\t\tassert_d_eq(mallctl(\"prof.dump\", NULL, NULL, NULL, 0),\n\t\t\t    0, \"Unexpected error while dumping heap profile\");\n\t\t}\n\n\t\tif (i % BT_COUNT_CHECK_INTERVAL == 0 ||\n\t\t    i+1 == NALLOCS_PER_THREAD) {\n\t\t\tbt_count = prof_bt_count();\n\t\t\tassert_zu_le(bt_count_prev+(i-i_prev), bt_count,\n\t\t\t    \"Expected larger backtrace count increase\");\n\t\t\ti_prev = i;\n\t\t\tbt_count_prev = bt_count;\n\t\t}\n\t}\n\n\treturn (NULL);\n}\n\nTEST_BEGIN(test_idump)\n{\n\tbool active;\n\tthd_t thds[NTHREADS];\n\tunsigned thd_args[NTHREADS];\n\tunsigned i;\n\n\ttest_skip_if(!config_prof);\n\n\tactive = true;\n\tassert_d_eq(mallctl(\"prof.active\", NULL, NULL, &active, sizeof(active)),\n\t    0, \"Unexpected mallctl failure while activating profiling\");\n\n\tprof_dump_open = prof_dump_open_intercept;\n\n\tfor (i = 0; i < NTHREADS; i++) {\n\t\tthd_args[i] = i;\n\t\tthd_create(&thds[i], thd_start, (void *)&thd_args[i]);\n\t}\n\tfor (i = 0; i < NTHREADS; i++)\n\t\tthd_join(thds[i], NULL);\n}\nTEST_END\n\nint\nmain(void)\n{\n\n\treturn (test(\n\t    test_idump));\n}\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/deps/jemalloc/test/unit/prof_active.c",
    "content": "#include \"test/jemalloc_test.h\"\n\n#ifdef JEMALLOC_PROF\nconst char *malloc_conf =\n    \"prof:true,prof_thread_active_init:false,lg_prof_sample:0\";\n#endif\n\nstatic void\nmallctl_bool_get(const char *name, bool expected, const char *func, int line)\n{\n\tbool old;\n\tsize_t sz;\n\n\tsz = sizeof(old);\n\tassert_d_eq(mallctl(name, &old, &sz, NULL, 0), 0,\n\t    \"%s():%d: Unexpected mallctl failure reading %s\", func, line, name);\n\tassert_b_eq(old, expected, \"%s():%d: Unexpected %s value\", func, line,\n\t    name);\n}\n\nstatic void\nmallctl_bool_set(const char *name, bool old_expected, bool val_new,\n    const char *func, int line)\n{\n\tbool old;\n\tsize_t sz;\n\n\tsz = sizeof(old);\n\tassert_d_eq(mallctl(name, &old, &sz, &val_new, sizeof(val_new)), 0,\n\t    \"%s():%d: Unexpected mallctl failure reading/writing %s\", func,\n\t    line, name);\n\tassert_b_eq(old, old_expected, \"%s():%d: Unexpected %s value\", func,\n\t    line, name);\n}\n\nstatic void\nmallctl_prof_active_get_impl(bool prof_active_old_expected, const char *func,\n    int line)\n{\n\n\tmallctl_bool_get(\"prof.active\", prof_active_old_expected, func, line);\n}\n#define\tmallctl_prof_active_get(a)\t\t\t\t\t\\\n\tmallctl_prof_active_get_impl(a, __func__, __LINE__)\n\nstatic void\nmallctl_prof_active_set_impl(bool prof_active_old_expected,\n    bool prof_active_new, const char *func, int line)\n{\n\n\tmallctl_bool_set(\"prof.active\", prof_active_old_expected,\n\t    prof_active_new, func, line);\n}\n#define\tmallctl_prof_active_set(a, b)\t\t\t\t\t\\\n\tmallctl_prof_active_set_impl(a, b, __func__, __LINE__)\n\nstatic void\nmallctl_thread_prof_active_get_impl(bool thread_prof_active_old_expected,\n    const char *func, int line)\n{\n\n\tmallctl_bool_get(\"thread.prof.active\", thread_prof_active_old_expected,\n\t    func, line);\n}\n#define\tmallctl_thread_prof_active_get(a)\t\t\t\t\\\n\tmallctl_thread_prof_active_get_impl(a, __func__, __LINE__)\n\nstatic void\nmallctl_thread_prof_active_set_impl(bool thread_prof_active_old_expected,\n    bool thread_prof_active_new, const char *func, int line)\n{\n\n\tmallctl_bool_set(\"thread.prof.active\", thread_prof_active_old_expected,\n\t    thread_prof_active_new, func, line);\n}\n#define\tmallctl_thread_prof_active_set(a, b)\t\t\t\t\\\n\tmallctl_thread_prof_active_set_impl(a, b, __func__, __LINE__)\n\nstatic void\nprof_sampling_probe_impl(bool expect_sample, const char *func, int line)\n{\n\tvoid *p;\n\tsize_t expected_backtraces = expect_sample ? 1 : 0;\n\n\tassert_zu_eq(prof_bt_count(), 0, \"%s():%d: Expected 0 backtraces\", func,\n\t    line);\n\tp = mallocx(1, 0);\n\tassert_ptr_not_null(p, \"Unexpected mallocx() failure\");\n\tassert_zu_eq(prof_bt_count(), expected_backtraces,\n\t    \"%s():%d: Unexpected backtrace count\", func, line);\n\tdallocx(p, 0);\n}\n#define\tprof_sampling_probe(a)\t\t\t\t\t\t\\\n\tprof_sampling_probe_impl(a, __func__, __LINE__)\n\nTEST_BEGIN(test_prof_active)\n{\n\n\ttest_skip_if(!config_prof);\n\n\tmallctl_prof_active_get(true);\n\tmallctl_thread_prof_active_get(false);\n\n\tmallctl_prof_active_set(true, true);\n\tmallctl_thread_prof_active_set(false, false);\n\t/* prof.active, !thread.prof.active. */\n\tprof_sampling_probe(false);\n\n\tmallctl_prof_active_set(true, false);\n\tmallctl_thread_prof_active_set(false, false);\n\t/* !prof.active, !thread.prof.active. */\n\tprof_sampling_probe(false);\n\n\tmallctl_prof_active_set(false, false);\n\tmallctl_thread_prof_active_set(false, true);\n\t/* !prof.active, thread.prof.active. */\n\tprof_sampling_probe(false);\n\n\tmallctl_prof_active_set(false, true);\n\tmallctl_thread_prof_active_set(true, true);\n\t/* prof.active, thread.prof.active. */\n\tprof_sampling_probe(true);\n\n\t/* Restore settings. */\n\tmallctl_prof_active_set(true, true);\n\tmallctl_thread_prof_active_set(true, false);\n}\nTEST_END\n\nint\nmain(void)\n{\n\n\treturn (test(\n\t    test_prof_active));\n}\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/deps/jemalloc/test/unit/prof_gdump.c",
    "content": "#include \"test/jemalloc_test.h\"\n\n#ifdef JEMALLOC_PROF\nconst char *malloc_conf = \"prof:true,prof_active:false,prof_gdump:true\";\n#endif\n\nstatic bool did_prof_dump_open;\n\nstatic int\nprof_dump_open_intercept(bool propagate_err, const char *filename)\n{\n\tint fd;\n\n\tdid_prof_dump_open = true;\n\n\tfd = open(\"/dev/null\", O_WRONLY);\n\tassert_d_ne(fd, -1, \"Unexpected open() failure\");\n\n\treturn (fd);\n}\n\nTEST_BEGIN(test_gdump)\n{\n\tbool active, gdump, gdump_old;\n\tvoid *p, *q, *r, *s;\n\tsize_t sz;\n\n\ttest_skip_if(!config_prof);\n\n\tactive = true;\n\tassert_d_eq(mallctl(\"prof.active\", NULL, NULL, &active, sizeof(active)),\n\t    0, \"Unexpected mallctl failure while activating profiling\");\n\n\tprof_dump_open = prof_dump_open_intercept;\n\n\tdid_prof_dump_open = false;\n\tp = mallocx(chunksize, 0);\n\tassert_ptr_not_null(p, \"Unexpected mallocx() failure\");\n\tassert_true(did_prof_dump_open, \"Expected a profile dump\");\n\n\tdid_prof_dump_open = false;\n\tq = mallocx(chunksize, 0);\n\tassert_ptr_not_null(q, \"Unexpected mallocx() failure\");\n\tassert_true(did_prof_dump_open, \"Expected a profile dump\");\n\n\tgdump = false;\n\tsz = sizeof(gdump_old);\n\tassert_d_eq(mallctl(\"prof.gdump\", &gdump_old, &sz, &gdump,\n\t    sizeof(gdump)), 0,\n\t    \"Unexpected mallctl failure while disabling prof.gdump\");\n\tassert(gdump_old);\n\tdid_prof_dump_open = false;\n\tr = mallocx(chunksize, 0);\n\tassert_ptr_not_null(q, \"Unexpected mallocx() failure\");\n\tassert_false(did_prof_dump_open, \"Unexpected profile dump\");\n\n\tgdump = true;\n\tsz = sizeof(gdump_old);\n\tassert_d_eq(mallctl(\"prof.gdump\", &gdump_old, &sz, &gdump,\n\t    sizeof(gdump)), 0,\n\t    \"Unexpected mallctl failure while enabling prof.gdump\");\n\tassert(!gdump_old);\n\tdid_prof_dump_open = false;\n\ts = mallocx(chunksize, 0);\n\tassert_ptr_not_null(q, \"Unexpected mallocx() failure\");\n\tassert_true(did_prof_dump_open, \"Expected a profile dump\");\n\n\tdallocx(p, 0);\n\tdallocx(q, 0);\n\tdallocx(r, 0);\n\tdallocx(s, 0);\n}\nTEST_END\n\nint\nmain(void)\n{\n\n\treturn (test(\n\t    test_gdump));\n}\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/deps/jemalloc/test/unit/prof_idump.c",
    "content": "#include \"test/jemalloc_test.h\"\n\n#ifdef JEMALLOC_PROF\nconst char *malloc_conf =\n    \"prof:true,prof_accum:true,prof_active:false,lg_prof_sample:0,\"\n    \"lg_prof_interval:0\";\n#endif\n\nstatic bool did_prof_dump_open;\n\nstatic int\nprof_dump_open_intercept(bool propagate_err, const char *filename)\n{\n\tint fd;\n\n\tdid_prof_dump_open = true;\n\n\tfd = open(\"/dev/null\", O_WRONLY);\n\tassert_d_ne(fd, -1, \"Unexpected open() failure\");\n\n\treturn (fd);\n}\n\nTEST_BEGIN(test_idump)\n{\n\tbool active;\n\tvoid *p;\n\n\ttest_skip_if(!config_prof);\n\n\tactive = true;\n\tassert_d_eq(mallctl(\"prof.active\", NULL, NULL, &active, sizeof(active)),\n\t    0, \"Unexpected mallctl failure while activating profiling\");\n\n\tprof_dump_open = prof_dump_open_intercept;\n\n\tdid_prof_dump_open = false;\n\tp = mallocx(1, 0);\n\tassert_ptr_not_null(p, \"Unexpected mallocx() failure\");\n\tdallocx(p, 0);\n\tassert_true(did_prof_dump_open, \"Expected a profile dump\");\n}\nTEST_END\n\nint\nmain(void)\n{\n\n\treturn (test(\n\t    test_idump));\n}\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/deps/jemalloc/test/unit/prof_reset.c",
    "content": "#include \"test/jemalloc_test.h\"\n\n#ifdef JEMALLOC_PROF\nconst char *malloc_conf =\n    \"prof:true,prof_active:false,lg_prof_sample:0\";\n#endif\n\nstatic int\nprof_dump_open_intercept(bool propagate_err, const char *filename)\n{\n\tint fd;\n\n\tfd = open(\"/dev/null\", O_WRONLY);\n\tassert_d_ne(fd, -1, \"Unexpected open() failure\");\n\n\treturn (fd);\n}\n\nstatic void\nset_prof_active(bool active)\n{\n\n\tassert_d_eq(mallctl(\"prof.active\", NULL, NULL, &active, sizeof(active)),\n\t    0, \"Unexpected mallctl failure\");\n}\n\nstatic size_t\nget_lg_prof_sample(void)\n{\n\tsize_t lg_prof_sample;\n\tsize_t sz = sizeof(size_t);\n\n\tassert_d_eq(mallctl(\"prof.lg_sample\", &lg_prof_sample, &sz, NULL, 0), 0,\n\t    \"Unexpected mallctl failure while reading profiling sample rate\");\n\treturn (lg_prof_sample);\n}\n\nstatic void\ndo_prof_reset(size_t lg_prof_sample)\n{\n\tassert_d_eq(mallctl(\"prof.reset\", NULL, NULL,\n\t    &lg_prof_sample, sizeof(size_t)), 0,\n\t    \"Unexpected mallctl failure while resetting profile data\");\n\tassert_zu_eq(lg_prof_sample, get_lg_prof_sample(),\n\t    \"Expected profile sample rate change\");\n}\n\nTEST_BEGIN(test_prof_reset_basic)\n{\n\tsize_t lg_prof_sample_orig, lg_prof_sample, lg_prof_sample_next;\n\tsize_t sz;\n\tunsigned i;\n\n\ttest_skip_if(!config_prof);\n\n\tsz = sizeof(size_t);\n\tassert_d_eq(mallctl(\"opt.lg_prof_sample\", &lg_prof_sample_orig, &sz,\n\t    NULL, 0), 0,\n\t    \"Unexpected mallctl failure while reading profiling sample rate\");\n\tassert_zu_eq(lg_prof_sample_orig, 0,\n\t    \"Unexpected profiling sample rate\");\n\tlg_prof_sample = get_lg_prof_sample();\n\tassert_zu_eq(lg_prof_sample_orig, lg_prof_sample,\n\t    \"Unexpected disagreement between \\\"opt.lg_prof_sample\\\" and \"\n\t    \"\\\"prof.lg_sample\\\"\");\n\n\t/* Test simple resets. */\n\tfor (i = 0; i < 2; i++) {\n\t\tassert_d_eq(mallctl(\"prof.reset\", NULL, NULL, NULL, 0), 0,\n\t\t    \"Unexpected mallctl failure while resetting profile data\");\n\t\tlg_prof_sample = get_lg_prof_sample();\n\t\tassert_zu_eq(lg_prof_sample_orig, lg_prof_sample,\n\t\t    \"Unexpected profile sample rate change\");\n\t}\n\n\t/* Test resets with prof.lg_sample changes. */\n\tlg_prof_sample_next = 1;\n\tfor (i = 0; i < 2; i++) {\n\t\tdo_prof_reset(lg_prof_sample_next);\n\t\tlg_prof_sample = get_lg_prof_sample();\n\t\tassert_zu_eq(lg_prof_sample, lg_prof_sample_next,\n\t\t    \"Expected profile sample rate change\");\n\t\tlg_prof_sample_next = lg_prof_sample_orig;\n\t}\n\n\t/* Make sure the test code restored prof.lg_sample. */\n\tlg_prof_sample = get_lg_prof_sample();\n\tassert_zu_eq(lg_prof_sample_orig, lg_prof_sample,\n\t    \"Unexpected disagreement between \\\"opt.lg_prof_sample\\\" and \"\n\t    \"\\\"prof.lg_sample\\\"\");\n}\nTEST_END\n\nbool prof_dump_header_intercepted = false;\nprof_cnt_t cnt_all_copy = {0, 0, 0, 0};\nstatic bool\nprof_dump_header_intercept(tsdn_t *tsdn, bool propagate_err,\n    const prof_cnt_t *cnt_all)\n{\n\n\tprof_dump_header_intercepted = true;\n\tmemcpy(&cnt_all_copy, cnt_all, sizeof(prof_cnt_t));\n\n\treturn (false);\n}\n\nTEST_BEGIN(test_prof_reset_cleanup)\n{\n\tvoid *p;\n\tprof_dump_header_t *prof_dump_header_orig;\n\n\ttest_skip_if(!config_prof);\n\n\tset_prof_active(true);\n\n\tassert_zu_eq(prof_bt_count(), 0, \"Expected 0 backtraces\");\n\tp = mallocx(1, 0);\n\tassert_ptr_not_null(p, \"Unexpected mallocx() failure\");\n\tassert_zu_eq(prof_bt_count(), 1, \"Expected 1 backtrace\");\n\n\tprof_dump_header_orig = prof_dump_header;\n\tprof_dump_header = prof_dump_header_intercept;\n\tassert_false(prof_dump_header_intercepted, \"Unexpected intercept\");\n\n\tassert_d_eq(mallctl(\"prof.dump\", NULL, NULL, NULL, 0),\n\t    0, \"Unexpected error while dumping heap profile\");\n\tassert_true(prof_dump_header_intercepted, \"Expected intercept\");\n\tassert_u64_eq(cnt_all_copy.curobjs, 1, \"Expected 1 allocation\");\n\n\tassert_d_eq(mallctl(\"prof.reset\", NULL, NULL, NULL, 0), 0,\n\t    \"Unexpected error while resetting heap profile data\");\n\tassert_d_eq(mallctl(\"prof.dump\", NULL, NULL, NULL, 0),\n\t    0, \"Unexpected error while dumping heap profile\");\n\tassert_u64_eq(cnt_all_copy.curobjs, 0, \"Expected 0 allocations\");\n\tassert_zu_eq(prof_bt_count(), 1, \"Expected 1 backtrace\");\n\n\tprof_dump_header = prof_dump_header_orig;\n\n\tdallocx(p, 0);\n\tassert_zu_eq(prof_bt_count(), 0, \"Expected 0 backtraces\");\n\n\tset_prof_active(false);\n}\nTEST_END\n\n#define\tNTHREADS\t\t4\n#define\tNALLOCS_PER_THREAD\t(1U << 13)\n#define\tOBJ_RING_BUF_COUNT\t1531\n#define\tRESET_INTERVAL\t\t(1U << 10)\n#define\tDUMP_INTERVAL\t\t3677\nstatic void *\nthd_start(void *varg)\n{\n\tunsigned thd_ind = *(unsigned *)varg;\n\tunsigned i;\n\tvoid *objs[OBJ_RING_BUF_COUNT];\n\n\tmemset(objs, 0, sizeof(objs));\n\n\tfor (i = 0; i < NALLOCS_PER_THREAD; i++) {\n\t\tif (i % RESET_INTERVAL == 0) {\n\t\t\tassert_d_eq(mallctl(\"prof.reset\", NULL, NULL, NULL, 0),\n\t\t\t    0, \"Unexpected error while resetting heap profile \"\n\t\t\t    \"data\");\n\t\t}\n\n\t\tif (i % DUMP_INTERVAL == 0) {\n\t\t\tassert_d_eq(mallctl(\"prof.dump\", NULL, NULL, NULL, 0),\n\t\t\t    0, \"Unexpected error while dumping heap profile\");\n\t\t}\n\n\t\t{\n\t\t\tvoid **pp = &objs[i % OBJ_RING_BUF_COUNT];\n\t\t\tif (*pp != NULL) {\n\t\t\t\tdallocx(*pp, 0);\n\t\t\t\t*pp = NULL;\n\t\t\t}\n\t\t\t*pp = btalloc(1, thd_ind*NALLOCS_PER_THREAD + i);\n\t\t\tassert_ptr_not_null(*pp,\n\t\t\t    \"Unexpected btalloc() failure\");\n\t\t}\n\t}\n\n\t/* Clean up any remaining objects. */\n\tfor (i = 0; i < OBJ_RING_BUF_COUNT; i++) {\n\t\tvoid **pp = &objs[i % OBJ_RING_BUF_COUNT];\n\t\tif (*pp != NULL) {\n\t\t\tdallocx(*pp, 0);\n\t\t\t*pp = NULL;\n\t\t}\n\t}\n\n\treturn (NULL);\n}\n\nTEST_BEGIN(test_prof_reset)\n{\n\tsize_t lg_prof_sample_orig;\n\tthd_t thds[NTHREADS];\n\tunsigned thd_args[NTHREADS];\n\tunsigned i;\n\tsize_t bt_count, tdata_count;\n\n\ttest_skip_if(!config_prof);\n\n\tbt_count = prof_bt_count();\n\tassert_zu_eq(bt_count, 0,\n\t    \"Unexpected pre-existing tdata structures\");\n\ttdata_count = prof_tdata_count();\n\n\tlg_prof_sample_orig = get_lg_prof_sample();\n\tdo_prof_reset(5);\n\n\tset_prof_active(true);\n\n\tfor (i = 0; i < NTHREADS; i++) {\n\t\tthd_args[i] = i;\n\t\tthd_create(&thds[i], thd_start, (void *)&thd_args[i]);\n\t}\n\tfor (i = 0; i < NTHREADS; i++)\n\t\tthd_join(thds[i], NULL);\n\n\tassert_zu_eq(prof_bt_count(), bt_count,\n\t    \"Unexpected bactrace count change\");\n\tassert_zu_eq(prof_tdata_count(), tdata_count,\n\t    \"Unexpected remaining tdata structures\");\n\n\tset_prof_active(false);\n\n\tdo_prof_reset(lg_prof_sample_orig);\n}\nTEST_END\n#undef NTHREADS\n#undef NALLOCS_PER_THREAD\n#undef OBJ_RING_BUF_COUNT\n#undef RESET_INTERVAL\n#undef DUMP_INTERVAL\n\n/* Test sampling at the same allocation site across resets. */\n#define\tNITER 10\nTEST_BEGIN(test_xallocx)\n{\n\tsize_t lg_prof_sample_orig;\n\tunsigned i;\n\tvoid *ptrs[NITER];\n\n\ttest_skip_if(!config_prof);\n\n\tlg_prof_sample_orig = get_lg_prof_sample();\n\tset_prof_active(true);\n\n\t/* Reset profiling. */\n\tdo_prof_reset(0);\n\n\tfor (i = 0; i < NITER; i++) {\n\t\tvoid *p;\n\t\tsize_t sz, nsz;\n\n\t\t/* Reset profiling. */\n\t\tdo_prof_reset(0);\n\n\t\t/* Allocate small object (which will be promoted). */\n\t\tp = ptrs[i] = mallocx(1, 0);\n\t\tassert_ptr_not_null(p, \"Unexpected mallocx() failure\");\n\n\t\t/* Reset profiling. */\n\t\tdo_prof_reset(0);\n\n\t\t/* Perform successful xallocx(). */\n\t\tsz = sallocx(p, 0);\n\t\tassert_zu_eq(xallocx(p, sz, 0, 0), sz,\n\t\t    \"Unexpected xallocx() failure\");\n\n\t\t/* Perform unsuccessful xallocx(). */\n\t\tnsz = nallocx(sz+1, 0);\n\t\tassert_zu_eq(xallocx(p, nsz, 0, 0), sz,\n\t\t    \"Unexpected xallocx() success\");\n\t}\n\n\tfor (i = 0; i < NITER; i++) {\n\t\t/* dallocx. */\n\t\tdallocx(ptrs[i], 0);\n\t}\n\n\tset_prof_active(false);\n\tdo_prof_reset(lg_prof_sample_orig);\n}\nTEST_END\n#undef NITER\n\nint\nmain(void)\n{\n\n\t/* Intercept dumping prior to running any tests. */\n\tprof_dump_open = prof_dump_open_intercept;\n\n\treturn (test(\n\t    test_prof_reset_basic,\n\t    test_prof_reset_cleanup,\n\t    test_prof_reset,\n\t    test_xallocx));\n}\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/deps/jemalloc/test/unit/prof_thread_name.c",
    "content": "#include \"test/jemalloc_test.h\"\n\n#ifdef JEMALLOC_PROF\nconst char *malloc_conf = \"prof:true,prof_active:false\";\n#endif\n\nstatic void\nmallctl_thread_name_get_impl(const char *thread_name_expected, const char *func,\n    int line)\n{\n\tconst char *thread_name_old;\n\tsize_t sz;\n\n\tsz = sizeof(thread_name_old);\n\tassert_d_eq(mallctl(\"thread.prof.name\", &thread_name_old, &sz, NULL, 0),\n\t    0, \"%s():%d: Unexpected mallctl failure reading thread.prof.name\",\n\t    func, line);\n\tassert_str_eq(thread_name_old, thread_name_expected,\n\t    \"%s():%d: Unexpected thread.prof.name value\", func, line);\n}\n#define\tmallctl_thread_name_get(a)\t\t\t\t\t\\\n\tmallctl_thread_name_get_impl(a, __func__, __LINE__)\n\nstatic void\nmallctl_thread_name_set_impl(const char *thread_name, const char *func,\n    int line)\n{\n\n\tassert_d_eq(mallctl(\"thread.prof.name\", NULL, NULL, &thread_name,\n\t    sizeof(thread_name)), 0,\n\t    \"%s():%d: Unexpected mallctl failure reading thread.prof.name\",\n\t    func, line);\n\tmallctl_thread_name_get_impl(thread_name, func, line);\n}\n#define\tmallctl_thread_name_set(a)\t\t\t\t\t\\\n\tmallctl_thread_name_set_impl(a, __func__, __LINE__)\n\nTEST_BEGIN(test_prof_thread_name_validation)\n{\n\tconst char *thread_name;\n\n\ttest_skip_if(!config_prof);\n\n\tmallctl_thread_name_get(\"\");\n\tmallctl_thread_name_set(\"hi there\");\n\n\t/* NULL input shouldn't be allowed. */\n\tthread_name = NULL;\n\tassert_d_eq(mallctl(\"thread.prof.name\", NULL, NULL, &thread_name,\n\t    sizeof(thread_name)), EFAULT,\n\t    \"Unexpected mallctl result writing \\\"%s\\\" to thread.prof.name\",\n\t    thread_name);\n\n\t/* '\\n' shouldn't be allowed. */\n\tthread_name = \"hi\\nthere\";\n\tassert_d_eq(mallctl(\"thread.prof.name\", NULL, NULL, &thread_name,\n\t    sizeof(thread_name)), EFAULT,\n\t    \"Unexpected mallctl result writing \\\"%s\\\" to thread.prof.name\",\n\t    thread_name);\n\n\t/* Simultaneous read/write shouldn't be allowed. */\n\t{\n\t\tconst char *thread_name_old;\n\t\tsize_t sz;\n\n\t\tsz = sizeof(thread_name_old);\n\t\tassert_d_eq(mallctl(\"thread.prof.name\", &thread_name_old, &sz,\n\t\t    &thread_name, sizeof(thread_name)), EPERM,\n\t\t    \"Unexpected mallctl result writing \\\"%s\\\" to \"\n\t\t    \"thread.prof.name\", thread_name);\n\t}\n\n\tmallctl_thread_name_set(\"\");\n}\nTEST_END\n\n#define\tNTHREADS\t4\n#define\tNRESET\t\t25\nstatic void *\nthd_start(void *varg)\n{\n\tunsigned thd_ind = *(unsigned *)varg;\n\tchar thread_name[16] = \"\";\n\tunsigned i;\n\n\tmalloc_snprintf(thread_name, sizeof(thread_name), \"thread %u\", thd_ind);\n\n\tmallctl_thread_name_get(\"\");\n\tmallctl_thread_name_set(thread_name);\n\n\tfor (i = 0; i < NRESET; i++) {\n\t\tassert_d_eq(mallctl(\"prof.reset\", NULL, NULL, NULL, 0), 0,\n\t\t    \"Unexpected error while resetting heap profile data\");\n\t\tmallctl_thread_name_get(thread_name);\n\t}\n\n\tmallctl_thread_name_set(thread_name);\n\tmallctl_thread_name_set(\"\");\n\n\treturn (NULL);\n}\n\nTEST_BEGIN(test_prof_thread_name_threaded)\n{\n\tthd_t thds[NTHREADS];\n\tunsigned thd_args[NTHREADS];\n\tunsigned i;\n\n\ttest_skip_if(!config_prof);\n\n\tfor (i = 0; i < NTHREADS; i++) {\n\t\tthd_args[i] = i;\n\t\tthd_create(&thds[i], thd_start, (void *)&thd_args[i]);\n\t}\n\tfor (i = 0; i < NTHREADS; i++)\n\t\tthd_join(thds[i], NULL);\n}\nTEST_END\n#undef NTHREADS\n#undef NRESET\n\nint\nmain(void)\n{\n\n\treturn (test(\n\t    test_prof_thread_name_validation,\n\t    test_prof_thread_name_threaded));\n}\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/deps/jemalloc/test/unit/ql.c",
    "content": "#include \"test/jemalloc_test.h\"\n\n/* Number of ring entries, in [2..26]. */\n#define\tNENTRIES 9\n\ntypedef struct list_s list_t;\ntypedef ql_head(list_t) list_head_t;\n\nstruct list_s {\n\tql_elm(list_t) link;\n\tchar id;\n};\n\nstatic void\ntest_empty_list(list_head_t *head)\n{\n\tlist_t *t;\n\tunsigned i;\n\n\tassert_ptr_null(ql_first(head), \"Unexpected element for empty list\");\n\tassert_ptr_null(ql_last(head, link),\n\t    \"Unexpected element for empty list\");\n\n\ti = 0;\n\tql_foreach(t, head, link) {\n\t\ti++;\n\t}\n\tassert_u_eq(i, 0, \"Unexpected element for empty list\");\n\n\ti = 0;\n\tql_reverse_foreach(t, head, link) {\n\t\ti++;\n\t}\n\tassert_u_eq(i, 0, \"Unexpected element for empty list\");\n}\n\nTEST_BEGIN(test_ql_empty)\n{\n\tlist_head_t head;\n\n\tql_new(&head);\n\ttest_empty_list(&head);\n}\nTEST_END\n\nstatic void\ninit_entries(list_t *entries, unsigned nentries)\n{\n\tunsigned i;\n\n\tfor (i = 0; i < nentries; i++) {\n\t\tentries[i].id = 'a' + i;\n\t\tql_elm_new(&entries[i], link);\n\t}\n}\n\nstatic void\ntest_entries_list(list_head_t *head, list_t *entries, unsigned nentries)\n{\n\tlist_t *t;\n\tunsigned i;\n\n\tassert_c_eq(ql_first(head)->id, entries[0].id, \"Element id mismatch\");\n\tassert_c_eq(ql_last(head, link)->id, entries[nentries-1].id,\n\t    \"Element id mismatch\");\n\n\ti = 0;\n\tql_foreach(t, head, link) {\n\t\tassert_c_eq(t->id, entries[i].id, \"Element id mismatch\");\n\t\ti++;\n\t}\n\n\ti = 0;\n\tql_reverse_foreach(t, head, link) {\n\t\tassert_c_eq(t->id, entries[nentries-i-1].id,\n\t\t    \"Element id mismatch\");\n\t\ti++;\n\t}\n\n\tfor (i = 0; i < nentries-1; i++) {\n\t\tt = ql_next(head, &entries[i], link);\n\t\tassert_c_eq(t->id, entries[i+1].id, \"Element id mismatch\");\n\t}\n\tassert_ptr_null(ql_next(head, &entries[nentries-1], link),\n\t    \"Unexpected element\");\n\n\tassert_ptr_null(ql_prev(head, &entries[0], link), \"Unexpected element\");\n\tfor (i = 1; i < nentries; i++) {\n\t\tt = ql_prev(head, &entries[i], link);\n\t\tassert_c_eq(t->id, entries[i-1].id, \"Element id mismatch\");\n\t}\n}\n\nTEST_BEGIN(test_ql_tail_insert)\n{\n\tlist_head_t head;\n\tlist_t entries[NENTRIES];\n\tunsigned i;\n\n\tql_new(&head);\n\tinit_entries(entries, sizeof(entries)/sizeof(list_t));\n\tfor (i = 0; i < NENTRIES; i++)\n\t\tql_tail_insert(&head, &entries[i], link);\n\n\ttest_entries_list(&head, entries, NENTRIES);\n}\nTEST_END\n\nTEST_BEGIN(test_ql_tail_remove)\n{\n\tlist_head_t head;\n\tlist_t entries[NENTRIES];\n\tunsigned i;\n\n\tql_new(&head);\n\tinit_entries(entries, sizeof(entries)/sizeof(list_t));\n\tfor (i = 0; i < NENTRIES; i++)\n\t\tql_tail_insert(&head, &entries[i], link);\n\n\tfor (i = 0; i < NENTRIES; i++) {\n\t\ttest_entries_list(&head, entries, NENTRIES-i);\n\t\tql_tail_remove(&head, list_t, link);\n\t}\n\ttest_empty_list(&head);\n}\nTEST_END\n\nTEST_BEGIN(test_ql_head_insert)\n{\n\tlist_head_t head;\n\tlist_t entries[NENTRIES];\n\tunsigned i;\n\n\tql_new(&head);\n\tinit_entries(entries, sizeof(entries)/sizeof(list_t));\n\tfor (i = 0; i < NENTRIES; i++)\n\t\tql_head_insert(&head, &entries[NENTRIES-i-1], link);\n\n\ttest_entries_list(&head, entries, NENTRIES);\n}\nTEST_END\n\nTEST_BEGIN(test_ql_head_remove)\n{\n\tlist_head_t head;\n\tlist_t entries[NENTRIES];\n\tunsigned i;\n\n\tql_new(&head);\n\tinit_entries(entries, sizeof(entries)/sizeof(list_t));\n\tfor (i = 0; i < NENTRIES; i++)\n\t\tql_head_insert(&head, &entries[NENTRIES-i-1], link);\n\n\tfor (i = 0; i < NENTRIES; i++) {\n\t\ttest_entries_list(&head, &entries[i], NENTRIES-i);\n\t\tql_head_remove(&head, list_t, link);\n\t}\n\ttest_empty_list(&head);\n}\nTEST_END\n\nTEST_BEGIN(test_ql_insert)\n{\n\tlist_head_t head;\n\tlist_t entries[8];\n\tlist_t *a, *b, *c, *d, *e, *f, *g, *h;\n\n\tql_new(&head);\n\tinit_entries(entries, sizeof(entries)/sizeof(list_t));\n\ta = &entries[0];\n\tb = &entries[1];\n\tc = &entries[2];\n\td = &entries[3];\n\te = &entries[4];\n\tf = &entries[5];\n\tg = &entries[6];\n\th = &entries[7];\n\n\t/*\n\t * ql_remove(), ql_before_insert(), and ql_after_insert() are used\n\t * internally by other macros that are already tested, so there's no\n\t * need to test them completely.  However, insertion/deletion from the\n\t * middle of lists is not otherwise tested; do so here.\n\t */\n\tql_tail_insert(&head, f, link);\n\tql_before_insert(&head, f, b, link);\n\tql_before_insert(&head, f, c, link);\n\tql_after_insert(f, h, link);\n\tql_after_insert(f, g, link);\n\tql_before_insert(&head, b, a, link);\n\tql_after_insert(c, d, link);\n\tql_before_insert(&head, f, e, link);\n\n\ttest_entries_list(&head, entries, sizeof(entries)/sizeof(list_t));\n}\nTEST_END\n\nint\nmain(void)\n{\n\n\treturn (test(\n\t    test_ql_empty,\n\t    test_ql_tail_insert,\n\t    test_ql_tail_remove,\n\t    test_ql_head_insert,\n\t    test_ql_head_remove,\n\t    test_ql_insert));\n}\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/deps/jemalloc/test/unit/qr.c",
    "content": "#include \"test/jemalloc_test.h\"\n\n/* Number of ring entries, in [2..26]. */\n#define\tNENTRIES 9\n/* Split index, in [1..NENTRIES). */\n#define\tSPLIT_INDEX 5\n\ntypedef struct ring_s ring_t;\n\nstruct ring_s {\n\tqr(ring_t) link;\n\tchar id;\n};\n\nstatic void\ninit_entries(ring_t *entries)\n{\n\tunsigned i;\n\n\tfor (i = 0; i < NENTRIES; i++) {\n\t\tqr_new(&entries[i], link);\n\t\tentries[i].id = 'a' + i;\n\t}\n}\n\nstatic void\ntest_independent_entries(ring_t *entries)\n{\n\tring_t *t;\n\tunsigned i, j;\n\n\tfor (i = 0; i < NENTRIES; i++) {\n\t\tj = 0;\n\t\tqr_foreach(t, &entries[i], link) {\n\t\t\tj++;\n\t\t}\n\t\tassert_u_eq(j, 1,\n\t\t    \"Iteration over single-element ring should visit precisely \"\n\t\t    \"one element\");\n\t}\n\tfor (i = 0; i < NENTRIES; i++) {\n\t\tj = 0;\n\t\tqr_reverse_foreach(t, &entries[i], link) {\n\t\t\tj++;\n\t\t}\n\t\tassert_u_eq(j, 1,\n\t\t    \"Iteration over single-element ring should visit precisely \"\n\t\t    \"one element\");\n\t}\n\tfor (i = 0; i < NENTRIES; i++) {\n\t\tt = qr_next(&entries[i], link);\n\t\tassert_ptr_eq(t, &entries[i],\n\t\t    \"Next element in single-element ring should be same as \"\n\t\t    \"current element\");\n\t}\n\tfor (i = 0; i < NENTRIES; i++) {\n\t\tt = qr_prev(&entries[i], link);\n\t\tassert_ptr_eq(t, &entries[i],\n\t\t    \"Previous element in single-element ring should be same as \"\n\t\t    \"current element\");\n\t}\n}\n\nTEST_BEGIN(test_qr_one)\n{\n\tring_t entries[NENTRIES];\n\n\tinit_entries(entries);\n\ttest_independent_entries(entries);\n}\nTEST_END\n\nstatic void\ntest_entries_ring(ring_t *entries)\n{\n\tring_t *t;\n\tunsigned i, j;\n\n\tfor (i = 0; i < NENTRIES; i++) {\n\t\tj = 0;\n\t\tqr_foreach(t, &entries[i], link) {\n\t\t\tassert_c_eq(t->id, entries[(i+j) % NENTRIES].id,\n\t\t\t    \"Element id mismatch\");\n\t\t\tj++;\n\t\t}\n\t}\n\tfor (i = 0; i < NENTRIES; i++) {\n\t\tj = 0;\n\t\tqr_reverse_foreach(t, &entries[i], link) {\n\t\t\tassert_c_eq(t->id, entries[(NENTRIES+i-j-1) %\n\t\t\t    NENTRIES].id, \"Element id mismatch\");\n\t\t\tj++;\n\t\t}\n\t}\n\tfor (i = 0; i < NENTRIES; i++) {\n\t\tt = qr_next(&entries[i], link);\n\t\tassert_c_eq(t->id, entries[(i+1) % NENTRIES].id,\n\t\t    \"Element id mismatch\");\n\t}\n\tfor (i = 0; i < NENTRIES; i++) {\n\t\tt = qr_prev(&entries[i], link);\n\t\tassert_c_eq(t->id, entries[(NENTRIES+i-1) % NENTRIES].id,\n\t\t    \"Element id mismatch\");\n\t}\n}\n\nTEST_BEGIN(test_qr_after_insert)\n{\n\tring_t entries[NENTRIES];\n\tunsigned i;\n\n\tinit_entries(entries);\n\tfor (i = 1; i < NENTRIES; i++)\n\t\tqr_after_insert(&entries[i - 1], &entries[i], link);\n\ttest_entries_ring(entries);\n}\nTEST_END\n\nTEST_BEGIN(test_qr_remove)\n{\n\tring_t entries[NENTRIES];\n\tring_t *t;\n\tunsigned i, j;\n\n\tinit_entries(entries);\n\tfor (i = 1; i < NENTRIES; i++)\n\t\tqr_after_insert(&entries[i - 1], &entries[i], link);\n\n\tfor (i = 0; i < NENTRIES; i++) {\n\t\tj = 0;\n\t\tqr_foreach(t, &entries[i], link) {\n\t\t\tassert_c_eq(t->id, entries[i+j].id,\n\t\t\t    \"Element id mismatch\");\n\t\t\tj++;\n\t\t}\n\t\tj = 0;\n\t\tqr_reverse_foreach(t, &entries[i], link) {\n\t\t\tassert_c_eq(t->id, entries[NENTRIES - 1 - j].id,\n\t\t\t\"Element id mismatch\");\n\t\t\tj++;\n\t\t}\n\t\tqr_remove(&entries[i], link);\n\t}\n\ttest_independent_entries(entries);\n}\nTEST_END\n\nTEST_BEGIN(test_qr_before_insert)\n{\n\tring_t entries[NENTRIES];\n\tring_t *t;\n\tunsigned i, j;\n\n\tinit_entries(entries);\n\tfor (i = 1; i < NENTRIES; i++)\n\t\tqr_before_insert(&entries[i - 1], &entries[i], link);\n\tfor (i = 0; i < NENTRIES; i++) {\n\t\tj = 0;\n\t\tqr_foreach(t, &entries[i], link) {\n\t\t\tassert_c_eq(t->id, entries[(NENTRIES+i-j) %\n\t\t\t    NENTRIES].id, \"Element id mismatch\");\n\t\t\tj++;\n\t\t}\n\t}\n\tfor (i = 0; i < NENTRIES; i++) {\n\t\tj = 0;\n\t\tqr_reverse_foreach(t, &entries[i], link) {\n\t\t\tassert_c_eq(t->id, entries[(i+j+1) % NENTRIES].id,\n\t\t\t    \"Element id mismatch\");\n\t\t\tj++;\n\t\t}\n\t}\n\tfor (i = 0; i < NENTRIES; i++) {\n\t\tt = qr_next(&entries[i], link);\n\t\tassert_c_eq(t->id, entries[(NENTRIES+i-1) % NENTRIES].id,\n\t\t    \"Element id mismatch\");\n\t}\n\tfor (i = 0; i < NENTRIES; i++) {\n\t\tt = qr_prev(&entries[i], link);\n\t\tassert_c_eq(t->id, entries[(i+1) % NENTRIES].id,\n\t\t    \"Element id mismatch\");\n\t}\n}\nTEST_END\n\nstatic void\ntest_split_entries(ring_t *entries)\n{\n\tring_t *t;\n\tunsigned i, j;\n\n\tfor (i = 0; i < NENTRIES; i++) {\n\t\tj = 0;\n\t\tqr_foreach(t, &entries[i], link) {\n\t\t\tif (i < SPLIT_INDEX) {\n\t\t\t\tassert_c_eq(t->id,\n\t\t\t\t    entries[(i+j) % SPLIT_INDEX].id,\n\t\t\t\t    \"Element id mismatch\");\n\t\t\t} else {\n\t\t\t\tassert_c_eq(t->id, entries[(i+j-SPLIT_INDEX) %\n\t\t\t\t    (NENTRIES-SPLIT_INDEX) + SPLIT_INDEX].id,\n\t\t\t\t    \"Element id mismatch\");\n\t\t\t}\n\t\t\tj++;\n\t\t}\n\t}\n}\n\nTEST_BEGIN(test_qr_meld_split)\n{\n\tring_t entries[NENTRIES];\n\tunsigned i;\n\n\tinit_entries(entries);\n\tfor (i = 1; i < NENTRIES; i++)\n\t\tqr_after_insert(&entries[i - 1], &entries[i], link);\n\n\tqr_split(&entries[0], &entries[SPLIT_INDEX], link);\n\ttest_split_entries(entries);\n\n\tqr_meld(&entries[0], &entries[SPLIT_INDEX], link);\n\ttest_entries_ring(entries);\n\n\tqr_meld(&entries[0], &entries[SPLIT_INDEX], link);\n\ttest_split_entries(entries);\n\n\tqr_split(&entries[0], &entries[SPLIT_INDEX], link);\n\ttest_entries_ring(entries);\n\n\tqr_split(&entries[0], &entries[0], link);\n\ttest_entries_ring(entries);\n\n\tqr_meld(&entries[0], &entries[0], link);\n\ttest_entries_ring(entries);\n}\nTEST_END\n\nint\nmain(void)\n{\n\n\treturn (test(\n\t    test_qr_one,\n\t    test_qr_after_insert,\n\t    test_qr_remove,\n\t    test_qr_before_insert,\n\t    test_qr_meld_split));\n}\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/deps/jemalloc/test/unit/quarantine.c",
    "content": "#include \"test/jemalloc_test.h\"\n\n#define\tQUARANTINE_SIZE\t\t8192\n#define\tSTRINGIFY_HELPER(x)\t#x\n#define\tSTRINGIFY(x)\t\tSTRINGIFY_HELPER(x)\n\n#ifdef JEMALLOC_FILL\nconst char *malloc_conf = \"abort:false,junk:true,redzone:true,quarantine:\"\n    STRINGIFY(QUARANTINE_SIZE);\n#endif\n\nvoid\nquarantine_clear(void)\n{\n\tvoid *p;\n\n\tp = mallocx(QUARANTINE_SIZE*2, 0);\n\tassert_ptr_not_null(p, \"Unexpected mallocx() failure\");\n\tdallocx(p, 0);\n}\n\nTEST_BEGIN(test_quarantine)\n{\n#define\tSZ\t\tZU(256)\n#define\tNQUARANTINED\t(QUARANTINE_SIZE/SZ)\n\tvoid *quarantined[NQUARANTINED+1];\n\tsize_t i, j;\n\n\ttest_skip_if(!config_fill);\n\n\tassert_zu_eq(nallocx(SZ, 0), SZ,\n\t    \"SZ=%zu does not precisely equal a size class\", SZ);\n\n\tquarantine_clear();\n\n\t/*\n\t * Allocate enough regions to completely fill the quarantine, plus one\n\t * more.  The last iteration occurs with a completely full quarantine,\n\t * but no regions should be drained from the quarantine until the last\n\t * deallocation occurs.  Therefore no region recycling should occur\n\t * until after this loop completes.\n\t */\n\tfor (i = 0; i < NQUARANTINED+1; i++) {\n\t\tvoid *p = mallocx(SZ, 0);\n\t\tassert_ptr_not_null(p, \"Unexpected mallocx() failure\");\n\t\tquarantined[i] = p;\n\t\tdallocx(p, 0);\n\t\tfor (j = 0; j < i; j++) {\n\t\t\tassert_ptr_ne(p, quarantined[j],\n\t\t\t    \"Quarantined region recycled too early; \"\n\t\t\t    \"i=%zu, j=%zu\", i, j);\n\t\t}\n\t}\n#undef NQUARANTINED\n#undef SZ\n}\nTEST_END\n\nstatic bool detected_redzone_corruption;\n\nstatic void\narena_redzone_corruption_replacement(void *ptr, size_t usize, bool after,\n    size_t offset, uint8_t byte)\n{\n\n\tdetected_redzone_corruption = true;\n}\n\nTEST_BEGIN(test_quarantine_redzone)\n{\n\tchar *s;\n\tarena_redzone_corruption_t *arena_redzone_corruption_orig;\n\n\ttest_skip_if(!config_fill);\n\n\tarena_redzone_corruption_orig = arena_redzone_corruption;\n\tarena_redzone_corruption = arena_redzone_corruption_replacement;\n\n\t/* Test underflow. */\n\tdetected_redzone_corruption = false;\n\ts = (char *)mallocx(1, 0);\n\tassert_ptr_not_null((void *)s, \"Unexpected mallocx() failure\");\n\ts[-1] = 0xbb;\n\tdallocx(s, 0);\n\tassert_true(detected_redzone_corruption,\n\t    \"Did not detect redzone corruption\");\n\n\t/* Test overflow. */\n\tdetected_redzone_corruption = false;\n\ts = (char *)mallocx(1, 0);\n\tassert_ptr_not_null((void *)s, \"Unexpected mallocx() failure\");\n\ts[sallocx(s, 0)] = 0xbb;\n\tdallocx(s, 0);\n\tassert_true(detected_redzone_corruption,\n\t    \"Did not detect redzone corruption\");\n\n\tarena_redzone_corruption = arena_redzone_corruption_orig;\n}\nTEST_END\n\nint\nmain(void)\n{\n\n\treturn (test(\n\t    test_quarantine,\n\t    test_quarantine_redzone));\n}\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/deps/jemalloc/test/unit/rb.c",
    "content": "#include \"test/jemalloc_test.h\"\n\n#define\trbtn_black_height(a_type, a_field, a_rbt, r_height) do {\t\\\n    a_type *rbp_bh_t;\t\t\t\t\t\t\t\\\n    for (rbp_bh_t = (a_rbt)->rbt_root, (r_height) = 0;\t\t\t\\\n\t rbp_bh_t != NULL;\t\t\t\t\t\t\\\n      rbp_bh_t = rbtn_left_get(a_type, a_field, rbp_bh_t)) {\t\t\\\n\tif (!rbtn_red_get(a_type, a_field, rbp_bh_t)) {\t\t\t\\\n\t    (r_height)++;\t\t\t\t\t\t\\\n\t}\t\t\t\t\t\t\t\t\\\n    }\t\t\t\t\t\t\t\t\t\\\n} while (0)\n\ntypedef struct node_s node_t;\n\nstruct node_s {\n#define\tNODE_MAGIC 0x9823af7e\n\tuint32_t magic;\n\trb_node(node_t) link;\n\tuint64_t key;\n};\n\nstatic int\nnode_cmp(const node_t *a, const node_t *b) {\n\tint ret;\n\n\tassert_u32_eq(a->magic, NODE_MAGIC, \"Bad magic\");\n\tassert_u32_eq(b->magic, NODE_MAGIC, \"Bad magic\");\n\n\tret = (a->key > b->key) - (a->key < b->key);\n\tif (ret == 0) {\n\t\t/*\n\t\t * Duplicates are not allowed in the tree, so force an\n\t\t * arbitrary ordering for non-identical items with equal keys.\n\t\t */\n\t\tret = (((uintptr_t)a) > ((uintptr_t)b))\n\t\t    - (((uintptr_t)a) < ((uintptr_t)b));\n\t}\n\treturn (ret);\n}\n\ntypedef rb_tree(node_t) tree_t;\nrb_gen(static, tree_, tree_t, node_t, link, node_cmp);\n\nTEST_BEGIN(test_rb_empty)\n{\n\ttree_t tree;\n\tnode_t key;\n\n\ttree_new(&tree);\n\n\tassert_true(tree_empty(&tree), \"Tree should be empty\");\n\tassert_ptr_null(tree_first(&tree), \"Unexpected node\");\n\tassert_ptr_null(tree_last(&tree), \"Unexpected node\");\n\n\tkey.key = 0;\n\tkey.magic = NODE_MAGIC;\n\tassert_ptr_null(tree_search(&tree, &key), \"Unexpected node\");\n\n\tkey.key = 0;\n\tkey.magic = NODE_MAGIC;\n\tassert_ptr_null(tree_nsearch(&tree, &key), \"Unexpected node\");\n\n\tkey.key = 0;\n\tkey.magic = NODE_MAGIC;\n\tassert_ptr_null(tree_psearch(&tree, &key), \"Unexpected node\");\n}\nTEST_END\n\nstatic unsigned\ntree_recurse(node_t *node, unsigned black_height, unsigned black_depth)\n{\n\tunsigned ret = 0;\n\tnode_t *left_node;\n\tnode_t *right_node;\n\n\tif (node == NULL)\n\t\treturn (ret);\n\n\tleft_node = rbtn_left_get(node_t, link, node);\n\tright_node = rbtn_right_get(node_t, link, node);\n\n\tif (!rbtn_red_get(node_t, link, node))\n\t\tblack_depth++;\n\n\t/* Red nodes must be interleaved with black nodes. */\n\tif (rbtn_red_get(node_t, link, node)) {\n\t\tif (left_node != NULL)\n\t\t\tassert_false(rbtn_red_get(node_t, link, left_node),\n\t\t\t\t\"Node should be black\");\n\t\tif (right_node != NULL)\n\t\t\tassert_false(rbtn_red_get(node_t, link, right_node),\n\t\t\t    \"Node should be black\");\n\t}\n\n\t/* Self. */\n\tassert_u32_eq(node->magic, NODE_MAGIC, \"Bad magic\");\n\n\t/* Left subtree. */\n\tif (left_node != NULL)\n\t\tret += tree_recurse(left_node, black_height, black_depth);\n\telse\n\t\tret += (black_depth != black_height);\n\n\t/* Right subtree. */\n\tif (right_node != NULL)\n\t\tret += tree_recurse(right_node, black_height, black_depth);\n\telse\n\t\tret += (black_depth != black_height);\n\n\treturn (ret);\n}\n\nstatic node_t *\ntree_iterate_cb(tree_t *tree, node_t *node, void *data)\n{\n\tunsigned *i = (unsigned *)data;\n\tnode_t *search_node;\n\n\tassert_u32_eq(node->magic, NODE_MAGIC, \"Bad magic\");\n\n\t/* Test rb_search(). */\n\tsearch_node = tree_search(tree, node);\n\tassert_ptr_eq(search_node, node,\n\t    \"tree_search() returned unexpected node\");\n\n\t/* Test rb_nsearch(). */\n\tsearch_node = tree_nsearch(tree, node);\n\tassert_ptr_eq(search_node, node,\n\t    \"tree_nsearch() returned unexpected node\");\n\n\t/* Test rb_psearch(). */\n\tsearch_node = tree_psearch(tree, node);\n\tassert_ptr_eq(search_node, node,\n\t    \"tree_psearch() returned unexpected node\");\n\n\t(*i)++;\n\n\treturn (NULL);\n}\n\nstatic unsigned\ntree_iterate(tree_t *tree)\n{\n\tunsigned i;\n\n\ti = 0;\n\ttree_iter(tree, NULL, tree_iterate_cb, (void *)&i);\n\n\treturn (i);\n}\n\nstatic unsigned\ntree_iterate_reverse(tree_t *tree)\n{\n\tunsigned i;\n\n\ti = 0;\n\ttree_reverse_iter(tree, NULL, tree_iterate_cb, (void *)&i);\n\n\treturn (i);\n}\n\nstatic void\nnode_remove(tree_t *tree, node_t *node, unsigned nnodes)\n{\n\tnode_t *search_node;\n\tunsigned black_height, imbalances;\n\n\ttree_remove(tree, node);\n\n\t/* Test rb_nsearch(). */\n\tsearch_node = tree_nsearch(tree, node);\n\tif (search_node != NULL) {\n\t\tassert_u64_ge(search_node->key, node->key,\n\t\t    \"Key ordering error\");\n\t}\n\n\t/* Test rb_psearch(). */\n\tsearch_node = tree_psearch(tree, node);\n\tif (search_node != NULL) {\n\t\tassert_u64_le(search_node->key, node->key,\n\t\t    \"Key ordering error\");\n\t}\n\n\tnode->magic = 0;\n\n\trbtn_black_height(node_t, link, tree, black_height);\n\timbalances = tree_recurse(tree->rbt_root, black_height, 0);\n\tassert_u_eq(imbalances, 0, \"Tree is unbalanced\");\n\tassert_u_eq(tree_iterate(tree), nnodes-1,\n\t    \"Unexpected node iteration count\");\n\tassert_u_eq(tree_iterate_reverse(tree), nnodes-1,\n\t    \"Unexpected node iteration count\");\n}\n\nstatic node_t *\nremove_iterate_cb(tree_t *tree, node_t *node, void *data)\n{\n\tunsigned *nnodes = (unsigned *)data;\n\tnode_t *ret = tree_next(tree, node);\n\n\tnode_remove(tree, node, *nnodes);\n\n\treturn (ret);\n}\n\nstatic node_t *\nremove_reverse_iterate_cb(tree_t *tree, node_t *node, void *data)\n{\n\tunsigned *nnodes = (unsigned *)data;\n\tnode_t *ret = tree_prev(tree, node);\n\n\tnode_remove(tree, node, *nnodes);\n\n\treturn (ret);\n}\n\nstatic void\ndestroy_cb(node_t *node, void *data)\n{\n\tunsigned *nnodes = (unsigned *)data;\n\n\tassert_u_gt(*nnodes, 0, \"Destruction removed too many nodes\");\n\t(*nnodes)--;\n}\n\nTEST_BEGIN(test_rb_random)\n{\n#define\tNNODES 25\n#define\tNBAGS 250\n#define\tSEED 42\n\tsfmt_t *sfmt;\n\tuint64_t bag[NNODES];\n\ttree_t tree;\n\tnode_t nodes[NNODES];\n\tunsigned i, j, k, black_height, imbalances;\n\n\tsfmt = init_gen_rand(SEED);\n\tfor (i = 0; i < NBAGS; i++) {\n\t\tswitch (i) {\n\t\tcase 0:\n\t\t\t/* Insert in order. */\n\t\t\tfor (j = 0; j < NNODES; j++)\n\t\t\t\tbag[j] = j;\n\t\t\tbreak;\n\t\tcase 1:\n\t\t\t/* Insert in reverse order. */\n\t\t\tfor (j = 0; j < NNODES; j++)\n\t\t\t\tbag[j] = NNODES - j - 1;\n\t\t\tbreak;\n\t\tdefault:\n\t\t\tfor (j = 0; j < NNODES; j++)\n\t\t\t\tbag[j] = gen_rand64_range(sfmt, NNODES);\n\t\t}\n\n\t\tfor (j = 1; j <= NNODES; j++) {\n\t\t\t/* Initialize tree and nodes. */\n\t\t\ttree_new(&tree);\n\t\t\tfor (k = 0; k < j; k++) {\n\t\t\t\tnodes[k].magic = NODE_MAGIC;\n\t\t\t\tnodes[k].key = bag[k];\n\t\t\t}\n\n\t\t\t/* Insert nodes. */\n\t\t\tfor (k = 0; k < j; k++) {\n\t\t\t\ttree_insert(&tree, &nodes[k]);\n\n\t\t\t\trbtn_black_height(node_t, link, &tree,\n\t\t\t\t    black_height);\n\t\t\t\timbalances = tree_recurse(tree.rbt_root,\n\t\t\t\t    black_height, 0);\n\t\t\t\tassert_u_eq(imbalances, 0,\n\t\t\t\t    \"Tree is unbalanced\");\n\n\t\t\t\tassert_u_eq(tree_iterate(&tree), k+1,\n\t\t\t\t    \"Unexpected node iteration count\");\n\t\t\t\tassert_u_eq(tree_iterate_reverse(&tree), k+1,\n\t\t\t\t    \"Unexpected node iteration count\");\n\n\t\t\t\tassert_false(tree_empty(&tree),\n\t\t\t\t    \"Tree should not be empty\");\n\t\t\t\tassert_ptr_not_null(tree_first(&tree),\n\t\t\t\t    \"Tree should not be empty\");\n\t\t\t\tassert_ptr_not_null(tree_last(&tree),\n\t\t\t\t    \"Tree should not be empty\");\n\n\t\t\t\ttree_next(&tree, &nodes[k]);\n\t\t\t\ttree_prev(&tree, &nodes[k]);\n\t\t\t}\n\n\t\t\t/* Remove nodes. */\n\t\t\tswitch (i % 5) {\n\t\t\tcase 0:\n\t\t\t\tfor (k = 0; k < j; k++)\n\t\t\t\t\tnode_remove(&tree, &nodes[k], j - k);\n\t\t\t\tbreak;\n\t\t\tcase 1:\n\t\t\t\tfor (k = j; k > 0; k--)\n\t\t\t\t\tnode_remove(&tree, &nodes[k-1], k);\n\t\t\t\tbreak;\n\t\t\tcase 2: {\n\t\t\t\tnode_t *start;\n\t\t\t\tunsigned nnodes = j;\n\n\t\t\t\tstart = NULL;\n\t\t\t\tdo {\n\t\t\t\t\tstart = tree_iter(&tree, start,\n\t\t\t\t\t    remove_iterate_cb, (void *)&nnodes);\n\t\t\t\t\tnnodes--;\n\t\t\t\t} while (start != NULL);\n\t\t\t\tassert_u_eq(nnodes, 0,\n\t\t\t\t    \"Removal terminated early\");\n\t\t\t\tbreak;\n\t\t\t} case 3: {\n\t\t\t\tnode_t *start;\n\t\t\t\tunsigned nnodes = j;\n\n\t\t\t\tstart = NULL;\n\t\t\t\tdo {\n\t\t\t\t\tstart = tree_reverse_iter(&tree, start,\n\t\t\t\t\t    remove_reverse_iterate_cb,\n\t\t\t\t\t    (void *)&nnodes);\n\t\t\t\t\tnnodes--;\n\t\t\t\t} while (start != NULL);\n\t\t\t\tassert_u_eq(nnodes, 0,\n\t\t\t\t    \"Removal terminated early\");\n\t\t\t\tbreak;\n\t\t\t} case 4: {\n\t\t\t\tunsigned nnodes = j;\n\t\t\t\ttree_destroy(&tree, destroy_cb, &nnodes);\n\t\t\t\tassert_u_eq(nnodes, 0,\n\t\t\t\t    \"Destruction terminated early\");\n\t\t\t\tbreak;\n\t\t\t} default:\n\t\t\t\tnot_reached();\n\t\t\t}\n\t\t}\n\t}\n\tfini_gen_rand(sfmt);\n#undef NNODES\n#undef NBAGS\n#undef SEED\n}\nTEST_END\n\nint\nmain(void)\n{\n\n\treturn (test(\n\t    test_rb_empty,\n\t    test_rb_random));\n}\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/deps/jemalloc/test/unit/rtree.c",
    "content": "#include \"test/jemalloc_test.h\"\n\nstatic rtree_node_elm_t *\nnode_alloc(size_t nelms)\n{\n\n\treturn ((rtree_node_elm_t *)calloc(nelms, sizeof(rtree_node_elm_t)));\n}\n\nstatic void\nnode_dalloc(rtree_node_elm_t *node)\n{\n\n\tfree(node);\n}\n\nTEST_BEGIN(test_rtree_get_empty)\n{\n\tunsigned i;\n\n\tfor (i = 1; i <= (sizeof(uintptr_t) << 3); i++) {\n\t\trtree_t rtree;\n\t\tassert_false(rtree_new(&rtree, i, node_alloc, node_dalloc),\n\t\t    \"Unexpected rtree_new() failure\");\n\t\tassert_ptr_null(rtree_get(&rtree, 0, false),\n\t\t    \"rtree_get() should return NULL for empty tree\");\n\t\trtree_delete(&rtree);\n\t}\n}\nTEST_END\n\nTEST_BEGIN(test_rtree_extrema)\n{\n\tunsigned i;\n\textent_node_t node_a, node_b;\n\n\tfor (i = 1; i <= (sizeof(uintptr_t) << 3); i++) {\n\t\trtree_t rtree;\n\t\tassert_false(rtree_new(&rtree, i, node_alloc, node_dalloc),\n\t\t    \"Unexpected rtree_new() failure\");\n\n\t\tassert_false(rtree_set(&rtree, 0, &node_a),\n\t\t    \"Unexpected rtree_set() failure\");\n\t\tassert_ptr_eq(rtree_get(&rtree, 0, true), &node_a,\n\t\t    \"rtree_get() should return previously set value\");\n\n\t\tassert_false(rtree_set(&rtree, ~((uintptr_t)0), &node_b),\n\t\t    \"Unexpected rtree_set() failure\");\n\t\tassert_ptr_eq(rtree_get(&rtree, ~((uintptr_t)0), true), &node_b,\n\t\t    \"rtree_get() should return previously set value\");\n\n\t\trtree_delete(&rtree);\n\t}\n}\nTEST_END\n\nTEST_BEGIN(test_rtree_bits)\n{\n\tunsigned i, j, k;\n\n\tfor (i = 1; i < (sizeof(uintptr_t) << 3); i++) {\n\t\tuintptr_t keys[] = {0, 1,\n\t\t    (((uintptr_t)1) << (sizeof(uintptr_t)*8-i)) - 1};\n\t\textent_node_t node;\n\t\trtree_t rtree;\n\n\t\tassert_false(rtree_new(&rtree, i, node_alloc, node_dalloc),\n\t\t    \"Unexpected rtree_new() failure\");\n\n\t\tfor (j = 0; j < sizeof(keys)/sizeof(uintptr_t); j++) {\n\t\t\tassert_false(rtree_set(&rtree, keys[j], &node),\n\t\t\t    \"Unexpected rtree_set() failure\");\n\t\t\tfor (k = 0; k < sizeof(keys)/sizeof(uintptr_t); k++) {\n\t\t\t\tassert_ptr_eq(rtree_get(&rtree, keys[k], true),\n\t\t\t\t    &node, \"rtree_get() should return \"\n\t\t\t\t    \"previously set value and ignore \"\n\t\t\t\t    \"insignificant key bits; i=%u, j=%u, k=%u, \"\n\t\t\t\t    \"set key=%#\"FMTxPTR\", get key=%#\"FMTxPTR, i,\n\t\t\t\t    j, k, keys[j], keys[k]);\n\t\t\t}\n\t\t\tassert_ptr_null(rtree_get(&rtree,\n\t\t\t    (((uintptr_t)1) << (sizeof(uintptr_t)*8-i)), false),\n\t\t\t    \"Only leftmost rtree leaf should be set; \"\n\t\t\t    \"i=%u, j=%u\", i, j);\n\t\t\tassert_false(rtree_set(&rtree, keys[j], NULL),\n\t\t\t    \"Unexpected rtree_set() failure\");\n\t\t}\n\n\t\trtree_delete(&rtree);\n\t}\n}\nTEST_END\n\nTEST_BEGIN(test_rtree_random)\n{\n\tunsigned i;\n\tsfmt_t *sfmt;\n#define\tNSET 16\n#define\tSEED 42\n\n\tsfmt = init_gen_rand(SEED);\n\tfor (i = 1; i <= (sizeof(uintptr_t) << 3); i++) {\n\t\tuintptr_t keys[NSET];\n\t\textent_node_t node;\n\t\tunsigned j;\n\t\trtree_t rtree;\n\n\t\tassert_false(rtree_new(&rtree, i, node_alloc, node_dalloc),\n\t\t    \"Unexpected rtree_new() failure\");\n\n\t\tfor (j = 0; j < NSET; j++) {\n\t\t\tkeys[j] = (uintptr_t)gen_rand64(sfmt);\n\t\t\tassert_false(rtree_set(&rtree, keys[j], &node),\n\t\t\t    \"Unexpected rtree_set() failure\");\n\t\t\tassert_ptr_eq(rtree_get(&rtree, keys[j], true), &node,\n\t\t\t    \"rtree_get() should return previously set value\");\n\t\t}\n\t\tfor (j = 0; j < NSET; j++) {\n\t\t\tassert_ptr_eq(rtree_get(&rtree, keys[j], true), &node,\n\t\t\t    \"rtree_get() should return previously set value\");\n\t\t}\n\n\t\tfor (j = 0; j < NSET; j++) {\n\t\t\tassert_false(rtree_set(&rtree, keys[j], NULL),\n\t\t\t    \"Unexpected rtree_set() failure\");\n\t\t\tassert_ptr_null(rtree_get(&rtree, keys[j], true),\n\t\t\t    \"rtree_get() should return previously set value\");\n\t\t}\n\t\tfor (j = 0; j < NSET; j++) {\n\t\t\tassert_ptr_null(rtree_get(&rtree, keys[j], true),\n\t\t\t    \"rtree_get() should return previously set value\");\n\t\t}\n\n\t\trtree_delete(&rtree);\n\t}\n\tfini_gen_rand(sfmt);\n#undef NSET\n#undef SEED\n}\nTEST_END\n\nint\nmain(void)\n{\n\n\treturn (test(\n\t    test_rtree_get_empty,\n\t    test_rtree_extrema,\n\t    test_rtree_bits,\n\t    test_rtree_random));\n}\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/deps/jemalloc/test/unit/run_quantize.c",
    "content": "#include \"test/jemalloc_test.h\"\n\nTEST_BEGIN(test_small_run_size)\n{\n\tunsigned nbins, i;\n\tsize_t sz, run_size;\n\tsize_t mib[4];\n\tsize_t miblen = sizeof(mib) / sizeof(size_t);\n\n\t/*\n\t * Iterate over all small size classes, get their run sizes, and verify\n\t * that the quantized size is the same as the run size.\n\t */\n\n\tsz = sizeof(unsigned);\n\tassert_d_eq(mallctl(\"arenas.nbins\", &nbins, &sz, NULL, 0), 0,\n\t    \"Unexpected mallctl failure\");\n\n\tassert_d_eq(mallctlnametomib(\"arenas.bin.0.run_size\", mib, &miblen), 0,\n\t    \"Unexpected mallctlnametomib failure\");\n\tfor (i = 0; i < nbins; i++) {\n\t\tmib[2] = i;\n\t\tsz = sizeof(size_t);\n\t\tassert_d_eq(mallctlbymib(mib, miblen, &run_size, &sz, NULL, 0),\n\t\t    0, \"Unexpected mallctlbymib failure\");\n\t\tassert_zu_eq(run_size, run_quantize_floor(run_size),\n\t\t    \"Small run quantization should be a no-op (run_size=%zu)\",\n\t\t    run_size);\n\t\tassert_zu_eq(run_size, run_quantize_ceil(run_size),\n\t\t    \"Small run quantization should be a no-op (run_size=%zu)\",\n\t\t    run_size);\n\t}\n}\nTEST_END\n\nTEST_BEGIN(test_large_run_size)\n{\n\tbool cache_oblivious;\n\tunsigned nlruns, i;\n\tsize_t sz, run_size_prev, ceil_prev;\n\tsize_t mib[4];\n\tsize_t miblen = sizeof(mib) / sizeof(size_t);\n\n\t/*\n\t * Iterate over all large size classes, get their run sizes, and verify\n\t * that the quantized size is the same as the run size.\n\t */\n\n\tsz = sizeof(bool);\n\tassert_d_eq(mallctl(\"config.cache_oblivious\", &cache_oblivious, &sz,\n\t    NULL, 0), 0, \"Unexpected mallctl failure\");\n\n\tsz = sizeof(unsigned);\n\tassert_d_eq(mallctl(\"arenas.nlruns\", &nlruns, &sz, NULL, 0), 0,\n\t    \"Unexpected mallctl failure\");\n\n\tassert_d_eq(mallctlnametomib(\"arenas.lrun.0.size\", mib, &miblen), 0,\n\t    \"Unexpected mallctlnametomib failure\");\n\tfor (i = 0; i < nlruns; i++) {\n\t\tsize_t lrun_size, run_size, floor, ceil;\n\n\t\tmib[2] = i;\n\t\tsz = sizeof(size_t);\n\t\tassert_d_eq(mallctlbymib(mib, miblen, &lrun_size, &sz, NULL, 0),\n\t\t    0, \"Unexpected mallctlbymib failure\");\n\t\trun_size = cache_oblivious ? lrun_size + PAGE : lrun_size;\n\t\tfloor = run_quantize_floor(run_size);\n\t\tceil = run_quantize_ceil(run_size);\n\n\t\tassert_zu_eq(run_size, floor,\n\t\t    \"Large run quantization should be a no-op for precise \"\n\t\t    \"size (lrun_size=%zu, run_size=%zu)\", lrun_size, run_size);\n\t\tassert_zu_eq(run_size, ceil,\n\t\t    \"Large run quantization should be a no-op for precise \"\n\t\t    \"size (lrun_size=%zu, run_size=%zu)\", lrun_size, run_size);\n\n\t\tif (i > 0) {\n\t\t\tassert_zu_eq(run_size_prev, run_quantize_floor(run_size\n\t\t\t    - PAGE), \"Floor should be a precise size\");\n\t\t\tif (run_size_prev < ceil_prev) {\n\t\t\t\tassert_zu_eq(ceil_prev, run_size,\n\t\t\t\t    \"Ceiling should be a precise size \"\n\t\t\t\t    \"(run_size_prev=%zu, ceil_prev=%zu, \"\n\t\t\t\t    \"run_size=%zu)\", run_size_prev, ceil_prev,\n\t\t\t\t    run_size);\n\t\t\t}\n\t\t}\n\t\trun_size_prev = floor;\n\t\tceil_prev = run_quantize_ceil(run_size + PAGE);\n\t}\n}\nTEST_END\n\nTEST_BEGIN(test_monotonic)\n{\n\tunsigned nbins, nlruns, i;\n\tsize_t sz, floor_prev, ceil_prev;\n\n\t/*\n\t * Iterate over all run sizes and verify that\n\t * run_quantize_{floor,ceil}() are monotonic.\n\t */\n\n\tsz = sizeof(unsigned);\n\tassert_d_eq(mallctl(\"arenas.nbins\", &nbins, &sz, NULL, 0), 0,\n\t    \"Unexpected mallctl failure\");\n\n\tsz = sizeof(unsigned);\n\tassert_d_eq(mallctl(\"arenas.nlruns\", &nlruns, &sz, NULL, 0), 0,\n\t    \"Unexpected mallctl failure\");\n\n\tfloor_prev = 0;\n\tceil_prev = 0;\n\tfor (i = 1; i < run_quantize_max >> LG_PAGE; i++) {\n\t\tsize_t run_size, floor, ceil;\n\n\t\trun_size = i << LG_PAGE;\n\t\tfloor = run_quantize_floor(run_size);\n\t\tceil = run_quantize_ceil(run_size);\n\n\t\tassert_zu_le(floor, run_size,\n\t\t    \"Floor should be <= (floor=%zu, run_size=%zu, ceil=%zu)\",\n\t\t    floor, run_size, ceil);\n\t\tassert_zu_ge(ceil, run_size,\n\t\t    \"Ceiling should be >= (floor=%zu, run_size=%zu, ceil=%zu)\",\n\t\t    floor, run_size, ceil);\n\n\t\tassert_zu_le(floor_prev, floor, \"Floor should be monotonic \"\n\t\t    \"(floor_prev=%zu, floor=%zu, run_size=%zu, ceil=%zu)\",\n\t\t    floor_prev, floor, run_size, ceil);\n\t\tassert_zu_le(ceil_prev, ceil, \"Ceiling should be monotonic \"\n\t\t    \"(floor=%zu, run_size=%zu, ceil_prev=%zu, ceil=%zu)\",\n\t\t    floor, run_size, ceil_prev, ceil);\n\n\t\tfloor_prev = floor;\n\t\tceil_prev = ceil;\n\t}\n}\nTEST_END\n\nint\nmain(void)\n{\n\n\treturn (test(\n\t    test_small_run_size,\n\t    test_large_run_size,\n\t    test_monotonic));\n}\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/deps/jemalloc/test/unit/size_classes.c",
    "content": "#include \"test/jemalloc_test.h\"\n\nstatic size_t\nget_max_size_class(void)\n{\n\tunsigned nhchunks;\n\tsize_t mib[4];\n\tsize_t sz, miblen, max_size_class;\n\n\tsz = sizeof(unsigned);\n\tassert_d_eq(mallctl(\"arenas.nhchunks\", &nhchunks, &sz, NULL, 0), 0,\n\t    \"Unexpected mallctl() error\");\n\n\tmiblen = sizeof(mib) / sizeof(size_t);\n\tassert_d_eq(mallctlnametomib(\"arenas.hchunk.0.size\", mib, &miblen), 0,\n\t    \"Unexpected mallctlnametomib() error\");\n\tmib[2] = nhchunks - 1;\n\n\tsz = sizeof(size_t);\n\tassert_d_eq(mallctlbymib(mib, miblen, &max_size_class, &sz, NULL, 0), 0,\n\t    \"Unexpected mallctlbymib() error\");\n\n\treturn (max_size_class);\n}\n\nTEST_BEGIN(test_size_classes)\n{\n\tsize_t size_class, max_size_class;\n\tszind_t index, max_index;\n\n\tmax_size_class = get_max_size_class();\n\tmax_index = size2index(max_size_class);\n\n\tfor (index = 0, size_class = index2size(index); index < max_index ||\n\t    size_class < max_size_class; index++, size_class =\n\t    index2size(index)) {\n\t\tassert_true(index < max_index,\n\t\t    \"Loop conditionals should be equivalent; index=%u, \"\n\t\t    \"size_class=%zu (%#zx)\", index, size_class, size_class);\n\t\tassert_true(size_class < max_size_class,\n\t\t    \"Loop conditionals should be equivalent; index=%u, \"\n\t\t    \"size_class=%zu (%#zx)\", index, size_class, size_class);\n\n\t\tassert_u_eq(index, size2index(size_class),\n\t\t    \"size2index() does not reverse index2size(): index=%u -->\"\n\t\t    \" size_class=%zu --> index=%u --> size_class=%zu\", index,\n\t\t    size_class, size2index(size_class),\n\t\t    index2size(size2index(size_class)));\n\t\tassert_zu_eq(size_class, index2size(size2index(size_class)),\n\t\t    \"index2size() does not reverse size2index(): index=%u -->\"\n\t\t    \" size_class=%zu --> index=%u --> size_class=%zu\", index,\n\t\t    size_class, size2index(size_class),\n\t\t    index2size(size2index(size_class)));\n\n\t\tassert_u_eq(index+1, size2index(size_class+1),\n\t\t    \"Next size_class does not round up properly\");\n\n\t\tassert_zu_eq(size_class, (index > 0) ?\n\t\t    s2u(index2size(index-1)+1) : s2u(1),\n\t\t    \"s2u() does not round up to size class\");\n\t\tassert_zu_eq(size_class, s2u(size_class-1),\n\t\t    \"s2u() does not round up to size class\");\n\t\tassert_zu_eq(size_class, s2u(size_class),\n\t\t    \"s2u() does not compute same size class\");\n\t\tassert_zu_eq(s2u(size_class+1), index2size(index+1),\n\t\t    \"s2u() does not round up to next size class\");\n\t}\n\n\tassert_u_eq(index, size2index(index2size(index)),\n\t    \"size2index() does not reverse index2size()\");\n\tassert_zu_eq(max_size_class, index2size(size2index(max_size_class)),\n\t    \"index2size() does not reverse size2index()\");\n\n\tassert_zu_eq(size_class, s2u(index2size(index-1)+1),\n\t    \"s2u() does not round up to size class\");\n\tassert_zu_eq(size_class, s2u(size_class-1),\n\t    \"s2u() does not round up to size class\");\n\tassert_zu_eq(size_class, s2u(size_class),\n\t    \"s2u() does not compute same size class\");\n}\nTEST_END\n\nTEST_BEGIN(test_overflow)\n{\n\tsize_t max_size_class;\n\n\tmax_size_class = get_max_size_class();\n\n\tassert_u_ge(size2index(max_size_class+1), NSIZES,\n\t    \"size2index() should return >= NSIZES on overflow\");\n\tassert_u_ge(size2index(ZU(PTRDIFF_MAX)+1), NSIZES,\n\t    \"size2index() should return >= NSIZES on overflow\");\n\tassert_u_ge(size2index(SIZE_T_MAX), NSIZES,\n\t    \"size2index() should return >= NSIZES on overflow\");\n\n\tassert_zu_gt(s2u(max_size_class+1), HUGE_MAXCLASS,\n\t    \"s2u() should return > HUGE_MAXCLASS for unsupported size\");\n\tassert_zu_gt(s2u(ZU(PTRDIFF_MAX)+1), HUGE_MAXCLASS,\n\t    \"s2u() should return > HUGE_MAXCLASS for unsupported size\");\n\tassert_zu_eq(s2u(SIZE_T_MAX), 0,\n\t    \"s2u() should return 0 on overflow\");\n}\nTEST_END\n\nint\nmain(void)\n{\n\n\treturn (test(\n\t    test_size_classes,\n\t    test_overflow));\n}\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/deps/jemalloc/test/unit/smoothstep.c",
    "content": "#include \"test/jemalloc_test.h\"\n\nstatic const uint64_t smoothstep_tab[] = {\n#define\tSTEP(step, h, x, y) \\\n\th,\n\tSMOOTHSTEP\n#undef STEP\n};\n\nTEST_BEGIN(test_smoothstep_integral)\n{\n\tuint64_t sum, min, max;\n\tunsigned i;\n\n\t/*\n\t * The integral of smoothstep in the [0..1] range equals 1/2.  Verify\n\t * that the fixed point representation's integral is no more than\n\t * rounding error distant from 1/2.  Regarding rounding, each table\n\t * element is rounded down to the nearest fixed point value, so the\n\t * integral may be off by as much as SMOOTHSTEP_NSTEPS ulps.\n\t */\n\tsum = 0;\n\tfor (i = 0; i < SMOOTHSTEP_NSTEPS; i++)\n\t\tsum += smoothstep_tab[i];\n\n\tmax = (KQU(1) << (SMOOTHSTEP_BFP-1)) * (SMOOTHSTEP_NSTEPS+1);\n\tmin = max - SMOOTHSTEP_NSTEPS;\n\n\tassert_u64_ge(sum, min,\n\t    \"Integral too small, even accounting for truncation\");\n\tassert_u64_le(sum, max, \"Integral exceeds 1/2\");\n\tif (false) {\n\t\tmalloc_printf(\"%\"FMTu64\" ulps under 1/2 (limit %d)\\n\",\n\t\t    max - sum, SMOOTHSTEP_NSTEPS);\n\t}\n}\nTEST_END\n\nTEST_BEGIN(test_smoothstep_monotonic)\n{\n\tuint64_t prev_h;\n\tunsigned i;\n\n\t/*\n\t * The smoothstep function is monotonic in [0..1], i.e. its slope is\n\t * non-negative.  In practice we want to parametrize table generation\n\t * such that piecewise slope is greater than zero, but do not require\n\t * that here.\n\t */\n\tprev_h = 0;\n\tfor (i = 0; i < SMOOTHSTEP_NSTEPS; i++) {\n\t\tuint64_t h = smoothstep_tab[i];\n\t\tassert_u64_ge(h, prev_h, \"Piecewise non-monotonic, i=%u\", i);\n\t\tprev_h = h;\n\t}\n\tassert_u64_eq(smoothstep_tab[SMOOTHSTEP_NSTEPS-1],\n\t    (KQU(1) << SMOOTHSTEP_BFP), \"Last step must equal 1\");\n}\nTEST_END\n\nTEST_BEGIN(test_smoothstep_slope)\n{\n\tuint64_t prev_h, prev_delta;\n\tunsigned i;\n\n\t/*\n\t * The smoothstep slope strictly increases until x=0.5, and then\n\t * strictly decreases until x=1.0.  Verify the slightly weaker\n\t * requirement of monotonicity, so that inadequate table precision does\n\t * not cause false test failures.\n\t */\n\tprev_h = 0;\n\tprev_delta = 0;\n\tfor (i = 0; i < SMOOTHSTEP_NSTEPS / 2 + SMOOTHSTEP_NSTEPS % 2; i++) {\n\t\tuint64_t h = smoothstep_tab[i];\n\t\tuint64_t delta = h - prev_h;\n\t\tassert_u64_ge(delta, prev_delta,\n\t\t    \"Slope must monotonically increase in 0.0 <= x <= 0.5, \"\n\t\t    \"i=%u\", i);\n\t\tprev_h = h;\n\t\tprev_delta = delta;\n\t}\n\n\tprev_h = KQU(1) << SMOOTHSTEP_BFP;\n\tprev_delta = 0;\n\tfor (i = SMOOTHSTEP_NSTEPS-1; i >= SMOOTHSTEP_NSTEPS / 2; i--) {\n\t\tuint64_t h = smoothstep_tab[i];\n\t\tuint64_t delta = prev_h - h;\n\t\tassert_u64_ge(delta, prev_delta,\n\t\t    \"Slope must monotonically decrease in 0.5 <= x <= 1.0, \"\n\t\t    \"i=%u\", i);\n\t\tprev_h = h;\n\t\tprev_delta = delta;\n\t}\n}\nTEST_END\n\nint\nmain(void)\n{\n\n\treturn (test(\n\t    test_smoothstep_integral,\n\t    test_smoothstep_monotonic,\n\t    test_smoothstep_slope));\n}\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/deps/jemalloc/test/unit/stats.c",
    "content": "#include \"test/jemalloc_test.h\"\n\nTEST_BEGIN(test_stats_summary)\n{\n\tsize_t *cactive;\n\tsize_t sz, allocated, active, resident, mapped;\n\tint expected = config_stats ? 0 : ENOENT;\n\n\tsz = sizeof(cactive);\n\tassert_d_eq(mallctl(\"stats.cactive\", &cactive, &sz, NULL, 0), expected,\n\t    \"Unexpected mallctl() result\");\n\n\tsz = sizeof(size_t);\n\tassert_d_eq(mallctl(\"stats.allocated\", &allocated, &sz, NULL, 0),\n\t    expected, \"Unexpected mallctl() result\");\n\tassert_d_eq(mallctl(\"stats.active\", &active, &sz, NULL, 0), expected,\n\t    \"Unexpected mallctl() result\");\n\tassert_d_eq(mallctl(\"stats.resident\", &resident, &sz, NULL, 0),\n\t    expected, \"Unexpected mallctl() result\");\n\tassert_d_eq(mallctl(\"stats.mapped\", &mapped, &sz, NULL, 0), expected,\n\t    \"Unexpected mallctl() result\");\n\n\tif (config_stats) {\n\t\tassert_zu_le(active, *cactive,\n\t\t    \"active should be no larger than cactive\");\n\t\tassert_zu_le(allocated, active,\n\t\t    \"allocated should be no larger than active\");\n\t\tassert_zu_lt(active, resident,\n\t\t    \"active should be less than resident\");\n\t\tassert_zu_lt(active, mapped,\n\t\t    \"active should be less than mapped\");\n\t}\n}\nTEST_END\n\nTEST_BEGIN(test_stats_huge)\n{\n\tvoid *p;\n\tuint64_t epoch;\n\tsize_t allocated;\n\tuint64_t nmalloc, ndalloc, nrequests;\n\tsize_t sz;\n\tint expected = config_stats ? 0 : ENOENT;\n\n\tp = mallocx(large_maxclass+1, 0);\n\tassert_ptr_not_null(p, \"Unexpected mallocx() failure\");\n\n\tassert_d_eq(mallctl(\"epoch\", NULL, NULL, &epoch, sizeof(epoch)), 0,\n\t    \"Unexpected mallctl() failure\");\n\n\tsz = sizeof(size_t);\n\tassert_d_eq(mallctl(\"stats.arenas.0.huge.allocated\", &allocated, &sz,\n\t    NULL, 0), expected, \"Unexpected mallctl() result\");\n\tsz = sizeof(uint64_t);\n\tassert_d_eq(mallctl(\"stats.arenas.0.huge.nmalloc\", &nmalloc, &sz, NULL,\n\t    0), expected, \"Unexpected mallctl() result\");\n\tassert_d_eq(mallctl(\"stats.arenas.0.huge.ndalloc\", &ndalloc, &sz, NULL,\n\t    0), expected, \"Unexpected mallctl() result\");\n\tassert_d_eq(mallctl(\"stats.arenas.0.huge.nrequests\", &nrequests, &sz,\n\t    NULL, 0), expected, \"Unexpected mallctl() result\");\n\n\tif (config_stats) {\n\t\tassert_zu_gt(allocated, 0,\n\t\t    \"allocated should be greater than zero\");\n\t\tassert_u64_ge(nmalloc, ndalloc,\n\t\t    \"nmalloc should be at least as large as ndalloc\");\n\t\tassert_u64_le(nmalloc, nrequests,\n\t\t    \"nmalloc should no larger than nrequests\");\n\t}\n\n\tdallocx(p, 0);\n}\nTEST_END\n\nTEST_BEGIN(test_stats_arenas_summary)\n{\n\tunsigned arena;\n\tvoid *little, *large, *huge;\n\tuint64_t epoch;\n\tsize_t sz;\n\tint expected = config_stats ? 0 : ENOENT;\n\tsize_t mapped;\n\tuint64_t npurge, nmadvise, purged;\n\n\tarena = 0;\n\tassert_d_eq(mallctl(\"thread.arena\", NULL, NULL, &arena, sizeof(arena)),\n\t    0, \"Unexpected mallctl() failure\");\n\n\tlittle = mallocx(SMALL_MAXCLASS, 0);\n\tassert_ptr_not_null(little, \"Unexpected mallocx() failure\");\n\tlarge = mallocx(large_maxclass, 0);\n\tassert_ptr_not_null(large, \"Unexpected mallocx() failure\");\n\thuge = mallocx(chunksize, 0);\n\tassert_ptr_not_null(huge, \"Unexpected mallocx() failure\");\n\n\tdallocx(little, 0);\n\tdallocx(large, 0);\n\tdallocx(huge, 0);\n\n\tassert_d_eq(mallctl(\"arena.0.purge\", NULL, NULL, NULL, 0), 0,\n\t    \"Unexpected mallctl() failure\");\n\n\tassert_d_eq(mallctl(\"epoch\", NULL, NULL, &epoch, sizeof(epoch)), 0,\n\t    \"Unexpected mallctl() failure\");\n\n\tsz = sizeof(size_t);\n\tassert_d_eq(mallctl(\"stats.arenas.0.mapped\", &mapped, &sz, NULL, 0),\n\t    expected, \"Unexepected mallctl() result\");\n\tsz = sizeof(uint64_t);\n\tassert_d_eq(mallctl(\"stats.arenas.0.npurge\", &npurge, &sz, NULL, 0),\n\t    expected, \"Unexepected mallctl() result\");\n\tassert_d_eq(mallctl(\"stats.arenas.0.nmadvise\", &nmadvise, &sz, NULL, 0),\n\t    expected, \"Unexepected mallctl() result\");\n\tassert_d_eq(mallctl(\"stats.arenas.0.purged\", &purged, &sz, NULL, 0),\n\t    expected, \"Unexepected mallctl() result\");\n\n\tif (config_stats) {\n\t\tassert_u64_gt(npurge, 0,\n\t\t    \"At least one purge should have occurred\");\n\t\tassert_u64_le(nmadvise, purged,\n\t\t    \"nmadvise should be no greater than purged\");\n\t}\n}\nTEST_END\n\nvoid *\nthd_start(void *arg)\n{\n\n\treturn (NULL);\n}\n\nstatic void\nno_lazy_lock(void)\n{\n\tthd_t thd;\n\n\tthd_create(&thd, thd_start, NULL);\n\tthd_join(thd, NULL);\n}\n\nTEST_BEGIN(test_stats_arenas_small)\n{\n\tunsigned arena;\n\tvoid *p;\n\tsize_t sz, allocated;\n\tuint64_t epoch, nmalloc, ndalloc, nrequests;\n\tint expected = config_stats ? 0 : ENOENT;\n\n\tno_lazy_lock(); /* Lazy locking would dodge tcache testing. */\n\n\tarena = 0;\n\tassert_d_eq(mallctl(\"thread.arena\", NULL, NULL, &arena, sizeof(arena)),\n\t    0, \"Unexpected mallctl() failure\");\n\n\tp = mallocx(SMALL_MAXCLASS, 0);\n\tassert_ptr_not_null(p, \"Unexpected mallocx() failure\");\n\n\tassert_d_eq(mallctl(\"thread.tcache.flush\", NULL, NULL, NULL, 0),\n\t    config_tcache ? 0 : ENOENT, \"Unexpected mallctl() result\");\n\n\tassert_d_eq(mallctl(\"epoch\", NULL, NULL, &epoch, sizeof(epoch)), 0,\n\t    \"Unexpected mallctl() failure\");\n\n\tsz = sizeof(size_t);\n\tassert_d_eq(mallctl(\"stats.arenas.0.small.allocated\", &allocated, &sz,\n\t    NULL, 0), expected, \"Unexpected mallctl() result\");\n\tsz = sizeof(uint64_t);\n\tassert_d_eq(mallctl(\"stats.arenas.0.small.nmalloc\", &nmalloc, &sz,\n\t    NULL, 0), expected, \"Unexpected mallctl() result\");\n\tassert_d_eq(mallctl(\"stats.arenas.0.small.ndalloc\", &ndalloc, &sz,\n\t    NULL, 0), expected, \"Unexpected mallctl() result\");\n\tassert_d_eq(mallctl(\"stats.arenas.0.small.nrequests\", &nrequests, &sz,\n\t    NULL, 0), expected, \"Unexpected mallctl() result\");\n\n\tif (config_stats) {\n\t\tassert_zu_gt(allocated, 0,\n\t\t    \"allocated should be greater than zero\");\n\t\tassert_u64_gt(nmalloc, 0,\n\t\t    \"nmalloc should be no greater than zero\");\n\t\tassert_u64_ge(nmalloc, ndalloc,\n\t\t    \"nmalloc should be at least as large as ndalloc\");\n\t\tassert_u64_gt(nrequests, 0,\n\t\t    \"nrequests should be greater than zero\");\n\t}\n\n\tdallocx(p, 0);\n}\nTEST_END\n\nTEST_BEGIN(test_stats_arenas_large)\n{\n\tunsigned arena;\n\tvoid *p;\n\tsize_t sz, allocated;\n\tuint64_t epoch, nmalloc, ndalloc, nrequests;\n\tint expected = config_stats ? 0 : ENOENT;\n\n\tarena = 0;\n\tassert_d_eq(mallctl(\"thread.arena\", NULL, NULL, &arena, sizeof(arena)),\n\t    0, \"Unexpected mallctl() failure\");\n\n\tp = mallocx(large_maxclass, 0);\n\tassert_ptr_not_null(p, \"Unexpected mallocx() failure\");\n\n\tassert_d_eq(mallctl(\"epoch\", NULL, NULL, &epoch, sizeof(epoch)), 0,\n\t    \"Unexpected mallctl() failure\");\n\n\tsz = sizeof(size_t);\n\tassert_d_eq(mallctl(\"stats.arenas.0.large.allocated\", &allocated, &sz,\n\t    NULL, 0), expected, \"Unexpected mallctl() result\");\n\tsz = sizeof(uint64_t);\n\tassert_d_eq(mallctl(\"stats.arenas.0.large.nmalloc\", &nmalloc, &sz,\n\t    NULL, 0), expected, \"Unexpected mallctl() result\");\n\tassert_d_eq(mallctl(\"stats.arenas.0.large.ndalloc\", &ndalloc, &sz,\n\t    NULL, 0), expected, \"Unexpected mallctl() result\");\n\tassert_d_eq(mallctl(\"stats.arenas.0.large.nrequests\", &nrequests, &sz,\n\t    NULL, 0), expected, \"Unexpected mallctl() result\");\n\n\tif (config_stats) {\n\t\tassert_zu_gt(allocated, 0,\n\t\t    \"allocated should be greater than zero\");\n\t\tassert_u64_gt(nmalloc, 0,\n\t\t    \"nmalloc should be greater than zero\");\n\t\tassert_u64_ge(nmalloc, ndalloc,\n\t\t    \"nmalloc should be at least as large as ndalloc\");\n\t\tassert_u64_gt(nrequests, 0,\n\t\t    \"nrequests should be greater than zero\");\n\t}\n\n\tdallocx(p, 0);\n}\nTEST_END\n\nTEST_BEGIN(test_stats_arenas_huge)\n{\n\tunsigned arena;\n\tvoid *p;\n\tsize_t sz, allocated;\n\tuint64_t epoch, nmalloc, ndalloc;\n\tint expected = config_stats ? 0 : ENOENT;\n\n\tarena = 0;\n\tassert_d_eq(mallctl(\"thread.arena\", NULL, NULL, &arena, sizeof(arena)),\n\t    0, \"Unexpected mallctl() failure\");\n\n\tp = mallocx(chunksize, 0);\n\tassert_ptr_not_null(p, \"Unexpected mallocx() failure\");\n\n\tassert_d_eq(mallctl(\"epoch\", NULL, NULL, &epoch, sizeof(epoch)), 0,\n\t    \"Unexpected mallctl() failure\");\n\n\tsz = sizeof(size_t);\n\tassert_d_eq(mallctl(\"stats.arenas.0.huge.allocated\", &allocated, &sz,\n\t    NULL, 0), expected, \"Unexpected mallctl() result\");\n\tsz = sizeof(uint64_t);\n\tassert_d_eq(mallctl(\"stats.arenas.0.huge.nmalloc\", &nmalloc, &sz,\n\t    NULL, 0), expected, \"Unexpected mallctl() result\");\n\tassert_d_eq(mallctl(\"stats.arenas.0.huge.ndalloc\", &ndalloc, &sz,\n\t    NULL, 0), expected, \"Unexpected mallctl() result\");\n\n\tif (config_stats) {\n\t\tassert_zu_gt(allocated, 0,\n\t\t    \"allocated should be greater than zero\");\n\t\tassert_u64_gt(nmalloc, 0,\n\t\t    \"nmalloc should be greater than zero\");\n\t\tassert_u64_ge(nmalloc, ndalloc,\n\t\t    \"nmalloc should be at least as large as ndalloc\");\n\t}\n\n\tdallocx(p, 0);\n}\nTEST_END\n\nTEST_BEGIN(test_stats_arenas_bins)\n{\n\tunsigned arena;\n\tvoid *p;\n\tsize_t sz, curruns, curregs;\n\tuint64_t epoch, nmalloc, ndalloc, nrequests, nfills, nflushes;\n\tuint64_t nruns, nreruns;\n\tint expected = config_stats ? 0 : ENOENT;\n\n\tarena = 0;\n\tassert_d_eq(mallctl(\"thread.arena\", NULL, NULL, &arena, sizeof(arena)),\n\t    0, \"Unexpected mallctl() failure\");\n\n\tp = mallocx(arena_bin_info[0].reg_size, 0);\n\tassert_ptr_not_null(p, \"Unexpected mallocx() failure\");\n\n\tassert_d_eq(mallctl(\"thread.tcache.flush\", NULL, NULL, NULL, 0),\n\t    config_tcache ? 0 : ENOENT, \"Unexpected mallctl() result\");\n\n\tassert_d_eq(mallctl(\"epoch\", NULL, NULL, &epoch, sizeof(epoch)), 0,\n\t    \"Unexpected mallctl() failure\");\n\n\tsz = sizeof(uint64_t);\n\tassert_d_eq(mallctl(\"stats.arenas.0.bins.0.nmalloc\", &nmalloc, &sz,\n\t    NULL, 0), expected, \"Unexpected mallctl() result\");\n\tassert_d_eq(mallctl(\"stats.arenas.0.bins.0.ndalloc\", &ndalloc, &sz,\n\t    NULL, 0), expected, \"Unexpected mallctl() result\");\n\tassert_d_eq(mallctl(\"stats.arenas.0.bins.0.nrequests\", &nrequests, &sz,\n\t    NULL, 0), expected, \"Unexpected mallctl() result\");\n\tsz = sizeof(size_t);\n\tassert_d_eq(mallctl(\"stats.arenas.0.bins.0.curregs\", &curregs, &sz,\n\t    NULL, 0), expected, \"Unexpected mallctl() result\");\n\n\tsz = sizeof(uint64_t);\n\tassert_d_eq(mallctl(\"stats.arenas.0.bins.0.nfills\", &nfills, &sz,\n\t    NULL, 0), config_tcache ? expected : ENOENT,\n\t    \"Unexpected mallctl() result\");\n\tassert_d_eq(mallctl(\"stats.arenas.0.bins.0.nflushes\", &nflushes, &sz,\n\t    NULL, 0), config_tcache ? expected : ENOENT,\n\t    \"Unexpected mallctl() result\");\n\n\tassert_d_eq(mallctl(\"stats.arenas.0.bins.0.nruns\", &nruns, &sz,\n\t    NULL, 0), expected, \"Unexpected mallctl() result\");\n\tassert_d_eq(mallctl(\"stats.arenas.0.bins.0.nreruns\", &nreruns, &sz,\n\t    NULL, 0), expected, \"Unexpected mallctl() result\");\n\tsz = sizeof(size_t);\n\tassert_d_eq(mallctl(\"stats.arenas.0.bins.0.curruns\", &curruns, &sz,\n\t    NULL, 0), expected, \"Unexpected mallctl() result\");\n\n\tif (config_stats) {\n\t\tassert_u64_gt(nmalloc, 0,\n\t\t    \"nmalloc should be greater than zero\");\n\t\tassert_u64_ge(nmalloc, ndalloc,\n\t\t    \"nmalloc should be at least as large as ndalloc\");\n\t\tassert_u64_gt(nrequests, 0,\n\t\t    \"nrequests should be greater than zero\");\n\t\tassert_zu_gt(curregs, 0,\n\t\t    \"allocated should be greater than zero\");\n\t\tif (config_tcache) {\n\t\t\tassert_u64_gt(nfills, 0,\n\t\t\t    \"At least one fill should have occurred\");\n\t\t\tassert_u64_gt(nflushes, 0,\n\t\t\t    \"At least one flush should have occurred\");\n\t\t}\n\t\tassert_u64_gt(nruns, 0,\n\t\t    \"At least one run should have been allocated\");\n\t\tassert_zu_gt(curruns, 0,\n\t\t    \"At least one run should be currently allocated\");\n\t}\n\n\tdallocx(p, 0);\n}\nTEST_END\n\nTEST_BEGIN(test_stats_arenas_lruns)\n{\n\tunsigned arena;\n\tvoid *p;\n\tuint64_t epoch, nmalloc, ndalloc, nrequests;\n\tsize_t curruns, sz;\n\tint expected = config_stats ? 0 : ENOENT;\n\n\tarena = 0;\n\tassert_d_eq(mallctl(\"thread.arena\", NULL, NULL, &arena, sizeof(arena)),\n\t    0, \"Unexpected mallctl() failure\");\n\n\tp = mallocx(LARGE_MINCLASS, 0);\n\tassert_ptr_not_null(p, \"Unexpected mallocx() failure\");\n\n\tassert_d_eq(mallctl(\"epoch\", NULL, NULL, &epoch, sizeof(epoch)), 0,\n\t    \"Unexpected mallctl() failure\");\n\n\tsz = sizeof(uint64_t);\n\tassert_d_eq(mallctl(\"stats.arenas.0.lruns.0.nmalloc\", &nmalloc, &sz,\n\t    NULL, 0), expected, \"Unexpected mallctl() result\");\n\tassert_d_eq(mallctl(\"stats.arenas.0.lruns.0.ndalloc\", &ndalloc, &sz,\n\t    NULL, 0), expected, \"Unexpected mallctl() result\");\n\tassert_d_eq(mallctl(\"stats.arenas.0.lruns.0.nrequests\", &nrequests, &sz,\n\t    NULL, 0), expected, \"Unexpected mallctl() result\");\n\tsz = sizeof(size_t);\n\tassert_d_eq(mallctl(\"stats.arenas.0.lruns.0.curruns\", &curruns, &sz,\n\t    NULL, 0), expected, \"Unexpected mallctl() result\");\n\n\tif (config_stats) {\n\t\tassert_u64_gt(nmalloc, 0,\n\t\t    \"nmalloc should be greater than zero\");\n\t\tassert_u64_ge(nmalloc, ndalloc,\n\t\t    \"nmalloc should be at least as large as ndalloc\");\n\t\tassert_u64_gt(nrequests, 0,\n\t\t    \"nrequests should be greater than zero\");\n\t\tassert_u64_gt(curruns, 0,\n\t\t    \"At least one run should be currently allocated\");\n\t}\n\n\tdallocx(p, 0);\n}\nTEST_END\n\nTEST_BEGIN(test_stats_arenas_hchunks)\n{\n\tunsigned arena;\n\tvoid *p;\n\tuint64_t epoch, nmalloc, ndalloc;\n\tsize_t curhchunks, sz;\n\tint expected = config_stats ? 0 : ENOENT;\n\n\tarena = 0;\n\tassert_d_eq(mallctl(\"thread.arena\", NULL, NULL, &arena, sizeof(arena)),\n\t    0, \"Unexpected mallctl() failure\");\n\n\tp = mallocx(chunksize, 0);\n\tassert_ptr_not_null(p, \"Unexpected mallocx() failure\");\n\n\tassert_d_eq(mallctl(\"epoch\", NULL, NULL, &epoch, sizeof(epoch)), 0,\n\t    \"Unexpected mallctl() failure\");\n\n\tsz = sizeof(uint64_t);\n\tassert_d_eq(mallctl(\"stats.arenas.0.hchunks.0.nmalloc\", &nmalloc, &sz,\n\t    NULL, 0), expected, \"Unexpected mallctl() result\");\n\tassert_d_eq(mallctl(\"stats.arenas.0.hchunks.0.ndalloc\", &ndalloc, &sz,\n\t    NULL, 0), expected, \"Unexpected mallctl() result\");\n\tsz = sizeof(size_t);\n\tassert_d_eq(mallctl(\"stats.arenas.0.hchunks.0.curhchunks\", &curhchunks,\n\t    &sz, NULL, 0), expected, \"Unexpected mallctl() result\");\n\n\tif (config_stats) {\n\t\tassert_u64_gt(nmalloc, 0,\n\t\t    \"nmalloc should be greater than zero\");\n\t\tassert_u64_ge(nmalloc, ndalloc,\n\t\t    \"nmalloc should be at least as large as ndalloc\");\n\t\tassert_u64_gt(curhchunks, 0,\n\t\t    \"At least one chunk should be currently allocated\");\n\t}\n\n\tdallocx(p, 0);\n}\nTEST_END\n\nint\nmain(void)\n{\n\n\treturn (test(\n\t    test_stats_summary,\n\t    test_stats_huge,\n\t    test_stats_arenas_summary,\n\t    test_stats_arenas_small,\n\t    test_stats_arenas_large,\n\t    test_stats_arenas_huge,\n\t    test_stats_arenas_bins,\n\t    test_stats_arenas_lruns,\n\t    test_stats_arenas_hchunks));\n}\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/deps/jemalloc/test/unit/ticker.c",
    "content": "#include \"test/jemalloc_test.h\"\n\nTEST_BEGIN(test_ticker_tick)\n{\n#define\tNREPS 2\n#define\tNTICKS 3\n\tticker_t ticker;\n\tint32_t i, j;\n\n\tticker_init(&ticker, NTICKS);\n\tfor (i = 0; i < NREPS; i++) {\n\t\tfor (j = 0; j < NTICKS; j++) {\n\t\t\tassert_u_eq(ticker_read(&ticker), NTICKS - j,\n\t\t\t    \"Unexpected ticker value (i=%d, j=%d)\", i, j);\n\t\t\tassert_false(ticker_tick(&ticker),\n\t\t\t    \"Unexpected ticker fire (i=%d, j=%d)\", i, j);\n\t\t}\n\t\tassert_u32_eq(ticker_read(&ticker), 0,\n\t\t    \"Expected ticker depletion\");\n\t\tassert_true(ticker_tick(&ticker),\n\t\t    \"Expected ticker fire (i=%d)\", i);\n\t\tassert_u32_eq(ticker_read(&ticker), NTICKS,\n\t\t    \"Expected ticker reset\");\n\t}\n#undef NTICKS\n}\nTEST_END\n\nTEST_BEGIN(test_ticker_ticks)\n{\n#define\tNTICKS 3\n\tticker_t ticker;\n\n\tticker_init(&ticker, NTICKS);\n\n\tassert_u_eq(ticker_read(&ticker), NTICKS, \"Unexpected ticker value\");\n\tassert_false(ticker_ticks(&ticker, NTICKS), \"Unexpected ticker fire\");\n\tassert_u_eq(ticker_read(&ticker), 0, \"Unexpected ticker value\");\n\tassert_true(ticker_ticks(&ticker, NTICKS), \"Expected ticker fire\");\n\tassert_u_eq(ticker_read(&ticker), NTICKS, \"Unexpected ticker value\");\n\n\tassert_true(ticker_ticks(&ticker, NTICKS + 1), \"Expected ticker fire\");\n\tassert_u_eq(ticker_read(&ticker), NTICKS, \"Unexpected ticker value\");\n#undef NTICKS\n}\nTEST_END\n\nTEST_BEGIN(test_ticker_copy)\n{\n#define\tNTICKS 3\n\tticker_t ta, tb;\n\n\tticker_init(&ta, NTICKS);\n\tticker_copy(&tb, &ta);\n\tassert_u_eq(ticker_read(&tb), NTICKS, \"Unexpected ticker value\");\n\tassert_true(ticker_ticks(&tb, NTICKS + 1), \"Expected ticker fire\");\n\tassert_u_eq(ticker_read(&tb), NTICKS, \"Unexpected ticker value\");\n\n\tticker_tick(&ta);\n\tticker_copy(&tb, &ta);\n\tassert_u_eq(ticker_read(&tb), NTICKS - 1, \"Unexpected ticker value\");\n\tassert_true(ticker_ticks(&tb, NTICKS), \"Expected ticker fire\");\n\tassert_u_eq(ticker_read(&tb), NTICKS, \"Unexpected ticker value\");\n#undef NTICKS\n}\nTEST_END\n\nint\nmain(void)\n{\n\n\treturn (test(\n\t    test_ticker_tick,\n\t    test_ticker_ticks,\n\t    test_ticker_copy));\n}\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/deps/jemalloc/test/unit/tsd.c",
    "content": "#include \"test/jemalloc_test.h\"\n\n#define\tTHREAD_DATA 0x72b65c10\n\ntypedef unsigned int data_t;\n\nstatic bool data_cleanup_executed;\n\nmalloc_tsd_types(data_, data_t)\nmalloc_tsd_protos(, data_, data_t)\n\nvoid\ndata_cleanup(void *arg)\n{\n\tdata_t *data = (data_t *)arg;\n\n\tif (!data_cleanup_executed) {\n\t\tassert_x_eq(*data, THREAD_DATA,\n\t\t    \"Argument passed into cleanup function should match tsd \"\n\t\t    \"value\");\n\t}\n\tdata_cleanup_executed = true;\n\n\t/*\n\t * Allocate during cleanup for two rounds, in order to assure that\n\t * jemalloc's internal tsd reinitialization happens.\n\t */\n\tswitch (*data) {\n\tcase THREAD_DATA:\n\t\t*data = 1;\n\t\tdata_tsd_set(data);\n\t\tbreak;\n\tcase 1:\n\t\t*data = 2;\n\t\tdata_tsd_set(data);\n\t\tbreak;\n\tcase 2:\n\t\treturn;\n\tdefault:\n\t\tnot_reached();\n\t}\n\n\t{\n\t\tvoid *p = mallocx(1, 0);\n\t\tassert_ptr_not_null(p, \"Unexpeced mallocx() failure\");\n\t\tdallocx(p, 0);\n\t}\n}\n\nmalloc_tsd_externs(data_, data_t)\n#define\tDATA_INIT 0x12345678\nmalloc_tsd_data(, data_, data_t, DATA_INIT)\nmalloc_tsd_funcs(, data_, data_t, DATA_INIT, data_cleanup)\n\nstatic void *\nthd_start(void *arg)\n{\n\tdata_t d = (data_t)(uintptr_t)arg;\n\tvoid *p;\n\n\tassert_x_eq(*data_tsd_get(), DATA_INIT,\n\t    \"Initial tsd get should return initialization value\");\n\n\tp = malloc(1);\n\tassert_ptr_not_null(p, \"Unexpected malloc() failure\");\n\n\tdata_tsd_set(&d);\n\tassert_x_eq(*data_tsd_get(), d,\n\t    \"After tsd set, tsd get should return value that was set\");\n\n\td = 0;\n\tassert_x_eq(*data_tsd_get(), (data_t)(uintptr_t)arg,\n\t    \"Resetting local data should have no effect on tsd\");\n\n\tfree(p);\n\treturn (NULL);\n}\n\nTEST_BEGIN(test_tsd_main_thread)\n{\n\n\tthd_start((void *) 0xa5f3e329);\n}\nTEST_END\n\nTEST_BEGIN(test_tsd_sub_thread)\n{\n\tthd_t thd;\n\n\tdata_cleanup_executed = false;\n\tthd_create(&thd, thd_start, (void *)THREAD_DATA);\n\tthd_join(thd, NULL);\n\tassert_true(data_cleanup_executed,\n\t    \"Cleanup function should have executed\");\n}\nTEST_END\n\nint\nmain(void)\n{\n\n\t/* Core tsd bootstrapping must happen prior to data_tsd_boot(). */\n\tif (nallocx(1, 0) == 0) {\n\t\tmalloc_printf(\"Initialization error\");\n\t\treturn (test_status_fail);\n\t}\n\tdata_tsd_boot();\n\n\treturn (test(\n\t    test_tsd_main_thread,\n\t    test_tsd_sub_thread));\n}\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/deps/jemalloc/test/unit/util.c",
    "content": "#include \"test/jemalloc_test.h\"\n\n#define\tTEST_POW2_CEIL(t, suf, pri) do {\t\t\t\t\\\n\tunsigned i, pow2;\t\t\t\t\t\t\\\n\tt x;\t\t\t\t\t\t\t\t\\\n\t\t\t\t\t\t\t\t\t\\\n\tassert_##suf##_eq(pow2_ceil_##suf(0), 0, \"Unexpected result\");\t\\\n\t\t\t\t\t\t\t\t\t\\\n\tfor (i = 0; i < sizeof(t) * 8; i++) {\t\t\t\t\\\n\t\tassert_##suf##_eq(pow2_ceil_##suf(((t)1) << i), ((t)1)\t\\\n\t\t    << i, \"Unexpected result\");\t\t\t\t\\\n\t}\t\t\t\t\t\t\t\t\\\n\t\t\t\t\t\t\t\t\t\\\n\tfor (i = 2; i < sizeof(t) * 8; i++) {\t\t\t\t\\\n\t\tassert_##suf##_eq(pow2_ceil_##suf((((t)1) << i) - 1),\t\\\n\t\t    ((t)1) << i, \"Unexpected result\");\t\t\t\\\n\t}\t\t\t\t\t\t\t\t\\\n\t\t\t\t\t\t\t\t\t\\\n\tfor (i = 0; i < sizeof(t) * 8 - 1; i++) {\t\t\t\\\n\t\tassert_##suf##_eq(pow2_ceil_##suf((((t)1) << i) + 1),\t\\\n\t\t    ((t)1) << (i+1), \"Unexpected result\");\t\t\\\n\t}\t\t\t\t\t\t\t\t\\\n\t\t\t\t\t\t\t\t\t\\\n\tfor (pow2 = 1; pow2 < 25; pow2++) {\t\t\t\t\\\n\t\tfor (x = (((t)1) << (pow2-1)) + 1; x <= ((t)1) << pow2;\t\\\n\t\t    x++) {\t\t\t\t\t\t\\\n\t\t\tassert_##suf##_eq(pow2_ceil_##suf(x),\t\t\\\n\t\t\t    ((t)1) << pow2,\t\t\t\t\\\n\t\t\t    \"Unexpected result, x=%\"pri, x);\t\t\\\n\t\t}\t\t\t\t\t\t\t\\\n\t}\t\t\t\t\t\t\t\t\\\n} while (0)\n\nTEST_BEGIN(test_pow2_ceil_u64)\n{\n\n\tTEST_POW2_CEIL(uint64_t, u64, FMTu64);\n}\nTEST_END\n\nTEST_BEGIN(test_pow2_ceil_u32)\n{\n\n\tTEST_POW2_CEIL(uint32_t, u32, FMTu32);\n}\nTEST_END\n\nTEST_BEGIN(test_pow2_ceil_zu)\n{\n\n\tTEST_POW2_CEIL(size_t, zu, \"zu\");\n}\nTEST_END\n\nTEST_BEGIN(test_malloc_strtoumax_no_endptr)\n{\n\tint err;\n\n\tset_errno(0);\n\tassert_ju_eq(malloc_strtoumax(\"0\", NULL, 0), 0, \"Unexpected result\");\n\terr = get_errno();\n\tassert_d_eq(err, 0, \"Unexpected failure\");\n}\nTEST_END\n\nTEST_BEGIN(test_malloc_strtoumax)\n{\n\tstruct test_s {\n\t\tconst char *input;\n\t\tconst char *expected_remainder;\n\t\tint base;\n\t\tint expected_errno;\n\t\tconst char *expected_errno_name;\n\t\tuintmax_t expected_x;\n\t};\n#define\tERR(e)\t\te, #e\n#define\tKUMAX(x)\t((uintmax_t)x##ULL)\n\tstruct test_s tests[] = {\n\t\t{\"0\",\t\t\"0\",\t-1,\tERR(EINVAL),\tUINTMAX_MAX},\n\t\t{\"0\",\t\t\"0\",\t1,\tERR(EINVAL),\tUINTMAX_MAX},\n\t\t{\"0\",\t\t\"0\",\t37,\tERR(EINVAL),\tUINTMAX_MAX},\n\n\t\t{\"\",\t\t\"\",\t0,\tERR(EINVAL),\tUINTMAX_MAX},\n\t\t{\"+\",\t\t\"+\",\t0,\tERR(EINVAL),\tUINTMAX_MAX},\n\t\t{\"++3\",\t\t\"++3\",\t0,\tERR(EINVAL),\tUINTMAX_MAX},\n\t\t{\"-\",\t\t\"-\",\t0,\tERR(EINVAL),\tUINTMAX_MAX},\n\n\t\t{\"42\",\t\t\"\",\t0,\tERR(0),\t\tKUMAX(42)},\n\t\t{\"+42\",\t\t\"\",\t0,\tERR(0),\t\tKUMAX(42)},\n\t\t{\"-42\",\t\t\"\",\t0,\tERR(0),\t\tKUMAX(-42)},\n\t\t{\"042\",\t\t\"\",\t0,\tERR(0),\t\tKUMAX(042)},\n\t\t{\"+042\",\t\"\",\t0,\tERR(0),\t\tKUMAX(042)},\n\t\t{\"-042\",\t\"\",\t0,\tERR(0),\t\tKUMAX(-042)},\n\t\t{\"0x42\",\t\"\",\t0,\tERR(0),\t\tKUMAX(0x42)},\n\t\t{\"+0x42\",\t\"\",\t0,\tERR(0),\t\tKUMAX(0x42)},\n\t\t{\"-0x42\",\t\"\",\t0,\tERR(0),\t\tKUMAX(-0x42)},\n\n\t\t{\"0\",\t\t\"\",\t0,\tERR(0),\t\tKUMAX(0)},\n\t\t{\"1\",\t\t\"\",\t0,\tERR(0),\t\tKUMAX(1)},\n\n\t\t{\"42\",\t\t\"\",\t0,\tERR(0),\t\tKUMAX(42)},\n\t\t{\" 42\",\t\t\"\",\t0,\tERR(0),\t\tKUMAX(42)},\n\t\t{\"42 \",\t\t\" \",\t0,\tERR(0),\t\tKUMAX(42)},\n\t\t{\"0x\",\t\t\"x\",\t0,\tERR(0),\t\tKUMAX(0)},\n\t\t{\"42x\",\t\t\"x\",\t0,\tERR(0),\t\tKUMAX(42)},\n\n\t\t{\"07\",\t\t\"\",\t0,\tERR(0),\t\tKUMAX(7)},\n\t\t{\"010\",\t\t\"\",\t0,\tERR(0),\t\tKUMAX(8)},\n\t\t{\"08\",\t\t\"8\",\t0,\tERR(0),\t\tKUMAX(0)},\n\t\t{\"0_\",\t\t\"_\",\t0,\tERR(0),\t\tKUMAX(0)},\n\n\t\t{\"0x\",\t\t\"x\",\t0,\tERR(0),\t\tKUMAX(0)},\n\t\t{\"0X\",\t\t\"X\",\t0,\tERR(0),\t\tKUMAX(0)},\n\t\t{\"0xg\",\t\t\"xg\",\t0,\tERR(0),\t\tKUMAX(0)},\n\t\t{\"0XA\",\t\t\"\",\t0,\tERR(0),\t\tKUMAX(10)},\n\n\t\t{\"010\",\t\t\"\",\t10,\tERR(0),\t\tKUMAX(10)},\n\t\t{\"0x3\",\t\t\"x3\",\t10,\tERR(0),\t\tKUMAX(0)},\n\n\t\t{\"12\",\t\t\"2\",\t2,\tERR(0),\t\tKUMAX(1)},\n\t\t{\"78\",\t\t\"8\",\t8,\tERR(0),\t\tKUMAX(7)},\n\t\t{\"9a\",\t\t\"a\",\t10,\tERR(0),\t\tKUMAX(9)},\n\t\t{\"9A\",\t\t\"A\",\t10,\tERR(0),\t\tKUMAX(9)},\n\t\t{\"fg\",\t\t\"g\",\t16,\tERR(0),\t\tKUMAX(15)},\n\t\t{\"FG\",\t\t\"G\",\t16,\tERR(0),\t\tKUMAX(15)},\n\t\t{\"0xfg\",\t\"g\",\t16,\tERR(0),\t\tKUMAX(15)},\n\t\t{\"0XFG\",\t\"G\",\t16,\tERR(0),\t\tKUMAX(15)},\n\t\t{\"z_\",\t\t\"_\",\t36,\tERR(0),\t\tKUMAX(35)},\n\t\t{\"Z_\",\t\t\"_\",\t36,\tERR(0),\t\tKUMAX(35)}\n\t};\n#undef ERR\n#undef KUMAX\n\tunsigned i;\n\n\tfor (i = 0; i < sizeof(tests)/sizeof(struct test_s); i++) {\n\t\tstruct test_s *test = &tests[i];\n\t\tint err;\n\t\tuintmax_t result;\n\t\tchar *remainder;\n\n\t\tset_errno(0);\n\t\tresult = malloc_strtoumax(test->input, &remainder, test->base);\n\t\terr = get_errno();\n\t\tassert_d_eq(err, test->expected_errno,\n\t\t    \"Expected errno %s for \\\"%s\\\", base %d\",\n\t\t    test->expected_errno_name, test->input, test->base);\n\t\tassert_str_eq(remainder, test->expected_remainder,\n\t\t    \"Unexpected remainder for \\\"%s\\\", base %d\",\n\t\t    test->input, test->base);\n\t\tif (err == 0) {\n\t\t\tassert_ju_eq(result, test->expected_x,\n\t\t\t    \"Unexpected result for \\\"%s\\\", base %d\",\n\t\t\t    test->input, test->base);\n\t\t}\n\t}\n}\nTEST_END\n\nTEST_BEGIN(test_malloc_snprintf_truncated)\n{\n#define\tBUFLEN\t15\n\tchar buf[BUFLEN];\n\tsize_t result;\n\tsize_t len;\n#define\tTEST(expected_str_untruncated, ...) do {\t\t\t\\\n\tresult = malloc_snprintf(buf, len, __VA_ARGS__);\t\t\\\n\tassert_d_eq(strncmp(buf, expected_str_untruncated, len-1), 0,\t\\\n\t    \"Unexpected string inequality (\\\"%s\\\" vs \\\"%s\\\")\",\t\t\\\n\t    buf, expected_str_untruncated);\t\t\t\t\\\n\tassert_zu_eq(result, strlen(expected_str_untruncated),\t\t\\\n\t    \"Unexpected result\");\t\t\t\t\t\\\n} while (0)\n\n\tfor (len = 1; len < BUFLEN; len++) {\n\t\tTEST(\"012346789\",\t\"012346789\");\n\t\tTEST(\"a0123b\",\t\t\"a%sb\", \"0123\");\n\t\tTEST(\"a01234567\",\t\"a%s%s\", \"0123\", \"4567\");\n\t\tTEST(\"a0123  \",\t\t\"a%-6s\", \"0123\");\n\t\tTEST(\"a  0123\",\t\t\"a%6s\", \"0123\");\n\t\tTEST(\"a   012\",\t\t\"a%6.3s\", \"0123\");\n\t\tTEST(\"a   012\",\t\t\"a%*.*s\", 6, 3, \"0123\");\n\t\tTEST(\"a 123b\",\t\t\"a% db\", 123);\n\t\tTEST(\"a123b\",\t\t\"a%-db\", 123);\n\t\tTEST(\"a-123b\",\t\t\"a%-db\", -123);\n\t\tTEST(\"a+123b\",\t\t\"a%+db\", 123);\n\t}\n#undef BUFLEN\n#undef TEST\n}\nTEST_END\n\nTEST_BEGIN(test_malloc_snprintf)\n{\n#define\tBUFLEN\t128\n\tchar buf[BUFLEN];\n\tsize_t result;\n#define\tTEST(expected_str, ...) do {\t\t\t\t\t\\\n\tresult = malloc_snprintf(buf, sizeof(buf), __VA_ARGS__);\t\\\n\tassert_str_eq(buf, expected_str, \"Unexpected output\");\t\t\\\n\tassert_zu_eq(result, strlen(expected_str), \"Unexpected result\");\\\n} while (0)\n\n\tTEST(\"hello\", \"hello\");\n\n\tTEST(\"50%, 100%\", \"50%%, %d%%\", 100);\n\n\tTEST(\"a0123b\", \"a%sb\", \"0123\");\n\n\tTEST(\"a 0123b\", \"a%5sb\", \"0123\");\n\tTEST(\"a 0123b\", \"a%*sb\", 5, \"0123\");\n\n\tTEST(\"a0123 b\", \"a%-5sb\", \"0123\");\n\tTEST(\"a0123b\", \"a%*sb\", -1, \"0123\");\n\tTEST(\"a0123 b\", \"a%*sb\", -5, \"0123\");\n\tTEST(\"a0123 b\", \"a%-*sb\", -5, \"0123\");\n\n\tTEST(\"a012b\", \"a%.3sb\", \"0123\");\n\tTEST(\"a012b\", \"a%.*sb\", 3, \"0123\");\n\tTEST(\"a0123b\", \"a%.*sb\", -3, \"0123\");\n\n\tTEST(\"a  012b\", \"a%5.3sb\", \"0123\");\n\tTEST(\"a  012b\", \"a%5.*sb\", 3, \"0123\");\n\tTEST(\"a  012b\", \"a%*.3sb\", 5, \"0123\");\n\tTEST(\"a  012b\", \"a%*.*sb\", 5, 3, \"0123\");\n\tTEST(\"a 0123b\", \"a%*.*sb\", 5, -3, \"0123\");\n\n\tTEST(\"_abcd_\", \"_%x_\", 0xabcd);\n\tTEST(\"_0xabcd_\", \"_%#x_\", 0xabcd);\n\tTEST(\"_1234_\", \"_%o_\", 01234);\n\tTEST(\"_01234_\", \"_%#o_\", 01234);\n\tTEST(\"_1234_\", \"_%u_\", 1234);\n\n\tTEST(\"_1234_\", \"_%d_\", 1234);\n\tTEST(\"_ 1234_\", \"_% d_\", 1234);\n\tTEST(\"_+1234_\", \"_%+d_\", 1234);\n\tTEST(\"_-1234_\", \"_%d_\", -1234);\n\tTEST(\"_-1234_\", \"_% d_\", -1234);\n\tTEST(\"_-1234_\", \"_%+d_\", -1234);\n\n\tTEST(\"_-1234_\", \"_%d_\", -1234);\n\tTEST(\"_1234_\", \"_%d_\", 1234);\n\tTEST(\"_-1234_\", \"_%i_\", -1234);\n\tTEST(\"_1234_\", \"_%i_\", 1234);\n\tTEST(\"_01234_\", \"_%#o_\", 01234);\n\tTEST(\"_1234_\", \"_%u_\", 1234);\n\tTEST(\"_0x1234abc_\", \"_%#x_\", 0x1234abc);\n\tTEST(\"_0X1234ABC_\", \"_%#X_\", 0x1234abc);\n\tTEST(\"_c_\", \"_%c_\", 'c');\n\tTEST(\"_string_\", \"_%s_\", \"string\");\n\tTEST(\"_0x42_\", \"_%p_\", ((void *)0x42));\n\n\tTEST(\"_-1234_\", \"_%ld_\", ((long)-1234));\n\tTEST(\"_1234_\", \"_%ld_\", ((long)1234));\n\tTEST(\"_-1234_\", \"_%li_\", ((long)-1234));\n\tTEST(\"_1234_\", \"_%li_\", ((long)1234));\n\tTEST(\"_01234_\", \"_%#lo_\", ((long)01234));\n\tTEST(\"_1234_\", \"_%lu_\", ((long)1234));\n\tTEST(\"_0x1234abc_\", \"_%#lx_\", ((long)0x1234abc));\n\tTEST(\"_0X1234ABC_\", \"_%#lX_\", ((long)0x1234ABC));\n\n\tTEST(\"_-1234_\", \"_%lld_\", ((long long)-1234));\n\tTEST(\"_1234_\", \"_%lld_\", ((long long)1234));\n\tTEST(\"_-1234_\", \"_%lli_\", ((long long)-1234));\n\tTEST(\"_1234_\", \"_%lli_\", ((long long)1234));\n\tTEST(\"_01234_\", \"_%#llo_\", ((long long)01234));\n\tTEST(\"_1234_\", \"_%llu_\", ((long long)1234));\n\tTEST(\"_0x1234abc_\", \"_%#llx_\", ((long long)0x1234abc));\n\tTEST(\"_0X1234ABC_\", \"_%#llX_\", ((long long)0x1234ABC));\n\n\tTEST(\"_-1234_\", \"_%qd_\", ((long long)-1234));\n\tTEST(\"_1234_\", \"_%qd_\", ((long long)1234));\n\tTEST(\"_-1234_\", \"_%qi_\", ((long long)-1234));\n\tTEST(\"_1234_\", \"_%qi_\", ((long long)1234));\n\tTEST(\"_01234_\", \"_%#qo_\", ((long long)01234));\n\tTEST(\"_1234_\", \"_%qu_\", ((long long)1234));\n\tTEST(\"_0x1234abc_\", \"_%#qx_\", ((long long)0x1234abc));\n\tTEST(\"_0X1234ABC_\", \"_%#qX_\", ((long long)0x1234ABC));\n\n\tTEST(\"_-1234_\", \"_%jd_\", ((intmax_t)-1234));\n\tTEST(\"_1234_\", \"_%jd_\", ((intmax_t)1234));\n\tTEST(\"_-1234_\", \"_%ji_\", ((intmax_t)-1234));\n\tTEST(\"_1234_\", \"_%ji_\", ((intmax_t)1234));\n\tTEST(\"_01234_\", \"_%#jo_\", ((intmax_t)01234));\n\tTEST(\"_1234_\", \"_%ju_\", ((intmax_t)1234));\n\tTEST(\"_0x1234abc_\", \"_%#jx_\", ((intmax_t)0x1234abc));\n\tTEST(\"_0X1234ABC_\", \"_%#jX_\", ((intmax_t)0x1234ABC));\n\n\tTEST(\"_1234_\", \"_%td_\", ((ptrdiff_t)1234));\n\tTEST(\"_-1234_\", \"_%td_\", ((ptrdiff_t)-1234));\n\tTEST(\"_1234_\", \"_%ti_\", ((ptrdiff_t)1234));\n\tTEST(\"_-1234_\", \"_%ti_\", ((ptrdiff_t)-1234));\n\n\tTEST(\"_-1234_\", \"_%zd_\", ((ssize_t)-1234));\n\tTEST(\"_1234_\", \"_%zd_\", ((ssize_t)1234));\n\tTEST(\"_-1234_\", \"_%zi_\", ((ssize_t)-1234));\n\tTEST(\"_1234_\", \"_%zi_\", ((ssize_t)1234));\n\tTEST(\"_01234_\", \"_%#zo_\", ((ssize_t)01234));\n\tTEST(\"_1234_\", \"_%zu_\", ((ssize_t)1234));\n\tTEST(\"_0x1234abc_\", \"_%#zx_\", ((ssize_t)0x1234abc));\n\tTEST(\"_0X1234ABC_\", \"_%#zX_\", ((ssize_t)0x1234ABC));\n#undef BUFLEN\n}\nTEST_END\n\nint\nmain(void)\n{\n\n\treturn (test(\n\t    test_pow2_ceil_u64,\n\t    test_pow2_ceil_u32,\n\t    test_pow2_ceil_zu,\n\t    test_malloc_strtoumax_no_endptr,\n\t    test_malloc_strtoumax,\n\t    test_malloc_snprintf_truncated,\n\t    test_malloc_snprintf));\n}\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/deps/jemalloc/test/unit/witness.c",
    "content": "#include \"test/jemalloc_test.h\"\n\nstatic witness_lock_error_t *witness_lock_error_orig;\nstatic witness_owner_error_t *witness_owner_error_orig;\nstatic witness_not_owner_error_t *witness_not_owner_error_orig;\nstatic witness_lockless_error_t *witness_lockless_error_orig;\n\nstatic bool saw_lock_error;\nstatic bool saw_owner_error;\nstatic bool saw_not_owner_error;\nstatic bool saw_lockless_error;\n\nstatic void\nwitness_lock_error_intercept(const witness_list_t *witnesses,\n    const witness_t *witness)\n{\n\n\tsaw_lock_error = true;\n}\n\nstatic void\nwitness_owner_error_intercept(const witness_t *witness)\n{\n\n\tsaw_owner_error = true;\n}\n\nstatic void\nwitness_not_owner_error_intercept(const witness_t *witness)\n{\n\n\tsaw_not_owner_error = true;\n}\n\nstatic void\nwitness_lockless_error_intercept(const witness_list_t *witnesses)\n{\n\n\tsaw_lockless_error = true;\n}\n\nstatic int\nwitness_comp(const witness_t *a, const witness_t *b)\n{\n\n\tassert_u_eq(a->rank, b->rank, \"Witnesses should have equal rank\");\n\n\treturn (strcmp(a->name, b->name));\n}\n\nstatic int\nwitness_comp_reverse(const witness_t *a, const witness_t *b)\n{\n\n\tassert_u_eq(a->rank, b->rank, \"Witnesses should have equal rank\");\n\n\treturn (-strcmp(a->name, b->name));\n}\n\nTEST_BEGIN(test_witness)\n{\n\twitness_t a, b;\n\ttsdn_t *tsdn;\n\n\ttest_skip_if(!config_debug);\n\n\ttsdn = tsdn_fetch();\n\n\twitness_assert_lockless(tsdn);\n\n\twitness_init(&a, \"a\", 1, NULL);\n\twitness_assert_not_owner(tsdn, &a);\n\twitness_lock(tsdn, &a);\n\twitness_assert_owner(tsdn, &a);\n\n\twitness_init(&b, \"b\", 2, NULL);\n\twitness_assert_not_owner(tsdn, &b);\n\twitness_lock(tsdn, &b);\n\twitness_assert_owner(tsdn, &b);\n\n\twitness_unlock(tsdn, &a);\n\twitness_unlock(tsdn, &b);\n\n\twitness_assert_lockless(tsdn);\n}\nTEST_END\n\nTEST_BEGIN(test_witness_comp)\n{\n\twitness_t a, b, c, d;\n\ttsdn_t *tsdn;\n\n\ttest_skip_if(!config_debug);\n\n\ttsdn = tsdn_fetch();\n\n\twitness_assert_lockless(tsdn);\n\n\twitness_init(&a, \"a\", 1, witness_comp);\n\twitness_assert_not_owner(tsdn, &a);\n\twitness_lock(tsdn, &a);\n\twitness_assert_owner(tsdn, &a);\n\n\twitness_init(&b, \"b\", 1, witness_comp);\n\twitness_assert_not_owner(tsdn, &b);\n\twitness_lock(tsdn, &b);\n\twitness_assert_owner(tsdn, &b);\n\twitness_unlock(tsdn, &b);\n\n\twitness_lock_error_orig = witness_lock_error;\n\twitness_lock_error = witness_lock_error_intercept;\n\tsaw_lock_error = false;\n\n\twitness_init(&c, \"c\", 1, witness_comp_reverse);\n\twitness_assert_not_owner(tsdn, &c);\n\tassert_false(saw_lock_error, \"Unexpected witness lock error\");\n\twitness_lock(tsdn, &c);\n\tassert_true(saw_lock_error, \"Expected witness lock error\");\n\twitness_unlock(tsdn, &c);\n\n\tsaw_lock_error = false;\n\n\twitness_init(&d, \"d\", 1, NULL);\n\twitness_assert_not_owner(tsdn, &d);\n\tassert_false(saw_lock_error, \"Unexpected witness lock error\");\n\twitness_lock(tsdn, &d);\n\tassert_true(saw_lock_error, \"Expected witness lock error\");\n\twitness_unlock(tsdn, &d);\n\n\twitness_unlock(tsdn, &a);\n\n\twitness_assert_lockless(tsdn);\n\n\twitness_lock_error = witness_lock_error_orig;\n}\nTEST_END\n\nTEST_BEGIN(test_witness_reversal)\n{\n\twitness_t a, b;\n\ttsdn_t *tsdn;\n\n\ttest_skip_if(!config_debug);\n\n\twitness_lock_error_orig = witness_lock_error;\n\twitness_lock_error = witness_lock_error_intercept;\n\tsaw_lock_error = false;\n\n\ttsdn = tsdn_fetch();\n\n\twitness_assert_lockless(tsdn);\n\n\twitness_init(&a, \"a\", 1, NULL);\n\twitness_init(&b, \"b\", 2, NULL);\n\n\twitness_lock(tsdn, &b);\n\tassert_false(saw_lock_error, \"Unexpected witness lock error\");\n\twitness_lock(tsdn, &a);\n\tassert_true(saw_lock_error, \"Expected witness lock error\");\n\n\twitness_unlock(tsdn, &a);\n\twitness_unlock(tsdn, &b);\n\n\twitness_assert_lockless(tsdn);\n\n\twitness_lock_error = witness_lock_error_orig;\n}\nTEST_END\n\nTEST_BEGIN(test_witness_recursive)\n{\n\twitness_t a;\n\ttsdn_t *tsdn;\n\n\ttest_skip_if(!config_debug);\n\n\twitness_not_owner_error_orig = witness_not_owner_error;\n\twitness_not_owner_error = witness_not_owner_error_intercept;\n\tsaw_not_owner_error = false;\n\n\twitness_lock_error_orig = witness_lock_error;\n\twitness_lock_error = witness_lock_error_intercept;\n\tsaw_lock_error = false;\n\n\ttsdn = tsdn_fetch();\n\n\twitness_assert_lockless(tsdn);\n\n\twitness_init(&a, \"a\", 1, NULL);\n\n\twitness_lock(tsdn, &a);\n\tassert_false(saw_lock_error, \"Unexpected witness lock error\");\n\tassert_false(saw_not_owner_error, \"Unexpected witness not owner error\");\n\twitness_lock(tsdn, &a);\n\tassert_true(saw_lock_error, \"Expected witness lock error\");\n\tassert_true(saw_not_owner_error, \"Expected witness not owner error\");\n\n\twitness_unlock(tsdn, &a);\n\n\twitness_assert_lockless(tsdn);\n\n\twitness_owner_error = witness_owner_error_orig;\n\twitness_lock_error = witness_lock_error_orig;\n\n}\nTEST_END\n\nTEST_BEGIN(test_witness_unlock_not_owned)\n{\n\twitness_t a;\n\ttsdn_t *tsdn;\n\n\ttest_skip_if(!config_debug);\n\n\twitness_owner_error_orig = witness_owner_error;\n\twitness_owner_error = witness_owner_error_intercept;\n\tsaw_owner_error = false;\n\n\ttsdn = tsdn_fetch();\n\n\twitness_assert_lockless(tsdn);\n\n\twitness_init(&a, \"a\", 1, NULL);\n\n\tassert_false(saw_owner_error, \"Unexpected owner error\");\n\twitness_unlock(tsdn, &a);\n\tassert_true(saw_owner_error, \"Expected owner error\");\n\n\twitness_assert_lockless(tsdn);\n\n\twitness_owner_error = witness_owner_error_orig;\n}\nTEST_END\n\nTEST_BEGIN(test_witness_lockful)\n{\n\twitness_t a;\n\ttsdn_t *tsdn;\n\n\ttest_skip_if(!config_debug);\n\n\twitness_lockless_error_orig = witness_lockless_error;\n\twitness_lockless_error = witness_lockless_error_intercept;\n\tsaw_lockless_error = false;\n\n\ttsdn = tsdn_fetch();\n\n\twitness_assert_lockless(tsdn);\n\n\twitness_init(&a, \"a\", 1, NULL);\n\n\tassert_false(saw_lockless_error, \"Unexpected lockless error\");\n\twitness_assert_lockless(tsdn);\n\n\twitness_lock(tsdn, &a);\n\twitness_assert_lockless(tsdn);\n\tassert_true(saw_lockless_error, \"Expected lockless error\");\n\n\twitness_unlock(tsdn, &a);\n\n\twitness_assert_lockless(tsdn);\n\n\twitness_lockless_error = witness_lockless_error_orig;\n}\nTEST_END\n\nint\nmain(void)\n{\n\n\treturn (test(\n\t    test_witness,\n\t    test_witness_comp,\n\t    test_witness_reversal,\n\t    test_witness_recursive,\n\t    test_witness_unlock_not_owned,\n\t    test_witness_lockful));\n}\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/deps/jemalloc/test/unit/zero.c",
    "content": "#include \"test/jemalloc_test.h\"\n\n#ifdef JEMALLOC_FILL\nconst char *malloc_conf =\n    \"abort:false,junk:false,zero:true,redzone:false,quarantine:0\";\n#endif\n\nstatic void\ntest_zero(size_t sz_min, size_t sz_max)\n{\n\tuint8_t *s;\n\tsize_t sz_prev, sz, i;\n#define\tMAGIC\t((uint8_t)0x61)\n\n\tsz_prev = 0;\n\ts = (uint8_t *)mallocx(sz_min, 0);\n\tassert_ptr_not_null((void *)s, \"Unexpected mallocx() failure\");\n\n\tfor (sz = sallocx(s, 0); sz <= sz_max;\n\t    sz_prev = sz, sz = sallocx(s, 0)) {\n\t\tif (sz_prev > 0) {\n\t\t\tassert_u_eq(s[0], MAGIC,\n\t\t\t    \"Previously allocated byte %zu/%zu is corrupted\",\n\t\t\t    ZU(0), sz_prev);\n\t\t\tassert_u_eq(s[sz_prev-1], MAGIC,\n\t\t\t    \"Previously allocated byte %zu/%zu is corrupted\",\n\t\t\t    sz_prev-1, sz_prev);\n\t\t}\n\n\t\tfor (i = sz_prev; i < sz; i++) {\n\t\t\tassert_u_eq(s[i], 0x0,\n\t\t\t    \"Newly allocated byte %zu/%zu isn't zero-filled\",\n\t\t\t    i, sz);\n\t\t\ts[i] = MAGIC;\n\t\t}\n\n\t\tif (xallocx(s, sz+1, 0, 0) == sz) {\n\t\t\ts = (uint8_t *)rallocx(s, sz+1, 0);\n\t\t\tassert_ptr_not_null((void *)s,\n\t\t\t    \"Unexpected rallocx() failure\");\n\t\t}\n\t}\n\n\tdallocx(s, 0);\n#undef MAGIC\n}\n\nTEST_BEGIN(test_zero_small)\n{\n\n\ttest_skip_if(!config_fill);\n\ttest_zero(1, SMALL_MAXCLASS-1);\n}\nTEST_END\n\nTEST_BEGIN(test_zero_large)\n{\n\n\ttest_skip_if(!config_fill);\n\ttest_zero(SMALL_MAXCLASS+1, large_maxclass);\n}\nTEST_END\n\nTEST_BEGIN(test_zero_huge)\n{\n\n\ttest_skip_if(!config_fill);\n\ttest_zero(large_maxclass+1, chunksize*2);\n}\nTEST_END\n\nint\nmain(void)\n{\n\n\treturn (test(\n\t    test_zero_small,\n\t    test_zero_large,\n\t    test_zero_huge));\n}\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/deps/linenoise/.gitignore",
    "content": "linenoise_example\n*.dSYM\nhistory.txt\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/deps/linenoise/Makefile",
    "content": "STD=\nWARN= -Wall\nOPT= -Os\n\nR_CFLAGS= $(STD) $(WARN) $(OPT) $(DEBUG) $(CFLAGS)\nR_LDFLAGS= $(LDFLAGS)\nDEBUG= -g\n\nR_CC=$(CC) $(R_CFLAGS)\nR_LD=$(CC) $(R_LDFLAGS)\n\nlinenoise.o: linenoise.h linenoise.c\n\nlinenoise_example: linenoise.o example.o\n\t$(R_LD) -o $@ $^\n\n.c.o:\n\t$(R_CC) -c $<\n\nclean:\n\trm -f linenoise_example *.o\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/deps/linenoise/README.markdown",
    "content": "# Linenoise\n\nA minimal, zero-config, BSD licensed, readline replacement used in Redis,\nMongoDB, and Android.\n\n* Single and multi line editing mode with the usual key bindings implemented.\n* History handling.\n* Completion.\n* Hints (suggestions at the right of the prompt as you type).\n* About 1,100 lines of BSD license source code.\n* Only uses a subset of VT100 escapes (ANSI.SYS compatible).\n\n## Can a line editing library be 20k lines of code?\n\nLine editing with some support for history is a really important feature for command line utilities. Instead of retyping almost the same stuff again and again it's just much better to hit the up arrow and edit on syntax errors, or in order to try a slightly different command. But apparently code dealing with terminals is some sort of Black Magic: readline is 30k lines of code, libedit 20k. Is it reasonable to link small utilities to huge libraries just to get a minimal support for line editing?\n\nSo what usually happens is either:\n\n * Large programs with configure scripts disabling line editing if readline is not present in the system, or not supporting it at all since readline is GPL licensed and libedit (the BSD clone) is not as known and available as readline is (Real world example of this problem: Tclsh).\n * Smaller programs not using a configure script not supporting line editing at all (A problem we had with Redis-cli for instance).\n \nThe result is a pollution of binaries without line editing support.\n\nSo I spent more or less two hours doing a reality check resulting in this little library: is it *really* needed for a line editing library to be 20k lines of code? Apparently not, it is possibe to get a very small, zero configuration, trivial to embed library, that solves the problem. Smaller programs will just include this, supporing line editing out of the box. Larger programs may use this little library or just checking with configure if readline/libedit is available and resorting to Linenoise if not.\n\n## Terminals, in 2010.\n\nApparently almost every terminal you can happen to use today has some kind of support for basic VT100 escape sequences. So I tried to write a lib using just very basic VT100 features. The resulting library appears to work everywhere I tried to use it, and now can work even on ANSI.SYS compatible terminals, since no\nVT220 specific sequences are used anymore.\n\nThe library is currently about 1100 lines of code. In order to use it in your project just look at the *example.c* file in the source distribution, it is trivial. Linenoise is BSD code, so you can use both in free software and commercial software.\n\n## Tested with...\n\n * Linux text only console ($TERM = linux)\n * Linux KDE terminal application ($TERM = xterm)\n * Linux xterm ($TERM = xterm)\n * Linux Buildroot ($TERM = vt100)\n * Mac OS X iTerm ($TERM = xterm)\n * Mac OS X default Terminal.app ($TERM = xterm)\n * OpenBSD 4.5 through an OSX Terminal.app ($TERM = screen)\n * IBM AIX 6.1\n * FreeBSD xterm ($TERM = xterm)\n * ANSI.SYS\n * Emacs comint mode ($TERM = dumb)\n\nPlease test it everywhere you can and report back!\n\n## Let's push this forward!\n\nPatches should be provided in the respect of Linenoise sensibility for small\neasy to understand code.\n\nSend feedbacks to antirez at gmail\n\n# The API\n\nLinenoise is very easy to use, and reading the example shipped with the\nlibrary should get you up to speed ASAP. Here is a list of API calls\nand how to use them.\n\n    char *linenoise(const char *prompt);\n\nThis is the main Linenoise call: it shows the user a prompt with line editing\nand history capabilities. The prompt you specify is used as a prompt, that is,\nit will be printed to the left of the cursor. The library returns a buffer\nwith the line composed by the user, or NULL on end of file or when there\nis an out of memory condition.\n\nWhen a tty is detected (the user is actually typing into a terminal session)\nthe maximum editable line length is `LINENOISE_MAX_LINE`. When instead the\nstandard input is not a tty, which happens every time you redirect a file\nto a program, or use it in an Unix pipeline, there are no limits to the\nlength of the line that can be returned.\n\nThe returned line should be freed with the `free()` standard system call.\nHowever sometimes it could happen that your program uses a different dynamic\nallocation library, so you may also used `linenoiseFree` to make sure the\nline is freed with the same allocator it was created.\n\nThe canonical loop used by a program using Linenoise will be something like\nthis:\n\n    while((line = linenoise(\"hello> \")) != NULL) {\n        printf(\"You wrote: %s\\n\", line);\n        linenoiseFree(line); /* Or just free(line) if you use libc malloc. */\n    }\n\n## Single line VS multi line editing\n\nBy default, Linenoise uses single line editing, that is, a single row on the\nscreen will be used, and as the user types more, the text will scroll towards\nleft to make room. This works if your program is one where the user is\nunlikely to write a lot of text, otherwise multi line editing, where multiple\nscreens rows are used, can be a lot more comfortable.\n\nIn order to enable multi line editing use the following API call:\n\n    linenoiseSetMultiLine(1);\n\nYou can disable it using `0` as argument.\n\n## History\n\nLinenoise supporst history, so that the user does not have to retype\nagain and again the same things, but can use the down and up arrows in order\nto search and re-edit already inserted lines of text.\n\nThe followings are the history API calls:\n\n    int linenoiseHistoryAdd(const char *line);\n    int linenoiseHistorySetMaxLen(int len);\n    int linenoiseHistorySave(const char *filename);\n    int linenoiseHistoryLoad(const char *filename);\n\nUse `linenoiseHistoryAdd` every time you want to add a new element\nto the top of the history (it will be the first the user will see when\nusing the up arrow).\n\nNote that for history to work, you have to set a length for the history\n(which is zero by default, so history will be disabled if you don't set\na proper one). This is accomplished using the `linenoiseHistorySetMaxLen`\nfunction.\n\nLinenoise has direct support for persisting the history into an history\nfile. The functions `linenoiseHistorySave` and `linenoiseHistoryLoad` do\njust that. Both functions return -1 on error and 0 on success.\n\n## Completion\n\nLinenoise supports completion, which is the ability to complete the user\ninput when she or he presses the `<TAB>` key.\n\nIn order to use completion, you need to register a completion callback, which\nis called every time the user presses `<TAB>`. Your callback will return a\nlist of items that are completions for the current string.\n\nThe following is an example of registering a completion callback:\n\n    linenoiseSetCompletionCallback(completion);\n\nThe completion must be a function returning `void` and getting as input\na `const char` pointer, which is the line the user has typed so far, and\na `linenoiseCompletions` object pointer, which is used as argument of\n`linenoiseAddCompletion` in order to add completions inside the callback.\nAn example will make it more clear:\n\n    void completion(const char *buf, linenoiseCompletions *lc) {\n        if (buf[0] == 'h') {\n            linenoiseAddCompletion(lc,\"hello\");\n            linenoiseAddCompletion(lc,\"hello there\");\n        }\n    }\n\nBasically in your completion callback, you inspect the input, and return\na list of items that are good completions by using `linenoiseAddCompletion`.\n\nIf you want to test the completion feature, compile the example program\nwith `make`, run it, type `h` and press `<TAB>`.\n\n## Hints\n\nLinenoise has a feature called *hints* which is very useful when you\nuse Linenoise in order to implement a REPL (Read Eval Print Loop) for\na program that accepts commands and arguments, but may also be useful in\nother conditions.\n\nThe feature shows, on the right of the cursor, as the user types, hints that\nmay be useful. The hints can be displayed using a different color compared\nto the color the user is typing, and can also be bold.\n\nFor example as the user starts to type `\"git remote add\"`, with hints it's\npossible to show on the right of the prompt a string `<name> <url>`.\n\nThe feature works similarly to the history feature, using a callback.\nTo register the callback we use:\n\n    linenoiseSetHintsCallback(hints);\n\nThe callback itself is implemented like this:\n\n    char *hints(const char *buf, int *color, int *bold) {\n        if (!strcasecmp(buf,\"git remote add\")) {\n            *color = 35;\n            *bold = 0;\n            return \" <name> <url>\";\n        }\n        return NULL;\n    }\n\nThe callback function returns the string that should be displayed or NULL\nif no hint is available for the text the user currently typed. The returned\nstring will be trimmed as needed depending on the number of columns available\non the screen.\n\nIt is possible to return a string allocated in dynamic way, by also registering\na function to deallocate the hint string once used:\n\n    void linenoiseSetFreeHintsCallback(linenoiseFreeHintsCallback *);\n\nThe free hint callback will just receive the pointer and free the string\nas needed (depending on how the hits callback allocated it).\n\nAs you can see in the example above, a `color` (in xterm color terminal codes)\ncan be provided together with a `bold` attribute. If no color is set, the\ncurrent terminal foreground color is used. If no bold attribute is set,\nnon-bold text is printed.\n\nColor codes are:\n\n    red = 31\n    green = 32\n    yellow = 33\n    blue = 34\n    magenta = 35\n    cyan = 36\n    white = 37;\n\n## Screen handling\n\nSometimes you may want to clear the screen as a result of something the\nuser typed. You can do this by calling the following function:\n\n    void linenoiseClearScreen(void);\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/deps/linenoise/example.c",
    "content": "#include <stdio.h>\n#include <stdlib.h>\n#include <string.h>\n#include \"linenoise.h\"\n\n\nvoid completion(const char *buf, linenoiseCompletions *lc) {\n    if (buf[0] == 'h') {\n        linenoiseAddCompletion(lc,\"hello\");\n        linenoiseAddCompletion(lc,\"hello there\");\n    }\n}\n\nchar *hints(const char *buf, int *color, int *bold) {\n    if (!strcasecmp(buf,\"hello\")) {\n        *color = 35;\n        *bold = 0;\n        return \" World\";\n    }\n    return NULL;\n}\n\nint main(int argc, char **argv) {\n    char *line;\n    char *prgname = argv[0];\n\n    /* Parse options, with --multiline we enable multi line editing. */\n    while(argc > 1) {\n        argc--;\n        argv++;\n        if (!strcmp(*argv,\"--multiline\")) {\n            linenoiseSetMultiLine(1);\n            printf(\"Multi-line mode enabled.\\n\");\n        } else if (!strcmp(*argv,\"--keycodes\")) {\n            linenoisePrintKeyCodes();\n            exit(0);\n        } else {\n            fprintf(stderr, \"Usage: %s [--multiline] [--keycodes]\\n\", prgname);\n            exit(1);\n        }\n    }\n\n    /* Set the completion callback. This will be called every time the\n     * user uses the <tab> key. */\n    linenoiseSetCompletionCallback(completion);\n    linenoiseSetHintsCallback(hints);\n\n    /* Load history from file. The history file is just a plain text file\n     * where entries are separated by newlines. */\n    linenoiseHistoryLoad(\"history.txt\"); /* Load the history at startup */\n\n    /* Now this is the main loop of the typical linenoise-based application.\n     * The call to linenoise() will block as long as the user types something\n     * and presses enter.\n     *\n     * The typed string is returned as a malloc() allocated string by\n     * linenoise, so the user needs to free() it. */\n    while((line = linenoise(\"hello> \")) != NULL) {\n        /* Do something with the string. */\n        if (line[0] != '\\0' && line[0] != '/') {\n            printf(\"echo: '%s'\\n\", line);\n            linenoiseHistoryAdd(line); /* Add to the history. */\n            linenoiseHistorySave(\"history.txt\"); /* Save the history on disk. */\n        } else if (!strncmp(line,\"/historylen\",11)) {\n            /* The \"/historylen\" command will change the history len. */\n            int len = atoi(line+11);\n            linenoiseHistorySetMaxLen(len);\n        } else if (line[0] == '/') {\n            printf(\"Unreconized command: %s\\n\", line);\n        }\n        free(line);\n    }\n    return 0;\n}\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/deps/linenoise/linenoise.c",
    "content": "/* linenoise.c -- guerrilla line editing library against the idea that a\n * line editing lib needs to be 20,000 lines of C code.\n *\n * You can find the latest source code at:\n *\n *   http://github.com/antirez/linenoise\n *\n * Does a number of crazy assumptions that happen to be true in 99.9999% of\n * the 2010 UNIX computers around.\n *\n * ------------------------------------------------------------------------\n *\n * Copyright (c) 2010-2016, Salvatore Sanfilippo <antirez at gmail dot com>\n * Copyright (c) 2010-2013, Pieter Noordhuis <pcnoordhuis at gmail dot com>\n *\n * All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions are\n * met:\n *\n *  *  Redistributions of source code must retain the above copyright\n *     notice, this list of conditions and the following disclaimer.\n *\n *  *  Redistributions in binary form must reproduce the above copyright\n *     notice, this list of conditions and the following disclaimer in the\n *     documentation and/or other materials provided with the distribution.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n * \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\n * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\n * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\n * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\n * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n *\n * ------------------------------------------------------------------------\n *\n * References:\n * - http://invisible-island.net/xterm/ctlseqs/ctlseqs.html\n * - http://www.3waylabs.com/nw/WWW/products/wizcon/vt220.html\n *\n * Todo list:\n * - Filter bogus Ctrl+<char> combinations.\n * - Win32 support\n *\n * Bloat:\n * - History search like Ctrl+r in readline?\n *\n * List of escape sequences used by this program, we do everything just\n * with three sequences. In order to be so cheap we may have some\n * flickering effect with some slow terminal, but the lesser sequences\n * the more compatible.\n *\n * EL (Erase Line)\n *    Sequence: ESC [ n K\n *    Effect: if n is 0 or missing, clear from cursor to end of line\n *    Effect: if n is 1, clear from beginning of line to cursor\n *    Effect: if n is 2, clear entire line\n *\n * CUF (CUrsor Forward)\n *    Sequence: ESC [ n C\n *    Effect: moves cursor forward n chars\n *\n * CUB (CUrsor Backward)\n *    Sequence: ESC [ n D\n *    Effect: moves cursor backward n chars\n *\n * The following is used to get the terminal width if getting\n * the width with the TIOCGWINSZ ioctl fails\n *\n * DSR (Device Status Report)\n *    Sequence: ESC [ 6 n\n *    Effect: reports the current cusor position as ESC [ n ; m R\n *            where n is the row and m is the column\n *\n * When multi line mode is enabled, we also use an additional escape\n * sequence. However multi line editing is disabled by default.\n *\n * CUU (Cursor Up)\n *    Sequence: ESC [ n A\n *    Effect: moves cursor up of n chars.\n *\n * CUD (Cursor Down)\n *    Sequence: ESC [ n B\n *    Effect: moves cursor down of n chars.\n *\n * When linenoiseClearScreen() is called, two additional escape sequences\n * are used in order to clear the screen and position the cursor at home\n * position.\n *\n * CUP (Cursor position)\n *    Sequence: ESC [ H\n *    Effect: moves the cursor to upper left corner\n *\n * ED (Erase display)\n *    Sequence: ESC [ 2 J\n *    Effect: clear the whole screen\n *\n */\n\n#include <termios.h>\n#include <unistd.h>\n#include <stdlib.h>\n#include <stdio.h>\n#include <errno.h>\n#include <string.h>\n#include <stdlib.h>\n#include <ctype.h>\n#include <sys/stat.h>\n#include <sys/types.h>\n#include <sys/ioctl.h>\n#include <unistd.h>\n#include \"linenoise.h\"\n\n#define LINENOISE_DEFAULT_HISTORY_MAX_LEN 100\n#define LINENOISE_MAX_LINE 4096\nstatic char *unsupported_term[] = {\"dumb\",\"cons25\",\"emacs\",NULL};\nstatic linenoiseCompletionCallback *completionCallback = NULL;\nstatic linenoiseHintsCallback *hintsCallback = NULL;\nstatic linenoiseFreeHintsCallback *freeHintsCallback = NULL;\n\nstatic struct termios orig_termios; /* In order to restore at exit.*/\nstatic int rawmode = 0; /* For atexit() function to check if restore is needed*/\nstatic int mlmode = 0;  /* Multi line mode. Default is single line. */\nstatic int atexit_registered = 0; /* Register atexit just 1 time. */\nstatic int history_max_len = LINENOISE_DEFAULT_HISTORY_MAX_LEN;\nstatic int history_len = 0;\nstatic char **history = NULL;\n\n/* The linenoiseState structure represents the state during line editing.\n * We pass this state to functions implementing specific editing\n * functionalities. */\nstruct linenoiseState {\n    int ifd;            /* Terminal stdin file descriptor. */\n    int ofd;            /* Terminal stdout file descriptor. */\n    char *buf;          /* Edited line buffer. */\n    size_t buflen;      /* Edited line buffer size. */\n    const char *prompt; /* Prompt to display. */\n    size_t plen;        /* Prompt length. */\n    size_t pos;         /* Current cursor position. */\n    size_t oldpos;      /* Previous refresh cursor position. */\n    size_t len;         /* Current edited line length. */\n    size_t cols;        /* Number of columns in terminal. */\n    size_t maxrows;     /* Maximum num of rows used so far (multiline mode) */\n    int history_index;  /* The history index we are currently editing. */\n};\n\nenum KEY_ACTION{\n\tKEY_NULL = 0,\t    /* NULL */\n\tCTRL_A = 1,         /* Ctrl+a */\n\tCTRL_B = 2,         /* Ctrl-b */\n\tCTRL_C = 3,         /* Ctrl-c */\n\tCTRL_D = 4,         /* Ctrl-d */\n\tCTRL_E = 5,         /* Ctrl-e */\n\tCTRL_F = 6,         /* Ctrl-f */\n\tCTRL_H = 8,         /* Ctrl-h */\n\tTAB = 9,            /* Tab */\n\tCTRL_K = 11,        /* Ctrl+k */\n\tCTRL_L = 12,        /* Ctrl+l */\n\tENTER = 13,         /* Enter */\n\tCTRL_N = 14,        /* Ctrl-n */\n\tCTRL_P = 16,        /* Ctrl-p */\n\tCTRL_T = 20,        /* Ctrl-t */\n\tCTRL_U = 21,        /* Ctrl+u */\n\tCTRL_W = 23,        /* Ctrl+w */\n\tESC = 27,           /* Escape */\n\tBACKSPACE =  127    /* Backspace */\n};\n\nstatic void linenoiseAtExit(void);\nint linenoiseHistoryAdd(const char *line);\nstatic void refreshLine(struct linenoiseState *l);\n\n/* Debugging macro. */\n#if 0\nFILE *lndebug_fp = NULL;\n#define lndebug(...) \\\n    do { \\\n        if (lndebug_fp == NULL) { \\\n            lndebug_fp = fopen(\"/tmp/lndebug.txt\",\"a\"); \\\n            fprintf(lndebug_fp, \\\n            \"[%d %d %d] p: %d, rows: %d, rpos: %d, max: %d, oldmax: %d\\n\", \\\n            (int)l->len,(int)l->pos,(int)l->oldpos,plen,rows,rpos, \\\n            (int)l->maxrows,old_rows); \\\n        } \\\n        fprintf(lndebug_fp, \", \" __VA_ARGS__); \\\n        fflush(lndebug_fp); \\\n    } while (0)\n#else\n#define lndebug(fmt, ...)\n#endif\n\n/* ======================= Low level terminal handling ====================== */\n\n/* Set if to use or not the multi line mode. */\nvoid linenoiseSetMultiLine(int ml) {\n    mlmode = ml;\n}\n\n/* Return true if the terminal name is in the list of terminals we know are\n * not able to understand basic escape sequences. */\nstatic int isUnsupportedTerm(void) {\n    char *term = getenv(\"TERM\");\n    int j;\n\n    if (term == NULL) return 0;\n    for (j = 0; unsupported_term[j]; j++)\n        if (!strcasecmp(term,unsupported_term[j])) return 1;\n    return 0;\n}\n\n/* Raw mode: 1960 magic shit. */\nstatic int enableRawMode(int fd) {\n    struct termios raw;\n\n    if (!isatty(STDIN_FILENO)) goto fatal;\n    if (!atexit_registered) {\n        atexit(linenoiseAtExit);\n        atexit_registered = 1;\n    }\n    if (tcgetattr(fd,&orig_termios) == -1) goto fatal;\n\n    raw = orig_termios;  /* modify the original mode */\n    /* input modes: no break, no CR to NL, no parity check, no strip char,\n     * no start/stop output control. */\n    raw.c_iflag &= ~(BRKINT | ICRNL | INPCK | ISTRIP | IXON);\n    /* output modes - disable post processing */\n    raw.c_oflag &= ~(OPOST);\n    /* control modes - set 8 bit chars */\n    raw.c_cflag |= (CS8);\n    /* local modes - choing off, canonical off, no extended functions,\n     * no signal chars (^Z,^C) */\n    raw.c_lflag &= ~(ECHO | ICANON | IEXTEN | ISIG);\n    /* control chars - set return condition: min number of bytes and timer.\n     * We want read to return every single byte, without timeout. */\n    raw.c_cc[VMIN] = 1; raw.c_cc[VTIME] = 0; /* 1 byte, no timer */\n\n    /* put terminal in raw mode after flushing */\n    if (tcsetattr(fd,TCSAFLUSH,&raw) < 0) goto fatal;\n    rawmode = 1;\n    return 0;\n\nfatal:\n    errno = ENOTTY;\n    return -1;\n}\n\nstatic void disableRawMode(int fd) {\n    /* Don't even check the return value as it's too late. */\n    if (rawmode && tcsetattr(fd,TCSAFLUSH,&orig_termios) != -1)\n        rawmode = 0;\n}\n\n/* Use the ESC [6n escape sequence to query the horizontal cursor position\n * and return it. On error -1 is returned, on success the position of the\n * cursor. */\nstatic int getCursorPosition(int ifd, int ofd) {\n    char buf[32];\n    int cols, rows;\n    unsigned int i = 0;\n\n    /* Report cursor location */\n    if (write(ofd, \"\\x1b[6n\", 4) != 4) return -1;\n\n    /* Read the response: ESC [ rows ; cols R */\n    while (i < sizeof(buf)-1) {\n        if (read(ifd,buf+i,1) != 1) break;\n        if (buf[i] == 'R') break;\n        i++;\n    }\n    buf[i] = '\\0';\n\n    /* Parse it. */\n    if (buf[0] != ESC || buf[1] != '[') return -1;\n    if (sscanf(buf+2,\"%d;%d\",&rows,&cols) != 2) return -1;\n    return cols;\n}\n\n/* Try to get the number of columns in the current terminal, or assume 80\n * if it fails. */\nstatic int getColumns(int ifd, int ofd) {\n    struct winsize ws;\n\n    if (ioctl(1, TIOCGWINSZ, &ws) == -1 || ws.ws_col == 0) {\n        /* ioctl() failed. Try to query the terminal itself. */\n        int start, cols;\n\n        /* Get the initial position so we can restore it later. */\n        start = getCursorPosition(ifd,ofd);\n        if (start == -1) goto failed;\n\n        /* Go to right margin and get position. */\n        if (write(ofd,\"\\x1b[999C\",6) != 6) goto failed;\n        cols = getCursorPosition(ifd,ofd);\n        if (cols == -1) goto failed;\n\n        /* Restore position. */\n        if (cols > start) {\n            char seq[32];\n            snprintf(seq,32,\"\\x1b[%dD\",cols-start);\n            if (write(ofd,seq,strlen(seq)) == -1) {\n                /* Can't recover... */\n            }\n        }\n        return cols;\n    } else {\n        return ws.ws_col;\n    }\n\nfailed:\n    return 80;\n}\n\n/* Clear the screen. Used to handle ctrl+l */\nvoid linenoiseClearScreen(void) {\n    if (write(STDOUT_FILENO,\"\\x1b[H\\x1b[2J\",7) <= 0) {\n        /* nothing to do, just to avoid warning. */\n    }\n}\n\n/* Beep, used for completion when there is nothing to complete or when all\n * the choices were already shown. */\nstatic void linenoiseBeep(void) {\n    fprintf(stderr, \"\\x7\");\n    fflush(stderr);\n}\n\n/* ============================== Completion ================================ */\n\n/* Free a list of completion option populated by linenoiseAddCompletion(). */\nstatic void freeCompletions(linenoiseCompletions *lc) {\n    size_t i;\n    for (i = 0; i < lc->len; i++)\n        free(lc->cvec[i]);\n    if (lc->cvec != NULL)\n        free(lc->cvec);\n}\n\n/* This is an helper function for linenoiseEdit() and is called when the\n * user types the <tab> key in order to complete the string currently in the\n * input.\n *\n * The state of the editing is encapsulated into the pointed linenoiseState\n * structure as described in the structure definition. */\nstatic int completeLine(struct linenoiseState *ls) {\n    linenoiseCompletions lc = { 0, NULL };\n    int nread, nwritten;\n    char c = 0;\n\n    completionCallback(ls->buf,&lc);\n    if (lc.len == 0) {\n        linenoiseBeep();\n    } else {\n        size_t stop = 0, i = 0;\n\n        while(!stop) {\n            /* Show completion or original buffer */\n            if (i < lc.len) {\n                struct linenoiseState saved = *ls;\n\n                ls->len = ls->pos = strlen(lc.cvec[i]);\n                ls->buf = lc.cvec[i];\n                refreshLine(ls);\n                ls->len = saved.len;\n                ls->pos = saved.pos;\n                ls->buf = saved.buf;\n            } else {\n                refreshLine(ls);\n            }\n\n            nread = read(ls->ifd,&c,1);\n            if (nread <= 0) {\n                freeCompletions(&lc);\n                return -1;\n            }\n\n            switch(c) {\n                case 9: /* tab */\n                    i = (i+1) % (lc.len+1);\n                    if (i == lc.len) linenoiseBeep();\n                    break;\n                case 27: /* escape */\n                    /* Re-show original buffer */\n                    if (i < lc.len) refreshLine(ls);\n                    stop = 1;\n                    break;\n                default:\n                    /* Update buffer and return */\n                    if (i < lc.len) {\n                        nwritten = snprintf(ls->buf,ls->buflen,\"%s\",lc.cvec[i]);\n                        ls->len = ls->pos = nwritten;\n                    }\n                    stop = 1;\n                    break;\n            }\n        }\n    }\n\n    freeCompletions(&lc);\n    return c; /* Return last read character */\n}\n\n/* Register a callback function to be called for tab-completion. */\nvoid linenoiseSetCompletionCallback(linenoiseCompletionCallback *fn) {\n    completionCallback = fn;\n}\n\n/* Register a hits function to be called to show hits to the user at the\n * right of the prompt. */\nvoid linenoiseSetHintsCallback(linenoiseHintsCallback *fn) {\n    hintsCallback = fn;\n}\n\n/* Register a function to free the hints returned by the hints callback\n * registered with linenoiseSetHintsCallback(). */\nvoid linenoiseSetFreeHintsCallback(linenoiseFreeHintsCallback *fn) {\n    freeHintsCallback = fn;\n}\n\n/* This function is used by the callback function registered by the user\n * in order to add completion options given the input string when the\n * user typed <tab>. See the example.c source code for a very easy to\n * understand example. */\nvoid linenoiseAddCompletion(linenoiseCompletions *lc, const char *str) {\n    size_t len = strlen(str);\n    char *copy, **cvec;\n\n    copy = malloc(len+1);\n    if (copy == NULL) return;\n    memcpy(copy,str,len+1);\n    cvec = realloc(lc->cvec,sizeof(char*)*(lc->len+1));\n    if (cvec == NULL) {\n        free(copy);\n        return;\n    }\n    lc->cvec = cvec;\n    lc->cvec[lc->len++] = copy;\n}\n\n/* =========================== Line editing ================================= */\n\n/* We define a very simple \"append buffer\" structure, that is an heap\n * allocated string where we can append to. This is useful in order to\n * write all the escape sequences in a buffer and flush them to the standard\n * output in a single call, to avoid flickering effects. */\nstruct abuf {\n    char *b;\n    int len;\n};\n\nstatic void abInit(struct abuf *ab) {\n    ab->b = NULL;\n    ab->len = 0;\n}\n\nstatic void abAppend(struct abuf *ab, const char *s, int len) {\n    char *new = realloc(ab->b,ab->len+len);\n\n    if (new == NULL) return;\n    memcpy(new+ab->len,s,len);\n    ab->b = new;\n    ab->len += len;\n}\n\nstatic void abFree(struct abuf *ab) {\n    free(ab->b);\n}\n\n/* Helper of refreshSingleLine() and refreshMultiLine() to show hints\n * to the right of the prompt. */\nvoid refreshShowHints(struct abuf *ab, struct linenoiseState *l, int plen) {\n    char seq[64];\n    if (hintsCallback && plen+l->len < l->cols) {\n        int color = -1, bold = 0;\n        char *hint = hintsCallback(l->buf,&color,&bold);\n        if (hint) {\n            int hintlen = strlen(hint);\n            int hintmaxlen = l->cols-(plen+l->len);\n            if (hintlen > hintmaxlen) hintlen = hintmaxlen;\n            if (bold == 1 && color == -1) color = 37;\n            if (color != -1 || bold != 0)\n                snprintf(seq,64,\"\\033[%d;%d;49m\",bold,color);\n            abAppend(ab,seq,strlen(seq));\n            abAppend(ab,hint,hintlen);\n            if (color != -1 || bold != 0)\n                abAppend(ab,\"\\033[0m\",4);\n            /* Call the function to free the hint returned. */\n            if (freeHintsCallback) freeHintsCallback(hint);\n        }\n    }\n}\n\n/* Single line low level line refresh.\n *\n * Rewrite the currently edited line accordingly to the buffer content,\n * cursor position, and number of columns of the terminal. */\nstatic void refreshSingleLine(struct linenoiseState *l) {\n    char seq[64];\n    size_t plen = strlen(l->prompt);\n    int fd = l->ofd;\n    char *buf = l->buf;\n    size_t len = l->len;\n    size_t pos = l->pos;\n    struct abuf ab;\n\n    while((plen+pos) >= l->cols) {\n        buf++;\n        len--;\n        pos--;\n    }\n    while (plen+len > l->cols) {\n        len--;\n    }\n\n    abInit(&ab);\n    /* Cursor to left edge */\n    snprintf(seq,64,\"\\r\");\n    abAppend(&ab,seq,strlen(seq));\n    /* Write the prompt and the current buffer content */\n    abAppend(&ab,l->prompt,strlen(l->prompt));\n    abAppend(&ab,buf,len);\n    /* Show hits if any. */\n    refreshShowHints(&ab,l,plen);\n    /* Erase to right */\n    snprintf(seq,64,\"\\x1b[0K\");\n    abAppend(&ab,seq,strlen(seq));\n    /* Move cursor to original position. */\n    snprintf(seq,64,\"\\r\\x1b[%dC\", (int)(pos+plen));\n    abAppend(&ab,seq,strlen(seq));\n    if (write(fd,ab.b,ab.len) == -1) {} /* Can't recover from write error. */\n    abFree(&ab);\n}\n\n/* Multi line low level line refresh.\n *\n * Rewrite the currently edited line accordingly to the buffer content,\n * cursor position, and number of columns of the terminal. */\nstatic void refreshMultiLine(struct linenoiseState *l) {\n    char seq[64];\n    int plen = strlen(l->prompt);\n    int rows = (plen+l->len+l->cols-1)/l->cols; /* rows used by current buf. */\n    int rpos = (plen+l->oldpos+l->cols)/l->cols; /* cursor relative row. */\n    int rpos2; /* rpos after refresh. */\n    int col; /* colum position, zero-based. */\n    int old_rows = l->maxrows;\n    int fd = l->ofd, j;\n    struct abuf ab;\n\n    /* Update maxrows if needed. */\n    if (rows > (int)l->maxrows) l->maxrows = rows;\n\n    /* First step: clear all the lines used before. To do so start by\n     * going to the last row. */\n    abInit(&ab);\n    if (old_rows-rpos > 0) {\n        lndebug(\"go down %d\", old_rows-rpos);\n        snprintf(seq,64,\"\\x1b[%dB\", old_rows-rpos);\n        abAppend(&ab,seq,strlen(seq));\n    }\n\n    /* Now for every row clear it, go up. */\n    for (j = 0; j < old_rows-1; j++) {\n        lndebug(\"clear+up\");\n        snprintf(seq,64,\"\\r\\x1b[0K\\x1b[1A\");\n        abAppend(&ab,seq,strlen(seq));\n    }\n\n    /* Clean the top line. */\n    lndebug(\"clear\");\n    snprintf(seq,64,\"\\r\\x1b[0K\");\n    abAppend(&ab,seq,strlen(seq));\n\n    /* Write the prompt and the current buffer content */\n    abAppend(&ab,l->prompt,strlen(l->prompt));\n    abAppend(&ab,l->buf,l->len);\n\n    /* Show hits if any. */\n    refreshShowHints(&ab,l,plen);\n\n    /* If we are at the very end of the screen with our prompt, we need to\n     * emit a newline and move the prompt to the first column. */\n    if (l->pos &&\n        l->pos == l->len &&\n        (l->pos+plen) % l->cols == 0)\n    {\n        lndebug(\"<newline>\");\n        abAppend(&ab,\"\\n\",1);\n        snprintf(seq,64,\"\\r\");\n        abAppend(&ab,seq,strlen(seq));\n        rows++;\n        if (rows > (int)l->maxrows) l->maxrows = rows;\n    }\n\n    /* Move cursor to right position. */\n    rpos2 = (plen+l->pos+l->cols)/l->cols; /* current cursor relative row. */\n    lndebug(\"rpos2 %d\", rpos2);\n\n    /* Go up till we reach the expected positon. */\n    if (rows-rpos2 > 0) {\n        lndebug(\"go-up %d\", rows-rpos2);\n        snprintf(seq,64,\"\\x1b[%dA\", rows-rpos2);\n        abAppend(&ab,seq,strlen(seq));\n    }\n\n    /* Set column. */\n    col = (plen+(int)l->pos) % (int)l->cols;\n    lndebug(\"set col %d\", 1+col);\n    if (col)\n        snprintf(seq,64,\"\\r\\x1b[%dC\", col);\n    else\n        snprintf(seq,64,\"\\r\");\n    abAppend(&ab,seq,strlen(seq));\n\n    lndebug(\"\\n\");\n    l->oldpos = l->pos;\n\n    if (write(fd,ab.b,ab.len) == -1) {} /* Can't recover from write error. */\n    abFree(&ab);\n}\n\n/* Calls the two low level functions refreshSingleLine() or\n * refreshMultiLine() according to the selected mode. */\nstatic void refreshLine(struct linenoiseState *l) {\n    if (mlmode)\n        refreshMultiLine(l);\n    else\n        refreshSingleLine(l);\n}\n\n/* Insert the character 'c' at cursor current position.\n *\n * On error writing to the terminal -1 is returned, otherwise 0. */\nint linenoiseEditInsert(struct linenoiseState *l, char c) {\n    if (l->len < l->buflen) {\n        if (l->len == l->pos) {\n            l->buf[l->pos] = c;\n            l->pos++;\n            l->len++;\n            l->buf[l->len] = '\\0';\n            if ((!mlmode && l->plen+l->len < l->cols && !hintsCallback)) {\n                /* Avoid a full update of the line in the\n                 * trivial case. */\n                if (write(l->ofd,&c,1) == -1) return -1;\n            } else {\n                refreshLine(l);\n            }\n        } else {\n            memmove(l->buf+l->pos+1,l->buf+l->pos,l->len-l->pos);\n            l->buf[l->pos] = c;\n            l->len++;\n            l->pos++;\n            l->buf[l->len] = '\\0';\n            refreshLine(l);\n        }\n    }\n    return 0;\n}\n\n/* Move cursor on the left. */\nvoid linenoiseEditMoveLeft(struct linenoiseState *l) {\n    if (l->pos > 0) {\n        l->pos--;\n        refreshLine(l);\n    }\n}\n\n/* Move cursor on the right. */\nvoid linenoiseEditMoveRight(struct linenoiseState *l) {\n    if (l->pos != l->len) {\n        l->pos++;\n        refreshLine(l);\n    }\n}\n\n/* Move cursor to the start of the line. */\nvoid linenoiseEditMoveHome(struct linenoiseState *l) {\n    if (l->pos != 0) {\n        l->pos = 0;\n        refreshLine(l);\n    }\n}\n\n/* Move cursor to the end of the line. */\nvoid linenoiseEditMoveEnd(struct linenoiseState *l) {\n    if (l->pos != l->len) {\n        l->pos = l->len;\n        refreshLine(l);\n    }\n}\n\n/* Substitute the currently edited line with the next or previous history\n * entry as specified by 'dir'. */\n#define LINENOISE_HISTORY_NEXT 0\n#define LINENOISE_HISTORY_PREV 1\nvoid linenoiseEditHistoryNext(struct linenoiseState *l, int dir) {\n    if (history_len > 1) {\n        /* Update the current history entry before to\n         * overwrite it with the next one. */\n        free(history[history_len - 1 - l->history_index]);\n        history[history_len - 1 - l->history_index] = strdup(l->buf);\n        /* Show the new entry */\n        l->history_index += (dir == LINENOISE_HISTORY_PREV) ? 1 : -1;\n        if (l->history_index < 0) {\n            l->history_index = 0;\n            return;\n        } else if (l->history_index >= history_len) {\n            l->history_index = history_len-1;\n            return;\n        }\n        strncpy(l->buf,history[history_len - 1 - l->history_index],l->buflen);\n        l->buf[l->buflen-1] = '\\0';\n        l->len = l->pos = strlen(l->buf);\n        refreshLine(l);\n    }\n}\n\n/* Delete the character at the right of the cursor without altering the cursor\n * position. Basically this is what happens with the \"Delete\" keyboard key. */\nvoid linenoiseEditDelete(struct linenoiseState *l) {\n    if (l->len > 0 && l->pos < l->len) {\n        memmove(l->buf+l->pos,l->buf+l->pos+1,l->len-l->pos-1);\n        l->len--;\n        l->buf[l->len] = '\\0';\n        refreshLine(l);\n    }\n}\n\n/* Backspace implementation. */\nvoid linenoiseEditBackspace(struct linenoiseState *l) {\n    if (l->pos > 0 && l->len > 0) {\n        memmove(l->buf+l->pos-1,l->buf+l->pos,l->len-l->pos);\n        l->pos--;\n        l->len--;\n        l->buf[l->len] = '\\0';\n        refreshLine(l);\n    }\n}\n\n/* Delete the previosu word, maintaining the cursor at the start of the\n * current word. */\nvoid linenoiseEditDeletePrevWord(struct linenoiseState *l) {\n    size_t old_pos = l->pos;\n    size_t diff;\n\n    while (l->pos > 0 && l->buf[l->pos-1] == ' ')\n        l->pos--;\n    while (l->pos > 0 && l->buf[l->pos-1] != ' ')\n        l->pos--;\n    diff = old_pos - l->pos;\n    memmove(l->buf+l->pos,l->buf+old_pos,l->len-old_pos+1);\n    l->len -= diff;\n    refreshLine(l);\n}\n\n/* This function is the core of the line editing capability of linenoise.\n * It expects 'fd' to be already in \"raw mode\" so that every key pressed\n * will be returned ASAP to read().\n *\n * The resulting string is put into 'buf' when the user type enter, or\n * when ctrl+d is typed.\n *\n * The function returns the length of the current buffer. */\nstatic int linenoiseEdit(int stdin_fd, int stdout_fd, char *buf, size_t buflen, const char *prompt)\n{\n    struct linenoiseState l;\n\n    /* Populate the linenoise state that we pass to functions implementing\n     * specific editing functionalities. */\n    l.ifd = stdin_fd;\n    l.ofd = stdout_fd;\n    l.buf = buf;\n    l.buflen = buflen;\n    l.prompt = prompt;\n    l.plen = strlen(prompt);\n    l.oldpos = l.pos = 0;\n    l.len = 0;\n    l.cols = getColumns(stdin_fd, stdout_fd);\n    l.maxrows = 0;\n    l.history_index = 0;\n\n    /* Buffer starts empty. */\n    l.buf[0] = '\\0';\n    l.buflen--; /* Make sure there is always space for the nulterm */\n\n    /* The latest history entry is always our current buffer, that\n     * initially is just an empty string. */\n    linenoiseHistoryAdd(\"\");\n\n    if (write(l.ofd,prompt,l.plen) == -1) return -1;\n    while(1) {\n        char c;\n        int nread;\n        char seq[3];\n\n        nread = read(l.ifd,&c,1);\n        if (nread <= 0) return l.len;\n\n        /* Only autocomplete when the callback is set. It returns < 0 when\n         * there was an error reading from fd. Otherwise it will return the\n         * character that should be handled next. */\n        if (c == 9 && completionCallback != NULL) {\n            c = completeLine(&l);\n            /* Return on errors */\n            if (c < 0) return l.len;\n            /* Read next character when 0 */\n            if (c == 0) continue;\n        }\n\n        switch(c) {\n        case ENTER:    /* enter */\n            history_len--;\n            free(history[history_len]);\n            if (mlmode) linenoiseEditMoveEnd(&l);\n            if (hintsCallback) {\n                /* Force a refresh without hints to leave the previous\n                 * line as the user typed it after a newline. */\n                linenoiseHintsCallback *hc = hintsCallback;\n                hintsCallback = NULL;\n                refreshLine(&l);\n                hintsCallback = hc;\n            }\n            return (int)l.len;\n        case CTRL_C:     /* ctrl-c */\n            errno = EAGAIN;\n            return -1;\n        case BACKSPACE:   /* backspace */\n        case 8:     /* ctrl-h */\n            linenoiseEditBackspace(&l);\n            break;\n        case CTRL_D:     /* ctrl-d, remove char at right of cursor, or if the\n                            line is empty, act as end-of-file. */\n            if (l.len > 0) {\n                linenoiseEditDelete(&l);\n            } else {\n                history_len--;\n                free(history[history_len]);\n                return -1;\n            }\n            break;\n        case CTRL_T:    /* ctrl-t, swaps current character with previous. */\n            if (l.pos > 0 && l.pos < l.len) {\n                int aux = buf[l.pos-1];\n                buf[l.pos-1] = buf[l.pos];\n                buf[l.pos] = aux;\n                if (l.pos != l.len-1) l.pos++;\n                refreshLine(&l);\n            }\n            break;\n        case CTRL_B:     /* ctrl-b */\n            linenoiseEditMoveLeft(&l);\n            break;\n        case CTRL_F:     /* ctrl-f */\n            linenoiseEditMoveRight(&l);\n            break;\n        case CTRL_P:    /* ctrl-p */\n            linenoiseEditHistoryNext(&l, LINENOISE_HISTORY_PREV);\n            break;\n        case CTRL_N:    /* ctrl-n */\n            linenoiseEditHistoryNext(&l, LINENOISE_HISTORY_NEXT);\n            break;\n        case ESC:    /* escape sequence */\n            /* Read the next two bytes representing the escape sequence.\n             * Use two calls to handle slow terminals returning the two\n             * chars at different times. */\n            if (read(l.ifd,seq,1) == -1) break;\n            if (read(l.ifd,seq+1,1) == -1) break;\n\n            /* ESC [ sequences. */\n            if (seq[0] == '[') {\n                if (seq[1] >= '0' && seq[1] <= '9') {\n                    /* Extended escape, read additional byte. */\n                    if (read(l.ifd,seq+2,1) == -1) break;\n                    if (seq[2] == '~') {\n                        switch(seq[1]) {\n                        case '3': /* Delete key. */\n                            linenoiseEditDelete(&l);\n                            break;\n                        }\n                    }\n                } else {\n                    switch(seq[1]) {\n                    case 'A': /* Up */\n                        linenoiseEditHistoryNext(&l, LINENOISE_HISTORY_PREV);\n                        break;\n                    case 'B': /* Down */\n                        linenoiseEditHistoryNext(&l, LINENOISE_HISTORY_NEXT);\n                        break;\n                    case 'C': /* Right */\n                        linenoiseEditMoveRight(&l);\n                        break;\n                    case 'D': /* Left */\n                        linenoiseEditMoveLeft(&l);\n                        break;\n                    case 'H': /* Home */\n                        linenoiseEditMoveHome(&l);\n                        break;\n                    case 'F': /* End*/\n                        linenoiseEditMoveEnd(&l);\n                        break;\n                    }\n                }\n            }\n\n            /* ESC O sequences. */\n            else if (seq[0] == 'O') {\n                switch(seq[1]) {\n                case 'H': /* Home */\n                    linenoiseEditMoveHome(&l);\n                    break;\n                case 'F': /* End*/\n                    linenoiseEditMoveEnd(&l);\n                    break;\n                }\n            }\n            break;\n        default:\n            if (linenoiseEditInsert(&l,c)) return -1;\n            break;\n        case CTRL_U: /* Ctrl+u, delete the whole line. */\n            buf[0] = '\\0';\n            l.pos = l.len = 0;\n            refreshLine(&l);\n            break;\n        case CTRL_K: /* Ctrl+k, delete from current to end of line. */\n            buf[l.pos] = '\\0';\n            l.len = l.pos;\n            refreshLine(&l);\n            break;\n        case CTRL_A: /* Ctrl+a, go to the start of the line */\n            linenoiseEditMoveHome(&l);\n            break;\n        case CTRL_E: /* ctrl+e, go to the end of the line */\n            linenoiseEditMoveEnd(&l);\n            break;\n        case CTRL_L: /* ctrl+l, clear screen */\n            linenoiseClearScreen();\n            refreshLine(&l);\n            break;\n        case CTRL_W: /* ctrl+w, delete previous word */\n            linenoiseEditDeletePrevWord(&l);\n            break;\n        }\n    }\n    return l.len;\n}\n\n/* This special mode is used by linenoise in order to print scan codes\n * on screen for debugging / development purposes. It is implemented\n * by the linenoise_example program using the --keycodes option. */\nvoid linenoisePrintKeyCodes(void) {\n    char quit[4];\n\n    printf(\"Linenoise key codes debugging mode.\\n\"\n            \"Press keys to see scan codes. Type 'quit' at any time to exit.\\n\");\n    if (enableRawMode(STDIN_FILENO) == -1) return;\n    memset(quit,' ',4);\n    while(1) {\n        char c;\n        int nread;\n\n        nread = read(STDIN_FILENO,&c,1);\n        if (nread <= 0) continue;\n        memmove(quit,quit+1,sizeof(quit)-1); /* shift string to left. */\n        quit[sizeof(quit)-1] = c; /* Insert current char on the right. */\n        if (memcmp(quit,\"quit\",sizeof(quit)) == 0) break;\n\n        printf(\"'%c' %02x (%d) (type quit to exit)\\n\",\n            isprint(c) ? c : '?', (int)c, (int)c);\n        printf(\"\\r\"); /* Go left edge manually, we are in raw mode. */\n        fflush(stdout);\n    }\n    disableRawMode(STDIN_FILENO);\n}\n\n/* This function calls the line editing function linenoiseEdit() using\n * the STDIN file descriptor set in raw mode. */\nstatic int linenoiseRaw(char *buf, size_t buflen, const char *prompt) {\n    int count;\n\n    if (buflen == 0) {\n        errno = EINVAL;\n        return -1;\n    }\n\n    if (enableRawMode(STDIN_FILENO) == -1) return -1;\n    count = linenoiseEdit(STDIN_FILENO, STDOUT_FILENO, buf, buflen, prompt);\n    disableRawMode(STDIN_FILENO);\n    printf(\"\\n\");\n    return count;\n}\n\n/* This function is called when linenoise() is called with the standard\n * input file descriptor not attached to a TTY. So for example when the\n * program using linenoise is called in pipe or with a file redirected\n * to its standard input. In this case, we want to be able to return the\n * line regardless of its length (by default we are limited to 4k). */\nstatic char *linenoiseNoTTY(void) {\n    char *line = NULL;\n    size_t len = 0, maxlen = 0;\n\n    while(1) {\n        if (len == maxlen) {\n            if (maxlen == 0) maxlen = 16;\n            maxlen *= 2;\n            char *oldval = line;\n            line = realloc(line,maxlen);\n            if (line == NULL) {\n                if (oldval) free(oldval);\n                return NULL;\n            }\n        }\n        int c = fgetc(stdin);\n        if (c == EOF || c == '\\n') {\n            if (c == EOF && len == 0) {\n                free(line);\n                return NULL;\n            } else {\n                line[len] = '\\0';\n                return line;\n            }\n        } else {\n            line[len] = c;\n            len++;\n        }\n    }\n}\n\n/* The high level function that is the main API of the linenoise library.\n * This function checks if the terminal has basic capabilities, just checking\n * for a blacklist of stupid terminals, and later either calls the line\n * editing function or uses dummy fgets() so that you will be able to type\n * something even in the most desperate of the conditions. */\nchar *linenoise(const char *prompt) {\n    char buf[LINENOISE_MAX_LINE];\n    int count;\n\n    if (!isatty(STDIN_FILENO)) {\n        /* Not a tty: read from file / pipe. In this mode we don't want any\n         * limit to the line size, so we call a function to handle that. */\n        return linenoiseNoTTY();\n    } else if (isUnsupportedTerm()) {\n        size_t len;\n\n        printf(\"%s\",prompt);\n        fflush(stdout);\n        if (fgets(buf,LINENOISE_MAX_LINE,stdin) == NULL) return NULL;\n        len = strlen(buf);\n        while(len && (buf[len-1] == '\\n' || buf[len-1] == '\\r')) {\n            len--;\n            buf[len] = '\\0';\n        }\n        return strdup(buf);\n    } else {\n        count = linenoiseRaw(buf,LINENOISE_MAX_LINE,prompt);\n        if (count == -1) return NULL;\n        return strdup(buf);\n    }\n}\n\n/* This is just a wrapper the user may want to call in order to make sure\n * the linenoise returned buffer is freed with the same allocator it was\n * created with. Useful when the main program is using an alternative\n * allocator. */\nvoid linenoiseFree(void *ptr) {\n    free(ptr);\n}\n\n/* ================================ History ================================= */\n\n/* Free the history, but does not reset it. Only used when we have to\n * exit() to avoid memory leaks are reported by valgrind & co. */\nstatic void freeHistory(void) {\n    if (history) {\n        int j;\n\n        for (j = 0; j < history_len; j++)\n            free(history[j]);\n        free(history);\n    }\n}\n\n/* At exit we'll try to fix the terminal to the initial conditions. */\nstatic void linenoiseAtExit(void) {\n    disableRawMode(STDIN_FILENO);\n    freeHistory();\n}\n\n/* This is the API call to add a new entry in the linenoise history.\n * It uses a fixed array of char pointers that are shifted (memmoved)\n * when the history max length is reached in order to remove the older\n * entry and make room for the new one, so it is not exactly suitable for huge\n * histories, but will work well for a few hundred of entries.\n *\n * Using a circular buffer is smarter, but a bit more complex to handle. */\nint linenoiseHistoryAdd(const char *line) {\n    char *linecopy;\n\n    if (history_max_len == 0) return 0;\n\n    /* Initialization on first call. */\n    if (history == NULL) {\n        history = malloc(sizeof(char*)*history_max_len);\n        if (history == NULL) return 0;\n        memset(history,0,(sizeof(char*)*history_max_len));\n    }\n\n    /* Don't add duplicated lines. */\n    if (history_len && !strcmp(history[history_len-1], line)) return 0;\n\n    /* Add an heap allocated copy of the line in the history.\n     * If we reached the max length, remove the older line. */\n    linecopy = strdup(line);\n    if (!linecopy) return 0;\n    if (history_len == history_max_len) {\n        free(history[0]);\n        memmove(history,history+1,sizeof(char*)*(history_max_len-1));\n        history_len--;\n    }\n    history[history_len] = linecopy;\n    history_len++;\n    return 1;\n}\n\n/* Set the maximum length for the history. This function can be called even\n * if there is already some history, the function will make sure to retain\n * just the latest 'len' elements if the new history length value is smaller\n * than the amount of items already inside the history. */\nint linenoiseHistorySetMaxLen(int len) {\n    char **new;\n\n    if (len < 1) return 0;\n    if (history) {\n        int tocopy = history_len;\n\n        new = malloc(sizeof(char*)*len);\n        if (new == NULL) return 0;\n\n        /* If we can't copy everything, free the elements we'll not use. */\n        if (len < tocopy) {\n            int j;\n\n            for (j = 0; j < tocopy-len; j++) free(history[j]);\n            tocopy = len;\n        }\n        memset(new,0,sizeof(char*)*len);\n        memcpy(new,history+(history_len-tocopy), sizeof(char*)*tocopy);\n        free(history);\n        history = new;\n    }\n    history_max_len = len;\n    if (history_len > history_max_len)\n        history_len = history_max_len;\n    return 1;\n}\n\n/* Save the history in the specified file. On success 0 is returned\n * otherwise -1 is returned. */\nint linenoiseHistorySave(const char *filename) {\n    mode_t old_umask = umask(S_IXUSR|S_IRWXG|S_IRWXO);\n    FILE *fp;\n    int j;\n\n    fp = fopen(filename,\"w\");\n    umask(old_umask);\n    if (fp == NULL) return -1;\n    chmod(filename,S_IRUSR|S_IWUSR);\n    for (j = 0; j < history_len; j++)\n        fprintf(fp,\"%s\\n\",history[j]);\n    fclose(fp);\n    return 0;\n}\n\n/* Load the history from the specified file. If the file does not exist\n * zero is returned and no operation is performed.\n *\n * If the file exists and the operation succeeded 0 is returned, otherwise\n * on error -1 is returned. */\nint linenoiseHistoryLoad(const char *filename) {\n    FILE *fp = fopen(filename,\"r\");\n    char buf[LINENOISE_MAX_LINE];\n\n    if (fp == NULL) return -1;\n\n    while (fgets(buf,LINENOISE_MAX_LINE,fp) != NULL) {\n        char *p;\n\n        p = strchr(buf,'\\r');\n        if (!p) p = strchr(buf,'\\n');\n        if (p) *p = '\\0';\n        linenoiseHistoryAdd(buf);\n    }\n    fclose(fp);\n    return 0;\n}\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/deps/linenoise/linenoise.h",
    "content": "/* linenoise.h -- VERSION 1.0\n *\n * Guerrilla line editing library against the idea that a line editing lib\n * needs to be 20,000 lines of C code.\n *\n * See linenoise.c for more information.\n *\n * ------------------------------------------------------------------------\n *\n * Copyright (c) 2010-2014, Salvatore Sanfilippo <antirez at gmail dot com>\n * Copyright (c) 2010-2013, Pieter Noordhuis <pcnoordhuis at gmail dot com>\n *\n * All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions are\n * met:\n *\n *  *  Redistributions of source code must retain the above copyright\n *     notice, this list of conditions and the following disclaimer.\n *\n *  *  Redistributions in binary form must reproduce the above copyright\n *     notice, this list of conditions and the following disclaimer in the\n *     documentation and/or other materials provided with the distribution.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n * \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\n * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\n * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\n * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\n * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n\n#ifndef __LINENOISE_H\n#define __LINENOISE_H\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\ntypedef struct linenoiseCompletions {\n  size_t len;\n  char **cvec;\n} linenoiseCompletions;\n\ntypedef void(linenoiseCompletionCallback)(const char *, linenoiseCompletions *);\ntypedef char*(linenoiseHintsCallback)(const char *, int *color, int *bold);\ntypedef void(linenoiseFreeHintsCallback)(void *);\nvoid linenoiseSetCompletionCallback(linenoiseCompletionCallback *);\nvoid linenoiseSetHintsCallback(linenoiseHintsCallback *);\nvoid linenoiseSetFreeHintsCallback(linenoiseFreeHintsCallback *);\nvoid linenoiseAddCompletion(linenoiseCompletions *, const char *);\n\nchar *linenoise(const char *prompt);\nvoid linenoiseFree(void *ptr);\nint linenoiseHistoryAdd(const char *line);\nint linenoiseHistorySetMaxLen(int len);\nint linenoiseHistorySave(const char *filename);\nint linenoiseHistoryLoad(const char *filename);\nvoid linenoiseClearScreen(void);\nvoid linenoiseSetMultiLine(int ml);\nvoid linenoisePrintKeyCodes(void);\n\n#ifdef __cplusplus\n}\n#endif\n\n#endif /* __LINENOISE_H */\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/deps/lua/COPYRIGHT",
    "content": "Lua License\n-----------\n\nLua is licensed under the terms of the MIT license reproduced below.\nThis means that Lua is free software and can be used for both academic\nand commercial purposes at absolutely no cost.\n\nFor details and rationale, see http://www.lua.org/license.html .\n\n===============================================================================\n\nCopyright (C) 1994-2012 Lua.org, PUC-Rio.\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in\nall copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\nTHE SOFTWARE.\n\n===============================================================================\n\n(end of COPYRIGHT)\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/deps/lua/HISTORY",
    "content": "HISTORY for Lua 5.1\n\n* Changes from version 5.0 to 5.1\n  -------------------------------\n  Language:\n  + new module system.\n  + new semantics for control variables of fors.\n  + new semantics for setn/getn.\n  + new syntax/semantics for varargs.\n  + new long strings and comments.\n  + new `mod' operator (`%')\n  + new length operator #t\n  + metatables for all types\n  API:\n  + new functions: lua_createtable, lua_get(set)field, lua_push(to)integer.\n  + user supplies memory allocator (lua_open becomes lua_newstate).\n  + luaopen_* functions must be called through Lua.\n  Implementation:\n  + new configuration scheme via luaconf.h.\n  + incremental garbage collection.\n  + better handling of end-of-line in the lexer.\n  + fully reentrant parser (new Lua function `load')\n  + better support for 64-bit machines.\n  + native loadlib support for Mac OS X.\n  + standard distribution in only one library (lualib.a merged into lua.a)\n\n* Changes from version 4.0 to 5.0\n  -------------------------------\n  Language:\n  + lexical scoping.\n  + Lua coroutines.\n  + standard libraries now packaged in tables.\n  + tags replaced by metatables and tag methods replaced by metamethods,\n    stored in metatables.\n  + proper tail calls.\n  + each function can have its own global table, which can be shared.\n  + new __newindex metamethod, called when we insert a new key into a table.\n  + new block comments: --[[ ... ]].\n  + new generic for.\n  + new weak tables.\n  + new boolean type.\n  + new syntax \"local function\".\n  + (f()) returns the first value returned by f.\n  + {f()} fills a table with all values returned by f.\n  + \\n ignored in [[\\n .\n  + fixed and-or priorities.\n  + more general syntax for function definition (e.g. function a.x.y:f()...end).\n  + more general syntax for function calls (e.g. (print or write)(9)).\n  + new functions (time/date, tmpfile, unpack, require, load*, etc.).\n  API:\n  + chunks are loaded by using lua_load; new luaL_loadfile and luaL_loadbuffer.\n  + introduced lightweight userdata, a simple \"void*\" without a metatable.\n  + new error handling protocol: the core no longer prints error messages;\n    all errors are reported to the caller on the stack.\n  + new lua_atpanic for host cleanup.\n  + new, signal-safe, hook scheme.\n  Implementation:\n  + new license: MIT.\n  + new, faster, register-based virtual machine.\n  + support for external multithreading and coroutines.\n  + new and consistent error message format.\n  + the core no longer needs \"stdio.h\" for anything (except for a single\n    use of sprintf to convert numbers to strings).\n  + lua.c now runs the environment variable LUA_INIT, if present. It can\n    be \"@filename\", to run a file, or the chunk itself.\n  + support for user extensions in lua.c.\n    sample implementation given for command line editing.\n  + new dynamic loading library, active by default on several platforms.\n  + safe garbage-collector metamethods.\n  + precompiled bytecodes checked for integrity (secure binary dostring).\n  + strings are fully aligned.\n  + position capture in string.find.\n  + read('*l') can read lines with embedded zeros.\n\n* Changes from version 3.2 to 4.0\n  -------------------------------\n  Language:\n  + new \"break\" and \"for\" statements (both numerical and for tables).\n  + uniform treatment of globals: globals are now stored in a Lua table.\n  + improved error messages.\n  + no more '$debug': full speed *and* full debug information.\n  + new read form: read(N) for next N bytes.\n  + general read patterns now deprecated.\n    (still available with -DCOMPAT_READPATTERNS.)\n  + all return values are passed as arguments for the last function\n    (old semantics still available with -DLUA_COMPAT_ARGRET)\n  + garbage collection tag methods for tables now deprecated.\n  + there is now only one tag method for order.\n  API:\n  + New API: fully re-entrant, simpler, and more efficient.\n  + New debug API.\n  Implementation:\n  + faster than ever: cleaner virtual machine and new hashing algorithm.\n  + non-recursive garbage-collector algorithm.\n  + reduced memory usage for programs with many strings.\n  + improved treatment for memory allocation errors.\n  + improved support for 16-bit machines (we hope).\n  + code now compiles unmodified as both ANSI C and C++.\n  + numbers in bases other than 10 are converted using strtoul.\n  + new -f option in Lua to support #! scripts.\n  + luac can now combine text and binaries.\n\n* Changes from version 3.1 to 3.2\n  -------------------------------\n  + redirected all output in Lua's core to _ERRORMESSAGE and _ALERT.\n  + increased limit on the number of constants and globals per function\n    (from 2^16 to 2^24).\n  + debugging info (lua_debug and hooks) moved into lua_state and new API\n    functions provided to get and set this info.\n  + new debug lib gives full debugging access within Lua.\n  + new table functions \"foreachi\", \"sort\", \"tinsert\", \"tremove\", \"getn\".\n  + new io functions \"flush\", \"seek\".\n\n* Changes from version 3.0 to 3.1\n  -------------------------------\n  + NEW FEATURE: anonymous functions with closures (via \"upvalues\").\n  + new syntax:\n    - local variables in chunks.\n    - better scope control with DO block END.\n    - constructors can now be also written: { record-part; list-part }.\n    - more general syntax for function calls and lvalues, e.g.:\n      f(x).y=1\n      o:f(x,y):g(z)\n      f\"string\" is sugar for f(\"string\")\n  + strings may now contain arbitrary binary data (e.g., embedded zeros).\n  + major code re-organization and clean-up; reduced module interdependecies.\n  + no arbitrary limits on the total number of constants and globals.\n  + support for multiple global contexts.\n  + better syntax error messages.\n  + new traversal functions \"foreach\" and \"foreachvar\".\n  + the default for numbers is now double.\n    changing it to use floats or longs is easy.\n  + complete debug information stored in pre-compiled chunks.\n  + sample interpreter now prompts user when run interactively, and also\n    handles control-C interruptions gracefully.\n\n* Changes from version 2.5 to 3.0\n  -------------------------------\n  + NEW CONCEPT: \"tag methods\".\n    Tag methods replace fallbacks as the meta-mechanism for extending the\n    semantics of Lua. Whereas fallbacks had a global nature, tag methods\n    work on objects having the same tag (e.g., groups of tables).\n    Existing code that uses fallbacks should work without change.\n  + new, general syntax for constructors {[exp] = exp, ... }.\n  + support for handling variable number of arguments in functions (varargs).\n  + support for conditional compilation ($if ... $else ... $end).\n  + cleaner semantics in API simplifies host code.\n  + better support for writing libraries (auxlib.h).\n  + better type checking and error messages in the standard library.\n  + luac can now also undump.\n\n* Changes from version 2.4 to 2.5\n  -------------------------------\n  + io and string libraries are now based on pattern matching;\n    the old libraries are still available for compatibility\n  + dofile and dostring can now return values (via return statement)\n  + better support for 16- and 64-bit machines\n  + expanded documentation, with more examples\n\n* Changes from version 2.2 to 2.4\n  -------------------------------\n  + external compiler creates portable binary files that can be loaded faster\n  + interface for debugging and profiling\n  + new \"getglobal\" fallback\n  + new functions for handling references to Lua objects\n  + new functions in standard lib\n  + only one copy of each string is stored\n  + expanded documentation, with more examples\n\n* Changes from version 2.1 to 2.2\n  -------------------------------\n  + functions now may be declared with any \"lvalue\" as a name\n  + garbage collection of functions\n  + support for pipes\n\n* Changes from version 1.1 to 2.1\n  -------------------------------\n  + object-oriented support\n  + fallbacks\n  + simplified syntax for tables\n  + many internal improvements\n\n(end of HISTORY)\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/deps/lua/INSTALL",
    "content": "INSTALL for Lua 5.1\n\n* Building Lua\n  ------------\n  Lua is built in the src directory, but the build process can be\n  controlled from the top-level Makefile.\n\n  Building Lua on Unix systems should be very easy. First do \"make\" and\n  see if your platform is listed. If so, just do \"make xxx\", where xxx\n  is your platform name. The platforms currently supported are:\n    aix ansi bsd freebsd generic linux macosx mingw posix solaris\n\n  If your platform is not listed, try the closest one or posix, generic,\n  ansi, in this order.\n\n  See below for customization instructions and for instructions on how\n  to build with other Windows compilers.\n\n  If you want to check that Lua has been built correctly, do \"make test\"\n  after building Lua. Also, have a look at the example programs in test.\n\n* Installing Lua\n  --------------\n  Once you have built Lua, you may want to install it in an official\n  place in your system. In this case, do \"make install\". The official\n  place and the way to install files are defined in Makefile. You must\n  have the right permissions to install files.\n\n  If you want to build and install Lua in one step, do \"make xxx install\",\n  where xxx is your platform name.\n\n  If you want to install Lua locally, then do \"make local\". This will\n  create directories bin, include, lib, man, and install Lua there as\n  follows:\n\n    bin:\tlua luac\n    include:\tlua.h luaconf.h lualib.h lauxlib.h lua.hpp\n    lib:\tliblua.a\n    man/man1:\tlua.1 luac.1\n\n  These are the only directories you need for development.\n\n  There are man pages for lua and luac, in both nroff and html, and a\n  reference manual in html in doc, some sample code in test, and some\n  useful stuff in etc. You don't need these directories for development.\n\n  If you want to install Lua locally, but in some other directory, do\n  \"make install INSTALL_TOP=xxx\", where xxx is your chosen directory.\n\n  See below for instructions for Windows and other systems.\n\n* Customization\n  -------------\n  Three things can be customized by editing a file:\n    - Where and how to install Lua -- edit Makefile.\n    - How to build Lua -- edit src/Makefile.\n    - Lua features -- edit src/luaconf.h.\n\n  You don't actually need to edit the Makefiles because you may set the\n  relevant variables when invoking make.\n\n  On the other hand, if you need to select some Lua features, you'll need\n  to edit src/luaconf.h. The edited file will be the one installed, and\n  it will be used by any Lua clients that you build, to ensure consistency.\n\n  We strongly recommend that you enable dynamic loading. This is done\n  automatically for all platforms listed above that have this feature\n  (and also Windows). See src/luaconf.h and also src/Makefile.\n\n* Building Lua on Windows and other systems\n  -----------------------------------------\n  If you're not using the usual Unix tools, then the instructions for\n  building Lua depend on the compiler you use. You'll need to create\n  projects (or whatever your compiler uses) for building the library,\n  the interpreter, and the compiler, as follows:\n\n  library:\tlapi.c lcode.c ldebug.c ldo.c ldump.c lfunc.c lgc.c llex.c\n\t\tlmem.c lobject.c lopcodes.c lparser.c lstate.c lstring.c\n\t\tltable.c ltm.c lundump.c lvm.c lzio.c\n\t\tlauxlib.c lbaselib.c ldblib.c liolib.c lmathlib.c loslib.c\n\t\tltablib.c lstrlib.c loadlib.c linit.c\n\n  interpreter:\tlibrary, lua.c\n\n  compiler:\tlibrary, luac.c print.c\n\n  If you use Visual Studio .NET, you can use etc/luavs.bat in its\n  \"Command Prompt\".\n\n  If all you want is to build the Lua interpreter, you may put all .c files\n  in a single project, except for luac.c and print.c. Or just use etc/all.c.\n\n  To use Lua as a library in your own programs, you'll need to know how to\n  create and use libraries with your compiler.\n\n  As mentioned above, you may edit luaconf.h to select some features before\n  building Lua.\n\n(end of INSTALL)\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/deps/lua/Makefile",
    "content": "# makefile for installing Lua\n# see INSTALL for installation instructions\n# see src/Makefile and src/luaconf.h for further customization\n\n# == CHANGE THE SETTINGS BELOW TO SUIT YOUR ENVIRONMENT =======================\n\n# Your platform. See PLATS for possible values.\nPLAT= none\n\n# Where to install. The installation starts in the src and doc directories,\n# so take care if INSTALL_TOP is not an absolute path.\nINSTALL_TOP= /usr/local\nINSTALL_BIN= $(INSTALL_TOP)/bin\nINSTALL_INC= $(INSTALL_TOP)/include\nINSTALL_LIB= $(INSTALL_TOP)/lib\nINSTALL_MAN= $(INSTALL_TOP)/man/man1\n#\n# You probably want to make INSTALL_LMOD and INSTALL_CMOD consistent with\n# LUA_ROOT, LUA_LDIR, and LUA_CDIR in luaconf.h (and also with etc/lua.pc).\nINSTALL_LMOD= $(INSTALL_TOP)/share/lua/$V\nINSTALL_CMOD= $(INSTALL_TOP)/lib/lua/$V\n\n# How to install. If your install program does not support \"-p\", then you\n# may have to run ranlib on the installed liblua.a (do \"make ranlib\").\nINSTALL= install -p\nINSTALL_EXEC= $(INSTALL) -m 0755\nINSTALL_DATA= $(INSTALL) -m 0644\n#\n# If you don't have install you can use cp instead.\n# INSTALL= cp -p\n# INSTALL_EXEC= $(INSTALL)\n# INSTALL_DATA= $(INSTALL)\n\n# Utilities.\nMKDIR= mkdir -p\nRANLIB= ranlib\n\n# == END OF USER SETTINGS. NO NEED TO CHANGE ANYTHING BELOW THIS LINE =========\n\n# Convenience platforms targets.\nPLATS= aix ansi bsd freebsd generic linux macosx mingw posix solaris\n\n# What to install.\nTO_BIN= lua luac\nTO_INC= lua.h luaconf.h lualib.h lauxlib.h ../etc/lua.hpp\nTO_LIB= liblua.a\nTO_MAN= lua.1 luac.1\n\n# Lua version and release.\nV= 5.1\nR= 5.1.5\n\nall:\t$(PLAT)\n\n$(PLATS) clean:\n\tcd src && $(MAKE) $@\n\ntest:\tdummy\n\tsrc/lua test/hello.lua\n\ninstall: dummy\n\tcd src && $(MKDIR) $(INSTALL_BIN) $(INSTALL_INC) $(INSTALL_LIB) $(INSTALL_MAN) $(INSTALL_LMOD) $(INSTALL_CMOD)\n\tcd src && $(INSTALL_EXEC) $(TO_BIN) $(INSTALL_BIN)\n\tcd src && $(INSTALL_DATA) $(TO_INC) $(INSTALL_INC)\n\tcd src && $(INSTALL_DATA) $(TO_LIB) $(INSTALL_LIB)\n\tcd doc && $(INSTALL_DATA) $(TO_MAN) $(INSTALL_MAN)\n\nranlib:\n\tcd src && cd $(INSTALL_LIB) && $(RANLIB) $(TO_LIB)\n\nlocal:\n\t$(MAKE) install INSTALL_TOP=..\n\nnone:\n\t@echo \"Please do\"\n\t@echo \"   make PLATFORM\"\n\t@echo \"where PLATFORM is one of these:\"\n\t@echo \"   $(PLATS)\"\n\t@echo \"See INSTALL for complete instructions.\"\n\n# make may get confused with test/ and INSTALL in a case-insensitive OS\ndummy:\n\n# echo config parameters\necho:\n\t@echo \"\"\n\t@echo \"These are the parameters currently set in src/Makefile to build Lua $R:\"\n\t@echo \"\"\n\t@cd src && $(MAKE) -s echo\n\t@echo \"\"\n\t@echo \"These are the parameters currently set in Makefile to install Lua $R:\"\n\t@echo \"\"\n\t@echo \"PLAT = $(PLAT)\"\n\t@echo \"INSTALL_TOP = $(INSTALL_TOP)\"\n\t@echo \"INSTALL_BIN = $(INSTALL_BIN)\"\n\t@echo \"INSTALL_INC = $(INSTALL_INC)\"\n\t@echo \"INSTALL_LIB = $(INSTALL_LIB)\"\n\t@echo \"INSTALL_MAN = $(INSTALL_MAN)\"\n\t@echo \"INSTALL_LMOD = $(INSTALL_LMOD)\"\n\t@echo \"INSTALL_CMOD = $(INSTALL_CMOD)\"\n\t@echo \"INSTALL_EXEC = $(INSTALL_EXEC)\"\n\t@echo \"INSTALL_DATA = $(INSTALL_DATA)\"\n\t@echo \"\"\n\t@echo \"See also src/luaconf.h .\"\n\t@echo \"\"\n\n# echo private config parameters\npecho:\n\t@echo \"V = $(V)\"\n\t@echo \"R = $(R)\"\n\t@echo \"TO_BIN = $(TO_BIN)\"\n\t@echo \"TO_INC = $(TO_INC)\"\n\t@echo \"TO_LIB = $(TO_LIB)\"\n\t@echo \"TO_MAN = $(TO_MAN)\"\n\n# echo config parameters as Lua code\n# uncomment the last sed expression if you want nil instead of empty strings\nlecho:\n\t@echo \"-- installation parameters for Lua $R\"\n\t@echo \"VERSION = '$V'\"\n\t@echo \"RELEASE = '$R'\"\n\t@$(MAKE) echo | grep = | sed -e 's/= /= \"/' -e 's/$$/\"/' #-e 's/\"\"/nil/'\n\t@echo \"-- EOF\"\n\n# list targets that do not create files (but not all makes understand .PHONY)\n.PHONY: all $(PLATS) clean test install local none dummy echo pecho lecho\n\n# (end of Makefile)\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/deps/lua/README",
    "content": "README for Lua 5.1\n\nSee INSTALL for installation instructions.\nSee HISTORY for a summary of changes since the last released version.\n\n* What is Lua?\n  ------------\n  Lua is a powerful, light-weight programming language designed for extending\n  applications. Lua is also frequently used as a general-purpose, stand-alone\n  language. Lua is free software.\n\n  For complete information, visit Lua's web site at http://www.lua.org/ .\n  For an executive summary, see http://www.lua.org/about.html .\n\n  Lua has been used in many different projects around the world.\n  For a short list, see http://www.lua.org/uses.html .\n\n* Availability\n  ------------\n  Lua is freely available for both academic and commercial purposes.\n  See COPYRIGHT and http://www.lua.org/license.html for details.\n  Lua can be downloaded at http://www.lua.org/download.html .\n\n* Installation\n  ------------\n  Lua is implemented in pure ANSI C, and compiles unmodified in all known\n  platforms that have an ANSI C compiler. In most Unix-like platforms, simply\n  do \"make\" with a suitable target. See INSTALL for detailed instructions.\n\n* Origin\n  ------\n  Lua is developed at Lua.org, a laboratory of the Department of Computer\n  Science of PUC-Rio (the Pontifical Catholic University of Rio de Janeiro\n  in Brazil).\n  For more information about the authors, see http://www.lua.org/authors.html .\n\n(end of README)\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/deps/lua/doc/contents.html",
    "content": "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\">\n<HTML>\n<HEAD>\n<TITLE>Lua 5.1 Reference Manual - contents</TITLE>\n<LINK REL=\"stylesheet\" TYPE=\"text/css\" HREF=\"lua.css\">\n<META HTTP-EQUIV=\"content-type\" CONTENT=\"text/html; charset=utf-8\">\n<STYLE TYPE=\"text/css\">\nul {\n\tlist-style-type: none ;\n}\n</STYLE>\n</HEAD>\n\n<BODY>\n\n<HR>\n<H1>\n<A HREF=\"http://www.lua.org/\"><IMG SRC=\"logo.gif\" ALT=\"\" BORDER=0></A>\nLua 5.1 Reference Manual\n</H1>\n\n<P>\nThe reference manual is the official definition of the Lua language.\nFor a complete introduction to Lua programming, see the book\n<A HREF=\"http://www.lua.org/docs.html#pil\">Programming in Lua</A>.\n\n<P>\nThis manual is also available as a book:\n<BLOCKQUOTE>\n<A HREF=\"http://www.amazon.com/exec/obidos/ASIN/8590379833/lua-indexmanual-20\">\n<IMG SRC=\"cover.png\" ALT=\"\" TITLE=\"buy from Amazon\" BORDER=1 ALIGN=\"left\" HSPACE=12>\n</A>\n<B>Lua 5.1 Reference Manual</B>\n<BR>by R. Ierusalimschy, L. H. de Figueiredo, W. Celes\n<BR>Lua.org, August 2006\n<BR>ISBN 85-903798-3-3\n<BR CLEAR=\"all\">\n</BLOCKQUOTE>\n\n<P>\n<A HREF=\"http://www.amazon.com/exec/obidos/ASIN/8590379833/lua-indexmanual-20\">Buy a copy</A>\nof this book and\n<A HREF=\"http://www.lua.org/donations.html\">help to support</A>\nthe Lua project.\n\n<P>\n<A HREF=\"manual.html\">start</A>\n&middot;\n<A HREF=\"#contents\">contents</A>\n&middot;\n<A HREF=\"#index\">index</A>\n&middot;\n<A HREF=\"http://www.lua.org/manual/\">other versions</A>\n<HR>\n<SMALL>\nCopyright &copy; 2006&ndash;2012 Lua.org, PUC-Rio.\nFreely available under the terms of the\n<A HREF=\"http://www.lua.org/license.html\">Lua license</A>.\n</SMALL>\n\n<H2><A NAME=\"contents\">Contents</A></H2>\n<UL style=\"padding: 0\">\n<LI><A HREF=\"manual.html\">1 &ndash; Introduction</A>\n<P>\n<LI><A HREF=\"manual.html#2\">2 &ndash; The Language</A>\n<UL>\n<LI><A HREF=\"manual.html#2.1\">2.1 &ndash; Lexical Conventions</A>\n<LI><A HREF=\"manual.html#2.2\">2.2 &ndash; Values and Types</A>\n<UL>\n<LI><A HREF=\"manual.html#2.2.1\">2.2.1 &ndash; Coercion</A>\n</UL>\n<LI><A HREF=\"manual.html#2.3\">2.3 &ndash; Variables</A>\n<LI><A HREF=\"manual.html#2.4\">2.4 &ndash; Statements</A>\n<UL>\n<LI><A HREF=\"manual.html#2.4.1\">2.4.1 &ndash; Chunks</A>\n<LI><A HREF=\"manual.html#2.4.2\">2.4.2 &ndash; Blocks</A>\n<LI><A HREF=\"manual.html#2.4.3\">2.4.3 &ndash; Assignment</A>\n<LI><A HREF=\"manual.html#2.4.4\">2.4.4 &ndash; Control Structures</A>\n<LI><A HREF=\"manual.html#2.4.5\">2.4.5 &ndash; For Statement</A>\n<LI><A HREF=\"manual.html#2.4.6\">2.4.6 &ndash; Function Calls as Statements</A>\n<LI><A HREF=\"manual.html#2.4.7\">2.4.7 &ndash; Local Declarations</A>\n</UL>\n<LI><A HREF=\"manual.html#2.5\">2.5 &ndash; Expressions</A>\n<UL>\n<LI><A HREF=\"manual.html#2.5.1\">2.5.1 &ndash; Arithmetic Operators</A>\n<LI><A HREF=\"manual.html#2.5.2\">2.5.2 &ndash; Relational Operators</A>\n<LI><A HREF=\"manual.html#2.5.3\">2.5.3 &ndash; Logical Operators</A>\n<LI><A HREF=\"manual.html#2.5.4\">2.5.4 &ndash; Concatenation</A>\n<LI><A HREF=\"manual.html#2.5.5\">2.5.5 &ndash; The Length Operator</A>\n<LI><A HREF=\"manual.html#2.5.6\">2.5.6 &ndash; Precedence</A>\n<LI><A HREF=\"manual.html#2.5.7\">2.5.7 &ndash; Table Constructors</A>\n<LI><A HREF=\"manual.html#2.5.8\">2.5.8 &ndash; Function Calls</A>\n<LI><A HREF=\"manual.html#2.5.9\">2.5.9 &ndash; Function Definitions</A>\n</UL>\n<LI><A HREF=\"manual.html#2.6\">2.6 &ndash; Visibility Rules</A>\n<LI><A HREF=\"manual.html#2.7\">2.7 &ndash; Error Handling</A>\n<LI><A HREF=\"manual.html#2.8\">2.8 &ndash; Metatables</A>\n<LI><A HREF=\"manual.html#2.9\">2.9 &ndash; Environments</A>\n<LI><A HREF=\"manual.html#2.10\">2.10 &ndash; Garbage Collection</A>\n<UL>\n<LI><A HREF=\"manual.html#2.10.1\">2.10.1 &ndash; Garbage-Collection Metamethods</A>\n<LI><A HREF=\"manual.html#2.10.2\">2.10.2 &ndash; Weak Tables</A>\n</UL>\n<LI><A HREF=\"manual.html#2.11\">2.11 &ndash; Coroutines</A>\n</UL>\n<P>\n<LI><A HREF=\"manual.html#3\">3 &ndash; The Application Program Interface</A>\n<UL>\n<LI><A HREF=\"manual.html#3.1\">3.1 &ndash; The Stack</A>\n<LI><A HREF=\"manual.html#3.2\">3.2 &ndash; Stack Size</A>\n<LI><A HREF=\"manual.html#3.3\">3.3 &ndash; Pseudo-Indices</A>\n<LI><A HREF=\"manual.html#3.4\">3.4 &ndash; C Closures</A>\n<LI><A HREF=\"manual.html#3.5\">3.5 &ndash; Registry</A>\n<LI><A HREF=\"manual.html#3.6\">3.6 &ndash; Error Handling in C</A>\n<LI><A HREF=\"manual.html#3.7\">3.7 &ndash; Functions and Types</A>\n<LI><A HREF=\"manual.html#3.8\">3.8 &ndash; The Debug Interface</A>\n</UL>\n<P>\n<LI><A HREF=\"manual.html#4\">4 &ndash; The Auxiliary Library</A>\n<UL>\n<LI><A HREF=\"manual.html#4.1\">4.1 &ndash; Functions and Types</A>\n</UL>\n<P>\n<LI><A HREF=\"manual.html#5\">5 &ndash; Standard Libraries</A>\n<UL>\n<LI><A HREF=\"manual.html#5.1\">5.1 &ndash; Basic Functions</A>\n<LI><A HREF=\"manual.html#5.2\">5.2 &ndash; Coroutine Manipulation</A>\n<LI><A HREF=\"manual.html#5.3\">5.3 &ndash; Modules</A>\n<LI><A HREF=\"manual.html#5.4\">5.4 &ndash; String Manipulation</A>\n<UL>\n<LI><A HREF=\"manual.html#5.4.1\">5.4.1 &ndash; Patterns</A>\n</UL>\n<LI><A HREF=\"manual.html#5.5\">5.5 &ndash; Table Manipulation</A>\n<LI><A HREF=\"manual.html#5.6\">5.6 &ndash; Mathematical Functions</A>\n<LI><A HREF=\"manual.html#5.7\">5.7 &ndash; Input and Output Facilities</A>\n<LI><A HREF=\"manual.html#5.8\">5.8 &ndash; Operating System Facilities</A>\n<LI><A HREF=\"manual.html#5.9\">5.9 &ndash; The Debug Library</A>\n</UL>\n<P>\n<LI><A HREF=\"manual.html#6\">6 &ndash; Lua Stand-alone</A>\n<P>\n<LI><A HREF=\"manual.html#7\">7 &ndash; Incompatibilities with the Previous Version</A>\n<UL>\n<LI><A HREF=\"manual.html#7.1\">7.1 &ndash; Changes in the Language</A>\n<LI><A HREF=\"manual.html#7.2\">7.2 &ndash; Changes in the Libraries</A>\n<LI><A HREF=\"manual.html#7.3\">7.3 &ndash; Changes in the API</A>\n</UL>\n<P>\n<LI><A HREF=\"manual.html#8\">8 &ndash; The Complete Syntax of Lua</A>\n</UL>\n\n<H2><A NAME=\"index\">Index</A></H2>\n<TABLE WIDTH=\"100%\">\n<TR VALIGN=\"top\">\n<TD>\n<H3><A NAME=\"functions\">Lua functions</A></H3>\n<A HREF=\"manual.html#pdf-_G\">_G</A><BR>\n<A HREF=\"manual.html#pdf-_VERSION\">_VERSION</A><BR>\n<P>\n\n<A HREF=\"manual.html#pdf-assert\">assert</A><BR>\n<A HREF=\"manual.html#pdf-collectgarbage\">collectgarbage</A><BR>\n<A HREF=\"manual.html#pdf-dofile\">dofile</A><BR>\n<A HREF=\"manual.html#pdf-error\">error</A><BR>\n<A HREF=\"manual.html#pdf-getfenv\">getfenv</A><BR>\n<A HREF=\"manual.html#pdf-getmetatable\">getmetatable</A><BR>\n<A HREF=\"manual.html#pdf-ipairs\">ipairs</A><BR>\n<A HREF=\"manual.html#pdf-load\">load</A><BR>\n<A HREF=\"manual.html#pdf-loadfile\">loadfile</A><BR>\n<A HREF=\"manual.html#pdf-loadstring\">loadstring</A><BR>\n<A HREF=\"manual.html#pdf-module\">module</A><BR>\n<A HREF=\"manual.html#pdf-next\">next</A><BR>\n<A HREF=\"manual.html#pdf-pairs\">pairs</A><BR>\n<A HREF=\"manual.html#pdf-pcall\">pcall</A><BR>\n<A HREF=\"manual.html#pdf-print\">print</A><BR>\n<A HREF=\"manual.html#pdf-rawequal\">rawequal</A><BR>\n<A HREF=\"manual.html#pdf-rawget\">rawget</A><BR>\n<A HREF=\"manual.html#pdf-rawset\">rawset</A><BR>\n<A HREF=\"manual.html#pdf-require\">require</A><BR>\n<A HREF=\"manual.html#pdf-select\">select</A><BR>\n<A HREF=\"manual.html#pdf-setfenv\">setfenv</A><BR>\n<A HREF=\"manual.html#pdf-setmetatable\">setmetatable</A><BR>\n<A HREF=\"manual.html#pdf-tonumber\">tonumber</A><BR>\n<A HREF=\"manual.html#pdf-tostring\">tostring</A><BR>\n<A HREF=\"manual.html#pdf-type\">type</A><BR>\n<A HREF=\"manual.html#pdf-unpack\">unpack</A><BR>\n<A HREF=\"manual.html#pdf-xpcall\">xpcall</A><BR>\n<P>\n\n<A HREF=\"manual.html#pdf-coroutine.create\">coroutine.create</A><BR>\n<A HREF=\"manual.html#pdf-coroutine.resume\">coroutine.resume</A><BR>\n<A HREF=\"manual.html#pdf-coroutine.running\">coroutine.running</A><BR>\n<A HREF=\"manual.html#pdf-coroutine.status\">coroutine.status</A><BR>\n<A HREF=\"manual.html#pdf-coroutine.wrap\">coroutine.wrap</A><BR>\n<A HREF=\"manual.html#pdf-coroutine.yield\">coroutine.yield</A><BR>\n<P>\n\n<A HREF=\"manual.html#pdf-debug.debug\">debug.debug</A><BR>\n<A HREF=\"manual.html#pdf-debug.getfenv\">debug.getfenv</A><BR>\n<A HREF=\"manual.html#pdf-debug.gethook\">debug.gethook</A><BR>\n<A HREF=\"manual.html#pdf-debug.getinfo\">debug.getinfo</A><BR>\n<A HREF=\"manual.html#pdf-debug.getlocal\">debug.getlocal</A><BR>\n<A HREF=\"manual.html#pdf-debug.getmetatable\">debug.getmetatable</A><BR>\n<A HREF=\"manual.html#pdf-debug.getregistry\">debug.getregistry</A><BR>\n<A HREF=\"manual.html#pdf-debug.getupvalue\">debug.getupvalue</A><BR>\n<A HREF=\"manual.html#pdf-debug.setfenv\">debug.setfenv</A><BR>\n<A HREF=\"manual.html#pdf-debug.sethook\">debug.sethook</A><BR>\n<A HREF=\"manual.html#pdf-debug.setlocal\">debug.setlocal</A><BR>\n<A HREF=\"manual.html#pdf-debug.setmetatable\">debug.setmetatable</A><BR>\n<A HREF=\"manual.html#pdf-debug.setupvalue\">debug.setupvalue</A><BR>\n<A HREF=\"manual.html#pdf-debug.traceback\">debug.traceback</A><BR>\n\n</TD>\n<TD>\n<H3>&nbsp;</H3>\n<A HREF=\"manual.html#pdf-file:close\">file:close</A><BR>\n<A HREF=\"manual.html#pdf-file:flush\">file:flush</A><BR>\n<A HREF=\"manual.html#pdf-file:lines\">file:lines</A><BR>\n<A HREF=\"manual.html#pdf-file:read\">file:read</A><BR>\n<A HREF=\"manual.html#pdf-file:seek\">file:seek</A><BR>\n<A HREF=\"manual.html#pdf-file:setvbuf\">file:setvbuf</A><BR>\n<A HREF=\"manual.html#pdf-file:write\">file:write</A><BR>\n<P>\n\n<A HREF=\"manual.html#pdf-io.close\">io.close</A><BR>\n<A HREF=\"manual.html#pdf-io.flush\">io.flush</A><BR>\n<A HREF=\"manual.html#pdf-io.input\">io.input</A><BR>\n<A HREF=\"manual.html#pdf-io.lines\">io.lines</A><BR>\n<A HREF=\"manual.html#pdf-io.open\">io.open</A><BR>\n<A HREF=\"manual.html#pdf-io.output\">io.output</A><BR>\n<A HREF=\"manual.html#pdf-io.popen\">io.popen</A><BR>\n<A HREF=\"manual.html#pdf-io.read\">io.read</A><BR>\n<A HREF=\"manual.html#pdf-io.stderr\">io.stderr</A><BR>\n<A HREF=\"manual.html#pdf-io.stdin\">io.stdin</A><BR>\n<A HREF=\"manual.html#pdf-io.stdout\">io.stdout</A><BR>\n<A HREF=\"manual.html#pdf-io.tmpfile\">io.tmpfile</A><BR>\n<A HREF=\"manual.html#pdf-io.type\">io.type</A><BR>\n<A HREF=\"manual.html#pdf-io.write\">io.write</A><BR>\n<P>\n\n<A HREF=\"manual.html#pdf-math.abs\">math.abs</A><BR>\n<A HREF=\"manual.html#pdf-math.acos\">math.acos</A><BR>\n<A HREF=\"manual.html#pdf-math.asin\">math.asin</A><BR>\n<A HREF=\"manual.html#pdf-math.atan\">math.atan</A><BR>\n<A HREF=\"manual.html#pdf-math.atan2\">math.atan2</A><BR>\n<A HREF=\"manual.html#pdf-math.ceil\">math.ceil</A><BR>\n<A HREF=\"manual.html#pdf-math.cos\">math.cos</A><BR>\n<A HREF=\"manual.html#pdf-math.cosh\">math.cosh</A><BR>\n<A HREF=\"manual.html#pdf-math.deg\">math.deg</A><BR>\n<A HREF=\"manual.html#pdf-math.exp\">math.exp</A><BR>\n<A HREF=\"manual.html#pdf-math.floor\">math.floor</A><BR>\n<A HREF=\"manual.html#pdf-math.fmod\">math.fmod</A><BR>\n<A HREF=\"manual.html#pdf-math.frexp\">math.frexp</A><BR>\n<A HREF=\"manual.html#pdf-math.huge\">math.huge</A><BR>\n<A HREF=\"manual.html#pdf-math.ldexp\">math.ldexp</A><BR>\n<A HREF=\"manual.html#pdf-math.log\">math.log</A><BR>\n<A HREF=\"manual.html#pdf-math.log10\">math.log10</A><BR>\n<A HREF=\"manual.html#pdf-math.max\">math.max</A><BR>\n<A HREF=\"manual.html#pdf-math.min\">math.min</A><BR>\n<A HREF=\"manual.html#pdf-math.modf\">math.modf</A><BR>\n<A HREF=\"manual.html#pdf-math.pi\">math.pi</A><BR>\n<A HREF=\"manual.html#pdf-math.pow\">math.pow</A><BR>\n<A HREF=\"manual.html#pdf-math.rad\">math.rad</A><BR>\n<A HREF=\"manual.html#pdf-math.random\">math.random</A><BR>\n<A HREF=\"manual.html#pdf-math.randomseed\">math.randomseed</A><BR>\n<A HREF=\"manual.html#pdf-math.sin\">math.sin</A><BR>\n<A HREF=\"manual.html#pdf-math.sinh\">math.sinh</A><BR>\n<A HREF=\"manual.html#pdf-math.sqrt\">math.sqrt</A><BR>\n<A HREF=\"manual.html#pdf-math.tan\">math.tan</A><BR>\n<A HREF=\"manual.html#pdf-math.tanh\">math.tanh</A><BR>\n<P>\n\n<A HREF=\"manual.html#pdf-os.clock\">os.clock</A><BR>\n<A HREF=\"manual.html#pdf-os.date\">os.date</A><BR>\n<A HREF=\"manual.html#pdf-os.difftime\">os.difftime</A><BR>\n<A HREF=\"manual.html#pdf-os.execute\">os.execute</A><BR>\n<A HREF=\"manual.html#pdf-os.exit\">os.exit</A><BR>\n<A HREF=\"manual.html#pdf-os.getenv\">os.getenv</A><BR>\n<A HREF=\"manual.html#pdf-os.remove\">os.remove</A><BR>\n<A HREF=\"manual.html#pdf-os.rename\">os.rename</A><BR>\n<A HREF=\"manual.html#pdf-os.setlocale\">os.setlocale</A><BR>\n<A HREF=\"manual.html#pdf-os.time\">os.time</A><BR>\n<A HREF=\"manual.html#pdf-os.tmpname\">os.tmpname</A><BR>\n<P>\n\n<A HREF=\"manual.html#pdf-package.cpath\">package.cpath</A><BR>\n<A HREF=\"manual.html#pdf-package.loaded\">package.loaded</A><BR>\n<A HREF=\"manual.html#pdf-package.loaders\">package.loaders</A><BR>\n<A HREF=\"manual.html#pdf-package.loadlib\">package.loadlib</A><BR>\n<A HREF=\"manual.html#pdf-package.path\">package.path</A><BR>\n<A HREF=\"manual.html#pdf-package.preload\">package.preload</A><BR>\n<A HREF=\"manual.html#pdf-package.seeall\">package.seeall</A><BR>\n<P>\n\n<A HREF=\"manual.html#pdf-string.byte\">string.byte</A><BR>\n<A HREF=\"manual.html#pdf-string.char\">string.char</A><BR>\n<A HREF=\"manual.html#pdf-string.dump\">string.dump</A><BR>\n<A HREF=\"manual.html#pdf-string.find\">string.find</A><BR>\n<A HREF=\"manual.html#pdf-string.format\">string.format</A><BR>\n<A HREF=\"manual.html#pdf-string.gmatch\">string.gmatch</A><BR>\n<A HREF=\"manual.html#pdf-string.gsub\">string.gsub</A><BR>\n<A HREF=\"manual.html#pdf-string.len\">string.len</A><BR>\n<A HREF=\"manual.html#pdf-string.lower\">string.lower</A><BR>\n<A HREF=\"manual.html#pdf-string.match\">string.match</A><BR>\n<A HREF=\"manual.html#pdf-string.rep\">string.rep</A><BR>\n<A HREF=\"manual.html#pdf-string.reverse\">string.reverse</A><BR>\n<A HREF=\"manual.html#pdf-string.sub\">string.sub</A><BR>\n<A HREF=\"manual.html#pdf-string.upper\">string.upper</A><BR>\n<P>\n\n<A HREF=\"manual.html#pdf-table.concat\">table.concat</A><BR>\n<A HREF=\"manual.html#pdf-table.insert\">table.insert</A><BR>\n<A HREF=\"manual.html#pdf-table.maxn\">table.maxn</A><BR>\n<A HREF=\"manual.html#pdf-table.remove\">table.remove</A><BR>\n<A HREF=\"manual.html#pdf-table.sort\">table.sort</A><BR>\n\n</TD>\n<TD>\n<H3>C API</H3>\n<A HREF=\"manual.html#lua_Alloc\">lua_Alloc</A><BR>\n<A HREF=\"manual.html#lua_CFunction\">lua_CFunction</A><BR>\n<A HREF=\"manual.html#lua_Debug\">lua_Debug</A><BR>\n<A HREF=\"manual.html#lua_Hook\">lua_Hook</A><BR>\n<A HREF=\"manual.html#lua_Integer\">lua_Integer</A><BR>\n<A HREF=\"manual.html#lua_Number\">lua_Number</A><BR>\n<A HREF=\"manual.html#lua_Reader\">lua_Reader</A><BR>\n<A HREF=\"manual.html#lua_State\">lua_State</A><BR>\n<A HREF=\"manual.html#lua_Writer\">lua_Writer</A><BR>\n<P>\n\n<A HREF=\"manual.html#lua_atpanic\">lua_atpanic</A><BR>\n<A HREF=\"manual.html#lua_call\">lua_call</A><BR>\n<A HREF=\"manual.html#lua_checkstack\">lua_checkstack</A><BR>\n<A HREF=\"manual.html#lua_close\">lua_close</A><BR>\n<A HREF=\"manual.html#lua_concat\">lua_concat</A><BR>\n<A HREF=\"manual.html#lua_cpcall\">lua_cpcall</A><BR>\n<A HREF=\"manual.html#lua_createtable\">lua_createtable</A><BR>\n<A HREF=\"manual.html#lua_dump\">lua_dump</A><BR>\n<A HREF=\"manual.html#lua_equal\">lua_equal</A><BR>\n<A HREF=\"manual.html#lua_error\">lua_error</A><BR>\n<A HREF=\"manual.html#lua_gc\">lua_gc</A><BR>\n<A HREF=\"manual.html#lua_getallocf\">lua_getallocf</A><BR>\n<A HREF=\"manual.html#lua_getfenv\">lua_getfenv</A><BR>\n<A HREF=\"manual.html#lua_getfield\">lua_getfield</A><BR>\n<A HREF=\"manual.html#lua_getglobal\">lua_getglobal</A><BR>\n<A HREF=\"manual.html#lua_gethook\">lua_gethook</A><BR>\n<A HREF=\"manual.html#lua_gethookcount\">lua_gethookcount</A><BR>\n<A HREF=\"manual.html#lua_gethookmask\">lua_gethookmask</A><BR>\n<A HREF=\"manual.html#lua_getinfo\">lua_getinfo</A><BR>\n<A HREF=\"manual.html#lua_getlocal\">lua_getlocal</A><BR>\n<A HREF=\"manual.html#lua_getmetatable\">lua_getmetatable</A><BR>\n<A HREF=\"manual.html#lua_getstack\">lua_getstack</A><BR>\n<A HREF=\"manual.html#lua_gettable\">lua_gettable</A><BR>\n<A HREF=\"manual.html#lua_gettop\">lua_gettop</A><BR>\n<A HREF=\"manual.html#lua_getupvalue\">lua_getupvalue</A><BR>\n<A HREF=\"manual.html#lua_insert\">lua_insert</A><BR>\n<A HREF=\"manual.html#lua_isboolean\">lua_isboolean</A><BR>\n<A HREF=\"manual.html#lua_iscfunction\">lua_iscfunction</A><BR>\n<A HREF=\"manual.html#lua_isfunction\">lua_isfunction</A><BR>\n<A HREF=\"manual.html#lua_islightuserdata\">lua_islightuserdata</A><BR>\n<A HREF=\"manual.html#lua_isnil\">lua_isnil</A><BR>\n<A HREF=\"manual.html#lua_isnone\">lua_isnone</A><BR>\n<A HREF=\"manual.html#lua_isnoneornil\">lua_isnoneornil</A><BR>\n<A HREF=\"manual.html#lua_isnumber\">lua_isnumber</A><BR>\n<A HREF=\"manual.html#lua_isstring\">lua_isstring</A><BR>\n<A HREF=\"manual.html#lua_istable\">lua_istable</A><BR>\n<A HREF=\"manual.html#lua_isthread\">lua_isthread</A><BR>\n<A HREF=\"manual.html#lua_isuserdata\">lua_isuserdata</A><BR>\n<A HREF=\"manual.html#lua_lessthan\">lua_lessthan</A><BR>\n<A HREF=\"manual.html#lua_load\">lua_load</A><BR>\n<A HREF=\"manual.html#lua_newstate\">lua_newstate</A><BR>\n<A HREF=\"manual.html#lua_newtable\">lua_newtable</A><BR>\n<A HREF=\"manual.html#lua_newthread\">lua_newthread</A><BR>\n<A HREF=\"manual.html#lua_newuserdata\">lua_newuserdata</A><BR>\n<A HREF=\"manual.html#lua_next\">lua_next</A><BR>\n<A HREF=\"manual.html#lua_objlen\">lua_objlen</A><BR>\n<A HREF=\"manual.html#lua_pcall\">lua_pcall</A><BR>\n<A HREF=\"manual.html#lua_pop\">lua_pop</A><BR>\n<A HREF=\"manual.html#lua_pushboolean\">lua_pushboolean</A><BR>\n<A HREF=\"manual.html#lua_pushcclosure\">lua_pushcclosure</A><BR>\n<A HREF=\"manual.html#lua_pushcfunction\">lua_pushcfunction</A><BR>\n<A HREF=\"manual.html#lua_pushfstring\">lua_pushfstring</A><BR>\n<A HREF=\"manual.html#lua_pushinteger\">lua_pushinteger</A><BR>\n<A HREF=\"manual.html#lua_pushlightuserdata\">lua_pushlightuserdata</A><BR>\n<A HREF=\"manual.html#lua_pushliteral\">lua_pushliteral</A><BR>\n<A HREF=\"manual.html#lua_pushlstring\">lua_pushlstring</A><BR>\n<A HREF=\"manual.html#lua_pushnil\">lua_pushnil</A><BR>\n<A HREF=\"manual.html#lua_pushnumber\">lua_pushnumber</A><BR>\n<A HREF=\"manual.html#lua_pushstring\">lua_pushstring</A><BR>\n<A HREF=\"manual.html#lua_pushthread\">lua_pushthread</A><BR>\n<A HREF=\"manual.html#lua_pushvalue\">lua_pushvalue</A><BR>\n<A HREF=\"manual.html#lua_pushvfstring\">lua_pushvfstring</A><BR>\n<A HREF=\"manual.html#lua_rawequal\">lua_rawequal</A><BR>\n<A HREF=\"manual.html#lua_rawget\">lua_rawget</A><BR>\n<A HREF=\"manual.html#lua_rawgeti\">lua_rawgeti</A><BR>\n<A HREF=\"manual.html#lua_rawset\">lua_rawset</A><BR>\n<A HREF=\"manual.html#lua_rawseti\">lua_rawseti</A><BR>\n<A HREF=\"manual.html#lua_register\">lua_register</A><BR>\n<A HREF=\"manual.html#lua_remove\">lua_remove</A><BR>\n<A HREF=\"manual.html#lua_replace\">lua_replace</A><BR>\n<A HREF=\"manual.html#lua_resume\">lua_resume</A><BR>\n<A HREF=\"manual.html#lua_setallocf\">lua_setallocf</A><BR>\n<A HREF=\"manual.html#lua_setfenv\">lua_setfenv</A><BR>\n<A HREF=\"manual.html#lua_setfield\">lua_setfield</A><BR>\n<A HREF=\"manual.html#lua_setglobal\">lua_setglobal</A><BR>\n<A HREF=\"manual.html#lua_sethook\">lua_sethook</A><BR>\n<A HREF=\"manual.html#lua_setlocal\">lua_setlocal</A><BR>\n<A HREF=\"manual.html#lua_setmetatable\">lua_setmetatable</A><BR>\n<A HREF=\"manual.html#lua_settable\">lua_settable</A><BR>\n<A HREF=\"manual.html#lua_settop\">lua_settop</A><BR>\n<A HREF=\"manual.html#lua_setupvalue\">lua_setupvalue</A><BR>\n<A HREF=\"manual.html#lua_status\">lua_status</A><BR>\n<A HREF=\"manual.html#lua_toboolean\">lua_toboolean</A><BR>\n<A HREF=\"manual.html#lua_tocfunction\">lua_tocfunction</A><BR>\n<A HREF=\"manual.html#lua_tointeger\">lua_tointeger</A><BR>\n<A HREF=\"manual.html#lua_tolstring\">lua_tolstring</A><BR>\n<A HREF=\"manual.html#lua_tonumber\">lua_tonumber</A><BR>\n<A HREF=\"manual.html#lua_topointer\">lua_topointer</A><BR>\n<A HREF=\"manual.html#lua_tostring\">lua_tostring</A><BR>\n<A HREF=\"manual.html#lua_tothread\">lua_tothread</A><BR>\n<A HREF=\"manual.html#lua_touserdata\">lua_touserdata</A><BR>\n<A HREF=\"manual.html#lua_type\">lua_type</A><BR>\n<A HREF=\"manual.html#lua_typename\">lua_typename</A><BR>\n<A HREF=\"manual.html#lua_upvalueindex\">lua_upvalueindex</A><BR>\n<A HREF=\"manual.html#lua_xmove\">lua_xmove</A><BR>\n<A HREF=\"manual.html#lua_yield\">lua_yield</A><BR>\n\n</TD>\n<TD>\n<H3>auxiliary library</H3>\n<A HREF=\"manual.html#luaL_Buffer\">luaL_Buffer</A><BR>\n<A HREF=\"manual.html#luaL_Reg\">luaL_Reg</A><BR>\n<P>\n\n<A HREF=\"manual.html#luaL_addchar\">luaL_addchar</A><BR>\n<A HREF=\"manual.html#luaL_addlstring\">luaL_addlstring</A><BR>\n<A HREF=\"manual.html#luaL_addsize\">luaL_addsize</A><BR>\n<A HREF=\"manual.html#luaL_addstring\">luaL_addstring</A><BR>\n<A HREF=\"manual.html#luaL_addvalue\">luaL_addvalue</A><BR>\n<A HREF=\"manual.html#luaL_argcheck\">luaL_argcheck</A><BR>\n<A HREF=\"manual.html#luaL_argerror\">luaL_argerror</A><BR>\n<A HREF=\"manual.html#luaL_buffinit\">luaL_buffinit</A><BR>\n<A HREF=\"manual.html#luaL_callmeta\">luaL_callmeta</A><BR>\n<A HREF=\"manual.html#luaL_checkany\">luaL_checkany</A><BR>\n<A HREF=\"manual.html#luaL_checkint\">luaL_checkint</A><BR>\n<A HREF=\"manual.html#luaL_checkinteger\">luaL_checkinteger</A><BR>\n<A HREF=\"manual.html#luaL_checklong\">luaL_checklong</A><BR>\n<A HREF=\"manual.html#luaL_checklstring\">luaL_checklstring</A><BR>\n<A HREF=\"manual.html#luaL_checknumber\">luaL_checknumber</A><BR>\n<A HREF=\"manual.html#luaL_checkoption\">luaL_checkoption</A><BR>\n<A HREF=\"manual.html#luaL_checkstack\">luaL_checkstack</A><BR>\n<A HREF=\"manual.html#luaL_checkstring\">luaL_checkstring</A><BR>\n<A HREF=\"manual.html#luaL_checktype\">luaL_checktype</A><BR>\n<A HREF=\"manual.html#luaL_checkudata\">luaL_checkudata</A><BR>\n<A HREF=\"manual.html#luaL_dofile\">luaL_dofile</A><BR>\n<A HREF=\"manual.html#luaL_dostring\">luaL_dostring</A><BR>\n<A HREF=\"manual.html#luaL_error\">luaL_error</A><BR>\n<A HREF=\"manual.html#luaL_getmetafield\">luaL_getmetafield</A><BR>\n<A HREF=\"manual.html#luaL_getmetatable\">luaL_getmetatable</A><BR>\n<A HREF=\"manual.html#luaL_gsub\">luaL_gsub</A><BR>\n<A HREF=\"manual.html#luaL_loadbuffer\">luaL_loadbuffer</A><BR>\n<A HREF=\"manual.html#luaL_loadfile\">luaL_loadfile</A><BR>\n<A HREF=\"manual.html#luaL_loadstring\">luaL_loadstring</A><BR>\n<A HREF=\"manual.html#luaL_newmetatable\">luaL_newmetatable</A><BR>\n<A HREF=\"manual.html#luaL_newstate\">luaL_newstate</A><BR>\n<A HREF=\"manual.html#luaL_openlibs\">luaL_openlibs</A><BR>\n<A HREF=\"manual.html#luaL_optint\">luaL_optint</A><BR>\n<A HREF=\"manual.html#luaL_optinteger\">luaL_optinteger</A><BR>\n<A HREF=\"manual.html#luaL_optlong\">luaL_optlong</A><BR>\n<A HREF=\"manual.html#luaL_optlstring\">luaL_optlstring</A><BR>\n<A HREF=\"manual.html#luaL_optnumber\">luaL_optnumber</A><BR>\n<A HREF=\"manual.html#luaL_optstring\">luaL_optstring</A><BR>\n<A HREF=\"manual.html#luaL_prepbuffer\">luaL_prepbuffer</A><BR>\n<A HREF=\"manual.html#luaL_pushresult\">luaL_pushresult</A><BR>\n<A HREF=\"manual.html#luaL_ref\">luaL_ref</A><BR>\n<A HREF=\"manual.html#luaL_register\">luaL_register</A><BR>\n<A HREF=\"manual.html#luaL_typename\">luaL_typename</A><BR>\n<A HREF=\"manual.html#luaL_typerror\">luaL_typerror</A><BR>\n<A HREF=\"manual.html#luaL_unref\">luaL_unref</A><BR>\n<A HREF=\"manual.html#luaL_where\">luaL_where</A><BR>\n\n</TD>\n</TR>\n</TABLE>\n<P>\n\n<HR>\n<SMALL CLASS=\"footer\">\nLast update:\nMon Feb 13 18:53:32 BRST 2012\n</SMALL>\n<!--\nLast change: revised for Lua 5.1.5\n-->\n\n</BODY>\n</HTML>\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/deps/lua/doc/lua.1",
    "content": ".\\\" $Id: lua.man,v 1.11 2006/01/06 16:03:34 lhf Exp $\n.TH LUA 1 \"$Date: 2006/01/06 16:03:34 $\"\n.SH NAME\nlua \\- Lua interpreter\n.SH SYNOPSIS\n.B lua\n[\n.I options\n]\n[\n.I script\n[\n.I args\n]\n]\n.SH DESCRIPTION\n.B lua\nis the stand-alone Lua interpreter.\nIt loads and executes Lua programs,\neither in textual source form or\nin precompiled binary form.\n(Precompiled binaries are output by\n.BR luac ,\nthe Lua compiler.)\n.B lua\ncan be used as a batch interpreter and also interactively.\n.LP\nThe given\n.I options\n(see below)\nare executed and then\nthe Lua program in file\n.I script\nis loaded and executed.\nThe given\n.I args\nare available to\n.I script\nas strings in a global table named\n.BR arg .\nIf these arguments contain spaces or other characters special to the shell,\nthen they should be quoted\n(but note that the quotes will be removed by the shell).\nThe arguments in\n.B arg\nstart at 0,\nwhich contains the string\n.RI ' script '.\nThe index of the last argument is stored in\n.BR arg.n .\nThe arguments given in the command line before\n.IR script ,\nincluding the name of the interpreter,\nare available in negative indices in\n.BR arg .\n.LP\nAt the very start,\nbefore even handling the command line,\n.B lua\nexecutes the contents of the environment variable\n.BR LUA_INIT ,\nif it is defined.\nIf the value of\n.B LUA_INIT\nis of the form\n.RI '@ filename ',\nthen\n.I filename\nis executed.\nOtherwise, the string is assumed to be a Lua statement and is executed.\n.LP\nOptions start with\n.B '\\-'\nand are described below.\nYou can use\n.B \"'\\--'\"\nto signal the end of options.\n.LP\nIf no arguments are given,\nthen\n.B \"\\-v \\-i\"\nis assumed when the standard input is a terminal;\notherwise,\n.B \"\\-\"\nis assumed.\n.LP\nIn interactive mode,\n.B lua\nprompts the user,\nreads lines from the standard input,\nand executes them as they are read.\nIf a line does not contain a complete statement,\nthen a secondary prompt is displayed and\nlines are read until a complete statement is formed or\na syntax error is found.\nSo, one way to interrupt the reading of an incomplete statement is\nto force a syntax error:\nadding a\n.B ';' \nin the middle of a statement is a sure way of forcing a syntax error\n(except inside multiline strings and comments; these must be closed explicitly).\nIf a line starts with\n.BR '=' ,\nthen\n.B lua\ndisplays the values of all the expressions in the remainder of the\nline. The expressions must be separated by commas.\nThe primary prompt is the value of the global variable\n.BR _PROMPT ,\nif this value is a string;\notherwise, the default prompt is used.\nSimilarly, the secondary prompt is the value of the global variable\n.BR _PROMPT2 .\nSo,\nto change the prompts,\nset the corresponding variable to a string of your choice.\nYou can do that after calling the interpreter\nor on the command line\n(but in this case you have to be careful with quotes\nif the prompt string contains a space; otherwise you may confuse the shell.)\nThe default prompts are \"> \" and \">> \".\n.SH OPTIONS\n.TP\n.B \\-\nload and execute the standard input as a file,\nthat is,\nnot interactively,\neven when the standard input is a terminal.\n.TP\n.BI \\-e \" stat\"\nexecute statement\n.IR stat .\nYou need to quote\n.I stat \nif it contains spaces, quotes,\nor other characters special to the shell.\n.TP\n.B \\-i\nenter interactive mode after\n.I script\nis executed.\n.TP\n.BI \\-l \" name\"\ncall\n.BI require(' name ')\nbefore executing\n.IR script .\nTypically used to load libraries.\n.TP\n.B \\-v\nshow version information.\n.SH \"SEE ALSO\"\n.BR luac (1)\n.br\nhttp://www.lua.org/\n.SH DIAGNOSTICS\nError messages should be self explanatory.\n.SH AUTHORS\nR. Ierusalimschy,\nL. H. de Figueiredo,\nand\nW. Celes\n.\\\" EOF\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/deps/lua/doc/lua.css",
    "content": "body {\n\tcolor: #000000 ;\n\tbackground-color: #FFFFFF ;\n\tfont-family: Helvetica, Arial, sans-serif ;\n\ttext-align: justify ;\n\tmargin-right: 30px ;\n\tmargin-left: 30px ;\n}\n\nh1, h2, h3, h4 {\n\tfont-family: Verdana, Geneva, sans-serif ;\n\tfont-weight: normal ;\n\tfont-style: italic ;\n}\n\nh2 {\n\tpadding-top: 0.4em ;\n\tpadding-bottom: 0.4em ;\n\tpadding-left: 30px ;\n\tpadding-right: 30px ;\n\tmargin-left: -30px ;\n\tbackground-color: #E0E0FF ;\n}\n\nh3 {\n\tpadding-left: 0.5em ;\n\tborder-left: solid #E0E0FF 1em ;\n}\n\ntable h3 {\n\tpadding-left: 0px ;\n\tborder-left: none ;\n}\n\na:link {\n\tcolor: #000080 ;\n\tbackground-color: inherit ;\n\ttext-decoration: none ;\n}\n\na:visited {\n\tbackground-color: inherit ;\n\ttext-decoration: none ;\n}\n\na:link:hover, a:visited:hover {\n\tcolor: #000080 ;\n\tbackground-color: #E0E0FF ;\n}\n\na:link:active, a:visited:active {\n\tcolor: #FF0000 ;\n}\n\nhr {\n\tborder: 0 ;\n\theight: 1px ;\n\tcolor: #a0a0a0 ;\n\tbackground-color: #a0a0a0 ;\n}\n\n:target {\n\tbackground-color: #F8F8F8 ;\n\tpadding: 8px ;\n\tborder: solid #a0a0a0 2px ;\n}\n\n.footer {\n\tcolor: gray ;\n\tfont-size: small ;\n}\n\ninput[type=text] {\n\tborder: solid #a0a0a0 2px ;\n\tborder-radius: 2em ;\n\t-moz-border-radius: 2em ;\n\tbackground-image: url('images/search.png') ;\n\tbackground-repeat: no-repeat;\n\tbackground-position: 4px center ;\n\tpadding-left: 20px ;\n\theight: 2em ;\n}\n\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/deps/lua/doc/lua.html",
    "content": "<!-- $Id: lua.man,v 1.11 2006/01/06 16:03:34 lhf Exp $ -->\n<HTML>\n<HEAD>\n<TITLE>LUA man page</TITLE>\n<LINK REL=\"stylesheet\" TYPE=\"text/css\" HREF=\"lua.css\">\n</HEAD>\n\n<BODY BGCOLOR=\"#FFFFFF\">\n\n<H2>NAME</H2>\nlua - Lua interpreter\n<H2>SYNOPSIS</H2>\n<B>lua</B>\n[\n<I>options</I>\n]\n[\n<I>script</I>\n[\n<I>args</I>\n]\n]\n<H2>DESCRIPTION</H2>\n<B>lua</B>\nis the stand-alone Lua interpreter.\nIt loads and executes Lua programs,\neither in textual source form or\nin precompiled binary form.\n(Precompiled binaries are output by\n<B>luac</B>,\nthe Lua compiler.)\n<B>lua</B>\ncan be used as a batch interpreter and also interactively.\n<P>\nThe given\n<I>options</I>\n(see below)\nare executed and then\nthe Lua program in file\n<I>script</I>\nis loaded and executed.\nThe given\n<I>args</I>\nare available to\n<I>script</I>\nas strings in a global table named\n<B>arg</B>.\nIf these arguments contain spaces or other characters special to the shell,\nthen they should be quoted\n(but note that the quotes will be removed by the shell).\nThe arguments in\n<B>arg</B>\nstart at 0,\nwhich contains the string\n'<I>script</I>'.\nThe index of the last argument is stored in\n<B>arg.n</B>.\nThe arguments given in the command line before\n<I>script</I>,\nincluding the name of the interpreter,\nare available in negative indices in\n<B>arg</B>.\n<P>\nAt the very start,\nbefore even handling the command line,\n<B>lua</B>\nexecutes the contents of the environment variable\n<B>LUA_INIT</B>,\nif it is defined.\nIf the value of\n<B>LUA_INIT</B>\nis of the form\n'@<I>filename</I>',\nthen\n<I>filename</I>\nis executed.\nOtherwise, the string is assumed to be a Lua statement and is executed.\n<P>\nOptions start with\n<B>'-'</B>\nand are described below.\nYou can use\n<B>'--'</B>\nto signal the end of options.\n<P>\nIf no arguments are given,\nthen\n<B>\"-v -i\"</B>\nis assumed when the standard input is a terminal;\notherwise,\n<B>\"-\"</B>\nis assumed.\n<P>\nIn interactive mode,\n<B>lua</B>\nprompts the user,\nreads lines from the standard input,\nand executes them as they are read.\nIf a line does not contain a complete statement,\nthen a secondary prompt is displayed and\nlines are read until a complete statement is formed or\na syntax error is found.\nSo, one way to interrupt the reading of an incomplete statement is\nto force a syntax error:\nadding a\n<B>';'</B>\nin the middle of a statement is a sure way of forcing a syntax error\n(except inside multiline strings and comments; these must be closed explicitly).\nIf a line starts with\n<B>'='</B>,\nthen\n<B>lua</B>\ndisplays the values of all the expressions in the remainder of the\nline. The expressions must be separated by commas.\nThe primary prompt is the value of the global variable\n<B>_PROMPT</B>,\nif this value is a string;\notherwise, the default prompt is used.\nSimilarly, the secondary prompt is the value of the global variable\n<B>_PROMPT2</B>.\nSo,\nto change the prompts,\nset the corresponding variable to a string of your choice.\nYou can do that after calling the interpreter\nor on the command line\n(but in this case you have to be careful with quotes\nif the prompt string contains a space; otherwise you may confuse the shell.)\nThe default prompts are \"&gt; \" and \"&gt;&gt; \".\n<H2>OPTIONS</H2>\n<P>\n<B>-</B>\nload and execute the standard input as a file,\nthat is,\nnot interactively,\neven when the standard input is a terminal.\n<P>\n<B>-e </B><I>stat</I>\nexecute statement\n<I>stat</I>.\nYou need to quote\n<I>stat </I>\nif it contains spaces, quotes,\nor other characters special to the shell.\n<P>\n<B>-i</B>\nenter interactive mode after\n<I>script</I>\nis executed.\n<P>\n<B>-l </B><I>name</I>\ncall\n<B>require</B>('<I>name</I>')\nbefore executing\n<I>script</I>.\nTypically used to load libraries.\n<P>\n<B>-v</B>\nshow version information.\n<H2>SEE ALSO</H2>\n<B>luac</B>(1)\n<BR>\n<A HREF=\"http://www.lua.org/\">http://www.lua.org/</A>\n<H2>DIAGNOSTICS</H2>\nError messages should be self explanatory.\n<H2>AUTHORS</H2>\nR. Ierusalimschy,\nL. H. de Figueiredo,\nand\nW. Celes\n<!-- EOF -->\n</BODY>\n</HTML>\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/deps/lua/doc/luac.1",
    "content": ".\\\" $Id: luac.man,v 1.28 2006/01/06 16:03:34 lhf Exp $\n.TH LUAC 1 \"$Date: 2006/01/06 16:03:34 $\"\n.SH NAME\nluac \\- Lua compiler\n.SH SYNOPSIS\n.B luac\n[\n.I options\n] [\n.I filenames\n]\n.SH DESCRIPTION\n.B luac\nis the Lua compiler.\nIt translates programs written in the Lua programming language\ninto binary files that can be later loaded and executed.\n.LP\nThe main advantages of precompiling chunks are:\nfaster loading,\nprotecting source code from accidental user changes,\nand\noff-line syntax checking.\n.LP\nPre-compiling does not imply faster execution\nbecause in Lua chunks are always compiled into bytecodes before being executed.\n.B luac\nsimply allows those bytecodes to be saved in a file for later execution.\n.LP\nPre-compiled chunks are not necessarily smaller than the corresponding source.\nThe main goal in pre-compiling is faster loading.\n.LP\nThe binary files created by\n.B luac\nare portable only among architectures with the same word size and byte order.\n.LP\n.B luac\nproduces a single output file containing the bytecodes\nfor all source files given.\nBy default,\nthe output file is named\n.BR luac.out ,\nbut you can change this with the\n.B \\-o\noption.\n.LP\nIn the command line,\nyou can mix\ntext files containing Lua source and\nbinary files containing precompiled chunks.\nThis is useful to combine several precompiled chunks,\neven from different (but compatible) platforms,\ninto a single precompiled chunk.\n.LP\nYou can use\n.B \"'\\-'\"\nto indicate the standard input as a source file\nand\n.B \"'\\--'\"\nto signal the end of options\n(that is,\nall remaining arguments will be treated as files even if they start with\n.BR \"'\\-'\" ).\n.LP\nThe internal format of the binary files produced by\n.B luac\nis likely to change when a new version of Lua is released.\nSo,\nsave the source files of all Lua programs that you precompile.\n.LP\n.SH OPTIONS\nOptions must be separate.\n.TP\n.B \\-l\nproduce a listing of the compiled bytecode for Lua's virtual machine.\nListing bytecodes is useful to learn about Lua's virtual machine.\nIf no files are given, then\n.B luac\nloads\n.B luac.out\nand lists its contents.\n.TP\n.BI \\-o \" file\"\noutput to\n.IR file ,\ninstead of the default\n.BR luac.out .\n(You can use\n.B \"'\\-'\"\nfor standard output,\nbut not on platforms that open standard output in text mode.)\nThe output file may be a source file because\nall files are loaded before the output file is written.\nBe careful not to overwrite precious files.\n.TP\n.B \\-p\nload files but do not generate any output file.\nUsed mainly for syntax checking and for testing precompiled chunks:\ncorrupted files will probably generate errors when loaded.\nLua always performs a thorough integrity test on precompiled chunks.\nBytecode that passes this test is completely safe,\nin the sense that it will not break the interpreter.\nHowever,\nthere is no guarantee that such code does anything sensible.\n(None can be given, because the halting problem is unsolvable.)\nIf no files are given, then\n.B luac\nloads\n.B luac.out\nand tests its contents.\nNo messages are displayed if the file passes the integrity test.\n.TP\n.B \\-s\nstrip debug information before writing the output file.\nThis saves some space in very large chunks,\nbut if errors occur when running a stripped chunk,\nthen the error messages may not contain the full information they usually do.\nFor instance,\nline numbers and names of local variables are lost.\n.TP\n.B \\-v\nshow version information.\n.SH FILES\n.TP 15\n.B luac.out\ndefault output file\n.SH \"SEE ALSO\"\n.BR lua (1)\n.br\nhttp://www.lua.org/\n.SH DIAGNOSTICS\nError messages should be self explanatory.\n.SH AUTHORS\nL. H. de Figueiredo,\nR. Ierusalimschy and\nW. Celes\n.\\\" EOF\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/deps/lua/doc/luac.html",
    "content": "<!-- $Id: luac.man,v 1.28 2006/01/06 16:03:34 lhf Exp $ -->\n<HTML>\n<HEAD>\n<TITLE>LUAC man page</TITLE>\n<LINK REL=\"stylesheet\" TYPE=\"text/css\" HREF=\"lua.css\">\n</HEAD>\n\n<BODY BGCOLOR=\"#FFFFFF\">\n\n<H2>NAME</H2>\nluac - Lua compiler\n<H2>SYNOPSIS</H2>\n<B>luac</B>\n[\n<I>options</I>\n] [\n<I>filenames</I>\n]\n<H2>DESCRIPTION</H2>\n<B>luac</B>\nis the Lua compiler.\nIt translates programs written in the Lua programming language\ninto binary files that can be later loaded and executed.\n<P>\nThe main advantages of precompiling chunks are:\nfaster loading,\nprotecting source code from accidental user changes,\nand\noff-line syntax checking.\n<P>\nPrecompiling does not imply faster execution\nbecause in Lua chunks are always compiled into bytecodes before being executed.\n<B>luac</B>\nsimply allows those bytecodes to be saved in a file for later execution.\n<P>\nPrecompiled chunks are not necessarily smaller than the corresponding source.\nThe main goal in precompiling is faster loading.\n<P>\nThe binary files created by\n<B>luac</B>\nare portable only among architectures with the same word size and byte order.\n<P>\n<B>luac</B>\nproduces a single output file containing the bytecodes\nfor all source files given.\nBy default,\nthe output file is named\n<B>luac.out</B>,\nbut you can change this with the\n<B>-o</B>\noption.\n<P>\nIn the command line,\nyou can mix\ntext files containing Lua source and\nbinary files containing precompiled chunks.\nThis is useful because several precompiled chunks,\neven from different (but compatible) platforms,\ncan be combined into a single precompiled chunk.\n<P>\nYou can use\n<B>'-'</B>\nto indicate the standard input as a source file\nand\n<B>'--'</B>\nto signal the end of options\n(that is,\nall remaining arguments will be treated as files even if they start with\n<B>'-'</B>).\n<P>\nThe internal format of the binary files produced by\n<B>luac</B>\nis likely to change when a new version of Lua is released.\nSo,\nsave the source files of all Lua programs that you precompile.\n<P>\n<H2>OPTIONS</H2>\nOptions must be separate.\n<P>\n<B>-l</B>\nproduce a listing of the compiled bytecode for Lua's virtual machine.\nListing bytecodes is useful to learn about Lua's virtual machine.\nIf no files are given, then\n<B>luac</B>\nloads\n<B>luac.out</B>\nand lists its contents.\n<P>\n<B>-o </B><I>file</I>\noutput to\n<I>file</I>,\ninstead of the default\n<B>luac.out</B>.\n(You can use\n<B>'-'</B>\nfor standard output,\nbut not on platforms that open standard output in text mode.)\nThe output file may be a source file because\nall files are loaded before the output file is written.\nBe careful not to overwrite precious files.\n<P>\n<B>-p</B>\nload files but do not generate any output file.\nUsed mainly for syntax checking and for testing precompiled chunks:\ncorrupted files will probably generate errors when loaded.\nLua always performs a thorough integrity test on precompiled chunks.\nBytecode that passes this test is completely safe,\nin the sense that it will not break the interpreter.\nHowever,\nthere is no guarantee that such code does anything sensible.\n(None can be given, because the halting problem is unsolvable.)\nIf no files are given, then\n<B>luac</B>\nloads\n<B>luac.out</B>\nand tests its contents.\nNo messages are displayed if the file passes the integrity test.\n<P>\n<B>-s</B>\nstrip debug information before writing the output file.\nThis saves some space in very large chunks,\nbut if errors occur when running a stripped chunk,\nthen the error messages may not contain the full information they usually do.\nFor instance,\nline numbers and names of local variables are lost.\n<P>\n<B>-v</B>\nshow version information.\n<H2>FILES</H2>\n<P>\n<B>luac.out</B>\ndefault output file\n<H2>SEE ALSO</H2>\n<B>lua</B>(1)\n<BR>\n<A HREF=\"http://www.lua.org/\">http://www.lua.org/</A>\n<H2>DIAGNOSTICS</H2>\nError messages should be self explanatory.\n<H2>AUTHORS</H2>\nL. H. de Figueiredo,\nR. Ierusalimschy and\nW. Celes\n<!-- EOF -->\n</BODY>\n</HTML>\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/deps/lua/doc/manual.css",
    "content": "h3 code {\n\tfont-family: inherit ;\n\tfont-size: inherit ;\n}\n\npre, code {\n\tfont-size: 12pt ;\n}\n\nspan.apii {\n\tfloat: right ;\n\tfont-family: inherit ;\n\tfont-style: normal ;\n\tfont-size: small ;\n\tcolor: gray ;\n}\n\np+h1, ul+h1 {\n\tpadding-top: 0.4em ;\n\tpadding-bottom: 0.4em ;\n\tpadding-left: 30px ;\n\tmargin-left: -30px ;\n\tbackground-color: #E0E0FF ;\n}\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/deps/lua/doc/manual.html",
    "content": "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\">\n<html>\n\n<head>\n<title>Lua 5.1 Reference Manual</title>\n<link rel=\"stylesheet\" type=\"text/css\" href=\"lua.css\">\n<link rel=\"stylesheet\" type=\"text/css\" href=\"manual.css\">\n<META HTTP-EQUIV=\"content-type\" CONTENT=\"text/html; charset=iso-8859-1\">\n</head>\n\n<body>\n\n<hr>\n<h1>\n<a href=\"http://www.lua.org/\"><img src=\"logo.gif\" alt=\"\" border=\"0\"></a>\nLua 5.1 Reference Manual\n</h1>\n\nby Roberto Ierusalimschy, Luiz Henrique de Figueiredo, Waldemar Celes\n<p>\n<small>\nCopyright &copy; 2006&ndash;2012 Lua.org, PUC-Rio.\nFreely available under the terms of the\n<a href=\"http://www.lua.org/license.html\">Lua license</a>.\n</small>\n<hr>\n<p>\n\n<a href=\"contents.html#contents\">contents</A>\n&middot;\n<a href=\"contents.html#index\">index</A>\n&middot;\n<A HREF=\"http://www.lua.org/manual/\">other versions</A>\n\n<!-- ====================================================================== -->\n<p>\n\n<!-- $Id: manual.of,v 1.49.1.2 2012/01/13 20:23:26 roberto Exp $ -->\n\n\n\n\n<h1>1 - <a name=\"1\">Introduction</a></h1>\n\n<p>\nLua is an extension programming language designed to support\ngeneral procedural programming with data description\nfacilities.\nIt also offers good support for object-oriented programming,\nfunctional programming, and data-driven programming.\nLua is intended to be used as a powerful, light-weight\nscripting language for any program that needs one.\nLua is implemented as a library, written in <em>clean</em> C\n(that is, in the common subset of ANSI&nbsp;C and C++).\n\n\n<p>\nBeing an extension language, Lua has no notion of a \"main\" program:\nit only works <em>embedded</em> in a host client,\ncalled the <em>embedding program</em> or simply the <em>host</em>.\nThis host program can invoke functions to execute a piece of Lua code,\ncan write and read Lua variables,\nand can register C&nbsp;functions to be called by Lua code.\nThrough the use of C&nbsp;functions, Lua can be augmented to cope with\na wide range of different domains,\nthus creating customized programming languages sharing a syntactical framework.\nThe Lua distribution includes a sample host program called <code>lua</code>,\nwhich uses the Lua library to offer a complete, stand-alone Lua interpreter.\n\n\n<p>\nLua is free software,\nand is provided as usual with no guarantees,\nas stated in its license.\nThe implementation described in this manual is available\nat Lua's official web site, <code>www.lua.org</code>.\n\n\n<p>\nLike any other reference manual,\nthis document is dry in places.\nFor a discussion of the decisions behind the design of Lua,\nsee the technical papers available at Lua's web site.\nFor a detailed introduction to programming in Lua,\nsee Roberto's book, <em>Programming in Lua (Second Edition)</em>.\n\n\n\n<h1>2 - <a name=\"2\">The Language</a></h1>\n\n<p>\nThis section describes the lexis, the syntax, and the semantics of Lua.\nIn other words,\nthis section describes\nwhich tokens are valid,\nhow they can be combined,\nand what their combinations mean.\n\n\n<p>\nThe language constructs will be explained using the usual extended BNF notation,\nin which\n{<em>a</em>}&nbsp;means&nbsp;0 or more <em>a</em>'s, and\n[<em>a</em>]&nbsp;means an optional <em>a</em>.\nNon-terminals are shown like non-terminal,\nkeywords are shown like <b>kword</b>,\nand other terminal symbols are shown like `<b>=</b>&acute;.\nThe complete syntax of Lua can be found in <a href=\"#8\">&sect;8</a>\nat the end of this manual.\n\n\n\n<h2>2.1 - <a name=\"2.1\">Lexical Conventions</a></h2>\n\n<p>\n<em>Names</em>\n(also called <em>identifiers</em>)\nin Lua can be any string of letters,\ndigits, and underscores,\nnot beginning with a digit.\nThis coincides with the definition of names in most languages.\n(The definition of letter depends on the current locale:\nany character considered alphabetic by the current locale\ncan be used in an identifier.)\nIdentifiers are used to name variables and table fields.\n\n\n<p>\nThe following <em>keywords</em> are reserved\nand cannot be used as names:\n\n\n<pre>\n     and       break     do        else      elseif\n     end       false     for       function  if\n     in        local     nil       not       or\n     repeat    return    then      true      until     while\n</pre>\n\n<p>\nLua is a case-sensitive language:\n<code>and</code> is a reserved word, but <code>And</code> and <code>AND</code>\nare two different, valid names.\nAs a convention, names starting with an underscore followed by\nuppercase letters (such as <a href=\"#pdf-_VERSION\"><code>_VERSION</code></a>)\nare reserved for internal global variables used by Lua.\n\n\n<p>\nThe following strings denote other tokens:\n\n<pre>\n     +     -     *     /     %     ^     #\n     ==    ~=    &lt;=    &gt;=    &lt;     &gt;     =\n     (     )     {     }     [     ]\n     ;     :     ,     .     ..    ...\n</pre>\n\n<p>\n<em>Literal strings</em>\ncan be delimited by matching single or double quotes,\nand can contain the following C-like escape sequences:\n'<code>\\a</code>' (bell),\n'<code>\\b</code>' (backspace),\n'<code>\\f</code>' (form feed),\n'<code>\\n</code>' (newline),\n'<code>\\r</code>' (carriage return),\n'<code>\\t</code>' (horizontal tab),\n'<code>\\v</code>' (vertical tab),\n'<code>\\\\</code>' (backslash),\n'<code>\\\"</code>' (quotation mark [double quote]),\nand '<code>\\'</code>' (apostrophe [single quote]).\nMoreover, a backslash followed by a real newline\nresults in a newline in the string.\nA character in a string can also be specified by its numerical value\nusing the escape sequence <code>\\<em>ddd</em></code>,\nwhere <em>ddd</em> is a sequence of up to three decimal digits.\n(Note that if a numerical escape is to be followed by a digit,\nit must be expressed using exactly three digits.)\nStrings in Lua can contain any 8-bit value, including embedded zeros,\nwhich can be specified as '<code>\\0</code>'.\n\n\n<p>\nLiteral strings can also be defined using a long format\nenclosed by <em>long brackets</em>.\nWe define an <em>opening long bracket of level <em>n</em></em> as an opening\nsquare bracket followed by <em>n</em> equal signs followed by another\nopening square bracket.\nSo, an opening long bracket of level&nbsp;0 is written as <code>[[</code>,\nan opening long bracket of level&nbsp;1 is written as <code>[=[</code>,\nand so on.\nA <em>closing long bracket</em> is defined similarly;\nfor instance, a closing long bracket of level&nbsp;4 is written as <code>]====]</code>.\nA long string starts with an opening long bracket of any level and\nends at the first closing long bracket of the same level.\nLiterals in this bracketed form can run for several lines,\ndo not interpret any escape sequences,\nand ignore long brackets of any other level.\nThey can contain anything except a closing bracket of the proper level.\n\n\n<p>\nFor convenience,\nwhen the opening long bracket is immediately followed by a newline,\nthe newline is not included in the string.\nAs an example, in a system using ASCII\n(in which '<code>a</code>' is coded as&nbsp;97,\nnewline is coded as&nbsp;10, and '<code>1</code>' is coded as&nbsp;49),\nthe five literal strings below denote the same string:\n\n<pre>\n     a = 'alo\\n123\"'\n     a = \"alo\\n123\\\"\"\n     a = '\\97lo\\10\\04923\"'\n     a = [[alo\n     123\"]]\n     a = [==[\n     alo\n     123\"]==]\n</pre>\n\n<p>\nA <em>numerical constant</em> can be written with an optional decimal part\nand an optional decimal exponent.\nLua also accepts integer hexadecimal constants,\nby prefixing them with <code>0x</code>.\nExamples of valid numerical constants are\n\n<pre>\n     3   3.0   3.1416   314.16e-2   0.31416E1   0xff   0x56\n</pre>\n\n<p>\nA <em>comment</em> starts with a double hyphen (<code>--</code>)\nanywhere outside a string.\nIf the text immediately after <code>--</code> is not an opening long bracket,\nthe comment is a <em>short comment</em>,\nwhich runs until the end of the line.\nOtherwise, it is a <em>long comment</em>,\nwhich runs until the corresponding closing long bracket.\nLong comments are frequently used to disable code temporarily.\n\n\n\n\n\n<h2>2.2 - <a name=\"2.2\">Values and Types</a></h2>\n\n<p>\nLua is a <em>dynamically typed language</em>.\nThis means that\nvariables do not have types; only values do.\nThere are no type definitions in the language.\nAll values carry their own type.\n\n\n<p>\nAll values in Lua are <em>first-class values</em>.\nThis means that all values can be stored in variables,\npassed as arguments to other functions, and returned as results.\n\n\n<p>\nThere are eight basic types in Lua:\n<em>nil</em>, <em>boolean</em>, <em>number</em>,\n<em>string</em>, <em>function</em>, <em>userdata</em>,\n<em>thread</em>, and <em>table</em>.\n<em>Nil</em> is the type of the value <b>nil</b>,\nwhose main property is to be different from any other value;\nit usually represents the absence of a useful value.\n<em>Boolean</em> is the type of the values <b>false</b> and <b>true</b>.\nBoth <b>nil</b> and <b>false</b> make a condition false;\nany other value makes it true.\n<em>Number</em> represents real (double-precision floating-point) numbers.\n(It is easy to build Lua interpreters that use other\ninternal representations for numbers,\nsuch as single-precision float or long integers;\nsee file <code>luaconf.h</code>.)\n<em>String</em> represents arrays of characters.\n\nLua is 8-bit clean:\nstrings can contain any 8-bit character,\nincluding embedded zeros ('<code>\\0</code>') (see <a href=\"#2.1\">&sect;2.1</a>).\n\n\n<p>\nLua can call (and manipulate) functions written in Lua and\nfunctions written in C\n(see <a href=\"#2.5.8\">&sect;2.5.8</a>).\n\n\n<p>\nThe type <em>userdata</em> is provided to allow arbitrary C&nbsp;data to\nbe stored in Lua variables.\nThis type corresponds to a block of raw memory\nand has no pre-defined operations in Lua,\nexcept assignment and identity test.\nHowever, by using <em>metatables</em>,\nthe programmer can define operations for userdata values\n(see <a href=\"#2.8\">&sect;2.8</a>).\nUserdata values cannot be created or modified in Lua,\nonly through the C&nbsp;API.\nThis guarantees the integrity of data owned by the host program.\n\n\n<p>\nThe type <em>thread</em> represents independent threads of execution\nand it is used to implement coroutines (see <a href=\"#2.11\">&sect;2.11</a>).\nDo not confuse Lua threads with operating-system threads.\nLua supports coroutines on all systems,\neven those that do not support threads.\n\n\n<p>\nThe type <em>table</em> implements associative arrays,\nthat is, arrays that can be indexed not only with numbers,\nbut with any value (except <b>nil</b>).\nTables can be <em>heterogeneous</em>;\nthat is, they can contain values of all types (except <b>nil</b>).\nTables are the sole data structuring mechanism in Lua;\nthey can be used to represent ordinary arrays,\nsymbol tables, sets, records, graphs, trees, etc.\nTo represent records, Lua uses the field name as an index.\nThe language supports this representation by\nproviding <code>a.name</code> as syntactic sugar for <code>a[\"name\"]</code>.\nThere are several convenient ways to create tables in Lua\n(see <a href=\"#2.5.7\">&sect;2.5.7</a>).\n\n\n<p>\nLike indices,\nthe value of a table field can be of any type (except <b>nil</b>).\nIn particular,\nbecause functions are first-class values,\ntable fields can contain functions.\nThus tables can also carry <em>methods</em> (see <a href=\"#2.5.9\">&sect;2.5.9</a>).\n\n\n<p>\nTables, functions, threads, and (full) userdata values are <em>objects</em>:\nvariables do not actually <em>contain</em> these values,\nonly <em>references</em> to them.\nAssignment, parameter passing, and function returns\nalways manipulate references to such values;\nthese operations do not imply any kind of copy.\n\n\n<p>\nThe library function <a href=\"#pdf-type\"><code>type</code></a> returns a string describing the type\nof a given value.\n\n\n\n<h3>2.2.1 - <a name=\"2.2.1\">Coercion</a></h3>\n\n<p>\nLua provides automatic conversion between\nstring and number values at run time.\nAny arithmetic operation applied to a string tries to convert\nthis string to a number, following the usual conversion rules.\nConversely, whenever a number is used where a string is expected,\nthe number is converted to a string, in a reasonable format.\nFor complete control over how numbers are converted to strings,\nuse the <code>format</code> function from the string library\n(see <a href=\"#pdf-string.format\"><code>string.format</code></a>).\n\n\n\n\n\n\n\n<h2>2.3 - <a name=\"2.3\">Variables</a></h2>\n\n<p>\nVariables are places that store values.\n\nThere are three kinds of variables in Lua:\nglobal variables, local variables, and table fields.\n\n\n<p>\nA single name can denote a global variable or a local variable\n(or a function's formal parameter,\nwhich is a particular kind of local variable):\n\n<pre>\n\tvar ::= Name\n</pre><p>\nName denotes identifiers, as defined in <a href=\"#2.1\">&sect;2.1</a>.\n\n\n<p>\nAny variable is assumed to be global unless explicitly declared\nas a local (see <a href=\"#2.4.7\">&sect;2.4.7</a>).\nLocal variables are <em>lexically scoped</em>:\nlocal variables can be freely accessed by functions\ndefined inside their scope (see <a href=\"#2.6\">&sect;2.6</a>).\n\n\n<p>\nBefore the first assignment to a variable, its value is <b>nil</b>.\n\n\n<p>\nSquare brackets are used to index a table:\n\n<pre>\n\tvar ::= prefixexp `<b>[</b>&acute; exp `<b>]</b>&acute;\n</pre><p>\nThe meaning of accesses to global variables \nand table fields can be changed via metatables.\nAn access to an indexed variable <code>t[i]</code> is equivalent to\na call <code>gettable_event(t,i)</code>.\n(See <a href=\"#2.8\">&sect;2.8</a> for a complete description of the\n<code>gettable_event</code> function.\nThis function is not defined or callable in Lua.\nWe use it here only for explanatory purposes.)\n\n\n<p>\nThe syntax <code>var.Name</code> is just syntactic sugar for\n<code>var[\"Name\"]</code>:\n\n<pre>\n\tvar ::= prefixexp `<b>.</b>&acute; Name\n</pre>\n\n<p>\nAll global variables live as fields in ordinary Lua tables,\ncalled <em>environment tables</em> or simply\n<em>environments</em> (see <a href=\"#2.9\">&sect;2.9</a>).\nEach function has its own reference to an environment,\nso that all global variables in this function\nwill refer to this environment table.\nWhen a function is created,\nit inherits the environment from the function that created it.\nTo get the environment table of a Lua function,\nyou call <a href=\"#pdf-getfenv\"><code>getfenv</code></a>.\nTo replace it,\nyou call <a href=\"#pdf-setfenv\"><code>setfenv</code></a>.\n(You can only manipulate the environment of C&nbsp;functions\nthrough the debug library; (see <a href=\"#5.9\">&sect;5.9</a>).)\n\n\n<p>\nAn access to a global variable <code>x</code>\nis equivalent to <code>_env.x</code>,\nwhich in turn is equivalent to\n\n<pre>\n     gettable_event(_env, \"x\")\n</pre><p>\nwhere <code>_env</code> is the environment of the running function.\n(See <a href=\"#2.8\">&sect;2.8</a> for a complete description of the\n<code>gettable_event</code> function.\nThis function is not defined or callable in Lua.\nSimilarly, the <code>_env</code> variable is not defined in Lua.\nWe use them here only for explanatory purposes.)\n\n\n\n\n\n<h2>2.4 - <a name=\"2.4\">Statements</a></h2>\n\n<p>\nLua supports an almost conventional set of statements,\nsimilar to those in Pascal or C.\nThis set includes\nassignments, control structures, function calls,\nand variable declarations.\n\n\n\n<h3>2.4.1 - <a name=\"2.4.1\">Chunks</a></h3>\n\n<p>\nThe unit of execution of Lua is called a <em>chunk</em>.\nA chunk is simply a sequence of statements,\nwhich are executed sequentially.\nEach statement can be optionally followed by a semicolon:\n\n<pre>\n\tchunk ::= {stat [`<b>;</b>&acute;]}\n</pre><p>\nThere are no empty statements and thus '<code>;;</code>' is not legal.\n\n\n<p>\nLua handles a chunk as the body of an anonymous function \nwith a variable number of arguments\n(see <a href=\"#2.5.9\">&sect;2.5.9</a>).\nAs such, chunks can define local variables,\nreceive arguments, and return values.\n\n\n<p>\nA chunk can be stored in a file or in a string inside the host program.\nTo execute a chunk,\nLua first pre-compiles the chunk into instructions for a virtual machine,\nand then it executes the compiled code\nwith an interpreter for the virtual machine.\n\n\n<p>\nChunks can also be pre-compiled into binary form;\nsee program <code>luac</code> for details.\nPrograms in source and compiled forms are interchangeable;\nLua automatically detects the file type and acts accordingly.\n\n\n\n\n\n\n<h3>2.4.2 - <a name=\"2.4.2\">Blocks</a></h3><p>\nA block is a list of statements;\nsyntactically, a block is the same as a chunk:\n\n<pre>\n\tblock ::= chunk\n</pre>\n\n<p>\nA block can be explicitly delimited to produce a single statement:\n\n<pre>\n\tstat ::= <b>do</b> block <b>end</b>\n</pre><p>\nExplicit blocks are useful\nto control the scope of variable declarations.\nExplicit blocks are also sometimes used to\nadd a <b>return</b> or <b>break</b> statement in the middle\nof another block (see <a href=\"#2.4.4\">&sect;2.4.4</a>).\n\n\n\n\n\n<h3>2.4.3 - <a name=\"2.4.3\">Assignment</a></h3>\n\n<p>\nLua allows multiple assignments.\nTherefore, the syntax for assignment\ndefines a list of variables on the left side\nand a list of expressions on the right side.\nThe elements in both lists are separated by commas:\n\n<pre>\n\tstat ::= varlist `<b>=</b>&acute; explist\n\tvarlist ::= var {`<b>,</b>&acute; var}\n\texplist ::= exp {`<b>,</b>&acute; exp}\n</pre><p>\nExpressions are discussed in <a href=\"#2.5\">&sect;2.5</a>.\n\n\n<p>\nBefore the assignment,\nthe list of values is <em>adjusted</em> to the length of\nthe list of variables.\nIf there are more values than needed,\nthe excess values are thrown away.\nIf there are fewer values than needed,\nthe list is extended with as many  <b>nil</b>'s as needed.\nIf the list of expressions ends with a function call,\nthen all values returned by that call enter the list of values,\nbefore the adjustment\n(except when the call is enclosed in parentheses; see <a href=\"#2.5\">&sect;2.5</a>).\n\n\n<p>\nThe assignment statement first evaluates all its expressions\nand only then are the assignments performed.\nThus the code\n\n<pre>\n     i = 3\n     i, a[i] = i+1, 20\n</pre><p>\nsets <code>a[3]</code> to 20, without affecting <code>a[4]</code>\nbecause the <code>i</code> in <code>a[i]</code> is evaluated (to 3)\nbefore it is assigned&nbsp;4.\nSimilarly, the line\n\n<pre>\n     x, y = y, x\n</pre><p>\nexchanges the values of <code>x</code> and <code>y</code>,\nand\n\n<pre>\n     x, y, z = y, z, x\n</pre><p>\ncyclically permutes the values of <code>x</code>, <code>y</code>, and <code>z</code>.\n\n\n<p>\nThe meaning of assignments to global variables\nand table fields can be changed via metatables.\nAn assignment to an indexed variable <code>t[i] = val</code> is equivalent to\n<code>settable_event(t,i,val)</code>.\n(See <a href=\"#2.8\">&sect;2.8</a> for a complete description of the\n<code>settable_event</code> function.\nThis function is not defined or callable in Lua.\nWe use it here only for explanatory purposes.)\n\n\n<p>\nAn assignment to a global variable <code>x = val</code>\nis equivalent to the assignment\n<code>_env.x = val</code>,\nwhich in turn is equivalent to\n\n<pre>\n     settable_event(_env, \"x\", val)\n</pre><p>\nwhere <code>_env</code> is the environment of the running function.\n(The <code>_env</code> variable is not defined in Lua.\nWe use it here only for explanatory purposes.)\n\n\n\n\n\n<h3>2.4.4 - <a name=\"2.4.4\">Control Structures</a></h3><p>\nThe control structures\n<b>if</b>, <b>while</b>, and <b>repeat</b> have the usual meaning and\nfamiliar syntax:\n\n\n\n\n<pre>\n\tstat ::= <b>while</b> exp <b>do</b> block <b>end</b>\n\tstat ::= <b>repeat</b> block <b>until</b> exp\n\tstat ::= <b>if</b> exp <b>then</b> block {<b>elseif</b> exp <b>then</b> block} [<b>else</b> block] <b>end</b>\n</pre><p>\nLua also has a <b>for</b> statement, in two flavors (see <a href=\"#2.4.5\">&sect;2.4.5</a>).\n\n\n<p>\nThe condition expression of a\ncontrol structure can return any value.\nBoth <b>false</b> and <b>nil</b> are considered false.\nAll values different from <b>nil</b> and <b>false</b> are considered true\n(in particular, the number 0 and the empty string are also true).\n\n\n<p>\nIn the <b>repeat</b>&ndash;<b>until</b> loop,\nthe inner block does not end at the <b>until</b> keyword,\nbut only after the condition.\nSo, the condition can refer to local variables\ndeclared inside the loop block.\n\n\n<p>\nThe <b>return</b> statement is used to return values\nfrom a function or a chunk (which is just a function).\n\nFunctions and chunks can return more than one value,\nand so the syntax for the <b>return</b> statement is\n\n<pre>\n\tstat ::= <b>return</b> [explist]\n</pre>\n\n<p>\nThe <b>break</b> statement is used to terminate the execution of a\n<b>while</b>, <b>repeat</b>, or <b>for</b> loop,\nskipping to the next statement after the loop:\n\n\n<pre>\n\tstat ::= <b>break</b>\n</pre><p>\nA <b>break</b> ends the innermost enclosing loop.\n\n\n<p>\nThe <b>return</b> and <b>break</b>\nstatements can only be written as the <em>last</em> statement of a block.\nIf it is really necessary to <b>return</b> or <b>break</b> in the\nmiddle of a block,\nthen an explicit inner block can be used,\nas in the idioms\n<code>do return end</code> and <code>do break end</code>,\nbecause now <b>return</b> and <b>break</b> are the last statements in\ntheir (inner) blocks.\n\n\n\n\n\n<h3>2.4.5 - <a name=\"2.4.5\">For Statement</a></h3>\n\n<p>\n\nThe <b>for</b> statement has two forms:\none numeric and one generic.\n\n\n<p>\nThe numeric <b>for</b> loop repeats a block of code while a\ncontrol variable runs through an arithmetic progression.\nIt has the following syntax:\n\n<pre>\n\tstat ::= <b>for</b> Name `<b>=</b>&acute; exp `<b>,</b>&acute; exp [`<b>,</b>&acute; exp] <b>do</b> block <b>end</b>\n</pre><p>\nThe <em>block</em> is repeated for <em>name</em> starting at the value of\nthe first <em>exp</em>, until it passes the second <em>exp</em> by steps of the\nthird <em>exp</em>.\nMore precisely, a <b>for</b> statement like\n\n<pre>\n     for v = <em>e1</em>, <em>e2</em>, <em>e3</em> do <em>block</em> end\n</pre><p>\nis equivalent to the code:\n\n<pre>\n     do\n       local <em>var</em>, <em>limit</em>, <em>step</em> = tonumber(<em>e1</em>), tonumber(<em>e2</em>), tonumber(<em>e3</em>)\n       if not (<em>var</em> and <em>limit</em> and <em>step</em>) then error() end\n       while (<em>step</em> &gt; 0 and <em>var</em> &lt;= <em>limit</em>) or (<em>step</em> &lt;= 0 and <em>var</em> &gt;= <em>limit</em>) do\n         local v = <em>var</em>\n         <em>block</em>\n         <em>var</em> = <em>var</em> + <em>step</em>\n       end\n     end\n</pre><p>\nNote the following:\n\n<ul>\n\n<li>\nAll three control expressions are evaluated only once,\nbefore the loop starts.\nThey must all result in numbers.\n</li>\n\n<li>\n<code><em>var</em></code>, <code><em>limit</em></code>, and <code><em>step</em></code> are invisible variables.\nThe names shown here are for explanatory purposes only.\n</li>\n\n<li>\nIf the third expression (the step) is absent,\nthen a step of&nbsp;1 is used.\n</li>\n\n<li>\nYou can use <b>break</b> to exit a <b>for</b> loop.\n</li>\n\n<li>\nThe loop variable <code>v</code> is local to the loop;\nyou cannot use its value after the <b>for</b> ends or is broken.\nIf you need this value,\nassign it to another variable before breaking or exiting the loop.\n</li>\n\n</ul>\n\n<p>\nThe generic <b>for</b> statement works over functions,\ncalled <em>iterators</em>.\nOn each iteration, the iterator function is called to produce a new value,\nstopping when this new value is <b>nil</b>.\nThe generic <b>for</b> loop has the following syntax:\n\n<pre>\n\tstat ::= <b>for</b> namelist <b>in</b> explist <b>do</b> block <b>end</b>\n\tnamelist ::= Name {`<b>,</b>&acute; Name}\n</pre><p>\nA <b>for</b> statement like\n\n<pre>\n     for <em>var_1</em>, &middot;&middot;&middot;, <em>var_n</em> in <em>explist</em> do <em>block</em> end\n</pre><p>\nis equivalent to the code:\n\n<pre>\n     do\n       local <em>f</em>, <em>s</em>, <em>var</em> = <em>explist</em>\n       while true do\n         local <em>var_1</em>, &middot;&middot;&middot;, <em>var_n</em> = <em>f</em>(<em>s</em>, <em>var</em>)\n         <em>var</em> = <em>var_1</em>\n         if <em>var</em> == nil then break end\n         <em>block</em>\n       end\n     end\n</pre><p>\nNote the following:\n\n<ul>\n\n<li>\n<code><em>explist</em></code> is evaluated only once.\nIts results are an <em>iterator</em> function,\na <em>state</em>,\nand an initial value for the first <em>iterator variable</em>.\n</li>\n\n<li>\n<code><em>f</em></code>, <code><em>s</em></code>, and <code><em>var</em></code> are invisible variables.\nThe names are here for explanatory purposes only.\n</li>\n\n<li>\nYou can use <b>break</b> to exit a <b>for</b> loop.\n</li>\n\n<li>\nThe loop variables <code><em>var_i</em></code> are local to the loop;\nyou cannot use their values after the <b>for</b> ends.\nIf you need these values,\nthen assign them to other variables before breaking or exiting the loop.\n</li>\n\n</ul>\n\n\n\n\n<h3>2.4.6 - <a name=\"2.4.6\">Function Calls as Statements</a></h3><p>\nTo allow possible side-effects,\nfunction calls can be executed as statements:\n\n<pre>\n\tstat ::= functioncall\n</pre><p>\nIn this case, all returned values are thrown away.\nFunction calls are explained in <a href=\"#2.5.8\">&sect;2.5.8</a>.\n\n\n\n\n\n<h3>2.4.7 - <a name=\"2.4.7\">Local Declarations</a></h3><p>\nLocal variables can be declared anywhere inside a block.\nThe declaration can include an initial assignment:\n\n<pre>\n\tstat ::= <b>local</b> namelist [`<b>=</b>&acute; explist]\n</pre><p>\nIf present, an initial assignment has the same semantics\nof a multiple assignment (see <a href=\"#2.4.3\">&sect;2.4.3</a>).\nOtherwise, all variables are initialized with <b>nil</b>.\n\n\n<p>\nA chunk is also a block (see <a href=\"#2.4.1\">&sect;2.4.1</a>),\nand so local variables can be declared in a chunk outside any explicit block.\nThe scope of such local variables extends until the end of the chunk.\n\n\n<p>\nThe visibility rules for local variables are explained in <a href=\"#2.6\">&sect;2.6</a>.\n\n\n\n\n\n\n\n<h2>2.5 - <a name=\"2.5\">Expressions</a></h2>\n\n<p>\nThe basic expressions in Lua are the following:\n\n<pre>\n\texp ::= prefixexp\n\texp ::= <b>nil</b> | <b>false</b> | <b>true</b>\n\texp ::= Number\n\texp ::= String\n\texp ::= function\n\texp ::= tableconstructor\n\texp ::= `<b>...</b>&acute;\n\texp ::= exp binop exp\n\texp ::= unop exp\n\tprefixexp ::= var | functioncall | `<b>(</b>&acute; exp `<b>)</b>&acute;\n</pre>\n\n<p>\nNumbers and literal strings are explained in <a href=\"#2.1\">&sect;2.1</a>;\nvariables are explained in <a href=\"#2.3\">&sect;2.3</a>;\nfunction definitions are explained in <a href=\"#2.5.9\">&sect;2.5.9</a>;\nfunction calls are explained in <a href=\"#2.5.8\">&sect;2.5.8</a>;\ntable constructors are explained in <a href=\"#2.5.7\">&sect;2.5.7</a>.\nVararg expressions,\ndenoted by three dots ('<code>...</code>'), can only be used when\ndirectly inside a vararg function;\nthey are explained in <a href=\"#2.5.9\">&sect;2.5.9</a>.\n\n\n<p>\nBinary operators comprise arithmetic operators (see <a href=\"#2.5.1\">&sect;2.5.1</a>),\nrelational operators (see <a href=\"#2.5.2\">&sect;2.5.2</a>), logical operators (see <a href=\"#2.5.3\">&sect;2.5.3</a>),\nand the concatenation operator (see <a href=\"#2.5.4\">&sect;2.5.4</a>).\nUnary operators comprise the unary minus (see <a href=\"#2.5.1\">&sect;2.5.1</a>),\nthe unary <b>not</b> (see <a href=\"#2.5.3\">&sect;2.5.3</a>),\nand the unary <em>length operator</em> (see <a href=\"#2.5.5\">&sect;2.5.5</a>).\n\n\n<p>\nBoth function calls and vararg expressions can result in multiple values.\nIf an expression is used as a statement\n(only possible for function calls (see <a href=\"#2.4.6\">&sect;2.4.6</a>)),\nthen its return list is adjusted to zero elements,\nthus discarding all returned values.\nIf an expression is used as the last (or the only) element\nof a list of expressions,\nthen no adjustment is made\n(unless the call is enclosed in parentheses).\nIn all other contexts,\nLua adjusts the result list to one element,\ndiscarding all values except the first one.\n\n\n<p>\nHere are some examples:\n\n<pre>\n     f()                -- adjusted to 0 results\n     g(f(), x)          -- f() is adjusted to 1 result\n     g(x, f())          -- g gets x plus all results from f()\n     a,b,c = f(), x     -- f() is adjusted to 1 result (c gets nil)\n     a,b = ...          -- a gets the first vararg parameter, b gets\n                        -- the second (both a and b can get nil if there\n                        -- is no corresponding vararg parameter)\n     \n     a,b,c = x, f()     -- f() is adjusted to 2 results\n     a,b,c = f()        -- f() is adjusted to 3 results\n     return f()         -- returns all results from f()\n     return ...         -- returns all received vararg parameters\n     return x,y,f()     -- returns x, y, and all results from f()\n     {f()}              -- creates a list with all results from f()\n     {...}              -- creates a list with all vararg parameters\n     {f(), nil}         -- f() is adjusted to 1 result\n</pre>\n\n<p>\nAny expression enclosed in parentheses always results in only one value.\nThus,\n<code>(f(x,y,z))</code> is always a single value,\neven if <code>f</code> returns several values.\n(The value of <code>(f(x,y,z))</code> is the first value returned by <code>f</code>\nor <b>nil</b> if <code>f</code> does not return any values.)\n\n\n\n<h3>2.5.1 - <a name=\"2.5.1\">Arithmetic Operators</a></h3><p>\nLua supports the usual arithmetic operators:\nthe binary <code>+</code> (addition),\n<code>-</code> (subtraction), <code>*</code> (multiplication),\n<code>/</code> (division), <code>%</code> (modulo), and <code>^</code> (exponentiation);\nand unary <code>-</code> (negation).\nIf the operands are numbers, or strings that can be converted to\nnumbers (see <a href=\"#2.2.1\">&sect;2.2.1</a>),\nthen all operations have the usual meaning.\nExponentiation works for any exponent.\nFor instance, <code>x^(-0.5)</code> computes the inverse of the square root of <code>x</code>.\nModulo is defined as\n\n<pre>\n     a % b == a - math.floor(a/b)*b\n</pre><p>\nThat is, it is the remainder of a division that rounds\nthe quotient towards minus infinity.\n\n\n\n\n\n<h3>2.5.2 - <a name=\"2.5.2\">Relational Operators</a></h3><p>\nThe relational operators in Lua are\n\n<pre>\n     ==    ~=    &lt;     &gt;     &lt;=    &gt;=\n</pre><p>\nThese operators always result in <b>false</b> or <b>true</b>.\n\n\n<p>\nEquality (<code>==</code>) first compares the type of its operands.\nIf the types are different, then the result is <b>false</b>.\nOtherwise, the values of the operands are compared.\nNumbers and strings are compared in the usual way.\nObjects (tables, userdata, threads, and functions)\nare compared by <em>reference</em>:\ntwo objects are considered equal only if they are the <em>same</em> object.\nEvery time you create a new object\n(a table, userdata, thread, or function),\nthis new object is different from any previously existing object.\n\n\n<p>\nYou can change the way that Lua compares tables and userdata \nby using the \"eq\" metamethod (see <a href=\"#2.8\">&sect;2.8</a>).\n\n\n<p>\nThe conversion rules of <a href=\"#2.2.1\">&sect;2.2.1</a>\n<em>do not</em> apply to equality comparisons.\nThus, <code>\"0\"==0</code> evaluates to <b>false</b>,\nand <code>t[0]</code> and <code>t[\"0\"]</code> denote different\nentries in a table.\n\n\n<p>\nThe operator <code>~=</code> is exactly the negation of equality (<code>==</code>).\n\n\n<p>\nThe order operators work as follows.\nIf both arguments are numbers, then they are compared as such.\nOtherwise, if both arguments are strings,\nthen their values are compared according to the current locale.\nOtherwise, Lua tries to call the \"lt\" or the \"le\"\nmetamethod (see <a href=\"#2.8\">&sect;2.8</a>).\nA comparison <code>a &gt; b</code> is translated to <code>b &lt; a</code>\nand <code>a &gt;= b</code> is translated to <code>b &lt;= a</code>.\n\n\n\n\n\n<h3>2.5.3 - <a name=\"2.5.3\">Logical Operators</a></h3><p>\nThe logical operators in Lua are\n<b>and</b>, <b>or</b>, and <b>not</b>.\nLike the control structures (see <a href=\"#2.4.4\">&sect;2.4.4</a>),\nall logical operators consider both <b>false</b> and <b>nil</b> as false\nand anything else as true.\n\n\n<p>\nThe negation operator <b>not</b> always returns <b>false</b> or <b>true</b>.\nThe conjunction operator <b>and</b> returns its first argument\nif this value is <b>false</b> or <b>nil</b>;\notherwise, <b>and</b> returns its second argument.\nThe disjunction operator <b>or</b> returns its first argument\nif this value is different from <b>nil</b> and <b>false</b>;\notherwise, <b>or</b> returns its second argument.\nBoth <b>and</b> and <b>or</b> use short-cut evaluation;\nthat is,\nthe second operand is evaluated only if necessary.\nHere are some examples:\n\n<pre>\n     10 or 20            --&gt; 10\n     10 or error()       --&gt; 10\n     nil or \"a\"          --&gt; \"a\"\n     nil and 10          --&gt; nil\n     false and error()   --&gt; false\n     false and nil       --&gt; false\n     false or nil        --&gt; nil\n     10 and 20           --&gt; 20\n</pre><p>\n(In this manual,\n<code>--&gt;</code> indicates the result of the preceding expression.)\n\n\n\n\n\n<h3>2.5.4 - <a name=\"2.5.4\">Concatenation</a></h3><p>\nThe string concatenation operator in Lua is\ndenoted by two dots ('<code>..</code>').\nIf both operands are strings or numbers, then they are converted to\nstrings according to the rules mentioned in <a href=\"#2.2.1\">&sect;2.2.1</a>.\nOtherwise, the \"concat\" metamethod is called (see <a href=\"#2.8\">&sect;2.8</a>).\n\n\n\n\n\n<h3>2.5.5 - <a name=\"2.5.5\">The Length Operator</a></h3>\n\n<p>\nThe length operator is denoted by the unary operator <code>#</code>.\nThe length of a string is its number of bytes\n(that is, the usual meaning of string length when each\ncharacter is one byte).\n\n\n<p>\nThe length of a table <code>t</code> is defined to be any\ninteger index <code>n</code>\nsuch that <code>t[n]</code> is not <b>nil</b> and <code>t[n+1]</code> is <b>nil</b>;\nmoreover, if <code>t[1]</code> is <b>nil</b>, <code>n</code> can be zero.\nFor a regular array, with non-nil values from 1 to a given <code>n</code>,\nits length is exactly that <code>n</code>,\nthe index of its last value.\nIf the array has \"holes\"\n(that is, <b>nil</b> values between other non-nil values),\nthen <code>#t</code> can be any of the indices that\ndirectly precedes a <b>nil</b> value\n(that is, it may consider any such <b>nil</b> value as the end of\nthe array). \n\n\n\n\n\n<h3>2.5.6 - <a name=\"2.5.6\">Precedence</a></h3><p>\nOperator precedence in Lua follows the table below,\nfrom lower to higher priority:\n\n<pre>\n     or\n     and\n     &lt;     &gt;     &lt;=    &gt;=    ~=    ==\n     ..\n     +     -\n     *     /     %\n     not   #     - (unary)\n     ^\n</pre><p>\nAs usual,\nyou can use parentheses to change the precedences of an expression.\nThe concatenation ('<code>..</code>') and exponentiation ('<code>^</code>')\noperators are right associative.\nAll other binary operators are left associative.\n\n\n\n\n\n<h3>2.5.7 - <a name=\"2.5.7\">Table Constructors</a></h3><p>\nTable constructors are expressions that create tables.\nEvery time a constructor is evaluated, a new table is created.\nA constructor can be used to create an empty table\nor to create a table and initialize some of its fields.\nThe general syntax for constructors is\n\n<pre>\n\ttableconstructor ::= `<b>{</b>&acute; [fieldlist] `<b>}</b>&acute;\n\tfieldlist ::= field {fieldsep field} [fieldsep]\n\tfield ::= `<b>[</b>&acute; exp `<b>]</b>&acute; `<b>=</b>&acute; exp | Name `<b>=</b>&acute; exp | exp\n\tfieldsep ::= `<b>,</b>&acute; | `<b>;</b>&acute;\n</pre>\n\n<p>\nEach field of the form <code>[exp1] = exp2</code> adds to the new table an entry\nwith key <code>exp1</code> and value <code>exp2</code>.\nA field of the form <code>name = exp</code> is equivalent to\n<code>[\"name\"] = exp</code>.\nFinally, fields of the form <code>exp</code> are equivalent to\n<code>[i] = exp</code>, where <code>i</code> are consecutive numerical integers,\nstarting with 1.\nFields in the other formats do not affect this counting.\nFor example,\n\n<pre>\n     a = { [f(1)] = g; \"x\", \"y\"; x = 1, f(x), [30] = 23; 45 }\n</pre><p>\nis equivalent to\n\n<pre>\n     do\n       local t = {}\n       t[f(1)] = g\n       t[1] = \"x\"         -- 1st exp\n       t[2] = \"y\"         -- 2nd exp\n       t.x = 1            -- t[\"x\"] = 1\n       t[3] = f(x)        -- 3rd exp\n       t[30] = 23\n       t[4] = 45          -- 4th exp\n       a = t\n     end\n</pre>\n\n<p>\nIf the last field in the list has the form <code>exp</code>\nand the expression is a function call or a vararg expression,\nthen all values returned by this expression enter the list consecutively\n(see <a href=\"#2.5.8\">&sect;2.5.8</a>).\nTo avoid this,\nenclose the function call or the vararg expression\nin parentheses (see <a href=\"#2.5\">&sect;2.5</a>).\n\n\n<p>\nThe field list can have an optional trailing separator,\nas a convenience for machine-generated code.\n\n\n\n\n\n<h3>2.5.8 - <a name=\"2.5.8\">Function Calls</a></h3><p>\nA function call in Lua has the following syntax:\n\n<pre>\n\tfunctioncall ::= prefixexp args\n</pre><p>\nIn a function call,\nfirst prefixexp and args are evaluated.\nIf the value of prefixexp has type <em>function</em>,\nthen this function is called\nwith the given arguments.\nOtherwise, the prefixexp \"call\" metamethod is called,\nhaving as first parameter the value of prefixexp,\nfollowed by the original call arguments\n(see <a href=\"#2.8\">&sect;2.8</a>).\n\n\n<p>\nThe form\n\n<pre>\n\tfunctioncall ::= prefixexp `<b>:</b>&acute; Name args\n</pre><p>\ncan be used to call \"methods\".\nA call <code>v:name(<em>args</em>)</code>\nis syntactic sugar for <code>v.name(v,<em>args</em>)</code>,\nexcept that <code>v</code> is evaluated only once.\n\n\n<p>\nArguments have the following syntax:\n\n<pre>\n\targs ::= `<b>(</b>&acute; [explist] `<b>)</b>&acute;\n\targs ::= tableconstructor\n\targs ::= String\n</pre><p>\nAll argument expressions are evaluated before the call.\nA call of the form <code>f{<em>fields</em>}</code> is\nsyntactic sugar for <code>f({<em>fields</em>})</code>;\nthat is, the argument list is a single new table.\nA call of the form <code>f'<em>string</em>'</code>\n(or <code>f\"<em>string</em>\"</code> or <code>f[[<em>string</em>]]</code>)\nis syntactic sugar for <code>f('<em>string</em>')</code>;\nthat is, the argument list is a single literal string.\n\n\n<p>\nAs an exception to the free-format syntax of Lua,\nyou cannot put a line break before the '<code>(</code>' in a function call.\nThis restriction avoids some ambiguities in the language.\nIf you write\n\n<pre>\n     a = f\n     (g).x(a)\n</pre><p>\nLua would see that as a single statement, <code>a = f(g).x(a)</code>.\nSo, if you want two statements, you must add a semi-colon between them.\nIf you actually want to call <code>f</code>,\nyou must remove the line break before <code>(g)</code>.\n\n\n<p>\nA call of the form <code>return</code> <em>functioncall</em> is called\na <em>tail call</em>.\nLua implements <em>proper tail calls</em>\n(or <em>proper tail recursion</em>):\nin a tail call,\nthe called function reuses the stack entry of the calling function.\nTherefore, there is no limit on the number of nested tail calls that\na program can execute.\nHowever, a tail call erases any debug information about the\ncalling function.\nNote that a tail call only happens with a particular syntax,\nwhere the <b>return</b> has one single function call as argument;\nthis syntax makes the calling function return exactly\nthe returns of the called function.\nSo, none of the following examples are tail calls:\n\n<pre>\n     return (f(x))        -- results adjusted to 1\n     return 2 * f(x)\n     return x, f(x)       -- additional results\n     f(x); return         -- results discarded\n     return x or f(x)     -- results adjusted to 1\n</pre>\n\n\n\n\n<h3>2.5.9 - <a name=\"2.5.9\">Function Definitions</a></h3>\n\n<p>\nThe syntax for function definition is\n\n<pre>\n\tfunction ::= <b>function</b> funcbody\n\tfuncbody ::= `<b>(</b>&acute; [parlist] `<b>)</b>&acute; block <b>end</b>\n</pre>\n\n<p>\nThe following syntactic sugar simplifies function definitions:\n\n<pre>\n\tstat ::= <b>function</b> funcname funcbody\n\tstat ::= <b>local</b> <b>function</b> Name funcbody\n\tfuncname ::= Name {`<b>.</b>&acute; Name} [`<b>:</b>&acute; Name]\n</pre><p>\nThe statement\n\n<pre>\n     function f () <em>body</em> end\n</pre><p>\ntranslates to\n\n<pre>\n     f = function () <em>body</em> end\n</pre><p>\nThe statement\n\n<pre>\n     function t.a.b.c.f () <em>body</em> end\n</pre><p>\ntranslates to\n\n<pre>\n     t.a.b.c.f = function () <em>body</em> end\n</pre><p>\nThe statement\n\n<pre>\n     local function f () <em>body</em> end\n</pre><p>\ntranslates to\n\n<pre>\n     local f; f = function () <em>body</em> end\n</pre><p>\n<em>not</em> to\n\n<pre>\n     local f = function () <em>body</em> end\n</pre><p>\n(This only makes a difference when the body of the function\ncontains references to <code>f</code>.)\n\n\n<p>\nA function definition is an executable expression,\nwhose value has type <em>function</em>.\nWhen Lua pre-compiles a chunk,\nall its function bodies are pre-compiled too.\nThen, whenever Lua executes the function definition,\nthe function is <em>instantiated</em> (or <em>closed</em>).\nThis function instance (or <em>closure</em>)\nis the final value of the expression.\nDifferent instances of the same function\ncan refer to different  external local variables\nand can have different environment tables.\n\n\n<p>\nParameters act as local variables that are\ninitialized with the argument values:\n\n<pre>\n\tparlist ::= namelist [`<b>,</b>&acute; `<b>...</b>&acute;] | `<b>...</b>&acute;\n</pre><p>\nWhen a function is called,\nthe list of arguments is adjusted to\nthe length of the list of parameters,\nunless the function is a variadic or <em>vararg function</em>,\nwhich is\nindicated by three dots ('<code>...</code>') at the end of its parameter list.\nA vararg function does not adjust its argument list;\ninstead, it collects all extra arguments and supplies them\nto the function through a <em>vararg expression</em>,\nwhich is also written as three dots.\nThe value of this expression is a list of all actual extra arguments,\nsimilar to a function with multiple results.\nIf a vararg expression is used inside another expression\nor in the middle of a list of expressions,\nthen its return list is adjusted to one element.\nIf the expression is used as the last element of a list of expressions,\nthen no adjustment is made\n(unless that last expression is enclosed in parentheses).\n\n\n<p>\nAs an example, consider the following definitions:\n\n<pre>\n     function f(a, b) end\n     function g(a, b, ...) end\n     function r() return 1,2,3 end\n</pre><p>\nThen, we have the following mapping from arguments to parameters and\nto the vararg expression:\n\n<pre>\n     CALL            PARAMETERS\n     \n     f(3)             a=3, b=nil\n     f(3, 4)          a=3, b=4\n     f(3, 4, 5)       a=3, b=4\n     f(r(), 10)       a=1, b=10\n     f(r())           a=1, b=2\n     \n     g(3)             a=3, b=nil, ... --&gt;  (nothing)\n     g(3, 4)          a=3, b=4,   ... --&gt;  (nothing)\n     g(3, 4, 5, 8)    a=3, b=4,   ... --&gt;  5  8\n     g(5, r())        a=5, b=1,   ... --&gt;  2  3\n</pre>\n\n<p>\nResults are returned using the <b>return</b> statement (see <a href=\"#2.4.4\">&sect;2.4.4</a>).\nIf control reaches the end of a function\nwithout encountering a <b>return</b> statement,\nthen the function returns with no results.\n\n\n<p>\nThe <em>colon</em> syntax\nis used for defining <em>methods</em>,\nthat is, functions that have an implicit extra parameter <code>self</code>.\nThus, the statement\n\n<pre>\n     function t.a.b.c:f (<em>params</em>) <em>body</em> end\n</pre><p>\nis syntactic sugar for\n\n<pre>\n     t.a.b.c.f = function (self, <em>params</em>) <em>body</em> end\n</pre>\n\n\n\n\n\n\n<h2>2.6 - <a name=\"2.6\">Visibility Rules</a></h2>\n\n<p>\n\nLua is a lexically scoped language.\nThe scope of variables begins at the first statement <em>after</em>\ntheir declaration and lasts until the end of the innermost block that\nincludes the declaration.\nConsider the following example:\n\n<pre>\n     x = 10                -- global variable\n     do                    -- new block\n       local x = x         -- new 'x', with value 10\n       print(x)            --&gt; 10\n       x = x+1\n       do                  -- another block\n         local x = x+1     -- another 'x'\n         print(x)          --&gt; 12\n       end\n       print(x)            --&gt; 11\n     end\n     print(x)              --&gt; 10  (the global one)\n</pre>\n\n<p>\nNotice that, in a declaration like <code>local x = x</code>,\nthe new <code>x</code> being declared is not in scope yet,\nand so the second <code>x</code> refers to the outside variable.\n\n\n<p>\nBecause of the lexical scoping rules,\nlocal variables can be freely accessed by functions\ndefined inside their scope.\nA local variable used by an inner function is called\nan <em>upvalue</em>, or <em>external local variable</em>,\ninside the inner function.\n\n\n<p>\nNotice that each execution of a <b>local</b> statement\ndefines new local variables.\nConsider the following example:\n\n<pre>\n     a = {}\n     local x = 20\n     for i=1,10 do\n       local y = 0\n       a[i] = function () y=y+1; return x+y end\n     end\n</pre><p>\nThe loop creates ten closures\n(that is, ten instances of the anonymous function).\nEach of these closures uses a different <code>y</code> variable,\nwhile all of them share the same <code>x</code>.\n\n\n\n\n\n<h2>2.7 - <a name=\"2.7\">Error Handling</a></h2>\n\n<p>\nBecause Lua is an embedded extension language,\nall Lua actions start from C&nbsp;code in the host program\ncalling a function from the Lua library (see <a href=\"#lua_pcall\"><code>lua_pcall</code></a>).\nWhenever an error occurs during Lua compilation or execution,\ncontrol returns to C,\nwhich can take appropriate measures\n(such as printing an error message).\n\n\n<p>\nLua code can explicitly generate an error by calling the\n<a href=\"#pdf-error\"><code>error</code></a> function.\nIf you need to catch errors in Lua,\nyou can use the <a href=\"#pdf-pcall\"><code>pcall</code></a> function.\n\n\n\n\n\n<h2>2.8 - <a name=\"2.8\">Metatables</a></h2>\n\n<p>\nEvery value in Lua can have a <em>metatable</em>.\nThis <em>metatable</em> is an ordinary Lua table\nthat defines the behavior of the original value\nunder certain special operations.\nYou can change several aspects of the behavior\nof operations over a value by setting specific fields in its metatable.\nFor instance, when a non-numeric value is the operand of an addition,\nLua checks for a function in the field <code>\"__add\"</code> in its metatable.\nIf it finds one,\nLua calls this function to perform the addition.\n\n\n<p>\nWe call the keys in a metatable <em>events</em>\nand the values <em>metamethods</em>.\nIn the previous example, the event is <code>\"add\"</code> \nand the metamethod is the function that performs the addition.\n\n\n<p>\nYou can query the metatable of any value\nthrough the <a href=\"#pdf-getmetatable\"><code>getmetatable</code></a> function.\n\n\n<p>\nYou can replace the metatable of tables\nthrough the <a href=\"#pdf-setmetatable\"><code>setmetatable</code></a>\nfunction.\nYou cannot change the metatable of other types from Lua\n(except by using the debug library);\nyou must use the C&nbsp;API for that.\n\n\n<p>\nTables and full userdata have individual metatables\n(although multiple tables and userdata can share their metatables).\nValues of all other types share one single metatable per type;\nthat is, there is one single metatable for all numbers,\none for all strings, etc.\n\n\n<p>\nA metatable controls how an object behaves in arithmetic operations,\norder comparisons, concatenation, length operation, and indexing.\nA metatable also can define a function to be called when a userdata\nis garbage collected.\nFor each of these operations Lua associates a specific key\ncalled an <em>event</em>.\nWhen Lua performs one of these operations over a value,\nit checks whether this value has a metatable with the corresponding event.\nIf so, the value associated with that key (the metamethod)\ncontrols how Lua will perform the operation.\n\n\n<p>\nMetatables control the operations listed next.\nEach operation is identified by its corresponding name.\nThe key for each operation is a string with its name prefixed by\ntwo underscores, '<code>__</code>';\nfor instance, the key for operation \"add\" is the\nstring <code>\"__add\"</code>.\nThe semantics of these operations is better explained by a Lua function\ndescribing how the interpreter executes the operation.\n\n\n<p>\nThe code shown here in Lua is only illustrative;\nthe real behavior is hard coded in the interpreter\nand it is much more efficient than this simulation.\nAll functions used in these descriptions\n(<a href=\"#pdf-rawget\"><code>rawget</code></a>, <a href=\"#pdf-tonumber\"><code>tonumber</code></a>, etc.)\nare described in <a href=\"#5.1\">&sect;5.1</a>.\nIn particular, to retrieve the metamethod of a given object,\nwe use the expression\n\n<pre>\n     metatable(obj)[event]\n</pre><p>\nThis should be read as\n\n<pre>\n     rawget(getmetatable(obj) or {}, event)\n</pre><p>\n\nThat is, the access to a metamethod does not invoke other metamethods,\nand the access to objects with no metatables does not fail\n(it simply results in <b>nil</b>).\n\n\n\n<ul>\n\n<li><b>\"add\":</b>\nthe <code>+</code> operation.\n\n\n\n<p>\nThe function <code>getbinhandler</code> below defines how Lua chooses a handler\nfor a binary operation.\nFirst, Lua tries the first operand.\nIf its type does not define a handler for the operation,\nthen Lua tries the second operand.\n\n<pre>\n     function getbinhandler (op1, op2, event)\n       return metatable(op1)[event] or metatable(op2)[event]\n     end\n</pre><p>\nBy using this function,\nthe behavior of the <code>op1 + op2</code> is\n\n<pre>\n     function add_event (op1, op2)\n       local o1, o2 = tonumber(op1), tonumber(op2)\n       if o1 and o2 then  -- both operands are numeric?\n         return o1 + o2   -- '+' here is the primitive 'add'\n       else  -- at least one of the operands is not numeric\n         local h = getbinhandler(op1, op2, \"__add\")\n         if h then\n           -- call the handler with both operands\n           return (h(op1, op2))\n         else  -- no handler available: default behavior\n           error(&middot;&middot;&middot;)\n         end\n       end\n     end\n</pre><p>\n</li>\n\n<li><b>\"sub\":</b>\nthe <code>-</code> operation.\n\nBehavior similar to the \"add\" operation.\n</li>\n\n<li><b>\"mul\":</b>\nthe <code>*</code> operation.\n\nBehavior similar to the \"add\" operation.\n</li>\n\n<li><b>\"div\":</b>\nthe <code>/</code> operation.\n\nBehavior similar to the \"add\" operation.\n</li>\n\n<li><b>\"mod\":</b>\nthe <code>%</code> operation.\n\nBehavior similar to the \"add\" operation,\nwith the operation\n<code>o1 - floor(o1/o2)*o2</code> as the primitive operation.\n</li>\n\n<li><b>\"pow\":</b>\nthe <code>^</code> (exponentiation) operation.\n\nBehavior similar to the \"add\" operation,\nwith the function <code>pow</code> (from the C&nbsp;math library)\nas the primitive operation.\n</li>\n\n<li><b>\"unm\":</b>\nthe unary <code>-</code> operation.\n\n\n<pre>\n     function unm_event (op)\n       local o = tonumber(op)\n       if o then  -- operand is numeric?\n         return -o  -- '-' here is the primitive 'unm'\n       else  -- the operand is not numeric.\n         -- Try to get a handler from the operand\n         local h = metatable(op).__unm\n         if h then\n           -- call the handler with the operand\n           return (h(op))\n         else  -- no handler available: default behavior\n           error(&middot;&middot;&middot;)\n         end\n       end\n     end\n</pre><p>\n</li>\n\n<li><b>\"concat\":</b>\nthe <code>..</code> (concatenation) operation.\n\n\n<pre>\n     function concat_event (op1, op2)\n       if (type(op1) == \"string\" or type(op1) == \"number\") and\n          (type(op2) == \"string\" or type(op2) == \"number\") then\n         return op1 .. op2  -- primitive string concatenation\n       else\n         local h = getbinhandler(op1, op2, \"__concat\")\n         if h then\n           return (h(op1, op2))\n         else\n           error(&middot;&middot;&middot;)\n         end\n       end\n     end\n</pre><p>\n</li>\n\n<li><b>\"len\":</b>\nthe <code>#</code> operation.\n\n\n<pre>\n     function len_event (op)\n       if type(op) == \"string\" then\n         return strlen(op)         -- primitive string length\n       elseif type(op) == \"table\" then\n         return #op                -- primitive table length\n       else\n         local h = metatable(op).__len\n         if h then\n           -- call the handler with the operand\n           return (h(op))\n         else  -- no handler available: default behavior\n           error(&middot;&middot;&middot;)\n         end\n       end\n     end\n</pre><p>\nSee <a href=\"#2.5.5\">&sect;2.5.5</a> for a description of the length of a table.\n</li>\n\n<li><b>\"eq\":</b>\nthe <code>==</code> operation.\n\nThe function <code>getcomphandler</code> defines how Lua chooses a metamethod\nfor comparison operators.\nA metamethod only is selected when both objects\nbeing compared have the same type\nand the same metamethod for the selected operation.\n\n<pre>\n     function getcomphandler (op1, op2, event)\n       if type(op1) ~= type(op2) then return nil end\n       local mm1 = metatable(op1)[event]\n       local mm2 = metatable(op2)[event]\n       if mm1 == mm2 then return mm1 else return nil end\n     end\n</pre><p>\nThe \"eq\" event is defined as follows:\n\n<pre>\n     function eq_event (op1, op2)\n       if type(op1) ~= type(op2) then  -- different types?\n         return false   -- different objects\n       end\n       if op1 == op2 then   -- primitive equal?\n         return true   -- objects are equal\n       end\n       -- try metamethod\n       local h = getcomphandler(op1, op2, \"__eq\")\n       if h then\n         return (h(op1, op2))\n       else\n         return false\n       end\n     end\n</pre><p>\n<code>a ~= b</code> is equivalent to <code>not (a == b)</code>.\n</li>\n\n<li><b>\"lt\":</b>\nthe <code>&lt;</code> operation.\n\n\n<pre>\n     function lt_event (op1, op2)\n       if type(op1) == \"number\" and type(op2) == \"number\" then\n         return op1 &lt; op2   -- numeric comparison\n       elseif type(op1) == \"string\" and type(op2) == \"string\" then\n         return op1 &lt; op2   -- lexicographic comparison\n       else\n         local h = getcomphandler(op1, op2, \"__lt\")\n         if h then\n           return (h(op1, op2))\n         else\n           error(&middot;&middot;&middot;)\n         end\n       end\n     end\n</pre><p>\n<code>a &gt; b</code> is equivalent to <code>b &lt; a</code>.\n</li>\n\n<li><b>\"le\":</b>\nthe <code>&lt;=</code> operation.\n\n\n<pre>\n     function le_event (op1, op2)\n       if type(op1) == \"number\" and type(op2) == \"number\" then\n         return op1 &lt;= op2   -- numeric comparison\n       elseif type(op1) == \"string\" and type(op2) == \"string\" then\n         return op1 &lt;= op2   -- lexicographic comparison\n       else\n         local h = getcomphandler(op1, op2, \"__le\")\n         if h then\n           return (h(op1, op2))\n         else\n           h = getcomphandler(op1, op2, \"__lt\")\n           if h then\n             return not h(op2, op1)\n           else\n             error(&middot;&middot;&middot;)\n           end\n         end\n       end\n     end\n</pre><p>\n<code>a &gt;= b</code> is equivalent to <code>b &lt;= a</code>.\nNote that, in the absence of a \"le\" metamethod,\nLua tries the \"lt\", assuming that <code>a &lt;= b</code> is\nequivalent to <code>not (b &lt; a)</code>.\n</li>\n\n<li><b>\"index\":</b>\nThe indexing access <code>table[key]</code>.\n\n\n<pre>\n     function gettable_event (table, key)\n       local h\n       if type(table) == \"table\" then\n         local v = rawget(table, key)\n         if v ~= nil then return v end\n         h = metatable(table).__index\n         if h == nil then return nil end\n       else\n         h = metatable(table).__index\n         if h == nil then\n           error(&middot;&middot;&middot;)\n         end\n       end\n       if type(h) == \"function\" then\n         return (h(table, key))     -- call the handler\n       else return h[key]           -- or repeat operation on it\n       end\n     end\n</pre><p>\n</li>\n\n<li><b>\"newindex\":</b>\nThe indexing assignment <code>table[key] = value</code>.\n\n\n<pre>\n     function settable_event (table, key, value)\n       local h\n       if type(table) == \"table\" then\n         local v = rawget(table, key)\n         if v ~= nil then rawset(table, key, value); return end\n         h = metatable(table).__newindex\n         if h == nil then rawset(table, key, value); return end\n       else\n         h = metatable(table).__newindex\n         if h == nil then\n           error(&middot;&middot;&middot;)\n         end\n       end\n       if type(h) == \"function\" then\n         h(table, key,value)           -- call the handler\n       else h[key] = value             -- or repeat operation on it\n       end\n     end\n</pre><p>\n</li>\n\n<li><b>\"call\":</b>\ncalled when Lua calls a value.\n\n\n<pre>\n     function function_event (func, ...)\n       if type(func) == \"function\" then\n         return func(...)   -- primitive call\n       else\n         local h = metatable(func).__call\n         if h then\n           return h(func, ...)\n         else\n           error(&middot;&middot;&middot;)\n         end\n       end\n     end\n</pre><p>\n</li>\n\n</ul>\n\n\n\n\n<h2>2.9 - <a name=\"2.9\">Environments</a></h2>\n\n<p>\nBesides metatables,\nobjects of types thread, function, and userdata\nhave another table associated with them,\ncalled their <em>environment</em>.\nLike metatables, environments are regular tables and\nmultiple objects can share the same environment.\n\n\n<p>\nThreads are created sharing the environment of the creating thread.\nUserdata and C&nbsp;functions are created sharing the environment\nof the creating C&nbsp;function.\nNon-nested Lua functions\n(created by <a href=\"#pdf-loadfile\"><code>loadfile</code></a>, <a href=\"#pdf-loadstring\"><code>loadstring</code></a> or <a href=\"#pdf-load\"><code>load</code></a>)\nare created sharing the environment of the creating thread.\nNested Lua functions are created sharing the environment of\nthe creating Lua function.\n\n\n<p>\nEnvironments associated with userdata have no meaning for Lua.\nIt is only a convenience feature for programmers to associate a table to\na userdata.\n\n\n<p>\nEnvironments associated with threads are called\n<em>global environments</em>.\nThey are used as the default environment for threads and\nnon-nested Lua functions created by the thread\nand can be directly accessed by C&nbsp;code (see <a href=\"#3.3\">&sect;3.3</a>).\n\n\n<p>\nThe environment associated with a C&nbsp;function can be directly\naccessed by C&nbsp;code (see <a href=\"#3.3\">&sect;3.3</a>).\nIt is used as the default environment for other C&nbsp;functions\nand userdata created by the function.\n\n\n<p>\nEnvironments associated with Lua functions are used to resolve\nall accesses to global variables within the function (see <a href=\"#2.3\">&sect;2.3</a>).\nThey are used as the default environment for nested Lua functions\ncreated by the function.\n\n\n<p>\nYou can change the environment of a Lua function or the\nrunning thread by calling <a href=\"#pdf-setfenv\"><code>setfenv</code></a>.\nYou can get the environment of a Lua function or the running thread\nby calling <a href=\"#pdf-getfenv\"><code>getfenv</code></a>.\nTo manipulate the environment of other objects\n(userdata, C&nbsp;functions, other threads) you must\nuse the C&nbsp;API.\n\n\n\n\n\n<h2>2.10 - <a name=\"2.10\">Garbage Collection</a></h2>\n\n<p>\nLua performs automatic memory management.\nThis means that\nyou have to worry neither about allocating memory for new objects\nnor about freeing it when the objects are no longer needed.\nLua manages memory automatically by running\na <em>garbage collector</em> from time to time\nto collect all <em>dead objects</em>\n(that is, objects that are no longer accessible from Lua).\nAll memory used by Lua is subject to automatic management:\ntables, userdata, functions, threads, strings, etc.\n\n\n<p>\nLua implements an incremental mark-and-sweep collector.\nIt uses two numbers to control its garbage-collection cycles:\nthe <em>garbage-collector pause</em> and\nthe <em>garbage-collector step multiplier</em>.\nBoth use percentage points as units\n(so that a value of 100 means an internal value of 1).\n\n\n<p>\nThe garbage-collector pause\ncontrols how long the collector waits before starting a new cycle.\nLarger values make the collector less aggressive.\nValues smaller than 100 mean the collector will not wait to\nstart a new cycle.\nA value of 200 means that the collector waits for the total memory in use\nto double before starting a new cycle.\n\n\n<p>\nThe step multiplier\ncontrols the relative speed of the collector relative to\nmemory allocation.\nLarger values make the collector more aggressive but also increase\nthe size of each incremental step.\nValues smaller than 100 make the collector too slow and\ncan result in the collector never finishing a cycle.\nThe default, 200, means that the collector runs at \"twice\"\nthe speed of memory allocation.\n\n\n<p>\nYou can change these numbers by calling <a href=\"#lua_gc\"><code>lua_gc</code></a> in C\nor <a href=\"#pdf-collectgarbage\"><code>collectgarbage</code></a> in Lua.\nWith these functions you can also control \nthe collector directly (e.g., stop and restart it).\n\n\n\n<h3>2.10.1 - <a name=\"2.10.1\">Garbage-Collection Metamethods</a></h3>\n\n<p>\nUsing the C&nbsp;API,\nyou can set garbage-collector metamethods for userdata (see <a href=\"#2.8\">&sect;2.8</a>).\nThese metamethods are also called <em>finalizers</em>.\nFinalizers allow you to coordinate Lua's garbage collection\nwith external resource management\n(such as closing files, network or database connections,\nor freeing your own memory).\n\n\n<p>\nGarbage userdata with a field <code>__gc</code> in their metatables are not\ncollected immediately by the garbage collector.\nInstead, Lua puts them in a list.\nAfter the collection,\nLua does the equivalent of the following function\nfor each userdata in that list:\n\n<pre>\n     function gc_event (udata)\n       local h = metatable(udata).__gc\n       if h then\n         h(udata)\n       end\n     end\n</pre>\n\n<p>\nAt the end of each garbage-collection cycle,\nthe finalizers for userdata are called in <em>reverse</em>\norder of their creation,\namong those collected in that cycle.\nThat is, the first finalizer to be called is the one associated\nwith the userdata created last in the program.\nThe userdata itself is freed only in the next garbage-collection cycle.\n\n\n\n\n\n<h3>2.10.2 - <a name=\"2.10.2\">Weak Tables</a></h3>\n\n<p>\nA <em>weak table</em> is a table whose elements are\n<em>weak references</em>.\nA weak reference is ignored by the garbage collector.\nIn other words,\nif the only references to an object are weak references,\nthen the garbage collector will collect this object.\n\n\n<p>\nA weak table can have weak keys, weak values, or both.\nA table with weak keys allows the collection of its keys,\nbut prevents the collection of its values.\nA table with both weak keys and weak values allows the collection of\nboth keys and values.\nIn any case, if either the key or the value is collected,\nthe whole pair is removed from the table.\nThe weakness of a table is controlled by the\n<code>__mode</code> field of its metatable.\nIf the <code>__mode</code> field is a string containing the character&nbsp;'<code>k</code>',\nthe keys in the table are weak.\nIf <code>__mode</code> contains '<code>v</code>',\nthe values in the table are weak.\n\n\n<p>\nAfter you use a table as a metatable,\nyou should not change the value of its <code>__mode</code> field.\nOtherwise, the weak behavior of the tables controlled by this\nmetatable is undefined.\n\n\n\n\n\n\n\n<h2>2.11 - <a name=\"2.11\">Coroutines</a></h2>\n\n<p>\nLua supports coroutines,\nalso called <em>collaborative multithreading</em>.\nA coroutine in Lua represents an independent thread of execution.\nUnlike threads in multithread systems, however,\na coroutine only suspends its execution by explicitly calling\na yield function.\n\n\n<p>\nYou create a coroutine with a call to <a href=\"#pdf-coroutine.create\"><code>coroutine.create</code></a>.\nIts sole argument is a function\nthat is the main function of the coroutine.\nThe <code>create</code> function only creates a new coroutine and\nreturns a handle to it (an object of type <em>thread</em>);\nit does not start the coroutine execution.\n\n\n<p>\nWhen you first call <a href=\"#pdf-coroutine.resume\"><code>coroutine.resume</code></a>,\npassing as its first argument\na thread returned by <a href=\"#pdf-coroutine.create\"><code>coroutine.create</code></a>,\nthe coroutine starts its execution,\nat the first line of its main function.\nExtra arguments passed to <a href=\"#pdf-coroutine.resume\"><code>coroutine.resume</code></a> are passed on\nto the coroutine main function.\nAfter the coroutine starts running,\nit runs until it terminates or <em>yields</em>.\n\n\n<p>\nA coroutine can terminate its execution in two ways:\nnormally, when its main function returns\n(explicitly or implicitly, after the last instruction);\nand abnormally, if there is an unprotected error.\nIn the first case, <a href=\"#pdf-coroutine.resume\"><code>coroutine.resume</code></a> returns <b>true</b>,\nplus any values returned by the coroutine main function.\nIn case of errors, <a href=\"#pdf-coroutine.resume\"><code>coroutine.resume</code></a> returns <b>false</b>\nplus an error message.\n\n\n<p>\nA coroutine yields by calling <a href=\"#pdf-coroutine.yield\"><code>coroutine.yield</code></a>.\nWhen a coroutine yields,\nthe corresponding <a href=\"#pdf-coroutine.resume\"><code>coroutine.resume</code></a> returns immediately,\neven if the yield happens inside nested function calls\n(that is, not in the main function,\nbut in a function directly or indirectly called by the main function).\nIn the case of a yield, <a href=\"#pdf-coroutine.resume\"><code>coroutine.resume</code></a> also returns <b>true</b>,\nplus any values passed to <a href=\"#pdf-coroutine.yield\"><code>coroutine.yield</code></a>.\nThe next time you resume the same coroutine,\nit continues its execution from the point where it yielded,\nwith the call to <a href=\"#pdf-coroutine.yield\"><code>coroutine.yield</code></a> returning any extra\narguments passed to <a href=\"#pdf-coroutine.resume\"><code>coroutine.resume</code></a>.\n\n\n<p>\nLike <a href=\"#pdf-coroutine.create\"><code>coroutine.create</code></a>,\nthe <a href=\"#pdf-coroutine.wrap\"><code>coroutine.wrap</code></a> function also creates a coroutine,\nbut instead of returning the coroutine itself,\nit returns a function that, when called, resumes the coroutine.\nAny arguments passed to this function\ngo as extra arguments to <a href=\"#pdf-coroutine.resume\"><code>coroutine.resume</code></a>.\n<a href=\"#pdf-coroutine.wrap\"><code>coroutine.wrap</code></a> returns all the values returned by <a href=\"#pdf-coroutine.resume\"><code>coroutine.resume</code></a>,\nexcept the first one (the boolean error code).\nUnlike <a href=\"#pdf-coroutine.resume\"><code>coroutine.resume</code></a>,\n<a href=\"#pdf-coroutine.wrap\"><code>coroutine.wrap</code></a> does not catch errors;\nany error is propagated to the caller.\n\n\n<p>\nAs an example,\nconsider the following code:\n\n<pre>\n     function foo (a)\n       print(\"foo\", a)\n       return coroutine.yield(2*a)\n     end\n     \n     co = coroutine.create(function (a,b)\n           print(\"co-body\", a, b)\n           local r = foo(a+1)\n           print(\"co-body\", r)\n           local r, s = coroutine.yield(a+b, a-b)\n           print(\"co-body\", r, s)\n           return b, \"end\"\n     end)\n            \n     print(\"main\", coroutine.resume(co, 1, 10))\n     print(\"main\", coroutine.resume(co, \"r\"))\n     print(\"main\", coroutine.resume(co, \"x\", \"y\"))\n     print(\"main\", coroutine.resume(co, \"x\", \"y\"))\n</pre><p>\nWhen you run it, it produces the following output:\n\n<pre>\n     co-body 1       10\n     foo     2\n     \n     main    true    4\n     co-body r\n     main    true    11      -9\n     co-body x       y\n     main    true    10      end\n     main    false   cannot resume dead coroutine\n</pre>\n\n\n\n\n<h1>3 - <a name=\"3\">The Application Program Interface</a></h1>\n\n<p>\n\nThis section describes the C&nbsp;API for Lua, that is,\nthe set of C&nbsp;functions available to the host program to communicate\nwith Lua.\nAll API functions and related types and constants\nare declared in the header file <a name=\"pdf-lua.h\"><code>lua.h</code></a>.\n\n\n<p>\nEven when we use the term \"function\",\nany facility in the API may be provided as a macro instead.\nAll such macros use each of their arguments exactly once\n(except for the first argument, which is always a Lua state),\nand so do not generate any hidden side-effects.\n\n\n<p>\nAs in most C&nbsp;libraries,\nthe Lua API functions do not check their arguments for validity or consistency.\nHowever, you can change this behavior by compiling Lua\nwith a proper definition for the macro <a name=\"pdf-luai_apicheck\"><code>luai_apicheck</code></a>,\nin file <code>luaconf.h</code>.\n\n\n\n<h2>3.1 - <a name=\"3.1\">The Stack</a></h2>\n\n<p>\nLua uses a <em>virtual stack</em> to pass values to and from C.\nEach element in this stack represents a Lua value\n(<b>nil</b>, number, string, etc.).\n\n\n<p>\nWhenever Lua calls C, the called function gets a new stack,\nwhich is independent of previous stacks and of stacks of\nC&nbsp;functions that are still active.\nThis stack initially contains any arguments to the C&nbsp;function\nand it is where the C&nbsp;function pushes its results\nto be returned to the caller (see <a href=\"#lua_CFunction\"><code>lua_CFunction</code></a>).\n\n\n<p>\nFor convenience,\nmost query operations in the API do not follow a strict stack discipline.\nInstead, they can refer to any element in the stack\nby using an <em>index</em>:\nA positive index represents an <em>absolute</em> stack position\n(starting at&nbsp;1);\na negative index represents an <em>offset</em> relative to the top of the stack.\nMore specifically, if the stack has <em>n</em> elements,\nthen index&nbsp;1 represents the first element\n(that is, the element that was pushed onto the stack first)\nand\nindex&nbsp;<em>n</em> represents the last element;\nindex&nbsp;-1 also represents the last element\n(that is, the element at the&nbsp;top)\nand index <em>-n</em> represents the first element.\nWe say that an index is <em>valid</em>\nif it lies between&nbsp;1 and the stack top\n(that is, if <code>1 &le; abs(index) &le; top</code>).\n \n\n\n\n\n\n<h2>3.2 - <a name=\"3.2\">Stack Size</a></h2>\n\n<p>\nWhen you interact with Lua API,\nyou are responsible for ensuring consistency.\nIn particular,\n<em>you are responsible for controlling stack overflow</em>.\nYou can use the function <a href=\"#lua_checkstack\"><code>lua_checkstack</code></a>\nto grow the stack size.\n\n\n<p>\nWhenever Lua calls C,\nit ensures that at least <a name=\"pdf-LUA_MINSTACK\"><code>LUA_MINSTACK</code></a> stack positions are available.\n<code>LUA_MINSTACK</code> is defined as 20,\nso that usually you do not have to worry about stack space\nunless your code has loops pushing elements onto the stack.\n\n\n<p>\nMost query functions accept as indices any value inside the\navailable stack space, that is, indices up to the maximum stack size\nyou have set through <a href=\"#lua_checkstack\"><code>lua_checkstack</code></a>.\nSuch indices are called <em>acceptable indices</em>.\nMore formally, we define an <em>acceptable index</em>\nas follows:\n\n<pre>\n     (index &lt; 0 &amp;&amp; abs(index) &lt;= top) ||\n     (index &gt; 0 &amp;&amp; index &lt;= stackspace)\n</pre><p>\nNote that 0 is never an acceptable index.\n\n\n\n\n\n<h2>3.3 - <a name=\"3.3\">Pseudo-Indices</a></h2>\n\n<p>\nUnless otherwise noted,\nany function that accepts valid indices can also be called with\n<em>pseudo-indices</em>,\nwhich represent some Lua values that are accessible to C&nbsp;code\nbut which are not in the stack.\nPseudo-indices are used to access the thread environment,\nthe function environment,\nthe registry,\nand the upvalues of a C&nbsp;function (see <a href=\"#3.4\">&sect;3.4</a>).\n\n\n<p>\nThe thread environment (where global variables live) is\nalways at pseudo-index <a name=\"pdf-LUA_GLOBALSINDEX\"><code>LUA_GLOBALSINDEX</code></a>.\nThe environment of the running C&nbsp;function is always\nat pseudo-index <a name=\"pdf-LUA_ENVIRONINDEX\"><code>LUA_ENVIRONINDEX</code></a>.\n\n\n<p>\nTo access and change the value of global variables,\nyou can use regular table operations over an environment table.\nFor instance, to access the value of a global variable, do\n\n<pre>\n     lua_getfield(L, LUA_GLOBALSINDEX, varname);\n</pre>\n\n\n\n\n<h2>3.4 - <a name=\"3.4\">C Closures</a></h2>\n\n<p>\nWhen a C&nbsp;function is created,\nit is possible to associate some values with it,\nthus creating a <em>C&nbsp;closure</em>;\nthese values are called <em>upvalues</em> and are\naccessible to the function whenever it is called\n(see <a href=\"#lua_pushcclosure\"><code>lua_pushcclosure</code></a>).\n\n\n<p>\nWhenever a C&nbsp;function is called,\nits upvalues are located at specific pseudo-indices.\nThese pseudo-indices are produced by the macro\n<a name=\"lua_upvalueindex\"><code>lua_upvalueindex</code></a>.\nThe first value associated with a function is at position\n<code>lua_upvalueindex(1)</code>, and so on.\nAny access to <code>lua_upvalueindex(<em>n</em>)</code>,\nwhere <em>n</em> is greater than the number of upvalues of the\ncurrent function (but not greater than 256),\nproduces an acceptable (but invalid) index.\n\n\n\n\n\n<h2>3.5 - <a name=\"3.5\">Registry</a></h2>\n\n<p>\nLua provides a <em>registry</em>,\na pre-defined table that can be used by any C&nbsp;code to\nstore whatever Lua value it needs to store.\nThis table is always located at pseudo-index\n<a name=\"pdf-LUA_REGISTRYINDEX\"><code>LUA_REGISTRYINDEX</code></a>.\nAny C&nbsp;library can store data into this table,\nbut it should take care to choose keys different from those used\nby other libraries, to avoid collisions.\nTypically, you should use as key a string containing your library name\nor a light userdata with the address of a C&nbsp;object in your code.\n\n\n<p>\nThe integer keys in the registry are used by the reference mechanism,\nimplemented by the auxiliary library,\nand therefore should not be used for other purposes.\n\n\n\n\n\n<h2>3.6 - <a name=\"3.6\">Error Handling in C</a></h2>\n\n<p>\nInternally, Lua uses the C <code>longjmp</code> facility to handle errors.\n(You can also choose to use exceptions if you use C++;\nsee file <code>luaconf.h</code>.)\nWhen Lua faces any error\n(such as memory allocation errors, type errors, syntax errors,\nand runtime errors)\nit <em>raises</em> an error;\nthat is, it does a long jump.\nA <em>protected environment</em> uses <code>setjmp</code>\nto set a recover point;\nany error jumps to the most recent active recover point.\n\n\n<p>\nMost functions in the API can throw an error,\nfor instance due to a memory allocation error.\nThe documentation for each function indicates whether\nit can throw errors.\n\n\n<p>\nInside a C&nbsp;function you can throw an error by calling <a href=\"#lua_error\"><code>lua_error</code></a>.\n\n\n\n\n\n<h2>3.7 - <a name=\"3.7\">Functions and Types</a></h2>\n\n<p>\nHere we list all functions and types from the C&nbsp;API in\nalphabetical order.\nEach function has an indicator like this:\n<span class=\"apii\">[-o, +p, <em>x</em>]</span>\n\n\n<p>\nThe first field, <code>o</code>,\nis how many elements the function pops from the stack.\nThe second field, <code>p</code>,\nis how many elements the function pushes onto the stack.\n(Any function always pushes its results after popping its arguments.)\nA field in the form <code>x|y</code> means the function can push (or pop)\n<code>x</code> or <code>y</code> elements,\ndepending on the situation;\nan interrogation mark '<code>?</code>' means that\nwe cannot know how many elements the function pops/pushes\nby looking only at its arguments\n(e.g., they may depend on what is on the stack).\nThe third field, <code>x</code>,\ntells whether the function may throw errors:\n'<code>-</code>' means the function never throws any error;\n'<code>m</code>' means the function may throw an error\nonly due to not enough memory;\n'<code>e</code>' means the function may throw other kinds of errors;\n'<code>v</code>' means the function may throw an error on purpose.\n\n\n\n<hr><h3><a name=\"lua_Alloc\"><code>lua_Alloc</code></a></h3>\n<pre>typedef void * (*lua_Alloc) (void *ud,\n                             void *ptr,\n                             size_t osize,\n                             size_t nsize);</pre>\n\n<p>\nThe type of the memory-allocation function used by Lua states.\nThe allocator function must provide a\nfunctionality similar to <code>realloc</code>,\nbut not exactly the same.\nIts arguments are\n<code>ud</code>, an opaque pointer passed to <a href=\"#lua_newstate\"><code>lua_newstate</code></a>;\n<code>ptr</code>, a pointer to the block being allocated/reallocated/freed;\n<code>osize</code>, the original size of the block;\n<code>nsize</code>, the new size of the block.\n<code>ptr</code> is <code>NULL</code> if and only if <code>osize</code> is zero.\nWhen <code>nsize</code> is zero, the allocator must return <code>NULL</code>;\nif <code>osize</code> is not zero,\nit should free the block pointed to by <code>ptr</code>.\nWhen <code>nsize</code> is not zero, the allocator returns <code>NULL</code>\nif and only if it cannot fill the request.\nWhen <code>nsize</code> is not zero and <code>osize</code> is zero,\nthe allocator should behave like <code>malloc</code>.\nWhen <code>nsize</code> and <code>osize</code> are not zero,\nthe allocator behaves like <code>realloc</code>.\nLua assumes that the allocator never fails when\n<code>osize &gt;= nsize</code>.\n\n\n<p>\nHere is a simple implementation for the allocator function.\nIt is used in the auxiliary library by <a href=\"#luaL_newstate\"><code>luaL_newstate</code></a>.\n\n<pre>\n     static void *l_alloc (void *ud, void *ptr, size_t osize,\n                                                size_t nsize) {\n       (void)ud;  (void)osize;  /* not used */\n       if (nsize == 0) {\n         free(ptr);\n         return NULL;\n       }\n       else\n         return realloc(ptr, nsize);\n     }\n</pre><p>\nThis code assumes\nthat <code>free(NULL)</code> has no effect and that\n<code>realloc(NULL, size)</code> is equivalent to <code>malloc(size)</code>.\nANSI&nbsp;C ensures both behaviors.\n\n\n\n\n\n<hr><h3><a name=\"lua_atpanic\"><code>lua_atpanic</code></a></h3><p>\n<span class=\"apii\">[-0, +0, <em>-</em>]</span>\n<pre>lua_CFunction lua_atpanic (lua_State *L, lua_CFunction panicf);</pre>\n\n<p>\nSets a new panic function and returns the old one.\n\n\n<p>\nIf an error happens outside any protected environment,\nLua calls a <em>panic function</em>\nand then calls <code>exit(EXIT_FAILURE)</code>,\nthus exiting the host application.\nYour panic function can avoid this exit by\nnever returning (e.g., doing a long jump).\n\n\n<p>\nThe panic function can access the error message at the top of the stack.\n\n\n\n\n\n<hr><h3><a name=\"lua_call\"><code>lua_call</code></a></h3><p>\n<span class=\"apii\">[-(nargs + 1), +nresults, <em>e</em>]</span>\n<pre>void lua_call (lua_State *L, int nargs, int nresults);</pre>\n\n<p>\nCalls a function.\n\n\n<p>\nTo call a function you must use the following protocol:\nfirst, the function to be called is pushed onto the stack;\nthen, the arguments to the function are pushed\nin direct order;\nthat is, the first argument is pushed first.\nFinally you call <a href=\"#lua_call\"><code>lua_call</code></a>;\n<code>nargs</code> is the number of arguments that you pushed onto the stack.\nAll arguments and the function value are popped from the stack\nwhen the function is called.\nThe function results are pushed onto the stack when the function returns.\nThe number of results is adjusted to <code>nresults</code>,\nunless <code>nresults</code> is <a name=\"pdf-LUA_MULTRET\"><code>LUA_MULTRET</code></a>.\nIn this case, <em>all</em> results from the function are pushed.\nLua takes care that the returned values fit into the stack space.\nThe function results are pushed onto the stack in direct order\n(the first result is pushed first),\nso that after the call the last result is on the top of the stack.\n\n\n<p>\nAny error inside the called function is propagated upwards\n(with a <code>longjmp</code>).\n\n\n<p>\nThe following example shows how the host program can do the\nequivalent to this Lua code:\n\n<pre>\n     a = f(\"how\", t.x, 14)\n</pre><p>\nHere it is in&nbsp;C:\n\n<pre>\n     lua_getfield(L, LUA_GLOBALSINDEX, \"f\"); /* function to be called */\n     lua_pushstring(L, \"how\");                        /* 1st argument */\n     lua_getfield(L, LUA_GLOBALSINDEX, \"t\");   /* table to be indexed */\n     lua_getfield(L, -1, \"x\");        /* push result of t.x (2nd arg) */\n     lua_remove(L, -2);                  /* remove 't' from the stack */\n     lua_pushinteger(L, 14);                          /* 3rd argument */\n     lua_call(L, 3, 1);     /* call 'f' with 3 arguments and 1 result */\n     lua_setfield(L, LUA_GLOBALSINDEX, \"a\");        /* set global 'a' */\n</pre><p>\nNote that the code above is \"balanced\":\nat its end, the stack is back to its original configuration.\nThis is considered good programming practice.\n\n\n\n\n\n<hr><h3><a name=\"lua_CFunction\"><code>lua_CFunction</code></a></h3>\n<pre>typedef int (*lua_CFunction) (lua_State *L);</pre>\n\n<p>\nType for C&nbsp;functions.\n\n\n<p>\nIn order to communicate properly with Lua,\na C&nbsp;function must use the following protocol,\nwhich defines the way parameters and results are passed:\na C&nbsp;function receives its arguments from Lua in its stack\nin direct order (the first argument is pushed first).\nSo, when the function starts,\n<code>lua_gettop(L)</code> returns the number of arguments received by the function.\nThe first argument (if any) is at index 1\nand its last argument is at index <code>lua_gettop(L)</code>.\nTo return values to Lua, a C&nbsp;function just pushes them onto the stack,\nin direct order (the first result is pushed first),\nand returns the number of results.\nAny other value in the stack below the results will be properly\ndiscarded by Lua.\nLike a Lua function, a C&nbsp;function called by Lua can also return\nmany results.\n\n\n<p>\nAs an example, the following function receives a variable number\nof numerical arguments and returns their average and sum:\n\n<pre>\n     static int foo (lua_State *L) {\n       int n = lua_gettop(L);    /* number of arguments */\n       lua_Number sum = 0;\n       int i;\n       for (i = 1; i &lt;= n; i++) {\n         if (!lua_isnumber(L, i)) {\n           lua_pushstring(L, \"incorrect argument\");\n           lua_error(L);\n         }\n         sum += lua_tonumber(L, i);\n       }\n       lua_pushnumber(L, sum/n);        /* first result */\n       lua_pushnumber(L, sum);         /* second result */\n       return 2;                   /* number of results */\n     }\n</pre>\n\n\n\n\n<hr><h3><a name=\"lua_checkstack\"><code>lua_checkstack</code></a></h3><p>\n<span class=\"apii\">[-0, +0, <em>m</em>]</span>\n<pre>int lua_checkstack (lua_State *L, int extra);</pre>\n\n<p>\nEnsures that there are at least <code>extra</code> free stack slots in the stack.\nIt returns false if it cannot grow the stack to that size.\nThis function never shrinks the stack;\nif the stack is already larger than the new size,\nit is left unchanged.\n\n\n\n\n\n<hr><h3><a name=\"lua_close\"><code>lua_close</code></a></h3><p>\n<span class=\"apii\">[-0, +0, <em>-</em>]</span>\n<pre>void lua_close (lua_State *L);</pre>\n\n<p>\nDestroys all objects in the given Lua state\n(calling the corresponding garbage-collection metamethods, if any)\nand frees all dynamic memory used by this state.\nOn several platforms, you may not need to call this function,\nbecause all resources are naturally released when the host program ends.\nOn the other hand, long-running programs,\nsuch as a daemon or a web server,\nmight need to release states as soon as they are not needed,\nto avoid growing too large.\n\n\n\n\n\n<hr><h3><a name=\"lua_concat\"><code>lua_concat</code></a></h3><p>\n<span class=\"apii\">[-n, +1, <em>e</em>]</span>\n<pre>void lua_concat (lua_State *L, int n);</pre>\n\n<p>\nConcatenates the <code>n</code> values at the top of the stack,\npops them, and leaves the result at the top.\nIf <code>n</code>&nbsp;is&nbsp;1, the result is the single value on the stack\n(that is, the function does nothing);\nif <code>n</code> is 0, the result is the empty string.\nConcatenation is performed following the usual semantics of Lua\n(see <a href=\"#2.5.4\">&sect;2.5.4</a>).\n\n\n\n\n\n<hr><h3><a name=\"lua_cpcall\"><code>lua_cpcall</code></a></h3><p>\n<span class=\"apii\">[-0, +(0|1), <em>-</em>]</span>\n<pre>int lua_cpcall (lua_State *L, lua_CFunction func, void *ud);</pre>\n\n<p>\nCalls the C&nbsp;function <code>func</code> in protected mode.\n<code>func</code> starts with only one element in its stack,\na light userdata containing <code>ud</code>.\nIn case of errors,\n<a href=\"#lua_cpcall\"><code>lua_cpcall</code></a> returns the same error codes as <a href=\"#lua_pcall\"><code>lua_pcall</code></a>,\nplus the error object on the top of the stack;\notherwise, it returns zero, and does not change the stack.\nAll values returned by <code>func</code> are discarded.\n\n\n\n\n\n<hr><h3><a name=\"lua_createtable\"><code>lua_createtable</code></a></h3><p>\n<span class=\"apii\">[-0, +1, <em>m</em>]</span>\n<pre>void lua_createtable (lua_State *L, int narr, int nrec);</pre>\n\n<p>\nCreates a new empty table and pushes it onto the stack.\nThe new table has space pre-allocated\nfor <code>narr</code> array elements and <code>nrec</code> non-array elements.\nThis pre-allocation is useful when you know exactly how many elements\nthe table will have.\nOtherwise you can use the function <a href=\"#lua_newtable\"><code>lua_newtable</code></a>.\n\n\n\n\n\n<hr><h3><a name=\"lua_dump\"><code>lua_dump</code></a></h3><p>\n<span class=\"apii\">[-0, +0, <em>m</em>]</span>\n<pre>int lua_dump (lua_State *L, lua_Writer writer, void *data);</pre>\n\n<p>\nDumps a function as a binary chunk.\nReceives a Lua function on the top of the stack\nand produces a binary chunk that,\nif loaded again,\nresults in a function equivalent to the one dumped.\nAs it produces parts of the chunk,\n<a href=\"#lua_dump\"><code>lua_dump</code></a> calls function <code>writer</code> (see <a href=\"#lua_Writer\"><code>lua_Writer</code></a>)\nwith the given <code>data</code>\nto write them.\n\n\n<p>\nThe value returned is the error code returned by the last\ncall to the writer;\n0&nbsp;means no errors.\n\n\n<p>\nThis function does not pop the Lua function from the stack.\n\n\n\n\n\n<hr><h3><a name=\"lua_equal\"><code>lua_equal</code></a></h3><p>\n<span class=\"apii\">[-0, +0, <em>e</em>]</span>\n<pre>int lua_equal (lua_State *L, int index1, int index2);</pre>\n\n<p>\nReturns 1 if the two values in acceptable indices <code>index1</code> and\n<code>index2</code> are equal,\nfollowing the semantics of the Lua <code>==</code> operator\n(that is, may call metamethods).\nOtherwise returns&nbsp;0.\nAlso returns&nbsp;0 if any of the indices is non valid.\n\n\n\n\n\n<hr><h3><a name=\"lua_error\"><code>lua_error</code></a></h3><p>\n<span class=\"apii\">[-1, +0, <em>v</em>]</span>\n<pre>int lua_error (lua_State *L);</pre>\n\n<p>\nGenerates a Lua error.\nThe error message (which can actually be a Lua value of any type)\nmust be on the stack top.\nThis function does a long jump,\nand therefore never returns.\n(see <a href=\"#luaL_error\"><code>luaL_error</code></a>).\n\n\n\n\n\n<hr><h3><a name=\"lua_gc\"><code>lua_gc</code></a></h3><p>\n<span class=\"apii\">[-0, +0, <em>e</em>]</span>\n<pre>int lua_gc (lua_State *L, int what, int data);</pre>\n\n<p>\nControls the garbage collector.\n\n\n<p>\nThis function performs several tasks,\naccording to the value of the parameter <code>what</code>:\n\n<ul>\n\n<li><b><code>LUA_GCSTOP</code>:</b>\nstops the garbage collector.\n</li>\n\n<li><b><code>LUA_GCRESTART</code>:</b>\nrestarts the garbage collector.\n</li>\n\n<li><b><code>LUA_GCCOLLECT</code>:</b>\nperforms a full garbage-collection cycle.\n</li>\n\n<li><b><code>LUA_GCCOUNT</code>:</b>\nreturns the current amount of memory (in Kbytes) in use by Lua.\n</li>\n\n<li><b><code>LUA_GCCOUNTB</code>:</b>\nreturns the remainder of dividing the current amount of bytes of\nmemory in use by Lua by 1024.\n</li>\n\n<li><b><code>LUA_GCSTEP</code>:</b>\nperforms an incremental step of garbage collection.\nThe step \"size\" is controlled by <code>data</code>\n(larger values mean more steps) in a non-specified way.\nIf you want to control the step size\nyou must experimentally tune the value of <code>data</code>.\nThe function returns 1 if the step finished a\ngarbage-collection cycle.\n</li>\n\n<li><b><code>LUA_GCSETPAUSE</code>:</b>\nsets <code>data</code> as the new value\nfor the <em>pause</em> of the collector (see <a href=\"#2.10\">&sect;2.10</a>).\nThe function returns the previous value of the pause.\n</li>\n\n<li><b><code>LUA_GCSETSTEPMUL</code>:</b>\nsets <code>data</code> as the new value for the <em>step multiplier</em> of\nthe collector (see <a href=\"#2.10\">&sect;2.10</a>).\nThe function returns the previous value of the step multiplier.\n</li>\n\n</ul>\n\n\n\n\n<hr><h3><a name=\"lua_getallocf\"><code>lua_getallocf</code></a></h3><p>\n<span class=\"apii\">[-0, +0, <em>-</em>]</span>\n<pre>lua_Alloc lua_getallocf (lua_State *L, void **ud);</pre>\n\n<p>\nReturns the memory-allocation function of a given state.\nIf <code>ud</code> is not <code>NULL</code>, Lua stores in <code>*ud</code> the\nopaque pointer passed to <a href=\"#lua_newstate\"><code>lua_newstate</code></a>.\n\n\n\n\n\n<hr><h3><a name=\"lua_getfenv\"><code>lua_getfenv</code></a></h3><p>\n<span class=\"apii\">[-0, +1, <em>-</em>]</span>\n<pre>void lua_getfenv (lua_State *L, int index);</pre>\n\n<p>\nPushes onto the stack the environment table of\nthe value at the given index.\n\n\n\n\n\n<hr><h3><a name=\"lua_getfield\"><code>lua_getfield</code></a></h3><p>\n<span class=\"apii\">[-0, +1, <em>e</em>]</span>\n<pre>void lua_getfield (lua_State *L, int index, const char *k);</pre>\n\n<p>\nPushes onto the stack the value <code>t[k]</code>,\nwhere <code>t</code> is the value at the given valid index.\nAs in Lua, this function may trigger a metamethod\nfor the \"index\" event (see <a href=\"#2.8\">&sect;2.8</a>).\n\n\n\n\n\n<hr><h3><a name=\"lua_getglobal\"><code>lua_getglobal</code></a></h3><p>\n<span class=\"apii\">[-0, +1, <em>e</em>]</span>\n<pre>void lua_getglobal (lua_State *L, const char *name);</pre>\n\n<p>\nPushes onto the stack the value of the global <code>name</code>.\nIt is defined as a macro:\n\n<pre>\n     #define lua_getglobal(L,s)  lua_getfield(L, LUA_GLOBALSINDEX, s)\n</pre>\n\n\n\n\n<hr><h3><a name=\"lua_getmetatable\"><code>lua_getmetatable</code></a></h3><p>\n<span class=\"apii\">[-0, +(0|1), <em>-</em>]</span>\n<pre>int lua_getmetatable (lua_State *L, int index);</pre>\n\n<p>\nPushes onto the stack the metatable of the value at the given\nacceptable index.\nIf the index is not valid,\nor if the value does not have a metatable,\nthe function returns&nbsp;0 and pushes nothing on the stack.\n\n\n\n\n\n<hr><h3><a name=\"lua_gettable\"><code>lua_gettable</code></a></h3><p>\n<span class=\"apii\">[-1, +1, <em>e</em>]</span>\n<pre>void lua_gettable (lua_State *L, int index);</pre>\n\n<p>\nPushes onto the stack the value <code>t[k]</code>,\nwhere <code>t</code> is the value at the given valid index\nand <code>k</code> is the value at the top of the stack.\n\n\n<p>\nThis function pops the key from the stack\n(putting the resulting value in its place).\nAs in Lua, this function may trigger a metamethod\nfor the \"index\" event (see <a href=\"#2.8\">&sect;2.8</a>).\n\n\n\n\n\n<hr><h3><a name=\"lua_gettop\"><code>lua_gettop</code></a></h3><p>\n<span class=\"apii\">[-0, +0, <em>-</em>]</span>\n<pre>int lua_gettop (lua_State *L);</pre>\n\n<p>\nReturns the index of the top element in the stack.\nBecause indices start at&nbsp;1,\nthis result is equal to the number of elements in the stack\n(and so 0&nbsp;means an empty stack).\n\n\n\n\n\n<hr><h3><a name=\"lua_insert\"><code>lua_insert</code></a></h3><p>\n<span class=\"apii\">[-1, +1, <em>-</em>]</span>\n<pre>void lua_insert (lua_State *L, int index);</pre>\n\n<p>\nMoves the top element into the given valid index,\nshifting up the elements above this index to open space.\nCannot be called with a pseudo-index,\nbecause a pseudo-index is not an actual stack position.\n\n\n\n\n\n<hr><h3><a name=\"lua_Integer\"><code>lua_Integer</code></a></h3>\n<pre>typedef ptrdiff_t lua_Integer;</pre>\n\n<p>\nThe type used by the Lua API to represent integral values.\n\n\n<p>\nBy default it is a <code>ptrdiff_t</code>,\nwhich is usually the largest signed integral type the machine handles\n\"comfortably\".\n\n\n\n\n\n<hr><h3><a name=\"lua_isboolean\"><code>lua_isboolean</code></a></h3><p>\n<span class=\"apii\">[-0, +0, <em>-</em>]</span>\n<pre>int lua_isboolean (lua_State *L, int index);</pre>\n\n<p>\nReturns 1 if the value at the given acceptable index has type boolean,\nand 0&nbsp;otherwise.\n\n\n\n\n\n<hr><h3><a name=\"lua_iscfunction\"><code>lua_iscfunction</code></a></h3><p>\n<span class=\"apii\">[-0, +0, <em>-</em>]</span>\n<pre>int lua_iscfunction (lua_State *L, int index);</pre>\n\n<p>\nReturns 1 if the value at the given acceptable index is a C&nbsp;function,\nand 0&nbsp;otherwise.\n\n\n\n\n\n<hr><h3><a name=\"lua_isfunction\"><code>lua_isfunction</code></a></h3><p>\n<span class=\"apii\">[-0, +0, <em>-</em>]</span>\n<pre>int lua_isfunction (lua_State *L, int index);</pre>\n\n<p>\nReturns 1 if the value at the given acceptable index is a function\n(either C or Lua), and 0&nbsp;otherwise.\n\n\n\n\n\n<hr><h3><a name=\"lua_islightuserdata\"><code>lua_islightuserdata</code></a></h3><p>\n<span class=\"apii\">[-0, +0, <em>-</em>]</span>\n<pre>int lua_islightuserdata (lua_State *L, int index);</pre>\n\n<p>\nReturns 1 if the value at the given acceptable index is a light userdata,\nand 0&nbsp;otherwise.\n\n\n\n\n\n<hr><h3><a name=\"lua_isnil\"><code>lua_isnil</code></a></h3><p>\n<span class=\"apii\">[-0, +0, <em>-</em>]</span>\n<pre>int lua_isnil (lua_State *L, int index);</pre>\n\n<p>\nReturns 1 if the value at the given acceptable index is <b>nil</b>,\nand 0&nbsp;otherwise.\n\n\n\n\n\n<hr><h3><a name=\"lua_isnone\"><code>lua_isnone</code></a></h3><p>\n<span class=\"apii\">[-0, +0, <em>-</em>]</span>\n<pre>int lua_isnone (lua_State *L, int index);</pre>\n\n<p>\nReturns 1 if the given acceptable index is not valid\n(that is, it refers to an element outside the current stack),\nand 0&nbsp;otherwise.\n\n\n\n\n\n<hr><h3><a name=\"lua_isnoneornil\"><code>lua_isnoneornil</code></a></h3><p>\n<span class=\"apii\">[-0, +0, <em>-</em>]</span>\n<pre>int lua_isnoneornil (lua_State *L, int index);</pre>\n\n<p>\nReturns 1 if the given acceptable index is not valid\n(that is, it refers to an element outside the current stack)\nor if the value at this index is <b>nil</b>,\nand 0&nbsp;otherwise.\n\n\n\n\n\n<hr><h3><a name=\"lua_isnumber\"><code>lua_isnumber</code></a></h3><p>\n<span class=\"apii\">[-0, +0, <em>-</em>]</span>\n<pre>int lua_isnumber (lua_State *L, int index);</pre>\n\n<p>\nReturns 1 if the value at the given acceptable index is a number\nor a string convertible to a number,\nand 0&nbsp;otherwise.\n\n\n\n\n\n<hr><h3><a name=\"lua_isstring\"><code>lua_isstring</code></a></h3><p>\n<span class=\"apii\">[-0, +0, <em>-</em>]</span>\n<pre>int lua_isstring (lua_State *L, int index);</pre>\n\n<p>\nReturns 1 if the value at the given acceptable index is a string\nor a number (which is always convertible to a string),\nand 0&nbsp;otherwise.\n\n\n\n\n\n<hr><h3><a name=\"lua_istable\"><code>lua_istable</code></a></h3><p>\n<span class=\"apii\">[-0, +0, <em>-</em>]</span>\n<pre>int lua_istable (lua_State *L, int index);</pre>\n\n<p>\nReturns 1 if the value at the given acceptable index is a table,\nand 0&nbsp;otherwise.\n\n\n\n\n\n<hr><h3><a name=\"lua_isthread\"><code>lua_isthread</code></a></h3><p>\n<span class=\"apii\">[-0, +0, <em>-</em>]</span>\n<pre>int lua_isthread (lua_State *L, int index);</pre>\n\n<p>\nReturns 1 if the value at the given acceptable index is a thread,\nand 0&nbsp;otherwise.\n\n\n\n\n\n<hr><h3><a name=\"lua_isuserdata\"><code>lua_isuserdata</code></a></h3><p>\n<span class=\"apii\">[-0, +0, <em>-</em>]</span>\n<pre>int lua_isuserdata (lua_State *L, int index);</pre>\n\n<p>\nReturns 1 if the value at the given acceptable index is a userdata\n(either full or light), and 0&nbsp;otherwise.\n\n\n\n\n\n<hr><h3><a name=\"lua_lessthan\"><code>lua_lessthan</code></a></h3><p>\n<span class=\"apii\">[-0, +0, <em>e</em>]</span>\n<pre>int lua_lessthan (lua_State *L, int index1, int index2);</pre>\n\n<p>\nReturns 1 if the value at acceptable index <code>index1</code> is smaller\nthan the value at acceptable index <code>index2</code>,\nfollowing the semantics of the Lua <code>&lt;</code> operator\n(that is, may call metamethods).\nOtherwise returns&nbsp;0.\nAlso returns&nbsp;0 if any of the indices is non valid.\n\n\n\n\n\n<hr><h3><a name=\"lua_load\"><code>lua_load</code></a></h3><p>\n<span class=\"apii\">[-0, +1, <em>-</em>]</span>\n<pre>int lua_load (lua_State *L,\n              lua_Reader reader,\n              void *data,\n              const char *chunkname);</pre>\n\n<p>\nLoads a Lua chunk.\nIf there are no errors,\n<a href=\"#lua_load\"><code>lua_load</code></a> pushes the compiled chunk as a Lua\nfunction on top of the stack.\nOtherwise, it pushes an error message.\nThe return values of <a href=\"#lua_load\"><code>lua_load</code></a> are:\n\n<ul>\n\n<li><b>0:</b> no errors;</li>\n\n<li><b><a name=\"pdf-LUA_ERRSYNTAX\"><code>LUA_ERRSYNTAX</code></a>:</b>\nsyntax error during pre-compilation;</li>\n\n<li><b><a href=\"#pdf-LUA_ERRMEM\"><code>LUA_ERRMEM</code></a>:</b>\nmemory allocation error.</li>\n\n</ul>\n\n<p>\nThis function only loads a chunk;\nit does not run it.\n\n\n<p>\n<a href=\"#lua_load\"><code>lua_load</code></a> automatically detects whether the chunk is text or binary,\nand loads it accordingly (see program <code>luac</code>).\n\n\n<p>\nThe <a href=\"#lua_load\"><code>lua_load</code></a> function uses a user-supplied <code>reader</code> function\nto read the chunk (see <a href=\"#lua_Reader\"><code>lua_Reader</code></a>).\nThe <code>data</code> argument is an opaque value passed to the reader function.\n\n\n<p>\nThe <code>chunkname</code> argument gives a name to the chunk,\nwhich is used for error messages and in debug information (see <a href=\"#3.8\">&sect;3.8</a>).\n\n\n\n\n\n<hr><h3><a name=\"lua_newstate\"><code>lua_newstate</code></a></h3><p>\n<span class=\"apii\">[-0, +0, <em>-</em>]</span>\n<pre>lua_State *lua_newstate (lua_Alloc f, void *ud);</pre>\n\n<p>\nCreates a new, independent state.\nReturns <code>NULL</code> if cannot create the state\n(due to lack of memory).\nThe argument <code>f</code> is the allocator function;\nLua does all memory allocation for this state through this function.\nThe second argument, <code>ud</code>, is an opaque pointer that Lua\nsimply passes to the allocator in every call.\n\n\n\n\n\n<hr><h3><a name=\"lua_newtable\"><code>lua_newtable</code></a></h3><p>\n<span class=\"apii\">[-0, +1, <em>m</em>]</span>\n<pre>void lua_newtable (lua_State *L);</pre>\n\n<p>\nCreates a new empty table and pushes it onto the stack.\nIt is equivalent to <code>lua_createtable(L, 0, 0)</code>.\n\n\n\n\n\n<hr><h3><a name=\"lua_newthread\"><code>lua_newthread</code></a></h3><p>\n<span class=\"apii\">[-0, +1, <em>m</em>]</span>\n<pre>lua_State *lua_newthread (lua_State *L);</pre>\n\n<p>\nCreates a new thread, pushes it on the stack,\nand returns a pointer to a <a href=\"#lua_State\"><code>lua_State</code></a> that represents this new thread.\nThe new state returned by this function shares with the original state\nall global objects (such as tables),\nbut has an independent execution stack.\n\n\n<p>\nThere is no explicit function to close or to destroy a thread.\nThreads are subject to garbage collection,\nlike any Lua object.\n\n\n\n\n\n<hr><h3><a name=\"lua_newuserdata\"><code>lua_newuserdata</code></a></h3><p>\n<span class=\"apii\">[-0, +1, <em>m</em>]</span>\n<pre>void *lua_newuserdata (lua_State *L, size_t size);</pre>\n\n<p>\nThis function allocates a new block of memory with the given size,\npushes onto the stack a new full userdata with the block address,\nand returns this address.\n\n\n<p>\nUserdata represent C&nbsp;values in Lua.\nA <em>full userdata</em> represents a block of memory.\nIt is an object (like a table):\nyou must create it, it can have its own metatable,\nand you can detect when it is being collected.\nA full userdata is only equal to itself (under raw equality).\n\n\n<p>\nWhen Lua collects a full userdata with a <code>gc</code> metamethod,\nLua calls the metamethod and marks the userdata as finalized.\nWhen this userdata is collected again then\nLua frees its corresponding memory.\n\n\n\n\n\n<hr><h3><a name=\"lua_next\"><code>lua_next</code></a></h3><p>\n<span class=\"apii\">[-1, +(2|0), <em>e</em>]</span>\n<pre>int lua_next (lua_State *L, int index);</pre>\n\n<p>\nPops a key from the stack,\nand pushes a key-value pair from the table at the given index\n(the \"next\" pair after the given key).\nIf there are no more elements in the table,\nthen <a href=\"#lua_next\"><code>lua_next</code></a> returns 0 (and pushes nothing).\n\n\n<p>\nA typical traversal looks like this:\n\n<pre>\n     /* table is in the stack at index 't' */\n     lua_pushnil(L);  /* first key */\n     while (lua_next(L, t) != 0) {\n       /* uses 'key' (at index -2) and 'value' (at index -1) */\n       printf(\"%s - %s\\n\",\n              lua_typename(L, lua_type(L, -2)),\n              lua_typename(L, lua_type(L, -1)));\n       /* removes 'value'; keeps 'key' for next iteration */\n       lua_pop(L, 1);\n     }\n</pre>\n\n<p>\nWhile traversing a table,\ndo not call <a href=\"#lua_tolstring\"><code>lua_tolstring</code></a> directly on a key,\nunless you know that the key is actually a string.\nRecall that <a href=\"#lua_tolstring\"><code>lua_tolstring</code></a> <em>changes</em>\nthe value at the given index;\nthis confuses the next call to <a href=\"#lua_next\"><code>lua_next</code></a>.\n\n\n\n\n\n<hr><h3><a name=\"lua_Number\"><code>lua_Number</code></a></h3>\n<pre>typedef double lua_Number;</pre>\n\n<p>\nThe type of numbers in Lua.\nBy default, it is double, but that can be changed in <code>luaconf.h</code>.\n\n\n<p>\nThrough the configuration file you can change\nLua to operate with another type for numbers (e.g., float or long).\n\n\n\n\n\n<hr><h3><a name=\"lua_objlen\"><code>lua_objlen</code></a></h3><p>\n<span class=\"apii\">[-0, +0, <em>-</em>]</span>\n<pre>size_t lua_objlen (lua_State *L, int index);</pre>\n\n<p>\nReturns the \"length\" of the value at the given acceptable index:\nfor strings, this is the string length;\nfor tables, this is the result of the length operator ('<code>#</code>');\nfor userdata, this is the size of the block of memory allocated\nfor the userdata;\nfor other values, it is&nbsp;0.\n\n\n\n\n\n<hr><h3><a name=\"lua_pcall\"><code>lua_pcall</code></a></h3><p>\n<span class=\"apii\">[-(nargs + 1), +(nresults|1), <em>-</em>]</span>\n<pre>int lua_pcall (lua_State *L, int nargs, int nresults, int errfunc);</pre>\n\n<p>\nCalls a function in protected mode.\n\n\n<p>\nBoth <code>nargs</code> and <code>nresults</code> have the same meaning as\nin <a href=\"#lua_call\"><code>lua_call</code></a>.\nIf there are no errors during the call,\n<a href=\"#lua_pcall\"><code>lua_pcall</code></a> behaves exactly like <a href=\"#lua_call\"><code>lua_call</code></a>.\nHowever, if there is any error,\n<a href=\"#lua_pcall\"><code>lua_pcall</code></a> catches it,\npushes a single value on the stack (the error message),\nand returns an error code.\nLike <a href=\"#lua_call\"><code>lua_call</code></a>,\n<a href=\"#lua_pcall\"><code>lua_pcall</code></a> always removes the function\nand its arguments from the stack.\n\n\n<p>\nIf <code>errfunc</code> is 0,\nthen the error message returned on the stack\nis exactly the original error message.\nOtherwise, <code>errfunc</code> is the stack index of an\n<em>error handler function</em>.\n(In the current implementation, this index cannot be a pseudo-index.)\nIn case of runtime errors,\nthis function will be called with the error message\nand its return value will be the message returned on the stack by <a href=\"#lua_pcall\"><code>lua_pcall</code></a>.\n\n\n<p>\nTypically, the error handler function is used to add more debug\ninformation to the error message, such as a stack traceback.\nSuch information cannot be gathered after the return of <a href=\"#lua_pcall\"><code>lua_pcall</code></a>,\nsince by then the stack has unwound.\n\n\n<p>\nThe <a href=\"#lua_pcall\"><code>lua_pcall</code></a> function returns 0 in case of success\nor one of the following error codes\n(defined in <code>lua.h</code>):\n\n<ul>\n\n<li><b><a name=\"pdf-LUA_ERRRUN\"><code>LUA_ERRRUN</code></a>:</b>\na runtime error.\n</li>\n\n<li><b><a name=\"pdf-LUA_ERRMEM\"><code>LUA_ERRMEM</code></a>:</b>\nmemory allocation error.\nFor such errors, Lua does not call the error handler function.\n</li>\n\n<li><b><a name=\"pdf-LUA_ERRERR\"><code>LUA_ERRERR</code></a>:</b>\nerror while running the error handler function.\n</li>\n\n</ul>\n\n\n\n\n<hr><h3><a name=\"lua_pop\"><code>lua_pop</code></a></h3><p>\n<span class=\"apii\">[-n, +0, <em>-</em>]</span>\n<pre>void lua_pop (lua_State *L, int n);</pre>\n\n<p>\nPops <code>n</code> elements from the stack.\n\n\n\n\n\n<hr><h3><a name=\"lua_pushboolean\"><code>lua_pushboolean</code></a></h3><p>\n<span class=\"apii\">[-0, +1, <em>-</em>]</span>\n<pre>void lua_pushboolean (lua_State *L, int b);</pre>\n\n<p>\nPushes a boolean value with value <code>b</code> onto the stack.\n\n\n\n\n\n<hr><h3><a name=\"lua_pushcclosure\"><code>lua_pushcclosure</code></a></h3><p>\n<span class=\"apii\">[-n, +1, <em>m</em>]</span>\n<pre>void lua_pushcclosure (lua_State *L, lua_CFunction fn, int n);</pre>\n\n<p>\nPushes a new C&nbsp;closure onto the stack.\n\n\n<p>\nWhen a C&nbsp;function is created,\nit is possible to associate some values with it,\nthus creating a C&nbsp;closure (see <a href=\"#3.4\">&sect;3.4</a>);\nthese values are then accessible to the function whenever it is called.\nTo associate values with a C&nbsp;function,\nfirst these values should be pushed onto the stack\n(when there are multiple values, the first value is pushed first).\nThen <a href=\"#lua_pushcclosure\"><code>lua_pushcclosure</code></a>\nis called to create and push the C&nbsp;function onto the stack,\nwith the argument <code>n</code> telling how many values should be\nassociated with the function.\n<a href=\"#lua_pushcclosure\"><code>lua_pushcclosure</code></a> also pops these values from the stack.\n\n\n<p>\nThe maximum value for <code>n</code> is 255.\n\n\n\n\n\n<hr><h3><a name=\"lua_pushcfunction\"><code>lua_pushcfunction</code></a></h3><p>\n<span class=\"apii\">[-0, +1, <em>m</em>]</span>\n<pre>void lua_pushcfunction (lua_State *L, lua_CFunction f);</pre>\n\n<p>\nPushes a C&nbsp;function onto the stack.\nThis function receives a pointer to a C function\nand pushes onto the stack a Lua value of type <code>function</code> that,\nwhen called, invokes the corresponding C&nbsp;function.\n\n\n<p>\nAny function to be registered in Lua must\nfollow the correct protocol to receive its parameters\nand return its results (see <a href=\"#lua_CFunction\"><code>lua_CFunction</code></a>).\n\n\n<p>\n<code>lua_pushcfunction</code> is defined as a macro:\n\n<pre>\n     #define lua_pushcfunction(L,f)  lua_pushcclosure(L,f,0)\n</pre>\n\n\n\n\n<hr><h3><a name=\"lua_pushfstring\"><code>lua_pushfstring</code></a></h3><p>\n<span class=\"apii\">[-0, +1, <em>m</em>]</span>\n<pre>const char *lua_pushfstring (lua_State *L, const char *fmt, ...);</pre>\n\n<p>\nPushes onto the stack a formatted string\nand returns a pointer to this string.\nIt is similar to the C&nbsp;function <code>sprintf</code>,\nbut has some important differences:\n\n<ul>\n\n<li>\nYou do not have to allocate space for the result:\nthe result is a Lua string and Lua takes care of memory allocation\n(and deallocation, through garbage collection).\n</li>\n\n<li>\nThe conversion specifiers are quite restricted.\nThere are no flags, widths, or precisions.\nThe conversion specifiers can only be\n'<code>%%</code>' (inserts a '<code>%</code>' in the string),\n'<code>%s</code>' (inserts a zero-terminated string, with no size restrictions),\n'<code>%f</code>' (inserts a <a href=\"#lua_Number\"><code>lua_Number</code></a>),\n'<code>%p</code>' (inserts a pointer as a hexadecimal numeral),\n'<code>%d</code>' (inserts an <code>int</code>), and\n'<code>%c</code>' (inserts an <code>int</code> as a character).\n</li>\n\n</ul>\n\n\n\n\n<hr><h3><a name=\"lua_pushinteger\"><code>lua_pushinteger</code></a></h3><p>\n<span class=\"apii\">[-0, +1, <em>-</em>]</span>\n<pre>void lua_pushinteger (lua_State *L, lua_Integer n);</pre>\n\n<p>\nPushes a number with value <code>n</code> onto the stack.\n\n\n\n\n\n<hr><h3><a name=\"lua_pushlightuserdata\"><code>lua_pushlightuserdata</code></a></h3><p>\n<span class=\"apii\">[-0, +1, <em>-</em>]</span>\n<pre>void lua_pushlightuserdata (lua_State *L, void *p);</pre>\n\n<p>\nPushes a light userdata onto the stack.\n\n\n<p>\nUserdata represent C&nbsp;values in Lua.\nA <em>light userdata</em> represents a pointer.\nIt is a value (like a number):\nyou do not create it, it has no individual metatable,\nand it is not collected (as it was never created).\nA light userdata is equal to \"any\"\nlight userdata with the same C&nbsp;address.\n\n\n\n\n\n<hr><h3><a name=\"lua_pushliteral\"><code>lua_pushliteral</code></a></h3><p>\n<span class=\"apii\">[-0, +1, <em>m</em>]</span>\n<pre>void lua_pushliteral (lua_State *L, const char *s);</pre>\n\n<p>\nThis macro is equivalent to <a href=\"#lua_pushlstring\"><code>lua_pushlstring</code></a>,\nbut can be used only when <code>s</code> is a literal string.\nIn these cases, it automatically provides the string length.\n\n\n\n\n\n<hr><h3><a name=\"lua_pushlstring\"><code>lua_pushlstring</code></a></h3><p>\n<span class=\"apii\">[-0, +1, <em>m</em>]</span>\n<pre>void lua_pushlstring (lua_State *L, const char *s, size_t len);</pre>\n\n<p>\nPushes the string pointed to by <code>s</code> with size <code>len</code>\nonto the stack.\nLua makes (or reuses) an internal copy of the given string,\nso the memory at <code>s</code> can be freed or reused immediately after\nthe function returns.\nThe string can contain embedded zeros.\n\n\n\n\n\n<hr><h3><a name=\"lua_pushnil\"><code>lua_pushnil</code></a></h3><p>\n<span class=\"apii\">[-0, +1, <em>-</em>]</span>\n<pre>void lua_pushnil (lua_State *L);</pre>\n\n<p>\nPushes a nil value onto the stack.\n\n\n\n\n\n<hr><h3><a name=\"lua_pushnumber\"><code>lua_pushnumber</code></a></h3><p>\n<span class=\"apii\">[-0, +1, <em>-</em>]</span>\n<pre>void lua_pushnumber (lua_State *L, lua_Number n);</pre>\n\n<p>\nPushes a number with value <code>n</code> onto the stack.\n\n\n\n\n\n<hr><h3><a name=\"lua_pushstring\"><code>lua_pushstring</code></a></h3><p>\n<span class=\"apii\">[-0, +1, <em>m</em>]</span>\n<pre>void lua_pushstring (lua_State *L, const char *s);</pre>\n\n<p>\nPushes the zero-terminated string pointed to by <code>s</code>\nonto the stack.\nLua makes (or reuses) an internal copy of the given string,\nso the memory at <code>s</code> can be freed or reused immediately after\nthe function returns.\nThe string cannot contain embedded zeros;\nit is assumed to end at the first zero.\n\n\n\n\n\n<hr><h3><a name=\"lua_pushthread\"><code>lua_pushthread</code></a></h3><p>\n<span class=\"apii\">[-0, +1, <em>-</em>]</span>\n<pre>int lua_pushthread (lua_State *L);</pre>\n\n<p>\nPushes the thread represented by <code>L</code> onto the stack.\nReturns 1 if this thread is the main thread of its state.\n\n\n\n\n\n<hr><h3><a name=\"lua_pushvalue\"><code>lua_pushvalue</code></a></h3><p>\n<span class=\"apii\">[-0, +1, <em>-</em>]</span>\n<pre>void lua_pushvalue (lua_State *L, int index);</pre>\n\n<p>\nPushes a copy of the element at the given valid index\nonto the stack.\n\n\n\n\n\n<hr><h3><a name=\"lua_pushvfstring\"><code>lua_pushvfstring</code></a></h3><p>\n<span class=\"apii\">[-0, +1, <em>m</em>]</span>\n<pre>const char *lua_pushvfstring (lua_State *L,\n                              const char *fmt,\n                              va_list argp);</pre>\n\n<p>\nEquivalent to <a href=\"#lua_pushfstring\"><code>lua_pushfstring</code></a>, except that it receives a <code>va_list</code>\ninstead of a variable number of arguments.\n\n\n\n\n\n<hr><h3><a name=\"lua_rawequal\"><code>lua_rawequal</code></a></h3><p>\n<span class=\"apii\">[-0, +0, <em>-</em>]</span>\n<pre>int lua_rawequal (lua_State *L, int index1, int index2);</pre>\n\n<p>\nReturns 1 if the two values in acceptable indices <code>index1</code> and\n<code>index2</code> are primitively equal\n(that is, without calling metamethods).\nOtherwise returns&nbsp;0.\nAlso returns&nbsp;0 if any of the indices are non valid.\n\n\n\n\n\n<hr><h3><a name=\"lua_rawget\"><code>lua_rawget</code></a></h3><p>\n<span class=\"apii\">[-1, +1, <em>-</em>]</span>\n<pre>void lua_rawget (lua_State *L, int index);</pre>\n\n<p>\nSimilar to <a href=\"#lua_gettable\"><code>lua_gettable</code></a>, but does a raw access\n(i.e., without metamethods).\n\n\n\n\n\n<hr><h3><a name=\"lua_rawgeti\"><code>lua_rawgeti</code></a></h3><p>\n<span class=\"apii\">[-0, +1, <em>-</em>]</span>\n<pre>void lua_rawgeti (lua_State *L, int index, int n);</pre>\n\n<p>\nPushes onto the stack the value <code>t[n]</code>,\nwhere <code>t</code> is the value at the given valid index.\nThe access is raw;\nthat is, it does not invoke metamethods.\n\n\n\n\n\n<hr><h3><a name=\"lua_rawset\"><code>lua_rawset</code></a></h3><p>\n<span class=\"apii\">[-2, +0, <em>m</em>]</span>\n<pre>void lua_rawset (lua_State *L, int index);</pre>\n\n<p>\nSimilar to <a href=\"#lua_settable\"><code>lua_settable</code></a>, but does a raw assignment\n(i.e., without metamethods).\n\n\n\n\n\n<hr><h3><a name=\"lua_rawseti\"><code>lua_rawseti</code></a></h3><p>\n<span class=\"apii\">[-1, +0, <em>m</em>]</span>\n<pre>void lua_rawseti (lua_State *L, int index, int n);</pre>\n\n<p>\nDoes the equivalent of <code>t[n] = v</code>,\nwhere <code>t</code> is the value at the given valid index\nand <code>v</code> is the value at the top of the stack.\n\n\n<p>\nThis function pops the value from the stack.\nThe assignment is raw;\nthat is, it does not invoke metamethods.\n\n\n\n\n\n<hr><h3><a name=\"lua_Reader\"><code>lua_Reader</code></a></h3>\n<pre>typedef const char * (*lua_Reader) (lua_State *L,\n                                    void *data,\n                                    size_t *size);</pre>\n\n<p>\nThe reader function used by <a href=\"#lua_load\"><code>lua_load</code></a>.\nEvery time it needs another piece of the chunk,\n<a href=\"#lua_load\"><code>lua_load</code></a> calls the reader,\npassing along its <code>data</code> parameter.\nThe reader must return a pointer to a block of memory\nwith a new piece of the chunk\nand set <code>size</code> to the block size.\nThe block must exist until the reader function is called again.\nTo signal the end of the chunk,\nthe reader must return <code>NULL</code> or set <code>size</code> to zero.\nThe reader function may return pieces of any size greater than zero.\n\n\n\n\n\n<hr><h3><a name=\"lua_register\"><code>lua_register</code></a></h3><p>\n<span class=\"apii\">[-0, +0, <em>e</em>]</span>\n<pre>void lua_register (lua_State *L,\n                   const char *name,\n                   lua_CFunction f);</pre>\n\n<p>\nSets the C function <code>f</code> as the new value of global <code>name</code>.\nIt is defined as a macro:\n\n<pre>\n     #define lua_register(L,n,f) \\\n            (lua_pushcfunction(L, f), lua_setglobal(L, n))\n</pre>\n\n\n\n\n<hr><h3><a name=\"lua_remove\"><code>lua_remove</code></a></h3><p>\n<span class=\"apii\">[-1, +0, <em>-</em>]</span>\n<pre>void lua_remove (lua_State *L, int index);</pre>\n\n<p>\nRemoves the element at the given valid index,\nshifting down the elements above this index to fill the gap.\nCannot be called with a pseudo-index,\nbecause a pseudo-index is not an actual stack position.\n\n\n\n\n\n<hr><h3><a name=\"lua_replace\"><code>lua_replace</code></a></h3><p>\n<span class=\"apii\">[-1, +0, <em>-</em>]</span>\n<pre>void lua_replace (lua_State *L, int index);</pre>\n\n<p>\nMoves the top element into the given position (and pops it),\nwithout shifting any element\n(therefore replacing the value at the given position).\n\n\n\n\n\n<hr><h3><a name=\"lua_resume\"><code>lua_resume</code></a></h3><p>\n<span class=\"apii\">[-?, +?, <em>-</em>]</span>\n<pre>int lua_resume (lua_State *L, int narg);</pre>\n\n<p>\nStarts and resumes a coroutine in a given thread.\n\n\n<p>\nTo start a coroutine, you first create a new thread\n(see <a href=\"#lua_newthread\"><code>lua_newthread</code></a>);\nthen you push onto its stack the main function plus any arguments;\nthen you call <a href=\"#lua_resume\"><code>lua_resume</code></a>,\nwith <code>narg</code> being the number of arguments.\nThis call returns when the coroutine suspends or finishes its execution.\nWhen it returns, the stack contains all values passed to <a href=\"#lua_yield\"><code>lua_yield</code></a>,\nor all values returned by the body function.\n<a href=\"#lua_resume\"><code>lua_resume</code></a> returns\n<a href=\"#pdf-LUA_YIELD\"><code>LUA_YIELD</code></a> if the coroutine yields,\n0 if the coroutine finishes its execution\nwithout errors,\nor an error code in case of errors (see <a href=\"#lua_pcall\"><code>lua_pcall</code></a>).\nIn case of errors,\nthe stack is not unwound,\nso you can use the debug API over it.\nThe error message is on the top of the stack.\nTo restart a coroutine, you put on its stack only the values to\nbe passed as results from <code>yield</code>,\nand then call <a href=\"#lua_resume\"><code>lua_resume</code></a>.\n\n\n\n\n\n<hr><h3><a name=\"lua_setallocf\"><code>lua_setallocf</code></a></h3><p>\n<span class=\"apii\">[-0, +0, <em>-</em>]</span>\n<pre>void lua_setallocf (lua_State *L, lua_Alloc f, void *ud);</pre>\n\n<p>\nChanges the allocator function of a given state to <code>f</code>\nwith user data <code>ud</code>.\n\n\n\n\n\n<hr><h3><a name=\"lua_setfenv\"><code>lua_setfenv</code></a></h3><p>\n<span class=\"apii\">[-1, +0, <em>-</em>]</span>\n<pre>int lua_setfenv (lua_State *L, int index);</pre>\n\n<p>\nPops a table from the stack and sets it as\nthe new environment for the value at the given index.\nIf the value at the given index is\nneither a function nor a thread nor a userdata,\n<a href=\"#lua_setfenv\"><code>lua_setfenv</code></a> returns 0.\nOtherwise it returns 1.\n\n\n\n\n\n<hr><h3><a name=\"lua_setfield\"><code>lua_setfield</code></a></h3><p>\n<span class=\"apii\">[-1, +0, <em>e</em>]</span>\n<pre>void lua_setfield (lua_State *L, int index, const char *k);</pre>\n\n<p>\nDoes the equivalent to <code>t[k] = v</code>,\nwhere <code>t</code> is the value at the given valid index\nand <code>v</code> is the value at the top of the stack.\n\n\n<p>\nThis function pops the value from the stack.\nAs in Lua, this function may trigger a metamethod\nfor the \"newindex\" event (see <a href=\"#2.8\">&sect;2.8</a>).\n\n\n\n\n\n<hr><h3><a name=\"lua_setglobal\"><code>lua_setglobal</code></a></h3><p>\n<span class=\"apii\">[-1, +0, <em>e</em>]</span>\n<pre>void lua_setglobal (lua_State *L, const char *name);</pre>\n\n<p>\nPops a value from the stack and\nsets it as the new value of global <code>name</code>.\nIt is defined as a macro:\n\n<pre>\n     #define lua_setglobal(L,s)   lua_setfield(L, LUA_GLOBALSINDEX, s)\n</pre>\n\n\n\n\n<hr><h3><a name=\"lua_setmetatable\"><code>lua_setmetatable</code></a></h3><p>\n<span class=\"apii\">[-1, +0, <em>-</em>]</span>\n<pre>int lua_setmetatable (lua_State *L, int index);</pre>\n\n<p>\nPops a table from the stack and\nsets it as the new metatable for the value at the given\nacceptable index.\n\n\n\n\n\n<hr><h3><a name=\"lua_settable\"><code>lua_settable</code></a></h3><p>\n<span class=\"apii\">[-2, +0, <em>e</em>]</span>\n<pre>void lua_settable (lua_State *L, int index);</pre>\n\n<p>\nDoes the equivalent to <code>t[k] = v</code>,\nwhere <code>t</code> is the value at the given valid index,\n<code>v</code> is the value at the top of the stack,\nand <code>k</code> is the value just below the top.\n\n\n<p>\nThis function pops both the key and the value from the stack.\nAs in Lua, this function may trigger a metamethod\nfor the \"newindex\" event (see <a href=\"#2.8\">&sect;2.8</a>).\n\n\n\n\n\n<hr><h3><a name=\"lua_settop\"><code>lua_settop</code></a></h3><p>\n<span class=\"apii\">[-?, +?, <em>-</em>]</span>\n<pre>void lua_settop (lua_State *L, int index);</pre>\n\n<p>\nAccepts any acceptable index, or&nbsp;0,\nand sets the stack top to this index.\nIf the new top is larger than the old one,\nthen the new elements are filled with <b>nil</b>.\nIf <code>index</code> is&nbsp;0, then all stack elements are removed.\n\n\n\n\n\n<hr><h3><a name=\"lua_State\"><code>lua_State</code></a></h3>\n<pre>typedef struct lua_State lua_State;</pre>\n\n<p>\nOpaque structure that keeps the whole state of a Lua interpreter.\nThe Lua library is fully reentrant:\nit has no global variables.\nAll information about a state is kept in this structure.\n\n\n<p>\nA pointer to this state must be passed as the first argument to\nevery function in the library, except to <a href=\"#lua_newstate\"><code>lua_newstate</code></a>,\nwhich creates a Lua state from scratch.\n\n\n\n\n\n<hr><h3><a name=\"lua_status\"><code>lua_status</code></a></h3><p>\n<span class=\"apii\">[-0, +0, <em>-</em>]</span>\n<pre>int lua_status (lua_State *L);</pre>\n\n<p>\nReturns the status of the thread <code>L</code>.\n\n\n<p>\nThe status can be 0 for a normal thread,\nan error code if the thread finished its execution with an error,\nor <a name=\"pdf-LUA_YIELD\"><code>LUA_YIELD</code></a> if the thread is suspended.\n\n\n\n\n\n<hr><h3><a name=\"lua_toboolean\"><code>lua_toboolean</code></a></h3><p>\n<span class=\"apii\">[-0, +0, <em>-</em>]</span>\n<pre>int lua_toboolean (lua_State *L, int index);</pre>\n\n<p>\nConverts the Lua value at the given acceptable index to a C&nbsp;boolean\nvalue (0&nbsp;or&nbsp;1).\nLike all tests in Lua,\n<a href=\"#lua_toboolean\"><code>lua_toboolean</code></a> returns 1 for any Lua value\ndifferent from <b>false</b> and <b>nil</b>;\notherwise it returns 0.\nIt also returns 0 when called with a non-valid index.\n(If you want to accept only actual boolean values,\nuse <a href=\"#lua_isboolean\"><code>lua_isboolean</code></a> to test the value's type.)\n\n\n\n\n\n<hr><h3><a name=\"lua_tocfunction\"><code>lua_tocfunction</code></a></h3><p>\n<span class=\"apii\">[-0, +0, <em>-</em>]</span>\n<pre>lua_CFunction lua_tocfunction (lua_State *L, int index);</pre>\n\n<p>\nConverts a value at the given acceptable index to a C&nbsp;function.\nThat value must be a C&nbsp;function;\notherwise, returns <code>NULL</code>.\n\n\n\n\n\n<hr><h3><a name=\"lua_tointeger\"><code>lua_tointeger</code></a></h3><p>\n<span class=\"apii\">[-0, +0, <em>-</em>]</span>\n<pre>lua_Integer lua_tointeger (lua_State *L, int index);</pre>\n\n<p>\nConverts the Lua value at the given acceptable index\nto the signed integral type <a href=\"#lua_Integer\"><code>lua_Integer</code></a>.\nThe Lua value must be a number or a string convertible to a number\n(see <a href=\"#2.2.1\">&sect;2.2.1</a>);\notherwise, <a href=\"#lua_tointeger\"><code>lua_tointeger</code></a> returns&nbsp;0.\n\n\n<p>\nIf the number is not an integer,\nit is truncated in some non-specified way.\n\n\n\n\n\n<hr><h3><a name=\"lua_tolstring\"><code>lua_tolstring</code></a></h3><p>\n<span class=\"apii\">[-0, +0, <em>m</em>]</span>\n<pre>const char *lua_tolstring (lua_State *L, int index, size_t *len);</pre>\n\n<p>\nConverts the Lua value at the given acceptable index to a C&nbsp;string.\nIf <code>len</code> is not <code>NULL</code>,\nit also sets <code>*len</code> with the string length.\nThe Lua value must be a string or a number;\notherwise, the function returns <code>NULL</code>.\nIf the value is a number,\nthen <a href=\"#lua_tolstring\"><code>lua_tolstring</code></a> also\n<em>changes the actual value in the stack to a string</em>.\n(This change confuses <a href=\"#lua_next\"><code>lua_next</code></a>\nwhen <a href=\"#lua_tolstring\"><code>lua_tolstring</code></a> is applied to keys during a table traversal.)\n\n\n<p>\n<a href=\"#lua_tolstring\"><code>lua_tolstring</code></a> returns a fully aligned pointer\nto a string inside the Lua state.\nThis string always has a zero ('<code>\\0</code>')\nafter its last character (as in&nbsp;C),\nbut can contain other zeros in its body.\nBecause Lua has garbage collection,\nthere is no guarantee that the pointer returned by <a href=\"#lua_tolstring\"><code>lua_tolstring</code></a>\nwill be valid after the corresponding value is removed from the stack.\n\n\n\n\n\n<hr><h3><a name=\"lua_tonumber\"><code>lua_tonumber</code></a></h3><p>\n<span class=\"apii\">[-0, +0, <em>-</em>]</span>\n<pre>lua_Number lua_tonumber (lua_State *L, int index);</pre>\n\n<p>\nConverts the Lua value at the given acceptable index\nto the C&nbsp;type <a href=\"#lua_Number\"><code>lua_Number</code></a> (see <a href=\"#lua_Number\"><code>lua_Number</code></a>).\nThe Lua value must be a number or a string convertible to a number\n(see <a href=\"#2.2.1\">&sect;2.2.1</a>);\notherwise, <a href=\"#lua_tonumber\"><code>lua_tonumber</code></a> returns&nbsp;0.\n\n\n\n\n\n<hr><h3><a name=\"lua_topointer\"><code>lua_topointer</code></a></h3><p>\n<span class=\"apii\">[-0, +0, <em>-</em>]</span>\n<pre>const void *lua_topointer (lua_State *L, int index);</pre>\n\n<p>\nConverts the value at the given acceptable index to a generic\nC&nbsp;pointer (<code>void*</code>).\nThe value can be a userdata, a table, a thread, or a function;\notherwise, <a href=\"#lua_topointer\"><code>lua_topointer</code></a> returns <code>NULL</code>.\nDifferent objects will give different pointers.\nThere is no way to convert the pointer back to its original value.\n\n\n<p>\nTypically this function is used only for debug information.\n\n\n\n\n\n<hr><h3><a name=\"lua_tostring\"><code>lua_tostring</code></a></h3><p>\n<span class=\"apii\">[-0, +0, <em>m</em>]</span>\n<pre>const char *lua_tostring (lua_State *L, int index);</pre>\n\n<p>\nEquivalent to <a href=\"#lua_tolstring\"><code>lua_tolstring</code></a> with <code>len</code> equal to <code>NULL</code>.\n\n\n\n\n\n<hr><h3><a name=\"lua_tothread\"><code>lua_tothread</code></a></h3><p>\n<span class=\"apii\">[-0, +0, <em>-</em>]</span>\n<pre>lua_State *lua_tothread (lua_State *L, int index);</pre>\n\n<p>\nConverts the value at the given acceptable index to a Lua thread\n(represented as <code>lua_State*</code>).\nThis value must be a thread;\notherwise, the function returns <code>NULL</code>.\n\n\n\n\n\n<hr><h3><a name=\"lua_touserdata\"><code>lua_touserdata</code></a></h3><p>\n<span class=\"apii\">[-0, +0, <em>-</em>]</span>\n<pre>void *lua_touserdata (lua_State *L, int index);</pre>\n\n<p>\nIf the value at the given acceptable index is a full userdata,\nreturns its block address.\nIf the value is a light userdata,\nreturns its pointer.\nOtherwise, returns <code>NULL</code>.\n\n\n\n\n\n<hr><h3><a name=\"lua_type\"><code>lua_type</code></a></h3><p>\n<span class=\"apii\">[-0, +0, <em>-</em>]</span>\n<pre>int lua_type (lua_State *L, int index);</pre>\n\n<p>\nReturns the type of the value in the given acceptable index,\nor <code>LUA_TNONE</code> for a non-valid index\n(that is, an index to an \"empty\" stack position).\nThe types returned by <a href=\"#lua_type\"><code>lua_type</code></a> are coded by the following constants\ndefined in <code>lua.h</code>:\n<code>LUA_TNIL</code>,\n<code>LUA_TNUMBER</code>,\n<code>LUA_TBOOLEAN</code>,\n<code>LUA_TSTRING</code>,\n<code>LUA_TTABLE</code>,\n<code>LUA_TFUNCTION</code>,\n<code>LUA_TUSERDATA</code>,\n<code>LUA_TTHREAD</code>,\nand\n<code>LUA_TLIGHTUSERDATA</code>.\n\n\n\n\n\n<hr><h3><a name=\"lua_typename\"><code>lua_typename</code></a></h3><p>\n<span class=\"apii\">[-0, +0, <em>-</em>]</span>\n<pre>const char *lua_typename  (lua_State *L, int tp);</pre>\n\n<p>\nReturns the name of the type encoded by the value <code>tp</code>,\nwhich must be one the values returned by <a href=\"#lua_type\"><code>lua_type</code></a>.\n\n\n\n\n\n<hr><h3><a name=\"lua_Writer\"><code>lua_Writer</code></a></h3>\n<pre>typedef int (*lua_Writer) (lua_State *L,\n                           const void* p,\n                           size_t sz,\n                           void* ud);</pre>\n\n<p>\nThe type of the writer function used by <a href=\"#lua_dump\"><code>lua_dump</code></a>.\nEvery time it produces another piece of chunk,\n<a href=\"#lua_dump\"><code>lua_dump</code></a> calls the writer,\npassing along the buffer to be written (<code>p</code>),\nits size (<code>sz</code>),\nand the <code>data</code> parameter supplied to <a href=\"#lua_dump\"><code>lua_dump</code></a>.\n\n\n<p>\nThe writer returns an error code:\n0&nbsp;means no errors;\nany other value means an error and stops <a href=\"#lua_dump\"><code>lua_dump</code></a> from\ncalling the writer again.\n\n\n\n\n\n<hr><h3><a name=\"lua_xmove\"><code>lua_xmove</code></a></h3><p>\n<span class=\"apii\">[-?, +?, <em>-</em>]</span>\n<pre>void lua_xmove (lua_State *from, lua_State *to, int n);</pre>\n\n<p>\nExchange values between different threads of the <em>same</em> global state.\n\n\n<p>\nThis function pops <code>n</code> values from the stack <code>from</code>,\nand pushes them onto the stack <code>to</code>.\n\n\n\n\n\n<hr><h3><a name=\"lua_yield\"><code>lua_yield</code></a></h3><p>\n<span class=\"apii\">[-?, +?, <em>-</em>]</span>\n<pre>int lua_yield  (lua_State *L, int nresults);</pre>\n\n<p>\nYields a coroutine.\n\n\n<p>\nThis function should only be called as the\nreturn expression of a C&nbsp;function, as follows:\n\n<pre>\n     return lua_yield (L, nresults);\n</pre><p>\nWhen a C&nbsp;function calls <a href=\"#lua_yield\"><code>lua_yield</code></a> in that way,\nthe running coroutine suspends its execution,\nand the call to <a href=\"#lua_resume\"><code>lua_resume</code></a> that started this coroutine returns.\nThe parameter <code>nresults</code> is the number of values from the stack\nthat are passed as results to <a href=\"#lua_resume\"><code>lua_resume</code></a>.\n\n\n\n\n\n\n\n<h2>3.8 - <a name=\"3.8\">The Debug Interface</a></h2>\n\n<p>\nLua has no built-in debugging facilities.\nInstead, it offers a special interface\nby means of functions and <em>hooks</em>.\nThis interface allows the construction of different\nkinds of debuggers, profilers, and other tools\nthat need \"inside information\" from the interpreter.\n\n\n\n<hr><h3><a name=\"lua_Debug\"><code>lua_Debug</code></a></h3>\n<pre>typedef struct lua_Debug {\n  int event;\n  const char *name;           /* (n) */\n  const char *namewhat;       /* (n) */\n  const char *what;           /* (S) */\n  const char *source;         /* (S) */\n  int currentline;            /* (l) */\n  int nups;                   /* (u) number of upvalues */\n  int linedefined;            /* (S) */\n  int lastlinedefined;        /* (S) */\n  char short_src[LUA_IDSIZE]; /* (S) */\n  /* private part */\n  <em>other fields</em>\n} lua_Debug;</pre>\n\n<p>\nA structure used to carry different pieces of\ninformation about an active function.\n<a href=\"#lua_getstack\"><code>lua_getstack</code></a> fills only the private part\nof this structure, for later use.\nTo fill the other fields of <a href=\"#lua_Debug\"><code>lua_Debug</code></a> with useful information,\ncall <a href=\"#lua_getinfo\"><code>lua_getinfo</code></a>.\n\n\n<p>\nThe fields of <a href=\"#lua_Debug\"><code>lua_Debug</code></a> have the following meaning:\n\n<ul>\n\n<li><b><code>source</code>:</b>\nIf the function was defined in a string,\nthen <code>source</code> is that string.\nIf the function was defined in a file,\nthen <code>source</code> starts with a '<code>@</code>' followed by the file name.\n</li>\n\n<li><b><code>short_src</code>:</b>\na \"printable\" version of <code>source</code>, to be used in error messages.\n</li>\n\n<li><b><code>linedefined</code>:</b>\nthe line number where the definition of the function starts.\n</li>\n\n<li><b><code>lastlinedefined</code>:</b>\nthe line number where the definition of the function ends.\n</li>\n\n<li><b><code>what</code>:</b>\nthe string <code>\"Lua\"</code> if the function is a Lua function,\n<code>\"C\"</code> if it is a C&nbsp;function,\n<code>\"main\"</code> if it is the main part of a chunk,\nand <code>\"tail\"</code> if it was a function that did a tail call.\nIn the latter case,\nLua has no other information about the function.\n</li>\n\n<li><b><code>currentline</code>:</b>\nthe current line where the given function is executing.\nWhen no line information is available,\n<code>currentline</code> is set to -1.\n</li>\n\n<li><b><code>name</code>:</b>\na reasonable name for the given function.\nBecause functions in Lua are first-class values,\nthey do not have a fixed name:\nsome functions can be the value of multiple global variables,\nwhile others can be stored only in a table field.\nThe <code>lua_getinfo</code> function checks how the function was\ncalled to find a suitable name.\nIf it cannot find a name,\nthen <code>name</code> is set to <code>NULL</code>.\n</li>\n\n<li><b><code>namewhat</code>:</b>\nexplains the <code>name</code> field.\nThe value of <code>namewhat</code> can be\n<code>\"global\"</code>, <code>\"local\"</code>, <code>\"method\"</code>,\n<code>\"field\"</code>, <code>\"upvalue\"</code>, or <code>\"\"</code> (the empty string),\naccording to how the function was called.\n(Lua uses the empty string when no other option seems to apply.)\n</li>\n\n<li><b><code>nups</code>:</b>\nthe number of upvalues of the function.\n</li>\n\n</ul>\n\n\n\n\n<hr><h3><a name=\"lua_gethook\"><code>lua_gethook</code></a></h3><p>\n<span class=\"apii\">[-0, +0, <em>-</em>]</span>\n<pre>lua_Hook lua_gethook (lua_State *L);</pre>\n\n<p>\nReturns the current hook function.\n\n\n\n\n\n<hr><h3><a name=\"lua_gethookcount\"><code>lua_gethookcount</code></a></h3><p>\n<span class=\"apii\">[-0, +0, <em>-</em>]</span>\n<pre>int lua_gethookcount (lua_State *L);</pre>\n\n<p>\nReturns the current hook count.\n\n\n\n\n\n<hr><h3><a name=\"lua_gethookmask\"><code>lua_gethookmask</code></a></h3><p>\n<span class=\"apii\">[-0, +0, <em>-</em>]</span>\n<pre>int lua_gethookmask (lua_State *L);</pre>\n\n<p>\nReturns the current hook mask.\n\n\n\n\n\n<hr><h3><a name=\"lua_getinfo\"><code>lua_getinfo</code></a></h3><p>\n<span class=\"apii\">[-(0|1), +(0|1|2), <em>m</em>]</span>\n<pre>int lua_getinfo (lua_State *L, const char *what, lua_Debug *ar);</pre>\n\n<p>\nReturns information about a specific function or function invocation.\n\n\n<p>\nTo get information about a function invocation,\nthe parameter <code>ar</code> must be a valid activation record that was\nfilled by a previous call to <a href=\"#lua_getstack\"><code>lua_getstack</code></a> or\ngiven as argument to a hook (see <a href=\"#lua_Hook\"><code>lua_Hook</code></a>).\n\n\n<p>\nTo get information about a function you push it onto the stack\nand start the <code>what</code> string with the character '<code>&gt;</code>'.\n(In that case,\n<code>lua_getinfo</code> pops the function in the top of the stack.)\nFor instance, to know in which line a function <code>f</code> was defined,\nyou can write the following code:\n\n<pre>\n     lua_Debug ar;\n     lua_getfield(L, LUA_GLOBALSINDEX, \"f\");  /* get global 'f' */\n     lua_getinfo(L, \"&gt;S\", &amp;ar);\n     printf(\"%d\\n\", ar.linedefined);\n</pre>\n\n<p>\nEach character in the string <code>what</code>\nselects some fields of the structure <code>ar</code> to be filled or\na value to be pushed on the stack:\n\n<ul>\n\n<li><b>'<code>n</code>':</b> fills in the field <code>name</code> and <code>namewhat</code>;\n</li>\n\n<li><b>'<code>S</code>':</b>\nfills in the fields <code>source</code>, <code>short_src</code>,\n<code>linedefined</code>, <code>lastlinedefined</code>, and <code>what</code>;\n</li>\n\n<li><b>'<code>l</code>':</b> fills in the field <code>currentline</code>;\n</li>\n\n<li><b>'<code>u</code>':</b> fills in the field <code>nups</code>;\n</li>\n\n<li><b>'<code>f</code>':</b>\npushes onto the stack the function that is\nrunning at the given level;\n</li>\n\n<li><b>'<code>L</code>':</b>\npushes onto the stack a table whose indices are the\nnumbers of the lines that are valid on the function.\n(A <em>valid line</em> is a line with some associated code,\nthat is, a line where you can put a break point.\nNon-valid lines include empty lines and comments.)\n</li>\n\n</ul>\n\n<p>\nThis function returns 0 on error\n(for instance, an invalid option in <code>what</code>).\n\n\n\n\n\n<hr><h3><a name=\"lua_getlocal\"><code>lua_getlocal</code></a></h3><p>\n<span class=\"apii\">[-0, +(0|1), <em>-</em>]</span>\n<pre>const char *lua_getlocal (lua_State *L, lua_Debug *ar, int n);</pre>\n\n<p>\nGets information about a local variable of a given activation record.\nThe parameter <code>ar</code> must be a valid activation record that was\nfilled by a previous call to <a href=\"#lua_getstack\"><code>lua_getstack</code></a> or\ngiven as argument to a hook (see <a href=\"#lua_Hook\"><code>lua_Hook</code></a>).\nThe index <code>n</code> selects which local variable to inspect\n(1 is the first parameter or active local variable, and so on,\nuntil the last active local variable).\n<a href=\"#lua_getlocal\"><code>lua_getlocal</code></a> pushes the variable's value onto the stack\nand returns its name.\n\n\n<p>\nVariable names starting with '<code>(</code>' (open parentheses)\nrepresent internal variables\n(loop control variables, temporaries, and C&nbsp;function locals).\n\n\n<p>\nReturns <code>NULL</code> (and pushes nothing)\nwhen the index is greater than\nthe number of active local variables.\n\n\n\n\n\n<hr><h3><a name=\"lua_getstack\"><code>lua_getstack</code></a></h3><p>\n<span class=\"apii\">[-0, +0, <em>-</em>]</span>\n<pre>int lua_getstack (lua_State *L, int level, lua_Debug *ar);</pre>\n\n<p>\nGet information about the interpreter runtime stack.\n\n\n<p>\nThis function fills parts of a <a href=\"#lua_Debug\"><code>lua_Debug</code></a> structure with\nan identification of the <em>activation record</em>\nof the function executing at a given level.\nLevel&nbsp;0 is the current running function,\nwhereas level <em>n+1</em> is the function that has called level <em>n</em>.\nWhen there are no errors, <a href=\"#lua_getstack\"><code>lua_getstack</code></a> returns 1;\nwhen called with a level greater than the stack depth,\nit returns 0.\n\n\n\n\n\n<hr><h3><a name=\"lua_getupvalue\"><code>lua_getupvalue</code></a></h3><p>\n<span class=\"apii\">[-0, +(0|1), <em>-</em>]</span>\n<pre>const char *lua_getupvalue (lua_State *L, int funcindex, int n);</pre>\n\n<p>\nGets information about a closure's upvalue.\n(For Lua functions,\nupvalues are the external local variables that the function uses,\nand that are consequently included in its closure.)\n<a href=\"#lua_getupvalue\"><code>lua_getupvalue</code></a> gets the index <code>n</code> of an upvalue,\npushes the upvalue's value onto the stack,\nand returns its name.\n<code>funcindex</code> points to the closure in the stack.\n(Upvalues have no particular order,\nas they are active through the whole function.\nSo, they are numbered in an arbitrary order.)\n\n\n<p>\nReturns <code>NULL</code> (and pushes nothing)\nwhen the index is greater than the number of upvalues.\nFor C&nbsp;functions, this function uses the empty string <code>\"\"</code>\nas a name for all upvalues.\n\n\n\n\n\n<hr><h3><a name=\"lua_Hook\"><code>lua_Hook</code></a></h3>\n<pre>typedef void (*lua_Hook) (lua_State *L, lua_Debug *ar);</pre>\n\n<p>\nType for debugging hook functions.\n\n\n<p>\nWhenever a hook is called, its <code>ar</code> argument has its field\n<code>event</code> set to the specific event that triggered the hook.\nLua identifies these events with the following constants:\n<a name=\"pdf-LUA_HOOKCALL\"><code>LUA_HOOKCALL</code></a>, <a name=\"pdf-LUA_HOOKRET\"><code>LUA_HOOKRET</code></a>,\n<a name=\"pdf-LUA_HOOKTAILRET\"><code>LUA_HOOKTAILRET</code></a>, <a name=\"pdf-LUA_HOOKLINE\"><code>LUA_HOOKLINE</code></a>,\nand <a name=\"pdf-LUA_HOOKCOUNT\"><code>LUA_HOOKCOUNT</code></a>.\nMoreover, for line events, the field <code>currentline</code> is also set.\nTo get the value of any other field in <code>ar</code>,\nthe hook must call <a href=\"#lua_getinfo\"><code>lua_getinfo</code></a>.\nFor return events, <code>event</code> can be <code>LUA_HOOKRET</code>,\nthe normal value, or <code>LUA_HOOKTAILRET</code>.\nIn the latter case, Lua is simulating a return from\na function that did a tail call;\nin this case, it is useless to call <a href=\"#lua_getinfo\"><code>lua_getinfo</code></a>.\n\n\n<p>\nWhile Lua is running a hook, it disables other calls to hooks.\nTherefore, if a hook calls back Lua to execute a function or a chunk,\nthis execution occurs without any calls to hooks.\n\n\n\n\n\n<hr><h3><a name=\"lua_sethook\"><code>lua_sethook</code></a></h3><p>\n<span class=\"apii\">[-0, +0, <em>-</em>]</span>\n<pre>int lua_sethook (lua_State *L, lua_Hook f, int mask, int count);</pre>\n\n<p>\nSets the debugging hook function.\n\n\n<p>\nArgument <code>f</code> is the hook function.\n<code>mask</code> specifies on which events the hook will be called:\nit is formed by a bitwise or of the constants\n<a name=\"pdf-LUA_MASKCALL\"><code>LUA_MASKCALL</code></a>,\n<a name=\"pdf-LUA_MASKRET\"><code>LUA_MASKRET</code></a>,\n<a name=\"pdf-LUA_MASKLINE\"><code>LUA_MASKLINE</code></a>,\nand <a name=\"pdf-LUA_MASKCOUNT\"><code>LUA_MASKCOUNT</code></a>.\nThe <code>count</code> argument is only meaningful when the mask\nincludes <code>LUA_MASKCOUNT</code>.\nFor each event, the hook is called as explained below:\n\n<ul>\n\n<li><b>The call hook:</b> is called when the interpreter calls a function.\nThe hook is called just after Lua enters the new function,\nbefore the function gets its arguments.\n</li>\n\n<li><b>The return hook:</b> is called when the interpreter returns from a function.\nThe hook is called just before Lua leaves the function.\nYou have no access to the values to be returned by the function.\n</li>\n\n<li><b>The line hook:</b> is called when the interpreter is about to\nstart the execution of a new line of code,\nor when it jumps back in the code (even to the same line).\n(This event only happens while Lua is executing a Lua function.)\n</li>\n\n<li><b>The count hook:</b> is called after the interpreter executes every\n<code>count</code> instructions.\n(This event only happens while Lua is executing a Lua function.)\n</li>\n\n</ul>\n\n<p>\nA hook is disabled by setting <code>mask</code> to zero.\n\n\n\n\n\n<hr><h3><a name=\"lua_setlocal\"><code>lua_setlocal</code></a></h3><p>\n<span class=\"apii\">[-(0|1), +0, <em>-</em>]</span>\n<pre>const char *lua_setlocal (lua_State *L, lua_Debug *ar, int n);</pre>\n\n<p>\nSets the value of a local variable of a given activation record.\nParameters <code>ar</code> and <code>n</code> are as in <a href=\"#lua_getlocal\"><code>lua_getlocal</code></a>\n(see <a href=\"#lua_getlocal\"><code>lua_getlocal</code></a>).\n<a href=\"#lua_setlocal\"><code>lua_setlocal</code></a> assigns the value at the top of the stack\nto the variable and returns its name.\nIt also pops the value from the stack.\n\n\n<p>\nReturns <code>NULL</code> (and pops nothing)\nwhen the index is greater than\nthe number of active local variables.\n\n\n\n\n\n<hr><h3><a name=\"lua_setupvalue\"><code>lua_setupvalue</code></a></h3><p>\n<span class=\"apii\">[-(0|1), +0, <em>-</em>]</span>\n<pre>const char *lua_setupvalue (lua_State *L, int funcindex, int n);</pre>\n\n<p>\nSets the value of a closure's upvalue.\nIt assigns the value at the top of the stack\nto the upvalue and returns its name.\nIt also pops the value from the stack.\nParameters <code>funcindex</code> and <code>n</code> are as in the <a href=\"#lua_getupvalue\"><code>lua_getupvalue</code></a>\n(see <a href=\"#lua_getupvalue\"><code>lua_getupvalue</code></a>).\n\n\n<p>\nReturns <code>NULL</code> (and pops nothing)\nwhen the index is greater than the number of upvalues.\n\n\n\n\n\n\n\n<h1>4 - <a name=\"4\">The Auxiliary Library</a></h1>\n\n<p>\n\nThe <em>auxiliary library</em> provides several convenient functions\nto interface C with Lua.\nWhile the basic API provides the primitive functions for all \ninteractions between C and Lua,\nthe auxiliary library provides higher-level functions for some\ncommon tasks.\n\n\n<p>\nAll functions from the auxiliary library\nare defined in header file <code>lauxlib.h</code> and\nhave a prefix <code>luaL_</code>.\n\n\n<p>\nAll functions in the auxiliary library are built on\ntop of the basic API,\nand so they provide nothing that cannot be done with this API.\n\n\n<p>\nSeveral functions in the auxiliary library are used to\ncheck C&nbsp;function arguments.\nTheir names are always <code>luaL_check*</code> or <code>luaL_opt*</code>.\nAll of these functions throw an error if the check is not satisfied.\nBecause the error message is formatted for arguments\n(e.g., \"<code>bad argument #1</code>\"),\nyou should not use these functions for other stack values.\n\n\n\n<h2>4.1 - <a name=\"4.1\">Functions and Types</a></h2>\n\n<p>\nHere we list all functions and types from the auxiliary library\nin alphabetical order.\n\n\n\n<hr><h3><a name=\"luaL_addchar\"><code>luaL_addchar</code></a></h3><p>\n<span class=\"apii\">[-0, +0, <em>m</em>]</span>\n<pre>void luaL_addchar (luaL_Buffer *B, char c);</pre>\n\n<p>\nAdds the character <code>c</code> to the buffer <code>B</code>\n(see <a href=\"#luaL_Buffer\"><code>luaL_Buffer</code></a>).\n\n\n\n\n\n<hr><h3><a name=\"luaL_addlstring\"><code>luaL_addlstring</code></a></h3><p>\n<span class=\"apii\">[-0, +0, <em>m</em>]</span>\n<pre>void luaL_addlstring (luaL_Buffer *B, const char *s, size_t l);</pre>\n\n<p>\nAdds the string pointed to by <code>s</code> with length <code>l</code> to\nthe buffer <code>B</code>\n(see <a href=\"#luaL_Buffer\"><code>luaL_Buffer</code></a>).\nThe string may contain embedded zeros.\n\n\n\n\n\n<hr><h3><a name=\"luaL_addsize\"><code>luaL_addsize</code></a></h3><p>\n<span class=\"apii\">[-0, +0, <em>m</em>]</span>\n<pre>void luaL_addsize (luaL_Buffer *B, size_t n);</pre>\n\n<p>\nAdds to the buffer <code>B</code> (see <a href=\"#luaL_Buffer\"><code>luaL_Buffer</code></a>)\na string of length <code>n</code> previously copied to the\nbuffer area (see <a href=\"#luaL_prepbuffer\"><code>luaL_prepbuffer</code></a>).\n\n\n\n\n\n<hr><h3><a name=\"luaL_addstring\"><code>luaL_addstring</code></a></h3><p>\n<span class=\"apii\">[-0, +0, <em>m</em>]</span>\n<pre>void luaL_addstring (luaL_Buffer *B, const char *s);</pre>\n\n<p>\nAdds the zero-terminated string pointed to by <code>s</code>\nto the buffer <code>B</code>\n(see <a href=\"#luaL_Buffer\"><code>luaL_Buffer</code></a>).\nThe string may not contain embedded zeros.\n\n\n\n\n\n<hr><h3><a name=\"luaL_addvalue\"><code>luaL_addvalue</code></a></h3><p>\n<span class=\"apii\">[-1, +0, <em>m</em>]</span>\n<pre>void luaL_addvalue (luaL_Buffer *B);</pre>\n\n<p>\nAdds the value at the top of the stack\nto the buffer <code>B</code>\n(see <a href=\"#luaL_Buffer\"><code>luaL_Buffer</code></a>).\nPops the value.\n\n\n<p>\nThis is the only function on string buffers that can (and must)\nbe called with an extra element on the stack,\nwhich is the value to be added to the buffer.\n\n\n\n\n\n<hr><h3><a name=\"luaL_argcheck\"><code>luaL_argcheck</code></a></h3><p>\n<span class=\"apii\">[-0, +0, <em>v</em>]</span>\n<pre>void luaL_argcheck (lua_State *L,\n                    int cond,\n                    int narg,\n                    const char *extramsg);</pre>\n\n<p>\nChecks whether <code>cond</code> is true.\nIf not, raises an error with the following message,\nwhere <code>func</code> is retrieved from the call stack:\n\n<pre>\n     bad argument #&lt;narg&gt; to &lt;func&gt; (&lt;extramsg&gt;)\n</pre>\n\n\n\n\n<hr><h3><a name=\"luaL_argerror\"><code>luaL_argerror</code></a></h3><p>\n<span class=\"apii\">[-0, +0, <em>v</em>]</span>\n<pre>int luaL_argerror (lua_State *L, int narg, const char *extramsg);</pre>\n\n<p>\nRaises an error with the following message,\nwhere <code>func</code> is retrieved from the call stack:\n\n<pre>\n     bad argument #&lt;narg&gt; to &lt;func&gt; (&lt;extramsg&gt;)\n</pre>\n\n<p>\nThis function never returns,\nbut it is an idiom to use it in C&nbsp;functions\nas <code>return luaL_argerror(<em>args</em>)</code>.\n\n\n\n\n\n<hr><h3><a name=\"luaL_Buffer\"><code>luaL_Buffer</code></a></h3>\n<pre>typedef struct luaL_Buffer luaL_Buffer;</pre>\n\n<p>\nType for a <em>string buffer</em>.\n\n\n<p>\nA string buffer allows C&nbsp;code to build Lua strings piecemeal.\nIts pattern of use is as follows:\n\n<ul>\n\n<li>First you declare a variable <code>b</code> of type <a href=\"#luaL_Buffer\"><code>luaL_Buffer</code></a>.</li>\n\n<li>Then you initialize it with a call <code>luaL_buffinit(L, &amp;b)</code>.</li>\n\n<li>\nThen you add string pieces to the buffer calling any of\nthe <code>luaL_add*</code> functions.\n</li>\n\n<li>\nYou finish by calling <code>luaL_pushresult(&amp;b)</code>.\nThis call leaves the final string on the top of the stack.\n</li>\n\n</ul>\n\n<p>\nDuring its normal operation,\na string buffer uses a variable number of stack slots.\nSo, while using a buffer, you cannot assume that you know where\nthe top of the stack is.\nYou can use the stack between successive calls to buffer operations\nas long as that use is balanced;\nthat is,\nwhen you call a buffer operation,\nthe stack is at the same level\nit was immediately after the previous buffer operation.\n(The only exception to this rule is <a href=\"#luaL_addvalue\"><code>luaL_addvalue</code></a>.)\nAfter calling <a href=\"#luaL_pushresult\"><code>luaL_pushresult</code></a> the stack is back to its\nlevel when the buffer was initialized,\nplus the final string on its top.\n\n\n\n\n\n<hr><h3><a name=\"luaL_buffinit\"><code>luaL_buffinit</code></a></h3><p>\n<span class=\"apii\">[-0, +0, <em>-</em>]</span>\n<pre>void luaL_buffinit (lua_State *L, luaL_Buffer *B);</pre>\n\n<p>\nInitializes a buffer <code>B</code>.\nThis function does not allocate any space;\nthe buffer must be declared as a variable\n(see <a href=\"#luaL_Buffer\"><code>luaL_Buffer</code></a>).\n\n\n\n\n\n<hr><h3><a name=\"luaL_callmeta\"><code>luaL_callmeta</code></a></h3><p>\n<span class=\"apii\">[-0, +(0|1), <em>e</em>]</span>\n<pre>int luaL_callmeta (lua_State *L, int obj, const char *e);</pre>\n\n<p>\nCalls a metamethod.\n\n\n<p>\nIf the object at index <code>obj</code> has a metatable and this\nmetatable has a field <code>e</code>,\nthis function calls this field and passes the object as its only argument.\nIn this case this function returns 1 and pushes onto the\nstack the value returned by the call.\nIf there is no metatable or no metamethod,\nthis function returns 0 (without pushing any value on the stack).\n\n\n\n\n\n<hr><h3><a name=\"luaL_checkany\"><code>luaL_checkany</code></a></h3><p>\n<span class=\"apii\">[-0, +0, <em>v</em>]</span>\n<pre>void luaL_checkany (lua_State *L, int narg);</pre>\n\n<p>\nChecks whether the function has an argument\nof any type (including <b>nil</b>) at position <code>narg</code>.\n\n\n\n\n\n<hr><h3><a name=\"luaL_checkint\"><code>luaL_checkint</code></a></h3><p>\n<span class=\"apii\">[-0, +0, <em>v</em>]</span>\n<pre>int luaL_checkint (lua_State *L, int narg);</pre>\n\n<p>\nChecks whether the function argument <code>narg</code> is a number\nand returns this number cast to an <code>int</code>.\n\n\n\n\n\n<hr><h3><a name=\"luaL_checkinteger\"><code>luaL_checkinteger</code></a></h3><p>\n<span class=\"apii\">[-0, +0, <em>v</em>]</span>\n<pre>lua_Integer luaL_checkinteger (lua_State *L, int narg);</pre>\n\n<p>\nChecks whether the function argument <code>narg</code> is a number\nand returns this number cast to a <a href=\"#lua_Integer\"><code>lua_Integer</code></a>.\n\n\n\n\n\n<hr><h3><a name=\"luaL_checklong\"><code>luaL_checklong</code></a></h3><p>\n<span class=\"apii\">[-0, +0, <em>v</em>]</span>\n<pre>long luaL_checklong (lua_State *L, int narg);</pre>\n\n<p>\nChecks whether the function argument <code>narg</code> is a number\nand returns this number cast to a <code>long</code>.\n\n\n\n\n\n<hr><h3><a name=\"luaL_checklstring\"><code>luaL_checklstring</code></a></h3><p>\n<span class=\"apii\">[-0, +0, <em>v</em>]</span>\n<pre>const char *luaL_checklstring (lua_State *L, int narg, size_t *l);</pre>\n\n<p>\nChecks whether the function argument <code>narg</code> is a string\nand returns this string;\nif <code>l</code> is not <code>NULL</code> fills <code>*l</code>\nwith the string's length.\n\n\n<p>\nThis function uses <a href=\"#lua_tolstring\"><code>lua_tolstring</code></a> to get its result,\nso all conversions and caveats of that function apply here.\n\n\n\n\n\n<hr><h3><a name=\"luaL_checknumber\"><code>luaL_checknumber</code></a></h3><p>\n<span class=\"apii\">[-0, +0, <em>v</em>]</span>\n<pre>lua_Number luaL_checknumber (lua_State *L, int narg);</pre>\n\n<p>\nChecks whether the function argument <code>narg</code> is a number\nand returns this number.\n\n\n\n\n\n<hr><h3><a name=\"luaL_checkoption\"><code>luaL_checkoption</code></a></h3><p>\n<span class=\"apii\">[-0, +0, <em>v</em>]</span>\n<pre>int luaL_checkoption (lua_State *L,\n                      int narg,\n                      const char *def,\n                      const char *const lst[]);</pre>\n\n<p>\nChecks whether the function argument <code>narg</code> is a string and\nsearches for this string in the array <code>lst</code>\n(which must be NULL-terminated).\nReturns the index in the array where the string was found.\nRaises an error if the argument is not a string or\nif the string cannot be found.\n\n\n<p>\nIf <code>def</code> is not <code>NULL</code>,\nthe function uses <code>def</code> as a default value when\nthere is no argument <code>narg</code> or if this argument is <b>nil</b>.\n\n\n<p>\nThis is a useful function for mapping strings to C&nbsp;enums.\n(The usual convention in Lua libraries is\nto use strings instead of numbers to select options.)\n\n\n\n\n\n<hr><h3><a name=\"luaL_checkstack\"><code>luaL_checkstack</code></a></h3><p>\n<span class=\"apii\">[-0, +0, <em>v</em>]</span>\n<pre>void luaL_checkstack (lua_State *L, int sz, const char *msg);</pre>\n\n<p>\nGrows the stack size to <code>top + sz</code> elements,\nraising an error if the stack cannot grow to that size.\n<code>msg</code> is an additional text to go into the error message.\n\n\n\n\n\n<hr><h3><a name=\"luaL_checkstring\"><code>luaL_checkstring</code></a></h3><p>\n<span class=\"apii\">[-0, +0, <em>v</em>]</span>\n<pre>const char *luaL_checkstring (lua_State *L, int narg);</pre>\n\n<p>\nChecks whether the function argument <code>narg</code> is a string\nand returns this string.\n\n\n<p>\nThis function uses <a href=\"#lua_tolstring\"><code>lua_tolstring</code></a> to get its result,\nso all conversions and caveats of that function apply here.\n\n\n\n\n\n<hr><h3><a name=\"luaL_checktype\"><code>luaL_checktype</code></a></h3><p>\n<span class=\"apii\">[-0, +0, <em>v</em>]</span>\n<pre>void luaL_checktype (lua_State *L, int narg, int t);</pre>\n\n<p>\nChecks whether the function argument <code>narg</code> has type <code>t</code>.\nSee <a href=\"#lua_type\"><code>lua_type</code></a> for the encoding of types for <code>t</code>.\n\n\n\n\n\n<hr><h3><a name=\"luaL_checkudata\"><code>luaL_checkudata</code></a></h3><p>\n<span class=\"apii\">[-0, +0, <em>v</em>]</span>\n<pre>void *luaL_checkudata (lua_State *L, int narg, const char *tname);</pre>\n\n<p>\nChecks whether the function argument <code>narg</code> is a userdata\nof the type <code>tname</code> (see <a href=\"#luaL_newmetatable\"><code>luaL_newmetatable</code></a>).\n\n\n\n\n\n<hr><h3><a name=\"luaL_dofile\"><code>luaL_dofile</code></a></h3><p>\n<span class=\"apii\">[-0, +?, <em>m</em>]</span>\n<pre>int luaL_dofile (lua_State *L, const char *filename);</pre>\n\n<p>\nLoads and runs the given file.\nIt is defined as the following macro:\n\n<pre>\n     (luaL_loadfile(L, filename) || lua_pcall(L, 0, LUA_MULTRET, 0))\n</pre><p>\nIt returns 0 if there are no errors\nor 1 in case of errors.\n\n\n\n\n\n<hr><h3><a name=\"luaL_dostring\"><code>luaL_dostring</code></a></h3><p>\n<span class=\"apii\">[-0, +?, <em>m</em>]</span>\n<pre>int luaL_dostring (lua_State *L, const char *str);</pre>\n\n<p>\nLoads and runs the given string.\nIt is defined as the following macro:\n\n<pre>\n     (luaL_loadstring(L, str) || lua_pcall(L, 0, LUA_MULTRET, 0))\n</pre><p>\nIt returns 0 if there are no errors\nor 1 in case of errors.\n\n\n\n\n\n<hr><h3><a name=\"luaL_error\"><code>luaL_error</code></a></h3><p>\n<span class=\"apii\">[-0, +0, <em>v</em>]</span>\n<pre>int luaL_error (lua_State *L, const char *fmt, ...);</pre>\n\n<p>\nRaises an error.\nThe error message format is given by <code>fmt</code>\nplus any extra arguments,\nfollowing the same rules of <a href=\"#lua_pushfstring\"><code>lua_pushfstring</code></a>.\nIt also adds at the beginning of the message the file name and\nthe line number where the error occurred,\nif this information is available.\n\n\n<p>\nThis function never returns,\nbut it is an idiom to use it in C&nbsp;functions\nas <code>return luaL_error(<em>args</em>)</code>.\n\n\n\n\n\n<hr><h3><a name=\"luaL_getmetafield\"><code>luaL_getmetafield</code></a></h3><p>\n<span class=\"apii\">[-0, +(0|1), <em>m</em>]</span>\n<pre>int luaL_getmetafield (lua_State *L, int obj, const char *e);</pre>\n\n<p>\nPushes onto the stack the field <code>e</code> from the metatable\nof the object at index <code>obj</code>.\nIf the object does not have a metatable,\nor if the metatable does not have this field,\nreturns 0 and pushes nothing.\n\n\n\n\n\n<hr><h3><a name=\"luaL_getmetatable\"><code>luaL_getmetatable</code></a></h3><p>\n<span class=\"apii\">[-0, +1, <em>-</em>]</span>\n<pre>void luaL_getmetatable (lua_State *L, const char *tname);</pre>\n\n<p>\nPushes onto the stack the metatable associated with name <code>tname</code>\nin the registry (see <a href=\"#luaL_newmetatable\"><code>luaL_newmetatable</code></a>).\n\n\n\n\n\n<hr><h3><a name=\"luaL_gsub\"><code>luaL_gsub</code></a></h3><p>\n<span class=\"apii\">[-0, +1, <em>m</em>]</span>\n<pre>const char *luaL_gsub (lua_State *L,\n                       const char *s,\n                       const char *p,\n                       const char *r);</pre>\n\n<p>\nCreates a copy of string <code>s</code> by replacing\nany occurrence of the string <code>p</code>\nwith the string <code>r</code>.\nPushes the resulting string on the stack and returns it.\n\n\n\n\n\n<hr><h3><a name=\"luaL_loadbuffer\"><code>luaL_loadbuffer</code></a></h3><p>\n<span class=\"apii\">[-0, +1, <em>m</em>]</span>\n<pre>int luaL_loadbuffer (lua_State *L,\n                     const char *buff,\n                     size_t sz,\n                     const char *name);</pre>\n\n<p>\nLoads a buffer as a Lua chunk.\nThis function uses <a href=\"#lua_load\"><code>lua_load</code></a> to load the chunk in the\nbuffer pointed to by <code>buff</code> with size <code>sz</code>.\n\n\n<p>\nThis function returns the same results as <a href=\"#lua_load\"><code>lua_load</code></a>.\n<code>name</code> is the chunk name,\nused for debug information and error messages.\n\n\n\n\n\n<hr><h3><a name=\"luaL_loadfile\"><code>luaL_loadfile</code></a></h3><p>\n<span class=\"apii\">[-0, +1, <em>m</em>]</span>\n<pre>int luaL_loadfile (lua_State *L, const char *filename);</pre>\n\n<p>\nLoads a file as a Lua chunk.\nThis function uses <a href=\"#lua_load\"><code>lua_load</code></a> to load the chunk in the file\nnamed <code>filename</code>.\nIf <code>filename</code> is <code>NULL</code>,\nthen it loads from the standard input.\nThe first line in the file is ignored if it starts with a <code>#</code>.\n\n\n<p>\nThis function returns the same results as <a href=\"#lua_load\"><code>lua_load</code></a>,\nbut it has an extra error code <a name=\"pdf-LUA_ERRFILE\"><code>LUA_ERRFILE</code></a>\nif it cannot open/read the file.\n\n\n<p>\nAs <a href=\"#lua_load\"><code>lua_load</code></a>, this function only loads the chunk;\nit does not run it.\n\n\n\n\n\n<hr><h3><a name=\"luaL_loadstring\"><code>luaL_loadstring</code></a></h3><p>\n<span class=\"apii\">[-0, +1, <em>m</em>]</span>\n<pre>int luaL_loadstring (lua_State *L, const char *s);</pre>\n\n<p>\nLoads a string as a Lua chunk.\nThis function uses <a href=\"#lua_load\"><code>lua_load</code></a> to load the chunk in\nthe zero-terminated string <code>s</code>.\n\n\n<p>\nThis function returns the same results as <a href=\"#lua_load\"><code>lua_load</code></a>.\n\n\n<p>\nAlso as <a href=\"#lua_load\"><code>lua_load</code></a>, this function only loads the chunk;\nit does not run it.\n\n\n\n\n\n<hr><h3><a name=\"luaL_newmetatable\"><code>luaL_newmetatable</code></a></h3><p>\n<span class=\"apii\">[-0, +1, <em>m</em>]</span>\n<pre>int luaL_newmetatable (lua_State *L, const char *tname);</pre>\n\n<p>\nIf the registry already has the key <code>tname</code>,\nreturns 0.\nOtherwise,\ncreates a new table to be used as a metatable for userdata,\nadds it to the registry with key <code>tname</code>,\nand returns 1.\n\n\n<p>\nIn both cases pushes onto the stack the final value associated\nwith <code>tname</code> in the registry.\n\n\n\n\n\n<hr><h3><a name=\"luaL_newstate\"><code>luaL_newstate</code></a></h3><p>\n<span class=\"apii\">[-0, +0, <em>-</em>]</span>\n<pre>lua_State *luaL_newstate (void);</pre>\n\n<p>\nCreates a new Lua state.\nIt calls <a href=\"#lua_newstate\"><code>lua_newstate</code></a> with an\nallocator based on the standard&nbsp;C <code>realloc</code> function\nand then sets a panic function (see <a href=\"#lua_atpanic\"><code>lua_atpanic</code></a>) that prints\nan error message to the standard error output in case of fatal\nerrors.\n\n\n<p>\nReturns the new state,\nor <code>NULL</code> if there is a memory allocation error.\n\n\n\n\n\n<hr><h3><a name=\"luaL_openlibs\"><code>luaL_openlibs</code></a></h3><p>\n<span class=\"apii\">[-0, +0, <em>m</em>]</span>\n<pre>void luaL_openlibs (lua_State *L);</pre>\n\n<p>\nOpens all standard Lua libraries into the given state.\n\n\n\n\n\n<hr><h3><a name=\"luaL_optint\"><code>luaL_optint</code></a></h3><p>\n<span class=\"apii\">[-0, +0, <em>v</em>]</span>\n<pre>int luaL_optint (lua_State *L, int narg, int d);</pre>\n\n<p>\nIf the function argument <code>narg</code> is a number,\nreturns this number cast to an <code>int</code>.\nIf this argument is absent or is <b>nil</b>,\nreturns <code>d</code>.\nOtherwise, raises an error.\n\n\n\n\n\n<hr><h3><a name=\"luaL_optinteger\"><code>luaL_optinteger</code></a></h3><p>\n<span class=\"apii\">[-0, +0, <em>v</em>]</span>\n<pre>lua_Integer luaL_optinteger (lua_State *L,\n                             int narg,\n                             lua_Integer d);</pre>\n\n<p>\nIf the function argument <code>narg</code> is a number,\nreturns this number cast to a <a href=\"#lua_Integer\"><code>lua_Integer</code></a>.\nIf this argument is absent or is <b>nil</b>,\nreturns <code>d</code>.\nOtherwise, raises an error.\n\n\n\n\n\n<hr><h3><a name=\"luaL_optlong\"><code>luaL_optlong</code></a></h3><p>\n<span class=\"apii\">[-0, +0, <em>v</em>]</span>\n<pre>long luaL_optlong (lua_State *L, int narg, long d);</pre>\n\n<p>\nIf the function argument <code>narg</code> is a number,\nreturns this number cast to a <code>long</code>.\nIf this argument is absent or is <b>nil</b>,\nreturns <code>d</code>.\nOtherwise, raises an error.\n\n\n\n\n\n<hr><h3><a name=\"luaL_optlstring\"><code>luaL_optlstring</code></a></h3><p>\n<span class=\"apii\">[-0, +0, <em>v</em>]</span>\n<pre>const char *luaL_optlstring (lua_State *L,\n                             int narg,\n                             const char *d,\n                             size_t *l);</pre>\n\n<p>\nIf the function argument <code>narg</code> is a string,\nreturns this string.\nIf this argument is absent or is <b>nil</b>,\nreturns <code>d</code>.\nOtherwise, raises an error.\n\n\n<p>\nIf <code>l</code> is not <code>NULL</code>,\nfills the position <code>*l</code> with the results's length.\n\n\n\n\n\n<hr><h3><a name=\"luaL_optnumber\"><code>luaL_optnumber</code></a></h3><p>\n<span class=\"apii\">[-0, +0, <em>v</em>]</span>\n<pre>lua_Number luaL_optnumber (lua_State *L, int narg, lua_Number d);</pre>\n\n<p>\nIf the function argument <code>narg</code> is a number,\nreturns this number.\nIf this argument is absent or is <b>nil</b>,\nreturns <code>d</code>.\nOtherwise, raises an error.\n\n\n\n\n\n<hr><h3><a name=\"luaL_optstring\"><code>luaL_optstring</code></a></h3><p>\n<span class=\"apii\">[-0, +0, <em>v</em>]</span>\n<pre>const char *luaL_optstring (lua_State *L,\n                            int narg,\n                            const char *d);</pre>\n\n<p>\nIf the function argument <code>narg</code> is a string,\nreturns this string.\nIf this argument is absent or is <b>nil</b>,\nreturns <code>d</code>.\nOtherwise, raises an error.\n\n\n\n\n\n<hr><h3><a name=\"luaL_prepbuffer\"><code>luaL_prepbuffer</code></a></h3><p>\n<span class=\"apii\">[-0, +0, <em>-</em>]</span>\n<pre>char *luaL_prepbuffer (luaL_Buffer *B);</pre>\n\n<p>\nReturns an address to a space of size <a name=\"pdf-LUAL_BUFFERSIZE\"><code>LUAL_BUFFERSIZE</code></a>\nwhere you can copy a string to be added to buffer <code>B</code>\n(see <a href=\"#luaL_Buffer\"><code>luaL_Buffer</code></a>).\nAfter copying the string into this space you must call\n<a href=\"#luaL_addsize\"><code>luaL_addsize</code></a> with the size of the string to actually add \nit to the buffer.\n\n\n\n\n\n<hr><h3><a name=\"luaL_pushresult\"><code>luaL_pushresult</code></a></h3><p>\n<span class=\"apii\">[-?, +1, <em>m</em>]</span>\n<pre>void luaL_pushresult (luaL_Buffer *B);</pre>\n\n<p>\nFinishes the use of buffer <code>B</code> leaving the final string on\nthe top of the stack.\n\n\n\n\n\n<hr><h3><a name=\"luaL_ref\"><code>luaL_ref</code></a></h3><p>\n<span class=\"apii\">[-1, +0, <em>m</em>]</span>\n<pre>int luaL_ref (lua_State *L, int t);</pre>\n\n<p>\nCreates and returns a <em>reference</em>,\nin the table at index <code>t</code>,\nfor the object at the top of the stack (and pops the object).\n\n\n<p>\nA reference is a unique integer key.\nAs long as you do not manually add integer keys into table <code>t</code>,\n<a href=\"#luaL_ref\"><code>luaL_ref</code></a> ensures the uniqueness of the key it returns.\nYou can retrieve an object referred by reference <code>r</code>\nby calling <code>lua_rawgeti(L, t, r)</code>.\nFunction <a href=\"#luaL_unref\"><code>luaL_unref</code></a> frees a reference and its associated object.\n\n\n<p>\nIf the object at the top of the stack is <b>nil</b>,\n<a href=\"#luaL_ref\"><code>luaL_ref</code></a> returns the constant <a name=\"pdf-LUA_REFNIL\"><code>LUA_REFNIL</code></a>.\nThe constant <a name=\"pdf-LUA_NOREF\"><code>LUA_NOREF</code></a> is guaranteed to be different\nfrom any reference returned by <a href=\"#luaL_ref\"><code>luaL_ref</code></a>.\n\n\n\n\n\n<hr><h3><a name=\"luaL_Reg\"><code>luaL_Reg</code></a></h3>\n<pre>typedef struct luaL_Reg {\n  const char *name;\n  lua_CFunction func;\n} luaL_Reg;</pre>\n\n<p>\nType for arrays of functions to be registered by\n<a href=\"#luaL_register\"><code>luaL_register</code></a>.\n<code>name</code> is the function name and <code>func</code> is a pointer to\nthe function.\nAny array of <a href=\"#luaL_Reg\"><code>luaL_Reg</code></a> must end with an sentinel entry\nin which both <code>name</code> and <code>func</code> are <code>NULL</code>.\n\n\n\n\n\n<hr><h3><a name=\"luaL_register\"><code>luaL_register</code></a></h3><p>\n<span class=\"apii\">[-(0|1), +1, <em>m</em>]</span>\n<pre>void luaL_register (lua_State *L,\n                    const char *libname,\n                    const luaL_Reg *l);</pre>\n\n<p>\nOpens a library.\n\n\n<p>\nWhen called with <code>libname</code> equal to <code>NULL</code>,\nit simply registers all functions in the list <code>l</code>\n(see <a href=\"#luaL_Reg\"><code>luaL_Reg</code></a>) into the table on the top of the stack.\n\n\n<p>\nWhen called with a non-null <code>libname</code>,\n<code>luaL_register</code> creates a new table <code>t</code>,\nsets it as the value of the global variable <code>libname</code>,\nsets it as the value of <code>package.loaded[libname]</code>,\nand registers on it all functions in the list <code>l</code>.\nIf there is a table in <code>package.loaded[libname]</code> or in\nvariable <code>libname</code>,\nreuses this table instead of creating a new one.\n\n\n<p>\nIn any case the function leaves the table\non the top of the stack.\n\n\n\n\n\n<hr><h3><a name=\"luaL_typename\"><code>luaL_typename</code></a></h3><p>\n<span class=\"apii\">[-0, +0, <em>-</em>]</span>\n<pre>const char *luaL_typename (lua_State *L, int index);</pre>\n\n<p>\nReturns the name of the type of the value at the given index.\n\n\n\n\n\n<hr><h3><a name=\"luaL_typerror\"><code>luaL_typerror</code></a></h3><p>\n<span class=\"apii\">[-0, +0, <em>v</em>]</span>\n<pre>int luaL_typerror (lua_State *L, int narg, const char *tname);</pre>\n\n<p>\nGenerates an error with a message like the following:\n\n<pre>\n     <em>location</em>: bad argument <em>narg</em> to '<em>func</em>' (<em>tname</em> expected, got <em>rt</em>)\n</pre><p>\nwhere <code><em>location</em></code> is produced by <a href=\"#luaL_where\"><code>luaL_where</code></a>,\n<code><em>func</em></code> is the name of the current function,\nand <code><em>rt</em></code> is the type name of the actual argument.\n\n\n\n\n\n<hr><h3><a name=\"luaL_unref\"><code>luaL_unref</code></a></h3><p>\n<span class=\"apii\">[-0, +0, <em>-</em>]</span>\n<pre>void luaL_unref (lua_State *L, int t, int ref);</pre>\n\n<p>\nReleases reference <code>ref</code> from the table at index <code>t</code>\n(see <a href=\"#luaL_ref\"><code>luaL_ref</code></a>).\nThe entry is removed from the table,\nso that the referred object can be collected.\nThe reference <code>ref</code> is also freed to be used again.\n\n\n<p>\nIf <code>ref</code> is <a href=\"#pdf-LUA_NOREF\"><code>LUA_NOREF</code></a> or <a href=\"#pdf-LUA_REFNIL\"><code>LUA_REFNIL</code></a>,\n<a href=\"#luaL_unref\"><code>luaL_unref</code></a> does nothing.\n\n\n\n\n\n<hr><h3><a name=\"luaL_where\"><code>luaL_where</code></a></h3><p>\n<span class=\"apii\">[-0, +1, <em>m</em>]</span>\n<pre>void luaL_where (lua_State *L, int lvl);</pre>\n\n<p>\nPushes onto the stack a string identifying the current position\nof the control at level <code>lvl</code> in the call stack.\nTypically this string has the following format:\n\n<pre>\n     <em>chunkname</em>:<em>currentline</em>:\n</pre><p>\nLevel&nbsp;0 is the running function,\nlevel&nbsp;1 is the function that called the running function,\netc.\n\n\n<p>\nThis function is used to build a prefix for error messages.\n\n\n\n\n\n\n\n<h1>5 - <a name=\"5\">Standard Libraries</a></h1>\n\n<p>\nThe standard Lua libraries provide useful functions\nthat are implemented directly through the C&nbsp;API.\nSome of these functions provide essential services to the language\n(e.g., <a href=\"#pdf-type\"><code>type</code></a> and <a href=\"#pdf-getmetatable\"><code>getmetatable</code></a>);\nothers provide access to \"outside\" services (e.g., I/O);\nand others could be implemented in Lua itself,\nbut are quite useful or have critical performance requirements that\ndeserve an implementation in C (e.g., <a href=\"#pdf-table.sort\"><code>table.sort</code></a>).\n\n\n<p>\nAll libraries are implemented through the official C&nbsp;API\nand are provided as separate C&nbsp;modules.\nCurrently, Lua has the following standard libraries:\n\n<ul>\n\n<li>basic library, which includes the coroutine sub-library;</li>\n\n<li>package library;</li>\n\n<li>string manipulation;</li>\n\n<li>table manipulation;</li>\n\n<li>mathematical functions (sin, log, etc.);</li>\n\n<li>input and output;</li>\n\n<li>operating system facilities;</li>\n\n<li>debug facilities.</li>\n\n</ul><p>\nExcept for the basic and package libraries,\neach library provides all its functions as fields of a global table\nor as methods of its objects.\n\n\n<p>\nTo have access to these libraries,\nthe C&nbsp;host program should call the <a href=\"#luaL_openlibs\"><code>luaL_openlibs</code></a> function,\nwhich opens all standard libraries.\nAlternatively,\nit can open them individually by calling\n<a name=\"pdf-luaopen_base\"><code>luaopen_base</code></a> (for the basic library),\n<a name=\"pdf-luaopen_package\"><code>luaopen_package</code></a> (for the package library),\n<a name=\"pdf-luaopen_string\"><code>luaopen_string</code></a> (for the string library),\n<a name=\"pdf-luaopen_table\"><code>luaopen_table</code></a> (for the table library),\n<a name=\"pdf-luaopen_math\"><code>luaopen_math</code></a> (for the mathematical library),\n<a name=\"pdf-luaopen_io\"><code>luaopen_io</code></a> (for the I/O library),\n<a name=\"pdf-luaopen_os\"><code>luaopen_os</code></a> (for the Operating System library),\nand <a name=\"pdf-luaopen_debug\"><code>luaopen_debug</code></a> (for the debug library).\nThese functions are declared in <a name=\"pdf-lualib.h\"><code>lualib.h</code></a>\nand should not be called directly:\nyou must call them like any other Lua C&nbsp;function,\ne.g., by using <a href=\"#lua_call\"><code>lua_call</code></a>.\n\n\n\n<h2>5.1 - <a name=\"5.1\">Basic Functions</a></h2>\n\n<p>\nThe basic library provides some core functions to Lua.\nIf you do not include this library in your application,\nyou should check carefully whether you need to provide \nimplementations for some of its facilities.\n\n\n<p>\n<hr><h3><a name=\"pdf-assert\"><code>assert (v [, message])</code></a></h3>\nIssues an  error when\nthe value of its argument <code>v</code> is false (i.e., <b>nil</b> or <b>false</b>);\notherwise, returns all its arguments.\n<code>message</code> is an error message;\nwhen absent, it defaults to \"assertion failed!\"\n\n\n\n\n<p>\n<hr><h3><a name=\"pdf-collectgarbage\"><code>collectgarbage ([opt [, arg]])</code></a></h3>\n\n\n<p>\nThis function is a generic interface to the garbage collector.\nIt performs different functions according to its first argument, <code>opt</code>:\n\n<ul>\n\n<li><b>\"collect\":</b>\nperforms a full garbage-collection cycle.\nThis is the default option.\n</li>\n\n<li><b>\"stop\":</b>\nstops the garbage collector.\n</li>\n\n<li><b>\"restart\":</b>\nrestarts the garbage collector.\n</li>\n\n<li><b>\"count\":</b>\nreturns the total memory in use by Lua (in Kbytes).\n</li>\n\n<li><b>\"step\":</b>\nperforms a garbage-collection step.\nThe step \"size\" is controlled by <code>arg</code>\n(larger values mean more steps) in a non-specified way.\nIf you want to control the step size\nyou must experimentally tune the value of <code>arg</code>.\nReturns <b>true</b> if the step finished a collection cycle.\n</li>\n\n<li><b>\"setpause\":</b>\nsets <code>arg</code> as the new value for the <em>pause</em> of\nthe collector (see <a href=\"#2.10\">&sect;2.10</a>).\nReturns the previous value for <em>pause</em>.\n</li>\n\n<li><b>\"setstepmul\":</b>\nsets <code>arg</code> as the new value for the <em>step multiplier</em> of\nthe collector (see <a href=\"#2.10\">&sect;2.10</a>).\nReturns the previous value for <em>step</em>.\n</li>\n\n</ul>\n\n\n\n<p>\n<hr><h3><a name=\"pdf-dofile\"><code>dofile ([filename])</code></a></h3>\nOpens the named file and executes its contents as a Lua chunk.\nWhen called without arguments,\n<code>dofile</code> executes the contents of the standard input (<code>stdin</code>).\nReturns all values returned by the chunk.\nIn case of errors, <code>dofile</code> propagates the error\nto its caller (that is, <code>dofile</code> does not run in protected mode).\n\n\n\n\n<p>\n<hr><h3><a name=\"pdf-error\"><code>error (message [, level])</code></a></h3>\nTerminates the last protected function called\nand returns <code>message</code> as the error message.\nFunction <code>error</code> never returns.\n\n\n<p>\nUsually, <code>error</code> adds some information about the error position\nat the beginning of the message.\nThe <code>level</code> argument specifies how to get the error position.\nWith level&nbsp;1 (the default), the error position is where the\n<code>error</code> function was called.\nLevel&nbsp;2 points the error to where the function\nthat called <code>error</code> was called; and so on.\nPassing a level&nbsp;0 avoids the addition of error position information\nto the message.\n\n\n\n\n<p>\n<hr><h3><a name=\"pdf-_G\"><code>_G</code></a></h3>\nA global variable (not a function) that\nholds the global environment (that is, <code>_G._G = _G</code>).\nLua itself does not use this variable;\nchanging its value does not affect any environment,\nnor vice-versa.\n(Use <a href=\"#pdf-setfenv\"><code>setfenv</code></a> to change environments.)\n\n\n\n\n<p>\n<hr><h3><a name=\"pdf-getfenv\"><code>getfenv ([f])</code></a></h3>\nReturns the current environment in use by the function.\n<code>f</code> can be a Lua function or a number\nthat specifies the function at that stack level:\nLevel&nbsp;1 is the function calling <code>getfenv</code>.\nIf the given function is not a Lua function,\nor if <code>f</code> is 0,\n<code>getfenv</code> returns the global environment.\nThe default for <code>f</code> is 1.\n\n\n\n\n<p>\n<hr><h3><a name=\"pdf-getmetatable\"><code>getmetatable (object)</code></a></h3>\n\n\n<p>\nIf <code>object</code> does not have a metatable, returns <b>nil</b>.\nOtherwise,\nif the object's metatable has a <code>\"__metatable\"</code> field,\nreturns the associated value.\nOtherwise, returns the metatable of the given object.\n\n\n\n\n<p>\n<hr><h3><a name=\"pdf-ipairs\"><code>ipairs (t)</code></a></h3>\n\n\n<p>\nReturns three values: an iterator function, the table <code>t</code>, and 0,\nso that the construction\n\n<pre>\n     for i,v in ipairs(t) do <em>body</em> end\n</pre><p>\nwill iterate over the pairs (<code>1,t[1]</code>), (<code>2,t[2]</code>), &middot;&middot;&middot;,\nup to the first integer key absent from the table.\n\n\n\n\n<p>\n<hr><h3><a name=\"pdf-load\"><code>load (func [, chunkname])</code></a></h3>\n\n\n<p>\nLoads a chunk using function <code>func</code> to get its pieces.\nEach call to <code>func</code> must return a string that concatenates\nwith previous results.\nA return of an empty string, <b>nil</b>, or no value signals the end of the chunk.\n\n\n<p>\nIf there are no errors, \nreturns the compiled chunk as a function;\notherwise, returns <b>nil</b> plus the error message.\nThe environment of the returned function is the global environment.\n\n\n<p>\n<code>chunkname</code> is used as the chunk name for error messages\nand debug information.\nWhen absent,\nit defaults to \"<code>=(load)</code>\".\n\n\n\n\n<p>\n<hr><h3><a name=\"pdf-loadfile\"><code>loadfile ([filename])</code></a></h3>\n\n\n<p>\nSimilar to <a href=\"#pdf-load\"><code>load</code></a>,\nbut gets the chunk from file <code>filename</code>\nor from the standard input,\nif no file name is given.\n\n\n\n\n<p>\n<hr><h3><a name=\"pdf-loadstring\"><code>loadstring (string [, chunkname])</code></a></h3>\n\n\n<p>\nSimilar to <a href=\"#pdf-load\"><code>load</code></a>,\nbut gets the chunk from the given string.\n\n\n<p>\nTo load and run a given string, use the idiom\n\n<pre>\n     assert(loadstring(s))()\n</pre>\n\n<p>\nWhen absent,\n<code>chunkname</code> defaults to the given string.\n\n\n\n\n<p>\n<hr><h3><a name=\"pdf-next\"><code>next (table [, index])</code></a></h3>\n\n\n<p>\nAllows a program to traverse all fields of a table.\nIts first argument is a table and its second argument\nis an index in this table.\n<code>next</code> returns the next index of the table\nand its associated value.\nWhen called with <b>nil</b> as its second argument,\n<code>next</code> returns an initial index\nand its associated value.\nWhen called with the last index,\nor with <b>nil</b> in an empty table,\n<code>next</code> returns <b>nil</b>.\nIf the second argument is absent, then it is interpreted as <b>nil</b>.\nIn particular,\nyou can use <code>next(t)</code> to check whether a table is empty.\n\n\n<p>\nThe order in which the indices are enumerated is not specified,\n<em>even for numeric indices</em>.\n(To traverse a table in numeric order,\nuse a numerical <b>for</b> or the <a href=\"#pdf-ipairs\"><code>ipairs</code></a> function.)\n\n\n<p>\nThe behavior of <code>next</code> is <em>undefined</em> if,\nduring the traversal,\nyou assign any value to a non-existent field in the table.\nYou may however modify existing fields.\nIn particular, you may clear existing fields.\n\n\n\n\n<p>\n<hr><h3><a name=\"pdf-pairs\"><code>pairs (t)</code></a></h3>\n\n\n<p>\nReturns three values: the <a href=\"#pdf-next\"><code>next</code></a> function, the table <code>t</code>, and <b>nil</b>,\nso that the construction\n\n<pre>\n     for k,v in pairs(t) do <em>body</em> end\n</pre><p>\nwill iterate over all key&ndash;value pairs of table <code>t</code>.\n\n\n<p>\nSee function <a href=\"#pdf-next\"><code>next</code></a> for the caveats of modifying\nthe table during its traversal.\n\n\n\n\n<p>\n<hr><h3><a name=\"pdf-pcall\"><code>pcall (f, arg1, &middot;&middot;&middot;)</code></a></h3>\n\n\n<p>\nCalls function <code>f</code> with\nthe given arguments in <em>protected mode</em>.\nThis means that any error inside&nbsp;<code>f</code> is not propagated;\ninstead, <code>pcall</code> catches the error\nand returns a status code.\nIts first result is the status code (a boolean),\nwhich is true if the call succeeds without errors.\nIn such case, <code>pcall</code> also returns all results from the call,\nafter this first result.\nIn case of any error, <code>pcall</code> returns <b>false</b> plus the error message.\n\n\n\n\n<p>\n<hr><h3><a name=\"pdf-print\"><code>print (&middot;&middot;&middot;)</code></a></h3>\nReceives any number of arguments,\nand prints their values to <code>stdout</code>,\nusing the <a href=\"#pdf-tostring\"><code>tostring</code></a> function to convert them to strings.\n<code>print</code> is not intended for formatted output,\nbut only as a quick way to show a value,\ntypically for debugging.\nFor formatted output, use <a href=\"#pdf-string.format\"><code>string.format</code></a>.\n\n\n\n\n<p>\n<hr><h3><a name=\"pdf-rawequal\"><code>rawequal (v1, v2)</code></a></h3>\nChecks whether <code>v1</code> is equal to <code>v2</code>,\nwithout invoking any metamethod.\nReturns a boolean.\n\n\n\n\n<p>\n<hr><h3><a name=\"pdf-rawget\"><code>rawget (table, index)</code></a></h3>\nGets the real value of <code>table[index]</code>,\nwithout invoking any metamethod.\n<code>table</code> must be a table;\n<code>index</code> may be any value.\n\n\n\n\n<p>\n<hr><h3><a name=\"pdf-rawset\"><code>rawset (table, index, value)</code></a></h3>\nSets the real value of <code>table[index]</code> to <code>value</code>,\nwithout invoking any metamethod.\n<code>table</code> must be a table,\n<code>index</code> any value different from <b>nil</b>,\nand <code>value</code> any Lua value.\n\n\n<p>\nThis function returns <code>table</code>.\n\n\n\n\n<p>\n<hr><h3><a name=\"pdf-select\"><code>select (index, &middot;&middot;&middot;)</code></a></h3>\n\n\n<p>\nIf <code>index</code> is a number,\nreturns all arguments after argument number <code>index</code>.\nOtherwise, <code>index</code> must be the string <code>\"#\"</code>,\nand <code>select</code> returns the total number of extra arguments it received.\n\n\n\n\n<p>\n<hr><h3><a name=\"pdf-setfenv\"><code>setfenv (f, table)</code></a></h3>\n\n\n<p>\nSets the environment to be used by the given function.\n<code>f</code> can be a Lua function or a number\nthat specifies the function at that stack level:\nLevel&nbsp;1 is the function calling <code>setfenv</code>.\n<code>setfenv</code> returns the given function.\n\n\n<p>\nAs a special case, when <code>f</code> is 0 <code>setfenv</code> changes\nthe environment of the running thread.\nIn this case, <code>setfenv</code> returns no values.\n\n\n\n\n<p>\n<hr><h3><a name=\"pdf-setmetatable\"><code>setmetatable (table, metatable)</code></a></h3>\n\n\n<p>\nSets the metatable for the given table.\n(You cannot change the metatable of other types from Lua, only from&nbsp;C.)\nIf <code>metatable</code> is <b>nil</b>,\nremoves the metatable of the given table.\nIf the original metatable has a <code>\"__metatable\"</code> field,\nraises an error.\n\n\n<p>\nThis function returns <code>table</code>.\n\n\n\n\n<p>\n<hr><h3><a name=\"pdf-tonumber\"><code>tonumber (e [, base])</code></a></h3>\nTries to convert its argument to a number.\nIf the argument is already a number or a string convertible\nto a number, then <code>tonumber</code> returns this number;\notherwise, it returns <b>nil</b>.\n\n\n<p>\nAn optional argument specifies the base to interpret the numeral.\nThe base may be any integer between 2 and 36, inclusive.\nIn bases above&nbsp;10, the letter '<code>A</code>' (in either upper or lower case)\nrepresents&nbsp;10, '<code>B</code>' represents&nbsp;11, and so forth,\nwith '<code>Z</code>' representing 35.\nIn base 10 (the default), the number can have a decimal part,\nas well as an optional exponent part (see <a href=\"#2.1\">&sect;2.1</a>).\nIn other bases, only unsigned integers are accepted.\n\n\n\n\n<p>\n<hr><h3><a name=\"pdf-tostring\"><code>tostring (e)</code></a></h3>\nReceives an argument of any type and\nconverts it to a string in a reasonable format.\nFor complete control of how numbers are converted,\nuse <a href=\"#pdf-string.format\"><code>string.format</code></a>.\n\n\n<p>\nIf the metatable of <code>e</code> has a <code>\"__tostring\"</code> field,\nthen <code>tostring</code> calls the corresponding value\nwith <code>e</code> as argument,\nand uses the result of the call as its result.\n\n\n\n\n<p>\n<hr><h3><a name=\"pdf-type\"><code>type (v)</code></a></h3>\nReturns the type of its only argument, coded as a string.\nThe possible results of this function are\n\"<code>nil</code>\" (a string, not the value <b>nil</b>),\n\"<code>number</code>\",\n\"<code>string</code>\",\n\"<code>boolean</code>\",\n\"<code>table</code>\",\n\"<code>function</code>\",\n\"<code>thread</code>\",\nand \"<code>userdata</code>\".\n\n\n\n\n<p>\n<hr><h3><a name=\"pdf-unpack\"><code>unpack (list [, i [, j]])</code></a></h3>\nReturns the elements from the given table.\nThis function is equivalent to\n\n<pre>\n     return list[i], list[i+1], &middot;&middot;&middot;, list[j]\n</pre><p>\nexcept that the above code can be written only for a fixed number\nof elements.\nBy default, <code>i</code> is&nbsp;1 and <code>j</code> is the length of the list,\nas defined by the length operator (see <a href=\"#2.5.5\">&sect;2.5.5</a>).\n\n\n\n\n<p>\n<hr><h3><a name=\"pdf-_VERSION\"><code>_VERSION</code></a></h3>\nA global variable (not a function) that\nholds a string containing the current interpreter version.\nThe current contents of this variable is \"<code>Lua 5.1</code>\".\n\n\n\n\n<p>\n<hr><h3><a name=\"pdf-xpcall\"><code>xpcall (f, err)</code></a></h3>\n\n\n<p>\nThis function is similar to <a href=\"#pdf-pcall\"><code>pcall</code></a>,\nexcept that you can set a new error handler.\n\n\n<p>\n<code>xpcall</code> calls function <code>f</code> in protected mode,\nusing <code>err</code> as the error handler.\nAny error inside <code>f</code> is not propagated;\ninstead, <code>xpcall</code> catches the error,\ncalls the <code>err</code> function with the original error object,\nand returns a status code.\nIts first result is the status code (a boolean),\nwhich is true if the call succeeds without errors.\nIn this case, <code>xpcall</code> also returns all results from the call,\nafter this first result.\nIn case of any error,\n<code>xpcall</code> returns <b>false</b> plus the result from <code>err</code>.\n\n\n\n\n\n\n\n<h2>5.2 - <a name=\"5.2\">Coroutine Manipulation</a></h2>\n\n<p>\nThe operations related to coroutines comprise a sub-library of\nthe basic library and come inside the table <a name=\"pdf-coroutine\"><code>coroutine</code></a>.\nSee <a href=\"#2.11\">&sect;2.11</a> for a general description of coroutines.\n\n\n<p>\n<hr><h3><a name=\"pdf-coroutine.create\"><code>coroutine.create (f)</code></a></h3>\n\n\n<p>\nCreates a new coroutine, with body <code>f</code>.\n<code>f</code> must be a Lua function.\nReturns this new coroutine,\nan object with type <code>\"thread\"</code>.\n\n\n\n\n<p>\n<hr><h3><a name=\"pdf-coroutine.resume\"><code>coroutine.resume (co [, val1, &middot;&middot;&middot;])</code></a></h3>\n\n\n<p>\nStarts or continues the execution of coroutine <code>co</code>.\nThe first time you resume a coroutine,\nit starts running its body.\nThe values <code>val1</code>, &middot;&middot;&middot; are passed\nas the arguments to the body function.\nIf the coroutine has yielded,\n<code>resume</code> restarts it;\nthe values <code>val1</code>, &middot;&middot;&middot; are passed\nas the results from the yield.\n\n\n<p>\nIf the coroutine runs without any errors,\n<code>resume</code> returns <b>true</b> plus any values passed to <code>yield</code>\n(if the coroutine yields) or any values returned by the body function\n(if the coroutine terminates).\nIf there is any error,\n<code>resume</code> returns <b>false</b> plus the error message.\n\n\n\n\n<p>\n<hr><h3><a name=\"pdf-coroutine.running\"><code>coroutine.running ()</code></a></h3>\n\n\n<p>\nReturns the running coroutine,\nor <b>nil</b> when called by the main thread.\n\n\n\n\n<p>\n<hr><h3><a name=\"pdf-coroutine.status\"><code>coroutine.status (co)</code></a></h3>\n\n\n<p>\nReturns the status of coroutine <code>co</code>, as a string:\n<code>\"running\"</code>,\nif the coroutine is running (that is, it called <code>status</code>);\n<code>\"suspended\"</code>, if the coroutine is suspended in a call to <code>yield</code>,\nor if it has not started running yet;\n<code>\"normal\"</code> if the coroutine is active but not running\n(that is, it has resumed another coroutine);\nand <code>\"dead\"</code> if the coroutine has finished its body function,\nor if it has stopped with an error.\n\n\n\n\n<p>\n<hr><h3><a name=\"pdf-coroutine.wrap\"><code>coroutine.wrap (f)</code></a></h3>\n\n\n<p>\nCreates a new coroutine, with body <code>f</code>.\n<code>f</code> must be a Lua function.\nReturns a function that resumes the coroutine each time it is called.\nAny arguments passed to the function behave as the\nextra arguments to <code>resume</code>.\nReturns the same values returned by <code>resume</code>,\nexcept the first boolean.\nIn case of error, propagates the error.\n\n\n\n\n<p>\n<hr><h3><a name=\"pdf-coroutine.yield\"><code>coroutine.yield (&middot;&middot;&middot;)</code></a></h3>\n\n\n<p>\nSuspends the execution of the calling coroutine.\nThe coroutine cannot be running a C&nbsp;function,\na metamethod, or an iterator.\nAny arguments to <code>yield</code> are passed as extra results to <code>resume</code>.\n\n\n\n\n\n\n\n<h2>5.3 - <a name=\"5.3\">Modules</a></h2>\n\n<p>\nThe package library provides basic\nfacilities for loading and building modules in Lua.\nIt exports two of its functions directly in the global environment:\n<a href=\"#pdf-require\"><code>require</code></a> and <a href=\"#pdf-module\"><code>module</code></a>.\nEverything else is exported in a table <a name=\"pdf-package\"><code>package</code></a>.\n\n\n<p>\n<hr><h3><a name=\"pdf-module\"><code>module (name [, &middot;&middot;&middot;])</code></a></h3>\n\n\n<p>\nCreates a module.\nIf there is a table in <code>package.loaded[name]</code>,\nthis table is the module.\nOtherwise, if there is a global table <code>t</code> with the given name,\nthis table is the module.\nOtherwise creates a new table <code>t</code> and\nsets it as the value of the global <code>name</code> and\nthe value of <code>package.loaded[name]</code>.\nThis function also initializes <code>t._NAME</code> with the given name,\n<code>t._M</code> with the module (<code>t</code> itself),\nand <code>t._PACKAGE</code> with the package name\n(the full module name minus last component; see below).\nFinally, <code>module</code> sets <code>t</code> as the new environment\nof the current function and the new value of <code>package.loaded[name]</code>,\nso that <a href=\"#pdf-require\"><code>require</code></a> returns <code>t</code>.\n\n\n<p>\nIf <code>name</code> is a compound name\n(that is, one with components separated by dots),\n<code>module</code> creates (or reuses, if they already exist)\ntables for each component.\nFor instance, if <code>name</code> is <code>a.b.c</code>,\nthen <code>module</code> stores the module table in field <code>c</code> of\nfield <code>b</code> of global <code>a</code>.\n\n\n<p>\nThis function can receive optional <em>options</em> after\nthe module name,\nwhere each option is a function to be applied over the module.\n\n\n\n\n<p>\n<hr><h3><a name=\"pdf-require\"><code>require (modname)</code></a></h3>\n\n\n<p>\nLoads the given module.\nThe function starts by looking into the <a href=\"#pdf-package.loaded\"><code>package.loaded</code></a> table\nto determine whether <code>modname</code> is already loaded.\nIf it is, then <code>require</code> returns the value stored\nat <code>package.loaded[modname]</code>.\nOtherwise, it tries to find a <em>loader</em> for the module.\n\n\n<p>\nTo find a loader,\n<code>require</code> is guided by the <a href=\"#pdf-package.loaders\"><code>package.loaders</code></a> array.\nBy changing this array,\nwe can change how <code>require</code> looks for a module.\nThe following explanation is based on the default configuration\nfor <a href=\"#pdf-package.loaders\"><code>package.loaders</code></a>.\n\n\n<p>\nFirst <code>require</code> queries <code>package.preload[modname]</code>.\nIf it has a value,\nthis value (which should be a function) is the loader.\nOtherwise <code>require</code> searches for a Lua loader using the\npath stored in <a href=\"#pdf-package.path\"><code>package.path</code></a>.\nIf that also fails, it searches for a C&nbsp;loader using the\npath stored in <a href=\"#pdf-package.cpath\"><code>package.cpath</code></a>.\nIf that also fails,\nit tries an <em>all-in-one</em> loader (see <a href=\"#pdf-package.loaders\"><code>package.loaders</code></a>).\n\n\n<p>\nOnce a loader is found,\n<code>require</code> calls the loader with a single argument, <code>modname</code>.\nIf the loader returns any value,\n<code>require</code> assigns the returned value to <code>package.loaded[modname]</code>.\nIf the loader returns no value and\nhas not assigned any value to <code>package.loaded[modname]</code>,\nthen <code>require</code> assigns <b>true</b> to this entry.\nIn any case, <code>require</code> returns the\nfinal value of <code>package.loaded[modname]</code>.\n\n\n<p>\nIf there is any error loading or running the module,\nor if it cannot find any loader for the module,\nthen <code>require</code> signals an error. \n\n\n\n\n<p>\n<hr><h3><a name=\"pdf-package.cpath\"><code>package.cpath</code></a></h3>\n\n\n<p>\nThe path used by <a href=\"#pdf-require\"><code>require</code></a> to search for a C&nbsp;loader.\n\n\n<p>\nLua initializes the C&nbsp;path <a href=\"#pdf-package.cpath\"><code>package.cpath</code></a> in the same way\nit initializes the Lua path <a href=\"#pdf-package.path\"><code>package.path</code></a>,\nusing the environment variable <a name=\"pdf-LUA_CPATH\"><code>LUA_CPATH</code></a>\nor a default path defined in <code>luaconf.h</code>.\n\n\n\n\n<p>\n\n<hr><h3><a name=\"pdf-package.loaded\"><code>package.loaded</code></a></h3>\n\n\n<p>\nA table used by <a href=\"#pdf-require\"><code>require</code></a> to control which\nmodules are already loaded.\nWhen you require a module <code>modname</code> and\n<code>package.loaded[modname]</code> is not false,\n<a href=\"#pdf-require\"><code>require</code></a> simply returns the value stored there.\n\n\n\n\n<p>\n<hr><h3><a name=\"pdf-package.loaders\"><code>package.loaders</code></a></h3>\n\n\n<p>\nA table used by <a href=\"#pdf-require\"><code>require</code></a> to control how to load modules.\n\n\n<p>\nEach entry in this table is a <em>searcher function</em>.\nWhen looking for a module,\n<a href=\"#pdf-require\"><code>require</code></a> calls each of these searchers in ascending order,\nwith the module name (the argument given to <a href=\"#pdf-require\"><code>require</code></a>) as its\nsole parameter.\nThe function can return another function (the module <em>loader</em>)\nor a string explaining why it did not find that module\n(or <b>nil</b> if it has nothing to say).\nLua initializes this table with four functions.\n\n\n<p>\nThe first searcher simply looks for a loader in the\n<a href=\"#pdf-package.preload\"><code>package.preload</code></a> table.\n\n\n<p>\nThe second searcher looks for a loader as a Lua library,\nusing the path stored at <a href=\"#pdf-package.path\"><code>package.path</code></a>.\nA path is a sequence of <em>templates</em> separated by semicolons.\nFor each template,\nthe searcher will change each interrogation\nmark in the template by <code>filename</code>,\nwhich is the module name with each dot replaced by a\n\"directory separator\" (such as \"<code>/</code>\" in Unix);\nthen it will try to open the resulting file name.\nSo, for instance, if the Lua path is the string\n\n<pre>\n     \"./?.lua;./?.lc;/usr/local/?/init.lua\"\n</pre><p>\nthe search for a Lua file for module <code>foo</code>\nwill try to open the files\n<code>./foo.lua</code>, <code>./foo.lc</code>, and\n<code>/usr/local/foo/init.lua</code>, in that order.\n\n\n<p>\nThe third searcher looks for a loader as a C&nbsp;library,\nusing the path given by the variable <a href=\"#pdf-package.cpath\"><code>package.cpath</code></a>.\nFor instance,\nif the C&nbsp;path is the string\n\n<pre>\n     \"./?.so;./?.dll;/usr/local/?/init.so\"\n</pre><p>\nthe searcher for module <code>foo</code>\nwill try to open the files <code>./foo.so</code>, <code>./foo.dll</code>,\nand <code>/usr/local/foo/init.so</code>, in that order.\nOnce it finds a C&nbsp;library,\nthis searcher first uses a dynamic link facility to link the\napplication with the library.\nThen it tries to find a C&nbsp;function inside the library to\nbe used as the loader.\nThe name of this C&nbsp;function is the string \"<code>luaopen_</code>\"\nconcatenated with a copy of the module name where each dot\nis replaced by an underscore.\nMoreover, if the module name has a hyphen,\nits prefix up to (and including) the first hyphen is removed.\nFor instance, if the module name is <code>a.v1-b.c</code>,\nthe function name will be <code>luaopen_b_c</code>.\n\n\n<p>\nThe fourth searcher tries an <em>all-in-one loader</em>.\nIt searches the C&nbsp;path for a library for\nthe root name of the given module.\nFor instance, when requiring <code>a.b.c</code>,\nit will search for a C&nbsp;library for <code>a</code>.\nIf found, it looks into it for an open function for\nthe submodule;\nin our example, that would be <code>luaopen_a_b_c</code>.\nWith this facility, a package can pack several C&nbsp;submodules\ninto one single library,\nwith each submodule keeping its original open function.\n\n\n\n\n<p>\n<hr><h3><a name=\"pdf-package.loadlib\"><code>package.loadlib (libname, funcname)</code></a></h3>\n\n\n<p>\nDynamically links the host program with the C&nbsp;library <code>libname</code>.\nInside this library, looks for a function <code>funcname</code>\nand returns this function as a C&nbsp;function.\n(So, <code>funcname</code> must follow the protocol (see <a href=\"#lua_CFunction\"><code>lua_CFunction</code></a>)).\n\n\n<p>\nThis is a low-level function.\nIt completely bypasses the package and module system.\nUnlike <a href=\"#pdf-require\"><code>require</code></a>,\nit does not perform any path searching and\ndoes not automatically adds extensions.\n<code>libname</code> must be the complete file name of the C&nbsp;library,\nincluding if necessary a path and extension.\n<code>funcname</code> must be the exact name exported by the C&nbsp;library\n(which may depend on the C&nbsp;compiler and linker used).\n\n\n<p>\nThis function is not supported by ANSI C.\nAs such, it is only available on some platforms\n(Windows, Linux, Mac OS X, Solaris, BSD,\nplus other Unix systems that support the <code>dlfcn</code> standard).\n\n\n\n\n<p>\n<hr><h3><a name=\"pdf-package.path\"><code>package.path</code></a></h3>\n\n\n<p>\nThe path used by <a href=\"#pdf-require\"><code>require</code></a> to search for a Lua loader.\n\n\n<p>\nAt start-up, Lua initializes this variable with\nthe value of the environment variable <a name=\"pdf-LUA_PATH\"><code>LUA_PATH</code></a> or\nwith a default path defined in <code>luaconf.h</code>,\nif the environment variable is not defined.\nAny \"<code>;;</code>\" in the value of the environment variable\nis replaced by the default path.\n\n\n\n\n<p>\n<hr><h3><a name=\"pdf-package.preload\"><code>package.preload</code></a></h3>\n\n\n<p>\nA table to store loaders for specific modules\n(see <a href=\"#pdf-require\"><code>require</code></a>).\n\n\n\n\n<p>\n<hr><h3><a name=\"pdf-package.seeall\"><code>package.seeall (module)</code></a></h3>\n\n\n<p>\nSets a metatable for <code>module</code> with\nits <code>__index</code> field referring to the global environment,\nso that this module inherits values\nfrom the global environment.\nTo be used as an option to function <a href=\"#pdf-module\"><code>module</code></a>.\n\n\n\n\n\n\n\n<h2>5.4 - <a name=\"5.4\">String Manipulation</a></h2>\n\n<p>\nThis library provides generic functions for string manipulation,\nsuch as finding and extracting substrings, and pattern matching.\nWhen indexing a string in Lua, the first character is at position&nbsp;1\n(not at&nbsp;0, as in C).\nIndices are allowed to be negative and are interpreted as indexing backwards,\nfrom the end of the string.\nThus, the last character is at position -1, and so on.\n\n\n<p>\nThe string library provides all its functions inside the table\n<a name=\"pdf-string\"><code>string</code></a>.\nIt also sets a metatable for strings\nwhere the <code>__index</code> field points to the <code>string</code> table.\nTherefore, you can use the string functions in object-oriented style.\nFor instance, <code>string.byte(s, i)</code>\ncan be written as <code>s:byte(i)</code>.\n\n\n<p>\nThe string library assumes one-byte character encodings.\n\n\n<p>\n<hr><h3><a name=\"pdf-string.byte\"><code>string.byte (s [, i [, j]])</code></a></h3>\nReturns the internal numerical codes of the characters <code>s[i]</code>,\n<code>s[i+1]</code>, &middot;&middot;&middot;, <code>s[j]</code>.\nThe default value for <code>i</code> is&nbsp;1;\nthe default value for <code>j</code> is&nbsp;<code>i</code>.\n\n\n<p>\nNote that numerical codes are not necessarily portable across platforms.\n\n\n\n\n<p>\n<hr><h3><a name=\"pdf-string.char\"><code>string.char (&middot;&middot;&middot;)</code></a></h3>\nReceives zero or more integers.\nReturns a string with length equal to the number of arguments,\nin which each character has the internal numerical code equal\nto its corresponding argument.\n\n\n<p>\nNote that numerical codes are not necessarily portable across platforms.\n\n\n\n\n<p>\n<hr><h3><a name=\"pdf-string.dump\"><code>string.dump (function)</code></a></h3>\n\n\n<p>\nReturns a string containing a binary representation of the given function,\nso that a later <a href=\"#pdf-loadstring\"><code>loadstring</code></a> on this string returns\na copy of the function.\n<code>function</code> must be a Lua function without upvalues.\n\n\n\n\n<p>\n<hr><h3><a name=\"pdf-string.find\"><code>string.find (s, pattern [, init [, plain]])</code></a></h3>\nLooks for the first match of\n<code>pattern</code> in the string <code>s</code>.\nIf it finds a match, then <code>find</code> returns the indices of&nbsp;<code>s</code>\nwhere this occurrence starts and ends;\notherwise, it returns <b>nil</b>.\nA third, optional numerical argument <code>init</code> specifies\nwhere to start the search;\nits default value is&nbsp;1 and can be negative.\nA value of <b>true</b> as a fourth, optional argument <code>plain</code>\nturns off the pattern matching facilities,\nso the function does a plain \"find substring\" operation,\nwith no characters in <code>pattern</code> being considered \"magic\".\nNote that if <code>plain</code> is given, then <code>init</code> must be given as well.\n\n\n<p>\nIf the pattern has captures,\nthen in a successful match\nthe captured values are also returned,\nafter the two indices.\n\n\n\n\n<p>\n<hr><h3><a name=\"pdf-string.format\"><code>string.format (formatstring, &middot;&middot;&middot;)</code></a></h3>\nReturns a formatted version of its variable number of arguments\nfollowing the description given in its first argument (which must be a string).\nThe format string follows the same rules as the <code>printf</code> family of\nstandard C&nbsp;functions.\nThe only differences are that the options/modifiers\n<code>*</code>, <code>l</code>, <code>L</code>, <code>n</code>, <code>p</code>,\nand <code>h</code> are not supported\nand that there is an extra option, <code>q</code>.\nThe <code>q</code> option formats a string in a form suitable to be safely read\nback by the Lua interpreter:\nthe string is written between double quotes,\nand all double quotes, newlines, embedded zeros,\nand backslashes in the string\nare correctly escaped when written.\nFor instance, the call\n\n<pre>\n     string.format('%q', 'a string with \"quotes\" and \\n new line')\n</pre><p>\nwill produce the string:\n\n<pre>\n     \"a string with \\\"quotes\\\" and \\\n      new line\"\n</pre>\n\n<p>\nThe options <code>c</code>, <code>d</code>, <code>E</code>, <code>e</code>, <code>f</code>,\n<code>g</code>, <code>G</code>, <code>i</code>, <code>o</code>, <code>u</code>, <code>X</code>, and <code>x</code> all\nexpect a number as argument,\nwhereas <code>q</code> and <code>s</code> expect a string.\n\n\n<p>\nThis function does not accept string values\ncontaining embedded zeros,\nexcept as arguments to the <code>q</code> option.\n\n\n\n\n<p>\n<hr><h3><a name=\"pdf-string.gmatch\"><code>string.gmatch (s, pattern)</code></a></h3>\nReturns an iterator function that,\neach time it is called,\nreturns the next captures from <code>pattern</code> over string <code>s</code>.\nIf <code>pattern</code> specifies no captures,\nthen the whole match is produced in each call.\n\n\n<p>\nAs an example, the following loop\n\n<pre>\n     s = \"hello world from Lua\"\n     for w in string.gmatch(s, \"%a+\") do\n       print(w)\n     end\n</pre><p>\nwill iterate over all the words from string <code>s</code>,\nprinting one per line.\nThe next example collects all pairs <code>key=value</code> from the\ngiven string into a table:\n\n<pre>\n     t = {}\n     s = \"from=world, to=Lua\"\n     for k, v in string.gmatch(s, \"(%w+)=(%w+)\") do\n       t[k] = v\n     end\n</pre>\n\n<p>\nFor this function, a '<code>^</code>' at the start of a pattern does not\nwork as an anchor, as this would prevent the iteration.\n\n\n\n\n<p>\n<hr><h3><a name=\"pdf-string.gsub\"><code>string.gsub (s, pattern, repl [, n])</code></a></h3>\nReturns a copy of <code>s</code>\nin which all (or the first <code>n</code>, if given)\noccurrences of the <code>pattern</code> have been\nreplaced by a replacement string specified by <code>repl</code>,\nwhich can be a string, a table, or a function.\n<code>gsub</code> also returns, as its second value,\nthe total number of matches that occurred.\n\n\n<p>\nIf <code>repl</code> is a string, then its value is used for replacement.\nThe character&nbsp;<code>%</code> works as an escape character:\nany sequence in <code>repl</code> of the form <code>%<em>n</em></code>,\nwith <em>n</em> between 1 and 9,\nstands for the value of the <em>n</em>-th captured substring (see below).\nThe sequence <code>%0</code> stands for the whole match.\nThe sequence <code>%%</code> stands for a single&nbsp;<code>%</code>.\n\n\n<p>\nIf <code>repl</code> is a table, then the table is queried for every match,\nusing the first capture as the key;\nif the pattern specifies no captures,\nthen the whole match is used as the key.\n\n\n<p>\nIf <code>repl</code> is a function, then this function is called every time a\nmatch occurs, with all captured substrings passed as arguments,\nin order;\nif the pattern specifies no captures,\nthen the whole match is passed as a sole argument.\n\n\n<p>\nIf the value returned by the table query or by the function call\nis a string or a number,\nthen it is used as the replacement string;\notherwise, if it is <b>false</b> or <b>nil</b>,\nthen there is no replacement\n(that is, the original match is kept in the string).\n\n\n<p>\nHere are some examples:\n\n<pre>\n     x = string.gsub(\"hello world\", \"(%w+)\", \"%1 %1\")\n     --&gt; x=\"hello hello world world\"\n     \n     x = string.gsub(\"hello world\", \"%w+\", \"%0 %0\", 1)\n     --&gt; x=\"hello hello world\"\n     \n     x = string.gsub(\"hello world from Lua\", \"(%w+)%s*(%w+)\", \"%2 %1\")\n     --&gt; x=\"world hello Lua from\"\n     \n     x = string.gsub(\"home = $HOME, user = $USER\", \"%$(%w+)\", os.getenv)\n     --&gt; x=\"home = /home/roberto, user = roberto\"\n     \n     x = string.gsub(\"4+5 = $return 4+5$\", \"%$(.-)%$\", function (s)\n           return loadstring(s)()\n         end)\n     --&gt; x=\"4+5 = 9\"\n     \n     local t = {name=\"lua\", version=\"5.1\"}\n     x = string.gsub(\"$name-$version.tar.gz\", \"%$(%w+)\", t)\n     --&gt; x=\"lua-5.1.tar.gz\"\n</pre>\n\n\n\n<p>\n<hr><h3><a name=\"pdf-string.len\"><code>string.len (s)</code></a></h3>\nReceives a string and returns its length.\nThe empty string <code>\"\"</code> has length 0.\nEmbedded zeros are counted,\nso <code>\"a\\000bc\\000\"</code> has length 5.\n\n\n\n\n<p>\n<hr><h3><a name=\"pdf-string.lower\"><code>string.lower (s)</code></a></h3>\nReceives a string and returns a copy of this string with all\nuppercase letters changed to lowercase.\nAll other characters are left unchanged.\nThe definition of what an uppercase letter is depends on the current locale.\n\n\n\n\n<p>\n<hr><h3><a name=\"pdf-string.match\"><code>string.match (s, pattern [, init])</code></a></h3>\nLooks for the first <em>match</em> of\n<code>pattern</code> in the string <code>s</code>.\nIf it finds one, then <code>match</code> returns\nthe captures from the pattern;\notherwise it returns <b>nil</b>.\nIf <code>pattern</code> specifies no captures,\nthen the whole match is returned.\nA third, optional numerical argument <code>init</code> specifies\nwhere to start the search;\nits default value is&nbsp;1 and can be negative.\n\n\n\n\n<p>\n<hr><h3><a name=\"pdf-string.rep\"><code>string.rep (s, n)</code></a></h3>\nReturns a string that is the concatenation of <code>n</code> copies of\nthe string <code>s</code>.\n\n\n\n\n<p>\n<hr><h3><a name=\"pdf-string.reverse\"><code>string.reverse (s)</code></a></h3>\nReturns a string that is the string <code>s</code> reversed.\n\n\n\n\n<p>\n<hr><h3><a name=\"pdf-string.sub\"><code>string.sub (s, i [, j])</code></a></h3>\nReturns the substring of <code>s</code> that\nstarts at <code>i</code>  and continues until <code>j</code>;\n<code>i</code> and <code>j</code> can be negative.\nIf <code>j</code> is absent, then it is assumed to be equal to -1\n(which is the same as the string length).\nIn particular,\nthe call <code>string.sub(s,1,j)</code> returns a prefix of <code>s</code>\nwith length <code>j</code>,\nand <code>string.sub(s, -i)</code> returns a suffix of <code>s</code>\nwith length <code>i</code>.\n\n\n\n\n<p>\n<hr><h3><a name=\"pdf-string.upper\"><code>string.upper (s)</code></a></h3>\nReceives a string and returns a copy of this string with all\nlowercase letters changed to uppercase.\nAll other characters are left unchanged.\nThe definition of what a lowercase letter is depends on the current locale.\n\n\n\n<h3>5.4.1 - <a name=\"5.4.1\">Patterns</a></h3>\n\n\n<h4>Character Class:</h4><p>\nA <em>character class</em> is used to represent a set of characters.\nThe following combinations are allowed in describing a character class:\n\n<ul>\n\n<li><b><em>x</em>:</b>\n(where <em>x</em> is not one of the <em>magic characters</em>\n<code>^$()%.[]*+-?</code>)\nrepresents the character <em>x</em> itself.\n</li>\n\n<li><b><code>.</code>:</b> (a dot) represents all characters.</li>\n\n<li><b><code>%a</code>:</b> represents all letters.</li>\n\n<li><b><code>%c</code>:</b> represents all control characters.</li>\n\n<li><b><code>%d</code>:</b> represents all digits.</li>\n\n<li><b><code>%l</code>:</b> represents all lowercase letters.</li>\n\n<li><b><code>%p</code>:</b> represents all punctuation characters.</li>\n\n<li><b><code>%s</code>:</b> represents all space characters.</li>\n\n<li><b><code>%u</code>:</b> represents all uppercase letters.</li>\n\n<li><b><code>%w</code>:</b> represents all alphanumeric characters.</li>\n\n<li><b><code>%x</code>:</b> represents all hexadecimal digits.</li>\n\n<li><b><code>%z</code>:</b> represents the character with representation 0.</li>\n\n<li><b><code>%<em>x</em></code>:</b> (where <em>x</em> is any non-alphanumeric character)\nrepresents the character <em>x</em>.\nThis is the standard way to escape the magic characters.\nAny punctuation character (even the non magic)\ncan be preceded by a '<code>%</code>'\nwhen used to represent itself in a pattern.\n</li>\n\n<li><b><code>[<em>set</em>]</code>:</b>\nrepresents the class which is the union of all\ncharacters in <em>set</em>.\nA range of characters can be specified by\nseparating the end characters of the range with a '<code>-</code>'.\nAll classes <code>%</code><em>x</em> described above can also be used as\ncomponents in <em>set</em>.\nAll other characters in <em>set</em> represent themselves.\nFor example, <code>[%w_]</code> (or <code>[_%w]</code>)\nrepresents all alphanumeric characters plus the underscore,\n<code>[0-7]</code> represents the octal digits,\nand <code>[0-7%l%-]</code> represents the octal digits plus\nthe lowercase letters plus the '<code>-</code>' character.\n\n\n<p>\nThe interaction between ranges and classes is not defined.\nTherefore, patterns like <code>[%a-z]</code> or <code>[a-%%]</code>\nhave no meaning.\n</li>\n\n<li><b><code>[^<em>set</em>]</code>:</b>\nrepresents the complement of <em>set</em>,\nwhere <em>set</em> is interpreted as above.\n</li>\n\n</ul><p>\nFor all classes represented by single letters (<code>%a</code>, <code>%c</code>, etc.),\nthe corresponding uppercase letter represents the complement of the class.\nFor instance, <code>%S</code> represents all non-space characters.\n\n\n<p>\nThe definitions of letter, space, and other character groups\ndepend on the current locale.\nIn particular, the class <code>[a-z]</code> may not be equivalent to <code>%l</code>.\n\n\n\n\n\n<h4>Pattern Item:</h4><p>\nA <em>pattern item</em> can be\n\n<ul>\n\n<li>\na single character class,\nwhich matches any single character in the class;\n</li>\n\n<li>\na single character class followed by '<code>*</code>',\nwhich matches 0 or more repetitions of characters in the class.\nThese repetition items will always match the longest possible sequence;\n</li>\n\n<li>\na single character class followed by '<code>+</code>',\nwhich matches 1 or more repetitions of characters in the class.\nThese repetition items will always match the longest possible sequence;\n</li>\n\n<li>\na single character class followed by '<code>-</code>',\nwhich also matches 0 or more repetitions of characters in the class.\nUnlike '<code>*</code>',\nthese repetition items will always match the <em>shortest</em> possible sequence;\n</li>\n\n<li>\na single character class followed by '<code>?</code>',\nwhich matches 0 or 1 occurrence of a character in the class;\n</li>\n\n<li>\n<code>%<em>n</em></code>, for <em>n</em> between 1 and 9;\nsuch item matches a substring equal to the <em>n</em>-th captured string\n(see below);\n</li>\n\n<li>\n<code>%b<em>xy</em></code>, where <em>x</em> and <em>y</em> are two distinct characters;\nsuch item matches strings that start with&nbsp;<em>x</em>, end with&nbsp;<em>y</em>,\nand where the <em>x</em> and <em>y</em> are <em>balanced</em>.\nThis means that, if one reads the string from left to right,\ncounting <em>+1</em> for an <em>x</em> and <em>-1</em> for a <em>y</em>,\nthe ending <em>y</em> is the first <em>y</em> where the count reaches 0.\nFor instance, the item <code>%b()</code> matches expressions with\nbalanced parentheses.\n</li>\n\n</ul>\n\n\n\n\n<h4>Pattern:</h4><p>\nA <em>pattern</em> is a sequence of pattern items.\nA '<code>^</code>' at the beginning of a pattern anchors the match at the\nbeginning of the subject string.\nA '<code>$</code>' at the end of a pattern anchors the match at the\nend of the subject string.\nAt other positions,\n'<code>^</code>' and '<code>$</code>' have no special meaning and represent themselves.\n\n\n\n\n\n<h4>Captures:</h4><p>\nA pattern can contain sub-patterns enclosed in parentheses;\nthey describe <em>captures</em>.\nWhen a match succeeds, the substrings of the subject string\nthat match captures are stored (<em>captured</em>) for future use.\nCaptures are numbered according to their left parentheses.\nFor instance, in the pattern <code>\"(a*(.)%w(%s*))\"</code>,\nthe part of the string matching <code>\"a*(.)%w(%s*)\"</code> is\nstored as the first capture (and therefore has number&nbsp;1);\nthe character matching \"<code>.</code>\" is captured with number&nbsp;2,\nand the part matching \"<code>%s*</code>\" has number&nbsp;3.\n\n\n<p>\nAs a special case, the empty capture <code>()</code> captures\nthe current string position (a number).\nFor instance, if we apply the pattern <code>\"()aa()\"</code> on the\nstring <code>\"flaaap\"</code>, there will be two captures: 3&nbsp;and&nbsp;5.\n\n\n<p>\nA pattern cannot contain embedded zeros.  Use <code>%z</code> instead.\n\n\n\n\n\n\n\n\n\n\n\n<h2>5.5 - <a name=\"5.5\">Table Manipulation</a></h2><p>\nThis library provides generic functions for table manipulation.\nIt provides all its functions inside the table <a name=\"pdf-table\"><code>table</code></a>.\n\n\n<p>\nMost functions in the table library assume that the table\nrepresents an array or a list.\nFor these functions, when we talk about the \"length\" of a table\nwe mean the result of the length operator.\n\n\n<p>\n<hr><h3><a name=\"pdf-table.concat\"><code>table.concat (table [, sep [, i [, j]]])</code></a></h3>\nGiven an array where all elements are strings or numbers,\nreturns <code>table[i]..sep..table[i+1] &middot;&middot;&middot; sep..table[j]</code>.\nThe default value for <code>sep</code> is the empty string,\nthe default for <code>i</code> is 1,\nand the default for <code>j</code> is the length of the table.\nIf <code>i</code> is greater than <code>j</code>, returns the empty string.\n\n\n\n\n<p>\n<hr><h3><a name=\"pdf-table.insert\"><code>table.insert (table, [pos,] value)</code></a></h3>\n\n\n<p>\nInserts element <code>value</code> at position <code>pos</code> in <code>table</code>,\nshifting up other elements to open space, if necessary.\nThe default value for <code>pos</code> is <code>n+1</code>,\nwhere <code>n</code> is the length of the table (see <a href=\"#2.5.5\">&sect;2.5.5</a>),\nso that a call <code>table.insert(t,x)</code> inserts <code>x</code> at the end\nof table <code>t</code>.\n\n\n\n\n<p>\n<hr><h3><a name=\"pdf-table.maxn\"><code>table.maxn (table)</code></a></h3>\n\n\n<p>\nReturns the largest positive numerical index of the given table,\nor zero if the table has no positive numerical indices.\n(To do its job this function does a linear traversal of\nthe whole table.) \n\n\n\n\n<p>\n<hr><h3><a name=\"pdf-table.remove\"><code>table.remove (table [, pos])</code></a></h3>\n\n\n<p>\nRemoves from <code>table</code> the element at position <code>pos</code>,\nshifting down other elements to close the space, if necessary.\nReturns the value of the removed element.\nThe default value for <code>pos</code> is <code>n</code>,\nwhere <code>n</code> is the length of the table,\nso that a call <code>table.remove(t)</code> removes the last element\nof table <code>t</code>.\n\n\n\n\n<p>\n<hr><h3><a name=\"pdf-table.sort\"><code>table.sort (table [, comp])</code></a></h3>\nSorts table elements in a given order, <em>in-place</em>,\nfrom <code>table[1]</code> to <code>table[n]</code>,\nwhere <code>n</code> is the length of the table.\nIf <code>comp</code> is given,\nthen it must be a function that receives two table elements,\nand returns true\nwhen the first is less than the second\n(so that <code>not comp(a[i+1],a[i])</code> will be true after the sort).\nIf <code>comp</code> is not given,\nthen the standard Lua operator <code>&lt;</code> is used instead.\n\n\n<p>\nThe sort algorithm is not stable;\nthat is, elements considered equal by the given order\nmay have their relative positions changed by the sort.\n\n\n\n\n\n\n\n<h2>5.6 - <a name=\"5.6\">Mathematical Functions</a></h2>\n\n<p>\nThis library is an interface to the standard C&nbsp;math library.\nIt provides all its functions inside the table <a name=\"pdf-math\"><code>math</code></a>.\n\n\n<p>\n<hr><h3><a name=\"pdf-math.abs\"><code>math.abs (x)</code></a></h3>\n\n\n<p>\nReturns the absolute value of <code>x</code>.\n\n\n\n\n<p>\n<hr><h3><a name=\"pdf-math.acos\"><code>math.acos (x)</code></a></h3>\n\n\n<p>\nReturns the arc cosine of <code>x</code> (in radians).\n\n\n\n\n<p>\n<hr><h3><a name=\"pdf-math.asin\"><code>math.asin (x)</code></a></h3>\n\n\n<p>\nReturns the arc sine of <code>x</code> (in radians).\n\n\n\n\n<p>\n<hr><h3><a name=\"pdf-math.atan\"><code>math.atan (x)</code></a></h3>\n\n\n<p>\nReturns the arc tangent of <code>x</code> (in radians).\n\n\n\n\n<p>\n<hr><h3><a name=\"pdf-math.atan2\"><code>math.atan2 (y, x)</code></a></h3>\n\n\n<p>\nReturns the arc tangent of <code>y/x</code> (in radians),\nbut uses the signs of both parameters to find the\nquadrant of the result.\n(It also handles correctly the case of <code>x</code> being zero.)\n\n\n\n\n<p>\n<hr><h3><a name=\"pdf-math.ceil\"><code>math.ceil (x)</code></a></h3>\n\n\n<p>\nReturns the smallest integer larger than or equal to <code>x</code>.\n\n\n\n\n<p>\n<hr><h3><a name=\"pdf-math.cos\"><code>math.cos (x)</code></a></h3>\n\n\n<p>\nReturns the cosine of <code>x</code> (assumed to be in radians).\n\n\n\n\n<p>\n<hr><h3><a name=\"pdf-math.cosh\"><code>math.cosh (x)</code></a></h3>\n\n\n<p>\nReturns the hyperbolic cosine of <code>x</code>.\n\n\n\n\n<p>\n<hr><h3><a name=\"pdf-math.deg\"><code>math.deg (x)</code></a></h3>\n\n\n<p>\nReturns the angle <code>x</code> (given in radians) in degrees.\n\n\n\n\n<p>\n<hr><h3><a name=\"pdf-math.exp\"><code>math.exp (x)</code></a></h3>\n\n\n<p>\nReturns the value <em>e<sup>x</sup></em>.\n\n\n\n\n<p>\n<hr><h3><a name=\"pdf-math.floor\"><code>math.floor (x)</code></a></h3>\n\n\n<p>\nReturns the largest integer smaller than or equal to <code>x</code>.\n\n\n\n\n<p>\n<hr><h3><a name=\"pdf-math.fmod\"><code>math.fmod (x, y)</code></a></h3>\n\n\n<p>\nReturns the remainder of the division of <code>x</code> by <code>y</code>\nthat rounds the quotient towards zero.\n\n\n\n\n<p>\n<hr><h3><a name=\"pdf-math.frexp\"><code>math.frexp (x)</code></a></h3>\n\n\n<p>\nReturns <code>m</code> and <code>e</code> such that <em>x = m2<sup>e</sup></em>,\n<code>e</code> is an integer and the absolute value of <code>m</code> is\nin the range <em>[0.5, 1)</em>\n(or zero when <code>x</code> is zero).\n\n\n\n\n<p>\n<hr><h3><a name=\"pdf-math.huge\"><code>math.huge</code></a></h3>\n\n\n<p>\nThe value <code>HUGE_VAL</code>,\na value larger than or equal to any other numerical value.\n\n\n\n\n<p>\n<hr><h3><a name=\"pdf-math.ldexp\"><code>math.ldexp (m, e)</code></a></h3>\n\n\n<p>\nReturns <em>m2<sup>e</sup></em> (<code>e</code> should be an integer).\n\n\n\n\n<p>\n<hr><h3><a name=\"pdf-math.log\"><code>math.log (x)</code></a></h3>\n\n\n<p>\nReturns the natural logarithm of <code>x</code>.\n\n\n\n\n<p>\n<hr><h3><a name=\"pdf-math.log10\"><code>math.log10 (x)</code></a></h3>\n\n\n<p>\nReturns the base-10 logarithm of <code>x</code>.\n\n\n\n\n<p>\n<hr><h3><a name=\"pdf-math.max\"><code>math.max (x, &middot;&middot;&middot;)</code></a></h3>\n\n\n<p>\nReturns the maximum value among its arguments.\n\n\n\n\n<p>\n<hr><h3><a name=\"pdf-math.min\"><code>math.min (x, &middot;&middot;&middot;)</code></a></h3>\n\n\n<p>\nReturns the minimum value among its arguments.\n\n\n\n\n<p>\n<hr><h3><a name=\"pdf-math.modf\"><code>math.modf (x)</code></a></h3>\n\n\n<p>\nReturns two numbers,\nthe integral part of <code>x</code> and the fractional part of <code>x</code>.\n\n\n\n\n<p>\n<hr><h3><a name=\"pdf-math.pi\"><code>math.pi</code></a></h3>\n\n\n<p>\nThe value of <em>pi</em>.\n\n\n\n\n<p>\n<hr><h3><a name=\"pdf-math.pow\"><code>math.pow (x, y)</code></a></h3>\n\n\n<p>\nReturns <em>x<sup>y</sup></em>.\n(You can also use the expression <code>x^y</code> to compute this value.)\n\n\n\n\n<p>\n<hr><h3><a name=\"pdf-math.rad\"><code>math.rad (x)</code></a></h3>\n\n\n<p>\nReturns the angle <code>x</code> (given in degrees) in radians.\n\n\n\n\n<p>\n<hr><h3><a name=\"pdf-math.random\"><code>math.random ([m [, n]])</code></a></h3>\n\n\n<p>\nThis function is an interface to the simple\npseudo-random generator function <code>rand</code> provided by ANSI&nbsp;C.\n(No guarantees can be given for its statistical properties.)\n\n\n<p>\nWhen called without arguments,\nreturns a uniform pseudo-random real number\nin the range <em>[0,1)</em>.  \nWhen called with an integer number <code>m</code>,\n<code>math.random</code> returns\na uniform pseudo-random integer in the range <em>[1, m]</em>.\nWhen called with two integer numbers <code>m</code> and <code>n</code>,\n<code>math.random</code> returns a uniform pseudo-random\ninteger in the range <em>[m, n]</em>.\n\n\n\n\n<p>\n<hr><h3><a name=\"pdf-math.randomseed\"><code>math.randomseed (x)</code></a></h3>\n\n\n<p>\nSets <code>x</code> as the \"seed\"\nfor the pseudo-random generator:\nequal seeds produce equal sequences of numbers.\n\n\n\n\n<p>\n<hr><h3><a name=\"pdf-math.sin\"><code>math.sin (x)</code></a></h3>\n\n\n<p>\nReturns the sine of <code>x</code> (assumed to be in radians).\n\n\n\n\n<p>\n<hr><h3><a name=\"pdf-math.sinh\"><code>math.sinh (x)</code></a></h3>\n\n\n<p>\nReturns the hyperbolic sine of <code>x</code>.\n\n\n\n\n<p>\n<hr><h3><a name=\"pdf-math.sqrt\"><code>math.sqrt (x)</code></a></h3>\n\n\n<p>\nReturns the square root of <code>x</code>.\n(You can also use the expression <code>x^0.5</code> to compute this value.)\n\n\n\n\n<p>\n<hr><h3><a name=\"pdf-math.tan\"><code>math.tan (x)</code></a></h3>\n\n\n<p>\nReturns the tangent of <code>x</code> (assumed to be in radians).\n\n\n\n\n<p>\n<hr><h3><a name=\"pdf-math.tanh\"><code>math.tanh (x)</code></a></h3>\n\n\n<p>\nReturns the hyperbolic tangent of <code>x</code>.\n\n\n\n\n\n\n\n<h2>5.7 - <a name=\"5.7\">Input and Output Facilities</a></h2>\n\n<p>\nThe I/O library provides two different styles for file manipulation.\nThe first one uses implicit file descriptors;\nthat is, there are operations to set a default input file and a\ndefault output file,\nand all input/output operations are over these default files.\nThe second style uses explicit file descriptors.\n\n\n<p>\nWhen using implicit file descriptors,\nall operations are supplied by table <a name=\"pdf-io\"><code>io</code></a>.\nWhen using explicit file descriptors,\nthe operation <a href=\"#pdf-io.open\"><code>io.open</code></a> returns a file descriptor\nand then all operations are supplied as methods of the file descriptor.\n\n\n<p>\nThe table <code>io</code> also provides\nthree predefined file descriptors with their usual meanings from C:\n<a name=\"pdf-io.stdin\"><code>io.stdin</code></a>, <a name=\"pdf-io.stdout\"><code>io.stdout</code></a>, and <a name=\"pdf-io.stderr\"><code>io.stderr</code></a>.\nThe I/O library never closes these files.\n\n\n<p>\nUnless otherwise stated,\nall I/O functions return <b>nil</b> on failure\n(plus an error message as a second result and\na system-dependent error code as a third result)\nand some value different from <b>nil</b> on success.\n\n\n<p>\n<hr><h3><a name=\"pdf-io.close\"><code>io.close ([file])</code></a></h3>\n\n\n<p>\nEquivalent to <code>file:close()</code>.\nWithout a <code>file</code>, closes the default output file.\n\n\n\n\n<p>\n<hr><h3><a name=\"pdf-io.flush\"><code>io.flush ()</code></a></h3>\n\n\n<p>\nEquivalent to <code>file:flush</code> over the default output file.\n\n\n\n\n<p>\n<hr><h3><a name=\"pdf-io.input\"><code>io.input ([file])</code></a></h3>\n\n\n<p>\nWhen called with a file name, it opens the named file (in text mode),\nand sets its handle as the default input file.\nWhen called with a file handle,\nit simply sets this file handle as the default input file.\nWhen called without parameters,\nit returns the current default input file.\n\n\n<p>\nIn case of errors this function raises the error,\ninstead of returning an error code.\n\n\n\n\n<p>\n<hr><h3><a name=\"pdf-io.lines\"><code>io.lines ([filename])</code></a></h3>\n\n\n<p>\nOpens the given file name in read mode\nand returns an iterator function that,\neach time it is called,\nreturns a new line from the file.\nTherefore, the construction\n\n<pre>\n     for line in io.lines(filename) do <em>body</em> end\n</pre><p>\nwill iterate over all lines of the file.\nWhen the iterator function detects the end of file,\nit returns <b>nil</b> (to finish the loop) and automatically closes the file.\n\n\n<p>\nThe call <code>io.lines()</code> (with no file name) is equivalent\nto <code>io.input():lines()</code>;\nthat is, it iterates over the lines of the default input file.\nIn this case it does not close the file when the loop ends.\n\n\n\n\n<p>\n<hr><h3><a name=\"pdf-io.open\"><code>io.open (filename [, mode])</code></a></h3>\n\n\n<p>\nThis function opens a file,\nin the mode specified in the string <code>mode</code>.\nIt returns a new file handle,\nor, in case of errors, <b>nil</b> plus an error message.\n\n\n<p>\nThe <code>mode</code> string can be any of the following:\n\n<ul>\n<li><b>\"r\":</b> read mode (the default);</li>\n<li><b>\"w\":</b> write mode;</li>\n<li><b>\"a\":</b> append mode;</li>\n<li><b>\"r+\":</b> update mode, all previous data is preserved;</li>\n<li><b>\"w+\":</b> update mode, all previous data is erased;</li>\n<li><b>\"a+\":</b> append update mode, previous data is preserved,\n  writing is only allowed at the end of file.</li>\n</ul><p>\nThe <code>mode</code> string can also have a '<code>b</code>' at the end,\nwhich is needed in some systems to open the file in binary mode.\nThis string is exactly what is used in the\nstandard&nbsp;C function <code>fopen</code>.\n\n\n\n\n<p>\n<hr><h3><a name=\"pdf-io.output\"><code>io.output ([file])</code></a></h3>\n\n\n<p>\nSimilar to <a href=\"#pdf-io.input\"><code>io.input</code></a>, but operates over the default output file.\n\n\n\n\n<p>\n<hr><h3><a name=\"pdf-io.popen\"><code>io.popen (prog [, mode])</code></a></h3>\n\n\n<p>\nStarts program <code>prog</code> in a separated process and returns\na file handle that you can use to read data from this program\n(if <code>mode</code> is <code>\"r\"</code>, the default)\nor to write data to this program\n(if <code>mode</code> is <code>\"w\"</code>).\n\n\n<p>\nThis function is system dependent and is not available\non all platforms.\n\n\n\n\n<p>\n<hr><h3><a name=\"pdf-io.read\"><code>io.read (&middot;&middot;&middot;)</code></a></h3>\n\n\n<p>\nEquivalent to <code>io.input():read</code>.\n\n\n\n\n<p>\n<hr><h3><a name=\"pdf-io.tmpfile\"><code>io.tmpfile ()</code></a></h3>\n\n\n<p>\nReturns a handle for a temporary file.\nThis file is opened in update mode\nand it is automatically removed when the program ends.\n\n\n\n\n<p>\n<hr><h3><a name=\"pdf-io.type\"><code>io.type (obj)</code></a></h3>\n\n\n<p>\nChecks whether <code>obj</code> is a valid file handle.\nReturns the string <code>\"file\"</code> if <code>obj</code> is an open file handle,\n<code>\"closed file\"</code> if <code>obj</code> is a closed file handle,\nor <b>nil</b> if <code>obj</code> is not a file handle.\n\n\n\n\n<p>\n<hr><h3><a name=\"pdf-io.write\"><code>io.write (&middot;&middot;&middot;)</code></a></h3>\n\n\n<p>\nEquivalent to <code>io.output():write</code>.\n\n\n\n\n<p>\n<hr><h3><a name=\"pdf-file:close\"><code>file:close ()</code></a></h3>\n\n\n<p>\nCloses <code>file</code>.\nNote that files are automatically closed when\ntheir handles are garbage collected,\nbut that takes an unpredictable amount of time to happen.\n\n\n\n\n<p>\n<hr><h3><a name=\"pdf-file:flush\"><code>file:flush ()</code></a></h3>\n\n\n<p>\nSaves any written data to <code>file</code>.\n\n\n\n\n<p>\n<hr><h3><a name=\"pdf-file:lines\"><code>file:lines ()</code></a></h3>\n\n\n<p>\nReturns an iterator function that,\neach time it is called,\nreturns a new line from the file.\nTherefore, the construction\n\n<pre>\n     for line in file:lines() do <em>body</em> end\n</pre><p>\nwill iterate over all lines of the file.\n(Unlike <a href=\"#pdf-io.lines\"><code>io.lines</code></a>, this function does not close the file\nwhen the loop ends.)\n\n\n\n\n<p>\n<hr><h3><a name=\"pdf-file:read\"><code>file:read (&middot;&middot;&middot;)</code></a></h3>\n\n\n<p>\nReads the file <code>file</code>,\naccording to the given formats, which specify what to read.\nFor each format,\nthe function returns a string (or a number) with the characters read,\nor <b>nil</b> if it cannot read data with the specified format.\nWhen called without formats,\nit uses a default format that reads the entire next line\n(see below).\n\n\n<p>\nThe available formats are\n\n<ul>\n\n<li><b>\"*n\":</b>\nreads a number;\nthis is the only format that returns a number instead of a string.\n</li>\n\n<li><b>\"*a\":</b>\nreads the whole file, starting at the current position.\nOn end of file, it returns the empty string.\n</li>\n\n<li><b>\"*l\":</b>\nreads the next line (skipping the end of line),\nreturning <b>nil</b> on end of file.\nThis is the default format.\n</li>\n\n<li><b><em>number</em>:</b>\nreads a string with up to this number of characters,\nreturning <b>nil</b> on end of file.\nIf number is zero,\nit reads nothing and returns an empty string,\nor <b>nil</b> on end of file.\n</li>\n\n</ul>\n\n\n\n<p>\n<hr><h3><a name=\"pdf-file:seek\"><code>file:seek ([whence] [, offset])</code></a></h3>\n\n\n<p>\nSets and gets the file position,\nmeasured from the beginning of the file,\nto the position given by <code>offset</code> plus a base\nspecified by the string <code>whence</code>, as follows:\n\n<ul>\n<li><b>\"set\":</b> base is position 0 (beginning of the file);</li>\n<li><b>\"cur\":</b> base is current position;</li>\n<li><b>\"end\":</b> base is end of file;</li>\n</ul><p>\nIn case of success, function <code>seek</code> returns the final file position,\nmeasured in bytes from the beginning of the file.\nIf this function fails, it returns <b>nil</b>,\nplus a string describing the error.\n\n\n<p>\nThe default value for <code>whence</code> is <code>\"cur\"</code>,\nand for <code>offset</code> is 0.\nTherefore, the call <code>file:seek()</code> returns the current\nfile position, without changing it;\nthe call <code>file:seek(\"set\")</code> sets the position to the\nbeginning of the file (and returns 0);\nand the call <code>file:seek(\"end\")</code> sets the position to the\nend of the file, and returns its size.\n\n\n\n\n<p>\n<hr><h3><a name=\"pdf-file:setvbuf\"><code>file:setvbuf (mode [, size])</code></a></h3>\n\n\n<p>\nSets the buffering mode for an output file.\nThere are three available modes:\n\n<ul>\n\n<li><b>\"no\":</b>\nno buffering; the result of any output operation appears immediately.\n</li>\n\n<li><b>\"full\":</b>\nfull buffering; output operation is performed only\nwhen the buffer is full (or when you explicitly <code>flush</code> the file\n(see <a href=\"#pdf-io.flush\"><code>io.flush</code></a>)).\n</li>\n\n<li><b>\"line\":</b>\nline buffering; output is buffered until a newline is output\nor there is any input from some special files\n(such as a terminal device).\n</li>\n\n</ul><p>\nFor the last two cases, <code>size</code>\nspecifies the size of the buffer, in bytes.\nThe default is an appropriate size.\n\n\n\n\n<p>\n<hr><h3><a name=\"pdf-file:write\"><code>file:write (&middot;&middot;&middot;)</code></a></h3>\n\n\n<p>\nWrites the value of each of its arguments to\nthe <code>file</code>.\nThe arguments must be strings or numbers.\nTo write other values,\nuse <a href=\"#pdf-tostring\"><code>tostring</code></a> or <a href=\"#pdf-string.format\"><code>string.format</code></a> before <code>write</code>.\n\n\n\n\n\n\n\n<h2>5.8 - <a name=\"5.8\">Operating System Facilities</a></h2>\n\n<p>\nThis library is implemented through table <a name=\"pdf-os\"><code>os</code></a>.\n\n\n<p>\n<hr><h3><a name=\"pdf-os.clock\"><code>os.clock ()</code></a></h3>\n\n\n<p>\nReturns an approximation of the amount in seconds of CPU time\nused by the program.\n\n\n\n\n<p>\n<hr><h3><a name=\"pdf-os.date\"><code>os.date ([format [, time]])</code></a></h3>\n\n\n<p>\nReturns a string or a table containing date and time,\nformatted according to the given string <code>format</code>.\n\n\n<p>\nIf the <code>time</code> argument is present,\nthis is the time to be formatted\n(see the <a href=\"#pdf-os.time\"><code>os.time</code></a> function for a description of this value).\nOtherwise, <code>date</code> formats the current time.\n\n\n<p>\nIf <code>format</code> starts with '<code>!</code>',\nthen the date is formatted in Coordinated Universal Time.\nAfter this optional character,\nif <code>format</code> is the string \"<code>*t</code>\",\nthen <code>date</code> returns a table with the following fields:\n<code>year</code> (four digits), <code>month</code> (1--12), <code>day</code> (1--31),\n<code>hour</code> (0--23), <code>min</code> (0--59), <code>sec</code> (0--61),\n<code>wday</code> (weekday, Sunday is&nbsp;1),\n<code>yday</code> (day of the year),\nand <code>isdst</code> (daylight saving flag, a boolean).\n\n\n<p>\nIf <code>format</code> is not \"<code>*t</code>\",\nthen <code>date</code> returns the date as a string,\nformatted according to the same rules as the C&nbsp;function <code>strftime</code>.\n\n\n<p>\nWhen called without arguments,\n<code>date</code> returns a reasonable date and time representation that depends on\nthe host system and on the current locale\n(that is, <code>os.date()</code> is equivalent to <code>os.date(\"%c\")</code>).\n\n\n\n\n<p>\n<hr><h3><a name=\"pdf-os.difftime\"><code>os.difftime (t2, t1)</code></a></h3>\n\n\n<p>\nReturns the number of seconds from time <code>t1</code> to time <code>t2</code>.\nIn POSIX, Windows, and some other systems,\nthis value is exactly <code>t2</code><em>-</em><code>t1</code>.\n\n\n\n\n<p>\n<hr><h3><a name=\"pdf-os.execute\"><code>os.execute ([command])</code></a></h3>\n\n\n<p>\nThis function is equivalent to the C&nbsp;function <code>system</code>.\nIt passes <code>command</code> to be executed by an operating system shell.\nIt returns a status code, which is system-dependent.\nIf <code>command</code> is absent, then it returns nonzero if a shell is available\nand zero otherwise.\n\n\n\n\n<p>\n<hr><h3><a name=\"pdf-os.exit\"><code>os.exit ([code])</code></a></h3>\n\n\n<p>\nCalls the C&nbsp;function <code>exit</code>,\nwith an optional <code>code</code>,\nto terminate the host program.\nThe default value for <code>code</code> is the success code.\n\n\n\n\n<p>\n<hr><h3><a name=\"pdf-os.getenv\"><code>os.getenv (varname)</code></a></h3>\n\n\n<p>\nReturns the value of the process environment variable <code>varname</code>,\nor <b>nil</b> if the variable is not defined.\n\n\n\n\n<p>\n<hr><h3><a name=\"pdf-os.remove\"><code>os.remove (filename)</code></a></h3>\n\n\n<p>\nDeletes the file or directory with the given name.\nDirectories must be empty to be removed.\nIf this function fails, it returns <b>nil</b>,\nplus a string describing the error.\n\n\n\n\n<p>\n<hr><h3><a name=\"pdf-os.rename\"><code>os.rename (oldname, newname)</code></a></h3>\n\n\n<p>\nRenames file or directory named <code>oldname</code> to <code>newname</code>.\nIf this function fails, it returns <b>nil</b>,\nplus a string describing the error.\n\n\n\n\n<p>\n<hr><h3><a name=\"pdf-os.setlocale\"><code>os.setlocale (locale [, category])</code></a></h3>\n\n\n<p>\nSets the current locale of the program.\n<code>locale</code> is a string specifying a locale;\n<code>category</code> is an optional string describing which category to change:\n<code>\"all\"</code>, <code>\"collate\"</code>, <code>\"ctype\"</code>,\n<code>\"monetary\"</code>, <code>\"numeric\"</code>, or <code>\"time\"</code>;\nthe default category is <code>\"all\"</code>.\nThe function returns the name of the new locale,\nor <b>nil</b> if the request cannot be honored.\n\n\n<p>\nIf <code>locale</code> is the empty string,\nthe current locale is set to an implementation-defined native locale.\nIf <code>locale</code> is the string \"<code>C</code>\",\nthe current locale is set to the standard C locale.\n\n\n<p>\nWhen called with <b>nil</b> as the first argument,\nthis function only returns the name of the current locale\nfor the given category.\n\n\n\n\n<p>\n<hr><h3><a name=\"pdf-os.time\"><code>os.time ([table])</code></a></h3>\n\n\n<p>\nReturns the current time when called without arguments,\nor a time representing the date and time specified by the given table.\nThis table must have fields <code>year</code>, <code>month</code>, and <code>day</code>,\nand may have fields <code>hour</code>, <code>min</code>, <code>sec</code>, and <code>isdst</code>\n(for a description of these fields, see the <a href=\"#pdf-os.date\"><code>os.date</code></a> function).\n\n\n<p>\nThe returned value is a number, whose meaning depends on your system.\nIn POSIX, Windows, and some other systems, this number counts the number\nof seconds since some given start time (the \"epoch\").\nIn other systems, the meaning is not specified,\nand the number returned by <code>time</code> can be used only as an argument to\n<code>date</code> and <code>difftime</code>.\n\n\n\n\n<p>\n<hr><h3><a name=\"pdf-os.tmpname\"><code>os.tmpname ()</code></a></h3>\n\n\n<p>\nReturns a string with a file name that can\nbe used for a temporary file.\nThe file must be explicitly opened before its use\nand explicitly removed when no longer needed.\n\n\n<p>\nOn some systems (POSIX),\nthis function also creates a file with that name,\nto avoid security risks.\n(Someone else might create the file with wrong permissions\nin the time between getting the name and creating the file.)\nYou still have to open the file to use it\nand to remove it (even if you do not use it).\n\n\n<p>\nWhen possible,\nyou may prefer to use <a href=\"#pdf-io.tmpfile\"><code>io.tmpfile</code></a>,\nwhich automatically removes the file when the program ends.\n\n\n\n\n\n\n\n<h2>5.9 - <a name=\"5.9\">The Debug Library</a></h2>\n\n<p>\nThis library provides\nthe functionality of the debug interface to Lua programs.\nYou should exert care when using this library.\nThe functions provided here should be used exclusively for debugging\nand similar tasks, such as profiling.\nPlease resist the temptation to use them as a\nusual programming tool:\nthey can be very slow.\nMoreover, several of these functions\nviolate some assumptions about Lua code\n(e.g., that variables local to a function\ncannot be accessed from outside or\nthat userdata metatables cannot be changed by Lua code)\nand therefore can compromise otherwise secure code.\n\n\n<p>\nAll functions in this library are provided\ninside the <a name=\"pdf-debug\"><code>debug</code></a> table.\nAll functions that operate over a thread\nhave an optional first argument which is the\nthread to operate over.\nThe default is always the current thread.\n\n\n<p>\n<hr><h3><a name=\"pdf-debug.debug\"><code>debug.debug ()</code></a></h3>\n\n\n<p>\nEnters an interactive mode with the user,\nrunning each string that the user enters.\nUsing simple commands and other debug facilities,\nthe user can inspect global and local variables,\nchange their values, evaluate expressions, and so on.\nA line containing only the word <code>cont</code> finishes this function,\nso that the caller continues its execution.\n\n\n<p>\nNote that commands for <code>debug.debug</code> are not lexically nested\nwithin any function, and so have no direct access to local variables.\n\n\n\n\n<p>\n<hr><h3><a name=\"pdf-debug.getfenv\"><code>debug.getfenv (o)</code></a></h3>\nReturns the environment of object <code>o</code>.\n\n\n\n\n<p>\n<hr><h3><a name=\"pdf-debug.gethook\"><code>debug.gethook ([thread])</code></a></h3>\n\n\n<p>\nReturns the current hook settings of the thread, as three values:\nthe current hook function, the current hook mask,\nand the current hook count\n(as set by the <a href=\"#pdf-debug.sethook\"><code>debug.sethook</code></a> function).\n\n\n\n\n<p>\n<hr><h3><a name=\"pdf-debug.getinfo\"><code>debug.getinfo ([thread,] function [, what])</code></a></h3>\n\n\n<p>\nReturns a table with information about a function.\nYou can give the function directly,\nor you can give a number as the value of <code>function</code>,\nwhich means the function running at level <code>function</code> of the call stack\nof the given thread:\nlevel&nbsp;0 is the current function (<code>getinfo</code> itself);\nlevel&nbsp;1 is the function that called <code>getinfo</code>;\nand so on.\nIf <code>function</code> is a number larger than the number of active functions,\nthen <code>getinfo</code> returns <b>nil</b>.\n\n\n<p>\nThe returned table can contain all the fields returned by <a href=\"#lua_getinfo\"><code>lua_getinfo</code></a>,\nwith the string <code>what</code> describing which fields to fill in.\nThe default for <code>what</code> is to get all information available,\nexcept the table of valid lines.\nIf present,\nthe option '<code>f</code>'\nadds a field named <code>func</code> with the function itself.\nIf present,\nthe option '<code>L</code>'\nadds a field named <code>activelines</code> with the table of\nvalid lines.\n\n\n<p>\nFor instance, the expression <code>debug.getinfo(1,\"n\").name</code> returns\na table with a name for the current function,\nif a reasonable name can be found,\nand the expression <code>debug.getinfo(print)</code>\nreturns a table with all available information\nabout the <a href=\"#pdf-print\"><code>print</code></a> function.\n\n\n\n\n<p>\n<hr><h3><a name=\"pdf-debug.getlocal\"><code>debug.getlocal ([thread,] level, local)</code></a></h3>\n\n\n<p>\nThis function returns the name and the value of the local variable\nwith index <code>local</code> of the function at level <code>level</code> of the stack.\n(The first parameter or local variable has index&nbsp;1, and so on,\nuntil the last active local variable.)\nThe function returns <b>nil</b> if there is no local\nvariable with the given index,\nand raises an error when called with a <code>level</code> out of range.\n(You can call <a href=\"#pdf-debug.getinfo\"><code>debug.getinfo</code></a> to check whether the level is valid.)\n\n\n<p>\nVariable names starting with '<code>(</code>' (open parentheses)\nrepresent internal variables\n(loop control variables, temporaries, and C&nbsp;function locals).\n\n\n\n\n<p>\n<hr><h3><a name=\"pdf-debug.getmetatable\"><code>debug.getmetatable (object)</code></a></h3>\n\n\n<p>\nReturns the metatable of the given <code>object</code>\nor <b>nil</b> if it does not have a metatable.\n\n\n\n\n<p>\n<hr><h3><a name=\"pdf-debug.getregistry\"><code>debug.getregistry ()</code></a></h3>\n\n\n<p>\nReturns the registry table (see <a href=\"#3.5\">&sect;3.5</a>).\n\n\n\n\n<p>\n<hr><h3><a name=\"pdf-debug.getupvalue\"><code>debug.getupvalue (func, up)</code></a></h3>\n\n\n<p>\nThis function returns the name and the value of the upvalue\nwith index <code>up</code> of the function <code>func</code>.\nThe function returns <b>nil</b> if there is no upvalue with the given index.\n\n\n\n\n<p>\n<hr><h3><a name=\"pdf-debug.setfenv\"><code>debug.setfenv (object, table)</code></a></h3>\n\n\n<p>\nSets the environment of the given <code>object</code> to the given <code>table</code>.\nReturns <code>object</code>.\n\n\n\n\n<p>\n<hr><h3><a name=\"pdf-debug.sethook\"><code>debug.sethook ([thread,] hook, mask [, count])</code></a></h3>\n\n\n<p>\nSets the given function as a hook.\nThe string <code>mask</code> and the number <code>count</code> describe\nwhen the hook will be called.\nThe string mask may have the following characters,\nwith the given meaning:\n\n<ul>\n<li><b><code>\"c\"</code>:</b> the hook is called every time Lua calls a function;</li>\n<li><b><code>\"r\"</code>:</b> the hook is called every time Lua returns from a function;</li>\n<li><b><code>\"l\"</code>:</b> the hook is called every time Lua enters a new line of code.</li>\n</ul><p>\nWith a <code>count</code> different from zero,\nthe hook is called after every <code>count</code> instructions.\n\n\n<p>\nWhen called without arguments,\n<a href=\"#pdf-debug.sethook\"><code>debug.sethook</code></a> turns off the hook.\n\n\n<p>\nWhen the hook is called, its first parameter is a string\ndescribing the event that has triggered its call:\n<code>\"call\"</code>, <code>\"return\"</code> (or <code>\"tail return\"</code>,\nwhen simulating a return from a tail call),\n<code>\"line\"</code>, and <code>\"count\"</code>.\nFor line events,\nthe hook also gets the new line number as its second parameter.\nInside a hook,\nyou can call <code>getinfo</code> with level&nbsp;2 to get more information about\nthe running function\n(level&nbsp;0 is the <code>getinfo</code> function,\nand level&nbsp;1 is the hook function),\nunless the event is <code>\"tail return\"</code>.\nIn this case, Lua is only simulating the return,\nand a call to <code>getinfo</code> will return invalid data.\n\n\n\n\n<p>\n<hr><h3><a name=\"pdf-debug.setlocal\"><code>debug.setlocal ([thread,] level, local, value)</code></a></h3>\n\n\n<p>\nThis function assigns the value <code>value</code> to the local variable\nwith index <code>local</code> of the function at level <code>level</code> of the stack.\nThe function returns <b>nil</b> if there is no local\nvariable with the given index,\nand raises an error when called with a <code>level</code> out of range.\n(You can call <code>getinfo</code> to check whether the level is valid.)\nOtherwise, it returns the name of the local variable.\n\n\n\n\n<p>\n<hr><h3><a name=\"pdf-debug.setmetatable\"><code>debug.setmetatable (object, table)</code></a></h3>\n\n\n<p>\nSets the metatable for the given <code>object</code> to the given <code>table</code>\n(which can be <b>nil</b>).\n\n\n\n\n<p>\n<hr><h3><a name=\"pdf-debug.setupvalue\"><code>debug.setupvalue (func, up, value)</code></a></h3>\n\n\n<p>\nThis function assigns the value <code>value</code> to the upvalue\nwith index <code>up</code> of the function <code>func</code>.\nThe function returns <b>nil</b> if there is no upvalue\nwith the given index.\nOtherwise, it returns the name of the upvalue.\n\n\n\n\n<p>\n<hr><h3><a name=\"pdf-debug.traceback\"><code>debug.traceback ([thread,] [message [, level]])</code></a></h3>\n\n\n<p>\nReturns a string with a traceback of the call stack.\nAn optional <code>message</code> string is appended\nat the beginning of the traceback.\nAn optional <code>level</code> number tells at which level\nto start the traceback\n(default is 1, the function calling <code>traceback</code>).\n\n\n\n\n\n\n\n<h1>6 - <a name=\"6\">Lua Stand-alone</a></h1>\n\n<p>\nAlthough Lua has been designed as an extension language,\nto be embedded in a host C&nbsp;program,\nit is also frequently used as a stand-alone language.\nAn interpreter for Lua as a stand-alone language,\ncalled simply <code>lua</code>,\nis provided with the standard distribution.\nThe stand-alone interpreter includes\nall standard libraries, including the debug library.\nIts usage is:\n\n<pre>\n     lua [options] [script [args]]\n</pre><p>\nThe options are:\n\n<ul>\n<li><b><code>-e <em>stat</em></code>:</b> executes string <em>stat</em>;</li>\n<li><b><code>-l <em>mod</em></code>:</b> \"requires\" <em>mod</em>;</li>\n<li><b><code>-i</code>:</b> enters interactive mode after running <em>script</em>;</li>\n<li><b><code>-v</code>:</b> prints version information;</li>\n<li><b><code>--</code>:</b> stops handling options;</li>\n<li><b><code>-</code>:</b> executes <code>stdin</code> as a file and stops handling options.</li>\n</ul><p>\nAfter handling its options, <code>lua</code> runs the given <em>script</em>,\npassing to it the given <em>args</em> as string arguments.\nWhen called without arguments,\n<code>lua</code> behaves as <code>lua -v -i</code>\nwhen the standard input (<code>stdin</code>) is a terminal,\nand as <code>lua -</code> otherwise.\n\n\n<p>\nBefore running any argument,\nthe interpreter checks for an environment variable <a name=\"pdf-LUA_INIT\"><code>LUA_INIT</code></a>.\nIf its format is <code>@<em>filename</em></code>,\nthen <code>lua</code> executes the file.\nOtherwise, <code>lua</code> executes the string itself.\n\n\n<p>\nAll options are handled in order, except <code>-i</code>.\nFor instance, an invocation like\n\n<pre>\n     $ lua -e'a=1' -e 'print(a)' script.lua\n</pre><p>\nwill first set <code>a</code> to 1, then print the value of <code>a</code> (which is '<code>1</code>'),\nand finally run the file <code>script.lua</code> with no arguments.\n(Here <code>$</code> is the shell prompt. Your prompt may be different.)\n\n\n<p>\nBefore starting to run the script,\n<code>lua</code> collects all arguments in the command line\nin a global table called <code>arg</code>.\nThe script name is stored at index 0,\nthe first argument after the script name goes to index 1,\nand so on.\nAny arguments before the script name\n(that is, the interpreter name plus the options)\ngo to negative indices.\nFor instance, in the call\n\n<pre>\n     $ lua -la b.lua t1 t2\n</pre><p>\nthe interpreter first runs the file <code>a.lua</code>,\nthen creates a table\n\n<pre>\n     arg = { [-2] = \"lua\", [-1] = \"-la\",\n             [0] = \"b.lua\",\n             [1] = \"t1\", [2] = \"t2\" }\n</pre><p>\nand finally runs the file <code>b.lua</code>.\nThe script is called with <code>arg[1]</code>, <code>arg[2]</code>, &middot;&middot;&middot;\nas arguments;\nit can also access these arguments with the vararg expression '<code>...</code>'.\n\n\n<p>\nIn interactive mode,\nif you write an incomplete statement,\nthe interpreter waits for its completion\nby issuing a different prompt.\n\n\n<p>\nIf the global variable <a name=\"pdf-_PROMPT\"><code>_PROMPT</code></a> contains a string,\nthen its value is used as the prompt.\nSimilarly, if the global variable <a name=\"pdf-_PROMPT2\"><code>_PROMPT2</code></a> contains a string,\nits value is used as the secondary prompt\n(issued during incomplete statements).\nTherefore, both prompts can be changed directly on the command line\nor in any Lua programs by assigning to <code>_PROMPT</code>.\nSee the next example:\n\n<pre>\n     $ lua -e\"_PROMPT='myprompt&gt; '\" -i\n</pre><p>\n(The outer pair of quotes is for the shell,\nthe inner pair is for Lua.)\nNote the use of <code>-i</code> to enter interactive mode;\notherwise,\nthe program would just end silently\nright after the assignment to <code>_PROMPT</code>.\n\n\n<p>\nTo allow the use of Lua as a\nscript interpreter in Unix systems,\nthe stand-alone interpreter skips\nthe first line of a chunk if it starts with <code>#</code>.\nTherefore, Lua scripts can be made into executable programs\nby using <code>chmod +x</code> and the&nbsp;<code>#!</code> form,\nas in\n\n<pre>\n     #!/usr/local/bin/lua\n</pre><p>\n(Of course,\nthe location of the Lua interpreter may be different in your machine.\nIf <code>lua</code> is in your <code>PATH</code>,\nthen \n\n<pre>\n     #!/usr/bin/env lua\n</pre><p>\nis a more portable solution.) \n\n\n\n<h1>7 - <a name=\"7\">Incompatibilities with the Previous Version</a></h1>\n\n<p>\nHere we list the incompatibilities that you may find when moving a program\nfrom Lua&nbsp;5.0 to Lua&nbsp;5.1.\nYou can avoid most of the incompatibilities compiling Lua with\nappropriate options (see file <code>luaconf.h</code>).\nHowever,\nall these compatibility options will be removed in the next version of Lua.\n\n\n\n<h2>7.1 - <a name=\"7.1\">Changes in the Language</a></h2>\n<ul>\n\n<li>\nThe vararg system changed from the pseudo-argument <code>arg</code> with a\ntable with the extra arguments to the vararg expression.\n(See compile-time option <code>LUA_COMPAT_VARARG</code> in <code>luaconf.h</code>.)\n</li>\n\n<li>\nThere was a subtle change in the scope of the implicit\nvariables of the <b>for</b> statement and for the <b>repeat</b> statement.\n</li>\n\n<li>\nThe long string/long comment syntax (<code>[[<em>string</em>]]</code>)\ndoes not allow nesting.\nYou can use the new syntax (<code>[=[<em>string</em>]=]</code>) in these cases.\n(See compile-time option <code>LUA_COMPAT_LSTR</code> in <code>luaconf.h</code>.)\n</li>\n\n</ul>\n\n\n\n\n<h2>7.2 - <a name=\"7.2\">Changes in the Libraries</a></h2>\n<ul>\n\n<li>\nFunction <code>string.gfind</code> was renamed <a href=\"#pdf-string.gmatch\"><code>string.gmatch</code></a>.\n(See compile-time option <code>LUA_COMPAT_GFIND</code> in <code>luaconf.h</code>.)\n</li>\n\n<li>\nWhen <a href=\"#pdf-string.gsub\"><code>string.gsub</code></a> is called with a function as its\nthird argument,\nwhenever this function returns <b>nil</b> or <b>false</b> the\nreplacement string is the whole match,\ninstead of the empty string.\n</li>\n\n<li>\nFunction <code>table.setn</code> was deprecated.\nFunction <code>table.getn</code> corresponds\nto the new length operator (<code>#</code>);\nuse the operator instead of the function.\n(See compile-time option <code>LUA_COMPAT_GETN</code> in <code>luaconf.h</code>.)\n</li>\n\n<li>\nFunction <code>loadlib</code> was renamed <a href=\"#pdf-package.loadlib\"><code>package.loadlib</code></a>.\n(See compile-time option <code>LUA_COMPAT_LOADLIB</code> in <code>luaconf.h</code>.)\n</li>\n\n<li>\nFunction <code>math.mod</code> was renamed <a href=\"#pdf-math.fmod\"><code>math.fmod</code></a>.\n(See compile-time option <code>LUA_COMPAT_MOD</code> in <code>luaconf.h</code>.)\n</li>\n\n<li>\nFunctions <code>table.foreach</code> and <code>table.foreachi</code> are deprecated.\nYou can use a for loop with <code>pairs</code> or <code>ipairs</code> instead.\n</li>\n\n<li>\nThere were substantial changes in function <a href=\"#pdf-require\"><code>require</code></a> due to\nthe new module system.\nHowever, the new behavior is mostly compatible with the old,\nbut <code>require</code> gets the path from <a href=\"#pdf-package.path\"><code>package.path</code></a> instead\nof from <code>LUA_PATH</code>.\n</li>\n\n<li>\nFunction <a href=\"#pdf-collectgarbage\"><code>collectgarbage</code></a> has different arguments.\nFunction <code>gcinfo</code> is deprecated;\nuse <code>collectgarbage(\"count\")</code> instead.\n</li>\n\n</ul>\n\n\n\n\n<h2>7.3 - <a name=\"7.3\">Changes in the API</a></h2>\n<ul>\n\n<li>\nThe <code>luaopen_*</code> functions (to open libraries)\ncannot be called directly,\nlike a regular C function.\nThey must be called through Lua,\nlike a Lua function.\n</li>\n\n<li>\nFunction <code>lua_open</code> was replaced by <a href=\"#lua_newstate\"><code>lua_newstate</code></a> to\nallow the user to set a memory-allocation function.\nYou can use <a href=\"#luaL_newstate\"><code>luaL_newstate</code></a> from the standard library to\ncreate a state with a standard allocation function\n(based on <code>realloc</code>).\n</li>\n\n<li>\nFunctions <code>luaL_getn</code> and <code>luaL_setn</code>\n(from the auxiliary library) are deprecated.\nUse <a href=\"#lua_objlen\"><code>lua_objlen</code></a> instead of <code>luaL_getn</code>\nand nothing instead of <code>luaL_setn</code>.\n</li>\n\n<li>\nFunction <code>luaL_openlib</code> was replaced by <a href=\"#luaL_register\"><code>luaL_register</code></a>.\n</li>\n\n<li>\nFunction <code>luaL_checkudata</code> now throws an error when the given value\nis not a userdata of the expected type.\n(In Lua&nbsp;5.0 it returned <code>NULL</code>.)\n</li>\n\n</ul>\n\n\n\n\n<h1>8 - <a name=\"8\">The Complete Syntax of Lua</a></h1>\n\n<p>\nHere is the complete syntax of Lua in extended BNF.\n(It does not describe operator precedences.)\n\n\n\n\n<pre>\n\n\tchunk ::= {stat [`<b>;</b>&acute;]} [laststat [`<b>;</b>&acute;]]\n\n\tblock ::= chunk\n\n\tstat ::=  varlist `<b>=</b>&acute; explist | \n\t\t functioncall | \n\t\t <b>do</b> block <b>end</b> | \n\t\t <b>while</b> exp <b>do</b> block <b>end</b> | \n\t\t <b>repeat</b> block <b>until</b> exp | \n\t\t <b>if</b> exp <b>then</b> block {<b>elseif</b> exp <b>then</b> block} [<b>else</b> block] <b>end</b> | \n\t\t <b>for</b> Name `<b>=</b>&acute; exp `<b>,</b>&acute; exp [`<b>,</b>&acute; exp] <b>do</b> block <b>end</b> | \n\t\t <b>for</b> namelist <b>in</b> explist <b>do</b> block <b>end</b> | \n\t\t <b>function</b> funcname funcbody | \n\t\t <b>local</b> <b>function</b> Name funcbody | \n\t\t <b>local</b> namelist [`<b>=</b>&acute; explist] \n\n\tlaststat ::= <b>return</b> [explist] | <b>break</b>\n\n\tfuncname ::= Name {`<b>.</b>&acute; Name} [`<b>:</b>&acute; Name]\n\n\tvarlist ::= var {`<b>,</b>&acute; var}\n\n\tvar ::=  Name | prefixexp `<b>[</b>&acute; exp `<b>]</b>&acute; | prefixexp `<b>.</b>&acute; Name \n\n\tnamelist ::= Name {`<b>,</b>&acute; Name}\n\n\texplist ::= {exp `<b>,</b>&acute;} exp\n\n\texp ::=  <b>nil</b> | <b>false</b> | <b>true</b> | Number | String | `<b>...</b>&acute; | function | \n\t\t prefixexp | tableconstructor | exp binop exp | unop exp \n\n\tprefixexp ::= var | functioncall | `<b>(</b>&acute; exp `<b>)</b>&acute;\n\n\tfunctioncall ::=  prefixexp args | prefixexp `<b>:</b>&acute; Name args \n\n\targs ::=  `<b>(</b>&acute; [explist] `<b>)</b>&acute; | tableconstructor | String \n\n\tfunction ::= <b>function</b> funcbody\n\n\tfuncbody ::= `<b>(</b>&acute; [parlist] `<b>)</b>&acute; block <b>end</b>\n\n\tparlist ::= namelist [`<b>,</b>&acute; `<b>...</b>&acute;] | `<b>...</b>&acute;\n\n\ttableconstructor ::= `<b>{</b>&acute; [fieldlist] `<b>}</b>&acute;\n\n\tfieldlist ::= field {fieldsep field} [fieldsep]\n\n\tfield ::= `<b>[</b>&acute; exp `<b>]</b>&acute; `<b>=</b>&acute; exp | Name `<b>=</b>&acute; exp | exp\n\n\tfieldsep ::= `<b>,</b>&acute; | `<b>;</b>&acute;\n\n\tbinop ::= `<b>+</b>&acute; | `<b>-</b>&acute; | `<b>*</b>&acute; | `<b>/</b>&acute; | `<b>^</b>&acute; | `<b>%</b>&acute; | `<b>..</b>&acute; | \n\t\t `<b>&lt;</b>&acute; | `<b>&lt;=</b>&acute; | `<b>&gt;</b>&acute; | `<b>&gt;=</b>&acute; | `<b>==</b>&acute; | `<b>~=</b>&acute; | \n\t\t <b>and</b> | <b>or</b>\n\n\tunop ::= `<b>-</b>&acute; | <b>not</b> | `<b>#</b>&acute;\n\n</pre>\n\n<p>\n\n\n\n\n\n\n\n<HR>\n<SMALL CLASS=\"footer\">\nLast update:\nMon Feb 13 18:54:19 BRST 2012\n</SMALL>\n<!--\nLast change: revised for Lua 5.1.5\n-->\n\n</body></html>\n\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/deps/lua/doc/readme.html",
    "content": "<HTML>\n<HEAD>\n<TITLE>Lua documentation</TITLE>\n<LINK REL=\"stylesheet\" TYPE=\"text/css\" HREF=\"lua.css\">\n</HEAD>\n\n<BODY>\n\n<HR>\n<H1>\n<A HREF=\"http://www.lua.org/\"><IMG SRC=\"logo.gif\" ALT=\"Lua\" BORDER=0></A>\nDocumentation\n</H1>\n\nThis is the documentation included in the source distribution of Lua 5.1.5.\n\n<UL>\n<LI><A HREF=\"contents.html\">Reference manual</A>\n<LI><A HREF=\"lua.html\">lua man page</A>\n<LI><A HREF=\"luac.html\">luac man page</A>\n<LI><A HREF=\"../README\">lua/README</A>\n<LI><A HREF=\"../etc/README\">lua/etc/README</A>\n<LI><A HREF=\"../test/README\">lua/test/README</A>\n</UL>\n\nLua's\n<A HREF=\"http://www.lua.org/\">official web site</A>\ncontains updated documentation,\nespecially the\n<A HREF=\"http://www.lua.org/manual/5.1/\">reference manual</A>.\n<P>\n\n<HR>\n<SMALL>\nLast update:\nFri Feb  3 09:44:42 BRST 2012\n</SMALL>\n\n</BODY>\n</HTML>\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/deps/lua/etc/Makefile",
    "content": "# makefile for Lua etc\n\nTOP= ..\nLIB= $(TOP)/src\nINC= $(TOP)/src\nBIN= $(TOP)/src\nSRC= $(TOP)/src\nTST= $(TOP)/test\n\nCC= gcc\nCFLAGS= -O2 -Wall -I$(INC) $(MYCFLAGS)\nMYCFLAGS= \nMYLDFLAGS= -Wl,-E\nMYLIBS= -lm\n#MYLIBS= -lm -Wl,-E -ldl -lreadline -lhistory -lncurses\nRM= rm -f\n\ndefault:\n\t@echo 'Please choose a target: min noparser one strict clean'\n\nmin:\tmin.c\n\t$(CC) $(CFLAGS) $@.c -L$(LIB) -llua $(MYLIBS)\n\techo 'print\"Hello there!\"' | ./a.out\n\nnoparser: noparser.o\n\t$(CC) noparser.o $(SRC)/lua.o -L$(LIB) -llua $(MYLIBS)\n\t$(BIN)/luac $(TST)/hello.lua\n\t-./a.out luac.out\n\t-./a.out -e'a=1'\n\none:\n\t$(CC) $(CFLAGS) all.c $(MYLIBS)\n\t./a.out $(TST)/hello.lua\n\nstrict:\n\t-$(BIN)/lua -e 'print(a);b=2'\n\t-$(BIN)/lua -lstrict -e 'print(a)'\n\t-$(BIN)/lua -e 'function f() b=2 end f()'\n\t-$(BIN)/lua -lstrict -e 'function f() b=2 end f()'\n\nclean:\n\t$(RM) a.out core core.* *.o luac.out\n\n.PHONY:\tdefault min noparser one strict clean\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/deps/lua/etc/README",
    "content": "This directory contains some useful files and code.\nUnlike the code in ../src, everything here is in the public domain.\n\nIf any of the makes fail, you're probably not using the same libraries\nused to build Lua. Set MYLIBS in Makefile accordingly.\n\nall.c\n\tFull Lua interpreter in a single file.\n\tDo \"make one\" for a demo.\n\nlua.hpp\n\tLua header files for C++ using 'extern \"C\"'.\n\nlua.ico\n\tA Lua icon for Windows (and web sites: save as favicon.ico).\n\tDrawn by hand by Markus Gritsch <gritsch@iue.tuwien.ac.at>.\n\nlua.pc\n\tpkg-config data for Lua\n\nluavs.bat\n\tScript to build Lua under \"Visual Studio .NET Command Prompt\".\n\tRun it from the toplevel as etc\\luavs.bat.\n\nmin.c\n\tA minimal Lua interpreter.\n\tGood for learning and for starting your own.\n\tDo \"make min\" for a demo.\n\nnoparser.c\n\tLinking with noparser.o avoids loading the parsing modules in lualib.a.\n\tDo \"make noparser\" for a demo.\n\nstrict.lua\n\tTraps uses of undeclared global variables.\n\tDo \"make strict\" for a demo.\n\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/deps/lua/etc/all.c",
    "content": "/*\n* all.c -- Lua core, libraries and interpreter in a single file\n*/\n\n#define luaall_c\n\n#include \"lapi.c\"\n#include \"lcode.c\"\n#include \"ldebug.c\"\n#include \"ldo.c\"\n#include \"ldump.c\"\n#include \"lfunc.c\"\n#include \"lgc.c\"\n#include \"llex.c\"\n#include \"lmem.c\"\n#include \"lobject.c\"\n#include \"lopcodes.c\"\n#include \"lparser.c\"\n#include \"lstate.c\"\n#include \"lstring.c\"\n#include \"ltable.c\"\n#include \"ltm.c\"\n#include \"lundump.c\"\n#include \"lvm.c\"\n#include \"lzio.c\"\n\n#include \"lauxlib.c\"\n#include \"lbaselib.c\"\n#include \"ldblib.c\"\n#include \"liolib.c\"\n#include \"linit.c\"\n#include \"lmathlib.c\"\n#include \"loadlib.c\"\n#include \"loslib.c\"\n#include \"lstrlib.c\"\n#include \"ltablib.c\"\n\n#include \"lua.c\"\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/deps/lua/etc/lua.hpp",
    "content": "// lua.hpp\n// Lua header files for C++\n// <<extern \"C\">> not supplied automatically because Lua also compiles as C++\n\nextern \"C\" {\n#include \"lua.h\"\n#include \"lualib.h\"\n#include \"lauxlib.h\"\n}\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/deps/lua/etc/lua.pc",
    "content": "# lua.pc -- pkg-config data for Lua\n\n# vars from install Makefile\n\n# grep '^V=' ../Makefile\nV= 5.1\n# grep '^R=' ../Makefile\nR= 5.1.5\n\n# grep '^INSTALL_.*=' ../Makefile | sed 's/INSTALL_TOP/prefix/'\nprefix= /usr/local\nINSTALL_BIN= ${prefix}/bin\nINSTALL_INC= ${prefix}/include\nINSTALL_LIB= ${prefix}/lib\nINSTALL_MAN= ${prefix}/man/man1\nINSTALL_LMOD= ${prefix}/share/lua/${V}\nINSTALL_CMOD= ${prefix}/lib/lua/${V}\n\n# canonical vars\nexec_prefix=${prefix}\nlibdir=${exec_prefix}/lib\nincludedir=${prefix}/include\n\nName: Lua\nDescription: An Extensible Extension Language\nVersion: ${R}\nRequires: \nLibs: -L${libdir} -llua -lm\nCflags: -I${includedir}\n\n# (end of lua.pc)\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/deps/lua/etc/luavs.bat",
    "content": "@rem Script to build Lua under \"Visual Studio .NET Command Prompt\".\r\n@rem Do not run from this directory; run it from the toplevel: etc\\luavs.bat .\r\n@rem It creates lua51.dll, lua51.lib, lua.exe, and luac.exe in src.\r\n@rem (contributed by David Manura and Mike Pall)\r\n\r\n@setlocal\r\n@set MYCOMPILE=cl /nologo /MD /O2 /W3 /c /D_CRT_SECURE_NO_DEPRECATE\r\n@set MYLINK=link /nologo\r\n@set MYMT=mt /nologo\r\n\r\ncd src\r\n%MYCOMPILE% /DLUA_BUILD_AS_DLL l*.c\r\ndel lua.obj luac.obj\r\n%MYLINK% /DLL /out:lua51.dll l*.obj\r\nif exist lua51.dll.manifest^\r\n  %MYMT% -manifest lua51.dll.manifest -outputresource:lua51.dll;2\r\n%MYCOMPILE% /DLUA_BUILD_AS_DLL lua.c\r\n%MYLINK% /out:lua.exe lua.obj lua51.lib\r\nif exist lua.exe.manifest^\r\n  %MYMT% -manifest lua.exe.manifest -outputresource:lua.exe\r\n%MYCOMPILE% l*.c print.c\r\ndel lua.obj linit.obj lbaselib.obj ldblib.obj liolib.obj lmathlib.obj^\r\n    loslib.obj ltablib.obj lstrlib.obj loadlib.obj\r\n%MYLINK% /out:luac.exe *.obj\r\nif exist luac.exe.manifest^\r\n  %MYMT% -manifest luac.exe.manifest -outputresource:luac.exe\r\ndel *.obj *.manifest\r\ncd ..\r\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/deps/lua/etc/min.c",
    "content": "/*\n* min.c -- a minimal Lua interpreter\n* loads stdin only with minimal error handling.\n* no interaction, and no standard library, only a \"print\" function.\n*/\n\n#include <stdio.h>\n\n#include \"lua.h\"\n#include \"lauxlib.h\"\n\nstatic int print(lua_State *L)\n{\n int n=lua_gettop(L);\n int i;\n for (i=1; i<=n; i++)\n {\n  if (i>1) printf(\"\\t\");\n  if (lua_isstring(L,i))\n   printf(\"%s\",lua_tostring(L,i));\n  else if (lua_isnil(L,i))\n   printf(\"%s\",\"nil\");\n  else if (lua_isboolean(L,i))\n   printf(\"%s\",lua_toboolean(L,i) ? \"true\" : \"false\");\n  else\n   printf(\"%s:%p\",luaL_typename(L,i),lua_topointer(L,i));\n }\n printf(\"\\n\");\n return 0;\n}\n\nint main(void)\n{\n lua_State *L=lua_open();\n lua_register(L,\"print\",print);\n if (luaL_dofile(L,NULL)!=0) fprintf(stderr,\"%s\\n\",lua_tostring(L,-1));\n lua_close(L);\n return 0;\n}\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/deps/lua/etc/noparser.c",
    "content": "/*\n* The code below can be used to make a Lua core that does not contain the\n* parsing modules (lcode, llex, lparser), which represent 35% of the total core.\n* You'll only be able to load binary files and strings, precompiled with luac.\n* (Of course, you'll have to build luac with the original parsing modules!)\n*\n* To use this module, simply compile it (\"make noparser\" does that) and list\n* its object file before the Lua libraries. The linker should then not load\n* the parsing modules. To try it, do \"make luab\".\n*\n* If you also want to avoid the dump module (ldump.o), define NODUMP.\n* #define NODUMP\n*/\n\n#define LUA_CORE\n\n#include \"llex.h\"\n#include \"lparser.h\"\n#include \"lzio.h\"\n\nLUAI_FUNC void luaX_init (lua_State *L) {\n  UNUSED(L);\n}\n\nLUAI_FUNC Proto *luaY_parser (lua_State *L, ZIO *z, Mbuffer *buff, const char *name) {\n  UNUSED(z);\n  UNUSED(buff);\n  UNUSED(name);\n  lua_pushliteral(L,\"parser not loaded\");\n  lua_error(L);\n  return NULL;\n}\n\n#ifdef NODUMP\n#include \"lundump.h\"\n\nLUAI_FUNC int luaU_dump (lua_State* L, const Proto* f, lua_Writer w, void* data, int strip) {\n  UNUSED(f);\n  UNUSED(w);\n  UNUSED(data);\n  UNUSED(strip);\n#if 1\n  UNUSED(L);\n  return 0;\n#else\n  lua_pushliteral(L,\"dumper not loaded\");\n  lua_error(L);\n#endif\n}\n#endif\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/deps/lua/etc/strict.lua",
    "content": "--\n-- strict.lua\n-- checks uses of undeclared global variables\n-- All global variables must be 'declared' through a regular assignment\n-- (even assigning nil will do) in a main chunk before being used\n-- anywhere or assigned to inside a function.\n--\n\nlocal getinfo, error, rawset, rawget = debug.getinfo, error, rawset, rawget\n\nlocal mt = getmetatable(_G)\nif mt == nil then\n  mt = {}\n  setmetatable(_G, mt)\nend\n\nmt.__declared = {}\n\nlocal function what ()\n  local d = getinfo(3, \"S\")\n  return d and d.what or \"C\"\nend\n\nmt.__newindex = function (t, n, v)\n  if not mt.__declared[n] then\n    local w = what()\n    if w ~= \"main\" and w ~= \"C\" then\n      error(\"assign to undeclared variable '\"..n..\"'\", 2)\n    end\n    mt.__declared[n] = true\n  end\n  rawset(t, n, v)\nend\n  \nmt.__index = function (t, n)\n  if not mt.__declared[n] and what() ~= \"C\" then\n    error(\"variable '\"..n..\"' is not declared\", 2)\n  end\n  return rawget(t, n)\nend\n\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/deps/lua/src/Makefile",
    "content": "# makefile for building Lua\n# see ../INSTALL for installation instructions\n# see ../Makefile and luaconf.h for further customization\n\n# == CHANGE THE SETTINGS BELOW TO SUIT YOUR ENVIRONMENT =======================\n\n# Your platform. See PLATS for possible values.\nPLAT= none\n\nCC?= gcc\nCFLAGS= -O2 -Wall $(MYCFLAGS)\nAR= ar rcu\nRANLIB= ranlib\nRM= rm -f\nLIBS= -lm $(MYLIBS)\n\nMYCFLAGS=\nMYLDFLAGS=\nMYLIBS=\n\n# == END OF USER SETTINGS. NO NEED TO CHANGE ANYTHING BELOW THIS LINE =========\n\nPLATS= aix ansi bsd freebsd generic linux macosx mingw posix solaris\n\nLUA_A=\tliblua.a\nCORE_O=\tlapi.o lcode.o ldebug.o ldo.o ldump.o lfunc.o lgc.o llex.o lmem.o \\\n\tlobject.o lopcodes.o lparser.o lstate.o lstring.o ltable.o ltm.o  \\\n\tlundump.o lvm.o lzio.o strbuf.o fpconv.o\nLIB_O=\tlauxlib.o lbaselib.o ldblib.o liolib.o lmathlib.o loslib.o ltablib.o \\\n\tlstrlib.o loadlib.o linit.o lua_cjson.o lua_struct.o lua_cmsgpack.o \\\n\tlua_bit.o\n\nLUA_T=\tlua\nLUA_O=\tlua.o\n\nLUAC_T=\tluac\nLUAC_O=\tluac.o print.o\n\nALL_O= $(CORE_O) $(LIB_O) $(LUA_O) $(LUAC_O)\nALL_T= $(LUA_A) $(LUA_T) $(LUAC_T)\nALL_A= $(LUA_A)\n\ndefault: $(PLAT)\n\nall:\t$(ALL_T)\n\no:\t$(ALL_O)\n\na:\t$(ALL_A)\n\n$(LUA_A): $(CORE_O) $(LIB_O)\n\t$(AR) $@ $(CORE_O) $(LIB_O)\t# DLL needs all object files\n\t$(RANLIB) $@\n\n$(LUA_T): $(LUA_O) $(LUA_A)\n\t$(CC) -o $@ $(MYLDFLAGS) $(LUA_O) $(LUA_A) $(LIBS)\n\n$(LUAC_T): $(LUAC_O) $(LUA_A)\n\t$(CC) -o $@ $(MYLDFLAGS) $(LUAC_O) $(LUA_A) $(LIBS)\n\nclean:\n\t$(RM) $(ALL_T) $(ALL_O)\n\ndepend:\n\t@$(CC) $(CFLAGS) -MM l*.c print.c\n\necho:\n\t@echo \"PLAT = $(PLAT)\"\n\t@echo \"CC = $(CC)\"\n\t@echo \"CFLAGS = $(CFLAGS)\"\n\t@echo \"AR = $(AR)\"\n\t@echo \"RANLIB = $(RANLIB)\"\n\t@echo \"RM = $(RM)\"\n\t@echo \"MYCFLAGS = $(MYCFLAGS)\"\n\t@echo \"MYLDFLAGS = $(MYLDFLAGS)\"\n\t@echo \"MYLIBS = $(MYLIBS)\"\n\n# convenience targets for popular platforms\n\nnone:\n\t@echo \"Please choose a platform:\"\n\t@echo \"   $(PLATS)\"\n\naix:\n\t$(MAKE) all CC=\"xlc\" CFLAGS=\"-O2 -DLUA_USE_POSIX -DLUA_USE_DLOPEN\" MYLIBS=\"-ldl\" MYLDFLAGS=\"-brtl -bexpall\"\n\nansi:\n\t$(MAKE) all MYCFLAGS=-DLUA_ANSI\n\nbsd:\n\t$(MAKE) all MYCFLAGS=\"-DLUA_USE_POSIX -DLUA_USE_DLOPEN\" MYLIBS=\"-Wl,-E\"\n\nfreebsd:\n\t$(MAKE) all MYCFLAGS=\"-DLUA_USE_LINUX\" MYLIBS=\"-Wl,-E -lreadline\"\n\ngeneric:\n\t$(MAKE) all MYCFLAGS=\n\nlinux:\n\t$(MAKE) all MYCFLAGS=-DLUA_USE_LINUX MYLIBS=\"-Wl,-E -ldl -lreadline -lhistory -lncurses\"\n\nmacosx:\n\t$(MAKE) all MYCFLAGS=-DLUA_USE_LINUX MYLIBS=\"-lreadline\"\n# use this on Mac OS X 10.3-\n#\t$(MAKE) all MYCFLAGS=-DLUA_USE_MACOSX\n\nmingw:\n\t$(MAKE) \"LUA_A=lua51.dll\" \"LUA_T=lua.exe\" \\\n\t\"AR=$(CC) -shared -o\" \"RANLIB=strip --strip-unneeded\" \\\n\t\"MYCFLAGS=-DLUA_BUILD_AS_DLL\" \"MYLIBS=\" \"MYLDFLAGS=-s\" lua.exe\n\t$(MAKE) \"LUAC_T=luac.exe\" luac.exe\n\nposix:\n\t$(MAKE) all MYCFLAGS=-DLUA_USE_POSIX\n\nsolaris:\n\t$(MAKE) all MYCFLAGS=\"-DLUA_USE_POSIX -DLUA_USE_DLOPEN\" MYLIBS=\"-ldl\"\n\n# list targets that do not create files (but not all makes understand .PHONY)\n.PHONY: all $(PLATS) default o a clean depend echo none\n\n# DO NOT DELETE\n\nlapi.o: lapi.c lua.h luaconf.h lapi.h lobject.h llimits.h ldebug.h \\\n  lstate.h ltm.h lzio.h lmem.h ldo.h lfunc.h lgc.h lstring.h ltable.h \\\n  lundump.h lvm.h\nlauxlib.o: lauxlib.c lua.h luaconf.h lauxlib.h\nlbaselib.o: lbaselib.c lua.h luaconf.h lauxlib.h lualib.h\nlcode.o: lcode.c lua.h luaconf.h lcode.h llex.h lobject.h llimits.h \\\n  lzio.h lmem.h lopcodes.h lparser.h ldebug.h lstate.h ltm.h ldo.h lgc.h \\\n  ltable.h\nldblib.o: ldblib.c lua.h luaconf.h lauxlib.h lualib.h\nldebug.o: ldebug.c lua.h luaconf.h lapi.h lobject.h llimits.h lcode.h \\\n  llex.h lzio.h lmem.h lopcodes.h lparser.h ldebug.h lstate.h ltm.h ldo.h \\\n  lfunc.h lstring.h lgc.h ltable.h lvm.h\nldo.o: ldo.c lua.h luaconf.h ldebug.h lstate.h lobject.h llimits.h ltm.h \\\n  lzio.h lmem.h ldo.h lfunc.h lgc.h lopcodes.h lparser.h lstring.h \\\n  ltable.h lundump.h lvm.h\nldump.o: ldump.c lua.h luaconf.h lobject.h llimits.h lstate.h ltm.h \\\n  lzio.h lmem.h lundump.h\nlfunc.o: lfunc.c lua.h luaconf.h lfunc.h lobject.h llimits.h lgc.h lmem.h \\\n  lstate.h ltm.h lzio.h\nlgc.o: lgc.c lua.h luaconf.h ldebug.h lstate.h lobject.h llimits.h ltm.h \\\n  lzio.h lmem.h ldo.h lfunc.h lgc.h lstring.h ltable.h\nlinit.o: linit.c lua.h luaconf.h lualib.h lauxlib.h\nliolib.o: liolib.c lua.h luaconf.h lauxlib.h lualib.h\nllex.o: llex.c lua.h luaconf.h ldo.h lobject.h llimits.h lstate.h ltm.h \\\n  lzio.h lmem.h llex.h lparser.h lstring.h lgc.h ltable.h\nlmathlib.o: lmathlib.c lua.h luaconf.h lauxlib.h lualib.h\nlmem.o: lmem.c lua.h luaconf.h ldebug.h lstate.h lobject.h llimits.h \\\n  ltm.h lzio.h lmem.h ldo.h\nloadlib.o: loadlib.c lua.h luaconf.h lauxlib.h lualib.h\nlobject.o: lobject.c lua.h luaconf.h ldo.h lobject.h llimits.h lstate.h \\\n  ltm.h lzio.h lmem.h lstring.h lgc.h lvm.h\nlopcodes.o: lopcodes.c lopcodes.h llimits.h lua.h luaconf.h\nloslib.o: loslib.c lua.h luaconf.h lauxlib.h lualib.h\nlparser.o: lparser.c lua.h luaconf.h lcode.h llex.h lobject.h llimits.h \\\n  lzio.h lmem.h lopcodes.h lparser.h ldebug.h lstate.h ltm.h ldo.h \\\n  lfunc.h lstring.h lgc.h ltable.h\nlstate.o: lstate.c lua.h luaconf.h ldebug.h lstate.h lobject.h llimits.h \\\n  ltm.h lzio.h lmem.h ldo.h lfunc.h lgc.h llex.h lstring.h ltable.h\nlstring.o: lstring.c lua.h luaconf.h lmem.h llimits.h lobject.h lstate.h \\\n  ltm.h lzio.h lstring.h lgc.h\nlstrlib.o: lstrlib.c lua.h luaconf.h lauxlib.h lualib.h\nltable.o: ltable.c lua.h luaconf.h ldebug.h lstate.h lobject.h llimits.h \\\n  ltm.h lzio.h lmem.h ldo.h lgc.h ltable.h\nltablib.o: ltablib.c lua.h luaconf.h lauxlib.h lualib.h\nltm.o: ltm.c lua.h luaconf.h lobject.h llimits.h lstate.h ltm.h lzio.h \\\n  lmem.h lstring.h lgc.h ltable.h\nlua.o: lua.c lua.h luaconf.h lauxlib.h lualib.h\nluac.o: luac.c lua.h luaconf.h lauxlib.h ldo.h lobject.h llimits.h \\\n  lstate.h ltm.h lzio.h lmem.h lfunc.h lopcodes.h lstring.h lgc.h \\\n  lundump.h\nlundump.o: lundump.c lua.h luaconf.h ldebug.h lstate.h lobject.h \\\n  llimits.h ltm.h lzio.h lmem.h ldo.h lfunc.h lstring.h lgc.h lundump.h\nlvm.o: lvm.c lua.h luaconf.h ldebug.h lstate.h lobject.h llimits.h ltm.h \\\n  lzio.h lmem.h ldo.h lfunc.h lgc.h lopcodes.h lstring.h ltable.h lvm.h\nlzio.o: lzio.c lua.h luaconf.h llimits.h lmem.h lstate.h lobject.h ltm.h \\\n  lzio.h\nprint.o: print.c ldebug.h lstate.h lua.h luaconf.h lobject.h llimits.h \\\n  ltm.h lzio.h lmem.h lopcodes.h lundump.h\n\n# (end of Makefile)\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/deps/lua/src/fpconv.c",
    "content": "/* fpconv - Floating point conversion routines\n *\n * Copyright (c) 2011-2012  Mark Pulford <mark@kyne.com.au>\n *\n * Permission is hereby granted, free of charge, to any person obtaining\n * a copy of this software and associated documentation files (the\n * \"Software\"), to deal in the Software without restriction, including\n * without limitation the rights to use, copy, modify, merge, publish,\n * distribute, sublicense, and/or sell copies of the Software, and to\n * permit persons to whom the Software is furnished to do so, subject to\n * the following conditions:\n *\n * The above copyright notice and this permission notice shall be\n * included in all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND,\n * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\n * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.\n * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY\n * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,\n * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE\n * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n */\n\n/* JSON uses a '.' decimal separator. strtod() / sprintf() under C libraries\n * with locale support will break when the decimal separator is a comma.\n *\n * fpconv_* will around these issues with a translation buffer if required.\n */\n\n#include <stdio.h>\n#include <stdlib.h>\n#include <assert.h>\n#include <string.h>\n\n#include \"fpconv.h\"\n\n/* Lua CJSON assumes the locale is the same for all threads within a\n * process and doesn't change after initialisation.\n *\n * This avoids the need for per thread storage or expensive checks\n * for call. */\nstatic char locale_decimal_point = '.';\n\n/* In theory multibyte decimal_points are possible, but\n * Lua CJSON only supports UTF-8 and known locales only have\n * single byte decimal points ([.,]).\n *\n * localconv() may not be thread safe (=>crash), and nl_langinfo() is\n * not supported on some platforms. Use sprintf() instead - if the\n * locale does change, at least Lua CJSON won't crash. */\nstatic void fpconv_update_locale()\n{\n    char buf[8];\n\n    snprintf(buf, sizeof(buf), \"%g\", 0.5);\n\n    /* Failing this test might imply the platform has a buggy dtoa\n     * implementation or wide characters */\n    if (buf[0] != '0' || buf[2] != '5' || buf[3] != 0) {\n        fprintf(stderr, \"Error: wide characters found or printf() bug.\");\n        abort();\n    }\n\n    locale_decimal_point = buf[1];\n}\n\n/* Check for a valid number character: [-+0-9a-yA-Y.]\n * Eg: -0.6e+5, infinity, 0xF0.F0pF0\n *\n * Used to find the probable end of a number. It doesn't matter if\n * invalid characters are counted - strtod() will find the valid\n * number if it exists.  The risk is that slightly more memory might\n * be allocated before a parse error occurs. */\nstatic inline int valid_number_character(char ch)\n{\n    char lower_ch;\n\n    if ('0' <= ch && ch <= '9')\n        return 1;\n    if (ch == '-' || ch == '+' || ch == '.')\n        return 1;\n\n    /* Hex digits, exponent (e), base (p), \"infinity\",.. */\n    lower_ch = ch | 0x20;\n    if ('a' <= lower_ch && lower_ch <= 'y')\n        return 1;\n\n    return 0;\n}\n\n/* Calculate the size of the buffer required for a strtod locale\n * conversion. */\nstatic int strtod_buffer_size(const char *s)\n{\n    const char *p = s;\n\n    while (valid_number_character(*p))\n        p++;\n\n    return p - s;\n}\n\n/* Similar to strtod(), but must be passed the current locale's decimal point\n * character. Guaranteed to be called at the start of any valid number in a string */\ndouble fpconv_strtod(const char *nptr, char **endptr)\n{\n    char localbuf[FPCONV_G_FMT_BUFSIZE];\n    char *buf, *endbuf, *dp;\n    int buflen;\n    double value;\n\n    /* System strtod() is fine when decimal point is '.' */\n    if (locale_decimal_point == '.')\n        return strtod(nptr, endptr);\n\n    buflen = strtod_buffer_size(nptr);\n    if (!buflen) {\n        /* No valid characters found, standard strtod() return */\n        *endptr = (char *)nptr;\n        return 0;\n    }\n\n    /* Duplicate number into buffer */\n    if (buflen >= FPCONV_G_FMT_BUFSIZE) {\n        /* Handle unusually large numbers */\n        buf = malloc(buflen + 1);\n        if (!buf) {\n            fprintf(stderr, \"Out of memory\");\n            abort();\n        }\n    } else {\n        /* This is the common case.. */\n        buf = localbuf;\n    }\n    memcpy(buf, nptr, buflen);\n    buf[buflen] = 0;\n\n    /* Update decimal point character if found */\n    dp = strchr(buf, '.');\n    if (dp)\n        *dp = locale_decimal_point;\n\n    value = strtod(buf, &endbuf);\n    *endptr = (char *)&nptr[endbuf - buf];\n    if (buflen >= FPCONV_G_FMT_BUFSIZE)\n        free(buf);\n\n    return value;\n}\n\n/* \"fmt\" must point to a buffer of at least 6 characters */\nstatic void set_number_format(char *fmt, int precision)\n{\n    int d1, d2, i;\n\n    assert(1 <= precision && precision <= 14);\n\n    /* Create printf format (%.14g) from precision */\n    d1 = precision / 10;\n    d2 = precision % 10;\n    fmt[0] = '%';\n    fmt[1] = '.';\n    i = 2;\n    if (d1) {\n        fmt[i++] = '0' + d1;\n    }\n    fmt[i++] = '0' + d2;\n    fmt[i++] = 'g';\n    fmt[i] = 0;\n}\n\n/* Assumes there is always at least 32 characters available in the target buffer */\nint fpconv_g_fmt(char *str, double num, int precision)\n{\n    char buf[FPCONV_G_FMT_BUFSIZE];\n    char fmt[6];\n    int len;\n    char *b;\n\n    set_number_format(fmt, precision);\n\n    /* Pass through when decimal point character is dot. */\n    if (locale_decimal_point == '.')\n        return snprintf(str, FPCONV_G_FMT_BUFSIZE, fmt, num);\n\n    /* snprintf() to a buffer then translate for other decimal point characters */\n    len = snprintf(buf, FPCONV_G_FMT_BUFSIZE, fmt, num);\n\n    /* Copy into target location. Translate decimal point if required */\n    b = buf;\n    do {\n        *str++ = (*b == locale_decimal_point ? '.' : *b);\n    } while(*b++);\n\n    return len;\n}\n\nvoid fpconv_init()\n{\n    fpconv_update_locale();\n}\n\n/* vi:ai et sw=4 ts=4:\n */\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/deps/lua/src/fpconv.h",
    "content": "/* Lua CJSON floating point conversion routines */\n\n/* Buffer required to store the largest string representation of a double.\n *\n * Longest double printed with %.14g is 21 characters long:\n * -1.7976931348623e+308 */\n# define FPCONV_G_FMT_BUFSIZE   32\n\n#ifdef USE_INTERNAL_FPCONV\nstatic inline void fpconv_init()\n{\n    /* Do nothing - not required */\n}\n#else\nextern void fpconv_init();\n#endif\n\nextern int fpconv_g_fmt(char*, double, int);\nextern double fpconv_strtod(const char*, char**);\n\n/* vi:ai et sw=4 ts=4:\n */\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/deps/lua/src/lapi.c",
    "content": "/*\n** $Id: lapi.c,v 2.55.1.5 2008/07/04 18:41:18 roberto Exp $\n** Lua API\n** See Copyright Notice in lua.h\n*/\n\n\n#include <assert.h>\n#include <math.h>\n#include <stdarg.h>\n#include <string.h>\n\n#define lapi_c\n#define LUA_CORE\n\n#include \"lua.h\"\n\n#include \"lapi.h\"\n#include \"ldebug.h\"\n#include \"ldo.h\"\n#include \"lfunc.h\"\n#include \"lgc.h\"\n#include \"lmem.h\"\n#include \"lobject.h\"\n#include \"lstate.h\"\n#include \"lstring.h\"\n#include \"ltable.h\"\n#include \"ltm.h\"\n#include \"lundump.h\"\n#include \"lvm.h\"\n\n\n\nconst char lua_ident[] =\n  \"$Lua: \" LUA_RELEASE \" \" LUA_COPYRIGHT \" $\\n\"\n  \"$Authors: \" LUA_AUTHORS \" $\\n\"\n  \"$URL: www.lua.org $\\n\";\n\n\n\n#define api_checknelems(L, n)\tapi_check(L, (n) <= (L->top - L->base))\n\n#define api_checkvalidindex(L, i)\tapi_check(L, (i) != luaO_nilobject)\n\n#define api_incr_top(L)   {api_check(L, L->top < L->ci->top); L->top++;}\n\n\n\nstatic TValue *index2adr (lua_State *L, int idx) {\n  if (idx > 0) {\n    TValue *o = L->base + (idx - 1);\n    api_check(L, idx <= L->ci->top - L->base);\n    if (o >= L->top) return cast(TValue *, luaO_nilobject);\n    else return o;\n  }\n  else if (idx > LUA_REGISTRYINDEX) {\n    api_check(L, idx != 0 && -idx <= L->top - L->base);\n    return L->top + idx;\n  }\n  else switch (idx) {  /* pseudo-indices */\n    case LUA_REGISTRYINDEX: return registry(L);\n    case LUA_ENVIRONINDEX: {\n      Closure *func = curr_func(L);\n      sethvalue(L, &L->env, func->c.env);\n      return &L->env;\n    }\n    case LUA_GLOBALSINDEX: return gt(L);\n    default: {\n      Closure *func = curr_func(L);\n      idx = LUA_GLOBALSINDEX - idx;\n      return (idx <= func->c.nupvalues)\n                ? &func->c.upvalue[idx-1]\n                : cast(TValue *, luaO_nilobject);\n    }\n  }\n}\n\n\nstatic Table *getcurrenv (lua_State *L) {\n  if (L->ci == L->base_ci)  /* no enclosing function? */\n    return hvalue(gt(L));  /* use global table as environment */\n  else {\n    Closure *func = curr_func(L);\n    return func->c.env;\n  }\n}\n\n\nvoid luaA_pushobject (lua_State *L, const TValue *o) {\n  setobj2s(L, L->top, o);\n  api_incr_top(L);\n}\n\n\nLUA_API int lua_checkstack (lua_State *L, int size) {\n  int res = 1;\n  lua_lock(L);\n  if (size > LUAI_MAXCSTACK || (L->top - L->base + size) > LUAI_MAXCSTACK)\n    res = 0;  /* stack overflow */\n  else if (size > 0) {\n    luaD_checkstack(L, size);\n    if (L->ci->top < L->top + size)\n      L->ci->top = L->top + size;\n  }\n  lua_unlock(L);\n  return res;\n}\n\n\nLUA_API void lua_xmove (lua_State *from, lua_State *to, int n) {\n  int i;\n  if (from == to) return;\n  lua_lock(to);\n  api_checknelems(from, n);\n  api_check(from, G(from) == G(to));\n  api_check(from, to->ci->top - to->top >= n);\n  from->top -= n;\n  for (i = 0; i < n; i++) {\n    setobj2s(to, to->top++, from->top + i);\n  }\n  lua_unlock(to);\n}\n\n\nLUA_API void lua_setlevel (lua_State *from, lua_State *to) {\n  to->nCcalls = from->nCcalls;\n}\n\n\nLUA_API lua_CFunction lua_atpanic (lua_State *L, lua_CFunction panicf) {\n  lua_CFunction old;\n  lua_lock(L);\n  old = G(L)->panic;\n  G(L)->panic = panicf;\n  lua_unlock(L);\n  return old;\n}\n\n\nLUA_API lua_State *lua_newthread (lua_State *L) {\n  lua_State *L1;\n  lua_lock(L);\n  luaC_checkGC(L);\n  L1 = luaE_newthread(L);\n  setthvalue(L, L->top, L1);\n  api_incr_top(L);\n  lua_unlock(L);\n  luai_userstatethread(L, L1);\n  return L1;\n}\n\n\n\n/*\n** basic stack manipulation\n*/\n\n\nLUA_API int lua_gettop (lua_State *L) {\n  return cast_int(L->top - L->base);\n}\n\n\nLUA_API void lua_settop (lua_State *L, int idx) {\n  lua_lock(L);\n  if (idx >= 0) {\n    api_check(L, idx <= L->stack_last - L->base);\n    while (L->top < L->base + idx)\n      setnilvalue(L->top++);\n    L->top = L->base + idx;\n  }\n  else {\n    api_check(L, -(idx+1) <= (L->top - L->base));\n    L->top += idx+1;  /* `subtract' index (index is negative) */\n  }\n  lua_unlock(L);\n}\n\n\nLUA_API void lua_remove (lua_State *L, int idx) {\n  StkId p;\n  lua_lock(L);\n  p = index2adr(L, idx);\n  api_checkvalidindex(L, p);\n  while (++p < L->top) setobjs2s(L, p-1, p);\n  L->top--;\n  lua_unlock(L);\n}\n\n\nLUA_API void lua_insert (lua_State *L, int idx) {\n  StkId p;\n  StkId q;\n  lua_lock(L);\n  p = index2adr(L, idx);\n  api_checkvalidindex(L, p);\n  for (q = L->top; q>p; q--) setobjs2s(L, q, q-1);\n  setobjs2s(L, p, L->top);\n  lua_unlock(L);\n}\n\n\nLUA_API void lua_replace (lua_State *L, int idx) {\n  StkId o;\n  lua_lock(L);\n  /* explicit test for incompatible code */\n  if (idx == LUA_ENVIRONINDEX && L->ci == L->base_ci)\n    luaG_runerror(L, \"no calling environment\");\n  api_checknelems(L, 1);\n  o = index2adr(L, idx);\n  api_checkvalidindex(L, o);\n  if (idx == LUA_ENVIRONINDEX) {\n    Closure *func = curr_func(L);\n    api_check(L, ttistable(L->top - 1)); \n    func->c.env = hvalue(L->top - 1);\n    luaC_barrier(L, func, L->top - 1);\n  }\n  else {\n    setobj(L, o, L->top - 1);\n    if (idx < LUA_GLOBALSINDEX)  /* function upvalue? */\n      luaC_barrier(L, curr_func(L), L->top - 1);\n  }\n  L->top--;\n  lua_unlock(L);\n}\n\n\nLUA_API void lua_pushvalue (lua_State *L, int idx) {\n  lua_lock(L);\n  setobj2s(L, L->top, index2adr(L, idx));\n  api_incr_top(L);\n  lua_unlock(L);\n}\n\n\n\n/*\n** access functions (stack -> C)\n*/\n\n\nLUA_API int lua_type (lua_State *L, int idx) {\n  StkId o = index2adr(L, idx);\n  return (o == luaO_nilobject) ? LUA_TNONE : ttype(o);\n}\n\n\nLUA_API const char *lua_typename (lua_State *L, int t) {\n  UNUSED(L);\n  return (t == LUA_TNONE) ? \"no value\" : luaT_typenames[t];\n}\n\n\nLUA_API int lua_iscfunction (lua_State *L, int idx) {\n  StkId o = index2adr(L, idx);\n  return iscfunction(o);\n}\n\n\nLUA_API int lua_isnumber (lua_State *L, int idx) {\n  TValue n;\n  const TValue *o = index2adr(L, idx);\n  return tonumber(o, &n);\n}\n\n\nLUA_API int lua_isstring (lua_State *L, int idx) {\n  int t = lua_type(L, idx);\n  return (t == LUA_TSTRING || t == LUA_TNUMBER);\n}\n\n\nLUA_API int lua_isuserdata (lua_State *L, int idx) {\n  const TValue *o = index2adr(L, idx);\n  return (ttisuserdata(o) || ttislightuserdata(o));\n}\n\n\nLUA_API int lua_rawequal (lua_State *L, int index1, int index2) {\n  StkId o1 = index2adr(L, index1);\n  StkId o2 = index2adr(L, index2);\n  return (o1 == luaO_nilobject || o2 == luaO_nilobject) ? 0\n         : luaO_rawequalObj(o1, o2);\n}\n\n\nLUA_API int lua_equal (lua_State *L, int index1, int index2) {\n  StkId o1, o2;\n  int i;\n  lua_lock(L);  /* may call tag method */\n  o1 = index2adr(L, index1);\n  o2 = index2adr(L, index2);\n  i = (o1 == luaO_nilobject || o2 == luaO_nilobject) ? 0 : equalobj(L, o1, o2);\n  lua_unlock(L);\n  return i;\n}\n\n\nLUA_API int lua_lessthan (lua_State *L, int index1, int index2) {\n  StkId o1, o2;\n  int i;\n  lua_lock(L);  /* may call tag method */\n  o1 = index2adr(L, index1);\n  o2 = index2adr(L, index2);\n  i = (o1 == luaO_nilobject || o2 == luaO_nilobject) ? 0\n       : luaV_lessthan(L, o1, o2);\n  lua_unlock(L);\n  return i;\n}\n\n\n\nLUA_API lua_Number lua_tonumber (lua_State *L, int idx) {\n  TValue n;\n  const TValue *o = index2adr(L, idx);\n  if (tonumber(o, &n))\n    return nvalue(o);\n  else\n    return 0;\n}\n\n\nLUA_API lua_Integer lua_tointeger (lua_State *L, int idx) {\n  TValue n;\n  const TValue *o = index2adr(L, idx);\n  if (tonumber(o, &n)) {\n    lua_Integer res;\n    lua_Number num = nvalue(o);\n    lua_number2integer(res, num);\n    return res;\n  }\n  else\n    return 0;\n}\n\n\nLUA_API int lua_toboolean (lua_State *L, int idx) {\n  const TValue *o = index2adr(L, idx);\n  return !l_isfalse(o);\n}\n\n\nLUA_API const char *lua_tolstring (lua_State *L, int idx, size_t *len) {\n  StkId o = index2adr(L, idx);\n  if (!ttisstring(o)) {\n    lua_lock(L);  /* `luaV_tostring' may create a new string */\n    if (!luaV_tostring(L, o)) {  /* conversion failed? */\n      if (len != NULL) *len = 0;\n      lua_unlock(L);\n      return NULL;\n    }\n    luaC_checkGC(L);\n    o = index2adr(L, idx);  /* previous call may reallocate the stack */\n    lua_unlock(L);\n  }\n  if (len != NULL) *len = tsvalue(o)->len;\n  return svalue(o);\n}\n\n\nLUA_API size_t lua_objlen (lua_State *L, int idx) {\n  StkId o = index2adr(L, idx);\n  switch (ttype(o)) {\n    case LUA_TSTRING: return tsvalue(o)->len;\n    case LUA_TUSERDATA: return uvalue(o)->len;\n    case LUA_TTABLE: return luaH_getn(hvalue(o));\n    case LUA_TNUMBER: {\n      size_t l;\n      lua_lock(L);  /* `luaV_tostring' may create a new string */\n      l = (luaV_tostring(L, o) ? tsvalue(o)->len : 0);\n      lua_unlock(L);\n      return l;\n    }\n    default: return 0;\n  }\n}\n\n\nLUA_API lua_CFunction lua_tocfunction (lua_State *L, int idx) {\n  StkId o = index2adr(L, idx);\n  return (!iscfunction(o)) ? NULL : clvalue(o)->c.f;\n}\n\n\nLUA_API void *lua_touserdata (lua_State *L, int idx) {\n  StkId o = index2adr(L, idx);\n  switch (ttype(o)) {\n    case LUA_TUSERDATA: return (rawuvalue(o) + 1);\n    case LUA_TLIGHTUSERDATA: return pvalue(o);\n    default: return NULL;\n  }\n}\n\n\nLUA_API lua_State *lua_tothread (lua_State *L, int idx) {\n  StkId o = index2adr(L, idx);\n  return (!ttisthread(o)) ? NULL : thvalue(o);\n}\n\n\nLUA_API const void *lua_topointer (lua_State *L, int idx) {\n  StkId o = index2adr(L, idx);\n  switch (ttype(o)) {\n    case LUA_TTABLE: return hvalue(o);\n    case LUA_TFUNCTION: return clvalue(o);\n    case LUA_TTHREAD: return thvalue(o);\n    case LUA_TUSERDATA:\n    case LUA_TLIGHTUSERDATA:\n      return lua_touserdata(L, idx);\n    default: return NULL;\n  }\n}\n\n\n\n/*\n** push functions (C -> stack)\n*/\n\n\nLUA_API void lua_pushnil (lua_State *L) {\n  lua_lock(L);\n  setnilvalue(L->top);\n  api_incr_top(L);\n  lua_unlock(L);\n}\n\n\nLUA_API void lua_pushnumber (lua_State *L, lua_Number n) {\n  lua_lock(L);\n  setnvalue(L->top, n);\n  api_incr_top(L);\n  lua_unlock(L);\n}\n\n\nLUA_API void lua_pushinteger (lua_State *L, lua_Integer n) {\n  lua_lock(L);\n  setnvalue(L->top, cast_num(n));\n  api_incr_top(L);\n  lua_unlock(L);\n}\n\n\nLUA_API void lua_pushlstring (lua_State *L, const char *s, size_t len) {\n  lua_lock(L);\n  luaC_checkGC(L);\n  setsvalue2s(L, L->top, luaS_newlstr(L, s, len));\n  api_incr_top(L);\n  lua_unlock(L);\n}\n\n\nLUA_API void lua_pushstring (lua_State *L, const char *s) {\n  if (s == NULL)\n    lua_pushnil(L);\n  else\n    lua_pushlstring(L, s, strlen(s));\n}\n\n\nLUA_API const char *lua_pushvfstring (lua_State *L, const char *fmt,\n                                      va_list argp) {\n  const char *ret;\n  lua_lock(L);\n  luaC_checkGC(L);\n  ret = luaO_pushvfstring(L, fmt, argp);\n  lua_unlock(L);\n  return ret;\n}\n\n\nLUA_API const char *lua_pushfstring (lua_State *L, const char *fmt, ...) {\n  const char *ret;\n  va_list argp;\n  lua_lock(L);\n  luaC_checkGC(L);\n  va_start(argp, fmt);\n  ret = luaO_pushvfstring(L, fmt, argp);\n  va_end(argp);\n  lua_unlock(L);\n  return ret;\n}\n\n\nLUA_API void lua_pushcclosure (lua_State *L, lua_CFunction fn, int n) {\n  Closure *cl;\n  lua_lock(L);\n  luaC_checkGC(L);\n  api_checknelems(L, n);\n  cl = luaF_newCclosure(L, n, getcurrenv(L));\n  cl->c.f = fn;\n  L->top -= n;\n  while (n--)\n    setobj2n(L, &cl->c.upvalue[n], L->top+n);\n  setclvalue(L, L->top, cl);\n  lua_assert(iswhite(obj2gco(cl)));\n  api_incr_top(L);\n  lua_unlock(L);\n}\n\n\nLUA_API void lua_pushboolean (lua_State *L, int b) {\n  lua_lock(L);\n  setbvalue(L->top, (b != 0));  /* ensure that true is 1 */\n  api_incr_top(L);\n  lua_unlock(L);\n}\n\n\nLUA_API void lua_pushlightuserdata (lua_State *L, void *p) {\n  lua_lock(L);\n  setpvalue(L->top, p);\n  api_incr_top(L);\n  lua_unlock(L);\n}\n\n\nLUA_API int lua_pushthread (lua_State *L) {\n  lua_lock(L);\n  setthvalue(L, L->top, L);\n  api_incr_top(L);\n  lua_unlock(L);\n  return (G(L)->mainthread == L);\n}\n\n\n\n/*\n** get functions (Lua -> stack)\n*/\n\n\nLUA_API void lua_gettable (lua_State *L, int idx) {\n  StkId t;\n  lua_lock(L);\n  t = index2adr(L, idx);\n  api_checkvalidindex(L, t);\n  luaV_gettable(L, t, L->top - 1, L->top - 1);\n  lua_unlock(L);\n}\n\n\nLUA_API void lua_getfield (lua_State *L, int idx, const char *k) {\n  StkId t;\n  TValue key;\n  lua_lock(L);\n  t = index2adr(L, idx);\n  api_checkvalidindex(L, t);\n  setsvalue(L, &key, luaS_new(L, k));\n  luaV_gettable(L, t, &key, L->top);\n  api_incr_top(L);\n  lua_unlock(L);\n}\n\n\nLUA_API void lua_rawget (lua_State *L, int idx) {\n  StkId t;\n  lua_lock(L);\n  t = index2adr(L, idx);\n  api_check(L, ttistable(t));\n  setobj2s(L, L->top - 1, luaH_get(hvalue(t), L->top - 1));\n  lua_unlock(L);\n}\n\n\nLUA_API void lua_rawgeti (lua_State *L, int idx, int n) {\n  StkId o;\n  lua_lock(L);\n  o = index2adr(L, idx);\n  api_check(L, ttistable(o));\n  setobj2s(L, L->top, luaH_getnum(hvalue(o), n));\n  api_incr_top(L);\n  lua_unlock(L);\n}\n\n\nLUA_API void lua_createtable (lua_State *L, int narray, int nrec) {\n  lua_lock(L);\n  luaC_checkGC(L);\n  sethvalue(L, L->top, luaH_new(L, narray, nrec));\n  api_incr_top(L);\n  lua_unlock(L);\n}\n\n\nLUA_API int lua_getmetatable (lua_State *L, int objindex) {\n  const TValue *obj;\n  Table *mt = NULL;\n  int res;\n  lua_lock(L);\n  obj = index2adr(L, objindex);\n  switch (ttype(obj)) {\n    case LUA_TTABLE:\n      mt = hvalue(obj)->metatable;\n      break;\n    case LUA_TUSERDATA:\n      mt = uvalue(obj)->metatable;\n      break;\n    default:\n      mt = G(L)->mt[ttype(obj)];\n      break;\n  }\n  if (mt == NULL)\n    res = 0;\n  else {\n    sethvalue(L, L->top, mt);\n    api_incr_top(L);\n    res = 1;\n  }\n  lua_unlock(L);\n  return res;\n}\n\n\nLUA_API void lua_getfenv (lua_State *L, int idx) {\n  StkId o;\n  lua_lock(L);\n  o = index2adr(L, idx);\n  api_checkvalidindex(L, o);\n  switch (ttype(o)) {\n    case LUA_TFUNCTION:\n      sethvalue(L, L->top, clvalue(o)->c.env);\n      break;\n    case LUA_TUSERDATA:\n      sethvalue(L, L->top, uvalue(o)->env);\n      break;\n    case LUA_TTHREAD:\n      setobj2s(L, L->top,  gt(thvalue(o)));\n      break;\n    default:\n      setnilvalue(L->top);\n      break;\n  }\n  api_incr_top(L);\n  lua_unlock(L);\n}\n\n\n/*\n** set functions (stack -> Lua)\n*/\n\n\nLUA_API void lua_settable (lua_State *L, int idx) {\n  StkId t;\n  lua_lock(L);\n  api_checknelems(L, 2);\n  t = index2adr(L, idx);\n  api_checkvalidindex(L, t);\n  luaV_settable(L, t, L->top - 2, L->top - 1);\n  L->top -= 2;  /* pop index and value */\n  lua_unlock(L);\n}\n\n\nLUA_API void lua_setfield (lua_State *L, int idx, const char *k) {\n  StkId t;\n  TValue key;\n  lua_lock(L);\n  api_checknelems(L, 1);\n  t = index2adr(L, idx);\n  api_checkvalidindex(L, t);\n  setsvalue(L, &key, luaS_new(L, k));\n  luaV_settable(L, t, &key, L->top - 1);\n  L->top--;  /* pop value */\n  lua_unlock(L);\n}\n\n\nLUA_API void lua_rawset (lua_State *L, int idx) {\n  StkId t;\n  lua_lock(L);\n  api_checknelems(L, 2);\n  t = index2adr(L, idx);\n  api_check(L, ttistable(t));\n  setobj2t(L, luaH_set(L, hvalue(t), L->top-2), L->top-1);\n  luaC_barriert(L, hvalue(t), L->top-1);\n  L->top -= 2;\n  lua_unlock(L);\n}\n\n\nLUA_API void lua_rawseti (lua_State *L, int idx, int n) {\n  StkId o;\n  lua_lock(L);\n  api_checknelems(L, 1);\n  o = index2adr(L, idx);\n  api_check(L, ttistable(o));\n  setobj2t(L, luaH_setnum(L, hvalue(o), n), L->top-1);\n  luaC_barriert(L, hvalue(o), L->top-1);\n  L->top--;\n  lua_unlock(L);\n}\n\n\nLUA_API int lua_setmetatable (lua_State *L, int objindex) {\n  TValue *obj;\n  Table *mt;\n  lua_lock(L);\n  api_checknelems(L, 1);\n  obj = index2adr(L, objindex);\n  api_checkvalidindex(L, obj);\n  if (ttisnil(L->top - 1))\n    mt = NULL;\n  else {\n    api_check(L, ttistable(L->top - 1));\n    mt = hvalue(L->top - 1);\n  }\n  switch (ttype(obj)) {\n    case LUA_TTABLE: {\n      hvalue(obj)->metatable = mt;\n      if (mt)\n        luaC_objbarriert(L, hvalue(obj), mt);\n      break;\n    }\n    case LUA_TUSERDATA: {\n      uvalue(obj)->metatable = mt;\n      if (mt)\n        luaC_objbarrier(L, rawuvalue(obj), mt);\n      break;\n    }\n    default: {\n      G(L)->mt[ttype(obj)] = mt;\n      break;\n    }\n  }\n  L->top--;\n  lua_unlock(L);\n  return 1;\n}\n\n\nLUA_API int lua_setfenv (lua_State *L, int idx) {\n  StkId o;\n  int res = 1;\n  lua_lock(L);\n  api_checknelems(L, 1);\n  o = index2adr(L, idx);\n  api_checkvalidindex(L, o);\n  api_check(L, ttistable(L->top - 1));\n  switch (ttype(o)) {\n    case LUA_TFUNCTION:\n      clvalue(o)->c.env = hvalue(L->top - 1);\n      break;\n    case LUA_TUSERDATA:\n      uvalue(o)->env = hvalue(L->top - 1);\n      break;\n    case LUA_TTHREAD:\n      sethvalue(L, gt(thvalue(o)), hvalue(L->top - 1));\n      break;\n    default:\n      res = 0;\n      break;\n  }\n  if (res) luaC_objbarrier(L, gcvalue(o), hvalue(L->top - 1));\n  L->top--;\n  lua_unlock(L);\n  return res;\n}\n\n\n/*\n** `load' and `call' functions (run Lua code)\n*/\n\n\n#define adjustresults(L,nres) \\\n    { if (nres == LUA_MULTRET && L->top >= L->ci->top) L->ci->top = L->top; }\n\n\n#define checkresults(L,na,nr) \\\n     api_check(L, (nr) == LUA_MULTRET || (L->ci->top - L->top >= (nr) - (na)))\n\t\n\nLUA_API void lua_call (lua_State *L, int nargs, int nresults) {\n  StkId func;\n  lua_lock(L);\n  api_checknelems(L, nargs+1);\n  checkresults(L, nargs, nresults);\n  func = L->top - (nargs+1);\n  luaD_call(L, func, nresults);\n  adjustresults(L, nresults);\n  lua_unlock(L);\n}\n\n\n\n/*\n** Execute a protected call.\n*/\nstruct CallS {  /* data to `f_call' */\n  StkId func;\n  int nresults;\n};\n\n\nstatic void f_call (lua_State *L, void *ud) {\n  struct CallS *c = cast(struct CallS *, ud);\n  luaD_call(L, c->func, c->nresults);\n}\n\n\n\nLUA_API int lua_pcall (lua_State *L, int nargs, int nresults, int errfunc) {\n  struct CallS c;\n  int status;\n  ptrdiff_t func;\n  lua_lock(L);\n  api_checknelems(L, nargs+1);\n  checkresults(L, nargs, nresults);\n  if (errfunc == 0)\n    func = 0;\n  else {\n    StkId o = index2adr(L, errfunc);\n    api_checkvalidindex(L, o);\n    func = savestack(L, o);\n  }\n  c.func = L->top - (nargs+1);  /* function to be called */\n  c.nresults = nresults;\n  status = luaD_pcall(L, f_call, &c, savestack(L, c.func), func);\n  adjustresults(L, nresults);\n  lua_unlock(L);\n  return status;\n}\n\n\n/*\n** Execute a protected C call.\n*/\nstruct CCallS {  /* data to `f_Ccall' */\n  lua_CFunction func;\n  void *ud;\n};\n\n\nstatic void f_Ccall (lua_State *L, void *ud) {\n  struct CCallS *c = cast(struct CCallS *, ud);\n  Closure *cl;\n  cl = luaF_newCclosure(L, 0, getcurrenv(L));\n  cl->c.f = c->func;\n  setclvalue(L, L->top, cl);  /* push function */\n  api_incr_top(L);\n  setpvalue(L->top, c->ud);  /* push only argument */\n  api_incr_top(L);\n  luaD_call(L, L->top - 2, 0);\n}\n\n\nLUA_API int lua_cpcall (lua_State *L, lua_CFunction func, void *ud) {\n  struct CCallS c;\n  int status;\n  lua_lock(L);\n  c.func = func;\n  c.ud = ud;\n  status = luaD_pcall(L, f_Ccall, &c, savestack(L, L->top), 0);\n  lua_unlock(L);\n  return status;\n}\n\n\nLUA_API int lua_load (lua_State *L, lua_Reader reader, void *data,\n                      const char *chunkname) {\n  ZIO z;\n  int status;\n  lua_lock(L);\n  if (!chunkname) chunkname = \"?\";\n  luaZ_init(L, &z, reader, data);\n  status = luaD_protectedparser(L, &z, chunkname);\n  lua_unlock(L);\n  return status;\n}\n\n\nLUA_API int lua_dump (lua_State *L, lua_Writer writer, void *data) {\n  int status;\n  TValue *o;\n  lua_lock(L);\n  api_checknelems(L, 1);\n  o = L->top - 1;\n  if (isLfunction(o))\n    status = luaU_dump(L, clvalue(o)->l.p, writer, data, 0);\n  else\n    status = 1;\n  lua_unlock(L);\n  return status;\n}\n\n\nLUA_API int  lua_status (lua_State *L) {\n  return L->status;\n}\n\n\n/*\n** Garbage-collection function\n*/\n\nLUA_API int lua_gc (lua_State *L, int what, int data) {\n  int res = 0;\n  global_State *g;\n  lua_lock(L);\n  g = G(L);\n  switch (what) {\n    case LUA_GCSTOP: {\n      g->GCthreshold = MAX_LUMEM;\n      break;\n    }\n    case LUA_GCRESTART: {\n      g->GCthreshold = g->totalbytes;\n      break;\n    }\n    case LUA_GCCOLLECT: {\n      luaC_fullgc(L);\n      break;\n    }\n    case LUA_GCCOUNT: {\n      /* GC values are expressed in Kbytes: #bytes/2^10 */\n      res = cast_int(g->totalbytes >> 10);\n      break;\n    }\n    case LUA_GCCOUNTB: {\n      res = cast_int(g->totalbytes & 0x3ff);\n      break;\n    }\n    case LUA_GCSTEP: {\n      lu_mem a = (cast(lu_mem, data) << 10);\n      if (a <= g->totalbytes)\n        g->GCthreshold = g->totalbytes - a;\n      else\n        g->GCthreshold = 0;\n      while (g->GCthreshold <= g->totalbytes) {\n        luaC_step(L);\n        if (g->gcstate == GCSpause) {  /* end of cycle? */\n          res = 1;  /* signal it */\n          break;\n        }\n      }\n      break;\n    }\n    case LUA_GCSETPAUSE: {\n      res = g->gcpause;\n      g->gcpause = data;\n      break;\n    }\n    case LUA_GCSETSTEPMUL: {\n      res = g->gcstepmul;\n      g->gcstepmul = data;\n      break;\n    }\n    default: res = -1;  /* invalid option */\n  }\n  lua_unlock(L);\n  return res;\n}\n\n\n\n/*\n** miscellaneous functions\n*/\n\n\nLUA_API int lua_error (lua_State *L) {\n  lua_lock(L);\n  api_checknelems(L, 1);\n  luaG_errormsg(L);\n  lua_unlock(L);\n  return 0;  /* to avoid warnings */\n}\n\n\nLUA_API int lua_next (lua_State *L, int idx) {\n  StkId t;\n  int more;\n  lua_lock(L);\n  t = index2adr(L, idx);\n  api_check(L, ttistable(t));\n  more = luaH_next(L, hvalue(t), L->top - 1);\n  if (more) {\n    api_incr_top(L);\n  }\n  else  /* no more elements */\n    L->top -= 1;  /* remove key */\n  lua_unlock(L);\n  return more;\n}\n\n\nLUA_API void lua_concat (lua_State *L, int n) {\n  lua_lock(L);\n  api_checknelems(L, n);\n  if (n >= 2) {\n    luaC_checkGC(L);\n    luaV_concat(L, n, cast_int(L->top - L->base) - 1);\n    L->top -= (n-1);\n  }\n  else if (n == 0) {  /* push empty string */\n    setsvalue2s(L, L->top, luaS_newlstr(L, \"\", 0));\n    api_incr_top(L);\n  }\n  /* else n == 1; nothing to do */\n  lua_unlock(L);\n}\n\n\nLUA_API lua_Alloc lua_getallocf (lua_State *L, void **ud) {\n  lua_Alloc f;\n  lua_lock(L);\n  if (ud) *ud = G(L)->ud;\n  f = G(L)->frealloc;\n  lua_unlock(L);\n  return f;\n}\n\n\nLUA_API void lua_setallocf (lua_State *L, lua_Alloc f, void *ud) {\n  lua_lock(L);\n  G(L)->ud = ud;\n  G(L)->frealloc = f;\n  lua_unlock(L);\n}\n\n\nLUA_API void *lua_newuserdata (lua_State *L, size_t size) {\n  Udata *u;\n  lua_lock(L);\n  luaC_checkGC(L);\n  u = luaS_newudata(L, size, getcurrenv(L));\n  setuvalue(L, L->top, u);\n  api_incr_top(L);\n  lua_unlock(L);\n  return u + 1;\n}\n\n\n\n\nstatic const char *aux_upvalue (StkId fi, int n, TValue **val) {\n  Closure *f;\n  if (!ttisfunction(fi)) return NULL;\n  f = clvalue(fi);\n  if (f->c.isC) {\n    if (!(1 <= n && n <= f->c.nupvalues)) return NULL;\n    *val = &f->c.upvalue[n-1];\n    return \"\";\n  }\n  else {\n    Proto *p = f->l.p;\n    if (!(1 <= n && n <= p->sizeupvalues)) return NULL;\n    *val = f->l.upvals[n-1]->v;\n    return getstr(p->upvalues[n-1]);\n  }\n}\n\n\nLUA_API const char *lua_getupvalue (lua_State *L, int funcindex, int n) {\n  const char *name;\n  TValue *val;\n  lua_lock(L);\n  name = aux_upvalue(index2adr(L, funcindex), n, &val);\n  if (name) {\n    setobj2s(L, L->top, val);\n    api_incr_top(L);\n  }\n  lua_unlock(L);\n  return name;\n}\n\n\nLUA_API const char *lua_setupvalue (lua_State *L, int funcindex, int n) {\n  const char *name;\n  TValue *val;\n  StkId fi;\n  lua_lock(L);\n  fi = index2adr(L, funcindex);\n  api_checknelems(L, 1);\n  name = aux_upvalue(fi, n, &val);\n  if (name) {\n    L->top--;\n    setobj(L, val, L->top);\n    luaC_barrier(L, clvalue(fi), L->top);\n  }\n  lua_unlock(L);\n  return name;\n}\n\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/deps/lua/src/lapi.h",
    "content": "/*\n** $Id: lapi.h,v 2.2.1.1 2007/12/27 13:02:25 roberto Exp $\n** Auxiliary functions from Lua API\n** See Copyright Notice in lua.h\n*/\n\n#ifndef lapi_h\n#define lapi_h\n\n\n#include \"lobject.h\"\n\n\nLUAI_FUNC void luaA_pushobject (lua_State *L, const TValue *o);\n\n#endif\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/deps/lua/src/lauxlib.c",
    "content": "/*\n** $Id: lauxlib.c,v 1.159.1.3 2008/01/21 13:20:51 roberto Exp $\n** Auxiliary functions for building Lua libraries\n** See Copyright Notice in lua.h\n*/\n\n\n#include <ctype.h>\n#include <errno.h>\n#include <stdarg.h>\n#include <stdio.h>\n#include <stdlib.h>\n#include <string.h>\n\n\n/* This file uses only the official API of Lua.\n** Any function declared here could be written as an application function.\n*/\n\n#define lauxlib_c\n#define LUA_LIB\n\n#include \"lua.h\"\n\n#include \"lauxlib.h\"\n\n\n#define FREELIST_REF\t0\t/* free list of references */\n\n\n/* convert a stack index to positive */\n#define abs_index(L, i)\t\t((i) > 0 || (i) <= LUA_REGISTRYINDEX ? (i) : \\\n\t\t\t\t\tlua_gettop(L) + (i) + 1)\n\n\n/*\n** {======================================================\n** Error-report functions\n** =======================================================\n*/\n\n\nLUALIB_API int luaL_argerror (lua_State *L, int narg, const char *extramsg) {\n  lua_Debug ar;\n  if (!lua_getstack(L, 0, &ar))  /* no stack frame? */\n    return luaL_error(L, \"bad argument #%d (%s)\", narg, extramsg);\n  lua_getinfo(L, \"n\", &ar);\n  if (strcmp(ar.namewhat, \"method\") == 0) {\n    narg--;  /* do not count `self' */\n    if (narg == 0)  /* error is in the self argument itself? */\n      return luaL_error(L, \"calling \" LUA_QS \" on bad self (%s)\",\n                           ar.name, extramsg);\n  }\n  if (ar.name == NULL)\n    ar.name = \"?\";\n  return luaL_error(L, \"bad argument #%d to \" LUA_QS \" (%s)\",\n                        narg, ar.name, extramsg);\n}\n\n\nLUALIB_API int luaL_typerror (lua_State *L, int narg, const char *tname) {\n  const char *msg = lua_pushfstring(L, \"%s expected, got %s\",\n                                    tname, luaL_typename(L, narg));\n  return luaL_argerror(L, narg, msg);\n}\n\n\nstatic void tag_error (lua_State *L, int narg, int tag) {\n  luaL_typerror(L, narg, lua_typename(L, tag));\n}\n\n\nLUALIB_API void luaL_where (lua_State *L, int level) {\n  lua_Debug ar;\n  if (lua_getstack(L, level, &ar)) {  /* check function at level */\n    lua_getinfo(L, \"Sl\", &ar);  /* get info about it */\n    if (ar.currentline > 0) {  /* is there info? */\n      lua_pushfstring(L, \"%s:%d: \", ar.short_src, ar.currentline);\n      return;\n    }\n  }\n  lua_pushliteral(L, \"\");  /* else, no information available... */\n}\n\n\nLUALIB_API int luaL_error (lua_State *L, const char *fmt, ...) {\n  va_list argp;\n  va_start(argp, fmt);\n  luaL_where(L, 1);\n  lua_pushvfstring(L, fmt, argp);\n  va_end(argp);\n  lua_concat(L, 2);\n  return lua_error(L);\n}\n\n/* }====================================================== */\n\n\nLUALIB_API int luaL_checkoption (lua_State *L, int narg, const char *def,\n                                 const char *const lst[]) {\n  const char *name = (def) ? luaL_optstring(L, narg, def) :\n                             luaL_checkstring(L, narg);\n  int i;\n  for (i=0; lst[i]; i++)\n    if (strcmp(lst[i], name) == 0)\n      return i;\n  return luaL_argerror(L, narg,\n                       lua_pushfstring(L, \"invalid option \" LUA_QS, name));\n}\n\n\nLUALIB_API int luaL_newmetatable (lua_State *L, const char *tname) {\n  lua_getfield(L, LUA_REGISTRYINDEX, tname);  /* get registry.name */\n  if (!lua_isnil(L, -1))  /* name already in use? */\n    return 0;  /* leave previous value on top, but return 0 */\n  lua_pop(L, 1);\n  lua_newtable(L);  /* create metatable */\n  lua_pushvalue(L, -1);\n  lua_setfield(L, LUA_REGISTRYINDEX, tname);  /* registry.name = metatable */\n  return 1;\n}\n\n\nLUALIB_API void *luaL_checkudata (lua_State *L, int ud, const char *tname) {\n  void *p = lua_touserdata(L, ud);\n  if (p != NULL) {  /* value is a userdata? */\n    if (lua_getmetatable(L, ud)) {  /* does it have a metatable? */\n      lua_getfield(L, LUA_REGISTRYINDEX, tname);  /* get correct metatable */\n      if (lua_rawequal(L, -1, -2)) {  /* does it have the correct mt? */\n        lua_pop(L, 2);  /* remove both metatables */\n        return p;\n      }\n    }\n  }\n  luaL_typerror(L, ud, tname);  /* else error */\n  return NULL;  /* to avoid warnings */\n}\n\n\nLUALIB_API void luaL_checkstack (lua_State *L, int space, const char *mes) {\n  if (!lua_checkstack(L, space))\n    luaL_error(L, \"stack overflow (%s)\", mes);\n}\n\n\nLUALIB_API void luaL_checktype (lua_State *L, int narg, int t) {\n  if (lua_type(L, narg) != t)\n    tag_error(L, narg, t);\n}\n\n\nLUALIB_API void luaL_checkany (lua_State *L, int narg) {\n  if (lua_type(L, narg) == LUA_TNONE)\n    luaL_argerror(L, narg, \"value expected\");\n}\n\n\nLUALIB_API const char *luaL_checklstring (lua_State *L, int narg, size_t *len) {\n  const char *s = lua_tolstring(L, narg, len);\n  if (!s) tag_error(L, narg, LUA_TSTRING);\n  return s;\n}\n\n\nLUALIB_API const char *luaL_optlstring (lua_State *L, int narg,\n                                        const char *def, size_t *len) {\n  if (lua_isnoneornil(L, narg)) {\n    if (len)\n      *len = (def ? strlen(def) : 0);\n    return def;\n  }\n  else return luaL_checklstring(L, narg, len);\n}\n\n\nLUALIB_API lua_Number luaL_checknumber (lua_State *L, int narg) {\n  lua_Number d = lua_tonumber(L, narg);\n  if (d == 0 && !lua_isnumber(L, narg))  /* avoid extra test when d is not 0 */\n    tag_error(L, narg, LUA_TNUMBER);\n  return d;\n}\n\n\nLUALIB_API lua_Number luaL_optnumber (lua_State *L, int narg, lua_Number def) {\n  return luaL_opt(L, luaL_checknumber, narg, def);\n}\n\n\nLUALIB_API lua_Integer luaL_checkinteger (lua_State *L, int narg) {\n  lua_Integer d = lua_tointeger(L, narg);\n  if (d == 0 && !lua_isnumber(L, narg))  /* avoid extra test when d is not 0 */\n    tag_error(L, narg, LUA_TNUMBER);\n  return d;\n}\n\n\nLUALIB_API lua_Integer luaL_optinteger (lua_State *L, int narg,\n                                                      lua_Integer def) {\n  return luaL_opt(L, luaL_checkinteger, narg, def);\n}\n\n\nLUALIB_API int luaL_getmetafield (lua_State *L, int obj, const char *event) {\n  if (!lua_getmetatable(L, obj))  /* no metatable? */\n    return 0;\n  lua_pushstring(L, event);\n  lua_rawget(L, -2);\n  if (lua_isnil(L, -1)) {\n    lua_pop(L, 2);  /* remove metatable and metafield */\n    return 0;\n  }\n  else {\n    lua_remove(L, -2);  /* remove only metatable */\n    return 1;\n  }\n}\n\n\nLUALIB_API int luaL_callmeta (lua_State *L, int obj, const char *event) {\n  obj = abs_index(L, obj);\n  if (!luaL_getmetafield(L, obj, event))  /* no metafield? */\n    return 0;\n  lua_pushvalue(L, obj);\n  lua_call(L, 1, 1);\n  return 1;\n}\n\n\nLUALIB_API void (luaL_register) (lua_State *L, const char *libname,\n                                const luaL_Reg *l) {\n  luaI_openlib(L, libname, l, 0);\n}\n\n\nstatic int libsize (const luaL_Reg *l) {\n  int size = 0;\n  for (; l->name; l++) size++;\n  return size;\n}\n\n\nLUALIB_API void luaI_openlib (lua_State *L, const char *libname,\n                              const luaL_Reg *l, int nup) {\n  if (libname) {\n    int size = libsize(l);\n    /* check whether lib already exists */\n    luaL_findtable(L, LUA_REGISTRYINDEX, \"_LOADED\", 1);\n    lua_getfield(L, -1, libname);  /* get _LOADED[libname] */\n    if (!lua_istable(L, -1)) {  /* not found? */\n      lua_pop(L, 1);  /* remove previous result */\n      /* try global variable (and create one if it does not exist) */\n      if (luaL_findtable(L, LUA_GLOBALSINDEX, libname, size) != NULL)\n        luaL_error(L, \"name conflict for module \" LUA_QS, libname);\n      lua_pushvalue(L, -1);\n      lua_setfield(L, -3, libname);  /* _LOADED[libname] = new table */\n    }\n    lua_remove(L, -2);  /* remove _LOADED table */\n    lua_insert(L, -(nup+1));  /* move library table to below upvalues */\n  }\n  for (; l->name; l++) {\n    int i;\n    for (i=0; i<nup; i++)  /* copy upvalues to the top */\n      lua_pushvalue(L, -nup);\n    lua_pushcclosure(L, l->func, nup);\n    lua_setfield(L, -(nup+2), l->name);\n  }\n  lua_pop(L, nup);  /* remove upvalues */\n}\n\n\n\n/*\n** {======================================================\n** getn-setn: size for arrays\n** =======================================================\n*/\n\n#if defined(LUA_COMPAT_GETN)\n\nstatic int checkint (lua_State *L, int topop) {\n  int n = (lua_type(L, -1) == LUA_TNUMBER) ? lua_tointeger(L, -1) : -1;\n  lua_pop(L, topop);\n  return n;\n}\n\n\nstatic void getsizes (lua_State *L) {\n  lua_getfield(L, LUA_REGISTRYINDEX, \"LUA_SIZES\");\n  if (lua_isnil(L, -1)) {  /* no `size' table? */\n    lua_pop(L, 1);  /* remove nil */\n    lua_newtable(L);  /* create it */\n    lua_pushvalue(L, -1);  /* `size' will be its own metatable */\n    lua_setmetatable(L, -2);\n    lua_pushliteral(L, \"kv\");\n    lua_setfield(L, -2, \"__mode\");  /* metatable(N).__mode = \"kv\" */\n    lua_pushvalue(L, -1);\n    lua_setfield(L, LUA_REGISTRYINDEX, \"LUA_SIZES\");  /* store in register */\n  }\n}\n\n\nLUALIB_API void luaL_setn (lua_State *L, int t, int n) {\n  t = abs_index(L, t);\n  lua_pushliteral(L, \"n\");\n  lua_rawget(L, t);\n  if (checkint(L, 1) >= 0) {  /* is there a numeric field `n'? */\n    lua_pushliteral(L, \"n\");  /* use it */\n    lua_pushinteger(L, n);\n    lua_rawset(L, t);\n  }\n  else {  /* use `sizes' */\n    getsizes(L);\n    lua_pushvalue(L, t);\n    lua_pushinteger(L, n);\n    lua_rawset(L, -3);  /* sizes[t] = n */\n    lua_pop(L, 1);  /* remove `sizes' */\n  }\n}\n\n\nLUALIB_API int luaL_getn (lua_State *L, int t) {\n  int n;\n  t = abs_index(L, t);\n  lua_pushliteral(L, \"n\");  /* try t.n */\n  lua_rawget(L, t);\n  if ((n = checkint(L, 1)) >= 0) return n;\n  getsizes(L);  /* else try sizes[t] */\n  lua_pushvalue(L, t);\n  lua_rawget(L, -2);\n  if ((n = checkint(L, 2)) >= 0) return n;\n  return (int)lua_objlen(L, t);\n}\n\n#endif\n\n/* }====================================================== */\n\n\n\nLUALIB_API const char *luaL_gsub (lua_State *L, const char *s, const char *p,\n                                                               const char *r) {\n  const char *wild;\n  size_t l = strlen(p);\n  luaL_Buffer b;\n  luaL_buffinit(L, &b);\n  while ((wild = strstr(s, p)) != NULL) {\n    luaL_addlstring(&b, s, wild - s);  /* push prefix */\n    luaL_addstring(&b, r);  /* push replacement in place of pattern */\n    s = wild + l;  /* continue after `p' */\n  }\n  luaL_addstring(&b, s);  /* push last suffix */\n  luaL_pushresult(&b);\n  return lua_tostring(L, -1);\n}\n\n\nLUALIB_API const char *luaL_findtable (lua_State *L, int idx,\n                                       const char *fname, int szhint) {\n  const char *e;\n  lua_pushvalue(L, idx);\n  do {\n    e = strchr(fname, '.');\n    if (e == NULL) e = fname + strlen(fname);\n    lua_pushlstring(L, fname, e - fname);\n    lua_rawget(L, -2);\n    if (lua_isnil(L, -1)) {  /* no such field? */\n      lua_pop(L, 1);  /* remove this nil */\n      lua_createtable(L, 0, (*e == '.' ? 1 : szhint)); /* new table for field */\n      lua_pushlstring(L, fname, e - fname);\n      lua_pushvalue(L, -2);\n      lua_settable(L, -4);  /* set new table into field */\n    }\n    else if (!lua_istable(L, -1)) {  /* field has a non-table value? */\n      lua_pop(L, 2);  /* remove table and value */\n      return fname;  /* return problematic part of the name */\n    }\n    lua_remove(L, -2);  /* remove previous table */\n    fname = e + 1;\n  } while (*e == '.');\n  return NULL;\n}\n\n\n\n/*\n** {======================================================\n** Generic Buffer manipulation\n** =======================================================\n*/\n\n\n#define bufflen(B)\t((B)->p - (B)->buffer)\n#define bufffree(B)\t((size_t)(LUAL_BUFFERSIZE - bufflen(B)))\n\n#define LIMIT\t(LUA_MINSTACK/2)\n\n\nstatic int emptybuffer (luaL_Buffer *B) {\n  size_t l = bufflen(B);\n  if (l == 0) return 0;  /* put nothing on stack */\n  else {\n    lua_pushlstring(B->L, B->buffer, l);\n    B->p = B->buffer;\n    B->lvl++;\n    return 1;\n  }\n}\n\n\nstatic void adjuststack (luaL_Buffer *B) {\n  if (B->lvl > 1) {\n    lua_State *L = B->L;\n    int toget = 1;  /* number of levels to concat */\n    size_t toplen = lua_strlen(L, -1);\n    do {\n      size_t l = lua_strlen(L, -(toget+1));\n      if (B->lvl - toget + 1 >= LIMIT || toplen > l) {\n        toplen += l;\n        toget++;\n      }\n      else break;\n    } while (toget < B->lvl);\n    lua_concat(L, toget);\n    B->lvl = B->lvl - toget + 1;\n  }\n}\n\n\nLUALIB_API char *luaL_prepbuffer (luaL_Buffer *B) {\n  if (emptybuffer(B))\n    adjuststack(B);\n  return B->buffer;\n}\n\n\nLUALIB_API void luaL_addlstring (luaL_Buffer *B, const char *s, size_t l) {\n  while (l--)\n    luaL_addchar(B, *s++);\n}\n\n\nLUALIB_API void luaL_addstring (luaL_Buffer *B, const char *s) {\n  luaL_addlstring(B, s, strlen(s));\n}\n\n\nLUALIB_API void luaL_pushresult (luaL_Buffer *B) {\n  emptybuffer(B);\n  lua_concat(B->L, B->lvl);\n  B->lvl = 1;\n}\n\n\nLUALIB_API void luaL_addvalue (luaL_Buffer *B) {\n  lua_State *L = B->L;\n  size_t vl;\n  const char *s = lua_tolstring(L, -1, &vl);\n  if (vl <= bufffree(B)) {  /* fit into buffer? */\n    memcpy(B->p, s, vl);  /* put it there */\n    B->p += vl;\n    lua_pop(L, 1);  /* remove from stack */\n  }\n  else {\n    if (emptybuffer(B))\n      lua_insert(L, -2);  /* put buffer before new value */\n    B->lvl++;  /* add new value into B stack */\n    adjuststack(B);\n  }\n}\n\n\nLUALIB_API void luaL_buffinit (lua_State *L, luaL_Buffer *B) {\n  B->L = L;\n  B->p = B->buffer;\n  B->lvl = 0;\n}\n\n/* }====================================================== */\n\n\nLUALIB_API int luaL_ref (lua_State *L, int t) {\n  int ref;\n  t = abs_index(L, t);\n  if (lua_isnil(L, -1)) {\n    lua_pop(L, 1);  /* remove from stack */\n    return LUA_REFNIL;  /* `nil' has a unique fixed reference */\n  }\n  lua_rawgeti(L, t, FREELIST_REF);  /* get first free element */\n  ref = (int)lua_tointeger(L, -1);  /* ref = t[FREELIST_REF] */\n  lua_pop(L, 1);  /* remove it from stack */\n  if (ref != 0) {  /* any free element? */\n    lua_rawgeti(L, t, ref);  /* remove it from list */\n    lua_rawseti(L, t, FREELIST_REF);  /* (t[FREELIST_REF] = t[ref]) */\n  }\n  else {  /* no free elements */\n    ref = (int)lua_objlen(L, t);\n    ref++;  /* create new reference */\n  }\n  lua_rawseti(L, t, ref);\n  return ref;\n}\n\n\nLUALIB_API void luaL_unref (lua_State *L, int t, int ref) {\n  if (ref >= 0) {\n    t = abs_index(L, t);\n    lua_rawgeti(L, t, FREELIST_REF);\n    lua_rawseti(L, t, ref);  /* t[ref] = t[FREELIST_REF] */\n    lua_pushinteger(L, ref);\n    lua_rawseti(L, t, FREELIST_REF);  /* t[FREELIST_REF] = ref */\n  }\n}\n\n\n\n/*\n** {======================================================\n** Load functions\n** =======================================================\n*/\n\ntypedef struct LoadF {\n  int extraline;\n  FILE *f;\n  char buff[LUAL_BUFFERSIZE];\n} LoadF;\n\n\nstatic const char *getF (lua_State *L, void *ud, size_t *size) {\n  LoadF *lf = (LoadF *)ud;\n  (void)L;\n  if (lf->extraline) {\n    lf->extraline = 0;\n    *size = 1;\n    return \"\\n\";\n  }\n  if (feof(lf->f)) return NULL;\n  *size = fread(lf->buff, 1, sizeof(lf->buff), lf->f);\n  return (*size > 0) ? lf->buff : NULL;\n}\n\n\nstatic int errfile (lua_State *L, const char *what, int fnameindex) {\n  const char *serr = strerror(errno);\n  const char *filename = lua_tostring(L, fnameindex) + 1;\n  lua_pushfstring(L, \"cannot %s %s: %s\", what, filename, serr);\n  lua_remove(L, fnameindex);\n  return LUA_ERRFILE;\n}\n\n\nLUALIB_API int luaL_loadfile (lua_State *L, const char *filename) {\n  LoadF lf;\n  int status, readstatus;\n  int c;\n  int fnameindex = lua_gettop(L) + 1;  /* index of filename on the stack */\n  lf.extraline = 0;\n  if (filename == NULL) {\n    lua_pushliteral(L, \"=stdin\");\n    lf.f = stdin;\n  }\n  else {\n    lua_pushfstring(L, \"@%s\", filename);\n    lf.f = fopen(filename, \"r\");\n    if (lf.f == NULL) return errfile(L, \"open\", fnameindex);\n  }\n  c = getc(lf.f);\n  if (c == '#') {  /* Unix exec. file? */\n    lf.extraline = 1;\n    while ((c = getc(lf.f)) != EOF && c != '\\n') ;  /* skip first line */\n    if (c == '\\n') c = getc(lf.f);\n  }\n  if (c == LUA_SIGNATURE[0] && filename) {  /* binary file? */\n    lf.f = freopen(filename, \"rb\", lf.f);  /* reopen in binary mode */\n    if (lf.f == NULL) return errfile(L, \"reopen\", fnameindex);\n    /* skip eventual `#!...' */\n   while ((c = getc(lf.f)) != EOF && c != LUA_SIGNATURE[0]) ;\n    lf.extraline = 0;\n  }\n  ungetc(c, lf.f);\n  status = lua_load(L, getF, &lf, lua_tostring(L, -1));\n  readstatus = ferror(lf.f);\n  if (filename) fclose(lf.f);  /* close file (even in case of errors) */\n  if (readstatus) {\n    lua_settop(L, fnameindex);  /* ignore results from `lua_load' */\n    return errfile(L, \"read\", fnameindex);\n  }\n  lua_remove(L, fnameindex);\n  return status;\n}\n\n\ntypedef struct LoadS {\n  const char *s;\n  size_t size;\n} LoadS;\n\n\nstatic const char *getS (lua_State *L, void *ud, size_t *size) {\n  LoadS *ls = (LoadS *)ud;\n  (void)L;\n  if (ls->size == 0) return NULL;\n  *size = ls->size;\n  ls->size = 0;\n  return ls->s;\n}\n\n\nLUALIB_API int luaL_loadbuffer (lua_State *L, const char *buff, size_t size,\n                                const char *name) {\n  LoadS ls;\n  ls.s = buff;\n  ls.size = size;\n  return lua_load(L, getS, &ls, name);\n}\n\n\nLUALIB_API int (luaL_loadstring) (lua_State *L, const char *s) {\n  return luaL_loadbuffer(L, s, strlen(s), s);\n}\n\n\n\n/* }====================================================== */\n\n\nstatic void *l_alloc (void *ud, void *ptr, size_t osize, size_t nsize) {\n  (void)ud;\n  (void)osize;\n  if (nsize == 0) {\n    free(ptr);\n    return NULL;\n  }\n  else\n    return realloc(ptr, nsize);\n}\n\n\nstatic int panic (lua_State *L) {\n  (void)L;  /* to avoid warnings */\n  fprintf(stderr, \"PANIC: unprotected error in call to Lua API (%s)\\n\",\n                   lua_tostring(L, -1));\n  return 0;\n}\n\n\nLUALIB_API lua_State *luaL_newstate (void) {\n  lua_State *L = lua_newstate(l_alloc, NULL);\n  if (L) lua_atpanic(L, &panic);\n  return L;\n}\n\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/deps/lua/src/lauxlib.h",
    "content": "/*\n** $Id: lauxlib.h,v 1.88.1.1 2007/12/27 13:02:25 roberto Exp $\n** Auxiliary functions for building Lua libraries\n** See Copyright Notice in lua.h\n*/\n\n\n#ifndef lauxlib_h\n#define lauxlib_h\n\n\n#include <stddef.h>\n#include <stdio.h>\n\n#include \"lua.h\"\n\n\n#if defined(LUA_COMPAT_GETN)\nLUALIB_API int (luaL_getn) (lua_State *L, int t);\nLUALIB_API void (luaL_setn) (lua_State *L, int t, int n);\n#else\n#define luaL_getn(L,i)          ((int)lua_objlen(L, i))\n#define luaL_setn(L,i,j)        ((void)0)  /* no op! */\n#endif\n\n#if defined(LUA_COMPAT_OPENLIB)\n#define luaI_openlib\tluaL_openlib\n#endif\n\n\n/* extra error code for `luaL_load' */\n#define LUA_ERRFILE     (LUA_ERRERR+1)\n\n\ntypedef struct luaL_Reg {\n  const char *name;\n  lua_CFunction func;\n} luaL_Reg;\n\n\n\nLUALIB_API void (luaI_openlib) (lua_State *L, const char *libname,\n                                const luaL_Reg *l, int nup);\nLUALIB_API void (luaL_register) (lua_State *L, const char *libname,\n                                const luaL_Reg *l);\nLUALIB_API int (luaL_getmetafield) (lua_State *L, int obj, const char *e);\nLUALIB_API int (luaL_callmeta) (lua_State *L, int obj, const char *e);\nLUALIB_API int (luaL_typerror) (lua_State *L, int narg, const char *tname);\nLUALIB_API int (luaL_argerror) (lua_State *L, int numarg, const char *extramsg);\nLUALIB_API const char *(luaL_checklstring) (lua_State *L, int numArg,\n                                                          size_t *l);\nLUALIB_API const char *(luaL_optlstring) (lua_State *L, int numArg,\n                                          const char *def, size_t *l);\nLUALIB_API lua_Number (luaL_checknumber) (lua_State *L, int numArg);\nLUALIB_API lua_Number (luaL_optnumber) (lua_State *L, int nArg, lua_Number def);\n\nLUALIB_API lua_Integer (luaL_checkinteger) (lua_State *L, int numArg);\nLUALIB_API lua_Integer (luaL_optinteger) (lua_State *L, int nArg,\n                                          lua_Integer def);\n\nLUALIB_API void (luaL_checkstack) (lua_State *L, int sz, const char *msg);\nLUALIB_API void (luaL_checktype) (lua_State *L, int narg, int t);\nLUALIB_API void (luaL_checkany) (lua_State *L, int narg);\n\nLUALIB_API int   (luaL_newmetatable) (lua_State *L, const char *tname);\nLUALIB_API void *(luaL_checkudata) (lua_State *L, int ud, const char *tname);\n\nLUALIB_API void (luaL_where) (lua_State *L, int lvl);\nLUALIB_API int (luaL_error) (lua_State *L, const char *fmt, ...);\n\nLUALIB_API int (luaL_checkoption) (lua_State *L, int narg, const char *def,\n                                   const char *const lst[]);\n\nLUALIB_API int (luaL_ref) (lua_State *L, int t);\nLUALIB_API void (luaL_unref) (lua_State *L, int t, int ref);\n\nLUALIB_API int (luaL_loadfile) (lua_State *L, const char *filename);\nLUALIB_API int (luaL_loadbuffer) (lua_State *L, const char *buff, size_t sz,\n                                  const char *name);\nLUALIB_API int (luaL_loadstring) (lua_State *L, const char *s);\n\nLUALIB_API lua_State *(luaL_newstate) (void);\n\n\nLUALIB_API const char *(luaL_gsub) (lua_State *L, const char *s, const char *p,\n                                                  const char *r);\n\nLUALIB_API const char *(luaL_findtable) (lua_State *L, int idx,\n                                         const char *fname, int szhint);\n\n\n\n\n/*\n** ===============================================================\n** some useful macros\n** ===============================================================\n*/\n\n#define luaL_argcheck(L, cond,numarg,extramsg)\t\\\n\t\t((void)((cond) || luaL_argerror(L, (numarg), (extramsg))))\n#define luaL_checkstring(L,n)\t(luaL_checklstring(L, (n), NULL))\n#define luaL_optstring(L,n,d)\t(luaL_optlstring(L, (n), (d), NULL))\n#define luaL_checkint(L,n)\t((int)luaL_checkinteger(L, (n)))\n#define luaL_optint(L,n,d)\t((int)luaL_optinteger(L, (n), (d)))\n#define luaL_checklong(L,n)\t((long)luaL_checkinteger(L, (n)))\n#define luaL_optlong(L,n,d)\t((long)luaL_optinteger(L, (n), (d)))\n\n#define luaL_typename(L,i)\tlua_typename(L, lua_type(L,(i)))\n\n#define luaL_dofile(L, fn) \\\n\t(luaL_loadfile(L, fn) || lua_pcall(L, 0, LUA_MULTRET, 0))\n\n#define luaL_dostring(L, s) \\\n\t(luaL_loadstring(L, s) || lua_pcall(L, 0, LUA_MULTRET, 0))\n\n#define luaL_getmetatable(L,n)\t(lua_getfield(L, LUA_REGISTRYINDEX, (n)))\n\n#define luaL_opt(L,f,n,d)\t(lua_isnoneornil(L,(n)) ? (d) : f(L,(n)))\n\n/*\n** {======================================================\n** Generic Buffer manipulation\n** =======================================================\n*/\n\n\n\ntypedef struct luaL_Buffer {\n  char *p;\t\t\t/* current position in buffer */\n  int lvl;  /* number of strings in the stack (level) */\n  lua_State *L;\n  char buffer[LUAL_BUFFERSIZE];\n} luaL_Buffer;\n\n#define luaL_addchar(B,c) \\\n  ((void)((B)->p < ((B)->buffer+LUAL_BUFFERSIZE) || luaL_prepbuffer(B)), \\\n   (*(B)->p++ = (char)(c)))\n\n/* compatibility only */\n#define luaL_putchar(B,c)\tluaL_addchar(B,c)\n\n#define luaL_addsize(B,n)\t((B)->p += (n))\n\nLUALIB_API void (luaL_buffinit) (lua_State *L, luaL_Buffer *B);\nLUALIB_API char *(luaL_prepbuffer) (luaL_Buffer *B);\nLUALIB_API void (luaL_addlstring) (luaL_Buffer *B, const char *s, size_t l);\nLUALIB_API void (luaL_addstring) (luaL_Buffer *B, const char *s);\nLUALIB_API void (luaL_addvalue) (luaL_Buffer *B);\nLUALIB_API void (luaL_pushresult) (luaL_Buffer *B);\n\n\n/* }====================================================== */\n\n\n/* compatibility with ref system */\n\n/* pre-defined references */\n#define LUA_NOREF       (-2)\n#define LUA_REFNIL      (-1)\n\n#define lua_ref(L,lock) ((lock) ? luaL_ref(L, LUA_REGISTRYINDEX) : \\\n      (lua_pushstring(L, \"unlocked references are obsolete\"), lua_error(L), 0))\n\n#define lua_unref(L,ref)        luaL_unref(L, LUA_REGISTRYINDEX, (ref))\n\n#define lua_getref(L,ref)       lua_rawgeti(L, LUA_REGISTRYINDEX, (ref))\n\n\n#define luaL_reg\tluaL_Reg\n\n#endif\n\n\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/deps/lua/src/lbaselib.c",
    "content": "/*\n** $Id: lbaselib.c,v 1.191.1.6 2008/02/14 16:46:22 roberto Exp $\n** Basic library\n** See Copyright Notice in lua.h\n*/\n\n\n\n#include <ctype.h>\n#include <stdio.h>\n#include <stdlib.h>\n#include <string.h>\n\n#define lbaselib_c\n#define LUA_LIB\n\n#include \"lua.h\"\n\n#include \"lauxlib.h\"\n#include \"lualib.h\"\n\n\n\n\n/*\n** If your system does not support `stdout', you can just remove this function.\n** If you need, you can define your own `print' function, following this\n** model but changing `fputs' to put the strings at a proper place\n** (a console window or a log file, for instance).\n*/\nstatic int luaB_print (lua_State *L) {\n  int n = lua_gettop(L);  /* number of arguments */\n  int i;\n  lua_getglobal(L, \"tostring\");\n  for (i=1; i<=n; i++) {\n    const char *s;\n    lua_pushvalue(L, -1);  /* function to be called */\n    lua_pushvalue(L, i);   /* value to print */\n    lua_call(L, 1, 1);\n    s = lua_tostring(L, -1);  /* get result */\n    if (s == NULL)\n      return luaL_error(L, LUA_QL(\"tostring\") \" must return a string to \"\n                           LUA_QL(\"print\"));\n    if (i>1) fputs(\"\\t\", stdout);\n    fputs(s, stdout);\n    lua_pop(L, 1);  /* pop result */\n  }\n  fputs(\"\\n\", stdout);\n  return 0;\n}\n\n\nstatic int luaB_tonumber (lua_State *L) {\n  int base = luaL_optint(L, 2, 10);\n  if (base == 10) {  /* standard conversion */\n    luaL_checkany(L, 1);\n    if (lua_isnumber(L, 1)) {\n      lua_pushnumber(L, lua_tonumber(L, 1));\n      return 1;\n    }\n  }\n  else {\n    const char *s1 = luaL_checkstring(L, 1);\n    char *s2;\n    unsigned long n;\n    luaL_argcheck(L, 2 <= base && base <= 36, 2, \"base out of range\");\n    n = strtoul(s1, &s2, base);\n    if (s1 != s2) {  /* at least one valid digit? */\n      while (isspace((unsigned char)(*s2))) s2++;  /* skip trailing spaces */\n      if (*s2 == '\\0') {  /* no invalid trailing characters? */\n        lua_pushnumber(L, (lua_Number)n);\n        return 1;\n      }\n    }\n  }\n  lua_pushnil(L);  /* else not a number */\n  return 1;\n}\n\n\nstatic int luaB_error (lua_State *L) {\n  int level = luaL_optint(L, 2, 1);\n  lua_settop(L, 1);\n  if (lua_isstring(L, 1) && level > 0) {  /* add extra information? */\n    luaL_where(L, level);\n    lua_pushvalue(L, 1);\n    lua_concat(L, 2);\n  }\n  return lua_error(L);\n}\n\n\nstatic int luaB_getmetatable (lua_State *L) {\n  luaL_checkany(L, 1);\n  if (!lua_getmetatable(L, 1)) {\n    lua_pushnil(L);\n    return 1;  /* no metatable */\n  }\n  luaL_getmetafield(L, 1, \"__metatable\");\n  return 1;  /* returns either __metatable field (if present) or metatable */\n}\n\n\nstatic int luaB_setmetatable (lua_State *L) {\n  int t = lua_type(L, 2);\n  luaL_checktype(L, 1, LUA_TTABLE);\n  luaL_argcheck(L, t == LUA_TNIL || t == LUA_TTABLE, 2,\n                    \"nil or table expected\");\n  if (luaL_getmetafield(L, 1, \"__metatable\"))\n    luaL_error(L, \"cannot change a protected metatable\");\n  lua_settop(L, 2);\n  lua_setmetatable(L, 1);\n  return 1;\n}\n\n\nstatic void getfunc (lua_State *L, int opt) {\n  if (lua_isfunction(L, 1)) lua_pushvalue(L, 1);\n  else {\n    lua_Debug ar;\n    int level = opt ? luaL_optint(L, 1, 1) : luaL_checkint(L, 1);\n    luaL_argcheck(L, level >= 0, 1, \"level must be non-negative\");\n    if (lua_getstack(L, level, &ar) == 0)\n      luaL_argerror(L, 1, \"invalid level\");\n    lua_getinfo(L, \"f\", &ar);\n    if (lua_isnil(L, -1))\n      luaL_error(L, \"no function environment for tail call at level %d\",\n                    level);\n  }\n}\n\n\nstatic int luaB_getfenv (lua_State *L) {\n  getfunc(L, 1);\n  if (lua_iscfunction(L, -1))  /* is a C function? */\n    lua_pushvalue(L, LUA_GLOBALSINDEX);  /* return the thread's global env. */\n  else\n    lua_getfenv(L, -1);\n  return 1;\n}\n\n\nstatic int luaB_setfenv (lua_State *L) {\n  luaL_checktype(L, 2, LUA_TTABLE);\n  getfunc(L, 0);\n  lua_pushvalue(L, 2);\n  if (lua_isnumber(L, 1) && lua_tonumber(L, 1) == 0) {\n    /* change environment of current thread */\n    lua_pushthread(L);\n    lua_insert(L, -2);\n    lua_setfenv(L, -2);\n    return 0;\n  }\n  else if (lua_iscfunction(L, -2) || lua_setfenv(L, -2) == 0)\n    luaL_error(L,\n          LUA_QL(\"setfenv\") \" cannot change environment of given object\");\n  return 1;\n}\n\n\nstatic int luaB_rawequal (lua_State *L) {\n  luaL_checkany(L, 1);\n  luaL_checkany(L, 2);\n  lua_pushboolean(L, lua_rawequal(L, 1, 2));\n  return 1;\n}\n\n\nstatic int luaB_rawget (lua_State *L) {\n  luaL_checktype(L, 1, LUA_TTABLE);\n  luaL_checkany(L, 2);\n  lua_settop(L, 2);\n  lua_rawget(L, 1);\n  return 1;\n}\n\nstatic int luaB_rawset (lua_State *L) {\n  luaL_checktype(L, 1, LUA_TTABLE);\n  luaL_checkany(L, 2);\n  luaL_checkany(L, 3);\n  lua_settop(L, 3);\n  lua_rawset(L, 1);\n  return 1;\n}\n\n\nstatic int luaB_gcinfo (lua_State *L) {\n  lua_pushinteger(L, lua_getgccount(L));\n  return 1;\n}\n\n\nstatic int luaB_collectgarbage (lua_State *L) {\n  static const char *const opts[] = {\"stop\", \"restart\", \"collect\",\n    \"count\", \"step\", \"setpause\", \"setstepmul\", NULL};\n  static const int optsnum[] = {LUA_GCSTOP, LUA_GCRESTART, LUA_GCCOLLECT,\n    LUA_GCCOUNT, LUA_GCSTEP, LUA_GCSETPAUSE, LUA_GCSETSTEPMUL};\n  int o = luaL_checkoption(L, 1, \"collect\", opts);\n  int ex = luaL_optint(L, 2, 0);\n  int res = lua_gc(L, optsnum[o], ex);\n  switch (optsnum[o]) {\n    case LUA_GCCOUNT: {\n      int b = lua_gc(L, LUA_GCCOUNTB, 0);\n      lua_pushnumber(L, res + ((lua_Number)b/1024));\n      return 1;\n    }\n    case LUA_GCSTEP: {\n      lua_pushboolean(L, res);\n      return 1;\n    }\n    default: {\n      lua_pushnumber(L, res);\n      return 1;\n    }\n  }\n}\n\n\nstatic int luaB_type (lua_State *L) {\n  luaL_checkany(L, 1);\n  lua_pushstring(L, luaL_typename(L, 1));\n  return 1;\n}\n\n\nstatic int luaB_next (lua_State *L) {\n  luaL_checktype(L, 1, LUA_TTABLE);\n  lua_settop(L, 2);  /* create a 2nd argument if there isn't one */\n  if (lua_next(L, 1))\n    return 2;\n  else {\n    lua_pushnil(L);\n    return 1;\n  }\n}\n\n\nstatic int luaB_pairs (lua_State *L) {\n  luaL_checktype(L, 1, LUA_TTABLE);\n  lua_pushvalue(L, lua_upvalueindex(1));  /* return generator, */\n  lua_pushvalue(L, 1);  /* state, */\n  lua_pushnil(L);  /* and initial value */\n  return 3;\n}\n\n\nstatic int ipairsaux (lua_State *L) {\n  int i = luaL_checkint(L, 2);\n  luaL_checktype(L, 1, LUA_TTABLE);\n  i++;  /* next value */\n  lua_pushinteger(L, i);\n  lua_rawgeti(L, 1, i);\n  return (lua_isnil(L, -1)) ? 0 : 2;\n}\n\n\nstatic int luaB_ipairs (lua_State *L) {\n  luaL_checktype(L, 1, LUA_TTABLE);\n  lua_pushvalue(L, lua_upvalueindex(1));  /* return generator, */\n  lua_pushvalue(L, 1);  /* state, */\n  lua_pushinteger(L, 0);  /* and initial value */\n  return 3;\n}\n\n\nstatic int load_aux (lua_State *L, int status) {\n  if (status == 0)  /* OK? */\n    return 1;\n  else {\n    lua_pushnil(L);\n    lua_insert(L, -2);  /* put before error message */\n    return 2;  /* return nil plus error message */\n  }\n}\n\n\nstatic int luaB_loadstring (lua_State *L) {\n  size_t l;\n  const char *s = luaL_checklstring(L, 1, &l);\n  const char *chunkname = luaL_optstring(L, 2, s);\n  return load_aux(L, luaL_loadbuffer(L, s, l, chunkname));\n}\n\n\nstatic int luaB_loadfile (lua_State *L) {\n  const char *fname = luaL_optstring(L, 1, NULL);\n  return load_aux(L, luaL_loadfile(L, fname));\n}\n\n\n/*\n** Reader for generic `load' function: `lua_load' uses the\n** stack for internal stuff, so the reader cannot change the\n** stack top. Instead, it keeps its resulting string in a\n** reserved slot inside the stack.\n*/\nstatic const char *generic_reader (lua_State *L, void *ud, size_t *size) {\n  (void)ud;  /* to avoid warnings */\n  luaL_checkstack(L, 2, \"too many nested functions\");\n  lua_pushvalue(L, 1);  /* get function */\n  lua_call(L, 0, 1);  /* call it */\n  if (lua_isnil(L, -1)) {\n    *size = 0;\n    return NULL;\n  }\n  else if (lua_isstring(L, -1)) {\n    lua_replace(L, 3);  /* save string in a reserved stack slot */\n    return lua_tolstring(L, 3, size);\n  }\n  else luaL_error(L, \"reader function must return a string\");\n  return NULL;  /* to avoid warnings */\n}\n\n\nstatic int luaB_load (lua_State *L) {\n  int status;\n  const char *cname = luaL_optstring(L, 2, \"=(load)\");\n  luaL_checktype(L, 1, LUA_TFUNCTION);\n  lua_settop(L, 3);  /* function, eventual name, plus one reserved slot */\n  status = lua_load(L, generic_reader, NULL, cname);\n  return load_aux(L, status);\n}\n\n\nstatic int luaB_dofile (lua_State *L) {\n  const char *fname = luaL_optstring(L, 1, NULL);\n  int n = lua_gettop(L);\n  if (luaL_loadfile(L, fname) != 0) lua_error(L);\n  lua_call(L, 0, LUA_MULTRET);\n  return lua_gettop(L) - n;\n}\n\n\nstatic int luaB_assert (lua_State *L) {\n  luaL_checkany(L, 1);\n  if (!lua_toboolean(L, 1))\n    return luaL_error(L, \"%s\", luaL_optstring(L, 2, \"assertion failed!\"));\n  return lua_gettop(L);\n}\n\n\nstatic int luaB_unpack (lua_State *L) {\n  int i, e, n;\n  luaL_checktype(L, 1, LUA_TTABLE);\n  i = luaL_optint(L, 2, 1);\n  e = luaL_opt(L, luaL_checkint, 3, luaL_getn(L, 1));\n  if (i > e) return 0;  /* empty range */\n  n = e - i + 1;  /* number of elements */\n  if (n <= 0 || !lua_checkstack(L, n))  /* n <= 0 means arith. overflow */\n    return luaL_error(L, \"too many results to unpack\");\n  lua_rawgeti(L, 1, i);  /* push arg[i] (avoiding overflow problems) */\n  while (i++ < e)  /* push arg[i + 1...e] */\n    lua_rawgeti(L, 1, i);\n  return n;\n}\n\n\nstatic int luaB_select (lua_State *L) {\n  int n = lua_gettop(L);\n  if (lua_type(L, 1) == LUA_TSTRING && *lua_tostring(L, 1) == '#') {\n    lua_pushinteger(L, n-1);\n    return 1;\n  }\n  else {\n    int i = luaL_checkint(L, 1);\n    if (i < 0) i = n + i;\n    else if (i > n) i = n;\n    luaL_argcheck(L, 1 <= i, 1, \"index out of range\");\n    return n - i;\n  }\n}\n\n\nstatic int luaB_pcall (lua_State *L) {\n  int status;\n  luaL_checkany(L, 1);\n  status = lua_pcall(L, lua_gettop(L) - 1, LUA_MULTRET, 0);\n  lua_pushboolean(L, (status == 0));\n  lua_insert(L, 1);\n  return lua_gettop(L);  /* return status + all results */\n}\n\n\nstatic int luaB_xpcall (lua_State *L) {\n  int status;\n  luaL_checkany(L, 2);\n  lua_settop(L, 2);\n  lua_insert(L, 1);  /* put error function under function to be called */\n  status = lua_pcall(L, 0, LUA_MULTRET, 1);\n  lua_pushboolean(L, (status == 0));\n  lua_replace(L, 1);\n  return lua_gettop(L);  /* return status + all results */\n}\n\n\nstatic int luaB_tostring (lua_State *L) {\n  luaL_checkany(L, 1);\n  if (luaL_callmeta(L, 1, \"__tostring\"))  /* is there a metafield? */\n    return 1;  /* use its value */\n  switch (lua_type(L, 1)) {\n    case LUA_TNUMBER:\n      lua_pushstring(L, lua_tostring(L, 1));\n      break;\n    case LUA_TSTRING:\n      lua_pushvalue(L, 1);\n      break;\n    case LUA_TBOOLEAN:\n      lua_pushstring(L, (lua_toboolean(L, 1) ? \"true\" : \"false\"));\n      break;\n    case LUA_TNIL:\n      lua_pushliteral(L, \"nil\");\n      break;\n    default:\n      lua_pushfstring(L, \"%s: %p\", luaL_typename(L, 1), lua_topointer(L, 1));\n      break;\n  }\n  return 1;\n}\n\n\nstatic int luaB_newproxy (lua_State *L) {\n  lua_settop(L, 1);\n  lua_newuserdata(L, 0);  /* create proxy */\n  if (lua_toboolean(L, 1) == 0)\n    return 1;  /* no metatable */\n  else if (lua_isboolean(L, 1)) {\n    lua_newtable(L);  /* create a new metatable `m' ... */\n    lua_pushvalue(L, -1);  /* ... and mark `m' as a valid metatable */\n    lua_pushboolean(L, 1);\n    lua_rawset(L, lua_upvalueindex(1));  /* weaktable[m] = true */\n  }\n  else {\n    int validproxy = 0;  /* to check if weaktable[metatable(u)] == true */\n    if (lua_getmetatable(L, 1)) {\n      lua_rawget(L, lua_upvalueindex(1));\n      validproxy = lua_toboolean(L, -1);\n      lua_pop(L, 1);  /* remove value */\n    }\n    luaL_argcheck(L, validproxy, 1, \"boolean or proxy expected\");\n    lua_getmetatable(L, 1);  /* metatable is valid; get it */\n  }\n  lua_setmetatable(L, 2);\n  return 1;\n}\n\n\nstatic const luaL_Reg base_funcs[] = {\n  {\"assert\", luaB_assert},\n  {\"collectgarbage\", luaB_collectgarbage},\n  {\"dofile\", luaB_dofile},\n  {\"error\", luaB_error},\n  {\"gcinfo\", luaB_gcinfo},\n  {\"getfenv\", luaB_getfenv},\n  {\"getmetatable\", luaB_getmetatable},\n  {\"loadfile\", luaB_loadfile},\n  {\"load\", luaB_load},\n  {\"loadstring\", luaB_loadstring},\n  {\"next\", luaB_next},\n  {\"pcall\", luaB_pcall},\n  {\"print\", luaB_print},\n  {\"rawequal\", luaB_rawequal},\n  {\"rawget\", luaB_rawget},\n  {\"rawset\", luaB_rawset},\n  {\"select\", luaB_select},\n  {\"setfenv\", luaB_setfenv},\n  {\"setmetatable\", luaB_setmetatable},\n  {\"tonumber\", luaB_tonumber},\n  {\"tostring\", luaB_tostring},\n  {\"type\", luaB_type},\n  {\"unpack\", luaB_unpack},\n  {\"xpcall\", luaB_xpcall},\n  {NULL, NULL}\n};\n\n\n/*\n** {======================================================\n** Coroutine library\n** =======================================================\n*/\n\n#define CO_RUN\t0\t/* running */\n#define CO_SUS\t1\t/* suspended */\n#define CO_NOR\t2\t/* 'normal' (it resumed another coroutine) */\n#define CO_DEAD\t3\n\nstatic const char *const statnames[] =\n    {\"running\", \"suspended\", \"normal\", \"dead\"};\n\nstatic int costatus (lua_State *L, lua_State *co) {\n  if (L == co) return CO_RUN;\n  switch (lua_status(co)) {\n    case LUA_YIELD:\n      return CO_SUS;\n    case 0: {\n      lua_Debug ar;\n      if (lua_getstack(co, 0, &ar) > 0)  /* does it have frames? */\n        return CO_NOR;  /* it is running */\n      else if (lua_gettop(co) == 0)\n          return CO_DEAD;\n      else\n        return CO_SUS;  /* initial state */\n    }\n    default:  /* some error occured */\n      return CO_DEAD;\n  }\n}\n\n\nstatic int luaB_costatus (lua_State *L) {\n  lua_State *co = lua_tothread(L, 1);\n  luaL_argcheck(L, co, 1, \"coroutine expected\");\n  lua_pushstring(L, statnames[costatus(L, co)]);\n  return 1;\n}\n\n\nstatic int auxresume (lua_State *L, lua_State *co, int narg) {\n  int status = costatus(L, co);\n  if (!lua_checkstack(co, narg))\n    luaL_error(L, \"too many arguments to resume\");\n  if (status != CO_SUS) {\n    lua_pushfstring(L, \"cannot resume %s coroutine\", statnames[status]);\n    return -1;  /* error flag */\n  }\n  lua_xmove(L, co, narg);\n  lua_setlevel(L, co);\n  status = lua_resume(co, narg);\n  if (status == 0 || status == LUA_YIELD) {\n    int nres = lua_gettop(co);\n    if (!lua_checkstack(L, nres + 1))\n      luaL_error(L, \"too many results to resume\");\n    lua_xmove(co, L, nres);  /* move yielded values */\n    return nres;\n  }\n  else {\n    lua_xmove(co, L, 1);  /* move error message */\n    return -1;  /* error flag */\n  }\n}\n\n\nstatic int luaB_coresume (lua_State *L) {\n  lua_State *co = lua_tothread(L, 1);\n  int r;\n  luaL_argcheck(L, co, 1, \"coroutine expected\");\n  r = auxresume(L, co, lua_gettop(L) - 1);\n  if (r < 0) {\n    lua_pushboolean(L, 0);\n    lua_insert(L, -2);\n    return 2;  /* return false + error message */\n  }\n  else {\n    lua_pushboolean(L, 1);\n    lua_insert(L, -(r + 1));\n    return r + 1;  /* return true + `resume' returns */\n  }\n}\n\n\nstatic int luaB_auxwrap (lua_State *L) {\n  lua_State *co = lua_tothread(L, lua_upvalueindex(1));\n  int r = auxresume(L, co, lua_gettop(L));\n  if (r < 0) {\n    if (lua_isstring(L, -1)) {  /* error object is a string? */\n      luaL_where(L, 1);  /* add extra info */\n      lua_insert(L, -2);\n      lua_concat(L, 2);\n    }\n    lua_error(L);  /* propagate error */\n  }\n  return r;\n}\n\n\nstatic int luaB_cocreate (lua_State *L) {\n  lua_State *NL = lua_newthread(L);\n  luaL_argcheck(L, lua_isfunction(L, 1) && !lua_iscfunction(L, 1), 1,\n    \"Lua function expected\");\n  lua_pushvalue(L, 1);  /* move function to top */\n  lua_xmove(L, NL, 1);  /* move function from L to NL */\n  return 1;\n}\n\n\nstatic int luaB_cowrap (lua_State *L) {\n  luaB_cocreate(L);\n  lua_pushcclosure(L, luaB_auxwrap, 1);\n  return 1;\n}\n\n\nstatic int luaB_yield (lua_State *L) {\n  return lua_yield(L, lua_gettop(L));\n}\n\n\nstatic int luaB_corunning (lua_State *L) {\n  if (lua_pushthread(L))\n    lua_pushnil(L);  /* main thread is not a coroutine */\n  return 1;\n}\n\n\nstatic const luaL_Reg co_funcs[] = {\n  {\"create\", luaB_cocreate},\n  {\"resume\", luaB_coresume},\n  {\"running\", luaB_corunning},\n  {\"status\", luaB_costatus},\n  {\"wrap\", luaB_cowrap},\n  {\"yield\", luaB_yield},\n  {NULL, NULL}\n};\n\n/* }====================================================== */\n\n\nstatic void auxopen (lua_State *L, const char *name,\n                     lua_CFunction f, lua_CFunction u) {\n  lua_pushcfunction(L, u);\n  lua_pushcclosure(L, f, 1);\n  lua_setfield(L, -2, name);\n}\n\n\nstatic void base_open (lua_State *L) {\n  /* set global _G */\n  lua_pushvalue(L, LUA_GLOBALSINDEX);\n  lua_setglobal(L, \"_G\");\n  /* open lib into global table */\n  luaL_register(L, \"_G\", base_funcs);\n  lua_pushliteral(L, LUA_VERSION);\n  lua_setglobal(L, \"_VERSION\");  /* set global _VERSION */\n  /* `ipairs' and `pairs' need auxiliary functions as upvalues */\n  auxopen(L, \"ipairs\", luaB_ipairs, ipairsaux);\n  auxopen(L, \"pairs\", luaB_pairs, luaB_next);\n  /* `newproxy' needs a weaktable as upvalue */\n  lua_createtable(L, 0, 1);  /* new table `w' */\n  lua_pushvalue(L, -1);  /* `w' will be its own metatable */\n  lua_setmetatable(L, -2);\n  lua_pushliteral(L, \"kv\");\n  lua_setfield(L, -2, \"__mode\");  /* metatable(w).__mode = \"kv\" */\n  lua_pushcclosure(L, luaB_newproxy, 1);\n  lua_setglobal(L, \"newproxy\");  /* set global `newproxy' */\n}\n\n\nLUALIB_API int luaopen_base (lua_State *L) {\n  base_open(L);\n  luaL_register(L, LUA_COLIBNAME, co_funcs);\n  return 2;\n}\n\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/deps/lua/src/lcode.c",
    "content": "/*\n** $Id: lcode.c,v 2.25.1.5 2011/01/31 14:53:16 roberto Exp $\n** Code generator for Lua\n** See Copyright Notice in lua.h\n*/\n\n\n#include <stdlib.h>\n\n#define lcode_c\n#define LUA_CORE\n\n#include \"lua.h\"\n\n#include \"lcode.h\"\n#include \"ldebug.h\"\n#include \"ldo.h\"\n#include \"lgc.h\"\n#include \"llex.h\"\n#include \"lmem.h\"\n#include \"lobject.h\"\n#include \"lopcodes.h\"\n#include \"lparser.h\"\n#include \"ltable.h\"\n\n\n#define hasjumps(e)\t((e)->t != (e)->f)\n\n\nstatic int isnumeral(expdesc *e) {\n  return (e->k == VKNUM && e->t == NO_JUMP && e->f == NO_JUMP);\n}\n\n\nvoid luaK_nil (FuncState *fs, int from, int n) {\n  Instruction *previous;\n  if (fs->pc > fs->lasttarget) {  /* no jumps to current position? */\n    if (fs->pc == 0) {  /* function start? */\n      if (from >= fs->nactvar)\n        return;  /* positions are already clean */\n    }\n    else {\n      previous = &fs->f->code[fs->pc-1];\n      if (GET_OPCODE(*previous) == OP_LOADNIL) {\n        int pfrom = GETARG_A(*previous);\n        int pto = GETARG_B(*previous);\n        if (pfrom <= from && from <= pto+1) {  /* can connect both? */\n          if (from+n-1 > pto)\n            SETARG_B(*previous, from+n-1);\n          return;\n        }\n      }\n    }\n  }\n  luaK_codeABC(fs, OP_LOADNIL, from, from+n-1, 0);  /* else no optimization */\n}\n\n\nint luaK_jump (FuncState *fs) {\n  int jpc = fs->jpc;  /* save list of jumps to here */\n  int j;\n  fs->jpc = NO_JUMP;\n  j = luaK_codeAsBx(fs, OP_JMP, 0, NO_JUMP);\n  luaK_concat(fs, &j, jpc);  /* keep them on hold */\n  return j;\n}\n\n\nvoid luaK_ret (FuncState *fs, int first, int nret) {\n  luaK_codeABC(fs, OP_RETURN, first, nret+1, 0);\n}\n\n\nstatic int condjump (FuncState *fs, OpCode op, int A, int B, int C) {\n  luaK_codeABC(fs, op, A, B, C);\n  return luaK_jump(fs);\n}\n\n\nstatic void fixjump (FuncState *fs, int pc, int dest) {\n  Instruction *jmp = &fs->f->code[pc];\n  int offset = dest-(pc+1);\n  lua_assert(dest != NO_JUMP);\n  if (abs(offset) > MAXARG_sBx)\n    luaX_syntaxerror(fs->ls, \"control structure too long\");\n  SETARG_sBx(*jmp, offset);\n}\n\n\n/*\n** returns current `pc' and marks it as a jump target (to avoid wrong\n** optimizations with consecutive instructions not in the same basic block).\n*/\nint luaK_getlabel (FuncState *fs) {\n  fs->lasttarget = fs->pc;\n  return fs->pc;\n}\n\n\nstatic int getjump (FuncState *fs, int pc) {\n  int offset = GETARG_sBx(fs->f->code[pc]);\n  if (offset == NO_JUMP)  /* point to itself represents end of list */\n    return NO_JUMP;  /* end of list */\n  else\n    return (pc+1)+offset;  /* turn offset into absolute position */\n}\n\n\nstatic Instruction *getjumpcontrol (FuncState *fs, int pc) {\n  Instruction *pi = &fs->f->code[pc];\n  if (pc >= 1 && testTMode(GET_OPCODE(*(pi-1))))\n    return pi-1;\n  else\n    return pi;\n}\n\n\n/*\n** check whether list has any jump that do not produce a value\n** (or produce an inverted value)\n*/\nstatic int need_value (FuncState *fs, int list) {\n  for (; list != NO_JUMP; list = getjump(fs, list)) {\n    Instruction i = *getjumpcontrol(fs, list);\n    if (GET_OPCODE(i) != OP_TESTSET) return 1;\n  }\n  return 0;  /* not found */\n}\n\n\nstatic int patchtestreg (FuncState *fs, int node, int reg) {\n  Instruction *i = getjumpcontrol(fs, node);\n  if (GET_OPCODE(*i) != OP_TESTSET)\n    return 0;  /* cannot patch other instructions */\n  if (reg != NO_REG && reg != GETARG_B(*i))\n    SETARG_A(*i, reg);\n  else  /* no register to put value or register already has the value */\n    *i = CREATE_ABC(OP_TEST, GETARG_B(*i), 0, GETARG_C(*i));\n\n  return 1;\n}\n\n\nstatic void removevalues (FuncState *fs, int list) {\n  for (; list != NO_JUMP; list = getjump(fs, list))\n      patchtestreg(fs, list, NO_REG);\n}\n\n\nstatic void patchlistaux (FuncState *fs, int list, int vtarget, int reg,\n                          int dtarget) {\n  while (list != NO_JUMP) {\n    int next = getjump(fs, list);\n    if (patchtestreg(fs, list, reg))\n      fixjump(fs, list, vtarget);\n    else\n      fixjump(fs, list, dtarget);  /* jump to default target */\n    list = next;\n  }\n}\n\n\nstatic void dischargejpc (FuncState *fs) {\n  patchlistaux(fs, fs->jpc, fs->pc, NO_REG, fs->pc);\n  fs->jpc = NO_JUMP;\n}\n\n\nvoid luaK_patchlist (FuncState *fs, int list, int target) {\n  if (target == fs->pc)\n    luaK_patchtohere(fs, list);\n  else {\n    lua_assert(target < fs->pc);\n    patchlistaux(fs, list, target, NO_REG, target);\n  }\n}\n\n\nvoid luaK_patchtohere (FuncState *fs, int list) {\n  luaK_getlabel(fs);\n  luaK_concat(fs, &fs->jpc, list);\n}\n\n\nvoid luaK_concat (FuncState *fs, int *l1, int l2) {\n  if (l2 == NO_JUMP) return;\n  else if (*l1 == NO_JUMP)\n    *l1 = l2;\n  else {\n    int list = *l1;\n    int next;\n    while ((next = getjump(fs, list)) != NO_JUMP)  /* find last element */\n      list = next;\n    fixjump(fs, list, l2);\n  }\n}\n\n\nvoid luaK_checkstack (FuncState *fs, int n) {\n  int newstack = fs->freereg + n;\n  if (newstack > fs->f->maxstacksize) {\n    if (newstack >= MAXSTACK)\n      luaX_syntaxerror(fs->ls, \"function or expression too complex\");\n    fs->f->maxstacksize = cast_byte(newstack);\n  }\n}\n\n\nvoid luaK_reserveregs (FuncState *fs, int n) {\n  luaK_checkstack(fs, n);\n  fs->freereg += n;\n}\n\n\nstatic void freereg (FuncState *fs, int reg) {\n  if (!ISK(reg) && reg >= fs->nactvar) {\n    fs->freereg--;\n    lua_assert(reg == fs->freereg);\n  }\n}\n\n\nstatic void freeexp (FuncState *fs, expdesc *e) {\n  if (e->k == VNONRELOC)\n    freereg(fs, e->u.s.info);\n}\n\n\nstatic int addk (FuncState *fs, TValue *k, TValue *v) {\n  lua_State *L = fs->L;\n  TValue *idx = luaH_set(L, fs->h, k);\n  Proto *f = fs->f;\n  int oldsize = f->sizek;\n  if (ttisnumber(idx)) {\n    lua_assert(luaO_rawequalObj(&fs->f->k[cast_int(nvalue(idx))], v));\n    return cast_int(nvalue(idx));\n  }\n  else {  /* constant not found; create a new entry */\n    setnvalue(idx, cast_num(fs->nk));\n    luaM_growvector(L, f->k, fs->nk, f->sizek, TValue,\n                    MAXARG_Bx, \"constant table overflow\");\n    while (oldsize < f->sizek) setnilvalue(&f->k[oldsize++]);\n    setobj(L, &f->k[fs->nk], v);\n    luaC_barrier(L, f, v);\n    return fs->nk++;\n  }\n}\n\n\nint luaK_stringK (FuncState *fs, TString *s) {\n  TValue o;\n  setsvalue(fs->L, &o, s);\n  return addk(fs, &o, &o);\n}\n\n\nint luaK_numberK (FuncState *fs, lua_Number r) {\n  TValue o;\n  setnvalue(&o, r);\n  return addk(fs, &o, &o);\n}\n\n\nstatic int boolK (FuncState *fs, int b) {\n  TValue o;\n  setbvalue(&o, b);\n  return addk(fs, &o, &o);\n}\n\n\nstatic int nilK (FuncState *fs) {\n  TValue k, v;\n  setnilvalue(&v);\n  /* cannot use nil as key; instead use table itself to represent nil */\n  sethvalue(fs->L, &k, fs->h);\n  return addk(fs, &k, &v);\n}\n\n\nvoid luaK_setreturns (FuncState *fs, expdesc *e, int nresults) {\n  if (e->k == VCALL) {  /* expression is an open function call? */\n    SETARG_C(getcode(fs, e), nresults+1);\n  }\n  else if (e->k == VVARARG) {\n    SETARG_B(getcode(fs, e), nresults+1);\n    SETARG_A(getcode(fs, e), fs->freereg);\n    luaK_reserveregs(fs, 1);\n  }\n}\n\n\nvoid luaK_setoneret (FuncState *fs, expdesc *e) {\n  if (e->k == VCALL) {  /* expression is an open function call? */\n    e->k = VNONRELOC;\n    e->u.s.info = GETARG_A(getcode(fs, e));\n  }\n  else if (e->k == VVARARG) {\n    SETARG_B(getcode(fs, e), 2);\n    e->k = VRELOCABLE;  /* can relocate its simple result */\n  }\n}\n\n\nvoid luaK_dischargevars (FuncState *fs, expdesc *e) {\n  switch (e->k) {\n    case VLOCAL: {\n      e->k = VNONRELOC;\n      break;\n    }\n    case VUPVAL: {\n      e->u.s.info = luaK_codeABC(fs, OP_GETUPVAL, 0, e->u.s.info, 0);\n      e->k = VRELOCABLE;\n      break;\n    }\n    case VGLOBAL: {\n      e->u.s.info = luaK_codeABx(fs, OP_GETGLOBAL, 0, e->u.s.info);\n      e->k = VRELOCABLE;\n      break;\n    }\n    case VINDEXED: {\n      freereg(fs, e->u.s.aux);\n      freereg(fs, e->u.s.info);\n      e->u.s.info = luaK_codeABC(fs, OP_GETTABLE, 0, e->u.s.info, e->u.s.aux);\n      e->k = VRELOCABLE;\n      break;\n    }\n    case VVARARG:\n    case VCALL: {\n      luaK_setoneret(fs, e);\n      break;\n    }\n    default: break;  /* there is one value available (somewhere) */\n  }\n}\n\n\nstatic int code_label (FuncState *fs, int A, int b, int jump) {\n  luaK_getlabel(fs);  /* those instructions may be jump targets */\n  return luaK_codeABC(fs, OP_LOADBOOL, A, b, jump);\n}\n\n\nstatic void discharge2reg (FuncState *fs, expdesc *e, int reg) {\n  luaK_dischargevars(fs, e);\n  switch (e->k) {\n    case VNIL: {\n      luaK_nil(fs, reg, 1);\n      break;\n    }\n    case VFALSE:  case VTRUE: {\n      luaK_codeABC(fs, OP_LOADBOOL, reg, e->k == VTRUE, 0);\n      break;\n    }\n    case VK: {\n      luaK_codeABx(fs, OP_LOADK, reg, e->u.s.info);\n      break;\n    }\n    case VKNUM: {\n      luaK_codeABx(fs, OP_LOADK, reg, luaK_numberK(fs, e->u.nval));\n      break;\n    }\n    case VRELOCABLE: {\n      Instruction *pc = &getcode(fs, e);\n      SETARG_A(*pc, reg);\n      break;\n    }\n    case VNONRELOC: {\n      if (reg != e->u.s.info)\n        luaK_codeABC(fs, OP_MOVE, reg, e->u.s.info, 0);\n      break;\n    }\n    default: {\n      lua_assert(e->k == VVOID || e->k == VJMP);\n      return;  /* nothing to do... */\n    }\n  }\n  e->u.s.info = reg;\n  e->k = VNONRELOC;\n}\n\n\nstatic void discharge2anyreg (FuncState *fs, expdesc *e) {\n  if (e->k != VNONRELOC) {\n    luaK_reserveregs(fs, 1);\n    discharge2reg(fs, e, fs->freereg-1);\n  }\n}\n\n\nstatic void exp2reg (FuncState *fs, expdesc *e, int reg) {\n  discharge2reg(fs, e, reg);\n  if (e->k == VJMP)\n    luaK_concat(fs, &e->t, e->u.s.info);  /* put this jump in `t' list */\n  if (hasjumps(e)) {\n    int final;  /* position after whole expression */\n    int p_f = NO_JUMP;  /* position of an eventual LOAD false */\n    int p_t = NO_JUMP;  /* position of an eventual LOAD true */\n    if (need_value(fs, e->t) || need_value(fs, e->f)) {\n      int fj = (e->k == VJMP) ? NO_JUMP : luaK_jump(fs);\n      p_f = code_label(fs, reg, 0, 1);\n      p_t = code_label(fs, reg, 1, 0);\n      luaK_patchtohere(fs, fj);\n    }\n    final = luaK_getlabel(fs);\n    patchlistaux(fs, e->f, final, reg, p_f);\n    patchlistaux(fs, e->t, final, reg, p_t);\n  }\n  e->f = e->t = NO_JUMP;\n  e->u.s.info = reg;\n  e->k = VNONRELOC;\n}\n\n\nvoid luaK_exp2nextreg (FuncState *fs, expdesc *e) {\n  luaK_dischargevars(fs, e);\n  freeexp(fs, e);\n  luaK_reserveregs(fs, 1);\n  exp2reg(fs, e, fs->freereg - 1);\n}\n\n\nint luaK_exp2anyreg (FuncState *fs, expdesc *e) {\n  luaK_dischargevars(fs, e);\n  if (e->k == VNONRELOC) {\n    if (!hasjumps(e)) return e->u.s.info;  /* exp is already in a register */\n    if (e->u.s.info >= fs->nactvar) {  /* reg. is not a local? */\n      exp2reg(fs, e, e->u.s.info);  /* put value on it */\n      return e->u.s.info;\n    }\n  }\n  luaK_exp2nextreg(fs, e);  /* default */\n  return e->u.s.info;\n}\n\n\nvoid luaK_exp2val (FuncState *fs, expdesc *e) {\n  if (hasjumps(e))\n    luaK_exp2anyreg(fs, e);\n  else\n    luaK_dischargevars(fs, e);\n}\n\n\nint luaK_exp2RK (FuncState *fs, expdesc *e) {\n  luaK_exp2val(fs, e);\n  switch (e->k) {\n    case VKNUM:\n    case VTRUE:\n    case VFALSE:\n    case VNIL: {\n      if (fs->nk <= MAXINDEXRK) {  /* constant fit in RK operand? */\n        e->u.s.info = (e->k == VNIL)  ? nilK(fs) :\n                      (e->k == VKNUM) ? luaK_numberK(fs, e->u.nval) :\n                                        boolK(fs, (e->k == VTRUE));\n        e->k = VK;\n        return RKASK(e->u.s.info);\n      }\n      else break;\n    }\n    case VK: {\n      if (e->u.s.info <= MAXINDEXRK)  /* constant fit in argC? */\n        return RKASK(e->u.s.info);\n      else break;\n    }\n    default: break;\n  }\n  /* not a constant in the right range: put it in a register */\n  return luaK_exp2anyreg(fs, e);\n}\n\n\nvoid luaK_storevar (FuncState *fs, expdesc *var, expdesc *ex) {\n  switch (var->k) {\n    case VLOCAL: {\n      freeexp(fs, ex);\n      exp2reg(fs, ex, var->u.s.info);\n      return;\n    }\n    case VUPVAL: {\n      int e = luaK_exp2anyreg(fs, ex);\n      luaK_codeABC(fs, OP_SETUPVAL, e, var->u.s.info, 0);\n      break;\n    }\n    case VGLOBAL: {\n      int e = luaK_exp2anyreg(fs, ex);\n      luaK_codeABx(fs, OP_SETGLOBAL, e, var->u.s.info);\n      break;\n    }\n    case VINDEXED: {\n      int e = luaK_exp2RK(fs, ex);\n      luaK_codeABC(fs, OP_SETTABLE, var->u.s.info, var->u.s.aux, e);\n      break;\n    }\n    default: {\n      lua_assert(0);  /* invalid var kind to store */\n      break;\n    }\n  }\n  freeexp(fs, ex);\n}\n\n\nvoid luaK_self (FuncState *fs, expdesc *e, expdesc *key) {\n  int func;\n  luaK_exp2anyreg(fs, e);\n  freeexp(fs, e);\n  func = fs->freereg;\n  luaK_reserveregs(fs, 2);\n  luaK_codeABC(fs, OP_SELF, func, e->u.s.info, luaK_exp2RK(fs, key));\n  freeexp(fs, key);\n  e->u.s.info = func;\n  e->k = VNONRELOC;\n}\n\n\nstatic void invertjump (FuncState *fs, expdesc *e) {\n  Instruction *pc = getjumpcontrol(fs, e->u.s.info);\n  lua_assert(testTMode(GET_OPCODE(*pc)) && GET_OPCODE(*pc) != OP_TESTSET &&\n                                           GET_OPCODE(*pc) != OP_TEST);\n  SETARG_A(*pc, !(GETARG_A(*pc)));\n}\n\n\nstatic int jumponcond (FuncState *fs, expdesc *e, int cond) {\n  if (e->k == VRELOCABLE) {\n    Instruction ie = getcode(fs, e);\n    if (GET_OPCODE(ie) == OP_NOT) {\n      fs->pc--;  /* remove previous OP_NOT */\n      return condjump(fs, OP_TEST, GETARG_B(ie), 0, !cond);\n    }\n    /* else go through */\n  }\n  discharge2anyreg(fs, e);\n  freeexp(fs, e);\n  return condjump(fs, OP_TESTSET, NO_REG, e->u.s.info, cond);\n}\n\n\nvoid luaK_goiftrue (FuncState *fs, expdesc *e) {\n  int pc;  /* pc of last jump */\n  luaK_dischargevars(fs, e);\n  switch (e->k) {\n    case VK: case VKNUM: case VTRUE: {\n      pc = NO_JUMP;  /* always true; do nothing */\n      break;\n    }\n    case VJMP: {\n      invertjump(fs, e);\n      pc = e->u.s.info;\n      break;\n    }\n    default: {\n      pc = jumponcond(fs, e, 0);\n      break;\n    }\n  }\n  luaK_concat(fs, &e->f, pc);  /* insert last jump in `f' list */\n  luaK_patchtohere(fs, e->t);\n  e->t = NO_JUMP;\n}\n\n\nstatic void luaK_goiffalse (FuncState *fs, expdesc *e) {\n  int pc;  /* pc of last jump */\n  luaK_dischargevars(fs, e);\n  switch (e->k) {\n    case VNIL: case VFALSE: {\n      pc = NO_JUMP;  /* always false; do nothing */\n      break;\n    }\n    case VJMP: {\n      pc = e->u.s.info;\n      break;\n    }\n    default: {\n      pc = jumponcond(fs, e, 1);\n      break;\n    }\n  }\n  luaK_concat(fs, &e->t, pc);  /* insert last jump in `t' list */\n  luaK_patchtohere(fs, e->f);\n  e->f = NO_JUMP;\n}\n\n\nstatic void codenot (FuncState *fs, expdesc *e) {\n  luaK_dischargevars(fs, e);\n  switch (e->k) {\n    case VNIL: case VFALSE: {\n      e->k = VTRUE;\n      break;\n    }\n    case VK: case VKNUM: case VTRUE: {\n      e->k = VFALSE;\n      break;\n    }\n    case VJMP: {\n      invertjump(fs, e);\n      break;\n    }\n    case VRELOCABLE:\n    case VNONRELOC: {\n      discharge2anyreg(fs, e);\n      freeexp(fs, e);\n      e->u.s.info = luaK_codeABC(fs, OP_NOT, 0, e->u.s.info, 0);\n      e->k = VRELOCABLE;\n      break;\n    }\n    default: {\n      lua_assert(0);  /* cannot happen */\n      break;\n    }\n  }\n  /* interchange true and false lists */\n  { int temp = e->f; e->f = e->t; e->t = temp; }\n  removevalues(fs, e->f);\n  removevalues(fs, e->t);\n}\n\n\nvoid luaK_indexed (FuncState *fs, expdesc *t, expdesc *k) {\n  t->u.s.aux = luaK_exp2RK(fs, k);\n  t->k = VINDEXED;\n}\n\n\nstatic int constfolding (OpCode op, expdesc *e1, expdesc *e2) {\n  lua_Number v1, v2, r;\n  if (!isnumeral(e1) || !isnumeral(e2)) return 0;\n  v1 = e1->u.nval;\n  v2 = e2->u.nval;\n  switch (op) {\n    case OP_ADD: r = luai_numadd(v1, v2); break;\n    case OP_SUB: r = luai_numsub(v1, v2); break;\n    case OP_MUL: r = luai_nummul(v1, v2); break;\n    case OP_DIV:\n      if (v2 == 0) return 0;  /* do not attempt to divide by 0 */\n      r = luai_numdiv(v1, v2); break;\n    case OP_MOD:\n      if (v2 == 0) return 0;  /* do not attempt to divide by 0 */\n      r = luai_nummod(v1, v2); break;\n    case OP_POW: r = luai_numpow(v1, v2); break;\n    case OP_UNM: r = luai_numunm(v1); break;\n    case OP_LEN: return 0;  /* no constant folding for 'len' */\n    default: lua_assert(0); r = 0; break;\n  }\n  if (luai_numisnan(r)) return 0;  /* do not attempt to produce NaN */\n  e1->u.nval = r;\n  return 1;\n}\n\n\nstatic void codearith (FuncState *fs, OpCode op, expdesc *e1, expdesc *e2) {\n  if (constfolding(op, e1, e2))\n    return;\n  else {\n    int o2 = (op != OP_UNM && op != OP_LEN) ? luaK_exp2RK(fs, e2) : 0;\n    int o1 = luaK_exp2RK(fs, e1);\n    if (o1 > o2) {\n      freeexp(fs, e1);\n      freeexp(fs, e2);\n    }\n    else {\n      freeexp(fs, e2);\n      freeexp(fs, e1);\n    }\n    e1->u.s.info = luaK_codeABC(fs, op, 0, o1, o2);\n    e1->k = VRELOCABLE;\n  }\n}\n\n\nstatic void codecomp (FuncState *fs, OpCode op, int cond, expdesc *e1,\n                                                          expdesc *e2) {\n  int o1 = luaK_exp2RK(fs, e1);\n  int o2 = luaK_exp2RK(fs, e2);\n  freeexp(fs, e2);\n  freeexp(fs, e1);\n  if (cond == 0 && op != OP_EQ) {\n    int temp;  /* exchange args to replace by `<' or `<=' */\n    temp = o1; o1 = o2; o2 = temp;  /* o1 <==> o2 */\n    cond = 1;\n  }\n  e1->u.s.info = condjump(fs, op, cond, o1, o2);\n  e1->k = VJMP;\n}\n\n\nvoid luaK_prefix (FuncState *fs, UnOpr op, expdesc *e) {\n  expdesc e2;\n  e2.t = e2.f = NO_JUMP; e2.k = VKNUM; e2.u.nval = 0;\n  switch (op) {\n    case OPR_MINUS: {\n      if (!isnumeral(e))\n        luaK_exp2anyreg(fs, e);  /* cannot operate on non-numeric constants */\n      codearith(fs, OP_UNM, e, &e2);\n      break;\n    }\n    case OPR_NOT: codenot(fs, e); break;\n    case OPR_LEN: {\n      luaK_exp2anyreg(fs, e);  /* cannot operate on constants */\n      codearith(fs, OP_LEN, e, &e2);\n      break;\n    }\n    default: lua_assert(0);\n  }\n}\n\n\nvoid luaK_infix (FuncState *fs, BinOpr op, expdesc *v) {\n  switch (op) {\n    case OPR_AND: {\n      luaK_goiftrue(fs, v);\n      break;\n    }\n    case OPR_OR: {\n      luaK_goiffalse(fs, v);\n      break;\n    }\n    case OPR_CONCAT: {\n      luaK_exp2nextreg(fs, v);  /* operand must be on the `stack' */\n      break;\n    }\n    case OPR_ADD: case OPR_SUB: case OPR_MUL: case OPR_DIV:\n    case OPR_MOD: case OPR_POW: {\n      if (!isnumeral(v)) luaK_exp2RK(fs, v);\n      break;\n    }\n    default: {\n      luaK_exp2RK(fs, v);\n      break;\n    }\n  }\n}\n\n\nvoid luaK_posfix (FuncState *fs, BinOpr op, expdesc *e1, expdesc *e2) {\n  switch (op) {\n    case OPR_AND: {\n      lua_assert(e1->t == NO_JUMP);  /* list must be closed */\n      luaK_dischargevars(fs, e2);\n      luaK_concat(fs, &e2->f, e1->f);\n      *e1 = *e2;\n      break;\n    }\n    case OPR_OR: {\n      lua_assert(e1->f == NO_JUMP);  /* list must be closed */\n      luaK_dischargevars(fs, e2);\n      luaK_concat(fs, &e2->t, e1->t);\n      *e1 = *e2;\n      break;\n    }\n    case OPR_CONCAT: {\n      luaK_exp2val(fs, e2);\n      if (e2->k == VRELOCABLE && GET_OPCODE(getcode(fs, e2)) == OP_CONCAT) {\n        lua_assert(e1->u.s.info == GETARG_B(getcode(fs, e2))-1);\n        freeexp(fs, e1);\n        SETARG_B(getcode(fs, e2), e1->u.s.info);\n        e1->k = VRELOCABLE; e1->u.s.info = e2->u.s.info;\n      }\n      else {\n        luaK_exp2nextreg(fs, e2);  /* operand must be on the 'stack' */\n        codearith(fs, OP_CONCAT, e1, e2);\n      }\n      break;\n    }\n    case OPR_ADD: codearith(fs, OP_ADD, e1, e2); break;\n    case OPR_SUB: codearith(fs, OP_SUB, e1, e2); break;\n    case OPR_MUL: codearith(fs, OP_MUL, e1, e2); break;\n    case OPR_DIV: codearith(fs, OP_DIV, e1, e2); break;\n    case OPR_MOD: codearith(fs, OP_MOD, e1, e2); break;\n    case OPR_POW: codearith(fs, OP_POW, e1, e2); break;\n    case OPR_EQ: codecomp(fs, OP_EQ, 1, e1, e2); break;\n    case OPR_NE: codecomp(fs, OP_EQ, 0, e1, e2); break;\n    case OPR_LT: codecomp(fs, OP_LT, 1, e1, e2); break;\n    case OPR_LE: codecomp(fs, OP_LE, 1, e1, e2); break;\n    case OPR_GT: codecomp(fs, OP_LT, 0, e1, e2); break;\n    case OPR_GE: codecomp(fs, OP_LE, 0, e1, e2); break;\n    default: lua_assert(0);\n  }\n}\n\n\nvoid luaK_fixline (FuncState *fs, int line) {\n  fs->f->lineinfo[fs->pc - 1] = line;\n}\n\n\nstatic int luaK_code (FuncState *fs, Instruction i, int line) {\n  Proto *f = fs->f;\n  dischargejpc(fs);  /* `pc' will change */\n  /* put new instruction in code array */\n  luaM_growvector(fs->L, f->code, fs->pc, f->sizecode, Instruction,\n                  MAX_INT, \"code size overflow\");\n  f->code[fs->pc] = i;\n  /* save corresponding line information */\n  luaM_growvector(fs->L, f->lineinfo, fs->pc, f->sizelineinfo, int,\n                  MAX_INT, \"code size overflow\");\n  f->lineinfo[fs->pc] = line;\n  return fs->pc++;\n}\n\n\nint luaK_codeABC (FuncState *fs, OpCode o, int a, int b, int c) {\n  lua_assert(getOpMode(o) == iABC);\n  lua_assert(getBMode(o) != OpArgN || b == 0);\n  lua_assert(getCMode(o) != OpArgN || c == 0);\n  return luaK_code(fs, CREATE_ABC(o, a, b, c), fs->ls->lastline);\n}\n\n\nint luaK_codeABx (FuncState *fs, OpCode o, int a, unsigned int bc) {\n  lua_assert(getOpMode(o) == iABx || getOpMode(o) == iAsBx);\n  lua_assert(getCMode(o) == OpArgN);\n  return luaK_code(fs, CREATE_ABx(o, a, bc), fs->ls->lastline);\n}\n\n\nvoid luaK_setlist (FuncState *fs, int base, int nelems, int tostore) {\n  int c =  (nelems - 1)/LFIELDS_PER_FLUSH + 1;\n  int b = (tostore == LUA_MULTRET) ? 0 : tostore;\n  lua_assert(tostore != 0);\n  if (c <= MAXARG_C)\n    luaK_codeABC(fs, OP_SETLIST, base, b, c);\n  else {\n    luaK_codeABC(fs, OP_SETLIST, base, b, 0);\n    luaK_code(fs, cast(Instruction, c), fs->ls->lastline);\n  }\n  fs->freereg = base + 1;  /* free registers with list values */\n}\n\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/deps/lua/src/lcode.h",
    "content": "/*\n** $Id: lcode.h,v 1.48.1.1 2007/12/27 13:02:25 roberto Exp $\n** Code generator for Lua\n** See Copyright Notice in lua.h\n*/\n\n#ifndef lcode_h\n#define lcode_h\n\n#include \"llex.h\"\n#include \"lobject.h\"\n#include \"lopcodes.h\"\n#include \"lparser.h\"\n\n\n/*\n** Marks the end of a patch list. It is an invalid value both as an absolute\n** address, and as a list link (would link an element to itself).\n*/\n#define NO_JUMP (-1)\n\n\n/*\n** grep \"ORDER OPR\" if you change these enums\n*/\ntypedef enum BinOpr {\n  OPR_ADD, OPR_SUB, OPR_MUL, OPR_DIV, OPR_MOD, OPR_POW,\n  OPR_CONCAT,\n  OPR_NE, OPR_EQ,\n  OPR_LT, OPR_LE, OPR_GT, OPR_GE,\n  OPR_AND, OPR_OR,\n  OPR_NOBINOPR\n} BinOpr;\n\n\ntypedef enum UnOpr { OPR_MINUS, OPR_NOT, OPR_LEN, OPR_NOUNOPR } UnOpr;\n\n\n#define getcode(fs,e)\t((fs)->f->code[(e)->u.s.info])\n\n#define luaK_codeAsBx(fs,o,A,sBx)\tluaK_codeABx(fs,o,A,(sBx)+MAXARG_sBx)\n\n#define luaK_setmultret(fs,e)\tluaK_setreturns(fs, e, LUA_MULTRET)\n\nLUAI_FUNC int luaK_codeABx (FuncState *fs, OpCode o, int A, unsigned int Bx);\nLUAI_FUNC int luaK_codeABC (FuncState *fs, OpCode o, int A, int B, int C);\nLUAI_FUNC void luaK_fixline (FuncState *fs, int line);\nLUAI_FUNC void luaK_nil (FuncState *fs, int from, int n);\nLUAI_FUNC void luaK_reserveregs (FuncState *fs, int n);\nLUAI_FUNC void luaK_checkstack (FuncState *fs, int n);\nLUAI_FUNC int luaK_stringK (FuncState *fs, TString *s);\nLUAI_FUNC int luaK_numberK (FuncState *fs, lua_Number r);\nLUAI_FUNC void luaK_dischargevars (FuncState *fs, expdesc *e);\nLUAI_FUNC int luaK_exp2anyreg (FuncState *fs, expdesc *e);\nLUAI_FUNC void luaK_exp2nextreg (FuncState *fs, expdesc *e);\nLUAI_FUNC void luaK_exp2val (FuncState *fs, expdesc *e);\nLUAI_FUNC int luaK_exp2RK (FuncState *fs, expdesc *e);\nLUAI_FUNC void luaK_self (FuncState *fs, expdesc *e, expdesc *key);\nLUAI_FUNC void luaK_indexed (FuncState *fs, expdesc *t, expdesc *k);\nLUAI_FUNC void luaK_goiftrue (FuncState *fs, expdesc *e);\nLUAI_FUNC void luaK_storevar (FuncState *fs, expdesc *var, expdesc *e);\nLUAI_FUNC void luaK_setreturns (FuncState *fs, expdesc *e, int nresults);\nLUAI_FUNC void luaK_setoneret (FuncState *fs, expdesc *e);\nLUAI_FUNC int luaK_jump (FuncState *fs);\nLUAI_FUNC void luaK_ret (FuncState *fs, int first, int nret);\nLUAI_FUNC void luaK_patchlist (FuncState *fs, int list, int target);\nLUAI_FUNC void luaK_patchtohere (FuncState *fs, int list);\nLUAI_FUNC void luaK_concat (FuncState *fs, int *l1, int l2);\nLUAI_FUNC int luaK_getlabel (FuncState *fs);\nLUAI_FUNC void luaK_prefix (FuncState *fs, UnOpr op, expdesc *v);\nLUAI_FUNC void luaK_infix (FuncState *fs, BinOpr op, expdesc *v);\nLUAI_FUNC void luaK_posfix (FuncState *fs, BinOpr op, expdesc *v1, expdesc *v2);\nLUAI_FUNC void luaK_setlist (FuncState *fs, int base, int nelems, int tostore);\n\n\n#endif\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/deps/lua/src/ldblib.c",
    "content": "/*\n** $Id: ldblib.c,v 1.104.1.4 2009/08/04 18:50:18 roberto Exp $\n** Interface from Lua to its debug API\n** See Copyright Notice in lua.h\n*/\n\n\n#include <stdio.h>\n#include <stdlib.h>\n#include <string.h>\n\n#define ldblib_c\n#define LUA_LIB\n\n#include \"lua.h\"\n\n#include \"lauxlib.h\"\n#include \"lualib.h\"\n\n\n\nstatic int db_getregistry (lua_State *L) {\n  lua_pushvalue(L, LUA_REGISTRYINDEX);\n  return 1;\n}\n\n\nstatic int db_getmetatable (lua_State *L) {\n  luaL_checkany(L, 1);\n  if (!lua_getmetatable(L, 1)) {\n    lua_pushnil(L);  /* no metatable */\n  }\n  return 1;\n}\n\n\nstatic int db_setmetatable (lua_State *L) {\n  int t = lua_type(L, 2);\n  luaL_argcheck(L, t == LUA_TNIL || t == LUA_TTABLE, 2,\n                    \"nil or table expected\");\n  lua_settop(L, 2);\n  lua_pushboolean(L, lua_setmetatable(L, 1));\n  return 1;\n}\n\n\nstatic int db_getfenv (lua_State *L) {\n  luaL_checkany(L, 1);\n  lua_getfenv(L, 1);\n  return 1;\n}\n\n\nstatic int db_setfenv (lua_State *L) {\n  luaL_checktype(L, 2, LUA_TTABLE);\n  lua_settop(L, 2);\n  if (lua_setfenv(L, 1) == 0)\n    luaL_error(L, LUA_QL(\"setfenv\")\n                  \" cannot change environment of given object\");\n  return 1;\n}\n\n\nstatic void settabss (lua_State *L, const char *i, const char *v) {\n  lua_pushstring(L, v);\n  lua_setfield(L, -2, i);\n}\n\n\nstatic void settabsi (lua_State *L, const char *i, int v) {\n  lua_pushinteger(L, v);\n  lua_setfield(L, -2, i);\n}\n\n\nstatic lua_State *getthread (lua_State *L, int *arg) {\n  if (lua_isthread(L, 1)) {\n    *arg = 1;\n    return lua_tothread(L, 1);\n  }\n  else {\n    *arg = 0;\n    return L;\n  }\n}\n\n\nstatic void treatstackoption (lua_State *L, lua_State *L1, const char *fname) {\n  if (L == L1) {\n    lua_pushvalue(L, -2);\n    lua_remove(L, -3);\n  }\n  else\n    lua_xmove(L1, L, 1);\n  lua_setfield(L, -2, fname);\n}\n\n\nstatic int db_getinfo (lua_State *L) {\n  lua_Debug ar;\n  int arg;\n  lua_State *L1 = getthread(L, &arg);\n  const char *options = luaL_optstring(L, arg+2, \"flnSu\");\n  if (lua_isnumber(L, arg+1)) {\n    if (!lua_getstack(L1, (int)lua_tointeger(L, arg+1), &ar)) {\n      lua_pushnil(L);  /* level out of range */\n      return 1;\n    }\n  }\n  else if (lua_isfunction(L, arg+1)) {\n    lua_pushfstring(L, \">%s\", options);\n    options = lua_tostring(L, -1);\n    lua_pushvalue(L, arg+1);\n    lua_xmove(L, L1, 1);\n  }\n  else\n    return luaL_argerror(L, arg+1, \"function or level expected\");\n  if (!lua_getinfo(L1, options, &ar))\n    return luaL_argerror(L, arg+2, \"invalid option\");\n  lua_createtable(L, 0, 2);\n  if (strchr(options, 'S')) {\n    settabss(L, \"source\", ar.source);\n    settabss(L, \"short_src\", ar.short_src);\n    settabsi(L, \"linedefined\", ar.linedefined);\n    settabsi(L, \"lastlinedefined\", ar.lastlinedefined);\n    settabss(L, \"what\", ar.what);\n  }\n  if (strchr(options, 'l'))\n    settabsi(L, \"currentline\", ar.currentline);\n  if (strchr(options, 'u'))\n    settabsi(L, \"nups\", ar.nups);\n  if (strchr(options, 'n')) {\n    settabss(L, \"name\", ar.name);\n    settabss(L, \"namewhat\", ar.namewhat);\n  }\n  if (strchr(options, 'L'))\n    treatstackoption(L, L1, \"activelines\");\n  if (strchr(options, 'f'))\n    treatstackoption(L, L1, \"func\");\n  return 1;  /* return table */\n}\n    \n\nstatic int db_getlocal (lua_State *L) {\n  int arg;\n  lua_State *L1 = getthread(L, &arg);\n  lua_Debug ar;\n  const char *name;\n  if (!lua_getstack(L1, luaL_checkint(L, arg+1), &ar))  /* out of range? */\n    return luaL_argerror(L, arg+1, \"level out of range\");\n  name = lua_getlocal(L1, &ar, luaL_checkint(L, arg+2));\n  if (name) {\n    lua_xmove(L1, L, 1);\n    lua_pushstring(L, name);\n    lua_pushvalue(L, -2);\n    return 2;\n  }\n  else {\n    lua_pushnil(L);\n    return 1;\n  }\n}\n\n\nstatic int db_setlocal (lua_State *L) {\n  int arg;\n  lua_State *L1 = getthread(L, &arg);\n  lua_Debug ar;\n  if (!lua_getstack(L1, luaL_checkint(L, arg+1), &ar))  /* out of range? */\n    return luaL_argerror(L, arg+1, \"level out of range\");\n  luaL_checkany(L, arg+3);\n  lua_settop(L, arg+3);\n  lua_xmove(L, L1, 1);\n  lua_pushstring(L, lua_setlocal(L1, &ar, luaL_checkint(L, arg+2)));\n  return 1;\n}\n\n\nstatic int auxupvalue (lua_State *L, int get) {\n  const char *name;\n  int n = luaL_checkint(L, 2);\n  luaL_checktype(L, 1, LUA_TFUNCTION);\n  if (lua_iscfunction(L, 1)) return 0;  /* cannot touch C upvalues from Lua */\n  name = get ? lua_getupvalue(L, 1, n) : lua_setupvalue(L, 1, n);\n  if (name == NULL) return 0;\n  lua_pushstring(L, name);\n  lua_insert(L, -(get+1));\n  return get + 1;\n}\n\n\nstatic int db_getupvalue (lua_State *L) {\n  return auxupvalue(L, 1);\n}\n\n\nstatic int db_setupvalue (lua_State *L) {\n  luaL_checkany(L, 3);\n  return auxupvalue(L, 0);\n}\n\n\n\nstatic const char KEY_HOOK = 'h';\n\n\nstatic void hookf (lua_State *L, lua_Debug *ar) {\n  static const char *const hooknames[] =\n    {\"call\", \"return\", \"line\", \"count\", \"tail return\"};\n  lua_pushlightuserdata(L, (void *)&KEY_HOOK);\n  lua_rawget(L, LUA_REGISTRYINDEX);\n  lua_pushlightuserdata(L, L);\n  lua_rawget(L, -2);\n  if (lua_isfunction(L, -1)) {\n    lua_pushstring(L, hooknames[(int)ar->event]);\n    if (ar->currentline >= 0)\n      lua_pushinteger(L, ar->currentline);\n    else lua_pushnil(L);\n    lua_assert(lua_getinfo(L, \"lS\", ar));\n    lua_call(L, 2, 0);\n  }\n}\n\n\nstatic int makemask (const char *smask, int count) {\n  int mask = 0;\n  if (strchr(smask, 'c')) mask |= LUA_MASKCALL;\n  if (strchr(smask, 'r')) mask |= LUA_MASKRET;\n  if (strchr(smask, 'l')) mask |= LUA_MASKLINE;\n  if (count > 0) mask |= LUA_MASKCOUNT;\n  return mask;\n}\n\n\nstatic char *unmakemask (int mask, char *smask) {\n  int i = 0;\n  if (mask & LUA_MASKCALL) smask[i++] = 'c';\n  if (mask & LUA_MASKRET) smask[i++] = 'r';\n  if (mask & LUA_MASKLINE) smask[i++] = 'l';\n  smask[i] = '\\0';\n  return smask;\n}\n\n\nstatic void gethooktable (lua_State *L) {\n  lua_pushlightuserdata(L, (void *)&KEY_HOOK);\n  lua_rawget(L, LUA_REGISTRYINDEX);\n  if (!lua_istable(L, -1)) {\n    lua_pop(L, 1);\n    lua_createtable(L, 0, 1);\n    lua_pushlightuserdata(L, (void *)&KEY_HOOK);\n    lua_pushvalue(L, -2);\n    lua_rawset(L, LUA_REGISTRYINDEX);\n  }\n}\n\n\nstatic int db_sethook (lua_State *L) {\n  int arg, mask, count;\n  lua_Hook func;\n  lua_State *L1 = getthread(L, &arg);\n  if (lua_isnoneornil(L, arg+1)) {\n    lua_settop(L, arg+1);\n    func = NULL; mask = 0; count = 0;  /* turn off hooks */\n  }\n  else {\n    const char *smask = luaL_checkstring(L, arg+2);\n    luaL_checktype(L, arg+1, LUA_TFUNCTION);\n    count = luaL_optint(L, arg+3, 0);\n    func = hookf; mask = makemask(smask, count);\n  }\n  gethooktable(L);\n  lua_pushlightuserdata(L, L1);\n  lua_pushvalue(L, arg+1);\n  lua_rawset(L, -3);  /* set new hook */\n  lua_pop(L, 1);  /* remove hook table */\n  lua_sethook(L1, func, mask, count);  /* set hooks */\n  return 0;\n}\n\n\nstatic int db_gethook (lua_State *L) {\n  int arg;\n  lua_State *L1 = getthread(L, &arg);\n  char buff[5];\n  int mask = lua_gethookmask(L1);\n  lua_Hook hook = lua_gethook(L1);\n  if (hook != NULL && hook != hookf)  /* external hook? */\n    lua_pushliteral(L, \"external hook\");\n  else {\n    gethooktable(L);\n    lua_pushlightuserdata(L, L1);\n    lua_rawget(L, -2);   /* get hook */\n    lua_remove(L, -2);  /* remove hook table */\n  }\n  lua_pushstring(L, unmakemask(mask, buff));\n  lua_pushinteger(L, lua_gethookcount(L1));\n  return 3;\n}\n\n\nstatic int db_debug (lua_State *L) {\n  for (;;) {\n    char buffer[250];\n    fputs(\"lua_debug> \", stderr);\n    if (fgets(buffer, sizeof(buffer), stdin) == 0 ||\n        strcmp(buffer, \"cont\\n\") == 0)\n      return 0;\n    if (luaL_loadbuffer(L, buffer, strlen(buffer), \"=(debug command)\") ||\n        lua_pcall(L, 0, 0, 0)) {\n      fputs(lua_tostring(L, -1), stderr);\n      fputs(\"\\n\", stderr);\n    }\n    lua_settop(L, 0);  /* remove eventual returns */\n  }\n}\n\n\n#define LEVELS1\t12\t/* size of the first part of the stack */\n#define LEVELS2\t10\t/* size of the second part of the stack */\n\nstatic int db_errorfb (lua_State *L) {\n  int level;\n  int firstpart = 1;  /* still before eventual `...' */\n  int arg;\n  lua_State *L1 = getthread(L, &arg);\n  lua_Debug ar;\n  if (lua_isnumber(L, arg+2)) {\n    level = (int)lua_tointeger(L, arg+2);\n    lua_pop(L, 1);\n  }\n  else\n    level = (L == L1) ? 1 : 0;  /* level 0 may be this own function */\n  if (lua_gettop(L) == arg)\n    lua_pushliteral(L, \"\");\n  else if (!lua_isstring(L, arg+1)) return 1;  /* message is not a string */\n  else lua_pushliteral(L, \"\\n\");\n  lua_pushliteral(L, \"stack traceback:\");\n  while (lua_getstack(L1, level++, &ar)) {\n    if (level > LEVELS1 && firstpart) {\n      /* no more than `LEVELS2' more levels? */\n      if (!lua_getstack(L1, level+LEVELS2, &ar))\n        level--;  /* keep going */\n      else {\n        lua_pushliteral(L, \"\\n\\t...\");  /* too many levels */\n        while (lua_getstack(L1, level+LEVELS2, &ar))  /* find last levels */\n          level++;\n      }\n      firstpart = 0;\n      continue;\n    }\n    lua_pushliteral(L, \"\\n\\t\");\n    lua_getinfo(L1, \"Snl\", &ar);\n    lua_pushfstring(L, \"%s:\", ar.short_src);\n    if (ar.currentline > 0)\n      lua_pushfstring(L, \"%d:\", ar.currentline);\n    if (*ar.namewhat != '\\0')  /* is there a name? */\n        lua_pushfstring(L, \" in function \" LUA_QS, ar.name);\n    else {\n      if (*ar.what == 'm')  /* main? */\n        lua_pushfstring(L, \" in main chunk\");\n      else if (*ar.what == 'C' || *ar.what == 't')\n        lua_pushliteral(L, \" ?\");  /* C function or tail call */\n      else\n        lua_pushfstring(L, \" in function <%s:%d>\",\n                           ar.short_src, ar.linedefined);\n    }\n    lua_concat(L, lua_gettop(L) - arg);\n  }\n  lua_concat(L, lua_gettop(L) - arg);\n  return 1;\n}\n\n\nstatic const luaL_Reg dblib[] = {\n  {\"debug\", db_debug},\n  {\"getfenv\", db_getfenv},\n  {\"gethook\", db_gethook},\n  {\"getinfo\", db_getinfo},\n  {\"getlocal\", db_getlocal},\n  {\"getregistry\", db_getregistry},\n  {\"getmetatable\", db_getmetatable},\n  {\"getupvalue\", db_getupvalue},\n  {\"setfenv\", db_setfenv},\n  {\"sethook\", db_sethook},\n  {\"setlocal\", db_setlocal},\n  {\"setmetatable\", db_setmetatable},\n  {\"setupvalue\", db_setupvalue},\n  {\"traceback\", db_errorfb},\n  {NULL, NULL}\n};\n\n\nLUALIB_API int luaopen_debug (lua_State *L) {\n  luaL_register(L, LUA_DBLIBNAME, dblib);\n  return 1;\n}\n\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/deps/lua/src/ldebug.c",
    "content": "/*\n** $Id: ldebug.c,v 2.29.1.6 2008/05/08 16:56:26 roberto Exp $\n** Debug Interface\n** See Copyright Notice in lua.h\n*/\n\n\n#include <stdarg.h>\n#include <stddef.h>\n#include <string.h>\n\n\n#define ldebug_c\n#define LUA_CORE\n\n#include \"lua.h\"\n\n#include \"lapi.h\"\n#include \"lcode.h\"\n#include \"ldebug.h\"\n#include \"ldo.h\"\n#include \"lfunc.h\"\n#include \"lobject.h\"\n#include \"lopcodes.h\"\n#include \"lstate.h\"\n#include \"lstring.h\"\n#include \"ltable.h\"\n#include \"ltm.h\"\n#include \"lvm.h\"\n\n\n\nstatic const char *getfuncname (lua_State *L, CallInfo *ci, const char **name);\n\n\nstatic int currentpc (lua_State *L, CallInfo *ci) {\n  if (!isLua(ci)) return -1;  /* function is not a Lua function? */\n  if (ci == L->ci)\n    ci->savedpc = L->savedpc;\n  return pcRel(ci->savedpc, ci_func(ci)->l.p);\n}\n\n\nstatic int currentline (lua_State *L, CallInfo *ci) {\n  int pc = currentpc(L, ci);\n  if (pc < 0)\n    return -1;  /* only active lua functions have current-line information */\n  else\n    return getline(ci_func(ci)->l.p, pc);\n}\n\n\n/*\n** this function can be called asynchronous (e.g. during a signal)\n*/\nLUA_API int lua_sethook (lua_State *L, lua_Hook func, int mask, int count) {\n  if (func == NULL || mask == 0) {  /* turn off hooks? */\n    mask = 0;\n    func = NULL;\n  }\n  L->hook = func;\n  L->basehookcount = count;\n  resethookcount(L);\n  L->hookmask = cast_byte(mask);\n  return 1;\n}\n\n\nLUA_API lua_Hook lua_gethook (lua_State *L) {\n  return L->hook;\n}\n\n\nLUA_API int lua_gethookmask (lua_State *L) {\n  return L->hookmask;\n}\n\n\nLUA_API int lua_gethookcount (lua_State *L) {\n  return L->basehookcount;\n}\n\n\nLUA_API int lua_getstack (lua_State *L, int level, lua_Debug *ar) {\n  int status;\n  CallInfo *ci;\n  lua_lock(L);\n  for (ci = L->ci; level > 0 && ci > L->base_ci; ci--) {\n    level--;\n    if (f_isLua(ci))  /* Lua function? */\n      level -= ci->tailcalls;  /* skip lost tail calls */\n  }\n  if (level == 0 && ci > L->base_ci) {  /* level found? */\n    status = 1;\n    ar->i_ci = cast_int(ci - L->base_ci);\n  }\n  else if (level < 0) {  /* level is of a lost tail call? */\n    status = 1;\n    ar->i_ci = 0;\n  }\n  else status = 0;  /* no such level */\n  lua_unlock(L);\n  return status;\n}\n\n\nstatic Proto *getluaproto (CallInfo *ci) {\n  return (isLua(ci) ? ci_func(ci)->l.p : NULL);\n}\n\n\nstatic const char *findlocal (lua_State *L, CallInfo *ci, int n) {\n  const char *name;\n  Proto *fp = getluaproto(ci);\n  if (fp && (name = luaF_getlocalname(fp, n, currentpc(L, ci))) != NULL)\n    return name;  /* is a local variable in a Lua function */\n  else {\n    StkId limit = (ci == L->ci) ? L->top : (ci+1)->func;\n    if (limit - ci->base >= n && n > 0)  /* is 'n' inside 'ci' stack? */\n      return \"(*temporary)\";\n    else\n      return NULL;\n  }\n}\n\n\nLUA_API const char *lua_getlocal (lua_State *L, const lua_Debug *ar, int n) {\n  CallInfo *ci = L->base_ci + ar->i_ci;\n  const char *name = findlocal(L, ci, n);\n  lua_lock(L);\n  if (name)\n      luaA_pushobject(L, ci->base + (n - 1));\n  lua_unlock(L);\n  return name;\n}\n\n\nLUA_API const char *lua_setlocal (lua_State *L, const lua_Debug *ar, int n) {\n  CallInfo *ci = L->base_ci + ar->i_ci;\n  const char *name = findlocal(L, ci, n);\n  lua_lock(L);\n  if (name)\n      setobjs2s(L, ci->base + (n - 1), L->top - 1);\n  L->top--;  /* pop value */\n  lua_unlock(L);\n  return name;\n}\n\n\nstatic void funcinfo (lua_Debug *ar, Closure *cl) {\n  if (cl->c.isC) {\n    ar->source = \"=[C]\";\n    ar->linedefined = -1;\n    ar->lastlinedefined = -1;\n    ar->what = \"C\";\n  }\n  else {\n    ar->source = getstr(cl->l.p->source);\n    ar->linedefined = cl->l.p->linedefined;\n    ar->lastlinedefined = cl->l.p->lastlinedefined;\n    ar->what = (ar->linedefined == 0) ? \"main\" : \"Lua\";\n  }\n  luaO_chunkid(ar->short_src, ar->source, LUA_IDSIZE);\n}\n\n\nstatic void info_tailcall (lua_Debug *ar) {\n  ar->name = ar->namewhat = \"\";\n  ar->what = \"tail\";\n  ar->lastlinedefined = ar->linedefined = ar->currentline = -1;\n  ar->source = \"=(tail call)\";\n  luaO_chunkid(ar->short_src, ar->source, LUA_IDSIZE);\n  ar->nups = 0;\n}\n\n\nstatic void collectvalidlines (lua_State *L, Closure *f) {\n  if (f == NULL || f->c.isC) {\n    setnilvalue(L->top);\n  }\n  else {\n    Table *t = luaH_new(L, 0, 0);\n    int *lineinfo = f->l.p->lineinfo;\n    int i;\n    for (i=0; i<f->l.p->sizelineinfo; i++)\n      setbvalue(luaH_setnum(L, t, lineinfo[i]), 1);\n    sethvalue(L, L->top, t); \n  }\n  incr_top(L);\n}\n\n\nstatic int auxgetinfo (lua_State *L, const char *what, lua_Debug *ar,\n                    Closure *f, CallInfo *ci) {\n  int status = 1;\n  if (f == NULL) {\n    info_tailcall(ar);\n    return status;\n  }\n  for (; *what; what++) {\n    switch (*what) {\n      case 'S': {\n        funcinfo(ar, f);\n        break;\n      }\n      case 'l': {\n        ar->currentline = (ci) ? currentline(L, ci) : -1;\n        break;\n      }\n      case 'u': {\n        ar->nups = f->c.nupvalues;\n        break;\n      }\n      case 'n': {\n        ar->namewhat = (ci) ? getfuncname(L, ci, &ar->name) : NULL;\n        if (ar->namewhat == NULL) {\n          ar->namewhat = \"\";  /* not found */\n          ar->name = NULL;\n        }\n        break;\n      }\n      case 'L':\n      case 'f':  /* handled by lua_getinfo */\n        break;\n      default: status = 0;  /* invalid option */\n    }\n  }\n  return status;\n}\n\n\nLUA_API int lua_getinfo (lua_State *L, const char *what, lua_Debug *ar) {\n  int status;\n  Closure *f = NULL;\n  CallInfo *ci = NULL;\n  lua_lock(L);\n  if (*what == '>') {\n    StkId func = L->top - 1;\n    luai_apicheck(L, ttisfunction(func));\n    what++;  /* skip the '>' */\n    f = clvalue(func);\n    L->top--;  /* pop function */\n  }\n  else if (ar->i_ci != 0) {  /* no tail call? */\n    ci = L->base_ci + ar->i_ci;\n    lua_assert(ttisfunction(ci->func));\n    f = clvalue(ci->func);\n  }\n  status = auxgetinfo(L, what, ar, f, ci);\n  if (strchr(what, 'f')) {\n    if (f == NULL) setnilvalue(L->top);\n    else setclvalue(L, L->top, f);\n    incr_top(L);\n  }\n  if (strchr(what, 'L'))\n    collectvalidlines(L, f);\n  lua_unlock(L);\n  return status;\n}\n\n\n/*\n** {======================================================\n** Symbolic Execution and code checker\n** =======================================================\n*/\n\n#define check(x)\t\tif (!(x)) return 0;\n\n#define checkjump(pt,pc)\tcheck(0 <= pc && pc < pt->sizecode)\n\n#define checkreg(pt,reg)\tcheck((reg) < (pt)->maxstacksize)\n\n\n\nstatic int precheck (const Proto *pt) {\n  check(pt->maxstacksize <= MAXSTACK);\n  check(pt->numparams+(pt->is_vararg & VARARG_HASARG) <= pt->maxstacksize);\n  check(!(pt->is_vararg & VARARG_NEEDSARG) ||\n              (pt->is_vararg & VARARG_HASARG));\n  check(pt->sizeupvalues <= pt->nups);\n  check(pt->sizelineinfo == pt->sizecode || pt->sizelineinfo == 0);\n  check(pt->sizecode > 0 && GET_OPCODE(pt->code[pt->sizecode-1]) == OP_RETURN);\n  return 1;\n}\n\n\n#define checkopenop(pt,pc)\tluaG_checkopenop((pt)->code[(pc)+1])\n\nint luaG_checkopenop (Instruction i) {\n  switch (GET_OPCODE(i)) {\n    case OP_CALL:\n    case OP_TAILCALL:\n    case OP_RETURN:\n    case OP_SETLIST: {\n      check(GETARG_B(i) == 0);\n      return 1;\n    }\n    default: return 0;  /* invalid instruction after an open call */\n  }\n}\n\n\nstatic int checkArgMode (const Proto *pt, int r, enum OpArgMask mode) {\n  switch (mode) {\n    case OpArgN: check(r == 0); break;\n    case OpArgU: break;\n    case OpArgR: checkreg(pt, r); break;\n    case OpArgK:\n      check(ISK(r) ? INDEXK(r) < pt->sizek : r < pt->maxstacksize);\n      break;\n  }\n  return 1;\n}\n\n\nstatic Instruction symbexec (const Proto *pt, int lastpc, int reg) {\n  int pc;\n  int last;  /* stores position of last instruction that changed `reg' */\n  last = pt->sizecode-1;  /* points to final return (a `neutral' instruction) */\n  check(precheck(pt));\n  for (pc = 0; pc < lastpc; pc++) {\n    Instruction i = pt->code[pc];\n    OpCode op = GET_OPCODE(i);\n    int a = GETARG_A(i);\n    int b = 0;\n    int c = 0;\n    check(op < NUM_OPCODES);\n    checkreg(pt, a);\n    switch (getOpMode(op)) {\n      case iABC: {\n        b = GETARG_B(i);\n        c = GETARG_C(i);\n        check(checkArgMode(pt, b, getBMode(op)));\n        check(checkArgMode(pt, c, getCMode(op)));\n        break;\n      }\n      case iABx: {\n        b = GETARG_Bx(i);\n        if (getBMode(op) == OpArgK) check(b < pt->sizek);\n        break;\n      }\n      case iAsBx: {\n        b = GETARG_sBx(i);\n        if (getBMode(op) == OpArgR) {\n          int dest = pc+1+b;\n          check(0 <= dest && dest < pt->sizecode);\n          if (dest > 0) {\n            int j;\n            /* check that it does not jump to a setlist count; this\n               is tricky, because the count from a previous setlist may\n               have the same value of an invalid setlist; so, we must\n               go all the way back to the first of them (if any) */\n            for (j = 0; j < dest; j++) {\n              Instruction d = pt->code[dest-1-j];\n              if (!(GET_OPCODE(d) == OP_SETLIST && GETARG_C(d) == 0)) break;\n            }\n            /* if 'j' is even, previous value is not a setlist (even if\n               it looks like one) */\n            check((j&1) == 0);\n          }\n        }\n        break;\n      }\n    }\n    if (testAMode(op)) {\n      if (a == reg) last = pc;  /* change register `a' */\n    }\n    if (testTMode(op)) {\n      check(pc+2 < pt->sizecode);  /* check skip */\n      check(GET_OPCODE(pt->code[pc+1]) == OP_JMP);\n    }\n    switch (op) {\n      case OP_LOADBOOL: {\n        if (c == 1) {  /* does it jump? */\n          check(pc+2 < pt->sizecode);  /* check its jump */\n          check(GET_OPCODE(pt->code[pc+1]) != OP_SETLIST ||\n                GETARG_C(pt->code[pc+1]) != 0);\n        }\n        break;\n      }\n      case OP_LOADNIL: {\n        if (a <= reg && reg <= b)\n          last = pc;  /* set registers from `a' to `b' */\n        break;\n      }\n      case OP_GETUPVAL:\n      case OP_SETUPVAL: {\n        check(b < pt->nups);\n        break;\n      }\n      case OP_GETGLOBAL:\n      case OP_SETGLOBAL: {\n        check(ttisstring(&pt->k[b]));\n        break;\n      }\n      case OP_SELF: {\n        checkreg(pt, a+1);\n        if (reg == a+1) last = pc;\n        break;\n      }\n      case OP_CONCAT: {\n        check(b < c);  /* at least two operands */\n        break;\n      }\n      case OP_TFORLOOP: {\n        check(c >= 1);  /* at least one result (control variable) */\n        checkreg(pt, a+2+c);  /* space for results */\n        if (reg >= a+2) last = pc;  /* affect all regs above its base */\n        break;\n      }\n      case OP_FORLOOP:\n      case OP_FORPREP:\n        checkreg(pt, a+3);\n        /* go through */\n      case OP_JMP: {\n        int dest = pc+1+b;\n        /* not full check and jump is forward and do not skip `lastpc'? */\n        if (reg != NO_REG && pc < dest && dest <= lastpc)\n          pc += b;  /* do the jump */\n        break;\n      }\n      case OP_CALL:\n      case OP_TAILCALL: {\n        if (b != 0) {\n          checkreg(pt, a+b-1);\n        }\n        c--;  /* c = num. returns */\n        if (c == LUA_MULTRET) {\n          check(checkopenop(pt, pc));\n        }\n        else if (c != 0)\n          checkreg(pt, a+c-1);\n        if (reg >= a) last = pc;  /* affect all registers above base */\n        break;\n      }\n      case OP_RETURN: {\n        b--;  /* b = num. returns */\n        if (b > 0) checkreg(pt, a+b-1);\n        break;\n      }\n      case OP_SETLIST: {\n        if (b > 0) checkreg(pt, a + b);\n        if (c == 0) {\n          pc++;\n          check(pc < pt->sizecode - 1);\n        }\n        break;\n      }\n      case OP_CLOSURE: {\n        int nup, j;\n        check(b < pt->sizep);\n        nup = pt->p[b]->nups;\n        check(pc + nup < pt->sizecode);\n        for (j = 1; j <= nup; j++) {\n          OpCode op1 = GET_OPCODE(pt->code[pc + j]);\n          check(op1 == OP_GETUPVAL || op1 == OP_MOVE);\n        }\n        if (reg != NO_REG)  /* tracing? */\n          pc += nup;  /* do not 'execute' these pseudo-instructions */\n        break;\n      }\n      case OP_VARARG: {\n        check((pt->is_vararg & VARARG_ISVARARG) &&\n             !(pt->is_vararg & VARARG_NEEDSARG));\n        b--;\n        if (b == LUA_MULTRET) check(checkopenop(pt, pc));\n        checkreg(pt, a+b-1);\n        break;\n      }\n      default: break;\n    }\n  }\n  return pt->code[last];\n}\n\n#undef check\n#undef checkjump\n#undef checkreg\n\n/* }====================================================== */\n\n\nint luaG_checkcode (const Proto *pt) {\n  return (symbexec(pt, pt->sizecode, NO_REG) != 0);\n}\n\n\nstatic const char *kname (Proto *p, int c) {\n  if (ISK(c) && ttisstring(&p->k[INDEXK(c)]))\n    return svalue(&p->k[INDEXK(c)]);\n  else\n    return \"?\";\n}\n\n\nstatic const char *getobjname (lua_State *L, CallInfo *ci, int stackpos,\n                               const char **name) {\n  if (isLua(ci)) {  /* a Lua function? */\n    Proto *p = ci_func(ci)->l.p;\n    int pc = currentpc(L, ci);\n    Instruction i;\n    *name = luaF_getlocalname(p, stackpos+1, pc);\n    if (*name)  /* is a local? */\n      return \"local\";\n    i = symbexec(p, pc, stackpos);  /* try symbolic execution */\n    lua_assert(pc != -1);\n    switch (GET_OPCODE(i)) {\n      case OP_GETGLOBAL: {\n        int g = GETARG_Bx(i);  /* global index */\n        lua_assert(ttisstring(&p->k[g]));\n        *name = svalue(&p->k[g]);\n        return \"global\";\n      }\n      case OP_MOVE: {\n        int a = GETARG_A(i);\n        int b = GETARG_B(i);  /* move from `b' to `a' */\n        if (b < a)\n          return getobjname(L, ci, b, name);  /* get name for `b' */\n        break;\n      }\n      case OP_GETTABLE: {\n        int k = GETARG_C(i);  /* key index */\n        *name = kname(p, k);\n        return \"field\";\n      }\n      case OP_GETUPVAL: {\n        int u = GETARG_B(i);  /* upvalue index */\n        *name = p->upvalues ? getstr(p->upvalues[u]) : \"?\";\n        return \"upvalue\";\n      }\n      case OP_SELF: {\n        int k = GETARG_C(i);  /* key index */\n        *name = kname(p, k);\n        return \"method\";\n      }\n      default: break;\n    }\n  }\n  return NULL;  /* no useful name found */\n}\n\n\nstatic const char *getfuncname (lua_State *L, CallInfo *ci, const char **name) {\n  Instruction i;\n  if ((isLua(ci) && ci->tailcalls > 0) || !isLua(ci - 1))\n    return NULL;  /* calling function is not Lua (or is unknown) */\n  ci--;  /* calling function */\n  i = ci_func(ci)->l.p->code[currentpc(L, ci)];\n  if (GET_OPCODE(i) == OP_CALL || GET_OPCODE(i) == OP_TAILCALL ||\n      GET_OPCODE(i) == OP_TFORLOOP)\n    return getobjname(L, ci, GETARG_A(i), name);\n  else\n    return NULL;  /* no useful name can be found */\n}\n\n\n/* only ANSI way to check whether a pointer points to an array */\nstatic int isinstack (CallInfo *ci, const TValue *o) {\n  StkId p;\n  for (p = ci->base; p < ci->top; p++)\n    if (o == p) return 1;\n  return 0;\n}\n\n\nvoid luaG_typeerror (lua_State *L, const TValue *o, const char *op) {\n  const char *name = NULL;\n  const char *t = luaT_typenames[ttype(o)];\n  const char *kind = (isinstack(L->ci, o)) ?\n                         getobjname(L, L->ci, cast_int(o - L->base), &name) :\n                         NULL;\n  if (kind)\n    luaG_runerror(L, \"attempt to %s %s \" LUA_QS \" (a %s value)\",\n                op, kind, name, t);\n  else\n    luaG_runerror(L, \"attempt to %s a %s value\", op, t);\n}\n\n\nvoid luaG_concaterror (lua_State *L, StkId p1, StkId p2) {\n  if (ttisstring(p1) || ttisnumber(p1)) p1 = p2;\n  lua_assert(!ttisstring(p1) && !ttisnumber(p1));\n  luaG_typeerror(L, p1, \"concatenate\");\n}\n\n\nvoid luaG_aritherror (lua_State *L, const TValue *p1, const TValue *p2) {\n  TValue temp;\n  if (luaV_tonumber(p1, &temp) == NULL)\n    p2 = p1;  /* first operand is wrong */\n  luaG_typeerror(L, p2, \"perform arithmetic on\");\n}\n\n\nint luaG_ordererror (lua_State *L, const TValue *p1, const TValue *p2) {\n  const char *t1 = luaT_typenames[ttype(p1)];\n  const char *t2 = luaT_typenames[ttype(p2)];\n  if (t1[2] == t2[2])\n    luaG_runerror(L, \"attempt to compare two %s values\", t1);\n  else\n    luaG_runerror(L, \"attempt to compare %s with %s\", t1, t2);\n  return 0;\n}\n\n\nstatic void addinfo (lua_State *L, const char *msg) {\n  CallInfo *ci = L->ci;\n  if (isLua(ci)) {  /* is Lua code? */\n    char buff[LUA_IDSIZE];  /* add file:line information */\n    int line = currentline(L, ci);\n    luaO_chunkid(buff, getstr(getluaproto(ci)->source), LUA_IDSIZE);\n    luaO_pushfstring(L, \"%s:%d: %s\", buff, line, msg);\n  }\n}\n\n\nvoid luaG_errormsg (lua_State *L) {\n  if (L->errfunc != 0) {  /* is there an error handling function? */\n    StkId errfunc = restorestack(L, L->errfunc);\n    if (!ttisfunction(errfunc)) luaD_throw(L, LUA_ERRERR);\n    setobjs2s(L, L->top, L->top - 1);  /* move argument */\n    setobjs2s(L, L->top - 1, errfunc);  /* push function */\n    incr_top(L);\n    luaD_call(L, L->top - 2, 1);  /* call it */\n  }\n  luaD_throw(L, LUA_ERRRUN);\n}\n\n\nvoid luaG_runerror (lua_State *L, const char *fmt, ...) {\n  va_list argp;\n  va_start(argp, fmt);\n  addinfo(L, luaO_pushvfstring(L, fmt, argp));\n  va_end(argp);\n  luaG_errormsg(L);\n}\n\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/deps/lua/src/ldebug.h",
    "content": "/*\n** $Id: ldebug.h,v 2.3.1.1 2007/12/27 13:02:25 roberto Exp $\n** Auxiliary functions from Debug Interface module\n** See Copyright Notice in lua.h\n*/\n\n#ifndef ldebug_h\n#define ldebug_h\n\n\n#include \"lstate.h\"\n\n\n#define pcRel(pc, p)\t(cast(int, (pc) - (p)->code) - 1)\n\n#define getline(f,pc)\t(((f)->lineinfo) ? (f)->lineinfo[pc] : 0)\n\n#define resethookcount(L)\t(L->hookcount = L->basehookcount)\n\n\nLUAI_FUNC void luaG_typeerror (lua_State *L, const TValue *o,\n                                             const char *opname);\nLUAI_FUNC void luaG_concaterror (lua_State *L, StkId p1, StkId p2);\nLUAI_FUNC void luaG_aritherror (lua_State *L, const TValue *p1,\n                                              const TValue *p2);\nLUAI_FUNC int luaG_ordererror (lua_State *L, const TValue *p1,\n                                             const TValue *p2);\nLUAI_FUNC void luaG_runerror (lua_State *L, const char *fmt, ...);\nLUAI_FUNC void luaG_errormsg (lua_State *L);\nLUAI_FUNC int luaG_checkcode (const Proto *pt);\nLUAI_FUNC int luaG_checkopenop (Instruction i);\n\n#endif\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/deps/lua/src/ldo.c",
    "content": "/*\n** $Id: ldo.c,v 2.38.1.4 2012/01/18 02:27:10 roberto Exp $\n** Stack and Call structure of Lua\n** See Copyright Notice in lua.h\n*/\n\n\n#include <setjmp.h>\n#include <stdlib.h>\n#include <string.h>\n\n#define ldo_c\n#define LUA_CORE\n\n#include \"lua.h\"\n\n#include \"ldebug.h\"\n#include \"ldo.h\"\n#include \"lfunc.h\"\n#include \"lgc.h\"\n#include \"lmem.h\"\n#include \"lobject.h\"\n#include \"lopcodes.h\"\n#include \"lparser.h\"\n#include \"lstate.h\"\n#include \"lstring.h\"\n#include \"ltable.h\"\n#include \"ltm.h\"\n#include \"lundump.h\"\n#include \"lvm.h\"\n#include \"lzio.h\"\n\n\n\n\n/*\n** {======================================================\n** Error-recovery functions\n** =======================================================\n*/\n\n\n/* chain list of long jump buffers */\nstruct lua_longjmp {\n  struct lua_longjmp *previous;\n  luai_jmpbuf b;\n  volatile int status;  /* error code */\n};\n\n\nvoid luaD_seterrorobj (lua_State *L, int errcode, StkId oldtop) {\n  switch (errcode) {\n    case LUA_ERRMEM: {\n      setsvalue2s(L, oldtop, luaS_newliteral(L, MEMERRMSG));\n      break;\n    }\n    case LUA_ERRERR: {\n      setsvalue2s(L, oldtop, luaS_newliteral(L, \"error in error handling\"));\n      break;\n    }\n    case LUA_ERRSYNTAX:\n    case LUA_ERRRUN: {\n      setobjs2s(L, oldtop, L->top - 1);  /* error message on current top */\n      break;\n    }\n  }\n  L->top = oldtop + 1;\n}\n\n\nstatic void restore_stack_limit (lua_State *L) {\n  lua_assert(L->stack_last - L->stack == L->stacksize - EXTRA_STACK - 1);\n  if (L->size_ci > LUAI_MAXCALLS) {  /* there was an overflow? */\n    int inuse = cast_int(L->ci - L->base_ci);\n    if (inuse + 1 < LUAI_MAXCALLS)  /* can `undo' overflow? */\n      luaD_reallocCI(L, LUAI_MAXCALLS);\n  }\n}\n\n\nstatic void resetstack (lua_State *L, int status) {\n  L->ci = L->base_ci;\n  L->base = L->ci->base;\n  luaF_close(L, L->base);  /* close eventual pending closures */\n  luaD_seterrorobj(L, status, L->base);\n  L->nCcalls = L->baseCcalls;\n  L->allowhook = 1;\n  restore_stack_limit(L);\n  L->errfunc = 0;\n  L->errorJmp = NULL;\n}\n\n\nvoid luaD_throw (lua_State *L, int errcode) {\n  if (L->errorJmp) {\n    L->errorJmp->status = errcode;\n    LUAI_THROW(L, L->errorJmp);\n  }\n  else {\n    L->status = cast_byte(errcode);\n    if (G(L)->panic) {\n      resetstack(L, errcode);\n      lua_unlock(L);\n      G(L)->panic(L);\n    }\n    exit(EXIT_FAILURE);\n  }\n}\n\n\nint luaD_rawrunprotected (lua_State *L, Pfunc f, void *ud) {\n  struct lua_longjmp lj;\n  lj.status = 0;\n  lj.previous = L->errorJmp;  /* chain new error handler */\n  L->errorJmp = &lj;\n  LUAI_TRY(L, &lj,\n    (*f)(L, ud);\n  );\n  L->errorJmp = lj.previous;  /* restore old error handler */\n  return lj.status;\n}\n\n/* }====================================================== */\n\n\nstatic void correctstack (lua_State *L, TValue *oldstack) {\n  CallInfo *ci;\n  GCObject *up;\n  L->top = (L->top - oldstack) + L->stack;\n  for (up = L->openupval; up != NULL; up = up->gch.next)\n    gco2uv(up)->v = (gco2uv(up)->v - oldstack) + L->stack;\n  for (ci = L->base_ci; ci <= L->ci; ci++) {\n    ci->top = (ci->top - oldstack) + L->stack;\n    ci->base = (ci->base - oldstack) + L->stack;\n    ci->func = (ci->func - oldstack) + L->stack;\n  }\n  L->base = (L->base - oldstack) + L->stack;\n}\n\n\nvoid luaD_reallocstack (lua_State *L, int newsize) {\n  TValue *oldstack = L->stack;\n  int realsize = newsize + 1 + EXTRA_STACK;\n  lua_assert(L->stack_last - L->stack == L->stacksize - EXTRA_STACK - 1);\n  luaM_reallocvector(L, L->stack, L->stacksize, realsize, TValue);\n  L->stacksize = realsize;\n  L->stack_last = L->stack+newsize;\n  correctstack(L, oldstack);\n}\n\n\nvoid luaD_reallocCI (lua_State *L, int newsize) {\n  CallInfo *oldci = L->base_ci;\n  luaM_reallocvector(L, L->base_ci, L->size_ci, newsize, CallInfo);\n  L->size_ci = newsize;\n  L->ci = (L->ci - oldci) + L->base_ci;\n  L->end_ci = L->base_ci + L->size_ci - 1;\n}\n\n\nvoid luaD_growstack (lua_State *L, int n) {\n  if (n <= L->stacksize)  /* double size is enough? */\n    luaD_reallocstack(L, 2*L->stacksize);\n  else\n    luaD_reallocstack(L, L->stacksize + n);\n}\n\n\nstatic CallInfo *growCI (lua_State *L) {\n  if (L->size_ci > LUAI_MAXCALLS)  /* overflow while handling overflow? */\n    luaD_throw(L, LUA_ERRERR);\n  else {\n    luaD_reallocCI(L, 2*L->size_ci);\n    if (L->size_ci > LUAI_MAXCALLS)\n      luaG_runerror(L, \"stack overflow\");\n  }\n  return ++L->ci;\n}\n\n\nvoid luaD_callhook (lua_State *L, int event, int line) {\n  lua_Hook hook = L->hook;\n  if (hook && L->allowhook) {\n    ptrdiff_t top = savestack(L, L->top);\n    ptrdiff_t ci_top = savestack(L, L->ci->top);\n    lua_Debug ar;\n    ar.event = event;\n    ar.currentline = line;\n    if (event == LUA_HOOKTAILRET)\n      ar.i_ci = 0;  /* tail call; no debug information about it */\n    else\n      ar.i_ci = cast_int(L->ci - L->base_ci);\n    luaD_checkstack(L, LUA_MINSTACK);  /* ensure minimum stack size */\n    L->ci->top = L->top + LUA_MINSTACK;\n    lua_assert(L->ci->top <= L->stack_last);\n    L->allowhook = 0;  /* cannot call hooks inside a hook */\n    lua_unlock(L);\n    (*hook)(L, &ar);\n    lua_lock(L);\n    lua_assert(!L->allowhook);\n    L->allowhook = 1;\n    L->ci->top = restorestack(L, ci_top);\n    L->top = restorestack(L, top);\n  }\n}\n\n\nstatic StkId adjust_varargs (lua_State *L, Proto *p, int actual) {\n  int i;\n  int nfixargs = p->numparams;\n  Table *htab = NULL;\n  StkId base, fixed;\n  for (; actual < nfixargs; ++actual)\n    setnilvalue(L->top++);\n#if defined(LUA_COMPAT_VARARG)\n  if (p->is_vararg & VARARG_NEEDSARG) { /* compat. with old-style vararg? */\n    int nvar = actual - nfixargs;  /* number of extra arguments */\n    lua_assert(p->is_vararg & VARARG_HASARG);\n    luaC_checkGC(L);\n    luaD_checkstack(L, p->maxstacksize);\n    htab = luaH_new(L, nvar, 1);  /* create `arg' table */\n    for (i=0; i<nvar; i++)  /* put extra arguments into `arg' table */\n      setobj2n(L, luaH_setnum(L, htab, i+1), L->top - nvar + i);\n    /* store counter in field `n' */\n    setnvalue(luaH_setstr(L, htab, luaS_newliteral(L, \"n\")), cast_num(nvar));\n  }\n#endif\n  /* move fixed parameters to final position */\n  fixed = L->top - actual;  /* first fixed argument */\n  base = L->top;  /* final position of first argument */\n  for (i=0; i<nfixargs; i++) {\n    setobjs2s(L, L->top++, fixed+i);\n    setnilvalue(fixed+i);\n  }\n  /* add `arg' parameter */\n  if (htab) {\n    sethvalue(L, L->top++, htab);\n    lua_assert(iswhite(obj2gco(htab)));\n  }\n  return base;\n}\n\n\nstatic StkId tryfuncTM (lua_State *L, StkId func) {\n  const TValue *tm = luaT_gettmbyobj(L, func, TM_CALL);\n  StkId p;\n  ptrdiff_t funcr = savestack(L, func);\n  if (!ttisfunction(tm))\n    luaG_typeerror(L, func, \"call\");\n  /* Open a hole inside the stack at `func' */\n  for (p = L->top; p > func; p--) setobjs2s(L, p, p-1);\n  incr_top(L);\n  func = restorestack(L, funcr);  /* previous call may change stack */\n  setobj2s(L, func, tm);  /* tag method is the new function to be called */\n  return func;\n}\n\n\n\n#define inc_ci(L) \\\n  ((L->ci == L->end_ci) ? growCI(L) : \\\n   (condhardstacktests(luaD_reallocCI(L, L->size_ci)), ++L->ci))\n\n\nint luaD_precall (lua_State *L, StkId func, int nresults) {\n  LClosure *cl;\n  ptrdiff_t funcr;\n  if (!ttisfunction(func)) /* `func' is not a function? */\n    func = tryfuncTM(L, func);  /* check the `function' tag method */\n  funcr = savestack(L, func);\n  cl = &clvalue(func)->l;\n  L->ci->savedpc = L->savedpc;\n  if (!cl->isC) {  /* Lua function? prepare its call */\n    CallInfo *ci;\n    StkId st, base;\n    Proto *p = cl->p;\n    luaD_checkstack(L, p->maxstacksize);\n    func = restorestack(L, funcr);\n    if (!p->is_vararg) {  /* no varargs? */\n      base = func + 1;\n      if (L->top > base + p->numparams)\n        L->top = base + p->numparams;\n    }\n    else {  /* vararg function */\n      int nargs = cast_int(L->top - func) - 1;\n      base = adjust_varargs(L, p, nargs);\n      func = restorestack(L, funcr);  /* previous call may change the stack */\n    }\n    ci = inc_ci(L);  /* now `enter' new function */\n    ci->func = func;\n    L->base = ci->base = base;\n    ci->top = L->base + p->maxstacksize;\n    lua_assert(ci->top <= L->stack_last);\n    L->savedpc = p->code;  /* starting point */\n    ci->tailcalls = 0;\n    ci->nresults = nresults;\n    for (st = L->top; st < ci->top; st++)\n      setnilvalue(st);\n    L->top = ci->top;\n    if (L->hookmask & LUA_MASKCALL) {\n      L->savedpc++;  /* hooks assume 'pc' is already incremented */\n      luaD_callhook(L, LUA_HOOKCALL, -1);\n      L->savedpc--;  /* correct 'pc' */\n    }\n    return PCRLUA;\n  }\n  else {  /* if is a C function, call it */\n    CallInfo *ci;\n    int n;\n    luaD_checkstack(L, LUA_MINSTACK);  /* ensure minimum stack size */\n    ci = inc_ci(L);  /* now `enter' new function */\n    ci->func = restorestack(L, funcr);\n    L->base = ci->base = ci->func + 1;\n    ci->top = L->top + LUA_MINSTACK;\n    lua_assert(ci->top <= L->stack_last);\n    ci->nresults = nresults;\n    if (L->hookmask & LUA_MASKCALL)\n      luaD_callhook(L, LUA_HOOKCALL, -1);\n    lua_unlock(L);\n    n = (*curr_func(L)->c.f)(L);  /* do the actual call */\n    lua_lock(L);\n    if (n < 0)  /* yielding? */\n      return PCRYIELD;\n    else {\n      luaD_poscall(L, L->top - n);\n      return PCRC;\n    }\n  }\n}\n\n\nstatic StkId callrethooks (lua_State *L, StkId firstResult) {\n  ptrdiff_t fr = savestack(L, firstResult);  /* next call may change stack */\n  luaD_callhook(L, LUA_HOOKRET, -1);\n  if (f_isLua(L->ci)) {  /* Lua function? */\n    while ((L->hookmask & LUA_MASKRET) && L->ci->tailcalls--) /* tail calls */\n      luaD_callhook(L, LUA_HOOKTAILRET, -1);\n  }\n  return restorestack(L, fr);\n}\n\n\nint luaD_poscall (lua_State *L, StkId firstResult) {\n  StkId res;\n  int wanted, i;\n  CallInfo *ci;\n  if (L->hookmask & LUA_MASKRET)\n    firstResult = callrethooks(L, firstResult);\n  ci = L->ci--;\n  res = ci->func;  /* res == final position of 1st result */\n  wanted = ci->nresults;\n  L->base = (ci - 1)->base;  /* restore base */\n  L->savedpc = (ci - 1)->savedpc;  /* restore savedpc */\n  /* move results to correct place */\n  for (i = wanted; i != 0 && firstResult < L->top; i--)\n    setobjs2s(L, res++, firstResult++);\n  while (i-- > 0)\n    setnilvalue(res++);\n  L->top = res;\n  return (wanted - LUA_MULTRET);  /* 0 iff wanted == LUA_MULTRET */\n}\n\n\n/*\n** Call a function (C or Lua). The function to be called is at *func.\n** The arguments are on the stack, right after the function.\n** When returns, all the results are on the stack, starting at the original\n** function position.\n*/ \nvoid luaD_call (lua_State *L, StkId func, int nResults) {\n  if (++L->nCcalls >= LUAI_MAXCCALLS) {\n    if (L->nCcalls == LUAI_MAXCCALLS)\n      luaG_runerror(L, \"C stack overflow\");\n    else if (L->nCcalls >= (LUAI_MAXCCALLS + (LUAI_MAXCCALLS>>3)))\n      luaD_throw(L, LUA_ERRERR);  /* error while handing stack error */\n  }\n  if (luaD_precall(L, func, nResults) == PCRLUA)  /* is a Lua function? */\n    luaV_execute(L, 1);  /* call it */\n  L->nCcalls--;\n  luaC_checkGC(L);\n}\n\n\nstatic void resume (lua_State *L, void *ud) {\n  StkId firstArg = cast(StkId, ud);\n  CallInfo *ci = L->ci;\n  if (L->status == 0) {  /* start coroutine? */\n    lua_assert(ci == L->base_ci && firstArg > L->base);\n    if (luaD_precall(L, firstArg - 1, LUA_MULTRET) != PCRLUA)\n      return;\n  }\n  else {  /* resuming from previous yield */\n    lua_assert(L->status == LUA_YIELD);\n    L->status = 0;\n    if (!f_isLua(ci)) {  /* `common' yield? */\n      /* finish interrupted execution of `OP_CALL' */\n      lua_assert(GET_OPCODE(*((ci-1)->savedpc - 1)) == OP_CALL ||\n                 GET_OPCODE(*((ci-1)->savedpc - 1)) == OP_TAILCALL);\n      if (luaD_poscall(L, firstArg))  /* complete it... */\n        L->top = L->ci->top;  /* and correct top if not multiple results */\n    }\n    else  /* yielded inside a hook: just continue its execution */\n      L->base = L->ci->base;\n  }\n  luaV_execute(L, cast_int(L->ci - L->base_ci));\n}\n\n\nstatic int resume_error (lua_State *L, const char *msg) {\n  L->top = L->ci->base;\n  setsvalue2s(L, L->top, luaS_new(L, msg));\n  incr_top(L);\n  lua_unlock(L);\n  return LUA_ERRRUN;\n}\n\n\nLUA_API int lua_resume (lua_State *L, int nargs) {\n  int status;\n  lua_lock(L);\n  if (L->status != LUA_YIELD && (L->status != 0 || L->ci != L->base_ci))\n      return resume_error(L, \"cannot resume non-suspended coroutine\");\n  if (L->nCcalls >= LUAI_MAXCCALLS)\n    return resume_error(L, \"C stack overflow\");\n  luai_userstateresume(L, nargs);\n  lua_assert(L->errfunc == 0);\n  L->baseCcalls = ++L->nCcalls;\n  status = luaD_rawrunprotected(L, resume, L->top - nargs);\n  if (status != 0) {  /* error? */\n    L->status = cast_byte(status);  /* mark thread as `dead' */\n    luaD_seterrorobj(L, status, L->top);\n    L->ci->top = L->top;\n  }\n  else {\n    lua_assert(L->nCcalls == L->baseCcalls);\n    status = L->status;\n  }\n  --L->nCcalls;\n  lua_unlock(L);\n  return status;\n}\n\n\nLUA_API int lua_yield (lua_State *L, int nresults) {\n  luai_userstateyield(L, nresults);\n  lua_lock(L);\n  if (L->nCcalls > L->baseCcalls)\n    luaG_runerror(L, \"attempt to yield across metamethod/C-call boundary\");\n  L->base = L->top - nresults;  /* protect stack slots below */\n  L->status = LUA_YIELD;\n  lua_unlock(L);\n  return -1;\n}\n\n\nint luaD_pcall (lua_State *L, Pfunc func, void *u,\n                ptrdiff_t old_top, ptrdiff_t ef) {\n  int status;\n  unsigned short oldnCcalls = L->nCcalls;\n  ptrdiff_t old_ci = saveci(L, L->ci);\n  lu_byte old_allowhooks = L->allowhook;\n  ptrdiff_t old_errfunc = L->errfunc;\n  L->errfunc = ef;\n  status = luaD_rawrunprotected(L, func, u);\n  if (status != 0) {  /* an error occurred? */\n    StkId oldtop = restorestack(L, old_top);\n    luaF_close(L, oldtop);  /* close eventual pending closures */\n    luaD_seterrorobj(L, status, oldtop);\n    L->nCcalls = oldnCcalls;\n    L->ci = restoreci(L, old_ci);\n    L->base = L->ci->base;\n    L->savedpc = L->ci->savedpc;\n    L->allowhook = old_allowhooks;\n    restore_stack_limit(L);\n  }\n  L->errfunc = old_errfunc;\n  return status;\n}\n\n\n\n/*\n** Execute a protected parser.\n*/\nstruct SParser {  /* data to `f_parser' */\n  ZIO *z;\n  Mbuffer buff;  /* buffer to be used by the scanner */\n  const char *name;\n};\n\nstatic void f_parser (lua_State *L, void *ud) {\n  int i;\n  Proto *tf;\n  Closure *cl;\n  struct SParser *p = cast(struct SParser *, ud);\n  int c = luaZ_lookahead(p->z);\n  luaC_checkGC(L);\n  tf = (luaY_parser)(L, p->z,\n                                                             &p->buff, p->name);\n  cl = luaF_newLclosure(L, tf->nups, hvalue(gt(L)));\n  cl->l.p = tf;\n  for (i = 0; i < tf->nups; i++)  /* initialize eventual upvalues */\n    cl->l.upvals[i] = luaF_newupval(L);\n  setclvalue(L, L->top, cl);\n  incr_top(L);\n}\n\n\nint luaD_protectedparser (lua_State *L, ZIO *z, const char *name) {\n  struct SParser p;\n  int status;\n  p.z = z; p.name = name;\n  luaZ_initbuffer(L, &p.buff);\n  status = luaD_pcall(L, f_parser, &p, savestack(L, L->top), L->errfunc);\n  luaZ_freebuffer(L, &p.buff);\n  return status;\n}\n\n\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/deps/lua/src/ldo.h",
    "content": "/*\n** $Id: ldo.h,v 2.7.1.1 2007/12/27 13:02:25 roberto Exp $\n** Stack and Call structure of Lua\n** See Copyright Notice in lua.h\n*/\n\n#ifndef ldo_h\n#define ldo_h\n\n\n#include \"lobject.h\"\n#include \"lstate.h\"\n#include \"lzio.h\"\n\n\n#define luaD_checkstack(L,n)\t\\\n  if ((char *)L->stack_last - (char *)L->top <= (n)*(int)sizeof(TValue)) \\\n    luaD_growstack(L, n); \\\n  else condhardstacktests(luaD_reallocstack(L, L->stacksize - EXTRA_STACK - 1));\n\n\n#define incr_top(L) {luaD_checkstack(L,1); L->top++;}\n\n#define savestack(L,p)\t\t((char *)(p) - (char *)L->stack)\n#define restorestack(L,n)\t((TValue *)((char *)L->stack + (n)))\n\n#define saveci(L,p)\t\t((char *)(p) - (char *)L->base_ci)\n#define restoreci(L,n)\t\t((CallInfo *)((char *)L->base_ci + (n)))\n\n\n/* results from luaD_precall */\n#define PCRLUA\t\t0\t/* initiated a call to a Lua function */\n#define PCRC\t\t1\t/* did a call to a C function */\n#define PCRYIELD\t2\t/* C funtion yielded */\n\n\n/* type of protected functions, to be ran by `runprotected' */\ntypedef void (*Pfunc) (lua_State *L, void *ud);\n\nLUAI_FUNC int luaD_protectedparser (lua_State *L, ZIO *z, const char *name);\nLUAI_FUNC void luaD_callhook (lua_State *L, int event, int line);\nLUAI_FUNC int luaD_precall (lua_State *L, StkId func, int nresults);\nLUAI_FUNC void luaD_call (lua_State *L, StkId func, int nResults);\nLUAI_FUNC int luaD_pcall (lua_State *L, Pfunc func, void *u,\n                                        ptrdiff_t oldtop, ptrdiff_t ef);\nLUAI_FUNC int luaD_poscall (lua_State *L, StkId firstResult);\nLUAI_FUNC void luaD_reallocCI (lua_State *L, int newsize);\nLUAI_FUNC void luaD_reallocstack (lua_State *L, int newsize);\nLUAI_FUNC void luaD_growstack (lua_State *L, int n);\n\nLUAI_FUNC void luaD_throw (lua_State *L, int errcode);\nLUAI_FUNC int luaD_rawrunprotected (lua_State *L, Pfunc f, void *ud);\n\nLUAI_FUNC void luaD_seterrorobj (lua_State *L, int errcode, StkId oldtop);\n\n#endif\n\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/deps/lua/src/ldump.c",
    "content": "/*\n** $Id: ldump.c,v 2.8.1.1 2007/12/27 13:02:25 roberto Exp $\n** save precompiled Lua chunks\n** See Copyright Notice in lua.h\n*/\n\n#include <stddef.h>\n\n#define ldump_c\n#define LUA_CORE\n\n#include \"lua.h\"\n\n#include \"lobject.h\"\n#include \"lstate.h\"\n#include \"lundump.h\"\n\ntypedef struct {\n lua_State* L;\n lua_Writer writer;\n void* data;\n int strip;\n int status;\n} DumpState;\n\n#define DumpMem(b,n,size,D)\tDumpBlock(b,(n)*(size),D)\n#define DumpVar(x,D)\t \tDumpMem(&x,1,sizeof(x),D)\n\nstatic void DumpBlock(const void* b, size_t size, DumpState* D)\n{\n if (D->status==0)\n {\n  lua_unlock(D->L);\n  D->status=(*D->writer)(D->L,b,size,D->data);\n  lua_lock(D->L);\n }\n}\n\nstatic void DumpChar(int y, DumpState* D)\n{\n char x=(char)y;\n DumpVar(x,D);\n}\n\nstatic void DumpInt(int x, DumpState* D)\n{\n DumpVar(x,D);\n}\n\nstatic void DumpNumber(lua_Number x, DumpState* D)\n{\n DumpVar(x,D);\n}\n\nstatic void DumpVector(const void* b, int n, size_t size, DumpState* D)\n{\n DumpInt(n,D);\n DumpMem(b,n,size,D);\n}\n\nstatic void DumpString(const TString* s, DumpState* D)\n{\n if (s==NULL || getstr(s)==NULL)\n {\n  size_t size=0;\n  DumpVar(size,D);\n }\n else\n {\n  size_t size=s->tsv.len+1;\t\t/* include trailing '\\0' */\n  DumpVar(size,D);\n  DumpBlock(getstr(s),size,D);\n }\n}\n\n#define DumpCode(f,D)\t DumpVector(f->code,f->sizecode,sizeof(Instruction),D)\n\nstatic void DumpFunction(const Proto* f, const TString* p, DumpState* D);\n\nstatic void DumpConstants(const Proto* f, DumpState* D)\n{\n int i,n=f->sizek;\n DumpInt(n,D);\n for (i=0; i<n; i++)\n {\n  const TValue* o=&f->k[i];\n  DumpChar(ttype(o),D);\n  switch (ttype(o))\n  {\n   case LUA_TNIL:\n\tbreak;\n   case LUA_TBOOLEAN:\n\tDumpChar(bvalue(o),D);\n\tbreak;\n   case LUA_TNUMBER:\n\tDumpNumber(nvalue(o),D);\n\tbreak;\n   case LUA_TSTRING:\n\tDumpString(rawtsvalue(o),D);\n\tbreak;\n   default:\n\tlua_assert(0);\t\t\t/* cannot happen */\n\tbreak;\n  }\n }\n n=f->sizep;\n DumpInt(n,D);\n for (i=0; i<n; i++) DumpFunction(f->p[i],f->source,D);\n}\n\nstatic void DumpDebug(const Proto* f, DumpState* D)\n{\n int i,n;\n n= (D->strip) ? 0 : f->sizelineinfo;\n DumpVector(f->lineinfo,n,sizeof(int),D);\n n= (D->strip) ? 0 : f->sizelocvars;\n DumpInt(n,D);\n for (i=0; i<n; i++)\n {\n  DumpString(f->locvars[i].varname,D);\n  DumpInt(f->locvars[i].startpc,D);\n  DumpInt(f->locvars[i].endpc,D);\n }\n n= (D->strip) ? 0 : f->sizeupvalues;\n DumpInt(n,D);\n for (i=0; i<n; i++) DumpString(f->upvalues[i],D);\n}\n\nstatic void DumpFunction(const Proto* f, const TString* p, DumpState* D)\n{\n DumpString((f->source==p || D->strip) ? NULL : f->source,D);\n DumpInt(f->linedefined,D);\n DumpInt(f->lastlinedefined,D);\n DumpChar(f->nups,D);\n DumpChar(f->numparams,D);\n DumpChar(f->is_vararg,D);\n DumpChar(f->maxstacksize,D);\n DumpCode(f,D);\n DumpConstants(f,D);\n DumpDebug(f,D);\n}\n\nstatic void DumpHeader(DumpState* D)\n{\n char h[LUAC_HEADERSIZE];\n luaU_header(h);\n DumpBlock(h,LUAC_HEADERSIZE,D);\n}\n\n/*\n** dump Lua function as precompiled chunk\n*/\nint luaU_dump (lua_State* L, const Proto* f, lua_Writer w, void* data, int strip)\n{\n DumpState D;\n D.L=L;\n D.writer=w;\n D.data=data;\n D.strip=strip;\n D.status=0;\n DumpHeader(&D);\n DumpFunction(f,NULL,&D);\n return D.status;\n}\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/deps/lua/src/lfunc.c",
    "content": "/*\n** $Id: lfunc.c,v 2.12.1.2 2007/12/28 14:58:43 roberto Exp $\n** Auxiliary functions to manipulate prototypes and closures\n** See Copyright Notice in lua.h\n*/\n\n\n#include <stddef.h>\n\n#define lfunc_c\n#define LUA_CORE\n\n#include \"lua.h\"\n\n#include \"lfunc.h\"\n#include \"lgc.h\"\n#include \"lmem.h\"\n#include \"lobject.h\"\n#include \"lstate.h\"\n\n\n\nClosure *luaF_newCclosure (lua_State *L, int nelems, Table *e) {\n  Closure *c = cast(Closure *, luaM_malloc(L, sizeCclosure(nelems)));\n  luaC_link(L, obj2gco(c), LUA_TFUNCTION);\n  c->c.isC = 1;\n  c->c.env = e;\n  c->c.nupvalues = cast_byte(nelems);\n  return c;\n}\n\n\nClosure *luaF_newLclosure (lua_State *L, int nelems, Table *e) {\n  Closure *c = cast(Closure *, luaM_malloc(L, sizeLclosure(nelems)));\n  luaC_link(L, obj2gco(c), LUA_TFUNCTION);\n  c->l.isC = 0;\n  c->l.env = e;\n  c->l.nupvalues = cast_byte(nelems);\n  while (nelems--) c->l.upvals[nelems] = NULL;\n  return c;\n}\n\n\nUpVal *luaF_newupval (lua_State *L) {\n  UpVal *uv = luaM_new(L, UpVal);\n  luaC_link(L, obj2gco(uv), LUA_TUPVAL);\n  uv->v = &uv->u.value;\n  setnilvalue(uv->v);\n  return uv;\n}\n\n\nUpVal *luaF_findupval (lua_State *L, StkId level) {\n  global_State *g = G(L);\n  GCObject **pp = &L->openupval;\n  UpVal *p;\n  UpVal *uv;\n  while (*pp != NULL && (p = ngcotouv(*pp))->v >= level) {\n    lua_assert(p->v != &p->u.value);\n    if (p->v == level) {  /* found a corresponding upvalue? */\n      if (isdead(g, obj2gco(p)))  /* is it dead? */\n        changewhite(obj2gco(p));  /* ressurect it */\n      return p;\n    }\n    pp = &p->next;\n  }\n  uv = luaM_new(L, UpVal);  /* not found: create a new one */\n  uv->tt = LUA_TUPVAL;\n  uv->marked = luaC_white(g);\n  uv->v = level;  /* current value lives in the stack */\n  uv->next = *pp;  /* chain it in the proper position */\n  *pp = obj2gco(uv);\n  uv->u.l.prev = &g->uvhead;  /* double link it in `uvhead' list */\n  uv->u.l.next = g->uvhead.u.l.next;\n  uv->u.l.next->u.l.prev = uv;\n  g->uvhead.u.l.next = uv;\n  lua_assert(uv->u.l.next->u.l.prev == uv && uv->u.l.prev->u.l.next == uv);\n  return uv;\n}\n\n\nstatic void unlinkupval (UpVal *uv) {\n  lua_assert(uv->u.l.next->u.l.prev == uv && uv->u.l.prev->u.l.next == uv);\n  uv->u.l.next->u.l.prev = uv->u.l.prev;  /* remove from `uvhead' list */\n  uv->u.l.prev->u.l.next = uv->u.l.next;\n}\n\n\nvoid luaF_freeupval (lua_State *L, UpVal *uv) {\n  if (uv->v != &uv->u.value)  /* is it open? */\n    unlinkupval(uv);  /* remove from open list */\n  luaM_free(L, uv);  /* free upvalue */\n}\n\n\nvoid luaF_close (lua_State *L, StkId level) {\n  UpVal *uv;\n  global_State *g = G(L);\n  while (L->openupval != NULL && (uv = ngcotouv(L->openupval))->v >= level) {\n    GCObject *o = obj2gco(uv);\n    lua_assert(!isblack(o) && uv->v != &uv->u.value);\n    L->openupval = uv->next;  /* remove from `open' list */\n    if (isdead(g, o))\n      luaF_freeupval(L, uv);  /* free upvalue */\n    else {\n      unlinkupval(uv);\n      setobj(L, &uv->u.value, uv->v);\n      uv->v = &uv->u.value;  /* now current value lives here */\n      luaC_linkupval(L, uv);  /* link upvalue into `gcroot' list */\n    }\n  }\n}\n\n\nProto *luaF_newproto (lua_State *L) {\n  Proto *f = luaM_new(L, Proto);\n  luaC_link(L, obj2gco(f), LUA_TPROTO);\n  f->k = NULL;\n  f->sizek = 0;\n  f->p = NULL;\n  f->sizep = 0;\n  f->code = NULL;\n  f->sizecode = 0;\n  f->sizelineinfo = 0;\n  f->sizeupvalues = 0;\n  f->nups = 0;\n  f->upvalues = NULL;\n  f->numparams = 0;\n  f->is_vararg = 0;\n  f->maxstacksize = 0;\n  f->lineinfo = NULL;\n  f->sizelocvars = 0;\n  f->locvars = NULL;\n  f->linedefined = 0;\n  f->lastlinedefined = 0;\n  f->source = NULL;\n  return f;\n}\n\n\nvoid luaF_freeproto (lua_State *L, Proto *f) {\n  luaM_freearray(L, f->code, f->sizecode, Instruction);\n  luaM_freearray(L, f->p, f->sizep, Proto *);\n  luaM_freearray(L, f->k, f->sizek, TValue);\n  luaM_freearray(L, f->lineinfo, f->sizelineinfo, int);\n  luaM_freearray(L, f->locvars, f->sizelocvars, struct LocVar);\n  luaM_freearray(L, f->upvalues, f->sizeupvalues, TString *);\n  luaM_free(L, f);\n}\n\n\nvoid luaF_freeclosure (lua_State *L, Closure *c) {\n  int size = (c->c.isC) ? sizeCclosure(c->c.nupvalues) :\n                          sizeLclosure(c->l.nupvalues);\n  luaM_freemem(L, c, size);\n}\n\n\n/*\n** Look for n-th local variable at line `line' in function `func'.\n** Returns NULL if not found.\n*/\nconst char *luaF_getlocalname (const Proto *f, int local_number, int pc) {\n  int i;\n  for (i = 0; i<f->sizelocvars && f->locvars[i].startpc <= pc; i++) {\n    if (pc < f->locvars[i].endpc) {  /* is variable active? */\n      local_number--;\n      if (local_number == 0)\n        return getstr(f->locvars[i].varname);\n    }\n  }\n  return NULL;  /* not found */\n}\n\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/deps/lua/src/lfunc.h",
    "content": "/*\n** $Id: lfunc.h,v 2.4.1.1 2007/12/27 13:02:25 roberto Exp $\n** Auxiliary functions to manipulate prototypes and closures\n** See Copyright Notice in lua.h\n*/\n\n#ifndef lfunc_h\n#define lfunc_h\n\n\n#include \"lobject.h\"\n\n\n#define sizeCclosure(n)\t(cast(int, sizeof(CClosure)) + \\\n                         cast(int, sizeof(TValue)*((n)-1)))\n\n#define sizeLclosure(n)\t(cast(int, sizeof(LClosure)) + \\\n                         cast(int, sizeof(TValue *)*((n)-1)))\n\n\nLUAI_FUNC Proto *luaF_newproto (lua_State *L);\nLUAI_FUNC Closure *luaF_newCclosure (lua_State *L, int nelems, Table *e);\nLUAI_FUNC Closure *luaF_newLclosure (lua_State *L, int nelems, Table *e);\nLUAI_FUNC UpVal *luaF_newupval (lua_State *L);\nLUAI_FUNC UpVal *luaF_findupval (lua_State *L, StkId level);\nLUAI_FUNC void luaF_close (lua_State *L, StkId level);\nLUAI_FUNC void luaF_freeproto (lua_State *L, Proto *f);\nLUAI_FUNC void luaF_freeclosure (lua_State *L, Closure *c);\nLUAI_FUNC void luaF_freeupval (lua_State *L, UpVal *uv);\nLUAI_FUNC const char *luaF_getlocalname (const Proto *func, int local_number,\n                                         int pc);\n\n\n#endif\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/deps/lua/src/lgc.c",
    "content": "/*\n** $Id: lgc.c,v 2.38.1.2 2011/03/18 18:05:38 roberto Exp $\n** Garbage Collector\n** See Copyright Notice in lua.h\n*/\n\n#include <string.h>\n\n#define lgc_c\n#define LUA_CORE\n\n#include \"lua.h\"\n\n#include \"ldebug.h\"\n#include \"ldo.h\"\n#include \"lfunc.h\"\n#include \"lgc.h\"\n#include \"lmem.h\"\n#include \"lobject.h\"\n#include \"lstate.h\"\n#include \"lstring.h\"\n#include \"ltable.h\"\n#include \"ltm.h\"\n\n\n#define GCSTEPSIZE\t1024u\n#define GCSWEEPMAX\t40\n#define GCSWEEPCOST\t10\n#define GCFINALIZECOST\t100\n\n\n#define maskmarks\tcast_byte(~(bitmask(BLACKBIT)|WHITEBITS))\n\n#define makewhite(g,x)\t\\\n   ((x)->gch.marked = cast_byte(((x)->gch.marked & maskmarks) | luaC_white(g)))\n\n#define white2gray(x)\treset2bits((x)->gch.marked, WHITE0BIT, WHITE1BIT)\n#define black2gray(x)\tresetbit((x)->gch.marked, BLACKBIT)\n\n#define stringmark(s)\treset2bits((s)->tsv.marked, WHITE0BIT, WHITE1BIT)\n\n\n#define isfinalized(u)\t\ttestbit((u)->marked, FINALIZEDBIT)\n#define markfinalized(u)\tl_setbit((u)->marked, FINALIZEDBIT)\n\n\n#define KEYWEAK         bitmask(KEYWEAKBIT)\n#define VALUEWEAK       bitmask(VALUEWEAKBIT)\n\n\n\n#define markvalue(g,o) { checkconsistency(o); \\\n  if (iscollectable(o) && iswhite(gcvalue(o))) reallymarkobject(g,gcvalue(o)); }\n\n#define markobject(g,t) { if (iswhite(obj2gco(t))) \\\n\t\treallymarkobject(g, obj2gco(t)); }\n\n\n#define setthreshold(g)  (g->GCthreshold = (g->estimate/100) * g->gcpause)\n\n\nstatic void removeentry (Node *n) {\n  lua_assert(ttisnil(gval(n)));\n  if (iscollectable(gkey(n)))\n    setttype(gkey(n), LUA_TDEADKEY);  /* dead key; remove it */\n}\n\n\nstatic void reallymarkobject (global_State *g, GCObject *o) {\n  lua_assert(iswhite(o) && !isdead(g, o));\n  white2gray(o);\n  switch (o->gch.tt) {\n    case LUA_TSTRING: {\n      return;\n    }\n    case LUA_TUSERDATA: {\n      Table *mt = gco2u(o)->metatable;\n      gray2black(o);  /* udata are never gray */\n      if (mt) markobject(g, mt);\n      markobject(g, gco2u(o)->env);\n      return;\n    }\n    case LUA_TUPVAL: {\n      UpVal *uv = gco2uv(o);\n      markvalue(g, uv->v);\n      if (uv->v == &uv->u.value)  /* closed? */\n        gray2black(o);  /* open upvalues are never black */\n      return;\n    }\n    case LUA_TFUNCTION: {\n      gco2cl(o)->c.gclist = g->gray;\n      g->gray = o;\n      break;\n    }\n    case LUA_TTABLE: {\n      gco2h(o)->gclist = g->gray;\n      g->gray = o;\n      break;\n    }\n    case LUA_TTHREAD: {\n      gco2th(o)->gclist = g->gray;\n      g->gray = o;\n      break;\n    }\n    case LUA_TPROTO: {\n      gco2p(o)->gclist = g->gray;\n      g->gray = o;\n      break;\n    }\n    default: lua_assert(0);\n  }\n}\n\n\nstatic void marktmu (global_State *g) {\n  GCObject *u = g->tmudata;\n  if (u) {\n    do {\n      u = u->gch.next;\n      makewhite(g, u);  /* may be marked, if left from previous GC */\n      reallymarkobject(g, u);\n    } while (u != g->tmudata);\n  }\n}\n\n\n/* move `dead' udata that need finalization to list `tmudata' */\nsize_t luaC_separateudata (lua_State *L, int all) {\n  global_State *g = G(L);\n  size_t deadmem = 0;\n  GCObject **p = &g->mainthread->next;\n  GCObject *curr;\n  while ((curr = *p) != NULL) {\n    if (!(iswhite(curr) || all) || isfinalized(gco2u(curr)))\n      p = &curr->gch.next;  /* don't bother with them */\n    else if (fasttm(L, gco2u(curr)->metatable, TM_GC) == NULL) {\n      markfinalized(gco2u(curr));  /* don't need finalization */\n      p = &curr->gch.next;\n    }\n    else {  /* must call its gc method */\n      deadmem += sizeudata(gco2u(curr));\n      markfinalized(gco2u(curr));\n      *p = curr->gch.next;\n      /* link `curr' at the end of `tmudata' list */\n      if (g->tmudata == NULL)  /* list is empty? */\n        g->tmudata = curr->gch.next = curr;  /* creates a circular list */\n      else {\n        curr->gch.next = g->tmudata->gch.next;\n        g->tmudata->gch.next = curr;\n        g->tmudata = curr;\n      }\n    }\n  }\n  return deadmem;\n}\n\n\nstatic int traversetable (global_State *g, Table *h) {\n  int i;\n  int weakkey = 0;\n  int weakvalue = 0;\n  const TValue *mode;\n  if (h->metatable)\n    markobject(g, h->metatable);\n  mode = gfasttm(g, h->metatable, TM_MODE);\n  if (mode && ttisstring(mode)) {  /* is there a weak mode? */\n    weakkey = (strchr(svalue(mode), 'k') != NULL);\n    weakvalue = (strchr(svalue(mode), 'v') != NULL);\n    if (weakkey || weakvalue) {  /* is really weak? */\n      h->marked &= ~(KEYWEAK | VALUEWEAK);  /* clear bits */\n      h->marked |= cast_byte((weakkey << KEYWEAKBIT) |\n                             (weakvalue << VALUEWEAKBIT));\n      h->gclist = g->weak;  /* must be cleared after GC, ... */\n      g->weak = obj2gco(h);  /* ... so put in the appropriate list */\n    }\n  }\n  if (weakkey && weakvalue) return 1;\n  if (!weakvalue) {\n    i = h->sizearray;\n    while (i--)\n      markvalue(g, &h->array[i]);\n  }\n  i = sizenode(h);\n  while (i--) {\n    Node *n = gnode(h, i);\n    lua_assert(ttype(gkey(n)) != LUA_TDEADKEY || ttisnil(gval(n)));\n    if (ttisnil(gval(n)))\n      removeentry(n);  /* remove empty entries */\n    else {\n      lua_assert(!ttisnil(gkey(n)));\n      if (!weakkey) markvalue(g, gkey(n));\n      if (!weakvalue) markvalue(g, gval(n));\n    }\n  }\n  return weakkey || weakvalue;\n}\n\n\n/*\n** All marks are conditional because a GC may happen while the\n** prototype is still being created\n*/\nstatic void traverseproto (global_State *g, Proto *f) {\n  int i;\n  if (f->source) stringmark(f->source);\n  for (i=0; i<f->sizek; i++)  /* mark literals */\n    markvalue(g, &f->k[i]);\n  for (i=0; i<f->sizeupvalues; i++) {  /* mark upvalue names */\n    if (f->upvalues[i])\n      stringmark(f->upvalues[i]);\n  }\n  for (i=0; i<f->sizep; i++) {  /* mark nested protos */\n    if (f->p[i])\n      markobject(g, f->p[i]);\n  }\n  for (i=0; i<f->sizelocvars; i++) {  /* mark local-variable names */\n    if (f->locvars[i].varname)\n      stringmark(f->locvars[i].varname);\n  }\n}\n\n\n\nstatic void traverseclosure (global_State *g, Closure *cl) {\n  markobject(g, cl->c.env);\n  if (cl->c.isC) {\n    int i;\n    for (i=0; i<cl->c.nupvalues; i++)  /* mark its upvalues */\n      markvalue(g, &cl->c.upvalue[i]);\n  }\n  else {\n    int i;\n    lua_assert(cl->l.nupvalues == cl->l.p->nups);\n    markobject(g, cl->l.p);\n    for (i=0; i<cl->l.nupvalues; i++)  /* mark its upvalues */\n      markobject(g, cl->l.upvals[i]);\n  }\n}\n\n\nstatic void checkstacksizes (lua_State *L, StkId max) {\n  int ci_used = cast_int(L->ci - L->base_ci);  /* number of `ci' in use */\n  int s_used = cast_int(max - L->stack);  /* part of stack in use */\n  if (L->size_ci > LUAI_MAXCALLS)  /* handling overflow? */\n    return;  /* do not touch the stacks */\n  if (4*ci_used < L->size_ci && 2*BASIC_CI_SIZE < L->size_ci)\n    luaD_reallocCI(L, L->size_ci/2);  /* still big enough... */\n  condhardstacktests(luaD_reallocCI(L, ci_used + 1));\n  if (4*s_used < L->stacksize &&\n      2*(BASIC_STACK_SIZE+EXTRA_STACK) < L->stacksize)\n    luaD_reallocstack(L, L->stacksize/2);  /* still big enough... */\n  condhardstacktests(luaD_reallocstack(L, s_used));\n}\n\n\nstatic void traversestack (global_State *g, lua_State *l) {\n  StkId o, lim;\n  CallInfo *ci;\n  markvalue(g, gt(l));\n  lim = l->top;\n  for (ci = l->base_ci; ci <= l->ci; ci++) {\n    lua_assert(ci->top <= l->stack_last);\n    if (lim < ci->top) lim = ci->top;\n  }\n  for (o = l->stack; o < l->top; o++)\n    markvalue(g, o);\n  for (; o <= lim; o++)\n    setnilvalue(o);\n  checkstacksizes(l, lim);\n}\n\n\n/*\n** traverse one gray object, turning it to black.\n** Returns `quantity' traversed.\n*/\nstatic l_mem propagatemark (global_State *g) {\n  GCObject *o = g->gray;\n  lua_assert(isgray(o));\n  gray2black(o);\n  switch (o->gch.tt) {\n    case LUA_TTABLE: {\n      Table *h = gco2h(o);\n      g->gray = h->gclist;\n      if (traversetable(g, h))  /* table is weak? */\n        black2gray(o);  /* keep it gray */\n      return sizeof(Table) + sizeof(TValue) * h->sizearray +\n                             sizeof(Node) * sizenode(h);\n    }\n    case LUA_TFUNCTION: {\n      Closure *cl = gco2cl(o);\n      g->gray = cl->c.gclist;\n      traverseclosure(g, cl);\n      return (cl->c.isC) ? sizeCclosure(cl->c.nupvalues) :\n                           sizeLclosure(cl->l.nupvalues);\n    }\n    case LUA_TTHREAD: {\n      lua_State *th = gco2th(o);\n      g->gray = th->gclist;\n      th->gclist = g->grayagain;\n      g->grayagain = o;\n      black2gray(o);\n      traversestack(g, th);\n      return sizeof(lua_State) + sizeof(TValue) * th->stacksize +\n                                 sizeof(CallInfo) * th->size_ci;\n    }\n    case LUA_TPROTO: {\n      Proto *p = gco2p(o);\n      g->gray = p->gclist;\n      traverseproto(g, p);\n      return sizeof(Proto) + sizeof(Instruction) * p->sizecode +\n                             sizeof(Proto *) * p->sizep +\n                             sizeof(TValue) * p->sizek + \n                             sizeof(int) * p->sizelineinfo +\n                             sizeof(LocVar) * p->sizelocvars +\n                             sizeof(TString *) * p->sizeupvalues;\n    }\n    default: lua_assert(0); return 0;\n  }\n}\n\n\nstatic size_t propagateall (global_State *g) {\n  size_t m = 0;\n  while (g->gray) m += propagatemark(g);\n  return m;\n}\n\n\n/*\n** The next function tells whether a key or value can be cleared from\n** a weak table. Non-collectable objects are never removed from weak\n** tables. Strings behave as `values', so are never removed too. for\n** other objects: if really collected, cannot keep them; for userdata\n** being finalized, keep them in keys, but not in values\n*/\nstatic int iscleared (const TValue *o, int iskey) {\n  if (!iscollectable(o)) return 0;\n  if (ttisstring(o)) {\n    stringmark(rawtsvalue(o));  /* strings are `values', so are never weak */\n    return 0;\n  }\n  return iswhite(gcvalue(o)) ||\n    (ttisuserdata(o) && (!iskey && isfinalized(uvalue(o))));\n}\n\n\n/*\n** clear collected entries from weaktables\n*/\nstatic void cleartable (GCObject *l) {\n  while (l) {\n    Table *h = gco2h(l);\n    int i = h->sizearray;\n    lua_assert(testbit(h->marked, VALUEWEAKBIT) ||\n               testbit(h->marked, KEYWEAKBIT));\n    if (testbit(h->marked, VALUEWEAKBIT)) {\n      while (i--) {\n        TValue *o = &h->array[i];\n        if (iscleared(o, 0))  /* value was collected? */\n          setnilvalue(o);  /* remove value */\n      }\n    }\n    i = sizenode(h);\n    while (i--) {\n      Node *n = gnode(h, i);\n      if (!ttisnil(gval(n)) &&  /* non-empty entry? */\n          (iscleared(key2tval(n), 1) || iscleared(gval(n), 0))) {\n        setnilvalue(gval(n));  /* remove value ... */\n        removeentry(n);  /* remove entry from table */\n      }\n    }\n    l = h->gclist;\n  }\n}\n\n\nstatic void freeobj (lua_State *L, GCObject *o) {\n  switch (o->gch.tt) {\n    case LUA_TPROTO: luaF_freeproto(L, gco2p(o)); break;\n    case LUA_TFUNCTION: luaF_freeclosure(L, gco2cl(o)); break;\n    case LUA_TUPVAL: luaF_freeupval(L, gco2uv(o)); break;\n    case LUA_TTABLE: luaH_free(L, gco2h(o)); break;\n    case LUA_TTHREAD: {\n      lua_assert(gco2th(o) != L && gco2th(o) != G(L)->mainthread);\n      luaE_freethread(L, gco2th(o));\n      break;\n    }\n    case LUA_TSTRING: {\n      G(L)->strt.nuse--;\n      luaM_freemem(L, o, sizestring(gco2ts(o)));\n      break;\n    }\n    case LUA_TUSERDATA: {\n      luaM_freemem(L, o, sizeudata(gco2u(o)));\n      break;\n    }\n    default: lua_assert(0);\n  }\n}\n\n\n\n#define sweepwholelist(L,p)\tsweeplist(L,p,MAX_LUMEM)\n\n\nstatic GCObject **sweeplist (lua_State *L, GCObject **p, lu_mem count) {\n  GCObject *curr;\n  global_State *g = G(L);\n  int deadmask = otherwhite(g);\n  while ((curr = *p) != NULL && count-- > 0) {\n    if (curr->gch.tt == LUA_TTHREAD)  /* sweep open upvalues of each thread */\n      sweepwholelist(L, &gco2th(curr)->openupval);\n    if ((curr->gch.marked ^ WHITEBITS) & deadmask) {  /* not dead? */\n      lua_assert(!isdead(g, curr) || testbit(curr->gch.marked, FIXEDBIT));\n      makewhite(g, curr);  /* make it white (for next cycle) */\n      p = &curr->gch.next;\n    }\n    else {  /* must erase `curr' */\n      lua_assert(isdead(g, curr) || deadmask == bitmask(SFIXEDBIT));\n      *p = curr->gch.next;\n      if (curr == g->rootgc)  /* is the first element of the list? */\n        g->rootgc = curr->gch.next;  /* adjust first */\n      freeobj(L, curr);\n    }\n  }\n  return p;\n}\n\n\nstatic void checkSizes (lua_State *L) {\n  global_State *g = G(L);\n  /* check size of string hash */\n  if (g->strt.nuse < cast(lu_int32, g->strt.size/4) &&\n      g->strt.size > MINSTRTABSIZE*2)\n    luaS_resize(L, g->strt.size/2);  /* table is too big */\n  /* check size of buffer */\n  if (luaZ_sizebuffer(&g->buff) > LUA_MINBUFFER*2) {  /* buffer too big? */\n    size_t newsize = luaZ_sizebuffer(&g->buff) / 2;\n    luaZ_resizebuffer(L, &g->buff, newsize);\n  }\n}\n\n\nstatic void GCTM (lua_State *L) {\n  global_State *g = G(L);\n  GCObject *o = g->tmudata->gch.next;  /* get first element */\n  Udata *udata = rawgco2u(o);\n  const TValue *tm;\n  /* remove udata from `tmudata' */\n  if (o == g->tmudata)  /* last element? */\n    g->tmudata = NULL;\n  else\n    g->tmudata->gch.next = udata->uv.next;\n  udata->uv.next = g->mainthread->next;  /* return it to `root' list */\n  g->mainthread->next = o;\n  makewhite(g, o);\n  tm = fasttm(L, udata->uv.metatable, TM_GC);\n  if (tm != NULL) {\n    lu_byte oldah = L->allowhook;\n    lu_mem oldt = g->GCthreshold;\n    L->allowhook = 0;  /* stop debug hooks during GC tag method */\n    g->GCthreshold = 2*g->totalbytes;  /* avoid GC steps */\n    setobj2s(L, L->top, tm);\n    setuvalue(L, L->top+1, udata);\n    L->top += 2;\n    luaD_call(L, L->top - 2, 0);\n    L->allowhook = oldah;  /* restore hooks */\n    g->GCthreshold = oldt;  /* restore threshold */\n  }\n}\n\n\n/*\n** Call all GC tag methods\n*/\nvoid luaC_callGCTM (lua_State *L) {\n  while (G(L)->tmudata)\n    GCTM(L);\n}\n\n\nvoid luaC_freeall (lua_State *L) {\n  global_State *g = G(L);\n  int i;\n  g->currentwhite = WHITEBITS | bitmask(SFIXEDBIT);  /* mask to collect all elements */\n  sweepwholelist(L, &g->rootgc);\n  for (i = 0; i < g->strt.size; i++)  /* free all string lists */\n    sweepwholelist(L, &g->strt.hash[i]);\n}\n\n\nstatic void markmt (global_State *g) {\n  int i;\n  for (i=0; i<NUM_TAGS; i++)\n    if (g->mt[i]) markobject(g, g->mt[i]);\n}\n\n\n/* mark root set */\nstatic void markroot (lua_State *L) {\n  global_State *g = G(L);\n  g->gray = NULL;\n  g->grayagain = NULL;\n  g->weak = NULL;\n  markobject(g, g->mainthread);\n  /* make global table be traversed before main stack */\n  markvalue(g, gt(g->mainthread));\n  markvalue(g, registry(L));\n  markmt(g);\n  g->gcstate = GCSpropagate;\n}\n\n\nstatic void remarkupvals (global_State *g) {\n  UpVal *uv;\n  for (uv = g->uvhead.u.l.next; uv != &g->uvhead; uv = uv->u.l.next) {\n    lua_assert(uv->u.l.next->u.l.prev == uv && uv->u.l.prev->u.l.next == uv);\n    if (isgray(obj2gco(uv)))\n      markvalue(g, uv->v);\n  }\n}\n\n\nstatic void atomic (lua_State *L) {\n  global_State *g = G(L);\n  size_t udsize;  /* total size of userdata to be finalized */\n  /* remark occasional upvalues of (maybe) dead threads */\n  remarkupvals(g);\n  /* traverse objects cautch by write barrier and by 'remarkupvals' */\n  propagateall(g);\n  /* remark weak tables */\n  g->gray = g->weak;\n  g->weak = NULL;\n  lua_assert(!iswhite(obj2gco(g->mainthread)));\n  markobject(g, L);  /* mark running thread */\n  markmt(g);  /* mark basic metatables (again) */\n  propagateall(g);\n  /* remark gray again */\n  g->gray = g->grayagain;\n  g->grayagain = NULL;\n  propagateall(g);\n  udsize = luaC_separateudata(L, 0);  /* separate userdata to be finalized */\n  marktmu(g);  /* mark `preserved' userdata */\n  udsize += propagateall(g);  /* remark, to propagate `preserveness' */\n  cleartable(g->weak);  /* remove collected objects from weak tables */\n  /* flip current white */\n  g->currentwhite = cast_byte(otherwhite(g));\n  g->sweepstrgc = 0;\n  g->sweepgc = &g->rootgc;\n  g->gcstate = GCSsweepstring;\n  g->estimate = g->totalbytes - udsize;  /* first estimate */\n}\n\n\nstatic l_mem singlestep (lua_State *L) {\n  global_State *g = G(L);\n  /*lua_checkmemory(L);*/\n  switch (g->gcstate) {\n    case GCSpause: {\n      markroot(L);  /* start a new collection */\n      return 0;\n    }\n    case GCSpropagate: {\n      if (g->gray)\n        return propagatemark(g);\n      else {  /* no more `gray' objects */\n        atomic(L);  /* finish mark phase */\n        return 0;\n      }\n    }\n    case GCSsweepstring: {\n      lu_mem old = g->totalbytes;\n      sweepwholelist(L, &g->strt.hash[g->sweepstrgc++]);\n      if (g->sweepstrgc >= g->strt.size)  /* nothing more to sweep? */\n        g->gcstate = GCSsweep;  /* end sweep-string phase */\n      lua_assert(old >= g->totalbytes);\n      g->estimate -= old - g->totalbytes;\n      return GCSWEEPCOST;\n    }\n    case GCSsweep: {\n      lu_mem old = g->totalbytes;\n      g->sweepgc = sweeplist(L, g->sweepgc, GCSWEEPMAX);\n      if (*g->sweepgc == NULL) {  /* nothing more to sweep? */\n        checkSizes(L);\n        g->gcstate = GCSfinalize;  /* end sweep phase */\n      }\n      lua_assert(old >= g->totalbytes);\n      g->estimate -= old - g->totalbytes;\n      return GCSWEEPMAX*GCSWEEPCOST;\n    }\n    case GCSfinalize: {\n      if (g->tmudata) {\n        GCTM(L);\n        if (g->estimate > GCFINALIZECOST)\n          g->estimate -= GCFINALIZECOST;\n        return GCFINALIZECOST;\n      }\n      else {\n        g->gcstate = GCSpause;  /* end collection */\n        g->gcdept = 0;\n        return 0;\n      }\n    }\n    default: lua_assert(0); return 0;\n  }\n}\n\n\nvoid luaC_step (lua_State *L) {\n  global_State *g = G(L);\n  l_mem lim = (GCSTEPSIZE/100) * g->gcstepmul;\n  if (lim == 0)\n    lim = (MAX_LUMEM-1)/2;  /* no limit */\n  g->gcdept += g->totalbytes - g->GCthreshold;\n  do {\n    lim -= singlestep(L);\n    if (g->gcstate == GCSpause)\n      break;\n  } while (lim > 0);\n  if (g->gcstate != GCSpause) {\n    if (g->gcdept < GCSTEPSIZE)\n      g->GCthreshold = g->totalbytes + GCSTEPSIZE;  /* - lim/g->gcstepmul;*/\n    else {\n      g->gcdept -= GCSTEPSIZE;\n      g->GCthreshold = g->totalbytes;\n    }\n  }\n  else {\n    setthreshold(g);\n  }\n}\n\n\nvoid luaC_fullgc (lua_State *L) {\n  global_State *g = G(L);\n  if (g->gcstate <= GCSpropagate) {\n    /* reset sweep marks to sweep all elements (returning them to white) */\n    g->sweepstrgc = 0;\n    g->sweepgc = &g->rootgc;\n    /* reset other collector lists */\n    g->gray = NULL;\n    g->grayagain = NULL;\n    g->weak = NULL;\n    g->gcstate = GCSsweepstring;\n  }\n  lua_assert(g->gcstate != GCSpause && g->gcstate != GCSpropagate);\n  /* finish any pending sweep phase */\n  while (g->gcstate != GCSfinalize) {\n    lua_assert(g->gcstate == GCSsweepstring || g->gcstate == GCSsweep);\n    singlestep(L);\n  }\n  markroot(L);\n  while (g->gcstate != GCSpause) {\n    singlestep(L);\n  }\n  setthreshold(g);\n}\n\n\nvoid luaC_barrierf (lua_State *L, GCObject *o, GCObject *v) {\n  global_State *g = G(L);\n  lua_assert(isblack(o) && iswhite(v) && !isdead(g, v) && !isdead(g, o));\n  lua_assert(g->gcstate != GCSfinalize && g->gcstate != GCSpause);\n  lua_assert(ttype(&o->gch) != LUA_TTABLE);\n  /* must keep invariant? */\n  if (g->gcstate == GCSpropagate)\n    reallymarkobject(g, v);  /* restore invariant */\n  else  /* don't mind */\n    makewhite(g, o);  /* mark as white just to avoid other barriers */\n}\n\n\nvoid luaC_barrierback (lua_State *L, Table *t) {\n  global_State *g = G(L);\n  GCObject *o = obj2gco(t);\n  lua_assert(isblack(o) && !isdead(g, o));\n  lua_assert(g->gcstate != GCSfinalize && g->gcstate != GCSpause);\n  black2gray(o);  /* make table gray (again) */\n  t->gclist = g->grayagain;\n  g->grayagain = o;\n}\n\n\nvoid luaC_link (lua_State *L, GCObject *o, lu_byte tt) {\n  global_State *g = G(L);\n  o->gch.next = g->rootgc;\n  g->rootgc = o;\n  o->gch.marked = luaC_white(g);\n  o->gch.tt = tt;\n}\n\n\nvoid luaC_linkupval (lua_State *L, UpVal *uv) {\n  global_State *g = G(L);\n  GCObject *o = obj2gco(uv);\n  o->gch.next = g->rootgc;  /* link upvalue into `rootgc' list */\n  g->rootgc = o;\n  if (isgray(o)) { \n    if (g->gcstate == GCSpropagate) {\n      gray2black(o);  /* closed upvalues need barrier */\n      luaC_barrier(L, uv, uv->v);\n    }\n    else {  /* sweep phase: sweep it (turning it into white) */\n      makewhite(g, o);\n      lua_assert(g->gcstate != GCSfinalize && g->gcstate != GCSpause);\n    }\n  }\n}\n\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/deps/lua/src/lgc.h",
    "content": "/*\n** $Id: lgc.h,v 2.15.1.1 2007/12/27 13:02:25 roberto Exp $\n** Garbage Collector\n** See Copyright Notice in lua.h\n*/\n\n#ifndef lgc_h\n#define lgc_h\n\n\n#include \"lobject.h\"\n\n\n/*\n** Possible states of the Garbage Collector\n*/\n#define GCSpause\t0\n#define GCSpropagate\t1\n#define GCSsweepstring\t2\n#define GCSsweep\t3\n#define GCSfinalize\t4\n\n\n/*\n** some userful bit tricks\n*/\n#define resetbits(x,m)\t((x) &= cast(lu_byte, ~(m)))\n#define setbits(x,m)\t((x) |= (m))\n#define testbits(x,m)\t((x) & (m))\n#define bitmask(b)\t(1<<(b))\n#define bit2mask(b1,b2)\t(bitmask(b1) | bitmask(b2))\n#define l_setbit(x,b)\tsetbits(x, bitmask(b))\n#define resetbit(x,b)\tresetbits(x, bitmask(b))\n#define testbit(x,b)\ttestbits(x, bitmask(b))\n#define set2bits(x,b1,b2)\tsetbits(x, (bit2mask(b1, b2)))\n#define reset2bits(x,b1,b2)\tresetbits(x, (bit2mask(b1, b2)))\n#define test2bits(x,b1,b2)\ttestbits(x, (bit2mask(b1, b2)))\n\n\n\n/*\n** Layout for bit use in `marked' field:\n** bit 0 - object is white (type 0)\n** bit 1 - object is white (type 1)\n** bit 2 - object is black\n** bit 3 - for userdata: has been finalized\n** bit 3 - for tables: has weak keys\n** bit 4 - for tables: has weak values\n** bit 5 - object is fixed (should not be collected)\n** bit 6 - object is \"super\" fixed (only the main thread)\n*/\n\n\n#define WHITE0BIT\t0\n#define WHITE1BIT\t1\n#define BLACKBIT\t2\n#define FINALIZEDBIT\t3\n#define KEYWEAKBIT\t3\n#define VALUEWEAKBIT\t4\n#define FIXEDBIT\t5\n#define SFIXEDBIT\t6\n#define WHITEBITS\tbit2mask(WHITE0BIT, WHITE1BIT)\n\n\n#define iswhite(x)      test2bits((x)->gch.marked, WHITE0BIT, WHITE1BIT)\n#define isblack(x)      testbit((x)->gch.marked, BLACKBIT)\n#define isgray(x)\t(!isblack(x) && !iswhite(x))\n\n#define otherwhite(g)\t(g->currentwhite ^ WHITEBITS)\n#define isdead(g,v)\t((v)->gch.marked & otherwhite(g) & WHITEBITS)\n\n#define changewhite(x)\t((x)->gch.marked ^= WHITEBITS)\n#define gray2black(x)\tl_setbit((x)->gch.marked, BLACKBIT)\n\n#define valiswhite(x)\t(iscollectable(x) && iswhite(gcvalue(x)))\n\n#define luaC_white(g)\tcast(lu_byte, (g)->currentwhite & WHITEBITS)\n\n\n#define luaC_checkGC(L) { \\\n  condhardstacktests(luaD_reallocstack(L, L->stacksize - EXTRA_STACK - 1)); \\\n  if (G(L)->totalbytes >= G(L)->GCthreshold) \\\n\tluaC_step(L); }\n\n\n#define luaC_barrier(L,p,v) { if (valiswhite(v) && isblack(obj2gco(p)))  \\\n\tluaC_barrierf(L,obj2gco(p),gcvalue(v)); }\n\n#define luaC_barriert(L,t,v) { if (valiswhite(v) && isblack(obj2gco(t)))  \\\n\tluaC_barrierback(L,t); }\n\n#define luaC_objbarrier(L,p,o)  \\\n\t{ if (iswhite(obj2gco(o)) && isblack(obj2gco(p))) \\\n\t\tluaC_barrierf(L,obj2gco(p),obj2gco(o)); }\n\n#define luaC_objbarriert(L,t,o)  \\\n   { if (iswhite(obj2gco(o)) && isblack(obj2gco(t))) luaC_barrierback(L,t); }\n\nLUAI_FUNC size_t luaC_separateudata (lua_State *L, int all);\nLUAI_FUNC void luaC_callGCTM (lua_State *L);\nLUAI_FUNC void luaC_freeall (lua_State *L);\nLUAI_FUNC void luaC_step (lua_State *L);\nLUAI_FUNC void luaC_fullgc (lua_State *L);\nLUAI_FUNC void luaC_link (lua_State *L, GCObject *o, lu_byte tt);\nLUAI_FUNC void luaC_linkupval (lua_State *L, UpVal *uv);\nLUAI_FUNC void luaC_barrierf (lua_State *L, GCObject *o, GCObject *v);\nLUAI_FUNC void luaC_barrierback (lua_State *L, Table *t);\n\n\n#endif\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/deps/lua/src/linit.c",
    "content": "/*\n** $Id: linit.c,v 1.14.1.1 2007/12/27 13:02:25 roberto Exp $\n** Initialization of libraries for lua.c\n** See Copyright Notice in lua.h\n*/\n\n\n#define linit_c\n#define LUA_LIB\n\n#include \"lua.h\"\n\n#include \"lualib.h\"\n#include \"lauxlib.h\"\n\n\nstatic const luaL_Reg lualibs[] = {\n  {\"\", luaopen_base},\n  {LUA_LOADLIBNAME, luaopen_package},\n  {LUA_TABLIBNAME, luaopen_table},\n  {LUA_IOLIBNAME, luaopen_io},\n  {LUA_OSLIBNAME, luaopen_os},\n  {LUA_STRLIBNAME, luaopen_string},\n  {LUA_MATHLIBNAME, luaopen_math},\n  {LUA_DBLIBNAME, luaopen_debug},\n  {NULL, NULL}\n};\n\n\nLUALIB_API void luaL_openlibs (lua_State *L) {\n  const luaL_Reg *lib = lualibs;\n  for (; lib->func; lib++) {\n    lua_pushcfunction(L, lib->func);\n    lua_pushstring(L, lib->name);\n    lua_call(L, 1, 0);\n  }\n}\n\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/deps/lua/src/liolib.c",
    "content": "/*\n** $Id: liolib.c,v 2.73.1.4 2010/05/14 15:33:51 roberto Exp $\n** Standard I/O (and system) library\n** See Copyright Notice in lua.h\n*/\n\n\n#include <errno.h>\n#include <stdio.h>\n#include <stdlib.h>\n#include <string.h>\n\n#define liolib_c\n#define LUA_LIB\n\n#include \"lua.h\"\n\n#include \"lauxlib.h\"\n#include \"lualib.h\"\n\n\n\n#define IO_INPUT\t1\n#define IO_OUTPUT\t2\n\n\nstatic const char *const fnames[] = {\"input\", \"output\"};\n\n\nstatic int pushresult (lua_State *L, int i, const char *filename) {\n  int en = errno;  /* calls to Lua API may change this value */\n  if (i) {\n    lua_pushboolean(L, 1);\n    return 1;\n  }\n  else {\n    lua_pushnil(L);\n    if (filename)\n      lua_pushfstring(L, \"%s: %s\", filename, strerror(en));\n    else\n      lua_pushfstring(L, \"%s\", strerror(en));\n    lua_pushinteger(L, en);\n    return 3;\n  }\n}\n\n\nstatic void fileerror (lua_State *L, int arg, const char *filename) {\n  lua_pushfstring(L, \"%s: %s\", filename, strerror(errno));\n  luaL_argerror(L, arg, lua_tostring(L, -1));\n}\n\n\n#define tofilep(L)\t((FILE **)luaL_checkudata(L, 1, LUA_FILEHANDLE))\n\n\nstatic int io_type (lua_State *L) {\n  void *ud;\n  luaL_checkany(L, 1);\n  ud = lua_touserdata(L, 1);\n  lua_getfield(L, LUA_REGISTRYINDEX, LUA_FILEHANDLE);\n  if (ud == NULL || !lua_getmetatable(L, 1) || !lua_rawequal(L, -2, -1))\n    lua_pushnil(L);  /* not a file */\n  else if (*((FILE **)ud) == NULL)\n    lua_pushliteral(L, \"closed file\");\n  else\n    lua_pushliteral(L, \"file\");\n  return 1;\n}\n\n\nstatic FILE *tofile (lua_State *L) {\n  FILE **f = tofilep(L);\n  if (*f == NULL)\n    luaL_error(L, \"attempt to use a closed file\");\n  return *f;\n}\n\n\n\n/*\n** When creating file handles, always creates a `closed' file handle\n** before opening the actual file; so, if there is a memory error, the\n** file is not left opened.\n*/\nstatic FILE **newfile (lua_State *L) {\n  FILE **pf = (FILE **)lua_newuserdata(L, sizeof(FILE *));\n  *pf = NULL;  /* file handle is currently `closed' */\n  luaL_getmetatable(L, LUA_FILEHANDLE);\n  lua_setmetatable(L, -2);\n  return pf;\n}\n\n\n/*\n** function to (not) close the standard files stdin, stdout, and stderr\n*/\nstatic int io_noclose (lua_State *L) {\n  lua_pushnil(L);\n  lua_pushliteral(L, \"cannot close standard file\");\n  return 2;\n}\n\n\n/*\n** function to close 'popen' files\n*/\nstatic int io_pclose (lua_State *L) {\n  FILE **p = tofilep(L);\n  int ok = lua_pclose(L, *p);\n  *p = NULL;\n  return pushresult(L, ok, NULL);\n}\n\n\n/*\n** function to close regular files\n*/\nstatic int io_fclose (lua_State *L) {\n  FILE **p = tofilep(L);\n  int ok = (fclose(*p) == 0);\n  *p = NULL;\n  return pushresult(L, ok, NULL);\n}\n\n\nstatic int aux_close (lua_State *L) {\n  lua_getfenv(L, 1);\n  lua_getfield(L, -1, \"__close\");\n  return (lua_tocfunction(L, -1))(L);\n}\n\n\nstatic int io_close (lua_State *L) {\n  if (lua_isnone(L, 1))\n    lua_rawgeti(L, LUA_ENVIRONINDEX, IO_OUTPUT);\n  tofile(L);  /* make sure argument is a file */\n  return aux_close(L);\n}\n\n\nstatic int io_gc (lua_State *L) {\n  FILE *f = *tofilep(L);\n  /* ignore closed files */\n  if (f != NULL)\n    aux_close(L);\n  return 0;\n}\n\n\nstatic int io_tostring (lua_State *L) {\n  FILE *f = *tofilep(L);\n  if (f == NULL)\n    lua_pushliteral(L, \"file (closed)\");\n  else\n    lua_pushfstring(L, \"file (%p)\", f);\n  return 1;\n}\n\n\nstatic int io_open (lua_State *L) {\n  const char *filename = luaL_checkstring(L, 1);\n  const char *mode = luaL_optstring(L, 2, \"r\");\n  FILE **pf = newfile(L);\n  *pf = fopen(filename, mode);\n  return (*pf == NULL) ? pushresult(L, 0, filename) : 1;\n}\n\n\n/*\n** this function has a separated environment, which defines the\n** correct __close for 'popen' files\n*/\nstatic int io_popen (lua_State *L) {\n  const char *filename = luaL_checkstring(L, 1);\n  const char *mode = luaL_optstring(L, 2, \"r\");\n  FILE **pf = newfile(L);\n  *pf = lua_popen(L, filename, mode);\n  return (*pf == NULL) ? pushresult(L, 0, filename) : 1;\n}\n\n\nstatic int io_tmpfile (lua_State *L) {\n  FILE **pf = newfile(L);\n  *pf = tmpfile();\n  return (*pf == NULL) ? pushresult(L, 0, NULL) : 1;\n}\n\n\nstatic FILE *getiofile (lua_State *L, int findex) {\n  FILE *f;\n  lua_rawgeti(L, LUA_ENVIRONINDEX, findex);\n  f = *(FILE **)lua_touserdata(L, -1);\n  if (f == NULL)\n    luaL_error(L, \"standard %s file is closed\", fnames[findex - 1]);\n  return f;\n}\n\n\nstatic int g_iofile (lua_State *L, int f, const char *mode) {\n  if (!lua_isnoneornil(L, 1)) {\n    const char *filename = lua_tostring(L, 1);\n    if (filename) {\n      FILE **pf = newfile(L);\n      *pf = fopen(filename, mode);\n      if (*pf == NULL)\n        fileerror(L, 1, filename);\n    }\n    else {\n      tofile(L);  /* check that it's a valid file handle */\n      lua_pushvalue(L, 1);\n    }\n    lua_rawseti(L, LUA_ENVIRONINDEX, f);\n  }\n  /* return current value */\n  lua_rawgeti(L, LUA_ENVIRONINDEX, f);\n  return 1;\n}\n\n\nstatic int io_input (lua_State *L) {\n  return g_iofile(L, IO_INPUT, \"r\");\n}\n\n\nstatic int io_output (lua_State *L) {\n  return g_iofile(L, IO_OUTPUT, \"w\");\n}\n\n\nstatic int io_readline (lua_State *L);\n\n\nstatic void aux_lines (lua_State *L, int idx, int toclose) {\n  lua_pushvalue(L, idx);\n  lua_pushboolean(L, toclose);  /* close/not close file when finished */\n  lua_pushcclosure(L, io_readline, 2);\n}\n\n\nstatic int f_lines (lua_State *L) {\n  tofile(L);  /* check that it's a valid file handle */\n  aux_lines(L, 1, 0);\n  return 1;\n}\n\n\nstatic int io_lines (lua_State *L) {\n  if (lua_isnoneornil(L, 1)) {  /* no arguments? */\n    /* will iterate over default input */\n    lua_rawgeti(L, LUA_ENVIRONINDEX, IO_INPUT);\n    return f_lines(L);\n  }\n  else {\n    const char *filename = luaL_checkstring(L, 1);\n    FILE **pf = newfile(L);\n    *pf = fopen(filename, \"r\");\n    if (*pf == NULL)\n      fileerror(L, 1, filename);\n    aux_lines(L, lua_gettop(L), 1);\n    return 1;\n  }\n}\n\n\n/*\n** {======================================================\n** READ\n** =======================================================\n*/\n\n\nstatic int read_number (lua_State *L, FILE *f) {\n  lua_Number d;\n  if (fscanf(f, LUA_NUMBER_SCAN, &d) == 1) {\n    lua_pushnumber(L, d);\n    return 1;\n  }\n  else {\n    lua_pushnil(L);  /* \"result\" to be removed */\n    return 0;  /* read fails */\n  }\n}\n\n\nstatic int test_eof (lua_State *L, FILE *f) {\n  int c = getc(f);\n  ungetc(c, f);\n  lua_pushlstring(L, NULL, 0);\n  return (c != EOF);\n}\n\n\nstatic int read_line (lua_State *L, FILE *f) {\n  luaL_Buffer b;\n  luaL_buffinit(L, &b);\n  for (;;) {\n    size_t l;\n    char *p = luaL_prepbuffer(&b);\n    if (fgets(p, LUAL_BUFFERSIZE, f) == NULL) {  /* eof? */\n      luaL_pushresult(&b);  /* close buffer */\n      return (lua_objlen(L, -1) > 0);  /* check whether read something */\n    }\n    l = strlen(p);\n    if (l == 0 || p[l-1] != '\\n')\n      luaL_addsize(&b, l);\n    else {\n      luaL_addsize(&b, l - 1);  /* do not include `eol' */\n      luaL_pushresult(&b);  /* close buffer */\n      return 1;  /* read at least an `eol' */\n    }\n  }\n}\n\n\nstatic int read_chars (lua_State *L, FILE *f, size_t n) {\n  size_t rlen;  /* how much to read */\n  size_t nr;  /* number of chars actually read */\n  luaL_Buffer b;\n  luaL_buffinit(L, &b);\n  rlen = LUAL_BUFFERSIZE;  /* try to read that much each time */\n  do {\n    char *p = luaL_prepbuffer(&b);\n    if (rlen > n) rlen = n;  /* cannot read more than asked */\n    nr = fread(p, sizeof(char), rlen, f);\n    luaL_addsize(&b, nr);\n    n -= nr;  /* still have to read `n' chars */\n  } while (n > 0 && nr == rlen);  /* until end of count or eof */\n  luaL_pushresult(&b);  /* close buffer */\n  return (n == 0 || lua_objlen(L, -1) > 0);\n}\n\n\nstatic int g_read (lua_State *L, FILE *f, int first) {\n  int nargs = lua_gettop(L) - 1;\n  int success;\n  int n;\n  clearerr(f);\n  if (nargs == 0) {  /* no arguments? */\n    success = read_line(L, f);\n    n = first+1;  /* to return 1 result */\n  }\n  else {  /* ensure stack space for all results and for auxlib's buffer */\n    luaL_checkstack(L, nargs+LUA_MINSTACK, \"too many arguments\");\n    success = 1;\n    for (n = first; nargs-- && success; n++) {\n      if (lua_type(L, n) == LUA_TNUMBER) {\n        size_t l = (size_t)lua_tointeger(L, n);\n        success = (l == 0) ? test_eof(L, f) : read_chars(L, f, l);\n      }\n      else {\n        const char *p = lua_tostring(L, n);\n        luaL_argcheck(L, p && p[0] == '*', n, \"invalid option\");\n        switch (p[1]) {\n          case 'n':  /* number */\n            success = read_number(L, f);\n            break;\n          case 'l':  /* line */\n            success = read_line(L, f);\n            break;\n          case 'a':  /* file */\n            read_chars(L, f, ~((size_t)0));  /* read MAX_SIZE_T chars */\n            success = 1; /* always success */\n            break;\n          default:\n            return luaL_argerror(L, n, \"invalid format\");\n        }\n      }\n    }\n  }\n  if (ferror(f))\n    return pushresult(L, 0, NULL);\n  if (!success) {\n    lua_pop(L, 1);  /* remove last result */\n    lua_pushnil(L);  /* push nil instead */\n  }\n  return n - first;\n}\n\n\nstatic int io_read (lua_State *L) {\n  return g_read(L, getiofile(L, IO_INPUT), 1);\n}\n\n\nstatic int f_read (lua_State *L) {\n  return g_read(L, tofile(L), 2);\n}\n\n\nstatic int io_readline (lua_State *L) {\n  FILE *f = *(FILE **)lua_touserdata(L, lua_upvalueindex(1));\n  int sucess;\n  if (f == NULL)  /* file is already closed? */\n    luaL_error(L, \"file is already closed\");\n  sucess = read_line(L, f);\n  if (ferror(f))\n    return luaL_error(L, \"%s\", strerror(errno));\n  if (sucess) return 1;\n  else {  /* EOF */\n    if (lua_toboolean(L, lua_upvalueindex(2))) {  /* generator created file? */\n      lua_settop(L, 0);\n      lua_pushvalue(L, lua_upvalueindex(1));\n      aux_close(L);  /* close it */\n    }\n    return 0;\n  }\n}\n\n/* }====================================================== */\n\n\nstatic int g_write (lua_State *L, FILE *f, int arg) {\n  int nargs = lua_gettop(L) - 1;\n  int status = 1;\n  for (; nargs--; arg++) {\n    if (lua_type(L, arg) == LUA_TNUMBER) {\n      /* optimization: could be done exactly as for strings */\n      status = status &&\n          fprintf(f, LUA_NUMBER_FMT, lua_tonumber(L, arg)) > 0;\n    }\n    else {\n      size_t l;\n      const char *s = luaL_checklstring(L, arg, &l);\n      status = status && (fwrite(s, sizeof(char), l, f) == l);\n    }\n  }\n  return pushresult(L, status, NULL);\n}\n\n\nstatic int io_write (lua_State *L) {\n  return g_write(L, getiofile(L, IO_OUTPUT), 1);\n}\n\n\nstatic int f_write (lua_State *L) {\n  return g_write(L, tofile(L), 2);\n}\n\n\nstatic int f_seek (lua_State *L) {\n  static const int mode[] = {SEEK_SET, SEEK_CUR, SEEK_END};\n  static const char *const modenames[] = {\"set\", \"cur\", \"end\", NULL};\n  FILE *f = tofile(L);\n  int op = luaL_checkoption(L, 2, \"cur\", modenames);\n  long offset = luaL_optlong(L, 3, 0);\n  op = fseek(f, offset, mode[op]);\n  if (op)\n    return pushresult(L, 0, NULL);  /* error */\n  else {\n    lua_pushinteger(L, ftell(f));\n    return 1;\n  }\n}\n\n\nstatic int f_setvbuf (lua_State *L) {\n  static const int mode[] = {_IONBF, _IOFBF, _IOLBF};\n  static const char *const modenames[] = {\"no\", \"full\", \"line\", NULL};\n  FILE *f = tofile(L);\n  int op = luaL_checkoption(L, 2, NULL, modenames);\n  lua_Integer sz = luaL_optinteger(L, 3, LUAL_BUFFERSIZE);\n  int res = setvbuf(f, NULL, mode[op], sz);\n  return pushresult(L, res == 0, NULL);\n}\n\n\n\nstatic int io_flush (lua_State *L) {\n  return pushresult(L, fflush(getiofile(L, IO_OUTPUT)) == 0, NULL);\n}\n\n\nstatic int f_flush (lua_State *L) {\n  return pushresult(L, fflush(tofile(L)) == 0, NULL);\n}\n\n\nstatic const luaL_Reg iolib[] = {\n  {\"close\", io_close},\n  {\"flush\", io_flush},\n  {\"input\", io_input},\n  {\"lines\", io_lines},\n  {\"open\", io_open},\n  {\"output\", io_output},\n  {\"popen\", io_popen},\n  {\"read\", io_read},\n  {\"tmpfile\", io_tmpfile},\n  {\"type\", io_type},\n  {\"write\", io_write},\n  {NULL, NULL}\n};\n\n\nstatic const luaL_Reg flib[] = {\n  {\"close\", io_close},\n  {\"flush\", f_flush},\n  {\"lines\", f_lines},\n  {\"read\", f_read},\n  {\"seek\", f_seek},\n  {\"setvbuf\", f_setvbuf},\n  {\"write\", f_write},\n  {\"__gc\", io_gc},\n  {\"__tostring\", io_tostring},\n  {NULL, NULL}\n};\n\n\nstatic void createmeta (lua_State *L) {\n  luaL_newmetatable(L, LUA_FILEHANDLE);  /* create metatable for file handles */\n  lua_pushvalue(L, -1);  /* push metatable */\n  lua_setfield(L, -2, \"__index\");  /* metatable.__index = metatable */\n  luaL_register(L, NULL, flib);  /* file methods */\n}\n\n\nstatic void createstdfile (lua_State *L, FILE *f, int k, const char *fname) {\n  *newfile(L) = f;\n  if (k > 0) {\n    lua_pushvalue(L, -1);\n    lua_rawseti(L, LUA_ENVIRONINDEX, k);\n  }\n  lua_pushvalue(L, -2);  /* copy environment */\n  lua_setfenv(L, -2);  /* set it */\n  lua_setfield(L, -3, fname);\n}\n\n\nstatic void newfenv (lua_State *L, lua_CFunction cls) {\n  lua_createtable(L, 0, 1);\n  lua_pushcfunction(L, cls);\n  lua_setfield(L, -2, \"__close\");\n}\n\n\nLUALIB_API int luaopen_io (lua_State *L) {\n  createmeta(L);\n  /* create (private) environment (with fields IO_INPUT, IO_OUTPUT, __close) */\n  newfenv(L, io_fclose);\n  lua_replace(L, LUA_ENVIRONINDEX);\n  /* open library */\n  luaL_register(L, LUA_IOLIBNAME, iolib);\n  /* create (and set) default files */\n  newfenv(L, io_noclose);  /* close function for default files */\n  createstdfile(L, stdin, IO_INPUT, \"stdin\");\n  createstdfile(L, stdout, IO_OUTPUT, \"stdout\");\n  createstdfile(L, stderr, 0, \"stderr\");\n  lua_pop(L, 1);  /* pop environment for default files */\n  lua_getfield(L, -1, \"popen\");\n  newfenv(L, io_pclose);  /* create environment for 'popen' */\n  lua_setfenv(L, -2);  /* set fenv for 'popen' */\n  lua_pop(L, 1);  /* pop 'popen' */\n  return 1;\n}\n\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/deps/lua/src/llex.c",
    "content": "/*\n** $Id: llex.c,v 2.20.1.2 2009/11/23 14:58:22 roberto Exp $\n** Lexical Analyzer\n** See Copyright Notice in lua.h\n*/\n\n\n#include <ctype.h>\n#include <locale.h>\n#include <string.h>\n\n#define llex_c\n#define LUA_CORE\n\n#include \"lua.h\"\n\n#include \"ldo.h\"\n#include \"llex.h\"\n#include \"lobject.h\"\n#include \"lparser.h\"\n#include \"lstate.h\"\n#include \"lstring.h\"\n#include \"ltable.h\"\n#include \"lzio.h\"\n\n\n\n#define next(ls) (ls->current = zgetc(ls->z))\n\n\n\n\n#define currIsNewline(ls)\t(ls->current == '\\n' || ls->current == '\\r')\n\n\n/* ORDER RESERVED */\nconst char *const luaX_tokens [] = {\n    \"and\", \"break\", \"do\", \"else\", \"elseif\",\n    \"end\", \"false\", \"for\", \"function\", \"if\",\n    \"in\", \"local\", \"nil\", \"not\", \"or\", \"repeat\",\n    \"return\", \"then\", \"true\", \"until\", \"while\",\n    \"..\", \"...\", \"==\", \">=\", \"<=\", \"~=\",\n    \"<number>\", \"<name>\", \"<string>\", \"<eof>\",\n    NULL\n};\n\n\n#define save_and_next(ls) (save(ls, ls->current), next(ls))\n\n\nstatic void save (LexState *ls, int c) {\n  Mbuffer *b = ls->buff;\n  if (b->n + 1 > b->buffsize) {\n    size_t newsize;\n    if (b->buffsize >= MAX_SIZET/2)\n      luaX_lexerror(ls, \"lexical element too long\", 0);\n    newsize = b->buffsize * 2;\n    luaZ_resizebuffer(ls->L, b, newsize);\n  }\n  b->buffer[b->n++] = cast(char, c);\n}\n\n\nvoid luaX_init (lua_State *L) {\n  int i;\n  for (i=0; i<NUM_RESERVED; i++) {\n    TString *ts = luaS_new(L, luaX_tokens[i]);\n    luaS_fix(ts);  /* reserved words are never collected */\n    lua_assert(strlen(luaX_tokens[i])+1 <= TOKEN_LEN);\n    ts->tsv.reserved = cast_byte(i+1);  /* reserved word */\n  }\n}\n\n\n#define MAXSRC          80\n\n\nconst char *luaX_token2str (LexState *ls, int token) {\n  if (token < FIRST_RESERVED) {\n    lua_assert(token == cast(unsigned char, token));\n    return (iscntrl(token)) ? luaO_pushfstring(ls->L, \"char(%d)\", token) :\n                              luaO_pushfstring(ls->L, \"%c\", token);\n  }\n  else\n    return luaX_tokens[token-FIRST_RESERVED];\n}\n\n\nstatic const char *txtToken (LexState *ls, int token) {\n  switch (token) {\n    case TK_NAME:\n    case TK_STRING:\n    case TK_NUMBER:\n      save(ls, '\\0');\n      return luaZ_buffer(ls->buff);\n    default:\n      return luaX_token2str(ls, token);\n  }\n}\n\n\nvoid luaX_lexerror (LexState *ls, const char *msg, int token) {\n  char buff[MAXSRC];\n  luaO_chunkid(buff, getstr(ls->source), MAXSRC);\n  msg = luaO_pushfstring(ls->L, \"%s:%d: %s\", buff, ls->linenumber, msg);\n  if (token)\n    luaO_pushfstring(ls->L, \"%s near \" LUA_QS, msg, txtToken(ls, token));\n  luaD_throw(ls->L, LUA_ERRSYNTAX);\n}\n\n\nvoid luaX_syntaxerror (LexState *ls, const char *msg) {\n  luaX_lexerror(ls, msg, ls->t.token);\n}\n\n\nTString *luaX_newstring (LexState *ls, const char *str, size_t l) {\n  lua_State *L = ls->L;\n  TString *ts = luaS_newlstr(L, str, l);\n  TValue *o = luaH_setstr(L, ls->fs->h, ts);  /* entry for `str' */\n  if (ttisnil(o)) {\n    setbvalue(o, 1);  /* make sure `str' will not be collected */\n    luaC_checkGC(L);\n  }\n  return ts;\n}\n\n\nstatic void inclinenumber (LexState *ls) {\n  int old = ls->current;\n  lua_assert(currIsNewline(ls));\n  next(ls);  /* skip `\\n' or `\\r' */\n  if (currIsNewline(ls) && ls->current != old)\n    next(ls);  /* skip `\\n\\r' or `\\r\\n' */\n  if (++ls->linenumber >= MAX_INT)\n    luaX_syntaxerror(ls, \"chunk has too many lines\");\n}\n\n\nvoid luaX_setinput (lua_State *L, LexState *ls, ZIO *z, TString *source) {\n  ls->decpoint = '.';\n  ls->L = L;\n  ls->lookahead.token = TK_EOS;  /* no look-ahead token */\n  ls->z = z;\n  ls->fs = NULL;\n  ls->linenumber = 1;\n  ls->lastline = 1;\n  ls->source = source;\n  luaZ_resizebuffer(ls->L, ls->buff, LUA_MINBUFFER);  /* initialize buffer */\n  next(ls);  /* read first char */\n}\n\n\n\n/*\n** =======================================================\n** LEXICAL ANALYZER\n** =======================================================\n*/\n\n\n\nstatic int check_next (LexState *ls, const char *set) {\n  if (!strchr(set, ls->current))\n    return 0;\n  save_and_next(ls);\n  return 1;\n}\n\n\nstatic void buffreplace (LexState *ls, char from, char to) {\n  size_t n = luaZ_bufflen(ls->buff);\n  char *p = luaZ_buffer(ls->buff);\n  while (n--)\n    if (p[n] == from) p[n] = to;\n}\n\n\nstatic void trydecpoint (LexState *ls, SemInfo *seminfo) {\n  /* format error: try to update decimal point separator */\n  struct lconv *cv = localeconv();\n  char old = ls->decpoint;\n  ls->decpoint = (cv ? cv->decimal_point[0] : '.');\n  buffreplace(ls, old, ls->decpoint);  /* try updated decimal separator */\n  if (!luaO_str2d(luaZ_buffer(ls->buff), &seminfo->r)) {\n    /* format error with correct decimal point: no more options */\n    buffreplace(ls, ls->decpoint, '.');  /* undo change (for error message) */\n    luaX_lexerror(ls, \"malformed number\", TK_NUMBER);\n  }\n}\n\n\n/* LUA_NUMBER */\nstatic void read_numeral (LexState *ls, SemInfo *seminfo) {\n  lua_assert(isdigit(ls->current));\n  do {\n    save_and_next(ls);\n  } while (isdigit(ls->current) || ls->current == '.');\n  if (check_next(ls, \"Ee\"))  /* `E'? */\n    check_next(ls, \"+-\");  /* optional exponent sign */\n  while (isalnum(ls->current) || ls->current == '_')\n    save_and_next(ls);\n  save(ls, '\\0');\n  buffreplace(ls, '.', ls->decpoint);  /* follow locale for decimal point */\n  if (!luaO_str2d(luaZ_buffer(ls->buff), &seminfo->r))  /* format error? */\n    trydecpoint(ls, seminfo); /* try to update decimal point separator */\n}\n\n\nstatic int skip_sep (LexState *ls) {\n  int count = 0;\n  int s = ls->current;\n  lua_assert(s == '[' || s == ']');\n  save_and_next(ls);\n  while (ls->current == '=') {\n    save_and_next(ls);\n    count++;\n  }\n  return (ls->current == s) ? count : (-count) - 1;\n}\n\n\nstatic void read_long_string (LexState *ls, SemInfo *seminfo, int sep) {\n  int cont = 0;\n  (void)(cont);  /* avoid warnings when `cont' is not used */\n  save_and_next(ls);  /* skip 2nd `[' */\n  if (currIsNewline(ls))  /* string starts with a newline? */\n    inclinenumber(ls);  /* skip it */\n  for (;;) {\n    switch (ls->current) {\n      case EOZ:\n        luaX_lexerror(ls, (seminfo) ? \"unfinished long string\" :\n                                   \"unfinished long comment\", TK_EOS);\n        break;  /* to avoid warnings */\n#if defined(LUA_COMPAT_LSTR)\n      case '[': {\n        if (skip_sep(ls) == sep) {\n          save_and_next(ls);  /* skip 2nd `[' */\n          cont++;\n#if LUA_COMPAT_LSTR == 1\n          if (sep == 0)\n            luaX_lexerror(ls, \"nesting of [[...]] is deprecated\", '[');\n#endif\n        }\n        break;\n      }\n#endif\n      case ']': {\n        if (skip_sep(ls) == sep) {\n          save_and_next(ls);  /* skip 2nd `]' */\n#if defined(LUA_COMPAT_LSTR) && LUA_COMPAT_LSTR == 2\n          cont--;\n          if (sep == 0 && cont >= 0) break;\n#endif\n          goto endloop;\n        }\n        break;\n      }\n      case '\\n':\n      case '\\r': {\n        save(ls, '\\n');\n        inclinenumber(ls);\n        if (!seminfo) luaZ_resetbuffer(ls->buff);  /* avoid wasting space */\n        break;\n      }\n      default: {\n        if (seminfo) save_and_next(ls);\n        else next(ls);\n      }\n    }\n  } endloop:\n  if (seminfo)\n    seminfo->ts = luaX_newstring(ls, luaZ_buffer(ls->buff) + (2 + sep),\n                                     luaZ_bufflen(ls->buff) - 2*(2 + sep));\n}\n\n\nstatic void read_string (LexState *ls, int del, SemInfo *seminfo) {\n  save_and_next(ls);\n  while (ls->current != del) {\n    switch (ls->current) {\n      case EOZ:\n        luaX_lexerror(ls, \"unfinished string\", TK_EOS);\n        continue;  /* to avoid warnings */\n      case '\\n':\n      case '\\r':\n        luaX_lexerror(ls, \"unfinished string\", TK_STRING);\n        continue;  /* to avoid warnings */\n      case '\\\\': {\n        int c;\n        next(ls);  /* do not save the `\\' */\n        switch (ls->current) {\n          case 'a': c = '\\a'; break;\n          case 'b': c = '\\b'; break;\n          case 'f': c = '\\f'; break;\n          case 'n': c = '\\n'; break;\n          case 'r': c = '\\r'; break;\n          case 't': c = '\\t'; break;\n          case 'v': c = '\\v'; break;\n          case '\\n':  /* go through */\n          case '\\r': save(ls, '\\n'); inclinenumber(ls); continue;\n          case EOZ: continue;  /* will raise an error next loop */\n          default: {\n            if (!isdigit(ls->current))\n              save_and_next(ls);  /* handles \\\\, \\\", \\', and \\? */\n            else {  /* \\xxx */\n              int i = 0;\n              c = 0;\n              do {\n                c = 10*c + (ls->current-'0');\n                next(ls);\n              } while (++i<3 && isdigit(ls->current));\n              if (c > UCHAR_MAX)\n                luaX_lexerror(ls, \"escape sequence too large\", TK_STRING);\n              save(ls, c);\n            }\n            continue;\n          }\n        }\n        save(ls, c);\n        next(ls);\n        continue;\n      }\n      default:\n        save_and_next(ls);\n    }\n  }\n  save_and_next(ls);  /* skip delimiter */\n  seminfo->ts = luaX_newstring(ls, luaZ_buffer(ls->buff) + 1,\n                                   luaZ_bufflen(ls->buff) - 2);\n}\n\n\nstatic int llex (LexState *ls, SemInfo *seminfo) {\n  luaZ_resetbuffer(ls->buff);\n  for (;;) {\n    switch (ls->current) {\n      case '\\n':\n      case '\\r': {\n        inclinenumber(ls);\n        continue;\n      }\n      case '-': {\n        next(ls);\n        if (ls->current != '-') return '-';\n        /* else is a comment */\n        next(ls);\n        if (ls->current == '[') {\n          int sep = skip_sep(ls);\n          luaZ_resetbuffer(ls->buff);  /* `skip_sep' may dirty the buffer */\n          if (sep >= 0) {\n            read_long_string(ls, NULL, sep);  /* long comment */\n            luaZ_resetbuffer(ls->buff);\n            continue;\n          }\n        }\n        /* else short comment */\n        while (!currIsNewline(ls) && ls->current != EOZ)\n          next(ls);\n        continue;\n      }\n      case '[': {\n        int sep = skip_sep(ls);\n        if (sep >= 0) {\n          read_long_string(ls, seminfo, sep);\n          return TK_STRING;\n        }\n        else if (sep == -1) return '[';\n        else luaX_lexerror(ls, \"invalid long string delimiter\", TK_STRING);\n      }\n      case '=': {\n        next(ls);\n        if (ls->current != '=') return '=';\n        else { next(ls); return TK_EQ; }\n      }\n      case '<': {\n        next(ls);\n        if (ls->current != '=') return '<';\n        else { next(ls); return TK_LE; }\n      }\n      case '>': {\n        next(ls);\n        if (ls->current != '=') return '>';\n        else { next(ls); return TK_GE; }\n      }\n      case '~': {\n        next(ls);\n        if (ls->current != '=') return '~';\n        else { next(ls); return TK_NE; }\n      }\n      case '\"':\n      case '\\'': {\n        read_string(ls, ls->current, seminfo);\n        return TK_STRING;\n      }\n      case '.': {\n        save_and_next(ls);\n        if (check_next(ls, \".\")) {\n          if (check_next(ls, \".\"))\n            return TK_DOTS;   /* ... */\n          else return TK_CONCAT;   /* .. */\n        }\n        else if (!isdigit(ls->current)) return '.';\n        else {\n          read_numeral(ls, seminfo);\n          return TK_NUMBER;\n        }\n      }\n      case EOZ: {\n        return TK_EOS;\n      }\n      default: {\n        if (isspace(ls->current)) {\n          lua_assert(!currIsNewline(ls));\n          next(ls);\n          continue;\n        }\n        else if (isdigit(ls->current)) {\n          read_numeral(ls, seminfo);\n          return TK_NUMBER;\n        }\n        else if (isalpha(ls->current) || ls->current == '_') {\n          /* identifier or reserved word */\n          TString *ts;\n          do {\n            save_and_next(ls);\n          } while (isalnum(ls->current) || ls->current == '_');\n          ts = luaX_newstring(ls, luaZ_buffer(ls->buff),\n                                  luaZ_bufflen(ls->buff));\n          if (ts->tsv.reserved > 0)  /* reserved word? */\n            return ts->tsv.reserved - 1 + FIRST_RESERVED;\n          else {\n            seminfo->ts = ts;\n            return TK_NAME;\n          }\n        }\n        else {\n          int c = ls->current;\n          next(ls);\n          return c;  /* single-char tokens (+ - / ...) */\n        }\n      }\n    }\n  }\n}\n\n\nvoid luaX_next (LexState *ls) {\n  ls->lastline = ls->linenumber;\n  if (ls->lookahead.token != TK_EOS) {  /* is there a look-ahead token? */\n    ls->t = ls->lookahead;  /* use this one */\n    ls->lookahead.token = TK_EOS;  /* and discharge it */\n  }\n  else\n    ls->t.token = llex(ls, &ls->t.seminfo);  /* read next token */\n}\n\n\nvoid luaX_lookahead (LexState *ls) {\n  lua_assert(ls->lookahead.token == TK_EOS);\n  ls->lookahead.token = llex(ls, &ls->lookahead.seminfo);\n}\n\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/deps/lua/src/llex.h",
    "content": "/*\n** $Id: llex.h,v 1.58.1.1 2007/12/27 13:02:25 roberto Exp $\n** Lexical Analyzer\n** See Copyright Notice in lua.h\n*/\n\n#ifndef llex_h\n#define llex_h\n\n#include \"lobject.h\"\n#include \"lzio.h\"\n\n\n#define FIRST_RESERVED\t257\n\n/* maximum length of a reserved word */\n#define TOKEN_LEN\t(sizeof(\"function\")/sizeof(char))\n\n\n/*\n* WARNING: if you change the order of this enumeration,\n* grep \"ORDER RESERVED\"\n*/\nenum RESERVED {\n  /* terminal symbols denoted by reserved words */\n  TK_AND = FIRST_RESERVED, TK_BREAK,\n  TK_DO, TK_ELSE, TK_ELSEIF, TK_END, TK_FALSE, TK_FOR, TK_FUNCTION,\n  TK_IF, TK_IN, TK_LOCAL, TK_NIL, TK_NOT, TK_OR, TK_REPEAT,\n  TK_RETURN, TK_THEN, TK_TRUE, TK_UNTIL, TK_WHILE,\n  /* other terminal symbols */\n  TK_CONCAT, TK_DOTS, TK_EQ, TK_GE, TK_LE, TK_NE, TK_NUMBER,\n  TK_NAME, TK_STRING, TK_EOS\n};\n\n/* number of reserved words */\n#define NUM_RESERVED\t(cast(int, TK_WHILE-FIRST_RESERVED+1))\n\n\n/* array with token `names' */\nLUAI_DATA const char *const luaX_tokens [];\n\n\ntypedef union {\n  lua_Number r;\n  TString *ts;\n} SemInfo;  /* semantics information */\n\n\ntypedef struct Token {\n  int token;\n  SemInfo seminfo;\n} Token;\n\n\ntypedef struct LexState {\n  int current;  /* current character (charint) */\n  int linenumber;  /* input line counter */\n  int lastline;  /* line of last token `consumed' */\n  Token t;  /* current token */\n  Token lookahead;  /* look ahead token */\n  struct FuncState *fs;  /* `FuncState' is private to the parser */\n  struct lua_State *L;\n  ZIO *z;  /* input stream */\n  Mbuffer *buff;  /* buffer for tokens */\n  TString *source;  /* current source name */\n  char decpoint;  /* locale decimal point */\n} LexState;\n\n\nLUAI_FUNC void luaX_init (lua_State *L);\nLUAI_FUNC void luaX_setinput (lua_State *L, LexState *ls, ZIO *z,\n                              TString *source);\nLUAI_FUNC TString *luaX_newstring (LexState *ls, const char *str, size_t l);\nLUAI_FUNC void luaX_next (LexState *ls);\nLUAI_FUNC void luaX_lookahead (LexState *ls);\nLUAI_FUNC void luaX_lexerror (LexState *ls, const char *msg, int token);\nLUAI_FUNC void luaX_syntaxerror (LexState *ls, const char *s);\nLUAI_FUNC const char *luaX_token2str (LexState *ls, int token);\n\n\n#endif\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/deps/lua/src/llimits.h",
    "content": "/*\n** $Id: llimits.h,v 1.69.1.1 2007/12/27 13:02:25 roberto Exp $\n** Limits, basic types, and some other `installation-dependent' definitions\n** See Copyright Notice in lua.h\n*/\n\n#ifndef llimits_h\n#define llimits_h\n\n\n#include <limits.h>\n#include <stddef.h>\n\n\n#include \"lua.h\"\n\n\ntypedef LUAI_UINT32 lu_int32;\n\ntypedef LUAI_UMEM lu_mem;\n\ntypedef LUAI_MEM l_mem;\n\n\n\n/* chars used as small naturals (so that `char' is reserved for characters) */\ntypedef unsigned char lu_byte;\n\n\n#define MAX_SIZET\t((size_t)(~(size_t)0)-2)\n\n#define MAX_LUMEM\t((lu_mem)(~(lu_mem)0)-2)\n\n\n#define MAX_INT (INT_MAX-2)  /* maximum value of an int (-2 for safety) */\n\n/*\n** conversion of pointer to integer\n** this is for hashing only; there is no problem if the integer\n** cannot hold the whole pointer value\n*/\n#define IntPoint(p)  ((unsigned int)(lu_mem)(p))\n\n\n\n/* type to ensure maximum alignment */\ntypedef LUAI_USER_ALIGNMENT_T L_Umaxalign;\n\n\n/* result of a `usual argument conversion' over lua_Number */\ntypedef LUAI_UACNUMBER l_uacNumber;\n\n\n/* internal assertions for in-house debugging */\n#ifdef lua_assert\n\n#define check_exp(c,e)\t\t(lua_assert(c), (e))\n#define api_check(l,e)\t\tlua_assert(e)\n\n#else\n\n#define lua_assert(c)\t\t((void)0)\n#define check_exp(c,e)\t\t(e)\n#define api_check\t\tluai_apicheck\n\n#endif\n\n\n#ifndef UNUSED\n#define UNUSED(x)\t((void)(x))\t/* to avoid warnings */\n#endif\n\n\n#ifndef cast\n#define cast(t, exp)\t((t)(exp))\n#endif\n\n#define cast_byte(i)\tcast(lu_byte, (i))\n#define cast_num(i)\tcast(lua_Number, (i))\n#define cast_int(i)\tcast(int, (i))\n\n\n\n/*\n** type for virtual-machine instructions\n** must be an unsigned with (at least) 4 bytes (see details in lopcodes.h)\n*/\ntypedef lu_int32 Instruction;\n\n\n\n/* maximum stack for a Lua function */\n#define MAXSTACK\t250\n\n\n\n/* minimum size for the string table (must be power of 2) */\n#ifndef MINSTRTABSIZE\n#define MINSTRTABSIZE\t32\n#endif\n\n\n/* minimum size for string buffer */\n#ifndef LUA_MINBUFFER\n#define LUA_MINBUFFER\t32\n#endif\n\n\n#ifndef lua_lock\n#define lua_lock(L)     ((void) 0) \n#define lua_unlock(L)   ((void) 0)\n#endif\n\n#ifndef luai_threadyield\n#define luai_threadyield(L)     {lua_unlock(L); lua_lock(L);}\n#endif\n\n\n/*\n** macro to control inclusion of some hard tests on stack reallocation\n*/ \n#ifndef HARDSTACKTESTS\n#define condhardstacktests(x)\t((void)0)\n#else\n#define condhardstacktests(x)\tx\n#endif\n\n#endif\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/deps/lua/src/lmathlib.c",
    "content": "/*\n** $Id: lmathlib.c,v 1.67.1.1 2007/12/27 13:02:25 roberto Exp $\n** Standard mathematical library\n** See Copyright Notice in lua.h\n*/\n\n\n#include <stdlib.h>\n#include <math.h>\n\n#define lmathlib_c\n#define LUA_LIB\n\n#include \"lua.h\"\n\n#include \"lauxlib.h\"\n#include \"lualib.h\"\n\n\n#undef PI\n#define PI (3.14159265358979323846)\n#define RADIANS_PER_DEGREE (PI/180.0)\n\n\n\nstatic int math_abs (lua_State *L) {\n  lua_pushnumber(L, fabs(luaL_checknumber(L, 1)));\n  return 1;\n}\n\nstatic int math_sin (lua_State *L) {\n  lua_pushnumber(L, sin(luaL_checknumber(L, 1)));\n  return 1;\n}\n\nstatic int math_sinh (lua_State *L) {\n  lua_pushnumber(L, sinh(luaL_checknumber(L, 1)));\n  return 1;\n}\n\nstatic int math_cos (lua_State *L) {\n  lua_pushnumber(L, cos(luaL_checknumber(L, 1)));\n  return 1;\n}\n\nstatic int math_cosh (lua_State *L) {\n  lua_pushnumber(L, cosh(luaL_checknumber(L, 1)));\n  return 1;\n}\n\nstatic int math_tan (lua_State *L) {\n  lua_pushnumber(L, tan(luaL_checknumber(L, 1)));\n  return 1;\n}\n\nstatic int math_tanh (lua_State *L) {\n  lua_pushnumber(L, tanh(luaL_checknumber(L, 1)));\n  return 1;\n}\n\nstatic int math_asin (lua_State *L) {\n  lua_pushnumber(L, asin(luaL_checknumber(L, 1)));\n  return 1;\n}\n\nstatic int math_acos (lua_State *L) {\n  lua_pushnumber(L, acos(luaL_checknumber(L, 1)));\n  return 1;\n}\n\nstatic int math_atan (lua_State *L) {\n  lua_pushnumber(L, atan(luaL_checknumber(L, 1)));\n  return 1;\n}\n\nstatic int math_atan2 (lua_State *L) {\n  lua_pushnumber(L, atan2(luaL_checknumber(L, 1), luaL_checknumber(L, 2)));\n  return 1;\n}\n\nstatic int math_ceil (lua_State *L) {\n  lua_pushnumber(L, ceil(luaL_checknumber(L, 1)));\n  return 1;\n}\n\nstatic int math_floor (lua_State *L) {\n  lua_pushnumber(L, floor(luaL_checknumber(L, 1)));\n  return 1;\n}\n\nstatic int math_fmod (lua_State *L) {\n  lua_pushnumber(L, fmod(luaL_checknumber(L, 1), luaL_checknumber(L, 2)));\n  return 1;\n}\n\nstatic int math_modf (lua_State *L) {\n  double ip;\n  double fp = modf(luaL_checknumber(L, 1), &ip);\n  lua_pushnumber(L, ip);\n  lua_pushnumber(L, fp);\n  return 2;\n}\n\nstatic int math_sqrt (lua_State *L) {\n  lua_pushnumber(L, sqrt(luaL_checknumber(L, 1)));\n  return 1;\n}\n\nstatic int math_pow (lua_State *L) {\n  lua_pushnumber(L, pow(luaL_checknumber(L, 1), luaL_checknumber(L, 2)));\n  return 1;\n}\n\nstatic int math_log (lua_State *L) {\n  lua_pushnumber(L, log(luaL_checknumber(L, 1)));\n  return 1;\n}\n\nstatic int math_log10 (lua_State *L) {\n  lua_pushnumber(L, log10(luaL_checknumber(L, 1)));\n  return 1;\n}\n\nstatic int math_exp (lua_State *L) {\n  lua_pushnumber(L, exp(luaL_checknumber(L, 1)));\n  return 1;\n}\n\nstatic int math_deg (lua_State *L) {\n  lua_pushnumber(L, luaL_checknumber(L, 1)/RADIANS_PER_DEGREE);\n  return 1;\n}\n\nstatic int math_rad (lua_State *L) {\n  lua_pushnumber(L, luaL_checknumber(L, 1)*RADIANS_PER_DEGREE);\n  return 1;\n}\n\nstatic int math_frexp (lua_State *L) {\n  int e;\n  lua_pushnumber(L, frexp(luaL_checknumber(L, 1), &e));\n  lua_pushinteger(L, e);\n  return 2;\n}\n\nstatic int math_ldexp (lua_State *L) {\n  lua_pushnumber(L, ldexp(luaL_checknumber(L, 1), luaL_checkint(L, 2)));\n  return 1;\n}\n\n\n\nstatic int math_min (lua_State *L) {\n  int n = lua_gettop(L);  /* number of arguments */\n  lua_Number dmin = luaL_checknumber(L, 1);\n  int i;\n  for (i=2; i<=n; i++) {\n    lua_Number d = luaL_checknumber(L, i);\n    if (d < dmin)\n      dmin = d;\n  }\n  lua_pushnumber(L, dmin);\n  return 1;\n}\n\n\nstatic int math_max (lua_State *L) {\n  int n = lua_gettop(L);  /* number of arguments */\n  lua_Number dmax = luaL_checknumber(L, 1);\n  int i;\n  for (i=2; i<=n; i++) {\n    lua_Number d = luaL_checknumber(L, i);\n    if (d > dmax)\n      dmax = d;\n  }\n  lua_pushnumber(L, dmax);\n  return 1;\n}\n\n\nstatic int math_random (lua_State *L) {\n  /* the `%' avoids the (rare) case of r==1, and is needed also because on\n     some systems (SunOS!) `rand()' may return a value larger than RAND_MAX */\n  lua_Number r = (lua_Number)(rand()%RAND_MAX) / (lua_Number)RAND_MAX;\n  switch (lua_gettop(L)) {  /* check number of arguments */\n    case 0: {  /* no arguments */\n      lua_pushnumber(L, r);  /* Number between 0 and 1 */\n      break;\n    }\n    case 1: {  /* only upper limit */\n      int u = luaL_checkint(L, 1);\n      luaL_argcheck(L, 1<=u, 1, \"interval is empty\");\n      lua_pushnumber(L, floor(r*u)+1);  /* int between 1 and `u' */\n      break;\n    }\n    case 2: {  /* lower and upper limits */\n      int l = luaL_checkint(L, 1);\n      int u = luaL_checkint(L, 2);\n      luaL_argcheck(L, l<=u, 2, \"interval is empty\");\n      lua_pushnumber(L, floor(r*(u-l+1))+l);  /* int between `l' and `u' */\n      break;\n    }\n    default: return luaL_error(L, \"wrong number of arguments\");\n  }\n  return 1;\n}\n\n\nstatic int math_randomseed (lua_State *L) {\n  srand(luaL_checkint(L, 1));\n  return 0;\n}\n\n\nstatic const luaL_Reg mathlib[] = {\n  {\"abs\",   math_abs},\n  {\"acos\",  math_acos},\n  {\"asin\",  math_asin},\n  {\"atan2\", math_atan2},\n  {\"atan\",  math_atan},\n  {\"ceil\",  math_ceil},\n  {\"cosh\",   math_cosh},\n  {\"cos\",   math_cos},\n  {\"deg\",   math_deg},\n  {\"exp\",   math_exp},\n  {\"floor\", math_floor},\n  {\"fmod\",   math_fmod},\n  {\"frexp\", math_frexp},\n  {\"ldexp\", math_ldexp},\n  {\"log10\", math_log10},\n  {\"log\",   math_log},\n  {\"max\",   math_max},\n  {\"min\",   math_min},\n  {\"modf\",   math_modf},\n  {\"pow\",   math_pow},\n  {\"rad\",   math_rad},\n  {\"random\",     math_random},\n  {\"randomseed\", math_randomseed},\n  {\"sinh\",   math_sinh},\n  {\"sin\",   math_sin},\n  {\"sqrt\",  math_sqrt},\n  {\"tanh\",   math_tanh},\n  {\"tan\",   math_tan},\n  {NULL, NULL}\n};\n\n\n/*\n** Open math library\n*/\nLUALIB_API int luaopen_math (lua_State *L) {\n  luaL_register(L, LUA_MATHLIBNAME, mathlib);\n  lua_pushnumber(L, PI);\n  lua_setfield(L, -2, \"pi\");\n  lua_pushnumber(L, HUGE_VAL);\n  lua_setfield(L, -2, \"huge\");\n#if defined(LUA_COMPAT_MOD)\n  lua_getfield(L, -1, \"fmod\");\n  lua_setfield(L, -2, \"mod\");\n#endif\n  return 1;\n}\n\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/deps/lua/src/lmem.c",
    "content": "/*\n** $Id: lmem.c,v 1.70.1.1 2007/12/27 13:02:25 roberto Exp $\n** Interface to Memory Manager\n** See Copyright Notice in lua.h\n*/\n\n\n#include <stddef.h>\n\n#define lmem_c\n#define LUA_CORE\n\n#include \"lua.h\"\n\n#include \"ldebug.h\"\n#include \"ldo.h\"\n#include \"lmem.h\"\n#include \"lobject.h\"\n#include \"lstate.h\"\n\n\n\n/*\n** About the realloc function:\n** void * frealloc (void *ud, void *ptr, size_t osize, size_t nsize);\n** (`osize' is the old size, `nsize' is the new size)\n**\n** Lua ensures that (ptr == NULL) iff (osize == 0).\n**\n** * frealloc(ud, NULL, 0, x) creates a new block of size `x'\n**\n** * frealloc(ud, p, x, 0) frees the block `p'\n** (in this specific case, frealloc must return NULL).\n** particularly, frealloc(ud, NULL, 0, 0) does nothing\n** (which is equivalent to free(NULL) in ANSI C)\n**\n** frealloc returns NULL if it cannot create or reallocate the area\n** (any reallocation to an equal or smaller size cannot fail!)\n*/\n\n\n\n#define MINSIZEARRAY\t4\n\n\nvoid *luaM_growaux_ (lua_State *L, void *block, int *size, size_t size_elems,\n                     int limit, const char *errormsg) {\n  void *newblock;\n  int newsize;\n  if (*size >= limit/2) {  /* cannot double it? */\n    if (*size >= limit)  /* cannot grow even a little? */\n      luaG_runerror(L, errormsg);\n    newsize = limit;  /* still have at least one free place */\n  }\n  else {\n    newsize = (*size)*2;\n    if (newsize < MINSIZEARRAY)\n      newsize = MINSIZEARRAY;  /* minimum size */\n  }\n  newblock = luaM_reallocv(L, block, *size, newsize, size_elems);\n  *size = newsize;  /* update only when everything else is OK */\n  return newblock;\n}\n\n\nvoid *luaM_toobig (lua_State *L) {\n  luaG_runerror(L, \"memory allocation error: block too big\");\n  return NULL;  /* to avoid warnings */\n}\n\n\n\n/*\n** generic allocation routine.\n*/\nvoid *luaM_realloc_ (lua_State *L, void *block, size_t osize, size_t nsize) {\n  global_State *g = G(L);\n  lua_assert((osize == 0) == (block == NULL));\n  block = (*g->frealloc)(g->ud, block, osize, nsize);\n  if (block == NULL && nsize > 0)\n    luaD_throw(L, LUA_ERRMEM);\n  lua_assert((nsize == 0) == (block == NULL));\n  g->totalbytes = (g->totalbytes - osize) + nsize;\n  return block;\n}\n\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/deps/lua/src/lmem.h",
    "content": "/*\n** $Id: lmem.h,v 1.31.1.1 2007/12/27 13:02:25 roberto Exp $\n** Interface to Memory Manager\n** See Copyright Notice in lua.h\n*/\n\n#ifndef lmem_h\n#define lmem_h\n\n\n#include <stddef.h>\n\n#include \"llimits.h\"\n#include \"lua.h\"\n\n#define MEMERRMSG\t\"not enough memory\"\n\n\n#define luaM_reallocv(L,b,on,n,e) \\\n\t((cast(size_t, (n)+1) <= MAX_SIZET/(e)) ?  /* +1 to avoid warnings */ \\\n\t\tluaM_realloc_(L, (b), (on)*(e), (n)*(e)) : \\\n\t\tluaM_toobig(L))\n\n#define luaM_freemem(L, b, s)\tluaM_realloc_(L, (b), (s), 0)\n#define luaM_free(L, b)\t\tluaM_realloc_(L, (b), sizeof(*(b)), 0)\n#define luaM_freearray(L, b, n, t)   luaM_reallocv(L, (b), n, 0, sizeof(t))\n\n#define luaM_malloc(L,t)\tluaM_realloc_(L, NULL, 0, (t))\n#define luaM_new(L,t)\t\tcast(t *, luaM_malloc(L, sizeof(t)))\n#define luaM_newvector(L,n,t) \\\n\t\tcast(t *, luaM_reallocv(L, NULL, 0, n, sizeof(t)))\n\n#define luaM_growvector(L,v,nelems,size,t,limit,e) \\\n          if ((nelems)+1 > (size)) \\\n            ((v)=cast(t *, luaM_growaux_(L,v,&(size),sizeof(t),limit,e)))\n\n#define luaM_reallocvector(L, v,oldn,n,t) \\\n   ((v)=cast(t *, luaM_reallocv(L, v, oldn, n, sizeof(t))))\n\n\nLUAI_FUNC void *luaM_realloc_ (lua_State *L, void *block, size_t oldsize,\n                                                          size_t size);\nLUAI_FUNC void *luaM_toobig (lua_State *L);\nLUAI_FUNC void *luaM_growaux_ (lua_State *L, void *block, int *size,\n                               size_t size_elem, int limit,\n                               const char *errormsg);\n\n#endif\n\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/deps/lua/src/loadlib.c",
    "content": "/*\n** $Id: loadlib.c,v 1.52.1.4 2009/09/09 13:17:16 roberto Exp $\n** Dynamic library loader for Lua\n** See Copyright Notice in lua.h\n**\n** This module contains an implementation of loadlib for Unix systems\n** that have dlfcn, an implementation for Darwin (Mac OS X), an\n** implementation for Windows, and a stub for other systems.\n*/\n\n\n#include <stdlib.h>\n#include <string.h>\n\n\n#define loadlib_c\n#define LUA_LIB\n\n#include \"lua.h\"\n\n#include \"lauxlib.h\"\n#include \"lualib.h\"\n\n\n/* prefix for open functions in C libraries */\n#define LUA_POF\t\t\"luaopen_\"\n\n/* separator for open functions in C libraries */\n#define LUA_OFSEP\t\"_\"\n\n\n#define LIBPREFIX\t\"LOADLIB: \"\n\n#define POF\t\tLUA_POF\n#define LIB_FAIL\t\"open\"\n\n\n/* error codes for ll_loadfunc */\n#define ERRLIB\t\t1\n#define ERRFUNC\t\t2\n\n#define setprogdir(L)\t\t((void)0)\n\n\nstatic void ll_unloadlib (void *lib);\nstatic void *ll_load (lua_State *L, const char *path);\nstatic lua_CFunction ll_sym (lua_State *L, void *lib, const char *sym);\n\n\n\n#if defined(LUA_DL_DLOPEN)\n/*\n** {========================================================================\n** This is an implementation of loadlib based on the dlfcn interface.\n** The dlfcn interface is available in Linux, SunOS, Solaris, IRIX, FreeBSD,\n** NetBSD, AIX 4.2, HPUX 11, and  probably most other Unix flavors, at least\n** as an emulation layer on top of native functions.\n** =========================================================================\n*/\n\n#include <dlfcn.h>\n\nstatic void ll_unloadlib (void *lib) {\n  dlclose(lib);\n}\n\n\nstatic void *ll_load (lua_State *L, const char *path) {\n  void *lib = dlopen(path, RTLD_NOW);\n  if (lib == NULL) lua_pushstring(L, dlerror());\n  return lib;\n}\n\n\nstatic lua_CFunction ll_sym (lua_State *L, void *lib, const char *sym) {\n  lua_CFunction f = (lua_CFunction)dlsym(lib, sym);\n  if (f == NULL) lua_pushstring(L, dlerror());\n  return f;\n}\n\n/* }====================================================== */\n\n\n\n#elif defined(LUA_DL_DLL)\n/*\n** {======================================================================\n** This is an implementation of loadlib for Windows using native functions.\n** =======================================================================\n*/\n\n#include <windows.h>\n\n\n#undef setprogdir\n\nstatic void setprogdir (lua_State *L) {\n  char buff[MAX_PATH + 1];\n  char *lb;\n  DWORD nsize = sizeof(buff)/sizeof(char);\n  DWORD n = GetModuleFileNameA(NULL, buff, nsize);\n  if (n == 0 || n == nsize || (lb = strrchr(buff, '\\\\')) == NULL)\n    luaL_error(L, \"unable to get ModuleFileName\");\n  else {\n    *lb = '\\0';\n    luaL_gsub(L, lua_tostring(L, -1), LUA_EXECDIR, buff);\n    lua_remove(L, -2);  /* remove original string */\n  }\n}\n\n\nstatic void pusherror (lua_State *L) {\n  int error = GetLastError();\n  char buffer[128];\n  if (FormatMessageA(FORMAT_MESSAGE_IGNORE_INSERTS | FORMAT_MESSAGE_FROM_SYSTEM,\n      NULL, error, 0, buffer, sizeof(buffer), NULL))\n    lua_pushstring(L, buffer);\n  else\n    lua_pushfstring(L, \"system error %d\\n\", error);\n}\n\nstatic void ll_unloadlib (void *lib) {\n  FreeLibrary((HINSTANCE)lib);\n}\n\n\nstatic void *ll_load (lua_State *L, const char *path) {\n  HINSTANCE lib = LoadLibraryA(path);\n  if (lib == NULL) pusherror(L);\n  return lib;\n}\n\n\nstatic lua_CFunction ll_sym (lua_State *L, void *lib, const char *sym) {\n  lua_CFunction f = (lua_CFunction)GetProcAddress((HINSTANCE)lib, sym);\n  if (f == NULL) pusherror(L);\n  return f;\n}\n\n/* }====================================================== */\n\n\n\n#elif defined(LUA_DL_DYLD)\n/*\n** {======================================================================\n** Native Mac OS X / Darwin Implementation\n** =======================================================================\n*/\n\n#include <mach-o/dyld.h>\n\n\n/* Mac appends a `_' before C function names */\n#undef POF\n#define POF\t\"_\" LUA_POF\n\n\nstatic void pusherror (lua_State *L) {\n  const char *err_str;\n  const char *err_file;\n  NSLinkEditErrors err;\n  int err_num;\n  NSLinkEditError(&err, &err_num, &err_file, &err_str);\n  lua_pushstring(L, err_str);\n}\n\n\nstatic const char *errorfromcode (NSObjectFileImageReturnCode ret) {\n  switch (ret) {\n    case NSObjectFileImageInappropriateFile:\n      return \"file is not a bundle\";\n    case NSObjectFileImageArch:\n      return \"library is for wrong CPU type\";\n    case NSObjectFileImageFormat:\n      return \"bad format\";\n    case NSObjectFileImageAccess:\n      return \"cannot access file\";\n    case NSObjectFileImageFailure:\n    default:\n      return \"unable to load library\";\n  }\n}\n\n\nstatic void ll_unloadlib (void *lib) {\n  NSUnLinkModule((NSModule)lib, NSUNLINKMODULE_OPTION_RESET_LAZY_REFERENCES);\n}\n\n\nstatic void *ll_load (lua_State *L, const char *path) {\n  NSObjectFileImage img;\n  NSObjectFileImageReturnCode ret;\n  /* this would be a rare case, but prevents crashing if it happens */\n  if(!_dyld_present()) {\n    lua_pushliteral(L, \"dyld not present\");\n    return NULL;\n  }\n  ret = NSCreateObjectFileImageFromFile(path, &img);\n  if (ret == NSObjectFileImageSuccess) {\n    NSModule mod = NSLinkModule(img, path, NSLINKMODULE_OPTION_PRIVATE |\n                       NSLINKMODULE_OPTION_RETURN_ON_ERROR);\n    NSDestroyObjectFileImage(img);\n    if (mod == NULL) pusherror(L);\n    return mod;\n  }\n  lua_pushstring(L, errorfromcode(ret));\n  return NULL;\n}\n\n\nstatic lua_CFunction ll_sym (lua_State *L, void *lib, const char *sym) {\n  NSSymbol nss = NSLookupSymbolInModule((NSModule)lib, sym);\n  if (nss == NULL) {\n    lua_pushfstring(L, \"symbol \" LUA_QS \" not found\", sym);\n    return NULL;\n  }\n  return (lua_CFunction)NSAddressOfSymbol(nss);\n}\n\n/* }====================================================== */\n\n\n\n#else\n/*\n** {======================================================\n** Fallback for other systems\n** =======================================================\n*/\n\n#undef LIB_FAIL\n#define LIB_FAIL\t\"absent\"\n\n\n#define DLMSG\t\"dynamic libraries not enabled; check your Lua installation\"\n\n\nstatic void ll_unloadlib (void *lib) {\n  (void)lib;  /* to avoid warnings */\n}\n\n\nstatic void *ll_load (lua_State *L, const char *path) {\n  (void)path;  /* to avoid warnings */\n  lua_pushliteral(L, DLMSG);\n  return NULL;\n}\n\n\nstatic lua_CFunction ll_sym (lua_State *L, void *lib, const char *sym) {\n  (void)lib; (void)sym;  /* to avoid warnings */\n  lua_pushliteral(L, DLMSG);\n  return NULL;\n}\n\n/* }====================================================== */\n#endif\n\n\n\nstatic void **ll_register (lua_State *L, const char *path) {\n  void **plib;\n  lua_pushfstring(L, \"%s%s\", LIBPREFIX, path);\n  lua_gettable(L, LUA_REGISTRYINDEX);  /* check library in registry? */\n  if (!lua_isnil(L, -1))  /* is there an entry? */\n    plib = (void **)lua_touserdata(L, -1);\n  else {  /* no entry yet; create one */\n    lua_pop(L, 1);\n    plib = (void **)lua_newuserdata(L, sizeof(const void *));\n    *plib = NULL;\n    luaL_getmetatable(L, \"_LOADLIB\");\n    lua_setmetatable(L, -2);\n    lua_pushfstring(L, \"%s%s\", LIBPREFIX, path);\n    lua_pushvalue(L, -2);\n    lua_settable(L, LUA_REGISTRYINDEX);\n  }\n  return plib;\n}\n\n\n/*\n** __gc tag method: calls library's `ll_unloadlib' function with the lib\n** handle\n*/\nstatic int gctm (lua_State *L) {\n  void **lib = (void **)luaL_checkudata(L, 1, \"_LOADLIB\");\n  if (*lib) ll_unloadlib(*lib);\n  *lib = NULL;  /* mark library as closed */\n  return 0;\n}\n\n\nstatic int ll_loadfunc (lua_State *L, const char *path, const char *sym) {\n  void **reg = ll_register(L, path);\n  if (*reg == NULL) *reg = ll_load(L, path);\n  if (*reg == NULL)\n    return ERRLIB;  /* unable to load library */\n  else {\n    lua_CFunction f = ll_sym(L, *reg, sym);\n    if (f == NULL)\n      return ERRFUNC;  /* unable to find function */\n    lua_pushcfunction(L, f);\n    return 0;  /* return function */\n  }\n}\n\n\nstatic int ll_loadlib (lua_State *L) {\n  const char *path = luaL_checkstring(L, 1);\n  const char *init = luaL_checkstring(L, 2);\n  int stat = ll_loadfunc(L, path, init);\n  if (stat == 0)  /* no errors? */\n    return 1;  /* return the loaded function */\n  else {  /* error; error message is on stack top */\n    lua_pushnil(L);\n    lua_insert(L, -2);\n    lua_pushstring(L, (stat == ERRLIB) ?  LIB_FAIL : \"init\");\n    return 3;  /* return nil, error message, and where */\n  }\n}\n\n\n\n/*\n** {======================================================\n** 'require' function\n** =======================================================\n*/\n\n\nstatic int readable (const char *filename) {\n  FILE *f = fopen(filename, \"r\");  /* try to open file */\n  if (f == NULL) return 0;  /* open failed */\n  fclose(f);\n  return 1;\n}\n\n\nstatic const char *pushnexttemplate (lua_State *L, const char *path) {\n  const char *l;\n  while (*path == *LUA_PATHSEP) path++;  /* skip separators */\n  if (*path == '\\0') return NULL;  /* no more templates */\n  l = strchr(path, *LUA_PATHSEP);  /* find next separator */\n  if (l == NULL) l = path + strlen(path);\n  lua_pushlstring(L, path, l - path);  /* template */\n  return l;\n}\n\n\nstatic const char *findfile (lua_State *L, const char *name,\n                                           const char *pname) {\n  const char *path;\n  name = luaL_gsub(L, name, \".\", LUA_DIRSEP);\n  lua_getfield(L, LUA_ENVIRONINDEX, pname);\n  path = lua_tostring(L, -1);\n  if (path == NULL)\n    luaL_error(L, LUA_QL(\"package.%s\") \" must be a string\", pname);\n  lua_pushliteral(L, \"\");  /* error accumulator */\n  while ((path = pushnexttemplate(L, path)) != NULL) {\n    const char *filename;\n    filename = luaL_gsub(L, lua_tostring(L, -1), LUA_PATH_MARK, name);\n    lua_remove(L, -2);  /* remove path template */\n    if (readable(filename))  /* does file exist and is readable? */\n      return filename;  /* return that file name */\n    lua_pushfstring(L, \"\\n\\tno file \" LUA_QS, filename);\n    lua_remove(L, -2);  /* remove file name */\n    lua_concat(L, 2);  /* add entry to possible error message */\n  }\n  return NULL;  /* not found */\n}\n\n\nstatic void loaderror (lua_State *L, const char *filename) {\n  luaL_error(L, \"error loading module \" LUA_QS \" from file \" LUA_QS \":\\n\\t%s\",\n                lua_tostring(L, 1), filename, lua_tostring(L, -1));\n}\n\n\nstatic int loader_Lua (lua_State *L) {\n  const char *filename;\n  const char *name = luaL_checkstring(L, 1);\n  filename = findfile(L, name, \"path\");\n  if (filename == NULL) return 1;  /* library not found in this path */\n  if (luaL_loadfile(L, filename) != 0)\n    loaderror(L, filename);\n  return 1;  /* library loaded successfully */\n}\n\n\nstatic const char *mkfuncname (lua_State *L, const char *modname) {\n  const char *funcname;\n  const char *mark = strchr(modname, *LUA_IGMARK);\n  if (mark) modname = mark + 1;\n  funcname = luaL_gsub(L, modname, \".\", LUA_OFSEP);\n  funcname = lua_pushfstring(L, POF\"%s\", funcname);\n  lua_remove(L, -2);  /* remove 'gsub' result */\n  return funcname;\n}\n\n\nstatic int loader_C (lua_State *L) {\n  const char *funcname;\n  const char *name = luaL_checkstring(L, 1);\n  const char *filename = findfile(L, name, \"cpath\");\n  if (filename == NULL) return 1;  /* library not found in this path */\n  funcname = mkfuncname(L, name);\n  if (ll_loadfunc(L, filename, funcname) != 0)\n    loaderror(L, filename);\n  return 1;  /* library loaded successfully */\n}\n\n\nstatic int loader_Croot (lua_State *L) {\n  const char *funcname;\n  const char *filename;\n  const char *name = luaL_checkstring(L, 1);\n  const char *p = strchr(name, '.');\n  int stat;\n  if (p == NULL) return 0;  /* is root */\n  lua_pushlstring(L, name, p - name);\n  filename = findfile(L, lua_tostring(L, -1), \"cpath\");\n  if (filename == NULL) return 1;  /* root not found */\n  funcname = mkfuncname(L, name);\n  if ((stat = ll_loadfunc(L, filename, funcname)) != 0) {\n    if (stat != ERRFUNC) loaderror(L, filename);  /* real error */\n    lua_pushfstring(L, \"\\n\\tno module \" LUA_QS \" in file \" LUA_QS,\n                       name, filename);\n    return 1;  /* function not found */\n  }\n  return 1;\n}\n\n\nstatic int loader_preload (lua_State *L) {\n  const char *name = luaL_checkstring(L, 1);\n  lua_getfield(L, LUA_ENVIRONINDEX, \"preload\");\n  if (!lua_istable(L, -1))\n    luaL_error(L, LUA_QL(\"package.preload\") \" must be a table\");\n  lua_getfield(L, -1, name);\n  if (lua_isnil(L, -1))  /* not found? */\n    lua_pushfstring(L, \"\\n\\tno field package.preload['%s']\", name);\n  return 1;\n}\n\n\nstatic const int sentinel_ = 0;\n#define sentinel\t((void *)&sentinel_)\n\n\nstatic int ll_require (lua_State *L) {\n  const char *name = luaL_checkstring(L, 1);\n  int i;\n  lua_settop(L, 1);  /* _LOADED table will be at index 2 */\n  lua_getfield(L, LUA_REGISTRYINDEX, \"_LOADED\");\n  lua_getfield(L, 2, name);\n  if (lua_toboolean(L, -1)) {  /* is it there? */\n    if (lua_touserdata(L, -1) == sentinel)  /* check loops */\n      luaL_error(L, \"loop or previous error loading module \" LUA_QS, name);\n    return 1;  /* package is already loaded */\n  }\n  /* else must load it; iterate over available loaders */\n  lua_getfield(L, LUA_ENVIRONINDEX, \"loaders\");\n  if (!lua_istable(L, -1))\n    luaL_error(L, LUA_QL(\"package.loaders\") \" must be a table\");\n  lua_pushliteral(L, \"\");  /* error message accumulator */\n  for (i=1; ; i++) {\n    lua_rawgeti(L, -2, i);  /* get a loader */\n    if (lua_isnil(L, -1))\n      luaL_error(L, \"module \" LUA_QS \" not found:%s\",\n                    name, lua_tostring(L, -2));\n    lua_pushstring(L, name);\n    lua_call(L, 1, 1);  /* call it */\n    if (lua_isfunction(L, -1))  /* did it find module? */\n      break;  /* module loaded successfully */\n    else if (lua_isstring(L, -1))  /* loader returned error message? */\n      lua_concat(L, 2);  /* accumulate it */\n    else\n      lua_pop(L, 1);\n  }\n  lua_pushlightuserdata(L, sentinel);\n  lua_setfield(L, 2, name);  /* _LOADED[name] = sentinel */\n  lua_pushstring(L, name);  /* pass name as argument to module */\n  lua_call(L, 1, 1);  /* run loaded module */\n  if (!lua_isnil(L, -1))  /* non-nil return? */\n    lua_setfield(L, 2, name);  /* _LOADED[name] = returned value */\n  lua_getfield(L, 2, name);\n  if (lua_touserdata(L, -1) == sentinel) {   /* module did not set a value? */\n    lua_pushboolean(L, 1);  /* use true as result */\n    lua_pushvalue(L, -1);  /* extra copy to be returned */\n    lua_setfield(L, 2, name);  /* _LOADED[name] = true */\n  }\n  return 1;\n}\n\n/* }====================================================== */\n\n\n\n/*\n** {======================================================\n** 'module' function\n** =======================================================\n*/\n  \n\nstatic void setfenv (lua_State *L) {\n  lua_Debug ar;\n  if (lua_getstack(L, 1, &ar) == 0 ||\n      lua_getinfo(L, \"f\", &ar) == 0 ||  /* get calling function */\n      lua_iscfunction(L, -1))\n    luaL_error(L, LUA_QL(\"module\") \" not called from a Lua function\");\n  lua_pushvalue(L, -2);\n  lua_setfenv(L, -2);\n  lua_pop(L, 1);\n}\n\n\nstatic void dooptions (lua_State *L, int n) {\n  int i;\n  for (i = 2; i <= n; i++) {\n    lua_pushvalue(L, i);  /* get option (a function) */\n    lua_pushvalue(L, -2);  /* module */\n    lua_call(L, 1, 0);\n  }\n}\n\n\nstatic void modinit (lua_State *L, const char *modname) {\n  const char *dot;\n  lua_pushvalue(L, -1);\n  lua_setfield(L, -2, \"_M\");  /* module._M = module */\n  lua_pushstring(L, modname);\n  lua_setfield(L, -2, \"_NAME\");\n  dot = strrchr(modname, '.');  /* look for last dot in module name */\n  if (dot == NULL) dot = modname;\n  else dot++;\n  /* set _PACKAGE as package name (full module name minus last part) */\n  lua_pushlstring(L, modname, dot - modname);\n  lua_setfield(L, -2, \"_PACKAGE\");\n}\n\n\nstatic int ll_module (lua_State *L) {\n  const char *modname = luaL_checkstring(L, 1);\n  int loaded = lua_gettop(L) + 1;  /* index of _LOADED table */\n  lua_getfield(L, LUA_REGISTRYINDEX, \"_LOADED\");\n  lua_getfield(L, loaded, modname);  /* get _LOADED[modname] */\n  if (!lua_istable(L, -1)) {  /* not found? */\n    lua_pop(L, 1);  /* remove previous result */\n    /* try global variable (and create one if it does not exist) */\n    if (luaL_findtable(L, LUA_GLOBALSINDEX, modname, 1) != NULL)\n      return luaL_error(L, \"name conflict for module \" LUA_QS, modname);\n    lua_pushvalue(L, -1);\n    lua_setfield(L, loaded, modname);  /* _LOADED[modname] = new table */\n  }\n  /* check whether table already has a _NAME field */\n  lua_getfield(L, -1, \"_NAME\");\n  if (!lua_isnil(L, -1))  /* is table an initialized module? */\n    lua_pop(L, 1);\n  else {  /* no; initialize it */\n    lua_pop(L, 1);\n    modinit(L, modname);\n  }\n  lua_pushvalue(L, -1);\n  setfenv(L);\n  dooptions(L, loaded - 1);\n  return 0;\n}\n\n\nstatic int ll_seeall (lua_State *L) {\n  luaL_checktype(L, 1, LUA_TTABLE);\n  if (!lua_getmetatable(L, 1)) {\n    lua_createtable(L, 0, 1); /* create new metatable */\n    lua_pushvalue(L, -1);\n    lua_setmetatable(L, 1);\n  }\n  lua_pushvalue(L, LUA_GLOBALSINDEX);\n  lua_setfield(L, -2, \"__index\");  /* mt.__index = _G */\n  return 0;\n}\n\n\n/* }====================================================== */\n\n\n\n/* auxiliary mark (for internal use) */\n#define AUXMARK\t\t\"\\1\"\n\nstatic void setpath (lua_State *L, const char *fieldname, const char *envname,\n                                   const char *def) {\n  const char *path = getenv(envname);\n  if (path == NULL)  /* no environment variable? */\n    lua_pushstring(L, def);  /* use default */\n  else {\n    /* replace \";;\" by \";AUXMARK;\" and then AUXMARK by default path */\n    path = luaL_gsub(L, path, LUA_PATHSEP LUA_PATHSEP,\n                              LUA_PATHSEP AUXMARK LUA_PATHSEP);\n    luaL_gsub(L, path, AUXMARK, def);\n    lua_remove(L, -2);\n  }\n  setprogdir(L);\n  lua_setfield(L, -2, fieldname);\n}\n\n\nstatic const luaL_Reg pk_funcs[] = {\n  {\"loadlib\", ll_loadlib},\n  {\"seeall\", ll_seeall},\n  {NULL, NULL}\n};\n\n\nstatic const luaL_Reg ll_funcs[] = {\n  {\"module\", ll_module},\n  {\"require\", ll_require},\n  {NULL, NULL}\n};\n\n\nstatic const lua_CFunction loaders[] =\n  {loader_preload, loader_Lua, loader_C, loader_Croot, NULL};\n\n\nLUALIB_API int luaopen_package (lua_State *L) {\n  int i;\n  /* create new type _LOADLIB */\n  luaL_newmetatable(L, \"_LOADLIB\");\n  lua_pushcfunction(L, gctm);\n  lua_setfield(L, -2, \"__gc\");\n  /* create `package' table */\n  luaL_register(L, LUA_LOADLIBNAME, pk_funcs);\n#if defined(LUA_COMPAT_LOADLIB) \n  lua_getfield(L, -1, \"loadlib\");\n  lua_setfield(L, LUA_GLOBALSINDEX, \"loadlib\");\n#endif\n  lua_pushvalue(L, -1);\n  lua_replace(L, LUA_ENVIRONINDEX);\n  /* create `loaders' table */\n  lua_createtable(L, sizeof(loaders)/sizeof(loaders[0]) - 1, 0);\n  /* fill it with pre-defined loaders */\n  for (i=0; loaders[i] != NULL; i++) {\n    lua_pushcfunction(L, loaders[i]);\n    lua_rawseti(L, -2, i+1);\n  }\n  lua_setfield(L, -2, \"loaders\");  /* put it in field `loaders' */\n  setpath(L, \"path\", LUA_PATH, LUA_PATH_DEFAULT);  /* set field `path' */\n  setpath(L, \"cpath\", LUA_CPATH, LUA_CPATH_DEFAULT); /* set field `cpath' */\n  /* store config information */\n  lua_pushliteral(L, LUA_DIRSEP \"\\n\" LUA_PATHSEP \"\\n\" LUA_PATH_MARK \"\\n\"\n                     LUA_EXECDIR \"\\n\" LUA_IGMARK);\n  lua_setfield(L, -2, \"config\");\n  /* set field `loaded' */\n  luaL_findtable(L, LUA_REGISTRYINDEX, \"_LOADED\", 2);\n  lua_setfield(L, -2, \"loaded\");\n  /* set field `preload' */\n  lua_newtable(L);\n  lua_setfield(L, -2, \"preload\");\n  lua_pushvalue(L, LUA_GLOBALSINDEX);\n  luaL_register(L, NULL, ll_funcs);  /* open lib into global table */\n  lua_pop(L, 1);\n  return 1;  /* return 'package' table */\n}\n\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/deps/lua/src/lobject.c",
    "content": "/*\n** $Id: lobject.c,v 2.22.1.1 2007/12/27 13:02:25 roberto Exp $\n** Some generic functions over Lua objects\n** See Copyright Notice in lua.h\n*/\n\n#include <ctype.h>\n#include <stdarg.h>\n#include <stdio.h>\n#include <stdlib.h>\n#include <string.h>\n\n#define lobject_c\n#define LUA_CORE\n\n#include \"lua.h\"\n\n#include \"ldo.h\"\n#include \"lmem.h\"\n#include \"lobject.h\"\n#include \"lstate.h\"\n#include \"lstring.h\"\n#include \"lvm.h\"\n\n\n\nconst TValue luaO_nilobject_ = {{NULL}, LUA_TNIL};\n\n\n/*\n** converts an integer to a \"floating point byte\", represented as\n** (eeeeexxx), where the real value is (1xxx) * 2^(eeeee - 1) if\n** eeeee != 0 and (xxx) otherwise.\n*/\nint luaO_int2fb (unsigned int x) {\n  int e = 0;  /* expoent */\n  while (x >= 16) {\n    x = (x+1) >> 1;\n    e++;\n  }\n  if (x < 8) return x;\n  else return ((e+1) << 3) | (cast_int(x) - 8);\n}\n\n\n/* converts back */\nint luaO_fb2int (int x) {\n  int e = (x >> 3) & 31;\n  if (e == 0) return x;\n  else return ((x & 7)+8) << (e - 1);\n}\n\n\nint luaO_log2 (unsigned int x) {\n  static const lu_byte log_2[256] = {\n    0,1,2,2,3,3,3,3,4,4,4,4,4,4,4,4,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,\n    6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,\n    7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,\n    7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,\n    8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,\n    8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,\n    8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,\n    8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8\n  };\n  int l = -1;\n  while (x >= 256) { l += 8; x >>= 8; }\n  return l + log_2[x];\n\n}\n\n\nint luaO_rawequalObj (const TValue *t1, const TValue *t2) {\n  if (ttype(t1) != ttype(t2)) return 0;\n  else switch (ttype(t1)) {\n    case LUA_TNIL:\n      return 1;\n    case LUA_TNUMBER:\n      return luai_numeq(nvalue(t1), nvalue(t2));\n    case LUA_TBOOLEAN:\n      return bvalue(t1) == bvalue(t2);  /* boolean true must be 1 !! */\n    case LUA_TLIGHTUSERDATA:\n      return pvalue(t1) == pvalue(t2);\n    default:\n      lua_assert(iscollectable(t1));\n      return gcvalue(t1) == gcvalue(t2);\n  }\n}\n\n\nint luaO_str2d (const char *s, lua_Number *result) {\n  char *endptr;\n  *result = lua_str2number(s, &endptr);\n  if (endptr == s) return 0;  /* conversion failed */\n  if (*endptr == 'x' || *endptr == 'X')  /* maybe an hexadecimal constant? */\n    *result = cast_num(strtoul(s, &endptr, 16));\n  if (*endptr == '\\0') return 1;  /* most common case */\n  while (isspace(cast(unsigned char, *endptr))) endptr++;\n  if (*endptr != '\\0') return 0;  /* invalid trailing characters? */\n  return 1;\n}\n\n\n\nstatic void pushstr (lua_State *L, const char *str) {\n  setsvalue2s(L, L->top, luaS_new(L, str));\n  incr_top(L);\n}\n\n\n/* this function handles only `%d', `%c', %f, %p, and `%s' formats */\nconst char *luaO_pushvfstring (lua_State *L, const char *fmt, va_list argp) {\n  int n = 1;\n  pushstr(L, \"\");\n  for (;;) {\n    const char *e = strchr(fmt, '%');\n    if (e == NULL) break;\n    setsvalue2s(L, L->top, luaS_newlstr(L, fmt, e-fmt));\n    incr_top(L);\n    switch (*(e+1)) {\n      case 's': {\n        const char *s = va_arg(argp, char *);\n        if (s == NULL) s = \"(null)\";\n        pushstr(L, s);\n        break;\n      }\n      case 'c': {\n        char buff[2];\n        buff[0] = cast(char, va_arg(argp, int));\n        buff[1] = '\\0';\n        pushstr(L, buff);\n        break;\n      }\n      case 'd': {\n        setnvalue(L->top, cast_num(va_arg(argp, int)));\n        incr_top(L);\n        break;\n      }\n      case 'f': {\n        setnvalue(L->top, cast_num(va_arg(argp, l_uacNumber)));\n        incr_top(L);\n        break;\n      }\n      case 'p': {\n        char buff[4*sizeof(void *) + 8]; /* should be enough space for a `%p' */\n        sprintf(buff, \"%p\", va_arg(argp, void *));\n        pushstr(L, buff);\n        break;\n      }\n      case '%': {\n        pushstr(L, \"%\");\n        break;\n      }\n      default: {\n        char buff[3];\n        buff[0] = '%';\n        buff[1] = *(e+1);\n        buff[2] = '\\0';\n        pushstr(L, buff);\n        break;\n      }\n    }\n    n += 2;\n    fmt = e+2;\n  }\n  pushstr(L, fmt);\n  luaV_concat(L, n+1, cast_int(L->top - L->base) - 1);\n  L->top -= n;\n  return svalue(L->top - 1);\n}\n\n\nconst char *luaO_pushfstring (lua_State *L, const char *fmt, ...) {\n  const char *msg;\n  va_list argp;\n  va_start(argp, fmt);\n  msg = luaO_pushvfstring(L, fmt, argp);\n  va_end(argp);\n  return msg;\n}\n\n\nvoid luaO_chunkid (char *out, const char *source, size_t bufflen) {\n  if (*source == '=') {\n    strncpy(out, source+1, bufflen);  /* remove first char */\n    out[bufflen-1] = '\\0';  /* ensures null termination */\n  }\n  else {  /* out = \"source\", or \"...source\" */\n    if (*source == '@') {\n      size_t l;\n      source++;  /* skip the `@' */\n      bufflen -= sizeof(\" '...' \");\n      l = strlen(source);\n      strcpy(out, \"\");\n      if (l > bufflen) {\n        source += (l-bufflen);  /* get last part of file name */\n        strcat(out, \"...\");\n      }\n      strcat(out, source);\n    }\n    else {  /* out = [string \"string\"] */\n      size_t len = strcspn(source, \"\\n\\r\");  /* stop at first newline */\n      bufflen -= sizeof(\" [string \\\"...\\\"] \");\n      if (len > bufflen) len = bufflen;\n      strcpy(out, \"[string \\\"\");\n      if (source[len] != '\\0') {  /* must truncate? */\n        strncat(out, source, len);\n        strcat(out, \"...\");\n      }\n      else\n        strcat(out, source);\n      strcat(out, \"\\\"]\");\n    }\n  }\n}\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/deps/lua/src/lobject.h",
    "content": "/*\n** $Id: lobject.h,v 2.20.1.2 2008/08/06 13:29:48 roberto Exp $\n** Type definitions for Lua objects\n** See Copyright Notice in lua.h\n*/\n\n\n#ifndef lobject_h\n#define lobject_h\n\n\n#include <stdarg.h>\n\n\n#include \"llimits.h\"\n#include \"lua.h\"\n\n\n/* tags for values visible from Lua */\n#define LAST_TAG\tLUA_TTHREAD\n\n#define NUM_TAGS\t(LAST_TAG+1)\n\n\n/*\n** Extra tags for non-values\n*/\n#define LUA_TPROTO\t(LAST_TAG+1)\n#define LUA_TUPVAL\t(LAST_TAG+2)\n#define LUA_TDEADKEY\t(LAST_TAG+3)\n\n\n/*\n** Union of all collectable objects\n*/\ntypedef union GCObject GCObject;\n\n\n/*\n** Common Header for all collectable objects (in macro form, to be\n** included in other objects)\n*/\n#define CommonHeader\tGCObject *next; lu_byte tt; lu_byte marked\n\n\n/*\n** Common header in struct form\n*/\ntypedef struct GCheader {\n  CommonHeader;\n} GCheader;\n\n\n\n\n/*\n** Union of all Lua values\n*/\ntypedef union {\n  GCObject *gc;\n  void *p;\n  lua_Number n;\n  int b;\n} Value;\n\n\n/*\n** Tagged Values\n*/\n\n#define TValuefields\tValue value; int tt\n\ntypedef struct lua_TValue {\n  TValuefields;\n} TValue;\n\n\n/* Macros to test type */\n#define ttisnil(o)\t(ttype(o) == LUA_TNIL)\n#define ttisnumber(o)\t(ttype(o) == LUA_TNUMBER)\n#define ttisstring(o)\t(ttype(o) == LUA_TSTRING)\n#define ttistable(o)\t(ttype(o) == LUA_TTABLE)\n#define ttisfunction(o)\t(ttype(o) == LUA_TFUNCTION)\n#define ttisboolean(o)\t(ttype(o) == LUA_TBOOLEAN)\n#define ttisuserdata(o)\t(ttype(o) == LUA_TUSERDATA)\n#define ttisthread(o)\t(ttype(o) == LUA_TTHREAD)\n#define ttislightuserdata(o)\t(ttype(o) == LUA_TLIGHTUSERDATA)\n\n/* Macros to access values */\n#define ttype(o)\t((o)->tt)\n#define gcvalue(o)\tcheck_exp(iscollectable(o), (o)->value.gc)\n#define pvalue(o)\tcheck_exp(ttislightuserdata(o), (o)->value.p)\n#define nvalue(o)\tcheck_exp(ttisnumber(o), (o)->value.n)\n#define rawtsvalue(o)\tcheck_exp(ttisstring(o), &(o)->value.gc->ts)\n#define tsvalue(o)\t(&rawtsvalue(o)->tsv)\n#define rawuvalue(o)\tcheck_exp(ttisuserdata(o), &(o)->value.gc->u)\n#define uvalue(o)\t(&rawuvalue(o)->uv)\n#define clvalue(o)\tcheck_exp(ttisfunction(o), &(o)->value.gc->cl)\n#define hvalue(o)\tcheck_exp(ttistable(o), &(o)->value.gc->h)\n#define bvalue(o)\tcheck_exp(ttisboolean(o), (o)->value.b)\n#define thvalue(o)\tcheck_exp(ttisthread(o), &(o)->value.gc->th)\n\n#define l_isfalse(o)\t(ttisnil(o) || (ttisboolean(o) && bvalue(o) == 0))\n\n/*\n** for internal debug only\n*/\n#define checkconsistency(obj) \\\n  lua_assert(!iscollectable(obj) || (ttype(obj) == (obj)->value.gc->gch.tt))\n\n#define checkliveness(g,obj) \\\n  lua_assert(!iscollectable(obj) || \\\n  ((ttype(obj) == (obj)->value.gc->gch.tt) && !isdead(g, (obj)->value.gc)))\n\n\n/* Macros to set values */\n#define setnilvalue(obj) ((obj)->tt=LUA_TNIL)\n\n#define setnvalue(obj,x) \\\n  { TValue *i_o=(obj); i_o->value.n=(x); i_o->tt=LUA_TNUMBER; }\n\n#define setpvalue(obj,x) \\\n  { TValue *i_o=(obj); i_o->value.p=(x); i_o->tt=LUA_TLIGHTUSERDATA; }\n\n#define setbvalue(obj,x) \\\n  { TValue *i_o=(obj); i_o->value.b=(x); i_o->tt=LUA_TBOOLEAN; }\n\n#define setsvalue(L,obj,x) \\\n  { TValue *i_o=(obj); \\\n    i_o->value.gc=cast(GCObject *, (x)); i_o->tt=LUA_TSTRING; \\\n    checkliveness(G(L),i_o); }\n\n#define setuvalue(L,obj,x) \\\n  { TValue *i_o=(obj); \\\n    i_o->value.gc=cast(GCObject *, (x)); i_o->tt=LUA_TUSERDATA; \\\n    checkliveness(G(L),i_o); }\n\n#define setthvalue(L,obj,x) \\\n  { TValue *i_o=(obj); \\\n    i_o->value.gc=cast(GCObject *, (x)); i_o->tt=LUA_TTHREAD; \\\n    checkliveness(G(L),i_o); }\n\n#define setclvalue(L,obj,x) \\\n  { TValue *i_o=(obj); \\\n    i_o->value.gc=cast(GCObject *, (x)); i_o->tt=LUA_TFUNCTION; \\\n    checkliveness(G(L),i_o); }\n\n#define sethvalue(L,obj,x) \\\n  { TValue *i_o=(obj); \\\n    i_o->value.gc=cast(GCObject *, (x)); i_o->tt=LUA_TTABLE; \\\n    checkliveness(G(L),i_o); }\n\n#define setptvalue(L,obj,x) \\\n  { TValue *i_o=(obj); \\\n    i_o->value.gc=cast(GCObject *, (x)); i_o->tt=LUA_TPROTO; \\\n    checkliveness(G(L),i_o); }\n\n\n\n\n#define setobj(L,obj1,obj2) \\\n  { const TValue *o2=(obj2); TValue *o1=(obj1); \\\n    o1->value = o2->value; o1->tt=o2->tt; \\\n    checkliveness(G(L),o1); }\n\n\n/*\n** different types of sets, according to destination\n*/\n\n/* from stack to (same) stack */\n#define setobjs2s\tsetobj\n/* to stack (not from same stack) */\n#define setobj2s\tsetobj\n#define setsvalue2s\tsetsvalue\n#define sethvalue2s\tsethvalue\n#define setptvalue2s\tsetptvalue\n/* from table to same table */\n#define setobjt2t\tsetobj\n/* to table */\n#define setobj2t\tsetobj\n/* to new object */\n#define setobj2n\tsetobj\n#define setsvalue2n\tsetsvalue\n\n#define setttype(obj, tt) (ttype(obj) = (tt))\n\n\n#define iscollectable(o)\t(ttype(o) >= LUA_TSTRING)\n\n\n\ntypedef TValue *StkId;  /* index to stack elements */\n\n\n/*\n** String headers for string table\n*/\ntypedef union TString {\n  L_Umaxalign dummy;  /* ensures maximum alignment for strings */\n  struct {\n    CommonHeader;\n    lu_byte reserved;\n    unsigned int hash;\n    size_t len;\n  } tsv;\n} TString;\n\n\n#define getstr(ts)\tcast(const char *, (ts) + 1)\n#define svalue(o)       getstr(rawtsvalue(o))\n\n\n\ntypedef union Udata {\n  L_Umaxalign dummy;  /* ensures maximum alignment for `local' udata */\n  struct {\n    CommonHeader;\n    struct Table *metatable;\n    struct Table *env;\n    size_t len;\n  } uv;\n} Udata;\n\n\n\n\n/*\n** Function Prototypes\n*/\ntypedef struct Proto {\n  CommonHeader;\n  TValue *k;  /* constants used by the function */\n  Instruction *code;\n  struct Proto **p;  /* functions defined inside the function */\n  int *lineinfo;  /* map from opcodes to source lines */\n  struct LocVar *locvars;  /* information about local variables */\n  TString **upvalues;  /* upvalue names */\n  TString  *source;\n  int sizeupvalues;\n  int sizek;  /* size of `k' */\n  int sizecode;\n  int sizelineinfo;\n  int sizep;  /* size of `p' */\n  int sizelocvars;\n  int linedefined;\n  int lastlinedefined;\n  GCObject *gclist;\n  lu_byte nups;  /* number of upvalues */\n  lu_byte numparams;\n  lu_byte is_vararg;\n  lu_byte maxstacksize;\n} Proto;\n\n\n/* masks for new-style vararg */\n#define VARARG_HASARG\t\t1\n#define VARARG_ISVARARG\t\t2\n#define VARARG_NEEDSARG\t\t4\n\n\ntypedef struct LocVar {\n  TString *varname;\n  int startpc;  /* first point where variable is active */\n  int endpc;    /* first point where variable is dead */\n} LocVar;\n\n\n\n/*\n** Upvalues\n*/\n\ntypedef struct UpVal {\n  CommonHeader;\n  TValue *v;  /* points to stack or to its own value */\n  union {\n    TValue value;  /* the value (when closed) */\n    struct {  /* double linked list (when open) */\n      struct UpVal *prev;\n      struct UpVal *next;\n    } l;\n  } u;\n} UpVal;\n\n\n/*\n** Closures\n*/\n\n#define ClosureHeader \\\n\tCommonHeader; lu_byte isC; lu_byte nupvalues; GCObject *gclist; \\\n\tstruct Table *env\n\ntypedef struct CClosure {\n  ClosureHeader;\n  lua_CFunction f;\n  TValue upvalue[1];\n} CClosure;\n\n\ntypedef struct LClosure {\n  ClosureHeader;\n  struct Proto *p;\n  UpVal *upvals[1];\n} LClosure;\n\n\ntypedef union Closure {\n  CClosure c;\n  LClosure l;\n} Closure;\n\n\n#define iscfunction(o)\t(ttype(o) == LUA_TFUNCTION && clvalue(o)->c.isC)\n#define isLfunction(o)\t(ttype(o) == LUA_TFUNCTION && !clvalue(o)->c.isC)\n\n\n/*\n** Tables\n*/\n\ntypedef union TKey {\n  struct {\n    TValuefields;\n    struct Node *next;  /* for chaining */\n  } nk;\n  TValue tvk;\n} TKey;\n\n\ntypedef struct Node {\n  TValue i_val;\n  TKey i_key;\n} Node;\n\n\ntypedef struct Table {\n  CommonHeader;\n  lu_byte flags;  /* 1<<p means tagmethod(p) is not present */ \n  lu_byte lsizenode;  /* log2 of size of `node' array */\n  struct Table *metatable;\n  TValue *array;  /* array part */\n  Node *node;\n  Node *lastfree;  /* any free position is before this position */\n  GCObject *gclist;\n  int sizearray;  /* size of `array' array */\n} Table;\n\n\n\n/*\n** `module' operation for hashing (size is always a power of 2)\n*/\n#define lmod(s,size) \\\n\t(check_exp((size&(size-1))==0, (cast(int, (s) & ((size)-1)))))\n\n\n#define twoto(x)\t(1<<(x))\n#define sizenode(t)\t(twoto((t)->lsizenode))\n\n\n#define luaO_nilobject\t\t(&luaO_nilobject_)\n\nLUAI_DATA const TValue luaO_nilobject_;\n\n#define ceillog2(x)\t(luaO_log2((x)-1) + 1)\n\nLUAI_FUNC int luaO_log2 (unsigned int x);\nLUAI_FUNC int luaO_int2fb (unsigned int x);\nLUAI_FUNC int luaO_fb2int (int x);\nLUAI_FUNC int luaO_rawequalObj (const TValue *t1, const TValue *t2);\nLUAI_FUNC int luaO_str2d (const char *s, lua_Number *result);\nLUAI_FUNC const char *luaO_pushvfstring (lua_State *L, const char *fmt,\n                                                       va_list argp);\nLUAI_FUNC const char *luaO_pushfstring (lua_State *L, const char *fmt, ...);\nLUAI_FUNC void luaO_chunkid (char *out, const char *source, size_t len);\n\n\n#endif\n\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/deps/lua/src/lopcodes.c",
    "content": "/*\n** $Id: lopcodes.c,v 1.37.1.1 2007/12/27 13:02:25 roberto Exp $\n** See Copyright Notice in lua.h\n*/\n\n\n#define lopcodes_c\n#define LUA_CORE\n\n\n#include \"lopcodes.h\"\n\n\n/* ORDER OP */\n\nconst char *const luaP_opnames[NUM_OPCODES+1] = {\n  \"MOVE\",\n  \"LOADK\",\n  \"LOADBOOL\",\n  \"LOADNIL\",\n  \"GETUPVAL\",\n  \"GETGLOBAL\",\n  \"GETTABLE\",\n  \"SETGLOBAL\",\n  \"SETUPVAL\",\n  \"SETTABLE\",\n  \"NEWTABLE\",\n  \"SELF\",\n  \"ADD\",\n  \"SUB\",\n  \"MUL\",\n  \"DIV\",\n  \"MOD\",\n  \"POW\",\n  \"UNM\",\n  \"NOT\",\n  \"LEN\",\n  \"CONCAT\",\n  \"JMP\",\n  \"EQ\",\n  \"LT\",\n  \"LE\",\n  \"TEST\",\n  \"TESTSET\",\n  \"CALL\",\n  \"TAILCALL\",\n  \"RETURN\",\n  \"FORLOOP\",\n  \"FORPREP\",\n  \"TFORLOOP\",\n  \"SETLIST\",\n  \"CLOSE\",\n  \"CLOSURE\",\n  \"VARARG\",\n  NULL\n};\n\n\n#define opmode(t,a,b,c,m) (((t)<<7) | ((a)<<6) | ((b)<<4) | ((c)<<2) | (m))\n\nconst lu_byte luaP_opmodes[NUM_OPCODES] = {\n/*       T  A    B       C     mode\t\t   opcode\t*/\n  opmode(0, 1, OpArgR, OpArgN, iABC) \t\t/* OP_MOVE */\n ,opmode(0, 1, OpArgK, OpArgN, iABx)\t\t/* OP_LOADK */\n ,opmode(0, 1, OpArgU, OpArgU, iABC)\t\t/* OP_LOADBOOL */\n ,opmode(0, 1, OpArgR, OpArgN, iABC)\t\t/* OP_LOADNIL */\n ,opmode(0, 1, OpArgU, OpArgN, iABC)\t\t/* OP_GETUPVAL */\n ,opmode(0, 1, OpArgK, OpArgN, iABx)\t\t/* OP_GETGLOBAL */\n ,opmode(0, 1, OpArgR, OpArgK, iABC)\t\t/* OP_GETTABLE */\n ,opmode(0, 0, OpArgK, OpArgN, iABx)\t\t/* OP_SETGLOBAL */\n ,opmode(0, 0, OpArgU, OpArgN, iABC)\t\t/* OP_SETUPVAL */\n ,opmode(0, 0, OpArgK, OpArgK, iABC)\t\t/* OP_SETTABLE */\n ,opmode(0, 1, OpArgU, OpArgU, iABC)\t\t/* OP_NEWTABLE */\n ,opmode(0, 1, OpArgR, OpArgK, iABC)\t\t/* OP_SELF */\n ,opmode(0, 1, OpArgK, OpArgK, iABC)\t\t/* OP_ADD */\n ,opmode(0, 1, OpArgK, OpArgK, iABC)\t\t/* OP_SUB */\n ,opmode(0, 1, OpArgK, OpArgK, iABC)\t\t/* OP_MUL */\n ,opmode(0, 1, OpArgK, OpArgK, iABC)\t\t/* OP_DIV */\n ,opmode(0, 1, OpArgK, OpArgK, iABC)\t\t/* OP_MOD */\n ,opmode(0, 1, OpArgK, OpArgK, iABC)\t\t/* OP_POW */\n ,opmode(0, 1, OpArgR, OpArgN, iABC)\t\t/* OP_UNM */\n ,opmode(0, 1, OpArgR, OpArgN, iABC)\t\t/* OP_NOT */\n ,opmode(0, 1, OpArgR, OpArgN, iABC)\t\t/* OP_LEN */\n ,opmode(0, 1, OpArgR, OpArgR, iABC)\t\t/* OP_CONCAT */\n ,opmode(0, 0, OpArgR, OpArgN, iAsBx)\t\t/* OP_JMP */\n ,opmode(1, 0, OpArgK, OpArgK, iABC)\t\t/* OP_EQ */\n ,opmode(1, 0, OpArgK, OpArgK, iABC)\t\t/* OP_LT */\n ,opmode(1, 0, OpArgK, OpArgK, iABC)\t\t/* OP_LE */\n ,opmode(1, 1, OpArgR, OpArgU, iABC)\t\t/* OP_TEST */\n ,opmode(1, 1, OpArgR, OpArgU, iABC)\t\t/* OP_TESTSET */\n ,opmode(0, 1, OpArgU, OpArgU, iABC)\t\t/* OP_CALL */\n ,opmode(0, 1, OpArgU, OpArgU, iABC)\t\t/* OP_TAILCALL */\n ,opmode(0, 0, OpArgU, OpArgN, iABC)\t\t/* OP_RETURN */\n ,opmode(0, 1, OpArgR, OpArgN, iAsBx)\t\t/* OP_FORLOOP */\n ,opmode(0, 1, OpArgR, OpArgN, iAsBx)\t\t/* OP_FORPREP */\n ,opmode(1, 0, OpArgN, OpArgU, iABC)\t\t/* OP_TFORLOOP */\n ,opmode(0, 0, OpArgU, OpArgU, iABC)\t\t/* OP_SETLIST */\n ,opmode(0, 0, OpArgN, OpArgN, iABC)\t\t/* OP_CLOSE */\n ,opmode(0, 1, OpArgU, OpArgN, iABx)\t\t/* OP_CLOSURE */\n ,opmode(0, 1, OpArgU, OpArgN, iABC)\t\t/* OP_VARARG */\n};\n\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/deps/lua/src/lopcodes.h",
    "content": "/*\n** $Id: lopcodes.h,v 1.125.1.1 2007/12/27 13:02:25 roberto Exp $\n** Opcodes for Lua virtual machine\n** See Copyright Notice in lua.h\n*/\n\n#ifndef lopcodes_h\n#define lopcodes_h\n\n#include \"llimits.h\"\n\n\n/*===========================================================================\n  We assume that instructions are unsigned numbers.\n  All instructions have an opcode in the first 6 bits.\n  Instructions can have the following fields:\n\t`A' : 8 bits\n\t`B' : 9 bits\n\t`C' : 9 bits\n\t`Bx' : 18 bits (`B' and `C' together)\n\t`sBx' : signed Bx\n\n  A signed argument is represented in excess K; that is, the number\n  value is the unsigned value minus K. K is exactly the maximum value\n  for that argument (so that -max is represented by 0, and +max is\n  represented by 2*max), which is half the maximum for the corresponding\n  unsigned argument.\n===========================================================================*/\n\n\nenum OpMode {iABC, iABx, iAsBx};  /* basic instruction format */\n\n\n/*\n** size and position of opcode arguments.\n*/\n#define SIZE_C\t\t9\n#define SIZE_B\t\t9\n#define SIZE_Bx\t\t(SIZE_C + SIZE_B)\n#define SIZE_A\t\t8\n\n#define SIZE_OP\t\t6\n\n#define POS_OP\t\t0\n#define POS_A\t\t(POS_OP + SIZE_OP)\n#define POS_C\t\t(POS_A + SIZE_A)\n#define POS_B\t\t(POS_C + SIZE_C)\n#define POS_Bx\t\tPOS_C\n\n\n/*\n** limits for opcode arguments.\n** we use (signed) int to manipulate most arguments,\n** so they must fit in LUAI_BITSINT-1 bits (-1 for sign)\n*/\n#if SIZE_Bx < LUAI_BITSINT-1\n#define MAXARG_Bx        ((1<<SIZE_Bx)-1)\n#define MAXARG_sBx        (MAXARG_Bx>>1)         /* `sBx' is signed */\n#else\n#define MAXARG_Bx        MAX_INT\n#define MAXARG_sBx        MAX_INT\n#endif\n\n\n#define MAXARG_A        ((1<<SIZE_A)-1)\n#define MAXARG_B        ((1<<SIZE_B)-1)\n#define MAXARG_C        ((1<<SIZE_C)-1)\n\n\n/* creates a mask with `n' 1 bits at position `p' */\n#define MASK1(n,p)\t((~((~(Instruction)0)<<n))<<p)\n\n/* creates a mask with `n' 0 bits at position `p' */\n#define MASK0(n,p)\t(~MASK1(n,p))\n\n/*\n** the following macros help to manipulate instructions\n*/\n\n#define GET_OPCODE(i)\t(cast(OpCode, ((i)>>POS_OP) & MASK1(SIZE_OP,0)))\n#define SET_OPCODE(i,o)\t((i) = (((i)&MASK0(SIZE_OP,POS_OP)) | \\\n\t\t((cast(Instruction, o)<<POS_OP)&MASK1(SIZE_OP,POS_OP))))\n\n#define GETARG_A(i)\t(cast(int, ((i)>>POS_A) & MASK1(SIZE_A,0)))\n#define SETARG_A(i,u)\t((i) = (((i)&MASK0(SIZE_A,POS_A)) | \\\n\t\t((cast(Instruction, u)<<POS_A)&MASK1(SIZE_A,POS_A))))\n\n#define GETARG_B(i)\t(cast(int, ((i)>>POS_B) & MASK1(SIZE_B,0)))\n#define SETARG_B(i,b)\t((i) = (((i)&MASK0(SIZE_B,POS_B)) | \\\n\t\t((cast(Instruction, b)<<POS_B)&MASK1(SIZE_B,POS_B))))\n\n#define GETARG_C(i)\t(cast(int, ((i)>>POS_C) & MASK1(SIZE_C,0)))\n#define SETARG_C(i,b)\t((i) = (((i)&MASK0(SIZE_C,POS_C)) | \\\n\t\t((cast(Instruction, b)<<POS_C)&MASK1(SIZE_C,POS_C))))\n\n#define GETARG_Bx(i)\t(cast(int, ((i)>>POS_Bx) & MASK1(SIZE_Bx,0)))\n#define SETARG_Bx(i,b)\t((i) = (((i)&MASK0(SIZE_Bx,POS_Bx)) | \\\n\t\t((cast(Instruction, b)<<POS_Bx)&MASK1(SIZE_Bx,POS_Bx))))\n\n#define GETARG_sBx(i)\t(GETARG_Bx(i)-MAXARG_sBx)\n#define SETARG_sBx(i,b)\tSETARG_Bx((i),cast(unsigned int, (b)+MAXARG_sBx))\n\n\n#define CREATE_ABC(o,a,b,c)\t((cast(Instruction, o)<<POS_OP) \\\n\t\t\t| (cast(Instruction, a)<<POS_A) \\\n\t\t\t| (cast(Instruction, b)<<POS_B) \\\n\t\t\t| (cast(Instruction, c)<<POS_C))\n\n#define CREATE_ABx(o,a,bc)\t((cast(Instruction, o)<<POS_OP) \\\n\t\t\t| (cast(Instruction, a)<<POS_A) \\\n\t\t\t| (cast(Instruction, bc)<<POS_Bx))\n\n\n/*\n** Macros to operate RK indices\n*/\n\n/* this bit 1 means constant (0 means register) */\n#define BITRK\t\t(1 << (SIZE_B - 1))\n\n/* test whether value is a constant */\n#define ISK(x)\t\t((x) & BITRK)\n\n/* gets the index of the constant */\n#define INDEXK(r)\t((int)(r) & ~BITRK)\n\n#define MAXINDEXRK\t(BITRK - 1)\n\n/* code a constant index as a RK value */\n#define RKASK(x)\t((x) | BITRK)\n\n\n/*\n** invalid register that fits in 8 bits\n*/\n#define NO_REG\t\tMAXARG_A\n\n\n/*\n** R(x) - register\n** Kst(x) - constant (in constant table)\n** RK(x) == if ISK(x) then Kst(INDEXK(x)) else R(x)\n*/\n\n\n/*\n** grep \"ORDER OP\" if you change these enums\n*/\n\ntypedef enum {\n/*----------------------------------------------------------------------\nname\t\targs\tdescription\n------------------------------------------------------------------------*/\nOP_MOVE,/*\tA B\tR(A) := R(B)\t\t\t\t\t*/\nOP_LOADK,/*\tA Bx\tR(A) := Kst(Bx)\t\t\t\t\t*/\nOP_LOADBOOL,/*\tA B C\tR(A) := (Bool)B; if (C) pc++\t\t\t*/\nOP_LOADNIL,/*\tA B\tR(A) := ... := R(B) := nil\t\t\t*/\nOP_GETUPVAL,/*\tA B\tR(A) := UpValue[B]\t\t\t\t*/\n\nOP_GETGLOBAL,/*\tA Bx\tR(A) := Gbl[Kst(Bx)]\t\t\t\t*/\nOP_GETTABLE,/*\tA B C\tR(A) := R(B)[RK(C)]\t\t\t\t*/\n\nOP_SETGLOBAL,/*\tA Bx\tGbl[Kst(Bx)] := R(A)\t\t\t\t*/\nOP_SETUPVAL,/*\tA B\tUpValue[B] := R(A)\t\t\t\t*/\nOP_SETTABLE,/*\tA B C\tR(A)[RK(B)] := RK(C)\t\t\t\t*/\n\nOP_NEWTABLE,/*\tA B C\tR(A) := {} (size = B,C)\t\t\t\t*/\n\nOP_SELF,/*\tA B C\tR(A+1) := R(B); R(A) := R(B)[RK(C)]\t\t*/\n\nOP_ADD,/*\tA B C\tR(A) := RK(B) + RK(C)\t\t\t\t*/\nOP_SUB,/*\tA B C\tR(A) := RK(B) - RK(C)\t\t\t\t*/\nOP_MUL,/*\tA B C\tR(A) := RK(B) * RK(C)\t\t\t\t*/\nOP_DIV,/*\tA B C\tR(A) := RK(B) / RK(C)\t\t\t\t*/\nOP_MOD,/*\tA B C\tR(A) := RK(B) % RK(C)\t\t\t\t*/\nOP_POW,/*\tA B C\tR(A) := RK(B) ^ RK(C)\t\t\t\t*/\nOP_UNM,/*\tA B\tR(A) := -R(B)\t\t\t\t\t*/\nOP_NOT,/*\tA B\tR(A) := not R(B)\t\t\t\t*/\nOP_LEN,/*\tA B\tR(A) := length of R(B)\t\t\t\t*/\n\nOP_CONCAT,/*\tA B C\tR(A) := R(B).. ... ..R(C)\t\t\t*/\n\nOP_JMP,/*\tsBx\tpc+=sBx\t\t\t\t\t*/\n\nOP_EQ,/*\tA B C\tif ((RK(B) == RK(C)) ~= A) then pc++\t\t*/\nOP_LT,/*\tA B C\tif ((RK(B) <  RK(C)) ~= A) then pc++  \t\t*/\nOP_LE,/*\tA B C\tif ((RK(B) <= RK(C)) ~= A) then pc++  \t\t*/\n\nOP_TEST,/*\tA C\tif not (R(A) <=> C) then pc++\t\t\t*/ \nOP_TESTSET,/*\tA B C\tif (R(B) <=> C) then R(A) := R(B) else pc++\t*/ \n\nOP_CALL,/*\tA B C\tR(A), ... ,R(A+C-2) := R(A)(R(A+1), ... ,R(A+B-1)) */\nOP_TAILCALL,/*\tA B C\treturn R(A)(R(A+1), ... ,R(A+B-1))\t\t*/\nOP_RETURN,/*\tA B\treturn R(A), ... ,R(A+B-2)\t(see note)\t*/\n\nOP_FORLOOP,/*\tA sBx\tR(A)+=R(A+2);\n\t\t\tif R(A) <?= R(A+1) then { pc+=sBx; R(A+3)=R(A) }*/\nOP_FORPREP,/*\tA sBx\tR(A)-=R(A+2); pc+=sBx\t\t\t\t*/\n\nOP_TFORLOOP,/*\tA C\tR(A+3), ... ,R(A+2+C) := R(A)(R(A+1), R(A+2)); \n                        if R(A+3) ~= nil then R(A+2)=R(A+3) else pc++\t*/ \nOP_SETLIST,/*\tA B C\tR(A)[(C-1)*FPF+i] := R(A+i), 1 <= i <= B\t*/\n\nOP_CLOSE,/*\tA \tclose all variables in the stack up to (>=) R(A)*/\nOP_CLOSURE,/*\tA Bx\tR(A) := closure(KPROTO[Bx], R(A), ... ,R(A+n))\t*/\n\nOP_VARARG/*\tA B\tR(A), R(A+1), ..., R(A+B-1) = vararg\t\t*/\n} OpCode;\n\n\n#define NUM_OPCODES\t(cast(int, OP_VARARG) + 1)\n\n\n\n/*===========================================================================\n  Notes:\n  (*) In OP_CALL, if (B == 0) then B = top. C is the number of returns - 1,\n      and can be 0: OP_CALL then sets `top' to last_result+1, so\n      next open instruction (OP_CALL, OP_RETURN, OP_SETLIST) may use `top'.\n\n  (*) In OP_VARARG, if (B == 0) then use actual number of varargs and\n      set top (like in OP_CALL with C == 0).\n\n  (*) In OP_RETURN, if (B == 0) then return up to `top'\n\n  (*) In OP_SETLIST, if (B == 0) then B = `top';\n      if (C == 0) then next `instruction' is real C\n\n  (*) For comparisons, A specifies what condition the test should accept\n      (true or false).\n\n  (*) All `skips' (pc++) assume that next instruction is a jump\n===========================================================================*/\n\n\n/*\n** masks for instruction properties. The format is:\n** bits 0-1: op mode\n** bits 2-3: C arg mode\n** bits 4-5: B arg mode\n** bit 6: instruction set register A\n** bit 7: operator is a test\n*/  \n\nenum OpArgMask {\n  OpArgN,  /* argument is not used */\n  OpArgU,  /* argument is used */\n  OpArgR,  /* argument is a register or a jump offset */\n  OpArgK   /* argument is a constant or register/constant */\n};\n\nLUAI_DATA const lu_byte luaP_opmodes[NUM_OPCODES];\n\n#define getOpMode(m)\t(cast(enum OpMode, luaP_opmodes[m] & 3))\n#define getBMode(m)\t(cast(enum OpArgMask, (luaP_opmodes[m] >> 4) & 3))\n#define getCMode(m)\t(cast(enum OpArgMask, (luaP_opmodes[m] >> 2) & 3))\n#define testAMode(m)\t(luaP_opmodes[m] & (1 << 6))\n#define testTMode(m)\t(luaP_opmodes[m] & (1 << 7))\n\n\nLUAI_DATA const char *const luaP_opnames[NUM_OPCODES+1];  /* opcode names */\n\n\n/* number of list items to accumulate before a SETLIST instruction */\n#define LFIELDS_PER_FLUSH\t50\n\n\n#endif\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/deps/lua/src/loslib.c",
    "content": "/*\n** $Id: loslib.c,v 1.19.1.3 2008/01/18 16:38:18 roberto Exp $\n** Standard Operating System library\n** See Copyright Notice in lua.h\n*/\n\n\n#include <errno.h>\n#include <locale.h>\n#include <stdlib.h>\n#include <string.h>\n#include <time.h>\n\n#define loslib_c\n#define LUA_LIB\n\n#include \"lua.h\"\n\n#include \"lauxlib.h\"\n#include \"lualib.h\"\n\n\nstatic int os_pushresult (lua_State *L, int i, const char *filename) {\n  int en = errno;  /* calls to Lua API may change this value */\n  if (i) {\n    lua_pushboolean(L, 1);\n    return 1;\n  }\n  else {\n    lua_pushnil(L);\n    lua_pushfstring(L, \"%s: %s\", filename, strerror(en));\n    lua_pushinteger(L, en);\n    return 3;\n  }\n}\n\n\nstatic int os_execute (lua_State *L) {\n  lua_pushinteger(L, system(luaL_optstring(L, 1, NULL)));\n  return 1;\n}\n\n\nstatic int os_remove (lua_State *L) {\n  const char *filename = luaL_checkstring(L, 1);\n  return os_pushresult(L, remove(filename) == 0, filename);\n}\n\n\nstatic int os_rename (lua_State *L) {\n  const char *fromname = luaL_checkstring(L, 1);\n  const char *toname = luaL_checkstring(L, 2);\n  return os_pushresult(L, rename(fromname, toname) == 0, fromname);\n}\n\n\nstatic int os_tmpname (lua_State *L) {\n  char buff[LUA_TMPNAMBUFSIZE];\n  int err;\n  lua_tmpnam(buff, err);\n  if (err)\n    return luaL_error(L, \"unable to generate a unique filename\");\n  lua_pushstring(L, buff);\n  return 1;\n}\n\n\nstatic int os_getenv (lua_State *L) {\n  lua_pushstring(L, getenv(luaL_checkstring(L, 1)));  /* if NULL push nil */\n  return 1;\n}\n\n\nstatic int os_clock (lua_State *L) {\n  lua_pushnumber(L, ((lua_Number)clock())/(lua_Number)CLOCKS_PER_SEC);\n  return 1;\n}\n\n\n/*\n** {======================================================\n** Time/Date operations\n** { year=%Y, month=%m, day=%d, hour=%H, min=%M, sec=%S,\n**   wday=%w+1, yday=%j, isdst=? }\n** =======================================================\n*/\n\nstatic void setfield (lua_State *L, const char *key, int value) {\n  lua_pushinteger(L, value);\n  lua_setfield(L, -2, key);\n}\n\nstatic void setboolfield (lua_State *L, const char *key, int value) {\n  if (value < 0)  /* undefined? */\n    return;  /* does not set field */\n  lua_pushboolean(L, value);\n  lua_setfield(L, -2, key);\n}\n\nstatic int getboolfield (lua_State *L, const char *key) {\n  int res;\n  lua_getfield(L, -1, key);\n  res = lua_isnil(L, -1) ? -1 : lua_toboolean(L, -1);\n  lua_pop(L, 1);\n  return res;\n}\n\n\nstatic int getfield (lua_State *L, const char *key, int d) {\n  int res;\n  lua_getfield(L, -1, key);\n  if (lua_isnumber(L, -1))\n    res = (int)lua_tointeger(L, -1);\n  else {\n    if (d < 0)\n      return luaL_error(L, \"field \" LUA_QS \" missing in date table\", key);\n    res = d;\n  }\n  lua_pop(L, 1);\n  return res;\n}\n\n\nstatic int os_date (lua_State *L) {\n  const char *s = luaL_optstring(L, 1, \"%c\");\n  time_t t = luaL_opt(L, (time_t)luaL_checknumber, 2, time(NULL));\n  struct tm *stm;\n  if (*s == '!') {  /* UTC? */\n    stm = gmtime(&t);\n    s++;  /* skip `!' */\n  }\n  else\n    stm = localtime(&t);\n  if (stm == NULL)  /* invalid date? */\n    lua_pushnil(L);\n  else if (strcmp(s, \"*t\") == 0) {\n    lua_createtable(L, 0, 9);  /* 9 = number of fields */\n    setfield(L, \"sec\", stm->tm_sec);\n    setfield(L, \"min\", stm->tm_min);\n    setfield(L, \"hour\", stm->tm_hour);\n    setfield(L, \"day\", stm->tm_mday);\n    setfield(L, \"month\", stm->tm_mon+1);\n    setfield(L, \"year\", stm->tm_year+1900);\n    setfield(L, \"wday\", stm->tm_wday+1);\n    setfield(L, \"yday\", stm->tm_yday+1);\n    setboolfield(L, \"isdst\", stm->tm_isdst);\n  }\n  else {\n    char cc[3];\n    luaL_Buffer b;\n    cc[0] = '%'; cc[2] = '\\0';\n    luaL_buffinit(L, &b);\n    for (; *s; s++) {\n      if (*s != '%' || *(s + 1) == '\\0')  /* no conversion specifier? */\n        luaL_addchar(&b, *s);\n      else {\n        size_t reslen;\n        char buff[200];  /* should be big enough for any conversion result */\n        cc[1] = *(++s);\n        reslen = strftime(buff, sizeof(buff), cc, stm);\n        luaL_addlstring(&b, buff, reslen);\n      }\n    }\n    luaL_pushresult(&b);\n  }\n  return 1;\n}\n\n\nstatic int os_time (lua_State *L) {\n  time_t t;\n  if (lua_isnoneornil(L, 1))  /* called without args? */\n    t = time(NULL);  /* get current time */\n  else {\n    struct tm ts;\n    luaL_checktype(L, 1, LUA_TTABLE);\n    lua_settop(L, 1);  /* make sure table is at the top */\n    ts.tm_sec = getfield(L, \"sec\", 0);\n    ts.tm_min = getfield(L, \"min\", 0);\n    ts.tm_hour = getfield(L, \"hour\", 12);\n    ts.tm_mday = getfield(L, \"day\", -1);\n    ts.tm_mon = getfield(L, \"month\", -1) - 1;\n    ts.tm_year = getfield(L, \"year\", -1) - 1900;\n    ts.tm_isdst = getboolfield(L, \"isdst\");\n    t = mktime(&ts);\n  }\n  if (t == (time_t)(-1))\n    lua_pushnil(L);\n  else\n    lua_pushnumber(L, (lua_Number)t);\n  return 1;\n}\n\n\nstatic int os_difftime (lua_State *L) {\n  lua_pushnumber(L, difftime((time_t)(luaL_checknumber(L, 1)),\n                             (time_t)(luaL_optnumber(L, 2, 0))));\n  return 1;\n}\n\n/* }====================================================== */\n\n\nstatic int os_setlocale (lua_State *L) {\n  static const int cat[] = {LC_ALL, LC_COLLATE, LC_CTYPE, LC_MONETARY,\n                      LC_NUMERIC, LC_TIME};\n  static const char *const catnames[] = {\"all\", \"collate\", \"ctype\", \"monetary\",\n     \"numeric\", \"time\", NULL};\n  const char *l = luaL_optstring(L, 1, NULL);\n  int op = luaL_checkoption(L, 2, \"all\", catnames);\n  lua_pushstring(L, setlocale(cat[op], l));\n  return 1;\n}\n\n\nstatic int os_exit (lua_State *L) {\n  exit(luaL_optint(L, 1, EXIT_SUCCESS));\n}\n\nstatic const luaL_Reg syslib[] = {\n  {\"clock\",     os_clock},\n  {\"date\",      os_date},\n  {\"difftime\",  os_difftime},\n  {\"execute\",   os_execute},\n  {\"exit\",      os_exit},\n  {\"getenv\",    os_getenv},\n  {\"remove\",    os_remove},\n  {\"rename\",    os_rename},\n  {\"setlocale\", os_setlocale},\n  {\"time\",      os_time},\n  {\"tmpname\",   os_tmpname},\n  {NULL, NULL}\n};\n\n/* }====================================================== */\n\n\n\nLUALIB_API int luaopen_os (lua_State *L) {\n  luaL_register(L, LUA_OSLIBNAME, syslib);\n  return 1;\n}\n\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/deps/lua/src/lparser.c",
    "content": "/*\n** $Id: lparser.c,v 2.42.1.4 2011/10/21 19:31:42 roberto Exp $\n** Lua Parser\n** See Copyright Notice in lua.h\n*/\n\n\n#include <string.h>\n\n#define lparser_c\n#define LUA_CORE\n\n#include \"lua.h\"\n\n#include \"lcode.h\"\n#include \"ldebug.h\"\n#include \"ldo.h\"\n#include \"lfunc.h\"\n#include \"llex.h\"\n#include \"lmem.h\"\n#include \"lobject.h\"\n#include \"lopcodes.h\"\n#include \"lparser.h\"\n#include \"lstate.h\"\n#include \"lstring.h\"\n#include \"ltable.h\"\n\n\n\n#define hasmultret(k)\t\t((k) == VCALL || (k) == VVARARG)\n\n#define getlocvar(fs, i)\t((fs)->f->locvars[(fs)->actvar[i]])\n\n#define luaY_checklimit(fs,v,l,m)\tif ((v)>(l)) errorlimit(fs,l,m)\n\n\n/*\n** nodes for block list (list of active blocks)\n*/\ntypedef struct BlockCnt {\n  struct BlockCnt *previous;  /* chain */\n  int breaklist;  /* list of jumps out of this loop */\n  lu_byte nactvar;  /* # active locals outside the breakable structure */\n  lu_byte upval;  /* true if some variable in the block is an upvalue */\n  lu_byte isbreakable;  /* true if `block' is a loop */\n} BlockCnt;\n\n\n\n/*\n** prototypes for recursive non-terminal functions\n*/\nstatic void chunk (LexState *ls);\nstatic void expr (LexState *ls, expdesc *v);\n\n\nstatic void anchor_token (LexState *ls) {\n  if (ls->t.token == TK_NAME || ls->t.token == TK_STRING) {\n    TString *ts = ls->t.seminfo.ts;\n    luaX_newstring(ls, getstr(ts), ts->tsv.len);\n  }\n}\n\n\nstatic void error_expected (LexState *ls, int token) {\n  luaX_syntaxerror(ls,\n      luaO_pushfstring(ls->L, LUA_QS \" expected\", luaX_token2str(ls, token)));\n}\n\n\nstatic void errorlimit (FuncState *fs, int limit, const char *what) {\n  const char *msg = (fs->f->linedefined == 0) ?\n    luaO_pushfstring(fs->L, \"main function has more than %d %s\", limit, what) :\n    luaO_pushfstring(fs->L, \"function at line %d has more than %d %s\",\n                            fs->f->linedefined, limit, what);\n  luaX_lexerror(fs->ls, msg, 0);\n}\n\n\nstatic int testnext (LexState *ls, int c) {\n  if (ls->t.token == c) {\n    luaX_next(ls);\n    return 1;\n  }\n  else return 0;\n}\n\n\nstatic void check (LexState *ls, int c) {\n  if (ls->t.token != c)\n    error_expected(ls, c);\n}\n\nstatic void checknext (LexState *ls, int c) {\n  check(ls, c);\n  luaX_next(ls);\n}\n\n\n#define check_condition(ls,c,msg)\t{ if (!(c)) luaX_syntaxerror(ls, msg); }\n\n\n\nstatic void check_match (LexState *ls, int what, int who, int where) {\n  if (!testnext(ls, what)) {\n    if (where == ls->linenumber)\n      error_expected(ls, what);\n    else {\n      luaX_syntaxerror(ls, luaO_pushfstring(ls->L,\n             LUA_QS \" expected (to close \" LUA_QS \" at line %d)\",\n              luaX_token2str(ls, what), luaX_token2str(ls, who), where));\n    }\n  }\n}\n\n\nstatic TString *str_checkname (LexState *ls) {\n  TString *ts;\n  check(ls, TK_NAME);\n  ts = ls->t.seminfo.ts;\n  luaX_next(ls);\n  return ts;\n}\n\n\nstatic void init_exp (expdesc *e, expkind k, int i) {\n  e->f = e->t = NO_JUMP;\n  e->k = k;\n  e->u.s.info = i;\n}\n\n\nstatic void codestring (LexState *ls, expdesc *e, TString *s) {\n  init_exp(e, VK, luaK_stringK(ls->fs, s));\n}\n\n\nstatic void checkname(LexState *ls, expdesc *e) {\n  codestring(ls, e, str_checkname(ls));\n}\n\n\nstatic int registerlocalvar (LexState *ls, TString *varname) {\n  FuncState *fs = ls->fs;\n  Proto *f = fs->f;\n  int oldsize = f->sizelocvars;\n  luaM_growvector(ls->L, f->locvars, fs->nlocvars, f->sizelocvars,\n                  LocVar, SHRT_MAX, \"too many local variables\");\n  while (oldsize < f->sizelocvars) f->locvars[oldsize++].varname = NULL;\n  f->locvars[fs->nlocvars].varname = varname;\n  luaC_objbarrier(ls->L, f, varname);\n  return fs->nlocvars++;\n}\n\n\n#define new_localvarliteral(ls,v,n) \\\n  new_localvar(ls, luaX_newstring(ls, \"\" v, (sizeof(v)/sizeof(char))-1), n)\n\n\nstatic void new_localvar (LexState *ls, TString *name, int n) {\n  FuncState *fs = ls->fs;\n  luaY_checklimit(fs, fs->nactvar+n+1, LUAI_MAXVARS, \"local variables\");\n  fs->actvar[fs->nactvar+n] = cast(unsigned short, registerlocalvar(ls, name));\n}\n\n\nstatic void adjustlocalvars (LexState *ls, int nvars) {\n  FuncState *fs = ls->fs;\n  fs->nactvar = cast_byte(fs->nactvar + nvars);\n  for (; nvars; nvars--) {\n    getlocvar(fs, fs->nactvar - nvars).startpc = fs->pc;\n  }\n}\n\n\nstatic void removevars (LexState *ls, int tolevel) {\n  FuncState *fs = ls->fs;\n  while (fs->nactvar > tolevel)\n    getlocvar(fs, --fs->nactvar).endpc = fs->pc;\n}\n\n\nstatic int indexupvalue (FuncState *fs, TString *name, expdesc *v) {\n  int i;\n  Proto *f = fs->f;\n  int oldsize = f->sizeupvalues;\n  for (i=0; i<f->nups; i++) {\n    if (fs->upvalues[i].k == v->k && fs->upvalues[i].info == v->u.s.info) {\n      lua_assert(f->upvalues[i] == name);\n      return i;\n    }\n  }\n  /* new one */\n  luaY_checklimit(fs, f->nups + 1, LUAI_MAXUPVALUES, \"upvalues\");\n  luaM_growvector(fs->L, f->upvalues, f->nups, f->sizeupvalues,\n                  TString *, MAX_INT, \"\");\n  while (oldsize < f->sizeupvalues) f->upvalues[oldsize++] = NULL;\n  f->upvalues[f->nups] = name;\n  luaC_objbarrier(fs->L, f, name);\n  lua_assert(v->k == VLOCAL || v->k == VUPVAL);\n  fs->upvalues[f->nups].k = cast_byte(v->k);\n  fs->upvalues[f->nups].info = cast_byte(v->u.s.info);\n  return f->nups++;\n}\n\n\nstatic int searchvar (FuncState *fs, TString *n) {\n  int i;\n  for (i=fs->nactvar-1; i >= 0; i--) {\n    if (n == getlocvar(fs, i).varname)\n      return i;\n  }\n  return -1;  /* not found */\n}\n\n\nstatic void markupval (FuncState *fs, int level) {\n  BlockCnt *bl = fs->bl;\n  while (bl && bl->nactvar > level) bl = bl->previous;\n  if (bl) bl->upval = 1;\n}\n\n\nstatic int singlevaraux (FuncState *fs, TString *n, expdesc *var, int base) {\n  if (fs == NULL) {  /* no more levels? */\n    init_exp(var, VGLOBAL, NO_REG);  /* default is global variable */\n    return VGLOBAL;\n  }\n  else {\n    int v = searchvar(fs, n);  /* look up at current level */\n    if (v >= 0) {\n      init_exp(var, VLOCAL, v);\n      if (!base)\n        markupval(fs, v);  /* local will be used as an upval */\n      return VLOCAL;\n    }\n    else {  /* not found at current level; try upper one */\n      if (singlevaraux(fs->prev, n, var, 0) == VGLOBAL)\n        return VGLOBAL;\n      var->u.s.info = indexupvalue(fs, n, var);  /* else was LOCAL or UPVAL */\n      var->k = VUPVAL;  /* upvalue in this level */\n      return VUPVAL;\n    }\n  }\n}\n\n\nstatic void singlevar (LexState *ls, expdesc *var) {\n  TString *varname = str_checkname(ls);\n  FuncState *fs = ls->fs;\n  if (singlevaraux(fs, varname, var, 1) == VGLOBAL)\n    var->u.s.info = luaK_stringK(fs, varname);  /* info points to global name */\n}\n\n\nstatic void adjust_assign (LexState *ls, int nvars, int nexps, expdesc *e) {\n  FuncState *fs = ls->fs;\n  int extra = nvars - nexps;\n  if (hasmultret(e->k)) {\n    extra++;  /* includes call itself */\n    if (extra < 0) extra = 0;\n    luaK_setreturns(fs, e, extra);  /* last exp. provides the difference */\n    if (extra > 1) luaK_reserveregs(fs, extra-1);\n  }\n  else {\n    if (e->k != VVOID) luaK_exp2nextreg(fs, e);  /* close last expression */\n    if (extra > 0) {\n      int reg = fs->freereg;\n      luaK_reserveregs(fs, extra);\n      luaK_nil(fs, reg, extra);\n    }\n  }\n}\n\n\nstatic void enterlevel (LexState *ls) {\n  if (++ls->L->nCcalls > LUAI_MAXCCALLS)\n\tluaX_lexerror(ls, \"chunk has too many syntax levels\", 0);\n}\n\n\n#define leavelevel(ls)\t((ls)->L->nCcalls--)\n\n\nstatic void enterblock (FuncState *fs, BlockCnt *bl, lu_byte isbreakable) {\n  bl->breaklist = NO_JUMP;\n  bl->isbreakable = isbreakable;\n  bl->nactvar = fs->nactvar;\n  bl->upval = 0;\n  bl->previous = fs->bl;\n  fs->bl = bl;\n  lua_assert(fs->freereg == fs->nactvar);\n}\n\n\nstatic void leaveblock (FuncState *fs) {\n  BlockCnt *bl = fs->bl;\n  fs->bl = bl->previous;\n  removevars(fs->ls, bl->nactvar);\n  if (bl->upval)\n    luaK_codeABC(fs, OP_CLOSE, bl->nactvar, 0, 0);\n  /* a block either controls scope or breaks (never both) */\n  lua_assert(!bl->isbreakable || !bl->upval);\n  lua_assert(bl->nactvar == fs->nactvar);\n  fs->freereg = fs->nactvar;  /* free registers */\n  luaK_patchtohere(fs, bl->breaklist);\n}\n\n\nstatic void pushclosure (LexState *ls, FuncState *func, expdesc *v) {\n  FuncState *fs = ls->fs;\n  Proto *f = fs->f;\n  int oldsize = f->sizep;\n  int i;\n  luaM_growvector(ls->L, f->p, fs->np, f->sizep, Proto *,\n                  MAXARG_Bx, \"constant table overflow\");\n  while (oldsize < f->sizep) f->p[oldsize++] = NULL;\n  f->p[fs->np++] = func->f;\n  luaC_objbarrier(ls->L, f, func->f);\n  init_exp(v, VRELOCABLE, luaK_codeABx(fs, OP_CLOSURE, 0, fs->np-1));\n  for (i=0; i<func->f->nups; i++) {\n    OpCode o = (func->upvalues[i].k == VLOCAL) ? OP_MOVE : OP_GETUPVAL;\n    luaK_codeABC(fs, o, 0, func->upvalues[i].info, 0);\n  }\n}\n\n\nstatic void open_func (LexState *ls, FuncState *fs) {\n  lua_State *L = ls->L;\n  Proto *f = luaF_newproto(L);\n  fs->f = f;\n  fs->prev = ls->fs;  /* linked list of funcstates */\n  fs->ls = ls;\n  fs->L = L;\n  ls->fs = fs;\n  fs->pc = 0;\n  fs->lasttarget = -1;\n  fs->jpc = NO_JUMP;\n  fs->freereg = 0;\n  fs->nk = 0;\n  fs->np = 0;\n  fs->nlocvars = 0;\n  fs->nactvar = 0;\n  fs->bl = NULL;\n  f->source = ls->source;\n  f->maxstacksize = 2;  /* registers 0/1 are always valid */\n  fs->h = luaH_new(L, 0, 0);\n  /* anchor table of constants and prototype (to avoid being collected) */\n  sethvalue2s(L, L->top, fs->h);\n  incr_top(L);\n  setptvalue2s(L, L->top, f);\n  incr_top(L);\n}\n\n\nstatic void close_func (LexState *ls) {\n  lua_State *L = ls->L;\n  FuncState *fs = ls->fs;\n  Proto *f = fs->f;\n  removevars(ls, 0);\n  luaK_ret(fs, 0, 0);  /* final return */\n  luaM_reallocvector(L, f->code, f->sizecode, fs->pc, Instruction);\n  f->sizecode = fs->pc;\n  luaM_reallocvector(L, f->lineinfo, f->sizelineinfo, fs->pc, int);\n  f->sizelineinfo = fs->pc;\n  luaM_reallocvector(L, f->k, f->sizek, fs->nk, TValue);\n  f->sizek = fs->nk;\n  luaM_reallocvector(L, f->p, f->sizep, fs->np, Proto *);\n  f->sizep = fs->np;\n  luaM_reallocvector(L, f->locvars, f->sizelocvars, fs->nlocvars, LocVar);\n  f->sizelocvars = fs->nlocvars;\n  luaM_reallocvector(L, f->upvalues, f->sizeupvalues, f->nups, TString *);\n  f->sizeupvalues = f->nups;\n  lua_assert(luaG_checkcode(f));\n  lua_assert(fs->bl == NULL);\n  ls->fs = fs->prev;\n  /* last token read was anchored in defunct function; must reanchor it */\n  if (fs) anchor_token(ls);\n  L->top -= 2;  /* remove table and prototype from the stack */\n}\n\n\nProto *luaY_parser (lua_State *L, ZIO *z, Mbuffer *buff, const char *name) {\n  struct LexState lexstate;\n  struct FuncState funcstate;\n  lexstate.buff = buff;\n  luaX_setinput(L, &lexstate, z, luaS_new(L, name));\n  open_func(&lexstate, &funcstate);\n  funcstate.f->is_vararg = VARARG_ISVARARG;  /* main func. is always vararg */\n  luaX_next(&lexstate);  /* read first token */\n  chunk(&lexstate);\n  check(&lexstate, TK_EOS);\n  close_func(&lexstate);\n  lua_assert(funcstate.prev == NULL);\n  lua_assert(funcstate.f->nups == 0);\n  lua_assert(lexstate.fs == NULL);\n  return funcstate.f;\n}\n\n\n\n/*============================================================*/\n/* GRAMMAR RULES */\n/*============================================================*/\n\n\nstatic void field (LexState *ls, expdesc *v) {\n  /* field -> ['.' | ':'] NAME */\n  FuncState *fs = ls->fs;\n  expdesc key;\n  luaK_exp2anyreg(fs, v);\n  luaX_next(ls);  /* skip the dot or colon */\n  checkname(ls, &key);\n  luaK_indexed(fs, v, &key);\n}\n\n\nstatic void yindex (LexState *ls, expdesc *v) {\n  /* index -> '[' expr ']' */\n  luaX_next(ls);  /* skip the '[' */\n  expr(ls, v);\n  luaK_exp2val(ls->fs, v);\n  checknext(ls, ']');\n}\n\n\n/*\n** {======================================================================\n** Rules for Constructors\n** =======================================================================\n*/\n\n\nstruct ConsControl {\n  expdesc v;  /* last list item read */\n  expdesc *t;  /* table descriptor */\n  int nh;  /* total number of `record' elements */\n  int na;  /* total number of array elements */\n  int tostore;  /* number of array elements pending to be stored */\n};\n\n\nstatic void recfield (LexState *ls, struct ConsControl *cc) {\n  /* recfield -> (NAME | `['exp1`]') = exp1 */\n  FuncState *fs = ls->fs;\n  int reg = ls->fs->freereg;\n  expdesc key, val;\n  int rkkey;\n  if (ls->t.token == TK_NAME) {\n    luaY_checklimit(fs, cc->nh, MAX_INT, \"items in a constructor\");\n    checkname(ls, &key);\n  }\n  else  /* ls->t.token == '[' */\n    yindex(ls, &key);\n  cc->nh++;\n  checknext(ls, '=');\n  rkkey = luaK_exp2RK(fs, &key);\n  expr(ls, &val);\n  luaK_codeABC(fs, OP_SETTABLE, cc->t->u.s.info, rkkey, luaK_exp2RK(fs, &val));\n  fs->freereg = reg;  /* free registers */\n}\n\n\nstatic void closelistfield (FuncState *fs, struct ConsControl *cc) {\n  if (cc->v.k == VVOID) return;  /* there is no list item */\n  luaK_exp2nextreg(fs, &cc->v);\n  cc->v.k = VVOID;\n  if (cc->tostore == LFIELDS_PER_FLUSH) {\n    luaK_setlist(fs, cc->t->u.s.info, cc->na, cc->tostore);  /* flush */\n    cc->tostore = 0;  /* no more items pending */\n  }\n}\n\n\nstatic void lastlistfield (FuncState *fs, struct ConsControl *cc) {\n  if (cc->tostore == 0) return;\n  if (hasmultret(cc->v.k)) {\n    luaK_setmultret(fs, &cc->v);\n    luaK_setlist(fs, cc->t->u.s.info, cc->na, LUA_MULTRET);\n    cc->na--;  /* do not count last expression (unknown number of elements) */\n  }\n  else {\n    if (cc->v.k != VVOID)\n      luaK_exp2nextreg(fs, &cc->v);\n    luaK_setlist(fs, cc->t->u.s.info, cc->na, cc->tostore);\n  }\n}\n\n\nstatic void listfield (LexState *ls, struct ConsControl *cc) {\n  expr(ls, &cc->v);\n  luaY_checklimit(ls->fs, cc->na, MAX_INT, \"items in a constructor\");\n  cc->na++;\n  cc->tostore++;\n}\n\n\nstatic void constructor (LexState *ls, expdesc *t) {\n  /* constructor -> ?? */\n  FuncState *fs = ls->fs;\n  int line = ls->linenumber;\n  int pc = luaK_codeABC(fs, OP_NEWTABLE, 0, 0, 0);\n  struct ConsControl cc;\n  cc.na = cc.nh = cc.tostore = 0;\n  cc.t = t;\n  init_exp(t, VRELOCABLE, pc);\n  init_exp(&cc.v, VVOID, 0);  /* no value (yet) */\n  luaK_exp2nextreg(ls->fs, t);  /* fix it at stack top (for gc) */\n  checknext(ls, '{');\n  do {\n    lua_assert(cc.v.k == VVOID || cc.tostore > 0);\n    if (ls->t.token == '}') break;\n    closelistfield(fs, &cc);\n    switch(ls->t.token) {\n      case TK_NAME: {  /* may be listfields or recfields */\n        luaX_lookahead(ls);\n        if (ls->lookahead.token != '=')  /* expression? */\n          listfield(ls, &cc);\n        else\n          recfield(ls, &cc);\n        break;\n      }\n      case '[': {  /* constructor_item -> recfield */\n        recfield(ls, &cc);\n        break;\n      }\n      default: {  /* constructor_part -> listfield */\n        listfield(ls, &cc);\n        break;\n      }\n    }\n  } while (testnext(ls, ',') || testnext(ls, ';'));\n  check_match(ls, '}', '{', line);\n  lastlistfield(fs, &cc);\n  SETARG_B(fs->f->code[pc], luaO_int2fb(cc.na)); /* set initial array size */\n  SETARG_C(fs->f->code[pc], luaO_int2fb(cc.nh));  /* set initial table size */\n}\n\n/* }====================================================================== */\n\n\n\nstatic void parlist (LexState *ls) {\n  /* parlist -> [ param { `,' param } ] */\n  FuncState *fs = ls->fs;\n  Proto *f = fs->f;\n  int nparams = 0;\n  f->is_vararg = 0;\n  if (ls->t.token != ')') {  /* is `parlist' not empty? */\n    do {\n      switch (ls->t.token) {\n        case TK_NAME: {  /* param -> NAME */\n          new_localvar(ls, str_checkname(ls), nparams++);\n          break;\n        }\n        case TK_DOTS: {  /* param -> `...' */\n          luaX_next(ls);\n#if defined(LUA_COMPAT_VARARG)\n          /* use `arg' as default name */\n          new_localvarliteral(ls, \"arg\", nparams++);\n          f->is_vararg = VARARG_HASARG | VARARG_NEEDSARG;\n#endif\n          f->is_vararg |= VARARG_ISVARARG;\n          break;\n        }\n        default: luaX_syntaxerror(ls, \"<name> or \" LUA_QL(\"...\") \" expected\");\n      }\n    } while (!f->is_vararg && testnext(ls, ','));\n  }\n  adjustlocalvars(ls, nparams);\n  f->numparams = cast_byte(fs->nactvar - (f->is_vararg & VARARG_HASARG));\n  luaK_reserveregs(fs, fs->nactvar);  /* reserve register for parameters */\n}\n\n\nstatic void body (LexState *ls, expdesc *e, int needself, int line) {\n  /* body ->  `(' parlist `)' chunk END */\n  FuncState new_fs;\n  open_func(ls, &new_fs);\n  new_fs.f->linedefined = line;\n  checknext(ls, '(');\n  if (needself) {\n    new_localvarliteral(ls, \"self\", 0);\n    adjustlocalvars(ls, 1);\n  }\n  parlist(ls);\n  checknext(ls, ')');\n  chunk(ls);\n  new_fs.f->lastlinedefined = ls->linenumber;\n  check_match(ls, TK_END, TK_FUNCTION, line);\n  close_func(ls);\n  pushclosure(ls, &new_fs, e);\n}\n\n\nstatic int explist1 (LexState *ls, expdesc *v) {\n  /* explist1 -> expr { `,' expr } */\n  int n = 1;  /* at least one expression */\n  expr(ls, v);\n  while (testnext(ls, ',')) {\n    luaK_exp2nextreg(ls->fs, v);\n    expr(ls, v);\n    n++;\n  }\n  return n;\n}\n\n\nstatic void funcargs (LexState *ls, expdesc *f) {\n  FuncState *fs = ls->fs;\n  expdesc args;\n  int base, nparams;\n  int line = ls->linenumber;\n  switch (ls->t.token) {\n    case '(': {  /* funcargs -> `(' [ explist1 ] `)' */\n      if (line != ls->lastline)\n        luaX_syntaxerror(ls,\"ambiguous syntax (function call x new statement)\");\n      luaX_next(ls);\n      if (ls->t.token == ')')  /* arg list is empty? */\n        args.k = VVOID;\n      else {\n        explist1(ls, &args);\n        luaK_setmultret(fs, &args);\n      }\n      check_match(ls, ')', '(', line);\n      break;\n    }\n    case '{': {  /* funcargs -> constructor */\n      constructor(ls, &args);\n      break;\n    }\n    case TK_STRING: {  /* funcargs -> STRING */\n      codestring(ls, &args, ls->t.seminfo.ts);\n      luaX_next(ls);  /* must use `seminfo' before `next' */\n      break;\n    }\n    default: {\n      luaX_syntaxerror(ls, \"function arguments expected\");\n      return;\n    }\n  }\n  lua_assert(f->k == VNONRELOC);\n  base = f->u.s.info;  /* base register for call */\n  if (hasmultret(args.k))\n    nparams = LUA_MULTRET;  /* open call */\n  else {\n    if (args.k != VVOID)\n      luaK_exp2nextreg(fs, &args);  /* close last argument */\n    nparams = fs->freereg - (base+1);\n  }\n  init_exp(f, VCALL, luaK_codeABC(fs, OP_CALL, base, nparams+1, 2));\n  luaK_fixline(fs, line);\n  fs->freereg = base+1;  /* call remove function and arguments and leaves\n                            (unless changed) one result */\n}\n\n\n\n\n/*\n** {======================================================================\n** Expression parsing\n** =======================================================================\n*/\n\n\nstatic void prefixexp (LexState *ls, expdesc *v) {\n  /* prefixexp -> NAME | '(' expr ')' */\n  switch (ls->t.token) {\n    case '(': {\n      int line = ls->linenumber;\n      luaX_next(ls);\n      expr(ls, v);\n      check_match(ls, ')', '(', line);\n      luaK_dischargevars(ls->fs, v);\n      return;\n    }\n    case TK_NAME: {\n      singlevar(ls, v);\n      return;\n    }\n    default: {\n      luaX_syntaxerror(ls, \"unexpected symbol\");\n      return;\n    }\n  }\n}\n\n\nstatic void primaryexp (LexState *ls, expdesc *v) {\n  /* primaryexp ->\n        prefixexp { `.' NAME | `[' exp `]' | `:' NAME funcargs | funcargs } */\n  FuncState *fs = ls->fs;\n  prefixexp(ls, v);\n  for (;;) {\n    switch (ls->t.token) {\n      case '.': {  /* field */\n        field(ls, v);\n        break;\n      }\n      case '[': {  /* `[' exp1 `]' */\n        expdesc key;\n        luaK_exp2anyreg(fs, v);\n        yindex(ls, &key);\n        luaK_indexed(fs, v, &key);\n        break;\n      }\n      case ':': {  /* `:' NAME funcargs */\n        expdesc key;\n        luaX_next(ls);\n        checkname(ls, &key);\n        luaK_self(fs, v, &key);\n        funcargs(ls, v);\n        break;\n      }\n      case '(': case TK_STRING: case '{': {  /* funcargs */\n        luaK_exp2nextreg(fs, v);\n        funcargs(ls, v);\n        break;\n      }\n      default: return;\n    }\n  }\n}\n\n\nstatic void simpleexp (LexState *ls, expdesc *v) {\n  /* simpleexp -> NUMBER | STRING | NIL | true | false | ... |\n                  constructor | FUNCTION body | primaryexp */\n  switch (ls->t.token) {\n    case TK_NUMBER: {\n      init_exp(v, VKNUM, 0);\n      v->u.nval = ls->t.seminfo.r;\n      break;\n    }\n    case TK_STRING: {\n      codestring(ls, v, ls->t.seminfo.ts);\n      break;\n    }\n    case TK_NIL: {\n      init_exp(v, VNIL, 0);\n      break;\n    }\n    case TK_TRUE: {\n      init_exp(v, VTRUE, 0);\n      break;\n    }\n    case TK_FALSE: {\n      init_exp(v, VFALSE, 0);\n      break;\n    }\n    case TK_DOTS: {  /* vararg */\n      FuncState *fs = ls->fs;\n      check_condition(ls, fs->f->is_vararg,\n                      \"cannot use \" LUA_QL(\"...\") \" outside a vararg function\");\n      fs->f->is_vararg &= ~VARARG_NEEDSARG;  /* don't need 'arg' */\n      init_exp(v, VVARARG, luaK_codeABC(fs, OP_VARARG, 0, 1, 0));\n      break;\n    }\n    case '{': {  /* constructor */\n      constructor(ls, v);\n      return;\n    }\n    case TK_FUNCTION: {\n      luaX_next(ls);\n      body(ls, v, 0, ls->linenumber);\n      return;\n    }\n    default: {\n      primaryexp(ls, v);\n      return;\n    }\n  }\n  luaX_next(ls);\n}\n\n\nstatic UnOpr getunopr (int op) {\n  switch (op) {\n    case TK_NOT: return OPR_NOT;\n    case '-': return OPR_MINUS;\n    case '#': return OPR_LEN;\n    default: return OPR_NOUNOPR;\n  }\n}\n\n\nstatic BinOpr getbinopr (int op) {\n  switch (op) {\n    case '+': return OPR_ADD;\n    case '-': return OPR_SUB;\n    case '*': return OPR_MUL;\n    case '/': return OPR_DIV;\n    case '%': return OPR_MOD;\n    case '^': return OPR_POW;\n    case TK_CONCAT: return OPR_CONCAT;\n    case TK_NE: return OPR_NE;\n    case TK_EQ: return OPR_EQ;\n    case '<': return OPR_LT;\n    case TK_LE: return OPR_LE;\n    case '>': return OPR_GT;\n    case TK_GE: return OPR_GE;\n    case TK_AND: return OPR_AND;\n    case TK_OR: return OPR_OR;\n    default: return OPR_NOBINOPR;\n  }\n}\n\n\nstatic const struct {\n  lu_byte left;  /* left priority for each binary operator */\n  lu_byte right; /* right priority */\n} priority[] = {  /* ORDER OPR */\n   {6, 6}, {6, 6}, {7, 7}, {7, 7}, {7, 7},  /* `+' `-' `/' `%' */\n   {10, 9}, {5, 4},                 /* power and concat (right associative) */\n   {3, 3}, {3, 3},                  /* equality and inequality */\n   {3, 3}, {3, 3}, {3, 3}, {3, 3},  /* order */\n   {2, 2}, {1, 1}                   /* logical (and/or) */\n};\n\n#define UNARY_PRIORITY\t8  /* priority for unary operators */\n\n\n/*\n** subexpr -> (simpleexp | unop subexpr) { binop subexpr }\n** where `binop' is any binary operator with a priority higher than `limit'\n*/\nstatic BinOpr subexpr (LexState *ls, expdesc *v, unsigned int limit) {\n  BinOpr op;\n  UnOpr uop;\n  enterlevel(ls);\n  uop = getunopr(ls->t.token);\n  if (uop != OPR_NOUNOPR) {\n    luaX_next(ls);\n    subexpr(ls, v, UNARY_PRIORITY);\n    luaK_prefix(ls->fs, uop, v);\n  }\n  else simpleexp(ls, v);\n  /* expand while operators have priorities higher than `limit' */\n  op = getbinopr(ls->t.token);\n  while (op != OPR_NOBINOPR && priority[op].left > limit) {\n    expdesc v2;\n    BinOpr nextop;\n    luaX_next(ls);\n    luaK_infix(ls->fs, op, v);\n    /* read sub-expression with higher priority */\n    nextop = subexpr(ls, &v2, priority[op].right);\n    luaK_posfix(ls->fs, op, v, &v2);\n    op = nextop;\n  }\n  leavelevel(ls);\n  return op;  /* return first untreated operator */\n}\n\n\nstatic void expr (LexState *ls, expdesc *v) {\n  subexpr(ls, v, 0);\n}\n\n/* }==================================================================== */\n\n\n\n/*\n** {======================================================================\n** Rules for Statements\n** =======================================================================\n*/\n\n\nstatic int block_follow (int token) {\n  switch (token) {\n    case TK_ELSE: case TK_ELSEIF: case TK_END:\n    case TK_UNTIL: case TK_EOS:\n      return 1;\n    default: return 0;\n  }\n}\n\n\nstatic void block (LexState *ls) {\n  /* block -> chunk */\n  FuncState *fs = ls->fs;\n  BlockCnt bl;\n  enterblock(fs, &bl, 0);\n  chunk(ls);\n  lua_assert(bl.breaklist == NO_JUMP);\n  leaveblock(fs);\n}\n\n\n/*\n** structure to chain all variables in the left-hand side of an\n** assignment\n*/\nstruct LHS_assign {\n  struct LHS_assign *prev;\n  expdesc v;  /* variable (global, local, upvalue, or indexed) */\n};\n\n\n/*\n** check whether, in an assignment to a local variable, the local variable\n** is needed in a previous assignment (to a table). If so, save original\n** local value in a safe place and use this safe copy in the previous\n** assignment.\n*/\nstatic void check_conflict (LexState *ls, struct LHS_assign *lh, expdesc *v) {\n  FuncState *fs = ls->fs;\n  int extra = fs->freereg;  /* eventual position to save local variable */\n  int conflict = 0;\n  for (; lh; lh = lh->prev) {\n    if (lh->v.k == VINDEXED) {\n      if (lh->v.u.s.info == v->u.s.info) {  /* conflict? */\n        conflict = 1;\n        lh->v.u.s.info = extra;  /* previous assignment will use safe copy */\n      }\n      if (lh->v.u.s.aux == v->u.s.info) {  /* conflict? */\n        conflict = 1;\n        lh->v.u.s.aux = extra;  /* previous assignment will use safe copy */\n      }\n    }\n  }\n  if (conflict) {\n    luaK_codeABC(fs, OP_MOVE, fs->freereg, v->u.s.info, 0);  /* make copy */\n    luaK_reserveregs(fs, 1);\n  }\n}\n\n\nstatic void assignment (LexState *ls, struct LHS_assign *lh, int nvars) {\n  expdesc e;\n  check_condition(ls, VLOCAL <= lh->v.k && lh->v.k <= VINDEXED,\n                      \"syntax error\");\n  if (testnext(ls, ',')) {  /* assignment -> `,' primaryexp assignment */\n    struct LHS_assign nv;\n    nv.prev = lh;\n    primaryexp(ls, &nv.v);\n    if (nv.v.k == VLOCAL)\n      check_conflict(ls, lh, &nv.v);\n    luaY_checklimit(ls->fs, nvars, LUAI_MAXCCALLS - ls->L->nCcalls,\n                    \"variables in assignment\");\n    assignment(ls, &nv, nvars+1);\n  }\n  else {  /* assignment -> `=' explist1 */\n    int nexps;\n    checknext(ls, '=');\n    nexps = explist1(ls, &e);\n    if (nexps != nvars) {\n      adjust_assign(ls, nvars, nexps, &e);\n      if (nexps > nvars)\n        ls->fs->freereg -= nexps - nvars;  /* remove extra values */\n    }\n    else {\n      luaK_setoneret(ls->fs, &e);  /* close last expression */\n      luaK_storevar(ls->fs, &lh->v, &e);\n      return;  /* avoid default */\n    }\n  }\n  init_exp(&e, VNONRELOC, ls->fs->freereg-1);  /* default assignment */\n  luaK_storevar(ls->fs, &lh->v, &e);\n}\n\n\nstatic int cond (LexState *ls) {\n  /* cond -> exp */\n  expdesc v;\n  expr(ls, &v);  /* read condition */\n  if (v.k == VNIL) v.k = VFALSE;  /* `falses' are all equal here */\n  luaK_goiftrue(ls->fs, &v);\n  return v.f;\n}\n\n\nstatic void breakstat (LexState *ls) {\n  FuncState *fs = ls->fs;\n  BlockCnt *bl = fs->bl;\n  int upval = 0;\n  while (bl && !bl->isbreakable) {\n    upval |= bl->upval;\n    bl = bl->previous;\n  }\n  if (!bl)\n    luaX_syntaxerror(ls, \"no loop to break\");\n  if (upval)\n    luaK_codeABC(fs, OP_CLOSE, bl->nactvar, 0, 0);\n  luaK_concat(fs, &bl->breaklist, luaK_jump(fs));\n}\n\n\nstatic void whilestat (LexState *ls, int line) {\n  /* whilestat -> WHILE cond DO block END */\n  FuncState *fs = ls->fs;\n  int whileinit;\n  int condexit;\n  BlockCnt bl;\n  luaX_next(ls);  /* skip WHILE */\n  whileinit = luaK_getlabel(fs);\n  condexit = cond(ls);\n  enterblock(fs, &bl, 1);\n  checknext(ls, TK_DO);\n  block(ls);\n  luaK_patchlist(fs, luaK_jump(fs), whileinit);\n  check_match(ls, TK_END, TK_WHILE, line);\n  leaveblock(fs);\n  luaK_patchtohere(fs, condexit);  /* false conditions finish the loop */\n}\n\n\nstatic void repeatstat (LexState *ls, int line) {\n  /* repeatstat -> REPEAT block UNTIL cond */\n  int condexit;\n  FuncState *fs = ls->fs;\n  int repeat_init = luaK_getlabel(fs);\n  BlockCnt bl1, bl2;\n  enterblock(fs, &bl1, 1);  /* loop block */\n  enterblock(fs, &bl2, 0);  /* scope block */\n  luaX_next(ls);  /* skip REPEAT */\n  chunk(ls);\n  check_match(ls, TK_UNTIL, TK_REPEAT, line);\n  condexit = cond(ls);  /* read condition (inside scope block) */\n  if (!bl2.upval) {  /* no upvalues? */\n    leaveblock(fs);  /* finish scope */\n    luaK_patchlist(ls->fs, condexit, repeat_init);  /* close the loop */\n  }\n  else {  /* complete semantics when there are upvalues */\n    breakstat(ls);  /* if condition then break */\n    luaK_patchtohere(ls->fs, condexit);  /* else... */\n    leaveblock(fs);  /* finish scope... */\n    luaK_patchlist(ls->fs, luaK_jump(fs), repeat_init);  /* and repeat */\n  }\n  leaveblock(fs);  /* finish loop */\n}\n\n\nstatic int exp1 (LexState *ls) {\n  expdesc e;\n  int k;\n  expr(ls, &e);\n  k = e.k;\n  luaK_exp2nextreg(ls->fs, &e);\n  return k;\n}\n\n\nstatic void forbody (LexState *ls, int base, int line, int nvars, int isnum) {\n  /* forbody -> DO block */\n  BlockCnt bl;\n  FuncState *fs = ls->fs;\n  int prep, endfor;\n  adjustlocalvars(ls, 3);  /* control variables */\n  checknext(ls, TK_DO);\n  prep = isnum ? luaK_codeAsBx(fs, OP_FORPREP, base, NO_JUMP) : luaK_jump(fs);\n  enterblock(fs, &bl, 0);  /* scope for declared variables */\n  adjustlocalvars(ls, nvars);\n  luaK_reserveregs(fs, nvars);\n  block(ls);\n  leaveblock(fs);  /* end of scope for declared variables */\n  luaK_patchtohere(fs, prep);\n  endfor = (isnum) ? luaK_codeAsBx(fs, OP_FORLOOP, base, NO_JUMP) :\n                     luaK_codeABC(fs, OP_TFORLOOP, base, 0, nvars);\n  luaK_fixline(fs, line);  /* pretend that `OP_FOR' starts the loop */\n  luaK_patchlist(fs, (isnum ? endfor : luaK_jump(fs)), prep + 1);\n}\n\n\nstatic void fornum (LexState *ls, TString *varname, int line) {\n  /* fornum -> NAME = exp1,exp1[,exp1] forbody */\n  FuncState *fs = ls->fs;\n  int base = fs->freereg;\n  new_localvarliteral(ls, \"(for index)\", 0);\n  new_localvarliteral(ls, \"(for limit)\", 1);\n  new_localvarliteral(ls, \"(for step)\", 2);\n  new_localvar(ls, varname, 3);\n  checknext(ls, '=');\n  exp1(ls);  /* initial value */\n  checknext(ls, ',');\n  exp1(ls);  /* limit */\n  if (testnext(ls, ','))\n    exp1(ls);  /* optional step */\n  else {  /* default step = 1 */\n    luaK_codeABx(fs, OP_LOADK, fs->freereg, luaK_numberK(fs, 1));\n    luaK_reserveregs(fs, 1);\n  }\n  forbody(ls, base, line, 1, 1);\n}\n\n\nstatic void forlist (LexState *ls, TString *indexname) {\n  /* forlist -> NAME {,NAME} IN explist1 forbody */\n  FuncState *fs = ls->fs;\n  expdesc e;\n  int nvars = 0;\n  int line;\n  int base = fs->freereg;\n  /* create control variables */\n  new_localvarliteral(ls, \"(for generator)\", nvars++);\n  new_localvarliteral(ls, \"(for state)\", nvars++);\n  new_localvarliteral(ls, \"(for control)\", nvars++);\n  /* create declared variables */\n  new_localvar(ls, indexname, nvars++);\n  while (testnext(ls, ','))\n    new_localvar(ls, str_checkname(ls), nvars++);\n  checknext(ls, TK_IN);\n  line = ls->linenumber;\n  adjust_assign(ls, 3, explist1(ls, &e), &e);\n  luaK_checkstack(fs, 3);  /* extra space to call generator */\n  forbody(ls, base, line, nvars - 3, 0);\n}\n\n\nstatic void forstat (LexState *ls, int line) {\n  /* forstat -> FOR (fornum | forlist) END */\n  FuncState *fs = ls->fs;\n  TString *varname;\n  BlockCnt bl;\n  enterblock(fs, &bl, 1);  /* scope for loop and control variables */\n  luaX_next(ls);  /* skip `for' */\n  varname = str_checkname(ls);  /* first variable name */\n  switch (ls->t.token) {\n    case '=': fornum(ls, varname, line); break;\n    case ',': case TK_IN: forlist(ls, varname); break;\n    default: luaX_syntaxerror(ls, LUA_QL(\"=\") \" or \" LUA_QL(\"in\") \" expected\");\n  }\n  check_match(ls, TK_END, TK_FOR, line);\n  leaveblock(fs);  /* loop scope (`break' jumps to this point) */\n}\n\n\nstatic int test_then_block (LexState *ls) {\n  /* test_then_block -> [IF | ELSEIF] cond THEN block */\n  int condexit;\n  luaX_next(ls);  /* skip IF or ELSEIF */\n  condexit = cond(ls);\n  checknext(ls, TK_THEN);\n  block(ls);  /* `then' part */\n  return condexit;\n}\n\n\nstatic void ifstat (LexState *ls, int line) {\n  /* ifstat -> IF cond THEN block {ELSEIF cond THEN block} [ELSE block] END */\n  FuncState *fs = ls->fs;\n  int flist;\n  int escapelist = NO_JUMP;\n  flist = test_then_block(ls);  /* IF cond THEN block */\n  while (ls->t.token == TK_ELSEIF) {\n    luaK_concat(fs, &escapelist, luaK_jump(fs));\n    luaK_patchtohere(fs, flist);\n    flist = test_then_block(ls);  /* ELSEIF cond THEN block */\n  }\n  if (ls->t.token == TK_ELSE) {\n    luaK_concat(fs, &escapelist, luaK_jump(fs));\n    luaK_patchtohere(fs, flist);\n    luaX_next(ls);  /* skip ELSE (after patch, for correct line info) */\n    block(ls);  /* `else' part */\n  }\n  else\n    luaK_concat(fs, &escapelist, flist);\n  luaK_patchtohere(fs, escapelist);\n  check_match(ls, TK_END, TK_IF, line);\n}\n\n\nstatic void localfunc (LexState *ls) {\n  expdesc v, b;\n  FuncState *fs = ls->fs;\n  new_localvar(ls, str_checkname(ls), 0);\n  init_exp(&v, VLOCAL, fs->freereg);\n  luaK_reserveregs(fs, 1);\n  adjustlocalvars(ls, 1);\n  body(ls, &b, 0, ls->linenumber);\n  luaK_storevar(fs, &v, &b);\n  /* debug information will only see the variable after this point! */\n  getlocvar(fs, fs->nactvar - 1).startpc = fs->pc;\n}\n\n\nstatic void localstat (LexState *ls) {\n  /* stat -> LOCAL NAME {`,' NAME} [`=' explist1] */\n  int nvars = 0;\n  int nexps;\n  expdesc e;\n  do {\n    new_localvar(ls, str_checkname(ls), nvars++);\n  } while (testnext(ls, ','));\n  if (testnext(ls, '='))\n    nexps = explist1(ls, &e);\n  else {\n    e.k = VVOID;\n    nexps = 0;\n  }\n  adjust_assign(ls, nvars, nexps, &e);\n  adjustlocalvars(ls, nvars);\n}\n\n\nstatic int funcname (LexState *ls, expdesc *v) {\n  /* funcname -> NAME {field} [`:' NAME] */\n  int needself = 0;\n  singlevar(ls, v);\n  while (ls->t.token == '.')\n    field(ls, v);\n  if (ls->t.token == ':') {\n    needself = 1;\n    field(ls, v);\n  }\n  return needself;\n}\n\n\nstatic void funcstat (LexState *ls, int line) {\n  /* funcstat -> FUNCTION funcname body */\n  int needself;\n  expdesc v, b;\n  luaX_next(ls);  /* skip FUNCTION */\n  needself = funcname(ls, &v);\n  body(ls, &b, needself, line);\n  luaK_storevar(ls->fs, &v, &b);\n  luaK_fixline(ls->fs, line);  /* definition `happens' in the first line */\n}\n\n\nstatic void exprstat (LexState *ls) {\n  /* stat -> func | assignment */\n  FuncState *fs = ls->fs;\n  struct LHS_assign v;\n  primaryexp(ls, &v.v);\n  if (v.v.k == VCALL)  /* stat -> func */\n    SETARG_C(getcode(fs, &v.v), 1);  /* call statement uses no results */\n  else {  /* stat -> assignment */\n    v.prev = NULL;\n    assignment(ls, &v, 1);\n  }\n}\n\n\nstatic void retstat (LexState *ls) {\n  /* stat -> RETURN explist */\n  FuncState *fs = ls->fs;\n  expdesc e;\n  int first, nret;  /* registers with returned values */\n  luaX_next(ls);  /* skip RETURN */\n  if (block_follow(ls->t.token) || ls->t.token == ';')\n    first = nret = 0;  /* return no values */\n  else {\n    nret = explist1(ls, &e);  /* optional return values */\n    if (hasmultret(e.k)) {\n      luaK_setmultret(fs, &e);\n      if (e.k == VCALL && nret == 1) {  /* tail call? */\n        SET_OPCODE(getcode(fs,&e), OP_TAILCALL);\n        lua_assert(GETARG_A(getcode(fs,&e)) == fs->nactvar);\n      }\n      first = fs->nactvar;\n      nret = LUA_MULTRET;  /* return all values */\n    }\n    else {\n      if (nret == 1)  /* only one single value? */\n        first = luaK_exp2anyreg(fs, &e);\n      else {\n        luaK_exp2nextreg(fs, &e);  /* values must go to the `stack' */\n        first = fs->nactvar;  /* return all `active' values */\n        lua_assert(nret == fs->freereg - first);\n      }\n    }\n  }\n  luaK_ret(fs, first, nret);\n}\n\n\nstatic int statement (LexState *ls) {\n  int line = ls->linenumber;  /* may be needed for error messages */\n  switch (ls->t.token) {\n    case TK_IF: {  /* stat -> ifstat */\n      ifstat(ls, line);\n      return 0;\n    }\n    case TK_WHILE: {  /* stat -> whilestat */\n      whilestat(ls, line);\n      return 0;\n    }\n    case TK_DO: {  /* stat -> DO block END */\n      luaX_next(ls);  /* skip DO */\n      block(ls);\n      check_match(ls, TK_END, TK_DO, line);\n      return 0;\n    }\n    case TK_FOR: {  /* stat -> forstat */\n      forstat(ls, line);\n      return 0;\n    }\n    case TK_REPEAT: {  /* stat -> repeatstat */\n      repeatstat(ls, line);\n      return 0;\n    }\n    case TK_FUNCTION: {\n      funcstat(ls, line);  /* stat -> funcstat */\n      return 0;\n    }\n    case TK_LOCAL: {  /* stat -> localstat */\n      luaX_next(ls);  /* skip LOCAL */\n      if (testnext(ls, TK_FUNCTION))  /* local function? */\n        localfunc(ls);\n      else\n        localstat(ls);\n      return 0;\n    }\n    case TK_RETURN: {  /* stat -> retstat */\n      retstat(ls);\n      return 1;  /* must be last statement */\n    }\n    case TK_BREAK: {  /* stat -> breakstat */\n      luaX_next(ls);  /* skip BREAK */\n      breakstat(ls);\n      return 1;  /* must be last statement */\n    }\n    default: {\n      exprstat(ls);\n      return 0;  /* to avoid warnings */\n    }\n  }\n}\n\n\nstatic void chunk (LexState *ls) {\n  /* chunk -> { stat [`;'] } */\n  int islast = 0;\n  enterlevel(ls);\n  while (!islast && !block_follow(ls->t.token)) {\n    islast = statement(ls);\n    testnext(ls, ';');\n    lua_assert(ls->fs->f->maxstacksize >= ls->fs->freereg &&\n               ls->fs->freereg >= ls->fs->nactvar);\n    ls->fs->freereg = ls->fs->nactvar;  /* free registers */\n  }\n  leavelevel(ls);\n}\n\n/* }====================================================================== */\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/deps/lua/src/lparser.h",
    "content": "/*\n** $Id: lparser.h,v 1.57.1.1 2007/12/27 13:02:25 roberto Exp $\n** Lua Parser\n** See Copyright Notice in lua.h\n*/\n\n#ifndef lparser_h\n#define lparser_h\n\n#include \"llimits.h\"\n#include \"lobject.h\"\n#include \"lzio.h\"\n\n\n/*\n** Expression descriptor\n*/\n\ntypedef enum {\n  VVOID,\t/* no value */\n  VNIL,\n  VTRUE,\n  VFALSE,\n  VK,\t\t/* info = index of constant in `k' */\n  VKNUM,\t/* nval = numerical value */\n  VLOCAL,\t/* info = local register */\n  VUPVAL,       /* info = index of upvalue in `upvalues' */\n  VGLOBAL,\t/* info = index of table; aux = index of global name in `k' */\n  VINDEXED,\t/* info = table register; aux = index register (or `k') */\n  VJMP,\t\t/* info = instruction pc */\n  VRELOCABLE,\t/* info = instruction pc */\n  VNONRELOC,\t/* info = result register */\n  VCALL,\t/* info = instruction pc */\n  VVARARG\t/* info = instruction pc */\n} expkind;\n\ntypedef struct expdesc {\n  expkind k;\n  union {\n    struct { int info, aux; } s;\n    lua_Number nval;\n  } u;\n  int t;  /* patch list of `exit when true' */\n  int f;  /* patch list of `exit when false' */\n} expdesc;\n\n\ntypedef struct upvaldesc {\n  lu_byte k;\n  lu_byte info;\n} upvaldesc;\n\n\nstruct BlockCnt;  /* defined in lparser.c */\n\n\n/* state needed to generate code for a given function */\ntypedef struct FuncState {\n  Proto *f;  /* current function header */\n  Table *h;  /* table to find (and reuse) elements in `k' */\n  struct FuncState *prev;  /* enclosing function */\n  struct LexState *ls;  /* lexical state */\n  struct lua_State *L;  /* copy of the Lua state */\n  struct BlockCnt *bl;  /* chain of current blocks */\n  int pc;  /* next position to code (equivalent to `ncode') */\n  int lasttarget;   /* `pc' of last `jump target' */\n  int jpc;  /* list of pending jumps to `pc' */\n  int freereg;  /* first free register */\n  int nk;  /* number of elements in `k' */\n  int np;  /* number of elements in `p' */\n  short nlocvars;  /* number of elements in `locvars' */\n  lu_byte nactvar;  /* number of active local variables */\n  upvaldesc upvalues[LUAI_MAXUPVALUES];  /* upvalues */\n  unsigned short actvar[LUAI_MAXVARS];  /* declared-variable stack */\n} FuncState;\n\n\nLUAI_FUNC Proto *luaY_parser (lua_State *L, ZIO *z, Mbuffer *buff,\n                                            const char *name);\n\n\n#endif\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/deps/lua/src/lstate.c",
    "content": "/*\n** $Id: lstate.c,v 2.36.1.2 2008/01/03 15:20:39 roberto Exp $\n** Global State\n** See Copyright Notice in lua.h\n*/\n\n\n#include <stddef.h>\n\n#define lstate_c\n#define LUA_CORE\n\n#include \"lua.h\"\n\n#include \"ldebug.h\"\n#include \"ldo.h\"\n#include \"lfunc.h\"\n#include \"lgc.h\"\n#include \"llex.h\"\n#include \"lmem.h\"\n#include \"lstate.h\"\n#include \"lstring.h\"\n#include \"ltable.h\"\n#include \"ltm.h\"\n\n\n#define state_size(x)\t(sizeof(x) + LUAI_EXTRASPACE)\n#define fromstate(l)\t(cast(lu_byte *, (l)) - LUAI_EXTRASPACE)\n#define tostate(l)   (cast(lua_State *, cast(lu_byte *, l) + LUAI_EXTRASPACE))\n\n\n/*\n** Main thread combines a thread state and the global state\n*/\ntypedef struct LG {\n  lua_State l;\n  global_State g;\n} LG;\n  \n\n\nstatic void stack_init (lua_State *L1, lua_State *L) {\n  /* initialize CallInfo array */\n  L1->base_ci = luaM_newvector(L, BASIC_CI_SIZE, CallInfo);\n  L1->ci = L1->base_ci;\n  L1->size_ci = BASIC_CI_SIZE;\n  L1->end_ci = L1->base_ci + L1->size_ci - 1;\n  /* initialize stack array */\n  L1->stack = luaM_newvector(L, BASIC_STACK_SIZE + EXTRA_STACK, TValue);\n  L1->stacksize = BASIC_STACK_SIZE + EXTRA_STACK;\n  L1->top = L1->stack;\n  L1->stack_last = L1->stack+(L1->stacksize - EXTRA_STACK)-1;\n  /* initialize first ci */\n  L1->ci->func = L1->top;\n  setnilvalue(L1->top++);  /* `function' entry for this `ci' */\n  L1->base = L1->ci->base = L1->top;\n  L1->ci->top = L1->top + LUA_MINSTACK;\n}\n\n\nstatic void freestack (lua_State *L, lua_State *L1) {\n  luaM_freearray(L, L1->base_ci, L1->size_ci, CallInfo);\n  luaM_freearray(L, L1->stack, L1->stacksize, TValue);\n}\n\n\n/*\n** open parts that may cause memory-allocation errors\n*/\nstatic void f_luaopen (lua_State *L, void *ud) {\n  global_State *g = G(L);\n  UNUSED(ud);\n  stack_init(L, L);  /* init stack */\n  sethvalue(L, gt(L), luaH_new(L, 0, 2));  /* table of globals */\n  sethvalue(L, registry(L), luaH_new(L, 0, 2));  /* registry */\n  luaS_resize(L, MINSTRTABSIZE);  /* initial size of string table */\n  luaT_init(L);\n  luaX_init(L);\n  luaS_fix(luaS_newliteral(L, MEMERRMSG));\n  g->GCthreshold = 4*g->totalbytes;\n}\n\n\nstatic void preinit_state (lua_State *L, global_State *g) {\n  G(L) = g;\n  L->stack = NULL;\n  L->stacksize = 0;\n  L->errorJmp = NULL;\n  L->hook = NULL;\n  L->hookmask = 0;\n  L->basehookcount = 0;\n  L->allowhook = 1;\n  resethookcount(L);\n  L->openupval = NULL;\n  L->size_ci = 0;\n  L->nCcalls = L->baseCcalls = 0;\n  L->status = 0;\n  L->base_ci = L->ci = NULL;\n  L->savedpc = NULL;\n  L->errfunc = 0;\n  setnilvalue(gt(L));\n}\n\n\nstatic void close_state (lua_State *L) {\n  global_State *g = G(L);\n  luaF_close(L, L->stack);  /* close all upvalues for this thread */\n  luaC_freeall(L);  /* collect all objects */\n  lua_assert(g->rootgc == obj2gco(L));\n  lua_assert(g->strt.nuse == 0);\n  luaM_freearray(L, G(L)->strt.hash, G(L)->strt.size, TString *);\n  luaZ_freebuffer(L, &g->buff);\n  freestack(L, L);\n  lua_assert(g->totalbytes == sizeof(LG));\n  (*g->frealloc)(g->ud, fromstate(L), state_size(LG), 0);\n}\n\n\nlua_State *luaE_newthread (lua_State *L) {\n  lua_State *L1 = tostate(luaM_malloc(L, state_size(lua_State)));\n  luaC_link(L, obj2gco(L1), LUA_TTHREAD);\n  preinit_state(L1, G(L));\n  stack_init(L1, L);  /* init stack */\n  setobj2n(L, gt(L1), gt(L));  /* share table of globals */\n  L1->hookmask = L->hookmask;\n  L1->basehookcount = L->basehookcount;\n  L1->hook = L->hook;\n  resethookcount(L1);\n  lua_assert(iswhite(obj2gco(L1)));\n  return L1;\n}\n\n\nvoid luaE_freethread (lua_State *L, lua_State *L1) {\n  luaF_close(L1, L1->stack);  /* close all upvalues for this thread */\n  lua_assert(L1->openupval == NULL);\n  luai_userstatefree(L1);\n  freestack(L, L1);\n  luaM_freemem(L, fromstate(L1), state_size(lua_State));\n}\n\n\nLUA_API lua_State *lua_newstate (lua_Alloc f, void *ud) {\n  int i;\n  lua_State *L;\n  global_State *g;\n  void *l = (*f)(ud, NULL, 0, state_size(LG));\n  if (l == NULL) return NULL;\n  L = tostate(l);\n  g = &((LG *)L)->g;\n  L->next = NULL;\n  L->tt = LUA_TTHREAD;\n  g->currentwhite = bit2mask(WHITE0BIT, FIXEDBIT);\n  L->marked = luaC_white(g);\n  set2bits(L->marked, FIXEDBIT, SFIXEDBIT);\n  preinit_state(L, g);\n  g->frealloc = f;\n  g->ud = ud;\n  g->mainthread = L;\n  g->uvhead.u.l.prev = &g->uvhead;\n  g->uvhead.u.l.next = &g->uvhead;\n  g->GCthreshold = 0;  /* mark it as unfinished state */\n  g->strt.size = 0;\n  g->strt.nuse = 0;\n  g->strt.hash = NULL;\n  setnilvalue(registry(L));\n  luaZ_initbuffer(L, &g->buff);\n  g->panic = NULL;\n  g->gcstate = GCSpause;\n  g->rootgc = obj2gco(L);\n  g->sweepstrgc = 0;\n  g->sweepgc = &g->rootgc;\n  g->gray = NULL;\n  g->grayagain = NULL;\n  g->weak = NULL;\n  g->tmudata = NULL;\n  g->totalbytes = sizeof(LG);\n  g->gcpause = LUAI_GCPAUSE;\n  g->gcstepmul = LUAI_GCMUL;\n  g->gcdept = 0;\n  for (i=0; i<NUM_TAGS; i++) g->mt[i] = NULL;\n  if (luaD_rawrunprotected(L, f_luaopen, NULL) != 0) {\n    /* memory allocation error: free partial state */\n    close_state(L);\n    L = NULL;\n  }\n  else\n    luai_userstateopen(L);\n  return L;\n}\n\n\nstatic void callallgcTM (lua_State *L, void *ud) {\n  UNUSED(ud);\n  luaC_callGCTM(L);  /* call GC metamethods for all udata */\n}\n\n\nLUA_API void lua_close (lua_State *L) {\n  L = G(L)->mainthread;  /* only the main thread can be closed */\n  lua_lock(L);\n  luaF_close(L, L->stack);  /* close all upvalues for this thread */\n  luaC_separateudata(L, 1);  /* separate udata that have GC metamethods */\n  L->errfunc = 0;  /* no error function during GC metamethods */\n  do {  /* repeat until no more errors */\n    L->ci = L->base_ci;\n    L->base = L->top = L->ci->base;\n    L->nCcalls = L->baseCcalls = 0;\n  } while (luaD_rawrunprotected(L, callallgcTM, NULL) != 0);\n  lua_assert(G(L)->tmudata == NULL);\n  luai_userstateclose(L);\n  close_state(L);\n}\n\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/deps/lua/src/lstate.h",
    "content": "/*\n** $Id: lstate.h,v 2.24.1.2 2008/01/03 15:20:39 roberto Exp $\n** Global State\n** See Copyright Notice in lua.h\n*/\n\n#ifndef lstate_h\n#define lstate_h\n\n#include \"lua.h\"\n\n#include \"lobject.h\"\n#include \"ltm.h\"\n#include \"lzio.h\"\n\n\n\nstruct lua_longjmp;  /* defined in ldo.c */\n\n\n/* table of globals */\n#define gt(L)\t(&L->l_gt)\n\n/* registry */\n#define registry(L)\t(&G(L)->l_registry)\n\n\n/* extra stack space to handle TM calls and some other extras */\n#define EXTRA_STACK   5\n\n\n#define BASIC_CI_SIZE           8\n\n#define BASIC_STACK_SIZE        (2*LUA_MINSTACK)\n\n\n\ntypedef struct stringtable {\n  GCObject **hash;\n  lu_int32 nuse;  /* number of elements */\n  int size;\n} stringtable;\n\n\n/*\n** informations about a call\n*/\ntypedef struct CallInfo {\n  StkId base;  /* base for this function */\n  StkId func;  /* function index in the stack */\n  StkId\ttop;  /* top for this function */\n  const Instruction *savedpc;\n  int nresults;  /* expected number of results from this function */\n  int tailcalls;  /* number of tail calls lost under this entry */\n} CallInfo;\n\n\n\n#define curr_func(L)\t(clvalue(L->ci->func))\n#define ci_func(ci)\t(clvalue((ci)->func))\n#define f_isLua(ci)\t(!ci_func(ci)->c.isC)\n#define isLua(ci)\t(ttisfunction((ci)->func) && f_isLua(ci))\n\n\n/*\n** `global state', shared by all threads of this state\n*/\ntypedef struct global_State {\n  stringtable strt;  /* hash table for strings */\n  lua_Alloc frealloc;  /* function to reallocate memory */\n  void *ud;         /* auxiliary data to `frealloc' */\n  lu_byte currentwhite;\n  lu_byte gcstate;  /* state of garbage collector */\n  int sweepstrgc;  /* position of sweep in `strt' */\n  GCObject *rootgc;  /* list of all collectable objects */\n  GCObject **sweepgc;  /* position of sweep in `rootgc' */\n  GCObject *gray;  /* list of gray objects */\n  GCObject *grayagain;  /* list of objects to be traversed atomically */\n  GCObject *weak;  /* list of weak tables (to be cleared) */\n  GCObject *tmudata;  /* last element of list of userdata to be GC */\n  Mbuffer buff;  /* temporary buffer for string concatentation */\n  lu_mem GCthreshold;\n  lu_mem totalbytes;  /* number of bytes currently allocated */\n  lu_mem estimate;  /* an estimate of number of bytes actually in use */\n  lu_mem gcdept;  /* how much GC is `behind schedule' */\n  int gcpause;  /* size of pause between successive GCs */\n  int gcstepmul;  /* GC `granularity' */\n  lua_CFunction panic;  /* to be called in unprotected errors */\n  TValue l_registry;\n  struct lua_State *mainthread;\n  UpVal uvhead;  /* head of double-linked list of all open upvalues */\n  struct Table *mt[NUM_TAGS];  /* metatables for basic types */\n  TString *tmname[TM_N];  /* array with tag-method names */\n} global_State;\n\n\n/*\n** `per thread' state\n*/\nstruct lua_State {\n  CommonHeader;\n  lu_byte status;\n  StkId top;  /* first free slot in the stack */\n  StkId base;  /* base of current function */\n  global_State *l_G;\n  CallInfo *ci;  /* call info for current function */\n  const Instruction *savedpc;  /* `savedpc' of current function */\n  StkId stack_last;  /* last free slot in the stack */\n  StkId stack;  /* stack base */\n  CallInfo *end_ci;  /* points after end of ci array*/\n  CallInfo *base_ci;  /* array of CallInfo's */\n  int stacksize;\n  int size_ci;  /* size of array `base_ci' */\n  unsigned short nCcalls;  /* number of nested C calls */\n  unsigned short baseCcalls;  /* nested C calls when resuming coroutine */\n  lu_byte hookmask;\n  lu_byte allowhook;\n  int basehookcount;\n  int hookcount;\n  lua_Hook hook;\n  TValue l_gt;  /* table of globals */\n  TValue env;  /* temporary place for environments */\n  GCObject *openupval;  /* list of open upvalues in this stack */\n  GCObject *gclist;\n  struct lua_longjmp *errorJmp;  /* current error recover point */\n  ptrdiff_t errfunc;  /* current error handling function (stack index) */\n};\n\n\n#define G(L)\t(L->l_G)\n\n\n/*\n** Union of all collectable objects\n*/\nunion GCObject {\n  GCheader gch;\n  union TString ts;\n  union Udata u;\n  union Closure cl;\n  struct Table h;\n  struct Proto p;\n  struct UpVal uv;\n  struct lua_State th;  /* thread */\n};\n\n\n/* macros to convert a GCObject into a specific value */\n#define rawgco2ts(o)\tcheck_exp((o)->gch.tt == LUA_TSTRING, &((o)->ts))\n#define gco2ts(o)\t(&rawgco2ts(o)->tsv)\n#define rawgco2u(o)\tcheck_exp((o)->gch.tt == LUA_TUSERDATA, &((o)->u))\n#define gco2u(o)\t(&rawgco2u(o)->uv)\n#define gco2cl(o)\tcheck_exp((o)->gch.tt == LUA_TFUNCTION, &((o)->cl))\n#define gco2h(o)\tcheck_exp((o)->gch.tt == LUA_TTABLE, &((o)->h))\n#define gco2p(o)\tcheck_exp((o)->gch.tt == LUA_TPROTO, &((o)->p))\n#define gco2uv(o)\tcheck_exp((o)->gch.tt == LUA_TUPVAL, &((o)->uv))\n#define ngcotouv(o) \\\n\tcheck_exp((o) == NULL || (o)->gch.tt == LUA_TUPVAL, &((o)->uv))\n#define gco2th(o)\tcheck_exp((o)->gch.tt == LUA_TTHREAD, &((o)->th))\n\n/* macro to convert any Lua object into a GCObject */\n#define obj2gco(v)\t(cast(GCObject *, (v)))\n\n\nLUAI_FUNC lua_State *luaE_newthread (lua_State *L);\nLUAI_FUNC void luaE_freethread (lua_State *L, lua_State *L1);\n\n#endif\n\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/deps/lua/src/lstring.c",
    "content": "/*\n** $Id: lstring.c,v 2.8.1.1 2007/12/27 13:02:25 roberto Exp $\n** String table (keeps all strings handled by Lua)\n** See Copyright Notice in lua.h\n*/\n\n\n#include <string.h>\n\n#define lstring_c\n#define LUA_CORE\n\n#include \"lua.h\"\n\n#include \"lmem.h\"\n#include \"lobject.h\"\n#include \"lstate.h\"\n#include \"lstring.h\"\n\n\n\nvoid luaS_resize (lua_State *L, int newsize) {\n  GCObject **newhash;\n  stringtable *tb;\n  int i;\n  if (G(L)->gcstate == GCSsweepstring)\n    return;  /* cannot resize during GC traverse */\n  newhash = luaM_newvector(L, newsize, GCObject *);\n  tb = &G(L)->strt;\n  for (i=0; i<newsize; i++) newhash[i] = NULL;\n  /* rehash */\n  for (i=0; i<tb->size; i++) {\n    GCObject *p = tb->hash[i];\n    while (p) {  /* for each node in the list */\n      GCObject *next = p->gch.next;  /* save next */\n      unsigned int h = gco2ts(p)->hash;\n      int h1 = lmod(h, newsize);  /* new position */\n      lua_assert(cast_int(h%newsize) == lmod(h, newsize));\n      p->gch.next = newhash[h1];  /* chain it */\n      newhash[h1] = p;\n      p = next;\n    }\n  }\n  luaM_freearray(L, tb->hash, tb->size, TString *);\n  tb->size = newsize;\n  tb->hash = newhash;\n}\n\n\nstatic TString *newlstr (lua_State *L, const char *str, size_t l,\n                                       unsigned int h) {\n  TString *ts;\n  stringtable *tb;\n  if (l+1 > (MAX_SIZET - sizeof(TString))/sizeof(char))\n    luaM_toobig(L);\n  ts = cast(TString *, luaM_malloc(L, (l+1)*sizeof(char)+sizeof(TString)));\n  ts->tsv.len = l;\n  ts->tsv.hash = h;\n  ts->tsv.marked = luaC_white(G(L));\n  ts->tsv.tt = LUA_TSTRING;\n  ts->tsv.reserved = 0;\n  memcpy(ts+1, str, l*sizeof(char));\n  ((char *)(ts+1))[l] = '\\0';  /* ending 0 */\n  tb = &G(L)->strt;\n  h = lmod(h, tb->size);\n  ts->tsv.next = tb->hash[h];  /* chain new entry */\n  tb->hash[h] = obj2gco(ts);\n  tb->nuse++;\n  if (tb->nuse > cast(lu_int32, tb->size) && tb->size <= MAX_INT/2)\n    luaS_resize(L, tb->size*2);  /* too crowded */\n  return ts;\n}\n\n\nTString *luaS_newlstr (lua_State *L, const char *str, size_t l) {\n  GCObject *o;\n  unsigned int h = cast(unsigned int, l);  /* seed */\n  size_t step = (l>>5)+1;  /* if string is too long, don't hash all its chars */\n  size_t l1;\n  for (l1=l; l1>=step; l1-=step)  /* compute hash */\n    h = h ^ ((h<<5)+(h>>2)+cast(unsigned char, str[l1-1]));\n  for (o = G(L)->strt.hash[lmod(h, G(L)->strt.size)];\n       o != NULL;\n       o = o->gch.next) {\n    TString *ts = rawgco2ts(o);\n    if (ts->tsv.len == l && (memcmp(str, getstr(ts), l) == 0)) {\n      /* string may be dead */\n      if (isdead(G(L), o)) changewhite(o);\n      return ts;\n    }\n  }\n  return newlstr(L, str, l, h);  /* not found */\n}\n\n\nUdata *luaS_newudata (lua_State *L, size_t s, Table *e) {\n  Udata *u;\n  if (s > MAX_SIZET - sizeof(Udata))\n    luaM_toobig(L);\n  u = cast(Udata *, luaM_malloc(L, s + sizeof(Udata)));\n  u->uv.marked = luaC_white(G(L));  /* is not finalized */\n  u->uv.tt = LUA_TUSERDATA;\n  u->uv.len = s;\n  u->uv.metatable = NULL;\n  u->uv.env = e;\n  /* chain it on udata list (after main thread) */\n  u->uv.next = G(L)->mainthread->next;\n  G(L)->mainthread->next = obj2gco(u);\n  return u;\n}\n\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/deps/lua/src/lstring.h",
    "content": "/*\n** $Id: lstring.h,v 1.43.1.1 2007/12/27 13:02:25 roberto Exp $\n** String table (keep all strings handled by Lua)\n** See Copyright Notice in lua.h\n*/\n\n#ifndef lstring_h\n#define lstring_h\n\n\n#include \"lgc.h\"\n#include \"lobject.h\"\n#include \"lstate.h\"\n\n\n#define sizestring(s)\t(sizeof(union TString)+((s)->len+1)*sizeof(char))\n\n#define sizeudata(u)\t(sizeof(union Udata)+(u)->len)\n\n#define luaS_new(L, s)\t(luaS_newlstr(L, s, strlen(s)))\n#define luaS_newliteral(L, s)\t(luaS_newlstr(L, \"\" s, \\\n                                 (sizeof(s)/sizeof(char))-1))\n\n#define luaS_fix(s)\tl_setbit((s)->tsv.marked, FIXEDBIT)\n\nLUAI_FUNC void luaS_resize (lua_State *L, int newsize);\nLUAI_FUNC Udata *luaS_newudata (lua_State *L, size_t s, Table *e);\nLUAI_FUNC TString *luaS_newlstr (lua_State *L, const char *str, size_t l);\n\n\n#endif\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/deps/lua/src/lstrlib.c",
    "content": "/*\n** $Id: lstrlib.c,v 1.132.1.5 2010/05/14 15:34:19 roberto Exp $\n** Standard library for string operations and pattern-matching\n** See Copyright Notice in lua.h\n*/\n\n\n#include <ctype.h>\n#include <stddef.h>\n#include <stdio.h>\n#include <stdlib.h>\n#include <string.h>\n\n#define lstrlib_c\n#define LUA_LIB\n\n#include \"lua.h\"\n\n#include \"lauxlib.h\"\n#include \"lualib.h\"\n\n\n/* macro to `unsign' a character */\n#define uchar(c)        ((unsigned char)(c))\n\n\n\nstatic int str_len (lua_State *L) {\n  size_t l;\n  luaL_checklstring(L, 1, &l);\n  lua_pushinteger(L, l);\n  return 1;\n}\n\n\nstatic ptrdiff_t posrelat (ptrdiff_t pos, size_t len) {\n  /* relative string position: negative means back from end */\n  if (pos < 0) pos += (ptrdiff_t)len + 1;\n  return (pos >= 0) ? pos : 0;\n}\n\n\nstatic int str_sub (lua_State *L) {\n  size_t l;\n  const char *s = luaL_checklstring(L, 1, &l);\n  ptrdiff_t start = posrelat(luaL_checkinteger(L, 2), l);\n  ptrdiff_t end = posrelat(luaL_optinteger(L, 3, -1), l);\n  if (start < 1) start = 1;\n  if (end > (ptrdiff_t)l) end = (ptrdiff_t)l;\n  if (start <= end)\n    lua_pushlstring(L, s+start-1, end-start+1);\n  else lua_pushliteral(L, \"\");\n  return 1;\n}\n\n\nstatic int str_reverse (lua_State *L) {\n  size_t l;\n  luaL_Buffer b;\n  const char *s = luaL_checklstring(L, 1, &l);\n  luaL_buffinit(L, &b);\n  while (l--) luaL_addchar(&b, s[l]);\n  luaL_pushresult(&b);\n  return 1;\n}\n\n\nstatic int str_lower (lua_State *L) {\n  size_t l;\n  size_t i;\n  luaL_Buffer b;\n  const char *s = luaL_checklstring(L, 1, &l);\n  luaL_buffinit(L, &b);\n  for (i=0; i<l; i++)\n    luaL_addchar(&b, tolower(uchar(s[i])));\n  luaL_pushresult(&b);\n  return 1;\n}\n\n\nstatic int str_upper (lua_State *L) {\n  size_t l;\n  size_t i;\n  luaL_Buffer b;\n  const char *s = luaL_checklstring(L, 1, &l);\n  luaL_buffinit(L, &b);\n  for (i=0; i<l; i++)\n    luaL_addchar(&b, toupper(uchar(s[i])));\n  luaL_pushresult(&b);\n  return 1;\n}\n\nstatic int str_rep (lua_State *L) {\n  size_t l;\n  luaL_Buffer b;\n  const char *s = luaL_checklstring(L, 1, &l);\n  int n = luaL_checkint(L, 2);\n  luaL_buffinit(L, &b);\n  while (n-- > 0)\n    luaL_addlstring(&b, s, l);\n  luaL_pushresult(&b);\n  return 1;\n}\n\n\nstatic int str_byte (lua_State *L) {\n  size_t l;\n  const char *s = luaL_checklstring(L, 1, &l);\n  ptrdiff_t posi = posrelat(luaL_optinteger(L, 2, 1), l);\n  ptrdiff_t pose = posrelat(luaL_optinteger(L, 3, posi), l);\n  int n, i;\n  if (posi <= 0) posi = 1;\n  if ((size_t)pose > l) pose = l;\n  if (posi > pose) return 0;  /* empty interval; return no values */\n  n = (int)(pose -  posi + 1);\n  if (posi + n <= pose)  /* overflow? */\n    luaL_error(L, \"string slice too long\");\n  luaL_checkstack(L, n, \"string slice too long\");\n  for (i=0; i<n; i++)\n    lua_pushinteger(L, uchar(s[posi+i-1]));\n  return n;\n}\n\n\nstatic int str_char (lua_State *L) {\n  int n = lua_gettop(L);  /* number of arguments */\n  int i;\n  luaL_Buffer b;\n  luaL_buffinit(L, &b);\n  for (i=1; i<=n; i++) {\n    int c = luaL_checkint(L, i);\n    luaL_argcheck(L, uchar(c) == c, i, \"invalid value\");\n    luaL_addchar(&b, uchar(c));\n  }\n  luaL_pushresult(&b);\n  return 1;\n}\n\n\nstatic int writer (lua_State *L, const void* b, size_t size, void* B) {\n  (void)L;\n  luaL_addlstring((luaL_Buffer*) B, (const char *)b, size);\n  return 0;\n}\n\n\nstatic int str_dump (lua_State *L) {\n  luaL_Buffer b;\n  luaL_checktype(L, 1, LUA_TFUNCTION);\n  lua_settop(L, 1);\n  luaL_buffinit(L,&b);\n  if (lua_dump(L, writer, &b) != 0)\n    luaL_error(L, \"unable to dump given function\");\n  luaL_pushresult(&b);\n  return 1;\n}\n\n\n\n/*\n** {======================================================\n** PATTERN MATCHING\n** =======================================================\n*/\n\n\n#define CAP_UNFINISHED\t(-1)\n#define CAP_POSITION\t(-2)\n\ntypedef struct MatchState {\n  const char *src_init;  /* init of source string */\n  const char *src_end;  /* end (`\\0') of source string */\n  lua_State *L;\n  int level;  /* total number of captures (finished or unfinished) */\n  struct {\n    const char *init;\n    ptrdiff_t len;\n  } capture[LUA_MAXCAPTURES];\n} MatchState;\n\n\n#define L_ESC\t\t'%'\n#define SPECIALS\t\"^$*+?.([%-\"\n\n\nstatic int check_capture (MatchState *ms, int l) {\n  l -= '1';\n  if (l < 0 || l >= ms->level || ms->capture[l].len == CAP_UNFINISHED)\n    return luaL_error(ms->L, \"invalid capture index\");\n  return l;\n}\n\n\nstatic int capture_to_close (MatchState *ms) {\n  int level = ms->level;\n  for (level--; level>=0; level--)\n    if (ms->capture[level].len == CAP_UNFINISHED) return level;\n  return luaL_error(ms->L, \"invalid pattern capture\");\n}\n\n\nstatic const char *classend (MatchState *ms, const char *p) {\n  switch (*p++) {\n    case L_ESC: {\n      if (*p == '\\0')\n        luaL_error(ms->L, \"malformed pattern (ends with \" LUA_QL(\"%%\") \")\");\n      return p+1;\n    }\n    case '[': {\n      if (*p == '^') p++;\n      do {  /* look for a `]' */\n        if (*p == '\\0')\n          luaL_error(ms->L, \"malformed pattern (missing \" LUA_QL(\"]\") \")\");\n        if (*(p++) == L_ESC && *p != '\\0')\n          p++;  /* skip escapes (e.g. `%]') */\n      } while (*p != ']');\n      return p+1;\n    }\n    default: {\n      return p;\n    }\n  }\n}\n\n\nstatic int match_class (int c, int cl) {\n  int res;\n  switch (tolower(cl)) {\n    case 'a' : res = isalpha(c); break;\n    case 'c' : res = iscntrl(c); break;\n    case 'd' : res = isdigit(c); break;\n    case 'l' : res = islower(c); break;\n    case 'p' : res = ispunct(c); break;\n    case 's' : res = isspace(c); break;\n    case 'u' : res = isupper(c); break;\n    case 'w' : res = isalnum(c); break;\n    case 'x' : res = isxdigit(c); break;\n    case 'z' : res = (c == 0); break;\n    default: return (cl == c);\n  }\n  return (islower(cl) ? res : !res);\n}\n\n\nstatic int matchbracketclass (int c, const char *p, const char *ec) {\n  int sig = 1;\n  if (*(p+1) == '^') {\n    sig = 0;\n    p++;  /* skip the `^' */\n  }\n  while (++p < ec) {\n    if (*p == L_ESC) {\n      p++;\n      if (match_class(c, uchar(*p)))\n        return sig;\n    }\n    else if ((*(p+1) == '-') && (p+2 < ec)) {\n      p+=2;\n      if (uchar(*(p-2)) <= c && c <= uchar(*p))\n        return sig;\n    }\n    else if (uchar(*p) == c) return sig;\n  }\n  return !sig;\n}\n\n\nstatic int singlematch (int c, const char *p, const char *ep) {\n  switch (*p) {\n    case '.': return 1;  /* matches any char */\n    case L_ESC: return match_class(c, uchar(*(p+1)));\n    case '[': return matchbracketclass(c, p, ep-1);\n    default:  return (uchar(*p) == c);\n  }\n}\n\n\nstatic const char *match (MatchState *ms, const char *s, const char *p);\n\n\nstatic const char *matchbalance (MatchState *ms, const char *s,\n                                   const char *p) {\n  if (*p == 0 || *(p+1) == 0)\n    luaL_error(ms->L, \"unbalanced pattern\");\n  if (*s != *p) return NULL;\n  else {\n    int b = *p;\n    int e = *(p+1);\n    int cont = 1;\n    while (++s < ms->src_end) {\n      if (*s == e) {\n        if (--cont == 0) return s+1;\n      }\n      else if (*s == b) cont++;\n    }\n  }\n  return NULL;  /* string ends out of balance */\n}\n\n\nstatic const char *max_expand (MatchState *ms, const char *s,\n                                 const char *p, const char *ep) {\n  ptrdiff_t i = 0;  /* counts maximum expand for item */\n  while ((s+i)<ms->src_end && singlematch(uchar(*(s+i)), p, ep))\n    i++;\n  /* keeps trying to match with the maximum repetitions */\n  while (i>=0) {\n    const char *res = match(ms, (s+i), ep+1);\n    if (res) return res;\n    i--;  /* else didn't match; reduce 1 repetition to try again */\n  }\n  return NULL;\n}\n\n\nstatic const char *min_expand (MatchState *ms, const char *s,\n                                 const char *p, const char *ep) {\n  for (;;) {\n    const char *res = match(ms, s, ep+1);\n    if (res != NULL)\n      return res;\n    else if (s<ms->src_end && singlematch(uchar(*s), p, ep))\n      s++;  /* try with one more repetition */\n    else return NULL;\n  }\n}\n\n\nstatic const char *start_capture (MatchState *ms, const char *s,\n                                    const char *p, int what) {\n  const char *res;\n  int level = ms->level;\n  if (level >= LUA_MAXCAPTURES) luaL_error(ms->L, \"too many captures\");\n  ms->capture[level].init = s;\n  ms->capture[level].len = what;\n  ms->level = level+1;\n  if ((res=match(ms, s, p)) == NULL)  /* match failed? */\n    ms->level--;  /* undo capture */\n  return res;\n}\n\n\nstatic const char *end_capture (MatchState *ms, const char *s,\n                                  const char *p) {\n  int l = capture_to_close(ms);\n  const char *res;\n  ms->capture[l].len = s - ms->capture[l].init;  /* close capture */\n  if ((res = match(ms, s, p)) == NULL)  /* match failed? */\n    ms->capture[l].len = CAP_UNFINISHED;  /* undo capture */\n  return res;\n}\n\n\nstatic const char *match_capture (MatchState *ms, const char *s, int l) {\n  size_t len;\n  l = check_capture(ms, l);\n  len = ms->capture[l].len;\n  if ((size_t)(ms->src_end-s) >= len &&\n      memcmp(ms->capture[l].init, s, len) == 0)\n    return s+len;\n  else return NULL;\n}\n\n\nstatic const char *match (MatchState *ms, const char *s, const char *p) {\n  init: /* using goto's to optimize tail recursion */\n  switch (*p) {\n    case '(': {  /* start capture */\n      if (*(p+1) == ')')  /* position capture? */\n        return start_capture(ms, s, p+2, CAP_POSITION);\n      else\n        return start_capture(ms, s, p+1, CAP_UNFINISHED);\n    }\n    case ')': {  /* end capture */\n      return end_capture(ms, s, p+1);\n    }\n    case L_ESC: {\n      switch (*(p+1)) {\n        case 'b': {  /* balanced string? */\n          s = matchbalance(ms, s, p+2);\n          if (s == NULL) return NULL;\n          p+=4; goto init;  /* else return match(ms, s, p+4); */\n        }\n        case 'f': {  /* frontier? */\n          const char *ep; char previous;\n          p += 2;\n          if (*p != '[')\n            luaL_error(ms->L, \"missing \" LUA_QL(\"[\") \" after \"\n                               LUA_QL(\"%%f\") \" in pattern\");\n          ep = classend(ms, p);  /* points to what is next */\n          previous = (s == ms->src_init) ? '\\0' : *(s-1);\n          if (matchbracketclass(uchar(previous), p, ep-1) ||\n             !matchbracketclass(uchar(*s), p, ep-1)) return NULL;\n          p=ep; goto init;  /* else return match(ms, s, ep); */\n        }\n        default: {\n          if (isdigit(uchar(*(p+1)))) {  /* capture results (%0-%9)? */\n            s = match_capture(ms, s, uchar(*(p+1)));\n            if (s == NULL) return NULL;\n            p+=2; goto init;  /* else return match(ms, s, p+2) */\n          }\n          goto dflt;  /* case default */\n        }\n      }\n    }\n    case '\\0': {  /* end of pattern */\n      return s;  /* match succeeded */\n    }\n    case '$': {\n      if (*(p+1) == '\\0')  /* is the `$' the last char in pattern? */\n        return (s == ms->src_end) ? s : NULL;  /* check end of string */\n      else goto dflt;\n    }\n    default: dflt: {  /* it is a pattern item */\n      const char *ep = classend(ms, p);  /* points to what is next */\n      int m = s<ms->src_end && singlematch(uchar(*s), p, ep);\n      switch (*ep) {\n        case '?': {  /* optional */\n          const char *res;\n          if (m && ((res=match(ms, s+1, ep+1)) != NULL))\n            return res;\n          p=ep+1; goto init;  /* else return match(ms, s, ep+1); */\n        }\n        case '*': {  /* 0 or more repetitions */\n          return max_expand(ms, s, p, ep);\n        }\n        case '+': {  /* 1 or more repetitions */\n          return (m ? max_expand(ms, s+1, p, ep) : NULL);\n        }\n        case '-': {  /* 0 or more repetitions (minimum) */\n          return min_expand(ms, s, p, ep);\n        }\n        default: {\n          if (!m) return NULL;\n          s++; p=ep; goto init;  /* else return match(ms, s+1, ep); */\n        }\n      }\n    }\n  }\n}\n\n\n\nstatic const char *lmemfind (const char *s1, size_t l1,\n                               const char *s2, size_t l2) {\n  if (l2 == 0) return s1;  /* empty strings are everywhere */\n  else if (l2 > l1) return NULL;  /* avoids a negative `l1' */\n  else {\n    const char *init;  /* to search for a `*s2' inside `s1' */\n    l2--;  /* 1st char will be checked by `memchr' */\n    l1 = l1-l2;  /* `s2' cannot be found after that */\n    while (l1 > 0 && (init = (const char *)memchr(s1, *s2, l1)) != NULL) {\n      init++;   /* 1st char is already checked */\n      if (memcmp(init, s2+1, l2) == 0)\n        return init-1;\n      else {  /* correct `l1' and `s1' to try again */\n        l1 -= init-s1;\n        s1 = init;\n      }\n    }\n    return NULL;  /* not found */\n  }\n}\n\n\nstatic void push_onecapture (MatchState *ms, int i, const char *s,\n                                                    const char *e) {\n  if (i >= ms->level) {\n    if (i == 0)  /* ms->level == 0, too */\n      lua_pushlstring(ms->L, s, e - s);  /* add whole match */\n    else\n      luaL_error(ms->L, \"invalid capture index\");\n  }\n  else {\n    ptrdiff_t l = ms->capture[i].len;\n    if (l == CAP_UNFINISHED) luaL_error(ms->L, \"unfinished capture\");\n    if (l == CAP_POSITION)\n      lua_pushinteger(ms->L, ms->capture[i].init - ms->src_init + 1);\n    else\n      lua_pushlstring(ms->L, ms->capture[i].init, l);\n  }\n}\n\n\nstatic int push_captures (MatchState *ms, const char *s, const char *e) {\n  int i;\n  int nlevels = (ms->level == 0 && s) ? 1 : ms->level;\n  luaL_checkstack(ms->L, nlevels, \"too many captures\");\n  for (i = 0; i < nlevels; i++)\n    push_onecapture(ms, i, s, e);\n  return nlevels;  /* number of strings pushed */\n}\n\n\nstatic int str_find_aux (lua_State *L, int find) {\n  size_t l1, l2;\n  const char *s = luaL_checklstring(L, 1, &l1);\n  const char *p = luaL_checklstring(L, 2, &l2);\n  ptrdiff_t init = posrelat(luaL_optinteger(L, 3, 1), l1) - 1;\n  if (init < 0) init = 0;\n  else if ((size_t)(init) > l1) init = (ptrdiff_t)l1;\n  if (find && (lua_toboolean(L, 4) ||  /* explicit request? */\n      strpbrk(p, SPECIALS) == NULL)) {  /* or no special characters? */\n    /* do a plain search */\n    const char *s2 = lmemfind(s+init, l1-init, p, l2);\n    if (s2) {\n      lua_pushinteger(L, s2-s+1);\n      lua_pushinteger(L, s2-s+l2);\n      return 2;\n    }\n  }\n  else {\n    MatchState ms;\n    int anchor = (*p == '^') ? (p++, 1) : 0;\n    const char *s1=s+init;\n    ms.L = L;\n    ms.src_init = s;\n    ms.src_end = s+l1;\n    do {\n      const char *res;\n      ms.level = 0;\n      if ((res=match(&ms, s1, p)) != NULL) {\n        if (find) {\n          lua_pushinteger(L, s1-s+1);  /* start */\n          lua_pushinteger(L, res-s);   /* end */\n          return push_captures(&ms, NULL, 0) + 2;\n        }\n        else\n          return push_captures(&ms, s1, res);\n      }\n    } while (s1++ < ms.src_end && !anchor);\n  }\n  lua_pushnil(L);  /* not found */\n  return 1;\n}\n\n\nstatic int str_find (lua_State *L) {\n  return str_find_aux(L, 1);\n}\n\n\nstatic int str_match (lua_State *L) {\n  return str_find_aux(L, 0);\n}\n\n\nstatic int gmatch_aux (lua_State *L) {\n  MatchState ms;\n  size_t ls;\n  const char *s = lua_tolstring(L, lua_upvalueindex(1), &ls);\n  const char *p = lua_tostring(L, lua_upvalueindex(2));\n  const char *src;\n  ms.L = L;\n  ms.src_init = s;\n  ms.src_end = s+ls;\n  for (src = s + (size_t)lua_tointeger(L, lua_upvalueindex(3));\n       src <= ms.src_end;\n       src++) {\n    const char *e;\n    ms.level = 0;\n    if ((e = match(&ms, src, p)) != NULL) {\n      lua_Integer newstart = e-s;\n      if (e == src) newstart++;  /* empty match? go at least one position */\n      lua_pushinteger(L, newstart);\n      lua_replace(L, lua_upvalueindex(3));\n      return push_captures(&ms, src, e);\n    }\n  }\n  return 0;  /* not found */\n}\n\n\nstatic int gmatch (lua_State *L) {\n  luaL_checkstring(L, 1);\n  luaL_checkstring(L, 2);\n  lua_settop(L, 2);\n  lua_pushinteger(L, 0);\n  lua_pushcclosure(L, gmatch_aux, 3);\n  return 1;\n}\n\n\nstatic int gfind_nodef (lua_State *L) {\n  return luaL_error(L, LUA_QL(\"string.gfind\") \" was renamed to \"\n                       LUA_QL(\"string.gmatch\"));\n}\n\n\nstatic void add_s (MatchState *ms, luaL_Buffer *b, const char *s,\n                                                   const char *e) {\n  size_t l, i;\n  const char *news = lua_tolstring(ms->L, 3, &l);\n  for (i = 0; i < l; i++) {\n    if (news[i] != L_ESC)\n      luaL_addchar(b, news[i]);\n    else {\n      i++;  /* skip ESC */\n      if (!isdigit(uchar(news[i])))\n        luaL_addchar(b, news[i]);\n      else if (news[i] == '0')\n          luaL_addlstring(b, s, e - s);\n      else {\n        push_onecapture(ms, news[i] - '1', s, e);\n        luaL_addvalue(b);  /* add capture to accumulated result */\n      }\n    }\n  }\n}\n\n\nstatic void add_value (MatchState *ms, luaL_Buffer *b, const char *s,\n                                                       const char *e) {\n  lua_State *L = ms->L;\n  switch (lua_type(L, 3)) {\n    case LUA_TNUMBER:\n    case LUA_TSTRING: {\n      add_s(ms, b, s, e);\n      return;\n    }\n    case LUA_TFUNCTION: {\n      int n;\n      lua_pushvalue(L, 3);\n      n = push_captures(ms, s, e);\n      lua_call(L, n, 1);\n      break;\n    }\n    case LUA_TTABLE: {\n      push_onecapture(ms, 0, s, e);\n      lua_gettable(L, 3);\n      break;\n    }\n  }\n  if (!lua_toboolean(L, -1)) {  /* nil or false? */\n    lua_pop(L, 1);\n    lua_pushlstring(L, s, e - s);  /* keep original text */\n  }\n  else if (!lua_isstring(L, -1))\n    luaL_error(L, \"invalid replacement value (a %s)\", luaL_typename(L, -1)); \n  luaL_addvalue(b);  /* add result to accumulator */\n}\n\n\nstatic int str_gsub (lua_State *L) {\n  size_t srcl;\n  const char *src = luaL_checklstring(L, 1, &srcl);\n  const char *p = luaL_checkstring(L, 2);\n  int  tr = lua_type(L, 3);\n  int max_s = luaL_optint(L, 4, srcl+1);\n  int anchor = (*p == '^') ? (p++, 1) : 0;\n  int n = 0;\n  MatchState ms;\n  luaL_Buffer b;\n  luaL_argcheck(L, tr == LUA_TNUMBER || tr == LUA_TSTRING ||\n                   tr == LUA_TFUNCTION || tr == LUA_TTABLE, 3,\n                      \"string/function/table expected\");\n  luaL_buffinit(L, &b);\n  ms.L = L;\n  ms.src_init = src;\n  ms.src_end = src+srcl;\n  while (n < max_s) {\n    const char *e;\n    ms.level = 0;\n    e = match(&ms, src, p);\n    if (e) {\n      n++;\n      add_value(&ms, &b, src, e);\n    }\n    if (e && e>src) /* non empty match? */\n      src = e;  /* skip it */\n    else if (src < ms.src_end)\n      luaL_addchar(&b, *src++);\n    else break;\n    if (anchor) break;\n  }\n  luaL_addlstring(&b, src, ms.src_end-src);\n  luaL_pushresult(&b);\n  lua_pushinteger(L, n);  /* number of substitutions */\n  return 2;\n}\n\n/* }====================================================== */\n\n\n/* maximum size of each formatted item (> len(format('%99.99f', -1e308))) */\n#define MAX_ITEM\t512\n/* valid flags in a format specification */\n#define FLAGS\t\"-+ #0\"\n/*\n** maximum size of each format specification (such as '%-099.99d')\n** (+10 accounts for %99.99x plus margin of error)\n*/\n#define MAX_FORMAT\t(sizeof(FLAGS) + sizeof(LUA_INTFRMLEN) + 10)\n\n\nstatic void addquoted (lua_State *L, luaL_Buffer *b, int arg) {\n  size_t l;\n  const char *s = luaL_checklstring(L, arg, &l);\n  luaL_addchar(b, '\"');\n  while (l--) {\n    switch (*s) {\n      case '\"': case '\\\\': case '\\n': {\n        luaL_addchar(b, '\\\\');\n        luaL_addchar(b, *s);\n        break;\n      }\n      case '\\r': {\n        luaL_addlstring(b, \"\\\\r\", 2);\n        break;\n      }\n      case '\\0': {\n        luaL_addlstring(b, \"\\\\000\", 4);\n        break;\n      }\n      default: {\n        luaL_addchar(b, *s);\n        break;\n      }\n    }\n    s++;\n  }\n  luaL_addchar(b, '\"');\n}\n\nstatic const char *scanformat (lua_State *L, const char *strfrmt, char *form) {\n  const char *p = strfrmt;\n  while (*p != '\\0' && strchr(FLAGS, *p) != NULL) p++;  /* skip flags */\n  if ((size_t)(p - strfrmt) >= sizeof(FLAGS))\n    luaL_error(L, \"invalid format (repeated flags)\");\n  if (isdigit(uchar(*p))) p++;  /* skip width */\n  if (isdigit(uchar(*p))) p++;  /* (2 digits at most) */\n  if (*p == '.') {\n    p++;\n    if (isdigit(uchar(*p))) p++;  /* skip precision */\n    if (isdigit(uchar(*p))) p++;  /* (2 digits at most) */\n  }\n  if (isdigit(uchar(*p)))\n    luaL_error(L, \"invalid format (width or precision too long)\");\n  *(form++) = '%';\n  strncpy(form, strfrmt, p - strfrmt + 1);\n  form += p - strfrmt + 1;\n  *form = '\\0';\n  return p;\n}\n\n\nstatic void addintlen (char *form) {\n  size_t l = strlen(form);\n  char spec = form[l - 1];\n  strcpy(form + l - 1, LUA_INTFRMLEN);\n  form[l + sizeof(LUA_INTFRMLEN) - 2] = spec;\n  form[l + sizeof(LUA_INTFRMLEN) - 1] = '\\0';\n}\n\n\nstatic int str_format (lua_State *L) {\n  int top = lua_gettop(L);\n  int arg = 1;\n  size_t sfl;\n  const char *strfrmt = luaL_checklstring(L, arg, &sfl);\n  const char *strfrmt_end = strfrmt+sfl;\n  luaL_Buffer b;\n  luaL_buffinit(L, &b);\n  while (strfrmt < strfrmt_end) {\n    if (*strfrmt != L_ESC)\n      luaL_addchar(&b, *strfrmt++);\n    else if (*++strfrmt == L_ESC)\n      luaL_addchar(&b, *strfrmt++);  /* %% */\n    else { /* format item */\n      char form[MAX_FORMAT];  /* to store the format (`%...') */\n      char buff[MAX_ITEM];  /* to store the formatted item */\n      if (++arg > top)\n        luaL_argerror(L, arg, \"no value\");\n      strfrmt = scanformat(L, strfrmt, form);\n      switch (*strfrmt++) {\n        case 'c': {\n          sprintf(buff, form, (int)luaL_checknumber(L, arg));\n          break;\n        }\n        case 'd':  case 'i': {\n          addintlen(form);\n          sprintf(buff, form, (LUA_INTFRM_T)luaL_checknumber(L, arg));\n          break;\n        }\n        case 'o':  case 'u':  case 'x':  case 'X': {\n          addintlen(form);\n          sprintf(buff, form, (unsigned LUA_INTFRM_T)luaL_checknumber(L, arg));\n          break;\n        }\n        case 'e':  case 'E': case 'f':\n        case 'g': case 'G': {\n          sprintf(buff, form, (double)luaL_checknumber(L, arg));\n          break;\n        }\n        case 'q': {\n          addquoted(L, &b, arg);\n          continue;  /* skip the 'addsize' at the end */\n        }\n        case 's': {\n          size_t l;\n          const char *s = luaL_checklstring(L, arg, &l);\n          if (!strchr(form, '.') && l >= 100) {\n            /* no precision and string is too long to be formatted;\n               keep original string */\n            lua_pushvalue(L, arg);\n            luaL_addvalue(&b);\n            continue;  /* skip the `addsize' at the end */\n          }\n          else {\n            sprintf(buff, form, s);\n            break;\n          }\n        }\n        default: {  /* also treat cases `pnLlh' */\n          return luaL_error(L, \"invalid option \" LUA_QL(\"%%%c\") \" to \"\n                               LUA_QL(\"format\"), *(strfrmt - 1));\n        }\n      }\n      luaL_addlstring(&b, buff, strlen(buff));\n    }\n  }\n  luaL_pushresult(&b);\n  return 1;\n}\n\n\nstatic const luaL_Reg strlib[] = {\n  {\"byte\", str_byte},\n  {\"char\", str_char},\n  {\"dump\", str_dump},\n  {\"find\", str_find},\n  {\"format\", str_format},\n  {\"gfind\", gfind_nodef},\n  {\"gmatch\", gmatch},\n  {\"gsub\", str_gsub},\n  {\"len\", str_len},\n  {\"lower\", str_lower},\n  {\"match\", str_match},\n  {\"rep\", str_rep},\n  {\"reverse\", str_reverse},\n  {\"sub\", str_sub},\n  {\"upper\", str_upper},\n  {NULL, NULL}\n};\n\n\nstatic void createmetatable (lua_State *L) {\n  lua_createtable(L, 0, 1);  /* create metatable for strings */\n  lua_pushliteral(L, \"\");  /* dummy string */\n  lua_pushvalue(L, -2);\n  lua_setmetatable(L, -2);  /* set string metatable */\n  lua_pop(L, 1);  /* pop dummy string */\n  lua_pushvalue(L, -2);  /* string library... */\n  lua_setfield(L, -2, \"__index\");  /* ...is the __index metamethod */\n  lua_pop(L, 1);  /* pop metatable */\n}\n\n\n/*\n** Open string library\n*/\nLUALIB_API int luaopen_string (lua_State *L) {\n  luaL_register(L, LUA_STRLIBNAME, strlib);\n#if defined(LUA_COMPAT_GFIND)\n  lua_getfield(L, -1, \"gmatch\");\n  lua_setfield(L, -2, \"gfind\");\n#endif\n  createmetatable(L);\n  return 1;\n}\n\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/deps/lua/src/ltable.c",
    "content": "/*\n** $Id: ltable.c,v 2.32.1.2 2007/12/28 15:32:23 roberto Exp $\n** Lua tables (hash)\n** See Copyright Notice in lua.h\n*/\n\n\n/*\n** Implementation of tables (aka arrays, objects, or hash tables).\n** Tables keep its elements in two parts: an array part and a hash part.\n** Non-negative integer keys are all candidates to be kept in the array\n** part. The actual size of the array is the largest `n' such that at\n** least half the slots between 0 and n are in use.\n** Hash uses a mix of chained scatter table with Brent's variation.\n** A main invariant of these tables is that, if an element is not\n** in its main position (i.e. the `original' position that its hash gives\n** to it), then the colliding element is in its own main position.\n** Hence even when the load factor reaches 100%, performance remains good.\n*/\n\n#include <math.h>\n#include <string.h>\n\n#define ltable_c\n#define LUA_CORE\n\n#include \"lua.h\"\n\n#include \"ldebug.h\"\n#include \"ldo.h\"\n#include \"lgc.h\"\n#include \"lmem.h\"\n#include \"lobject.h\"\n#include \"lstate.h\"\n#include \"ltable.h\"\n\n\n/*\n** max size of array part is 2^MAXBITS\n*/\n#if LUAI_BITSINT > 26\n#define MAXBITS\t\t26\n#else\n#define MAXBITS\t\t(LUAI_BITSINT-2)\n#endif\n\n#define MAXASIZE\t(1 << MAXBITS)\n\n\n#define hashpow2(t,n)      (gnode(t, lmod((n), sizenode(t))))\n  \n#define hashstr(t,str)  hashpow2(t, (str)->tsv.hash)\n#define hashboolean(t,p)        hashpow2(t, p)\n\n\n/*\n** for some types, it is better to avoid modulus by power of 2, as\n** they tend to have many 2 factors.\n*/\n#define hashmod(t,n)\t(gnode(t, ((n) % ((sizenode(t)-1)|1))))\n\n\n#define hashpointer(t,p)\thashmod(t, IntPoint(p))\n\n\n/*\n** number of ints inside a lua_Number\n*/\n#define numints\t\tcast_int(sizeof(lua_Number)/sizeof(int))\n\n\n\n#define dummynode\t\t(&dummynode_)\n\nstatic const Node dummynode_ = {\n  {{NULL}, LUA_TNIL},  /* value */\n  {{{NULL}, LUA_TNIL, NULL}}  /* key */\n};\n\n\n/*\n** hash for lua_Numbers\n*/\nstatic Node *hashnum (const Table *t, lua_Number n) {\n  unsigned int a[numints];\n  int i;\n  if (luai_numeq(n, 0))  /* avoid problems with -0 */\n    return gnode(t, 0);\n  memcpy(a, &n, sizeof(a));\n  for (i = 1; i < numints; i++) a[0] += a[i];\n  return hashmod(t, a[0]);\n}\n\n\n\n/*\n** returns the `main' position of an element in a table (that is, the index\n** of its hash value)\n*/\nstatic Node *mainposition (const Table *t, const TValue *key) {\n  switch (ttype(key)) {\n    case LUA_TNUMBER:\n      return hashnum(t, nvalue(key));\n    case LUA_TSTRING:\n      return hashstr(t, rawtsvalue(key));\n    case LUA_TBOOLEAN:\n      return hashboolean(t, bvalue(key));\n    case LUA_TLIGHTUSERDATA:\n      return hashpointer(t, pvalue(key));\n    default:\n      return hashpointer(t, gcvalue(key));\n  }\n}\n\n\n/*\n** returns the index for `key' if `key' is an appropriate key to live in\n** the array part of the table, -1 otherwise.\n*/\nstatic int arrayindex (const TValue *key) {\n  if (ttisnumber(key)) {\n    lua_Number n = nvalue(key);\n    int k;\n    lua_number2int(k, n);\n    if (luai_numeq(cast_num(k), n))\n      return k;\n  }\n  return -1;  /* `key' did not match some condition */\n}\n\n\n/*\n** returns the index of a `key' for table traversals. First goes all\n** elements in the array part, then elements in the hash part. The\n** beginning of a traversal is signalled by -1.\n*/\nstatic int findindex (lua_State *L, Table *t, StkId key) {\n  int i;\n  if (ttisnil(key)) return -1;  /* first iteration */\n  i = arrayindex(key);\n  if (0 < i && i <= t->sizearray)  /* is `key' inside array part? */\n    return i-1;  /* yes; that's the index (corrected to C) */\n  else {\n    Node *n = mainposition(t, key);\n    do {  /* check whether `key' is somewhere in the chain */\n      /* key may be dead already, but it is ok to use it in `next' */\n      if (luaO_rawequalObj(key2tval(n), key) ||\n            (ttype(gkey(n)) == LUA_TDEADKEY && iscollectable(key) &&\n             gcvalue(gkey(n)) == gcvalue(key))) {\n        i = cast_int(n - gnode(t, 0));  /* key index in hash table */\n        /* hash elements are numbered after array ones */\n        return i + t->sizearray;\n      }\n      else n = gnext(n);\n    } while (n);\n    luaG_runerror(L, \"invalid key to \" LUA_QL(\"next\"));  /* key not found */\n    return 0;  /* to avoid warnings */\n  }\n}\n\n\nint luaH_next (lua_State *L, Table *t, StkId key) {\n  int i = findindex(L, t, key);  /* find original element */\n  for (i++; i < t->sizearray; i++) {  /* try first array part */\n    if (!ttisnil(&t->array[i])) {  /* a non-nil value? */\n      setnvalue(key, cast_num(i+1));\n      setobj2s(L, key+1, &t->array[i]);\n      return 1;\n    }\n  }\n  for (i -= t->sizearray; i < sizenode(t); i++) {  /* then hash part */\n    if (!ttisnil(gval(gnode(t, i)))) {  /* a non-nil value? */\n      setobj2s(L, key, key2tval(gnode(t, i)));\n      setobj2s(L, key+1, gval(gnode(t, i)));\n      return 1;\n    }\n  }\n  return 0;  /* no more elements */\n}\n\n\n/*\n** {=============================================================\n** Rehash\n** ==============================================================\n*/\n\n\nstatic int computesizes (int nums[], int *narray) {\n  int i;\n  int twotoi;  /* 2^i */\n  int a = 0;  /* number of elements smaller than 2^i */\n  int na = 0;  /* number of elements to go to array part */\n  int n = 0;  /* optimal size for array part */\n  for (i = 0, twotoi = 1; twotoi/2 < *narray; i++, twotoi *= 2) {\n    if (nums[i] > 0) {\n      a += nums[i];\n      if (a > twotoi/2) {  /* more than half elements present? */\n        n = twotoi;  /* optimal size (till now) */\n        na = a;  /* all elements smaller than n will go to array part */\n      }\n    }\n    if (a == *narray) break;  /* all elements already counted */\n  }\n  *narray = n;\n  lua_assert(*narray/2 <= na && na <= *narray);\n  return na;\n}\n\n\nstatic int countint (const TValue *key, int *nums) {\n  int k = arrayindex(key);\n  if (0 < k && k <= MAXASIZE) {  /* is `key' an appropriate array index? */\n    nums[ceillog2(k)]++;  /* count as such */\n    return 1;\n  }\n  else\n    return 0;\n}\n\n\nstatic int numusearray (const Table *t, int *nums) {\n  int lg;\n  int ttlg;  /* 2^lg */\n  int ause = 0;  /* summation of `nums' */\n  int i = 1;  /* count to traverse all array keys */\n  for (lg=0, ttlg=1; lg<=MAXBITS; lg++, ttlg*=2) {  /* for each slice */\n    int lc = 0;  /* counter */\n    int lim = ttlg;\n    if (lim > t->sizearray) {\n      lim = t->sizearray;  /* adjust upper limit */\n      if (i > lim)\n        break;  /* no more elements to count */\n    }\n    /* count elements in range (2^(lg-1), 2^lg] */\n    for (; i <= lim; i++) {\n      if (!ttisnil(&t->array[i-1]))\n        lc++;\n    }\n    nums[lg] += lc;\n    ause += lc;\n  }\n  return ause;\n}\n\n\nstatic int numusehash (const Table *t, int *nums, int *pnasize) {\n  int totaluse = 0;  /* total number of elements */\n  int ause = 0;  /* summation of `nums' */\n  int i = sizenode(t);\n  while (i--) {\n    Node *n = &t->node[i];\n    if (!ttisnil(gval(n))) {\n      ause += countint(key2tval(n), nums);\n      totaluse++;\n    }\n  }\n  *pnasize += ause;\n  return totaluse;\n}\n\n\nstatic void setarrayvector (lua_State *L, Table *t, int size) {\n  int i;\n  luaM_reallocvector(L, t->array, t->sizearray, size, TValue);\n  for (i=t->sizearray; i<size; i++)\n     setnilvalue(&t->array[i]);\n  t->sizearray = size;\n}\n\n\nstatic void setnodevector (lua_State *L, Table *t, int size) {\n  int lsize;\n  if (size == 0) {  /* no elements to hash part? */\n    t->node = cast(Node *, dummynode);  /* use common `dummynode' */\n    lsize = 0;\n  }\n  else {\n    int i;\n    lsize = ceillog2(size);\n    if (lsize > MAXBITS)\n      luaG_runerror(L, \"table overflow\");\n    size = twoto(lsize);\n    t->node = luaM_newvector(L, size, Node);\n    for (i=0; i<size; i++) {\n      Node *n = gnode(t, i);\n      gnext(n) = NULL;\n      setnilvalue(gkey(n));\n      setnilvalue(gval(n));\n    }\n  }\n  t->lsizenode = cast_byte(lsize);\n  t->lastfree = gnode(t, size);  /* all positions are free */\n}\n\n\nstatic void resize (lua_State *L, Table *t, int nasize, int nhsize) {\n  int i;\n  int oldasize = t->sizearray;\n  int oldhsize = t->lsizenode;\n  Node *nold = t->node;  /* save old hash ... */\n  if (nasize > oldasize)  /* array part must grow? */\n    setarrayvector(L, t, nasize);\n  /* create new hash part with appropriate size */\n  setnodevector(L, t, nhsize);  \n  if (nasize < oldasize) {  /* array part must shrink? */\n    t->sizearray = nasize;\n    /* re-insert elements from vanishing slice */\n    for (i=nasize; i<oldasize; i++) {\n      if (!ttisnil(&t->array[i]))\n        setobjt2t(L, luaH_setnum(L, t, i+1), &t->array[i]);\n    }\n    /* shrink array */\n    luaM_reallocvector(L, t->array, oldasize, nasize, TValue);\n  }\n  /* re-insert elements from hash part */\n  for (i = twoto(oldhsize) - 1; i >= 0; i--) {\n    Node *old = nold+i;\n    if (!ttisnil(gval(old)))\n      setobjt2t(L, luaH_set(L, t, key2tval(old)), gval(old));\n  }\n  if (nold != dummynode)\n    luaM_freearray(L, nold, twoto(oldhsize), Node);  /* free old array */\n}\n\n\nvoid luaH_resizearray (lua_State *L, Table *t, int nasize) {\n  int nsize = (t->node == dummynode) ? 0 : sizenode(t);\n  resize(L, t, nasize, nsize);\n}\n\n\nstatic void rehash (lua_State *L, Table *t, const TValue *ek) {\n  int nasize, na;\n  int nums[MAXBITS+1];  /* nums[i] = number of keys between 2^(i-1) and 2^i */\n  int i;\n  int totaluse;\n  for (i=0; i<=MAXBITS; i++) nums[i] = 0;  /* reset counts */\n  nasize = numusearray(t, nums);  /* count keys in array part */\n  totaluse = nasize;  /* all those keys are integer keys */\n  totaluse += numusehash(t, nums, &nasize);  /* count keys in hash part */\n  /* count extra key */\n  nasize += countint(ek, nums);\n  totaluse++;\n  /* compute new size for array part */\n  na = computesizes(nums, &nasize);\n  /* resize the table to new computed sizes */\n  resize(L, t, nasize, totaluse - na);\n}\n\n\n\n/*\n** }=============================================================\n*/\n\n\nTable *luaH_new (lua_State *L, int narray, int nhash) {\n  Table *t = luaM_new(L, Table);\n  luaC_link(L, obj2gco(t), LUA_TTABLE);\n  t->metatable = NULL;\n  t->flags = cast_byte(~0);\n  /* temporary values (kept only if some malloc fails) */\n  t->array = NULL;\n  t->sizearray = 0;\n  t->lsizenode = 0;\n  t->node = cast(Node *, dummynode);\n  setarrayvector(L, t, narray);\n  setnodevector(L, t, nhash);\n  return t;\n}\n\n\nvoid luaH_free (lua_State *L, Table *t) {\n  if (t->node != dummynode)\n    luaM_freearray(L, t->node, sizenode(t), Node);\n  luaM_freearray(L, t->array, t->sizearray, TValue);\n  luaM_free(L, t);\n}\n\n\nstatic Node *getfreepos (Table *t) {\n  while (t->lastfree-- > t->node) {\n    if (ttisnil(gkey(t->lastfree)))\n      return t->lastfree;\n  }\n  return NULL;  /* could not find a free place */\n}\n\n\n\n/*\n** inserts a new key into a hash table; first, check whether key's main \n** position is free. If not, check whether colliding node is in its main \n** position or not: if it is not, move colliding node to an empty place and \n** put new key in its main position; otherwise (colliding node is in its main \n** position), new key goes to an empty position. \n*/\nstatic TValue *newkey (lua_State *L, Table *t, const TValue *key) {\n  Node *mp = mainposition(t, key);\n  if (!ttisnil(gval(mp)) || mp == dummynode) {\n    Node *othern;\n    Node *n = getfreepos(t);  /* get a free place */\n    if (n == NULL) {  /* cannot find a free place? */\n      rehash(L, t, key);  /* grow table */\n      return luaH_set(L, t, key);  /* re-insert key into grown table */\n    }\n    lua_assert(n != dummynode);\n    othern = mainposition(t, key2tval(mp));\n    if (othern != mp) {  /* is colliding node out of its main position? */\n      /* yes; move colliding node into free position */\n      while (gnext(othern) != mp) othern = gnext(othern);  /* find previous */\n      gnext(othern) = n;  /* redo the chain with `n' in place of `mp' */\n      *n = *mp;  /* copy colliding node into free pos. (mp->next also goes) */\n      gnext(mp) = NULL;  /* now `mp' is free */\n      setnilvalue(gval(mp));\n    }\n    else {  /* colliding node is in its own main position */\n      /* new node will go into free position */\n      gnext(n) = gnext(mp);  /* chain new position */\n      gnext(mp) = n;\n      mp = n;\n    }\n  }\n  gkey(mp)->value = key->value; gkey(mp)->tt = key->tt;\n  luaC_barriert(L, t, key);\n  lua_assert(ttisnil(gval(mp)));\n  return gval(mp);\n}\n\n\n/*\n** search function for integers\n*/\nconst TValue *luaH_getnum (Table *t, int key) {\n  /* (1 <= key && key <= t->sizearray) */\n  if (cast(unsigned int, key-1) < cast(unsigned int, t->sizearray))\n    return &t->array[key-1];\n  else {\n    lua_Number nk = cast_num(key);\n    Node *n = hashnum(t, nk);\n    do {  /* check whether `key' is somewhere in the chain */\n      if (ttisnumber(gkey(n)) && luai_numeq(nvalue(gkey(n)), nk))\n        return gval(n);  /* that's it */\n      else n = gnext(n);\n    } while (n);\n    return luaO_nilobject;\n  }\n}\n\n\n/*\n** search function for strings\n*/\nconst TValue *luaH_getstr (Table *t, TString *key) {\n  Node *n = hashstr(t, key);\n  do {  /* check whether `key' is somewhere in the chain */\n    if (ttisstring(gkey(n)) && rawtsvalue(gkey(n)) == key)\n      return gval(n);  /* that's it */\n    else n = gnext(n);\n  } while (n);\n  return luaO_nilobject;\n}\n\n\n/*\n** main search function\n*/\nconst TValue *luaH_get (Table *t, const TValue *key) {\n  switch (ttype(key)) {\n    case LUA_TNIL: return luaO_nilobject;\n    case LUA_TSTRING: return luaH_getstr(t, rawtsvalue(key));\n    case LUA_TNUMBER: {\n      int k;\n      lua_Number n = nvalue(key);\n      lua_number2int(k, n);\n      if (luai_numeq(cast_num(k), nvalue(key))) /* index is int? */\n        return luaH_getnum(t, k);  /* use specialized version */\n      /* else go through */\n    }\n    default: {\n      Node *n = mainposition(t, key);\n      do {  /* check whether `key' is somewhere in the chain */\n        if (luaO_rawequalObj(key2tval(n), key))\n          return gval(n);  /* that's it */\n        else n = gnext(n);\n      } while (n);\n      return luaO_nilobject;\n    }\n  }\n}\n\n\nTValue *luaH_set (lua_State *L, Table *t, const TValue *key) {\n  const TValue *p = luaH_get(t, key);\n  t->flags = 0;\n  if (p != luaO_nilobject)\n    return cast(TValue *, p);\n  else {\n    if (ttisnil(key)) luaG_runerror(L, \"table index is nil\");\n    else if (ttisnumber(key) && luai_numisnan(nvalue(key)))\n      luaG_runerror(L, \"table index is NaN\");\n    return newkey(L, t, key);\n  }\n}\n\n\nTValue *luaH_setnum (lua_State *L, Table *t, int key) {\n  const TValue *p = luaH_getnum(t, key);\n  if (p != luaO_nilobject)\n    return cast(TValue *, p);\n  else {\n    TValue k;\n    setnvalue(&k, cast_num(key));\n    return newkey(L, t, &k);\n  }\n}\n\n\nTValue *luaH_setstr (lua_State *L, Table *t, TString *key) {\n  const TValue *p = luaH_getstr(t, key);\n  if (p != luaO_nilobject)\n    return cast(TValue *, p);\n  else {\n    TValue k;\n    setsvalue(L, &k, key);\n    return newkey(L, t, &k);\n  }\n}\n\n\nstatic int unbound_search (Table *t, unsigned int j) {\n  unsigned int i = j;  /* i is zero or a present index */\n  j++;\n  /* find `i' and `j' such that i is present and j is not */\n  while (!ttisnil(luaH_getnum(t, j))) {\n    i = j;\n    j *= 2;\n    if (j > cast(unsigned int, MAX_INT)) {  /* overflow? */\n      /* table was built with bad purposes: resort to linear search */\n      i = 1;\n      while (!ttisnil(luaH_getnum(t, i))) i++;\n      return i - 1;\n    }\n  }\n  /* now do a binary search between them */\n  while (j - i > 1) {\n    unsigned int m = (i+j)/2;\n    if (ttisnil(luaH_getnum(t, m))) j = m;\n    else i = m;\n  }\n  return i;\n}\n\n\n/*\n** Try to find a boundary in table `t'. A `boundary' is an integer index\n** such that t[i] is non-nil and t[i+1] is nil (and 0 if t[1] is nil).\n*/\nint luaH_getn (Table *t) {\n  unsigned int j = t->sizearray;\n  if (j > 0 && ttisnil(&t->array[j - 1])) {\n    /* there is a boundary in the array part: (binary) search for it */\n    unsigned int i = 0;\n    while (j - i > 1) {\n      unsigned int m = (i+j)/2;\n      if (ttisnil(&t->array[m - 1])) j = m;\n      else i = m;\n    }\n    return i;\n  }\n  /* else must find a boundary in hash part */\n  else if (t->node == dummynode)  /* hash part is empty? */\n    return j;  /* that is easy... */\n  else return unbound_search(t, j);\n}\n\n\n\n#if defined(LUA_DEBUG)\n\nNode *luaH_mainposition (const Table *t, const TValue *key) {\n  return mainposition(t, key);\n}\n\nint luaH_isdummy (Node *n) { return n == dummynode; }\n\n#endif\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/deps/lua/src/ltable.h",
    "content": "/*\n** $Id: ltable.h,v 2.10.1.1 2007/12/27 13:02:25 roberto Exp $\n** Lua tables (hash)\n** See Copyright Notice in lua.h\n*/\n\n#ifndef ltable_h\n#define ltable_h\n\n#include \"lobject.h\"\n\n\n#define gnode(t,i)\t(&(t)->node[i])\n#define gkey(n)\t\t(&(n)->i_key.nk)\n#define gval(n)\t\t(&(n)->i_val)\n#define gnext(n)\t((n)->i_key.nk.next)\n\n#define key2tval(n)\t(&(n)->i_key.tvk)\n\n\nLUAI_FUNC const TValue *luaH_getnum (Table *t, int key);\nLUAI_FUNC TValue *luaH_setnum (lua_State *L, Table *t, int key);\nLUAI_FUNC const TValue *luaH_getstr (Table *t, TString *key);\nLUAI_FUNC TValue *luaH_setstr (lua_State *L, Table *t, TString *key);\nLUAI_FUNC const TValue *luaH_get (Table *t, const TValue *key);\nLUAI_FUNC TValue *luaH_set (lua_State *L, Table *t, const TValue *key);\nLUAI_FUNC Table *luaH_new (lua_State *L, int narray, int lnhash);\nLUAI_FUNC void luaH_resizearray (lua_State *L, Table *t, int nasize);\nLUAI_FUNC void luaH_free (lua_State *L, Table *t);\nLUAI_FUNC int luaH_next (lua_State *L, Table *t, StkId key);\nLUAI_FUNC int luaH_getn (Table *t);\n\n\n#if defined(LUA_DEBUG)\nLUAI_FUNC Node *luaH_mainposition (const Table *t, const TValue *key);\nLUAI_FUNC int luaH_isdummy (Node *n);\n#endif\n\n\n#endif\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/deps/lua/src/ltablib.c",
    "content": "/*\n** $Id: ltablib.c,v 1.38.1.3 2008/02/14 16:46:58 roberto Exp $\n** Library for Table Manipulation\n** See Copyright Notice in lua.h\n*/\n\n\n#include <stddef.h>\n\n#define ltablib_c\n#define LUA_LIB\n\n#include \"lua.h\"\n\n#include \"lauxlib.h\"\n#include \"lualib.h\"\n\n\n#define aux_getn(L,n)\t(luaL_checktype(L, n, LUA_TTABLE), luaL_getn(L, n))\n\n\nstatic int foreachi (lua_State *L) {\n  int i;\n  int n = aux_getn(L, 1);\n  luaL_checktype(L, 2, LUA_TFUNCTION);\n  for (i=1; i <= n; i++) {\n    lua_pushvalue(L, 2);  /* function */\n    lua_pushinteger(L, i);  /* 1st argument */\n    lua_rawgeti(L, 1, i);  /* 2nd argument */\n    lua_call(L, 2, 1);\n    if (!lua_isnil(L, -1))\n      return 1;\n    lua_pop(L, 1);  /* remove nil result */\n  }\n  return 0;\n}\n\n\nstatic int foreach (lua_State *L) {\n  luaL_checktype(L, 1, LUA_TTABLE);\n  luaL_checktype(L, 2, LUA_TFUNCTION);\n  lua_pushnil(L);  /* first key */\n  while (lua_next(L, 1)) {\n    lua_pushvalue(L, 2);  /* function */\n    lua_pushvalue(L, -3);  /* key */\n    lua_pushvalue(L, -3);  /* value */\n    lua_call(L, 2, 1);\n    if (!lua_isnil(L, -1))\n      return 1;\n    lua_pop(L, 2);  /* remove value and result */\n  }\n  return 0;\n}\n\n\nstatic int maxn (lua_State *L) {\n  lua_Number max = 0;\n  luaL_checktype(L, 1, LUA_TTABLE);\n  lua_pushnil(L);  /* first key */\n  while (lua_next(L, 1)) {\n    lua_pop(L, 1);  /* remove value */\n    if (lua_type(L, -1) == LUA_TNUMBER) {\n      lua_Number v = lua_tonumber(L, -1);\n      if (v > max) max = v;\n    }\n  }\n  lua_pushnumber(L, max);\n  return 1;\n}\n\n\nstatic int getn (lua_State *L) {\n  lua_pushinteger(L, aux_getn(L, 1));\n  return 1;\n}\n\n\nstatic int setn (lua_State *L) {\n  luaL_checktype(L, 1, LUA_TTABLE);\n#ifndef luaL_setn\n  luaL_setn(L, 1, luaL_checkint(L, 2));\n#else\n  luaL_error(L, LUA_QL(\"setn\") \" is obsolete\");\n#endif\n  lua_pushvalue(L, 1);\n  return 1;\n}\n\n\nstatic int tinsert (lua_State *L) {\n  int e = aux_getn(L, 1) + 1;  /* first empty element */\n  int pos;  /* where to insert new element */\n  switch (lua_gettop(L)) {\n    case 2: {  /* called with only 2 arguments */\n      pos = e;  /* insert new element at the end */\n      break;\n    }\n    case 3: {\n      int i;\n      pos = luaL_checkint(L, 2);  /* 2nd argument is the position */\n      if (pos > e) e = pos;  /* `grow' array if necessary */\n      for (i = e; i > pos; i--) {  /* move up elements */\n        lua_rawgeti(L, 1, i-1);\n        lua_rawseti(L, 1, i);  /* t[i] = t[i-1] */\n      }\n      break;\n    }\n    default: {\n      return luaL_error(L, \"wrong number of arguments to \" LUA_QL(\"insert\"));\n    }\n  }\n  luaL_setn(L, 1, e);  /* new size */\n  lua_rawseti(L, 1, pos);  /* t[pos] = v */\n  return 0;\n}\n\n\nstatic int tremove (lua_State *L) {\n  int e = aux_getn(L, 1);\n  int pos = luaL_optint(L, 2, e);\n  if (!(1 <= pos && pos <= e))  /* position is outside bounds? */\n   return 0;  /* nothing to remove */\n  luaL_setn(L, 1, e - 1);  /* t.n = n-1 */\n  lua_rawgeti(L, 1, pos);  /* result = t[pos] */\n  for ( ;pos<e; pos++) {\n    lua_rawgeti(L, 1, pos+1);\n    lua_rawseti(L, 1, pos);  /* t[pos] = t[pos+1] */\n  }\n  lua_pushnil(L);\n  lua_rawseti(L, 1, e);  /* t[e] = nil */\n  return 1;\n}\n\n\nstatic void addfield (lua_State *L, luaL_Buffer *b, int i) {\n  lua_rawgeti(L, 1, i);\n  if (!lua_isstring(L, -1))\n    luaL_error(L, \"invalid value (%s) at index %d in table for \"\n                  LUA_QL(\"concat\"), luaL_typename(L, -1), i);\n    luaL_addvalue(b);\n}\n\n\nstatic int tconcat (lua_State *L) {\n  luaL_Buffer b;\n  size_t lsep;\n  int i, last;\n  const char *sep = luaL_optlstring(L, 2, \"\", &lsep);\n  luaL_checktype(L, 1, LUA_TTABLE);\n  i = luaL_optint(L, 3, 1);\n  last = luaL_opt(L, luaL_checkint, 4, luaL_getn(L, 1));\n  luaL_buffinit(L, &b);\n  for (; i < last; i++) {\n    addfield(L, &b, i);\n    luaL_addlstring(&b, sep, lsep);\n  }\n  if (i == last)  /* add last value (if interval was not empty) */\n    addfield(L, &b, i);\n  luaL_pushresult(&b);\n  return 1;\n}\n\n\n\n/*\n** {======================================================\n** Quicksort\n** (based on `Algorithms in MODULA-3', Robert Sedgewick;\n**  Addison-Wesley, 1993.)\n*/\n\n\nstatic void set2 (lua_State *L, int i, int j) {\n  lua_rawseti(L, 1, i);\n  lua_rawseti(L, 1, j);\n}\n\nstatic int sort_comp (lua_State *L, int a, int b) {\n  if (!lua_isnil(L, 2)) {  /* function? */\n    int res;\n    lua_pushvalue(L, 2);\n    lua_pushvalue(L, a-1);  /* -1 to compensate function */\n    lua_pushvalue(L, b-2);  /* -2 to compensate function and `a' */\n    lua_call(L, 2, 1);\n    res = lua_toboolean(L, -1);\n    lua_pop(L, 1);\n    return res;\n  }\n  else  /* a < b? */\n    return lua_lessthan(L, a, b);\n}\n\nstatic void auxsort (lua_State *L, int l, int u) {\n  while (l < u) {  /* for tail recursion */\n    int i, j;\n    /* sort elements a[l], a[(l+u)/2] and a[u] */\n    lua_rawgeti(L, 1, l);\n    lua_rawgeti(L, 1, u);\n    if (sort_comp(L, -1, -2))  /* a[u] < a[l]? */\n      set2(L, l, u);  /* swap a[l] - a[u] */\n    else\n      lua_pop(L, 2);\n    if (u-l == 1) break;  /* only 2 elements */\n    i = (l+u)/2;\n    lua_rawgeti(L, 1, i);\n    lua_rawgeti(L, 1, l);\n    if (sort_comp(L, -2, -1))  /* a[i]<a[l]? */\n      set2(L, i, l);\n    else {\n      lua_pop(L, 1);  /* remove a[l] */\n      lua_rawgeti(L, 1, u);\n      if (sort_comp(L, -1, -2))  /* a[u]<a[i]? */\n        set2(L, i, u);\n      else\n        lua_pop(L, 2);\n    }\n    if (u-l == 2) break;  /* only 3 elements */\n    lua_rawgeti(L, 1, i);  /* Pivot */\n    lua_pushvalue(L, -1);\n    lua_rawgeti(L, 1, u-1);\n    set2(L, i, u-1);\n    /* a[l] <= P == a[u-1] <= a[u], only need to sort from l+1 to u-2 */\n    i = l; j = u-1;\n    for (;;) {  /* invariant: a[l..i] <= P <= a[j..u] */\n      /* repeat ++i until a[i] >= P */\n      while (lua_rawgeti(L, 1, ++i), sort_comp(L, -1, -2)) {\n        if (i>u) luaL_error(L, \"invalid order function for sorting\");\n        lua_pop(L, 1);  /* remove a[i] */\n      }\n      /* repeat --j until a[j] <= P */\n      while (lua_rawgeti(L, 1, --j), sort_comp(L, -3, -1)) {\n        if (j<l) luaL_error(L, \"invalid order function for sorting\");\n        lua_pop(L, 1);  /* remove a[j] */\n      }\n      if (j<i) {\n        lua_pop(L, 3);  /* pop pivot, a[i], a[j] */\n        break;\n      }\n      set2(L, i, j);\n    }\n    lua_rawgeti(L, 1, u-1);\n    lua_rawgeti(L, 1, i);\n    set2(L, u-1, i);  /* swap pivot (a[u-1]) with a[i] */\n    /* a[l..i-1] <= a[i] == P <= a[i+1..u] */\n    /* adjust so that smaller half is in [j..i] and larger one in [l..u] */\n    if (i-l < u-i) {\n      j=l; i=i-1; l=i+2;\n    }\n    else {\n      j=i+1; i=u; u=j-2;\n    }\n    auxsort(L, j, i);  /* call recursively the smaller one */\n  }  /* repeat the routine for the larger one */\n}\n\nstatic int sort (lua_State *L) {\n  int n = aux_getn(L, 1);\n  luaL_checkstack(L, 40, \"\");  /* assume array is smaller than 2^40 */\n  if (!lua_isnoneornil(L, 2))  /* is there a 2nd argument? */\n    luaL_checktype(L, 2, LUA_TFUNCTION);\n  lua_settop(L, 2);  /* make sure there is two arguments */\n  auxsort(L, 1, n);\n  return 0;\n}\n\n/* }====================================================== */\n\n\nstatic const luaL_Reg tab_funcs[] = {\n  {\"concat\", tconcat},\n  {\"foreach\", foreach},\n  {\"foreachi\", foreachi},\n  {\"getn\", getn},\n  {\"maxn\", maxn},\n  {\"insert\", tinsert},\n  {\"remove\", tremove},\n  {\"setn\", setn},\n  {\"sort\", sort},\n  {NULL, NULL}\n};\n\n\nLUALIB_API int luaopen_table (lua_State *L) {\n  luaL_register(L, LUA_TABLIBNAME, tab_funcs);\n  return 1;\n}\n\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/deps/lua/src/ltm.c",
    "content": "/*\n** $Id: ltm.c,v 2.8.1.1 2007/12/27 13:02:25 roberto Exp $\n** Tag methods\n** See Copyright Notice in lua.h\n*/\n\n\n#include <string.h>\n\n#define ltm_c\n#define LUA_CORE\n\n#include \"lua.h\"\n\n#include \"lobject.h\"\n#include \"lstate.h\"\n#include \"lstring.h\"\n#include \"ltable.h\"\n#include \"ltm.h\"\n\n\n\nconst char *const luaT_typenames[] = {\n  \"nil\", \"boolean\", \"userdata\", \"number\",\n  \"string\", \"table\", \"function\", \"userdata\", \"thread\",\n  \"proto\", \"upval\"\n};\n\n\nvoid luaT_init (lua_State *L) {\n  static const char *const luaT_eventname[] = {  /* ORDER TM */\n    \"__index\", \"__newindex\",\n    \"__gc\", \"__mode\", \"__eq\",\n    \"__add\", \"__sub\", \"__mul\", \"__div\", \"__mod\",\n    \"__pow\", \"__unm\", \"__len\", \"__lt\", \"__le\",\n    \"__concat\", \"__call\"\n  };\n  int i;\n  for (i=0; i<TM_N; i++) {\n    G(L)->tmname[i] = luaS_new(L, luaT_eventname[i]);\n    luaS_fix(G(L)->tmname[i]);  /* never collect these names */\n  }\n}\n\n\n/*\n** function to be used with macro \"fasttm\": optimized for absence of\n** tag methods\n*/\nconst TValue *luaT_gettm (Table *events, TMS event, TString *ename) {\n  const TValue *tm = luaH_getstr(events, ename);\n  lua_assert(event <= TM_EQ);\n  if (ttisnil(tm)) {  /* no tag method? */\n    events->flags |= cast_byte(1u<<event);  /* cache this fact */\n    return NULL;\n  }\n  else return tm;\n}\n\n\nconst TValue *luaT_gettmbyobj (lua_State *L, const TValue *o, TMS event) {\n  Table *mt;\n  switch (ttype(o)) {\n    case LUA_TTABLE:\n      mt = hvalue(o)->metatable;\n      break;\n    case LUA_TUSERDATA:\n      mt = uvalue(o)->metatable;\n      break;\n    default:\n      mt = G(L)->mt[ttype(o)];\n  }\n  return (mt ? luaH_getstr(mt, G(L)->tmname[event]) : luaO_nilobject);\n}\n\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/deps/lua/src/ltm.h",
    "content": "/*\n** $Id: ltm.h,v 2.6.1.1 2007/12/27 13:02:25 roberto Exp $\n** Tag methods\n** See Copyright Notice in lua.h\n*/\n\n#ifndef ltm_h\n#define ltm_h\n\n\n#include \"lobject.h\"\n\n\n/*\n* WARNING: if you change the order of this enumeration,\n* grep \"ORDER TM\"\n*/\ntypedef enum {\n  TM_INDEX,\n  TM_NEWINDEX,\n  TM_GC,\n  TM_MODE,\n  TM_EQ,  /* last tag method with `fast' access */\n  TM_ADD,\n  TM_SUB,\n  TM_MUL,\n  TM_DIV,\n  TM_MOD,\n  TM_POW,\n  TM_UNM,\n  TM_LEN,\n  TM_LT,\n  TM_LE,\n  TM_CONCAT,\n  TM_CALL,\n  TM_N\t\t/* number of elements in the enum */\n} TMS;\n\n\n\n#define gfasttm(g,et,e) ((et) == NULL ? NULL : \\\n  ((et)->flags & (1u<<(e))) ? NULL : luaT_gettm(et, e, (g)->tmname[e]))\n\n#define fasttm(l,et,e)\tgfasttm(G(l), et, e)\n\nLUAI_DATA const char *const luaT_typenames[];\n\n\nLUAI_FUNC const TValue *luaT_gettm (Table *events, TMS event, TString *ename);\nLUAI_FUNC const TValue *luaT_gettmbyobj (lua_State *L, const TValue *o,\n                                                       TMS event);\nLUAI_FUNC void luaT_init (lua_State *L);\n\n#endif\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/deps/lua/src/lua.c",
    "content": "/*\n** $Id: lua.c,v 1.160.1.2 2007/12/28 15:32:23 roberto Exp $\n** Lua stand-alone interpreter\n** See Copyright Notice in lua.h\n*/\n\n\n#include <signal.h>\n#include <stdio.h>\n#include <stdlib.h>\n#include <string.h>\n\n#define lua_c\n\n#include \"lua.h\"\n\n#include \"lauxlib.h\"\n#include \"lualib.h\"\n\n\n\nstatic lua_State *globalL = NULL;\n\nstatic const char *progname = LUA_PROGNAME;\n\n\n\nstatic void lstop (lua_State *L, lua_Debug *ar) {\n  (void)ar;  /* unused arg. */\n  lua_sethook(L, NULL, 0, 0);\n  luaL_error(L, \"interrupted!\");\n}\n\n\nstatic void laction (int i) {\n  signal(i, SIG_DFL); /* if another SIGINT happens before lstop,\n                              terminate process (default action) */\n  lua_sethook(globalL, lstop, LUA_MASKCALL | LUA_MASKRET | LUA_MASKCOUNT, 1);\n}\n\n\nstatic void print_usage (void) {\n  fprintf(stderr,\n  \"usage: %s [options] [script [args]].\\n\"\n  \"Available options are:\\n\"\n  \"  -e stat  execute string \" LUA_QL(\"stat\") \"\\n\"\n  \"  -l name  require library \" LUA_QL(\"name\") \"\\n\"\n  \"  -i       enter interactive mode after executing \" LUA_QL(\"script\") \"\\n\"\n  \"  -v       show version information\\n\"\n  \"  --       stop handling options\\n\"\n  \"  -        execute stdin and stop handling options\\n\"\n  ,\n  progname);\n  fflush(stderr);\n}\n\n\nstatic void l_message (const char *pname, const char *msg) {\n  if (pname) fprintf(stderr, \"%s: \", pname);\n  fprintf(stderr, \"%s\\n\", msg);\n  fflush(stderr);\n}\n\n\nstatic int report (lua_State *L, int status) {\n  if (status && !lua_isnil(L, -1)) {\n    const char *msg = lua_tostring(L, -1);\n    if (msg == NULL) msg = \"(error object is not a string)\";\n    l_message(progname, msg);\n    lua_pop(L, 1);\n  }\n  return status;\n}\n\n\nstatic int traceback (lua_State *L) {\n  if (!lua_isstring(L, 1))  /* 'message' not a string? */\n    return 1;  /* keep it intact */\n  lua_getfield(L, LUA_GLOBALSINDEX, \"debug\");\n  if (!lua_istable(L, -1)) {\n    lua_pop(L, 1);\n    return 1;\n  }\n  lua_getfield(L, -1, \"traceback\");\n  if (!lua_isfunction(L, -1)) {\n    lua_pop(L, 2);\n    return 1;\n  }\n  lua_pushvalue(L, 1);  /* pass error message */\n  lua_pushinteger(L, 2);  /* skip this function and traceback */\n  lua_call(L, 2, 1);  /* call debug.traceback */\n  return 1;\n}\n\n\nstatic int docall (lua_State *L, int narg, int clear) {\n  int status;\n  int base = lua_gettop(L) - narg;  /* function index */\n  lua_pushcfunction(L, traceback);  /* push traceback function */\n  lua_insert(L, base);  /* put it under chunk and args */\n  signal(SIGINT, laction);\n  status = lua_pcall(L, narg, (clear ? 0 : LUA_MULTRET), base);\n  signal(SIGINT, SIG_DFL);\n  lua_remove(L, base);  /* remove traceback function */\n  /* force a complete garbage collection in case of errors */\n  if (status != 0) lua_gc(L, LUA_GCCOLLECT, 0);\n  return status;\n}\n\n\nstatic void print_version (void) {\n  l_message(NULL, LUA_RELEASE \"  \" LUA_COPYRIGHT);\n}\n\n\nstatic int getargs (lua_State *L, char **argv, int n) {\n  int narg;\n  int i;\n  int argc = 0;\n  while (argv[argc]) argc++;  /* count total number of arguments */\n  narg = argc - (n + 1);  /* number of arguments to the script */\n  luaL_checkstack(L, narg + 3, \"too many arguments to script\");\n  for (i=n+1; i < argc; i++)\n    lua_pushstring(L, argv[i]);\n  lua_createtable(L, narg, n + 1);\n  for (i=0; i < argc; i++) {\n    lua_pushstring(L, argv[i]);\n    lua_rawseti(L, -2, i - n);\n  }\n  return narg;\n}\n\n\nstatic int dofile (lua_State *L, const char *name) {\n  int status = luaL_loadfile(L, name) || docall(L, 0, 1);\n  return report(L, status);\n}\n\n\nstatic int dostring (lua_State *L, const char *s, const char *name) {\n  int status = luaL_loadbuffer(L, s, strlen(s), name) || docall(L, 0, 1);\n  return report(L, status);\n}\n\n\nstatic int dolibrary (lua_State *L, const char *name) {\n  lua_getglobal(L, \"require\");\n  lua_pushstring(L, name);\n  return report(L, docall(L, 1, 1));\n}\n\n\nstatic const char *get_prompt (lua_State *L, int firstline) {\n  const char *p;\n  lua_getfield(L, LUA_GLOBALSINDEX, firstline ? \"_PROMPT\" : \"_PROMPT2\");\n  p = lua_tostring(L, -1);\n  if (p == NULL) p = (firstline ? LUA_PROMPT : LUA_PROMPT2);\n  lua_pop(L, 1);  /* remove global */\n  return p;\n}\n\n\nstatic int incomplete (lua_State *L, int status) {\n  if (status == LUA_ERRSYNTAX) {\n    size_t lmsg;\n    const char *msg = lua_tolstring(L, -1, &lmsg);\n    const char *tp = msg + lmsg - (sizeof(LUA_QL(\"<eof>\")) - 1);\n    if (strstr(msg, LUA_QL(\"<eof>\")) == tp) {\n      lua_pop(L, 1);\n      return 1;\n    }\n  }\n  return 0;  /* else... */\n}\n\n\nstatic int pushline (lua_State *L, int firstline) {\n  char buffer[LUA_MAXINPUT];\n  char *b = buffer;\n  size_t l;\n  const char *prmt = get_prompt(L, firstline);\n  if (lua_readline(L, b, prmt) == 0)\n    return 0;  /* no input */\n  l = strlen(b);\n  if (l > 0 && b[l-1] == '\\n')  /* line ends with newline? */\n    b[l-1] = '\\0';  /* remove it */\n  if (firstline && b[0] == '=')  /* first line starts with `=' ? */\n    lua_pushfstring(L, \"return %s\", b+1);  /* change it to `return' */\n  else\n    lua_pushstring(L, b);\n  lua_freeline(L, b);\n  return 1;\n}\n\n\nstatic int loadline (lua_State *L) {\n  int status;\n  lua_settop(L, 0);\n  if (!pushline(L, 1))\n    return -1;  /* no input */\n  for (;;) {  /* repeat until gets a complete line */\n    status = luaL_loadbuffer(L, lua_tostring(L, 1), lua_strlen(L, 1), \"=stdin\");\n    if (!incomplete(L, status)) break;  /* cannot try to add lines? */\n    if (!pushline(L, 0))  /* no more input? */\n      return -1;\n    lua_pushliteral(L, \"\\n\");  /* add a new line... */\n    lua_insert(L, -2);  /* ...between the two lines */\n    lua_concat(L, 3);  /* join them */\n  }\n  lua_saveline(L, 1);\n  lua_remove(L, 1);  /* remove line */\n  return status;\n}\n\n\nstatic void dotty (lua_State *L) {\n  int status;\n  const char *oldprogname = progname;\n  progname = NULL;\n  while ((status = loadline(L)) != -1) {\n    if (status == 0) status = docall(L, 0, 0);\n    report(L, status);\n    if (status == 0 && lua_gettop(L) > 0) {  /* any result to print? */\n      lua_getglobal(L, \"print\");\n      lua_insert(L, 1);\n      if (lua_pcall(L, lua_gettop(L)-1, 0, 0) != 0)\n        l_message(progname, lua_pushfstring(L,\n                               \"error calling \" LUA_QL(\"print\") \" (%s)\",\n                               lua_tostring(L, -1)));\n    }\n  }\n  lua_settop(L, 0);  /* clear stack */\n  fputs(\"\\n\", stdout);\n  fflush(stdout);\n  progname = oldprogname;\n}\n\n\nstatic int handle_script (lua_State *L, char **argv, int n) {\n  int status;\n  const char *fname;\n  int narg = getargs(L, argv, n);  /* collect arguments */\n  lua_setglobal(L, \"arg\");\n  fname = argv[n];\n  if (strcmp(fname, \"-\") == 0 && strcmp(argv[n-1], \"--\") != 0) \n    fname = NULL;  /* stdin */\n  status = luaL_loadfile(L, fname);\n  lua_insert(L, -(narg+1));\n  if (status == 0)\n    status = docall(L, narg, 0);\n  else\n    lua_pop(L, narg);      \n  return report(L, status);\n}\n\n\n/* check that argument has no extra characters at the end */\n#define notail(x)\t{if ((x)[2] != '\\0') return -1;}\n\n\nstatic int collectargs (char **argv, int *pi, int *pv, int *pe) {\n  int i;\n  for (i = 1; argv[i] != NULL; i++) {\n    if (argv[i][0] != '-')  /* not an option? */\n        return i;\n    switch (argv[i][1]) {  /* option */\n      case '-':\n        notail(argv[i]);\n        return (argv[i+1] != NULL ? i+1 : 0);\n      case '\\0':\n        return i;\n      case 'i':\n        notail(argv[i]);\n        *pi = 1;  /* go through */\n      case 'v':\n        notail(argv[i]);\n        *pv = 1;\n        break;\n      case 'e':\n        *pe = 1;  /* go through */\n      case 'l':\n        if (argv[i][2] == '\\0') {\n          i++;\n          if (argv[i] == NULL) return -1;\n        }\n        break;\n      default: return -1;  /* invalid option */\n    }\n  }\n  return 0;\n}\n\n\nstatic int runargs (lua_State *L, char **argv, int n) {\n  int i;\n  for (i = 1; i < n; i++) {\n    if (argv[i] == NULL) continue;\n    lua_assert(argv[i][0] == '-');\n    switch (argv[i][1]) {  /* option */\n      case 'e': {\n        const char *chunk = argv[i] + 2;\n        if (*chunk == '\\0') chunk = argv[++i];\n        lua_assert(chunk != NULL);\n        if (dostring(L, chunk, \"=(command line)\") != 0)\n          return 1;\n        break;\n      }\n      case 'l': {\n        const char *filename = argv[i] + 2;\n        if (*filename == '\\0') filename = argv[++i];\n        lua_assert(filename != NULL);\n        if (dolibrary(L, filename))\n          return 1;  /* stop if file fails */\n        break;\n      }\n      default: break;\n    }\n  }\n  return 0;\n}\n\n\nstatic int handle_luainit (lua_State *L) {\n  const char *init = getenv(LUA_INIT);\n  if (init == NULL) return 0;  /* status OK */\n  else if (init[0] == '@')\n    return dofile(L, init+1);\n  else\n    return dostring(L, init, \"=\" LUA_INIT);\n}\n\n\nstruct Smain {\n  int argc;\n  char **argv;\n  int status;\n};\n\n\nstatic int pmain (lua_State *L) {\n  struct Smain *s = (struct Smain *)lua_touserdata(L, 1);\n  char **argv = s->argv;\n  int script;\n  int has_i = 0, has_v = 0, has_e = 0;\n  globalL = L;\n  if (argv[0] && argv[0][0]) progname = argv[0];\n  lua_gc(L, LUA_GCSTOP, 0);  /* stop collector during initialization */\n  luaL_openlibs(L);  /* open libraries */\n  lua_gc(L, LUA_GCRESTART, 0);\n  s->status = handle_luainit(L);\n  if (s->status != 0) return 0;\n  script = collectargs(argv, &has_i, &has_v, &has_e);\n  if (script < 0) {  /* invalid args? */\n    print_usage();\n    s->status = 1;\n    return 0;\n  }\n  if (has_v) print_version();\n  s->status = runargs(L, argv, (script > 0) ? script : s->argc);\n  if (s->status != 0) return 0;\n  if (script)\n    s->status = handle_script(L, argv, script);\n  if (s->status != 0) return 0;\n  if (has_i)\n    dotty(L);\n  else if (script == 0 && !has_e && !has_v) {\n    if (lua_stdin_is_tty()) {\n      print_version();\n      dotty(L);\n    }\n    else dofile(L, NULL);  /* executes stdin as a file */\n  }\n  return 0;\n}\n\n\nint main (int argc, char **argv) {\n  int status;\n  struct Smain s;\n  lua_State *L = lua_open();  /* create state */\n  if (L == NULL) {\n    l_message(argv[0], \"cannot create state: not enough memory\");\n    return EXIT_FAILURE;\n  }\n  s.argc = argc;\n  s.argv = argv;\n  status = lua_cpcall(L, &pmain, &s);\n  report(L, status);\n  lua_close(L);\n  return (status || s.status) ? EXIT_FAILURE : EXIT_SUCCESS;\n}\n\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/deps/lua/src/lua.h",
    "content": "/*\n** $Id: lua.h,v 1.218.1.7 2012/01/13 20:36:20 roberto Exp $\n** Lua - An Extensible Extension Language\n** Lua.org, PUC-Rio, Brazil (http://www.lua.org)\n** See Copyright Notice at the end of this file\n*/\n\n\n#ifndef lua_h\n#define lua_h\n\n#include <stdarg.h>\n#include <stddef.h>\n\n\n#include \"luaconf.h\"\n\n\n#define LUA_VERSION\t\"Lua 5.1\"\n#define LUA_RELEASE\t\"Lua 5.1.5\"\n#define LUA_VERSION_NUM\t501\n#define LUA_COPYRIGHT\t\"Copyright (C) 1994-2012 Lua.org, PUC-Rio\"\n#define LUA_AUTHORS \t\"R. Ierusalimschy, L. H. de Figueiredo & W. Celes\"\n\n\n/* mark for precompiled code (`<esc>Lua') */\n#define\tLUA_SIGNATURE\t\"\\033Lua\"\n\n/* option for multiple returns in `lua_pcall' and `lua_call' */\n#define LUA_MULTRET\t(-1)\n\n\n/*\n** pseudo-indices\n*/\n#define LUA_REGISTRYINDEX\t(-10000)\n#define LUA_ENVIRONINDEX\t(-10001)\n#define LUA_GLOBALSINDEX\t(-10002)\n#define lua_upvalueindex(i)\t(LUA_GLOBALSINDEX-(i))\n\n\n/* thread status; 0 is OK */\n#define LUA_YIELD\t1\n#define LUA_ERRRUN\t2\n#define LUA_ERRSYNTAX\t3\n#define LUA_ERRMEM\t4\n#define LUA_ERRERR\t5\n\n\ntypedef struct lua_State lua_State;\n\ntypedef int (*lua_CFunction) (lua_State *L);\n\n\n/*\n** functions that read/write blocks when loading/dumping Lua chunks\n*/\ntypedef const char * (*lua_Reader) (lua_State *L, void *ud, size_t *sz);\n\ntypedef int (*lua_Writer) (lua_State *L, const void* p, size_t sz, void* ud);\n\n\n/*\n** prototype for memory-allocation functions\n*/\ntypedef void * (*lua_Alloc) (void *ud, void *ptr, size_t osize, size_t nsize);\n\n\n/*\n** basic types\n*/\n#define LUA_TNONE\t\t(-1)\n\n#define LUA_TNIL\t\t0\n#define LUA_TBOOLEAN\t\t1\n#define LUA_TLIGHTUSERDATA\t2\n#define LUA_TNUMBER\t\t3\n#define LUA_TSTRING\t\t4\n#define LUA_TTABLE\t\t5\n#define LUA_TFUNCTION\t\t6\n#define LUA_TUSERDATA\t\t7\n#define LUA_TTHREAD\t\t8\n\n\n\n/* minimum Lua stack available to a C function */\n#define LUA_MINSTACK\t20\n\n\n/*\n** generic extra include file\n*/\n#if defined(LUA_USER_H)\n#include LUA_USER_H\n#endif\n\n\n/* type of numbers in Lua */\ntypedef LUA_NUMBER lua_Number;\n\n\n/* type for integer functions */\ntypedef LUA_INTEGER lua_Integer;\n\n\n\n/*\n** state manipulation\n*/\nLUA_API lua_State *(lua_newstate) (lua_Alloc f, void *ud);\nLUA_API void       (lua_close) (lua_State *L);\nLUA_API lua_State *(lua_newthread) (lua_State *L);\n\nLUA_API lua_CFunction (lua_atpanic) (lua_State *L, lua_CFunction panicf);\n\n\n/*\n** basic stack manipulation\n*/\nLUA_API int   (lua_gettop) (lua_State *L);\nLUA_API void  (lua_settop) (lua_State *L, int idx);\nLUA_API void  (lua_pushvalue) (lua_State *L, int idx);\nLUA_API void  (lua_remove) (lua_State *L, int idx);\nLUA_API void  (lua_insert) (lua_State *L, int idx);\nLUA_API void  (lua_replace) (lua_State *L, int idx);\nLUA_API int   (lua_checkstack) (lua_State *L, int sz);\n\nLUA_API void  (lua_xmove) (lua_State *from, lua_State *to, int n);\n\n\n/*\n** access functions (stack -> C)\n*/\n\nLUA_API int             (lua_isnumber) (lua_State *L, int idx);\nLUA_API int             (lua_isstring) (lua_State *L, int idx);\nLUA_API int             (lua_iscfunction) (lua_State *L, int idx);\nLUA_API int             (lua_isuserdata) (lua_State *L, int idx);\nLUA_API int             (lua_type) (lua_State *L, int idx);\nLUA_API const char     *(lua_typename) (lua_State *L, int tp);\n\nLUA_API int            (lua_equal) (lua_State *L, int idx1, int idx2);\nLUA_API int            (lua_rawequal) (lua_State *L, int idx1, int idx2);\nLUA_API int            (lua_lessthan) (lua_State *L, int idx1, int idx2);\n\nLUA_API lua_Number      (lua_tonumber) (lua_State *L, int idx);\nLUA_API lua_Integer     (lua_tointeger) (lua_State *L, int idx);\nLUA_API int             (lua_toboolean) (lua_State *L, int idx);\nLUA_API const char     *(lua_tolstring) (lua_State *L, int idx, size_t *len);\nLUA_API size_t          (lua_objlen) (lua_State *L, int idx);\nLUA_API lua_CFunction   (lua_tocfunction) (lua_State *L, int idx);\nLUA_API void\t       *(lua_touserdata) (lua_State *L, int idx);\nLUA_API lua_State      *(lua_tothread) (lua_State *L, int idx);\nLUA_API const void     *(lua_topointer) (lua_State *L, int idx);\n\n\n/*\n** push functions (C -> stack)\n*/\nLUA_API void  (lua_pushnil) (lua_State *L);\nLUA_API void  (lua_pushnumber) (lua_State *L, lua_Number n);\nLUA_API void  (lua_pushinteger) (lua_State *L, lua_Integer n);\nLUA_API void  (lua_pushlstring) (lua_State *L, const char *s, size_t l);\nLUA_API void  (lua_pushstring) (lua_State *L, const char *s);\nLUA_API const char *(lua_pushvfstring) (lua_State *L, const char *fmt,\n                                                      va_list argp);\nLUA_API const char *(lua_pushfstring) (lua_State *L, const char *fmt, ...);\nLUA_API void  (lua_pushcclosure) (lua_State *L, lua_CFunction fn, int n);\nLUA_API void  (lua_pushboolean) (lua_State *L, int b);\nLUA_API void  (lua_pushlightuserdata) (lua_State *L, void *p);\nLUA_API int   (lua_pushthread) (lua_State *L);\n\n\n/*\n** get functions (Lua -> stack)\n*/\nLUA_API void  (lua_gettable) (lua_State *L, int idx);\nLUA_API void  (lua_getfield) (lua_State *L, int idx, const char *k);\nLUA_API void  (lua_rawget) (lua_State *L, int idx);\nLUA_API void  (lua_rawgeti) (lua_State *L, int idx, int n);\nLUA_API void  (lua_createtable) (lua_State *L, int narr, int nrec);\nLUA_API void *(lua_newuserdata) (lua_State *L, size_t sz);\nLUA_API int   (lua_getmetatable) (lua_State *L, int objindex);\nLUA_API void  (lua_getfenv) (lua_State *L, int idx);\n\n\n/*\n** set functions (stack -> Lua)\n*/\nLUA_API void  (lua_settable) (lua_State *L, int idx);\nLUA_API void  (lua_setfield) (lua_State *L, int idx, const char *k);\nLUA_API void  (lua_rawset) (lua_State *L, int idx);\nLUA_API void  (lua_rawseti) (lua_State *L, int idx, int n);\nLUA_API int   (lua_setmetatable) (lua_State *L, int objindex);\nLUA_API int   (lua_setfenv) (lua_State *L, int idx);\n\n\n/*\n** `load' and `call' functions (load and run Lua code)\n*/\nLUA_API void  (lua_call) (lua_State *L, int nargs, int nresults);\nLUA_API int   (lua_pcall) (lua_State *L, int nargs, int nresults, int errfunc);\nLUA_API int   (lua_cpcall) (lua_State *L, lua_CFunction func, void *ud);\nLUA_API int   (lua_load) (lua_State *L, lua_Reader reader, void *dt,\n                                        const char *chunkname);\n\nLUA_API int (lua_dump) (lua_State *L, lua_Writer writer, void *data);\n\n\n/*\n** coroutine functions\n*/\nLUA_API int  (lua_yield) (lua_State *L, int nresults);\nLUA_API int  (lua_resume) (lua_State *L, int narg);\nLUA_API int  (lua_status) (lua_State *L);\n\n/*\n** garbage-collection function and options\n*/\n\n#define LUA_GCSTOP\t\t0\n#define LUA_GCRESTART\t\t1\n#define LUA_GCCOLLECT\t\t2\n#define LUA_GCCOUNT\t\t3\n#define LUA_GCCOUNTB\t\t4\n#define LUA_GCSTEP\t\t5\n#define LUA_GCSETPAUSE\t\t6\n#define LUA_GCSETSTEPMUL\t7\n\nLUA_API int (lua_gc) (lua_State *L, int what, int data);\n\n\n/*\n** miscellaneous functions\n*/\n\nLUA_API int   (lua_error) (lua_State *L);\n\nLUA_API int   (lua_next) (lua_State *L, int idx);\n\nLUA_API void  (lua_concat) (lua_State *L, int n);\n\nLUA_API lua_Alloc (lua_getallocf) (lua_State *L, void **ud);\nLUA_API void lua_setallocf (lua_State *L, lua_Alloc f, void *ud);\n\n\n\n/* \n** ===============================================================\n** some useful macros\n** ===============================================================\n*/\n\n#define lua_pop(L,n)\t\tlua_settop(L, -(n)-1)\n\n#define lua_newtable(L)\t\tlua_createtable(L, 0, 0)\n\n#define lua_register(L,n,f) (lua_pushcfunction(L, (f)), lua_setglobal(L, (n)))\n\n#define lua_pushcfunction(L,f)\tlua_pushcclosure(L, (f), 0)\n\n#define lua_strlen(L,i)\t\tlua_objlen(L, (i))\n\n#define lua_isfunction(L,n)\t(lua_type(L, (n)) == LUA_TFUNCTION)\n#define lua_istable(L,n)\t(lua_type(L, (n)) == LUA_TTABLE)\n#define lua_islightuserdata(L,n)\t(lua_type(L, (n)) == LUA_TLIGHTUSERDATA)\n#define lua_isnil(L,n)\t\t(lua_type(L, (n)) == LUA_TNIL)\n#define lua_isboolean(L,n)\t(lua_type(L, (n)) == LUA_TBOOLEAN)\n#define lua_isthread(L,n)\t(lua_type(L, (n)) == LUA_TTHREAD)\n#define lua_isnone(L,n)\t\t(lua_type(L, (n)) == LUA_TNONE)\n#define lua_isnoneornil(L, n)\t(lua_type(L, (n)) <= 0)\n\n#define lua_pushliteral(L, s)\t\\\n\tlua_pushlstring(L, \"\" s, (sizeof(s)/sizeof(char))-1)\n\n#define lua_setglobal(L,s)\tlua_setfield(L, LUA_GLOBALSINDEX, (s))\n#define lua_getglobal(L,s)\tlua_getfield(L, LUA_GLOBALSINDEX, (s))\n\n#define lua_tostring(L,i)\tlua_tolstring(L, (i), NULL)\n\n\n\n/*\n** compatibility macros and functions\n*/\n\n#define lua_open()\tluaL_newstate()\n\n#define lua_getregistry(L)\tlua_pushvalue(L, LUA_REGISTRYINDEX)\n\n#define lua_getgccount(L)\tlua_gc(L, LUA_GCCOUNT, 0)\n\n#define lua_Chunkreader\t\tlua_Reader\n#define lua_Chunkwriter\t\tlua_Writer\n\n\n/* hack */\nLUA_API void lua_setlevel\t(lua_State *from, lua_State *to);\n\n\n/*\n** {======================================================================\n** Debug API\n** =======================================================================\n*/\n\n\n/*\n** Event codes\n*/\n#define LUA_HOOKCALL\t0\n#define LUA_HOOKRET\t1\n#define LUA_HOOKLINE\t2\n#define LUA_HOOKCOUNT\t3\n#define LUA_HOOKTAILRET 4\n\n\n/*\n** Event masks\n*/\n#define LUA_MASKCALL\t(1 << LUA_HOOKCALL)\n#define LUA_MASKRET\t(1 << LUA_HOOKRET)\n#define LUA_MASKLINE\t(1 << LUA_HOOKLINE)\n#define LUA_MASKCOUNT\t(1 << LUA_HOOKCOUNT)\n\ntypedef struct lua_Debug lua_Debug;  /* activation record */\n\n\n/* Functions to be called by the debuger in specific events */\ntypedef void (*lua_Hook) (lua_State *L, lua_Debug *ar);\n\n\nLUA_API int lua_getstack (lua_State *L, int level, lua_Debug *ar);\nLUA_API int lua_getinfo (lua_State *L, const char *what, lua_Debug *ar);\nLUA_API const char *lua_getlocal (lua_State *L, const lua_Debug *ar, int n);\nLUA_API const char *lua_setlocal (lua_State *L, const lua_Debug *ar, int n);\nLUA_API const char *lua_getupvalue (lua_State *L, int funcindex, int n);\nLUA_API const char *lua_setupvalue (lua_State *L, int funcindex, int n);\n\nLUA_API int lua_sethook (lua_State *L, lua_Hook func, int mask, int count);\nLUA_API lua_Hook lua_gethook (lua_State *L);\nLUA_API int lua_gethookmask (lua_State *L);\nLUA_API int lua_gethookcount (lua_State *L);\n\n\nstruct lua_Debug {\n  int event;\n  const char *name;\t/* (n) */\n  const char *namewhat;\t/* (n) `global', `local', `field', `method' */\n  const char *what;\t/* (S) `Lua', `C', `main', `tail' */\n  const char *source;\t/* (S) */\n  int currentline;\t/* (l) */\n  int nups;\t\t/* (u) number of upvalues */\n  int linedefined;\t/* (S) */\n  int lastlinedefined;\t/* (S) */\n  char short_src[LUA_IDSIZE]; /* (S) */\n  /* private part */\n  int i_ci;  /* active function */\n};\n\n/* }====================================================================== */\n\n\n/******************************************************************************\n* Copyright (C) 1994-2012 Lua.org, PUC-Rio.  All rights reserved.\n*\n* Permission is hereby granted, free of charge, to any person obtaining\n* a copy of this software and associated documentation files (the\n* \"Software\"), to deal in the Software without restriction, including\n* without limitation the rights to use, copy, modify, merge, publish,\n* distribute, sublicense, and/or sell copies of the Software, and to\n* permit persons to whom the Software is furnished to do so, subject to\n* the following conditions:\n*\n* The above copyright notice and this permission notice shall be\n* included in all copies or substantial portions of the Software.\n*\n* THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND,\n* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\n* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.\n* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY\n* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,\n* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE\n* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n******************************************************************************/\n\n\n#endif\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/deps/lua/src/lua_bit.c",
    "content": "/*\n** Lua BitOp -- a bit operations library for Lua 5.1/5.2.\n** http://bitop.luajit.org/\n**\n** Copyright (C) 2008-2012 Mike Pall. All rights reserved.\n**\n** Permission is hereby granted, free of charge, to any person obtaining\n** a copy of this software and associated documentation files (the\n** \"Software\"), to deal in the Software without restriction, including\n** without limitation the rights to use, copy, modify, merge, publish,\n** distribute, sublicense, and/or sell copies of the Software, and to\n** permit persons to whom the Software is furnished to do so, subject to\n** the following conditions:\n**\n** The above copyright notice and this permission notice shall be\n** included in all copies or substantial portions of the Software.\n**\n** THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND,\n** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\n** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.\n** IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY\n** CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,\n** TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE\n** SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n**\n** [ MIT license: http://www.opensource.org/licenses/mit-license.php ]\n*/\n\n#define LUA_BITOP_VERSION\t\"1.0.2\"\n\n#define LUA_LIB\n#include \"lua.h\"\n#include \"lauxlib.h\"\n\n#ifdef _MSC_VER\n/* MSVC is stuck in the last century and doesn't have C99's stdint.h. */\ntypedef __int32 int32_t;\ntypedef unsigned __int32 uint32_t;\ntypedef unsigned __int64 uint64_t;\n#else\n#include <stdint.h>\n#endif\n\ntypedef int32_t SBits;\ntypedef uint32_t UBits;\n\ntypedef union {\n  lua_Number n;\n#ifdef LUA_NUMBER_DOUBLE\n  uint64_t b;\n#else\n  UBits b;\n#endif\n} BitNum;\n\n/* Convert argument to bit type. */\nstatic UBits barg(lua_State *L, int idx)\n{\n  BitNum bn;\n  UBits b;\n#if LUA_VERSION_NUM < 502\n  bn.n = lua_tonumber(L, idx);\n#else\n  bn.n = luaL_checknumber(L, idx);\n#endif\n#if defined(LUA_NUMBER_DOUBLE)\n  bn.n += 6755399441055744.0;  /* 2^52+2^51 */\n#ifdef SWAPPED_DOUBLE\n  b = (UBits)(bn.b >> 32);\n#else\n  b = (UBits)bn.b;\n#endif\n#elif defined(LUA_NUMBER_INT) || defined(LUA_NUMBER_LONG) || \\\n      defined(LUA_NUMBER_LONGLONG) || defined(LUA_NUMBER_LONG_LONG) || \\\n      defined(LUA_NUMBER_LLONG)\n  if (sizeof(UBits) == sizeof(lua_Number))\n    b = bn.b;\n  else\n    b = (UBits)(SBits)bn.n;\n#elif defined(LUA_NUMBER_FLOAT)\n#error \"A 'float' lua_Number type is incompatible with this library\"\n#else\n#error \"Unknown number type, check LUA_NUMBER_* in luaconf.h\"\n#endif\n#if LUA_VERSION_NUM < 502\n  if (b == 0 && !lua_isnumber(L, idx)) {\n    luaL_typerror(L, idx, \"number\");\n  }\n#endif\n  return b;\n}\n\n/* Return bit type. */\n#define BRET(b)  lua_pushnumber(L, (lua_Number)(SBits)(b)); return 1;\n\nstatic int bit_tobit(lua_State *L) { BRET(barg(L, 1)) }\nstatic int bit_bnot(lua_State *L) { BRET(~barg(L, 1)) }\n\n#define BIT_OP(func, opr) \\\n  static int func(lua_State *L) { int i; UBits b = barg(L, 1); \\\n    for (i = lua_gettop(L); i > 1; i--) b opr barg(L, i); BRET(b) }\nBIT_OP(bit_band, &=)\nBIT_OP(bit_bor, |=)\nBIT_OP(bit_bxor, ^=)\n\n#define bshl(b, n)  (b << n)\n#define bshr(b, n)  (b >> n)\n#define bsar(b, n)  ((SBits)b >> n)\n#define brol(b, n)  ((b << n) | (b >> (32-n)))\n#define bror(b, n)  ((b << (32-n)) | (b >> n))\n#define BIT_SH(func, fn) \\\n  static int func(lua_State *L) { \\\n    UBits b = barg(L, 1); UBits n = barg(L, 2) & 31; BRET(fn(b, n)) }\nBIT_SH(bit_lshift, bshl)\nBIT_SH(bit_rshift, bshr)\nBIT_SH(bit_arshift, bsar)\nBIT_SH(bit_rol, brol)\nBIT_SH(bit_ror, bror)\n\nstatic int bit_bswap(lua_State *L)\n{\n  UBits b = barg(L, 1);\n  b = (b >> 24) | ((b >> 8) & 0xff00) | ((b & 0xff00) << 8) | (b << 24);\n  BRET(b)\n}\n\nstatic int bit_tohex(lua_State *L)\n{\n  UBits b = barg(L, 1);\n  SBits n = lua_isnone(L, 2) ? 8 : (SBits)barg(L, 2);\n  const char *hexdigits = \"0123456789abcdef\";\n  char buf[8];\n  int i;\n  if (n < 0) { n = -n; hexdigits = \"0123456789ABCDEF\"; }\n  if (n > 8) n = 8;\n  for (i = (int)n; --i >= 0; ) { buf[i] = hexdigits[b & 15]; b >>= 4; }\n  lua_pushlstring(L, buf, (size_t)n);\n  return 1;\n}\n\nstatic const struct luaL_Reg bit_funcs[] = {\n  { \"tobit\",\tbit_tobit },\n  { \"bnot\",\tbit_bnot },\n  { \"band\",\tbit_band },\n  { \"bor\",\tbit_bor },\n  { \"bxor\",\tbit_bxor },\n  { \"lshift\",\tbit_lshift },\n  { \"rshift\",\tbit_rshift },\n  { \"arshift\",\tbit_arshift },\n  { \"rol\",\tbit_rol },\n  { \"ror\",\tbit_ror },\n  { \"bswap\",\tbit_bswap },\n  { \"tohex\",\tbit_tohex },\n  { NULL, NULL }\n};\n\n/* Signed right-shifts are implementation-defined per C89/C99.\n** But the de facto standard are arithmetic right-shifts on two's\n** complement CPUs. This behaviour is required here, so test for it.\n*/\n#define BAD_SAR\t\t(bsar(-8, 2) != (SBits)-2)\n\nLUALIB_API int luaopen_bit(lua_State *L)\n{\n  UBits b;\n  lua_pushnumber(L, (lua_Number)1437217655L);\n  b = barg(L, -1);\n  if (b != (UBits)1437217655L || BAD_SAR) {  /* Perform a simple self-test. */\n    const char *msg = \"compiled with incompatible luaconf.h\";\n#ifdef LUA_NUMBER_DOUBLE\n#ifdef _WIN32\n    if (b == (UBits)1610612736L)\n      msg = \"use D3DCREATE_FPU_PRESERVE with DirectX\";\n#endif\n    if (b == (UBits)1127743488L)\n      msg = \"not compiled with SWAPPED_DOUBLE\";\n#endif\n    if (BAD_SAR)\n      msg = \"arithmetic right-shift broken\";\n    luaL_error(L, \"bit library self-test failed (%s)\", msg);\n  }\n#if LUA_VERSION_NUM < 502\n  luaL_register(L, \"bit\", bit_funcs);\n#else\n  luaL_newlib(L, bit_funcs);\n#endif\n  return 1;\n}\n\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/deps/lua/src/lua_cjson.c",
    "content": "/* Lua CJSON - JSON support for Lua\n *\n * Copyright (c) 2010-2012  Mark Pulford <mark@kyne.com.au>\n *\n * Permission is hereby granted, free of charge, to any person obtaining\n * a copy of this software and associated documentation files (the\n * \"Software\"), to deal in the Software without restriction, including\n * without limitation the rights to use, copy, modify, merge, publish,\n * distribute, sublicense, and/or sell copies of the Software, and to\n * permit persons to whom the Software is furnished to do so, subject to\n * the following conditions:\n *\n * The above copyright notice and this permission notice shall be\n * included in all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND,\n * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\n * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.\n * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY\n * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,\n * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE\n * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n */\n\n/* Caveats:\n * - JSON \"null\" values are represented as lightuserdata since Lua\n *   tables cannot contain \"nil\". Compare with cjson.null.\n * - Invalid UTF-8 characters are not detected and will be passed\n *   untouched. If required, UTF-8 error checking should be done\n *   outside this library.\n * - Javascript comments are not part of the JSON spec, and are not\n *   currently supported.\n *\n * Note: Decoding is slower than encoding. Lua spends significant\n *       time (30%) managing tables when parsing JSON since it is\n *       difficult to know object/array sizes ahead of time.\n */\n\n#include <assert.h>\n#include <string.h>\n#include <math.h>\n#include <limits.h>\n#include \"lua.h\"\n#include \"lauxlib.h\"\n\n#include \"strbuf.h\"\n#include \"fpconv.h\"\n\n#include \"../../../src/solarisfixes.h\"\n\n#ifndef CJSON_MODNAME\n#define CJSON_MODNAME   \"cjson\"\n#endif\n\n#ifndef CJSON_VERSION\n#define CJSON_VERSION   \"2.1.0\"\n#endif\n\n/* Workaround for Solaris platforms missing isinf() */\n#if !defined(isinf) && (defined(USE_INTERNAL_ISINF) || defined(MISSING_ISINF))\n#define isinf(x) (!isnan(x) && isnan((x) - (x)))\n#endif\n\n#define DEFAULT_SPARSE_CONVERT 0\n#define DEFAULT_SPARSE_RATIO 2\n#define DEFAULT_SPARSE_SAFE 10\n#define DEFAULT_ENCODE_MAX_DEPTH 1000\n#define DEFAULT_DECODE_MAX_DEPTH 1000\n#define DEFAULT_ENCODE_INVALID_NUMBERS 0\n#define DEFAULT_DECODE_INVALID_NUMBERS 1\n#define DEFAULT_ENCODE_KEEP_BUFFER 1\n#define DEFAULT_ENCODE_NUMBER_PRECISION 14\n\n#ifdef DISABLE_INVALID_NUMBERS\n#undef DEFAULT_DECODE_INVALID_NUMBERS\n#define DEFAULT_DECODE_INVALID_NUMBERS 0\n#endif\n\ntypedef enum {\n    T_OBJ_BEGIN,\n    T_OBJ_END,\n    T_ARR_BEGIN,\n    T_ARR_END,\n    T_STRING,\n    T_NUMBER,\n    T_BOOLEAN,\n    T_NULL,\n    T_COLON,\n    T_COMMA,\n    T_END,\n    T_WHITESPACE,\n    T_ERROR,\n    T_UNKNOWN\n} json_token_type_t;\n\nstatic const char *json_token_type_name[] = {\n    \"T_OBJ_BEGIN\",\n    \"T_OBJ_END\",\n    \"T_ARR_BEGIN\",\n    \"T_ARR_END\",\n    \"T_STRING\",\n    \"T_NUMBER\",\n    \"T_BOOLEAN\",\n    \"T_NULL\",\n    \"T_COLON\",\n    \"T_COMMA\",\n    \"T_END\",\n    \"T_WHITESPACE\",\n    \"T_ERROR\",\n    \"T_UNKNOWN\",\n    NULL\n};\n\ntypedef struct {\n    json_token_type_t ch2token[256];\n    char escape2char[256];  /* Decoding */\n\n    /* encode_buf is only allocated and used when\n     * encode_keep_buffer is set */\n    strbuf_t encode_buf;\n\n    int encode_sparse_convert;\n    int encode_sparse_ratio;\n    int encode_sparse_safe;\n    int encode_max_depth;\n    int encode_invalid_numbers;     /* 2 => Encode as \"null\" */\n    int encode_number_precision;\n    int encode_keep_buffer;\n\n    int decode_invalid_numbers;\n    int decode_max_depth;\n} json_config_t;\n\ntypedef struct {\n    const char *data;\n    const char *ptr;\n    strbuf_t *tmp;    /* Temporary storage for strings */\n    json_config_t *cfg;\n    int current_depth;\n} json_parse_t;\n\ntypedef struct {\n    json_token_type_t type;\n    int index;\n    union {\n        const char *string;\n        double number;\n        int boolean;\n    } value;\n    int string_len;\n} json_token_t;\n\nstatic const char *char2escape[256] = {\n    \"\\\\u0000\", \"\\\\u0001\", \"\\\\u0002\", \"\\\\u0003\",\n    \"\\\\u0004\", \"\\\\u0005\", \"\\\\u0006\", \"\\\\u0007\",\n    \"\\\\b\", \"\\\\t\", \"\\\\n\", \"\\\\u000b\",\n    \"\\\\f\", \"\\\\r\", \"\\\\u000e\", \"\\\\u000f\",\n    \"\\\\u0010\", \"\\\\u0011\", \"\\\\u0012\", \"\\\\u0013\",\n    \"\\\\u0014\", \"\\\\u0015\", \"\\\\u0016\", \"\\\\u0017\",\n    \"\\\\u0018\", \"\\\\u0019\", \"\\\\u001a\", \"\\\\u001b\",\n    \"\\\\u001c\", \"\\\\u001d\", \"\\\\u001e\", \"\\\\u001f\",\n    NULL, NULL, \"\\\\\\\"\", NULL, NULL, NULL, NULL, NULL,\n    NULL, NULL, NULL, NULL, NULL, NULL, NULL, \"\\\\/\",\n    NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,\n    NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,\n    NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,\n    NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,\n    NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,\n    NULL, NULL, NULL, NULL, \"\\\\\\\\\", NULL, NULL, NULL,\n    NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,\n    NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,\n    NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,\n    NULL, NULL, NULL, NULL, NULL, NULL, NULL, \"\\\\u007f\",\n    NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,\n    NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,\n    NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,\n    NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,\n    NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,\n    NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,\n    NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,\n    NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,\n    NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,\n    NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,\n    NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,\n    NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,\n    NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,\n    NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,\n    NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,\n    NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,\n};\n\n/* ===== CONFIGURATION ===== */\n\nstatic json_config_t *json_fetch_config(lua_State *l)\n{\n    json_config_t *cfg;\n\n    cfg = lua_touserdata(l, lua_upvalueindex(1));\n    if (!cfg)\n        luaL_error(l, \"BUG: Unable to fetch CJSON configuration\");\n\n    return cfg;\n}\n\n/* Ensure the correct number of arguments have been provided.\n * Pad with nil to allow other functions to simply check arg[i]\n * to find whether an argument was provided */\nstatic json_config_t *json_arg_init(lua_State *l, int args)\n{\n    luaL_argcheck(l, lua_gettop(l) <= args, args + 1,\n                  \"found too many arguments\");\n\n    while (lua_gettop(l) < args)\n        lua_pushnil(l);\n\n    return json_fetch_config(l);\n}\n\n/* Process integer options for configuration functions */\nstatic int json_integer_option(lua_State *l, int optindex, int *setting,\n                               int min, int max)\n{\n    char errmsg[64];\n    int value;\n\n    if (!lua_isnil(l, optindex)) {\n        value = luaL_checkinteger(l, optindex);\n        snprintf(errmsg, sizeof(errmsg), \"expected integer between %d and %d\", min, max);\n        luaL_argcheck(l, min <= value && value <= max, 1, errmsg);\n        *setting = value;\n    }\n\n    lua_pushinteger(l, *setting);\n\n    return 1;\n}\n\n/* Process enumerated arguments for a configuration function */\nstatic int json_enum_option(lua_State *l, int optindex, int *setting,\n                            const char **options, int bool_true)\n{\n    static const char *bool_options[] = { \"off\", \"on\", NULL };\n\n    if (!options) {\n        options = bool_options;\n        bool_true = 1;\n    }\n\n    if (!lua_isnil(l, optindex)) {\n        if (bool_true && lua_isboolean(l, optindex))\n            *setting = lua_toboolean(l, optindex) * bool_true;\n        else\n            *setting = luaL_checkoption(l, optindex, NULL, options);\n    }\n\n    if (bool_true && (*setting == 0 || *setting == bool_true))\n        lua_pushboolean(l, *setting);\n    else\n        lua_pushstring(l, options[*setting]);\n\n    return 1;\n}\n\n/* Configures handling of extremely sparse arrays:\n * convert: Convert extremely sparse arrays into objects? Otherwise error.\n * ratio: 0: always allow sparse; 1: never allow sparse; >1: use ratio\n * safe: Always use an array when the max index <= safe */\nstatic int json_cfg_encode_sparse_array(lua_State *l)\n{\n    json_config_t *cfg = json_arg_init(l, 3);\n\n    json_enum_option(l, 1, &cfg->encode_sparse_convert, NULL, 1);\n    json_integer_option(l, 2, &cfg->encode_sparse_ratio, 0, INT_MAX);\n    json_integer_option(l, 3, &cfg->encode_sparse_safe, 0, INT_MAX);\n\n    return 3;\n}\n\n/* Configures the maximum number of nested arrays/objects allowed when\n * encoding */\nstatic int json_cfg_encode_max_depth(lua_State *l)\n{\n    json_config_t *cfg = json_arg_init(l, 1);\n\n    return json_integer_option(l, 1, &cfg->encode_max_depth, 1, INT_MAX);\n}\n\n/* Configures the maximum number of nested arrays/objects allowed when\n * encoding */\nstatic int json_cfg_decode_max_depth(lua_State *l)\n{\n    json_config_t *cfg = json_arg_init(l, 1);\n\n    return json_integer_option(l, 1, &cfg->decode_max_depth, 1, INT_MAX);\n}\n\n/* Configures number precision when converting doubles to text */\nstatic int json_cfg_encode_number_precision(lua_State *l)\n{\n    json_config_t *cfg = json_arg_init(l, 1);\n\n    return json_integer_option(l, 1, &cfg->encode_number_precision, 1, 14);\n}\n\n/* Configures JSON encoding buffer persistence */\nstatic int json_cfg_encode_keep_buffer(lua_State *l)\n{\n    json_config_t *cfg = json_arg_init(l, 1);\n    int old_value;\n\n    old_value = cfg->encode_keep_buffer;\n\n    json_enum_option(l, 1, &cfg->encode_keep_buffer, NULL, 1);\n\n    /* Init / free the buffer if the setting has changed */\n    if (old_value ^ cfg->encode_keep_buffer) {\n        if (cfg->encode_keep_buffer)\n            strbuf_init(&cfg->encode_buf, 0);\n        else\n            strbuf_free(&cfg->encode_buf);\n    }\n\n    return 1;\n}\n\n#if defined(DISABLE_INVALID_NUMBERS) && !defined(USE_INTERNAL_FPCONV)\nvoid json_verify_invalid_number_setting(lua_State *l, int *setting)\n{\n    if (*setting == 1) {\n        *setting = 0;\n        luaL_error(l, \"Infinity, NaN, and/or hexadecimal numbers are not supported.\");\n    }\n}\n#else\n#define json_verify_invalid_number_setting(l, s)    do { } while(0)\n#endif\n\nstatic int json_cfg_encode_invalid_numbers(lua_State *l)\n{\n    static const char *options[] = { \"off\", \"on\", \"null\", NULL };\n    json_config_t *cfg = json_arg_init(l, 1);\n\n    json_enum_option(l, 1, &cfg->encode_invalid_numbers, options, 1);\n\n    json_verify_invalid_number_setting(l, &cfg->encode_invalid_numbers);\n\n    return 1;\n}\n\nstatic int json_cfg_decode_invalid_numbers(lua_State *l)\n{\n    json_config_t *cfg = json_arg_init(l, 1);\n\n    json_enum_option(l, 1, &cfg->decode_invalid_numbers, NULL, 1);\n\n    json_verify_invalid_number_setting(l, &cfg->encode_invalid_numbers);\n\n    return 1;\n}\n\nstatic int json_destroy_config(lua_State *l)\n{\n    json_config_t *cfg;\n\n    cfg = lua_touserdata(l, 1);\n    if (cfg)\n        strbuf_free(&cfg->encode_buf);\n    cfg = NULL;\n\n    return 0;\n}\n\nstatic void json_create_config(lua_State *l)\n{\n    json_config_t *cfg;\n    int i;\n\n    cfg = lua_newuserdata(l, sizeof(*cfg));\n\n    /* Create GC method to clean up strbuf */\n    lua_newtable(l);\n    lua_pushcfunction(l, json_destroy_config);\n    lua_setfield(l, -2, \"__gc\");\n    lua_setmetatable(l, -2);\n\n    cfg->encode_sparse_convert = DEFAULT_SPARSE_CONVERT;\n    cfg->encode_sparse_ratio = DEFAULT_SPARSE_RATIO;\n    cfg->encode_sparse_safe = DEFAULT_SPARSE_SAFE;\n    cfg->encode_max_depth = DEFAULT_ENCODE_MAX_DEPTH;\n    cfg->decode_max_depth = DEFAULT_DECODE_MAX_DEPTH;\n    cfg->encode_invalid_numbers = DEFAULT_ENCODE_INVALID_NUMBERS;\n    cfg->decode_invalid_numbers = DEFAULT_DECODE_INVALID_NUMBERS;\n    cfg->encode_keep_buffer = DEFAULT_ENCODE_KEEP_BUFFER;\n    cfg->encode_number_precision = DEFAULT_ENCODE_NUMBER_PRECISION;\n\n#if DEFAULT_ENCODE_KEEP_BUFFER > 0\n    strbuf_init(&cfg->encode_buf, 0);\n#endif\n\n    /* Decoding init */\n\n    /* Tag all characters as an error */\n    for (i = 0; i < 256; i++)\n        cfg->ch2token[i] = T_ERROR;\n\n    /* Set tokens that require no further processing */\n    cfg->ch2token['{'] = T_OBJ_BEGIN;\n    cfg->ch2token['}'] = T_OBJ_END;\n    cfg->ch2token['['] = T_ARR_BEGIN;\n    cfg->ch2token[']'] = T_ARR_END;\n    cfg->ch2token[','] = T_COMMA;\n    cfg->ch2token[':'] = T_COLON;\n    cfg->ch2token['\\0'] = T_END;\n    cfg->ch2token[' '] = T_WHITESPACE;\n    cfg->ch2token['\\t'] = T_WHITESPACE;\n    cfg->ch2token['\\n'] = T_WHITESPACE;\n    cfg->ch2token['\\r'] = T_WHITESPACE;\n\n    /* Update characters that require further processing */\n    cfg->ch2token['f'] = T_UNKNOWN;     /* false? */\n    cfg->ch2token['i'] = T_UNKNOWN;     /* inf, ininity? */\n    cfg->ch2token['I'] = T_UNKNOWN;\n    cfg->ch2token['n'] = T_UNKNOWN;     /* null, nan? */\n    cfg->ch2token['N'] = T_UNKNOWN;\n    cfg->ch2token['t'] = T_UNKNOWN;     /* true? */\n    cfg->ch2token['\"'] = T_UNKNOWN;     /* string? */\n    cfg->ch2token['+'] = T_UNKNOWN;     /* number? */\n    cfg->ch2token['-'] = T_UNKNOWN;\n    for (i = 0; i < 10; i++)\n        cfg->ch2token['0' + i] = T_UNKNOWN;\n\n    /* Lookup table for parsing escape characters */\n    for (i = 0; i < 256; i++)\n        cfg->escape2char[i] = 0;          /* String error */\n    cfg->escape2char['\"'] = '\"';\n    cfg->escape2char['\\\\'] = '\\\\';\n    cfg->escape2char['/'] = '/';\n    cfg->escape2char['b'] = '\\b';\n    cfg->escape2char['t'] = '\\t';\n    cfg->escape2char['n'] = '\\n';\n    cfg->escape2char['f'] = '\\f';\n    cfg->escape2char['r'] = '\\r';\n    cfg->escape2char['u'] = 'u';          /* Unicode parsing required */\n}\n\n/* ===== ENCODING ===== */\n\nstatic void json_encode_exception(lua_State *l, json_config_t *cfg, strbuf_t *json, int lindex,\n                                  const char *reason)\n{\n    if (!cfg->encode_keep_buffer)\n        strbuf_free(json);\n    luaL_error(l, \"Cannot serialise %s: %s\",\n                  lua_typename(l, lua_type(l, lindex)), reason);\n}\n\n/* json_append_string args:\n * - lua_State\n * - JSON strbuf\n * - String (Lua stack index)\n *\n * Returns nothing. Doesn't remove string from Lua stack */\nstatic void json_append_string(lua_State *l, strbuf_t *json, int lindex)\n{\n    const char *escstr;\n    int i;\n    const char *str;\n    size_t len;\n\n    str = lua_tolstring(l, lindex, &len);\n\n    /* Worst case is len * 6 (all unicode escapes).\n     * This buffer is reused constantly for small strings\n     * If there are any excess pages, they won't be hit anyway.\n     * This gains ~5% speedup. */\n    strbuf_ensure_empty_length(json, len * 6 + 2);\n\n    strbuf_append_char_unsafe(json, '\\\"');\n    for (i = 0; i < len; i++) {\n        escstr = char2escape[(unsigned char)str[i]];\n        if (escstr)\n            strbuf_append_string(json, escstr);\n        else\n            strbuf_append_char_unsafe(json, str[i]);\n    }\n    strbuf_append_char_unsafe(json, '\\\"');\n}\n\n/* Find the size of the array on the top of the Lua stack\n * -1   object (not a pure array)\n * >=0  elements in array\n */\nstatic int lua_array_length(lua_State *l, json_config_t *cfg, strbuf_t *json)\n{\n    double k;\n    int max;\n    int items;\n\n    max = 0;\n    items = 0;\n\n    lua_pushnil(l);\n    /* table, startkey */\n    while (lua_next(l, -2) != 0) {\n        /* table, key, value */\n        if (lua_type(l, -2) == LUA_TNUMBER &&\n            (k = lua_tonumber(l, -2))) {\n            /* Integer >= 1 ? */\n            if (floor(k) == k && k >= 1) {\n                if (k > max)\n                    max = k;\n                items++;\n                lua_pop(l, 1);\n                continue;\n            }\n        }\n\n        /* Must not be an array (non integer key) */\n        lua_pop(l, 2);\n        return -1;\n    }\n\n    /* Encode excessively sparse arrays as objects (if enabled) */\n    if (cfg->encode_sparse_ratio > 0 &&\n        max > items * cfg->encode_sparse_ratio &&\n        max > cfg->encode_sparse_safe) {\n        if (!cfg->encode_sparse_convert)\n            json_encode_exception(l, cfg, json, -1, \"excessively sparse array\");\n\n        return -1;\n    }\n\n    return max;\n}\n\nstatic void json_check_encode_depth(lua_State *l, json_config_t *cfg,\n                                    int current_depth, strbuf_t *json)\n{\n    /* Ensure there are enough slots free to traverse a table (key,\n     * value) and push a string for a potential error message.\n     *\n     * Unlike \"decode\", the key and value are still on the stack when\n     * lua_checkstack() is called.  Hence an extra slot for luaL_error()\n     * below is required just in case the next check to lua_checkstack()\n     * fails.\n     *\n     * While this won't cause a crash due to the EXTRA_STACK reserve\n     * slots, it would still be an improper use of the API. */\n    if (current_depth <= cfg->encode_max_depth && lua_checkstack(l, 3))\n        return;\n\n    if (!cfg->encode_keep_buffer)\n        strbuf_free(json);\n\n    luaL_error(l, \"Cannot serialise, excessive nesting (%d)\",\n               current_depth);\n}\n\nstatic void json_append_data(lua_State *l, json_config_t *cfg,\n                             int current_depth, strbuf_t *json);\n\n/* json_append_array args:\n * - lua_State\n * - JSON strbuf\n * - Size of passwd Lua array (top of stack) */\nstatic void json_append_array(lua_State *l, json_config_t *cfg, int current_depth,\n                              strbuf_t *json, int array_length)\n{\n    int comma, i;\n\n    strbuf_append_char(json, '[');\n\n    comma = 0;\n    for (i = 1; i <= array_length; i++) {\n        if (comma)\n            strbuf_append_char(json, ',');\n        else\n            comma = 1;\n\n        lua_rawgeti(l, -1, i);\n        json_append_data(l, cfg, current_depth, json);\n        lua_pop(l, 1);\n    }\n\n    strbuf_append_char(json, ']');\n}\n\nstatic void json_append_number(lua_State *l, json_config_t *cfg,\n                               strbuf_t *json, int lindex)\n{\n    double num = lua_tonumber(l, lindex);\n    int len;\n\n    if (cfg->encode_invalid_numbers == 0) {\n        /* Prevent encoding invalid numbers */\n        if (isinf(num) || isnan(num))\n            json_encode_exception(l, cfg, json, lindex, \"must not be NaN or Inf\");\n    } else if (cfg->encode_invalid_numbers == 1) {\n        /* Encode invalid numbers, but handle \"nan\" separately\n         * since some platforms may encode as \"-nan\". */\n        if (isnan(num)) {\n            strbuf_append_mem(json, \"nan\", 3);\n            return;\n        }\n    } else {\n        /* Encode invalid numbers as \"null\" */\n        if (isinf(num) || isnan(num)) {\n            strbuf_append_mem(json, \"null\", 4);\n            return;\n        }\n    }\n\n    strbuf_ensure_empty_length(json, FPCONV_G_FMT_BUFSIZE);\n    len = fpconv_g_fmt(strbuf_empty_ptr(json), num, cfg->encode_number_precision);\n    strbuf_extend_length(json, len);\n}\n\nstatic void json_append_object(lua_State *l, json_config_t *cfg,\n                               int current_depth, strbuf_t *json)\n{\n    int comma, keytype;\n\n    /* Object */\n    strbuf_append_char(json, '{');\n\n    lua_pushnil(l);\n    /* table, startkey */\n    comma = 0;\n    while (lua_next(l, -2) != 0) {\n        if (comma)\n            strbuf_append_char(json, ',');\n        else\n            comma = 1;\n\n        /* table, key, value */\n        keytype = lua_type(l, -2);\n        if (keytype == LUA_TNUMBER) {\n            strbuf_append_char(json, '\"');\n            json_append_number(l, cfg, json, -2);\n            strbuf_append_mem(json, \"\\\":\", 2);\n        } else if (keytype == LUA_TSTRING) {\n            json_append_string(l, json, -2);\n            strbuf_append_char(json, ':');\n        } else {\n            json_encode_exception(l, cfg, json, -2,\n                                  \"table key must be a number or string\");\n            /* never returns */\n        }\n\n        /* table, key, value */\n        json_append_data(l, cfg, current_depth, json);\n        lua_pop(l, 1);\n        /* table, key */\n    }\n\n    strbuf_append_char(json, '}');\n}\n\n/* Serialise Lua data into JSON string. */\nstatic void json_append_data(lua_State *l, json_config_t *cfg,\n                             int current_depth, strbuf_t *json)\n{\n    int len;\n\n    switch (lua_type(l, -1)) {\n    case LUA_TSTRING:\n        json_append_string(l, json, -1);\n        break;\n    case LUA_TNUMBER:\n        json_append_number(l, cfg, json, -1);\n        break;\n    case LUA_TBOOLEAN:\n        if (lua_toboolean(l, -1))\n            strbuf_append_mem(json, \"true\", 4);\n        else\n            strbuf_append_mem(json, \"false\", 5);\n        break;\n    case LUA_TTABLE:\n        current_depth++;\n        json_check_encode_depth(l, cfg, current_depth, json);\n        len = lua_array_length(l, cfg, json);\n        if (len > 0)\n            json_append_array(l, cfg, current_depth, json, len);\n        else\n            json_append_object(l, cfg, current_depth, json);\n        break;\n    case LUA_TNIL:\n        strbuf_append_mem(json, \"null\", 4);\n        break;\n    case LUA_TLIGHTUSERDATA:\n        if (lua_touserdata(l, -1) == NULL) {\n            strbuf_append_mem(json, \"null\", 4);\n            break;\n        }\n    default:\n        /* Remaining types (LUA_TFUNCTION, LUA_TUSERDATA, LUA_TTHREAD,\n         * and LUA_TLIGHTUSERDATA) cannot be serialised */\n        json_encode_exception(l, cfg, json, -1, \"type not supported\");\n        /* never returns */\n    }\n}\n\nstatic int json_encode(lua_State *l)\n{\n    json_config_t *cfg = json_fetch_config(l);\n    strbuf_t local_encode_buf;\n    strbuf_t *encode_buf;\n    char *json;\n    int len;\n\n    luaL_argcheck(l, lua_gettop(l) == 1, 1, \"expected 1 argument\");\n\n    if (!cfg->encode_keep_buffer) {\n        /* Use private buffer */\n        encode_buf = &local_encode_buf;\n        strbuf_init(encode_buf, 0);\n    } else {\n        /* Reuse existing buffer */\n        encode_buf = &cfg->encode_buf;\n        strbuf_reset(encode_buf);\n    }\n\n    json_append_data(l, cfg, 0, encode_buf);\n    json = strbuf_string(encode_buf, &len);\n\n    lua_pushlstring(l, json, len);\n\n    if (!cfg->encode_keep_buffer)\n        strbuf_free(encode_buf);\n\n    return 1;\n}\n\n/* ===== DECODING ===== */\n\nstatic void json_process_value(lua_State *l, json_parse_t *json,\n                               json_token_t *token);\n\nstatic int hexdigit2int(char hex)\n{\n    if ('0' <= hex  && hex <= '9')\n        return hex - '0';\n\n    /* Force lowercase */\n    hex |= 0x20;\n    if ('a' <= hex && hex <= 'f')\n        return 10 + hex - 'a';\n\n    return -1;\n}\n\nstatic int decode_hex4(const char *hex)\n{\n    int digit[4];\n    int i;\n\n    /* Convert ASCII hex digit to numeric digit\n     * Note: this returns an error for invalid hex digits, including\n     *       NULL */\n    for (i = 0; i < 4; i++) {\n        digit[i] = hexdigit2int(hex[i]);\n        if (digit[i] < 0) {\n            return -1;\n        }\n    }\n\n    return (digit[0] << 12) +\n           (digit[1] << 8) +\n           (digit[2] << 4) +\n            digit[3];\n}\n\n/* Converts a Unicode codepoint to UTF-8.\n * Returns UTF-8 string length, and up to 4 bytes in *utf8 */\nstatic int codepoint_to_utf8(char *utf8, int codepoint)\n{\n    /* 0xxxxxxx */\n    if (codepoint <= 0x7F) {\n        utf8[0] = codepoint;\n        return 1;\n    }\n\n    /* 110xxxxx 10xxxxxx */\n    if (codepoint <= 0x7FF) {\n        utf8[0] = (codepoint >> 6) | 0xC0;\n        utf8[1] = (codepoint & 0x3F) | 0x80;\n        return 2;\n    }\n\n    /* 1110xxxx 10xxxxxx 10xxxxxx */\n    if (codepoint <= 0xFFFF) {\n        utf8[0] = (codepoint >> 12) | 0xE0;\n        utf8[1] = ((codepoint >> 6) & 0x3F) | 0x80;\n        utf8[2] = (codepoint & 0x3F) | 0x80;\n        return 3;\n    }\n\n    /* 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx */\n    if (codepoint <= 0x1FFFFF) {\n        utf8[0] = (codepoint >> 18) | 0xF0;\n        utf8[1] = ((codepoint >> 12) & 0x3F) | 0x80;\n        utf8[2] = ((codepoint >> 6) & 0x3F) | 0x80;\n        utf8[3] = (codepoint & 0x3F) | 0x80;\n        return 4;\n    }\n\n    return 0;\n}\n\n\n/* Called when index pointing to beginning of UTF-16 code escape: \\uXXXX\n * \\u is guaranteed to exist, but the remaining hex characters may be\n * missing.\n * Translate to UTF-8 and append to temporary token string.\n * Must advance index to the next character to be processed.\n * Returns: 0   success\n *          -1  error\n */\nstatic int json_append_unicode_escape(json_parse_t *json)\n{\n    char utf8[4];       /* Surrogate pairs require 4 UTF-8 bytes */\n    int codepoint;\n    int surrogate_low;\n    int len;\n    int escape_len = 6;\n\n    /* Fetch UTF-16 code unit */\n    codepoint = decode_hex4(json->ptr + 2);\n    if (codepoint < 0)\n        return -1;\n\n    /* UTF-16 surrogate pairs take the following 2 byte form:\n     *      11011 x yyyyyyyyyy\n     * When x = 0: y is the high 10 bits of the codepoint\n     *      x = 1: y is the low 10 bits of the codepoint\n     *\n     * Check for a surrogate pair (high or low) */\n    if ((codepoint & 0xF800) == 0xD800) {\n        /* Error if the 1st surrogate is not high */\n        if (codepoint & 0x400)\n            return -1;\n\n        /* Ensure the next code is a unicode escape */\n        if (*(json->ptr + escape_len) != '\\\\' ||\n            *(json->ptr + escape_len + 1) != 'u') {\n            return -1;\n        }\n\n        /* Fetch the next codepoint */\n        surrogate_low = decode_hex4(json->ptr + 2 + escape_len);\n        if (surrogate_low < 0)\n            return -1;\n\n        /* Error if the 2nd code is not a low surrogate */\n        if ((surrogate_low & 0xFC00) != 0xDC00)\n            return -1;\n\n        /* Calculate Unicode codepoint */\n        codepoint = (codepoint & 0x3FF) << 10;\n        surrogate_low &= 0x3FF;\n        codepoint = (codepoint | surrogate_low) + 0x10000;\n        escape_len = 12;\n    }\n\n    /* Convert codepoint to UTF-8 */\n    len = codepoint_to_utf8(utf8, codepoint);\n    if (!len)\n        return -1;\n\n    /* Append bytes and advance parse index */\n    strbuf_append_mem_unsafe(json->tmp, utf8, len);\n    json->ptr += escape_len;\n\n    return 0;\n}\n\nstatic void json_set_token_error(json_token_t *token, json_parse_t *json,\n                                 const char *errtype)\n{\n    token->type = T_ERROR;\n    token->index = json->ptr - json->data;\n    token->value.string = errtype;\n}\n\nstatic void json_next_string_token(json_parse_t *json, json_token_t *token)\n{\n    char *escape2char = json->cfg->escape2char;\n    char ch;\n\n    /* Caller must ensure a string is next */\n    assert(*json->ptr == '\"');\n\n    /* Skip \" */\n    json->ptr++;\n\n    /* json->tmp is the temporary strbuf used to accumulate the\n     * decoded string value.\n     * json->tmp is sized to handle JSON containing only a string value.\n     */\n    strbuf_reset(json->tmp);\n\n    while ((ch = *json->ptr) != '\"') {\n        if (!ch) {\n            /* Premature end of the string */\n            json_set_token_error(token, json, \"unexpected end of string\");\n            return;\n        }\n\n        /* Handle escapes */\n        if (ch == '\\\\') {\n            /* Fetch escape character */\n            ch = *(json->ptr + 1);\n\n            /* Translate escape code and append to tmp string */\n            ch = escape2char[(unsigned char)ch];\n            if (ch == 'u') {\n                if (json_append_unicode_escape(json) == 0)\n                    continue;\n\n                json_set_token_error(token, json,\n                                     \"invalid unicode escape code\");\n                return;\n            }\n            if (!ch) {\n                json_set_token_error(token, json, \"invalid escape code\");\n                return;\n            }\n\n            /* Skip '\\' */\n            json->ptr++;\n        }\n        /* Append normal character or translated single character\n         * Unicode escapes are handled above */\n        strbuf_append_char_unsafe(json->tmp, ch);\n        json->ptr++;\n    }\n    json->ptr++;    /* Eat final quote (\") */\n\n    strbuf_ensure_null(json->tmp);\n\n    token->type = T_STRING;\n    token->value.string = strbuf_string(json->tmp, &token->string_len);\n}\n\n/* JSON numbers should take the following form:\n *      -?(0|[1-9]|[1-9][0-9]+)(.[0-9]+)?([eE][-+]?[0-9]+)?\n *\n * json_next_number_token() uses strtod() which allows other forms:\n * - numbers starting with '+'\n * - NaN, -NaN, infinity, -infinity\n * - hexadecimal numbers\n * - numbers with leading zeros\n *\n * json_is_invalid_number() detects \"numbers\" which may pass strtod()'s\n * error checking, but should not be allowed with strict JSON.\n *\n * json_is_invalid_number() may pass numbers which cause strtod()\n * to generate an error.\n */\nstatic int json_is_invalid_number(json_parse_t *json)\n{\n    const char *p = json->ptr;\n\n    /* Reject numbers starting with + */\n    if (*p == '+')\n        return 1;\n\n    /* Skip minus sign if it exists */\n    if (*p == '-')\n        p++;\n\n    /* Reject numbers starting with 0x, or leading zeros */\n    if (*p == '0') {\n        int ch2 = *(p + 1);\n\n        if ((ch2 | 0x20) == 'x' ||          /* Hex */\n            ('0' <= ch2 && ch2 <= '9'))     /* Leading zero */\n            return 1;\n\n        return 0;\n    } else if (*p <= '9') {\n        return 0;                           /* Ordinary number */\n    }\n\n    /* Reject inf/nan */\n    if (!strncasecmp(p, \"inf\", 3))\n        return 1;\n    if (!strncasecmp(p, \"nan\", 3))\n        return 1;\n\n    /* Pass all other numbers which may still be invalid, but\n     * strtod() will catch them. */\n    return 0;\n}\n\nstatic void json_next_number_token(json_parse_t *json, json_token_t *token)\n{\n    char *endptr;\n\n    token->type = T_NUMBER;\n    token->value.number = fpconv_strtod(json->ptr, &endptr);\n    if (json->ptr == endptr)\n        json_set_token_error(token, json, \"invalid number\");\n    else\n        json->ptr = endptr;     /* Skip the processed number */\n\n    return;\n}\n\n/* Fills in the token struct.\n * T_STRING will return a pointer to the json_parse_t temporary string\n * T_ERROR will leave the json->ptr pointer at the error.\n */\nstatic void json_next_token(json_parse_t *json, json_token_t *token)\n{\n    const json_token_type_t *ch2token = json->cfg->ch2token;\n    int ch;\n\n    /* Eat whitespace. */\n    while (1) {\n        ch = (unsigned char)*(json->ptr);\n        token->type = ch2token[ch];\n        if (token->type != T_WHITESPACE)\n            break;\n        json->ptr++;\n    }\n\n    /* Store location of new token. Required when throwing errors\n     * for unexpected tokens (syntax errors). */\n    token->index = json->ptr - json->data;\n\n    /* Don't advance the pointer for an error or the end */\n    if (token->type == T_ERROR) {\n        json_set_token_error(token, json, \"invalid token\");\n        return;\n    }\n\n    if (token->type == T_END) {\n        return;\n    }\n\n    /* Found a known single character token, advance index and return */\n    if (token->type != T_UNKNOWN) {\n        json->ptr++;\n        return;\n    }\n\n    /* Process characters which triggered T_UNKNOWN\n     *\n     * Must use strncmp() to match the front of the JSON string.\n     * JSON identifier must be lowercase.\n     * When strict_numbers if disabled, either case is allowed for\n     * Infinity/NaN (since we are no longer following the spec..) */\n    if (ch == '\"') {\n        json_next_string_token(json, token);\n        return;\n    } else if (ch == '-' || ('0' <= ch && ch <= '9')) {\n        if (!json->cfg->decode_invalid_numbers && json_is_invalid_number(json)) {\n            json_set_token_error(token, json, \"invalid number\");\n            return;\n        }\n        json_next_number_token(json, token);\n        return;\n    } else if (!strncmp(json->ptr, \"true\", 4)) {\n        token->type = T_BOOLEAN;\n        token->value.boolean = 1;\n        json->ptr += 4;\n        return;\n    } else if (!strncmp(json->ptr, \"false\", 5)) {\n        token->type = T_BOOLEAN;\n        token->value.boolean = 0;\n        json->ptr += 5;\n        return;\n    } else if (!strncmp(json->ptr, \"null\", 4)) {\n        token->type = T_NULL;\n        json->ptr += 4;\n        return;\n    } else if (json->cfg->decode_invalid_numbers &&\n               json_is_invalid_number(json)) {\n        /* When decode_invalid_numbers is enabled, only attempt to process\n         * numbers we know are invalid JSON (Inf, NaN, hex)\n         * This is required to generate an appropriate token error,\n         * otherwise all bad tokens will register as \"invalid number\"\n         */\n        json_next_number_token(json, token);\n        return;\n    }\n\n    /* Token starts with t/f/n but isn't recognised above. */\n    json_set_token_error(token, json, \"invalid token\");\n}\n\n/* This function does not return.\n * DO NOT CALL WITH DYNAMIC MEMORY ALLOCATED.\n * The only supported exception is the temporary parser string\n * json->tmp struct.\n * json and token should exist on the stack somewhere.\n * luaL_error() will long_jmp and release the stack */\nstatic void json_throw_parse_error(lua_State *l, json_parse_t *json,\n                                   const char *exp, json_token_t *token)\n{\n    const char *found;\n\n    strbuf_free(json->tmp);\n\n    if (token->type == T_ERROR)\n        found = token->value.string;\n    else\n        found = json_token_type_name[token->type];\n\n    /* Note: token->index is 0 based, display starting from 1 */\n    luaL_error(l, \"Expected %s but found %s at character %d\",\n               exp, found, token->index + 1);\n}\n\nstatic inline void json_decode_ascend(json_parse_t *json)\n{\n    json->current_depth--;\n}\n\nstatic void json_decode_descend(lua_State *l, json_parse_t *json, int slots)\n{\n    json->current_depth++;\n\n    if (json->current_depth <= json->cfg->decode_max_depth &&\n        lua_checkstack(l, slots)) {\n        return;\n    }\n\n    strbuf_free(json->tmp);\n    luaL_error(l, \"Found too many nested data structures (%d) at character %d\",\n        json->current_depth, json->ptr - json->data);\n}\n\nstatic void json_parse_object_context(lua_State *l, json_parse_t *json)\n{\n    json_token_t token;\n\n    /* 3 slots required:\n     * .., table, key, value */\n    json_decode_descend(l, json, 3);\n\n    lua_newtable(l);\n\n    json_next_token(json, &token);\n\n    /* Handle empty objects */\n    if (token.type == T_OBJ_END) {\n        json_decode_ascend(json);\n        return;\n    }\n\n    while (1) {\n        if (token.type != T_STRING)\n            json_throw_parse_error(l, json, \"object key string\", &token);\n\n        /* Push key */\n        lua_pushlstring(l, token.value.string, token.string_len);\n\n        json_next_token(json, &token);\n        if (token.type != T_COLON)\n            json_throw_parse_error(l, json, \"colon\", &token);\n\n        /* Fetch value */\n        json_next_token(json, &token);\n        json_process_value(l, json, &token);\n\n        /* Set key = value */\n        lua_rawset(l, -3);\n\n        json_next_token(json, &token);\n\n        if (token.type == T_OBJ_END) {\n            json_decode_ascend(json);\n            return;\n        }\n\n        if (token.type != T_COMMA)\n            json_throw_parse_error(l, json, \"comma or object end\", &token);\n\n        json_next_token(json, &token);\n    }\n}\n\n/* Handle the array context */\nstatic void json_parse_array_context(lua_State *l, json_parse_t *json)\n{\n    json_token_t token;\n    int i;\n\n    /* 2 slots required:\n     * .., table, value */\n    json_decode_descend(l, json, 2);\n\n    lua_newtable(l);\n\n    json_next_token(json, &token);\n\n    /* Handle empty arrays */\n    if (token.type == T_ARR_END) {\n        json_decode_ascend(json);\n        return;\n    }\n\n    for (i = 1; ; i++) {\n        json_process_value(l, json, &token);\n        lua_rawseti(l, -2, i);            /* arr[i] = value */\n\n        json_next_token(json, &token);\n\n        if (token.type == T_ARR_END) {\n            json_decode_ascend(json);\n            return;\n        }\n\n        if (token.type != T_COMMA)\n            json_throw_parse_error(l, json, \"comma or array end\", &token);\n\n        json_next_token(json, &token);\n    }\n}\n\n/* Handle the \"value\" context */\nstatic void json_process_value(lua_State *l, json_parse_t *json,\n                               json_token_t *token)\n{\n    switch (token->type) {\n    case T_STRING:\n        lua_pushlstring(l, token->value.string, token->string_len);\n        break;;\n    case T_NUMBER:\n        lua_pushnumber(l, token->value.number);\n        break;;\n    case T_BOOLEAN:\n        lua_pushboolean(l, token->value.boolean);\n        break;;\n    case T_OBJ_BEGIN:\n        json_parse_object_context(l, json);\n        break;;\n    case T_ARR_BEGIN:\n        json_parse_array_context(l, json);\n        break;;\n    case T_NULL:\n        /* In Lua, setting \"t[k] = nil\" will delete k from the table.\n         * Hence a NULL pointer lightuserdata object is used instead */\n        lua_pushlightuserdata(l, NULL);\n        break;;\n    default:\n        json_throw_parse_error(l, json, \"value\", token);\n    }\n}\n\nstatic int json_decode(lua_State *l)\n{\n    json_parse_t json;\n    json_token_t token;\n    size_t json_len;\n\n    luaL_argcheck(l, lua_gettop(l) == 1, 1, \"expected 1 argument\");\n\n    json.cfg = json_fetch_config(l);\n    json.data = luaL_checklstring(l, 1, &json_len);\n    json.current_depth = 0;\n    json.ptr = json.data;\n\n    /* Detect Unicode other than UTF-8 (see RFC 4627, Sec 3)\n     *\n     * CJSON can support any simple data type, hence only the first\n     * character is guaranteed to be ASCII (at worst: '\"'). This is\n     * still enough to detect whether the wrong encoding is in use. */\n    if (json_len >= 2 && (!json.data[0] || !json.data[1]))\n        luaL_error(l, \"JSON parser does not support UTF-16 or UTF-32\");\n\n    /* Ensure the temporary buffer can hold the entire string.\n     * This means we no longer need to do length checks since the decoded\n     * string must be smaller than the entire json string */\n    json.tmp = strbuf_new(json_len);\n\n    json_next_token(&json, &token);\n    json_process_value(l, &json, &token);\n\n    /* Ensure there is no more input left */\n    json_next_token(&json, &token);\n\n    if (token.type != T_END)\n        json_throw_parse_error(l, &json, \"the end\", &token);\n\n    strbuf_free(json.tmp);\n\n    return 1;\n}\n\n/* ===== INITIALISATION ===== */\n\n#if !defined(LUA_VERSION_NUM) || LUA_VERSION_NUM < 502\n/* Compatibility for Lua 5.1.\n *\n * luaL_setfuncs() is used to create a module table where the functions have\n * json_config_t as their first upvalue. Code borrowed from Lua 5.2 source. */\nstatic void luaL_setfuncs (lua_State *l, const luaL_Reg *reg, int nup)\n{\n    int i;\n\n    luaL_checkstack(l, nup, \"too many upvalues\");\n    for (; reg->name != NULL; reg++) {  /* fill the table with given functions */\n        for (i = 0; i < nup; i++)  /* copy upvalues to the top */\n            lua_pushvalue(l, -nup);\n        lua_pushcclosure(l, reg->func, nup);  /* closure with those upvalues */\n        lua_setfield(l, -(nup + 2), reg->name);\n    }\n    lua_pop(l, nup);  /* remove upvalues */\n}\n#endif\n\n/* Call target function in protected mode with all supplied args.\n * Assumes target function only returns a single non-nil value.\n * Convert and return thrown errors as: nil, \"error message\" */\nstatic int json_protect_conversion(lua_State *l)\n{\n    int err;\n\n    /* Deliberately throw an error for invalid arguments */\n    luaL_argcheck(l, lua_gettop(l) == 1, 1, \"expected 1 argument\");\n\n    /* pcall() the function stored as upvalue(1) */\n    lua_pushvalue(l, lua_upvalueindex(1));\n    lua_insert(l, 1);\n    err = lua_pcall(l, 1, 1, 0);\n    if (!err)\n        return 1;\n\n    if (err == LUA_ERRRUN) {\n        lua_pushnil(l);\n        lua_insert(l, -2);\n        return 2;\n    }\n\n    /* Since we are not using a custom error handler, the only remaining\n     * errors are memory related */\n    return luaL_error(l, \"Memory allocation error in CJSON protected call\");\n}\n\n/* Return cjson module table */\nstatic int lua_cjson_new(lua_State *l)\n{\n    luaL_Reg reg[] = {\n        { \"encode\", json_encode },\n        { \"decode\", json_decode },\n        { \"encode_sparse_array\", json_cfg_encode_sparse_array },\n        { \"encode_max_depth\", json_cfg_encode_max_depth },\n        { \"decode_max_depth\", json_cfg_decode_max_depth },\n        { \"encode_number_precision\", json_cfg_encode_number_precision },\n        { \"encode_keep_buffer\", json_cfg_encode_keep_buffer },\n        { \"encode_invalid_numbers\", json_cfg_encode_invalid_numbers },\n        { \"decode_invalid_numbers\", json_cfg_decode_invalid_numbers },\n        { \"new\", lua_cjson_new },\n        { NULL, NULL }\n    };\n\n    /* Initialise number conversions */\n    fpconv_init();\n\n    /* cjson module table */\n    lua_newtable(l);\n\n    /* Register functions with config data as upvalue */\n    json_create_config(l);\n    luaL_setfuncs(l, reg, 1);\n\n    /* Set cjson.null */\n    lua_pushlightuserdata(l, NULL);\n    lua_setfield(l, -2, \"null\");\n\n    /* Set module name / version fields */\n    lua_pushliteral(l, CJSON_MODNAME);\n    lua_setfield(l, -2, \"_NAME\");\n    lua_pushliteral(l, CJSON_VERSION);\n    lua_setfield(l, -2, \"_VERSION\");\n\n    return 1;\n}\n\n/* Return cjson.safe module table */\nstatic int lua_cjson_safe_new(lua_State *l)\n{\n    const char *func[] = { \"decode\", \"encode\", NULL };\n    int i;\n\n    lua_cjson_new(l);\n\n    /* Fix new() method */\n    lua_pushcfunction(l, lua_cjson_safe_new);\n    lua_setfield(l, -2, \"new\");\n\n    for (i = 0; func[i]; i++) {\n        lua_getfield(l, -1, func[i]);\n        lua_pushcclosure(l, json_protect_conversion, 1);\n        lua_setfield(l, -2, func[i]);\n    }\n\n    return 1;\n}\n\nint luaopen_cjson(lua_State *l)\n{\n    lua_cjson_new(l);\n\n#ifdef ENABLE_CJSON_GLOBAL\n    /* Register a global \"cjson\" table. */\n    lua_pushvalue(l, -1);\n    lua_setglobal(l, CJSON_MODNAME);\n#endif\n\n    /* Return cjson table */\n    return 1;\n}\n\nint luaopen_cjson_safe(lua_State *l)\n{\n    lua_cjson_safe_new(l);\n\n    /* Return cjson.safe table */\n    return 1;\n}\n\n/* vi:ai et sw=4 ts=4:\n */\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/deps/lua/src/lua_cmsgpack.c",
    "content": "#include <math.h>\n#include <stdlib.h>\n#include <stdint.h>\n#include <string.h>\n#include <assert.h>\n\n#include \"lua.h\"\n#include \"lauxlib.h\"\n\n#define LUACMSGPACK_NAME        \"cmsgpack\"\n#define LUACMSGPACK_SAFE_NAME   \"cmsgpack_safe\"\n#define LUACMSGPACK_VERSION     \"lua-cmsgpack 0.4.0\"\n#define LUACMSGPACK_COPYRIGHT   \"Copyright (C) 2012, Salvatore Sanfilippo\"\n#define LUACMSGPACK_DESCRIPTION \"MessagePack C implementation for Lua\"\n\n/* Allows a preprocessor directive to override MAX_NESTING */\n#ifndef LUACMSGPACK_MAX_NESTING\n    #define LUACMSGPACK_MAX_NESTING  16 /* Max tables nesting. */\n#endif\n\n/* Check if float or double can be an integer without loss of precision */\n#define IS_INT_TYPE_EQUIVALENT(x, T) (!isinf(x) && (T)(x) == (x))\n\n#define IS_INT64_EQUIVALENT(x) IS_INT_TYPE_EQUIVALENT(x, int64_t)\n#define IS_INT_EQUIVALENT(x) IS_INT_TYPE_EQUIVALENT(x, int)\n\n/* If size of pointer is equal to a 4 byte integer, we're on 32 bits. */\n#if UINTPTR_MAX == UINT_MAX\n    #define BITS_32 1\n#else\n    #define BITS_32 0\n#endif\n\n#if BITS_32\n    #define lua_pushunsigned(L, n) lua_pushnumber(L, n)\n#else\n    #define lua_pushunsigned(L, n) lua_pushinteger(L, n)\n#endif\n\n/* =============================================================================\n * MessagePack implementation and bindings for Lua 5.1/5.2.\n * Copyright(C) 2012 Salvatore Sanfilippo <antirez@gmail.com>\n *\n * http://github.com/antirez/lua-cmsgpack\n *\n * For MessagePack specification check the following web site:\n * http://wiki.msgpack.org/display/MSGPACK/Format+specification\n *\n * See Copyright Notice at the end of this file.\n *\n * CHANGELOG:\n * 19-Feb-2012 (ver 0.1.0): Initial release.\n * 20-Feb-2012 (ver 0.2.0): Tables encoding improved.\n * 20-Feb-2012 (ver 0.2.1): Minor bug fixing.\n * 20-Feb-2012 (ver 0.3.0): Module renamed lua-cmsgpack (was lua-msgpack).\n * 04-Apr-2014 (ver 0.3.1): Lua 5.2 support and minor bug fix.\n * 07-Apr-2014 (ver 0.4.0): Multiple pack/unpack, lua allocator, efficiency.\n * ========================================================================== */\n\n/* -------------------------- Endian conversion --------------------------------\n * We use it only for floats and doubles, all the other conversions performed\n * in an endian independent fashion. So the only thing we need is a function\n * that swaps a binary string if arch is little endian (and left it untouched\n * otherwise). */\n\n/* Reverse memory bytes if arch is little endian. Given the conceptual\n * simplicity of the Lua build system we prefer check for endianess at runtime.\n * The performance difference should be acceptable. */\nvoid memrevifle(void *ptr, size_t len) {\n    unsigned char   *p = (unsigned char *)ptr,\n                    *e = (unsigned char *)p+len-1,\n                    aux;\n    int test = 1;\n    unsigned char *testp = (unsigned char*) &test;\n\n    if (testp[0] == 0) return; /* Big endian, nothing to do. */\n    len /= 2;\n    while(len--) {\n        aux = *p;\n        *p = *e;\n        *e = aux;\n        p++;\n        e--;\n    }\n}\n\n/* ---------------------------- String buffer ----------------------------------\n * This is a simple implementation of string buffers. The only operation\n * supported is creating empty buffers and appending bytes to it.\n * The string buffer uses 2x preallocation on every realloc for O(N) append\n * behavior.  */\n\ntypedef struct mp_buf {\n    unsigned char *b;\n    size_t len, free;\n} mp_buf;\n\nvoid *mp_realloc(lua_State *L, void *target, size_t osize,size_t nsize) {\n    void *(*local_realloc) (void *, void *, size_t osize, size_t nsize) = NULL;\n    void *ud;\n\n    local_realloc = lua_getallocf(L, &ud);\n\n    return local_realloc(ud, target, osize, nsize);\n}\n\nmp_buf *mp_buf_new(lua_State *L) {\n    mp_buf *buf = NULL;\n\n    /* Old size = 0; new size = sizeof(*buf) */\n    buf = (mp_buf*)mp_realloc(L, NULL, 0, sizeof(*buf));\n\n    buf->b = NULL;\n    buf->len = buf->free = 0;\n    return buf;\n}\n\nvoid mp_buf_append(lua_State *L, mp_buf *buf, const unsigned char *s, size_t len) {\n    if (buf->free < len) {\n        size_t newsize = (buf->len+len)*2;\n\n        buf->b = (unsigned char*)mp_realloc(L, buf->b, buf->len + buf->free, newsize);\n        buf->free = newsize - buf->len;\n    }\n    memcpy(buf->b+buf->len,s,len);\n    buf->len += len;\n    buf->free -= len;\n}\n\nvoid mp_buf_free(lua_State *L, mp_buf *buf) {\n    mp_realloc(L, buf->b, buf->len + buf->free, 0); /* realloc to 0 = free */\n    mp_realloc(L, buf, sizeof(*buf), 0);\n}\n\n/* ---------------------------- String cursor ----------------------------------\n * This simple data structure is used for parsing. Basically you create a cursor\n * using a string pointer and a length, then it is possible to access the\n * current string position with cursor->p, check the remaining length\n * in cursor->left, and finally consume more string using\n * mp_cur_consume(cursor,len), to advance 'p' and subtract 'left'.\n * An additional field cursor->error is set to zero on initialization and can\n * be used to report errors. */\n\n#define MP_CUR_ERROR_NONE   0\n#define MP_CUR_ERROR_EOF    1   /* Not enough data to complete operation. */\n#define MP_CUR_ERROR_BADFMT 2   /* Bad data format */\n\ntypedef struct mp_cur {\n    const unsigned char *p;\n    size_t left;\n    int err;\n} mp_cur;\n\nvoid mp_cur_init(mp_cur *cursor, const unsigned char *s, size_t len) {\n    cursor->p = s;\n    cursor->left = len;\n    cursor->err = MP_CUR_ERROR_NONE;\n}\n\n#define mp_cur_consume(_c,_len) do { _c->p += _len; _c->left -= _len; } while(0)\n\n/* When there is not enough room we set an error in the cursor and return. This\n * is very common across the code so we have a macro to make the code look\n * a bit simpler. */\n#define mp_cur_need(_c,_len) do { \\\n    if (_c->left < _len) { \\\n        _c->err = MP_CUR_ERROR_EOF; \\\n        return; \\\n    } \\\n} while(0)\n\n/* ------------------------- Low level MP encoding -------------------------- */\n\nvoid mp_encode_bytes(lua_State *L, mp_buf *buf, const unsigned char *s, size_t len) {\n    unsigned char hdr[5];\n    int hdrlen;\n\n    if (len < 32) {\n        hdr[0] = 0xa0 | (len&0xff); /* fix raw */\n        hdrlen = 1;\n    } else if (len <= 0xff) {\n        hdr[0] = 0xd9;\n        hdr[1] = len;\n        hdrlen = 2;\n    } else if (len <= 0xffff) {\n        hdr[0] = 0xda;\n        hdr[1] = (len&0xff00)>>8;\n        hdr[2] = len&0xff;\n        hdrlen = 3;\n    } else {\n        hdr[0] = 0xdb;\n        hdr[1] = (len&0xff000000)>>24;\n        hdr[2] = (len&0xff0000)>>16;\n        hdr[3] = (len&0xff00)>>8;\n        hdr[4] = len&0xff;\n        hdrlen = 5;\n    }\n    mp_buf_append(L,buf,hdr,hdrlen);\n    mp_buf_append(L,buf,s,len);\n}\n\n/* we assume IEEE 754 internal format for single and double precision floats. */\nvoid mp_encode_double(lua_State *L, mp_buf *buf, double d) {\n    unsigned char b[9];\n    float f = d;\n\n    assert(sizeof(f) == 4 && sizeof(d) == 8);\n    if (d == (double)f) {\n        b[0] = 0xca;    /* float IEEE 754 */\n        memcpy(b+1,&f,4);\n        memrevifle(b+1,4);\n        mp_buf_append(L,buf,b,5);\n    } else if (sizeof(d) == 8) {\n        b[0] = 0xcb;    /* double IEEE 754 */\n        memcpy(b+1,&d,8);\n        memrevifle(b+1,8);\n        mp_buf_append(L,buf,b,9);\n    }\n}\n\nvoid mp_encode_int(lua_State *L, mp_buf *buf, int64_t n) {\n    unsigned char b[9];\n    int enclen;\n\n    if (n >= 0) {\n        if (n <= 127) {\n            b[0] = n & 0x7f;    /* positive fixnum */\n            enclen = 1;\n        } else if (n <= 0xff) {\n            b[0] = 0xcc;        /* uint 8 */\n            b[1] = n & 0xff;\n            enclen = 2;\n        } else if (n <= 0xffff) {\n            b[0] = 0xcd;        /* uint 16 */\n            b[1] = (n & 0xff00) >> 8;\n            b[2] = n & 0xff;\n            enclen = 3;\n        } else if (n <= 0xffffffffLL) {\n            b[0] = 0xce;        /* uint 32 */\n            b[1] = (n & 0xff000000) >> 24;\n            b[2] = (n & 0xff0000) >> 16;\n            b[3] = (n & 0xff00) >> 8;\n            b[4] = n & 0xff;\n            enclen = 5;\n        } else {\n            b[0] = 0xcf;        /* uint 64 */\n            b[1] = (n & 0xff00000000000000LL) >> 56;\n            b[2] = (n & 0xff000000000000LL) >> 48;\n            b[3] = (n & 0xff0000000000LL) >> 40;\n            b[4] = (n & 0xff00000000LL) >> 32;\n            b[5] = (n & 0xff000000) >> 24;\n            b[6] = (n & 0xff0000) >> 16;\n            b[7] = (n & 0xff00) >> 8;\n            b[8] = n & 0xff;\n            enclen = 9;\n        }\n    } else {\n        if (n >= -32) {\n            b[0] = ((signed char)n);   /* negative fixnum */\n            enclen = 1;\n        } else if (n >= -128) {\n            b[0] = 0xd0;        /* int 8 */\n            b[1] = n & 0xff;\n            enclen = 2;\n        } else if (n >= -32768) {\n            b[0] = 0xd1;        /* int 16 */\n            b[1] = (n & 0xff00) >> 8;\n            b[2] = n & 0xff;\n            enclen = 3;\n        } else if (n >= -2147483648LL) {\n            b[0] = 0xd2;        /* int 32 */\n            b[1] = (n & 0xff000000) >> 24;\n            b[2] = (n & 0xff0000) >> 16;\n            b[3] = (n & 0xff00) >> 8;\n            b[4] = n & 0xff;\n            enclen = 5;\n        } else {\n            b[0] = 0xd3;        /* int 64 */\n            b[1] = (n & 0xff00000000000000LL) >> 56;\n            b[2] = (n & 0xff000000000000LL) >> 48;\n            b[3] = (n & 0xff0000000000LL) >> 40;\n            b[4] = (n & 0xff00000000LL) >> 32;\n            b[5] = (n & 0xff000000) >> 24;\n            b[6] = (n & 0xff0000) >> 16;\n            b[7] = (n & 0xff00) >> 8;\n            b[8] = n & 0xff;\n            enclen = 9;\n        }\n    }\n    mp_buf_append(L,buf,b,enclen);\n}\n\nvoid mp_encode_array(lua_State *L, mp_buf *buf, int64_t n) {\n    unsigned char b[5];\n    int enclen;\n\n    if (n <= 15) {\n        b[0] = 0x90 | (n & 0xf);    /* fix array */\n        enclen = 1;\n    } else if (n <= 65535) {\n        b[0] = 0xdc;                /* array 16 */\n        b[1] = (n & 0xff00) >> 8;\n        b[2] = n & 0xff;\n        enclen = 3;\n    } else {\n        b[0] = 0xdd;                /* array 32 */\n        b[1] = (n & 0xff000000) >> 24;\n        b[2] = (n & 0xff0000) >> 16;\n        b[3] = (n & 0xff00) >> 8;\n        b[4] = n & 0xff;\n        enclen = 5;\n    }\n    mp_buf_append(L,buf,b,enclen);\n}\n\nvoid mp_encode_map(lua_State *L, mp_buf *buf, int64_t n) {\n    unsigned char b[5];\n    int enclen;\n\n    if (n <= 15) {\n        b[0] = 0x80 | (n & 0xf);    /* fix map */\n        enclen = 1;\n    } else if (n <= 65535) {\n        b[0] = 0xde;                /* map 16 */\n        b[1] = (n & 0xff00) >> 8;\n        b[2] = n & 0xff;\n        enclen = 3;\n    } else {\n        b[0] = 0xdf;                /* map 32 */\n        b[1] = (n & 0xff000000) >> 24;\n        b[2] = (n & 0xff0000) >> 16;\n        b[3] = (n & 0xff00) >> 8;\n        b[4] = n & 0xff;\n        enclen = 5;\n    }\n    mp_buf_append(L,buf,b,enclen);\n}\n\n/* --------------------------- Lua types encoding --------------------------- */\n\nvoid mp_encode_lua_string(lua_State *L, mp_buf *buf) {\n    size_t len;\n    const char *s;\n\n    s = lua_tolstring(L,-1,&len);\n    mp_encode_bytes(L,buf,(const unsigned char*)s,len);\n}\n\nvoid mp_encode_lua_bool(lua_State *L, mp_buf *buf) {\n    unsigned char b = lua_toboolean(L,-1) ? 0xc3 : 0xc2;\n    mp_buf_append(L,buf,&b,1);\n}\n\n/* Lua 5.3 has a built in 64-bit integer type */\nvoid mp_encode_lua_integer(lua_State *L, mp_buf *buf) {\n#if (LUA_VERSION_NUM < 503) && BITS_32\n    lua_Number i = lua_tonumber(L,-1);\n#else\n    lua_Integer i = lua_tointeger(L,-1);\n#endif\n    mp_encode_int(L, buf, (int64_t)i);\n}\n\n/* Lua 5.2 and lower only has 64-bit doubles, so we need to\n * detect if the double may be representable as an int\n * for Lua < 5.3 */\nvoid mp_encode_lua_number(lua_State *L, mp_buf *buf) {\n    lua_Number n = lua_tonumber(L,-1);\n\n    if (IS_INT64_EQUIVALENT(n)) {\n        mp_encode_lua_integer(L, buf);\n    } else {\n        mp_encode_double(L,buf,(double)n);\n    }\n}\n\nvoid mp_encode_lua_type(lua_State *L, mp_buf *buf, int level);\n\n/* Convert a lua table into a message pack list. */\nvoid mp_encode_lua_table_as_array(lua_State *L, mp_buf *buf, int level) {\n#if LUA_VERSION_NUM < 502\n    size_t len = lua_objlen(L,-1), j;\n#else\n    size_t len = lua_rawlen(L,-1), j;\n#endif\n\n    mp_encode_array(L,buf,len);\n    for (j = 1; j <= len; j++) {\n        lua_pushnumber(L,j);\n        lua_gettable(L,-2);\n        mp_encode_lua_type(L,buf,level+1);\n    }\n}\n\n/* Convert a lua table into a message pack key-value map. */\nvoid mp_encode_lua_table_as_map(lua_State *L, mp_buf *buf, int level) {\n    size_t len = 0;\n\n    /* First step: count keys into table. No other way to do it with the\n     * Lua API, we need to iterate a first time. Note that an alternative\n     * would be to do a single run, and then hack the buffer to insert the\n     * map opcodes for message pack. Too hackish for this lib. */\n    lua_pushnil(L);\n    while(lua_next(L,-2)) {\n        lua_pop(L,1); /* remove value, keep key for next iteration. */\n        len++;\n    }\n\n    /* Step two: actually encoding of the map. */\n    mp_encode_map(L,buf,len);\n    lua_pushnil(L);\n    while(lua_next(L,-2)) {\n        /* Stack: ... key value */\n        lua_pushvalue(L,-2); /* Stack: ... key value key */\n        mp_encode_lua_type(L,buf,level+1); /* encode key */\n        mp_encode_lua_type(L,buf,level+1); /* encode val */\n    }\n}\n\n/* Returns true if the Lua table on top of the stack is exclusively composed\n * of keys from numerical keys from 1 up to N, with N being the total number\n * of elements, without any hole in the middle. */\nint table_is_an_array(lua_State *L) {\n    int count = 0, max = 0;\n#if LUA_VERSION_NUM < 503\n    lua_Number n;\n#else\n    lua_Integer n;\n#endif\n\n    /* Stack top on function entry */\n    int stacktop;\n\n    stacktop = lua_gettop(L);\n\n    lua_pushnil(L);\n    while(lua_next(L,-2)) {\n        /* Stack: ... key value */\n        lua_pop(L,1); /* Stack: ... key */\n        /* The <= 0 check is valid here because we're comparing indexes. */\n#if LUA_VERSION_NUM < 503\n        if ((LUA_TNUMBER != lua_type(L,-1)) || (n = lua_tonumber(L, -1)) <= 0 ||\n            !IS_INT_EQUIVALENT(n))\n#else\n        if (!lua_isinteger(L,-1) || (n = lua_tointeger(L, -1)) <= 0)\n#endif\n        {\n            lua_settop(L, stacktop);\n            return 0;\n        }\n        max = (n > max ? n : max);\n        count++;\n    }\n    /* We have the total number of elements in \"count\". Also we have\n     * the max index encountered in \"max\". We can't reach this code\n     * if there are indexes <= 0. If you also note that there can not be\n     * repeated keys into a table, you have that if max==count you are sure\n     * that there are all the keys form 1 to count (both included). */\n    lua_settop(L, stacktop);\n    return max == count;\n}\n\n/* If the length operator returns non-zero, that is, there is at least\n * an object at key '1', we serialize to message pack list. Otherwise\n * we use a map. */\nvoid mp_encode_lua_table(lua_State *L, mp_buf *buf, int level) {\n    if (table_is_an_array(L))\n        mp_encode_lua_table_as_array(L,buf,level);\n    else\n        mp_encode_lua_table_as_map(L,buf,level);\n}\n\nvoid mp_encode_lua_null(lua_State *L, mp_buf *buf) {\n    unsigned char b[1];\n\n    b[0] = 0xc0;\n    mp_buf_append(L,buf,b,1);\n}\n\nvoid mp_encode_lua_type(lua_State *L, mp_buf *buf, int level) {\n    int t = lua_type(L,-1);\n\n    /* Limit the encoding of nested tables to a specified maximum depth, so that\n     * we survive when called against circular references in tables. */\n    if (t == LUA_TTABLE && level == LUACMSGPACK_MAX_NESTING) t = LUA_TNIL;\n    switch(t) {\n    case LUA_TSTRING: mp_encode_lua_string(L,buf); break;\n    case LUA_TBOOLEAN: mp_encode_lua_bool(L,buf); break;\n    case LUA_TNUMBER:\n    #if LUA_VERSION_NUM < 503\n        mp_encode_lua_number(L,buf); break;\n    #else\n        if (lua_isinteger(L, -1)) {\n            mp_encode_lua_integer(L, buf);\n        } else {\n            mp_encode_lua_number(L, buf);\n        }\n        break;\n    #endif\n    case LUA_TTABLE: mp_encode_lua_table(L,buf,level); break;\n    default: mp_encode_lua_null(L,buf); break;\n    }\n    lua_pop(L,1);\n}\n\n/*\n * Packs all arguments as a stream for multiple upacking later.\n * Returns error if no arguments provided.\n */\nint mp_pack(lua_State *L) {\n    int nargs = lua_gettop(L);\n    int i;\n    mp_buf *buf;\n\n    if (nargs == 0)\n        return luaL_argerror(L, 0, \"MessagePack pack needs input.\");\n\n    buf = mp_buf_new(L);\n    for(i = 1; i <= nargs; i++) {\n        /* Copy argument i to top of stack for _encode processing;\n         * the encode function pops it from the stack when complete. */\n        lua_pushvalue(L, i);\n\n        mp_encode_lua_type(L,buf,0);\n\n        lua_pushlstring(L,(char*)buf->b,buf->len);\n\n        /* Reuse the buffer for the next operation by\n         * setting its free count to the total buffer size\n         * and the current position to zero. */\n        buf->free += buf->len;\n        buf->len = 0;\n    }\n    mp_buf_free(L, buf);\n\n    /* Concatenate all nargs buffers together */\n    lua_concat(L, nargs);\n    return 1;\n}\n\n/* ------------------------------- Decoding --------------------------------- */\n\nvoid mp_decode_to_lua_type(lua_State *L, mp_cur *c);\n\nvoid mp_decode_to_lua_array(lua_State *L, mp_cur *c, size_t len) {\n    assert(len <= UINT_MAX);\n    int index = 1;\n\n    lua_newtable(L);\n    while(len--) {\n        lua_pushnumber(L,index++);\n        mp_decode_to_lua_type(L,c);\n        if (c->err) return;\n        lua_settable(L,-3);\n    }\n}\n\nvoid mp_decode_to_lua_hash(lua_State *L, mp_cur *c, size_t len) {\n    assert(len <= UINT_MAX);\n    lua_newtable(L);\n    while(len--) {\n        mp_decode_to_lua_type(L,c); /* key */\n        if (c->err) return;\n        mp_decode_to_lua_type(L,c); /* value */\n        if (c->err) return;\n        lua_settable(L,-3);\n    }\n}\n\n/* Decode a Message Pack raw object pointed by the string cursor 'c' to\n * a Lua type, that is left as the only result on the stack. */\nvoid mp_decode_to_lua_type(lua_State *L, mp_cur *c) {\n    mp_cur_need(c,1);\n\n    /* If we return more than 18 elements, we must resize the stack to\n     * fit all our return values.  But, there is no way to\n     * determine how many objects a msgpack will unpack to up front, so\n     * we request a +1 larger stack on each iteration (noop if stack is\n     * big enough, and when stack does require resize it doubles in size) */\n    luaL_checkstack(L, 1,\n        \"too many return values at once; \"\n        \"use unpack_one or unpack_limit instead.\");\n\n    switch(c->p[0]) {\n    case 0xcc:  /* uint 8 */\n        mp_cur_need(c,2);\n        lua_pushunsigned(L,c->p[1]);\n        mp_cur_consume(c,2);\n        break;\n    case 0xd0:  /* int 8 */\n        mp_cur_need(c,2);\n        lua_pushinteger(L,(signed char)c->p[1]);\n        mp_cur_consume(c,2);\n        break;\n    case 0xcd:  /* uint 16 */\n        mp_cur_need(c,3);\n        lua_pushunsigned(L,\n            (c->p[1] << 8) |\n             c->p[2]);\n        mp_cur_consume(c,3);\n        break;\n    case 0xd1:  /* int 16 */\n        mp_cur_need(c,3);\n        lua_pushinteger(L,(int16_t)\n            (c->p[1] << 8) |\n             c->p[2]);\n        mp_cur_consume(c,3);\n        break;\n    case 0xce:  /* uint 32 */\n        mp_cur_need(c,5);\n        lua_pushunsigned(L,\n            ((uint32_t)c->p[1] << 24) |\n            ((uint32_t)c->p[2] << 16) |\n            ((uint32_t)c->p[3] << 8) |\n             (uint32_t)c->p[4]);\n        mp_cur_consume(c,5);\n        break;\n    case 0xd2:  /* int 32 */\n        mp_cur_need(c,5);\n        lua_pushinteger(L,\n            ((int32_t)c->p[1] << 24) |\n            ((int32_t)c->p[2] << 16) |\n            ((int32_t)c->p[3] << 8) |\n             (int32_t)c->p[4]);\n        mp_cur_consume(c,5);\n        break;\n    case 0xcf:  /* uint 64 */\n        mp_cur_need(c,9);\n        lua_pushunsigned(L,\n            ((uint64_t)c->p[1] << 56) |\n            ((uint64_t)c->p[2] << 48) |\n            ((uint64_t)c->p[3] << 40) |\n            ((uint64_t)c->p[4] << 32) |\n            ((uint64_t)c->p[5] << 24) |\n            ((uint64_t)c->p[6] << 16) |\n            ((uint64_t)c->p[7] << 8) |\n             (uint64_t)c->p[8]);\n        mp_cur_consume(c,9);\n        break;\n    case 0xd3:  /* int 64 */\n        mp_cur_need(c,9);\n#if LUA_VERSION_NUM < 503\n        lua_pushnumber(L,\n#else\n        lua_pushinteger(L,\n#endif\n            ((int64_t)c->p[1] << 56) |\n            ((int64_t)c->p[2] << 48) |\n            ((int64_t)c->p[3] << 40) |\n            ((int64_t)c->p[4] << 32) |\n            ((int64_t)c->p[5] << 24) |\n            ((int64_t)c->p[6] << 16) |\n            ((int64_t)c->p[7] << 8) |\n             (int64_t)c->p[8]);\n        mp_cur_consume(c,9);\n        break;\n    case 0xc0:  /* nil */\n        lua_pushnil(L);\n        mp_cur_consume(c,1);\n        break;\n    case 0xc3:  /* true */\n        lua_pushboolean(L,1);\n        mp_cur_consume(c,1);\n        break;\n    case 0xc2:  /* false */\n        lua_pushboolean(L,0);\n        mp_cur_consume(c,1);\n        break;\n    case 0xca:  /* float */\n        mp_cur_need(c,5);\n        assert(sizeof(float) == 4);\n        {\n            float f;\n            memcpy(&f,c->p+1,4);\n            memrevifle(&f,4);\n            lua_pushnumber(L,f);\n            mp_cur_consume(c,5);\n        }\n        break;\n    case 0xcb:  /* double */\n        mp_cur_need(c,9);\n        assert(sizeof(double) == 8);\n        {\n            double d;\n            memcpy(&d,c->p+1,8);\n            memrevifle(&d,8);\n            lua_pushnumber(L,d);\n            mp_cur_consume(c,9);\n        }\n        break;\n    case 0xd9:  /* raw 8 */\n        mp_cur_need(c,2);\n        {\n            size_t l = c->p[1];\n            mp_cur_need(c,2+l);\n            lua_pushlstring(L,(char*)c->p+2,l);\n            mp_cur_consume(c,2+l);\n        }\n        break;\n    case 0xda:  /* raw 16 */\n        mp_cur_need(c,3);\n        {\n            size_t l = (c->p[1] << 8) | c->p[2];\n            mp_cur_need(c,3+l);\n            lua_pushlstring(L,(char*)c->p+3,l);\n            mp_cur_consume(c,3+l);\n        }\n        break;\n    case 0xdb:  /* raw 32 */\n        mp_cur_need(c,5);\n        {\n            size_t l = ((size_t)c->p[1] << 24) |\n                       ((size_t)c->p[2] << 16) |\n                       ((size_t)c->p[3] << 8) |\n                       (size_t)c->p[4];\n            mp_cur_consume(c,5);\n            mp_cur_need(c,l);\n            lua_pushlstring(L,(char*)c->p,l);\n            mp_cur_consume(c,l);\n        }\n        break;\n    case 0xdc:  /* array 16 */\n        mp_cur_need(c,3);\n        {\n            size_t l = (c->p[1] << 8) | c->p[2];\n            mp_cur_consume(c,3);\n            mp_decode_to_lua_array(L,c,l);\n        }\n        break;\n    case 0xdd:  /* array 32 */\n        mp_cur_need(c,5);\n        {\n            size_t l = ((size_t)c->p[1] << 24) |\n                       ((size_t)c->p[2] << 16) |\n                       ((size_t)c->p[3] << 8) |\n                       (size_t)c->p[4];\n            mp_cur_consume(c,5);\n            mp_decode_to_lua_array(L,c,l);\n        }\n        break;\n    case 0xde:  /* map 16 */\n        mp_cur_need(c,3);\n        {\n            size_t l = (c->p[1] << 8) | c->p[2];\n            mp_cur_consume(c,3);\n            mp_decode_to_lua_hash(L,c,l);\n        }\n        break;\n    case 0xdf:  /* map 32 */\n        mp_cur_need(c,5);\n        {\n            size_t l = ((size_t)c->p[1] << 24) |\n                       ((size_t)c->p[2] << 16) |\n                       ((size_t)c->p[3] << 8) |\n                       (size_t)c->p[4];\n            mp_cur_consume(c,5);\n            mp_decode_to_lua_hash(L,c,l);\n        }\n        break;\n    default:    /* types that can't be idenitified by first byte value. */\n        if ((c->p[0] & 0x80) == 0) {   /* positive fixnum */\n            lua_pushunsigned(L,c->p[0]);\n            mp_cur_consume(c,1);\n        } else if ((c->p[0] & 0xe0) == 0xe0) {  /* negative fixnum */\n            lua_pushinteger(L,(signed char)c->p[0]);\n            mp_cur_consume(c,1);\n        } else if ((c->p[0] & 0xe0) == 0xa0) {  /* fix raw */\n            size_t l = c->p[0] & 0x1f;\n            mp_cur_need(c,1+l);\n            lua_pushlstring(L,(char*)c->p+1,l);\n            mp_cur_consume(c,1+l);\n        } else if ((c->p[0] & 0xf0) == 0x90) {  /* fix map */\n            size_t l = c->p[0] & 0xf;\n            mp_cur_consume(c,1);\n            mp_decode_to_lua_array(L,c,l);\n        } else if ((c->p[0] & 0xf0) == 0x80) {  /* fix map */\n            size_t l = c->p[0] & 0xf;\n            mp_cur_consume(c,1);\n            mp_decode_to_lua_hash(L,c,l);\n        } else {\n            c->err = MP_CUR_ERROR_BADFMT;\n        }\n    }\n}\n\nint mp_unpack_full(lua_State *L, int limit, int offset) {\n    size_t len;\n    const char *s;\n    mp_cur c;\n    int cnt; /* Number of objects unpacked */\n    int decode_all = (!limit && !offset);\n\n    s = luaL_checklstring(L,1,&len); /* if no match, exits */\n\n    if (offset < 0 || limit < 0) /* requesting negative off or lim is invalid */\n        return luaL_error(L,\n            \"Invalid request to unpack with offset of %d and limit of %d.\",\n            offset, len);\n    else if (offset > len)\n        return luaL_error(L,\n            \"Start offset %d greater than input length %d.\", offset, len);\n\n    if (decode_all) limit = INT_MAX;\n\n    mp_cur_init(&c,(const unsigned char *)s+offset,len-offset);\n\n    /* We loop over the decode because this could be a stream\n     * of multiple top-level values serialized together */\n    for(cnt = 0; c.left > 0 && cnt < limit; cnt++) {\n        mp_decode_to_lua_type(L,&c);\n\n        if (c.err == MP_CUR_ERROR_EOF) {\n            return luaL_error(L,\"Missing bytes in input.\");\n        } else if (c.err == MP_CUR_ERROR_BADFMT) {\n            return luaL_error(L,\"Bad data format in input.\");\n        }\n    }\n\n    if (!decode_all) {\n        /* c->left is the remaining size of the input buffer.\n         * subtract the entire buffer size from the unprocessed size\n         * to get our next start offset */\n        int offset = len - c.left;\n        /* Return offset -1 when we have have processed the entire buffer. */\n        lua_pushinteger(L, c.left == 0 ? -1 : offset);\n        /* Results are returned with the arg elements still\n         * in place. Lua takes care of only returning\n         * elements above the args for us.\n         * In this case, we have one arg on the stack\n         * for this function, so we insert our first return\n         * value at position 2. */\n        lua_insert(L, 2);\n        cnt += 1; /* increase return count by one to make room for offset */\n    }\n\n    return cnt;\n}\n\nint mp_unpack(lua_State *L) {\n    return mp_unpack_full(L, 0, 0);\n}\n\nint mp_unpack_one(lua_State *L) {\n    int offset = luaL_optinteger(L, 2, 0);\n    /* Variable pop because offset may not exist */\n    lua_pop(L, lua_gettop(L)-1);\n    return mp_unpack_full(L, 1, offset);\n}\n\nint mp_unpack_limit(lua_State *L) {\n    int limit = luaL_checkinteger(L, 2);\n    int offset = luaL_optinteger(L, 3, 0);\n    /* Variable pop because offset may not exist */\n    lua_pop(L, lua_gettop(L)-1);\n\n    return mp_unpack_full(L, limit, offset);\n}\n\nint mp_safe(lua_State *L) {\n    int argc, err, total_results;\n\n    argc = lua_gettop(L);\n\n    /* This adds our function to the bottom of the stack\n     * (the \"call this function\" position) */\n    lua_pushvalue(L, lua_upvalueindex(1));\n    lua_insert(L, 1);\n\n    err = lua_pcall(L, argc, LUA_MULTRET, 0);\n    total_results = lua_gettop(L);\n\n    if (!err) {\n        return total_results;\n    } else {\n        lua_pushnil(L);\n        lua_insert(L,-2);\n        return 2;\n    }\n}\n\n/* -------------------------------------------------------------------------- */\nconst struct luaL_Reg cmds[] = {\n    {\"pack\", mp_pack},\n    {\"unpack\", mp_unpack},\n    {\"unpack_one\", mp_unpack_one},\n    {\"unpack_limit\", mp_unpack_limit},\n    {0}\n};\n\nint luaopen_create(lua_State *L) {\n    int i;\n    /* Manually construct our module table instead of\n     * relying on _register or _newlib */\n    lua_newtable(L);\n\n    for (i = 0; i < (sizeof(cmds)/sizeof(*cmds) - 1); i++) {\n        lua_pushcfunction(L, cmds[i].func);\n        lua_setfield(L, -2, cmds[i].name);\n    }\n\n    /* Add metadata */\n    lua_pushliteral(L, LUACMSGPACK_NAME);\n    lua_setfield(L, -2, \"_NAME\");\n    lua_pushliteral(L, LUACMSGPACK_VERSION);\n    lua_setfield(L, -2, \"_VERSION\");\n    lua_pushliteral(L, LUACMSGPACK_COPYRIGHT);\n    lua_setfield(L, -2, \"_COPYRIGHT\");\n    lua_pushliteral(L, LUACMSGPACK_DESCRIPTION);\n    lua_setfield(L, -2, \"_DESCRIPTION\");\n    return 1;\n}\n\nLUALIB_API int luaopen_cmsgpack(lua_State *L) {\n    luaopen_create(L);\n\n#if LUA_VERSION_NUM < 502\n    /* Register name globally for 5.1 */\n    lua_pushvalue(L, -1);\n    lua_setglobal(L, LUACMSGPACK_NAME);\n#endif\n\n    return 1;\n}\n\nLUALIB_API int luaopen_cmsgpack_safe(lua_State *L) {\n    int i;\n\n    luaopen_cmsgpack(L);\n\n    /* Wrap all functions in the safe handler */\n    for (i = 0; i < (sizeof(cmds)/sizeof(*cmds) - 1); i++) {\n        lua_getfield(L, -1, cmds[i].name);\n        lua_pushcclosure(L, mp_safe, 1);\n        lua_setfield(L, -2, cmds[i].name);\n    }\n\n#if LUA_VERSION_NUM < 502\n    /* Register name globally for 5.1 */\n    lua_pushvalue(L, -1);\n    lua_setglobal(L, LUACMSGPACK_SAFE_NAME);\n#endif\n\n    return 1;\n}\n\n/******************************************************************************\n* Copyright (C) 2012 Salvatore Sanfilippo.  All rights reserved.\n*\n* Permission is hereby granted, free of charge, to any person obtaining\n* a copy of this software and associated documentation files (the\n* \"Software\"), to deal in the Software without restriction, including\n* without limitation the rights to use, copy, modify, merge, publish,\n* distribute, sublicense, and/or sell copies of the Software, and to\n* permit persons to whom the Software is furnished to do so, subject to\n* the following conditions:\n*\n* The above copyright notice and this permission notice shall be\n* included in all copies or substantial portions of the Software.\n*\n* THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND,\n* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\n* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.\n* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY\n* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,\n* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE\n* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n******************************************************************************/\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/deps/lua/src/lua_struct.c",
    "content": "/*\n** {======================================================\n** Library for packing/unpacking structures.\n** $Id: struct.c,v 1.4 2012/07/04 18:54:29 roberto Exp $\n** See Copyright Notice at the end of this file\n** =======================================================\n*/\n/*\n** Valid formats:\n** > - big endian\n** < - little endian\n** ![num] - alignment\n** x - pading\n** b/B - signed/unsigned byte\n** h/H - signed/unsigned short\n** l/L - signed/unsigned long\n** T   - size_t\n** i/In - signed/unsigned integer with size `n' (default is size of int)\n** cn - sequence of `n' chars (from/to a string); when packing, n==0 means\n        the whole string; when unpacking, n==0 means use the previous\n        read number as the string length\n** s - zero-terminated string\n** f - float\n** d - double\n** ' ' - ignored\n*/\n\n\n#include <assert.h>\n#include <ctype.h>\n#include <limits.h>\n#include <stddef.h>\n#include <string.h>\n\n\n#include \"lua.h\"\n#include \"lauxlib.h\"\n\n\n#if (LUA_VERSION_NUM >= 502)\n\n#define luaL_register(L,n,f)\tluaL_newlib(L,f)\n\n#endif\n\n\n/* basic integer type */\n#if !defined(STRUCT_INT)\n#define STRUCT_INT\tlong\n#endif\n\ntypedef STRUCT_INT Inttype;\n\n/* corresponding unsigned version */\ntypedef unsigned STRUCT_INT Uinttype;\n\n\n/* maximum size (in bytes) for integral types */\n#define MAXINTSIZE\t32\n\n/* is 'x' a power of 2? */\n#define isp2(x)\t\t((x) > 0 && ((x) & ((x) - 1)) == 0)\n\n/* dummy structure to get alignment requirements */\nstruct cD {\n  char c;\n  double d;\n};\n\n\n#define PADDING\t\t(sizeof(struct cD) - sizeof(double))\n#define MAXALIGN  \t(PADDING > sizeof(int) ? PADDING : sizeof(int))\n\n\n/* endian options */\n#define BIG\t0\n#define LITTLE\t1\n\n\nstatic union {\n  int dummy;\n  char endian;\n} const native = {1};\n\n\ntypedef struct Header {\n  int endian;\n  int align;\n} Header;\n\n\nstatic int getnum (lua_State *L, const char **fmt, int df) {\n  if (!isdigit(**fmt))  /* no number? */\n    return df;  /* return default value */\n  else {\n    int a = 0;\n    do {\n      if (a > (INT_MAX / 10) || a * 10 > (INT_MAX - (**fmt - '0')))\n        luaL_error(L, \"integral size overflow\");\n      a = a*10 + *((*fmt)++) - '0';\n    } while (isdigit(**fmt));\n    return a;\n  }\n}\n\n\n#define defaultoptions(h)\t((h)->endian = native.endian, (h)->align = 1)\n\n\n\nstatic size_t optsize (lua_State *L, char opt, const char **fmt) {\n  switch (opt) {\n    case 'B': case 'b': return sizeof(char);\n    case 'H': case 'h': return sizeof(short);\n    case 'L': case 'l': return sizeof(long);\n    case 'T': return sizeof(size_t);\n    case 'f':  return sizeof(float);\n    case 'd':  return sizeof(double);\n    case 'x': return 1;\n    case 'c': return getnum(L, fmt, 1);\n    case 'i': case 'I': {\n      int sz = getnum(L, fmt, sizeof(int));\n      if (sz > MAXINTSIZE)\n        luaL_error(L, \"integral size %d is larger than limit of %d\",\n                       sz, MAXINTSIZE);\n      return sz;\n    }\n    default: return 0;  /* other cases do not need alignment */\n  }\n}\n\n\n/*\n** return number of bytes needed to align an element of size 'size'\n** at current position 'len'\n*/\nstatic int gettoalign (size_t len, Header *h, int opt, size_t size) {\n  if (size == 0 || opt == 'c') return 0;\n  if (size > (size_t)h->align)\n    size = h->align;  /* respect max. alignment */\n  return (size - (len & (size - 1))) & (size - 1);\n}\n\n\n/*\n** options to control endianess and alignment\n*/\nstatic void controloptions (lua_State *L, int opt, const char **fmt,\n                            Header *h) {\n  switch (opt) {\n    case  ' ': return;  /* ignore white spaces */\n    case '>': h->endian = BIG; return;\n    case '<': h->endian = LITTLE; return;\n    case '!': {\n      int a = getnum(L, fmt, MAXALIGN);\n      if (!isp2(a))\n        luaL_error(L, \"alignment %d is not a power of 2\", a);\n      h->align = a;\n      return;\n    }\n    default: {\n      const char *msg = lua_pushfstring(L, \"invalid format option '%c'\", opt);\n      luaL_argerror(L, 1, msg);\n    }\n  }\n}\n\n\nstatic void putinteger (lua_State *L, luaL_Buffer *b, int arg, int endian,\n                        int size) {\n  lua_Number n = luaL_checknumber(L, arg);\n  Uinttype value;\n  char buff[MAXINTSIZE];\n  if (n < 0)\n    value = (Uinttype)(Inttype)n;\n  else\n    value = (Uinttype)n;\n  if (endian == LITTLE) {\n    int i;\n    for (i = 0; i < size; i++) {\n      buff[i] = (value & 0xff);\n      value >>= 8;\n    }\n  }\n  else {\n    int i;\n    for (i = size - 1; i >= 0; i--) {\n      buff[i] = (value & 0xff);\n      value >>= 8;\n    }\n  }\n  luaL_addlstring(b, buff, size);\n}\n\n\nstatic void correctbytes (char *b, int size, int endian) {\n  if (endian != native.endian) {\n    int i = 0;\n    while (i < --size) {\n      char temp = b[i];\n      b[i++] = b[size];\n      b[size] = temp;\n    }\n  }\n}\n\n\nstatic int b_pack (lua_State *L) {\n  luaL_Buffer b;\n  const char *fmt = luaL_checkstring(L, 1);\n  Header h;\n  int arg = 2;\n  size_t totalsize = 0;\n  defaultoptions(&h);\n  lua_pushnil(L);  /* mark to separate arguments from string buffer */\n  luaL_buffinit(L, &b);\n  while (*fmt != '\\0') {\n    int opt = *fmt++;\n    size_t size = optsize(L, opt, &fmt);\n    int toalign = gettoalign(totalsize, &h, opt, size);\n    totalsize += toalign;\n    while (toalign-- > 0) luaL_addchar(&b, '\\0');\n    switch (opt) {\n      case 'b': case 'B': case 'h': case 'H':\n      case 'l': case 'L': case 'T': case 'i': case 'I': {  /* integer types */\n        putinteger(L, &b, arg++, h.endian, size);\n        break;\n      }\n      case 'x': {\n        luaL_addchar(&b, '\\0');\n        break;\n      }\n      case 'f': {\n        float f = (float)luaL_checknumber(L, arg++);\n        correctbytes((char *)&f, size, h.endian);\n        luaL_addlstring(&b, (char *)&f, size);\n        break;\n      }\n      case 'd': {\n        double d = luaL_checknumber(L, arg++);\n        correctbytes((char *)&d, size, h.endian);\n        luaL_addlstring(&b, (char *)&d, size);\n        break;\n      }\n      case 'c': case 's': {\n        size_t l;\n        const char *s = luaL_checklstring(L, arg++, &l);\n        if (size == 0) size = l;\n        luaL_argcheck(L, l >= (size_t)size, arg, \"string too short\");\n        luaL_addlstring(&b, s, size);\n        if (opt == 's') {\n          luaL_addchar(&b, '\\0');  /* add zero at the end */\n          size++;\n        }\n        break;\n      }\n      default: controloptions(L, opt, &fmt, &h);\n    }\n    totalsize += size;\n  }\n  luaL_pushresult(&b);\n  return 1;\n}\n\n\nstatic lua_Number getinteger (const char *buff, int endian,\n                        int issigned, int size) {\n  Uinttype l = 0;\n  int i;\n  if (endian == BIG) {\n    for (i = 0; i < size; i++) {\n      l <<= 8;\n      l |= (Uinttype)(unsigned char)buff[i];\n    }\n  }\n  else {\n    for (i = size - 1; i >= 0; i--) {\n      l <<= 8;\n      l |= (Uinttype)(unsigned char)buff[i];\n    }\n  }\n  if (!issigned)\n    return (lua_Number)l;\n  else {  /* signed format */\n    Uinttype mask = (Uinttype)(~((Uinttype)0)) << (size*8 - 1);\n    if (l & mask)  /* negative value? */\n      l |= mask;  /* signal extension */\n    return (lua_Number)(Inttype)l;\n  }\n}\n\n\nstatic int b_unpack (lua_State *L) {\n  Header h;\n  const char *fmt = luaL_checkstring(L, 1);\n  size_t ld;\n  const char *data = luaL_checklstring(L, 2, &ld);\n  size_t pos = luaL_optinteger(L, 3, 1) - 1;\n  defaultoptions(&h);\n  lua_settop(L, 2);\n  while (*fmt) {\n    int opt = *fmt++;\n    size_t size = optsize(L, opt, &fmt);\n    pos += gettoalign(pos, &h, opt, size);\n    luaL_argcheck(L, pos+size <= ld, 2, \"data string too short\");\n    luaL_checkstack(L, 1, \"too many results\");\n    switch (opt) {\n      case 'b': case 'B': case 'h': case 'H':\n      case 'l': case 'L': case 'T': case 'i':  case 'I': {  /* integer types */\n        int issigned = islower(opt);\n        lua_Number res = getinteger(data+pos, h.endian, issigned, size);\n        lua_pushnumber(L, res);\n        break;\n      }\n      case 'x': {\n        break;\n      }\n      case 'f': {\n        float f;\n        memcpy(&f, data+pos, size);\n        correctbytes((char *)&f, sizeof(f), h.endian);\n        lua_pushnumber(L, f);\n        break;\n      }\n      case 'd': {\n        double d;\n        memcpy(&d, data+pos, size);\n        correctbytes((char *)&d, sizeof(d), h.endian);\n        lua_pushnumber(L, d);\n        break;\n      }\n      case 'c': {\n        if (size == 0) {\n          if (!lua_isnumber(L, -1))\n            luaL_error(L, \"format `c0' needs a previous size\");\n          size = lua_tonumber(L, -1);\n          lua_pop(L, 1);\n          luaL_argcheck(L, pos+size <= ld, 2, \"data string too short\");\n        }\n        lua_pushlstring(L, data+pos, size);\n        break;\n      }\n      case 's': {\n        const char *e = (const char *)memchr(data+pos, '\\0', ld - pos);\n        if (e == NULL)\n          luaL_error(L, \"unfinished string in data\");\n        size = (e - (data+pos)) + 1;\n        lua_pushlstring(L, data+pos, size - 1);\n        break;\n      }\n      default: controloptions(L, opt, &fmt, &h);\n    }\n    pos += size;\n  }\n  lua_pushinteger(L, pos + 1);\n  return lua_gettop(L) - 2;\n}\n\n\nstatic int b_size (lua_State *L) {\n  Header h;\n  const char *fmt = luaL_checkstring(L, 1);\n  size_t pos = 0;\n  defaultoptions(&h);\n  while (*fmt) {\n    int opt = *fmt++;\n    size_t size = optsize(L, opt, &fmt);\n    pos += gettoalign(pos, &h, opt, size);\n    if (opt == 's')\n      luaL_argerror(L, 1, \"option 's' has no fixed size\");\n    else if (opt == 'c' && size == 0)\n      luaL_argerror(L, 1, \"option 'c0' has no fixed size\");\n    if (!isalnum(opt))\n      controloptions(L, opt, &fmt, &h);\n    pos += size;\n  }\n  lua_pushinteger(L, pos);\n  return 1;\n}\n\n/* }====================================================== */\n\n\n\nstatic const struct luaL_Reg thislib[] = {\n  {\"pack\", b_pack},\n  {\"unpack\", b_unpack},\n  {\"size\", b_size},\n  {NULL, NULL}\n};\n\n\nLUALIB_API int luaopen_struct (lua_State *L);\n\nLUALIB_API int luaopen_struct (lua_State *L) {\n  luaL_register(L, \"struct\", thislib);\n  return 1;\n}\n\n\n/******************************************************************************\n* Copyright (C) 2010-2012 Lua.org, PUC-Rio.  All rights reserved.\n*\n* Permission is hereby granted, free of charge, to any person obtaining\n* a copy of this software and associated documentation files (the\n* \"Software\"), to deal in the Software without restriction, including\n* without limitation the rights to use, copy, modify, merge, publish,\n* distribute, sublicense, and/or sell copies of the Software, and to\n* permit persons to whom the Software is furnished to do so, subject to\n* the following conditions:\n*\n* The above copyright notice and this permission notice shall be\n* included in all copies or substantial portions of the Software.\n*\n* THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND,\n* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\n* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.\n* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY\n* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,\n* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE\n* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n******************************************************************************/\n\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/deps/lua/src/luac.c",
    "content": "/*\n** $Id: luac.c,v 1.54 2006/06/02 17:37:11 lhf Exp $\n** Lua compiler (saves bytecodes to files; also list bytecodes)\n** See Copyright Notice in lua.h\n*/\n\n#include <errno.h>\n#include <stdio.h>\n#include <stdlib.h>\n#include <string.h>\n\n#define luac_c\n#define LUA_CORE\n\n#include \"lua.h\"\n#include \"lauxlib.h\"\n\n#include \"ldo.h\"\n#include \"lfunc.h\"\n#include \"lmem.h\"\n#include \"lobject.h\"\n#include \"lopcodes.h\"\n#include \"lstring.h\"\n#include \"lundump.h\"\n\n#define PROGNAME\t\"luac\"\t\t/* default program name */\n#define\tOUTPUT\t\tPROGNAME \".out\"\t/* default output file */\n\nstatic int listing=0;\t\t\t/* list bytecodes? */\nstatic int dumping=1;\t\t\t/* dump bytecodes? */\nstatic int stripping=0;\t\t\t/* strip debug information? */\nstatic char Output[]={ OUTPUT };\t/* default output file name */\nstatic const char* output=Output;\t/* actual output file name */\nstatic const char* progname=PROGNAME;\t/* actual program name */\n\nstatic void fatal(const char* message)\n{\n fprintf(stderr,\"%s: %s\\n\",progname,message);\n exit(EXIT_FAILURE);\n}\n\nstatic void cannot(const char* what)\n{\n fprintf(stderr,\"%s: cannot %s %s: %s\\n\",progname,what,output,strerror(errno));\n exit(EXIT_FAILURE);\n}\n\nstatic void usage(const char* message)\n{\n if (*message=='-')\n  fprintf(stderr,\"%s: unrecognized option \" LUA_QS \"\\n\",progname,message);\n else\n  fprintf(stderr,\"%s: %s\\n\",progname,message);\n fprintf(stderr,\n \"usage: %s [options] [filenames].\\n\"\n \"Available options are:\\n\"\n \"  -        process stdin\\n\"\n \"  -l       list\\n\"\n \"  -o name  output to file \" LUA_QL(\"name\") \" (default is \\\"%s\\\")\\n\"\n \"  -p       parse only\\n\"\n \"  -s       strip debug information\\n\"\n \"  -v       show version information\\n\"\n \"  --       stop handling options\\n\",\n progname,Output);\n exit(EXIT_FAILURE);\n}\n\n#define\tIS(s)\t(strcmp(argv[i],s)==0)\n\nstatic int doargs(int argc, char* argv[])\n{\n int i;\n int version=0;\n if (argv[0]!=NULL && *argv[0]!=0) progname=argv[0];\n for (i=1; i<argc; i++)\n {\n  if (*argv[i]!='-')\t\t\t/* end of options; keep it */\n   break;\n  else if (IS(\"--\"))\t\t\t/* end of options; skip it */\n  {\n   ++i;\n   if (version) ++version;\n   break;\n  }\n  else if (IS(\"-\"))\t\t\t/* end of options; use stdin */\n   break;\n  else if (IS(\"-l\"))\t\t\t/* list */\n   ++listing;\n  else if (IS(\"-o\"))\t\t\t/* output file */\n  {\n   output=argv[++i];\n   if (output==NULL || *output==0) usage(LUA_QL(\"-o\") \" needs argument\");\n   if (IS(\"-\")) output=NULL;\n  }\n  else if (IS(\"-p\"))\t\t\t/* parse only */\n   dumping=0;\n  else if (IS(\"-s\"))\t\t\t/* strip debug information */\n   stripping=1;\n  else if (IS(\"-v\"))\t\t\t/* show version */\n   ++version;\n  else\t\t\t\t\t/* unknown option */\n   usage(argv[i]);\n }\n if (i==argc && (listing || !dumping))\n {\n  dumping=0;\n  argv[--i]=Output;\n }\n if (version)\n {\n  printf(\"%s  %s\\n\",LUA_RELEASE,LUA_COPYRIGHT);\n  if (version==argc-1) exit(EXIT_SUCCESS);\n }\n return i;\n}\n\n#define toproto(L,i) (clvalue(L->top+(i))->l.p)\n\nstatic const Proto* combine(lua_State* L, int n)\n{\n if (n==1)\n  return toproto(L,-1);\n else\n {\n  int i,pc;\n  Proto* f=luaF_newproto(L);\n  setptvalue2s(L,L->top,f); incr_top(L);\n  f->source=luaS_newliteral(L,\"=(\" PROGNAME \")\");\n  f->maxstacksize=1;\n  pc=2*n+1;\n  f->code=luaM_newvector(L,pc,Instruction);\n  f->sizecode=pc;\n  f->p=luaM_newvector(L,n,Proto*);\n  f->sizep=n;\n  pc=0;\n  for (i=0; i<n; i++)\n  {\n   f->p[i]=toproto(L,i-n-1);\n   f->code[pc++]=CREATE_ABx(OP_CLOSURE,0,i);\n   f->code[pc++]=CREATE_ABC(OP_CALL,0,1,1);\n  }\n  f->code[pc++]=CREATE_ABC(OP_RETURN,0,1,0);\n  return f;\n }\n}\n\nstatic int writer(lua_State* L, const void* p, size_t size, void* u)\n{\n UNUSED(L);\n return (fwrite(p,size,1,(FILE*)u)!=1) && (size!=0);\n}\n\nstruct Smain {\n int argc;\n char** argv;\n};\n\nstatic int pmain(lua_State* L)\n{\n struct Smain* s = (struct Smain*)lua_touserdata(L, 1);\n int argc=s->argc;\n char** argv=s->argv;\n const Proto* f;\n int i;\n if (!lua_checkstack(L,argc)) fatal(\"too many input files\");\n for (i=0; i<argc; i++)\n {\n  const char* filename=IS(\"-\") ? NULL : argv[i];\n  if (luaL_loadfile(L,filename)!=0) fatal(lua_tostring(L,-1));\n }\n f=combine(L,argc);\n if (listing) luaU_print(f,listing>1);\n if (dumping)\n {\n  FILE* D= (output==NULL) ? stdout : fopen(output,\"wb\");\n  if (D==NULL) cannot(\"open\");\n  lua_lock(L);\n  luaU_dump(L,f,writer,D,stripping);\n  lua_unlock(L);\n  if (ferror(D)) cannot(\"write\");\n  if (fclose(D)) cannot(\"close\");\n }\n return 0;\n}\n\nint main(int argc, char* argv[])\n{\n lua_State* L;\n struct Smain s;\n int i=doargs(argc,argv);\n argc-=i; argv+=i;\n if (argc<=0) usage(\"no input files given\");\n L=lua_open();\n if (L==NULL) fatal(\"not enough memory for state\");\n s.argc=argc;\n s.argv=argv;\n if (lua_cpcall(L,pmain,&s)!=0) fatal(lua_tostring(L,-1));\n lua_close(L);\n return EXIT_SUCCESS;\n}\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/deps/lua/src/luaconf.h",
    "content": "/*\n** $Id: luaconf.h,v 1.82.1.7 2008/02/11 16:25:08 roberto Exp $\n** Configuration file for Lua\n** See Copyright Notice in lua.h\n*/\n\n\n#ifndef lconfig_h\n#define lconfig_h\n\n#include <limits.h>\n#include <stddef.h>\n\n\n/*\n** ==================================================================\n** Search for \"@@\" to find all configurable definitions.\n** ===================================================================\n*/\n\n\n/*\n@@ LUA_ANSI controls the use of non-ansi features.\n** CHANGE it (define it) if you want Lua to avoid the use of any\n** non-ansi feature or library.\n*/\n#if defined(__STRICT_ANSI__)\n#define LUA_ANSI\n#endif\n\n\n#if !defined(LUA_ANSI) && defined(_WIN32)\n#define LUA_WIN\n#endif\n\n#if defined(LUA_USE_LINUX)\n#define LUA_USE_POSIX\n#define LUA_USE_DLOPEN\t\t/* needs an extra library: -ldl */\n#define LUA_USE_READLINE\t/* needs some extra libraries */\n#endif\n\n#if defined(LUA_USE_MACOSX)\n#define LUA_USE_POSIX\n#define LUA_DL_DYLD\t\t/* does not need extra library */\n#endif\n\n\n\n/*\n@@ LUA_USE_POSIX includes all functionallity listed as X/Open System\n@* Interfaces Extension (XSI).\n** CHANGE it (define it) if your system is XSI compatible.\n*/\n#if defined(LUA_USE_POSIX)\n#define LUA_USE_MKSTEMP\n#define LUA_USE_ISATTY\n#define LUA_USE_POPEN\n#define LUA_USE_ULONGJMP\n#endif\n\n\n/*\n@@ LUA_PATH and LUA_CPATH are the names of the environment variables that\n@* Lua check to set its paths.\n@@ LUA_INIT is the name of the environment variable that Lua\n@* checks for initialization code.\n** CHANGE them if you want different names.\n*/\n#define LUA_PATH        \"LUA_PATH\"\n#define LUA_CPATH       \"LUA_CPATH\"\n#define LUA_INIT\t\"LUA_INIT\"\n\n\n/*\n@@ LUA_PATH_DEFAULT is the default path that Lua uses to look for\n@* Lua libraries.\n@@ LUA_CPATH_DEFAULT is the default path that Lua uses to look for\n@* C libraries.\n** CHANGE them if your machine has a non-conventional directory\n** hierarchy or if you want to install your libraries in\n** non-conventional directories.\n*/\n#if defined(_WIN32)\n/*\n** In Windows, any exclamation mark ('!') in the path is replaced by the\n** path of the directory of the executable file of the current process.\n*/\n#define LUA_LDIR\t\"!\\\\lua\\\\\"\n#define LUA_CDIR\t\"!\\\\\"\n#define LUA_PATH_DEFAULT  \\\n\t\t\".\\\\?.lua;\"  LUA_LDIR\"?.lua;\"  LUA_LDIR\"?\\\\init.lua;\" \\\n\t\t             LUA_CDIR\"?.lua;\"  LUA_CDIR\"?\\\\init.lua\"\n#define LUA_CPATH_DEFAULT \\\n\t\".\\\\?.dll;\"  LUA_CDIR\"?.dll;\" LUA_CDIR\"loadall.dll\"\n\n#else\n#define LUA_ROOT\t\"/usr/local/\"\n#define LUA_LDIR\tLUA_ROOT \"share/lua/5.1/\"\n#define LUA_CDIR\tLUA_ROOT \"lib/lua/5.1/\"\n#define LUA_PATH_DEFAULT  \\\n\t\t\"./?.lua;\"  LUA_LDIR\"?.lua;\"  LUA_LDIR\"?/init.lua;\" \\\n\t\t            LUA_CDIR\"?.lua;\"  LUA_CDIR\"?/init.lua\"\n#define LUA_CPATH_DEFAULT \\\n\t\"./?.so;\"  LUA_CDIR\"?.so;\" LUA_CDIR\"loadall.so\"\n#endif\n\n\n/*\n@@ LUA_DIRSEP is the directory separator (for submodules).\n** CHANGE it if your machine does not use \"/\" as the directory separator\n** and is not Windows. (On Windows Lua automatically uses \"\\\".)\n*/\n#if defined(_WIN32)\n#define LUA_DIRSEP\t\"\\\\\"\n#else\n#define LUA_DIRSEP\t\"/\"\n#endif\n\n\n/*\n@@ LUA_PATHSEP is the character that separates templates in a path.\n@@ LUA_PATH_MARK is the string that marks the substitution points in a\n@* template.\n@@ LUA_EXECDIR in a Windows path is replaced by the executable's\n@* directory.\n@@ LUA_IGMARK is a mark to ignore all before it when bulding the\n@* luaopen_ function name.\n** CHANGE them if for some reason your system cannot use those\n** characters. (E.g., if one of those characters is a common character\n** in file/directory names.) Probably you do not need to change them.\n*/\n#define LUA_PATHSEP\t\";\"\n#define LUA_PATH_MARK\t\"?\"\n#define LUA_EXECDIR\t\"!\"\n#define LUA_IGMARK\t\"-\"\n\n\n/*\n@@ LUA_INTEGER is the integral type used by lua_pushinteger/lua_tointeger.\n** CHANGE that if ptrdiff_t is not adequate on your machine. (On most\n** machines, ptrdiff_t gives a good choice between int or long.)\n*/\n#define LUA_INTEGER\tptrdiff_t\n\n\n/*\n@@ LUA_API is a mark for all core API functions.\n@@ LUALIB_API is a mark for all standard library functions.\n** CHANGE them if you need to define those functions in some special way.\n** For instance, if you want to create one Windows DLL with the core and\n** the libraries, you may want to use the following definition (define\n** LUA_BUILD_AS_DLL to get it).\n*/\n#if defined(LUA_BUILD_AS_DLL)\n\n#if defined(LUA_CORE) || defined(LUA_LIB)\n#define LUA_API __declspec(dllexport)\n#else\n#define LUA_API __declspec(dllimport)\n#endif\n\n#else\n\n#define LUA_API\t\textern\n\n#endif\n\n/* more often than not the libs go together with the core */\n#define LUALIB_API\tLUA_API\n\n\n/*\n@@ LUAI_FUNC is a mark for all extern functions that are not to be\n@* exported to outside modules.\n@@ LUAI_DATA is a mark for all extern (const) variables that are not to\n@* be exported to outside modules.\n** CHANGE them if you need to mark them in some special way. Elf/gcc\n** (versions 3.2 and later) mark them as \"hidden\" to optimize access\n** when Lua is compiled as a shared library.\n*/\n#if defined(luaall_c)\n#define LUAI_FUNC\tstatic\n#define LUAI_DATA\t/* empty */\n\n#elif defined(__GNUC__) && ((__GNUC__*100 + __GNUC_MINOR__) >= 302) && \\\n      defined(__ELF__)\n#define LUAI_FUNC\t__attribute__((visibility(\"hidden\"))) extern\n#define LUAI_DATA\tLUAI_FUNC\n\n#else\n#define LUAI_FUNC\textern\n#define LUAI_DATA\textern\n#endif\n\n\n\n/*\n@@ LUA_QL describes how error messages quote program elements.\n** CHANGE it if you want a different appearance.\n*/\n#define LUA_QL(x)\t\"'\" x \"'\"\n#define LUA_QS\t\tLUA_QL(\"%s\")\n\n\n/*\n@@ LUA_IDSIZE gives the maximum size for the description of the source\n@* of a function in debug information.\n** CHANGE it if you want a different size.\n*/\n#define LUA_IDSIZE\t60\n\n\n/*\n** {==================================================================\n** Stand-alone configuration\n** ===================================================================\n*/\n\n#if defined(lua_c) || defined(luaall_c)\n\n/*\n@@ lua_stdin_is_tty detects whether the standard input is a 'tty' (that\n@* is, whether we're running lua interactively).\n** CHANGE it if you have a better definition for non-POSIX/non-Windows\n** systems.\n*/\n#if defined(LUA_USE_ISATTY)\n#include <unistd.h>\n#define lua_stdin_is_tty()\tisatty(0)\n#elif defined(LUA_WIN)\n#include <io.h>\n#include <stdio.h>\n#define lua_stdin_is_tty()\t_isatty(_fileno(stdin))\n#else\n#define lua_stdin_is_tty()\t1  /* assume stdin is a tty */\n#endif\n\n\n/*\n@@ LUA_PROMPT is the default prompt used by stand-alone Lua.\n@@ LUA_PROMPT2 is the default continuation prompt used by stand-alone Lua.\n** CHANGE them if you want different prompts. (You can also change the\n** prompts dynamically, assigning to globals _PROMPT/_PROMPT2.)\n*/\n#define LUA_PROMPT\t\t\"> \"\n#define LUA_PROMPT2\t\t\">> \"\n\n\n/*\n@@ LUA_PROGNAME is the default name for the stand-alone Lua program.\n** CHANGE it if your stand-alone interpreter has a different name and\n** your system is not able to detect that name automatically.\n*/\n#define LUA_PROGNAME\t\t\"lua\"\n\n\n/*\n@@ LUA_MAXINPUT is the maximum length for an input line in the\n@* stand-alone interpreter.\n** CHANGE it if you need longer lines.\n*/\n#define LUA_MAXINPUT\t512\n\n\n/*\n@@ lua_readline defines how to show a prompt and then read a line from\n@* the standard input.\n@@ lua_saveline defines how to \"save\" a read line in a \"history\".\n@@ lua_freeline defines how to free a line read by lua_readline.\n** CHANGE them if you want to improve this functionality (e.g., by using\n** GNU readline and history facilities).\n*/\n#if defined(LUA_USE_READLINE)\n#include <stdio.h>\n#include <readline/readline.h>\n#include <readline/history.h>\n#define lua_readline(L,b,p)\t((void)L, ((b)=readline(p)) != NULL)\n#define lua_saveline(L,idx) \\\n\tif (lua_strlen(L,idx) > 0)  /* non-empty line? */ \\\n\t  add_history(lua_tostring(L, idx));  /* add it to history */\n#define lua_freeline(L,b)\t((void)L, free(b))\n#else\n#define lua_readline(L,b,p)\t\\\n\t((void)L, fputs(p, stdout), fflush(stdout),  /* show prompt */ \\\n\tfgets(b, LUA_MAXINPUT, stdin) != NULL)  /* get line */\n#define lua_saveline(L,idx)\t{ (void)L; (void)idx; }\n#define lua_freeline(L,b)\t{ (void)L; (void)b; }\n#endif\n\n#endif\n\n/* }================================================================== */\n\n\n/*\n@@ LUAI_GCPAUSE defines the default pause between garbage-collector cycles\n@* as a percentage.\n** CHANGE it if you want the GC to run faster or slower (higher values\n** mean larger pauses which mean slower collection.) You can also change\n** this value dynamically.\n*/\n#define LUAI_GCPAUSE\t200  /* 200% (wait memory to double before next GC) */\n\n\n/*\n@@ LUAI_GCMUL defines the default speed of garbage collection relative to\n@* memory allocation as a percentage.\n** CHANGE it if you want to change the granularity of the garbage\n** collection. (Higher values mean coarser collections. 0 represents\n** infinity, where each step performs a full collection.) You can also\n** change this value dynamically.\n*/\n#define LUAI_GCMUL\t200 /* GC runs 'twice the speed' of memory allocation */\n\n\n\n/*\n@@ LUA_COMPAT_GETN controls compatibility with old getn behavior.\n** CHANGE it (define it) if you want exact compatibility with the\n** behavior of setn/getn in Lua 5.0.\n*/\n#undef LUA_COMPAT_GETN\n\n/*\n@@ LUA_COMPAT_LOADLIB controls compatibility about global loadlib.\n** CHANGE it to undefined as soon as you do not need a global 'loadlib'\n** function (the function is still available as 'package.loadlib').\n*/\n#undef LUA_COMPAT_LOADLIB\n\n/*\n@@ LUA_COMPAT_VARARG controls compatibility with old vararg feature.\n** CHANGE it to undefined as soon as your programs use only '...' to\n** access vararg parameters (instead of the old 'arg' table).\n*/\n#define LUA_COMPAT_VARARG\n\n/*\n@@ LUA_COMPAT_MOD controls compatibility with old math.mod function.\n** CHANGE it to undefined as soon as your programs use 'math.fmod' or\n** the new '%' operator instead of 'math.mod'.\n*/\n#define LUA_COMPAT_MOD\n\n/*\n@@ LUA_COMPAT_LSTR controls compatibility with old long string nesting\n@* facility.\n** CHANGE it to 2 if you want the old behaviour, or undefine it to turn\n** off the advisory error when nesting [[...]].\n*/\n#define LUA_COMPAT_LSTR\t\t1\n\n/*\n@@ LUA_COMPAT_GFIND controls compatibility with old 'string.gfind' name.\n** CHANGE it to undefined as soon as you rename 'string.gfind' to\n** 'string.gmatch'.\n*/\n#define LUA_COMPAT_GFIND\n\n/*\n@@ LUA_COMPAT_OPENLIB controls compatibility with old 'luaL_openlib'\n@* behavior.\n** CHANGE it to undefined as soon as you replace to 'luaL_register'\n** your uses of 'luaL_openlib'\n*/\n#define LUA_COMPAT_OPENLIB\n\n\n\n/*\n@@ luai_apicheck is the assert macro used by the Lua-C API.\n** CHANGE luai_apicheck if you want Lua to perform some checks in the\n** parameters it gets from API calls. This may slow down the interpreter\n** a bit, but may be quite useful when debugging C code that interfaces\n** with Lua. A useful redefinition is to use assert.h.\n*/\n#if defined(LUA_USE_APICHECK)\n#include <assert.h>\n#define luai_apicheck(L,o)\t{ (void)L; assert(o); }\n#else\n#define luai_apicheck(L,o)\t{ (void)L; }\n#endif\n\n\n/*\n@@ LUAI_BITSINT defines the number of bits in an int.\n** CHANGE here if Lua cannot automatically detect the number of bits of\n** your machine. Probably you do not need to change this.\n*/\n/* avoid overflows in comparison */\n#if INT_MAX-20 < 32760\n#define LUAI_BITSINT\t16\n#elif INT_MAX > 2147483640L\n/* int has at least 32 bits */\n#define LUAI_BITSINT\t32\n#else\n#error \"you must define LUA_BITSINT with number of bits in an integer\"\n#endif\n\n\n/*\n@@ LUAI_UINT32 is an unsigned integer with at least 32 bits.\n@@ LUAI_INT32 is an signed integer with at least 32 bits.\n@@ LUAI_UMEM is an unsigned integer big enough to count the total\n@* memory used by Lua.\n@@ LUAI_MEM is a signed integer big enough to count the total memory\n@* used by Lua.\n** CHANGE here if for some weird reason the default definitions are not\n** good enough for your machine. (The definitions in the 'else'\n** part always works, but may waste space on machines with 64-bit\n** longs.) Probably you do not need to change this.\n*/\n#if LUAI_BITSINT >= 32\n#define LUAI_UINT32\tunsigned int\n#define LUAI_INT32\tint\n#define LUAI_MAXINT32\tINT_MAX\n#define LUAI_UMEM\tsize_t\n#define LUAI_MEM\tptrdiff_t\n#else\n/* 16-bit ints */\n#define LUAI_UINT32\tunsigned long\n#define LUAI_INT32\tlong\n#define LUAI_MAXINT32\tLONG_MAX\n#define LUAI_UMEM\tunsigned long\n#define LUAI_MEM\tlong\n#endif\n\n\n/*\n@@ LUAI_MAXCALLS limits the number of nested calls.\n** CHANGE it if you need really deep recursive calls. This limit is\n** arbitrary; its only purpose is to stop infinite recursion before\n** exhausting memory.\n*/\n#define LUAI_MAXCALLS\t20000\n\n\n/*\n@@ LUAI_MAXCSTACK limits the number of Lua stack slots that a C function\n@* can use.\n** CHANGE it if you need lots of (Lua) stack space for your C\n** functions. This limit is arbitrary; its only purpose is to stop C\n** functions to consume unlimited stack space. (must be smaller than\n** -LUA_REGISTRYINDEX)\n*/\n#define LUAI_MAXCSTACK\t8000\n\n\n\n/*\n** {==================================================================\n** CHANGE (to smaller values) the following definitions if your system\n** has a small C stack. (Or you may want to change them to larger\n** values if your system has a large C stack and these limits are\n** too rigid for you.) Some of these constants control the size of\n** stack-allocated arrays used by the compiler or the interpreter, while\n** others limit the maximum number of recursive calls that the compiler\n** or the interpreter can perform. Values too large may cause a C stack\n** overflow for some forms of deep constructs.\n** ===================================================================\n*/\n\n\n/*\n@@ LUAI_MAXCCALLS is the maximum depth for nested C calls (short) and\n@* syntactical nested non-terminals in a program.\n*/\n#define LUAI_MAXCCALLS\t\t200\n\n\n/*\n@@ LUAI_MAXVARS is the maximum number of local variables per function\n@* (must be smaller than 250).\n*/\n#define LUAI_MAXVARS\t\t200\n\n\n/*\n@@ LUAI_MAXUPVALUES is the maximum number of upvalues per function\n@* (must be smaller than 250).\n*/\n#define LUAI_MAXUPVALUES\t60\n\n\n/*\n@@ LUAL_BUFFERSIZE is the buffer size used by the lauxlib buffer system.\n*/\n#define LUAL_BUFFERSIZE\t\tBUFSIZ\n\n/* }================================================================== */\n\n\n\n\n/*\n** {==================================================================\n@@ LUA_NUMBER is the type of numbers in Lua.\n** CHANGE the following definitions only if you want to build Lua\n** with a number type different from double. You may also need to\n** change lua_number2int & lua_number2integer.\n** ===================================================================\n*/\n\n#define LUA_NUMBER_DOUBLE\n#define LUA_NUMBER\tdouble\n\n/*\n@@ LUAI_UACNUMBER is the result of an 'usual argument conversion'\n@* over a number.\n*/\n#define LUAI_UACNUMBER\tdouble\n\n\n/*\n@@ LUA_NUMBER_SCAN is the format for reading numbers.\n@@ LUA_NUMBER_FMT is the format for writing numbers.\n@@ lua_number2str converts a number to a string.\n@@ LUAI_MAXNUMBER2STR is maximum size of previous conversion.\n@@ lua_str2number converts a string to a number.\n*/\n#define LUA_NUMBER_SCAN\t\t\"%lf\"\n#define LUA_NUMBER_FMT\t\t\"%.14g\"\n#define lua_number2str(s,n)\tsprintf((s), LUA_NUMBER_FMT, (n))\n#define LUAI_MAXNUMBER2STR\t32 /* 16 digits, sign, point, and \\0 */\n#define lua_str2number(s,p)\tstrtod((s), (p))\n\n\n/*\n@@ The luai_num* macros define the primitive operations over numbers.\n*/\n#if defined(LUA_CORE)\n#include <math.h>\n#define luai_numadd(a,b)\t((a)+(b))\n#define luai_numsub(a,b)\t((a)-(b))\n#define luai_nummul(a,b)\t((a)*(b))\n#define luai_numdiv(a,b)\t((a)/(b))\n#define luai_nummod(a,b)\t((a) - floor((a)/(b))*(b))\n#define luai_numpow(a,b)\t(pow(a,b))\n#define luai_numunm(a)\t\t(-(a))\n#define luai_numeq(a,b)\t\t((a)==(b))\n#define luai_numlt(a,b)\t\t((a)<(b))\n#define luai_numle(a,b)\t\t((a)<=(b))\n#define luai_numisnan(a)\t(!luai_numeq((a), (a)))\n#endif\n\n\n/*\n@@ lua_number2int is a macro to convert lua_Number to int.\n@@ lua_number2integer is a macro to convert lua_Number to lua_Integer.\n** CHANGE them if you know a faster way to convert a lua_Number to\n** int (with any rounding method and without throwing errors) in your\n** system. In Pentium machines, a naive typecast from double to int\n** in C is extremely slow, so any alternative is worth trying.\n*/\n\n/* On a Pentium, resort to a trick */\n#if defined(LUA_NUMBER_DOUBLE) && !defined(LUA_ANSI) && !defined(__SSE2__) && \\\n    (defined(__i386) || defined (_M_IX86) || defined(__i386__))\n\n/* On a Microsoft compiler, use assembler */\n#if defined(_MSC_VER)\n\n#define lua_number2int(i,d)   __asm fld d   __asm fistp i\n#define lua_number2integer(i,n)\t\tlua_number2int(i, n)\n\n/* the next trick should work on any Pentium, but sometimes clashes\n   with a DirectX idiosyncrasy */\n#else\n\nunion luai_Cast { double l_d; long l_l; };\n#define lua_number2int(i,d) \\\n  { volatile union luai_Cast u; u.l_d = (d) + 6755399441055744.0; (i) = u.l_l; }\n#define lua_number2integer(i,n)\t\tlua_number2int(i, n)\n\n#endif\n\n\n/* this option always works, but may be slow */\n#else\n#define lua_number2int(i,d)\t((i)=(int)(d))\n#define lua_number2integer(i,d)\t((i)=(lua_Integer)(d))\n\n#endif\n\n/* }================================================================== */\n\n\n/*\n@@ LUAI_USER_ALIGNMENT_T is a type that requires maximum alignment.\n** CHANGE it if your system requires alignments larger than double. (For\n** instance, if your system supports long doubles and they must be\n** aligned in 16-byte boundaries, then you should add long double in the\n** union.) Probably you do not need to change this.\n*/\n#define LUAI_USER_ALIGNMENT_T\tunion { double u; void *s; long l; }\n\n\n/*\n@@ LUAI_THROW/LUAI_TRY define how Lua does exception handling.\n** CHANGE them if you prefer to use longjmp/setjmp even with C++\n** or if want/don't to use _longjmp/_setjmp instead of regular\n** longjmp/setjmp. By default, Lua handles errors with exceptions when\n** compiling as C++ code, with _longjmp/_setjmp when asked to use them,\n** and with longjmp/setjmp otherwise.\n*/\n#if defined(__cplusplus)\n/* C++ exceptions */\n#define LUAI_THROW(L,c)\tthrow(c)\n#define LUAI_TRY(L,c,a)\ttry { a } catch(...) \\\n\t{ if ((c)->status == 0) (c)->status = -1; }\n#define luai_jmpbuf\tint  /* dummy variable */\n\n#elif defined(LUA_USE_ULONGJMP)\n/* in Unix, try _longjmp/_setjmp (more efficient) */\n#define LUAI_THROW(L,c)\t_longjmp((c)->b, 1)\n#define LUAI_TRY(L,c,a)\tif (_setjmp((c)->b) == 0) { a }\n#define luai_jmpbuf\tjmp_buf\n\n#else\n/* default handling with long jumps */\n#define LUAI_THROW(L,c)\tlongjmp((c)->b, 1)\n#define LUAI_TRY(L,c,a)\tif (setjmp((c)->b) == 0) { a }\n#define luai_jmpbuf\tjmp_buf\n\n#endif\n\n\n/*\n@@ LUA_MAXCAPTURES is the maximum number of captures that a pattern\n@* can do during pattern-matching.\n** CHANGE it if you need more captures. This limit is arbitrary.\n*/\n#define LUA_MAXCAPTURES\t\t32\n\n\n/*\n@@ lua_tmpnam is the function that the OS library uses to create a\n@* temporary name.\n@@ LUA_TMPNAMBUFSIZE is the maximum size of a name created by lua_tmpnam.\n** CHANGE them if you have an alternative to tmpnam (which is considered\n** insecure) or if you want the original tmpnam anyway.  By default, Lua\n** uses tmpnam except when POSIX is available, where it uses mkstemp.\n*/\n#if defined(loslib_c) || defined(luaall_c)\n\n#if defined(LUA_USE_MKSTEMP)\n#include <unistd.h>\n#define LUA_TMPNAMBUFSIZE\t32\n#define lua_tmpnam(b,e)\t{ \\\n\tstrcpy(b, \"/tmp/lua_XXXXXX\"); \\\n\te = mkstemp(b); \\\n\tif (e != -1) close(e); \\\n\te = (e == -1); }\n\n#else\n#define LUA_TMPNAMBUFSIZE\tL_tmpnam\n#define lua_tmpnam(b,e)\t\t{ e = (tmpnam(b) == NULL); }\n#endif\n\n#endif\n\n\n/*\n@@ lua_popen spawns a new process connected to the current one through\n@* the file streams.\n** CHANGE it if you have a way to implement it in your system.\n*/\n#if defined(LUA_USE_POPEN)\n\n#define lua_popen(L,c,m)\t((void)L, fflush(NULL), popen(c,m))\n#define lua_pclose(L,file)\t((void)L, (pclose(file) != -1))\n\n#elif defined(LUA_WIN)\n\n#define lua_popen(L,c,m)\t((void)L, _popen(c,m))\n#define lua_pclose(L,file)\t((void)L, (_pclose(file) != -1))\n\n#else\n\n#define lua_popen(L,c,m)\t((void)((void)c, m),  \\\n\t\tluaL_error(L, LUA_QL(\"popen\") \" not supported\"), (FILE*)0)\n#define lua_pclose(L,file)\t\t((void)((void)L, file), 0)\n\n#endif\n\n/*\n@@ LUA_DL_* define which dynamic-library system Lua should use.\n** CHANGE here if Lua has problems choosing the appropriate\n** dynamic-library system for your platform (either Windows' DLL, Mac's\n** dyld, or Unix's dlopen). If your system is some kind of Unix, there\n** is a good chance that it has dlopen, so LUA_DL_DLOPEN will work for\n** it.  To use dlopen you also need to adapt the src/Makefile (probably\n** adding -ldl to the linker options), so Lua does not select it\n** automatically.  (When you change the makefile to add -ldl, you must\n** also add -DLUA_USE_DLOPEN.)\n** If you do not want any kind of dynamic library, undefine all these\n** options.\n** By default, _WIN32 gets LUA_DL_DLL and MAC OS X gets LUA_DL_DYLD.\n*/\n#if defined(LUA_USE_DLOPEN)\n#define LUA_DL_DLOPEN\n#endif\n\n#if defined(LUA_WIN)\n#define LUA_DL_DLL\n#endif\n\n\n/*\n@@ LUAI_EXTRASPACE allows you to add user-specific data in a lua_State\n@* (the data goes just *before* the lua_State pointer).\n** CHANGE (define) this if you really need that. This value must be\n** a multiple of the maximum alignment required for your machine.\n*/\n#define LUAI_EXTRASPACE\t\t0\n\n\n/*\n@@ luai_userstate* allow user-specific actions on threads.\n** CHANGE them if you defined LUAI_EXTRASPACE and need to do something\n** extra when a thread is created/deleted/resumed/yielded.\n*/\n#define luai_userstateopen(L)\t\t((void)L)\n#define luai_userstateclose(L)\t\t((void)L)\n#define luai_userstatethread(L,L1)\t((void)L)\n#define luai_userstatefree(L)\t\t((void)L)\n#define luai_userstateresume(L,n)\t((void)L)\n#define luai_userstateyield(L,n)\t((void)L)\n\n\n/*\n@@ LUA_INTFRMLEN is the length modifier for integer conversions\n@* in 'string.format'.\n@@ LUA_INTFRM_T is the integer type correspoding to the previous length\n@* modifier.\n** CHANGE them if your system supports long long or does not support long.\n*/\n\n#if defined(LUA_USELONGLONG)\n\n#define LUA_INTFRMLEN\t\t\"ll\"\n#define LUA_INTFRM_T\t\tlong long\n\n#else\n\n#define LUA_INTFRMLEN\t\t\"l\"\n#define LUA_INTFRM_T\t\tlong\n\n#endif\n\n\n\n/* =================================================================== */\n\n/*\n** Local configuration. You can use this space to add your redefinitions\n** without modifying the main part of the file.\n*/\n\n\n\n#endif\n\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/deps/lua/src/lualib.h",
    "content": "/*\n** $Id: lualib.h,v 1.36.1.1 2007/12/27 13:02:25 roberto Exp $\n** Lua standard libraries\n** See Copyright Notice in lua.h\n*/\n\n\n#ifndef lualib_h\n#define lualib_h\n\n#include \"lua.h\"\n\n\n/* Key to file-handle type */\n#define LUA_FILEHANDLE\t\t\"FILE*\"\n\n\n#define LUA_COLIBNAME\t\"coroutine\"\nLUALIB_API int (luaopen_base) (lua_State *L);\n\n#define LUA_TABLIBNAME\t\"table\"\nLUALIB_API int (luaopen_table) (lua_State *L);\n\n#define LUA_IOLIBNAME\t\"io\"\nLUALIB_API int (luaopen_io) (lua_State *L);\n\n#define LUA_OSLIBNAME\t\"os\"\nLUALIB_API int (luaopen_os) (lua_State *L);\n\n#define LUA_STRLIBNAME\t\"string\"\nLUALIB_API int (luaopen_string) (lua_State *L);\n\n#define LUA_MATHLIBNAME\t\"math\"\nLUALIB_API int (luaopen_math) (lua_State *L);\n\n#define LUA_DBLIBNAME\t\"debug\"\nLUALIB_API int (luaopen_debug) (lua_State *L);\n\n#define LUA_LOADLIBNAME\t\"package\"\nLUALIB_API int (luaopen_package) (lua_State *L);\n\n\n/* open all previous libraries */\nLUALIB_API void (luaL_openlibs) (lua_State *L); \n\n\n\n#ifndef lua_assert\n#define lua_assert(x)\t((void)0)\n#endif\n\n\n#endif\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/deps/lua/src/lundump.c",
    "content": "/*\n** $Id: lundump.c,v 2.7.1.4 2008/04/04 19:51:41 roberto Exp $\n** load precompiled Lua chunks\n** See Copyright Notice in lua.h\n*/\n\n#include <string.h>\n\n#define lundump_c\n#define LUA_CORE\n\n#include \"lua.h\"\n\n#include \"ldebug.h\"\n#include \"ldo.h\"\n#include \"lfunc.h\"\n#include \"lmem.h\"\n#include \"lobject.h\"\n#include \"lstring.h\"\n#include \"lundump.h\"\n#include \"lzio.h\"\n\ntypedef struct {\n lua_State* L;\n ZIO* Z;\n Mbuffer* b;\n const char* name;\n} LoadState;\n\n#ifdef LUAC_TRUST_BINARIES\n#define IF(c,s)\n#define error(S,s)\n#else\n#define IF(c,s)\t\tif (c) error(S,s)\n\nstatic void error(LoadState* S, const char* why)\n{\n luaO_pushfstring(S->L,\"%s: %s in precompiled chunk\",S->name,why);\n luaD_throw(S->L,LUA_ERRSYNTAX);\n}\n#endif\n\n#define LoadMem(S,b,n,size)\tLoadBlock(S,b,(n)*(size))\n#define\tLoadByte(S)\t\t(lu_byte)LoadChar(S)\n#define LoadVar(S,x)\t\tLoadMem(S,&x,1,sizeof(x))\n#define LoadVector(S,b,n,size)\tLoadMem(S,b,n,size)\n\nstatic void LoadBlock(LoadState* S, void* b, size_t size)\n{\n size_t r=luaZ_read(S->Z,b,size);\n IF (r!=0, \"unexpected end\");\n}\n\nstatic int LoadChar(LoadState* S)\n{\n char x;\n LoadVar(S,x);\n return x;\n}\n\nstatic int LoadInt(LoadState* S)\n{\n int x;\n LoadVar(S,x);\n IF (x<0, \"bad integer\");\n return x;\n}\n\nstatic lua_Number LoadNumber(LoadState* S)\n{\n lua_Number x;\n LoadVar(S,x);\n return x;\n}\n\nstatic TString* LoadString(LoadState* S)\n{\n size_t size;\n LoadVar(S,size);\n if (size==0)\n  return NULL;\n else\n {\n  char* s=luaZ_openspace(S->L,S->b,size);\n  LoadBlock(S,s,size);\n  return luaS_newlstr(S->L,s,size-1);\t\t/* remove trailing '\\0' */\n }\n}\n\nstatic void LoadCode(LoadState* S, Proto* f)\n{\n int n=LoadInt(S);\n f->code=luaM_newvector(S->L,n,Instruction);\n f->sizecode=n;\n LoadVector(S,f->code,n,sizeof(Instruction));\n}\n\nstatic Proto* LoadFunction(LoadState* S, TString* p);\n\nstatic void LoadConstants(LoadState* S, Proto* f)\n{\n int i,n;\n n=LoadInt(S);\n f->k=luaM_newvector(S->L,n,TValue);\n f->sizek=n;\n for (i=0; i<n; i++) setnilvalue(&f->k[i]);\n for (i=0; i<n; i++)\n {\n  TValue* o=&f->k[i];\n  int t=LoadChar(S);\n  switch (t)\n  {\n   case LUA_TNIL:\n   \tsetnilvalue(o);\n\tbreak;\n   case LUA_TBOOLEAN:\n   \tsetbvalue(o,LoadChar(S)!=0);\n\tbreak;\n   case LUA_TNUMBER:\n\tsetnvalue(o,LoadNumber(S));\n\tbreak;\n   case LUA_TSTRING:\n\tsetsvalue2n(S->L,o,LoadString(S));\n\tbreak;\n   default:\n\terror(S,\"bad constant\");\n\tbreak;\n  }\n }\n n=LoadInt(S);\n f->p=luaM_newvector(S->L,n,Proto*);\n f->sizep=n;\n for (i=0; i<n; i++) f->p[i]=NULL;\n for (i=0; i<n; i++) f->p[i]=LoadFunction(S,f->source);\n}\n\nstatic void LoadDebug(LoadState* S, Proto* f)\n{\n int i,n;\n n=LoadInt(S);\n f->lineinfo=luaM_newvector(S->L,n,int);\n f->sizelineinfo=n;\n LoadVector(S,f->lineinfo,n,sizeof(int));\n n=LoadInt(S);\n f->locvars=luaM_newvector(S->L,n,LocVar);\n f->sizelocvars=n;\n for (i=0; i<n; i++) f->locvars[i].varname=NULL;\n for (i=0; i<n; i++)\n {\n  f->locvars[i].varname=LoadString(S);\n  f->locvars[i].startpc=LoadInt(S);\n  f->locvars[i].endpc=LoadInt(S);\n }\n n=LoadInt(S);\n f->upvalues=luaM_newvector(S->L,n,TString*);\n f->sizeupvalues=n;\n for (i=0; i<n; i++) f->upvalues[i]=NULL;\n for (i=0; i<n; i++) f->upvalues[i]=LoadString(S);\n}\n\nstatic Proto* LoadFunction(LoadState* S, TString* p)\n{\n Proto* f;\n if (++S->L->nCcalls > LUAI_MAXCCALLS) error(S,\"code too deep\");\n f=luaF_newproto(S->L);\n setptvalue2s(S->L,S->L->top,f); incr_top(S->L);\n f->source=LoadString(S); if (f->source==NULL) f->source=p;\n f->linedefined=LoadInt(S);\n f->lastlinedefined=LoadInt(S);\n f->nups=LoadByte(S);\n f->numparams=LoadByte(S);\n f->is_vararg=LoadByte(S);\n f->maxstacksize=LoadByte(S);\n LoadCode(S,f);\n LoadConstants(S,f);\n LoadDebug(S,f);\n IF (!luaG_checkcode(f), \"bad code\");\n S->L->top--;\n S->L->nCcalls--;\n return f;\n}\n\nstatic void LoadHeader(LoadState* S)\n{\n char h[LUAC_HEADERSIZE];\n char s[LUAC_HEADERSIZE];\n luaU_header(h);\n LoadBlock(S,s,LUAC_HEADERSIZE);\n IF (memcmp(h,s,LUAC_HEADERSIZE)!=0, \"bad header\");\n}\n\n/*\n** load precompiled chunk\n*/\nProto* luaU_undump (lua_State* L, ZIO* Z, Mbuffer* buff, const char* name)\n{\n LoadState S;\n if (*name=='@' || *name=='=')\n  S.name=name+1;\n else if (*name==LUA_SIGNATURE[0])\n  S.name=\"binary string\";\n else\n  S.name=name;\n S.L=L;\n S.Z=Z;\n S.b=buff;\n LoadHeader(&S);\n return LoadFunction(&S,luaS_newliteral(L,\"=?\"));\n}\n\n/*\n* make header\n*/\nvoid luaU_header (char* h)\n{\n int x=1;\n memcpy(h,LUA_SIGNATURE,sizeof(LUA_SIGNATURE)-1);\n h+=sizeof(LUA_SIGNATURE)-1;\n *h++=(char)LUAC_VERSION;\n *h++=(char)LUAC_FORMAT;\n *h++=(char)*(char*)&x;\t\t\t\t/* endianness */\n *h++=(char)sizeof(int);\n *h++=(char)sizeof(size_t);\n *h++=(char)sizeof(Instruction);\n *h++=(char)sizeof(lua_Number);\n *h++=(char)(((lua_Number)0.5)==0);\t\t/* is lua_Number integral? */\n}\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/deps/lua/src/lundump.h",
    "content": "/*\n** $Id: lundump.h,v 1.37.1.1 2007/12/27 13:02:25 roberto Exp $\n** load precompiled Lua chunks\n** See Copyright Notice in lua.h\n*/\n\n#ifndef lundump_h\n#define lundump_h\n\n#include \"lobject.h\"\n#include \"lzio.h\"\n\n/* load one chunk; from lundump.c */\nLUAI_FUNC Proto* luaU_undump (lua_State* L, ZIO* Z, Mbuffer* buff, const char* name);\n\n/* make header; from lundump.c */\nLUAI_FUNC void luaU_header (char* h);\n\n/* dump one chunk; from ldump.c */\nLUAI_FUNC int luaU_dump (lua_State* L, const Proto* f, lua_Writer w, void* data, int strip);\n\n#ifdef luac_c\n/* print one chunk; from print.c */\nLUAI_FUNC void luaU_print (const Proto* f, int full);\n#endif\n\n/* for header of binary files -- this is Lua 5.1 */\n#define LUAC_VERSION\t\t0x51\n\n/* for header of binary files -- this is the official format */\n#define LUAC_FORMAT\t\t0\n\n/* size of header of binary files */\n#define LUAC_HEADERSIZE\t\t12\n\n#endif\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/deps/lua/src/lvm.c",
    "content": "/*\n** $Id: lvm.c,v 2.63.1.5 2011/08/17 20:43:11 roberto Exp $\n** Lua virtual machine\n** See Copyright Notice in lua.h\n*/\n\n\n#include <stdio.h>\n#include <stdlib.h>\n#include <string.h>\n\n#define lvm_c\n#define LUA_CORE\n\n#include \"lua.h\"\n\n#include \"ldebug.h\"\n#include \"ldo.h\"\n#include \"lfunc.h\"\n#include \"lgc.h\"\n#include \"lobject.h\"\n#include \"lopcodes.h\"\n#include \"lstate.h\"\n#include \"lstring.h\"\n#include \"ltable.h\"\n#include \"ltm.h\"\n#include \"lvm.h\"\n\n\n\n/* limit for table tag-method chains (to avoid loops) */\n#define MAXTAGLOOP\t100\n\n\nconst TValue *luaV_tonumber (const TValue *obj, TValue *n) {\n  lua_Number num;\n  if (ttisnumber(obj)) return obj;\n  if (ttisstring(obj) && luaO_str2d(svalue(obj), &num)) {\n    setnvalue(n, num);\n    return n;\n  }\n  else\n    return NULL;\n}\n\n\nint luaV_tostring (lua_State *L, StkId obj) {\n  if (!ttisnumber(obj))\n    return 0;\n  else {\n    char s[LUAI_MAXNUMBER2STR];\n    lua_Number n = nvalue(obj);\n    lua_number2str(s, n);\n    setsvalue2s(L, obj, luaS_new(L, s));\n    return 1;\n  }\n}\n\n\nstatic void traceexec (lua_State *L, const Instruction *pc) {\n  lu_byte mask = L->hookmask;\n  const Instruction *oldpc = L->savedpc;\n  L->savedpc = pc;\n  if ((mask & LUA_MASKCOUNT) && L->hookcount == 0) {\n    resethookcount(L);\n    luaD_callhook(L, LUA_HOOKCOUNT, -1);\n  }\n  if (mask & LUA_MASKLINE) {\n    Proto *p = ci_func(L->ci)->l.p;\n    int npc = pcRel(pc, p);\n    int newline = getline(p, npc);\n    /* call linehook when enter a new function, when jump back (loop),\n       or when enter a new line */\n    if (npc == 0 || pc <= oldpc || newline != getline(p, pcRel(oldpc, p)))\n      luaD_callhook(L, LUA_HOOKLINE, newline);\n  }\n}\n\n\nstatic void callTMres (lua_State *L, StkId res, const TValue *f,\n                        const TValue *p1, const TValue *p2) {\n  ptrdiff_t result = savestack(L, res);\n  setobj2s(L, L->top, f);  /* push function */\n  setobj2s(L, L->top+1, p1);  /* 1st argument */\n  setobj2s(L, L->top+2, p2);  /* 2nd argument */\n  luaD_checkstack(L, 3);\n  L->top += 3;\n  luaD_call(L, L->top - 3, 1);\n  res = restorestack(L, result);\n  L->top--;\n  setobjs2s(L, res, L->top);\n}\n\n\n\nstatic void callTM (lua_State *L, const TValue *f, const TValue *p1,\n                    const TValue *p2, const TValue *p3) {\n  setobj2s(L, L->top, f);  /* push function */\n  setobj2s(L, L->top+1, p1);  /* 1st argument */\n  setobj2s(L, L->top+2, p2);  /* 2nd argument */\n  setobj2s(L, L->top+3, p3);  /* 3th argument */\n  luaD_checkstack(L, 4);\n  L->top += 4;\n  luaD_call(L, L->top - 4, 0);\n}\n\n\nvoid luaV_gettable (lua_State *L, const TValue *t, TValue *key, StkId val) {\n  int loop;\n  for (loop = 0; loop < MAXTAGLOOP; loop++) {\n    const TValue *tm;\n    if (ttistable(t)) {  /* `t' is a table? */\n      Table *h = hvalue(t);\n      const TValue *res = luaH_get(h, key); /* do a primitive get */\n      if (!ttisnil(res) ||  /* result is no nil? */\n          (tm = fasttm(L, h->metatable, TM_INDEX)) == NULL) { /* or no TM? */\n        setobj2s(L, val, res);\n        return;\n      }\n      /* else will try the tag method */\n    }\n    else if (ttisnil(tm = luaT_gettmbyobj(L, t, TM_INDEX)))\n      luaG_typeerror(L, t, \"index\");\n    if (ttisfunction(tm)) {\n      callTMres(L, val, tm, t, key);\n      return;\n    }\n    t = tm;  /* else repeat with `tm' */ \n  }\n  luaG_runerror(L, \"loop in gettable\");\n}\n\n\nvoid luaV_settable (lua_State *L, const TValue *t, TValue *key, StkId val) {\n  int loop;\n  TValue temp;\n  for (loop = 0; loop < MAXTAGLOOP; loop++) {\n    const TValue *tm;\n    if (ttistable(t)) {  /* `t' is a table? */\n      Table *h = hvalue(t);\n      TValue *oldval = luaH_set(L, h, key); /* do a primitive set */\n      if (!ttisnil(oldval) ||  /* result is no nil? */\n          (tm = fasttm(L, h->metatable, TM_NEWINDEX)) == NULL) { /* or no TM? */\n        setobj2t(L, oldval, val);\n        h->flags = 0;\n        luaC_barriert(L, h, val);\n        return;\n      }\n      /* else will try the tag method */\n    }\n    else if (ttisnil(tm = luaT_gettmbyobj(L, t, TM_NEWINDEX)))\n      luaG_typeerror(L, t, \"index\");\n    if (ttisfunction(tm)) {\n      callTM(L, tm, t, key, val);\n      return;\n    }\n    /* else repeat with `tm' */\n    setobj(L, &temp, tm);  /* avoid pointing inside table (may rehash) */\n    t = &temp;\n  }\n  luaG_runerror(L, \"loop in settable\");\n}\n\n\nstatic int call_binTM (lua_State *L, const TValue *p1, const TValue *p2,\n                       StkId res, TMS event) {\n  const TValue *tm = luaT_gettmbyobj(L, p1, event);  /* try first operand */\n  if (ttisnil(tm))\n    tm = luaT_gettmbyobj(L, p2, event);  /* try second operand */\n  if (ttisnil(tm)) return 0;\n  callTMres(L, res, tm, p1, p2);\n  return 1;\n}\n\n\nstatic const TValue *get_compTM (lua_State *L, Table *mt1, Table *mt2,\n                                  TMS event) {\n  const TValue *tm1 = fasttm(L, mt1, event);\n  const TValue *tm2;\n  if (tm1 == NULL) return NULL;  /* no metamethod */\n  if (mt1 == mt2) return tm1;  /* same metatables => same metamethods */\n  tm2 = fasttm(L, mt2, event);\n  if (tm2 == NULL) return NULL;  /* no metamethod */\n  if (luaO_rawequalObj(tm1, tm2))  /* same metamethods? */\n    return tm1;\n  return NULL;\n}\n\n\nstatic int call_orderTM (lua_State *L, const TValue *p1, const TValue *p2,\n                         TMS event) {\n  const TValue *tm1 = luaT_gettmbyobj(L, p1, event);\n  const TValue *tm2;\n  if (ttisnil(tm1)) return -1;  /* no metamethod? */\n  tm2 = luaT_gettmbyobj(L, p2, event);\n  if (!luaO_rawequalObj(tm1, tm2))  /* different metamethods? */\n    return -1;\n  callTMres(L, L->top, tm1, p1, p2);\n  return !l_isfalse(L->top);\n}\n\n\nstatic int l_strcmp (const TString *ls, const TString *rs) {\n  const char *l = getstr(ls);\n  size_t ll = ls->tsv.len;\n  const char *r = getstr(rs);\n  size_t lr = rs->tsv.len;\n  for (;;) {\n    int temp = strcoll(l, r);\n    if (temp != 0) return temp;\n    else {  /* strings are equal up to a `\\0' */\n      size_t len = strlen(l);  /* index of first `\\0' in both strings */\n      if (len == lr)  /* r is finished? */\n        return (len == ll) ? 0 : 1;\n      else if (len == ll)  /* l is finished? */\n        return -1;  /* l is smaller than r (because r is not finished) */\n      /* both strings longer than `len'; go on comparing (after the `\\0') */\n      len++;\n      l += len; ll -= len; r += len; lr -= len;\n    }\n  }\n}\n\n\nint luaV_lessthan (lua_State *L, const TValue *l, const TValue *r) {\n  int res;\n  if (ttype(l) != ttype(r))\n    return luaG_ordererror(L, l, r);\n  else if (ttisnumber(l))\n    return luai_numlt(nvalue(l), nvalue(r));\n  else if (ttisstring(l))\n    return l_strcmp(rawtsvalue(l), rawtsvalue(r)) < 0;\n  else if ((res = call_orderTM(L, l, r, TM_LT)) != -1)\n    return res;\n  return luaG_ordererror(L, l, r);\n}\n\n\nstatic int lessequal (lua_State *L, const TValue *l, const TValue *r) {\n  int res;\n  if (ttype(l) != ttype(r))\n    return luaG_ordererror(L, l, r);\n  else if (ttisnumber(l))\n    return luai_numle(nvalue(l), nvalue(r));\n  else if (ttisstring(l))\n    return l_strcmp(rawtsvalue(l), rawtsvalue(r)) <= 0;\n  else if ((res = call_orderTM(L, l, r, TM_LE)) != -1)  /* first try `le' */\n    return res;\n  else if ((res = call_orderTM(L, r, l, TM_LT)) != -1)  /* else try `lt' */\n    return !res;\n  return luaG_ordererror(L, l, r);\n}\n\n\nint luaV_equalval (lua_State *L, const TValue *t1, const TValue *t2) {\n  const TValue *tm;\n  lua_assert(ttype(t1) == ttype(t2));\n  switch (ttype(t1)) {\n    case LUA_TNIL: return 1;\n    case LUA_TNUMBER: return luai_numeq(nvalue(t1), nvalue(t2));\n    case LUA_TBOOLEAN: return bvalue(t1) == bvalue(t2);  /* true must be 1 !! */\n    case LUA_TLIGHTUSERDATA: return pvalue(t1) == pvalue(t2);\n    case LUA_TUSERDATA: {\n      if (uvalue(t1) == uvalue(t2)) return 1;\n      tm = get_compTM(L, uvalue(t1)->metatable, uvalue(t2)->metatable,\n                         TM_EQ);\n      break;  /* will try TM */\n    }\n    case LUA_TTABLE: {\n      if (hvalue(t1) == hvalue(t2)) return 1;\n      tm = get_compTM(L, hvalue(t1)->metatable, hvalue(t2)->metatable, TM_EQ);\n      break;  /* will try TM */\n    }\n    default: return gcvalue(t1) == gcvalue(t2);\n  }\n  if (tm == NULL) return 0;  /* no TM? */\n  callTMres(L, L->top, tm, t1, t2);  /* call TM */\n  return !l_isfalse(L->top);\n}\n\n\nvoid luaV_concat (lua_State *L, int total, int last) {\n  do {\n    StkId top = L->base + last + 1;\n    int n = 2;  /* number of elements handled in this pass (at least 2) */\n    if (!(ttisstring(top-2) || ttisnumber(top-2)) || !tostring(L, top-1)) {\n      if (!call_binTM(L, top-2, top-1, top-2, TM_CONCAT))\n        luaG_concaterror(L, top-2, top-1);\n    } else if (tsvalue(top-1)->len == 0)  /* second op is empty? */\n      (void)tostring(L, top - 2);  /* result is first op (as string) */\n    else {\n      /* at least two string values; get as many as possible */\n      size_t tl = tsvalue(top-1)->len;\n      char *buffer;\n      int i;\n      /* collect total length */\n      for (n = 1; n < total && tostring(L, top-n-1); n++) {\n        size_t l = tsvalue(top-n-1)->len;\n        if (l >= MAX_SIZET - tl) luaG_runerror(L, \"string length overflow\");\n        tl += l;\n      }\n      buffer = luaZ_openspace(L, &G(L)->buff, tl);\n      tl = 0;\n      for (i=n; i>0; i--) {  /* concat all strings */\n        size_t l = tsvalue(top-i)->len;\n        memcpy(buffer+tl, svalue(top-i), l);\n        tl += l;\n      }\n      setsvalue2s(L, top-n, luaS_newlstr(L, buffer, tl));\n    }\n    total -= n-1;  /* got `n' strings to create 1 new */\n    last -= n-1;\n  } while (total > 1);  /* repeat until only 1 result left */\n}\n\n\nstatic void Arith (lua_State *L, StkId ra, const TValue *rb,\n                   const TValue *rc, TMS op) {\n  TValue tempb, tempc;\n  const TValue *b, *c;\n  if ((b = luaV_tonumber(rb, &tempb)) != NULL &&\n      (c = luaV_tonumber(rc, &tempc)) != NULL) {\n    lua_Number nb = nvalue(b), nc = nvalue(c);\n    switch (op) {\n      case TM_ADD: setnvalue(ra, luai_numadd(nb, nc)); break;\n      case TM_SUB: setnvalue(ra, luai_numsub(nb, nc)); break;\n      case TM_MUL: setnvalue(ra, luai_nummul(nb, nc)); break;\n      case TM_DIV: setnvalue(ra, luai_numdiv(nb, nc)); break;\n      case TM_MOD: setnvalue(ra, luai_nummod(nb, nc)); break;\n      case TM_POW: setnvalue(ra, luai_numpow(nb, nc)); break;\n      case TM_UNM: setnvalue(ra, luai_numunm(nb)); break;\n      default: lua_assert(0); break;\n    }\n  }\n  else if (!call_binTM(L, rb, rc, ra, op))\n    luaG_aritherror(L, rb, rc);\n}\n\n\n\n/*\n** some macros for common tasks in `luaV_execute'\n*/\n\n#define runtime_check(L, c)\t{ if (!(c)) break; }\n\n#define RA(i)\t(base+GETARG_A(i))\n/* to be used after possible stack reallocation */\n#define RB(i)\tcheck_exp(getBMode(GET_OPCODE(i)) == OpArgR, base+GETARG_B(i))\n#define RC(i)\tcheck_exp(getCMode(GET_OPCODE(i)) == OpArgR, base+GETARG_C(i))\n#define RKB(i)\tcheck_exp(getBMode(GET_OPCODE(i)) == OpArgK, \\\n\tISK(GETARG_B(i)) ? k+INDEXK(GETARG_B(i)) : base+GETARG_B(i))\n#define RKC(i)\tcheck_exp(getCMode(GET_OPCODE(i)) == OpArgK, \\\n\tISK(GETARG_C(i)) ? k+INDEXK(GETARG_C(i)) : base+GETARG_C(i))\n#define KBx(i)\tcheck_exp(getBMode(GET_OPCODE(i)) == OpArgK, k+GETARG_Bx(i))\n\n\n#define dojump(L,pc,i)\t{(pc) += (i); luai_threadyield(L);}\n\n\n#define Protect(x)\t{ L->savedpc = pc; {x;}; base = L->base; }\n\n\n#define arith_op(op,tm) { \\\n        TValue *rb = RKB(i); \\\n        TValue *rc = RKC(i); \\\n        if (ttisnumber(rb) && ttisnumber(rc)) { \\\n          lua_Number nb = nvalue(rb), nc = nvalue(rc); \\\n          setnvalue(ra, op(nb, nc)); \\\n        } \\\n        else \\\n          Protect(Arith(L, ra, rb, rc, tm)); \\\n      }\n\n\n\nvoid luaV_execute (lua_State *L, int nexeccalls) {\n  LClosure *cl;\n  StkId base;\n  TValue *k;\n  const Instruction *pc;\n reentry:  /* entry point */\n  lua_assert(isLua(L->ci));\n  pc = L->savedpc;\n  cl = &clvalue(L->ci->func)->l;\n  base = L->base;\n  k = cl->p->k;\n  /* main loop of interpreter */\n  for (;;) {\n    const Instruction i = *pc++;\n    StkId ra;\n    if ((L->hookmask & (LUA_MASKLINE | LUA_MASKCOUNT)) &&\n        (--L->hookcount == 0 || L->hookmask & LUA_MASKLINE)) {\n      traceexec(L, pc);\n      if (L->status == LUA_YIELD) {  /* did hook yield? */\n        L->savedpc = pc - 1;\n        return;\n      }\n      base = L->base;\n    }\n    /* warning!! several calls may realloc the stack and invalidate `ra' */\n    ra = RA(i);\n    lua_assert(base == L->base && L->base == L->ci->base);\n    lua_assert(base <= L->top && L->top <= L->stack + L->stacksize);\n    lua_assert(L->top == L->ci->top || luaG_checkopenop(i));\n    switch (GET_OPCODE(i)) {\n      case OP_MOVE: {\n        setobjs2s(L, ra, RB(i));\n        continue;\n      }\n      case OP_LOADK: {\n        setobj2s(L, ra, KBx(i));\n        continue;\n      }\n      case OP_LOADBOOL: {\n        setbvalue(ra, GETARG_B(i));\n        if (GETARG_C(i)) pc++;  /* skip next instruction (if C) */\n        continue;\n      }\n      case OP_LOADNIL: {\n        TValue *rb = RB(i);\n        do {\n          setnilvalue(rb--);\n        } while (rb >= ra);\n        continue;\n      }\n      case OP_GETUPVAL: {\n        int b = GETARG_B(i);\n        setobj2s(L, ra, cl->upvals[b]->v);\n        continue;\n      }\n      case OP_GETGLOBAL: {\n        TValue g;\n        TValue *rb = KBx(i);\n        sethvalue(L, &g, cl->env);\n        lua_assert(ttisstring(rb));\n        Protect(luaV_gettable(L, &g, rb, ra));\n        continue;\n      }\n      case OP_GETTABLE: {\n        Protect(luaV_gettable(L, RB(i), RKC(i), ra));\n        continue;\n      }\n      case OP_SETGLOBAL: {\n        TValue g;\n        sethvalue(L, &g, cl->env);\n        lua_assert(ttisstring(KBx(i)));\n        Protect(luaV_settable(L, &g, KBx(i), ra));\n        continue;\n      }\n      case OP_SETUPVAL: {\n        UpVal *uv = cl->upvals[GETARG_B(i)];\n        setobj(L, uv->v, ra);\n        luaC_barrier(L, uv, ra);\n        continue;\n      }\n      case OP_SETTABLE: {\n        Protect(luaV_settable(L, ra, RKB(i), RKC(i)));\n        continue;\n      }\n      case OP_NEWTABLE: {\n        int b = GETARG_B(i);\n        int c = GETARG_C(i);\n        sethvalue(L, ra, luaH_new(L, luaO_fb2int(b), luaO_fb2int(c)));\n        Protect(luaC_checkGC(L));\n        continue;\n      }\n      case OP_SELF: {\n        StkId rb = RB(i);\n        setobjs2s(L, ra+1, rb);\n        Protect(luaV_gettable(L, rb, RKC(i), ra));\n        continue;\n      }\n      case OP_ADD: {\n        arith_op(luai_numadd, TM_ADD);\n        continue;\n      }\n      case OP_SUB: {\n        arith_op(luai_numsub, TM_SUB);\n        continue;\n      }\n      case OP_MUL: {\n        arith_op(luai_nummul, TM_MUL);\n        continue;\n      }\n      case OP_DIV: {\n        arith_op(luai_numdiv, TM_DIV);\n        continue;\n      }\n      case OP_MOD: {\n        arith_op(luai_nummod, TM_MOD);\n        continue;\n      }\n      case OP_POW: {\n        arith_op(luai_numpow, TM_POW);\n        continue;\n      }\n      case OP_UNM: {\n        TValue *rb = RB(i);\n        if (ttisnumber(rb)) {\n          lua_Number nb = nvalue(rb);\n          setnvalue(ra, luai_numunm(nb));\n        }\n        else {\n          Protect(Arith(L, ra, rb, rb, TM_UNM));\n        }\n        continue;\n      }\n      case OP_NOT: {\n        int res = l_isfalse(RB(i));  /* next assignment may change this value */\n        setbvalue(ra, res);\n        continue;\n      }\n      case OP_LEN: {\n        const TValue *rb = RB(i);\n        switch (ttype(rb)) {\n          case LUA_TTABLE: {\n            setnvalue(ra, cast_num(luaH_getn(hvalue(rb))));\n            break;\n          }\n          case LUA_TSTRING: {\n            setnvalue(ra, cast_num(tsvalue(rb)->len));\n            break;\n          }\n          default: {  /* try metamethod */\n            Protect(\n              if (!call_binTM(L, rb, luaO_nilobject, ra, TM_LEN))\n                luaG_typeerror(L, rb, \"get length of\");\n            )\n          }\n        }\n        continue;\n      }\n      case OP_CONCAT: {\n        int b = GETARG_B(i);\n        int c = GETARG_C(i);\n        Protect(luaV_concat(L, c-b+1, c); luaC_checkGC(L));\n        setobjs2s(L, RA(i), base+b);\n        continue;\n      }\n      case OP_JMP: {\n        dojump(L, pc, GETARG_sBx(i));\n        continue;\n      }\n      case OP_EQ: {\n        TValue *rb = RKB(i);\n        TValue *rc = RKC(i);\n        Protect(\n          if (equalobj(L, rb, rc) == GETARG_A(i))\n            dojump(L, pc, GETARG_sBx(*pc));\n        )\n        pc++;\n        continue;\n      }\n      case OP_LT: {\n        Protect(\n          if (luaV_lessthan(L, RKB(i), RKC(i)) == GETARG_A(i))\n            dojump(L, pc, GETARG_sBx(*pc));\n        )\n        pc++;\n        continue;\n      }\n      case OP_LE: {\n        Protect(\n          if (lessequal(L, RKB(i), RKC(i)) == GETARG_A(i))\n            dojump(L, pc, GETARG_sBx(*pc));\n        )\n        pc++;\n        continue;\n      }\n      case OP_TEST: {\n        if (l_isfalse(ra) != GETARG_C(i))\n          dojump(L, pc, GETARG_sBx(*pc));\n        pc++;\n        continue;\n      }\n      case OP_TESTSET: {\n        TValue *rb = RB(i);\n        if (l_isfalse(rb) != GETARG_C(i)) {\n          setobjs2s(L, ra, rb);\n          dojump(L, pc, GETARG_sBx(*pc));\n        }\n        pc++;\n        continue;\n      }\n      case OP_CALL: {\n        int b = GETARG_B(i);\n        int nresults = GETARG_C(i) - 1;\n        if (b != 0) L->top = ra+b;  /* else previous instruction set top */\n        L->savedpc = pc;\n        switch (luaD_precall(L, ra, nresults)) {\n          case PCRLUA: {\n            nexeccalls++;\n            goto reentry;  /* restart luaV_execute over new Lua function */\n          }\n          case PCRC: {\n            /* it was a C function (`precall' called it); adjust results */\n            if (nresults >= 0) L->top = L->ci->top;\n            base = L->base;\n            continue;\n          }\n          default: {\n            return;  /* yield */\n          }\n        }\n      }\n      case OP_TAILCALL: {\n        int b = GETARG_B(i);\n        if (b != 0) L->top = ra+b;  /* else previous instruction set top */\n        L->savedpc = pc;\n        lua_assert(GETARG_C(i) - 1 == LUA_MULTRET);\n        switch (luaD_precall(L, ra, LUA_MULTRET)) {\n          case PCRLUA: {\n            /* tail call: put new frame in place of previous one */\n            CallInfo *ci = L->ci - 1;  /* previous frame */\n            int aux;\n            StkId func = ci->func;\n            StkId pfunc = (ci+1)->func;  /* previous function index */\n            if (L->openupval) luaF_close(L, ci->base);\n            L->base = ci->base = ci->func + ((ci+1)->base - pfunc);\n            for (aux = 0; pfunc+aux < L->top; aux++)  /* move frame down */\n              setobjs2s(L, func+aux, pfunc+aux);\n            ci->top = L->top = func+aux;  /* correct top */\n            lua_assert(L->top == L->base + clvalue(func)->l.p->maxstacksize);\n            ci->savedpc = L->savedpc;\n            ci->tailcalls++;  /* one more call lost */\n            L->ci--;  /* remove new frame */\n            goto reentry;\n          }\n          case PCRC: {  /* it was a C function (`precall' called it) */\n            base = L->base;\n            continue;\n          }\n          default: {\n            return;  /* yield */\n          }\n        }\n      }\n      case OP_RETURN: {\n        int b = GETARG_B(i);\n        if (b != 0) L->top = ra+b-1;\n        if (L->openupval) luaF_close(L, base);\n        L->savedpc = pc;\n        b = luaD_poscall(L, ra);\n        if (--nexeccalls == 0)  /* was previous function running `here'? */\n          return;  /* no: return */\n        else {  /* yes: continue its execution */\n          if (b) L->top = L->ci->top;\n          lua_assert(isLua(L->ci));\n          lua_assert(GET_OPCODE(*((L->ci)->savedpc - 1)) == OP_CALL);\n          goto reentry;\n        }\n      }\n      case OP_FORLOOP: {\n        lua_Number step = nvalue(ra+2);\n        lua_Number idx = luai_numadd(nvalue(ra), step); /* increment index */\n        lua_Number limit = nvalue(ra+1);\n        if (luai_numlt(0, step) ? luai_numle(idx, limit)\n                                : luai_numle(limit, idx)) {\n          dojump(L, pc, GETARG_sBx(i));  /* jump back */\n          setnvalue(ra, idx);  /* update internal index... */\n          setnvalue(ra+3, idx);  /* ...and external index */\n        }\n        continue;\n      }\n      case OP_FORPREP: {\n        const TValue *init = ra;\n        const TValue *plimit = ra+1;\n        const TValue *pstep = ra+2;\n        L->savedpc = pc;  /* next steps may throw errors */\n        if (!tonumber(init, ra))\n          luaG_runerror(L, LUA_QL(\"for\") \" initial value must be a number\");\n        else if (!tonumber(plimit, ra+1))\n          luaG_runerror(L, LUA_QL(\"for\") \" limit must be a number\");\n        else if (!tonumber(pstep, ra+2))\n          luaG_runerror(L, LUA_QL(\"for\") \" step must be a number\");\n        setnvalue(ra, luai_numsub(nvalue(ra), nvalue(pstep)));\n        dojump(L, pc, GETARG_sBx(i));\n        continue;\n      }\n      case OP_TFORLOOP: {\n        StkId cb = ra + 3;  /* call base */\n        setobjs2s(L, cb+2, ra+2);\n        setobjs2s(L, cb+1, ra+1);\n        setobjs2s(L, cb, ra);\n        L->top = cb+3;  /* func. + 2 args (state and index) */\n        Protect(luaD_call(L, cb, GETARG_C(i)));\n        L->top = L->ci->top;\n        cb = RA(i) + 3;  /* previous call may change the stack */\n        if (!ttisnil(cb)) {  /* continue loop? */\n          setobjs2s(L, cb-1, cb);  /* save control variable */\n          dojump(L, pc, GETARG_sBx(*pc));  /* jump back */\n        }\n        pc++;\n        continue;\n      }\n      case OP_SETLIST: {\n        int n = GETARG_B(i);\n        int c = GETARG_C(i);\n        int last;\n        Table *h;\n        if (n == 0) {\n          n = cast_int(L->top - ra) - 1;\n          L->top = L->ci->top;\n        }\n        if (c == 0) c = cast_int(*pc++);\n        runtime_check(L, ttistable(ra));\n        h = hvalue(ra);\n        last = ((c-1)*LFIELDS_PER_FLUSH) + n;\n        if (last > h->sizearray)  /* needs more space? */\n          luaH_resizearray(L, h, last);  /* pre-alloc it at once */\n        for (; n > 0; n--) {\n          TValue *val = ra+n;\n          setobj2t(L, luaH_setnum(L, h, last--), val);\n          luaC_barriert(L, h, val);\n        }\n        continue;\n      }\n      case OP_CLOSE: {\n        luaF_close(L, ra);\n        continue;\n      }\n      case OP_CLOSURE: {\n        Proto *p;\n        Closure *ncl;\n        int nup, j;\n        p = cl->p->p[GETARG_Bx(i)];\n        nup = p->nups;\n        ncl = luaF_newLclosure(L, nup, cl->env);\n        ncl->l.p = p;\n        for (j=0; j<nup; j++, pc++) {\n          if (GET_OPCODE(*pc) == OP_GETUPVAL)\n            ncl->l.upvals[j] = cl->upvals[GETARG_B(*pc)];\n          else {\n            lua_assert(GET_OPCODE(*pc) == OP_MOVE);\n            ncl->l.upvals[j] = luaF_findupval(L, base + GETARG_B(*pc));\n          }\n        }\n        setclvalue(L, ra, ncl);\n        Protect(luaC_checkGC(L));\n        continue;\n      }\n      case OP_VARARG: {\n        int b = GETARG_B(i) - 1;\n        int j;\n        CallInfo *ci = L->ci;\n        int n = cast_int(ci->base - ci->func) - cl->p->numparams - 1;\n        if (b == LUA_MULTRET) {\n          Protect(luaD_checkstack(L, n));\n          ra = RA(i);  /* previous call may change the stack */\n          b = n;\n          L->top = ra + n;\n        }\n        for (j = 0; j < b; j++) {\n          if (j < n) {\n            setobjs2s(L, ra + j, ci->base - n + j);\n          }\n          else {\n            setnilvalue(ra + j);\n          }\n        }\n        continue;\n      }\n    }\n  }\n}\n\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/deps/lua/src/lvm.h",
    "content": "/*\n** $Id: lvm.h,v 2.5.1.1 2007/12/27 13:02:25 roberto Exp $\n** Lua virtual machine\n** See Copyright Notice in lua.h\n*/\n\n#ifndef lvm_h\n#define lvm_h\n\n\n#include \"ldo.h\"\n#include \"lobject.h\"\n#include \"ltm.h\"\n\n\n#define tostring(L,o) ((ttype(o) == LUA_TSTRING) || (luaV_tostring(L, o)))\n\n#define tonumber(o,n)\t(ttype(o) == LUA_TNUMBER || \\\n                         (((o) = luaV_tonumber(o,n)) != NULL))\n\n#define equalobj(L,o1,o2) \\\n\t(ttype(o1) == ttype(o2) && luaV_equalval(L, o1, o2))\n\n\nLUAI_FUNC int luaV_lessthan (lua_State *L, const TValue *l, const TValue *r);\nLUAI_FUNC int luaV_equalval (lua_State *L, const TValue *t1, const TValue *t2);\nLUAI_FUNC const TValue *luaV_tonumber (const TValue *obj, TValue *n);\nLUAI_FUNC int luaV_tostring (lua_State *L, StkId obj);\nLUAI_FUNC void luaV_gettable (lua_State *L, const TValue *t, TValue *key,\n                                            StkId val);\nLUAI_FUNC void luaV_settable (lua_State *L, const TValue *t, TValue *key,\n                                            StkId val);\nLUAI_FUNC void luaV_execute (lua_State *L, int nexeccalls);\nLUAI_FUNC void luaV_concat (lua_State *L, int total, int last);\n\n#endif\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/deps/lua/src/lzio.c",
    "content": "/*\n** $Id: lzio.c,v 1.31.1.1 2007/12/27 13:02:25 roberto Exp $\n** a generic input stream interface\n** See Copyright Notice in lua.h\n*/\n\n\n#include <string.h>\n\n#define lzio_c\n#define LUA_CORE\n\n#include \"lua.h\"\n\n#include \"llimits.h\"\n#include \"lmem.h\"\n#include \"lstate.h\"\n#include \"lzio.h\"\n\n\nint luaZ_fill (ZIO *z) {\n  size_t size;\n  lua_State *L = z->L;\n  const char *buff;\n  lua_unlock(L);\n  buff = z->reader(L, z->data, &size);\n  lua_lock(L);\n  if (buff == NULL || size == 0) return EOZ;\n  z->n = size - 1;\n  z->p = buff;\n  return char2int(*(z->p++));\n}\n\n\nint luaZ_lookahead (ZIO *z) {\n  if (z->n == 0) {\n    if (luaZ_fill(z) == EOZ)\n      return EOZ;\n    else {\n      z->n++;  /* luaZ_fill removed first byte; put back it */\n      z->p--;\n    }\n  }\n  return char2int(*z->p);\n}\n\n\nvoid luaZ_init (lua_State *L, ZIO *z, lua_Reader reader, void *data) {\n  z->L = L;\n  z->reader = reader;\n  z->data = data;\n  z->n = 0;\n  z->p = NULL;\n}\n\n\n/* --------------------------------------------------------------- read --- */\nsize_t luaZ_read (ZIO *z, void *b, size_t n) {\n  while (n) {\n    size_t m;\n    if (luaZ_lookahead(z) == EOZ)\n      return n;  /* return number of missing bytes */\n    m = (n <= z->n) ? n : z->n;  /* min. between n and z->n */\n    memcpy(b, z->p, m);\n    z->n -= m;\n    z->p += m;\n    b = (char *)b + m;\n    n -= m;\n  }\n  return 0;\n}\n\n/* ------------------------------------------------------------------------ */\nchar *luaZ_openspace (lua_State *L, Mbuffer *buff, size_t n) {\n  if (n > buff->buffsize) {\n    if (n < LUA_MINBUFFER) n = LUA_MINBUFFER;\n    luaZ_resizebuffer(L, buff, n);\n  }\n  return buff->buffer;\n}\n\n\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/deps/lua/src/lzio.h",
    "content": "/*\n** $Id: lzio.h,v 1.21.1.1 2007/12/27 13:02:25 roberto Exp $\n** Buffered streams\n** See Copyright Notice in lua.h\n*/\n\n\n#ifndef lzio_h\n#define lzio_h\n\n#include \"lua.h\"\n\n#include \"lmem.h\"\n\n\n#define EOZ\t(-1)\t\t\t/* end of stream */\n\ntypedef struct Zio ZIO;\n\n#define char2int(c)\tcast(int, cast(unsigned char, (c)))\n\n#define zgetc(z)  (((z)->n--)>0 ?  char2int(*(z)->p++) : luaZ_fill(z))\n\ntypedef struct Mbuffer {\n  char *buffer;\n  size_t n;\n  size_t buffsize;\n} Mbuffer;\n\n#define luaZ_initbuffer(L, buff) ((buff)->buffer = NULL, (buff)->buffsize = 0)\n\n#define luaZ_buffer(buff)\t((buff)->buffer)\n#define luaZ_sizebuffer(buff)\t((buff)->buffsize)\n#define luaZ_bufflen(buff)\t((buff)->n)\n\n#define luaZ_resetbuffer(buff) ((buff)->n = 0)\n\n\n#define luaZ_resizebuffer(L, buff, size) \\\n\t(luaM_reallocvector(L, (buff)->buffer, (buff)->buffsize, size, char), \\\n\t(buff)->buffsize = size)\n\n#define luaZ_freebuffer(L, buff)\tluaZ_resizebuffer(L, buff, 0)\n\n\nLUAI_FUNC char *luaZ_openspace (lua_State *L, Mbuffer *buff, size_t n);\nLUAI_FUNC void luaZ_init (lua_State *L, ZIO *z, lua_Reader reader,\n                                        void *data);\nLUAI_FUNC size_t luaZ_read (ZIO* z, void* b, size_t n);\t/* read next n bytes */\nLUAI_FUNC int luaZ_lookahead (ZIO *z);\n\n\n\n/* --------- Private Part ------------------ */\n\nstruct Zio {\n  size_t n;\t\t\t/* bytes still unread */\n  const char *p;\t\t/* current position in buffer */\n  lua_Reader reader;\n  void* data;\t\t\t/* additional data */\n  lua_State *L;\t\t\t/* Lua state (for reader) */\n};\n\n\nLUAI_FUNC int luaZ_fill (ZIO *z);\n\n#endif\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/deps/lua/src/print.c",
    "content": "/*\n** $Id: print.c,v 1.55a 2006/05/31 13:30:05 lhf Exp $\n** print bytecodes\n** See Copyright Notice in lua.h\n*/\n\n#include <ctype.h>\n#include <stdio.h>\n\n#define luac_c\n#define LUA_CORE\n\n#include \"ldebug.h\"\n#include \"lobject.h\"\n#include \"lopcodes.h\"\n#include \"lundump.h\"\n\n#define PrintFunction\tluaU_print\n\n#define Sizeof(x)\t((int)sizeof(x))\n#define VOID(p)\t\t((const void*)(p))\n\nstatic void PrintString(const TString* ts)\n{\n const char* s=getstr(ts);\n size_t i,n=ts->tsv.len;\n putchar('\"');\n for (i=0; i<n; i++)\n {\n  int c=s[i];\n  switch (c)\n  {\n   case '\"': printf(\"\\\\\\\"\"); break;\n   case '\\\\': printf(\"\\\\\\\\\"); break;\n   case '\\a': printf(\"\\\\a\"); break;\n   case '\\b': printf(\"\\\\b\"); break;\n   case '\\f': printf(\"\\\\f\"); break;\n   case '\\n': printf(\"\\\\n\"); break;\n   case '\\r': printf(\"\\\\r\"); break;\n   case '\\t': printf(\"\\\\t\"); break;\n   case '\\v': printf(\"\\\\v\"); break;\n   default:\tif (isprint((unsigned char)c))\n   \t\t\tputchar(c);\n\t\telse\n\t\t\tprintf(\"\\\\%03u\",(unsigned char)c);\n  }\n }\n putchar('\"');\n}\n\nstatic void PrintConstant(const Proto* f, int i)\n{\n const TValue* o=&f->k[i];\n switch (ttype(o))\n {\n  case LUA_TNIL:\n\tprintf(\"nil\");\n\tbreak;\n  case LUA_TBOOLEAN:\n\tprintf(bvalue(o) ? \"true\" : \"false\");\n\tbreak;\n  case LUA_TNUMBER:\n\tprintf(LUA_NUMBER_FMT,nvalue(o));\n\tbreak;\n  case LUA_TSTRING:\n\tPrintString(rawtsvalue(o));\n\tbreak;\n  default:\t\t\t\t/* cannot happen */\n\tprintf(\"? type=%d\",ttype(o));\n\tbreak;\n }\n}\n\nstatic void PrintCode(const Proto* f)\n{\n const Instruction* code=f->code;\n int pc,n=f->sizecode;\n for (pc=0; pc<n; pc++)\n {\n  Instruction i=code[pc];\n  OpCode o=GET_OPCODE(i);\n  int a=GETARG_A(i);\n  int b=GETARG_B(i);\n  int c=GETARG_C(i);\n  int bx=GETARG_Bx(i);\n  int sbx=GETARG_sBx(i);\n  int line=getline(f,pc);\n  printf(\"\\t%d\\t\",pc+1);\n  if (line>0) printf(\"[%d]\\t\",line); else printf(\"[-]\\t\");\n  printf(\"%-9s\\t\",luaP_opnames[o]);\n  switch (getOpMode(o))\n  {\n   case iABC:\n    printf(\"%d\",a);\n    if (getBMode(o)!=OpArgN) printf(\" %d\",ISK(b) ? (-1-INDEXK(b)) : b);\n    if (getCMode(o)!=OpArgN) printf(\" %d\",ISK(c) ? (-1-INDEXK(c)) : c);\n    break;\n   case iABx:\n    if (getBMode(o)==OpArgK) printf(\"%d %d\",a,-1-bx); else printf(\"%d %d\",a,bx);\n    break;\n   case iAsBx:\n    if (o==OP_JMP) printf(\"%d\",sbx); else printf(\"%d %d\",a,sbx);\n    break;\n  }\n  switch (o)\n  {\n   case OP_LOADK:\n    printf(\"\\t; \"); PrintConstant(f,bx);\n    break;\n   case OP_GETUPVAL:\n   case OP_SETUPVAL:\n    printf(\"\\t; %s\", (f->sizeupvalues>0) ? getstr(f->upvalues[b]) : \"-\");\n    break;\n   case OP_GETGLOBAL:\n   case OP_SETGLOBAL:\n    printf(\"\\t; %s\",svalue(&f->k[bx]));\n    break;\n   case OP_GETTABLE:\n   case OP_SELF:\n    if (ISK(c)) { printf(\"\\t; \"); PrintConstant(f,INDEXK(c)); }\n    break;\n   case OP_SETTABLE:\n   case OP_ADD:\n   case OP_SUB:\n   case OP_MUL:\n   case OP_DIV:\n   case OP_POW:\n   case OP_EQ:\n   case OP_LT:\n   case OP_LE:\n    if (ISK(b) || ISK(c))\n    {\n     printf(\"\\t; \");\n     if (ISK(b)) PrintConstant(f,INDEXK(b)); else printf(\"-\");\n     printf(\" \");\n     if (ISK(c)) PrintConstant(f,INDEXK(c)); else printf(\"-\");\n    }\n    break;\n   case OP_JMP:\n   case OP_FORLOOP:\n   case OP_FORPREP:\n    printf(\"\\t; to %d\",sbx+pc+2);\n    break;\n   case OP_CLOSURE:\n    printf(\"\\t; %p\",VOID(f->p[bx]));\n    break;\n   case OP_SETLIST:\n    if (c==0) printf(\"\\t; %d\",(int)code[++pc]);\n    else printf(\"\\t; %d\",c);\n    break;\n   default:\n    break;\n  }\n  printf(\"\\n\");\n }\n}\n\n#define SS(x)\t(x==1)?\"\":\"s\"\n#define S(x)\tx,SS(x)\n\nstatic void PrintHeader(const Proto* f)\n{\n const char* s=getstr(f->source);\n if (*s=='@' || *s=='=')\n  s++;\n else if (*s==LUA_SIGNATURE[0])\n  s=\"(bstring)\";\n else\n  s=\"(string)\";\n printf(\"\\n%s <%s:%d,%d> (%d instruction%s, %d bytes at %p)\\n\",\n \t(f->linedefined==0)?\"main\":\"function\",s,\n\tf->linedefined,f->lastlinedefined,\n\tS(f->sizecode),f->sizecode*Sizeof(Instruction),VOID(f));\n printf(\"%d%s param%s, %d slot%s, %d upvalue%s, \",\n\tf->numparams,f->is_vararg?\"+\":\"\",SS(f->numparams),\n\tS(f->maxstacksize),S(f->nups));\n printf(\"%d local%s, %d constant%s, %d function%s\\n\",\n\tS(f->sizelocvars),S(f->sizek),S(f->sizep));\n}\n\nstatic void PrintConstants(const Proto* f)\n{\n int i,n=f->sizek;\n printf(\"constants (%d) for %p:\\n\",n,VOID(f));\n for (i=0; i<n; i++)\n {\n  printf(\"\\t%d\\t\",i+1);\n  PrintConstant(f,i);\n  printf(\"\\n\");\n }\n}\n\nstatic void PrintLocals(const Proto* f)\n{\n int i,n=f->sizelocvars;\n printf(\"locals (%d) for %p:\\n\",n,VOID(f));\n for (i=0; i<n; i++)\n {\n  printf(\"\\t%d\\t%s\\t%d\\t%d\\n\",\n  i,getstr(f->locvars[i].varname),f->locvars[i].startpc+1,f->locvars[i].endpc+1);\n }\n}\n\nstatic void PrintUpvalues(const Proto* f)\n{\n int i,n=f->sizeupvalues;\n printf(\"upvalues (%d) for %p:\\n\",n,VOID(f));\n if (f->upvalues==NULL) return;\n for (i=0; i<n; i++)\n {\n  printf(\"\\t%d\\t%s\\n\",i,getstr(f->upvalues[i]));\n }\n}\n\nvoid PrintFunction(const Proto* f, int full)\n{\n int i,n=f->sizep;\n PrintHeader(f);\n PrintCode(f);\n if (full)\n {\n  PrintConstants(f);\n  PrintLocals(f);\n  PrintUpvalues(f);\n }\n for (i=0; i<n; i++) PrintFunction(f->p[i],full);\n}\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/deps/lua/src/strbuf.c",
    "content": "/* strbuf - String buffer routines\n *\n * Copyright (c) 2010-2012  Mark Pulford <mark@kyne.com.au>\n *\n * Permission is hereby granted, free of charge, to any person obtaining\n * a copy of this software and associated documentation files (the\n * \"Software\"), to deal in the Software without restriction, including\n * without limitation the rights to use, copy, modify, merge, publish,\n * distribute, sublicense, and/or sell copies of the Software, and to\n * permit persons to whom the Software is furnished to do so, subject to\n * the following conditions:\n *\n * The above copyright notice and this permission notice shall be\n * included in all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND,\n * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\n * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.\n * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY\n * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,\n * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE\n * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n */\n\n#include <stdio.h>\n#include <stdlib.h>\n#include <stdarg.h>\n#include <string.h>\n\n#include \"strbuf.h\"\n\nstatic void die(const char *fmt, ...)\n{\n    va_list arg;\n\n    va_start(arg, fmt);\n    vfprintf(stderr, fmt, arg);\n    va_end(arg);\n    fprintf(stderr, \"\\n\");\n\n    exit(-1);\n}\n\nvoid strbuf_init(strbuf_t *s, int len)\n{\n    int size;\n\n    if (len <= 0)\n        size = STRBUF_DEFAULT_SIZE;\n    else\n        size = len + 1;         /* \\0 terminator */\n\n    s->buf = NULL;\n    s->size = size;\n    s->length = 0;\n    s->increment = STRBUF_DEFAULT_INCREMENT;\n    s->dynamic = 0;\n    s->reallocs = 0;\n    s->debug = 0;\n\n    s->buf = malloc(size);\n    if (!s->buf)\n        die(\"Out of memory\");\n\n    strbuf_ensure_null(s);\n}\n\nstrbuf_t *strbuf_new(int len)\n{\n    strbuf_t *s;\n\n    s = malloc(sizeof(strbuf_t));\n    if (!s)\n        die(\"Out of memory\");\n\n    strbuf_init(s, len);\n\n    /* Dynamic strbuf allocation / deallocation */\n    s->dynamic = 1;\n\n    return s;\n}\n\nvoid strbuf_set_increment(strbuf_t *s, int increment)\n{\n    /* Increment > 0:  Linear buffer growth rate\n     * Increment < -1: Exponential buffer growth rate */\n    if (increment == 0 || increment == -1)\n        die(\"BUG: Invalid string increment\");\n\n    s->increment = increment;\n}\n\nstatic inline void debug_stats(strbuf_t *s)\n{\n    if (s->debug) {\n        fprintf(stderr, \"strbuf(%lx) reallocs: %d, length: %d, size: %d\\n\",\n                (long)s, s->reallocs, s->length, s->size);\n    }\n}\n\n/* If strbuf_t has not been dynamically allocated, strbuf_free() can\n * be called any number of times strbuf_init() */\nvoid strbuf_free(strbuf_t *s)\n{\n    debug_stats(s);\n\n    if (s->buf) {\n        free(s->buf);\n        s->buf = NULL;\n    }\n    if (s->dynamic)\n        free(s);\n}\n\nchar *strbuf_free_to_string(strbuf_t *s, int *len)\n{\n    char *buf;\n\n    debug_stats(s);\n\n    strbuf_ensure_null(s);\n\n    buf = s->buf;\n    if (len)\n        *len = s->length;\n\n    if (s->dynamic)\n        free(s);\n\n    return buf;\n}\n\nstatic int calculate_new_size(strbuf_t *s, int len)\n{\n    int reqsize, newsize;\n\n    if (len <= 0)\n        die(\"BUG: Invalid strbuf length requested\");\n\n    /* Ensure there is room for optional NULL termination */\n    reqsize = len + 1;\n\n    /* If the user has requested to shrink the buffer, do it exactly */\n    if (s->size > reqsize)\n        return reqsize;\n\n    newsize = s->size;\n    if (s->increment < 0) {\n        /* Exponential sizing */\n        while (newsize < reqsize)\n            newsize *= -s->increment;\n    } else {\n        /* Linear sizing */\n        newsize = ((newsize + s->increment - 1) / s->increment) * s->increment;\n    }\n\n    return newsize;\n}\n\n\n/* Ensure strbuf can handle a string length bytes long (ignoring NULL\n * optional termination). */\nvoid strbuf_resize(strbuf_t *s, int len)\n{\n    int newsize;\n\n    newsize = calculate_new_size(s, len);\n\n    if (s->debug > 1) {\n        fprintf(stderr, \"strbuf(%lx) resize: %d => %d\\n\",\n                (long)s, s->size, newsize);\n    }\n\n    s->size = newsize;\n    s->buf = realloc(s->buf, s->size);\n    if (!s->buf)\n        die(\"Out of memory\");\n    s->reallocs++;\n}\n\nvoid strbuf_append_string(strbuf_t *s, const char *str)\n{\n    int space, i;\n\n    space = strbuf_empty_length(s);\n\n    for (i = 0; str[i]; i++) {\n        if (space < 1) {\n            strbuf_resize(s, s->length + 1);\n            space = strbuf_empty_length(s);\n        }\n\n        s->buf[s->length] = str[i];\n        s->length++;\n        space--;\n    }\n}\n\n/* strbuf_append_fmt() should only be used when an upper bound\n * is known for the output string. */\nvoid strbuf_append_fmt(strbuf_t *s, int len, const char *fmt, ...)\n{\n    va_list arg;\n    int fmt_len;\n\n    strbuf_ensure_empty_length(s, len);\n\n    va_start(arg, fmt);\n    fmt_len = vsnprintf(s->buf + s->length, len, fmt, arg);\n    va_end(arg);\n\n    if (fmt_len < 0)\n        die(\"BUG: Unable to convert number\");  /* This should never happen.. */\n\n    s->length += fmt_len;\n}\n\n/* strbuf_append_fmt_retry() can be used when the there is no known\n * upper bound for the output string. */\nvoid strbuf_append_fmt_retry(strbuf_t *s, const char *fmt, ...)\n{\n    va_list arg;\n    int fmt_len, try;\n    int empty_len;\n\n    /* If the first attempt to append fails, resize the buffer appropriately\n     * and try again */\n    for (try = 0; ; try++) {\n        va_start(arg, fmt);\n        /* Append the new formatted string */\n        /* fmt_len is the length of the string required, excluding the\n         * trailing NULL */\n        empty_len = strbuf_empty_length(s);\n        /* Add 1 since there is also space to store the terminating NULL. */\n        fmt_len = vsnprintf(s->buf + s->length, empty_len + 1, fmt, arg);\n        va_end(arg);\n\n        if (fmt_len <= empty_len)\n            break;  /* SUCCESS */\n        if (try > 0)\n            die(\"BUG: length of formatted string changed\");\n\n        strbuf_resize(s, s->length + fmt_len);\n    }\n\n    s->length += fmt_len;\n}\n\n/* vi:ai et sw=4 ts=4:\n */\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/deps/lua/src/strbuf.h",
    "content": "/* strbuf - String buffer routines\n *\n * Copyright (c) 2010-2012  Mark Pulford <mark@kyne.com.au>\n *\n * Permission is hereby granted, free of charge, to any person obtaining\n * a copy of this software and associated documentation files (the\n * \"Software\"), to deal in the Software without restriction, including\n * without limitation the rights to use, copy, modify, merge, publish,\n * distribute, sublicense, and/or sell copies of the Software, and to\n * permit persons to whom the Software is furnished to do so, subject to\n * the following conditions:\n *\n * The above copyright notice and this permission notice shall be\n * included in all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND,\n * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\n * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.\n * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY\n * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,\n * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE\n * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n */\n\n#include <stdlib.h>\n#include <stdarg.h>\n\n/* Size: Total bytes allocated to *buf\n * Length: String length, excluding optional NULL terminator.\n * Increment: Allocation increments when resizing the string buffer.\n * Dynamic: True if created via strbuf_new()\n */\n\ntypedef struct {\n    char *buf;\n    int size;\n    int length;\n    int increment;\n    int dynamic;\n    int reallocs;\n    int debug;\n} strbuf_t;\n\n#ifndef STRBUF_DEFAULT_SIZE\n#define STRBUF_DEFAULT_SIZE 1023\n#endif\n#ifndef STRBUF_DEFAULT_INCREMENT\n#define STRBUF_DEFAULT_INCREMENT -2\n#endif\n\n/* Initialise */\nextern strbuf_t *strbuf_new(int len);\nextern void strbuf_init(strbuf_t *s, int len);\nextern void strbuf_set_increment(strbuf_t *s, int increment);\n\n/* Release */\nextern void strbuf_free(strbuf_t *s);\nextern char *strbuf_free_to_string(strbuf_t *s, int *len);\n\n/* Management */\nextern void strbuf_resize(strbuf_t *s, int len);\nstatic int strbuf_empty_length(strbuf_t *s);\nstatic int strbuf_length(strbuf_t *s);\nstatic char *strbuf_string(strbuf_t *s, int *len);\nstatic void strbuf_ensure_empty_length(strbuf_t *s, int len);\nstatic char *strbuf_empty_ptr(strbuf_t *s);\nstatic void strbuf_extend_length(strbuf_t *s, int len);\n\n/* Update */\nextern void strbuf_append_fmt(strbuf_t *s, int len, const char *fmt, ...);\nextern void strbuf_append_fmt_retry(strbuf_t *s, const char *format, ...);\nstatic void strbuf_append_mem(strbuf_t *s, const char *c, int len);\nextern void strbuf_append_string(strbuf_t *s, const char *str);\nstatic void strbuf_append_char(strbuf_t *s, const char c);\nstatic void strbuf_ensure_null(strbuf_t *s);\n\n/* Reset string for before use */\nstatic inline void strbuf_reset(strbuf_t *s)\n{\n    s->length = 0;\n}\n\nstatic inline int strbuf_allocated(strbuf_t *s)\n{\n    return s->buf != NULL;\n}\n\n/* Return bytes remaining in the string buffer\n * Ensure there is space for a NULL terminator. */\nstatic inline int strbuf_empty_length(strbuf_t *s)\n{\n    return s->size - s->length - 1;\n}\n\nstatic inline void strbuf_ensure_empty_length(strbuf_t *s, int len)\n{\n    if (len > strbuf_empty_length(s))\n        strbuf_resize(s, s->length + len);\n}\n\nstatic inline char *strbuf_empty_ptr(strbuf_t *s)\n{\n    return s->buf + s->length;\n}\n\nstatic inline void strbuf_extend_length(strbuf_t *s, int len)\n{\n    s->length += len;\n}\n\nstatic inline int strbuf_length(strbuf_t *s)\n{\n    return s->length;\n}\n\nstatic inline void strbuf_append_char(strbuf_t *s, const char c)\n{\n    strbuf_ensure_empty_length(s, 1);\n    s->buf[s->length++] = c;\n}\n\nstatic inline void strbuf_append_char_unsafe(strbuf_t *s, const char c)\n{\n    s->buf[s->length++] = c;\n}\n\nstatic inline void strbuf_append_mem(strbuf_t *s, const char *c, int len)\n{\n    strbuf_ensure_empty_length(s, len);\n    memcpy(s->buf + s->length, c, len);\n    s->length += len;\n}\n\nstatic inline void strbuf_append_mem_unsafe(strbuf_t *s, const char *c, int len)\n{\n    memcpy(s->buf + s->length, c, len);\n    s->length += len;\n}\n\nstatic inline void strbuf_ensure_null(strbuf_t *s)\n{\n    s->buf[s->length] = 0;\n}\n\nstatic inline char *strbuf_string(strbuf_t *s, int *len)\n{\n    if (len)\n        *len = s->length;\n\n    return s->buf;\n}\n\n/* vi:ai et sw=4 ts=4:\n */\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/deps/lua/test/README",
    "content": "These are simple tests for Lua.  Some of them contain useful code.\nThey are meant to be run to make sure Lua is built correctly and also\nto be read, to see how Lua programs look.\n\nHere is a one-line summary of each program:\n\n   bisect.lua\t\tbisection method for solving non-linear equations\n   cf.lua\t\ttemperature conversion table (celsius to farenheit)\n   echo.lua             echo command line arguments\n   env.lua              environment variables as automatic global variables\n   factorial.lua\tfactorial without recursion\n   fib.lua\t\tfibonacci function with cache\n   fibfor.lua\t\tfibonacci numbers with coroutines and generators\n   globals.lua\t\treport global variable usage\n   hello.lua\t\tthe first program in every language\n   life.lua\t\tConway's Game of Life\n   luac.lua\t \tbare-bones luac\n   printf.lua\t\tan implementation of printf\n   readonly.lua\t\tmake global variables readonly\n   sieve.lua\t\tthe sieve of of Eratosthenes programmed with coroutines\n   sort.lua\t\ttwo implementations of a sort function\n   table.lua\t\tmake table, grouping all data for the same item\n   trace-calls.lua\ttrace calls\n   trace-globals.lua\ttrace assigments to global variables\n   xd.lua\t\thex dump\n\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/deps/lua/test/bisect.lua",
    "content": "-- bisection method for solving non-linear equations\n\ndelta=1e-6\t-- tolerance\n\nfunction bisect(f,a,b,fa,fb)\n local c=(a+b)/2\n io.write(n,\" c=\",c,\" a=\",a,\" b=\",b,\"\\n\")\n if c==a or c==b or math.abs(a-b)<delta then return c,b-a end\n n=n+1\n local fc=f(c)\n if fa*fc<0 then return bisect(f,a,c,fa,fc) else return bisect(f,c,b,fc,fb) end\nend\n\n-- find root of f in the inverval [a,b]. needs f(a)*f(b)<0\nfunction solve(f,a,b)\n n=0\n local z,e=bisect(f,a,b,f(a),f(b))\n io.write(string.format(\"after %d steps, root is %.17g with error %.1e, f=%.1e\\n\",n,z,e,f(z)))\nend\n\n-- our function\nfunction f(x)\n return x*x*x-x-1\nend\n\n-- find zero in [1,2]\nsolve(f,1,2)\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/deps/lua/test/cf.lua",
    "content": "-- temperature conversion table (celsius to farenheit)\n\nfor c0=-20,50-1,10 do\n\tio.write(\"C \")\n\tfor c=c0,c0+10-1 do\n\t\tio.write(string.format(\"%3.0f \",c))\n\tend\n\tio.write(\"\\n\")\n\t\n\tio.write(\"F \")\n\tfor c=c0,c0+10-1 do\n\t\tf=(9/5)*c+32\n\t\tio.write(string.format(\"%3.0f \",f))\n\tend\n\tio.write(\"\\n\\n\")\nend\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/deps/lua/test/echo.lua",
    "content": "-- echo command line arguments\n\nfor i=0,table.getn(arg) do\n print(i,arg[i])\nend\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/deps/lua/test/env.lua",
    "content": "-- read environment variables as if they were global variables\n\nlocal f=function (t,i) return os.getenv(i) end\nsetmetatable(getfenv(),{__index=f})\n\n-- an example\nprint(a,USER,PATH)\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/deps/lua/test/factorial.lua",
    "content": "-- function closures are powerful\n\n-- traditional fixed-point operator from functional programming\nY = function (g)\n      local a = function (f) return f(f) end\n      return a(function (f)\n                 return g(function (x)\n                             local c=f(f)\n                             return c(x)\n                           end)\n               end)\nend\n\n\n-- factorial without recursion\nF = function (f)\n      return function (n)\n               if n == 0 then return 1\n               else return n*f(n-1) end\n             end\n    end\n\nfactorial = Y(F)   -- factorial is the fixed point of F\n\n-- now test it\nfunction test(x)\n\tio.write(x,\"! = \",factorial(x),\"\\n\")\nend\n\nfor n=0,16 do\n\ttest(n)\nend\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/deps/lua/test/fib.lua",
    "content": "-- fibonacci function with cache\n\n-- very inefficient fibonacci function\nfunction fib(n)\n\tN=N+1\n\tif n<2 then\n\t\treturn n\n\telse\n\t\treturn fib(n-1)+fib(n-2)\n\tend\nend\n\n-- a general-purpose value cache\nfunction cache(f)\n\tlocal c={}\n\treturn function (x)\n\t\tlocal y=c[x]\n\t\tif not y then\n\t\t\ty=f(x)\n\t\t\tc[x]=y\n\t\tend\n\t\treturn y\n\tend\nend\n\n-- run and time it\nfunction test(s,f)\n\tN=0\n\tlocal c=os.clock()\n\tlocal v=f(n)\n\tlocal t=os.clock()-c\n\tprint(s,n,v,t,N)\nend\n\nn=arg[1] or 24\t\t-- for other values, do lua fib.lua XX\nn=tonumber(n)\nprint(\"\",\"n\",\"value\",\"time\",\"evals\")\ntest(\"plain\",fib)\nfib=cache(fib)\ntest(\"cached\",fib)\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/deps/lua/test/fibfor.lua",
    "content": "-- example of for with generator functions\n\nfunction generatefib (n)\n  return coroutine.wrap(function ()\n    local a,b = 1, 1\n    while a <= n do\n      coroutine.yield(a)\n      a, b = b, a+b\n    end\n  end)\nend\n\nfor i in generatefib(1000) do print(i) end\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/deps/lua/test/globals.lua",
    "content": "-- reads luac listings and reports global variable usage\n-- lines where a global is written to are marked with \"*\"\n-- typical usage: luac -p -l file.lua | lua globals.lua | sort | lua table.lua\n\nwhile 1 do\n local s=io.read()\n if s==nil then break end\n local ok,_,l,op,g=string.find(s,\"%[%-?(%d*)%]%s*([GS])ETGLOBAL.-;%s+(.*)$\")\n if ok then\n  if op==\"S\" then op=\"*\" else op=\"\" end\n  io.write(g,\"\\t\",l,op,\"\\n\")\n end\nend\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/deps/lua/test/hello.lua",
    "content": "-- the first program in every language\n\nio.write(\"Hello world, from \",_VERSION,\"!\\n\")\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/deps/lua/test/life.lua",
    "content": "-- life.lua\n-- original by Dave Bollinger <DBollinger@compuserve.com> posted to lua-l\n-- modified to use ANSI terminal escape sequences\n-- modified to use for instead of while\n\nlocal write=io.write\n\nALIVE=\"\"\tDEAD=\"\"\nALIVE=\"O\"\tDEAD=\"-\"\n\nfunction delay() -- NOTE: SYSTEM-DEPENDENT, adjust as necessary\n  for i=1,10000 do end\n  -- local i=os.clock()+1 while(os.clock()<i) do end\nend\n\nfunction ARRAY2D(w,h)\n  local t = {w=w,h=h}\n  for y=1,h do\n    t[y] = {}\n    for x=1,w do\n      t[y][x]=0\n    end\n  end\n  return t\nend\n\n_CELLS = {}\n\n-- give birth to a \"shape\" within the cell array\nfunction _CELLS:spawn(shape,left,top)\n  for y=0,shape.h-1 do\n    for x=0,shape.w-1 do\n      self[top+y][left+x] = shape[y*shape.w+x+1]\n    end\n  end\nend\n\n-- run the CA and produce the next generation\nfunction _CELLS:evolve(next)\n  local ym1,y,yp1,yi=self.h-1,self.h,1,self.h\n  while yi > 0 do\n    local xm1,x,xp1,xi=self.w-1,self.w,1,self.w\n    while xi > 0 do\n      local sum = self[ym1][xm1] + self[ym1][x] + self[ym1][xp1] +\n                  self[y][xm1] + self[y][xp1] +\n                  self[yp1][xm1] + self[yp1][x] + self[yp1][xp1]\n      next[y][x] = ((sum==2) and self[y][x]) or ((sum==3) and 1) or 0\n      xm1,x,xp1,xi = x,xp1,xp1+1,xi-1\n    end\n    ym1,y,yp1,yi = y,yp1,yp1+1,yi-1\n  end\nend\n\n-- output the array to screen\nfunction _CELLS:draw()\n  local out=\"\" -- accumulate to reduce flicker\n  for y=1,self.h do\n   for x=1,self.w do\n      out=out..(((self[y][x]>0) and ALIVE) or DEAD)\n    end\n    out=out..\"\\n\"\n  end\n  write(out)\nend\n\n-- constructor\nfunction CELLS(w,h)\n  local c = ARRAY2D(w,h)\n  c.spawn = _CELLS.spawn\n  c.evolve = _CELLS.evolve\n  c.draw = _CELLS.draw\n  return c\nend\n\n--\n-- shapes suitable for use with spawn() above\n--\nHEART = { 1,0,1,1,0,1,1,1,1; w=3,h=3 }\nGLIDER = { 0,0,1,1,0,1,0,1,1; w=3,h=3 }\nEXPLODE = { 0,1,0,1,1,1,1,0,1,0,1,0; w=3,h=4 }\nFISH = { 0,1,1,1,1,1,0,0,0,1,0,0,0,0,1,1,0,0,1,0; w=5,h=4 }\nBUTTERFLY = { 1,0,0,0,1,0,1,1,1,0,1,0,0,0,1,1,0,1,0,1,1,0,0,0,1; w=5,h=5 }\n\n-- the main routine\nfunction LIFE(w,h)\n  -- create two arrays\n  local thisgen = CELLS(w,h)\n  local nextgen = CELLS(w,h)\n\n  -- create some life\n  -- about 1000 generations of fun, then a glider steady-state\n  thisgen:spawn(GLIDER,5,4)\n  thisgen:spawn(EXPLODE,25,10)\n  thisgen:spawn(FISH,4,12)\n\n  -- run until break\n  local gen=1\n  write(\"\\027[2J\")\t-- ANSI clear screen\n  while 1 do\n    thisgen:evolve(nextgen)\n    thisgen,nextgen = nextgen,thisgen\n    write(\"\\027[H\")\t-- ANSI home cursor\n    thisgen:draw()\n    write(\"Life - generation \",gen,\"\\n\")\n    gen=gen+1\n    if gen>2000 then break end\n    --delay()\t\t-- no delay\n  end\nend\n\nLIFE(40,20)\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/deps/lua/test/luac.lua",
    "content": "-- bare-bones luac in Lua\n-- usage: lua luac.lua file.lua\n\nassert(arg[1]~=nil and arg[2]==nil,\"usage: lua luac.lua file.lua\")\nf=assert(io.open(\"luac.out\",\"wb\"))\nassert(f:write(string.dump(assert(loadfile(arg[1])))))\nassert(f:close())\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/deps/lua/test/printf.lua",
    "content": "-- an implementation of printf\n\nfunction printf(...)\n io.write(string.format(...))\nend\n\nprintf(\"Hello %s from %s on %s\\n\",os.getenv\"USER\" or \"there\",_VERSION,os.date())\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/deps/lua/test/readonly.lua",
    "content": "-- make global variables readonly\n\nlocal f=function (t,i) error(\"cannot redefine global variable `\"..i..\"'\",2) end\nlocal g={}\nlocal G=getfenv()\nsetmetatable(g,{__index=G,__newindex=f})\nsetfenv(1,g)\n\n-- an example\nrawset(g,\"x\",3)\nx=2\ny=1\t-- cannot redefine `y'\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/deps/lua/test/sieve.lua",
    "content": "-- the sieve of of Eratosthenes programmed with coroutines\n-- typical usage: lua -e N=1000 sieve.lua | column\n\n-- generate all the numbers from 2 to n\nfunction gen (n)\n  return coroutine.wrap(function ()\n    for i=2,n do coroutine.yield(i) end\n  end)\nend\n\n-- filter the numbers generated by `g', removing multiples of `p'\nfunction filter (p, g)\n  return coroutine.wrap(function ()\n    while 1 do\n      local n = g()\n      if n == nil then return end\n      if math.mod(n, p) ~= 0 then coroutine.yield(n) end\n    end\n  end)\nend\n\nN=N or 1000\t\t-- from command line\nx = gen(N)\t\t-- generate primes up to N\nwhile 1 do\n  local n = x()\t\t-- pick a number until done\n  if n == nil then break end\n  print(n)\t\t-- must be a prime number\n  x = filter(n, x)\t-- now remove its multiples\nend\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/deps/lua/test/sort.lua",
    "content": "-- two implementations of a sort function\n-- this is an example only. Lua has now a built-in function \"sort\"\n\n-- extracted from Programming Pearls, page 110\nfunction qsort(x,l,u,f)\n if l<u then\n  local m=math.random(u-(l-1))+l-1\t-- choose a random pivot in range l..u\n  x[l],x[m]=x[m],x[l]\t\t\t-- swap pivot to first position\n  local t=x[l]\t\t\t\t-- pivot value\n  m=l\n  local i=l+1\n  while i<=u do\n    -- invariant: x[l+1..m] < t <= x[m+1..i-1]\n    if f(x[i],t) then\n      m=m+1\n      x[m],x[i]=x[i],x[m]\t\t-- swap x[i] and x[m]\n    end\n    i=i+1\n  end\n  x[l],x[m]=x[m],x[l]\t\t\t-- swap pivot to a valid place\n  -- x[l+1..m-1] < x[m] <= x[m+1..u]\n  qsort(x,l,m-1,f)\n  qsort(x,m+1,u,f)\n end\nend\n\nfunction selectionsort(x,n,f)\n local i=1\n while i<=n do\n  local m,j=i,i+1\n  while j<=n do\n   if f(x[j],x[m]) then m=j end\n   j=j+1\n  end\n x[i],x[m]=x[m],x[i]\t\t\t-- swap x[i] and x[m]\n i=i+1\n end\nend\n\nfunction show(m,x)\n io.write(m,\"\\n\\t\")\n local i=1\n while x[i] do\n  io.write(x[i])\n  i=i+1\n  if x[i] then io.write(\",\") end\n end\n io.write(\"\\n\")\nend\n\nfunction testsorts(x)\n local n=1\n while x[n] do n=n+1 end; n=n-1\t\t-- count elements\n show(\"original\",x)\n qsort(x,1,n,function (x,y) return x<y end)\n show(\"after quicksort\",x)\n selectionsort(x,n,function (x,y) return x>y end)\n show(\"after reverse selection sort\",x)\n qsort(x,1,n,function (x,y) return x<y end)\n show(\"after quicksort again\",x)\nend\n\n-- array to be sorted\nx={\"Jan\",\"Feb\",\"Mar\",\"Apr\",\"May\",\"Jun\",\"Jul\",\"Aug\",\"Sep\",\"Oct\",\"Nov\",\"Dec\"}\n\ntestsorts(x)\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/deps/lua/test/table.lua",
    "content": "-- make table, grouping all data for the same item\n-- input is 2 columns (item, data)\n\nlocal A\nwhile 1 do\n local l=io.read()\n if l==nil then break end\n local _,_,a,b=string.find(l,'\"?([_%w]+)\"?%s*(.*)$')\n if a~=A then A=a io.write(\"\\n\",a,\":\") end\n io.write(\" \",b)\nend\nio.write(\"\\n\")\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/deps/lua/test/trace-calls.lua",
    "content": "-- trace calls\n-- example: lua -ltrace-calls bisect.lua\n\nlocal level=0\n\nlocal function hook(event)\n local t=debug.getinfo(3)\n io.write(level,\" >>> \",string.rep(\" \",level))\n if t~=nil and t.currentline>=0 then io.write(t.short_src,\":\",t.currentline,\" \") end\n t=debug.getinfo(2)\n if event==\"call\" then\n  level=level+1\n else\n  level=level-1 if level<0 then level=0 end\n end\n if t.what==\"main\" then\n  if event==\"call\" then\n   io.write(\"begin \",t.short_src)\n  else\n   io.write(\"end \",t.short_src)\n  end\n elseif t.what==\"Lua\" then\n-- table.foreach(t,print)\n  io.write(event,\" \",t.name or \"(Lua)\",\" <\",t.linedefined,\":\",t.short_src,\">\")\n else\n io.write(event,\" \",t.name or \"(C)\",\" [\",t.what,\"] \")\n end\n io.write(\"\\n\")\nend\n\ndebug.sethook(hook,\"cr\")\nlevel=0\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/deps/lua/test/trace-globals.lua",
    "content": "-- trace assigments to global variables\n\ndo\n -- a tostring that quotes strings. note the use of the original tostring.\n local _tostring=tostring\n local tostring=function(a)\n  if type(a)==\"string\" then\n   return string.format(\"%q\",a)\n  else\n   return _tostring(a)\n  end\n end\n\n local log=function (name,old,new)\n  local t=debug.getinfo(3,\"Sl\")\n  local line=t.currentline\n  io.write(t.short_src)\n  if line>=0 then io.write(\":\",line) end\n  io.write(\": \",name,\" is now \",tostring(new),\" (was \",tostring(old),\")\",\"\\n\")\n end\n\n local g={}\n local set=function (t,name,value)\n  log(name,g[name],value)\n  g[name]=value\n end\n setmetatable(getfenv(),{__index=g,__newindex=set})\nend\n\n-- an example\n\na=1\nb=2\na=10\nb=20\nb=nil\nb=200\nprint(a,b,c)\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/deps/lua/test/xd.lua",
    "content": "-- hex dump\n-- usage: lua xd.lua < file\n\nlocal offset=0\nwhile true do\n local s=io.read(16)\n if s==nil then return end\n io.write(string.format(\"%08X  \",offset))\n string.gsub(s,\"(.)\",\n\tfunction (c) io.write(string.format(\"%02X \",string.byte(c))) end)\n io.write(string.rep(\" \",3*(16-string.len(s))))\n io.write(\" \",string.gsub(s,\"%c\",\".\"),\"\\n\") \n offset=offset+16\nend\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/deps/update-jemalloc.sh",
    "content": "#!/bin/bash\nVER=$1\nURL=\"http://www.canonware.com/download/jemalloc/jemalloc-${VER}.tar.bz2\"\necho \"Downloading $URL\"\ncurl $URL > /tmp/jemalloc.tar.bz2\ntar xvjf /tmp/jemalloc.tar.bz2\nrm -rf jemalloc\nmv jemalloc-${VER} jemalloc\necho \"Use git status, add all files and commit changes.\"\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/redis.conf",
    "content": "# Redis configuration file example.\n#\n# Note that in order to read the configuration file, Redis must be\n# started with the file path as first argument:\n#\n# ./redis-server /path/to/redis.conf\n\n# Note on units: when memory size is needed, it is possible to specify\n# it in the usual form of 1k 5GB 4M and so forth:\n#\n# 1k => 1000 bytes\n# 1kb => 1024 bytes\n# 1m => 1000000 bytes\n# 1mb => 1024*1024 bytes\n# 1g => 1000000000 bytes\n# 1gb => 1024*1024*1024 bytes\n#\n# units are case insensitive so 1GB 1Gb 1gB are all the same.\n\n################################## INCLUDES ###################################\n\n# Include one or more other config files here.  This is useful if you\n# have a standard template that goes to all Redis servers but also need\n# to customize a few per-server settings.  Include files can include\n# other files, so use this wisely.\n#\n# Notice option \"include\" won't be rewritten by command \"CONFIG REWRITE\"\n# from admin or Redis Sentinel. Since Redis always uses the last processed\n# line as value of a configuration directive, you'd better put includes\n# at the beginning of this file to avoid overwriting config change at runtime.\n#\n# If instead you are interested in using includes to override configuration\n# options, it is better to use include as the last line.\n#\n# include /path/to/local.conf\n# include /path/to/other.conf\n\n################################## NETWORK #####################################\n\n# By default, if no \"bind\" configuration directive is specified, Redis listens\n# for connections from all the network interfaces available on the server.\n# It is possible to listen to just one or multiple selected interfaces using\n# the \"bind\" configuration directive, followed by one or more IP addresses.\n#\n# Examples:\n#\n# bind 192.168.1.100 10.0.0.1\n# bind 127.0.0.1 ::1\n#\n# ~~~ WARNING ~~~ If the computer running Redis is directly exposed to the\n# internet, binding to all the interfaces is dangerous and will expose the\n# instance to everybody on the internet. So by default we uncomment the\n# following bind directive, that will force Redis to listen only into\n# the IPv4 lookback interface address (this means Redis will be able to\n# accept connections only from clients running into the same computer it\n# is running).\n#\n# IF YOU ARE SURE YOU WANT YOUR INSTANCE TO LISTEN TO ALL THE INTERFACES\n# JUST COMMENT THE FOLLOWING LINE.\n# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\nbind 127.0.0.1\n\n# Protected mode is a layer of security protection, in order to avoid that\n# Redis instances left open on the internet are accessed and exploited.\n#\n# When protected mode is on and if:\n#\n# 1) The server is not binding explicitly to a set of addresses using the\n#    \"bind\" directive.\n# 2) No password is configured.\n#\n# The server only accepts connections from clients connecting from the\n# IPv4 and IPv6 loopback addresses 127.0.0.1 and ::1, and from Unix domain\n# sockets.\n#\n# By default protected mode is enabled. You should disable it only if\n# you are sure you want clients from other hosts to connect to Redis\n# even if no authentication is configured, nor a specific set of interfaces\n# are explicitly listed using the \"bind\" directive.\nprotected-mode yes\n\n# Accept connections on the specified port, default is 6379 (IANA #815344).\n# If port 0 is specified Redis will not listen on a TCP socket.\nport 6379\n\n# TCP listen() backlog.\n#\n# In high requests-per-second environments you need an high backlog in order\n# to avoid slow clients connections issues. Note that the Linux kernel\n# will silently truncate it to the value of /proc/sys/net/core/somaxconn so\n# make sure to raise both the value of somaxconn and tcp_max_syn_backlog\n# in order to get the desired effect.\ntcp-backlog 511\n\n# Unix socket.\n#\n# Specify the path for the Unix socket that will be used to listen for\n# incoming connections. There is no default, so Redis will not listen\n# on a unix socket when not specified.\n#\n# unixsocket /tmp/redis.sock\n# unixsocketperm 700\n\n# Close the connection after a client is idle for N seconds (0 to disable)\ntimeout 0\n\n# TCP keepalive.\n#\n# If non-zero, use SO_KEEPALIVE to send TCP ACKs to clients in absence\n# of communication. This is useful for two reasons:\n#\n# 1) Detect dead peers.\n# 2) Take the connection alive from the point of view of network\n#    equipment in the middle.\n#\n# On Linux, the specified value (in seconds) is the period used to send ACKs.\n# Note that to close the connection the double of the time is needed.\n# On other kernels the period depends on the kernel configuration.\n#\n# A reasonable value for this option is 300 seconds, which is the new\n# Redis default starting with Redis 3.2.1.\ntcp-keepalive 300\n\n################################# GENERAL #####################################\n\n# By default Redis does not run as a daemon. Use 'yes' if you need it.\n# Note that Redis will write a pid file in /var/run/redis.pid when daemonized.\ndaemonize no\n\n# If you run Redis from upstart or systemd, Redis can interact with your\n# supervision tree. Options:\n#   supervised no      - no supervision interaction\n#   supervised upstart - signal upstart by putting Redis into SIGSTOP mode\n#   supervised systemd - signal systemd by writing READY=1 to $NOTIFY_SOCKET\n#   supervised auto    - detect upstart or systemd method based on\n#                        UPSTART_JOB or NOTIFY_SOCKET environment variables\n# Note: these supervision methods only signal \"process is ready.\"\n#       They do not enable continuous liveness pings back to your supervisor.\nsupervised no\n\n# If a pid file is specified, Redis writes it where specified at startup\n# and removes it at exit.\n#\n# When the server runs non daemonized, no pid file is created if none is\n# specified in the configuration. When the server is daemonized, the pid file\n# is used even if not specified, defaulting to \"/var/run/redis.pid\".\n#\n# Creating a pid file is best effort: if Redis is not able to create it\n# nothing bad happens, the server will start and run normally.\npidfile /var/run/redis_6379.pid\n\n# Specify the server verbosity level.\n# This can be one of:\n# debug (a lot of information, useful for development/testing)\n# verbose (many rarely useful info, but not a mess like the debug level)\n# notice (moderately verbose, what you want in production probably)\n# warning (only very important / critical messages are logged)\nloglevel notice\n\n# Specify the log file name. Also the empty string can be used to force\n# Redis to log on the standard output. Note that if you use standard\n# output for logging but daemonize, logs will be sent to /dev/null\nlogfile \"\"\n\n# To enable logging to the system logger, just set 'syslog-enabled' to yes,\n# and optionally update the other syslog parameters to suit your needs.\n# syslog-enabled no\n\n# Specify the syslog identity.\n# syslog-ident redis\n\n# Specify the syslog facility. Must be USER or between LOCAL0-LOCAL7.\n# syslog-facility local0\n\n# Set the number of databases. The default database is DB 0, you can select\n# a different one on a per-connection basis using SELECT <dbid> where\n# dbid is a number between 0 and 'databases'-1\ndatabases 16\n\n################################ SNAPSHOTTING  ################################\n#\n# Save the DB on disk:\n#\n#   save <seconds> <changes>\n#\n#   Will save the DB if both the given number of seconds and the given\n#   number of write operations against the DB occurred.\n#\n#   In the example below the behaviour will be to save:\n#   after 900 sec (15 min) if at least 1 key changed\n#   after 300 sec (5 min) if at least 10 keys changed\n#   after 60 sec if at least 10000 keys changed\n#\n#   Note: you can disable saving completely by commenting out all \"save\" lines.\n#\n#   It is also possible to remove all the previously configured save\n#   points by adding a save directive with a single empty string argument\n#   like in the following example:\n#\n#   save \"\"\n\nsave 900 1\nsave 300 10\nsave 60 10000\n\n# By default Redis will stop accepting writes if RDB snapshots are enabled\n# (at least one save point) and the latest background save failed.\n# This will make the user aware (in a hard way) that data is not persisting\n# on disk properly, otherwise chances are that no one will notice and some\n# disaster will happen.\n#\n# If the background saving process will start working again Redis will\n# automatically allow writes again.\n#\n# However if you have setup your proper monitoring of the Redis server\n# and persistence, you may want to disable this feature so that Redis will\n# continue to work as usual even if there are problems with disk,\n# permissions, and so forth.\nstop-writes-on-bgsave-error yes\n\n# Compress string objects using LZF when dump .rdb databases?\n# For default that's set to 'yes' as it's almost always a win.\n# If you want to save some CPU in the saving child set it to 'no' but\n# the dataset will likely be bigger if you have compressible values or keys.\nrdbcompression yes\n\n# Since version 5 of RDB a CRC64 checksum is placed at the end of the file.\n# This makes the format more resistant to corruption but there is a performance\n# hit to pay (around 10%) when saving and loading RDB files, so you can disable it\n# for maximum performances.\n#\n# RDB files created with checksum disabled have a checksum of zero that will\n# tell the loading code to skip the check.\nrdbchecksum yes\n\n# The filename where to dump the DB\ndbfilename dump.rdb\n\n# The working directory.\n#\n# The DB will be written inside this directory, with the filename specified\n# above using the 'dbfilename' configuration directive.\n#\n# The Append Only File will also be created inside this directory.\n#\n# Note that you must specify a directory here, not a file name.\ndir ./\n\n################################# REPLICATION #################################\n\n# Master-Slave replication. Use slaveof to make a Redis instance a copy of\n# another Redis server. A few things to understand ASAP about Redis replication.\n#\n# 1) Redis replication is asynchronous, but you can configure a master to\n#    stop accepting writes if it appears to be not connected with at least\n#    a given number of slaves.\n# 2) Redis slaves are able to perform a partial resynchronization with the\n#    master if the replication link is lost for a relatively small amount of\n#    time. You may want to configure the replication backlog size (see the next\n#    sections of this file) with a sensible value depending on your needs.\n# 3) Replication is automatic and does not need user intervention. After a\n#    network partition slaves automatically try to reconnect to masters\n#    and resynchronize with them.\n#\n# slaveof <masterip> <masterport>\n\n# If the master is password protected (using the \"requirepass\" configuration\n# directive below) it is possible to tell the slave to authenticate before\n# starting the replication synchronization process, otherwise the master will\n# refuse the slave request.\n#\n# masterauth <master-password>\n\n# When a slave loses its connection with the master, or when the replication\n# is still in progress, the slave can act in two different ways:\n#\n# 1) if slave-serve-stale-data is set to 'yes' (the default) the slave will\n#    still reply to client requests, possibly with out of date data, or the\n#    data set may just be empty if this is the first synchronization.\n#\n# 2) if slave-serve-stale-data is set to 'no' the slave will reply with\n#    an error \"SYNC with master in progress\" to all the kind of commands\n#    but to INFO and SLAVEOF.\n#\nslave-serve-stale-data yes\n\n# You can configure a slave instance to accept writes or not. Writing against\n# a slave instance may be useful to store some ephemeral data (because data\n# written on a slave will be easily deleted after resync with the master) but\n# may also cause problems if clients are writing to it because of a\n# misconfiguration.\n#\n# Since Redis 2.6 by default slaves are read-only.\n#\n# Note: read only slaves are not designed to be exposed to untrusted clients\n# on the internet. It's just a protection layer against misuse of the instance.\n# Still a read only slave exports by default all the administrative commands\n# such as CONFIG, DEBUG, and so forth. To a limited extent you can improve\n# security of read only slaves using 'rename-command' to shadow all the\n# administrative / dangerous commands.\nslave-read-only yes\n\n# Replication SYNC strategy: disk or socket.\n#\n# -------------------------------------------------------\n# WARNING: DISKLESS REPLICATION IS EXPERIMENTAL CURRENTLY\n# -------------------------------------------------------\n#\n# New slaves and reconnecting slaves that are not able to continue the replication\n# process just receiving differences, need to do what is called a \"full\n# synchronization\". An RDB file is transmitted from the master to the slaves.\n# The transmission can happen in two different ways:\n#\n# 1) Disk-backed: The Redis master creates a new process that writes the RDB\n#                 file on disk. Later the file is transferred by the parent\n#                 process to the slaves incrementally.\n# 2) Diskless: The Redis master creates a new process that directly writes the\n#              RDB file to slave sockets, without touching the disk at all.\n#\n# With disk-backed replication, while the RDB file is generated, more slaves\n# can be queued and served with the RDB file as soon as the current child producing\n# the RDB file finishes its work. With diskless replication instead once\n# the transfer starts, new slaves arriving will be queued and a new transfer\n# will start when the current one terminates.\n#\n# When diskless replication is used, the master waits a configurable amount of\n# time (in seconds) before starting the transfer in the hope that multiple slaves\n# will arrive and the transfer can be parallelized.\n#\n# With slow disks and fast (large bandwidth) networks, diskless replication\n# works better.\nrepl-diskless-sync no\n\n# When diskless replication is enabled, it is possible to configure the delay\n# the server waits in order to spawn the child that transfers the RDB via socket\n# to the slaves.\n#\n# This is important since once the transfer starts, it is not possible to serve\n# new slaves arriving, that will be queued for the next RDB transfer, so the server\n# waits a delay in order to let more slaves arrive.\n#\n# The delay is specified in seconds, and by default is 5 seconds. To disable\n# it entirely just set it to 0 seconds and the transfer will start ASAP.\nrepl-diskless-sync-delay 5\n\n# Slaves send PINGs to server in a predefined interval. It's possible to change\n# this interval with the repl_ping_slave_period option. The default value is 10\n# seconds.\n#\n# repl-ping-slave-period 10\n\n# The following option sets the replication timeout for:\n#\n# 1) Bulk transfer I/O during SYNC, from the point of view of slave.\n# 2) Master timeout from the point of view of slaves (data, pings).\n# 3) Slave timeout from the point of view of masters (REPLCONF ACK pings).\n#\n# It is important to make sure that this value is greater than the value\n# specified for repl-ping-slave-period otherwise a timeout will be detected\n# every time there is low traffic between the master and the slave.\n#\n# repl-timeout 60\n\n# Disable TCP_NODELAY on the slave socket after SYNC?\n#\n# If you select \"yes\" Redis will use a smaller number of TCP packets and\n# less bandwidth to send data to slaves. But this can add a delay for\n# the data to appear on the slave side, up to 40 milliseconds with\n# Linux kernels using a default configuration.\n#\n# If you select \"no\" the delay for data to appear on the slave side will\n# be reduced but more bandwidth will be used for replication.\n#\n# By default we optimize for low latency, but in very high traffic conditions\n# or when the master and slaves are many hops away, turning this to \"yes\" may\n# be a good idea.\nrepl-disable-tcp-nodelay no\n\n# Set the replication backlog size. The backlog is a buffer that accumulates\n# slave data when slaves are disconnected for some time, so that when a slave\n# wants to reconnect again, often a full resync is not needed, but a partial\n# resync is enough, just passing the portion of data the slave missed while\n# disconnected.\n#\n# The bigger the replication backlog, the longer the time the slave can be\n# disconnected and later be able to perform a partial resynchronization.\n#\n# The backlog is only allocated once there is at least a slave connected.\n#\n# repl-backlog-size 1mb\n\n# After a master has no longer connected slaves for some time, the backlog\n# will be freed. The following option configures the amount of seconds that\n# need to elapse, starting from the time the last slave disconnected, for\n# the backlog buffer to be freed.\n#\n# A value of 0 means to never release the backlog.\n#\n# repl-backlog-ttl 3600\n\n# The slave priority is an integer number published by Redis in the INFO output.\n# It is used by Redis Sentinel in order to select a slave to promote into a\n# master if the master is no longer working correctly.\n#\n# A slave with a low priority number is considered better for promotion, so\n# for instance if there are three slaves with priority 10, 100, 25 Sentinel will\n# pick the one with priority 10, that is the lowest.\n#\n# However a special priority of 0 marks the slave as not able to perform the\n# role of master, so a slave with priority of 0 will never be selected by\n# Redis Sentinel for promotion.\n#\n# By default the priority is 100.\nslave-priority 100\n\n# It is possible for a master to stop accepting writes if there are less than\n# N slaves connected, having a lag less or equal than M seconds.\n#\n# The N slaves need to be in \"online\" state.\n#\n# The lag in seconds, that must be <= the specified value, is calculated from\n# the last ping received from the slave, that is usually sent every second.\n#\n# This option does not GUARANTEE that N replicas will accept the write, but\n# will limit the window of exposure for lost writes in case not enough slaves\n# are available, to the specified number of seconds.\n#\n# For example to require at least 3 slaves with a lag <= 10 seconds use:\n#\n# min-slaves-to-write 3\n# min-slaves-max-lag 10\n#\n# Setting one or the other to 0 disables the feature.\n#\n# By default min-slaves-to-write is set to 0 (feature disabled) and\n# min-slaves-max-lag is set to 10.\n\n# A Redis master is able to list the address and port of the attached\n# slaves in different ways. For example the \"INFO replication\" section\n# offers this information, which is used, among other tools, by\n# Redis Sentinel in order to discover slave instances.\n# Another place where this info is available is in the output of the\n# \"ROLE\" command of a masteer.\n#\n# The listed IP and address normally reported by a slave is obtained\n# in the following way:\n#\n#   IP: The address is auto detected by checking the peer address\n#   of the socket used by the slave to connect with the master.\n#\n#   Port: The port is communicated by the slave during the replication\n#   handshake, and is normally the port that the slave is using to\n#   list for connections.\n#\n# However when port forwarding or Network Address Translation (NAT) is\n# used, the slave may be actually reachable via different IP and port\n# pairs. The following two options can be used by a slave in order to\n# report to its master a specific set of IP and port, so that both INFO\n# and ROLE will report those values.\n#\n# There is no need to use both the options if you need to override just\n# the port or the IP address.\n#\n# slave-announce-ip 5.5.5.5\n# slave-announce-port 1234\n\n################################## SECURITY ###################################\n\n# Require clients to issue AUTH <PASSWORD> before processing any other\n# commands.  This might be useful in environments in which you do not trust\n# others with access to the host running redis-server.\n#\n# This should stay commented out for backward compatibility and because most\n# people do not need auth (e.g. they run their own servers).\n#\n# Warning: since Redis is pretty fast an outside user can try up to\n# 150k passwords per second against a good box. This means that you should\n# use a very strong password otherwise it will be very easy to break.\n#\n# requirepass foobared\n\n# Command renaming.\n#\n# It is possible to change the name of dangerous commands in a shared\n# environment. For instance the CONFIG command may be renamed into something\n# hard to guess so that it will still be available for internal-use tools\n# but not available for general clients.\n#\n# Example:\n#\n# rename-command CONFIG b840fc02d524045429941cc15f59e41cb7be6c52\n#\n# It is also possible to completely kill a command by renaming it into\n# an empty string:\n#\n# rename-command CONFIG \"\"\n#\n# Please note that changing the name of commands that are logged into the\n# AOF file or transmitted to slaves may cause problems.\n\n################################### LIMITS ####################################\n\n# Set the max number of connected clients at the same time. By default\n# this limit is set to 10000 clients, however if the Redis server is not\n# able to configure the process file limit to allow for the specified limit\n# the max number of allowed clients is set to the current file limit\n# minus 32 (as Redis reserves a few file descriptors for internal uses).\n#\n# Once the limit is reached Redis will close all the new connections sending\n# an error 'max number of clients reached'.\n#\n# maxclients 10000\n\n# Don't use more memory than the specified amount of bytes.\n# When the memory limit is reached Redis will try to remove keys\n# according to the eviction policy selected (see maxmemory-policy).\n#\n# If Redis can't remove keys according to the policy, or if the policy is\n# set to 'noeviction', Redis will start to reply with errors to commands\n# that would use more memory, like SET, LPUSH, and so on, and will continue\n# to reply to read-only commands like GET.\n#\n# This option is usually useful when using Redis as an LRU cache, or to set\n# a hard memory limit for an instance (using the 'noeviction' policy).\n#\n# WARNING: If you have slaves attached to an instance with maxmemory on,\n# the size of the output buffers needed to feed the slaves are subtracted\n# from the used memory count, so that network problems / resyncs will\n# not trigger a loop where keys are evicted, and in turn the output\n# buffer of slaves is full with DELs of keys evicted triggering the deletion\n# of more keys, and so forth until the database is completely emptied.\n#\n# In short... if you have slaves attached it is suggested that you set a lower\n# limit for maxmemory so that there is some free RAM on the system for slave\n# output buffers (but this is not needed if the policy is 'noeviction').\n#\n# maxmemory <bytes>\n\n# MAXMEMORY POLICY: how Redis will select what to remove when maxmemory\n# is reached. You can select among five behaviors:\n#\n# volatile-lru -> remove the key with an expire set using an LRU algorithm\n# allkeys-lru -> remove any key according to the LRU algorithm\n# volatile-random -> remove a random key with an expire set\n# allkeys-random -> remove a random key, any key\n# volatile-ttl -> remove the key with the nearest expire time (minor TTL)\n# noeviction -> don't expire at all, just return an error on write operations\n#\n# Note: with any of the above policies, Redis will return an error on write\n#       operations, when there are no suitable keys for eviction.\n#\n#       At the date of writing these commands are: set setnx setex append\n#       incr decr rpush lpush rpushx lpushx linsert lset rpoplpush sadd\n#       sinter sinterstore sunion sunionstore sdiff sdiffstore zadd zincrby\n#       zunionstore zinterstore hset hsetnx hmset hincrby incrby decrby\n#       getset mset msetnx exec sort\n#\n# The default is:\n#\n# maxmemory-policy noeviction\n\n# LRU and minimal TTL algorithms are not precise algorithms but approximated\n# algorithms (in order to save memory), so you can tune it for speed or\n# accuracy. For default Redis will check five keys and pick the one that was\n# used less recently, you can change the sample size using the following\n# configuration directive.\n#\n# The default of 5 produces good enough results. 10 Approximates very closely\n# true LRU but costs a bit more CPU. 3 is very fast but not very accurate.\n#\n# maxmemory-samples 5\n\n############################## APPEND ONLY MODE ###############################\n\n# By default Redis asynchronously dumps the dataset on disk. This mode is\n# good enough in many applications, but an issue with the Redis process or\n# a power outage may result into a few minutes of writes lost (depending on\n# the configured save points).\n#\n# The Append Only File is an alternative persistence mode that provides\n# much better durability. For instance using the default data fsync policy\n# (see later in the config file) Redis can lose just one second of writes in a\n# dramatic event like a server power outage, or a single write if something\n# wrong with the Redis process itself happens, but the operating system is\n# still running correctly.\n#\n# AOF and RDB persistence can be enabled at the same time without problems.\n# If the AOF is enabled on startup Redis will load the AOF, that is the file\n# with the better durability guarantees.\n#\n# Please check http://redis.io/topics/persistence for more information.\n\nappendonly no\n\n# The name of the append only file (default: \"appendonly.aof\")\n\nappendfilename \"appendonly.aof\"\n\n# The fsync() call tells the Operating System to actually write data on disk\n# instead of waiting for more data in the output buffer. Some OS will really flush\n# data on disk, some other OS will just try to do it ASAP.\n#\n# Redis supports three different modes:\n#\n# no: don't fsync, just let the OS flush the data when it wants. Faster.\n# always: fsync after every write to the append only log. Slow, Safest.\n# everysec: fsync only one time every second. Compromise.\n#\n# The default is \"everysec\", as that's usually the right compromise between\n# speed and data safety. It's up to you to understand if you can relax this to\n# \"no\" that will let the operating system flush the output buffer when\n# it wants, for better performances (but if you can live with the idea of\n# some data loss consider the default persistence mode that's snapshotting),\n# or on the contrary, use \"always\" that's very slow but a bit safer than\n# everysec.\n#\n# More details please check the following article:\n# http://antirez.com/post/redis-persistence-demystified.html\n#\n# If unsure, use \"everysec\".\n\n# appendfsync always\nappendfsync everysec\n# appendfsync no\n\n# When the AOF fsync policy is set to always or everysec, and a background\n# saving process (a background save or AOF log background rewriting) is\n# performing a lot of I/O against the disk, in some Linux configurations\n# Redis may block too long on the fsync() call. Note that there is no fix for\n# this currently, as even performing fsync in a different thread will block\n# our synchronous write(2) call.\n#\n# In order to mitigate this problem it's possible to use the following option\n# that will prevent fsync() from being called in the main process while a\n# BGSAVE or BGREWRITEAOF is in progress.\n#\n# This means that while another child is saving, the durability of Redis is\n# the same as \"appendfsync none\". In practical terms, this means that it is\n# possible to lose up to 30 seconds of log in the worst scenario (with the\n# default Linux settings).\n#\n# If you have latency problems turn this to \"yes\". Otherwise leave it as\n# \"no\" that is the safest pick from the point of view of durability.\n\nno-appendfsync-on-rewrite no\n\n# Automatic rewrite of the append only file.\n# Redis is able to automatically rewrite the log file implicitly calling\n# BGREWRITEAOF when the AOF log size grows by the specified percentage.\n#\n# This is how it works: Redis remembers the size of the AOF file after the\n# latest rewrite (if no rewrite has happened since the restart, the size of\n# the AOF at startup is used).\n#\n# This base size is compared to the current size. If the current size is\n# bigger than the specified percentage, the rewrite is triggered. Also\n# you need to specify a minimal size for the AOF file to be rewritten, this\n# is useful to avoid rewriting the AOF file even if the percentage increase\n# is reached but it is still pretty small.\n#\n# Specify a percentage of zero in order to disable the automatic AOF\n# rewrite feature.\n\nauto-aof-rewrite-percentage 100\nauto-aof-rewrite-min-size 64mb\n\n# An AOF file may be found to be truncated at the end during the Redis\n# startup process, when the AOF data gets loaded back into memory.\n# This may happen when the system where Redis is running\n# crashes, especially when an ext4 filesystem is mounted without the\n# data=ordered option (however this can't happen when Redis itself\n# crashes or aborts but the operating system still works correctly).\n#\n# Redis can either exit with an error when this happens, or load as much\n# data as possible (the default now) and start if the AOF file is found\n# to be truncated at the end. The following option controls this behavior.\n#\n# If aof-load-truncated is set to yes, a truncated AOF file is loaded and\n# the Redis server starts emitting a log to inform the user of the event.\n# Otherwise if the option is set to no, the server aborts with an error\n# and refuses to start. When the option is set to no, the user requires\n# to fix the AOF file using the \"redis-check-aof\" utility before to restart\n# the server.\n#\n# Note that if the AOF file will be found to be corrupted in the middle\n# the server will still exit with an error. This option only applies when\n# Redis will try to read more data from the AOF file but not enough bytes\n# will be found.\naof-load-truncated yes\n\n################################ LUA SCRIPTING  ###############################\n\n# Max execution time of a Lua script in milliseconds.\n#\n# If the maximum execution time is reached Redis will log that a script is\n# still in execution after the maximum allowed time and will start to\n# reply to queries with an error.\n#\n# When a long running script exceeds the maximum execution time only the\n# SCRIPT KILL and SHUTDOWN NOSAVE commands are available. The first can be\n# used to stop a script that did not yet called write commands. The second\n# is the only way to shut down the server in the case a write command was\n# already issued by the script but the user doesn't want to wait for the natural\n# termination of the script.\n#\n# Set it to 0 or a negative value for unlimited execution without warnings.\nlua-time-limit 5000\n\n################################ REDIS CLUSTER  ###############################\n#\n# ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++\n# WARNING EXPERIMENTAL: Redis Cluster is considered to be stable code, however\n# in order to mark it as \"mature\" we need to wait for a non trivial percentage\n# of users to deploy it in production.\n# ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++\n#\n# Normal Redis instances can't be part of a Redis Cluster; only nodes that are\n# started as cluster nodes can. In order to start a Redis instance as a\n# cluster node enable the cluster support uncommenting the following:\n#\n# cluster-enabled yes\n\n# Every cluster node has a cluster configuration file. This file is not\n# intended to be edited by hand. It is created and updated by Redis nodes.\n# Every Redis Cluster node requires a different cluster configuration file.\n# Make sure that instances running in the same system do not have\n# overlapping cluster configuration file names.\n#\n# cluster-config-file nodes-6379.conf\n\n# Cluster node timeout is the amount of milliseconds a node must be unreachable\n# for it to be considered in failure state.\n# Most other internal time limits are multiple of the node timeout.\n#\n# cluster-node-timeout 15000\n\n# A slave of a failing master will avoid to start a failover if its data\n# looks too old.\n#\n# There is no simple way for a slave to actually have a exact measure of\n# its \"data age\", so the following two checks are performed:\n#\n# 1) If there are multiple slaves able to failover, they exchange messages\n#    in order to try to give an advantage to the slave with the best\n#    replication offset (more data from the master processed).\n#    Slaves will try to get their rank by offset, and apply to the start\n#    of the failover a delay proportional to their rank.\n#\n# 2) Every single slave computes the time of the last interaction with\n#    its master. This can be the last ping or command received (if the master\n#    is still in the \"connected\" state), or the time that elapsed since the\n#    disconnection with the master (if the replication link is currently down).\n#    If the last interaction is too old, the slave will not try to failover\n#    at all.\n#\n# The point \"2\" can be tuned by user. Specifically a slave will not perform\n# the failover if, since the last interaction with the master, the time\n# elapsed is greater than:\n#\n#   (node-timeout * slave-validity-factor) + repl-ping-slave-period\n#\n# So for example if node-timeout is 30 seconds, and the slave-validity-factor\n# is 10, and assuming a default repl-ping-slave-period of 10 seconds, the\n# slave will not try to failover if it was not able to talk with the master\n# for longer than 310 seconds.\n#\n# A large slave-validity-factor may allow slaves with too old data to failover\n# a master, while a too small value may prevent the cluster from being able to\n# elect a slave at all.\n#\n# For maximum availability, it is possible to set the slave-validity-factor\n# to a value of 0, which means, that slaves will always try to failover the\n# master regardless of the last time they interacted with the master.\n# (However they'll always try to apply a delay proportional to their\n# offset rank).\n#\n# Zero is the only value able to guarantee that when all the partitions heal\n# the cluster will always be able to continue.\n#\n# cluster-slave-validity-factor 10\n\n# Cluster slaves are able to migrate to orphaned masters, that are masters\n# that are left without working slaves. This improves the cluster ability\n# to resist to failures as otherwise an orphaned master can't be failed over\n# in case of failure if it has no working slaves.\n#\n# Slaves migrate to orphaned masters only if there are still at least a\n# given number of other working slaves for their old master. This number\n# is the \"migration barrier\". A migration barrier of 1 means that a slave\n# will migrate only if there is at least 1 other working slave for its master\n# and so forth. It usually reflects the number of slaves you want for every\n# master in your cluster.\n#\n# Default is 1 (slaves migrate only if their masters remain with at least\n# one slave). To disable migration just set it to a very large value.\n# A value of 0 can be set but is useful only for debugging and dangerous\n# in production.\n#\n# cluster-migration-barrier 1\n\n# By default Redis Cluster nodes stop accepting queries if they detect there\n# is at least an hash slot uncovered (no available node is serving it).\n# This way if the cluster is partially down (for example a range of hash slots\n# are no longer covered) all the cluster becomes, eventually, unavailable.\n# It automatically returns available as soon as all the slots are covered again.\n#\n# However sometimes you want the subset of the cluster which is working,\n# to continue to accept queries for the part of the key space that is still\n# covered. In order to do so, just set the cluster-require-full-coverage\n# option to no.\n#\n# cluster-require-full-coverage yes\n\n# In order to setup your cluster make sure to read the documentation\n# available at http://redis.io web site.\n\n################################## SLOW LOG ###################################\n\n# The Redis Slow Log is a system to log queries that exceeded a specified\n# execution time. The execution time does not include the I/O operations\n# like talking with the client, sending the reply and so forth,\n# but just the time needed to actually execute the command (this is the only\n# stage of command execution where the thread is blocked and can not serve\n# other requests in the meantime).\n#\n# You can configure the slow log with two parameters: one tells Redis\n# what is the execution time, in microseconds, to exceed in order for the\n# command to get logged, and the other parameter is the length of the\n# slow log. When a new command is logged the oldest one is removed from the\n# queue of logged commands.\n\n# The following time is expressed in microseconds, so 1000000 is equivalent\n# to one second. Note that a negative number disables the slow log, while\n# a value of zero forces the logging of every command.\nslowlog-log-slower-than 10000\n\n# There is no limit to this length. Just be aware that it will consume memory.\n# You can reclaim memory used by the slow log with SLOWLOG RESET.\nslowlog-max-len 128\n\n################################ LATENCY MONITOR ##############################\n\n# The Redis latency monitoring subsystem samples different operations\n# at runtime in order to collect data related to possible sources of\n# latency of a Redis instance.\n#\n# Via the LATENCY command this information is available to the user that can\n# print graphs and obtain reports.\n#\n# The system only logs operations that were performed in a time equal or\n# greater than the amount of milliseconds specified via the\n# latency-monitor-threshold configuration directive. When its value is set\n# to zero, the latency monitor is turned off.\n#\n# By default latency monitoring is disabled since it is mostly not needed\n# if you don't have latency issues, and collecting data has a performance\n# impact, that while very small, can be measured under big load. Latency\n# monitoring can easily be enabled at runtime using the command\n# \"CONFIG SET latency-monitor-threshold <milliseconds>\" if needed.\nlatency-monitor-threshold 0\n\n############################# EVENT NOTIFICATION ##############################\n\n# Redis can notify Pub/Sub clients about events happening in the key space.\n# This feature is documented at http://redis.io/topics/notifications\n#\n# For instance if keyspace events notification is enabled, and a client\n# performs a DEL operation on key \"foo\" stored in the Database 0, two\n# messages will be published via Pub/Sub:\n#\n# PUBLISH __keyspace@0__:foo del\n# PUBLISH __keyevent@0__:del foo\n#\n# It is possible to select the events that Redis will notify among a set\n# of classes. Every class is identified by a single character:\n#\n#  K     Keyspace events, published with __keyspace@<db>__ prefix.\n#  E     Keyevent events, published with __keyevent@<db>__ prefix.\n#  g     Generic commands (non-type specific) like DEL, EXPIRE, RENAME, ...\n#  $     String commands\n#  l     List commands\n#  s     Set commands\n#  h     Hash commands\n#  z     Sorted set commands\n#  x     Expired events (events generated every time a key expires)\n#  e     Evicted events (events generated when a key is evicted for maxmemory)\n#  A     Alias for g$lshzxe, so that the \"AKE\" string means all the events.\n#\n#  The \"notify-keyspace-events\" takes as argument a string that is composed\n#  of zero or multiple characters. The empty string means that notifications\n#  are disabled.\n#\n#  Example: to enable list and generic events, from the point of view of the\n#           event name, use:\n#\n#  notify-keyspace-events Elg\n#\n#  Example 2: to get the stream of the expired keys subscribing to channel\n#             name __keyevent@0__:expired use:\n#\n#  notify-keyspace-events Ex\n#\n#  By default all notifications are disabled because most users don't need\n#  this feature and the feature has some overhead. Note that if you don't\n#  specify at least one of K or E, no events will be delivered.\nnotify-keyspace-events \"\"\n\n############################### ADVANCED CONFIG ###############################\n\n# Hashes are encoded using a memory efficient data structure when they have a\n# small number of entries, and the biggest entry does not exceed a given\n# threshold. These thresholds can be configured using the following directives.\nhash-max-ziplist-entries 512\nhash-max-ziplist-value 64\n\n# Lists are also encoded in a special way to save a lot of space.\n# The number of entries allowed per internal list node can be specified\n# as a fixed maximum size or a maximum number of elements.\n# For a fixed maximum size, use -5 through -1, meaning:\n# -5: max size: 64 Kb  <-- not recommended for normal workloads\n# -4: max size: 32 Kb  <-- not recommended\n# -3: max size: 16 Kb  <-- probably not recommended\n# -2: max size: 8 Kb   <-- good\n# -1: max size: 4 Kb   <-- good\n# Positive numbers mean store up to _exactly_ that number of elements\n# per list node.\n# The highest performing option is usually -2 (8 Kb size) or -1 (4 Kb size),\n# but if your use case is unique, adjust the settings as necessary.\nlist-max-ziplist-size -2\n\n# Lists may also be compressed.\n# Compress depth is the number of quicklist ziplist nodes from *each* side of\n# the list to *exclude* from compression.  The head and tail of the list\n# are always uncompressed for fast push/pop operations.  Settings are:\n# 0: disable all list compression\n# 1: depth 1 means \"don't start compressing until after 1 node into the list,\n#    going from either the head or tail\"\n#    So: [head]->node->node->...->node->[tail]\n#    [head], [tail] will always be uncompressed; inner nodes will compress.\n# 2: [head]->[next]->node->node->...->node->[prev]->[tail]\n#    2 here means: don't compress head or head->next or tail->prev or tail,\n#    but compress all nodes between them.\n# 3: [head]->[next]->[next]->node->node->...->node->[prev]->[prev]->[tail]\n# etc.\nlist-compress-depth 0\n\n# Sets have a special encoding in just one case: when a set is composed\n# of just strings that happen to be integers in radix 10 in the range\n# of 64 bit signed integers.\n# The following configuration setting sets the limit in the size of the\n# set in order to use this special memory saving encoding.\nset-max-intset-entries 512\n\n# Similarly to hashes and lists, sorted sets are also specially encoded in\n# order to save a lot of space. This encoding is only used when the length and\n# elements of a sorted set are below the following limits:\nzset-max-ziplist-entries 128\nzset-max-ziplist-value 64\n\n# HyperLogLog sparse representation bytes limit. The limit includes the\n# 16 bytes header. When an HyperLogLog using the sparse representation crosses\n# this limit, it is converted into the dense representation.\n#\n# A value greater than 16000 is totally useless, since at that point the\n# dense representation is more memory efficient.\n#\n# The suggested value is ~ 3000 in order to have the benefits of\n# the space efficient encoding without slowing down too much PFADD,\n# which is O(N) with the sparse encoding. The value can be raised to\n# ~ 10000 when CPU is not a concern, but space is, and the data set is\n# composed of many HyperLogLogs with cardinality in the 0 - 15000 range.\nhll-sparse-max-bytes 3000\n\n# Active rehashing uses 1 millisecond every 100 milliseconds of CPU time in\n# order to help rehashing the main Redis hash table (the one mapping top-level\n# keys to values). The hash table implementation Redis uses (see dict.c)\n# performs a lazy rehashing: the more operation you run into a hash table\n# that is rehashing, the more rehashing \"steps\" are performed, so if the\n# server is idle the rehashing is never complete and some more memory is used\n# by the hash table.\n#\n# The default is to use this millisecond 10 times every second in order to\n# actively rehash the main dictionaries, freeing memory when possible.\n#\n# If unsure:\n# use \"activerehashing no\" if you have hard latency requirements and it is\n# not a good thing in your environment that Redis can reply from time to time\n# to queries with 2 milliseconds delay.\n#\n# use \"activerehashing yes\" if you don't have such hard requirements but\n# want to free memory asap when possible.\nactiverehashing yes\n\n# The client output buffer limits can be used to force disconnection of clients\n# that are not reading data from the server fast enough for some reason (a\n# common reason is that a Pub/Sub client can't consume messages as fast as the\n# publisher can produce them).\n#\n# The limit can be set differently for the three different classes of clients:\n#\n# normal -> normal clients including MONITOR clients\n# slave  -> slave clients\n# pubsub -> clients subscribed to at least one pubsub channel or pattern\n#\n# The syntax of every client-output-buffer-limit directive is the following:\n#\n# client-output-buffer-limit <class> <hard limit> <soft limit> <soft seconds>\n#\n# A client is immediately disconnected once the hard limit is reached, or if\n# the soft limit is reached and remains reached for the specified number of\n# seconds (continuously).\n# So for instance if the hard limit is 32 megabytes and the soft limit is\n# 16 megabytes / 10 seconds, the client will get disconnected immediately\n# if the size of the output buffers reach 32 megabytes, but will also get\n# disconnected if the client reaches 16 megabytes and continuously overcomes\n# the limit for 10 seconds.\n#\n# By default normal clients are not limited because they don't receive data\n# without asking (in a push way), but just after a request, so only\n# asynchronous clients may create a scenario where data is requested faster\n# than it can read.\n#\n# Instead there is a default limit for pubsub and slave clients, since\n# subscribers and slaves receive data in a push fashion.\n#\n# Both the hard or the soft limit can be disabled by setting them to zero.\nclient-output-buffer-limit normal 0 0 0\nclient-output-buffer-limit slave 256mb 64mb 60\nclient-output-buffer-limit pubsub 32mb 8mb 60\n\n# Redis calls an internal function to perform many background tasks, like\n# closing connections of clients in timeout, purging expired keys that are\n# never requested, and so forth.\n#\n# Not all tasks are performed with the same frequency, but Redis checks for\n# tasks to perform according to the specified \"hz\" value.\n#\n# By default \"hz\" is set to 10. Raising the value will use more CPU when\n# Redis is idle, but at the same time will make Redis more responsive when\n# there are many keys expiring at the same time, and timeouts may be\n# handled with more precision.\n#\n# The range is between 1 and 500, however a value over 100 is usually not\n# a good idea. Most users should use the default of 10 and raise this up to\n# 100 only in environments where very low latency is required.\nhz 10\n\n# When a child rewrites the AOF file, if the following option is enabled\n# the file will be fsync-ed every 32 MB of data generated. This is useful\n# in order to commit the file to the disk more incrementally and avoid\n# big latency spikes.\naof-rewrite-incremental-fsync yes\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/runtest",
    "content": "#!/bin/sh\nTCL_VERSIONS=\"8.5 8.6\"\nTCLSH=\"\"\n\nfor VERSION in $TCL_VERSIONS; do\n\tTCL=`which tclsh$VERSION 2>/dev/null` && TCLSH=$TCL\ndone\n\nif [ -z $TCLSH ]\nthen\n    echo \"You need tcl 8.5 or newer in order to run the Redis test\"\n    exit 1\nfi\n$TCLSH tests/test_helper.tcl $*\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/runtest-cluster",
    "content": "#!/bin/sh\nTCL_VERSIONS=\"8.5 8.6\"\nTCLSH=\"\"\n\nfor VERSION in $TCL_VERSIONS; do\n\tTCL=`which tclsh$VERSION 2>/dev/null` && TCLSH=$TCL\ndone\n\nif [ -z $TCLSH ]\nthen\n    echo \"You need tcl 8.5 or newer in order to run the Redis Sentinel test\"\n    exit 1\nfi\n$TCLSH tests/cluster/run.tcl $*\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/runtest-sentinel",
    "content": "#!/bin/sh\nTCL_VERSIONS=\"8.5 8.6\"\nTCLSH=\"\"\n\nfor VERSION in $TCL_VERSIONS; do\n\tTCL=`which tclsh$VERSION 2>/dev/null` && TCLSH=$TCL\ndone\n\nif [ -z $TCLSH ]\nthen\n    echo \"You need tcl 8.5 or newer in order to run the Redis Sentinel test\"\n    exit 1\nfi\n$TCLSH tests/sentinel/run.tcl $*\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/sentinel.conf",
    "content": "# Example sentinel.conf\n\n# *** IMPORTANT ***\n#\n# By default Sentinel will not be reachable from interfaces different than\n# localhost, either use the 'bind' directive to bind to a list of network\n# interfaces, or disable protected mode with \"protected-mode no\" by\n# adding it to this configuration file.\n#\n# Before doing that MAKE SURE the instance is protected from the outside\n# world via firewalling or other means.\n#\n# For example you may use one of the following:\n#\n# bind 127.0.0.1 192.168.1.1\n#\n# protected-mode no\n\n# port <sentinel-port>\n# The port that this sentinel instance will run on\nport 26379\n\n# sentinel announce-ip <ip>\n# sentinel announce-port <port>\n#\n# The above two configuration directives are useful in environments where,\n# because of NAT, Sentinel is reachable from outside via a non-local address.\n#\n# When announce-ip is provided, the Sentinel will claim the specified IP address\n# in HELLO messages used to gossip its presence, instead of auto-detecting the\n# local address as it usually does.\n#\n# Similarly when announce-port is provided and is valid and non-zero, Sentinel\n# will announce the specified TCP port.\n#\n# The two options don't need to be used together, if only announce-ip is\n# provided, the Sentinel will announce the specified IP and the server port\n# as specified by the \"port\" option. If only announce-port is provided, the\n# Sentinel will announce the auto-detected local IP and the specified port.\n#\n# Example:\n#\n# sentinel announce-ip 1.2.3.4\n\n# dir <working-directory>\n# Every long running process should have a well-defined working directory.\n# For Redis Sentinel to chdir to /tmp at startup is the simplest thing\n# for the process to don't interfere with administrative tasks such as\n# unmounting filesystems.\ndir /tmp\n\n# sentinel monitor <master-name> <ip> <redis-port> <quorum>\n#\n# Tells Sentinel to monitor this master, and to consider it in O_DOWN\n# (Objectively Down) state only if at least <quorum> sentinels agree.\n#\n# Note that whatever is the ODOWN quorum, a Sentinel will require to\n# be elected by the majority of the known Sentinels in order to\n# start a failover, so no failover can be performed in minority.\n#\n# Slaves are auto-discovered, so you don't need to specify slaves in\n# any way. Sentinel itself will rewrite this configuration file adding\n# the slaves using additional configuration options.\n# Also note that the configuration file is rewritten when a\n# slave is promoted to master.\n#\n# Note: master name should not include special characters or spaces.\n# The valid charset is A-z 0-9 and the three characters \".-_\".\nsentinel monitor mymaster 127.0.0.1 6379 2\n\n# sentinel auth-pass <master-name> <password>\n#\n# Set the password to use to authenticate with the master and slaves.\n# Useful if there is a password set in the Redis instances to monitor.\n#\n# Note that the master password is also used for slaves, so it is not\n# possible to set a different password in masters and slaves instances\n# if you want to be able to monitor these instances with Sentinel.\n#\n# However you can have Redis instances without the authentication enabled\n# mixed with Redis instances requiring the authentication (as long as the\n# password set is the same for all the instances requiring the password) as\n# the AUTH command will have no effect in Redis instances with authentication\n# switched off.\n#\n# Example:\n#\n# sentinel auth-pass mymaster MySUPER--secret-0123passw0rd\n\n# sentinel down-after-milliseconds <master-name> <milliseconds>\n#\n# Number of milliseconds the master (or any attached slave or sentinel) should\n# be unreachable (as in, not acceptable reply to PING, continuously, for the\n# specified period) in order to consider it in S_DOWN state (Subjectively\n# Down).\n#\n# Default is 30 seconds.\nsentinel down-after-milliseconds mymaster 30000\n\n# sentinel parallel-syncs <master-name> <numslaves>\n#\n# How many slaves we can reconfigure to point to the new slave simultaneously\n# during the failover. Use a low number if you use the slaves to serve query\n# to avoid that all the slaves will be unreachable at about the same\n# time while performing the synchronization with the master.\nsentinel parallel-syncs mymaster 1\n\n# sentinel failover-timeout <master-name> <milliseconds>\n#\n# Specifies the failover timeout in milliseconds. It is used in many ways:\n#\n# - The time needed to re-start a failover after a previous failover was\n#   already tried against the same master by a given Sentinel, is two\n#   times the failover timeout.\n#\n# - The time needed for a slave replicating to a wrong master according\n#   to a Sentinel current configuration, to be forced to replicate\n#   with the right master, is exactly the failover timeout (counting since\n#   the moment a Sentinel detected the misconfiguration).\n#\n# - The time needed to cancel a failover that is already in progress but\n#   did not produced any configuration change (SLAVEOF NO ONE yet not\n#   acknowledged by the promoted slave).\n#\n# - The maximum time a failover in progress waits for all the slaves to be\n#   reconfigured as slaves of the new master. However even after this time\n#   the slaves will be reconfigured by the Sentinels anyway, but not with\n#   the exact parallel-syncs progression as specified.\n#\n# Default is 3 minutes.\nsentinel failover-timeout mymaster 180000\n\n# SCRIPTS EXECUTION\n#\n# sentinel notification-script and sentinel reconfig-script are used in order\n# to configure scripts that are called to notify the system administrator\n# or to reconfigure clients after a failover. The scripts are executed\n# with the following rules for error handling:\n#\n# If script exits with \"1\" the execution is retried later (up to a maximum\n# number of times currently set to 10).\n#\n# If script exits with \"2\" (or an higher value) the script execution is\n# not retried.\n#\n# If script terminates because it receives a signal the behavior is the same\n# as exit code 1.\n#\n# A script has a maximum running time of 60 seconds. After this limit is\n# reached the script is terminated with a SIGKILL and the execution retried.\n\n# NOTIFICATION SCRIPT\n#\n# sentinel notification-script <master-name> <script-path>\n# \n# Call the specified notification script for any sentinel event that is\n# generated in the WARNING level (for instance -sdown, -odown, and so forth).\n# This script should notify the system administrator via email, SMS, or any\n# other messaging system, that there is something wrong with the monitored\n# Redis systems.\n#\n# The script is called with just two arguments: the first is the event type\n# and the second the event description.\n#\n# The script must exist and be executable in order for sentinel to start if\n# this option is provided.\n#\n# Example:\n#\n# sentinel notification-script mymaster /var/redis/notify.sh\n\n# CLIENTS RECONFIGURATION SCRIPT\n#\n# sentinel client-reconfig-script <master-name> <script-path>\n#\n# When the master changed because of a failover a script can be called in\n# order to perform application-specific tasks to notify the clients that the\n# configuration has changed and the master is at a different address.\n# \n# The following arguments are passed to the script:\n#\n# <master-name> <role> <state> <from-ip> <from-port> <to-ip> <to-port>\n#\n# <state> is currently always \"failover\"\n# <role> is either \"leader\" or \"observer\"\n# \n# The arguments from-ip, from-port, to-ip, to-port are used to communicate\n# the old address of the master and the new address of the elected slave\n# (now a master).\n#\n# This script should be resistant to multiple invocations.\n#\n# Example:\n#\n# sentinel client-reconfig-script mymaster /var/redis/reconfig.sh\n\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/src/.gitignore",
    "content": "*.gcda\n*.gcno\n*.gcov\nredis.info\nlcov-html\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/src/Makefile",
    "content": "# Redis Makefile\n# Copyright (C) 2009 Salvatore Sanfilippo <antirez at gmail dot com>\n# This file is released under the BSD license, see the COPYING file\n#\n# The Makefile composes the final FINAL_CFLAGS and FINAL_LDFLAGS using\n# what is needed for Redis plus the standard CFLAGS and LDFLAGS passed.\n# However when building the dependencies (Jemalloc, Lua, Hiredis, ...)\n# CFLAGS and LDFLAGS are propagated to the dependencies, so to pass\n# flags only to be used when compiling / linking Redis itself REDIS_CFLAGS\n# and REDIS_LDFLAGS are used instead (this is the case of 'make gcov').\n#\n# Dependencies are stored in the Makefile.dep file. To rebuild this file\n# Just use 'make dep', but this is only needed by developers.\n\nrelease_hdr := $(shell sh -c './mkreleasehdr.sh')\nuname_S := $(shell sh -c 'uname -s 2>/dev/null || echo not')\nOPTIMIZATION?=-O2\nDEPENDENCY_TARGETS=hiredis linenoise lua geohash-int\n\n# Default settings\nSTD=-std=c99 -pedantic -DREDIS_STATIC=''\nWARN=-Wall -W\nOPT=$(OPTIMIZATION)\n\nPREFIX?=/usr/local\nINSTALL_BIN=$(PREFIX)/bin\nINSTALL=install\n\n# Default allocator\nifeq ($(uname_S),Linux)\n\tMALLOC=jemalloc\nelse\n\tMALLOC=libc\nendif\n\n# Backwards compatibility for selecting an allocator\nifeq ($(USE_TCMALLOC),yes)\n\tMALLOC=tcmalloc\nendif\n\nifeq ($(USE_TCMALLOC_MINIMAL),yes)\n\tMALLOC=tcmalloc_minimal\nendif\n\nifeq ($(USE_JEMALLOC),yes)\n\tMALLOC=jemalloc\nendif\n\nifeq ($(USE_JEMALLOC),no)\n\tMALLOC=libc\nendif\n\n# Override default settings if possible\n-include .make-settings\n\nFINAL_CFLAGS=$(STD) $(WARN) $(OPT) $(DEBUG) $(CFLAGS) $(REDIS_CFLAGS) -I../deps/geohash-int\nFINAL_LDFLAGS=$(LDFLAGS) $(REDIS_LDFLAGS) $(DEBUG)\nFINAL_LIBS=-lm\nDEBUG=-g -ggdb\n\nifeq ($(uname_S),SunOS)\n\t# SunOS\n\tINSTALL=cp -pf\n\tFINAL_CFLAGS+= -D__EXTENSIONS__ -D_XPG6\n\tFINAL_LIBS+= -ldl -lnsl -lsocket -lresolv -lpthread -lrt\nelse\nifeq ($(uname_S),Darwin)\n\t# Darwin (nothing to do)\nelse\nifeq ($(uname_S),AIX)\n        # AIX\n        FINAL_LDFLAGS+= -Wl,-bexpall\n        FINAL_LIBS+= -pthread -lcrypt -lbsd\n\nelse\n\t# All the other OSes (notably Linux)\n\tFINAL_LDFLAGS+= -rdynamic\n\tFINAL_LIBS+= -pthread\nendif\nendif\nendif\n# Include paths to dependencies\nFINAL_CFLAGS+= -I../deps/hiredis -I../deps/linenoise -I../deps/lua/src\n\nifeq ($(MALLOC),tcmalloc)\n\tFINAL_CFLAGS+= -DUSE_TCMALLOC\n\tFINAL_LIBS+= -ltcmalloc\nendif\n\nifeq ($(MALLOC),tcmalloc_minimal)\n\tFINAL_CFLAGS+= -DUSE_TCMALLOC\n\tFINAL_LIBS+= -ltcmalloc_minimal\nendif\n\nifeq ($(MALLOC),jemalloc)\n\tDEPENDENCY_TARGETS+= jemalloc\n\tFINAL_CFLAGS+= -DUSE_JEMALLOC -I../deps/jemalloc/include\n\tFINAL_LIBS+= ../deps/jemalloc/lib/libjemalloc.a -ldl -lrt\nendif\n\nREDIS_CC=$(QUIET_CC)$(CC) $(FINAL_CFLAGS)\nREDIS_LD=$(QUIET_LINK)$(CC) $(FINAL_LDFLAGS)\nREDIS_INSTALL=$(QUIET_INSTALL)$(INSTALL)\n\nCCCOLOR=\"\\033[34m\"\nLINKCOLOR=\"\\033[34;1m\"\nSRCCOLOR=\"\\033[33m\"\nBINCOLOR=\"\\033[37;1m\"\nMAKECOLOR=\"\\033[32;1m\"\nENDCOLOR=\"\\033[0m\"\n\nifndef V\nQUIET_CC = @printf '    %b %b\\n' $(CCCOLOR)CC$(ENDCOLOR) $(SRCCOLOR)$@$(ENDCOLOR) 1>&2;\nQUIET_LINK = @printf '    %b %b\\n' $(LINKCOLOR)LINK$(ENDCOLOR) $(BINCOLOR)$@$(ENDCOLOR) 1>&2;\nQUIET_INSTALL = @printf '    %b %b\\n' $(LINKCOLOR)INSTALL$(ENDCOLOR) $(BINCOLOR)$@$(ENDCOLOR) 1>&2;\nendif\n\nREDIS_SERVER_NAME=redis-server\nREDIS_SENTINEL_NAME=redis-sentinel\nREDIS_SERVER_OBJ=adlist.o quicklist.o ae.o anet.o dict.o server.o sds.o zmalloc.o lzf_c.o lzf_d.o pqsort.o zipmap.o sha1.o ziplist.o release.o networking.o util.o object.o db.o replication.o rdb.o t_string.o t_list.o t_set.o t_zset.o t_hash.o config.o aof.o pubsub.o multi.o debug.o sort.o intset.o syncio.o cluster.o crc16.o endianconv.o slowlog.o scripting.o bio.o rio.o rand.o memtest.o crc64.o bitops.o sentinel.o notify.o setproctitle.o blocked.o hyperloglog.o latency.o sparkline.o redis-check-rdb.o geo.o slots.o crc32.o\nREDIS_GEOHASH_OBJ=../deps/geohash-int/geohash.o ../deps/geohash-int/geohash_helper.o\nREDIS_CLI_NAME=redis-cli\nREDIS_CLI_OBJ=anet.o adlist.o redis-cli.o zmalloc.o release.o anet.o ae.o crc64.o\nREDIS_BENCHMARK_NAME=redis-benchmark\nREDIS_BENCHMARK_OBJ=ae.o anet.o redis-benchmark.o adlist.o zmalloc.o redis-benchmark.o\nREDIS_CHECK_RDB_NAME=redis-check-rdb\nREDIS_CHECK_AOF_NAME=redis-check-aof\nREDIS_CHECK_AOF_OBJ=redis-check-aof.o\n\nall: $(REDIS_SERVER_NAME) $(REDIS_SENTINEL_NAME) $(REDIS_CLI_NAME) $(REDIS_BENCHMARK_NAME) $(REDIS_CHECK_RDB_NAME) $(REDIS_CHECK_AOF_NAME)\n\t@echo \"\"\n\t@echo \"Hint: It's a good idea to run 'make test' ;)\"\n\t@echo \"\"\n\n.PHONY: all\n\n# Deps (use make dep to generate this)\ninclude Makefile.dep\n\ndep:\n\t$(REDIS_CC) -MM *.c > Makefile.dep\n\n.PHONY: dep\n\npersist-settings: distclean\n\techo STD=$(STD) >> .make-settings\n\techo WARN=$(WARN) >> .make-settings\n\techo OPT=$(OPT) >> .make-settings\n\techo MALLOC=$(MALLOC) >> .make-settings\n\techo CFLAGS=$(CFLAGS) >> .make-settings\n\techo LDFLAGS=$(LDFLAGS) >> .make-settings\n\techo REDIS_CFLAGS=$(REDIS_CFLAGS) >> .make-settings\n\techo REDIS_LDFLAGS=$(REDIS_LDFLAGS) >> .make-settings\n\techo PREV_FINAL_CFLAGS=$(FINAL_CFLAGS) >> .make-settings\n\techo PREV_FINAL_LDFLAGS=$(FINAL_LDFLAGS) >> .make-settings\n\t-(cd ../deps && $(MAKE) $(DEPENDENCY_TARGETS))\n\n.PHONY: persist-settings\n\n# Prerequisites target\n.make-prerequisites:\n\t@touch $@\n\n# Clean everything, persist settings and build dependencies if anything changed\nifneq ($(strip $(PREV_FINAL_CFLAGS)), $(strip $(FINAL_CFLAGS)))\n.make-prerequisites: persist-settings\nendif\n\nifneq ($(strip $(PREV_FINAL_LDFLAGS)), $(strip $(FINAL_LDFLAGS)))\n.make-prerequisites: persist-settings\nendif\n\n# redis-server\n$(REDIS_SERVER_NAME): $(REDIS_SERVER_OBJ)\n\t$(REDIS_LD) -o $@ $^ ../deps/hiredis/libhiredis.a ../deps/lua/src/liblua.a $(REDIS_GEOHASH_OBJ) $(FINAL_LIBS)\n\n# redis-sentinel\n$(REDIS_SENTINEL_NAME): $(REDIS_SERVER_NAME)\n\t$(REDIS_INSTALL) $(REDIS_SERVER_NAME) $(REDIS_SENTINEL_NAME)\n\n# redis-check-rdb\n$(REDIS_CHECK_RDB_NAME): $(REDIS_SERVER_NAME)\n\t$(REDIS_INSTALL) $(REDIS_SERVER_NAME) $(REDIS_CHECK_RDB_NAME)\n\n# redis-cli\n$(REDIS_CLI_NAME): $(REDIS_CLI_OBJ)\n\t$(REDIS_LD) -o $@ $^ ../deps/hiredis/libhiredis.a ../deps/linenoise/linenoise.o $(FINAL_LIBS)\n\n# redis-benchmark\n$(REDIS_BENCHMARK_NAME): $(REDIS_BENCHMARK_OBJ)\n\t$(REDIS_LD) -o $@ $^ ../deps/hiredis/libhiredis.a $(FINAL_LIBS)\n\n# redis-check-aof\n$(REDIS_CHECK_AOF_NAME): $(REDIS_CHECK_AOF_OBJ)\n\t$(REDIS_LD) -o $@ $^ $(FINAL_LIBS)\n\n# Because the jemalloc.h header is generated as a part of the jemalloc build,\n# building it should complete before building any other object. Instead of\n# depending on a single artifact, build all dependencies first.\n%.o: %.c .make-prerequisites\n\t$(REDIS_CC) -c $<\n\nclean:\n\trm -rf $(REDIS_SERVER_NAME) $(REDIS_SENTINEL_NAME) $(REDIS_CLI_NAME) $(REDIS_BENCHMARK_NAME) $(REDIS_CHECK_RDB_NAME) $(REDIS_CHECK_AOF_NAME) *.o *.gcda *.gcno *.gcov redis.info lcov-html\n\n.PHONY: clean\n\ndistclean: clean\n\t-(cd ../deps && $(MAKE) distclean)\n\t-(rm -f .make-*)\n\n.PHONY: distclean\n\ntest: $(REDIS_SERVER_NAME) $(REDIS_CHECK_AOF_NAME)\n\t@(cd ..; ./runtest)\n\ntest-sentinel: $(REDIS_SENTINEL_NAME)\n\t@(cd ..; ./runtest-sentinel)\n\ncheck: test\n\nlcov:\n\t$(MAKE) gcov\n\t@(set -e; cd ..; ./runtest --clients 1)\n\t@geninfo -o redis.info .\n\t@genhtml --legend -o lcov-html redis.info\n\ntest-sds: sds.c sds.h\n\t$(REDIS_CC) sds.c zmalloc.c -DSDS_TEST_MAIN -o /tmp/sds_test\n\t/tmp/sds_test\n\n.PHONY: lcov\n\nbench: $(REDIS_BENCHMARK_NAME)\n\t./$(REDIS_BENCHMARK_NAME)\n\n32bit:\n\t@echo \"\"\n\t@echo \"WARNING: if it fails under Linux you probably need to install libc6-dev-i386\"\n\t@echo \"\"\n\t$(MAKE) CFLAGS=\"-m32\" LDFLAGS=\"-m32\"\n\ngcov:\n\t$(MAKE) REDIS_CFLAGS=\"-fprofile-arcs -ftest-coverage -DCOVERAGE_TEST\" REDIS_LDFLAGS=\"-fprofile-arcs -ftest-coverage\"\n\nnoopt:\n\t$(MAKE) OPTIMIZATION=\"-O0\"\n\nvalgrind:\n\t$(MAKE) OPTIMIZATION=\"-O0\" MALLOC=\"libc\"\n\nsrc/help.h:\n\t@../utils/generate-command-help.rb > help.h\n\ninstall: all\n\t@mkdir -p $(INSTALL_BIN)\n\t$(REDIS_INSTALL) $(REDIS_SERVER_NAME) $(INSTALL_BIN)\n\t$(REDIS_INSTALL) $(REDIS_BENCHMARK_NAME) $(INSTALL_BIN)\n\t$(REDIS_INSTALL) $(REDIS_CLI_NAME) $(INSTALL_BIN)\n\t$(REDIS_INSTALL) $(REDIS_CHECK_RDB_NAME) $(INSTALL_BIN)\n\t$(REDIS_INSTALL) $(REDIS_CHECK_AOF_NAME) $(INSTALL_BIN)\n\t@ln -sf $(REDIS_SERVER_NAME) $(INSTALL_BIN)/$(REDIS_SENTINEL_NAME)\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/src/Makefile.dep",
    "content": "adlist.o: adlist.c adlist.h zmalloc.h\nae.o: ae.c ae.h zmalloc.h config.h ae_kqueue.c ae_epoll.c ae_select.c ae_evport.c\nae_epoll.o: ae_epoll.c\nae_evport.o: ae_evport.c\nae_kqueue.o: ae_kqueue.c\nae_select.o: ae_select.c\nanet.o: anet.c fmacros.h anet.h\naof.o: aof.c server.h fmacros.h config.h solarisfixes.h \\\n ../deps/lua/src/lua.h ../deps/lua/src/luaconf.h ae.h sds.h dict.h \\\n adlist.h zmalloc.h anet.h ziplist.h intset.h version.h util.h latency.h \\\n sparkline.h quicklist.h zipmap.h sha1.h endianconv.h crc64.h rdb.h rio.h \\\n bio.h\nbio.o: bio.c server.h fmacros.h config.h solarisfixes.h \\\n ../deps/lua/src/lua.h ../deps/lua/src/luaconf.h ae.h sds.h dict.h \\\n adlist.h zmalloc.h anet.h ziplist.h intset.h version.h util.h latency.h \\\n sparkline.h quicklist.h zipmap.h sha1.h endianconv.h crc64.h rdb.h rio.h \\\n bio.h\nbitops.o: bitops.c server.h fmacros.h config.h solarisfixes.h \\\n ../deps/lua/src/lua.h ../deps/lua/src/luaconf.h ae.h sds.h dict.h \\\n adlist.h zmalloc.h anet.h ziplist.h intset.h version.h util.h latency.h \\\n sparkline.h quicklist.h zipmap.h sha1.h endianconv.h crc64.h rdb.h rio.h\nblocked.o: blocked.c server.h fmacros.h config.h solarisfixes.h \\\n ../deps/lua/src/lua.h ../deps/lua/src/luaconf.h ae.h sds.h dict.h \\\n adlist.h zmalloc.h anet.h ziplist.h intset.h version.h util.h latency.h \\\n sparkline.h quicklist.h zipmap.h sha1.h endianconv.h crc64.h rdb.h rio.h\ncluster.o: cluster.c server.h fmacros.h config.h solarisfixes.h \\\n ../deps/lua/src/lua.h ../deps/lua/src/luaconf.h ae.h sds.h dict.h \\\n adlist.h zmalloc.h anet.h ziplist.h intset.h version.h util.h latency.h \\\n sparkline.h quicklist.h zipmap.h sha1.h endianconv.h crc64.h rdb.h rio.h \\\n cluster.h\nconfig.o: config.c server.h fmacros.h config.h solarisfixes.h \\\n ../deps/lua/src/lua.h ../deps/lua/src/luaconf.h ae.h sds.h dict.h \\\n adlist.h zmalloc.h anet.h ziplist.h intset.h version.h util.h latency.h \\\n sparkline.h quicklist.h zipmap.h sha1.h endianconv.h crc64.h rdb.h rio.h \\\n cluster.h\ncrc16.o: crc16.c server.h fmacros.h config.h solarisfixes.h \\\n ../deps/lua/src/lua.h ../deps/lua/src/luaconf.h ae.h sds.h dict.h \\\n adlist.h zmalloc.h anet.h ziplist.h intset.h version.h util.h latency.h \\\n sparkline.h quicklist.h zipmap.h sha1.h endianconv.h crc64.h rdb.h rio.h\ncrc64.o: crc64.c\ndb.o: db.c server.h fmacros.h config.h solarisfixes.h \\\n ../deps/lua/src/lua.h ../deps/lua/src/luaconf.h ae.h sds.h dict.h \\\n adlist.h zmalloc.h anet.h ziplist.h intset.h version.h util.h latency.h \\\n sparkline.h quicklist.h zipmap.h sha1.h endianconv.h crc64.h rdb.h rio.h \\\n cluster.h\ndebug.o: debug.c server.h fmacros.h config.h solarisfixes.h \\\n ../deps/lua/src/lua.h ../deps/lua/src/luaconf.h ae.h sds.h dict.h \\\n adlist.h zmalloc.h anet.h ziplist.h intset.h version.h util.h latency.h \\\n sparkline.h quicklist.h zipmap.h sha1.h endianconv.h crc64.h rdb.h rio.h \\\n bio.h\ndict.o: dict.c fmacros.h dict.h zmalloc.h redisassert.h\nendianconv.o: endianconv.c\ngeo.o: geo.c geo.h server.h fmacros.h config.h solarisfixes.h \\\n ../deps/lua/src/lua.h ../deps/lua/src/luaconf.h ae.h sds.h dict.h \\\n adlist.h zmalloc.h anet.h ziplist.h intset.h version.h util.h latency.h \\\n sparkline.h quicklist.h zipmap.h sha1.h endianconv.h crc64.h rdb.h rio.h \\\n ../deps/geohash-int/geohash_helper.h ../deps/geohash-int/geohash.h\nhyperloglog.o: hyperloglog.c server.h fmacros.h config.h solarisfixes.h \\\n ../deps/lua/src/lua.h ../deps/lua/src/luaconf.h ae.h sds.h dict.h \\\n adlist.h zmalloc.h anet.h ziplist.h intset.h version.h util.h latency.h \\\n sparkline.h quicklist.h zipmap.h sha1.h endianconv.h crc64.h rdb.h rio.h\nintset.o: intset.c intset.h zmalloc.h endianconv.h config.h\nlatency.o: latency.c server.h fmacros.h config.h solarisfixes.h \\\n ../deps/lua/src/lua.h ../deps/lua/src/luaconf.h ae.h sds.h dict.h \\\n adlist.h zmalloc.h anet.h ziplist.h intset.h version.h util.h latency.h \\\n sparkline.h quicklist.h zipmap.h sha1.h endianconv.h crc64.h rdb.h rio.h\nlzf_c.o: lzf_c.c lzfP.h\nlzf_d.o: lzf_d.c lzfP.h\nmemtest.o: memtest.c config.h\ncrc32.o: crc32.c\nslots.o: slots.c server.h\nmulti.o: multi.c server.h fmacros.h config.h solarisfixes.h \\\n ../deps/lua/src/lua.h ../deps/lua/src/luaconf.h ae.h sds.h dict.h \\\n adlist.h zmalloc.h anet.h ziplist.h intset.h version.h util.h latency.h \\\n sparkline.h quicklist.h zipmap.h sha1.h endianconv.h crc64.h rdb.h rio.h\nnetworking.o: networking.c server.h fmacros.h config.h solarisfixes.h \\\n ../deps/lua/src/lua.h ../deps/lua/src/luaconf.h ae.h sds.h dict.h \\\n adlist.h zmalloc.h anet.h ziplist.h intset.h version.h util.h latency.h \\\n sparkline.h quicklist.h zipmap.h sha1.h endianconv.h crc64.h rdb.h rio.h\nnotify.o: notify.c server.h fmacros.h config.h solarisfixes.h \\\n ../deps/lua/src/lua.h ../deps/lua/src/luaconf.h ae.h sds.h dict.h \\\n adlist.h zmalloc.h anet.h ziplist.h intset.h version.h util.h latency.h \\\n sparkline.h quicklist.h zipmap.h sha1.h endianconv.h crc64.h rdb.h rio.h\nobject.o: object.c server.h fmacros.h config.h solarisfixes.h \\\n ../deps/lua/src/lua.h ../deps/lua/src/luaconf.h ae.h sds.h dict.h \\\n adlist.h zmalloc.h anet.h ziplist.h intset.h version.h util.h latency.h \\\n sparkline.h quicklist.h zipmap.h sha1.h endianconv.h crc64.h rdb.h rio.h\npqsort.o: pqsort.c\npubsub.o: pubsub.c server.h fmacros.h config.h solarisfixes.h \\\n ../deps/lua/src/lua.h ../deps/lua/src/luaconf.h ae.h sds.h dict.h \\\n adlist.h zmalloc.h anet.h ziplist.h intset.h version.h util.h latency.h \\\n sparkline.h quicklist.h zipmap.h sha1.h endianconv.h crc64.h rdb.h rio.h\nquicklist.o: quicklist.c quicklist.h zmalloc.h ziplist.h util.h sds.h \\\n lzf.h\nrand.o: rand.c\nrdb.o: rdb.c server.h fmacros.h config.h solarisfixes.h \\\n ../deps/lua/src/lua.h ../deps/lua/src/luaconf.h ae.h sds.h dict.h \\\n adlist.h zmalloc.h anet.h ziplist.h intset.h version.h util.h latency.h \\\n sparkline.h quicklist.h zipmap.h sha1.h endianconv.h crc64.h rdb.h rio.h \\\n lzf.h\nredis-benchmark.o: redis-benchmark.c fmacros.h ../deps/hiredis/sds.h ae.h \\\n ../deps/hiredis/hiredis.h adlist.h zmalloc.h\nredis-check-aof.o: redis-check-aof.c fmacros.h config.h\nredis-check-rdb.o: redis-check-rdb.c server.h fmacros.h config.h \\\n solarisfixes.h ../deps/lua/src/lua.h ../deps/lua/src/luaconf.h ae.h \\\n sds.h dict.h adlist.h zmalloc.h anet.h ziplist.h intset.h version.h \\\n util.h latency.h sparkline.h quicklist.h zipmap.h sha1.h endianconv.h \\\n crc64.h rdb.h rio.h lzf.h\nredis-cli.o: redis-cli.c fmacros.h version.h ../deps/hiredis/hiredis.h \\\n ../deps/hiredis/sds.h zmalloc.h ../deps/linenoise/linenoise.h help.h \\\n anet.h ae.h\nrelease.o: release.c release.h version.h crc64.h\nreplication.o: replication.c server.h fmacros.h config.h solarisfixes.h \\\n ../deps/lua/src/lua.h ../deps/lua/src/luaconf.h ae.h sds.h dict.h \\\n adlist.h zmalloc.h anet.h ziplist.h intset.h version.h util.h latency.h \\\n sparkline.h quicklist.h zipmap.h sha1.h endianconv.h crc64.h rdb.h rio.h\nrio.o: rio.c fmacros.h rio.h sds.h util.h crc64.h config.h server.h \\\n solarisfixes.h ../deps/lua/src/lua.h ../deps/lua/src/luaconf.h ae.h \\\n dict.h adlist.h zmalloc.h anet.h ziplist.h intset.h version.h latency.h \\\n sparkline.h quicklist.h zipmap.h sha1.h endianconv.h rdb.h\nscripting.o: scripting.c server.h fmacros.h config.h solarisfixes.h \\\n ../deps/lua/src/lua.h ../deps/lua/src/luaconf.h ae.h sds.h dict.h \\\n adlist.h zmalloc.h anet.h ziplist.h intset.h version.h util.h latency.h \\\n sparkline.h quicklist.h zipmap.h sha1.h endianconv.h crc64.h rdb.h rio.h \\\n rand.h cluster.h ../deps/lua/src/lauxlib.h ../deps/lua/src/lua.h \\\n ../deps/lua/src/lualib.h\nsds.o: sds.c sds.h sdsalloc.h zmalloc.h\nsentinel.o: sentinel.c server.h fmacros.h config.h solarisfixes.h \\\n ../deps/lua/src/lua.h ../deps/lua/src/luaconf.h ae.h sds.h dict.h \\\n adlist.h zmalloc.h anet.h ziplist.h intset.h version.h util.h latency.h \\\n sparkline.h quicklist.h zipmap.h sha1.h endianconv.h crc64.h rdb.h rio.h \\\n ../deps/hiredis/hiredis.h ../deps/hiredis/async.h \\\n ../deps/hiredis/hiredis.h\nserver.o: server.c server.h fmacros.h config.h solarisfixes.h \\\n ../deps/lua/src/lua.h ../deps/lua/src/luaconf.h ae.h sds.h dict.h \\\n adlist.h zmalloc.h anet.h ziplist.h intset.h version.h util.h latency.h \\\n sparkline.h quicklist.h zipmap.h sha1.h endianconv.h crc64.h rdb.h rio.h \\\n cluster.h slowlog.h bio.h asciilogo.h\nsetproctitle.o: setproctitle.c\nsha1.o: sha1.c solarisfixes.h sha1.h config.h\nslowlog.o: slowlog.c server.h fmacros.h config.h solarisfixes.h \\\n ../deps/lua/src/lua.h ../deps/lua/src/luaconf.h ae.h sds.h dict.h \\\n adlist.h zmalloc.h anet.h ziplist.h intset.h version.h util.h latency.h \\\n sparkline.h quicklist.h zipmap.h sha1.h endianconv.h crc64.h rdb.h rio.h \\\n slowlog.h\nsort.o: sort.c server.h fmacros.h config.h solarisfixes.h \\\n ../deps/lua/src/lua.h ../deps/lua/src/luaconf.h ae.h sds.h dict.h \\\n adlist.h zmalloc.h anet.h ziplist.h intset.h version.h util.h latency.h \\\n sparkline.h quicklist.h zipmap.h sha1.h endianconv.h crc64.h rdb.h rio.h \\\n pqsort.h\nsparkline.o: sparkline.c server.h fmacros.h config.h solarisfixes.h \\\n ../deps/lua/src/lua.h ../deps/lua/src/luaconf.h ae.h sds.h dict.h \\\n adlist.h zmalloc.h anet.h ziplist.h intset.h version.h util.h latency.h \\\n sparkline.h quicklist.h zipmap.h sha1.h endianconv.h crc64.h rdb.h rio.h\nsyncio.o: syncio.c server.h fmacros.h config.h solarisfixes.h \\\n ../deps/lua/src/lua.h ../deps/lua/src/luaconf.h ae.h sds.h dict.h \\\n adlist.h zmalloc.h anet.h ziplist.h intset.h version.h util.h latency.h \\\n sparkline.h quicklist.h zipmap.h sha1.h endianconv.h crc64.h rdb.h rio.h\nt_hash.o: t_hash.c server.h fmacros.h config.h solarisfixes.h \\\n ../deps/lua/src/lua.h ../deps/lua/src/luaconf.h ae.h sds.h dict.h \\\n adlist.h zmalloc.h anet.h ziplist.h intset.h version.h util.h latency.h \\\n sparkline.h quicklist.h zipmap.h sha1.h endianconv.h crc64.h rdb.h rio.h\nt_list.o: t_list.c server.h fmacros.h config.h solarisfixes.h \\\n ../deps/lua/src/lua.h ../deps/lua/src/luaconf.h ae.h sds.h dict.h \\\n adlist.h zmalloc.h anet.h ziplist.h intset.h version.h util.h latency.h \\\n sparkline.h quicklist.h zipmap.h sha1.h endianconv.h crc64.h rdb.h rio.h\nt_set.o: t_set.c server.h fmacros.h config.h solarisfixes.h \\\n ../deps/lua/src/lua.h ../deps/lua/src/luaconf.h ae.h sds.h dict.h \\\n adlist.h zmalloc.h anet.h ziplist.h intset.h version.h util.h latency.h \\\n sparkline.h quicklist.h zipmap.h sha1.h endianconv.h crc64.h rdb.h rio.h\nt_string.o: t_string.c server.h fmacros.h config.h solarisfixes.h \\\n ../deps/lua/src/lua.h ../deps/lua/src/luaconf.h ae.h sds.h dict.h \\\n adlist.h zmalloc.h anet.h ziplist.h intset.h version.h util.h latency.h \\\n sparkline.h quicklist.h zipmap.h sha1.h endianconv.h crc64.h rdb.h rio.h\nt_zset.o: t_zset.c server.h fmacros.h config.h solarisfixes.h \\\n ../deps/lua/src/lua.h ../deps/lua/src/luaconf.h ae.h sds.h dict.h \\\n adlist.h zmalloc.h anet.h ziplist.h intset.h version.h util.h latency.h \\\n sparkline.h quicklist.h zipmap.h sha1.h endianconv.h crc64.h rdb.h rio.h\nutil.o: util.c fmacros.h util.h sds.h sha1.h\nziplist.o: ziplist.c zmalloc.h util.h sds.h ziplist.h endianconv.h \\\n config.h redisassert.h\nzipmap.o: zipmap.c zmalloc.h endianconv.h config.h\nzmalloc.o: zmalloc.c config.h zmalloc.h\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/src/adlist.c",
    "content": "/* adlist.c - A generic doubly linked list implementation\n *\n * Copyright (c) 2006-2010, Salvatore Sanfilippo <antirez at gmail dot com>\n * All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions are met:\n *\n *   * Redistributions of source code must retain the above copyright notice,\n *     this list of conditions and the following disclaimer.\n *   * Redistributions in binary form must reproduce the above copyright\n *     notice, this list of conditions and the following disclaimer in the\n *     documentation and/or other materials provided with the distribution.\n *   * Neither the name of Redis nor the names of its contributors may be used\n *     to endorse or promote products derived from this software without\n *     specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\"\n * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\n * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE\n * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR\n * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF\n * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS\n * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN\n * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)\n * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE\n * POSSIBILITY OF SUCH DAMAGE.\n */\n\n\n#include <stdlib.h>\n#include \"adlist.h\"\n#include \"zmalloc.h\"\n\n/* Create a new list. The created list can be freed with\n * AlFreeList(), but private value of every node need to be freed\n * by the user before to call AlFreeList().\n *\n * On error, NULL is returned. Otherwise the pointer to the new list. */\nlist *listCreate(void)\n{\n    struct list *list;\n\n    if ((list = zmalloc(sizeof(*list))) == NULL)\n        return NULL;\n    list->head = list->tail = NULL;\n    list->len = 0;\n    list->dup = NULL;\n    list->free = NULL;\n    list->match = NULL;\n    return list;\n}\n\n/* Free the whole list.\n *\n * This function can't fail. */\nvoid listRelease(list *list)\n{\n    unsigned long len;\n    listNode *current, *next;\n\n    current = list->head;\n    len = list->len;\n    while(len--) {\n        next = current->next;\n        if (list->free) list->free(current->value);\n        zfree(current);\n        current = next;\n    }\n    zfree(list);\n}\n\n/* Add a new node to the list, to head, containing the specified 'value'\n * pointer as value.\n *\n * On error, NULL is returned and no operation is performed (i.e. the\n * list remains unaltered).\n * On success the 'list' pointer you pass to the function is returned. */\nlist *listAddNodeHead(list *list, void *value)\n{\n    listNode *node;\n\n    if ((node = zmalloc(sizeof(*node))) == NULL)\n        return NULL;\n    node->value = value;\n    if (list->len == 0) {\n        list->head = list->tail = node;\n        node->prev = node->next = NULL;\n    } else {\n        node->prev = NULL;\n        node->next = list->head;\n        list->head->prev = node;\n        list->head = node;\n    }\n    list->len++;\n    return list;\n}\n\n/* Add a new node to the list, to tail, containing the specified 'value'\n * pointer as value.\n *\n * On error, NULL is returned and no operation is performed (i.e. the\n * list remains unaltered).\n * On success the 'list' pointer you pass to the function is returned. */\nlist *listAddNodeTail(list *list, void *value)\n{\n    listNode *node;\n\n    if ((node = zmalloc(sizeof(*node))) == NULL)\n        return NULL;\n    node->value = value;\n    if (list->len == 0) {\n        list->head = list->tail = node;\n        node->prev = node->next = NULL;\n    } else {\n        node->prev = list->tail;\n        node->next = NULL;\n        list->tail->next = node;\n        list->tail = node;\n    }\n    list->len++;\n    return list;\n}\n\nlist *listInsertNode(list *list, listNode *old_node, void *value, int after) {\n    listNode *node;\n\n    if ((node = zmalloc(sizeof(*node))) == NULL)\n        return NULL;\n    node->value = value;\n    if (after) {\n        node->prev = old_node;\n        node->next = old_node->next;\n        if (list->tail == old_node) {\n            list->tail = node;\n        }\n    } else {\n        node->next = old_node;\n        node->prev = old_node->prev;\n        if (list->head == old_node) {\n            list->head = node;\n        }\n    }\n    if (node->prev != NULL) {\n        node->prev->next = node;\n    }\n    if (node->next != NULL) {\n        node->next->prev = node;\n    }\n    list->len++;\n    return list;\n}\n\n/* Remove the specified node from the specified list.\n * It's up to the caller to free the private value of the node.\n *\n * This function can't fail. */\nvoid listDelNode(list *list, listNode *node)\n{\n    if (node->prev)\n        node->prev->next = node->next;\n    else\n        list->head = node->next;\n    if (node->next)\n        node->next->prev = node->prev;\n    else\n        list->tail = node->prev;\n    if (list->free) list->free(node->value);\n    zfree(node);\n    list->len--;\n}\n\n/* Returns a list iterator 'iter'. After the initialization every\n * call to listNext() will return the next element of the list.\n *\n * This function can't fail. */\nlistIter *listGetIterator(list *list, int direction)\n{\n    listIter *iter;\n\n    if ((iter = zmalloc(sizeof(*iter))) == NULL) return NULL;\n    if (direction == AL_START_HEAD)\n        iter->next = list->head;\n    else\n        iter->next = list->tail;\n    iter->direction = direction;\n    return iter;\n}\n\n/* Release the iterator memory */\nvoid listReleaseIterator(listIter *iter) {\n    zfree(iter);\n}\n\n/* Create an iterator in the list private iterator structure */\nvoid listRewind(list *list, listIter *li) {\n    li->next = list->head;\n    li->direction = AL_START_HEAD;\n}\n\nvoid listRewindTail(list *list, listIter *li) {\n    li->next = list->tail;\n    li->direction = AL_START_TAIL;\n}\n\n/* Return the next element of an iterator.\n * It's valid to remove the currently returned element using\n * listDelNode(), but not to remove other elements.\n *\n * The function returns a pointer to the next element of the list,\n * or NULL if there are no more elements, so the classical usage patter\n * is:\n *\n * iter = listGetIterator(list,<direction>);\n * while ((node = listNext(iter)) != NULL) {\n *     doSomethingWith(listNodeValue(node));\n * }\n *\n * */\nlistNode *listNext(listIter *iter)\n{\n    listNode *current = iter->next;\n\n    if (current != NULL) {\n        if (iter->direction == AL_START_HEAD)\n            iter->next = current->next;\n        else\n            iter->next = current->prev;\n    }\n    return current;\n}\n\n/* Duplicate the whole list. On out of memory NULL is returned.\n * On success a copy of the original list is returned.\n *\n * The 'Dup' method set with listSetDupMethod() function is used\n * to copy the node value. Otherwise the same pointer value of\n * the original node is used as value of the copied node.\n *\n * The original list both on success or error is never modified. */\nlist *listDup(list *orig)\n{\n    list *copy;\n    listIter iter;\n    listNode *node;\n\n    if ((copy = listCreate()) == NULL)\n        return NULL;\n    copy->dup = orig->dup;\n    copy->free = orig->free;\n    copy->match = orig->match;\n    listRewind(orig, &iter);\n    while((node = listNext(&iter)) != NULL) {\n        void *value;\n\n        if (copy->dup) {\n            value = copy->dup(node->value);\n            if (value == NULL) {\n                listRelease(copy);\n                return NULL;\n            }\n        } else\n            value = node->value;\n        if (listAddNodeTail(copy, value) == NULL) {\n            listRelease(copy);\n            return NULL;\n        }\n    }\n    return copy;\n}\n\n/* Search the list for a node matching a given key.\n * The match is performed using the 'match' method\n * set with listSetMatchMethod(). If no 'match' method\n * is set, the 'value' pointer of every node is directly\n * compared with the 'key' pointer.\n *\n * On success the first matching node pointer is returned\n * (search starts from head). If no matching node exists\n * NULL is returned. */\nlistNode *listSearchKey(list *list, void *key)\n{\n    listIter iter;\n    listNode *node;\n\n    listRewind(list, &iter);\n    while((node = listNext(&iter)) != NULL) {\n        if (list->match) {\n            if (list->match(node->value, key)) {\n                return node;\n            }\n        } else {\n            if (key == node->value) {\n                return node;\n            }\n        }\n    }\n    return NULL;\n}\n\n/* Return the element at the specified zero-based index\n * where 0 is the head, 1 is the element next to head\n * and so on. Negative integers are used in order to count\n * from the tail, -1 is the last element, -2 the penultimate\n * and so on. If the index is out of range NULL is returned. */\nlistNode *listIndex(list *list, long index) {\n    listNode *n;\n\n    if (index < 0) {\n        index = (-index)-1;\n        n = list->tail;\n        while(index-- && n) n = n->prev;\n    } else {\n        n = list->head;\n        while(index-- && n) n = n->next;\n    }\n    return n;\n}\n\n/* Rotate the list removing the tail node and inserting it to the head. */\nvoid listRotate(list *list) {\n    listNode *tail = list->tail;\n\n    if (listLength(list) <= 1) return;\n\n    /* Detach current tail */\n    list->tail = tail->prev;\n    list->tail->next = NULL;\n    /* Move it as head */\n    list->head->prev = tail;\n    tail->prev = NULL;\n    tail->next = list->head;\n    list->head = tail;\n}\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/src/adlist.h",
    "content": "/* adlist.h - A generic doubly linked list implementation\n *\n * Copyright (c) 2006-2012, Salvatore Sanfilippo <antirez at gmail dot com>\n * All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions are met:\n *\n *   * Redistributions of source code must retain the above copyright notice,\n *     this list of conditions and the following disclaimer.\n *   * Redistributions in binary form must reproduce the above copyright\n *     notice, this list of conditions and the following disclaimer in the\n *     documentation and/or other materials provided with the distribution.\n *   * Neither the name of Redis nor the names of its contributors may be used\n *     to endorse or promote products derived from this software without\n *     specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\"\n * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\n * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE\n * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR\n * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF\n * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS\n * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN\n * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)\n * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE\n * POSSIBILITY OF SUCH DAMAGE.\n */\n\n#ifndef __ADLIST_H__\n#define __ADLIST_H__\n\n/* Node, List, and Iterator are the only data structures used currently. */\n\ntypedef struct listNode {\n    struct listNode *prev;\n    struct listNode *next;\n    void *value;\n} listNode;\n\ntypedef struct listIter {\n    listNode *next;\n    int direction;\n} listIter;\n\ntypedef struct list {\n    listNode *head;\n    listNode *tail;\n    void *(*dup)(void *ptr);\n    void (*free)(void *ptr);\n    int (*match)(void *ptr, void *key);\n    unsigned long len;\n} list;\n\n/* Functions implemented as macros */\n#define listLength(l) ((l)->len)\n#define listFirst(l) ((l)->head)\n#define listLast(l) ((l)->tail)\n#define listPrevNode(n) ((n)->prev)\n#define listNextNode(n) ((n)->next)\n#define listNodeValue(n) ((n)->value)\n\n#define listSetDupMethod(l,m) ((l)->dup = (m))\n#define listSetFreeMethod(l,m) ((l)->free = (m))\n#define listSetMatchMethod(l,m) ((l)->match = (m))\n\n#define listGetDupMethod(l) ((l)->dup)\n#define listGetFree(l) ((l)->free)\n#define listGetMatchMethod(l) ((l)->match)\n\n/* Prototypes */\nlist *listCreate(void);\nvoid listRelease(list *list);\nlist *listAddNodeHead(list *list, void *value);\nlist *listAddNodeTail(list *list, void *value);\nlist *listInsertNode(list *list, listNode *old_node, void *value, int after);\nvoid listDelNode(list *list, listNode *node);\nlistIter *listGetIterator(list *list, int direction);\nlistNode *listNext(listIter *iter);\nvoid listReleaseIterator(listIter *iter);\nlist *listDup(list *orig);\nlistNode *listSearchKey(list *list, void *key);\nlistNode *listIndex(list *list, long index);\nvoid listRewind(list *list, listIter *li);\nvoid listRewindTail(list *list, listIter *li);\nvoid listRotate(list *list);\n\n/* Directions for iterators */\n#define AL_START_HEAD 0\n#define AL_START_TAIL 1\n\n#endif /* __ADLIST_H__ */\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/src/ae.c",
    "content": "/* A simple event-driven programming library. Originally I wrote this code\n * for the Jim's event-loop (Jim is a Tcl interpreter) but later translated\n * it in form of a library for easy reuse.\n *\n * Copyright (c) 2006-2010, Salvatore Sanfilippo <antirez at gmail dot com>\n * All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions are met:\n *\n *   * Redistributions of source code must retain the above copyright notice,\n *     this list of conditions and the following disclaimer.\n *   * Redistributions in binary form must reproduce the above copyright\n *     notice, this list of conditions and the following disclaimer in the\n *     documentation and/or other materials provided with the distribution.\n *   * Neither the name of Redis nor the names of its contributors may be used\n *     to endorse or promote products derived from this software without\n *     specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\"\n * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\n * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE\n * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR\n * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF\n * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS\n * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN\n * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)\n * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE\n * POSSIBILITY OF SUCH DAMAGE.\n */\n\n#include <stdio.h>\n#include <sys/time.h>\n#include <sys/types.h>\n#include <unistd.h>\n#include <stdlib.h>\n#include <poll.h>\n#include <string.h>\n#include <time.h>\n#include <errno.h>\n\n#include \"ae.h\"\n#include \"zmalloc.h\"\n#include \"config.h\"\n\n/* Include the best multiplexing layer supported by this system.\n * The following should be ordered by performances, descending. */\n#ifdef HAVE_EVPORT\n#include \"ae_evport.c\"\n#else\n    #ifdef HAVE_EPOLL\n    #include \"ae_epoll.c\"\n    #else\n        #ifdef HAVE_KQUEUE\n        #include \"ae_kqueue.c\"\n        #else\n        #include \"ae_select.c\"\n        #endif\n    #endif\n#endif\n\naeEventLoop *aeCreateEventLoop(int setsize) {\n    aeEventLoop *eventLoop;\n    int i;\n\n    if ((eventLoop = zmalloc(sizeof(*eventLoop))) == NULL) goto err;\n    eventLoop->events = zmalloc(sizeof(aeFileEvent)*setsize);\n    eventLoop->fired = zmalloc(sizeof(aeFiredEvent)*setsize);\n    if (eventLoop->events == NULL || eventLoop->fired == NULL) goto err;\n    eventLoop->setsize = setsize;\n    eventLoop->lastTime = time(NULL);\n    eventLoop->timeEventHead = NULL;\n    eventLoop->timeEventNextId = 0;\n    eventLoop->stop = 0;\n    eventLoop->maxfd = -1;\n    eventLoop->beforesleep = NULL;\n    if (aeApiCreate(eventLoop) == -1) goto err;\n    /* Events with mask == AE_NONE are not set. So let's initialize the\n     * vector with it. */\n    for (i = 0; i < setsize; i++)\n        eventLoop->events[i].mask = AE_NONE;\n    return eventLoop;\n\nerr:\n    if (eventLoop) {\n        zfree(eventLoop->events);\n        zfree(eventLoop->fired);\n        zfree(eventLoop);\n    }\n    return NULL;\n}\n\n/* Return the current set size. */\nint aeGetSetSize(aeEventLoop *eventLoop) {\n    return eventLoop->setsize;\n}\n\n/* Resize the maximum set size of the event loop.\n * If the requested set size is smaller than the current set size, but\n * there is already a file descriptor in use that is >= the requested\n * set size minus one, AE_ERR is returned and the operation is not\n * performed at all.\n *\n * Otherwise AE_OK is returned and the operation is successful. */\nint aeResizeSetSize(aeEventLoop *eventLoop, int setsize) {\n    int i;\n\n    if (setsize == eventLoop->setsize) return AE_OK;\n    if (eventLoop->maxfd >= setsize) return AE_ERR;\n    if (aeApiResize(eventLoop,setsize) == -1) return AE_ERR;\n\n    eventLoop->events = zrealloc(eventLoop->events,sizeof(aeFileEvent)*setsize);\n    eventLoop->fired = zrealloc(eventLoop->fired,sizeof(aeFiredEvent)*setsize);\n    eventLoop->setsize = setsize;\n\n    /* Make sure that if we created new slots, they are initialized with\n     * an AE_NONE mask. */\n    for (i = eventLoop->maxfd+1; i < setsize; i++)\n        eventLoop->events[i].mask = AE_NONE;\n    return AE_OK;\n}\n\nvoid aeDeleteEventLoop(aeEventLoop *eventLoop) {\n    aeApiFree(eventLoop);\n    zfree(eventLoop->events);\n    zfree(eventLoop->fired);\n    zfree(eventLoop);\n}\n\nvoid aeStop(aeEventLoop *eventLoop) {\n    eventLoop->stop = 1;\n}\n\nint aeCreateFileEvent(aeEventLoop *eventLoop, int fd, int mask,\n        aeFileProc *proc, void *clientData)\n{\n    if (fd >= eventLoop->setsize) {\n        errno = ERANGE;\n        return AE_ERR;\n    }\n    aeFileEvent *fe = &eventLoop->events[fd];\n\n    if (aeApiAddEvent(eventLoop, fd, mask) == -1)\n        return AE_ERR;\n    fe->mask |= mask;\n    if (mask & AE_READABLE) fe->rfileProc = proc;\n    if (mask & AE_WRITABLE) fe->wfileProc = proc;\n    fe->clientData = clientData;\n    if (fd > eventLoop->maxfd)\n        eventLoop->maxfd = fd;\n    return AE_OK;\n}\n\nvoid aeDeleteFileEvent(aeEventLoop *eventLoop, int fd, int mask)\n{\n    if (fd >= eventLoop->setsize) return;\n    aeFileEvent *fe = &eventLoop->events[fd];\n    if (fe->mask == AE_NONE) return;\n\n    aeApiDelEvent(eventLoop, fd, mask);\n    fe->mask = fe->mask & (~mask);\n    if (fd == eventLoop->maxfd && fe->mask == AE_NONE) {\n        /* Update the max fd */\n        int j;\n\n        for (j = eventLoop->maxfd-1; j >= 0; j--)\n            if (eventLoop->events[j].mask != AE_NONE) break;\n        eventLoop->maxfd = j;\n    }\n}\n\nint aeGetFileEvents(aeEventLoop *eventLoop, int fd) {\n    if (fd >= eventLoop->setsize) return 0;\n    aeFileEvent *fe = &eventLoop->events[fd];\n\n    return fe->mask;\n}\n\nstatic void aeGetTime(long *seconds, long *milliseconds)\n{\n    struct timeval tv;\n\n    gettimeofday(&tv, NULL);\n    *seconds = tv.tv_sec;\n    *milliseconds = tv.tv_usec/1000;\n}\n\nstatic void aeAddMillisecondsToNow(long long milliseconds, long *sec, long *ms) {\n    long cur_sec, cur_ms, when_sec, when_ms;\n\n    aeGetTime(&cur_sec, &cur_ms);\n    when_sec = cur_sec + milliseconds/1000;\n    when_ms = cur_ms + milliseconds%1000;\n    if (when_ms >= 1000) {\n        when_sec ++;\n        when_ms -= 1000;\n    }\n    *sec = when_sec;\n    *ms = when_ms;\n}\n\nlong long aeCreateTimeEvent(aeEventLoop *eventLoop, long long milliseconds,\n        aeTimeProc *proc, void *clientData,\n        aeEventFinalizerProc *finalizerProc)\n{\n    long long id = eventLoop->timeEventNextId++;\n    aeTimeEvent *te;\n\n    te = zmalloc(sizeof(*te));\n    if (te == NULL) return AE_ERR;\n    te->id = id;\n    aeAddMillisecondsToNow(milliseconds,&te->when_sec,&te->when_ms);\n    te->timeProc = proc;\n    te->finalizerProc = finalizerProc;\n    te->clientData = clientData;\n    te->next = eventLoop->timeEventHead;\n    eventLoop->timeEventHead = te;\n    return id;\n}\n\nint aeDeleteTimeEvent(aeEventLoop *eventLoop, long long id)\n{\n    aeTimeEvent *te = eventLoop->timeEventHead;\n    while(te) {\n        if (te->id == id) {\n            te->id = AE_DELETED_EVENT_ID;\n            return AE_OK;\n        }\n        te = te->next;\n    }\n    return AE_ERR; /* NO event with the specified ID found */\n}\n\n/* Search the first timer to fire.\n * This operation is useful to know how many time the select can be\n * put in sleep without to delay any event.\n * If there are no timers NULL is returned.\n *\n * Note that's O(N) since time events are unsorted.\n * Possible optimizations (not needed by Redis so far, but...):\n * 1) Insert the event in order, so that the nearest is just the head.\n *    Much better but still insertion or deletion of timers is O(N).\n * 2) Use a skiplist to have this operation as O(1) and insertion as O(log(N)).\n */\nstatic aeTimeEvent *aeSearchNearestTimer(aeEventLoop *eventLoop)\n{\n    aeTimeEvent *te = eventLoop->timeEventHead;\n    aeTimeEvent *nearest = NULL;\n\n    while(te) {\n        if (!nearest || te->when_sec < nearest->when_sec ||\n                (te->when_sec == nearest->when_sec &&\n                 te->when_ms < nearest->when_ms))\n            nearest = te;\n        te = te->next;\n    }\n    return nearest;\n}\n\n/* Process time events */\nstatic int processTimeEvents(aeEventLoop *eventLoop) {\n    int processed = 0;\n    aeTimeEvent *te, *prev;\n    long long maxId;\n    time_t now = time(NULL);\n\n    /* If the system clock is moved to the future, and then set back to the\n     * right value, time events may be delayed in a random way. Often this\n     * means that scheduled operations will not be performed soon enough.\n     *\n     * Here we try to detect system clock skews, and force all the time\n     * events to be processed ASAP when this happens: the idea is that\n     * processing events earlier is less dangerous than delaying them\n     * indefinitely, and practice suggests it is. */\n    if (now < eventLoop->lastTime) {\n        te = eventLoop->timeEventHead;\n        while(te) {\n            te->when_sec = 0;\n            te = te->next;\n        }\n    }\n    eventLoop->lastTime = now;\n\n    prev = NULL;\n    te = eventLoop->timeEventHead;\n    maxId = eventLoop->timeEventNextId-1;\n    while(te) {\n        long now_sec, now_ms;\n        long long id;\n\n        /* Remove events scheduled for deletion. */\n        if (te->id == AE_DELETED_EVENT_ID) {\n            aeTimeEvent *next = te->next;\n            if (prev == NULL)\n                eventLoop->timeEventHead = te->next;\n            else\n                prev->next = te->next;\n            if (te->finalizerProc)\n                te->finalizerProc(eventLoop, te->clientData);\n            zfree(te);\n            te = next;\n            continue;\n        }\n\n        /* Make sure we don't process time events created by time events in\n         * this iteration. Note that this check is currently useless: we always\n         * add new timers on the head, however if we change the implementation\n         * detail, this check may be useful again: we keep it here for future\n         * defense. */\n        if (te->id > maxId) {\n            te = te->next;\n            continue;\n        }\n        aeGetTime(&now_sec, &now_ms);\n        if (now_sec > te->when_sec ||\n            (now_sec == te->when_sec && now_ms >= te->when_ms))\n        {\n            int retval;\n\n            id = te->id;\n            retval = te->timeProc(eventLoop, id, te->clientData);\n            processed++;\n            if (retval != AE_NOMORE) {\n                aeAddMillisecondsToNow(retval,&te->when_sec,&te->when_ms);\n            } else {\n                te->id = AE_DELETED_EVENT_ID;\n            }\n        }\n        prev = te;\n        te = te->next;\n    }\n    return processed;\n}\n\n/* Process every pending time event, then every pending file event\n * (that may be registered by time event callbacks just processed).\n * Without special flags the function sleeps until some file event\n * fires, or when the next time event occurs (if any).\n *\n * If flags is 0, the function does nothing and returns.\n * if flags has AE_ALL_EVENTS set, all the kind of events are processed.\n * if flags has AE_FILE_EVENTS set, file events are processed.\n * if flags has AE_TIME_EVENTS set, time events are processed.\n * if flags has AE_DONT_WAIT set the function returns ASAP until all\n * the events that's possible to process without to wait are processed.\n *\n * The function returns the number of events processed. */\nint aeProcessEvents(aeEventLoop *eventLoop, int flags)\n{\n    int processed = 0, numevents;\n\n    /* Nothing to do? return ASAP */\n    if (!(flags & AE_TIME_EVENTS) && !(flags & AE_FILE_EVENTS)) return 0;\n\n    /* Note that we want call select() even if there are no\n     * file events to process as long as we want to process time\n     * events, in order to sleep until the next time event is ready\n     * to fire. */\n    if (eventLoop->maxfd != -1 ||\n        ((flags & AE_TIME_EVENTS) && !(flags & AE_DONT_WAIT))) {\n        int j;\n        aeTimeEvent *shortest = NULL;\n        struct timeval tv, *tvp;\n\n        if (flags & AE_TIME_EVENTS && !(flags & AE_DONT_WAIT))\n            shortest = aeSearchNearestTimer(eventLoop);\n        if (shortest) {\n            long now_sec, now_ms;\n\n            aeGetTime(&now_sec, &now_ms);\n            tvp = &tv;\n\n            /* How many milliseconds we need to wait for the next\n             * time event to fire? */\n            long long ms =\n                (shortest->when_sec - now_sec)*1000 +\n                shortest->when_ms - now_ms;\n\n            if (ms > 0) {\n                tvp->tv_sec = ms/1000;\n                tvp->tv_usec = (ms % 1000)*1000;\n            } else {\n                tvp->tv_sec = 0;\n                tvp->tv_usec = 0;\n            }\n        } else {\n            /* If we have to check for events but need to return\n             * ASAP because of AE_DONT_WAIT we need to set the timeout\n             * to zero */\n            if (flags & AE_DONT_WAIT) {\n                tv.tv_sec = tv.tv_usec = 0;\n                tvp = &tv;\n            } else {\n                /* Otherwise we can block */\n                tvp = NULL; /* wait forever */\n            }\n        }\n\n        numevents = aeApiPoll(eventLoop, tvp);\n        for (j = 0; j < numevents; j++) {\n            aeFileEvent *fe = &eventLoop->events[eventLoop->fired[j].fd];\n            int mask = eventLoop->fired[j].mask;\n            int fd = eventLoop->fired[j].fd;\n            int rfired = 0;\n\n\t    /* note the fe->mask & mask & ... code: maybe an already processed\n             * event removed an element that fired and we still didn't\n             * processed, so we check if the event is still valid. */\n            if (fe->mask & mask & AE_READABLE) {\n                rfired = 1;\n                fe->rfileProc(eventLoop,fd,fe->clientData,mask);\n            }\n            if (fe->mask & mask & AE_WRITABLE) {\n                if (!rfired || fe->wfileProc != fe->rfileProc)\n                    fe->wfileProc(eventLoop,fd,fe->clientData,mask);\n            }\n            processed++;\n        }\n    }\n    /* Check time events */\n    if (flags & AE_TIME_EVENTS)\n        processed += processTimeEvents(eventLoop);\n\n    return processed; /* return the number of processed file/time events */\n}\n\n/* Wait for milliseconds until the given file descriptor becomes\n * writable/readable/exception */\nint aeWait(int fd, int mask, long long milliseconds) {\n    struct pollfd pfd;\n    int retmask = 0, retval;\n\n    memset(&pfd, 0, sizeof(pfd));\n    pfd.fd = fd;\n    if (mask & AE_READABLE) pfd.events |= POLLIN;\n    if (mask & AE_WRITABLE) pfd.events |= POLLOUT;\n\n    if ((retval = poll(&pfd, 1, milliseconds))== 1) {\n        if (pfd.revents & POLLIN) retmask |= AE_READABLE;\n        if (pfd.revents & POLLOUT) retmask |= AE_WRITABLE;\n\tif (pfd.revents & POLLERR) retmask |= AE_WRITABLE;\n        if (pfd.revents & POLLHUP) retmask |= AE_WRITABLE;\n        return retmask;\n    } else {\n        return retval;\n    }\n}\n\nvoid aeMain(aeEventLoop *eventLoop) {\n    eventLoop->stop = 0;\n    while (!eventLoop->stop) {\n        if (eventLoop->beforesleep != NULL)\n            eventLoop->beforesleep(eventLoop);\n        aeProcessEvents(eventLoop, AE_ALL_EVENTS);\n    }\n}\n\nchar *aeGetApiName(void) {\n    return aeApiName();\n}\n\nvoid aeSetBeforeSleepProc(aeEventLoop *eventLoop, aeBeforeSleepProc *beforesleep) {\n    eventLoop->beforesleep = beforesleep;\n}\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/src/ae.h",
    "content": "/* A simple event-driven programming library. Originally I wrote this code\n * for the Jim's event-loop (Jim is a Tcl interpreter) but later translated\n * it in form of a library for easy reuse.\n *\n * Copyright (c) 2006-2012, Salvatore Sanfilippo <antirez at gmail dot com>\n * All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions are met:\n *\n *   * Redistributions of source code must retain the above copyright notice,\n *     this list of conditions and the following disclaimer.\n *   * Redistributions in binary form must reproduce the above copyright\n *     notice, this list of conditions and the following disclaimer in the\n *     documentation and/or other materials provided with the distribution.\n *   * Neither the name of Redis nor the names of its contributors may be used\n *     to endorse or promote products derived from this software without\n *     specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\"\n * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\n * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE\n * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR\n * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF\n * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS\n * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN\n * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)\n * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE\n * POSSIBILITY OF SUCH DAMAGE.\n */\n\n#ifndef __AE_H__\n#define __AE_H__\n\n#include <time.h>\n\n#define AE_OK 0\n#define AE_ERR -1\n\n#define AE_NONE 0\n#define AE_READABLE 1\n#define AE_WRITABLE 2\n\n#define AE_FILE_EVENTS 1\n#define AE_TIME_EVENTS 2\n#define AE_ALL_EVENTS (AE_FILE_EVENTS|AE_TIME_EVENTS)\n#define AE_DONT_WAIT 4\n\n#define AE_NOMORE -1\n#define AE_DELETED_EVENT_ID -1\n\n/* Macros */\n#define AE_NOTUSED(V) ((void) V)\n\nstruct aeEventLoop;\n\n/* Types and data structures */\ntypedef void aeFileProc(struct aeEventLoop *eventLoop, int fd, void *clientData, int mask);\ntypedef int aeTimeProc(struct aeEventLoop *eventLoop, long long id, void *clientData);\ntypedef void aeEventFinalizerProc(struct aeEventLoop *eventLoop, void *clientData);\ntypedef void aeBeforeSleepProc(struct aeEventLoop *eventLoop);\n\n/* File event structure */\ntypedef struct aeFileEvent {\n    int mask; /* one of AE_(READABLE|WRITABLE) */\n    aeFileProc *rfileProc;\n    aeFileProc *wfileProc;\n    void *clientData;\n} aeFileEvent;\n\n/* Time event structure */\ntypedef struct aeTimeEvent {\n    long long id; /* time event identifier. */\n    long when_sec; /* seconds */\n    long when_ms; /* milliseconds */\n    aeTimeProc *timeProc;\n    aeEventFinalizerProc *finalizerProc;\n    void *clientData;\n    struct aeTimeEvent *next;\n} aeTimeEvent;\n\n/* A fired event */\ntypedef struct aeFiredEvent {\n    int fd;\n    int mask;\n} aeFiredEvent;\n\n/* State of an event based program */\ntypedef struct aeEventLoop {\n    int maxfd;   /* highest file descriptor currently registered */\n    int setsize; /* max number of file descriptors tracked */\n    long long timeEventNextId;\n    time_t lastTime;     /* Used to detect system clock skew */\n    aeFileEvent *events; /* Registered events */\n    aeFiredEvent *fired; /* Fired events */\n    aeTimeEvent *timeEventHead;\n    int stop;\n    void *apidata; /* This is used for polling API specific data */\n    aeBeforeSleepProc *beforesleep;\n} aeEventLoop;\n\n/* Prototypes */\naeEventLoop *aeCreateEventLoop(int setsize);\nvoid aeDeleteEventLoop(aeEventLoop *eventLoop);\nvoid aeStop(aeEventLoop *eventLoop);\nint aeCreateFileEvent(aeEventLoop *eventLoop, int fd, int mask,\n        aeFileProc *proc, void *clientData);\nvoid aeDeleteFileEvent(aeEventLoop *eventLoop, int fd, int mask);\nint aeGetFileEvents(aeEventLoop *eventLoop, int fd);\nlong long aeCreateTimeEvent(aeEventLoop *eventLoop, long long milliseconds,\n        aeTimeProc *proc, void *clientData,\n        aeEventFinalizerProc *finalizerProc);\nint aeDeleteTimeEvent(aeEventLoop *eventLoop, long long id);\nint aeProcessEvents(aeEventLoop *eventLoop, int flags);\nint aeWait(int fd, int mask, long long milliseconds);\nvoid aeMain(aeEventLoop *eventLoop);\nchar *aeGetApiName(void);\nvoid aeSetBeforeSleepProc(aeEventLoop *eventLoop, aeBeforeSleepProc *beforesleep);\nint aeGetSetSize(aeEventLoop *eventLoop);\nint aeResizeSetSize(aeEventLoop *eventLoop, int setsize);\n\n#endif\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/src/ae_epoll.c",
    "content": "/* Linux epoll(2) based ae.c module\n *\n * Copyright (c) 2009-2012, Salvatore Sanfilippo <antirez at gmail dot com>\n * All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions are met:\n *\n *   * Redistributions of source code must retain the above copyright notice,\n *     this list of conditions and the following disclaimer.\n *   * Redistributions in binary form must reproduce the above copyright\n *     notice, this list of conditions and the following disclaimer in the\n *     documentation and/or other materials provided with the distribution.\n *   * Neither the name of Redis nor the names of its contributors may be used\n *     to endorse or promote products derived from this software without\n *     specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\"\n * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\n * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE\n * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR\n * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF\n * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS\n * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN\n * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)\n * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE\n * POSSIBILITY OF SUCH DAMAGE.\n */\n\n\n#include <sys/epoll.h>\n\ntypedef struct aeApiState {\n    int epfd;\n    struct epoll_event *events;\n} aeApiState;\n\nstatic int aeApiCreate(aeEventLoop *eventLoop) {\n    aeApiState *state = zmalloc(sizeof(aeApiState));\n\n    if (!state) return -1;\n    state->events = zmalloc(sizeof(struct epoll_event)*eventLoop->setsize);\n    if (!state->events) {\n        zfree(state);\n        return -1;\n    }\n    state->epfd = epoll_create(1024); /* 1024 is just a hint for the kernel */\n    if (state->epfd == -1) {\n        zfree(state->events);\n        zfree(state);\n        return -1;\n    }\n    eventLoop->apidata = state;\n    return 0;\n}\n\nstatic int aeApiResize(aeEventLoop *eventLoop, int setsize) {\n    aeApiState *state = eventLoop->apidata;\n\n    state->events = zrealloc(state->events, sizeof(struct epoll_event)*setsize);\n    return 0;\n}\n\nstatic void aeApiFree(aeEventLoop *eventLoop) {\n    aeApiState *state = eventLoop->apidata;\n\n    close(state->epfd);\n    zfree(state->events);\n    zfree(state);\n}\n\nstatic int aeApiAddEvent(aeEventLoop *eventLoop, int fd, int mask) {\n    aeApiState *state = eventLoop->apidata;\n    struct epoll_event ee = {0}; /* avoid valgrind warning */\n    /* If the fd was already monitored for some event, we need a MOD\n     * operation. Otherwise we need an ADD operation. */\n    int op = eventLoop->events[fd].mask == AE_NONE ?\n            EPOLL_CTL_ADD : EPOLL_CTL_MOD;\n\n    ee.events = 0;\n    mask |= eventLoop->events[fd].mask; /* Merge old events */\n    if (mask & AE_READABLE) ee.events |= EPOLLIN;\n    if (mask & AE_WRITABLE) ee.events |= EPOLLOUT;\n    ee.data.fd = fd;\n    if (epoll_ctl(state->epfd,op,fd,&ee) == -1) return -1;\n    return 0;\n}\n\nstatic void aeApiDelEvent(aeEventLoop *eventLoop, int fd, int delmask) {\n    aeApiState *state = eventLoop->apidata;\n    struct epoll_event ee = {0}; /* avoid valgrind warning */\n    int mask = eventLoop->events[fd].mask & (~delmask);\n\n    ee.events = 0;\n    if (mask & AE_READABLE) ee.events |= EPOLLIN;\n    if (mask & AE_WRITABLE) ee.events |= EPOLLOUT;\n    ee.data.fd = fd;\n    if (mask != AE_NONE) {\n        epoll_ctl(state->epfd,EPOLL_CTL_MOD,fd,&ee);\n    } else {\n        /* Note, Kernel < 2.6.9 requires a non null event pointer even for\n         * EPOLL_CTL_DEL. */\n        epoll_ctl(state->epfd,EPOLL_CTL_DEL,fd,&ee);\n    }\n}\n\nstatic int aeApiPoll(aeEventLoop *eventLoop, struct timeval *tvp) {\n    aeApiState *state = eventLoop->apidata;\n    int retval, numevents = 0;\n\n    retval = epoll_wait(state->epfd,state->events,eventLoop->setsize,\n            tvp ? (tvp->tv_sec*1000 + tvp->tv_usec/1000) : -1);\n    if (retval > 0) {\n        int j;\n\n        numevents = retval;\n        for (j = 0; j < numevents; j++) {\n            int mask = 0;\n            struct epoll_event *e = state->events+j;\n\n            if (e->events & EPOLLIN) mask |= AE_READABLE;\n            if (e->events & EPOLLOUT) mask |= AE_WRITABLE;\n            if (e->events & EPOLLERR) mask |= AE_WRITABLE;\n            if (e->events & EPOLLHUP) mask |= AE_WRITABLE;\n            eventLoop->fired[j].fd = e->data.fd;\n            eventLoop->fired[j].mask = mask;\n        }\n    }\n    return numevents;\n}\n\nstatic char *aeApiName(void) {\n    return \"epoll\";\n}\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/src/ae_evport.c",
    "content": "/* ae.c module for illumos event ports.\n *\n * Copyright (c) 2012, Joyent, Inc. All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions are met:\n *\n *   * Redistributions of source code must retain the above copyright notice,\n *     this list of conditions and the following disclaimer.\n *   * Redistributions in binary form must reproduce the above copyright\n *     notice, this list of conditions and the following disclaimer in the\n *     documentation and/or other materials provided with the distribution.\n *   * Neither the name of Redis nor the names of its contributors may be used\n *     to endorse or promote products derived from this software without\n *     specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\"\n * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\n * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE\n * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR\n * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF\n * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS\n * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN\n * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)\n * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE\n * POSSIBILITY OF SUCH DAMAGE.\n */\n\n\n#include <assert.h>\n#include <errno.h>\n#include <port.h>\n#include <poll.h>\n\n#include <sys/types.h>\n#include <sys/time.h>\n\n#include <stdio.h>\n\nstatic int evport_debug = 0;\n\n/*\n * This file implements the ae API using event ports, present on Solaris-based\n * systems since Solaris 10.  Using the event port interface, we associate file\n * descriptors with the port.  Each association also includes the set of poll(2)\n * events that the consumer is interested in (e.g., POLLIN and POLLOUT).\n *\n * There's one tricky piece to this implementation: when we return events via\n * aeApiPoll, the corresponding file descriptors become dissociated from the\n * port.  This is necessary because poll events are level-triggered, so if the\n * fd didn't become dissociated, it would immediately fire another event since\n * the underlying state hasn't changed yet.  We must re-associate the file\n * descriptor, but only after we know that our caller has actually read from it.\n * The ae API does not tell us exactly when that happens, but we do know that\n * it must happen by the time aeApiPoll is called again.  Our solution is to\n * keep track of the last fds returned by aeApiPoll and re-associate them next\n * time aeApiPoll is invoked.\n *\n * To summarize, in this module, each fd association is EITHER (a) represented\n * only via the in-kernel association OR (b) represented by pending_fds and\n * pending_masks.  (b) is only true for the last fds we returned from aeApiPoll,\n * and only until we enter aeApiPoll again (at which point we restore the\n * in-kernel association).\n */\n#define MAX_EVENT_BATCHSZ 512\n\ntypedef struct aeApiState {\n    int     portfd;                             /* event port */\n    int     npending;                           /* # of pending fds */\n    int     pending_fds[MAX_EVENT_BATCHSZ];     /* pending fds */\n    int     pending_masks[MAX_EVENT_BATCHSZ];   /* pending fds' masks */\n} aeApiState;\n\nstatic int aeApiCreate(aeEventLoop *eventLoop) {\n    int i;\n    aeApiState *state = zmalloc(sizeof(aeApiState));\n    if (!state) return -1;\n\n    state->portfd = port_create();\n    if (state->portfd == -1) {\n        zfree(state);\n        return -1;\n    }\n\n    state->npending = 0;\n\n    for (i = 0; i < MAX_EVENT_BATCHSZ; i++) {\n        state->pending_fds[i] = -1;\n        state->pending_masks[i] = AE_NONE;\n    }\n\n    eventLoop->apidata = state;\n    return 0;\n}\n\nstatic int aeApiResize(aeEventLoop *eventLoop, int setsize) {\n    /* Nothing to resize here. */\n    return 0;\n}\n\nstatic void aeApiFree(aeEventLoop *eventLoop) {\n    aeApiState *state = eventLoop->apidata;\n\n    close(state->portfd);\n    zfree(state);\n}\n\nstatic int aeApiLookupPending(aeApiState *state, int fd) {\n    int i;\n\n    for (i = 0; i < state->npending; i++) {\n        if (state->pending_fds[i] == fd)\n            return (i);\n    }\n\n    return (-1);\n}\n\n/*\n * Helper function to invoke port_associate for the given fd and mask.\n */\nstatic int aeApiAssociate(const char *where, int portfd, int fd, int mask) {\n    int events = 0;\n    int rv, err;\n\n    if (mask & AE_READABLE)\n        events |= POLLIN;\n    if (mask & AE_WRITABLE)\n        events |= POLLOUT;\n\n    if (evport_debug)\n        fprintf(stderr, \"%s: port_associate(%d, 0x%x) = \", where, fd, events);\n\n    rv = port_associate(portfd, PORT_SOURCE_FD, fd, events,\n        (void *)(uintptr_t)mask);\n    err = errno;\n\n    if (evport_debug)\n        fprintf(stderr, \"%d (%s)\\n\", rv, rv == 0 ? \"no error\" : strerror(err));\n\n    if (rv == -1) {\n        fprintf(stderr, \"%s: port_associate: %s\\n\", where, strerror(err));\n\n        if (err == EAGAIN)\n            fprintf(stderr, \"aeApiAssociate: event port limit exceeded.\");\n    }\n\n    return rv;\n}\n\nstatic int aeApiAddEvent(aeEventLoop *eventLoop, int fd, int mask) {\n    aeApiState *state = eventLoop->apidata;\n    int fullmask, pfd;\n\n    if (evport_debug)\n        fprintf(stderr, \"aeApiAddEvent: fd %d mask 0x%x\\n\", fd, mask);\n\n    /*\n     * Since port_associate's \"events\" argument replaces any existing events, we\n     * must be sure to include whatever events are already associated when\n     * we call port_associate() again.\n     */\n    fullmask = mask | eventLoop->events[fd].mask;\n    pfd = aeApiLookupPending(state, fd);\n\n    if (pfd != -1) {\n        /*\n         * This fd was recently returned from aeApiPoll.  It should be safe to\n         * assume that the consumer has processed that poll event, but we play\n         * it safer by simply updating pending_mask.  The fd will be\n         * re-associated as usual when aeApiPoll is called again.\n         */\n        if (evport_debug)\n            fprintf(stderr, \"aeApiAddEvent: adding to pending fd %d\\n\", fd);\n        state->pending_masks[pfd] |= fullmask;\n        return 0;\n    }\n\n    return (aeApiAssociate(\"aeApiAddEvent\", state->portfd, fd, fullmask));\n}\n\nstatic void aeApiDelEvent(aeEventLoop *eventLoop, int fd, int mask) {\n    aeApiState *state = eventLoop->apidata;\n    int fullmask, pfd;\n\n    if (evport_debug)\n        fprintf(stderr, \"del fd %d mask 0x%x\\n\", fd, mask);\n\n    pfd = aeApiLookupPending(state, fd);\n\n    if (pfd != -1) {\n        if (evport_debug)\n            fprintf(stderr, \"deleting event from pending fd %d\\n\", fd);\n\n        /*\n         * This fd was just returned from aeApiPoll, so it's not currently\n         * associated with the port.  All we need to do is update\n         * pending_mask appropriately.\n         */\n        state->pending_masks[pfd] &= ~mask;\n\n        if (state->pending_masks[pfd] == AE_NONE)\n            state->pending_fds[pfd] = -1;\n\n        return;\n    }\n\n    /*\n     * The fd is currently associated with the port.  Like with the add case\n     * above, we must look at the full mask for the file descriptor before\n     * updating that association.  We don't have a good way of knowing what the\n     * events are without looking into the eventLoop state directly.  We rely on\n     * the fact that our caller has already updated the mask in the eventLoop.\n     */\n\n    fullmask = eventLoop->events[fd].mask;\n    if (fullmask == AE_NONE) {\n        /*\n         * We're removing *all* events, so use port_dissociate to remove the\n         * association completely.  Failure here indicates a bug.\n         */\n        if (evport_debug)\n            fprintf(stderr, \"aeApiDelEvent: port_dissociate(%d)\\n\", fd);\n\n        if (port_dissociate(state->portfd, PORT_SOURCE_FD, fd) != 0) {\n            perror(\"aeApiDelEvent: port_dissociate\");\n            abort(); /* will not return */\n        }\n    } else if (aeApiAssociate(\"aeApiDelEvent\", state->portfd, fd,\n        fullmask) != 0) {\n        /*\n         * ENOMEM is a potentially transient condition, but the kernel won't\n         * generally return it unless things are really bad.  EAGAIN indicates\n         * we've reached an resource limit, for which it doesn't make sense to\n         * retry (counter-intuitively).  All other errors indicate a bug.  In any\n         * of these cases, the best we can do is to abort.\n         */\n        abort(); /* will not return */\n    }\n}\n\nstatic int aeApiPoll(aeEventLoop *eventLoop, struct timeval *tvp) {\n    aeApiState *state = eventLoop->apidata;\n    struct timespec timeout, *tsp;\n    int mask, i;\n    uint_t nevents;\n    port_event_t event[MAX_EVENT_BATCHSZ];\n\n    /*\n     * If we've returned fd events before, we must re-associate them with the\n     * port now, before calling port_get().  See the block comment at the top of\n     * this file for an explanation of why.\n     */\n    for (i = 0; i < state->npending; i++) {\n        if (state->pending_fds[i] == -1)\n            /* This fd has since been deleted. */\n            continue;\n\n        if (aeApiAssociate(\"aeApiPoll\", state->portfd,\n            state->pending_fds[i], state->pending_masks[i]) != 0) {\n            /* See aeApiDelEvent for why this case is fatal. */\n            abort();\n        }\n\n        state->pending_masks[i] = AE_NONE;\n        state->pending_fds[i] = -1;\n    }\n\n    state->npending = 0;\n\n    if (tvp != NULL) {\n        timeout.tv_sec = tvp->tv_sec;\n        timeout.tv_nsec = tvp->tv_usec * 1000;\n        tsp = &timeout;\n    } else {\n        tsp = NULL;\n    }\n\n    /*\n     * port_getn can return with errno == ETIME having returned some events (!).\n     * So if we get ETIME, we check nevents, too.\n     */\n    nevents = 1;\n    if (port_getn(state->portfd, event, MAX_EVENT_BATCHSZ, &nevents,\n        tsp) == -1 && (errno != ETIME || nevents == 0)) {\n        if (errno == ETIME || errno == EINTR)\n            return 0;\n\n        /* Any other error indicates a bug. */\n        perror(\"aeApiPoll: port_get\");\n        abort();\n    }\n\n    state->npending = nevents;\n\n    for (i = 0; i < nevents; i++) {\n            mask = 0;\n            if (event[i].portev_events & POLLIN)\n                mask |= AE_READABLE;\n            if (event[i].portev_events & POLLOUT)\n                mask |= AE_WRITABLE;\n\n            eventLoop->fired[i].fd = event[i].portev_object;\n            eventLoop->fired[i].mask = mask;\n\n            if (evport_debug)\n                fprintf(stderr, \"aeApiPoll: fd %d mask 0x%x\\n\",\n                    (int)event[i].portev_object, mask);\n\n            state->pending_fds[i] = event[i].portev_object;\n            state->pending_masks[i] = (uintptr_t)event[i].portev_user;\n    }\n\n    return nevents;\n}\n\nstatic char *aeApiName(void) {\n    return \"evport\";\n}\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/src/ae_kqueue.c",
    "content": "/* Kqueue(2)-based ae.c module\n *\n * Copyright (C) 2009 Harish Mallipeddi - harish.mallipeddi@gmail.com\n * All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions are met:\n *\n *   * Redistributions of source code must retain the above copyright notice,\n *     this list of conditions and the following disclaimer.\n *   * Redistributions in binary form must reproduce the above copyright\n *     notice, this list of conditions and the following disclaimer in the\n *     documentation and/or other materials provided with the distribution.\n *   * Neither the name of Redis nor the names of its contributors may be used\n *     to endorse or promote products derived from this software without\n *     specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\"\n * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\n * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE\n * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR\n * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF\n * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS\n * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN\n * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)\n * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE\n * POSSIBILITY OF SUCH DAMAGE.\n */\n\n\n#include <sys/types.h>\n#include <sys/event.h>\n#include <sys/time.h>\n\ntypedef struct aeApiState {\n    int kqfd;\n    struct kevent *events;\n} aeApiState;\n\nstatic int aeApiCreate(aeEventLoop *eventLoop) {\n    aeApiState *state = zmalloc(sizeof(aeApiState));\n\n    if (!state) return -1;\n    state->events = zmalloc(sizeof(struct kevent)*eventLoop->setsize);\n    if (!state->events) {\n        zfree(state);\n        return -1;\n    }\n    state->kqfd = kqueue();\n    if (state->kqfd == -1) {\n        zfree(state->events);\n        zfree(state);\n        return -1;\n    }\n    eventLoop->apidata = state;\n    return 0;\n}\n\nstatic int aeApiResize(aeEventLoop *eventLoop, int setsize) {\n    aeApiState *state = eventLoop->apidata;\n\n    state->events = zrealloc(state->events, sizeof(struct kevent)*setsize);\n    return 0;\n}\n\nstatic void aeApiFree(aeEventLoop *eventLoop) {\n    aeApiState *state = eventLoop->apidata;\n\n    close(state->kqfd);\n    zfree(state->events);\n    zfree(state);\n}\n\nstatic int aeApiAddEvent(aeEventLoop *eventLoop, int fd, int mask) {\n    aeApiState *state = eventLoop->apidata;\n    struct kevent ke;\n\n    if (mask & AE_READABLE) {\n        EV_SET(&ke, fd, EVFILT_READ, EV_ADD, 0, 0, NULL);\n        if (kevent(state->kqfd, &ke, 1, NULL, 0, NULL) == -1) return -1;\n    }\n    if (mask & AE_WRITABLE) {\n        EV_SET(&ke, fd, EVFILT_WRITE, EV_ADD, 0, 0, NULL);\n        if (kevent(state->kqfd, &ke, 1, NULL, 0, NULL) == -1) return -1;\n    }\n    return 0;\n}\n\nstatic void aeApiDelEvent(aeEventLoop *eventLoop, int fd, int mask) {\n    aeApiState *state = eventLoop->apidata;\n    struct kevent ke;\n\n    if (mask & AE_READABLE) {\n        EV_SET(&ke, fd, EVFILT_READ, EV_DELETE, 0, 0, NULL);\n        kevent(state->kqfd, &ke, 1, NULL, 0, NULL);\n    }\n    if (mask & AE_WRITABLE) {\n        EV_SET(&ke, fd, EVFILT_WRITE, EV_DELETE, 0, 0, NULL);\n        kevent(state->kqfd, &ke, 1, NULL, 0, NULL);\n    }\n}\n\nstatic int aeApiPoll(aeEventLoop *eventLoop, struct timeval *tvp) {\n    aeApiState *state = eventLoop->apidata;\n    int retval, numevents = 0;\n\n    if (tvp != NULL) {\n        struct timespec timeout;\n        timeout.tv_sec = tvp->tv_sec;\n        timeout.tv_nsec = tvp->tv_usec * 1000;\n        retval = kevent(state->kqfd, NULL, 0, state->events, eventLoop->setsize,\n                        &timeout);\n    } else {\n        retval = kevent(state->kqfd, NULL, 0, state->events, eventLoop->setsize,\n                        NULL);\n    }\n\n    if (retval > 0) {\n        int j;\n\n        numevents = retval;\n        for(j = 0; j < numevents; j++) {\n            int mask = 0;\n            struct kevent *e = state->events+j;\n\n            if (e->filter == EVFILT_READ) mask |= AE_READABLE;\n            if (e->filter == EVFILT_WRITE) mask |= AE_WRITABLE;\n            eventLoop->fired[j].fd = e->ident;\n            eventLoop->fired[j].mask = mask;\n        }\n    }\n    return numevents;\n}\n\nstatic char *aeApiName(void) {\n    return \"kqueue\";\n}\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/src/ae_select.c",
    "content": "/* Select()-based ae.c module.\n *\n * Copyright (c) 2009-2012, Salvatore Sanfilippo <antirez at gmail dot com>\n * All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions are met:\n *\n *   * Redistributions of source code must retain the above copyright notice,\n *     this list of conditions and the following disclaimer.\n *   * Redistributions in binary form must reproduce the above copyright\n *     notice, this list of conditions and the following disclaimer in the\n *     documentation and/or other materials provided with the distribution.\n *   * Neither the name of Redis nor the names of its contributors may be used\n *     to endorse or promote products derived from this software without\n *     specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\"\n * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\n * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE\n * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR\n * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF\n * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS\n * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN\n * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)\n * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE\n * POSSIBILITY OF SUCH DAMAGE.\n */\n\n\n#include <sys/select.h>\n#include <string.h>\n\ntypedef struct aeApiState {\n    fd_set rfds, wfds;\n    /* We need to have a copy of the fd sets as it's not safe to reuse\n     * FD sets after select(). */\n    fd_set _rfds, _wfds;\n} aeApiState;\n\nstatic int aeApiCreate(aeEventLoop *eventLoop) {\n    aeApiState *state = zmalloc(sizeof(aeApiState));\n\n    if (!state) return -1;\n    FD_ZERO(&state->rfds);\n    FD_ZERO(&state->wfds);\n    eventLoop->apidata = state;\n    return 0;\n}\n\nstatic int aeApiResize(aeEventLoop *eventLoop, int setsize) {\n    /* Just ensure we have enough room in the fd_set type. */\n    if (setsize >= FD_SETSIZE) return -1;\n    return 0;\n}\n\nstatic void aeApiFree(aeEventLoop *eventLoop) {\n    zfree(eventLoop->apidata);\n}\n\nstatic int aeApiAddEvent(aeEventLoop *eventLoop, int fd, int mask) {\n    aeApiState *state = eventLoop->apidata;\n\n    if (mask & AE_READABLE) FD_SET(fd,&state->rfds);\n    if (mask & AE_WRITABLE) FD_SET(fd,&state->wfds);\n    return 0;\n}\n\nstatic void aeApiDelEvent(aeEventLoop *eventLoop, int fd, int mask) {\n    aeApiState *state = eventLoop->apidata;\n\n    if (mask & AE_READABLE) FD_CLR(fd,&state->rfds);\n    if (mask & AE_WRITABLE) FD_CLR(fd,&state->wfds);\n}\n\nstatic int aeApiPoll(aeEventLoop *eventLoop, struct timeval *tvp) {\n    aeApiState *state = eventLoop->apidata;\n    int retval, j, numevents = 0;\n\n    memcpy(&state->_rfds,&state->rfds,sizeof(fd_set));\n    memcpy(&state->_wfds,&state->wfds,sizeof(fd_set));\n\n    retval = select(eventLoop->maxfd+1,\n                &state->_rfds,&state->_wfds,NULL,tvp);\n    if (retval > 0) {\n        for (j = 0; j <= eventLoop->maxfd; j++) {\n            int mask = 0;\n            aeFileEvent *fe = &eventLoop->events[j];\n\n            if (fe->mask == AE_NONE) continue;\n            if (fe->mask & AE_READABLE && FD_ISSET(j,&state->_rfds))\n                mask |= AE_READABLE;\n            if (fe->mask & AE_WRITABLE && FD_ISSET(j,&state->_wfds))\n                mask |= AE_WRITABLE;\n            eventLoop->fired[numevents].fd = j;\n            eventLoop->fired[numevents].mask = mask;\n            numevents++;\n        }\n    }\n    return numevents;\n}\n\nstatic char *aeApiName(void) {\n    return \"select\";\n}\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/src/anet.c",
    "content": "/* anet.c -- Basic TCP socket stuff made a bit less boring\n *\n * Copyright (c) 2006-2012, Salvatore Sanfilippo <antirez at gmail dot com>\n * All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions are met:\n *\n *   * Redistributions of source code must retain the above copyright notice,\n *     this list of conditions and the following disclaimer.\n *   * Redistributions in binary form must reproduce the above copyright\n *     notice, this list of conditions and the following disclaimer in the\n *     documentation and/or other materials provided with the distribution.\n *   * Neither the name of Redis nor the names of its contributors may be used\n *     to endorse or promote products derived from this software without\n *     specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\"\n * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\n * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE\n * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR\n * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF\n * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS\n * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN\n * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)\n * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE\n * POSSIBILITY OF SUCH DAMAGE.\n */\n\n#include \"fmacros.h\"\n\n#include <sys/types.h>\n#include <sys/socket.h>\n#include <sys/stat.h>\n#include <sys/un.h>\n#include <sys/time.h>\n#include <netinet/in.h>\n#include <netinet/tcp.h>\n#include <arpa/inet.h>\n#include <unistd.h>\n#include <fcntl.h>\n#include <string.h>\n#include <netdb.h>\n#include <errno.h>\n#include <stdarg.h>\n#include <stdio.h>\n\n#include \"anet.h\"\n\nstatic void anetSetError(char *err, const char *fmt, ...)\n{\n    va_list ap;\n\n    if (!err) return;\n    va_start(ap, fmt);\n    vsnprintf(err, ANET_ERR_LEN, fmt, ap);\n    va_end(ap);\n}\n\nint anetSetBlock(char *err, int fd, int non_block) {\n    int flags;\n\n    /* Set the socket blocking (if non_block is zero) or non-blocking.\n     * Note that fcntl(2) for F_GETFL and F_SETFL can't be\n     * interrupted by a signal. */\n    if ((flags = fcntl(fd, F_GETFL)) == -1) {\n        anetSetError(err, \"fcntl(F_GETFL): %s\", strerror(errno));\n        return ANET_ERR;\n    }\n\n    if (non_block)\n        flags |= O_NONBLOCK;\n    else\n        flags &= ~O_NONBLOCK;\n\n    if (fcntl(fd, F_SETFL, flags) == -1) {\n        anetSetError(err, \"fcntl(F_SETFL,O_NONBLOCK): %s\", strerror(errno));\n        return ANET_ERR;\n    }\n    return ANET_OK;\n}\n\nint anetNonBlock(char *err, int fd) {\n    return anetSetBlock(err,fd,1);\n}\n\nint anetBlock(char *err, int fd) {\n    return anetSetBlock(err,fd,0);\n}\n\n/* Set TCP keep alive option to detect dead peers. The interval option\n * is only used for Linux as we are using Linux-specific APIs to set\n * the probe send time, interval, and count. */\nint anetKeepAlive(char *err, int fd, int interval)\n{\n    int val = 1;\n\n    if (setsockopt(fd, SOL_SOCKET, SO_KEEPALIVE, &val, sizeof(val)) == -1)\n    {\n        anetSetError(err, \"setsockopt SO_KEEPALIVE: %s\", strerror(errno));\n        return ANET_ERR;\n    }\n\n#ifdef __linux__\n    /* Default settings are more or less garbage, with the keepalive time\n     * set to 7200 by default on Linux. Modify settings to make the feature\n     * actually useful. */\n\n    /* Send first probe after interval. */\n    val = interval;\n    if (setsockopt(fd, IPPROTO_TCP, TCP_KEEPIDLE, &val, sizeof(val)) < 0) {\n        anetSetError(err, \"setsockopt TCP_KEEPIDLE: %s\\n\", strerror(errno));\n        return ANET_ERR;\n    }\n\n    /* Send next probes after the specified interval. Note that we set the\n     * delay as interval / 3, as we send three probes before detecting\n     * an error (see the next setsockopt call). */\n    val = interval/3;\n    if (val == 0) val = 1;\n    if (setsockopt(fd, IPPROTO_TCP, TCP_KEEPINTVL, &val, sizeof(val)) < 0) {\n        anetSetError(err, \"setsockopt TCP_KEEPINTVL: %s\\n\", strerror(errno));\n        return ANET_ERR;\n    }\n\n    /* Consider the socket in error state after three we send three ACK\n     * probes without getting a reply. */\n    val = 3;\n    if (setsockopt(fd, IPPROTO_TCP, TCP_KEEPCNT, &val, sizeof(val)) < 0) {\n        anetSetError(err, \"setsockopt TCP_KEEPCNT: %s\\n\", strerror(errno));\n        return ANET_ERR;\n    }\n#else\n    ((void) interval); /* Avoid unused var warning for non Linux systems. */\n#endif\n\n    return ANET_OK;\n}\n\nstatic int anetSetTcpNoDelay(char *err, int fd, int val)\n{\n    if (setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, &val, sizeof(val)) == -1)\n    {\n        anetSetError(err, \"setsockopt TCP_NODELAY: %s\", strerror(errno));\n        return ANET_ERR;\n    }\n    return ANET_OK;\n}\n\nint anetEnableTcpNoDelay(char *err, int fd)\n{\n    return anetSetTcpNoDelay(err, fd, 1);\n}\n\nint anetDisableTcpNoDelay(char *err, int fd)\n{\n    return anetSetTcpNoDelay(err, fd, 0);\n}\n\n\nint anetSetSendBuffer(char *err, int fd, int buffsize)\n{\n    if (setsockopt(fd, SOL_SOCKET, SO_SNDBUF, &buffsize, sizeof(buffsize)) == -1)\n    {\n        anetSetError(err, \"setsockopt SO_SNDBUF: %s\", strerror(errno));\n        return ANET_ERR;\n    }\n    return ANET_OK;\n}\n\nint anetTcpKeepAlive(char *err, int fd)\n{\n    int yes = 1;\n    if (setsockopt(fd, SOL_SOCKET, SO_KEEPALIVE, &yes, sizeof(yes)) == -1) {\n        anetSetError(err, \"setsockopt SO_KEEPALIVE: %s\", strerror(errno));\n        return ANET_ERR;\n    }\n    return ANET_OK;\n}\n\n/* Set the socket send timeout (SO_SNDTIMEO socket option) to the specified\n * number of milliseconds, or disable it if the 'ms' argument is zero. */\nint anetSendTimeout(char *err, int fd, long long ms) {\n    struct timeval tv;\n\n    tv.tv_sec = ms/1000;\n    tv.tv_usec = (ms%1000)*1000;\n    if (setsockopt(fd, SOL_SOCKET, SO_SNDTIMEO, &tv, sizeof(tv)) == -1) {\n        anetSetError(err, \"setsockopt SO_SNDTIMEO: %s\", strerror(errno));\n        return ANET_ERR;\n    }\n    return ANET_OK;\n}\n\n/* anetGenericResolve() is called by anetResolve() and anetResolveIP() to\n * do the actual work. It resolves the hostname \"host\" and set the string\n * representation of the IP address into the buffer pointed by \"ipbuf\".\n *\n * If flags is set to ANET_IP_ONLY the function only resolves hostnames\n * that are actually already IPv4 or IPv6 addresses. This turns the function\n * into a validating / normalizing function. */\nint anetGenericResolve(char *err, char *host, char *ipbuf, size_t ipbuf_len,\n                       int flags)\n{\n    struct addrinfo hints, *info;\n    int rv;\n\n    memset(&hints,0,sizeof(hints));\n    if (flags & ANET_IP_ONLY) hints.ai_flags = AI_NUMERICHOST;\n    hints.ai_family = AF_UNSPEC;\n    hints.ai_socktype = SOCK_STREAM;  /* specify socktype to avoid dups */\n\n    if ((rv = getaddrinfo(host, NULL, &hints, &info)) != 0) {\n        anetSetError(err, \"%s\", gai_strerror(rv));\n        return ANET_ERR;\n    }\n    if (info->ai_family == AF_INET) {\n        struct sockaddr_in *sa = (struct sockaddr_in *)info->ai_addr;\n        inet_ntop(AF_INET, &(sa->sin_addr), ipbuf, ipbuf_len);\n    } else {\n        struct sockaddr_in6 *sa = (struct sockaddr_in6 *)info->ai_addr;\n        inet_ntop(AF_INET6, &(sa->sin6_addr), ipbuf, ipbuf_len);\n    }\n\n    freeaddrinfo(info);\n    return ANET_OK;\n}\n\nint anetResolve(char *err, char *host, char *ipbuf, size_t ipbuf_len) {\n    return anetGenericResolve(err,host,ipbuf,ipbuf_len,ANET_NONE);\n}\n\nint anetResolveIP(char *err, char *host, char *ipbuf, size_t ipbuf_len) {\n    return anetGenericResolve(err,host,ipbuf,ipbuf_len,ANET_IP_ONLY);\n}\n\nstatic int anetSetReuseAddr(char *err, int fd) {\n    int yes = 1;\n    /* Make sure connection-intensive things like the redis benckmark\n     * will be able to close/open sockets a zillion of times */\n    if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(yes)) == -1) {\n        anetSetError(err, \"setsockopt SO_REUSEADDR: %s\", strerror(errno));\n        return ANET_ERR;\n    }\n    return ANET_OK;\n}\n\nstatic int anetCreateSocket(char *err, int domain) {\n    int s;\n    if ((s = socket(domain, SOCK_STREAM, 0)) == -1) {\n        anetSetError(err, \"creating socket: %s\", strerror(errno));\n        return ANET_ERR;\n    }\n\n    /* Make sure connection-intensive things like the redis benchmark\n     * will be able to close/open sockets a zillion of times */\n    if (anetSetReuseAddr(err,s) == ANET_ERR) {\n        close(s);\n        return ANET_ERR;\n    }\n    return s;\n}\n\n#define ANET_CONNECT_NONE 0\n#define ANET_CONNECT_NONBLOCK 1\n#define ANET_CONNECT_BE_BINDING 2 /* Best effort binding. */\nstatic int anetTcpGenericConnect(char *err, char *addr, int port,\n                                 char *source_addr, int flags)\n{\n    int s = ANET_ERR, rv;\n    char portstr[6];  /* strlen(\"65535\") + 1; */\n    struct addrinfo hints, *servinfo, *bservinfo, *p, *b;\n\n    snprintf(portstr,sizeof(portstr),\"%d\",port);\n    memset(&hints,0,sizeof(hints));\n    hints.ai_family = AF_UNSPEC;\n    hints.ai_socktype = SOCK_STREAM;\n\n    if ((rv = getaddrinfo(addr,portstr,&hints,&servinfo)) != 0) {\n        anetSetError(err, \"%s\", gai_strerror(rv));\n        return ANET_ERR;\n    }\n    for (p = servinfo; p != NULL; p = p->ai_next) {\n        /* Try to create the socket and to connect it.\n         * If we fail in the socket() call, or on connect(), we retry with\n         * the next entry in servinfo. */\n        if ((s = socket(p->ai_family,p->ai_socktype,p->ai_protocol)) == -1)\n            continue;\n        if (anetSetReuseAddr(err,s) == ANET_ERR) goto error;\n        if (flags & ANET_CONNECT_NONBLOCK && anetNonBlock(err,s) != ANET_OK)\n            goto error;\n        if (source_addr) {\n            int bound = 0;\n            /* Using getaddrinfo saves us from self-determining IPv4 vs IPv6 */\n            if ((rv = getaddrinfo(source_addr, NULL, &hints, &bservinfo)) != 0)\n            {\n                anetSetError(err, \"%s\", gai_strerror(rv));\n                goto error;\n            }\n            for (b = bservinfo; b != NULL; b = b->ai_next) {\n                if (bind(s,b->ai_addr,b->ai_addrlen) != -1) {\n                    bound = 1;\n                    break;\n                }\n            }\n            freeaddrinfo(bservinfo);\n            if (!bound) {\n                anetSetError(err, \"bind: %s\", strerror(errno));\n                goto error;\n            }\n        }\n        if (connect(s,p->ai_addr,p->ai_addrlen) == -1) {\n            /* If the socket is non-blocking, it is ok for connect() to\n             * return an EINPROGRESS error here. */\n            if (errno == EINPROGRESS && flags & ANET_CONNECT_NONBLOCK)\n                goto end;\n            close(s);\n            s = ANET_ERR;\n            continue;\n        }\n\n        /* If we ended an iteration of the for loop without errors, we\n         * have a connected socket. Let's return to the caller. */\n        goto end;\n    }\n    if (p == NULL)\n        anetSetError(err, \"creating socket: %s\", strerror(errno));\n\nerror:\n    if (s != ANET_ERR) {\n        close(s);\n        s = ANET_ERR;\n    }\n\nend:\n    freeaddrinfo(servinfo);\n\n    /* Handle best effort binding: if a binding address was used, but it is\n     * not possible to create a socket, try again without a binding address. */\n    if (s == ANET_ERR && source_addr && (flags & ANET_CONNECT_BE_BINDING)) {\n        return anetTcpGenericConnect(err,addr,port,NULL,flags);\n    } else {\n        return s;\n    }\n}\n\nint anetTcpConnect(char *err, char *addr, int port)\n{\n    return anetTcpGenericConnect(err,addr,port,NULL,ANET_CONNECT_NONE);\n}\n\nint anetTcpNonBlockConnect(char *err, char *addr, int port)\n{\n    return anetTcpGenericConnect(err,addr,port,NULL,ANET_CONNECT_NONBLOCK);\n}\n\nint anetTcpNonBlockBindConnect(char *err, char *addr, int port,\n                               char *source_addr)\n{\n    return anetTcpGenericConnect(err,addr,port,source_addr,\n            ANET_CONNECT_NONBLOCK);\n}\n\nint anetTcpNonBlockBestEffortBindConnect(char *err, char *addr, int port,\n                                         char *source_addr)\n{\n    return anetTcpGenericConnect(err,addr,port,source_addr,\n            ANET_CONNECT_NONBLOCK|ANET_CONNECT_BE_BINDING);\n}\n\nint anetUnixGenericConnect(char *err, char *path, int flags)\n{\n    int s;\n    struct sockaddr_un sa;\n\n    if ((s = anetCreateSocket(err,AF_LOCAL)) == ANET_ERR)\n        return ANET_ERR;\n\n    sa.sun_family = AF_LOCAL;\n    strncpy(sa.sun_path,path,sizeof(sa.sun_path)-1);\n    if (flags & ANET_CONNECT_NONBLOCK) {\n        if (anetNonBlock(err,s) != ANET_OK)\n            return ANET_ERR;\n    }\n    if (connect(s,(struct sockaddr*)&sa,sizeof(sa)) == -1) {\n        if (errno == EINPROGRESS &&\n            flags & ANET_CONNECT_NONBLOCK)\n            return s;\n\n        anetSetError(err, \"connect: %s\", strerror(errno));\n        close(s);\n        return ANET_ERR;\n    }\n    return s;\n}\n\nint anetUnixConnect(char *err, char *path)\n{\n    return anetUnixGenericConnect(err,path,ANET_CONNECT_NONE);\n}\n\nint anetUnixNonBlockConnect(char *err, char *path)\n{\n    return anetUnixGenericConnect(err,path,ANET_CONNECT_NONBLOCK);\n}\n\n/* Like read(2) but make sure 'count' is read before to return\n * (unless error or EOF condition is encountered) */\nint anetRead(int fd, char *buf, int count)\n{\n    ssize_t nread, totlen = 0;\n    while(totlen != count) {\n        nread = read(fd,buf,count-totlen);\n        if (nread == 0) return totlen;\n        if (nread == -1) return -1;\n        totlen += nread;\n        buf += nread;\n    }\n    return totlen;\n}\n\n/* Like write(2) but make sure 'count' is written before to return\n * (unless error is encountered) */\nint anetWrite(int fd, char *buf, int count)\n{\n    ssize_t nwritten, totlen = 0;\n    while(totlen != count) {\n        nwritten = write(fd,buf,count-totlen);\n        if (nwritten == 0) return totlen;\n        if (nwritten == -1) return -1;\n        totlen += nwritten;\n        buf += nwritten;\n    }\n    return totlen;\n}\n\nstatic int anetListen(char *err, int s, struct sockaddr *sa, socklen_t len, int backlog) {\n    if (bind(s,sa,len) == -1) {\n        anetSetError(err, \"bind: %s\", strerror(errno));\n        close(s);\n        return ANET_ERR;\n    }\n\n    if (listen(s, backlog) == -1) {\n        anetSetError(err, \"listen: %s\", strerror(errno));\n        close(s);\n        return ANET_ERR;\n    }\n    return ANET_OK;\n}\n\nstatic int anetV6Only(char *err, int s) {\n    int yes = 1;\n    if (setsockopt(s,IPPROTO_IPV6,IPV6_V6ONLY,&yes,sizeof(yes)) == -1) {\n        anetSetError(err, \"setsockopt: %s\", strerror(errno));\n        close(s);\n        return ANET_ERR;\n    }\n    return ANET_OK;\n}\n\nstatic int _anetTcpServer(char *err, int port, char *bindaddr, int af, int backlog)\n{\n    int s, rv;\n    char _port[6];  /* strlen(\"65535\") */\n    struct addrinfo hints, *servinfo, *p;\n\n    snprintf(_port,6,\"%d\",port);\n    memset(&hints,0,sizeof(hints));\n    hints.ai_family = af;\n    hints.ai_socktype = SOCK_STREAM;\n    hints.ai_flags = AI_PASSIVE;    /* No effect if bindaddr != NULL */\n\n    if ((rv = getaddrinfo(bindaddr,_port,&hints,&servinfo)) != 0) {\n        anetSetError(err, \"%s\", gai_strerror(rv));\n        return ANET_ERR;\n    }\n    for (p = servinfo; p != NULL; p = p->ai_next) {\n        if ((s = socket(p->ai_family,p->ai_socktype,p->ai_protocol)) == -1)\n            continue;\n\n        if (af == AF_INET6 && anetV6Only(err,s) == ANET_ERR) goto error;\n        if (anetSetReuseAddr(err,s) == ANET_ERR) goto error;\n        if (anetListen(err,s,p->ai_addr,p->ai_addrlen,backlog) == ANET_ERR) goto error;\n        goto end;\n    }\n    if (p == NULL) {\n        anetSetError(err, \"unable to bind socket, errno: %d\", errno);\n        goto error;\n    }\n\nerror:\n    s = ANET_ERR;\nend:\n    freeaddrinfo(servinfo);\n    return s;\n}\n\nint anetTcpServer(char *err, int port, char *bindaddr, int backlog)\n{\n    return _anetTcpServer(err, port, bindaddr, AF_INET, backlog);\n}\n\nint anetTcp6Server(char *err, int port, char *bindaddr, int backlog)\n{\n    return _anetTcpServer(err, port, bindaddr, AF_INET6, backlog);\n}\n\nint anetUnixServer(char *err, char *path, mode_t perm, int backlog)\n{\n    int s;\n    struct sockaddr_un sa;\n\n    if ((s = anetCreateSocket(err,AF_LOCAL)) == ANET_ERR)\n        return ANET_ERR;\n\n    memset(&sa,0,sizeof(sa));\n    sa.sun_family = AF_LOCAL;\n    strncpy(sa.sun_path,path,sizeof(sa.sun_path)-1);\n    if (anetListen(err,s,(struct sockaddr*)&sa,sizeof(sa),backlog) == ANET_ERR)\n        return ANET_ERR;\n    if (perm)\n        chmod(sa.sun_path, perm);\n    return s;\n}\n\nstatic int anetGenericAccept(char *err, int s, struct sockaddr *sa, socklen_t *len) {\n    int fd;\n    while(1) {\n        fd = accept(s,sa,len);\n        if (fd == -1) {\n            if (errno == EINTR)\n                continue;\n            else {\n                anetSetError(err, \"accept: %s\", strerror(errno));\n                return ANET_ERR;\n            }\n        }\n        break;\n    }\n    return fd;\n}\n\nint anetTcpAccept(char *err, int s, char *ip, size_t ip_len, int *port) {\n    int fd;\n    struct sockaddr_storage sa;\n    socklen_t salen = sizeof(sa);\n    if ((fd = anetGenericAccept(err,s,(struct sockaddr*)&sa,&salen)) == -1)\n        return ANET_ERR;\n\n    if (sa.ss_family == AF_INET) {\n        struct sockaddr_in *s = (struct sockaddr_in *)&sa;\n        if (ip) inet_ntop(AF_INET,(void*)&(s->sin_addr),ip,ip_len);\n        if (port) *port = ntohs(s->sin_port);\n    } else {\n        struct sockaddr_in6 *s = (struct sockaddr_in6 *)&sa;\n        if (ip) inet_ntop(AF_INET6,(void*)&(s->sin6_addr),ip,ip_len);\n        if (port) *port = ntohs(s->sin6_port);\n    }\n    return fd;\n}\n\nint anetUnixAccept(char *err, int s) {\n    int fd;\n    struct sockaddr_un sa;\n    socklen_t salen = sizeof(sa);\n    if ((fd = anetGenericAccept(err,s,(struct sockaddr*)&sa,&salen)) == -1)\n        return ANET_ERR;\n\n    return fd;\n}\n\nint anetPeerToString(int fd, char *ip, size_t ip_len, int *port) {\n    struct sockaddr_storage sa;\n    socklen_t salen = sizeof(sa);\n\n    if (getpeername(fd,(struct sockaddr*)&sa,&salen) == -1) goto error;\n    if (ip_len == 0) goto error;\n\n    if (sa.ss_family == AF_INET) {\n        struct sockaddr_in *s = (struct sockaddr_in *)&sa;\n        if (ip) inet_ntop(AF_INET,(void*)&(s->sin_addr),ip,ip_len);\n        if (port) *port = ntohs(s->sin_port);\n    } else if (sa.ss_family == AF_INET6) {\n        struct sockaddr_in6 *s = (struct sockaddr_in6 *)&sa;\n        if (ip) inet_ntop(AF_INET6,(void*)&(s->sin6_addr),ip,ip_len);\n        if (port) *port = ntohs(s->sin6_port);\n    } else if (sa.ss_family == AF_UNIX) {\n        if (ip) strncpy(ip,\"/unixsocket\",ip_len);\n        if (port) *port = 0;\n    } else {\n        goto error;\n    }\n    return 0;\n\nerror:\n    if (ip) {\n        if (ip_len >= 2) {\n            ip[0] = '?';\n            ip[1] = '\\0';\n        } else if (ip_len == 1) {\n            ip[0] = '\\0';\n        }\n    }\n    if (port) *port = 0;\n    return -1;\n}\n\n/* Format an IP,port pair into something easy to parse. If IP is IPv6\n * (matches for \":\"), the ip is surrounded by []. IP and port are just\n * separated by colons. This the standard to display addresses within Redis. */\nint anetFormatAddr(char *buf, size_t buf_len, char *ip, int port) {\n    return snprintf(buf,buf_len, strchr(ip,':') ?\n           \"[%s]:%d\" : \"%s:%d\", ip, port);\n}\n\n/* Like anetFormatAddr() but extract ip and port from the socket's peer. */\nint anetFormatPeer(int fd, char *buf, size_t buf_len) {\n    char ip[INET6_ADDRSTRLEN];\n    int port;\n\n    anetPeerToString(fd,ip,sizeof(ip),&port);\n    return anetFormatAddr(buf, buf_len, ip, port);\n}\n\nint anetSockName(int fd, char *ip, size_t ip_len, int *port) {\n    struct sockaddr_storage sa;\n    socklen_t salen = sizeof(sa);\n\n    if (getsockname(fd,(struct sockaddr*)&sa,&salen) == -1) {\n        if (port) *port = 0;\n        ip[0] = '?';\n        ip[1] = '\\0';\n        return -1;\n    }\n    if (sa.ss_family == AF_INET) {\n        struct sockaddr_in *s = (struct sockaddr_in *)&sa;\n        if (ip) inet_ntop(AF_INET,(void*)&(s->sin_addr),ip,ip_len);\n        if (port) *port = ntohs(s->sin_port);\n    } else {\n        struct sockaddr_in6 *s = (struct sockaddr_in6 *)&sa;\n        if (ip) inet_ntop(AF_INET6,(void*)&(s->sin6_addr),ip,ip_len);\n        if (port) *port = ntohs(s->sin6_port);\n    }\n    return 0;\n}\n\nint anetFormatSock(int fd, char *fmt, size_t fmt_len) {\n    char ip[INET6_ADDRSTRLEN];\n    int port;\n\n    anetSockName(fd,ip,sizeof(ip),&port);\n    return anetFormatAddr(fmt, fmt_len, ip, port);\n}\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/src/anet.h",
    "content": "/* anet.c -- Basic TCP socket stuff made a bit less boring\n *\n * Copyright (c) 2006-2012, Salvatore Sanfilippo <antirez at gmail dot com>\n * All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions are met:\n *\n *   * Redistributions of source code must retain the above copyright notice,\n *     this list of conditions and the following disclaimer.\n *   * Redistributions in binary form must reproduce the above copyright\n *     notice, this list of conditions and the following disclaimer in the\n *     documentation and/or other materials provided with the distribution.\n *   * Neither the name of Redis nor the names of its contributors may be used\n *     to endorse or promote products derived from this software without\n *     specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\"\n * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\n * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE\n * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR\n * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF\n * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS\n * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN\n * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)\n * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE\n * POSSIBILITY OF SUCH DAMAGE.\n */\n\n#ifndef ANET_H\n#define ANET_H\n\n#include <sys/types.h>\n\n#define ANET_OK 0\n#define ANET_ERR -1\n#define ANET_ERR_LEN 256\n\n/* Flags used with certain functions. */\n#define ANET_NONE 0\n#define ANET_IP_ONLY (1<<0)\n\n#if defined(__sun) || defined(_AIX)\n#define AF_LOCAL AF_UNIX\n#endif\n\n#ifdef _AIX\n#undef ip_len\n#endif\n\nint anetTcpConnect(char *err, char *addr, int port);\nint anetTcpNonBlockConnect(char *err, char *addr, int port);\nint anetTcpNonBlockBindConnect(char *err, char *addr, int port, char *source_addr);\nint anetTcpNonBlockBestEffortBindConnect(char *err, char *addr, int port, char *source_addr);\nint anetUnixConnect(char *err, char *path);\nint anetUnixNonBlockConnect(char *err, char *path);\nint anetRead(int fd, char *buf, int count);\nint anetResolve(char *err, char *host, char *ipbuf, size_t ipbuf_len);\nint anetResolveIP(char *err, char *host, char *ipbuf, size_t ipbuf_len);\nint anetTcpServer(char *err, int port, char *bindaddr, int backlog);\nint anetTcp6Server(char *err, int port, char *bindaddr, int backlog);\nint anetUnixServer(char *err, char *path, mode_t perm, int backlog);\nint anetTcpAccept(char *err, int serversock, char *ip, size_t ip_len, int *port);\nint anetUnixAccept(char *err, int serversock);\nint anetWrite(int fd, char *buf, int count);\nint anetNonBlock(char *err, int fd);\nint anetBlock(char *err, int fd);\nint anetEnableTcpNoDelay(char *err, int fd);\nint anetDisableTcpNoDelay(char *err, int fd);\nint anetTcpKeepAlive(char *err, int fd);\nint anetSendTimeout(char *err, int fd, long long ms);\nint anetPeerToString(int fd, char *ip, size_t ip_len, int *port);\nint anetKeepAlive(char *err, int fd, int interval);\nint anetSockName(int fd, char *ip, size_t ip_len, int *port);\nint anetFormatAddr(char *fmt, size_t fmt_len, char *ip, int port);\nint anetFormatPeer(int fd, char *fmt, size_t fmt_len);\nint anetFormatSock(int fd, char *fmt, size_t fmt_len);\n\n#endif\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/src/aof.c",
    "content": "/*\n * Copyright (c) 2009-2012, Salvatore Sanfilippo <antirez at gmail dot com>\n * All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions are met:\n *\n *   * Redistributions of source code must retain the above copyright notice,\n *     this list of conditions and the following disclaimer.\n *   * Redistributions in binary form must reproduce the above copyright\n *     notice, this list of conditions and the following disclaimer in the\n *     documentation and/or other materials provided with the distribution.\n *   * Neither the name of Redis nor the names of its contributors may be used\n *     to endorse or promote products derived from this software without\n *     specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\"\n * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\n * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE\n * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR\n * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF\n * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS\n * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN\n * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)\n * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE\n * POSSIBILITY OF SUCH DAMAGE.\n */\n\n#include \"server.h\"\n#include \"bio.h\"\n#include \"rio.h\"\n\n#include <signal.h>\n#include <fcntl.h>\n#include <sys/stat.h>\n#include <sys/types.h>\n#include <sys/time.h>\n#include <sys/resource.h>\n#include <sys/wait.h>\n#include <sys/param.h>\n\nvoid aofUpdateCurrentSize(void);\nvoid aofClosePipes(void);\n\n/* ----------------------------------------------------------------------------\n * AOF rewrite buffer implementation.\n *\n * The following code implement a simple buffer used in order to accumulate\n * changes while the background process is rewriting the AOF file.\n *\n * We only need to append, but can't just use realloc with a large block\n * because 'huge' reallocs are not always handled as one could expect\n * (via remapping of pages at OS level) but may involve copying data.\n *\n * For this reason we use a list of blocks, every block is\n * AOF_RW_BUF_BLOCK_SIZE bytes.\n * ------------------------------------------------------------------------- */\n\n#define AOF_RW_BUF_BLOCK_SIZE (1024*1024*10)    /* 10 MB per block */\n\ntypedef struct aofrwblock {\n    unsigned long used, free;\n    char buf[AOF_RW_BUF_BLOCK_SIZE];\n} aofrwblock;\n\n/* This function free the old AOF rewrite buffer if needed, and initialize\n * a fresh new one. It tests for server.aof_rewrite_buf_blocks equal to NULL\n * so can be used for the first initialization as well. */\nvoid aofRewriteBufferReset(void) {\n    if (server.aof_rewrite_buf_blocks)\n        listRelease(server.aof_rewrite_buf_blocks);\n\n    server.aof_rewrite_buf_blocks = listCreate();\n    listSetFreeMethod(server.aof_rewrite_buf_blocks,zfree);\n}\n\n/* Return the current size of the AOF rewrite buffer. */\nunsigned long aofRewriteBufferSize(void) {\n    listNode *ln;\n    listIter li;\n    unsigned long size = 0;\n\n    listRewind(server.aof_rewrite_buf_blocks,&li);\n    while((ln = listNext(&li))) {\n        aofrwblock *block = listNodeValue(ln);\n        size += block->used;\n    }\n    return size;\n}\n\n/* Event handler used to send data to the child process doing the AOF\n * rewrite. We send pieces of our AOF differences buffer so that the final\n * write when the child finishes the rewrite will be small. */\nvoid aofChildWriteDiffData(aeEventLoop *el, int fd, void *privdata, int mask) {\n    listNode *ln;\n    aofrwblock *block;\n    ssize_t nwritten;\n    UNUSED(el);\n    UNUSED(fd);\n    UNUSED(privdata);\n    UNUSED(mask);\n\n    while(1) {\n        ln = listFirst(server.aof_rewrite_buf_blocks);\n        block = ln ? ln->value : NULL;\n        if (server.aof_stop_sending_diff || !block) {\n            aeDeleteFileEvent(server.el,server.aof_pipe_write_data_to_child,\n                              AE_WRITABLE);\n            return;\n        }\n        if (block->used > 0) {\n            nwritten = write(server.aof_pipe_write_data_to_child,\n                             block->buf,block->used);\n            if (nwritten <= 0) return;\n            memmove(block->buf,block->buf+nwritten,block->used-nwritten);\n            block->used -= nwritten;\n        }\n        if (block->used == 0) listDelNode(server.aof_rewrite_buf_blocks,ln);\n    }\n}\n\n/* Append data to the AOF rewrite buffer, allocating new blocks if needed. */\nvoid aofRewriteBufferAppend(unsigned char *s, unsigned long len) {\n    listNode *ln = listLast(server.aof_rewrite_buf_blocks);\n    aofrwblock *block = ln ? ln->value : NULL;\n\n    while(len) {\n        /* If we already got at least an allocated block, try appending\n         * at least some piece into it. */\n        if (block) {\n            unsigned long thislen = (block->free < len) ? block->free : len;\n            if (thislen) {  /* The current block is not already full. */\n                memcpy(block->buf+block->used, s, thislen);\n                block->used += thislen;\n                block->free -= thislen;\n                s += thislen;\n                len -= thislen;\n            }\n        }\n\n        if (len) { /* First block to allocate, or need another block. */\n            int numblocks;\n\n            block = zmalloc(sizeof(*block));\n            block->free = AOF_RW_BUF_BLOCK_SIZE;\n            block->used = 0;\n            listAddNodeTail(server.aof_rewrite_buf_blocks,block);\n\n            /* Log every time we cross more 10 or 100 blocks, respectively\n             * as a notice or warning. */\n            numblocks = listLength(server.aof_rewrite_buf_blocks);\n            if (((numblocks+1) % 10) == 0) {\n                int level = ((numblocks+1) % 100) == 0 ? LL_WARNING :\n                                                         LL_NOTICE;\n                serverLog(level,\"Background AOF buffer size: %lu MB\",\n                    aofRewriteBufferSize()/(1024*1024));\n            }\n        }\n    }\n\n    /* Install a file event to send data to the rewrite child if there is\n     * not one already. */\n    if (aeGetFileEvents(server.el,server.aof_pipe_write_data_to_child) == 0) {\n        aeCreateFileEvent(server.el, server.aof_pipe_write_data_to_child,\n            AE_WRITABLE, aofChildWriteDiffData, NULL);\n    }\n}\n\n/* Write the buffer (possibly composed of multiple blocks) into the specified\n * fd. If a short write or any other error happens -1 is returned,\n * otherwise the number of bytes written is returned. */\nssize_t aofRewriteBufferWrite(int fd) {\n    listNode *ln;\n    listIter li;\n    ssize_t count = 0;\n\n    listRewind(server.aof_rewrite_buf_blocks,&li);\n    while((ln = listNext(&li))) {\n        aofrwblock *block = listNodeValue(ln);\n        ssize_t nwritten;\n\n        if (block->used) {\n            nwritten = write(fd,block->buf,block->used);\n            if (nwritten != (ssize_t)block->used) {\n                if (nwritten == 0) errno = EIO;\n                return -1;\n            }\n            count += nwritten;\n        }\n    }\n    return count;\n}\n\n/* ----------------------------------------------------------------------------\n * AOF file implementation\n * ------------------------------------------------------------------------- */\n\n/* Starts a background task that performs fsync() against the specified\n * file descriptor (the one of the AOF file) in another thread. */\nvoid aof_background_fsync(int fd) {\n    bioCreateBackgroundJob(BIO_AOF_FSYNC,(void*)(long)fd,NULL,NULL);\n}\n\n/* Called when the user switches from \"appendonly yes\" to \"appendonly no\"\n * at runtime using the CONFIG command. */\nvoid stopAppendOnly(void) {\n    serverAssert(server.aof_state != AOF_OFF);\n    flushAppendOnlyFile(1);\n    aof_fsync(server.aof_fd);\n    close(server.aof_fd);\n\n    server.aof_fd = -1;\n    server.aof_selected_db = -1;\n    server.aof_state = AOF_OFF;\n    /* rewrite operation in progress? kill it, wait child exit */\n    if (server.aof_child_pid != -1) {\n        int statloc;\n\n        serverLog(LL_NOTICE,\"Killing running AOF rewrite child: %ld\",\n            (long) server.aof_child_pid);\n        if (kill(server.aof_child_pid,SIGUSR1) != -1) {\n            while(wait3(&statloc,0,NULL) != server.aof_child_pid);\n        }\n        /* reset the buffer accumulating changes while the child saves */\n        aofRewriteBufferReset();\n        aofRemoveTempFile(server.aof_child_pid);\n        server.aof_child_pid = -1;\n        server.aof_rewrite_time_start = -1;\n        /* close pipes used for IPC between the two processes. */\n        aofClosePipes();\n    }\n}\n\n/* Called when the user switches from \"appendonly no\" to \"appendonly yes\"\n * at runtime using the CONFIG command. */\nint startAppendOnly(void) {\n    char cwd[MAXPATHLEN]; /* Current working dir path for error messages. */\n\n    server.aof_last_fsync = server.unixtime;\n    server.aof_fd = open(server.aof_filename,O_WRONLY|O_APPEND|O_CREAT,0644);\n    serverAssert(server.aof_state == AOF_OFF);\n    if (server.aof_fd == -1) {\n        char *cwdp = getcwd(cwd,MAXPATHLEN);\n\n        serverLog(LL_WARNING,\n            \"Redis needs to enable the AOF but can't open the \"\n            \"append only file %s (in server root dir %s): %s\",\n            server.aof_filename,\n            cwdp ? cwdp : \"unknown\",\n            strerror(errno));\n        return C_ERR;\n    }\n    if (server.rdb_child_pid != -1) {\n        server.aof_rewrite_scheduled = 1;\n        serverLog(LL_WARNING,\"AOF was enabled but there is already a child process saving an RDB file on disk. An AOF background was scheduled to start when possible.\");\n    } else if (rewriteAppendOnlyFileBackground() == C_ERR) {\n        close(server.aof_fd);\n        serverLog(LL_WARNING,\"Redis needs to enable the AOF but can't trigger a background AOF rewrite operation. Check the above logs for more info about the error.\");\n        return C_ERR;\n    }\n    /* We correctly switched on AOF, now wait for the rewrite to be complete\n     * in order to append data on disk. */\n    server.aof_state = AOF_WAIT_REWRITE;\n    return C_OK;\n}\n\n/* Write the append only file buffer on disk.\n *\n * Since we are required to write the AOF before replying to the client,\n * and the only way the client socket can get a write is entering when the\n * the event loop, we accumulate all the AOF writes in a memory\n * buffer and write it on disk using this function just before entering\n * the event loop again.\n *\n * About the 'force' argument:\n *\n * When the fsync policy is set to 'everysec' we may delay the flush if there\n * is still an fsync() going on in the background thread, since for instance\n * on Linux write(2) will be blocked by the background fsync anyway.\n * When this happens we remember that there is some aof buffer to be\n * flushed ASAP, and will try to do that in the serverCron() function.\n *\n * However if force is set to 1 we'll write regardless of the background\n * fsync. */\n#define AOF_WRITE_LOG_ERROR_RATE 30 /* Seconds between errors logging. */\nvoid flushAppendOnlyFile(int force) {\n    ssize_t nwritten;\n    int sync_in_progress = 0;\n    mstime_t latency;\n\n    if (sdslen(server.aof_buf) == 0) return;\n\n    if (server.aof_fsync == AOF_FSYNC_EVERYSEC)\n        sync_in_progress = bioPendingJobsOfType(BIO_AOF_FSYNC) != 0;\n\n    if (server.aof_fsync == AOF_FSYNC_EVERYSEC && !force) {\n        /* With this append fsync policy we do background fsyncing.\n         * If the fsync is still in progress we can try to delay\n         * the write for a couple of seconds. */\n        if (sync_in_progress) {\n            if (server.aof_flush_postponed_start == 0) {\n                /* No previous write postponing, remember that we are\n                 * postponing the flush and return. */\n                server.aof_flush_postponed_start = server.unixtime;\n                return;\n            } else if (server.unixtime - server.aof_flush_postponed_start < 2) {\n                /* We were already waiting for fsync to finish, but for less\n                 * than two seconds this is still ok. Postpone again. */\n                return;\n            }\n            /* Otherwise fall trough, and go write since we can't wait\n             * over two seconds. */\n            server.aof_delayed_fsync++;\n            serverLog(LL_NOTICE,\"Asynchronous AOF fsync is taking too long (disk is busy?). Writing the AOF buffer without waiting for fsync to complete, this may slow down Redis.\");\n        }\n    }\n    /* We want to perform a single write. This should be guaranteed atomic\n     * at least if the filesystem we are writing is a real physical one.\n     * While this will save us against the server being killed I don't think\n     * there is much to do about the whole server stopping for power problems\n     * or alike */\n\n    latencyStartMonitor(latency);\n    nwritten = write(server.aof_fd,server.aof_buf,sdslen(server.aof_buf));\n    latencyEndMonitor(latency);\n    /* We want to capture different events for delayed writes:\n     * when the delay happens with a pending fsync, or with a saving child\n     * active, and when the above two conditions are missing.\n     * We also use an additional event name to save all samples which is\n     * useful for graphing / monitoring purposes. */\n    if (sync_in_progress) {\n        latencyAddSampleIfNeeded(\"aof-write-pending-fsync\",latency);\n    } else if (server.aof_child_pid != -1 || server.rdb_child_pid != -1) {\n        latencyAddSampleIfNeeded(\"aof-write-active-child\",latency);\n    } else {\n        latencyAddSampleIfNeeded(\"aof-write-alone\",latency);\n    }\n    latencyAddSampleIfNeeded(\"aof-write\",latency);\n\n    /* We performed the write so reset the postponed flush sentinel to zero. */\n    server.aof_flush_postponed_start = 0;\n\n    if (nwritten != (signed)sdslen(server.aof_buf)) {\n        static time_t last_write_error_log = 0;\n        int can_log = 0;\n\n        /* Limit logging rate to 1 line per AOF_WRITE_LOG_ERROR_RATE seconds. */\n        if ((server.unixtime - last_write_error_log) > AOF_WRITE_LOG_ERROR_RATE) {\n            can_log = 1;\n            last_write_error_log = server.unixtime;\n        }\n\n        /* Log the AOF write error and record the error code. */\n        if (nwritten == -1) {\n            if (can_log) {\n                serverLog(LL_WARNING,\"Error writing to the AOF file: %s\",\n                    strerror(errno));\n                server.aof_last_write_errno = errno;\n            }\n        } else {\n            if (can_log) {\n                serverLog(LL_WARNING,\"Short write while writing to \"\n                                       \"the AOF file: (nwritten=%lld, \"\n                                       \"expected=%lld)\",\n                                       (long long)nwritten,\n                                       (long long)sdslen(server.aof_buf));\n            }\n\n            if (ftruncate(server.aof_fd, server.aof_current_size) == -1) {\n                if (can_log) {\n                    serverLog(LL_WARNING, \"Could not remove short write \"\n                             \"from the append-only file.  Redis may refuse \"\n                             \"to load the AOF the next time it starts.  \"\n                             \"ftruncate: %s\", strerror(errno));\n                }\n            } else {\n                /* If the ftruncate() succeeded we can set nwritten to\n                 * -1 since there is no longer partial data into the AOF. */\n                nwritten = -1;\n            }\n            server.aof_last_write_errno = ENOSPC;\n        }\n\n        /* Handle the AOF write error. */\n        if (server.aof_fsync == AOF_FSYNC_ALWAYS) {\n            /* We can't recover when the fsync policy is ALWAYS since the\n             * reply for the client is already in the output buffers, and we\n             * have the contract with the user that on acknowledged write data\n             * is synced on disk. */\n            serverLog(LL_WARNING,\"Can't recover from AOF write error when the AOF fsync policy is 'always'. Exiting...\");\n            exit(1);\n        } else {\n            /* Recover from failed write leaving data into the buffer. However\n             * set an error to stop accepting writes as long as the error\n             * condition is not cleared. */\n            server.aof_last_write_status = C_ERR;\n\n            /* Trim the sds buffer if there was a partial write, and there\n             * was no way to undo it with ftruncate(2). */\n            if (nwritten > 0) {\n                server.aof_current_size += nwritten;\n                sdsrange(server.aof_buf,nwritten,-1);\n            }\n            return; /* We'll try again on the next call... */\n        }\n    } else {\n        /* Successful write(2). If AOF was in error state, restore the\n         * OK state and log the event. */\n        if (server.aof_last_write_status == C_ERR) {\n            serverLog(LL_WARNING,\n                \"AOF write error looks solved, Redis can write again.\");\n            server.aof_last_write_status = C_OK;\n        }\n    }\n    server.aof_current_size += nwritten;\n\n    /* Re-use AOF buffer when it is small enough. The maximum comes from the\n     * arena size of 4k minus some overhead (but is otherwise arbitrary). */\n    if ((sdslen(server.aof_buf)+sdsavail(server.aof_buf)) < 4000) {\n        sdsclear(server.aof_buf);\n    } else {\n        sdsfree(server.aof_buf);\n        server.aof_buf = sdsempty();\n    }\n\n    /* Don't fsync if no-appendfsync-on-rewrite is set to yes and there are\n     * children doing I/O in the background. */\n    if (server.aof_no_fsync_on_rewrite &&\n        (server.aof_child_pid != -1 || server.rdb_child_pid != -1))\n            return;\n\n    /* Perform the fsync if needed. */\n    if (server.aof_fsync == AOF_FSYNC_ALWAYS) {\n        /* aof_fsync is defined as fdatasync() for Linux in order to avoid\n         * flushing metadata. */\n        latencyStartMonitor(latency);\n        aof_fsync(server.aof_fd); /* Let's try to get this data on the disk */\n        latencyEndMonitor(latency);\n        latencyAddSampleIfNeeded(\"aof-fsync-always\",latency);\n        server.aof_last_fsync = server.unixtime;\n    } else if ((server.aof_fsync == AOF_FSYNC_EVERYSEC &&\n                server.unixtime > server.aof_last_fsync)) {\n        if (!sync_in_progress) aof_background_fsync(server.aof_fd);\n        server.aof_last_fsync = server.unixtime;\n    }\n}\n\nsds catAppendOnlyGenericCommand(sds dst, int argc, robj **argv) {\n    char buf[32];\n    int len, j;\n    robj *o;\n\n    buf[0] = '*';\n    len = 1+ll2string(buf+1,sizeof(buf)-1,argc);\n    buf[len++] = '\\r';\n    buf[len++] = '\\n';\n    dst = sdscatlen(dst,buf,len);\n\n    for (j = 0; j < argc; j++) {\n        o = getDecodedObject(argv[j]);\n        buf[0] = '$';\n        len = 1+ll2string(buf+1,sizeof(buf)-1,sdslen(o->ptr));\n        buf[len++] = '\\r';\n        buf[len++] = '\\n';\n        dst = sdscatlen(dst,buf,len);\n        dst = sdscatlen(dst,o->ptr,sdslen(o->ptr));\n        dst = sdscatlen(dst,\"\\r\\n\",2);\n        decrRefCount(o);\n    }\n    return dst;\n}\n\n/* Create the sds representation of an PEXPIREAT command, using\n * 'seconds' as time to live and 'cmd' to understand what command\n * we are translating into a PEXPIREAT.\n *\n * This command is used in order to translate EXPIRE and PEXPIRE commands\n * into PEXPIREAT command so that we retain precision in the append only\n * file, and the time is always absolute and not relative. */\nsds catAppendOnlyExpireAtCommand(sds buf, struct redisCommand *cmd, robj *key, robj *seconds) {\n    long long when;\n    robj *argv[3];\n\n    /* Make sure we can use strtoll */\n    seconds = getDecodedObject(seconds);\n    when = strtoll(seconds->ptr,NULL,10);\n    /* Convert argument into milliseconds for EXPIRE, SETEX, EXPIREAT */\n    if (cmd->proc == expireCommand || cmd->proc == setexCommand ||\n        cmd->proc == expireatCommand)\n    {\n        when *= 1000;\n    }\n    /* Convert into absolute time for EXPIRE, PEXPIRE, SETEX, PSETEX */\n    if (cmd->proc == expireCommand || cmd->proc == pexpireCommand ||\n        cmd->proc == setexCommand || cmd->proc == psetexCommand)\n    {\n        when += mstime();\n    }\n    decrRefCount(seconds);\n\n    argv[0] = createStringObject(\"PEXPIREAT\",9);\n    argv[1] = key;\n    argv[2] = createStringObjectFromLongLong(when);\n    buf = catAppendOnlyGenericCommand(buf, 3, argv);\n    decrRefCount(argv[0]);\n    decrRefCount(argv[2]);\n    return buf;\n}\n\nvoid feedAppendOnlyFile(struct redisCommand *cmd, int dictid, robj **argv, int argc) {\n    sds buf = sdsempty();\n    robj *tmpargv[3];\n\n    /* The DB this command was targeting is not the same as the last command\n     * we appended. To issue a SELECT command is needed. */\n    if (dictid != server.aof_selected_db) {\n        char seldb[64];\n\n        snprintf(seldb,sizeof(seldb),\"%d\",dictid);\n        buf = sdscatprintf(buf,\"*2\\r\\n$6\\r\\nSELECT\\r\\n$%lu\\r\\n%s\\r\\n\",\n            (unsigned long)strlen(seldb),seldb);\n        server.aof_selected_db = dictid;\n    }\n\n    if (cmd->proc == expireCommand || cmd->proc == pexpireCommand ||\n        cmd->proc == expireatCommand) {\n        /* Translate EXPIRE/PEXPIRE/EXPIREAT into PEXPIREAT */\n        buf = catAppendOnlyExpireAtCommand(buf,cmd,argv[1],argv[2]);\n    } else if (cmd->proc == setexCommand || cmd->proc == psetexCommand) {\n        /* Translate SETEX/PSETEX to SET and PEXPIREAT */\n        tmpargv[0] = createStringObject(\"SET\",3);\n        tmpargv[1] = argv[1];\n        tmpargv[2] = argv[3];\n        buf = catAppendOnlyGenericCommand(buf,3,tmpargv);\n        decrRefCount(tmpargv[0]);\n        buf = catAppendOnlyExpireAtCommand(buf,cmd,argv[1],argv[2]);\n    } else {\n        /* All the other commands don't need translation or need the\n         * same translation already operated in the command vector\n         * for the replication itself. */\n        buf = catAppendOnlyGenericCommand(buf,argc,argv);\n    }\n\n    /* Append to the AOF buffer. This will be flushed on disk just before\n     * of re-entering the event loop, so before the client will get a\n     * positive reply about the operation performed. */\n    if (server.aof_state == AOF_ON)\n        server.aof_buf = sdscatlen(server.aof_buf,buf,sdslen(buf));\n\n    /* If a background append only file rewriting is in progress we want to\n     * accumulate the differences between the child DB and the current one\n     * in a buffer, so that when the child process will do its work we\n     * can append the differences to the new append only file. */\n    if (server.aof_child_pid != -1)\n        aofRewriteBufferAppend((unsigned char*)buf,sdslen(buf));\n\n    sdsfree(buf);\n}\n\n/* ----------------------------------------------------------------------------\n * AOF loading\n * ------------------------------------------------------------------------- */\n\n/* In Redis commands are always executed in the context of a client, so in\n * order to load the append only file we need to create a fake client. */\nstruct client *createFakeClient(void) {\n    struct client *c = zmalloc(sizeof(*c));\n\n    selectDb(c,0);\n    c->fd = -1;\n    c->name = NULL;\n    c->querybuf = sdsempty();\n    c->querybuf_peak = 0;\n    c->argc = 0;\n    c->argv = NULL;\n    c->bufpos = 0;\n    c->flags = 0;\n    c->btype = BLOCKED_NONE;\n    /* We set the fake client as a slave waiting for the synchronization\n     * so that Redis will not try to send replies to this client. */\n    c->replstate = SLAVE_STATE_WAIT_BGSAVE_START;\n    c->reply = listCreate();\n    c->reply_bytes = 0;\n    c->obuf_soft_limit_reached_time = 0;\n    c->watched_keys = listCreate();\n    c->peerid = NULL;\n    listSetFreeMethod(c->reply,decrRefCountVoid);\n    listSetDupMethod(c->reply,dupClientReplyValue);\n    initClientMultiState(c);\n    return c;\n}\n\nvoid freeFakeClientArgv(struct client *c) {\n    int j;\n\n    for (j = 0; j < c->argc; j++)\n        decrRefCount(c->argv[j]);\n    zfree(c->argv);\n}\n\nvoid freeFakeClient(struct client *c) {\n    sdsfree(c->querybuf);\n    listRelease(c->reply);\n    listRelease(c->watched_keys);\n    freeClientMultiState(c);\n    zfree(c);\n}\n\n/* Replay the append log file. On success C_OK is returned. On non fatal\n * error (the append only file is zero-length) C_ERR is returned. On\n * fatal error an error message is logged and the program exists. */\nint loadAppendOnlyFile(char *filename) {\n    struct client *fakeClient;\n    FILE *fp = fopen(filename,\"r\");\n    struct redis_stat sb;\n    int old_aof_state = server.aof_state;\n    long loops = 0;\n    off_t valid_up_to = 0; /* Offset of the latest well-formed command loaded. */\n\n    if (fp && redis_fstat(fileno(fp),&sb) != -1 && sb.st_size == 0) {\n        server.aof_current_size = 0;\n        fclose(fp);\n        return C_ERR;\n    }\n\n    if (fp == NULL) {\n        serverLog(LL_WARNING,\"Fatal error: can't open the append log file for reading: %s\",strerror(errno));\n        exit(1);\n    }\n\n    /* Temporarily disable AOF, to prevent EXEC from feeding a MULTI\n     * to the same file we're about to read. */\n    server.aof_state = AOF_OFF;\n\n    fakeClient = createFakeClient();\n    startLoading(fp);\n\n    while(1) {\n        int argc, j;\n        unsigned long len;\n        robj **argv;\n        char buf[128];\n        sds argsds;\n        struct redisCommand *cmd;\n\n        /* Serve the clients from time to time */\n        if (!(loops++ % 1000)) {\n            loadingProgress(ftello(fp));\n            processEventsWhileBlocked();\n        }\n\n        if (fgets(buf,sizeof(buf),fp) == NULL) {\n            if (feof(fp))\n                break;\n            else\n                goto readerr;\n        }\n        if (buf[0] != '*') goto fmterr;\n        if (buf[1] == '\\0') goto readerr;\n        argc = atoi(buf+1);\n        if (argc < 1) goto fmterr;\n\n        argv = zmalloc(sizeof(robj*)*argc);\n        fakeClient->argc = argc;\n        fakeClient->argv = argv;\n\n        for (j = 0; j < argc; j++) {\n            if (fgets(buf,sizeof(buf),fp) == NULL) {\n                fakeClient->argc = j; /* Free up to j-1. */\n                freeFakeClientArgv(fakeClient);\n                goto readerr;\n            }\n            if (buf[0] != '$') goto fmterr;\n            len = strtol(buf+1,NULL,10);\n            argsds = sdsnewlen(NULL,len);\n            if (len && fread(argsds,len,1,fp) == 0) {\n                sdsfree(argsds);\n                fakeClient->argc = j; /* Free up to j-1. */\n                freeFakeClientArgv(fakeClient);\n                goto readerr;\n            }\n            argv[j] = createObject(OBJ_STRING,argsds);\n            if (fread(buf,2,1,fp) == 0) {\n                fakeClient->argc = j+1; /* Free up to j. */\n                freeFakeClientArgv(fakeClient);\n                goto readerr; /* discard CRLF */\n            }\n        }\n\n        /* Command lookup */\n        cmd = lookupCommand(argv[0]->ptr);\n        if (!cmd) {\n            serverLog(LL_WARNING,\"Unknown command '%s' reading the append only file\", (char*)argv[0]->ptr);\n            exit(1);\n        }\n\n        /* Run the command in the context of a fake client */\n        cmd->proc(fakeClient);\n\n        /* The fake client should not have a reply */\n        serverAssert(fakeClient->bufpos == 0 && listLength(fakeClient->reply) == 0);\n        /* The fake client should never get blocked */\n        serverAssert((fakeClient->flags & CLIENT_BLOCKED) == 0);\n\n        /* Clean up. Command code may have changed argv/argc so we use the\n         * argv/argc of the client instead of the local variables. */\n        freeFakeClientArgv(fakeClient);\n        if (server.aof_load_truncated) valid_up_to = ftello(fp);\n    }\n\n    /* This point can only be reached when EOF is reached without errors.\n     * If the client is in the middle of a MULTI/EXEC, log error and quit. */\n    if (fakeClient->flags & CLIENT_MULTI) goto uxeof;\n\nloaded_ok: /* DB loaded, cleanup and return C_OK to the caller. */\n    fclose(fp);\n    freeFakeClient(fakeClient);\n    server.aof_state = old_aof_state;\n    stopLoading();\n    aofUpdateCurrentSize();\n    server.aof_rewrite_base_size = server.aof_current_size;\n    return C_OK;\n\nreaderr: /* Read error. If feof(fp) is true, fall through to unexpected EOF. */\n    if (!feof(fp)) {\n        if (fakeClient) freeFakeClient(fakeClient); /* avoid valgrind warning */\n        serverLog(LL_WARNING,\"Unrecoverable error reading the append only file: %s\", strerror(errno));\n        exit(1);\n    }\n\nuxeof: /* Unexpected AOF end of file. */\n    if (server.aof_load_truncated) {\n        serverLog(LL_WARNING,\"!!! Warning: short read while loading the AOF file !!!\");\n        serverLog(LL_WARNING,\"!!! Truncating the AOF at offset %llu !!!\",\n            (unsigned long long) valid_up_to);\n        if (valid_up_to == -1 || truncate(filename,valid_up_to) == -1) {\n            if (valid_up_to == -1) {\n                serverLog(LL_WARNING,\"Last valid command offset is invalid\");\n            } else {\n                serverLog(LL_WARNING,\"Error truncating the AOF file: %s\",\n                    strerror(errno));\n            }\n        } else {\n            /* Make sure the AOF file descriptor points to the end of the\n             * file after the truncate call. */\n            if (server.aof_fd != -1 && lseek(server.aof_fd,0,SEEK_END) == -1) {\n                serverLog(LL_WARNING,\"Can't seek the end of the AOF file: %s\",\n                    strerror(errno));\n            } else {\n                serverLog(LL_WARNING,\n                    \"AOF loaded anyway because aof-load-truncated is enabled\");\n                goto loaded_ok;\n            }\n        }\n    }\n    if (fakeClient) freeFakeClient(fakeClient); /* avoid valgrind warning */\n    serverLog(LL_WARNING,\"Unexpected end of file reading the append only file. You can: 1) Make a backup of your AOF file, then use ./redis-check-aof --fix <filename>. 2) Alternatively you can set the 'aof-load-truncated' configuration option to yes and restart the server.\");\n    exit(1);\n\nfmterr: /* Format error. */\n    if (fakeClient) freeFakeClient(fakeClient); /* avoid valgrind warning */\n    serverLog(LL_WARNING,\"Bad file format reading the append only file: make a backup of your AOF file, then use ./redis-check-aof --fix <filename>\");\n    exit(1);\n}\n\n/* ----------------------------------------------------------------------------\n * AOF rewrite\n * ------------------------------------------------------------------------- */\n\n/* Delegate writing an object to writing a bulk string or bulk long long.\n * This is not placed in rio.c since that adds the server.h dependency. */\nint rioWriteBulkObject(rio *r, robj *obj) {\n    /* Avoid using getDecodedObject to help copy-on-write (we are often\n     * in a child process when this function is called). */\n    if (obj->encoding == OBJ_ENCODING_INT) {\n        return rioWriteBulkLongLong(r,(long)obj->ptr);\n    } else if (sdsEncodedObject(obj)) {\n        return rioWriteBulkString(r,obj->ptr,sdslen(obj->ptr));\n    } else {\n        serverPanic(\"Unknown string encoding\");\n    }\n}\n\n/* Emit the commands needed to rebuild a list object.\n * The function returns 0 on error, 1 on success. */\nint rewriteListObject(rio *r, robj *key, robj *o) {\n    long long count = 0, items = listTypeLength(o);\n\n    if (o->encoding == OBJ_ENCODING_QUICKLIST) {\n        quicklist *list = o->ptr;\n        quicklistIter *li = quicklistGetIterator(list, AL_START_HEAD);\n        quicklistEntry entry;\n\n        while (quicklistNext(li,&entry)) {\n            if (count == 0) {\n                int cmd_items = (items > AOF_REWRITE_ITEMS_PER_CMD) ?\n                    AOF_REWRITE_ITEMS_PER_CMD : items;\n                if (rioWriteBulkCount(r,'*',2+cmd_items) == 0) return 0;\n                if (rioWriteBulkString(r,\"RPUSH\",5) == 0) return 0;\n                if (rioWriteBulkObject(r,key) == 0) return 0;\n            }\n\n            if (entry.value) {\n                if (rioWriteBulkString(r,(char*)entry.value,entry.sz) == 0) return 0;\n            } else {\n                if (rioWriteBulkLongLong(r,entry.longval) == 0) return 0;\n            }\n            if (++count == AOF_REWRITE_ITEMS_PER_CMD) count = 0;\n            items--;\n        }\n        quicklistReleaseIterator(li);\n    } else {\n        serverPanic(\"Unknown list encoding\");\n    }\n    return 1;\n}\n\n/* Emit the commands needed to rebuild a set object.\n * The function returns 0 on error, 1 on success. */\nint rewriteSetObject(rio *r, robj *key, robj *o) {\n    long long count = 0, items = setTypeSize(o);\n\n    if (o->encoding == OBJ_ENCODING_INTSET) {\n        int ii = 0;\n        int64_t llval;\n\n        while(intsetGet(o->ptr,ii++,&llval)) {\n            if (count == 0) {\n                int cmd_items = (items > AOF_REWRITE_ITEMS_PER_CMD) ?\n                    AOF_REWRITE_ITEMS_PER_CMD : items;\n\n                if (rioWriteBulkCount(r,'*',2+cmd_items) == 0) return 0;\n                if (rioWriteBulkString(r,\"SADD\",4) == 0) return 0;\n                if (rioWriteBulkObject(r,key) == 0) return 0;\n            }\n            if (rioWriteBulkLongLong(r,llval) == 0) return 0;\n            if (++count == AOF_REWRITE_ITEMS_PER_CMD) count = 0;\n            items--;\n        }\n    } else if (o->encoding == OBJ_ENCODING_HT) {\n        dictIterator *di = dictGetIterator(o->ptr);\n        dictEntry *de;\n\n        while((de = dictNext(di)) != NULL) {\n            robj *eleobj = dictGetKey(de);\n            if (count == 0) {\n                int cmd_items = (items > AOF_REWRITE_ITEMS_PER_CMD) ?\n                    AOF_REWRITE_ITEMS_PER_CMD : items;\n\n                if (rioWriteBulkCount(r,'*',2+cmd_items) == 0) return 0;\n                if (rioWriteBulkString(r,\"SADD\",4) == 0) return 0;\n                if (rioWriteBulkObject(r,key) == 0) return 0;\n            }\n            if (rioWriteBulkObject(r,eleobj) == 0) return 0;\n            if (++count == AOF_REWRITE_ITEMS_PER_CMD) count = 0;\n            items--;\n        }\n        dictReleaseIterator(di);\n    } else {\n        serverPanic(\"Unknown set encoding\");\n    }\n    return 1;\n}\n\n/* Emit the commands needed to rebuild a sorted set object.\n * The function returns 0 on error, 1 on success. */\nint rewriteSortedSetObject(rio *r, robj *key, robj *o) {\n    long long count = 0, items = zsetLength(o);\n\n    if (o->encoding == OBJ_ENCODING_ZIPLIST) {\n        unsigned char *zl = o->ptr;\n        unsigned char *eptr, *sptr;\n        unsigned char *vstr;\n        unsigned int vlen;\n        long long vll;\n        double score;\n\n        eptr = ziplistIndex(zl,0);\n        serverAssert(eptr != NULL);\n        sptr = ziplistNext(zl,eptr);\n        serverAssert(sptr != NULL);\n\n        while (eptr != NULL) {\n            serverAssert(ziplistGet(eptr,&vstr,&vlen,&vll));\n            score = zzlGetScore(sptr);\n\n            if (count == 0) {\n                int cmd_items = (items > AOF_REWRITE_ITEMS_PER_CMD) ?\n                    AOF_REWRITE_ITEMS_PER_CMD : items;\n\n                if (rioWriteBulkCount(r,'*',2+cmd_items*2) == 0) return 0;\n                if (rioWriteBulkString(r,\"ZADD\",4) == 0) return 0;\n                if (rioWriteBulkObject(r,key) == 0) return 0;\n            }\n            if (rioWriteBulkDouble(r,score) == 0) return 0;\n            if (vstr != NULL) {\n                if (rioWriteBulkString(r,(char*)vstr,vlen) == 0) return 0;\n            } else {\n                if (rioWriteBulkLongLong(r,vll) == 0) return 0;\n            }\n            zzlNext(zl,&eptr,&sptr);\n            if (++count == AOF_REWRITE_ITEMS_PER_CMD) count = 0;\n            items--;\n        }\n    } else if (o->encoding == OBJ_ENCODING_SKIPLIST) {\n        zset *zs = o->ptr;\n        dictIterator *di = dictGetIterator(zs->dict);\n        dictEntry *de;\n\n        while((de = dictNext(di)) != NULL) {\n            robj *eleobj = dictGetKey(de);\n            double *score = dictGetVal(de);\n\n            if (count == 0) {\n                int cmd_items = (items > AOF_REWRITE_ITEMS_PER_CMD) ?\n                    AOF_REWRITE_ITEMS_PER_CMD : items;\n\n                if (rioWriteBulkCount(r,'*',2+cmd_items*2) == 0) return 0;\n                if (rioWriteBulkString(r,\"ZADD\",4) == 0) return 0;\n                if (rioWriteBulkObject(r,key) == 0) return 0;\n            }\n            if (rioWriteBulkDouble(r,*score) == 0) return 0;\n            if (rioWriteBulkObject(r,eleobj) == 0) return 0;\n            if (++count == AOF_REWRITE_ITEMS_PER_CMD) count = 0;\n            items--;\n        }\n        dictReleaseIterator(di);\n    } else {\n        serverPanic(\"Unknown sorted zset encoding\");\n    }\n    return 1;\n}\n\n/* Write either the key or the value of the currently selected item of a hash.\n * The 'hi' argument passes a valid Redis hash iterator.\n * The 'what' filed specifies if to write a key or a value and can be\n * either OBJ_HASH_KEY or OBJ_HASH_VALUE.\n *\n * The function returns 0 on error, non-zero on success. */\nstatic int rioWriteHashIteratorCursor(rio *r, hashTypeIterator *hi, int what) {\n    if (hi->encoding == OBJ_ENCODING_ZIPLIST) {\n        unsigned char *vstr = NULL;\n        unsigned int vlen = UINT_MAX;\n        long long vll = LLONG_MAX;\n\n        hashTypeCurrentFromZiplist(hi, what, &vstr, &vlen, &vll);\n        if (vstr) {\n            return rioWriteBulkString(r, (char*)vstr, vlen);\n        } else {\n            return rioWriteBulkLongLong(r, vll);\n        }\n\n    } else if (hi->encoding == OBJ_ENCODING_HT) {\n        robj *value;\n\n        hashTypeCurrentFromHashTable(hi, what, &value);\n        return rioWriteBulkObject(r, value);\n    }\n\n    serverPanic(\"Unknown hash encoding\");\n    return 0;\n}\n\n/* Emit the commands needed to rebuild a hash object.\n * The function returns 0 on error, 1 on success. */\nint rewriteHashObject(rio *r, robj *key, robj *o) {\n    hashTypeIterator *hi;\n    long long count = 0, items = hashTypeLength(o);\n\n    hi = hashTypeInitIterator(o);\n    while (hashTypeNext(hi) != C_ERR) {\n        if (count == 0) {\n            int cmd_items = (items > AOF_REWRITE_ITEMS_PER_CMD) ?\n                AOF_REWRITE_ITEMS_PER_CMD : items;\n\n            if (rioWriteBulkCount(r,'*',2+cmd_items*2) == 0) return 0;\n            if (rioWriteBulkString(r,\"HMSET\",5) == 0) return 0;\n            if (rioWriteBulkObject(r,key) == 0) return 0;\n        }\n\n        if (rioWriteHashIteratorCursor(r, hi, OBJ_HASH_KEY) == 0) return 0;\n        if (rioWriteHashIteratorCursor(r, hi, OBJ_HASH_VALUE) == 0) return 0;\n        if (++count == AOF_REWRITE_ITEMS_PER_CMD) count = 0;\n        items--;\n    }\n\n    hashTypeReleaseIterator(hi);\n\n    return 1;\n}\n\n/* This function is called by the child rewriting the AOF file to read\n * the difference accumulated from the parent into a buffer, that is\n * concatenated at the end of the rewrite. */\nssize_t aofReadDiffFromParent(void) {\n    char buf[65536]; /* Default pipe buffer size on most Linux systems. */\n    ssize_t nread, total = 0;\n\n    while ((nread =\n            read(server.aof_pipe_read_data_from_parent,buf,sizeof(buf))) > 0) {\n        server.aof_child_diff = sdscatlen(server.aof_child_diff,buf,nread);\n        total += nread;\n    }\n    return total;\n}\n\n/* Write a sequence of commands able to fully rebuild the dataset into\n * \"filename\". Used both by REWRITEAOF and BGREWRITEAOF.\n *\n * In order to minimize the number of commands needed in the rewritten\n * log Redis uses variadic commands when possible, such as RPUSH, SADD\n * and ZADD. However at max AOF_REWRITE_ITEMS_PER_CMD items per time\n * are inserted using a single command. */\nint rewriteAppendOnlyFile(char *filename) {\n    dictIterator *di = NULL;\n    dictEntry *de;\n    rio aof;\n    FILE *fp;\n    char tmpfile[256];\n    int j;\n    long long now = mstime();\n    char byte;\n    size_t processed = 0;\n\n    /* Note that we have to use a different temp name here compared to the\n     * one used by rewriteAppendOnlyFileBackground() function. */\n    snprintf(tmpfile,256,\"temp-rewriteaof-%d.aof\", (int) getpid());\n    fp = fopen(tmpfile,\"w\");\n    if (!fp) {\n        serverLog(LL_WARNING, \"Opening the temp file for AOF rewrite in rewriteAppendOnlyFile(): %s\", strerror(errno));\n        return C_ERR;\n    }\n\n    server.aof_child_diff = sdsempty();\n    rioInitWithFile(&aof,fp);\n    if (server.aof_rewrite_incremental_fsync)\n        rioSetAutoSync(&aof,AOF_AUTOSYNC_BYTES);\n    for (j = 0; j < server.dbnum; j++) {\n        char selectcmd[] = \"*2\\r\\n$6\\r\\nSELECT\\r\\n\";\n        redisDb *db = server.db+j;\n        dict *d = db->dict;\n        if (dictSize(d) == 0) continue;\n        di = dictGetSafeIterator(d);\n        if (!di) {\n            fclose(fp);\n            return C_ERR;\n        }\n\n        /* SELECT the new DB */\n        if (rioWrite(&aof,selectcmd,sizeof(selectcmd)-1) == 0) goto werr;\n        if (rioWriteBulkLongLong(&aof,j) == 0) goto werr;\n\n        /* Iterate this DB writing every entry */\n        while((de = dictNext(di)) != NULL) {\n            sds keystr;\n            robj key, *o;\n            long long expiretime;\n\n            keystr = dictGetKey(de);\n            o = dictGetVal(de);\n            initStaticStringObject(key,keystr);\n\n            expiretime = getExpire(db,&key);\n\n            /* If this key is already expired skip it */\n            if (expiretime != -1 && expiretime < now) continue;\n\n            /* Save the key and associated value */\n            if (o->type == OBJ_STRING) {\n                /* Emit a SET command */\n                char cmd[]=\"*3\\r\\n$3\\r\\nSET\\r\\n\";\n                if (rioWrite(&aof,cmd,sizeof(cmd)-1) == 0) goto werr;\n                /* Key and value */\n                if (rioWriteBulkObject(&aof,&key) == 0) goto werr;\n                if (rioWriteBulkObject(&aof,o) == 0) goto werr;\n            } else if (o->type == OBJ_LIST) {\n                if (rewriteListObject(&aof,&key,o) == 0) goto werr;\n            } else if (o->type == OBJ_SET) {\n                if (rewriteSetObject(&aof,&key,o) == 0) goto werr;\n            } else if (o->type == OBJ_ZSET) {\n                if (rewriteSortedSetObject(&aof,&key,o) == 0) goto werr;\n            } else if (o->type == OBJ_HASH) {\n                if (rewriteHashObject(&aof,&key,o) == 0) goto werr;\n            } else {\n                serverPanic(\"Unknown object type\");\n            }\n            /* Save the expire time */\n            if (expiretime != -1) {\n                char cmd[]=\"*3\\r\\n$9\\r\\nPEXPIREAT\\r\\n\";\n                if (rioWrite(&aof,cmd,sizeof(cmd)-1) == 0) goto werr;\n                if (rioWriteBulkObject(&aof,&key) == 0) goto werr;\n                if (rioWriteBulkLongLong(&aof,expiretime) == 0) goto werr;\n            }\n            /* Read some diff from the parent process from time to time. */\n            if (aof.processed_bytes > processed+1024*10) {\n                processed = aof.processed_bytes;\n                aofReadDiffFromParent();\n            }\n        }\n        dictReleaseIterator(di);\n        di = NULL;\n    }\n\n    /* Do an initial slow fsync here while the parent is still sending\n     * data, in order to make the next final fsync faster. */\n    if (fflush(fp) == EOF) goto werr;\n    if (fsync(fileno(fp)) == -1) goto werr;\n\n    /* Read again a few times to get more data from the parent.\n     * We can't read forever (the server may receive data from clients\n     * faster than it is able to send data to the child), so we try to read\n     * some more data in a loop as soon as there is a good chance more data\n     * will come. If it looks like we are wasting time, we abort (this\n     * happens after 20 ms without new data). */\n    int nodata = 0;\n    mstime_t start = mstime();\n    while(mstime()-start < 1000 && nodata < 20) {\n        if (aeWait(server.aof_pipe_read_data_from_parent, AE_READABLE, 1) <= 0)\n        {\n            nodata++;\n            continue;\n        }\n        nodata = 0; /* Start counting from zero, we stop on N *contiguous*\n                       timeouts. */\n        aofReadDiffFromParent();\n    }\n\n    /* Ask the master to stop sending diffs. */\n    if (write(server.aof_pipe_write_ack_to_parent,\"!\",1) != 1) goto werr;\n    if (anetNonBlock(NULL,server.aof_pipe_read_ack_from_parent) != ANET_OK)\n        goto werr;\n    /* We read the ACK from the server using a 10 seconds timeout. Normally\n     * it should reply ASAP, but just in case we lose its reply, we are sure\n     * the child will eventually get terminated. */\n    if (syncRead(server.aof_pipe_read_ack_from_parent,&byte,1,5000) != 1 ||\n        byte != '!') goto werr;\n    serverLog(LL_NOTICE,\"Parent agreed to stop sending diffs. Finalizing AOF...\");\n\n    /* Read the final diff if any. */\n    aofReadDiffFromParent();\n\n    /* Write the received diff to the file. */\n    serverLog(LL_NOTICE,\n        \"Concatenating %.2f MB of AOF diff received from parent.\",\n        (double) sdslen(server.aof_child_diff) / (1024*1024));\n    if (rioWrite(&aof,server.aof_child_diff,sdslen(server.aof_child_diff)) == 0)\n        goto werr;\n\n    /* Make sure data will not remain on the OS's output buffers */\n    if (fflush(fp) == EOF) goto werr;\n    if (fsync(fileno(fp)) == -1) goto werr;\n    if (fclose(fp) == EOF) goto werr;\n\n    /* Use RENAME to make sure the DB file is changed atomically only\n     * if the generate DB file is ok. */\n    if (rename(tmpfile,filename) == -1) {\n        serverLog(LL_WARNING,\"Error moving temp append only file on the final destination: %s\", strerror(errno));\n        unlink(tmpfile);\n        return C_ERR;\n    }\n    serverLog(LL_NOTICE,\"SYNC append only file rewrite performed\");\n    return C_OK;\n\nwerr:\n    serverLog(LL_WARNING,\"Write error writing append only file on disk: %s\", strerror(errno));\n    fclose(fp);\n    unlink(tmpfile);\n    if (di) dictReleaseIterator(di);\n    return C_ERR;\n}\n\n/* ----------------------------------------------------------------------------\n * AOF rewrite pipes for IPC\n * -------------------------------------------------------------------------- */\n\n/* This event handler is called when the AOF rewriting child sends us a\n * single '!' char to signal we should stop sending buffer diffs. The\n * parent sends a '!' as well to acknowledge. */\nvoid aofChildPipeReadable(aeEventLoop *el, int fd, void *privdata, int mask) {\n    char byte;\n    UNUSED(el);\n    UNUSED(privdata);\n    UNUSED(mask);\n\n    if (read(fd,&byte,1) == 1 && byte == '!') {\n        serverLog(LL_NOTICE,\"AOF rewrite child asks to stop sending diffs.\");\n        server.aof_stop_sending_diff = 1;\n        if (write(server.aof_pipe_write_ack_to_child,\"!\",1) != 1) {\n            /* If we can't send the ack, inform the user, but don't try again\n             * since in the other side the children will use a timeout if the\n             * kernel can't buffer our write, or, the children was\n             * terminated. */\n            serverLog(LL_WARNING,\"Can't send ACK to AOF child: %s\",\n                strerror(errno));\n        }\n    }\n    /* Remove the handler since this can be called only one time during a\n     * rewrite. */\n    aeDeleteFileEvent(server.el,server.aof_pipe_read_ack_from_child,AE_READABLE);\n}\n\n/* Create the pipes used for parent - child process IPC during rewrite.\n * We have a data pipe used to send AOF incremental diffs to the child,\n * and two other pipes used by the children to signal it finished with\n * the rewrite so no more data should be written, and another for the\n * parent to acknowledge it understood this new condition. */\nint aofCreatePipes(void) {\n    int fds[6] = {-1, -1, -1, -1, -1, -1};\n    int j;\n\n    if (pipe(fds) == -1) goto error; /* parent -> children data. */\n    if (pipe(fds+2) == -1) goto error; /* children -> parent ack. */\n    if (pipe(fds+4) == -1) goto error; /* children -> parent ack. */\n    /* Parent -> children data is non blocking. */\n    if (anetNonBlock(NULL,fds[0]) != ANET_OK) goto error;\n    if (anetNonBlock(NULL,fds[1]) != ANET_OK) goto error;\n    if (aeCreateFileEvent(server.el, fds[2], AE_READABLE, aofChildPipeReadable, NULL) == AE_ERR) goto error;\n\n    server.aof_pipe_write_data_to_child = fds[1];\n    server.aof_pipe_read_data_from_parent = fds[0];\n    server.aof_pipe_write_ack_to_parent = fds[3];\n    server.aof_pipe_read_ack_from_child = fds[2];\n    server.aof_pipe_write_ack_to_child = fds[5];\n    server.aof_pipe_read_ack_from_parent = fds[4];\n    server.aof_stop_sending_diff = 0;\n    return C_OK;\n\nerror:\n    serverLog(LL_WARNING,\"Error opening /setting AOF rewrite IPC pipes: %s\",\n        strerror(errno));\n    for (j = 0; j < 6; j++) if(fds[j] != -1) close(fds[j]);\n    return C_ERR;\n}\n\nvoid aofClosePipes(void) {\n    aeDeleteFileEvent(server.el,server.aof_pipe_read_ack_from_child,AE_READABLE);\n    aeDeleteFileEvent(server.el,server.aof_pipe_write_data_to_child,AE_WRITABLE);\n    close(server.aof_pipe_write_data_to_child);\n    close(server.aof_pipe_read_data_from_parent);\n    close(server.aof_pipe_write_ack_to_parent);\n    close(server.aof_pipe_read_ack_from_child);\n    close(server.aof_pipe_write_ack_to_child);\n    close(server.aof_pipe_read_ack_from_parent);\n}\n\n/* ----------------------------------------------------------------------------\n * AOF background rewrite\n * ------------------------------------------------------------------------- */\n\n/* This is how rewriting of the append only file in background works:\n *\n * 1) The user calls BGREWRITEAOF\n * 2) Redis calls this function, that forks():\n *    2a) the child rewrite the append only file in a temp file.\n *    2b) the parent accumulates differences in server.aof_rewrite_buf.\n * 3) When the child finished '2a' exists.\n * 4) The parent will trap the exit code, if it's OK, will append the\n *    data accumulated into server.aof_rewrite_buf into the temp file, and\n *    finally will rename(2) the temp file in the actual file name.\n *    The the new file is reopened as the new append only file. Profit!\n */\nint rewriteAppendOnlyFileBackground(void) {\n    pid_t childpid;\n    long long start;\n\n    if (server.aof_child_pid != -1 || server.rdb_child_pid != -1) return C_ERR;\n    if (aofCreatePipes() != C_OK) return C_ERR;\n    start = ustime();\n    if ((childpid = fork()) == 0) {\n        char tmpfile[256];\n\n        /* Child */\n        closeListeningSockets(0);\n        redisSetProcTitle(\"redis-aof-rewrite\");\n        snprintf(tmpfile,256,\"temp-rewriteaof-bg-%d.aof\", (int) getpid());\n        if (rewriteAppendOnlyFile(tmpfile) == C_OK) {\n            size_t private_dirty = zmalloc_get_private_dirty();\n\n            if (private_dirty) {\n                serverLog(LL_NOTICE,\n                    \"AOF rewrite: %zu MB of memory used by copy-on-write\",\n                    private_dirty/(1024*1024));\n            }\n            exitFromChild(0);\n        } else {\n            exitFromChild(1);\n        }\n    } else {\n        /* Parent */\n        server.stat_fork_time = ustime()-start;\n        server.stat_fork_rate = (double) zmalloc_used_memory() * 1000000 / server.stat_fork_time / (1024*1024*1024); /* GB per second. */\n        latencyAddSampleIfNeeded(\"fork\",server.stat_fork_time/1000);\n        if (childpid == -1) {\n            serverLog(LL_WARNING,\n                \"Can't rewrite append only file in background: fork: %s\",\n                strerror(errno));\n            return C_ERR;\n        }\n        serverLog(LL_NOTICE,\n            \"Background append only file rewriting started by pid %d\",childpid);\n        server.aof_rewrite_scheduled = 0;\n        server.aof_rewrite_time_start = time(NULL);\n        server.aof_child_pid = childpid;\n        updateDictResizePolicy();\n        /* We set appendseldb to -1 in order to force the next call to the\n         * feedAppendOnlyFile() to issue a SELECT command, so the differences\n         * accumulated by the parent into server.aof_rewrite_buf will start\n         * with a SELECT statement and it will be safe to merge. */\n        server.aof_selected_db = -1;\n        replicationScriptCacheFlush();\n        return C_OK;\n    }\n    return C_OK; /* unreached */\n}\n\nvoid bgrewriteaofCommand(client *c) {\n    if (server.aof_child_pid != -1) {\n        addReplyError(c,\"Background append only file rewriting already in progress\");\n    } else if (server.rdb_child_pid != -1) {\n        server.aof_rewrite_scheduled = 1;\n        addReplyStatus(c,\"Background append only file rewriting scheduled\");\n    } else if (rewriteAppendOnlyFileBackground() == C_OK) {\n        addReplyStatus(c,\"Background append only file rewriting started\");\n    } else {\n        addReply(c,shared.err);\n    }\n}\n\nvoid aofRemoveTempFile(pid_t childpid) {\n    char tmpfile[256];\n\n    snprintf(tmpfile,256,\"temp-rewriteaof-bg-%d.aof\", (int) childpid);\n    unlink(tmpfile);\n}\n\n/* Update the server.aof_current_size field explicitly using stat(2)\n * to check the size of the file. This is useful after a rewrite or after\n * a restart, normally the size is updated just adding the write length\n * to the current length, that is much faster. */\nvoid aofUpdateCurrentSize(void) {\n    struct redis_stat sb;\n    mstime_t latency;\n\n    latencyStartMonitor(latency);\n    if (redis_fstat(server.aof_fd,&sb) == -1) {\n        serverLog(LL_WARNING,\"Unable to obtain the AOF file length. stat: %s\",\n            strerror(errno));\n    } else {\n        server.aof_current_size = sb.st_size;\n    }\n    latencyEndMonitor(latency);\n    latencyAddSampleIfNeeded(\"aof-fstat\",latency);\n}\n\n/* A background append only file rewriting (BGREWRITEAOF) terminated its work.\n * Handle this. */\nvoid backgroundRewriteDoneHandler(int exitcode, int bysignal) {\n    if (!bysignal && exitcode == 0) {\n        int newfd, oldfd;\n        char tmpfile[256];\n        long long now = ustime();\n        mstime_t latency;\n\n        serverLog(LL_NOTICE,\n            \"Background AOF rewrite terminated with success\");\n\n        /* Flush the differences accumulated by the parent to the\n         * rewritten AOF. */\n        latencyStartMonitor(latency);\n        snprintf(tmpfile,256,\"temp-rewriteaof-bg-%d.aof\",\n            (int)server.aof_child_pid);\n        newfd = open(tmpfile,O_WRONLY|O_APPEND);\n        if (newfd == -1) {\n            serverLog(LL_WARNING,\n                \"Unable to open the temporary AOF produced by the child: %s\", strerror(errno));\n            goto cleanup;\n        }\n\n        if (aofRewriteBufferWrite(newfd) == -1) {\n            serverLog(LL_WARNING,\n                \"Error trying to flush the parent diff to the rewritten AOF: %s\", strerror(errno));\n            close(newfd);\n            goto cleanup;\n        }\n        latencyEndMonitor(latency);\n        latencyAddSampleIfNeeded(\"aof-rewrite-diff-write\",latency);\n\n        serverLog(LL_NOTICE,\n            \"Residual parent diff successfully flushed to the rewritten AOF (%.2f MB)\", (double) aofRewriteBufferSize() / (1024*1024));\n\n        /* The only remaining thing to do is to rename the temporary file to\n         * the configured file and switch the file descriptor used to do AOF\n         * writes. We don't want close(2) or rename(2) calls to block the\n         * server on old file deletion.\n         *\n         * There are two possible scenarios:\n         *\n         * 1) AOF is DISABLED and this was a one time rewrite. The temporary\n         * file will be renamed to the configured file. When this file already\n         * exists, it will be unlinked, which may block the server.\n         *\n         * 2) AOF is ENABLED and the rewritten AOF will immediately start\n         * receiving writes. After the temporary file is renamed to the\n         * configured file, the original AOF file descriptor will be closed.\n         * Since this will be the last reference to that file, closing it\n         * causes the underlying file to be unlinked, which may block the\n         * server.\n         *\n         * To mitigate the blocking effect of the unlink operation (either\n         * caused by rename(2) in scenario 1, or by close(2) in scenario 2), we\n         * use a background thread to take care of this. First, we\n         * make scenario 1 identical to scenario 2 by opening the target file\n         * when it exists. The unlink operation after the rename(2) will then\n         * be executed upon calling close(2) for its descriptor. Everything to\n         * guarantee atomicity for this switch has already happened by then, so\n         * we don't care what the outcome or duration of that close operation\n         * is, as long as the file descriptor is released again. */\n        if (server.aof_fd == -1) {\n            /* AOF disabled */\n\n             /* Don't care if this fails: oldfd will be -1 and we handle that.\n              * One notable case of -1 return is if the old file does\n              * not exist. */\n             oldfd = open(server.aof_filename,O_RDONLY|O_NONBLOCK);\n        } else {\n            /* AOF enabled */\n            oldfd = -1; /* We'll set this to the current AOF filedes later. */\n        }\n\n        /* Rename the temporary file. This will not unlink the target file if\n         * it exists, because we reference it with \"oldfd\". */\n        latencyStartMonitor(latency);\n        if (rename(tmpfile,server.aof_filename) == -1) {\n            serverLog(LL_WARNING,\n                \"Error trying to rename the temporary AOF file %s into %s: %s\",\n                tmpfile,\n                server.aof_filename,\n                strerror(errno));\n            close(newfd);\n            if (oldfd != -1) close(oldfd);\n            goto cleanup;\n        }\n        latencyEndMonitor(latency);\n        latencyAddSampleIfNeeded(\"aof-rename\",latency);\n\n        if (server.aof_fd == -1) {\n            /* AOF disabled, we don't need to set the AOF file descriptor\n             * to this new file, so we can close it. */\n            close(newfd);\n        } else {\n            /* AOF enabled, replace the old fd with the new one. */\n            oldfd = server.aof_fd;\n            server.aof_fd = newfd;\n            if (server.aof_fsync == AOF_FSYNC_ALWAYS)\n                aof_fsync(newfd);\n            else if (server.aof_fsync == AOF_FSYNC_EVERYSEC)\n                aof_background_fsync(newfd);\n            server.aof_selected_db = -1; /* Make sure SELECT is re-issued */\n            aofUpdateCurrentSize();\n            server.aof_rewrite_base_size = server.aof_current_size;\n\n            /* Clear regular AOF buffer since its contents was just written to\n             * the new AOF from the background rewrite buffer. */\n            sdsfree(server.aof_buf);\n            server.aof_buf = sdsempty();\n        }\n\n        server.aof_lastbgrewrite_status = C_OK;\n\n        serverLog(LL_NOTICE, \"Background AOF rewrite finished successfully\");\n        /* Change state from WAIT_REWRITE to ON if needed */\n        if (server.aof_state == AOF_WAIT_REWRITE)\n            server.aof_state = AOF_ON;\n\n        /* Asynchronously close the overwritten AOF. */\n        if (oldfd != -1) bioCreateBackgroundJob(BIO_CLOSE_FILE,(void*)(long)oldfd,NULL,NULL);\n\n        serverLog(LL_VERBOSE,\n            \"Background AOF rewrite signal handler took %lldus\", ustime()-now);\n    } else if (!bysignal && exitcode != 0) {\n        /* SIGUSR1 is whitelisted, so we have a way to kill a child without\n         * tirggering an error conditon. */\n        if (bysignal != SIGUSR1)\n            server.aof_lastbgrewrite_status = C_ERR;\n        serverLog(LL_WARNING,\n            \"Background AOF rewrite terminated with error\");\n    } else {\n        server.aof_lastbgrewrite_status = C_ERR;\n\n        serverLog(LL_WARNING,\n            \"Background AOF rewrite terminated by signal %d\", bysignal);\n    }\n\ncleanup:\n    aofClosePipes();\n    aofRewriteBufferReset();\n    aofRemoveTempFile(server.aof_child_pid);\n    server.aof_child_pid = -1;\n    server.aof_rewrite_time_last = time(NULL)-server.aof_rewrite_time_start;\n    server.aof_rewrite_time_start = -1;\n    /* Schedule a new rewrite if we are waiting for it to switch the AOF ON. */\n    if (server.aof_state == AOF_WAIT_REWRITE)\n        server.aof_rewrite_scheduled = 1;\n}\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/src/asciilogo.h",
    "content": "/*\n * Copyright (c) 2009-2012, Salvatore Sanfilippo <antirez at gmail dot com>\n * All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions are met:\n *\n *   * Redistributions of source code must retain the above copyright notice,\n *     this list of conditions and the following disclaimer.\n *   * Redistributions in binary form must reproduce the above copyright\n *     notice, this list of conditions and the following disclaimer in the\n *     documentation and/or other materials provided with the distribution.\n *   * Neither the name of Redis nor the names of its contributors may be used\n *     to endorse or promote products derived from this software without\n *     specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\"\n * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\n * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE\n * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR\n * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF\n * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS\n * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN\n * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)\n * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE\n * POSSIBILITY OF SUCH DAMAGE.\n */\n\nchar *ascii_logo =\n\"                _._                                                  \\n\"\n\"           _.-``__ ''-._                                             \\n\"\n\"      _.-``    `.  `_.  ''-._           Redis %s (%s/%d) %s bit\\n\"\n\"  .-`` .-```.  ```\\\\/    _.,_ ''-._                                   \\n\"\n\" (    '      ,       .-`  | `,    )     Running in %s mode\\n\"\n\" |`-._`-...-` __...-.``-._|'` _.-'|     Port: %d\\n\"\n\" |    `-._   `._    /     _.-'    |     PID: %ld\\n\"\n\"  `-._    `-._  `-./  _.-'    _.-'                                   \\n\"\n\" |`-._`-._    `-.__.-'    _.-'_.-'|                                  \\n\"\n\" |    `-._`-._        _.-'_.-'    |           http://redis.io        \\n\"\n\"  `-._    `-._`-.__.-'_.-'    _.-'                                   \\n\"\n\" |`-._`-._    `-.__.-'    _.-'_.-'|                                  \\n\"\n\" |    `-._`-._        _.-'_.-'    |                                  \\n\"\n\"  `-._    `-._`-.__.-'_.-'    _.-'                                   \\n\"\n\"      `-._    `-.__.-'    _.-'                                       \\n\"\n\"          `-._        _.-'                                           \\n\"\n\"              `-.__.-'                                               \\n\\n\";\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/src/bio.c",
    "content": "/* Background I/O service for Redis.\n *\n * This file implements operations that we need to perform in the background.\n * Currently there is only a single operation, that is a background close(2)\n * system call. This is needed as when the process is the last owner of a\n * reference to a file closing it means unlinking it, and the deletion of the\n * file is slow, blocking the server.\n *\n * In the future we'll either continue implementing new things we need or\n * we'll switch to libeio. However there are probably long term uses for this\n * file as we may want to put here Redis specific background tasks (for instance\n * it is not impossible that we'll need a non blocking FLUSHDB/FLUSHALL\n * implementation).\n *\n * DESIGN\n * ------\n *\n * The design is trivial, we have a structure representing a job to perform\n * and a different thread and job queue for every job type.\n * Every thread wait for new jobs in its queue, and process every job\n * sequentially.\n *\n * Jobs of the same type are guaranteed to be processed from the least\n * recently inserted to the most recently inserted (older jobs processed\n * first).\n *\n * Currently there is no way for the creator of the job to be notified about\n * the completion of the operation, this will only be added when/if needed.\n *\n * ----------------------------------------------------------------------------\n *\n * Copyright (c) 2009-2012, Salvatore Sanfilippo <antirez at gmail dot com>\n * All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions are met:\n *\n *   * Redistributions of source code must retain the above copyright notice,\n *     this list of conditions and the following disclaimer.\n *   * Redistributions in binary form must reproduce the above copyright\n *     notice, this list of conditions and the following disclaimer in the\n *     documentation and/or other materials provided with the distribution.\n *   * Neither the name of Redis nor the names of its contributors may be used\n *     to endorse or promote products derived from this software without\n *     specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\"\n * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\n * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE\n * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR\n * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF\n * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS\n * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN\n * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)\n * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE\n * POSSIBILITY OF SUCH DAMAGE.\n */\n\n\n#include \"server.h\"\n#include \"bio.h\"\n\nstatic pthread_t bio_threads[BIO_NUM_OPS];\nstatic pthread_mutex_t bio_mutex[BIO_NUM_OPS];\nstatic pthread_cond_t bio_condvar[BIO_NUM_OPS];\nstatic list *bio_jobs[BIO_NUM_OPS];\n/* The following array is used to hold the number of pending jobs for every\n * OP type. This allows us to export the bioPendingJobsOfType() API that is\n * useful when the main thread wants to perform some operation that may involve\n * objects shared with the background thread. The main thread will just wait\n * that there are no longer jobs of this type to be executed before performing\n * the sensible operation. This data is also useful for reporting. */\nstatic unsigned long long bio_pending[BIO_NUM_OPS];\n\n/* This structure represents a background Job. It is only used locally to this\n * file as the API does not expose the internals at all. */\nstruct bio_job {\n    time_t time; /* Time at which the job was created. */\n    /* Job specific arguments pointers. If we need to pass more than three\n     * arguments we can just pass a pointer to a structure or alike. */\n    void *arg1, *arg2, *arg3;\n};\n\nvoid *bioProcessBackgroundJobs(void *arg);\n\n/* Make sure we have enough stack to perform all the things we do in the\n * main thread. */\n#define REDIS_THREAD_STACK_SIZE (1024*1024*4)\n\n/* Initialize the background system, spawning the thread. */\nvoid bioInit(void) {\n    pthread_attr_t attr;\n    pthread_t thread;\n    size_t stacksize;\n    int j;\n\n    /* Initialization of state vars and objects */\n    for (j = 0; j < BIO_NUM_OPS; j++) {\n        pthread_mutex_init(&bio_mutex[j],NULL);\n        pthread_cond_init(&bio_condvar[j],NULL);\n        bio_jobs[j] = listCreate();\n        bio_pending[j] = 0;\n    }\n\n    /* Set the stack size as by default it may be small in some system */\n    pthread_attr_init(&attr);\n    pthread_attr_getstacksize(&attr,&stacksize);\n    if (!stacksize) stacksize = 1; /* The world is full of Solaris Fixes */\n    while (stacksize < REDIS_THREAD_STACK_SIZE) stacksize *= 2;\n    pthread_attr_setstacksize(&attr, stacksize);\n\n    /* Ready to spawn our threads. We use the single argument the thread\n     * function accepts in order to pass the job ID the thread is\n     * responsible of. */\n    for (j = 0; j < BIO_NUM_OPS; j++) {\n        void *arg = (void*)(unsigned long) j;\n        if (pthread_create(&thread,&attr,bioProcessBackgroundJobs,arg) != 0) {\n            serverLog(LL_WARNING,\"Fatal: Can't initialize Background Jobs.\");\n            exit(1);\n        }\n        bio_threads[j] = thread;\n    }\n}\n\nvoid bioCreateBackgroundJob(int type, void *arg1, void *arg2, void *arg3) {\n    struct bio_job *job = zmalloc(sizeof(*job));\n\n    job->time = time(NULL);\n    job->arg1 = arg1;\n    job->arg2 = arg2;\n    job->arg3 = arg3;\n    pthread_mutex_lock(&bio_mutex[type]);\n    listAddNodeTail(bio_jobs[type],job);\n    bio_pending[type]++;\n    pthread_cond_signal(&bio_condvar[type]);\n    pthread_mutex_unlock(&bio_mutex[type]);\n}\n\nvoid *bioProcessBackgroundJobs(void *arg) {\n    struct bio_job *job;\n    unsigned long type = (unsigned long) arg;\n    sigset_t sigset;\n\n    /* Check that the type is within the right interval. */\n    if (type >= BIO_NUM_OPS) {\n        serverLog(LL_WARNING,\n            \"Warning: bio thread started with wrong type %lu\",type);\n        return NULL;\n    }\n\n    /* Make the thread killable at any time, so that bioKillThreads()\n     * can work reliably. */\n    pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);\n    pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL);\n\n    pthread_mutex_lock(&bio_mutex[type]);\n    /* Block SIGALRM so we are sure that only the main thread will\n     * receive the watchdog signal. */\n    sigemptyset(&sigset);\n    sigaddset(&sigset, SIGALRM);\n    if (pthread_sigmask(SIG_BLOCK, &sigset, NULL))\n        serverLog(LL_WARNING,\n            \"Warning: can't mask SIGALRM in bio.c thread: %s\", strerror(errno));\n\n    while(1) {\n        listNode *ln;\n\n        /* The loop always starts with the lock hold. */\n        if (listLength(bio_jobs[type]) == 0) {\n            pthread_cond_wait(&bio_condvar[type],&bio_mutex[type]);\n            continue;\n        }\n        /* Pop the job from the queue. */\n        ln = listFirst(bio_jobs[type]);\n        job = ln->value;\n        /* It is now possible to unlock the background system as we know have\n         * a stand alone job structure to process.*/\n        pthread_mutex_unlock(&bio_mutex[type]);\n\n        /* Process the job accordingly to its type. */\n        if (type == BIO_CLOSE_FILE) {\n            close((long)job->arg1);\n        } else if (type == BIO_AOF_FSYNC) {\n            aof_fsync((long)job->arg1);\n        } else {\n            serverPanic(\"Wrong job type in bioProcessBackgroundJobs().\");\n        }\n        zfree(job);\n\n        /* Lock again before reiterating the loop, if there are no longer\n         * jobs to process we'll block again in pthread_cond_wait(). */\n        pthread_mutex_lock(&bio_mutex[type]);\n        listDelNode(bio_jobs[type],ln);\n        bio_pending[type]--;\n    }\n}\n\n/* Return the number of pending jobs of the specified type. */\nunsigned long long bioPendingJobsOfType(int type) {\n    unsigned long long val;\n    pthread_mutex_lock(&bio_mutex[type]);\n    val = bio_pending[type];\n    pthread_mutex_unlock(&bio_mutex[type]);\n    return val;\n}\n\n/* Kill the running bio threads in an unclean way. This function should be\n * used only when it's critical to stop the threads for some reason.\n * Currently Redis does this only on crash (for instance on SIGSEGV) in order\n * to perform a fast memory check without other threads messing with memory. */\nvoid bioKillThreads(void) {\n    int err, j;\n\n    for (j = 0; j < BIO_NUM_OPS; j++) {\n        if (pthread_cancel(bio_threads[j]) == 0) {\n            if ((err = pthread_join(bio_threads[j],NULL)) != 0) {\n                serverLog(LL_WARNING,\n                    \"Bio thread for job type #%d can be joined: %s\",\n                        j, strerror(err));\n            } else {\n                serverLog(LL_WARNING,\n                    \"Bio thread for job type #%d terminated\",j);\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/src/bio.h",
    "content": "/*\n * Copyright (c) 2009-2012, Salvatore Sanfilippo <antirez at gmail dot com>\n * All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions are met:\n *\n *   * Redistributions of source code must retain the above copyright notice,\n *     this list of conditions and the following disclaimer.\n *   * Redistributions in binary form must reproduce the above copyright\n *     notice, this list of conditions and the following disclaimer in the\n *     documentation and/or other materials provided with the distribution.\n *   * Neither the name of Redis nor the names of its contributors may be used\n *     to endorse or promote products derived from this software without\n *     specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\"\n * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\n * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE\n * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR\n * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF\n * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS\n * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN\n * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)\n * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE\n * POSSIBILITY OF SUCH DAMAGE.\n */\n\n/* Exported API */\nvoid bioInit(void);\nvoid bioCreateBackgroundJob(int type, void *arg1, void *arg2, void *arg3);\nunsigned long long bioPendingJobsOfType(int type);\nvoid bioWaitPendingJobsLE(int type, unsigned long long num);\ntime_t bioOlderJobOfType(int type);\nvoid bioKillThreads(void);\n\n/* Background job opcodes */\n#define BIO_CLOSE_FILE    0 /* Deferred close(2) syscall. */\n#define BIO_AOF_FSYNC     1 /* Deferred AOF fsync. */\n#define BIO_NUM_OPS       2\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/src/bitops.c",
    "content": "/* Bit operations.\n *\n * Copyright (c) 2009-2012, Salvatore Sanfilippo <antirez at gmail dot com>\n * All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions are met:\n *\n *   * Redistributions of source code must retain the above copyright notice,\n *     this list of conditions and the following disclaimer.\n *   * Redistributions in binary form must reproduce the above copyright\n *     notice, this list of conditions and the following disclaimer in the\n *     documentation and/or other materials provided with the distribution.\n *   * Neither the name of Redis nor the names of its contributors may be used\n *     to endorse or promote products derived from this software without\n *     specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\"\n * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\n * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE\n * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR\n * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF\n * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS\n * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN\n * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)\n * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE\n * POSSIBILITY OF SUCH DAMAGE.\n */\n\n#include \"server.h\"\n\n/* -----------------------------------------------------------------------------\n * Helpers and low level bit functions.\n * -------------------------------------------------------------------------- */\n\n/* Count number of bits set in the binary array pointed by 's' and long\n * 'count' bytes. The implementation of this function is required to\n * work with a input string length up to 512 MB. */\nsize_t redisPopcount(void *s, long count) {\n    size_t bits = 0;\n    unsigned char *p = s;\n    uint32_t *p4;\n    static const unsigned char bitsinbyte[256] = {0,1,1,2,1,2,2,3,1,2,2,3,2,3,3,4,1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5,1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5,2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5,2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5,2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8};\n\n    /* Count initial bytes not aligned to 32 bit. */\n    while((unsigned long)p & 3 && count) {\n        bits += bitsinbyte[*p++];\n        count--;\n    }\n\n    /* Count bits 28 bytes at a time */\n    p4 = (uint32_t*)p;\n    while(count>=28) {\n        uint32_t aux1, aux2, aux3, aux4, aux5, aux6, aux7;\n\n        aux1 = *p4++;\n        aux2 = *p4++;\n        aux3 = *p4++;\n        aux4 = *p4++;\n        aux5 = *p4++;\n        aux6 = *p4++;\n        aux7 = *p4++;\n        count -= 28;\n\n        aux1 = aux1 - ((aux1 >> 1) & 0x55555555);\n        aux1 = (aux1 & 0x33333333) + ((aux1 >> 2) & 0x33333333);\n        aux2 = aux2 - ((aux2 >> 1) & 0x55555555);\n        aux2 = (aux2 & 0x33333333) + ((aux2 >> 2) & 0x33333333);\n        aux3 = aux3 - ((aux3 >> 1) & 0x55555555);\n        aux3 = (aux3 & 0x33333333) + ((aux3 >> 2) & 0x33333333);\n        aux4 = aux4 - ((aux4 >> 1) & 0x55555555);\n        aux4 = (aux4 & 0x33333333) + ((aux4 >> 2) & 0x33333333);\n        aux5 = aux5 - ((aux5 >> 1) & 0x55555555);\n        aux5 = (aux5 & 0x33333333) + ((aux5 >> 2) & 0x33333333);\n        aux6 = aux6 - ((aux6 >> 1) & 0x55555555);\n        aux6 = (aux6 & 0x33333333) + ((aux6 >> 2) & 0x33333333);\n        aux7 = aux7 - ((aux7 >> 1) & 0x55555555);\n        aux7 = (aux7 & 0x33333333) + ((aux7 >> 2) & 0x33333333);\n        bits += ((((aux1 + (aux1 >> 4)) & 0x0F0F0F0F) +\n                    ((aux2 + (aux2 >> 4)) & 0x0F0F0F0F) +\n                    ((aux3 + (aux3 >> 4)) & 0x0F0F0F0F) +\n                    ((aux4 + (aux4 >> 4)) & 0x0F0F0F0F) +\n                    ((aux5 + (aux5 >> 4)) & 0x0F0F0F0F) +\n                    ((aux6 + (aux6 >> 4)) & 0x0F0F0F0F) +\n                    ((aux7 + (aux7 >> 4)) & 0x0F0F0F0F))* 0x01010101) >> 24;\n    }\n    /* Count the remaining bytes. */\n    p = (unsigned char*)p4;\n    while(count--) bits += bitsinbyte[*p++];\n    return bits;\n}\n\n/* Return the position of the first bit set to one (if 'bit' is 1) or\n * zero (if 'bit' is 0) in the bitmap starting at 's' and long 'count' bytes.\n *\n * The function is guaranteed to return a value >= 0 if 'bit' is 0 since if\n * no zero bit is found, it returns count*8 assuming the string is zero\n * padded on the right. However if 'bit' is 1 it is possible that there is\n * not a single set bit in the bitmap. In this special case -1 is returned. */\nlong redisBitpos(void *s, unsigned long count, int bit) {\n    unsigned long *l;\n    unsigned char *c;\n    unsigned long skipval, word = 0, one;\n    long pos = 0; /* Position of bit, to return to the caller. */\n    unsigned long j;\n\n    /* Process whole words first, seeking for first word that is not\n     * all ones or all zeros respectively if we are lookig for zeros\n     * or ones. This is much faster with large strings having contiguous\n     * blocks of 1 or 0 bits compared to the vanilla bit per bit processing.\n     *\n     * Note that if we start from an address that is not aligned\n     * to sizeof(unsigned long) we consume it byte by byte until it is\n     * aligned. */\n\n    /* Skip initial bits not aligned to sizeof(unsigned long) byte by byte. */\n    skipval = bit ? 0 : UCHAR_MAX;\n    c = (unsigned char*) s;\n    while((unsigned long)c & (sizeof(*l)-1) && count) {\n        if (*c != skipval) break;\n        c++;\n        count--;\n        pos += 8;\n    }\n\n    /* Skip bits with full word step. */\n    skipval = bit ? 0 : ULONG_MAX;\n    l = (unsigned long*) c;\n    while (count >= sizeof(*l)) {\n        if (*l != skipval) break;\n        l++;\n        count -= sizeof(*l);\n        pos += sizeof(*l)*8;\n    }\n\n    /* Load bytes into \"word\" considering the first byte as the most significant\n     * (we basically consider it as written in big endian, since we consider the\n     * string as a set of bits from left to right, with the first bit at position\n     * zero.\n     *\n     * Note that the loading is designed to work even when the bytes left\n     * (count) are less than a full word. We pad it with zero on the right. */\n    c = (unsigned char*)l;\n    for (j = 0; j < sizeof(*l); j++) {\n        word <<= 8;\n        if (count) {\n            word |= *c;\n            c++;\n            count--;\n        }\n    }\n\n    /* Special case:\n     * If bits in the string are all zero and we are looking for one,\n     * return -1 to signal that there is not a single \"1\" in the whole\n     * string. This can't happen when we are looking for \"0\" as we assume\n     * that the right of the string is zero padded. */\n    if (bit == 1 && word == 0) return -1;\n\n    /* Last word left, scan bit by bit. The first thing we need is to\n     * have a single \"1\" set in the most significant position in an\n     * unsigned long. We don't know the size of the long so we use a\n     * simple trick. */\n    one = ULONG_MAX; /* All bits set to 1.*/\n    one >>= 1;       /* All bits set to 1 but the MSB. */\n    one = ~one;      /* All bits set to 0 but the MSB. */\n\n    while(one) {\n        if (((one & word) != 0) == bit) return pos;\n        pos++;\n        one >>= 1;\n    }\n\n    /* If we reached this point, there is a bug in the algorithm, since\n     * the case of no match is handled as a special case before. */\n    serverPanic(\"End of redisBitpos() reached.\");\n    return 0; /* Just to avoid warnings. */\n}\n\n/* The following set.*Bitfield and get.*Bitfield functions implement setting\n * and getting arbitrary size (up to 64 bits) signed and unsigned integers\n * at arbitrary positions into a bitmap.\n *\n * The representation considers the bitmap as having the bit number 0 to be\n * the most significant bit of the first byte, and so forth, so for example\n * setting a 5 bits unsigned integer to value 23 at offset 7 into a bitmap\n * previously set to all zeroes, will produce the following representation:\n *\n * +--------+--------+\n * |00000001|01110000|\n * +--------+--------+\n *\n * When offsets and integer sizes are aligned to bytes boundaries, this is the\n * same as big endian, however when such alignment does not exist, its important\n * to also understand how the bits inside a byte are ordered.\n *\n * Note that this format follows the same convention as SETBIT and related\n * commands.\n */\n\nvoid setUnsignedBitfield(unsigned char *p, uint64_t offset, uint64_t bits, uint64_t value) {\n    uint64_t byte, bit, byteval, bitval, j;\n\n    for (j = 0; j < bits; j++) {\n        bitval = (value & ((uint64_t)1<<(bits-1-j))) != 0;\n        byte = offset >> 3;\n        bit = 7 - (offset & 0x7);\n        byteval = p[byte];\n        byteval &= ~(1 << bit);\n        byteval |= bitval << bit;\n        p[byte] = byteval & 0xff;\n        offset++;\n    }\n}\n\nvoid setSignedBitfield(unsigned char *p, uint64_t offset, uint64_t bits, int64_t value) {\n    uint64_t uv = value; /* Casting will add UINT64_MAX + 1 if v is negative. */\n    setUnsignedBitfield(p,offset,bits,uv);\n}\n\nuint64_t getUnsignedBitfield(unsigned char *p, uint64_t offset, uint64_t bits) {\n    uint64_t byte, bit, byteval, bitval, j, value = 0;\n\n    for (j = 0; j < bits; j++) {\n        byte = offset >> 3;\n        bit = 7 - (offset & 0x7);\n        byteval = p[byte];\n        bitval = (byteval >> bit) & 1;\n        value = (value<<1) | bitval;\n        offset++;\n    }\n    return value;\n}\n\nint64_t getSignedBitfield(unsigned char *p, uint64_t offset, uint64_t bits) {\n    int64_t value;\n    union {uint64_t u; int64_t i;} conv;\n\n    /* Converting from unsigned to signed is undefined when the value does\n     * not fit, however here we assume two's complement and the original value\n     * was obtained from signed -> unsigned conversion, so we'll find the\n     * most significant bit set if the original value was negative.\n     *\n     * Note that two's complement is mandatory for exact-width types\n     * according to the C99 standard. */\n    conv.u = getUnsignedBitfield(p,offset,bits);\n    value = conv.i;\n\n    /* If the top significant bit is 1, propagate it to all the\n     * higher bits for two's complement representation of signed\n     * integers. */\n    if (value & ((uint64_t)1 << (bits-1)))\n        value |= ((uint64_t)-1) << bits;\n    return value;\n}\n\n/* The following two functions detect overflow of a value in the context\n * of storing it as an unsigned or signed integer with the specified\n * number of bits. The functions both take the value and a possible increment.\n * If no overflow could happen and the value+increment fit inside the limits,\n * then zero is returned, otherwise in case of overflow, 1 is returned,\n * otherwise in case of underflow, -1 is returned.\n *\n * When non-zero is returned (oferflow or underflow), if not NULL, *limit is\n * set to the value the operation should result when an overflow happens,\n * depending on the specified overflow semantics:\n *\n * For BFOVERFLOW_SAT if 1 is returned, *limit it is set maximum value that\n * you can store in that integer. when -1 is returned, *limit is set to the\n * minimum value that an integer of that size can represent.\n *\n * For BFOVERFLOW_WRAP *limit is set by performing the operation in order to\n * \"wrap\" around towards zero for unsigned integers, or towards the most\n * negative number that is possible to represent for signed integers. */\n\n#define BFOVERFLOW_WRAP 0\n#define BFOVERFLOW_SAT 1\n#define BFOVERFLOW_FAIL 2 /* Used by the BITFIELD command implementation. */\n\nint checkUnsignedBitfieldOverflow(uint64_t value, int64_t incr, uint64_t bits, int owtype, uint64_t *limit) {\n    uint64_t max = (bits == 64) ? UINT64_MAX : (((uint64_t)1<<bits)-1);\n    int64_t maxincr = max-value;\n    int64_t minincr = -value;\n\n    if (value > max || (incr > 0 && incr > maxincr)) {\n        if (limit) {\n            if (owtype == BFOVERFLOW_WRAP) {\n                goto handle_wrap;\n            } else if (owtype == BFOVERFLOW_SAT) {\n                *limit = max;\n            }\n        }\n        return 1;\n    } else if (incr < 0 && incr < minincr) {\n        if (limit) {\n            if (owtype == BFOVERFLOW_WRAP) {\n                goto handle_wrap;\n            } else if (owtype == BFOVERFLOW_SAT) {\n                *limit = 0;\n            }\n        }\n        return -1;\n    }\n    return 0;\n\nhandle_wrap:\n    {\n        uint64_t mask = ((uint64_t)-1) << bits;\n        uint64_t res = value+incr;\n\n        res &= ~mask;\n        *limit = res;\n    }\n    return 1;\n}\n\nint checkSignedBitfieldOverflow(int64_t value, int64_t incr, uint64_t bits, int owtype, int64_t *limit) {\n    int64_t max = (bits == 64) ? INT64_MAX : (((int64_t)1<<(bits-1))-1);\n    int64_t min = (-max)-1;\n\n    /* Note that maxincr and minincr could overflow, but we use the values\n     * only after checking 'value' range, so when we use it no overflow\n     * happens. */\n    int64_t maxincr = max-value;\n    int64_t minincr = min-value;\n\n    if (value > max || (bits != 64 && incr > maxincr) || (value >= 0 && incr > 0 && incr > maxincr))\n    {\n        if (limit) {\n            if (owtype == BFOVERFLOW_WRAP) {\n                goto handle_wrap;\n            } else if (owtype == BFOVERFLOW_SAT) {\n                *limit = max;\n            }\n        }\n        return 1;\n    } else if (value < min || (bits != 64 && incr < minincr) || (value < 0 && incr < 0 && incr < minincr)) {\n        if (limit) {\n            if (owtype == BFOVERFLOW_WRAP) {\n                goto handle_wrap;\n            } else if (owtype == BFOVERFLOW_SAT) {\n                *limit = min;\n            }\n        }\n        return -1;\n    }\n    return 0;\n\nhandle_wrap:\n    {\n        uint64_t mask = ((uint64_t)-1) << bits;\n        uint64_t msb = (uint64_t)1 << (bits-1);\n        uint64_t a = value, b = incr, c;\n        c = a+b; /* Perform addition as unsigned so that's defined. */\n\n        /* If the sign bit is set, propagate to all the higher order\n         * bits, to cap the negative value. If it's clear, mask to\n         * the positive integer limit. */\n        if (c & msb) {\n            c |= mask;\n        } else {\n            c &= ~mask;\n        }\n        *limit = c;\n    }\n    return 1;\n}\n\n/* Debugging function. Just show bits in the specified bitmap. Not used\n * but here for not having to rewrite it when debugging is needed. */\nvoid printBits(unsigned char *p, unsigned long count) {\n    unsigned long j, i, byte;\n\n    for (j = 0; j < count; j++) {\n        byte = p[j];\n        for (i = 0x80; i > 0; i /= 2)\n            printf(\"%c\", (byte & i) ? '1' : '0');\n        printf(\"|\");\n    }\n    printf(\"\\n\");\n}\n\n/* -----------------------------------------------------------------------------\n * Bits related string commands: GETBIT, SETBIT, BITCOUNT, BITOP.\n * -------------------------------------------------------------------------- */\n\n#define BITOP_AND   0\n#define BITOP_OR    1\n#define BITOP_XOR   2\n#define BITOP_NOT   3\n\n#define BITFIELDOP_GET 0\n#define BITFIELDOP_SET 1\n#define BITFIELDOP_INCRBY 2\n\n/* This helper function used by GETBIT / SETBIT parses the bit offset argument\n * making sure an error is returned if it is negative or if it overflows\n * Redis 512 MB limit for the string value.\n *\n * If the 'hash' argument is true, and 'bits is positive, then the command\n * will also parse bit offsets prefixed by \"#\". In such a case the offset\n * is multiplied by 'bits'. This is useful for the BITFIELD command. */\nint getBitOffsetFromArgument(client *c, robj *o, size_t *offset, int hash, int bits) {\n    long long loffset;\n    char *err = \"bit offset is not an integer or out of range\";\n    char *p = o->ptr;\n    size_t plen = sdslen(p);\n    int usehash = 0;\n\n    /* Handle #<offset> form. */\n    if (p[0] == '#' && hash && bits > 0) usehash = 1;\n\n    if (string2ll(p+usehash,plen-usehash,&loffset) == 0) {\n        addReplyError(c,err);\n        return C_ERR;\n    }\n\n    /* Adjust the offset by 'bits' for #<offset> form. */\n    if (usehash) loffset *= bits;\n\n    /* Limit offset to 512MB in bytes */\n    if ((loffset < 0) || ((unsigned long long)loffset >> 3) >= (512*1024*1024))\n    {\n        addReplyError(c,err);\n        return C_ERR;\n    }\n\n    *offset = (size_t)loffset;\n    return C_OK;\n}\n\n/* This helper function for BITFIELD parses a bitfield type in the form\n * <sign><bits> where sign is 'u' or 'i' for unsigned and signed, and\n * the bits is a value between 1 and 64. However 64 bits unsigned integers\n * are reported as an error because of current limitations of Redis protocol\n * to return unsigned integer values greater than INT64_MAX.\n *\n * On error C_ERR is returned and an error is sent to the client. */\nint getBitfieldTypeFromArgument(client *c, robj *o, int *sign, int *bits) {\n    char *p = o->ptr;\n    char *err = \"Invalid bitfield type. Use something like i16 u8. Note that u64 is not supported but i64 is.\";\n    long long llbits;\n\n    if (p[0] == 'i') {\n        *sign = 1;\n    } else if (p[0] == 'u') {\n        *sign = 0;\n    } else {\n        addReplyError(c,err);\n        return C_ERR;\n    }\n\n    if ((string2ll(p+1,strlen(p+1),&llbits)) == 0 ||\n        llbits < 1 ||\n        (*sign == 1 && llbits > 64) ||\n        (*sign == 0 && llbits > 63))\n    {\n        addReplyError(c,err);\n        return C_ERR;\n    }\n    *bits = llbits;\n    return C_OK;\n}\n\n/* This is an helper function for commands implementations that need to write\n * bits to a string object. The command creates or pad with zeroes the string\n * so that the 'maxbit' bit can be addressed. The object is finally\n * returned. Otherwise if the key holds a wrong type NULL is returned and\n * an error is sent to the client. */\nrobj *lookupStringForBitCommand(client *c, size_t maxbit) {\n    size_t byte = maxbit >> 3;\n    robj *o = lookupKeyWrite(c->db,c->argv[1]);\n\n    if (o == NULL) {\n        o = createObject(OBJ_STRING,sdsnewlen(NULL, byte+1));\n        dbAdd(c->db,c->argv[1],o);\n    } else {\n        if (checkType(c,o,OBJ_STRING)) return NULL;\n        o = dbUnshareStringValue(c->db,c->argv[1],o);\n        o->ptr = sdsgrowzero(o->ptr,byte+1);\n    }\n    return o;\n}\n\n/* Return a pointer to the string object content, and stores its length\n * in 'len'. The user is required to pass (likely stack allocated) buffer\n * 'llbuf' of at least LONG_STR_SIZE bytes. Such a buffer is used in the case\n * the object is integer encoded in order to provide the representation\n * without usign heap allocation.\n *\n * The function returns the pointer to the object array of bytes representing\n * the string it contains, that may be a pointer to 'llbuf' or to the\n * internal object representation. As a side effect 'len' is filled with\n * the length of such buffer.\n *\n * If the source object is NULL the function is guaranteed to return NULL\n * and set 'len' to 0. */\nunsigned char *getObjectReadOnlyString(robj *o, long *len, char *llbuf) {\n    serverAssert(o->type == OBJ_STRING);\n    unsigned char *p = NULL;\n\n    /* Set the 'p' pointer to the string, that can be just a stack allocated\n     * array if our string was integer encoded. */\n    if (o && o->encoding == OBJ_ENCODING_INT) {\n        p = (unsigned char*) llbuf;\n        if (len) *len = ll2string(llbuf,LONG_STR_SIZE,(long)o->ptr);\n    } else if (o) {\n        p = (unsigned char*) o->ptr;\n        if (len) *len = sdslen(o->ptr);\n    } else {\n        if (len) *len = 0;\n    }\n    return p;\n}\n\n/* SETBIT key offset bitvalue */\nvoid setbitCommand(client *c) {\n    robj *o;\n    char *err = \"bit is not an integer or out of range\";\n    size_t bitoffset;\n    ssize_t byte, bit;\n    int byteval, bitval;\n    long on;\n\n    if (getBitOffsetFromArgument(c,c->argv[2],&bitoffset,0,0) != C_OK)\n        return;\n\n    if (getLongFromObjectOrReply(c,c->argv[3],&on,err) != C_OK)\n        return;\n\n    /* Bits can only be set or cleared... */\n    if (on & ~1) {\n        addReplyError(c,err);\n        return;\n    }\n\n    if ((o = lookupStringForBitCommand(c,bitoffset)) == NULL) return;\n\n    /* Get current values */\n    byte = bitoffset >> 3;\n    byteval = ((uint8_t*)o->ptr)[byte];\n    bit = 7 - (bitoffset & 0x7);\n    bitval = byteval & (1 << bit);\n\n    /* Update byte with new bit value and return original value */\n    byteval &= ~(1 << bit);\n    byteval |= ((on & 0x1) << bit);\n    ((uint8_t*)o->ptr)[byte] = byteval;\n    signalModifiedKey(c->db,c->argv[1]);\n    notifyKeyspaceEvent(NOTIFY_STRING,\"setbit\",c->argv[1],c->db->id);\n    server.dirty++;\n    addReply(c, bitval ? shared.cone : shared.czero);\n}\n\n/* GETBIT key offset */\nvoid getbitCommand(client *c) {\n    robj *o;\n    char llbuf[32];\n    size_t bitoffset;\n    size_t byte, bit;\n    size_t bitval = 0;\n\n    if (getBitOffsetFromArgument(c,c->argv[2],&bitoffset,0,0) != C_OK)\n        return;\n\n    if ((o = lookupKeyReadOrReply(c,c->argv[1],shared.czero)) == NULL ||\n        checkType(c,o,OBJ_STRING)) return;\n\n    byte = bitoffset >> 3;\n    bit = 7 - (bitoffset & 0x7);\n    if (sdsEncodedObject(o)) {\n        if (byte < sdslen(o->ptr))\n            bitval = ((uint8_t*)o->ptr)[byte] & (1 << bit);\n    } else {\n        if (byte < (size_t)ll2string(llbuf,sizeof(llbuf),(long)o->ptr))\n            bitval = llbuf[byte] & (1 << bit);\n    }\n\n    addReply(c, bitval ? shared.cone : shared.czero);\n}\n\n/* BITOP op_name target_key src_key1 src_key2 src_key3 ... src_keyN */\nvoid bitopCommand(client *c) {\n    char *opname = c->argv[1]->ptr;\n    robj *o, *targetkey = c->argv[2];\n    unsigned long op, j, numkeys;\n    robj **objects;      /* Array of source objects. */\n    unsigned char **src; /* Array of source strings pointers. */\n    unsigned long *len, maxlen = 0; /* Array of length of src strings,\n                                       and max len. */\n    unsigned long minlen = 0;    /* Min len among the input keys. */\n    unsigned char *res = NULL; /* Resulting string. */\n\n    /* Parse the operation name. */\n    if ((opname[0] == 'a' || opname[0] == 'A') && !strcasecmp(opname,\"and\"))\n        op = BITOP_AND;\n    else if((opname[0] == 'o' || opname[0] == 'O') && !strcasecmp(opname,\"or\"))\n        op = BITOP_OR;\n    else if((opname[0] == 'x' || opname[0] == 'X') && !strcasecmp(opname,\"xor\"))\n        op = BITOP_XOR;\n    else if((opname[0] == 'n' || opname[0] == 'N') && !strcasecmp(opname,\"not\"))\n        op = BITOP_NOT;\n    else {\n        addReply(c,shared.syntaxerr);\n        return;\n    }\n\n    /* Sanity check: NOT accepts only a single key argument. */\n    if (op == BITOP_NOT && c->argc != 4) {\n        addReplyError(c,\"BITOP NOT must be called with a single source key.\");\n        return;\n    }\n\n    /* Lookup keys, and store pointers to the string objects into an array. */\n    numkeys = c->argc - 3;\n    src = zmalloc(sizeof(unsigned char*) * numkeys);\n    len = zmalloc(sizeof(long) * numkeys);\n    objects = zmalloc(sizeof(robj*) * numkeys);\n    for (j = 0; j < numkeys; j++) {\n        o = lookupKeyRead(c->db,c->argv[j+3]);\n        /* Handle non-existing keys as empty strings. */\n        if (o == NULL) {\n            objects[j] = NULL;\n            src[j] = NULL;\n            len[j] = 0;\n            minlen = 0;\n            continue;\n        }\n        /* Return an error if one of the keys is not a string. */\n        if (checkType(c,o,OBJ_STRING)) {\n            unsigned long i;\n            for (i = 0; i < j; i++) {\n                if (objects[i])\n                    decrRefCount(objects[i]);\n            }\n            zfree(src);\n            zfree(len);\n            zfree(objects);\n            return;\n        }\n        objects[j] = getDecodedObject(o);\n        src[j] = objects[j]->ptr;\n        len[j] = sdslen(objects[j]->ptr);\n        if (len[j] > maxlen) maxlen = len[j];\n        if (j == 0 || len[j] < minlen) minlen = len[j];\n    }\n\n    /* Compute the bit operation, if at least one string is not empty. */\n    if (maxlen) {\n        res = (unsigned char*) sdsnewlen(NULL,maxlen);\n        unsigned char output, byte;\n        unsigned long i;\n\n        /* Fast path: as far as we have data for all the input bitmaps we\n         * can take a fast path that performs much better than the\n         * vanilla algorithm. */\n        j = 0;\n        if (minlen >= sizeof(unsigned long)*4 && numkeys <= 16) {\n            unsigned long *lp[16];\n            unsigned long *lres = (unsigned long*) res;\n\n            /* Note: sds pointer is always aligned to 8 byte boundary. */\n            memcpy(lp,src,sizeof(unsigned long*)*numkeys);\n            memcpy(res,src[0],minlen);\n\n            /* Different branches per different operations for speed (sorry). */\n            if (op == BITOP_AND) {\n                while(minlen >= sizeof(unsigned long)*4) {\n                    for (i = 1; i < numkeys; i++) {\n                        lres[0] &= lp[i][0];\n                        lres[1] &= lp[i][1];\n                        lres[2] &= lp[i][2];\n                        lres[3] &= lp[i][3];\n                        lp[i]+=4;\n                    }\n                    lres+=4;\n                    j += sizeof(unsigned long)*4;\n                    minlen -= sizeof(unsigned long)*4;\n                }\n            } else if (op == BITOP_OR) {\n                while(minlen >= sizeof(unsigned long)*4) {\n                    for (i = 1; i < numkeys; i++) {\n                        lres[0] |= lp[i][0];\n                        lres[1] |= lp[i][1];\n                        lres[2] |= lp[i][2];\n                        lres[3] |= lp[i][3];\n                        lp[i]+=4;\n                    }\n                    lres+=4;\n                    j += sizeof(unsigned long)*4;\n                    minlen -= sizeof(unsigned long)*4;\n                }\n            } else if (op == BITOP_XOR) {\n                while(minlen >= sizeof(unsigned long)*4) {\n                    for (i = 1; i < numkeys; i++) {\n                        lres[0] ^= lp[i][0];\n                        lres[1] ^= lp[i][1];\n                        lres[2] ^= lp[i][2];\n                        lres[3] ^= lp[i][3];\n                        lp[i]+=4;\n                    }\n                    lres+=4;\n                    j += sizeof(unsigned long)*4;\n                    minlen -= sizeof(unsigned long)*4;\n                }\n            } else if (op == BITOP_NOT) {\n                while(minlen >= sizeof(unsigned long)*4) {\n                    lres[0] = ~lres[0];\n                    lres[1] = ~lres[1];\n                    lres[2] = ~lres[2];\n                    lres[3] = ~lres[3];\n                    lres+=4;\n                    j += sizeof(unsigned long)*4;\n                    minlen -= sizeof(unsigned long)*4;\n                }\n            }\n        }\n\n        /* j is set to the next byte to process by the previous loop. */\n        for (; j < maxlen; j++) {\n            output = (len[0] <= j) ? 0 : src[0][j];\n            if (op == BITOP_NOT) output = ~output;\n            for (i = 1; i < numkeys; i++) {\n                byte = (len[i] <= j) ? 0 : src[i][j];\n                switch(op) {\n                case BITOP_AND: output &= byte; break;\n                case BITOP_OR:  output |= byte; break;\n                case BITOP_XOR: output ^= byte; break;\n                }\n            }\n            res[j] = output;\n        }\n    }\n    for (j = 0; j < numkeys; j++) {\n        if (objects[j])\n            decrRefCount(objects[j]);\n    }\n    zfree(src);\n    zfree(len);\n    zfree(objects);\n\n    /* Store the computed value into the target key */\n    if (maxlen) {\n        o = createObject(OBJ_STRING,res);\n        setKey(c->db,targetkey,o);\n        notifyKeyspaceEvent(NOTIFY_STRING,\"set\",targetkey,c->db->id);\n        decrRefCount(o);\n    } else if (dbDelete(c->db,targetkey)) {\n        signalModifiedKey(c->db,targetkey);\n        notifyKeyspaceEvent(NOTIFY_GENERIC,\"del\",targetkey,c->db->id);\n    }\n    server.dirty++;\n    addReplyLongLong(c,maxlen); /* Return the output string length in bytes. */\n}\n\n/* BITCOUNT key [start end] */\nvoid bitcountCommand(client *c) {\n    robj *o;\n    long start, end, strlen;\n    unsigned char *p;\n    char llbuf[LONG_STR_SIZE];\n\n    /* Lookup, check for type, and return 0 for non existing keys. */\n    if ((o = lookupKeyReadOrReply(c,c->argv[1],shared.czero)) == NULL ||\n        checkType(c,o,OBJ_STRING)) return;\n    p = getObjectReadOnlyString(o,&strlen,llbuf);\n\n    /* Parse start/end range if any. */\n    if (c->argc == 4) {\n        if (getLongFromObjectOrReply(c,c->argv[2],&start,NULL) != C_OK)\n            return;\n        if (getLongFromObjectOrReply(c,c->argv[3],&end,NULL) != C_OK)\n            return;\n        /* Convert negative indexes */\n        if (start < 0 && end < 0 && start > end) {\n            addReply(c,shared.czero);\n            return;\n        }\n        if (start < 0) start = strlen+start;\n        if (end < 0) end = strlen+end;\n        if (start < 0) start = 0;\n        if (end < 0) end = 0;\n        if (end >= strlen) end = strlen-1;\n    } else if (c->argc == 2) {\n        /* The whole string. */\n        start = 0;\n        end = strlen-1;\n    } else {\n        /* Syntax error. */\n        addReply(c,shared.syntaxerr);\n        return;\n    }\n\n    /* Precondition: end >= 0 && end < strlen, so the only condition where\n     * zero can be returned is: start > end. */\n    if (start > end) {\n        addReply(c,shared.czero);\n    } else {\n        long bytes = end-start+1;\n\n        addReplyLongLong(c,redisPopcount(p+start,bytes));\n    }\n}\n\n/* BITPOS key bit [start [end]] */\nvoid bitposCommand(client *c) {\n    robj *o;\n    long bit, start, end, strlen;\n    unsigned char *p;\n    char llbuf[LONG_STR_SIZE];\n    int end_given = 0;\n\n    /* Parse the bit argument to understand what we are looking for, set\n     * or clear bits. */\n    if (getLongFromObjectOrReply(c,c->argv[2],&bit,NULL) != C_OK)\n        return;\n    if (bit != 0 && bit != 1) {\n        addReplyError(c, \"The bit argument must be 1 or 0.\");\n        return;\n    }\n\n    /* If the key does not exist, from our point of view it is an infinite\n     * array of 0 bits. If the user is looking for the fist clear bit return 0,\n     * If the user is looking for the first set bit, return -1. */\n    if ((o = lookupKeyRead(c->db,c->argv[1])) == NULL) {\n        addReplyLongLong(c, bit ? -1 : 0);\n        return;\n    }\n    if (checkType(c,o,OBJ_STRING)) return;\n    p = getObjectReadOnlyString(o,&strlen,llbuf);\n\n    /* Parse start/end range if any. */\n    if (c->argc == 4 || c->argc == 5) {\n        if (getLongFromObjectOrReply(c,c->argv[3],&start,NULL) != C_OK)\n            return;\n        if (c->argc == 5) {\n            if (getLongFromObjectOrReply(c,c->argv[4],&end,NULL) != C_OK)\n                return;\n            end_given = 1;\n        } else {\n            end = strlen-1;\n        }\n        /* Convert negative indexes */\n        if (start < 0) start = strlen+start;\n        if (end < 0) end = strlen+end;\n        if (start < 0) start = 0;\n        if (end < 0) end = 0;\n        if (end >= strlen) end = strlen-1;\n    } else if (c->argc == 3) {\n        /* The whole string. */\n        start = 0;\n        end = strlen-1;\n    } else {\n        /* Syntax error. */\n        addReply(c,shared.syntaxerr);\n        return;\n    }\n\n    /* For empty ranges (start > end) we return -1 as an empty range does\n     * not contain a 0 nor a 1. */\n    if (start > end) {\n        addReplyLongLong(c, -1);\n    } else {\n        long bytes = end-start+1;\n        long pos = redisBitpos(p+start,bytes,bit);\n\n        /* If we are looking for clear bits, and the user specified an exact\n         * range with start-end, we can't consider the right of the range as\n         * zero padded (as we do when no explicit end is given).\n         *\n         * So if redisBitpos() returns the first bit outside the range,\n         * we return -1 to the caller, to mean, in the specified range there\n         * is not a single \"0\" bit. */\n        if (end_given && bit == 0 && pos == bytes*8) {\n            addReplyLongLong(c,-1);\n            return;\n        }\n        if (pos != -1) pos += start*8; /* Adjust for the bytes we skipped. */\n        addReplyLongLong(c,pos);\n    }\n}\n\n/* BITFIELD key subcommmand-1 arg ... subcommand-2 arg ... subcommand-N ...\n *\n * Supported subcommands:\n *\n * GET <type> <offset>\n * SET <type> <offset> <value>\n * INCRBY <type> <offset> <increment>\n * OVERFLOW [WRAP|SAT|FAIL]\n */\n\nstruct bitfieldOp {\n    uint64_t offset;    /* Bitfield offset. */\n    int64_t i64;        /* Increment amount (INCRBY) or SET value */\n    int opcode;         /* Operation id. */\n    int owtype;         /* Overflow type to use. */\n    int bits;           /* Integer bitfield bits width. */\n    int sign;           /* True if signed, otherwise unsigned op. */\n};\n\nvoid bitfieldCommand(client *c) {\n    robj *o;\n    size_t bitoffset;\n    int j, numops = 0, changes = 0;\n    struct bitfieldOp *ops = NULL; /* Array of ops to execute at end. */\n    int owtype = BFOVERFLOW_WRAP; /* Overflow type. */\n    int readonly = 1;\n    long higest_write_offset = 0;\n\n    for (j = 2; j < c->argc; j++) {\n        int remargs = c->argc-j-1; /* Remaining args other than current. */\n        char *subcmd = c->argv[j]->ptr; /* Current command name. */\n        int opcode; /* Current operation code. */\n        long long i64 = 0;  /* Signed SET value. */\n        int sign = 0; /* Signed or unsigned type? */\n        int bits = 0; /* Bitfield width in bits. */\n\n        if (!strcasecmp(subcmd,\"get\") && remargs >= 2)\n            opcode = BITFIELDOP_GET;\n        else if (!strcasecmp(subcmd,\"set\") && remargs >= 3)\n            opcode = BITFIELDOP_SET;\n        else if (!strcasecmp(subcmd,\"incrby\") && remargs >= 3)\n            opcode = BITFIELDOP_INCRBY;\n        else if (!strcasecmp(subcmd,\"overflow\") && remargs >= 1) {\n            char *owtypename = c->argv[j+1]->ptr;\n            j++;\n            if (!strcasecmp(owtypename,\"wrap\"))\n                owtype = BFOVERFLOW_WRAP;\n            else if (!strcasecmp(owtypename,\"sat\"))\n                owtype = BFOVERFLOW_SAT;\n            else if (!strcasecmp(owtypename,\"fail\"))\n                owtype = BFOVERFLOW_FAIL;\n            else {\n                addReplyError(c,\"Invalid OVERFLOW type specified\");\n                zfree(ops);\n                return;\n            }\n            continue;\n        } else {\n            addReply(c,shared.syntaxerr);\n            zfree(ops);\n            return;\n        }\n\n        /* Get the type and offset arguments, common to all the ops. */\n        if (getBitfieldTypeFromArgument(c,c->argv[j+1],&sign,&bits) != C_OK) {\n            zfree(ops);\n            return;\n        }\n\n        if (getBitOffsetFromArgument(c,c->argv[j+2],&bitoffset,1,bits) != C_OK){\n            zfree(ops);\n            return;\n        }\n\n        if (opcode != BITFIELDOP_GET) {\n            readonly = 0;\n            higest_write_offset = bitoffset + bits - 1;\n            /* INCRBY and SET require another argument. */\n            if (getLongLongFromObjectOrReply(c,c->argv[j+3],&i64,NULL) != C_OK){\n                zfree(ops);\n                return;\n            }\n        }\n\n        /* Populate the array of operations we'll process. */\n        ops = zrealloc(ops,sizeof(*ops)*(numops+1));\n        ops[numops].offset = bitoffset;\n        ops[numops].i64 = i64;\n        ops[numops].opcode = opcode;\n        ops[numops].owtype = owtype;\n        ops[numops].bits = bits;\n        ops[numops].sign = sign;\n        numops++;\n\n        j += 3 - (opcode == BITFIELDOP_GET);\n    }\n\n    if (readonly) {\n        /* Lookup for read is ok if key doesn't exit, but errors\n         * if it's not a string. */\n        o = lookupKeyRead(c->db,c->argv[1]);\n        if (o != NULL && checkType(c,o,OBJ_STRING)) return;\n    } else {\n        /* Lookup by making room up to the farest bit reached by\n         * this operation. */\n        if ((o = lookupStringForBitCommand(c,\n            higest_write_offset)) == NULL) return;\n    }\n\n    addReplyMultiBulkLen(c,numops);\n\n    /* Actually process the operations. */\n    for (j = 0; j < numops; j++) {\n        struct bitfieldOp *thisop = ops+j;\n\n        /* Execute the operation. */\n        if (thisop->opcode == BITFIELDOP_SET ||\n            thisop->opcode == BITFIELDOP_INCRBY)\n        {\n            /* SET and INCRBY: We handle both with the same code path\n             * for simplicity. SET return value is the previous value so\n             * we need fetch & store as well. */\n\n            /* We need two different but very similar code paths for signed\n             * and unsigned operations, since the set of functions to get/set\n             * the integers and the used variables types are different. */\n            if (thisop->sign) {\n                int64_t oldval, newval, wrapped, retval;\n                int overflow;\n\n                oldval = getSignedBitfield(o->ptr,thisop->offset,\n                        thisop->bits);\n\n                if (thisop->opcode == BITFIELDOP_INCRBY) {\n                    newval = oldval + thisop->i64;\n                    overflow = checkSignedBitfieldOverflow(oldval,\n                            thisop->i64,thisop->bits,thisop->owtype,&wrapped);\n                    if (overflow) newval = wrapped;\n                    retval = newval;\n                } else {\n                    newval = thisop->i64;\n                    overflow = checkSignedBitfieldOverflow(newval,\n                            0,thisop->bits,thisop->owtype,&wrapped);\n                    if (overflow) newval = wrapped;\n                    retval = oldval;\n                }\n\n                /* On overflow of type is \"FAIL\", don't write and return\n                 * NULL to signal the condition. */\n                if (!(overflow && thisop->owtype == BFOVERFLOW_FAIL)) {\n                    addReplyLongLong(c,retval);\n                    setSignedBitfield(o->ptr,thisop->offset,\n                                      thisop->bits,newval);\n                } else {\n                    addReply(c,shared.nullbulk);\n                }\n            } else {\n                uint64_t oldval, newval, wrapped, retval;\n                int overflow;\n\n                oldval = getUnsignedBitfield(o->ptr,thisop->offset,\n                        thisop->bits);\n\n                if (thisop->opcode == BITFIELDOP_INCRBY) {\n                    newval = oldval + thisop->i64;\n                    overflow = checkUnsignedBitfieldOverflow(oldval,\n                            thisop->i64,thisop->bits,thisop->owtype,&wrapped);\n                    if (overflow) newval = wrapped;\n                    retval = newval;\n                } else {\n                    newval = thisop->i64;\n                    overflow = checkUnsignedBitfieldOverflow(newval,\n                            0,thisop->bits,thisop->owtype,&wrapped);\n                    if (overflow) newval = wrapped;\n                    retval = oldval;\n                }\n                /* On overflow of type is \"FAIL\", don't write and return\n                 * NULL to signal the condition. */\n                if (!(overflow && thisop->owtype == BFOVERFLOW_FAIL)) {\n                    addReplyLongLong(c,retval);\n                    setUnsignedBitfield(o->ptr,thisop->offset,\n                                        thisop->bits,newval);\n                } else {\n                    addReply(c,shared.nullbulk);\n                }\n            }\n            changes++;\n        } else {\n            /* GET */\n            unsigned char buf[9];\n            long strlen = 0;\n            unsigned char *src = NULL;\n            char llbuf[LONG_STR_SIZE];\n\n            if (o != NULL)\n                src = getObjectReadOnlyString(o,&strlen,llbuf);\n\n            /* For GET we use a trick: before executing the operation\n             * copy up to 9 bytes to a local buffer, so that we can easily\n             * execute up to 64 bit operations that are at actual string\n             * object boundaries. */\n            memset(buf,0,9);\n            int i;\n            size_t byte = thisop->offset >> 3;\n            for (i = 0; i < 9; i++) {\n                if (src == NULL || i+byte >= (size_t)strlen) break;\n                buf[i] = src[i+byte];\n            }\n\n            /* Now operate on the copied buffer which is guaranteed\n             * to be zero-padded. */\n            if (thisop->sign) {\n                int64_t val = getSignedBitfield(buf,thisop->offset-(byte*8),\n                                            thisop->bits);\n                addReplyLongLong(c,val);\n            } else {\n                uint64_t val = getUnsignedBitfield(buf,thisop->offset-(byte*8),\n                                            thisop->bits);\n                addReplyLongLong(c,val);\n            }\n        }\n    }\n\n    if (changes) {\n        signalModifiedKey(c->db,c->argv[1]);\n        notifyKeyspaceEvent(NOTIFY_STRING,\"setbit\",c->argv[1],c->db->id);\n        server.dirty += changes;\n    }\n    zfree(ops);\n}\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/src/blocked.c",
    "content": "/* blocked.c - generic support for blocking operations like BLPOP & WAIT.\n *\n * Copyright (c) 2009-2012, Salvatore Sanfilippo <antirez at gmail dot com>\n * All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions are met:\n *\n *   * Redistributions of source code must retain the above copyright notice,\n *     this list of conditions and the following disclaimer.\n *   * Redistributions in binary form must reproduce the above copyright\n *     notice, this list of conditions and the following disclaimer in the\n *     documentation and/or other materials provided with the distribution.\n *   * Neither the name of Redis nor the names of its contributors may be used\n *     to endorse or promote products derived from this software without\n *     specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\"\n * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\n * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE\n * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR\n * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF\n * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS\n * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN\n * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)\n * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE\n * POSSIBILITY OF SUCH DAMAGE.\n *\n * ---------------------------------------------------------------------------\n *\n * API:\n *\n * getTimeoutFromObjectOrReply() is just an utility function to parse a\n * timeout argument since blocking operations usually require a timeout.\n *\n * blockClient() set the CLIENT_BLOCKED flag in the client, and set the\n * specified block type 'btype' filed to one of BLOCKED_* macros.\n *\n * unblockClient() unblocks the client doing the following:\n * 1) It calls the btype-specific function to cleanup the state.\n * 2) It unblocks the client by unsetting the CLIENT_BLOCKED flag.\n * 3) It puts the client into a list of just unblocked clients that are\n *    processed ASAP in the beforeSleep() event loop callback, so that\n *    if there is some query buffer to process, we do it. This is also\n *    required because otherwise there is no 'readable' event fired, we\n *    already read the pending commands. We also set the CLIENT_UNBLOCKED\n *    flag to remember the client is in the unblocked_clients list.\n *\n * processUnblockedClients() is called inside the beforeSleep() function\n * to process the query buffer from unblocked clients and remove the clients\n * from the blocked_clients queue.\n *\n * replyToBlockedClientTimedOut() is called by the cron function when\n * a client blocked reaches the specified timeout (if the timeout is set\n * to 0, no timeout is processed).\n * It usually just needs to send a reply to the client.\n *\n * When implementing a new type of blocking opeation, the implementation\n * should modify unblockClient() and replyToBlockedClientTimedOut() in order\n * to handle the btype-specific behavior of this two functions.\n * If the blocking operation waits for certain keys to change state, the\n * clusterRedirectBlockedClientIfNeeded() function should also be updated.\n */\n\n#include \"server.h\"\n\n/* Get a timeout value from an object and store it into 'timeout'.\n * The final timeout is always stored as milliseconds as a time where the\n * timeout will expire, however the parsing is performed according to\n * the 'unit' that can be seconds or milliseconds.\n *\n * Note that if the timeout is zero (usually from the point of view of\n * commands API this means no timeout) the value stored into 'timeout'\n * is zero. */\nint getTimeoutFromObjectOrReply(client *c, robj *object, mstime_t *timeout, int unit) {\n    long long tval;\n\n    if (getLongLongFromObjectOrReply(c,object,&tval,\n        \"timeout is not an integer or out of range\") != C_OK)\n        return C_ERR;\n\n    if (tval < 0) {\n        addReplyError(c,\"timeout is negative\");\n        return C_ERR;\n    }\n\n    if (tval > 0) {\n        if (unit == UNIT_SECONDS) tval *= 1000;\n        tval += mstime();\n    }\n    *timeout = tval;\n\n    return C_OK;\n}\n\n/* Block a client for the specific operation type. Once the CLIENT_BLOCKED\n * flag is set client query buffer is not longer processed, but accumulated,\n * and will be processed when the client is unblocked. */\nvoid blockClient(client *c, int btype) {\n    c->flags |= CLIENT_BLOCKED;\n    c->btype = btype;\n    server.bpop_blocked_clients++;\n}\n\n/* This function is called in the beforeSleep() function of the event loop\n * in order to process the pending input buffer of clients that were\n * unblocked after a blocking operation. */\nvoid processUnblockedClients(void) {\n    listNode *ln;\n    client *c;\n\n    while (listLength(server.unblocked_clients)) {\n        ln = listFirst(server.unblocked_clients);\n        serverAssert(ln != NULL);\n        c = ln->value;\n        listDelNode(server.unblocked_clients,ln);\n        c->flags &= ~CLIENT_UNBLOCKED;\n\n        /* Process remaining data in the input buffer, unless the client\n         * is blocked again. Actually processInputBuffer() checks that the\n         * client is not blocked before to proceed, but things may change and\n         * the code is conceptually more correct this way. */\n        if (!(c->flags & CLIENT_BLOCKED)) {\n            if (c->querybuf && sdslen(c->querybuf) > 0) {\n                processInputBuffer(c);\n            }\n        }\n    }\n}\n\n/* Unblock a client calling the right function depending on the kind\n * of operation the client is blocking for. */\nvoid unblockClient(client *c) {\n    if (c->btype == BLOCKED_LIST) {\n        unblockClientWaitingData(c);\n    } else if (c->btype == BLOCKED_WAIT) {\n        unblockClientWaitingReplicas(c);\n    } else {\n        serverPanic(\"Unknown btype in unblockClient().\");\n    }\n    /* Clear the flags, and put the client in the unblocked list so that\n     * we'll process new commands in its query buffer ASAP. */\n    c->flags &= ~CLIENT_BLOCKED;\n    c->btype = BLOCKED_NONE;\n    server.bpop_blocked_clients--;\n    /* The client may already be into the unblocked list because of a previous\n     * blocking operation, don't add back it into the list multiple times. */\n    if (!(c->flags & CLIENT_UNBLOCKED)) {\n        c->flags |= CLIENT_UNBLOCKED;\n        listAddNodeTail(server.unblocked_clients,c);\n    }\n}\n\n/* This function gets called when a blocked client timed out in order to\n * send it a reply of some kind. */\nvoid replyToBlockedClientTimedOut(client *c) {\n    if (c->btype == BLOCKED_LIST) {\n        addReply(c,shared.nullmultibulk);\n    } else if (c->btype == BLOCKED_WAIT) {\n        addReplyLongLong(c,replicationCountAcksByOffset(c->bpop.reploffset));\n    } else {\n        serverPanic(\"Unknown btype in replyToBlockedClientTimedOut().\");\n    }\n}\n\n/* Mass-unblock clients because something changed in the instance that makes\n * blocking no longer safe. For example clients blocked in list operations\n * in an instance which turns from master to slave is unsafe, so this function\n * is called when a master turns into a slave.\n *\n * The semantics is to send an -UNBLOCKED error to the client, disconnecting\n * it at the same time. */\nvoid disconnectAllBlockedClients(void) {\n    listNode *ln;\n    listIter li;\n\n    listRewind(server.clients,&li);\n    while((ln = listNext(&li))) {\n        client *c = listNodeValue(ln);\n\n        if (c->flags & CLIENT_BLOCKED) {\n            addReplySds(c,sdsnew(\n                \"-UNBLOCKED force unblock from blocking operation, \"\n                \"instance state changed (master -> slave?)\\r\\n\"));\n            unblockClient(c);\n            c->flags |= CLIENT_CLOSE_AFTER_REPLY;\n        }\n    }\n}\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/src/cluster.c",
    "content": "/* Redis Cluster implementation.\n *\n * Copyright (c) 2009-2012, Salvatore Sanfilippo <antirez at gmail dot com>\n * All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions are met:\n *\n *   * Redistributions of source code must retain the above copyright notice,\n *     this list of conditions and the following disclaimer.\n *   * Redistributions in binary form must reproduce the above copyright\n *     notice, this list of conditions and the following disclaimer in the\n *     documentation and/or other materials provided with the distribution.\n *   * Neither the name of Redis nor the names of its contributors may be used\n *     to endorse or promote products derived from this software without\n *     specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\"\n * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\n * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE\n * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR\n * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF\n * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS\n * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN\n * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)\n * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE\n * POSSIBILITY OF SUCH DAMAGE.\n */\n\n#include \"server.h\"\n#include \"cluster.h\"\n#include \"endianconv.h\"\n\n#include <sys/types.h>\n#include <sys/socket.h>\n#include <arpa/inet.h>\n#include <fcntl.h>\n#include <unistd.h>\n#include <sys/socket.h>\n#include <sys/stat.h>\n#include <sys/file.h>\n#include <math.h>\n\n/* A global reference to myself is handy to make code more clear.\n * Myself always points to server.cluster->myself, that is, the clusterNode\n * that represents this node. */\nclusterNode *myself = NULL;\n\nclusterNode *createClusterNode(char *nodename, int flags);\nint clusterAddNode(clusterNode *node);\nvoid clusterAcceptHandler(aeEventLoop *el, int fd, void *privdata, int mask);\nvoid clusterReadHandler(aeEventLoop *el, int fd, void *privdata, int mask);\nvoid clusterSendPing(clusterLink *link, int type);\nvoid clusterSendFail(char *nodename);\nvoid clusterSendFailoverAuthIfNeeded(clusterNode *node, clusterMsg *request);\nvoid clusterUpdateState(void);\nint clusterNodeGetSlotBit(clusterNode *n, int slot);\nsds clusterGenNodesDescription(int filter);\nclusterNode *clusterLookupNode(char *name);\nint clusterNodeAddSlave(clusterNode *master, clusterNode *slave);\nint clusterAddSlot(clusterNode *n, int slot);\nint clusterDelSlot(int slot);\nint clusterDelNodeSlots(clusterNode *node);\nint clusterNodeSetSlotBit(clusterNode *n, int slot);\nvoid clusterSetMaster(clusterNode *n);\nvoid clusterHandleSlaveFailover(void);\nvoid clusterHandleSlaveMigration(int max_slaves);\nint bitmapTestBit(unsigned char *bitmap, int pos);\nvoid clusterDoBeforeSleep(int flags);\nvoid clusterSendUpdate(clusterLink *link, clusterNode *node);\nvoid resetManualFailover(void);\nvoid clusterCloseAllSlots(void);\nvoid clusterSetNodeAsMaster(clusterNode *n);\nvoid clusterDelNode(clusterNode *delnode);\nsds representClusterNodeFlags(sds ci, uint16_t flags);\nuint64_t clusterGetMaxEpoch(void);\nint clusterBumpConfigEpochWithoutConsensus(void);\n\n/* -----------------------------------------------------------------------------\n * Initialization\n * -------------------------------------------------------------------------- */\n\n/* Load the cluster config from 'filename'.\n *\n * If the file does not exist or is zero-length (this may happen because\n * when we lock the nodes.conf file, we create a zero-length one for the\n * sake of locking if it does not already exist), C_ERR is returned.\n * If the configuration was loaded from the file, C_OK is returned. */\nint clusterLoadConfig(char *filename) {\n    FILE *fp = fopen(filename,\"r\");\n    struct stat sb;\n    char *line;\n    int maxline, j;\n\n    if (fp == NULL) {\n        if (errno == ENOENT) {\n            return C_ERR;\n        } else {\n            serverLog(LL_WARNING,\n                \"Loading the cluster node config from %s: %s\",\n                filename, strerror(errno));\n            exit(1);\n        }\n    }\n\n    /* Check if the file is zero-length: if so return C_ERR to signal\n     * we have to write the config. */\n    if (fstat(fileno(fp),&sb) != -1 && sb.st_size == 0) {\n        fclose(fp);\n        return C_ERR;\n    }\n\n    /* Parse the file. Note that single lines of the cluster config file can\n     * be really long as they include all the hash slots of the node.\n     * This means in the worst possible case, half of the Redis slots will be\n     * present in a single line, possibly in importing or migrating state, so\n     * together with the node ID of the sender/receiver.\n     *\n     * To simplify we allocate 1024+CLUSTER_SLOTS*128 bytes per line. */\n    maxline = 1024+CLUSTER_SLOTS*128;\n    line = zmalloc(maxline);\n    while(fgets(line,maxline,fp) != NULL) {\n        int argc;\n        sds *argv;\n        clusterNode *n, *master;\n        char *p, *s;\n\n        /* Skip blank lines, they can be created either by users manually\n         * editing nodes.conf or by the config writing process if stopped\n         * before the truncate() call. */\n        if (line[0] == '\\n') continue;\n\n        /* Split the line into arguments for processing. */\n        argv = sdssplitargs(line,&argc);\n        if (argv == NULL) goto fmterr;\n\n        /* Handle the special \"vars\" line. Don't pretend it is the last\n         * line even if it actually is when generated by Redis. */\n        if (strcasecmp(argv[0],\"vars\") == 0) {\n            for (j = 1; j < argc; j += 2) {\n                if (strcasecmp(argv[j],\"currentEpoch\") == 0) {\n                    server.cluster->currentEpoch =\n                            strtoull(argv[j+1],NULL,10);\n                } else if (strcasecmp(argv[j],\"lastVoteEpoch\") == 0) {\n                    server.cluster->lastVoteEpoch =\n                            strtoull(argv[j+1],NULL,10);\n                } else {\n                    serverLog(LL_WARNING,\n                        \"Skipping unknown cluster config variable '%s'\",\n                        argv[j]);\n                }\n            }\n            sdsfreesplitres(argv,argc);\n            continue;\n        }\n\n        /* Regular config lines have at least eight fields */\n        if (argc < 8) goto fmterr;\n\n        /* Create this node if it does not exist */\n        n = clusterLookupNode(argv[0]);\n        if (!n) {\n            n = createClusterNode(argv[0],0);\n            clusterAddNode(n);\n        }\n        /* Address and port */\n        if ((p = strrchr(argv[1],':')) == NULL) goto fmterr;\n        *p = '\\0';\n        memcpy(n->ip,argv[1],strlen(argv[1])+1);\n        n->port = atoi(p+1);\n\n        /* Parse flags */\n        p = s = argv[2];\n        while(p) {\n            p = strchr(s,',');\n            if (p) *p = '\\0';\n            if (!strcasecmp(s,\"myself\")) {\n                serverAssert(server.cluster->myself == NULL);\n                myself = server.cluster->myself = n;\n                n->flags |= CLUSTER_NODE_MYSELF;\n            } else if (!strcasecmp(s,\"master\")) {\n                n->flags |= CLUSTER_NODE_MASTER;\n            } else if (!strcasecmp(s,\"slave\")) {\n                n->flags |= CLUSTER_NODE_SLAVE;\n            } else if (!strcasecmp(s,\"fail?\")) {\n                n->flags |= CLUSTER_NODE_PFAIL;\n            } else if (!strcasecmp(s,\"fail\")) {\n                n->flags |= CLUSTER_NODE_FAIL;\n                n->fail_time = mstime();\n            } else if (!strcasecmp(s,\"handshake\")) {\n                n->flags |= CLUSTER_NODE_HANDSHAKE;\n            } else if (!strcasecmp(s,\"noaddr\")) {\n                n->flags |= CLUSTER_NODE_NOADDR;\n            } else if (!strcasecmp(s,\"noflags\")) {\n                /* nothing to do */\n            } else {\n                serverPanic(\"Unknown flag in redis cluster config file\");\n            }\n            if (p) s = p+1;\n        }\n\n        /* Get master if any. Set the master and populate master's\n         * slave list. */\n        if (argv[3][0] != '-') {\n            master = clusterLookupNode(argv[3]);\n            if (!master) {\n                master = createClusterNode(argv[3],0);\n                clusterAddNode(master);\n            }\n            n->slaveof = master;\n            clusterNodeAddSlave(master,n);\n        }\n\n        /* Set ping sent / pong received timestamps */\n        if (atoi(argv[4])) n->ping_sent = mstime();\n        if (atoi(argv[5])) n->pong_received = mstime();\n\n        /* Set configEpoch for this node. */\n        n->configEpoch = strtoull(argv[6],NULL,10);\n\n        /* Populate hash slots served by this instance. */\n        for (j = 8; j < argc; j++) {\n            int start, stop;\n\n            if (argv[j][0] == '[') {\n                /* Here we handle migrating / importing slots */\n                int slot;\n                char direction;\n                clusterNode *cn;\n\n                p = strchr(argv[j],'-');\n                serverAssert(p != NULL);\n                *p = '\\0';\n                direction = p[1]; /* Either '>' or '<' */\n                slot = atoi(argv[j]+1);\n                p += 3;\n                cn = clusterLookupNode(p);\n                if (!cn) {\n                    cn = createClusterNode(p,0);\n                    clusterAddNode(cn);\n                }\n                if (direction == '>') {\n                    server.cluster->migrating_slots_to[slot] = cn;\n                } else {\n                    server.cluster->importing_slots_from[slot] = cn;\n                }\n                continue;\n            } else if ((p = strchr(argv[j],'-')) != NULL) {\n                *p = '\\0';\n                start = atoi(argv[j]);\n                stop = atoi(p+1);\n            } else {\n                start = stop = atoi(argv[j]);\n            }\n            while(start <= stop) clusterAddSlot(n, start++);\n        }\n\n        sdsfreesplitres(argv,argc);\n    }\n    /* Config sanity check */\n    if (server.cluster->myself == NULL) goto fmterr;\n\n    zfree(line);\n    fclose(fp);\n\n    serverLog(LL_NOTICE,\"Node configuration loaded, I'm %.40s\", myself->name);\n\n    /* Something that should never happen: currentEpoch smaller than\n     * the max epoch found in the nodes configuration. However we handle this\n     * as some form of protection against manual editing of critical files. */\n    if (clusterGetMaxEpoch() > server.cluster->currentEpoch) {\n        server.cluster->currentEpoch = clusterGetMaxEpoch();\n    }\n    return C_OK;\n\nfmterr:\n    serverLog(LL_WARNING,\n        \"Unrecoverable error: corrupted cluster config file.\");\n    zfree(line);\n    if (fp) fclose(fp);\n    exit(1);\n}\n\n/* Cluster node configuration is exactly the same as CLUSTER NODES output.\n *\n * This function writes the node config and returns 0, on error -1\n * is returned.\n *\n * Note: we need to write the file in an atomic way from the point of view\n * of the POSIX filesystem semantics, so that if the server is stopped\n * or crashes during the write, we'll end with either the old file or the\n * new one. Since we have the full payload to write available we can use\n * a single write to write the whole file. If the pre-existing file was\n * bigger we pad our payload with newlines that are anyway ignored and truncate\n * the file afterward. */\nint clusterSaveConfig(int do_fsync) {\n    sds ci;\n    size_t content_size;\n    struct stat sb;\n    int fd;\n\n    server.cluster->todo_before_sleep &= ~CLUSTER_TODO_SAVE_CONFIG;\n\n    /* Get the nodes description and concatenate our \"vars\" directive to\n     * save currentEpoch and lastVoteEpoch. */\n    ci = clusterGenNodesDescription(CLUSTER_NODE_HANDSHAKE);\n    ci = sdscatprintf(ci,\"vars currentEpoch %llu lastVoteEpoch %llu\\n\",\n        (unsigned long long) server.cluster->currentEpoch,\n        (unsigned long long) server.cluster->lastVoteEpoch);\n    content_size = sdslen(ci);\n\n    if ((fd = open(server.cluster_configfile,O_WRONLY|O_CREAT,0644))\n        == -1) goto err;\n\n    /* Pad the new payload if the existing file length is greater. */\n    if (fstat(fd,&sb) != -1) {\n        if (sb.st_size > (off_t)content_size) {\n            ci = sdsgrowzero(ci,sb.st_size);\n            memset(ci+content_size,'\\n',sb.st_size-content_size);\n        }\n    }\n    if (write(fd,ci,sdslen(ci)) != (ssize_t)sdslen(ci)) goto err;\n    if (do_fsync) {\n        server.cluster->todo_before_sleep &= ~CLUSTER_TODO_FSYNC_CONFIG;\n        fsync(fd);\n    }\n\n    /* Truncate the file if needed to remove the final \\n padding that\n     * is just garbage. */\n    if (content_size != sdslen(ci) && ftruncate(fd,content_size) == -1) {\n        /* ftruncate() failing is not a critical error. */\n    }\n    close(fd);\n    sdsfree(ci);\n    return 0;\n\nerr:\n    if (fd != -1) close(fd);\n    sdsfree(ci);\n    return -1;\n}\n\nvoid clusterSaveConfigOrDie(int do_fsync) {\n    if (clusterSaveConfig(do_fsync) == -1) {\n        serverLog(LL_WARNING,\"Fatal: can't update cluster config file.\");\n        exit(1);\n    }\n}\n\n/* Lock the cluster config using flock(), and leaks the file descritor used to\n * acquire the lock so that the file will be locked forever.\n *\n * This works because we always update nodes.conf with a new version\n * in-place, reopening the file, and writing to it in place (later adjusting\n * the length with ftruncate()).\n *\n * On success C_OK is returned, otherwise an error is logged and\n * the function returns C_ERR to signal a lock was not acquired. */\nint clusterLockConfig(char *filename) {\n/* flock() does not exist on Solaris\n * and a fcntl-based solution won't help, as we constantly re-open that file,\n * which will release _all_ locks anyway\n */\n#if !defined(__sun)\n    /* To lock it, we need to open the file in a way it is created if\n     * it does not exist, otherwise there is a race condition with other\n     * processes. */\n    int fd = open(filename,O_WRONLY|O_CREAT,0644);\n    if (fd == -1) {\n        serverLog(LL_WARNING,\n            \"Can't open %s in order to acquire a lock: %s\",\n            filename, strerror(errno));\n        return C_ERR;\n    }\n\n    if (flock(fd,LOCK_EX|LOCK_NB) == -1) {\n        if (errno == EWOULDBLOCK) {\n            serverLog(LL_WARNING,\n                 \"Sorry, the cluster configuration file %s is already used \"\n                 \"by a different Redis Cluster node. Please make sure that \"\n                 \"different nodes use different cluster configuration \"\n                 \"files.\", filename);\n        } else {\n            serverLog(LL_WARNING,\n                \"Impossible to lock %s: %s\", filename, strerror(errno));\n        }\n        close(fd);\n        return C_ERR;\n    }\n    /* Lock acquired: leak the 'fd' by not closing it, so that we'll retain the\n     * lock to the file as long as the process exists. */\n#endif /* __sun */\n\n    return C_OK;\n}\n\nvoid clusterInit(void) {\n    int saveconf = 0;\n\n    server.cluster = zmalloc(sizeof(clusterState));\n    server.cluster->myself = NULL;\n    server.cluster->currentEpoch = 0;\n    server.cluster->state = CLUSTER_FAIL;\n    server.cluster->size = 1;\n    server.cluster->todo_before_sleep = 0;\n    server.cluster->nodes = dictCreate(&clusterNodesDictType,NULL);\n    server.cluster->nodes_black_list =\n        dictCreate(&clusterNodesBlackListDictType,NULL);\n    server.cluster->failover_auth_time = 0;\n    server.cluster->failover_auth_count = 0;\n    server.cluster->failover_auth_rank = 0;\n    server.cluster->failover_auth_epoch = 0;\n    server.cluster->cant_failover_reason = CLUSTER_CANT_FAILOVER_NONE;\n    server.cluster->lastVoteEpoch = 0;\n    server.cluster->stats_bus_messages_sent = 0;\n    server.cluster->stats_bus_messages_received = 0;\n    memset(server.cluster->slots,0, sizeof(server.cluster->slots));\n    clusterCloseAllSlots();\n\n    /* Lock the cluster config file to make sure every node uses\n     * its own nodes.conf. */\n    if (clusterLockConfig(server.cluster_configfile) == C_ERR)\n        exit(1);\n\n    /* Load or create a new nodes configuration. */\n    if (clusterLoadConfig(server.cluster_configfile) == C_ERR) {\n        /* No configuration found. We will just use the random name provided\n         * by the createClusterNode() function. */\n        myself = server.cluster->myself =\n            createClusterNode(NULL,CLUSTER_NODE_MYSELF|CLUSTER_NODE_MASTER);\n        serverLog(LL_NOTICE,\"No cluster configuration found, I'm %.40s\",\n            myself->name);\n        clusterAddNode(myself);\n        saveconf = 1;\n    }\n    if (saveconf) clusterSaveConfigOrDie(1);\n\n    /* We need a listening TCP port for our cluster messaging needs. */\n    server.cfd_count = 0;\n\n    /* Port sanity check II\n     * The other handshake port check is triggered too late to stop\n     * us from trying to use a too-high cluster port number. */\n    if (server.port > (65535-CLUSTER_PORT_INCR)) {\n        serverLog(LL_WARNING, \"Redis port number too high. \"\n                   \"Cluster communication port is 10,000 port \"\n                   \"numbers higher than your Redis port. \"\n                   \"Your Redis port number must be \"\n                   \"lower than 55535.\");\n        exit(1);\n    }\n\n    if (listenToPort(server.port+CLUSTER_PORT_INCR,\n        server.cfd,&server.cfd_count) == C_ERR)\n    {\n        exit(1);\n    } else {\n        int j;\n\n        for (j = 0; j < server.cfd_count; j++) {\n            if (aeCreateFileEvent(server.el, server.cfd[j], AE_READABLE,\n                clusterAcceptHandler, NULL) == AE_ERR)\n                    serverPanic(\"Unrecoverable error creating Redis Cluster \"\n                                \"file event.\");\n        }\n    }\n\n    /* The slots -> keys map is a sorted set. Init it. */\n    server.cluster->slots_to_keys = zslCreate();\n\n    /* Set myself->port to my listening port, we'll just need to discover\n     * the IP address via MEET messages. */\n    myself->port = server.port;\n\n    server.cluster->mf_end = 0;\n    resetManualFailover();\n}\n\n/* Reset a node performing a soft or hard reset:\n *\n * 1) All other nodes are forget.\n * 2) All the assigned / open slots are released.\n * 3) If the node is a slave, it turns into a master.\n * 5) Only for hard reset: a new Node ID is generated.\n * 6) Only for hard reset: currentEpoch and configEpoch are set to 0.\n * 7) The new configuration is saved and the cluster state updated.\n * 8) If the node was a slave, the whole data set is flushed away. */\nvoid clusterReset(int hard) {\n    dictIterator *di;\n    dictEntry *de;\n    int j;\n\n    /* Turn into master. */\n    if (nodeIsSlave(myself)) {\n        clusterSetNodeAsMaster(myself);\n        replicationUnsetMaster();\n        emptyDb(NULL);\n    }\n\n    /* Close slots, reset manual failover state. */\n    clusterCloseAllSlots();\n    resetManualFailover();\n\n    /* Unassign all the slots. */\n    for (j = 0; j < CLUSTER_SLOTS; j++) clusterDelSlot(j);\n\n    /* Forget all the nodes, but myself. */\n    di = dictGetSafeIterator(server.cluster->nodes);\n    while((de = dictNext(di)) != NULL) {\n        clusterNode *node = dictGetVal(de);\n\n        if (node == myself) continue;\n        clusterDelNode(node);\n    }\n    dictReleaseIterator(di);\n\n    /* Hard reset only: set epochs to 0, change node ID. */\n    if (hard) {\n        sds oldname;\n\n        server.cluster->currentEpoch = 0;\n        server.cluster->lastVoteEpoch = 0;\n        myself->configEpoch = 0;\n        serverLog(LL_WARNING, \"configEpoch set to 0 via CLUSTER RESET HARD\");\n\n        /* To change the Node ID we need to remove the old name from the\n         * nodes table, change the ID, and re-add back with new name. */\n        oldname = sdsnewlen(myself->name, CLUSTER_NAMELEN);\n        dictDelete(server.cluster->nodes,oldname);\n        sdsfree(oldname);\n        getRandomHexChars(myself->name, CLUSTER_NAMELEN);\n        clusterAddNode(myself);\n        serverLog(LL_NOTICE,\"Node hard reset, now I'm %.40s\", myself->name);\n    }\n\n    /* Make sure to persist the new config and update the state. */\n    clusterDoBeforeSleep(CLUSTER_TODO_SAVE_CONFIG|\n                         CLUSTER_TODO_UPDATE_STATE|\n                         CLUSTER_TODO_FSYNC_CONFIG);\n}\n\n/* -----------------------------------------------------------------------------\n * CLUSTER communication link\n * -------------------------------------------------------------------------- */\n\nclusterLink *createClusterLink(clusterNode *node) {\n    clusterLink *link = zmalloc(sizeof(*link));\n    link->ctime = mstime();\n    link->sndbuf = sdsempty();\n    link->rcvbuf = sdsempty();\n    link->node = node;\n    link->fd = -1;\n    return link;\n}\n\n/* Free a cluster link, but does not free the associated node of course.\n * This function will just make sure that the original node associated\n * with this link will have the 'link' field set to NULL. */\nvoid freeClusterLink(clusterLink *link) {\n    if (link->fd != -1) {\n        aeDeleteFileEvent(server.el, link->fd, AE_WRITABLE);\n        aeDeleteFileEvent(server.el, link->fd, AE_READABLE);\n    }\n    sdsfree(link->sndbuf);\n    sdsfree(link->rcvbuf);\n    if (link->node)\n        link->node->link = NULL;\n    close(link->fd);\n    zfree(link);\n}\n\n#define MAX_CLUSTER_ACCEPTS_PER_CALL 1000\nvoid clusterAcceptHandler(aeEventLoop *el, int fd, void *privdata, int mask) {\n    int cport, cfd;\n    int max = MAX_CLUSTER_ACCEPTS_PER_CALL;\n    char cip[NET_IP_STR_LEN];\n    clusterLink *link;\n    UNUSED(el);\n    UNUSED(mask);\n    UNUSED(privdata);\n\n    /* If the server is starting up, don't accept cluster connections:\n     * UPDATE messages may interact with the database content. */\n    if (server.masterhost == NULL && server.loading) return;\n\n    while(max--) {\n        cfd = anetTcpAccept(server.neterr, fd, cip, sizeof(cip), &cport);\n        if (cfd == ANET_ERR) {\n            if (errno != EWOULDBLOCK)\n                serverLog(LL_VERBOSE,\n                    \"Error accepting cluster node: %s\", server.neterr);\n            return;\n        }\n        anetNonBlock(NULL,cfd);\n        anetEnableTcpNoDelay(NULL,cfd);\n\n        /* Use non-blocking I/O for cluster messages. */\n        serverLog(LL_VERBOSE,\"Accepted cluster node %s:%d\", cip, cport);\n        /* Create a link object we use to handle the connection.\n         * It gets passed to the readable handler when data is available.\n         * Initiallly the link->node pointer is set to NULL as we don't know\n         * which node is, but the right node is references once we know the\n         * node identity. */\n        link = createClusterLink(NULL);\n        link->fd = cfd;\n        aeCreateFileEvent(server.el,cfd,AE_READABLE,clusterReadHandler,link);\n    }\n}\n\n/* -----------------------------------------------------------------------------\n * Key space handling\n * -------------------------------------------------------------------------- */\n\n/* We have 16384 hash slots. The hash slot of a given key is obtained\n * as the least significant 14 bits of the crc16 of the key.\n *\n * However if the key contains the {...} pattern, only the part between\n * { and } is hashed. This may be useful in the future to force certain\n * keys to be in the same node (assuming no resharding is in progress). */\nunsigned int keyHashSlot(char *key, int keylen) {\n    int s, e; /* start-end indexes of { and } */\n\n    for (s = 0; s < keylen; s++)\n        if (key[s] == '{') break;\n\n    /* No '{' ? Hash the whole key. This is the base case. */\n    if (s == keylen) return crc16(key,keylen) & 0x3FFF;\n\n    /* '{' found? Check if we have the corresponding '}'. */\n    for (e = s+1; e < keylen; e++)\n        if (key[e] == '}') break;\n\n    /* No '}' or nothing betweeen {} ? Hash the whole key. */\n    if (e == keylen || e == s+1) return crc16(key,keylen) & 0x3FFF;\n\n    /* If we are here there is both a { and a } on its right. Hash\n     * what is in the middle between { and }. */\n    return crc16(key+s+1,e-s-1) & 0x3FFF;\n}\n\n/* -----------------------------------------------------------------------------\n * CLUSTER node API\n * -------------------------------------------------------------------------- */\n\n/* Create a new cluster node, with the specified flags.\n * If \"nodename\" is NULL this is considered a first handshake and a random\n * node name is assigned to this node (it will be fixed later when we'll\n * receive the first pong).\n *\n * The node is created and returned to the user, but it is not automatically\n * added to the nodes hash table. */\nclusterNode *createClusterNode(char *nodename, int flags) {\n    clusterNode *node = zmalloc(sizeof(*node));\n\n    if (nodename)\n        memcpy(node->name, nodename, CLUSTER_NAMELEN);\n    else\n        getRandomHexChars(node->name, CLUSTER_NAMELEN);\n    node->ctime = mstime();\n    node->configEpoch = 0;\n    node->flags = flags;\n    memset(node->slots,0,sizeof(node->slots));\n    node->numslots = 0;\n    node->numslaves = 0;\n    node->slaves = NULL;\n    node->slaveof = NULL;\n    node->ping_sent = node->pong_received = 0;\n    node->fail_time = 0;\n    node->link = NULL;\n    memset(node->ip,0,sizeof(node->ip));\n    node->port = 0;\n    node->fail_reports = listCreate();\n    node->voted_time = 0;\n    node->orphaned_time = 0;\n    node->repl_offset_time = 0;\n    node->repl_offset = 0;\n    listSetFreeMethod(node->fail_reports,zfree);\n    return node;\n}\n\n/* This function is called every time we get a failure report from a node.\n * The side effect is to populate the fail_reports list (or to update\n * the timestamp of an existing report).\n *\n * 'failing' is the node that is in failure state according to the\n * 'sender' node.\n *\n * The function returns 0 if it just updates a timestamp of an existing\n * failure report from the same sender. 1 is returned if a new failure\n * report is created. */\nint clusterNodeAddFailureReport(clusterNode *failing, clusterNode *sender) {\n    list *l = failing->fail_reports;\n    listNode *ln;\n    listIter li;\n    clusterNodeFailReport *fr;\n\n    /* If a failure report from the same sender already exists, just update\n     * the timestamp. */\n    listRewind(l,&li);\n    while ((ln = listNext(&li)) != NULL) {\n        fr = ln->value;\n        if (fr->node == sender) {\n            fr->time = mstime();\n            return 0;\n        }\n    }\n\n    /* Otherwise create a new report. */\n    fr = zmalloc(sizeof(*fr));\n    fr->node = sender;\n    fr->time = mstime();\n    listAddNodeTail(l,fr);\n    return 1;\n}\n\n/* Remove failure reports that are too old, where too old means reasonably\n * older than the global node timeout. Note that anyway for a node to be\n * flagged as FAIL we need to have a local PFAIL state that is at least\n * older than the global node timeout, so we don't just trust the number\n * of failure reports from other nodes. */\nvoid clusterNodeCleanupFailureReports(clusterNode *node) {\n    list *l = node->fail_reports;\n    listNode *ln;\n    listIter li;\n    clusterNodeFailReport *fr;\n    mstime_t maxtime = server.cluster_node_timeout *\n                     CLUSTER_FAIL_REPORT_VALIDITY_MULT;\n    mstime_t now = mstime();\n\n    listRewind(l,&li);\n    while ((ln = listNext(&li)) != NULL) {\n        fr = ln->value;\n        if (now - fr->time > maxtime) listDelNode(l,ln);\n    }\n}\n\n/* Remove the failing report for 'node' if it was previously considered\n * failing by 'sender'. This function is called when a node informs us via\n * gossip that a node is OK from its point of view (no FAIL or PFAIL flags).\n *\n * Note that this function is called relatively often as it gets called even\n * when there are no nodes failing, and is O(N), however when the cluster is\n * fine the failure reports list is empty so the function runs in constant\n * time.\n *\n * The function returns 1 if the failure report was found and removed.\n * Otherwise 0 is returned. */\nint clusterNodeDelFailureReport(clusterNode *node, clusterNode *sender) {\n    list *l = node->fail_reports;\n    listNode *ln;\n    listIter li;\n    clusterNodeFailReport *fr;\n\n    /* Search for a failure report from this sender. */\n    listRewind(l,&li);\n    while ((ln = listNext(&li)) != NULL) {\n        fr = ln->value;\n        if (fr->node == sender) break;\n    }\n    if (!ln) return 0; /* No failure report from this sender. */\n\n    /* Remove the failure report. */\n    listDelNode(l,ln);\n    clusterNodeCleanupFailureReports(node);\n    return 1;\n}\n\n/* Return the number of external nodes that believe 'node' is failing,\n * not including this node, that may have a PFAIL or FAIL state for this\n * node as well. */\nint clusterNodeFailureReportsCount(clusterNode *node) {\n    clusterNodeCleanupFailureReports(node);\n    return listLength(node->fail_reports);\n}\n\nint clusterNodeRemoveSlave(clusterNode *master, clusterNode *slave) {\n    int j;\n\n    for (j = 0; j < master->numslaves; j++) {\n        if (master->slaves[j] == slave) {\n            if ((j+1) < master->numslaves) {\n                int remaining_slaves = (master->numslaves - j) - 1;\n                memmove(master->slaves+j,master->slaves+(j+1),\n                        (sizeof(*master->slaves) * remaining_slaves));\n            }\n            master->numslaves--;\n            if (master->numslaves == 0)\n                master->flags &= ~CLUSTER_NODE_MIGRATE_TO;\n            return C_OK;\n        }\n    }\n    return C_ERR;\n}\n\nint clusterNodeAddSlave(clusterNode *master, clusterNode *slave) {\n    int j;\n\n    /* If it's already a slave, don't add it again. */\n    for (j = 0; j < master->numslaves; j++)\n        if (master->slaves[j] == slave) return C_ERR;\n    master->slaves = zrealloc(master->slaves,\n        sizeof(clusterNode*)*(master->numslaves+1));\n    master->slaves[master->numslaves] = slave;\n    master->numslaves++;\n    master->flags |= CLUSTER_NODE_MIGRATE_TO;\n    return C_OK;\n}\n\nint clusterCountNonFailingSlaves(clusterNode *n) {\n    int j, okslaves = 0;\n\n    for (j = 0; j < n->numslaves; j++)\n        if (!nodeFailed(n->slaves[j])) okslaves++;\n    return okslaves;\n}\n\n/* Low level cleanup of the node structure. Only called by clusterDelNode(). */\nvoid freeClusterNode(clusterNode *n) {\n    sds nodename;\n    int j;\n\n    /* If the node has associated slaves, we have to set\n     * all the slaves->slaveof fields to NULL (unknown). */\n    for (j = 0; j < n->numslaves; j++)\n        n->slaves[j]->slaveof = NULL;\n\n    /* Remove this node from the list of slaves of its master. */\n    if (nodeIsSlave(n) && n->slaveof) clusterNodeRemoveSlave(n->slaveof,n);\n\n    /* Unlink from the set of nodes. */\n    nodename = sdsnewlen(n->name, CLUSTER_NAMELEN);\n    serverAssert(dictDelete(server.cluster->nodes,nodename) == DICT_OK);\n    sdsfree(nodename);\n\n    /* Release link and associated data structures. */\n    if (n->link) freeClusterLink(n->link);\n    listRelease(n->fail_reports);\n    zfree(n->slaves);\n    zfree(n);\n}\n\n/* Add a node to the nodes hash table */\nint clusterAddNode(clusterNode *node) {\n    int retval;\n\n    retval = dictAdd(server.cluster->nodes,\n            sdsnewlen(node->name,CLUSTER_NAMELEN), node);\n    return (retval == DICT_OK) ? C_OK : C_ERR;\n}\n\n/* Remove a node from the cluster. The functio performs the high level\n * cleanup, calling freeClusterNode() for the low level cleanup.\n * Here we do the following:\n *\n * 1) Mark all the slots handled by it as unassigned.\n * 2) Remove all the failure reports sent by this node and referenced by\n *    other nodes.\n * 3) Free the node with freeClusterNode() that will in turn remove it\n *    from the hash table and from the list of slaves of its master, if\n *    it is a slave node.\n */\nvoid clusterDelNode(clusterNode *delnode) {\n    int j;\n    dictIterator *di;\n    dictEntry *de;\n\n    /* 1) Mark slots as unassigned. */\n    for (j = 0; j < CLUSTER_SLOTS; j++) {\n        if (server.cluster->importing_slots_from[j] == delnode)\n            server.cluster->importing_slots_from[j] = NULL;\n        if (server.cluster->migrating_slots_to[j] == delnode)\n            server.cluster->migrating_slots_to[j] = NULL;\n        if (server.cluster->slots[j] == delnode)\n            clusterDelSlot(j);\n    }\n\n    /* 2) Remove failure reports. */\n    di = dictGetSafeIterator(server.cluster->nodes);\n    while((de = dictNext(di)) != NULL) {\n        clusterNode *node = dictGetVal(de);\n\n        if (node == delnode) continue;\n        clusterNodeDelFailureReport(node,delnode);\n    }\n    dictReleaseIterator(di);\n\n    /* 3) Free the node, unlinking it from the cluster. */\n    freeClusterNode(delnode);\n}\n\n/* Node lookup by name */\nclusterNode *clusterLookupNode(char *name) {\n    sds s = sdsnewlen(name, CLUSTER_NAMELEN);\n    dictEntry *de;\n\n    de = dictFind(server.cluster->nodes,s);\n    sdsfree(s);\n    if (de == NULL) return NULL;\n    return dictGetVal(de);\n}\n\n/* This is only used after the handshake. When we connect a given IP/PORT\n * as a result of CLUSTER MEET we don't have the node name yet, so we\n * pick a random one, and will fix it when we receive the PONG request using\n * this function. */\nvoid clusterRenameNode(clusterNode *node, char *newname) {\n    int retval;\n    sds s = sdsnewlen(node->name, CLUSTER_NAMELEN);\n\n    serverLog(LL_DEBUG,\"Renaming node %.40s into %.40s\",\n        node->name, newname);\n    retval = dictDelete(server.cluster->nodes, s);\n    sdsfree(s);\n    serverAssert(retval == DICT_OK);\n    memcpy(node->name, newname, CLUSTER_NAMELEN);\n    clusterAddNode(node);\n}\n\n/* -----------------------------------------------------------------------------\n * CLUSTER config epoch handling\n * -------------------------------------------------------------------------- */\n\n/* Return the greatest configEpoch found in the cluster, or the current\n * epoch if greater than any node configEpoch. */\nuint64_t clusterGetMaxEpoch(void) {\n    uint64_t max = 0;\n    dictIterator *di;\n    dictEntry *de;\n\n    di = dictGetSafeIterator(server.cluster->nodes);\n    while((de = dictNext(di)) != NULL) {\n        clusterNode *node = dictGetVal(de);\n        if (node->configEpoch > max) max = node->configEpoch;\n    }\n    dictReleaseIterator(di);\n    if (max < server.cluster->currentEpoch) max = server.cluster->currentEpoch;\n    return max;\n}\n\n/* If this node epoch is zero or is not already the greatest across the\n * cluster (from the POV of the local configuration), this function will:\n *\n * 1) Generate a new config epoch, incrementing the current epoch.\n * 2) Assign the new epoch to this node, WITHOUT any consensus.\n * 3) Persist the configuration on disk before sending packets with the\n *    new configuration.\n *\n * If the new config epoch is generated and assigend, C_OK is returned,\n * otherwise C_ERR is returned (since the node has already the greatest\n * configuration around) and no operation is performed.\n *\n * Important note: this function violates the principle that config epochs\n * should be generated with consensus and should be unique across the cluster.\n * However Redis Cluster uses this auto-generated new config epochs in two\n * cases:\n *\n * 1) When slots are closed after importing. Otherwise resharding would be\n *    too expensive.\n * 2) When CLUSTER FAILOVER is called with options that force a slave to\n *    failover its master even if there is not master majority able to\n *    create a new configuration epoch.\n *\n * Redis Cluster will not explode using this function, even in the case of\n * a collision between this node and another node, generating the same\n * configuration epoch unilaterally, because the config epoch conflict\n * resolution algorithm will eventually move colliding nodes to different\n * config epochs. However using this function may violate the \"last failover\n * wins\" rule, so should only be used with care. */\nint clusterBumpConfigEpochWithoutConsensus(void) {\n    uint64_t maxEpoch = clusterGetMaxEpoch();\n\n    if (myself->configEpoch == 0 ||\n        myself->configEpoch != maxEpoch)\n    {\n        server.cluster->currentEpoch++;\n        myself->configEpoch = server.cluster->currentEpoch;\n        clusterDoBeforeSleep(CLUSTER_TODO_SAVE_CONFIG|\n                             CLUSTER_TODO_FSYNC_CONFIG);\n        serverLog(LL_WARNING,\n            \"New configEpoch set to %llu\",\n            (unsigned long long) myself->configEpoch);\n        return C_OK;\n    } else {\n        return C_ERR;\n    }\n}\n\n/* This function is called when this node is a master, and we receive from\n * another master a configuration epoch that is equal to our configuration\n * epoch.\n *\n * BACKGROUND\n *\n * It is not possible that different slaves get the same config\n * epoch during a failover election, because the slaves need to get voted\n * by a majority. However when we perform a manual resharding of the cluster\n * the node will assign a configuration epoch to itself without to ask\n * for agreement. Usually resharding happens when the cluster is working well\n * and is supervised by the sysadmin, however it is possible for a failover\n * to happen exactly while the node we are resharding a slot to assigns itself\n * a new configuration epoch, but before it is able to propagate it.\n *\n * So technically it is possible in this condition that two nodes end with\n * the same configuration epoch.\n *\n * Another possibility is that there are bugs in the implementation causing\n * this to happen.\n *\n * Moreover when a new cluster is created, all the nodes start with the same\n * configEpoch. This collision resolution code allows nodes to automatically\n * end with a different configEpoch at startup automatically.\n *\n * In all the cases, we want a mechanism that resolves this issue automatically\n * as a safeguard. The same configuration epoch for masters serving different\n * set of slots is not harmful, but it is if the nodes end serving the same\n * slots for some reason (manual errors or software bugs) without a proper\n * failover procedure.\n *\n * In general we want a system that eventually always ends with different\n * masters having different configuration epochs whatever happened, since\n * nothign is worse than a split-brain condition in a distributed system.\n *\n * BEHAVIOR\n *\n * When this function gets called, what happens is that if this node\n * has the lexicographically smaller Node ID compared to the other node\n * with the conflicting epoch (the 'sender' node), it will assign itself\n * the greatest configuration epoch currently detected among nodes plus 1.\n *\n * This means that even if there are multiple nodes colliding, the node\n * with the greatest Node ID never moves forward, so eventually all the nodes\n * end with a different configuration epoch.\n */\nvoid clusterHandleConfigEpochCollision(clusterNode *sender) {\n    /* Prerequisites: nodes have the same configEpoch and are both masters. */\n    if (sender->configEpoch != myself->configEpoch ||\n        !nodeIsMaster(sender) || !nodeIsMaster(myself)) return;\n    /* Don't act if the colliding node has a smaller Node ID. */\n    if (memcmp(sender->name,myself->name,CLUSTER_NAMELEN) <= 0) return;\n    /* Get the next ID available at the best of this node knowledge. */\n    server.cluster->currentEpoch++;\n    myself->configEpoch = server.cluster->currentEpoch;\n    clusterSaveConfigOrDie(1);\n    serverLog(LL_VERBOSE,\n        \"WARNING: configEpoch collision with node %.40s.\"\n        \" configEpoch set to %llu\",\n        sender->name,\n        (unsigned long long) myself->configEpoch);\n}\n\n/* -----------------------------------------------------------------------------\n * CLUSTER nodes blacklist\n *\n * The nodes blacklist is just a way to ensure that a given node with a given\n * Node ID is not readded before some time elapsed (this time is specified\n * in seconds in CLUSTER_BLACKLIST_TTL).\n *\n * This is useful when we want to remove a node from the cluster completely:\n * when CLUSTER FORGET is called, it also puts the node into the blacklist so\n * that even if we receive gossip messages from other nodes that still remember\n * about the node we want to remove, we don't re-add it before some time.\n *\n * Currently the CLUSTER_BLACKLIST_TTL is set to 1 minute, this means\n * that redis-trib has 60 seconds to send CLUSTER FORGET messages to nodes\n * in the cluster without dealing with the problem of other nodes re-adding\n * back the node to nodes we already sent the FORGET command to.\n *\n * The data structure used is a hash table with an sds string representing\n * the node ID as key, and the time when it is ok to re-add the node as\n * value.\n * -------------------------------------------------------------------------- */\n\n#define CLUSTER_BLACKLIST_TTL 60      /* 1 minute. */\n\n\n/* Before of the addNode() or Exists() operations we always remove expired\n * entries from the black list. This is an O(N) operation but it is not a\n * problem since add / exists operations are called very infrequently and\n * the hash table is supposed to contain very little elements at max.\n * However without the cleanup during long uptimes and with some automated\n * node add/removal procedures, entries could accumulate. */\nvoid clusterBlacklistCleanup(void) {\n    dictIterator *di;\n    dictEntry *de;\n\n    di = dictGetSafeIterator(server.cluster->nodes_black_list);\n    while((de = dictNext(di)) != NULL) {\n        int64_t expire = dictGetUnsignedIntegerVal(de);\n\n        if (expire < server.unixtime)\n            dictDelete(server.cluster->nodes_black_list,dictGetKey(de));\n    }\n    dictReleaseIterator(di);\n}\n\n/* Cleanup the blacklist and add a new node ID to the black list. */\nvoid clusterBlacklistAddNode(clusterNode *node) {\n    dictEntry *de;\n    sds id = sdsnewlen(node->name,CLUSTER_NAMELEN);\n\n    clusterBlacklistCleanup();\n    if (dictAdd(server.cluster->nodes_black_list,id,NULL) == DICT_OK) {\n        /* If the key was added, duplicate the sds string representation of\n         * the key for the next lookup. We'll free it at the end. */\n        id = sdsdup(id);\n    }\n    de = dictFind(server.cluster->nodes_black_list,id);\n    dictSetUnsignedIntegerVal(de,time(NULL)+CLUSTER_BLACKLIST_TTL);\n    sdsfree(id);\n}\n\n/* Return non-zero if the specified node ID exists in the blacklist.\n * You don't need to pass an sds string here, any pointer to 40 bytes\n * will work. */\nint clusterBlacklistExists(char *nodeid) {\n    sds id = sdsnewlen(nodeid,CLUSTER_NAMELEN);\n    int retval;\n\n    clusterBlacklistCleanup();\n    retval = dictFind(server.cluster->nodes_black_list,id) != NULL;\n    sdsfree(id);\n    return retval;\n}\n\n/* -----------------------------------------------------------------------------\n * CLUSTER messages exchange - PING/PONG and gossip\n * -------------------------------------------------------------------------- */\n\n/* This function checks if a given node should be marked as FAIL.\n * It happens if the following conditions are met:\n *\n * 1) We received enough failure reports from other master nodes via gossip.\n *    Enough means that the majority of the masters signaled the node is\n *    down recently.\n * 2) We believe this node is in PFAIL state.\n *\n * If a failure is detected we also inform the whole cluster about this\n * event trying to force every other node to set the FAIL flag for the node.\n *\n * Note that the form of agreement used here is weak, as we collect the majority\n * of masters state during some time, and even if we force agreement by\n * propagating the FAIL message, because of partitions we may not reach every\n * node. However:\n *\n * 1) Either we reach the majority and eventually the FAIL state will propagate\n *    to all the cluster.\n * 2) Or there is no majority so no slave promotion will be authorized and the\n *    FAIL flag will be cleared after some time.\n */\nvoid markNodeAsFailingIfNeeded(clusterNode *node) {\n    int failures;\n    int needed_quorum = (server.cluster->size / 2) + 1;\n\n    if (!nodeTimedOut(node)) return; /* We can reach it. */\n    if (nodeFailed(node)) return; /* Already FAILing. */\n\n    failures = clusterNodeFailureReportsCount(node);\n    /* Also count myself as a voter if I'm a master. */\n    if (nodeIsMaster(myself)) failures++;\n    if (failures < needed_quorum) return; /* No weak agreement from masters. */\n\n    serverLog(LL_NOTICE,\n        \"Marking node %.40s as failing (quorum reached).\", node->name);\n\n    /* Mark the node as failing. */\n    node->flags &= ~CLUSTER_NODE_PFAIL;\n    node->flags |= CLUSTER_NODE_FAIL;\n    node->fail_time = mstime();\n\n    /* Broadcast the failing node name to everybody, forcing all the other\n     * reachable nodes to flag the node as FAIL. */\n    if (nodeIsMaster(myself)) clusterSendFail(node->name);\n    clusterDoBeforeSleep(CLUSTER_TODO_UPDATE_STATE|CLUSTER_TODO_SAVE_CONFIG);\n}\n\n/* This function is called only if a node is marked as FAIL, but we are able\n * to reach it again. It checks if there are the conditions to undo the FAIL\n * state. */\nvoid clearNodeFailureIfNeeded(clusterNode *node) {\n    mstime_t now = mstime();\n\n    serverAssert(nodeFailed(node));\n\n    /* For slaves we always clear the FAIL flag if we can contact the\n     * node again. */\n    if (nodeIsSlave(node) || node->numslots == 0) {\n        serverLog(LL_NOTICE,\n            \"Clear FAIL state for node %.40s: %s is reachable again.\",\n                node->name,\n                nodeIsSlave(node) ? \"slave\" : \"master without slots\");\n        node->flags &= ~CLUSTER_NODE_FAIL;\n        clusterDoBeforeSleep(CLUSTER_TODO_UPDATE_STATE|CLUSTER_TODO_SAVE_CONFIG);\n    }\n\n    /* If it is a master and...\n     * 1) The FAIL state is old enough.\n     * 2) It is yet serving slots from our point of view (not failed over).\n     * Apparently no one is going to fix these slots, clear the FAIL flag. */\n    if (nodeIsMaster(node) && node->numslots > 0 &&\n        (now - node->fail_time) >\n        (server.cluster_node_timeout * CLUSTER_FAIL_UNDO_TIME_MULT))\n    {\n        serverLog(LL_NOTICE,\n            \"Clear FAIL state for node %.40s: is reachable again and nobody is serving its slots after some time.\",\n                node->name);\n        node->flags &= ~CLUSTER_NODE_FAIL;\n        clusterDoBeforeSleep(CLUSTER_TODO_UPDATE_STATE|CLUSTER_TODO_SAVE_CONFIG);\n    }\n}\n\n/* Return true if we already have a node in HANDSHAKE state matching the\n * specified ip address and port number. This function is used in order to\n * avoid adding a new handshake node for the same address multiple times. */\nint clusterHandshakeInProgress(char *ip, int port) {\n    dictIterator *di;\n    dictEntry *de;\n\n    di = dictGetSafeIterator(server.cluster->nodes);\n    while((de = dictNext(di)) != NULL) {\n        clusterNode *node = dictGetVal(de);\n\n        if (!nodeInHandshake(node)) continue;\n        if (!strcasecmp(node->ip,ip) && node->port == port) break;\n    }\n    dictReleaseIterator(di);\n    return de != NULL;\n}\n\n/* Start an handshake with the specified address if there is not one\n * already in progress. Returns non-zero if the handshake was actually\n * started. On error zero is returned and errno is set to one of the\n * following values:\n *\n * EAGAIN - There is already an handshake in progress for this address.\n * EINVAL - IP or port are not valid. */\nint clusterStartHandshake(char *ip, int port) {\n    clusterNode *n;\n    char norm_ip[NET_IP_STR_LEN];\n    struct sockaddr_storage sa;\n\n    /* IP sanity check */\n    if (inet_pton(AF_INET,ip,\n            &(((struct sockaddr_in *)&sa)->sin_addr)))\n    {\n        sa.ss_family = AF_INET;\n    } else if (inet_pton(AF_INET6,ip,\n            &(((struct sockaddr_in6 *)&sa)->sin6_addr)))\n    {\n        sa.ss_family = AF_INET6;\n    } else {\n        errno = EINVAL;\n        return 0;\n    }\n\n    /* Port sanity check */\n    if (port <= 0 || port > (65535-CLUSTER_PORT_INCR)) {\n        errno = EINVAL;\n        return 0;\n    }\n\n    /* Set norm_ip as the normalized string representation of the node\n     * IP address. */\n    memset(norm_ip,0,NET_IP_STR_LEN);\n    if (sa.ss_family == AF_INET)\n        inet_ntop(AF_INET,\n            (void*)&(((struct sockaddr_in *)&sa)->sin_addr),\n            norm_ip,NET_IP_STR_LEN);\n    else\n        inet_ntop(AF_INET6,\n            (void*)&(((struct sockaddr_in6 *)&sa)->sin6_addr),\n            norm_ip,NET_IP_STR_LEN);\n\n    if (clusterHandshakeInProgress(norm_ip,port)) {\n        errno = EAGAIN;\n        return 0;\n    }\n\n    /* Add the node with a random address (NULL as first argument to\n     * createClusterNode()). Everything will be fixed during the\n     * handshake. */\n    n = createClusterNode(NULL,CLUSTER_NODE_HANDSHAKE|CLUSTER_NODE_MEET);\n    memcpy(n->ip,norm_ip,sizeof(n->ip));\n    n->port = port;\n    clusterAddNode(n);\n    return 1;\n}\n\n/* Process the gossip section of PING or PONG packets.\n * Note that this function assumes that the packet is already sanity-checked\n * by the caller, not in the content of the gossip section, but in the\n * length. */\nvoid clusterProcessGossipSection(clusterMsg *hdr, clusterLink *link) {\n    uint16_t count = ntohs(hdr->count);\n    clusterMsgDataGossip *g = (clusterMsgDataGossip*) hdr->data.ping.gossip;\n    clusterNode *sender = link->node ? link->node : clusterLookupNode(hdr->sender);\n\n    while(count--) {\n        uint16_t flags = ntohs(g->flags);\n        clusterNode *node;\n        sds ci;\n\n        ci = representClusterNodeFlags(sdsempty(), flags);\n        serverLog(LL_DEBUG,\"GOSSIP %.40s %s:%d %s\",\n            g->nodename,\n            g->ip,\n            ntohs(g->port),\n            ci);\n        sdsfree(ci);\n\n        /* Update our state accordingly to the gossip sections */\n        node = clusterLookupNode(g->nodename);\n        if (node) {\n            /* We already know this node.\n               Handle failure reports, only when the sender is a master. */\n            if (sender && nodeIsMaster(sender) && node != myself) {\n                if (flags & (CLUSTER_NODE_FAIL|CLUSTER_NODE_PFAIL)) {\n                    if (clusterNodeAddFailureReport(node,sender)) {\n                        serverLog(LL_VERBOSE,\n                            \"Node %.40s reported node %.40s as not reachable.\",\n                            sender->name, node->name);\n                    }\n                    markNodeAsFailingIfNeeded(node);\n                } else {\n                    if (clusterNodeDelFailureReport(node,sender)) {\n                        serverLog(LL_VERBOSE,\n                            \"Node %.40s reported node %.40s is back online.\",\n                            sender->name, node->name);\n                    }\n                }\n            }\n\n            /* If we already know this node, but it is not reachable, and\n             * we see a different address in the gossip section of a node that\n             * can talk with this other node, update the address, disconnect\n             * the old link if any, so that we'll attempt to connect with the\n             * new address. */\n            if (node->flags & (CLUSTER_NODE_FAIL|CLUSTER_NODE_PFAIL) &&\n                !(flags & CLUSTER_NODE_NOADDR) &&\n                !(flags & (CLUSTER_NODE_FAIL|CLUSTER_NODE_PFAIL)) &&\n                (strcasecmp(node->ip,g->ip) || node->port != ntohs(g->port)))\n            {\n                if (node->link) freeClusterLink(node->link);\n                memcpy(node->ip,g->ip,NET_IP_STR_LEN);\n                node->port = ntohs(g->port);\n                node->flags &= ~CLUSTER_NODE_NOADDR;\n            }\n        } else {\n            /* If it's not in NOADDR state and we don't have it, we\n             * start a handshake process against this IP/PORT pairs.\n             *\n             * Note that we require that the sender of this gossip message\n             * is a well known node in our cluster, otherwise we risk\n             * joining another cluster. */\n            if (sender &&\n                !(flags & CLUSTER_NODE_NOADDR) &&\n                !clusterBlacklistExists(g->nodename))\n            {\n                clusterStartHandshake(g->ip,ntohs(g->port));\n            }\n        }\n\n        /* Next node */\n        g++;\n    }\n}\n\n/* IP -> string conversion. 'buf' is supposed to at least be 46 bytes. */\nvoid nodeIp2String(char *buf, clusterLink *link) {\n    anetPeerToString(link->fd, buf, NET_IP_STR_LEN, NULL);\n}\n\n/* Update the node address to the IP address that can be extracted\n * from link->fd, and at the specified port.\n * Also disconnect the node link so that we'll connect again to the new\n * address.\n *\n * If the ip/port pair are already correct no operation is performed at\n * all.\n *\n * The function returns 0 if the node address is still the same,\n * otherwise 1 is returned. */\nint nodeUpdateAddressIfNeeded(clusterNode *node, clusterLink *link, int port) {\n    char ip[NET_IP_STR_LEN] = {0};\n\n    /* We don't proceed if the link is the same as the sender link, as this\n     * function is designed to see if the node link is consistent with the\n     * symmetric link that is used to receive PINGs from the node.\n     *\n     * As a side effect this function never frees the passed 'link', so\n     * it is safe to call during packet processing. */\n    if (link == node->link) return 0;\n\n    nodeIp2String(ip,link);\n    if (node->port == port && strcmp(ip,node->ip) == 0) return 0;\n\n    /* IP / port is different, update it. */\n    memcpy(node->ip,ip,sizeof(ip));\n    node->port = port;\n    if (node->link) freeClusterLink(node->link);\n    node->flags &= ~CLUSTER_NODE_NOADDR;\n    serverLog(LL_WARNING,\"Address updated for node %.40s, now %s:%d\",\n        node->name, node->ip, node->port);\n\n    /* Check if this is our master and we have to change the\n     * replication target as well. */\n    if (nodeIsSlave(myself) && myself->slaveof == node)\n        replicationSetMaster(node->ip, node->port);\n    return 1;\n}\n\n/* Reconfigure the specified node 'n' as a master. This function is called when\n * a node that we believed to be a slave is now acting as master in order to\n * update the state of the node. */\nvoid clusterSetNodeAsMaster(clusterNode *n) {\n    if (nodeIsMaster(n)) return;\n\n    if (n->slaveof) {\n        clusterNodeRemoveSlave(n->slaveof,n);\n        if (n != myself) n->flags |= CLUSTER_NODE_MIGRATE_TO;\n    }\n    n->flags &= ~CLUSTER_NODE_SLAVE;\n    n->flags |= CLUSTER_NODE_MASTER;\n    n->slaveof = NULL;\n\n    /* Update config and state. */\n    clusterDoBeforeSleep(CLUSTER_TODO_SAVE_CONFIG|\n                         CLUSTER_TODO_UPDATE_STATE);\n}\n\n/* This function is called when we receive a master configuration via a\n * PING, PONG or UPDATE packet. What we receive is a node, a configEpoch of the\n * node, and the set of slots claimed under this configEpoch.\n *\n * What we do is to rebind the slots with newer configuration compared to our\n * local configuration, and if needed, we turn ourself into a replica of the\n * node (see the function comments for more info).\n *\n * The 'sender' is the node for which we received a configuration update.\n * Sometimes it is not actually the \"Sender\" of the information, like in the\n * case we receive the info via an UPDATE packet. */\nvoid clusterUpdateSlotsConfigWith(clusterNode *sender, uint64_t senderConfigEpoch, unsigned char *slots) {\n    int j;\n    clusterNode *curmaster, *newmaster = NULL;\n    /* The dirty slots list is a list of slots for which we lose the ownership\n     * while having still keys inside. This usually happens after a failover\n     * or after a manual cluster reconfiguration operated by the admin.\n     *\n     * If the update message is not able to demote a master to slave (in this\n     * case we'll resync with the master updating the whole key space), we\n     * need to delete all the keys in the slots we lost ownership. */\n    uint16_t dirty_slots[CLUSTER_SLOTS];\n    int dirty_slots_count = 0;\n\n    /* Here we set curmaster to this node or the node this node\n     * replicates to if it's a slave. In the for loop we are\n     * interested to check if slots are taken away from curmaster. */\n    curmaster = nodeIsMaster(myself) ? myself : myself->slaveof;\n\n    if (sender == myself) {\n        serverLog(LL_WARNING,\"Discarding UPDATE message about myself.\");\n        return;\n    }\n\n    for (j = 0; j < CLUSTER_SLOTS; j++) {\n        if (bitmapTestBit(slots,j)) {\n            /* The slot is already bound to the sender of this message. */\n            if (server.cluster->slots[j] == sender) continue;\n\n            /* The slot is in importing state, it should be modified only\n             * manually via redis-trib (example: a resharding is in progress\n             * and the migrating side slot was already closed and is advertising\n             * a new config. We still want the slot to be closed manually). */\n            if (server.cluster->importing_slots_from[j]) continue;\n\n            /* We rebind the slot to the new node claiming it if:\n             * 1) The slot was unassigned or the new node claims it with a\n             *    greater configEpoch.\n             * 2) We are not currently importing the slot. */\n            if (server.cluster->slots[j] == NULL ||\n                server.cluster->slots[j]->configEpoch < senderConfigEpoch)\n            {\n                /* Was this slot mine, and still contains keys? Mark it as\n                 * a dirty slot. */\n                if (server.cluster->slots[j] == myself &&\n                    countKeysInSlot(j) &&\n                    sender != myself)\n                {\n                    dirty_slots[dirty_slots_count] = j;\n                    dirty_slots_count++;\n                }\n\n                if (server.cluster->slots[j] == curmaster)\n                    newmaster = sender;\n                clusterDelSlot(j);\n                clusterAddSlot(sender,j);\n                clusterDoBeforeSleep(CLUSTER_TODO_SAVE_CONFIG|\n                                     CLUSTER_TODO_UPDATE_STATE|\n                                     CLUSTER_TODO_FSYNC_CONFIG);\n            }\n        }\n    }\n\n    /* If at least one slot was reassigned from a node to another node\n     * with a greater configEpoch, it is possible that:\n     * 1) We are a master left without slots. This means that we were\n     *    failed over and we should turn into a replica of the new\n     *    master.\n     * 2) We are a slave and our master is left without slots. We need\n     *    to replicate to the new slots owner. */\n    if (newmaster && curmaster->numslots == 0) {\n        serverLog(LL_WARNING,\n            \"Configuration change detected. Reconfiguring myself \"\n            \"as a replica of %.40s\", sender->name);\n        clusterSetMaster(sender);\n        clusterDoBeforeSleep(CLUSTER_TODO_SAVE_CONFIG|\n                             CLUSTER_TODO_UPDATE_STATE|\n                             CLUSTER_TODO_FSYNC_CONFIG);\n    } else if (dirty_slots_count) {\n        /* If we are here, we received an update message which removed\n         * ownership for certain slots we still have keys about, but still\n         * we are serving some slots, so this master node was not demoted to\n         * a slave.\n         *\n         * In order to maintain a consistent state between keys and slots\n         * we need to remove all the keys from the slots we lost. */\n        for (j = 0; j < dirty_slots_count; j++)\n            delKeysInSlot(dirty_slots[j]);\n    }\n}\n\n/* When this function is called, there is a packet to process starting\n * at node->rcvbuf. Releasing the buffer is up to the caller, so this\n * function should just handle the higher level stuff of processing the\n * packet, modifying the cluster state if needed.\n *\n * The function returns 1 if the link is still valid after the packet\n * was processed, otherwise 0 if the link was freed since the packet\n * processing lead to some inconsistency error (for instance a PONG\n * received from the wrong sender ID). */\nint clusterProcessPacket(clusterLink *link) {\n    clusterMsg *hdr = (clusterMsg*) link->rcvbuf;\n    uint32_t totlen = ntohl(hdr->totlen);\n    uint16_t type = ntohs(hdr->type);\n\n    server.cluster->stats_bus_messages_received++;\n    serverLog(LL_DEBUG,\"--- Processing packet of type %d, %lu bytes\",\n        type, (unsigned long) totlen);\n\n    /* Perform sanity checks */\n    if (totlen < 16) return 1; /* At least signature, version, totlen, count. */\n    if (totlen > sdslen(link->rcvbuf)) return 1;\n\n    if (ntohs(hdr->ver) != CLUSTER_PROTO_VER) {\n        /* Can't handle messages of different versions. */\n        return 1;\n    }\n\n    uint16_t flags = ntohs(hdr->flags);\n    uint64_t senderCurrentEpoch = 0, senderConfigEpoch = 0;\n    clusterNode *sender;\n\n    if (type == CLUSTERMSG_TYPE_PING || type == CLUSTERMSG_TYPE_PONG ||\n        type == CLUSTERMSG_TYPE_MEET)\n    {\n        uint16_t count = ntohs(hdr->count);\n        uint32_t explen; /* expected length of this packet */\n\n        explen = sizeof(clusterMsg)-sizeof(union clusterMsgData);\n        explen += (sizeof(clusterMsgDataGossip)*count);\n        if (totlen != explen) return 1;\n    } else if (type == CLUSTERMSG_TYPE_FAIL) {\n        uint32_t explen = sizeof(clusterMsg)-sizeof(union clusterMsgData);\n\n        explen += sizeof(clusterMsgDataFail);\n        if (totlen != explen) return 1;\n    } else if (type == CLUSTERMSG_TYPE_PUBLISH) {\n        uint32_t explen = sizeof(clusterMsg)-sizeof(union clusterMsgData);\n\n        explen += sizeof(clusterMsgDataPublish) -\n                8 +\n                ntohl(hdr->data.publish.msg.channel_len) +\n                ntohl(hdr->data.publish.msg.message_len);\n        if (totlen != explen) return 1;\n    } else if (type == CLUSTERMSG_TYPE_FAILOVER_AUTH_REQUEST ||\n               type == CLUSTERMSG_TYPE_FAILOVER_AUTH_ACK ||\n               type == CLUSTERMSG_TYPE_MFSTART)\n    {\n        uint32_t explen = sizeof(clusterMsg)-sizeof(union clusterMsgData);\n\n        if (totlen != explen) return 1;\n    } else if (type == CLUSTERMSG_TYPE_UPDATE) {\n        uint32_t explen = sizeof(clusterMsg)-sizeof(union clusterMsgData);\n\n        explen += sizeof(clusterMsgDataUpdate);\n        if (totlen != explen) return 1;\n    }\n\n    /* Check if the sender is a known node. */\n    sender = clusterLookupNode(hdr->sender);\n    if (sender && !nodeInHandshake(sender)) {\n        /* Update our curretEpoch if we see a newer epoch in the cluster. */\n        senderCurrentEpoch = ntohu64(hdr->currentEpoch);\n        senderConfigEpoch = ntohu64(hdr->configEpoch);\n        if (senderCurrentEpoch > server.cluster->currentEpoch)\n            server.cluster->currentEpoch = senderCurrentEpoch;\n        /* Update the sender configEpoch if it is publishing a newer one. */\n        if (senderConfigEpoch > sender->configEpoch) {\n            sender->configEpoch = senderConfigEpoch;\n            clusterDoBeforeSleep(CLUSTER_TODO_SAVE_CONFIG|\n                                 CLUSTER_TODO_FSYNC_CONFIG);\n        }\n        /* Update the replication offset info for this node. */\n        sender->repl_offset = ntohu64(hdr->offset);\n        sender->repl_offset_time = mstime();\n        /* If we are a slave performing a manual failover and our master\n         * sent its offset while already paused, populate the MF state. */\n        if (server.cluster->mf_end &&\n            nodeIsSlave(myself) &&\n            myself->slaveof == sender &&\n            hdr->mflags[0] & CLUSTERMSG_FLAG0_PAUSED &&\n            server.cluster->mf_master_offset == 0)\n        {\n            server.cluster->mf_master_offset = sender->repl_offset;\n            serverLog(LL_WARNING,\n                \"Received replication offset for paused \"\n                \"master manual failover: %lld\",\n                server.cluster->mf_master_offset);\n        }\n    }\n\n    /* Initial processing of PING and MEET requests replying with a PONG. */\n    if (type == CLUSTERMSG_TYPE_PING || type == CLUSTERMSG_TYPE_MEET) {\n        serverLog(LL_DEBUG,\"Ping packet received: %p\", (void*)link->node);\n\n        /* We use incoming MEET messages in order to set the address\n         * for 'myself', since only other cluster nodes will send us\n         * MEET messagses on handshakes, when the cluster joins, or\n         * later if we changed address, and those nodes will use our\n         * official address to connect to us. So by obtaining this address\n         * from the socket is a simple way to discover / update our own\n         * address in the cluster without it being hardcoded in the config.\n         *\n         * However if we don't have an address at all, we update the address\n         * even with a normal PING packet. If it's wrong it will be fixed\n         * by MEET later. */\n        if (type == CLUSTERMSG_TYPE_MEET || myself->ip[0] == '\\0') {\n            char ip[NET_IP_STR_LEN];\n\n            if (anetSockName(link->fd,ip,sizeof(ip),NULL) != -1 &&\n                strcmp(ip,myself->ip))\n            {\n                memcpy(myself->ip,ip,NET_IP_STR_LEN);\n                serverLog(LL_WARNING,\"IP address for this node updated to %s\",\n                    myself->ip);\n                clusterDoBeforeSleep(CLUSTER_TODO_SAVE_CONFIG);\n            }\n        }\n\n        /* Add this node if it is new for us and the msg type is MEET.\n         * In this stage we don't try to add the node with the right\n         * flags, slaveof pointer, and so forth, as this details will be\n         * resolved when we'll receive PONGs from the node. */\n        if (!sender && type == CLUSTERMSG_TYPE_MEET) {\n            clusterNode *node;\n\n            node = createClusterNode(NULL,CLUSTER_NODE_HANDSHAKE);\n            nodeIp2String(node->ip,link);\n            node->port = ntohs(hdr->port);\n            clusterAddNode(node);\n            clusterDoBeforeSleep(CLUSTER_TODO_SAVE_CONFIG);\n        }\n\n        /* If this is a MEET packet from an unknown node, we still process\n         * the gossip section here since we have to trust the sender because\n         * of the message type. */\n        if (!sender && type == CLUSTERMSG_TYPE_MEET)\n            clusterProcessGossipSection(hdr,link);\n\n        /* Anyway reply with a PONG */\n        clusterSendPing(link,CLUSTERMSG_TYPE_PONG);\n    }\n\n    /* PING, PONG, MEET: process config information. */\n    if (type == CLUSTERMSG_TYPE_PING || type == CLUSTERMSG_TYPE_PONG ||\n        type == CLUSTERMSG_TYPE_MEET)\n    {\n        serverLog(LL_DEBUG,\"%s packet received: %p\",\n            type == CLUSTERMSG_TYPE_PING ? \"ping\" : \"pong\",\n            (void*)link->node);\n        if (link->node) {\n            if (nodeInHandshake(link->node)) {\n                /* If we already have this node, try to change the\n                 * IP/port of the node with the new one. */\n                if (sender) {\n                    serverLog(LL_VERBOSE,\n                        \"Handshake: we already know node %.40s, \"\n                        \"updating the address if needed.\", sender->name);\n                    if (nodeUpdateAddressIfNeeded(sender,link,ntohs(hdr->port)))\n                    {\n                        clusterDoBeforeSleep(CLUSTER_TODO_SAVE_CONFIG|\n                                             CLUSTER_TODO_UPDATE_STATE);\n                    }\n                    /* Free this node as we already have it. This will\n                     * cause the link to be freed as well. */\n                    clusterDelNode(link->node);\n                    return 0;\n                }\n\n                /* First thing to do is replacing the random name with the\n                 * right node name if this was a handshake stage. */\n                clusterRenameNode(link->node, hdr->sender);\n                serverLog(LL_DEBUG,\"Handshake with node %.40s completed.\",\n                    link->node->name);\n                link->node->flags &= ~CLUSTER_NODE_HANDSHAKE;\n                link->node->flags |= flags&(CLUSTER_NODE_MASTER|CLUSTER_NODE_SLAVE);\n                clusterDoBeforeSleep(CLUSTER_TODO_SAVE_CONFIG);\n            } else if (memcmp(link->node->name,hdr->sender,\n                        CLUSTER_NAMELEN) != 0)\n            {\n                /* If the reply has a non matching node ID we\n                 * disconnect this node and set it as not having an associated\n                 * address. */\n                serverLog(LL_DEBUG,\"PONG contains mismatching sender ID. About node %.40s added %d ms ago, having flags %d\",\n                    link->node->name,\n                    (int)(mstime()-(link->node->ctime)),\n                    link->node->flags);\n                link->node->flags |= CLUSTER_NODE_NOADDR;\n                link->node->ip[0] = '\\0';\n                link->node->port = 0;\n                freeClusterLink(link);\n                clusterDoBeforeSleep(CLUSTER_TODO_SAVE_CONFIG);\n                return 0;\n            }\n        }\n\n        /* Update the node address if it changed. */\n        if (sender && type == CLUSTERMSG_TYPE_PING &&\n            !nodeInHandshake(sender) &&\n            nodeUpdateAddressIfNeeded(sender,link,ntohs(hdr->port)))\n        {\n            clusterDoBeforeSleep(CLUSTER_TODO_SAVE_CONFIG|\n                                 CLUSTER_TODO_UPDATE_STATE);\n        }\n\n        /* Update our info about the node */\n        if (link->node && type == CLUSTERMSG_TYPE_PONG) {\n            link->node->pong_received = mstime();\n            link->node->ping_sent = 0;\n\n            /* The PFAIL condition can be reversed without external\n             * help if it is momentary (that is, if it does not\n             * turn into a FAIL state).\n             *\n             * The FAIL condition is also reversible under specific\n             * conditions detected by clearNodeFailureIfNeeded(). */\n            if (nodeTimedOut(link->node)) {\n                link->node->flags &= ~CLUSTER_NODE_PFAIL;\n                clusterDoBeforeSleep(CLUSTER_TODO_SAVE_CONFIG|\n                                     CLUSTER_TODO_UPDATE_STATE);\n            } else if (nodeFailed(link->node)) {\n                clearNodeFailureIfNeeded(link->node);\n            }\n        }\n\n        /* Check for role switch: slave -> master or master -> slave. */\n        if (sender) {\n            if (!memcmp(hdr->slaveof,CLUSTER_NODE_NULL_NAME,\n                sizeof(hdr->slaveof)))\n            {\n                /* Node is a master. */\n                clusterSetNodeAsMaster(sender);\n            } else {\n                /* Node is a slave. */\n                clusterNode *master = clusterLookupNode(hdr->slaveof);\n\n                if (nodeIsMaster(sender)) {\n                    /* Master turned into a slave! Reconfigure the node. */\n                    clusterDelNodeSlots(sender);\n                    sender->flags &= ~(CLUSTER_NODE_MASTER|\n                                       CLUSTER_NODE_MIGRATE_TO);\n                    sender->flags |= CLUSTER_NODE_SLAVE;\n\n                    /* Update config and state. */\n                    clusterDoBeforeSleep(CLUSTER_TODO_SAVE_CONFIG|\n                                         CLUSTER_TODO_UPDATE_STATE);\n                }\n\n                /* Master node changed for this slave? */\n                if (master && sender->slaveof != master) {\n                    if (sender->slaveof)\n                        clusterNodeRemoveSlave(sender->slaveof,sender);\n                    clusterNodeAddSlave(master,sender);\n                    sender->slaveof = master;\n\n                    /* Update config. */\n                    clusterDoBeforeSleep(CLUSTER_TODO_SAVE_CONFIG);\n                }\n            }\n        }\n\n        /* Update our info about served slots.\n         *\n         * Note: this MUST happen after we update the master/slave state\n         * so that CLUSTER_NODE_MASTER flag will be set. */\n\n        /* Many checks are only needed if the set of served slots this\n         * instance claims is different compared to the set of slots we have\n         * for it. Check this ASAP to avoid other computational expansive\n         * checks later. */\n        clusterNode *sender_master = NULL; /* Sender or its master if slave. */\n        int dirty_slots = 0; /* Sender claimed slots don't match my view? */\n\n        if (sender) {\n            sender_master = nodeIsMaster(sender) ? sender : sender->slaveof;\n            if (sender_master) {\n                dirty_slots = memcmp(sender_master->slots,\n                        hdr->myslots,sizeof(hdr->myslots)) != 0;\n            }\n        }\n\n        /* 1) If the sender of the message is a master, and we detected that\n         *    the set of slots it claims changed, scan the slots to see if we\n         *    need to update our configuration. */\n        if (sender && nodeIsMaster(sender) && dirty_slots)\n            clusterUpdateSlotsConfigWith(sender,senderConfigEpoch,hdr->myslots);\n\n        /* 2) We also check for the reverse condition, that is, the sender\n         *    claims to serve slots we know are served by a master with a\n         *    greater configEpoch. If this happens we inform the sender.\n         *\n         * This is useful because sometimes after a partition heals, a\n         * reappearing master may be the last one to claim a given set of\n         * hash slots, but with a configuration that other instances know to\n         * be deprecated. Example:\n         *\n         * A and B are master and slave for slots 1,2,3.\n         * A is partitioned away, B gets promoted.\n         * B is partitioned away, and A returns available.\n         *\n         * Usually B would PING A publishing its set of served slots and its\n         * configEpoch, but because of the partition B can't inform A of the\n         * new configuration, so other nodes that have an updated table must\n         * do it. In this way A will stop to act as a master (or can try to\n         * failover if there are the conditions to win the election). */\n        if (sender && dirty_slots) {\n            int j;\n\n            for (j = 0; j < CLUSTER_SLOTS; j++) {\n                if (bitmapTestBit(hdr->myslots,j)) {\n                    if (server.cluster->slots[j] == sender ||\n                        server.cluster->slots[j] == NULL) continue;\n                    if (server.cluster->slots[j]->configEpoch >\n                        senderConfigEpoch)\n                    {\n                        serverLog(LL_VERBOSE,\n                            \"Node %.40s has old slots configuration, sending \"\n                            \"an UPDATE message about %.40s\",\n                                sender->name, server.cluster->slots[j]->name);\n                        clusterSendUpdate(sender->link,\n                            server.cluster->slots[j]);\n\n                        /* TODO: instead of exiting the loop send every other\n                         * UPDATE packet for other nodes that are the new owner\n                         * of sender's slots. */\n                        break;\n                    }\n                }\n            }\n        }\n\n        /* If our config epoch collides with the sender's try to fix\n         * the problem. */\n        if (sender &&\n            nodeIsMaster(myself) && nodeIsMaster(sender) &&\n            senderConfigEpoch == myself->configEpoch)\n        {\n            clusterHandleConfigEpochCollision(sender);\n        }\n\n        /* Get info from the gossip section */\n        if (sender) clusterProcessGossipSection(hdr,link);\n    } else if (type == CLUSTERMSG_TYPE_FAIL) {\n        clusterNode *failing;\n\n        if (sender) {\n            failing = clusterLookupNode(hdr->data.fail.about.nodename);\n            if (failing &&\n                !(failing->flags & (CLUSTER_NODE_FAIL|CLUSTER_NODE_MYSELF)))\n            {\n                serverLog(LL_NOTICE,\n                    \"FAIL message received from %.40s about %.40s\",\n                    hdr->sender, hdr->data.fail.about.nodename);\n                failing->flags |= CLUSTER_NODE_FAIL;\n                failing->fail_time = mstime();\n                failing->flags &= ~CLUSTER_NODE_PFAIL;\n                clusterDoBeforeSleep(CLUSTER_TODO_SAVE_CONFIG|\n                                     CLUSTER_TODO_UPDATE_STATE);\n            }\n        } else {\n            serverLog(LL_NOTICE,\n                \"Ignoring FAIL message from unknown node %.40s about %.40s\",\n                hdr->sender, hdr->data.fail.about.nodename);\n        }\n    } else if (type == CLUSTERMSG_TYPE_PUBLISH) {\n        robj *channel, *message;\n        uint32_t channel_len, message_len;\n\n        /* Don't bother creating useless objects if there are no\n         * Pub/Sub subscribers. */\n        if (dictSize(server.pubsub_channels) ||\n           listLength(server.pubsub_patterns))\n        {\n            channel_len = ntohl(hdr->data.publish.msg.channel_len);\n            message_len = ntohl(hdr->data.publish.msg.message_len);\n            channel = createStringObject(\n                        (char*)hdr->data.publish.msg.bulk_data,channel_len);\n            message = createStringObject(\n                        (char*)hdr->data.publish.msg.bulk_data+channel_len,\n                        message_len);\n            pubsubPublishMessage(channel,message);\n            decrRefCount(channel);\n            decrRefCount(message);\n        }\n    } else if (type == CLUSTERMSG_TYPE_FAILOVER_AUTH_REQUEST) {\n        if (!sender) return 1;  /* We don't know that node. */\n        clusterSendFailoverAuthIfNeeded(sender,hdr);\n    } else if (type == CLUSTERMSG_TYPE_FAILOVER_AUTH_ACK) {\n        if (!sender) return 1;  /* We don't know that node. */\n        /* We consider this vote only if the sender is a master serving\n         * a non zero number of slots, and its currentEpoch is greater or\n         * equal to epoch where this node started the election. */\n        if (nodeIsMaster(sender) && sender->numslots > 0 &&\n            senderCurrentEpoch >= server.cluster->failover_auth_epoch)\n        {\n            server.cluster->failover_auth_count++;\n            /* Maybe we reached a quorum here, set a flag to make sure\n             * we check ASAP. */\n            clusterDoBeforeSleep(CLUSTER_TODO_HANDLE_FAILOVER);\n        }\n    } else if (type == CLUSTERMSG_TYPE_MFSTART) {\n        /* This message is acceptable only if I'm a master and the sender\n         * is one of my slaves. */\n        if (!sender || sender->slaveof != myself) return 1;\n        /* Manual failover requested from slaves. Initialize the state\n         * accordingly. */\n        resetManualFailover();\n        server.cluster->mf_end = mstime() + CLUSTER_MF_TIMEOUT;\n        server.cluster->mf_slave = sender;\n        pauseClients(mstime()+(CLUSTER_MF_TIMEOUT*2));\n        serverLog(LL_WARNING,\"Manual failover requested by slave %.40s.\",\n            sender->name);\n    } else if (type == CLUSTERMSG_TYPE_UPDATE) {\n        clusterNode *n; /* The node the update is about. */\n        uint64_t reportedConfigEpoch =\n                    ntohu64(hdr->data.update.nodecfg.configEpoch);\n\n        if (!sender) return 1;  /* We don't know the sender. */\n        n = clusterLookupNode(hdr->data.update.nodecfg.nodename);\n        if (!n) return 1;   /* We don't know the reported node. */\n        if (n->configEpoch >= reportedConfigEpoch) return 1; /* Nothing new. */\n\n        /* If in our current config the node is a slave, set it as a master. */\n        if (nodeIsSlave(n)) clusterSetNodeAsMaster(n);\n\n        /* Update the node's configEpoch. */\n        n->configEpoch = reportedConfigEpoch;\n        clusterDoBeforeSleep(CLUSTER_TODO_SAVE_CONFIG|\n                             CLUSTER_TODO_FSYNC_CONFIG);\n\n        /* Check the bitmap of served slots and update our\n         * config accordingly. */\n        clusterUpdateSlotsConfigWith(n,reportedConfigEpoch,\n            hdr->data.update.nodecfg.slots);\n    } else {\n        serverLog(LL_WARNING,\"Received unknown packet type: %d\", type);\n    }\n    return 1;\n}\n\n/* This function is called when we detect the link with this node is lost.\n   We set the node as no longer connected. The Cluster Cron will detect\n   this connection and will try to get it connected again.\n\n   Instead if the node is a temporary node used to accept a query, we\n   completely free the node on error. */\nvoid handleLinkIOError(clusterLink *link) {\n    freeClusterLink(link);\n}\n\n/* Send data. This is handled using a trivial send buffer that gets\n * consumed by write(). We don't try to optimize this for speed too much\n * as this is a very low traffic channel. */\nvoid clusterWriteHandler(aeEventLoop *el, int fd, void *privdata, int mask) {\n    clusterLink *link = (clusterLink*) privdata;\n    ssize_t nwritten;\n    UNUSED(el);\n    UNUSED(mask);\n\n    nwritten = write(fd, link->sndbuf, sdslen(link->sndbuf));\n    if (nwritten <= 0) {\n        serverLog(LL_DEBUG,\"I/O error writing to node link: %s\",\n            strerror(errno));\n        handleLinkIOError(link);\n        return;\n    }\n    sdsrange(link->sndbuf,nwritten,-1);\n    if (sdslen(link->sndbuf) == 0)\n        aeDeleteFileEvent(server.el, link->fd, AE_WRITABLE);\n}\n\n/* Read data. Try to read the first field of the header first to check the\n * full length of the packet. When a whole packet is in memory this function\n * will call the function to process the packet. And so forth. */\nvoid clusterReadHandler(aeEventLoop *el, int fd, void *privdata, int mask) {\n    char buf[sizeof(clusterMsg)];\n    ssize_t nread;\n    clusterMsg *hdr;\n    clusterLink *link = (clusterLink*) privdata;\n    unsigned int readlen, rcvbuflen;\n    UNUSED(el);\n    UNUSED(mask);\n\n    while(1) { /* Read as long as there is data to read. */\n        rcvbuflen = sdslen(link->rcvbuf);\n        if (rcvbuflen < 8) {\n            /* First, obtain the first 8 bytes to get the full message\n             * length. */\n            readlen = 8 - rcvbuflen;\n        } else {\n            /* Finally read the full message. */\n            hdr = (clusterMsg*) link->rcvbuf;\n            if (rcvbuflen == 8) {\n                /* Perform some sanity check on the message signature\n                 * and length. */\n                if (memcmp(hdr->sig,\"RCmb\",4) != 0 ||\n                    ntohl(hdr->totlen) < CLUSTERMSG_MIN_LEN)\n                {\n                    serverLog(LL_WARNING,\n                        \"Bad message length or signature received \"\n                        \"from Cluster bus.\");\n                    handleLinkIOError(link);\n                    return;\n                }\n            }\n            readlen = ntohl(hdr->totlen) - rcvbuflen;\n            if (readlen > sizeof(buf)) readlen = sizeof(buf);\n        }\n\n        nread = read(fd,buf,readlen);\n        if (nread == -1 && errno == EAGAIN) return; /* No more data ready. */\n\n        if (nread <= 0) {\n            /* I/O error... */\n            serverLog(LL_DEBUG,\"I/O error reading from node link: %s\",\n                (nread == 0) ? \"connection closed\" : strerror(errno));\n            handleLinkIOError(link);\n            return;\n        } else {\n            /* Read data and recast the pointer to the new buffer. */\n            link->rcvbuf = sdscatlen(link->rcvbuf,buf,nread);\n            hdr = (clusterMsg*) link->rcvbuf;\n            rcvbuflen += nread;\n        }\n\n        /* Total length obtained? Process this packet. */\n        if (rcvbuflen >= 8 && rcvbuflen == ntohl(hdr->totlen)) {\n            if (clusterProcessPacket(link)) {\n                sdsfree(link->rcvbuf);\n                link->rcvbuf = sdsempty();\n            } else {\n                return; /* Link no longer valid. */\n            }\n        }\n    }\n}\n\n/* Put stuff into the send buffer.\n *\n * It is guaranteed that this function will never have as a side effect\n * the link to be invalidated, so it is safe to call this function\n * from event handlers that will do stuff with the same link later. */\nvoid clusterSendMessage(clusterLink *link, unsigned char *msg, size_t msglen) {\n    if (sdslen(link->sndbuf) == 0 && msglen != 0)\n        aeCreateFileEvent(server.el,link->fd,AE_WRITABLE,\n                    clusterWriteHandler,link);\n\n    link->sndbuf = sdscatlen(link->sndbuf, msg, msglen);\n    server.cluster->stats_bus_messages_sent++;\n}\n\n/* Send a message to all the nodes that are part of the cluster having\n * a connected link.\n *\n * It is guaranteed that this function will never have as a side effect\n * some node->link to be invalidated, so it is safe to call this function\n * from event handlers that will do stuff with node links later. */\nvoid clusterBroadcastMessage(void *buf, size_t len) {\n    dictIterator *di;\n    dictEntry *de;\n\n    di = dictGetSafeIterator(server.cluster->nodes);\n    while((de = dictNext(di)) != NULL) {\n        clusterNode *node = dictGetVal(de);\n\n        if (!node->link) continue;\n        if (node->flags & (CLUSTER_NODE_MYSELF|CLUSTER_NODE_HANDSHAKE))\n            continue;\n        clusterSendMessage(node->link,buf,len);\n    }\n    dictReleaseIterator(di);\n}\n\n/* Build the message header. hdr must point to a buffer at least\n * sizeof(clusterMsg) in bytes. */\nvoid clusterBuildMessageHdr(clusterMsg *hdr, int type) {\n    int totlen = 0;\n    uint64_t offset;\n    clusterNode *master;\n\n    /* If this node is a master, we send its slots bitmap and configEpoch.\n     * If this node is a slave we send the master's information instead (the\n     * node is flagged as slave so the receiver knows that it is NOT really\n     * in charge for this slots. */\n    master = (nodeIsSlave(myself) && myself->slaveof) ?\n              myself->slaveof : myself;\n\n    memset(hdr,0,sizeof(*hdr));\n    hdr->ver = htons(CLUSTER_PROTO_VER);\n    hdr->sig[0] = 'R';\n    hdr->sig[1] = 'C';\n    hdr->sig[2] = 'm';\n    hdr->sig[3] = 'b';\n    hdr->type = htons(type);\n    memcpy(hdr->sender,myself->name,CLUSTER_NAMELEN);\n\n    memcpy(hdr->myslots,master->slots,sizeof(hdr->myslots));\n    memset(hdr->slaveof,0,CLUSTER_NAMELEN);\n    if (myself->slaveof != NULL)\n        memcpy(hdr->slaveof,myself->slaveof->name, CLUSTER_NAMELEN);\n    hdr->port = htons(server.port);\n    hdr->flags = htons(myself->flags);\n    hdr->state = server.cluster->state;\n\n    /* Set the currentEpoch and configEpochs. */\n    hdr->currentEpoch = htonu64(server.cluster->currentEpoch);\n    hdr->configEpoch = htonu64(master->configEpoch);\n\n    /* Set the replication offset. */\n    if (nodeIsSlave(myself))\n        offset = replicationGetSlaveOffset();\n    else\n        offset = server.master_repl_offset;\n    hdr->offset = htonu64(offset);\n\n    /* Set the message flags. */\n    if (nodeIsMaster(myself) && server.cluster->mf_end)\n        hdr->mflags[0] |= CLUSTERMSG_FLAG0_PAUSED;\n\n    /* Compute the message length for certain messages. For other messages\n     * this is up to the caller. */\n    if (type == CLUSTERMSG_TYPE_FAIL) {\n        totlen = sizeof(clusterMsg)-sizeof(union clusterMsgData);\n        totlen += sizeof(clusterMsgDataFail);\n    } else if (type == CLUSTERMSG_TYPE_UPDATE) {\n        totlen = sizeof(clusterMsg)-sizeof(union clusterMsgData);\n        totlen += sizeof(clusterMsgDataUpdate);\n    }\n    hdr->totlen = htonl(totlen);\n    /* For PING, PONG, and MEET, fixing the totlen field is up to the caller. */\n}\n\n/* Send a PING or PONG packet to the specified node, making sure to add enough\n * gossip informations. */\nvoid clusterSendPing(clusterLink *link, int type) {\n    unsigned char *buf;\n    clusterMsg *hdr;\n    int gossipcount = 0; /* Number of gossip sections added so far. */\n    int wanted; /* Number of gossip sections we want to append if possible. */\n    int totlen; /* Total packet length. */\n    /* freshnodes is the max number of nodes we can hope to append at all:\n     * nodes available minus two (ourself and the node we are sending the\n     * message to). However practically there may be less valid nodes since\n     * nodes in handshake state, disconnected, are not considered. */\n    int freshnodes = dictSize(server.cluster->nodes)-2;\n\n    /* How many gossip sections we want to add? 1/10 of the number of nodes\n     * and anyway at least 3. Why 1/10?\n     *\n     * If we have N masters, with N/10 entries, and we consider that in\n     * node_timeout we exchange with each other node at least 4 packets\n     * (we ping in the worst case in node_timeout/2 time, and we also\n     * receive two pings from the host), we have a total of 8 packets\n     * in the node_timeout*2 falure reports validity time. So we have\n     * that, for a single PFAIL node, we can expect to receive the following\n     * number of failure reports (in the specified window of time):\n     *\n     * PROB * GOSSIP_ENTRIES_PER_PACKET * TOTAL_PACKETS:\n     *\n     * PROB = probability of being featured in a single gossip entry,\n     *        which is 1 / NUM_OF_NODES.\n     * ENTRIES = 10.\n     * TOTAL_PACKETS = 2 * 4 * NUM_OF_MASTERS.\n     *\n     * If we assume we have just masters (so num of nodes and num of masters\n     * is the same), with 1/10 we always get over the majority, and specifically\n     * 80% of the number of nodes, to account for many masters failing at the\n     * same time.\n     *\n     * Since we have non-voting slaves that lower the probability of an entry\n     * to feature our node, we set the number of entires per packet as\n     * 10% of the total nodes we have. */\n    wanted = floor(dictSize(server.cluster->nodes)/10);\n    if (wanted < 3) wanted = 3;\n    if (wanted > freshnodes) wanted = freshnodes;\n\n    /* Compute the maxium totlen to allocate our buffer. We'll fix the totlen\n     * later according to the number of gossip sections we really were able\n     * to put inside the packet. */\n    totlen = sizeof(clusterMsg)-sizeof(union clusterMsgData);\n    totlen += (sizeof(clusterMsgDataGossip)*wanted);\n    /* Note: clusterBuildMessageHdr() expects the buffer to be always at least\n     * sizeof(clusterMsg) or more. */\n    if (totlen < (int)sizeof(clusterMsg)) totlen = sizeof(clusterMsg);\n    buf = zcalloc(totlen);\n    hdr = (clusterMsg*) buf;\n\n    /* Populate the header. */\n    if (link->node && type == CLUSTERMSG_TYPE_PING)\n        link->node->ping_sent = mstime();\n    clusterBuildMessageHdr(hdr,type);\n\n    /* Populate the gossip fields */\n    int maxiterations = wanted*3;\n    while(freshnodes > 0 && gossipcount < wanted && maxiterations--) {\n        dictEntry *de = dictGetRandomKey(server.cluster->nodes);\n        clusterNode *this = dictGetVal(de);\n        clusterMsgDataGossip *gossip;\n        int j;\n\n        /* Don't include this node: the whole packet header is about us\n         * already, so we just gossip about other nodes. */\n        if (this == myself) continue;\n\n        /* Give a bias to FAIL/PFAIL nodes. */\n        if (maxiterations > wanted*2 &&\n            !(this->flags & (CLUSTER_NODE_PFAIL|CLUSTER_NODE_FAIL)))\n            continue;\n\n        /* In the gossip section don't include:\n         * 1) Nodes in HANDSHAKE state.\n         * 3) Nodes with the NOADDR flag set.\n         * 4) Disconnected nodes if they don't have configured slots.\n         */\n        if (this->flags & (CLUSTER_NODE_HANDSHAKE|CLUSTER_NODE_NOADDR) ||\n            (this->link == NULL && this->numslots == 0))\n        {\n            freshnodes--; /* Tecnically not correct, but saves CPU. */\n            continue;\n        }\n\n        /* Check if we already added this node */\n        for (j = 0; j < gossipcount; j++) {\n            if (memcmp(hdr->data.ping.gossip[j].nodename,this->name,\n                    CLUSTER_NAMELEN) == 0) break;\n        }\n        if (j != gossipcount) continue;\n\n        /* Add it */\n        freshnodes--;\n        gossip = &(hdr->data.ping.gossip[gossipcount]);\n        memcpy(gossip->nodename,this->name,CLUSTER_NAMELEN);\n        gossip->ping_sent = htonl(this->ping_sent);\n        gossip->pong_received = htonl(this->pong_received);\n        memcpy(gossip->ip,this->ip,sizeof(this->ip));\n        gossip->port = htons(this->port);\n        gossip->flags = htons(this->flags);\n        gossip->notused1 = 0;\n        gossip->notused2 = 0;\n        gossipcount++;\n    }\n\n    /* Ready to send... fix the totlen fiend and queue the message in the\n     * output buffer. */\n    totlen = sizeof(clusterMsg)-sizeof(union clusterMsgData);\n    totlen += (sizeof(clusterMsgDataGossip)*gossipcount);\n    hdr->count = htons(gossipcount);\n    hdr->totlen = htonl(totlen);\n    clusterSendMessage(link,buf,totlen);\n    zfree(buf);\n}\n\n/* Send a PONG packet to every connected node that's not in handshake state\n * and for which we have a valid link.\n *\n * In Redis Cluster pongs are not used just for failure detection, but also\n * to carry important configuration information. So broadcasting a pong is\n * useful when something changes in the configuration and we want to make\n * the cluster aware ASAP (for instance after a slave promotion).\n *\n * The 'target' argument specifies the receiving instances using the\n * defines below:\n *\n * CLUSTER_BROADCAST_ALL -> All known instances.\n * CLUSTER_BROADCAST_LOCAL_SLAVES -> All slaves in my master-slaves ring.\n */\n#define CLUSTER_BROADCAST_ALL 0\n#define CLUSTER_BROADCAST_LOCAL_SLAVES 1\nvoid clusterBroadcastPong(int target) {\n    dictIterator *di;\n    dictEntry *de;\n\n    di = dictGetSafeIterator(server.cluster->nodes);\n    while((de = dictNext(di)) != NULL) {\n        clusterNode *node = dictGetVal(de);\n\n        if (!node->link) continue;\n        if (node == myself || nodeInHandshake(node)) continue;\n        if (target == CLUSTER_BROADCAST_LOCAL_SLAVES) {\n            int local_slave =\n                nodeIsSlave(node) && node->slaveof &&\n                (node->slaveof == myself || node->slaveof == myself->slaveof);\n            if (!local_slave) continue;\n        }\n        clusterSendPing(node->link,CLUSTERMSG_TYPE_PONG);\n    }\n    dictReleaseIterator(di);\n}\n\n/* Send a PUBLISH message.\n *\n * If link is NULL, then the message is broadcasted to the whole cluster. */\nvoid clusterSendPublish(clusterLink *link, robj *channel, robj *message) {\n    unsigned char buf[sizeof(clusterMsg)], *payload;\n    clusterMsg *hdr = (clusterMsg*) buf;\n    uint32_t totlen;\n    uint32_t channel_len, message_len;\n\n    channel = getDecodedObject(channel);\n    message = getDecodedObject(message);\n    channel_len = sdslen(channel->ptr);\n    message_len = sdslen(message->ptr);\n\n    clusterBuildMessageHdr(hdr,CLUSTERMSG_TYPE_PUBLISH);\n    totlen = sizeof(clusterMsg)-sizeof(union clusterMsgData);\n    totlen += sizeof(clusterMsgDataPublish) - 8 + channel_len + message_len;\n\n    hdr->data.publish.msg.channel_len = htonl(channel_len);\n    hdr->data.publish.msg.message_len = htonl(message_len);\n    hdr->totlen = htonl(totlen);\n\n    /* Try to use the local buffer if possible */\n    if (totlen < sizeof(buf)) {\n        payload = buf;\n    } else {\n        payload = zmalloc(totlen);\n        memcpy(payload,hdr,sizeof(*hdr));\n        hdr = (clusterMsg*) payload;\n    }\n    memcpy(hdr->data.publish.msg.bulk_data,channel->ptr,sdslen(channel->ptr));\n    memcpy(hdr->data.publish.msg.bulk_data+sdslen(channel->ptr),\n        message->ptr,sdslen(message->ptr));\n\n    if (link)\n        clusterSendMessage(link,payload,totlen);\n    else\n        clusterBroadcastMessage(payload,totlen);\n\n    decrRefCount(channel);\n    decrRefCount(message);\n    if (payload != buf) zfree(payload);\n}\n\n/* Send a FAIL message to all the nodes we are able to contact.\n * The FAIL message is sent when we detect that a node is failing\n * (CLUSTER_NODE_PFAIL) and we also receive a gossip confirmation of this:\n * we switch the node state to CLUSTER_NODE_FAIL and ask all the other\n * nodes to do the same ASAP. */\nvoid clusterSendFail(char *nodename) {\n    unsigned char buf[sizeof(clusterMsg)];\n    clusterMsg *hdr = (clusterMsg*) buf;\n\n    clusterBuildMessageHdr(hdr,CLUSTERMSG_TYPE_FAIL);\n    memcpy(hdr->data.fail.about.nodename,nodename,CLUSTER_NAMELEN);\n    clusterBroadcastMessage(buf,ntohl(hdr->totlen));\n}\n\n/* Send an UPDATE message to the specified link carrying the specified 'node'\n * slots configuration. The node name, slots bitmap, and configEpoch info\n * are included. */\nvoid clusterSendUpdate(clusterLink *link, clusterNode *node) {\n    unsigned char buf[sizeof(clusterMsg)];\n    clusterMsg *hdr = (clusterMsg*) buf;\n\n    if (link == NULL) return;\n    clusterBuildMessageHdr(hdr,CLUSTERMSG_TYPE_UPDATE);\n    memcpy(hdr->data.update.nodecfg.nodename,node->name,CLUSTER_NAMELEN);\n    hdr->data.update.nodecfg.configEpoch = htonu64(node->configEpoch);\n    memcpy(hdr->data.update.nodecfg.slots,node->slots,sizeof(node->slots));\n    clusterSendMessage(link,buf,ntohl(hdr->totlen));\n}\n\n/* -----------------------------------------------------------------------------\n * CLUSTER Pub/Sub support\n *\n * For now we do very little, just propagating PUBLISH messages across the whole\n * cluster. In the future we'll try to get smarter and avoiding propagating those\n * messages to hosts without receives for a given channel.\n * -------------------------------------------------------------------------- */\nvoid clusterPropagatePublish(robj *channel, robj *message) {\n    clusterSendPublish(NULL, channel, message);\n}\n\n/* -----------------------------------------------------------------------------\n * SLAVE node specific functions\n * -------------------------------------------------------------------------- */\n\n/* This function sends a FAILOVE_AUTH_REQUEST message to every node in order to\n * see if there is the quorum for this slave instance to failover its failing\n * master.\n *\n * Note that we send the failover request to everybody, master and slave nodes,\n * but only the masters are supposed to reply to our query. */\nvoid clusterRequestFailoverAuth(void) {\n    unsigned char buf[sizeof(clusterMsg)];\n    clusterMsg *hdr = (clusterMsg*) buf;\n    uint32_t totlen;\n\n    clusterBuildMessageHdr(hdr,CLUSTERMSG_TYPE_FAILOVER_AUTH_REQUEST);\n    /* If this is a manual failover, set the CLUSTERMSG_FLAG0_FORCEACK bit\n     * in the header to communicate the nodes receiving the message that\n     * they should authorized the failover even if the master is working. */\n    if (server.cluster->mf_end) hdr->mflags[0] |= CLUSTERMSG_FLAG0_FORCEACK;\n    totlen = sizeof(clusterMsg)-sizeof(union clusterMsgData);\n    hdr->totlen = htonl(totlen);\n    clusterBroadcastMessage(buf,totlen);\n}\n\n/* Send a FAILOVER_AUTH_ACK message to the specified node. */\nvoid clusterSendFailoverAuth(clusterNode *node) {\n    unsigned char buf[sizeof(clusterMsg)];\n    clusterMsg *hdr = (clusterMsg*) buf;\n    uint32_t totlen;\n\n    if (!node->link) return;\n    clusterBuildMessageHdr(hdr,CLUSTERMSG_TYPE_FAILOVER_AUTH_ACK);\n    totlen = sizeof(clusterMsg)-sizeof(union clusterMsgData);\n    hdr->totlen = htonl(totlen);\n    clusterSendMessage(node->link,buf,totlen);\n}\n\n/* Send a MFSTART message to the specified node. */\nvoid clusterSendMFStart(clusterNode *node) {\n    unsigned char buf[sizeof(clusterMsg)];\n    clusterMsg *hdr = (clusterMsg*) buf;\n    uint32_t totlen;\n\n    if (!node->link) return;\n    clusterBuildMessageHdr(hdr,CLUSTERMSG_TYPE_MFSTART);\n    totlen = sizeof(clusterMsg)-sizeof(union clusterMsgData);\n    hdr->totlen = htonl(totlen);\n    clusterSendMessage(node->link,buf,totlen);\n}\n\n/* Vote for the node asking for our vote if there are the conditions. */\nvoid clusterSendFailoverAuthIfNeeded(clusterNode *node, clusterMsg *request) {\n    clusterNode *master = node->slaveof;\n    uint64_t requestCurrentEpoch = ntohu64(request->currentEpoch);\n    uint64_t requestConfigEpoch = ntohu64(request->configEpoch);\n    unsigned char *claimed_slots = request->myslots;\n    int force_ack = request->mflags[0] & CLUSTERMSG_FLAG0_FORCEACK;\n    int j;\n\n    /* IF we are not a master serving at least 1 slot, we don't have the\n     * right to vote, as the cluster size in Redis Cluster is the number\n     * of masters serving at least one slot, and quorum is the cluster\n     * size + 1 */\n    if (nodeIsSlave(myself) || myself->numslots == 0) return;\n\n    /* Request epoch must be >= our currentEpoch.\n     * Note that it is impossible for it to actually be greater since\n     * our currentEpoch was updated as a side effect of receiving this\n     * request, if the request epoch was greater. */\n    if (requestCurrentEpoch < server.cluster->currentEpoch) {\n        serverLog(LL_WARNING,\n            \"Failover auth denied to %.40s: reqEpoch (%llu) < curEpoch(%llu)\",\n            node->name,\n            (unsigned long long) requestCurrentEpoch,\n            (unsigned long long) server.cluster->currentEpoch);\n        return;\n    }\n\n    /* I already voted for this epoch? Return ASAP. */\n    if (server.cluster->lastVoteEpoch == server.cluster->currentEpoch) {\n        serverLog(LL_WARNING,\n                \"Failover auth denied to %.40s: already voted for epoch %llu\",\n                node->name,\n                (unsigned long long) server.cluster->currentEpoch);\n        return;\n    }\n\n    /* Node must be a slave and its master down.\n     * The master can be non failing if the request is flagged\n     * with CLUSTERMSG_FLAG0_FORCEACK (manual failover). */\n    if (nodeIsMaster(node) || master == NULL ||\n        (!nodeFailed(master) && !force_ack))\n    {\n        if (nodeIsMaster(node)) {\n            serverLog(LL_WARNING,\n                    \"Failover auth denied to %.40s: it is a master node\",\n                    node->name);\n        } else if (master == NULL) {\n            serverLog(LL_WARNING,\n                    \"Failover auth denied to %.40s: I don't know its master\",\n                    node->name);\n        } else if (!nodeFailed(master)) {\n            serverLog(LL_WARNING,\n                    \"Failover auth denied to %.40s: its master is up\",\n                    node->name);\n        }\n        return;\n    }\n\n    /* We did not voted for a slave about this master for two\n     * times the node timeout. This is not strictly needed for correctness\n     * of the algorithm but makes the base case more linear. */\n    if (mstime() - node->slaveof->voted_time < server.cluster_node_timeout * 2)\n    {\n        serverLog(LL_WARNING,\n                \"Failover auth denied to %.40s: \"\n                \"can't vote about this master before %lld milliseconds\",\n                node->name,\n                (long long) ((server.cluster_node_timeout*2)-\n                             (mstime() - node->slaveof->voted_time)));\n        return;\n    }\n\n    /* The slave requesting the vote must have a configEpoch for the claimed\n     * slots that is >= the one of the masters currently serving the same\n     * slots in the current configuration. */\n    for (j = 0; j < CLUSTER_SLOTS; j++) {\n        if (bitmapTestBit(claimed_slots, j) == 0) continue;\n        if (server.cluster->slots[j] == NULL ||\n            server.cluster->slots[j]->configEpoch <= requestConfigEpoch)\n        {\n            continue;\n        }\n        /* If we reached this point we found a slot that in our current slots\n         * is served by a master with a greater configEpoch than the one claimed\n         * by the slave requesting our vote. Refuse to vote for this slave. */\n        serverLog(LL_WARNING,\n                \"Failover auth denied to %.40s: \"\n                \"slot %d epoch (%llu) > reqEpoch (%llu)\",\n                node->name, j,\n                (unsigned long long) server.cluster->slots[j]->configEpoch,\n                (unsigned long long) requestConfigEpoch);\n        return;\n    }\n\n    /* We can vote for this slave. */\n    clusterSendFailoverAuth(node);\n    server.cluster->lastVoteEpoch = server.cluster->currentEpoch;\n    node->slaveof->voted_time = mstime();\n    serverLog(LL_WARNING, \"Failover auth granted to %.40s for epoch %llu\",\n        node->name, (unsigned long long) server.cluster->currentEpoch);\n}\n\n/* This function returns the \"rank\" of this instance, a slave, in the context\n * of its master-slaves ring. The rank of the slave is given by the number of\n * other slaves for the same master that have a better replication offset\n * compared to the local one (better means, greater, so they claim more data).\n *\n * A slave with rank 0 is the one with the greatest (most up to date)\n * replication offset, and so forth. Note that because how the rank is computed\n * multiple slaves may have the same rank, in case they have the same offset.\n *\n * The slave rank is used to add a delay to start an election in order to\n * get voted and replace a failing master. Slaves with better replication\n * offsets are more likely to win. */\nint clusterGetSlaveRank(void) {\n    long long myoffset;\n    int j, rank = 0;\n    clusterNode *master;\n\n    serverAssert(nodeIsSlave(myself));\n    master = myself->slaveof;\n    if (master == NULL) return 0; /* Never called by slaves without master. */\n\n    myoffset = replicationGetSlaveOffset();\n    for (j = 0; j < master->numslaves; j++)\n        if (master->slaves[j] != myself &&\n            master->slaves[j]->repl_offset > myoffset) rank++;\n    return rank;\n}\n\n/* This function is called by clusterHandleSlaveFailover() in order to\n * let the slave log why it is not able to failover. Sometimes there are\n * not the conditions, but since the failover function is called again and\n * again, we can't log the same things continuously.\n *\n * This function works by logging only if a given set of conditions are\n * true:\n *\n * 1) The reason for which the failover can't be initiated changed.\n *    The reasons also include a NONE reason we reset the state to\n *    when the slave finds that its master is fine (no FAIL flag).\n * 2) Also, the log is emitted again if the master is still down and\n *    the reason for not failing over is still the same, but more than\n *    CLUSTER_CANT_FAILOVER_RELOG_PERIOD seconds elapsed.\n * 3) Finally, the function only logs if the slave is down for more than\n *    five seconds + NODE_TIMEOUT. This way nothing is logged when a\n *    failover starts in a reasonable time.\n *\n * The function is called with the reason why the slave can't failover\n * which is one of the integer macros CLUSTER_CANT_FAILOVER_*.\n *\n * The function is guaranteed to be called only if 'myself' is a slave. */\nvoid clusterLogCantFailover(int reason) {\n    char *msg;\n    static time_t lastlog_time = 0;\n    mstime_t nolog_fail_time = server.cluster_node_timeout + 5000;\n\n    /* Don't log if we have the same reason for some time. */\n    if (reason == server.cluster->cant_failover_reason &&\n        time(NULL)-lastlog_time < CLUSTER_CANT_FAILOVER_RELOG_PERIOD)\n        return;\n\n    server.cluster->cant_failover_reason = reason;\n\n    /* We also don't emit any log if the master failed no long ago, the\n     * goal of this function is to log slaves in a stalled condition for\n     * a long time. */\n    if (myself->slaveof &&\n        nodeFailed(myself->slaveof) &&\n        (mstime() - myself->slaveof->fail_time) < nolog_fail_time) return;\n\n    switch(reason) {\n    case CLUSTER_CANT_FAILOVER_DATA_AGE:\n        msg = \"Disconnected from master for longer than allowed. \"\n              \"Please check the 'cluster-slave-validity-factor' configuration \"\n              \"option.\";\n        break;\n    case CLUSTER_CANT_FAILOVER_WAITING_DELAY:\n        msg = \"Waiting the delay before I can start a new failover.\";\n        break;\n    case CLUSTER_CANT_FAILOVER_EXPIRED:\n        msg = \"Failover attempt expired.\";\n        break;\n    case CLUSTER_CANT_FAILOVER_WAITING_VOTES:\n        msg = \"Waiting for votes, but majority still not reached.\";\n        break;\n    default:\n        msg = \"Unknown reason code.\";\n        break;\n    }\n    lastlog_time = time(NULL);\n    serverLog(LL_WARNING,\"Currently unable to failover: %s\", msg);\n}\n\n/* This function implements the final part of automatic and manual failovers,\n * where the slave grabs its master's hash slots, and propagates the new\n * configuration.\n *\n * Note that it's up to the caller to be sure that the node got a new\n * configuration epoch already. */\nvoid clusterFailoverReplaceYourMaster(void) {\n    int j;\n    clusterNode *oldmaster = myself->slaveof;\n\n    if (nodeIsMaster(myself) || oldmaster == NULL) return;\n\n    /* 1) Turn this node into a master. */\n    clusterSetNodeAsMaster(myself);\n    replicationUnsetMaster();\n\n    /* 2) Claim all the slots assigned to our master. */\n    for (j = 0; j < CLUSTER_SLOTS; j++) {\n        if (clusterNodeGetSlotBit(oldmaster,j)) {\n            clusterDelSlot(j);\n            clusterAddSlot(myself,j);\n        }\n    }\n\n    /* 3) Update state and save config. */\n    clusterUpdateState();\n    clusterSaveConfigOrDie(1);\n\n    /* 4) Pong all the other nodes so that they can update the state\n     *    accordingly and detect that we switched to master role. */\n    clusterBroadcastPong(CLUSTER_BROADCAST_ALL);\n\n    /* 5) If there was a manual failover in progress, clear the state. */\n    resetManualFailover();\n}\n\n/* This function is called if we are a slave node and our master serving\n * a non-zero amount of hash slots is in FAIL state.\n *\n * The gaol of this function is:\n * 1) To check if we are able to perform a failover, is our data updated?\n * 2) Try to get elected by masters.\n * 3) Perform the failover informing all the other nodes.\n */\nvoid clusterHandleSlaveFailover(void) {\n    mstime_t data_age;\n    mstime_t auth_age = mstime() - server.cluster->failover_auth_time;\n    int needed_quorum = (server.cluster->size / 2) + 1;\n    int manual_failover = server.cluster->mf_end != 0 &&\n                          server.cluster->mf_can_start;\n    mstime_t auth_timeout, auth_retry_time;\n\n    server.cluster->todo_before_sleep &= ~CLUSTER_TODO_HANDLE_FAILOVER;\n\n    /* Compute the failover timeout (the max time we have to send votes\n     * and wait for replies), and the failover retry time (the time to wait\n     * before trying to get voted again).\n     *\n     * Timeout is MIN(NODE_TIMEOUT*2,2000) milliseconds.\n     * Retry is two times the Timeout.\n     */\n    auth_timeout = server.cluster_node_timeout*2;\n    if (auth_timeout < 2000) auth_timeout = 2000;\n    auth_retry_time = auth_timeout*2;\n\n    /* Pre conditions to run the function, that must be met both in case\n     * of an automatic or manual failover:\n     * 1) We are a slave.\n     * 2) Our master is flagged as FAIL, or this is a manual failover.\n     * 3) It is serving slots. */\n    if (nodeIsMaster(myself) ||\n        myself->slaveof == NULL ||\n        (!nodeFailed(myself->slaveof) && !manual_failover) ||\n        myself->slaveof->numslots == 0)\n    {\n        /* There are no reasons to failover, so we set the reason why we\n         * are returning without failing over to NONE. */\n        server.cluster->cant_failover_reason = CLUSTER_CANT_FAILOVER_NONE;\n        return;\n    }\n\n    /* Set data_age to the number of seconds we are disconnected from\n     * the master. */\n    if (server.repl_state == REPL_STATE_CONNECTED) {\n        data_age = (mstime_t)(server.unixtime - server.master->lastinteraction)\n                   * 1000;\n    } else {\n        data_age = (mstime_t)(server.unixtime - server.repl_down_since) * 1000;\n    }\n\n    /* Remove the node timeout from the data age as it is fine that we are\n     * disconnected from our master at least for the time it was down to be\n     * flagged as FAIL, that's the baseline. */\n    if (data_age > server.cluster_node_timeout)\n        data_age -= server.cluster_node_timeout;\n\n    /* Check if our data is recent enough according to the slave validity\n     * factor configured by the user.\n     *\n     * Check bypassed for manual failovers. */\n    if (server.cluster_slave_validity_factor &&\n        data_age >\n        (((mstime_t)server.repl_ping_slave_period * 1000) +\n         (server.cluster_node_timeout * server.cluster_slave_validity_factor)))\n    {\n        if (!manual_failover) {\n            clusterLogCantFailover(CLUSTER_CANT_FAILOVER_DATA_AGE);\n            return;\n        }\n    }\n\n    /* If the previous failover attempt timedout and the retry time has\n     * elapsed, we can setup a new one. */\n    if (auth_age > auth_retry_time) {\n        server.cluster->failover_auth_time = mstime() +\n            500 + /* Fixed delay of 500 milliseconds, let FAIL msg propagate. */\n            random() % 500; /* Random delay between 0 and 500 milliseconds. */\n        server.cluster->failover_auth_count = 0;\n        server.cluster->failover_auth_sent = 0;\n        server.cluster->failover_auth_rank = clusterGetSlaveRank();\n        /* We add another delay that is proportional to the slave rank.\n         * Specifically 1 second * rank. This way slaves that have a probably\n         * less updated replication offset, are penalized. */\n        server.cluster->failover_auth_time +=\n            server.cluster->failover_auth_rank * 1000;\n        /* However if this is a manual failover, no delay is needed. */\n        if (server.cluster->mf_end) {\n            server.cluster->failover_auth_time = mstime();\n            server.cluster->failover_auth_rank = 0;\n        }\n        serverLog(LL_WARNING,\n            \"Start of election delayed for %lld milliseconds \"\n            \"(rank #%d, offset %lld).\",\n            server.cluster->failover_auth_time - mstime(),\n            server.cluster->failover_auth_rank,\n            replicationGetSlaveOffset());\n        /* Now that we have a scheduled election, broadcast our offset\n         * to all the other slaves so that they'll updated their offsets\n         * if our offset is better. */\n        clusterBroadcastPong(CLUSTER_BROADCAST_LOCAL_SLAVES);\n        return;\n    }\n\n    /* It is possible that we received more updated offsets from other\n     * slaves for the same master since we computed our election delay.\n     * Update the delay if our rank changed.\n     *\n     * Not performed if this is a manual failover. */\n    if (server.cluster->failover_auth_sent == 0 &&\n        server.cluster->mf_end == 0)\n    {\n        int newrank = clusterGetSlaveRank();\n        if (newrank > server.cluster->failover_auth_rank) {\n            long long added_delay =\n                (newrank - server.cluster->failover_auth_rank) * 1000;\n            server.cluster->failover_auth_time += added_delay;\n            server.cluster->failover_auth_rank = newrank;\n            serverLog(LL_WARNING,\n                \"Slave rank updated to #%d, added %lld milliseconds of delay.\",\n                newrank, added_delay);\n        }\n    }\n\n    /* Return ASAP if we can't still start the election. */\n    if (mstime() < server.cluster->failover_auth_time) {\n        clusterLogCantFailover(CLUSTER_CANT_FAILOVER_WAITING_DELAY);\n        return;\n    }\n\n    /* Return ASAP if the election is too old to be valid. */\n    if (auth_age > auth_timeout) {\n        clusterLogCantFailover(CLUSTER_CANT_FAILOVER_EXPIRED);\n        return;\n    }\n\n    /* Ask for votes if needed. */\n    if (server.cluster->failover_auth_sent == 0) {\n        server.cluster->currentEpoch++;\n        server.cluster->failover_auth_epoch = server.cluster->currentEpoch;\n        serverLog(LL_WARNING,\"Starting a failover election for epoch %llu.\",\n            (unsigned long long) server.cluster->currentEpoch);\n        clusterRequestFailoverAuth();\n        server.cluster->failover_auth_sent = 1;\n        clusterDoBeforeSleep(CLUSTER_TODO_SAVE_CONFIG|\n                             CLUSTER_TODO_UPDATE_STATE|\n                             CLUSTER_TODO_FSYNC_CONFIG);\n        return; /* Wait for replies. */\n    }\n\n    /* Check if we reached the quorum. */\n    if (server.cluster->failover_auth_count >= needed_quorum) {\n        /* We have the quorum, we can finally failover the master. */\n\n        serverLog(LL_WARNING,\n            \"Failover election won: I'm the new master.\");\n\n        /* Update my configEpoch to the epoch of the election. */\n        if (myself->configEpoch < server.cluster->failover_auth_epoch) {\n            myself->configEpoch = server.cluster->failover_auth_epoch;\n            serverLog(LL_WARNING,\n                \"configEpoch set to %llu after successful failover\",\n                (unsigned long long) myself->configEpoch);\n        }\n\n        /* Take responsability for the cluster slots. */\n        clusterFailoverReplaceYourMaster();\n    } else {\n        clusterLogCantFailover(CLUSTER_CANT_FAILOVER_WAITING_VOTES);\n    }\n}\n\n/* -----------------------------------------------------------------------------\n * CLUSTER slave migration\n *\n * Slave migration is the process that allows a slave of a master that is\n * already covered by at least another slave, to \"migrate\" to a master that\n * is orpaned, that is, left with no working slaves.\n * ------------------------------------------------------------------------- */\n\n/* This function is responsible to decide if this replica should be migrated\n * to a different (orphaned) master. It is called by the clusterCron() function\n * only if:\n *\n * 1) We are a slave node.\n * 2) It was detected that there is at least one orphaned master in\n *    the cluster.\n * 3) We are a slave of one of the masters with the greatest number of\n *    slaves.\n *\n * This checks are performed by the caller since it requires to iterate\n * the nodes anyway, so we spend time into clusterHandleSlaveMigration()\n * if definitely needed.\n *\n * The fuction is called with a pre-computed max_slaves, that is the max\n * number of working (not in FAIL state) slaves for a single master.\n *\n * Additional conditions for migration are examined inside the function.\n */\nvoid clusterHandleSlaveMigration(int max_slaves) {\n    int j, okslaves = 0;\n    clusterNode *mymaster = myself->slaveof, *target = NULL, *candidate = NULL;\n    dictIterator *di;\n    dictEntry *de;\n\n    /* Step 1: Don't migrate if the cluster state is not ok. */\n    if (server.cluster->state != CLUSTER_OK) return;\n\n    /* Step 2: Don't migrate if my master will not be left with at least\n     *         'migration-barrier' slaves after my migration. */\n    if (mymaster == NULL) return;\n    for (j = 0; j < mymaster->numslaves; j++)\n        if (!nodeFailed(mymaster->slaves[j]) &&\n            !nodeTimedOut(mymaster->slaves[j])) okslaves++;\n    if (okslaves <= server.cluster_migration_barrier) return;\n\n    /* Step 3: Idenitfy a candidate for migration, and check if among the\n     * masters with the greatest number of ok slaves, I'm the one with the\n     * smallest node ID (the \"candidate slave\").\n     *\n     * Note: this means that eventually a replica migration will occurr\n     * since slaves that are reachable again always have their FAIL flag\n     * cleared, so eventually there must be a candidate. At the same time\n     * this does not mean that there are no race conditions possible (two\n     * slaves migrating at the same time), but this is unlikely to\n     * happen, and harmless when happens. */\n    candidate = myself;\n    di = dictGetSafeIterator(server.cluster->nodes);\n    while((de = dictNext(di)) != NULL) {\n        clusterNode *node = dictGetVal(de);\n        int okslaves = 0, is_orphaned = 1;\n\n        /* We want to migrate only if this master is working, orphaned, and\n         * used to have slaves or if failed over a master that had slaves\n         * (MIGRATE_TO flag). This way we only migrate to instances that were\n         * supposed to have replicas. */\n        if (nodeIsSlave(node) || nodeFailed(node)) is_orphaned = 0;\n        if (!(node->flags & CLUSTER_NODE_MIGRATE_TO)) is_orphaned = 0;\n\n        /* Check number of working slaves. */\n        if (nodeIsMaster(node)) okslaves = clusterCountNonFailingSlaves(node);\n        if (okslaves > 0) is_orphaned = 0;\n\n        if (is_orphaned) {\n            if (!target && node->numslots > 0) target = node;\n\n            /* Track the starting time of the orphaned condition for this\n             * master. */\n            if (!node->orphaned_time) node->orphaned_time = mstime();\n        } else {\n            node->orphaned_time = 0;\n        }\n\n        /* Check if I'm the slave candidate for the migration: attached\n         * to a master with the maximum number of slaves and with the smallest\n         * node ID. */\n        if (okslaves == max_slaves) {\n            for (j = 0; j < node->numslaves; j++) {\n                if (memcmp(node->slaves[j]->name,\n                           candidate->name,\n                           CLUSTER_NAMELEN) < 0)\n                {\n                    candidate = node->slaves[j];\n                }\n            }\n        }\n    }\n    dictReleaseIterator(di);\n\n    /* Step 4: perform the migration if there is a target, and if I'm the\n     * candidate, but only if the master is continuously orphaned for a\n     * couple of seconds, so that during failovers, we give some time to\n     * the natural slaves of this instance to advertise their switch from\n     * the old master to the new one. */\n    if (target && candidate == myself &&\n        (mstime()-target->orphaned_time) > CLUSTER_SLAVE_MIGRATION_DELAY)\n    {\n        serverLog(LL_WARNING,\"Migrating to orphaned master %.40s\",\n            target->name);\n        clusterSetMaster(target);\n    }\n}\n\n/* -----------------------------------------------------------------------------\n * CLUSTER manual failover\n *\n * This are the important steps performed by slaves during a manual failover:\n * 1) User send CLUSTER FAILOVER command. The failover state is initialized\n *    setting mf_end to the millisecond unix time at which we'll abort the\n *    attempt.\n * 2) Slave sends a MFSTART message to the master requesting to pause clients\n *    for two times the manual failover timeout CLUSTER_MF_TIMEOUT.\n *    When master is paused for manual failover, it also starts to flag\n *    packets with CLUSTERMSG_FLAG0_PAUSED.\n * 3) Slave waits for master to send its replication offset flagged as PAUSED.\n * 4) If slave received the offset from the master, and its offset matches,\n *    mf_can_start is set to 1, and clusterHandleSlaveFailover() will perform\n *    the failover as usually, with the difference that the vote request\n *    will be modified to force masters to vote for a slave that has a\n *    working master.\n *\n * From the point of view of the master things are simpler: when a\n * PAUSE_CLIENTS packet is received the master sets mf_end as well and\n * the sender in mf_slave. During the time limit for the manual failover\n * the master will just send PINGs more often to this slave, flagged with\n * the PAUSED flag, so that the slave will set mf_master_offset when receiving\n * a packet from the master with this flag set.\n *\n * The gaol of the manual failover is to perform a fast failover without\n * data loss due to the asynchronous master-slave replication.\n * -------------------------------------------------------------------------- */\n\n/* Reset the manual failover state. This works for both masters and slavesa\n * as all the state about manual failover is cleared.\n *\n * The function can be used both to initialize the manual failover state at\n * startup or to abort a manual failover in progress. */\nvoid resetManualFailover(void) {\n    if (server.cluster->mf_end && clientsArePaused()) {\n        server.clients_pause_end_time = 0;\n        clientsArePaused(); /* Just use the side effect of the function. */\n    }\n    server.cluster->mf_end = 0; /* No manual failover in progress. */\n    server.cluster->mf_can_start = 0;\n    server.cluster->mf_slave = NULL;\n    server.cluster->mf_master_offset = 0;\n}\n\n/* If a manual failover timed out, abort it. */\nvoid manualFailoverCheckTimeout(void) {\n    if (server.cluster->mf_end && server.cluster->mf_end < mstime()) {\n        serverLog(LL_WARNING,\"Manual failover timed out.\");\n        resetManualFailover();\n    }\n}\n\n/* This function is called from the cluster cron function in order to go\n * forward with a manual failover state machine. */\nvoid clusterHandleManualFailover(void) {\n    /* Return ASAP if no manual failover is in progress. */\n    if (server.cluster->mf_end == 0) return;\n\n    /* If mf_can_start is non-zero, the failover was already triggered so the\n     * next steps are performed by clusterHandleSlaveFailover(). */\n    if (server.cluster->mf_can_start) return;\n\n    if (server.cluster->mf_master_offset == 0) return; /* Wait for offset... */\n\n    if (server.cluster->mf_master_offset == replicationGetSlaveOffset()) {\n        /* Our replication offset matches the master replication offset\n         * announced after clients were paused. We can start the failover. */\n        server.cluster->mf_can_start = 1;\n        serverLog(LL_WARNING,\n            \"All master replication stream processed, \"\n            \"manual failover can start.\");\n    }\n}\n\n/* -----------------------------------------------------------------------------\n * CLUSTER cron job\n * -------------------------------------------------------------------------- */\n\n/* This is executed 10 times every second */\nvoid clusterCron(void) {\n    dictIterator *di;\n    dictEntry *de;\n    int update_state = 0;\n    int orphaned_masters; /* How many masters there are without ok slaves. */\n    int max_slaves; /* Max number of ok slaves for a single master. */\n    int this_slaves; /* Number of ok slaves for our master (if we are slave). */\n    mstime_t min_pong = 0, now = mstime();\n    clusterNode *min_pong_node = NULL;\n    static unsigned long long iteration = 0;\n    mstime_t handshake_timeout;\n\n    iteration++; /* Number of times this function was called so far. */\n\n    /* The handshake timeout is the time after which a handshake node that was\n     * not turned into a normal node is removed from the nodes. Usually it is\n     * just the NODE_TIMEOUT value, but when NODE_TIMEOUT is too small we use\n     * the value of 1 second. */\n    handshake_timeout = server.cluster_node_timeout;\n    if (handshake_timeout < 1000) handshake_timeout = 1000;\n\n    /* Check if we have disconnected nodes and re-establish the connection. */\n    di = dictGetSafeIterator(server.cluster->nodes);\n    while((de = dictNext(di)) != NULL) {\n        clusterNode *node = dictGetVal(de);\n\n        if (node->flags & (CLUSTER_NODE_MYSELF|CLUSTER_NODE_NOADDR)) continue;\n\n        /* A Node in HANDSHAKE state has a limited lifespan equal to the\n         * configured node timeout. */\n        if (nodeInHandshake(node) && now - node->ctime > handshake_timeout) {\n            clusterDelNode(node);\n            continue;\n        }\n\n        if (node->link == NULL) {\n            int fd;\n            mstime_t old_ping_sent;\n            clusterLink *link;\n\n            fd = anetTcpNonBlockBindConnect(server.neterr, node->ip,\n                node->port+CLUSTER_PORT_INCR, NET_FIRST_BIND_ADDR);\n            if (fd == -1) {\n                /* We got a synchronous error from connect before\n                 * clusterSendPing() had a chance to be called.\n                 * If node->ping_sent is zero, failure detection can't work,\n                 * so we claim we actually sent a ping now (that will\n                 * be really sent as soon as the link is obtained). */\n                if (node->ping_sent == 0) node->ping_sent = mstime();\n                serverLog(LL_DEBUG, \"Unable to connect to \"\n                    \"Cluster Node [%s]:%d -> %s\", node->ip,\n                    node->port+CLUSTER_PORT_INCR,\n                    server.neterr);\n                continue;\n            }\n            link = createClusterLink(node);\n            link->fd = fd;\n            node->link = link;\n            aeCreateFileEvent(server.el,link->fd,AE_READABLE,\n                    clusterReadHandler,link);\n            /* Queue a PING in the new connection ASAP: this is crucial\n             * to avoid false positives in failure detection.\n             *\n             * If the node is flagged as MEET, we send a MEET message instead\n             * of a PING one, to force the receiver to add us in its node\n             * table. */\n            old_ping_sent = node->ping_sent;\n            clusterSendPing(link, node->flags & CLUSTER_NODE_MEET ?\n                    CLUSTERMSG_TYPE_MEET : CLUSTERMSG_TYPE_PING);\n            if (old_ping_sent) {\n                /* If there was an active ping before the link was\n                 * disconnected, we want to restore the ping time, otherwise\n                 * replaced by the clusterSendPing() call. */\n                node->ping_sent = old_ping_sent;\n            }\n            /* We can clear the flag after the first packet is sent.\n             * If we'll never receive a PONG, we'll never send new packets\n             * to this node. Instead after the PONG is received and we\n             * are no longer in meet/handshake status, we want to send\n             * normal PING packets. */\n            node->flags &= ~CLUSTER_NODE_MEET;\n\n            serverLog(LL_DEBUG,\"Connecting with Node %.40s at %s:%d\",\n                    node->name, node->ip, node->port+CLUSTER_PORT_INCR);\n        }\n    }\n    dictReleaseIterator(di);\n\n    /* Ping some random node 1 time every 10 iterations, so that we usually ping\n     * one random node every second. */\n    if (!(iteration % 10)) {\n        int j;\n\n        /* Check a few random nodes and ping the one with the oldest\n         * pong_received time. */\n        for (j = 0; j < 5; j++) {\n            de = dictGetRandomKey(server.cluster->nodes);\n            clusterNode *this = dictGetVal(de);\n\n            /* Don't ping nodes disconnected or with a ping currently active. */\n            if (this->link == NULL || this->ping_sent != 0) continue;\n            if (this->flags & (CLUSTER_NODE_MYSELF|CLUSTER_NODE_HANDSHAKE))\n                continue;\n            if (min_pong_node == NULL || min_pong > this->pong_received) {\n                min_pong_node = this;\n                min_pong = this->pong_received;\n            }\n        }\n        if (min_pong_node) {\n            serverLog(LL_DEBUG,\"Pinging node %.40s\", min_pong_node->name);\n            clusterSendPing(min_pong_node->link, CLUSTERMSG_TYPE_PING);\n        }\n    }\n\n    /* Iterate nodes to check if we need to flag something as failing.\n     * This loop is also responsible to:\n     * 1) Check if there are orphaned masters (masters without non failing\n     *    slaves).\n     * 2) Count the max number of non failing slaves for a single master.\n     * 3) Count the number of slaves for our master, if we are a slave. */\n    orphaned_masters = 0;\n    max_slaves = 0;\n    this_slaves = 0;\n    di = dictGetSafeIterator(server.cluster->nodes);\n    while((de = dictNext(di)) != NULL) {\n        clusterNode *node = dictGetVal(de);\n        now = mstime(); /* Use an updated time at every iteration. */\n        mstime_t delay;\n\n        if (node->flags &\n            (CLUSTER_NODE_MYSELF|CLUSTER_NODE_NOADDR|CLUSTER_NODE_HANDSHAKE))\n                continue;\n\n        /* Orphaned master check, useful only if the current instance\n         * is a slave that may migrate to another master. */\n        if (nodeIsSlave(myself) && nodeIsMaster(node) && !nodeFailed(node)) {\n            int okslaves = clusterCountNonFailingSlaves(node);\n\n            /* A master is orphaned if it is serving a non-zero number of\n             * slots, have no working slaves, but used to have at least one\n             * slave, or failed over a master that used to have slaves. */\n            if (okslaves == 0 && node->numslots > 0 &&\n                node->flags & CLUSTER_NODE_MIGRATE_TO)\n            {\n                orphaned_masters++;\n            }\n            if (okslaves > max_slaves) max_slaves = okslaves;\n            if (nodeIsSlave(myself) && myself->slaveof == node)\n                this_slaves = okslaves;\n        }\n\n        /* If we are waiting for the PONG more than half the cluster\n         * timeout, reconnect the link: maybe there is a connection\n         * issue even if the node is alive. */\n        if (node->link && /* is connected */\n            now - node->link->ctime >\n            server.cluster_node_timeout && /* was not already reconnected */\n            node->ping_sent && /* we already sent a ping */\n            node->pong_received < node->ping_sent && /* still waiting pong */\n            /* and we are waiting for the pong more than timeout/2 */\n            now - node->ping_sent > server.cluster_node_timeout/2)\n        {\n            /* Disconnect the link, it will be reconnected automatically. */\n            freeClusterLink(node->link);\n        }\n\n        /* If we have currently no active ping in this instance, and the\n         * received PONG is older than half the cluster timeout, send\n         * a new ping now, to ensure all the nodes are pinged without\n         * a too big delay. */\n        if (node->link &&\n            node->ping_sent == 0 &&\n            (now - node->pong_received) > server.cluster_node_timeout/2)\n        {\n            clusterSendPing(node->link, CLUSTERMSG_TYPE_PING);\n            continue;\n        }\n\n        /* If we are a master and one of the slaves requested a manual\n         * failover, ping it continuously. */\n        if (server.cluster->mf_end &&\n            nodeIsMaster(myself) &&\n            server.cluster->mf_slave == node &&\n            node->link)\n        {\n            clusterSendPing(node->link, CLUSTERMSG_TYPE_PING);\n            continue;\n        }\n\n        /* Check only if we have an active ping for this instance. */\n        if (node->ping_sent == 0) continue;\n\n        /* Compute the delay of the PONG. Note that if we already received\n         * the PONG, then node->ping_sent is zero, so can't reach this\n         * code at all. */\n        delay = now - node->ping_sent;\n\n        if (delay > server.cluster_node_timeout) {\n            /* Timeout reached. Set the node as possibly failing if it is\n             * not already in this state. */\n            if (!(node->flags & (CLUSTER_NODE_PFAIL|CLUSTER_NODE_FAIL))) {\n                serverLog(LL_DEBUG,\"*** NODE %.40s possibly failing\",\n                    node->name);\n                node->flags |= CLUSTER_NODE_PFAIL;\n                update_state = 1;\n            }\n        }\n    }\n    dictReleaseIterator(di);\n\n    /* If we are a slave node but the replication is still turned off,\n     * enable it if we know the address of our master and it appears to\n     * be up. */\n    if (nodeIsSlave(myself) &&\n        server.masterhost == NULL &&\n        myself->slaveof &&\n        nodeHasAddr(myself->slaveof))\n    {\n        replicationSetMaster(myself->slaveof->ip, myself->slaveof->port);\n    }\n\n    /* Abourt a manual failover if the timeout is reached. */\n    manualFailoverCheckTimeout();\n\n    if (nodeIsSlave(myself)) {\n        clusterHandleManualFailover();\n        clusterHandleSlaveFailover();\n        /* If there are orphaned slaves, and we are a slave among the masters\n         * with the max number of non-failing slaves, consider migrating to\n         * the orphaned masters. Note that it does not make sense to try\n         * a migration if there is no master with at least *two* working\n         * slaves. */\n        if (orphaned_masters && max_slaves >= 2 && this_slaves == max_slaves)\n            clusterHandleSlaveMigration(max_slaves);\n    }\n\n    if (update_state || server.cluster->state == CLUSTER_FAIL)\n        clusterUpdateState();\n}\n\n/* This function is called before the event handler returns to sleep for\n * events. It is useful to perform operations that must be done ASAP in\n * reaction to events fired but that are not safe to perform inside event\n * handlers, or to perform potentially expansive tasks that we need to do\n * a single time before replying to clients. */\nvoid clusterBeforeSleep(void) {\n    /* Handle failover, this is needed when it is likely that there is already\n     * the quorum from masters in order to react fast. */\n    if (server.cluster->todo_before_sleep & CLUSTER_TODO_HANDLE_FAILOVER)\n        clusterHandleSlaveFailover();\n\n    /* Update the cluster state. */\n    if (server.cluster->todo_before_sleep & CLUSTER_TODO_UPDATE_STATE)\n        clusterUpdateState();\n\n    /* Save the config, possibly using fsync. */\n    if (server.cluster->todo_before_sleep & CLUSTER_TODO_SAVE_CONFIG) {\n        int fsync = server.cluster->todo_before_sleep &\n                    CLUSTER_TODO_FSYNC_CONFIG;\n        clusterSaveConfigOrDie(fsync);\n    }\n\n    /* Reset our flags (not strictly needed since every single function\n     * called for flags set should be able to clear its flag). */\n    server.cluster->todo_before_sleep = 0;\n}\n\nvoid clusterDoBeforeSleep(int flags) {\n    server.cluster->todo_before_sleep |= flags;\n}\n\n/* -----------------------------------------------------------------------------\n * Slots management\n * -------------------------------------------------------------------------- */\n\n/* Test bit 'pos' in a generic bitmap. Return 1 if the bit is set,\n * otherwise 0. */\nint bitmapTestBit(unsigned char *bitmap, int pos) {\n    off_t byte = pos/8;\n    int bit = pos&7;\n    return (bitmap[byte] & (1<<bit)) != 0;\n}\n\n/* Set the bit at position 'pos' in a bitmap. */\nvoid bitmapSetBit(unsigned char *bitmap, int pos) {\n    off_t byte = pos/8;\n    int bit = pos&7;\n    bitmap[byte] |= 1<<bit;\n}\n\n/* Clear the bit at position 'pos' in a bitmap. */\nvoid bitmapClearBit(unsigned char *bitmap, int pos) {\n    off_t byte = pos/8;\n    int bit = pos&7;\n    bitmap[byte] &= ~(1<<bit);\n}\n\n/* Return non-zero if there is at least one master with slaves in the cluster.\n * Otherwise zero is returned. Used by clusterNodeSetSlotBit() to set the\n * MIGRATE_TO flag the when a master gets the first slot. */\nint clusterMastersHaveSlaves(void) {\n    dictIterator *di = dictGetSafeIterator(server.cluster->nodes);\n    dictEntry *de;\n    int slaves = 0;\n    while((de = dictNext(di)) != NULL) {\n        clusterNode *node = dictGetVal(de);\n\n        if (nodeIsSlave(node)) continue;\n        slaves += node->numslaves;\n    }\n    dictReleaseIterator(di);\n    return slaves != 0;\n}\n\n/* Set the slot bit and return the old value. */\nint clusterNodeSetSlotBit(clusterNode *n, int slot) {\n    int old = bitmapTestBit(n->slots,slot);\n    bitmapSetBit(n->slots,slot);\n    if (!old) {\n        n->numslots++;\n        /* When a master gets its first slot, even if it has no slaves,\n         * it gets flagged with MIGRATE_TO, that is, the master is a valid\n         * target for replicas migration, if and only if at least one of\n         * the other masters has slaves right now.\n         *\n         * Normally masters are valid targerts of replica migration if:\n         * 1. The used to have slaves (but no longer have).\n         * 2. They are slaves failing over a master that used to have slaves.\n         *\n         * However new masters with slots assigned are considered valid\n         * migration tagets if the rest of the cluster is not a slave-less.\n         *\n         * See https://github.com/antirez/redis/issues/3043 for more info. */\n        if (n->numslots == 1 && clusterMastersHaveSlaves())\n            n->flags |= CLUSTER_NODE_MIGRATE_TO;\n    }\n    return old;\n}\n\n/* Clear the slot bit and return the old value. */\nint clusterNodeClearSlotBit(clusterNode *n, int slot) {\n    int old = bitmapTestBit(n->slots,slot);\n    bitmapClearBit(n->slots,slot);\n    if (old) n->numslots--;\n    return old;\n}\n\n/* Return the slot bit from the cluster node structure. */\nint clusterNodeGetSlotBit(clusterNode *n, int slot) {\n    return bitmapTestBit(n->slots,slot);\n}\n\n/* Add the specified slot to the list of slots that node 'n' will\n * serve. Return C_OK if the operation ended with success.\n * If the slot is already assigned to another instance this is considered\n * an error and C_ERR is returned. */\nint clusterAddSlot(clusterNode *n, int slot) {\n    if (server.cluster->slots[slot]) return C_ERR;\n    clusterNodeSetSlotBit(n,slot);\n    server.cluster->slots[slot] = n;\n    return C_OK;\n}\n\n/* Delete the specified slot marking it as unassigned.\n * Returns C_OK if the slot was assigned, otherwise if the slot was\n * already unassigned C_ERR is returned. */\nint clusterDelSlot(int slot) {\n    clusterNode *n = server.cluster->slots[slot];\n\n    if (!n) return C_ERR;\n    serverAssert(clusterNodeClearSlotBit(n,slot) == 1);\n    server.cluster->slots[slot] = NULL;\n    return C_OK;\n}\n\n/* Delete all the slots associated with the specified node.\n * The number of deleted slots is returned. */\nint clusterDelNodeSlots(clusterNode *node) {\n    int deleted = 0, j;\n\n    for (j = 0; j < CLUSTER_SLOTS; j++) {\n        if (clusterNodeGetSlotBit(node,j)) clusterDelSlot(j);\n        deleted++;\n    }\n    return deleted;\n}\n\n/* Clear the migrating / importing state for all the slots.\n * This is useful at initialization and when turning a master into slave. */\nvoid clusterCloseAllSlots(void) {\n    memset(server.cluster->migrating_slots_to,0,\n        sizeof(server.cluster->migrating_slots_to));\n    memset(server.cluster->importing_slots_from,0,\n        sizeof(server.cluster->importing_slots_from));\n}\n\n/* -----------------------------------------------------------------------------\n * Cluster state evaluation function\n * -------------------------------------------------------------------------- */\n\n/* The following are defines that are only used in the evaluation function\n * and are based on heuristics. Actaully the main point about the rejoin and\n * writable delay is that they should be a few orders of magnitude larger\n * than the network latency. */\n#define CLUSTER_MAX_REJOIN_DELAY 5000\n#define CLUSTER_MIN_REJOIN_DELAY 500\n#define CLUSTER_WRITABLE_DELAY 2000\n\nvoid clusterUpdateState(void) {\n    int j, new_state;\n    int reachable_masters = 0;\n    static mstime_t among_minority_time;\n    static mstime_t first_call_time = 0;\n\n    server.cluster->todo_before_sleep &= ~CLUSTER_TODO_UPDATE_STATE;\n\n    /* If this is a master node, wait some time before turning the state\n     * into OK, since it is not a good idea to rejoin the cluster as a writable\n     * master, after a reboot, without giving the cluster a chance to\n     * reconfigure this node. Note that the delay is calculated starting from\n     * the first call to this function and not since the server start, in order\n     * to don't count the DB loading time. */\n    if (first_call_time == 0) first_call_time = mstime();\n    if (nodeIsMaster(myself) &&\n        server.cluster->state == CLUSTER_FAIL &&\n        mstime() - first_call_time < CLUSTER_WRITABLE_DELAY) return;\n\n    /* Start assuming the state is OK. We'll turn it into FAIL if there\n     * are the right conditions. */\n    new_state = CLUSTER_OK;\n\n    /* Check if all the slots are covered. */\n    if (server.cluster_require_full_coverage) {\n        for (j = 0; j < CLUSTER_SLOTS; j++) {\n            if (server.cluster->slots[j] == NULL ||\n                server.cluster->slots[j]->flags & (CLUSTER_NODE_FAIL))\n            {\n                new_state = CLUSTER_FAIL;\n                break;\n            }\n        }\n    }\n\n    /* Compute the cluster size, that is the number of master nodes\n     * serving at least a single slot.\n     *\n     * At the same time count the number of reachable masters having\n     * at least one slot. */\n    {\n        dictIterator *di;\n        dictEntry *de;\n\n        server.cluster->size = 0;\n        di = dictGetSafeIterator(server.cluster->nodes);\n        while((de = dictNext(di)) != NULL) {\n            clusterNode *node = dictGetVal(de);\n\n            if (nodeIsMaster(node) && node->numslots) {\n                server.cluster->size++;\n                if ((node->flags & (CLUSTER_NODE_FAIL|CLUSTER_NODE_PFAIL)) == 0)\n                    reachable_masters++;\n            }\n        }\n        dictReleaseIterator(di);\n    }\n\n    /* If we are in a minority partition, change the cluster state\n     * to FAIL. */\n    {\n        int needed_quorum = (server.cluster->size / 2) + 1;\n\n        if (reachable_masters < needed_quorum) {\n            new_state = CLUSTER_FAIL;\n            among_minority_time = mstime();\n        }\n    }\n\n    /* Log a state change */\n    if (new_state != server.cluster->state) {\n        mstime_t rejoin_delay = server.cluster_node_timeout;\n\n        /* If the instance is a master and was partitioned away with the\n         * minority, don't let it accept queries for some time after the\n         * partition heals, to make sure there is enough time to receive\n         * a configuration update. */\n        if (rejoin_delay > CLUSTER_MAX_REJOIN_DELAY)\n            rejoin_delay = CLUSTER_MAX_REJOIN_DELAY;\n        if (rejoin_delay < CLUSTER_MIN_REJOIN_DELAY)\n            rejoin_delay = CLUSTER_MIN_REJOIN_DELAY;\n\n        if (new_state == CLUSTER_OK &&\n            nodeIsMaster(myself) &&\n            mstime() - among_minority_time < rejoin_delay)\n        {\n            return;\n        }\n\n        /* Change the state and log the event. */\n        serverLog(LL_WARNING,\"Cluster state changed: %s\",\n            new_state == CLUSTER_OK ? \"ok\" : \"fail\");\n        server.cluster->state = new_state;\n    }\n}\n\n/* This function is called after the node startup in order to verify that data\n * loaded from disk is in agreement with the cluster configuration:\n *\n * 1) If we find keys about hash slots we have no responsibility for, the\n *    following happens:\n *    A) If no other node is in charge according to the current cluster\n *       configuration, we add these slots to our node.\n *    B) If according to our config other nodes are already in charge for\n *       this lots, we set the slots as IMPORTING from our point of view\n *       in order to justify we have those slots, and in order to make\n *       redis-trib aware of the issue, so that it can try to fix it.\n * 2) If we find data in a DB different than DB0 we return C_ERR to\n *    signal the caller it should quit the server with an error message\n *    or take other actions.\n *\n * The function always returns C_OK even if it will try to correct\n * the error described in \"1\". However if data is found in DB different\n * from DB0, C_ERR is returned.\n *\n * The function also uses the logging facility in order to warn the user\n * about desynchronizations between the data we have in memory and the\n * cluster configuration. */\nint verifyClusterConfigWithData(void) {\n    int j;\n    int update_config = 0;\n\n    /* If this node is a slave, don't perform the check at all as we\n     * completely depend on the replication stream. */\n    if (nodeIsSlave(myself)) return C_OK;\n\n    /* Make sure we only have keys in DB0. */\n    for (j = 1; j < server.dbnum; j++) {\n        if (dictSize(server.db[j].dict)) return C_ERR;\n    }\n\n    /* Check that all the slots we see populated memory have a corresponding\n     * entry in the cluster table. Otherwise fix the table. */\n    for (j = 0; j < CLUSTER_SLOTS; j++) {\n        if (!countKeysInSlot(j)) continue; /* No keys in this slot. */\n        /* Check if we are assigned to this slot or if we are importing it.\n         * In both cases check the next slot as the configuration makes\n         * sense. */\n        if (server.cluster->slots[j] == myself ||\n            server.cluster->importing_slots_from[j] != NULL) continue;\n\n        /* If we are here data and cluster config don't agree, and we have\n         * slot 'j' populated even if we are not importing it, nor we are\n         * assigned to this slot. Fix this condition. */\n\n        update_config++;\n        /* Case A: slot is unassigned. Take responsibility for it. */\n        if (server.cluster->slots[j] == NULL) {\n            serverLog(LL_WARNING, \"I have keys for unassigned slot %d. \"\n                                    \"Taking responsibility for it.\",j);\n            clusterAddSlot(myself,j);\n        } else {\n            serverLog(LL_WARNING, \"I have keys for slot %d, but the slot is \"\n                                    \"assigned to another node. \"\n                                    \"Setting it to importing state.\",j);\n            server.cluster->importing_slots_from[j] = server.cluster->slots[j];\n        }\n    }\n    if (update_config) clusterSaveConfigOrDie(1);\n    return C_OK;\n}\n\n/* -----------------------------------------------------------------------------\n * SLAVE nodes handling\n * -------------------------------------------------------------------------- */\n\n/* Set the specified node 'n' as master for this node.\n * If this node is currently a master, it is turned into a slave. */\nvoid clusterSetMaster(clusterNode *n) {\n    serverAssert(n != myself);\n    serverAssert(myself->numslots == 0);\n\n    if (nodeIsMaster(myself)) {\n        myself->flags &= ~(CLUSTER_NODE_MASTER|CLUSTER_NODE_MIGRATE_TO);\n        myself->flags |= CLUSTER_NODE_SLAVE;\n        clusterCloseAllSlots();\n    } else {\n        if (myself->slaveof)\n            clusterNodeRemoveSlave(myself->slaveof,myself);\n    }\n    myself->slaveof = n;\n    clusterNodeAddSlave(n,myself);\n    replicationSetMaster(n->ip, n->port);\n    resetManualFailover();\n}\n\n/* -----------------------------------------------------------------------------\n * Nodes to string representation functions.\n * -------------------------------------------------------------------------- */\n\nstruct redisNodeFlags {\n    uint16_t flag;\n    char *name;\n};\n\nstatic struct redisNodeFlags redisNodeFlagsTable[] = {\n    {CLUSTER_NODE_MYSELF,       \"myself,\"},\n    {CLUSTER_NODE_MASTER,       \"master,\"},\n    {CLUSTER_NODE_SLAVE,        \"slave,\"},\n    {CLUSTER_NODE_PFAIL,        \"fail?,\"},\n    {CLUSTER_NODE_FAIL,         \"fail,\"},\n    {CLUSTER_NODE_HANDSHAKE,    \"handshake,\"},\n    {CLUSTER_NODE_NOADDR,       \"noaddr,\"}\n};\n\n/* Concatenate the comma separated list of node flags to the given SDS\n * string 'ci'. */\nsds representClusterNodeFlags(sds ci, uint16_t flags) {\n    if (flags == 0) {\n        ci = sdscat(ci,\"noflags,\");\n    } else {\n        int i, size = sizeof(redisNodeFlagsTable)/sizeof(struct redisNodeFlags);\n        for (i = 0; i < size; i++) {\n            struct redisNodeFlags *nodeflag = redisNodeFlagsTable + i;\n            if (flags & nodeflag->flag) ci = sdscat(ci, nodeflag->name);\n        }\n    }\n    sdsIncrLen(ci,-1); /* Remove trailing comma. */\n    return ci;\n}\n\n/* Generate a csv-alike representation of the specified cluster node.\n * See clusterGenNodesDescription() top comment for more information.\n *\n * The function returns the string representation as an SDS string. */\nsds clusterGenNodeDescription(clusterNode *node) {\n    int j, start;\n    sds ci;\n\n    /* Node coordinates */\n    ci = sdscatprintf(sdsempty(),\"%.40s %s:%d \",\n        node->name,\n        node->ip,\n        node->port);\n\n    /* Flags */\n    ci = representClusterNodeFlags(ci, node->flags);\n\n    /* Slave of... or just \"-\" */\n    if (node->slaveof)\n        ci = sdscatprintf(ci,\" %.40s \",node->slaveof->name);\n    else\n        ci = sdscatlen(ci,\" - \",3);\n\n    /* Latency from the POV of this node, config epoch, link status */\n    ci = sdscatprintf(ci,\"%lld %lld %llu %s\",\n        (long long) node->ping_sent,\n        (long long) node->pong_received,\n        (unsigned long long) node->configEpoch,\n        (node->link || node->flags & CLUSTER_NODE_MYSELF) ?\n                    \"connected\" : \"disconnected\");\n\n    /* Slots served by this instance */\n    start = -1;\n    for (j = 0; j < CLUSTER_SLOTS; j++) {\n        int bit;\n\n        if ((bit = clusterNodeGetSlotBit(node,j)) != 0) {\n            if (start == -1) start = j;\n        }\n        if (start != -1 && (!bit || j == CLUSTER_SLOTS-1)) {\n            if (bit && j == CLUSTER_SLOTS-1) j++;\n\n            if (start == j-1) {\n                ci = sdscatprintf(ci,\" %d\",start);\n            } else {\n                ci = sdscatprintf(ci,\" %d-%d\",start,j-1);\n            }\n            start = -1;\n        }\n    }\n\n    /* Just for MYSELF node we also dump info about slots that\n     * we are migrating to other instances or importing from other\n     * instances. */\n    if (node->flags & CLUSTER_NODE_MYSELF) {\n        for (j = 0; j < CLUSTER_SLOTS; j++) {\n            if (server.cluster->migrating_slots_to[j]) {\n                ci = sdscatprintf(ci,\" [%d->-%.40s]\",j,\n                    server.cluster->migrating_slots_to[j]->name);\n            } else if (server.cluster->importing_slots_from[j]) {\n                ci = sdscatprintf(ci,\" [%d-<-%.40s]\",j,\n                    server.cluster->importing_slots_from[j]->name);\n            }\n        }\n    }\n    return ci;\n}\n\n/* Generate a csv-alike representation of the nodes we are aware of,\n * including the \"myself\" node, and return an SDS string containing the\n * representation (it is up to the caller to free it).\n *\n * All the nodes matching at least one of the node flags specified in\n * \"filter\" are excluded from the output, so using zero as a filter will\n * include all the known nodes in the representation, including nodes in\n * the HANDSHAKE state.\n *\n * The representation obtained using this function is used for the output\n * of the CLUSTER NODES function, and as format for the cluster\n * configuration file (nodes.conf) for a given node. */\nsds clusterGenNodesDescription(int filter) {\n    sds ci = sdsempty(), ni;\n    dictIterator *di;\n    dictEntry *de;\n\n    di = dictGetSafeIterator(server.cluster->nodes);\n    while((de = dictNext(di)) != NULL) {\n        clusterNode *node = dictGetVal(de);\n\n        if (node->flags & filter) continue;\n        ni = clusterGenNodeDescription(node);\n        ci = sdscatsds(ci,ni);\n        sdsfree(ni);\n        ci = sdscatlen(ci,\"\\n\",1);\n    }\n    dictReleaseIterator(di);\n    return ci;\n}\n\n/* -----------------------------------------------------------------------------\n * CLUSTER command\n * -------------------------------------------------------------------------- */\n\nint getSlotOrReply(client *c, robj *o) {\n    long long slot;\n\n    if (getLongLongFromObject(o,&slot) != C_OK ||\n        slot < 0 || slot >= CLUSTER_SLOTS)\n    {\n        addReplyError(c,\"Invalid or out of range slot\");\n        return -1;\n    }\n    return (int) slot;\n}\n\nvoid clusterReplyMultiBulkSlots(client *c) {\n    /* Format: 1) 1) start slot\n     *            2) end slot\n     *            3) 1) master IP\n     *               2) master port\n     *               3) node ID\n     *            4) 1) replica IP\n     *               2) replica port\n     *               3) node ID\n     *           ... continued until done\n     */\n\n    int num_masters = 0;\n    void *slot_replylen = addDeferredMultiBulkLength(c);\n\n    dictEntry *de;\n    dictIterator *di = dictGetSafeIterator(server.cluster->nodes);\n    while((de = dictNext(di)) != NULL) {\n        clusterNode *node = dictGetVal(de);\n        int j = 0, start = -1;\n\n        /* Skip slaves (that are iterated when producing the output of their\n         * master) and  masters not serving any slot. */\n        if (!nodeIsMaster(node) || node->numslots == 0) continue;\n\n        for (j = 0; j < CLUSTER_SLOTS; j++) {\n            int bit, i;\n\n            if ((bit = clusterNodeGetSlotBit(node,j)) != 0) {\n                if (start == -1) start = j;\n            }\n            if (start != -1 && (!bit || j == CLUSTER_SLOTS-1)) {\n                int nested_elements = 3; /* slots (2) + master addr (1). */\n                void *nested_replylen = addDeferredMultiBulkLength(c);\n\n                if (bit && j == CLUSTER_SLOTS-1) j++;\n\n                /* If slot exists in output map, add to it's list.\n                 * else, create a new output map for this slot */\n                if (start == j-1) {\n                    addReplyLongLong(c, start); /* only one slot; low==high */\n                    addReplyLongLong(c, start);\n                } else {\n                    addReplyLongLong(c, start); /* low */\n                    addReplyLongLong(c, j-1);   /* high */\n                }\n                start = -1;\n\n                /* First node reply position is always the master */\n                addReplyMultiBulkLen(c, 3);\n                addReplyBulkCString(c, node->ip);\n                addReplyLongLong(c, node->port);\n                addReplyBulkCBuffer(c, node->name, CLUSTER_NAMELEN);\n\n                /* Remaining nodes in reply are replicas for slot range */\n                for (i = 0; i < node->numslaves; i++) {\n                    /* This loop is copy/pasted from clusterGenNodeDescription()\n                     * with modifications for per-slot node aggregation */\n                    if (nodeFailed(node->slaves[i])) continue;\n                    addReplyMultiBulkLen(c, 3);\n                    addReplyBulkCString(c, node->slaves[i]->ip);\n                    addReplyLongLong(c, node->slaves[i]->port);\n                    addReplyBulkCBuffer(c, node->slaves[i]->name, CLUSTER_NAMELEN);\n                    nested_elements++;\n                }\n                setDeferredMultiBulkLength(c, nested_replylen, nested_elements);\n                num_masters++;\n            }\n        }\n    }\n    dictReleaseIterator(di);\n    setDeferredMultiBulkLength(c, slot_replylen, num_masters);\n}\n\nvoid clusterCommand(client *c) {\n    if (server.cluster_enabled == 0) {\n        addReplyError(c,\"This instance has cluster support disabled\");\n        return;\n    }\n\n    if (!strcasecmp(c->argv[1]->ptr,\"meet\") && c->argc == 4) {\n        long long port;\n\n        if (getLongLongFromObject(c->argv[3], &port) != C_OK) {\n            addReplyErrorFormat(c,\"Invalid TCP port specified: %s\",\n                                (char*)c->argv[3]->ptr);\n            return;\n        }\n\n        if (clusterStartHandshake(c->argv[2]->ptr,port) == 0 &&\n            errno == EINVAL)\n        {\n            addReplyErrorFormat(c,\"Invalid node address specified: %s:%s\",\n                            (char*)c->argv[2]->ptr, (char*)c->argv[3]->ptr);\n        } else {\n            addReply(c,shared.ok);\n        }\n    } else if (!strcasecmp(c->argv[1]->ptr,\"nodes\") && c->argc == 2) {\n        /* CLUSTER NODES */\n        robj *o;\n        sds ci = clusterGenNodesDescription(0);\n\n        o = createObject(OBJ_STRING,ci);\n        addReplyBulk(c,o);\n        decrRefCount(o);\n    } else if (!strcasecmp(c->argv[1]->ptr,\"myid\") && c->argc == 2) {\n        /* CLUSTER MYID */\n        addReplyBulkCBuffer(c,myself->name, CLUSTER_NAMELEN);\n    } else if (!strcasecmp(c->argv[1]->ptr,\"slots\") && c->argc == 2) {\n        /* CLUSTER SLOTS */\n        clusterReplyMultiBulkSlots(c);\n    } else if (!strcasecmp(c->argv[1]->ptr,\"flushslots\") && c->argc == 2) {\n        /* CLUSTER FLUSHSLOTS */\n        if (dictSize(server.db[0].dict) != 0) {\n            addReplyError(c,\"DB must be empty to perform CLUSTER FLUSHSLOTS.\");\n            return;\n        }\n        clusterDelNodeSlots(myself);\n        clusterDoBeforeSleep(CLUSTER_TODO_UPDATE_STATE|CLUSTER_TODO_SAVE_CONFIG);\n        addReply(c,shared.ok);\n    } else if ((!strcasecmp(c->argv[1]->ptr,\"addslots\") ||\n               !strcasecmp(c->argv[1]->ptr,\"delslots\")) && c->argc >= 3)\n    {\n        /* CLUSTER ADDSLOTS <slot> [slot] ... */\n        /* CLUSTER DELSLOTS <slot> [slot] ... */\n        int j, slot;\n        unsigned char *slots = zmalloc(CLUSTER_SLOTS);\n        int del = !strcasecmp(c->argv[1]->ptr,\"delslots\");\n\n        memset(slots,0,CLUSTER_SLOTS);\n        /* Check that all the arguments are parseable and that all the\n         * slots are not already busy. */\n        for (j = 2; j < c->argc; j++) {\n            if ((slot = getSlotOrReply(c,c->argv[j])) == -1) {\n                zfree(slots);\n                return;\n            }\n            if (del && server.cluster->slots[slot] == NULL) {\n                addReplyErrorFormat(c,\"Slot %d is already unassigned\", slot);\n                zfree(slots);\n                return;\n            } else if (!del && server.cluster->slots[slot]) {\n                addReplyErrorFormat(c,\"Slot %d is already busy\", slot);\n                zfree(slots);\n                return;\n            }\n            if (slots[slot]++ == 1) {\n                addReplyErrorFormat(c,\"Slot %d specified multiple times\",\n                    (int)slot);\n                zfree(slots);\n                return;\n            }\n        }\n        for (j = 0; j < CLUSTER_SLOTS; j++) {\n            if (slots[j]) {\n                int retval;\n\n                /* If this slot was set as importing we can clear this\n                 * state as now we are the real owner of the slot. */\n                if (server.cluster->importing_slots_from[j])\n                    server.cluster->importing_slots_from[j] = NULL;\n\n                retval = del ? clusterDelSlot(j) :\n                               clusterAddSlot(myself,j);\n                serverAssertWithInfo(c,NULL,retval == C_OK);\n            }\n        }\n        zfree(slots);\n        clusterDoBeforeSleep(CLUSTER_TODO_UPDATE_STATE|CLUSTER_TODO_SAVE_CONFIG);\n        addReply(c,shared.ok);\n    } else if (!strcasecmp(c->argv[1]->ptr,\"setslot\") && c->argc >= 4) {\n        /* SETSLOT 10 MIGRATING <node ID> */\n        /* SETSLOT 10 IMPORTING <node ID> */\n        /* SETSLOT 10 STABLE */\n        /* SETSLOT 10 NODE <node ID> */\n        int slot;\n        clusterNode *n;\n\n        if (nodeIsSlave(myself)) {\n            addReplyError(c,\"Please use SETSLOT only with masters.\");\n            return;\n        }\n\n        if ((slot = getSlotOrReply(c,c->argv[2])) == -1) return;\n\n        if (!strcasecmp(c->argv[3]->ptr,\"migrating\") && c->argc == 5) {\n            if (server.cluster->slots[slot] != myself) {\n                addReplyErrorFormat(c,\"I'm not the owner of hash slot %u\",slot);\n                return;\n            }\n            if ((n = clusterLookupNode(c->argv[4]->ptr)) == NULL) {\n                addReplyErrorFormat(c,\"I don't know about node %s\",\n                    (char*)c->argv[4]->ptr);\n                return;\n            }\n            server.cluster->migrating_slots_to[slot] = n;\n        } else if (!strcasecmp(c->argv[3]->ptr,\"importing\") && c->argc == 5) {\n            if (server.cluster->slots[slot] == myself) {\n                addReplyErrorFormat(c,\n                    \"I'm already the owner of hash slot %u\",slot);\n                return;\n            }\n            if ((n = clusterLookupNode(c->argv[4]->ptr)) == NULL) {\n                addReplyErrorFormat(c,\"I don't know about node %s\",\n                    (char*)c->argv[3]->ptr);\n                return;\n            }\n            server.cluster->importing_slots_from[slot] = n;\n        } else if (!strcasecmp(c->argv[3]->ptr,\"stable\") && c->argc == 4) {\n            /* CLUSTER SETSLOT <SLOT> STABLE */\n            server.cluster->importing_slots_from[slot] = NULL;\n            server.cluster->migrating_slots_to[slot] = NULL;\n        } else if (!strcasecmp(c->argv[3]->ptr,\"node\") && c->argc == 5) {\n            /* CLUSTER SETSLOT <SLOT> NODE <NODE ID> */\n            clusterNode *n = clusterLookupNode(c->argv[4]->ptr);\n\n            if (!n) {\n                addReplyErrorFormat(c,\"Unknown node %s\",\n                    (char*)c->argv[4]->ptr);\n                return;\n            }\n            /* If this hash slot was served by 'myself' before to switch\n             * make sure there are no longer local keys for this hash slot. */\n            if (server.cluster->slots[slot] == myself && n != myself) {\n                if (countKeysInSlot(slot) != 0) {\n                    addReplyErrorFormat(c,\n                        \"Can't assign hashslot %d to a different node \"\n                        \"while I still hold keys for this hash slot.\", slot);\n                    return;\n                }\n            }\n            /* If this slot is in migrating status but we have no keys\n             * for it assigning the slot to another node will clear\n             * the migratig status. */\n            if (countKeysInSlot(slot) == 0 &&\n                server.cluster->migrating_slots_to[slot])\n                server.cluster->migrating_slots_to[slot] = NULL;\n\n            /* If this node was importing this slot, assigning the slot to\n             * itself also clears the importing status. */\n            if (n == myself &&\n                server.cluster->importing_slots_from[slot])\n            {\n                /* This slot was manually migrated, set this node configEpoch\n                 * to a new epoch so that the new version can be propagated\n                 * by the cluster.\n                 *\n                 * Note that if this ever results in a collision with another\n                 * node getting the same configEpoch, for example because a\n                 * failover happens at the same time we close the slot, the\n                 * configEpoch collision resolution will fix it assigning\n                 * a different epoch to each node. */\n                if (clusterBumpConfigEpochWithoutConsensus() == C_OK) {\n                    serverLog(LL_WARNING,\n                        \"configEpoch updated after importing slot %d\", slot);\n                }\n                server.cluster->importing_slots_from[slot] = NULL;\n            }\n            clusterDelSlot(slot);\n            clusterAddSlot(n,slot);\n        } else {\n            addReplyError(c,\n                \"Invalid CLUSTER SETSLOT action or number of arguments\");\n            return;\n        }\n        clusterDoBeforeSleep(CLUSTER_TODO_SAVE_CONFIG|CLUSTER_TODO_UPDATE_STATE);\n        addReply(c,shared.ok);\n    } else if (!strcasecmp(c->argv[1]->ptr,\"bumpepoch\") && c->argc == 2) {\n        /* CLUSTER BUMPEPOCH */\n        int retval = clusterBumpConfigEpochWithoutConsensus();\n        sds reply = sdscatprintf(sdsempty(),\"+%s %llu\\r\\n\",\n                (retval == C_OK) ? \"BUMPED\" : \"STILL\",\n                (unsigned long long) myself->configEpoch);\n        addReplySds(c,reply);\n    } else if (!strcasecmp(c->argv[1]->ptr,\"info\") && c->argc == 2) {\n        /* CLUSTER INFO */\n        char *statestr[] = {\"ok\",\"fail\",\"needhelp\"};\n        int slots_assigned = 0, slots_ok = 0, slots_pfail = 0, slots_fail = 0;\n        uint64_t myepoch;\n        int j;\n\n        for (j = 0; j < CLUSTER_SLOTS; j++) {\n            clusterNode *n = server.cluster->slots[j];\n\n            if (n == NULL) continue;\n            slots_assigned++;\n            if (nodeFailed(n)) {\n                slots_fail++;\n            } else if (nodeTimedOut(n)) {\n                slots_pfail++;\n            } else {\n                slots_ok++;\n            }\n        }\n\n        myepoch = (nodeIsSlave(myself) && myself->slaveof) ?\n                  myself->slaveof->configEpoch : myself->configEpoch;\n\n        sds info = sdscatprintf(sdsempty(),\n            \"cluster_state:%s\\r\\n\"\n            \"cluster_slots_assigned:%d\\r\\n\"\n            \"cluster_slots_ok:%d\\r\\n\"\n            \"cluster_slots_pfail:%d\\r\\n\"\n            \"cluster_slots_fail:%d\\r\\n\"\n            \"cluster_known_nodes:%lu\\r\\n\"\n            \"cluster_size:%d\\r\\n\"\n            \"cluster_current_epoch:%llu\\r\\n\"\n            \"cluster_my_epoch:%llu\\r\\n\"\n            \"cluster_stats_messages_sent:%lld\\r\\n\"\n            \"cluster_stats_messages_received:%lld\\r\\n\"\n            , statestr[server.cluster->state],\n            slots_assigned,\n            slots_ok,\n            slots_pfail,\n            slots_fail,\n            dictSize(server.cluster->nodes),\n            server.cluster->size,\n            (unsigned long long) server.cluster->currentEpoch,\n            (unsigned long long) myepoch,\n            server.cluster->stats_bus_messages_sent,\n            server.cluster->stats_bus_messages_received\n        );\n        addReplySds(c,sdscatprintf(sdsempty(),\"$%lu\\r\\n\",\n            (unsigned long)sdslen(info)));\n        addReplySds(c,info);\n        addReply(c,shared.crlf);\n    } else if (!strcasecmp(c->argv[1]->ptr,\"saveconfig\") && c->argc == 2) {\n        int retval = clusterSaveConfig(1);\n\n        if (retval == 0)\n            addReply(c,shared.ok);\n        else\n            addReplyErrorFormat(c,\"error saving the cluster node config: %s\",\n                strerror(errno));\n    } else if (!strcasecmp(c->argv[1]->ptr,\"keyslot\") && c->argc == 3) {\n        /* CLUSTER KEYSLOT <key> */\n        sds key = c->argv[2]->ptr;\n\n        addReplyLongLong(c,keyHashSlot(key,sdslen(key)));\n    } else if (!strcasecmp(c->argv[1]->ptr,\"countkeysinslot\") && c->argc == 3) {\n        /* CLUSTER COUNTKEYSINSLOT <slot> */\n        long long slot;\n\n        if (getLongLongFromObjectOrReply(c,c->argv[2],&slot,NULL) != C_OK)\n            return;\n        if (slot < 0 || slot >= CLUSTER_SLOTS) {\n            addReplyError(c,\"Invalid slot\");\n            return;\n        }\n        addReplyLongLong(c,countKeysInSlot(slot));\n    } else if (!strcasecmp(c->argv[1]->ptr,\"getkeysinslot\") && c->argc == 4) {\n        /* CLUSTER GETKEYSINSLOT <slot> <count> */\n        long long maxkeys, slot;\n        unsigned int numkeys, j;\n        robj **keys;\n\n        if (getLongLongFromObjectOrReply(c,c->argv[2],&slot,NULL) != C_OK)\n            return;\n        if (getLongLongFromObjectOrReply(c,c->argv[3],&maxkeys,NULL)\n            != C_OK)\n            return;\n        if (slot < 0 || slot >= CLUSTER_SLOTS || maxkeys < 0) {\n            addReplyError(c,\"Invalid slot or number of keys\");\n            return;\n        }\n\n        keys = zmalloc(sizeof(robj*)*maxkeys);\n        numkeys = getKeysInSlot(slot, keys, maxkeys);\n        addReplyMultiBulkLen(c,numkeys);\n        for (j = 0; j < numkeys; j++) addReplyBulk(c,keys[j]);\n        zfree(keys);\n    } else if (!strcasecmp(c->argv[1]->ptr,\"forget\") && c->argc == 3) {\n        /* CLUSTER FORGET <NODE ID> */\n        clusterNode *n = clusterLookupNode(c->argv[2]->ptr);\n\n        if (!n) {\n            addReplyErrorFormat(c,\"Unknown node %s\", (char*)c->argv[2]->ptr);\n            return;\n        } else if (n == myself) {\n            addReplyError(c,\"I tried hard but I can't forget myself...\");\n            return;\n        } else if (nodeIsSlave(myself) && myself->slaveof == n) {\n            addReplyError(c,\"Can't forget my master!\");\n            return;\n        }\n        clusterBlacklistAddNode(n);\n        clusterDelNode(n);\n        clusterDoBeforeSleep(CLUSTER_TODO_UPDATE_STATE|\n                             CLUSTER_TODO_SAVE_CONFIG);\n        addReply(c,shared.ok);\n    } else if (!strcasecmp(c->argv[1]->ptr,\"replicate\") && c->argc == 3) {\n        /* CLUSTER REPLICATE <NODE ID> */\n        clusterNode *n = clusterLookupNode(c->argv[2]->ptr);\n\n        /* Lookup the specified node in our table. */\n        if (!n) {\n            addReplyErrorFormat(c,\"Unknown node %s\", (char*)c->argv[2]->ptr);\n            return;\n        }\n\n        /* I can't replicate myself. */\n        if (n == myself) {\n            addReplyError(c,\"Can't replicate myself\");\n            return;\n        }\n\n        /* Can't replicate a slave. */\n        if (nodeIsSlave(n)) {\n            addReplyError(c,\"I can only replicate a master, not a slave.\");\n            return;\n        }\n\n        /* If the instance is currently a master, it should have no assigned\n         * slots nor keys to accept to replicate some other node.\n         * Slaves can switch to another master without issues. */\n        if (nodeIsMaster(myself) &&\n            (myself->numslots != 0 || dictSize(server.db[0].dict) != 0)) {\n            addReplyError(c,\n                \"To set a master the node must be empty and \"\n                \"without assigned slots.\");\n            return;\n        }\n\n        /* Set the master. */\n        clusterSetMaster(n);\n        clusterDoBeforeSleep(CLUSTER_TODO_UPDATE_STATE|CLUSTER_TODO_SAVE_CONFIG);\n        addReply(c,shared.ok);\n    } else if (!strcasecmp(c->argv[1]->ptr,\"slaves\") && c->argc == 3) {\n        /* CLUSTER SLAVES <NODE ID> */\n        clusterNode *n = clusterLookupNode(c->argv[2]->ptr);\n        int j;\n\n        /* Lookup the specified node in our table. */\n        if (!n) {\n            addReplyErrorFormat(c,\"Unknown node %s\", (char*)c->argv[2]->ptr);\n            return;\n        }\n\n        if (nodeIsSlave(n)) {\n            addReplyError(c,\"The specified node is not a master\");\n            return;\n        }\n\n        addReplyMultiBulkLen(c,n->numslaves);\n        for (j = 0; j < n->numslaves; j++) {\n            sds ni = clusterGenNodeDescription(n->slaves[j]);\n            addReplyBulkCString(c,ni);\n            sdsfree(ni);\n        }\n    } else if (!strcasecmp(c->argv[1]->ptr,\"count-failure-reports\") &&\n               c->argc == 3)\n    {\n        /* CLUSTER COUNT-FAILURE-REPORTS <NODE ID> */\n        clusterNode *n = clusterLookupNode(c->argv[2]->ptr);\n\n        if (!n) {\n            addReplyErrorFormat(c,\"Unknown node %s\", (char*)c->argv[2]->ptr);\n            return;\n        } else {\n            addReplyLongLong(c,clusterNodeFailureReportsCount(n));\n        }\n    } else if (!strcasecmp(c->argv[1]->ptr,\"failover\") &&\n               (c->argc == 2 || c->argc == 3))\n    {\n        /* CLUSTER FAILOVER [FORCE|TAKEOVER] */\n        int force = 0, takeover = 0;\n\n        if (c->argc == 3) {\n            if (!strcasecmp(c->argv[2]->ptr,\"force\")) {\n                force = 1;\n            } else if (!strcasecmp(c->argv[2]->ptr,\"takeover\")) {\n                takeover = 1;\n                force = 1; /* Takeover also implies force. */\n            } else {\n                addReply(c,shared.syntaxerr);\n                return;\n            }\n        }\n\n        /* Check preconditions. */\n        if (nodeIsMaster(myself)) {\n            addReplyError(c,\"You should send CLUSTER FAILOVER to a slave\");\n            return;\n        } else if (myself->slaveof == NULL) {\n            addReplyError(c,\"I'm a slave but my master is unknown to me\");\n            return;\n        } else if (!force &&\n                   (nodeFailed(myself->slaveof) ||\n                    myself->slaveof->link == NULL))\n        {\n            addReplyError(c,\"Master is down or failed, \"\n                            \"please use CLUSTER FAILOVER FORCE\");\n            return;\n        }\n        resetManualFailover();\n        server.cluster->mf_end = mstime() + CLUSTER_MF_TIMEOUT;\n\n        if (takeover) {\n            /* A takeover does not perform any initial check. It just\n             * generates a new configuration epoch for this node without\n             * consensus, claims the master's slots, and broadcast the new\n             * configuration. */\n            serverLog(LL_WARNING,\"Taking over the master (user request).\");\n            clusterBumpConfigEpochWithoutConsensus();\n            clusterFailoverReplaceYourMaster();\n        } else if (force) {\n            /* If this is a forced failover, we don't need to talk with our\n             * master to agree about the offset. We just failover taking over\n             * it without coordination. */\n            serverLog(LL_WARNING,\"Forced failover user request accepted.\");\n            server.cluster->mf_can_start = 1;\n        } else {\n            serverLog(LL_WARNING,\"Manual failover user request accepted.\");\n            clusterSendMFStart(myself->slaveof);\n        }\n        addReply(c,shared.ok);\n    } else if (!strcasecmp(c->argv[1]->ptr,\"set-config-epoch\") && c->argc == 3)\n    {\n        /* CLUSTER SET-CONFIG-EPOCH <epoch>\n         *\n         * The user is allowed to set the config epoch only when a node is\n         * totally fresh: no config epoch, no other known node, and so forth.\n         * This happens at cluster creation time to start with a cluster where\n         * every node has a different node ID, without to rely on the conflicts\n         * resolution system which is too slow when a big cluster is created. */\n        long long epoch;\n\n        if (getLongLongFromObjectOrReply(c,c->argv[2],&epoch,NULL) != C_OK)\n            return;\n\n        if (epoch < 0) {\n            addReplyErrorFormat(c,\"Invalid config epoch specified: %lld\",epoch);\n        } else if (dictSize(server.cluster->nodes) > 1) {\n            addReplyError(c,\"The user can assign a config epoch only when the \"\n                            \"node does not know any other node.\");\n        } else if (myself->configEpoch != 0) {\n            addReplyError(c,\"Node config epoch is already non-zero\");\n        } else {\n            myself->configEpoch = epoch;\n            serverLog(LL_WARNING,\n                \"configEpoch set to %llu via CLUSTER SET-CONFIG-EPOCH\",\n                (unsigned long long) myself->configEpoch);\n\n            if (server.cluster->currentEpoch < (uint64_t)epoch)\n                server.cluster->currentEpoch = epoch;\n            /* No need to fsync the config here since in the unlucky event\n             * of a failure to persist the config, the conflict resolution code\n             * will assign an unique config to this node. */\n            clusterDoBeforeSleep(CLUSTER_TODO_UPDATE_STATE|\n                                 CLUSTER_TODO_SAVE_CONFIG);\n            addReply(c,shared.ok);\n        }\n    } else if (!strcasecmp(c->argv[1]->ptr,\"reset\") &&\n               (c->argc == 2 || c->argc == 3))\n    {\n        /* CLUSTER RESET [SOFT|HARD] */\n        int hard = 0;\n\n        /* Parse soft/hard argument. Default is soft. */\n        if (c->argc == 3) {\n            if (!strcasecmp(c->argv[2]->ptr,\"hard\")) {\n                hard = 1;\n            } else if (!strcasecmp(c->argv[2]->ptr,\"soft\")) {\n                hard = 0;\n            } else {\n                addReply(c,shared.syntaxerr);\n                return;\n            }\n        }\n\n        /* Slaves can be reset while containing data, but not master nodes\n         * that must be empty. */\n        if (nodeIsMaster(myself) && dictSize(c->db->dict) != 0) {\n            addReplyError(c,\"CLUSTER RESET can't be called with \"\n                            \"master nodes containing keys\");\n            return;\n        }\n        clusterReset(hard);\n        addReply(c,shared.ok);\n    } else {\n        addReplyError(c,\"Wrong CLUSTER subcommand or number of arguments\");\n    }\n}\n\n/* -----------------------------------------------------------------------------\n * DUMP, RESTORE and MIGRATE commands\n * -------------------------------------------------------------------------- */\n\n/* Generates a DUMP-format representation of the object 'o', adding it to the\n * io stream pointed by 'rio'. This function can't fail. */\nvoid createDumpPayload(rio *payload, robj *o) {\n    unsigned char buf[2];\n    uint64_t crc;\n\n    /* Serialize the object in a RDB-like format. It consist of an object type\n     * byte followed by the serialized object. This is understood by RESTORE. */\n    rioInitWithBuffer(payload,sdsempty());\n    serverAssert(rdbSaveObjectType(payload,o));\n    serverAssert(rdbSaveObject(payload,o));\n\n    /* Write the footer, this is how it looks like:\n     * ----------------+---------------------+---------------+\n     * ... RDB payload | 2 bytes RDB version | 8 bytes CRC64 |\n     * ----------------+---------------------+---------------+\n     * RDB version and CRC are both in little endian.\n     */\n\n    /* RDB version */\n    buf[0] = RDB_VERSION & 0xff;\n    buf[1] = (RDB_VERSION >> 8) & 0xff;\n    payload->io.buffer.ptr = sdscatlen(payload->io.buffer.ptr,buf,2);\n\n    /* CRC64 */\n    crc = crc64(0,(unsigned char*)payload->io.buffer.ptr,\n                sdslen(payload->io.buffer.ptr));\n    memrev64ifbe(&crc);\n    payload->io.buffer.ptr = sdscatlen(payload->io.buffer.ptr,&crc,8);\n}\n\n/* Verify that the RDB version of the dump payload matches the one of this Redis\n * instance and that the checksum is ok.\n * If the DUMP payload looks valid C_OK is returned, otherwise C_ERR\n * is returned. */\nint verifyDumpPayload(unsigned char *p, size_t len) {\n    unsigned char *footer;\n    uint16_t rdbver;\n    uint64_t crc;\n\n    /* At least 2 bytes of RDB version and 8 of CRC64 should be present. */\n    if (len < 10) return C_ERR;\n    footer = p+(len-10);\n\n    /* Verify RDB version */\n    rdbver = (footer[1] << 8) | footer[0];\n    if (rdbver > RDB_VERSION) return C_ERR;\n\n    /* Verify CRC64 */\n    crc = crc64(0,p,len-8);\n    memrev64ifbe(&crc);\n    return (memcmp(&crc,footer+2,8) == 0) ? C_OK : C_ERR;\n}\n\n/* DUMP keyname\n * DUMP is actually not used by Redis Cluster but it is the obvious\n * complement of RESTORE and can be useful for different applications. */\nvoid dumpCommand(client *c) {\n    robj *o, *dumpobj;\n    rio payload;\n\n    /* Check if the key is here. */\n    if ((o = lookupKeyRead(c->db,c->argv[1])) == NULL) {\n        addReply(c,shared.nullbulk);\n        return;\n    }\n\n    /* Create the DUMP encoded representation. */\n    createDumpPayload(&payload,o);\n\n    /* Transfer to the client */\n    dumpobj = createObject(OBJ_STRING,payload.io.buffer.ptr);\n    addReplyBulk(c,dumpobj);\n    decrRefCount(dumpobj);\n    return;\n}\n\n/* RESTORE key ttl serialized-value [REPLACE] */\nvoid restoreCommand(client *c) {\n    long long ttl;\n    rio payload;\n    int j, type, replace = 0;\n    robj *obj;\n\n    /* Parse additional options */\n    for (j = 4; j < c->argc; j++) {\n        if (!strcasecmp(c->argv[j]->ptr,\"replace\")) {\n            replace = 1;\n        } else {\n            addReply(c,shared.syntaxerr);\n            return;\n        }\n    }\n\n    /* Make sure this key does not already exist here... */\n    if (!replace && lookupKeyWrite(c->db,c->argv[1]) != NULL) {\n        addReply(c,shared.busykeyerr);\n        return;\n    }\n\n    /* Check if the TTL value makes sense */\n    if (getLongLongFromObjectOrReply(c,c->argv[2],&ttl,NULL) != C_OK) {\n        return;\n    } else if (ttl < 0) {\n        addReplyError(c,\"Invalid TTL value, must be >= 0\");\n        return;\n    }\n\n    /* Verify RDB version and data checksum. */\n    if (verifyDumpPayload(c->argv[3]->ptr,sdslen(c->argv[3]->ptr)) == C_ERR)\n    {\n        addReplyError(c,\"DUMP payload version or checksum are wrong\");\n        return;\n    }\n\n    rioInitWithBuffer(&payload,c->argv[3]->ptr);\n    if (((type = rdbLoadObjectType(&payload)) == -1) ||\n        ((obj = rdbLoadObject(type,&payload)) == NULL))\n    {\n        addReplyError(c,\"Bad data format\");\n        return;\n    }\n\n    /* Remove the old key if needed. */\n    if (replace) dbDelete(c->db,c->argv[1]);\n\n    /* Create the key and set the TTL if any */\n    dbAdd(c->db,c->argv[1],obj);\n    if (ttl) setExpire(c->db,c->argv[1],mstime()+ttl);\n    signalModifiedKey(c->db,c->argv[1]);\n    addReply(c,shared.ok);\n    server.dirty++;\n}\n\n/* MIGRATE socket cache implementation.\n *\n * We take a map between host:ip and a TCP socket that we used to connect\n * to this instance in recent time.\n * This sockets are closed when the max number we cache is reached, and also\n * in serverCron() when they are around for more than a few seconds. */\n#define MIGRATE_SOCKET_CACHE_ITEMS 64 /* max num of items in the cache. */\n#define MIGRATE_SOCKET_CACHE_TTL 10 /* close cached sockets after 10 sec. */\n\ntypedef struct migrateCachedSocket {\n    int fd;\n    long last_dbid;\n    time_t last_use_time;\n} migrateCachedSocket;\n\n/* Return a migrateCachedSocket containing a TCP socket connected with the\n * target instance, possibly returning a cached one.\n *\n * This function is responsible of sending errors to the client if a\n * connection can't be established. In this case -1 is returned.\n * Otherwise on success the socket is returned, and the caller should not\n * attempt to free it after usage.\n *\n * If the caller detects an error while using the socket, migrateCloseSocket()\n * should be called so that the connection will be created from scratch\n * the next time. */\nmigrateCachedSocket* migrateGetSocket(client *c, robj *host, robj *port, long timeout) {\n    int fd;\n    sds name = sdsempty();\n    migrateCachedSocket *cs;\n\n    /* Check if we have an already cached socket for this ip:port pair. */\n    name = sdscatlen(name,host->ptr,sdslen(host->ptr));\n    name = sdscatlen(name,\":\",1);\n    name = sdscatlen(name,port->ptr,sdslen(port->ptr));\n    cs = dictFetchValue(server.migrate_cached_sockets,name);\n    if (cs) {\n        sdsfree(name);\n        cs->last_use_time = server.unixtime;\n        return cs;\n    }\n\n    /* No cached socket, create one. */\n    if (dictSize(server.migrate_cached_sockets) == MIGRATE_SOCKET_CACHE_ITEMS) {\n        /* Too many items, drop one at random. */\n        dictEntry *de = dictGetRandomKey(server.migrate_cached_sockets);\n        cs = dictGetVal(de);\n        close(cs->fd);\n        zfree(cs);\n        dictDelete(server.migrate_cached_sockets,dictGetKey(de));\n    }\n\n    /* Create the socket */\n    fd = anetTcpNonBlockConnect(server.neterr,c->argv[1]->ptr,\n                                atoi(c->argv[2]->ptr));\n    if (fd == -1) {\n        sdsfree(name);\n        addReplyErrorFormat(c,\"Can't connect to target node: %s\",\n            server.neterr);\n        return NULL;\n    }\n    anetEnableTcpNoDelay(server.neterr,fd);\n\n    /* Check if it connects within the specified timeout. */\n    if ((aeWait(fd,AE_WRITABLE,timeout) & AE_WRITABLE) == 0) {\n        sdsfree(name);\n        addReplySds(c,\n            sdsnew(\"-IOERR error or timeout connecting to the client\\r\\n\"));\n        close(fd);\n        return NULL;\n    }\n\n    /* Add to the cache and return it to the caller. */\n    cs = zmalloc(sizeof(*cs));\n    cs->fd = fd;\n    cs->last_dbid = -1;\n    cs->last_use_time = server.unixtime;\n    dictAdd(server.migrate_cached_sockets,name,cs);\n    return cs;\n}\n\n/* Free a migrate cached connection. */\nvoid migrateCloseSocket(robj *host, robj *port) {\n    sds name = sdsempty();\n    migrateCachedSocket *cs;\n\n    name = sdscatlen(name,host->ptr,sdslen(host->ptr));\n    name = sdscatlen(name,\":\",1);\n    name = sdscatlen(name,port->ptr,sdslen(port->ptr));\n    cs = dictFetchValue(server.migrate_cached_sockets,name);\n    if (!cs) {\n        sdsfree(name);\n        return;\n    }\n\n    close(cs->fd);\n    zfree(cs);\n    dictDelete(server.migrate_cached_sockets,name);\n    sdsfree(name);\n}\n\nvoid migrateCloseTimedoutSockets(void) {\n    dictIterator *di = dictGetSafeIterator(server.migrate_cached_sockets);\n    dictEntry *de;\n\n    while((de = dictNext(di)) != NULL) {\n        migrateCachedSocket *cs = dictGetVal(de);\n\n        if ((server.unixtime - cs->last_use_time) > MIGRATE_SOCKET_CACHE_TTL) {\n            close(cs->fd);\n            zfree(cs);\n            dictDelete(server.migrate_cached_sockets,dictGetKey(de));\n        }\n    }\n    dictReleaseIterator(di);\n}\n\n/* MIGRATE host port key dbid timeout [COPY | REPLACE]\n *\n * On in the multiple keys form:\n *\n * MIGRATE host port \"\" dbid timeout [COPY | REPLACE] KEYS key1 key2 ... keyN */\nvoid migrateCommand(client *c) {\n    migrateCachedSocket *cs;\n    int copy, replace, j;\n    long timeout;\n    long dbid;\n    long long ttl, expireat;\n    robj **ov = NULL; /* Objects to migrate. */\n    robj **kv = NULL; /* Key names. */\n    robj **newargv = NULL; /* Used to rewrite the command as DEL ... keys ... */\n    rio cmd, payload;\n    int may_retry = 1;\n    int write_error = 0;\n\n    /* To support the KEYS option we need the following additional state. */\n    int first_key = 3; /* Argument index of the first key. */\n    int num_keys = 1;  /* By default only migrate the 'key' argument. */\n\n    /* Initialization */\n    copy = 0;\n    replace = 0;\n    ttl = 0;\n\n    /* Parse additional options */\n    for (j = 6; j < c->argc; j++) {\n        if (!strcasecmp(c->argv[j]->ptr,\"copy\")) {\n            copy = 1;\n        } else if (!strcasecmp(c->argv[j]->ptr,\"replace\")) {\n            replace = 1;\n        } else if (!strcasecmp(c->argv[j]->ptr,\"keys\")) {\n            if (sdslen(c->argv[3]->ptr) != 0) {\n                addReplyError(c,\n                    \"When using MIGRATE KEYS option, the key argument\"\n                    \" must be set to the empty string\");\n                return;\n            }\n            first_key = j+1;\n            num_keys = c->argc - j - 1;\n            break; /* All the remaining args are keys. */\n        } else {\n            addReply(c,shared.syntaxerr);\n            return;\n        }\n    }\n\n    /* Sanity check */\n    if (getLongFromObjectOrReply(c,c->argv[5],&timeout,NULL) != C_OK ||\n        getLongFromObjectOrReply(c,c->argv[4],&dbid,NULL) != C_OK)\n    {\n        return;\n    }\n    if (timeout <= 0) timeout = 1000;\n\n    /* Check if the keys are here. If at least one key is to migrate, do it\n     * otherwise if all the keys are missing reply with \"NOKEY\" to signal\n     * the caller there was nothing to migrate. We don't return an error in\n     * this case, since often this is due to a normal condition like the key\n     * expiring in the meantime. */\n    ov = zrealloc(ov,sizeof(robj*)*num_keys);\n    kv = zrealloc(kv,sizeof(robj*)*num_keys);\n    int oi = 0;\n\n    for (j = 0; j < num_keys; j++) {\n        if ((ov[oi] = lookupKeyRead(c->db,c->argv[first_key+j])) != NULL) {\n            kv[oi] = c->argv[first_key+j];\n            oi++;\n        }\n    }\n    num_keys = oi;\n    if (num_keys == 0) {\n        zfree(ov); zfree(kv);\n        addReplySds(c,sdsnew(\"+NOKEY\\r\\n\"));\n        return;\n    }\n\ntry_again:\n    write_error = 0;\n\n    /* Connect */\n    cs = migrateGetSocket(c,c->argv[1],c->argv[2],timeout);\n    if (cs == NULL) {\n        zfree(ov); zfree(kv);\n        return; /* error sent to the client by migrateGetSocket() */\n    }\n\n    rioInitWithBuffer(&cmd,sdsempty());\n\n    /* Send the SELECT command if the current DB is not already selected. */\n    int select = cs->last_dbid != dbid; /* Should we emit SELECT? */\n    if (select) {\n        serverAssertWithInfo(c,NULL,rioWriteBulkCount(&cmd,'*',2));\n        serverAssertWithInfo(c,NULL,rioWriteBulkString(&cmd,\"SELECT\",6));\n        serverAssertWithInfo(c,NULL,rioWriteBulkLongLong(&cmd,dbid));\n    }\n\n    /* Create RESTORE payload and generate the protocol to call the command. */\n    for (j = 0; j < num_keys; j++) {\n        expireat = getExpire(c->db,kv[j]);\n        if (expireat != -1) {\n            ttl = expireat-mstime();\n            if (ttl < 1) ttl = 1;\n        }\n        serverAssertWithInfo(c,NULL,rioWriteBulkCount(&cmd,'*',replace ? 5 : 4));\n        if (server.cluster_enabled)\n            serverAssertWithInfo(c,NULL,\n                rioWriteBulkString(&cmd,\"RESTORE-ASKING\",14));\n        else\n            serverAssertWithInfo(c,NULL,rioWriteBulkString(&cmd,\"RESTORE\",7));\n        serverAssertWithInfo(c,NULL,sdsEncodedObject(kv[j]));\n        serverAssertWithInfo(c,NULL,rioWriteBulkString(&cmd,kv[j]->ptr,\n                sdslen(kv[j]->ptr)));\n        serverAssertWithInfo(c,NULL,rioWriteBulkLongLong(&cmd,ttl));\n\n        /* Emit the payload argument, that is the serialized object using\n         * the DUMP format. */\n        createDumpPayload(&payload,ov[j]);\n        serverAssertWithInfo(c,NULL,\n            rioWriteBulkString(&cmd,payload.io.buffer.ptr,\n                               sdslen(payload.io.buffer.ptr)));\n        sdsfree(payload.io.buffer.ptr);\n\n        /* Add the REPLACE option to the RESTORE command if it was specified\n         * as a MIGRATE option. */\n        if (replace)\n            serverAssertWithInfo(c,NULL,rioWriteBulkString(&cmd,\"REPLACE\",7));\n    }\n\n    /* Transfer the query to the other node in 64K chunks. */\n    errno = 0;\n    {\n        sds buf = cmd.io.buffer.ptr;\n        size_t pos = 0, towrite;\n        int nwritten = 0;\n\n        while ((towrite = sdslen(buf)-pos) > 0) {\n            towrite = (towrite > (64*1024) ? (64*1024) : towrite);\n            nwritten = syncWrite(cs->fd,buf+pos,towrite,timeout);\n            if (nwritten != (signed)towrite) {\n                write_error = 1;\n                goto socket_err;\n            }\n            pos += nwritten;\n        }\n    }\n\n    char buf1[1024]; /* Select reply. */\n    char buf2[1024]; /* Restore reply. */\n\n    /* Read the SELECT reply if needed. */\n    if (select && syncReadLine(cs->fd, buf1, sizeof(buf1), timeout) <= 0)\n        goto socket_err;\n\n    /* Read the RESTORE replies. */\n    int error_from_target = 0;\n    int socket_error = 0;\n    int del_idx = 1; /* Index of the key argument for the replicated DEL op. */\n\n    if (!copy) newargv = zmalloc(sizeof(robj*)*(num_keys+1));\n\n    for (j = 0; j < num_keys; j++) {\n        if (syncReadLine(cs->fd, buf2, sizeof(buf2), timeout) <= 0) {\n            socket_error = 1;\n            break;\n        }\n        if ((select && buf1[0] == '-') || buf2[0] == '-') {\n            /* On error assume that last_dbid is no longer valid. */\n            if (!error_from_target) {\n                cs->last_dbid = -1;\n                addReplyErrorFormat(c,\"Target instance replied with error: %s\",\n                    (select && buf1[0] == '-') ? buf1+1 : buf2+1);\n                error_from_target = 1;\n            }\n        } else {\n            if (!copy) {\n                /* No COPY option: remove the local key, signal the change. */\n                dbDelete(c->db,kv[j]);\n                signalModifiedKey(c->db,kv[j]);\n                server.dirty++;\n\n                /* Populate the argument vector to replace the old one. */\n                newargv[del_idx++] = kv[j];\n                incrRefCount(kv[j]);\n            }\n        }\n    }\n\n    /* On socket error, if we want to retry, do it now before rewriting the\n     * command vector. We only retry if we are sure nothing was processed\n     * and we failed to read the first reply (j == 0 test). */\n    if (!error_from_target && socket_error && j == 0 && may_retry &&\n        errno != ETIMEDOUT)\n    {\n        goto socket_err; /* A retry is guaranteed because of tested conditions.*/\n    }\n\n    if (!copy) {\n        /* Translate MIGRATE as DEL for replication/AOF. */\n        if (del_idx > 1) {\n            newargv[0] = createStringObject(\"DEL\",3);\n            /* Note that the following call takes ownership of newargv. */\n            replaceClientCommandVector(c,del_idx,newargv);\n        } else {\n            /* No key transfer acknowledged, no need to rewrite as DEL. */\n            zfree(newargv);\n        }\n        newargv = NULL; /* Make it safe to call zfree() on it in the future. */\n    }\n\n    /* If we are here and a socket error happened, we don't want to retry.\n     * Just signal the problem to the client, but only do it if we don't\n     * already queued a different error reported by the destination server. */\n    if (!error_from_target && socket_error) {\n        may_retry = 0;\n        goto socket_err;\n    }\n\n    if (!error_from_target) {\n        /* Success! Update the last_dbid in migrateCachedSocket, so that we can\n         * avoid SELECT the next time if the target DB is the same. Reply +OK. */\n        cs->last_dbid = dbid;\n        addReply(c,shared.ok);\n    } else {\n        /* On error we already sent it in the for loop above, and set\n         * the curretly selected socket to -1 to force SELECT the next time. */\n    }\n\n    sdsfree(cmd.io.buffer.ptr);\n    zfree(ov); zfree(kv); zfree(newargv);\n    if (socket_error) migrateCloseSocket(c->argv[1],c->argv[2]);\n    return;\n\n/* On socket errors we try to close the cached socket and try again.\n * It is very common for the cached socket to get closed, if just reopening\n * it works it's a shame to notify the error to the caller. */\nsocket_err:\n    /* Cleanup we want to perform in both the retry and no retry case.\n     * Note: Closing the migrate socket will also force SELECT next time. */\n    sdsfree(cmd.io.buffer.ptr);\n    migrateCloseSocket(c->argv[1],c->argv[2]);\n    zfree(newargv);\n    newargv = NULL; /* This will get reallocated on retry. */\n\n    /* Retry only if it's not a timeout and we never attempted a retry\n     * (or the code jumping here did not set may_retry to zero). */\n    if (errno != ETIMEDOUT && may_retry) {\n        may_retry = 0;\n        goto try_again;\n    }\n\n    /* Cleanup we want to do if no retry is attempted. */\n    zfree(ov); zfree(kv);\n    addReplySds(c,\n        sdscatprintf(sdsempty(),\n            \"-IOERR error or timeout %s to target instance\\r\\n\",\n            write_error ? \"writing\" : \"reading\"));\n    return;\n}\n\n/* -----------------------------------------------------------------------------\n * Cluster functions related to serving / redirecting clients\n * -------------------------------------------------------------------------- */\n\n/* The ASKING command is required after a -ASK redirection.\n * The client should issue ASKING before to actually send the command to\n * the target instance. See the Redis Cluster specification for more\n * information. */\nvoid askingCommand(client *c) {\n    if (server.cluster_enabled == 0) {\n        addReplyError(c,\"This instance has cluster support disabled\");\n        return;\n    }\n    c->flags |= CLIENT_ASKING;\n    addReply(c,shared.ok);\n}\n\n/* The READONLY command is used by clients to enter the read-only mode.\n * In this mode slaves will not redirect clients as long as clients access\n * with read-only commands to keys that are served by the slave's master. */\nvoid readonlyCommand(client *c) {\n    if (server.cluster_enabled == 0) {\n        addReplyError(c,\"This instance has cluster support disabled\");\n        return;\n    }\n    c->flags |= CLIENT_READONLY;\n    addReply(c,shared.ok);\n}\n\n/* The READWRITE command just clears the READONLY command state. */\nvoid readwriteCommand(client *c) {\n    c->flags &= ~CLIENT_READONLY;\n    addReply(c,shared.ok);\n}\n\n/* Return the pointer to the cluster node that is able to serve the command.\n * For the function to succeed the command should only target either:\n *\n * 1) A single key (even multiple times like LPOPRPUSH mylist mylist).\n * 2) Multiple keys in the same hash slot, while the slot is stable (no\n *    resharding in progress).\n *\n * On success the function returns the node that is able to serve the request.\n * If the node is not 'myself' a redirection must be perfomed. The kind of\n * redirection is specified setting the integer passed by reference\n * 'error_code', which will be set to CLUSTER_REDIR_ASK or\n * CLUSTER_REDIR_MOVED.\n *\n * When the node is 'myself' 'error_code' is set to CLUSTER_REDIR_NONE.\n *\n * If the command fails NULL is returned, and the reason of the failure is\n * provided via 'error_code', which will be set to:\n *\n * CLUSTER_REDIR_CROSS_SLOT if the request contains multiple keys that\n * don't belong to the same hash slot.\n *\n * CLUSTER_REDIR_UNSTABLE if the request contains multiple keys\n * belonging to the same slot, but the slot is not stable (in migration or\n * importing state, likely because a resharding is in progress).\n *\n * CLUSTER_REDIR_DOWN_UNBOUND if the request addresses a slot which is\n * not bound to any node. In this case the cluster global state should be\n * already \"down\" but it is fragile to rely on the update of the global state,\n * so we also handle it here.\n *\n * CLUSTER_REDIR_DOWN_STATE if the cluster is down but the user attempts to\n * execute a command that addresses one or more keys. */\nclusterNode *getNodeByQuery(client *c, struct redisCommand *cmd, robj **argv, int argc, int *hashslot, int *error_code) {\n    clusterNode *n = NULL;\n    robj *firstkey = NULL;\n    int multiple_keys = 0;\n    multiState *ms, _ms;\n    multiCmd mc;\n    int i, slot = 0, migrating_slot = 0, importing_slot = 0, missing_keys = 0;\n\n    /* Set error code optimistically for the base case. */\n    if (error_code) *error_code = CLUSTER_REDIR_NONE;\n\n    /* We handle all the cases as if they were EXEC commands, so we have\n     * a common code path for everything */\n    if (cmd->proc == execCommand) {\n        /* If CLIENT_MULTI flag is not set EXEC is just going to return an\n         * error. */\n        if (!(c->flags & CLIENT_MULTI)) return myself;\n        ms = &c->mstate;\n    } else {\n        /* In order to have a single codepath create a fake Multi State\n         * structure if the client is not in MULTI/EXEC state, this way\n         * we have a single codepath below. */\n        ms = &_ms;\n        _ms.commands = &mc;\n        _ms.count = 1;\n        mc.argv = argv;\n        mc.argc = argc;\n        mc.cmd = cmd;\n    }\n\n    /* Check that all the keys are in the same hash slot, and obtain this\n     * slot and the node associated. */\n    for (i = 0; i < ms->count; i++) {\n        struct redisCommand *mcmd;\n        robj **margv;\n        int margc, *keyindex, numkeys, j;\n\n        mcmd = ms->commands[i].cmd;\n        margc = ms->commands[i].argc;\n        margv = ms->commands[i].argv;\n\n        keyindex = getKeysFromCommand(mcmd,margv,margc,&numkeys);\n        for (j = 0; j < numkeys; j++) {\n            robj *thiskey = margv[keyindex[j]];\n            int thisslot = keyHashSlot((char*)thiskey->ptr,\n                                       sdslen(thiskey->ptr));\n\n            if (firstkey == NULL) {\n                /* This is the first key we see. Check what is the slot\n                 * and node. */\n                firstkey = thiskey;\n                slot = thisslot;\n                n = server.cluster->slots[slot];\n\n                /* Error: If a slot is not served, we are in \"cluster down\"\n                 * state. However the state is yet to be updated, so this was\n                 * not trapped earlier in processCommand(). Report the same\n                 * error to the client. */\n                if (n == NULL) {\n                    getKeysFreeResult(keyindex);\n                    if (error_code)\n                        *error_code = CLUSTER_REDIR_DOWN_UNBOUND;\n                    return NULL;\n                }\n\n                /* If we are migrating or importing this slot, we need to check\n                 * if we have all the keys in the request (the only way we\n                 * can safely serve the request, otherwise we return a TRYAGAIN\n                 * error). To do so we set the importing/migrating state and\n                 * increment a counter for every missing key. */\n                if (n == myself &&\n                    server.cluster->migrating_slots_to[slot] != NULL)\n                {\n                    migrating_slot = 1;\n                } else if (server.cluster->importing_slots_from[slot] != NULL) {\n                    importing_slot = 1;\n                }\n            } else {\n                /* If it is not the first key, make sure it is exactly\n                 * the same key as the first we saw. */\n                if (!equalStringObjects(firstkey,thiskey)) {\n                    if (slot != thisslot) {\n                        /* Error: multiple keys from different slots. */\n                        getKeysFreeResult(keyindex);\n                        if (error_code)\n                            *error_code = CLUSTER_REDIR_CROSS_SLOT;\n                        return NULL;\n                    } else {\n                        /* Flag this request as one with multiple different\n                         * keys. */\n                        multiple_keys = 1;\n                    }\n                }\n            }\n\n            /* Migarting / Improrting slot? Count keys we don't have. */\n            if ((migrating_slot || importing_slot) &&\n                lookupKeyRead(&server.db[0],thiskey) == NULL)\n            {\n                missing_keys++;\n            }\n        }\n        getKeysFreeResult(keyindex);\n    }\n\n    /* No key at all in command? then we can serve the request\n     * without redirections or errors in all the cases. */\n    if (n == NULL) return myself;\n\n    /* Cluster is globally down but we got keys? We can't serve the request. */\n    if (server.cluster->state != CLUSTER_OK) {\n        if (error_code) *error_code = CLUSTER_REDIR_DOWN_STATE;\n        return NULL;\n    }\n\n    /* Return the hashslot by reference. */\n    if (hashslot) *hashslot = slot;\n\n    /* MIGRATE always works in the context of the local node if the slot\n     * is open (migrating or importing state). We need to be able to freely\n     * move keys among instances in this case. */\n    if ((migrating_slot || importing_slot) && cmd->proc == migrateCommand)\n        return myself;\n\n    /* If we don't have all the keys and we are migrating the slot, send\n     * an ASK redirection. */\n    if (migrating_slot && missing_keys) {\n        if (error_code) *error_code = CLUSTER_REDIR_ASK;\n        return server.cluster->migrating_slots_to[slot];\n    }\n\n    /* If we are receiving the slot, and the client correctly flagged the\n     * request as \"ASKING\", we can serve the request. However if the request\n     * involves multiple keys and we don't have them all, the only option is\n     * to send a TRYAGAIN error. */\n    if (importing_slot &&\n        (c->flags & CLIENT_ASKING || cmd->flags & CMD_ASKING))\n    {\n        if (multiple_keys && missing_keys) {\n            if (error_code) *error_code = CLUSTER_REDIR_UNSTABLE;\n            return NULL;\n        } else {\n            return myself;\n        }\n    }\n\n    /* Handle the read-only client case reading from a slave: if this\n     * node is a slave and the request is about an hash slot our master\n     * is serving, we can reply without redirection. */\n    if (c->flags & CLIENT_READONLY &&\n        cmd->flags & CMD_READONLY &&\n        nodeIsSlave(myself) &&\n        myself->slaveof == n)\n    {\n        return myself;\n    }\n\n    /* Base case: just return the right node. However if this node is not\n     * myself, set error_code to MOVED since we need to issue a rediretion. */\n    if (n != myself && error_code) *error_code = CLUSTER_REDIR_MOVED;\n    return n;\n}\n\n/* Send the client the right redirection code, according to error_code\n * that should be set to one of CLUSTER_REDIR_* macros.\n *\n * If CLUSTER_REDIR_ASK or CLUSTER_REDIR_MOVED error codes\n * are used, then the node 'n' should not be NULL, but should be the\n * node we want to mention in the redirection. Moreover hashslot should\n * be set to the hash slot that caused the redirection. */\nvoid clusterRedirectClient(client *c, clusterNode *n, int hashslot, int error_code) {\n    if (error_code == CLUSTER_REDIR_CROSS_SLOT) {\n        addReplySds(c,sdsnew(\"-CROSSSLOT Keys in request don't hash to the same slot\\r\\n\"));\n    } else if (error_code == CLUSTER_REDIR_UNSTABLE) {\n        /* The request spawns mutliple keys in the same slot,\n         * but the slot is not \"stable\" currently as there is\n         * a migration or import in progress. */\n        addReplySds(c,sdsnew(\"-TRYAGAIN Multiple keys request during rehashing of slot\\r\\n\"));\n    } else if (error_code == CLUSTER_REDIR_DOWN_STATE) {\n        addReplySds(c,sdsnew(\"-CLUSTERDOWN The cluster is down\\r\\n\"));\n    } else if (error_code == CLUSTER_REDIR_DOWN_UNBOUND) {\n        addReplySds(c,sdsnew(\"-CLUSTERDOWN Hash slot not served\\r\\n\"));\n    } else if (error_code == CLUSTER_REDIR_MOVED ||\n               error_code == CLUSTER_REDIR_ASK)\n    {\n        addReplySds(c,sdscatprintf(sdsempty(),\n            \"-%s %d %s:%d\\r\\n\",\n            (error_code == CLUSTER_REDIR_ASK) ? \"ASK\" : \"MOVED\",\n            hashslot,n->ip,n->port));\n    } else {\n        serverPanic(\"getNodeByQuery() unknown error.\");\n    }\n}\n\n/* This function is called by the function processing clients incrementally\n * to detect timeouts, in order to handle the following case:\n *\n * 1) A client blocks with BLPOP or similar blocking operation.\n * 2) The master migrates the hash slot elsewhere or turns into a slave.\n * 3) The client may remain blocked forever (or up to the max timeout time)\n *    waiting for a key change that will never happen.\n *\n * If the client is found to be blocked into an hash slot this node no\n * longer handles, the client is sent a redirection error, and the function\n * returns 1. Otherwise 0 is returned and no operation is performed. */\nint clusterRedirectBlockedClientIfNeeded(client *c) {\n    if (c->flags & CLIENT_BLOCKED && c->btype == BLOCKED_LIST) {\n        dictEntry *de;\n        dictIterator *di;\n\n        /* If the cluster is down, unblock the client with the right error. */\n        if (server.cluster->state == CLUSTER_FAIL) {\n            clusterRedirectClient(c,NULL,0,CLUSTER_REDIR_DOWN_STATE);\n            return 1;\n        }\n\n        di = dictGetIterator(c->bpop.keys);\n        while((de = dictNext(di)) != NULL) {\n            robj *key = dictGetKey(de);\n            int slot = keyHashSlot((char*)key->ptr, sdslen(key->ptr));\n            clusterNode *node = server.cluster->slots[slot];\n\n            /* We send an error and unblock the client if:\n             * 1) The slot is unassigned, emitting a cluster down error.\n             * 2) The slot is not handled by this node, nor being imported. */\n            if (node != myself &&\n                server.cluster->importing_slots_from[slot] == NULL)\n            {\n                if (node == NULL) {\n                    clusterRedirectClient(c,NULL,0,\n                        CLUSTER_REDIR_DOWN_UNBOUND);\n                } else {\n                    clusterRedirectClient(c,node,slot,\n                        CLUSTER_REDIR_MOVED);\n                }\n                return 1;\n            }\n        }\n        dictReleaseIterator(di);\n    }\n    return 0;\n}\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/src/cluster.h",
    "content": "#ifndef __CLUSTER_H\n#define __CLUSTER_H\n\n/*-----------------------------------------------------------------------------\n * Redis cluster data structures, defines, exported API.\n *----------------------------------------------------------------------------*/\n\n#define CLUSTER_SLOTS 16384\n#define CLUSTER_OK 0          /* Everything looks ok */\n#define CLUSTER_FAIL 1        /* The cluster can't work */\n#define CLUSTER_NAMELEN 40    /* sha1 hex length */\n#define CLUSTER_PORT_INCR 10000 /* Cluster port = baseport + PORT_INCR */\n\n/* The following defines are amount of time, sometimes expressed as\n * multiplicators of the node timeout value (when ending with MULT). */\n#define CLUSTER_DEFAULT_NODE_TIMEOUT 15000\n#define CLUSTER_DEFAULT_SLAVE_VALIDITY 10 /* Slave max data age factor. */\n#define CLUSTER_DEFAULT_REQUIRE_FULL_COVERAGE 1\n#define CLUSTER_FAIL_REPORT_VALIDITY_MULT 2 /* Fail report validity. */\n#define CLUSTER_FAIL_UNDO_TIME_MULT 2 /* Undo fail if master is back. */\n#define CLUSTER_FAIL_UNDO_TIME_ADD 10 /* Some additional time. */\n#define CLUSTER_FAILOVER_DELAY 5 /* Seconds */\n#define CLUSTER_DEFAULT_MIGRATION_BARRIER 1\n#define CLUSTER_MF_TIMEOUT 5000 /* Milliseconds to do a manual failover. */\n#define CLUSTER_MF_PAUSE_MULT 2 /* Master pause manual failover mult. */\n#define CLUSTER_SLAVE_MIGRATION_DELAY 5000 /* Delay for slave migration. */\n\n/* Redirection errors returned by getNodeByQuery(). */\n#define CLUSTER_REDIR_NONE 0          /* Node can serve the request. */\n#define CLUSTER_REDIR_CROSS_SLOT 1    /* -CROSSSLOT request. */\n#define CLUSTER_REDIR_UNSTABLE 2      /* -TRYAGAIN redirection required */\n#define CLUSTER_REDIR_ASK 3           /* -ASK redirection required. */\n#define CLUSTER_REDIR_MOVED 4         /* -MOVED redirection required. */\n#define CLUSTER_REDIR_DOWN_STATE 5    /* -CLUSTERDOWN, global state. */\n#define CLUSTER_REDIR_DOWN_UNBOUND 6  /* -CLUSTERDOWN, unbound slot. */\n\nstruct clusterNode;\n\n/* clusterLink encapsulates everything needed to talk with a remote node. */\ntypedef struct clusterLink {\n    mstime_t ctime;             /* Link creation time */\n    int fd;                     /* TCP socket file descriptor */\n    sds sndbuf;                 /* Packet send buffer */\n    sds rcvbuf;                 /* Packet reception buffer */\n    struct clusterNode *node;   /* Node related to this link if any, or NULL */\n} clusterLink;\n\n/* Cluster node flags and macros. */\n#define CLUSTER_NODE_MASTER 1     /* The node is a master */\n#define CLUSTER_NODE_SLAVE 2      /* The node is a slave */\n#define CLUSTER_NODE_PFAIL 4      /* Failure? Need acknowledge */\n#define CLUSTER_NODE_FAIL 8       /* The node is believed to be malfunctioning */\n#define CLUSTER_NODE_MYSELF 16    /* This node is myself */\n#define CLUSTER_NODE_HANDSHAKE 32 /* We have still to exchange the first ping */\n#define CLUSTER_NODE_NOADDR   64  /* We don't know the address of this node */\n#define CLUSTER_NODE_MEET 128     /* Send a MEET message to this node */\n#define CLUSTER_NODE_MIGRATE_TO 256 /* Master elegible for replica migration. */\n#define CLUSTER_NODE_NULL_NAME \"\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\"\n\n#define nodeIsMaster(n) ((n)->flags & CLUSTER_NODE_MASTER)\n#define nodeIsSlave(n) ((n)->flags & CLUSTER_NODE_SLAVE)\n#define nodeInHandshake(n) ((n)->flags & CLUSTER_NODE_HANDSHAKE)\n#define nodeHasAddr(n) (!((n)->flags & CLUSTER_NODE_NOADDR))\n#define nodeWithoutAddr(n) ((n)->flags & CLUSTER_NODE_NOADDR)\n#define nodeTimedOut(n) ((n)->flags & CLUSTER_NODE_PFAIL)\n#define nodeFailed(n) ((n)->flags & CLUSTER_NODE_FAIL)\n\n/* Reasons why a slave is not able to failover. */\n#define CLUSTER_CANT_FAILOVER_NONE 0\n#define CLUSTER_CANT_FAILOVER_DATA_AGE 1\n#define CLUSTER_CANT_FAILOVER_WAITING_DELAY 2\n#define CLUSTER_CANT_FAILOVER_EXPIRED 3\n#define CLUSTER_CANT_FAILOVER_WAITING_VOTES 4\n#define CLUSTER_CANT_FAILOVER_RELOG_PERIOD (60*5) /* seconds. */\n\n/* This structure represent elements of node->fail_reports. */\ntypedef struct clusterNodeFailReport {\n    struct clusterNode *node;  /* Node reporting the failure condition. */\n    mstime_t time;             /* Time of the last report from this node. */\n} clusterNodeFailReport;\n\ntypedef struct clusterNode {\n    mstime_t ctime; /* Node object creation time. */\n    char name[CLUSTER_NAMELEN]; /* Node name, hex string, sha1-size */\n    int flags;      /* CLUSTER_NODE_... */\n    uint64_t configEpoch; /* Last configEpoch observed for this node */\n    unsigned char slots[CLUSTER_SLOTS/8]; /* slots handled by this node */\n    int numslots;   /* Number of slots handled by this node */\n    int numslaves;  /* Number of slave nodes, if this is a master */\n    struct clusterNode **slaves; /* pointers to slave nodes */\n    struct clusterNode *slaveof; /* pointer to the master node. Note that it\n                                    may be NULL even if the node is a slave\n                                    if we don't have the master node in our\n                                    tables. */\n    mstime_t ping_sent;      /* Unix time we sent latest ping */\n    mstime_t pong_received;  /* Unix time we received the pong */\n    mstime_t fail_time;      /* Unix time when FAIL flag was set */\n    mstime_t voted_time;     /* Last time we voted for a slave of this master */\n    mstime_t repl_offset_time;  /* Unix time we received offset for this node */\n    mstime_t orphaned_time;     /* Starting time of orphaned master condition */\n    long long repl_offset;      /* Last known repl offset for this node. */\n    char ip[NET_IP_STR_LEN];  /* Latest known IP address of this node */\n    int port;                   /* Latest known port of this node */\n    clusterLink *link;          /* TCP/IP link with this node */\n    list *fail_reports;         /* List of nodes signaling this as failing */\n} clusterNode;\n\ntypedef struct clusterState {\n    clusterNode *myself;  /* This node */\n    uint64_t currentEpoch;\n    int state;            /* CLUSTER_OK, CLUSTER_FAIL, ... */\n    int size;             /* Num of master nodes with at least one slot */\n    dict *nodes;          /* Hash table of name -> clusterNode structures */\n    dict *nodes_black_list; /* Nodes we don't re-add for a few seconds. */\n    clusterNode *migrating_slots_to[CLUSTER_SLOTS];\n    clusterNode *importing_slots_from[CLUSTER_SLOTS];\n    clusterNode *slots[CLUSTER_SLOTS];\n    zskiplist *slots_to_keys;\n    /* The following fields are used to take the slave state on elections. */\n    mstime_t failover_auth_time; /* Time of previous or next election. */\n    int failover_auth_count;    /* Number of votes received so far. */\n    int failover_auth_sent;     /* True if we already asked for votes. */\n    int failover_auth_rank;     /* This slave rank for current auth request. */\n    uint64_t failover_auth_epoch; /* Epoch of the current election. */\n    int cant_failover_reason;   /* Why a slave is currently not able to\n                                   failover. See the CANT_FAILOVER_* macros. */\n    /* Manual failover state in common. */\n    mstime_t mf_end;            /* Manual failover time limit (ms unixtime).\n                                   It is zero if there is no MF in progress. */\n    /* Manual failover state of master. */\n    clusterNode *mf_slave;      /* Slave performing the manual failover. */\n    /* Manual failover state of slave. */\n    long long mf_master_offset; /* Master offset the slave needs to start MF\n                                   or zero if stil not received. */\n    int mf_can_start;           /* If non-zero signal that the manual failover\n                                   can start requesting masters vote. */\n    /* The followign fields are used by masters to take state on elections. */\n    uint64_t lastVoteEpoch;     /* Epoch of the last vote granted. */\n    int todo_before_sleep; /* Things to do in clusterBeforeSleep(). */\n    long long stats_bus_messages_sent;  /* Num of msg sent via cluster bus. */\n    long long stats_bus_messages_received; /* Num of msg rcvd via cluster bus.*/\n} clusterState;\n\n/* clusterState todo_before_sleep flags. */\n#define CLUSTER_TODO_HANDLE_FAILOVER (1<<0)\n#define CLUSTER_TODO_UPDATE_STATE (1<<1)\n#define CLUSTER_TODO_SAVE_CONFIG (1<<2)\n#define CLUSTER_TODO_FSYNC_CONFIG (1<<3)\n\n/* Redis cluster messages header */\n\n/* Note that the PING, PONG and MEET messages are actually the same exact\n * kind of packet. PONG is the reply to ping, in the exact format as a PING,\n * while MEET is a special PING that forces the receiver to add the sender\n * as a node (if it is not already in the list). */\n#define CLUSTERMSG_TYPE_PING 0          /* Ping */\n#define CLUSTERMSG_TYPE_PONG 1          /* Pong (reply to Ping) */\n#define CLUSTERMSG_TYPE_MEET 2          /* Meet \"let's join\" message */\n#define CLUSTERMSG_TYPE_FAIL 3          /* Mark node xxx as failing */\n#define CLUSTERMSG_TYPE_PUBLISH 4       /* Pub/Sub Publish propagation */\n#define CLUSTERMSG_TYPE_FAILOVER_AUTH_REQUEST 5 /* May I failover? */\n#define CLUSTERMSG_TYPE_FAILOVER_AUTH_ACK 6     /* Yes, you have my vote */\n#define CLUSTERMSG_TYPE_UPDATE 7        /* Another node slots configuration */\n#define CLUSTERMSG_TYPE_MFSTART 8       /* Pause clients for manual failover */\n\n/* Initially we don't know our \"name\", but we'll find it once we connect\n * to the first node, using the getsockname() function. Then we'll use this\n * address for all the next messages. */\ntypedef struct {\n    char nodename[CLUSTER_NAMELEN];\n    uint32_t ping_sent;\n    uint32_t pong_received;\n    char ip[NET_IP_STR_LEN];  /* IP address last time it was seen */\n    uint16_t port;              /* port last time it was seen */\n    uint16_t flags;             /* node->flags copy */\n    uint16_t notused1;          /* Some room for future improvements. */\n    uint32_t notused2;\n} clusterMsgDataGossip;\n\ntypedef struct {\n    char nodename[CLUSTER_NAMELEN];\n} clusterMsgDataFail;\n\ntypedef struct {\n    uint32_t channel_len;\n    uint32_t message_len;\n    /* We can't reclare bulk_data as bulk_data[] since this structure is\n     * nested. The 8 bytes are removed from the count during the message\n     * length computation. */\n    unsigned char bulk_data[8];\n} clusterMsgDataPublish;\n\ntypedef struct {\n    uint64_t configEpoch; /* Config epoch of the specified instance. */\n    char nodename[CLUSTER_NAMELEN]; /* Name of the slots owner. */\n    unsigned char slots[CLUSTER_SLOTS/8]; /* Slots bitmap. */\n} clusterMsgDataUpdate;\n\nunion clusterMsgData {\n    /* PING, MEET and PONG */\n    struct {\n        /* Array of N clusterMsgDataGossip structures */\n        clusterMsgDataGossip gossip[1];\n    } ping;\n\n    /* FAIL */\n    struct {\n        clusterMsgDataFail about;\n    } fail;\n\n    /* PUBLISH */\n    struct {\n        clusterMsgDataPublish msg;\n    } publish;\n\n    /* UPDATE */\n    struct {\n        clusterMsgDataUpdate nodecfg;\n    } update;\n};\n\n#define CLUSTER_PROTO_VER 0 /* Cluster bus protocol version. */\n\ntypedef struct {\n    char sig[4];        /* Siganture \"RCmb\" (Redis Cluster message bus). */\n    uint32_t totlen;    /* Total length of this message */\n    uint16_t ver;       /* Protocol version, currently set to 0. */\n    uint16_t notused0;  /* 2 bytes not used. */\n    uint16_t type;      /* Message type */\n    uint16_t count;     /* Only used for some kind of messages. */\n    uint64_t currentEpoch;  /* The epoch accordingly to the sending node. */\n    uint64_t configEpoch;   /* The config epoch if it's a master, or the last\n                               epoch advertised by its master if it is a\n                               slave. */\n    uint64_t offset;    /* Master replication offset if node is a master or\n                           processed replication offset if node is a slave. */\n    char sender[CLUSTER_NAMELEN]; /* Name of the sender node */\n    unsigned char myslots[CLUSTER_SLOTS/8];\n    char slaveof[CLUSTER_NAMELEN];\n    char notused1[32];  /* 32 bytes reserved for future usage. */\n    uint16_t port;      /* Sender TCP base port */\n    uint16_t flags;     /* Sender node flags */\n    unsigned char state; /* Cluster state from the POV of the sender */\n    unsigned char mflags[3]; /* Message flags: CLUSTERMSG_FLAG[012]_... */\n    union clusterMsgData data;\n} clusterMsg;\n\n#define CLUSTERMSG_MIN_LEN (sizeof(clusterMsg)-sizeof(union clusterMsgData))\n\n/* Message flags better specify the packet content or are used to\n * provide some information about the node state. */\n#define CLUSTERMSG_FLAG0_PAUSED (1<<0) /* Master paused for manual failover. */\n#define CLUSTERMSG_FLAG0_FORCEACK (1<<1) /* Give ACK to AUTH_REQUEST even if\n                                            master is up. */\n\n/* ---------------------- API exported outside cluster.c -------------------- */\nclusterNode *getNodeByQuery(client *c, struct redisCommand *cmd, robj **argv, int argc, int *hashslot, int *ask);\nint clusterRedirectBlockedClientIfNeeded(client *c);\nvoid clusterRedirectClient(client *c, clusterNode *n, int hashslot, int error_code);\n\n#endif /* __CLUSTER_H */\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/src/config.c",
    "content": "/* Configuration file parsing and CONFIG GET/SET commands implementation.\n *\n * Copyright (c) 2009-2012, Salvatore Sanfilippo <antirez at gmail dot com>\n * All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions are met:\n *\n *   * Redistributions of source code must retain the above copyright notice,\n *     this list of conditions and the following disclaimer.\n *   * Redistributions in binary form must reproduce the above copyright\n *     notice, this list of conditions and the following disclaimer in the\n *     documentation and/or other materials provided with the distribution.\n *   * Neither the name of Redis nor the names of its contributors may be used\n *     to endorse or promote products derived from this software without\n *     specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\"\n * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\n * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE\n * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR\n * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF\n * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS\n * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN\n * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)\n * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE\n * POSSIBILITY OF SUCH DAMAGE.\n */\n\n#include \"server.h\"\n#include \"cluster.h\"\n\n#include <fcntl.h>\n#include <sys/stat.h>\n\n/*-----------------------------------------------------------------------------\n * Config file name-value maps.\n *----------------------------------------------------------------------------*/\n\ntypedef struct configEnum {\n    const char *name;\n    const int val;\n} configEnum;\n\nconfigEnum maxmemory_policy_enum[] = {\n    {\"volatile-lru\", MAXMEMORY_VOLATILE_LRU},\n    {\"volatile-random\",MAXMEMORY_VOLATILE_RANDOM},\n    {\"volatile-ttl\",MAXMEMORY_VOLATILE_TTL},\n    {\"allkeys-lru\",MAXMEMORY_ALLKEYS_LRU},\n    {\"allkeys-random\",MAXMEMORY_ALLKEYS_RANDOM},\n    {\"noeviction\",MAXMEMORY_NO_EVICTION},\n    {NULL, 0}\n};\n\nconfigEnum syslog_facility_enum[] = {\n    {\"user\",    LOG_USER},\n    {\"local0\",  LOG_LOCAL0},\n    {\"local1\",  LOG_LOCAL1},\n    {\"local2\",  LOG_LOCAL2},\n    {\"local3\",  LOG_LOCAL3},\n    {\"local4\",  LOG_LOCAL4},\n    {\"local5\",  LOG_LOCAL5},\n    {\"local6\",  LOG_LOCAL6},\n    {\"local7\",  LOG_LOCAL7},\n    {NULL, 0}\n};\n\nconfigEnum loglevel_enum[] = {\n    {\"debug\", LL_DEBUG},\n    {\"verbose\", LL_VERBOSE},\n    {\"notice\", LL_NOTICE},\n    {\"warning\", LL_WARNING},\n    {NULL,0}\n};\n\nconfigEnum supervised_mode_enum[] = {\n    {\"upstart\", SUPERVISED_UPSTART},\n    {\"systemd\", SUPERVISED_SYSTEMD},\n    {\"auto\", SUPERVISED_AUTODETECT},\n    {\"no\", SUPERVISED_NONE},\n    {NULL, 0}\n};\n\nconfigEnum aof_fsync_enum[] = {\n    {\"everysec\", AOF_FSYNC_EVERYSEC},\n    {\"always\", AOF_FSYNC_ALWAYS},\n    {\"no\", AOF_FSYNC_NO},\n    {NULL, 0}\n};\n\n/* Output buffer limits presets. */\nclientBufferLimitsConfig clientBufferLimitsDefaults[CLIENT_TYPE_OBUF_COUNT] = {\n    {0, 0, 0}, /* normal */\n    {1024*1024*256, 1024*1024*64, 60}, /* slave */\n    {1024*1024*32, 1024*1024*8, 60}  /* pubsub */\n};\n\n/*-----------------------------------------------------------------------------\n * Enum access functions\n *----------------------------------------------------------------------------*/\n\n/* Get enum value from name. If there is no match INT_MIN is returned. */\nint configEnumGetValue(configEnum *ce, char *name) {\n    while(ce->name != NULL) {\n        if (!strcasecmp(ce->name,name)) return ce->val;\n        ce++;\n    }\n    return INT_MIN;\n}\n\n/* Get enum name from value. If no match is found NULL is returned. */\nconst char *configEnumGetName(configEnum *ce, int val) {\n    while(ce->name != NULL) {\n        if (ce->val == val) return ce->name;\n        ce++;\n    }\n    return NULL;\n}\n\n/* Wrapper for configEnumGetName() returning \"unknown\" insetad of NULL if\n * there is no match. */\nconst char *configEnumGetNameOrUnknown(configEnum *ce, int val) {\n    const char *name = configEnumGetName(ce,val);\n    return name ? name : \"unknown\";\n}\n\n/* Used for INFO generation. */\nconst char *evictPolicyToString(void) {\n    return configEnumGetNameOrUnknown(maxmemory_policy_enum,server.maxmemory_policy);\n}\n\n/*-----------------------------------------------------------------------------\n * Config file parsing\n *----------------------------------------------------------------------------*/\n\nint yesnotoi(char *s) {\n    if (!strcasecmp(s,\"yes\")) return 1;\n    else if (!strcasecmp(s,\"no\")) return 0;\n    else return -1;\n}\n\nvoid appendServerSaveParams(time_t seconds, int changes) {\n    server.saveparams = zrealloc(server.saveparams,sizeof(struct saveparam)*(server.saveparamslen+1));\n    server.saveparams[server.saveparamslen].seconds = seconds;\n    server.saveparams[server.saveparamslen].changes = changes;\n    server.saveparamslen++;\n}\n\nvoid resetServerSaveParams(void) {\n    zfree(server.saveparams);\n    server.saveparams = NULL;\n    server.saveparamslen = 0;\n}\n\nvoid loadServerConfigFromString(char *config) {\n    char *err = NULL;\n    int linenum = 0, totlines, i;\n    int slaveof_linenum = 0;\n    sds *lines;\n\n    lines = sdssplitlen(config,strlen(config),\"\\n\",1,&totlines);\n\n    for (i = 0; i < totlines; i++) {\n        sds *argv;\n        int argc;\n\n        linenum = i+1;\n        lines[i] = sdstrim(lines[i],\" \\t\\r\\n\");\n\n        /* Skip comments and blank lines */\n        if (lines[i][0] == '#' || lines[i][0] == '\\0') continue;\n\n        /* Split into arguments */\n        argv = sdssplitargs(lines[i],&argc);\n        if (argv == NULL) {\n            err = \"Unbalanced quotes in configuration line\";\n            goto loaderr;\n        }\n\n        /* Skip this line if the resulting command vector is empty. */\n        if (argc == 0) {\n            sdsfreesplitres(argv,argc);\n            continue;\n        }\n        sdstolower(argv[0]);\n\n        /* Execute config directives */\n        if (!strcasecmp(argv[0],\"timeout\") && argc == 2) {\n            server.maxidletime = atoi(argv[1]);\n            if (server.maxidletime < 0) {\n                err = \"Invalid timeout value\"; goto loaderr;\n            }\n        } else if (!strcasecmp(argv[0],\"tcp-keepalive\") && argc == 2) {\n            server.tcpkeepalive = atoi(argv[1]);\n            if (server.tcpkeepalive < 0) {\n                err = \"Invalid tcp-keepalive value\"; goto loaderr;\n            }\n        } else if (!strcasecmp(argv[0],\"protected-mode\") && argc == 2) {\n            if ((server.protected_mode = yesnotoi(argv[1])) == -1) {\n                err = \"argument must be 'yes' or 'no'\"; goto loaderr;\n            }\n        } else if (!strcasecmp(argv[0],\"port\") && argc == 2) {\n            server.port = atoi(argv[1]);\n            if (server.port < 0 || server.port > 65535) {\n                err = \"Invalid port\"; goto loaderr;\n            }\n        } else if (!strcasecmp(argv[0],\"tcp-backlog\") && argc == 2) {\n            server.tcp_backlog = atoi(argv[1]);\n            if (server.tcp_backlog < 0) {\n                err = \"Invalid backlog value\"; goto loaderr;\n            }\n        } else if (!strcasecmp(argv[0],\"bind\") && argc >= 2) {\n            int j, addresses = argc-1;\n\n            if (addresses > CONFIG_BINDADDR_MAX) {\n                err = \"Too many bind addresses specified\"; goto loaderr;\n            }\n            for (j = 0; j < addresses; j++)\n                server.bindaddr[j] = zstrdup(argv[j+1]);\n            server.bindaddr_count = addresses;\n        } else if (!strcasecmp(argv[0],\"unixsocket\") && argc == 2) {\n            server.unixsocket = zstrdup(argv[1]);\n        } else if (!strcasecmp(argv[0],\"unixsocketperm\") && argc == 2) {\n            errno = 0;\n            server.unixsocketperm = (mode_t)strtol(argv[1], NULL, 8);\n            if (errno || server.unixsocketperm > 0777) {\n                err = \"Invalid socket file permissions\"; goto loaderr;\n            }\n        } else if (!strcasecmp(argv[0],\"save\")) {\n            if (argc == 3) {\n                int seconds = atoi(argv[1]);\n                int changes = atoi(argv[2]);\n                if (seconds < 1 || changes < 0) {\n                    err = \"Invalid save parameters\"; goto loaderr;\n                }\n                appendServerSaveParams(seconds,changes);\n            } else if (argc == 2 && !strcasecmp(argv[1],\"\")) {\n                resetServerSaveParams();\n            }\n        } else if (!strcasecmp(argv[0],\"dir\") && argc == 2) {\n            if (chdir(argv[1]) == -1) {\n                serverLog(LL_WARNING,\"Can't chdir to '%s': %s\",\n                    argv[1], strerror(errno));\n                exit(1);\n            }\n        } else if (!strcasecmp(argv[0],\"loglevel\") && argc == 2) {\n            server.verbosity = configEnumGetValue(loglevel_enum,argv[1]);\n            if (server.verbosity == INT_MIN) {\n                err = \"Invalid log level. \"\n                      \"Must be one of debug, verbose, notice, warning\";\n                goto loaderr;\n            }\n        } else if (!strcasecmp(argv[0],\"logfile\") && argc == 2) {\n            FILE *logfp;\n\n            zfree(server.logfile);\n            server.logfile = zstrdup(argv[1]);\n            if (server.logfile[0] != '\\0') {\n                /* Test if we are able to open the file. The server will not\n                 * be able to abort just for this problem later... */\n                logfp = fopen(server.logfile,\"a\");\n                if (logfp == NULL) {\n                    err = sdscatprintf(sdsempty(),\n                        \"Can't open the log file: %s\", strerror(errno));\n                    goto loaderr;\n                }\n                fclose(logfp);\n            }\n        } else if (!strcasecmp(argv[0],\"syslog-enabled\") && argc == 2) {\n            if ((server.syslog_enabled = yesnotoi(argv[1])) == -1) {\n                err = \"argument must be 'yes' or 'no'\"; goto loaderr;\n            }\n        } else if (!strcasecmp(argv[0],\"syslog-ident\") && argc == 2) {\n            if (server.syslog_ident) zfree(server.syslog_ident);\n            server.syslog_ident = zstrdup(argv[1]);\n        } else if (!strcasecmp(argv[0],\"syslog-facility\") && argc == 2) {\n            server.syslog_facility =\n                configEnumGetValue(syslog_facility_enum,argv[1]);\n            if (server.syslog_facility == INT_MIN) {\n                err = \"Invalid log facility. Must be one of USER or between LOCAL0-LOCAL7\";\n                goto loaderr;\n            }\n        } else if (!strcasecmp(argv[0],\"databases\") && argc == 2) {\n            server.dbnum = atoi(argv[1]);\n            if (server.dbnum < 1) {\n                err = \"Invalid number of databases\"; goto loaderr;\n            }\n        } else if (!strcasecmp(argv[0],\"include\") && argc == 2) {\n            loadServerConfig(argv[1],NULL);\n        } else if (!strcasecmp(argv[0],\"maxclients\") && argc == 2) {\n            server.maxclients = atoi(argv[1]);\n            if (server.maxclients < 1) {\n                err = \"Invalid max clients limit\"; goto loaderr;\n            }\n        } else if (!strcasecmp(argv[0],\"maxmemory\") && argc == 2) {\n            server.maxmemory = memtoll(argv[1],NULL);\n        } else if (!strcasecmp(argv[0],\"maxmemory-policy\") && argc == 2) {\n            server.maxmemory_policy =\n                configEnumGetValue(maxmemory_policy_enum,argv[1]);\n            if (server.maxmemory_policy == INT_MIN) {\n                err = \"Invalid maxmemory policy\";\n                goto loaderr;\n            }\n        } else if (!strcasecmp(argv[0],\"maxmemory-samples\") && argc == 2) {\n            server.maxmemory_samples = atoi(argv[1]);\n            if (server.maxmemory_samples <= 0) {\n                err = \"maxmemory-samples must be 1 or greater\";\n                goto loaderr;\n            }\n        } else if (!strcasecmp(argv[0],\"slaveof\") && argc == 3) {\n            slaveof_linenum = linenum;\n            server.masterhost = sdsnew(argv[1]);\n            server.masterport = atoi(argv[2]);\n            server.repl_state = REPL_STATE_CONNECT;\n        } else if (!strcasecmp(argv[0],\"repl-ping-slave-period\") && argc == 2) {\n            server.repl_ping_slave_period = atoi(argv[1]);\n            if (server.repl_ping_slave_period <= 0) {\n                err = \"repl-ping-slave-period must be 1 or greater\";\n                goto loaderr;\n            }\n        } else if (!strcasecmp(argv[0],\"repl-timeout\") && argc == 2) {\n            server.repl_timeout = atoi(argv[1]);\n            if (server.repl_timeout <= 0) {\n                err = \"repl-timeout must be 1 or greater\";\n                goto loaderr;\n            }\n        } else if (!strcasecmp(argv[0],\"repl-disable-tcp-nodelay\") && argc==2) {\n            if ((server.repl_disable_tcp_nodelay = yesnotoi(argv[1])) == -1) {\n                err = \"argument must be 'yes' or 'no'\"; goto loaderr;\n            }\n        } else if (!strcasecmp(argv[0],\"repl-diskless-sync\") && argc==2) {\n            if ((server.repl_diskless_sync = yesnotoi(argv[1])) == -1) {\n                err = \"argument must be 'yes' or 'no'\"; goto loaderr;\n            }\n        } else if (!strcasecmp(argv[0],\"repl-diskless-sync-delay\") && argc==2) {\n            server.repl_diskless_sync_delay = atoi(argv[1]);\n            if (server.repl_diskless_sync_delay < 0) {\n                err = \"repl-diskless-sync-delay can't be negative\";\n                goto loaderr;\n            }\n        } else if (!strcasecmp(argv[0],\"repl-backlog-size\") && argc == 2) {\n            long long size = memtoll(argv[1],NULL);\n            if (size <= 0) {\n                err = \"repl-backlog-size must be 1 or greater.\";\n                goto loaderr;\n            }\n            resizeReplicationBacklog(size);\n        } else if (!strcasecmp(argv[0],\"repl-backlog-ttl\") && argc == 2) {\n            server.repl_backlog_time_limit = atoi(argv[1]);\n            if (server.repl_backlog_time_limit < 0) {\n                err = \"repl-backlog-ttl can't be negative \";\n                goto loaderr;\n            }\n        } else if (!strcasecmp(argv[0],\"masterauth\") && argc == 2) {\n            zfree(server.masterauth);\n            server.masterauth = zstrdup(argv[1]);\n        } else if (!strcasecmp(argv[0],\"slave-serve-stale-data\") && argc == 2) {\n            if ((server.repl_serve_stale_data = yesnotoi(argv[1])) == -1) {\n                err = \"argument must be 'yes' or 'no'\"; goto loaderr;\n            }\n        } else if (!strcasecmp(argv[0],\"slave-read-only\") && argc == 2) {\n            if ((server.repl_slave_ro = yesnotoi(argv[1])) == -1) {\n                err = \"argument must be 'yes' or 'no'\"; goto loaderr;\n            }\n        } else if (!strcasecmp(argv[0],\"rdbcompression\") && argc == 2) {\n            if ((server.rdb_compression = yesnotoi(argv[1])) == -1) {\n                err = \"argument must be 'yes' or 'no'\"; goto loaderr;\n            }\n        } else if (!strcasecmp(argv[0],\"rdbchecksum\") && argc == 2) {\n            if ((server.rdb_checksum = yesnotoi(argv[1])) == -1) {\n                err = \"argument must be 'yes' or 'no'\"; goto loaderr;\n            }\n        } else if (!strcasecmp(argv[0],\"activerehashing\") && argc == 2) {\n            if ((server.activerehashing = yesnotoi(argv[1])) == -1) {\n                err = \"argument must be 'yes' or 'no'\"; goto loaderr;\n            }\n        } else if (!strcasecmp(argv[0],\"daemonize\") && argc == 2) {\n            if ((server.daemonize = yesnotoi(argv[1])) == -1) {\n                err = \"argument must be 'yes' or 'no'\"; goto loaderr;\n            }\n        } else if (!strcasecmp(argv[0],\"hz\") && argc == 2) {\n            server.hz = atoi(argv[1]);\n            if (server.hz < CONFIG_MIN_HZ) server.hz = CONFIG_MIN_HZ;\n            if (server.hz > CONFIG_MAX_HZ) server.hz = CONFIG_MAX_HZ;\n        } else if (!strcasecmp(argv[0],\"appendonly\") && argc == 2) {\n            int yes;\n\n            if ((yes = yesnotoi(argv[1])) == -1) {\n                err = \"argument must be 'yes' or 'no'\"; goto loaderr;\n            }\n            server.aof_state = yes ? AOF_ON : AOF_OFF;\n        } else if (!strcasecmp(argv[0],\"appendfilename\") && argc == 2) {\n            if (!pathIsBaseName(argv[1])) {\n                err = \"appendfilename can't be a path, just a filename\";\n                goto loaderr;\n            }\n            zfree(server.aof_filename);\n            server.aof_filename = zstrdup(argv[1]);\n        } else if (!strcasecmp(argv[0],\"no-appendfsync-on-rewrite\")\n                   && argc == 2) {\n            if ((server.aof_no_fsync_on_rewrite= yesnotoi(argv[1])) == -1) {\n                err = \"argument must be 'yes' or 'no'\"; goto loaderr;\n            }\n        } else if (!strcasecmp(argv[0],\"appendfsync\") && argc == 2) {\n            server.aof_fsync = configEnumGetValue(aof_fsync_enum,argv[1]);\n            if (server.aof_fsync == INT_MIN) {\n                err = \"argument must be 'no', 'always' or 'everysec'\";\n                goto loaderr;\n            }\n        } else if (!strcasecmp(argv[0],\"auto-aof-rewrite-percentage\") &&\n                   argc == 2)\n        {\n            server.aof_rewrite_perc = atoi(argv[1]);\n            if (server.aof_rewrite_perc < 0) {\n                err = \"Invalid negative percentage for AOF auto rewrite\";\n                goto loaderr;\n            }\n        } else if (!strcasecmp(argv[0],\"auto-aof-rewrite-min-size\") &&\n                   argc == 2)\n        {\n            server.aof_rewrite_min_size = memtoll(argv[1],NULL);\n        } else if (!strcasecmp(argv[0],\"aof-rewrite-incremental-fsync\") &&\n                   argc == 2)\n        {\n            if ((server.aof_rewrite_incremental_fsync =\n                 yesnotoi(argv[1])) == -1) {\n                err = \"argument must be 'yes' or 'no'\"; goto loaderr;\n            }\n        } else if (!strcasecmp(argv[0],\"aof-load-truncated\") && argc == 2) {\n            if ((server.aof_load_truncated = yesnotoi(argv[1])) == -1) {\n                err = \"argument must be 'yes' or 'no'\"; goto loaderr;\n            }\n        } else if (!strcasecmp(argv[0],\"requirepass\") && argc == 2) {\n            if (strlen(argv[1]) > CONFIG_AUTHPASS_MAX_LEN) {\n                err = \"Password is longer than CONFIG_AUTHPASS_MAX_LEN\";\n                goto loaderr;\n            }\n            server.requirepass = zstrdup(argv[1]);\n        } else if (!strcasecmp(argv[0],\"pidfile\") && argc == 2) {\n            zfree(server.pidfile);\n            server.pidfile = zstrdup(argv[1]);\n        } else if (!strcasecmp(argv[0],\"dbfilename\") && argc == 2) {\n            if (!pathIsBaseName(argv[1])) {\n                err = \"dbfilename can't be a path, just a filename\";\n                goto loaderr;\n            }\n            zfree(server.rdb_filename);\n            server.rdb_filename = zstrdup(argv[1]);\n        } else if (!strcasecmp(argv[0],\"hash-max-ziplist-entries\") && argc == 2) {\n            server.hash_max_ziplist_entries = memtoll(argv[1], NULL);\n        } else if (!strcasecmp(argv[0],\"hash-max-ziplist-value\") && argc == 2) {\n            server.hash_max_ziplist_value = memtoll(argv[1], NULL);\n        } else if (!strcasecmp(argv[0],\"list-max-ziplist-entries\") && argc == 2){\n            /* DEAD OPTION */\n        } else if (!strcasecmp(argv[0],\"list-max-ziplist-value\") && argc == 2) {\n            /* DEAD OPTION */\n        } else if (!strcasecmp(argv[0],\"list-max-ziplist-size\") && argc == 2) {\n            server.list_max_ziplist_size = atoi(argv[1]);\n        } else if (!strcasecmp(argv[0],\"list-compress-depth\") && argc == 2) {\n            server.list_compress_depth = atoi(argv[1]);\n        } else if (!strcasecmp(argv[0],\"set-max-intset-entries\") && argc == 2) {\n            server.set_max_intset_entries = memtoll(argv[1], NULL);\n        } else if (!strcasecmp(argv[0],\"zset-max-ziplist-entries\") && argc == 2) {\n            server.zset_max_ziplist_entries = memtoll(argv[1], NULL);\n        } else if (!strcasecmp(argv[0],\"zset-max-ziplist-value\") && argc == 2) {\n            server.zset_max_ziplist_value = memtoll(argv[1], NULL);\n        } else if (!strcasecmp(argv[0],\"hll-sparse-max-bytes\") && argc == 2) {\n            server.hll_sparse_max_bytes = memtoll(argv[1], NULL);\n        } else if (!strcasecmp(argv[0],\"rename-command\") && argc == 3) {\n            struct redisCommand *cmd = lookupCommand(argv[1]);\n            int retval;\n\n            if (!cmd) {\n                err = \"No such command in rename-command\";\n                goto loaderr;\n            }\n\n            /* If the target command name is the empty string we just\n             * remove it from the command table. */\n            retval = dictDelete(server.commands, argv[1]);\n            serverAssert(retval == DICT_OK);\n\n            /* Otherwise we re-add the command under a different name. */\n            if (sdslen(argv[2]) != 0) {\n                sds copy = sdsdup(argv[2]);\n\n                retval = dictAdd(server.commands, copy, cmd);\n                if (retval != DICT_OK) {\n                    sdsfree(copy);\n                    err = \"Target command name already exists\"; goto loaderr;\n                }\n            }\n        } else if (!strcasecmp(argv[0],\"cluster-enabled\") && argc == 2) {\n            if ((server.cluster_enabled = yesnotoi(argv[1])) == -1) {\n                err = \"argument must be 'yes' or 'no'\"; goto loaderr;\n            }\n        } else if (!strcasecmp(argv[0],\"cluster-config-file\") && argc == 2) {\n            zfree(server.cluster_configfile);\n            server.cluster_configfile = zstrdup(argv[1]);\n        } else if (!strcasecmp(argv[0],\"cluster-require-full-coverage\") &&\n                    argc == 2)\n        {\n            if ((server.cluster_require_full_coverage = yesnotoi(argv[1])) == -1)\n            {\n                err = \"argument must be 'yes' or 'no'\"; goto loaderr;\n            }\n        } else if (!strcasecmp(argv[0],\"cluster-node-timeout\") && argc == 2) {\n            server.cluster_node_timeout = strtoll(argv[1],NULL,10);\n            if (server.cluster_node_timeout <= 0) {\n                err = \"cluster node timeout must be 1 or greater\"; goto loaderr;\n            }\n        } else if (!strcasecmp(argv[0],\"cluster-migration-barrier\")\n                   && argc == 2)\n        {\n            server.cluster_migration_barrier = atoi(argv[1]);\n            if (server.cluster_migration_barrier < 0) {\n                err = \"cluster migration barrier must zero or positive\";\n                goto loaderr;\n            }\n        } else if (!strcasecmp(argv[0],\"cluster-slave-validity-factor\")\n                   && argc == 2)\n        {\n            server.cluster_slave_validity_factor = atoi(argv[1]);\n            if (server.cluster_slave_validity_factor < 0) {\n                err = \"cluster slave validity factor must be zero or positive\";\n                goto loaderr;\n            }\n        } else if (!strcasecmp(argv[0],\"lua-time-limit\") && argc == 2) {\n            server.lua_time_limit = strtoll(argv[1],NULL,10);\n        } else if (!strcasecmp(argv[0],\"slowlog-log-slower-than\") &&\n                   argc == 2)\n        {\n            server.slowlog_log_slower_than = strtoll(argv[1],NULL,10);\n        } else if (!strcasecmp(argv[0],\"latency-monitor-threshold\") &&\n                   argc == 2)\n        {\n            server.latency_monitor_threshold = strtoll(argv[1],NULL,10);\n            if (server.latency_monitor_threshold < 0) {\n                err = \"The latency threshold can't be negative\";\n                goto loaderr;\n            }\n        } else if (!strcasecmp(argv[0],\"slowlog-max-len\") && argc == 2) {\n            server.slowlog_max_len = strtoll(argv[1],NULL,10);\n        } else if (!strcasecmp(argv[0],\"client-output-buffer-limit\") &&\n                   argc == 5)\n        {\n            int class = getClientTypeByName(argv[1]);\n            unsigned long long hard, soft;\n            int soft_seconds;\n\n            if (class == -1 || class == CLIENT_TYPE_MASTER) {\n                err = \"Unrecognized client limit class: the user specified \"\n                \"an invalid one, or 'master' which has no buffer limits.\";\n                goto loaderr;\n            }\n            hard = memtoll(argv[2],NULL);\n            soft = memtoll(argv[3],NULL);\n            soft_seconds = atoi(argv[4]);\n            if (soft_seconds < 0) {\n                err = \"Negative number of seconds in soft limit is invalid\";\n                goto loaderr;\n            }\n            server.client_obuf_limits[class].hard_limit_bytes = hard;\n            server.client_obuf_limits[class].soft_limit_bytes = soft;\n            server.client_obuf_limits[class].soft_limit_seconds = soft_seconds;\n        } else if (!strcasecmp(argv[0],\"stop-writes-on-bgsave-error\") &&\n                   argc == 2) {\n            if ((server.stop_writes_on_bgsave_err = yesnotoi(argv[1])) == -1) {\n                err = \"argument must be 'yes' or 'no'\"; goto loaderr;\n            }\n        } else if (!strcasecmp(argv[0],\"slave-priority\") && argc == 2) {\n            server.slave_priority = atoi(argv[1]);\n        } else if (!strcasecmp(argv[0],\"slave-announce-ip\") && argc == 2) {\n            zfree(server.slave_announce_ip);\n            server.slave_announce_ip = zstrdup(argv[1]);\n        } else if (!strcasecmp(argv[0],\"slave-announce-port\") && argc == 2) {\n            server.slave_announce_port = atoi(argv[1]);\n            if (server.slave_announce_port < 0 ||\n                server.slave_announce_port > 65535)\n            {\n                err = \"Invalid port\"; goto loaderr;\n            }\n        } else if (!strcasecmp(argv[0],\"min-slaves-to-write\") && argc == 2) {\n            server.repl_min_slaves_to_write = atoi(argv[1]);\n            if (server.repl_min_slaves_to_write < 0) {\n                err = \"Invalid value for min-slaves-to-write.\"; goto loaderr;\n            }\n        } else if (!strcasecmp(argv[0],\"min-slaves-max-lag\") && argc == 2) {\n            server.repl_min_slaves_max_lag = atoi(argv[1]);\n            if (server.repl_min_slaves_max_lag < 0) {\n                err = \"Invalid value for min-slaves-max-lag.\"; goto loaderr;\n            }\n        } else if (!strcasecmp(argv[0],\"notify-keyspace-events\") && argc == 2) {\n            int flags = keyspaceEventsStringToFlags(argv[1]);\n\n            if (flags == -1) {\n                err = \"Invalid event class character. Use 'g$lshzxeA'.\";\n                goto loaderr;\n            }\n            server.notify_keyspace_events = flags;\n        } else if (!strcasecmp(argv[0],\"supervised\") && argc == 2) {\n            server.supervised_mode =\n                configEnumGetValue(supervised_mode_enum,argv[1]);\n\n            if (server.supervised_mode == INT_MIN) {\n                err = \"Invalid option for 'supervised'. \"\n                    \"Allowed values: 'upstart', 'systemd', 'auto', or 'no'\";\n                goto loaderr;\n            }\n        } else if (!strcasecmp(argv[0],\"sentinel\")) {\n            /* argc == 1 is handled by main() as we need to enter the sentinel\n             * mode ASAP. */\n            if (argc != 1) {\n                if (!server.sentinel_mode) {\n                    err = \"sentinel directive while not in sentinel mode\";\n                    goto loaderr;\n                }\n                err = sentinelHandleConfiguration(argv+1,argc-1);\n                if (err) goto loaderr;\n            }\n        } else {\n            err = \"Bad directive or wrong number of arguments\"; goto loaderr;\n        }\n        sdsfreesplitres(argv,argc);\n    }\n\n    /* Sanity checks. */\n    if (server.cluster_enabled && server.masterhost) {\n        linenum = slaveof_linenum;\n        i = linenum-1;\n        err = \"slaveof directive not allowed in cluster mode\";\n        goto loaderr;\n    }\n\n    sdsfreesplitres(lines,totlines);\n    return;\n\nloaderr:\n    fprintf(stderr, \"\\n*** FATAL CONFIG FILE ERROR ***\\n\");\n    fprintf(stderr, \"Reading the configuration file, at line %d\\n\", linenum);\n    fprintf(stderr, \">>> '%s'\\n\", lines[i]);\n    fprintf(stderr, \"%s\\n\", err);\n    exit(1);\n}\n\n/* Load the server configuration from the specified filename.\n * The function appends the additional configuration directives stored\n * in the 'options' string to the config file before loading.\n *\n * Both filename and options can be NULL, in such a case are considered\n * empty. This way loadServerConfig can be used to just load a file or\n * just load a string. */\nvoid loadServerConfig(char *filename, char *options) {\n    sds config = sdsempty();\n    char buf[CONFIG_MAX_LINE+1];\n\n    /* Load the file content */\n    if (filename) {\n        FILE *fp;\n\n        if (filename[0] == '-' && filename[1] == '\\0') {\n            fp = stdin;\n        } else {\n            if ((fp = fopen(filename,\"r\")) == NULL) {\n                serverLog(LL_WARNING,\n                    \"Fatal error, can't open config file '%s'\", filename);\n                exit(1);\n            }\n        }\n        while(fgets(buf,CONFIG_MAX_LINE+1,fp) != NULL)\n            config = sdscat(config,buf);\n        if (fp != stdin) fclose(fp);\n    }\n    /* Append the additional options */\n    if (options) {\n        config = sdscat(config,\"\\n\");\n        config = sdscat(config,options);\n    }\n    loadServerConfigFromString(config);\n    sdsfree(config);\n}\n\n/*-----------------------------------------------------------------------------\n * CONFIG SET implementation\n *----------------------------------------------------------------------------*/\n\n#define config_set_bool_field(_name,_var) \\\n    } else if (!strcasecmp(c->argv[2]->ptr,_name)) { \\\n        int yn = yesnotoi(o->ptr); \\\n        if (yn == -1) goto badfmt; \\\n        _var = yn;\n\n#define config_set_numerical_field(_name,_var,min,max) \\\n    } else if (!strcasecmp(c->argv[2]->ptr,_name)) { \\\n        if (getLongLongFromObject(o,&ll) == C_ERR) goto badfmt; \\\n        if (min != LLONG_MIN && ll < min) goto badfmt; \\\n        if (max != LLONG_MAX && ll > max) goto badfmt; \\\n        _var = ll;\n\n#define config_set_memory_field(_name,_var) \\\n    } else if (!strcasecmp(c->argv[2]->ptr,_name)) { \\\n        ll = memtoll(o->ptr,&err); \\\n        if (err || ll < 0) goto badfmt; \\\n        _var = ll;\n\n#define config_set_enum_field(_name,_var,_enumvar) \\\n    } else if (!strcasecmp(c->argv[2]->ptr,_name)) { \\\n        int enumval = configEnumGetValue(_enumvar,o->ptr); \\\n        if (enumval == INT_MIN) goto badfmt; \\\n        _var = enumval;\n\n#define config_set_special_field(_name) \\\n    } else if (!strcasecmp(c->argv[2]->ptr,_name)) {\n\n#define config_set_else } else\n\nvoid configSetCommand(client *c) {\n    robj *o;\n    long long ll;\n    int err;\n    serverAssertWithInfo(c,c->argv[2],sdsEncodedObject(c->argv[2]));\n    serverAssertWithInfo(c,c->argv[3],sdsEncodedObject(c->argv[3]));\n    o = c->argv[3];\n\n    if (0) { /* this starts the config_set macros else-if chain. */\n\n    /* Special fields that can't be handled with general macros. */\n    config_set_special_field(\"dbfilename\") {\n        if (!pathIsBaseName(o->ptr)) {\n            addReplyError(c, \"dbfilename can't be a path, just a filename\");\n            return;\n        }\n        zfree(server.rdb_filename);\n        server.rdb_filename = zstrdup(o->ptr);\n    } config_set_special_field(\"requirepass\") {\n        if (sdslen(o->ptr) > CONFIG_AUTHPASS_MAX_LEN) goto badfmt;\n        zfree(server.requirepass);\n        server.requirepass = ((char*)o->ptr)[0] ? zstrdup(o->ptr) : NULL;\n    } config_set_special_field(\"masterauth\") {\n        zfree(server.masterauth);\n        server.masterauth = ((char*)o->ptr)[0] ? zstrdup(o->ptr) : NULL;\n    } config_set_special_field(\"maxclients\") {\n        int orig_value = server.maxclients;\n\n        if (getLongLongFromObject(o,&ll) == C_ERR || ll < 1) goto badfmt;\n\n        /* Try to check if the OS is capable of supporting so many FDs. */\n        server.maxclients = ll;\n        if (ll > orig_value) {\n            adjustOpenFilesLimit();\n            if (server.maxclients != ll) {\n                addReplyErrorFormat(c,\"The operating system is not able to handle the specified number of clients, try with %d\", server.maxclients);\n                server.maxclients = orig_value;\n                return;\n            }\n            if ((unsigned int) aeGetSetSize(server.el) <\n                server.maxclients + CONFIG_FDSET_INCR)\n            {\n                if (aeResizeSetSize(server.el,\n                    server.maxclients + CONFIG_FDSET_INCR) == AE_ERR)\n                {\n                    addReplyError(c,\"The event loop API used by Redis is not able to handle the specified number of clients\");\n                    server.maxclients = orig_value;\n                    return;\n                }\n            }\n        }\n    } config_set_special_field(\"appendonly\") {\n        int enable = yesnotoi(o->ptr);\n\n        if (enable == -1) goto badfmt;\n        if (enable == 0 && server.aof_state != AOF_OFF) {\n            stopAppendOnly();\n        } else if (enable && server.aof_state == AOF_OFF) {\n            if (startAppendOnly() == C_ERR) {\n                addReplyError(c,\n                    \"Unable to turn on AOF. Check server logs.\");\n                return;\n            }\n        }\n    } config_set_special_field(\"save\") {\n        int vlen, j;\n        sds *v = sdssplitlen(o->ptr,sdslen(o->ptr),\" \",1,&vlen);\n\n        /* Perform sanity check before setting the new config:\n         * - Even number of args\n         * - Seconds >= 1, changes >= 0 */\n        if (vlen & 1) {\n            sdsfreesplitres(v,vlen);\n            goto badfmt;\n        }\n        for (j = 0; j < vlen; j++) {\n            char *eptr;\n            long val;\n\n            val = strtoll(v[j], &eptr, 10);\n            if (eptr[0] != '\\0' ||\n                ((j & 1) == 0 && val < 1) ||\n                ((j & 1) == 1 && val < 0)) {\n                sdsfreesplitres(v,vlen);\n                goto badfmt;\n            }\n        }\n        /* Finally set the new config */\n        resetServerSaveParams();\n        for (j = 0; j < vlen; j += 2) {\n            time_t seconds;\n            int changes;\n\n            seconds = strtoll(v[j],NULL,10);\n            changes = strtoll(v[j+1],NULL,10);\n            appendServerSaveParams(seconds, changes);\n        }\n        sdsfreesplitres(v,vlen);\n    } config_set_special_field(\"dir\") {\n        if (chdir((char*)o->ptr) == -1) {\n            addReplyErrorFormat(c,\"Changing directory: %s\", strerror(errno));\n            return;\n        }\n    } config_set_special_field(\"client-output-buffer-limit\") {\n        int vlen, j;\n        sds *v = sdssplitlen(o->ptr,sdslen(o->ptr),\" \",1,&vlen);\n\n        /* We need a multiple of 4: <class> <hard> <soft> <soft_seconds> */\n        if (vlen % 4) {\n            sdsfreesplitres(v,vlen);\n            goto badfmt;\n        }\n\n        /* Sanity check of single arguments, so that we either refuse the\n         * whole configuration string or accept it all, even if a single\n         * error in a single client class is present. */\n        for (j = 0; j < vlen; j++) {\n            long val;\n\n            if ((j % 4) == 0) {\n                int class = getClientTypeByName(v[j]);\n                if (class == -1 || class == CLIENT_TYPE_MASTER) {\n                    sdsfreesplitres(v,vlen);\n                    goto badfmt;\n                }\n            } else {\n                val = memtoll(v[j], &err);\n                if (err || val < 0) {\n                    sdsfreesplitres(v,vlen);\n                    goto badfmt;\n                }\n            }\n        }\n        /* Finally set the new config */\n        for (j = 0; j < vlen; j += 4) {\n            int class;\n            unsigned long long hard, soft;\n            int soft_seconds;\n\n            class = getClientTypeByName(v[j]);\n            hard = strtoll(v[j+1],NULL,10);\n            soft = strtoll(v[j+2],NULL,10);\n            soft_seconds = strtoll(v[j+3],NULL,10);\n\n            server.client_obuf_limits[class].hard_limit_bytes = hard;\n            server.client_obuf_limits[class].soft_limit_bytes = soft;\n            server.client_obuf_limits[class].soft_limit_seconds = soft_seconds;\n        }\n        sdsfreesplitres(v,vlen);\n    } config_set_special_field(\"notify-keyspace-events\") {\n        int flags = keyspaceEventsStringToFlags(o->ptr);\n\n        if (flags == -1) goto badfmt;\n        server.notify_keyspace_events = flags;\n    } config_set_special_field(\"slave-announce-ip\") {\n        zfree(server.slave_announce_ip);\n        server.slave_announce_ip = ((char*)o->ptr)[0] ? zstrdup(o->ptr) : NULL;\n\n    /* Boolean fields.\n     * config_set_bool_field(name,var). */\n    } config_set_bool_field(\n      \"rdbcompression\", server.rdb_compression) {\n    } config_set_bool_field(\n      \"repl-disable-tcp-nodelay\",server.repl_disable_tcp_nodelay) {\n    } config_set_bool_field(\n      \"repl-diskless-sync\",server.repl_diskless_sync) {\n    } config_set_bool_field(\n      \"cluster-require-full-coverage\",server.cluster_require_full_coverage) {\n    } config_set_bool_field(\n      \"aof-rewrite-incremental-fsync\",server.aof_rewrite_incremental_fsync) {\n    } config_set_bool_field(\n      \"aof-load-truncated\",server.aof_load_truncated) {\n    } config_set_bool_field(\n      \"slave-serve-stale-data\",server.repl_serve_stale_data) {\n    } config_set_bool_field(\n      \"slave-read-only\",server.repl_slave_ro) {\n    } config_set_bool_field(\n      \"activerehashing\",server.activerehashing) {\n    } config_set_bool_field(\n      \"protected-mode\",server.protected_mode) {\n    } config_set_bool_field(\n      \"stop-writes-on-bgsave-error\",server.stop_writes_on_bgsave_err) {\n    } config_set_bool_field(\n      \"no-appendfsync-on-rewrite\",server.aof_no_fsync_on_rewrite) {\n\n    /* Numerical fields.\n     * config_set_numerical_field(name,var,min,max) */\n    } config_set_numerical_field(\n      \"tcp-keepalive\",server.tcpkeepalive,0,LLONG_MAX) {\n    } config_set_numerical_field(\n      \"maxmemory-samples\",server.maxmemory_samples,1,LLONG_MAX) {\n    } config_set_numerical_field(\n      \"timeout\",server.maxidletime,0,LONG_MAX) {\n    } config_set_numerical_field(\n      \"auto-aof-rewrite-percentage\",server.aof_rewrite_perc,0,LLONG_MAX){\n    } config_set_numerical_field(\n      \"auto-aof-rewrite-min-size\",server.aof_rewrite_min_size,0,LLONG_MAX) {\n    } config_set_numerical_field(\n      \"hash-max-ziplist-entries\",server.hash_max_ziplist_entries,0,LLONG_MAX) {\n    } config_set_numerical_field(\n      \"hash-max-ziplist-value\",server.hash_max_ziplist_value,0,LLONG_MAX) {\n    } config_set_numerical_field(\n      \"list-max-ziplist-size\",server.list_max_ziplist_size,INT_MIN,INT_MAX) {\n    } config_set_numerical_field(\n      \"list-compress-depth\",server.list_compress_depth,0,INT_MAX) {\n    } config_set_numerical_field(\n      \"set-max-intset-entries\",server.set_max_intset_entries,0,LLONG_MAX) {\n    } config_set_numerical_field(\n      \"zset-max-ziplist-entries\",server.zset_max_ziplist_entries,0,LLONG_MAX) {\n    } config_set_numerical_field(\n      \"zset-max-ziplist-value\",server.zset_max_ziplist_value,0,LLONG_MAX) {\n    } config_set_numerical_field(\n      \"hll-sparse-max-bytes\",server.hll_sparse_max_bytes,0,LLONG_MAX) {\n    } config_set_numerical_field(\n      \"lua-time-limit\",server.lua_time_limit,0,LLONG_MAX) {\n    } config_set_numerical_field(\n      \"slowlog-log-slower-than\",server.slowlog_log_slower_than,0,LLONG_MAX) {\n    } config_set_numerical_field(\n      \"slowlog-max-len\",ll,0,LLONG_MAX) {\n      /* Cast to unsigned. */\n        server.slowlog_max_len = (unsigned)ll;\n    } config_set_numerical_field(\n      \"latency-monitor-threshold\",server.latency_monitor_threshold,0,LLONG_MAX){\n    } config_set_numerical_field(\n      \"repl-ping-slave-period\",server.repl_ping_slave_period,1,LLONG_MAX) {\n    } config_set_numerical_field(\n      \"repl-timeout\",server.repl_timeout,1,LLONG_MAX) {\n    } config_set_numerical_field(\n      \"repl-backlog-ttl\",server.repl_backlog_time_limit,0,LLONG_MAX) {\n    } config_set_numerical_field(\n      \"repl-diskless-sync-delay\",server.repl_diskless_sync_delay,0,LLONG_MAX) {\n    } config_set_numerical_field(\n      \"slave-priority\",server.slave_priority,0,LLONG_MAX) {\n    } config_set_numerical_field(\n      \"slave-announce-port\",server.slave_announce_port,0,65535) {\n    } config_set_numerical_field(\n      \"min-slaves-to-write\",server.repl_min_slaves_to_write,0,LLONG_MAX) {\n        refreshGoodSlavesCount();\n    } config_set_numerical_field(\n      \"min-slaves-max-lag\",server.repl_min_slaves_max_lag,0,LLONG_MAX) {\n        refreshGoodSlavesCount();\n    } config_set_numerical_field(\n      \"cluster-node-timeout\",server.cluster_node_timeout,0,LLONG_MAX) {\n    } config_set_numerical_field(\n      \"cluster-migration-barrier\",server.cluster_migration_barrier,0,LLONG_MAX){\n    } config_set_numerical_field(\n      \"cluster-slave-validity-factor\",server.cluster_slave_validity_factor,0,LLONG_MAX) {\n    } config_set_numerical_field(\n      \"hz\",server.hz,0,LLONG_MAX) {\n        /* Hz is more an hint from the user, so we accept values out of range\n         * but cap them to reasonable values. */\n        if (server.hz < CONFIG_MIN_HZ) server.hz = CONFIG_MIN_HZ;\n        if (server.hz > CONFIG_MAX_HZ) server.hz = CONFIG_MAX_HZ;\n    } config_set_numerical_field(\n      \"watchdog-period\",ll,0,LLONG_MAX) {\n        if (ll)\n            enableWatchdog(ll);\n        else\n            disableWatchdog();\n\n    /* Memory fields.\n     * config_set_memory_field(name,var) */\n    } config_set_memory_field(\"maxmemory\",server.maxmemory) {\n        if (server.maxmemory) {\n            if (server.maxmemory < zmalloc_used_memory()) {\n                serverLog(LL_WARNING,\"WARNING: the new maxmemory value set via CONFIG SET is smaller than the current memory usage. This will result in keys eviction and/or inability to accept new write commands depending on the maxmemory-policy.\");\n            }\n            freeMemoryIfNeeded();\n        }\n    } config_set_memory_field(\"repl-backlog-size\",ll) {\n        resizeReplicationBacklog(ll);\n\n    /* Enumeration fields.\n     * config_set_enum_field(name,var,enum_var) */\n    } config_set_enum_field(\n      \"loglevel\",server.verbosity,loglevel_enum) {\n    } config_set_enum_field(\n      \"maxmemory-policy\",server.maxmemory_policy,maxmemory_policy_enum) {\n    } config_set_enum_field(\n      \"appendfsync\",server.aof_fsync,aof_fsync_enum) {\n\n    /* Everyhing else is an error... */\n    } config_set_else {\n        addReplyErrorFormat(c,\"Unsupported CONFIG parameter: %s\",\n            (char*)c->argv[2]->ptr);\n        return;\n    }\n\n    /* On success we just return a generic OK for all the options. */\n    addReply(c,shared.ok);\n    return;\n\nbadfmt: /* Bad format errors */\n    addReplyErrorFormat(c,\"Invalid argument '%s' for CONFIG SET '%s'\",\n            (char*)o->ptr,\n            (char*)c->argv[2]->ptr);\n}\n\n/*-----------------------------------------------------------------------------\n * CONFIG GET implementation\n *----------------------------------------------------------------------------*/\n\n#define config_get_string_field(_name,_var) do { \\\n    if (stringmatch(pattern,_name,1)) { \\\n        addReplyBulkCString(c,_name); \\\n        addReplyBulkCString(c,_var ? _var : \"\"); \\\n        matches++; \\\n    } \\\n} while(0);\n\n#define config_get_bool_field(_name,_var) do { \\\n    if (stringmatch(pattern,_name,1)) { \\\n        addReplyBulkCString(c,_name); \\\n        addReplyBulkCString(c,_var ? \"yes\" : \"no\"); \\\n        matches++; \\\n    } \\\n} while(0);\n\n#define config_get_numerical_field(_name,_var) do { \\\n    if (stringmatch(pattern,_name,1)) { \\\n        ll2string(buf,sizeof(buf),_var); \\\n        addReplyBulkCString(c,_name); \\\n        addReplyBulkCString(c,buf); \\\n        matches++; \\\n    } \\\n} while(0);\n\n#define config_get_enum_field(_name,_var,_enumvar) do { \\\n    if (stringmatch(pattern,_name,1)) { \\\n        addReplyBulkCString(c,_name); \\\n        addReplyBulkCString(c,configEnumGetNameOrUnknown(_enumvar,_var)); \\\n        matches++; \\\n    } \\\n} while(0);\n\nvoid configGetCommand(client *c) {\n    robj *o = c->argv[2];\n    void *replylen = addDeferredMultiBulkLength(c);\n    char *pattern = o->ptr;\n    char buf[128];\n    int matches = 0;\n    serverAssertWithInfo(c,o,sdsEncodedObject(o));\n\n    /* String values */\n    config_get_string_field(\"dbfilename\",server.rdb_filename);\n    config_get_string_field(\"requirepass\",server.requirepass);\n    config_get_string_field(\"masterauth\",server.masterauth);\n    config_get_string_field(\"unixsocket\",server.unixsocket);\n    config_get_string_field(\"logfile\",server.logfile);\n    config_get_string_field(\"pidfile\",server.pidfile);\n    config_get_string_field(\"slave-announce-ip\",server.slave_announce_ip);\n\n    /* Numerical values */\n    config_get_numerical_field(\"maxmemory\",server.maxmemory);\n    config_get_numerical_field(\"maxmemory-samples\",server.maxmemory_samples);\n    config_get_numerical_field(\"timeout\",server.maxidletime);\n    config_get_numerical_field(\"auto-aof-rewrite-percentage\",\n            server.aof_rewrite_perc);\n    config_get_numerical_field(\"auto-aof-rewrite-min-size\",\n            server.aof_rewrite_min_size);\n    config_get_numerical_field(\"hash-max-ziplist-entries\",\n            server.hash_max_ziplist_entries);\n    config_get_numerical_field(\"hash-max-ziplist-value\",\n            server.hash_max_ziplist_value);\n    config_get_numerical_field(\"list-max-ziplist-size\",\n            server.list_max_ziplist_size);\n    config_get_numerical_field(\"list-compress-depth\",\n            server.list_compress_depth);\n    config_get_numerical_field(\"set-max-intset-entries\",\n            server.set_max_intset_entries);\n    config_get_numerical_field(\"zset-max-ziplist-entries\",\n            server.zset_max_ziplist_entries);\n    config_get_numerical_field(\"zset-max-ziplist-value\",\n            server.zset_max_ziplist_value);\n    config_get_numerical_field(\"hll-sparse-max-bytes\",\n            server.hll_sparse_max_bytes);\n    config_get_numerical_field(\"lua-time-limit\",server.lua_time_limit);\n    config_get_numerical_field(\"slowlog-log-slower-than\",\n            server.slowlog_log_slower_than);\n    config_get_numerical_field(\"latency-monitor-threshold\",\n            server.latency_monitor_threshold);\n    config_get_numerical_field(\"slowlog-max-len\",\n            server.slowlog_max_len);\n    config_get_numerical_field(\"port\",server.port);\n    config_get_numerical_field(\"tcp-backlog\",server.tcp_backlog);\n    config_get_numerical_field(\"databases\",server.dbnum);\n    config_get_numerical_field(\"repl-ping-slave-period\",server.repl_ping_slave_period);\n    config_get_numerical_field(\"repl-timeout\",server.repl_timeout);\n    config_get_numerical_field(\"repl-backlog-size\",server.repl_backlog_size);\n    config_get_numerical_field(\"repl-backlog-ttl\",server.repl_backlog_time_limit);\n    config_get_numerical_field(\"maxclients\",server.maxclients);\n    config_get_numerical_field(\"watchdog-period\",server.watchdog_period);\n    config_get_numerical_field(\"slave-priority\",server.slave_priority);\n    config_get_numerical_field(\"slave-announce-port\",server.slave_announce_port);\n    config_get_numerical_field(\"min-slaves-to-write\",server.repl_min_slaves_to_write);\n    config_get_numerical_field(\"min-slaves-max-lag\",server.repl_min_slaves_max_lag);\n    config_get_numerical_field(\"hz\",server.hz);\n    config_get_numerical_field(\"cluster-node-timeout\",server.cluster_node_timeout);\n    config_get_numerical_field(\"cluster-migration-barrier\",server.cluster_migration_barrier);\n    config_get_numerical_field(\"cluster-slave-validity-factor\",server.cluster_slave_validity_factor);\n    config_get_numerical_field(\"repl-diskless-sync-delay\",server.repl_diskless_sync_delay);\n    config_get_numerical_field(\"tcp-keepalive\",server.tcpkeepalive);\n\n    /* Bool (yes/no) values */\n    config_get_bool_field(\"cluster-require-full-coverage\",\n            server.cluster_require_full_coverage);\n    config_get_bool_field(\"no-appendfsync-on-rewrite\",\n            server.aof_no_fsync_on_rewrite);\n    config_get_bool_field(\"slave-serve-stale-data\",\n            server.repl_serve_stale_data);\n    config_get_bool_field(\"slave-read-only\",\n            server.repl_slave_ro);\n    config_get_bool_field(\"stop-writes-on-bgsave-error\",\n            server.stop_writes_on_bgsave_err);\n    config_get_bool_field(\"daemonize\", server.daemonize);\n    config_get_bool_field(\"rdbcompression\", server.rdb_compression);\n    config_get_bool_field(\"rdbchecksum\", server.rdb_checksum);\n    config_get_bool_field(\"activerehashing\", server.activerehashing);\n    config_get_bool_field(\"protected-mode\", server.protected_mode);\n    config_get_bool_field(\"repl-disable-tcp-nodelay\",\n            server.repl_disable_tcp_nodelay);\n    config_get_bool_field(\"repl-diskless-sync\",\n            server.repl_diskless_sync);\n    config_get_bool_field(\"aof-rewrite-incremental-fsync\",\n            server.aof_rewrite_incremental_fsync);\n    config_get_bool_field(\"aof-load-truncated\",\n            server.aof_load_truncated);\n\n    /* Enum values */\n    config_get_enum_field(\"maxmemory-policy\",\n            server.maxmemory_policy,maxmemory_policy_enum);\n    config_get_enum_field(\"loglevel\",\n            server.verbosity,loglevel_enum);\n    config_get_enum_field(\"supervised\",\n            server.supervised_mode,supervised_mode_enum);\n    config_get_enum_field(\"appendfsync\",\n            server.aof_fsync,aof_fsync_enum);\n    config_get_enum_field(\"syslog-facility\",\n            server.syslog_facility,syslog_facility_enum);\n\n    /* Everything we can't handle with macros follows. */\n\n    if (stringmatch(pattern,\"appendonly\",1)) {\n        addReplyBulkCString(c,\"appendonly\");\n        addReplyBulkCString(c,server.aof_state == AOF_OFF ? \"no\" : \"yes\");\n        matches++;\n    }\n    if (stringmatch(pattern,\"dir\",1)) {\n        char buf[1024];\n\n        if (getcwd(buf,sizeof(buf)) == NULL)\n            buf[0] = '\\0';\n\n        addReplyBulkCString(c,\"dir\");\n        addReplyBulkCString(c,buf);\n        matches++;\n    }\n    if (stringmatch(pattern,\"save\",1)) {\n        sds buf = sdsempty();\n        int j;\n\n        for (j = 0; j < server.saveparamslen; j++) {\n            buf = sdscatprintf(buf,\"%jd %d\",\n                    (intmax_t)server.saveparams[j].seconds,\n                    server.saveparams[j].changes);\n            if (j != server.saveparamslen-1)\n                buf = sdscatlen(buf,\" \",1);\n        }\n        addReplyBulkCString(c,\"save\");\n        addReplyBulkCString(c,buf);\n        sdsfree(buf);\n        matches++;\n    }\n    if (stringmatch(pattern,\"client-output-buffer-limit\",1)) {\n        sds buf = sdsempty();\n        int j;\n\n        for (j = 0; j < CLIENT_TYPE_OBUF_COUNT; j++) {\n            buf = sdscatprintf(buf,\"%s %llu %llu %ld\",\n                    getClientTypeName(j),\n                    server.client_obuf_limits[j].hard_limit_bytes,\n                    server.client_obuf_limits[j].soft_limit_bytes,\n                    (long) server.client_obuf_limits[j].soft_limit_seconds);\n            if (j != CLIENT_TYPE_OBUF_COUNT-1)\n                buf = sdscatlen(buf,\" \",1);\n        }\n        addReplyBulkCString(c,\"client-output-buffer-limit\");\n        addReplyBulkCString(c,buf);\n        sdsfree(buf);\n        matches++;\n    }\n    if (stringmatch(pattern,\"unixsocketperm\",1)) {\n        char buf[32];\n        snprintf(buf,sizeof(buf),\"%o\",server.unixsocketperm);\n        addReplyBulkCString(c,\"unixsocketperm\");\n        addReplyBulkCString(c,buf);\n        matches++;\n    }\n    if (stringmatch(pattern,\"slaveof\",1)) {\n        char buf[256];\n\n        addReplyBulkCString(c,\"slaveof\");\n        if (server.masterhost)\n            snprintf(buf,sizeof(buf),\"%s %d\",\n                server.masterhost, server.masterport);\n        else\n            buf[0] = '\\0';\n        addReplyBulkCString(c,buf);\n        matches++;\n    }\n    if (stringmatch(pattern,\"notify-keyspace-events\",1)) {\n        robj *flagsobj = createObject(OBJ_STRING,\n            keyspaceEventsFlagsToString(server.notify_keyspace_events));\n\n        addReplyBulkCString(c,\"notify-keyspace-events\");\n        addReplyBulk(c,flagsobj);\n        decrRefCount(flagsobj);\n        matches++;\n    }\n    if (stringmatch(pattern,\"bind\",1)) {\n        sds aux = sdsjoin(server.bindaddr,server.bindaddr_count,\" \");\n\n        addReplyBulkCString(c,\"bind\");\n        addReplyBulkCString(c,aux);\n        sdsfree(aux);\n        matches++;\n    }\n    setDeferredMultiBulkLength(c,replylen,matches*2);\n}\n\n/*-----------------------------------------------------------------------------\n * CONFIG REWRITE implementation\n *----------------------------------------------------------------------------*/\n\n#define REDIS_CONFIG_REWRITE_SIGNATURE \"# Generated by CONFIG REWRITE\"\n\n/* We use the following dictionary type to store where a configuration\n * option is mentioned in the old configuration file, so it's\n * like \"maxmemory\" -> list of line numbers (first line is zero). */\nunsigned int dictSdsCaseHash(const void *key);\nint dictSdsKeyCaseCompare(void *privdata, const void *key1, const void *key2);\nvoid dictSdsDestructor(void *privdata, void *val);\nvoid dictListDestructor(void *privdata, void *val);\n\n/* Sentinel config rewriting is implemented inside sentinel.c by\n * rewriteConfigSentinelOption(). */\nvoid rewriteConfigSentinelOption(struct rewriteConfigState *state);\n\ndictType optionToLineDictType = {\n    dictSdsCaseHash,            /* hash function */\n    NULL,                       /* key dup */\n    NULL,                       /* val dup */\n    dictSdsKeyCaseCompare,      /* key compare */\n    dictSdsDestructor,          /* key destructor */\n    dictListDestructor          /* val destructor */\n};\n\ndictType optionSetDictType = {\n    dictSdsCaseHash,            /* hash function */\n    NULL,                       /* key dup */\n    NULL,                       /* val dup */\n    dictSdsKeyCaseCompare,      /* key compare */\n    dictSdsDestructor,          /* key destructor */\n    NULL                        /* val destructor */\n};\n\n/* The config rewrite state. */\nstruct rewriteConfigState {\n    dict *option_to_line; /* Option -> list of config file lines map */\n    dict *rewritten;      /* Dictionary of already processed options */\n    int numlines;         /* Number of lines in current config */\n    sds *lines;           /* Current lines as an array of sds strings */\n    int has_tail;         /* True if we already added directives that were\n                             not present in the original config file. */\n};\n\n/* Append the new line to the current configuration state. */\nvoid rewriteConfigAppendLine(struct rewriteConfigState *state, sds line) {\n    state->lines = zrealloc(state->lines, sizeof(char*) * (state->numlines+1));\n    state->lines[state->numlines++] = line;\n}\n\n/* Populate the option -> list of line numbers map. */\nvoid rewriteConfigAddLineNumberToOption(struct rewriteConfigState *state, sds option, int linenum) {\n    list *l = dictFetchValue(state->option_to_line,option);\n\n    if (l == NULL) {\n        l = listCreate();\n        dictAdd(state->option_to_line,sdsdup(option),l);\n    }\n    listAddNodeTail(l,(void*)(long)linenum);\n}\n\n/* Add the specified option to the set of processed options.\n * This is useful as only unused lines of processed options will be blanked\n * in the config file, while options the rewrite process does not understand\n * remain untouched. */\nvoid rewriteConfigMarkAsProcessed(struct rewriteConfigState *state, const char *option) {\n    sds opt = sdsnew(option);\n\n    if (dictAdd(state->rewritten,opt,NULL) != DICT_OK) sdsfree(opt);\n}\n\n/* Read the old file, split it into lines to populate a newly created\n * config rewrite state, and return it to the caller.\n *\n * If it is impossible to read the old file, NULL is returned.\n * If the old file does not exist at all, an empty state is returned. */\nstruct rewriteConfigState *rewriteConfigReadOldFile(char *path) {\n    FILE *fp = fopen(path,\"r\");\n    struct rewriteConfigState *state = zmalloc(sizeof(*state));\n    char buf[CONFIG_MAX_LINE+1];\n    int linenum = -1;\n\n    if (fp == NULL && errno != ENOENT) return NULL;\n\n    state->option_to_line = dictCreate(&optionToLineDictType,NULL);\n    state->rewritten = dictCreate(&optionSetDictType,NULL);\n    state->numlines = 0;\n    state->lines = NULL;\n    state->has_tail = 0;\n    if (fp == NULL) return state;\n\n    /* Read the old file line by line, populate the state. */\n    while(fgets(buf,CONFIG_MAX_LINE+1,fp) != NULL) {\n        int argc;\n        sds *argv;\n        sds line = sdstrim(sdsnew(buf),\"\\r\\n\\t \");\n\n        linenum++; /* Zero based, so we init at -1 */\n\n        /* Handle comments and empty lines. */\n        if (line[0] == '#' || line[0] == '\\0') {\n            if (!state->has_tail && !strcmp(line,REDIS_CONFIG_REWRITE_SIGNATURE))\n                state->has_tail = 1;\n            rewriteConfigAppendLine(state,line);\n            continue;\n        }\n\n        /* Not a comment, split into arguments. */\n        argv = sdssplitargs(line,&argc);\n        if (argv == NULL) {\n            /* Apparently the line is unparsable for some reason, for\n             * instance it may have unbalanced quotes. Load it as a\n             * comment. */\n            sds aux = sdsnew(\"# ??? \");\n            aux = sdscatsds(aux,line);\n            sdsfree(line);\n            rewriteConfigAppendLine(state,aux);\n            continue;\n        }\n\n        sdstolower(argv[0]); /* We only want lowercase config directives. */\n\n        /* Now we populate the state according to the content of this line.\n         * Append the line and populate the option -> line numbers map. */\n        rewriteConfigAppendLine(state,line);\n        rewriteConfigAddLineNumberToOption(state,argv[0],linenum);\n\n        sdsfreesplitres(argv,argc);\n    }\n    fclose(fp);\n    return state;\n}\n\n/* Rewrite the specified configuration option with the new \"line\".\n * It progressively uses lines of the file that were already used for the same\n * configuration option in the old version of the file, removing that line from\n * the map of options -> line numbers.\n *\n * If there are lines associated with a given configuration option and\n * \"force\" is non-zero, the line is appended to the configuration file.\n * Usually \"force\" is true when an option has not its default value, so it\n * must be rewritten even if not present previously.\n *\n * The first time a line is appended into a configuration file, a comment\n * is added to show that starting from that point the config file was generated\n * by CONFIG REWRITE.\n *\n * \"line\" is either used, or freed, so the caller does not need to free it\n * in any way. */\nvoid rewriteConfigRewriteLine(struct rewriteConfigState *state, const char *option, sds line, int force) {\n    sds o = sdsnew(option);\n    list *l = dictFetchValue(state->option_to_line,o);\n\n    rewriteConfigMarkAsProcessed(state,option);\n\n    if (!l && !force) {\n        /* Option not used previously, and we are not forced to use it. */\n        sdsfree(line);\n        sdsfree(o);\n        return;\n    }\n\n    if (l) {\n        listNode *ln = listFirst(l);\n        int linenum = (long) ln->value;\n\n        /* There are still lines in the old configuration file we can reuse\n         * for this option. Replace the line with the new one. */\n        listDelNode(l,ln);\n        if (listLength(l) == 0) dictDelete(state->option_to_line,o);\n        sdsfree(state->lines[linenum]);\n        state->lines[linenum] = line;\n    } else {\n        /* Append a new line. */\n        if (!state->has_tail) {\n            rewriteConfigAppendLine(state,\n                sdsnew(REDIS_CONFIG_REWRITE_SIGNATURE));\n            state->has_tail = 1;\n        }\n        rewriteConfigAppendLine(state,line);\n    }\n    sdsfree(o);\n}\n\n/* Write the long long 'bytes' value as a string in a way that is parsable\n * inside redis.conf. If possible uses the GB, MB, KB notation. */\nint rewriteConfigFormatMemory(char *buf, size_t len, long long bytes) {\n    int gb = 1024*1024*1024;\n    int mb = 1024*1024;\n    int kb = 1024;\n\n    if (bytes && (bytes % gb) == 0) {\n        return snprintf(buf,len,\"%lldgb\",bytes/gb);\n    } else if (bytes && (bytes % mb) == 0) {\n        return snprintf(buf,len,\"%lldmb\",bytes/mb);\n    } else if (bytes && (bytes % kb) == 0) {\n        return snprintf(buf,len,\"%lldkb\",bytes/kb);\n    } else {\n        return snprintf(buf,len,\"%lld\",bytes);\n    }\n}\n\n/* Rewrite a simple \"option-name <bytes>\" configuration option. */\nvoid rewriteConfigBytesOption(struct rewriteConfigState *state, char *option, long long value, long long defvalue) {\n    char buf[64];\n    int force = value != defvalue;\n    sds line;\n\n    rewriteConfigFormatMemory(buf,sizeof(buf),value);\n    line = sdscatprintf(sdsempty(),\"%s %s\",option,buf);\n    rewriteConfigRewriteLine(state,option,line,force);\n}\n\n/* Rewrite a yes/no option. */\nvoid rewriteConfigYesNoOption(struct rewriteConfigState *state, char *option, int value, int defvalue) {\n    int force = value != defvalue;\n    sds line = sdscatprintf(sdsempty(),\"%s %s\",option,\n        value ? \"yes\" : \"no\");\n\n    rewriteConfigRewriteLine(state,option,line,force);\n}\n\n/* Rewrite a string option. */\nvoid rewriteConfigStringOption(struct rewriteConfigState *state, char *option, char *value, char *defvalue) {\n    int force = 1;\n    sds line;\n\n    /* String options set to NULL need to be not present at all in the\n     * configuration file to be set to NULL again at the next reboot. */\n    if (value == NULL) {\n        rewriteConfigMarkAsProcessed(state,option);\n        return;\n    }\n\n    /* Set force to zero if the value is set to its default. */\n    if (defvalue && strcmp(value,defvalue) == 0) force = 0;\n\n    line = sdsnew(option);\n    line = sdscatlen(line, \" \", 1);\n    line = sdscatrepr(line, value, strlen(value));\n\n    rewriteConfigRewriteLine(state,option,line,force);\n}\n\n/* Rewrite a numerical (long long range) option. */\nvoid rewriteConfigNumericalOption(struct rewriteConfigState *state, char *option, long long value, long long defvalue) {\n    int force = value != defvalue;\n    sds line = sdscatprintf(sdsempty(),\"%s %lld\",option,value);\n\n    rewriteConfigRewriteLine(state,option,line,force);\n}\n\n/* Rewrite a octal option. */\nvoid rewriteConfigOctalOption(struct rewriteConfigState *state, char *option, int value, int defvalue) {\n    int force = value != defvalue;\n    sds line = sdscatprintf(sdsempty(),\"%s %o\",option,value);\n\n    rewriteConfigRewriteLine(state,option,line,force);\n}\n\n/* Rewrite an enumeration option. It takes as usually state and option name,\n * and in addition the enumeration array and the default value for the\n * option. */\nvoid rewriteConfigEnumOption(struct rewriteConfigState *state, char *option, int value, configEnum *ce, int defval) {\n    sds line;\n    const char *name = configEnumGetNameOrUnknown(ce,value);\n    int force = value != defval;\n\n    line = sdscatprintf(sdsempty(),\"%s %s\",option,name);\n    rewriteConfigRewriteLine(state,option,line,force);\n}\n\n/* Rewrite the syslog-facility option. */\nvoid rewriteConfigSyslogfacilityOption(struct rewriteConfigState *state) {\n    int value = server.syslog_facility;\n    int force = value != LOG_LOCAL0;\n    const char *name = NULL, *option = \"syslog-facility\";\n    sds line;\n\n    name = configEnumGetNameOrUnknown(syslog_facility_enum,value);\n    line = sdscatprintf(sdsempty(),\"%s %s\",option,name);\n    rewriteConfigRewriteLine(state,option,line,force);\n}\n\n/* Rewrite the save option. */\nvoid rewriteConfigSaveOption(struct rewriteConfigState *state) {\n    int j;\n    sds line;\n\n    /* Note that if there are no save parameters at all, all the current\n     * config line with \"save\" will be detected as orphaned and deleted,\n     * resulting into no RDB persistence as expected. */\n    for (j = 0; j < server.saveparamslen; j++) {\n        line = sdscatprintf(sdsempty(),\"save %ld %d\",\n            (long) server.saveparams[j].seconds, server.saveparams[j].changes);\n        rewriteConfigRewriteLine(state,\"save\",line,1);\n    }\n    /* Mark \"save\" as processed in case server.saveparamslen is zero. */\n    rewriteConfigMarkAsProcessed(state,\"save\");\n}\n\n/* Rewrite the dir option, always using absolute paths.*/\nvoid rewriteConfigDirOption(struct rewriteConfigState *state) {\n    char cwd[1024];\n\n    if (getcwd(cwd,sizeof(cwd)) == NULL) {\n        rewriteConfigMarkAsProcessed(state,\"dir\");\n        return; /* no rewrite on error. */\n    }\n    rewriteConfigStringOption(state,\"dir\",cwd,NULL);\n}\n\n/* Rewrite the slaveof option. */\nvoid rewriteConfigSlaveofOption(struct rewriteConfigState *state) {\n    char *option = \"slaveof\";\n    sds line;\n\n    /* If this is a master, we want all the slaveof config options\n     * in the file to be removed. Note that if this is a cluster instance\n     * we don't want a slaveof directive inside redis.conf. */\n    if (server.cluster_enabled || server.masterhost == NULL) {\n        rewriteConfigMarkAsProcessed(state,\"slaveof\");\n        return;\n    }\n    line = sdscatprintf(sdsempty(),\"%s %s %d\", option,\n        server.masterhost, server.masterport);\n    rewriteConfigRewriteLine(state,option,line,1);\n}\n\n/* Rewrite the notify-keyspace-events option. */\nvoid rewriteConfigNotifykeyspaceeventsOption(struct rewriteConfigState *state) {\n    int force = server.notify_keyspace_events != 0;\n    char *option = \"notify-keyspace-events\";\n    sds line, flags;\n\n    flags = keyspaceEventsFlagsToString(server.notify_keyspace_events);\n    line = sdsnew(option);\n    line = sdscatlen(line, \" \", 1);\n    line = sdscatrepr(line, flags, sdslen(flags));\n    sdsfree(flags);\n    rewriteConfigRewriteLine(state,option,line,force);\n}\n\n/* Rewrite the client-output-buffer-limit option. */\nvoid rewriteConfigClientoutputbufferlimitOption(struct rewriteConfigState *state) {\n    int j;\n    char *option = \"client-output-buffer-limit\";\n\n    for (j = 0; j < CLIENT_TYPE_OBUF_COUNT; j++) {\n        int force = (server.client_obuf_limits[j].hard_limit_bytes !=\n                    clientBufferLimitsDefaults[j].hard_limit_bytes) ||\n                    (server.client_obuf_limits[j].soft_limit_bytes !=\n                    clientBufferLimitsDefaults[j].soft_limit_bytes) ||\n                    (server.client_obuf_limits[j].soft_limit_seconds !=\n                    clientBufferLimitsDefaults[j].soft_limit_seconds);\n        sds line;\n        char hard[64], soft[64];\n\n        rewriteConfigFormatMemory(hard,sizeof(hard),\n                server.client_obuf_limits[j].hard_limit_bytes);\n        rewriteConfigFormatMemory(soft,sizeof(soft),\n                server.client_obuf_limits[j].soft_limit_bytes);\n\n        line = sdscatprintf(sdsempty(),\"%s %s %s %s %ld\",\n                option, getClientTypeName(j), hard, soft,\n                (long) server.client_obuf_limits[j].soft_limit_seconds);\n        rewriteConfigRewriteLine(state,option,line,force);\n    }\n}\n\n/* Rewrite the bind option. */\nvoid rewriteConfigBindOption(struct rewriteConfigState *state) {\n    int force = 1;\n    sds line, addresses;\n    char *option = \"bind\";\n\n    /* Nothing to rewrite if we don't have bind addresses. */\n    if (server.bindaddr_count == 0) {\n        rewriteConfigMarkAsProcessed(state,option);\n        return;\n    }\n\n    /* Rewrite as bind <addr1> <addr2> ... <addrN> */\n    addresses = sdsjoin(server.bindaddr,server.bindaddr_count,\" \");\n    line = sdsnew(option);\n    line = sdscatlen(line, \" \", 1);\n    line = sdscatsds(line, addresses);\n    sdsfree(addresses);\n\n    rewriteConfigRewriteLine(state,option,line,force);\n}\n\n/* Glue together the configuration lines in the current configuration\n * rewrite state into a single string, stripping multiple empty lines. */\nsds rewriteConfigGetContentFromState(struct rewriteConfigState *state) {\n    sds content = sdsempty();\n    int j, was_empty = 0;\n\n    for (j = 0; j < state->numlines; j++) {\n        /* Every cluster of empty lines is turned into a single empty line. */\n        if (sdslen(state->lines[j]) == 0) {\n            if (was_empty) continue;\n            was_empty = 1;\n        } else {\n            was_empty = 0;\n        }\n        content = sdscatsds(content,state->lines[j]);\n        content = sdscatlen(content,\"\\n\",1);\n    }\n    return content;\n}\n\n/* Free the configuration rewrite state. */\nvoid rewriteConfigReleaseState(struct rewriteConfigState *state) {\n    sdsfreesplitres(state->lines,state->numlines);\n    dictRelease(state->option_to_line);\n    dictRelease(state->rewritten);\n    zfree(state);\n}\n\n/* At the end of the rewrite process the state contains the remaining\n * map between \"option name\" => \"lines in the original config file\".\n * Lines used by the rewrite process were removed by the function\n * rewriteConfigRewriteLine(), all the other lines are \"orphaned\" and\n * should be replaced by empty lines.\n *\n * This function does just this, iterating all the option names and\n * blanking all the lines still associated. */\nvoid rewriteConfigRemoveOrphaned(struct rewriteConfigState *state) {\n    dictIterator *di = dictGetIterator(state->option_to_line);\n    dictEntry *de;\n\n    while((de = dictNext(di)) != NULL) {\n        list *l = dictGetVal(de);\n        sds option = dictGetKey(de);\n\n        /* Don't blank lines about options the rewrite process\n         * don't understand. */\n        if (dictFind(state->rewritten,option) == NULL) {\n            serverLog(LL_DEBUG,\"Not rewritten option: %s\", option);\n            continue;\n        }\n\n        while(listLength(l)) {\n            listNode *ln = listFirst(l);\n            int linenum = (long) ln->value;\n\n            sdsfree(state->lines[linenum]);\n            state->lines[linenum] = sdsempty();\n            listDelNode(l,ln);\n        }\n    }\n    dictReleaseIterator(di);\n}\n\n/* This function overwrites the old configuration file with the new content.\n *\n * 1) The old file length is obtained.\n * 2) If the new content is smaller, padding is added.\n * 3) A single write(2) call is used to replace the content of the file.\n * 4) Later the file is truncated to the length of the new content.\n *\n * This way we are sure the file is left in a consistent state even if the\n * process is stopped between any of the four operations.\n *\n * The function returns 0 on success, otherwise -1 is returned and errno\n * set accordingly. */\nint rewriteConfigOverwriteFile(char *configfile, sds content) {\n    int retval = 0;\n    int fd = open(configfile,O_RDWR|O_CREAT,0644);\n    int content_size = sdslen(content), padding = 0;\n    struct stat sb;\n    sds content_padded;\n\n    /* 1) Open the old file (or create a new one if it does not\n     *    exist), get the size. */\n    if (fd == -1) return -1; /* errno set by open(). */\n    if (fstat(fd,&sb) == -1) {\n        close(fd);\n        return -1; /* errno set by fstat(). */\n    }\n\n    /* 2) Pad the content at least match the old file size. */\n    content_padded = sdsdup(content);\n    if (content_size < sb.st_size) {\n        /* If the old file was bigger, pad the content with\n         * a newline plus as many \"#\" chars as required. */\n        padding = sb.st_size - content_size;\n        content_padded = sdsgrowzero(content_padded,sb.st_size);\n        content_padded[content_size] = '\\n';\n        memset(content_padded+content_size+1,'#',padding-1);\n    }\n\n    /* 3) Write the new content using a single write(2). */\n    if (write(fd,content_padded,strlen(content_padded)) == -1) {\n        retval = -1;\n        goto cleanup;\n    }\n\n    /* 4) Truncate the file to the right length if we used padding. */\n    if (padding) {\n        if (ftruncate(fd,content_size) == -1) {\n            /* Non critical error... */\n        }\n    }\n\ncleanup:\n    sdsfree(content_padded);\n    close(fd);\n    return retval;\n}\n\n/* Rewrite the configuration file at \"path\".\n * If the configuration file already exists, we try at best to retain comments\n * and overall structure.\n *\n * Configuration parameters that are at their default value, unless already\n * explicitly included in the old configuration file, are not rewritten.\n *\n * On error -1 is returned and errno is set accordingly, otherwise 0. */\nint rewriteConfig(char *path) {\n    struct rewriteConfigState *state;\n    sds newcontent;\n    int retval;\n\n    /* Step 1: read the old config into our rewrite state. */\n    if ((state = rewriteConfigReadOldFile(path)) == NULL) return -1;\n\n    /* Step 2: rewrite every single option, replacing or appending it inside\n     * the rewrite state. */\n\n    rewriteConfigYesNoOption(state,\"daemonize\",server.daemonize,0);\n    rewriteConfigStringOption(state,\"pidfile\",server.pidfile,CONFIG_DEFAULT_PID_FILE);\n    rewriteConfigNumericalOption(state,\"port\",server.port,CONFIG_DEFAULT_SERVER_PORT);\n    rewriteConfigNumericalOption(state,\"tcp-backlog\",server.tcp_backlog,CONFIG_DEFAULT_TCP_BACKLOG);\n    rewriteConfigBindOption(state);\n    rewriteConfigStringOption(state,\"unixsocket\",server.unixsocket,NULL);\n    rewriteConfigOctalOption(state,\"unixsocketperm\",server.unixsocketperm,CONFIG_DEFAULT_UNIX_SOCKET_PERM);\n    rewriteConfigNumericalOption(state,\"timeout\",server.maxidletime,CONFIG_DEFAULT_CLIENT_TIMEOUT);\n    rewriteConfigNumericalOption(state,\"tcp-keepalive\",server.tcpkeepalive,CONFIG_DEFAULT_TCP_KEEPALIVE);\n    rewriteConfigNumericalOption(state,\"slave-announce-port\",server.slave_announce_port,CONFIG_DEFAULT_SLAVE_ANNOUNCE_PORT);\n    rewriteConfigEnumOption(state,\"loglevel\",server.verbosity,loglevel_enum,CONFIG_DEFAULT_VERBOSITY);\n    rewriteConfigStringOption(state,\"logfile\",server.logfile,CONFIG_DEFAULT_LOGFILE);\n    rewriteConfigYesNoOption(state,\"syslog-enabled\",server.syslog_enabled,CONFIG_DEFAULT_SYSLOG_ENABLED);\n    rewriteConfigStringOption(state,\"syslog-ident\",server.syslog_ident,CONFIG_DEFAULT_SYSLOG_IDENT);\n    rewriteConfigSyslogfacilityOption(state);\n    rewriteConfigSaveOption(state);\n    rewriteConfigNumericalOption(state,\"databases\",server.dbnum,CONFIG_DEFAULT_DBNUM);\n    rewriteConfigYesNoOption(state,\"stop-writes-on-bgsave-error\",server.stop_writes_on_bgsave_err,CONFIG_DEFAULT_STOP_WRITES_ON_BGSAVE_ERROR);\n    rewriteConfigYesNoOption(state,\"rdbcompression\",server.rdb_compression,CONFIG_DEFAULT_RDB_COMPRESSION);\n    rewriteConfigYesNoOption(state,\"rdbchecksum\",server.rdb_checksum,CONFIG_DEFAULT_RDB_CHECKSUM);\n    rewriteConfigStringOption(state,\"dbfilename\",server.rdb_filename,CONFIG_DEFAULT_RDB_FILENAME);\n    rewriteConfigDirOption(state);\n    rewriteConfigSlaveofOption(state);\n    rewriteConfigStringOption(state,\"slave-announce-ip\",server.slave_announce_ip,CONFIG_DEFAULT_SLAVE_ANNOUNCE_IP);\n    rewriteConfigStringOption(state,\"masterauth\",server.masterauth,NULL);\n    rewriteConfigYesNoOption(state,\"slave-serve-stale-data\",server.repl_serve_stale_data,CONFIG_DEFAULT_SLAVE_SERVE_STALE_DATA);\n    rewriteConfigYesNoOption(state,\"slave-read-only\",server.repl_slave_ro,CONFIG_DEFAULT_SLAVE_READ_ONLY);\n    rewriteConfigNumericalOption(state,\"repl-ping-slave-period\",server.repl_ping_slave_period,CONFIG_DEFAULT_REPL_PING_SLAVE_PERIOD);\n    rewriteConfigNumericalOption(state,\"repl-timeout\",server.repl_timeout,CONFIG_DEFAULT_REPL_TIMEOUT);\n    rewriteConfigBytesOption(state,\"repl-backlog-size\",server.repl_backlog_size,CONFIG_DEFAULT_REPL_BACKLOG_SIZE);\n    rewriteConfigBytesOption(state,\"repl-backlog-ttl\",server.repl_backlog_time_limit,CONFIG_DEFAULT_REPL_BACKLOG_TIME_LIMIT);\n    rewriteConfigYesNoOption(state,\"repl-disable-tcp-nodelay\",server.repl_disable_tcp_nodelay,CONFIG_DEFAULT_REPL_DISABLE_TCP_NODELAY);\n    rewriteConfigYesNoOption(state,\"repl-diskless-sync\",server.repl_diskless_sync,CONFIG_DEFAULT_REPL_DISKLESS_SYNC);\n    rewriteConfigNumericalOption(state,\"repl-diskless-sync-delay\",server.repl_diskless_sync_delay,CONFIG_DEFAULT_REPL_DISKLESS_SYNC_DELAY);\n    rewriteConfigNumericalOption(state,\"slave-priority\",server.slave_priority,CONFIG_DEFAULT_SLAVE_PRIORITY);\n    rewriteConfigNumericalOption(state,\"min-slaves-to-write\",server.repl_min_slaves_to_write,CONFIG_DEFAULT_MIN_SLAVES_TO_WRITE);\n    rewriteConfigNumericalOption(state,\"min-slaves-max-lag\",server.repl_min_slaves_max_lag,CONFIG_DEFAULT_MIN_SLAVES_MAX_LAG);\n    rewriteConfigStringOption(state,\"requirepass\",server.requirepass,NULL);\n    rewriteConfigNumericalOption(state,\"maxclients\",server.maxclients,CONFIG_DEFAULT_MAX_CLIENTS);\n    rewriteConfigBytesOption(state,\"maxmemory\",server.maxmemory,CONFIG_DEFAULT_MAXMEMORY);\n    rewriteConfigEnumOption(state,\"maxmemory-policy\",server.maxmemory_policy,maxmemory_policy_enum,CONFIG_DEFAULT_MAXMEMORY_POLICY);\n    rewriteConfigNumericalOption(state,\"maxmemory-samples\",server.maxmemory_samples,CONFIG_DEFAULT_MAXMEMORY_SAMPLES);\n    rewriteConfigYesNoOption(state,\"appendonly\",server.aof_state != AOF_OFF,0);\n    rewriteConfigStringOption(state,\"appendfilename\",server.aof_filename,CONFIG_DEFAULT_AOF_FILENAME);\n    rewriteConfigEnumOption(state,\"appendfsync\",server.aof_fsync,aof_fsync_enum,CONFIG_DEFAULT_AOF_FSYNC);\n    rewriteConfigYesNoOption(state,\"no-appendfsync-on-rewrite\",server.aof_no_fsync_on_rewrite,CONFIG_DEFAULT_AOF_NO_FSYNC_ON_REWRITE);\n    rewriteConfigNumericalOption(state,\"auto-aof-rewrite-percentage\",server.aof_rewrite_perc,AOF_REWRITE_PERC);\n    rewriteConfigBytesOption(state,\"auto-aof-rewrite-min-size\",server.aof_rewrite_min_size,AOF_REWRITE_MIN_SIZE);\n    rewriteConfigNumericalOption(state,\"lua-time-limit\",server.lua_time_limit,LUA_SCRIPT_TIME_LIMIT);\n    rewriteConfigYesNoOption(state,\"cluster-enabled\",server.cluster_enabled,0);\n    rewriteConfigStringOption(state,\"cluster-config-file\",server.cluster_configfile,CONFIG_DEFAULT_CLUSTER_CONFIG_FILE);\n    rewriteConfigYesNoOption(state,\"cluster-require-full-coverage\",server.cluster_require_full_coverage,CLUSTER_DEFAULT_REQUIRE_FULL_COVERAGE);\n    rewriteConfigNumericalOption(state,\"cluster-node-timeout\",server.cluster_node_timeout,CLUSTER_DEFAULT_NODE_TIMEOUT);\n    rewriteConfigNumericalOption(state,\"cluster-migration-barrier\",server.cluster_migration_barrier,CLUSTER_DEFAULT_MIGRATION_BARRIER);\n    rewriteConfigNumericalOption(state,\"cluster-slave-validity-factor\",server.cluster_slave_validity_factor,CLUSTER_DEFAULT_SLAVE_VALIDITY);\n    rewriteConfigNumericalOption(state,\"slowlog-log-slower-than\",server.slowlog_log_slower_than,CONFIG_DEFAULT_SLOWLOG_LOG_SLOWER_THAN);\n    rewriteConfigNumericalOption(state,\"latency-monitor-threshold\",server.latency_monitor_threshold,CONFIG_DEFAULT_LATENCY_MONITOR_THRESHOLD);\n    rewriteConfigNumericalOption(state,\"slowlog-max-len\",server.slowlog_max_len,CONFIG_DEFAULT_SLOWLOG_MAX_LEN);\n    rewriteConfigNotifykeyspaceeventsOption(state);\n    rewriteConfigNumericalOption(state,\"hash-max-ziplist-entries\",server.hash_max_ziplist_entries,OBJ_HASH_MAX_ZIPLIST_ENTRIES);\n    rewriteConfigNumericalOption(state,\"hash-max-ziplist-value\",server.hash_max_ziplist_value,OBJ_HASH_MAX_ZIPLIST_VALUE);\n    rewriteConfigNumericalOption(state,\"list-max-ziplist-size\",server.list_max_ziplist_size,OBJ_LIST_MAX_ZIPLIST_SIZE);\n    rewriteConfigNumericalOption(state,\"list-compress-depth\",server.list_compress_depth,OBJ_LIST_COMPRESS_DEPTH);\n    rewriteConfigNumericalOption(state,\"set-max-intset-entries\",server.set_max_intset_entries,OBJ_SET_MAX_INTSET_ENTRIES);\n    rewriteConfigNumericalOption(state,\"zset-max-ziplist-entries\",server.zset_max_ziplist_entries,OBJ_ZSET_MAX_ZIPLIST_ENTRIES);\n    rewriteConfigNumericalOption(state,\"zset-max-ziplist-value\",server.zset_max_ziplist_value,OBJ_ZSET_MAX_ZIPLIST_VALUE);\n    rewriteConfigNumericalOption(state,\"hll-sparse-max-bytes\",server.hll_sparse_max_bytes,CONFIG_DEFAULT_HLL_SPARSE_MAX_BYTES);\n    rewriteConfigYesNoOption(state,\"activerehashing\",server.activerehashing,CONFIG_DEFAULT_ACTIVE_REHASHING);\n    rewriteConfigYesNoOption(state,\"protected-mode\",server.protected_mode,CONFIG_DEFAULT_PROTECTED_MODE);\n    rewriteConfigClientoutputbufferlimitOption(state);\n    rewriteConfigNumericalOption(state,\"hz\",server.hz,CONFIG_DEFAULT_HZ);\n    rewriteConfigYesNoOption(state,\"aof-rewrite-incremental-fsync\",server.aof_rewrite_incremental_fsync,CONFIG_DEFAULT_AOF_REWRITE_INCREMENTAL_FSYNC);\n    rewriteConfigYesNoOption(state,\"aof-load-truncated\",server.aof_load_truncated,CONFIG_DEFAULT_AOF_LOAD_TRUNCATED);\n    rewriteConfigEnumOption(state,\"supervised\",server.supervised_mode,supervised_mode_enum,SUPERVISED_NONE);\n\n    /* Rewrite Sentinel config if in Sentinel mode. */\n    if (server.sentinel_mode) rewriteConfigSentinelOption(state);\n\n    /* Step 3: remove all the orphaned lines in the old file, that is, lines\n     * that were used by a config option and are no longer used, like in case\n     * of multiple \"save\" options or duplicated options. */\n    rewriteConfigRemoveOrphaned(state);\n\n    /* Step 4: generate a new configuration file from the modified state\n     * and write it into the original file. */\n    newcontent = rewriteConfigGetContentFromState(state);\n    retval = rewriteConfigOverwriteFile(server.configfile,newcontent);\n\n    sdsfree(newcontent);\n    rewriteConfigReleaseState(state);\n    return retval;\n}\n\n/*-----------------------------------------------------------------------------\n * CONFIG command entry point\n *----------------------------------------------------------------------------*/\n\nvoid configCommand(client *c) {\n    /* Only allow CONFIG GET while loading. */\n    if (server.loading && strcasecmp(c->argv[1]->ptr,\"get\")) {\n        addReplyError(c,\"Only CONFIG GET is allowed during loading\");\n        return;\n    }\n\n    if (!strcasecmp(c->argv[1]->ptr,\"set\")) {\n        if (c->argc != 4) goto badarity;\n        configSetCommand(c);\n    } else if (!strcasecmp(c->argv[1]->ptr,\"get\")) {\n        if (c->argc != 3) goto badarity;\n        configGetCommand(c);\n    } else if (!strcasecmp(c->argv[1]->ptr,\"resetstat\")) {\n        if (c->argc != 2) goto badarity;\n        resetServerStats();\n        resetCommandTableStats();\n        addReply(c,shared.ok);\n    } else if (!strcasecmp(c->argv[1]->ptr,\"rewrite\")) {\n        if (c->argc != 2) goto badarity;\n        if (server.configfile == NULL) {\n            addReplyError(c,\"The server is running without a config file\");\n            return;\n        }\n        if (rewriteConfig(server.configfile) == -1) {\n            serverLog(LL_WARNING,\"CONFIG REWRITE failed: %s\", strerror(errno));\n            addReplyErrorFormat(c,\"Rewriting config file: %s\", strerror(errno));\n        } else {\n            serverLog(LL_WARNING,\"CONFIG REWRITE executed with success.\");\n            addReply(c,shared.ok);\n        }\n    } else {\n        addReplyError(c,\n            \"CONFIG subcommand must be one of GET, SET, RESETSTAT, REWRITE\");\n    }\n    return;\n\nbadarity:\n    addReplyErrorFormat(c,\"Wrong number of arguments for CONFIG %s\",\n        (char*) c->argv[1]->ptr);\n}\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/src/config.h",
    "content": "/*\n * Copyright (c) 2009-2012, Salvatore Sanfilippo <antirez at gmail dot com>\n * All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions are met:\n *\n *   * Redistributions of source code must retain the above copyright notice,\n *     this list of conditions and the following disclaimer.\n *   * Redistributions in binary form must reproduce the above copyright\n *     notice, this list of conditions and the following disclaimer in the\n *     documentation and/or other materials provided with the distribution.\n *   * Neither the name of Redis nor the names of its contributors may be used\n *     to endorse or promote products derived from this software without\n *     specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\"\n * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\n * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE\n * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR\n * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF\n * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS\n * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN\n * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)\n * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE\n * POSSIBILITY OF SUCH DAMAGE.\n */\n\n#ifndef __CONFIG_H\n#define __CONFIG_H\n\n#ifdef __APPLE__\n#include <AvailabilityMacros.h>\n#endif\n\n#ifdef __linux__\n#include <linux/version.h>\n#include <features.h>\n#endif\n\n/* Define redis_fstat to fstat or fstat64() */\n#if defined(__APPLE__) && !defined(MAC_OS_X_VERSION_10_6)\n#define redis_fstat fstat64\n#define redis_stat stat64\n#else\n#define redis_fstat fstat\n#define redis_stat stat\n#endif\n\n/* Test for proc filesystem */\n#ifdef __linux__\n#define HAVE_PROC_STAT 1\n#define HAVE_PROC_MAPS 1\n#define HAVE_PROC_SMAPS 1\n#define HAVE_PROC_SOMAXCONN 1\n#endif\n\n/* Test for task_info() */\n#if defined(__APPLE__)\n#define HAVE_TASKINFO 1\n#endif\n\n/* Test for backtrace() */\n#if defined(__APPLE__) || (defined(__linux__) && defined(__GLIBC__))\n#define HAVE_BACKTRACE 1\n#endif\n\n/* MSG_NOSIGNAL. */\n#ifdef __linux__\n#define HAVE_MSG_NOSIGNAL 1\n#endif\n\n/* Test for polling API */\n#ifdef __linux__\n#define HAVE_EPOLL 1\n#endif\n\n#if (defined(__APPLE__) && defined(MAC_OS_X_VERSION_10_6)) || defined(__FreeBSD__) || defined(__OpenBSD__) || defined (__NetBSD__)\n#define HAVE_KQUEUE 1\n#endif\n\n#ifdef __sun\n#include <sys/feature_tests.h>\n#ifdef _DTRACE_VERSION\n#define HAVE_EVPORT 1\n#endif\n#endif\n\n/* Define aof_fsync to fdatasync() in Linux and fsync() for all the rest */\n#ifdef __linux__\n#define aof_fsync fdatasync\n#else\n#define aof_fsync fsync\n#endif\n\n/* Define rdb_fsync_range to sync_file_range() on Linux, otherwise we use\n * the plain fsync() call. */\n#ifdef __linux__\n#if defined(__GLIBC__) && defined(__GLIBC_PREREQ)\n#if (LINUX_VERSION_CODE >= 0x020611 && __GLIBC_PREREQ(2, 6))\n#define HAVE_SYNC_FILE_RANGE 1\n#endif\n#else\n#if (LINUX_VERSION_CODE >= 0x020611)\n#define HAVE_SYNC_FILE_RANGE 1\n#endif\n#endif\n#endif\n\n#ifdef HAVE_SYNC_FILE_RANGE\n#define rdb_fsync_range(fd,off,size) sync_file_range(fd,off,size,SYNC_FILE_RANGE_WAIT_BEFORE|SYNC_FILE_RANGE_WRITE)\n#else\n#define rdb_fsync_range(fd,off,size) fsync(fd)\n#endif\n\n/* Check if we can use setproctitle().\n * BSD systems have support for it, we provide an implementation for\n * Linux and osx. */\n#if (defined __NetBSD__ || defined __FreeBSD__ || defined __OpenBSD__)\n#define USE_SETPROCTITLE\n#endif\n\n#if ((defined __linux && defined(__GLIBC__)) || defined __APPLE__)\n#define USE_SETPROCTITLE\n#define INIT_SETPROCTITLE_REPLACEMENT\nvoid spt_init(int argc, char *argv[]);\nvoid setproctitle(const char *fmt, ...);\n#endif\n\n/* Byte ordering detection */\n#include <sys/types.h> /* This will likely define BYTE_ORDER */\n\n#ifndef BYTE_ORDER\n#if (BSD >= 199103)\n# include <machine/endian.h>\n#else\n#if defined(linux) || defined(__linux__)\n# include <endian.h>\n#else\n#define\tLITTLE_ENDIAN\t1234\t/* least-significant byte first (vax, pc) */\n#define\tBIG_ENDIAN\t4321\t/* most-significant byte first (IBM, net) */\n#define\tPDP_ENDIAN\t3412\t/* LSB first in word, MSW first in long (pdp)*/\n\n#if defined(__i386__) || defined(__x86_64__) || defined(__amd64__) || \\\n   defined(vax) || defined(ns32000) || defined(sun386) || \\\n   defined(MIPSEL) || defined(_MIPSEL) || defined(BIT_ZERO_ON_RIGHT) || \\\n   defined(__alpha__) || defined(__alpha)\n#define BYTE_ORDER    LITTLE_ENDIAN\n#endif\n\n#if defined(sel) || defined(pyr) || defined(mc68000) || defined(sparc) || \\\n    defined(is68k) || defined(tahoe) || defined(ibm032) || defined(ibm370) || \\\n    defined(MIPSEB) || defined(_MIPSEB) || defined(_IBMR2) || defined(DGUX) ||\\\n    defined(apollo) || defined(__convex__) || defined(_CRAY) || \\\n    defined(__hppa) || defined(__hp9000) || \\\n    defined(__hp9000s300) || defined(__hp9000s700) || \\\n    defined (BIT_ZERO_ON_LEFT) || defined(m68k) || defined(__sparc)\n#define BYTE_ORDER\tBIG_ENDIAN\n#endif\n#endif /* linux */\n#endif /* BSD */\n#endif /* BYTE_ORDER */\n\n/* Sometimes after including an OS-specific header that defines the\n * endianess we end with __BYTE_ORDER but not with BYTE_ORDER that is what\n * the Redis code uses. In this case let's define everything without the\n * underscores. */\n#ifndef BYTE_ORDER\n#ifdef __BYTE_ORDER\n#if defined(__LITTLE_ENDIAN) && defined(__BIG_ENDIAN)\n#ifndef LITTLE_ENDIAN\n#define LITTLE_ENDIAN __LITTLE_ENDIAN\n#endif\n#ifndef BIG_ENDIAN\n#define BIG_ENDIAN __BIG_ENDIAN\n#endif\n#if (__BYTE_ORDER == __LITTLE_ENDIAN)\n#define BYTE_ORDER LITTLE_ENDIAN\n#else\n#define BYTE_ORDER BIG_ENDIAN\n#endif\n#endif\n#endif\n#endif\n\n#if !defined(BYTE_ORDER) || \\\n    (BYTE_ORDER != BIG_ENDIAN && BYTE_ORDER != LITTLE_ENDIAN)\n\t/* you must determine what the correct bit order is for\n\t * your compiler - the next line is an intentional error\n\t * which will force your compiles to bomb until you fix\n\t * the above macros.\n\t */\n#error \"Undefined or invalid BYTE_ORDER\"\n#endif\n\n#if (__i386 || __amd64 || __powerpc__) && __GNUC__\n#define GNUC_VERSION (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__)\n#if defined(__clang__)\n#define HAVE_ATOMIC\n#endif\n#if (defined(__GLIBC__) && defined(__GLIBC_PREREQ))\n#if (GNUC_VERSION >= 40100 && __GLIBC_PREREQ(2, 6))\n#define HAVE_ATOMIC\n#endif\n#endif\n#endif\n\n#endif\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/src/crc16.c",
    "content": "#include \"server.h\"\n\n/*\n * Copyright 2001-2010 Georges Menie (www.menie.org)\n * Copyright 2010-2012 Salvatore Sanfilippo (adapted to Redis coding style)\n * All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions are met:\n *\n *     * Redistributions of source code must retain the above copyright\n *       notice, this list of conditions and the following disclaimer.\n *     * Redistributions in binary form must reproduce the above copyright\n *       notice, this list of conditions and the following disclaimer in the\n *       documentation and/or other materials provided with the distribution.\n *     * Neither the name of the University of California, Berkeley nor the\n *       names of its contributors may be used to endorse or promote products\n *       derived from this software without specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ANY\n * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n * DISCLAIMED. IN NO EVENT SHALL THE REGENTS AND CONTRIBUTORS BE LIABLE FOR ANY\n * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\n * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND\n * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\n * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n\n/* CRC16 implementation according to CCITT standards.\n *\n * Note by @antirez: this is actually the XMODEM CRC 16 algorithm, using the\n * following parameters:\n *\n * Name                       : \"XMODEM\", also known as \"ZMODEM\", \"CRC-16/ACORN\"\n * Width                      : 16 bit\n * Poly                       : 1021 (That is actually x^16 + x^12 + x^5 + 1)\n * Initialization             : 0000\n * Reflect Input byte         : False\n * Reflect Output CRC         : False\n * Xor constant to output CRC : 0000\n * Output for \"123456789\"     : 31C3\n */\n\nstatic const uint16_t crc16tab[256]= {\n    0x0000,0x1021,0x2042,0x3063,0x4084,0x50a5,0x60c6,0x70e7,\n    0x8108,0x9129,0xa14a,0xb16b,0xc18c,0xd1ad,0xe1ce,0xf1ef,\n    0x1231,0x0210,0x3273,0x2252,0x52b5,0x4294,0x72f7,0x62d6,\n    0x9339,0x8318,0xb37b,0xa35a,0xd3bd,0xc39c,0xf3ff,0xe3de,\n    0x2462,0x3443,0x0420,0x1401,0x64e6,0x74c7,0x44a4,0x5485,\n    0xa56a,0xb54b,0x8528,0x9509,0xe5ee,0xf5cf,0xc5ac,0xd58d,\n    0x3653,0x2672,0x1611,0x0630,0x76d7,0x66f6,0x5695,0x46b4,\n    0xb75b,0xa77a,0x9719,0x8738,0xf7df,0xe7fe,0xd79d,0xc7bc,\n    0x48c4,0x58e5,0x6886,0x78a7,0x0840,0x1861,0x2802,0x3823,\n    0xc9cc,0xd9ed,0xe98e,0xf9af,0x8948,0x9969,0xa90a,0xb92b,\n    0x5af5,0x4ad4,0x7ab7,0x6a96,0x1a71,0x0a50,0x3a33,0x2a12,\n    0xdbfd,0xcbdc,0xfbbf,0xeb9e,0x9b79,0x8b58,0xbb3b,0xab1a,\n    0x6ca6,0x7c87,0x4ce4,0x5cc5,0x2c22,0x3c03,0x0c60,0x1c41,\n    0xedae,0xfd8f,0xcdec,0xddcd,0xad2a,0xbd0b,0x8d68,0x9d49,\n    0x7e97,0x6eb6,0x5ed5,0x4ef4,0x3e13,0x2e32,0x1e51,0x0e70,\n    0xff9f,0xefbe,0xdfdd,0xcffc,0xbf1b,0xaf3a,0x9f59,0x8f78,\n    0x9188,0x81a9,0xb1ca,0xa1eb,0xd10c,0xc12d,0xf14e,0xe16f,\n    0x1080,0x00a1,0x30c2,0x20e3,0x5004,0x4025,0x7046,0x6067,\n    0x83b9,0x9398,0xa3fb,0xb3da,0xc33d,0xd31c,0xe37f,0xf35e,\n    0x02b1,0x1290,0x22f3,0x32d2,0x4235,0x5214,0x6277,0x7256,\n    0xb5ea,0xa5cb,0x95a8,0x8589,0xf56e,0xe54f,0xd52c,0xc50d,\n    0x34e2,0x24c3,0x14a0,0x0481,0x7466,0x6447,0x5424,0x4405,\n    0xa7db,0xb7fa,0x8799,0x97b8,0xe75f,0xf77e,0xc71d,0xd73c,\n    0x26d3,0x36f2,0x0691,0x16b0,0x6657,0x7676,0x4615,0x5634,\n    0xd94c,0xc96d,0xf90e,0xe92f,0x99c8,0x89e9,0xb98a,0xa9ab,\n    0x5844,0x4865,0x7806,0x6827,0x18c0,0x08e1,0x3882,0x28a3,\n    0xcb7d,0xdb5c,0xeb3f,0xfb1e,0x8bf9,0x9bd8,0xabbb,0xbb9a,\n    0x4a75,0x5a54,0x6a37,0x7a16,0x0af1,0x1ad0,0x2ab3,0x3a92,\n    0xfd2e,0xed0f,0xdd6c,0xcd4d,0xbdaa,0xad8b,0x9de8,0x8dc9,\n    0x7c26,0x6c07,0x5c64,0x4c45,0x3ca2,0x2c83,0x1ce0,0x0cc1,\n    0xef1f,0xff3e,0xcf5d,0xdf7c,0xaf9b,0xbfba,0x8fd9,0x9ff8,\n    0x6e17,0x7e36,0x4e55,0x5e74,0x2e93,0x3eb2,0x0ed1,0x1ef0\n};\n\nuint16_t crc16(const char *buf, int len) {\n    int counter;\n    uint16_t crc = 0;\n    for (counter = 0; counter < len; counter++)\n            crc = (crc<<8) ^ crc16tab[((crc>>8) ^ *buf++)&0x00FF];\n    return crc;\n}\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/src/crc32.c",
    "content": "#include <stdint.h>\n\nstatic const uint32_t IEEE_POLY = 0xedb88320;\n\nstatic uint32_t crc32tab[256];\n\nstatic void\ncrc32_tabinit(uint32_t poly) {\n    int i, j;\n    for (i = 0; i < 256; i ++) {\n        uint32_t crc = i;\n        for (j = 0; j < 8; j ++) {\n            if (crc & 1) {\n                crc = (crc >> 1) ^ poly;\n            } else {\n                crc = (crc >> 1);\n            }\n        }\n        crc32tab[i] = crc;\n    }\n}\n\nvoid\ncrc32_init() {\n    crc32_tabinit(IEEE_POLY);\n}\n\nstatic uint32_t\ncrc32_update(uint32_t crc, const char *buf, int len) {\n    int i;\n    crc = ~crc;\n    for (i = 0; i < len; i ++) {\n        crc = crc32tab[(uint8_t)((char)crc ^ buf[i])] ^ (crc >> 8);\n    }\n    return ~crc;\n}\n\nuint32_t\ncrc32_checksum(const char *buf, int len) {\n    return crc32_update(0, buf, len);\n}\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/src/crc64.c",
    "content": "/* Redis uses the CRC64 variant with \"Jones\" coefficients and init value of 0.\n *\n * Specification of this CRC64 variant follows:\n * Name: crc-64-jones\n * Width: 64 bites\n * Poly: 0xad93d23594c935a9\n * Reflected In: True\n * Xor_In: 0xffffffffffffffff\n * Reflected_Out: True\n * Xor_Out: 0x0\n * Check(\"123456789\"): 0xe9c6d914c4b8d9ca\n *\n * Copyright (c) 2012, Salvatore Sanfilippo <antirez at gmail dot com>\n * All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions are met:\n *\n *   * Redistributions of source code must retain the above copyright notice,\n *     this list of conditions and the following disclaimer.\n *   * Redistributions in binary form must reproduce the above copyright\n *     notice, this list of conditions and the following disclaimer in the\n *     documentation and/or other materials provided with the distribution.\n *   * Neither the name of Redis nor the names of its contributors may be used\n *     to endorse or promote products derived from this software without\n *     specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\"\n * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\n * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE\n * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR\n * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF\n * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS\n * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN\n * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)\n * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE\n * POSSIBILITY OF SUCH DAMAGE. */\n\n#include <stdint.h>\n\nstatic const uint64_t crc64_tab[256] = {\n    UINT64_C(0x0000000000000000), UINT64_C(0x7ad870c830358979),\n    UINT64_C(0xf5b0e190606b12f2), UINT64_C(0x8f689158505e9b8b),\n    UINT64_C(0xc038e5739841b68f), UINT64_C(0xbae095bba8743ff6),\n    UINT64_C(0x358804e3f82aa47d), UINT64_C(0x4f50742bc81f2d04),\n    UINT64_C(0xab28ecb46814fe75), UINT64_C(0xd1f09c7c5821770c),\n    UINT64_C(0x5e980d24087fec87), UINT64_C(0x24407dec384a65fe),\n    UINT64_C(0x6b1009c7f05548fa), UINT64_C(0x11c8790fc060c183),\n    UINT64_C(0x9ea0e857903e5a08), UINT64_C(0xe478989fa00bd371),\n    UINT64_C(0x7d08ff3b88be6f81), UINT64_C(0x07d08ff3b88be6f8),\n    UINT64_C(0x88b81eabe8d57d73), UINT64_C(0xf2606e63d8e0f40a),\n    UINT64_C(0xbd301a4810ffd90e), UINT64_C(0xc7e86a8020ca5077),\n    UINT64_C(0x4880fbd87094cbfc), UINT64_C(0x32588b1040a14285),\n    UINT64_C(0xd620138fe0aa91f4), UINT64_C(0xacf86347d09f188d),\n    UINT64_C(0x2390f21f80c18306), UINT64_C(0x594882d7b0f40a7f),\n    UINT64_C(0x1618f6fc78eb277b), UINT64_C(0x6cc0863448deae02),\n    UINT64_C(0xe3a8176c18803589), UINT64_C(0x997067a428b5bcf0),\n    UINT64_C(0xfa11fe77117cdf02), UINT64_C(0x80c98ebf2149567b),\n    UINT64_C(0x0fa11fe77117cdf0), UINT64_C(0x75796f2f41224489),\n    UINT64_C(0x3a291b04893d698d), UINT64_C(0x40f16bccb908e0f4),\n    UINT64_C(0xcf99fa94e9567b7f), UINT64_C(0xb5418a5cd963f206),\n    UINT64_C(0x513912c379682177), UINT64_C(0x2be1620b495da80e),\n    UINT64_C(0xa489f35319033385), UINT64_C(0xde51839b2936bafc),\n    UINT64_C(0x9101f7b0e12997f8), UINT64_C(0xebd98778d11c1e81),\n    UINT64_C(0x64b116208142850a), UINT64_C(0x1e6966e8b1770c73),\n    UINT64_C(0x8719014c99c2b083), UINT64_C(0xfdc17184a9f739fa),\n    UINT64_C(0x72a9e0dcf9a9a271), UINT64_C(0x08719014c99c2b08),\n    UINT64_C(0x4721e43f0183060c), UINT64_C(0x3df994f731b68f75),\n    UINT64_C(0xb29105af61e814fe), UINT64_C(0xc849756751dd9d87),\n    UINT64_C(0x2c31edf8f1d64ef6), UINT64_C(0x56e99d30c1e3c78f),\n    UINT64_C(0xd9810c6891bd5c04), UINT64_C(0xa3597ca0a188d57d),\n    UINT64_C(0xec09088b6997f879), UINT64_C(0x96d1784359a27100),\n    UINT64_C(0x19b9e91b09fcea8b), UINT64_C(0x636199d339c963f2),\n    UINT64_C(0xdf7adabd7a6e2d6f), UINT64_C(0xa5a2aa754a5ba416),\n    UINT64_C(0x2aca3b2d1a053f9d), UINT64_C(0x50124be52a30b6e4),\n    UINT64_C(0x1f423fcee22f9be0), UINT64_C(0x659a4f06d21a1299),\n    UINT64_C(0xeaf2de5e82448912), UINT64_C(0x902aae96b271006b),\n    UINT64_C(0x74523609127ad31a), UINT64_C(0x0e8a46c1224f5a63),\n    UINT64_C(0x81e2d7997211c1e8), UINT64_C(0xfb3aa75142244891),\n    UINT64_C(0xb46ad37a8a3b6595), UINT64_C(0xceb2a3b2ba0eecec),\n    UINT64_C(0x41da32eaea507767), UINT64_C(0x3b024222da65fe1e),\n    UINT64_C(0xa2722586f2d042ee), UINT64_C(0xd8aa554ec2e5cb97),\n    UINT64_C(0x57c2c41692bb501c), UINT64_C(0x2d1ab4dea28ed965),\n    UINT64_C(0x624ac0f56a91f461), UINT64_C(0x1892b03d5aa47d18),\n    UINT64_C(0x97fa21650afae693), UINT64_C(0xed2251ad3acf6fea),\n    UINT64_C(0x095ac9329ac4bc9b), UINT64_C(0x7382b9faaaf135e2),\n    UINT64_C(0xfcea28a2faafae69), UINT64_C(0x8632586aca9a2710),\n    UINT64_C(0xc9622c4102850a14), UINT64_C(0xb3ba5c8932b0836d),\n    UINT64_C(0x3cd2cdd162ee18e6), UINT64_C(0x460abd1952db919f),\n    UINT64_C(0x256b24ca6b12f26d), UINT64_C(0x5fb354025b277b14),\n    UINT64_C(0xd0dbc55a0b79e09f), UINT64_C(0xaa03b5923b4c69e6),\n    UINT64_C(0xe553c1b9f35344e2), UINT64_C(0x9f8bb171c366cd9b),\n    UINT64_C(0x10e3202993385610), UINT64_C(0x6a3b50e1a30ddf69),\n    UINT64_C(0x8e43c87e03060c18), UINT64_C(0xf49bb8b633338561),\n    UINT64_C(0x7bf329ee636d1eea), UINT64_C(0x012b592653589793),\n    UINT64_C(0x4e7b2d0d9b47ba97), UINT64_C(0x34a35dc5ab7233ee),\n    UINT64_C(0xbbcbcc9dfb2ca865), UINT64_C(0xc113bc55cb19211c),\n    UINT64_C(0x5863dbf1e3ac9dec), UINT64_C(0x22bbab39d3991495),\n    UINT64_C(0xadd33a6183c78f1e), UINT64_C(0xd70b4aa9b3f20667),\n    UINT64_C(0x985b3e827bed2b63), UINT64_C(0xe2834e4a4bd8a21a),\n    UINT64_C(0x6debdf121b863991), UINT64_C(0x1733afda2bb3b0e8),\n    UINT64_C(0xf34b37458bb86399), UINT64_C(0x8993478dbb8deae0),\n    UINT64_C(0x06fbd6d5ebd3716b), UINT64_C(0x7c23a61ddbe6f812),\n    UINT64_C(0x3373d23613f9d516), UINT64_C(0x49aba2fe23cc5c6f),\n    UINT64_C(0xc6c333a67392c7e4), UINT64_C(0xbc1b436e43a74e9d),\n    UINT64_C(0x95ac9329ac4bc9b5), UINT64_C(0xef74e3e19c7e40cc),\n    UINT64_C(0x601c72b9cc20db47), UINT64_C(0x1ac40271fc15523e),\n    UINT64_C(0x5594765a340a7f3a), UINT64_C(0x2f4c0692043ff643),\n    UINT64_C(0xa02497ca54616dc8), UINT64_C(0xdafce7026454e4b1),\n    UINT64_C(0x3e847f9dc45f37c0), UINT64_C(0x445c0f55f46abeb9),\n    UINT64_C(0xcb349e0da4342532), UINT64_C(0xb1eceec59401ac4b),\n    UINT64_C(0xfebc9aee5c1e814f), UINT64_C(0x8464ea266c2b0836),\n    UINT64_C(0x0b0c7b7e3c7593bd), UINT64_C(0x71d40bb60c401ac4),\n    UINT64_C(0xe8a46c1224f5a634), UINT64_C(0x927c1cda14c02f4d),\n    UINT64_C(0x1d148d82449eb4c6), UINT64_C(0x67ccfd4a74ab3dbf),\n    UINT64_C(0x289c8961bcb410bb), UINT64_C(0x5244f9a98c8199c2),\n    UINT64_C(0xdd2c68f1dcdf0249), UINT64_C(0xa7f41839ecea8b30),\n    UINT64_C(0x438c80a64ce15841), UINT64_C(0x3954f06e7cd4d138),\n    UINT64_C(0xb63c61362c8a4ab3), UINT64_C(0xcce411fe1cbfc3ca),\n    UINT64_C(0x83b465d5d4a0eece), UINT64_C(0xf96c151de49567b7),\n    UINT64_C(0x76048445b4cbfc3c), UINT64_C(0x0cdcf48d84fe7545),\n    UINT64_C(0x6fbd6d5ebd3716b7), UINT64_C(0x15651d968d029fce),\n    UINT64_C(0x9a0d8ccedd5c0445), UINT64_C(0xe0d5fc06ed698d3c),\n    UINT64_C(0xaf85882d2576a038), UINT64_C(0xd55df8e515432941),\n    UINT64_C(0x5a3569bd451db2ca), UINT64_C(0x20ed197575283bb3),\n    UINT64_C(0xc49581ead523e8c2), UINT64_C(0xbe4df122e51661bb),\n    UINT64_C(0x3125607ab548fa30), UINT64_C(0x4bfd10b2857d7349),\n    UINT64_C(0x04ad64994d625e4d), UINT64_C(0x7e7514517d57d734),\n    UINT64_C(0xf11d85092d094cbf), UINT64_C(0x8bc5f5c11d3cc5c6),\n    UINT64_C(0x12b5926535897936), UINT64_C(0x686de2ad05bcf04f),\n    UINT64_C(0xe70573f555e26bc4), UINT64_C(0x9ddd033d65d7e2bd),\n    UINT64_C(0xd28d7716adc8cfb9), UINT64_C(0xa85507de9dfd46c0),\n    UINT64_C(0x273d9686cda3dd4b), UINT64_C(0x5de5e64efd965432),\n    UINT64_C(0xb99d7ed15d9d8743), UINT64_C(0xc3450e196da80e3a),\n    UINT64_C(0x4c2d9f413df695b1), UINT64_C(0x36f5ef890dc31cc8),\n    UINT64_C(0x79a59ba2c5dc31cc), UINT64_C(0x037deb6af5e9b8b5),\n    UINT64_C(0x8c157a32a5b7233e), UINT64_C(0xf6cd0afa9582aa47),\n    UINT64_C(0x4ad64994d625e4da), UINT64_C(0x300e395ce6106da3),\n    UINT64_C(0xbf66a804b64ef628), UINT64_C(0xc5bed8cc867b7f51),\n    UINT64_C(0x8aeeace74e645255), UINT64_C(0xf036dc2f7e51db2c),\n    UINT64_C(0x7f5e4d772e0f40a7), UINT64_C(0x05863dbf1e3ac9de),\n    UINT64_C(0xe1fea520be311aaf), UINT64_C(0x9b26d5e88e0493d6),\n    UINT64_C(0x144e44b0de5a085d), UINT64_C(0x6e963478ee6f8124),\n    UINT64_C(0x21c640532670ac20), UINT64_C(0x5b1e309b16452559),\n    UINT64_C(0xd476a1c3461bbed2), UINT64_C(0xaeaed10b762e37ab),\n    UINT64_C(0x37deb6af5e9b8b5b), UINT64_C(0x4d06c6676eae0222),\n    UINT64_C(0xc26e573f3ef099a9), UINT64_C(0xb8b627f70ec510d0),\n    UINT64_C(0xf7e653dcc6da3dd4), UINT64_C(0x8d3e2314f6efb4ad),\n    UINT64_C(0x0256b24ca6b12f26), UINT64_C(0x788ec2849684a65f),\n    UINT64_C(0x9cf65a1b368f752e), UINT64_C(0xe62e2ad306bafc57),\n    UINT64_C(0x6946bb8b56e467dc), UINT64_C(0x139ecb4366d1eea5),\n    UINT64_C(0x5ccebf68aecec3a1), UINT64_C(0x2616cfa09efb4ad8),\n    UINT64_C(0xa97e5ef8cea5d153), UINT64_C(0xd3a62e30fe90582a),\n    UINT64_C(0xb0c7b7e3c7593bd8), UINT64_C(0xca1fc72bf76cb2a1),\n    UINT64_C(0x45775673a732292a), UINT64_C(0x3faf26bb9707a053),\n    UINT64_C(0x70ff52905f188d57), UINT64_C(0x0a2722586f2d042e),\n    UINT64_C(0x854fb3003f739fa5), UINT64_C(0xff97c3c80f4616dc),\n    UINT64_C(0x1bef5b57af4dc5ad), UINT64_C(0x61372b9f9f784cd4),\n    UINT64_C(0xee5fbac7cf26d75f), UINT64_C(0x9487ca0fff135e26),\n    UINT64_C(0xdbd7be24370c7322), UINT64_C(0xa10fceec0739fa5b),\n    UINT64_C(0x2e675fb4576761d0), UINT64_C(0x54bf2f7c6752e8a9),\n    UINT64_C(0xcdcf48d84fe75459), UINT64_C(0xb71738107fd2dd20),\n    UINT64_C(0x387fa9482f8c46ab), UINT64_C(0x42a7d9801fb9cfd2),\n    UINT64_C(0x0df7adabd7a6e2d6), UINT64_C(0x772fdd63e7936baf),\n    UINT64_C(0xf8474c3bb7cdf024), UINT64_C(0x829f3cf387f8795d),\n    UINT64_C(0x66e7a46c27f3aa2c), UINT64_C(0x1c3fd4a417c62355),\n    UINT64_C(0x935745fc4798b8de), UINT64_C(0xe98f353477ad31a7),\n    UINT64_C(0xa6df411fbfb21ca3), UINT64_C(0xdc0731d78f8795da),\n    UINT64_C(0x536fa08fdfd90e51), UINT64_C(0x29b7d047efec8728),\n};\n\nuint64_t crc64(uint64_t crc, const unsigned char *s, uint64_t l) {\n    uint64_t j;\n\n    for (j = 0; j < l; j++) {\n        uint8_t byte = s[j];\n        crc = crc64_tab[(uint8_t)crc ^ byte] ^ (crc >> 8);\n    }\n    return crc;\n}\n\n/* Test main */\n#ifdef REDIS_TEST\n#include <stdio.h>\n\n#define UNUSED(x) (void)(x)\nint crc64Test(int argc, char *argv[]) {\n    UNUSED(argc);\n    UNUSED(argv);\n    printf(\"e9c6d914c4b8d9ca == %016llx\\n\",\n        (unsigned long long) crc64(0,(unsigned char*)\"123456789\",9));\n    return 0;\n}\n#endif\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/src/crc64.h",
    "content": "#ifndef CRC64_H\n#define CRC64_H\n\n#include <stdint.h>\n\nuint64_t crc64(uint64_t crc, const unsigned char *s, uint64_t l);\n\n#ifdef REDIS_TEST\nint crc64Test(int argc, char *argv[]);\n#endif\n\n#endif\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/src/db.c",
    "content": "/*\n * Copyright (c) 2009-2012, Salvatore Sanfilippo <antirez at gmail dot com>\n * All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions are met:\n *\n *   * Redistributions of source code must retain the above copyright notice,\n *     this list of conditions and the following disclaimer.\n *   * Redistributions in binary form must reproduce the above copyright\n *     notice, this list of conditions and the following disclaimer in the\n *     documentation and/or other materials provided with the distribution.\n *   * Neither the name of Redis nor the names of its contributors may be used\n *     to endorse or promote products derived from this software without\n *     specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\"\n * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\n * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE\n * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR\n * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF\n * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS\n * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN\n * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)\n * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE\n * POSSIBILITY OF SUCH DAMAGE.\n */\n\n#include \"server.h\"\n#include \"cluster.h\"\n\n#include <signal.h>\n#include <ctype.h>\n\nvoid slotToKeyAdd(robj *key);\nvoid slotToKeyDel(robj *key);\nvoid slotToKeyFlush(void);\n\n/*-----------------------------------------------------------------------------\n * C-level DB API\n *----------------------------------------------------------------------------*/\n\n/* Low level key lookup API, not actually called directly from commands\n * implementations that should instead rely on lookupKeyRead(),\n * lookupKeyWrite() and lookupKeyReadWithFlags(). */\nrobj *lookupKey(redisDb *db, robj *key, int flags) {\n    dictEntry *de = dictFind(db->dict,key->ptr);\n    if (de) {\n        robj *val = dictGetVal(de);\n\n        /* Update the access time for the ageing algorithm.\n         * Don't do it if we have a saving child, as this will trigger\n         * a copy on write madness. */\n        if (server.rdb_child_pid == -1 &&\n            server.aof_child_pid == -1 &&\n            !(flags & LOOKUP_NOTOUCH))\n        {\n            val->lru = LRU_CLOCK();\n        }\n        return val;\n    } else {\n        return NULL;\n    }\n}\n\n/* Lookup a key for read operations, or return NULL if the key is not found\n * in the specified DB.\n *\n * As a side effect of calling this function:\n * 1. A key gets expired if it reached it's TTL.\n * 2. The key last access time is updated.\n * 3. The global keys hits/misses stats are updated (reported in INFO).\n *\n * This API should not be used when we write to the key after obtaining\n * the object linked to the key, but only for read only operations.\n *\n * Flags change the behavior of this command:\n *\n *  LOOKUP_NONE (or zero): no special flags are passed.\n *  LOOKUP_NOTOUCH: don't alter the last access time of the key.\n *\n * Note: this function also returns NULL is the key is logically expired\n * but still existing, in case this is a slave, since this API is called only\n * for read operations. Even if the key expiry is master-driven, we can\n * correctly report a key is expired on slaves even if the master is lagging\n * expiring our key via DELs in the replication link. */\nrobj *lookupKeyReadWithFlags(redisDb *db, robj *key, int flags) {\n    robj *val;\n\n    if (expireIfNeeded(db,key) == 1) {\n        /* Key expired. If we are in the context of a master, expireIfNeeded()\n         * returns 0 only when the key does not exist at all, so it's save\n         * to return NULL ASAP. */\n        if (server.masterhost == NULL) return NULL;\n\n        /* However if we are in the context of a slave, expireIfNeeded() will\n         * not really try to expire the key, it only returns information\n         * about the \"logical\" status of the key: key expiring is up to the\n         * master in order to have a consistent view of master's data set.\n         *\n         * However, if the command caller is not the master, and as additional\n         * safety measure, the command invoked is a read-only command, we can\n         * safely return NULL here, and provide a more consistent behavior\n         * to clients accessign expired values in a read-only fashion, that\n         * will say the key as non exisitng.\n         *\n         * Notably this covers GETs when slaves are used to scale reads. */\n        if (server.current_client &&\n            server.current_client != server.master &&\n            server.current_client->cmd &&\n            server.current_client->cmd->flags & CMD_READONLY)\n        {\n            return NULL;\n        }\n    }\n    val = lookupKey(db,key,flags);\n    if (val == NULL)\n        server.stat_keyspace_misses++;\n    else\n        server.stat_keyspace_hits++;\n    return val;\n}\n\n/* Like lookupKeyReadWithFlags(), but does not use any flag, which is the\n * common case. */\nrobj *lookupKeyRead(redisDb *db, robj *key) {\n    return lookupKeyReadWithFlags(db,key,LOOKUP_NONE);\n}\n\n/* Lookup a key for write operations, and as a side effect, if needed, expires\n * the key if its TTL is reached.\n *\n * Returns the linked value object if the key exists or NULL if the key\n * does not exist in the specified DB. */\nrobj *lookupKeyWrite(redisDb *db, robj *key) {\n    expireIfNeeded(db,key);\n    return lookupKey(db,key,LOOKUP_NONE);\n}\n\nrobj *lookupKeyReadOrReply(client *c, robj *key, robj *reply) {\n    robj *o = lookupKeyRead(c->db, key);\n    if (!o) addReply(c,reply);\n    return o;\n}\n\nrobj *lookupKeyWriteOrReply(client *c, robj *key, robj *reply) {\n    robj *o = lookupKeyWrite(c->db, key);\n    if (!o) addReply(c,reply);\n    return o;\n}\n\n/* Add the key to the DB. It's up to the caller to increment the reference\n * counter of the value if needed.\n *\n * The program is aborted if the key already exists. */\nvoid dbAdd(redisDb *db, robj *key, robj *val) {\n    sds copy = sdsdup(key->ptr);\n    int retval = dictAdd(db->dict, copy, val);\n\n    do {\n        uint32_t crc;\n        int hastag;\n        int slot = slots_num(key->ptr, &crc, &hastag);\n        dictAdd(db->hash_slots[slot], copy, (void *)(long)crc);\n        if (hastag) {\n            incrRefCount(key);\n            zslInsert(db->tagged_keys, (double)crc, key);\n        }\n    } while (0);\n\n    serverAssertWithInfo(NULL,key,retval == DICT_OK);\n    if (val->type == OBJ_LIST) signalListAsReady(db, key);\n    if (server.cluster_enabled) slotToKeyAdd(key);\n }\n\n/* Overwrite an existing key with a new value. Incrementing the reference\n * count of the new value is up to the caller.\n * This function does not modify the expire time of the existing key.\n *\n * The program is aborted if the key was not already present. */\nvoid dbOverwrite(redisDb *db, robj *key, robj *val) {\n    dictEntry *de = dictFind(db->dict,key->ptr);\n\n    serverAssertWithInfo(NULL,key,de != NULL);\n    dictReplace(db->dict, key->ptr, val);\n}\n\n/* High level Set operation. This function can be used in order to set\n * a key, whatever it was existing or not, to a new object.\n *\n * 1) The ref count of the value object is incremented.\n * 2) clients WATCHing for the destination key notified.\n * 3) The expire time of the key is reset (the key is made persistent). */\nvoid setKey(redisDb *db, robj *key, robj *val) {\n    if (lookupKeyWrite(db,key) == NULL) {\n        dbAdd(db,key,val);\n    } else {\n        dbOverwrite(db,key,val);\n    }\n    incrRefCount(val);\n    removeExpire(db,key);\n    signalModifiedKey(db,key);\n}\n\nint dbExists(redisDb *db, robj *key) {\n    return dictFind(db->dict,key->ptr) != NULL;\n}\n\n/* Return a random key, in form of a Redis object.\n * If there are no keys, NULL is returned.\n *\n * The function makes sure to return keys not already expired. */\nrobj *dbRandomKey(redisDb *db) {\n    dictEntry *de;\n\n    while(1) {\n        sds key;\n        robj *keyobj;\n\n        de = dictGetRandomKey(db->dict);\n        if (de == NULL) return NULL;\n\n        key = dictGetKey(de);\n        keyobj = createStringObject(key,sdslen(key));\n        if (dictFind(db->expires,key)) {\n            if (expireIfNeeded(db,keyobj)) {\n                decrRefCount(keyobj);\n                continue; /* search for another key. This expired. */\n            }\n        }\n        return keyobj;\n    }\n}\n\n/* Delete a key, value, and associated expiration entry if any, from the DB */\nint dbDelete(redisDb *db, robj *key) {\n    /* Deleting an entry from the expires dict will not free the sds of\n     * the key, because it is shared with the main dictionary. */\n    if (dictSize(db->expires) > 0) dictDelete(db->expires,key->ptr);\n\n    do {\n        uint32_t crc;\n        int hastag;\n        int slot = slots_num(key->ptr, &crc, &hastag);\n        if (dictDelete(db->hash_slots[slot], key->ptr) == DICT_OK) {\n            if (hastag) {\n                zslDelete(db->tagged_keys, (double)crc, key);\n            }\n        }\n    } while (0);\n\n    if (dictDelete(db->dict,key->ptr) == DICT_OK) {\n        if (server.cluster_enabled) slotToKeyDel(key);\n        return 1;\n    } else {\n        return 0;\n    }\n}\n\n/* Prepare the string object stored at 'key' to be modified destructively\n * to implement commands like SETBIT or APPEND.\n *\n * An object is usually ready to be modified unless one of the two conditions\n * are true:\n *\n * 1) The object 'o' is shared (refcount > 1), we don't want to affect\n *    other users.\n * 2) The object encoding is not \"RAW\".\n *\n * If the object is found in one of the above conditions (or both) by the\n * function, an unshared / not-encoded copy of the string object is stored\n * at 'key' in the specified 'db'. Otherwise the object 'o' itself is\n * returned.\n *\n * USAGE:\n *\n * The object 'o' is what the caller already obtained by looking up 'key'\n * in 'db', the usage pattern looks like this:\n *\n * o = lookupKeyWrite(db,key);\n * if (checkType(c,o,OBJ_STRING)) return;\n * o = dbUnshareStringValue(db,key,o);\n *\n * At this point the caller is ready to modify the object, for example\n * using an sdscat() call to append some data, or anything else.\n */\nrobj *dbUnshareStringValue(redisDb *db, robj *key, robj *o) {\n    serverAssert(o->type == OBJ_STRING);\n    if (o->refcount != 1 || o->encoding != OBJ_ENCODING_RAW) {\n        robj *decoded = getDecodedObject(o);\n        o = createRawStringObject(decoded->ptr, sdslen(decoded->ptr));\n        decrRefCount(decoded);\n        dbOverwrite(db,key,o);\n    }\n    return o;\n}\n\nlong long emptyDb(void(callback)(void*)) {\n    int i, j;\n    long long removed = 0;\n\n    for (j = 0; j < server.dbnum; j++) {\n        removed += dictSize(server.db[j].dict);\n        for (i = 0; i < HASH_SLOTS_SIZE; i ++) {\n            dictEmpty(server.db[j].hash_slots[i], NULL);\n        }\n        if (server.db[j].tagged_keys->length != 0) {\n            zslFree(server.db[j].tagged_keys);\n            server.db[j].tagged_keys = zslCreate();\n        }\n        dictEmpty(server.db[j].dict,callback);\n        dictEmpty(server.db[j].expires,callback);\n    }\n    if (server.cluster_enabled) slotToKeyFlush();\n    return removed;\n}\n\nint selectDb(client *c, int id) {\n    if (id < 0 || id >= server.dbnum)\n        return C_ERR;\n    c->db = &server.db[id];\n    return C_OK;\n}\n\n/*-----------------------------------------------------------------------------\n * Hooks for key space changes.\n *\n * Every time a key in the database is modified the function\n * signalModifiedKey() is called.\n *\n * Every time a DB is flushed the function signalFlushDb() is called.\n *----------------------------------------------------------------------------*/\n\nvoid signalModifiedKey(redisDb *db, robj *key) {\n    touchWatchedKey(db,key);\n}\n\nvoid signalFlushedDb(int dbid) {\n    touchWatchedKeysOnFlush(dbid);\n}\n\n/*-----------------------------------------------------------------------------\n * Type agnostic commands operating on the key space\n *----------------------------------------------------------------------------*/\n\nvoid flushdbCommand(client *c) {\n    int i;\n    server.dirty += dictSize(c->db->dict);\n    signalFlushedDb(c->db->id);\n    for (i = 0; i < HASH_SLOTS_SIZE; i ++) {\n        dictEmpty(c->db->hash_slots[i], NULL);\n    }\n    if (c->db->tagged_keys->length != 0) {\n        zslFree(c->db->tagged_keys);\n        c->db->tagged_keys = zslCreate();\n    }\n    dictEmpty(c->db->dict,NULL);\n    dictEmpty(c->db->expires,NULL);\n    if (server.cluster_enabled) slotToKeyFlush();\n    addReply(c,shared.ok);\n}\n\nvoid flushallCommand(client *c) {\n    signalFlushedDb(-1);\n    server.dirty += emptyDb(NULL);\n    addReply(c,shared.ok);\n    if (server.rdb_child_pid != -1) {\n        kill(server.rdb_child_pid,SIGUSR1);\n        rdbRemoveTempFile(server.rdb_child_pid);\n    }\n    if (server.saveparamslen > 0) {\n        /* Normally rdbSave() will reset dirty, but we don't want this here\n         * as otherwise FLUSHALL will not be replicated nor put into the AOF. */\n        int saved_dirty = server.dirty;\n        rdbSave(server.rdb_filename);\n        server.dirty = saved_dirty;\n    }\n    server.dirty++;\n}\n\nvoid delCommand(client *c) {\n    int deleted = 0, j;\n\n    for (j = 1; j < c->argc; j++) {\n        expireIfNeeded(c->db,c->argv[j]);\n        if (dbDelete(c->db,c->argv[j])) {\n            signalModifiedKey(c->db,c->argv[j]);\n            notifyKeyspaceEvent(NOTIFY_GENERIC,\n                \"del\",c->argv[j],c->db->id);\n            server.dirty++;\n            deleted++;\n        }\n    }\n    addReplyLongLong(c,deleted);\n}\n\n/* EXISTS key1 key2 ... key_N.\n * Return value is the number of keys existing. */\nvoid existsCommand(client *c) {\n    long long count = 0;\n    int j;\n\n    for (j = 1; j < c->argc; j++) {\n        expireIfNeeded(c->db,c->argv[j]);\n        if (dbExists(c->db,c->argv[j])) count++;\n    }\n    addReplyLongLong(c,count);\n}\n\nvoid selectCommand(client *c) {\n    long id;\n\n    if (getLongFromObjectOrReply(c, c->argv[1], &id,\n        \"invalid DB index\") != C_OK)\n        return;\n\n    if (server.cluster_enabled && id != 0) {\n        addReplyError(c,\"SELECT is not allowed in cluster mode\");\n        return;\n    }\n    if (selectDb(c,id) == C_ERR) {\n        addReplyError(c,\"invalid DB index\");\n    } else {\n        addReply(c,shared.ok);\n    }\n}\n\nvoid randomkeyCommand(client *c) {\n    robj *key;\n\n    if ((key = dbRandomKey(c->db)) == NULL) {\n        addReply(c,shared.nullbulk);\n        return;\n    }\n\n    addReplyBulk(c,key);\n    decrRefCount(key);\n}\n\nvoid keysCommand(client *c) {\n    dictIterator *di;\n    dictEntry *de;\n    sds pattern = c->argv[1]->ptr;\n    int plen = sdslen(pattern), allkeys;\n    unsigned long numkeys = 0;\n    void *replylen = addDeferredMultiBulkLength(c);\n\n    di = dictGetSafeIterator(c->db->dict);\n    allkeys = (pattern[0] == '*' && pattern[1] == '\\0');\n    while((de = dictNext(di)) != NULL) {\n        sds key = dictGetKey(de);\n        robj *keyobj;\n\n        if (allkeys || stringmatchlen(pattern,plen,key,sdslen(key),0)) {\n            keyobj = createStringObject(key,sdslen(key));\n            if (expireIfNeeded(c->db,keyobj) == 0) {\n                addReplyBulk(c,keyobj);\n                numkeys++;\n            }\n            decrRefCount(keyobj);\n        }\n    }\n    dictReleaseIterator(di);\n    setDeferredMultiBulkLength(c,replylen,numkeys);\n}\n\n/* This callback is used by scanGenericCommand in order to collect elements\n * returned by the dictionary iterator into a list. */\nvoid scanCallback(void *privdata, const dictEntry *de) {\n    void **pd = (void**) privdata;\n    list *keys = pd[0];\n    robj *o = pd[1];\n    robj *key, *val = NULL;\n\n    if (o == NULL) {\n        sds sdskey = dictGetKey(de);\n        key = createStringObject(sdskey, sdslen(sdskey));\n    } else if (o->type == OBJ_SET) {\n        key = dictGetKey(de);\n        incrRefCount(key);\n    } else if (o->type == OBJ_HASH) {\n        key = dictGetKey(de);\n        incrRefCount(key);\n        val = dictGetVal(de);\n        incrRefCount(val);\n    } else if (o->type == OBJ_ZSET) {\n        key = dictGetKey(de);\n        incrRefCount(key);\n        val = createStringObjectFromLongDouble(*(double*)dictGetVal(de),0);\n    } else {\n        serverPanic(\"Type not handled in SCAN callback.\");\n    }\n\n    listAddNodeTail(keys, key);\n    if (val) listAddNodeTail(keys, val);\n}\n\n/* Try to parse a SCAN cursor stored at object 'o':\n * if the cursor is valid, store it as unsigned integer into *cursor and\n * returns C_OK. Otherwise return C_ERR and send an error to the\n * client. */\nint parseScanCursorOrReply(client *c, robj *o, unsigned long *cursor) {\n    char *eptr;\n\n    /* Use strtoul() because we need an *unsigned* long, so\n     * getLongLongFromObject() does not cover the whole cursor space. */\n    errno = 0;\n    *cursor = strtoul(o->ptr, &eptr, 10);\n    if (isspace(((char*)o->ptr)[0]) || eptr[0] != '\\0' || errno == ERANGE)\n    {\n        addReplyError(c, \"invalid cursor\");\n        return C_ERR;\n    }\n    return C_OK;\n}\n\n/* This command implements SCAN, HSCAN and SSCAN commands.\n * If object 'o' is passed, then it must be a Hash or Set object, otherwise\n * if 'o' is NULL the command will operate on the dictionary associated with\n * the current database.\n *\n * When 'o' is not NULL the function assumes that the first argument in\n * the client arguments vector is a key so it skips it before iterating\n * in order to parse options.\n *\n * In the case of a Hash object the function returns both the field and value\n * of every element on the Hash. */\nvoid scanGenericCommand(client *c, robj *o, unsigned long cursor) {\n    int i, j;\n    list *keys = listCreate();\n    listNode *node, *nextnode;\n    long count = 10;\n    sds pat = NULL;\n    int patlen = 0, use_pattern = 0;\n    dict *ht;\n\n    /* Object must be NULL (to iterate keys names), or the type of the object\n     * must be Set, Sorted Set, or Hash. */\n    serverAssert(o == NULL || o->type == OBJ_SET || o->type == OBJ_HASH ||\n                o->type == OBJ_ZSET);\n\n    /* Set i to the first option argument. The previous one is the cursor. */\n    i = (o == NULL) ? 2 : 3; /* Skip the key argument if needed. */\n\n    /* Step 1: Parse options. */\n    while (i < c->argc) {\n        j = c->argc - i;\n        if (!strcasecmp(c->argv[i]->ptr, \"count\") && j >= 2) {\n            if (getLongFromObjectOrReply(c, c->argv[i+1], &count, NULL)\n                != C_OK)\n            {\n                goto cleanup;\n            }\n\n            if (count < 1) {\n                addReply(c,shared.syntaxerr);\n                goto cleanup;\n            }\n\n            i += 2;\n        } else if (!strcasecmp(c->argv[i]->ptr, \"match\") && j >= 2) {\n            pat = c->argv[i+1]->ptr;\n            patlen = sdslen(pat);\n\n            /* The pattern always matches if it is exactly \"*\", so it is\n             * equivalent to disabling it. */\n            use_pattern = !(pat[0] == '*' && patlen == 1);\n\n            i += 2;\n        } else {\n            addReply(c,shared.syntaxerr);\n            goto cleanup;\n        }\n    }\n\n    /* Step 2: Iterate the collection.\n     *\n     * Note that if the object is encoded with a ziplist, intset, or any other\n     * representation that is not a hash table, we are sure that it is also\n     * composed of a small number of elements. So to avoid taking state we\n     * just return everything inside the object in a single call, setting the\n     * cursor to zero to signal the end of the iteration. */\n\n    /* Handle the case of a hash table. */\n    ht = NULL;\n    if (o == NULL) {\n        ht = c->db->dict;\n    } else if (o->type == OBJ_SET && o->encoding == OBJ_ENCODING_HT) {\n        ht = o->ptr;\n    } else if (o->type == OBJ_HASH && o->encoding == OBJ_ENCODING_HT) {\n        ht = o->ptr;\n        count *= 2; /* We return key / value for this type. */\n    } else if (o->type == OBJ_ZSET && o->encoding == OBJ_ENCODING_SKIPLIST) {\n        zset *zs = o->ptr;\n        ht = zs->dict;\n        count *= 2; /* We return key / value for this type. */\n    }\n\n    if (ht) {\n        void *privdata[2];\n        /* We set the max number of iterations to ten times the specified\n         * COUNT, so if the hash table is in a pathological state (very\n         * sparsely populated) we avoid to block too much time at the cost\n         * of returning no or very few elements. */\n        long maxiterations = count*10;\n\n        /* We pass two pointers to the callback: the list to which it will\n         * add new elements, and the object containing the dictionary so that\n         * it is possible to fetch more data in a type-dependent way. */\n        privdata[0] = keys;\n        privdata[1] = o;\n        do {\n            cursor = dictScan(ht, cursor, scanCallback, privdata);\n        } while (cursor &&\n              maxiterations-- &&\n              listLength(keys) < (unsigned long)count);\n    } else if (o->type == OBJ_SET) {\n        int pos = 0;\n        int64_t ll;\n\n        while(intsetGet(o->ptr,pos++,&ll))\n            listAddNodeTail(keys,createStringObjectFromLongLong(ll));\n        cursor = 0;\n    } else if (o->type == OBJ_HASH || o->type == OBJ_ZSET) {\n        unsigned char *p = ziplistIndex(o->ptr,0);\n        unsigned char *vstr;\n        unsigned int vlen;\n        long long vll;\n\n        while(p) {\n            ziplistGet(p,&vstr,&vlen,&vll);\n            listAddNodeTail(keys,\n                (vstr != NULL) ? createStringObject((char*)vstr,vlen) :\n                                 createStringObjectFromLongLong(vll));\n            p = ziplistNext(o->ptr,p);\n        }\n        cursor = 0;\n    } else {\n        serverPanic(\"Not handled encoding in SCAN.\");\n    }\n\n    /* Step 3: Filter elements. */\n    node = listFirst(keys);\n    while (node) {\n        robj *kobj = listNodeValue(node);\n        nextnode = listNextNode(node);\n        int filter = 0;\n\n        /* Filter element if it does not match the pattern. */\n        if (!filter && use_pattern) {\n            if (sdsEncodedObject(kobj)) {\n                if (!stringmatchlen(pat, patlen, kobj->ptr, sdslen(kobj->ptr), 0))\n                    filter = 1;\n            } else {\n                char buf[LONG_STR_SIZE];\n                int len;\n\n                serverAssert(kobj->encoding == OBJ_ENCODING_INT);\n                len = ll2string(buf,sizeof(buf),(long)kobj->ptr);\n                if (!stringmatchlen(pat, patlen, buf, len, 0)) filter = 1;\n            }\n        }\n\n        /* Filter element if it is an expired key. */\n        if (!filter && o == NULL && expireIfNeeded(c->db, kobj)) filter = 1;\n\n        /* Remove the element and its associted value if needed. */\n        if (filter) {\n            decrRefCount(kobj);\n            listDelNode(keys, node);\n        }\n\n        /* If this is a hash or a sorted set, we have a flat list of\n         * key-value elements, so if this element was filtered, remove the\n         * value, or skip it if it was not filtered: we only match keys. */\n        if (o && (o->type == OBJ_ZSET || o->type == OBJ_HASH)) {\n            node = nextnode;\n            nextnode = listNextNode(node);\n            if (filter) {\n                kobj = listNodeValue(node);\n                decrRefCount(kobj);\n                listDelNode(keys, node);\n            }\n        }\n        node = nextnode;\n    }\n\n    /* Step 4: Reply to the client. */\n    addReplyMultiBulkLen(c, 2);\n    addReplyBulkLongLong(c,cursor);\n\n    addReplyMultiBulkLen(c, listLength(keys));\n    while ((node = listFirst(keys)) != NULL) {\n        robj *kobj = listNodeValue(node);\n        addReplyBulk(c, kobj);\n        decrRefCount(kobj);\n        listDelNode(keys, node);\n    }\n\ncleanup:\n    listSetFreeMethod(keys,decrRefCountVoid);\n    listRelease(keys);\n}\n\n/* The SCAN command completely relies on scanGenericCommand. */\nvoid scanCommand(client *c) {\n    unsigned long cursor;\n    if (parseScanCursorOrReply(c,c->argv[1],&cursor) == C_ERR) return;\n    scanGenericCommand(c,NULL,cursor);\n}\n\nvoid dbsizeCommand(client *c) {\n    addReplyLongLong(c,dictSize(c->db->dict));\n}\n\nvoid lastsaveCommand(client *c) {\n    addReplyLongLong(c,server.lastsave);\n}\n\nvoid typeCommand(client *c) {\n    robj *o;\n    char *type;\n\n    o = lookupKeyReadWithFlags(c->db,c->argv[1],LOOKUP_NOTOUCH);\n    if (o == NULL) {\n        type = \"none\";\n    } else {\n        switch(o->type) {\n        case OBJ_STRING: type = \"string\"; break;\n        case OBJ_LIST: type = \"list\"; break;\n        case OBJ_SET: type = \"set\"; break;\n        case OBJ_ZSET: type = \"zset\"; break;\n        case OBJ_HASH: type = \"hash\"; break;\n        default: type = \"unknown\"; break;\n        }\n    }\n    addReplyStatus(c,type);\n}\n\nvoid shutdownCommand(client *c) {\n    int flags = 0;\n\n    if (c->argc > 2) {\n        addReply(c,shared.syntaxerr);\n        return;\n    } else if (c->argc == 2) {\n        if (!strcasecmp(c->argv[1]->ptr,\"nosave\")) {\n            flags |= SHUTDOWN_NOSAVE;\n        } else if (!strcasecmp(c->argv[1]->ptr,\"save\")) {\n            flags |= SHUTDOWN_SAVE;\n        } else {\n            addReply(c,shared.syntaxerr);\n            return;\n        }\n    }\n    /* When SHUTDOWN is called while the server is loading a dataset in\n     * memory we need to make sure no attempt is performed to save\n     * the dataset on shutdown (otherwise it could overwrite the current DB\n     * with half-read data).\n     *\n     * Also when in Sentinel mode clear the SAVE flag and force NOSAVE. */\n    if (server.loading || server.sentinel_mode)\n        flags = (flags & ~SHUTDOWN_SAVE) | SHUTDOWN_NOSAVE;\n    if (prepareForShutdown(flags) == C_OK) {\n        for (int j = 0; j < server.dbnum; j ++) {\n            for (int i = 0; i < HASH_SLOTS_SIZE; i ++) {\n                dictRelease(server.db[j].hash_slots[i]);\n            }\n            zslFree(server.db[j].tagged_keys);\n        }\n        exit(0);\n    }\n    addReplyError(c,\"Errors trying to SHUTDOWN. Check logs.\");\n}\n\nvoid renameGenericCommand(client *c, int nx) {\n    robj *o;\n    long long expire;\n    int samekey = 0;\n\n    /* When source and dest key is the same, no operation is performed,\n     * if the key exists, however we still return an error on unexisting key. */\n    if (sdscmp(c->argv[1]->ptr,c->argv[2]->ptr) == 0) samekey = 1;\n\n    if ((o = lookupKeyWriteOrReply(c,c->argv[1],shared.nokeyerr)) == NULL)\n        return;\n\n    if (samekey) {\n        addReply(c,nx ? shared.czero : shared.ok);\n        return;\n    }\n\n    incrRefCount(o);\n    expire = getExpire(c->db,c->argv[1]);\n    if (lookupKeyWrite(c->db,c->argv[2]) != NULL) {\n        if (nx) {\n            decrRefCount(o);\n            addReply(c,shared.czero);\n            return;\n        }\n        /* Overwrite: delete the old key before creating the new one\n         * with the same name. */\n        dbDelete(c->db,c->argv[2]);\n    }\n    dbAdd(c->db,c->argv[2],o);\n    if (expire != -1) setExpire(c->db,c->argv[2],expire);\n    dbDelete(c->db,c->argv[1]);\n    signalModifiedKey(c->db,c->argv[1]);\n    signalModifiedKey(c->db,c->argv[2]);\n    notifyKeyspaceEvent(NOTIFY_GENERIC,\"rename_from\",\n        c->argv[1],c->db->id);\n    notifyKeyspaceEvent(NOTIFY_GENERIC,\"rename_to\",\n        c->argv[2],c->db->id);\n    server.dirty++;\n    addReply(c,nx ? shared.cone : shared.ok);\n}\n\nvoid renameCommand(client *c) {\n    renameGenericCommand(c,0);\n}\n\nvoid renamenxCommand(client *c) {\n    renameGenericCommand(c,1);\n}\n\nvoid moveCommand(client *c) {\n    robj *o;\n    redisDb *src, *dst;\n    int srcid;\n    long long dbid, expire;\n\n    if (server.cluster_enabled) {\n        addReplyError(c,\"MOVE is not allowed in cluster mode\");\n        return;\n    }\n\n    /* Obtain source and target DB pointers */\n    src = c->db;\n    srcid = c->db->id;\n\n    if (getLongLongFromObject(c->argv[2],&dbid) == C_ERR ||\n        dbid < INT_MIN || dbid > INT_MAX ||\n        selectDb(c,dbid) == C_ERR)\n    {\n        addReply(c,shared.outofrangeerr);\n        return;\n    }\n    dst = c->db;\n    selectDb(c,srcid); /* Back to the source DB */\n\n    /* If the user is moving using as target the same\n     * DB as the source DB it is probably an error. */\n    if (src == dst) {\n        addReply(c,shared.sameobjecterr);\n        return;\n    }\n\n    /* Check if the element exists and get a reference */\n    o = lookupKeyWrite(c->db,c->argv[1]);\n    if (!o) {\n        addReply(c,shared.czero);\n        return;\n    }\n    expire = getExpire(c->db,c->argv[1]);\n\n    /* Return zero if the key already exists in the target DB */\n    if (lookupKeyWrite(dst,c->argv[1]) != NULL) {\n        addReply(c,shared.czero);\n        return;\n    }\n    dbAdd(dst,c->argv[1],o);\n    if (expire != -1) setExpire(dst,c->argv[1],expire);\n    incrRefCount(o);\n\n    /* OK! key moved, free the entry in the source DB */\n    dbDelete(src,c->argv[1]);\n    server.dirty++;\n    addReply(c,shared.cone);\n}\n\n/*-----------------------------------------------------------------------------\n * Expires API\n *----------------------------------------------------------------------------*/\n\nint removeExpire(redisDb *db, robj *key) {\n    /* An expire may only be removed if there is a corresponding entry in the\n     * main dict. Otherwise, the key will never be freed. */\n    serverAssertWithInfo(NULL,key,dictFind(db->dict,key->ptr) != NULL);\n    return dictDelete(db->expires,key->ptr) == DICT_OK;\n}\n\nvoid setExpire(redisDb *db, robj *key, long long when) {\n    dictEntry *kde, *de;\n\n    /* Reuse the sds from the main dict in the expire dict */\n    kde = dictFind(db->dict,key->ptr);\n    serverAssertWithInfo(NULL,key,kde != NULL);\n    de = dictReplaceRaw(db->expires,dictGetKey(kde));\n    dictSetSignedIntegerVal(de,when);\n}\n\n/* Return the expire time of the specified key, or -1 if no expire\n * is associated with this key (i.e. the key is non volatile) */\nlong long getExpire(redisDb *db, robj *key) {\n    dictEntry *de;\n\n    /* No expire? return ASAP */\n    if (dictSize(db->expires) == 0 ||\n       (de = dictFind(db->expires,key->ptr)) == NULL) return -1;\n\n    /* The entry was found in the expire dict, this means it should also\n     * be present in the main dict (safety check). */\n    serverAssertWithInfo(NULL,key,dictFind(db->dict,key->ptr) != NULL);\n    return dictGetSignedIntegerVal(de);\n}\n\n/* Propagate expires into slaves and the AOF file.\n * When a key expires in the master, a DEL operation for this key is sent\n * to all the slaves and the AOF file if enabled.\n *\n * This way the key expiry is centralized in one place, and since both\n * AOF and the master->slave link guarantee operation ordering, everything\n * will be consistent even if we allow write operations against expiring\n * keys. */\nvoid propagateExpire(redisDb *db, robj *key) {\n    robj *argv[2];\n\n    argv[0] = shared.del;\n    argv[1] = key;\n    incrRefCount(argv[0]);\n    incrRefCount(argv[1]);\n\n    if (server.aof_state != AOF_OFF)\n        feedAppendOnlyFile(server.delCommand,db->id,argv,2);\n    replicationFeedSlaves(server.slaves,db->id,argv,2);\n\n    decrRefCount(argv[0]);\n    decrRefCount(argv[1]);\n}\n\nint expireIfNeeded(redisDb *db, robj *key) {\n    mstime_t when = getExpire(db,key);\n    mstime_t now;\n\n    if (when < 0) return 0; /* No expire for this key */\n\n    /* Don't expire anything while loading. It will be done later. */\n    if (server.loading) return 0;\n\n    /* If we are in the context of a Lua script, we claim that time is\n     * blocked to when the Lua script started. This way a key can expire\n     * only the first time it is accessed and not in the middle of the\n     * script execution, making propagation to slaves / AOF consistent.\n     * See issue #1525 on Github for more information. */\n    now = server.lua_caller ? server.lua_time_start : mstime();\n\n    /* If we are running in the context of a slave, return ASAP:\n     * the slave key expiration is controlled by the master that will\n     * send us synthesized DEL operations for expired keys.\n     *\n     * Still we try to return the right information to the caller,\n     * that is, 0 if we think the key should be still valid, 1 if\n     * we think the key is expired at this time. */\n    if (server.masterhost != NULL) return now > when;\n\n    /* Return when this key has not expired */\n    if (now <= when) return 0;\n\n    /* Delete the key */\n    server.stat_expiredkeys++;\n    propagateExpire(db,key);\n    notifyKeyspaceEvent(NOTIFY_EXPIRED,\n        \"expired\",key,db->id);\n    return dbDelete(db,key);\n}\n\n/*-----------------------------------------------------------------------------\n * Expires Commands\n *----------------------------------------------------------------------------*/\n\n/* This is the generic command implementation for EXPIRE, PEXPIRE, EXPIREAT\n * and PEXPIREAT. Because the commad second argument may be relative or absolute\n * the \"basetime\" argument is used to signal what the base time is (either 0\n * for *AT variants of the command, or the current time for relative expires).\n *\n * unit is either UNIT_SECONDS or UNIT_MILLISECONDS, and is only used for\n * the argv[2] parameter. The basetime is always specified in milliseconds. */\nvoid expireGenericCommand(client *c, long long basetime, int unit) {\n    robj *key = c->argv[1], *param = c->argv[2];\n    long long when; /* unix time in milliseconds when the key will expire. */\n\n    if (getLongLongFromObjectOrReply(c, param, &when, NULL) != C_OK)\n        return;\n\n    if (unit == UNIT_SECONDS) when *= 1000;\n    when += basetime;\n\n    /* No key, return zero. */\n    if (lookupKeyWrite(c->db,key) == NULL) {\n        addReply(c,shared.czero);\n        return;\n    }\n\n    /* EXPIRE with negative TTL, or EXPIREAT with a timestamp into the past\n     * should never be executed as a DEL when load the AOF or in the context\n     * of a slave instance.\n     *\n     * Instead we take the other branch of the IF statement setting an expire\n     * (possibly in the past) and wait for an explicit DEL from the master. */\n    if (when <= mstime() && !server.loading && !server.masterhost) {\n        robj *aux;\n\n        serverAssertWithInfo(c,key,dbDelete(c->db,key));\n        server.dirty++;\n\n        /* Replicate/AOF this as an explicit DEL. */\n        aux = createStringObject(\"DEL\",3);\n        rewriteClientCommandVector(c,2,aux,key);\n        decrRefCount(aux);\n        signalModifiedKey(c->db,key);\n        notifyKeyspaceEvent(NOTIFY_GENERIC,\"del\",key,c->db->id);\n        addReply(c, shared.cone);\n        return;\n    } else {\n        setExpire(c->db,key,when);\n        addReply(c,shared.cone);\n        signalModifiedKey(c->db,key);\n        notifyKeyspaceEvent(NOTIFY_GENERIC,\"expire\",key,c->db->id);\n        server.dirty++;\n        return;\n    }\n}\n\nvoid expireCommand(client *c) {\n    expireGenericCommand(c,mstime(),UNIT_SECONDS);\n}\n\nvoid expireatCommand(client *c) {\n    expireGenericCommand(c,0,UNIT_SECONDS);\n}\n\nvoid pexpireCommand(client *c) {\n    expireGenericCommand(c,mstime(),UNIT_MILLISECONDS);\n}\n\nvoid pexpireatCommand(client *c) {\n    expireGenericCommand(c,0,UNIT_MILLISECONDS);\n}\n\nvoid ttlGenericCommand(client *c, int output_ms) {\n    long long expire, ttl = -1;\n\n    /* If the key does not exist at all, return -2 */\n    if (lookupKeyReadWithFlags(c->db,c->argv[1],LOOKUP_NOTOUCH) == NULL) {\n        addReplyLongLong(c,-2);\n        return;\n    }\n    /* The key exists. Return -1 if it has no expire, or the actual\n     * TTL value otherwise. */\n    expire = getExpire(c->db,c->argv[1]);\n    if (expire != -1) {\n        ttl = expire-mstime();\n        if (ttl < 0) ttl = 0;\n    }\n    if (ttl == -1) {\n        addReplyLongLong(c,-1);\n    } else {\n        addReplyLongLong(c,output_ms ? ttl : ((ttl+500)/1000));\n    }\n}\n\nvoid ttlCommand(client *c) {\n    ttlGenericCommand(c, 0);\n}\n\nvoid pttlCommand(client *c) {\n    ttlGenericCommand(c, 1);\n}\n\nvoid persistCommand(client *c) {\n    dictEntry *de;\n\n    de = dictFind(c->db->dict,c->argv[1]->ptr);\n    if (de == NULL) {\n        addReply(c,shared.czero);\n    } else {\n        if (removeExpire(c->db,c->argv[1])) {\n            addReply(c,shared.cone);\n            server.dirty++;\n        } else {\n            addReply(c,shared.czero);\n        }\n    }\n}\n\n/* TOUCH key1 [key2 key3 ... keyN] */\nvoid touchCommand(client *c) {\n    int touched = 0;\n    for (int j = 1; j < c->argc; j++)\n        if (lookupKeyRead(c->db,c->argv[j]) != NULL) touched++;\n    addReplyLongLong(c,touched);\n}\n\n/* -----------------------------------------------------------------------------\n * API to get key arguments from commands\n * ---------------------------------------------------------------------------*/\n\n/* The base case is to use the keys position as given in the command table\n * (firstkey, lastkey, step). */\nint *getKeysUsingCommandTable(struct redisCommand *cmd,robj **argv, int argc, int *numkeys) {\n    int j, i = 0, last, *keys;\n    UNUSED(argv);\n\n    if (cmd->firstkey == 0) {\n        *numkeys = 0;\n        return NULL;\n    }\n    last = cmd->lastkey;\n    if (last < 0) last = argc+last;\n    keys = zmalloc(sizeof(int)*((last - cmd->firstkey)+1));\n    for (j = cmd->firstkey; j <= last; j += cmd->keystep) {\n        serverAssert(j < argc);\n        keys[i++] = j;\n    }\n    *numkeys = i;\n    return keys;\n}\n\n/* Return all the arguments that are keys in the command passed via argc / argv.\n *\n * The command returns the positions of all the key arguments inside the array,\n * so the actual return value is an heap allocated array of integers. The\n * length of the array is returned by reference into *numkeys.\n *\n * 'cmd' must be point to the corresponding entry into the redisCommand\n * table, according to the command name in argv[0].\n *\n * This function uses the command table if a command-specific helper function\n * is not required, otherwise it calls the command-specific function. */\nint *getKeysFromCommand(struct redisCommand *cmd, robj **argv, int argc, int *numkeys) {\n    if (cmd->getkeys_proc) {\n        return cmd->getkeys_proc(cmd,argv,argc,numkeys);\n    } else {\n        return getKeysUsingCommandTable(cmd,argv,argc,numkeys);\n    }\n}\n\n/* Free the result of getKeysFromCommand. */\nvoid getKeysFreeResult(int *result) {\n    zfree(result);\n}\n\n/* Helper function to extract keys from following commands:\n * ZUNIONSTORE <destkey> <num-keys> <key> <key> ... <key> <options>\n * ZINTERSTORE <destkey> <num-keys> <key> <key> ... <key> <options> */\nint *zunionInterGetKeys(struct redisCommand *cmd, robj **argv, int argc, int *numkeys) {\n    int i, num, *keys;\n    UNUSED(cmd);\n\n    num = atoi(argv[2]->ptr);\n    /* Sanity check. Don't return any key if the command is going to\n     * reply with syntax error. */\n    if (num > (argc-3)) {\n        *numkeys = 0;\n        return NULL;\n    }\n\n    /* Keys in z{union,inter}store come from two places:\n     * argv[1] = storage key,\n     * argv[3...n] = keys to intersect */\n    keys = zmalloc(sizeof(int)*(num+1));\n\n    /* Add all key positions for argv[3...n] to keys[] */\n    for (i = 0; i < num; i++) keys[i] = 3+i;\n\n    /* Finally add the argv[1] key position (the storage key target). */\n    keys[num] = 1;\n    *numkeys = num+1;  /* Total keys = {union,inter} keys + storage key */\n    return keys;\n}\n\n/* Helper function to extract keys from the following commands:\n * EVAL <script> <num-keys> <key> <key> ... <key> [more stuff]\n * EVALSHA <script> <num-keys> <key> <key> ... <key> [more stuff] */\nint *evalGetKeys(struct redisCommand *cmd, robj **argv, int argc, int *numkeys) {\n    int i, num, *keys;\n    UNUSED(cmd);\n\n    num = atoi(argv[2]->ptr);\n    /* Sanity check. Don't return any key if the command is going to\n     * reply with syntax error. */\n    if (num > (argc-3)) {\n        *numkeys = 0;\n        return NULL;\n    }\n\n    keys = zmalloc(sizeof(int)*num);\n    *numkeys = num;\n\n    /* Add all key positions for argv[3...n] to keys[] */\n    for (i = 0; i < num; i++) keys[i] = 3+i;\n\n    return keys;\n}\n\n/* Helper function to extract keys from the SORT command.\n *\n * SORT <sort-key> ... STORE <store-key> ...\n *\n * The first argument of SORT is always a key, however a list of options\n * follow in SQL-alike style. Here we parse just the minimum in order to\n * correctly identify keys in the \"STORE\" option. */\nint *sortGetKeys(struct redisCommand *cmd, robj **argv, int argc, int *numkeys) {\n    int i, j, num, *keys, found_store = 0;\n    UNUSED(cmd);\n\n    num = 0;\n    keys = zmalloc(sizeof(int)*2); /* Alloc 2 places for the worst case. */\n\n    keys[num++] = 1; /* <sort-key> is always present. */\n\n    /* Search for STORE option. By default we consider options to don't\n     * have arguments, so if we find an unknown option name we scan the\n     * next. However there are options with 1 or 2 arguments, so we\n     * provide a list here in order to skip the right number of args. */\n    struct {\n        char *name;\n        int skip;\n    } skiplist[] = {\n        {\"limit\", 2},\n        {\"get\", 1},\n        {\"by\", 1},\n        {NULL, 0} /* End of elements. */\n    };\n\n    for (i = 2; i < argc; i++) {\n        for (j = 0; skiplist[j].name != NULL; j++) {\n            if (!strcasecmp(argv[i]->ptr,skiplist[j].name)) {\n                i += skiplist[j].skip;\n                break;\n            } else if (!strcasecmp(argv[i]->ptr,\"store\") && i+1 < argc) {\n                /* Note: we don't increment \"num\" here and continue the loop\n                 * to be sure to process the *last* \"STORE\" option if multiple\n                 * ones are provided. This is same behavior as SORT. */\n                found_store = 1;\n                keys[num] = i+1; /* <store-key> */\n                break;\n            }\n        }\n    }\n    *numkeys = num + found_store;\n    return keys;\n}\n\nint *migrateGetKeys(struct redisCommand *cmd, robj **argv, int argc, int *numkeys) {\n    int i, num, first, *keys;\n    UNUSED(cmd);\n\n    /* Assume the obvious form. */\n    first = 3;\n    num = 1;\n\n    /* But check for the extended one with the KEYS option. */\n    if (argc > 6) {\n        for (i = 6; i < argc; i++) {\n            if (!strcasecmp(argv[i]->ptr,\"keys\") &&\n                sdslen(argv[3]->ptr) == 0)\n            {\n                first = i+1;\n                num = argc-first;\n                break;\n            }\n        }\n    }\n\n    keys = zmalloc(sizeof(int)*num);\n    for (i = 0; i < num; i++) keys[i] = first+i;\n    *numkeys = num;\n    return keys;\n}\n\n/* Slot to Key API. This is used by Redis Cluster in order to obtain in\n * a fast way a key that belongs to a specified hash slot. This is useful\n * while rehashing the cluster. */\nvoid slotToKeyAdd(robj *key) {\n    unsigned int hashslot = keyHashSlot(key->ptr,sdslen(key->ptr));\n\n    zslInsert(server.cluster->slots_to_keys,hashslot,key);\n    incrRefCount(key);\n}\n\nvoid slotToKeyDel(robj *key) {\n    unsigned int hashslot = keyHashSlot(key->ptr,sdslen(key->ptr));\n\n    zslDelete(server.cluster->slots_to_keys,hashslot,key);\n}\n\nvoid slotToKeyFlush(void) {\n    zslFree(server.cluster->slots_to_keys);\n    server.cluster->slots_to_keys = zslCreate();\n}\n\nunsigned int getKeysInSlot(unsigned int hashslot, robj **keys, unsigned int count) {\n    zskiplistNode *n;\n    zrangespec range;\n    int j = 0;\n\n    range.min = range.max = hashslot;\n    range.minex = range.maxex = 0;\n\n    n = zslFirstInRange(server.cluster->slots_to_keys, &range);\n    while(n && n->score == hashslot && count--) {\n        keys[j++] = n->obj;\n        n = n->level[0].forward;\n    }\n    return j;\n}\n\n/* Remove all the keys in the specified hash slot.\n * The number of removed items is returned. */\nunsigned int delKeysInSlot(unsigned int hashslot) {\n    zskiplistNode *n;\n    zrangespec range;\n    int j = 0;\n\n    range.min = range.max = hashslot;\n    range.minex = range.maxex = 0;\n\n    n = zslFirstInRange(server.cluster->slots_to_keys, &range);\n    while(n && n->score == hashslot) {\n        robj *key = n->obj;\n        n = n->level[0].forward; /* Go to the next item before freeing it. */\n        incrRefCount(key); /* Protect the object while freeing it. */\n        dbDelete(&server.db[0],key);\n        decrRefCount(key);\n        j++;\n    }\n    return j;\n}\n\nunsigned int countKeysInSlot(unsigned int hashslot) {\n    zskiplist *zsl = server.cluster->slots_to_keys;\n    zskiplistNode *zn;\n    zrangespec range;\n    int rank, count = 0;\n\n    range.min = range.max = hashslot;\n    range.minex = range.maxex = 0;\n\n    /* Find first element in range */\n    zn = zslFirstInRange(zsl, &range);\n\n    /* Use rank of first element, if any, to determine preliminary count */\n    if (zn != NULL) {\n        rank = zslGetRank(zsl, zn->score, zn->obj);\n        count = (zsl->length - (rank - 1));\n\n        /* Find last element in range */\n        zn = zslLastInRange(zsl, &range);\n\n        /* Use rank of last element, if any, to determine the actual count */\n        if (zn != NULL) {\n            rank = zslGetRank(zsl, zn->score, zn->obj);\n            count -= (zsl->length - rank);\n        }\n    }\n    return count;\n}\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/src/debug.c",
    "content": "/*\n * Copyright (c) 2009-2012, Salvatore Sanfilippo <antirez at gmail dot com>\n * All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions are met:\n *\n *   * Redistributions of source code must retain the above copyright notice,\n *     this list of conditions and the following disclaimer.\n *   * Redistributions in binary form must reproduce the above copyright\n *     notice, this list of conditions and the following disclaimer in the\n *     documentation and/or other materials provided with the distribution.\n *   * Neither the name of Redis nor the names of its contributors may be used\n *     to endorse or promote products derived from this software without\n *     specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\"\n * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\n * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE\n * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR\n * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF\n * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS\n * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN\n * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)\n * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE\n * POSSIBILITY OF SUCH DAMAGE.\n */\n\n#include \"server.h\"\n#include \"sha1.h\"   /* SHA1 is used for DEBUG DIGEST */\n#include \"crc64.h\"\n\n#include <arpa/inet.h>\n#include <signal.h>\n\n#ifdef HAVE_BACKTRACE\n#include <execinfo.h>\n#include <ucontext.h>\n#include <fcntl.h>\n#include \"bio.h\"\n#include <unistd.h>\n#include <dlfcn.h>\n#endif /* HAVE_BACKTRACE */\n\n#ifdef __CYGWIN__\n#ifndef SA_ONSTACK\n#define SA_ONSTACK 0x08000000\n#endif\n#endif\n\n/* ================================= Debugging ============================== */\n\n/* Compute the sha1 of string at 's' with 'len' bytes long.\n * The SHA1 is then xored against the string pointed by digest.\n * Since xor is commutative, this operation is used in order to\n * \"add\" digests relative to unordered elements.\n *\n * So digest(a,b,c,d) will be the same of digest(b,a,c,d) */\nvoid xorDigest(unsigned char *digest, void *ptr, size_t len) {\n    SHA1_CTX ctx;\n    unsigned char hash[20], *s = ptr;\n    int j;\n\n    SHA1Init(&ctx);\n    SHA1Update(&ctx,s,len);\n    SHA1Final(hash,&ctx);\n\n    for (j = 0; j < 20; j++)\n        digest[j] ^= hash[j];\n}\n\nvoid xorObjectDigest(unsigned char *digest, robj *o) {\n    o = getDecodedObject(o);\n    xorDigest(digest,o->ptr,sdslen(o->ptr));\n    decrRefCount(o);\n}\n\n/* This function instead of just computing the SHA1 and xoring it\n * against digest, also perform the digest of \"digest\" itself and\n * replace the old value with the new one.\n *\n * So the final digest will be:\n *\n * digest = SHA1(digest xor SHA1(data))\n *\n * This function is used every time we want to preserve the order so\n * that digest(a,b,c,d) will be different than digest(b,c,d,a)\n *\n * Also note that mixdigest(\"foo\") followed by mixdigest(\"bar\")\n * will lead to a different digest compared to \"fo\", \"obar\".\n */\nvoid mixDigest(unsigned char *digest, void *ptr, size_t len) {\n    SHA1_CTX ctx;\n    char *s = ptr;\n\n    xorDigest(digest,s,len);\n    SHA1Init(&ctx);\n    SHA1Update(&ctx,digest,20);\n    SHA1Final(digest,&ctx);\n}\n\nvoid mixObjectDigest(unsigned char *digest, robj *o) {\n    o = getDecodedObject(o);\n    mixDigest(digest,o->ptr,sdslen(o->ptr));\n    decrRefCount(o);\n}\n\n/* Compute the dataset digest. Since keys, sets elements, hashes elements\n * are not ordered, we use a trick: every aggregate digest is the xor\n * of the digests of their elements. This way the order will not change\n * the result. For list instead we use a feedback entering the output digest\n * as input in order to ensure that a different ordered list will result in\n * a different digest. */\nvoid computeDatasetDigest(unsigned char *final) {\n    unsigned char digest[20];\n    char buf[128];\n    dictIterator *di = NULL;\n    dictEntry *de;\n    int j;\n    uint32_t aux;\n\n    memset(final,0,20); /* Start with a clean result */\n\n    for (j = 0; j < server.dbnum; j++) {\n        redisDb *db = server.db+j;\n\n        if (dictSize(db->dict) == 0) continue;\n        di = dictGetIterator(db->dict);\n\n        /* hash the DB id, so the same dataset moved in a different\n         * DB will lead to a different digest */\n        aux = htonl(j);\n        mixDigest(final,&aux,sizeof(aux));\n\n        /* Iterate this DB writing every entry */\n        while((de = dictNext(di)) != NULL) {\n            sds key;\n            robj *keyobj, *o;\n            long long expiretime;\n\n            memset(digest,0,20); /* This key-val digest */\n            key = dictGetKey(de);\n            keyobj = createStringObject(key,sdslen(key));\n\n            mixDigest(digest,key,sdslen(key));\n\n            o = dictGetVal(de);\n\n            aux = htonl(o->type);\n            mixDigest(digest,&aux,sizeof(aux));\n            expiretime = getExpire(db,keyobj);\n\n            /* Save the key and associated value */\n            if (o->type == OBJ_STRING) {\n                mixObjectDigest(digest,o);\n            } else if (o->type == OBJ_LIST) {\n                listTypeIterator *li = listTypeInitIterator(o,0,LIST_TAIL);\n                listTypeEntry entry;\n                while(listTypeNext(li,&entry)) {\n                    robj *eleobj = listTypeGet(&entry);\n                    mixObjectDigest(digest,eleobj);\n                    decrRefCount(eleobj);\n                }\n                listTypeReleaseIterator(li);\n            } else if (o->type == OBJ_SET) {\n                setTypeIterator *si = setTypeInitIterator(o);\n                robj *ele;\n                while((ele = setTypeNextObject(si)) != NULL) {\n                    xorObjectDigest(digest,ele);\n                    decrRefCount(ele);\n                }\n                setTypeReleaseIterator(si);\n            } else if (o->type == OBJ_ZSET) {\n                unsigned char eledigest[20];\n\n                if (o->encoding == OBJ_ENCODING_ZIPLIST) {\n                    unsigned char *zl = o->ptr;\n                    unsigned char *eptr, *sptr;\n                    unsigned char *vstr;\n                    unsigned int vlen;\n                    long long vll;\n                    double score;\n\n                    eptr = ziplistIndex(zl,0);\n                    serverAssert(eptr != NULL);\n                    sptr = ziplistNext(zl,eptr);\n                    serverAssert(sptr != NULL);\n\n                    while (eptr != NULL) {\n                        serverAssert(ziplistGet(eptr,&vstr,&vlen,&vll));\n                        score = zzlGetScore(sptr);\n\n                        memset(eledigest,0,20);\n                        if (vstr != NULL) {\n                            mixDigest(eledigest,vstr,vlen);\n                        } else {\n                            ll2string(buf,sizeof(buf),vll);\n                            mixDigest(eledigest,buf,strlen(buf));\n                        }\n\n                        snprintf(buf,sizeof(buf),\"%.17g\",score);\n                        mixDigest(eledigest,buf,strlen(buf));\n                        xorDigest(digest,eledigest,20);\n                        zzlNext(zl,&eptr,&sptr);\n                    }\n                } else if (o->encoding == OBJ_ENCODING_SKIPLIST) {\n                    zset *zs = o->ptr;\n                    dictIterator *di = dictGetIterator(zs->dict);\n                    dictEntry *de;\n\n                    while((de = dictNext(di)) != NULL) {\n                        robj *eleobj = dictGetKey(de);\n                        double *score = dictGetVal(de);\n\n                        snprintf(buf,sizeof(buf),\"%.17g\",*score);\n                        memset(eledigest,0,20);\n                        mixObjectDigest(eledigest,eleobj);\n                        mixDigest(eledigest,buf,strlen(buf));\n                        xorDigest(digest,eledigest,20);\n                    }\n                    dictReleaseIterator(di);\n                } else {\n                    serverPanic(\"Unknown sorted set encoding\");\n                }\n            } else if (o->type == OBJ_HASH) {\n                hashTypeIterator *hi;\n                robj *obj;\n\n                hi = hashTypeInitIterator(o);\n                while (hashTypeNext(hi) != C_ERR) {\n                    unsigned char eledigest[20];\n\n                    memset(eledigest,0,20);\n                    obj = hashTypeCurrentObject(hi,OBJ_HASH_KEY);\n                    mixObjectDigest(eledigest,obj);\n                    decrRefCount(obj);\n                    obj = hashTypeCurrentObject(hi,OBJ_HASH_VALUE);\n                    mixObjectDigest(eledigest,obj);\n                    decrRefCount(obj);\n                    xorDigest(digest,eledigest,20);\n                }\n                hashTypeReleaseIterator(hi);\n            } else {\n                serverPanic(\"Unknown object type\");\n            }\n            /* If the key has an expire, add it to the mix */\n            if (expiretime != -1) xorDigest(digest,\"!!expire!!\",10);\n            /* We can finally xor the key-val digest to the final digest */\n            xorDigest(final,digest,20);\n            decrRefCount(keyobj);\n        }\n        dictReleaseIterator(di);\n    }\n}\n\n#if defined(USE_JEMALLOC)\nvoid inputCatSds(void *result, const char *str) {\n    /* result is actually a (sds *), so re-cast it here */\n    sds *info = (sds *)result;\n    *info = sdscat(*info, str);\n}\n#endif\n\nvoid debugCommand(client *c) {\n    if (c->argc == 1) {\n        addReplyError(c,\"You must specify a subcommand for DEBUG. Try DEBUG HELP for info.\");\n        return;\n    }\n\n    if (!strcasecmp(c->argv[1]->ptr,\"help\")) {\n        void *blenp = addDeferredMultiBulkLength(c);\n        int blen = 0;\n        blen++; addReplyStatus(c,\n        \"DEBUG <subcommand> arg arg ... arg. Subcommands:\");\n        blen++; addReplyStatus(c,\n        \"segfault -- Crash the server with sigsegv.\");\n        blen++; addReplyStatus(c,\n        \"restart  -- Graceful restart: save config, db, restart.\");\n        blen++; addReplyStatus(c,\n        \"crash-and-recovery <milliseconds> -- Hard crash and restart after <milliseconds> delay.\");\n        blen++; addReplyStatus(c,\n        \"assert   -- Crash by assertion failed.\");\n        blen++; addReplyStatus(c,\n        \"reload   -- Save the RDB on disk and reload it back in memory.\");\n        blen++; addReplyStatus(c,\n        \"loadaof  -- Flush the AOF buffers on disk and reload the AOF in memory.\");\n        blen++; addReplyStatus(c,\n        \"object <key> -- Show low level info about key and associated value.\");\n        blen++; addReplyStatus(c,\n        \"sdslen <key> -- Show low level SDS string info representing key and value.\");\n        blen++; addReplyStatus(c,\n        \"populate <count> [prefix] -- Create <count> string keys named key:<num>. If a prefix is specified is used instead of the 'key' prefix.\");\n        blen++; addReplyStatus(c,\n        \"digest   -- Outputs an hex signature representing the current DB content.\");\n        blen++; addReplyStatus(c,\n        \"sleep <seconds> -- Stop the server for <seconds>. Decimals allowed.\");\n        blen++; addReplyStatus(c,\n        \"set-active-expire (0|1) -- Setting it to 0 disables expiring keys in background when they are not accessed (otherwise the Redis behavior). Setting it to 1 reenables back the default.\");\n        blen++; addReplyStatus(c,\n        \"lua-always-replicate-commands (0|1) -- Setting it to 1 makes Lua replication defaulting to replicating single commands, without the script having to enable effects replication.\");\n        blen++; addReplyStatus(c,\n        \"error <string> -- Return a Redis protocol error with <string> as message. Useful for clients unit tests to simulate Redis errors.\");\n        blen++; addReplyStatus(c,\n        \"structsize -- Return the size of different Redis core C structures.\");\n        blen++; addReplyStatus(c,\n        \"htstats <dbid> -- Return hash table statistics of the specified Redis database.\");\n        blen++; addReplyStatus(c,\n        \"jemalloc info  -- Show internal jemalloc statistics.\");\n        blen++; addReplyStatus(c,\n        \"jemalloc purge -- Force jemalloc to release unused memory.\");\n        setDeferredMultiBulkLength(c,blenp,blen);\n    } else if (!strcasecmp(c->argv[1]->ptr,\"segfault\")) {\n        *((char*)-1) = 'x';\n    } else if (!strcasecmp(c->argv[1]->ptr,\"restart\") ||\n               !strcasecmp(c->argv[1]->ptr,\"crash-and-recover\"))\n    {\n        long long delay = 0;\n        if (c->argc >= 3) {\n            if (getLongLongFromObjectOrReply(c, c->argv[2], &delay, NULL)\n                != C_OK) return;\n            if (delay < 0) delay = 0;\n        }\n        int flags = !strcasecmp(c->argv[1]->ptr,\"restart\") ?\n            (RESTART_SERVER_GRACEFULLY|RESTART_SERVER_CONFIG_REWRITE) :\n             RESTART_SERVER_NONE;\n        restartServer(flags,delay);\n        addReplyError(c,\"failed to restart the server. Check server logs.\");\n    } else if (!strcasecmp(c->argv[1]->ptr,\"oom\")) {\n        void *ptr = zmalloc(ULONG_MAX); /* Should trigger an out of memory. */\n        zfree(ptr);\n        addReply(c,shared.ok);\n    } else if (!strcasecmp(c->argv[1]->ptr,\"assert\")) {\n        if (c->argc >= 3) c->argv[2] = tryObjectEncoding(c->argv[2]);\n        serverAssertWithInfo(c,c->argv[0],1 == 2);\n    } else if (!strcasecmp(c->argv[1]->ptr,\"reload\")) {\n        if (rdbSave(server.rdb_filename) != C_OK) {\n            addReply(c,shared.err);\n            return;\n        }\n        emptyDb(NULL);\n        if (rdbLoad(server.rdb_filename) != C_OK) {\n            addReplyError(c,\"Error trying to load the RDB dump\");\n            return;\n        }\n        serverLog(LL_WARNING,\"DB reloaded by DEBUG RELOAD\");\n        addReply(c,shared.ok);\n    } else if (!strcasecmp(c->argv[1]->ptr,\"loadaof\")) {\n        if (server.aof_state == AOF_ON) flushAppendOnlyFile(1);\n        emptyDb(NULL);\n        if (loadAppendOnlyFile(server.aof_filename) != C_OK) {\n            addReply(c,shared.err);\n            return;\n        }\n        server.dirty = 0; /* Prevent AOF / replication */\n        serverLog(LL_WARNING,\"Append Only File loaded by DEBUG LOADAOF\");\n        addReply(c,shared.ok);\n    } else if (!strcasecmp(c->argv[1]->ptr,\"object\") && c->argc == 3) {\n        dictEntry *de;\n        robj *val;\n        char *strenc;\n\n        if ((de = dictFind(c->db->dict,c->argv[2]->ptr)) == NULL) {\n            addReply(c,shared.nokeyerr);\n            return;\n        }\n        val = dictGetVal(de);\n        strenc = strEncoding(val->encoding);\n\n        char extra[128] = {0};\n        if (val->encoding == OBJ_ENCODING_QUICKLIST) {\n            char *nextra = extra;\n            int remaining = sizeof(extra);\n            quicklist *ql = val->ptr;\n            /* Add number of quicklist nodes */\n            int used = snprintf(nextra, remaining, \" ql_nodes:%u\", ql->len);\n            nextra += used;\n            remaining -= used;\n            /* Add average quicklist fill factor */\n            double avg = (double)ql->count/ql->len;\n            used = snprintf(nextra, remaining, \" ql_avg_node:%.2f\", avg);\n            nextra += used;\n            remaining -= used;\n            /* Add quicklist fill level / max ziplist size */\n            used = snprintf(nextra, remaining, \" ql_ziplist_max:%d\", ql->fill);\n            nextra += used;\n            remaining -= used;\n            /* Add isCompressed? */\n            int compressed = ql->compress != 0;\n            used = snprintf(nextra, remaining, \" ql_compressed:%d\", compressed);\n            nextra += used;\n            remaining -= used;\n            /* Add total uncompressed size */\n            unsigned long sz = 0;\n            for (quicklistNode *node = ql->head; node; node = node->next) {\n                sz += node->sz;\n            }\n            used = snprintf(nextra, remaining, \" ql_uncompressed_size:%lu\", sz);\n            nextra += used;\n            remaining -= used;\n        }\n\n        addReplyStatusFormat(c,\n            \"Value at:%p refcount:%d \"\n            \"encoding:%s serializedlength:%zu \"\n            \"lru:%d lru_seconds_idle:%llu%s\",\n            (void*)val, val->refcount,\n            strenc, rdbSavedObjectLen(val),\n            val->lru, estimateObjectIdleTime(val)/1000, extra);\n    } else if (!strcasecmp(c->argv[1]->ptr,\"sdslen\") && c->argc == 3) {\n        dictEntry *de;\n        robj *val;\n        sds key;\n\n        if ((de = dictFind(c->db->dict,c->argv[2]->ptr)) == NULL) {\n            addReply(c,shared.nokeyerr);\n            return;\n        }\n        val = dictGetVal(de);\n        key = dictGetKey(de);\n\n        if (val->type != OBJ_STRING || !sdsEncodedObject(val)) {\n            addReplyError(c,\"Not an sds encoded string.\");\n        } else {\n            addReplyStatusFormat(c,\n                \"key_sds_len:%lld, key_sds_avail:%lld, \"\n                \"val_sds_len:%lld, val_sds_avail:%lld\",\n                (long long) sdslen(key),\n                (long long) sdsavail(key),\n                (long long) sdslen(val->ptr),\n                (long long) sdsavail(val->ptr));\n        }\n    } else if (!strcasecmp(c->argv[1]->ptr,\"populate\") &&\n               (c->argc == 3 || c->argc == 4)) {\n        long keys, j;\n        robj *key, *val;\n        char buf[128];\n\n        if (getLongFromObjectOrReply(c, c->argv[2], &keys, NULL) != C_OK)\n            return;\n        dictExpand(c->db->dict,keys);\n        for (j = 0; j < keys; j++) {\n            snprintf(buf,sizeof(buf),\"%s:%lu\",\n                (c->argc == 3) ? \"key\" : (char*)c->argv[3]->ptr, j);\n            key = createStringObject(buf,strlen(buf));\n            if (lookupKeyWrite(c->db,key) != NULL) {\n                decrRefCount(key);\n                continue;\n            }\n            snprintf(buf,sizeof(buf),\"value:%lu\",j);\n            val = createStringObject(buf,strlen(buf));\n            dbAdd(c->db,key,val);\n            signalModifiedKey(c->db,key);\n            decrRefCount(key);\n        }\n        addReply(c,shared.ok);\n    } else if (!strcasecmp(c->argv[1]->ptr,\"digest\") && c->argc == 2) {\n        unsigned char digest[20];\n        sds d = sdsempty();\n        int j;\n\n        computeDatasetDigest(digest);\n        for (j = 0; j < 20; j++)\n            d = sdscatprintf(d, \"%02x\",digest[j]);\n        addReplyStatus(c,d);\n        sdsfree(d);\n    } else if (!strcasecmp(c->argv[1]->ptr,\"sleep\") && c->argc == 3) {\n        double dtime = strtod(c->argv[2]->ptr,NULL);\n        long long utime = dtime*1000000;\n        struct timespec tv;\n\n        tv.tv_sec = utime / 1000000;\n        tv.tv_nsec = (utime % 1000000) * 1000;\n        nanosleep(&tv, NULL);\n        addReply(c,shared.ok);\n    } else if (!strcasecmp(c->argv[1]->ptr,\"set-active-expire\") &&\n               c->argc == 3)\n    {\n        server.active_expire_enabled = atoi(c->argv[2]->ptr);\n        addReply(c,shared.ok);\n    } else if (!strcasecmp(c->argv[1]->ptr,\"lua-always-replicate-commands\") &&\n               c->argc == 3)\n    {\n        server.lua_always_replicate_commands = atoi(c->argv[2]->ptr);\n        addReply(c,shared.ok);\n    } else if (!strcasecmp(c->argv[1]->ptr,\"error\") && c->argc == 3) {\n        sds errstr = sdsnewlen(\"-\",1);\n\n        errstr = sdscatsds(errstr,c->argv[2]->ptr);\n        errstr = sdsmapchars(errstr,\"\\n\\r\",\"  \",2); /* no newlines in errors. */\n        errstr = sdscatlen(errstr,\"\\r\\n\",2);\n        addReplySds(c,errstr);\n    } else if (!strcasecmp(c->argv[1]->ptr,\"structsize\") && c->argc == 2) {\n        sds sizes = sdsempty();\n        sizes = sdscatprintf(sizes,\"bits:%d \",(sizeof(void*) == 8)?64:32);\n        sizes = sdscatprintf(sizes,\"robj:%d \",(int)sizeof(robj));\n        sizes = sdscatprintf(sizes,\"dictentry:%d \",(int)sizeof(dictEntry));\n        sizes = sdscatprintf(sizes,\"sdshdr5:%d \",(int)sizeof(struct sdshdr5));\n        sizes = sdscatprintf(sizes,\"sdshdr8:%d \",(int)sizeof(struct sdshdr8));\n        sizes = sdscatprintf(sizes,\"sdshdr16:%d \",(int)sizeof(struct sdshdr16));\n        sizes = sdscatprintf(sizes,\"sdshdr32:%d \",(int)sizeof(struct sdshdr32));\n        sizes = sdscatprintf(sizes,\"sdshdr64:%d \",(int)sizeof(struct sdshdr64));\n        addReplyBulkSds(c,sizes);\n    } else if (!strcasecmp(c->argv[1]->ptr,\"htstats\") && c->argc == 3) {\n        long dbid;\n        sds stats = sdsempty();\n        char buf[4096];\n\n        if (getLongFromObjectOrReply(c, c->argv[2], &dbid, NULL) != C_OK)\n            return;\n        if (dbid < 0 || dbid >= server.dbnum) {\n            addReplyError(c,\"Out of range database\");\n            return;\n        }\n\n        stats = sdscatprintf(stats,\"[Dictionary HT]\\n\");\n        dictGetStats(buf,sizeof(buf),server.db[dbid].dict);\n        stats = sdscat(stats,buf);\n\n        stats = sdscatprintf(stats,\"[Expires HT]\\n\");\n        dictGetStats(buf,sizeof(buf),server.db[dbid].expires);\n        stats = sdscat(stats,buf);\n\n        addReplyBulkSds(c,stats);\n    } else if (!strcasecmp(c->argv[1]->ptr,\"jemalloc\") && c->argc == 3) {\n#if defined(USE_JEMALLOC)\n        if (!strcasecmp(c->argv[2]->ptr, \"info\")) {\n            sds info = sdsempty();\n            je_malloc_stats_print(inputCatSds, &info, NULL);\n            addReplyBulkSds(c, info);\n        } else if (!strcasecmp(c->argv[2]->ptr, \"purge\")) {\n            char tmp[32];\n            unsigned narenas = 0;\n            size_t sz = sizeof(unsigned);\n            if (!je_mallctl(\"arenas.narenas\", &narenas, &sz, NULL, 0)) {\n                sprintf(tmp, \"arena.%d.purge\", narenas);\n                if (!je_mallctl(tmp, NULL, 0, NULL, 0)) {\n                    addReply(c, shared.ok);\n                    return;\n                }\n            }\n            addReplyError(c, \"Error purging dirty pages\");\n        } else {\n            addReplyErrorFormat(c, \"Valid jemalloc debug fields: info, purge\");\n        }\n#else\n        addReplyErrorFormat(c, \"jemalloc support not available\");\n#endif\n    } else {\n        addReplyErrorFormat(c, \"Unknown DEBUG subcommand or wrong number of arguments for '%s'\",\n            (char*)c->argv[1]->ptr);\n    }\n}\n\n/* =========================== Crash handling  ============================== */\n\nvoid _serverAssert(char *estr, char *file, int line) {\n    bugReportStart();\n    serverLog(LL_WARNING,\"=== ASSERTION FAILED ===\");\n    serverLog(LL_WARNING,\"==> %s:%d '%s' is not true\",file,line,estr);\n#ifdef HAVE_BACKTRACE\n    server.assert_failed = estr;\n    server.assert_file = file;\n    server.assert_line = line;\n    serverLog(LL_WARNING,\"(forcing SIGSEGV to print the bug report.)\");\n#endif\n    *((char*)-1) = 'x';\n}\n\nvoid _serverAssertPrintClientInfo(client *c) {\n    int j;\n\n    bugReportStart();\n    serverLog(LL_WARNING,\"=== ASSERTION FAILED CLIENT CONTEXT ===\");\n    serverLog(LL_WARNING,\"client->flags = %d\", c->flags);\n    serverLog(LL_WARNING,\"client->fd = %d\", c->fd);\n    serverLog(LL_WARNING,\"client->argc = %d\", c->argc);\n    for (j=0; j < c->argc; j++) {\n        char buf[128];\n        char *arg;\n\n        if (c->argv[j]->type == OBJ_STRING && sdsEncodedObject(c->argv[j])) {\n            arg = (char*) c->argv[j]->ptr;\n        } else {\n            snprintf(buf,sizeof(buf),\"Object type: %u, encoding: %u\",\n                c->argv[j]->type, c->argv[j]->encoding);\n            arg = buf;\n        }\n        serverLog(LL_WARNING,\"client->argv[%d] = \\\"%s\\\" (refcount: %d)\",\n            j, arg, c->argv[j]->refcount);\n    }\n}\n\nvoid serverLogObjectDebugInfo(robj *o) {\n    serverLog(LL_WARNING,\"Object type: %d\", o->type);\n    serverLog(LL_WARNING,\"Object encoding: %d\", o->encoding);\n    serverLog(LL_WARNING,\"Object refcount: %d\", o->refcount);\n    if (o->type == OBJ_STRING && sdsEncodedObject(o)) {\n        serverLog(LL_WARNING,\"Object raw string len: %zu\", sdslen(o->ptr));\n        if (sdslen(o->ptr) < 4096) {\n            sds repr = sdscatrepr(sdsempty(),o->ptr,sdslen(o->ptr));\n            serverLog(LL_WARNING,\"Object raw string content: %s\", repr);\n            sdsfree(repr);\n        }\n    } else if (o->type == OBJ_LIST) {\n        serverLog(LL_WARNING,\"List length: %d\", (int) listTypeLength(o));\n    } else if (o->type == OBJ_SET) {\n        serverLog(LL_WARNING,\"Set size: %d\", (int) setTypeSize(o));\n    } else if (o->type == OBJ_HASH) {\n        serverLog(LL_WARNING,\"Hash size: %d\", (int) hashTypeLength(o));\n    } else if (o->type == OBJ_ZSET) {\n        serverLog(LL_WARNING,\"Sorted set size: %d\", (int) zsetLength(o));\n        if (o->encoding == OBJ_ENCODING_SKIPLIST)\n            serverLog(LL_WARNING,\"Skiplist level: %d\", (int) ((zset*)o->ptr)->zsl->level);\n    }\n}\n\nvoid _serverAssertPrintObject(robj *o) {\n    bugReportStart();\n    serverLog(LL_WARNING,\"=== ASSERTION FAILED OBJECT CONTEXT ===\");\n    serverLogObjectDebugInfo(o);\n}\n\nvoid _serverAssertWithInfo(client *c, robj *o, char *estr, char *file, int line) {\n    if (c) _serverAssertPrintClientInfo(c);\n    if (o) _serverAssertPrintObject(o);\n    _serverAssert(estr,file,line);\n}\n\nvoid _serverPanic(char *msg, char *file, int line) {\n    bugReportStart();\n    serverLog(LL_WARNING,\"------------------------------------------------\");\n    serverLog(LL_WARNING,\"!!! Software Failure. Press left mouse button to continue\");\n    serverLog(LL_WARNING,\"Guru Meditation: %s #%s:%d\",msg,file,line);\n#ifdef HAVE_BACKTRACE\n    serverLog(LL_WARNING,\"(forcing SIGSEGV in order to print the stack trace)\");\n#endif\n    serverLog(LL_WARNING,\"------------------------------------------------\");\n    *((char*)-1) = 'x';\n}\n\nvoid bugReportStart(void) {\n    if (server.bug_report_start == 0) {\n        serverLogRaw(LL_WARNING|LL_RAW,\n        \"\\n\\n=== REDIS BUG REPORT START: Cut & paste starting from here ===\\n\");\n        server.bug_report_start = 1;\n    }\n}\n\n#ifdef HAVE_BACKTRACE\nstatic void *getMcontextEip(ucontext_t *uc) {\n#if defined(__APPLE__) && !defined(MAC_OS_X_VERSION_10_6)\n    /* OSX < 10.6 */\n    #if defined(__x86_64__)\n    return (void*) uc->uc_mcontext->__ss.__rip;\n    #elif defined(__i386__)\n    return (void*) uc->uc_mcontext->__ss.__eip;\n    #else\n    return (void*) uc->uc_mcontext->__ss.__srr0;\n    #endif\n#elif defined(__APPLE__) && defined(MAC_OS_X_VERSION_10_6)\n    /* OSX >= 10.6 */\n    #if defined(_STRUCT_X86_THREAD_STATE64) && !defined(__i386__)\n    return (void*) uc->uc_mcontext->__ss.__rip;\n    #else\n    return (void*) uc->uc_mcontext->__ss.__eip;\n    #endif\n#elif defined(__linux__)\n    /* Linux */\n    #if defined(__i386__)\n    return (void*) uc->uc_mcontext.gregs[14]; /* Linux 32 */\n    #elif defined(__X86_64__) || defined(__x86_64__)\n    return (void*) uc->uc_mcontext.gregs[16]; /* Linux 64 */\n    #elif defined(__ia64__) /* Linux IA64 */\n    return (void*) uc->uc_mcontext.sc_ip;\n    #elif defined(__arm__) /* Linux ARM */\n    return (void*) uc->uc_mcontext.arm_pc;\n    #endif\n#else\n    return NULL;\n#endif\n}\n\nvoid logStackContent(void **sp) {\n    int i;\n    for (i = 15; i >= 0; i--) {\n        unsigned long addr = (unsigned long) sp+i;\n        unsigned long val = (unsigned long) sp[i];\n\n        if (sizeof(long) == 4)\n            serverLog(LL_WARNING, \"(%08lx) -> %08lx\", addr, val);\n        else\n            serverLog(LL_WARNING, \"(%016lx) -> %016lx\", addr, val);\n    }\n}\n\nvoid logRegisters(ucontext_t *uc) {\n    serverLog(LL_WARNING|LL_RAW, \"\\n------ REGISTERS ------\\n\");\n\n/* OSX */\n#if defined(__APPLE__) && defined(MAC_OS_X_VERSION_10_6)\n  /* OSX AMD64 */\n    #if defined(_STRUCT_X86_THREAD_STATE64) && !defined(__i386__)\n    serverLog(LL_WARNING,\n    \"\\n\"\n    \"RAX:%016lx RBX:%016lx\\nRCX:%016lx RDX:%016lx\\n\"\n    \"RDI:%016lx RSI:%016lx\\nRBP:%016lx RSP:%016lx\\n\"\n    \"R8 :%016lx R9 :%016lx\\nR10:%016lx R11:%016lx\\n\"\n    \"R12:%016lx R13:%016lx\\nR14:%016lx R15:%016lx\\n\"\n    \"RIP:%016lx EFL:%016lx\\nCS :%016lx FS:%016lx  GS:%016lx\",\n        (unsigned long) uc->uc_mcontext->__ss.__rax,\n        (unsigned long) uc->uc_mcontext->__ss.__rbx,\n        (unsigned long) uc->uc_mcontext->__ss.__rcx,\n        (unsigned long) uc->uc_mcontext->__ss.__rdx,\n        (unsigned long) uc->uc_mcontext->__ss.__rdi,\n        (unsigned long) uc->uc_mcontext->__ss.__rsi,\n        (unsigned long) uc->uc_mcontext->__ss.__rbp,\n        (unsigned long) uc->uc_mcontext->__ss.__rsp,\n        (unsigned long) uc->uc_mcontext->__ss.__r8,\n        (unsigned long) uc->uc_mcontext->__ss.__r9,\n        (unsigned long) uc->uc_mcontext->__ss.__r10,\n        (unsigned long) uc->uc_mcontext->__ss.__r11,\n        (unsigned long) uc->uc_mcontext->__ss.__r12,\n        (unsigned long) uc->uc_mcontext->__ss.__r13,\n        (unsigned long) uc->uc_mcontext->__ss.__r14,\n        (unsigned long) uc->uc_mcontext->__ss.__r15,\n        (unsigned long) uc->uc_mcontext->__ss.__rip,\n        (unsigned long) uc->uc_mcontext->__ss.__rflags,\n        (unsigned long) uc->uc_mcontext->__ss.__cs,\n        (unsigned long) uc->uc_mcontext->__ss.__fs,\n        (unsigned long) uc->uc_mcontext->__ss.__gs\n    );\n    logStackContent((void**)uc->uc_mcontext->__ss.__rsp);\n    #else\n    /* OSX x86 */\n    serverLog(LL_WARNING,\n    \"\\n\"\n    \"EAX:%08lx EBX:%08lx ECX:%08lx EDX:%08lx\\n\"\n    \"EDI:%08lx ESI:%08lx EBP:%08lx ESP:%08lx\\n\"\n    \"SS:%08lx  EFL:%08lx EIP:%08lx CS :%08lx\\n\"\n    \"DS:%08lx  ES:%08lx  FS :%08lx GS :%08lx\",\n        (unsigned long) uc->uc_mcontext->__ss.__eax,\n        (unsigned long) uc->uc_mcontext->__ss.__ebx,\n        (unsigned long) uc->uc_mcontext->__ss.__ecx,\n        (unsigned long) uc->uc_mcontext->__ss.__edx,\n        (unsigned long) uc->uc_mcontext->__ss.__edi,\n        (unsigned long) uc->uc_mcontext->__ss.__esi,\n        (unsigned long) uc->uc_mcontext->__ss.__ebp,\n        (unsigned long) uc->uc_mcontext->__ss.__esp,\n        (unsigned long) uc->uc_mcontext->__ss.__ss,\n        (unsigned long) uc->uc_mcontext->__ss.__eflags,\n        (unsigned long) uc->uc_mcontext->__ss.__eip,\n        (unsigned long) uc->uc_mcontext->__ss.__cs,\n        (unsigned long) uc->uc_mcontext->__ss.__ds,\n        (unsigned long) uc->uc_mcontext->__ss.__es,\n        (unsigned long) uc->uc_mcontext->__ss.__fs,\n        (unsigned long) uc->uc_mcontext->__ss.__gs\n    );\n    logStackContent((void**)uc->uc_mcontext->__ss.__esp);\n    #endif\n/* Linux */\n#elif defined(__linux__)\n    /* Linux x86 */\n    #if defined(__i386__)\n    serverLog(LL_WARNING,\n    \"\\n\"\n    \"EAX:%08lx EBX:%08lx ECX:%08lx EDX:%08lx\\n\"\n    \"EDI:%08lx ESI:%08lx EBP:%08lx ESP:%08lx\\n\"\n    \"SS :%08lx EFL:%08lx EIP:%08lx CS:%08lx\\n\"\n    \"DS :%08lx ES :%08lx FS :%08lx GS:%08lx\",\n        (unsigned long) uc->uc_mcontext.gregs[11],\n        (unsigned long) uc->uc_mcontext.gregs[8],\n        (unsigned long) uc->uc_mcontext.gregs[10],\n        (unsigned long) uc->uc_mcontext.gregs[9],\n        (unsigned long) uc->uc_mcontext.gregs[4],\n        (unsigned long) uc->uc_mcontext.gregs[5],\n        (unsigned long) uc->uc_mcontext.gregs[6],\n        (unsigned long) uc->uc_mcontext.gregs[7],\n        (unsigned long) uc->uc_mcontext.gregs[18],\n        (unsigned long) uc->uc_mcontext.gregs[17],\n        (unsigned long) uc->uc_mcontext.gregs[14],\n        (unsigned long) uc->uc_mcontext.gregs[15],\n        (unsigned long) uc->uc_mcontext.gregs[3],\n        (unsigned long) uc->uc_mcontext.gregs[2],\n        (unsigned long) uc->uc_mcontext.gregs[1],\n        (unsigned long) uc->uc_mcontext.gregs[0]\n    );\n    logStackContent((void**)uc->uc_mcontext.gregs[7]);\n    #elif defined(__X86_64__) || defined(__x86_64__)\n    /* Linux AMD64 */\n    serverLog(LL_WARNING,\n    \"\\n\"\n    \"RAX:%016lx RBX:%016lx\\nRCX:%016lx RDX:%016lx\\n\"\n    \"RDI:%016lx RSI:%016lx\\nRBP:%016lx RSP:%016lx\\n\"\n    \"R8 :%016lx R9 :%016lx\\nR10:%016lx R11:%016lx\\n\"\n    \"R12:%016lx R13:%016lx\\nR14:%016lx R15:%016lx\\n\"\n    \"RIP:%016lx EFL:%016lx\\nCSGSFS:%016lx\",\n        (unsigned long) uc->uc_mcontext.gregs[13],\n        (unsigned long) uc->uc_mcontext.gregs[11],\n        (unsigned long) uc->uc_mcontext.gregs[14],\n        (unsigned long) uc->uc_mcontext.gregs[12],\n        (unsigned long) uc->uc_mcontext.gregs[8],\n        (unsigned long) uc->uc_mcontext.gregs[9],\n        (unsigned long) uc->uc_mcontext.gregs[10],\n        (unsigned long) uc->uc_mcontext.gregs[15],\n        (unsigned long) uc->uc_mcontext.gregs[0],\n        (unsigned long) uc->uc_mcontext.gregs[1],\n        (unsigned long) uc->uc_mcontext.gregs[2],\n        (unsigned long) uc->uc_mcontext.gregs[3],\n        (unsigned long) uc->uc_mcontext.gregs[4],\n        (unsigned long) uc->uc_mcontext.gregs[5],\n        (unsigned long) uc->uc_mcontext.gregs[6],\n        (unsigned long) uc->uc_mcontext.gregs[7],\n        (unsigned long) uc->uc_mcontext.gregs[16],\n        (unsigned long) uc->uc_mcontext.gregs[17],\n        (unsigned long) uc->uc_mcontext.gregs[18]\n    );\n    logStackContent((void**)uc->uc_mcontext.gregs[15]);\n    #endif\n#else\n    serverLog(LL_WARNING,\n        \"  Dumping of registers not supported for this OS/arch\");\n#endif\n}\n\n/* Return a file descriptor to write directly to the Redis log with the\n * write(2) syscall, that can be used in critical sections of the code\n * where the rest of Redis can't be trusted (for example during the memory\n * test) or when an API call requires a raw fd.\n *\n * Close it with closeDirectLogFiledes(). */\nint openDirectLogFiledes(void) {\n    int log_to_stdout = server.logfile[0] == '\\0';\n    int fd = log_to_stdout ?\n        STDOUT_FILENO :\n        open(server.logfile, O_APPEND|O_CREAT|O_WRONLY, 0644);\n    return fd;\n}\n\n/* Used to close what closeDirectLogFiledes() returns. */\nvoid closeDirectLogFiledes(int fd) {\n    int log_to_stdout = server.logfile[0] == '\\0';\n    if (!log_to_stdout) close(fd);\n}\n\n/* Logs the stack trace using the backtrace() call. This function is designed\n * to be called from signal handlers safely. */\nvoid logStackTrace(ucontext_t *uc) {\n    void *trace[101];\n    int trace_size = 0, fd = openDirectLogFiledes();\n\n    if (fd == -1) return; /* If we can't log there is anything to do. */\n\n    /* Generate the stack trace */\n    trace_size = backtrace(trace+1, 100);\n\n    if (getMcontextEip(uc) != NULL) {\n        char *msg1 = \"EIP:\\n\";\n        char *msg2 = \"\\nBacktrace:\\n\";\n        if (write(fd,msg1,strlen(msg1)) == -1) {/* Avoid warning. */};\n        trace[0] = getMcontextEip(uc);\n        backtrace_symbols_fd(trace, 1, fd);\n        if (write(fd,msg2,strlen(msg2)) == -1) {/* Avoid warning. */};\n    }\n\n    /* Write symbols to log file */\n    backtrace_symbols_fd(trace+1, trace_size, fd);\n\n    /* Cleanup */\n    closeDirectLogFiledes(fd);\n}\n\n/* Log information about the \"current\" client, that is, the client that is\n * currently being served by Redis. May be NULL if Redis is not serving a\n * client right now. */\nvoid logCurrentClient(void) {\n    if (server.current_client == NULL) return;\n\n    client *cc = server.current_client;\n    sds client;\n    int j;\n\n    serverLogRaw(LL_WARNING|LL_RAW, \"\\n------ CURRENT CLIENT INFO ------\\n\");\n    client = catClientInfoString(sdsempty(),cc);\n    serverLog(LL_WARNING|LL_RAW,\"%s\\n\", client);\n    sdsfree(client);\n    for (j = 0; j < cc->argc; j++) {\n        robj *decoded;\n\n        decoded = getDecodedObject(cc->argv[j]);\n        serverLog(LL_WARNING|LL_RAW,\"argv[%d]: '%s'\\n\", j,\n            (char*)decoded->ptr);\n        decrRefCount(decoded);\n    }\n    /* Check if the first argument, usually a key, is found inside the\n     * selected DB, and if so print info about the associated object. */\n    if (cc->argc >= 1) {\n        robj *val, *key;\n        dictEntry *de;\n\n        key = getDecodedObject(cc->argv[1]);\n        de = dictFind(cc->db->dict, key->ptr);\n        if (de) {\n            val = dictGetVal(de);\n            serverLog(LL_WARNING,\"key '%s' found in DB containing the following object:\", (char*)key->ptr);\n            serverLogObjectDebugInfo(val);\n        }\n        decrRefCount(key);\n    }\n}\n\n#if defined(HAVE_PROC_MAPS)\n\n#define MEMTEST_MAX_REGIONS 128\n\n/* A non destructive memory test executed during segfauls. */\nint memtest_test_linux_anonymous_maps(void) {\n    FILE *fp;\n    char line[1024];\n    char logbuf[1024];\n    size_t start_addr, end_addr, size;\n    size_t start_vect[MEMTEST_MAX_REGIONS];\n    size_t size_vect[MEMTEST_MAX_REGIONS];\n    int regions = 0, j;\n\n    int fd = openDirectLogFiledes();\n    if (!fd) return 0;\n\n    fp = fopen(\"/proc/self/maps\",\"r\");\n    if (!fp) return 0;\n    while(fgets(line,sizeof(line),fp) != NULL) {\n        char *start, *end, *p = line;\n\n        start = p;\n        p = strchr(p,'-');\n        if (!p) continue;\n        *p++ = '\\0';\n        end = p;\n        p = strchr(p,' ');\n        if (!p) continue;\n        *p++ = '\\0';\n        if (strstr(p,\"stack\") ||\n            strstr(p,\"vdso\") ||\n            strstr(p,\"vsyscall\")) continue;\n        if (!strstr(p,\"00:00\")) continue;\n        if (!strstr(p,\"rw\")) continue;\n\n        start_addr = strtoul(start,NULL,16);\n        end_addr = strtoul(end,NULL,16);\n        size = end_addr-start_addr;\n\n        start_vect[regions] = start_addr;\n        size_vect[regions] = size;\n        snprintf(logbuf,sizeof(logbuf),\n            \"*** Preparing to test memory region %lx (%lu bytes)\\n\",\n                (unsigned long) start_vect[regions],\n                (unsigned long) size_vect[regions]);\n        if (write(fd,logbuf,strlen(logbuf)) == -1) { /* Nothing to do. */ }\n        regions++;\n    }\n\n    int errors = 0;\n    for (j = 0; j < regions; j++) {\n        if (write(fd,\".\",1) == -1) { /* Nothing to do. */ }\n        errors += memtest_preserving_test((void*)start_vect[j],size_vect[j],1);\n        if (write(fd, errors ? \"E\" : \"O\",1) == -1) { /* Nothing to do. */ }\n    }\n    if (write(fd,\"\\n\",1) == -1) { /* Nothing to do. */ }\n\n    /* NOTE: It is very important to close the file descriptor only now\n     * because closing it before may result into unmapping of some memory\n     * region that we are testing. */\n    fclose(fp);\n    closeDirectLogFiledes(fd);\n    return errors;\n}\n#endif\n\n/* Scans the (assumed) x86 code starting at addr, for a max of `len`\n * bytes, searching for E8 (callq) opcodes, and dumping the symbols\n * and the call offset if they appear to be valid. */\nvoid dumpX86Calls(void *addr, size_t len) {\n    size_t j;\n    unsigned char *p = addr;\n    Dl_info info;\n    /* Hash table to best-effort avoid printing the same symbol\n     * multiple times. */\n    unsigned long ht[256] = {0};\n\n    if (len < 5) return;\n    for (j = 0; j < len-4; j++) {\n        if (p[j] != 0xE8) continue; /* Not an E8 CALL opcode. */\n        unsigned long target = (unsigned long)addr+j+5;\n        target += *((int32_t*)(p+j+1));\n        if (dladdr((void*)target, &info) != 0 && info.dli_sname != NULL) {\n            if (ht[target&0xff] != target) {\n                printf(\"Function at 0x%lx is %s\\n\",target,info.dli_sname);\n                ht[target&0xff] = target;\n            }\n            j += 4; /* Skip the 32 bit immediate. */\n        }\n    }\n}\n\nvoid sigsegvHandler(int sig, siginfo_t *info, void *secret) {\n    ucontext_t *uc = (ucontext_t*) secret;\n    void *eip = getMcontextEip(uc);\n    sds infostring, clients;\n    struct sigaction act;\n    UNUSED(info);\n\n    bugReportStart();\n    serverLog(LL_WARNING,\n        \"Redis %s crashed by signal: %d\", REDIS_VERSION, sig);\n    if (eip != NULL) {\n        serverLog(LL_WARNING,\n        \"Crashed running the instuction at: %p\", eip);\n    }\n    if (sig == SIGSEGV || sig == SIGBUS) {\n        serverLog(LL_WARNING,\n        \"Accessing address: %p\", (void*)info->si_addr);\n    }\n    serverLog(LL_WARNING,\n        \"Failed assertion: %s (%s:%d)\", server.assert_failed,\n                        server.assert_file, server.assert_line);\n\n    /* Log the stack trace */\n    serverLogRaw(LL_WARNING|LL_RAW, \"\\n------ STACK TRACE ------\\n\");\n    logStackTrace(uc);\n\n    /* Log INFO and CLIENT LIST */\n    serverLogRaw(LL_WARNING|LL_RAW, \"\\n------ INFO OUTPUT ------\\n\");\n    infostring = genRedisInfoString(\"all\");\n    infostring = sdscatprintf(infostring, \"hash_init_value: %u\\n\",\n        dictGetHashFunctionSeed());\n    serverLogRaw(LL_WARNING|LL_RAW, infostring);\n    serverLogRaw(LL_WARNING|LL_RAW, \"\\n------ CLIENT LIST OUTPUT ------\\n\");\n    clients = getAllClientsInfoString();\n    serverLogRaw(LL_WARNING|LL_RAW, clients);\n    sdsfree(infostring);\n    sdsfree(clients);\n\n    /* Log the current client */\n    logCurrentClient();\n\n    /* Log dump of processor registers */\n    logRegisters(uc);\n\n#if defined(HAVE_PROC_MAPS)\n    /* Test memory */\n    serverLogRaw(LL_WARNING|LL_RAW, \"\\n------ FAST MEMORY TEST ------\\n\");\n    bioKillThreads();\n    if (memtest_test_linux_anonymous_maps()) {\n        serverLogRaw(LL_WARNING|LL_RAW,\n            \"!!! MEMORY ERROR DETECTED! Check your memory ASAP !!!\\n\");\n    } else {\n        serverLogRaw(LL_WARNING|LL_RAW,\n            \"Fast memory test PASSED, however your memory can still be broken. Please run a memory test for several hours if possible.\\n\");\n    }\n#endif\n\n    if (eip != NULL) {\n        Dl_info info;\n        if (dladdr(eip, &info) != 0) {\n            serverLog(LL_WARNING|LL_RAW,\n                \"\\n------ DUMPING CODE AROUND EIP ------\\n\"\n                \"Symbol: %s (base: %p)\\n\"\n                \"Module: %s (base %p)\\n\"\n                \"$ xxd -r -p /tmp/dump.hex /tmp/dump.bin\\n\"\n                \"$ objdump --adjust-vma=%p -D -b binary -m i386:x86-64 /tmp/dump.bin\\n\"\n                \"------\\n\",\n                info.dli_sname, info.dli_saddr, info.dli_fname, info.dli_fbase,\n                info.dli_saddr);\n            size_t len = (long)eip - (long)info.dli_saddr;\n            unsigned long sz = sysconf(_SC_PAGESIZE);\n            if (len < 1<<13) { /* we don't have functions over 8k (verified) */\n                /* Find the address of the next page, which is our \"safety\"\n                 * limit when dumping. Then try to dump just 128 bytes more\n                 * than EIP if there is room, or stop sooner. */\n                unsigned long next = ((unsigned long)eip + sz) & ~(sz-1);\n                unsigned long end = (unsigned long)eip + 128;\n                if (end > next) end = next;\n                len = end - (unsigned long)info.dli_saddr;\n                serverLogHexDump(LL_WARNING, \"dump of function\",\n                    info.dli_saddr ,len);\n                dumpX86Calls(info.dli_saddr,len);\n            }\n        }\n    }\n\n    serverLogRaw(LL_WARNING|LL_RAW,\n\"\\n=== REDIS BUG REPORT END. Make sure to include from START to END. ===\\n\\n\"\n\"       Please report the crash by opening an issue on github:\\n\\n\"\n\"           http://github.com/antirez/redis/issues\\n\\n\"\n\"  Suspect RAM error? Use redis-server --test-memory to verify it.\\n\\n\"\n);\n\n    /* free(messages); Don't call free() with possibly corrupted memory. */\n    if (server.daemonize && server.supervised == 0) unlink(server.pidfile);\n\n    /* Make sure we exit with the right signal at the end. So for instance\n     * the core will be dumped if enabled. */\n    sigemptyset (&act.sa_mask);\n    act.sa_flags = SA_NODEFER | SA_ONSTACK | SA_RESETHAND;\n    act.sa_handler = SIG_DFL;\n    sigaction (sig, &act, NULL);\n    kill(getpid(),sig);\n}\n#endif /* HAVE_BACKTRACE */\n\n/* ==================== Logging functions for debugging ===================== */\n\nvoid serverLogHexDump(int level, char *descr, void *value, size_t len) {\n    char buf[65], *b;\n    unsigned char *v = value;\n    char charset[] = \"0123456789abcdef\";\n\n    serverLog(level,\"%s (hexdump of %zu bytes):\", descr, len);\n    b = buf;\n    while(len) {\n        b[0] = charset[(*v)>>4];\n        b[1] = charset[(*v)&0xf];\n        b[2] = '\\0';\n        b += 2;\n        len--;\n        v++;\n        if (b-buf == 64 || len == 0) {\n            serverLogRaw(level|LL_RAW,buf);\n            b = buf;\n        }\n    }\n    serverLogRaw(level|LL_RAW,\"\\n\");\n}\n\n/* =========================== Software Watchdog ============================ */\n#include <sys/time.h>\n\nvoid watchdogSignalHandler(int sig, siginfo_t *info, void *secret) {\n#ifdef HAVE_BACKTRACE\n    ucontext_t *uc = (ucontext_t*) secret;\n#endif\n    UNUSED(info);\n    UNUSED(sig);\n\n    serverLogFromHandler(LL_WARNING,\"\\n--- WATCHDOG TIMER EXPIRED ---\");\n#ifdef HAVE_BACKTRACE\n    logStackTrace(uc);\n#else\n    serverLogFromHandler(LL_WARNING,\"Sorry: no support for backtrace().\");\n#endif\n    serverLogFromHandler(LL_WARNING,\"--------\\n\");\n}\n\n/* Schedule a SIGALRM delivery after the specified period in milliseconds.\n * If a timer is already scheduled, this function will re-schedule it to the\n * specified time. If period is 0 the current timer is disabled. */\nvoid watchdogScheduleSignal(int period) {\n    struct itimerval it;\n\n    /* Will stop the timer if period is 0. */\n    it.it_value.tv_sec = period/1000;\n    it.it_value.tv_usec = (period%1000)*1000;\n    /* Don't automatically restart. */\n    it.it_interval.tv_sec = 0;\n    it.it_interval.tv_usec = 0;\n    setitimer(ITIMER_REAL, &it, NULL);\n}\n\n/* Enable the software watchdog with the specified period in milliseconds. */\nvoid enableWatchdog(int period) {\n    int min_period;\n\n    if (server.watchdog_period == 0) {\n        struct sigaction act;\n\n        /* Watchdog was actually disabled, so we have to setup the signal\n         * handler. */\n        sigemptyset(&act.sa_mask);\n        act.sa_flags = SA_ONSTACK | SA_SIGINFO;\n        act.sa_sigaction = watchdogSignalHandler;\n        sigaction(SIGALRM, &act, NULL);\n    }\n    /* If the configured period is smaller than twice the timer period, it is\n     * too short for the software watchdog to work reliably. Fix it now\n     * if needed. */\n    min_period = (1000/server.hz)*2;\n    if (period < min_period) period = min_period;\n    watchdogScheduleSignal(period); /* Adjust the current timer. */\n    server.watchdog_period = period;\n}\n\n/* Disable the software watchdog. */\nvoid disableWatchdog(void) {\n    struct sigaction act;\n    if (server.watchdog_period == 0) return; /* Already disabled. */\n    watchdogScheduleSignal(0); /* Stop the current timer. */\n\n    /* Set the signal handler to SIG_IGN, this will also remove pending\n     * signals from the queue. */\n    sigemptyset(&act.sa_mask);\n    act.sa_flags = 0;\n    act.sa_handler = SIG_IGN;\n    sigaction(SIGALRM, &act, NULL);\n    server.watchdog_period = 0;\n}\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/src/debugmacro.h",
    "content": "/* This file contains debugging macros to be used when investigating issues.\n *\n * -----------------------------------------------------------------------------\n *\n * Copyright (c) 2016, Salvatore Sanfilippo <antirez at gmail dot com>\n * All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions are met:\n *\n *   * Redistributions of source code must retain the above copyright notice,\n *     this list of conditions and the following disclaimer.\n *   * Redistributions in binary form must reproduce the above copyright\n *     notice, this list of conditions and the following disclaimer in the\n *     documentation and/or other materials provided with the distribution.\n *   * Neither the name of Redis nor the names of its contributors may be used\n *     to endorse or promote products derived from this software without\n *     specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\"\n * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\n * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE\n * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR\n * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF\n * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS\n * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN\n * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)\n * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE\n * POSSIBILITY OF SUCH DAMAGE.\n */\n\n#include <stdio.h>\n#define D(...)                                                               \\\n    do {                                                                     \\\n        FILE *fp = fopen(\"/tmp/log.txt\",\"a\");                                \\\n        fprintf(fp,\"%s:%s:%d:\\t\", __FILE__, __func__, __LINE__);             \\\n        fprintf(fp,__VA_ARGS__);                                             \\\n        fprintf(fp,\"\\n\");                                                    \\\n        fclose(fp);                                                          \\\n    } while (0);\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/src/dict.c",
    "content": "/* Hash Tables Implementation.\n *\n * This file implements in memory hash tables with insert/del/replace/find/\n * get-random-element operations. Hash tables will auto resize if needed\n * tables of power of two in size are used, collisions are handled by\n * chaining. See the source code for more information... :)\n *\n * Copyright (c) 2006-2012, Salvatore Sanfilippo <antirez at gmail dot com>\n * All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions are met:\n *\n *   * Redistributions of source code must retain the above copyright notice,\n *     this list of conditions and the following disclaimer.\n *   * Redistributions in binary form must reproduce the above copyright\n *     notice, this list of conditions and the following disclaimer in the\n *     documentation and/or other materials provided with the distribution.\n *   * Neither the name of Redis nor the names of its contributors may be used\n *     to endorse or promote products derived from this software without\n *     specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\"\n * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\n * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE\n * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR\n * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF\n * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS\n * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN\n * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)\n * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE\n * POSSIBILITY OF SUCH DAMAGE.\n */\n\n#include \"fmacros.h\"\n\n#include <stdio.h>\n#include <stdlib.h>\n#include <string.h>\n#include <stdarg.h>\n#include <limits.h>\n#include <sys/time.h>\n#include <ctype.h>\n\n#include \"dict.h\"\n#include \"zmalloc.h\"\n#include \"redisassert.h\"\n\n/* Using dictEnableResize() / dictDisableResize() we make possible to\n * enable/disable resizing of the hash table as needed. This is very important\n * for Redis, as we use copy-on-write and don't want to move too much memory\n * around when there is a child performing saving operations.\n *\n * Note that even when dict_can_resize is set to 0, not all resizes are\n * prevented: a hash table is still allowed to grow if the ratio between\n * the number of elements and the buckets > dict_force_resize_ratio. */\nstatic int dict_can_resize = 1;\nstatic unsigned int dict_force_resize_ratio = 5;\n\n/* -------------------------- private prototypes ---------------------------- */\n\nstatic int _dictExpandIfNeeded(dict *ht);\nstatic unsigned long _dictNextPower(unsigned long size);\nstatic int _dictKeyIndex(dict *ht, const void *key);\nstatic int _dictInit(dict *ht, dictType *type, void *privDataPtr);\n\n/* -------------------------- hash functions -------------------------------- */\n\n/* Thomas Wang's 32 bit Mix Function */\nunsigned int dictIntHashFunction(unsigned int key)\n{\n    key += ~(key << 15);\n    key ^=  (key >> 10);\n    key +=  (key << 3);\n    key ^=  (key >> 6);\n    key += ~(key << 11);\n    key ^=  (key >> 16);\n    return key;\n}\n\nstatic uint32_t dict_hash_function_seed = 5381;\n\nvoid dictSetHashFunctionSeed(uint32_t seed) {\n    dict_hash_function_seed = seed;\n}\n\nuint32_t dictGetHashFunctionSeed(void) {\n    return dict_hash_function_seed;\n}\n\n/* MurmurHash2, by Austin Appleby\n * Note - This code makes a few assumptions about how your machine behaves -\n * 1. We can read a 4-byte value from any address without crashing\n * 2. sizeof(int) == 4\n *\n * And it has a few limitations -\n *\n * 1. It will not work incrementally.\n * 2. It will not produce the same results on little-endian and big-endian\n *    machines.\n */\nunsigned int dictGenHashFunction(const void *key, int len) {\n    /* 'm' and 'r' are mixing constants generated offline.\n     They're not really 'magic', they just happen to work well.  */\n    uint32_t seed = dict_hash_function_seed;\n    const uint32_t m = 0x5bd1e995;\n    const int r = 24;\n\n    /* Initialize the hash to a 'random' value */\n    uint32_t h = seed ^ len;\n\n    /* Mix 4 bytes at a time into the hash */\n    const unsigned char *data = (const unsigned char *)key;\n\n    while(len >= 4) {\n        uint32_t k = *(uint32_t*)data;\n\n        k *= m;\n        k ^= k >> r;\n        k *= m;\n\n        h *= m;\n        h ^= k;\n\n        data += 4;\n        len -= 4;\n    }\n\n    /* Handle the last few bytes of the input array  */\n    switch(len) {\n    case 3: h ^= data[2] << 16;\n    case 2: h ^= data[1] << 8;\n    case 1: h ^= data[0]; h *= m;\n    };\n\n    /* Do a few final mixes of the hash to ensure the last few\n     * bytes are well-incorporated. */\n    h ^= h >> 13;\n    h *= m;\n    h ^= h >> 15;\n\n    return (unsigned int)h;\n}\n\n/* And a case insensitive hash function (based on djb hash) */\nunsigned int dictGenCaseHashFunction(const unsigned char *buf, int len) {\n    unsigned int hash = (unsigned int)dict_hash_function_seed;\n\n    while (len--)\n        hash = ((hash << 5) + hash) + (tolower(*buf++)); /* hash * 33 + c */\n    return hash;\n}\n\n/* ----------------------------- API implementation ------------------------- */\n\n/* Reset a hash table already initialized with ht_init().\n * NOTE: This function should only be called by ht_destroy(). */\nstatic void _dictReset(dictht *ht)\n{\n    ht->table = NULL;\n    ht->size = 0;\n    ht->sizemask = 0;\n    ht->used = 0;\n}\n\n/* Create a new hash table */\ndict *dictCreate(dictType *type,\n        void *privDataPtr)\n{\n    dict *d = zmalloc(sizeof(*d));\n\n    _dictInit(d,type,privDataPtr);\n    return d;\n}\n\n/* Initialize the hash table */\nint _dictInit(dict *d, dictType *type,\n        void *privDataPtr)\n{\n    _dictReset(&d->ht[0]);\n    _dictReset(&d->ht[1]);\n    d->type = type;\n    d->privdata = privDataPtr;\n    d->rehashidx = -1;\n    d->iterators = 0;\n    return DICT_OK;\n}\n\n/* Resize the table to the minimal size that contains all the elements,\n * but with the invariant of a USED/BUCKETS ratio near to <= 1 */\nint dictResize(dict *d)\n{\n    int minimal;\n\n    if (!dict_can_resize || dictIsRehashing(d)) return DICT_ERR;\n    minimal = d->ht[0].used;\n    if (minimal < DICT_HT_INITIAL_SIZE)\n        minimal = DICT_HT_INITIAL_SIZE;\n    return dictExpand(d, minimal);\n}\n\n/* Expand or create the hash table */\nint dictExpand(dict *d, unsigned long size)\n{\n    dictht n; /* the new hash table */\n    unsigned long realsize = _dictNextPower(size);\n\n    /* the size is invalid if it is smaller than the number of\n     * elements already inside the hash table */\n    if (dictIsRehashing(d) || d->ht[0].used > size)\n        return DICT_ERR;\n\n    /* Rehashing to the same table size is not useful. */\n    if (realsize == d->ht[0].size) return DICT_ERR;\n\n    /* Allocate the new hash table and initialize all pointers to NULL */\n    n.size = realsize;\n    n.sizemask = realsize-1;\n    n.table = zcalloc(realsize*sizeof(dictEntry*));\n    n.used = 0;\n\n    /* Is this the first initialization? If so it's not really a rehashing\n     * we just set the first hash table so that it can accept keys. */\n    if (d->ht[0].table == NULL) {\n        d->ht[0] = n;\n        return DICT_OK;\n    }\n\n    /* Prepare a second hash table for incremental rehashing */\n    d->ht[1] = n;\n    d->rehashidx = 0;\n    return DICT_OK;\n}\n\n/* Performs N steps of incremental rehashing. Returns 1 if there are still\n * keys to move from the old to the new hash table, otherwise 0 is returned.\n *\n * Note that a rehashing step consists in moving a bucket (that may have more\n * than one key as we use chaining) from the old to the new hash table, however\n * since part of the hash table may be composed of empty spaces, it is not\n * guaranteed that this function will rehash even a single bucket, since it\n * will visit at max N*10 empty buckets in total, otherwise the amount of\n * work it does would be unbound and the function may block for a long time. */\nint dictRehash(dict *d, int n) {\n    int empty_visits = n*10; /* Max number of empty buckets to visit. */\n    if (!dictIsRehashing(d)) return 0;\n\n    while(n-- && d->ht[0].used != 0) {\n        dictEntry *de, *nextde;\n\n        /* Note that rehashidx can't overflow as we are sure there are more\n         * elements because ht[0].used != 0 */\n        assert(d->ht[0].size > (unsigned long)d->rehashidx);\n        while(d->ht[0].table[d->rehashidx] == NULL) {\n            d->rehashidx++;\n            if (--empty_visits == 0) return 1;\n        }\n        de = d->ht[0].table[d->rehashidx];\n        /* Move all the keys in this bucket from the old to the new hash HT */\n        while(de) {\n            unsigned int h;\n\n            nextde = de->next;\n            /* Get the index in the new hash table */\n            h = dictHashKey(d, de->key) & d->ht[1].sizemask;\n            de->next = d->ht[1].table[h];\n            d->ht[1].table[h] = de;\n            d->ht[0].used--;\n            d->ht[1].used++;\n            de = nextde;\n        }\n        d->ht[0].table[d->rehashidx] = NULL;\n        d->rehashidx++;\n    }\n\n    /* Check if we already rehashed the whole table... */\n    if (d->ht[0].used == 0) {\n        zfree(d->ht[0].table);\n        d->ht[0] = d->ht[1];\n        _dictReset(&d->ht[1]);\n        d->rehashidx = -1;\n        return 0;\n    }\n\n    /* More to rehash... */\n    return 1;\n}\n\nlong long timeInMilliseconds(void) {\n    struct timeval tv;\n\n    gettimeofday(&tv,NULL);\n    return (((long long)tv.tv_sec)*1000)+(tv.tv_usec/1000);\n}\n\n/* Rehash for an amount of time between ms milliseconds and ms+1 milliseconds */\nint dictRehashMilliseconds(dict *d, int ms) {\n    long long start = timeInMilliseconds();\n    int rehashes = 0;\n\n    while(dictRehash(d,100)) {\n        rehashes += 100;\n        if (timeInMilliseconds()-start > ms) break;\n    }\n    return rehashes;\n}\n\n/* This function performs just a step of rehashing, and only if there are\n * no safe iterators bound to our hash table. When we have iterators in the\n * middle of a rehashing we can't mess with the two hash tables otherwise\n * some element can be missed or duplicated.\n *\n * This function is called by common lookup or update operations in the\n * dictionary so that the hash table automatically migrates from H1 to H2\n * while it is actively used. */\nstatic void _dictRehashStep(dict *d) {\n    if (d->iterators == 0) dictRehash(d,1);\n}\n\n/* Add an element to the target hash table */\nint dictAdd(dict *d, void *key, void *val)\n{\n    dictEntry *entry = dictAddRaw(d,key);\n\n    if (!entry) return DICT_ERR;\n    dictSetVal(d, entry, val);\n    return DICT_OK;\n}\n\n/* Low level add. This function adds the entry but instead of setting\n * a value returns the dictEntry structure to the user, that will make\n * sure to fill the value field as he wishes.\n *\n * This function is also directly exposed to the user API to be called\n * mainly in order to store non-pointers inside the hash value, example:\n *\n * entry = dictAddRaw(dict,mykey);\n * if (entry != NULL) dictSetSignedIntegerVal(entry,1000);\n *\n * Return values:\n *\n * If key already exists NULL is returned.\n * If key was added, the hash entry is returned to be manipulated by the caller.\n */\ndictEntry *dictAddRaw(dict *d, void *key)\n{\n    int index;\n    dictEntry *entry;\n    dictht *ht;\n\n    if (dictIsRehashing(d)) _dictRehashStep(d);\n\n    /* Get the index of the new element, or -1 if\n     * the element already exists. */\n    if ((index = _dictKeyIndex(d, key)) == -1)\n        return NULL;\n\n    /* Allocate the memory and store the new entry.\n     * Insert the element in top, with the assumption that in a database\n     * system it is more likely that recently added entries are accessed\n     * more frequently. */\n    ht = dictIsRehashing(d) ? &d->ht[1] : &d->ht[0];\n    entry = zmalloc(sizeof(*entry));\n    entry->next = ht->table[index];\n    ht->table[index] = entry;\n    ht->used++;\n\n    /* Set the hash entry fields. */\n    dictSetKey(d, entry, key);\n    return entry;\n}\n\n/* Add an element, discarding the old if the key already exists.\n * Return 1 if the key was added from scratch, 0 if there was already an\n * element with such key and dictReplace() just performed a value update\n * operation. */\nint dictReplace(dict *d, void *key, void *val)\n{\n    dictEntry *entry, auxentry;\n\n    /* Try to add the element. If the key\n     * does not exists dictAdd will suceed. */\n    if (dictAdd(d, key, val) == DICT_OK)\n        return 1;\n    /* It already exists, get the entry */\n    entry = dictFind(d, key);\n    /* Set the new value and free the old one. Note that it is important\n     * to do that in this order, as the value may just be exactly the same\n     * as the previous one. In this context, think to reference counting,\n     * you want to increment (set), and then decrement (free), and not the\n     * reverse. */\n    auxentry = *entry;\n    dictSetVal(d, entry, val);\n    dictFreeVal(d, &auxentry);\n    return 0;\n}\n\n/* dictReplaceRaw() is simply a version of dictAddRaw() that always\n * returns the hash entry of the specified key, even if the key already\n * exists and can't be added (in that case the entry of the already\n * existing key is returned.)\n *\n * See dictAddRaw() for more information. */\ndictEntry *dictReplaceRaw(dict *d, void *key) {\n    dictEntry *entry = dictFind(d,key);\n\n    return entry ? entry : dictAddRaw(d,key);\n}\n\n/* Search and remove an element */\nstatic int dictGenericDelete(dict *d, const void *key, int nofree)\n{\n    unsigned int h, idx;\n    dictEntry *he, *prevHe;\n    int table;\n\n    if (d->ht[0].size == 0) return DICT_ERR; /* d->ht[0].table is NULL */\n    if (dictIsRehashing(d)) _dictRehashStep(d);\n    h = dictHashKey(d, key);\n\n    for (table = 0; table <= 1; table++) {\n        idx = h & d->ht[table].sizemask;\n        he = d->ht[table].table[idx];\n        prevHe = NULL;\n        while(he) {\n            if (key==he->key || dictCompareKeys(d, key, he->key)) {\n                /* Unlink the element from the list */\n                if (prevHe)\n                    prevHe->next = he->next;\n                else\n                    d->ht[table].table[idx] = he->next;\n                if (!nofree) {\n                    dictFreeKey(d, he);\n                    dictFreeVal(d, he);\n                }\n                zfree(he);\n                d->ht[table].used--;\n                return DICT_OK;\n            }\n            prevHe = he;\n            he = he->next;\n        }\n        if (!dictIsRehashing(d)) break;\n    }\n    return DICT_ERR; /* not found */\n}\n\nint dictDelete(dict *ht, const void *key) {\n    return dictGenericDelete(ht,key,0);\n}\n\nint dictDeleteNoFree(dict *ht, const void *key) {\n    return dictGenericDelete(ht,key,1);\n}\n\n/* Destroy an entire dictionary */\nint _dictClear(dict *d, dictht *ht, void(callback)(void *)) {\n    unsigned long i;\n\n    /* Free all the elements */\n    for (i = 0; i < ht->size && ht->used > 0; i++) {\n        dictEntry *he, *nextHe;\n\n        if (callback && (i & 65535) == 0) callback(d->privdata);\n\n        if ((he = ht->table[i]) == NULL) continue;\n        while(he) {\n            nextHe = he->next;\n            dictFreeKey(d, he);\n            dictFreeVal(d, he);\n            zfree(he);\n            ht->used--;\n            he = nextHe;\n        }\n    }\n    /* Free the table and the allocated cache structure */\n    zfree(ht->table);\n    /* Re-initialize the table */\n    _dictReset(ht);\n    return DICT_OK; /* never fails */\n}\n\n/* Clear & Release the hash table */\nvoid dictRelease(dict *d)\n{\n    _dictClear(d,&d->ht[0],NULL);\n    _dictClear(d,&d->ht[1],NULL);\n    zfree(d);\n}\n\ndictEntry *dictFind(dict *d, const void *key)\n{\n    dictEntry *he;\n    unsigned int h, idx, table;\n\n    if (d->ht[0].used + d->ht[1].used == 0) return NULL; /* dict is empty */\n    if (dictIsRehashing(d)) _dictRehashStep(d);\n    h = dictHashKey(d, key);\n    for (table = 0; table <= 1; table++) {\n        idx = h & d->ht[table].sizemask;\n        he = d->ht[table].table[idx];\n        while(he) {\n            if (key==he->key || dictCompareKeys(d, key, he->key))\n                return he;\n            he = he->next;\n        }\n        if (!dictIsRehashing(d)) return NULL;\n    }\n    return NULL;\n}\n\nvoid *dictFetchValue(dict *d, const void *key) {\n    dictEntry *he;\n\n    he = dictFind(d,key);\n    return he ? dictGetVal(he) : NULL;\n}\n\n/* A fingerprint is a 64 bit number that represents the state of the dictionary\n * at a given time, it's just a few dict properties xored together.\n * When an unsafe iterator is initialized, we get the dict fingerprint, and check\n * the fingerprint again when the iterator is released.\n * If the two fingerprints are different it means that the user of the iterator\n * performed forbidden operations against the dictionary while iterating. */\nlong long dictFingerprint(dict *d) {\n    long long integers[6], hash = 0;\n    int j;\n\n    integers[0] = (long) d->ht[0].table;\n    integers[1] = d->ht[0].size;\n    integers[2] = d->ht[0].used;\n    integers[3] = (long) d->ht[1].table;\n    integers[4] = d->ht[1].size;\n    integers[5] = d->ht[1].used;\n\n    /* We hash N integers by summing every successive integer with the integer\n     * hashing of the previous sum. Basically:\n     *\n     * Result = hash(hash(hash(int1)+int2)+int3) ...\n     *\n     * This way the same set of integers in a different order will (likely) hash\n     * to a different number. */\n    for (j = 0; j < 6; j++) {\n        hash += integers[j];\n        /* For the hashing step we use Tomas Wang's 64 bit integer hash. */\n        hash = (~hash) + (hash << 21); // hash = (hash << 21) - hash - 1;\n        hash = hash ^ (hash >> 24);\n        hash = (hash + (hash << 3)) + (hash << 8); // hash * 265\n        hash = hash ^ (hash >> 14);\n        hash = (hash + (hash << 2)) + (hash << 4); // hash * 21\n        hash = hash ^ (hash >> 28);\n        hash = hash + (hash << 31);\n    }\n    return hash;\n}\n\ndictIterator *dictGetIterator(dict *d)\n{\n    dictIterator *iter = zmalloc(sizeof(*iter));\n\n    iter->d = d;\n    iter->table = 0;\n    iter->index = -1;\n    iter->safe = 0;\n    iter->entry = NULL;\n    iter->nextEntry = NULL;\n    return iter;\n}\n\ndictIterator *dictGetSafeIterator(dict *d) {\n    dictIterator *i = dictGetIterator(d);\n\n    i->safe = 1;\n    return i;\n}\n\ndictEntry *dictNext(dictIterator *iter)\n{\n    while (1) {\n        if (iter->entry == NULL) {\n            dictht *ht = &iter->d->ht[iter->table];\n            if (iter->index == -1 && iter->table == 0) {\n                if (iter->safe)\n                    iter->d->iterators++;\n                else\n                    iter->fingerprint = dictFingerprint(iter->d);\n            }\n            iter->index++;\n            if (iter->index >= (long) ht->size) {\n                if (dictIsRehashing(iter->d) && iter->table == 0) {\n                    iter->table++;\n                    iter->index = 0;\n                    ht = &iter->d->ht[1];\n                } else {\n                    break;\n                }\n            }\n            iter->entry = ht->table[iter->index];\n        } else {\n            iter->entry = iter->nextEntry;\n        }\n        if (iter->entry) {\n            /* We need to save the 'next' here, the iterator user\n             * may delete the entry we are returning. */\n            iter->nextEntry = iter->entry->next;\n            return iter->entry;\n        }\n    }\n    return NULL;\n}\n\nvoid dictReleaseIterator(dictIterator *iter)\n{\n    if (!(iter->index == -1 && iter->table == 0)) {\n        if (iter->safe)\n            iter->d->iterators--;\n        else\n            assert(iter->fingerprint == dictFingerprint(iter->d));\n    }\n    zfree(iter);\n}\n\n/* Return a random entry from the hash table. Useful to\n * implement randomized algorithms */\ndictEntry *dictGetRandomKey(dict *d)\n{\n    dictEntry *he, *orighe;\n    unsigned int h;\n    int listlen, listele;\n\n    if (dictSize(d) == 0) return NULL;\n    if (dictIsRehashing(d)) _dictRehashStep(d);\n    if (dictIsRehashing(d)) {\n        do {\n            /* We are sure there are no elements in indexes from 0\n             * to rehashidx-1 */\n            h = d->rehashidx + (random() % (d->ht[0].size +\n                                            d->ht[1].size -\n                                            d->rehashidx));\n            he = (h >= d->ht[0].size) ? d->ht[1].table[h - d->ht[0].size] :\n                                      d->ht[0].table[h];\n        } while(he == NULL);\n    } else {\n        do {\n            h = random() & d->ht[0].sizemask;\n            he = d->ht[0].table[h];\n        } while(he == NULL);\n    }\n\n    /* Now we found a non empty bucket, but it is a linked\n     * list and we need to get a random element from the list.\n     * The only sane way to do so is counting the elements and\n     * select a random index. */\n    listlen = 0;\n    orighe = he;\n    while(he) {\n        he = he->next;\n        listlen++;\n    }\n    listele = random() % listlen;\n    he = orighe;\n    while(listele--) he = he->next;\n    return he;\n}\n\n/* This function samples the dictionary to return a few keys from random\n * locations.\n *\n * It does not guarantee to return all the keys specified in 'count', nor\n * it does guarantee to return non-duplicated elements, however it will make\n * some effort to do both things.\n *\n * Returned pointers to hash table entries are stored into 'des' that\n * points to an array of dictEntry pointers. The array must have room for\n * at least 'count' elements, that is the argument we pass to the function\n * to tell how many random elements we need.\n *\n * The function returns the number of items stored into 'des', that may\n * be less than 'count' if the hash table has less than 'count' elements\n * inside, or if not enough elements were found in a reasonable amount of\n * steps.\n *\n * Note that this function is not suitable when you need a good distribution\n * of the returned items, but only when you need to \"sample\" a given number\n * of continuous elements to run some kind of algorithm or to produce\n * statistics. However the function is much faster than dictGetRandomKey()\n * at producing N elements. */\nunsigned int dictGetSomeKeys(dict *d, dictEntry **des, unsigned int count) {\n    unsigned long j; /* internal hash table id, 0 or 1. */\n    unsigned long tables; /* 1 or 2 tables? */\n    unsigned long stored = 0, maxsizemask;\n    unsigned long maxsteps;\n\n    if (dictSize(d) < count) count = dictSize(d);\n    maxsteps = count*10;\n\n    /* Try to do a rehashing work proportional to 'count'. */\n    for (j = 0; j < count; j++) {\n        if (dictIsRehashing(d))\n            _dictRehashStep(d);\n        else\n            break;\n    }\n\n    tables = dictIsRehashing(d) ? 2 : 1;\n    maxsizemask = d->ht[0].sizemask;\n    if (tables > 1 && maxsizemask < d->ht[1].sizemask)\n        maxsizemask = d->ht[1].sizemask;\n\n    /* Pick a random point inside the larger table. */\n    unsigned long i = random() & maxsizemask;\n    unsigned long emptylen = 0; /* Continuous empty entries so far. */\n    while(stored < count && maxsteps--) {\n        for (j = 0; j < tables; j++) {\n            /* Invariant of the dict.c rehashing: up to the indexes already\n             * visited in ht[0] during the rehashing, there are no populated\n             * buckets, so we can skip ht[0] for indexes between 0 and idx-1. */\n            if (tables == 2 && j == 0 && i < (unsigned long) d->rehashidx) {\n                /* Moreover, if we are currently out of range in the second\n                 * table, there will be no elements in both tables up to\n                 * the current rehashing index, so we jump if possible.\n                 * (this happens when going from big to small table). */\n                if (i >= d->ht[1].size) i = d->rehashidx;\n                continue;\n            }\n            if (i >= d->ht[j].size) continue; /* Out of range for this table. */\n            dictEntry *he = d->ht[j].table[i];\n\n            /* Count contiguous empty buckets, and jump to other\n             * locations if they reach 'count' (with a minimum of 5). */\n            if (he == NULL) {\n                emptylen++;\n                if (emptylen >= 5 && emptylen > count) {\n                    i = random() & maxsizemask;\n                    emptylen = 0;\n                }\n            } else {\n                emptylen = 0;\n                while (he) {\n                    /* Collect all the elements of the buckets found non\n                     * empty while iterating. */\n                    *des = he;\n                    des++;\n                    he = he->next;\n                    stored++;\n                    if (stored == count) return stored;\n                }\n            }\n        }\n        i = (i+1) & maxsizemask;\n    }\n    return stored;\n}\n\n/* Function to reverse bits. Algorithm from:\n * http://graphics.stanford.edu/~seander/bithacks.html#ReverseParallel */\nstatic unsigned long rev(unsigned long v) {\n    unsigned long s = 8 * sizeof(v); // bit size; must be power of 2\n    unsigned long mask = ~0;\n    while ((s >>= 1) > 0) {\n        mask ^= (mask << s);\n        v = ((v >> s) & mask) | ((v << s) & ~mask);\n    }\n    return v;\n}\n\n/* dictScan() is used to iterate over the elements of a dictionary.\n *\n * Iterating works the following way:\n *\n * 1) Initially you call the function using a cursor (v) value of 0.\n * 2) The function performs one step of the iteration, and returns the\n *    new cursor value you must use in the next call.\n * 3) When the returned cursor is 0, the iteration is complete.\n *\n * The function guarantees all elements present in the\n * dictionary get returned between the start and end of the iteration.\n * However it is possible some elements get returned multiple times.\n *\n * For every element returned, the callback argument 'fn' is\n * called with 'privdata' as first argument and the dictionary entry\n * 'de' as second argument.\n *\n * HOW IT WORKS.\n *\n * The iteration algorithm was designed by Pieter Noordhuis.\n * The main idea is to increment a cursor starting from the higher order\n * bits. That is, instead of incrementing the cursor normally, the bits\n * of the cursor are reversed, then the cursor is incremented, and finally\n * the bits are reversed again.\n *\n * This strategy is needed because the hash table may be resized between\n * iteration calls.\n *\n * dict.c hash tables are always power of two in size, and they\n * use chaining, so the position of an element in a given table is given\n * by computing the bitwise AND between Hash(key) and SIZE-1\n * (where SIZE-1 is always the mask that is equivalent to taking the rest\n *  of the division between the Hash of the key and SIZE).\n *\n * For example if the current hash table size is 16, the mask is\n * (in binary) 1111. The position of a key in the hash table will always be\n * the last four bits of the hash output, and so forth.\n *\n * WHAT HAPPENS IF THE TABLE CHANGES IN SIZE?\n *\n * If the hash table grows, elements can go anywhere in one multiple of\n * the old bucket: for example let's say we already iterated with\n * a 4 bit cursor 1100 (the mask is 1111 because hash table size = 16).\n *\n * If the hash table will be resized to 64 elements, then the new mask will\n * be 111111. The new buckets you obtain by substituting in ??1100\n * with either 0 or 1 can be targeted only by keys we already visited\n * when scanning the bucket 1100 in the smaller hash table.\n *\n * By iterating the higher bits first, because of the inverted counter, the\n * cursor does not need to restart if the table size gets bigger. It will\n * continue iterating using cursors without '1100' at the end, and also\n * without any other combination of the final 4 bits already explored.\n *\n * Similarly when the table size shrinks over time, for example going from\n * 16 to 8, if a combination of the lower three bits (the mask for size 8\n * is 111) were already completely explored, it would not be visited again\n * because we are sure we tried, for example, both 0111 and 1111 (all the\n * variations of the higher bit) so we don't need to test it again.\n *\n * WAIT... YOU HAVE *TWO* TABLES DURING REHASHING!\n *\n * Yes, this is true, but we always iterate the smaller table first, then\n * we test all the expansions of the current cursor into the larger\n * table. For example if the current cursor is 101 and we also have a\n * larger table of size 16, we also test (0)101 and (1)101 inside the larger\n * table. This reduces the problem back to having only one table, where\n * the larger one, if it exists, is just an expansion of the smaller one.\n *\n * LIMITATIONS\n *\n * This iterator is completely stateless, and this is a huge advantage,\n * including no additional memory used.\n *\n * The disadvantages resulting from this design are:\n *\n * 1) It is possible we return elements more than once. However this is usually\n *    easy to deal with in the application level.\n * 2) The iterator must return multiple elements per call, as it needs to always\n *    return all the keys chained in a given bucket, and all the expansions, so\n *    we are sure we don't miss keys moving during rehashing.\n * 3) The reverse cursor is somewhat hard to understand at first, but this\n *    comment is supposed to help.\n */\nunsigned long dictScan(dict *d,\n                       unsigned long v,\n                       dictScanFunction *fn,\n                       void *privdata)\n{\n    dictht *t0, *t1;\n    const dictEntry *de;\n    unsigned long m0, m1;\n\n    if (dictSize(d) == 0) return 0;\n\n    if (!dictIsRehashing(d)) {\n        t0 = &(d->ht[0]);\n        m0 = t0->sizemask;\n\n        /* Emit entries at cursor */\n        de = t0->table[v & m0];\n        while (de) {\n            fn(privdata, de);\n            de = de->next;\n        }\n\n    } else {\n        t0 = &d->ht[0];\n        t1 = &d->ht[1];\n\n        /* Make sure t0 is the smaller and t1 is the bigger table */\n        if (t0->size > t1->size) {\n            t0 = &d->ht[1];\n            t1 = &d->ht[0];\n        }\n\n        m0 = t0->sizemask;\n        m1 = t1->sizemask;\n\n        /* Emit entries at cursor */\n        de = t0->table[v & m0];\n        while (de) {\n            fn(privdata, de);\n            de = de->next;\n        }\n\n        /* Iterate over indices in larger table that are the expansion\n         * of the index pointed to by the cursor in the smaller table */\n        do {\n            /* Emit entries at cursor */\n            de = t1->table[v & m1];\n            while (de) {\n                fn(privdata, de);\n                de = de->next;\n            }\n\n            /* Increment bits not covered by the smaller mask */\n            v = (((v | m0) + 1) & ~m0) | (v & m0);\n\n            /* Continue while bits covered by mask difference is non-zero */\n        } while (v & (m0 ^ m1));\n    }\n\n    /* Set unmasked bits so incrementing the reversed cursor\n     * operates on the masked bits of the smaller table */\n    v |= ~m0;\n\n    /* Increment the reverse cursor */\n    v = rev(v);\n    v++;\n    v = rev(v);\n\n    return v;\n}\n\n/* ------------------------- private functions ------------------------------ */\n\n/* Expand the hash table if needed */\nstatic int _dictExpandIfNeeded(dict *d)\n{\n    /* Incremental rehashing already in progress. Return. */\n    if (dictIsRehashing(d)) return DICT_OK;\n\n    /* If the hash table is empty expand it to the initial size. */\n    if (d->ht[0].size == 0) return dictExpand(d, DICT_HT_INITIAL_SIZE);\n\n    /* If we reached the 1:1 ratio, and we are allowed to resize the hash\n     * table (global setting) or we should avoid it but the ratio between\n     * elements/buckets is over the \"safe\" threshold, we resize doubling\n     * the number of buckets. */\n    if (d->ht[0].used >= d->ht[0].size &&\n        (dict_can_resize ||\n         d->ht[0].used/d->ht[0].size > dict_force_resize_ratio))\n    {\n        return dictExpand(d, d->ht[0].used*2);\n    }\n    return DICT_OK;\n}\n\n/* Our hash table capability is a power of two */\nstatic unsigned long _dictNextPower(unsigned long size)\n{\n    unsigned long i = DICT_HT_INITIAL_SIZE;\n\n    if (size >= LONG_MAX) return LONG_MAX;\n    while(1) {\n        if (i >= size)\n            return i;\n        i *= 2;\n    }\n}\n\n/* Returns the index of a free slot that can be populated with\n * a hash entry for the given 'key'.\n * If the key already exists, -1 is returned.\n *\n * Note that if we are in the process of rehashing the hash table, the\n * index is always returned in the context of the second (new) hash table. */\nstatic int _dictKeyIndex(dict *d, const void *key)\n{\n    unsigned int h, idx, table;\n    dictEntry *he;\n\n    /* Expand the hash table if needed */\n    if (_dictExpandIfNeeded(d) == DICT_ERR)\n        return -1;\n    /* Compute the key hash value */\n    h = dictHashKey(d, key);\n    for (table = 0; table <= 1; table++) {\n        idx = h & d->ht[table].sizemask;\n        /* Search if this slot does not already contain the given key */\n        he = d->ht[table].table[idx];\n        while(he) {\n            if (key==he->key || dictCompareKeys(d, key, he->key))\n                return -1;\n            he = he->next;\n        }\n        if (!dictIsRehashing(d)) break;\n    }\n    return idx;\n}\n\nvoid dictEmpty(dict *d, void(callback)(void*)) {\n    _dictClear(d,&d->ht[0],callback);\n    _dictClear(d,&d->ht[1],callback);\n    d->rehashidx = -1;\n    d->iterators = 0;\n}\n\nvoid dictEnableResize(void) {\n    dict_can_resize = 1;\n}\n\nvoid dictDisableResize(void) {\n    dict_can_resize = 0;\n}\n\n/* ------------------------------- Debugging ---------------------------------*/\n\n#define DICT_STATS_VECTLEN 50\nsize_t _dictGetStatsHt(char *buf, size_t bufsize, dictht *ht, int tableid) {\n    unsigned long i, slots = 0, chainlen, maxchainlen = 0;\n    unsigned long totchainlen = 0;\n    unsigned long clvector[DICT_STATS_VECTLEN];\n    size_t l = 0;\n\n    if (ht->used == 0) {\n        return snprintf(buf,bufsize,\n            \"No stats available for empty dictionaries\\n\");\n    }\n\n    /* Compute stats. */\n    for (i = 0; i < DICT_STATS_VECTLEN; i++) clvector[i] = 0;\n    for (i = 0; i < ht->size; i++) {\n        dictEntry *he;\n\n        if (ht->table[i] == NULL) {\n            clvector[0]++;\n            continue;\n        }\n        slots++;\n        /* For each hash entry on this slot... */\n        chainlen = 0;\n        he = ht->table[i];\n        while(he) {\n            chainlen++;\n            he = he->next;\n        }\n        clvector[(chainlen < DICT_STATS_VECTLEN) ? chainlen : (DICT_STATS_VECTLEN-1)]++;\n        if (chainlen > maxchainlen) maxchainlen = chainlen;\n        totchainlen += chainlen;\n    }\n\n    /* Generate human readable stats. */\n    l += snprintf(buf+l,bufsize-l,\n        \"Hash table %d stats (%s):\\n\"\n        \" table size: %ld\\n\"\n        \" number of elements: %ld\\n\"\n        \" different slots: %ld\\n\"\n        \" max chain length: %ld\\n\"\n        \" avg chain length (counted): %.02f\\n\"\n        \" avg chain length (computed): %.02f\\n\"\n        \" Chain length distribution:\\n\",\n        tableid, (tableid == 0) ? \"main hash table\" : \"rehashing target\",\n        ht->size, ht->used, slots, maxchainlen,\n        (float)totchainlen/slots, (float)ht->used/slots);\n\n    for (i = 0; i < DICT_STATS_VECTLEN-1; i++) {\n        if (clvector[i] == 0) continue;\n        if (l >= bufsize) break;\n        l += snprintf(buf+l,bufsize-l,\n            \"   %s%ld: %ld (%.02f%%)\\n\",\n            (i == DICT_STATS_VECTLEN-1)?\">= \":\"\",\n            i, clvector[i], ((float)clvector[i]/ht->size)*100);\n    }\n\n    /* Unlike snprintf(), teturn the number of characters actually written. */\n    if (bufsize) buf[bufsize-1] = '\\0';\n    return strlen(buf);\n}\n\nvoid dictGetStats(char *buf, size_t bufsize, dict *d) {\n    size_t l;\n    char *orig_buf = buf;\n    size_t orig_bufsize = bufsize;\n\n    l = _dictGetStatsHt(buf,bufsize,&d->ht[0],0);\n    buf += l;\n    bufsize -= l;\n    if (dictIsRehashing(d) && bufsize > 0) {\n        _dictGetStatsHt(buf,bufsize,&d->ht[1],1);\n    }\n    /* Make sure there is a NULL term at the end. */\n    if (orig_bufsize) orig_buf[orig_bufsize-1] = '\\0';\n}\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/src/dict.h",
    "content": "/* Hash Tables Implementation.\n *\n * This file implements in-memory hash tables with insert/del/replace/find/\n * get-random-element operations. Hash tables will auto-resize if needed\n * tables of power of two in size are used, collisions are handled by\n * chaining. See the source code for more information... :)\n *\n * Copyright (c) 2006-2012, Salvatore Sanfilippo <antirez at gmail dot com>\n * All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions are met:\n *\n *   * Redistributions of source code must retain the above copyright notice,\n *     this list of conditions and the following disclaimer.\n *   * Redistributions in binary form must reproduce the above copyright\n *     notice, this list of conditions and the following disclaimer in the\n *     documentation and/or other materials provided with the distribution.\n *   * Neither the name of Redis nor the names of its contributors may be used\n *     to endorse or promote products derived from this software without\n *     specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\"\n * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\n * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE\n * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR\n * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF\n * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS\n * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN\n * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)\n * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE\n * POSSIBILITY OF SUCH DAMAGE.\n */\n\n#include <stdint.h>\n\n#ifndef __DICT_H\n#define __DICT_H\n\n#define DICT_OK 0\n#define DICT_ERR 1\n\n/* Unused arguments generate annoying warnings... */\n#define DICT_NOTUSED(V) ((void) V)\n\ntypedef struct dictEntry {\n    void *key;\n    union {\n        void *val;\n        uint64_t u64;\n        int64_t s64;\n        double d;\n    } v;\n    struct dictEntry *next;\n} dictEntry;\n\ntypedef struct dictType {\n    unsigned int (*hashFunction)(const void *key);\n    void *(*keyDup)(void *privdata, const void *key);\n    void *(*valDup)(void *privdata, const void *obj);\n    int (*keyCompare)(void *privdata, const void *key1, const void *key2);\n    void (*keyDestructor)(void *privdata, void *key);\n    void (*valDestructor)(void *privdata, void *obj);\n} dictType;\n\n/* This is our hash table structure. Every dictionary has two of this as we\n * implement incremental rehashing, for the old to the new table. */\ntypedef struct dictht {\n    dictEntry **table;\n    unsigned long size;\n    unsigned long sizemask;\n    unsigned long used;\n} dictht;\n\ntypedef struct dict {\n    dictType *type;\n    void *privdata;\n    dictht ht[2];\n    long rehashidx; /* rehashing not in progress if rehashidx == -1 */\n    int iterators; /* number of iterators currently running */\n} dict;\n\n/* If safe is set to 1 this is a safe iterator, that means, you can call\n * dictAdd, dictFind, and other functions against the dictionary even while\n * iterating. Otherwise it is a non safe iterator, and only dictNext()\n * should be called while iterating. */\ntypedef struct dictIterator {\n    dict *d;\n    long index;\n    int table, safe;\n    dictEntry *entry, *nextEntry;\n    /* unsafe iterator fingerprint for misuse detection. */\n    long long fingerprint;\n} dictIterator;\n\ntypedef void (dictScanFunction)(void *privdata, const dictEntry *de);\n\n/* This is the initial size of every hash table */\n#define DICT_HT_INITIAL_SIZE     4\n\n/* ------------------------------- Macros ------------------------------------*/\n#define dictFreeVal(d, entry) \\\n    if ((d)->type->valDestructor) \\\n        (d)->type->valDestructor((d)->privdata, (entry)->v.val)\n\n#define dictSetVal(d, entry, _val_) do { \\\n    if ((d)->type->valDup) \\\n        entry->v.val = (d)->type->valDup((d)->privdata, _val_); \\\n    else \\\n        entry->v.val = (_val_); \\\n} while(0)\n\n#define dictSetSignedIntegerVal(entry, _val_) \\\n    do { entry->v.s64 = _val_; } while(0)\n\n#define dictSetUnsignedIntegerVal(entry, _val_) \\\n    do { entry->v.u64 = _val_; } while(0)\n\n#define dictSetDoubleVal(entry, _val_) \\\n    do { entry->v.d = _val_; } while(0)\n\n#define dictFreeKey(d, entry) \\\n    if ((d)->type->keyDestructor) \\\n        (d)->type->keyDestructor((d)->privdata, (entry)->key)\n\n#define dictSetKey(d, entry, _key_) do { \\\n    if ((d)->type->keyDup) \\\n        entry->key = (d)->type->keyDup((d)->privdata, _key_); \\\n    else \\\n        entry->key = (_key_); \\\n} while(0)\n\n#define dictCompareKeys(d, key1, key2) \\\n    (((d)->type->keyCompare) ? \\\n        (d)->type->keyCompare((d)->privdata, key1, key2) : \\\n        (key1) == (key2))\n\n#define dictHashKey(d, key) (d)->type->hashFunction(key)\n#define dictGetKey(he) ((he)->key)\n#define dictGetVal(he) ((he)->v.val)\n#define dictGetSignedIntegerVal(he) ((he)->v.s64)\n#define dictGetUnsignedIntegerVal(he) ((he)->v.u64)\n#define dictGetDoubleVal(he) ((he)->v.d)\n#define dictSlots(d) ((d)->ht[0].size+(d)->ht[1].size)\n#define dictSize(d) ((d)->ht[0].used+(d)->ht[1].used)\n#define dictIsRehashing(d) ((d)->rehashidx != -1)\n\n/* API */\ndict *dictCreate(dictType *type, void *privDataPtr);\nint dictExpand(dict *d, unsigned long size);\nint dictAdd(dict *d, void *key, void *val);\ndictEntry *dictAddRaw(dict *d, void *key);\nint dictReplace(dict *d, void *key, void *val);\ndictEntry *dictReplaceRaw(dict *d, void *key);\nint dictDelete(dict *d, const void *key);\nint dictDeleteNoFree(dict *d, const void *key);\nvoid dictRelease(dict *d);\ndictEntry * dictFind(dict *d, const void *key);\nvoid *dictFetchValue(dict *d, const void *key);\nint dictResize(dict *d);\ndictIterator *dictGetIterator(dict *d);\ndictIterator *dictGetSafeIterator(dict *d);\ndictEntry *dictNext(dictIterator *iter);\nvoid dictReleaseIterator(dictIterator *iter);\ndictEntry *dictGetRandomKey(dict *d);\nunsigned int dictGetSomeKeys(dict *d, dictEntry **des, unsigned int count);\nvoid dictGetStats(char *buf, size_t bufsize, dict *d);\nunsigned int dictGenHashFunction(const void *key, int len);\nunsigned int dictGenCaseHashFunction(const unsigned char *buf, int len);\nvoid dictEmpty(dict *d, void(callback)(void*));\nvoid dictEnableResize(void);\nvoid dictDisableResize(void);\nint dictRehash(dict *d, int n);\nint dictRehashMilliseconds(dict *d, int ms);\nvoid dictSetHashFunctionSeed(unsigned int initval);\nunsigned int dictGetHashFunctionSeed(void);\nunsigned long dictScan(dict *d, unsigned long v, dictScanFunction *fn, void *privdata);\n\n/* Hash table types */\nextern dictType dictTypeHeapStringCopyKey;\nextern dictType dictTypeHeapStrings;\nextern dictType dictTypeHeapStringCopyKeyValue;\n\n#endif /* __DICT_H */\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/src/endianconv.c",
    "content": "/* endinconv.c -- Endian conversions utilities.\n *\n * This functions are never called directly, but always using the macros\n * defined into endianconv.h, this way we define everything is a non-operation\n * if the arch is already little endian.\n *\n * Redis tries to encode everything as little endian (but a few things that need\n * to be backward compatible are still in big endian) because most of the\n * production environments are little endian, and we have a lot of conversions\n * in a few places because ziplists, intsets, zipmaps, need to be endian-neutral\n * even in memory, since they are serialied on RDB files directly with a single\n * write(2) without other additional steps.\n *\n * ----------------------------------------------------------------------------\n *\n * Copyright (c) 2011-2012, Salvatore Sanfilippo <antirez at gmail dot com>\n * All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions are met:\n *\n *   * Redistributions of source code must retain the above copyright notice,\n *     this list of conditions and the following disclaimer.\n *   * Redistributions in binary form must reproduce the above copyright\n *     notice, this list of conditions and the following disclaimer in the\n *     documentation and/or other materials provided with the distribution.\n *   * Neither the name of Redis nor the names of its contributors may be used\n *     to endorse or promote products derived from this software without\n *     specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\"\n * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\n * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE\n * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR\n * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF\n * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS\n * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN\n * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)\n * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE\n * POSSIBILITY OF SUCH DAMAGE.\n */\n\n\n#include <stdint.h>\n\n/* Toggle the 16 bit unsigned integer pointed by *p from little endian to\n * big endian */\nvoid memrev16(void *p) {\n    unsigned char *x = p, t;\n\n    t = x[0];\n    x[0] = x[1];\n    x[1] = t;\n}\n\n/* Toggle the 32 bit unsigned integer pointed by *p from little endian to\n * big endian */\nvoid memrev32(void *p) {\n    unsigned char *x = p, t;\n\n    t = x[0];\n    x[0] = x[3];\n    x[3] = t;\n    t = x[1];\n    x[1] = x[2];\n    x[2] = t;\n}\n\n/* Toggle the 64 bit unsigned integer pointed by *p from little endian to\n * big endian */\nvoid memrev64(void *p) {\n    unsigned char *x = p, t;\n\n    t = x[0];\n    x[0] = x[7];\n    x[7] = t;\n    t = x[1];\n    x[1] = x[6];\n    x[6] = t;\n    t = x[2];\n    x[2] = x[5];\n    x[5] = t;\n    t = x[3];\n    x[3] = x[4];\n    x[4] = t;\n}\n\nuint16_t intrev16(uint16_t v) {\n    memrev16(&v);\n    return v;\n}\n\nuint32_t intrev32(uint32_t v) {\n    memrev32(&v);\n    return v;\n}\n\nuint64_t intrev64(uint64_t v) {\n    memrev64(&v);\n    return v;\n}\n\n#ifdef REDIS_TEST\n#include <stdio.h>\n\n#define UNUSED(x) (void)(x)\nint endianconvTest(int argc, char *argv[]) {\n    char buf[32];\n\n    UNUSED(argc);\n    UNUSED(argv);\n\n    sprintf(buf,\"ciaoroma\");\n    memrev16(buf);\n    printf(\"%s\\n\", buf);\n\n    sprintf(buf,\"ciaoroma\");\n    memrev32(buf);\n    printf(\"%s\\n\", buf);\n\n    sprintf(buf,\"ciaoroma\");\n    memrev64(buf);\n    printf(\"%s\\n\", buf);\n\n    return 0;\n}\n#endif\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/src/endianconv.h",
    "content": "/* See endianconv.c top comments for more information\n *\n * ----------------------------------------------------------------------------\n *\n * Copyright (c) 2011-2012, Salvatore Sanfilippo <antirez at gmail dot com>\n * All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions are met:\n *\n *   * Redistributions of source code must retain the above copyright notice,\n *     this list of conditions and the following disclaimer.\n *   * Redistributions in binary form must reproduce the above copyright\n *     notice, this list of conditions and the following disclaimer in the\n *     documentation and/or other materials provided with the distribution.\n *   * Neither the name of Redis nor the names of its contributors may be used\n *     to endorse or promote products derived from this software without\n *     specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\"\n * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\n * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE\n * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR\n * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF\n * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS\n * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN\n * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)\n * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE\n * POSSIBILITY OF SUCH DAMAGE.\n */\n\n#ifndef __ENDIANCONV_H\n#define __ENDIANCONV_H\n\n#include \"config.h\"\n#include <stdint.h>\n\nvoid memrev16(void *p);\nvoid memrev32(void *p);\nvoid memrev64(void *p);\nuint16_t intrev16(uint16_t v);\nuint32_t intrev32(uint32_t v);\nuint64_t intrev64(uint64_t v);\n\n/* variants of the function doing the actual convertion only if the target\n * host is big endian */\n#if (BYTE_ORDER == LITTLE_ENDIAN)\n#define memrev16ifbe(p)\n#define memrev32ifbe(p)\n#define memrev64ifbe(p)\n#define intrev16ifbe(v) (v)\n#define intrev32ifbe(v) (v)\n#define intrev64ifbe(v) (v)\n#else\n#define memrev16ifbe(p) memrev16(p)\n#define memrev32ifbe(p) memrev32(p)\n#define memrev64ifbe(p) memrev64(p)\n#define intrev16ifbe(v) intrev16(v)\n#define intrev32ifbe(v) intrev32(v)\n#define intrev64ifbe(v) intrev64(v)\n#endif\n\n/* The functions htonu64() and ntohu64() convert the specified value to\n * network byte ordering and back. In big endian systems they are no-ops. */\n#if (BYTE_ORDER == BIG_ENDIAN)\n#define htonu64(v) (v)\n#define ntohu64(v) (v)\n#else\n#define htonu64(v) intrev64(v)\n#define ntohu64(v) intrev64(v)\n#endif\n\n#ifdef REDIS_TEST\nint endianconvTest(int argc, char *argv[]);\n#endif\n\n#endif\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/src/fmacros.h",
    "content": "/*\n * Copyright (c) 2009-2012, Salvatore Sanfilippo <antirez at gmail dot com>\n * All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions are met:\n *\n *   * Redistributions of source code must retain the above copyright notice,\n *     this list of conditions and the following disclaimer.\n *   * Redistributions in binary form must reproduce the above copyright\n *     notice, this list of conditions and the following disclaimer in the\n *     documentation and/or other materials provided with the distribution.\n *   * Neither the name of Redis nor the names of its contributors may be used\n *     to endorse or promote products derived from this software without\n *     specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\"\n * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\n * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE\n * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR\n * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF\n * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS\n * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN\n * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)\n * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE\n * POSSIBILITY OF SUCH DAMAGE.\n */\n\n#ifndef _REDIS_FMACRO_H\n#define _REDIS_FMACRO_H\n\n#define _BSD_SOURCE\n\n#if defined(__linux__)\n#define _GNU_SOURCE\n#define _DEFAULT_SOURCE\n#endif\n\n#if defined(_AIX)\n#define _ALL_SOURCE\n#endif\n\n#if defined(__linux__) || defined(__OpenBSD__)\n#define _XOPEN_SOURCE 700\n/*\n * On NetBSD, _XOPEN_SOURCE undefines _NETBSD_SOURCE and\n * thus hides inet_aton etc.\n */\n#elif !defined(__NetBSD__)\n#define _XOPEN_SOURCE\n#endif\n\n#if defined(__sun)\n#define _POSIX_C_SOURCE 199506L\n#endif\n\n#define _LARGEFILE_SOURCE\n#define _FILE_OFFSET_BITS 64\n\n#endif\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/src/geo.c",
    "content": "/*\n * Copyright (c) 2014, Matt Stancliff <matt@genges.com>.\n * Copyright (c) 2015-2016, Salvatore Sanfilippo <antirez@gmail.com>.\n * All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions are met:\n *\n *   * Redistributions of source code must retain the above copyright notice,\n *     this list of conditions and the following disclaimer.\n *   * Redistributions in binary form must reproduce the above copyright\n *     notice, this list of conditions and the following disclaimer in the\n *     documentation and/or other materials provided with the distribution.\n *   * Neither the name of Redis nor the names of its contributors may be used\n *     to endorse or promote products derived from this software without\n *     specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\"\n * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\n * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE\n * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR\n * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF\n * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS\n * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN\n * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)\n * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE\n * POSSIBILITY OF SUCH DAMAGE.\n */\n\n#include \"geo.h\"\n#include \"geohash_helper.h\"\n#include \"debugmacro.h\"\n\n/* Things exported from t_zset.c only for geo.c, since it is the only other\n * part of Redis that requires close zset introspection. */\nunsigned char *zzlFirstInRange(unsigned char *zl, zrangespec *range);\nint zslValueLteMax(double value, zrangespec *spec);\n\n/* ====================================================================\n * This file implements the following commands:\n *\n *   - geoadd - add coordinates for value to geoset\n *   - georadius - search radius by coordinates in geoset\n *   - georadiusbymember - search radius based on geoset member position\n * ==================================================================== */\n\n/* ====================================================================\n * geoArray implementation\n * ==================================================================== */\n\n/* Create a new array of geoPoints. */\ngeoArray *geoArrayCreate(void) {\n    geoArray *ga = zmalloc(sizeof(*ga));\n    /* It gets allocated on first geoArrayAppend() call. */\n    ga->array = NULL;\n    ga->buckets = 0;\n    ga->used = 0;\n    return ga;\n}\n\n/* Add a new entry and return its pointer so that the caller can populate\n * it with data. */\ngeoPoint *geoArrayAppend(geoArray *ga) {\n    if (ga->used == ga->buckets) {\n        ga->buckets = (ga->buckets == 0) ? 8 : ga->buckets*2;\n        ga->array = zrealloc(ga->array,sizeof(geoPoint)*ga->buckets);\n    }\n    geoPoint *gp = ga->array+ga->used;\n    ga->used++;\n    return gp;\n}\n\n/* Destroy a geoArray created with geoArrayCreate(). */\nvoid geoArrayFree(geoArray *ga) {\n    size_t i;\n    for (i = 0; i < ga->used; i++) sdsfree(ga->array[i].member);\n    zfree(ga->array);\n    zfree(ga);\n}\n\n/* ====================================================================\n * Helpers\n * ==================================================================== */\nint decodeGeohash(double bits, double *xy) {\n    GeoHashBits hash = { .bits = (uint64_t)bits, .step = GEO_STEP_MAX };\n    return geohashDecodeToLongLatWGS84(hash, xy);\n}\n\n/* Input Argument Helper */\n/* Take a pointer to the latitude arg then use the next arg for longitude.\n * On parse error C_ERR is returned, otherwise C_OK. */\nint extractLongLatOrReply(client *c, robj **argv, double *xy) {\n    int i;\n    for (i = 0; i < 2; i++) {\n        if (getDoubleFromObjectOrReply(c, argv[i], xy + i, NULL) !=\n            C_OK) {\n            return C_ERR;\n        }\n    }\n    if (xy[0] < GEO_LONG_MIN || xy[0] > GEO_LONG_MAX ||\n        xy[1] < GEO_LAT_MIN  || xy[1] > GEO_LAT_MAX) {\n        addReplySds(c, sdscatprintf(sdsempty(),\n            \"-ERR invalid longitude,latitude pair %f,%f\\r\\n\",xy[0],xy[1]));\n        return C_ERR;\n    }\n    return C_OK;\n}\n\n/* Input Argument Helper */\n/* Decode lat/long from a zset member's score.\n * Returns C_OK on successful decoding, otherwise C_ERR is returned. */\nint longLatFromMember(robj *zobj, robj *member, double *xy) {\n    double score = 0;\n\n    if (zsetScore(zobj, member, &score) == C_ERR) return C_ERR;\n    if (!decodeGeohash(score, xy)) return C_ERR;\n    return C_OK;\n}\n\n/* Check that the unit argument matches one of the known units, and returns\n * the conversion factor to meters (you need to divide meters by the conversion\n * factor to convert to the right unit).\n *\n * If the unit is not valid, an error is reported to the client, and a value\n * less than zero is returned. */\ndouble extractUnitOrReply(client *c, robj *unit) {\n    char *u = unit->ptr;\n\n    if (!strcmp(u, \"m\")) {\n        return 1;\n    } else if (!strcmp(u, \"km\")) {\n        return 1000;\n    } else if (!strcmp(u, \"ft\")) {\n        return 0.3048;\n    } else if (!strcmp(u, \"mi\")) {\n        return 1609.34;\n    } else {\n        addReplyError(c,\n            \"unsupported unit provided. please use m, km, ft, mi\");\n        return -1;\n    }\n}\n\n/* Input Argument Helper.\n * Extract the dinstance from the specified two arguments starting at 'argv'\n * that shouldbe in the form: <number> <unit> and return the dinstance in the\n * specified unit on success. *conversino is populated with the coefficient\n * to use in order to convert meters to the unit.\n *\n * On error a value less than zero is returned. */\ndouble extractDistanceOrReply(client *c, robj **argv,\n                                     double *conversion) {\n    double distance;\n    if (getDoubleFromObjectOrReply(c, argv[0], &distance,\n                                   \"need numeric radius\") != C_OK) {\n        return -1;\n    }\n\n    if (distance < 0) {\n        addReplyError(c,\"radius cannot be negative\");\n        return -1;\n    }\n    \n    double to_meters = extractUnitOrReply(c,argv[1]);\n    if (to_meters < 0) {\n        return -1;\n    }\n\n    if (conversion) *conversion = to_meters;\n    return distance * to_meters;\n}\n\n/* The default addReplyDouble has too much accuracy.  We use this\n * for returning location distances. \"5.2145 meters away\" is nicer\n * than \"5.2144992818115 meters away.\" We provide 4 digits after the dot\n * so that the returned value is decently accurate even when the unit is\n * the kilometer. */\nvoid addReplyDoubleDistance(client *c, double d) {\n    char dbuf[128];\n    int dlen = snprintf(dbuf, sizeof(dbuf), \"%.4f\", d);\n    addReplyBulkCBuffer(c, dbuf, dlen);\n}\n\n/* Helper function for geoGetPointsInRange(): given a sorted set score\n * representing a point, and another point (the center of our search) and\n * a radius, appends this entry as a geoPoint into the specified geoArray\n * only if the point is within the search area.\n *\n * returns C_OK if the point is included, or REIDS_ERR if it is outside. */\nint geoAppendIfWithinRadius(geoArray *ga, double lon, double lat, double radius, double score, sds member) {\n    double distance, xy[2];\n\n    if (!decodeGeohash(score,xy)) return C_ERR; /* Can't decode. */\n    /* Note that geohashGetDistanceIfInRadiusWGS84() takes arguments in\n     * reverse order: longitude first, latitude later. */\n    if (!geohashGetDistanceIfInRadiusWGS84(lon,lat, xy[0], xy[1],\n                                           radius, &distance))\n    {\n        return C_ERR;\n    }\n\n    /* Append the new element. */\n    geoPoint *gp = geoArrayAppend(ga);\n    gp->longitude = xy[0];\n    gp->latitude = xy[1];\n    gp->dist = distance;\n    gp->member = member;\n    gp->score = score;\n    return C_OK;\n}\n\n/* Query a Redis sorted set to extract all the elements between 'min' and\n * 'max', appending them into the array of geoPoint structures 'gparray'.\n * The command returns the number of elements added to the array.\n *\n * Elements which are farest than 'radius' from the specified 'x' and 'y'\n * coordinates are not included.\n *\n * The ability of this function to append to an existing set of points is\n * important for good performances because querying by radius is performed\n * using multiple queries to the sorted set, that we later need to sort\n * via qsort. Similarly we need to be able to reject points outside the search\n * radius area ASAP in order to allocate and process more points than needed. */\nint geoGetPointsInRange(robj *zobj, double min, double max, double lon, double lat, double radius, geoArray *ga) {\n    /* minex 0 = include min in range; maxex 1 = exclude max in range */\n    /* That's: min <= val < max */\n    zrangespec range = { .min = min, .max = max, .minex = 0, .maxex = 1 };\n    size_t origincount = ga->used;\n    sds member;\n\n    if (zobj->encoding == OBJ_ENCODING_ZIPLIST) {\n        unsigned char *zl = zobj->ptr;\n        unsigned char *eptr, *sptr;\n        unsigned char *vstr = NULL;\n        unsigned int vlen = 0;\n        long long vlong = 0;\n        double score = 0;\n\n        if ((eptr = zzlFirstInRange(zl, &range)) == NULL) {\n            /* Nothing exists starting at our min.  No results. */\n            return 0;\n        }\n\n        sptr = ziplistNext(zl, eptr);\n        while (eptr) {\n            score = zzlGetScore(sptr);\n\n            /* If we fell out of range, break. */\n            if (!zslValueLteMax(score, &range))\n                break;\n\n            /* We know the element exists. ziplistGet should always succeed */\n            ziplistGet(eptr, &vstr, &vlen, &vlong);\n            member = (vstr == NULL) ? sdsfromlonglong(vlong) :\n                                      sdsnewlen(vstr,vlen);\n            if (geoAppendIfWithinRadius(ga,lon,lat,radius,score,member)\n                == C_ERR) sdsfree(member);\n            zzlNext(zl, &eptr, &sptr);\n        }\n    } else if (zobj->encoding == OBJ_ENCODING_SKIPLIST) {\n        zset *zs = zobj->ptr;\n        zskiplist *zsl = zs->zsl;\n        zskiplistNode *ln;\n\n        if ((ln = zslFirstInRange(zsl, &range)) == NULL) {\n            /* Nothing exists starting at our min.  No results. */\n            return 0;\n        }\n\n        while (ln) {\n            robj *o = ln->obj;\n            /* Abort when the node is no longer in range. */\n            if (!zslValueLteMax(ln->score, &range))\n                break;\n\n            member = (o->encoding == OBJ_ENCODING_INT) ?\n                        sdsfromlonglong((long)o->ptr) :\n                        sdsdup(o->ptr);\n            if (geoAppendIfWithinRadius(ga,lon,lat,radius,ln->score,member)\n                == C_ERR) sdsfree(member);\n            ln = ln->level[0].forward;\n        }\n    }\n    return ga->used - origincount;\n}\n\n/* Compute the sorted set scores min (inclusive), max (exclusive) we should\n * query in order to retrieve all the elements inside the specified area\n * 'hash'. The two scores are returned by reference in *min and *max. */\nvoid scoresOfGeoHashBox(GeoHashBits hash, GeoHashFix52Bits *min, GeoHashFix52Bits *max) {\n    /* We want to compute the sorted set scores that will include all the\n     * elements inside the specified Geohash 'hash', which has as many\n     * bits as specified by hash.step * 2.\n     *\n     * So if step is, for example, 3, and the hash value in binary\n     * is 101010, since our score is 52 bits we want every element which\n     * is in binary: 101010?????????????????????????????????????????????\n     * Where ? can be 0 or 1.\n     *\n     * To get the min score we just use the initial hash value left\n     * shifted enough to get the 52 bit value. Later we increment the\n     * 6 bit prefis (see the hash.bits++ statement), and get the new\n     * prefix: 101011, which we align again to 52 bits to get the maximum\n     * value (which is excluded from the search). So we get everything\n     * between the two following scores (represented in binary):\n     *\n     * 1010100000000000000000000000000000000000000000000000 (included)\n     * and\n     * 1010110000000000000000000000000000000000000000000000 (excluded).\n     */\n    *min = geohashAlign52Bits(hash);\n    hash.bits++;\n    *max = geohashAlign52Bits(hash);\n}\n\n/* Obtain all members between the min/max of this geohash bounding box.\n * Populate a geoArray of GeoPoints by calling geoGetPointsInRange().\n * Return the number of points added to the array. */\nint membersOfGeoHashBox(robj *zobj, GeoHashBits hash, geoArray *ga, double lon, double lat, double radius) {\n    GeoHashFix52Bits min, max;\n\n    scoresOfGeoHashBox(hash,&min,&max);\n    return geoGetPointsInRange(zobj, min, max, lon, lat, radius, ga);\n}\n\n/* Search all eight neighbors + self geohash box */\nint membersOfAllNeighbors(robj *zobj, GeoHashRadius n, double lon, double lat, double radius, geoArray *ga) {\n    GeoHashBits neighbors[9];\n    unsigned int i, count = 0, last_processed = 0;\n\n    neighbors[0] = n.hash;\n    neighbors[1] = n.neighbors.north;\n    neighbors[2] = n.neighbors.south;\n    neighbors[3] = n.neighbors.east;\n    neighbors[4] = n.neighbors.west;\n    neighbors[5] = n.neighbors.north_east;\n    neighbors[6] = n.neighbors.north_west;\n    neighbors[7] = n.neighbors.south_east;\n    neighbors[8] = n.neighbors.south_west;\n\n    /* For each neighbor (*and* our own hashbox), get all the matching\n     * members and add them to the potential result list. */\n    for (i = 0; i < sizeof(neighbors) / sizeof(*neighbors); i++) {\n        if (HASHISZERO(neighbors[i]))\n            continue;\n\n        /* When a huge Radius (in the 5000 km range or more) is used,\n         * adjacent neighbors can be the same, leading to duplicated\n         * elements. Skip every range which is the same as the one\n         * processed previously. */\n        if (last_processed &&\n            neighbors[i].bits == neighbors[last_processed].bits &&\n            neighbors[i].step == neighbors[last_processed].step)\n            continue;\n        count += membersOfGeoHashBox(zobj, neighbors[i], ga, lon, lat, radius);\n        last_processed = i;\n    }\n    return count;\n}\n\n/* Sort comparators for qsort() */\nstatic int sort_gp_asc(const void *a, const void *b) {\n    const struct geoPoint *gpa = a, *gpb = b;\n    /* We can't do adist - bdist because they are doubles and\n     * the comparator returns an int. */\n    if (gpa->dist > gpb->dist)\n        return 1;\n    else if (gpa->dist == gpb->dist)\n        return 0;\n    else\n        return -1;\n}\n\nstatic int sort_gp_desc(const void *a, const void *b) {\n    return -sort_gp_asc(a, b);\n}\n\n/* ====================================================================\n * Commands\n * ==================================================================== */\n\n/* GEOADD key long lat name [long2 lat2 name2 ... longN latN nameN] */\nvoid geoaddCommand(client *c) {\n    /* Check arguments number for sanity. */\n    if ((c->argc - 2) % 3 != 0) {\n        /* Need an odd number of arguments if we got this far... */\n        addReplyError(c, \"syntax error. Try GEOADD key [x1] [y1] [name1] \"\n                         \"[x2] [y2] [name2] ... \");\n        return;\n    }\n\n    int elements = (c->argc - 2) / 3;\n    int argc = 2+elements*2; /* ZADD key score ele ... */\n    robj **argv = zcalloc(argc*sizeof(robj*));\n    argv[0] = createRawStringObject(\"zadd\",4);\n    argv[1] = c->argv[1]; /* key */\n    incrRefCount(argv[1]);\n\n    /* Create the argument vector to call ZADD in order to add all\n     * the score,value pairs to the requested zset, where score is actually\n     * an encoded version of lat,long. */\n    int i;\n    for (i = 0; i < elements; i++) {\n        double xy[2];\n\n        if (extractLongLatOrReply(c, (c->argv+2)+(i*3),xy) == C_ERR) {\n            for (i = 0; i < argc; i++)\n                if (argv[i]) decrRefCount(argv[i]);\n            zfree(argv);\n            return;\n        }\n\n        /* Turn the coordinates into the score of the element. */\n        GeoHashBits hash;\n        geohashEncodeWGS84(xy[0], xy[1], GEO_STEP_MAX, &hash);\n        GeoHashFix52Bits bits = geohashAlign52Bits(hash);\n        robj *score = createObject(OBJ_STRING, sdsfromlonglong(bits));\n        robj *val = c->argv[2 + i * 3 + 2];\n        argv[2+i*2] = score;\n        argv[3+i*2] = val;\n        incrRefCount(val);\n    }\n\n    /* Finally call ZADD that will do the work for us. */\n    replaceClientCommandVector(c,argc,argv);\n    zaddCommand(c);\n}\n\n#define SORT_NONE 0\n#define SORT_ASC 1\n#define SORT_DESC 2\n\n#define RADIUS_COORDS 1\n#define RADIUS_MEMBER 2\n\n/* GEORADIUS key x y radius unit [WITHDIST] [WITHHASH] [WITHCOORD] [ASC|DESC]\n *                               [COUNT count] [STORE key] [STOREDIST key]\n * GEORADIUSBYMEMBER key member radius unit ... options ... */\nvoid georadiusGeneric(client *c, int type) {\n    robj *key = c->argv[1];\n    robj *storekey = NULL;\n    int storedist = 0; /* 0 for STORE, 1 for STOREDIST. */\n\n    /* Look up the requested zset */\n    robj *zobj = NULL;\n    if ((zobj = lookupKeyReadOrReply(c, key, shared.emptymultibulk)) == NULL ||\n        checkType(c, zobj, OBJ_ZSET)) {\n        return;\n    }\n\n    /* Find long/lat to use for radius search based on inquiry type */\n    int base_args;\n    double xy[2] = { 0 };\n    if (type == RADIUS_COORDS) {\n        base_args = 6;\n        if (extractLongLatOrReply(c, c->argv + 2, xy) == C_ERR)\n            return;\n    } else if (type == RADIUS_MEMBER) {\n        base_args = 5;\n        robj *member = c->argv[2];\n        if (longLatFromMember(zobj, member, xy) == C_ERR) {\n            addReplyError(c, \"could not decode requested zset member\");\n            return;\n        }\n    } else {\n        addReplyError(c, \"unknown georadius search type\");\n        return;\n    }\n\n    /* Extract radius and units from arguments */\n    double radius_meters = 0, conversion = 1;\n    if ((radius_meters = extractDistanceOrReply(c, c->argv + base_args - 2,\n                                                &conversion)) < 0) {\n        return;\n    }\n\n    /* Discover and populate all optional parameters. */\n    int withdist = 0, withhash = 0, withcoords = 0;\n    int sort = SORT_NONE;\n    long long count = 0;\n    if (c->argc > base_args) {\n        int remaining = c->argc - base_args;\n        for (int i = 0; i < remaining; i++) {\n            char *arg = c->argv[base_args + i]->ptr;\n            if (!strcasecmp(arg, \"withdist\")) {\n                withdist = 1;\n            } else if (!strcasecmp(arg, \"withhash\")) {\n                withhash = 1;\n            } else if (!strcasecmp(arg, \"withcoord\")) {\n                withcoords = 1;\n            } else if (!strcasecmp(arg, \"asc\")) {\n                sort = SORT_ASC;\n            } else if (!strcasecmp(arg, \"desc\")) {\n                sort = SORT_DESC;\n            } else if (!strcasecmp(arg, \"count\") && (i+1) < remaining) {\n                if (getLongLongFromObjectOrReply(c, c->argv[base_args+i+1],\n                    &count, NULL) != C_OK) return;\n                if (count <= 0) {\n                    addReplyError(c,\"COUNT must be > 0\");\n                    return;\n                }\n                i++;\n            } else if (!strcasecmp(arg, \"store\") && (i+1) < remaining) {\n                storekey = c->argv[base_args+i+1];\n                storedist = 0;\n                i++;\n            } else if (!strcasecmp(arg, \"storedist\") && (i+1) < remaining) {\n                storekey = c->argv[base_args+i+1];\n                storedist = 1;\n                i++;\n            } else {\n                addReply(c, shared.syntaxerr);\n                return;\n            }\n        }\n    }\n\n    /* Trap options not compatible with STORE and STOREDIST. */\n    if (storekey && (withdist || withhash || withcoords)) {\n        addReplyError(c,\n            \"STORE option in GEORADIUS is not compatible with \"\n            \"WITHDIST, WITHHASH and WITHCOORDS options\");\n        return;\n    }\n\n    /* COUNT without ordering does not make much sense, force ASC\n     * ordering if COUNT was specified but no sorting was requested. */\n    if (count != 0 && sort == SORT_NONE) sort = SORT_ASC;\n\n    /* Get all neighbor geohash boxes for our radius search */\n    GeoHashRadius georadius =\n        geohashGetAreasByRadiusWGS84(xy[0], xy[1], radius_meters);\n\n    /* Search the zset for all matching points */\n    geoArray *ga = geoArrayCreate();\n    membersOfAllNeighbors(zobj, georadius, xy[0], xy[1], radius_meters, ga);\n\n    /* If no matching results, the user gets an empty reply. */\n    if (ga->used == 0 && storekey == NULL) {\n        addReply(c, shared.emptymultibulk);\n        geoArrayFree(ga);\n        return;\n    }\n\n    long result_length = ga->used;\n    long returned_items = (count == 0 || result_length < count) ?\n                          result_length : count;\n    long option_length = 0;\n\n    /* Process [optional] requested sorting */\n    if (sort == SORT_ASC) {\n        qsort(ga->array, result_length, sizeof(geoPoint), sort_gp_asc);\n    } else if (sort == SORT_DESC) {\n        qsort(ga->array, result_length, sizeof(geoPoint), sort_gp_desc);\n    }\n\n    if (storekey == NULL) {\n        /* No target key, return results to user. */\n\n        /* Our options are self-contained nested multibulk replies, so we\n         * only need to track how many of those nested replies we return. */\n        if (withdist)\n            option_length++;\n\n        if (withcoords)\n            option_length++;\n\n        if (withhash)\n            option_length++;\n\n        /* The multibulk len we send is exactly result_length. The result is\n         * either all strings of just zset members  *or* a nested multi-bulk\n         * reply containing the zset member string _and_ all the additional\n         * options the user enabled for this request. */\n        addReplyMultiBulkLen(c, returned_items);\n\n        /* Finally send results back to the caller */\n        int i;\n        for (i = 0; i < returned_items; i++) {\n            geoPoint *gp = ga->array+i;\n            gp->dist /= conversion; /* Fix according to unit. */\n\n            /* If we have options in option_length, return each sub-result\n             * as a nested multi-bulk.  Add 1 to account for result value\n             * itself. */\n            if (option_length)\n                addReplyMultiBulkLen(c, option_length + 1);\n\n            addReplyBulkSds(c,gp->member);\n            gp->member = NULL;\n\n            if (withdist)\n                addReplyDoubleDistance(c, gp->dist);\n\n            if (withhash)\n                addReplyLongLong(c, gp->score);\n\n            if (withcoords) {\n                addReplyMultiBulkLen(c, 2);\n                addReplyHumanLongDouble(c, gp->longitude);\n                addReplyHumanLongDouble(c, gp->latitude);\n            }\n        }\n    } else {\n        /* Target key, create a sorted set with the results. */\n        robj *zobj;\n        zset *zs;\n        int i;\n        size_t maxelelen = 0;\n\n        if (returned_items) {\n            zobj = createZsetObject();\n            zs = zobj->ptr;\n        }\n\n        for (i = 0; i < returned_items; i++) {\n            zskiplistNode *znode;\n            geoPoint *gp = ga->array+i;\n            gp->dist /= conversion; /* Fix according to unit. */\n            double score = storedist ? gp->dist : gp->score;\n            size_t elelen = sdslen(gp->member);\n            robj *ele = createObject(OBJ_STRING,gp->member);\n\n            if (maxelelen < elelen) maxelelen = elelen;\n            incrRefCount(ele); /* Set refcount to 2 since we reference the\n                                  object both in the skiplist and dict. */\n            znode = zslInsert(zs->zsl,score,ele);\n            serverAssert(dictAdd(zs->dict,ele,&znode->score) == DICT_OK);\n            gp->member = NULL;\n        }\n\n        if (returned_items) {\n            zsetConvertToZiplistIfNeeded(zobj,maxelelen);\n            setKey(c->db,storekey,zobj);\n            decrRefCount(zobj);\n            notifyKeyspaceEvent(NOTIFY_LIST,\"georadiusstore\",storekey,\n                                c->db->id);\n            server.dirty += returned_items;\n        } else if (dbDelete(c->db,storekey)) {\n            signalModifiedKey(c->db,storekey);\n            notifyKeyspaceEvent(NOTIFY_GENERIC,\"del\",storekey,c->db->id);\n            server.dirty++;\n        }\n        addReplyLongLong(c, returned_items);\n    }\n    geoArrayFree(ga);\n}\n\n/* GEORADIUS wrapper function. */\nvoid georadiusCommand(client *c) {\n    georadiusGeneric(c, RADIUS_COORDS);\n}\n\n/* GEORADIUSBYMEMBER wrapper function. */\nvoid georadiusByMemberCommand(client *c) {\n    georadiusGeneric(c, RADIUS_MEMBER);\n}\n\n/* GEOHASH key ele1 ele2 ... eleN\n *\n * Returns an array with an 11 characters geohash representation of the\n * position of the specified elements. */\nvoid geohashCommand(client *c) {\n    char *geoalphabet= \"0123456789bcdefghjkmnpqrstuvwxyz\";\n    int j;\n\n    /* Look up the requested zset */\n    robj *zobj = NULL;\n    if ((zobj = lookupKeyReadOrReply(c, c->argv[1], shared.emptymultibulk))\n        == NULL || checkType(c, zobj, OBJ_ZSET)) return;\n\n    /* Geohash elements one after the other, using a null bulk reply for\n     * missing elements. */\n    addReplyMultiBulkLen(c,c->argc-2);\n    for (j = 2; j < c->argc; j++) {\n        double score;\n        if (zsetScore(zobj, c->argv[j], &score) == C_ERR) {\n            addReply(c,shared.nullbulk);\n        } else {\n            /* The internal format we use for geocoding is a bit different\n             * than the standard, since we use as initial latitude range\n             * -85,85, while the normal geohashing algorithm uses -90,90.\n             * So we have to decode our position and re-encode using the\n             * standard ranges in order to output a valid geohash string. */\n\n            /* Decode... */\n            double xy[2];\n            if (!decodeGeohash(score,xy)) {\n                addReply(c,shared.nullbulk);\n                continue;\n            }\n\n            /* Re-encode */\n            GeoHashRange r[2];\n            GeoHashBits hash;\n            r[0].min = -180;\n            r[0].max = 180;\n            r[1].min = -90;\n            r[1].max = 90;\n            geohashEncode(&r[0],&r[1],xy[0],xy[1],26,&hash);\n\n            char buf[12];\n            int i;\n            for (i = 0; i < 11; i++) {\n                int idx = (hash.bits >> (52-((i+1)*5))) & 0x1f;\n                buf[i] = geoalphabet[idx];\n            }\n            buf[11] = '\\0';\n            addReplyBulkCBuffer(c,buf,11);\n        }\n    }\n}\n\n/* GEOPOS key ele1 ele2 ... eleN\n *\n * Returns an array of two-items arrays representing the x,y position of each\n * element specified in the arguments. For missing elements NULL is returned. */\nvoid geoposCommand(client *c) {\n    int j;\n\n    /* Look up the requested zset */\n    robj *zobj = NULL;\n    if ((zobj = lookupKeyReadOrReply(c, c->argv[1], shared.emptymultibulk))\n        == NULL || checkType(c, zobj, OBJ_ZSET)) return;\n\n    /* Report elements one after the other, using a null bulk reply for\n     * missing elements. */\n    addReplyMultiBulkLen(c,c->argc-2);\n    for (j = 2; j < c->argc; j++) {\n        double score;\n        if (zsetScore(zobj, c->argv[j], &score) == C_ERR) {\n            addReply(c,shared.nullmultibulk);\n        } else {\n            /* Decode... */\n            double xy[2];\n            if (!decodeGeohash(score,xy)) {\n                addReply(c,shared.nullmultibulk);\n                continue;\n            }\n            addReplyMultiBulkLen(c,2);\n            addReplyHumanLongDouble(c,xy[0]);\n            addReplyHumanLongDouble(c,xy[1]);\n        }\n    }\n}\n\n/* GEODIST key ele1 ele2 [unit]\n *\n * Return the distance, in meters by default, otherwise accordig to \"unit\",\n * between points ele1 and ele2. If one or more elements are missing NULL\n * is returned. */\nvoid geodistCommand(client *c) {\n    double to_meter = 1;\n\n    /* Check if there is the unit to extract, otherwise assume meters. */\n    if (c->argc == 5) {\n        to_meter = extractUnitOrReply(c,c->argv[4]);\n        if (to_meter < 0) return;\n    } else if (c->argc > 5) {\n        addReply(c,shared.syntaxerr);\n        return;\n    }\n\n    /* Look up the requested zset */\n    robj *zobj = NULL;\n    if ((zobj = lookupKeyReadOrReply(c, c->argv[1], shared.emptybulk))\n        == NULL || checkType(c, zobj, OBJ_ZSET)) return;\n\n    /* Get the scores. We need both otherwise NULL is returned. */\n    double score1, score2, xyxy[4];\n    if (zsetScore(zobj, c->argv[2], &score1) == C_ERR ||\n        zsetScore(zobj, c->argv[3], &score2) == C_ERR)\n    {\n        addReply(c,shared.nullbulk);\n        return;\n    }\n\n    /* Decode & compute the distance. */\n    if (!decodeGeohash(score1,xyxy) || !decodeGeohash(score2,xyxy+2))\n        addReply(c,shared.nullbulk);\n    else\n        addReplyDoubleDistance(c,\n            geohashGetDistance(xyxy[0],xyxy[1],xyxy[2],xyxy[3]) / to_meter);\n}\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/src/geo.h",
    "content": "#ifndef __GEO_H__\n#define __GEO_H__\n\n#include \"server.h\"\n\n/* Structures used inside geo.c in order to represent points and array of\n * points on the earth. */\ntypedef struct geoPoint {\n    double longitude;\n    double latitude;\n    double dist;\n    double score;\n    char *member;\n} geoPoint;\n\ntypedef struct geoArray {\n    struct geoPoint *array;\n    size_t buckets;\n    size_t used;\n} geoArray;\n\n#endif\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/src/help.h",
    "content": "/* Automatically generated by utils/generate-command-help.rb, do not edit. */\n\n#ifndef __REDIS_HELP_H\n#define __REDIS_HELP_H\n\nstatic char *commandGroups[] = {\n    \"generic\",\n    \"string\",\n    \"list\",\n    \"set\",\n    \"sorted_set\",\n    \"hash\",\n    \"pubsub\",\n    \"transactions\",\n    \"connection\",\n    \"server\",\n    \"scripting\",\n    \"hyperloglog\",\n    \"cluster\",\n    \"geo\"\n};\n\nstruct commandHelp {\n  char *name;\n  char *params;\n  char *summary;\n  int group;\n  char *since;\n} commandHelp[] = {\n    { \"APPEND\",\n    \"key value\",\n    \"Append a value to a key\",\n    1,\n    \"2.0.0\" },\n    { \"AUTH\",\n    \"password\",\n    \"Authenticate to the server\",\n    8,\n    \"1.0.0\" },\n    { \"BGREWRITEAOF\",\n    \"-\",\n    \"Asynchronously rewrite the append-only file\",\n    9,\n    \"1.0.0\" },\n    { \"BGSAVE\",\n    \"-\",\n    \"Asynchronously save the dataset to disk\",\n    9,\n    \"1.0.0\" },\n    { \"BITCOUNT\",\n    \"key [start end]\",\n    \"Count set bits in a string\",\n    1,\n    \"2.6.0\" },\n    { \"BITFIELD\",\n    \"key [GET type offset] [SET type offset value] [INCRBY type offset increment] [OVERFLOW WRAP|SAT|FAIL]\",\n    \"Perform arbitrary bitfield integer operations on strings\",\n    1,\n    \"3.2.0\" },\n    { \"BITOP\",\n    \"operation destkey key [key ...]\",\n    \"Perform bitwise operations between strings\",\n    1,\n    \"2.6.0\" },\n    { \"BITPOS\",\n    \"key bit [start] [end]\",\n    \"Find first bit set or clear in a string\",\n    1,\n    \"2.8.7\" },\n    { \"BLPOP\",\n    \"key [key ...] timeout\",\n    \"Remove and get the first element in a list, or block until one is available\",\n    2,\n    \"2.0.0\" },\n    { \"BRPOP\",\n    \"key [key ...] timeout\",\n    \"Remove and get the last element in a list, or block until one is available\",\n    2,\n    \"2.0.0\" },\n    { \"BRPOPLPUSH\",\n    \"source destination timeout\",\n    \"Pop a value from a list, push it to another list and return it; or block until one is available\",\n    2,\n    \"2.2.0\" },\n    { \"CLIENT GETNAME\",\n    \"-\",\n    \"Get the current connection name\",\n    9,\n    \"2.6.9\" },\n    { \"CLIENT KILL\",\n    \"[ip:port] [ID client-id] [TYPE normal|master|slave|pubsub] [ADDR ip:port] [SKIPME yes/no]\",\n    \"Kill the connection of a client\",\n    9,\n    \"2.4.0\" },\n    { \"CLIENT LIST\",\n    \"-\",\n    \"Get the list of client connections\",\n    9,\n    \"2.4.0\" },\n    { \"CLIENT PAUSE\",\n    \"timeout\",\n    \"Stop processing commands from clients for some time\",\n    9,\n    \"2.9.50\" },\n    { \"CLIENT REPLY\",\n    \"ON|OFF|SKIP\",\n    \"Instruct the server whether to reply to commands\",\n    9,\n    \"3.2\" },\n    { \"CLIENT SETNAME\",\n    \"connection-name\",\n    \"Set the current connection name\",\n    9,\n    \"2.6.9\" },\n    { \"CLUSTER ADDSLOTS\",\n    \"slot [slot ...]\",\n    \"Assign new hash slots to receiving node\",\n    12,\n    \"3.0.0\" },\n    { \"CLUSTER COUNT-FAILURE-REPORTS\",\n    \"node-id\",\n    \"Return the number of failure reports active for a given node\",\n    12,\n    \"3.0.0\" },\n    { \"CLUSTER COUNTKEYSINSLOT\",\n    \"slot\",\n    \"Return the number of local keys in the specified hash slot\",\n    12,\n    \"3.0.0\" },\n    { \"CLUSTER DELSLOTS\",\n    \"slot [slot ...]\",\n    \"Set hash slots as unbound in receiving node\",\n    12,\n    \"3.0.0\" },\n    { \"CLUSTER FAILOVER\",\n    \"[FORCE|TAKEOVER]\",\n    \"Forces a slave to perform a manual failover of its master.\",\n    12,\n    \"3.0.0\" },\n    { \"CLUSTER FORGET\",\n    \"node-id\",\n    \"Remove a node from the nodes table\",\n    12,\n    \"3.0.0\" },\n    { \"CLUSTER GETKEYSINSLOT\",\n    \"slot count\",\n    \"Return local key names in the specified hash slot\",\n    12,\n    \"3.0.0\" },\n    { \"CLUSTER INFO\",\n    \"-\",\n    \"Provides info about Redis Cluster node state\",\n    12,\n    \"3.0.0\" },\n    { \"CLUSTER KEYSLOT\",\n    \"key\",\n    \"Returns the hash slot of the specified key\",\n    12,\n    \"3.0.0\" },\n    { \"CLUSTER MEET\",\n    \"ip port\",\n    \"Force a node cluster to handshake with another node\",\n    12,\n    \"3.0.0\" },\n    { \"CLUSTER NODES\",\n    \"-\",\n    \"Get Cluster config for the node\",\n    12,\n    \"3.0.0\" },\n    { \"CLUSTER REPLICATE\",\n    \"node-id\",\n    \"Reconfigure a node as a slave of the specified master node\",\n    12,\n    \"3.0.0\" },\n    { \"CLUSTER RESET\",\n    \"[HARD|SOFT]\",\n    \"Reset a Redis Cluster node\",\n    12,\n    \"3.0.0\" },\n    { \"CLUSTER SAVECONFIG\",\n    \"-\",\n    \"Forces the node to save cluster state on disk\",\n    12,\n    \"3.0.0\" },\n    { \"CLUSTER SET-CONFIG-EPOCH\",\n    \"config-epoch\",\n    \"Set the configuration epoch in a new node\",\n    12,\n    \"3.0.0\" },\n    { \"CLUSTER SETSLOT\",\n    \"slot IMPORTING|MIGRATING|STABLE|NODE [node-id]\",\n    \"Bind a hash slot to a specific node\",\n    12,\n    \"3.0.0\" },\n    { \"CLUSTER SLAVES\",\n    \"node-id\",\n    \"List slave nodes of the specified master node\",\n    12,\n    \"3.0.0\" },\n    { \"CLUSTER SLOTS\",\n    \"-\",\n    \"Get array of Cluster slot to node mappings\",\n    12,\n    \"3.0.0\" },\n    { \"COMMAND\",\n    \"-\",\n    \"Get array of Redis command details\",\n    9,\n    \"2.8.13\" },\n    { \"COMMAND COUNT\",\n    \"-\",\n    \"Get total number of Redis commands\",\n    9,\n    \"2.8.13\" },\n    { \"COMMAND GETKEYS\",\n    \"-\",\n    \"Extract keys given a full Redis command\",\n    9,\n    \"2.8.13\" },\n    { \"COMMAND INFO\",\n    \"command-name [command-name ...]\",\n    \"Get array of specific Redis command details\",\n    9,\n    \"2.8.13\" },\n    { \"CONFIG GET\",\n    \"parameter\",\n    \"Get the value of a configuration parameter\",\n    9,\n    \"2.0.0\" },\n    { \"CONFIG RESETSTAT\",\n    \"-\",\n    \"Reset the stats returned by INFO\",\n    9,\n    \"2.0.0\" },\n    { \"CONFIG REWRITE\",\n    \"-\",\n    \"Rewrite the configuration file with the in memory configuration\",\n    9,\n    \"2.8.0\" },\n    { \"CONFIG SET\",\n    \"parameter value\",\n    \"Set a configuration parameter to the given value\",\n    9,\n    \"2.0.0\" },\n    { \"DBSIZE\",\n    \"-\",\n    \"Return the number of keys in the selected database\",\n    9,\n    \"1.0.0\" },\n    { \"DEBUG OBJECT\",\n    \"key\",\n    \"Get debugging information about a key\",\n    9,\n    \"1.0.0\" },\n    { \"DEBUG SEGFAULT\",\n    \"-\",\n    \"Make the server crash\",\n    9,\n    \"1.0.0\" },\n    { \"DECR\",\n    \"key\",\n    \"Decrement the integer value of a key by one\",\n    1,\n    \"1.0.0\" },\n    { \"DECRBY\",\n    \"key decrement\",\n    \"Decrement the integer value of a key by the given number\",\n    1,\n    \"1.0.0\" },\n    { \"DEL\",\n    \"key [key ...]\",\n    \"Delete a key\",\n    0,\n    \"1.0.0\" },\n    { \"DISCARD\",\n    \"-\",\n    \"Discard all commands issued after MULTI\",\n    7,\n    \"2.0.0\" },\n    { \"DUMP\",\n    \"key\",\n    \"Return a serialized version of the value stored at the specified key.\",\n    0,\n    \"2.6.0\" },\n    { \"ECHO\",\n    \"message\",\n    \"Echo the given string\",\n    8,\n    \"1.0.0\" },\n    { \"EVAL\",\n    \"script numkeys key [key ...] arg [arg ...]\",\n    \"Execute a Lua script server side\",\n    10,\n    \"2.6.0\" },\n    { \"EVALSHA\",\n    \"sha1 numkeys key [key ...] arg [arg ...]\",\n    \"Execute a Lua script server side\",\n    10,\n    \"2.6.0\" },\n    { \"EXEC\",\n    \"-\",\n    \"Execute all commands issued after MULTI\",\n    7,\n    \"1.2.0\" },\n    { \"EXISTS\",\n    \"key [key ...]\",\n    \"Determine if a key exists\",\n    0,\n    \"1.0.0\" },\n    { \"EXPIRE\",\n    \"key seconds\",\n    \"Set a key's time to live in seconds\",\n    0,\n    \"1.0.0\" },\n    { \"EXPIREAT\",\n    \"key timestamp\",\n    \"Set the expiration for a key as a UNIX timestamp\",\n    0,\n    \"1.2.0\" },\n    { \"FLUSHALL\",\n    \"-\",\n    \"Remove all keys from all databases\",\n    9,\n    \"1.0.0\" },\n    { \"FLUSHDB\",\n    \"-\",\n    \"Remove all keys from the current database\",\n    9,\n    \"1.0.0\" },\n    { \"GEOADD\",\n    \"key longitude latitude member [longitude latitude member ...]\",\n    \"Add one or more geospatial items in the geospatial index represented using a sorted set\",\n    13,\n    \"3.2.0\" },\n    { \"GEODIST\",\n    \"key member1 member2 [unit]\",\n    \"Returns the distance between two members of a geospatial index\",\n    13,\n    \"3.2.0\" },\n    { \"GEOHASH\",\n    \"key member [member ...]\",\n    \"Returns members of a geospatial index as standard geohash strings\",\n    13,\n    \"3.2.0\" },\n    { \"GEOPOS\",\n    \"key member [member ...]\",\n    \"Returns longitude and latitude of members of a geospatial index\",\n    13,\n    \"3.2.0\" },\n    { \"GEORADIUS\",\n    \"key longitude latitude radius m|km|ft|mi [WITHCOORD] [WITHDIST] [WITHHASH] [COUNT count] [ASC|DESC] [STORE key] [STOREDIST key]\",\n    \"Query a sorted set representing a geospatial index to fetch members matching a given maximum distance from a point\",\n    13,\n    \"3.2.0\" },\n    { \"GEORADIUSBYMEMBER\",\n    \"key member radius m|km|ft|mi [WITHCOORD] [WITHDIST] [WITHHASH] [COUNT count] [ASC|DESC] [STORE key] [STOREDIST key]\",\n    \"Query a sorted set representing a geospatial index to fetch members matching a given maximum distance from a member\",\n    13,\n    \"3.2.0\" },\n    { \"GET\",\n    \"key\",\n    \"Get the value of a key\",\n    1,\n    \"1.0.0\" },\n    { \"GETBIT\",\n    \"key offset\",\n    \"Returns the bit value at offset in the string value stored at key\",\n    1,\n    \"2.2.0\" },\n    { \"GETRANGE\",\n    \"key start end\",\n    \"Get a substring of the string stored at a key\",\n    1,\n    \"2.4.0\" },\n    { \"GETSET\",\n    \"key value\",\n    \"Set the string value of a key and return its old value\",\n    1,\n    \"1.0.0\" },\n    { \"HDEL\",\n    \"key field [field ...]\",\n    \"Delete one or more hash fields\",\n    5,\n    \"2.0.0\" },\n    { \"HEXISTS\",\n    \"key field\",\n    \"Determine if a hash field exists\",\n    5,\n    \"2.0.0\" },\n    { \"HGET\",\n    \"key field\",\n    \"Get the value of a hash field\",\n    5,\n    \"2.0.0\" },\n    { \"HGETALL\",\n    \"key\",\n    \"Get all the fields and values in a hash\",\n    5,\n    \"2.0.0\" },\n    { \"HINCRBY\",\n    \"key field increment\",\n    \"Increment the integer value of a hash field by the given number\",\n    5,\n    \"2.0.0\" },\n    { \"HINCRBYFLOAT\",\n    \"key field increment\",\n    \"Increment the float value of a hash field by the given amount\",\n    5,\n    \"2.6.0\" },\n    { \"HKEYS\",\n    \"key\",\n    \"Get all the fields in a hash\",\n    5,\n    \"2.0.0\" },\n    { \"HLEN\",\n    \"key\",\n    \"Get the number of fields in a hash\",\n    5,\n    \"2.0.0\" },\n    { \"HMGET\",\n    \"key field [field ...]\",\n    \"Get the values of all the given hash fields\",\n    5,\n    \"2.0.0\" },\n    { \"HMSET\",\n    \"key field value [field value ...]\",\n    \"Set multiple hash fields to multiple values\",\n    5,\n    \"2.0.0\" },\n    { \"HSCAN\",\n    \"key cursor [MATCH pattern] [COUNT count]\",\n    \"Incrementally iterate hash fields and associated values\",\n    5,\n    \"2.8.0\" },\n    { \"HSET\",\n    \"key field value\",\n    \"Set the string value of a hash field\",\n    5,\n    \"2.0.0\" },\n    { \"HSETNX\",\n    \"key field value\",\n    \"Set the value of a hash field, only if the field does not exist\",\n    5,\n    \"2.0.0\" },\n    { \"HSTRLEN\",\n    \"key field\",\n    \"Get the length of the value of a hash field\",\n    5,\n    \"3.2.0\" },\n    { \"HVALS\",\n    \"key\",\n    \"Get all the values in a hash\",\n    5,\n    \"2.0.0\" },\n    { \"INCR\",\n    \"key\",\n    \"Increment the integer value of a key by one\",\n    1,\n    \"1.0.0\" },\n    { \"INCRBY\",\n    \"key increment\",\n    \"Increment the integer value of a key by the given amount\",\n    1,\n    \"1.0.0\" },\n    { \"INCRBYFLOAT\",\n    \"key increment\",\n    \"Increment the float value of a key by the given amount\",\n    1,\n    \"2.6.0\" },\n    { \"INFO\",\n    \"[section]\",\n    \"Get information and statistics about the server\",\n    9,\n    \"1.0.0\" },\n    { \"KEYS\",\n    \"pattern\",\n    \"Find all keys matching the given pattern\",\n    0,\n    \"1.0.0\" },\n    { \"LASTSAVE\",\n    \"-\",\n    \"Get the UNIX time stamp of the last successful save to disk\",\n    9,\n    \"1.0.0\" },\n    { \"LINDEX\",\n    \"key index\",\n    \"Get an element from a list by its index\",\n    2,\n    \"1.0.0\" },\n    { \"LINSERT\",\n    \"key BEFORE|AFTER pivot value\",\n    \"Insert an element before or after another element in a list\",\n    2,\n    \"2.2.0\" },\n    { \"LLEN\",\n    \"key\",\n    \"Get the length of a list\",\n    2,\n    \"1.0.0\" },\n    { \"LPOP\",\n    \"key\",\n    \"Remove and get the first element in a list\",\n    2,\n    \"1.0.0\" },\n    { \"LPUSH\",\n    \"key value [value ...]\",\n    \"Prepend one or multiple values to a list\",\n    2,\n    \"1.0.0\" },\n    { \"LPUSHX\",\n    \"key value\",\n    \"Prepend a value to a list, only if the list exists\",\n    2,\n    \"2.2.0\" },\n    { \"LRANGE\",\n    \"key start stop\",\n    \"Get a range of elements from a list\",\n    2,\n    \"1.0.0\" },\n    { \"LREM\",\n    \"key count value\",\n    \"Remove elements from a list\",\n    2,\n    \"1.0.0\" },\n    { \"LSET\",\n    \"key index value\",\n    \"Set the value of an element in a list by its index\",\n    2,\n    \"1.0.0\" },\n    { \"LTRIM\",\n    \"key start stop\",\n    \"Trim a list to the specified range\",\n    2,\n    \"1.0.0\" },\n    { \"MGET\",\n    \"key [key ...]\",\n    \"Get the values of all the given keys\",\n    1,\n    \"1.0.0\" },\n    { \"MIGRATE\",\n    \"host port key|\"\" destination-db timeout [COPY] [REPLACE] [KEYS key]\",\n    \"Atomically transfer a key from a Redis instance to another one.\",\n    0,\n    \"2.6.0\" },\n    { \"MONITOR\",\n    \"-\",\n    \"Listen for all requests received by the server in real time\",\n    9,\n    \"1.0.0\" },\n    { \"MOVE\",\n    \"key db\",\n    \"Move a key to another database\",\n    0,\n    \"1.0.0\" },\n    { \"MSET\",\n    \"key value [key value ...]\",\n    \"Set multiple keys to multiple values\",\n    1,\n    \"1.0.1\" },\n    { \"MSETNX\",\n    \"key value [key value ...]\",\n    \"Set multiple keys to multiple values, only if none of the keys exist\",\n    1,\n    \"1.0.1\" },\n    { \"MULTI\",\n    \"-\",\n    \"Mark the start of a transaction block\",\n    7,\n    \"1.2.0\" },\n    { \"OBJECT\",\n    \"subcommand [arguments [arguments ...]]\",\n    \"Inspect the internals of Redis objects\",\n    0,\n    \"2.2.3\" },\n    { \"PERSIST\",\n    \"key\",\n    \"Remove the expiration from a key\",\n    0,\n    \"2.2.0\" },\n    { \"PEXPIRE\",\n    \"key milliseconds\",\n    \"Set a key's time to live in milliseconds\",\n    0,\n    \"2.6.0\" },\n    { \"PEXPIREAT\",\n    \"key milliseconds-timestamp\",\n    \"Set the expiration for a key as a UNIX timestamp specified in milliseconds\",\n    0,\n    \"2.6.0\" },\n    { \"PFADD\",\n    \"key element [element ...]\",\n    \"Adds the specified elements to the specified HyperLogLog.\",\n    11,\n    \"2.8.9\" },\n    { \"PFCOUNT\",\n    \"key [key ...]\",\n    \"Return the approximated cardinality of the set(s) observed by the HyperLogLog at key(s).\",\n    11,\n    \"2.8.9\" },\n    { \"PFMERGE\",\n    \"destkey sourcekey [sourcekey ...]\",\n    \"Merge N different HyperLogLogs into a single one.\",\n    11,\n    \"2.8.9\" },\n    { \"PING\",\n    \"[message]\",\n    \"Ping the server\",\n    8,\n    \"1.0.0\" },\n    { \"PSETEX\",\n    \"key milliseconds value\",\n    \"Set the value and expiration in milliseconds of a key\",\n    1,\n    \"2.6.0\" },\n    { \"PSUBSCRIBE\",\n    \"pattern [pattern ...]\",\n    \"Listen for messages published to channels matching the given patterns\",\n    6,\n    \"2.0.0\" },\n    { \"PTTL\",\n    \"key\",\n    \"Get the time to live for a key in milliseconds\",\n    0,\n    \"2.6.0\" },\n    { \"PUBLISH\",\n    \"channel message\",\n    \"Post a message to a channel\",\n    6,\n    \"2.0.0\" },\n    { \"PUBSUB\",\n    \"subcommand [argument [argument ...]]\",\n    \"Inspect the state of the Pub/Sub subsystem\",\n    6,\n    \"2.8.0\" },\n    { \"PUNSUBSCRIBE\",\n    \"[pattern [pattern ...]]\",\n    \"Stop listening for messages posted to channels matching the given patterns\",\n    6,\n    \"2.0.0\" },\n    { \"QUIT\",\n    \"-\",\n    \"Close the connection\",\n    8,\n    \"1.0.0\" },\n    { \"RANDOMKEY\",\n    \"-\",\n    \"Return a random key from the keyspace\",\n    0,\n    \"1.0.0\" },\n    { \"READONLY\",\n    \"-\",\n    \"Enables read queries for a connection to a cluster slave node\",\n    12,\n    \"3.0.0\" },\n    { \"READWRITE\",\n    \"-\",\n    \"Disables read queries for a connection to a cluster slave node\",\n    12,\n    \"3.0.0\" },\n    { \"RENAME\",\n    \"key newkey\",\n    \"Rename a key\",\n    0,\n    \"1.0.0\" },\n    { \"RENAMENX\",\n    \"key newkey\",\n    \"Rename a key, only if the new key does not exist\",\n    0,\n    \"1.0.0\" },\n    { \"RESTORE\",\n    \"key ttl serialized-value [REPLACE]\",\n    \"Create a key using the provided serialized value, previously obtained using DUMP.\",\n    0,\n    \"2.6.0\" },\n    { \"ROLE\",\n    \"-\",\n    \"Return the role of the instance in the context of replication\",\n    9,\n    \"2.8.12\" },\n    { \"RPOP\",\n    \"key\",\n    \"Remove and get the last element in a list\",\n    2,\n    \"1.0.0\" },\n    { \"RPOPLPUSH\",\n    \"source destination\",\n    \"Remove the last element in a list, prepend it to another list and return it\",\n    2,\n    \"1.2.0\" },\n    { \"RPUSH\",\n    \"key value [value ...]\",\n    \"Append one or multiple values to a list\",\n    2,\n    \"1.0.0\" },\n    { \"RPUSHX\",\n    \"key value\",\n    \"Append a value to a list, only if the list exists\",\n    2,\n    \"2.2.0\" },\n    { \"SADD\",\n    \"key member [member ...]\",\n    \"Add one or more members to a set\",\n    3,\n    \"1.0.0\" },\n    { \"SAVE\",\n    \"-\",\n    \"Synchronously save the dataset to disk\",\n    9,\n    \"1.0.0\" },\n    { \"SCAN\",\n    \"cursor [MATCH pattern] [COUNT count]\",\n    \"Incrementally iterate the keys space\",\n    0,\n    \"2.8.0\" },\n    { \"SCARD\",\n    \"key\",\n    \"Get the number of members in a set\",\n    3,\n    \"1.0.0\" },\n    { \"SCRIPT DEBUG\",\n    \"YES|SYNC|NO\",\n    \"Set the debug mode for executed scripts.\",\n    10,\n    \"3.2.0\" },\n    { \"SCRIPT EXISTS\",\n    \"script [script ...]\",\n    \"Check existence of scripts in the script cache.\",\n    10,\n    \"2.6.0\" },\n    { \"SCRIPT FLUSH\",\n    \"-\",\n    \"Remove all the scripts from the script cache.\",\n    10,\n    \"2.6.0\" },\n    { \"SCRIPT KILL\",\n    \"-\",\n    \"Kill the script currently in execution.\",\n    10,\n    \"2.6.0\" },\n    { \"SCRIPT LOAD\",\n    \"script\",\n    \"Load the specified Lua script into the script cache.\",\n    10,\n    \"2.6.0\" },\n    { \"SDIFF\",\n    \"key [key ...]\",\n    \"Subtract multiple sets\",\n    3,\n    \"1.0.0\" },\n    { \"SDIFFSTORE\",\n    \"destination key [key ...]\",\n    \"Subtract multiple sets and store the resulting set in a key\",\n    3,\n    \"1.0.0\" },\n    { \"SELECT\",\n    \"index\",\n    \"Change the selected database for the current connection\",\n    8,\n    \"1.0.0\" },\n    { \"SET\",\n    \"key value [EX seconds] [PX milliseconds] [NX|XX]\",\n    \"Set the string value of a key\",\n    1,\n    \"1.0.0\" },\n    { \"SETBIT\",\n    \"key offset value\",\n    \"Sets or clears the bit at offset in the string value stored at key\",\n    1,\n    \"2.2.0\" },\n    { \"SETEX\",\n    \"key seconds value\",\n    \"Set the value and expiration of a key\",\n    1,\n    \"2.0.0\" },\n    { \"SETNX\",\n    \"key value\",\n    \"Set the value of a key, only if the key does not exist\",\n    1,\n    \"1.0.0\" },\n    { \"SETRANGE\",\n    \"key offset value\",\n    \"Overwrite part of a string at key starting at the specified offset\",\n    1,\n    \"2.2.0\" },\n    { \"SHUTDOWN\",\n    \"[NOSAVE|SAVE]\",\n    \"Synchronously save the dataset to disk and then shut down the server\",\n    9,\n    \"1.0.0\" },\n    { \"SINTER\",\n    \"key [key ...]\",\n    \"Intersect multiple sets\",\n    3,\n    \"1.0.0\" },\n    { \"SINTERSTORE\",\n    \"destination key [key ...]\",\n    \"Intersect multiple sets and store the resulting set in a key\",\n    3,\n    \"1.0.0\" },\n    { \"SISMEMBER\",\n    \"key member\",\n    \"Determine if a given value is a member of a set\",\n    3,\n    \"1.0.0\" },\n    { \"SLAVEOF\",\n    \"host port\",\n    \"Make the server a slave of another instance, or promote it as master\",\n    9,\n    \"1.0.0\" },\n    { \"SLOWLOG\",\n    \"subcommand [argument]\",\n    \"Manages the Redis slow queries log\",\n    9,\n    \"2.2.12\" },\n    { \"SMEMBERS\",\n    \"key\",\n    \"Get all the members in a set\",\n    3,\n    \"1.0.0\" },\n    { \"SMOVE\",\n    \"source destination member\",\n    \"Move a member from one set to another\",\n    3,\n    \"1.0.0\" },\n    { \"SORT\",\n    \"key [BY pattern] [LIMIT offset count] [GET pattern [GET pattern ...]] [ASC|DESC] [ALPHA] [STORE destination]\",\n    \"Sort the elements in a list, set or sorted set\",\n    0,\n    \"1.0.0\" },\n    { \"SPOP\",\n    \"key [count]\",\n    \"Remove and return one or multiple random members from a set\",\n    3,\n    \"1.0.0\" },\n    { \"SRANDMEMBER\",\n    \"key [count]\",\n    \"Get one or multiple random members from a set\",\n    3,\n    \"1.0.0\" },\n    { \"SREM\",\n    \"key member [member ...]\",\n    \"Remove one or more members from a set\",\n    3,\n    \"1.0.0\" },\n    { \"SSCAN\",\n    \"key cursor [MATCH pattern] [COUNT count]\",\n    \"Incrementally iterate Set elements\",\n    3,\n    \"2.8.0\" },\n    { \"STRLEN\",\n    \"key\",\n    \"Get the length of the value stored in a key\",\n    1,\n    \"2.2.0\" },\n    { \"SUBSCRIBE\",\n    \"channel [channel ...]\",\n    \"Listen for messages published to the given channels\",\n    6,\n    \"2.0.0\" },\n    { \"SUNION\",\n    \"key [key ...]\",\n    \"Add multiple sets\",\n    3,\n    \"1.0.0\" },\n    { \"SUNIONSTORE\",\n    \"destination key [key ...]\",\n    \"Add multiple sets and store the resulting set in a key\",\n    3,\n    \"1.0.0\" },\n    { \"SYNC\",\n    \"-\",\n    \"Internal command used for replication\",\n    9,\n    \"1.0.0\" },\n    { \"TIME\",\n    \"-\",\n    \"Return the current server time\",\n    9,\n    \"2.6.0\" },\n    { \"TTL\",\n    \"key\",\n    \"Get the time to live for a key\",\n    0,\n    \"1.0.0\" },\n    { \"TYPE\",\n    \"key\",\n    \"Determine the type stored at key\",\n    0,\n    \"1.0.0\" },\n    { \"UNSUBSCRIBE\",\n    \"[channel [channel ...]]\",\n    \"Stop listening for messages posted to the given channels\",\n    6,\n    \"2.0.0\" },\n    { \"UNWATCH\",\n    \"-\",\n    \"Forget about all watched keys\",\n    7,\n    \"2.2.0\" },\n    { \"WAIT\",\n    \"numslaves timeout\",\n    \"Wait for the synchronous replication of all the write commands sent in the context of the current connection\",\n    0,\n    \"3.0.0\" },\n    { \"WATCH\",\n    \"key [key ...]\",\n    \"Watch the given keys to determine execution of the MULTI/EXEC block\",\n    7,\n    \"2.2.0\" },\n    { \"ZADD\",\n    \"key [NX|XX] [CH] [INCR] score member [score member ...]\",\n    \"Add one or more members to a sorted set, or update its score if it already exists\",\n    4,\n    \"1.2.0\" },\n    { \"ZCARD\",\n    \"key\",\n    \"Get the number of members in a sorted set\",\n    4,\n    \"1.2.0\" },\n    { \"ZCOUNT\",\n    \"key min max\",\n    \"Count the members in a sorted set with scores within the given values\",\n    4,\n    \"2.0.0\" },\n    { \"ZINCRBY\",\n    \"key increment member\",\n    \"Increment the score of a member in a sorted set\",\n    4,\n    \"1.2.0\" },\n    { \"ZINTERSTORE\",\n    \"destination numkeys key [key ...] [WEIGHTS weight] [AGGREGATE SUM|MIN|MAX]\",\n    \"Intersect multiple sorted sets and store the resulting sorted set in a new key\",\n    4,\n    \"2.0.0\" },\n    { \"ZLEXCOUNT\",\n    \"key min max\",\n    \"Count the number of members in a sorted set between a given lexicographical range\",\n    4,\n    \"2.8.9\" },\n    { \"ZRANGE\",\n    \"key start stop [WITHSCORES]\",\n    \"Return a range of members in a sorted set, by index\",\n    4,\n    \"1.2.0\" },\n    { \"ZRANGEBYLEX\",\n    \"key min max [LIMIT offset count]\",\n    \"Return a range of members in a sorted set, by lexicographical range\",\n    4,\n    \"2.8.9\" },\n    { \"ZRANGEBYSCORE\",\n    \"key min max [WITHSCORES] [LIMIT offset count]\",\n    \"Return a range of members in a sorted set, by score\",\n    4,\n    \"1.0.5\" },\n    { \"ZRANK\",\n    \"key member\",\n    \"Determine the index of a member in a sorted set\",\n    4,\n    \"2.0.0\" },\n    { \"ZREM\",\n    \"key member [member ...]\",\n    \"Remove one or more members from a sorted set\",\n    4,\n    \"1.2.0\" },\n    { \"ZREMRANGEBYLEX\",\n    \"key min max\",\n    \"Remove all members in a sorted set between the given lexicographical range\",\n    4,\n    \"2.8.9\" },\n    { \"ZREMRANGEBYRANK\",\n    \"key start stop\",\n    \"Remove all members in a sorted set within the given indexes\",\n    4,\n    \"2.0.0\" },\n    { \"ZREMRANGEBYSCORE\",\n    \"key min max\",\n    \"Remove all members in a sorted set within the given scores\",\n    4,\n    \"1.2.0\" },\n    { \"ZREVRANGE\",\n    \"key start stop [WITHSCORES]\",\n    \"Return a range of members in a sorted set, by index, with scores ordered from high to low\",\n    4,\n    \"1.2.0\" },\n    { \"ZREVRANGEBYLEX\",\n    \"key max min [LIMIT offset count]\",\n    \"Return a range of members in a sorted set, by lexicographical range, ordered from higher to lower strings.\",\n    4,\n    \"2.8.9\" },\n    { \"ZREVRANGEBYSCORE\",\n    \"key max min [WITHSCORES] [LIMIT offset count]\",\n    \"Return a range of members in a sorted set, by score, with scores ordered from high to low\",\n    4,\n    \"2.2.0\" },\n    { \"ZREVRANK\",\n    \"key member\",\n    \"Determine the index of a member in a sorted set, with scores ordered from high to low\",\n    4,\n    \"2.0.0\" },\n    { \"ZSCAN\",\n    \"key cursor [MATCH pattern] [COUNT count]\",\n    \"Incrementally iterate sorted sets elements and associated scores\",\n    4,\n    \"2.8.0\" },\n    { \"ZSCORE\",\n    \"key member\",\n    \"Get the score associated with the given member in a sorted set\",\n    4,\n    \"1.2.0\" },\n    { \"ZUNIONSTORE\",\n    \"destination numkeys key [key ...] [WEIGHTS weight] [AGGREGATE SUM|MIN|MAX]\",\n    \"Add multiple sorted sets and store the resulting sorted set in a new key\",\n    4,\n    \"2.0.0\" }\n};\n\n#endif\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/src/hyperloglog.c",
    "content": "/* hyperloglog.c - Redis HyperLogLog probabilistic cardinality approximation.\n * This file implements the algorithm and the exported Redis commands.\n *\n * Copyright (c) 2014, Salvatore Sanfilippo <antirez at gmail dot com>\n * All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions are met:\n *\n *   * Redistributions of source code must retain the above copyright notice,\n *     this list of conditions and the following disclaimer.\n *   * Redistributions in binary form must reproduce the above copyright\n *     notice, this list of conditions and the following disclaimer in the\n *     documentation and/or other materials provided with the distribution.\n *   * Neither the name of Redis nor the names of its contributors may be used\n *     to endorse or promote products derived from this software without\n *     specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\"\n * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\n * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE\n * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR\n * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF\n * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS\n * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN\n * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)\n * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE\n * POSSIBILITY OF SUCH DAMAGE.\n */\n\n#include \"server.h\"\n\n#include <stdint.h>\n#include <math.h>\n\n/* The Redis HyperLogLog implementation is based on the following ideas:\n *\n * * The use of a 64 bit hash function as proposed in [1], in order to don't\n *   limited to cardinalities up to 10^9, at the cost of just 1 additional\n *   bit per register.\n * * The use of 16384 6-bit registers for a great level of accuracy, using\n *   a total of 12k per key.\n * * The use of the Redis string data type. No new type is introduced.\n * * No attempt is made to compress the data structure as in [1]. Also the\n *   algorithm used is the original HyperLogLog Algorithm as in [2], with\n *   the only difference that a 64 bit hash function is used, so no correction\n *   is performed for values near 2^32 as in [1].\n *\n * [1] Heule, Nunkesser, Hall: HyperLogLog in Practice: Algorithmic\n *     Engineering of a State of The Art Cardinality Estimation Algorithm.\n *\n * [2] P. Flajolet, Éric Fusy, O. Gandouet, and F. Meunier. Hyperloglog: The\n *     analysis of a near-optimal cardinality estimation algorithm.\n *\n * Redis uses two representations:\n *\n * 1) A \"dense\" representation where every entry is represented by\n *    a 6-bit integer.\n * 2) A \"sparse\" representation using run length compression suitable\n *    for representing HyperLogLogs with many registers set to 0 in\n *    a memory efficient way.\n *\n *\n * HLL header\n * ===\n *\n * Both the dense and sparse representation have a 16 byte header as follows:\n *\n * +------+---+-----+----------+\n * | HYLL | E | N/U | Cardin.  |\n * +------+---+-----+----------+\n *\n * The first 4 bytes are a magic string set to the bytes \"HYLL\".\n * \"E\" is one byte encoding, currently set to HLL_DENSE or\n * HLL_SPARSE. N/U are three not used bytes.\n *\n * The \"Cardin.\" field is a 64 bit integer stored in little endian format\n * with the latest cardinality computed that can be reused if the data\n * structure was not modified since the last computation (this is useful\n * because there are high probabilities that HLLADD operations don't\n * modify the actual data structure and hence the approximated cardinality).\n *\n * When the most significant bit in the most significant byte of the cached\n * cardinality is set, it means that the data structure was modified and\n * we can't reuse the cached value that must be recomputed.\n *\n * Dense representation\n * ===\n *\n * The dense representation used by Redis is the following:\n *\n * +--------+--------+--------+------//      //--+\n * |11000000|22221111|33333322|55444444 ....     |\n * +--------+--------+--------+------//      //--+\n *\n * The 6 bits counters are encoded one after the other starting from the\n * LSB to the MSB, and using the next bytes as needed.\n *\n * Sparse representation\n * ===\n *\n * The sparse representation encodes registers using a run length\n * encoding composed of three opcodes, two using one byte, and one using\n * of two bytes. The opcodes are called ZERO, XZERO and VAL.\n *\n * ZERO opcode is represented as 00xxxxxx. The 6-bit integer represented\n * by the six bits 'xxxxxx', plus 1, means that there are N registers set\n * to 0. This opcode can represent from 1 to 64 contiguous registers set\n * to the value of 0.\n *\n * XZERO opcode is represented by two bytes 01xxxxxx yyyyyyyy. The 14-bit\n * integer represented by the bits 'xxxxxx' as most significant bits and\n * 'yyyyyyyy' as least significant bits, plus 1, means that there are N\n * registers set to 0. This opcode can represent from 0 to 16384 contiguous\n * registers set to the value of 0.\n *\n * VAL opcode is represented as 1vvvvvxx. It contains a 5-bit integer\n * representing the value of a register, and a 2-bit integer representing\n * the number of contiguous registers set to that value 'vvvvv'.\n * To obtain the value and run length, the integers vvvvv and xx must be\n * incremented by one. This opcode can represent values from 1 to 32,\n * repeated from 1 to 4 times.\n *\n * The sparse representation can't represent registers with a value greater\n * than 32, however it is very unlikely that we find such a register in an\n * HLL with a cardinality where the sparse representation is still more\n * memory efficient than the dense representation. When this happens the\n * HLL is converted to the dense representation.\n *\n * The sparse representation is purely positional. For example a sparse\n * representation of an empty HLL is just: XZERO:16384.\n *\n * An HLL having only 3 non-zero registers at position 1000, 1020, 1021\n * respectively set to 2, 3, 3, is represented by the following three\n * opcodes:\n *\n * XZERO:1000 (Registers 0-999 are set to 0)\n * VAL:2,1    (1 register set to value 2, that is register 1000)\n * ZERO:19    (Registers 1001-1019 set to 0)\n * VAL:3,2    (2 registers set to value 3, that is registers 1020,1021)\n * XZERO:15362 (Registers 1022-16383 set to 0)\n *\n * In the example the sparse representation used just 7 bytes instead\n * of 12k in order to represent the HLL registers. In general for low\n * cardinality there is a big win in terms of space efficiency, traded\n * with CPU time since the sparse representation is slower to access:\n *\n * The following table shows average cardinality vs bytes used, 100\n * samples per cardinality (when the set was not representable because\n * of registers with too big value, the dense representation size was used\n * as a sample).\n *\n * 100 267\n * 200 485\n * 300 678\n * 400 859\n * 500 1033\n * 600 1205\n * 700 1375\n * 800 1544\n * 900 1713\n * 1000 1882\n * 2000 3480\n * 3000 4879\n * 4000 6089\n * 5000 7138\n * 6000 8042\n * 7000 8823\n * 8000 9500\n * 9000 10088\n * 10000 10591\n *\n * The dense representation uses 12288 bytes, so there is a big win up to\n * a cardinality of ~2000-3000. For bigger cardinalities the constant times\n * involved in updating the sparse representation is not justified by the\n * memory savings. The exact maximum length of the sparse representation\n * when this implementation switches to the dense representation is\n * configured via the define server.hll_sparse_max_bytes.\n */\n\nstruct hllhdr {\n    char magic[4];      /* \"HYLL\" */\n    uint8_t encoding;   /* HLL_DENSE or HLL_SPARSE. */\n    uint8_t notused[3]; /* Reserved for future use, must be zero. */\n    uint8_t card[8];    /* Cached cardinality, little endian. */\n    uint8_t registers[]; /* Data bytes. */\n};\n\n/* The cached cardinality MSB is used to signal validity of the cached value. */\n#define HLL_INVALIDATE_CACHE(hdr) (hdr)->card[7] |= (1<<7)\n#define HLL_VALID_CACHE(hdr) (((hdr)->card[7] & (1<<7)) == 0)\n\n#define HLL_P 14 /* The greater is P, the smaller the error. */\n#define HLL_REGISTERS (1<<HLL_P) /* With P=14, 16384 registers. */\n#define HLL_P_MASK (HLL_REGISTERS-1) /* Mask to index register. */\n#define HLL_BITS 6 /* Enough to count up to 63 leading zeroes. */\n#define HLL_REGISTER_MAX ((1<<HLL_BITS)-1)\n#define HLL_HDR_SIZE sizeof(struct hllhdr)\n#define HLL_DENSE_SIZE (HLL_HDR_SIZE+((HLL_REGISTERS*HLL_BITS+7)/8))\n#define HLL_DENSE 0 /* Dense encoding. */\n#define HLL_SPARSE 1 /* Sparse encoding. */\n#define HLL_RAW 255 /* Only used internally, never exposed. */\n#define HLL_MAX_ENCODING 1\n\nstatic char *invalid_hll_err = \"-INVALIDOBJ Corrupted HLL object detected\\r\\n\";\n\n/* =========================== Low level bit macros ========================= */\n\n/* Macros to access the dense representation.\n *\n * We need to get and set 6 bit counters in an array of 8 bit bytes.\n * We use macros to make sure the code is inlined since speed is critical\n * especially in order to compute the approximated cardinality in\n * HLLCOUNT where we need to access all the registers at once.\n * For the same reason we also want to avoid conditionals in this code path.\n *\n * +--------+--------+--------+------//\n * |11000000|22221111|33333322|55444444\n * +--------+--------+--------+------//\n *\n * Note: in the above representation the most significant bit (MSB)\n * of every byte is on the left. We start using bits from the LSB to MSB,\n * and so forth passing to the next byte.\n *\n * Example, we want to access to counter at pos = 1 (\"111111\" in the\n * illustration above).\n *\n * The index of the first byte b0 containing our data is:\n *\n *  b0 = 6 * pos / 8 = 0\n *\n *   +--------+\n *   |11000000|  <- Our byte at b0\n *   +--------+\n *\n * The position of the first bit (counting from the LSB = 0) in the byte\n * is given by:\n *\n *  fb = 6 * pos % 8 -> 6\n *\n * Right shift b0 of 'fb' bits.\n *\n *   +--------+\n *   |11000000|  <- Initial value of b0\n *   |00000011|  <- After right shift of 6 pos.\n *   +--------+\n *\n * Left shift b1 of bits 8-fb bits (2 bits)\n *\n *   +--------+\n *   |22221111|  <- Initial value of b1\n *   |22111100|  <- After left shift of 2 bits.\n *   +--------+\n *\n * OR the two bits, and finally AND with 111111 (63 in decimal) to\n * clean the higher order bits we are not interested in:\n *\n *   +--------+\n *   |00000011|  <- b0 right shifted\n *   |22111100|  <- b1 left shifted\n *   |22111111|  <- b0 OR b1\n *   |  111111|  <- (b0 OR b1) AND 63, our value.\n *   +--------+\n *\n * We can try with a different example, like pos = 0. In this case\n * the 6-bit counter is actually contained in a single byte.\n *\n *  b0 = 6 * pos / 8 = 0\n *\n *   +--------+\n *   |11000000|  <- Our byte at b0\n *   +--------+\n *\n *  fb = 6 * pos % 8 = 0\n *\n *  So we right shift of 0 bits (no shift in practice) and\n *  left shift the next byte of 8 bits, even if we don't use it,\n *  but this has the effect of clearing the bits so the result\n *  will not be affacted after the OR.\n *\n * -------------------------------------------------------------------------\n *\n * Setting the register is a bit more complex, let's assume that 'val'\n * is the value we want to set, already in the right range.\n *\n * We need two steps, in one we need to clear the bits, and in the other\n * we need to bitwise-OR the new bits.\n *\n * Let's try with 'pos' = 1, so our first byte at 'b' is 0,\n *\n * \"fb\" is 6 in this case.\n *\n *   +--------+\n *   |11000000|  <- Our byte at b0\n *   +--------+\n *\n * To create a AND-mask to clear the bits about this position, we just\n * initialize the mask with the value 63, left shift it of \"fs\" bits,\n * and finally invert the result.\n *\n *   +--------+\n *   |00111111|  <- \"mask\" starts at 63\n *   |11000000|  <- \"mask\" after left shift of \"ls\" bits.\n *   |00111111|  <- \"mask\" after invert.\n *   +--------+\n *\n * Now we can bitwise-AND the byte at \"b\" with the mask, and bitwise-OR\n * it with \"val\" left-shifted of \"ls\" bits to set the new bits.\n *\n * Now let's focus on the next byte b1:\n *\n *   +--------+\n *   |22221111|  <- Initial value of b1\n *   +--------+\n *\n * To build the AND mask we start again with the 63 value, right shift\n * it by 8-fb bits, and invert it.\n *\n *   +--------+\n *   |00111111|  <- \"mask\" set at 2&6-1\n *   |00001111|  <- \"mask\" after the right shift by 8-fb = 2 bits\n *   |11110000|  <- \"mask\" after bitwise not.\n *   +--------+\n *\n * Now we can mask it with b+1 to clear the old bits, and bitwise-OR\n * with \"val\" left-shifted by \"rs\" bits to set the new value.\n */\n\n/* Note: if we access the last counter, we will also access the b+1 byte\n * that is out of the array, but sds strings always have an implicit null\n * term, so the byte exists, and we can skip the conditional (or the need\n * to allocate 1 byte more explicitly). */\n\n/* Store the value of the register at position 'regnum' into variable 'target'.\n * 'p' is an array of unsigned bytes. */\n#define HLL_DENSE_GET_REGISTER(target,p,regnum) do { \\\n    uint8_t *_p = (uint8_t*) p; \\\n    unsigned long _byte = regnum*HLL_BITS/8; \\\n    unsigned long _fb = regnum*HLL_BITS&7; \\\n    unsigned long _fb8 = 8 - _fb; \\\n    unsigned long b0 = _p[_byte]; \\\n    unsigned long b1 = _p[_byte+1]; \\\n    target = ((b0 >> _fb) | (b1 << _fb8)) & HLL_REGISTER_MAX; \\\n} while(0)\n\n/* Set the value of the register at position 'regnum' to 'val'.\n * 'p' is an array of unsigned bytes. */\n#define HLL_DENSE_SET_REGISTER(p,regnum,val) do { \\\n    uint8_t *_p = (uint8_t*) p; \\\n    unsigned long _byte = regnum*HLL_BITS/8; \\\n    unsigned long _fb = regnum*HLL_BITS&7; \\\n    unsigned long _fb8 = 8 - _fb; \\\n    unsigned long _v = val; \\\n    _p[_byte] &= ~(HLL_REGISTER_MAX << _fb); \\\n    _p[_byte] |= _v << _fb; \\\n    _p[_byte+1] &= ~(HLL_REGISTER_MAX >> _fb8); \\\n    _p[_byte+1] |= _v >> _fb8; \\\n} while(0)\n\n/* Macros to access the sparse representation.\n * The macros parameter is expected to be an uint8_t pointer. */\n#define HLL_SPARSE_XZERO_BIT 0x40 /* 01xxxxxx */\n#define HLL_SPARSE_VAL_BIT 0x80 /* 1vvvvvxx */\n#define HLL_SPARSE_IS_ZERO(p) (((*(p)) & 0xc0) == 0) /* 00xxxxxx */\n#define HLL_SPARSE_IS_XZERO(p) (((*(p)) & 0xc0) == HLL_SPARSE_XZERO_BIT)\n#define HLL_SPARSE_IS_VAL(p) ((*(p)) & HLL_SPARSE_VAL_BIT)\n#define HLL_SPARSE_ZERO_LEN(p) (((*(p)) & 0x3f)+1)\n#define HLL_SPARSE_XZERO_LEN(p) (((((*(p)) & 0x3f) << 8) | (*((p)+1)))+1)\n#define HLL_SPARSE_VAL_VALUE(p) ((((*(p)) >> 2) & 0x1f)+1)\n#define HLL_SPARSE_VAL_LEN(p) (((*(p)) & 0x3)+1)\n#define HLL_SPARSE_VAL_MAX_VALUE 32\n#define HLL_SPARSE_VAL_MAX_LEN 4\n#define HLL_SPARSE_ZERO_MAX_LEN 64\n#define HLL_SPARSE_XZERO_MAX_LEN 16384\n#define HLL_SPARSE_VAL_SET(p,val,len) do { \\\n    *(p) = (((val)-1)<<2|((len)-1))|HLL_SPARSE_VAL_BIT; \\\n} while(0)\n#define HLL_SPARSE_ZERO_SET(p,len) do { \\\n    *(p) = (len)-1; \\\n} while(0)\n#define HLL_SPARSE_XZERO_SET(p,len) do { \\\n    int _l = (len)-1; \\\n    *(p) = (_l>>8) | HLL_SPARSE_XZERO_BIT; \\\n    *((p)+1) = (_l&0xff); \\\n} while(0)\n\n/* ========================= HyperLogLog algorithm  ========================= */\n\n/* Our hash function is MurmurHash2, 64 bit version.\n * It was modified for Redis in order to provide the same result in\n * big and little endian archs (endian neutral). */\nuint64_t MurmurHash64A (const void * key, int len, unsigned int seed) {\n    const uint64_t m = 0xc6a4a7935bd1e995;\n    const int r = 47;\n    uint64_t h = seed ^ (len * m);\n    const uint8_t *data = (const uint8_t *)key;\n    const uint8_t *end = data + (len-(len&7));\n\n    while(data != end) {\n        uint64_t k;\n\n#if (BYTE_ORDER == LITTLE_ENDIAN)\n        k = *((uint64_t*)data);\n#else\n        k = (uint64_t) data[0];\n        k |= (uint64_t) data[1] << 8;\n        k |= (uint64_t) data[2] << 16;\n        k |= (uint64_t) data[3] << 24;\n        k |= (uint64_t) data[4] << 32;\n        k |= (uint64_t) data[5] << 40;\n        k |= (uint64_t) data[6] << 48;\n        k |= (uint64_t) data[7] << 56;\n#endif\n\n        k *= m;\n        k ^= k >> r;\n        k *= m;\n        h ^= k;\n        h *= m;\n        data += 8;\n    }\n\n    switch(len & 7) {\n    case 7: h ^= (uint64_t)data[6] << 48;\n    case 6: h ^= (uint64_t)data[5] << 40;\n    case 5: h ^= (uint64_t)data[4] << 32;\n    case 4: h ^= (uint64_t)data[3] << 24;\n    case 3: h ^= (uint64_t)data[2] << 16;\n    case 2: h ^= (uint64_t)data[1] << 8;\n    case 1: h ^= (uint64_t)data[0];\n            h *= m;\n    };\n\n    h ^= h >> r;\n    h *= m;\n    h ^= h >> r;\n    return h;\n}\n\n/* Given a string element to add to the HyperLogLog, returns the length\n * of the pattern 000..1 of the element hash. As a side effect 'regp' is\n * set to the register index this element hashes to. */\nint hllPatLen(unsigned char *ele, size_t elesize, long *regp) {\n    uint64_t hash, bit, index;\n    int count;\n\n    /* Count the number of zeroes starting from bit HLL_REGISTERS\n     * (that is a power of two corresponding to the first bit we don't use\n     * as index). The max run can be 64-P+1 bits.\n     *\n     * Note that the final \"1\" ending the sequence of zeroes must be\n     * included in the count, so if we find \"001\" the count is 3, and\n     * the smallest count possible is no zeroes at all, just a 1 bit\n     * at the first position, that is a count of 1.\n     *\n     * This may sound like inefficient, but actually in the average case\n     * there are high probabilities to find a 1 after a few iterations. */\n    hash = MurmurHash64A(ele,elesize,0xadc83b19ULL);\n    index = hash & HLL_P_MASK; /* Register index. */\n    hash |= ((uint64_t)1<<63); /* Make sure the loop terminates. */\n    bit = HLL_REGISTERS; /* First bit not used to address the register. */\n    count = 1; /* Initialized to 1 since we count the \"00000...1\" pattern. */\n    while((hash & bit) == 0) {\n        count++;\n        bit <<= 1;\n    }\n    *regp = (int) index;\n    return count;\n}\n\n/* ================== Dense representation implementation  ================== */\n\n/* \"Add\" the element in the dense hyperloglog data structure.\n * Actually nothing is added, but the max 0 pattern counter of the subset\n * the element belongs to is incremented if needed.\n *\n * 'registers' is expected to have room for HLL_REGISTERS plus an\n * additional byte on the right. This requirement is met by sds strings\n * automatically since they are implicitly null terminated.\n *\n * The function always succeed, however if as a result of the operation\n * the approximated cardinality changed, 1 is returned. Otherwise 0\n * is returned. */\nint hllDenseAdd(uint8_t *registers, unsigned char *ele, size_t elesize) {\n    uint8_t oldcount, count;\n    long index;\n\n    /* Update the register if this element produced a longer run of zeroes. */\n    count = hllPatLen(ele,elesize,&index);\n    HLL_DENSE_GET_REGISTER(oldcount,registers,index);\n    if (count > oldcount) {\n        HLL_DENSE_SET_REGISTER(registers,index,count);\n        return 1;\n    } else {\n        return 0;\n    }\n}\n\n/* Compute SUM(2^-reg) in the dense representation.\n * PE is an array with a pre-computer table of values 2^-reg indexed by reg.\n * As a side effect the integer pointed by 'ezp' is set to the number\n * of zero registers. */\ndouble hllDenseSum(uint8_t *registers, double *PE, int *ezp) {\n    double E = 0;\n    int j, ez = 0;\n\n    /* Redis default is to use 16384 registers 6 bits each. The code works\n     * with other values by modifying the defines, but for our target value\n     * we take a faster path with unrolled loops. */\n    if (HLL_REGISTERS == 16384 && HLL_BITS == 6) {\n        uint8_t *r = registers;\n        unsigned long r0, r1, r2, r3, r4, r5, r6, r7, r8, r9,\n                      r10, r11, r12, r13, r14, r15;\n        for (j = 0; j < 1024; j++) {\n            /* Handle 16 registers per iteration. */\n            r0 = r[0] & 63; if (r0 == 0) ez++;\n            r1 = (r[0] >> 6 | r[1] << 2) & 63; if (r1 == 0) ez++;\n            r2 = (r[1] >> 4 | r[2] << 4) & 63; if (r2 == 0) ez++;\n            r3 = (r[2] >> 2) & 63; if (r3 == 0) ez++;\n            r4 = r[3] & 63; if (r4 == 0) ez++;\n            r5 = (r[3] >> 6 | r[4] << 2) & 63; if (r5 == 0) ez++;\n            r6 = (r[4] >> 4 | r[5] << 4) & 63; if (r6 == 0) ez++;\n            r7 = (r[5] >> 2) & 63; if (r7 == 0) ez++;\n            r8 = r[6] & 63; if (r8 == 0) ez++;\n            r9 = (r[6] >> 6 | r[7] << 2) & 63; if (r9 == 0) ez++;\n            r10 = (r[7] >> 4 | r[8] << 4) & 63; if (r10 == 0) ez++;\n            r11 = (r[8] >> 2) & 63; if (r11 == 0) ez++;\n            r12 = r[9] & 63; if (r12 == 0) ez++;\n            r13 = (r[9] >> 6 | r[10] << 2) & 63; if (r13 == 0) ez++;\n            r14 = (r[10] >> 4 | r[11] << 4) & 63; if (r14 == 0) ez++;\n            r15 = (r[11] >> 2) & 63; if (r15 == 0) ez++;\n\n            /* Additional parens will allow the compiler to optimize the\n             * code more with a loss of precision that is not very relevant\n             * here (floating point math is not commutative!). */\n            E += (PE[r0] + PE[r1]) + (PE[r2] + PE[r3]) + (PE[r4] + PE[r5]) +\n                 (PE[r6] + PE[r7]) + (PE[r8] + PE[r9]) + (PE[r10] + PE[r11]) +\n                 (PE[r12] + PE[r13]) + (PE[r14] + PE[r15]);\n            r += 12;\n        }\n    } else {\n        for (j = 0; j < HLL_REGISTERS; j++) {\n            unsigned long reg;\n\n            HLL_DENSE_GET_REGISTER(reg,registers,j);\n            if (reg == 0) {\n                ez++;\n                /* Increment E at the end of the loop. */\n            } else {\n                E += PE[reg]; /* Precomputed 2^(-reg[j]). */\n            }\n        }\n        E += ez; /* Add 2^0 'ez' times. */\n    }\n    *ezp = ez;\n    return E;\n}\n\n/* ================== Sparse representation implementation  ================= */\n\n/* Convert the HLL with sparse representation given as input in its dense\n * representation. Both representations are represented by SDS strings, and\n * the input representation is freed as a side effect.\n *\n * The function returns C_OK if the sparse representation was valid,\n * otherwise C_ERR is returned if the representation was corrupted. */\nint hllSparseToDense(robj *o) {\n    sds sparse = o->ptr, dense;\n    struct hllhdr *hdr, *oldhdr = (struct hllhdr*)sparse;\n    int idx = 0, runlen, regval;\n    uint8_t *p = (uint8_t*)sparse, *end = p+sdslen(sparse);\n\n    /* If the representation is already the right one return ASAP. */\n    hdr = (struct hllhdr*) sparse;\n    if (hdr->encoding == HLL_DENSE) return C_OK;\n\n    /* Create a string of the right size filled with zero bytes.\n     * Note that the cached cardinality is set to 0 as a side effect\n     * that is exactly the cardinality of an empty HLL. */\n    dense = sdsnewlen(NULL,HLL_DENSE_SIZE);\n    hdr = (struct hllhdr*) dense;\n    *hdr = *oldhdr; /* This will copy the magic and cached cardinality. */\n    hdr->encoding = HLL_DENSE;\n\n    /* Now read the sparse representation and set non-zero registers\n     * accordingly. */\n    p += HLL_HDR_SIZE;\n    while(p < end) {\n        if (HLL_SPARSE_IS_ZERO(p)) {\n            runlen = HLL_SPARSE_ZERO_LEN(p);\n            idx += runlen;\n            p++;\n        } else if (HLL_SPARSE_IS_XZERO(p)) {\n            runlen = HLL_SPARSE_XZERO_LEN(p);\n            idx += runlen;\n            p += 2;\n        } else {\n            runlen = HLL_SPARSE_VAL_LEN(p);\n            regval = HLL_SPARSE_VAL_VALUE(p);\n            while(runlen--) {\n                HLL_DENSE_SET_REGISTER(hdr->registers,idx,regval);\n                idx++;\n            }\n            p++;\n        }\n    }\n\n    /* If the sparse representation was valid, we expect to find idx\n     * set to HLL_REGISTERS. */\n    if (idx != HLL_REGISTERS) {\n        sdsfree(dense);\n        return C_ERR;\n    }\n\n    /* Free the old representation and set the new one. */\n    sdsfree(o->ptr);\n    o->ptr = dense;\n    return C_OK;\n}\n\n/* \"Add\" the element in the sparse hyperloglog data structure.\n * Actually nothing is added, but the max 0 pattern counter of the subset\n * the element belongs to is incremented if needed.\n *\n * The object 'o' is the String object holding the HLL. The function requires\n * a reference to the object in order to be able to enlarge the string if\n * needed.\n *\n * On success, the function returns 1 if the cardinality changed, or 0\n * if the register for this element was not updated.\n * On error (if the representation is invalid) -1 is returned.\n *\n * As a side effect the function may promote the HLL representation from\n * sparse to dense: this happens when a register requires to be set to a value\n * not representable with the sparse representation, or when the resulting\n * size would be greater than server.hll_sparse_max_bytes. */\nint hllSparseAdd(robj *o, unsigned char *ele, size_t elesize) {\n    struct hllhdr *hdr;\n    uint8_t oldcount, count, *sparse, *end, *p, *prev, *next;\n    long index, first, span;\n    long is_zero = 0, is_xzero = 0, is_val = 0, runlen = 0;\n\n    /* Update the register if this element produced a longer run of zeroes. */\n    count = hllPatLen(ele,elesize,&index);\n\n    /* If the count is too big to be representable by the sparse representation\n     * switch to dense representation. */\n    if (count > HLL_SPARSE_VAL_MAX_VALUE) goto promote;\n\n    /* When updating a sparse representation, sometimes we may need to\n     * enlarge the buffer for up to 3 bytes in the worst case (XZERO split\n     * into XZERO-VAL-XZERO). Make sure there is enough space right now\n     * so that the pointers we take during the execution of the function\n     * will be valid all the time. */\n    o->ptr = sdsMakeRoomFor(o->ptr,3);\n\n    /* Step 1: we need to locate the opcode we need to modify to check\n     * if a value update is actually needed. */\n    sparse = p = ((uint8_t*)o->ptr) + HLL_HDR_SIZE;\n    end = p + sdslen(o->ptr) - HLL_HDR_SIZE;\n\n    first = 0;\n    prev = NULL; /* Points to previos opcode at the end of the loop. */\n    next = NULL; /* Points to the next opcode at the end of the loop. */\n    span = 0;\n    while(p < end) {\n        long oplen;\n\n        /* Set span to the number of registers covered by this opcode.\n         *\n         * This is the most performance critical loop of the sparse\n         * representation. Sorting the conditionals from the most to the\n         * least frequent opcode in many-bytes sparse HLLs is faster. */\n        oplen = 1;\n        if (HLL_SPARSE_IS_ZERO(p)) {\n            span = HLL_SPARSE_ZERO_LEN(p);\n        } else if (HLL_SPARSE_IS_VAL(p)) {\n            span = HLL_SPARSE_VAL_LEN(p);\n        } else { /* XZERO. */\n            span = HLL_SPARSE_XZERO_LEN(p);\n            oplen = 2;\n        }\n        /* Break if this opcode covers the register as 'index'. */\n        if (index <= first+span-1) break;\n        prev = p;\n        p += oplen;\n        first += span;\n    }\n    if (span == 0) return -1; /* Invalid format. */\n\n    next = HLL_SPARSE_IS_XZERO(p) ? p+2 : p+1;\n    if (next >= end) next = NULL;\n\n    /* Cache current opcode type to avoid using the macro again and\n     * again for something that will not change.\n     * Also cache the run-length of the opcode. */\n    if (HLL_SPARSE_IS_ZERO(p)) {\n        is_zero = 1;\n        runlen = HLL_SPARSE_ZERO_LEN(p);\n    } else if (HLL_SPARSE_IS_XZERO(p)) {\n        is_xzero = 1;\n        runlen = HLL_SPARSE_XZERO_LEN(p);\n    } else {\n        is_val = 1;\n        runlen = HLL_SPARSE_VAL_LEN(p);\n    }\n\n    /* Step 2: After the loop:\n     *\n     * 'first' stores to the index of the first register covered\n     *  by the current opcode, which is pointed by 'p'.\n     *\n     * 'next' ad 'prev' store respectively the next and previous opcode,\n     *  or NULL if the opcode at 'p' is respectively the last or first.\n     *\n     * 'span' is set to the number of registers covered by the current\n     *  opcode.\n     *\n     * There are different cases in order to update the data structure\n     * in place without generating it from scratch:\n     *\n     * A) If it is a VAL opcode already set to a value >= our 'count'\n     *    no update is needed, regardless of the VAL run-length field.\n     *    In this case PFADD returns 0 since no changes are performed.\n     *\n     * B) If it is a VAL opcode with len = 1 (representing only our\n     *    register) and the value is less than 'count', we just update it\n     *    since this is a trivial case. */\n    if (is_val) {\n        oldcount = HLL_SPARSE_VAL_VALUE(p);\n        /* Case A. */\n        if (oldcount >= count) return 0;\n\n        /* Case B. */\n        if (runlen == 1) {\n            HLL_SPARSE_VAL_SET(p,count,1);\n            goto updated;\n        }\n    }\n\n    /* C) Another trivial to handle case is a ZERO opcode with a len of 1.\n     * We can just replace it with a VAL opcode with our value and len of 1. */\n    if (is_zero && runlen == 1) {\n        HLL_SPARSE_VAL_SET(p,count,1);\n        goto updated;\n    }\n\n    /* D) General case.\n     *\n     * The other cases are more complex: our register requires to be updated\n     * and is either currently represented by a VAL opcode with len > 1,\n     * by a ZERO opcode with len > 1, or by an XZERO opcode.\n     *\n     * In those cases the original opcode must be split into muliple\n     * opcodes. The worst case is an XZERO split in the middle resuling into\n     * XZERO - VAL - XZERO, so the resulting sequence max length is\n     * 5 bytes.\n     *\n     * We perform the split writing the new sequence into the 'new' buffer\n     * with 'newlen' as length. Later the new sequence is inserted in place\n     * of the old one, possibly moving what is on the right a few bytes\n     * if the new sequence is longer than the older one. */\n    uint8_t seq[5], *n = seq;\n    int last = first+span-1; /* Last register covered by the sequence. */\n    int len;\n\n    if (is_zero || is_xzero) {\n        /* Handle splitting of ZERO / XZERO. */\n        if (index != first) {\n            len = index-first;\n            if (len > HLL_SPARSE_ZERO_MAX_LEN) {\n                HLL_SPARSE_XZERO_SET(n,len);\n                n += 2;\n            } else {\n                HLL_SPARSE_ZERO_SET(n,len);\n                n++;\n            }\n        }\n        HLL_SPARSE_VAL_SET(n,count,1);\n        n++;\n        if (index != last) {\n            len = last-index;\n            if (len > HLL_SPARSE_ZERO_MAX_LEN) {\n                HLL_SPARSE_XZERO_SET(n,len);\n                n += 2;\n            } else {\n                HLL_SPARSE_ZERO_SET(n,len);\n                n++;\n            }\n        }\n    } else {\n        /* Handle splitting of VAL. */\n        int curval = HLL_SPARSE_VAL_VALUE(p);\n\n        if (index != first) {\n            len = index-first;\n            HLL_SPARSE_VAL_SET(n,curval,len);\n            n++;\n        }\n        HLL_SPARSE_VAL_SET(n,count,1);\n        n++;\n        if (index != last) {\n            len = last-index;\n            HLL_SPARSE_VAL_SET(n,curval,len);\n            n++;\n        }\n    }\n\n    /* Step 3: substitute the new sequence with the old one.\n     *\n     * Note that we already allocated space on the sds string\n     * calling sdsMakeRoomFor(). */\n     int seqlen = n-seq;\n     int oldlen = is_xzero ? 2 : 1;\n     int deltalen = seqlen-oldlen;\n\n     if (deltalen > 0 &&\n         sdslen(o->ptr)+deltalen > server.hll_sparse_max_bytes) goto promote;\n     if (deltalen && next) memmove(next+deltalen,next,end-next);\n     sdsIncrLen(o->ptr,deltalen);\n     memcpy(p,seq,seqlen);\n     end += deltalen;\n\nupdated:\n    /* Step 4: Merge adjacent values if possible.\n     *\n     * The representation was updated, however the resulting representation\n     * may not be optimal: adjacent VAL opcodes can sometimes be merged into\n     * a single one. */\n    p = prev ? prev : sparse;\n    int scanlen = 5; /* Scan up to 5 upcodes starting from prev. */\n    while (p < end && scanlen--) {\n        if (HLL_SPARSE_IS_XZERO(p)) {\n            p += 2;\n            continue;\n        } else if (HLL_SPARSE_IS_ZERO(p)) {\n            p++;\n            continue;\n        }\n        /* We need two adjacent VAL opcodes to try a merge, having\n         * the same value, and a len that fits the VAL opcode max len. */\n        if (p+1 < end && HLL_SPARSE_IS_VAL(p+1)) {\n            int v1 = HLL_SPARSE_VAL_VALUE(p);\n            int v2 = HLL_SPARSE_VAL_VALUE(p+1);\n            if (v1 == v2) {\n                int len = HLL_SPARSE_VAL_LEN(p)+HLL_SPARSE_VAL_LEN(p+1);\n                if (len <= HLL_SPARSE_VAL_MAX_LEN) {\n                    HLL_SPARSE_VAL_SET(p+1,v1,len);\n                    memmove(p,p+1,end-p);\n                    sdsIncrLen(o->ptr,-1);\n                    end--;\n                    /* After a merge we reiterate without incrementing 'p'\n                     * in order to try to merge the just merged value with\n                     * a value on its right. */\n                    continue;\n                }\n            }\n        }\n        p++;\n    }\n\n    /* Invalidate the cached cardinality. */\n    hdr = o->ptr;\n    HLL_INVALIDATE_CACHE(hdr);\n    return 1;\n\npromote: /* Promote to dense representation. */\n    if (hllSparseToDense(o) == C_ERR) return -1; /* Corrupted HLL. */\n    hdr = o->ptr;\n\n    /* We need to call hllDenseAdd() to perform the operation after the\n     * conversion. However the result must be 1, since if we need to\n     * convert from sparse to dense a register requires to be updated.\n     *\n     * Note that this in turn means that PFADD will make sure the command\n     * is propagated to slaves / AOF, so if there is a sparse -> dense\n     * convertion, it will be performed in all the slaves as well. */\n    int dense_retval = hllDenseAdd(hdr->registers, ele, elesize);\n    serverAssert(dense_retval == 1);\n    return dense_retval;\n}\n\n/* Compute SUM(2^-reg) in the sparse representation.\n * PE is an array with a pre-computer table of values 2^-reg indexed by reg.\n * As a side effect the integer pointed by 'ezp' is set to the number\n * of zero registers. */\ndouble hllSparseSum(uint8_t *sparse, int sparselen, double *PE, int *ezp, int *invalid) {\n    double E = 0;\n    int ez = 0, idx = 0, runlen, regval;\n    uint8_t *end = sparse+sparselen, *p = sparse;\n\n    while(p < end) {\n        if (HLL_SPARSE_IS_ZERO(p)) {\n            runlen = HLL_SPARSE_ZERO_LEN(p);\n            idx += runlen;\n            ez += runlen;\n            /* Increment E at the end of the loop. */\n            p++;\n        } else if (HLL_SPARSE_IS_XZERO(p)) {\n            runlen = HLL_SPARSE_XZERO_LEN(p);\n            idx += runlen;\n            ez += runlen;\n            /* Increment E at the end of the loop. */\n            p += 2;\n        } else {\n            runlen = HLL_SPARSE_VAL_LEN(p);\n            regval = HLL_SPARSE_VAL_VALUE(p);\n            idx += runlen;\n            E += PE[regval]*runlen;\n            p++;\n        }\n    }\n    if (idx != HLL_REGISTERS && invalid) *invalid = 1;\n    E += ez; /* Add 2^0 'ez' times. */\n    *ezp = ez;\n    return E;\n}\n\n/* ========================= HyperLogLog Count ==============================\n * This is the core of the algorithm where the approximated count is computed.\n * The function uses the lower level hllDenseSum() and hllSparseSum() functions\n * as helpers to compute the SUM(2^-reg) part of the computation, which is\n * representation-specific, while all the rest is common. */\n\n/* Implements the SUM operation for uint8_t data type which is only used\n * internally as speedup for PFCOUNT with multiple keys. */\ndouble hllRawSum(uint8_t *registers, double *PE, int *ezp) {\n    double E = 0;\n    int j, ez = 0;\n    uint64_t *word = (uint64_t*) registers;\n    uint8_t *bytes;\n\n    for (j = 0; j < HLL_REGISTERS/8; j++) {\n        if (*word == 0) {\n            ez += 8;\n        } else {\n            bytes = (uint8_t*) word;\n            if (bytes[0]) E += PE[bytes[0]]; else ez++;\n            if (bytes[1]) E += PE[bytes[1]]; else ez++;\n            if (bytes[2]) E += PE[bytes[2]]; else ez++;\n            if (bytes[3]) E += PE[bytes[3]]; else ez++;\n            if (bytes[4]) E += PE[bytes[4]]; else ez++;\n            if (bytes[5]) E += PE[bytes[5]]; else ez++;\n            if (bytes[6]) E += PE[bytes[6]]; else ez++;\n            if (bytes[7]) E += PE[bytes[7]]; else ez++;\n        }\n        word++;\n    }\n    E += ez; /* 2^(-reg[j]) is 1 when m is 0, add it 'ez' times for every\n                zero register in the HLL. */\n    *ezp = ez;\n    return E;\n}\n\n/* Return the approximated cardinality of the set based on the harmonic\n * mean of the registers values. 'hdr' points to the start of the SDS\n * representing the String object holding the HLL representation.\n *\n * If the sparse representation of the HLL object is not valid, the integer\n * pointed by 'invalid' is set to non-zero, otherwise it is left untouched.\n *\n * hllCount() supports a special internal-only encoding of HLL_RAW, that\n * is, hdr->registers will point to an uint8_t array of HLL_REGISTERS element.\n * This is useful in order to speedup PFCOUNT when called against multiple\n * keys (no need to work with 6-bit integers encoding). */\nuint64_t hllCount(struct hllhdr *hdr, int *invalid) {\n    double m = HLL_REGISTERS;\n    double E, alpha = 0.7213/(1+1.079/m);\n    int j, ez; /* Number of registers equal to 0. */\n\n    /* We precompute 2^(-reg[j]) in a small table in order to\n     * speedup the computation of SUM(2^-register[0..i]). */\n    static int initialized = 0;\n    static double PE[64];\n    if (!initialized) {\n        PE[0] = 1; /* 2^(-reg[j]) is 1 when m is 0. */\n        for (j = 1; j < 64; j++) {\n            /* 2^(-reg[j]) is the same as 1/2^reg[j]. */\n            PE[j] = 1.0/(1ULL << j);\n        }\n        initialized = 1;\n    }\n\n    /* Compute SUM(2^-register[0..i]). */\n    if (hdr->encoding == HLL_DENSE) {\n        E = hllDenseSum(hdr->registers,PE,&ez);\n    } else if (hdr->encoding == HLL_SPARSE) {\n        E = hllSparseSum(hdr->registers,\n                         sdslen((sds)hdr)-HLL_HDR_SIZE,PE,&ez,invalid);\n    } else if (hdr->encoding == HLL_RAW) {\n        E = hllRawSum(hdr->registers,PE,&ez);\n    } else {\n        serverPanic(\"Unknown HyperLogLog encoding in hllCount()\");\n    }\n\n    /* Muliply the inverse of E for alpha_m * m^2 to have the raw estimate. */\n    E = (1/E)*alpha*m*m;\n\n    /* Use the LINEARCOUNTING algorithm for small cardinalities.\n     * For larger values but up to 72000 HyperLogLog raw approximation is\n     * used since linear counting error starts to increase. However HyperLogLog\n     * shows a strong bias in the range 2.5*16384 - 72000, so we try to\n     * compensate for it. */\n    if (E < m*2.5 && ez != 0) {\n        E = m*log(m/ez); /* LINEARCOUNTING() */\n    } else if (m == 16384 && E < 72000) {\n        /* We did polynomial regression of the bias for this range, this\n         * way we can compute the bias for a given cardinality and correct\n         * according to it. Only apply the correction for P=14 that's what\n         * we use and the value the correction was verified with. */\n        double bias = 5.9119*1.0e-18*(E*E*E*E)\n                      -1.4253*1.0e-12*(E*E*E)+\n                      1.2940*1.0e-7*(E*E)\n                      -5.2921*1.0e-3*E+\n                      83.3216;\n        E -= E*(bias/100);\n    }\n    /* We don't apply the correction for E > 1/30 of 2^32 since we use\n     * a 64 bit function and 6 bit counters. To apply the correction for\n     * 1/30 of 2^64 is not needed since it would require a huge set\n     * to approach such a value. */\n    return (uint64_t) E;\n}\n\n/* Call hllDenseAdd() or hllSparseAdd() according to the HLL encoding. */\nint hllAdd(robj *o, unsigned char *ele, size_t elesize) {\n    struct hllhdr *hdr = o->ptr;\n    switch(hdr->encoding) {\n    case HLL_DENSE: return hllDenseAdd(hdr->registers,ele,elesize);\n    case HLL_SPARSE: return hllSparseAdd(o,ele,elesize);\n    default: return -1; /* Invalid representation. */\n    }\n}\n\n/* Merge by computing MAX(registers[i],hll[i]) the HyperLogLog 'hll'\n * with an array of uint8_t HLL_REGISTERS registers pointed by 'max'.\n *\n * The hll object must be already validated via isHLLObjectOrReply()\n * or in some other way.\n *\n * If the HyperLogLog is sparse and is found to be invalid, C_ERR\n * is returned, otherwise the function always succeeds. */\nint hllMerge(uint8_t *max, robj *hll) {\n    struct hllhdr *hdr = hll->ptr;\n    int i;\n\n    if (hdr->encoding == HLL_DENSE) {\n        uint8_t val;\n\n        for (i = 0; i < HLL_REGISTERS; i++) {\n            HLL_DENSE_GET_REGISTER(val,hdr->registers,i);\n            if (val > max[i]) max[i] = val;\n        }\n    } else {\n        uint8_t *p = hll->ptr, *end = p + sdslen(hll->ptr);\n        long runlen, regval;\n\n        p += HLL_HDR_SIZE;\n        i = 0;\n        while(p < end) {\n            if (HLL_SPARSE_IS_ZERO(p)) {\n                runlen = HLL_SPARSE_ZERO_LEN(p);\n                i += runlen;\n                p++;\n            } else if (HLL_SPARSE_IS_XZERO(p)) {\n                runlen = HLL_SPARSE_XZERO_LEN(p);\n                i += runlen;\n                p += 2;\n            } else {\n                runlen = HLL_SPARSE_VAL_LEN(p);\n                regval = HLL_SPARSE_VAL_VALUE(p);\n                while(runlen--) {\n                    if (regval > max[i]) max[i] = regval;\n                    i++;\n                }\n                p++;\n            }\n        }\n        if (i != HLL_REGISTERS) return C_ERR;\n    }\n    return C_OK;\n}\n\n/* ========================== HyperLogLog commands ========================== */\n\n/* Create an HLL object. We always create the HLL using sparse encoding.\n * This will be upgraded to the dense representation as needed. */\nrobj *createHLLObject(void) {\n    robj *o;\n    struct hllhdr *hdr;\n    sds s;\n    uint8_t *p;\n    int sparselen = HLL_HDR_SIZE +\n                    (((HLL_REGISTERS+(HLL_SPARSE_XZERO_MAX_LEN-1)) /\n                     HLL_SPARSE_XZERO_MAX_LEN)*2);\n    int aux;\n\n    /* Populate the sparse representation with as many XZERO opcodes as\n     * needed to represent all the registers. */\n    aux = HLL_REGISTERS;\n    s = sdsnewlen(NULL,sparselen);\n    p = (uint8_t*)s + HLL_HDR_SIZE;\n    while(aux) {\n        int xzero = HLL_SPARSE_XZERO_MAX_LEN;\n        if (xzero > aux) xzero = aux;\n        HLL_SPARSE_XZERO_SET(p,xzero);\n        p += 2;\n        aux -= xzero;\n    }\n    serverAssert((p-(uint8_t*)s) == sparselen);\n\n    /* Create the actual object. */\n    o = createObject(OBJ_STRING,s);\n    hdr = o->ptr;\n    memcpy(hdr->magic,\"HYLL\",4);\n    hdr->encoding = HLL_SPARSE;\n    return o;\n}\n\n/* Check if the object is a String with a valid HLL representation.\n * Return C_OK if this is true, otherwise reply to the client\n * with an error and return C_ERR. */\nint isHLLObjectOrReply(client *c, robj *o) {\n    struct hllhdr *hdr;\n\n    /* Key exists, check type */\n    if (checkType(c,o,OBJ_STRING))\n        return C_ERR; /* Error already sent. */\n\n    if (stringObjectLen(o) < sizeof(*hdr)) goto invalid;\n    hdr = o->ptr;\n\n    /* Magic should be \"HYLL\". */\n    if (hdr->magic[0] != 'H' || hdr->magic[1] != 'Y' ||\n        hdr->magic[2] != 'L' || hdr->magic[3] != 'L') goto invalid;\n\n    if (hdr->encoding > HLL_MAX_ENCODING) goto invalid;\n\n    /* Dense representation string length should match exactly. */\n    if (hdr->encoding == HLL_DENSE &&\n        stringObjectLen(o) != HLL_DENSE_SIZE) goto invalid;\n\n    /* All tests passed. */\n    return C_OK;\n\ninvalid:\n    addReplySds(c,\n        sdsnew(\"-WRONGTYPE Key is not a valid \"\n               \"HyperLogLog string value.\\r\\n\"));\n    return C_ERR;\n}\n\n/* PFADD var ele ele ele ... ele => :0 or :1 */\nvoid pfaddCommand(client *c) {\n    robj *o = lookupKeyWrite(c->db,c->argv[1]);\n    struct hllhdr *hdr;\n    int updated = 0, j;\n\n    if (o == NULL) {\n        /* Create the key with a string value of the exact length to\n         * hold our HLL data structure. sdsnewlen() when NULL is passed\n         * is guaranteed to return bytes initialized to zero. */\n        o = createHLLObject();\n        dbAdd(c->db,c->argv[1],o);\n        updated++;\n    } else {\n        if (isHLLObjectOrReply(c,o) != C_OK) return;\n        o = dbUnshareStringValue(c->db,c->argv[1],o);\n    }\n    /* Perform the low level ADD operation for every element. */\n    for (j = 2; j < c->argc; j++) {\n        int retval = hllAdd(o, (unsigned char*)c->argv[j]->ptr,\n                               sdslen(c->argv[j]->ptr));\n        switch(retval) {\n        case 1:\n            updated++;\n            break;\n        case -1:\n            addReplySds(c,sdsnew(invalid_hll_err));\n            return;\n        }\n    }\n    hdr = o->ptr;\n    if (updated) {\n        signalModifiedKey(c->db,c->argv[1]);\n        notifyKeyspaceEvent(NOTIFY_STRING,\"pfadd\",c->argv[1],c->db->id);\n        server.dirty++;\n        HLL_INVALIDATE_CACHE(hdr);\n    }\n    addReply(c, updated ? shared.cone : shared.czero);\n}\n\n/* PFCOUNT var -> approximated cardinality of set. */\nvoid pfcountCommand(client *c) {\n    robj *o;\n    struct hllhdr *hdr;\n    uint64_t card;\n\n    /* Case 1: multi-key keys, cardinality of the union.\n     *\n     * When multiple keys are specified, PFCOUNT actually computes\n     * the cardinality of the merge of the N HLLs specified. */\n    if (c->argc > 2) {\n        uint8_t max[HLL_HDR_SIZE+HLL_REGISTERS], *registers;\n        int j;\n\n        /* Compute an HLL with M[i] = MAX(M[i]_j). */\n        memset(max,0,sizeof(max));\n        hdr = (struct hllhdr*) max;\n        hdr->encoding = HLL_RAW; /* Special internal-only encoding. */\n        registers = max + HLL_HDR_SIZE;\n        for (j = 1; j < c->argc; j++) {\n            /* Check type and size. */\n            robj *o = lookupKeyRead(c->db,c->argv[j]);\n            if (o == NULL) continue; /* Assume empty HLL for non existing var.*/\n            if (isHLLObjectOrReply(c,o) != C_OK) return;\n\n            /* Merge with this HLL with our 'max' HHL by setting max[i]\n             * to MAX(max[i],hll[i]). */\n            if (hllMerge(registers,o) == C_ERR) {\n                addReplySds(c,sdsnew(invalid_hll_err));\n                return;\n            }\n        }\n\n        /* Compute cardinality of the resulting set. */\n        addReplyLongLong(c,hllCount(hdr,NULL));\n        return;\n    }\n\n    /* Case 2: cardinality of the single HLL.\n     *\n     * The user specified a single key. Either return the cached value\n     * or compute one and update the cache. */\n    o = lookupKeyWrite(c->db,c->argv[1]);\n    if (o == NULL) {\n        /* No key? Cardinality is zero since no element was added, otherwise\n         * we would have a key as HLLADD creates it as a side effect. */\n        addReply(c,shared.czero);\n    } else {\n        if (isHLLObjectOrReply(c,o) != C_OK) return;\n        o = dbUnshareStringValue(c->db,c->argv[1],o);\n\n        /* Check if the cached cardinality is valid. */\n        hdr = o->ptr;\n        if (HLL_VALID_CACHE(hdr)) {\n            /* Just return the cached value. */\n            card = (uint64_t)hdr->card[0];\n            card |= (uint64_t)hdr->card[1] << 8;\n            card |= (uint64_t)hdr->card[2] << 16;\n            card |= (uint64_t)hdr->card[3] << 24;\n            card |= (uint64_t)hdr->card[4] << 32;\n            card |= (uint64_t)hdr->card[5] << 40;\n            card |= (uint64_t)hdr->card[6] << 48;\n            card |= (uint64_t)hdr->card[7] << 56;\n        } else {\n            int invalid = 0;\n            /* Recompute it and update the cached value. */\n            card = hllCount(hdr,&invalid);\n            if (invalid) {\n                addReplySds(c,sdsnew(invalid_hll_err));\n                return;\n            }\n            hdr->card[0] = card & 0xff;\n            hdr->card[1] = (card >> 8) & 0xff;\n            hdr->card[2] = (card >> 16) & 0xff;\n            hdr->card[3] = (card >> 24) & 0xff;\n            hdr->card[4] = (card >> 32) & 0xff;\n            hdr->card[5] = (card >> 40) & 0xff;\n            hdr->card[6] = (card >> 48) & 0xff;\n            hdr->card[7] = (card >> 56) & 0xff;\n            /* This is not considered a read-only command even if the\n             * data structure is not modified, since the cached value\n             * may be modified and given that the HLL is a Redis string\n             * we need to propagate the change. */\n            signalModifiedKey(c->db,c->argv[1]);\n            server.dirty++;\n        }\n        addReplyLongLong(c,card);\n    }\n}\n\n/* PFMERGE dest src1 src2 src3 ... srcN => OK */\nvoid pfmergeCommand(client *c) {\n    uint8_t max[HLL_REGISTERS];\n    struct hllhdr *hdr;\n    int j;\n\n    /* Compute an HLL with M[i] = MAX(M[i]_j).\n     * We we the maximum into the max array of registers. We'll write\n     * it to the target variable later. */\n    memset(max,0,sizeof(max));\n    for (j = 1; j < c->argc; j++) {\n        /* Check type and size. */\n        robj *o = lookupKeyRead(c->db,c->argv[j]);\n        if (o == NULL) continue; /* Assume empty HLL for non existing var. */\n        if (isHLLObjectOrReply(c,o) != C_OK) return;\n\n        /* Merge with this HLL with our 'max' HHL by setting max[i]\n         * to MAX(max[i],hll[i]). */\n        if (hllMerge(max,o) == C_ERR) {\n            addReplySds(c,sdsnew(invalid_hll_err));\n            return;\n        }\n    }\n\n    /* Create / unshare the destination key's value if needed. */\n    robj *o = lookupKeyWrite(c->db,c->argv[1]);\n    if (o == NULL) {\n        /* Create the key with a string value of the exact length to\n         * hold our HLL data structure. sdsnewlen() when NULL is passed\n         * is guaranteed to return bytes initialized to zero. */\n        o = createHLLObject();\n        dbAdd(c->db,c->argv[1],o);\n    } else {\n        /* If key exists we are sure it's of the right type/size\n         * since we checked when merging the different HLLs, so we\n         * don't check again. */\n        o = dbUnshareStringValue(c->db,c->argv[1],o);\n    }\n\n    /* Only support dense objects as destination. */\n    if (hllSparseToDense(o) == C_ERR) {\n        addReplySds(c,sdsnew(invalid_hll_err));\n        return;\n    }\n\n    /* Write the resulting HLL to the destination HLL registers and\n     * invalidate the cached value. */\n    hdr = o->ptr;\n    for (j = 0; j < HLL_REGISTERS; j++) {\n        HLL_DENSE_SET_REGISTER(hdr->registers,j,max[j]);\n    }\n    HLL_INVALIDATE_CACHE(hdr);\n\n    signalModifiedKey(c->db,c->argv[1]);\n    /* We generate an PFADD event for PFMERGE for semantical simplicity\n     * since in theory this is a mass-add of elements. */\n    notifyKeyspaceEvent(NOTIFY_STRING,\"pfadd\",c->argv[1],c->db->id);\n    server.dirty++;\n    addReply(c,shared.ok);\n}\n\n/* ========================== Testing / Debugging  ========================== */\n\n/* PFSELFTEST\n * This command performs a self-test of the HLL registers implementation.\n * Something that is not easy to test from within the outside. */\n#define HLL_TEST_CYCLES 1000\nvoid pfselftestCommand(client *c) {\n    unsigned int j, i;\n    sds bitcounters = sdsnewlen(NULL,HLL_DENSE_SIZE);\n    struct hllhdr *hdr = (struct hllhdr*) bitcounters, *hdr2;\n    robj *o = NULL;\n    uint8_t bytecounters[HLL_REGISTERS];\n\n    /* Test 1: access registers.\n     * The test is conceived to test that the different counters of our data\n     * structure are accessible and that setting their values both result in\n     * the correct value to be retained and not affect adjacent values. */\n    for (j = 0; j < HLL_TEST_CYCLES; j++) {\n        /* Set the HLL counters and an array of unsigned byes of the\n         * same size to the same set of random values. */\n        for (i = 0; i < HLL_REGISTERS; i++) {\n            unsigned int r = rand() & HLL_REGISTER_MAX;\n\n            bytecounters[i] = r;\n            HLL_DENSE_SET_REGISTER(hdr->registers,i,r);\n        }\n        /* Check that we are able to retrieve the same values. */\n        for (i = 0; i < HLL_REGISTERS; i++) {\n            unsigned int val;\n\n            HLL_DENSE_GET_REGISTER(val,hdr->registers,i);\n            if (val != bytecounters[i]) {\n                addReplyErrorFormat(c,\n                    \"TESTFAILED Register %d should be %d but is %d\",\n                    i, (int) bytecounters[i], (int) val);\n                goto cleanup;\n            }\n        }\n    }\n\n    /* Test 2: approximation error.\n     * The test adds unique elements and check that the estimated value\n     * is always reasonable bounds.\n     *\n     * We check that the error is smaller than a few times than the expected\n     * standard error, to make it very unlikely for the test to fail because\n     * of a \"bad\" run.\n     *\n     * The test is performed with both dense and sparse HLLs at the same\n     * time also verifying that the computed cardinality is the same. */\n    memset(hdr->registers,0,HLL_DENSE_SIZE-HLL_HDR_SIZE);\n    o = createHLLObject();\n    double relerr = 1.04/sqrt(HLL_REGISTERS);\n    int64_t checkpoint = 1;\n    uint64_t seed = (uint64_t)rand() | (uint64_t)rand() << 32;\n    uint64_t ele;\n    for (j = 1; j <= 10000000; j++) {\n        ele = j ^ seed;\n        hllDenseAdd(hdr->registers,(unsigned char*)&ele,sizeof(ele));\n        hllAdd(o,(unsigned char*)&ele,sizeof(ele));\n\n        /* Make sure that for small cardinalities we use sparse\n         * encoding. */\n        if (j == checkpoint && j < server.hll_sparse_max_bytes/2) {\n            hdr2 = o->ptr;\n            if (hdr2->encoding != HLL_SPARSE) {\n                addReplyError(c, \"TESTFAILED sparse encoding not used\");\n                goto cleanup;\n            }\n        }\n\n        /* Check that dense and sparse representations agree. */\n        if (j == checkpoint && hllCount(hdr,NULL) != hllCount(o->ptr,NULL)) {\n                addReplyError(c, \"TESTFAILED dense/sparse disagree\");\n                goto cleanup;\n        }\n\n        /* Check error. */\n        if (j == checkpoint) {\n            int64_t abserr = checkpoint - (int64_t)hllCount(hdr,NULL);\n            uint64_t maxerr = ceil(relerr*6*checkpoint);\n\n            /* Adjust the max error we expect for cardinality 10\n             * since from time to time it is statistically likely to get\n             * much higher error due to collision, resulting into a false\n             * positive. */\n            if (j == 10) maxerr = 1;\n\n            if (abserr < 0) abserr = -abserr;\n            if (abserr > (int64_t)maxerr) {\n                addReplyErrorFormat(c,\n                    \"TESTFAILED Too big error. card:%llu abserr:%llu\",\n                    (unsigned long long) checkpoint,\n                    (unsigned long long) abserr);\n                goto cleanup;\n            }\n            checkpoint *= 10;\n        }\n    }\n\n    /* Success! */\n    addReply(c,shared.ok);\n\ncleanup:\n    sdsfree(bitcounters);\n    if (o) decrRefCount(o);\n}\n\n/* PFDEBUG <subcommand> <key> ... args ...\n * Different debugging related operations about the HLL implementation. */\nvoid pfdebugCommand(client *c) {\n    char *cmd = c->argv[1]->ptr;\n    struct hllhdr *hdr;\n    robj *o;\n    int j;\n\n    o = lookupKeyWrite(c->db,c->argv[2]);\n    if (o == NULL) {\n        addReplyError(c,\"The specified key does not exist\");\n        return;\n    }\n    if (isHLLObjectOrReply(c,o) != C_OK) return;\n    o = dbUnshareStringValue(c->db,c->argv[2],o);\n    hdr = o->ptr;\n\n    /* PFDEBUG GETREG <key> */\n    if (!strcasecmp(cmd,\"getreg\")) {\n        if (c->argc != 3) goto arityerr;\n\n        if (hdr->encoding == HLL_SPARSE) {\n            if (hllSparseToDense(o) == C_ERR) {\n                addReplySds(c,sdsnew(invalid_hll_err));\n                return;\n            }\n            server.dirty++; /* Force propagation on encoding change. */\n        }\n\n        hdr = o->ptr;\n        addReplyMultiBulkLen(c,HLL_REGISTERS);\n        for (j = 0; j < HLL_REGISTERS; j++) {\n            uint8_t val;\n\n            HLL_DENSE_GET_REGISTER(val,hdr->registers,j);\n            addReplyLongLong(c,val);\n        }\n    }\n    /* PFDEBUG DECODE <key> */\n    else if (!strcasecmp(cmd,\"decode\")) {\n        if (c->argc != 3) goto arityerr;\n\n        uint8_t *p = o->ptr, *end = p+sdslen(o->ptr);\n        sds decoded = sdsempty();\n\n        if (hdr->encoding != HLL_SPARSE) {\n            addReplyError(c,\"HLL encoding is not sparse\");\n            return;\n        }\n\n        p += HLL_HDR_SIZE;\n        while(p < end) {\n            int runlen, regval;\n\n            if (HLL_SPARSE_IS_ZERO(p)) {\n                runlen = HLL_SPARSE_ZERO_LEN(p);\n                p++;\n                decoded = sdscatprintf(decoded,\"z:%d \",runlen);\n            } else if (HLL_SPARSE_IS_XZERO(p)) {\n                runlen = HLL_SPARSE_XZERO_LEN(p);\n                p += 2;\n                decoded = sdscatprintf(decoded,\"Z:%d \",runlen);\n            } else {\n                runlen = HLL_SPARSE_VAL_LEN(p);\n                regval = HLL_SPARSE_VAL_VALUE(p);\n                p++;\n                decoded = sdscatprintf(decoded,\"v:%d,%d \",regval,runlen);\n            }\n        }\n        decoded = sdstrim(decoded,\" \");\n        addReplyBulkCBuffer(c,decoded,sdslen(decoded));\n        sdsfree(decoded);\n    }\n    /* PFDEBUG ENCODING <key> */\n    else if (!strcasecmp(cmd,\"encoding\")) {\n        char *encodingstr[2] = {\"dense\",\"sparse\"};\n        if (c->argc != 3) goto arityerr;\n\n        addReplyStatus(c,encodingstr[hdr->encoding]);\n    }\n    /* PFDEBUG TODENSE <key> */\n    else if (!strcasecmp(cmd,\"todense\")) {\n        int conv = 0;\n        if (c->argc != 3) goto arityerr;\n\n        if (hdr->encoding == HLL_SPARSE) {\n            if (hllSparseToDense(o) == C_ERR) {\n                addReplySds(c,sdsnew(invalid_hll_err));\n                return;\n            }\n            conv = 1;\n            server.dirty++; /* Force propagation on encoding change. */\n        }\n        addReply(c,conv ? shared.cone : shared.czero);\n    } else {\n        addReplyErrorFormat(c,\"Unknown PFDEBUG subcommand '%s'\", cmd);\n    }\n    return;\n\narityerr:\n    addReplyErrorFormat(c,\n        \"Wrong number of arguments for the '%s' subcommand\",cmd);\n}\n\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/src/intset.c",
    "content": "/*\n * Copyright (c) 2009-2012, Pieter Noordhuis <pcnoordhuis at gmail dot com>\n * Copyright (c) 2009-2012, Salvatore Sanfilippo <antirez at gmail dot com>\n * All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions are met:\n *\n *   * Redistributions of source code must retain the above copyright notice,\n *     this list of conditions and the following disclaimer.\n *   * Redistributions in binary form must reproduce the above copyright\n *     notice, this list of conditions and the following disclaimer in the\n *     documentation and/or other materials provided with the distribution.\n *   * Neither the name of Redis nor the names of its contributors may be used\n *     to endorse or promote products derived from this software without\n *     specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\"\n * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\n * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE\n * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR\n * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF\n * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS\n * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN\n * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)\n * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE\n * POSSIBILITY OF SUCH DAMAGE.\n */\n\n#include <stdio.h>\n#include <stdlib.h>\n#include <string.h>\n#include \"intset.h\"\n#include \"zmalloc.h\"\n#include \"endianconv.h\"\n\n/* Note that these encodings are ordered, so:\n * INTSET_ENC_INT16 < INTSET_ENC_INT32 < INTSET_ENC_INT64. */\n#define INTSET_ENC_INT16 (sizeof(int16_t))\n#define INTSET_ENC_INT32 (sizeof(int32_t))\n#define INTSET_ENC_INT64 (sizeof(int64_t))\n\n/* Return the required encoding for the provided value. */\nstatic uint8_t _intsetValueEncoding(int64_t v) {\n    if (v < INT32_MIN || v > INT32_MAX)\n        return INTSET_ENC_INT64;\n    else if (v < INT16_MIN || v > INT16_MAX)\n        return INTSET_ENC_INT32;\n    else\n        return INTSET_ENC_INT16;\n}\n\n/* Return the value at pos, given an encoding. */\nstatic int64_t _intsetGetEncoded(intset *is, int pos, uint8_t enc) {\n    int64_t v64;\n    int32_t v32;\n    int16_t v16;\n\n    if (enc == INTSET_ENC_INT64) {\n        memcpy(&v64,((int64_t*)is->contents)+pos,sizeof(v64));\n        memrev64ifbe(&v64);\n        return v64;\n    } else if (enc == INTSET_ENC_INT32) {\n        memcpy(&v32,((int32_t*)is->contents)+pos,sizeof(v32));\n        memrev32ifbe(&v32);\n        return v32;\n    } else {\n        memcpy(&v16,((int16_t*)is->contents)+pos,sizeof(v16));\n        memrev16ifbe(&v16);\n        return v16;\n    }\n}\n\n/* Return the value at pos, using the configured encoding. */\nstatic int64_t _intsetGet(intset *is, int pos) {\n    return _intsetGetEncoded(is,pos,intrev32ifbe(is->encoding));\n}\n\n/* Set the value at pos, using the configured encoding. */\nstatic void _intsetSet(intset *is, int pos, int64_t value) {\n    uint32_t encoding = intrev32ifbe(is->encoding);\n\n    if (encoding == INTSET_ENC_INT64) {\n        ((int64_t*)is->contents)[pos] = value;\n        memrev64ifbe(((int64_t*)is->contents)+pos);\n    } else if (encoding == INTSET_ENC_INT32) {\n        ((int32_t*)is->contents)[pos] = value;\n        memrev32ifbe(((int32_t*)is->contents)+pos);\n    } else {\n        ((int16_t*)is->contents)[pos] = value;\n        memrev16ifbe(((int16_t*)is->contents)+pos);\n    }\n}\n\n/* Create an empty intset. */\nintset *intsetNew(void) {\n    intset *is = zmalloc(sizeof(intset));\n    is->encoding = intrev32ifbe(INTSET_ENC_INT16);\n    is->length = 0;\n    return is;\n}\n\n/* Resize the intset */\nstatic intset *intsetResize(intset *is, uint32_t len) {\n    uint32_t size = len*intrev32ifbe(is->encoding);\n    is = zrealloc(is,sizeof(intset)+size);\n    return is;\n}\n\n/* Search for the position of \"value\". Return 1 when the value was found and\n * sets \"pos\" to the position of the value within the intset. Return 0 when\n * the value is not present in the intset and sets \"pos\" to the position\n * where \"value\" can be inserted. */\nstatic uint8_t intsetSearch(intset *is, int64_t value, uint32_t *pos) {\n    int min = 0, max = intrev32ifbe(is->length)-1, mid = -1;\n    int64_t cur = -1;\n\n    /* The value can never be found when the set is empty */\n    if (intrev32ifbe(is->length) == 0) {\n        if (pos) *pos = 0;\n        return 0;\n    } else {\n        /* Check for the case where we know we cannot find the value,\n         * but do know the insert position. */\n        if (value > _intsetGet(is,intrev32ifbe(is->length)-1)) {\n            if (pos) *pos = intrev32ifbe(is->length);\n            return 0;\n        } else if (value < _intsetGet(is,0)) {\n            if (pos) *pos = 0;\n            return 0;\n        }\n    }\n\n    while(max >= min) {\n        mid = ((unsigned int)min + (unsigned int)max) >> 1;\n        cur = _intsetGet(is,mid);\n        if (value > cur) {\n            min = mid+1;\n        } else if (value < cur) {\n            max = mid-1;\n        } else {\n            break;\n        }\n    }\n\n    if (value == cur) {\n        if (pos) *pos = mid;\n        return 1;\n    } else {\n        if (pos) *pos = min;\n        return 0;\n    }\n}\n\n/* Upgrades the intset to a larger encoding and inserts the given integer. */\nstatic intset *intsetUpgradeAndAdd(intset *is, int64_t value) {\n    uint8_t curenc = intrev32ifbe(is->encoding);\n    uint8_t newenc = _intsetValueEncoding(value);\n    int length = intrev32ifbe(is->length);\n    int prepend = value < 0 ? 1 : 0;\n\n    /* First set new encoding and resize */\n    is->encoding = intrev32ifbe(newenc);\n    is = intsetResize(is,intrev32ifbe(is->length)+1);\n\n    /* Upgrade back-to-front so we don't overwrite values.\n     * Note that the \"prepend\" variable is used to make sure we have an empty\n     * space at either the beginning or the end of the intset. */\n    while(length--)\n        _intsetSet(is,length+prepend,_intsetGetEncoded(is,length,curenc));\n\n    /* Set the value at the beginning or the end. */\n    if (prepend)\n        _intsetSet(is,0,value);\n    else\n        _intsetSet(is,intrev32ifbe(is->length),value);\n    is->length = intrev32ifbe(intrev32ifbe(is->length)+1);\n    return is;\n}\n\nstatic void intsetMoveTail(intset *is, uint32_t from, uint32_t to) {\n    void *src, *dst;\n    uint32_t bytes = intrev32ifbe(is->length)-from;\n    uint32_t encoding = intrev32ifbe(is->encoding);\n\n    if (encoding == INTSET_ENC_INT64) {\n        src = (int64_t*)is->contents+from;\n        dst = (int64_t*)is->contents+to;\n        bytes *= sizeof(int64_t);\n    } else if (encoding == INTSET_ENC_INT32) {\n        src = (int32_t*)is->contents+from;\n        dst = (int32_t*)is->contents+to;\n        bytes *= sizeof(int32_t);\n    } else {\n        src = (int16_t*)is->contents+from;\n        dst = (int16_t*)is->contents+to;\n        bytes *= sizeof(int16_t);\n    }\n    memmove(dst,src,bytes);\n}\n\n/* Insert an integer in the intset */\nintset *intsetAdd(intset *is, int64_t value, uint8_t *success) {\n    uint8_t valenc = _intsetValueEncoding(value);\n    uint32_t pos;\n    if (success) *success = 1;\n\n    /* Upgrade encoding if necessary. If we need to upgrade, we know that\n     * this value should be either appended (if > 0) or prepended (if < 0),\n     * because it lies outside the range of existing values. */\n    if (valenc > intrev32ifbe(is->encoding)) {\n        /* This always succeeds, so we don't need to curry *success. */\n        return intsetUpgradeAndAdd(is,value);\n    } else {\n        /* Abort if the value is already present in the set.\n         * This call will populate \"pos\" with the right position to insert\n         * the value when it cannot be found. */\n        if (intsetSearch(is,value,&pos)) {\n            if (success) *success = 0;\n            return is;\n        }\n\n        is = intsetResize(is,intrev32ifbe(is->length)+1);\n        if (pos < intrev32ifbe(is->length)) intsetMoveTail(is,pos,pos+1);\n    }\n\n    _intsetSet(is,pos,value);\n    is->length = intrev32ifbe(intrev32ifbe(is->length)+1);\n    return is;\n}\n\n/* Delete integer from intset */\nintset *intsetRemove(intset *is, int64_t value, int *success) {\n    uint8_t valenc = _intsetValueEncoding(value);\n    uint32_t pos;\n    if (success) *success = 0;\n\n    if (valenc <= intrev32ifbe(is->encoding) && intsetSearch(is,value,&pos)) {\n        uint32_t len = intrev32ifbe(is->length);\n\n        /* We know we can delete */\n        if (success) *success = 1;\n\n        /* Overwrite value with tail and update length */\n        if (pos < (len-1)) intsetMoveTail(is,pos+1,pos);\n        is = intsetResize(is,len-1);\n        is->length = intrev32ifbe(len-1);\n    }\n    return is;\n}\n\n/* Determine whether a value belongs to this set */\nuint8_t intsetFind(intset *is, int64_t value) {\n    uint8_t valenc = _intsetValueEncoding(value);\n    return valenc <= intrev32ifbe(is->encoding) && intsetSearch(is,value,NULL);\n}\n\n/* Return random member */\nint64_t intsetRandom(intset *is) {\n    return _intsetGet(is,rand()%intrev32ifbe(is->length));\n}\n\n/* Sets the value to the value at the given position. When this position is\n * out of range the function returns 0, when in range it returns 1. */\nuint8_t intsetGet(intset *is, uint32_t pos, int64_t *value) {\n    if (pos < intrev32ifbe(is->length)) {\n        *value = _intsetGet(is,pos);\n        return 1;\n    }\n    return 0;\n}\n\n/* Return intset length */\nuint32_t intsetLen(intset *is) {\n    return intrev32ifbe(is->length);\n}\n\n/* Return intset blob size in bytes. */\nsize_t intsetBlobLen(intset *is) {\n    return sizeof(intset)+intrev32ifbe(is->length)*intrev32ifbe(is->encoding);\n}\n\n#ifdef REDIS_TEST\n#include <sys/time.h>\n#include <time.h>\n\n#if 0\nstatic void intsetRepr(intset *is) {\n    for (uint32_t i = 0; i < intrev32ifbe(is->length); i++) {\n        printf(\"%lld\\n\", (uint64_t)_intsetGet(is,i));\n    }\n    printf(\"\\n\");\n}\n\nstatic void error(char *err) {\n    printf(\"%s\\n\", err);\n    exit(1);\n}\n#endif\n\nstatic void ok(void) {\n    printf(\"OK\\n\");\n}\n\nstatic long long usec(void) {\n    struct timeval tv;\n    gettimeofday(&tv,NULL);\n    return (((long long)tv.tv_sec)*1000000)+tv.tv_usec;\n}\n\n#define assert(_e) ((_e)?(void)0:(_assert(#_e,__FILE__,__LINE__),exit(1)))\nstatic void _assert(char *estr, char *file, int line) {\n    printf(\"\\n\\n=== ASSERTION FAILED ===\\n\");\n    printf(\"==> %s:%d '%s' is not true\\n\",file,line,estr);\n}\n\nstatic intset *createSet(int bits, int size) {\n    uint64_t mask = (1<<bits)-1;\n    uint64_t value;\n    intset *is = intsetNew();\n\n    for (int i = 0; i < size; i++) {\n        if (bits > 32) {\n            value = (rand()*rand()) & mask;\n        } else {\n            value = rand() & mask;\n        }\n        is = intsetAdd(is,value,NULL);\n    }\n    return is;\n}\n\nstatic void checkConsistency(intset *is) {\n    for (uint32_t i = 0; i < (intrev32ifbe(is->length)-1); i++) {\n        uint32_t encoding = intrev32ifbe(is->encoding);\n\n        if (encoding == INTSET_ENC_INT16) {\n            int16_t *i16 = (int16_t*)is->contents;\n            assert(i16[i] < i16[i+1]);\n        } else if (encoding == INTSET_ENC_INT32) {\n            int32_t *i32 = (int32_t*)is->contents;\n            assert(i32[i] < i32[i+1]);\n        } else {\n            int64_t *i64 = (int64_t*)is->contents;\n            assert(i64[i] < i64[i+1]);\n        }\n    }\n}\n\n#define UNUSED(x) (void)(x)\nint intsetTest(int argc, char **argv) {\n    uint8_t success;\n    int i;\n    intset *is;\n    srand(time(NULL));\n\n    UNUSED(argc);\n    UNUSED(argv);\n\n    printf(\"Value encodings: \"); {\n        assert(_intsetValueEncoding(-32768) == INTSET_ENC_INT16);\n        assert(_intsetValueEncoding(+32767) == INTSET_ENC_INT16);\n        assert(_intsetValueEncoding(-32769) == INTSET_ENC_INT32);\n        assert(_intsetValueEncoding(+32768) == INTSET_ENC_INT32);\n        assert(_intsetValueEncoding(-2147483648) == INTSET_ENC_INT32);\n        assert(_intsetValueEncoding(+2147483647) == INTSET_ENC_INT32);\n        assert(_intsetValueEncoding(-2147483649) == INTSET_ENC_INT64);\n        assert(_intsetValueEncoding(+2147483648) == INTSET_ENC_INT64);\n        assert(_intsetValueEncoding(-9223372036854775808ull) ==\n                    INTSET_ENC_INT64);\n        assert(_intsetValueEncoding(+9223372036854775807ull) ==\n                    INTSET_ENC_INT64);\n        ok();\n    }\n\n    printf(\"Basic adding: \"); {\n        is = intsetNew();\n        is = intsetAdd(is,5,&success); assert(success);\n        is = intsetAdd(is,6,&success); assert(success);\n        is = intsetAdd(is,4,&success); assert(success);\n        is = intsetAdd(is,4,&success); assert(!success);\n        ok();\n    }\n\n    printf(\"Large number of random adds: \"); {\n        uint32_t inserts = 0;\n        is = intsetNew();\n        for (i = 0; i < 1024; i++) {\n            is = intsetAdd(is,rand()%0x800,&success);\n            if (success) inserts++;\n        }\n        assert(intrev32ifbe(is->length) == inserts);\n        checkConsistency(is);\n        ok();\n    }\n\n    printf(\"Upgrade from int16 to int32: \"); {\n        is = intsetNew();\n        is = intsetAdd(is,32,NULL);\n        assert(intrev32ifbe(is->encoding) == INTSET_ENC_INT16);\n        is = intsetAdd(is,65535,NULL);\n        assert(intrev32ifbe(is->encoding) == INTSET_ENC_INT32);\n        assert(intsetFind(is,32));\n        assert(intsetFind(is,65535));\n        checkConsistency(is);\n\n        is = intsetNew();\n        is = intsetAdd(is,32,NULL);\n        assert(intrev32ifbe(is->encoding) == INTSET_ENC_INT16);\n        is = intsetAdd(is,-65535,NULL);\n        assert(intrev32ifbe(is->encoding) == INTSET_ENC_INT32);\n        assert(intsetFind(is,32));\n        assert(intsetFind(is,-65535));\n        checkConsistency(is);\n        ok();\n    }\n\n    printf(\"Upgrade from int16 to int64: \"); {\n        is = intsetNew();\n        is = intsetAdd(is,32,NULL);\n        assert(intrev32ifbe(is->encoding) == INTSET_ENC_INT16);\n        is = intsetAdd(is,4294967295,NULL);\n        assert(intrev32ifbe(is->encoding) == INTSET_ENC_INT64);\n        assert(intsetFind(is,32));\n        assert(intsetFind(is,4294967295));\n        checkConsistency(is);\n\n        is = intsetNew();\n        is = intsetAdd(is,32,NULL);\n        assert(intrev32ifbe(is->encoding) == INTSET_ENC_INT16);\n        is = intsetAdd(is,-4294967295,NULL);\n        assert(intrev32ifbe(is->encoding) == INTSET_ENC_INT64);\n        assert(intsetFind(is,32));\n        assert(intsetFind(is,-4294967295));\n        checkConsistency(is);\n        ok();\n    }\n\n    printf(\"Upgrade from int32 to int64: \"); {\n        is = intsetNew();\n        is = intsetAdd(is,65535,NULL);\n        assert(intrev32ifbe(is->encoding) == INTSET_ENC_INT32);\n        is = intsetAdd(is,4294967295,NULL);\n        assert(intrev32ifbe(is->encoding) == INTSET_ENC_INT64);\n        assert(intsetFind(is,65535));\n        assert(intsetFind(is,4294967295));\n        checkConsistency(is);\n\n        is = intsetNew();\n        is = intsetAdd(is,65535,NULL);\n        assert(intrev32ifbe(is->encoding) == INTSET_ENC_INT32);\n        is = intsetAdd(is,-4294967295,NULL);\n        assert(intrev32ifbe(is->encoding) == INTSET_ENC_INT64);\n        assert(intsetFind(is,65535));\n        assert(intsetFind(is,-4294967295));\n        checkConsistency(is);\n        ok();\n    }\n\n    printf(\"Stress lookups: \"); {\n        long num = 100000, size = 10000;\n        int i, bits = 20;\n        long long start;\n        is = createSet(bits,size);\n        checkConsistency(is);\n\n        start = usec();\n        for (i = 0; i < num; i++) intsetSearch(is,rand() % ((1<<bits)-1),NULL);\n        printf(\"%ld lookups, %ld element set, %lldusec\\n\",\n               num,size,usec()-start);\n    }\n\n    printf(\"Stress add+delete: \"); {\n        int i, v1, v2;\n        is = intsetNew();\n        for (i = 0; i < 0xffff; i++) {\n            v1 = rand() % 0xfff;\n            is = intsetAdd(is,v1,NULL);\n            assert(intsetFind(is,v1));\n\n            v2 = rand() % 0xfff;\n            is = intsetRemove(is,v2,NULL);\n            assert(!intsetFind(is,v2));\n        }\n        checkConsistency(is);\n        ok();\n    }\n\n    return 0;\n}\n#endif\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/src/intset.h",
    "content": "/*\n * Copyright (c) 2009-2012, Pieter Noordhuis <pcnoordhuis at gmail dot com>\n * Copyright (c) 2009-2012, Salvatore Sanfilippo <antirez at gmail dot com>\n * All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions are met:\n *\n *   * Redistributions of source code must retain the above copyright notice,\n *     this list of conditions and the following disclaimer.\n *   * Redistributions in binary form must reproduce the above copyright\n *     notice, this list of conditions and the following disclaimer in the\n *     documentation and/or other materials provided with the distribution.\n *   * Neither the name of Redis nor the names of its contributors may be used\n *     to endorse or promote products derived from this software without\n *     specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\"\n * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\n * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE\n * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR\n * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF\n * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS\n * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN\n * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)\n * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE\n * POSSIBILITY OF SUCH DAMAGE.\n */\n\n#ifndef __INTSET_H\n#define __INTSET_H\n#include <stdint.h>\n\ntypedef struct intset {\n    uint32_t encoding;\n    uint32_t length;\n    int8_t contents[];\n} intset;\n\nintset *intsetNew(void);\nintset *intsetAdd(intset *is, int64_t value, uint8_t *success);\nintset *intsetRemove(intset *is, int64_t value, int *success);\nuint8_t intsetFind(intset *is, int64_t value);\nint64_t intsetRandom(intset *is);\nuint8_t intsetGet(intset *is, uint32_t pos, int64_t *value);\nuint32_t intsetLen(intset *is);\nsize_t intsetBlobLen(intset *is);\n\n#ifdef REDIS_TEST\nint intsetTest(int argc, char *argv[]);\n#endif\n\n#endif // __INTSET_H\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/src/latency.c",
    "content": "/* The latency monitor allows to easily observe the sources of latency\n * in a Redis instance using the LATENCY command. Different latency\n * sources are monitored, like disk I/O, execution of commands, fork\n * system call, and so forth.\n *\n * ----------------------------------------------------------------------------\n *\n * Copyright (c) 2014, Salvatore Sanfilippo <antirez at gmail dot com>\n * All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions are met:\n *\n *   * Redistributions of source code must retain the above copyright notice,\n *     this list of conditions and the following disclaimer.\n *   * Redistributions in binary form must reproduce the above copyright\n *     notice, this list of conditions and the following disclaimer in the\n *     documentation and/or other materials provided with the distribution.\n *   * Neither the name of Redis nor the names of its contributors may be used\n *     to endorse or promote products derived from this software without\n *     specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\"\n * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\n * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE\n * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR\n * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF\n * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS\n * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN\n * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)\n * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE\n * POSSIBILITY OF SUCH DAMAGE.\n */\n\n#include \"server.h\"\n\n/* Dictionary type for latency events. */\nint dictStringKeyCompare(void *privdata, const void *key1, const void *key2) {\n    UNUSED(privdata);\n    return strcmp(key1,key2) == 0;\n}\n\nunsigned int dictStringHash(const void *key) {\n    return dictGenHashFunction(key, strlen(key));\n}\n\nvoid dictVanillaFree(void *privdata, void *val);\n\ndictType latencyTimeSeriesDictType = {\n    dictStringHash,             /* hash function */\n    NULL,                       /* key dup */\n    NULL,                       /* val dup */\n    dictStringKeyCompare,       /* key compare */\n    dictVanillaFree,            /* key destructor */\n    dictVanillaFree             /* val destructor */\n};\n\n/* ------------------------- Utility functions ------------------------------ */\n\n#ifdef __linux__\n/* Returns 1 if Transparent Huge Pages support is enabled in the kernel.\n * Otherwise (or if we are unable to check) 0 is returned. */\nint THPIsEnabled(void) {\n    char buf[1024];\n\n    FILE *fp = fopen(\"/sys/kernel/mm/transparent_hugepage/enabled\",\"r\");\n    if (!fp) return 0;\n    if (fgets(buf,sizeof(buf),fp) == NULL) {\n        fclose(fp);\n        return 0;\n    }\n    fclose(fp);\n    return (strstr(buf,\"[never]\") == NULL) ? 1 : 0;\n}\n#endif\n\n/* Report the amount of AnonHugePages in smap, in bytes. If the return\n * value of the function is non-zero, the process is being targeted by\n * THP support, and is likely to have memory usage / latency issues. */\nint THPGetAnonHugePagesSize(void) {\n    return zmalloc_get_smap_bytes_by_field(\"AnonHugePages:\");\n}\n\n/* ---------------------------- Latency API --------------------------------- */\n\n/* Latency monitor initialization. We just need to create the dictionary\n * of time series, each time serie is craeted on demand in order to avoid\n * having a fixed list to maintain. */\nvoid latencyMonitorInit(void) {\n    server.latency_events = dictCreate(&latencyTimeSeriesDictType,NULL);\n}\n\n/* Add the specified sample to the specified time series \"event\".\n * This function is usually called via latencyAddSampleIfNeeded(), that\n * is a macro that only adds the sample if the latency is higher than\n * server.latency_monitor_threshold. */\nvoid latencyAddSample(char *event, mstime_t latency) {\n    struct latencyTimeSeries *ts = dictFetchValue(server.latency_events,event);\n    time_t now = time(NULL);\n    int prev;\n\n    /* Create the time series if it does not exist. */\n    if (ts == NULL) {\n        ts = zmalloc(sizeof(*ts));\n        ts->idx = 0;\n        ts->max = 0;\n        memset(ts->samples,0,sizeof(ts->samples));\n        dictAdd(server.latency_events,zstrdup(event),ts);\n    }\n\n    /* If the previous sample is in the same second, we update our old sample\n     * if this latency is > of the old one, or just return. */\n    prev = (ts->idx + LATENCY_TS_LEN - 1) % LATENCY_TS_LEN;\n    if (ts->samples[prev].time == now) {\n        if (latency > ts->samples[prev].latency)\n            ts->samples[prev].latency = latency;\n        return;\n    }\n\n    ts->samples[ts->idx].time = time(NULL);\n    ts->samples[ts->idx].latency = latency;\n    if (latency > ts->max) ts->max = latency;\n\n    ts->idx++;\n    if (ts->idx == LATENCY_TS_LEN) ts->idx = 0;\n}\n\n/* Reset data for the specified event, or all the events data if 'event' is\n * NULL.\n *\n * Note: this is O(N) even when event_to_reset is not NULL because makes\n * the code simpler and we have a small fixed max number of events. */\nint latencyResetEvent(char *event_to_reset) {\n    dictIterator *di;\n    dictEntry *de;\n    int resets = 0;\n\n    di = dictGetSafeIterator(server.latency_events);\n    while((de = dictNext(di)) != NULL) {\n        char *event = dictGetKey(de);\n\n        if (event_to_reset == NULL || strcasecmp(event,event_to_reset) == 0) {\n            dictDelete(server.latency_events, event);\n            resets++;\n        }\n    }\n    dictReleaseIterator(di);\n    return resets;\n}\n\n/* ------------------------ Latency reporting (doctor) ---------------------- */\n\n/* Analyze the samples avaialble for a given event and return a structure\n * populate with different metrics, average, MAD, min, max, and so forth.\n * Check latency.h definition of struct latenctStat for more info.\n * If the specified event has no elements the structure is populate with\n * zero values. */\nvoid analyzeLatencyForEvent(char *event, struct latencyStats *ls) {\n    struct latencyTimeSeries *ts = dictFetchValue(server.latency_events,event);\n    int j;\n    uint64_t sum;\n\n    ls->all_time_high = ts ? ts->max : 0;\n    ls->avg = 0;\n    ls->min = 0;\n    ls->max = 0;\n    ls->mad = 0;\n    ls->samples = 0;\n    ls->period = 0;\n    if (!ts) return;\n\n    /* First pass, populate everything but the MAD. */\n    sum = 0;\n    for (j = 0; j < LATENCY_TS_LEN; j++) {\n        if (ts->samples[j].time == 0) continue;\n        ls->samples++;\n        if (ls->samples == 1) {\n            ls->min = ls->max = ts->samples[j].latency;\n        } else {\n            if (ls->min > ts->samples[j].latency)\n                ls->min = ts->samples[j].latency;\n            if (ls->max < ts->samples[j].latency)\n                ls->max = ts->samples[j].latency;\n        }\n        sum += ts->samples[j].latency;\n\n        /* Track the oldest event time in ls->period. */\n        if (ls->period == 0 || ts->samples[j].time < ls->period)\n            ls->period = ts->samples[j].time;\n    }\n\n    /* So far avg is actually the sum of the latencies, and period is\n     * the oldest event time. We need to make the first an average and\n     * the second a range of seconds. */\n    if (ls->samples) {\n        ls->avg = sum / ls->samples;\n        ls->period = time(NULL) - ls->period;\n        if (ls->period == 0) ls->period = 1;\n    }\n\n    /* Second pass, compute MAD. */\n    sum = 0;\n    for (j = 0; j < LATENCY_TS_LEN; j++) {\n        int64_t delta;\n\n        if (ts->samples[j].time == 0) continue;\n        delta = (int64_t)ls->avg - ts->samples[j].latency;\n        if (delta < 0) delta = -delta;\n        sum += delta;\n    }\n    if (ls->samples) ls->mad = sum / ls->samples;\n}\n\n/* Create a human readable report of latency events for this Redis instance. */\nsds createLatencyReport(void) {\n    sds report = sdsempty();\n    int advise_better_vm = 0;       /* Better virtual machines. */\n    int advise_slowlog_enabled = 0; /* Enable slowlog. */\n    int advise_slowlog_tuning = 0;  /* Reconfigure slowlog. */\n    int advise_slowlog_inspect = 0; /* Check your slowlog. */\n    int advise_disk_contention = 0; /* Try to lower disk contention. */\n    int advise_scheduler = 0;       /* Intrinsic latency. */\n    int advise_data_writeback = 0;  /* data=writeback. */\n    int advise_no_appendfsync = 0;  /* don't fsync during rewrites. */\n    int advise_local_disk = 0;      /* Avoid remote disks. */\n    int advise_ssd = 0;             /* Use an SSD drive. */\n    int advise_write_load_info = 0; /* Print info about AOF and write load. */\n    int advise_hz = 0;              /* Use higher HZ. */\n    int advise_large_objects = 0;   /* Deletion of large objects. */\n    int advise_mass_eviction = 0;   /* Avoid mass eviction of keys. */\n    int advise_relax_fsync_policy = 0; /* appendfsync always is slow. */\n    int advise_disable_thp = 0;     /* AnonHugePages detected. */\n    int advices = 0;\n\n    /* Return ASAP if the latency engine is disabled and it looks like it\n     * was never enabled so far. */\n    if (dictSize(server.latency_events) == 0 &&\n        server.latency_monitor_threshold == 0)\n    {\n        report = sdscat(report,\"I'm sorry, Dave, I can't do that. Latency monitoring is disabled in this Redis instance. You may use \\\"CONFIG SET latency-monitor-threshold <milliseconds>.\\\" in order to enable it. If we weren't in a deep space mission I'd suggest to take a look at http://redis.io/topics/latency-monitor.\\n\");\n        return report;\n    }\n\n    /* Show all the events stats and add for each event some event-related\n     * comment depending on the values. */\n    dictIterator *di;\n    dictEntry *de;\n    int eventnum = 0;\n\n    di = dictGetSafeIterator(server.latency_events);\n    while((de = dictNext(di)) != NULL) {\n        char *event = dictGetKey(de);\n        struct latencyTimeSeries *ts = dictGetVal(de);\n        struct latencyStats ls;\n\n        if (ts == NULL) continue;\n        eventnum++;\n        if (eventnum == 1) {\n            report = sdscat(report,\"Dave, I have observed latency spikes in this Redis instance. You don't mind talking about it, do you Dave?\\n\\n\");\n        }\n        analyzeLatencyForEvent(event,&ls);\n\n        report = sdscatprintf(report,\n            \"%d. %s: %d latency spikes (average %lums, mean deviation %lums, period %.2f sec). Worst all time event %lums.\",\n            eventnum, event,\n            ls.samples,\n            (unsigned long) ls.avg,\n            (unsigned long) ls.mad,\n            (double) ls.period/ls.samples,\n            (unsigned long) ts->max);\n\n        /* Fork */\n        if (!strcasecmp(event,\"fork\")) {\n            char *fork_quality;\n            if (server.stat_fork_rate < 10) {\n                fork_quality = \"terrible\";\n                advise_better_vm = 1;\n                advices++;\n            } else if (server.stat_fork_rate < 25) {\n                fork_quality = \"poor\";\n                advise_better_vm = 1;\n                advices++;\n            } else if (server.stat_fork_rate < 100) {\n                fork_quality = \"good\";\n            } else {\n                fork_quality = \"excellent\";\n            }\n            report = sdscatprintf(report,\n                \" Fork rate is %.2f GB/sec (%s).\", server.stat_fork_rate,\n                fork_quality);\n        }\n\n        /* Potentially commands. */\n        if (!strcasecmp(event,\"command\")) {\n            if (server.slowlog_log_slower_than == 0) {\n                advise_slowlog_enabled = 1;\n                advices++;\n            } else if (server.slowlog_log_slower_than/1000 >\n                       server.latency_monitor_threshold)\n            {\n                advise_slowlog_tuning = 1;\n                advices++;\n            }\n            advise_slowlog_inspect = 1;\n            advise_large_objects = 1;\n            advices += 2;\n        }\n\n        /* fast-command. */\n        if (!strcasecmp(event,\"fast-command\")) {\n            advise_scheduler = 1;\n            advices++;\n        }\n\n        /* AOF and I/O. */\n        if (!strcasecmp(event,\"aof-write-pending-fsync\")) {\n            advise_local_disk = 1;\n            advise_disk_contention = 1;\n            advise_ssd = 1;\n            advise_data_writeback = 1;\n            advices += 4;\n        }\n\n        if (!strcasecmp(event,\"aof-write-active-child\")) {\n            advise_no_appendfsync = 1;\n            advise_data_writeback = 1;\n            advise_ssd = 1;\n            advices += 3;\n        }\n\n        if (!strcasecmp(event,\"aof-write-alone\")) {\n            advise_local_disk = 1;\n            advise_data_writeback = 1;\n            advise_ssd = 1;\n            advices += 3;\n        }\n\n        if (!strcasecmp(event,\"aof-fsync-always\")) {\n            advise_relax_fsync_policy = 1;\n            advices++;\n        }\n\n        if (!strcasecmp(event,\"aof-fstat\") ||\n            !strcasecmp(event,\"rdb-unlik-temp-file\")) {\n            advise_disk_contention = 1;\n            advise_local_disk = 1;\n            advices += 2;\n        }\n\n        if (!strcasecmp(event,\"aof-rewrite-diff-write\") ||\n            !strcasecmp(event,\"aof-rename\")) {\n            advise_write_load_info = 1;\n            advise_data_writeback = 1;\n            advise_ssd = 1;\n            advise_local_disk = 1;\n            advices += 4;\n        }\n\n        /* Expire cycle. */\n        if (!strcasecmp(event,\"expire-cycle\")) {\n            advise_hz = 1;\n            advise_large_objects = 1;\n            advices += 2;\n        }\n\n        /* Eviction cycle. */\n        if (!strcasecmp(event,\"eviction-del\")) {\n            advise_large_objects = 1;\n            advices++;\n        }\n\n        if (!strcasecmp(event,\"eviction-cycle\")) {\n            advise_mass_eviction = 1;\n            advices++;\n        }\n\n        report = sdscatlen(report,\"\\n\",1);\n    }\n    dictReleaseIterator(di);\n\n    /* Add non event based advices. */\n    if (THPGetAnonHugePagesSize() > 0) {\n        advise_disable_thp = 1;\n        advices++;\n    }\n\n    if (eventnum == 0 && advices == 0) {\n        report = sdscat(report,\"Dave, no latency spike was observed during the lifetime of this Redis instance, not in the slightest bit. I honestly think you ought to sit down calmly, take a stress pill, and think things over.\\n\");\n    } else if (eventnum > 0 && advices == 0) {\n        report = sdscat(report,\"\\nWhile there are latency events logged, I'm not able to suggest any easy fix. Please use the Redis community to get some help, providing this report in your help request.\\n\");\n    } else {\n        /* Add all the suggestions accumulated so far. */\n\n        /* Better VM. */\n        report = sdscat(report,\"\\nI have a few advices for you:\\n\\n\");\n        if (advise_better_vm) {\n            report = sdscat(report,\"- If you are using a virtual machine, consider upgrading it with a faster one using an hypervisior that provides less latency during fork() calls. Xen is known to have poor fork() performance. Even in the context of the same VM provider, certain kinds of instances can execute fork faster than others.\\n\");\n        }\n\n        /* Slow log. */\n        if (advise_slowlog_enabled) {\n            report = sdscatprintf(report,\"- There are latency issues with potentially slow commands you are using. Try to enable the Slow Log Redis feature using the command 'CONFIG SET slowlog-log-slower-than %llu'. If the Slow log is disabled Redis is not able to log slow commands execution for you.\\n\", (unsigned long long)server.latency_monitor_threshold*1000);\n        }\n\n        if (advise_slowlog_tuning) {\n            report = sdscatprintf(report,\"- Your current Slow Log configuration only logs events that are slower than your configured latency monitor threshold. Please use 'CONFIG SET slowlog-log-slower-than %llu'.\\n\", (unsigned long long)server.latency_monitor_threshold*1000);\n        }\n\n        if (advise_slowlog_inspect) {\n            report = sdscat(report,\"- Check your Slow Log to understand what are the commands you are running which are too slow to execute. Please check http://redis.io/commands/slowlog for more information.\\n\");\n        }\n\n        /* Intrinsic latency. */\n        if (advise_scheduler) {\n            report = sdscat(report,\"- The system is slow to execute Redis code paths not containing system calls. This usually means the system does not provide Redis CPU time to run for long periods. You should try to:\\n\"\n            \"  1) Lower the system load.\\n\"\n            \"  2) Use a computer / VM just for Redis if you are running other softawre in the same system.\\n\"\n            \"  3) Check if you have a \\\"noisy neighbour\\\" problem.\\n\"\n            \"  4) Check with 'redis-cli --intrinsic-latency 100' what is the intrinsic latency in your system.\\n\"\n            \"  5) Check if the problem is allocator-related by recompiling Redis with MALLOC=libc, if you are using Jemalloc. However this may create fragmentation problems.\\n\");\n        }\n\n        /* AOF / Disk latency. */\n        if (advise_local_disk) {\n            report = sdscat(report,\"- It is strongly advised to use local disks for persistence, especially if you are using AOF. Remote disks provided by platform-as-a-service providers are known to be slow.\\n\");\n        }\n\n        if (advise_ssd) {\n            report = sdscat(report,\"- SSD disks are able to reduce fsync latency, and total time needed for snapshotting and AOF log rewriting (resulting in smaller memory usage and smaller final AOF rewrite buffer flushes). With extremely high write load SSD disks can be a good option. However Redis should perform reasonably with high load using normal disks. Use this advice as a last resort.\\n\");\n        }\n\n        if (advise_data_writeback) {\n            report = sdscat(report,\"- Mounting ext3/4 filesystems with data=writeback can provide a performance boost compared to data=ordered, however this mode of operation provides less guarantees, and sometimes it can happen that after a hard crash the AOF file will have an half-written command at the end and will require to be repaired before Redis restarts.\\n\");\n        }\n\n        if (advise_disk_contention) {\n            report = sdscat(report,\"- Try to lower the disk contention. This is often caused by other disk intensive processes running in the same computer (including other Redis instances).\\n\");\n        }\n\n        if (advise_no_appendfsync) {\n            report = sdscat(report,\"- Assuming from the point of view of data safety this is viable in your environment, you could try to enable the 'no-appendfsync-on-rewrite' option, so that fsync will not be performed while there is a child rewriting the AOF file or producing an RDB file (the moment where there is high disk contention).\\n\");\n        }\n\n        if (advise_relax_fsync_policy && server.aof_fsync == AOF_FSYNC_ALWAYS) {\n            report = sdscat(report,\"- Your fsync policy is set to 'always'. It is very hard to get good performances with such a setup, if possible try to relax the fsync policy to 'onesec'.\\n\");\n        }\n\n        if (advise_write_load_info) {\n            report = sdscat(report,\"- Latency during the AOF atomic rename operation or when the final difference is flushed to the AOF file at the end of the rewrite, sometimes is caused by very high write load, causing the AOF buffer to get very large. If possible try to send less commands to accomplish the same work, or use Lua scripts to group multiple operations into a single EVALSHA call.\\n\");\n        }\n\n        if (advise_hz && server.hz < 100) {\n            report = sdscat(report,\"- In order to make the Redis keys expiring process more incremental, try to set the 'hz' configuration parameter to 100 using 'CONFIG SET hz 100'.\\n\");\n        }\n\n        if (advise_large_objects) {\n            report = sdscat(report,\"- Deleting, expiring or evicting (because of maxmemory policy) large objects is a blocking operation. If you have very large objects that are often deleted, expired, or evicted, try to fragment those objects into multiple smaller objects.\\n\");\n        }\n\n        if (advise_mass_eviction) {\n            report = sdscat(report,\"- Sudden changes to the 'maxmemory' setting via 'CONFIG SET', or allocation of large objects via sets or sorted sets intersections, STORE option of SORT, Redis Cluster large keys migrations (RESTORE command), may create sudden memory pressure forcing the server to block trying to evict keys. \\n\");\n        }\n\n        if (advise_disable_thp) {\n            report = sdscat(report,\"- I detected a non zero amount of anonymous huge pages used by your process. This creates very serious latency events in different conditions, especially when Redis is persisting on disk. To disable THP support use the command 'echo never > /sys/kernel/mm/transparent_hugepage/enabled', make sure to also add it into /etc/rc.local so that the command will be executed again after a reboot. Note that even if you have already disabled THP, you still need to restart the Redis process to get rid of the huge pages already created.\\n\");\n        }\n    }\n\n    return report;\n}\n\n/* ---------------------- Latency command implementation -------------------- */\n\n/* latencyCommand() helper to produce a time-delay reply for all the samples\n * in memory for the specified time series. */\nvoid latencyCommandReplyWithSamples(client *c, struct latencyTimeSeries *ts) {\n    void *replylen = addDeferredMultiBulkLength(c);\n    int samples = 0, j;\n\n    for (j = 0; j < LATENCY_TS_LEN; j++) {\n        int i = (ts->idx + j) % LATENCY_TS_LEN;\n\n        if (ts->samples[i].time == 0) continue;\n        addReplyMultiBulkLen(c,2);\n        addReplyLongLong(c,ts->samples[i].time);\n        addReplyLongLong(c,ts->samples[i].latency);\n        samples++;\n    }\n    setDeferredMultiBulkLength(c,replylen,samples);\n}\n\n/* latencyCommand() helper to produce the reply for the LATEST subcommand,\n * listing the last latency sample for every event type registered so far. */\nvoid latencyCommandReplyWithLatestEvents(client *c) {\n    dictIterator *di;\n    dictEntry *de;\n\n    addReplyMultiBulkLen(c,dictSize(server.latency_events));\n    di = dictGetIterator(server.latency_events);\n    while((de = dictNext(di)) != NULL) {\n        char *event = dictGetKey(de);\n        struct latencyTimeSeries *ts = dictGetVal(de);\n        int last = (ts->idx + LATENCY_TS_LEN - 1) % LATENCY_TS_LEN;\n\n        addReplyMultiBulkLen(c,4);\n        addReplyBulkCString(c,event);\n        addReplyLongLong(c,ts->samples[last].time);\n        addReplyLongLong(c,ts->samples[last].latency);\n        addReplyLongLong(c,ts->max);\n    }\n    dictReleaseIterator(di);\n}\n\n#define LATENCY_GRAPH_COLS 80\nsds latencyCommandGenSparkeline(char *event, struct latencyTimeSeries *ts) {\n    int j;\n    struct sequence *seq = createSparklineSequence();\n    sds graph = sdsempty();\n    uint32_t min = 0, max = 0;\n\n    for (j = 0; j < LATENCY_TS_LEN; j++) {\n        int i = (ts->idx + j) % LATENCY_TS_LEN;\n        int elapsed;\n        char buf[64];\n\n        if (ts->samples[i].time == 0) continue;\n        /* Update min and max. */\n        if (seq->length == 0) {\n            min = max = ts->samples[i].latency;\n        } else {\n            if (ts->samples[i].latency > max) max = ts->samples[i].latency;\n            if (ts->samples[i].latency < min) min = ts->samples[i].latency;\n        }\n        /* Use as label the number of seconds / minutes / hours / days\n         * ago the event happened. */\n        elapsed = time(NULL) - ts->samples[i].time;\n        if (elapsed < 60)\n            snprintf(buf,sizeof(buf),\"%ds\",elapsed);\n        else if (elapsed < 3600)\n            snprintf(buf,sizeof(buf),\"%dm\",elapsed/60);\n        else if (elapsed < 3600*24)\n            snprintf(buf,sizeof(buf),\"%dh\",elapsed/3600);\n        else\n            snprintf(buf,sizeof(buf),\"%dd\",elapsed/(3600*24));\n        sparklineSequenceAddSample(seq,ts->samples[i].latency,buf);\n    }\n\n    graph = sdscatprintf(graph,\n        \"%s - high %lu ms, low %lu ms (all time high %lu ms)\\n\", event,\n        (unsigned long) max, (unsigned long) min, (unsigned long) ts->max);\n    for (j = 0; j < LATENCY_GRAPH_COLS; j++)\n        graph = sdscatlen(graph,\"-\",1);\n    graph = sdscatlen(graph,\"\\n\",1);\n    graph = sparklineRender(graph,seq,LATENCY_GRAPH_COLS,4,SPARKLINE_FILL);\n    freeSparklineSequence(seq);\n    return graph;\n}\n\n/* LATENCY command implementations.\n *\n * LATENCY SAMPLES: return time-latency samples for the specified event.\n * LATENCY LATEST: return the latest latency for all the events classes.\n * LATENCY DOCTOR: returns an human readable analysis of instance latency.\n * LATENCY GRAPH: provide an ASCII graph of the latency of the specified event.\n */\nvoid latencyCommand(client *c) {\n    struct latencyTimeSeries *ts;\n\n    if (!strcasecmp(c->argv[1]->ptr,\"history\") && c->argc == 3) {\n        /* LATENCY HISTORY <event> */\n        ts = dictFetchValue(server.latency_events,c->argv[2]->ptr);\n        if (ts == NULL) {\n            addReplyMultiBulkLen(c,0);\n        } else {\n            latencyCommandReplyWithSamples(c,ts);\n        }\n    } else if (!strcasecmp(c->argv[1]->ptr,\"graph\") && c->argc == 3) {\n        /* LATENCY GRAPH <event> */\n        sds graph;\n        dictEntry *de;\n        char *event;\n\n        de = dictFind(server.latency_events,c->argv[2]->ptr);\n        if (de == NULL) goto nodataerr;\n        ts = dictGetVal(de);\n        event = dictGetKey(de);\n\n        graph = latencyCommandGenSparkeline(event,ts);\n        addReplyBulkCString(c,graph);\n        sdsfree(graph);\n    } else if (!strcasecmp(c->argv[1]->ptr,\"latest\") && c->argc == 2) {\n        /* LATENCY LATEST */\n        latencyCommandReplyWithLatestEvents(c);\n    } else if (!strcasecmp(c->argv[1]->ptr,\"doctor\") && c->argc == 2) {\n        /* LATENCY DOCTOR */\n        sds report = createLatencyReport();\n\n        addReplyBulkCBuffer(c,report,sdslen(report));\n        sdsfree(report);\n    } else if (!strcasecmp(c->argv[1]->ptr,\"reset\") && c->argc >= 2) {\n        /* LATENCY RESET */\n        if (c->argc == 2) {\n            addReplyLongLong(c,latencyResetEvent(NULL));\n        } else {\n            int j, resets = 0;\n\n            for (j = 2; j < c->argc; j++)\n                resets += latencyResetEvent(c->argv[j]->ptr);\n            addReplyLongLong(c,resets);\n        }\n    } else {\n        addReply(c,shared.syntaxerr);\n    }\n    return;\n\nnodataerr:\n    /* Common error when the user asks for an event we have no latency\n     * information about. */\n    addReplyErrorFormat(c,\n        \"No samples available for event '%s'\", (char*) c->argv[2]->ptr);\n}\n\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/src/latency.h",
    "content": "/* latency.h -- latency monitor API header file\n * See latency.c for more information.\n *\n * ----------------------------------------------------------------------------\n *\n * Copyright (c) 2014, Salvatore Sanfilippo <antirez at gmail dot com>\n * All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions are met:\n *\n *   * Redistributions of source code must retain the above copyright notice,\n *     this list of conditions and the following disclaimer.\n *   * Redistributions in binary form must reproduce the above copyright\n *     notice, this list of conditions and the following disclaimer in the\n *     documentation and/or other materials provided with the distribution.\n *   * Neither the name of Redis nor the names of its contributors may be used\n *     to endorse or promote products derived from this software without\n *     specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\"\n * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\n * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE\n * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR\n * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF\n * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS\n * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN\n * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)\n * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE\n * POSSIBILITY OF SUCH DAMAGE.\n */\n\n#ifndef __LATENCY_H\n#define __LATENCY_H\n\n#define LATENCY_TS_LEN 160 /* History length for every monitored event. */\n\n/* Representation of a latency sample: the sampling time and the latency\n * observed in milliseconds. */\nstruct latencySample {\n    int32_t time; /* We don't use time_t to force 4 bytes usage everywhere. */\n    uint32_t latency; /* Latency in milliseconds. */\n};\n\n/* The latency time series for a given event. */\nstruct latencyTimeSeries {\n    int idx; /* Index of the next sample to store. */\n    uint32_t max; /* Max latency observed for this event. */\n    struct latencySample samples[LATENCY_TS_LEN]; /* Latest history. */\n};\n\n/* Latency statistics structure. */\nstruct latencyStats {\n    uint32_t all_time_high; /* Absolute max observed since latest reset. */\n    uint32_t avg;           /* Average of current samples. */\n    uint32_t min;           /* Min of current samples. */\n    uint32_t max;           /* Max of current samples. */\n    uint32_t mad;           /* Mean absolute deviation. */\n    uint32_t samples;       /* Number of non-zero samples. */\n    time_t period;          /* Number of seconds since first event and now. */\n};\n\nvoid latencyMonitorInit(void);\nvoid latencyAddSample(char *event, mstime_t latency);\nint THPIsEnabled(void);\n\n/* Latency monitoring macros. */\n\n/* Start monitoring an event. We just set the current time. */\n#define latencyStartMonitor(var) if (server.latency_monitor_threshold) { \\\n    var = mstime(); \\\n} else { \\\n    var = 0; \\\n}\n\n/* End monitoring an event, compute the difference with the current time\n * to check the amount of time elapsed. */\n#define latencyEndMonitor(var) if (server.latency_monitor_threshold) { \\\n    var = mstime() - var; \\\n}\n\n/* Add the sample only if the elapsed time is >= to the configured threshold. */\n#define latencyAddSampleIfNeeded(event,var) \\\n    if (server.latency_monitor_threshold && \\\n        (var) >= server.latency_monitor_threshold) \\\n          latencyAddSample((event),(var));\n\n/* Remove time from a nested event. */\n#define latencyRemoveNestedEvent(event_var,nested_var) \\\n    event_var += nested_var;\n\n#endif /* __LATENCY_H */\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/src/lzf.h",
    "content": "/*\n * Copyright (c) 2000-2008 Marc Alexander Lehmann <schmorp@schmorp.de>\n *\n * Redistribution and use in source and binary forms, with or without modifica-\n * tion, are permitted provided that the following conditions are met:\n *\n *   1.  Redistributions of source code must retain the above copyright notice,\n *       this list of conditions and the following disclaimer.\n *\n *   2.  Redistributions in binary form must reproduce the above copyright\n *       notice, this list of conditions and the following disclaimer in the\n *       documentation and/or other materials provided with the distribution.\n *\n * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED\n * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MER-\n * CHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO\n * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPE-\n * CIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,\n * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;\n * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,\n * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTH-\n * ERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED\n * OF THE POSSIBILITY OF SUCH DAMAGE.\n *\n * Alternatively, the contents of this file may be used under the terms of\n * the GNU General Public License (\"GPL\") version 2 or any later version,\n * in which case the provisions of the GPL are applicable instead of\n * the above. If you wish to allow the use of your version of this file\n * only under the terms of the GPL and not to allow others to use your\n * version of this file under the BSD license, indicate your decision\n * by deleting the provisions above and replace them with the notice\n * and other provisions required by the GPL. If you do not delete the\n * provisions above, a recipient may use your version of this file under\n * either the BSD or the GPL.\n */\n\n#ifndef LZF_H\n#define LZF_H\n\n/***********************************************************************\n**\n**\tlzf -- an extremely fast/free compression/decompression-method\n**\thttp://liblzf.plan9.de/\n**\n**\tThis algorithm is believed to be patent-free.\n**\n***********************************************************************/\n\n#define LZF_VERSION 0x0105 /* 1.5, API version */\n\n/*\n * Compress in_len bytes stored at the memory block starting at\n * in_data and write the result to out_data, up to a maximum length\n * of out_len bytes.\n *\n * If the output buffer is not large enough or any error occurs return 0,\n * otherwise return the number of bytes used, which might be considerably\n * more than in_len (but less than 104% of the original size), so it\n * makes sense to always use out_len == in_len - 1), to ensure _some_\n * compression, and store the data uncompressed otherwise (with a flag, of\n * course.\n *\n * lzf_compress might use different algorithms on different systems and\n * even different runs, thus might result in different compressed strings\n * depending on the phase of the moon or similar factors. However, all\n * these strings are architecture-independent and will result in the\n * original data when decompressed using lzf_decompress.\n *\n * The buffers must not be overlapping.\n *\n * If the option LZF_STATE_ARG is enabled, an extra argument must be\n * supplied which is not reflected in this header file. Refer to lzfP.h\n * and lzf_c.c.\n *\n */\nunsigned int\nlzf_compress (const void *const in_data,  unsigned int in_len,\n              void             *out_data, unsigned int out_len);\n\n/*\n * Decompress data compressed with some version of the lzf_compress\n * function and stored at location in_data and length in_len. The result\n * will be stored at out_data up to a maximum of out_len characters.\n *\n * If the output buffer is not large enough to hold the decompressed\n * data, a 0 is returned and errno is set to E2BIG. Otherwise the number\n * of decompressed bytes (i.e. the original length of the data) is\n * returned.\n *\n * If an error in the compressed data is detected, a zero is returned and\n * errno is set to EINVAL.\n *\n * This function is very fast, about as fast as a copying loop.\n */\nunsigned int\nlzf_decompress (const void *const in_data,  unsigned int in_len,\n                void             *out_data, unsigned int out_len);\n\n#endif\n\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/src/lzfP.h",
    "content": "/*\n * Copyright (c) 2000-2007 Marc Alexander Lehmann <schmorp@schmorp.de>\n *\n * Redistribution and use in source and binary forms, with or without modifica-\n * tion, are permitted provided that the following conditions are met:\n *\n *   1.  Redistributions of source code must retain the above copyright notice,\n *       this list of conditions and the following disclaimer.\n *\n *   2.  Redistributions in binary form must reproduce the above copyright\n *       notice, this list of conditions and the following disclaimer in the\n *       documentation and/or other materials provided with the distribution.\n *\n * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED\n * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MER-\n * CHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO\n * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPE-\n * CIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,\n * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;\n * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,\n * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTH-\n * ERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED\n * OF THE POSSIBILITY OF SUCH DAMAGE.\n *\n * Alternatively, the contents of this file may be used under the terms of\n * the GNU General Public License (\"GPL\") version 2 or any later version,\n * in which case the provisions of the GPL are applicable instead of\n * the above. If you wish to allow the use of your version of this file\n * only under the terms of the GPL and not to allow others to use your\n * version of this file under the BSD license, indicate your decision\n * by deleting the provisions above and replace them with the notice\n * and other provisions required by the GPL. If you do not delete the\n * provisions above, a recipient may use your version of this file under\n * either the BSD or the GPL.\n */\n\n#ifndef LZFP_h\n#define LZFP_h\n\n#define STANDALONE 1 /* at the moment, this is ok. */\n\n#ifndef STANDALONE\n# include \"lzf.h\"\n#endif\n\n/*\n * Size of hashtable is (1 << HLOG) * sizeof (char *)\n * decompression is independent of the hash table size\n * the difference between 15 and 14 is very small\n * for small blocks (and 14 is usually a bit faster).\n * For a low-memory/faster configuration, use HLOG == 13;\n * For best compression, use 15 or 16 (or more, up to 22).\n */\n#ifndef HLOG\n# define HLOG 16\n#endif\n\n/*\n * Sacrifice very little compression quality in favour of compression speed.\n * This gives almost the same compression as the default code, and is\n * (very roughly) 15% faster. This is the preferred mode of operation.\n */\n#ifndef VERY_FAST\n# define VERY_FAST 1\n#endif\n\n/*\n * Sacrifice some more compression quality in favour of compression speed.\n * (roughly 1-2% worse compression for large blocks and\n * 9-10% for small, redundant, blocks and >>20% better speed in both cases)\n * In short: when in need for speed, enable this for binary data,\n * possibly disable this for text data.\n */\n#ifndef ULTRA_FAST\n# define ULTRA_FAST 0\n#endif\n\n/*\n * Unconditionally aligning does not cost very much, so do it if unsure\n */\n#ifndef STRICT_ALIGN\n# define STRICT_ALIGN !(defined(__i386) || defined (__amd64))\n#endif\n\n/*\n * You may choose to pre-set the hash table (might be faster on some\n * modern cpus and large (>>64k) blocks, and also makes compression\n * deterministic/repeatable when the configuration otherwise is the same).\n */\n#ifndef INIT_HTAB\n# define INIT_HTAB 0\n#endif\n\n/*\n * Avoid assigning values to errno variable? for some embedding purposes\n * (linux kernel for example), this is necessary. NOTE: this breaks\n * the documentation in lzf.h. Avoiding errno has no speed impact.\n */\n#ifndef AVOID_ERRNO\n# define AVOID_ERRNO 0\n#endif\n\n/*\n * Whether to pass the LZF_STATE variable as argument, or allocate it\n * on the stack. For small-stack environments, define this to 1.\n * NOTE: this breaks the prototype in lzf.h.\n */\n#ifndef LZF_STATE_ARG\n# define LZF_STATE_ARG 0\n#endif\n\n/*\n * Whether to add extra checks for input validity in lzf_decompress\n * and return EINVAL if the input stream has been corrupted. This\n * only shields against overflowing the input buffer and will not\n * detect most corrupted streams.\n * This check is not normally noticeable on modern hardware\n * (<1% slowdown), but might slow down older cpus considerably.\n */\n#ifndef CHECK_INPUT\n# define CHECK_INPUT 1\n#endif\n\n/*\n * Whether to store pointers or offsets inside the hash table. On\n * 64 bit architetcures, pointers take up twice as much space,\n * and might also be slower. Default is to autodetect.\n */\n/*#define LZF_USER_OFFSETS autodetect */\n\n/*****************************************************************************/\n/* nothing should be changed below */\n\n#ifdef __cplusplus\n# include <cstring>\n# include <climits>\nusing namespace std;\n#else\n# include <string.h>\n# include <limits.h>\n#endif\n\n#ifndef LZF_USE_OFFSETS\n# if defined (WIN32)\n#  define LZF_USE_OFFSETS defined(_M_X64)\n# else\n#  if __cplusplus > 199711L\n#   include <cstdint>\n#  else\n#   include <stdint.h>\n#  endif\n#  define LZF_USE_OFFSETS (UINTPTR_MAX > 0xffffffffU)\n# endif\n#endif\n\ntypedef unsigned char u8;\n\n#if LZF_USE_OFFSETS\n# define LZF_HSLOT_BIAS ((const u8 *)in_data)\n  typedef unsigned int LZF_HSLOT;\n#else\n# define LZF_HSLOT_BIAS 0\n  typedef const u8 *LZF_HSLOT;\n#endif\n\ntypedef LZF_HSLOT LZF_STATE[1 << (HLOG)];\n\n#if !STRICT_ALIGN\n/* for unaligned accesses we need a 16 bit datatype. */\n# if USHRT_MAX == 65535\n    typedef unsigned short u16;\n# elif UINT_MAX == 65535\n    typedef unsigned int u16;\n# else\n#  undef STRICT_ALIGN\n#  define STRICT_ALIGN 1\n# endif\n#endif\n\n#if ULTRA_FAST\n# undef VERY_FAST\n#endif\n\n#endif\n\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/src/lzf_c.c",
    "content": "/*\n * Copyright (c) 2000-2010 Marc Alexander Lehmann <schmorp@schmorp.de>\n *\n * Redistribution and use in source and binary forms, with or without modifica-\n * tion, are permitted provided that the following conditions are met:\n *\n *   1.  Redistributions of source code must retain the above copyright notice,\n *       this list of conditions and the following disclaimer.\n *\n *   2.  Redistributions in binary form must reproduce the above copyright\n *       notice, this list of conditions and the following disclaimer in the\n *       documentation and/or other materials provided with the distribution.\n *\n * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED\n * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MER-\n * CHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO\n * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPE-\n * CIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,\n * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;\n * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,\n * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTH-\n * ERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED\n * OF THE POSSIBILITY OF SUCH DAMAGE.\n *\n * Alternatively, the contents of this file may be used under the terms of\n * the GNU General Public License (\"GPL\") version 2 or any later version,\n * in which case the provisions of the GPL are applicable instead of\n * the above. If you wish to allow the use of your version of this file\n * only under the terms of the GPL and not to allow others to use your\n * version of this file under the BSD license, indicate your decision\n * by deleting the provisions above and replace them with the notice\n * and other provisions required by the GPL. If you do not delete the\n * provisions above, a recipient may use your version of this file under\n * either the BSD or the GPL.\n */\n\n#include \"lzfP.h\"\n\n#define HSIZE (1 << (HLOG))\n\n/*\n * don't play with this unless you benchmark!\n * the data format is not dependent on the hash function.\n * the hash function might seem strange, just believe me,\n * it works ;)\n */\n#ifndef FRST\n# define FRST(p) (((p[0]) << 8) | p[1])\n# define NEXT(v,p) (((v) << 8) | p[2])\n# if ULTRA_FAST\n#  define IDX(h) ((( h             >> (3*8 - HLOG)) - h  ) & (HSIZE - 1))\n# elif VERY_FAST\n#  define IDX(h) ((( h             >> (3*8 - HLOG)) - h*5) & (HSIZE - 1))\n# else\n#  define IDX(h) ((((h ^ (h << 5)) >> (3*8 - HLOG)) - h*5) & (HSIZE - 1))\n# endif\n#endif\n/*\n * IDX works because it is very similar to a multiplicative hash, e.g.\n * ((h * 57321 >> (3*8 - HLOG)) & (HSIZE - 1))\n * the latter is also quite fast on newer CPUs, and compresses similarly.\n *\n * the next one is also quite good, albeit slow ;)\n * (int)(cos(h & 0xffffff) * 1e6)\n */\n\n#if 0\n/* original lzv-like hash function, much worse and thus slower */\n# define FRST(p) (p[0] << 5) ^ p[1]\n# define NEXT(v,p) ((v) << 5) ^ p[2]\n# define IDX(h) ((h) & (HSIZE - 1))\n#endif\n\n#define        MAX_LIT        (1 <<  5)\n#define        MAX_OFF        (1 << 13)\n#define        MAX_REF        ((1 << 8) + (1 << 3))\n\n#if __GNUC__ >= 3\n# define expect(expr,value)         __builtin_expect ((expr),(value))\n# define inline                     inline\n#else\n# define expect(expr,value)         (expr)\n# define inline                     static\n#endif\n\n#define expect_false(expr) expect ((expr) != 0, 0)\n#define expect_true(expr)  expect ((expr) != 0, 1)\n\n/*\n * compressed format\n *\n * 000LLLLL <L+1>    ; literal, L+1=1..33 octets\n * LLLooooo oooooooo ; backref L+1=1..7 octets, o+1=1..4096 offset\n * 111ooooo LLLLLLLL oooooooo ; backref L+8 octets, o+1=1..4096 offset\n *\n */\n\nunsigned int\nlzf_compress (const void *const in_data, unsigned int in_len,\n\t      void *out_data, unsigned int out_len\n#if LZF_STATE_ARG\n              , LZF_STATE htab\n#endif\n              )\n{\n#if !LZF_STATE_ARG\n  LZF_STATE htab;\n#endif\n  const u8 *ip = (const u8 *)in_data;\n        u8 *op = (u8 *)out_data;\n  const u8 *in_end  = ip + in_len;\n        u8 *out_end = op + out_len;\n  const u8 *ref;\n\n  /* off requires a type wide enough to hold a general pointer difference.\n   * ISO C doesn't have that (size_t might not be enough and ptrdiff_t only\n   * works for differences within a single object). We also assume that no\n   * no bit pattern traps. Since the only platform that is both non-POSIX\n   * and fails to support both assumptions is windows 64 bit, we make a\n   * special workaround for it.\n   */\n#if defined (WIN32) && defined (_M_X64)\n  unsigned _int64 off; /* workaround for missing POSIX compliance */\n#else\n  unsigned long off;\n#endif\n  unsigned int hval;\n  int lit;\n\n  if (!in_len || !out_len)\n    return 0;\n\n#if INIT_HTAB\n  memset (htab, 0, sizeof (htab));\n#endif\n\n  lit = 0; op++; /* start run */\n\n  hval = FRST (ip);\n  while (ip < in_end - 2)\n    {\n      LZF_HSLOT *hslot;\n\n      hval = NEXT (hval, ip);\n      hslot = htab + IDX (hval);\n      ref = *hslot + LZF_HSLOT_BIAS; *hslot = ip - LZF_HSLOT_BIAS;\n\n      if (1\n#if INIT_HTAB\n          && ref < ip /* the next test will actually take care of this, but this is faster */\n#endif\n          && (off = ip - ref - 1) < MAX_OFF\n          && ref > (u8 *)in_data\n          && ref[2] == ip[2]\n#if STRICT_ALIGN\n          && ((ref[1] << 8) | ref[0]) == ((ip[1] << 8) | ip[0])\n#else\n          && *(u16 *)ref == *(u16 *)ip\n#endif\n        )\n        {\n          /* match found at *ref++ */\n          unsigned int len = 2;\n          unsigned int maxlen = in_end - ip - len;\n          maxlen = maxlen > MAX_REF ? MAX_REF : maxlen;\n\n          if (expect_false (op + 3 + 1 >= out_end)) /* first a faster conservative test */\n            if (op - !lit + 3 + 1 >= out_end) /* second the exact but rare test */\n              return 0;\n\n          op [- lit - 1] = lit - 1; /* stop run */\n          op -= !lit; /* undo run if length is zero */\n\n          for (;;)\n            {\n              if (expect_true (maxlen > 16))\n                {\n                  len++; if (ref [len] != ip [len]) break;\n                  len++; if (ref [len] != ip [len]) break;\n                  len++; if (ref [len] != ip [len]) break;\n                  len++; if (ref [len] != ip [len]) break;\n\n                  len++; if (ref [len] != ip [len]) break;\n                  len++; if (ref [len] != ip [len]) break;\n                  len++; if (ref [len] != ip [len]) break;\n                  len++; if (ref [len] != ip [len]) break;\n\n                  len++; if (ref [len] != ip [len]) break;\n                  len++; if (ref [len] != ip [len]) break;\n                  len++; if (ref [len] != ip [len]) break;\n                  len++; if (ref [len] != ip [len]) break;\n\n                  len++; if (ref [len] != ip [len]) break;\n                  len++; if (ref [len] != ip [len]) break;\n                  len++; if (ref [len] != ip [len]) break;\n                  len++; if (ref [len] != ip [len]) break;\n                }\n\n              do\n                len++;\n              while (len < maxlen && ref[len] == ip[len]);\n\n              break;\n            }\n\n          len -= 2; /* len is now #octets - 1 */\n          ip++;\n\n          if (len < 7)\n            {\n              *op++ = (off >> 8) + (len << 5);\n            }\n          else\n            {\n              *op++ = (off >> 8) + (  7 << 5);\n              *op++ = len - 7;\n            }\n\n          *op++ = off;\n\n          lit = 0; op++; /* start run */\n\n          ip += len + 1;\n\n          if (expect_false (ip >= in_end - 2))\n            break;\n\n#if ULTRA_FAST || VERY_FAST\n          --ip;\n# if VERY_FAST && !ULTRA_FAST\n          --ip;\n# endif\n          hval = FRST (ip);\n\n          hval = NEXT (hval, ip);\n          htab[IDX (hval)] = ip - LZF_HSLOT_BIAS;\n          ip++;\n\n# if VERY_FAST && !ULTRA_FAST\n          hval = NEXT (hval, ip);\n          htab[IDX (hval)] = ip - LZF_HSLOT_BIAS;\n          ip++;\n# endif\n#else\n          ip -= len + 1;\n\n          do\n            {\n              hval = NEXT (hval, ip);\n              htab[IDX (hval)] = ip - LZF_HSLOT_BIAS;\n              ip++;\n            }\n          while (len--);\n#endif\n        }\n      else\n        {\n          /* one more literal byte we must copy */\n          if (expect_false (op >= out_end))\n            return 0;\n\n          lit++; *op++ = *ip++;\n\n          if (expect_false (lit == MAX_LIT))\n            {\n              op [- lit - 1] = lit - 1; /* stop run */\n              lit = 0; op++; /* start run */\n            }\n        }\n    }\n\n  if (op + 3 > out_end) /* at most 3 bytes can be missing here */\n    return 0;\n\n  while (ip < in_end)\n    {\n      lit++; *op++ = *ip++;\n\n      if (expect_false (lit == MAX_LIT))\n        {\n          op [- lit - 1] = lit - 1; /* stop run */\n          lit = 0; op++; /* start run */\n        }\n    }\n\n  op [- lit - 1] = lit - 1; /* end run */\n  op -= !lit; /* undo run if length is zero */\n\n  return op - (u8 *)out_data;\n}\n\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/src/lzf_d.c",
    "content": "/*\n * Copyright (c) 2000-2010 Marc Alexander Lehmann <schmorp@schmorp.de>\n *\n * Redistribution and use in source and binary forms, with or without modifica-\n * tion, are permitted provided that the following conditions are met:\n *\n *   1.  Redistributions of source code must retain the above copyright notice,\n *       this list of conditions and the following disclaimer.\n *\n *   2.  Redistributions in binary form must reproduce the above copyright\n *       notice, this list of conditions and the following disclaimer in the\n *       documentation and/or other materials provided with the distribution.\n *\n * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED\n * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MER-\n * CHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO\n * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPE-\n * CIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,\n * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;\n * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,\n * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTH-\n * ERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED\n * OF THE POSSIBILITY OF SUCH DAMAGE.\n *\n * Alternatively, the contents of this file may be used under the terms of\n * the GNU General Public License (\"GPL\") version 2 or any later version,\n * in which case the provisions of the GPL are applicable instead of\n * the above. If you wish to allow the use of your version of this file\n * only under the terms of the GPL and not to allow others to use your\n * version of this file under the BSD license, indicate your decision\n * by deleting the provisions above and replace them with the notice\n * and other provisions required by the GPL. If you do not delete the\n * provisions above, a recipient may use your version of this file under\n * either the BSD or the GPL.\n */\n\n#include \"lzfP.h\"\n\n#if AVOID_ERRNO\n# define SET_ERRNO(n)\n#else\n# include <errno.h>\n# define SET_ERRNO(n) errno = (n)\n#endif\n\n#if USE_REP_MOVSB /* small win on amd, big loss on intel */\n#if (__i386 || __amd64) && __GNUC__ >= 3\n# define lzf_movsb(dst, src, len)                \\\n   asm (\"rep movsb\"                              \\\n        : \"=D\" (dst), \"=S\" (src), \"=c\" (len)     \\\n        :  \"0\" (dst),  \"1\" (src),  \"2\" (len));\n#endif\n#endif\n\nunsigned int\nlzf_decompress (const void *const in_data,  unsigned int in_len,\n                void             *out_data, unsigned int out_len)\n{\n  u8 const *ip = (const u8 *)in_data;\n  u8       *op = (u8 *)out_data;\n  u8 const *const in_end  = ip + in_len;\n  u8       *const out_end = op + out_len;\n\n  do\n    {\n      unsigned int ctrl = *ip++;\n\n      if (ctrl < (1 << 5)) /* literal run */\n        {\n          ctrl++;\n\n          if (op + ctrl > out_end)\n            {\n              SET_ERRNO (E2BIG);\n              return 0;\n            }\n\n#if CHECK_INPUT\n          if (ip + ctrl > in_end)\n            {\n              SET_ERRNO (EINVAL);\n              return 0;\n            }\n#endif\n\n#ifdef lzf_movsb\n          lzf_movsb (op, ip, ctrl);\n#else\n          switch (ctrl)\n            {\n              case 32: *op++ = *ip++; case 31: *op++ = *ip++; case 30: *op++ = *ip++; case 29: *op++ = *ip++;\n              case 28: *op++ = *ip++; case 27: *op++ = *ip++; case 26: *op++ = *ip++; case 25: *op++ = *ip++;\n              case 24: *op++ = *ip++; case 23: *op++ = *ip++; case 22: *op++ = *ip++; case 21: *op++ = *ip++;\n              case 20: *op++ = *ip++; case 19: *op++ = *ip++; case 18: *op++ = *ip++; case 17: *op++ = *ip++;\n              case 16: *op++ = *ip++; case 15: *op++ = *ip++; case 14: *op++ = *ip++; case 13: *op++ = *ip++;\n              case 12: *op++ = *ip++; case 11: *op++ = *ip++; case 10: *op++ = *ip++; case  9: *op++ = *ip++;\n              case  8: *op++ = *ip++; case  7: *op++ = *ip++; case  6: *op++ = *ip++; case  5: *op++ = *ip++;\n              case  4: *op++ = *ip++; case  3: *op++ = *ip++; case  2: *op++ = *ip++; case  1: *op++ = *ip++;\n            }\n#endif\n        }\n      else /* back reference */\n        {\n          unsigned int len = ctrl >> 5;\n\n          u8 *ref = op - ((ctrl & 0x1f) << 8) - 1;\n\n#if CHECK_INPUT\n          if (ip >= in_end)\n            {\n              SET_ERRNO (EINVAL);\n              return 0;\n            }\n#endif\n          if (len == 7)\n            {\n              len += *ip++;\n#if CHECK_INPUT\n              if (ip >= in_end)\n                {\n                  SET_ERRNO (EINVAL);\n                  return 0;\n                }\n#endif\n            }\n\n          ref -= *ip++;\n\n          if (op + len + 2 > out_end)\n            {\n              SET_ERRNO (E2BIG);\n              return 0;\n            }\n\n          if (ref < (u8 *)out_data)\n            {\n              SET_ERRNO (EINVAL);\n              return 0;\n            }\n\n#ifdef lzf_movsb\n          len += 2;\n          lzf_movsb (op, ref, len);\n#else\n          switch (len)\n            {\n              default:\n                len += 2;\n\n                if (op >= ref + len)\n                  {\n                    /* disjunct areas */\n                    memcpy (op, ref, len);\n                    op += len;\n                  }\n                else\n                  {\n                    /* overlapping, use octte by octte copying */\n                    do\n                      *op++ = *ref++;\n                    while (--len);\n                  }\n\n                break;\n\n              case 9: *op++ = *ref++;\n              case 8: *op++ = *ref++;\n              case 7: *op++ = *ref++;\n              case 6: *op++ = *ref++;\n              case 5: *op++ = *ref++;\n              case 4: *op++ = *ref++;\n              case 3: *op++ = *ref++;\n              case 2: *op++ = *ref++;\n              case 1: *op++ = *ref++;\n              case 0: *op++ = *ref++; /* two octets more */\n                      *op++ = *ref++;\n            }\n#endif\n        }\n    }\n  while (ip < in_end);\n\n  return op - (u8 *)out_data;\n}\n\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/src/memtest.c",
    "content": "/*\n * Copyright (c) 2009-2012, Salvatore Sanfilippo <antirez at gmail dot com>\n * All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions are met:\n *\n *   * Redistributions of source code must retain the above copyright notice,\n *     this list of conditions and the following disclaimer.\n *   * Redistributions in binary form must reproduce the above copyright\n *     notice, this list of conditions and the following disclaimer in the\n *     documentation and/or other materials provided with the distribution.\n *   * Neither the name of Redis nor the names of its contributors may be used\n *     to endorse or promote products derived from this software without\n *     specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\"\n * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\n * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE\n * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR\n * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF\n * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS\n * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN\n * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)\n * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE\n * POSSIBILITY OF SUCH DAMAGE.\n */\n#include <stdint.h>\n#include <stdlib.h>\n#include <stdio.h>\n#include <string.h>\n#include <assert.h>\n#include <limits.h>\n#include <errno.h>\n#include <termios.h>\n#include <sys/ioctl.h>\n#if defined(__sun)\n#include <stropts.h>\n#endif\n#include \"config.h\"\n\n#if (ULONG_MAX == 4294967295UL)\n#define MEMTEST_32BIT\n#elif (ULONG_MAX == 18446744073709551615ULL)\n#define MEMTEST_64BIT\n#else\n#error \"ULONG_MAX value not supported.\"\n#endif\n\n#ifdef MEMTEST_32BIT\n#define ULONG_ONEZERO 0xaaaaaaaaUL\n#define ULONG_ZEROONE 0x55555555UL\n#else\n#define ULONG_ONEZERO 0xaaaaaaaaaaaaaaaaUL\n#define ULONG_ZEROONE 0x5555555555555555UL\n#endif\n\nstatic struct winsize ws;\nsize_t progress_printed; /* Printed chars in screen-wide progress bar. */\nsize_t progress_full; /* How many chars to write to fill the progress bar. */\n\nvoid memtest_progress_start(char *title, int pass) {\n    int j;\n\n    printf(\"\\x1b[H\\x1b[2J\");    /* Cursor home, clear screen. */\n    /* Fill with dots. */\n    for (j = 0; j < ws.ws_col*(ws.ws_row-2); j++) printf(\".\");\n    printf(\"Please keep the test running several minutes per GB of memory.\\n\");\n    printf(\"Also check http://www.memtest86.com/ and http://pyropus.ca/software/memtester/\");\n    printf(\"\\x1b[H\\x1b[2K\");          /* Cursor home, clear current line.  */\n    printf(\"%s [%d]\\n\", title, pass); /* Print title. */\n    progress_printed = 0;\n    progress_full = ws.ws_col*(ws.ws_row-3);\n    fflush(stdout);\n}\n\nvoid memtest_progress_end(void) {\n    printf(\"\\x1b[H\\x1b[2J\");    /* Cursor home, clear screen. */\n}\n\nvoid memtest_progress_step(size_t curr, size_t size, char c) {\n    size_t chars = ((unsigned long long)curr*progress_full)/size, j;\n\n    for (j = 0; j < chars-progress_printed; j++) printf(\"%c\",c);\n    progress_printed = chars;\n    fflush(stdout);\n}\n\n/* Test that addressing is fine. Every location is populated with its own\n * address, and finally verified. This test is very fast but may detect\n * ASAP big issues with the memory subsystem. */\nint memtest_addressing(unsigned long *l, size_t bytes, int interactive) {\n    unsigned long words = bytes/sizeof(unsigned long);\n    unsigned long j, *p;\n\n    /* Fill */\n    p = l;\n    for (j = 0; j < words; j++) {\n        *p = (unsigned long)p;\n        p++;\n        if ((j & 0xffff) == 0 && interactive)\n            memtest_progress_step(j,words*2,'A');\n    }\n    /* Test */\n    p = l;\n    for (j = 0; j < words; j++) {\n        if (*p != (unsigned long)p) {\n            if (interactive) {\n                printf(\"\\n*** MEMORY ADDRESSING ERROR: %p contains %lu\\n\",\n                    (void*) p, *p);\n                exit(1);\n            }\n            return 1;\n        }\n        p++;\n        if ((j & 0xffff) == 0 && interactive)\n            memtest_progress_step(j+words,words*2,'A');\n    }\n    return 0;\n}\n\n/* Fill words stepping a single page at every write, so we continue to\n * touch all the pages in the smallest amount of time reducing the\n * effectiveness of caches, and making it hard for the OS to transfer\n * pages on the swap.\n *\n * In this test we can't call rand() since the system may be completely\n * unable to handle library calls, so we have to resort to our own\n * PRNG that only uses local state. We use an xorshift* PRNG. */\n#define xorshift64star_next() do { \\\n        rseed ^= rseed >> 12; \\\n        rseed ^= rseed << 25; \\\n        rseed ^= rseed >> 27; \\\n        rout = rseed * UINT64_C(2685821657736338717); \\\n} while(0)\n\nvoid memtest_fill_random(unsigned long *l, size_t bytes, int interactive) {\n    unsigned long step = 4096/sizeof(unsigned long);\n    unsigned long words = bytes/sizeof(unsigned long)/2;\n    unsigned long iwords = words/step;  /* words per iteration */\n    unsigned long off, w, *l1, *l2;\n    uint64_t rseed = UINT64_C(0xd13133de9afdb566); /* Just a random seed. */\n    uint64_t rout = 0;\n\n    assert((bytes & 4095) == 0);\n    for (off = 0; off < step; off++) {\n        l1 = l+off;\n        l2 = l1+words;\n        for (w = 0; w < iwords; w++) {\n            xorshift64star_next();\n            *l1 = *l2 = (unsigned long) rout;\n            l1 += step;\n            l2 += step;\n            if ((w & 0xffff) == 0 && interactive)\n                memtest_progress_step(w+iwords*off,words,'R');\n        }\n    }\n}\n\n/* Like memtest_fill_random() but uses the two specified values to fill\n * memory, in an alternated way (v1|v2|v1|v2|...) */\nvoid memtest_fill_value(unsigned long *l, size_t bytes, unsigned long v1,\n                        unsigned long v2, char sym, int interactive)\n{\n    unsigned long step = 4096/sizeof(unsigned long);\n    unsigned long words = bytes/sizeof(unsigned long)/2;\n    unsigned long iwords = words/step;  /* words per iteration */\n    unsigned long off, w, *l1, *l2, v;\n\n    assert((bytes & 4095) == 0);\n    for (off = 0; off < step; off++) {\n        l1 = l+off;\n        l2 = l1+words;\n        v = (off & 1) ? v2 : v1;\n        for (w = 0; w < iwords; w++) {\n#ifdef MEMTEST_32BIT\n            *l1 = *l2 = ((unsigned long)     v) |\n                        (((unsigned long)    v) << 16);\n#else\n            *l1 = *l2 = ((unsigned long)     v) |\n                        (((unsigned long)    v) << 16) |\n                        (((unsigned long)    v) << 32) |\n                        (((unsigned long)    v) << 48);\n#endif\n            l1 += step;\n            l2 += step;\n            if ((w & 0xffff) == 0 && interactive)\n                memtest_progress_step(w+iwords*off,words,sym);\n        }\n    }\n}\n\nint memtest_compare(unsigned long *l, size_t bytes, int interactive) {\n    unsigned long words = bytes/sizeof(unsigned long)/2;\n    unsigned long w, *l1, *l2;\n\n    assert((bytes & 4095) == 0);\n    l1 = l;\n    l2 = l1+words;\n    for (w = 0; w < words; w++) {\n        if (*l1 != *l2) {\n            if (interactive) {\n                printf(\"\\n*** MEMORY ERROR DETECTED: %p != %p (%lu vs %lu)\\n\",\n                    (void*)l1, (void*)l2, *l1, *l2);\n                exit(1);\n            }\n            return 1;\n        }\n        l1 ++;\n        l2 ++;\n        if ((w & 0xffff) == 0 && interactive)\n            memtest_progress_step(w,words,'=');\n    }\n    return 0;\n}\n\nint memtest_compare_times(unsigned long *m, size_t bytes, int pass, int times,\n                          int interactive)\n{\n    int j;\n    int errors = 0;\n\n    for (j = 0; j < times; j++) {\n        if (interactive) memtest_progress_start(\"Compare\",pass);\n        errors += memtest_compare(m,bytes,interactive);\n        if (interactive) memtest_progress_end();\n    }\n    return errors;\n}\n\n/* Test the specified memory. The number of bytes must be multiple of 4096.\n * If interactive is true the program exists with an error and prints\n * ASCII arts to show progresses. Instead when interactive is 0, it can\n * be used as an API call, and returns 1 if memory errors were found or\n * 0 if there were no errors detected. */\nint memtest_test(unsigned long *m, size_t bytes, int passes, int interactive) {\n    int pass = 0;\n    int errors = 0;\n\n    while (pass != passes) {\n        pass++;\n\n        if (interactive) memtest_progress_start(\"Addressing test\",pass);\n        errors += memtest_addressing(m,bytes,interactive);\n        if (interactive) memtest_progress_end();\n\n        if (interactive) memtest_progress_start(\"Random fill\",pass);\n        memtest_fill_random(m,bytes,interactive);\n        if (interactive) memtest_progress_end();\n        errors += memtest_compare_times(m,bytes,pass,4,interactive);\n\n        if (interactive) memtest_progress_start(\"Solid fill\",pass);\n        memtest_fill_value(m,bytes,0,(unsigned long)-1,'S',interactive);\n        if (interactive) memtest_progress_end();\n        errors += memtest_compare_times(m,bytes,pass,4,interactive);\n\n        if (interactive) memtest_progress_start(\"Checkerboard fill\",pass);\n        memtest_fill_value(m,bytes,ULONG_ONEZERO,ULONG_ZEROONE,'C',interactive);\n        if (interactive) memtest_progress_end();\n        errors += memtest_compare_times(m,bytes,pass,4,interactive);\n    }\n    return errors;\n}\n\n/* A version of memtest_test() that tests memory in small pieces\n * in order to restore the memory content at exit.\n *\n * One problem we have with this approach, is that the cache can avoid\n * real memory accesses, and we can't test big chunks of memory at the\n * same time, because we need to backup them on the stack (the allocator\n * may not be usable or we may be already in an out of memory condition).\n * So what we do is to try to trash the cache with useless memory accesses\n * between the fill and compare cycles. */\n#define MEMTEST_BACKUP_WORDS (1024*(1024/sizeof(long)))\n/* Random accesses of MEMTEST_DECACHE_SIZE are performed at the start and\n * end of the region between fill and compare cycles in order to trash\n * the cache. */\n#define MEMTEST_DECACHE_SIZE (1024*8)\nint memtest_preserving_test(unsigned long *m, size_t bytes, int passes) {\n    unsigned long backup[MEMTEST_BACKUP_WORDS];\n    unsigned long *p = m;\n    unsigned long *end = (unsigned long*) (((unsigned char*)m)+(bytes-MEMTEST_DECACHE_SIZE));\n    size_t left = bytes;\n    int errors = 0;\n\n    if (bytes & 4095) return 0; /* Can't test across 4k page boundaries. */\n    if (bytes < 4096*2) return 0; /* Can't test a single page. */\n\n    while(left) {\n        /* If we have to test a single final page, go back a single page\n         * so that we can test two pages, since the code can't test a single\n         * page but at least two. */\n        if (left == 4096) {\n            left += 4096;\n            p -= 4096/sizeof(unsigned long);\n        }\n\n        int pass = 0;\n        size_t len = (left > sizeof(backup)) ? sizeof(backup) : left;\n\n        /* Always test an even number of pages. */\n        if (len/4096 % 2) len -= 4096;\n\n        memcpy(backup,p,len); /* Backup. */\n        while(pass != passes) {\n            pass++;\n            errors += memtest_addressing(p,len,0);\n            memtest_fill_random(p,len,0);\n            if (bytes >= MEMTEST_DECACHE_SIZE) {\n                memtest_compare_times(m,MEMTEST_DECACHE_SIZE,pass,1,0);\n                memtest_compare_times(end,MEMTEST_DECACHE_SIZE,pass,1,0);\n            }\n            errors += memtest_compare_times(p,len,pass,4,0);\n            memtest_fill_value(p,len,0,(unsigned long)-1,'S',0);\n            if (bytes >= MEMTEST_DECACHE_SIZE) {\n                memtest_compare_times(m,MEMTEST_DECACHE_SIZE,pass,1,0);\n                memtest_compare_times(end,MEMTEST_DECACHE_SIZE,pass,1,0);\n            }\n            errors += memtest_compare_times(p,len,pass,4,0);\n            memtest_fill_value(p,len,ULONG_ONEZERO,ULONG_ZEROONE,'C',0);\n            if (bytes >= MEMTEST_DECACHE_SIZE) {\n                memtest_compare_times(m,MEMTEST_DECACHE_SIZE,pass,1,0);\n                memtest_compare_times(end,MEMTEST_DECACHE_SIZE,pass,1,0);\n            }\n            errors += memtest_compare_times(p,len,pass,4,0);\n        }\n        memcpy(p,backup,len); /* Restore. */\n        left -= len;\n        p += len/sizeof(unsigned long);\n    }\n    return errors;\n}\n\n/* Perform an interactive test allocating the specified number of megabytes. */\nvoid memtest_alloc_and_test(size_t megabytes, int passes) {\n    size_t bytes = megabytes*1024*1024;\n    unsigned long *m = malloc(bytes);\n\n    if (m == NULL) {\n        fprintf(stderr,\"Unable to allocate %zu megabytes: %s\",\n            megabytes, strerror(errno));\n        exit(1);\n    }\n    memtest_test(m,bytes,passes,1);\n    free(m);\n}\n\nvoid memtest(size_t megabytes, int passes) {\n    if (ioctl(1, TIOCGWINSZ, &ws) == -1) {\n        ws.ws_col = 80;\n        ws.ws_row = 20;\n    }\n    memtest_alloc_and_test(megabytes,passes);\n    printf(\"\\nYour memory passed this test.\\n\");\n    printf(\"Please if you are still in doubt use the following two tools:\\n\");\n    printf(\"1) memtest86: http://www.memtest86.com/\\n\");\n    printf(\"2) memtester: http://pyropus.ca/software/memtester/\\n\");\n    exit(0);\n}\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/src/mkreleasehdr.sh",
    "content": "#!/bin/sh\nGIT_SHA1=`(git show-ref --head --hash=8 2> /dev/null || echo 00000000) | head -n1`\nGIT_DIRTY=`git diff --no-ext-diff 2> /dev/null | wc -l`\nBUILD_ID=`uname -n`\"-\"`date +%s`\ntest -f release.h || touch release.h\n(cat release.h | grep SHA1 | grep $GIT_SHA1) && \\\n(cat release.h | grep DIRTY | grep $GIT_DIRTY) && exit 0 # Already up-to-date\necho \"#define REDIS_GIT_SHA1 \\\"$GIT_SHA1\\\"\" > release.h\necho \"#define REDIS_GIT_DIRTY \\\"$GIT_DIRTY\\\"\" >> release.h\necho \"#define REDIS_BUILD_ID \\\"$BUILD_ID\\\"\" >> release.h\ntouch release.c # Force recompile of release.c\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/src/multi.c",
    "content": "/*\n * Copyright (c) 2009-2012, Salvatore Sanfilippo <antirez at gmail dot com>\n * All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions are met:\n *\n *   * Redistributions of source code must retain the above copyright notice,\n *     this list of conditions and the following disclaimer.\n *   * Redistributions in binary form must reproduce the above copyright\n *     notice, this list of conditions and the following disclaimer in the\n *     documentation and/or other materials provided with the distribution.\n *   * Neither the name of Redis nor the names of its contributors may be used\n *     to endorse or promote products derived from this software without\n *     specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\"\n * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\n * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE\n * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR\n * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF\n * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS\n * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN\n * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)\n * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE\n * POSSIBILITY OF SUCH DAMAGE.\n */\n\n#include \"server.h\"\n\n/* ================================ MULTI/EXEC ============================== */\n\n/* Client state initialization for MULTI/EXEC */\nvoid initClientMultiState(client *c) {\n    c->mstate.commands = NULL;\n    c->mstate.count = 0;\n}\n\n/* Release all the resources associated with MULTI/EXEC state */\nvoid freeClientMultiState(client *c) {\n    int j;\n\n    for (j = 0; j < c->mstate.count; j++) {\n        int i;\n        multiCmd *mc = c->mstate.commands+j;\n\n        for (i = 0; i < mc->argc; i++)\n            decrRefCount(mc->argv[i]);\n        zfree(mc->argv);\n    }\n    zfree(c->mstate.commands);\n}\n\n/* Add a new command into the MULTI commands queue */\nvoid queueMultiCommand(client *c) {\n    multiCmd *mc;\n    int j;\n\n    c->mstate.commands = zrealloc(c->mstate.commands,\n            sizeof(multiCmd)*(c->mstate.count+1));\n    mc = c->mstate.commands+c->mstate.count;\n    mc->cmd = c->cmd;\n    mc->argc = c->argc;\n    mc->argv = zmalloc(sizeof(robj*)*c->argc);\n    memcpy(mc->argv,c->argv,sizeof(robj*)*c->argc);\n    for (j = 0; j < c->argc; j++)\n        incrRefCount(mc->argv[j]);\n    c->mstate.count++;\n}\n\nvoid discardTransaction(client *c) {\n    freeClientMultiState(c);\n    initClientMultiState(c);\n    c->flags &= ~(CLIENT_MULTI|CLIENT_DIRTY_CAS|CLIENT_DIRTY_EXEC);\n    unwatchAllKeys(c);\n}\n\n/* Flag the transacation as DIRTY_EXEC so that EXEC will fail.\n * Should be called every time there is an error while queueing a command. */\nvoid flagTransaction(client *c) {\n    if (c->flags & CLIENT_MULTI)\n        c->flags |= CLIENT_DIRTY_EXEC;\n}\n\nvoid multiCommand(client *c) {\n    if (c->flags & CLIENT_MULTI) {\n        addReplyError(c,\"MULTI calls can not be nested\");\n        return;\n    }\n    c->flags |= CLIENT_MULTI;\n    addReply(c,shared.ok);\n}\n\nvoid discardCommand(client *c) {\n    if (!(c->flags & CLIENT_MULTI)) {\n        addReplyError(c,\"DISCARD without MULTI\");\n        return;\n    }\n    discardTransaction(c);\n    addReply(c,shared.ok);\n}\n\n/* Send a MULTI command to all the slaves and AOF file. Check the execCommand\n * implementation for more information. */\nvoid execCommandPropagateMulti(client *c) {\n    robj *multistring = createStringObject(\"MULTI\",5);\n\n    propagate(server.multiCommand,c->db->id,&multistring,1,\n              PROPAGATE_AOF|PROPAGATE_REPL);\n    decrRefCount(multistring);\n}\n\nvoid execCommand(client *c) {\n    int j;\n    robj **orig_argv;\n    int orig_argc;\n    struct redisCommand *orig_cmd;\n    int must_propagate = 0; /* Need to propagate MULTI/EXEC to AOF / slaves? */\n\n    if (!(c->flags & CLIENT_MULTI)) {\n        addReplyError(c,\"EXEC without MULTI\");\n        return;\n    }\n\n    /* Check if we need to abort the EXEC because:\n     * 1) Some WATCHed key was touched.\n     * 2) There was a previous error while queueing commands.\n     * A failed EXEC in the first case returns a multi bulk nil object\n     * (technically it is not an error but a special behavior), while\n     * in the second an EXECABORT error is returned. */\n    if (c->flags & (CLIENT_DIRTY_CAS|CLIENT_DIRTY_EXEC)) {\n        addReply(c, c->flags & CLIENT_DIRTY_EXEC ? shared.execaborterr :\n                                                  shared.nullmultibulk);\n        discardTransaction(c);\n        goto handle_monitor;\n    }\n\n    /* Exec all the queued commands */\n    unwatchAllKeys(c); /* Unwatch ASAP otherwise we'll waste CPU cycles */\n    orig_argv = c->argv;\n    orig_argc = c->argc;\n    orig_cmd = c->cmd;\n    addReplyMultiBulkLen(c,c->mstate.count);\n    for (j = 0; j < c->mstate.count; j++) {\n        c->argc = c->mstate.commands[j].argc;\n        c->argv = c->mstate.commands[j].argv;\n        c->cmd = c->mstate.commands[j].cmd;\n\n        /* Propagate a MULTI request once we encounter the first write op.\n         * This way we'll deliver the MULTI/..../EXEC block as a whole and\n         * both the AOF and the replication link will have the same consistency\n         * and atomicity guarantees. */\n        if (!must_propagate && !(c->cmd->flags & CMD_READONLY)) {\n            execCommandPropagateMulti(c);\n            must_propagate = 1;\n        }\n\n        call(c,CMD_CALL_FULL);\n\n        /* Commands may alter argc/argv, restore mstate. */\n        c->mstate.commands[j].argc = c->argc;\n        c->mstate.commands[j].argv = c->argv;\n        c->mstate.commands[j].cmd = c->cmd;\n    }\n    c->argv = orig_argv;\n    c->argc = orig_argc;\n    c->cmd = orig_cmd;\n    discardTransaction(c);\n    /* Make sure the EXEC command will be propagated as well if MULTI\n     * was already propagated. */\n    if (must_propagate) server.dirty++;\n\nhandle_monitor:\n    /* Send EXEC to clients waiting data from MONITOR. We do it here\n     * since the natural order of commands execution is actually:\n     * MUTLI, EXEC, ... commands inside transaction ...\n     * Instead EXEC is flagged as CMD_SKIP_MONITOR in the command\n     * table, and we do it here with correct ordering. */\n    if (listLength(server.monitors) && !server.loading)\n        replicationFeedMonitors(c,server.monitors,c->db->id,c->argv,c->argc);\n}\n\n/* ===================== WATCH (CAS alike for MULTI/EXEC) ===================\n *\n * The implementation uses a per-DB hash table mapping keys to list of clients\n * WATCHing those keys, so that given a key that is going to be modified\n * we can mark all the associated clients as dirty.\n *\n * Also every client contains a list of WATCHed keys so that's possible to\n * un-watch such keys when the client is freed or when UNWATCH is called. */\n\n/* In the client->watched_keys list we need to use watchedKey structures\n * as in order to identify a key in Redis we need both the key name and the\n * DB */\ntypedef struct watchedKey {\n    robj *key;\n    redisDb *db;\n} watchedKey;\n\n/* Watch for the specified key */\nvoid watchForKey(client *c, robj *key) {\n    list *clients = NULL;\n    listIter li;\n    listNode *ln;\n    watchedKey *wk;\n\n    /* Check if we are already watching for this key */\n    listRewind(c->watched_keys,&li);\n    while((ln = listNext(&li))) {\n        wk = listNodeValue(ln);\n        if (wk->db == c->db && equalStringObjects(key,wk->key))\n            return; /* Key already watched */\n    }\n    /* This key is not already watched in this DB. Let's add it */\n    clients = dictFetchValue(c->db->watched_keys,key);\n    if (!clients) {\n        clients = listCreate();\n        dictAdd(c->db->watched_keys,key,clients);\n        incrRefCount(key);\n    }\n    listAddNodeTail(clients,c);\n    /* Add the new key to the list of keys watched by this client */\n    wk = zmalloc(sizeof(*wk));\n    wk->key = key;\n    wk->db = c->db;\n    incrRefCount(key);\n    listAddNodeTail(c->watched_keys,wk);\n}\n\n/* Unwatch all the keys watched by this client. To clean the EXEC dirty\n * flag is up to the caller. */\nvoid unwatchAllKeys(client *c) {\n    listIter li;\n    listNode *ln;\n\n    if (listLength(c->watched_keys) == 0) return;\n    listRewind(c->watched_keys,&li);\n    while((ln = listNext(&li))) {\n        list *clients;\n        watchedKey *wk;\n\n        /* Lookup the watched key -> clients list and remove the client\n         * from the list */\n        wk = listNodeValue(ln);\n        clients = dictFetchValue(wk->db->watched_keys, wk->key);\n        serverAssertWithInfo(c,NULL,clients != NULL);\n        listDelNode(clients,listSearchKey(clients,c));\n        /* Kill the entry at all if this was the only client */\n        if (listLength(clients) == 0)\n            dictDelete(wk->db->watched_keys, wk->key);\n        /* Remove this watched key from the client->watched list */\n        listDelNode(c->watched_keys,ln);\n        decrRefCount(wk->key);\n        zfree(wk);\n    }\n}\n\n/* \"Touch\" a key, so that if this key is being WATCHed by some client the\n * next EXEC will fail. */\nvoid touchWatchedKey(redisDb *db, robj *key) {\n    list *clients;\n    listIter li;\n    listNode *ln;\n\n    if (dictSize(db->watched_keys) == 0) return;\n    clients = dictFetchValue(db->watched_keys, key);\n    if (!clients) return;\n\n    /* Mark all the clients watching this key as CLIENT_DIRTY_CAS */\n    /* Check if we are already watching for this key */\n    listRewind(clients,&li);\n    while((ln = listNext(&li))) {\n        client *c = listNodeValue(ln);\n\n        c->flags |= CLIENT_DIRTY_CAS;\n    }\n}\n\n/* On FLUSHDB or FLUSHALL all the watched keys that are present before the\n * flush but will be deleted as effect of the flushing operation should\n * be touched. \"dbid\" is the DB that's getting the flush. -1 if it is\n * a FLUSHALL operation (all the DBs flushed). */\nvoid touchWatchedKeysOnFlush(int dbid) {\n    listIter li1, li2;\n    listNode *ln;\n\n    /* For every client, check all the waited keys */\n    listRewind(server.clients,&li1);\n    while((ln = listNext(&li1))) {\n        client *c = listNodeValue(ln);\n        listRewind(c->watched_keys,&li2);\n        while((ln = listNext(&li2))) {\n            watchedKey *wk = listNodeValue(ln);\n\n            /* For every watched key matching the specified DB, if the\n             * key exists, mark the client as dirty, as the key will be\n             * removed. */\n            if (dbid == -1 || wk->db->id == dbid) {\n                if (dictFind(wk->db->dict, wk->key->ptr) != NULL)\n                    c->flags |= CLIENT_DIRTY_CAS;\n            }\n        }\n    }\n}\n\nvoid watchCommand(client *c) {\n    int j;\n\n    if (c->flags & CLIENT_MULTI) {\n        addReplyError(c,\"WATCH inside MULTI is not allowed\");\n        return;\n    }\n    for (j = 1; j < c->argc; j++)\n        watchForKey(c,c->argv[j]);\n    addReply(c,shared.ok);\n}\n\nvoid unwatchCommand(client *c) {\n    unwatchAllKeys(c);\n    c->flags &= (~CLIENT_DIRTY_CAS);\n    addReply(c,shared.ok);\n}\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/src/networking.c",
    "content": "/*\n * Copyright (c) 2009-2012, Salvatore Sanfilippo <antirez at gmail dot com>\n * All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions are met:\n *\n *   * Redistributions of source code must retain the above copyright notice,\n *     this list of conditions and the following disclaimer.\n *   * Redistributions in binary form must reproduce the above copyright\n *     notice, this list of conditions and the following disclaimer in the\n *     documentation and/or other materials provided with the distribution.\n *   * Neither the name of Redis nor the names of its contributors may be used\n *     to endorse or promote products derived from this software without\n *     specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\"\n * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\n * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE\n * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR\n * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF\n * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS\n * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN\n * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)\n * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE\n * POSSIBILITY OF SUCH DAMAGE.\n */\n\n#include \"server.h\"\n#include <sys/uio.h>\n#include <math.h>\n\nstatic void setProtocolError(client *c, int pos);\n\n/* Return the size consumed from the allocator, for the specified SDS string,\n * including internal fragmentation. This function is used in order to compute\n * the client output buffer size. */\nsize_t sdsZmallocSize(sds s) {\n    void *sh = sdsAllocPtr(s);\n    return zmalloc_size(sh);\n}\n\n/* Return the amount of memory used by the sds string at object->ptr\n * for a string object. */\nsize_t getStringObjectSdsUsedMemory(robj *o) {\n    serverAssertWithInfo(NULL,o,o->type == OBJ_STRING);\n    switch(o->encoding) {\n    case OBJ_ENCODING_RAW: return sdsZmallocSize(o->ptr);\n    case OBJ_ENCODING_EMBSTR: return zmalloc_size(o)-sizeof(robj);\n    default: return 0; /* Just integer encoding for now. */\n    }\n}\n\nvoid *dupClientReplyValue(void *o) {\n    incrRefCount((robj*)o);\n    return o;\n}\n\nint listMatchObjects(void *a, void *b) {\n    return equalStringObjects(a,b);\n}\n\nclient *createClient(int fd) {\n    client *c = zmalloc(sizeof(client));\n\n    /* passing -1 as fd it is possible to create a non connected client.\n     * This is useful since all the commands needs to be executed\n     * in the context of a client. When commands are executed in other\n     * contexts (for instance a Lua script) we need a non connected client. */\n    if (fd != -1) {\n        anetNonBlock(NULL,fd);\n        anetEnableTcpNoDelay(NULL,fd);\n        if (server.tcpkeepalive)\n            anetKeepAlive(NULL,fd,server.tcpkeepalive);\n        if (aeCreateFileEvent(server.el,fd,AE_READABLE,\n            readQueryFromClient, c) == AE_ERR)\n        {\n            close(fd);\n            zfree(c);\n            return NULL;\n        }\n    }\n\n    selectDb(c,0);\n    c->id = server.next_client_id++;\n    c->fd = fd;\n    c->name = NULL;\n    c->bufpos = 0;\n    c->querybuf = sdsempty();\n    c->querybuf_peak = 0;\n    c->reqtype = 0;\n    c->argc = 0;\n    c->argv = NULL;\n    c->cmd = c->lastcmd = NULL;\n    c->multibulklen = 0;\n    c->bulklen = -1;\n    c->sentlen = 0;\n    c->flags = 0;\n    c->ctime = c->lastinteraction = server.unixtime;\n    c->authenticated = 0;\n    c->replstate = REPL_STATE_NONE;\n    c->repl_put_online_on_ack = 0;\n    c->reploff = 0;\n    c->repl_ack_off = 0;\n    c->repl_ack_time = 0;\n    c->slave_listening_port = 0;\n    c->slave_ip[0] = '\\0';\n    c->slave_capa = SLAVE_CAPA_NONE;\n    c->reply = listCreate();\n    c->reply_bytes = 0;\n    c->obuf_soft_limit_reached_time = 0;\n    listSetFreeMethod(c->reply,decrRefCountVoid);\n    listSetDupMethod(c->reply,dupClientReplyValue);\n    c->btype = BLOCKED_NONE;\n    c->bpop.timeout = 0;\n    c->bpop.keys = dictCreate(&setDictType,NULL);\n    c->bpop.target = NULL;\n    c->bpop.numreplicas = 0;\n    c->bpop.reploffset = 0;\n    c->woff = 0;\n    c->watched_keys = listCreate();\n    c->pubsub_channels = dictCreate(&setDictType,NULL);\n    c->pubsub_patterns = listCreate();\n    c->peerid = NULL;\n    listSetFreeMethod(c->pubsub_patterns,decrRefCountVoid);\n    listSetMatchMethod(c->pubsub_patterns,listMatchObjects);\n    if (fd != -1) listAddNodeTail(server.clients,c);\n    initClientMultiState(c);\n    return c;\n}\n\n/* This function is called every time we are going to transmit new data\n * to the client. The behavior is the following:\n *\n * If the client should receive new data (normal clients will) the function\n * returns C_OK, and make sure to install the write handler in our event\n * loop so that when the socket is writable new data gets written.\n *\n * If the client should not receive new data, because it is a fake client\n * (used to load AOF in memory), a master or because the setup of the write\n * handler failed, the function returns C_ERR.\n *\n * The function may return C_OK without actually installing the write\n * event handler in the following cases:\n *\n * 1) The event handler should already be installed since the output buffer\n *    already contained something.\n * 2) The client is a slave but not yet online, so we want to just accumulate\n *    writes in the buffer but not actually sending them yet.\n *\n * Typically gets called every time a reply is built, before adding more\n * data to the clients output buffers. If the function returns C_ERR no\n * data should be appended to the output buffers. */\nint prepareClientToWrite(client *c) {\n    /* If it's the Lua client we always return ok without installing any\n     * handler since there is no socket at all. */\n    if (c->flags & CLIENT_LUA) return C_OK;\n\n    /* CLIENT REPLY OFF / SKIP handling: don't send replies. */\n    if (c->flags & (CLIENT_REPLY_OFF|CLIENT_REPLY_SKIP)) return C_ERR;\n\n    /* Masters don't receive replies, unless CLIENT_MASTER_FORCE_REPLY flag\n     * is set. */\n    if ((c->flags & CLIENT_MASTER) &&\n        !(c->flags & CLIENT_MASTER_FORCE_REPLY)) return C_ERR;\n\n    if (c->fd <= 0) return C_ERR; /* Fake client for AOF loading. */\n\n    /* Schedule the client to write the output buffers to the socket only\n     * if not already done (there were no pending writes already and the client\n     * was yet not flagged), and, for slaves, if the slave can actually\n     * receive writes at this stage. */\n    if (!clientHasPendingReplies(c) &&\n        !(c->flags & CLIENT_PENDING_WRITE) &&\n        (c->replstate == REPL_STATE_NONE ||\n         (c->replstate == SLAVE_STATE_ONLINE && !c->repl_put_online_on_ack)))\n    {\n        /* Here instead of installing the write handler, we just flag the\n         * client and put it into a list of clients that have something\n         * to write to the socket. This way before re-entering the event\n         * loop, we can try to directly write to the client sockets avoiding\n         * a system call. We'll only really install the write handler if\n         * we'll not be able to write the whole reply at once. */\n        c->flags |= CLIENT_PENDING_WRITE;\n        listAddNodeHead(server.clients_pending_write,c);\n    }\n\n    /* Authorize the caller to queue in the output buffer of this client. */\n    return C_OK;\n}\n\n/* Create a duplicate of the last object in the reply list when\n * it is not exclusively owned by the reply list. */\nrobj *dupLastObjectIfNeeded(list *reply) {\n    robj *new, *cur;\n    listNode *ln;\n    serverAssert(listLength(reply) > 0);\n    ln = listLast(reply);\n    cur = listNodeValue(ln);\n    if (cur->refcount > 1) {\n        new = dupStringObject(cur);\n        decrRefCount(cur);\n        listNodeValue(ln) = new;\n    }\n    return listNodeValue(ln);\n}\n\n/* -----------------------------------------------------------------------------\n * Low level functions to add more data to output buffers.\n * -------------------------------------------------------------------------- */\n\nint _addReplyToBuffer(client *c, const char *s, size_t len) {\n    size_t available = sizeof(c->buf)-c->bufpos;\n\n    if (c->flags & CLIENT_CLOSE_AFTER_REPLY) return C_OK;\n\n    /* If there already are entries in the reply list, we cannot\n     * add anything more to the static buffer. */\n    if (listLength(c->reply) > 0) return C_ERR;\n\n    /* Check that the buffer has enough space available for this string. */\n    if (len > available) return C_ERR;\n\n    memcpy(c->buf+c->bufpos,s,len);\n    c->bufpos+=len;\n    return C_OK;\n}\n\nvoid _addReplyObjectToList(client *c, robj *o) {\n    robj *tail;\n\n    if (c->flags & CLIENT_CLOSE_AFTER_REPLY) return;\n\n    if (listLength(c->reply) == 0) {\n        incrRefCount(o);\n        listAddNodeTail(c->reply,o);\n        c->reply_bytes += getStringObjectSdsUsedMemory(o);\n    } else {\n        tail = listNodeValue(listLast(c->reply));\n\n        /* Append to this object when possible. */\n        if (tail->ptr != NULL &&\n            tail->encoding == OBJ_ENCODING_RAW &&\n            sdslen(tail->ptr)+sdslen(o->ptr) <= PROTO_REPLY_CHUNK_BYTES)\n        {\n            c->reply_bytes -= sdsZmallocSize(tail->ptr);\n            tail = dupLastObjectIfNeeded(c->reply);\n            tail->ptr = sdscatlen(tail->ptr,o->ptr,sdslen(o->ptr));\n            c->reply_bytes += sdsZmallocSize(tail->ptr);\n        } else {\n            incrRefCount(o);\n            listAddNodeTail(c->reply,o);\n            c->reply_bytes += getStringObjectSdsUsedMemory(o);\n        }\n    }\n    asyncCloseClientOnOutputBufferLimitReached(c);\n}\n\n/* This method takes responsibility over the sds. When it is no longer\n * needed it will be free'd, otherwise it ends up in a robj. */\nvoid _addReplySdsToList(client *c, sds s) {\n    robj *tail;\n\n    if (c->flags & CLIENT_CLOSE_AFTER_REPLY) {\n        sdsfree(s);\n        return;\n    }\n\n    if (listLength(c->reply) == 0) {\n        listAddNodeTail(c->reply,createObject(OBJ_STRING,s));\n        c->reply_bytes += sdsZmallocSize(s);\n    } else {\n        tail = listNodeValue(listLast(c->reply));\n\n        /* Append to this object when possible. */\n        if (tail->ptr != NULL && tail->encoding == OBJ_ENCODING_RAW &&\n            sdslen(tail->ptr)+sdslen(s) <= PROTO_REPLY_CHUNK_BYTES)\n        {\n            c->reply_bytes -= sdsZmallocSize(tail->ptr);\n            tail = dupLastObjectIfNeeded(c->reply);\n            tail->ptr = sdscatlen(tail->ptr,s,sdslen(s));\n            c->reply_bytes += sdsZmallocSize(tail->ptr);\n            sdsfree(s);\n        } else {\n            listAddNodeTail(c->reply,createObject(OBJ_STRING,s));\n            c->reply_bytes += sdsZmallocSize(s);\n        }\n    }\n    asyncCloseClientOnOutputBufferLimitReached(c);\n}\n\nvoid _addReplyStringToList(client *c, const char *s, size_t len) {\n    robj *tail;\n\n    if (c->flags & CLIENT_CLOSE_AFTER_REPLY) return;\n\n    if (listLength(c->reply) == 0) {\n        robj *o = createStringObject(s,len);\n\n        listAddNodeTail(c->reply,o);\n        c->reply_bytes += getStringObjectSdsUsedMemory(o);\n    } else {\n        tail = listNodeValue(listLast(c->reply));\n\n        /* Append to this object when possible. */\n        if (tail->ptr != NULL && tail->encoding == OBJ_ENCODING_RAW &&\n            sdslen(tail->ptr)+len <= PROTO_REPLY_CHUNK_BYTES)\n        {\n            c->reply_bytes -= sdsZmallocSize(tail->ptr);\n            tail = dupLastObjectIfNeeded(c->reply);\n            tail->ptr = sdscatlen(tail->ptr,s,len);\n            c->reply_bytes += sdsZmallocSize(tail->ptr);\n        } else {\n            robj *o = createStringObject(s,len);\n\n            listAddNodeTail(c->reply,o);\n            c->reply_bytes += getStringObjectSdsUsedMemory(o);\n        }\n    }\n    asyncCloseClientOnOutputBufferLimitReached(c);\n}\n\n/* -----------------------------------------------------------------------------\n * Higher level functions to queue data on the client output buffer.\n * The following functions are the ones that commands implementations will call.\n * -------------------------------------------------------------------------- */\n\nvoid addReply(client *c, robj *obj) {\n    if (prepareClientToWrite(c) != C_OK) return;\n\n    /* This is an important place where we can avoid copy-on-write\n     * when there is a saving child running, avoiding touching the\n     * refcount field of the object if it's not needed.\n     *\n     * If the encoding is RAW and there is room in the static buffer\n     * we'll be able to send the object to the client without\n     * messing with its page. */\n    if (sdsEncodedObject(obj)) {\n        if (_addReplyToBuffer(c,obj->ptr,sdslen(obj->ptr)) != C_OK)\n            _addReplyObjectToList(c,obj);\n    } else if (obj->encoding == OBJ_ENCODING_INT) {\n        /* Optimization: if there is room in the static buffer for 32 bytes\n         * (more than the max chars a 64 bit integer can take as string) we\n         * avoid decoding the object and go for the lower level approach. */\n        if (listLength(c->reply) == 0 && (sizeof(c->buf) - c->bufpos) >= 32) {\n            char buf[32];\n            int len;\n\n            len = ll2string(buf,sizeof(buf),(long)obj->ptr);\n            if (_addReplyToBuffer(c,buf,len) == C_OK)\n                return;\n            /* else... continue with the normal code path, but should never\n             * happen actually since we verified there is room. */\n        }\n        obj = getDecodedObject(obj);\n        if (_addReplyToBuffer(c,obj->ptr,sdslen(obj->ptr)) != C_OK)\n            _addReplyObjectToList(c,obj);\n        decrRefCount(obj);\n    } else {\n        serverPanic(\"Wrong obj->encoding in addReply()\");\n    }\n}\n\nvoid addReplySds(client *c, sds s) {\n    if (prepareClientToWrite(c) != C_OK) {\n        /* The caller expects the sds to be free'd. */\n        sdsfree(s);\n        return;\n    }\n    if (_addReplyToBuffer(c,s,sdslen(s)) == C_OK) {\n        sdsfree(s);\n    } else {\n        /* This method free's the sds when it is no longer needed. */\n        _addReplySdsToList(c,s);\n    }\n}\n\nvoid addReplyString(client *c, const char *s, size_t len) {\n    if (prepareClientToWrite(c) != C_OK) return;\n    if (_addReplyToBuffer(c,s,len) != C_OK)\n        _addReplyStringToList(c,s,len);\n}\n\nvoid addReplyErrorLength(client *c, const char *s, size_t len) {\n    addReplyString(c,\"-ERR \",5);\n    addReplyString(c,s,len);\n    addReplyString(c,\"\\r\\n\",2);\n}\n\nvoid addReplyError(client *c, const char *err) {\n    addReplyErrorLength(c,err,strlen(err));\n}\n\nvoid addReplyErrorFormat(client *c, const char *fmt, ...) {\n    size_t l, j;\n    va_list ap;\n    va_start(ap,fmt);\n    sds s = sdscatvprintf(sdsempty(),fmt,ap);\n    va_end(ap);\n    /* Make sure there are no newlines in the string, otherwise invalid protocol\n     * is emitted. */\n    l = sdslen(s);\n    for (j = 0; j < l; j++) {\n        if (s[j] == '\\r' || s[j] == '\\n') s[j] = ' ';\n    }\n    addReplyErrorLength(c,s,sdslen(s));\n    sdsfree(s);\n}\n\nvoid addReplyStatusLength(client *c, const char *s, size_t len) {\n    addReplyString(c,\"+\",1);\n    addReplyString(c,s,len);\n    addReplyString(c,\"\\r\\n\",2);\n}\n\nvoid addReplyStatus(client *c, const char *status) {\n    addReplyStatusLength(c,status,strlen(status));\n}\n\nvoid addReplyStatusFormat(client *c, const char *fmt, ...) {\n    va_list ap;\n    va_start(ap,fmt);\n    sds s = sdscatvprintf(sdsempty(),fmt,ap);\n    va_end(ap);\n    addReplyStatusLength(c,s,sdslen(s));\n    sdsfree(s);\n}\n\n/* Adds an empty object to the reply list that will contain the multi bulk\n * length, which is not known when this function is called. */\nvoid *addDeferredMultiBulkLength(client *c) {\n    /* Note that we install the write event here even if the object is not\n     * ready to be sent, since we are sure that before returning to the\n     * event loop setDeferredMultiBulkLength() will be called. */\n    if (prepareClientToWrite(c) != C_OK) return NULL;\n    listAddNodeTail(c->reply,createObject(OBJ_STRING,NULL));\n    return listLast(c->reply);\n}\n\n/* Populate the length object and try gluing it to the next chunk. */\nvoid setDeferredMultiBulkLength(client *c, void *node, long length) {\n    listNode *ln = (listNode*)node;\n    robj *len, *next;\n\n    /* Abort when *node is NULL (see addDeferredMultiBulkLength). */\n    if (node == NULL) return;\n\n    len = listNodeValue(ln);\n    len->ptr = sdscatprintf(sdsempty(),\"*%ld\\r\\n\",length);\n    len->encoding = OBJ_ENCODING_RAW; /* in case it was an EMBSTR. */\n    c->reply_bytes += sdsZmallocSize(len->ptr);\n    if (ln->next != NULL) {\n        next = listNodeValue(ln->next);\n\n        /* Only glue when the next node is non-NULL (an sds in this case) */\n        if (next->ptr != NULL) {\n            c->reply_bytes -= sdsZmallocSize(len->ptr);\n            c->reply_bytes -= getStringObjectSdsUsedMemory(next);\n            len->ptr = sdscatlen(len->ptr,next->ptr,sdslen(next->ptr));\n            c->reply_bytes += sdsZmallocSize(len->ptr);\n            listDelNode(c->reply,ln->next);\n        }\n    }\n    asyncCloseClientOnOutputBufferLimitReached(c);\n}\n\n/* Add a double as a bulk reply */\nvoid addReplyDouble(client *c, double d) {\n    char dbuf[128], sbuf[128];\n    int dlen, slen;\n    if (isinf(d)) {\n        /* Libc in odd systems (Hi Solaris!) will format infinite in a\n         * different way, so better to handle it in an explicit way. */\n        addReplyBulkCString(c, d > 0 ? \"inf\" : \"-inf\");\n    } else {\n        dlen = snprintf(dbuf,sizeof(dbuf),\"%.17g\",d);\n        slen = snprintf(sbuf,sizeof(sbuf),\"$%d\\r\\n%s\\r\\n\",dlen,dbuf);\n        addReplyString(c,sbuf,slen);\n    }\n}\n\n/* Add a long double as a bulk reply, but uses a human readable formatting\n * of the double instead of exposing the crude behavior of doubles to the\n * dear user. */\nvoid addReplyHumanLongDouble(client *c, long double d) {\n    robj *o = createStringObjectFromLongDouble(d,1);\n    addReplyBulk(c,o);\n    decrRefCount(o);\n}\n\n/* Add a long long as integer reply or bulk len / multi bulk count.\n * Basically this is used to output <prefix><long long><crlf>. */\nvoid addReplyLongLongWithPrefix(client *c, long long ll, char prefix) {\n    char buf[128];\n    int len;\n\n    /* Things like $3\\r\\n or *2\\r\\n are emitted very often by the protocol\n     * so we have a few shared objects to use if the integer is small\n     * like it is most of the times. */\n    if (prefix == '*' && ll < OBJ_SHARED_BULKHDR_LEN && ll >= 0) {\n        addReply(c,shared.mbulkhdr[ll]);\n        return;\n    } else if (prefix == '$' && ll < OBJ_SHARED_BULKHDR_LEN && ll >= 0) {\n        addReply(c,shared.bulkhdr[ll]);\n        return;\n    }\n\n    buf[0] = prefix;\n    len = ll2string(buf+1,sizeof(buf)-1,ll);\n    buf[len+1] = '\\r';\n    buf[len+2] = '\\n';\n    addReplyString(c,buf,len+3);\n}\n\nvoid addReplyLongLong(client *c, long long ll) {\n    if (ll == 0)\n        addReply(c,shared.czero);\n    else if (ll == 1)\n        addReply(c,shared.cone);\n    else\n        addReplyLongLongWithPrefix(c,ll,':');\n}\n\nvoid addReplyMultiBulkLen(client *c, long length) {\n    if (length < OBJ_SHARED_BULKHDR_LEN)\n        addReply(c,shared.mbulkhdr[length]);\n    else\n        addReplyLongLongWithPrefix(c,length,'*');\n}\n\n/* Create the length prefix of a bulk reply, example: $2234 */\nvoid addReplyBulkLen(client *c, robj *obj) {\n    size_t len;\n\n    if (sdsEncodedObject(obj)) {\n        len = sdslen(obj->ptr);\n    } else {\n        long n = (long)obj->ptr;\n\n        /* Compute how many bytes will take this integer as a radix 10 string */\n        len = 1;\n        if (n < 0) {\n            len++;\n            n = -n;\n        }\n        while((n = n/10) != 0) {\n            len++;\n        }\n    }\n\n    if (len < OBJ_SHARED_BULKHDR_LEN)\n        addReply(c,shared.bulkhdr[len]);\n    else\n        addReplyLongLongWithPrefix(c,len,'$');\n}\n\n/* Add a Redis Object as a bulk reply */\nvoid addReplyBulk(client *c, robj *obj) {\n    addReplyBulkLen(c,obj);\n    addReply(c,obj);\n    addReply(c,shared.crlf);\n}\n\n/* Add a C buffer as bulk reply */\nvoid addReplyBulkCBuffer(client *c, const void *p, size_t len) {\n    addReplyLongLongWithPrefix(c,len,'$');\n    addReplyString(c,p,len);\n    addReply(c,shared.crlf);\n}\n\n/* Add sds to reply (takes ownership of sds and frees it) */\nvoid addReplyBulkSds(client *c, sds s)  {\n    addReplySds(c,sdscatfmt(sdsempty(),\"$%u\\r\\n\",\n        (unsigned long)sdslen(s)));\n    addReplySds(c,s);\n    addReply(c,shared.crlf);\n}\n\n/* Add a C nul term string as bulk reply */\nvoid addReplyBulkCString(client *c, const char *s) {\n    if (s == NULL) {\n        addReply(c,shared.nullbulk);\n    } else {\n        addReplyBulkCBuffer(c,s,strlen(s));\n    }\n}\n\n/* Add a long long as a bulk reply */\nvoid addReplyBulkLongLong(client *c, long long ll) {\n    char buf[64];\n    int len;\n\n    len = ll2string(buf,64,ll);\n    addReplyBulkCBuffer(c,buf,len);\n}\n\n/* Copy 'src' client output buffers into 'dst' client output buffers.\n * The function takes care of freeing the old output buffers of the\n * destination client. */\nvoid copyClientOutputBuffer(client *dst, client *src) {\n    listRelease(dst->reply);\n    dst->reply = listDup(src->reply);\n    memcpy(dst->buf,src->buf,src->bufpos);\n    dst->bufpos = src->bufpos;\n    dst->reply_bytes = src->reply_bytes;\n}\n\n/* Return true if the specified client has pending reply buffers to write to\n * the socket. */\nint clientHasPendingReplies(client *c) {\n    return c->bufpos || listLength(c->reply);\n}\n\n#define MAX_ACCEPTS_PER_CALL 1000\nstatic void acceptCommonHandler(int fd, int flags, char *ip) {\n    client *c;\n    if ((c = createClient(fd)) == NULL) {\n        serverLog(LL_WARNING,\n            \"Error registering fd event for the new client: %s (fd=%d)\",\n            strerror(errno),fd);\n        close(fd); /* May be already closed, just ignore errors */\n        return;\n    }\n    /* If maxclient directive is set and this is one client more... close the\n     * connection. Note that we create the client instead to check before\n     * for this condition, since now the socket is already set in non-blocking\n     * mode and we can send an error for free using the Kernel I/O */\n    if (listLength(server.clients) > server.maxclients) {\n        char *err = \"-ERR max number of clients reached\\r\\n\";\n\n        /* That's a best effort error message, don't check write errors */\n        if (write(c->fd,err,strlen(err)) == -1) {\n            /* Nothing to do, Just to avoid the warning... */\n        }\n        server.stat_rejected_conn++;\n        freeClient(c);\n        return;\n    }\n\n    /* If the server is running in protected mode (the default) and there\n     * is no password set, nor a specific interface is bound, we don't accept\n     * requests from non loopback interfaces. Instead we try to explain the\n     * user what to do to fix it if needed. */\n    if (server.protected_mode &&\n        server.bindaddr_count == 0 &&\n        server.requirepass == NULL &&\n        !(flags & CLIENT_UNIX_SOCKET) &&\n        ip != NULL)\n    {\n        if (strcmp(ip,\"127.0.0.1\") && strcmp(ip,\"::1\")) {\n            char *err =\n                \"-DENIED Redis is running in protected mode because protected \"\n                \"mode is enabled, no bind address was specified, no \"\n                \"authentication password is requested to clients. In this mode \"\n                \"connections are only accepted from the loopback interface. \"\n                \"If you want to connect from external computers to Redis you \"\n                \"may adopt one of the following solutions: \"\n                \"1) Just disable protected mode sending the command \"\n                \"'CONFIG SET protected-mode no' from the loopback interface \"\n                \"by connecting to Redis from the same host the server is \"\n                \"running, however MAKE SURE Redis is not publicly accessible \"\n                \"from internet if you do so. Use CONFIG REWRITE to make this \"\n                \"change permanent. \"\n                \"2) Alternatively you can just disable the protected mode by \"\n                \"editing the Redis configuration file, and setting the protected \"\n                \"mode option to 'no', and then restarting the server. \"\n                \"3) If you started the server manually just for testing, restart \"\n                \"it with the '--protected-mode no' option. \"\n                \"4) Setup a bind address or an authentication password. \"\n                \"NOTE: You only need to do one of the above things in order for \"\n                \"the server to start accepting connections from the outside.\\r\\n\";\n            if (write(c->fd,err,strlen(err)) == -1) {\n                /* Nothing to do, Just to avoid the warning... */\n            }\n            server.stat_rejected_conn++;\n            freeClient(c);\n            return;\n        }\n    }\n\n    server.stat_numconnections++;\n    c->flags |= flags;\n}\n\nvoid acceptTcpHandler(aeEventLoop *el, int fd, void *privdata, int mask) {\n    int cport, cfd, max = MAX_ACCEPTS_PER_CALL;\n    char cip[NET_IP_STR_LEN];\n    UNUSED(el);\n    UNUSED(mask);\n    UNUSED(privdata);\n\n    while(max--) {\n        cfd = anetTcpAccept(server.neterr, fd, cip, sizeof(cip), &cport);\n        if (cfd == ANET_ERR) {\n            if (errno != EWOULDBLOCK)\n                serverLog(LL_WARNING,\n                    \"Accepting client connection: %s\", server.neterr);\n            return;\n        }\n        serverLog(LL_VERBOSE,\"Accepted %s:%d\", cip, cport);\n        acceptCommonHandler(cfd,0,cip);\n    }\n}\n\nvoid acceptUnixHandler(aeEventLoop *el, int fd, void *privdata, int mask) {\n    int cfd, max = MAX_ACCEPTS_PER_CALL;\n    UNUSED(el);\n    UNUSED(mask);\n    UNUSED(privdata);\n\n    while(max--) {\n        cfd = anetUnixAccept(server.neterr, fd);\n        if (cfd == ANET_ERR) {\n            if (errno != EWOULDBLOCK)\n                serverLog(LL_WARNING,\n                    \"Accepting client connection: %s\", server.neterr);\n            return;\n        }\n        serverLog(LL_VERBOSE,\"Accepted connection to %s\", server.unixsocket);\n        acceptCommonHandler(cfd,CLIENT_UNIX_SOCKET,NULL);\n    }\n}\n\nstatic void freeClientArgv(client *c) {\n    int j;\n    for (j = 0; j < c->argc; j++)\n        decrRefCount(c->argv[j]);\n    c->argc = 0;\n    c->cmd = NULL;\n}\n\n/* Close all the slaves connections. This is useful in chained replication\n * when we resync with our own master and want to force all our slaves to\n * resync with us as well. */\nvoid disconnectSlaves(void) {\n    while (listLength(server.slaves)) {\n        listNode *ln = listFirst(server.slaves);\n        freeClient((client*)ln->value);\n    }\n}\n\n/* Remove the specified client from global lists where the client could\n * be referenced, not including the Pub/Sub channels.\n * This is used by freeClient() and replicationCacheMaster(). */\nvoid unlinkClient(client *c) {\n    listNode *ln;\n\n    /* If this is marked as current client unset it. */\n    if (server.current_client == c) server.current_client = NULL;\n\n    /* Certain operations must be done only if the client has an active socket.\n     * If the client was already unlinked or if it's a \"fake client\" the\n     * fd is already set to -1. */\n    if (c->fd != -1) {\n        /* Remove from the list of active clients. */\n        ln = listSearchKey(server.clients,c);\n        serverAssert(ln != NULL);\n        listDelNode(server.clients,ln);\n\n        /* Unregister async I/O handlers and close the socket. */\n        aeDeleteFileEvent(server.el,c->fd,AE_READABLE);\n        aeDeleteFileEvent(server.el,c->fd,AE_WRITABLE);\n        close(c->fd);\n        c->fd = -1;\n    }\n\n    /* Remove from the list of pending writes if needed. */\n    if (c->flags & CLIENT_PENDING_WRITE) {\n        ln = listSearchKey(server.clients_pending_write,c);\n        serverAssert(ln != NULL);\n        listDelNode(server.clients_pending_write,ln);\n        c->flags &= ~CLIENT_PENDING_WRITE;\n    }\n\n    /* When client was just unblocked because of a blocking operation,\n     * remove it from the list of unblocked clients. */\n    if (c->flags & CLIENT_UNBLOCKED) {\n        ln = listSearchKey(server.unblocked_clients,c);\n        serverAssert(ln != NULL);\n        listDelNode(server.unblocked_clients,ln);\n        c->flags &= ~CLIENT_UNBLOCKED;\n    }\n}\n\nvoid freeClient(client *c) {\n    listNode *ln;\n\n    /* If it is our master that's beging disconnected we should make sure\n     * to cache the state to try a partial resynchronization later.\n     *\n     * Note that before doing this we make sure that the client is not in\n     * some unexpected state, by checking its flags. */\n    if (server.master && c->flags & CLIENT_MASTER) {\n        serverLog(LL_WARNING,\"Connection with master lost.\");\n        if (!(c->flags & (CLIENT_CLOSE_AFTER_REPLY|\n                          CLIENT_CLOSE_ASAP|\n                          CLIENT_BLOCKED|\n                          CLIENT_UNBLOCKED)))\n        {\n            replicationCacheMaster(c);\n            return;\n        }\n    }\n\n    /* Log link disconnection with slave */\n    if ((c->flags & CLIENT_SLAVE) && !(c->flags & CLIENT_MONITOR)) {\n        serverLog(LL_WARNING,\"Connection with slave %s lost.\",\n            replicationGetSlaveName(c));\n    }\n\n    /* Free the query buffer */\n    sdsfree(c->querybuf);\n    c->querybuf = NULL;\n\n    /* Deallocate structures used to block on blocking ops. */\n    if (c->flags & CLIENT_BLOCKED) unblockClient(c);\n    dictRelease(c->bpop.keys);\n\n    /* UNWATCH all the keys */\n    unwatchAllKeys(c);\n    listRelease(c->watched_keys);\n\n    /* Unsubscribe from all the pubsub channels */\n    pubsubUnsubscribeAllChannels(c,0);\n    pubsubUnsubscribeAllPatterns(c,0);\n    dictRelease(c->pubsub_channels);\n    listRelease(c->pubsub_patterns);\n\n    /* Free data structures. */\n    listRelease(c->reply);\n    freeClientArgv(c);\n\n    /* Unlink the client: this will close the socket, remove the I/O\n     * handlers, and remove references of the client from different\n     * places where active clients may be referenced. */\n    unlinkClient(c);\n\n    /* Master/slave cleanup Case 1:\n     * we lost the connection with a slave. */\n    if (c->flags & CLIENT_SLAVE) {\n        if (c->replstate == SLAVE_STATE_SEND_BULK) {\n            if (c->repldbfd != -1) close(c->repldbfd);\n            if (c->replpreamble) sdsfree(c->replpreamble);\n        }\n        list *l = (c->flags & CLIENT_MONITOR) ? server.monitors : server.slaves;\n        ln = listSearchKey(l,c);\n        serverAssert(ln != NULL);\n        listDelNode(l,ln);\n        /* We need to remember the time when we started to have zero\n         * attached slaves, as after some time we'll free the replication\n         * backlog. */\n        if (c->flags & CLIENT_SLAVE && listLength(server.slaves) == 0)\n            server.repl_no_slaves_since = server.unixtime;\n        refreshGoodSlavesCount();\n    }\n\n    /* Master/slave cleanup Case 2:\n     * we lost the connection with the master. */\n    if (c->flags & CLIENT_MASTER) replicationHandleMasterDisconnection();\n\n    /* If this client was scheduled for async freeing we need to remove it\n     * from the queue. */\n    if (c->flags & CLIENT_CLOSE_ASAP) {\n        ln = listSearchKey(server.clients_to_close,c);\n        serverAssert(ln != NULL);\n        listDelNode(server.clients_to_close,ln);\n    }\n\n    /* Release other dynamically allocated client structure fields,\n     * and finally release the client structure itself. */\n    if (c->name) decrRefCount(c->name);\n    zfree(c->argv);\n    freeClientMultiState(c);\n    sdsfree(c->peerid);\n    zfree(c);\n}\n\n/* Schedule a client to free it at a safe time in the serverCron() function.\n * This function is useful when we need to terminate a client but we are in\n * a context where calling freeClient() is not possible, because the client\n * should be valid for the continuation of the flow of the program. */\nvoid freeClientAsync(client *c) {\n    if (c->flags & CLIENT_CLOSE_ASAP || c->flags & CLIENT_LUA) return;\n    c->flags |= CLIENT_CLOSE_ASAP;\n    listAddNodeTail(server.clients_to_close,c);\n}\n\nvoid freeClientsInAsyncFreeQueue(void) {\n    while (listLength(server.clients_to_close)) {\n        listNode *ln = listFirst(server.clients_to_close);\n        client *c = listNodeValue(ln);\n\n        c->flags &= ~CLIENT_CLOSE_ASAP;\n        freeClient(c);\n        listDelNode(server.clients_to_close,ln);\n    }\n}\n\n/* Write data in output buffers to client. Return C_OK if the client\n * is still valid after the call, C_ERR if it was freed. */\nint writeToClient(int fd, client *c, int handler_installed) {\n    ssize_t nwritten = 0, totwritten = 0;\n    size_t objlen;\n    size_t objmem;\n    robj *o;\n\n    while(clientHasPendingReplies(c)) {\n        if (c->bufpos > 0) {\n            nwritten = write(fd,c->buf+c->sentlen,c->bufpos-c->sentlen);\n            if (nwritten <= 0) break;\n            c->sentlen += nwritten;\n            totwritten += nwritten;\n\n            /* If the buffer was sent, set bufpos to zero to continue with\n             * the remainder of the reply. */\n            if ((int)c->sentlen == c->bufpos) {\n                c->bufpos = 0;\n                c->sentlen = 0;\n            }\n        } else {\n            o = listNodeValue(listFirst(c->reply));\n            objlen = sdslen(o->ptr);\n            objmem = getStringObjectSdsUsedMemory(o);\n\n            if (objlen == 0) {\n                listDelNode(c->reply,listFirst(c->reply));\n                c->reply_bytes -= objmem;\n                continue;\n            }\n\n            nwritten = write(fd, ((char*)o->ptr)+c->sentlen,objlen-c->sentlen);\n            if (nwritten <= 0) break;\n            c->sentlen += nwritten;\n            totwritten += nwritten;\n\n            /* If we fully sent the object on head go to the next one */\n            if (c->sentlen == objlen) {\n                listDelNode(c->reply,listFirst(c->reply));\n                c->sentlen = 0;\n                c->reply_bytes -= objmem;\n            }\n        }\n        /* Note that we avoid to send more than NET_MAX_WRITES_PER_EVENT\n         * bytes, in a single threaded server it's a good idea to serve\n         * other clients as well, even if a very large request comes from\n         * super fast link that is always able to accept data (in real world\n         * scenario think about 'KEYS *' against the loopback interface).\n         *\n         * However if we are over the maxmemory limit we ignore that and\n         * just deliver as much data as it is possible to deliver. */\n        server.stat_net_output_bytes += totwritten;\n        if (totwritten > NET_MAX_WRITES_PER_EVENT &&\n            (server.maxmemory == 0 ||\n             zmalloc_used_memory() < server.maxmemory)) break;\n    }\n    if (nwritten == -1) {\n        if (errno == EAGAIN) {\n            nwritten = 0;\n        } else {\n            serverLog(LL_VERBOSE,\n                \"Error writing to client: %s\", strerror(errno));\n            freeClient(c);\n            return C_ERR;\n        }\n    }\n    if (totwritten > 0) {\n        /* For clients representing masters we don't count sending data\n         * as an interaction, since we always send REPLCONF ACK commands\n         * that take some time to just fill the socket output buffer.\n         * We just rely on data / pings received for timeout detection. */\n        if (!(c->flags & CLIENT_MASTER)) c->lastinteraction = server.unixtime;\n    }\n    if (!clientHasPendingReplies(c)) {\n        c->sentlen = 0;\n        if (handler_installed) aeDeleteFileEvent(server.el,c->fd,AE_WRITABLE);\n\n        /* Close connection after entire reply has been sent. */\n        if (c->flags & CLIENT_CLOSE_AFTER_REPLY) {\n            freeClient(c);\n            return C_ERR;\n        }\n    }\n    return C_OK;\n}\n\n/* Write event handler. Just send data to the client. */\nvoid sendReplyToClient(aeEventLoop *el, int fd, void *privdata, int mask) {\n    UNUSED(el);\n    UNUSED(mask);\n    writeToClient(fd,privdata,1);\n}\n\n/* This function is called just before entering the event loop, in the hope\n * we can just write the replies to the client output buffer without any\n * need to use a syscall in order to install the writable event handler,\n * get it called, and so forth. */\nint handleClientsWithPendingWrites(void) {\n    listIter li;\n    listNode *ln;\n    int processed = listLength(server.clients_pending_write);\n\n    listRewind(server.clients_pending_write,&li);\n    while((ln = listNext(&li))) {\n        client *c = listNodeValue(ln);\n        c->flags &= ~CLIENT_PENDING_WRITE;\n        listDelNode(server.clients_pending_write,ln);\n\n        /* Try to write buffers to the client socket. */\n        if (writeToClient(c->fd,c,0) == C_ERR) continue;\n\n        /* If there is nothing left, do nothing. Otherwise install\n         * the write handler. */\n        if (clientHasPendingReplies(c) &&\n            aeCreateFileEvent(server.el, c->fd, AE_WRITABLE,\n                sendReplyToClient, c) == AE_ERR)\n        {\n            freeClientAsync(c);\n        }\n    }\n    return processed;\n}\n\n/* resetClient prepare the client to process the next command */\nvoid resetClient(client *c) {\n    redisCommandProc *prevcmd = c->cmd ? c->cmd->proc : NULL;\n\n    freeClientArgv(c);\n    c->reqtype = 0;\n    c->multibulklen = 0;\n    c->bulklen = -1;\n\n    /* We clear the ASKING flag as well if we are not inside a MULTI, and\n     * if what we just executed is not the ASKING command itself. */\n    if (!(c->flags & CLIENT_MULTI) && prevcmd != askingCommand)\n        c->flags &= ~CLIENT_ASKING;\n\n    /* Remove the CLIENT_REPLY_SKIP flag if any so that the reply\n     * to the next command will be sent, but set the flag if the command\n     * we just processed was \"CLIENT REPLY SKIP\". */\n    c->flags &= ~CLIENT_REPLY_SKIP;\n    if (c->flags & CLIENT_REPLY_SKIP_NEXT) {\n        c->flags |= CLIENT_REPLY_SKIP;\n        c->flags &= ~CLIENT_REPLY_SKIP_NEXT;\n    }\n}\n\nint processInlineBuffer(client *c) {\n    char *newline;\n    int argc, j;\n    sds *argv, aux;\n    size_t querylen;\n\n    /* Search for end of line */\n    newline = strchr(c->querybuf,'\\n');\n\n    /* Nothing to do without a \\r\\n */\n    if (newline == NULL) {\n        if (sdslen(c->querybuf) > PROTO_INLINE_MAX_SIZE) {\n            addReplyError(c,\"Protocol error: too big inline request\");\n            setProtocolError(c,0);\n        }\n        return C_ERR;\n    }\n\n    /* Handle the \\r\\n case. */\n    if (newline && newline != c->querybuf && *(newline-1) == '\\r')\n        newline--;\n\n    /* Split the input buffer up to the \\r\\n */\n    querylen = newline-(c->querybuf);\n    aux = sdsnewlen(c->querybuf,querylen);\n    argv = sdssplitargs(aux,&argc);\n    sdsfree(aux);\n    if (argv == NULL) {\n        addReplyError(c,\"Protocol error: unbalanced quotes in request\");\n        setProtocolError(c,0);\n        return C_ERR;\n    }\n\n    /* Newline from slaves can be used to refresh the last ACK time.\n     * This is useful for a slave to ping back while loading a big\n     * RDB file. */\n    if (querylen == 0 && c->flags & CLIENT_SLAVE)\n        c->repl_ack_time = server.unixtime;\n\n    /* Leave data after the first line of the query in the buffer */\n    sdsrange(c->querybuf,querylen+2,-1);\n\n    /* Setup argv array on client structure */\n    if (argc) {\n        if (c->argv) zfree(c->argv);\n        c->argv = zmalloc(sizeof(robj*)*argc);\n    }\n\n    /* Create redis objects for all arguments. */\n    for (c->argc = 0, j = 0; j < argc; j++) {\n        if (sdslen(argv[j])) {\n            c->argv[c->argc] = createObject(OBJ_STRING,argv[j]);\n            c->argc++;\n        } else {\n            sdsfree(argv[j]);\n        }\n    }\n    zfree(argv);\n    return C_OK;\n}\n\n/* Helper function. Trims query buffer to make the function that processes\n * multi bulk requests idempotent. */\nstatic void setProtocolError(client *c, int pos) {\n    if (server.verbosity <= LL_VERBOSE) {\n        sds client = catClientInfoString(sdsempty(),c);\n        serverLog(LL_VERBOSE,\n            \"Protocol error from client: %s\", client);\n        sdsfree(client);\n    }\n    c->flags |= CLIENT_CLOSE_AFTER_REPLY;\n    sdsrange(c->querybuf,pos,-1);\n}\n\nint processMultibulkBuffer(client *c) {\n    char *newline = NULL;\n    int pos = 0, ok;\n    long long ll;\n\n    if (c->multibulklen == 0) {\n        /* The client should have been reset */\n        serverAssertWithInfo(c,NULL,c->argc == 0);\n\n        /* Multi bulk length cannot be read without a \\r\\n */\n        newline = strchr(c->querybuf,'\\r');\n        if (newline == NULL) {\n            if (sdslen(c->querybuf) > PROTO_INLINE_MAX_SIZE) {\n                addReplyError(c,\"Protocol error: too big mbulk count string\");\n                setProtocolError(c,0);\n            }\n            return C_ERR;\n        }\n\n        /* Buffer should also contain \\n */\n        if (newline-(c->querybuf) > ((signed)sdslen(c->querybuf)-2))\n            return C_ERR;\n\n        /* We know for sure there is a whole line since newline != NULL,\n         * so go ahead and find out the multi bulk length. */\n        serverAssertWithInfo(c,NULL,c->querybuf[0] == '*');\n        ok = string2ll(c->querybuf+1,newline-(c->querybuf+1),&ll);\n        if (!ok || ll > 1024*1024) {\n            addReplyError(c,\"Protocol error: invalid multibulk length\");\n            setProtocolError(c,pos);\n            return C_ERR;\n        }\n\n        pos = (newline-c->querybuf)+2;\n        if (ll <= 0) {\n            sdsrange(c->querybuf,pos,-1);\n            return C_OK;\n        }\n\n        c->multibulklen = ll;\n\n        /* Setup argv array on client structure */\n        if (c->argv) zfree(c->argv);\n        c->argv = zmalloc(sizeof(robj*)*c->multibulklen);\n    }\n\n    serverAssertWithInfo(c,NULL,c->multibulklen > 0);\n    while(c->multibulklen) {\n        /* Read bulk length if unknown */\n        if (c->bulklen == -1) {\n            newline = strchr(c->querybuf+pos,'\\r');\n            if (newline == NULL) {\n                if (sdslen(c->querybuf) > PROTO_INLINE_MAX_SIZE) {\n                    addReplyError(c,\n                        \"Protocol error: too big bulk count string\");\n                    setProtocolError(c,0);\n                    return C_ERR;\n                }\n                break;\n            }\n\n            /* Buffer should also contain \\n */\n            if (newline-(c->querybuf) > ((signed)sdslen(c->querybuf)-2))\n                break;\n\n            if (c->querybuf[pos] != '$') {\n                addReplyErrorFormat(c,\n                    \"Protocol error: expected '$', got '%c'\",\n                    c->querybuf[pos]);\n                setProtocolError(c,pos);\n                return C_ERR;\n            }\n\n            ok = string2ll(c->querybuf+pos+1,newline-(c->querybuf+pos+1),&ll);\n            if (!ok || ll < 0 || ll > 512*1024*1024) {\n                addReplyError(c,\"Protocol error: invalid bulk length\");\n                setProtocolError(c,pos);\n                return C_ERR;\n            }\n\n            pos += newline-(c->querybuf+pos)+2;\n            if (ll >= PROTO_MBULK_BIG_ARG) {\n                size_t qblen;\n\n                /* If we are going to read a large object from network\n                 * try to make it likely that it will start at c->querybuf\n                 * boundary so that we can optimize object creation\n                 * avoiding a large copy of data. */\n                sdsrange(c->querybuf,pos,-1);\n                pos = 0;\n                qblen = sdslen(c->querybuf);\n                /* Hint the sds library about the amount of bytes this string is\n                 * going to contain. */\n                if (qblen < (size_t)ll+2)\n                    c->querybuf = sdsMakeRoomFor(c->querybuf,ll+2-qblen);\n            }\n            c->bulklen = ll;\n        }\n\n        /* Read bulk argument */\n        if (sdslen(c->querybuf)-pos < (unsigned)(c->bulklen+2)) {\n            /* Not enough data (+2 == trailing \\r\\n) */\n            break;\n        } else {\n            /* Optimization: if the buffer contains JUST our bulk element\n             * instead of creating a new object by *copying* the sds we\n             * just use the current sds string. */\n            if (pos == 0 &&\n                c->bulklen >= PROTO_MBULK_BIG_ARG &&\n                (signed) sdslen(c->querybuf) == c->bulklen+2)\n            {\n                c->argv[c->argc++] = createObject(OBJ_STRING,c->querybuf);\n                sdsIncrLen(c->querybuf,-2); /* remove CRLF */\n                /* Assume that if we saw a fat argument we'll see another one\n                 * likely... */\n                c->querybuf = sdsnewlen(NULL,c->bulklen+2);\n                sdsclear(c->querybuf);\n                pos = 0;\n            } else {\n                c->argv[c->argc++] =\n                    createStringObject(c->querybuf+pos,c->bulklen);\n                pos += c->bulklen+2;\n            }\n            c->bulklen = -1;\n            c->multibulklen--;\n        }\n    }\n\n    /* Trim to pos */\n    if (pos) sdsrange(c->querybuf,pos,-1);\n\n    /* We're done when c->multibulk == 0 */\n    if (c->multibulklen == 0) return C_OK;\n\n    /* Still not read to process the command */\n    return C_ERR;\n}\n\nvoid processInputBuffer(client *c) {\n    server.current_client = c;\n    /* Keep processing while there is something in the input buffer */\n    while(sdslen(c->querybuf)) {\n        /* Return if clients are paused. */\n        if (!(c->flags & CLIENT_SLAVE) && clientsArePaused()) break;\n\n        /* Immediately abort if the client is in the middle of something. */\n        if (c->flags & CLIENT_BLOCKED) break;\n\n        /* CLIENT_CLOSE_AFTER_REPLY closes the connection once the reply is\n         * written to the client. Make sure to not let the reply grow after\n         * this flag has been set (i.e. don't process more commands). */\n        if (c->flags & CLIENT_CLOSE_AFTER_REPLY) break;\n\n        /* Determine request type when unknown. */\n        if (!c->reqtype) {\n            if (c->querybuf[0] == '*') {\n                c->reqtype = PROTO_REQ_MULTIBULK;\n            } else {\n                c->reqtype = PROTO_REQ_INLINE;\n            }\n        }\n\n        if (c->reqtype == PROTO_REQ_INLINE) {\n            if (processInlineBuffer(c) != C_OK) break;\n        } else if (c->reqtype == PROTO_REQ_MULTIBULK) {\n            if (processMultibulkBuffer(c) != C_OK) break;\n        } else {\n            serverPanic(\"Unknown request type\");\n        }\n\n        /* Multibulk processing could see a <= 0 length. */\n        if (c->argc == 0) {\n            resetClient(c);\n        } else {\n            /* Only reset the client when the command was executed. */\n            if (processCommand(c) == C_OK)\n                resetClient(c);\n            /* freeMemoryIfNeeded may flush slave output buffers. This may result\n             * into a slave, that may be the active client, to be freed. */\n            if (server.current_client == NULL) break;\n        }\n    }\n    server.current_client = NULL;\n}\n\nvoid readQueryFromClient(aeEventLoop *el, int fd, void *privdata, int mask) {\n    client *c = (client*) privdata;\n    int nread, readlen;\n    size_t qblen;\n    UNUSED(el);\n    UNUSED(mask);\n\n    readlen = PROTO_IOBUF_LEN;\n    /* If this is a multi bulk request, and we are processing a bulk reply\n     * that is large enough, try to maximize the probability that the query\n     * buffer contains exactly the SDS string representing the object, even\n     * at the risk of requiring more read(2) calls. This way the function\n     * processMultiBulkBuffer() can avoid copying buffers to create the\n     * Redis Object representing the argument. */\n    if (c->reqtype == PROTO_REQ_MULTIBULK && c->multibulklen && c->bulklen != -1\n        && c->bulklen >= PROTO_MBULK_BIG_ARG)\n    {\n        int remaining = (unsigned)(c->bulklen+2)-sdslen(c->querybuf);\n\n        if (remaining < readlen) readlen = remaining;\n    }\n\n    qblen = sdslen(c->querybuf);\n    if (c->querybuf_peak < qblen) c->querybuf_peak = qblen;\n    c->querybuf = sdsMakeRoomFor(c->querybuf, readlen);\n    nread = read(fd, c->querybuf+qblen, readlen);\n    if (nread == -1) {\n        if (errno == EAGAIN) {\n            return;\n        } else {\n            serverLog(LL_VERBOSE, \"Reading from client: %s\",strerror(errno));\n            freeClient(c);\n            return;\n        }\n    } else if (nread == 0) {\n        serverLog(LL_VERBOSE, \"Client closed connection\");\n        freeClient(c);\n        return;\n    }\n\n    sdsIncrLen(c->querybuf,nread);\n    c->lastinteraction = server.unixtime;\n    if (c->flags & CLIENT_MASTER) c->reploff += nread;\n    server.stat_net_input_bytes += nread;\n    if (sdslen(c->querybuf) > server.client_max_querybuf_len) {\n        sds ci = catClientInfoString(sdsempty(),c), bytes = sdsempty();\n\n        bytes = sdscatrepr(bytes,c->querybuf,64);\n        serverLog(LL_WARNING,\"Closing client that reached max query buffer length: %s (qbuf initial bytes: %s)\", ci, bytes);\n        sdsfree(ci);\n        sdsfree(bytes);\n        freeClient(c);\n        return;\n    }\n    processInputBuffer(c);\n}\n\nvoid getClientsMaxBuffers(unsigned long *longest_output_list,\n                          unsigned long *biggest_input_buffer) {\n    client *c;\n    listNode *ln;\n    listIter li;\n    unsigned long lol = 0, bib = 0;\n\n    listRewind(server.clients,&li);\n    while ((ln = listNext(&li)) != NULL) {\n        c = listNodeValue(ln);\n\n        if (listLength(c->reply) > lol) lol = listLength(c->reply);\n        if (sdslen(c->querybuf) > bib) bib = sdslen(c->querybuf);\n    }\n    *longest_output_list = lol;\n    *biggest_input_buffer = bib;\n}\n\n/* A Redis \"Peer ID\" is a colon separated ip:port pair.\n * For IPv4 it's in the form x.y.z.k:port, example: \"127.0.0.1:1234\".\n * For IPv6 addresses we use [] around the IP part, like in \"[::1]:1234\".\n * For Unix sockets we use path:0, like in \"/tmp/redis:0\".\n *\n * A Peer ID always fits inside a buffer of NET_PEER_ID_LEN bytes, including\n * the null term.\n *\n * On failure the function still populates 'peerid' with the \"?:0\" string\n * in case you want to relax error checking or need to display something\n * anyway (see anetPeerToString implementation for more info). */\nvoid genClientPeerId(client *client, char *peerid,\n                            size_t peerid_len) {\n    if (client->flags & CLIENT_UNIX_SOCKET) {\n        /* Unix socket client. */\n        snprintf(peerid,peerid_len,\"%s:0\",server.unixsocket);\n    } else {\n        /* TCP client. */\n        anetFormatPeer(client->fd,peerid,peerid_len);\n    }\n}\n\n/* This function returns the client peer id, by creating and caching it\n * if client->peerid is NULL, otherwise returning the cached value.\n * The Peer ID never changes during the life of the client, however it\n * is expensive to compute. */\nchar *getClientPeerId(client *c) {\n    char peerid[NET_PEER_ID_LEN];\n\n    if (c->peerid == NULL) {\n        genClientPeerId(c,peerid,sizeof(peerid));\n        c->peerid = sdsnew(peerid);\n    }\n    return c->peerid;\n}\n\n/* Concatenate a string representing the state of a client in an human\n * readable format, into the sds string 's'. */\nsds catClientInfoString(sds s, client *client) {\n    char flags[16], events[3], *p;\n    int emask;\n\n    p = flags;\n    if (client->flags & CLIENT_SLAVE) {\n        if (client->flags & CLIENT_MONITOR)\n            *p++ = 'O';\n        else\n            *p++ = 'S';\n    }\n    if (client->flags & CLIENT_MASTER) *p++ = 'M';\n    if (client->flags & CLIENT_MULTI) *p++ = 'x';\n    if (client->flags & CLIENT_BLOCKED) *p++ = 'b';\n    if (client->flags & CLIENT_DIRTY_CAS) *p++ = 'd';\n    if (client->flags & CLIENT_CLOSE_AFTER_REPLY) *p++ = 'c';\n    if (client->flags & CLIENT_UNBLOCKED) *p++ = 'u';\n    if (client->flags & CLIENT_CLOSE_ASAP) *p++ = 'A';\n    if (client->flags & CLIENT_UNIX_SOCKET) *p++ = 'U';\n    if (client->flags & CLIENT_READONLY) *p++ = 'r';\n    if (p == flags) *p++ = 'N';\n    *p++ = '\\0';\n\n    emask = client->fd == -1 ? 0 : aeGetFileEvents(server.el,client->fd);\n    p = events;\n    if (emask & AE_READABLE) *p++ = 'r';\n    if (emask & AE_WRITABLE) *p++ = 'w';\n    *p = '\\0';\n    return sdscatfmt(s,\n        \"id=%U addr=%s fd=%i name=%s age=%I idle=%I flags=%s db=%i sub=%i psub=%i multi=%i qbuf=%U qbuf-free=%U obl=%U oll=%U omem=%U events=%s cmd=%s\",\n        (unsigned long long) client->id,\n        getClientPeerId(client),\n        client->fd,\n        client->name ? (char*)client->name->ptr : \"\",\n        (long long)(server.unixtime - client->ctime),\n        (long long)(server.unixtime - client->lastinteraction),\n        flags,\n        client->db->id,\n        (int) dictSize(client->pubsub_channels),\n        (int) listLength(client->pubsub_patterns),\n        (client->flags & CLIENT_MULTI) ? client->mstate.count : -1,\n        (unsigned long long) sdslen(client->querybuf),\n        (unsigned long long) sdsavail(client->querybuf),\n        (unsigned long long) client->bufpos,\n        (unsigned long long) listLength(client->reply),\n        (unsigned long long) getClientOutputBufferMemoryUsage(client),\n        events,\n        client->lastcmd ? client->lastcmd->name : \"NULL\");\n}\n\nsds getAllClientsInfoString(void) {\n    listNode *ln;\n    listIter li;\n    client *client;\n    sds o = sdsnewlen(NULL,200*listLength(server.clients));\n    sdsclear(o);\n    listRewind(server.clients,&li);\n    while ((ln = listNext(&li)) != NULL) {\n        client = listNodeValue(ln);\n        o = catClientInfoString(o,client);\n        o = sdscatlen(o,\"\\n\",1);\n    }\n    return o;\n}\n\nvoid clientCommand(client *c) {\n    listNode *ln;\n    listIter li;\n    client *client;\n\n    if (!strcasecmp(c->argv[1]->ptr,\"list\") && c->argc == 2) {\n        /* CLIENT LIST */\n        sds o = getAllClientsInfoString();\n        addReplyBulkCBuffer(c,o,sdslen(o));\n        sdsfree(o);\n    } else if (!strcasecmp(c->argv[1]->ptr,\"reply\") && c->argc == 3) {\n        /* CLIENT REPLY ON|OFF|SKIP */\n        if (!strcasecmp(c->argv[2]->ptr,\"on\")) {\n            c->flags &= ~(CLIENT_REPLY_SKIP|CLIENT_REPLY_OFF);\n            addReply(c,shared.ok);\n        } else if (!strcasecmp(c->argv[2]->ptr,\"off\")) {\n            c->flags |= CLIENT_REPLY_OFF;\n        } else if (!strcasecmp(c->argv[2]->ptr,\"skip\")) {\n            if (!(c->flags & CLIENT_REPLY_OFF))\n                c->flags |= CLIENT_REPLY_SKIP_NEXT;\n        } else {\n            addReply(c,shared.syntaxerr);\n            return;\n        }\n    } else if (!strcasecmp(c->argv[1]->ptr,\"kill\")) {\n        /* CLIENT KILL <ip:port>\n         * CLIENT KILL <option> [value] ... <option> [value] */\n        char *addr = NULL;\n        int type = -1;\n        uint64_t id = 0;\n        int skipme = 1;\n        int killed = 0, close_this_client = 0;\n\n        if (c->argc == 3) {\n            /* Old style syntax: CLIENT KILL <addr> */\n            addr = c->argv[2]->ptr;\n            skipme = 0; /* With the old form, you can kill yourself. */\n        } else if (c->argc > 3) {\n            int i = 2; /* Next option index. */\n\n            /* New style syntax: parse options. */\n            while(i < c->argc) {\n                int moreargs = c->argc > i+1;\n\n                if (!strcasecmp(c->argv[i]->ptr,\"id\") && moreargs) {\n                    long long tmp;\n\n                    if (getLongLongFromObjectOrReply(c,c->argv[i+1],&tmp,NULL)\n                        != C_OK) return;\n                    id = tmp;\n                } else if (!strcasecmp(c->argv[i]->ptr,\"type\") && moreargs) {\n                    type = getClientTypeByName(c->argv[i+1]->ptr);\n                    if (type == -1) {\n                        addReplyErrorFormat(c,\"Unknown client type '%s'\",\n                            (char*) c->argv[i+1]->ptr);\n                        return;\n                    }\n                } else if (!strcasecmp(c->argv[i]->ptr,\"addr\") && moreargs) {\n                    addr = c->argv[i+1]->ptr;\n                } else if (!strcasecmp(c->argv[i]->ptr,\"skipme\") && moreargs) {\n                    if (!strcasecmp(c->argv[i+1]->ptr,\"yes\")) {\n                        skipme = 1;\n                    } else if (!strcasecmp(c->argv[i+1]->ptr,\"no\")) {\n                        skipme = 0;\n                    } else {\n                        addReply(c,shared.syntaxerr);\n                        return;\n                    }\n                } else {\n                    addReply(c,shared.syntaxerr);\n                    return;\n                }\n                i += 2;\n            }\n        } else {\n            addReply(c,shared.syntaxerr);\n            return;\n        }\n\n        /* Iterate clients killing all the matching clients. */\n        listRewind(server.clients,&li);\n        while ((ln = listNext(&li)) != NULL) {\n            client = listNodeValue(ln);\n            if (addr && strcmp(getClientPeerId(client),addr) != 0) continue;\n            if (type != -1 && getClientType(client) != type) continue;\n            if (id != 0 && client->id != id) continue;\n            if (c == client && skipme) continue;\n\n            /* Kill it. */\n            if (c == client) {\n                close_this_client = 1;\n            } else {\n                freeClient(client);\n            }\n            killed++;\n        }\n\n        /* Reply according to old/new format. */\n        if (c->argc == 3) {\n            if (killed == 0)\n                addReplyError(c,\"No such client\");\n            else\n                addReply(c,shared.ok);\n        } else {\n            addReplyLongLong(c,killed);\n        }\n\n        /* If this client has to be closed, flag it as CLOSE_AFTER_REPLY\n         * only after we queued the reply to its output buffers. */\n        if (close_this_client) c->flags |= CLIENT_CLOSE_AFTER_REPLY;\n    } else if (!strcasecmp(c->argv[1]->ptr,\"setname\") && c->argc == 3) {\n        int j, len = sdslen(c->argv[2]->ptr);\n        char *p = c->argv[2]->ptr;\n\n        /* Setting the client name to an empty string actually removes\n         * the current name. */\n        if (len == 0) {\n            if (c->name) decrRefCount(c->name);\n            c->name = NULL;\n            addReply(c,shared.ok);\n            return;\n        }\n\n        /* Otherwise check if the charset is ok. We need to do this otherwise\n         * CLIENT LIST format will break. You should always be able to\n         * split by space to get the different fields. */\n        for (j = 0; j < len; j++) {\n            if (p[j] < '!' || p[j] > '~') { /* ASCII is assumed. */\n                addReplyError(c,\n                    \"Client names cannot contain spaces, \"\n                    \"newlines or special characters.\");\n                return;\n            }\n        }\n        if (c->name) decrRefCount(c->name);\n        c->name = c->argv[2];\n        incrRefCount(c->name);\n        addReply(c,shared.ok);\n    } else if (!strcasecmp(c->argv[1]->ptr,\"getname\") && c->argc == 2) {\n        if (c->name)\n            addReplyBulk(c,c->name);\n        else\n            addReply(c,shared.nullbulk);\n    } else if (!strcasecmp(c->argv[1]->ptr,\"pause\") && c->argc == 3) {\n        long long duration;\n\n        if (getTimeoutFromObjectOrReply(c,c->argv[2],&duration,UNIT_MILLISECONDS)\n                                        != C_OK) return;\n        pauseClients(duration);\n        addReply(c,shared.ok);\n    } else {\n        addReplyError(c, \"Syntax error, try CLIENT (LIST | KILL | GETNAME | SETNAME | PAUSE | REPLY)\");\n    }\n}\n\n/* Rewrite the command vector of the client. All the new objects ref count\n * is incremented. The old command vector is freed, and the old objects\n * ref count is decremented. */\nvoid rewriteClientCommandVector(client *c, int argc, ...) {\n    va_list ap;\n    int j;\n    robj **argv; /* The new argument vector */\n\n    argv = zmalloc(sizeof(robj*)*argc);\n    va_start(ap,argc);\n    for (j = 0; j < argc; j++) {\n        robj *a;\n\n        a = va_arg(ap, robj*);\n        argv[j] = a;\n        incrRefCount(a);\n    }\n    /* We free the objects in the original vector at the end, so we are\n     * sure that if the same objects are reused in the new vector the\n     * refcount gets incremented before it gets decremented. */\n    for (j = 0; j < c->argc; j++) decrRefCount(c->argv[j]);\n    zfree(c->argv);\n    /* Replace argv and argc with our new versions. */\n    c->argv = argv;\n    c->argc = argc;\n    c->cmd = lookupCommandOrOriginal(c->argv[0]->ptr);\n    serverAssertWithInfo(c,NULL,c->cmd != NULL);\n    va_end(ap);\n}\n\n/* Completely replace the client command vector with the provided one. */\nvoid replaceClientCommandVector(client *c, int argc, robj **argv) {\n    freeClientArgv(c);\n    zfree(c->argv);\n    c->argv = argv;\n    c->argc = argc;\n    c->cmd = lookupCommandOrOriginal(c->argv[0]->ptr);\n    serverAssertWithInfo(c,NULL,c->cmd != NULL);\n}\n\n/* Rewrite a single item in the command vector.\n * The new val ref count is incremented, and the old decremented.\n *\n * It is possible to specify an argument over the current size of the\n * argument vector: in this case the array of objects gets reallocated\n * and c->argc set to the max value. However it's up to the caller to\n *\n * 1. Make sure there are no \"holes\" and all the arguments are set.\n * 2. If the original argument vector was longer than the one we\n *    want to end with, it's up to the caller to set c->argc and\n *    free the no longer used objects on c->argv. */\nvoid rewriteClientCommandArgument(client *c, int i, robj *newval) {\n    robj *oldval;\n\n    if (i >= c->argc) {\n        c->argv = zrealloc(c->argv,sizeof(robj*)*(i+1));\n        c->argc = i+1;\n        c->argv[i] = NULL;\n    }\n    oldval = c->argv[i];\n    c->argv[i] = newval;\n    incrRefCount(newval);\n    if (oldval) decrRefCount(oldval);\n\n    /* If this is the command name make sure to fix c->cmd. */\n    if (i == 0) {\n        c->cmd = lookupCommandOrOriginal(c->argv[0]->ptr);\n        serverAssertWithInfo(c,NULL,c->cmd != NULL);\n    }\n}\n\n/* This function returns the number of bytes that Redis is virtually\n * using to store the reply still not read by the client.\n * It is \"virtual\" since the reply output list may contain objects that\n * are shared and are not really using additional memory.\n *\n * The function returns the total sum of the length of all the objects\n * stored in the output list, plus the memory used to allocate every\n * list node. The static reply buffer is not taken into account since it\n * is allocated anyway.\n *\n * Note: this function is very fast so can be called as many time as\n * the caller wishes. The main usage of this function currently is\n * enforcing the client output length limits. */\nunsigned long getClientOutputBufferMemoryUsage(client *c) {\n    unsigned long list_item_size = sizeof(listNode)+sizeof(robj);\n\n    return c->reply_bytes + (list_item_size*listLength(c->reply));\n}\n\n/* Get the class of a client, used in order to enforce limits to different\n * classes of clients.\n *\n * The function will return one of the following:\n * CLIENT_TYPE_NORMAL -> Normal client\n * CLIENT_TYPE_SLAVE  -> Slave or client executing MONITOR command\n * CLIENT_TYPE_PUBSUB -> Client subscribed to Pub/Sub channels\n * CLIENT_TYPE_MASTER -> The client representing our replication master.\n */\nint getClientType(client *c) {\n    if (c->flags & CLIENT_MASTER) return CLIENT_TYPE_MASTER;\n    if ((c->flags & CLIENT_SLAVE) && !(c->flags & CLIENT_MONITOR))\n        return CLIENT_TYPE_SLAVE;\n    if (c->flags & CLIENT_PUBSUB) return CLIENT_TYPE_PUBSUB;\n    return CLIENT_TYPE_NORMAL;\n}\n\nint getClientTypeByName(char *name) {\n    if (!strcasecmp(name,\"normal\")) return CLIENT_TYPE_NORMAL;\n    else if (!strcasecmp(name,\"slave\")) return CLIENT_TYPE_SLAVE;\n    else if (!strcasecmp(name,\"pubsub\")) return CLIENT_TYPE_PUBSUB;\n    else if (!strcasecmp(name,\"master\")) return CLIENT_TYPE_MASTER;\n    else return -1;\n}\n\nchar *getClientTypeName(int class) {\n    switch(class) {\n    case CLIENT_TYPE_NORMAL: return \"normal\";\n    case CLIENT_TYPE_SLAVE:  return \"slave\";\n    case CLIENT_TYPE_PUBSUB: return \"pubsub\";\n    case CLIENT_TYPE_MASTER: return \"master\";\n    default:                       return NULL;\n    }\n}\n\n/* The function checks if the client reached output buffer soft or hard\n * limit, and also update the state needed to check the soft limit as\n * a side effect.\n *\n * Return value: non-zero if the client reached the soft or the hard limit.\n *               Otherwise zero is returned. */\nint checkClientOutputBufferLimits(client *c) {\n    int soft = 0, hard = 0, class;\n    unsigned long used_mem = getClientOutputBufferMemoryUsage(c);\n\n    class = getClientType(c);\n    /* For the purpose of output buffer limiting, masters are handled\n     * like normal clients. */\n    if (class == CLIENT_TYPE_MASTER) class = CLIENT_TYPE_NORMAL;\n\n    if (server.client_obuf_limits[class].hard_limit_bytes &&\n        used_mem >= server.client_obuf_limits[class].hard_limit_bytes)\n        hard = 1;\n    if (server.client_obuf_limits[class].soft_limit_bytes &&\n        used_mem >= server.client_obuf_limits[class].soft_limit_bytes)\n        soft = 1;\n\n    /* We need to check if the soft limit is reached continuously for the\n     * specified amount of seconds. */\n    if (soft) {\n        if (c->obuf_soft_limit_reached_time == 0) {\n            c->obuf_soft_limit_reached_time = server.unixtime;\n            soft = 0; /* First time we see the soft limit reached */\n        } else {\n            time_t elapsed = server.unixtime - c->obuf_soft_limit_reached_time;\n\n            if (elapsed <=\n                server.client_obuf_limits[class].soft_limit_seconds) {\n                soft = 0; /* The client still did not reached the max number of\n                             seconds for the soft limit to be considered\n                             reached. */\n            }\n        }\n    } else {\n        c->obuf_soft_limit_reached_time = 0;\n    }\n    return soft || hard;\n}\n\n/* Asynchronously close a client if soft or hard limit is reached on the\n * output buffer size. The caller can check if the client will be closed\n * checking if the client CLIENT_CLOSE_ASAP flag is set.\n *\n * Note: we need to close the client asynchronously because this function is\n * called from contexts where the client can't be freed safely, i.e. from the\n * lower level functions pushing data inside the client output buffers. */\nvoid asyncCloseClientOnOutputBufferLimitReached(client *c) {\n    serverAssert(c->reply_bytes < SIZE_MAX-(1024*64));\n    if (c->reply_bytes == 0 || c->flags & CLIENT_CLOSE_ASAP) return;\n    if (checkClientOutputBufferLimits(c)) {\n        sds client = catClientInfoString(sdsempty(),c);\n\n        freeClientAsync(c);\n        serverLog(LL_WARNING,\"Client %s scheduled to be closed ASAP for overcoming of output buffer limits.\", client);\n        sdsfree(client);\n    }\n}\n\n/* Helper function used by freeMemoryIfNeeded() in order to flush slaves\n * output buffers without returning control to the event loop.\n * This is also called by SHUTDOWN for a best-effort attempt to send\n * slaves the latest writes. */\nvoid flushSlavesOutputBuffers(void) {\n    listIter li;\n    listNode *ln;\n\n    listRewind(server.slaves,&li);\n    while((ln = listNext(&li))) {\n        client *slave = listNodeValue(ln);\n        int events;\n\n        /* Note that the following will not flush output buffers of slaves\n         * in STATE_ONLINE but having put_online_on_ack set to true: in this\n         * case the writable event is never installed, since the purpose\n         * of put_online_on_ack is to postpone the moment it is installed.\n         * This is what we want since slaves in this state should not receive\n         * writes before the first ACK. */\n        events = aeGetFileEvents(server.el,slave->fd);\n        if (events & AE_WRITABLE &&\n            slave->replstate == SLAVE_STATE_ONLINE &&\n            clientHasPendingReplies(slave))\n        {\n            writeToClient(slave->fd,slave,0);\n        }\n    }\n}\n\n/* Pause clients up to the specified unixtime (in ms). While clients\n * are paused no command is processed from clients, so the data set can't\n * change during that time.\n *\n * However while this function pauses normal and Pub/Sub clients, slaves are\n * still served, so this function can be used on server upgrades where it is\n * required that slaves process the latest bytes from the replication stream\n * before being turned to masters.\n *\n * This function is also internally used by Redis Cluster for the manual\n * failover procedure implemented by CLUSTER FAILOVER.\n *\n * The function always succeed, even if there is already a pause in progress.\n * In such a case, the pause is extended if the duration is more than the\n * time left for the previous duration. However if the duration is smaller\n * than the time left for the previous pause, no change is made to the\n * left duration. */\nvoid pauseClients(mstime_t end) {\n    if (!server.clients_paused || end > server.clients_pause_end_time)\n        server.clients_pause_end_time = end;\n    server.clients_paused = 1;\n}\n\n/* Return non-zero if clients are currently paused. As a side effect the\n * function checks if the pause time was reached and clear it. */\nint clientsArePaused(void) {\n    if (server.clients_paused &&\n        server.clients_pause_end_time < server.mstime)\n    {\n        listNode *ln;\n        listIter li;\n        client *c;\n\n        server.clients_paused = 0;\n\n        /* Put all the clients in the unblocked clients queue in order to\n         * force the re-processing of the input buffer if any. */\n        listRewind(server.clients,&li);\n        while ((ln = listNext(&li)) != NULL) {\n            c = listNodeValue(ln);\n\n            /* Don't touch slaves and blocked clients. The latter pending\n             * requests be processed when unblocked. */\n            if (c->flags & (CLIENT_SLAVE|CLIENT_BLOCKED)) continue;\n            c->flags |= CLIENT_UNBLOCKED;\n            listAddNodeTail(server.unblocked_clients,c);\n        }\n    }\n    return server.clients_paused;\n}\n\n/* This function is called by Redis in order to process a few events from\n * time to time while blocked into some not interruptible operation.\n * This allows to reply to clients with the -LOADING error while loading the\n * data set at startup or after a full resynchronization with the master\n * and so forth.\n *\n * It calls the event loop in order to process a few events. Specifically we\n * try to call the event loop 4 times as long as we receive acknowledge that\n * some event was processed, in order to go forward with the accept, read,\n * write, close sequence needed to serve a client.\n *\n * The function returns the total number of events processed. */\nint processEventsWhileBlocked(void) {\n    int iterations = 4; /* See the function top-comment. */\n    int count = 0;\n    while (iterations--) {\n        int events = 0;\n        events += aeProcessEvents(server.el, AE_FILE_EVENTS|AE_DONT_WAIT);\n        events += handleClientsWithPendingWrites();\n        if (!events) break;\n        count += events;\n    }\n    return count;\n}\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/src/notify.c",
    "content": "/*\n * Copyright (c) 2013, Salvatore Sanfilippo <antirez at gmail dot com>\n * All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions are met:\n *\n *   * Redistributions of source code must retain the above copyright notice,\n *     this list of conditions and the following disclaimer.\n *   * Redistributions in binary form must reproduce the above copyright\n *     notice, this list of conditions and the following disclaimer in the\n *     documentation and/or other materials provided with the distribution.\n *   * Neither the name of Redis nor the names of its contributors may be used\n *     to endorse or promote products derived from this software without\n *     specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\"\n * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\n * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE\n * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR\n * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF\n * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS\n * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN\n * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)\n * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE\n * POSSIBILITY OF SUCH DAMAGE.\n */\n\n#include \"server.h\"\n\n/* This file implements keyspace events notification via Pub/Sub ad\n * described at http://redis.io/topics/keyspace-events. */\n\n/* Turn a string representing notification classes into an integer\n * representing notification classes flags xored.\n *\n * The function returns -1 if the input contains characters not mapping to\n * any class. */\nint keyspaceEventsStringToFlags(char *classes) {\n    char *p = classes;\n    int c, flags = 0;\n\n    while((c = *p++) != '\\0') {\n        switch(c) {\n        case 'A': flags |= NOTIFY_ALL; break;\n        case 'g': flags |= NOTIFY_GENERIC; break;\n        case '$': flags |= NOTIFY_STRING; break;\n        case 'l': flags |= NOTIFY_LIST; break;\n        case 's': flags |= NOTIFY_SET; break;\n        case 'h': flags |= NOTIFY_HASH; break;\n        case 'z': flags |= NOTIFY_ZSET; break;\n        case 'x': flags |= NOTIFY_EXPIRED; break;\n        case 'e': flags |= NOTIFY_EVICTED; break;\n        case 'K': flags |= NOTIFY_KEYSPACE; break;\n        case 'E': flags |= NOTIFY_KEYEVENT; break;\n        default: return -1;\n        }\n    }\n    return flags;\n}\n\n/* This function does exactly the revese of the function above: it gets\n * as input an integer with the xored flags and returns a string representing\n * the selected classes. The string returned is an sds string that needs to\n * be released with sdsfree(). */\nsds keyspaceEventsFlagsToString(int flags) {\n    sds res;\n\n    res = sdsempty();\n    if ((flags & NOTIFY_ALL) == NOTIFY_ALL) {\n        res = sdscatlen(res,\"A\",1);\n    } else {\n        if (flags & NOTIFY_GENERIC) res = sdscatlen(res,\"g\",1);\n        if (flags & NOTIFY_STRING) res = sdscatlen(res,\"$\",1);\n        if (flags & NOTIFY_LIST) res = sdscatlen(res,\"l\",1);\n        if (flags & NOTIFY_SET) res = sdscatlen(res,\"s\",1);\n        if (flags & NOTIFY_HASH) res = sdscatlen(res,\"h\",1);\n        if (flags & NOTIFY_ZSET) res = sdscatlen(res,\"z\",1);\n        if (flags & NOTIFY_EXPIRED) res = sdscatlen(res,\"x\",1);\n        if (flags & NOTIFY_EVICTED) res = sdscatlen(res,\"e\",1);\n    }\n    if (flags & NOTIFY_KEYSPACE) res = sdscatlen(res,\"K\",1);\n    if (flags & NOTIFY_KEYEVENT) res = sdscatlen(res,\"E\",1);\n    return res;\n}\n\n/* The API provided to the rest of the Redis core is a simple function:\n *\n * notifyKeyspaceEvent(char *event, robj *key, int dbid);\n *\n * 'event' is a C string representing the event name.\n * 'key' is a Redis object representing the key name.\n * 'dbid' is the database ID where the key lives.  */\nvoid notifyKeyspaceEvent(int type, char *event, robj *key, int dbid) {\n    sds chan;\n    robj *chanobj, *eventobj;\n    int len = -1;\n    char buf[24];\n\n    /* If notifications for this class of events are off, return ASAP. */\n    if (!(server.notify_keyspace_events & type)) return;\n\n    eventobj = createStringObject(event,strlen(event));\n\n    /* __keyspace@<db>__:<key> <event> notifications. */\n    if (server.notify_keyspace_events & NOTIFY_KEYSPACE) {\n        chan = sdsnewlen(\"__keyspace@\",11);\n        len = ll2string(buf,sizeof(buf),dbid);\n        chan = sdscatlen(chan, buf, len);\n        chan = sdscatlen(chan, \"__:\", 3);\n        chan = sdscatsds(chan, key->ptr);\n        chanobj = createObject(OBJ_STRING, chan);\n        pubsubPublishMessage(chanobj, eventobj);\n        decrRefCount(chanobj);\n    }\n\n    /* __keyevente@<db>__:<event> <key> notifications. */\n    if (server.notify_keyspace_events & NOTIFY_KEYEVENT) {\n        chan = sdsnewlen(\"__keyevent@\",11);\n        if (len == -1) len = ll2string(buf,sizeof(buf),dbid);\n        chan = sdscatlen(chan, buf, len);\n        chan = sdscatlen(chan, \"__:\", 3);\n        chan = sdscatsds(chan, eventobj->ptr);\n        chanobj = createObject(OBJ_STRING, chan);\n        pubsubPublishMessage(chanobj, key);\n        decrRefCount(chanobj);\n    }\n    decrRefCount(eventobj);\n}\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/src/object.c",
    "content": "/* Redis Object implementation.\n *\n * Copyright (c) 2009-2012, Salvatore Sanfilippo <antirez at gmail dot com>\n * All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions are met:\n *\n *   * Redistributions of source code must retain the above copyright notice,\n *     this list of conditions and the following disclaimer.\n *   * Redistributions in binary form must reproduce the above copyright\n *     notice, this list of conditions and the following disclaimer in the\n *     documentation and/or other materials provided with the distribution.\n *   * Neither the name of Redis nor the names of its contributors may be used\n *     to endorse or promote products derived from this software without\n *     specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\"\n * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\n * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE\n * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR\n * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF\n * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS\n * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN\n * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)\n * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE\n * POSSIBILITY OF SUCH DAMAGE.\n */\n\n#include \"server.h\"\n#include <math.h>\n#include <ctype.h>\n\n#ifdef __CYGWIN__\n#define strtold(a,b) ((long double)strtod((a),(b)))\n#endif\n\nrobj *createObject(int type, void *ptr) {\n    robj *o = zmalloc(sizeof(*o));\n    o->type = type;\n    o->encoding = OBJ_ENCODING_RAW;\n    o->ptr = ptr;\n    o->refcount = 1;\n\n    /* Set the LRU to the current lruclock (minutes resolution). */\n    o->lru = LRU_CLOCK();\n    return o;\n}\n\n/* Create a string object with encoding OBJ_ENCODING_RAW, that is a plain\n * string object where o->ptr points to a proper sds string. */\nrobj *createRawStringObject(const char *ptr, size_t len) {\n    return createObject(OBJ_STRING,sdsnewlen(ptr,len));\n}\n\n/* Create a string object with encoding OBJ_ENCODING_EMBSTR, that is\n * an object where the sds string is actually an unmodifiable string\n * allocated in the same chunk as the object itself. */\nrobj *createEmbeddedStringObject(const char *ptr, size_t len) {\n    robj *o = zmalloc(sizeof(robj)+sizeof(struct sdshdr8)+len+1);\n    struct sdshdr8 *sh = (void*)(o+1);\n\n    o->type = OBJ_STRING;\n    o->encoding = OBJ_ENCODING_EMBSTR;\n    o->ptr = sh+1;\n    o->refcount = 1;\n    o->lru = LRU_CLOCK();\n\n    sh->len = len;\n    sh->alloc = len;\n    sh->flags = SDS_TYPE_8;\n    if (ptr) {\n        memcpy(sh->buf,ptr,len);\n        sh->buf[len] = '\\0';\n    } else {\n        memset(sh->buf,0,len+1);\n    }\n    return o;\n}\n\n/* Create a string object with EMBSTR encoding if it is smaller than\n * REIDS_ENCODING_EMBSTR_SIZE_LIMIT, otherwise the RAW encoding is\n * used.\n *\n * The current limit of 39 is chosen so that the biggest string object\n * we allocate as EMBSTR will still fit into the 64 byte arena of jemalloc. */\n#define OBJ_ENCODING_EMBSTR_SIZE_LIMIT 44\nrobj *createStringObject(const char *ptr, size_t len) {\n    if (len <= OBJ_ENCODING_EMBSTR_SIZE_LIMIT)\n        return createEmbeddedStringObject(ptr,len);\n    else\n        return createRawStringObject(ptr,len);\n}\n\nrobj *createStringObjectFromLongLong(long long value) {\n    robj *o;\n    if (value >= 0 && value < OBJ_SHARED_INTEGERS) {\n        incrRefCount(shared.integers[value]);\n        o = shared.integers[value];\n    } else {\n        if (value >= LONG_MIN && value <= LONG_MAX) {\n            o = createObject(OBJ_STRING, NULL);\n            o->encoding = OBJ_ENCODING_INT;\n            o->ptr = (void*)((long)value);\n        } else {\n            o = createObject(OBJ_STRING,sdsfromlonglong(value));\n        }\n    }\n    return o;\n}\n\n/* Create a string object from a long double. If humanfriendly is non-zero\n * it does not use exponential format and trims trailing zeroes at the end,\n * however this results in loss of precision. Otherwise exp format is used\n * and the output of snprintf() is not modified.\n *\n * The 'humanfriendly' option is used for INCRBYFLOAT and HINCRBYFLOAT. */\nrobj *createStringObjectFromLongDouble(long double value, int humanfriendly) {\n    char buf[256];\n    int len;\n\n    if (isinf(value)) {\n        /* Libc in odd systems (Hi Solaris!) will format infinite in a\n         * different way, so better to handle it in an explicit way. */\n        if (value > 0) {\n            memcpy(buf,\"inf\",3);\n            len = 3;\n        } else {\n            memcpy(buf,\"-inf\",4);\n            len = 4;\n        }\n    } else if (humanfriendly) {\n        /* We use 17 digits precision since with 128 bit floats that precision\n         * after rounding is able to represent most small decimal numbers in a\n         * way that is \"non surprising\" for the user (that is, most small\n         * decimal numbers will be represented in a way that when converted\n         * back into a string are exactly the same as what the user typed.) */\n        len = snprintf(buf,sizeof(buf),\"%.17Lf\", value);\n        /* Now remove trailing zeroes after the '.' */\n        if (strchr(buf,'.') != NULL) {\n            char *p = buf+len-1;\n            while(*p == '0') {\n                p--;\n                len--;\n            }\n            if (*p == '.') len--;\n        }\n    } else {\n        len = snprintf(buf,sizeof(buf),\"%.17Lg\", value);\n    }\n    return createStringObject(buf,len);\n}\n\n/* Duplicate a string object, with the guarantee that the returned object\n * has the same encoding as the original one.\n *\n * This function also guarantees that duplicating a small integere object\n * (or a string object that contains a representation of a small integer)\n * will always result in a fresh object that is unshared (refcount == 1).\n *\n * The resulting object always has refcount set to 1. */\nrobj *dupStringObject(robj *o) {\n    robj *d;\n\n    serverAssert(o->type == OBJ_STRING);\n\n    switch(o->encoding) {\n    case OBJ_ENCODING_RAW:\n        return createRawStringObject(o->ptr,sdslen(o->ptr));\n    case OBJ_ENCODING_EMBSTR:\n        return createEmbeddedStringObject(o->ptr,sdslen(o->ptr));\n    case OBJ_ENCODING_INT:\n        d = createObject(OBJ_STRING, NULL);\n        d->encoding = OBJ_ENCODING_INT;\n        d->ptr = o->ptr;\n        return d;\n    default:\n        serverPanic(\"Wrong encoding.\");\n        break;\n    }\n}\n\nrobj *createQuicklistObject(void) {\n    quicklist *l = quicklistCreate();\n    robj *o = createObject(OBJ_LIST,l);\n    o->encoding = OBJ_ENCODING_QUICKLIST;\n    return o;\n}\n\nrobj *createZiplistObject(void) {\n    unsigned char *zl = ziplistNew();\n    robj *o = createObject(OBJ_LIST,zl);\n    o->encoding = OBJ_ENCODING_ZIPLIST;\n    return o;\n}\n\nrobj *createSetObject(void) {\n    dict *d = dictCreate(&setDictType,NULL);\n    robj *o = createObject(OBJ_SET,d);\n    o->encoding = OBJ_ENCODING_HT;\n    return o;\n}\n\nrobj *createIntsetObject(void) {\n    intset *is = intsetNew();\n    robj *o = createObject(OBJ_SET,is);\n    o->encoding = OBJ_ENCODING_INTSET;\n    return o;\n}\n\nrobj *createHashObject(void) {\n    unsigned char *zl = ziplistNew();\n    robj *o = createObject(OBJ_HASH, zl);\n    o->encoding = OBJ_ENCODING_ZIPLIST;\n    return o;\n}\n\nrobj *createZsetObject(void) {\n    zset *zs = zmalloc(sizeof(*zs));\n    robj *o;\n\n    zs->dict = dictCreate(&zsetDictType,NULL);\n    zs->zsl = zslCreate();\n    o = createObject(OBJ_ZSET,zs);\n    o->encoding = OBJ_ENCODING_SKIPLIST;\n    return o;\n}\n\nrobj *createZsetZiplistObject(void) {\n    unsigned char *zl = ziplistNew();\n    robj *o = createObject(OBJ_ZSET,zl);\n    o->encoding = OBJ_ENCODING_ZIPLIST;\n    return o;\n}\n\nvoid freeStringObject(robj *o) {\n    if (o->encoding == OBJ_ENCODING_RAW) {\n        sdsfree(o->ptr);\n    }\n}\n\nvoid freeListObject(robj *o) {\n    switch (o->encoding) {\n    case OBJ_ENCODING_QUICKLIST:\n        quicklistRelease(o->ptr);\n        break;\n    default:\n        serverPanic(\"Unknown list encoding type\");\n    }\n}\n\nvoid freeSetObject(robj *o) {\n    switch (o->encoding) {\n    case OBJ_ENCODING_HT:\n        dictRelease((dict*) o->ptr);\n        break;\n    case OBJ_ENCODING_INTSET:\n        zfree(o->ptr);\n        break;\n    default:\n        serverPanic(\"Unknown set encoding type\");\n    }\n}\n\nvoid freeZsetObject(robj *o) {\n    zset *zs;\n    switch (o->encoding) {\n    case OBJ_ENCODING_SKIPLIST:\n        zs = o->ptr;\n        dictRelease(zs->dict);\n        zslFree(zs->zsl);\n        zfree(zs);\n        break;\n    case OBJ_ENCODING_ZIPLIST:\n        zfree(o->ptr);\n        break;\n    default:\n        serverPanic(\"Unknown sorted set encoding\");\n    }\n}\n\nvoid freeHashObject(robj *o) {\n    switch (o->encoding) {\n    case OBJ_ENCODING_HT:\n        dictRelease((dict*) o->ptr);\n        break;\n    case OBJ_ENCODING_ZIPLIST:\n        zfree(o->ptr);\n        break;\n    default:\n        serverPanic(\"Unknown hash encoding type\");\n        break;\n    }\n}\n\nvoid incrRefCount(robj *o) {\n    o->refcount++;\n}\n\nvoid decrRefCount(robj *o) {\n    if (o->refcount <= 0) serverPanic(\"decrRefCount against refcount <= 0\");\n    if (o->refcount == 1) {\n        switch(o->type) {\n        case OBJ_STRING: freeStringObject(o); break;\n        case OBJ_LIST: freeListObject(o); break;\n        case OBJ_SET: freeSetObject(o); break;\n        case OBJ_ZSET: freeZsetObject(o); break;\n        case OBJ_HASH: freeHashObject(o); break;\n        default: serverPanic(\"Unknown object type\"); break;\n        }\n        zfree(o);\n    } else {\n        o->refcount--;\n    }\n}\n\n/* This variant of decrRefCount() gets its argument as void, and is useful\n * as free method in data structures that expect a 'void free_object(void*)'\n * prototype for the free method. */\nvoid decrRefCountVoid(void *o) {\n    decrRefCount(o);\n}\n\n/* This function set the ref count to zero without freeing the object.\n * It is useful in order to pass a new object to functions incrementing\n * the ref count of the received object. Example:\n *\n *    functionThatWillIncrementRefCount(resetRefCount(CreateObject(...)));\n *\n * Otherwise you need to resort to the less elegant pattern:\n *\n *    *obj = createObject(...);\n *    functionThatWillIncrementRefCount(obj);\n *    decrRefCount(obj);\n */\nrobj *resetRefCount(robj *obj) {\n    obj->refcount = 0;\n    return obj;\n}\n\nint checkType(client *c, robj *o, int type) {\n    if (o->type != type) {\n        addReply(c,shared.wrongtypeerr);\n        return 1;\n    }\n    return 0;\n}\n\nint isObjectRepresentableAsLongLong(robj *o, long long *llval) {\n    serverAssertWithInfo(NULL,o,o->type == OBJ_STRING);\n    if (o->encoding == OBJ_ENCODING_INT) {\n        if (llval) *llval = (long) o->ptr;\n        return C_OK;\n    } else {\n        return string2ll(o->ptr,sdslen(o->ptr),llval) ? C_OK : C_ERR;\n    }\n}\n\n/* Try to encode a string object in order to save space */\nrobj *tryObjectEncoding(robj *o) {\n    long value;\n    sds s = o->ptr;\n    size_t len;\n\n    /* Make sure this is a string object, the only type we encode\n     * in this function. Other types use encoded memory efficient\n     * representations but are handled by the commands implementing\n     * the type. */\n    serverAssertWithInfo(NULL,o,o->type == OBJ_STRING);\n\n    /* We try some specialized encoding only for objects that are\n     * RAW or EMBSTR encoded, in other words objects that are still\n     * in represented by an actually array of chars. */\n    if (!sdsEncodedObject(o)) return o;\n\n    /* It's not safe to encode shared objects: shared objects can be shared\n     * everywhere in the \"object space\" of Redis and may end in places where\n     * they are not handled. We handle them only as values in the keyspace. */\n     if (o->refcount > 1) return o;\n\n    /* Check if we can represent this string as a long integer.\n     * Note that we are sure that a string larger than 20 chars is not\n     * representable as a 32 nor 64 bit integer. */\n    len = sdslen(s);\n    if (len <= 20 && string2l(s,len,&value)) {\n        /* This object is encodable as a long. Try to use a shared object.\n         * Note that we avoid using shared integers when maxmemory is used\n         * because every object needs to have a private LRU field for the LRU\n         * algorithm to work well. */\n        if ((server.maxmemory == 0 ||\n             (server.maxmemory_policy != MAXMEMORY_VOLATILE_LRU &&\n              server.maxmemory_policy != MAXMEMORY_ALLKEYS_LRU)) &&\n            value >= 0 &&\n            value < OBJ_SHARED_INTEGERS)\n        {\n            decrRefCount(o);\n            incrRefCount(shared.integers[value]);\n            return shared.integers[value];\n        } else {\n            if (o->encoding == OBJ_ENCODING_RAW) sdsfree(o->ptr);\n            o->encoding = OBJ_ENCODING_INT;\n            o->ptr = (void*) value;\n            return o;\n        }\n    }\n\n    /* If the string is small and is still RAW encoded,\n     * try the EMBSTR encoding which is more efficient.\n     * In this representation the object and the SDS string are allocated\n     * in the same chunk of memory to save space and cache misses. */\n    if (len <= OBJ_ENCODING_EMBSTR_SIZE_LIMIT) {\n        robj *emb;\n\n        if (o->encoding == OBJ_ENCODING_EMBSTR) return o;\n        emb = createEmbeddedStringObject(s,sdslen(s));\n        decrRefCount(o);\n        return emb;\n    }\n\n    /* We can't encode the object...\n     *\n     * Do the last try, and at least optimize the SDS string inside\n     * the string object to require little space, in case there\n     * is more than 10% of free space at the end of the SDS string.\n     *\n     * We do that only for relatively large strings as this branch\n     * is only entered if the length of the string is greater than\n     * OBJ_ENCODING_EMBSTR_SIZE_LIMIT. */\n    if (o->encoding == OBJ_ENCODING_RAW &&\n        sdsavail(s) > len/10)\n    {\n        o->ptr = sdsRemoveFreeSpace(o->ptr);\n    }\n\n    /* Return the original object. */\n    return o;\n}\n\n/* Get a decoded version of an encoded object (returned as a new object).\n * If the object is already raw-encoded just increment the ref count. */\nrobj *getDecodedObject(robj *o) {\n    robj *dec;\n\n    if (sdsEncodedObject(o)) {\n        incrRefCount(o);\n        return o;\n    }\n    if (o->type == OBJ_STRING && o->encoding == OBJ_ENCODING_INT) {\n        char buf[32];\n\n        ll2string(buf,32,(long)o->ptr);\n        dec = createStringObject(buf,strlen(buf));\n        return dec;\n    } else {\n        serverPanic(\"Unknown encoding type\");\n    }\n}\n\n/* Compare two string objects via strcmp() or strcoll() depending on flags.\n * Note that the objects may be integer-encoded. In such a case we\n * use ll2string() to get a string representation of the numbers on the stack\n * and compare the strings, it's much faster than calling getDecodedObject().\n *\n * Important note: when REDIS_COMPARE_BINARY is used a binary-safe comparison\n * is used. */\n\n#define REDIS_COMPARE_BINARY (1<<0)\n#define REDIS_COMPARE_COLL (1<<1)\n\nint compareStringObjectsWithFlags(robj *a, robj *b, int flags) {\n    serverAssertWithInfo(NULL,a,a->type == OBJ_STRING && b->type == OBJ_STRING);\n    char bufa[128], bufb[128], *astr, *bstr;\n    size_t alen, blen, minlen;\n\n    if (a == b) return 0;\n    if (sdsEncodedObject(a)) {\n        astr = a->ptr;\n        alen = sdslen(astr);\n    } else {\n        alen = ll2string(bufa,sizeof(bufa),(long) a->ptr);\n        astr = bufa;\n    }\n    if (sdsEncodedObject(b)) {\n        bstr = b->ptr;\n        blen = sdslen(bstr);\n    } else {\n        blen = ll2string(bufb,sizeof(bufb),(long) b->ptr);\n        bstr = bufb;\n    }\n    if (flags & REDIS_COMPARE_COLL) {\n        return strcoll(astr,bstr);\n    } else {\n        int cmp;\n\n        minlen = (alen < blen) ? alen : blen;\n        cmp = memcmp(astr,bstr,minlen);\n        if (cmp == 0) return alen-blen;\n        return cmp;\n    }\n}\n\n/* Wrapper for compareStringObjectsWithFlags() using binary comparison. */\nint compareStringObjects(robj *a, robj *b) {\n    return compareStringObjectsWithFlags(a,b,REDIS_COMPARE_BINARY);\n}\n\n/* Wrapper for compareStringObjectsWithFlags() using collation. */\nint collateStringObjects(robj *a, robj *b) {\n    return compareStringObjectsWithFlags(a,b,REDIS_COMPARE_COLL);\n}\n\n/* Equal string objects return 1 if the two objects are the same from the\n * point of view of a string comparison, otherwise 0 is returned. Note that\n * this function is faster then checking for (compareStringObject(a,b) == 0)\n * because it can perform some more optimization. */\nint equalStringObjects(robj *a, robj *b) {\n    if (a->encoding == OBJ_ENCODING_INT &&\n        b->encoding == OBJ_ENCODING_INT){\n        /* If both strings are integer encoded just check if the stored\n         * long is the same. */\n        return a->ptr == b->ptr;\n    } else {\n        return compareStringObjects(a,b) == 0;\n    }\n}\n\nsize_t stringObjectLen(robj *o) {\n    serverAssertWithInfo(NULL,o,o->type == OBJ_STRING);\n    if (sdsEncodedObject(o)) {\n        return sdslen(o->ptr);\n    } else {\n        return sdigits10((long)o->ptr);\n    }\n}\n\nint getDoubleFromObject(robj *o, double *target) {\n    double value;\n    char *eptr;\n\n    if (o == NULL) {\n        value = 0;\n    } else {\n        serverAssertWithInfo(NULL,o,o->type == OBJ_STRING);\n        if (sdsEncodedObject(o)) {\n            errno = 0;\n            value = strtod(o->ptr, &eptr);\n            if (isspace(((char*)o->ptr)[0]) ||\n                eptr[0] != '\\0' ||\n                (errno == ERANGE &&\n                    (value == HUGE_VAL || value == -HUGE_VAL || value == 0)) ||\n                errno == EINVAL ||\n                isnan(value))\n                return C_ERR;\n        } else if (o->encoding == OBJ_ENCODING_INT) {\n            value = (long)o->ptr;\n        } else {\n            serverPanic(\"Unknown string encoding\");\n        }\n    }\n    *target = value;\n    return C_OK;\n}\n\nint getDoubleFromObjectOrReply(client *c, robj *o, double *target, const char *msg) {\n    double value;\n    if (getDoubleFromObject(o, &value) != C_OK) {\n        if (msg != NULL) {\n            addReplyError(c,(char*)msg);\n        } else {\n            addReplyError(c,\"value is not a valid float\");\n        }\n        return C_ERR;\n    }\n    *target = value;\n    return C_OK;\n}\n\nint getLongDoubleFromObject(robj *o, long double *target) {\n    long double value;\n    char *eptr;\n\n    if (o == NULL) {\n        value = 0;\n    } else {\n        serverAssertWithInfo(NULL,o,o->type == OBJ_STRING);\n        if (sdsEncodedObject(o)) {\n            errno = 0;\n            value = strtold(o->ptr, &eptr);\n            if (isspace(((char*)o->ptr)[0]) || eptr[0] != '\\0' ||\n                errno == ERANGE || isnan(value))\n                return C_ERR;\n        } else if (o->encoding == OBJ_ENCODING_INT) {\n            value = (long)o->ptr;\n        } else {\n            serverPanic(\"Unknown string encoding\");\n        }\n    }\n    *target = value;\n    return C_OK;\n}\n\nint getLongDoubleFromObjectOrReply(client *c, robj *o, long double *target, const char *msg) {\n    long double value;\n    if (getLongDoubleFromObject(o, &value) != C_OK) {\n        if (msg != NULL) {\n            addReplyError(c,(char*)msg);\n        } else {\n            addReplyError(c,\"value is not a valid float\");\n        }\n        return C_ERR;\n    }\n    *target = value;\n    return C_OK;\n}\n\nint getLongLongFromObject(robj *o, long long *target) {\n    long long value;\n\n    if (o == NULL) {\n        value = 0;\n    } else {\n        serverAssertWithInfo(NULL,o,o->type == OBJ_STRING);\n        if (sdsEncodedObject(o)) {\n            if (string2ll(o->ptr,sdslen(o->ptr),&value) == 0) return C_ERR;\n        } else if (o->encoding == OBJ_ENCODING_INT) {\n            value = (long)o->ptr;\n        } else {\n            serverPanic(\"Unknown string encoding\");\n        }\n    }\n    if (target) *target = value;\n    return C_OK;\n}\n\nint getLongLongFromObjectOrReply(client *c, robj *o, long long *target, const char *msg) {\n    long long value;\n    if (getLongLongFromObject(o, &value) != C_OK) {\n        if (msg != NULL) {\n            addReplyError(c,(char*)msg);\n        } else {\n            addReplyError(c,\"value is not an integer or out of range\");\n        }\n        return C_ERR;\n    }\n    *target = value;\n    return C_OK;\n}\n\nint getLongFromObjectOrReply(client *c, robj *o, long *target, const char *msg) {\n    long long value;\n\n    if (getLongLongFromObjectOrReply(c, o, &value, msg) != C_OK) return C_ERR;\n    if (value < LONG_MIN || value > LONG_MAX) {\n        if (msg != NULL) {\n            addReplyError(c,(char*)msg);\n        } else {\n            addReplyError(c,\"value is out of range\");\n        }\n        return C_ERR;\n    }\n    *target = value;\n    return C_OK;\n}\n\nchar *strEncoding(int encoding) {\n    switch(encoding) {\n    case OBJ_ENCODING_RAW: return \"raw\";\n    case OBJ_ENCODING_INT: return \"int\";\n    case OBJ_ENCODING_HT: return \"hashtable\";\n    case OBJ_ENCODING_QUICKLIST: return \"quicklist\";\n    case OBJ_ENCODING_ZIPLIST: return \"ziplist\";\n    case OBJ_ENCODING_INTSET: return \"intset\";\n    case OBJ_ENCODING_SKIPLIST: return \"skiplist\";\n    case OBJ_ENCODING_EMBSTR: return \"embstr\";\n    default: return \"unknown\";\n    }\n}\n\n/* Given an object returns the min number of milliseconds the object was never\n * requested, using an approximated LRU algorithm. */\nunsigned long long estimateObjectIdleTime(robj *o) {\n    unsigned long long lruclock = LRU_CLOCK();\n    if (lruclock >= o->lru) {\n        return (lruclock - o->lru) * LRU_CLOCK_RESOLUTION;\n    } else {\n        return (lruclock + (LRU_CLOCK_MAX - o->lru)) *\n                    LRU_CLOCK_RESOLUTION;\n    }\n}\n\n/* This is a helper function for the OBJECT command. We need to lookup keys\n * without any modification of LRU or other parameters. */\nrobj *objectCommandLookup(client *c, robj *key) {\n    dictEntry *de;\n\n    if ((de = dictFind(c->db->dict,key->ptr)) == NULL) return NULL;\n    return (robj*) dictGetVal(de);\n}\n\nrobj *objectCommandLookupOrReply(client *c, robj *key, robj *reply) {\n    robj *o = objectCommandLookup(c,key);\n\n    if (!o) addReply(c, reply);\n    return o;\n}\n\n/* Object command allows to inspect the internals of an Redis Object.\n * Usage: OBJECT <refcount|encoding|idletime> <key> */\nvoid objectCommand(client *c) {\n    robj *o;\n\n    if (!strcasecmp(c->argv[1]->ptr,\"refcount\") && c->argc == 3) {\n        if ((o = objectCommandLookupOrReply(c,c->argv[2],shared.nullbulk))\n                == NULL) return;\n        addReplyLongLong(c,o->refcount);\n    } else if (!strcasecmp(c->argv[1]->ptr,\"encoding\") && c->argc == 3) {\n        if ((o = objectCommandLookupOrReply(c,c->argv[2],shared.nullbulk))\n                == NULL) return;\n        addReplyBulkCString(c,strEncoding(o->encoding));\n    } else if (!strcasecmp(c->argv[1]->ptr,\"idletime\") && c->argc == 3) {\n        if ((o = objectCommandLookupOrReply(c,c->argv[2],shared.nullbulk))\n                == NULL) return;\n        addReplyLongLong(c,estimateObjectIdleTime(o)/1000);\n    } else {\n        addReplyError(c,\"Syntax error. Try OBJECT (refcount|encoding|idletime)\");\n    }\n}\n\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/src/pqsort.c",
    "content": "/* The following is the NetBSD libc qsort implementation modified in order to\n * support partial sorting of ranges for Redis.\n *\n * Copyright(C) 2009-2012 Salvatore Sanfilippo. All rights reserved.\n *\n * The original copyright notice follows. */\n\n\n/*\t$NetBSD: qsort.c,v 1.19 2009/01/30 23:38:44 lukem Exp $\t*/\n\n/*-\n * Copyright (c) 1992, 1993\n *\tThe Regents of the University of California.  All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions\n * are met:\n * 1. Redistributions of source code must retain the above copyright\n *    notice, this list of conditions and the following disclaimer.\n * 2. Redistributions in binary form must reproduce the above copyright\n *    notice, this list of conditions and the following disclaimer in the\n *    documentation and/or other materials provided with the distribution.\n * 3. Neither the name of the University nor the names of its contributors\n *    may be used to endorse or promote products derived from this software\n *    without specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND\n * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\n * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE\n * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL\n * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS\n * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)\n * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT\n * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY\n * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF\n * SUCH DAMAGE.\n */\n\n#include <sys/types.h>\n\n#include <errno.h>\n#include <stdlib.h>\n\nstatic inline char\t*med3 (char *, char *, char *,\n    int (*)(const void *, const void *));\nstatic inline void\t swapfunc (char *, char *, size_t, int);\n\n#define min(a, b)\t(a) < (b) ? a : b\n\n/*\n * Qsort routine from Bentley & McIlroy's \"Engineering a Sort Function\".\n */\n#define swapcode(TYPE, parmi, parmj, n) { \t\t\\\n\tsize_t i = (n) / sizeof (TYPE); \t\t\\\n\tTYPE *pi = (TYPE *)(void *)(parmi); \t\t\\\n\tTYPE *pj = (TYPE *)(void *)(parmj); \t\t\\\n\tdo { \t\t\t\t\t\t\\\n\t\tTYPE\tt = *pi;\t\t\t\\\n\t\t*pi++ = *pj;\t\t\t\t\\\n\t\t*pj++ = t;\t\t\t\t\\\n        } while (--i > 0);\t\t\t\t\\\n}\n\n#define SWAPINIT(a, es) swaptype = ((char *)a - (char *)0) % sizeof(long) || \\\n\tes % sizeof(long) ? 2 : es == sizeof(long)? 0 : 1;\n\nstatic inline void\nswapfunc(char *a, char *b, size_t n, int swaptype)\n{\n\n\tif (swaptype <= 1)\n\t\tswapcode(long, a, b, n)\n\telse\n\t\tswapcode(char, a, b, n)\n}\n\n#define swap(a, b)\t\t\t\t\t\t\\\n\tif (swaptype == 0) {\t\t\t\t\t\\\n\t\tlong t = *(long *)(void *)(a);\t\t\t\\\n\t\t*(long *)(void *)(a) = *(long *)(void *)(b);\t\\\n\t\t*(long *)(void *)(b) = t;\t\t\t\\\n\t} else\t\t\t\t\t\t\t\\\n\t\tswapfunc(a, b, es, swaptype)\n\n#define vecswap(a, b, n) if ((n) > 0) swapfunc((a), (b), (size_t)(n), swaptype)\n\nstatic inline char *\nmed3(char *a, char *b, char *c,\n    int (*cmp) (const void *, const void *))\n{\n\n\treturn cmp(a, b) < 0 ?\n\t       (cmp(b, c) < 0 ? b : (cmp(a, c) < 0 ? c : a ))\n              :(cmp(b, c) > 0 ? b : (cmp(a, c) < 0 ? a : c ));\n}\n\nstatic void\n_pqsort(void *a, size_t n, size_t es,\n    int (*cmp) (const void *, const void *), void *lrange, void *rrange)\n{\n\tchar *pa, *pb, *pc, *pd, *pl, *pm, *pn;\n\tsize_t d, r;\n\tint swaptype, cmp_result;\n\nloop:\tSWAPINIT(a, es);\n\tif (n < 7) {\n\t\tfor (pm = (char *) a + es; pm < (char *) a + n * es; pm += es)\n\t\t\tfor (pl = pm; pl > (char *) a && cmp(pl - es, pl) > 0;\n\t\t\t     pl -= es)\n\t\t\t\tswap(pl, pl - es);\n\t\treturn;\n\t}\n\tpm = (char *) a + (n / 2) * es;\n\tif (n > 7) {\n\t\tpl = (char *) a;\n\t\tpn = (char *) a + (n - 1) * es;\n\t\tif (n > 40) {\n\t\t\td = (n / 8) * es;\n\t\t\tpl = med3(pl, pl + d, pl + 2 * d, cmp);\n\t\t\tpm = med3(pm - d, pm, pm + d, cmp);\n\t\t\tpn = med3(pn - 2 * d, pn - d, pn, cmp);\n\t\t}\n\t\tpm = med3(pl, pm, pn, cmp);\n\t}\n\tswap(a, pm);\n\tpa = pb = (char *) a + es;\n\n\tpc = pd = (char *) a + (n - 1) * es;\n\tfor (;;) {\n\t\twhile (pb <= pc && (cmp_result = cmp(pb, a)) <= 0) {\n\t\t\tif (cmp_result == 0) {\n\t\t\t\tswap(pa, pb);\n\t\t\t\tpa += es;\n\t\t\t}\n\t\t\tpb += es;\n\t\t}\n\t\twhile (pb <= pc && (cmp_result = cmp(pc, a)) >= 0) {\n\t\t\tif (cmp_result == 0) {\n\t\t\t\tswap(pc, pd);\n\t\t\t\tpd -= es;\n\t\t\t}\n\t\t\tpc -= es;\n\t\t}\n\t\tif (pb > pc)\n\t\t\tbreak;\n\t\tswap(pb, pc);\n\t\tpb += es;\n\t\tpc -= es;\n\t}\n\n\tpn = (char *) a + n * es;\n\tr = min(pa - (char *) a, pb - pa);\n\tvecswap(a, pb - r, r);\n\tr = min((size_t)(pd - pc), pn - pd - es);\n\tvecswap(pb, pn - r, r);\n\tif ((r = pb - pa) > es) {\n                void *_l = a, *_r = ((unsigned char*)a)+r-1;\n                if (!((lrange < _l && rrange < _l) ||\n                    (lrange > _r && rrange > _r)))\n\t\t    _pqsort(a, r / es, es, cmp, lrange, rrange);\n        }\n\tif ((r = pd - pc) > es) {\n                void *_l, *_r;\n\n\t\t/* Iterate rather than recurse to save stack space */\n\t\ta = pn - r;\n\t\tn = r / es;\n\n                _l = a;\n                _r = ((unsigned char*)a)+r-1;\n                if (!((lrange < _l && rrange < _l) ||\n                    (lrange > _r && rrange > _r)))\n\t\t    goto loop;\n\t}\n/*\t\tqsort(pn - r, r / es, es, cmp);*/\n}\n\nvoid\npqsort(void *a, size_t n, size_t es,\n    int (*cmp) (const void *, const void *), size_t lrange, size_t rrange)\n{\n    _pqsort(a,n,es,cmp,((unsigned char*)a)+(lrange*es),\n                       ((unsigned char*)a)+((rrange+1)*es)-1);\n}\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/src/pqsort.h",
    "content": "/* The following is the NetBSD libc qsort implementation modified in order to\n * support partial sorting of ranges for Redis.\n *\n * Copyright (c) 2009-2012, Salvatore Sanfilippo <antirez at gmail dot com>\n * All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions are met:\n *\n *   * Redistributions of source code must retain the above copyright notice,\n *     this list of conditions and the following disclaimer.\n *   * Redistributions in binary form must reproduce the above copyright\n *     notice, this list of conditions and the following disclaimer in the\n *     documentation and/or other materials provided with the distribution.\n *   * Neither the name of Redis nor the names of its contributors may be used\n *     to endorse or promote products derived from this software without\n *     specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\"\n * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\n * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE\n * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR\n * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF\n * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS\n * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN\n * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)\n * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE\n * POSSIBILITY OF SUCH DAMAGE.\n *\n * See the pqsort.c file for the original copyright notice. */\n\n#ifndef __PQSORT_H\n#define __PQSORT_H\n\nvoid\npqsort(void *a, size_t n, size_t es,\n    int (*cmp) (const void *, const void *), size_t lrange, size_t rrange);\n\n#endif\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/src/pubsub.c",
    "content": "/*\n * Copyright (c) 2009-2012, Salvatore Sanfilippo <antirez at gmail dot com>\n * All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions are met:\n *\n *   * Redistributions of source code must retain the above copyright notice,\n *     this list of conditions and the following disclaimer.\n *   * Redistributions in binary form must reproduce the above copyright\n *     notice, this list of conditions and the following disclaimer in the\n *     documentation and/or other materials provided with the distribution.\n *   * Neither the name of Redis nor the names of its contributors may be used\n *     to endorse or promote products derived from this software without\n *     specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\"\n * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\n * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE\n * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR\n * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF\n * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS\n * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN\n * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)\n * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE\n * POSSIBILITY OF SUCH DAMAGE.\n */\n\n#include \"server.h\"\n\n/*-----------------------------------------------------------------------------\n * Pubsub low level API\n *----------------------------------------------------------------------------*/\n\nvoid freePubsubPattern(void *p) {\n    pubsubPattern *pat = p;\n\n    decrRefCount(pat->pattern);\n    zfree(pat);\n}\n\nint listMatchPubsubPattern(void *a, void *b) {\n    pubsubPattern *pa = a, *pb = b;\n\n    return (pa->client == pb->client) &&\n           (equalStringObjects(pa->pattern,pb->pattern));\n}\n\n/* Return the number of channels + patterns a client is subscribed to. */\nint clientSubscriptionsCount(client *c) {\n    return dictSize(c->pubsub_channels)+\n           listLength(c->pubsub_patterns);\n}\n\n/* Subscribe a client to a channel. Returns 1 if the operation succeeded, or\n * 0 if the client was already subscribed to that channel. */\nint pubsubSubscribeChannel(client *c, robj *channel) {\n    dictEntry *de;\n    list *clients = NULL;\n    int retval = 0;\n\n    /* Add the channel to the client -> channels hash table */\n    if (dictAdd(c->pubsub_channels,channel,NULL) == DICT_OK) {\n        retval = 1;\n        incrRefCount(channel);\n        /* Add the client to the channel -> list of clients hash table */\n        de = dictFind(server.pubsub_channels,channel);\n        if (de == NULL) {\n            clients = listCreate();\n            dictAdd(server.pubsub_channels,channel,clients);\n            incrRefCount(channel);\n        } else {\n            clients = dictGetVal(de);\n        }\n        listAddNodeTail(clients,c);\n    }\n    /* Notify the client */\n    addReply(c,shared.mbulkhdr[3]);\n    addReply(c,shared.subscribebulk);\n    addReplyBulk(c,channel);\n    addReplyLongLong(c,clientSubscriptionsCount(c));\n    return retval;\n}\n\n/* Unsubscribe a client from a channel. Returns 1 if the operation succeeded, or\n * 0 if the client was not subscribed to the specified channel. */\nint pubsubUnsubscribeChannel(client *c, robj *channel, int notify) {\n    dictEntry *de;\n    list *clients;\n    listNode *ln;\n    int retval = 0;\n\n    /* Remove the channel from the client -> channels hash table */\n    incrRefCount(channel); /* channel may be just a pointer to the same object\n                            we have in the hash tables. Protect it... */\n    if (dictDelete(c->pubsub_channels,channel) == DICT_OK) {\n        retval = 1;\n        /* Remove the client from the channel -> clients list hash table */\n        de = dictFind(server.pubsub_channels,channel);\n        serverAssertWithInfo(c,NULL,de != NULL);\n        clients = dictGetVal(de);\n        ln = listSearchKey(clients,c);\n        serverAssertWithInfo(c,NULL,ln != NULL);\n        listDelNode(clients,ln);\n        if (listLength(clients) == 0) {\n            /* Free the list and associated hash entry at all if this was\n             * the latest client, so that it will be possible to abuse\n             * Redis PUBSUB creating millions of channels. */\n            dictDelete(server.pubsub_channels,channel);\n        }\n    }\n    /* Notify the client */\n    if (notify) {\n        addReply(c,shared.mbulkhdr[3]);\n        addReply(c,shared.unsubscribebulk);\n        addReplyBulk(c,channel);\n        addReplyLongLong(c,dictSize(c->pubsub_channels)+\n                       listLength(c->pubsub_patterns));\n\n    }\n    decrRefCount(channel); /* it is finally safe to release it */\n    return retval;\n}\n\n/* Subscribe a client to a pattern. Returns 1 if the operation succeeded, or 0 if the client was already subscribed to that pattern. */\nint pubsubSubscribePattern(client *c, robj *pattern) {\n    int retval = 0;\n\n    if (listSearchKey(c->pubsub_patterns,pattern) == NULL) {\n        retval = 1;\n        pubsubPattern *pat;\n        listAddNodeTail(c->pubsub_patterns,pattern);\n        incrRefCount(pattern);\n        pat = zmalloc(sizeof(*pat));\n        pat->pattern = getDecodedObject(pattern);\n        pat->client = c;\n        listAddNodeTail(server.pubsub_patterns,pat);\n    }\n    /* Notify the client */\n    addReply(c,shared.mbulkhdr[3]);\n    addReply(c,shared.psubscribebulk);\n    addReplyBulk(c,pattern);\n    addReplyLongLong(c,clientSubscriptionsCount(c));\n    return retval;\n}\n\n/* Unsubscribe a client from a channel. Returns 1 if the operation succeeded, or\n * 0 if the client was not subscribed to the specified channel. */\nint pubsubUnsubscribePattern(client *c, robj *pattern, int notify) {\n    listNode *ln;\n    pubsubPattern pat;\n    int retval = 0;\n\n    incrRefCount(pattern); /* Protect the object. May be the same we remove */\n    if ((ln = listSearchKey(c->pubsub_patterns,pattern)) != NULL) {\n        retval = 1;\n        listDelNode(c->pubsub_patterns,ln);\n        pat.client = c;\n        pat.pattern = pattern;\n        ln = listSearchKey(server.pubsub_patterns,&pat);\n        listDelNode(server.pubsub_patterns,ln);\n    }\n    /* Notify the client */\n    if (notify) {\n        addReply(c,shared.mbulkhdr[3]);\n        addReply(c,shared.punsubscribebulk);\n        addReplyBulk(c,pattern);\n        addReplyLongLong(c,dictSize(c->pubsub_channels)+\n                       listLength(c->pubsub_patterns));\n    }\n    decrRefCount(pattern);\n    return retval;\n}\n\n/* Unsubscribe from all the channels. Return the number of channels the\n * client was subscribed to. */\nint pubsubUnsubscribeAllChannels(client *c, int notify) {\n    dictIterator *di = dictGetSafeIterator(c->pubsub_channels);\n    dictEntry *de;\n    int count = 0;\n\n    while((de = dictNext(di)) != NULL) {\n        robj *channel = dictGetKey(de);\n\n        count += pubsubUnsubscribeChannel(c,channel,notify);\n    }\n    /* We were subscribed to nothing? Still reply to the client. */\n    if (notify && count == 0) {\n        addReply(c,shared.mbulkhdr[3]);\n        addReply(c,shared.unsubscribebulk);\n        addReply(c,shared.nullbulk);\n        addReplyLongLong(c,dictSize(c->pubsub_channels)+\n                       listLength(c->pubsub_patterns));\n    }\n    dictReleaseIterator(di);\n    return count;\n}\n\n/* Unsubscribe from all the patterns. Return the number of patterns the\n * client was subscribed from. */\nint pubsubUnsubscribeAllPatterns(client *c, int notify) {\n    listNode *ln;\n    listIter li;\n    int count = 0;\n\n    listRewind(c->pubsub_patterns,&li);\n    while ((ln = listNext(&li)) != NULL) {\n        robj *pattern = ln->value;\n\n        count += pubsubUnsubscribePattern(c,pattern,notify);\n    }\n    if (notify && count == 0) {\n        /* We were subscribed to nothing? Still reply to the client. */\n        addReply(c,shared.mbulkhdr[3]);\n        addReply(c,shared.punsubscribebulk);\n        addReply(c,shared.nullbulk);\n        addReplyLongLong(c,dictSize(c->pubsub_channels)+\n                       listLength(c->pubsub_patterns));\n    }\n    return count;\n}\n\n/* Publish a message */\nint pubsubPublishMessage(robj *channel, robj *message) {\n    int receivers = 0;\n    dictEntry *de;\n    listNode *ln;\n    listIter li;\n\n    /* Send to clients listening for that channel */\n    de = dictFind(server.pubsub_channels,channel);\n    if (de) {\n        list *list = dictGetVal(de);\n        listNode *ln;\n        listIter li;\n\n        listRewind(list,&li);\n        while ((ln = listNext(&li)) != NULL) {\n            client *c = ln->value;\n\n            addReply(c,shared.mbulkhdr[3]);\n            addReply(c,shared.messagebulk);\n            addReplyBulk(c,channel);\n            addReplyBulk(c,message);\n            receivers++;\n        }\n    }\n    /* Send to clients listening to matching channels */\n    if (listLength(server.pubsub_patterns)) {\n        listRewind(server.pubsub_patterns,&li);\n        channel = getDecodedObject(channel);\n        while ((ln = listNext(&li)) != NULL) {\n            pubsubPattern *pat = ln->value;\n\n            if (stringmatchlen((char*)pat->pattern->ptr,\n                                sdslen(pat->pattern->ptr),\n                                (char*)channel->ptr,\n                                sdslen(channel->ptr),0)) {\n                addReply(pat->client,shared.mbulkhdr[4]);\n                addReply(pat->client,shared.pmessagebulk);\n                addReplyBulk(pat->client,pat->pattern);\n                addReplyBulk(pat->client,channel);\n                addReplyBulk(pat->client,message);\n                receivers++;\n            }\n        }\n        decrRefCount(channel);\n    }\n    return receivers;\n}\n\n/*-----------------------------------------------------------------------------\n * Pubsub commands implementation\n *----------------------------------------------------------------------------*/\n\nvoid subscribeCommand(client *c) {\n    int j;\n\n    for (j = 1; j < c->argc; j++)\n        pubsubSubscribeChannel(c,c->argv[j]);\n    c->flags |= CLIENT_PUBSUB;\n}\n\nvoid unsubscribeCommand(client *c) {\n    if (c->argc == 1) {\n        pubsubUnsubscribeAllChannels(c,1);\n    } else {\n        int j;\n\n        for (j = 1; j < c->argc; j++)\n            pubsubUnsubscribeChannel(c,c->argv[j],1);\n    }\n    if (clientSubscriptionsCount(c) == 0) c->flags &= ~CLIENT_PUBSUB;\n}\n\nvoid psubscribeCommand(client *c) {\n    int j;\n\n    for (j = 1; j < c->argc; j++)\n        pubsubSubscribePattern(c,c->argv[j]);\n    c->flags |= CLIENT_PUBSUB;\n}\n\nvoid punsubscribeCommand(client *c) {\n    if (c->argc == 1) {\n        pubsubUnsubscribeAllPatterns(c,1);\n    } else {\n        int j;\n\n        for (j = 1; j < c->argc; j++)\n            pubsubUnsubscribePattern(c,c->argv[j],1);\n    }\n    if (clientSubscriptionsCount(c) == 0) c->flags &= ~CLIENT_PUBSUB;\n}\n\nvoid publishCommand(client *c) {\n    int receivers = pubsubPublishMessage(c->argv[1],c->argv[2]);\n    if (server.cluster_enabled)\n        clusterPropagatePublish(c->argv[1],c->argv[2]);\n    else\n        forceCommandPropagation(c,PROPAGATE_REPL);\n    addReplyLongLong(c,receivers);\n}\n\n/* PUBSUB command for Pub/Sub introspection. */\nvoid pubsubCommand(client *c) {\n    if (!strcasecmp(c->argv[1]->ptr,\"channels\") &&\n        (c->argc == 2 || c->argc ==3))\n    {\n        /* PUBSUB CHANNELS [<pattern>] */\n        sds pat = (c->argc == 2) ? NULL : c->argv[2]->ptr;\n        dictIterator *di = dictGetIterator(server.pubsub_channels);\n        dictEntry *de;\n        long mblen = 0;\n        void *replylen;\n\n        replylen = addDeferredMultiBulkLength(c);\n        while((de = dictNext(di)) != NULL) {\n            robj *cobj = dictGetKey(de);\n            sds channel = cobj->ptr;\n\n            if (!pat || stringmatchlen(pat, sdslen(pat),\n                                       channel, sdslen(channel),0))\n            {\n                addReplyBulk(c,cobj);\n                mblen++;\n            }\n        }\n        dictReleaseIterator(di);\n        setDeferredMultiBulkLength(c,replylen,mblen);\n    } else if (!strcasecmp(c->argv[1]->ptr,\"numsub\") && c->argc >= 2) {\n        /* PUBSUB NUMSUB [Channel_1 ... Channel_N] */\n        int j;\n\n        addReplyMultiBulkLen(c,(c->argc-2)*2);\n        for (j = 2; j < c->argc; j++) {\n            list *l = dictFetchValue(server.pubsub_channels,c->argv[j]);\n\n            addReplyBulk(c,c->argv[j]);\n            addReplyLongLong(c,l ? listLength(l) : 0);\n        }\n    } else if (!strcasecmp(c->argv[1]->ptr,\"numpat\") && c->argc == 2) {\n        /* PUBSUB NUMPAT */\n        addReplyLongLong(c,listLength(server.pubsub_patterns));\n    } else {\n        addReplyErrorFormat(c,\n            \"Unknown PUBSUB subcommand or wrong number of arguments for '%s'\",\n            (char*)c->argv[1]->ptr);\n    }\n}\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/src/quicklist.c",
    "content": "/* quicklist.c - A doubly linked list of ziplists\n *\n * Copyright (c) 2014, Matt Stancliff <matt@genges.com>\n * All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions are met:\n *\n *   * Redistributions of source code must start the above copyright notice,\n *     this quicklist of conditions and the following disclaimer.\n *   * Redistributions in binary form must reproduce the above copyright\n *     notice, this quicklist of conditions and the following disclaimer in the\n *     documentation and/or other materials provided with the distribution.\n *   * Neither the name of Redis nor the names of its contributors may be used\n *     to endorse or promote products derived from this software without\n *     specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\"\n * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\n * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE\n * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR\n * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF\n * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS\n * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN\n * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)\n * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE\n * POSSIBILITY OF SUCH DAMAGE.\n */\n\n#include <string.h> /* for memcpy */\n#include \"quicklist.h\"\n#include \"zmalloc.h\"\n#include \"ziplist.h\"\n#include \"util.h\" /* for ll2string */\n#include \"lzf.h\"\n\n#if defined(REDIS_TEST) || defined(REDIS_TEST_VERBOSE)\n#include <stdio.h> /* for printf (debug printing), snprintf (genstr) */\n#endif\n\n#ifndef REDIS_STATIC\n#define REDIS_STATIC static\n#endif\n\n/* Optimization levels for size-based filling */\nstatic const size_t optimization_level[] = {4096, 8192, 16384, 32768, 65536};\n\n/* Maximum size in bytes of any multi-element ziplist.\n * Larger values will live in their own isolated ziplists. */\n#define SIZE_SAFETY_LIMIT 8192\n\n/* Minimum ziplist size in bytes for attempting compression. */\n#define MIN_COMPRESS_BYTES 48\n\n/* Minimum size reduction in bytes to store compressed quicklistNode data.\n * This also prevents us from storing compression if the compression\n * resulted in a larger size than the original data. */\n#define MIN_COMPRESS_IMPROVE 8\n\n/* If not verbose testing, remove all debug printing. */\n#ifndef REDIS_TEST_VERBOSE\n#define D(...)\n#else\n#define D(...)                                                                 \\\n    do {                                                                       \\\n        printf(\"%s:%s:%d:\\t\", __FILE__, __FUNCTION__, __LINE__);               \\\n        printf(__VA_ARGS__);                                                   \\\n        printf(\"\\n\");                                                          \\\n    } while (0);\n#endif\n\n/* Simple way to give quicklistEntry structs default values with one call. */\n#define initEntry(e)                                                           \\\n    do {                                                                       \\\n        (e)->zi = (e)->value = NULL;                                           \\\n        (e)->longval = -123456789;                                             \\\n        (e)->quicklist = NULL;                                                 \\\n        (e)->node = NULL;                                                      \\\n        (e)->offset = 123456789;                                               \\\n        (e)->sz = 0;                                                           \\\n    } while (0)\n\n#if __GNUC__ >= 3\n#define likely(x) __builtin_expect(!!(x), 1)\n#define unlikely(x) __builtin_expect(!!(x), 0)\n#else\n#define likely(x) (x)\n#define unlikely(x) (x)\n#endif\n\n/* Create a new quicklist.\n * Free with quicklistRelease(). */\nquicklist *quicklistCreate(void) {\n    struct quicklist *quicklist;\n\n    quicklist = zmalloc(sizeof(*quicklist));\n    quicklist->head = quicklist->tail = NULL;\n    quicklist->len = 0;\n    quicklist->count = 0;\n    quicklist->compress = 0;\n    quicklist->fill = -2;\n    return quicklist;\n}\n\n#define COMPRESS_MAX (1 << 16)\nvoid quicklistSetCompressDepth(quicklist *quicklist, int compress) {\n    if (compress > COMPRESS_MAX) {\n        compress = COMPRESS_MAX;\n    } else if (compress < 0) {\n        compress = 0;\n    }\n    quicklist->compress = compress;\n}\n\n#define FILL_MAX (1 << 15)\nvoid quicklistSetFill(quicklist *quicklist, int fill) {\n    if (fill > FILL_MAX) {\n        fill = FILL_MAX;\n    } else if (fill < -5) {\n        fill = -5;\n    }\n    quicklist->fill = fill;\n}\n\nvoid quicklistSetOptions(quicklist *quicklist, int fill, int depth) {\n    quicklistSetFill(quicklist, fill);\n    quicklistSetCompressDepth(quicklist, depth);\n}\n\n/* Create a new quicklist with some default parameters. */\nquicklist *quicklistNew(int fill, int compress) {\n    quicklist *quicklist = quicklistCreate();\n    quicklistSetOptions(quicklist, fill, compress);\n    return quicklist;\n}\n\nREDIS_STATIC quicklistNode *quicklistCreateNode(void) {\n    quicklistNode *node;\n    node = zmalloc(sizeof(*node));\n    node->zl = NULL;\n    node->count = 0;\n    node->sz = 0;\n    node->next = node->prev = NULL;\n    node->encoding = QUICKLIST_NODE_ENCODING_RAW;\n    node->container = QUICKLIST_NODE_CONTAINER_ZIPLIST;\n    node->recompress = 0;\n    return node;\n}\n\n/* Return cached quicklist count */\nunsigned int quicklistCount(quicklist *ql) { return ql->count; }\n\n/* Free entire quicklist. */\nvoid quicklistRelease(quicklist *quicklist) {\n    unsigned long len;\n    quicklistNode *current, *next;\n\n    current = quicklist->head;\n    len = quicklist->len;\n    while (len--) {\n        next = current->next;\n\n        zfree(current->zl);\n        quicklist->count -= current->count;\n\n        zfree(current);\n\n        quicklist->len--;\n        current = next;\n    }\n    zfree(quicklist);\n}\n\n/* Compress the ziplist in 'node' and update encoding details.\n * Returns 1 if ziplist compressed successfully.\n * Returns 0 if compression failed or if ziplist too small to compress. */\nREDIS_STATIC int __quicklistCompressNode(quicklistNode *node) {\n#ifdef REDIS_TEST\n    node->attempted_compress = 1;\n#endif\n\n    /* Don't bother compressing small values */\n    if (node->sz < MIN_COMPRESS_BYTES)\n        return 0;\n\n    quicklistLZF *lzf = zmalloc(sizeof(*lzf) + node->sz);\n\n    /* Cancel if compression fails or doesn't compress small enough */\n    if (((lzf->sz = lzf_compress(node->zl, node->sz, lzf->compressed,\n                                 node->sz)) == 0) ||\n        lzf->sz + MIN_COMPRESS_IMPROVE >= node->sz) {\n        /* lzf_compress aborts/rejects compression if value not compressable. */\n        zfree(lzf);\n        return 0;\n    }\n    lzf = zrealloc(lzf, sizeof(*lzf) + lzf->sz);\n    zfree(node->zl);\n    node->zl = (unsigned char *)lzf;\n    node->encoding = QUICKLIST_NODE_ENCODING_LZF;\n    node->recompress = 0;\n    return 1;\n}\n\n/* Compress only uncompressed nodes. */\n#define quicklistCompressNode(_node)                                           \\\n    do {                                                                       \\\n        if ((_node) && (_node)->encoding == QUICKLIST_NODE_ENCODING_RAW) {     \\\n            __quicklistCompressNode((_node));                                  \\\n        }                                                                      \\\n    } while (0)\n\n/* Uncompress the ziplist in 'node' and update encoding details.\n * Returns 1 on successful decode, 0 on failure to decode. */\nREDIS_STATIC int __quicklistDecompressNode(quicklistNode *node) {\n#ifdef REDIS_TEST\n    node->attempted_compress = 0;\n#endif\n\n    void *decompressed = zmalloc(node->sz);\n    quicklistLZF *lzf = (quicklistLZF *)node->zl;\n    if (lzf_decompress(lzf->compressed, lzf->sz, decompressed, node->sz) == 0) {\n        /* Someone requested decompress, but we can't decompress.  Not good. */\n        zfree(decompressed);\n        return 0;\n    }\n    zfree(lzf);\n    node->zl = decompressed;\n    node->encoding = QUICKLIST_NODE_ENCODING_RAW;\n    return 1;\n}\n\n/* Decompress only compressed nodes. */\n#define quicklistDecompressNode(_node)                                         \\\n    do {                                                                       \\\n        if ((_node) && (_node)->encoding == QUICKLIST_NODE_ENCODING_LZF) {     \\\n            __quicklistDecompressNode((_node));                                \\\n        }                                                                      \\\n    } while (0)\n\n/* Force node to not be immediately re-compresable */\n#define quicklistDecompressNodeForUse(_node)                                   \\\n    do {                                                                       \\\n        if ((_node) && (_node)->encoding == QUICKLIST_NODE_ENCODING_LZF) {     \\\n            __quicklistDecompressNode((_node));                                \\\n            (_node)->recompress = 1;                                           \\\n        }                                                                      \\\n    } while (0)\n\n/* Extract the raw LZF data from this quicklistNode.\n * Pointer to LZF data is assigned to '*data'.\n * Return value is the length of compressed LZF data. */\nsize_t quicklistGetLzf(const quicklistNode *node, void **data) {\n    quicklistLZF *lzf = (quicklistLZF *)node->zl;\n    *data = lzf->compressed;\n    return lzf->sz;\n}\n\n#define quicklistAllowsCompression(_ql) ((_ql)->compress != 0)\n\n/* Force 'quicklist' to meet compression guidelines set by compress depth.\n * The only way to guarantee interior nodes get compressed is to iterate\n * to our \"interior\" compress depth then compress the next node we find.\n * If compress depth is larger than the entire list, we return immediately. */\nREDIS_STATIC void __quicklistCompress(const quicklist *quicklist,\n                                      quicklistNode *node) {\n    /* If length is less than our compress depth (from both sides),\n     * we can't compress anything. */\n    if (!quicklistAllowsCompression(quicklist) ||\n        quicklist->len < (unsigned int)(quicklist->compress * 2))\n        return;\n\n#if 0\n    /* Optimized cases for small depth counts */\n    if (quicklist->compress == 1) {\n        quicklistNode *h = quicklist->head, *t = quicklist->tail;\n        quicklistDecompressNode(h);\n        quicklistDecompressNode(t);\n        if (h != node && t != node)\n            quicklistCompressNode(node);\n        return;\n    } else if (quicklist->compress == 2) {\n        quicklistNode *h = quicklist->head, *hn = h->next, *hnn = hn->next;\n        quicklistNode *t = quicklist->tail, *tp = t->prev, *tpp = tp->prev;\n        quicklistDecompressNode(h);\n        quicklistDecompressNode(hn);\n        quicklistDecompressNode(t);\n        quicklistDecompressNode(tp);\n        if (h != node && hn != node && t != node && tp != node) {\n            quicklistCompressNode(node);\n        }\n        if (hnn != t) {\n            quicklistCompressNode(hnn);\n        }\n        if (tpp != h) {\n            quicklistCompressNode(tpp);\n        }\n        return;\n    }\n#endif\n\n    /* Iterate until we reach compress depth for both sides of the list.a\n     * Note: because we do length checks at the *top* of this function,\n     *       we can skip explicit null checks below. Everything exists. */\n    quicklistNode *forward = quicklist->head;\n    quicklistNode *reverse = quicklist->tail;\n    int depth = 0;\n    int in_depth = 0;\n    while (depth++ < quicklist->compress) {\n        quicklistDecompressNode(forward);\n        quicklistDecompressNode(reverse);\n\n        if (forward == node || reverse == node)\n            in_depth = 1;\n\n        if (forward == reverse)\n            return;\n\n        forward = forward->next;\n        reverse = reverse->prev;\n    }\n\n    if (!in_depth)\n        quicklistCompressNode(node);\n\n    if (depth > 2) {\n        /* At this point, forward and reverse are one node beyond depth */\n        quicklistCompressNode(forward);\n        quicklistCompressNode(reverse);\n    }\n}\n\n#define quicklistCompress(_ql, _node)                                          \\\n    do {                                                                       \\\n        if ((_node)->recompress)                                               \\\n            quicklistCompressNode((_node));                                    \\\n        else                                                                   \\\n            __quicklistCompress((_ql), (_node));                               \\\n    } while (0)\n\n/* If we previously used quicklistDecompressNodeForUse(), just recompress. */\n#define quicklistRecompressOnly(_ql, _node)                                    \\\n    do {                                                                       \\\n        if ((_node)->recompress)                                               \\\n            quicklistCompressNode((_node));                                    \\\n    } while (0)\n\n/* Insert 'new_node' after 'old_node' if 'after' is 1.\n * Insert 'new_node' before 'old_node' if 'after' is 0.\n * Note: 'new_node' is *always* uncompressed, so if we assign it to\n *       head or tail, we do not need to uncompress it. */\nREDIS_STATIC void __quicklistInsertNode(quicklist *quicklist,\n                                        quicklistNode *old_node,\n                                        quicklistNode *new_node, int after) {\n    if (after) {\n        new_node->prev = old_node;\n        if (old_node) {\n            new_node->next = old_node->next;\n            if (old_node->next)\n                old_node->next->prev = new_node;\n            old_node->next = new_node;\n        }\n        if (quicklist->tail == old_node)\n            quicklist->tail = new_node;\n    } else {\n        new_node->next = old_node;\n        if (old_node) {\n            new_node->prev = old_node->prev;\n            if (old_node->prev)\n                old_node->prev->next = new_node;\n            old_node->prev = new_node;\n        }\n        if (quicklist->head == old_node)\n            quicklist->head = new_node;\n    }\n    /* If this insert creates the only element so far, initialize head/tail. */\n    if (quicklist->len == 0) {\n        quicklist->head = quicklist->tail = new_node;\n    }\n\n    if (old_node)\n        quicklistCompress(quicklist, old_node);\n\n    quicklist->len++;\n}\n\n/* Wrappers for node inserting around existing node. */\nREDIS_STATIC void _quicklistInsertNodeBefore(quicklist *quicklist,\n                                             quicklistNode *old_node,\n                                             quicklistNode *new_node) {\n    __quicklistInsertNode(quicklist, old_node, new_node, 0);\n}\n\nREDIS_STATIC void _quicklistInsertNodeAfter(quicklist *quicklist,\n                                            quicklistNode *old_node,\n                                            quicklistNode *new_node) {\n    __quicklistInsertNode(quicklist, old_node, new_node, 1);\n}\n\nREDIS_STATIC int\n_quicklistNodeSizeMeetsOptimizationRequirement(const size_t sz,\n                                               const int fill) {\n    if (fill >= 0)\n        return 0;\n\n    size_t offset = (-fill) - 1;\n    if (offset < (sizeof(optimization_level) / sizeof(*optimization_level))) {\n        if (sz <= optimization_level[offset]) {\n            return 1;\n        } else {\n            return 0;\n        }\n    } else {\n        return 0;\n    }\n}\n\n#define sizeMeetsSafetyLimit(sz) ((sz) <= SIZE_SAFETY_LIMIT)\n\nREDIS_STATIC int _quicklistNodeAllowInsert(const quicklistNode *node,\n                                           const int fill, const size_t sz) {\n    if (unlikely(!node))\n        return 0;\n\n    int ziplist_overhead;\n    /* size of previous offset */\n    if (sz < 254)\n        ziplist_overhead = 1;\n    else\n        ziplist_overhead = 5;\n\n    /* size of forward offset */\n    if (sz < 64)\n        ziplist_overhead += 1;\n    else if (likely(sz < 16384))\n        ziplist_overhead += 2;\n    else\n        ziplist_overhead += 5;\n\n    /* new_sz overestimates if 'sz' encodes to an integer type */\n    unsigned int new_sz = node->sz + sz + ziplist_overhead;\n    if (likely(_quicklistNodeSizeMeetsOptimizationRequirement(new_sz, fill)))\n        return 1;\n    else if (!sizeMeetsSafetyLimit(new_sz))\n        return 0;\n    else if ((int)node->count < fill)\n        return 1;\n    else\n        return 0;\n}\n\nREDIS_STATIC int _quicklistNodeAllowMerge(const quicklistNode *a,\n                                          const quicklistNode *b,\n                                          const int fill) {\n    if (!a || !b)\n        return 0;\n\n    /* approximate merged ziplist size (- 11 to remove one ziplist\n     * header/trailer) */\n    unsigned int merge_sz = a->sz + b->sz - 11;\n    if (likely(_quicklistNodeSizeMeetsOptimizationRequirement(merge_sz, fill)))\n        return 1;\n    else if (!sizeMeetsSafetyLimit(merge_sz))\n        return 0;\n    else if ((int)(a->count + b->count) <= fill)\n        return 1;\n    else\n        return 0;\n}\n\n#define quicklistNodeUpdateSz(node)                                            \\\n    do {                                                                       \\\n        (node)->sz = ziplistBlobLen((node)->zl);                               \\\n    } while (0)\n\n/* Add new entry to head node of quicklist.\n *\n * Returns 0 if used existing head.\n * Returns 1 if new head created. */\nint quicklistPushHead(quicklist *quicklist, void *value, size_t sz) {\n    quicklistNode *orig_head = quicklist->head;\n    if (likely(\n            _quicklistNodeAllowInsert(quicklist->head, quicklist->fill, sz))) {\n        quicklist->head->zl =\n            ziplistPush(quicklist->head->zl, value, sz, ZIPLIST_HEAD);\n        quicklistNodeUpdateSz(quicklist->head);\n    } else {\n        quicklistNode *node = quicklistCreateNode();\n        node->zl = ziplistPush(ziplistNew(), value, sz, ZIPLIST_HEAD);\n\n        quicklistNodeUpdateSz(node);\n        _quicklistInsertNodeBefore(quicklist, quicklist->head, node);\n    }\n    quicklist->count++;\n    quicklist->head->count++;\n    return (orig_head != quicklist->head);\n}\n\n/* Add new entry to tail node of quicklist.\n *\n * Returns 0 if used existing tail.\n * Returns 1 if new tail created. */\nint quicklistPushTail(quicklist *quicklist, void *value, size_t sz) {\n    quicklistNode *orig_tail = quicklist->tail;\n    if (likely(\n            _quicklistNodeAllowInsert(quicklist->tail, quicklist->fill, sz))) {\n        quicklist->tail->zl =\n            ziplistPush(quicklist->tail->zl, value, sz, ZIPLIST_TAIL);\n        quicklistNodeUpdateSz(quicklist->tail);\n    } else {\n        quicklistNode *node = quicklistCreateNode();\n        node->zl = ziplistPush(ziplistNew(), value, sz, ZIPLIST_TAIL);\n\n        quicklistNodeUpdateSz(node);\n        _quicklistInsertNodeAfter(quicklist, quicklist->tail, node);\n    }\n    quicklist->count++;\n    quicklist->tail->count++;\n    return (orig_tail != quicklist->tail);\n}\n\n/* Create new node consisting of a pre-formed ziplist.\n * Used for loading RDBs where entire ziplists have been stored\n * to be retrieved later. */\nvoid quicklistAppendZiplist(quicklist *quicklist, unsigned char *zl) {\n    quicklistNode *node = quicklistCreateNode();\n\n    node->zl = zl;\n    node->count = ziplistLen(node->zl);\n    node->sz = ziplistBlobLen(zl);\n\n    _quicklistInsertNodeAfter(quicklist, quicklist->tail, node);\n    quicklist->count += node->count;\n}\n\n/* Append all values of ziplist 'zl' individually into 'quicklist'.\n *\n * This allows us to restore old RDB ziplists into new quicklists\n * with smaller ziplist sizes than the saved RDB ziplist.\n *\n * Returns 'quicklist' argument. Frees passed-in ziplist 'zl' */\nquicklist *quicklistAppendValuesFromZiplist(quicklist *quicklist,\n                                            unsigned char *zl) {\n    unsigned char *value;\n    unsigned int sz;\n    long long longval;\n    char longstr[32] = {0};\n\n    unsigned char *p = ziplistIndex(zl, 0);\n    while (ziplistGet(p, &value, &sz, &longval)) {\n        if (!value) {\n            /* Write the longval as a string so we can re-add it */\n            sz = ll2string(longstr, sizeof(longstr), longval);\n            value = (unsigned char *)longstr;\n        }\n        quicklistPushTail(quicklist, value, sz);\n        p = ziplistNext(zl, p);\n    }\n    zfree(zl);\n    return quicklist;\n}\n\n/* Create new (potentially multi-node) quicklist from a single existing ziplist.\n *\n * Returns new quicklist.  Frees passed-in ziplist 'zl'. */\nquicklist *quicklistCreateFromZiplist(int fill, int compress,\n                                      unsigned char *zl) {\n    return quicklistAppendValuesFromZiplist(quicklistNew(fill, compress), zl);\n}\n\n#define quicklistDeleteIfEmpty(ql, n)                                          \\\n    do {                                                                       \\\n        if ((n)->count == 0) {                                                 \\\n            __quicklistDelNode((ql), (n));                                     \\\n            (n) = NULL;                                                        \\\n        }                                                                      \\\n    } while (0)\n\nREDIS_STATIC void __quicklistDelNode(quicklist *quicklist,\n                                     quicklistNode *node) {\n    if (node->next)\n        node->next->prev = node->prev;\n    if (node->prev)\n        node->prev->next = node->next;\n\n    if (node == quicklist->tail) {\n        quicklist->tail = node->prev;\n    }\n\n    if (node == quicklist->head) {\n        quicklist->head = node->next;\n    }\n\n    /* If we deleted a node within our compress depth, we\n     * now have compressed nodes needing to be decompressed. */\n    __quicklistCompress(quicklist, NULL);\n\n    quicklist->count -= node->count;\n\n    zfree(node->zl);\n    zfree(node);\n    quicklist->len--;\n}\n\n/* Delete one entry from list given the node for the entry and a pointer\n * to the entry in the node.\n *\n * Note: quicklistDelIndex() *requires* uncompressed nodes because you\n *       already had to get *p from an uncompressed node somewhere.\n *\n * Returns 1 if the entire node was deleted, 0 if node still exists.\n * Also updates in/out param 'p' with the next offset in the ziplist. */\nREDIS_STATIC int quicklistDelIndex(quicklist *quicklist, quicklistNode *node,\n                                   unsigned char **p) {\n    int gone = 0;\n\n    node->zl = ziplistDelete(node->zl, p);\n    node->count--;\n    if (node->count == 0) {\n        gone = 1;\n        __quicklistDelNode(quicklist, node);\n    } else {\n        quicklistNodeUpdateSz(node);\n    }\n    quicklist->count--;\n    /* If we deleted the node, the original node is no longer valid */\n    return gone ? 1 : 0;\n}\n\n/* Delete one element represented by 'entry'\n *\n * 'entry' stores enough metadata to delete the proper position in\n * the correct ziplist in the correct quicklist node. */\nvoid quicklistDelEntry(quicklistIter *iter, quicklistEntry *entry) {\n    quicklistNode *prev = entry->node->prev;\n    quicklistNode *next = entry->node->next;\n    int deleted_node = quicklistDelIndex((quicklist *)entry->quicklist,\n                                         entry->node, &entry->zi);\n\n    /* after delete, the zi is now invalid for any future usage. */\n    iter->zi = NULL;\n\n    /* If current node is deleted, we must update iterator node and offset. */\n    if (deleted_node) {\n        if (iter->direction == AL_START_HEAD) {\n            iter->current = next;\n            iter->offset = 0;\n        } else if (iter->direction == AL_START_TAIL) {\n            iter->current = prev;\n            iter->offset = -1;\n        }\n    }\n    /* else if (!deleted_node), no changes needed.\n     * we already reset iter->zi above, and the existing iter->offset\n     * doesn't move again because:\n     *   - [1, 2, 3] => delete offset 1 => [1, 3]: next element still offset 1\n     *   - [1, 2, 3] => delete offset 0 => [2, 3]: next element still offset 0\n     *  if we deleted the last element at offet N and now\n     *  length of this ziplist is N-1, the next call into\n     *  quicklistNext() will jump to the next node. */\n}\n\n/* Replace quicklist entry at offset 'index' by 'data' with length 'sz'.\n *\n * Returns 1 if replace happened.\n * Returns 0 if replace failed and no changes happened. */\nint quicklistReplaceAtIndex(quicklist *quicklist, long index, void *data,\n                            int sz) {\n    quicklistEntry entry;\n    if (likely(quicklistIndex(quicklist, index, &entry))) {\n        /* quicklistIndex provides an uncompressed node */\n        entry.node->zl = ziplistDelete(entry.node->zl, &entry.zi);\n        entry.node->zl = ziplistInsert(entry.node->zl, entry.zi, data, sz);\n        quicklistNodeUpdateSz(entry.node);\n        quicklistCompress(quicklist, entry.node);\n        return 1;\n    } else {\n        return 0;\n    }\n}\n\n/* Given two nodes, try to merge their ziplists.\n *\n * This helps us not have a quicklist with 3 element ziplists if\n * our fill factor can handle much higher levels.\n *\n * Note: 'a' must be to the LEFT of 'b'.\n *\n * After calling this function, both 'a' and 'b' should be considered\n * unusable.  The return value from this function must be used\n * instead of re-using any of the quicklistNode input arguments.\n *\n * Returns the input node picked to merge against or NULL if\n * merging was not possible. */\nREDIS_STATIC quicklistNode *_quicklistZiplistMerge(quicklist *quicklist,\n                                                   quicklistNode *a,\n                                                   quicklistNode *b) {\n    D(\"Requested merge (a,b) (%u, %u)\", a->count, b->count);\n\n    quicklistDecompressNode(a);\n    quicklistDecompressNode(b);\n    if ((ziplistMerge(&a->zl, &b->zl))) {\n        /* We merged ziplists! Now remove the unused quicklistNode. */\n        quicklistNode *keep = NULL, *nokeep = NULL;\n        if (!a->zl) {\n            nokeep = a;\n            keep = b;\n        } else if (!b->zl) {\n            nokeep = b;\n            keep = a;\n        }\n        keep->count = ziplistLen(keep->zl);\n        quicklistNodeUpdateSz(keep);\n\n        nokeep->count = 0;\n        __quicklistDelNode(quicklist, nokeep);\n        quicklistCompress(quicklist, keep);\n        return keep;\n    } else {\n        /* else, the merge returned NULL and nothing changed. */\n        return NULL;\n    }\n}\n\n/* Attempt to merge ziplists within two nodes on either side of 'center'.\n *\n * We attempt to merge:\n *   - (center->prev->prev, center->prev)\n *   - (center->next, center->next->next)\n *   - (center->prev, center)\n *   - (center, center->next)\n */\nREDIS_STATIC void _quicklistMergeNodes(quicklist *quicklist,\n                                       quicklistNode *center) {\n    int fill = quicklist->fill;\n    quicklistNode *prev, *prev_prev, *next, *next_next, *target;\n    prev = prev_prev = next = next_next = target = NULL;\n\n    if (center->prev) {\n        prev = center->prev;\n        if (center->prev->prev)\n            prev_prev = center->prev->prev;\n    }\n\n    if (center->next) {\n        next = center->next;\n        if (center->next->next)\n            next_next = center->next->next;\n    }\n\n    /* Try to merge prev_prev and prev */\n    if (_quicklistNodeAllowMerge(prev, prev_prev, fill)) {\n        _quicklistZiplistMerge(quicklist, prev_prev, prev);\n        prev_prev = prev = NULL; /* they could have moved, invalidate them. */\n    }\n\n    /* Try to merge next and next_next */\n    if (_quicklistNodeAllowMerge(next, next_next, fill)) {\n        _quicklistZiplistMerge(quicklist, next, next_next);\n        next = next_next = NULL; /* they could have moved, invalidate them. */\n    }\n\n    /* Try to merge center node and previous node */\n    if (_quicklistNodeAllowMerge(center, center->prev, fill)) {\n        target = _quicklistZiplistMerge(quicklist, center->prev, center);\n        center = NULL; /* center could have been deleted, invalidate it. */\n    } else {\n        /* else, we didn't merge here, but target needs to be valid below. */\n        target = center;\n    }\n\n    /* Use result of center merge (or original) to merge with next node. */\n    if (_quicklistNodeAllowMerge(target, target->next, fill)) {\n        _quicklistZiplistMerge(quicklist, target, target->next);\n    }\n}\n\n/* Split 'node' into two parts, parameterized by 'offset' and 'after'.\n *\n * The 'after' argument controls which quicklistNode gets returned.\n * If 'after'==1, returned node has elements after 'offset'.\n *                input node keeps elements up to 'offset', including 'offset'.\n * If 'after'==0, returned node has elements up to 'offset', including 'offset'.\n *                input node keeps elements after 'offset'.\n *\n * If 'after'==1, returned node will have elements _after_ 'offset'.\n *                The returned node will have elements [OFFSET+1, END].\n *                The input node keeps elements [0, OFFSET].\n *\n * If 'after'==0, returned node will keep elements up to and including 'offset'.\n *                The returned node will have elements [0, OFFSET].\n *                The input node keeps elements [OFFSET+1, END].\n *\n * The input node keeps all elements not taken by the returned node.\n *\n * Returns newly created node or NULL if split not possible. */\nREDIS_STATIC quicklistNode *_quicklistSplitNode(quicklistNode *node, int offset,\n                                                int after) {\n    size_t zl_sz = node->sz;\n\n    quicklistNode *new_node = quicklistCreateNode();\n    new_node->zl = zmalloc(zl_sz);\n\n    /* Copy original ziplist so we can split it */\n    memcpy(new_node->zl, node->zl, zl_sz);\n\n    /* -1 here means \"continue deleting until the list ends\" */\n    int orig_start = after ? offset + 1 : 0;\n    int orig_extent = after ? -1 : offset;\n    int new_start = after ? 0 : offset;\n    int new_extent = after ? offset + 1 : -1;\n\n    D(\"After %d (%d); ranges: [%d, %d], [%d, %d]\", after, offset, orig_start,\n      orig_extent, new_start, new_extent);\n\n    node->zl = ziplistDeleteRange(node->zl, orig_start, orig_extent);\n    node->count = ziplistLen(node->zl);\n    quicklistNodeUpdateSz(node);\n\n    new_node->zl = ziplistDeleteRange(new_node->zl, new_start, new_extent);\n    new_node->count = ziplistLen(new_node->zl);\n    quicklistNodeUpdateSz(new_node);\n\n    D(\"After split lengths: orig (%d), new (%d)\", node->count, new_node->count);\n    return new_node;\n}\n\n/* Insert a new entry before or after existing entry 'entry'.\n *\n * If after==1, the new value is inserted after 'entry', otherwise\n * the new value is inserted before 'entry'. */\nREDIS_STATIC void _quicklistInsert(quicklist *quicklist, quicklistEntry *entry,\n                                   void *value, const size_t sz, int after) {\n    int full = 0, at_tail = 0, at_head = 0, full_next = 0, full_prev = 0;\n    int fill = quicklist->fill;\n    quicklistNode *node = entry->node;\n    quicklistNode *new_node = NULL;\n\n    if (!node) {\n        /* we have no reference node, so let's create only node in the list */\n        D(\"No node given!\");\n        new_node = quicklistCreateNode();\n        new_node->zl = ziplistPush(ziplistNew(), value, sz, ZIPLIST_HEAD);\n        __quicklistInsertNode(quicklist, NULL, new_node, after);\n        new_node->count++;\n        quicklist->count++;\n        return;\n    }\n\n    /* Populate accounting flags for easier boolean checks later */\n    if (!_quicklistNodeAllowInsert(node, fill, sz)) {\n        D(\"Current node is full with count %d with requested fill %lu\",\n          node->count, fill);\n        full = 1;\n    }\n\n    if (after && (entry->offset == node->count)) {\n        D(\"At Tail of current ziplist\");\n        at_tail = 1;\n        if (!_quicklistNodeAllowInsert(node->next, fill, sz)) {\n            D(\"Next node is full too.\");\n            full_next = 1;\n        }\n    }\n\n    if (!after && (entry->offset == 0)) {\n        D(\"At Head\");\n        at_head = 1;\n        if (!_quicklistNodeAllowInsert(node->prev, fill, sz)) {\n            D(\"Prev node is full too.\");\n            full_prev = 1;\n        }\n    }\n\n    /* Now determine where and how to insert the new element */\n    if (!full && after) {\n        D(\"Not full, inserting after current position.\");\n        quicklistDecompressNodeForUse(node);\n        unsigned char *next = ziplistNext(node->zl, entry->zi);\n        if (next == NULL) {\n            node->zl = ziplistPush(node->zl, value, sz, ZIPLIST_TAIL);\n        } else {\n            node->zl = ziplistInsert(node->zl, next, value, sz);\n        }\n        node->count++;\n        quicklistNodeUpdateSz(node);\n        quicklistRecompressOnly(quicklist, node);\n    } else if (!full && !after) {\n        D(\"Not full, inserting before current position.\");\n        quicklistDecompressNodeForUse(node);\n        node->zl = ziplistInsert(node->zl, entry->zi, value, sz);\n        node->count++;\n        quicklistNodeUpdateSz(node);\n        quicklistRecompressOnly(quicklist, node);\n    } else if (full && at_tail && node->next && !full_next && after) {\n        /* If we are: at tail, next has free space, and inserting after:\n         *   - insert entry at head of next node. */\n        D(\"Full and tail, but next isn't full; inserting next node head\");\n        new_node = node->next;\n        quicklistDecompressNodeForUse(new_node);\n        new_node->zl = ziplistPush(new_node->zl, value, sz, ZIPLIST_HEAD);\n        new_node->count++;\n        quicklistNodeUpdateSz(new_node);\n        quicklistRecompressOnly(quicklist, new_node);\n    } else if (full && at_head && node->prev && !full_prev && !after) {\n        /* If we are: at head, previous has free space, and inserting before:\n         *   - insert entry at tail of previous node. */\n        D(\"Full and head, but prev isn't full, inserting prev node tail\");\n        new_node = node->prev;\n        quicklistDecompressNodeForUse(new_node);\n        new_node->zl = ziplistPush(new_node->zl, value, sz, ZIPLIST_TAIL);\n        new_node->count++;\n        quicklistNodeUpdateSz(new_node);\n        quicklistRecompressOnly(quicklist, new_node);\n    } else if (full && ((at_tail && node->next && full_next && after) ||\n                        (at_head && node->prev && full_prev && !after))) {\n        /* If we are: full, and our prev/next is full, then:\n         *   - create new node and attach to quicklist */\n        D(\"\\tprovisioning new node...\");\n        new_node = quicklistCreateNode();\n        new_node->zl = ziplistPush(ziplistNew(), value, sz, ZIPLIST_HEAD);\n        new_node->count++;\n        quicklistNodeUpdateSz(new_node);\n        __quicklistInsertNode(quicklist, node, new_node, after);\n    } else if (full) {\n        /* else, node is full we need to split it. */\n        /* covers both after and !after cases */\n        D(\"\\tsplitting node...\");\n        quicklistDecompressNodeForUse(node);\n        new_node = _quicklistSplitNode(node, entry->offset, after);\n        new_node->zl = ziplistPush(new_node->zl, value, sz,\n                                   after ? ZIPLIST_HEAD : ZIPLIST_TAIL);\n        new_node->count++;\n        quicklistNodeUpdateSz(new_node);\n        __quicklistInsertNode(quicklist, node, new_node, after);\n        _quicklistMergeNodes(quicklist, node);\n    }\n\n    quicklist->count++;\n}\n\nvoid quicklistInsertBefore(quicklist *quicklist, quicklistEntry *entry,\n                           void *value, const size_t sz) {\n    _quicklistInsert(quicklist, entry, value, sz, 0);\n}\n\nvoid quicklistInsertAfter(quicklist *quicklist, quicklistEntry *entry,\n                          void *value, const size_t sz) {\n    _quicklistInsert(quicklist, entry, value, sz, 1);\n}\n\n/* Delete a range of elements from the quicklist.\n *\n * elements may span across multiple quicklistNodes, so we\n * have to be careful about tracking where we start and end.\n *\n * Returns 1 if entries were deleted, 0 if nothing was deleted. */\nint quicklistDelRange(quicklist *quicklist, const long start,\n                      const long count) {\n    if (count <= 0)\n        return 0;\n\n    unsigned long extent = count; /* range is inclusive of start position */\n\n    if (start >= 0 && extent > (quicklist->count - start)) {\n        /* if requesting delete more elements than exist, limit to list size. */\n        extent = quicklist->count - start;\n    } else if (start < 0 && extent > (unsigned long)(-start)) {\n        /* else, if at negative offset, limit max size to rest of list. */\n        extent = -start; /* c.f. LREM -29 29; just delete until end. */\n    }\n\n    quicklistEntry entry;\n    if (!quicklistIndex(quicklist, start, &entry))\n        return 0;\n\n    D(\"Quicklist delete request for start %ld, count %ld, extent: %ld\", start,\n      count, extent);\n    quicklistNode *node = entry.node;\n\n    /* iterate over next nodes until everything is deleted. */\n    while (extent) {\n        quicklistNode *next = node->next;\n\n        unsigned long del;\n        int delete_entire_node = 0;\n        if (entry.offset == 0 && extent >= node->count) {\n            /* If we are deleting more than the count of this node, we\n             * can just delete the entire node without ziplist math. */\n            delete_entire_node = 1;\n            del = node->count;\n        } else if (entry.offset >= 0 && extent >= node->count) {\n            /* If deleting more nodes after this one, calculate delete based\n             * on size of current node. */\n            del = node->count - entry.offset;\n        } else if (entry.offset < 0) {\n            /* If offset is negative, we are in the first run of this loop\n             * and we are deleting the entire range\n             * from this start offset to end of list.  Since the Negative\n             * offset is the number of elements until the tail of the list,\n             * just use it directly as the deletion count. */\n            del = -entry.offset;\n\n            /* If the positive offset is greater than the remaining extent,\n             * we only delete the remaining extent, not the entire offset.\n             */\n            if (del > extent)\n                del = extent;\n        } else {\n            /* else, we are deleting less than the extent of this node, so\n             * use extent directly. */\n            del = extent;\n        }\n\n        D(\"[%ld]: asking to del: %ld because offset: %d; (ENTIRE NODE: %d), \"\n          \"node count: %u\",\n          extent, del, entry.offset, delete_entire_node, node->count);\n\n        if (delete_entire_node) {\n            __quicklistDelNode(quicklist, node);\n        } else {\n            quicklistDecompressNodeForUse(node);\n            node->zl = ziplistDeleteRange(node->zl, entry.offset, del);\n            quicklistNodeUpdateSz(node);\n            node->count -= del;\n            quicklist->count -= del;\n            quicklistDeleteIfEmpty(quicklist, node);\n            if (node)\n                quicklistRecompressOnly(quicklist, node);\n        }\n\n        extent -= del;\n\n        node = next;\n\n        entry.offset = 0;\n    }\n    return 1;\n}\n\n/* Passthrough to ziplistCompare() */\nint quicklistCompare(unsigned char *p1, unsigned char *p2, int p2_len) {\n    return ziplistCompare(p1, p2, p2_len);\n}\n\n/* Returns a quicklist iterator 'iter'. After the initialization every\n * call to quicklistNext() will return the next element of the quicklist. */\nquicklistIter *quicklistGetIterator(const quicklist *quicklist, int direction) {\n    quicklistIter *iter;\n\n    iter = zmalloc(sizeof(*iter));\n\n    if (direction == AL_START_HEAD) {\n        iter->current = quicklist->head;\n        iter->offset = 0;\n    } else if (direction == AL_START_TAIL) {\n        iter->current = quicklist->tail;\n        iter->offset = -1;\n    }\n\n    iter->direction = direction;\n    iter->quicklist = quicklist;\n\n    iter->zi = NULL;\n\n    return iter;\n}\n\n/* Initialize an iterator at a specific offset 'idx' and make the iterator\n * return nodes in 'direction' direction. */\nquicklistIter *quicklistGetIteratorAtIdx(const quicklist *quicklist,\n                                         const int direction,\n                                         const long long idx) {\n    quicklistEntry entry;\n\n    if (quicklistIndex(quicklist, idx, &entry)) {\n        quicklistIter *base = quicklistGetIterator(quicklist, direction);\n        base->zi = NULL;\n        base->current = entry.node;\n        base->offset = entry.offset;\n        return base;\n    } else {\n        return NULL;\n    }\n}\n\n/* Release iterator.\n * If we still have a valid current node, then re-encode current node. */\nvoid quicklistReleaseIterator(quicklistIter *iter) {\n    if (iter->current)\n        quicklistCompress(iter->quicklist, iter->current);\n\n    zfree(iter);\n}\n\n/* Get next element in iterator.\n *\n * Note: You must NOT insert into the list while iterating over it.\n * You *may* delete from the list while iterating using the\n * quicklistDelEntry() function.\n * If you insert into the quicklist while iterating, you should\n * re-create the iterator after your addition.\n *\n * iter = quicklistGetIterator(quicklist,<direction>);\n * quicklistEntry entry;\n * while (quicklistNext(iter, &entry)) {\n *     if (entry.value)\n *          [[ use entry.value with entry.sz ]]\n *     else\n *          [[ use entry.longval ]]\n * }\n *\n * Populates 'entry' with values for this iteration.\n * Returns 0 when iteration is complete or if iteration not possible.\n * If return value is 0, the contents of 'entry' are not valid.\n */\nint quicklistNext(quicklistIter *iter, quicklistEntry *entry) {\n    initEntry(entry);\n\n    if (!iter) {\n        D(\"Returning because no iter!\");\n        return 0;\n    }\n\n    entry->quicklist = iter->quicklist;\n    entry->node = iter->current;\n\n    if (!iter->current) {\n        D(\"Returning because current node is NULL\")\n        return 0;\n    }\n\n    unsigned char *(*nextFn)(unsigned char *, unsigned char *) = NULL;\n    int offset_update = 0;\n\n    if (!iter->zi) {\n        /* If !zi, use current index. */\n        quicklistDecompressNodeForUse(iter->current);\n        iter->zi = ziplistIndex(iter->current->zl, iter->offset);\n    } else {\n        /* else, use existing iterator offset and get prev/next as necessary. */\n        if (iter->direction == AL_START_HEAD) {\n            nextFn = ziplistNext;\n            offset_update = 1;\n        } else if (iter->direction == AL_START_TAIL) {\n            nextFn = ziplistPrev;\n            offset_update = -1;\n        }\n        iter->zi = nextFn(iter->current->zl, iter->zi);\n        iter->offset += offset_update;\n    }\n\n    entry->zi = iter->zi;\n    entry->offset = iter->offset;\n\n    if (iter->zi) {\n        /* Populate value from existing ziplist position */\n        ziplistGet(entry->zi, &entry->value, &entry->sz, &entry->longval);\n        return 1;\n    } else {\n        /* We ran out of ziplist entries.\n         * Pick next node, update offset, then re-run retrieval. */\n        quicklistCompress(iter->quicklist, iter->current);\n        if (iter->direction == AL_START_HEAD) {\n            /* Forward traversal */\n            D(\"Jumping to start of next node\");\n            iter->current = iter->current->next;\n            iter->offset = 0;\n        } else if (iter->direction == AL_START_TAIL) {\n            /* Reverse traversal */\n            D(\"Jumping to end of previous node\");\n            iter->current = iter->current->prev;\n            iter->offset = -1;\n        }\n        iter->zi = NULL;\n        return quicklistNext(iter, entry);\n    }\n}\n\n/* Duplicate the quicklist.\n * On success a copy of the original quicklist is returned.\n *\n * The original quicklist both on success or error is never modified.\n *\n * Returns newly allocated quicklist. */\nquicklist *quicklistDup(quicklist *orig) {\n    quicklist *copy;\n\n    copy = quicklistNew(orig->fill, orig->compress);\n\n    for (quicklistNode *current = orig->head; current;\n         current = current->next) {\n        quicklistNode *node = quicklistCreateNode();\n\n        if (node->encoding == QUICKLIST_NODE_ENCODING_LZF) {\n            quicklistLZF *lzf = (quicklistLZF *)node->zl;\n            size_t lzf_sz = sizeof(*lzf) + lzf->sz;\n            node->zl = zmalloc(lzf_sz);\n            memcpy(node->zl, current->zl, lzf_sz);\n        } else if (node->encoding == QUICKLIST_NODE_ENCODING_RAW) {\n            node->zl = zmalloc(current->sz);\n            memcpy(node->zl, current->zl, current->sz);\n        }\n\n        node->count = current->count;\n        copy->count += node->count;\n        node->sz = current->sz;\n        node->encoding = current->encoding;\n\n        _quicklistInsertNodeAfter(copy, copy->tail, node);\n    }\n\n    /* copy->count must equal orig->count here */\n    return copy;\n}\n\n/* Populate 'entry' with the element at the specified zero-based index\n * where 0 is the head, 1 is the element next to head\n * and so on. Negative integers are used in order to count\n * from the tail, -1 is the last element, -2 the penultimate\n * and so on. If the index is out of range 0 is returned.\n *\n * Returns 1 if element found\n * Returns 0 if element not found */\nint quicklistIndex(const quicklist *quicklist, const long long idx,\n                   quicklistEntry *entry) {\n    quicklistNode *n;\n    unsigned long long accum = 0;\n    unsigned long long index;\n    int forward = idx < 0 ? 0 : 1; /* < 0 -> reverse, 0+ -> forward */\n\n    initEntry(entry);\n    entry->quicklist = quicklist;\n\n    if (!forward) {\n        index = (-idx) - 1;\n        n = quicklist->tail;\n    } else {\n        index = idx;\n        n = quicklist->head;\n    }\n\n    if (index >= quicklist->count)\n        return 0;\n\n    while (likely(n)) {\n        if ((accum + n->count) > index) {\n            break;\n        } else {\n            D(\"Skipping over (%p) %u at accum %lld\", (void *)n, n->count,\n              accum);\n            accum += n->count;\n            n = forward ? n->next : n->prev;\n        }\n    }\n\n    if (!n)\n        return 0;\n\n    D(\"Found node: %p at accum %llu, idx %llu, sub+ %llu, sub- %llu\", (void *)n,\n      accum, index, index - accum, (-index) - 1 + accum);\n\n    entry->node = n;\n    if (forward) {\n        /* forward = normal head-to-tail offset. */\n        entry->offset = index - accum;\n    } else {\n        /* reverse = need negative offset for tail-to-head, so undo\n         * the result of the original if (index < 0) above. */\n        entry->offset = (-index) - 1 + accum;\n    }\n\n    quicklistDecompressNodeForUse(entry->node);\n    entry->zi = ziplistIndex(entry->node->zl, entry->offset);\n    ziplistGet(entry->zi, &entry->value, &entry->sz, &entry->longval);\n    /* The caller will use our result, so we don't re-compress here.\n     * The caller can recompress or delete the node as needed. */\n    return 1;\n}\n\n/* Rotate quicklist by moving the tail element to the head. */\nvoid quicklistRotate(quicklist *quicklist) {\n    if (quicklist->count <= 1)\n        return;\n\n    /* First, get the tail entry */\n    unsigned char *p = ziplistIndex(quicklist->tail->zl, -1);\n    unsigned char *value;\n    long long longval;\n    unsigned int sz;\n    char longstr[32] = {0};\n    ziplistGet(p, &value, &sz, &longval);\n\n    /* If value found is NULL, then ziplistGet populated longval instead */\n    if (!value) {\n        /* Write the longval as a string so we can re-add it */\n        sz = ll2string(longstr, sizeof(longstr), longval);\n        value = (unsigned char *)longstr;\n    }\n\n    /* Add tail entry to head (must happen before tail is deleted). */\n    quicklistPushHead(quicklist, value, sz);\n\n    /* If quicklist has only one node, the head ziplist is also the\n     * tail ziplist and PushHead() could have reallocated our single ziplist,\n     * which would make our pre-existing 'p' unusable. */\n    if (quicklist->len == 1) {\n        p = ziplistIndex(quicklist->tail->zl, -1);\n    }\n\n    /* Remove tail entry. */\n    quicklistDelIndex(quicklist, quicklist->tail, &p);\n}\n\n/* pop from quicklist and return result in 'data' ptr.  Value of 'data'\n * is the return value of 'saver' function pointer if the data is NOT a number.\n *\n * If the quicklist element is a long long, then the return value is returned in\n * 'sval'.\n *\n * Return value of 0 means no elements available.\n * Return value of 1 means check 'data' and 'sval' for values.\n * If 'data' is set, use 'data' and 'sz'.  Otherwise, use 'sval'. */\nint quicklistPopCustom(quicklist *quicklist, int where, unsigned char **data,\n                       unsigned int *sz, long long *sval,\n                       void *(*saver)(unsigned char *data, unsigned int sz)) {\n    unsigned char *p;\n    unsigned char *vstr;\n    unsigned int vlen;\n    long long vlong;\n    int pos = (where == QUICKLIST_HEAD) ? 0 : -1;\n\n    if (quicklist->count == 0)\n        return 0;\n\n    if (data)\n        *data = NULL;\n    if (sz)\n        *sz = 0;\n    if (sval)\n        *sval = -123456789;\n\n    quicklistNode *node;\n    if (where == QUICKLIST_HEAD && quicklist->head) {\n        node = quicklist->head;\n    } else if (where == QUICKLIST_TAIL && quicklist->tail) {\n        node = quicklist->tail;\n    } else {\n        return 0;\n    }\n\n    p = ziplistIndex(node->zl, pos);\n    if (ziplistGet(p, &vstr, &vlen, &vlong)) {\n        if (vstr) {\n            if (data)\n                *data = saver(vstr, vlen);\n            if (sz)\n                *sz = vlen;\n        } else {\n            if (data)\n                *data = NULL;\n            if (sval)\n                *sval = vlong;\n        }\n        quicklistDelIndex(quicklist, node, &p);\n        return 1;\n    }\n    return 0;\n}\n\n/* Return a malloc'd copy of data passed in */\nREDIS_STATIC void *_quicklistSaver(unsigned char *data, unsigned int sz) {\n    unsigned char *vstr;\n    if (data) {\n        vstr = zmalloc(sz);\n        memcpy(vstr, data, sz);\n        return vstr;\n    }\n    return NULL;\n}\n\n/* Default pop function\n *\n * Returns malloc'd value from quicklist */\nint quicklistPop(quicklist *quicklist, int where, unsigned char **data,\n                 unsigned int *sz, long long *slong) {\n    unsigned char *vstr;\n    unsigned int vlen;\n    long long vlong;\n    if (quicklist->count == 0)\n        return 0;\n    int ret = quicklistPopCustom(quicklist, where, &vstr, &vlen, &vlong,\n                                 _quicklistSaver);\n    if (data)\n        *data = vstr;\n    if (slong)\n        *slong = vlong;\n    if (sz)\n        *sz = vlen;\n    return ret;\n}\n\n/* Wrapper to allow argument-based switching between HEAD/TAIL pop */\nvoid quicklistPush(quicklist *quicklist, void *value, const size_t sz,\n                   int where) {\n    if (where == QUICKLIST_HEAD) {\n        quicklistPushHead(quicklist, value, sz);\n    } else if (where == QUICKLIST_TAIL) {\n        quicklistPushTail(quicklist, value, sz);\n    }\n}\n\n/* The rest of this file is test cases and test helpers. */\n#ifdef REDIS_TEST\n#include <stdint.h>\n#include <sys/time.h>\n\n#define assert(_e)                                                             \\\n    do {                                                                       \\\n        if (!(_e)) {                                                           \\\n            printf(\"\\n\\n=== ASSERTION FAILED ===\\n\");                          \\\n            printf(\"==> %s:%d '%s' is not true\\n\", __FILE__, __LINE__, #_e);   \\\n            err++;                                                             \\\n        }                                                                      \\\n    } while (0)\n\n#define yell(str, ...) printf(\"ERROR! \" str \"\\n\\n\", __VA_ARGS__)\n\n#define OK printf(\"\\tOK\\n\")\n\n#define ERROR                                                                  \\\n    do {                                                                       \\\n        printf(\"\\tERROR!\\n\");                                                  \\\n        err++;                                                                 \\\n    } while (0)\n\n#define ERR(x, ...)                                                            \\\n    do {                                                                       \\\n        printf(\"%s:%s:%d:\\t\", __FILE__, __FUNCTION__, __LINE__);               \\\n        printf(\"ERROR! \" x \"\\n\", __VA_ARGS__);                                 \\\n        err++;                                                                 \\\n    } while (0)\n\n#define TEST(name) printf(\"test — %s\\n\", name);\n#define TEST_DESC(name, ...) printf(\"test — \" name \"\\n\", __VA_ARGS__);\n\n#define QL_TEST_VERBOSE 0\n\n#define UNUSED(x) (void)(x)\nstatic void ql_info(quicklist *ql) {\n#if QL_TEST_VERBOSE\n    printf(\"Container length: %lu\\n\", ql->len);\n    printf(\"Container size: %lu\\n\", ql->count);\n    if (ql->head)\n        printf(\"\\t(zsize head: %d)\\n\", ziplistLen(ql->head->zl));\n    if (ql->tail)\n        printf(\"\\t(zsize tail: %d)\\n\", ziplistLen(ql->tail->zl));\n    printf(\"\\n\");\n#else\n    UNUSED(ql);\n#endif\n}\n\n/* Return the UNIX time in microseconds */\nstatic long long ustime(void) {\n    struct timeval tv;\n    long long ust;\n\n    gettimeofday(&tv, NULL);\n    ust = ((long long)tv.tv_sec) * 1000000;\n    ust += tv.tv_usec;\n    return ust;\n}\n\n/* Return the UNIX time in milliseconds */\nstatic long long mstime(void) { return ustime() / 1000; }\n\n/* Iterate over an entire quicklist.\n * Print the list if 'print' == 1.\n *\n * Returns physical count of elements found by iterating over the list. */\nstatic int _itrprintr(quicklist *ql, int print, int forward) {\n    quicklistIter *iter =\n        quicklistGetIterator(ql, forward ? AL_START_HEAD : AL_START_TAIL);\n    quicklistEntry entry;\n    int i = 0;\n    int p = 0;\n    quicklistNode *prev = NULL;\n    while (quicklistNext(iter, &entry)) {\n        if (entry.node != prev) {\n            /* Count the number of list nodes too */\n            p++;\n            prev = entry.node;\n        }\n        if (print) {\n            printf(\"[%3d (%2d)]: [%.*s] (%lld)\\n\", i, p, entry.sz,\n                   (char *)entry.value, entry.longval);\n        }\n        i++;\n    }\n    quicklistReleaseIterator(iter);\n    return i;\n}\nstatic int itrprintr(quicklist *ql, int print) {\n    return _itrprintr(ql, print, 1);\n}\n\nstatic int itrprintr_rev(quicklist *ql, int print) {\n    return _itrprintr(ql, print, 0);\n}\n\n#define ql_verify(a, b, c, d, e)                                               \\\n    do {                                                                       \\\n        err += _ql_verify((a), (b), (c), (d), (e));                            \\\n    } while (0)\n\n/* Verify list metadata matches physical list contents. */\nstatic int _ql_verify(quicklist *ql, uint32_t len, uint32_t count,\n                      uint32_t head_count, uint32_t tail_count) {\n    int errors = 0;\n\n    ql_info(ql);\n    if (len != ql->len) {\n        yell(\"quicklist length wrong: expected %d, got %u\", len, ql->len);\n        errors++;\n    }\n\n    if (count != ql->count) {\n        yell(\"quicklist count wrong: expected %d, got %lu\", count, ql->count);\n        errors++;\n    }\n\n    int loopr = itrprintr(ql, 0);\n    if (loopr != (int)ql->count) {\n        yell(\"quicklist cached count not match actual count: expected %lu, got \"\n             \"%d\",\n             ql->count, loopr);\n        errors++;\n    }\n\n    int rloopr = itrprintr_rev(ql, 0);\n    if (loopr != rloopr) {\n        yell(\"quicklist has different forward count than reverse count!  \"\n             \"Forward count is %d, reverse count is %d.\",\n             loopr, rloopr);\n        errors++;\n    }\n\n    if (ql->len == 0 && !errors) {\n        OK;\n        return errors;\n    }\n\n    if (ql->head && head_count != ql->head->count &&\n        head_count != ziplistLen(ql->head->zl)) {\n        yell(\"quicklist head count wrong: expected %d, \"\n             \"got cached %d vs. actual %d\",\n             head_count, ql->head->count, ziplistLen(ql->head->zl));\n        errors++;\n    }\n\n    if (ql->tail && tail_count != ql->tail->count &&\n        tail_count != ziplistLen(ql->tail->zl)) {\n        yell(\"quicklist tail count wrong: expected %d, \"\n             \"got cached %u vs. actual %d\",\n             tail_count, ql->tail->count, ziplistLen(ql->tail->zl));\n        errors++;\n    }\n\n    if (quicklistAllowsCompression(ql)) {\n        quicklistNode *node = ql->head;\n        unsigned int low_raw = ql->compress;\n        unsigned int high_raw = ql->len - ql->compress;\n\n        for (unsigned int at = 0; at < ql->len; at++, node = node->next) {\n            if (node && (at < low_raw || at >= high_raw)) {\n                if (node->encoding != QUICKLIST_NODE_ENCODING_RAW) {\n                    yell(\"Incorrect compression: node %d is \"\n                         \"compressed at depth %d ((%u, %u); total \"\n                         \"nodes: %u; size: %u; recompress: %d)\",\n                         at, ql->compress, low_raw, high_raw, ql->len, node->sz,\n                         node->recompress);\n                    errors++;\n                }\n            } else {\n                if (node->encoding != QUICKLIST_NODE_ENCODING_LZF &&\n                    !node->attempted_compress) {\n                    yell(\"Incorrect non-compression: node %d is NOT \"\n                         \"compressed at depth %d ((%u, %u); total \"\n                         \"nodes: %u; size: %u; recompress: %d; attempted: %d)\",\n                         at, ql->compress, low_raw, high_raw, ql->len, node->sz,\n                         node->recompress, node->attempted_compress);\n                    errors++;\n                }\n            }\n        }\n    }\n\n    if (!errors)\n        OK;\n    return errors;\n}\n\n/* Generate new string concatenating integer i against string 'prefix' */\nstatic char *genstr(char *prefix, int i) {\n    static char result[64] = {0};\n    snprintf(result, sizeof(result), \"%s%d\", prefix, i);\n    return result;\n}\n\n/* main test, but callable from other files */\nint quicklistTest(int argc, char *argv[]) {\n    UNUSED(argc);\n    UNUSED(argv);\n\n    unsigned int err = 0;\n    int optimize_start =\n        -(int)(sizeof(optimization_level) / sizeof(*optimization_level));\n\n    printf(\"Starting optimization offset at: %d\\n\", optimize_start);\n\n    int options[] = {0, 1, 2, 3, 4, 5, 6, 10};\n    size_t option_count = sizeof(options) / sizeof(*options);\n    long long runtime[option_count];\n\n    for (int _i = 0; _i < (int)option_count; _i++) {\n        printf(\"Testing Option %d\\n\", options[_i]);\n        long long start = mstime();\n\n        TEST(\"create list\") {\n            quicklist *ql = quicklistNew(-2, options[_i]);\n            ql_verify(ql, 0, 0, 0, 0);\n            quicklistRelease(ql);\n        }\n\n        TEST(\"add to tail of empty list\") {\n            quicklist *ql = quicklistNew(-2, options[_i]);\n            quicklistPushTail(ql, \"hello\", 6);\n            /* 1 for head and 1 for tail beacuse 1 node = head = tail */\n            ql_verify(ql, 1, 1, 1, 1);\n            quicklistRelease(ql);\n        }\n\n        TEST(\"add to head of empty list\") {\n            quicklist *ql = quicklistNew(-2, options[_i]);\n            quicklistPushHead(ql, \"hello\", 6);\n            /* 1 for head and 1 for tail beacuse 1 node = head = tail */\n            ql_verify(ql, 1, 1, 1, 1);\n            quicklistRelease(ql);\n        }\n\n        for (int f = optimize_start; f < 32; f++) {\n            TEST_DESC(\"add to tail 5x at fill %d at compress %d\", f,\n                      options[_i]) {\n                quicklist *ql = quicklistNew(f, options[_i]);\n                for (int i = 0; i < 5; i++)\n                    quicklistPushTail(ql, genstr(\"hello\", i), 32);\n                if (ql->count != 5)\n                    ERROR;\n                if (f == 32)\n                    ql_verify(ql, 1, 5, 5, 5);\n                quicklistRelease(ql);\n            }\n        }\n\n        for (int f = optimize_start; f < 32; f++) {\n            TEST_DESC(\"add to head 5x at fill %d at compress %d\", f,\n                      options[_i]) {\n                quicklist *ql = quicklistNew(f, options[_i]);\n                for (int i = 0; i < 5; i++)\n                    quicklistPushHead(ql, genstr(\"hello\", i), 32);\n                if (ql->count != 5)\n                    ERROR;\n                if (f == 32)\n                    ql_verify(ql, 1, 5, 5, 5);\n                quicklistRelease(ql);\n            }\n        }\n\n        for (int f = optimize_start; f < 512; f++) {\n            TEST_DESC(\"add to tail 500x at fill %d at compress %d\", f,\n                      options[_i]) {\n                quicklist *ql = quicklistNew(f, options[_i]);\n                for (int i = 0; i < 500; i++)\n                    quicklistPushTail(ql, genstr(\"hello\", i), 64);\n                if (ql->count != 500)\n                    ERROR;\n                if (f == 32)\n                    ql_verify(ql, 16, 500, 32, 20);\n                quicklistRelease(ql);\n            }\n        }\n\n        for (int f = optimize_start; f < 512; f++) {\n            TEST_DESC(\"add to head 500x at fill %d at compress %d\", f,\n                      options[_i]) {\n                quicklist *ql = quicklistNew(f, options[_i]);\n                for (int i = 0; i < 500; i++)\n                    quicklistPushHead(ql, genstr(\"hello\", i), 32);\n                if (ql->count != 500)\n                    ERROR;\n                if (f == 32)\n                    ql_verify(ql, 16, 500, 20, 32);\n                quicklistRelease(ql);\n            }\n        }\n\n        TEST(\"rotate empty\") {\n            quicklist *ql = quicklistNew(-2, options[_i]);\n            quicklistRotate(ql);\n            ql_verify(ql, 0, 0, 0, 0);\n            quicklistRelease(ql);\n        }\n\n        for (int f = optimize_start; f < 32; f++) {\n            TEST(\"rotate one val once\") {\n                quicklist *ql = quicklistNew(f, options[_i]);\n                quicklistPushHead(ql, \"hello\", 6);\n                quicklistRotate(ql);\n                /* Ignore compression verify because ziplist is\n                 * too small to compress. */\n                ql_verify(ql, 1, 1, 1, 1);\n                quicklistRelease(ql);\n            }\n        }\n\n        for (int f = optimize_start; f < 3; f++) {\n            TEST_DESC(\"rotate 500 val 5000 times at fill %d at compress %d\", f,\n                      options[_i]) {\n                quicklist *ql = quicklistNew(f, options[_i]);\n                quicklistPushHead(ql, \"900\", 3);\n                quicklistPushHead(ql, \"7000\", 4);\n                quicklistPushHead(ql, \"-1200\", 5);\n                quicklistPushHead(ql, \"42\", 2);\n                for (int i = 0; i < 500; i++)\n                    quicklistPushHead(ql, genstr(\"hello\", i), 64);\n                ql_info(ql);\n                for (int i = 0; i < 5000; i++) {\n                    ql_info(ql);\n                    quicklistRotate(ql);\n                }\n                if (f == 1)\n                    ql_verify(ql, 504, 504, 1, 1);\n                else if (f == 2)\n                    ql_verify(ql, 252, 504, 2, 2);\n                else if (f == 32)\n                    ql_verify(ql, 16, 504, 32, 24);\n                quicklistRelease(ql);\n            }\n        }\n\n        TEST(\"pop empty\") {\n            quicklist *ql = quicklistNew(-2, options[_i]);\n            quicklistPop(ql, QUICKLIST_HEAD, NULL, NULL, NULL);\n            ql_verify(ql, 0, 0, 0, 0);\n            quicklistRelease(ql);\n        }\n\n        TEST(\"pop 1 string from 1\") {\n            quicklist *ql = quicklistNew(-2, options[_i]);\n            char *populate = genstr(\"hello\", 331);\n            quicklistPushHead(ql, populate, 32);\n            unsigned char *data;\n            unsigned int sz;\n            long long lv;\n            ql_info(ql);\n            quicklistPop(ql, QUICKLIST_HEAD, &data, &sz, &lv);\n            assert(data != NULL);\n            assert(sz == 32);\n            if (strcmp(populate, (char *)data))\n                ERR(\"Pop'd value (%.*s) didn't equal original value (%s)\", sz,\n                    data, populate);\n            zfree(data);\n            ql_verify(ql, 0, 0, 0, 0);\n            quicklistRelease(ql);\n        }\n\n        TEST(\"pop head 1 number from 1\") {\n            quicklist *ql = quicklistNew(-2, options[_i]);\n            quicklistPushHead(ql, \"55513\", 5);\n            unsigned char *data;\n            unsigned int sz;\n            long long lv;\n            ql_info(ql);\n            quicklistPop(ql, QUICKLIST_HEAD, &data, &sz, &lv);\n            assert(data == NULL);\n            assert(lv == 55513);\n            ql_verify(ql, 0, 0, 0, 0);\n            quicklistRelease(ql);\n        }\n\n        TEST(\"pop head 500 from 500\") {\n            quicklist *ql = quicklistNew(-2, options[_i]);\n            for (int i = 0; i < 500; i++)\n                quicklistPushHead(ql, genstr(\"hello\", i), 32);\n            ql_info(ql);\n            for (int i = 0; i < 500; i++) {\n                unsigned char *data;\n                unsigned int sz;\n                long long lv;\n                int ret = quicklistPop(ql, QUICKLIST_HEAD, &data, &sz, &lv);\n                assert(ret == 1);\n                assert(data != NULL);\n                assert(sz == 32);\n                if (strcmp(genstr(\"hello\", 499 - i), (char *)data))\n                    ERR(\"Pop'd value (%.*s) didn't equal original value (%s)\",\n                        sz, data, genstr(\"hello\", 499 - i));\n                zfree(data);\n            }\n            ql_verify(ql, 0, 0, 0, 0);\n            quicklistRelease(ql);\n        }\n\n        TEST(\"pop head 5000 from 500\") {\n            quicklist *ql = quicklistNew(-2, options[_i]);\n            for (int i = 0; i < 500; i++)\n                quicklistPushHead(ql, genstr(\"hello\", i), 32);\n            for (int i = 0; i < 5000; i++) {\n                unsigned char *data;\n                unsigned int sz;\n                long long lv;\n                int ret = quicklistPop(ql, QUICKLIST_HEAD, &data, &sz, &lv);\n                if (i < 500) {\n                    assert(ret == 1);\n                    assert(data != NULL);\n                    assert(sz == 32);\n                    if (strcmp(genstr(\"hello\", 499 - i), (char *)data))\n                        ERR(\"Pop'd value (%.*s) didn't equal original value \"\n                            \"(%s)\",\n                            sz, data, genstr(\"hello\", 499 - i));\n                    zfree(data);\n                } else {\n                    assert(ret == 0);\n                }\n            }\n            ql_verify(ql, 0, 0, 0, 0);\n            quicklistRelease(ql);\n        }\n\n        TEST(\"iterate forward over 500 list\") {\n            quicklist *ql = quicklistNew(-2, options[_i]);\n            quicklistSetFill(ql, 32);\n            for (int i = 0; i < 500; i++)\n                quicklistPushHead(ql, genstr(\"hello\", i), 32);\n            quicklistIter *iter = quicklistGetIterator(ql, AL_START_HEAD);\n            quicklistEntry entry;\n            int i = 499, count = 0;\n            while (quicklistNext(iter, &entry)) {\n                char *h = genstr(\"hello\", i);\n                if (strcmp((char *)entry.value, h))\n                    ERR(\"value [%s] didn't match [%s] at position %d\",\n                        entry.value, h, i);\n                i--;\n                count++;\n            }\n            if (count != 500)\n                ERR(\"Didn't iterate over exactly 500 elements (%d)\", i);\n            ql_verify(ql, 16, 500, 20, 32);\n            quicklistReleaseIterator(iter);\n            quicklistRelease(ql);\n        }\n\n        TEST(\"iterate reverse over 500 list\") {\n            quicklist *ql = quicklistNew(-2, options[_i]);\n            quicklistSetFill(ql, 32);\n            for (int i = 0; i < 500; i++)\n                quicklistPushHead(ql, genstr(\"hello\", i), 32);\n            quicklistIter *iter = quicklistGetIterator(ql, AL_START_TAIL);\n            quicklistEntry entry;\n            int i = 0;\n            while (quicklistNext(iter, &entry)) {\n                char *h = genstr(\"hello\", i);\n                if (strcmp((char *)entry.value, h))\n                    ERR(\"value [%s] didn't match [%s] at position %d\",\n                        entry.value, h, i);\n                i++;\n            }\n            if (i != 500)\n                ERR(\"Didn't iterate over exactly 500 elements (%d)\", i);\n            ql_verify(ql, 16, 500, 20, 32);\n            quicklistReleaseIterator(iter);\n            quicklistRelease(ql);\n        }\n\n        TEST(\"insert before with 0 elements\") {\n            quicklist *ql = quicklistNew(-2, options[_i]);\n            quicklistEntry entry;\n            quicklistIndex(ql, 0, &entry);\n            quicklistInsertBefore(ql, &entry, \"abc\", 4);\n            ql_verify(ql, 1, 1, 1, 1);\n            quicklistRelease(ql);\n        }\n\n        TEST(\"insert after with 0 elements\") {\n            quicklist *ql = quicklistNew(-2, options[_i]);\n            quicklistEntry entry;\n            quicklistIndex(ql, 0, &entry);\n            quicklistInsertAfter(ql, &entry, \"abc\", 4);\n            ql_verify(ql, 1, 1, 1, 1);\n            quicklistRelease(ql);\n        }\n\n        TEST(\"insert after 1 element\") {\n            quicklist *ql = quicklistNew(-2, options[_i]);\n            quicklistPushHead(ql, \"hello\", 6);\n            quicklistEntry entry;\n            quicklistIndex(ql, 0, &entry);\n            quicklistInsertAfter(ql, &entry, \"abc\", 4);\n            ql_verify(ql, 1, 2, 2, 2);\n            quicklistRelease(ql);\n        }\n\n        TEST(\"insert before 1 element\") {\n            quicklist *ql = quicklistNew(-2, options[_i]);\n            quicklistPushHead(ql, \"hello\", 6);\n            quicklistEntry entry;\n            quicklistIndex(ql, 0, &entry);\n            quicklistInsertAfter(ql, &entry, \"abc\", 4);\n            ql_verify(ql, 1, 2, 2, 2);\n            quicklistRelease(ql);\n        }\n\n        for (int f = optimize_start; f < 12; f++) {\n            TEST_DESC(\"insert once in elements while iterating at fill %d at \"\n                      \"compress %d\\n\",\n                      f, options[_i]) {\n                quicklist *ql = quicklistNew(f, options[_i]);\n                quicklistPushTail(ql, \"abc\", 3);\n                quicklistSetFill(ql, 1);\n                quicklistPushTail(ql, \"def\", 3); /* force to unique node */\n                quicklistSetFill(ql, f);\n                quicklistPushTail(ql, \"bob\", 3); /* force to reset for +3 */\n                quicklistPushTail(ql, \"foo\", 3);\n                quicklistPushTail(ql, \"zoo\", 3);\n\n                itrprintr(ql, 0);\n                /* insert \"bar\" before \"bob\" while iterating over list. */\n                quicklistIter *iter = quicklistGetIterator(ql, AL_START_HEAD);\n                quicklistEntry entry;\n                while (quicklistNext(iter, &entry)) {\n                    if (!strncmp((char *)entry.value, \"bob\", 3)) {\n                        /* Insert as fill = 1 so it spills into new node. */\n                        quicklistInsertBefore(ql, &entry, \"bar\", 3);\n                        break; /* didn't we fix insert-while-iterating? */\n                    }\n                }\n                itrprintr(ql, 0);\n\n                /* verify results */\n                quicklistIndex(ql, 0, &entry);\n                if (strncmp((char *)entry.value, \"abc\", 3))\n                    ERR(\"Value 0 didn't match, instead got: %.*s\", entry.sz,\n                        entry.value);\n                quicklistIndex(ql, 1, &entry);\n                if (strncmp((char *)entry.value, \"def\", 3))\n                    ERR(\"Value 1 didn't match, instead got: %.*s\", entry.sz,\n                        entry.value);\n                quicklistIndex(ql, 2, &entry);\n                if (strncmp((char *)entry.value, \"bar\", 3))\n                    ERR(\"Value 2 didn't match, instead got: %.*s\", entry.sz,\n                        entry.value);\n                quicklistIndex(ql, 3, &entry);\n                if (strncmp((char *)entry.value, \"bob\", 3))\n                    ERR(\"Value 3 didn't match, instead got: %.*s\", entry.sz,\n                        entry.value);\n                quicklistIndex(ql, 4, &entry);\n                if (strncmp((char *)entry.value, \"foo\", 3))\n                    ERR(\"Value 4 didn't match, instead got: %.*s\", entry.sz,\n                        entry.value);\n                quicklistIndex(ql, 5, &entry);\n                if (strncmp((char *)entry.value, \"zoo\", 3))\n                    ERR(\"Value 5 didn't match, instead got: %.*s\", entry.sz,\n                        entry.value);\n                quicklistReleaseIterator(iter);\n                quicklistRelease(ql);\n            }\n        }\n\n        for (int f = optimize_start; f < 1024; f++) {\n            TEST_DESC(\n                \"insert [before] 250 new in middle of 500 elements at fill\"\n                \" %d at compress %d\",\n                f, options[_i]) {\n                quicklist *ql = quicklistNew(f, options[_i]);\n                for (int i = 0; i < 500; i++)\n                    quicklistPushTail(ql, genstr(\"hello\", i), 32);\n                for (int i = 0; i < 250; i++) {\n                    quicklistEntry entry;\n                    quicklistIndex(ql, 250, &entry);\n                    quicklistInsertBefore(ql, &entry, genstr(\"abc\", i), 32);\n                }\n                if (f == 32)\n                    ql_verify(ql, 25, 750, 32, 20);\n                quicklistRelease(ql);\n            }\n        }\n\n        for (int f = optimize_start; f < 1024; f++) {\n            TEST_DESC(\"insert [after] 250 new in middle of 500 elements at \"\n                      \"fill %d at compress %d\",\n                      f, options[_i]) {\n                quicklist *ql = quicklistNew(f, options[_i]);\n                for (int i = 0; i < 500; i++)\n                    quicklistPushHead(ql, genstr(\"hello\", i), 32);\n                for (int i = 0; i < 250; i++) {\n                    quicklistEntry entry;\n                    quicklistIndex(ql, 250, &entry);\n                    quicklistInsertAfter(ql, &entry, genstr(\"abc\", i), 32);\n                }\n\n                if (ql->count != 750)\n                    ERR(\"List size not 750, but rather %ld\", ql->count);\n\n                if (f == 32)\n                    ql_verify(ql, 26, 750, 20, 32);\n                quicklistRelease(ql);\n            }\n        }\n\n        TEST(\"duplicate empty list\") {\n            quicklist *ql = quicklistNew(-2, options[_i]);\n            ql_verify(ql, 0, 0, 0, 0);\n            quicklist *copy = quicklistDup(ql);\n            ql_verify(copy, 0, 0, 0, 0);\n            quicklistRelease(ql);\n            quicklistRelease(copy);\n        }\n\n        TEST(\"duplicate list of 1 element\") {\n            quicklist *ql = quicklistNew(-2, options[_i]);\n            quicklistPushHead(ql, genstr(\"hello\", 3), 32);\n            ql_verify(ql, 1, 1, 1, 1);\n            quicklist *copy = quicklistDup(ql);\n            ql_verify(copy, 1, 1, 1, 1);\n            quicklistRelease(ql);\n            quicklistRelease(copy);\n        }\n\n        TEST(\"duplicate list of 500\") {\n            quicklist *ql = quicklistNew(-2, options[_i]);\n            quicklistSetFill(ql, 32);\n            for (int i = 0; i < 500; i++)\n                quicklistPushHead(ql, genstr(\"hello\", i), 32);\n            ql_verify(ql, 16, 500, 20, 32);\n\n            quicklist *copy = quicklistDup(ql);\n            ql_verify(copy, 16, 500, 20, 32);\n            quicklistRelease(ql);\n            quicklistRelease(copy);\n        }\n\n        for (int f = optimize_start; f < 512; f++) {\n            TEST_DESC(\"index 1,200 from 500 list at fill %d at compress %d\", f,\n                      options[_i]) {\n                quicklist *ql = quicklistNew(f, options[_i]);\n                for (int i = 0; i < 500; i++)\n                    quicklistPushTail(ql, genstr(\"hello\", i + 1), 32);\n                quicklistEntry entry;\n                quicklistIndex(ql, 1, &entry);\n                if (!strcmp((char *)entry.value, \"hello2\"))\n                    OK;\n                else\n                    ERR(\"Value: %s\", entry.value);\n                quicklistIndex(ql, 200, &entry);\n                if (!strcmp((char *)entry.value, \"hello201\"))\n                    OK;\n                else\n                    ERR(\"Value: %s\", entry.value);\n                quicklistRelease(ql);\n            }\n\n            TEST_DESC(\"index -1,-2 from 500 list at fill %d at compress %d\", f,\n                      options[_i]) {\n                quicklist *ql = quicklistNew(f, options[_i]);\n                for (int i = 0; i < 500; i++)\n                    quicklistPushTail(ql, genstr(\"hello\", i + 1), 32);\n                quicklistEntry entry;\n                quicklistIndex(ql, -1, &entry);\n                if (!strcmp((char *)entry.value, \"hello500\"))\n                    OK;\n                else\n                    ERR(\"Value: %s\", entry.value);\n                quicklistIndex(ql, -2, &entry);\n                if (!strcmp((char *)entry.value, \"hello499\"))\n                    OK;\n                else\n                    ERR(\"Value: %s\", entry.value);\n                quicklistRelease(ql);\n            }\n\n            TEST_DESC(\"index -100 from 500 list at fill %d at compress %d\", f,\n                      options[_i]) {\n                quicklist *ql = quicklistNew(f, options[_i]);\n                for (int i = 0; i < 500; i++)\n                    quicklistPushTail(ql, genstr(\"hello\", i + 1), 32);\n                quicklistEntry entry;\n                quicklistIndex(ql, -100, &entry);\n                if (!strcmp((char *)entry.value, \"hello401\"))\n                    OK;\n                else\n                    ERR(\"Value: %s\", entry.value);\n                quicklistRelease(ql);\n            }\n\n            TEST_DESC(\"index too big +1 from 50 list at fill %d at compress %d\",\n                      f, options[_i]) {\n                quicklist *ql = quicklistNew(f, options[_i]);\n                for (int i = 0; i < 50; i++)\n                    quicklistPushTail(ql, genstr(\"hello\", i + 1), 32);\n                quicklistEntry entry;\n                if (quicklistIndex(ql, 50, &entry))\n                    ERR(\"Index found at 50 with 50 list: %.*s\", entry.sz,\n                        entry.value);\n                else\n                    OK;\n                quicklistRelease(ql);\n            }\n        }\n\n        TEST(\"delete range empty list\") {\n            quicklist *ql = quicklistNew(-2, options[_i]);\n            quicklistDelRange(ql, 5, 20);\n            ql_verify(ql, 0, 0, 0, 0);\n            quicklistRelease(ql);\n        }\n\n        TEST(\"delete range of entire node in list of one node\") {\n            quicklist *ql = quicklistNew(-2, options[_i]);\n            for (int i = 0; i < 32; i++)\n                quicklistPushHead(ql, genstr(\"hello\", i), 32);\n            ql_verify(ql, 1, 32, 32, 32);\n            quicklistDelRange(ql, 0, 32);\n            ql_verify(ql, 0, 0, 0, 0);\n            quicklistRelease(ql);\n        }\n\n        TEST(\"delete range of entire node with overflow counts\") {\n            quicklist *ql = quicklistNew(-2, options[_i]);\n            for (int i = 0; i < 32; i++)\n                quicklistPushHead(ql, genstr(\"hello\", i), 32);\n            ql_verify(ql, 1, 32, 32, 32);\n            quicklistDelRange(ql, 0, 128);\n            ql_verify(ql, 0, 0, 0, 0);\n            quicklistRelease(ql);\n        }\n\n        TEST(\"delete middle 100 of 500 list\") {\n            quicklist *ql = quicklistNew(-2, options[_i]);\n            quicklistSetFill(ql, 32);\n            for (int i = 0; i < 500; i++)\n                quicklistPushTail(ql, genstr(\"hello\", i + 1), 32);\n            ql_verify(ql, 16, 500, 32, 20);\n            quicklistDelRange(ql, 200, 100);\n            ql_verify(ql, 14, 400, 32, 20);\n            quicklistRelease(ql);\n        }\n\n        TEST(\"delete negative 1 from 500 list\") {\n            quicklist *ql = quicklistNew(-2, options[_i]);\n            quicklistSetFill(ql, 32);\n            for (int i = 0; i < 500; i++)\n                quicklistPushTail(ql, genstr(\"hello\", i + 1), 32);\n            ql_verify(ql, 16, 500, 32, 20);\n            quicklistDelRange(ql, -1, 1);\n            ql_verify(ql, 16, 499, 32, 19);\n            quicklistRelease(ql);\n        }\n\n        TEST(\"delete negative 1 from 500 list with overflow counts\") {\n            quicklist *ql = quicklistNew(-2, options[_i]);\n            quicklistSetFill(ql, 32);\n            for (int i = 0; i < 500; i++)\n                quicklistPushTail(ql, genstr(\"hello\", i + 1), 32);\n            ql_verify(ql, 16, 500, 32, 20);\n            quicklistDelRange(ql, -1, 128);\n            ql_verify(ql, 16, 499, 32, 19);\n            quicklistRelease(ql);\n        }\n\n        TEST(\"delete negative 100 from 500 list\") {\n            quicklist *ql = quicklistNew(-2, options[_i]);\n            quicklistSetFill(ql, 32);\n            for (int i = 0; i < 500; i++)\n                quicklistPushTail(ql, genstr(\"hello\", i + 1), 32);\n            quicklistDelRange(ql, -100, 100);\n            ql_verify(ql, 13, 400, 32, 16);\n            quicklistRelease(ql);\n        }\n\n        TEST(\"delete -10 count 5 from 50 list\") {\n            quicklist *ql = quicklistNew(-2, options[_i]);\n            quicklistSetFill(ql, 32);\n            for (int i = 0; i < 50; i++)\n                quicklistPushTail(ql, genstr(\"hello\", i + 1), 32);\n            ql_verify(ql, 2, 50, 32, 18);\n            quicklistDelRange(ql, -10, 5);\n            ql_verify(ql, 2, 45, 32, 13);\n            quicklistRelease(ql);\n        }\n\n        TEST(\"numbers only list read\") {\n            quicklist *ql = quicklistNew(-2, options[_i]);\n            quicklistPushTail(ql, \"1111\", 4);\n            quicklistPushTail(ql, \"2222\", 4);\n            quicklistPushTail(ql, \"3333\", 4);\n            quicklistPushTail(ql, \"4444\", 4);\n            ql_verify(ql, 1, 4, 4, 4);\n            quicklistEntry entry;\n            quicklistIndex(ql, 0, &entry);\n            if (entry.longval != 1111)\n                ERR(\"Not 1111, %lld\", entry.longval);\n            quicklistIndex(ql, 1, &entry);\n            if (entry.longval != 2222)\n                ERR(\"Not 2222, %lld\", entry.longval);\n            quicklistIndex(ql, 2, &entry);\n            if (entry.longval != 3333)\n                ERR(\"Not 3333, %lld\", entry.longval);\n            quicklistIndex(ql, 3, &entry);\n            if (entry.longval != 4444)\n                ERR(\"Not 4444, %lld\", entry.longval);\n            if (quicklistIndex(ql, 4, &entry))\n                ERR(\"Index past elements: %lld\", entry.longval);\n            quicklistIndex(ql, -1, &entry);\n            if (entry.longval != 4444)\n                ERR(\"Not 4444 (reverse), %lld\", entry.longval);\n            quicklistIndex(ql, -2, &entry);\n            if (entry.longval != 3333)\n                ERR(\"Not 3333 (reverse), %lld\", entry.longval);\n            quicklistIndex(ql, -3, &entry);\n            if (entry.longval != 2222)\n                ERR(\"Not 2222 (reverse), %lld\", entry.longval);\n            quicklistIndex(ql, -4, &entry);\n            if (entry.longval != 1111)\n                ERR(\"Not 1111 (reverse), %lld\", entry.longval);\n            if (quicklistIndex(ql, -5, &entry))\n                ERR(\"Index past elements (reverse), %lld\", entry.longval);\n            quicklistRelease(ql);\n        }\n\n        TEST(\"numbers larger list read\") {\n            quicklist *ql = quicklistNew(-2, options[_i]);\n            quicklistSetFill(ql, 32);\n            char num[32];\n            long long nums[5000];\n            for (int i = 0; i < 5000; i++) {\n                nums[i] = -5157318210846258176 + i;\n                int sz = ll2string(num, sizeof(num), nums[i]);\n                quicklistPushTail(ql, num, sz);\n            }\n            quicklistPushTail(ql, \"xxxxxxxxxxxxxxxxxxxx\", 20);\n            quicklistEntry entry;\n            for (int i = 0; i < 5000; i++) {\n                quicklistIndex(ql, i, &entry);\n                if (entry.longval != nums[i])\n                    ERR(\"[%d] Not longval %lld but rather %lld\", i, nums[i],\n                        entry.longval);\n                entry.longval = 0xdeadbeef;\n            }\n            quicklistIndex(ql, 5000, &entry);\n            if (strncmp((char *)entry.value, \"xxxxxxxxxxxxxxxxxxxx\", 20))\n                ERR(\"String val not match: %s\", entry.value);\n            ql_verify(ql, 157, 5001, 32, 9);\n            quicklistRelease(ql);\n        }\n\n        TEST(\"numbers larger list read B\") {\n            quicklist *ql = quicklistNew(-2, options[_i]);\n            quicklistPushTail(ql, \"99\", 2);\n            quicklistPushTail(ql, \"98\", 2);\n            quicklistPushTail(ql, \"xxxxxxxxxxxxxxxxxxxx\", 20);\n            quicklistPushTail(ql, \"96\", 2);\n            quicklistPushTail(ql, \"95\", 2);\n            quicklistReplaceAtIndex(ql, 1, \"foo\", 3);\n            quicklistReplaceAtIndex(ql, -1, \"bar\", 3);\n            quicklistRelease(ql);\n            OK;\n        }\n\n        for (int f = optimize_start; f < 16; f++) {\n            TEST_DESC(\"lrem test at fill %d at compress %d\", f, options[_i]) {\n                quicklist *ql = quicklistNew(f, options[_i]);\n                char *words[] = {\"abc\", \"foo\", \"bar\",  \"foobar\", \"foobared\",\n                                 \"zap\", \"bar\", \"test\", \"foo\"};\n                char *result[] = {\"abc\", \"foo\",  \"foobar\", \"foobared\",\n                                  \"zap\", \"test\", \"foo\"};\n                char *resultB[] = {\"abc\",      \"foo\", \"foobar\",\n                                   \"foobared\", \"zap\", \"test\"};\n                for (int i = 0; i < 9; i++)\n                    quicklistPushTail(ql, words[i], strlen(words[i]));\n\n                /* lrem 0 bar */\n                quicklistIter *iter = quicklistGetIterator(ql, AL_START_HEAD);\n                quicklistEntry entry;\n                int i = 0;\n                while (quicklistNext(iter, &entry)) {\n                    if (quicklistCompare(entry.zi, (unsigned char *)\"bar\", 3)) {\n                        quicklistDelEntry(iter, &entry);\n                    }\n                    i++;\n                }\n                quicklistReleaseIterator(iter);\n\n                /* check result of lrem 0 bar */\n                iter = quicklistGetIterator(ql, AL_START_HEAD);\n                i = 0;\n                int ok = 1;\n                while (quicklistNext(iter, &entry)) {\n                    /* Result must be: abc, foo, foobar, foobared, zap, test,\n                     * foo */\n                    if (strncmp((char *)entry.value, result[i], entry.sz)) {\n                        ERR(\"No match at position %d, got %.*s instead of %s\",\n                            i, entry.sz, entry.value, result[i]);\n                        ok = 0;\n                    }\n                    i++;\n                }\n                quicklistReleaseIterator(iter);\n\n                quicklistPushTail(ql, \"foo\", 3);\n\n                /* lrem -2 foo */\n                iter = quicklistGetIterator(ql, AL_START_TAIL);\n                i = 0;\n                int del = 2;\n                while (quicklistNext(iter, &entry)) {\n                    if (quicklistCompare(entry.zi, (unsigned char *)\"foo\", 3)) {\n                        quicklistDelEntry(iter, &entry);\n                        del--;\n                    }\n                    if (!del)\n                        break;\n                    i++;\n                }\n                quicklistReleaseIterator(iter);\n\n                /* check result of lrem -2 foo */\n                /* (we're ignoring the '2' part and still deleting all foo\n                 * because\n                 * we only have two foo) */\n                iter = quicklistGetIterator(ql, AL_START_TAIL);\n                i = 0;\n                size_t resB = sizeof(resultB) / sizeof(*resultB);\n                while (quicklistNext(iter, &entry)) {\n                    /* Result must be: abc, foo, foobar, foobared, zap, test,\n                     * foo */\n                    if (strncmp((char *)entry.value, resultB[resB - 1 - i],\n                                entry.sz)) {\n                        ERR(\"No match at position %d, got %.*s instead of %s\",\n                            i, entry.sz, entry.value, resultB[resB - 1 - i]);\n                        ok = 0;\n                    }\n                    i++;\n                }\n\n                quicklistReleaseIterator(iter);\n                /* final result of all tests */\n                if (ok)\n                    OK;\n                quicklistRelease(ql);\n            }\n        }\n\n        for (int f = optimize_start; f < 16; f++) {\n            TEST_DESC(\"iterate reverse + delete at fill %d at compress %d\", f,\n                      options[_i]) {\n                quicklist *ql = quicklistNew(f, options[_i]);\n                quicklistPushTail(ql, \"abc\", 3);\n                quicklistPushTail(ql, \"def\", 3);\n                quicklistPushTail(ql, \"hij\", 3);\n                quicklistPushTail(ql, \"jkl\", 3);\n                quicklistPushTail(ql, \"oop\", 3);\n\n                quicklistEntry entry;\n                quicklistIter *iter = quicklistGetIterator(ql, AL_START_TAIL);\n                int i = 0;\n                while (quicklistNext(iter, &entry)) {\n                    if (quicklistCompare(entry.zi, (unsigned char *)\"hij\", 3)) {\n                        quicklistDelEntry(iter, &entry);\n                    }\n                    i++;\n                }\n                quicklistReleaseIterator(iter);\n\n                if (i != 5)\n                    ERR(\"Didn't iterate 5 times, iterated %d times.\", i);\n\n                /* Check results after deletion of \"hij\" */\n                iter = quicklistGetIterator(ql, AL_START_HEAD);\n                i = 0;\n                char *vals[] = {\"abc\", \"def\", \"jkl\", \"oop\"};\n                while (quicklistNext(iter, &entry)) {\n                    if (!quicklistCompare(entry.zi, (unsigned char *)vals[i],\n                                          3)) {\n                        ERR(\"Value at %d didn't match %s\\n\", i, vals[i]);\n                    }\n                    i++;\n                }\n                quicklistReleaseIterator(iter);\n                quicklistRelease(ql);\n            }\n        }\n\n        for (int f = optimize_start; f < 800; f++) {\n            TEST_DESC(\"iterator at index test at fill %d at compress %d\", f,\n                      options[_i]) {\n                quicklist *ql = quicklistNew(f, options[_i]);\n                char num[32];\n                long long nums[5000];\n                for (int i = 0; i < 760; i++) {\n                    nums[i] = -5157318210846258176 + i;\n                    int sz = ll2string(num, sizeof(num), nums[i]);\n                    quicklistPushTail(ql, num, sz);\n                }\n\n                quicklistEntry entry;\n                quicklistIter *iter =\n                    quicklistGetIteratorAtIdx(ql, AL_START_HEAD, 437);\n                int i = 437;\n                while (quicklistNext(iter, &entry)) {\n                    if (entry.longval != nums[i])\n                        ERR(\"Expected %lld, but got %lld\", entry.longval,\n                            nums[i]);\n                    i++;\n                }\n                quicklistReleaseIterator(iter);\n                quicklistRelease(ql);\n            }\n        }\n\n        for (int f = optimize_start; f < 40; f++) {\n            TEST_DESC(\"ltrim test A at fill %d at compress %d\", f,\n                      options[_i]) {\n                quicklist *ql = quicklistNew(f, options[_i]);\n                char num[32];\n                long long nums[5000];\n                for (int i = 0; i < 32; i++) {\n                    nums[i] = -5157318210846258176 + i;\n                    int sz = ll2string(num, sizeof(num), nums[i]);\n                    quicklistPushTail(ql, num, sz);\n                }\n                if (f == 32)\n                    ql_verify(ql, 1, 32, 32, 32);\n                /* ltrim 25 53 (keep [25,32] inclusive = 7 remaining) */\n                quicklistDelRange(ql, 0, 25);\n                quicklistDelRange(ql, 0, 0);\n                quicklistEntry entry;\n                for (int i = 0; i < 7; i++) {\n                    quicklistIndex(ql, i, &entry);\n                    if (entry.longval != nums[25 + i])\n                        ERR(\"Deleted invalid range!  Expected %lld but got \"\n                            \"%lld\",\n                            entry.longval, nums[25 + i]);\n                }\n                if (f == 32)\n                    ql_verify(ql, 1, 7, 7, 7);\n                quicklistRelease(ql);\n            }\n        }\n\n        for (int f = optimize_start; f < 40; f++) {\n            TEST_DESC(\"ltrim test B at fill %d at compress %d\", f,\n                      options[_i]) {\n                /* Force-disable compression because our 33 sequential\n                 * integers don't compress and the check always fails. */\n                quicklist *ql = quicklistNew(f, QUICKLIST_NOCOMPRESS);\n                char num[32];\n                long long nums[5000];\n                for (int i = 0; i < 33; i++) {\n                    nums[i] = i;\n                    int sz = ll2string(num, sizeof(num), nums[i]);\n                    quicklistPushTail(ql, num, sz);\n                }\n                if (f == 32)\n                    ql_verify(ql, 2, 33, 32, 1);\n                /* ltrim 5 16 (keep [5,16] inclusive = 12 remaining) */\n                quicklistDelRange(ql, 0, 5);\n                quicklistDelRange(ql, -16, 16);\n                if (f == 32)\n                    ql_verify(ql, 1, 12, 12, 12);\n                quicklistEntry entry;\n                quicklistIndex(ql, 0, &entry);\n                if (entry.longval != 5)\n                    ERR(\"A: longval not 5, but %lld\", entry.longval);\n                else\n                    OK;\n                quicklistIndex(ql, -1, &entry);\n                if (entry.longval != 16)\n                    ERR(\"B! got instead: %lld\", entry.longval);\n                else\n                    OK;\n                quicklistPushTail(ql, \"bobobob\", 7);\n                quicklistIndex(ql, -1, &entry);\n                if (strncmp((char *)entry.value, \"bobobob\", 7))\n                    ERR(\"Tail doesn't match bobobob, it's %.*s instead\",\n                        entry.sz, entry.value);\n                for (int i = 0; i < 12; i++) {\n                    quicklistIndex(ql, i, &entry);\n                    if (entry.longval != nums[5 + i])\n                        ERR(\"Deleted invalid range!  Expected %lld but got \"\n                            \"%lld\",\n                            entry.longval, nums[5 + i]);\n                }\n                quicklistRelease(ql);\n            }\n        }\n\n        for (int f = optimize_start; f < 40; f++) {\n            TEST_DESC(\"ltrim test C at fill %d at compress %d\", f,\n                      options[_i]) {\n                quicklist *ql = quicklistNew(f, options[_i]);\n                char num[32];\n                long long nums[5000];\n                for (int i = 0; i < 33; i++) {\n                    nums[i] = -5157318210846258176 + i;\n                    int sz = ll2string(num, sizeof(num), nums[i]);\n                    quicklistPushTail(ql, num, sz);\n                }\n                if (f == 32)\n                    ql_verify(ql, 2, 33, 32, 1);\n                /* ltrim 3 3 (keep [3,3] inclusive = 1 remaining) */\n                quicklistDelRange(ql, 0, 3);\n                quicklistDelRange(ql, -29,\n                                  4000); /* make sure not loop forever */\n                if (f == 32)\n                    ql_verify(ql, 1, 1, 1, 1);\n                quicklistEntry entry;\n                quicklistIndex(ql, 0, &entry);\n                if (entry.longval != -5157318210846258173)\n                    ERROR;\n                else\n                    OK;\n                quicklistRelease(ql);\n            }\n        }\n\n        for (int f = optimize_start; f < 40; f++) {\n            TEST_DESC(\"ltrim test D at fill %d at compress %d\", f,\n                      options[_i]) {\n                quicklist *ql = quicklistNew(f, options[_i]);\n                char num[32];\n                long long nums[5000];\n                for (int i = 0; i < 33; i++) {\n                    nums[i] = -5157318210846258176 + i;\n                    int sz = ll2string(num, sizeof(num), nums[i]);\n                    quicklistPushTail(ql, num, sz);\n                }\n                if (f == 32)\n                    ql_verify(ql, 2, 33, 32, 1);\n                quicklistDelRange(ql, -12, 3);\n                if (ql->count != 30)\n                    ERR(\"Didn't delete exactly three elements!  Count is: %lu\",\n                        ql->count);\n                quicklistRelease(ql);\n            }\n        }\n\n        for (int f = optimize_start; f < 72; f++) {\n            TEST_DESC(\"create quicklist from ziplist at fill %d at compress %d\",\n                      f, options[_i]) {\n                unsigned char *zl = ziplistNew();\n                long long nums[64];\n                char num[64];\n                for (int i = 0; i < 33; i++) {\n                    nums[i] = -5157318210846258176 + i;\n                    int sz = ll2string(num, sizeof(num), nums[i]);\n                    zl =\n                        ziplistPush(zl, (unsigned char *)num, sz, ZIPLIST_TAIL);\n                }\n                for (int i = 0; i < 33; i++) {\n                    zl = ziplistPush(zl, (unsigned char *)genstr(\"hello\", i),\n                                     32, ZIPLIST_TAIL);\n                }\n                quicklist *ql = quicklistCreateFromZiplist(f, options[_i], zl);\n                if (f == 1)\n                    ql_verify(ql, 66, 66, 1, 1);\n                else if (f == 32)\n                    ql_verify(ql, 3, 66, 32, 2);\n                else if (f == 66)\n                    ql_verify(ql, 1, 66, 66, 66);\n                quicklistRelease(ql);\n            }\n        }\n\n        long long stop = mstime();\n        runtime[_i] = stop - start;\n    }\n\n    /* Run a longer test of compression depth outside of primary test loop. */\n    int list_sizes[] = {250, 251, 500, 999, 1000};\n    long long start = mstime();\n    for (int list = 0; list < (int)(sizeof(list_sizes) / sizeof(*list_sizes));\n         list++) {\n        for (int f = optimize_start; f < 128; f++) {\n            for (int depth = 1; depth < 40; depth++) {\n                /* skip over many redundant test cases */\n                TEST_DESC(\"verify specific compression of interior nodes with \"\n                          \"%d list \"\n                          \"at fill %d at compress %d\",\n                          list_sizes[list], f, depth) {\n                    quicklist *ql = quicklistNew(f, depth);\n                    for (int i = 0; i < list_sizes[list]; i++) {\n                        quicklistPushTail(ql, genstr(\"hello TAIL\", i + 1), 64);\n                        quicklistPushHead(ql, genstr(\"hello HEAD\", i + 1), 64);\n                    }\n\n                    quicklistNode *node = ql->head;\n                    unsigned int low_raw = ql->compress;\n                    unsigned int high_raw = ql->len - ql->compress;\n\n                    for (unsigned int at = 0; at < ql->len;\n                         at++, node = node->next) {\n                        if (at < low_raw || at >= high_raw) {\n                            if (node->encoding != QUICKLIST_NODE_ENCODING_RAW) {\n                                ERR(\"Incorrect compression: node %d is \"\n                                    \"compressed at depth %d ((%u, %u); total \"\n                                    \"nodes: %u; size: %u)\",\n                                    at, depth, low_raw, high_raw, ql->len,\n                                    node->sz);\n                            }\n                        } else {\n                            if (node->encoding != QUICKLIST_NODE_ENCODING_LZF) {\n                                ERR(\"Incorrect non-compression: node %d is NOT \"\n                                    \"compressed at depth %d ((%u, %u); total \"\n                                    \"nodes: %u; size: %u; attempted: %d)\",\n                                    at, depth, low_raw, high_raw, ql->len,\n                                    node->sz, node->attempted_compress);\n                            }\n                        }\n                    }\n                    quicklistRelease(ql);\n                }\n            }\n        }\n    }\n    long long stop = mstime();\n\n    printf(\"\\n\");\n    for (size_t i = 0; i < option_count; i++)\n        printf(\"Test Loop %02d: %0.2f seconds.\\n\", options[i],\n               (float)runtime[i] / 1000);\n    printf(\"Compressions: %0.2f seconds.\\n\", (float)(stop - start) / 1000);\n    printf(\"\\n\");\n\n    if (!err)\n        printf(\"ALL TESTS PASSED!\\n\");\n    else\n        ERR(\"Sorry, not all tests passed!  In fact, %d tests failed.\", err);\n\n    return err;\n}\n#endif\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/src/quicklist.h",
    "content": "/* quicklist.h - A generic doubly linked quicklist implementation\n *\n * Copyright (c) 2014, Matt Stancliff <matt@genges.com>\n * All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions are met:\n *\n *   * Redistributions of source code must retain the above copyright notice,\n *     this quicklist of conditions and the following disclaimer.\n *   * Redistributions in binary form must reproduce the above copyright\n *     notice, this quicklist of conditions and the following disclaimer in the\n *     documentation and/or other materials provided with the distribution.\n *   * Neither the name of Redis nor the names of its contributors may be used\n *     to endorse or promote products derived from this software without\n *     specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\"\n * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\n * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE\n * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR\n * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF\n * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS\n * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN\n * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)\n * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE\n * POSSIBILITY OF SUCH DAMAGE.\n */\n\n#ifndef __QUICKLIST_H__\n#define __QUICKLIST_H__\n\n/* Node, quicklist, and Iterator are the only data structures used currently. */\n\n/* quicklistNode is a 32 byte struct describing a ziplist for a quicklist.\n * We use bit fields keep the quicklistNode at 32 bytes.\n * count: 16 bits, max 65536 (max zl bytes is 65k, so max count actually < 32k).\n * encoding: 2 bits, RAW=1, LZF=2.\n * container: 2 bits, NONE=1, ZIPLIST=2.\n * recompress: 1 bit, bool, true if node is temporarry decompressed for usage.\n * attempted_compress: 1 bit, boolean, used for verifying during testing.\n * extra: 12 bits, free for future use; pads out the remainder of 32 bits */\ntypedef struct quicklistNode {\n    struct quicklistNode *prev;\n    struct quicklistNode *next;\n    unsigned char *zl;\n    unsigned int sz;             /* ziplist size in bytes */\n    unsigned int count : 16;     /* count of items in ziplist */\n    unsigned int encoding : 2;   /* RAW==1 or LZF==2 */\n    unsigned int container : 2;  /* NONE==1 or ZIPLIST==2 */\n    unsigned int recompress : 1; /* was this node previous compressed? */\n    unsigned int attempted_compress : 1; /* node can't compress; too small */\n    unsigned int extra : 10; /* more bits to steal for future usage */\n} quicklistNode;\n\n/* quicklistLZF is a 4+N byte struct holding 'sz' followed by 'compressed'.\n * 'sz' is byte length of 'compressed' field.\n * 'compressed' is LZF data with total (compressed) length 'sz'\n * NOTE: uncompressed length is stored in quicklistNode->sz.\n * When quicklistNode->zl is compressed, node->zl points to a quicklistLZF */\ntypedef struct quicklistLZF {\n    unsigned int sz; /* LZF size in bytes*/\n    char compressed[];\n} quicklistLZF;\n\n/* quicklist is a 32 byte struct (on 64-bit systems) describing a quicklist.\n * 'count' is the number of total entries.\n * 'len' is the number of quicklist nodes.\n * 'compress' is: -1 if compression disabled, otherwise it's the number\n *                of quicklistNodes to leave uncompressed at ends of quicklist.\n * 'fill' is the user-requested (or default) fill factor. */\ntypedef struct quicklist {\n    quicklistNode *head;\n    quicklistNode *tail;\n    unsigned long count;        /* total count of all entries in all ziplists */\n    unsigned int len;           /* number of quicklistNodes */\n    int fill : 16;              /* fill factor for individual nodes */\n    unsigned int compress : 16; /* depth of end nodes not to compress;0=off */\n} quicklist;\n\ntypedef struct quicklistIter {\n    const quicklist *quicklist;\n    quicklistNode *current;\n    unsigned char *zi;\n    long offset; /* offset in current ziplist */\n    int direction;\n} quicklistIter;\n\ntypedef struct quicklistEntry {\n    const quicklist *quicklist;\n    quicklistNode *node;\n    unsigned char *zi;\n    unsigned char *value;\n    long long longval;\n    unsigned int sz;\n    int offset;\n} quicklistEntry;\n\n#define QUICKLIST_HEAD 0\n#define QUICKLIST_TAIL -1\n\n/* quicklist node encodings */\n#define QUICKLIST_NODE_ENCODING_RAW 1\n#define QUICKLIST_NODE_ENCODING_LZF 2\n\n/* quicklist compression disable */\n#define QUICKLIST_NOCOMPRESS 0\n\n/* quicklist container formats */\n#define QUICKLIST_NODE_CONTAINER_NONE 1\n#define QUICKLIST_NODE_CONTAINER_ZIPLIST 2\n\n#define quicklistNodeIsCompressed(node)                                        \\\n    ((node)->encoding == QUICKLIST_NODE_ENCODING_LZF)\n\n/* Prototypes */\nquicklist *quicklistCreate(void);\nquicklist *quicklistNew(int fill, int compress);\nvoid quicklistSetCompressDepth(quicklist *quicklist, int depth);\nvoid quicklistSetFill(quicklist *quicklist, int fill);\nvoid quicklistSetOptions(quicklist *quicklist, int fill, int depth);\nvoid quicklistRelease(quicklist *quicklist);\nint quicklistPushHead(quicklist *quicklist, void *value, const size_t sz);\nint quicklistPushTail(quicklist *quicklist, void *value, const size_t sz);\nvoid quicklistPush(quicklist *quicklist, void *value, const size_t sz,\n                   int where);\nvoid quicklistAppendZiplist(quicklist *quicklist, unsigned char *zl);\nquicklist *quicklistAppendValuesFromZiplist(quicklist *quicklist,\n                                            unsigned char *zl);\nquicklist *quicklistCreateFromZiplist(int fill, int compress,\n                                      unsigned char *zl);\nvoid quicklistInsertAfter(quicklist *quicklist, quicklistEntry *node,\n                          void *value, const size_t sz);\nvoid quicklistInsertBefore(quicklist *quicklist, quicklistEntry *node,\n                           void *value, const size_t sz);\nvoid quicklistDelEntry(quicklistIter *iter, quicklistEntry *entry);\nint quicklistReplaceAtIndex(quicklist *quicklist, long index, void *data,\n                            int sz);\nint quicklistDelRange(quicklist *quicklist, const long start, const long stop);\nquicklistIter *quicklistGetIterator(const quicklist *quicklist, int direction);\nquicklistIter *quicklistGetIteratorAtIdx(const quicklist *quicklist,\n                                         int direction, const long long idx);\nint quicklistNext(quicklistIter *iter, quicklistEntry *node);\nvoid quicklistReleaseIterator(quicklistIter *iter);\nquicklist *quicklistDup(quicklist *orig);\nint quicklistIndex(const quicklist *quicklist, const long long index,\n                   quicklistEntry *entry);\nvoid quicklistRewind(quicklist *quicklist, quicklistIter *li);\nvoid quicklistRewindTail(quicklist *quicklist, quicklistIter *li);\nvoid quicklistRotate(quicklist *quicklist);\nint quicklistPopCustom(quicklist *quicklist, int where, unsigned char **data,\n                       unsigned int *sz, long long *sval,\n                       void *(*saver)(unsigned char *data, unsigned int sz));\nint quicklistPop(quicklist *quicklist, int where, unsigned char **data,\n                 unsigned int *sz, long long *slong);\nunsigned int quicklistCount(quicklist *ql);\nint quicklistCompare(unsigned char *p1, unsigned char *p2, int p2_len);\nsize_t quicklistGetLzf(const quicklistNode *node, void **data);\n\n#ifdef REDIS_TEST\nint quicklistTest(int argc, char *argv[]);\n#endif\n\n/* Directions for iterators */\n#define AL_START_HEAD 0\n#define AL_START_TAIL 1\n\n#endif /* __QUICKLIST_H__ */\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/src/rand.c",
    "content": "/* Pseudo random number generation functions derived from the drand48()\n * function obtained from pysam source code.\n *\n * This functions are used in order to replace the default math.random()\n * Lua implementation with something having exactly the same behavior\n * across different systems (by default Lua uses libc's rand() that is not\n * required to implement a specific PRNG generating the same sequence\n * in different systems if seeded with the same integer).\n *\n * The original code appears to be under the public domain.\n * I modified it removing the non needed functions and all the\n * 1960-style C coding stuff...\n *\n * ----------------------------------------------------------------------------\n *\n * Copyright (c) 2010-2012, Salvatore Sanfilippo <antirez at gmail dot com>\n * All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions are met:\n *\n *   * Redistributions of source code must retain the above copyright notice,\n *     this list of conditions and the following disclaimer.\n *   * Redistributions in binary form must reproduce the above copyright\n *     notice, this list of conditions and the following disclaimer in the\n *     documentation and/or other materials provided with the distribution.\n *   * Neither the name of Redis nor the names of its contributors may be used\n *     to endorse or promote products derived from this software without\n *     specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\"\n * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\n * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE\n * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR\n * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF\n * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS\n * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN\n * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)\n * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE\n * POSSIBILITY OF SUCH DAMAGE.\n */\n\n#include <stdint.h>\n\n#define N\t16\n#define MASK\t((1 << (N - 1)) + (1 << (N - 1)) - 1)\n#define LOW(x)\t((unsigned)(x) & MASK)\n#define HIGH(x)\tLOW((x) >> N)\n#define MUL(x, y, z)\t{ int32_t l = (long)(x) * (long)(y); \\\n\t\t(z)[0] = LOW(l); (z)[1] = HIGH(l); }\n#define CARRY(x, y)\t((int32_t)(x) + (long)(y) > MASK)\n#define ADDEQU(x, y, z)\t(z = CARRY(x, (y)), x = LOW(x + (y)))\n#define X0\t0x330E\n#define X1\t0xABCD\n#define X2\t0x1234\n#define A0\t0xE66D\n#define A1\t0xDEEC\n#define A2\t0x5\n#define C\t0xB\n#define SET3(x, x0, x1, x2)\t((x)[0] = (x0), (x)[1] = (x1), (x)[2] = (x2))\n#define SETLOW(x, y, n) SET3(x, LOW((y)[n]), LOW((y)[(n)+1]), LOW((y)[(n)+2]))\n#define SEED(x0, x1, x2) (SET3(x, x0, x1, x2), SET3(a, A0, A1, A2), c = C)\n#define REST(v)\tfor (i = 0; i < 3; i++) { xsubi[i] = x[i]; x[i] = temp[i]; } \\\n\t\treturn (v);\n#define HI_BIT\t(1L << (2 * N - 1))\n\nstatic uint32_t x[3] = { X0, X1, X2 }, a[3] = { A0, A1, A2 }, c = C;\nstatic void next(void);\n\nint32_t redisLrand48() {\n    next();\n    return (((int32_t)x[2] << (N - 1)) + (x[1] >> 1));\n}\n\nvoid redisSrand48(int32_t seedval) {\n    SEED(X0, LOW(seedval), HIGH(seedval));\n}\n\nstatic void next(void) {\n    uint32_t p[2], q[2], r[2], carry0, carry1;\n\n    MUL(a[0], x[0], p);\n    ADDEQU(p[0], c, carry0);\n    ADDEQU(p[1], carry0, carry1);\n    MUL(a[0], x[1], q);\n    ADDEQU(p[1], q[0], carry0);\n    MUL(a[1], x[0], r);\n    x[2] = LOW(carry0 + carry1 + CARRY(p[1], r[0]) + q[1] + r[1] +\n            a[0] * x[2] + a[1] * x[1] + a[2] * x[0]);\n    x[1] = LOW(p[1] + r[0]);\n    x[0] = LOW(p[0]);\n}\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/src/rand.h",
    "content": "/*\n * Copyright (c) 2009-2012, Salvatore Sanfilippo <antirez at gmail dot com>\n * All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions are met:\n *\n *   * Redistributions of source code must retain the above copyright notice,\n *     this list of conditions and the following disclaimer.\n *   * Redistributions in binary form must reproduce the above copyright\n *     notice, this list of conditions and the following disclaimer in the\n *     documentation and/or other materials provided with the distribution.\n *   * Neither the name of Redis nor the names of its contributors may be used\n *     to endorse or promote products derived from this software without\n *     specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\"\n * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\n * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE\n * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR\n * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF\n * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS\n * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN\n * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)\n * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE\n * POSSIBILITY OF SUCH DAMAGE.\n */\n\n#ifndef REDIS_RANDOM_H\n#define REDIS_RANDOM_H\n\nint32_t redisLrand48();\nvoid redisSrand48(int32_t seedval);\n\n#define REDIS_LRAND48_MAX INT32_MAX\n\n#endif\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/src/rdb.c",
    "content": "/*\n * Copyright (c) 2009-2012, Salvatore Sanfilippo <antirez at gmail dot com>\n * All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions are met:\n *\n *   * Redistributions of source code must retain the above copyright notice,\n *     this list of conditions and the following disclaimer.\n *   * Redistributions in binary form must reproduce the above copyright\n *     notice, this list of conditions and the following disclaimer in the\n *     documentation and/or other materials provided with the distribution.\n *   * Neither the name of Redis nor the names of its contributors may be used\n *     to endorse or promote products derived from this software without\n *     specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\"\n * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\n * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE\n * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR\n * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF\n * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS\n * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN\n * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)\n * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE\n * POSSIBILITY OF SUCH DAMAGE.\n */\n\n#include \"server.h\"\n#include \"lzf.h\"    /* LZF compression library */\n#include \"zipmap.h\"\n#include \"endianconv.h\"\n\n#include <math.h>\n#include <sys/types.h>\n#include <sys/time.h>\n#include <sys/resource.h>\n#include <sys/wait.h>\n#include <arpa/inet.h>\n#include <sys/stat.h>\n#include <sys/param.h>\n\n#define RDB_LOAD_NONE   0\n#define RDB_LOAD_ENC    (1<<0)\n#define RDB_LOAD_PLAIN  (1<<1)\n\n#define rdbExitReportCorruptRDB(...) rdbCheckThenExit(__LINE__,__VA_ARGS__)\n\nextern int rdbCheckMode;\nvoid rdbCheckError(const char *fmt, ...);\nvoid rdbCheckSetError(const char *fmt, ...);\n\nvoid rdbCheckThenExit(int linenum, char *reason, ...) {\n    va_list ap;\n    char msg[1024];\n    int len;\n\n    len = snprintf(msg,sizeof(msg),\n        \"Internal error in RDB reading function at rdb.c:%d -> \", linenum);\n    va_start(ap,reason);\n    vsnprintf(msg+len,sizeof(msg)-len,reason,ap);\n    va_end(ap);\n\n    if (!rdbCheckMode) {\n        serverLog(LL_WARNING, \"%s\", msg);\n        char *argv[2] = {\"\",server.rdb_filename};\n        redis_check_rdb_main(2,argv);\n    } else {\n        rdbCheckError(\"%s\",msg);\n    }\n    exit(1);\n}\n\nstatic int rdbWriteRaw(rio *rdb, void *p, size_t len) {\n    if (rdb && rioWrite(rdb,p,len) == 0)\n        return -1;\n    return len;\n}\n\nint rdbSaveType(rio *rdb, unsigned char type) {\n    return rdbWriteRaw(rdb,&type,1);\n}\n\n/* Load a \"type\" in RDB format, that is a one byte unsigned integer.\n * This function is not only used to load object types, but also special\n * \"types\" like the end-of-file type, the EXPIRE type, and so forth. */\nint rdbLoadType(rio *rdb) {\n    unsigned char type;\n    if (rioRead(rdb,&type,1) == 0) return -1;\n    return type;\n}\n\ntime_t rdbLoadTime(rio *rdb) {\n    int32_t t32;\n    if (rioRead(rdb,&t32,4) == 0) return -1;\n    return (time_t)t32;\n}\n\nint rdbSaveMillisecondTime(rio *rdb, long long t) {\n    int64_t t64 = (int64_t) t;\n    return rdbWriteRaw(rdb,&t64,8);\n}\n\nlong long rdbLoadMillisecondTime(rio *rdb) {\n    int64_t t64;\n    if (rioRead(rdb,&t64,8) == 0) return -1;\n    return (long long)t64;\n}\n\n/* Saves an encoded length. The first two bits in the first byte are used to\n * hold the encoding type. See the RDB_* definitions for more information\n * on the types of encoding. */\nint rdbSaveLen(rio *rdb, uint32_t len) {\n    unsigned char buf[2];\n    size_t nwritten;\n\n    if (len < (1<<6)) {\n        /* Save a 6 bit len */\n        buf[0] = (len&0xFF)|(RDB_6BITLEN<<6);\n        if (rdbWriteRaw(rdb,buf,1) == -1) return -1;\n        nwritten = 1;\n    } else if (len < (1<<14)) {\n        /* Save a 14 bit len */\n        buf[0] = ((len>>8)&0xFF)|(RDB_14BITLEN<<6);\n        buf[1] = len&0xFF;\n        if (rdbWriteRaw(rdb,buf,2) == -1) return -1;\n        nwritten = 2;\n    } else {\n        /* Save a 32 bit len */\n        buf[0] = (RDB_32BITLEN<<6);\n        if (rdbWriteRaw(rdb,buf,1) == -1) return -1;\n        len = htonl(len);\n        if (rdbWriteRaw(rdb,&len,4) == -1) return -1;\n        nwritten = 1+4;\n    }\n    return nwritten;\n}\n\n/* Load an encoded length. The \"isencoded\" argument is set to 1 if the length\n * is not actually a length but an \"encoding type\". See the RDB_ENC_*\n * definitions in rdb.h for more information. */\nuint32_t rdbLoadLen(rio *rdb, int *isencoded) {\n    unsigned char buf[2];\n    uint32_t len;\n    int type;\n\n    if (isencoded) *isencoded = 0;\n    if (rioRead(rdb,buf,1) == 0) return RDB_LENERR;\n    type = (buf[0]&0xC0)>>6;\n    if (type == RDB_ENCVAL) {\n        /* Read a 6 bit encoding type. */\n        if (isencoded) *isencoded = 1;\n        return buf[0]&0x3F;\n    } else if (type == RDB_6BITLEN) {\n        /* Read a 6 bit len. */\n        return buf[0]&0x3F;\n    } else if (type == RDB_14BITLEN) {\n        /* Read a 14 bit len. */\n        if (rioRead(rdb,buf+1,1) == 0) return RDB_LENERR;\n        return ((buf[0]&0x3F)<<8)|buf[1];\n    } else if (type == RDB_32BITLEN) {\n        /* Read a 32 bit len. */\n        if (rioRead(rdb,&len,4) == 0) return RDB_LENERR;\n        return ntohl(len);\n    } else {\n        rdbExitReportCorruptRDB(\n            \"Unknown length encoding %d in rdbLoadLen()\",type);\n        return -1; /* Never reached. */\n    }\n}\n\n/* Encodes the \"value\" argument as integer when it fits in the supported ranges\n * for encoded types. If the function successfully encodes the integer, the\n * representation is stored in the buffer pointer to by \"enc\" and the string\n * length is returned. Otherwise 0 is returned. */\nint rdbEncodeInteger(long long value, unsigned char *enc) {\n    if (value >= -(1<<7) && value <= (1<<7)-1) {\n        enc[0] = (RDB_ENCVAL<<6)|RDB_ENC_INT8;\n        enc[1] = value&0xFF;\n        return 2;\n    } else if (value >= -(1<<15) && value <= (1<<15)-1) {\n        enc[0] = (RDB_ENCVAL<<6)|RDB_ENC_INT16;\n        enc[1] = value&0xFF;\n        enc[2] = (value>>8)&0xFF;\n        return 3;\n    } else if (value >= -((long long)1<<31) && value <= ((long long)1<<31)-1) {\n        enc[0] = (RDB_ENCVAL<<6)|RDB_ENC_INT32;\n        enc[1] = value&0xFF;\n        enc[2] = (value>>8)&0xFF;\n        enc[3] = (value>>16)&0xFF;\n        enc[4] = (value>>24)&0xFF;\n        return 5;\n    } else {\n        return 0;\n    }\n}\n\n/* Loads an integer-encoded object with the specified encoding type \"enctype\".\n * The returned value changes according to the flags, see\n * rdbGenerincLoadStringObject() for more info. */\nvoid *rdbLoadIntegerObject(rio *rdb, int enctype, int flags) {\n    int plain = flags & RDB_LOAD_PLAIN;\n    int encode = flags & RDB_LOAD_ENC;\n    unsigned char enc[4];\n    long long val;\n\n    if (enctype == RDB_ENC_INT8) {\n        if (rioRead(rdb,enc,1) == 0) return NULL;\n        val = (signed char)enc[0];\n    } else if (enctype == RDB_ENC_INT16) {\n        uint16_t v;\n        if (rioRead(rdb,enc,2) == 0) return NULL;\n        v = enc[0]|(enc[1]<<8);\n        val = (int16_t)v;\n    } else if (enctype == RDB_ENC_INT32) {\n        uint32_t v;\n        if (rioRead(rdb,enc,4) == 0) return NULL;\n        v = enc[0]|(enc[1]<<8)|(enc[2]<<16)|(enc[3]<<24);\n        val = (int32_t)v;\n    } else {\n        val = 0; /* anti-warning */\n        rdbExitReportCorruptRDB(\"Unknown RDB integer encoding type %d\",enctype);\n    }\n    if (plain) {\n        char buf[LONG_STR_SIZE], *p;\n        int len = ll2string(buf,sizeof(buf),val);\n        p = zmalloc(len);\n        memcpy(p,buf,len);\n        return p;\n    } else if (encode) {\n        return createStringObjectFromLongLong(val);\n    } else {\n        return createObject(OBJ_STRING,sdsfromlonglong(val));\n    }\n}\n\n/* String objects in the form \"2391\" \"-100\" without any space and with a\n * range of values that can fit in an 8, 16 or 32 bit signed value can be\n * encoded as integers to save space */\nint rdbTryIntegerEncoding(char *s, size_t len, unsigned char *enc) {\n    long long value;\n    char *endptr, buf[32];\n\n    /* Check if it's possible to encode this value as a number */\n    value = strtoll(s, &endptr, 10);\n    if (endptr[0] != '\\0') return 0;\n    ll2string(buf,32,value);\n\n    /* If the number converted back into a string is not identical\n     * then it's not possible to encode the string as integer */\n    if (strlen(buf) != len || memcmp(buf,s,len)) return 0;\n\n    return rdbEncodeInteger(value,enc);\n}\n\nssize_t rdbSaveLzfBlob(rio *rdb, void *data, size_t compress_len,\n                       size_t original_len) {\n    unsigned char byte;\n    ssize_t n, nwritten = 0;\n\n    /* Data compressed! Let's save it on disk */\n    byte = (RDB_ENCVAL<<6)|RDB_ENC_LZF;\n    if ((n = rdbWriteRaw(rdb,&byte,1)) == -1) goto writeerr;\n    nwritten += n;\n\n    if ((n = rdbSaveLen(rdb,compress_len)) == -1) goto writeerr;\n    nwritten += n;\n\n    if ((n = rdbSaveLen(rdb,original_len)) == -1) goto writeerr;\n    nwritten += n;\n\n    if ((n = rdbWriteRaw(rdb,data,compress_len)) == -1) goto writeerr;\n    nwritten += n;\n\n    return nwritten;\n\nwriteerr:\n    return -1;\n}\n\nssize_t rdbSaveLzfStringObject(rio *rdb, unsigned char *s, size_t len) {\n    size_t comprlen, outlen;\n    void *out;\n\n    /* We require at least four bytes compression for this to be worth it */\n    if (len <= 4) return 0;\n    outlen = len-4;\n    if ((out = zmalloc(outlen+1)) == NULL) return 0;\n    comprlen = lzf_compress(s, len, out, outlen);\n    if (comprlen == 0) {\n        zfree(out);\n        return 0;\n    }\n    ssize_t nwritten = rdbSaveLzfBlob(rdb, out, comprlen, len);\n    zfree(out);\n    return nwritten;\n}\n\n/* Load an LZF compressed string in RDB format. The returned value\n * changes according to 'flags'. For more info check the\n * rdbGenericLoadStringObject() function. */\nvoid *rdbLoadLzfStringObject(rio *rdb, int flags) {\n    int plain = flags & RDB_LOAD_PLAIN;\n    unsigned int len, clen;\n    unsigned char *c = NULL;\n    sds val = NULL;\n\n    if ((clen = rdbLoadLen(rdb,NULL)) == RDB_LENERR) return NULL;\n    if ((len = rdbLoadLen(rdb,NULL)) == RDB_LENERR) return NULL;\n    if ((c = zmalloc(clen)) == NULL) goto err;\n\n    /* Allocate our target according to the uncompressed size. */\n    if (plain) {\n        val = zmalloc(len);\n    } else {\n        if ((val = sdsnewlen(NULL,len)) == NULL) goto err;\n    }\n\n    /* Load the compressed representation and uncompress it to target. */\n    if (rioRead(rdb,c,clen) == 0) goto err;\n    if (lzf_decompress(c,clen,val,len) == 0) {\n        if (rdbCheckMode) rdbCheckSetError(\"Invalid LZF compressed string\");\n        goto err;\n    }\n    zfree(c);\n\n    if (plain)\n        return val;\n    else\n        return createObject(OBJ_STRING,val);\nerr:\n    zfree(c);\n    if (plain)\n        zfree(val);\n    else\n        sdsfree(val);\n    return NULL;\n}\n\n/* Save a string object as [len][data] on disk. If the object is a string\n * representation of an integer value we try to save it in a special form */\nssize_t rdbSaveRawString(rio *rdb, unsigned char *s, size_t len) {\n    int enclen;\n    ssize_t n, nwritten = 0;\n\n    /* Try integer encoding */\n    if (len <= 11) {\n        unsigned char buf[5];\n        if ((enclen = rdbTryIntegerEncoding((char*)s,len,buf)) > 0) {\n            if (rdbWriteRaw(rdb,buf,enclen) == -1) return -1;\n            return enclen;\n        }\n    }\n\n    /* Try LZF compression - under 20 bytes it's unable to compress even\n     * aaaaaaaaaaaaaaaaaa so skip it */\n    if (server.rdb_compression && len > 20) {\n        n = rdbSaveLzfStringObject(rdb,s,len);\n        if (n == -1) return -1;\n        if (n > 0) return n;\n        /* Return value of 0 means data can't be compressed, save the old way */\n    }\n\n    /* Store verbatim */\n    if ((n = rdbSaveLen(rdb,len)) == -1) return -1;\n    nwritten += n;\n    if (len > 0) {\n        if (rdbWriteRaw(rdb,s,len) == -1) return -1;\n        nwritten += len;\n    }\n    return nwritten;\n}\n\n/* Save a long long value as either an encoded string or a string. */\nssize_t rdbSaveLongLongAsStringObject(rio *rdb, long long value) {\n    unsigned char buf[32];\n    ssize_t n, nwritten = 0;\n    int enclen = rdbEncodeInteger(value,buf);\n    if (enclen > 0) {\n        return rdbWriteRaw(rdb,buf,enclen);\n    } else {\n        /* Encode as string */\n        enclen = ll2string((char*)buf,32,value);\n        serverAssert(enclen < 32);\n        if ((n = rdbSaveLen(rdb,enclen)) == -1) return -1;\n        nwritten += n;\n        if ((n = rdbWriteRaw(rdb,buf,enclen)) == -1) return -1;\n        nwritten += n;\n    }\n    return nwritten;\n}\n\n/* Like rdbSaveStringObjectRaw() but handle encoded objects */\nint rdbSaveStringObject(rio *rdb, robj *obj) {\n    /* Avoid to decode the object, then encode it again, if the\n     * object is already integer encoded. */\n    if (obj->encoding == OBJ_ENCODING_INT) {\n        return rdbSaveLongLongAsStringObject(rdb,(long)obj->ptr);\n    } else {\n        serverAssertWithInfo(NULL,obj,sdsEncodedObject(obj));\n        return rdbSaveRawString(rdb,obj->ptr,sdslen(obj->ptr));\n    }\n}\n\n/* Load a string object from an RDB file according to flags:\n *\n * RDB_LOAD_NONE (no flags): load an RDB object, unencoded.\n * RDB_LOAD_ENC: If the returned type is a Redis object, try to\n *               encode it in a special way to be more memory\n *               efficient. When this flag is passed the function\n *               no longer guarantees that obj->ptr is an SDS string.\n * RDB_LOAD_PLAIN: Return a plain string allocated with zmalloc()\n *                 instead of a Redis object with an sds in it.\n * RDB_LOAD_SDS: Return an SDS string instead of a Redis object.\n */\nvoid *rdbGenericLoadStringObject(rio *rdb, int flags) {\n    int encode = flags & RDB_LOAD_ENC;\n    int plain = flags & RDB_LOAD_PLAIN;\n    int isencoded;\n    uint32_t len;\n\n    len = rdbLoadLen(rdb,&isencoded);\n    if (isencoded) {\n        switch(len) {\n        case RDB_ENC_INT8:\n        case RDB_ENC_INT16:\n        case RDB_ENC_INT32:\n            return rdbLoadIntegerObject(rdb,len,flags);\n        case RDB_ENC_LZF:\n            return rdbLoadLzfStringObject(rdb,flags);\n        default:\n            rdbExitReportCorruptRDB(\"Unknown RDB string encoding type %d\",len);\n        }\n    }\n\n    if (len == RDB_LENERR) return NULL;\n    if (!plain) {\n        robj *o = encode ? createStringObject(NULL,len) :\n                           createRawStringObject(NULL,len);\n        if (len && rioRead(rdb,o->ptr,len) == 0) {\n            decrRefCount(o);\n            return NULL;\n        }\n        return o;\n    } else {\n        void *buf = zmalloc(len);\n        if (len && rioRead(rdb,buf,len) == 0) {\n            zfree(buf);\n            return NULL;\n        }\n        return buf;\n    }\n}\n\nrobj *rdbLoadStringObject(rio *rdb) {\n    return rdbGenericLoadStringObject(rdb,RDB_LOAD_NONE);\n}\n\nrobj *rdbLoadEncodedStringObject(rio *rdb) {\n    return rdbGenericLoadStringObject(rdb,RDB_LOAD_ENC);\n}\n\n/* Save a double value. Doubles are saved as strings prefixed by an unsigned\n * 8 bit integer specifying the length of the representation.\n * This 8 bit integer has special values in order to specify the following\n * conditions:\n * 253: not a number\n * 254: + inf\n * 255: - inf\n */\nint rdbSaveDoubleValue(rio *rdb, double val) {\n    unsigned char buf[128];\n    int len;\n\n    if (isnan(val)) {\n        buf[0] = 253;\n        len = 1;\n    } else if (!isfinite(val)) {\n        len = 1;\n        buf[0] = (val < 0) ? 255 : 254;\n    } else {\n#if (DBL_MANT_DIG >= 52) && (LLONG_MAX == 0x7fffffffffffffffLL)\n        /* Check if the float is in a safe range to be casted into a\n         * long long. We are assuming that long long is 64 bit here.\n         * Also we are assuming that there are no implementations around where\n         * double has precision < 52 bit.\n         *\n         * Under this assumptions we test if a double is inside an interval\n         * where casting to long long is safe. Then using two castings we\n         * make sure the decimal part is zero. If all this is true we use\n         * integer printing function that is much faster. */\n        double min = -4503599627370495; /* (2^52)-1 */\n        double max = 4503599627370496; /* -(2^52) */\n        if (val > min && val < max && val == ((double)((long long)val)))\n            ll2string((char*)buf+1,sizeof(buf)-1,(long long)val);\n        else\n#endif\n            snprintf((char*)buf+1,sizeof(buf)-1,\"%.17g\",val);\n        buf[0] = strlen((char*)buf+1);\n        len = buf[0]+1;\n    }\n    return rdbWriteRaw(rdb,buf,len);\n}\n\n/* For information about double serialization check rdbSaveDoubleValue() */\nint rdbLoadDoubleValue(rio *rdb, double *val) {\n    char buf[256];\n    unsigned char len;\n\n    if (rioRead(rdb,&len,1) == 0) return -1;\n    switch(len) {\n    case 255: *val = R_NegInf; return 0;\n    case 254: *val = R_PosInf; return 0;\n    case 253: *val = R_Nan; return 0;\n    default:\n        if (rioRead(rdb,buf,len) == 0) return -1;\n        buf[len] = '\\0';\n        sscanf(buf, \"%lg\", val);\n        return 0;\n    }\n}\n\n/* Save the object type of object \"o\". */\nint rdbSaveObjectType(rio *rdb, robj *o) {\n    switch (o->type) {\n    case OBJ_STRING:\n        return rdbSaveType(rdb,RDB_TYPE_STRING);\n    case OBJ_LIST:\n        if (o->encoding == OBJ_ENCODING_QUICKLIST)\n            return rdbSaveType(rdb,RDB_TYPE_LIST_QUICKLIST);\n        else\n            serverPanic(\"Unknown list encoding\");\n    case OBJ_SET:\n        if (o->encoding == OBJ_ENCODING_INTSET)\n            return rdbSaveType(rdb,RDB_TYPE_SET_INTSET);\n        else if (o->encoding == OBJ_ENCODING_HT)\n            return rdbSaveType(rdb,RDB_TYPE_SET);\n        else\n            serverPanic(\"Unknown set encoding\");\n    case OBJ_ZSET:\n        if (o->encoding == OBJ_ENCODING_ZIPLIST)\n            return rdbSaveType(rdb,RDB_TYPE_ZSET_ZIPLIST);\n        else if (o->encoding == OBJ_ENCODING_SKIPLIST)\n            return rdbSaveType(rdb,RDB_TYPE_ZSET);\n        else\n            serverPanic(\"Unknown sorted set encoding\");\n    case OBJ_HASH:\n        if (o->encoding == OBJ_ENCODING_ZIPLIST)\n            return rdbSaveType(rdb,RDB_TYPE_HASH_ZIPLIST);\n        else if (o->encoding == OBJ_ENCODING_HT)\n            return rdbSaveType(rdb,RDB_TYPE_HASH);\n        else\n            serverPanic(\"Unknown hash encoding\");\n    default:\n        serverPanic(\"Unknown object type\");\n    }\n    return -1; /* avoid warning */\n}\n\n/* Use rdbLoadType() to load a TYPE in RDB format, but returns -1 if the\n * type is not specifically a valid Object Type. */\nint rdbLoadObjectType(rio *rdb) {\n    int type;\n    if ((type = rdbLoadType(rdb)) == -1) return -1;\n    if (!rdbIsObjectType(type)) return -1;\n    return type;\n}\n\n/* Save a Redis object. Returns -1 on error, number of bytes written on success. */\nssize_t rdbSaveObject(rio *rdb, robj *o) {\n    ssize_t n = 0, nwritten = 0;\n\n    if (o->type == OBJ_STRING) {\n        /* Save a string value */\n        if ((n = rdbSaveStringObject(rdb,o)) == -1) return -1;\n        nwritten += n;\n    } else if (o->type == OBJ_LIST) {\n        /* Save a list value */\n        if (o->encoding == OBJ_ENCODING_QUICKLIST) {\n            quicklist *ql = o->ptr;\n            quicklistNode *node = ql->head;\n\n            if ((n = rdbSaveLen(rdb,ql->len)) == -1) return -1;\n            nwritten += n;\n\n            do {\n                if (quicklistNodeIsCompressed(node)) {\n                    void *data;\n                    size_t compress_len = quicklistGetLzf(node, &data);\n                    if ((n = rdbSaveLzfBlob(rdb,data,compress_len,node->sz)) == -1) return -1;\n                    nwritten += n;\n                } else {\n                    if ((n = rdbSaveRawString(rdb,node->zl,node->sz)) == -1) return -1;\n                    nwritten += n;\n                }\n            } while ((node = node->next));\n        } else {\n            serverPanic(\"Unknown list encoding\");\n        }\n    } else if (o->type == OBJ_SET) {\n        /* Save a set value */\n        if (o->encoding == OBJ_ENCODING_HT) {\n            dict *set = o->ptr;\n            dictIterator *di = dictGetIterator(set);\n            dictEntry *de;\n\n            if ((n = rdbSaveLen(rdb,dictSize(set))) == -1) return -1;\n            nwritten += n;\n\n            while((de = dictNext(di)) != NULL) {\n                robj *eleobj = dictGetKey(de);\n                if ((n = rdbSaveStringObject(rdb,eleobj)) == -1) return -1;\n                nwritten += n;\n            }\n            dictReleaseIterator(di);\n        } else if (o->encoding == OBJ_ENCODING_INTSET) {\n            size_t l = intsetBlobLen((intset*)o->ptr);\n\n            if ((n = rdbSaveRawString(rdb,o->ptr,l)) == -1) return -1;\n            nwritten += n;\n        } else {\n            serverPanic(\"Unknown set encoding\");\n        }\n    } else if (o->type == OBJ_ZSET) {\n        /* Save a sorted set value */\n        if (o->encoding == OBJ_ENCODING_ZIPLIST) {\n            size_t l = ziplistBlobLen((unsigned char*)o->ptr);\n\n            if ((n = rdbSaveRawString(rdb,o->ptr,l)) == -1) return -1;\n            nwritten += n;\n        } else if (o->encoding == OBJ_ENCODING_SKIPLIST) {\n            zset *zs = o->ptr;\n            dictIterator *di = dictGetIterator(zs->dict);\n            dictEntry *de;\n\n            if ((n = rdbSaveLen(rdb,dictSize(zs->dict))) == -1) return -1;\n            nwritten += n;\n\n            while((de = dictNext(di)) != NULL) {\n                robj *eleobj = dictGetKey(de);\n                double *score = dictGetVal(de);\n\n                if ((n = rdbSaveStringObject(rdb,eleobj)) == -1) return -1;\n                nwritten += n;\n                if ((n = rdbSaveDoubleValue(rdb,*score)) == -1) return -1;\n                nwritten += n;\n            }\n            dictReleaseIterator(di);\n        } else {\n            serverPanic(\"Unknown sorted set encoding\");\n        }\n    } else if (o->type == OBJ_HASH) {\n        /* Save a hash value */\n        if (o->encoding == OBJ_ENCODING_ZIPLIST) {\n            size_t l = ziplistBlobLen((unsigned char*)o->ptr);\n\n            if ((n = rdbSaveRawString(rdb,o->ptr,l)) == -1) return -1;\n            nwritten += n;\n\n        } else if (o->encoding == OBJ_ENCODING_HT) {\n            dictIterator *di = dictGetIterator(o->ptr);\n            dictEntry *de;\n\n            if ((n = rdbSaveLen(rdb,dictSize((dict*)o->ptr))) == -1) return -1;\n            nwritten += n;\n\n            while((de = dictNext(di)) != NULL) {\n                robj *key = dictGetKey(de);\n                robj *val = dictGetVal(de);\n\n                if ((n = rdbSaveStringObject(rdb,key)) == -1) return -1;\n                nwritten += n;\n                if ((n = rdbSaveStringObject(rdb,val)) == -1) return -1;\n                nwritten += n;\n            }\n            dictReleaseIterator(di);\n\n        } else {\n            serverPanic(\"Unknown hash encoding\");\n        }\n\n    } else {\n        serverPanic(\"Unknown object type\");\n    }\n    return nwritten;\n}\n\n/* Return the length the object will have on disk if saved with\n * the rdbSaveObject() function. Currently we use a trick to get\n * this length with very little changes to the code. In the future\n * we could switch to a faster solution. */\nsize_t rdbSavedObjectLen(robj *o) {\n    ssize_t len = rdbSaveObject(NULL,o);\n    serverAssertWithInfo(NULL,o,len != -1);\n    return len;\n}\n\n/* Save a key-value pair, with expire time, type, key, value.\n * On error -1 is returned.\n * On success if the key was actually saved 1 is returned, otherwise 0\n * is returned (the key was already expired). */\nint rdbSaveKeyValuePair(rio *rdb, robj *key, robj *val,\n                        long long expiretime, long long now)\n{\n    /* Save the expire time */\n    if (expiretime != -1) {\n        /* If this key is already expired skip it */\n        if (expiretime < now) return 0;\n        if (rdbSaveType(rdb,RDB_OPCODE_EXPIRETIME_MS) == -1) return -1;\n        if (rdbSaveMillisecondTime(rdb,expiretime) == -1) return -1;\n    }\n\n    /* Save type, key, value */\n    if (rdbSaveObjectType(rdb,val) == -1) return -1;\n    if (rdbSaveStringObject(rdb,key) == -1) return -1;\n    if (rdbSaveObject(rdb,val) == -1) return -1;\n    return 1;\n}\n\n/* Save an AUX field. */\nint rdbSaveAuxField(rio *rdb, void *key, size_t keylen, void *val, size_t vallen) {\n    if (rdbSaveType(rdb,RDB_OPCODE_AUX) == -1) return -1;\n    if (rdbSaveRawString(rdb,key,keylen) == -1) return -1;\n    if (rdbSaveRawString(rdb,val,vallen) == -1) return -1;\n    return 1;\n}\n\n/* Wrapper for rdbSaveAuxField() used when key/val length can be obtained\n * with strlen(). */\nint rdbSaveAuxFieldStrStr(rio *rdb, char *key, char *val) {\n    return rdbSaveAuxField(rdb,key,strlen(key),val,strlen(val));\n}\n\n/* Wrapper for strlen(key) + integer type (up to long long range). */\nint rdbSaveAuxFieldStrInt(rio *rdb, char *key, long long val) {\n    char buf[LONG_STR_SIZE];\n    int vlen = ll2string(buf,sizeof(buf),val);\n    return rdbSaveAuxField(rdb,key,strlen(key),buf,vlen);\n}\n\n/* Save a few default AUX fields with information about the RDB generated. */\nint rdbSaveInfoAuxFields(rio *rdb) {\n    int redis_bits = (sizeof(void*) == 8) ? 64 : 32;\n\n    /* Add a few fields about the state when the RDB was created. */\n    if (rdbSaveAuxFieldStrStr(rdb,\"redis-ver\",REDIS_VERSION) == -1) return -1;\n    if (rdbSaveAuxFieldStrInt(rdb,\"redis-bits\",redis_bits) == -1) return -1;\n    if (rdbSaveAuxFieldStrInt(rdb,\"ctime\",time(NULL)) == -1) return -1;\n    if (rdbSaveAuxFieldStrInt(rdb,\"used-mem\",zmalloc_used_memory()) == -1) return -1;\n    return 1;\n}\n\n/* Produces a dump of the database in RDB format sending it to the specified\n * Redis I/O channel. On success C_OK is returned, otherwise C_ERR\n * is returned and part of the output, or all the output, can be\n * missing because of I/O errors.\n *\n * When the function returns C_ERR and if 'error' is not NULL, the\n * integer pointed by 'error' is set to the value of errno just after the I/O\n * error. */\nint rdbSaveRio(rio *rdb, int *error) {\n    dictIterator *di = NULL;\n    dictEntry *de;\n    char magic[10];\n    int j;\n    long long now = mstime();\n    uint64_t cksum;\n\n    if (server.rdb_checksum)\n        rdb->update_cksum = rioGenericUpdateChecksum;\n    snprintf(magic,sizeof(magic),\"REDIS%04d\",RDB_VERSION);\n    if (rdbWriteRaw(rdb,magic,9) == -1) goto werr;\n    if (rdbSaveInfoAuxFields(rdb) == -1) goto werr;\n\n    for (j = 0; j < server.dbnum; j++) {\n        redisDb *db = server.db+j;\n        dict *d = db->dict;\n        if (dictSize(d) == 0) continue;\n        di = dictGetSafeIterator(d);\n        if (!di) return C_ERR;\n\n        /* Write the SELECT DB opcode */\n        if (rdbSaveType(rdb,RDB_OPCODE_SELECTDB) == -1) goto werr;\n        if (rdbSaveLen(rdb,j) == -1) goto werr;\n\n        /* Write the RESIZE DB opcode. We trim the size to UINT32_MAX, which\n         * is currently the largest type we are able to represent in RDB sizes.\n         * However this does not limit the actual size of the DB to load since\n         * these sizes are just hints to resize the hash tables. */\n        uint32_t db_size, expires_size;\n        db_size = (dictSize(db->dict) <= UINT32_MAX) ?\n                                dictSize(db->dict) :\n                                UINT32_MAX;\n        expires_size = (dictSize(db->expires) <= UINT32_MAX) ?\n                                dictSize(db->expires) :\n                                UINT32_MAX;\n        if (rdbSaveType(rdb,RDB_OPCODE_RESIZEDB) == -1) goto werr;\n        if (rdbSaveLen(rdb,db_size) == -1) goto werr;\n        if (rdbSaveLen(rdb,expires_size) == -1) goto werr;\n\n        /* Iterate this DB writing every entry */\n        while((de = dictNext(di)) != NULL) {\n            sds keystr = dictGetKey(de);\n            robj key, *o = dictGetVal(de);\n            long long expire;\n\n            initStaticStringObject(key,keystr);\n            expire = getExpire(db,&key);\n            if (rdbSaveKeyValuePair(rdb,&key,o,expire,now) == -1) goto werr;\n        }\n        dictReleaseIterator(di);\n    }\n    di = NULL; /* So that we don't release it again on error. */\n\n    /* EOF opcode */\n    if (rdbSaveType(rdb,RDB_OPCODE_EOF) == -1) goto werr;\n\n    /* CRC64 checksum. It will be zero if checksum computation is disabled, the\n     * loading code skips the check in this case. */\n    cksum = rdb->cksum;\n    memrev64ifbe(&cksum);\n    if (rioWrite(rdb,&cksum,8) == 0) goto werr;\n    return C_OK;\n\nwerr:\n    if (error) *error = errno;\n    if (di) dictReleaseIterator(di);\n    return C_ERR;\n}\n\n/* This is just a wrapper to rdbSaveRio() that additionally adds a prefix\n * and a suffix to the generated RDB dump. The prefix is:\n *\n * $EOF:<40 bytes unguessable hex string>\\r\\n\n *\n * While the suffix is the 40 bytes hex string we announced in the prefix.\n * This way processes receiving the payload can understand when it ends\n * without doing any processing of the content. */\nint rdbSaveRioWithEOFMark(rio *rdb, int *error) {\n    char eofmark[RDB_EOF_MARK_SIZE];\n\n    getRandomHexChars(eofmark,RDB_EOF_MARK_SIZE);\n    if (error) *error = 0;\n    if (rioWrite(rdb,\"$EOF:\",5) == 0) goto werr;\n    if (rioWrite(rdb,eofmark,RDB_EOF_MARK_SIZE) == 0) goto werr;\n    if (rioWrite(rdb,\"\\r\\n\",2) == 0) goto werr;\n    if (rdbSaveRio(rdb,error) == C_ERR) goto werr;\n    if (rioWrite(rdb,eofmark,RDB_EOF_MARK_SIZE) == 0) goto werr;\n    return C_OK;\n\nwerr: /* Write error. */\n    /* Set 'error' only if not already set by rdbSaveRio() call. */\n    if (error && *error == 0) *error = errno;\n    return C_ERR;\n}\n\n/* Save the DB on disk. Return C_ERR on error, C_OK on success. */\nint rdbSave(char *filename) {\n    char tmpfile[256];\n    char cwd[MAXPATHLEN]; /* Current working dir path for error messages. */\n    FILE *fp;\n    rio rdb;\n    int error = 0;\n\n    snprintf(tmpfile,256,\"temp-%d.rdb\", (int) getpid());\n    fp = fopen(tmpfile,\"w\");\n    if (!fp) {\n        char *cwdp = getcwd(cwd,MAXPATHLEN);\n        serverLog(LL_WARNING,\n            \"Failed opening the RDB file %s (in server root dir %s) \"\n            \"for saving: %s\",\n            filename,\n            cwdp ? cwdp : \"unknown\",\n            strerror(errno));\n        return C_ERR;\n    }\n\n    rioInitWithFile(&rdb,fp);\n    if (rdbSaveRio(&rdb,&error) == C_ERR) {\n        errno = error;\n        goto werr;\n    }\n\n    /* Make sure data will not remain on the OS's output buffers */\n    if (fflush(fp) == EOF) goto werr;\n    if (fsync(fileno(fp)) == -1) goto werr;\n    if (fclose(fp) == EOF) goto werr;\n\n    /* Use RENAME to make sure the DB file is changed atomically only\n     * if the generate DB file is ok. */\n    if (rename(tmpfile,filename) == -1) {\n        char *cwdp = getcwd(cwd,MAXPATHLEN);\n        serverLog(LL_WARNING,\n            \"Error moving temp DB file %s on the final \"\n            \"destination %s (in server root dir %s): %s\",\n            tmpfile,\n            filename,\n            cwdp ? cwdp : \"unknown\",\n            strerror(errno));\n        unlink(tmpfile);\n        return C_ERR;\n    }\n\n    serverLog(LL_NOTICE,\"DB saved on disk\");\n    server.dirty = 0;\n    server.lastsave = time(NULL);\n    server.lastbgsave_status = C_OK;\n    return C_OK;\n\nwerr:\n    serverLog(LL_WARNING,\"Write error saving DB on disk: %s\", strerror(errno));\n    fclose(fp);\n    unlink(tmpfile);\n    return C_ERR;\n}\n\nint rdbSaveBackground(char *filename) {\n    pid_t childpid;\n    long long start;\n\n    if (server.aof_child_pid != -1 || server.rdb_child_pid != -1) return C_ERR;\n\n    server.dirty_before_bgsave = server.dirty;\n    server.lastbgsave_try = time(NULL);\n\n    start = ustime();\n    if ((childpid = fork()) == 0) {\n        int retval;\n\n        /* Child */\n        closeListeningSockets(0);\n        redisSetProcTitle(\"redis-rdb-bgsave\");\n        retval = rdbSave(filename);\n        if (retval == C_OK) {\n            size_t private_dirty = zmalloc_get_private_dirty();\n\n            if (private_dirty) {\n                serverLog(LL_NOTICE,\n                    \"RDB: %zu MB of memory used by copy-on-write\",\n                    private_dirty/(1024*1024));\n            }\n        }\n        exitFromChild((retval == C_OK) ? 0 : 1);\n    } else {\n        /* Parent */\n        server.stat_fork_time = ustime()-start;\n        server.stat_fork_rate = (double) zmalloc_used_memory() * 1000000 / server.stat_fork_time / (1024*1024*1024); /* GB per second. */\n        latencyAddSampleIfNeeded(\"fork\",server.stat_fork_time/1000);\n        if (childpid == -1) {\n            server.lastbgsave_status = C_ERR;\n            serverLog(LL_WARNING,\"Can't save in background: fork: %s\",\n                strerror(errno));\n            return C_ERR;\n        }\n        serverLog(LL_NOTICE,\"Background saving started by pid %d\",childpid);\n        server.rdb_save_time_start = time(NULL);\n        server.rdb_child_pid = childpid;\n        server.rdb_child_type = RDB_CHILD_TYPE_DISK;\n        updateDictResizePolicy();\n        return C_OK;\n    }\n    return C_OK; /* unreached */\n}\n\nvoid rdbRemoveTempFile(pid_t childpid) {\n    char tmpfile[256];\n\n    snprintf(tmpfile,sizeof(tmpfile),\"temp-%d.rdb\", (int) childpid);\n    unlink(tmpfile);\n}\n\n/* Load a Redis object of the specified type from the specified file.\n * On success a newly allocated object is returned, otherwise NULL. */\nrobj *rdbLoadObject(int rdbtype, rio *rdb) {\n    robj *o = NULL, *ele, *dec;\n    size_t len;\n    unsigned int i;\n\n    if (rdbtype == RDB_TYPE_STRING) {\n        /* Read string value */\n        if ((o = rdbLoadEncodedStringObject(rdb)) == NULL) return NULL;\n        o = tryObjectEncoding(o);\n    } else if (rdbtype == RDB_TYPE_LIST) {\n        /* Read list value */\n        if ((len = rdbLoadLen(rdb,NULL)) == RDB_LENERR) return NULL;\n\n        o = createQuicklistObject();\n        quicklistSetOptions(o->ptr, server.list_max_ziplist_size,\n                            server.list_compress_depth);\n\n        /* Load every single element of the list */\n        while(len--) {\n            if ((ele = rdbLoadEncodedStringObject(rdb)) == NULL) return NULL;\n            dec = getDecodedObject(ele);\n            size_t len = sdslen(dec->ptr);\n            quicklistPushTail(o->ptr, dec->ptr, len);\n            decrRefCount(dec);\n            decrRefCount(ele);\n        }\n    } else if (rdbtype == RDB_TYPE_SET) {\n        /* Read list/set value */\n        if ((len = rdbLoadLen(rdb,NULL)) == RDB_LENERR) return NULL;\n\n        /* Use a regular set when there are too many entries. */\n        if (len > server.set_max_intset_entries) {\n            o = createSetObject();\n            /* It's faster to expand the dict to the right size asap in order\n             * to avoid rehashing */\n            if (len > DICT_HT_INITIAL_SIZE)\n                dictExpand(o->ptr,len);\n        } else {\n            o = createIntsetObject();\n        }\n\n        /* Load every single element of the list/set */\n        for (i = 0; i < len; i++) {\n            long long llval;\n            if ((ele = rdbLoadEncodedStringObject(rdb)) == NULL) return NULL;\n            ele = tryObjectEncoding(ele);\n\n            if (o->encoding == OBJ_ENCODING_INTSET) {\n                /* Fetch integer value from element */\n                if (isObjectRepresentableAsLongLong(ele,&llval) == C_OK) {\n                    o->ptr = intsetAdd(o->ptr,llval,NULL);\n                } else {\n                    setTypeConvert(o,OBJ_ENCODING_HT);\n                    dictExpand(o->ptr,len);\n                }\n            }\n\n            /* This will also be called when the set was just converted\n             * to a regular hash table encoded set */\n            if (o->encoding == OBJ_ENCODING_HT) {\n                dictAdd((dict*)o->ptr,ele,NULL);\n            } else {\n                decrRefCount(ele);\n            }\n        }\n    } else if (rdbtype == RDB_TYPE_ZSET) {\n        /* Read list/set value */\n        size_t zsetlen;\n        size_t maxelelen = 0;\n        zset *zs;\n\n        if ((zsetlen = rdbLoadLen(rdb,NULL)) == RDB_LENERR) return NULL;\n        o = createZsetObject();\n        zs = o->ptr;\n\n        /* Load every single element of the list/set */\n        while(zsetlen--) {\n            robj *ele;\n            double score;\n            zskiplistNode *znode;\n\n            if ((ele = rdbLoadEncodedStringObject(rdb)) == NULL) return NULL;\n            ele = tryObjectEncoding(ele);\n            if (rdbLoadDoubleValue(rdb,&score) == -1) return NULL;\n\n            /* Don't care about integer-encoded strings. */\n            if (sdsEncodedObject(ele) && sdslen(ele->ptr) > maxelelen)\n                maxelelen = sdslen(ele->ptr);\n\n            znode = zslInsert(zs->zsl,score,ele);\n            dictAdd(zs->dict,ele,&znode->score);\n            incrRefCount(ele); /* added to skiplist */\n        }\n\n        /* Convert *after* loading, since sorted sets are not stored ordered. */\n        if (zsetLength(o) <= server.zset_max_ziplist_entries &&\n            maxelelen <= server.zset_max_ziplist_value)\n                zsetConvert(o,OBJ_ENCODING_ZIPLIST);\n    } else if (rdbtype == RDB_TYPE_HASH) {\n        size_t len;\n        int ret;\n\n        len = rdbLoadLen(rdb, NULL);\n        if (len == RDB_LENERR) return NULL;\n\n        o = createHashObject();\n\n        /* Too many entries? Use a hash table. */\n        if (len > server.hash_max_ziplist_entries)\n            hashTypeConvert(o, OBJ_ENCODING_HT);\n\n        /* Load every field and value into the ziplist */\n        while (o->encoding == OBJ_ENCODING_ZIPLIST && len > 0) {\n            robj *field, *value;\n\n            len--;\n            /* Load raw strings */\n            field = rdbLoadStringObject(rdb);\n            if (field == NULL) return NULL;\n            serverAssert(sdsEncodedObject(field));\n            value = rdbLoadStringObject(rdb);\n            if (value == NULL) return NULL;\n            serverAssert(sdsEncodedObject(value));\n\n            /* Add pair to ziplist */\n            o->ptr = ziplistPush(o->ptr, field->ptr, sdslen(field->ptr), ZIPLIST_TAIL);\n            o->ptr = ziplistPush(o->ptr, value->ptr, sdslen(value->ptr), ZIPLIST_TAIL);\n            /* Convert to hash table if size threshold is exceeded */\n            if (sdslen(field->ptr) > server.hash_max_ziplist_value ||\n                sdslen(value->ptr) > server.hash_max_ziplist_value)\n            {\n                decrRefCount(field);\n                decrRefCount(value);\n                hashTypeConvert(o, OBJ_ENCODING_HT);\n                break;\n            }\n            decrRefCount(field);\n            decrRefCount(value);\n        }\n\n        /* Load remaining fields and values into the hash table */\n        while (o->encoding == OBJ_ENCODING_HT && len > 0) {\n            robj *field, *value;\n\n            len--;\n            /* Load encoded strings */\n            field = rdbLoadEncodedStringObject(rdb);\n            if (field == NULL) return NULL;\n            value = rdbLoadEncodedStringObject(rdb);\n            if (value == NULL) return NULL;\n\n            field = tryObjectEncoding(field);\n            value = tryObjectEncoding(value);\n\n            /* Add pair to hash table */\n            ret = dictAdd((dict*)o->ptr, field, value);\n            if (ret == DICT_ERR) {\n                rdbExitReportCorruptRDB(\"Duplicate keys detected\");\n            }\n        }\n\n        /* All pairs should be read by now */\n        serverAssert(len == 0);\n    } else if (rdbtype == RDB_TYPE_LIST_QUICKLIST) {\n        if ((len = rdbLoadLen(rdb,NULL)) == RDB_LENERR) return NULL;\n        o = createQuicklistObject();\n        quicklistSetOptions(o->ptr, server.list_max_ziplist_size,\n                            server.list_compress_depth);\n\n        while (len--) {\n            unsigned char *zl = rdbGenericLoadStringObject(rdb,RDB_LOAD_PLAIN);\n            if (zl == NULL) return NULL;\n            quicklistAppendZiplist(o->ptr, zl);\n        }\n    } else if (rdbtype == RDB_TYPE_HASH_ZIPMAP  ||\n               rdbtype == RDB_TYPE_LIST_ZIPLIST ||\n               rdbtype == RDB_TYPE_SET_INTSET   ||\n               rdbtype == RDB_TYPE_ZSET_ZIPLIST ||\n               rdbtype == RDB_TYPE_HASH_ZIPLIST)\n    {\n        unsigned char *encoded = rdbGenericLoadStringObject(rdb,RDB_LOAD_PLAIN);\n        if (encoded == NULL) return NULL;\n        o = createObject(OBJ_STRING,encoded); /* Obj type fixed below. */\n\n        /* Fix the object encoding, and make sure to convert the encoded\n         * data type into the base type if accordingly to the current\n         * configuration there are too many elements in the encoded data\n         * type. Note that we only check the length and not max element\n         * size as this is an O(N) scan. Eventually everything will get\n         * converted. */\n        switch(rdbtype) {\n            case RDB_TYPE_HASH_ZIPMAP:\n                /* Convert to ziplist encoded hash. This must be deprecated\n                 * when loading dumps created by Redis 2.4 gets deprecated. */\n                {\n                    unsigned char *zl = ziplistNew();\n                    unsigned char *zi = zipmapRewind(o->ptr);\n                    unsigned char *fstr, *vstr;\n                    unsigned int flen, vlen;\n                    unsigned int maxlen = 0;\n\n                    while ((zi = zipmapNext(zi, &fstr, &flen, &vstr, &vlen)) != NULL) {\n                        if (flen > maxlen) maxlen = flen;\n                        if (vlen > maxlen) maxlen = vlen;\n                        zl = ziplistPush(zl, fstr, flen, ZIPLIST_TAIL);\n                        zl = ziplistPush(zl, vstr, vlen, ZIPLIST_TAIL);\n                    }\n\n                    zfree(o->ptr);\n                    o->ptr = zl;\n                    o->type = OBJ_HASH;\n                    o->encoding = OBJ_ENCODING_ZIPLIST;\n\n                    if (hashTypeLength(o) > server.hash_max_ziplist_entries ||\n                        maxlen > server.hash_max_ziplist_value)\n                    {\n                        hashTypeConvert(o, OBJ_ENCODING_HT);\n                    }\n                }\n                break;\n            case RDB_TYPE_LIST_ZIPLIST:\n                o->type = OBJ_LIST;\n                o->encoding = OBJ_ENCODING_ZIPLIST;\n                listTypeConvert(o,OBJ_ENCODING_QUICKLIST);\n                break;\n            case RDB_TYPE_SET_INTSET:\n                o->type = OBJ_SET;\n                o->encoding = OBJ_ENCODING_INTSET;\n                if (intsetLen(o->ptr) > server.set_max_intset_entries)\n                    setTypeConvert(o,OBJ_ENCODING_HT);\n                break;\n            case RDB_TYPE_ZSET_ZIPLIST:\n                o->type = OBJ_ZSET;\n                o->encoding = OBJ_ENCODING_ZIPLIST;\n                if (zsetLength(o) > server.zset_max_ziplist_entries)\n                    zsetConvert(o,OBJ_ENCODING_SKIPLIST);\n                break;\n            case RDB_TYPE_HASH_ZIPLIST:\n                o->type = OBJ_HASH;\n                o->encoding = OBJ_ENCODING_ZIPLIST;\n                if (hashTypeLength(o) > server.hash_max_ziplist_entries)\n                    hashTypeConvert(o, OBJ_ENCODING_HT);\n                break;\n            default:\n                rdbExitReportCorruptRDB(\"Unknown RDB encoding type %d\",rdbtype);\n                break;\n        }\n    } else {\n        rdbExitReportCorruptRDB(\"Unknown RDB encoding type %d\",rdbtype);\n    }\n    return o;\n}\n\n/* Mark that we are loading in the global state and setup the fields\n * needed to provide loading stats. */\nvoid startLoading(FILE *fp) {\n    struct stat sb;\n\n    /* Load the DB */\n    server.loading = 1;\n    server.loading_start_time = time(NULL);\n    server.loading_loaded_bytes = 0;\n    if (fstat(fileno(fp), &sb) == -1) {\n        server.loading_total_bytes = 0;\n    } else {\n        server.loading_total_bytes = sb.st_size;\n    }\n}\n\n/* Refresh the loading progress info */\nvoid loadingProgress(off_t pos) {\n    server.loading_loaded_bytes = pos;\n    if (server.stat_peak_memory < zmalloc_used_memory())\n        server.stat_peak_memory = zmalloc_used_memory();\n}\n\n/* Loading finished */\nvoid stopLoading(void) {\n    server.loading = 0;\n}\n\n/* Track loading progress in order to serve client's from time to time\n   and if needed calculate rdb checksum  */\nvoid rdbLoadProgressCallback(rio *r, const void *buf, size_t len) {\n    if (server.rdb_checksum)\n        rioGenericUpdateChecksum(r, buf, len);\n    if (server.loading_process_events_interval_bytes &&\n        (r->processed_bytes + len)/server.loading_process_events_interval_bytes > r->processed_bytes/server.loading_process_events_interval_bytes)\n    {\n        /* The DB can take some non trivial amount of time to load. Update\n         * our cached time since it is used to create and update the last\n         * interaction time with clients and for other important things. */\n        updateCachedTime();\n        if (server.masterhost && server.repl_state == REPL_STATE_TRANSFER)\n            replicationSendNewlineToMaster();\n        loadingProgress(r->processed_bytes);\n        processEventsWhileBlocked();\n    }\n}\n\nint rdbLoad(char *filename) {\n    uint32_t dbid;\n    int type, rdbver;\n    redisDb *db = server.db+0;\n    char buf[1024];\n    long long expiretime, now = mstime();\n    FILE *fp;\n    rio rdb;\n\n    if ((fp = fopen(filename,\"r\")) == NULL) return C_ERR;\n\n    rioInitWithFile(&rdb,fp);\n    rdb.update_cksum = rdbLoadProgressCallback;\n    rdb.max_processing_chunk = server.loading_process_events_interval_bytes;\n    if (rioRead(&rdb,buf,9) == 0) goto eoferr;\n    buf[9] = '\\0';\n    if (memcmp(buf,\"REDIS\",5) != 0) {\n        fclose(fp);\n        serverLog(LL_WARNING,\"Wrong signature trying to load DB from file\");\n        errno = EINVAL;\n        return C_ERR;\n    }\n    rdbver = atoi(buf+5);\n    if (rdbver < 1 || rdbver > RDB_VERSION) {\n        fclose(fp);\n        serverLog(LL_WARNING,\"Can't handle RDB format version %d\",rdbver);\n        errno = EINVAL;\n        return C_ERR;\n    }\n\n    startLoading(fp);\n    while(1) {\n        robj *key, *val;\n        expiretime = -1;\n\n        /* Read type. */\n        if ((type = rdbLoadType(&rdb)) == -1) goto eoferr;\n\n        /* Handle special types. */\n        if (type == RDB_OPCODE_EXPIRETIME) {\n            /* EXPIRETIME: load an expire associated with the next key\n             * to load. Note that after loading an expire we need to\n             * load the actual type, and continue. */\n            if ((expiretime = rdbLoadTime(&rdb)) == -1) goto eoferr;\n            /* We read the time so we need to read the object type again. */\n            if ((type = rdbLoadType(&rdb)) == -1) goto eoferr;\n            /* the EXPIRETIME opcode specifies time in seconds, so convert\n             * into milliseconds. */\n            expiretime *= 1000;\n        } else if (type == RDB_OPCODE_EXPIRETIME_MS) {\n            /* EXPIRETIME_MS: milliseconds precision expire times introduced\n             * with RDB v3. Like EXPIRETIME but no with more precision. */\n            if ((expiretime = rdbLoadMillisecondTime(&rdb)) == -1) goto eoferr;\n            /* We read the time so we need to read the object type again. */\n            if ((type = rdbLoadType(&rdb)) == -1) goto eoferr;\n        } else if (type == RDB_OPCODE_EOF) {\n            /* EOF: End of file, exit the main loop. */\n            break;\n        } else if (type == RDB_OPCODE_SELECTDB) {\n            /* SELECTDB: Select the specified database. */\n            if ((dbid = rdbLoadLen(&rdb,NULL)) == RDB_LENERR)\n                goto eoferr;\n            if (dbid >= (unsigned)server.dbnum) {\n                serverLog(LL_WARNING,\n                    \"FATAL: Data file was created with a Redis \"\n                    \"server configured to handle more than %d \"\n                    \"databases. Exiting\\n\", server.dbnum);\n                exit(1);\n            }\n            db = server.db+dbid;\n            continue; /* Read type again. */\n        } else if (type == RDB_OPCODE_RESIZEDB) {\n            /* RESIZEDB: Hint about the size of the keys in the currently\n             * selected data base, in order to avoid useless rehashing. */\n            uint32_t db_size, expires_size;\n            if ((db_size = rdbLoadLen(&rdb,NULL)) == RDB_LENERR)\n                goto eoferr;\n            if ((expires_size = rdbLoadLen(&rdb,NULL)) == RDB_LENERR)\n                goto eoferr;\n            dictExpand(db->dict,db_size);\n            dictExpand(db->expires,expires_size);\n            continue; /* Read type again. */\n        } else if (type == RDB_OPCODE_AUX) {\n            /* AUX: generic string-string fields. Use to add state to RDB\n             * which is backward compatible. Implementations of RDB loading\n             * are requierd to skip AUX fields they don't understand.\n             *\n             * An AUX field is composed of two strings: key and value. */\n            robj *auxkey, *auxval;\n            if ((auxkey = rdbLoadStringObject(&rdb)) == NULL) goto eoferr;\n            if ((auxval = rdbLoadStringObject(&rdb)) == NULL) goto eoferr;\n\n            if (((char*)auxkey->ptr)[0] == '%') {\n                /* All the fields with a name staring with '%' are considered\n                 * information fields and are logged at startup with a log\n                 * level of NOTICE. */\n                serverLog(LL_NOTICE,\"RDB '%s': %s\",\n                    (char*)auxkey->ptr,\n                    (char*)auxval->ptr);\n            } else {\n                /* We ignore fields we don't understand, as by AUX field\n                 * contract. */\n                serverLog(LL_DEBUG,\"Unrecognized RDB AUX field: '%s'\",\n                    (char*)auxkey->ptr);\n            }\n\n            decrRefCount(auxkey);\n            decrRefCount(auxval);\n            continue; /* Read type again. */\n        }\n\n        /* Read key */\n        if ((key = rdbLoadStringObject(&rdb)) == NULL) goto eoferr;\n        /* Read value */\n        if ((val = rdbLoadObject(type,&rdb)) == NULL) goto eoferr;\n        /* Check if the key already expired. This function is used when loading\n         * an RDB file from disk, either at startup, or when an RDB was\n         * received from the master. In the latter case, the master is\n         * responsible for key expiry. If we would expire keys here, the\n         * snapshot taken by the master may not be reflected on the slave. */\n        if (server.masterhost == NULL && expiretime != -1 && expiretime < now) {\n            decrRefCount(key);\n            decrRefCount(val);\n            continue;\n        }\n        /* Add the new object in the hash table */\n        dbAdd(db,key,val);\n\n        /* Set the expire time if needed */\n        if (expiretime != -1) setExpire(db,key,expiretime);\n\n        decrRefCount(key);\n    }\n    /* Verify the checksum if RDB version is >= 5 */\n    if (rdbver >= 5 && server.rdb_checksum) {\n        uint64_t cksum, expected = rdb.cksum;\n\n        if (rioRead(&rdb,&cksum,8) == 0) goto eoferr;\n        memrev64ifbe(&cksum);\n        if (cksum == 0) {\n            serverLog(LL_WARNING,\"RDB file was saved with checksum disabled: no check performed.\");\n        } else if (cksum != expected) {\n            serverLog(LL_WARNING,\"Wrong RDB checksum. Aborting now.\");\n            rdbExitReportCorruptRDB(\"RDB CRC error\");\n        }\n    }\n\n    fclose(fp);\n    stopLoading();\n    return C_OK;\n\neoferr: /* unexpected end of file is handled here with a fatal exit */\n    serverLog(LL_WARNING,\"Short read or OOM loading DB. Unrecoverable error, aborting now.\");\n    rdbExitReportCorruptRDB(\"Unexpected EOF reading RDB file\");\n    return C_ERR; /* Just to avoid warning */\n}\n\n/* A background saving child (BGSAVE) terminated its work. Handle this.\n * This function covers the case of actual BGSAVEs. */\nvoid backgroundSaveDoneHandlerDisk(int exitcode, int bysignal) {\n    if (!bysignal && exitcode == 0) {\n        serverLog(LL_NOTICE,\n            \"Background saving terminated with success\");\n        server.dirty = server.dirty - server.dirty_before_bgsave;\n        server.lastsave = time(NULL);\n        server.lastbgsave_status = C_OK;\n    } else if (!bysignal && exitcode != 0) {\n        serverLog(LL_WARNING, \"Background saving error\");\n        server.lastbgsave_status = C_ERR;\n    } else {\n        mstime_t latency;\n\n        serverLog(LL_WARNING,\n            \"Background saving terminated by signal %d\", bysignal);\n        latencyStartMonitor(latency);\n        rdbRemoveTempFile(server.rdb_child_pid);\n        latencyEndMonitor(latency);\n        latencyAddSampleIfNeeded(\"rdb-unlink-temp-file\",latency);\n        /* SIGUSR1 is whitelisted, so we have a way to kill a child without\n         * tirggering an error conditon. */\n        if (bysignal != SIGUSR1)\n            server.lastbgsave_status = C_ERR;\n    }\n    server.rdb_child_pid = -1;\n    server.rdb_child_type = RDB_CHILD_TYPE_NONE;\n    server.rdb_save_time_last = time(NULL)-server.rdb_save_time_start;\n    server.rdb_save_time_start = -1;\n    /* Possibly there are slaves waiting for a BGSAVE in order to be served\n     * (the first stage of SYNC is a bulk transfer of dump.rdb) */\n    updateSlavesWaitingBgsave((!bysignal && exitcode == 0) ? C_OK : C_ERR, RDB_CHILD_TYPE_DISK);\n}\n\n/* A background saving child (BGSAVE) terminated its work. Handle this.\n * This function covers the case of RDB -> Salves socket transfers for\n * diskless replication. */\nvoid backgroundSaveDoneHandlerSocket(int exitcode, int bysignal) {\n    uint64_t *ok_slaves;\n\n    if (!bysignal && exitcode == 0) {\n        serverLog(LL_NOTICE,\n            \"Background RDB transfer terminated with success\");\n    } else if (!bysignal && exitcode != 0) {\n        serverLog(LL_WARNING, \"Background transfer error\");\n    } else {\n        serverLog(LL_WARNING,\n            \"Background transfer terminated by signal %d\", bysignal);\n    }\n    server.rdb_child_pid = -1;\n    server.rdb_child_type = RDB_CHILD_TYPE_NONE;\n    server.rdb_save_time_start = -1;\n\n    /* If the child returns an OK exit code, read the set of slave client\n     * IDs and the associated status code. We'll terminate all the slaves\n     * in error state.\n     *\n     * If the process returned an error, consider the list of slaves that\n     * can continue to be emtpy, so that it's just a special case of the\n     * normal code path. */\n    ok_slaves = zmalloc(sizeof(uint64_t)); /* Make space for the count. */\n    ok_slaves[0] = 0;\n    if (!bysignal && exitcode == 0) {\n        int readlen = sizeof(uint64_t);\n\n        if (read(server.rdb_pipe_read_result_from_child, ok_slaves, readlen) ==\n                 readlen)\n        {\n            readlen = ok_slaves[0]*sizeof(uint64_t)*2;\n\n            /* Make space for enough elements as specified by the first\n             * uint64_t element in the array. */\n            ok_slaves = zrealloc(ok_slaves,sizeof(uint64_t)+readlen);\n            if (readlen &&\n                read(server.rdb_pipe_read_result_from_child, ok_slaves+1,\n                     readlen) != readlen)\n            {\n                ok_slaves[0] = 0;\n            }\n        }\n    }\n\n    close(server.rdb_pipe_read_result_from_child);\n    close(server.rdb_pipe_write_result_to_parent);\n\n    /* We can continue the replication process with all the slaves that\n     * correctly received the full payload. Others are terminated. */\n    listNode *ln;\n    listIter li;\n\n    listRewind(server.slaves,&li);\n    while((ln = listNext(&li))) {\n        client *slave = ln->value;\n\n        if (slave->replstate == SLAVE_STATE_WAIT_BGSAVE_END) {\n            uint64_t j;\n            int errorcode = 0;\n\n            /* Search for the slave ID in the reply. In order for a slave to\n             * continue the replication process, we need to find it in the list,\n             * and it must have an error code set to 0 (which means success). */\n            for (j = 0; j < ok_slaves[0]; j++) {\n                if (slave->id == ok_slaves[2*j+1]) {\n                    errorcode = ok_slaves[2*j+2];\n                    break; /* Found in slaves list. */\n                }\n            }\n            if (j == ok_slaves[0] || errorcode != 0) {\n                serverLog(LL_WARNING,\n                \"Closing slave %s: child->slave RDB transfer failed: %s\",\n                    replicationGetSlaveName(slave),\n                    (errorcode == 0) ? \"RDB transfer child aborted\"\n                                     : strerror(errorcode));\n                freeClient(slave);\n            } else {\n                serverLog(LL_WARNING,\n                \"Slave %s correctly received the streamed RDB file.\",\n                    replicationGetSlaveName(slave));\n                /* Restore the socket as non-blocking. */\n                anetNonBlock(NULL,slave->fd);\n                anetSendTimeout(NULL,slave->fd,0);\n            }\n        }\n    }\n    zfree(ok_slaves);\n\n    updateSlavesWaitingBgsave((!bysignal && exitcode == 0) ? C_OK : C_ERR, RDB_CHILD_TYPE_SOCKET);\n}\n\n/* When a background RDB saving/transfer terminates, call the right handler. */\nvoid backgroundSaveDoneHandler(int exitcode, int bysignal) {\n    switch(server.rdb_child_type) {\n    case RDB_CHILD_TYPE_DISK:\n        backgroundSaveDoneHandlerDisk(exitcode,bysignal);\n        break;\n    case RDB_CHILD_TYPE_SOCKET:\n        backgroundSaveDoneHandlerSocket(exitcode,bysignal);\n        break;\n    default:\n        serverPanic(\"Unknown RDB child type.\");\n        break;\n    }\n}\n\n/* Spawn an RDB child that writes the RDB to the sockets of the slaves\n * that are currently in SLAVE_STATE_WAIT_BGSAVE_START state. */\nint rdbSaveToSlavesSockets(void) {\n    int *fds;\n    uint64_t *clientids;\n    int numfds;\n    listNode *ln;\n    listIter li;\n    pid_t childpid;\n    long long start;\n    int pipefds[2];\n\n    if (server.aof_child_pid != -1 || server.rdb_child_pid != -1) return C_ERR;\n\n    /* Before to fork, create a pipe that will be used in order to\n     * send back to the parent the IDs of the slaves that successfully\n     * received all the writes. */\n    if (pipe(pipefds) == -1) return C_ERR;\n    server.rdb_pipe_read_result_from_child = pipefds[0];\n    server.rdb_pipe_write_result_to_parent = pipefds[1];\n\n    /* Collect the file descriptors of the slaves we want to transfer\n     * the RDB to, which are i WAIT_BGSAVE_START state. */\n    fds = zmalloc(sizeof(int)*listLength(server.slaves));\n    /* We also allocate an array of corresponding client IDs. This will\n     * be useful for the child process in order to build the report\n     * (sent via unix pipe) that will be sent to the parent. */\n    clientids = zmalloc(sizeof(uint64_t)*listLength(server.slaves));\n    numfds = 0;\n\n    listRewind(server.slaves,&li);\n    while((ln = listNext(&li))) {\n        client *slave = ln->value;\n\n        if (slave->replstate == SLAVE_STATE_WAIT_BGSAVE_START) {\n            clientids[numfds] = slave->id;\n            fds[numfds++] = slave->fd;\n            replicationSetupSlaveForFullResync(slave,getPsyncInitialOffset());\n            /* Put the socket in blocking mode to simplify RDB transfer.\n             * We'll restore it when the children returns (since duped socket\n             * will share the O_NONBLOCK attribute with the parent). */\n            anetBlock(NULL,slave->fd);\n            anetSendTimeout(NULL,slave->fd,server.repl_timeout*1000);\n        }\n    }\n\n    /* Create the child process. */\n    start = ustime();\n    if ((childpid = fork()) == 0) {\n        /* Child */\n        int retval;\n        rio slave_sockets;\n\n        rioInitWithFdset(&slave_sockets,fds,numfds);\n        zfree(fds);\n\n        closeListeningSockets(0);\n        redisSetProcTitle(\"redis-rdb-to-slaves\");\n\n        retval = rdbSaveRioWithEOFMark(&slave_sockets,NULL);\n        if (retval == C_OK && rioFlush(&slave_sockets) == 0)\n            retval = C_ERR;\n\n        if (retval == C_OK) {\n            size_t private_dirty = zmalloc_get_private_dirty();\n\n            if (private_dirty) {\n                serverLog(LL_NOTICE,\n                    \"RDB: %zu MB of memory used by copy-on-write\",\n                    private_dirty/(1024*1024));\n            }\n\n            /* If we are returning OK, at least one slave was served\n             * with the RDB file as expected, so we need to send a report\n             * to the parent via the pipe. The format of the message is:\n             *\n             * <len> <slave[0].id> <slave[0].error> ...\n             *\n             * len, slave IDs, and slave errors, are all uint64_t integers,\n             * so basically the reply is composed of 64 bits for the len field\n             * plus 2 additional 64 bit integers for each entry, for a total\n             * of 'len' entries.\n             *\n             * The 'id' represents the slave's client ID, so that the master\n             * can match the report with a specific slave, and 'error' is\n             * set to 0 if the replication process terminated with a success\n             * or the error code if an error occurred. */\n            void *msg = zmalloc(sizeof(uint64_t)*(1+2*numfds));\n            uint64_t *len = msg;\n            uint64_t *ids = len+1;\n            int j, msglen;\n\n            *len = numfds;\n            for (j = 0; j < numfds; j++) {\n                *ids++ = clientids[j];\n                *ids++ = slave_sockets.io.fdset.state[j];\n            }\n\n            /* Write the message to the parent. If we have no good slaves or\n             * we are unable to transfer the message to the parent, we exit\n             * with an error so that the parent will abort the replication\n             * process with all the childre that were waiting. */\n            msglen = sizeof(uint64_t)*(1+2*numfds);\n            if (*len == 0 ||\n                write(server.rdb_pipe_write_result_to_parent,msg,msglen)\n                != msglen)\n            {\n                retval = C_ERR;\n            }\n            zfree(msg);\n        }\n        zfree(clientids);\n        rioFreeFdset(&slave_sockets);\n        exitFromChild((retval == C_OK) ? 0 : 1);\n    } else {\n        /* Parent */\n        server.stat_fork_time = ustime()-start;\n        server.stat_fork_rate = (double) zmalloc_used_memory() * 1000000 / server.stat_fork_time / (1024*1024*1024); /* GB per second. */\n        latencyAddSampleIfNeeded(\"fork\",server.stat_fork_time/1000);\n        if (childpid == -1) {\n            serverLog(LL_WARNING,\"Can't save in background: fork: %s\",\n                strerror(errno));\n\n            /* Undo the state change. The caller will perform cleanup on\n             * all the slaves in BGSAVE_START state, but an early call to\n             * replicationSetupSlaveForFullResync() turned it into BGSAVE_END */\n            listRewind(server.slaves,&li);\n            while((ln = listNext(&li))) {\n                client *slave = ln->value;\n                int j;\n\n                for (j = 0; j < numfds; j++) {\n                    if (slave->id == clientids[j]) {\n                        slave->replstate = SLAVE_STATE_WAIT_BGSAVE_START;\n                        break;\n                    }\n                }\n            }\n            close(pipefds[0]);\n            close(pipefds[1]);\n        } else {\n            serverLog(LL_NOTICE,\"Background RDB transfer started by pid %d\",\n                childpid);\n            server.rdb_save_time_start = time(NULL);\n            server.rdb_child_pid = childpid;\n            server.rdb_child_type = RDB_CHILD_TYPE_SOCKET;\n            updateDictResizePolicy();\n        }\n        zfree(clientids);\n        zfree(fds);\n        return (childpid == -1) ? C_ERR : C_OK;\n    }\n    return C_OK; /* Unreached. */\n}\n\nvoid saveCommand(client *c) {\n    if (server.rdb_child_pid != -1) {\n        addReplyError(c,\"Background save already in progress\");\n        return;\n    }\n    if (rdbSave(server.rdb_filename) == C_OK) {\n        addReply(c,shared.ok);\n    } else {\n        addReply(c,shared.err);\n    }\n}\n\n/* BGSAVE [SCHEDULE] */\nvoid bgsaveCommand(client *c) {\n    int schedule = 0;\n\n    /* The SCHEDULE option changes the behavior of BGSAVE when an AOF rewrite\n     * is in progress. Instead of returning an error a BGSAVE gets scheduled. */\n    if (c->argc > 1) {\n        if (c->argc == 2 && !strcasecmp(c->argv[1]->ptr,\"schedule\")) {\n            schedule = 1;\n        } else {\n            addReply(c,shared.syntaxerr);\n            return;\n        }\n    }\n\n    if (server.rdb_child_pid != -1) {\n        addReplyError(c,\"Background save already in progress\");\n    } else if (server.aof_child_pid != -1) {\n        if (schedule) {\n            server.rdb_bgsave_scheduled = 1;\n            addReplyStatus(c,\"Background saving scheduled\");\n        } else {\n            addReplyError(c,\n                \"An AOF log rewriting in progress: can't BGSAVE right now. \"\n                \"Use BGSAVE SCHEDULE in order to schedule a BGSAVE whenver \"\n                \"possible.\");\n        }\n    } else if (rdbSaveBackground(server.rdb_filename) == C_OK) {\n        addReplyStatus(c,\"Background saving started\");\n    } else {\n        addReply(c,shared.err);\n    }\n}\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/src/rdb.h",
    "content": "/*\n * Copyright (c) 2009-2012, Salvatore Sanfilippo <antirez at gmail dot com>\n * All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions are met:\n *\n *   * Redistributions of source code must retain the above copyright notice,\n *     this list of conditions and the following disclaimer.\n *   * Redistributions in binary form must reproduce the above copyright\n *     notice, this list of conditions and the following disclaimer in the\n *     documentation and/or other materials provided with the distribution.\n *   * Neither the name of Redis nor the names of its contributors may be used\n *     to endorse or promote products derived from this software without\n *     specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\"\n * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\n * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE\n * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR\n * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF\n * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS\n * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN\n * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)\n * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE\n * POSSIBILITY OF SUCH DAMAGE.\n */\n\n#ifndef __RDB_H\n#define __RDB_H\n\n#include <stdio.h>\n#include \"rio.h\"\n\n/* TBD: include only necessary headers. */\n#include \"server.h\"\n\n/* The current RDB version. When the format changes in a way that is no longer\n * backward compatible this number gets incremented. */\n#define RDB_VERSION 7\n\n/* Defines related to the dump file format. To store 32 bits lengths for short\n * keys requires a lot of space, so we check the most significant 2 bits of\n * the first byte to interpreter the length:\n *\n * 00|000000 => if the two MSB are 00 the len is the 6 bits of this byte\n * 01|000000 00000000 =>  01, the len is 14 byes, 6 bits + 8 bits of next byte\n * 10|000000 [32 bit integer] => if it's 01, a full 32 bit len will follow\n * 11|000000 this means: specially encoded object will follow. The six bits\n *           number specify the kind of object that follows.\n *           See the RDB_ENC_* defines.\n *\n * Lengths up to 63 are stored using a single byte, most DB keys, and may\n * values, will fit inside. */\n#define RDB_6BITLEN 0\n#define RDB_14BITLEN 1\n#define RDB_32BITLEN 2\n#define RDB_ENCVAL 3\n#define RDB_LENERR UINT_MAX\n\n/* When a length of a string object stored on disk has the first two bits\n * set, the remaining two bits specify a special encoding for the object\n * accordingly to the following defines: */\n#define RDB_ENC_INT8 0        /* 8 bit signed integer */\n#define RDB_ENC_INT16 1       /* 16 bit signed integer */\n#define RDB_ENC_INT32 2       /* 32 bit signed integer */\n#define RDB_ENC_LZF 3         /* string compressed with FASTLZ */\n\n/* Dup object types to RDB object types. Only reason is readability (are we\n * dealing with RDB types or with in-memory object types?). */\n#define RDB_TYPE_STRING 0\n#define RDB_TYPE_LIST   1\n#define RDB_TYPE_SET    2\n#define RDB_TYPE_ZSET   3\n#define RDB_TYPE_HASH   4\n/* NOTE: WHEN ADDING NEW RDB TYPE, UPDATE rdbIsObjectType() BELOW */\n\n/* Object types for encoded objects. */\n#define RDB_TYPE_HASH_ZIPMAP    9\n#define RDB_TYPE_LIST_ZIPLIST  10\n#define RDB_TYPE_SET_INTSET    11\n#define RDB_TYPE_ZSET_ZIPLIST  12\n#define RDB_TYPE_HASH_ZIPLIST  13\n#define RDB_TYPE_LIST_QUICKLIST 14\n/* NOTE: WHEN ADDING NEW RDB TYPE, UPDATE rdbIsObjectType() BELOW */\n\n/* Test if a type is an object type. */\n#define rdbIsObjectType(t) ((t >= 0 && t <= 4) || (t >= 9 && t <= 14))\n\n/* Special RDB opcodes (saved/loaded with rdbSaveType/rdbLoadType). */\n#define RDB_OPCODE_AUX        250\n#define RDB_OPCODE_RESIZEDB   251\n#define RDB_OPCODE_EXPIRETIME_MS 252\n#define RDB_OPCODE_EXPIRETIME 253\n#define RDB_OPCODE_SELECTDB   254\n#define RDB_OPCODE_EOF        255\n\nint rdbSaveType(rio *rdb, unsigned char type);\nint rdbLoadType(rio *rdb);\nint rdbSaveTime(rio *rdb, time_t t);\ntime_t rdbLoadTime(rio *rdb);\nint rdbSaveLen(rio *rdb, uint32_t len);\nuint32_t rdbLoadLen(rio *rdb, int *isencoded);\nint rdbSaveObjectType(rio *rdb, robj *o);\nint rdbLoadObjectType(rio *rdb);\nint rdbLoad(char *filename);\nint rdbSaveBackground(char *filename);\nint rdbSaveToSlavesSockets(void);\nvoid rdbRemoveTempFile(pid_t childpid);\nint rdbSave(char *filename);\nssize_t rdbSaveObject(rio *rdb, robj *o);\nsize_t rdbSavedObjectLen(robj *o);\nrobj *rdbLoadObject(int type, rio *rdb);\nvoid backgroundSaveDoneHandler(int exitcode, int bysignal);\nint rdbSaveKeyValuePair(rio *rdb, robj *key, robj *val, long long expiretime, long long now);\nrobj *rdbLoadStringObject(rio *rdb);\n\n#endif\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/src/redis-benchmark.c",
    "content": "/* Redis benchmark utility.\n *\n * Copyright (c) 2009-2012, Salvatore Sanfilippo <antirez at gmail dot com>\n * All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions are met:\n *\n *   * Redistributions of source code must retain the above copyright notice,\n *     this list of conditions and the following disclaimer.\n *   * Redistributions in binary form must reproduce the above copyright\n *     notice, this list of conditions and the following disclaimer in the\n *     documentation and/or other materials provided with the distribution.\n *   * Neither the name of Redis nor the names of its contributors may be used\n *     to endorse or promote products derived from this software without\n *     specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\"\n * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\n * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE\n * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR\n * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF\n * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS\n * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN\n * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)\n * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE\n * POSSIBILITY OF SUCH DAMAGE.\n */\n\n#include \"fmacros.h\"\n\n#include <stdio.h>\n#include <string.h>\n#include <stdlib.h>\n#include <unistd.h>\n#include <errno.h>\n#include <time.h>\n#include <sys/time.h>\n#include <signal.h>\n#include <assert.h>\n\n#include <sds.h> /* Use hiredis sds. */\n#include \"ae.h\"\n#include \"hiredis.h\"\n#include \"adlist.h\"\n#include \"zmalloc.h\"\n\n#define UNUSED(V) ((void) V)\n#define RANDPTR_INITIAL_SIZE 8\n\nstatic struct config {\n    aeEventLoop *el;\n    const char *hostip;\n    int hostport;\n    const char *hostsocket;\n    int numclients;\n    int liveclients;\n    int requests;\n    int requests_issued;\n    int requests_finished;\n    int keysize;\n    int datasize;\n    int randomkeys;\n    int randomkeys_keyspacelen;\n    int keepalive;\n    int pipeline;\n    int showerrors;\n    long long start;\n    long long totlatency;\n    long long *latency;\n    const char *title;\n    list *clients;\n    int quiet;\n    int csv;\n    int loop;\n    int idlemode;\n    int dbnum;\n    sds dbnumstr;\n    char *tests;\n    char *auth;\n} config;\n\ntypedef struct _client {\n    redisContext *context;\n    sds obuf;\n    char **randptr;         /* Pointers to :rand: strings inside the command buf */\n    size_t randlen;         /* Number of pointers in client->randptr */\n    size_t randfree;        /* Number of unused pointers in client->randptr */\n    size_t written;         /* Bytes of 'obuf' already written */\n    long long start;        /* Start time of a request */\n    long long latency;      /* Request latency */\n    int pending;            /* Number of pending requests (replies to consume) */\n    int prefix_pending;     /* If non-zero, number of pending prefix commands. Commands\n                               such as auth and select are prefixed to the pipeline of\n                               benchmark commands and discarded after the first send. */\n    int prefixlen;          /* Size in bytes of the pending prefix commands */\n} *client;\n\n/* Prototypes */\nstatic void writeHandler(aeEventLoop *el, int fd, void *privdata, int mask);\nstatic void createMissingClients(client c);\n\n/* Implementation */\nstatic long long ustime(void) {\n    struct timeval tv;\n    long long ust;\n\n    gettimeofday(&tv, NULL);\n    ust = ((long)tv.tv_sec)*1000000;\n    ust += tv.tv_usec;\n    return ust;\n}\n\nstatic long long mstime(void) {\n    struct timeval tv;\n    long long mst;\n\n    gettimeofday(&tv, NULL);\n    mst = ((long long)tv.tv_sec)*1000;\n    mst += tv.tv_usec/1000;\n    return mst;\n}\n\nstatic void freeClient(client c) {\n    listNode *ln;\n    aeDeleteFileEvent(config.el,c->context->fd,AE_WRITABLE);\n    aeDeleteFileEvent(config.el,c->context->fd,AE_READABLE);\n    redisFree(c->context);\n    sdsfree(c->obuf);\n    zfree(c->randptr);\n    zfree(c);\n    config.liveclients--;\n    ln = listSearchKey(config.clients,c);\n    assert(ln != NULL);\n    listDelNode(config.clients,ln);\n}\n\nstatic void freeAllClients(void) {\n    listNode *ln = config.clients->head, *next;\n\n    while(ln) {\n        next = ln->next;\n        freeClient(ln->value);\n        ln = next;\n    }\n}\n\nstatic void resetClient(client c) {\n    aeDeleteFileEvent(config.el,c->context->fd,AE_WRITABLE);\n    aeDeleteFileEvent(config.el,c->context->fd,AE_READABLE);\n    aeCreateFileEvent(config.el,c->context->fd,AE_WRITABLE,writeHandler,c);\n    c->written = 0;\n    c->pending = config.pipeline;\n}\n\nstatic void randomizeClientKey(client c) {\n    size_t i;\n\n    for (i = 0; i < c->randlen; i++) {\n        char *p = c->randptr[i]+11;\n        size_t r = random() % config.randomkeys_keyspacelen;\n        size_t j;\n\n        for (j = 0; j < 12; j++) {\n            *p = '0'+r%10;\n            r/=10;\n            p--;\n        }\n    }\n}\n\nstatic void clientDone(client c) {\n    if (config.requests_finished == config.requests) {\n        freeClient(c);\n        aeStop(config.el);\n        return;\n    }\n    if (config.keepalive) {\n        resetClient(c);\n    } else {\n        config.liveclients--;\n        createMissingClients(c);\n        config.liveclients++;\n        freeClient(c);\n    }\n}\n\nstatic void readHandler(aeEventLoop *el, int fd, void *privdata, int mask) {\n    client c = privdata;\n    void *reply = NULL;\n    UNUSED(el);\n    UNUSED(fd);\n    UNUSED(mask);\n\n    /* Calculate latency only for the first read event. This means that the\n     * server already sent the reply and we need to parse it. Parsing overhead\n     * is not part of the latency, so calculate it only once, here. */\n    if (c->latency < 0) c->latency = ustime()-(c->start);\n\n    if (redisBufferRead(c->context) != REDIS_OK) {\n        fprintf(stderr,\"Error: %s\\n\",c->context->errstr);\n        exit(1);\n    } else {\n        while(c->pending) {\n            if (redisGetReply(c->context,&reply) != REDIS_OK) {\n                fprintf(stderr,\"Error: %s\\n\",c->context->errstr);\n                exit(1);\n            }\n            if (reply != NULL) {\n                if (reply == (void*)REDIS_REPLY_ERROR) {\n                    fprintf(stderr,\"Unexpected error reply, exiting...\\n\");\n                    exit(1);\n                }\n\n                if (config.showerrors) {\n                    static time_t lasterr_time = 0;\n                    time_t now = time(NULL);\n                    redisReply *r = reply;\n                    if (r->type == REDIS_REPLY_ERROR && lasterr_time != now) {\n                        lasterr_time = now;\n                        printf(\"Error from server: %s\\n\", r->str);\n                    }\n                }\n\n                freeReplyObject(reply);\n                /* This is an OK for prefix commands such as auth and select.*/\n                if (c->prefix_pending > 0) {\n                    c->prefix_pending--;\n                    c->pending--;\n                    /* Discard prefix commands on first response.*/\n                    if (c->prefixlen > 0) {\n                        size_t j;\n                        sdsrange(c->obuf, c->prefixlen, -1);\n                        /* We also need to fix the pointers to the strings\n                        * we need to randomize. */\n                        for (j = 0; j < c->randlen; j++)\n                            c->randptr[j] -= c->prefixlen;\n                        c->prefixlen = 0;\n                    }\n                    continue;\n                }\n\n                if (config.requests_finished < config.requests)\n                    config.latency[config.requests_finished++] = c->latency;\n                c->pending--;\n                if (c->pending == 0) {\n                    clientDone(c);\n                    break;\n                }\n            } else {\n                break;\n            }\n        }\n    }\n}\n\nstatic void writeHandler(aeEventLoop *el, int fd, void *privdata, int mask) {\n    client c = privdata;\n    UNUSED(el);\n    UNUSED(fd);\n    UNUSED(mask);\n\n    /* Initialize request when nothing was written. */\n    if (c->written == 0) {\n        /* Enforce upper bound to number of requests. */\n        if (config.requests_issued++ >= config.requests) {\n            freeClient(c);\n            return;\n        }\n\n        /* Really initialize: randomize keys and set start time. */\n        if (config.randomkeys) randomizeClientKey(c);\n        c->start = ustime();\n        c->latency = -1;\n    }\n\n    if (sdslen(c->obuf) > c->written) {\n        void *ptr = c->obuf+c->written;\n        ssize_t nwritten = write(c->context->fd,ptr,sdslen(c->obuf)-c->written);\n        if (nwritten == -1) {\n            if (errno != EPIPE)\n                fprintf(stderr, \"Writing to socket: %s\\n\", strerror(errno));\n            freeClient(c);\n            return;\n        }\n        c->written += nwritten;\n        if (sdslen(c->obuf) == c->written) {\n            aeDeleteFileEvent(config.el,c->context->fd,AE_WRITABLE);\n            aeCreateFileEvent(config.el,c->context->fd,AE_READABLE,readHandler,c);\n        }\n    }\n}\n\n/* Create a benchmark client, configured to send the command passed as 'cmd' of\n * 'len' bytes.\n *\n * The command is copied N times in the client output buffer (that is reused\n * again and again to send the request to the server) accordingly to the configured\n * pipeline size.\n *\n * Also an initial SELECT command is prepended in order to make sure the right\n * database is selected, if needed. The initial SELECT will be discarded as soon\n * as the first reply is received.\n *\n * To create a client from scratch, the 'from' pointer is set to NULL. If instead\n * we want to create a client using another client as reference, the 'from' pointer\n * points to the client to use as reference. In such a case the following\n * information is take from the 'from' client:\n *\n * 1) The command line to use.\n * 2) The offsets of the __rand_int__ elements inside the command line, used\n *    for arguments randomization.\n *\n * Even when cloning another client, prefix commands are applied if needed.*/\nstatic client createClient(char *cmd, size_t len, client from) {\n    int j;\n    client c = zmalloc(sizeof(struct _client));\n\n    if (config.hostsocket == NULL) {\n        c->context = redisConnectNonBlock(config.hostip,config.hostport);\n    } else {\n        c->context = redisConnectUnixNonBlock(config.hostsocket);\n    }\n    if (c->context->err) {\n        fprintf(stderr,\"Could not connect to Redis at \");\n        if (config.hostsocket == NULL)\n            fprintf(stderr,\"%s:%d: %s\\n\",config.hostip,config.hostport,c->context->errstr);\n        else\n            fprintf(stderr,\"%s: %s\\n\",config.hostsocket,c->context->errstr);\n        exit(1);\n    }\n    /* Suppress hiredis cleanup of unused buffers for max speed. */\n    c->context->reader->maxbuf = 0;\n\n    /* Build the request buffer:\n     * Queue N requests accordingly to the pipeline size, or simply clone\n     * the example client buffer. */\n    c->obuf = sdsempty();\n    /* Prefix the request buffer with AUTH and/or SELECT commands, if applicable.\n     * These commands are discarded after the first response, so if the client is\n     * reused the commands will not be used again. */\n    c->prefix_pending = 0;\n    if (config.auth) {\n        char *buf = NULL;\n        int len = redisFormatCommand(&buf, \"AUTH %s\", config.auth);\n        c->obuf = sdscatlen(c->obuf, buf, len);\n        free(buf);\n        c->prefix_pending++;\n    }\n\n    /* If a DB number different than zero is selected, prefix our request\n     * buffer with the SELECT command, that will be discarded the first\n     * time the replies are received, so if the client is reused the\n     * SELECT command will not be used again. */\n    if (config.dbnum != 0) {\n        c->obuf = sdscatprintf(c->obuf,\"*2\\r\\n$6\\r\\nSELECT\\r\\n$%d\\r\\n%s\\r\\n\",\n            (int)sdslen(config.dbnumstr),config.dbnumstr);\n        c->prefix_pending++;\n    }\n    c->prefixlen = sdslen(c->obuf);\n    /* Append the request itself. */\n    if (from) {\n        c->obuf = sdscatlen(c->obuf,\n            from->obuf+from->prefixlen,\n            sdslen(from->obuf)-from->prefixlen);\n    } else {\n        for (j = 0; j < config.pipeline; j++)\n            c->obuf = sdscatlen(c->obuf,cmd,len);\n    }\n\n    c->written = 0;\n    c->pending = config.pipeline+c->prefix_pending;\n    c->randptr = NULL;\n    c->randlen = 0;\n\n    /* Find substrings in the output buffer that need to be randomized. */\n    if (config.randomkeys) {\n        if (from) {\n            c->randlen = from->randlen;\n            c->randfree = 0;\n            c->randptr = zmalloc(sizeof(char*)*c->randlen);\n            /* copy the offsets. */\n            for (j = 0; j < (int)c->randlen; j++) {\n                c->randptr[j] = c->obuf + (from->randptr[j]-from->obuf);\n                /* Adjust for the different select prefix length. */\n                c->randptr[j] += c->prefixlen - from->prefixlen;\n            }\n        } else {\n            char *p = c->obuf;\n\n            c->randlen = 0;\n            c->randfree = RANDPTR_INITIAL_SIZE;\n            c->randptr = zmalloc(sizeof(char*)*c->randfree);\n            while ((p = strstr(p,\"__rand_int__\")) != NULL) {\n                if (c->randfree == 0) {\n                    c->randptr = zrealloc(c->randptr,sizeof(char*)*c->randlen*2);\n                    c->randfree += c->randlen;\n                }\n                c->randptr[c->randlen++] = p;\n                c->randfree--;\n                p += 12; /* 12 is strlen(\"__rand_int__). */\n            }\n        }\n    }\n    if (config.idlemode == 0)\n        aeCreateFileEvent(config.el,c->context->fd,AE_WRITABLE,writeHandler,c);\n    listAddNodeTail(config.clients,c);\n    config.liveclients++;\n    return c;\n}\n\nstatic void createMissingClients(client c) {\n    int n = 0;\n\n    while(config.liveclients < config.numclients) {\n        createClient(NULL,0,c);\n\n        /* Listen backlog is quite limited on most systems */\n        if (++n > 64) {\n            usleep(50000);\n            n = 0;\n        }\n    }\n}\n\nstatic int compareLatency(const void *a, const void *b) {\n    return (*(long long*)a)-(*(long long*)b);\n}\n\nstatic void showLatencyReport(void) {\n    int i, curlat = 0;\n    float perc, reqpersec;\n\n    reqpersec = (float)config.requests_finished/((float)config.totlatency/1000);\n    if (!config.quiet && !config.csv) {\n        printf(\"====== %s ======\\n\", config.title);\n        printf(\"  %d requests completed in %.2f seconds\\n\", config.requests_finished,\n            (float)config.totlatency/1000);\n        printf(\"  %d parallel clients\\n\", config.numclients);\n        printf(\"  %d bytes payload\\n\", config.datasize);\n        printf(\"  keep alive: %d\\n\", config.keepalive);\n        printf(\"\\n\");\n\n        qsort(config.latency,config.requests,sizeof(long long),compareLatency);\n        for (i = 0; i < config.requests; i++) {\n            if (config.latency[i]/1000 != curlat || i == (config.requests-1)) {\n                curlat = config.latency[i]/1000;\n                perc = ((float)(i+1)*100)/config.requests;\n                printf(\"%.2f%% <= %d milliseconds\\n\", perc, curlat);\n            }\n        }\n        printf(\"%.2f requests per second\\n\\n\", reqpersec);\n    } else if (config.csv) {\n        printf(\"\\\"%s\\\",\\\"%.2f\\\"\\n\", config.title, reqpersec);\n    } else {\n        printf(\"%s: %.2f requests per second\\n\", config.title, reqpersec);\n    }\n}\n\nstatic void benchmark(char *title, char *cmd, int len) {\n    client c;\n\n    config.title = title;\n    config.requests_issued = 0;\n    config.requests_finished = 0;\n\n    c = createClient(cmd,len,NULL);\n    createMissingClients(c);\n\n    config.start = mstime();\n    aeMain(config.el);\n    config.totlatency = mstime()-config.start;\n\n    showLatencyReport();\n    freeAllClients();\n}\n\n/* Returns number of consumed options. */\nint parseOptions(int argc, const char **argv) {\n    int i;\n    int lastarg;\n    int exit_status = 1;\n\n    for (i = 1; i < argc; i++) {\n        lastarg = (i == (argc-1));\n\n        if (!strcmp(argv[i],\"-c\")) {\n            if (lastarg) goto invalid;\n            config.numclients = atoi(argv[++i]);\n        } else if (!strcmp(argv[i],\"-n\")) {\n            if (lastarg) goto invalid;\n            config.requests = atoi(argv[++i]);\n        } else if (!strcmp(argv[i],\"-k\")) {\n            if (lastarg) goto invalid;\n            config.keepalive = atoi(argv[++i]);\n        } else if (!strcmp(argv[i],\"-h\")) {\n            if (lastarg) goto invalid;\n            config.hostip = strdup(argv[++i]);\n        } else if (!strcmp(argv[i],\"-p\")) {\n            if (lastarg) goto invalid;\n            config.hostport = atoi(argv[++i]);\n        } else if (!strcmp(argv[i],\"-s\")) {\n            if (lastarg) goto invalid;\n            config.hostsocket = strdup(argv[++i]);\n        } else if (!strcmp(argv[i],\"-a\") ) {\n            if (lastarg) goto invalid;\n            config.auth = strdup(argv[++i]);\n        } else if (!strcmp(argv[i],\"-d\")) {\n            if (lastarg) goto invalid;\n            config.datasize = atoi(argv[++i]);\n            if (config.datasize < 1) config.datasize=1;\n            if (config.datasize > 1024*1024*1024) config.datasize = 1024*1024*1024;\n        } else if (!strcmp(argv[i],\"-P\")) {\n            if (lastarg) goto invalid;\n            config.pipeline = atoi(argv[++i]);\n            if (config.pipeline <= 0) config.pipeline=1;\n        } else if (!strcmp(argv[i],\"-r\")) {\n            if (lastarg) goto invalid;\n            config.randomkeys = 1;\n            config.randomkeys_keyspacelen = atoi(argv[++i]);\n            if (config.randomkeys_keyspacelen < 0)\n                config.randomkeys_keyspacelen = 0;\n        } else if (!strcmp(argv[i],\"-q\")) {\n            config.quiet = 1;\n        } else if (!strcmp(argv[i],\"--csv\")) {\n            config.csv = 1;\n        } else if (!strcmp(argv[i],\"-l\")) {\n            config.loop = 1;\n        } else if (!strcmp(argv[i],\"-I\")) {\n            config.idlemode = 1;\n        } else if (!strcmp(argv[i],\"-e\")) {\n            config.showerrors = 1;\n        } else if (!strcmp(argv[i],\"-t\")) {\n            if (lastarg) goto invalid;\n            /* We get the list of tests to run as a string in the form\n             * get,set,lrange,...,test_N. Then we add a comma before and\n             * after the string in order to make sure that searching\n             * for \",testname,\" will always get a match if the test is\n             * enabled. */\n            config.tests = sdsnew(\",\");\n            config.tests = sdscat(config.tests,(char*)argv[++i]);\n            config.tests = sdscat(config.tests,\",\");\n            sdstolower(config.tests);\n        } else if (!strcmp(argv[i],\"--dbnum\")) {\n            if (lastarg) goto invalid;\n            config.dbnum = atoi(argv[++i]);\n            config.dbnumstr = sdsfromlonglong(config.dbnum);\n        } else if (!strcmp(argv[i],\"--help\")) {\n            exit_status = 0;\n            goto usage;\n        } else {\n            /* Assume the user meant to provide an option when the arg starts\n             * with a dash. We're done otherwise and should use the remainder\n             * as the command and arguments for running the benchmark. */\n            if (argv[i][0] == '-') goto invalid;\n            return i;\n        }\n    }\n\n    return i;\n\ninvalid:\n    printf(\"Invalid option \\\"%s\\\" or option argument missing\\n\\n\",argv[i]);\n\nusage:\n    printf(\n\"Usage: redis-benchmark [-h <host>] [-p <port>] [-c <clients>] [-n <requests]> [-k <boolean>]\\n\\n\"\n\" -h <hostname>      Server hostname (default 127.0.0.1)\\n\"\n\" -p <port>          Server port (default 6379)\\n\"\n\" -s <socket>        Server socket (overrides host and port)\\n\"\n\" -a <password>      Password for Redis Auth\\n\"\n\" -c <clients>       Number of parallel connections (default 50)\\n\"\n\" -n <requests>      Total number of requests (default 100000)\\n\"\n\" -d <size>          Data size of SET/GET value in bytes (default 2)\\n\"\n\" -dbnum <db>        SELECT the specified db number (default 0)\\n\"\n\" -k <boolean>       1=keep alive 0=reconnect (default 1)\\n\"\n\" -r <keyspacelen>   Use random keys for SET/GET/INCR, random values for SADD\\n\"\n\"  Using this option the benchmark will expand the string __rand_int__\\n\"\n\"  inside an argument with a 12 digits number in the specified range\\n\"\n\"  from 0 to keyspacelen-1. The substitution changes every time a command\\n\"\n\"  is executed. Default tests use this to hit random keys in the\\n\"\n\"  specified range.\\n\"\n\" -P <numreq>        Pipeline <numreq> requests. Default 1 (no pipeline).\\n\"\n\" -e                 If server replies with errors, show them on stdout.\\n\"\n\"                    (no more than 1 error per second is displayed)\\n\"\n\" -q                 Quiet. Just show query/sec values\\n\"\n\" --csv              Output in CSV format\\n\"\n\" -l                 Loop. Run the tests forever\\n\"\n\" -t <tests>         Only run the comma separated list of tests. The test\\n\"\n\"                    names are the same as the ones produced as output.\\n\"\n\" -I                 Idle mode. Just open N idle connections and wait.\\n\\n\"\n\"Examples:\\n\\n\"\n\" Run the benchmark with the default configuration against 127.0.0.1:6379:\\n\"\n\"   $ redis-benchmark\\n\\n\"\n\" Use 20 parallel clients, for a total of 100k requests, against 192.168.1.1:\\n\"\n\"   $ redis-benchmark -h 192.168.1.1 -p 6379 -n 100000 -c 20\\n\\n\"\n\" Fill 127.0.0.1:6379 with about 1 million keys only using the SET test:\\n\"\n\"   $ redis-benchmark -t set -n 1000000 -r 100000000\\n\\n\"\n\" Benchmark 127.0.0.1:6379 for a few commands producing CSV output:\\n\"\n\"   $ redis-benchmark -t ping,set,get -n 100000 --csv\\n\\n\"\n\" Benchmark a specific command line:\\n\"\n\"   $ redis-benchmark -r 10000 -n 10000 eval 'return redis.call(\\\"ping\\\")' 0\\n\\n\"\n\" Fill a list with 10000 random elements:\\n\"\n\"   $ redis-benchmark -r 10000 -n 10000 lpush mylist __rand_int__\\n\\n\"\n\" On user specified command lines __rand_int__ is replaced with a random integer\\n\"\n\" with a range of values selected by the -r option.\\n\"\n    );\n    exit(exit_status);\n}\n\nint showThroughput(struct aeEventLoop *eventLoop, long long id, void *clientData) {\n    UNUSED(eventLoop);\n    UNUSED(id);\n    UNUSED(clientData);\n\n    if (config.liveclients == 0) {\n        fprintf(stderr,\"All clients disconnected... aborting.\\n\");\n        exit(1);\n    }\n    if (config.csv) return 250;\n    if (config.idlemode == 1) {\n        printf(\"clients: %d\\r\", config.liveclients);\n        fflush(stdout);\n\treturn 250;\n    }\n    float dt = (float)(mstime()-config.start)/1000.0;\n    float rps = (float)config.requests_finished/dt;\n    printf(\"%s: %.2f\\r\", config.title, rps);\n    fflush(stdout);\n    return 250; /* every 250ms */\n}\n\n/* Return true if the named test was selected using the -t command line\n * switch, or if all the tests are selected (no -t passed by user). */\nint test_is_selected(char *name) {\n    char buf[256];\n    int l = strlen(name);\n\n    if (config.tests == NULL) return 1;\n    buf[0] = ',';\n    memcpy(buf+1,name,l);\n    buf[l+1] = ',';\n    buf[l+2] = '\\0';\n    return strstr(config.tests,buf) != NULL;\n}\n\nint main(int argc, const char **argv) {\n    int i;\n    char *data, *cmd;\n    int len;\n\n    client c;\n\n    srandom(time(NULL));\n    signal(SIGHUP, SIG_IGN);\n    signal(SIGPIPE, SIG_IGN);\n\n    config.numclients = 50;\n    config.requests = 100000;\n    config.liveclients = 0;\n    config.el = aeCreateEventLoop(1024*10);\n    aeCreateTimeEvent(config.el,1,showThroughput,NULL,NULL);\n    config.keepalive = 1;\n    config.datasize = 3;\n    config.pipeline = 1;\n    config.showerrors = 0;\n    config.randomkeys = 0;\n    config.randomkeys_keyspacelen = 0;\n    config.quiet = 0;\n    config.csv = 0;\n    config.loop = 0;\n    config.idlemode = 0;\n    config.latency = NULL;\n    config.clients = listCreate();\n    config.hostip = \"127.0.0.1\";\n    config.hostport = 6379;\n    config.hostsocket = NULL;\n    config.tests = NULL;\n    config.dbnum = 0;\n    config.auth = NULL;\n\n    i = parseOptions(argc,argv);\n    argc -= i;\n    argv += i;\n\n    config.latency = zmalloc(sizeof(long long)*config.requests);\n\n    if (config.keepalive == 0) {\n        printf(\"WARNING: keepalive disabled, you probably need 'echo 1 > /proc/sys/net/ipv4/tcp_tw_reuse' for Linux and 'sudo sysctl -w net.inet.tcp.msl=1000' for Mac OS X in order to use a lot of clients/requests\\n\");\n    }\n\n    if (config.idlemode) {\n        printf(\"Creating %d idle connections and waiting forever (Ctrl+C when done)\\n\", config.numclients);\n        c = createClient(\"\",0,NULL); /* will never receive a reply */\n        createMissingClients(c);\n        aeMain(config.el);\n        /* and will wait for every */\n    }\n\n    /* Run benchmark with command in the remainder of the arguments. */\n    if (argc) {\n        sds title = sdsnew(argv[0]);\n        for (i = 1; i < argc; i++) {\n            title = sdscatlen(title, \" \", 1);\n            title = sdscatlen(title, (char*)argv[i], strlen(argv[i]));\n        }\n\n        do {\n            len = redisFormatCommandArgv(&cmd,argc,argv,NULL);\n            benchmark(title,cmd,len);\n            free(cmd);\n        } while(config.loop);\n\n        return 0;\n    }\n\n    /* Run default benchmark suite. */\n    data = zmalloc(config.datasize+1);\n    do {\n        memset(data,'x',config.datasize);\n        data[config.datasize] = '\\0';\n\n        if (test_is_selected(\"ping_inline\") || test_is_selected(\"ping\"))\n            benchmark(\"PING_INLINE\",\"PING\\r\\n\",6);\n\n        if (test_is_selected(\"ping_mbulk\") || test_is_selected(\"ping\")) {\n            len = redisFormatCommand(&cmd,\"PING\");\n            benchmark(\"PING_BULK\",cmd,len);\n            free(cmd);\n        }\n\n        if (test_is_selected(\"set\")) {\n            len = redisFormatCommand(&cmd,\"SET key:__rand_int__ %s\",data);\n            benchmark(\"SET\",cmd,len);\n            free(cmd);\n        }\n\n        if (test_is_selected(\"get\")) {\n            len = redisFormatCommand(&cmd,\"GET key:__rand_int__\");\n            benchmark(\"GET\",cmd,len);\n            free(cmd);\n        }\n\n        if (test_is_selected(\"incr\")) {\n            len = redisFormatCommand(&cmd,\"INCR counter:__rand_int__\");\n            benchmark(\"INCR\",cmd,len);\n            free(cmd);\n        }\n\n        if (test_is_selected(\"lpush\")) {\n            len = redisFormatCommand(&cmd,\"LPUSH mylist %s\",data);\n            benchmark(\"LPUSH\",cmd,len);\n            free(cmd);\n        }\n\n        if (test_is_selected(\"rpush\")) {\n            len = redisFormatCommand(&cmd,\"RPUSH mylist %s\",data);\n            benchmark(\"RPUSH\",cmd,len);\n            free(cmd);\n        }\n\n        if (test_is_selected(\"lpop\")) {\n            len = redisFormatCommand(&cmd,\"LPOP mylist\");\n            benchmark(\"LPOP\",cmd,len);\n            free(cmd);\n        }\n\n        if (test_is_selected(\"rpop\")) {\n            len = redisFormatCommand(&cmd,\"RPOP mylist\");\n            benchmark(\"RPOP\",cmd,len);\n            free(cmd);\n        }\n\n        if (test_is_selected(\"sadd\")) {\n            len = redisFormatCommand(&cmd,\n                \"SADD myset element:__rand_int__\");\n            benchmark(\"SADD\",cmd,len);\n            free(cmd);\n        }\n\n        if (test_is_selected(\"spop\")) {\n            len = redisFormatCommand(&cmd,\"SPOP myset\");\n            benchmark(\"SPOP\",cmd,len);\n            free(cmd);\n        }\n\n        if (test_is_selected(\"lrange\") ||\n            test_is_selected(\"lrange_100\") ||\n            test_is_selected(\"lrange_300\") ||\n            test_is_selected(\"lrange_500\") ||\n            test_is_selected(\"lrange_600\"))\n        {\n            len = redisFormatCommand(&cmd,\"LPUSH mylist %s\",data);\n            benchmark(\"LPUSH (needed to benchmark LRANGE)\",cmd,len);\n            free(cmd);\n        }\n\n        if (test_is_selected(\"lrange\") || test_is_selected(\"lrange_100\")) {\n            len = redisFormatCommand(&cmd,\"LRANGE mylist 0 99\");\n            benchmark(\"LRANGE_100 (first 100 elements)\",cmd,len);\n            free(cmd);\n        }\n\n        if (test_is_selected(\"lrange\") || test_is_selected(\"lrange_300\")) {\n            len = redisFormatCommand(&cmd,\"LRANGE mylist 0 299\");\n            benchmark(\"LRANGE_300 (first 300 elements)\",cmd,len);\n            free(cmd);\n        }\n\n        if (test_is_selected(\"lrange\") || test_is_selected(\"lrange_500\")) {\n            len = redisFormatCommand(&cmd,\"LRANGE mylist 0 449\");\n            benchmark(\"LRANGE_500 (first 450 elements)\",cmd,len);\n            free(cmd);\n        }\n\n        if (test_is_selected(\"lrange\") || test_is_selected(\"lrange_600\")) {\n            len = redisFormatCommand(&cmd,\"LRANGE mylist 0 599\");\n            benchmark(\"LRANGE_600 (first 600 elements)\",cmd,len);\n            free(cmd);\n        }\n\n        if (test_is_selected(\"mset\")) {\n            const char *argv[21];\n            argv[0] = \"MSET\";\n            for (i = 1; i < 21; i += 2) {\n                argv[i] = \"key:__rand_int__\";\n                argv[i+1] = data;\n            }\n            len = redisFormatCommandArgv(&cmd,21,argv,NULL);\n            benchmark(\"MSET (10 keys)\",cmd,len);\n            free(cmd);\n        }\n\n        if (!config.csv) printf(\"\\n\");\n    } while(config.loop);\n\n    return 0;\n}\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/src/redis-check-aof.c",
    "content": "/*\n * Copyright (c) 2009-2012, Pieter Noordhuis <pcnoordhuis at gmail dot com>\n * Copyright (c) 2009-2012, Salvatore Sanfilippo <antirez at gmail dot com>\n * All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions are met:\n *\n *   * Redistributions of source code must retain the above copyright notice,\n *     this list of conditions and the following disclaimer.\n *   * Redistributions in binary form must reproduce the above copyright\n *     notice, this list of conditions and the following disclaimer in the\n *     documentation and/or other materials provided with the distribution.\n *   * Neither the name of Redis nor the names of its contributors may be used\n *     to endorse or promote products derived from this software without\n *     specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\"\n * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\n * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE\n * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR\n * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF\n * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS\n * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN\n * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)\n * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE\n * POSSIBILITY OF SUCH DAMAGE.\n */\n\n#include \"fmacros.h\"\n#include <stdlib.h>\n#include <stdio.h>\n#include <string.h>\n#include <unistd.h>\n#include <sys/stat.h>\n#include \"config.h\"\n\n#define ERROR(...) { \\\n    char __buf[1024]; \\\n    sprintf(__buf, __VA_ARGS__); \\\n    sprintf(error, \"0x%16llx: %s\", (long long)epos, __buf); \\\n}\n\nstatic char error[1024];\nstatic off_t epos;\n\nint consumeNewline(char *buf) {\n    if (strncmp(buf,\"\\r\\n\",2) != 0) {\n        ERROR(\"Expected \\\\r\\\\n, got: %02x%02x\",buf[0],buf[1]);\n        return 0;\n    }\n    return 1;\n}\n\nint readLong(FILE *fp, char prefix, long *target) {\n    char buf[128], *eptr;\n    epos = ftello(fp);\n    if (fgets(buf,sizeof(buf),fp) == NULL) {\n        return 0;\n    }\n    if (buf[0] != prefix) {\n        ERROR(\"Expected prefix '%c', got: '%c'\",buf[0],prefix);\n        return 0;\n    }\n    *target = strtol(buf+1,&eptr,10);\n    return consumeNewline(eptr);\n}\n\nint readBytes(FILE *fp, char *target, long length) {\n    long real;\n    epos = ftello(fp);\n    real = fread(target,1,length,fp);\n    if (real != length) {\n        ERROR(\"Expected to read %ld bytes, got %ld bytes\",length,real);\n        return 0;\n    }\n    return 1;\n}\n\nint readString(FILE *fp, char** target) {\n    long len;\n    *target = NULL;\n    if (!readLong(fp,'$',&len)) {\n        return 0;\n    }\n\n    /* Increase length to also consume \\r\\n */\n    len += 2;\n    *target = (char*)malloc(len);\n    if (!readBytes(fp,*target,len)) {\n        return 0;\n    }\n    if (!consumeNewline(*target+len-2)) {\n        return 0;\n    }\n    (*target)[len-2] = '\\0';\n    return 1;\n}\n\nint readArgc(FILE *fp, long *target) {\n    return readLong(fp,'*',target);\n}\n\noff_t process(FILE *fp) {\n    long argc;\n    off_t pos = 0;\n    int i, multi = 0;\n    char *str;\n\n    while(1) {\n        if (!multi) pos = ftello(fp);\n        if (!readArgc(fp, &argc)) break;\n\n        for (i = 0; i < argc; i++) {\n            if (!readString(fp,&str)) break;\n            if (i == 0) {\n                if (strcasecmp(str, \"multi\") == 0) {\n                    if (multi++) {\n                        ERROR(\"Unexpected MULTI\");\n                        break;\n                    }\n                } else if (strcasecmp(str, \"exec\") == 0) {\n                    if (--multi) {\n                        ERROR(\"Unexpected EXEC\");\n                        break;\n                    }\n                }\n            }\n            free(str);\n        }\n\n        /* Stop if the loop did not finish */\n        if (i < argc) {\n            if (str) free(str);\n            break;\n        }\n    }\n\n    if (feof(fp) && multi && strlen(error) == 0) {\n        ERROR(\"Reached EOF before reading EXEC for MULTI\");\n    }\n    if (strlen(error) > 0) {\n        printf(\"%s\\n\", error);\n    }\n    return pos;\n}\n\nint main(int argc, char **argv) {\n    char *filename;\n    int fix = 0;\n\n    if (argc < 2) {\n        printf(\"Usage: %s [--fix] <file.aof>\\n\", argv[0]);\n        exit(1);\n    } else if (argc == 2) {\n        filename = argv[1];\n    } else if (argc == 3) {\n        if (strcmp(argv[1],\"--fix\") != 0) {\n            printf(\"Invalid argument: %s\\n\", argv[1]);\n            exit(1);\n        }\n        filename = argv[2];\n        fix = 1;\n    } else {\n        printf(\"Invalid arguments\\n\");\n        exit(1);\n    }\n\n    FILE *fp = fopen(filename,\"r+\");\n    if (fp == NULL) {\n        printf(\"Cannot open file: %s\\n\", filename);\n        exit(1);\n    }\n\n    struct redis_stat sb;\n    if (redis_fstat(fileno(fp),&sb) == -1) {\n        printf(\"Cannot stat file: %s\\n\", filename);\n        exit(1);\n    }\n\n    off_t size = sb.st_size;\n    if (size == 0) {\n        printf(\"Empty file: %s\\n\", filename);\n        exit(1);\n    }\n\n    off_t pos = process(fp);\n    off_t diff = size-pos;\n    printf(\"AOF analyzed: size=%lld, ok_up_to=%lld, diff=%lld\\n\",\n        (long long) size, (long long) pos, (long long) diff);\n    if (diff > 0) {\n        if (fix) {\n            char buf[2];\n            printf(\"This will shrink the AOF from %lld bytes, with %lld bytes, to %lld bytes\\n\",(long long)size,(long long)diff,(long long)pos);\n            printf(\"Continue? [y/N]: \");\n            if (fgets(buf,sizeof(buf),stdin) == NULL ||\n                strncasecmp(buf,\"y\",1) != 0) {\n                    printf(\"Aborting...\\n\");\n                    exit(1);\n            }\n            if (ftruncate(fileno(fp), pos) == -1) {\n                printf(\"Failed to truncate AOF\\n\");\n                exit(1);\n            } else {\n                printf(\"Successfully truncated AOF\\n\");\n            }\n        } else {\n            printf(\"AOF is not valid\\n\");\n            exit(1);\n        }\n    } else {\n        printf(\"AOF is valid\\n\");\n    }\n\n    fclose(fp);\n    return 0;\n}\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/src/redis-check-rdb.c",
    "content": "/*\n * Copyright (c) 2016, Salvatore Sanfilippo <antirez at gmail dot com>\n * All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions are met:\n *\n *   * Redistributions of source code must retain the above copyright notice,\n *     this list of conditions and the following disclaimer.\n *   * Redistributions in binary form must reproduce the above copyright\n *     notice, this list of conditions and the following disclaimer in the\n *     documentation and/or other materials provided with the distribution.\n *   * Neither the name of Redis nor the names of its contributors may be used\n *     to endorse or promote products derived from this software without\n *     specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\"\n * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\n * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE\n * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR\n * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF\n * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS\n * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN\n * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)\n * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE\n * POSSIBILITY OF SUCH DAMAGE.\n */\n\n#include \"server.h\"\n#include \"rdb.h\"\n\n#include <stdarg.h>\n\nvoid createSharedObjects(void);\nvoid rdbLoadProgressCallback(rio *r, const void *buf, size_t len);\nlong long rdbLoadMillisecondTime(rio *rdb);\nint rdbCheckMode = 0;\n\nstruct {\n    rio *rio;\n    robj *key;                      /* Current key we are reading. */\n    int key_type;                   /* Current key type if != -1. */\n    unsigned long keys;             /* Number of keys processed. */\n    unsigned long expires;          /* Number of keys with an expire. */\n    unsigned long already_expired;  /* Number of keys already expired. */\n    int doing;                      /* The state while reading the RDB. */\n    int error_set;                  /* True if error is populated. */\n    char error[1024];\n} rdbstate;\n\n/* At every loading step try to remember what we were about to do, so that\n * we can log this information when an error is encountered. */\n#define RDB_CHECK_DOING_START 0\n#define RDB_CHECK_DOING_READ_TYPE 1\n#define RDB_CHECK_DOING_READ_EXPIRE 2\n#define RDB_CHECK_DOING_READ_KEY 3\n#define RDB_CHECK_DOING_READ_OBJECT_VALUE 4\n#define RDB_CHECK_DOING_CHECK_SUM 5\n#define RDB_CHECK_DOING_READ_LEN 6\n#define RDB_CHECK_DOING_READ_AUX 7\n\nchar *rdb_check_doing_string[] = {\n    \"start\",\n    \"read-type\",\n    \"read-expire\",\n    \"read-key\",\n    \"read-object-value\",\n    \"check-sum\",\n    \"read-len\",\n    \"read-aux\"\n};\n\nchar *rdb_type_string[] = {\n    \"string\",\n    \"list-linked\",\n    \"set-hashtable\",\n    \"zset-v1\",\n    \"hash-hashtable\",\n    \"zset-v2\",\n    \"module-value\",\n    \"\",\"\",\n    \"hash-zipmap\",\n    \"list-ziplist\",\n    \"set-intset\",\n    \"zset-ziplist\",\n    \"hash-ziplist\",\n    \"quicklist\"\n};\n\n/* Show a few stats collected into 'rdbstate' */\nvoid rdbShowGenericInfo(void) {\n    printf(\"[info] %lu keys read\\n\", rdbstate.keys);\n    printf(\"[info] %lu expires\\n\", rdbstate.expires);\n    printf(\"[info] %lu already expired\\n\", rdbstate.already_expired);\n}\n\n/* Called on RDB errors. Provides details about the RDB and the offset\n * we were when the error was detected. */\nvoid rdbCheckError(const char *fmt, ...) {\n    char msg[1024];\n    va_list ap;\n\n    va_start(ap, fmt);\n    vsnprintf(msg, sizeof(msg), fmt, ap);\n    va_end(ap);\n\n    printf(\"--- RDB ERROR DETECTED ---\\n\");\n    printf(\"[offset %llu] %s\\n\",\n        (unsigned long long) (rdbstate.rio ?\n            rdbstate.rio->processed_bytes : 0), msg);\n    printf(\"[additional info] While doing: %s\\n\",\n        rdb_check_doing_string[rdbstate.doing]);\n    if (rdbstate.key)\n        printf(\"[additional info] Reading key '%s'\\n\",\n            (char*)rdbstate.key->ptr);\n    if (rdbstate.key_type != -1)\n        printf(\"[additional info] Reading type %d (%s)\\n\",\n            rdbstate.key_type,\n            ((unsigned)rdbstate.key_type <\n             sizeof(rdb_type_string)/sizeof(char*)) ?\n                rdb_type_string[rdbstate.key_type] : \"unknown\");\n    rdbShowGenericInfo();\n}\n\n/* Print informations during RDB checking. */\nvoid rdbCheckInfo(const char *fmt, ...) {\n    char msg[1024];\n    va_list ap;\n\n    va_start(ap, fmt);\n    vsnprintf(msg, sizeof(msg), fmt, ap);\n    va_end(ap);\n\n    printf(\"[offset %llu] %s\\n\",\n        (unsigned long long) (rdbstate.rio ?\n            rdbstate.rio->processed_bytes : 0), msg);\n}\n\n/* Used inside rdb.c in order to log specific errors happening inside\n * the RDB loading internals. */\nvoid rdbCheckSetError(const char *fmt, ...) {\n    va_list ap;\n\n    va_start(ap, fmt);\n    vsnprintf(rdbstate.error, sizeof(rdbstate.error), fmt, ap);\n    va_end(ap);\n    rdbstate.error_set = 1;\n}\n\n/* During RDB check we setup a special signal handler for memory violations\n * and similar conditions, so that we can log the offending part of the RDB\n * if the crash is due to broken content. */\nvoid rdbCheckHandleCrash(int sig, siginfo_t *info, void *secret) {\n    UNUSED(sig);\n    UNUSED(info);\n    UNUSED(secret);\n\n    rdbCheckError(\"Server crash checking the specified RDB file!\");\n    exit(1);\n}\n\nvoid rdbCheckSetupSignals(void) {\n    struct sigaction act;\n\n    sigemptyset(&act.sa_mask);\n    act.sa_flags = SA_NODEFER | SA_RESETHAND | SA_SIGINFO;\n    act.sa_sigaction = rdbCheckHandleCrash;\n    sigaction(SIGSEGV, &act, NULL);\n    sigaction(SIGBUS, &act, NULL);\n    sigaction(SIGFPE, &act, NULL);\n    sigaction(SIGILL, &act, NULL);\n}\n\n/* Check the specified RDB file. */\nint redis_check_rdb(char *rdbfilename) {\n    uint64_t dbid;\n    int type, rdbver;\n    char buf[1024];\n    long long expiretime, now = mstime();\n    FILE *fp;\n    rio rdb;\n\n    if ((fp = fopen(rdbfilename,\"r\")) == NULL) return C_ERR;\n\n    rioInitWithFile(&rdb,fp);\n    rdbstate.rio = &rdb;\n    rdb.update_cksum = rdbLoadProgressCallback;\n    if (rioRead(&rdb,buf,9) == 0) goto eoferr;\n    buf[9] = '\\0';\n    if (memcmp(buf,\"REDIS\",5) != 0) {\n        rdbCheckError(\"Wrong signature trying to load DB from file\");\n        return 1;\n    }\n    rdbver = atoi(buf+5);\n    if (rdbver < 1 || rdbver > RDB_VERSION) {\n        rdbCheckError(\"Can't handle RDB format version %d\",rdbver);\n        return 1;\n    }\n\n    startLoading(fp);\n    while(1) {\n        robj *key, *val;\n        expiretime = -1;\n\n        /* Read type. */\n        rdbstate.doing = RDB_CHECK_DOING_READ_TYPE;\n        if ((type = rdbLoadType(&rdb)) == -1) goto eoferr;\n\n        /* Handle special types. */\n        if (type == RDB_OPCODE_EXPIRETIME) {\n            rdbstate.doing = RDB_CHECK_DOING_READ_EXPIRE;\n            /* EXPIRETIME: load an expire associated with the next key\n             * to load. Note that after loading an expire we need to\n             * load the actual type, and continue. */\n            if ((expiretime = rdbLoadTime(&rdb)) == -1) goto eoferr;\n            /* We read the time so we need to read the object type again. */\n            rdbstate.doing = RDB_CHECK_DOING_READ_TYPE;\n            if ((type = rdbLoadType(&rdb)) == -1) goto eoferr;\n            /* the EXPIRETIME opcode specifies time in seconds, so convert\n             * into milliseconds. */\n            expiretime *= 1000;\n        } else if (type == RDB_OPCODE_EXPIRETIME_MS) {\n            /* EXPIRETIME_MS: milliseconds precision expire times introduced\n             * with RDB v3. Like EXPIRETIME but no with more precision. */\n            rdbstate.doing = RDB_CHECK_DOING_READ_EXPIRE;\n            if ((expiretime = rdbLoadMillisecondTime(&rdb)) == -1) goto eoferr;\n            /* We read the time so we need to read the object type again. */\n            rdbstate.doing = RDB_CHECK_DOING_READ_TYPE;\n            if ((type = rdbLoadType(&rdb)) == -1) goto eoferr;\n        } else if (type == RDB_OPCODE_EOF) {\n            /* EOF: End of file, exit the main loop. */\n            break;\n        } else if (type == RDB_OPCODE_SELECTDB) {\n            /* SELECTDB: Select the specified database. */\n            rdbstate.doing = RDB_CHECK_DOING_READ_LEN;\n            if ((dbid = rdbLoadLen(&rdb,NULL)) == RDB_LENERR)\n                goto eoferr;\n            rdbCheckInfo(\"Selecting DB ID %d\", dbid);\n            continue; /* Read type again. */\n        } else if (type == RDB_OPCODE_RESIZEDB) {\n            /* RESIZEDB: Hint about the size of the keys in the currently\n             * selected data base, in order to avoid useless rehashing. */\n            uint64_t db_size, expires_size;\n            rdbstate.doing = RDB_CHECK_DOING_READ_LEN;\n            if ((db_size = rdbLoadLen(&rdb,NULL)) == RDB_LENERR)\n                goto eoferr;\n            if ((expires_size = rdbLoadLen(&rdb,NULL)) == RDB_LENERR)\n                goto eoferr;\n            continue; /* Read type again. */\n        } else if (type == RDB_OPCODE_AUX) {\n            /* AUX: generic string-string fields. Use to add state to RDB\n             * which is backward compatible. Implementations of RDB loading\n             * are requierd to skip AUX fields they don't understand.\n             *\n             * An AUX field is composed of two strings: key and value. */\n            robj *auxkey, *auxval;\n            rdbstate.doing = RDB_CHECK_DOING_READ_AUX;\n            if ((auxkey = rdbLoadStringObject(&rdb)) == NULL) goto eoferr;\n            if ((auxval = rdbLoadStringObject(&rdb)) == NULL) goto eoferr;\n\n            rdbCheckInfo(\"AUX FIELD %s = '%s'\",\n                (char*)auxkey->ptr, (char*)auxval->ptr);\n            decrRefCount(auxkey);\n            decrRefCount(auxval);\n            continue; /* Read type again. */\n        } else {\n            if (!rdbIsObjectType(type)) {\n                rdbCheckError(\"Invalid object type: %d\", type);\n                return 1;\n            }\n            rdbstate.key_type = type;\n        }\n\n        /* Read key */\n        rdbstate.doing = RDB_CHECK_DOING_READ_KEY;\n        if ((key = rdbLoadStringObject(&rdb)) == NULL) goto eoferr;\n        rdbstate.key = key;\n        rdbstate.keys++;\n        /* Read value */\n        rdbstate.doing = RDB_CHECK_DOING_READ_OBJECT_VALUE;\n        if ((val = rdbLoadObject(type,&rdb)) == NULL) goto eoferr;\n        /* Check if the key already expired. This function is used when loading\n         * an RDB file from disk, either at startup, or when an RDB was\n         * received from the master. In the latter case, the master is\n         * responsible for key expiry. If we would expire keys here, the\n         * snapshot taken by the master may not be reflected on the slave. */\n        if (server.masterhost == NULL && expiretime != -1 && expiretime < now)\n            rdbstate.already_expired++;\n        if (expiretime != -1) rdbstate.expires++;\n        rdbstate.key = NULL;\n        decrRefCount(key);\n        decrRefCount(val);\n        rdbstate.key_type = -1;\n    }\n    /* Verify the checksum if RDB version is >= 5 */\n    if (rdbver >= 5 && server.rdb_checksum) {\n        uint64_t cksum, expected = rdb.cksum;\n\n        rdbstate.doing = RDB_CHECK_DOING_CHECK_SUM;\n        if (rioRead(&rdb,&cksum,8) == 0) goto eoferr;\n        memrev64ifbe(&cksum);\n        if (cksum == 0) {\n            rdbCheckInfo(\"RDB file was saved with checksum disabled: no check performed.\");\n        } else if (cksum != expected) {\n            rdbCheckError(\"RDB CRC error\");\n        } else {\n            rdbCheckInfo(\"Checksum OK\");\n        }\n    }\n\n    fclose(fp);\n    return 0;\n\neoferr: /* unexpected end of file is handled here with a fatal exit */\n    if (rdbstate.error_set) {\n        rdbCheckError(rdbstate.error);\n    } else {\n        rdbCheckError(\"Unexpected EOF reading RDB file\");\n    }\n    return 1;\n}\n\n/* RDB check main: called form redis.c when Redis is executed with the\n * redis-check-rdb alias.\n *\n * The function never returns, but exits with the status code according\n * to success (RDB is sane) or error (RDB is corrupted). */\nint redis_check_rdb_main(int argc, char **argv) {\n    if (argc != 2) {\n        fprintf(stderr, \"Usage: %s <rdb-file-name>\\n\", argv[0]);\n        exit(1);\n    }\n    createSharedObjects(); /* Needed for loading. */\n    server.loading_process_events_interval_bytes = 0;\n    rdbCheckMode = 1;\n    rdbCheckInfo(\"Checking RDB file %s\", argv[1]);\n    rdbCheckSetupSignals();\n    int retval = redis_check_rdb(argv[1]);\n    if (retval == 0) {\n        rdbCheckInfo(\"\\\\o/ RDB looks OK! \\\\o/\");\n        rdbShowGenericInfo();\n    }\n    exit(retval);\n}\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/src/redis-cli.c",
    "content": "/* Redis CLI (command line interface)\n *\n * Copyright (c) 2009-2012, Salvatore Sanfilippo <antirez at gmail dot com>\n * All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions are met:\n *\n *   * Redistributions of source code must retain the above copyright notice,\n *     this list of conditions and the following disclaimer.\n *   * Redistributions in binary form must reproduce the above copyright\n *     notice, this list of conditions and the following disclaimer in the\n *     documentation and/or other materials provided with the distribution.\n *   * Neither the name of Redis nor the names of its contributors may be used\n *     to endorse or promote products derived from this software without\n *     specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\"\n * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\n * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE\n * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR\n * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF\n * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS\n * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN\n * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)\n * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE\n * POSSIBILITY OF SUCH DAMAGE.\n */\n\n#include \"fmacros.h\"\n#include \"version.h\"\n\n#include <stdio.h>\n#include <string.h>\n#include <stdlib.h>\n#include <signal.h>\n#include <unistd.h>\n#include <time.h>\n#include <ctype.h>\n#include <errno.h>\n#include <sys/stat.h>\n#include <sys/time.h>\n#include <assert.h>\n#include <fcntl.h>\n#include <limits.h>\n#include <math.h>\n\n#include <hiredis.h>\n#include <sds.h> /* use sds.h from hiredis, so that only one set of sds functions will be present in the binary */\n#include \"zmalloc.h\"\n#include \"linenoise.h\"\n#include \"help.h\"\n#include \"anet.h\"\n#include \"ae.h\"\n\n#define UNUSED(V) ((void) V)\n\n#define OUTPUT_STANDARD 0\n#define OUTPUT_RAW 1\n#define OUTPUT_CSV 2\n#define REDIS_CLI_KEEPALIVE_INTERVAL 15 /* seconds */\n#define REDIS_CLI_DEFAULT_PIPE_TIMEOUT 30 /* seconds */\n#define REDIS_CLI_HISTFILE_ENV \"REDISCLI_HISTFILE\"\n#define REDIS_CLI_HISTFILE_DEFAULT \".rediscli_history\"\n#define REDIS_CLI_RCFILE_ENV \"REDISCLI_RCFILE\"\n#define REDIS_CLI_RCFILE_DEFAULT \".redisclirc\"\n\n/* --latency-dist palettes. */\nint spectrum_palette_color_size = 19;\nint spectrum_palette_color[] = {0,233,234,235,237,239,241,243,245,247,144,143,142,184,226,214,208,202,196};\n\nint spectrum_palette_mono_size = 13;\nint spectrum_palette_mono[] = {0,233,234,235,237,239,241,243,245,247,249,251,253};\n\n/* The actual palette in use. */\nint *spectrum_palette;\nint spectrum_palette_size;\n\nstatic redisContext *context;\nstatic struct config {\n    char *hostip;\n    int hostport;\n    char *hostsocket;\n    long repeat;\n    long interval;\n    int dbnum;\n    int interactive;\n    int shutdown;\n    int monitor_mode;\n    int pubsub_mode;\n    int latency_mode;\n    int latency_dist_mode;\n    int latency_history;\n    int lru_test_mode;\n    long long lru_test_sample_size;\n    int cluster_mode;\n    int cluster_reissue_command;\n    int slave_mode;\n    int pipe_mode;\n    int pipe_timeout;\n    int getrdb_mode;\n    int stat_mode;\n    int scan_mode;\n    int intrinsic_latency_mode;\n    int intrinsic_latency_duration;\n    char *pattern;\n    char *rdb_filename;\n    int bigkeys;\n    int stdinarg; /* get last arg from stdin. (-x option) */\n    char *auth;\n    int output; /* output mode, see OUTPUT_* defines */\n    sds mb_delim;\n    char prompt[128];\n    char *eval;\n    int eval_ldb;\n    int eval_ldb_sync;  /* Ask for synchronous mode of the Lua debugger. */\n    int eval_ldb_end;   /* Lua debugging session ended. */\n    int enable_ldb_on_eval; /* Handle manual SCRIPT DEBUG + EVAL commands. */\n    int last_cmd_type;\n} config;\n\n/* User preferences. */\nstatic struct pref {\n    int hints;\n} pref;\n\nstatic volatile sig_atomic_t force_cancel_loop = 0;\nstatic void usage(void);\nstatic void slaveMode(void);\nchar *redisGitSHA1(void);\nchar *redisGitDirty(void);\nstatic int cliConnect(int force);\n\n/*------------------------------------------------------------------------------\n * Utility functions\n *--------------------------------------------------------------------------- */\n\nstatic long long ustime(void) {\n    struct timeval tv;\n    long long ust;\n\n    gettimeofday(&tv, NULL);\n    ust = ((long long)tv.tv_sec)*1000000;\n    ust += tv.tv_usec;\n    return ust;\n}\n\nstatic long long mstime(void) {\n    return ustime()/1000;\n}\n\nstatic void cliRefreshPrompt(void) {\n    int len;\n\n    if (config.eval_ldb) return;\n    if (config.hostsocket != NULL)\n        len = snprintf(config.prompt,sizeof(config.prompt),\"redis %s\",\n                       config.hostsocket);\n    else\n        len = anetFormatAddr(config.prompt, sizeof(config.prompt),\n                           config.hostip, config.hostport);\n    /* Add [dbnum] if needed */\n    if (config.dbnum != 0)\n        len += snprintf(config.prompt+len,sizeof(config.prompt)-len,\"[%d]\",\n            config.dbnum);\n    snprintf(config.prompt+len,sizeof(config.prompt)-len,\"> \");\n}\n\n/* Return the name of the dotfile for the specified 'dotfilename'.\n * Normally it just concatenates user $HOME to the file specified\n * in 'dotfilename'. However if the environment varialbe 'envoverride'\n * is set, its value is taken as the path.\n *\n * The function returns NULL (if the file is /dev/null or cannot be\n * obtained for some error), or an SDS string that must be freed by\n * the user. */\nstatic sds getDotfilePath(char *envoverride, char *dotfilename) {\n    char *path = NULL;\n    sds dotPath = NULL;\n\n    /* Check the env for a dotfile override. */\n    path = getenv(envoverride);\n    if (path != NULL && *path != '\\0') {\n        if (!strcmp(\"/dev/null\", path)) {\n            return NULL;\n        }\n\n        /* If the env is set, return it. */\n        dotPath = sdsnew(path);\n    } else {\n        char *home = getenv(\"HOME\");\n        if (home != NULL && *home != '\\0') {\n            /* If no override is set use $HOME/<dotfilename>. */\n            dotPath = sdscatprintf(sdsempty(), \"%s/%s\", home, dotfilename);\n        }\n    }\n    return dotPath;\n}\n\n/*------------------------------------------------------------------------------\n * Help functions\n *--------------------------------------------------------------------------- */\n\n#define CLI_HELP_COMMAND 1\n#define CLI_HELP_GROUP 2\n\ntypedef struct {\n    int type;\n    int argc;\n    sds *argv;\n    sds full;\n\n    /* Only used for help on commands */\n    struct commandHelp *org;\n} helpEntry;\n\nstatic helpEntry *helpEntries;\nstatic int helpEntriesLen;\n\nstatic sds cliVersion(void) {\n    sds version;\n    version = sdscatprintf(sdsempty(), \"%s\", REDIS_VERSION);\n\n    /* Add git commit and working tree status when available */\n    if (strtoll(redisGitSHA1(),NULL,16)) {\n        version = sdscatprintf(version, \" (git:%s\", redisGitSHA1());\n        if (strtoll(redisGitDirty(),NULL,10))\n            version = sdscatprintf(version, \"-dirty\");\n        version = sdscat(version, \")\");\n    }\n    return version;\n}\n\nstatic void cliInitHelp(void) {\n    int commandslen = sizeof(commandHelp)/sizeof(struct commandHelp);\n    int groupslen = sizeof(commandGroups)/sizeof(char*);\n    int i, len, pos = 0;\n    helpEntry tmp;\n\n    helpEntriesLen = len = commandslen+groupslen;\n    helpEntries = zmalloc(sizeof(helpEntry)*len);\n\n    for (i = 0; i < groupslen; i++) {\n        tmp.argc = 1;\n        tmp.argv = zmalloc(sizeof(sds));\n        tmp.argv[0] = sdscatprintf(sdsempty(),\"@%s\",commandGroups[i]);\n        tmp.full = tmp.argv[0];\n        tmp.type = CLI_HELP_GROUP;\n        tmp.org = NULL;\n        helpEntries[pos++] = tmp;\n    }\n\n    for (i = 0; i < commandslen; i++) {\n        tmp.argv = sdssplitargs(commandHelp[i].name,&tmp.argc);\n        tmp.full = sdsnew(commandHelp[i].name);\n        tmp.type = CLI_HELP_COMMAND;\n        tmp.org = &commandHelp[i];\n        helpEntries[pos++] = tmp;\n    }\n}\n\n/* cliInitHelp() setups the helpEntries array with the command and group\n * names from the help.h file. However the Redis instance we are connecting\n * to may support more commands, so this function integrates the previous\n * entries with additional entries obtained using the COMMAND command\n * available in recent versions of Redis. */\nstatic void cliIntegrateHelp(void) {\n    if (cliConnect(0) == REDIS_ERR) return;\n\n    redisReply *reply = redisCommand(context, \"COMMAND\");\n    if(reply == NULL || reply->type != REDIS_REPLY_ARRAY) return;\n\n    /* Scan the array reported by COMMAND and fill only the entries that\n     * don't already match what we have. */\n    for (size_t j = 0; j < reply->elements; j++) {\n        redisReply *entry = reply->element[j];\n        char *cmdname = entry->element[0]->str;\n        int i;\n\n        for (i = 0; i < helpEntriesLen; i++) {\n            helpEntry *he = helpEntries+i;\n            if (!strcasecmp(he->argv[0],cmdname))\n                break;\n        }\n        if (i != helpEntriesLen) continue;\n\n        helpEntriesLen++;\n        helpEntries = zrealloc(helpEntries,sizeof(helpEntry)*helpEntriesLen);\n        helpEntry *new = helpEntries+(helpEntriesLen-1);\n\n        new->argc = 1;\n        new->argv = zmalloc(sizeof(sds));\n        new->argv[0] = sdsnew(cmdname);\n        new->full = new->argv[0];\n        new->type = CLI_HELP_COMMAND;\n        sdstoupper(new->argv[0]);\n\n        struct commandHelp *ch = zmalloc(sizeof(*ch));\n        ch->name = new->argv[0];\n        ch->params = sdsempty();\n        int args = llabs(entry->element[1]->integer);\n        if (entry->element[3]->integer == 1) {\n            ch->params = sdscat(ch->params,\"key \");\n            args--;\n        }\n        while(args--) ch->params = sdscat(ch->params,\"arg \");\n        if (entry->element[1]->integer < 0)\n            ch->params = sdscat(ch->params,\"...options...\");\n        ch->summary = \"Help not available\";\n        ch->group = 0;\n        ch->since = \"not known\";\n        new->org = ch;\n    }\n    freeReplyObject(reply);\n}\n\n/* Output command help to stdout. */\nstatic void cliOutputCommandHelp(struct commandHelp *help, int group) {\n    printf(\"\\r\\n  \\x1b[1m%s\\x1b[0m \\x1b[90m%s\\x1b[0m\\r\\n\", help->name, help->params);\n    printf(\"  \\x1b[33msummary:\\x1b[0m %s\\r\\n\", help->summary);\n    printf(\"  \\x1b[33msince:\\x1b[0m %s\\r\\n\", help->since);\n    if (group) {\n        printf(\"  \\x1b[33mgroup:\\x1b[0m %s\\r\\n\", commandGroups[help->group]);\n    }\n}\n\n/* Print generic help. */\nstatic void cliOutputGenericHelp(void) {\n    sds version = cliVersion();\n    printf(\n        \"redis-cli %s\\n\"\n        \"To get help about Redis commands type:\\n\"\n        \"      \\\"help @<group>\\\" to get a list of commands in <group>\\n\"\n        \"      \\\"help <command>\\\" for help on <command>\\n\"\n        \"      \\\"help <tab>\\\" to get a list of possible help topics\\n\"\n        \"      \\\"quit\\\" to exit\\n\"\n        \"\\n\"\n        \"To set redis-cli perferences:\\n\"\n        \"      \\\":set hints\\\" enable online hints\\n\"\n        \"      \\\":set nohints\\\" disable online hints\\n\"\n        \"Set your preferences in ~/.redisclirc\\n\",\n        version\n    );\n    sdsfree(version);\n}\n\n/* Output all command help, filtering by group or command name. */\nstatic void cliOutputHelp(int argc, char **argv) {\n    int i, j, len;\n    int group = -1;\n    helpEntry *entry;\n    struct commandHelp *help;\n\n    if (argc == 0) {\n        cliOutputGenericHelp();\n        return;\n    } else if (argc > 0 && argv[0][0] == '@') {\n        len = sizeof(commandGroups)/sizeof(char*);\n        for (i = 0; i < len; i++) {\n            if (strcasecmp(argv[0]+1,commandGroups[i]) == 0) {\n                group = i;\n                break;\n            }\n        }\n    }\n\n    assert(argc > 0);\n    for (i = 0; i < helpEntriesLen; i++) {\n        entry = &helpEntries[i];\n        if (entry->type != CLI_HELP_COMMAND) continue;\n\n        help = entry->org;\n        if (group == -1) {\n            /* Compare all arguments */\n            if (argc == entry->argc) {\n                for (j = 0; j < argc; j++) {\n                    if (strcasecmp(argv[j],entry->argv[j]) != 0) break;\n                }\n                if (j == argc) {\n                    cliOutputCommandHelp(help,1);\n                }\n            }\n        } else {\n            if (group == help->group) {\n                cliOutputCommandHelp(help,0);\n            }\n        }\n    }\n    printf(\"\\r\\n\");\n}\n\n/* Linenoise completion callback. */\nstatic void completionCallback(const char *buf, linenoiseCompletions *lc) {\n    size_t startpos = 0;\n    int mask;\n    int i;\n    size_t matchlen;\n    sds tmp;\n\n    if (strncasecmp(buf,\"help \",5) == 0) {\n        startpos = 5;\n        while (isspace(buf[startpos])) startpos++;\n        mask = CLI_HELP_COMMAND | CLI_HELP_GROUP;\n    } else {\n        mask = CLI_HELP_COMMAND;\n    }\n\n    for (i = 0; i < helpEntriesLen; i++) {\n        if (!(helpEntries[i].type & mask)) continue;\n\n        matchlen = strlen(buf+startpos);\n        if (strncasecmp(buf+startpos,helpEntries[i].full,matchlen) == 0) {\n            tmp = sdsnewlen(buf,startpos);\n            tmp = sdscat(tmp,helpEntries[i].full);\n            linenoiseAddCompletion(lc,tmp);\n            sdsfree(tmp);\n        }\n    }\n}\n\n/* Linenoise hints callback. */\nstatic char *hintsCallback(const char *buf, int *color, int *bold) {\n    if (!pref.hints) return NULL;\n\n    int i, argc, buflen = strlen(buf);\n    sds *argv = sdssplitargs(buf,&argc);\n    int endspace = buflen && isspace(buf[buflen-1]);\n\n    /* Check if the argument list is empty and return ASAP. */\n    if (argc == 0) {\n        sdsfreesplitres(argv,argc);\n        return NULL;\n    }\n\n    for (i = 0; i < helpEntriesLen; i++) {\n        if (!(helpEntries[i].type & CLI_HELP_COMMAND)) continue;\n\n        if (strcasecmp(argv[0],helpEntries[i].full) == 0)\n        {\n            *color = 90;\n            *bold = 0;\n            sds hint = sdsnew(helpEntries[i].org->params);\n\n            /* Remove arguments from the returned hint to show only the\n             * ones the user did not yet typed. */\n            int toremove = argc-1;\n            while(toremove > 0 && sdslen(hint)) {\n                if (hint[0] == '[') break;\n                if (hint[0] == ' ') toremove--;\n                sdsrange(hint,1,-1);\n            }\n\n            /* Add an initial space if needed. */\n            if (!endspace) {\n                sds newhint = sdsnewlen(\" \",1);\n                newhint = sdscatsds(newhint,hint);\n                sdsfree(hint);\n                hint = newhint;\n            }\n\n            sdsfreesplitres(argv,argc);\n            return hint;\n        }\n    }\n    sdsfreesplitres(argv,argc);\n    return NULL;\n}\n\nstatic void freeHintsCallback(void *ptr) {\n    sdsfree(ptr);\n}\n\n/*------------------------------------------------------------------------------\n * Networking / parsing\n *--------------------------------------------------------------------------- */\n\n/* Send AUTH command to the server */\nstatic int cliAuth(void) {\n    redisReply *reply;\n    if (config.auth == NULL) return REDIS_OK;\n\n    reply = redisCommand(context,\"AUTH %s\",config.auth);\n    if (reply != NULL) {\n        freeReplyObject(reply);\n        return REDIS_OK;\n    }\n    return REDIS_ERR;\n}\n\n/* Send SELECT dbnum to the server */\nstatic int cliSelect(void) {\n    redisReply *reply;\n    if (config.dbnum == 0) return REDIS_OK;\n\n    reply = redisCommand(context,\"SELECT %d\",config.dbnum);\n    if (reply != NULL) {\n        int result = REDIS_OK;\n        if (reply->type == REDIS_REPLY_ERROR) result = REDIS_ERR;\n        freeReplyObject(reply);\n        return result;\n    }\n    return REDIS_ERR;\n}\n\n/* Connect to the server. If force is not zero the connection is performed\n * even if there is already a connected socket. */\nstatic int cliConnect(int force) {\n    if (context == NULL || force) {\n        if (context != NULL) {\n            redisFree(context);\n        }\n\n        if (config.hostsocket == NULL) {\n            context = redisConnect(config.hostip,config.hostport);\n        } else {\n            context = redisConnectUnix(config.hostsocket);\n        }\n\n        if (context->err) {\n            fprintf(stderr,\"Could not connect to Redis at \");\n            if (config.hostsocket == NULL)\n                fprintf(stderr,\"%s:%d: %s\\n\",config.hostip,config.hostport,context->errstr);\n            else\n                fprintf(stderr,\"%s: %s\\n\",config.hostsocket,context->errstr);\n            redisFree(context);\n            context = NULL;\n            return REDIS_ERR;\n        }\n\n        /* Set aggressive KEEP_ALIVE socket option in the Redis context socket\n         * in order to prevent timeouts caused by the execution of long\n         * commands. At the same time this improves the detection of real\n         * errors. */\n        anetKeepAlive(NULL, context->fd, REDIS_CLI_KEEPALIVE_INTERVAL);\n\n        /* Do AUTH and select the right DB. */\n        if (cliAuth() != REDIS_OK)\n            return REDIS_ERR;\n        if (cliSelect() != REDIS_OK)\n            return REDIS_ERR;\n    }\n    return REDIS_OK;\n}\n\nstatic void cliPrintContextError(void) {\n    if (context == NULL) return;\n    fprintf(stderr,\"Error: %s\\n\",context->errstr);\n}\n\nstatic sds cliFormatReplyTTY(redisReply *r, char *prefix) {\n    sds out = sdsempty();\n    switch (r->type) {\n    case REDIS_REPLY_ERROR:\n        out = sdscatprintf(out,\"(error) %s\\n\", r->str);\n    break;\n    case REDIS_REPLY_STATUS:\n        out = sdscat(out,r->str);\n        out = sdscat(out,\"\\n\");\n    break;\n    case REDIS_REPLY_INTEGER:\n        out = sdscatprintf(out,\"(integer) %lld\\n\",r->integer);\n    break;\n    case REDIS_REPLY_STRING:\n        /* If you are producing output for the standard output we want\n        * a more interesting output with quoted characters and so forth */\n        out = sdscatrepr(out,r->str,r->len);\n        out = sdscat(out,\"\\n\");\n    break;\n    case REDIS_REPLY_NIL:\n        out = sdscat(out,\"(nil)\\n\");\n    break;\n    case REDIS_REPLY_ARRAY:\n        if (r->elements == 0) {\n            out = sdscat(out,\"(empty list or set)\\n\");\n        } else {\n            unsigned int i, idxlen = 0;\n            char _prefixlen[16];\n            char _prefixfmt[16];\n            sds _prefix;\n            sds tmp;\n\n            /* Calculate chars needed to represent the largest index */\n            i = r->elements;\n            do {\n                idxlen++;\n                i /= 10;\n            } while(i);\n\n            /* Prefix for nested multi bulks should grow with idxlen+2 spaces */\n            memset(_prefixlen,' ',idxlen+2);\n            _prefixlen[idxlen+2] = '\\0';\n            _prefix = sdscat(sdsnew(prefix),_prefixlen);\n\n            /* Setup prefix format for every entry */\n            snprintf(_prefixfmt,sizeof(_prefixfmt),\"%%s%%%ud) \",idxlen);\n\n            for (i = 0; i < r->elements; i++) {\n                /* Don't use the prefix for the first element, as the parent\n                 * caller already prepended the index number. */\n                out = sdscatprintf(out,_prefixfmt,i == 0 ? \"\" : prefix,i+1);\n\n                /* Format the multi bulk entry */\n                tmp = cliFormatReplyTTY(r->element[i],_prefix);\n                out = sdscatlen(out,tmp,sdslen(tmp));\n                sdsfree(tmp);\n            }\n            sdsfree(_prefix);\n        }\n    break;\n    default:\n        fprintf(stderr,\"Unknown reply type: %d\\n\", r->type);\n        exit(1);\n    }\n    return out;\n}\n\nint isColorTerm(void) {\n    char *t = getenv(\"TERM\");\n    return t != NULL && strstr(t,\"xterm\") != NULL;\n}\n\n/* Helpe  function for sdsCatColorizedLdbReply() appending colorize strings\n * to an SDS string. */\nsds sdscatcolor(sds o, char *s, size_t len, char *color) {\n    if (!isColorTerm()) return sdscatlen(o,s,len);\n\n    int bold = strstr(color,\"bold\") != NULL;\n    int ccode = 37; /* Defaults to white. */\n    if (strstr(color,\"red\")) ccode = 31;\n    else if (strstr(color,\"red\")) ccode = 31;\n    else if (strstr(color,\"green\")) ccode = 32;\n    else if (strstr(color,\"yellow\")) ccode = 33;\n    else if (strstr(color,\"blue\")) ccode = 34;\n    else if (strstr(color,\"magenta\")) ccode = 35;\n    else if (strstr(color,\"cyan\")) ccode = 36;\n    else if (strstr(color,\"white\")) ccode = 37;\n\n    o = sdscatfmt(o,\"\\033[%i;%i;49m\",bold,ccode);\n    o = sdscatlen(o,s,len);\n    o = sdscat(o,\"\\033[0m\");\n    return o;\n}\n\n/* Colorize Lua debugger status replies according to the prefix they\n * have. */\nsds sdsCatColorizedLdbReply(sds o, char *s, size_t len) {\n    char *color = \"white\";\n\n    if (strstr(s,\"<debug>\")) color = \"bold\";\n    if (strstr(s,\"<redis>\")) color = \"green\";\n    if (strstr(s,\"<reply>\")) color = \"cyan\";\n    if (strstr(s,\"<error>\")) color = \"red\";\n    if (strstr(s,\"<hint>\")) color = \"bold\";\n    if (strstr(s,\"<value>\") || strstr(s,\"<retval>\")) color = \"magenta\";\n    if (len > 4 && isdigit(s[3])) {\n        if (s[1] == '>') color = \"yellow\"; /* Current line. */\n        else if (s[2] == '#') color = \"bold\"; /* Break point. */\n    }\n    return sdscatcolor(o,s,len,color);\n}\n\nstatic sds cliFormatReplyRaw(redisReply *r) {\n    sds out = sdsempty(), tmp;\n    size_t i;\n\n    switch (r->type) {\n    case REDIS_REPLY_NIL:\n        /* Nothing... */\n        break;\n    case REDIS_REPLY_ERROR:\n        out = sdscatlen(out,r->str,r->len);\n        out = sdscatlen(out,\"\\n\",1);\n        break;\n    case REDIS_REPLY_STATUS:\n    case REDIS_REPLY_STRING:\n        if (r->type == REDIS_REPLY_STATUS && config.eval_ldb) {\n            /* The Lua debugger replies with arrays of simple (status)\n             * strings. We colorize the output for more fun if this\n             * is a debugging session. */\n\n            /* Detect the end of a debugging session. */\n            if (strstr(r->str,\"<endsession>\") == r->str) {\n                config.enable_ldb_on_eval = 0;\n                config.eval_ldb = 0;\n                config.eval_ldb_end = 1; /* Signal the caller session ended. */\n                config.output = OUTPUT_STANDARD;\n                cliRefreshPrompt();\n            } else {\n                out = sdsCatColorizedLdbReply(out,r->str,r->len);\n            }\n        } else {\n            out = sdscatlen(out,r->str,r->len);\n        }\n        break;\n    case REDIS_REPLY_INTEGER:\n        out = sdscatprintf(out,\"%lld\",r->integer);\n        break;\n    case REDIS_REPLY_ARRAY:\n        for (i = 0; i < r->elements; i++) {\n            if (i > 0) out = sdscat(out,config.mb_delim);\n            tmp = cliFormatReplyRaw(r->element[i]);\n            out = sdscatlen(out,tmp,sdslen(tmp));\n            sdsfree(tmp);\n        }\n        break;\n    default:\n        fprintf(stderr,\"Unknown reply type: %d\\n\", r->type);\n        exit(1);\n    }\n    return out;\n}\n\nstatic sds cliFormatReplyCSV(redisReply *r) {\n    unsigned int i;\n\n    sds out = sdsempty();\n    switch (r->type) {\n    case REDIS_REPLY_ERROR:\n        out = sdscat(out,\"ERROR,\");\n        out = sdscatrepr(out,r->str,strlen(r->str));\n    break;\n    case REDIS_REPLY_STATUS:\n        out = sdscatrepr(out,r->str,r->len);\n    break;\n    case REDIS_REPLY_INTEGER:\n        out = sdscatprintf(out,\"%lld\",r->integer);\n    break;\n    case REDIS_REPLY_STRING:\n        out = sdscatrepr(out,r->str,r->len);\n    break;\n    case REDIS_REPLY_NIL:\n        out = sdscat(out,\"NIL\");\n    break;\n    case REDIS_REPLY_ARRAY:\n        for (i = 0; i < r->elements; i++) {\n            sds tmp = cliFormatReplyCSV(r->element[i]);\n            out = sdscatlen(out,tmp,sdslen(tmp));\n            if (i != r->elements-1) out = sdscat(out,\",\");\n            sdsfree(tmp);\n        }\n    break;\n    default:\n        fprintf(stderr,\"Unknown reply type: %d\\n\", r->type);\n        exit(1);\n    }\n    return out;\n}\n\nstatic int cliReadReply(int output_raw_strings) {\n    void *_reply;\n    redisReply *reply;\n    sds out = NULL;\n    int output = 1;\n\n    if (redisGetReply(context,&_reply) != REDIS_OK) {\n        if (config.shutdown) {\n            redisFree(context);\n            context = NULL;\n            return REDIS_OK;\n        }\n        if (config.interactive) {\n            /* Filter cases where we should reconnect */\n            if (context->err == REDIS_ERR_IO &&\n                (errno == ECONNRESET || errno == EPIPE))\n                return REDIS_ERR;\n            if (context->err == REDIS_ERR_EOF)\n                return REDIS_ERR;\n        }\n        cliPrintContextError();\n        exit(1);\n        return REDIS_ERR; /* avoid compiler warning */\n    }\n\n    reply = (redisReply*)_reply;\n\n    config.last_cmd_type = reply->type;\n\n    /* Check if we need to connect to a different node and reissue the\n     * request. */\n    if (config.cluster_mode && reply->type == REDIS_REPLY_ERROR &&\n        (!strncmp(reply->str,\"MOVED\",5) || !strcmp(reply->str,\"ASK\")))\n    {\n        char *p = reply->str, *s;\n        int slot;\n\n        output = 0;\n        /* Comments show the position of the pointer as:\n         *\n         * [S] for pointer 's'\n         * [P] for pointer 'p'\n         */\n        s = strchr(p,' ');      /* MOVED[S]3999 127.0.0.1:6381 */\n        p = strchr(s+1,' ');    /* MOVED[S]3999[P]127.0.0.1:6381 */\n        *p = '\\0';\n        slot = atoi(s+1);\n        s = strrchr(p+1,':');    /* MOVED 3999[P]127.0.0.1[S]6381 */\n        *s = '\\0';\n        sdsfree(config.hostip);\n        config.hostip = sdsnew(p+1);\n        config.hostport = atoi(s+1);\n        if (config.interactive)\n            printf(\"-> Redirected to slot [%d] located at %s:%d\\n\",\n                slot, config.hostip, config.hostport);\n        config.cluster_reissue_command = 1;\n        cliRefreshPrompt();\n    }\n\n    if (output) {\n        if (output_raw_strings) {\n            out = cliFormatReplyRaw(reply);\n        } else {\n            if (config.output == OUTPUT_RAW) {\n                out = cliFormatReplyRaw(reply);\n                out = sdscat(out,\"\\n\");\n            } else if (config.output == OUTPUT_STANDARD) {\n                out = cliFormatReplyTTY(reply,\"\");\n            } else if (config.output == OUTPUT_CSV) {\n                out = cliFormatReplyCSV(reply);\n                out = sdscat(out,\"\\n\");\n            }\n        }\n        fwrite(out,sdslen(out),1,stdout);\n        sdsfree(out);\n    }\n    freeReplyObject(reply);\n    return REDIS_OK;\n}\n\nstatic int cliSendCommand(int argc, char **argv, int repeat) {\n    char *command = argv[0];\n    size_t *argvlen;\n    int j, output_raw;\n\n    if (!config.eval_ldb && /* In debugging mode, let's pass \"help\" to Redis. */\n        (!strcasecmp(command,\"help\") || !strcasecmp(command,\"?\"))) {\n        cliOutputHelp(--argc, ++argv);\n        return REDIS_OK;\n    }\n\n    if (context == NULL) return REDIS_ERR;\n\n    output_raw = 0;\n    if (!strcasecmp(command,\"info\") ||\n        (argc >= 2 && !strcasecmp(command,\"debug\") &&\n                      ((!strcasecmp(argv[1],\"jemalloc\") && !strcasecmp(argv[2],\"info\")) ||\n                       !strcasecmp(argv[1],\"htstats\"))) ||\n        (argc == 2 && !strcasecmp(command,\"cluster\") &&\n                      (!strcasecmp(argv[1],\"nodes\") ||\n                       !strcasecmp(argv[1],\"info\"))) ||\n        (argc == 2 && !strcasecmp(command,\"client\") &&\n                       !strcasecmp(argv[1],\"list\")) ||\n        (argc == 3 && !strcasecmp(command,\"latency\") &&\n                       !strcasecmp(argv[1],\"graph\")) ||\n        (argc == 2 && !strcasecmp(command,\"latency\") &&\n                       !strcasecmp(argv[1],\"doctor\")))\n    {\n        output_raw = 1;\n    }\n\n    if (!strcasecmp(command,\"shutdown\")) config.shutdown = 1;\n    if (!strcasecmp(command,\"monitor\")) config.monitor_mode = 1;\n    if (!strcasecmp(command,\"subscribe\") ||\n        !strcasecmp(command,\"psubscribe\")) config.pubsub_mode = 1;\n    if (!strcasecmp(command,\"sync\") ||\n        !strcasecmp(command,\"psync\")) config.slave_mode = 1;\n\n    /* When the user manually calls SCRIPT DEBUG, setup the activation of\n     * debugging mode on the next eval if needed. */\n    if (argc == 3 && !strcasecmp(argv[0],\"script\") &&\n                     !strcasecmp(argv[1],\"debug\"))\n    {\n        if (!strcasecmp(argv[2],\"yes\") || !strcasecmp(argv[2],\"sync\")) {\n            config.enable_ldb_on_eval = 1;\n        } else {\n            config.enable_ldb_on_eval = 0;\n        }\n    }\n\n    /* Actually activate LDB on EVAL if needed. */\n    if (!strcasecmp(command,\"eval\") && config.enable_ldb_on_eval) {\n        config.eval_ldb = 1;\n        config.output = OUTPUT_RAW;\n    }\n\n    /* Setup argument length */\n    argvlen = zmalloc(argc*sizeof(size_t));\n    for (j = 0; j < argc; j++)\n        argvlen[j] = sdslen(argv[j]);\n\n    while(repeat--) {\n        redisAppendCommandArgv(context,argc,(const char**)argv,argvlen);\n        while (config.monitor_mode) {\n            if (cliReadReply(output_raw) != REDIS_OK) exit(1);\n            fflush(stdout);\n        }\n\n        if (config.pubsub_mode) {\n            if (config.output != OUTPUT_RAW)\n                printf(\"Reading messages... (press Ctrl-C to quit)\\n\");\n            while (1) {\n                if (cliReadReply(output_raw) != REDIS_OK) exit(1);\n            }\n        }\n\n        if (config.slave_mode) {\n            printf(\"Entering slave output mode...  (press Ctrl-C to quit)\\n\");\n            slaveMode();\n            config.slave_mode = 0;\n            zfree(argvlen);\n            return REDIS_ERR;  /* Error = slaveMode lost connection to master */\n        }\n\n        if (cliReadReply(output_raw) != REDIS_OK) {\n            zfree(argvlen);\n            return REDIS_ERR;\n        } else {\n            /* Store database number when SELECT was successfully executed. */\n            if (!strcasecmp(command,\"select\") && argc == 2 && config.last_cmd_type != REDIS_REPLY_ERROR) {\n                config.dbnum = atoi(argv[1]);\n                cliRefreshPrompt();\n            } else if (!strcasecmp(command,\"auth\") && argc == 2) {\n                cliSelect();\n            }\n        }\n        if (config.interval) usleep(config.interval);\n        fflush(stdout); /* Make it grep friendly */\n    }\n\n    zfree(argvlen);\n    return REDIS_OK;\n}\n\n/* Send a command reconnecting the link if needed. */\nstatic redisReply *reconnectingRedisCommand(redisContext *c, const char *fmt, ...) {\n    redisReply *reply = NULL;\n    int tries = 0;\n    va_list ap;\n\n    assert(!c->err);\n    while(reply == NULL) {\n        while (c->err & (REDIS_ERR_IO | REDIS_ERR_EOF)) {\n            printf(\"\\r\\x1b[0K\"); /* Cursor to left edge + clear line. */\n            printf(\"Reconnecting... %d\\r\", ++tries);\n            fflush(stdout);\n\n            redisFree(c);\n            c = redisConnect(config.hostip,config.hostport);\n            usleep(1000000);\n        }\n\n        va_start(ap,fmt);\n        reply = redisvCommand(c,fmt,ap);\n        va_end(ap);\n\n        if (c->err && !(c->err & (REDIS_ERR_IO | REDIS_ERR_EOF))) {\n            fprintf(stderr, \"Error: %s\\n\", c->errstr);\n            exit(1);\n        } else if (tries > 0) {\n            printf(\"\\r\\x1b[0K\"); /* Cursor to left edge + clear line. */\n        }\n    }\n\n    context = c;\n    return reply;\n}\n\n/*------------------------------------------------------------------------------\n * User interface\n *--------------------------------------------------------------------------- */\n\nstatic int parseOptions(int argc, char **argv) {\n    int i;\n\n    for (i = 1; i < argc; i++) {\n        int lastarg = i==argc-1;\n\n        if (!strcmp(argv[i],\"-h\") && !lastarg) {\n            sdsfree(config.hostip);\n            config.hostip = sdsnew(argv[++i]);\n        } else if (!strcmp(argv[i],\"-h\") && lastarg) {\n            usage();\n        } else if (!strcmp(argv[i],\"--help\")) {\n            usage();\n        } else if (!strcmp(argv[i],\"-x\")) {\n            config.stdinarg = 1;\n        } else if (!strcmp(argv[i],\"-p\") && !lastarg) {\n            config.hostport = atoi(argv[++i]);\n        } else if (!strcmp(argv[i],\"-s\") && !lastarg) {\n            config.hostsocket = argv[++i];\n        } else if (!strcmp(argv[i],\"-r\") && !lastarg) {\n            config.repeat = strtoll(argv[++i],NULL,10);\n        } else if (!strcmp(argv[i],\"-i\") && !lastarg) {\n            double seconds = atof(argv[++i]);\n            config.interval = seconds*1000000;\n        } else if (!strcmp(argv[i],\"-n\") && !lastarg) {\n            config.dbnum = atoi(argv[++i]);\n        } else if (!strcmp(argv[i],\"-a\") && !lastarg) {\n            config.auth = argv[++i];\n        } else if (!strcmp(argv[i],\"--raw\")) {\n            config.output = OUTPUT_RAW;\n        } else if (!strcmp(argv[i],\"--no-raw\")) {\n            config.output = OUTPUT_STANDARD;\n        } else if (!strcmp(argv[i],\"--csv\")) {\n            config.output = OUTPUT_CSV;\n        } else if (!strcmp(argv[i],\"--latency\")) {\n            config.latency_mode = 1;\n        } else if (!strcmp(argv[i],\"--latency-dist\")) {\n            config.latency_dist_mode = 1;\n        } else if (!strcmp(argv[i],\"--mono\")) {\n            spectrum_palette = spectrum_palette_mono;\n            spectrum_palette_size = spectrum_palette_mono_size;\n        } else if (!strcmp(argv[i],\"--latency-history\")) {\n            config.latency_mode = 1;\n            config.latency_history = 1;\n        } else if (!strcmp(argv[i],\"--lru-test\") && !lastarg) {\n            config.lru_test_mode = 1;\n            config.lru_test_sample_size = strtoll(argv[++i],NULL,10);\n        } else if (!strcmp(argv[i],\"--slave\")) {\n            config.slave_mode = 1;\n        } else if (!strcmp(argv[i],\"--stat\")) {\n            config.stat_mode = 1;\n        } else if (!strcmp(argv[i],\"--scan\")) {\n            config.scan_mode = 1;\n        } else if (!strcmp(argv[i],\"--pattern\") && !lastarg) {\n            config.pattern = argv[++i];\n        } else if (!strcmp(argv[i],\"--intrinsic-latency\") && !lastarg) {\n            config.intrinsic_latency_mode = 1;\n            config.intrinsic_latency_duration = atoi(argv[++i]);\n        } else if (!strcmp(argv[i],\"--rdb\") && !lastarg) {\n            config.getrdb_mode = 1;\n            config.rdb_filename = argv[++i];\n        } else if (!strcmp(argv[i],\"--pipe\")) {\n            config.pipe_mode = 1;\n        } else if (!strcmp(argv[i],\"--pipe-timeout\") && !lastarg) {\n            config.pipe_timeout = atoi(argv[++i]);\n        } else if (!strcmp(argv[i],\"--bigkeys\")) {\n            config.bigkeys = 1;\n        } else if (!strcmp(argv[i],\"--eval\") && !lastarg) {\n            config.eval = argv[++i];\n        } else if (!strcmp(argv[i],\"--ldb\")) {\n            config.eval_ldb = 1;\n            config.output = OUTPUT_RAW;\n        } else if (!strcmp(argv[i],\"--ldb-sync-mode\")) {\n            config.eval_ldb = 1;\n            config.eval_ldb_sync = 1;\n            config.output = OUTPUT_RAW;\n        } else if (!strcmp(argv[i],\"-c\")) {\n            config.cluster_mode = 1;\n        } else if (!strcmp(argv[i],\"-d\") && !lastarg) {\n            sdsfree(config.mb_delim);\n            config.mb_delim = sdsnew(argv[++i]);\n        } else if (!strcmp(argv[i],\"-v\") || !strcmp(argv[i], \"--version\")) {\n            sds version = cliVersion();\n            printf(\"redis-cli %s\\n\", version);\n            sdsfree(version);\n            exit(0);\n        } else {\n            if (argv[i][0] == '-') {\n                fprintf(stderr,\n                    \"Unrecognized option or bad number of args for: '%s'\\n\",\n                    argv[i]);\n                exit(1);\n            } else {\n                /* Likely the command name, stop here. */\n                break;\n            }\n        }\n    }\n\n    /* --ldb requires --eval. */\n    if (config.eval_ldb && config.eval == NULL) {\n        fprintf(stderr,\"Options --ldb and --ldb-sync-mode require --eval.\\n\");\n        fprintf(stderr,\"Try %s --help for more information.\\n\", argv[0]);\n        exit(1);\n    }\n    return i;\n}\n\nstatic sds readArgFromStdin(void) {\n    char buf[1024];\n    sds arg = sdsempty();\n\n    while(1) {\n        int nread = read(fileno(stdin),buf,1024);\n\n        if (nread == 0) break;\n        else if (nread == -1) {\n            perror(\"Reading from standard input\");\n            exit(1);\n        }\n        arg = sdscatlen(arg,buf,nread);\n    }\n    return arg;\n}\n\nstatic void usage(void) {\n    sds version = cliVersion();\n    fprintf(stderr,\n\"redis-cli %s\\n\"\n\"\\n\"\n\"Usage: redis-cli [OPTIONS] [cmd [arg [arg ...]]]\\n\"\n\"  -h <hostname>      Server hostname (default: 127.0.0.1).\\n\"\n\"  -p <port>          Server port (default: 6379).\\n\"\n\"  -s <socket>        Server socket (overrides hostname and port).\\n\"\n\"  -a <password>      Password to use when connecting to the server.\\n\"\n\"  -r <repeat>        Execute specified command N times.\\n\"\n\"  -i <interval>      When -r is used, waits <interval> seconds per command.\\n\"\n\"                     It is possible to specify sub-second times like -i 0.1.\\n\"\n\"  -n <db>            Database number.\\n\"\n\"  -x                 Read last argument from STDIN.\\n\"\n\"  -d <delimiter>     Multi-bulk delimiter in for raw formatting (default: \\\\n).\\n\"\n\"  -c                 Enable cluster mode (follow -ASK and -MOVED redirections).\\n\"\n\"  --raw              Use raw formatting for replies (default when STDOUT is\\n\"\n\"                     not a tty).\\n\"\n\"  --no-raw           Force formatted output even when STDOUT is not a tty.\\n\"\n\"  --csv              Output in CSV format.\\n\"\n\"  --stat             Print rolling stats about server: mem, clients, ...\\n\"\n\"  --latency          Enter a special mode continuously sampling latency.\\n\"\n\"  --latency-history  Like --latency but tracking latency changes over time.\\n\"\n\"                     Default time interval is 15 sec. Change it using -i.\\n\"\n\"  --latency-dist     Shows latency as a spectrum, requires xterm 256 colors.\\n\"\n\"                     Default time interval is 1 sec. Change it using -i.\\n\"\n\"  --lru-test <keys>  Simulate a cache workload with an 80-20 distribution.\\n\"\n\"  --slave            Simulate a slave showing commands received from the master.\\n\"\n\"  --rdb <filename>   Transfer an RDB dump from remote server to local file.\\n\"\n\"  --pipe             Transfer raw Redis protocol from stdin to server.\\n\"\n\"  --pipe-timeout <n> In --pipe mode, abort with error if after sending all data.\\n\"\n\"                     no reply is received within <n> seconds.\\n\"\n\"                     Default timeout: %d. Use 0 to wait forever.\\n\"\n\"  --bigkeys          Sample Redis keys looking for big keys.\\n\"\n\"  --scan             List all keys using the SCAN command.\\n\"\n\"  --pattern <pat>    Useful with --scan to specify a SCAN pattern.\\n\"\n\"  --intrinsic-latency <sec> Run a test to measure intrinsic system latency.\\n\"\n\"                     The test will run for the specified amount of seconds.\\n\"\n\"  --eval <file>      Send an EVAL command using the Lua script at <file>.\\n\"\n\"  --ldb              Used with --eval enable the Redis Lua debugger.\\n\"\n\"  --ldb-sync-mode    Like --ldb but uses the synchronous Lua debugger, in\\n\"\n\"                     this mode the server is blocked and script changes are\\n\"\n\"                     are not rolled back from the server memory.\\n\"\n\"  --help             Output this help and exit.\\n\"\n\"  --version          Output version and exit.\\n\"\n\"\\n\"\n\"Examples:\\n\"\n\"  cat /etc/passwd | redis-cli -x set mypasswd\\n\"\n\"  redis-cli get mypasswd\\n\"\n\"  redis-cli -r 100 lpush mylist x\\n\"\n\"  redis-cli -r 100 -i 1 info | grep used_memory_human:\\n\"\n\"  redis-cli --eval myscript.lua key1 key2 , arg1 arg2 arg3\\n\"\n\"  redis-cli --scan --pattern '*:12345*'\\n\"\n\"\\n\"\n\"  (Note: when using --eval the comma separates KEYS[] from ARGV[] items)\\n\"\n\"\\n\"\n\"When no command is given, redis-cli starts in interactive mode.\\n\"\n\"Type \\\"help\\\" in interactive mode for information on available commands\\n\"\n\"and settings.\\n\"\n\"\\n\",\n        version, REDIS_CLI_DEFAULT_PIPE_TIMEOUT);\n    sdsfree(version);\n    exit(1);\n}\n\n/* Turn the plain C strings into Sds strings */\nstatic char **convertToSds(int count, char** args) {\n  int j;\n  char **sds = zmalloc(sizeof(char*)*count);\n\n  for(j = 0; j < count; j++)\n    sds[j] = sdsnew(args[j]);\n\n  return sds;\n}\n\nstatic int issueCommandRepeat(int argc, char **argv, long repeat) {\n    while (1) {\n        config.cluster_reissue_command = 0;\n        if (cliSendCommand(argc,argv,repeat) != REDIS_OK) {\n            cliConnect(1);\n\n            /* If we still cannot send the command print error.\n             * We'll try to reconnect the next time. */\n            if (cliSendCommand(argc,argv,repeat) != REDIS_OK) {\n                cliPrintContextError();\n                return REDIS_ERR;\n            }\n         }\n         /* Issue the command again if we got redirected in cluster mode */\n         if (config.cluster_mode && config.cluster_reissue_command) {\n            cliConnect(1);\n         } else {\n             break;\n        }\n    }\n    return REDIS_OK;\n}\n\nstatic int issueCommand(int argc, char **argv) {\n    return issueCommandRepeat(argc, argv, config.repeat);\n}\n\n/* Split the user provided command into multiple SDS arguments.\n * This function normally uses sdssplitargs() from sds.c which is able\n * to understand \"quoted strings\", escapes and so forth. However when\n * we are in Lua debugging mode and the \"eval\" command is used, we want\n * the remaining Lua script (after \"e \" or \"eval \") to be passed verbatim\n * as a single big argument. */\nstatic sds *cliSplitArgs(char *line, int *argc) {\n    if (config.eval_ldb && (strstr(line,\"eval \") == line ||\n                            strstr(line,\"e \") == line))\n    {\n        sds *argv = sds_malloc(sizeof(sds)*2);\n        *argc = 2;\n        int len = strlen(line);\n        int elen = line[1] == ' ' ? 2 : 5; /* \"e \" or \"eval \"? */\n        argv[0] = sdsnewlen(line,elen-1);\n        argv[1] = sdsnewlen(line+elen,len-elen);\n        return argv;\n    } else {\n        return sdssplitargs(line,argc);\n    }\n}\n\n/* Set the CLI perferences. This function is invoked when an interactive\n * \":command\" is called, or when reading ~/.redisclirc file, in order to\n * set user preferences. */\nvoid cliSetPreferences(char **argv, int argc, int interactive) {\n    if (!strcasecmp(argv[0],\":set\") && argc >= 2) {\n        if (!strcasecmp(argv[1],\"hints\")) pref.hints = 1;\n        else if (!strcasecmp(argv[1],\"nohints\")) pref.hints = 0;\n        else {\n            printf(\"%sunknown redis-cli preference '%s'\\n\",\n                interactive ? \"\" : \".redisclirc: \",\n                argv[1]);\n        }\n    } else {\n        printf(\"%sunknown redis-cli internal command '%s'\\n\",\n            interactive ? \"\" : \".redisclirc: \",\n            argv[0]);\n    }\n}\n\n/* Load the ~/.redisclirc file if any. */\nvoid cliLoadPreferences(void) {\n    sds rcfile = getDotfilePath(REDIS_CLI_RCFILE_ENV,REDIS_CLI_RCFILE_DEFAULT);\n    if (rcfile == NULL) return;\n    FILE *fp = fopen(rcfile,\"r\");\n    char buf[1024];\n\n    if (fp) {\n        while(fgets(buf,sizeof(buf),fp) != NULL) {\n            sds *argv;\n            int argc;\n\n            argv = sdssplitargs(buf,&argc);\n            if (argc > 0) cliSetPreferences(argv,argc,0);\n            sdsfreesplitres(argv,argc);\n        }\n    }\n    sdsfree(rcfile);\n}\n\nstatic void repl(void) {\n    sds historyfile = NULL;\n    int history = 0;\n    char *line;\n    int argc;\n    sds *argv;\n\n    config.interactive = 1;\n    linenoiseSetMultiLine(1);\n    linenoiseSetCompletionCallback(completionCallback);\n    linenoiseSetHintsCallback(hintsCallback);\n    linenoiseSetFreeHintsCallback(freeHintsCallback);\n\n    /* Only use history and load the rc file when stdin is a tty. */\n    if (isatty(fileno(stdin))) {\n        historyfile = getDotfilePath(REDIS_CLI_HISTFILE_ENV,REDIS_CLI_HISTFILE_DEFAULT);\n        if (historyfile != NULL) {\n            history = 1;\n            linenoiseHistoryLoad(historyfile);\n        }\n        cliLoadPreferences();\n    }\n\n    cliRefreshPrompt();\n    while((line = linenoise(context ? config.prompt : \"not connected> \")) != NULL) {\n        if (line[0] != '\\0') {\n            argv = cliSplitArgs(line,&argc);\n            if (history) linenoiseHistoryAdd(line);\n            if (historyfile) linenoiseHistorySave(historyfile);\n\n            if (argv == NULL) {\n                printf(\"Invalid argument(s)\\n\");\n                linenoiseFree(line);\n                continue;\n            } else if (argc > 0) {\n                if (strcasecmp(argv[0],\"quit\") == 0 ||\n                    strcasecmp(argv[0],\"exit\") == 0)\n                {\n                    exit(0);\n                } else if (argv[0][0] == ':') {\n                    cliSetPreferences(argv,argc,1);\n                    continue;\n                } else if (strcasecmp(argv[0],\"restart\") == 0) {\n                    if (config.eval) {\n                        config.eval_ldb = 1;\n                        config.output = OUTPUT_RAW;\n                        return; /* Return to evalMode to restart the session. */\n                    } else {\n                        printf(\"Use 'restart' only in Lua debugging mode.\");\n                    }\n                } else if (argc == 3 && !strcasecmp(argv[0],\"connect\")) {\n                    sdsfree(config.hostip);\n                    config.hostip = sdsnew(argv[1]);\n                    config.hostport = atoi(argv[2]);\n                    cliRefreshPrompt();\n                    cliConnect(1);\n                } else if (argc == 1 && !strcasecmp(argv[0],\"clear\")) {\n                    linenoiseClearScreen();\n                } else {\n                    long long start_time = mstime(), elapsed;\n                    int repeat, skipargs = 0;\n\n                    repeat = atoi(argv[0]);\n                    if (argc > 1 && repeat) {\n                        skipargs = 1;\n                    } else {\n                        repeat = 1;\n                    }\n\n                    issueCommandRepeat(argc-skipargs, argv+skipargs, repeat);\n\n                    /* If our debugging session ended, show the EVAL final\n                     * reply. */\n                    if (config.eval_ldb_end) {\n                        config.eval_ldb_end = 0;\n                        cliReadReply(0);\n                        printf(\"\\n(Lua debugging session ended%s)\\n\\n\",\n                            config.eval_ldb_sync ? \"\" :\n                            \" -- dataset changes rolled back\");\n                    }\n\n                    elapsed = mstime()-start_time;\n                    if (elapsed >= 500) {\n                        printf(\"(%.2fs)\\n\",(double)elapsed/1000);\n                    }\n                }\n            }\n            /* Free the argument vector */\n            sdsfreesplitres(argv,argc);\n        }\n        /* linenoise() returns malloc-ed lines like readline() */\n        linenoiseFree(line);\n    }\n    exit(0);\n}\n\nstatic int noninteractive(int argc, char **argv) {\n    int retval = 0;\n    if (config.stdinarg) {\n        argv = zrealloc(argv, (argc+1)*sizeof(char*));\n        argv[argc] = readArgFromStdin();\n        retval = issueCommand(argc+1, argv);\n    } else {\n        retval = issueCommand(argc, argv);\n    }\n    return retval;\n}\n\n/*------------------------------------------------------------------------------\n * Eval mode\n *--------------------------------------------------------------------------- */\n\nstatic int evalMode(int argc, char **argv) {\n    sds script = NULL;\n    FILE *fp;\n    char buf[1024];\n    size_t nread;\n    char **argv2;\n    int j, got_comma, keys;\n    int retval = REDIS_OK;\n\n    while(1) {\n        if (config.eval_ldb) {\n            printf(\n            \"Lua debugging session started, please use:\\n\"\n            \"quit    -- End the session.\\n\"\n            \"restart -- Restart the script in debug mode again.\\n\"\n            \"help    -- Show Lua script debugging commands.\\n\\n\"\n            );\n        }\n\n        sdsfree(script);\n        script = sdsempty();\n        got_comma = 0;\n        keys = 0;\n\n        /* Load the script from the file, as an sds string. */\n        fp = fopen(config.eval,\"r\");\n        if (!fp) {\n            fprintf(stderr,\n                \"Can't open file '%s': %s\\n\", config.eval, strerror(errno));\n            exit(1);\n        }\n        while((nread = fread(buf,1,sizeof(buf),fp)) != 0) {\n            script = sdscatlen(script,buf,nread);\n        }\n        fclose(fp);\n\n        /* If we are debugging a script, enable the Lua debugger. */\n        if (config.eval_ldb) {\n            redisReply *reply = redisCommand(context,\n                    config.eval_ldb_sync ?\n                    \"SCRIPT DEBUG sync\": \"SCRIPT DEBUG yes\");\n            if (reply) freeReplyObject(reply);\n        }\n\n        /* Create our argument vector */\n        argv2 = zmalloc(sizeof(sds)*(argc+3));\n        argv2[0] = sdsnew(\"EVAL\");\n        argv2[1] = script;\n        for (j = 0; j < argc; j++) {\n            if (!got_comma && argv[j][0] == ',' && argv[j][1] == 0) {\n                got_comma = 1;\n                continue;\n            }\n            argv2[j+3-got_comma] = sdsnew(argv[j]);\n            if (!got_comma) keys++;\n        }\n        argv2[2] = sdscatprintf(sdsempty(),\"%d\",keys);\n\n        /* Call it */\n        int eval_ldb = config.eval_ldb; /* Save it, may be reverteed. */\n        retval = issueCommand(argc+3-got_comma, argv2);\n        if (eval_ldb) {\n            if (!config.eval_ldb) {\n                /* If the debugging session ended immediately, there was an\n                 * error compiling the script. Show it and don't enter\n                 * the REPL at all. */\n                printf(\"Eval debugging session can't start:\\n\");\n                cliReadReply(0);\n                break; /* Return to the caller. */\n            } else {\n                strncpy(config.prompt,\"lua debugger> \",sizeof(config.prompt));\n                repl();\n                /* Restart the session if repl() returned. */\n                cliConnect(1);\n                printf(\"\\n\");\n            }\n        } else {\n            break; /* Return to the caller. */\n        }\n    }\n    return retval;\n}\n\n/*------------------------------------------------------------------------------\n * Latency and latency history modes\n *--------------------------------------------------------------------------- */\n\n#define LATENCY_SAMPLE_RATE 10 /* milliseconds. */\n#define LATENCY_HISTORY_DEFAULT_INTERVAL 15000 /* milliseconds. */\nstatic void latencyMode(void) {\n    redisReply *reply;\n    long long start, latency, min = 0, max = 0, tot = 0, count = 0;\n    long long history_interval =\n        config.interval ? config.interval/1000 :\n                          LATENCY_HISTORY_DEFAULT_INTERVAL;\n    double avg;\n    long long history_start = mstime();\n\n    if (!context) exit(1);\n    while(1) {\n        start = mstime();\n        reply = reconnectingRedisCommand(context,\"PING\");\n        if (reply == NULL) {\n            fprintf(stderr,\"\\nI/O error\\n\");\n            exit(1);\n        }\n        latency = mstime()-start;\n        freeReplyObject(reply);\n        count++;\n        if (count == 1) {\n            min = max = tot = latency;\n            avg = (double) latency;\n        } else {\n            if (latency < min) min = latency;\n            if (latency > max) max = latency;\n            tot += latency;\n            avg = (double) tot/count;\n        }\n        printf(\"\\x1b[0G\\x1b[2Kmin: %lld, max: %lld, avg: %.2f (%lld samples)\",\n            min, max, avg, count);\n        fflush(stdout);\n        if (config.latency_history && mstime()-history_start > history_interval)\n        {\n            printf(\" -- %.2f seconds range\\n\", (float)(mstime()-history_start)/1000);\n            history_start = mstime();\n            min = max = tot = count = 0;\n        }\n        usleep(LATENCY_SAMPLE_RATE * 1000);\n    }\n}\n\n/*------------------------------------------------------------------------------\n * Latency distribution mode -- requires 256 colors xterm\n *--------------------------------------------------------------------------- */\n\n#define LATENCY_DIST_DEFAULT_INTERVAL 1000 /* milliseconds. */\n\n/* Structure to store samples distribution. */\nstruct distsamples {\n    long long max;   /* Max latency to fit into this interval (usec). */\n    long long count; /* Number of samples in this interval. */\n    int character;   /* Associated character in visualization. */\n};\n\n/* Helper function for latencyDistMode(). Performs the spectrum visualization\n * of the collected samples targeting an xterm 256 terminal.\n *\n * Takes an array of distsamples structures, ordered from smaller to bigger\n * 'max' value. Last sample max must be 0, to mean that it olds all the\n * samples greater than the previous one, and is also the stop sentinel.\n *\n * \"tot' is the total number of samples in the different buckets, so it\n * is the SUM(samples[i].conut) for i to 0 up to the max sample.\n *\n * As a side effect the function sets all the buckets count to 0. */\nvoid showLatencyDistSamples(struct distsamples *samples, long long tot) {\n    int j;\n\n     /* We convert samples into a index inside the palette\n     * proportional to the percentage a given bucket represents.\n     * This way intensity of the different parts of the spectrum\n     * don't change relative to the number of requests, which avoids to\n     * pollute the visualization with non-latency related info. */\n    printf(\"\\033[38;5;0m\"); /* Set foreground color to black. */\n    for (j = 0; ; j++) {\n        int coloridx =\n            ceil((float) samples[j].count / tot * (spectrum_palette_size-1));\n        int color = spectrum_palette[coloridx];\n        printf(\"\\033[48;5;%dm%c\", (int)color, samples[j].character);\n        samples[j].count = 0;\n        if (samples[j].max == 0) break; /* Last sample. */\n    }\n    printf(\"\\033[0m\\n\");\n    fflush(stdout);\n}\n\n/* Show the legend: different buckets values and colors meaning, so\n * that the spectrum is more easily readable. */\nvoid showLatencyDistLegend(void) {\n    int j;\n\n    printf(\"---------------------------------------------\\n\");\n    printf(\". - * #          .01 .125 .25 .5 milliseconds\\n\");\n    printf(\"1,2,3,...,9      from 1 to 9     milliseconds\\n\");\n    printf(\"A,B,C,D,E        10,20,30,40,50  milliseconds\\n\");\n    printf(\"F,G,H,I,J        .1,.2,.3,.4,.5       seconds\\n\");\n    printf(\"K,L,M,N,O,P,Q,?  1,2,4,8,16,30,60,>60 seconds\\n\");\n    printf(\"From 0 to 100%%: \");\n    for (j = 0; j < spectrum_palette_size; j++) {\n        printf(\"\\033[48;5;%dm \", spectrum_palette[j]);\n    }\n    printf(\"\\033[0m\\n\");\n    printf(\"---------------------------------------------\\n\");\n}\n\nstatic void latencyDistMode(void) {\n    redisReply *reply;\n    long long start, latency, count = 0;\n    long long history_interval =\n        config.interval ? config.interval/1000 :\n                          LATENCY_DIST_DEFAULT_INTERVAL;\n    long long history_start = ustime();\n    int j, outputs = 0;\n\n    struct distsamples samples[] = {\n        /* We use a mostly logarithmic scale, with certain linear intervals\n         * which are more interesting than others, like 1-10 milliseconds\n         * range. */\n        {10,0,'.'},         /* 0.01 ms */\n        {125,0,'-'},        /* 0.125 ms */\n        {250,0,'*'},        /* 0.25 ms */\n        {500,0,'#'},        /* 0.5 ms */\n        {1000,0,'1'},       /* 1 ms */\n        {2000,0,'2'},       /* 2 ms */\n        {3000,0,'3'},       /* 3 ms */\n        {4000,0,'4'},       /* 4 ms */\n        {5000,0,'5'},       /* 5 ms */\n        {6000,0,'6'},       /* 6 ms */\n        {7000,0,'7'},       /* 7 ms */\n        {8000,0,'8'},       /* 8 ms */\n        {9000,0,'9'},       /* 9 ms */\n        {10000,0,'A'},      /* 10 ms */\n        {20000,0,'B'},      /* 20 ms */\n        {30000,0,'C'},      /* 30 ms */\n        {40000,0,'D'},      /* 40 ms */\n        {50000,0,'E'},      /* 50 ms */\n        {100000,0,'F'},     /* 0.1 s */\n        {200000,0,'G'},     /* 0.2 s */\n        {300000,0,'H'},     /* 0.3 s */\n        {400000,0,'I'},     /* 0.4 s */\n        {500000,0,'J'},     /* 0.5 s */\n        {1000000,0,'K'},    /* 1 s */\n        {2000000,0,'L'},    /* 2 s */\n        {4000000,0,'M'},    /* 4 s */\n        {8000000,0,'N'},    /* 8 s */\n        {16000000,0,'O'},   /* 16 s */\n        {30000000,0,'P'},   /* 30 s */\n        {60000000,0,'Q'},   /* 1 minute */\n        {0,0,'?'},          /* > 1 minute */\n    };\n\n    if (!context) exit(1);\n    while(1) {\n        start = ustime();\n        reply = reconnectingRedisCommand(context,\"PING\");\n        if (reply == NULL) {\n            fprintf(stderr,\"\\nI/O error\\n\");\n            exit(1);\n        }\n        latency = ustime()-start;\n        freeReplyObject(reply);\n        count++;\n\n        /* Populate the relevant bucket. */\n        for (j = 0; ; j++) {\n            if (samples[j].max == 0 || latency <= samples[j].max) {\n                samples[j].count++;\n                break;\n            }\n        }\n\n        /* From time to time show the spectrum. */\n        if (count && (ustime()-history_start)/1000 > history_interval) {\n            if ((outputs++ % 20) == 0)\n                showLatencyDistLegend();\n            showLatencyDistSamples(samples,count);\n            history_start = ustime();\n            count = 0;\n        }\n        usleep(LATENCY_SAMPLE_RATE * 1000);\n    }\n}\n\n/*------------------------------------------------------------------------------\n * Slave mode\n *--------------------------------------------------------------------------- */\n\n/* Sends SYNC and reads the number of bytes in the payload. Used both by\n * slaveMode() and getRDB(). */\nunsigned long long sendSync(int fd) {\n    /* To start we need to send the SYNC command and return the payload.\n     * The hiredis client lib does not understand this part of the protocol\n     * and we don't want to mess with its buffers, so everything is performed\n     * using direct low-level I/O. */\n    char buf[4096], *p;\n    ssize_t nread;\n\n    /* Send the SYNC command. */\n    if (write(fd,\"SYNC\\r\\n\",6) != 6) {\n        fprintf(stderr,\"Error writing to master\\n\");\n        exit(1);\n    }\n\n    /* Read $<payload>\\r\\n, making sure to read just up to \"\\n\" */\n    p = buf;\n    while(1) {\n        nread = read(fd,p,1);\n        if (nread <= 0) {\n            fprintf(stderr,\"Error reading bulk length while SYNCing\\n\");\n            exit(1);\n        }\n        if (*p == '\\n' && p != buf) break;\n        if (*p != '\\n') p++;\n    }\n    *p = '\\0';\n    if (buf[0] == '-') {\n        printf(\"SYNC with master failed: %s\\n\", buf);\n        exit(1);\n    }\n    return strtoull(buf+1,NULL,10);\n}\n\nstatic void slaveMode(void) {\n    int fd = context->fd;\n    unsigned long long payload = sendSync(fd);\n    char buf[1024];\n    int original_output = config.output;\n\n    fprintf(stderr,\"SYNC with master, discarding %llu \"\n                   \"bytes of bulk transfer...\\n\", payload);\n\n    /* Discard the payload. */\n    while(payload) {\n        ssize_t nread;\n\n        nread = read(fd,buf,(payload > sizeof(buf)) ? sizeof(buf) : payload);\n        if (nread <= 0) {\n            fprintf(stderr,\"Error reading RDB payload while SYNCing\\n\");\n            exit(1);\n        }\n        payload -= nread;\n    }\n    fprintf(stderr,\"SYNC done. Logging commands from master.\\n\");\n\n    /* Now we can use hiredis to read the incoming protocol. */\n    config.output = OUTPUT_CSV;\n    while (cliReadReply(0) == REDIS_OK);\n    config.output = original_output;\n}\n\n/*------------------------------------------------------------------------------\n * RDB transfer mode\n *--------------------------------------------------------------------------- */\n\n/* This function implements --rdb, so it uses the replication protocol in order\n * to fetch the RDB file from a remote server. */\nstatic void getRDB(void) {\n    int s = context->fd;\n    int fd;\n    unsigned long long payload = sendSync(s);\n    char buf[4096];\n\n    fprintf(stderr,\"SYNC sent to master, writing %llu bytes to '%s'\\n\",\n        payload, config.rdb_filename);\n\n    /* Write to file. */\n    if (!strcmp(config.rdb_filename,\"-\")) {\n        fd = STDOUT_FILENO;\n    } else {\n        fd = open(config.rdb_filename, O_CREAT|O_WRONLY, 0644);\n        if (fd == -1) {\n            fprintf(stderr, \"Error opening '%s': %s\\n\", config.rdb_filename,\n                strerror(errno));\n            exit(1);\n        }\n    }\n\n    while(payload) {\n        ssize_t nread, nwritten;\n\n        nread = read(s,buf,(payload > sizeof(buf)) ? sizeof(buf) : payload);\n        if (nread <= 0) {\n            fprintf(stderr,\"I/O Error reading RDB payload from socket\\n\");\n            exit(1);\n        }\n        nwritten = write(fd, buf, nread);\n        if (nwritten != nread) {\n            fprintf(stderr,\"Error writing data to file: %s\\n\",\n                strerror(errno));\n            exit(1);\n        }\n        payload -= nread;\n    }\n    close(s); /* Close the file descriptor ASAP as fsync() may take time. */\n    fsync(fd);\n    fprintf(stderr,\"Transfer finished with success.\\n\");\n    exit(0);\n}\n\n/*------------------------------------------------------------------------------\n * Bulk import (pipe) mode\n *--------------------------------------------------------------------------- */\n\n#define PIPEMODE_WRITE_LOOP_MAX_BYTES (128*1024)\nstatic void pipeMode(void) {\n    int fd = context->fd;\n    long long errors = 0, replies = 0, obuf_len = 0, obuf_pos = 0;\n    char ibuf[1024*16], obuf[1024*16]; /* Input and output buffers */\n    char aneterr[ANET_ERR_LEN];\n    redisReader *reader = redisReaderCreate();\n    redisReply *reply;\n    int eof = 0; /* True once we consumed all the standard input. */\n    int done = 0;\n    char magic[20]; /* Special reply we recognize. */\n    time_t last_read_time = time(NULL);\n\n    srand(time(NULL));\n\n    /* Use non blocking I/O. */\n    if (anetNonBlock(aneterr,fd) == ANET_ERR) {\n        fprintf(stderr, \"Can't set the socket in non blocking mode: %s\\n\",\n            aneterr);\n        exit(1);\n    }\n\n    /* Transfer raw protocol and read replies from the server at the same\n     * time. */\n    while(!done) {\n        int mask = AE_READABLE;\n\n        if (!eof || obuf_len != 0) mask |= AE_WRITABLE;\n        mask = aeWait(fd,mask,1000);\n\n        /* Handle the readable state: we can read replies from the server. */\n        if (mask & AE_READABLE) {\n            ssize_t nread;\n\n            /* Read from socket and feed the hiredis reader. */\n            do {\n                nread = read(fd,ibuf,sizeof(ibuf));\n                if (nread == -1 && errno != EAGAIN && errno != EINTR) {\n                    fprintf(stderr, \"Error reading from the server: %s\\n\",\n                        strerror(errno));\n                    exit(1);\n                }\n                if (nread > 0) {\n                    redisReaderFeed(reader,ibuf,nread);\n                    last_read_time = time(NULL);\n                }\n            } while(nread > 0);\n\n            /* Consume replies. */\n            do {\n                if (redisReaderGetReply(reader,(void**)&reply) == REDIS_ERR) {\n                    fprintf(stderr, \"Error reading replies from server\\n\");\n                    exit(1);\n                }\n                if (reply) {\n                    if (reply->type == REDIS_REPLY_ERROR) {\n                        fprintf(stderr,\"%s\\n\", reply->str);\n                        errors++;\n                    } else if (eof && reply->type == REDIS_REPLY_STRING &&\n                                      reply->len == 20) {\n                        /* Check if this is the reply to our final ECHO\n                         * command. If so everything was received\n                         * from the server. */\n                        if (memcmp(reply->str,magic,20) == 0) {\n                            printf(\"Last reply received from server.\\n\");\n                            done = 1;\n                            replies--;\n                        }\n                    }\n                    replies++;\n                    freeReplyObject(reply);\n                }\n            } while(reply);\n        }\n\n        /* Handle the writable state: we can send protocol to the server. */\n        if (mask & AE_WRITABLE) {\n            ssize_t loop_nwritten = 0;\n\n            while(1) {\n                /* Transfer current buffer to server. */\n                if (obuf_len != 0) {\n                    ssize_t nwritten = write(fd,obuf+obuf_pos,obuf_len);\n\n                    if (nwritten == -1) {\n                        if (errno != EAGAIN && errno != EINTR) {\n                            fprintf(stderr, \"Error writing to the server: %s\\n\",\n                                strerror(errno));\n                            exit(1);\n                        } else {\n                            nwritten = 0;\n                        }\n                    }\n                    obuf_len -= nwritten;\n                    obuf_pos += nwritten;\n                    loop_nwritten += nwritten;\n                    if (obuf_len != 0) break; /* Can't accept more data. */\n                }\n                /* If buffer is empty, load from stdin. */\n                if (obuf_len == 0 && !eof) {\n                    ssize_t nread = read(STDIN_FILENO,obuf,sizeof(obuf));\n\n                    if (nread == 0) {\n                        /* The ECHO sequence starts with a \"\\r\\n\" so that if there\n                         * is garbage in the protocol we read from stdin, the ECHO\n                         * will likely still be properly formatted.\n                         * CRLF is ignored by Redis, so it has no effects. */\n                        char echo[] =\n                        \"\\r\\n*2\\r\\n$4\\r\\nECHO\\r\\n$20\\r\\n01234567890123456789\\r\\n\";\n                        int j;\n\n                        eof = 1;\n                        /* Everything transferred, so we queue a special\n                         * ECHO command that we can match in the replies\n                         * to make sure everything was read from the server. */\n                        for (j = 0; j < 20; j++)\n                            magic[j] = rand() & 0xff;\n                        memcpy(echo+21,magic,20);\n                        memcpy(obuf,echo,sizeof(echo)-1);\n                        obuf_len = sizeof(echo)-1;\n                        obuf_pos = 0;\n                        printf(\"All data transferred. Waiting for the last reply...\\n\");\n                    } else if (nread == -1) {\n                        fprintf(stderr, \"Error reading from stdin: %s\\n\",\n                            strerror(errno));\n                        exit(1);\n                    } else {\n                        obuf_len = nread;\n                        obuf_pos = 0;\n                    }\n                }\n                if ((obuf_len == 0 && eof) ||\n                    loop_nwritten > PIPEMODE_WRITE_LOOP_MAX_BYTES) break;\n            }\n        }\n\n        /* Handle timeout, that is, we reached EOF, and we are not getting\n         * replies from the server for a few seconds, nor the final ECHO is\n         * received. */\n        if (eof && config.pipe_timeout > 0 &&\n            time(NULL)-last_read_time > config.pipe_timeout)\n        {\n            fprintf(stderr,\"No replies for %d seconds: exiting.\\n\",\n                config.pipe_timeout);\n            errors++;\n            break;\n        }\n    }\n    redisReaderFree(reader);\n    printf(\"errors: %lld, replies: %lld\\n\", errors, replies);\n    if (errors)\n        exit(1);\n    else\n        exit(0);\n}\n\n/*------------------------------------------------------------------------------\n * Find big keys\n *--------------------------------------------------------------------------- */\n\n#define TYPE_STRING 0\n#define TYPE_LIST   1\n#define TYPE_SET    2\n#define TYPE_HASH   3\n#define TYPE_ZSET   4\n#define TYPE_NONE   5\n\nstatic redisReply *sendScan(unsigned long long *it) {\n    redisReply *reply = redisCommand(context, \"SCAN %llu\", *it);\n\n    /* Handle any error conditions */\n    if(reply == NULL) {\n        fprintf(stderr, \"\\nI/O error\\n\");\n        exit(1);\n    } else if(reply->type == REDIS_REPLY_ERROR) {\n        fprintf(stderr, \"SCAN error: %s\\n\", reply->str);\n        exit(1);\n    } else if(reply->type != REDIS_REPLY_ARRAY) {\n        fprintf(stderr, \"Non ARRAY response from SCAN!\\n\");\n        exit(1);\n    } else if(reply->elements != 2) {\n        fprintf(stderr, \"Invalid element count from SCAN!\\n\");\n        exit(1);\n    }\n\n    /* Validate our types are correct */\n    assert(reply->element[0]->type == REDIS_REPLY_STRING);\n    assert(reply->element[1]->type == REDIS_REPLY_ARRAY);\n\n    /* Update iterator */\n    *it = strtoull(reply->element[0]->str, NULL, 10);\n\n    return reply;\n}\n\nstatic int getDbSize(void) {\n    redisReply *reply;\n    int size;\n\n    reply = redisCommand(context, \"DBSIZE\");\n\n    if(reply == NULL || reply->type != REDIS_REPLY_INTEGER) {\n        fprintf(stderr, \"Couldn't determine DBSIZE!\\n\");\n        exit(1);\n    }\n\n    /* Grab the number of keys and free our reply */\n    size = reply->integer;\n    freeReplyObject(reply);\n\n    return size;\n}\n\nstatic int toIntType(char *key, char *type) {\n    if(!strcmp(type, \"string\")) {\n        return TYPE_STRING;\n    } else if(!strcmp(type, \"list\")) {\n        return TYPE_LIST;\n    } else if(!strcmp(type, \"set\")) {\n        return TYPE_SET;\n    } else if(!strcmp(type, \"hash\")) {\n        return TYPE_HASH;\n    } else if(!strcmp(type, \"zset\")) {\n        return TYPE_ZSET;\n    } else if(!strcmp(type, \"none\")) {\n        return TYPE_NONE;\n    } else {\n        fprintf(stderr, \"Unknown type '%s' for key '%s'\\n\", type, key);\n        exit(1);\n    }\n}\n\nstatic void getKeyTypes(redisReply *keys, int *types) {\n    redisReply *reply;\n    unsigned int i;\n\n    /* Pipeline TYPE commands */\n    for(i=0;i<keys->elements;i++) {\n        redisAppendCommand(context, \"TYPE %s\", keys->element[i]->str);\n    }\n\n    /* Retrieve types */\n    for(i=0;i<keys->elements;i++) {\n        if(redisGetReply(context, (void**)&reply)!=REDIS_OK) {\n            fprintf(stderr, \"Error getting type for key '%s' (%d: %s)\\n\",\n                keys->element[i]->str, context->err, context->errstr);\n            exit(1);\n        } else if(reply->type != REDIS_REPLY_STATUS) {\n            fprintf(stderr, \"Invalid reply type (%d) for TYPE on key '%s'!\\n\",\n                reply->type, keys->element[i]->str);\n            exit(1);\n        }\n\n        types[i] = toIntType(keys->element[i]->str, reply->str);\n        freeReplyObject(reply);\n    }\n}\n\nstatic void getKeySizes(redisReply *keys, int *types,\n                        unsigned long long *sizes)\n{\n    redisReply *reply;\n    char *sizecmds[] = {\"STRLEN\",\"LLEN\",\"SCARD\",\"HLEN\",\"ZCARD\"};\n    unsigned int i;\n\n    /* Pipeline size commands */\n    for(i=0;i<keys->elements;i++) {\n        /* Skip keys that were deleted */\n        if(types[i]==TYPE_NONE)\n            continue;\n\n        redisAppendCommand(context, \"%s %s\", sizecmds[types[i]],\n            keys->element[i]->str);\n    }\n\n    /* Retreive sizes */\n    for(i=0;i<keys->elements;i++) {\n        /* Skip keys that dissapeared between SCAN and TYPE */\n        if(types[i] == TYPE_NONE) {\n            sizes[i] = 0;\n            continue;\n        }\n\n        /* Retreive size */\n        if(redisGetReply(context, (void**)&reply)!=REDIS_OK) {\n            fprintf(stderr, \"Error getting size for key '%s' (%d: %s)\\n\",\n                keys->element[i]->str, context->err, context->errstr);\n            exit(1);\n        } else if(reply->type != REDIS_REPLY_INTEGER) {\n            /* Theoretically the key could have been removed and\n             * added as a different type between TYPE and SIZE */\n            fprintf(stderr,\n                \"Warning:  %s on '%s' failed (may have changed type)\\n\",\n                 sizecmds[types[i]], keys->element[i]->str);\n            sizes[i] = 0;\n        } else {\n            sizes[i] = reply->integer;\n        }\n\n        freeReplyObject(reply);\n    }\n}\n\nstatic void findBigKeys(void) {\n    unsigned long long biggest[5] = {0}, counts[5] = {0}, totalsize[5] = {0};\n    unsigned long long sampled = 0, total_keys, totlen=0, *sizes=NULL, it=0;\n    sds maxkeys[5] = {0};\n    char *typename[] = {\"string\",\"list\",\"set\",\"hash\",\"zset\"};\n    char *typeunit[] = {\"bytes\",\"items\",\"members\",\"fields\",\"members\"};\n    redisReply *reply, *keys;\n    unsigned int arrsize=0, i;\n    int type, *types=NULL;\n    double pct;\n\n    /* Total keys pre scanning */\n    total_keys = getDbSize();\n\n    /* Status message */\n    printf(\"\\n# Scanning the entire keyspace to find biggest keys as well as\\n\");\n    printf(\"# average sizes per key type.  You can use -i 0.1 to sleep 0.1 sec\\n\");\n    printf(\"# per 100 SCAN commands (not usually needed).\\n\\n\");\n\n    /* New up sds strings to keep track of overall biggest per type */\n    for(i=0;i<TYPE_NONE; i++) {\n        maxkeys[i] = sdsempty();\n        if(!maxkeys[i]) {\n            fprintf(stderr, \"Failed to allocate memory for largest key names!\\n\");\n            exit(1);\n        }\n    }\n\n    /* SCAN loop */\n    do {\n        /* Calculate approximate percentage completion */\n        pct = 100 * (double)sampled/total_keys;\n\n        /* Grab some keys and point to the keys array */\n        reply = sendScan(&it);\n        keys  = reply->element[1];\n\n        /* Reallocate our type and size array if we need to */\n        if(keys->elements > arrsize) {\n            types = zrealloc(types, sizeof(int)*keys->elements);\n            sizes = zrealloc(sizes, sizeof(unsigned long long)*keys->elements);\n\n            if(!types || !sizes) {\n                fprintf(stderr, \"Failed to allocate storage for keys!\\n\");\n                exit(1);\n            }\n\n            arrsize = keys->elements;\n        }\n\n        /* Retreive types and then sizes */\n        getKeyTypes(keys, types);\n        getKeySizes(keys, types, sizes);\n\n        /* Now update our stats */\n        for(i=0;i<keys->elements;i++) {\n            if((type = types[i]) == TYPE_NONE)\n                continue;\n\n            totalsize[type] += sizes[i];\n            counts[type]++;\n            totlen += keys->element[i]->len;\n            sampled++;\n\n            if(biggest[type]<sizes[i]) {\n                printf(\n                   \"[%05.2f%%] Biggest %-6s found so far '%s' with %llu %s\\n\",\n                   pct, typename[type], keys->element[i]->str, sizes[i],\n                   typeunit[type]);\n\n                /* Keep track of biggest key name for this type */\n                maxkeys[type] = sdscpy(maxkeys[type], keys->element[i]->str);\n                if(!maxkeys[type]) {\n                    fprintf(stderr, \"Failed to allocate memory for key!\\n\");\n                    exit(1);\n                }\n\n                /* Keep track of the biggest size for this type */\n                biggest[type] = sizes[i];\n            }\n\n            /* Update overall progress */\n            if(sampled % 1000000 == 0) {\n                printf(\"[%05.2f%%] Sampled %llu keys so far\\n\", pct, sampled);\n            }\n        }\n\n        /* Sleep if we've been directed to do so */\n        if(sampled && (sampled %100) == 0 && config.interval) {\n            usleep(config.interval);\n        }\n\n        freeReplyObject(reply);\n    } while(it != 0);\n\n    if(types) zfree(types);\n    if(sizes) zfree(sizes);\n\n    /* We're done */\n    printf(\"\\n-------- summary -------\\n\\n\");\n\n    printf(\"Sampled %llu keys in the keyspace!\\n\", sampled);\n    printf(\"Total key length in bytes is %llu (avg len %.2f)\\n\\n\",\n       totlen, totlen ? (double)totlen/sampled : 0);\n\n    /* Output the biggest keys we found, for types we did find */\n    for(i=0;i<TYPE_NONE;i++) {\n        if(sdslen(maxkeys[i])>0) {\n            printf(\"Biggest %6s found '%s' has %llu %s\\n\", typename[i], maxkeys[i],\n               biggest[i], typeunit[i]);\n        }\n    }\n\n    printf(\"\\n\");\n\n    for(i=0;i<TYPE_NONE;i++) {\n        printf(\"%llu %ss with %llu %s (%05.2f%% of keys, avg size %.2f)\\n\",\n           counts[i], typename[i], totalsize[i], typeunit[i],\n           sampled ? 100 * (double)counts[i]/sampled : 0,\n           counts[i] ? (double)totalsize[i]/counts[i] : 0);\n    }\n\n    /* Free sds strings containing max keys */\n    for(i=0;i<TYPE_NONE;i++) {\n        sdsfree(maxkeys[i]);\n    }\n\n    /* Success! */\n    exit(0);\n}\n\n/*------------------------------------------------------------------------------\n * Stats mode\n *--------------------------------------------------------------------------- */\n\n/* Return the specified INFO field from the INFO command output \"info\".\n * A new buffer is allocated for the result, that needs to be free'd.\n * If the field is not found NULL is returned. */\nstatic char *getInfoField(char *info, char *field) {\n    char *p = strstr(info,field);\n    char *n1, *n2;\n    char *result;\n\n    if (!p) return NULL;\n    p += strlen(field)+1;\n    n1 = strchr(p,'\\r');\n    n2 = strchr(p,',');\n    if (n2 && n2 < n1) n1 = n2;\n    result = zmalloc(sizeof(char)*(n1-p)+1);\n    memcpy(result,p,(n1-p));\n    result[n1-p] = '\\0';\n    return result;\n}\n\n/* Like the above function but automatically convert the result into\n * a long. On error (missing field) LONG_MIN is returned. */\nstatic long getLongInfoField(char *info, char *field) {\n    char *value = getInfoField(info,field);\n    long l;\n\n    if (!value) return LONG_MIN;\n    l = strtol(value,NULL,10);\n    zfree(value);\n    return l;\n}\n\n/* Convert number of bytes into a human readable string of the form:\n * 100B, 2G, 100M, 4K, and so forth. */\nvoid bytesToHuman(char *s, long long n) {\n    double d;\n\n    if (n < 0) {\n        *s = '-';\n        s++;\n        n = -n;\n    }\n    if (n < 1024) {\n        /* Bytes */\n        sprintf(s,\"%lldB\",n);\n        return;\n    } else if (n < (1024*1024)) {\n        d = (double)n/(1024);\n        sprintf(s,\"%.2fK\",d);\n    } else if (n < (1024LL*1024*1024)) {\n        d = (double)n/(1024*1024);\n        sprintf(s,\"%.2fM\",d);\n    } else if (n < (1024LL*1024*1024*1024)) {\n        d = (double)n/(1024LL*1024*1024);\n        sprintf(s,\"%.2fG\",d);\n    }\n}\n\nstatic void statMode(void) {\n    redisReply *reply;\n    long aux, requests = 0;\n    int i = 0;\n\n    while(1) {\n        char buf[64];\n        int j;\n\n        reply = reconnectingRedisCommand(context,\"INFO\");\n        if (reply->type == REDIS_REPLY_ERROR) {\n            printf(\"ERROR: %s\\n\", reply->str);\n            exit(1);\n        }\n\n        if ((i++ % 20) == 0) {\n            printf(\n\"------- data ------ --------------------- load -------------------- - child -\\n\"\n\"keys       mem      clients blocked requests            connections          \\n\");\n        }\n\n        /* Keys */\n        aux = 0;\n        for (j = 0; j < 20; j++) {\n            long k;\n\n            sprintf(buf,\"db%d:keys\",j);\n            k = getLongInfoField(reply->str,buf);\n            if (k == LONG_MIN) continue;\n            aux += k;\n        }\n        sprintf(buf,\"%ld\",aux);\n        printf(\"%-11s\",buf);\n\n        /* Used memory */\n        aux = getLongInfoField(reply->str,\"used_memory\");\n        bytesToHuman(buf,aux);\n        printf(\"%-8s\",buf);\n\n        /* Clients */\n        aux = getLongInfoField(reply->str,\"connected_clients\");\n        sprintf(buf,\"%ld\",aux);\n        printf(\" %-8s\",buf);\n\n        /* Blocked (BLPOPPING) Clients */\n        aux = getLongInfoField(reply->str,\"blocked_clients\");\n        sprintf(buf,\"%ld\",aux);\n        printf(\"%-8s\",buf);\n\n        /* Requets */\n        aux = getLongInfoField(reply->str,\"total_commands_processed\");\n        sprintf(buf,\"%ld (+%ld)\",aux,requests == 0 ? 0 : aux-requests);\n        printf(\"%-19s\",buf);\n        requests = aux;\n\n        /* Connections */\n        aux = getLongInfoField(reply->str,\"total_connections_received\");\n        sprintf(buf,\"%ld\",aux);\n        printf(\" %-12s\",buf);\n\n        /* Children */\n        aux = getLongInfoField(reply->str,\"bgsave_in_progress\");\n        aux |= getLongInfoField(reply->str,\"aof_rewrite_in_progress\") << 1;\n        aux |= getLongInfoField(reply->str,\"loading\") << 2;\n        switch(aux) {\n        case 0: break;\n        case 1:\n            printf(\"SAVE\");\n            break;\n        case 2:\n            printf(\"AOF\");\n            break;\n        case 3:\n            printf(\"SAVE+AOF\");\n            break;\n        case 4:\n            printf(\"LOAD\");\n            break;\n        }\n\n        printf(\"\\n\");\n        freeReplyObject(reply);\n        usleep(config.interval);\n    }\n}\n\n/*------------------------------------------------------------------------------\n * Scan mode\n *--------------------------------------------------------------------------- */\n\nstatic void scanMode(void) {\n    redisReply *reply;\n    unsigned long long cur = 0;\n\n    do {\n        if (config.pattern)\n            reply = redisCommand(context,\"SCAN %llu MATCH %s\",\n                cur,config.pattern);\n        else\n            reply = redisCommand(context,\"SCAN %llu\",cur);\n        if (reply == NULL) {\n            printf(\"I/O error\\n\");\n            exit(1);\n        } else if (reply->type == REDIS_REPLY_ERROR) {\n            printf(\"ERROR: %s\\n\", reply->str);\n            exit(1);\n        } else {\n            unsigned int j;\n\n            cur = strtoull(reply->element[0]->str,NULL,10);\n            for (j = 0; j < reply->element[1]->elements; j++)\n                printf(\"%s\\n\", reply->element[1]->element[j]->str);\n        }\n        freeReplyObject(reply);\n    } while(cur != 0);\n\n    exit(0);\n}\n\n/*------------------------------------------------------------------------------\n * LRU test mode\n *--------------------------------------------------------------------------- */\n\n/* Return an integer from min to max (both inclusive) using a power-law\n * distribution, depending on the value of alpha: the greater the alpha\n * the more bias towards lower values.\n *\n * With alpha = 6.2 the output follows the 80-20 rule where 20% of\n * the returned numbers will account for 80% of the frequency. */\nlong long powerLawRand(long long min, long long max, double alpha) {\n    double pl, r;\n\n    max += 1;\n    r = ((double)rand()) / RAND_MAX;\n    pl = pow(\n        ((pow(max,alpha+1) - pow(min,alpha+1))*r + pow(min,alpha+1)),\n        (1.0/(alpha+1)));\n    return (max-1-(long long)pl)+min;\n}\n\n/* Generates a key name among a set of lru_test_sample_size keys, using\n * an 80-20 distribution. */\nvoid LRUTestGenKey(char *buf, size_t buflen) {\n    snprintf(buf, buflen, \"lru:%lld\\n\",\n        powerLawRand(1, config.lru_test_sample_size, 6.2));\n}\n\n#define LRU_CYCLE_PERIOD 1000 /* 1000 milliseconds. */\n#define LRU_CYCLE_PIPELINE_SIZE 250\nstatic void LRUTestMode(void) {\n    redisReply *reply;\n    char key[128];\n    long long start_cycle;\n    int j;\n\n    srand(time(NULL)^getpid());\n    while(1) {\n        /* Perform cycles of 1 second with 50% writes and 50% reads.\n         * We use pipelining batching writes / reads N times per cycle in order\n         * to fill the target instance easily. */\n        start_cycle = mstime();\n        long long hits = 0, misses = 0;\n        while(mstime() - start_cycle < 1000) {\n            /* Write cycle. */\n            for (j = 0; j < LRU_CYCLE_PIPELINE_SIZE; j++) {\n                LRUTestGenKey(key,sizeof(key));\n                redisAppendCommand(context, \"SET %s val\",key);\n            }\n            for (j = 0; j < LRU_CYCLE_PIPELINE_SIZE; j++)\n                redisGetReply(context, (void**)&reply);\n\n            /* Read cycle. */\n            for (j = 0; j < LRU_CYCLE_PIPELINE_SIZE; j++) {\n                LRUTestGenKey(key,sizeof(key));\n                redisAppendCommand(context, \"GET %s\",key);\n            }\n            for (j = 0; j < LRU_CYCLE_PIPELINE_SIZE; j++) {\n                if (redisGetReply(context, (void**)&reply) == REDIS_OK) {\n                    switch(reply->type) {\n                        case REDIS_REPLY_ERROR:\n                            printf(\"%s\\n\", reply->str);\n                            break;\n                        case REDIS_REPLY_NIL:\n                            misses++;\n                            break;\n                        default:\n                            hits++;\n                            break;\n                    }\n                }\n            }\n\n            if (context->err) {\n                fprintf(stderr,\"I/O error during LRU test\\n\");\n                exit(1);\n            }\n        }\n        /* Print stats. */\n        printf(\n            \"%lld Gets/sec | Hits: %lld (%.2f%%) | Misses: %lld (%.2f%%)\\n\",\n            hits+misses,\n            hits, (double)hits/(hits+misses)*100,\n            misses, (double)misses/(hits+misses)*100);\n    }\n    exit(0);\n}\n\n/*------------------------------------------------------------------------------\n * Intrisic latency mode.\n *\n * Measure max latency of a running process that does not result from\n * syscalls. Basically this software should provide an hint about how much\n * time the kernel leaves the process without a chance to run.\n *--------------------------------------------------------------------------- */\n\n/* This is just some computation the compiler can't optimize out.\n * Should run in less than 100-200 microseconds even using very\n * slow hardware. Runs in less than 10 microseconds in modern HW. */\nunsigned long compute_something_fast(void) {\n    unsigned char s[256], i, j, t;\n    int count = 1000, k;\n    unsigned long output = 0;\n\n    for (k = 0; k < 256; k++) s[k] = k;\n\n    i = 0;\n    j = 0;\n    while(count--) {\n        i++;\n        j = j + s[i];\n        t = s[i];\n        s[i] = s[j];\n        s[j] = t;\n        output += s[(s[i]+s[j])&255];\n    }\n    return output;\n}\n\nstatic void intrinsicLatencyModeStop(int s) {\n    UNUSED(s);\n    force_cancel_loop = 1;\n}\n\nstatic void intrinsicLatencyMode(void) {\n    long long test_end, run_time, max_latency = 0, runs = 0;\n\n    run_time = config.intrinsic_latency_duration*1000000;\n    test_end = ustime() + run_time;\n    signal(SIGINT, intrinsicLatencyModeStop);\n\n    while(1) {\n        long long start, end, latency;\n\n        start = ustime();\n        compute_something_fast();\n        end = ustime();\n        latency = end-start;\n        runs++;\n        if (latency <= 0) continue;\n\n        /* Reporting */\n        if (latency > max_latency) {\n            max_latency = latency;\n            printf(\"Max latency so far: %lld microseconds.\\n\", max_latency);\n        }\n\n        double avg_us = (double)run_time/runs;\n        double avg_ns = avg_us * 1e3;\n        if (force_cancel_loop || end > test_end) {\n            printf(\"\\n%lld total runs \"\n                \"(avg latency: \"\n                \"%.4f microseconds / %.2f nanoseconds per run).\\n\",\n                runs, avg_us, avg_ns);\n            printf(\"Worst run took %.0fx longer than the average latency.\\n\",\n                max_latency / avg_us);\n            exit(0);\n        }\n    }\n}\n\n/*------------------------------------------------------------------------------\n * Program main()\n *--------------------------------------------------------------------------- */\n\nint main(int argc, char **argv) {\n    int firstarg;\n\n    config.hostip = sdsnew(\"127.0.0.1\");\n    config.hostport = 6379;\n    config.hostsocket = NULL;\n    config.repeat = 1;\n    config.interval = 0;\n    config.dbnum = 0;\n    config.interactive = 0;\n    config.shutdown = 0;\n    config.monitor_mode = 0;\n    config.pubsub_mode = 0;\n    config.latency_mode = 0;\n    config.latency_dist_mode = 0;\n    config.latency_history = 0;\n    config.lru_test_mode = 0;\n    config.lru_test_sample_size = 0;\n    config.cluster_mode = 0;\n    config.slave_mode = 0;\n    config.getrdb_mode = 0;\n    config.stat_mode = 0;\n    config.scan_mode = 0;\n    config.intrinsic_latency_mode = 0;\n    config.pattern = NULL;\n    config.rdb_filename = NULL;\n    config.pipe_mode = 0;\n    config.pipe_timeout = REDIS_CLI_DEFAULT_PIPE_TIMEOUT;\n    config.bigkeys = 0;\n    config.stdinarg = 0;\n    config.auth = NULL;\n    config.eval = NULL;\n    config.eval_ldb = 0;\n    config.eval_ldb_end = 0;\n    config.eval_ldb_sync = 0;\n    config.enable_ldb_on_eval = 0;\n    config.last_cmd_type = -1;\n\n    pref.hints = 1;\n\n    spectrum_palette = spectrum_palette_color;\n    spectrum_palette_size = spectrum_palette_color_size;\n\n    if (!isatty(fileno(stdout)) && (getenv(\"FAKETTY\") == NULL))\n        config.output = OUTPUT_RAW;\n    else\n        config.output = OUTPUT_STANDARD;\n    config.mb_delim = sdsnew(\"\\n\");\n\n    firstarg = parseOptions(argc,argv);\n    argc -= firstarg;\n    argv += firstarg;\n\n    /* Initialize the help and, if possible, use the COMMAND command in order\n     * to retrieve missing entries. */\n    cliInitHelp();\n    cliIntegrateHelp();\n\n    /* Latency mode */\n    if (config.latency_mode) {\n        if (cliConnect(0) == REDIS_ERR) exit(1);\n        latencyMode();\n    }\n\n    /* Latency distribution mode */\n    if (config.latency_dist_mode) {\n        if (cliConnect(0) == REDIS_ERR) exit(1);\n        latencyDistMode();\n    }\n\n    /* Slave mode */\n    if (config.slave_mode) {\n        if (cliConnect(0) == REDIS_ERR) exit(1);\n        slaveMode();\n    }\n\n    /* Get RDB mode. */\n    if (config.getrdb_mode) {\n        if (cliConnect(0) == REDIS_ERR) exit(1);\n        getRDB();\n    }\n\n    /* Pipe mode */\n    if (config.pipe_mode) {\n        if (cliConnect(0) == REDIS_ERR) exit(1);\n        pipeMode();\n    }\n\n    /* Find big keys */\n    if (config.bigkeys) {\n        if (cliConnect(0) == REDIS_ERR) exit(1);\n        findBigKeys();\n    }\n\n    /* Stat mode */\n    if (config.stat_mode) {\n        if (cliConnect(0) == REDIS_ERR) exit(1);\n        if (config.interval == 0) config.interval = 1000000;\n        statMode();\n    }\n\n    /* Scan mode */\n    if (config.scan_mode) {\n        if (cliConnect(0) == REDIS_ERR) exit(1);\n        scanMode();\n    }\n\n    /* LRU test mode */\n    if (config.lru_test_mode) {\n        if (cliConnect(0) == REDIS_ERR) exit(1);\n        LRUTestMode();\n    }\n\n    /* Intrinsic latency mode */\n    if (config.intrinsic_latency_mode) intrinsicLatencyMode();\n\n    /* Start interactive mode when no command is provided */\n    if (argc == 0 && !config.eval) {\n        /* Ignore SIGPIPE in interactive mode to force a reconnect */\n        signal(SIGPIPE, SIG_IGN);\n\n        /* Note that in repl mode we don't abort on connection error.\n         * A new attempt will be performed for every command send. */\n        cliConnect(0);\n        repl();\n    }\n\n    /* Otherwise, we have some arguments to execute */\n    if (cliConnect(0) != REDIS_OK) exit(1);\n    if (config.eval) {\n        return evalMode(argc,argv);\n    } else {\n        return noninteractive(argc,convertToSds(argc,argv));\n    }\n}\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/src/redis-trib.rb",
    "content": "#!/usr/bin/env ruby\n\n# TODO (temporary here, we'll move this into the Github issues once\n#       redis-trib initial implementation is completed).\n#\n# - Make sure that if the rehashing fails in the middle redis-trib will try\n#   to recover.\n# - When redis-trib performs a cluster check, if it detects a slot move in\n#   progress it should prompt the user to continue the move from where it\n#   stopped.\n# - Gracefully handle Ctrl+C in move_slot to prompt the user if really stop\n#   while rehashing, and performing the best cleanup possible if the user\n#   forces the quit.\n# - When doing \"fix\" set a global Fix to true, and prompt the user to\n#   fix the problem if automatically fixable every time there is something\n#   to fix. For instance:\n#   1) If there is a node that pretend to receive a slot, or to migrate a\n#      slot, but has no entries in that slot, fix it.\n#   2) If there is a node having keys in slots that are not owned by it\n#      fix this condition moving the entries in the same node.\n#   3) Perform more possibly slow tests about the state of the cluster.\n#   4) When aborted slot migration is detected, fix it.\n\nrequire 'rubygems'\nrequire 'redis'\n\nClusterHashSlots = 16384\nMigrateDefaultTimeout = 60000\nMigrateDefaultPipeline = 10\nRebalanceDefaultThreshold = 2\n\n$verbose = false\n\ndef xputs(s)\n    case s[0..2]\n    when \">>>\"\n        color=\"29;1\"\n    when \"[ER\"\n        color=\"31;1\"\n    when \"[WA\"\n        color=\"31;1\"\n    when \"[OK\"\n        color=\"32\"\n    when \"[FA\",\"***\"\n        color=\"33\"\n    else\n        color=nil\n    end\n\n    color = nil if ENV['TERM'] != \"xterm\"\n    print \"\\033[#{color}m\" if color\n    print s\n    print \"\\033[0m\" if color\n    print \"\\n\"\nend\n\nclass ClusterNode\n    def initialize(addr)\n        s = addr.split(\":\")\n        if s.length < 2\n           puts \"Invalid IP or Port (given as #{addr}) - use IP:Port format\"\n           exit 1\n        end\n        port = s.pop # removes port from split array\n        ip = s.join(\":\") # if s.length > 1 here, it's IPv6, so restore address\n        @r = nil\n        @info = {}\n        @info[:host] = ip\n        @info[:port] = port\n        @info[:slots] = {}\n        @info[:migrating] = {}\n        @info[:importing] = {}\n        @info[:replicate] = false\n        @dirty = false # True if we need to flush slots info into node.\n        @friends = []\n    end\n\n    def friends\n        @friends\n    end\n\n    def slots\n        @info[:slots]\n    end\n\n    def has_flag?(flag)\n        @info[:flags].index(flag)\n    end\n\n    def to_s\n        \"#{@info[:host]}:#{@info[:port]}\"\n    end\n\n    def connect(o={})\n        return if @r\n        print \"Connecting to node #{self}: \" if $verbose\n        STDOUT.flush\n        begin\n            @r = Redis.new(:host => @info[:host], :port => @info[:port], :timeout => 60)\n            @r.ping\n        rescue\n            xputs \"[ERR] Sorry, can't connect to node #{self}\"\n            exit 1 if o[:abort]\n            @r = nil\n        end\n        xputs \"OK\" if $verbose\n    end\n\n    def assert_cluster\n        info = @r.info\n        if !info[\"cluster_enabled\"] || info[\"cluster_enabled\"].to_i == 0\n            xputs \"[ERR] Node #{self} is not configured as a cluster node.\"\n            exit 1\n        end\n    end\n\n    def assert_empty\n        if !(@r.cluster(\"info\").split(\"\\r\\n\").index(\"cluster_known_nodes:1\")) ||\n            (@r.info['db0'])\n            xputs \"[ERR] Node #{self} is not empty. Either the node already knows other nodes (check with CLUSTER NODES) or contains some key in database 0.\"\n            exit 1\n        end\n    end\n\n    def load_info(o={})\n        self.connect\n        nodes = @r.cluster(\"nodes\").split(\"\\n\")\n        nodes.each{|n|\n            # name addr flags role ping_sent ping_recv link_status slots\n            split = n.split\n            name,addr,flags,master_id,ping_sent,ping_recv,config_epoch,link_status = split[0..6]\n            slots = split[8..-1]\n            info = {\n                :name => name,\n                :addr => addr,\n                :flags => flags.split(\",\"),\n                :replicate => master_id,\n                :ping_sent => ping_sent.to_i,\n                :ping_recv => ping_recv.to_i,\n                :link_status => link_status\n            }\n            info[:replicate] = false if master_id == \"-\"\n\n            if info[:flags].index(\"myself\")\n                @info = @info.merge(info)\n                @info[:slots] = {}\n                slots.each{|s|\n                    if s[0..0] == '['\n                        if s.index(\"->-\") # Migrating\n                            slot,dst = s[1..-1].split(\"->-\")\n                            @info[:migrating][slot.to_i] = dst\n                        elsif s.index(\"-<-\") # Importing\n                            slot,src = s[1..-1].split(\"-<-\")\n                            @info[:importing][slot.to_i] = src\n                        end\n                    elsif s.index(\"-\")\n                        start,stop = s.split(\"-\")\n                        self.add_slots((start.to_i)..(stop.to_i))\n                    else\n                        self.add_slots((s.to_i)..(s.to_i))\n                    end\n                } if slots\n                @dirty = false\n                @r.cluster(\"info\").split(\"\\n\").each{|e|\n                    k,v=e.split(\":\")\n                    k = k.to_sym\n                    v.chop!\n                    if k != :cluster_state\n                        @info[k] = v.to_i\n                    else\n                        @info[k] = v\n                    end\n                }\n            elsif o[:getfriends]\n                @friends << info\n            end\n        }\n    end\n\n    def add_slots(slots)\n        slots.each{|s|\n            @info[:slots][s] = :new\n        }\n        @dirty = true\n    end\n\n    def set_as_replica(node_id)\n        @info[:replicate] = node_id\n        @dirty = true\n    end\n\n    def flush_node_config\n        return if !@dirty\n        if @info[:replicate]\n            begin\n                @r.cluster(\"replicate\",@info[:replicate])\n            rescue\n                # If the cluster did not already joined it is possible that\n                # the slave does not know the master node yet. So on errors\n                # we return ASAP leaving the dirty flag set, to flush the\n                # config later.\n                return\n            end\n        else\n            new = []\n            @info[:slots].each{|s,val|\n                if val == :new\n                    new << s\n                    @info[:slots][s] = true\n                end\n            }\n            @r.cluster(\"addslots\",*new)\n        end\n        @dirty = false\n    end\n\n    def info_string\n        # We want to display the hash slots assigned to this node\n        # as ranges, like in: \"1-5,8-9,20-25,30\"\n        #\n        # Note: this could be easily written without side effects,\n        # we use 'slots' just to split the computation into steps.\n\n        # First step: we want an increasing array of integers\n        # for instance: [1,2,3,4,5,8,9,20,21,22,23,24,25,30]\n        slots = @info[:slots].keys.sort\n\n        # As we want to aggregate adjacent slots we convert all the\n        # slot integers into ranges (with just one element)\n        # So we have something like [1..1,2..2, ... and so forth.\n        slots.map!{|x| x..x}\n\n        # Finally we group ranges with adjacent elements.\n        slots = slots.reduce([]) {|a,b|\n            if !a.empty? && b.first == (a[-1].last)+1\n                a[0..-2] + [(a[-1].first)..(b.last)]\n            else\n                a + [b]\n            end\n        }\n\n        # Now our task is easy, we just convert ranges with just one\n        # element into a number, and a real range into a start-end format.\n        # Finally we join the array using the comma as separator.\n        slots = slots.map{|x|\n            x.count == 1 ? x.first.to_s : \"#{x.first}-#{x.last}\"\n        }.join(\",\")\n\n        role = self.has_flag?(\"master\") ? \"M\" : \"S\"\n\n        if self.info[:replicate] and @dirty\n            is = \"S: #{self.info[:name]} #{self.to_s}\"\n        else\n            is = \"#{role}: #{self.info[:name]} #{self.to_s}\\n\"+\n            \"   slots:#{slots} (#{self.slots.length} slots) \"+\n            \"#{(self.info[:flags]-[\"myself\"]).join(\",\")}\"\n        end\n        if self.info[:replicate]\n            is += \"\\n   replicates #{info[:replicate]}\"\n        elsif self.has_flag?(\"master\") && self.info[:replicas]\n            is += \"\\n   #{info[:replicas].length} additional replica(s)\"\n        end\n        is\n    end\n\n    # Return a single string representing nodes and associated slots.\n    # TODO: remove slaves from config when slaves will be handled\n    # by Redis Cluster.\n    def get_config_signature\n        config = []\n        @r.cluster(\"nodes\").each_line{|l|\n            s = l.split\n            slots = s[8..-1].select {|x| x[0..0] != \"[\"}\n            next if slots.length == 0\n            config << s[0]+\":\"+(slots.sort.join(\",\"))\n        }\n        config.sort.join(\"|\")\n    end\n\n    def info\n        @info\n    end\n\n    def is_dirty?\n        @dirty\n    end\n\n    def r\n        @r\n    end\nend\n\nclass RedisTrib\n    def initialize\n        @nodes = []\n        @fix = false\n        @errors = []\n        @timeout = MigrateDefaultTimeout\n    end\n\n    def check_arity(req_args, num_args)\n        if ((req_args > 0 and num_args != req_args) ||\n           (req_args < 0 and num_args < req_args.abs))\n           xputs \"[ERR] Wrong number of arguments for specified sub command\"\n           exit 1\n        end\n    end\n\n    def add_node(node)\n        @nodes << node\n    end\n\n    def reset_nodes\n        @nodes = []\n    end\n\n    def cluster_error(msg)\n        @errors << msg\n        xputs msg\n    end\n\n    # Return the node with the specified ID or Nil.\n    def get_node_by_name(name)\n        @nodes.each{|n|\n            return n if n.info[:name] == name.downcase\n        }\n        return nil\n    end\n\n    # Like get_node_by_name but the specified name can be just the first\n    # part of the node ID as long as the prefix in unique across the\n    # cluster.\n    def get_node_by_abbreviated_name(name)\n        l = name.length\n        candidates = []\n        @nodes.each{|n|\n            if n.info[:name][0...l] == name.downcase\n                candidates << n\n            end\n        }\n        return nil if candidates.length != 1\n        candidates[0]\n    end\n\n    # This function returns the master that has the least number of replicas\n    # in the cluster. If there are multiple masters with the same smaller\n    # number of replicas, one at random is returned.\n    def get_master_with_least_replicas\n        masters = @nodes.select{|n| n.has_flag? \"master\"}\n        sorted = masters.sort{|a,b|\n            a.info[:replicas].length <=> b.info[:replicas].length\n        }\n        sorted[0]\n    end\n\n    def check_cluster(opt={})\n        xputs \">>> Performing Cluster Check (using node #{@nodes[0]})\"\n        show_nodes if !opt[:quiet]\n        check_config_consistency\n        check_open_slots\n        check_slots_coverage\n    end\n\n    def show_cluster_info\n        masters = 0\n        keys = 0\n        @nodes.each{|n|\n            if n.has_flag?(\"master\")\n                puts \"#{n} (#{n.info[:name][0...8]}...) -> #{n.r.dbsize} keys | #{n.slots.length} slots | \"+\n                     \"#{n.info[:replicas].length} slaves.\"\n                masters += 1\n                keys += n.r.dbsize\n            end\n        }\n        xputs \"[OK] #{keys} keys in #{masters} masters.\"\n        keys_per_slot = sprintf(\"%.2f\",keys/16384.0)\n        puts \"#{keys_per_slot} keys per slot on average.\"\n    end\n\n    # Merge slots of every known node. If the resulting slots are equal\n    # to ClusterHashSlots, then all slots are served.\n    def covered_slots\n        slots = {}\n        @nodes.each{|n|\n            slots = slots.merge(n.slots)\n        }\n        slots\n    end\n\n    def check_slots_coverage\n        xputs \">>> Check slots coverage...\"\n        slots = covered_slots\n        if slots.length == ClusterHashSlots\n            xputs \"[OK] All #{ClusterHashSlots} slots covered.\"\n        else\n            cluster_error \\\n                \"[ERR] Not all #{ClusterHashSlots} slots are covered by nodes.\"\n            fix_slots_coverage if @fix\n        end\n    end\n\n    def check_open_slots\n        xputs \">>> Check for open slots...\"\n        open_slots = []\n        @nodes.each{|n|\n            if n.info[:migrating].size > 0\n                cluster_error \\\n                    \"[WARNING] Node #{n} has slots in migrating state (#{n.info[:migrating].keys.join(\",\")}).\"\n                open_slots += n.info[:migrating].keys\n            end\n            if n.info[:importing].size > 0\n                cluster_error \\\n                    \"[WARNING] Node #{n} has slots in importing state (#{n.info[:importing].keys.join(\",\")}).\"\n                open_slots += n.info[:importing].keys\n            end\n        }\n        open_slots.uniq!\n        if open_slots.length > 0\n            xputs \"[WARNING] The following slots are open: #{open_slots.join(\",\")}\"\n        end\n        if @fix\n            open_slots.each{|slot| fix_open_slot slot}\n        end\n    end\n\n    def nodes_with_keys_in_slot(slot)\n        nodes = []\n        @nodes.each{|n|\n            next if n.has_flag?(\"slave\")\n            nodes << n if n.r.cluster(\"getkeysinslot\",slot,1).length > 0\n        }\n        nodes\n    end\n\n    def fix_slots_coverage\n        not_covered = (0...ClusterHashSlots).to_a - covered_slots.keys\n        xputs \">>> Fixing slots coverage...\"\n        xputs \"List of not covered slots: \" + not_covered.join(\",\")\n\n        # For every slot, take action depending on the actual condition:\n        # 1) No node has keys for this slot.\n        # 2) A single node has keys for this slot.\n        # 3) Multiple nodes have keys for this slot.\n        slots = {}\n        not_covered.each{|slot|\n            nodes = nodes_with_keys_in_slot(slot)\n            slots[slot] = nodes\n            xputs \"Slot #{slot} has keys in #{nodes.length} nodes: #{nodes.join(\", \")}\"\n        }\n\n        none = slots.select {|k,v| v.length == 0}\n        single = slots.select {|k,v| v.length == 1}\n        multi = slots.select {|k,v| v.length > 1}\n\n        # Handle case \"1\": keys in no node.\n        if none.length > 0\n            xputs \"The folowing uncovered slots have no keys across the cluster:\"\n            xputs none.keys.join(\",\")\n            yes_or_die \"Fix these slots by covering with a random node?\"\n            none.each{|slot,nodes|\n                node = @nodes.sample\n                xputs \">>> Covering slot #{slot} with #{node}\"\n                node.r.cluster(\"addslots\",slot)\n            }\n        end\n\n        # Handle case \"2\": keys only in one node.\n        if single.length > 0\n            xputs \"The folowing uncovered slots have keys in just one node:\"\n            puts single.keys.join(\",\")\n            yes_or_die \"Fix these slots by covering with those nodes?\"\n            single.each{|slot,nodes|\n                xputs \">>> Covering slot #{slot} with #{nodes[0]}\"\n                nodes[0].r.cluster(\"addslots\",slot)\n            }\n        end\n\n        # Handle case \"3\": keys in multiple nodes.\n        if multi.length > 0\n            xputs \"The folowing uncovered slots have keys in multiple nodes:\"\n            xputs multi.keys.join(\",\")\n            yes_or_die \"Fix these slots by moving keys into a single node?\"\n            multi.each{|slot,nodes|\n                target = get_node_with_most_keys_in_slot(nodes,slot)\n                xputs \">>> Covering slot #{slot} moving keys to #{target}\"\n\n                target.r.cluster('addslots',slot)\n                target.r.cluster('setslot',slot,'stable')\n                nodes.each{|src|\n                    next if src == target\n                    # Set the source node in 'importing' state (even if we will\n                    # actually migrate keys away) in order to avoid receiving\n                    # redirections for MIGRATE.\n                    src.r.cluster('setslot',slot,'importing',target.info[:name])\n                    move_slot(src,target,slot,:dots=>true,:fix=>true,:cold=>true)\n                    src.r.cluster('setslot',slot,'stable')\n                }\n            }\n        end\n    end\n\n    # Return the owner of the specified slot\n    def get_slot_owners(slot)\n        owners = []\n        @nodes.each{|n|\n            next if n.has_flag?(\"slave\")\n            n.slots.each{|s,_|\n                owners << n if s == slot\n            }\n        }\n        owners\n    end\n\n    # Return the node, among 'nodes' with the greatest number of keys\n    # in the specified slot.\n    def get_node_with_most_keys_in_slot(nodes,slot)\n        best = nil\n        best_numkeys = 0\n        @nodes.each{|n|\n            next if n.has_flag?(\"slave\")\n            numkeys = n.r.cluster(\"countkeysinslot\",slot)\n            if numkeys > best_numkeys || best == nil\n                best = n\n                best_numkeys = numkeys\n            end\n        }\n        return best\n    end\n\n    # Slot 'slot' was found to be in importing or migrating state in one or\n    # more nodes. This function fixes this condition by migrating keys where\n    # it seems more sensible.\n    def fix_open_slot(slot)\n        puts \">>> Fixing open slot #{slot}\"\n\n        # Try to obtain the current slot owner, according to the current\n        # nodes configuration.\n        owners = get_slot_owners(slot)\n        owner = owners[0] if owners.length == 1\n\n        migrating = []\n        importing = []\n        @nodes.each{|n|\n            next if n.has_flag? \"slave\"\n            if n.info[:migrating][slot]\n                migrating << n\n            elsif n.info[:importing][slot]\n                importing << n\n            elsif n.r.cluster(\"countkeysinslot\",slot) > 0 && n != owner\n                xputs \"*** Found keys about slot #{slot} in node #{n}!\"\n                importing << n\n            end\n        }\n        puts \"Set as migrating in: #{migrating.join(\",\")}\"\n        puts \"Set as importing in: #{importing.join(\",\")}\"\n\n        # If there is no slot owner, set as owner the slot with the biggest\n        # number of keys, among the set of migrating / importing nodes.\n        if !owner\n            xputs \">>> Nobody claims ownership, selecting an owner...\"\n            owner = get_node_with_most_keys_in_slot(@nodes,slot)\n\n            # If we still don't have an owner, we can't fix it.\n            if !owner\n                xputs \"[ERR] Can't select a slot owner. Impossible to fix.\"\n                exit 1\n            end\n\n            # Use ADDSLOTS to assign the slot.\n            puts \"*** Configuring #{owner} as the slot owner\"\n            owner.r.cluster(\"setslot\",slot,\"stable\")\n            owner.r.cluster(\"addslots\",slot)\n            # Make sure this information will propagate. Not strictly needed\n            # since there is no past owner, so all the other nodes will accept\n            # whatever epoch this node will claim the slot with.\n            owner.r.cluster(\"bumpepoch\")\n\n            # Remove the owner from the list of migrating/importing\n            # nodes.\n            migrating.delete(owner)\n            importing.delete(owner)\n        end\n\n        # If there are multiple owners of the slot, we need to fix it\n        # so that a single node is the owner and all the other nodes\n        # are in importing state. Later the fix can be handled by one\n        # of the base cases above.\n        #\n        # Note that this case also covers multiple nodes having the slot\n        # in migrating state, since migrating is a valid state only for\n        # slot owners.\n        if owners.length > 1\n            owner = get_node_with_most_keys_in_slot(owners,slot)\n            owners.each{|n|\n                next if n == owner\n                n.r.cluster('delslots',slot)\n                n.r.cluster('setslot',slot,'importing',owner.info[:name])\n                importing.delete(n) # Avoid duplciates\n                importing << n\n            }\n            owner.r.cluster('bumpepoch')\n        end\n\n        # Case 1: The slot is in migrating state in one slot, and in\n        #         importing state in 1 slot. That's trivial to address.\n        if migrating.length == 1 && importing.length == 1\n            move_slot(migrating[0],importing[0],slot,:dots=>true,:fix=>true)\n        # Case 2: There are multiple nodes that claim the slot as importing,\n        # they probably got keys about the slot after a restart so opened\n        # the slot. In this case we just move all the keys to the owner\n        # according to the configuration.\n        elsif migrating.length == 0 && importing.length > 0\n            xputs \">>> Moving all the #{slot} slot keys to its owner #{owner}\"\n            importing.each {|node|\n                next if node == owner\n                move_slot(node,owner,slot,:dots=>true,:fix=>true,:cold=>true)\n                xputs \">>> Setting #{slot} as STABLE in #{node}\"\n                node.r.cluster(\"setslot\",slot,\"stable\")\n            }\n        # Case 3: There are no slots claiming to be in importing state, but\n        # there is a migrating node that actually don't have any key. We\n        # can just close the slot, probably a reshard interrupted in the middle.\n        elsif importing.length == 0 && migrating.length == 1 &&\n              migrating[0].r.cluster(\"getkeysinslot\",slot,10).length == 0\n            migrating[0].r.cluster(\"setslot\",slot,\"stable\")\n        else\n            xputs \"[ERR] Sorry, Redis-trib can't fix this slot yet (work in progress). Slot is set as migrating in #{migrating.join(\",\")}, as importing in #{importing.join(\",\")}, owner is #{owner}\"\n        end\n    end\n\n    # Check if all the nodes agree about the cluster configuration\n    def check_config_consistency\n        if !is_config_consistent?\n            cluster_error \"[ERR] Nodes don't agree about configuration!\"\n        else\n            xputs \"[OK] All nodes agree about slots configuration.\"\n        end\n    end\n\n    def is_config_consistent?\n        signatures=[]\n        @nodes.each{|n|\n            signatures << n.get_config_signature\n        }\n        return signatures.uniq.length == 1\n    end\n\n    def wait_cluster_join\n        print \"Waiting for the cluster to join\"\n        while !is_config_consistent?\n            print \".\"\n            STDOUT.flush\n            sleep 1\n        end\n        print \"\\n\"\n    end\n\n    def alloc_slots\n        nodes_count = @nodes.length\n        masters_count = @nodes.length / (@replicas+1)\n        masters = []\n\n        # The first step is to split instances by IP. This is useful as\n        # we'll try to allocate master nodes in different physical machines\n        # (as much as possible) and to allocate slaves of a given master in\n        # different physical machines as well.\n        #\n        # This code assumes just that if the IP is different, than it is more\n        # likely that the instance is running in a different physical host\n        # or at least a different virtual machine.\n        ips = {}\n        @nodes.each{|n|\n            ips[n.info[:host]] = [] if !ips[n.info[:host]]\n            ips[n.info[:host]] << n\n        }\n\n        # Select master instances\n        puts \"Using #{masters_count} masters:\"\n        interleaved = []\n        stop = false\n        while not stop do\n            # Take one node from each IP until we run out of nodes\n            # across every IP.\n            ips.each do |ip,nodes|\n                if nodes.empty?\n                    # if this IP has no remaining nodes, check for termination\n                    if interleaved.length == nodes_count\n                        # stop when 'interleaved' has accumulated all nodes\n                        stop = true\n                        next\n                    end\n                else\n                    # else, move one node from this IP to 'interleaved'\n                    interleaved.push nodes.shift\n                end\n            end\n        end\n\n        masters = interleaved.slice!(0, masters_count)\n        nodes_count -= masters.length\n\n        masters.each{|m| puts m}\n\n        # Alloc slots on masters\n        slots_per_node = ClusterHashSlots.to_f / masters_count\n        first = 0\n        cursor = 0.0\n        masters.each_with_index{|n,masternum|\n            last = (cursor+slots_per_node-1).round\n            if last > ClusterHashSlots || masternum == masters.length-1\n                last = ClusterHashSlots-1\n            end\n            last = first if last < first # Min step is 1.\n            n.add_slots first..last\n            first = last+1\n            cursor += slots_per_node\n        }\n\n        # Select N replicas for every master.\n        # We try to split the replicas among all the IPs with spare nodes\n        # trying to avoid the host where the master is running, if possible.\n        #\n        # Note we loop two times.  The first loop assigns the requested\n        # number of replicas to each master.  The second loop assigns any\n        # remaining instances as extra replicas to masters.  Some masters\n        # may end up with more than their requested number of replicas, but\n        # all nodes will be used.\n        assignment_verbose = false\n\n        [:requested,:unused].each do |assign|\n            masters.each do |m|\n                assigned_replicas = 0\n                while assigned_replicas < @replicas\n                    break if nodes_count == 0\n                    if assignment_verbose\n                        if assign == :requested\n                            puts \"Requesting total of #{@replicas} replicas \" \\\n                                 \"(#{assigned_replicas} replicas assigned \" \\\n                                 \"so far with #{nodes_count} total remaining).\"\n                        elsif assign == :unused\n                            puts \"Assigning extra instance to replication \" \\\n                                 \"role too (#{nodes_count} remaining).\"\n                        end\n                    end\n\n                    # Return the first node not matching our current master\n                    node = interleaved.find{|n| n.info[:host] != m.info[:host]}\n\n                    # If we found a node, use it as a best-first match.\n                    # Otherwise, we didn't find a node on a different IP, so we\n                    # go ahead and use a same-IP replica.\n                    if node\n                        slave = node\n                        interleaved.delete node\n                    else\n                        slave = interleaved.shift\n                    end\n                    slave.set_as_replica(m.info[:name])\n                    nodes_count -= 1\n                    assigned_replicas += 1\n                    puts \"Adding replica #{slave} to #{m}\"\n\n                    # If we are in the \"assign extra nodes\" loop,\n                    # we want to assign one extra replica to each\n                    # master before repeating masters.\n                    # This break lets us assign extra replicas to masters\n                    # in a round-robin way.\n                    break if assign == :unused\n                end\n            end\n        end\n    end\n\n    def flush_nodes_config\n        @nodes.each{|n|\n            n.flush_node_config\n        }\n    end\n\n    def show_nodes\n        @nodes.each{|n|\n            xputs n.info_string\n        }\n    end\n\n    # Redis Cluster config epoch collision resolution code is able to eventually\n    # set a different epoch to each node after a new cluster is created, but\n    # it is slow compared to assign a progressive config epoch to each node\n    # before joining the cluster. However we do just a best-effort try here\n    # since if we fail is not a problem.\n    def assign_config_epoch\n        config_epoch = 1\n        @nodes.each{|n|\n            begin\n                n.r.cluster(\"set-config-epoch\",config_epoch)\n            rescue\n            end\n            config_epoch += 1\n        }\n    end\n\n    def join_cluster\n        # We use a brute force approach to make sure the node will meet\n        # each other, that is, sending CLUSTER MEET messages to all the nodes\n        # about the very same node.\n        # Thanks to gossip this information should propagate across all the\n        # cluster in a matter of seconds.\n        first = false\n        @nodes.each{|n|\n            if !first then first = n.info; next; end # Skip the first node\n            n.r.cluster(\"meet\",first[:host],first[:port])\n        }\n    end\n\n    def yes_or_die(msg)\n        print \"#{msg} (type 'yes' to accept): \"\n        STDOUT.flush\n        if !(STDIN.gets.chomp.downcase == \"yes\")\n            xputs \"*** Aborting...\"\n            exit 1\n        end\n    end\n\n    def load_cluster_info_from_node(nodeaddr)\n        node = ClusterNode.new(nodeaddr)\n        node.connect(:abort => true)\n        node.assert_cluster\n        node.load_info(:getfriends => true)\n        add_node(node)\n        node.friends.each{|f|\n            next if f[:flags].index(\"noaddr\") ||\n                    f[:flags].index(\"disconnected\") ||\n                    f[:flags].index(\"fail\")\n            fnode = ClusterNode.new(f[:addr])\n            fnode.connect()\n            next if !fnode.r\n            begin\n                fnode.load_info()\n                add_node(fnode)\n            rescue => e\n                xputs \"[ERR] Unable to load info for node #{fnode}\"\n            end\n        }\n        populate_nodes_replicas_info\n    end\n\n    # This function is called by load_cluster_info_from_node in order to\n    # add additional information to every node as a list of replicas.\n    def populate_nodes_replicas_info\n        # Start adding the new field to every node.\n        @nodes.each{|n|\n            n.info[:replicas] = []\n        }\n\n        # Populate the replicas field using the replicate field of slave\n        # nodes.\n        @nodes.each{|n|\n            if n.info[:replicate]\n                master = get_node_by_name(n.info[:replicate])\n                if !master\n                    xputs \"*** WARNING: #{n} claims to be slave of unknown node ID #{n.info[:replicate]}.\"\n                else\n                    master.info[:replicas] << n\n                end\n            end\n        }\n    end\n\n    # Given a list of source nodes return a \"resharding plan\"\n    # with what slots to move in order to move \"numslots\" slots to another\n    # instance.\n    def compute_reshard_table(sources,numslots)\n        moved = []\n        # Sort from bigger to smaller instance, for two reasons:\n        # 1) If we take less slots than instances it is better to start\n        #    getting from the biggest instances.\n        # 2) We take one slot more from the first instance in the case of not\n        #    perfect divisibility. Like we have 3 nodes and need to get 10\n        #    slots, we take 4 from the first, and 3 from the rest. So the\n        #    biggest is always the first.\n        sources = sources.sort{|a,b| b.slots.length <=> a.slots.length}\n        source_tot_slots = sources.inject(0) {|sum,source|\n            sum+source.slots.length\n        }\n        sources.each_with_index{|s,i|\n            # Every node will provide a number of slots proportional to the\n            # slots it has assigned.\n            n = (numslots.to_f/source_tot_slots*s.slots.length)\n            if i == 0\n                n = n.ceil\n            else\n                n = n.floor\n            end\n            s.slots.keys.sort[(0...n)].each{|slot|\n                if moved.length < numslots\n                    moved << {:source => s, :slot => slot}\n                end\n            }\n        }\n        return moved\n    end\n\n    def show_reshard_table(table)\n        table.each{|e|\n            puts \"    Moving slot #{e[:slot]} from #{e[:source].info[:name]}\"\n        }\n    end\n\n    # Move slots between source and target nodes using MIGRATE.\n    #\n    # Options:\n    # :verbose -- Print a dot for every moved key.\n    # :fix     -- We are moving in the context of a fix. Use REPLACE.\n    # :cold    -- Move keys without opening slots / reconfiguring the nodes.\n    # :update  -- Update nodes.info[:slots] for source/target nodes.\n    # :quiet   -- Don't print info messages.\n    def move_slot(source,target,slot,o={})\n        o = {:pipeline => MigrateDefaultPipeline}.merge(o)\n\n        # We start marking the slot as importing in the destination node,\n        # and the slot as migrating in the target host. Note that the order of\n        # the operations is important, as otherwise a client may be redirected\n        # to the target node that does not yet know it is importing this slot.\n        if !o[:quiet]\n            print \"Moving slot #{slot} from #{source} to #{target}: \"\n            STDOUT.flush\n        end\n\n        if !o[:cold]\n            target.r.cluster(\"setslot\",slot,\"importing\",source.info[:name])\n            source.r.cluster(\"setslot\",slot,\"migrating\",target.info[:name])\n        end\n        # Migrate all the keys from source to target using the MIGRATE command\n        while true\n            keys = source.r.cluster(\"getkeysinslot\",slot,o[:pipeline])\n            break if keys.length == 0\n            begin\n                source.r.client.call([\"migrate\",target.info[:host],target.info[:port],\"\",0,@timeout,:keys,*keys])\n            rescue => e\n                if o[:fix] && e.to_s =~ /BUSYKEY/\n                    xputs \"*** Target key exists. Replacing it for FIX.\"\n                    source.r.client.call([\"migrate\",target.info[:host],target.info[:port],\"\",0,@timeout,:replace,:keys,*keys])\n                else\n                    puts \"\"\n                    xputs \"[ERR] Calling MIGRATE: #{e}\"\n                    exit 1\n                end\n            end\n            print \".\"*keys.length if o[:dots]\n            STDOUT.flush\n        end\n\n        puts if !o[:quiet]\n        # Set the new node as the owner of the slot in all the known nodes.\n        if !o[:cold]\n            @nodes.each{|n|\n                next if n.has_flag?(\"slave\")\n                n.r.cluster(\"setslot\",slot,\"node\",target.info[:name])\n            }\n        end\n\n        # Update the node logical config\n        if o[:update] then\n            source.info[:slots].delete(slot)\n            target.info[:slots][slot] = true\n        end\n    end\n\n    # redis-trib subcommands implementations.\n\n    def check_cluster_cmd(argv,opt)\n        load_cluster_info_from_node(argv[0])\n        check_cluster\n    end\n\n    def info_cluster_cmd(argv,opt)\n        load_cluster_info_from_node(argv[0])\n        show_cluster_info\n    end\n\n    def rebalance_cluster_cmd(argv,opt)\n        opt = {\n            'pipeline' => MigrateDefaultPipeline,\n            'threshold' => RebalanceDefaultThreshold\n        }.merge(opt)\n\n        # Load nodes info before parsing options, otherwise we can't\n        # handle --weight.\n        load_cluster_info_from_node(argv[0])\n\n        # Options parsing\n        threshold = opt['threshold'].to_i\n        autoweights = opt['auto-weights']\n        weights = {}\n        opt['weight'].each{|w|\n            fields = w.split(\"=\")\n            node = get_node_by_abbreviated_name(fields[0])\n            if !node || !node.has_flag?(\"master\")\n                puts \"*** No such master node #{fields[0]}\"\n                exit 1\n            end\n            weights[node.info[:name]] = fields[1].to_f\n        } if opt['weight']\n        useempty = opt['use-empty-masters']\n\n       # Assign a weight to each node, and compute the total cluster weight.\n        total_weight = 0\n        nodes_involved = 0\n        @nodes.each{|n|\n            if n.has_flag?(\"master\")\n                next if !useempty && n.slots.length == 0\n                n.info[:w] = weights[n.info[:name]] ? weights[n.info[:name]] : 1\n                total_weight += n.info[:w]\n                nodes_involved += 1\n            end\n        }\n\n        # Check cluster, only proceed if it looks sane.\n        check_cluster(:quiet => true)\n        if @errors.length != 0\n            puts \"*** Please fix your cluster problems before rebalancing\"\n            exit 1\n        end\n\n        # Calculate the slots balance for each node. It's the number of\n        # slots the node should lose (if positive) or gain (if negative)\n        # in order to be balanced.\n        threshold = opt['threshold'].to_f\n        threshold_reached = false\n        @nodes.each{|n|\n            if n.has_flag?(\"master\")\n                next if !n.info[:w]\n                expected = ((ClusterHashSlots.to_f / total_weight) *\n                            n.info[:w]).to_i\n                n.info[:balance] = n.slots.length - expected\n                # Compute the percentage of difference between the\n                # expected number of slots and the real one, to see\n                # if it's over the threshold specified by the user.\n                over_threshold = false\n                if threshold > 0\n                    if n.slots.length > 0\n                        err_perc = (100-(100.0*expected/n.slots.length)).abs\n                        over_threshold = true if err_perc > threshold\n                    elsif expected > 0\n                        over_threshold = true\n                    end\n                end\n                threshold_reached = true if over_threshold\n            end\n        }\n        if !threshold_reached\n            xputs \"*** No rebalancing needed! All nodes are within the #{threshold}% threshold.\"\n            return\n        end\n\n        # Only consider nodes we want to change\n        sn = @nodes.select{|n|\n            n.has_flag?(\"master\") && n.info[:w]\n        }\n\n        # Because of rounding, it is possible that the balance of all nodes\n        # summed does not give 0. Make sure that nodes that have to provide\n        # slots are always matched by nodes receiving slots.\n        total_balance = sn.map{|x| x.info[:balance]}.reduce{|a,b| a+b}\n        while total_balance > 0\n            sn.each{|n|\n                if n.info[:balance] < 0 && total_balance > 0\n                    n.info[:balance] -= 1\n                    total_balance -= 1\n                end\n            }\n        end\n\n        # Sort nodes by their slots balance.\n        sn = sn.sort{|a,b|\n            a.info[:balance] <=> b.info[:balance]\n        }\n\n        xputs \">>> Rebalancing across #{nodes_involved} nodes. Total weight = #{total_weight}\"\n\n        if $verbose\n            sn.each{|n|\n                puts \"#{n} balance is #{n.info[:balance]} slots\"\n            }\n        end\n\n        # Now we have at the start of the 'sn' array nodes that should get\n        # slots, at the end nodes that must give slots.\n        # We take two indexes, one at the start, and one at the end,\n        # incrementing or decrementing the indexes accordingly til we\n        # find nodes that need to get/provide slots.\n        dst_idx = 0\n        src_idx = sn.length - 1\n\n        while dst_idx < src_idx\n            dst = sn[dst_idx]\n            src = sn[src_idx]\n            numslots = [dst.info[:balance],src.info[:balance]].map{|n|\n                n.abs\n            }.min\n\n            if numslots > 0\n                puts \"Moving #{numslots} slots from #{src} to #{dst}\"\n\n                # Actaully move the slots.\n                reshard_table = compute_reshard_table([src],numslots)\n                if reshard_table.length != numslots\n                    xputs \"*** Assertio failed: Reshard table != number of slots\"\n                    exit 1\n                end\n                if opt['simulate']\n                    print \"#\"*reshard_table.length\n                else\n                    reshard_table.each{|e|\n                        move_slot(e[:source],dst,e[:slot],\n                            :quiet=>true,\n                            :dots=>false,\n                            :update=>true,\n                            :pipeline=>opt['pipeline'])\n                        print \"#\"\n                        STDOUT.flush\n                    }\n                end\n                puts\n            end\n\n            # Update nodes balance.\n            dst.info[:balance] += numslots\n            src.info[:balance] -= numslots\n            dst_idx += 1 if dst.info[:balance] == 0\n            src_idx -= 1 if src.info[:balance] == 0\n        end\n    end\n\n    def fix_cluster_cmd(argv,opt)\n        @fix = true\n        @timeout = opt['timeout'].to_i if opt['timeout']\n\n        load_cluster_info_from_node(argv[0])\n        check_cluster\n    end\n\n    def reshard_cluster_cmd(argv,opt)\n        opt = {'pipeline' => MigrateDefaultPipeline}.merge(opt)\n\n        load_cluster_info_from_node(argv[0])\n        check_cluster\n        if @errors.length != 0\n            puts \"*** Please fix your cluster problems before resharding\"\n            exit 1\n        end\n\n        @timeout = opt['timeout'].to_i if opt['timeout'].to_i\n\n        # Get number of slots\n        if opt['slots']\n            numslots = opt['slots'].to_i\n        else\n            numslots = 0\n            while numslots <= 0 or numslots > ClusterHashSlots\n                print \"How many slots do you want to move (from 1 to #{ClusterHashSlots})? \"\n                numslots = STDIN.gets.to_i\n            end\n        end\n\n        # Get the target instance\n        if opt['to']\n            target = get_node_by_name(opt['to'])\n            if !target || target.has_flag?(\"slave\")\n                xputs \"*** The specified node is not known or not a master, please retry.\"\n                exit 1\n            end\n        else\n            target = nil\n            while not target\n                print \"What is the receiving node ID? \"\n                target = get_node_by_name(STDIN.gets.chop)\n                if !target || target.has_flag?(\"slave\")\n                    xputs \"*** The specified node is not known or not a master, please retry.\"\n                    target = nil\n                end\n            end\n        end\n\n        # Get the source instances\n        sources = []\n        if opt['from']\n            opt['from'].split(',').each{|node_id|\n                if node_id == \"all\"\n                    sources = \"all\"\n                    break\n                end\n                src = get_node_by_name(node_id)\n                if !src || src.has_flag?(\"slave\")\n                    xputs \"*** The specified node is not known or is not a master, please retry.\"\n                    exit 1\n                end\n                sources << src\n            }\n        else\n            xputs \"Please enter all the source node IDs.\"\n            xputs \"  Type 'all' to use all the nodes as source nodes for the hash slots.\"\n            xputs \"  Type 'done' once you entered all the source nodes IDs.\"\n            while true\n                print \"Source node ##{sources.length+1}:\"\n                line = STDIN.gets.chop\n                src = get_node_by_name(line)\n                if line == \"done\"\n                    break\n                elsif line == \"all\"\n                    sources = \"all\"\n                    break\n                elsif !src || src.has_flag?(\"slave\")\n                    xputs \"*** The specified node is not known or is not a master, please retry.\"\n                elsif src.info[:name] == target.info[:name]\n                    xputs \"*** It is not possible to use the target node as source node.\"\n                else\n                    sources << src\n                end\n            end\n        end\n\n        if sources.length == 0\n            puts \"*** No source nodes given, operation aborted\"\n            exit 1\n        end\n\n        # Handle soures == all.\n        if sources == \"all\"\n            sources = []\n            @nodes.each{|n|\n                next if n.info[:name] == target.info[:name]\n                next if n.has_flag?(\"slave\")\n                sources << n\n            }\n        end\n\n        # Check if the destination node is the same of any source nodes.\n        if sources.index(target)\n            xputs \"*** Target node is also listed among the source nodes!\"\n            exit 1\n        end\n\n        puts \"\\nReady to move #{numslots} slots.\"\n        puts \"  Source nodes:\"\n        sources.each{|s| puts \"    \"+s.info_string}\n        puts \"  Destination node:\"\n        puts \"    #{target.info_string}\"\n        reshard_table = compute_reshard_table(sources,numslots)\n        puts \"  Resharding plan:\"\n        show_reshard_table(reshard_table)\n        if !opt['yes']\n            print \"Do you want to proceed with the proposed reshard plan (yes/no)? \"\n            yesno = STDIN.gets.chop\n            exit(1) if (yesno != \"yes\")\n        end\n        reshard_table.each{|e|\n            move_slot(e[:source],target,e[:slot],\n                :dots=>true,\n                :pipeline=>opt['pipeline'])\n        }\n    end\n\n    # This is an helper function for create_cluster_cmd that verifies if\n    # the number of nodes and the specified replicas have a valid configuration\n    # where there are at least three master nodes and enough replicas per node.\n    def check_create_parameters\n        masters = @nodes.length/(@replicas+1)\n        if masters < 3\n            puts \"*** ERROR: Invalid configuration for cluster creation.\"\n            puts \"*** Redis Cluster requires at least 3 master nodes.\"\n            puts \"*** This is not possible with #{@nodes.length} nodes and #{@replicas} replicas per node.\"\n            puts \"*** At least #{3*(@replicas+1)} nodes are required.\"\n            exit 1\n        end\n    end\n\n    def create_cluster_cmd(argv,opt)\n        opt = {'replicas' => 0}.merge(opt)\n        @replicas = opt['replicas'].to_i\n\n        xputs \">>> Creating cluster\"\n        argv[0..-1].each{|n|\n            node = ClusterNode.new(n)\n            node.connect(:abort => true)\n            node.assert_cluster\n            node.load_info\n            node.assert_empty\n            add_node(node)\n        }\n        check_create_parameters\n        xputs \">>> Performing hash slots allocation on #{@nodes.length} nodes...\"\n        alloc_slots\n        show_nodes\n        yes_or_die \"Can I set the above configuration?\"\n        flush_nodes_config\n        xputs \">>> Nodes configuration updated\"\n        xputs \">>> Assign a different config epoch to each node\"\n        assign_config_epoch\n        xputs \">>> Sending CLUSTER MEET messages to join the cluster\"\n        join_cluster\n        # Give one second for the join to start, in order to avoid that\n        # wait_cluster_join will find all the nodes agree about the config as\n        # they are still empty with unassigned slots.\n        sleep 1\n        wait_cluster_join\n        flush_nodes_config # Useful for the replicas\n        # Reset the node information, so that when the\n        # final summary is listed in check_cluster about the newly created cluster\n        # all the nodes would get properly listed as slaves or masters\n        reset_nodes\n        load_cluster_info_from_node(argv[0])\n        check_cluster\n    end\n\n    def addnode_cluster_cmd(argv,opt)\n        xputs \">>> Adding node #{argv[0]} to cluster #{argv[1]}\"\n\n        # Check the existing cluster\n        load_cluster_info_from_node(argv[1])\n        check_cluster\n\n        # If --master-id was specified, try to resolve it now so that we\n        # abort before starting with the node configuration.\n        if opt['slave']\n            if opt['master-id']\n                master = get_node_by_name(opt['master-id'])\n                if !master\n                    xputs \"[ERR] No such master ID #{opt['master-id']}\"\n                end\n            else\n                master = get_master_with_least_replicas\n                xputs \"Automatically selected master #{master}\"\n            end\n        end\n\n        # Add the new node\n        new = ClusterNode.new(argv[0])\n        new.connect(:abort => true)\n        new.assert_cluster\n        new.load_info\n        new.assert_empty\n        first = @nodes.first.info\n        add_node(new)\n\n        # Send CLUSTER MEET command to the new node\n        xputs \">>> Send CLUSTER MEET to node #{new} to make it join the cluster.\"\n        new.r.cluster(\"meet\",first[:host],first[:port])\n\n        # Additional configuration is needed if the node is added as\n        # a slave.\n        if opt['slave']\n            wait_cluster_join\n            xputs \">>> Configure node as replica of #{master}.\"\n            new.r.cluster(\"replicate\",master.info[:name])\n        end\n        xputs \"[OK] New node added correctly.\"\n    end\n\n    def delnode_cluster_cmd(argv,opt)\n        id = argv[1].downcase\n        xputs \">>> Removing node #{id} from cluster #{argv[0]}\"\n\n        # Load cluster information\n        load_cluster_info_from_node(argv[0])\n\n        # Check if the node exists and is not empty\n        node = get_node_by_name(id)\n\n        if !node\n            xputs \"[ERR] No such node ID #{id}\"\n            exit 1\n        end\n\n        if node.slots.length != 0\n            xputs \"[ERR] Node #{node} is not empty! Reshard data away and try again.\"\n            exit 1\n        end\n\n        # Send CLUSTER FORGET to all the nodes but the node to remove\n        xputs \">>> Sending CLUSTER FORGET messages to the cluster...\"\n        @nodes.each{|n|\n            next if n == node\n            if n.info[:replicate] && n.info[:replicate].downcase == id\n                # Reconfigure the slave to replicate with some other node\n                master = get_master_with_least_replicas\n                xputs \">>> #{n} as replica of #{master}\"\n                n.r.cluster(\"replicate\",master.info[:name])\n            end\n            n.r.cluster(\"forget\",argv[1])\n        }\n\n        # Finally shutdown the node\n        xputs \">>> SHUTDOWN the node.\"\n        node.r.shutdown\n    end\n\n    def set_timeout_cluster_cmd(argv,opt)\n        timeout = argv[1].to_i\n        if timeout < 100\n            puts \"Setting a node timeout of less than 100 milliseconds is a bad idea.\"\n            exit 1\n        end\n\n        # Load cluster information\n        load_cluster_info_from_node(argv[0])\n        ok_count = 0\n        err_count = 0\n\n        # Send CLUSTER FORGET to all the nodes but the node to remove\n        xputs \">>> Reconfiguring node timeout in every cluster node...\"\n        @nodes.each{|n|\n            begin\n                n.r.config(\"set\",\"cluster-node-timeout\",timeout)\n                n.r.config(\"rewrite\")\n                ok_count += 1\n                xputs \"*** New timeout set for #{n}\"\n            rescue => e\n                puts \"ERR setting node-timeot for #{n}: #{e}\"\n                err_count += 1\n            end\n        }\n        xputs \">>> New node timeout set. #{ok_count} OK, #{err_count} ERR.\"\n    end\n\n    def call_cluster_cmd(argv,opt)\n        cmd = argv[1..-1]\n        cmd[0] = cmd[0].upcase\n\n        # Load cluster information\n        load_cluster_info_from_node(argv[0])\n        xputs \">>> Calling #{cmd.join(\" \")}\"\n        @nodes.each{|n|\n            begin\n                res = n.r.send(*cmd)\n                puts \"#{n}: #{res}\"\n            rescue => e\n                puts \"#{n}: #{e}\"\n            end\n        }\n    end\n\n    def import_cluster_cmd(argv,opt)\n        source_addr = opt['from']\n        xputs \">>> Importing data from #{source_addr} to cluster #{argv[1]}\"\n        use_copy = opt['copy']\n        use_replace = opt['replace']\n        \n        # Check the existing cluster.\n        load_cluster_info_from_node(argv[0])\n        check_cluster\n\n        # Connect to the source node.\n        xputs \">>> Connecting to the source Redis instance\"\n        src_host,src_port = source_addr.split(\":\")\n        source = Redis.new(:host =>src_host, :port =>src_port)\n        if source.info['cluster_enabled'].to_i == 1\n            xputs \"[ERR] The source node should not be a cluster node.\"\n        end\n        xputs \"*** Importing #{source.dbsize} keys from DB 0\"\n\n        # Build a slot -> node map\n        slots = {}\n        @nodes.each{|n|\n            n.slots.each{|s,_|\n                slots[s] = n\n            }\n        }\n\n        # Use SCAN to iterate over the keys, migrating to the\n        # right node as needed.\n        cursor = nil\n        while cursor != 0\n            cursor,keys = source.scan(cursor, :count => 1000)\n            cursor = cursor.to_i\n            keys.each{|k|\n                # Migrate keys using the MIGRATE command.\n                slot = key_to_slot(k)\n                target = slots[slot]\n                print \"Migrating #{k} to #{target}: \"\n                STDOUT.flush\n                begin\n                    cmd = [\"migrate\",target.info[:host],target.info[:port],k,0,@timeout]\n                    cmd << :copy if use_copy\n                    cmd << :replace if use_replace\n                    source.client.call(cmd)\n                rescue => e\n                    puts e\n                else\n                    puts \"OK\"\n                end\n            }\n        end\n    end\n\n    def help_cluster_cmd(argv,opt)\n        show_help\n        exit 0\n    end\n\n    # Parse the options for the specific command \"cmd\".\n    # Returns an hash populate with option => value pairs, and the index of\n    # the first non-option argument in ARGV.\n    def parse_options(cmd)\n        idx = 1 ; # Current index into ARGV\n        options={}\n        while idx < ARGV.length && ARGV[idx][0..1] == '--'\n            if ARGV[idx][0..1] == \"--\"\n                option = ARGV[idx][2..-1]\n                idx += 1\n\n                # --verbose is a global option\n                if option == \"verbose\"\n                    $verbose = true\n                    next\n                end\n\n                if ALLOWED_OPTIONS[cmd] == nil || ALLOWED_OPTIONS[cmd][option] == nil\n                    puts \"Unknown option '#{option}' for command '#{cmd}'\"\n                    exit 1\n                end\n                if ALLOWED_OPTIONS[cmd][option] != false\n                    value = ARGV[idx]\n                    idx += 1\n                else\n                    value = true\n                end\n\n                # If the option is set to [], it's a multiple arguments\n                # option. We just queue every new value into an array.\n                if ALLOWED_OPTIONS[cmd][option] == []\n                    options[option] = [] if !options[option]\n                    options[option] << value\n                else\n                    options[option] = value\n                end\n            else\n                # Remaining arguments are not options.\n                break\n            end\n        end\n\n        # Enforce mandatory options\n        if ALLOWED_OPTIONS[cmd]\n            ALLOWED_OPTIONS[cmd].each {|option,val|\n                if !options[option] && val == :required\n                    puts \"Option '--#{option}' is required \"+ \\\n                         \"for subcommand '#{cmd}'\"\n                    exit 1\n                end\n            }\n        end\n        return options,idx\n    end\nend\n\n#################################################################################\n# Libraries\n#\n# We try to don't depend on external libs since this is a critical part\n# of Redis Cluster.\n#################################################################################\n\n# This is the CRC16 algorithm used by Redis Cluster to hash keys.\n# Implementation according to CCITT standards.\n#\n# This is actually the XMODEM CRC 16 algorithm, using the\n# following parameters:\n#\n# Name                       : \"XMODEM\", also known as \"ZMODEM\", \"CRC-16/ACORN\"\n# Width                      : 16 bit\n# Poly                       : 1021 (That is actually x^16 + x^12 + x^5 + 1)\n# Initialization             : 0000\n# Reflect Input byte         : False\n# Reflect Output CRC         : False\n# Xor constant to output CRC : 0000\n# Output for \"123456789\"     : 31C3\n\nmodule RedisClusterCRC16\n    def RedisClusterCRC16.crc16(bytes)\n        crc = 0\n        bytes.each_byte{|b|\n            crc = ((crc<<8) & 0xffff) ^ XMODEMCRC16Lookup[((crc>>8)^b) & 0xff]\n        }\n        crc\n    end\n\nprivate\n    XMODEMCRC16Lookup = [\n        0x0000,0x1021,0x2042,0x3063,0x4084,0x50a5,0x60c6,0x70e7,\n        0x8108,0x9129,0xa14a,0xb16b,0xc18c,0xd1ad,0xe1ce,0xf1ef,\n        0x1231,0x0210,0x3273,0x2252,0x52b5,0x4294,0x72f7,0x62d6,\n        0x9339,0x8318,0xb37b,0xa35a,0xd3bd,0xc39c,0xf3ff,0xe3de,\n        0x2462,0x3443,0x0420,0x1401,0x64e6,0x74c7,0x44a4,0x5485,\n        0xa56a,0xb54b,0x8528,0x9509,0xe5ee,0xf5cf,0xc5ac,0xd58d,\n        0x3653,0x2672,0x1611,0x0630,0x76d7,0x66f6,0x5695,0x46b4,\n        0xb75b,0xa77a,0x9719,0x8738,0xf7df,0xe7fe,0xd79d,0xc7bc,\n        0x48c4,0x58e5,0x6886,0x78a7,0x0840,0x1861,0x2802,0x3823,\n        0xc9cc,0xd9ed,0xe98e,0xf9af,0x8948,0x9969,0xa90a,0xb92b,\n        0x5af5,0x4ad4,0x7ab7,0x6a96,0x1a71,0x0a50,0x3a33,0x2a12,\n        0xdbfd,0xcbdc,0xfbbf,0xeb9e,0x9b79,0x8b58,0xbb3b,0xab1a,\n        0x6ca6,0x7c87,0x4ce4,0x5cc5,0x2c22,0x3c03,0x0c60,0x1c41,\n        0xedae,0xfd8f,0xcdec,0xddcd,0xad2a,0xbd0b,0x8d68,0x9d49,\n        0x7e97,0x6eb6,0x5ed5,0x4ef4,0x3e13,0x2e32,0x1e51,0x0e70,\n        0xff9f,0xefbe,0xdfdd,0xcffc,0xbf1b,0xaf3a,0x9f59,0x8f78,\n        0x9188,0x81a9,0xb1ca,0xa1eb,0xd10c,0xc12d,0xf14e,0xe16f,\n        0x1080,0x00a1,0x30c2,0x20e3,0x5004,0x4025,0x7046,0x6067,\n        0x83b9,0x9398,0xa3fb,0xb3da,0xc33d,0xd31c,0xe37f,0xf35e,\n        0x02b1,0x1290,0x22f3,0x32d2,0x4235,0x5214,0x6277,0x7256,\n        0xb5ea,0xa5cb,0x95a8,0x8589,0xf56e,0xe54f,0xd52c,0xc50d,\n        0x34e2,0x24c3,0x14a0,0x0481,0x7466,0x6447,0x5424,0x4405,\n        0xa7db,0xb7fa,0x8799,0x97b8,0xe75f,0xf77e,0xc71d,0xd73c,\n        0x26d3,0x36f2,0x0691,0x16b0,0x6657,0x7676,0x4615,0x5634,\n        0xd94c,0xc96d,0xf90e,0xe92f,0x99c8,0x89e9,0xb98a,0xa9ab,\n        0x5844,0x4865,0x7806,0x6827,0x18c0,0x08e1,0x3882,0x28a3,\n        0xcb7d,0xdb5c,0xeb3f,0xfb1e,0x8bf9,0x9bd8,0xabbb,0xbb9a,\n        0x4a75,0x5a54,0x6a37,0x7a16,0x0af1,0x1ad0,0x2ab3,0x3a92,\n        0xfd2e,0xed0f,0xdd6c,0xcd4d,0xbdaa,0xad8b,0x9de8,0x8dc9,\n        0x7c26,0x6c07,0x5c64,0x4c45,0x3ca2,0x2c83,0x1ce0,0x0cc1,\n        0xef1f,0xff3e,0xcf5d,0xdf7c,0xaf9b,0xbfba,0x8fd9,0x9ff8,\n        0x6e17,0x7e36,0x4e55,0x5e74,0x2e93,0x3eb2,0x0ed1,0x1ef0\n    ]\nend\n\n# Turn a key name into the corrisponding Redis Cluster slot.\ndef key_to_slot(key)\n    # Only hash what is inside {...} if there is such a pattern in the key.\n    # Note that the specification requires the content that is between\n    # the first { and the first } after the first {. If we found {} without\n    # nothing in the middle, the whole key is hashed as usually.\n    s = key.index \"{\"\n    if s\n        e = key.index \"}\",s+1\n        if e && e != s+1\n            key = key[s+1..e-1]\n        end\n    end\n    RedisClusterCRC16.crc16(key) % 16384\nend\n\n#################################################################################\n# Definition of commands\n#################################################################################\n\nCOMMANDS={\n    \"create\"  => [\"create_cluster_cmd\", -2, \"host1:port1 ... hostN:portN\"],\n    \"check\"   => [\"check_cluster_cmd\", 2, \"host:port\"],\n    \"info\"    => [\"info_cluster_cmd\", 2, \"host:port\"],\n    \"fix\"     => [\"fix_cluster_cmd\", 2, \"host:port\"],\n    \"reshard\" => [\"reshard_cluster_cmd\", 2, \"host:port\"],\n    \"rebalance\" => [\"rebalance_cluster_cmd\", -2, \"host:port\"],\n    \"add-node\" => [\"addnode_cluster_cmd\", 3, \"new_host:new_port existing_host:existing_port\"],\n    \"del-node\" => [\"delnode_cluster_cmd\", 3, \"host:port node_id\"],\n    \"set-timeout\" => [\"set_timeout_cluster_cmd\", 3, \"host:port milliseconds\"],\n    \"call\" =>    [\"call_cluster_cmd\", -3, \"host:port command arg arg .. arg\"],\n    \"import\" =>  [\"import_cluster_cmd\", 2, \"host:port\"],\n    \"help\"    => [\"help_cluster_cmd\", 1, \"(show this help)\"]\n}\n\nALLOWED_OPTIONS={\n    \"create\" => {\"replicas\" => true},\n    \"add-node\" => {\"slave\" => false, \"master-id\" => true},\n    \"import\" => {\"from\" => :required, \"copy\" => false, \"replace\" => false},\n    \"reshard\" => {\"from\" => true, \"to\" => true, \"slots\" => true, \"yes\" => false, \"timeout\" => true, \"pipeline\" => true},\n    \"rebalance\" => {\"weight\" => [], \"auto-weights\" => false, \"use-empty-masters\" => false, \"timeout\" => true, \"simulate\" => false, \"pipeline\" => true, \"threshold\" => true},\n    \"fix\" => {\"timeout\" => MigrateDefaultTimeout},\n}\n\ndef show_help\n    puts \"Usage: redis-trib <command> <options> <arguments ...>\\n\\n\"\n    COMMANDS.each{|k,v|\n        o = \"\"\n        puts \"  #{k.ljust(15)} #{v[2]}\"\n        if ALLOWED_OPTIONS[k]\n            ALLOWED_OPTIONS[k].each{|optname,has_arg|\n                puts \"                  --#{optname}\" + (has_arg ? \" <arg>\" : \"\")\n            }\n        end\n    }\n    puts \"\\nFor check, fix, reshard, del-node, set-timeout you can specify the host and port of any working node in the cluster.\\n\"\nend\n\n# Sanity check\nif ARGV.length == 0\n    show_help\n    exit 1\nend\n\nrt = RedisTrib.new\ncmd_spec = COMMANDS[ARGV[0].downcase]\nif !cmd_spec\n    puts \"Unknown redis-trib subcommand '#{ARGV[0]}'\"\n    exit 1\nend\n\n# Parse options\ncmd_options,first_non_option = rt.parse_options(ARGV[0].downcase)\nrt.check_arity(cmd_spec[1],ARGV.length-(first_non_option-1))\n\n# Dispatch\nrt.send(cmd_spec[0],ARGV[first_non_option..-1],cmd_options)\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/src/redisassert.h",
    "content": "/* redisassert.h -- Drop in replacemnet assert.h that prints the stack trace\n *                  in the Redis logs.\n *\n * This file should be included instead of \"assert.h\" inside libraries used by\n * Redis that are using assertions, so instead of Redis disappearing with\n * SIGABORT, we get the details and stack trace inside the log file.\n *\n * ----------------------------------------------------------------------------\n *\n * Copyright (c) 2006-2012, Salvatore Sanfilippo <antirez at gmail dot com>\n * All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions are met:\n *\n *   * Redistributions of source code must retain the above copyright notice,\n *     this list of conditions and the following disclaimer.\n *   * Redistributions in binary form must reproduce the above copyright\n *     notice, this list of conditions and the following disclaimer in the\n *     documentation and/or other materials provided with the distribution.\n *   * Neither the name of Redis nor the names of its contributors may be used\n *     to endorse or promote products derived from this software without\n *     specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\"\n * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\n * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE\n * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR\n * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF\n * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS\n * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN\n * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)\n * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE\n * POSSIBILITY OF SUCH DAMAGE.\n */\n\n#ifndef __REDIS_ASSERT_H__\n#define __REDIS_ASSERT_H__\n\n#include <unistd.h> /* for _exit() */\n\n#define assert(_e) ((_e)?(void)0 : (_serverAssert(#_e,__FILE__,__LINE__),_exit(1)))\n\nvoid _serverAssert(char *estr, char *file, int line);\n\n#endif\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/src/release.c",
    "content": "/*\n * Copyright (c) 2009-2012, Salvatore Sanfilippo <antirez at gmail dot com>\n * All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions are met:\n *\n *   * Redistributions of source code must retain the above copyright notice,\n *     this list of conditions and the following disclaimer.\n *   * Redistributions in binary form must reproduce the above copyright\n *     notice, this list of conditions and the following disclaimer in the\n *     documentation and/or other materials provided with the distribution.\n *   * Neither the name of Redis nor the names of its contributors may be used\n *     to endorse or promote products derived from this software without\n *     specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\"\n * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\n * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE\n * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR\n * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF\n * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS\n * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN\n * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)\n * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE\n * POSSIBILITY OF SUCH DAMAGE.\n */\n\n/* Every time the Redis Git SHA1 or Dirty status changes only this small\n * file is recompiled, as we access this information in all the other\n * files using this functions. */\n\n#include <string.h>\n\n#include \"release.h\"\n#include \"version.h\"\n#include \"crc64.h\"\n\nchar *redisGitSHA1(void) {\n    return REDIS_GIT_SHA1;\n}\n\nchar *redisGitDirty(void) {\n    return REDIS_GIT_DIRTY;\n}\n\nuint64_t redisBuildId(void) {\n    char *buildid = REDIS_VERSION REDIS_BUILD_ID REDIS_GIT_DIRTY REDIS_GIT_SHA1;\n\n    return crc64(0,(unsigned char*)buildid,strlen(buildid));\n}\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/src/replication.c",
    "content": "/* Asynchronous replication implementation.\n *\n * Copyright (c) 2009-2012, Salvatore Sanfilippo <antirez at gmail dot com>\n * All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions are met:\n *\n *   * Redistributions of source code must retain the above copyright notice,\n *     this list of conditions and the following disclaimer.\n *   * Redistributions in binary form must reproduce the above copyright\n *     notice, this list of conditions and the following disclaimer in the\n *     documentation and/or other materials provided with the distribution.\n *   * Neither the name of Redis nor the names of its contributors may be used\n *     to endorse or promote products derived from this software without\n *     specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\"\n * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\n * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE\n * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR\n * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF\n * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS\n * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN\n * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)\n * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE\n * POSSIBILITY OF SUCH DAMAGE.\n */\n\n\n#include \"server.h\"\n\n#include <sys/time.h>\n#include <unistd.h>\n#include <fcntl.h>\n#include <sys/socket.h>\n#include <sys/stat.h>\n\nvoid replicationDiscardCachedMaster(void);\nvoid replicationResurrectCachedMaster(int newfd);\nvoid replicationSendAck(void);\nvoid putSlaveOnline(client *slave);\nint cancelReplicationHandshake(void);\n\n/* --------------------------- Utility functions ---------------------------- */\n\n/* Return the pointer to a string representing the slave ip:listening_port\n * pair. Mostly useful for logging, since we want to log a slave using its\n * IP address and its listening port which is more clear for the user, for\n * example: \"Closing connection with slave 10.1.2.3:6380\". */\nchar *replicationGetSlaveName(client *c) {\n    static char buf[NET_PEER_ID_LEN];\n    char ip[NET_IP_STR_LEN];\n\n    ip[0] = '\\0';\n    buf[0] = '\\0';\n    if (c->slave_ip[0] != '\\0' ||\n        anetPeerToString(c->fd,ip,sizeof(ip),NULL) != -1)\n    {\n        /* Note that the 'ip' buffer is always larger than 'c->slave_ip' */\n        if (c->slave_ip[0] != '\\0') memcpy(ip,c->slave_ip,sizeof(c->slave_ip));\n\n        if (c->slave_listening_port)\n            anetFormatAddr(buf,sizeof(buf),ip,c->slave_listening_port);\n        else\n            snprintf(buf,sizeof(buf),\"%s:<unknown-slave-port>\",ip);\n    } else {\n        snprintf(buf,sizeof(buf),\"client id #%llu\",\n            (unsigned long long) c->id);\n    }\n    return buf;\n}\n\n/* ---------------------------------- MASTER -------------------------------- */\n\nvoid createReplicationBacklog(void) {\n    serverAssert(server.repl_backlog == NULL);\n    server.repl_backlog = zmalloc(server.repl_backlog_size);\n    server.repl_backlog_histlen = 0;\n    server.repl_backlog_idx = 0;\n    /* When a new backlog buffer is created, we increment the replication\n     * offset by one to make sure we'll not be able to PSYNC with any\n     * previous slave. This is needed because we avoid incrementing the\n     * master_repl_offset if no backlog exists nor slaves are attached. */\n    server.master_repl_offset++;\n\n    /* We don't have any data inside our buffer, but virtually the first\n     * byte we have is the next byte that will be generated for the\n     * replication stream. */\n    server.repl_backlog_off = server.master_repl_offset+1;\n}\n\n/* This function is called when the user modifies the replication backlog\n * size at runtime. It is up to the function to both update the\n * server.repl_backlog_size and to resize the buffer and setup it so that\n * it contains the same data as the previous one (possibly less data, but\n * the most recent bytes, or the same data and more free space in case the\n * buffer is enlarged). */\nvoid resizeReplicationBacklog(long long newsize) {\n    if (newsize < CONFIG_REPL_BACKLOG_MIN_SIZE)\n        newsize = CONFIG_REPL_BACKLOG_MIN_SIZE;\n    if (server.repl_backlog_size == newsize) return;\n\n    server.repl_backlog_size = newsize;\n    if (server.repl_backlog != NULL) {\n        /* What we actually do is to flush the old buffer and realloc a new\n         * empty one. It will refill with new data incrementally.\n         * The reason is that copying a few gigabytes adds latency and even\n         * worse often we need to alloc additional space before freeing the\n         * old buffer. */\n        zfree(server.repl_backlog);\n        server.repl_backlog = zmalloc(server.repl_backlog_size);\n        server.repl_backlog_histlen = 0;\n        server.repl_backlog_idx = 0;\n        /* Next byte we have is... the next since the buffer is empty. */\n        server.repl_backlog_off = server.master_repl_offset+1;\n    }\n}\n\nvoid freeReplicationBacklog(void) {\n    serverAssert(listLength(server.slaves) == 0);\n    zfree(server.repl_backlog);\n    server.repl_backlog = NULL;\n}\n\n/* Add data to the replication backlog.\n * This function also increments the global replication offset stored at\n * server.master_repl_offset, because there is no case where we want to feed\n * the backlog without incrementing the buffer. */\nvoid feedReplicationBacklog(void *ptr, size_t len) {\n    unsigned char *p = ptr;\n\n    server.master_repl_offset += len;\n\n    /* This is a circular buffer, so write as much data we can at every\n     * iteration and rewind the \"idx\" index if we reach the limit. */\n    while(len) {\n        size_t thislen = server.repl_backlog_size - server.repl_backlog_idx;\n        if (thislen > len) thislen = len;\n        memcpy(server.repl_backlog+server.repl_backlog_idx,p,thislen);\n        server.repl_backlog_idx += thislen;\n        if (server.repl_backlog_idx == server.repl_backlog_size)\n            server.repl_backlog_idx = 0;\n        len -= thislen;\n        p += thislen;\n        server.repl_backlog_histlen += thislen;\n    }\n    if (server.repl_backlog_histlen > server.repl_backlog_size)\n        server.repl_backlog_histlen = server.repl_backlog_size;\n    /* Set the offset of the first byte we have in the backlog. */\n    server.repl_backlog_off = server.master_repl_offset -\n                              server.repl_backlog_histlen + 1;\n}\n\n/* Wrapper for feedReplicationBacklog() that takes Redis string objects\n * as input. */\nvoid feedReplicationBacklogWithObject(robj *o) {\n    char llstr[LONG_STR_SIZE];\n    void *p;\n    size_t len;\n\n    if (o->encoding == OBJ_ENCODING_INT) {\n        len = ll2string(llstr,sizeof(llstr),(long)o->ptr);\n        p = llstr;\n    } else {\n        len = sdslen(o->ptr);\n        p = o->ptr;\n    }\n    feedReplicationBacklog(p,len);\n}\n\nvoid replicationFeedSlaves(list *slaves, int dictid, robj **argv, int argc) {\n    listNode *ln;\n    listIter li;\n    int j, len;\n    char llstr[LONG_STR_SIZE];\n\n    /* If there aren't slaves, and there is no backlog buffer to populate,\n     * we can return ASAP. */\n    if (server.repl_backlog == NULL && listLength(slaves) == 0) return;\n\n    /* We can't have slaves attached and no backlog. */\n    serverAssert(!(listLength(slaves) != 0 && server.repl_backlog == NULL));\n\n    /* Send SELECT command to every slave if needed. */\n    if (server.slaveseldb != dictid) {\n        robj *selectcmd;\n\n        /* For a few DBs we have pre-computed SELECT command. */\n        if (dictid >= 0 && dictid < PROTO_SHARED_SELECT_CMDS) {\n            selectcmd = shared.select[dictid];\n        } else {\n            int dictid_len;\n\n            dictid_len = ll2string(llstr,sizeof(llstr),dictid);\n            selectcmd = createObject(OBJ_STRING,\n                sdscatprintf(sdsempty(),\n                \"*2\\r\\n$6\\r\\nSELECT\\r\\n$%d\\r\\n%s\\r\\n\",\n                dictid_len, llstr));\n        }\n\n        /* Add the SELECT command into the backlog. */\n        if (server.repl_backlog) feedReplicationBacklogWithObject(selectcmd);\n\n        /* Send it to slaves. */\n        listRewind(slaves,&li);\n        while((ln = listNext(&li))) {\n            client *slave = ln->value;\n            if (slave->replstate == SLAVE_STATE_WAIT_BGSAVE_START) continue;\n            addReply(slave,selectcmd);\n        }\n\n        if (dictid < 0 || dictid >= PROTO_SHARED_SELECT_CMDS)\n            decrRefCount(selectcmd);\n    }\n    server.slaveseldb = dictid;\n\n    /* Write the command to the replication backlog if any. */\n    if (server.repl_backlog) {\n        char aux[LONG_STR_SIZE+3];\n\n        /* Add the multi bulk reply length. */\n        aux[0] = '*';\n        len = ll2string(aux+1,sizeof(aux)-1,argc);\n        aux[len+1] = '\\r';\n        aux[len+2] = '\\n';\n        feedReplicationBacklog(aux,len+3);\n\n        for (j = 0; j < argc; j++) {\n            long objlen = stringObjectLen(argv[j]);\n\n            /* We need to feed the buffer with the object as a bulk reply\n             * not just as a plain string, so create the $..CRLF payload len\n             * and add the final CRLF */\n            aux[0] = '$';\n            len = ll2string(aux+1,sizeof(aux)-1,objlen);\n            aux[len+1] = '\\r';\n            aux[len+2] = '\\n';\n            feedReplicationBacklog(aux,len+3);\n            feedReplicationBacklogWithObject(argv[j]);\n            feedReplicationBacklog(aux+len+1,2);\n        }\n    }\n\n    /* Write the command to every slave. */\n    listRewind(server.slaves,&li);\n    while((ln = listNext(&li))) {\n        client *slave = ln->value;\n\n        /* Don't feed slaves that are still waiting for BGSAVE to start */\n        if (slave->replstate == SLAVE_STATE_WAIT_BGSAVE_START) continue;\n\n        /* Feed slaves that are waiting for the initial SYNC (so these commands\n         * are queued in the output buffer until the initial SYNC completes),\n         * or are already in sync with the master. */\n\n        /* Add the multi bulk length. */\n        addReplyMultiBulkLen(slave,argc);\n\n        /* Finally any additional argument that was not stored inside the\n         * static buffer if any (from j to argc). */\n        for (j = 0; j < argc; j++)\n            addReplyBulk(slave,argv[j]);\n    }\n}\n\nvoid replicationFeedMonitors(client *c, list *monitors, int dictid, robj **argv, int argc) {\n    listNode *ln;\n    listIter li;\n    int j;\n    sds cmdrepr = sdsnew(\"+\");\n    robj *cmdobj;\n    struct timeval tv;\n\n    gettimeofday(&tv,NULL);\n    cmdrepr = sdscatprintf(cmdrepr,\"%ld.%06ld \",(long)tv.tv_sec,(long)tv.tv_usec);\n    if (c->flags & CLIENT_LUA) {\n        cmdrepr = sdscatprintf(cmdrepr,\"[%d lua] \",dictid);\n    } else if (c->flags & CLIENT_UNIX_SOCKET) {\n        cmdrepr = sdscatprintf(cmdrepr,\"[%d unix:%s] \",dictid,server.unixsocket);\n    } else {\n        cmdrepr = sdscatprintf(cmdrepr,\"[%d %s] \",dictid,getClientPeerId(c));\n    }\n\n    for (j = 0; j < argc; j++) {\n        if (argv[j]->encoding == OBJ_ENCODING_INT) {\n            cmdrepr = sdscatprintf(cmdrepr, \"\\\"%ld\\\"\", (long)argv[j]->ptr);\n        } else {\n            cmdrepr = sdscatrepr(cmdrepr,(char*)argv[j]->ptr,\n                        sdslen(argv[j]->ptr));\n        }\n        if (j != argc-1)\n            cmdrepr = sdscatlen(cmdrepr,\" \",1);\n    }\n    cmdrepr = sdscatlen(cmdrepr,\"\\r\\n\",2);\n    cmdobj = createObject(OBJ_STRING,cmdrepr);\n\n    listRewind(monitors,&li);\n    while((ln = listNext(&li))) {\n        client *monitor = ln->value;\n        addReply(monitor,cmdobj);\n    }\n    decrRefCount(cmdobj);\n}\n\n/* Feed the slave 'c' with the replication backlog starting from the\n * specified 'offset' up to the end of the backlog. */\nlong long addReplyReplicationBacklog(client *c, long long offset) {\n    long long j, skip, len;\n\n    serverLog(LL_DEBUG, \"[PSYNC] Slave request offset: %lld\", offset);\n\n    if (server.repl_backlog_histlen == 0) {\n        serverLog(LL_DEBUG, \"[PSYNC] Backlog history len is zero\");\n        return 0;\n    }\n\n    serverLog(LL_DEBUG, \"[PSYNC] Backlog size: %lld\",\n             server.repl_backlog_size);\n    serverLog(LL_DEBUG, \"[PSYNC] First byte: %lld\",\n             server.repl_backlog_off);\n    serverLog(LL_DEBUG, \"[PSYNC] History len: %lld\",\n             server.repl_backlog_histlen);\n    serverLog(LL_DEBUG, \"[PSYNC] Current index: %lld\",\n             server.repl_backlog_idx);\n\n    /* Compute the amount of bytes we need to discard. */\n    skip = offset - server.repl_backlog_off;\n    serverLog(LL_DEBUG, \"[PSYNC] Skipping: %lld\", skip);\n\n    /* Point j to the oldest byte, that is actaully our\n     * server.repl_backlog_off byte. */\n    j = (server.repl_backlog_idx +\n        (server.repl_backlog_size-server.repl_backlog_histlen)) %\n        server.repl_backlog_size;\n    serverLog(LL_DEBUG, \"[PSYNC] Index of first byte: %lld\", j);\n\n    /* Discard the amount of data to seek to the specified 'offset'. */\n    j = (j + skip) % server.repl_backlog_size;\n\n    /* Feed slave with data. Since it is a circular buffer we have to\n     * split the reply in two parts if we are cross-boundary. */\n    len = server.repl_backlog_histlen - skip;\n    serverLog(LL_DEBUG, \"[PSYNC] Reply total length: %lld\", len);\n    while(len) {\n        long long thislen =\n            ((server.repl_backlog_size - j) < len) ?\n            (server.repl_backlog_size - j) : len;\n\n        serverLog(LL_DEBUG, \"[PSYNC] addReply() length: %lld\", thislen);\n        addReplySds(c,sdsnewlen(server.repl_backlog + j, thislen));\n        len -= thislen;\n        j = 0;\n    }\n    return server.repl_backlog_histlen - skip;\n}\n\n/* Return the offset to provide as reply to the PSYNC command received\n * from the slave. The returned value is only valid immediately after\n * the BGSAVE process started and before executing any other command\n * from clients. */\nlong long getPsyncInitialOffset(void) {\n    long long psync_offset = server.master_repl_offset;\n    /* Add 1 to psync_offset if it the replication backlog does not exists\n     * as when it will be created later we'll increment the offset by one. */\n    if (server.repl_backlog == NULL) psync_offset++;\n    return psync_offset;\n}\n\n/* Send a FULLRESYNC reply in the specific case of a full resynchronization,\n * as a side effect setup the slave for a full sync in different ways:\n *\n * 1) Remember, into the slave client structure, the offset we sent\n *    here, so that if new slaves will later attach to the same\n *    background RDB saving process (by duplicating this client output\n *    buffer), we can get the right offset from this slave.\n * 2) Set the replication state of the slave to WAIT_BGSAVE_END so that\n *    we start accumulating differences from this point.\n * 3) Force the replication stream to re-emit a SELECT statement so\n *    the new slave incremental differences will start selecting the\n *    right database number.\n *\n * Normally this function should be called immediately after a successful\n * BGSAVE for replication was started, or when there is one already in\n * progress that we attached our slave to. */\nint replicationSetupSlaveForFullResync(client *slave, long long offset) {\n    char buf[128];\n    int buflen;\n\n    slave->psync_initial_offset = offset;\n    slave->replstate = SLAVE_STATE_WAIT_BGSAVE_END;\n    /* We are going to accumulate the incremental changes for this\n     * slave as well. Set slaveseldb to -1 in order to force to re-emit\n     * a SLEECT statement in the replication stream. */\n    server.slaveseldb = -1;\n\n    /* Don't send this reply to slaves that approached us with\n     * the old SYNC command. */\n    if (!(slave->flags & CLIENT_PRE_PSYNC)) {\n        buflen = snprintf(buf,sizeof(buf),\"+FULLRESYNC %s %lld\\r\\n\",\n                          server.runid,offset);\n        if (write(slave->fd,buf,buflen) != buflen) {\n            freeClientAsync(slave);\n            return C_ERR;\n        }\n    }\n    return C_OK;\n}\n\n/* This function handles the PSYNC command from the point of view of a\n * master receiving a request for partial resynchronization.\n *\n * On success return C_OK, otherwise C_ERR is returned and we proceed\n * with the usual full resync. */\nint masterTryPartialResynchronization(client *c) {\n    long long psync_offset, psync_len;\n    char *master_runid = c->argv[1]->ptr;\n    char buf[128];\n    int buflen;\n\n    /* Is the runid of this master the same advertised by the wannabe slave\n     * via PSYNC? If runid changed this master is a different instance and\n     * there is no way to continue. */\n    if (strcasecmp(master_runid, server.runid)) {\n        /* Run id \"?\" is used by slaves that want to force a full resync. */\n        if (master_runid[0] != '?') {\n            serverLog(LL_NOTICE,\"Partial resynchronization not accepted: \"\n                \"Runid mismatch (Client asked for runid '%s', my runid is '%s')\",\n                master_runid, server.runid);\n        } else {\n            serverLog(LL_NOTICE,\"Full resync requested by slave %s\",\n                replicationGetSlaveName(c));\n        }\n        goto need_full_resync;\n    }\n\n    /* We still have the data our slave is asking for? */\n    if (getLongLongFromObjectOrReply(c,c->argv[2],&psync_offset,NULL) !=\n       C_OK) goto need_full_resync;\n    if (!server.repl_backlog ||\n        psync_offset < server.repl_backlog_off ||\n        psync_offset > (server.repl_backlog_off + server.repl_backlog_histlen))\n    {\n        serverLog(LL_NOTICE,\n            \"Unable to partial resync with slave %s for lack of backlog (Slave request was: %lld).\", replicationGetSlaveName(c), psync_offset);\n        if (psync_offset > server.master_repl_offset) {\n            serverLog(LL_WARNING,\n                \"Warning: slave %s tried to PSYNC with an offset that is greater than the master replication offset.\", replicationGetSlaveName(c));\n        }\n        goto need_full_resync;\n    }\n\n    /* If we reached this point, we are able to perform a partial resync:\n     * 1) Set client state to make it a slave.\n     * 2) Inform the client we can continue with +CONTINUE\n     * 3) Send the backlog data (from the offset to the end) to the slave. */\n    c->flags |= CLIENT_SLAVE;\n    c->replstate = SLAVE_STATE_ONLINE;\n    c->repl_ack_time = server.unixtime;\n    c->repl_put_online_on_ack = 0;\n    listAddNodeTail(server.slaves,c);\n    /* We can't use the connection buffers since they are used to accumulate\n     * new commands at this stage. But we are sure the socket send buffer is\n     * empty so this write will never fail actually. */\n    buflen = snprintf(buf,sizeof(buf),\"+CONTINUE\\r\\n\");\n    if (write(c->fd,buf,buflen) != buflen) {\n        freeClientAsync(c);\n        return C_OK;\n    }\n    psync_len = addReplyReplicationBacklog(c,psync_offset);\n    serverLog(LL_NOTICE,\n        \"Partial resynchronization request from %s accepted. Sending %lld bytes of backlog starting from offset %lld.\",\n            replicationGetSlaveName(c),\n            psync_len, psync_offset);\n    /* Note that we don't need to set the selected DB at server.slaveseldb\n     * to -1 to force the master to emit SELECT, since the slave already\n     * has this state from the previous connection with the master. */\n\n    refreshGoodSlavesCount();\n    return C_OK; /* The caller can return, no full resync needed. */\n\nneed_full_resync:\n    /* We need a full resync for some reason... Note that we can't\n     * reply to PSYNC right now if a full SYNC is needed. The reply\n     * must include the master offset at the time the RDB file we transfer\n     * is generated, so we need to delay the reply to that moment. */\n    return C_ERR;\n}\n\n/* Start a BGSAVE for replication goals, which is, selecting the disk or\n * socket target depending on the configuration, and making sure that\n * the script cache is flushed before to start.\n *\n * The mincapa argument is the bitwise AND among all the slaves capabilities\n * of the slaves waiting for this BGSAVE, so represents the slave capabilities\n * all the slaves support. Can be tested via SLAVE_CAPA_* macros.\n *\n * Side effects, other than starting a BGSAVE:\n *\n * 1) Handle the slaves in WAIT_START state, by preparing them for a full\n *    sync if the BGSAVE was succesfully started, or sending them an error\n *    and dropping them from the list of slaves.\n *\n * 2) Flush the Lua scripting script cache if the BGSAVE was actually\n *    started.\n *\n * Returns C_OK on success or C_ERR otherwise. */\nint startBgsaveForReplication(int mincapa) {\n    int retval;\n    int socket_target = server.repl_diskless_sync && (mincapa & SLAVE_CAPA_EOF);\n    listIter li;\n    listNode *ln;\n\n    serverLog(LL_NOTICE,\"Starting BGSAVE for SYNC with target: %s\",\n        socket_target ? \"slaves sockets\" : \"disk\");\n\n    if (socket_target)\n        retval = rdbSaveToSlavesSockets();\n    else\n        retval = rdbSaveBackground(server.rdb_filename);\n\n    /* If we failed to BGSAVE, remove the slaves waiting for a full\n     * resynchorinization from the list of salves, inform them with\n     * an error about what happened, close the connection ASAP. */\n    if (retval == C_ERR) {\n        serverLog(LL_WARNING,\"BGSAVE for replication failed\");\n        listRewind(server.slaves,&li);\n        while((ln = listNext(&li))) {\n            client *slave = ln->value;\n\n            if (slave->replstate == SLAVE_STATE_WAIT_BGSAVE_START) {\n                slave->flags &= ~CLIENT_SLAVE;\n                listDelNode(server.slaves,ln);\n                addReplyError(slave,\n                    \"BGSAVE failed, replication can't continue\");\n                slave->flags |= CLIENT_CLOSE_AFTER_REPLY;\n            }\n        }\n        return retval;\n    }\n\n    /* If the target is socket, rdbSaveToSlavesSockets() already setup\n     * the salves for a full resync. Otherwise for disk target do it now.*/\n    if (!socket_target) {\n        listRewind(server.slaves,&li);\n        while((ln = listNext(&li))) {\n            client *slave = ln->value;\n\n            if (slave->replstate == SLAVE_STATE_WAIT_BGSAVE_START) {\n                    replicationSetupSlaveForFullResync(slave,\n                            getPsyncInitialOffset());\n            }\n        }\n    }\n\n    /* Flush the script cache, since we need that slave differences are\n     * accumulated without requiring slaves to match our cached scripts. */\n    if (retval == C_OK) replicationScriptCacheFlush();\n    return retval;\n}\n\n/* SYNC and PSYNC command implemenation. */\nvoid syncCommand(client *c) {\n    /* ignore SYNC if already slave or in monitor mode */\n    if (c->flags & CLIENT_SLAVE) return;\n\n    /* Refuse SYNC requests if we are a slave but the link with our master\n     * is not ok... */\n    if (server.masterhost && server.repl_state != REPL_STATE_CONNECTED) {\n        addReplyError(c,\"Can't SYNC while not connected with my master\");\n        return;\n    }\n\n    /* SYNC can't be issued when the server has pending data to send to\n     * the client about already issued commands. We need a fresh reply\n     * buffer registering the differences between the BGSAVE and the current\n     * dataset, so that we can copy to other slaves if needed. */\n    if (clientHasPendingReplies(c)) {\n        addReplyError(c,\"SYNC and PSYNC are invalid with pending output\");\n        return;\n    }\n\n    serverLog(LL_NOTICE,\"Slave %s asks for synchronization\",\n        replicationGetSlaveName(c));\n\n    /* Try a partial resynchronization if this is a PSYNC command.\n     * If it fails, we continue with usual full resynchronization, however\n     * when this happens masterTryPartialResynchronization() already\n     * replied with:\n     *\n     * +FULLRESYNC <runid> <offset>\n     *\n     * So the slave knows the new runid and offset to try a PSYNC later\n     * if the connection with the master is lost. */\n    if (!strcasecmp(c->argv[0]->ptr,\"psync\")) {\n        if (masterTryPartialResynchronization(c) == C_OK) {\n            server.stat_sync_partial_ok++;\n            return; /* No full resync needed, return. */\n        } else {\n            char *master_runid = c->argv[1]->ptr;\n\n            /* Increment stats for failed PSYNCs, but only if the\n             * runid is not \"?\", as this is used by slaves to force a full\n             * resync on purpose when they are not albe to partially\n             * resync. */\n            if (master_runid[0] != '?') server.stat_sync_partial_err++;\n        }\n    } else {\n        /* If a slave uses SYNC, we are dealing with an old implementation\n         * of the replication protocol (like redis-cli --slave). Flag the client\n         * so that we don't expect to receive REPLCONF ACK feedbacks. */\n        c->flags |= CLIENT_PRE_PSYNC;\n    }\n\n    /* Full resynchronization. */\n    server.stat_sync_full++;\n\n    /* Setup the slave as one waiting for BGSAVE to start. The following code\n     * paths will change the state if we handle the slave differently. */\n    c->replstate = SLAVE_STATE_WAIT_BGSAVE_START;\n    if (server.repl_disable_tcp_nodelay)\n        anetDisableTcpNoDelay(NULL, c->fd); /* Non critical if it fails. */\n    c->repldbfd = -1;\n    c->flags |= CLIENT_SLAVE;\n    listAddNodeTail(server.slaves,c);\n\n    /* CASE 1: BGSAVE is in progress, with disk target. */\n    if (server.rdb_child_pid != -1 &&\n        server.rdb_child_type == RDB_CHILD_TYPE_DISK)\n    {\n        /* Ok a background save is in progress. Let's check if it is a good\n         * one for replication, i.e. if there is another slave that is\n         * registering differences since the server forked to save. */\n        client *slave;\n        listNode *ln;\n        listIter li;\n\n        listRewind(server.slaves,&li);\n        while((ln = listNext(&li))) {\n            slave = ln->value;\n            if (slave->replstate == SLAVE_STATE_WAIT_BGSAVE_END) break;\n        }\n        /* To attach this slave, we check that it has at least all the\n         * capabilities of the slave that triggered the current BGSAVE. */\n        if (ln && ((c->slave_capa & slave->slave_capa) == slave->slave_capa)) {\n            /* Perfect, the server is already registering differences for\n             * another slave. Set the right state, and copy the buffer. */\n            copyClientOutputBuffer(c,slave);\n            replicationSetupSlaveForFullResync(c,slave->psync_initial_offset);\n            serverLog(LL_NOTICE,\"Waiting for end of BGSAVE for SYNC\");\n        } else {\n            /* No way, we need to wait for the next BGSAVE in order to\n             * register differences. */\n            serverLog(LL_NOTICE,\"Can't attach the slave to the current BGSAVE. Waiting for next BGSAVE for SYNC\");\n        }\n\n    /* CASE 2: BGSAVE is in progress, with socket target. */\n    } else if (server.rdb_child_pid != -1 &&\n               server.rdb_child_type == RDB_CHILD_TYPE_SOCKET)\n    {\n        /* There is an RDB child process but it is writing directly to\n         * children sockets. We need to wait for the next BGSAVE\n         * in order to synchronize. */\n        serverLog(LL_NOTICE,\"Current BGSAVE has socket target. Waiting for next BGSAVE for SYNC\");\n\n    /* CASE 3: There is no BGSAVE is progress. */\n    } else {\n        if (server.repl_diskless_sync && (c->slave_capa & SLAVE_CAPA_EOF)) {\n            /* Diskless replication RDB child is created inside\n             * replicationCron() since we want to delay its start a\n             * few seconds to wait for more slaves to arrive. */\n            if (server.repl_diskless_sync_delay)\n                serverLog(LL_NOTICE,\"Delay next BGSAVE for diskless SYNC\");\n        } else {\n            /* Target is disk (or the slave is not capable of supporting\n             * diskless replication) and we don't have a BGSAVE in progress,\n             * let's start one. */\n            if (server.aof_child_pid == -1) {\n                startBgsaveForReplication(c->slave_capa);\n            } else {\n                serverLog(LL_NOTICE,\n                    \"No BGSAVE in progress, but an AOF rewrite is active. \"\n                    \"BGSAVE for replication delayed\");\n            }\n        }\n    }\n\n    if (listLength(server.slaves) == 1 && server.repl_backlog == NULL)\n        createReplicationBacklog();\n    return;\n}\n\n/* REPLCONF <option> <value> <option> <value> ...\n * This command is used by a slave in order to configure the replication\n * process before starting it with the SYNC command.\n *\n * Currently the only use of this command is to communicate to the master\n * what is the listening port of the Slave redis instance, so that the\n * master can accurately list slaves and their listening ports in\n * the INFO output.\n *\n * In the future the same command can be used in order to configure\n * the replication to initiate an incremental replication instead of a\n * full resync. */\nvoid replconfCommand(client *c) {\n    int j;\n\n    if ((c->argc % 2) == 0) {\n        /* Number of arguments must be odd to make sure that every\n         * option has a corresponding value. */\n        addReply(c,shared.syntaxerr);\n        return;\n    }\n\n    /* Process every option-value pair. */\n    for (j = 1; j < c->argc; j+=2) {\n        if (!strcasecmp(c->argv[j]->ptr,\"listening-port\")) {\n            long port;\n\n            if ((getLongFromObjectOrReply(c,c->argv[j+1],\n                    &port,NULL) != C_OK))\n                return;\n            c->slave_listening_port = port;\n        } else if (!strcasecmp(c->argv[j]->ptr,\"ip-address\")) {\n            sds ip = c->argv[j+1]->ptr;\n            if (sdslen(ip) < sizeof(c->slave_ip)) {\n                memcpy(c->slave_ip,ip,sdslen(ip)+1);\n            } else {\n                addReplyErrorFormat(c,\"REPLCONF ip-address provided by \"\n                    \"slave instance is too long: %zd bytes\", sdslen(ip));\n                return;\n            }\n        } else if (!strcasecmp(c->argv[j]->ptr,\"capa\")) {\n            /* Ignore capabilities not understood by this master. */\n            if (!strcasecmp(c->argv[j+1]->ptr,\"eof\"))\n                c->slave_capa |= SLAVE_CAPA_EOF;\n        } else if (!strcasecmp(c->argv[j]->ptr,\"ack\")) {\n            /* REPLCONF ACK is used by slave to inform the master the amount\n             * of replication stream that it processed so far. It is an\n             * internal only command that normal clients should never use. */\n            long long offset;\n\n            if (!(c->flags & CLIENT_SLAVE)) return;\n            if ((getLongLongFromObject(c->argv[j+1], &offset) != C_OK))\n                return;\n            if (offset > c->repl_ack_off)\n                c->repl_ack_off = offset;\n            c->repl_ack_time = server.unixtime;\n            /* If this was a diskless replication, we need to really put\n             * the slave online when the first ACK is received (which\n             * confirms slave is online and ready to get more data). */\n            if (c->repl_put_online_on_ack && c->replstate == SLAVE_STATE_ONLINE)\n                putSlaveOnline(c);\n            /* Note: this command does not reply anything! */\n            return;\n        } else if (!strcasecmp(c->argv[j]->ptr,\"getack\")) {\n            /* REPLCONF GETACK is used in order to request an ACK ASAP\n             * to the slave. */\n            if (server.masterhost && server.master) replicationSendAck();\n            /* Note: this command does not reply anything! */\n        } else {\n            addReplyErrorFormat(c,\"Unrecognized REPLCONF option: %s\",\n                (char*)c->argv[j]->ptr);\n            return;\n        }\n    }\n    addReply(c,shared.ok);\n}\n\n/* This function puts a slave in the online state, and should be called just\n * after a slave received the RDB file for the initial synchronization, and\n * we are finally ready to send the incremental stream of commands.\n *\n * It does a few things:\n *\n * 1) Put the slave in ONLINE state (useless when the function is called\n *    because state is already ONLINE but repl_put_online_on_ack is true).\n * 2) Make sure the writable event is re-installed, since calling the SYNC\n *    command disables it, so that we can accumulate output buffer without\n *    sending it to the slave.\n * 3) Update the count of good slaves. */\nvoid putSlaveOnline(client *slave) {\n    slave->replstate = SLAVE_STATE_ONLINE;\n    slave->repl_put_online_on_ack = 0;\n    slave->repl_ack_time = server.unixtime; /* Prevent false timeout. */\n    if (aeCreateFileEvent(server.el, slave->fd, AE_WRITABLE,\n        sendReplyToClient, slave) == AE_ERR) {\n        serverLog(LL_WARNING,\"Unable to register writable event for slave bulk transfer: %s\", strerror(errno));\n        freeClient(slave);\n        return;\n    }\n    refreshGoodSlavesCount();\n    serverLog(LL_NOTICE,\"Synchronization with slave %s succeeded\",\n        replicationGetSlaveName(slave));\n}\n\nvoid sendBulkToSlave(aeEventLoop *el, int fd, void *privdata, int mask) {\n    client *slave = privdata;\n    UNUSED(el);\n    UNUSED(mask);\n    char buf[PROTO_IOBUF_LEN];\n    ssize_t nwritten, buflen;\n\n    /* Before sending the RDB file, we send the preamble as configured by the\n     * replication process. Currently the preamble is just the bulk count of\n     * the file in the form \"$<length>\\r\\n\". */\n    if (slave->replpreamble) {\n        nwritten = write(fd,slave->replpreamble,sdslen(slave->replpreamble));\n        if (nwritten == -1) {\n            serverLog(LL_VERBOSE,\"Write error sending RDB preamble to slave: %s\",\n                strerror(errno));\n            freeClient(slave);\n            return;\n        }\n        server.stat_net_output_bytes += nwritten;\n        sdsrange(slave->replpreamble,nwritten,-1);\n        if (sdslen(slave->replpreamble) == 0) {\n            sdsfree(slave->replpreamble);\n            slave->replpreamble = NULL;\n            /* fall through sending data. */\n        } else {\n            return;\n        }\n    }\n\n    /* If the preamble was already transfered, send the RDB bulk data. */\n    lseek(slave->repldbfd,slave->repldboff,SEEK_SET);\n    buflen = read(slave->repldbfd,buf,PROTO_IOBUF_LEN);\n    if (buflen <= 0) {\n        serverLog(LL_WARNING,\"Read error sending DB to slave: %s\",\n            (buflen == 0) ? \"premature EOF\" : strerror(errno));\n        freeClient(slave);\n        return;\n    }\n    if ((nwritten = write(fd,buf,buflen)) == -1) {\n        if (errno != EAGAIN) {\n            serverLog(LL_WARNING,\"Write error sending DB to slave: %s\",\n                strerror(errno));\n            freeClient(slave);\n        }\n        return;\n    }\n    slave->repldboff += nwritten;\n    server.stat_net_output_bytes += nwritten;\n    if (slave->repldboff == slave->repldbsize) {\n        close(slave->repldbfd);\n        slave->repldbfd = -1;\n        aeDeleteFileEvent(server.el,slave->fd,AE_WRITABLE);\n        putSlaveOnline(slave);\n    }\n}\n\n/* This function is called at the end of every background saving,\n * or when the replication RDB transfer strategy is modified from\n * disk to socket or the other way around.\n *\n * The goal of this function is to handle slaves waiting for a successful\n * background saving in order to perform non-blocking synchronization, and\n * to schedule a new BGSAVE if there are slaves that attached while a\n * BGSAVE was in progress, but it was not a good one for replication (no\n * other slave was accumulating differences).\n *\n * The argument bgsaveerr is C_OK if the background saving succeeded\n * otherwise C_ERR is passed to the function.\n * The 'type' argument is the type of the child that terminated\n * (if it had a disk or socket target). */\nvoid updateSlavesWaitingBgsave(int bgsaveerr, int type) {\n    listNode *ln;\n    int startbgsave = 0;\n    int mincapa = -1;\n    listIter li;\n\n    listRewind(server.slaves,&li);\n    while((ln = listNext(&li))) {\n        client *slave = ln->value;\n\n        if (slave->replstate == SLAVE_STATE_WAIT_BGSAVE_START) {\n            startbgsave = 1;\n            mincapa = (mincapa == -1) ? slave->slave_capa :\n                                        (mincapa & slave->slave_capa);\n        } else if (slave->replstate == SLAVE_STATE_WAIT_BGSAVE_END) {\n            struct redis_stat buf;\n\n            /* If this was an RDB on disk save, we have to prepare to send\n             * the RDB from disk to the slave socket. Otherwise if this was\n             * already an RDB -> Slaves socket transfer, used in the case of\n             * diskless replication, our work is trivial, we can just put\n             * the slave online. */\n            if (type == RDB_CHILD_TYPE_SOCKET) {\n                serverLog(LL_NOTICE,\n                    \"Streamed RDB transfer with slave %s succeeded (socket). Waiting for REPLCONF ACK from slave to enable streaming\",\n                        replicationGetSlaveName(slave));\n                /* Note: we wait for a REPLCONF ACK message from slave in\n                 * order to really put it online (install the write handler\n                 * so that the accumulated data can be transfered). However\n                 * we change the replication state ASAP, since our slave\n                 * is technically online now. */\n                slave->replstate = SLAVE_STATE_ONLINE;\n                slave->repl_put_online_on_ack = 1;\n                slave->repl_ack_time = server.unixtime; /* Timeout otherwise. */\n            } else {\n                if (bgsaveerr != C_OK) {\n                    freeClient(slave);\n                    serverLog(LL_WARNING,\"SYNC failed. BGSAVE child returned an error\");\n                    continue;\n                }\n                if ((slave->repldbfd = open(server.rdb_filename,O_RDONLY)) == -1 ||\n                    redis_fstat(slave->repldbfd,&buf) == -1) {\n                    freeClient(slave);\n                    serverLog(LL_WARNING,\"SYNC failed. Can't open/stat DB after BGSAVE: %s\", strerror(errno));\n                    continue;\n                }\n                slave->repldboff = 0;\n                slave->repldbsize = buf.st_size;\n                slave->replstate = SLAVE_STATE_SEND_BULK;\n                slave->replpreamble = sdscatprintf(sdsempty(),\"$%lld\\r\\n\",\n                    (unsigned long long) slave->repldbsize);\n\n                aeDeleteFileEvent(server.el,slave->fd,AE_WRITABLE);\n                if (aeCreateFileEvent(server.el, slave->fd, AE_WRITABLE, sendBulkToSlave, slave) == AE_ERR) {\n                    freeClient(slave);\n                    continue;\n                }\n            }\n        }\n    }\n    if (startbgsave) startBgsaveForReplication(mincapa);\n}\n\n/* ----------------------------------- SLAVE -------------------------------- */\n\n/* Returns 1 if the given replication state is a handshake state,\n * 0 otherwise. */\nint slaveIsInHandshakeState(void) {\n    return server.repl_state >= REPL_STATE_RECEIVE_PONG &&\n           server.repl_state <= REPL_STATE_RECEIVE_PSYNC;\n}\n\n/* Avoid the master to detect the slave is timing out while loading the\n * RDB file in initial synchronization. We send a single newline character\n * that is valid protocol but is guaranteed to either be sent entierly or\n * not, since the byte is indivisible.\n *\n * The function is called in two contexts: while we flush the current\n * data with emptyDb(), and while we load the new data received as an\n * RDB file from the master. */\nvoid replicationSendNewlineToMaster(void) {\n    static time_t newline_sent;\n    if (time(NULL) != newline_sent) {\n        newline_sent = time(NULL);\n        if (write(server.repl_transfer_s,\"\\n\",1) == -1) {\n            /* Pinging back in this stage is best-effort. */\n        }\n    }\n}\n\n/* Callback used by emptyDb() while flushing away old data to load\n * the new dataset received by the master. */\nvoid replicationEmptyDbCallback(void *privdata) {\n    UNUSED(privdata);\n    replicationSendNewlineToMaster();\n}\n\n/* Once we have a link with the master and the synchroniziation was\n * performed, this function materializes the master client we store\n * at server.master, starting from the specified file descriptor. */\nvoid replicationCreateMasterClient(int fd) {\n    server.master = createClient(fd);\n    server.master->flags |= CLIENT_MASTER;\n    server.master->authenticated = 1;\n    server.repl_state = REPL_STATE_CONNECTED;\n    server.master->reploff = server.repl_master_initial_offset;\n    memcpy(server.master->replrunid, server.repl_master_runid,\n        sizeof(server.repl_master_runid));\n    /* If master offset is set to -1, this master is old and is not\n     * PSYNC capable, so we flag it accordingly. */\n    if (server.master->reploff == -1)\n        server.master->flags |= CLIENT_PRE_PSYNC;\n}\n\n/* Asynchronously read the SYNC payload we receive from a master */\n#define REPL_MAX_WRITTEN_BEFORE_FSYNC (1024*1024*8) /* 8 MB */\nvoid readSyncBulkPayload(aeEventLoop *el, int fd, void *privdata, int mask) {\n    char buf[4096];\n    ssize_t nread, readlen;\n    off_t left;\n    UNUSED(el);\n    UNUSED(privdata);\n    UNUSED(mask);\n\n    /* Static vars used to hold the EOF mark, and the last bytes received\n     * form the server: when they match, we reached the end of the transfer. */\n    static char eofmark[CONFIG_RUN_ID_SIZE];\n    static char lastbytes[CONFIG_RUN_ID_SIZE];\n    static int usemark = 0;\n\n    /* If repl_transfer_size == -1 we still have to read the bulk length\n     * from the master reply. */\n    if (server.repl_transfer_size == -1) {\n        if (syncReadLine(fd,buf,1024,server.repl_syncio_timeout*1000) == -1) {\n            serverLog(LL_WARNING,\n                \"I/O error reading bulk count from MASTER: %s\",\n                strerror(errno));\n            goto error;\n        }\n\n        if (buf[0] == '-') {\n            serverLog(LL_WARNING,\n                \"MASTER aborted replication with an error: %s\",\n                buf+1);\n            goto error;\n        } else if (buf[0] == '\\0') {\n            /* At this stage just a newline works as a PING in order to take\n             * the connection live. So we refresh our last interaction\n             * timestamp. */\n            server.repl_transfer_lastio = server.unixtime;\n            return;\n        } else if (buf[0] != '$') {\n            serverLog(LL_WARNING,\"Bad protocol from MASTER, the first byte is not '$' (we received '%s'), are you sure the host and port are right?\", buf);\n            goto error;\n        }\n\n        /* There are two possible forms for the bulk payload. One is the\n         * usual $<count> bulk format. The other is used for diskless transfers\n         * when the master does not know beforehand the size of the file to\n         * transfer. In the latter case, the following format is used:\n         *\n         * $EOF:<40 bytes delimiter>\n         *\n         * At the end of the file the announced delimiter is transmitted. The\n         * delimiter is long and random enough that the probability of a\n         * collision with the actual file content can be ignored. */\n        if (strncmp(buf+1,\"EOF:\",4) == 0 && strlen(buf+5) >= CONFIG_RUN_ID_SIZE) {\n            usemark = 1;\n            memcpy(eofmark,buf+5,CONFIG_RUN_ID_SIZE);\n            memset(lastbytes,0,CONFIG_RUN_ID_SIZE);\n            /* Set any repl_transfer_size to avoid entering this code path\n             * at the next call. */\n            server.repl_transfer_size = 0;\n            serverLog(LL_NOTICE,\n                \"MASTER <-> SLAVE sync: receiving streamed RDB from master\");\n        } else {\n            usemark = 0;\n            server.repl_transfer_size = strtol(buf+1,NULL,10);\n            serverLog(LL_NOTICE,\n                \"MASTER <-> SLAVE sync: receiving %lld bytes from master\",\n                (long long) server.repl_transfer_size);\n        }\n        return;\n    }\n\n    /* Read bulk data */\n    if (usemark) {\n        readlen = sizeof(buf);\n    } else {\n        left = server.repl_transfer_size - server.repl_transfer_read;\n        readlen = (left < (signed)sizeof(buf)) ? left : (signed)sizeof(buf);\n    }\n\n    nread = read(fd,buf,readlen);\n    if (nread <= 0) {\n        serverLog(LL_WARNING,\"I/O error trying to sync with MASTER: %s\",\n            (nread == -1) ? strerror(errno) : \"connection lost\");\n        cancelReplicationHandshake();\n        return;\n    }\n    server.stat_net_input_bytes += nread;\n\n    /* When a mark is used, we want to detect EOF asap in order to avoid\n     * writing the EOF mark into the file... */\n    int eof_reached = 0;\n\n    if (usemark) {\n        /* Update the last bytes array, and check if it matches our delimiter.*/\n        if (nread >= CONFIG_RUN_ID_SIZE) {\n            memcpy(lastbytes,buf+nread-CONFIG_RUN_ID_SIZE,CONFIG_RUN_ID_SIZE);\n        } else {\n            int rem = CONFIG_RUN_ID_SIZE-nread;\n            memmove(lastbytes,lastbytes+nread,rem);\n            memcpy(lastbytes+rem,buf,nread);\n        }\n        if (memcmp(lastbytes,eofmark,CONFIG_RUN_ID_SIZE) == 0) eof_reached = 1;\n    }\n\n    server.repl_transfer_lastio = server.unixtime;\n    if (write(server.repl_transfer_fd,buf,nread) != nread) {\n        serverLog(LL_WARNING,\"Write error or short write writing to the DB dump file needed for MASTER <-> SLAVE synchronization: %s\", strerror(errno));\n        goto error;\n    }\n    server.repl_transfer_read += nread;\n\n    /* Delete the last 40 bytes from the file if we reached EOF. */\n    if (usemark && eof_reached) {\n        if (ftruncate(server.repl_transfer_fd,\n            server.repl_transfer_read - CONFIG_RUN_ID_SIZE) == -1)\n        {\n            serverLog(LL_WARNING,\"Error truncating the RDB file received from the master for SYNC: %s\", strerror(errno));\n            goto error;\n        }\n    }\n\n    /* Sync data on disk from time to time, otherwise at the end of the transfer\n     * we may suffer a big delay as the memory buffers are copied into the\n     * actual disk. */\n    if (server.repl_transfer_read >=\n        server.repl_transfer_last_fsync_off + REPL_MAX_WRITTEN_BEFORE_FSYNC)\n    {\n        off_t sync_size = server.repl_transfer_read -\n                          server.repl_transfer_last_fsync_off;\n        rdb_fsync_range(server.repl_transfer_fd,\n            server.repl_transfer_last_fsync_off, sync_size);\n        server.repl_transfer_last_fsync_off += sync_size;\n    }\n\n    /* Check if the transfer is now complete */\n    if (!usemark) {\n        if (server.repl_transfer_read == server.repl_transfer_size)\n            eof_reached = 1;\n    }\n\n    if (eof_reached) {\n        if (rename(server.repl_transfer_tmpfile,server.rdb_filename) == -1) {\n            serverLog(LL_WARNING,\"Failed trying to rename the temp DB into dump.rdb in MASTER <-> SLAVE synchronization: %s\", strerror(errno));\n            cancelReplicationHandshake();\n            return;\n        }\n        serverLog(LL_NOTICE, \"MASTER <-> SLAVE sync: Flushing old data\");\n        signalFlushedDb(-1);\n        emptyDb(replicationEmptyDbCallback);\n        /* Before loading the DB into memory we need to delete the readable\n         * handler, otherwise it will get called recursively since\n         * rdbLoad() will call the event loop to process events from time to\n         * time for non blocking loading. */\n        aeDeleteFileEvent(server.el,server.repl_transfer_s,AE_READABLE);\n        serverLog(LL_NOTICE, \"MASTER <-> SLAVE sync: Loading DB in memory\");\n        if (rdbLoad(server.rdb_filename) != C_OK) {\n            serverLog(LL_WARNING,\"Failed trying to load the MASTER synchronization DB from disk\");\n            cancelReplicationHandshake();\n            return;\n        }\n        /* Final setup of the connected slave <- master link */\n        zfree(server.repl_transfer_tmpfile);\n        close(server.repl_transfer_fd);\n        replicationCreateMasterClient(server.repl_transfer_s);\n        serverLog(LL_NOTICE, \"MASTER <-> SLAVE sync: Finished with success\");\n        /* Restart the AOF subsystem now that we finished the sync. This\n         * will trigger an AOF rewrite, and when done will start appending\n         * to the new file. */\n        if (server.aof_state != AOF_OFF) {\n            int retry = 10;\n\n            stopAppendOnly();\n            while (retry-- && startAppendOnly() == C_ERR) {\n                serverLog(LL_WARNING,\"Failed enabling the AOF after successful master synchronization! Trying it again in one second.\");\n                sleep(1);\n            }\n            if (!retry) {\n                serverLog(LL_WARNING,\"FATAL: this slave instance finished the synchronization with its master, but the AOF can't be turned on. Exiting now.\");\n                exit(1);\n            }\n        }\n    }\n\n    return;\n\nerror:\n    cancelReplicationHandshake();\n    return;\n}\n\n/* Send a synchronous command to the master. Used to send AUTH and\n * REPLCONF commands before starting the replication with SYNC.\n *\n * The command returns an sds string representing the result of the\n * operation. On error the first byte is a \"-\".\n */\n#define SYNC_CMD_READ (1<<0)\n#define SYNC_CMD_WRITE (1<<1)\n#define SYNC_CMD_FULL (SYNC_CMD_READ|SYNC_CMD_WRITE)\nchar *sendSynchronousCommand(int flags, int fd, ...) {\n\n    /* Create the command to send to the master, we use simple inline\n     * protocol for simplicity as currently we only send simple strings. */\n    if (flags & SYNC_CMD_WRITE) {\n        char *arg;\n        va_list ap;\n        sds cmd = sdsempty();\n        va_start(ap,fd);\n\n        while(1) {\n            arg = va_arg(ap, char*);\n            if (arg == NULL) break;\n\n            if (sdslen(cmd) != 0) cmd = sdscatlen(cmd,\" \",1);\n            cmd = sdscat(cmd,arg);\n        }\n        cmd = sdscatlen(cmd,\"\\r\\n\",2);\n\n        /* Transfer command to the server. */\n        if (syncWrite(fd,cmd,sdslen(cmd),server.repl_syncio_timeout*1000)\n            == -1)\n        {\n            sdsfree(cmd);\n            return sdscatprintf(sdsempty(),\"-Writing to master: %s\",\n                    strerror(errno));\n        }\n        sdsfree(cmd);\n        va_end(ap);\n    }\n\n    /* Read the reply from the server. */\n    if (flags & SYNC_CMD_READ) {\n        char buf[256];\n\n        if (syncReadLine(fd,buf,sizeof(buf),server.repl_syncio_timeout*1000)\n            == -1)\n        {\n            return sdscatprintf(sdsempty(),\"-Reading from master: %s\",\n                    strerror(errno));\n        }\n        server.repl_transfer_lastio = server.unixtime;\n        return sdsnew(buf);\n    }\n    return NULL;\n}\n\n/* Try a partial resynchronization with the master if we are about to reconnect.\n * If there is no cached master structure, at least try to issue a\n * \"PSYNC ? -1\" command in order to trigger a full resync using the PSYNC\n * command in order to obtain the master run id and the master replication\n * global offset.\n *\n * This function is designed to be called from syncWithMaster(), so the\n * following assumptions are made:\n *\n * 1) We pass the function an already connected socket \"fd\".\n * 2) This function does not close the file descriptor \"fd\". However in case\n *    of successful partial resynchronization, the function will reuse\n *    'fd' as file descriptor of the server.master client structure.\n *\n * The function is split in two halves: if read_reply is 0, the function\n * writes the PSYNC command on the socket, and a new function call is\n * needed, with read_reply set to 1, in order to read the reply of the\n * command. This is useful in order to support non blocking operations, so\n * that we write, return into the event loop, and read when there are data.\n *\n * When read_reply is 0 the function returns PSYNC_WRITE_ERR if there\n * was a write error, or PSYNC_WAIT_REPLY to signal we need another call\n * with read_reply set to 1. However even when read_reply is set to 1\n * the function may return PSYNC_WAIT_REPLY again to signal there were\n * insufficient data to read to complete its work. We should re-enter\n * into the event loop and wait in such a case.\n *\n * The function returns:\n *\n * PSYNC_CONTINUE: If the PSYNC command succeded and we can continue.\n * PSYNC_FULLRESYNC: If PSYNC is supported but a full resync is needed.\n *                   In this case the master run_id and global replication\n *                   offset is saved.\n * PSYNC_NOT_SUPPORTED: If the server does not understand PSYNC at all and\n *                      the caller should fall back to SYNC.\n * PSYNC_WRITE_ERR: There was an error writing the command to the socket.\n * PSYNC_WAIT_REPLY: Call again the function with read_reply set to 1.\n *\n * Notable side effects:\n *\n * 1) As a side effect of the function call the function removes the readable\n *    event handler from \"fd\", unless the return value is PSYNC_WAIT_REPLY.\n * 2) server.repl_master_initial_offset is set to the right value according\n *    to the master reply. This will be used to populate the 'server.master'\n *    structure replication offset.\n */\n\n#define PSYNC_WRITE_ERROR 0\n#define PSYNC_WAIT_REPLY 1\n#define PSYNC_CONTINUE 2\n#define PSYNC_FULLRESYNC 3\n#define PSYNC_NOT_SUPPORTED 4\nint slaveTryPartialResynchronization(int fd, int read_reply) {\n    char *psync_runid;\n    char psync_offset[32];\n    sds reply;\n\n    /* Writing half */\n    if (!read_reply) {\n        /* Initially set repl_master_initial_offset to -1 to mark the current\n         * master run_id and offset as not valid. Later if we'll be able to do\n         * a FULL resync using the PSYNC command we'll set the offset at the\n         * right value, so that this information will be propagated to the\n         * client structure representing the master into server.master. */\n        server.repl_master_initial_offset = -1;\n\n        if (server.cached_master) {\n            psync_runid = server.cached_master->replrunid;\n            snprintf(psync_offset,sizeof(psync_offset),\"%lld\", server.cached_master->reploff+1);\n            serverLog(LL_NOTICE,\"Trying a partial resynchronization (request %s:%s).\", psync_runid, psync_offset);\n        } else {\n            serverLog(LL_NOTICE,\"Partial resynchronization not possible (no cached master)\");\n            psync_runid = \"?\";\n            memcpy(psync_offset,\"-1\",3);\n        }\n\n        /* Issue the PSYNC command */\n        reply = sendSynchronousCommand(SYNC_CMD_WRITE,fd,\"PSYNC\",psync_runid,psync_offset,NULL);\n        if (reply != NULL) {\n            serverLog(LL_WARNING,\"Unable to send PSYNC to master: %s\",reply);\n            sdsfree(reply);\n            aeDeleteFileEvent(server.el,fd,AE_READABLE);\n            return PSYNC_WRITE_ERROR;\n        }\n        return PSYNC_WAIT_REPLY;\n    }\n\n    /* Reading half */\n    reply = sendSynchronousCommand(SYNC_CMD_READ,fd,NULL);\n    if (sdslen(reply) == 0) {\n        /* The master may send empty newlines after it receives PSYNC\n         * and before to reply, just to keep the connection alive. */\n        sdsfree(reply);\n        return PSYNC_WAIT_REPLY;\n    }\n\n    aeDeleteFileEvent(server.el,fd,AE_READABLE);\n\n    if (!strncmp(reply,\"+FULLRESYNC\",11)) {\n        char *runid = NULL, *offset = NULL;\n\n        /* FULL RESYNC, parse the reply in order to extract the run id\n         * and the replication offset. */\n        runid = strchr(reply,' ');\n        if (runid) {\n            runid++;\n            offset = strchr(runid,' ');\n            if (offset) offset++;\n        }\n        if (!runid || !offset || (offset-runid-1) != CONFIG_RUN_ID_SIZE) {\n            serverLog(LL_WARNING,\n                \"Master replied with wrong +FULLRESYNC syntax.\");\n            /* This is an unexpected condition, actually the +FULLRESYNC\n             * reply means that the master supports PSYNC, but the reply\n             * format seems wrong. To stay safe we blank the master\n             * runid to make sure next PSYNCs will fail. */\n            memset(server.repl_master_runid,0,CONFIG_RUN_ID_SIZE+1);\n        } else {\n            memcpy(server.repl_master_runid, runid, offset-runid-1);\n            server.repl_master_runid[CONFIG_RUN_ID_SIZE] = '\\0';\n            server.repl_master_initial_offset = strtoll(offset,NULL,10);\n            serverLog(LL_NOTICE,\"Full resync from master: %s:%lld\",\n                server.repl_master_runid,\n                server.repl_master_initial_offset);\n        }\n        /* We are going to full resync, discard the cached master structure. */\n        replicationDiscardCachedMaster();\n        sdsfree(reply);\n        return PSYNC_FULLRESYNC;\n    }\n\n    if (!strncmp(reply,\"+CONTINUE\",9)) {\n        /* Partial resync was accepted, set the replication state accordingly */\n        serverLog(LL_NOTICE,\n            \"Successful partial resynchronization with master.\");\n        sdsfree(reply);\n        replicationResurrectCachedMaster(fd);\n        return PSYNC_CONTINUE;\n    }\n\n    /* If we reach this point we received either an error since the master does\n     * not understand PSYNC, or an unexpected reply from the master.\n     * Return PSYNC_NOT_SUPPORTED to the caller in both cases. */\n\n    if (strncmp(reply,\"-ERR\",4)) {\n        /* If it's not an error, log the unexpected event. */\n        serverLog(LL_WARNING,\n            \"Unexpected reply to PSYNC from master: %s\", reply);\n    } else {\n        serverLog(LL_NOTICE,\n            \"Master does not support PSYNC or is in \"\n            \"error state (reply: %s)\", reply);\n    }\n    sdsfree(reply);\n    replicationDiscardCachedMaster();\n    return PSYNC_NOT_SUPPORTED;\n}\n\nvoid syncWithMaster(aeEventLoop *el, int fd, void *privdata, int mask) {\n    char tmpfile[256], *err = NULL;\n    int dfd, maxtries = 5;\n    int sockerr = 0, psync_result;\n    socklen_t errlen = sizeof(sockerr);\n    UNUSED(el);\n    UNUSED(privdata);\n    UNUSED(mask);\n\n    /* If this event fired after the user turned the instance into a master\n     * with SLAVEOF NO ONE we must just return ASAP. */\n    if (server.repl_state == REPL_STATE_NONE) {\n        close(fd);\n        return;\n    }\n\n    /* Check for errors in the socket. */\n    if (getsockopt(fd, SOL_SOCKET, SO_ERROR, &sockerr, &errlen) == -1)\n        sockerr = errno;\n    if (sockerr) {\n        serverLog(LL_WARNING,\"Error condition on socket for SYNC: %s\",\n            strerror(sockerr));\n        goto error;\n    }\n\n    /* Send a PING to check the master is able to reply without errors. */\n    if (server.repl_state == REPL_STATE_CONNECTING) {\n        serverLog(LL_NOTICE,\"Non blocking connect for SYNC fired the event.\");\n        /* Delete the writable event so that the readable event remains\n         * registered and we can wait for the PONG reply. */\n        aeDeleteFileEvent(server.el,fd,AE_WRITABLE);\n        server.repl_state = REPL_STATE_RECEIVE_PONG;\n        /* Send the PING, don't check for errors at all, we have the timeout\n         * that will take care about this. */\n        err = sendSynchronousCommand(SYNC_CMD_WRITE,fd,\"PING\",NULL);\n        if (err) goto write_error;\n        return;\n    }\n\n    /* Receive the PONG command. */\n    if (server.repl_state == REPL_STATE_RECEIVE_PONG) {\n        err = sendSynchronousCommand(SYNC_CMD_READ,fd,NULL);\n\n        /* We accept only two replies as valid, a positive +PONG reply\n         * (we just check for \"+\") or an authentication error.\n         * Note that older versions of Redis replied with \"operation not\n         * permitted\" instead of using a proper error code, so we test\n         * both. */\n        if (err[0] != '+' &&\n            strncmp(err,\"-NOAUTH\",7) != 0 &&\n            strncmp(err,\"-ERR operation not permitted\",28) != 0)\n        {\n            serverLog(LL_WARNING,\"Error reply to PING from master: '%s'\",err);\n            sdsfree(err);\n            goto error;\n        } else {\n            serverLog(LL_NOTICE,\n                \"Master replied to PING, replication can continue...\");\n        }\n        sdsfree(err);\n        server.repl_state = REPL_STATE_SEND_AUTH;\n    }\n\n    /* AUTH with the master if required. */\n    if (server.repl_state == REPL_STATE_SEND_AUTH) {\n        if (server.masterauth) {\n            err = sendSynchronousCommand(SYNC_CMD_WRITE,fd,\"AUTH\",server.masterauth,NULL);\n            if (err) goto write_error;\n            server.repl_state = REPL_STATE_RECEIVE_AUTH;\n            return;\n        } else {\n            server.repl_state = REPL_STATE_SEND_PORT;\n        }\n    }\n\n    /* Receive AUTH reply. */\n    if (server.repl_state == REPL_STATE_RECEIVE_AUTH) {\n        err = sendSynchronousCommand(SYNC_CMD_READ,fd,NULL);\n        if (err[0] == '-') {\n            serverLog(LL_WARNING,\"Unable to AUTH to MASTER: %s\",err);\n            sdsfree(err);\n            goto error;\n        }\n        sdsfree(err);\n        server.repl_state = REPL_STATE_SEND_PORT;\n    }\n\n    /* Set the slave port, so that Master's INFO command can list the\n     * slave listening port correctly. */\n    if (server.repl_state == REPL_STATE_SEND_PORT) {\n        sds port = sdsfromlonglong(server.slave_announce_port ?\n            server.slave_announce_port : server.port);\n        err = sendSynchronousCommand(SYNC_CMD_WRITE,fd,\"REPLCONF\",\n                \"listening-port\",port, NULL);\n        sdsfree(port);\n        if (err) goto write_error;\n        sdsfree(err);\n        server.repl_state = REPL_STATE_RECEIVE_PORT;\n        return;\n    }\n\n    /* Receive REPLCONF listening-port reply. */\n    if (server.repl_state == REPL_STATE_RECEIVE_PORT) {\n        err = sendSynchronousCommand(SYNC_CMD_READ,fd,NULL);\n        /* Ignore the error if any, not all the Redis versions support\n         * REPLCONF listening-port. */\n        if (err[0] == '-') {\n            serverLog(LL_NOTICE,\"(Non critical) Master does not understand \"\n                                \"REPLCONF listening-port: %s\", err);\n        }\n        sdsfree(err);\n        server.repl_state = REPL_STATE_SEND_IP;\n    }\n\n    /* Skip REPLCONF ip-address if there is no slave-announce-ip option set. */\n    if (server.repl_state == REPL_STATE_SEND_IP &&\n        server.slave_announce_ip == NULL)\n    {\n            server.repl_state = REPL_STATE_SEND_CAPA;\n    }\n\n    /* Set the slave ip, so that Master's INFO command can list the\n     * slave IP address port correctly in case of port forwarding or NAT. */\n    if (server.repl_state == REPL_STATE_SEND_IP) {\n        err = sendSynchronousCommand(SYNC_CMD_WRITE,fd,\"REPLCONF\",\n                \"ip-address\",server.slave_announce_ip, NULL);\n        if (err) goto write_error;\n        sdsfree(err);\n        server.repl_state = REPL_STATE_RECEIVE_IP;\n        return;\n    }\n\n    /* Receive REPLCONF ip-address reply. */\n    if (server.repl_state == REPL_STATE_RECEIVE_IP) {\n        err = sendSynchronousCommand(SYNC_CMD_READ,fd,NULL);\n        /* Ignore the error if any, not all the Redis versions support\n         * REPLCONF listening-port. */\n        if (err[0] == '-') {\n            serverLog(LL_NOTICE,\"(Non critical) Master does not understand \"\n                                \"REPLCONF ip-address: %s\", err);\n        }\n        sdsfree(err);\n        server.repl_state = REPL_STATE_SEND_CAPA;\n    }\n\n    /* Inform the master of our capabilities. While we currently send\n     * just one capability, it is possible to chain new capabilities here\n     * in the form of REPLCONF capa X capa Y capa Z ...\n     * The master will ignore capabilities it does not understand. */\n    if (server.repl_state == REPL_STATE_SEND_CAPA) {\n        err = sendSynchronousCommand(SYNC_CMD_WRITE,fd,\"REPLCONF\",\n                \"capa\",\"eof\",NULL);\n        if (err) goto write_error;\n        sdsfree(err);\n        server.repl_state = REPL_STATE_RECEIVE_CAPA;\n        return;\n    }\n\n    /* Receive CAPA reply. */\n    if (server.repl_state == REPL_STATE_RECEIVE_CAPA) {\n        err = sendSynchronousCommand(SYNC_CMD_READ,fd,NULL);\n        /* Ignore the error if any, not all the Redis versions support\n         * REPLCONF capa. */\n        if (err[0] == '-') {\n            serverLog(LL_NOTICE,\"(Non critical) Master does not understand \"\n                                  \"REPLCONF capa: %s\", err);\n        }\n        sdsfree(err);\n        server.repl_state = REPL_STATE_SEND_PSYNC;\n    }\n\n    /* Try a partial resynchonization. If we don't have a cached master\n     * slaveTryPartialResynchronization() will at least try to use PSYNC\n     * to start a full resynchronization so that we get the master run id\n     * and the global offset, to try a partial resync at the next\n     * reconnection attempt. */\n    if (server.repl_state == REPL_STATE_SEND_PSYNC) {\n        if (slaveTryPartialResynchronization(fd,0) == PSYNC_WRITE_ERROR) {\n            err = sdsnew(\"Write error sending the PSYNC command.\");\n            goto write_error;\n        }\n        server.repl_state = REPL_STATE_RECEIVE_PSYNC;\n        return;\n    }\n\n    /* If reached this point, we should be in REPL_STATE_RECEIVE_PSYNC. */\n    if (server.repl_state != REPL_STATE_RECEIVE_PSYNC) {\n        serverLog(LL_WARNING,\"syncWithMaster(): state machine error, \"\n                             \"state should be RECEIVE_PSYNC but is %d\",\n                             server.repl_state);\n        goto error;\n    }\n\n    psync_result = slaveTryPartialResynchronization(fd,1);\n    if (psync_result == PSYNC_WAIT_REPLY) return; /* Try again later... */\n\n    /* Note: if PSYNC does not return WAIT_REPLY, it will take care of\n     * uninstalling the read handler from the file descriptor. */\n\n    if (psync_result == PSYNC_CONTINUE) {\n        serverLog(LL_NOTICE, \"MASTER <-> SLAVE sync: Master accepted a Partial Resynchronization.\");\n        return;\n    }\n\n    /* PSYNC failed or is not supported: we want our slaves to resync with us\n     * as well, if we have any (chained replication case). The mater may\n     * transfer us an entirely different data set and we have no way to\n     * incrementally feed our slaves after that. */\n    disconnectSlaves(); /* Force our slaves to resync with us as well. */\n    freeReplicationBacklog(); /* Don't allow our chained slaves to PSYNC. */\n\n    /* Fall back to SYNC if needed. Otherwise psync_result == PSYNC_FULLRESYNC\n     * and the server.repl_master_runid and repl_master_initial_offset are\n     * already populated. */\n    if (psync_result == PSYNC_NOT_SUPPORTED) {\n        serverLog(LL_NOTICE,\"Retrying with SYNC...\");\n        if (syncWrite(fd,\"SYNC\\r\\n\",6,server.repl_syncio_timeout*1000) == -1) {\n            serverLog(LL_WARNING,\"I/O error writing to MASTER: %s\",\n                strerror(errno));\n            goto error;\n        }\n    }\n\n    /* Prepare a suitable temp file for bulk transfer */\n    while(maxtries--) {\n        snprintf(tmpfile,256,\n            \"temp-%d.%ld.rdb\",(int)server.unixtime,(long int)getpid());\n        dfd = open(tmpfile,O_CREAT|O_WRONLY|O_EXCL,0644);\n        if (dfd != -1) break;\n        sleep(1);\n    }\n    if (dfd == -1) {\n        serverLog(LL_WARNING,\"Opening the temp file needed for MASTER <-> SLAVE synchronization: %s\",strerror(errno));\n        goto error;\n    }\n\n    /* Setup the non blocking download of the bulk file. */\n    if (aeCreateFileEvent(server.el,fd, AE_READABLE,readSyncBulkPayload,NULL)\n            == AE_ERR)\n    {\n        serverLog(LL_WARNING,\n            \"Can't create readable event for SYNC: %s (fd=%d)\",\n            strerror(errno),fd);\n        goto error;\n    }\n\n    server.repl_state = REPL_STATE_TRANSFER;\n    server.repl_transfer_size = -1;\n    server.repl_transfer_read = 0;\n    server.repl_transfer_last_fsync_off = 0;\n    server.repl_transfer_fd = dfd;\n    server.repl_transfer_lastio = server.unixtime;\n    server.repl_transfer_tmpfile = zstrdup(tmpfile);\n    return;\n\nerror:\n    aeDeleteFileEvent(server.el,fd,AE_READABLE|AE_WRITABLE);\n    close(fd);\n    server.repl_transfer_s = -1;\n    server.repl_state = REPL_STATE_CONNECT;\n    return;\n\nwrite_error: /* Handle sendSynchronousCommand(SYNC_CMD_WRITE) errors. */\n    serverLog(LL_WARNING,\"Sending command to master in replication handshake: %s\", err);\n    sdsfree(err);\n    goto error;\n}\n\nint connectWithMaster(void) {\n    int fd;\n\n    fd = anetTcpNonBlockBestEffortBindConnect(NULL,\n        server.masterhost,server.masterport,NET_FIRST_BIND_ADDR);\n    if (fd == -1) {\n        serverLog(LL_WARNING,\"Unable to connect to MASTER: %s\",\n            strerror(errno));\n        return C_ERR;\n    }\n\n    if (aeCreateFileEvent(server.el,fd,AE_READABLE|AE_WRITABLE,syncWithMaster,NULL) ==\n            AE_ERR)\n    {\n        close(fd);\n        serverLog(LL_WARNING,\"Can't create readable event for SYNC\");\n        return C_ERR;\n    }\n\n    server.repl_transfer_lastio = server.unixtime;\n    server.repl_transfer_s = fd;\n    server.repl_state = REPL_STATE_CONNECTING;\n    return C_OK;\n}\n\n/* This function can be called when a non blocking connection is currently\n * in progress to undo it.\n * Never call this function directly, use cancelReplicationHandshake() instead.\n */\nvoid undoConnectWithMaster(void) {\n    int fd = server.repl_transfer_s;\n\n    aeDeleteFileEvent(server.el,fd,AE_READABLE|AE_WRITABLE);\n    close(fd);\n    server.repl_transfer_s = -1;\n}\n\n/* Abort the async download of the bulk dataset while SYNC-ing with master.\n * Never call this function directly, use cancelReplicationHandshake() instead.\n */\nvoid replicationAbortSyncTransfer(void) {\n    serverAssert(server.repl_state == REPL_STATE_TRANSFER);\n    undoConnectWithMaster();\n    close(server.repl_transfer_fd);\n    unlink(server.repl_transfer_tmpfile);\n    zfree(server.repl_transfer_tmpfile);\n}\n\n/* This function aborts a non blocking replication attempt if there is one\n * in progress, by canceling the non-blocking connect attempt or\n * the initial bulk transfer.\n *\n * If there was a replication handshake in progress 1 is returned and\n * the replication state (server.repl_state) set to REPL_STATE_CONNECT.\n *\n * Otherwise zero is returned and no operation is perforemd at all. */\nint cancelReplicationHandshake(void) {\n    if (server.repl_state == REPL_STATE_TRANSFER) {\n        replicationAbortSyncTransfer();\n        server.repl_state = REPL_STATE_CONNECT;\n    } else if (server.repl_state == REPL_STATE_CONNECTING ||\n               slaveIsInHandshakeState())\n    {\n        undoConnectWithMaster();\n        server.repl_state = REPL_STATE_CONNECT;\n    } else {\n        return 0;\n    }\n    return 1;\n}\n\n/* Set replication to the specified master address and port. */\nvoid replicationSetMaster(char *ip, int port) {\n    sdsfree(server.masterhost);\n    server.masterhost = sdsnew(ip);\n    server.masterport = port;\n    if (server.master) freeClient(server.master);\n    disconnectAllBlockedClients(); /* Clients blocked in master, now slave. */\n    disconnectSlaves(); /* Force our slaves to resync with us as well. */\n    replicationDiscardCachedMaster(); /* Don't try a PSYNC. */\n    freeReplicationBacklog(); /* Don't allow our chained slaves to PSYNC. */\n    cancelReplicationHandshake();\n    server.repl_state = REPL_STATE_CONNECT;\n    server.master_repl_offset = 0;\n    server.repl_down_since = 0;\n}\n\n/* Cancel replication, setting the instance as a master itself. */\nvoid replicationUnsetMaster(void) {\n    if (server.masterhost == NULL) return; /* Nothing to do. */\n    sdsfree(server.masterhost);\n    server.masterhost = NULL;\n    if (server.master) {\n        if (listLength(server.slaves) == 0) {\n            /* If this instance is turned into a master and there are no\n             * slaves, it inherits the replication offset from the master.\n             * Under certain conditions this makes replicas comparable by\n             * replication offset to understand what is the most updated. */\n            server.master_repl_offset = server.master->reploff;\n            freeReplicationBacklog();\n        }\n        freeClient(server.master);\n    }\n    replicationDiscardCachedMaster();\n    cancelReplicationHandshake();\n    server.repl_state = REPL_STATE_NONE;\n}\n\n/* This function is called when the slave lose the connection with the\n * master into an unexpected way. */\nvoid replicationHandleMasterDisconnection(void) {\n    server.master = NULL;\n    server.repl_state = REPL_STATE_CONNECT;\n    server.repl_down_since = server.unixtime;\n    /* We lost connection with our master, don't disconnect slaves yet,\n     * maybe we'll be able to PSYNC with our master later. We'll disconnect\n     * the slaves only if we'll have to do a full resync with our master. */\n}\n\nvoid slaveofCommand(client *c) {\n    /* SLAVEOF is not allowed in cluster mode as replication is automatically\n     * configured using the current address of the master node. */\n    if (server.cluster_enabled) {\n        addReplyError(c,\"SLAVEOF not allowed in cluster mode.\");\n        return;\n    }\n\n    /* The special host/port combination \"NO\" \"ONE\" turns the instance\n     * into a master. Otherwise the new master address is set. */\n    if (!strcasecmp(c->argv[1]->ptr,\"no\") &&\n        !strcasecmp(c->argv[2]->ptr,\"one\")) {\n        if (server.masterhost) {\n            replicationUnsetMaster();\n            sds client = catClientInfoString(sdsempty(),c);\n            serverLog(LL_NOTICE,\"MASTER MODE enabled (user request from '%s')\",\n                client);\n            sdsfree(client);\n        }\n    } else {\n        long port;\n\n        if ((getLongFromObjectOrReply(c, c->argv[2], &port, NULL) != C_OK))\n            return;\n\n        /* Check if we are already attached to the specified slave */\n        if (server.masterhost && !strcasecmp(server.masterhost,c->argv[1]->ptr)\n            && server.masterport == port) {\n            serverLog(LL_NOTICE,\"SLAVE OF would result into synchronization with the master we are already connected with. No operation performed.\");\n            addReplySds(c,sdsnew(\"+OK Already connected to specified master\\r\\n\"));\n            return;\n        }\n        /* There was no previous master or the user specified a different one,\n         * we can continue. */\n        replicationSetMaster(c->argv[1]->ptr, port);\n        sds client = catClientInfoString(sdsempty(),c);\n        serverLog(LL_NOTICE,\"SLAVE OF %s:%d enabled (user request from '%s')\",\n            server.masterhost, server.masterport, client);\n        sdsfree(client);\n    }\n    addReply(c,shared.ok);\n}\n\n/* ROLE command: provide information about the role of the instance\n * (master or slave) and additional information related to replication\n * in an easy to process format. */\nvoid roleCommand(client *c) {\n    if (server.masterhost == NULL) {\n        listIter li;\n        listNode *ln;\n        void *mbcount;\n        int slaves = 0;\n\n        addReplyMultiBulkLen(c,3);\n        addReplyBulkCBuffer(c,\"master\",6);\n        addReplyLongLong(c,server.master_repl_offset);\n        mbcount = addDeferredMultiBulkLength(c);\n        listRewind(server.slaves,&li);\n        while((ln = listNext(&li))) {\n            client *slave = ln->value;\n            char ip[NET_IP_STR_LEN], *slaveip = slave->slave_ip;\n\n            if (slaveip[0] == '\\0') {\n                if (anetPeerToString(slave->fd,ip,sizeof(ip),NULL) == -1)\n                    continue;\n                slaveip = ip;\n            }\n            if (slave->replstate != SLAVE_STATE_ONLINE) continue;\n            addReplyMultiBulkLen(c,3);\n            addReplyBulkCString(c,slaveip);\n            addReplyBulkLongLong(c,slave->slave_listening_port);\n            addReplyBulkLongLong(c,slave->repl_ack_off);\n            slaves++;\n        }\n        setDeferredMultiBulkLength(c,mbcount,slaves);\n    } else {\n        char *slavestate = NULL;\n\n        addReplyMultiBulkLen(c,5);\n        addReplyBulkCBuffer(c,\"slave\",5);\n        addReplyBulkCString(c,server.masterhost);\n        addReplyLongLong(c,server.masterport);\n        if (slaveIsInHandshakeState()) {\n            slavestate = \"handshake\";\n        } else {\n            switch(server.repl_state) {\n            case REPL_STATE_NONE: slavestate = \"none\"; break;\n            case REPL_STATE_CONNECT: slavestate = \"connect\"; break;\n            case REPL_STATE_CONNECTING: slavestate = \"connecting\"; break;\n            case REPL_STATE_TRANSFER: slavestate = \"sync\"; break;\n            case REPL_STATE_CONNECTED: slavestate = \"connected\"; break;\n            default: slavestate = \"unknown\"; break;\n            }\n        }\n        addReplyBulkCString(c,slavestate);\n        addReplyLongLong(c,server.master ? server.master->reploff : -1);\n    }\n}\n\n/* Send a REPLCONF ACK command to the master to inform it about the current\n * processed offset. If we are not connected with a master, the command has\n * no effects. */\nvoid replicationSendAck(void) {\n    client *c = server.master;\n\n    if (c != NULL) {\n        c->flags |= CLIENT_MASTER_FORCE_REPLY;\n        addReplyMultiBulkLen(c,3);\n        addReplyBulkCString(c,\"REPLCONF\");\n        addReplyBulkCString(c,\"ACK\");\n        addReplyBulkLongLong(c,c->reploff);\n        c->flags &= ~CLIENT_MASTER_FORCE_REPLY;\n    }\n}\n\n/* ---------------------- MASTER CACHING FOR PSYNC -------------------------- */\n\n/* In order to implement partial synchronization we need to be able to cache\n * our master's client structure after a transient disconnection.\n * It is cached into server.cached_master and flushed away using the following\n * functions. */\n\n/* This function is called by freeClient() in order to cache the master\n * client structure instead of destryoing it. freeClient() will return\n * ASAP after this function returns, so every action needed to avoid problems\n * with a client that is really \"suspended\" has to be done by this function.\n *\n * The other functions that will deal with the cached master are:\n *\n * replicationDiscardCachedMaster() that will make sure to kill the client\n * as for some reason we don't want to use it in the future.\n *\n * replicationResurrectCachedMaster() that is used after a successful PSYNC\n * handshake in order to reactivate the cached master.\n */\nvoid replicationCacheMaster(client *c) {\n    serverAssert(server.master != NULL && server.cached_master == NULL);\n    serverLog(LL_NOTICE,\"Caching the disconnected master state.\");\n\n    /* Unlink the client from the server structures. */\n    unlinkClient(c);\n\n    /* Save the master. Server.master will be set to null later by\n     * replicationHandleMasterDisconnection(). */\n    server.cached_master = server.master;\n\n    /* Invalidate the Peer ID cache. */\n    if (c->peerid) {\n        sdsfree(c->peerid);\n        c->peerid = NULL;\n    }\n\n    /* Caching the master happens instead of the actual freeClient() call,\n     * so make sure to adjust the replication state. This function will\n     * also set server.master to NULL. */\n    replicationHandleMasterDisconnection();\n}\n\n/* Free a cached master, called when there are no longer the conditions for\n * a partial resync on reconnection. */\nvoid replicationDiscardCachedMaster(void) {\n    if (server.cached_master == NULL) return;\n\n    serverLog(LL_NOTICE,\"Discarding previously cached master state.\");\n    server.cached_master->flags &= ~CLIENT_MASTER;\n    freeClient(server.cached_master);\n    server.cached_master = NULL;\n}\n\n/* Turn the cached master into the current master, using the file descriptor\n * passed as argument as the socket for the new master.\n *\n * This function is called when successfully setup a partial resynchronization\n * so the stream of data that we'll receive will start from were this\n * master left. */\nvoid replicationResurrectCachedMaster(int newfd) {\n    server.master = server.cached_master;\n    server.cached_master = NULL;\n    server.master->fd = newfd;\n    server.master->flags &= ~(CLIENT_CLOSE_AFTER_REPLY|CLIENT_CLOSE_ASAP);\n    server.master->authenticated = 1;\n    server.master->lastinteraction = server.unixtime;\n    server.repl_state = REPL_STATE_CONNECTED;\n\n    /* Re-add to the list of clients. */\n    listAddNodeTail(server.clients,server.master);\n    if (aeCreateFileEvent(server.el, newfd, AE_READABLE,\n                          readQueryFromClient, server.master)) {\n        serverLog(LL_WARNING,\"Error resurrecting the cached master, impossible to add the readable handler: %s\", strerror(errno));\n        freeClientAsync(server.master); /* Close ASAP. */\n    }\n\n    /* We may also need to install the write handler as well if there is\n     * pending data in the write buffers. */\n    if (clientHasPendingReplies(server.master)) {\n        if (aeCreateFileEvent(server.el, newfd, AE_WRITABLE,\n                          sendReplyToClient, server.master)) {\n            serverLog(LL_WARNING,\"Error resurrecting the cached master, impossible to add the writable handler: %s\", strerror(errno));\n            freeClientAsync(server.master); /* Close ASAP. */\n        }\n    }\n}\n\n/* ------------------------- MIN-SLAVES-TO-WRITE  --------------------------- */\n\n/* This function counts the number of slaves with lag <= min-slaves-max-lag.\n * If the option is active, the server will prevent writes if there are not\n * enough connected slaves with the specified lag (or less). */\nvoid refreshGoodSlavesCount(void) {\n    listIter li;\n    listNode *ln;\n    int good = 0;\n\n    if (!server.repl_min_slaves_to_write ||\n        !server.repl_min_slaves_max_lag) return;\n\n    listRewind(server.slaves,&li);\n    while((ln = listNext(&li))) {\n        client *slave = ln->value;\n        time_t lag = server.unixtime - slave->repl_ack_time;\n\n        if (slave->replstate == SLAVE_STATE_ONLINE &&\n            lag <= server.repl_min_slaves_max_lag) good++;\n    }\n    server.repl_good_slaves_count = good;\n}\n\n/* ----------------------- REPLICATION SCRIPT CACHE --------------------------\n * The goal of this code is to keep track of scripts already sent to every\n * connected slave, in order to be able to replicate EVALSHA as it is without\n * translating it to EVAL every time it is possible.\n *\n * We use a capped collection implemented by a hash table for fast lookup\n * of scripts we can send as EVALSHA, plus a linked list that is used for\n * eviction of the oldest entry when the max number of items is reached.\n *\n * We don't care about taking a different cache for every different slave\n * since to fill the cache again is not very costly, the goal of this code\n * is to avoid that the same big script is trasmitted a big number of times\n * per second wasting bandwidth and processor speed, but it is not a problem\n * if we need to rebuild the cache from scratch from time to time, every used\n * script will need to be transmitted a single time to reappear in the cache.\n *\n * This is how the system works:\n *\n * 1) Every time a new slave connects, we flush the whole script cache.\n * 2) We only send as EVALSHA what was sent to the master as EVALSHA, without\n *    trying to convert EVAL into EVALSHA specifically for slaves.\n * 3) Every time we trasmit a script as EVAL to the slaves, we also add the\n *    corresponding SHA1 of the script into the cache as we are sure every\n *    slave knows about the script starting from now.\n * 4) On SCRIPT FLUSH command, we replicate the command to all the slaves\n *    and at the same time flush the script cache.\n * 5) When the last slave disconnects, flush the cache.\n * 6) We handle SCRIPT LOAD as well since that's how scripts are loaded\n *    in the master sometimes.\n */\n\n/* Initialize the script cache, only called at startup. */\nvoid replicationScriptCacheInit(void) {\n    server.repl_scriptcache_size = 10000;\n    server.repl_scriptcache_dict = dictCreate(&replScriptCacheDictType,NULL);\n    server.repl_scriptcache_fifo = listCreate();\n}\n\n/* Empty the script cache. Should be called every time we are no longer sure\n * that every slave knows about all the scripts in our set, or when the\n * current AOF \"context\" is no longer aware of the script. In general we\n * should flush the cache:\n *\n * 1) Every time a new slave reconnects to this master and performs a\n *    full SYNC (PSYNC does not require flushing).\n * 2) Every time an AOF rewrite is performed.\n * 3) Every time we are left without slaves at all, and AOF is off, in order\n *    to reclaim otherwise unused memory.\n */\nvoid replicationScriptCacheFlush(void) {\n    dictEmpty(server.repl_scriptcache_dict,NULL);\n    listRelease(server.repl_scriptcache_fifo);\n    server.repl_scriptcache_fifo = listCreate();\n}\n\n/* Add an entry into the script cache, if we reach max number of entries the\n * oldest is removed from the list. */\nvoid replicationScriptCacheAdd(sds sha1) {\n    int retval;\n    sds key = sdsdup(sha1);\n\n    /* Evict oldest. */\n    if (listLength(server.repl_scriptcache_fifo) == server.repl_scriptcache_size)\n    {\n        listNode *ln = listLast(server.repl_scriptcache_fifo);\n        sds oldest = listNodeValue(ln);\n\n        retval = dictDelete(server.repl_scriptcache_dict,oldest);\n        serverAssert(retval == DICT_OK);\n        listDelNode(server.repl_scriptcache_fifo,ln);\n    }\n\n    /* Add current. */\n    retval = dictAdd(server.repl_scriptcache_dict,key,NULL);\n    listAddNodeHead(server.repl_scriptcache_fifo,key);\n    serverAssert(retval == DICT_OK);\n}\n\n/* Returns non-zero if the specified entry exists inside the cache, that is,\n * if all the slaves are aware of this script SHA1. */\nint replicationScriptCacheExists(sds sha1) {\n    return dictFind(server.repl_scriptcache_dict,sha1) != NULL;\n}\n\n/* ----------------------- SYNCHRONOUS REPLICATION --------------------------\n * Redis synchronous replication design can be summarized in points:\n *\n * - Redis masters have a global replication offset, used by PSYNC.\n * - Master increment the offset every time new commands are sent to slaves.\n * - Slaves ping back masters with the offset processed so far.\n *\n * So synchronous replication adds a new WAIT command in the form:\n *\n *   WAIT <num_replicas> <milliseconds_timeout>\n *\n * That returns the number of replicas that processed the query when\n * we finally have at least num_replicas, or when the timeout was\n * reached.\n *\n * The command is implemented in this way:\n *\n * - Every time a client processes a command, we remember the replication\n *   offset after sending that command to the slaves.\n * - When WAIT is called, we ask slaves to send an acknowledgement ASAP.\n *   The client is blocked at the same time (see blocked.c).\n * - Once we receive enough ACKs for a given offset or when the timeout\n *   is reached, the WAIT command is unblocked and the reply sent to the\n *   client.\n */\n\n/* This just set a flag so that we broadcast a REPLCONF GETACK command\n * to all the slaves in the beforeSleep() function. Note that this way\n * we \"group\" all the clients that want to wait for synchronouns replication\n * in a given event loop iteration, and send a single GETACK for them all. */\nvoid replicationRequestAckFromSlaves(void) {\n    server.get_ack_from_slaves = 1;\n}\n\n/* Return the number of slaves that already acknowledged the specified\n * replication offset. */\nint replicationCountAcksByOffset(long long offset) {\n    listIter li;\n    listNode *ln;\n    int count = 0;\n\n    listRewind(server.slaves,&li);\n    while((ln = listNext(&li))) {\n        client *slave = ln->value;\n\n        if (slave->replstate != SLAVE_STATE_ONLINE) continue;\n        if (slave->repl_ack_off >= offset) count++;\n    }\n    return count;\n}\n\n/* WAIT for N replicas to acknowledge the processing of our latest\n * write command (and all the previous commands). */\nvoid waitCommand(client *c) {\n    mstime_t timeout;\n    long numreplicas, ackreplicas;\n    long long offset = c->woff;\n\n    /* Argument parsing. */\n    if (getLongFromObjectOrReply(c,c->argv[1],&numreplicas,NULL) != C_OK)\n        return;\n    if (getTimeoutFromObjectOrReply(c,c->argv[2],&timeout,UNIT_MILLISECONDS)\n        != C_OK) return;\n\n    /* First try without blocking at all. */\n    ackreplicas = replicationCountAcksByOffset(c->woff);\n    if (ackreplicas >= numreplicas || c->flags & CLIENT_MULTI) {\n        addReplyLongLong(c,ackreplicas);\n        return;\n    }\n\n    /* Otherwise block the client and put it into our list of clients\n     * waiting for ack from slaves. */\n    c->bpop.timeout = timeout;\n    c->bpop.reploffset = offset;\n    c->bpop.numreplicas = numreplicas;\n    listAddNodeTail(server.clients_waiting_acks,c);\n    blockClient(c,BLOCKED_WAIT);\n\n    /* Make sure that the server will send an ACK request to all the slaves\n     * before returning to the event loop. */\n    replicationRequestAckFromSlaves();\n}\n\n/* This is called by unblockClient() to perform the blocking op type\n * specific cleanup. We just remove the client from the list of clients\n * waiting for replica acks. Never call it directly, call unblockClient()\n * instead. */\nvoid unblockClientWaitingReplicas(client *c) {\n    listNode *ln = listSearchKey(server.clients_waiting_acks,c);\n    serverAssert(ln != NULL);\n    listDelNode(server.clients_waiting_acks,ln);\n}\n\n/* Check if there are clients blocked in WAIT that can be unblocked since\n * we received enough ACKs from slaves. */\nvoid processClientsWaitingReplicas(void) {\n    long long last_offset = 0;\n    int last_numreplicas = 0;\n\n    listIter li;\n    listNode *ln;\n\n    listRewind(server.clients_waiting_acks,&li);\n    while((ln = listNext(&li))) {\n        client *c = ln->value;\n\n        /* Every time we find a client that is satisfied for a given\n         * offset and number of replicas, we remember it so the next client\n         * may be unblocked without calling replicationCountAcksByOffset()\n         * if the requested offset / replicas were equal or less. */\n        if (last_offset && last_offset > c->bpop.reploffset &&\n                           last_numreplicas > c->bpop.numreplicas)\n        {\n            unblockClient(c);\n            addReplyLongLong(c,last_numreplicas);\n        } else {\n            int numreplicas = replicationCountAcksByOffset(c->bpop.reploffset);\n\n            if (numreplicas >= c->bpop.numreplicas) {\n                last_offset = c->bpop.reploffset;\n                last_numreplicas = numreplicas;\n                unblockClient(c);\n                addReplyLongLong(c,numreplicas);\n            }\n        }\n    }\n}\n\n/* Return the slave replication offset for this instance, that is\n * the offset for which we already processed the master replication stream. */\nlong long replicationGetSlaveOffset(void) {\n    long long offset = 0;\n\n    if (server.masterhost != NULL) {\n        if (server.master) {\n            offset = server.master->reploff;\n        } else if (server.cached_master) {\n            offset = server.cached_master->reploff;\n        }\n    }\n    /* offset may be -1 when the master does not support it at all, however\n     * this function is designed to return an offset that can express the\n     * amount of data processed by the master, so we return a positive\n     * integer. */\n    if (offset < 0) offset = 0;\n    return offset;\n}\n\n/* --------------------------- REPLICATION CRON  ---------------------------- */\n\n/* Replication cron function, called 1 time per second. */\nvoid replicationCron(void) {\n    static long long replication_cron_loops = 0;\n\n    /* Non blocking connection timeout? */\n    if (server.masterhost &&\n        (server.repl_state == REPL_STATE_CONNECTING ||\n         slaveIsInHandshakeState()) &&\n         (time(NULL)-server.repl_transfer_lastio) > server.repl_timeout)\n    {\n        serverLog(LL_WARNING,\"Timeout connecting to the MASTER...\");\n        cancelReplicationHandshake();\n    }\n\n    /* Bulk transfer I/O timeout? */\n    if (server.masterhost && server.repl_state == REPL_STATE_TRANSFER &&\n        (time(NULL)-server.repl_transfer_lastio) > server.repl_timeout)\n    {\n        serverLog(LL_WARNING,\"Timeout receiving bulk data from MASTER... If the problem persists try to set the 'repl-timeout' parameter in redis.conf to a larger value.\");\n        cancelReplicationHandshake();\n    }\n\n    /* Timed out master when we are an already connected slave? */\n    if (server.masterhost && server.repl_state == REPL_STATE_CONNECTED &&\n        (time(NULL)-server.master->lastinteraction) > server.repl_timeout)\n    {\n        serverLog(LL_WARNING,\"MASTER timeout: no data nor PING received...\");\n        freeClient(server.master);\n    }\n\n    /* Check if we should connect to a MASTER */\n    if (server.repl_state == REPL_STATE_CONNECT) {\n        serverLog(LL_NOTICE,\"Connecting to MASTER %s:%d\",\n            server.masterhost, server.masterport);\n        if (connectWithMaster() == C_OK) {\n            serverLog(LL_NOTICE,\"MASTER <-> SLAVE sync started\");\n        }\n    }\n\n    /* Send ACK to master from time to time.\n     * Note that we do not send periodic acks to masters that don't\n     * support PSYNC and replication offsets. */\n    if (server.masterhost && server.master &&\n        !(server.master->flags & CLIENT_PRE_PSYNC))\n        replicationSendAck();\n\n    /* If we have attached slaves, PING them from time to time.\n     * So slaves can implement an explicit timeout to masters, and will\n     * be able to detect a link disconnection even if the TCP connection\n     * will not actually go down. */\n    listIter li;\n    listNode *ln;\n    robj *ping_argv[1];\n\n    /* First, send PING according to ping_slave_period. */\n    if ((replication_cron_loops % server.repl_ping_slave_period) == 0) {\n        ping_argv[0] = createStringObject(\"PING\",4);\n        replicationFeedSlaves(server.slaves, server.slaveseldb,\n            ping_argv, 1);\n        decrRefCount(ping_argv[0]);\n    }\n\n    /* Second, send a newline to all the slaves in pre-synchronization\n     * stage, that is, slaves waiting for the master to create the RDB file.\n     * The newline will be ignored by the slave but will refresh the\n     * last-io timer preventing a timeout. In this case we ignore the\n     * ping period and refresh the connection once per second since certain\n     * timeouts are set at a few seconds (example: PSYNC response). */\n    listRewind(server.slaves,&li);\n    while((ln = listNext(&li))) {\n        client *slave = ln->value;\n\n        if (slave->replstate == SLAVE_STATE_WAIT_BGSAVE_START ||\n            (slave->replstate == SLAVE_STATE_WAIT_BGSAVE_END &&\n             server.rdb_child_type != RDB_CHILD_TYPE_SOCKET))\n        {\n            if (write(slave->fd, \"\\n\", 1) == -1) {\n                /* Don't worry, it's just a ping. */\n            }\n        }\n    }\n\n    /* Disconnect timedout slaves. */\n    if (listLength(server.slaves)) {\n        listIter li;\n        listNode *ln;\n\n        listRewind(server.slaves,&li);\n        while((ln = listNext(&li))) {\n            client *slave = ln->value;\n\n            if (slave->replstate != SLAVE_STATE_ONLINE) continue;\n            if (slave->flags & CLIENT_PRE_PSYNC) continue;\n            if ((server.unixtime - slave->repl_ack_time) > server.repl_timeout)\n            {\n                serverLog(LL_WARNING, \"Disconnecting timedout slave: %s\",\n                    replicationGetSlaveName(slave));\n                freeClient(slave);\n            }\n        }\n    }\n\n    /* If we have no attached slaves and there is a replication backlog\n     * using memory, free it after some (configured) time. */\n    if (listLength(server.slaves) == 0 && server.repl_backlog_time_limit &&\n        server.repl_backlog)\n    {\n        time_t idle = server.unixtime - server.repl_no_slaves_since;\n\n        if (idle > server.repl_backlog_time_limit) {\n            freeReplicationBacklog();\n            serverLog(LL_NOTICE,\n                \"Replication backlog freed after %d seconds \"\n                \"without connected slaves.\",\n                (int) server.repl_backlog_time_limit);\n        }\n    }\n\n    /* If AOF is disabled and we no longer have attached slaves, we can\n     * free our Replication Script Cache as there is no need to propagate\n     * EVALSHA at all. */\n    if (listLength(server.slaves) == 0 &&\n        server.aof_state == AOF_OFF &&\n        listLength(server.repl_scriptcache_fifo) != 0)\n    {\n        replicationScriptCacheFlush();\n    }\n\n    /* Start a BGSAVE good for replication if we have slaves in\n     * WAIT_BGSAVE_START state.\n     *\n     * In case of diskless replication, we make sure to wait the specified\n     * number of seconds (according to configuration) so that other slaves\n     * have the time to arrive before we start streaming. */\n    if (server.rdb_child_pid == -1 && server.aof_child_pid == -1) {\n        time_t idle, max_idle = 0;\n        int slaves_waiting = 0;\n        int mincapa = -1;\n        listNode *ln;\n        listIter li;\n\n        listRewind(server.slaves,&li);\n        while((ln = listNext(&li))) {\n            client *slave = ln->value;\n            if (slave->replstate == SLAVE_STATE_WAIT_BGSAVE_START) {\n                idle = server.unixtime - slave->lastinteraction;\n                if (idle > max_idle) max_idle = idle;\n                slaves_waiting++;\n                mincapa = (mincapa == -1) ? slave->slave_capa :\n                                            (mincapa & slave->slave_capa);\n            }\n        }\n\n        if (slaves_waiting &&\n            (!server.repl_diskless_sync ||\n             max_idle > server.repl_diskless_sync_delay))\n        {\n            /* Start the BGSAVE. The called function may start a\n             * BGSAVE with socket target or disk target depending on the\n             * configuration and slaves capabilities. */\n            startBgsaveForReplication(mincapa);\n        }\n    }\n\n    /* Refresh the number of slaves with lag <= min-slaves-max-lag. */\n    refreshGoodSlavesCount();\n    replication_cron_loops++; /* Incremented with frequency 1 HZ. */\n}\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/src/rio.c",
    "content": "/* rio.c is a simple stream-oriented I/O abstraction that provides an interface\n * to write code that can consume/produce data using different concrete input\n * and output devices. For instance the same rdb.c code using the rio\n * abstraction can be used to read and write the RDB format using in-memory\n * buffers or files.\n *\n * A rio object provides the following methods:\n *  read: read from stream.\n *  write: write to stream.\n *  tell: get the current offset.\n *\n * It is also possible to set a 'checksum' method that is used by rio.c in order\n * to compute a checksum of the data written or read, or to query the rio object\n * for the current checksum.\n *\n * ----------------------------------------------------------------------------\n *\n * Copyright (c) 2009-2012, Pieter Noordhuis <pcnoordhuis at gmail dot com>\n * Copyright (c) 2009-2012, Salvatore Sanfilippo <antirez at gmail dot com>\n * All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions are met:\n *\n *   * Redistributions of source code must retain the above copyright notice,\n *     this list of conditions and the following disclaimer.\n *   * Redistributions in binary form must reproduce the above copyright\n *     notice, this list of conditions and the following disclaimer in the\n *     documentation and/or other materials provided with the distribution.\n *   * Neither the name of Redis nor the names of its contributors may be used\n *     to endorse or promote products derived from this software without\n *     specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\"\n * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\n * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE\n * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR\n * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF\n * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS\n * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN\n * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)\n * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE\n * POSSIBILITY OF SUCH DAMAGE.\n */\n\n\n#include \"fmacros.h\"\n#include <string.h>\n#include <stdio.h>\n#include <unistd.h>\n#include \"rio.h\"\n#include \"util.h\"\n#include \"crc64.h\"\n#include \"config.h\"\n#include \"server.h\"\n\n/* ------------------------- Buffer I/O implementation ----------------------- */\n\n/* Returns 1 or 0 for success/failure. */\nstatic size_t rioBufferWrite(rio *r, const void *buf, size_t len) {\n    r->io.buffer.ptr = sdscatlen(r->io.buffer.ptr,(char*)buf,len);\n    r->io.buffer.pos += len;\n    return 1;\n}\n\n/* Returns 1 or 0 for success/failure. */\nstatic size_t rioBufferRead(rio *r, void *buf, size_t len) {\n    if (sdslen(r->io.buffer.ptr)-r->io.buffer.pos < len)\n        return 0; /* not enough buffer to return len bytes. */\n    memcpy(buf,r->io.buffer.ptr+r->io.buffer.pos,len);\n    r->io.buffer.pos += len;\n    return 1;\n}\n\n/* Returns read/write position in buffer. */\nstatic off_t rioBufferTell(rio *r) {\n    return r->io.buffer.pos;\n}\n\n/* Flushes any buffer to target device if applicable. Returns 1 on success\n * and 0 on failures. */\nstatic int rioBufferFlush(rio *r) {\n    UNUSED(r);\n    return 1; /* Nothing to do, our write just appends to the buffer. */\n}\n\nstatic const rio rioBufferIO = {\n    rioBufferRead,\n    rioBufferWrite,\n    rioBufferTell,\n    rioBufferFlush,\n    NULL,           /* update_checksum */\n    0,              /* current checksum */\n    0,              /* bytes read or written */\n    0,              /* read/write chunk size */\n    { { NULL, 0 } } /* union for io-specific vars */\n};\n\nvoid rioInitWithBuffer(rio *r, sds s) {\n    *r = rioBufferIO;\n    r->io.buffer.ptr = s;\n    r->io.buffer.pos = 0;\n}\n\n/* --------------------- Stdio file pointer implementation ------------------- */\n\n/* Returns 1 or 0 for success/failure. */\nstatic size_t rioFileWrite(rio *r, const void *buf, size_t len) {\n    size_t retval;\n\n    retval = fwrite(buf,len,1,r->io.file.fp);\n    r->io.file.buffered += len;\n\n    if (r->io.file.autosync &&\n        r->io.file.buffered >= r->io.file.autosync)\n    {\n        fflush(r->io.file.fp);\n        aof_fsync(fileno(r->io.file.fp));\n        r->io.file.buffered = 0;\n    }\n    return retval;\n}\n\n/* Returns 1 or 0 for success/failure. */\nstatic size_t rioFileRead(rio *r, void *buf, size_t len) {\n    return fread(buf,len,1,r->io.file.fp);\n}\n\n/* Returns read/write position in file. */\nstatic off_t rioFileTell(rio *r) {\n    return ftello(r->io.file.fp);\n}\n\n/* Flushes any buffer to target device if applicable. Returns 1 on success\n * and 0 on failures. */\nstatic int rioFileFlush(rio *r) {\n    return (fflush(r->io.file.fp) == 0) ? 1 : 0;\n}\n\nstatic const rio rioFileIO = {\n    rioFileRead,\n    rioFileWrite,\n    rioFileTell,\n    rioFileFlush,\n    NULL,           /* update_checksum */\n    0,              /* current checksum */\n    0,              /* bytes read or written */\n    0,              /* read/write chunk size */\n    { { NULL, 0 } } /* union for io-specific vars */\n};\n\nvoid rioInitWithFile(rio *r, FILE *fp) {\n    *r = rioFileIO;\n    r->io.file.fp = fp;\n    r->io.file.buffered = 0;\n    r->io.file.autosync = 0;\n}\n\n/* ------------------- File descriptors set implementation ------------------- */\n\n/* Returns 1 or 0 for success/failure.\n * The function returns success as long as we are able to correctly write\n * to at least one file descriptor.\n *\n * When buf is NULL and len is 0, the function performs a flush operation\n * if there is some pending buffer, so this function is also used in order\n * to implement rioFdsetFlush(). */\nstatic size_t rioFdsetWrite(rio *r, const void *buf, size_t len) {\n    ssize_t retval;\n    int j;\n    unsigned char *p = (unsigned char*) buf;\n    int doflush = (buf == NULL && len == 0);\n\n    /* To start we always append to our buffer. If it gets larger than\n     * a given size, we actually write to the sockets. */\n    if (len) {\n        r->io.fdset.buf = sdscatlen(r->io.fdset.buf,buf,len);\n        len = 0; /* Prevent entering the while below if we don't flush. */\n        if (sdslen(r->io.fdset.buf) > PROTO_IOBUF_LEN) doflush = 1;\n    }\n\n    if (doflush) {\n        p = (unsigned char*) r->io.fdset.buf;\n        len = sdslen(r->io.fdset.buf);\n    }\n\n    /* Write in little chunchs so that when there are big writes we\n     * parallelize while the kernel is sending data in background to\n     * the TCP socket. */\n    while(len) {\n        size_t count = len < 1024 ? len : 1024;\n        int broken = 0;\n        for (j = 0; j < r->io.fdset.numfds; j++) {\n            if (r->io.fdset.state[j] != 0) {\n                /* Skip FDs alraedy in error. */\n                broken++;\n                continue;\n            }\n\n            /* Make sure to write 'count' bytes to the socket regardless\n             * of short writes. */\n            size_t nwritten = 0;\n            while(nwritten != count) {\n                retval = write(r->io.fdset.fds[j],p+nwritten,count-nwritten);\n                if (retval <= 0) {\n                    /* With blocking sockets, which is the sole user of this\n                     * rio target, EWOULDBLOCK is returned only because of\n                     * the SO_SNDTIMEO socket option, so we translate the error\n                     * into one more recognizable by the user. */\n                    if (retval == -1 && errno == EWOULDBLOCK) errno = ETIMEDOUT;\n                    break;\n                }\n                nwritten += retval;\n            }\n\n            if (nwritten != count) {\n                /* Mark this FD as broken. */\n                r->io.fdset.state[j] = errno;\n                if (r->io.fdset.state[j] == 0) r->io.fdset.state[j] = EIO;\n            }\n        }\n        if (broken == r->io.fdset.numfds) return 0; /* All the FDs in error. */\n        p += count;\n        len -= count;\n        r->io.fdset.pos += count;\n    }\n\n    if (doflush) sdsclear(r->io.fdset.buf);\n    return 1;\n}\n\n/* Returns 1 or 0 for success/failure. */\nstatic size_t rioFdsetRead(rio *r, void *buf, size_t len) {\n    UNUSED(r);\n    UNUSED(buf);\n    UNUSED(len);\n    return 0; /* Error, this target does not support reading. */\n}\n\n/* Returns read/write position in file. */\nstatic off_t rioFdsetTell(rio *r) {\n    return r->io.fdset.pos;\n}\n\n/* Flushes any buffer to target device if applicable. Returns 1 on success\n * and 0 on failures. */\nstatic int rioFdsetFlush(rio *r) {\n    /* Our flush is implemented by the write method, that recognizes a\n     * buffer set to NULL with a count of zero as a flush request. */\n    return rioFdsetWrite(r,NULL,0);\n}\n\nstatic const rio rioFdsetIO = {\n    rioFdsetRead,\n    rioFdsetWrite,\n    rioFdsetTell,\n    rioFdsetFlush,\n    NULL,           /* update_checksum */\n    0,              /* current checksum */\n    0,              /* bytes read or written */\n    0,              /* read/write chunk size */\n    { { NULL, 0 } } /* union for io-specific vars */\n};\n\nvoid rioInitWithFdset(rio *r, int *fds, int numfds) {\n    int j;\n\n    *r = rioFdsetIO;\n    r->io.fdset.fds = zmalloc(sizeof(int)*numfds);\n    r->io.fdset.state = zmalloc(sizeof(int)*numfds);\n    memcpy(r->io.fdset.fds,fds,sizeof(int)*numfds);\n    for (j = 0; j < numfds; j++) r->io.fdset.state[j] = 0;\n    r->io.fdset.numfds = numfds;\n    r->io.fdset.pos = 0;\n    r->io.fdset.buf = sdsempty();\n}\n\n/* release the rio stream. */\nvoid rioFreeFdset(rio *r) {\n    zfree(r->io.fdset.fds);\n    zfree(r->io.fdset.state);\n    sdsfree(r->io.fdset.buf);\n}\n\n/* ---------------------------- Generic functions ---------------------------- */\n\n/* This function can be installed both in memory and file streams when checksum\n * computation is needed. */\nvoid rioGenericUpdateChecksum(rio *r, const void *buf, size_t len) {\n    r->cksum = crc64(r->cksum,buf,len);\n}\n\n/* Set the file-based rio object to auto-fsync every 'bytes' file written.\n * By default this is set to zero that means no automatic file sync is\n * performed.\n *\n * This feature is useful in a few contexts since when we rely on OS write\n * buffers sometimes the OS buffers way too much, resulting in too many\n * disk I/O concentrated in very little time. When we fsync in an explicit\n * way instead the I/O pressure is more distributed across time. */\nvoid rioSetAutoSync(rio *r, off_t bytes) {\n    serverAssert(r->read == rioFileIO.read);\n    r->io.file.autosync = bytes;\n}\n\n/* --------------------------- Higher level interface --------------------------\n *\n * The following higher level functions use lower level rio.c functions to help\n * generating the Redis protocol for the Append Only File. */\n\n/* Write multi bulk count in the format: \"*<count>\\r\\n\". */\nsize_t rioWriteBulkCount(rio *r, char prefix, int count) {\n    char cbuf[128];\n    int clen;\n\n    cbuf[0] = prefix;\n    clen = 1+ll2string(cbuf+1,sizeof(cbuf)-1,count);\n    cbuf[clen++] = '\\r';\n    cbuf[clen++] = '\\n';\n    if (rioWrite(r,cbuf,clen) == 0) return 0;\n    return clen;\n}\n\n/* Write binary-safe string in the format: \"$<count>\\r\\n<payload>\\r\\n\". */\nsize_t rioWriteBulkString(rio *r, const char *buf, size_t len) {\n    size_t nwritten;\n\n    if ((nwritten = rioWriteBulkCount(r,'$',len)) == 0) return 0;\n    if (len > 0 && rioWrite(r,buf,len) == 0) return 0;\n    if (rioWrite(r,\"\\r\\n\",2) == 0) return 0;\n    return nwritten+len+2;\n}\n\n/* Write a long long value in format: \"$<count>\\r\\n<payload>\\r\\n\". */\nsize_t rioWriteBulkLongLong(rio *r, long long l) {\n    char lbuf[32];\n    unsigned int llen;\n\n    llen = ll2string(lbuf,sizeof(lbuf),l);\n    return rioWriteBulkString(r,lbuf,llen);\n}\n\n/* Write a double value in the format: \"$<count>\\r\\n<payload>\\r\\n\" */\nsize_t rioWriteBulkDouble(rio *r, double d) {\n    char dbuf[128];\n    unsigned int dlen;\n\n    dlen = snprintf(dbuf,sizeof(dbuf),\"%.17g\",d);\n    return rioWriteBulkString(r,dbuf,dlen);\n}\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/src/rio.h",
    "content": "/*\n * Copyright (c) 2009-2012, Pieter Noordhuis <pcnoordhuis at gmail dot com>\n * Copyright (c) 2009-2012, Salvatore Sanfilippo <antirez at gmail dot com>\n * All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions are met:\n *\n *   * Redistributions of source code must retain the above copyright notice,\n *     this list of conditions and the following disclaimer.\n *   * Redistributions in binary form must reproduce the above copyright\n *     notice, this list of conditions and the following disclaimer in the\n *     documentation and/or other materials provided with the distribution.\n *   * Neither the name of Redis nor the names of its contributors may be used\n *     to endorse or promote products derived from this software without\n *     specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\"\n * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\n * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE\n * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR\n * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF\n * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS\n * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN\n * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)\n * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE\n * POSSIBILITY OF SUCH DAMAGE.\n */\n\n\n#ifndef __REDIS_RIO_H\n#define __REDIS_RIO_H\n\n#include <stdio.h>\n#include <stdint.h>\n#include \"sds.h\"\n\nstruct _rio {\n    /* Backend functions.\n     * Since this functions do not tolerate short writes or reads the return\n     * value is simplified to: zero on error, non zero on complete success. */\n    size_t (*read)(struct _rio *, void *buf, size_t len);\n    size_t (*write)(struct _rio *, const void *buf, size_t len);\n    off_t (*tell)(struct _rio *);\n    int (*flush)(struct _rio *);\n    /* The update_cksum method if not NULL is used to compute the checksum of\n     * all the data that was read or written so far. The method should be\n     * designed so that can be called with the current checksum, and the buf\n     * and len fields pointing to the new block of data to add to the checksum\n     * computation. */\n    void (*update_cksum)(struct _rio *, const void *buf, size_t len);\n\n    /* The current checksum */\n    uint64_t cksum;\n\n    /* number of bytes read or written */\n    size_t processed_bytes;\n\n    /* maximum single read or write chunk size */\n    size_t max_processing_chunk;\n\n    /* Backend-specific vars. */\n    union {\n        /* In-memory buffer target. */\n        struct {\n            sds ptr;\n            off_t pos;\n        } buffer;\n        /* Stdio file pointer target. */\n        struct {\n            FILE *fp;\n            off_t buffered; /* Bytes written since last fsync. */\n            off_t autosync; /* fsync after 'autosync' bytes written. */\n        } file;\n        /* Multiple FDs target (used to write to N sockets). */\n        struct {\n            int *fds;       /* File descriptors. */\n            int *state;     /* Error state of each fd. 0 (if ok) or errno. */\n            int numfds;\n            off_t pos;\n            sds buf;\n        } fdset;\n    } io;\n};\n\ntypedef struct _rio rio;\n\n/* The following functions are our interface with the stream. They'll call the\n * actual implementation of read / write / tell, and will update the checksum\n * if needed. */\n\nstatic inline size_t rioWrite(rio *r, const void *buf, size_t len) {\n    while (len) {\n        size_t bytes_to_write = (r->max_processing_chunk && r->max_processing_chunk < len) ? r->max_processing_chunk : len;\n        if (r->update_cksum) r->update_cksum(r,buf,bytes_to_write);\n        if (r->write(r,buf,bytes_to_write) == 0)\n            return 0;\n        buf = (char*)buf + bytes_to_write;\n        len -= bytes_to_write;\n        r->processed_bytes += bytes_to_write;\n    }\n    return 1;\n}\n\nstatic inline size_t rioRead(rio *r, void *buf, size_t len) {\n    while (len) {\n        size_t bytes_to_read = (r->max_processing_chunk && r->max_processing_chunk < len) ? r->max_processing_chunk : len;\n        if (r->read(r,buf,bytes_to_read) == 0)\n            return 0;\n        if (r->update_cksum) r->update_cksum(r,buf,bytes_to_read);\n        buf = (char*)buf + bytes_to_read;\n        len -= bytes_to_read;\n        r->processed_bytes += bytes_to_read;\n    }\n    return 1;\n}\n\nstatic inline off_t rioTell(rio *r) {\n    return r->tell(r);\n}\n\nstatic inline int rioFlush(rio *r) {\n    return r->flush(r);\n}\n\nvoid rioInitWithFile(rio *r, FILE *fp);\nvoid rioInitWithBuffer(rio *r, sds s);\nvoid rioInitWithFdset(rio *r, int *fds, int numfds);\n\nvoid rioFreeFdset(rio *r);\n\nsize_t rioWriteBulkCount(rio *r, char prefix, int count);\nsize_t rioWriteBulkString(rio *r, const char *buf, size_t len);\nsize_t rioWriteBulkLongLong(rio *r, long long l);\nsize_t rioWriteBulkDouble(rio *r, double d);\n\nvoid rioGenericUpdateChecksum(rio *r, const void *buf, size_t len);\nvoid rioSetAutoSync(rio *r, off_t bytes);\n\n#endif\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/src/scripting.c",
    "content": "/*\n * Copyright (c) 2009-2012, Salvatore Sanfilippo <antirez at gmail dot com>\n * All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions are met:\n *\n *   * Redistributions of source code must retain the above copyright notice,\n *     this list of conditions and the following disclaimer.\n *   * Redistributions in binary form must reproduce the above copyright\n *     notice, this list of conditions and the following disclaimer in the\n *     documentation and/or other materials provided with the distribution.\n *   * Neither the name of Redis nor the names of its contributors may be used\n *     to endorse or promote products derived from this software without\n *     specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\"\n * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\n * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE\n * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR\n * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF\n * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS\n * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN\n * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)\n * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE\n * POSSIBILITY OF SUCH DAMAGE.\n */\n\n#include \"server.h\"\n#include \"sha1.h\"\n#include \"rand.h\"\n#include \"cluster.h\"\n\n#include <lua.h>\n#include <lauxlib.h>\n#include <lualib.h>\n#include <ctype.h>\n#include <math.h>\n\nchar *redisProtocolToLuaType_Int(lua_State *lua, char *reply);\nchar *redisProtocolToLuaType_Bulk(lua_State *lua, char *reply);\nchar *redisProtocolToLuaType_Status(lua_State *lua, char *reply);\nchar *redisProtocolToLuaType_Error(lua_State *lua, char *reply);\nchar *redisProtocolToLuaType_MultiBulk(lua_State *lua, char *reply);\nint redis_math_random (lua_State *L);\nint redis_math_randomseed (lua_State *L);\nvoid ldbInit(void);\nvoid ldbDisable(client *c);\nvoid ldbEnable(client *c);\nvoid evalGenericCommandWithDebugging(client *c, int evalsha);\nvoid luaLdbLineHook(lua_State *lua, lua_Debug *ar);\nvoid ldbLog(sds entry);\nvoid ldbLogRedisReply(char *reply);\nsds ldbCatStackValue(sds s, lua_State *lua, int idx);\n\n/* Debugger shared state is stored inside this global structure. */\n#define LDB_BREAKPOINTS_MAX 64  /* Max number of breakpoints. */\n#define LDB_MAX_LEN_DEFAULT 256 /* Default len limit for replies / var dumps. */\nstruct ldbState {\n    int fd;     /* Socket of the debugging client. */\n    int active; /* Are we debugging EVAL right now? */\n    int forked; /* Is this a fork()ed debugging session? */\n    list *logs; /* List of messages to send to the client. */\n    list *traces; /* Messages about Redis commands executed since last stop.*/\n    list *children; /* All forked debugging sessions pids. */\n    int bp[LDB_BREAKPOINTS_MAX]; /* An array of breakpoints line numbers. */\n    int bpcount; /* Number of valid entries inside bp. */\n    int step;   /* Stop at next line ragardless of breakpoints. */\n    int luabp;  /* Stop at next line because redis.breakpoint() was called. */\n    sds *src;   /* Lua script source code split by line. */\n    int lines;  /* Number of lines in 'src'. */\n    int currentline;    /* Current line number. */\n    sds cbuf;   /* Debugger client command buffer. */\n    size_t maxlen;  /* Max var dump / reply length. */\n    int maxlen_hint_sent; /* Did we already hint about \"set maxlen\"? */\n} ldb;\n\n/* ---------------------------------------------------------------------------\n * Utility functions.\n * ------------------------------------------------------------------------- */\n\n/* Perform the SHA1 of the input string. We use this both for hashing script\n * bodies in order to obtain the Lua function name, and in the implementation\n * of redis.sha1().\n *\n * 'digest' should point to a 41 bytes buffer: 40 for SHA1 converted into an\n * hexadecimal number, plus 1 byte for null term. */\nvoid sha1hex(char *digest, char *script, size_t len) {\n    SHA1_CTX ctx;\n    unsigned char hash[20];\n    char *cset = \"0123456789abcdef\";\n    int j;\n\n    SHA1Init(&ctx);\n    SHA1Update(&ctx,(unsigned char*)script,len);\n    SHA1Final(hash,&ctx);\n\n    for (j = 0; j < 20; j++) {\n        digest[j*2] = cset[((hash[j]&0xF0)>>4)];\n        digest[j*2+1] = cset[(hash[j]&0xF)];\n    }\n    digest[40] = '\\0';\n}\n\n/* ---------------------------------------------------------------------------\n * Redis reply to Lua type conversion functions.\n * ------------------------------------------------------------------------- */\n\n/* Take a Redis reply in the Redis protocol format and convert it into a\n * Lua type. Thanks to this function, and the introduction of not connected\n * clients, it is trivial to implement the redis() lua function.\n *\n * Basically we take the arguments, execute the Redis command in the context\n * of a non connected client, then take the generated reply and convert it\n * into a suitable Lua type. With this trick the scripting feature does not\n * need the introduction of a full Redis internals API. The script\n * is like a normal client that bypasses all the slow I/O paths.\n *\n * Note: in this function we do not do any sanity check as the reply is\n * generated by Redis directly. This allows us to go faster.\n *\n * Errors are returned as a table with a single 'err' field set to the\n * error string.\n */\n\nchar *redisProtocolToLuaType(lua_State *lua, char* reply) {\n    char *p = reply;\n\n    switch(*p) {\n    case ':': p = redisProtocolToLuaType_Int(lua,reply); break;\n    case '$': p = redisProtocolToLuaType_Bulk(lua,reply); break;\n    case '+': p = redisProtocolToLuaType_Status(lua,reply); break;\n    case '-': p = redisProtocolToLuaType_Error(lua,reply); break;\n    case '*': p = redisProtocolToLuaType_MultiBulk(lua,reply); break;\n    }\n    return p;\n}\n\nchar *redisProtocolToLuaType_Int(lua_State *lua, char *reply) {\n    char *p = strchr(reply+1,'\\r');\n    long long value;\n\n    string2ll(reply+1,p-reply-1,&value);\n    lua_pushnumber(lua,(lua_Number)value);\n    return p+2;\n}\n\nchar *redisProtocolToLuaType_Bulk(lua_State *lua, char *reply) {\n    char *p = strchr(reply+1,'\\r');\n    long long bulklen;\n\n    string2ll(reply+1,p-reply-1,&bulklen);\n    if (bulklen == -1) {\n        lua_pushboolean(lua,0);\n        return p+2;\n    } else {\n        lua_pushlstring(lua,p+2,bulklen);\n        return p+2+bulklen+2;\n    }\n}\n\nchar *redisProtocolToLuaType_Status(lua_State *lua, char *reply) {\n    char *p = strchr(reply+1,'\\r');\n\n    lua_newtable(lua);\n    lua_pushstring(lua,\"ok\");\n    lua_pushlstring(lua,reply+1,p-reply-1);\n    lua_settable(lua,-3);\n    return p+2;\n}\n\nchar *redisProtocolToLuaType_Error(lua_State *lua, char *reply) {\n    char *p = strchr(reply+1,'\\r');\n\n    lua_newtable(lua);\n    lua_pushstring(lua,\"err\");\n    lua_pushlstring(lua,reply+1,p-reply-1);\n    lua_settable(lua,-3);\n    return p+2;\n}\n\nchar *redisProtocolToLuaType_MultiBulk(lua_State *lua, char *reply) {\n    char *p = strchr(reply+1,'\\r');\n    long long mbulklen;\n    int j = 0;\n\n    string2ll(reply+1,p-reply-1,&mbulklen);\n    p += 2;\n    if (mbulklen == -1) {\n        lua_pushboolean(lua,0);\n        return p;\n    }\n    lua_newtable(lua);\n    for (j = 0; j < mbulklen; j++) {\n        lua_pushnumber(lua,j+1);\n        p = redisProtocolToLuaType(lua,p);\n        lua_settable(lua,-3);\n    }\n    return p;\n}\n\n/* This function is used in order to push an error on the Lua stack in the\n * format used by redis.pcall to return errors, which is a lua table\n * with a single \"err\" field set to the error string. Note that this\n * table is never a valid reply by proper commands, since the returned\n * tables are otherwise always indexed by integers, never by strings. */\nvoid luaPushError(lua_State *lua, char *error) {\n    lua_Debug dbg;\n\n    /* If debugging is active and in step mode, log errors resulting from\n     * Redis commands. */\n    if (ldb.active && ldb.step) {\n        ldbLog(sdscatprintf(sdsempty(),\"<error> %s\",error));\n    }\n\n    lua_newtable(lua);\n    lua_pushstring(lua,\"err\");\n\n    /* Attempt to figure out where this function was called, if possible */\n    if(lua_getstack(lua, 1, &dbg) && lua_getinfo(lua, \"nSl\", &dbg)) {\n        sds msg = sdscatprintf(sdsempty(), \"%s: %d: %s\",\n            dbg.source, dbg.currentline, error);\n        lua_pushstring(lua, msg);\n        sdsfree(msg);\n    } else {\n        lua_pushstring(lua, error);\n    }\n    lua_settable(lua,-3);\n}\n\n/* In case the error set into the Lua stack by luaPushError() was generated\n * by the non-error-trapping version of redis.pcall(), which is redis.call(),\n * this function will raise the Lua error so that the execution of the\n * script will be halted. */\nint luaRaiseError(lua_State *lua) {\n    lua_pushstring(lua,\"err\");\n    lua_gettable(lua,-2);\n    return lua_error(lua);\n}\n\n/* Sort the array currently in the stack. We do this to make the output\n * of commands like KEYS or SMEMBERS something deterministic when called\n * from Lua (to play well with AOf/replication).\n *\n * The array is sorted using table.sort itself, and assuming all the\n * list elements are strings. */\nvoid luaSortArray(lua_State *lua) {\n    /* Initial Stack: array */\n    lua_getglobal(lua,\"table\");\n    lua_pushstring(lua,\"sort\");\n    lua_gettable(lua,-2);       /* Stack: array, table, table.sort */\n    lua_pushvalue(lua,-3);      /* Stack: array, table, table.sort, array */\n    if (lua_pcall(lua,1,0,0)) {\n        /* Stack: array, table, error */\n\n        /* We are not interested in the error, we assume that the problem is\n         * that there are 'false' elements inside the array, so we try\n         * again with a slower function but able to handle this case, that\n         * is: table.sort(table, __redis__compare_helper) */\n        lua_pop(lua,1);             /* Stack: array, table */\n        lua_pushstring(lua,\"sort\"); /* Stack: array, table, sort */\n        lua_gettable(lua,-2);       /* Stack: array, table, table.sort */\n        lua_pushvalue(lua,-3);      /* Stack: array, table, table.sort, array */\n        lua_getglobal(lua,\"__redis__compare_helper\");\n        /* Stack: array, table, table.sort, array, __redis__compare_helper */\n        lua_call(lua,2,0);\n    }\n    /* Stack: array (sorted), table */\n    lua_pop(lua,1);             /* Stack: array (sorted) */\n}\n\n/* ---------------------------------------------------------------------------\n * Lua reply to Redis reply conversion functions.\n * ------------------------------------------------------------------------- */\n\nvoid luaReplyToRedisReply(client *c, lua_State *lua) {\n    int t = lua_type(lua,-1);\n\n    switch(t) {\n    case LUA_TSTRING:\n        addReplyBulkCBuffer(c,(char*)lua_tostring(lua,-1),lua_strlen(lua,-1));\n        break;\n    case LUA_TBOOLEAN:\n        addReply(c,lua_toboolean(lua,-1) ? shared.cone : shared.nullbulk);\n        break;\n    case LUA_TNUMBER:\n        addReplyLongLong(c,(long long)lua_tonumber(lua,-1));\n        break;\n    case LUA_TTABLE:\n        /* We need to check if it is an array, an error, or a status reply.\n         * Error are returned as a single element table with 'err' field.\n         * Status replies are returned as single element table with 'ok'\n         * field. */\n        lua_pushstring(lua,\"err\");\n        lua_gettable(lua,-2);\n        t = lua_type(lua,-1);\n        if (t == LUA_TSTRING) {\n            sds err = sdsnew(lua_tostring(lua,-1));\n            sdsmapchars(err,\"\\r\\n\",\"  \",2);\n            addReplySds(c,sdscatprintf(sdsempty(),\"-%s\\r\\n\",err));\n            sdsfree(err);\n            lua_pop(lua,2);\n            return;\n        }\n\n        lua_pop(lua,1);\n        lua_pushstring(lua,\"ok\");\n        lua_gettable(lua,-2);\n        t = lua_type(lua,-1);\n        if (t == LUA_TSTRING) {\n            sds ok = sdsnew(lua_tostring(lua,-1));\n            sdsmapchars(ok,\"\\r\\n\",\"  \",2);\n            addReplySds(c,sdscatprintf(sdsempty(),\"+%s\\r\\n\",ok));\n            sdsfree(ok);\n            lua_pop(lua,1);\n        } else {\n            void *replylen = addDeferredMultiBulkLength(c);\n            int j = 1, mbulklen = 0;\n\n            lua_pop(lua,1); /* Discard the 'ok' field value we popped */\n            while(1) {\n                lua_pushnumber(lua,j++);\n                lua_gettable(lua,-2);\n                t = lua_type(lua,-1);\n                if (t == LUA_TNIL) {\n                    lua_pop(lua,1);\n                    break;\n                }\n                luaReplyToRedisReply(c, lua);\n                mbulklen++;\n            }\n            setDeferredMultiBulkLength(c,replylen,mbulklen);\n        }\n        break;\n    default:\n        addReply(c,shared.nullbulk);\n    }\n    lua_pop(lua,1);\n}\n\n/* ---------------------------------------------------------------------------\n * Lua redis.* functions implementations.\n * ------------------------------------------------------------------------- */\n\n#define LUA_CMD_OBJCACHE_SIZE 32\n#define LUA_CMD_OBJCACHE_MAX_LEN 64\nint luaRedisGenericCommand(lua_State *lua, int raise_error) {\n    int j, argc = lua_gettop(lua);\n    struct redisCommand *cmd;\n    client *c = server.lua_client;\n    sds reply;\n\n    /* Cached across calls. */\n    static robj **argv = NULL;\n    static int argv_size = 0;\n    static robj *cached_objects[LUA_CMD_OBJCACHE_SIZE];\n    static size_t cached_objects_len[LUA_CMD_OBJCACHE_SIZE];\n    static int inuse = 0;   /* Recursive calls detection. */\n\n    /* By using Lua debug hooks it is possible to trigger a recursive call\n     * to luaRedisGenericCommand(), which normally should never happen.\n     * To make this function reentrant is futile and makes it slower, but\n     * we should at least detect such a misuse, and abort. */\n    if (inuse) {\n        char *recursion_warning =\n            \"luaRedisGenericCommand() recursive call detected. \"\n            \"Are you doing funny stuff with Lua debug hooks?\";\n        serverLog(LL_WARNING,\"%s\",recursion_warning);\n        luaPushError(lua,recursion_warning);\n        return 1;\n    }\n    inuse++;\n\n    /* Require at least one argument */\n    if (argc == 0) {\n        luaPushError(lua,\n            \"Please specify at least one argument for redis.call()\");\n        inuse--;\n        return raise_error ? luaRaiseError(lua) : 1;\n    }\n\n    /* Build the arguments vector */\n    if (argv_size < argc) {\n        argv = zrealloc(argv,sizeof(robj*)*argc);\n        argv_size = argc;\n    }\n\n    for (j = 0; j < argc; j++) {\n        char *obj_s;\n        size_t obj_len;\n        char dbuf[64];\n\n        if (lua_type(lua,j+1) == LUA_TNUMBER) {\n            /* We can't use lua_tolstring() for number -> string conversion\n             * since Lua uses a format specifier that loses precision. */\n            lua_Number num = lua_tonumber(lua,j+1);\n\n            obj_len = snprintf(dbuf,sizeof(dbuf),\"%.17g\",(double)num);\n            obj_s = dbuf;\n        } else {\n            obj_s = (char*)lua_tolstring(lua,j+1,&obj_len);\n            if (obj_s == NULL) break; /* Not a string. */\n        }\n\n        /* Try to use a cached object. */\n        if (j < LUA_CMD_OBJCACHE_SIZE && cached_objects[j] &&\n            cached_objects_len[j] >= obj_len)\n        {\n            sds s = cached_objects[j]->ptr;\n            argv[j] = cached_objects[j];\n            cached_objects[j] = NULL;\n            memcpy(s,obj_s,obj_len+1);\n            sdssetlen(s, obj_len);\n        } else {\n            argv[j] = createStringObject(obj_s, obj_len);\n        }\n    }\n\n    /* Check if one of the arguments passed by the Lua script\n     * is not a string or an integer (lua_isstring() return true for\n     * integers as well). */\n    if (j != argc) {\n        j--;\n        while (j >= 0) {\n            decrRefCount(argv[j]);\n            j--;\n        }\n        luaPushError(lua,\n            \"Lua redis() command arguments must be strings or integers\");\n        inuse--;\n        return raise_error ? luaRaiseError(lua) : 1;\n    }\n\n    /* Setup our fake client for command execution */\n    c->argv = argv;\n    c->argc = argc;\n\n    /* Log the command if debugging is active. */\n    if (ldb.active && ldb.step) {\n        sds cmdlog = sdsnew(\"<redis>\");\n        for (j = 0; j < c->argc; j++) {\n            if (j == 10) {\n                cmdlog = sdscatprintf(cmdlog,\" ... (%d more)\",\n                    c->argc-j-1);\n            } else {\n                cmdlog = sdscatlen(cmdlog,\" \",1);\n                cmdlog = sdscatsds(cmdlog,c->argv[j]->ptr);\n            }\n        }\n        ldbLog(cmdlog);\n    }\n\n    /* Command lookup */\n    cmd = lookupCommand(argv[0]->ptr);\n    if (!cmd || ((cmd->arity > 0 && cmd->arity != argc) ||\n                   (argc < -cmd->arity)))\n    {\n        if (cmd)\n            luaPushError(lua,\n                \"Wrong number of args calling Redis command From Lua script\");\n        else\n            luaPushError(lua,\"Unknown Redis command called from Lua script\");\n        goto cleanup;\n    }\n    c->cmd = c->lastcmd = cmd;\n\n    /* There are commands that are not allowed inside scripts. */\n    if (cmd->flags & CMD_NOSCRIPT) {\n        luaPushError(lua, \"This Redis command is not allowed from scripts\");\n        goto cleanup;\n    }\n\n    /* Write commands are forbidden against read-only slaves, or if a\n     * command marked as non-deterministic was already called in the context\n     * of this script. */\n    if (cmd->flags & CMD_WRITE) {\n        if (server.lua_random_dirty && !server.lua_replicate_commands) {\n            luaPushError(lua,\n                \"Write commands not allowed after non deterministic commands. Call redis.replicate_commands() at the start of your script in order to switch to single commands replication mode.\");\n            goto cleanup;\n        } else if (server.masterhost && server.repl_slave_ro &&\n                   !server.loading &&\n                   !(server.lua_caller->flags & CLIENT_MASTER))\n        {\n            luaPushError(lua, shared.roslaveerr->ptr);\n            goto cleanup;\n        } else if (server.stop_writes_on_bgsave_err &&\n                   server.saveparamslen > 0 &&\n                   server.lastbgsave_status == C_ERR)\n        {\n            luaPushError(lua, shared.bgsaveerr->ptr);\n            goto cleanup;\n        }\n    }\n\n    /* If we reached the memory limit configured via maxmemory, commands that\n     * could enlarge the memory usage are not allowed, but only if this is the\n     * first write in the context of this script, otherwise we can't stop\n     * in the middle. */\n    if (server.maxmemory && server.lua_write_dirty == 0 &&\n        (cmd->flags & CMD_DENYOOM))\n    {\n        if (freeMemoryIfNeeded() == C_ERR) {\n            luaPushError(lua, shared.oomerr->ptr);\n            goto cleanup;\n        }\n    }\n\n    if (cmd->flags & CMD_RANDOM) server.lua_random_dirty = 1;\n    if (cmd->flags & CMD_WRITE) server.lua_write_dirty = 1;\n\n    /* If this is a Redis Cluster node, we need to make sure Lua is not\n     * trying to access non-local keys, with the exception of commands\n     * received from our master or when loading the AOF back in memory. */\n    if (server.cluster_enabled && !server.loading &&\n        !(server.lua_caller->flags & CLIENT_MASTER))\n    {\n        /* Duplicate relevant flags in the lua client. */\n        c->flags &= ~(CLIENT_READONLY|CLIENT_ASKING);\n        c->flags |= server.lua_caller->flags & (CLIENT_READONLY|CLIENT_ASKING);\n        if (getNodeByQuery(c,c->cmd,c->argv,c->argc,NULL,NULL) !=\n                           server.cluster->myself)\n        {\n            luaPushError(lua,\n                \"Lua script attempted to access a non local key in a \"\n                \"cluster node\");\n            goto cleanup;\n        }\n    }\n\n    /* If we are using single commands replication, we need to wrap what\n     * we propagate into a MULTI/EXEC block, so that it will be atomic like\n     * a Lua script in the context of AOF and slaves. */\n    if (server.lua_replicate_commands &&\n        !server.lua_multi_emitted &&\n        server.lua_write_dirty &&\n        server.lua_repl != PROPAGATE_NONE)\n    {\n        execCommandPropagateMulti(server.lua_caller);\n        server.lua_multi_emitted = 1;\n    }\n\n    /* Run the command */\n    int call_flags = CMD_CALL_SLOWLOG | CMD_CALL_STATS;\n    if (server.lua_replicate_commands) {\n        /* Set flags according to redis.set_repl() settings. */\n        if (server.lua_repl & PROPAGATE_AOF)\n            call_flags |= CMD_CALL_PROPAGATE_AOF;\n        if (server.lua_repl & PROPAGATE_REPL)\n            call_flags |= CMD_CALL_PROPAGATE_REPL;\n    }\n    call(c,call_flags);\n\n    /* Convert the result of the Redis command into a suitable Lua type.\n     * The first thing we need is to create a single string from the client\n     * output buffers. */\n    if (listLength(c->reply) == 0 && c->bufpos < PROTO_REPLY_CHUNK_BYTES) {\n        /* This is a fast path for the common case of a reply inside the\n         * client static buffer. Don't create an SDS string but just use\n         * the client buffer directly. */\n        c->buf[c->bufpos] = '\\0';\n        reply = c->buf;\n        c->bufpos = 0;\n    } else {\n        reply = sdsnewlen(c->buf,c->bufpos);\n        c->bufpos = 0;\n        while(listLength(c->reply)) {\n            robj *o = listNodeValue(listFirst(c->reply));\n\n            reply = sdscatlen(reply,o->ptr,sdslen(o->ptr));\n            listDelNode(c->reply,listFirst(c->reply));\n        }\n    }\n    if (raise_error && reply[0] != '-') raise_error = 0;\n    redisProtocolToLuaType(lua,reply);\n\n    /* If the debugger is active, log the reply from Redis. */\n    if (ldb.active && ldb.step)\n        ldbLogRedisReply(reply);\n\n    /* Sort the output array if needed, assuming it is a non-null multi bulk\n     * reply as expected. */\n    if ((cmd->flags & CMD_SORT_FOR_SCRIPT) &&\n        (server.lua_replicate_commands == 0) &&\n        (reply[0] == '*' && reply[1] != '-')) {\n            luaSortArray(lua);\n    }\n    if (reply != c->buf) sdsfree(reply);\n    c->reply_bytes = 0;\n\ncleanup:\n    /* Clean up. Command code may have changed argv/argc so we use the\n     * argv/argc of the client instead of the local variables. */\n    for (j = 0; j < c->argc; j++) {\n        robj *o = c->argv[j];\n\n        /* Try to cache the object in the cached_objects array.\n         * The object must be small, SDS-encoded, and with refcount = 1\n         * (we must be the only owner) for us to cache it. */\n        if (j < LUA_CMD_OBJCACHE_SIZE &&\n            o->refcount == 1 &&\n            (o->encoding == OBJ_ENCODING_RAW ||\n             o->encoding == OBJ_ENCODING_EMBSTR) &&\n            sdslen(o->ptr) <= LUA_CMD_OBJCACHE_MAX_LEN)\n        {\n            sds s = o->ptr;\n            if (cached_objects[j]) decrRefCount(cached_objects[j]);\n            cached_objects[j] = o;\n            cached_objects_len[j] = sdsalloc(s);\n        } else {\n            decrRefCount(o);\n        }\n    }\n\n    if (c->argv != argv) {\n        zfree(c->argv);\n        argv = NULL;\n        argv_size = 0;\n    }\n\n    if (raise_error) {\n        /* If we are here we should have an error in the stack, in the\n         * form of a table with an \"err\" field. Extract the string to\n         * return the plain error. */\n        inuse--;\n        return luaRaiseError(lua);\n    }\n    inuse--;\n    return 1;\n}\n\n/* redis.call() */\nint luaRedisCallCommand(lua_State *lua) {\n    return luaRedisGenericCommand(lua,1);\n}\n\n/* redis.pcall() */\nint luaRedisPCallCommand(lua_State *lua) {\n    return luaRedisGenericCommand(lua,0);\n}\n\n/* This adds redis.sha1hex(string) to Lua scripts using the same hashing\n * function used for sha1ing lua scripts. */\nint luaRedisSha1hexCommand(lua_State *lua) {\n    int argc = lua_gettop(lua);\n    char digest[41];\n    size_t len;\n    char *s;\n\n    if (argc != 1) {\n        lua_pushstring(lua, \"wrong number of arguments\");\n        return lua_error(lua);\n    }\n\n    s = (char*)lua_tolstring(lua,1,&len);\n    sha1hex(digest,s,len);\n    lua_pushstring(lua,digest);\n    return 1;\n}\n\n/* Returns a table with a single field 'field' set to the string value\n * passed as argument. This helper function is handy when returning\n * a Redis Protocol error or status reply from Lua:\n *\n * return redis.error_reply(\"ERR Some Error\")\n * return redis.status_reply(\"ERR Some Error\")\n */\nint luaRedisReturnSingleFieldTable(lua_State *lua, char *field) {\n    if (lua_gettop(lua) != 1 || lua_type(lua,-1) != LUA_TSTRING) {\n        luaPushError(lua, \"wrong number or type of arguments\");\n        return 1;\n    }\n\n    lua_newtable(lua);\n    lua_pushstring(lua, field);\n    lua_pushvalue(lua, -3);\n    lua_settable(lua, -3);\n    return 1;\n}\n\n/* redis.error_reply() */\nint luaRedisErrorReplyCommand(lua_State *lua) {\n    return luaRedisReturnSingleFieldTable(lua,\"err\");\n}\n\n/* redis.status_reply() */\nint luaRedisStatusReplyCommand(lua_State *lua) {\n    return luaRedisReturnSingleFieldTable(lua,\"ok\");\n}\n\n/* redis.replicate_commands()\n *\n * Turn on single commands replication if the script never called\n * a write command so far, and returns true. Otherwise if the script\n * already started to write, returns false and stick to whole scripts\n * replication, which is our default. */\nint luaRedisReplicateCommandsCommand(lua_State *lua) {\n    if (server.lua_write_dirty) {\n        lua_pushboolean(lua,0);\n    } else {\n        server.lua_replicate_commands = 1;\n        /* When we switch to single commands replication, we can provide\n         * different math.random() sequences at every call, which is what\n         * the user normally expects. */\n        redisSrand48(rand());\n        lua_pushboolean(lua,1);\n    }\n    return 1;\n}\n\n/* redis.breakpoint()\n *\n * Allows to stop execution during a debuggign session from within\n * the Lua code implementation, like if a breakpoint was set in the code\n * immediately after the function. */\nint luaRedisBreakpointCommand(lua_State *lua) {\n    if (ldb.active) {\n        ldb.luabp = 1;\n        lua_pushboolean(lua,1);\n    } else {\n        lua_pushboolean(lua,0);\n    }\n    return 1;\n}\n\n/* redis.debug()\n *\n * Log a string message into the output console.\n * Can take multiple arguments that will be separated by commas.\n * Nothing is returned to the caller. */\nint luaRedisDebugCommand(lua_State *lua) {\n    if (!ldb.active) return 0;\n    int argc = lua_gettop(lua);\n    sds log = sdscatprintf(sdsempty(),\"<debug> line %d: \", ldb.currentline);\n    while(argc--) {\n        log = ldbCatStackValue(log,lua,-1 - argc);\n        if (argc != 0) log = sdscatlen(log,\", \",2);\n    }\n    ldbLog(log);\n    return 0;\n}\n\n/* redis.set_repl()\n *\n * Set the propagation of write commands executed in the context of the\n * script to on/off for AOF and slaves. */\nint luaRedisSetReplCommand(lua_State *lua) {\n    int argc = lua_gettop(lua);\n    int flags;\n\n    if (server.lua_replicate_commands == 0) {\n        lua_pushstring(lua, \"You can set the replication behavior only after turning on single commands replication with redis.replicate_commands().\");\n        return lua_error(lua);\n    } else if (argc != 1) {\n        lua_pushstring(lua, \"redis.set_repl() requires two arguments.\");\n        return lua_error(lua);\n    }\n\n    flags = lua_tonumber(lua,-1);\n    if ((flags & ~(PROPAGATE_AOF|PROPAGATE_REPL)) != 0) {\n        lua_pushstring(lua, \"Invalid replication flags. Use REPL_AOF, REPL_SLAVE, REPL_ALL or REPL_NONE.\");\n        return lua_error(lua);\n    }\n    server.lua_repl = flags;\n    return 0;\n}\n\n/* redis.log() */\nint luaLogCommand(lua_State *lua) {\n    int j, argc = lua_gettop(lua);\n    int level;\n    sds log;\n\n    if (argc < 2) {\n        lua_pushstring(lua, \"redis.log() requires two arguments or more.\");\n        return lua_error(lua);\n    } else if (!lua_isnumber(lua,-argc)) {\n        lua_pushstring(lua, \"First argument must be a number (log level).\");\n        return lua_error(lua);\n    }\n    level = lua_tonumber(lua,-argc);\n    if (level < LL_DEBUG || level > LL_WARNING) {\n        lua_pushstring(lua, \"Invalid debug level.\");\n        return lua_error(lua);\n    }\n\n    /* Glue together all the arguments */\n    log = sdsempty();\n    for (j = 1; j < argc; j++) {\n        size_t len;\n        char *s;\n\n        s = (char*)lua_tolstring(lua,(-argc)+j,&len);\n        if (s) {\n            if (j != 1) log = sdscatlen(log,\" \",1);\n            log = sdscatlen(log,s,len);\n        }\n    }\n    serverLogRaw(level,log);\n    sdsfree(log);\n    return 0;\n}\n\n/* ---------------------------------------------------------------------------\n * Lua engine initialization and reset.\n * ------------------------------------------------------------------------- */\n\nvoid luaLoadLib(lua_State *lua, const char *libname, lua_CFunction luafunc) {\n  lua_pushcfunction(lua, luafunc);\n  lua_pushstring(lua, libname);\n  lua_call(lua, 1, 0);\n}\n\nLUALIB_API int (luaopen_cjson) (lua_State *L);\nLUALIB_API int (luaopen_struct) (lua_State *L);\nLUALIB_API int (luaopen_cmsgpack) (lua_State *L);\nLUALIB_API int (luaopen_bit) (lua_State *L);\n\nvoid luaLoadLibraries(lua_State *lua) {\n    luaLoadLib(lua, \"\", luaopen_base);\n    luaLoadLib(lua, LUA_TABLIBNAME, luaopen_table);\n    luaLoadLib(lua, LUA_STRLIBNAME, luaopen_string);\n    luaLoadLib(lua, LUA_MATHLIBNAME, luaopen_math);\n    luaLoadLib(lua, LUA_DBLIBNAME, luaopen_debug);\n    luaLoadLib(lua, \"cjson\", luaopen_cjson);\n    luaLoadLib(lua, \"struct\", luaopen_struct);\n    luaLoadLib(lua, \"cmsgpack\", luaopen_cmsgpack);\n    luaLoadLib(lua, \"bit\", luaopen_bit);\n\n#if 0 /* Stuff that we don't load currently, for sandboxing concerns. */\n    luaLoadLib(lua, LUA_LOADLIBNAME, luaopen_package);\n    luaLoadLib(lua, LUA_OSLIBNAME, luaopen_os);\n#endif\n}\n\n/* Remove a functions that we don't want to expose to the Redis scripting\n * environment. */\nvoid luaRemoveUnsupportedFunctions(lua_State *lua) {\n    lua_pushnil(lua);\n    lua_setglobal(lua,\"loadfile\");\n    lua_pushnil(lua);\n    lua_setglobal(lua,\"dofile\");\n}\n\n/* This function installs metamethods in the global table _G that prevent\n * the creation of globals accidentally.\n *\n * It should be the last to be called in the scripting engine initialization\n * sequence, because it may interact with creation of globals. */\nvoid scriptingEnableGlobalsProtection(lua_State *lua) {\n    char *s[32];\n    sds code = sdsempty();\n    int j = 0;\n\n    /* strict.lua from: http://metalua.luaforge.net/src/lib/strict.lua.html.\n     * Modified to be adapted to Redis. */\n    s[j++]=\"local dbg=debug\\n\";\n    s[j++]=\"local mt = {}\\n\";\n    s[j++]=\"setmetatable(_G, mt)\\n\";\n    s[j++]=\"mt.__newindex = function (t, n, v)\\n\";\n    s[j++]=\"  if dbg.getinfo(2) then\\n\";\n    s[j++]=\"    local w = dbg.getinfo(2, \\\"S\\\").what\\n\";\n    s[j++]=\"    if w ~= \\\"main\\\" and w ~= \\\"C\\\" then\\n\";\n    s[j++]=\"      error(\\\"Script attempted to create global variable '\\\"..tostring(n)..\\\"'\\\", 2)\\n\";\n    s[j++]=\"    end\\n\";\n    s[j++]=\"  end\\n\";\n    s[j++]=\"  rawset(t, n, v)\\n\";\n    s[j++]=\"end\\n\";\n    s[j++]=\"mt.__index = function (t, n)\\n\";\n    s[j++]=\"  if dbg.getinfo(2) and dbg.getinfo(2, \\\"S\\\").what ~= \\\"C\\\" then\\n\";\n    s[j++]=\"    error(\\\"Script attempted to access unexisting global variable '\\\"..tostring(n)..\\\"'\\\", 2)\\n\";\n    s[j++]=\"  end\\n\";\n    s[j++]=\"  return rawget(t, n)\\n\";\n    s[j++]=\"end\\n\";\n    s[j++]=\"debug = nil\\n\";\n    s[j++]=NULL;\n\n    for (j = 0; s[j] != NULL; j++) code = sdscatlen(code,s[j],strlen(s[j]));\n    luaL_loadbuffer(lua,code,sdslen(code),\"@enable_strict_lua\");\n    lua_pcall(lua,0,0,0);\n    sdsfree(code);\n}\n\n/* Initialize the scripting environment.\n *\n * This function is called the first time at server startup with\n * the 'setup' argument set to 1.\n *\n * It can be called again multiple times during the lifetime of the Redis\n * process, with 'setup' set to 0, and following a scriptingRelease() call,\n * in order to reset the Lua scripting environment.\n *\n * However it is simpler to just call scriptingReset() that does just that. */\nvoid scriptingInit(int setup) {\n    lua_State *lua = lua_open();\n\n    if (setup) {\n        server.lua_client = NULL;\n        server.lua_caller = NULL;\n        server.lua_timedout = 0;\n        server.lua_always_replicate_commands = 0; /* Only DEBUG can change it.*/\n        server.lua_time_limit = LUA_SCRIPT_TIME_LIMIT;\n        ldbInit();\n    }\n\n    luaLoadLibraries(lua);\n    luaRemoveUnsupportedFunctions(lua);\n\n    /* Initialize a dictionary we use to map SHAs to scripts.\n     * This is useful for replication, as we need to replicate EVALSHA\n     * as EVAL, so we need to remember the associated script. */\n    server.lua_scripts = dictCreate(&shaScriptObjectDictType,NULL);\n\n    /* Register the redis commands table and fields */\n    lua_newtable(lua);\n\n    /* redis.call */\n    lua_pushstring(lua,\"call\");\n    lua_pushcfunction(lua,luaRedisCallCommand);\n    lua_settable(lua,-3);\n\n    /* redis.pcall */\n    lua_pushstring(lua,\"pcall\");\n    lua_pushcfunction(lua,luaRedisPCallCommand);\n    lua_settable(lua,-3);\n\n    /* redis.log and log levels. */\n    lua_pushstring(lua,\"log\");\n    lua_pushcfunction(lua,luaLogCommand);\n    lua_settable(lua,-3);\n\n    lua_pushstring(lua,\"LOG_DEBUG\");\n    lua_pushnumber(lua,LL_DEBUG);\n    lua_settable(lua,-3);\n\n    lua_pushstring(lua,\"LOG_VERBOSE\");\n    lua_pushnumber(lua,LL_VERBOSE);\n    lua_settable(lua,-3);\n\n    lua_pushstring(lua,\"LOG_NOTICE\");\n    lua_pushnumber(lua,LL_NOTICE);\n    lua_settable(lua,-3);\n\n    lua_pushstring(lua,\"LOG_WARNING\");\n    lua_pushnumber(lua,LL_WARNING);\n    lua_settable(lua,-3);\n\n    /* redis.sha1hex */\n    lua_pushstring(lua, \"sha1hex\");\n    lua_pushcfunction(lua, luaRedisSha1hexCommand);\n    lua_settable(lua, -3);\n\n    /* redis.error_reply and redis.status_reply */\n    lua_pushstring(lua, \"error_reply\");\n    lua_pushcfunction(lua, luaRedisErrorReplyCommand);\n    lua_settable(lua, -3);\n    lua_pushstring(lua, \"status_reply\");\n    lua_pushcfunction(lua, luaRedisStatusReplyCommand);\n    lua_settable(lua, -3);\n\n    /* redis.replicate_commands */\n    lua_pushstring(lua, \"replicate_commands\");\n    lua_pushcfunction(lua, luaRedisReplicateCommandsCommand);\n    lua_settable(lua, -3);\n\n    /* redis.set_repl and associated flags. */\n    lua_pushstring(lua,\"set_repl\");\n    lua_pushcfunction(lua,luaRedisSetReplCommand);\n    lua_settable(lua,-3);\n\n    lua_pushstring(lua,\"REPL_NONE\");\n    lua_pushnumber(lua,PROPAGATE_NONE);\n    lua_settable(lua,-3);\n\n    lua_pushstring(lua,\"REPL_AOF\");\n    lua_pushnumber(lua,PROPAGATE_AOF);\n    lua_settable(lua,-3);\n\n    lua_pushstring(lua,\"REPL_SLAVE\");\n    lua_pushnumber(lua,PROPAGATE_REPL);\n    lua_settable(lua,-3);\n\n    lua_pushstring(lua,\"REPL_ALL\");\n    lua_pushnumber(lua,PROPAGATE_AOF|PROPAGATE_REPL);\n    lua_settable(lua,-3);\n\n    /* redis.breakpoint */\n    lua_pushstring(lua,\"breakpoint\");\n    lua_pushcfunction(lua,luaRedisBreakpointCommand);\n    lua_settable(lua,-3);\n\n    /* redis.debug */\n    lua_pushstring(lua,\"debug\");\n    lua_pushcfunction(lua,luaRedisDebugCommand);\n    lua_settable(lua,-3);\n\n    /* Finally set the table as 'redis' global var. */\n    lua_setglobal(lua,\"redis\");\n\n    /* Replace math.random and math.randomseed with our implementations. */\n    lua_getglobal(lua,\"math\");\n\n    lua_pushstring(lua,\"random\");\n    lua_pushcfunction(lua,redis_math_random);\n    lua_settable(lua,-3);\n\n    lua_pushstring(lua,\"randomseed\");\n    lua_pushcfunction(lua,redis_math_randomseed);\n    lua_settable(lua,-3);\n\n    lua_setglobal(lua,\"math\");\n\n    /* Add a helper function that we use to sort the multi bulk output of non\n     * deterministic commands, when containing 'false' elements. */\n    {\n        char *compare_func =    \"function __redis__compare_helper(a,b)\\n\"\n                                \"  if a == false then a = '' end\\n\"\n                                \"  if b == false then b = '' end\\n\"\n                                \"  return a<b\\n\"\n                                \"end\\n\";\n        luaL_loadbuffer(lua,compare_func,strlen(compare_func),\"@cmp_func_def\");\n        lua_pcall(lua,0,0,0);\n    }\n\n    /* Add a helper function we use for pcall error reporting.\n     * Note that when the error is in the C function we want to report the\n     * information about the caller, that's what makes sense from the point\n     * of view of the user debugging a script. */\n    {\n        char *errh_func =       \"local dbg = debug\\n\"\n                                \"function __redis__err__handler(err)\\n\"\n                                \"  local i = dbg.getinfo(2,'nSl')\\n\"\n                                \"  if i and i.what == 'C' then\\n\"\n                                \"    i = dbg.getinfo(3,'nSl')\\n\"\n                                \"  end\\n\"\n                                \"  if i then\\n\"\n                                \"    return i.source .. ':' .. i.currentline .. ': ' .. err\\n\"\n                                \"  else\\n\"\n                                \"    return err\\n\"\n                                \"  end\\n\"\n                                \"end\\n\";\n        luaL_loadbuffer(lua,errh_func,strlen(errh_func),\"@err_handler_def\");\n        lua_pcall(lua,0,0,0);\n    }\n\n    /* Create the (non connected) client that we use to execute Redis commands\n     * inside the Lua interpreter.\n     * Note: there is no need to create it again when this function is called\n     * by scriptingReset(). */\n    if (server.lua_client == NULL) {\n        server.lua_client = createClient(-1);\n        server.lua_client->flags |= CLIENT_LUA;\n    }\n\n    /* Lua beginners often don't use \"local\", this is likely to introduce\n     * subtle bugs in their code. To prevent problems we protect accesses\n     * to global variables. */\n    scriptingEnableGlobalsProtection(lua);\n\n    server.lua = lua;\n}\n\n/* Release resources related to Lua scripting.\n * This function is used in order to reset the scripting environment. */\nvoid scriptingRelease(void) {\n    dictRelease(server.lua_scripts);\n    lua_close(server.lua);\n}\n\nvoid scriptingReset(void) {\n    scriptingRelease();\n    scriptingInit(0);\n}\n\n/* Set an array of Redis String Objects as a Lua array (table) stored into a\n * global variable. */\nvoid luaSetGlobalArray(lua_State *lua, char *var, robj **elev, int elec) {\n    int j;\n\n    lua_newtable(lua);\n    for (j = 0; j < elec; j++) {\n        lua_pushlstring(lua,(char*)elev[j]->ptr,sdslen(elev[j]->ptr));\n        lua_rawseti(lua,-2,j+1);\n    }\n    lua_setglobal(lua,var);\n}\n\n/* ---------------------------------------------------------------------------\n * Redis provided math.random\n * ------------------------------------------------------------------------- */\n\n/* We replace math.random() with our implementation that is not affected\n * by specific libc random() implementations and will output the same sequence\n * (for the same seed) in every arch. */\n\n/* The following implementation is the one shipped with Lua itself but with\n * rand() replaced by redisLrand48(). */\nint redis_math_random (lua_State *L) {\n  /* the `%' avoids the (rare) case of r==1, and is needed also because on\n     some systems (SunOS!) `rand()' may return a value larger than RAND_MAX */\n  lua_Number r = (lua_Number)(redisLrand48()%REDIS_LRAND48_MAX) /\n                                (lua_Number)REDIS_LRAND48_MAX;\n  switch (lua_gettop(L)) {  /* check number of arguments */\n    case 0: {  /* no arguments */\n      lua_pushnumber(L, r);  /* Number between 0 and 1 */\n      break;\n    }\n    case 1: {  /* only upper limit */\n      int u = luaL_checkint(L, 1);\n      luaL_argcheck(L, 1<=u, 1, \"interval is empty\");\n      lua_pushnumber(L, floor(r*u)+1);  /* int between 1 and `u' */\n      break;\n    }\n    case 2: {  /* lower and upper limits */\n      int l = luaL_checkint(L, 1);\n      int u = luaL_checkint(L, 2);\n      luaL_argcheck(L, l<=u, 2, \"interval is empty\");\n      lua_pushnumber(L, floor(r*(u-l+1))+l);  /* int between `l' and `u' */\n      break;\n    }\n    default: return luaL_error(L, \"wrong number of arguments\");\n  }\n  return 1;\n}\n\nint redis_math_randomseed (lua_State *L) {\n  redisSrand48(luaL_checkint(L, 1));\n  return 0;\n}\n\n/* ---------------------------------------------------------------------------\n * EVAL and SCRIPT commands implementation\n * ------------------------------------------------------------------------- */\n\n/* Define a lua function with the specified function name and body.\n * The function name musts be a 42 characters long string, since all the\n * functions we defined in the Lua context are in the form:\n *\n *   f_<hex sha1 sum>\n *\n * On success C_OK is returned, and nothing is left on the Lua stack.\n * On error C_ERR is returned and an appropriate error is set in the\n * client context. */\nint luaCreateFunction(client *c, lua_State *lua, char *funcname, robj *body) {\n    sds funcdef = sdsempty();\n\n    funcdef = sdscat(funcdef,\"function \");\n    funcdef = sdscatlen(funcdef,funcname,42);\n    funcdef = sdscatlen(funcdef,\"() \",3);\n    funcdef = sdscatlen(funcdef,body->ptr,sdslen(body->ptr));\n    funcdef = sdscatlen(funcdef,\"\\nend\",4);\n\n    if (luaL_loadbuffer(lua,funcdef,sdslen(funcdef),\"@user_script\")) {\n        addReplyErrorFormat(c,\"Error compiling script (new function): %s\\n\",\n            lua_tostring(lua,-1));\n        lua_pop(lua,1);\n        sdsfree(funcdef);\n        return C_ERR;\n    }\n    sdsfree(funcdef);\n    if (lua_pcall(lua,0,0,0)) {\n        addReplyErrorFormat(c,\"Error running script (new function): %s\\n\",\n            lua_tostring(lua,-1));\n        lua_pop(lua,1);\n        return C_ERR;\n    }\n\n    /* We also save a SHA1 -> Original script map in a dictionary\n     * so that we can replicate / write in the AOF all the\n     * EVALSHA commands as EVAL using the original script. */\n    {\n        int retval = dictAdd(server.lua_scripts,\n                             sdsnewlen(funcname+2,40),body);\n        serverAssertWithInfo(c,NULL,retval == DICT_OK);\n        incrRefCount(body);\n    }\n    return C_OK;\n}\n\n/* This is the Lua script \"count\" hook that we use to detect scripts timeout. */\nvoid luaMaskCountHook(lua_State *lua, lua_Debug *ar) {\n    long long elapsed;\n    UNUSED(ar);\n    UNUSED(lua);\n\n    elapsed = mstime() - server.lua_time_start;\n    if (elapsed >= server.lua_time_limit && server.lua_timedout == 0) {\n        serverLog(LL_WARNING,\"Lua slow script detected: still in execution after %lld milliseconds. You can try killing the script using the SCRIPT KILL command.\",elapsed);\n        server.lua_timedout = 1;\n        /* Once the script timeouts we reenter the event loop to permit others\n         * to call SCRIPT KILL or SHUTDOWN NOSAVE if needed. For this reason\n         * we need to mask the client executing the script from the event loop.\n         * If we don't do that the client may disconnect and could no longer be\n         * here when the EVAL command will return. */\n         aeDeleteFileEvent(server.el, server.lua_caller->fd, AE_READABLE);\n    }\n    if (server.lua_timedout) processEventsWhileBlocked();\n    if (server.lua_kill) {\n        serverLog(LL_WARNING,\"Lua script killed by user with SCRIPT KILL.\");\n        lua_pushstring(lua,\"Script killed by user with SCRIPT KILL...\");\n        lua_error(lua);\n    }\n}\n\nvoid evalGenericCommand(client *c, int evalsha) {\n    lua_State *lua = server.lua;\n    char funcname[43];\n    long long numkeys;\n    int delhook = 0, err;\n\n    /* When we replicate whole scripts, we want the same PRNG sequence at\n     * every call so that our PRNG is not affected by external state. */\n    redisSrand48(0);\n\n    /* We set this flag to zero to remember that so far no random command\n     * was called. This way we can allow the user to call commands like\n     * SRANDMEMBER or RANDOMKEY from Lua scripts as far as no write command\n     * is called (otherwise the replication and AOF would end with non\n     * deterministic sequences).\n     *\n     * Thanks to this flag we'll raise an error every time a write command\n     * is called after a random command was used. */\n    server.lua_random_dirty = 0;\n    server.lua_write_dirty = 0;\n    server.lua_replicate_commands = server.lua_always_replicate_commands;\n    server.lua_multi_emitted = 0;\n    server.lua_repl = PROPAGATE_AOF|PROPAGATE_REPL;\n\n    /* Get the number of arguments that are keys */\n    if (getLongLongFromObjectOrReply(c,c->argv[2],&numkeys,NULL) != C_OK)\n        return;\n    if (numkeys > (c->argc - 3)) {\n        addReplyError(c,\"Number of keys can't be greater than number of args\");\n        return;\n    } else if (numkeys < 0) {\n        addReplyError(c,\"Number of keys can't be negative\");\n        return;\n    }\n\n    /* We obtain the script SHA1, then check if this function is already\n     * defined into the Lua state */\n    funcname[0] = 'f';\n    funcname[1] = '_';\n    if (!evalsha) {\n        /* Hash the code if this is an EVAL call */\n        sha1hex(funcname+2,c->argv[1]->ptr,sdslen(c->argv[1]->ptr));\n    } else {\n        /* We already have the SHA if it is a EVALSHA */\n        int j;\n        char *sha = c->argv[1]->ptr;\n\n        /* Convert to lowercase. We don't use tolower since the function\n         * managed to always show up in the profiler output consuming\n         * a non trivial amount of time. */\n        for (j = 0; j < 40; j++)\n            funcname[j+2] = (sha[j] >= 'A' && sha[j] <= 'Z') ?\n                sha[j]+('a'-'A') : sha[j];\n        funcname[42] = '\\0';\n    }\n\n    /* Push the pcall error handler function on the stack. */\n    lua_getglobal(lua, \"__redis__err__handler\");\n\n    /* Try to lookup the Lua function */\n    lua_getglobal(lua, funcname);\n    if (lua_isnil(lua,-1)) {\n        lua_pop(lua,1); /* remove the nil from the stack */\n        /* Function not defined... let's define it if we have the\n         * body of the function. If this is an EVALSHA call we can just\n         * return an error. */\n        if (evalsha) {\n            lua_pop(lua,1); /* remove the error handler from the stack. */\n            addReply(c, shared.noscripterr);\n            return;\n        }\n        if (luaCreateFunction(c,lua,funcname,c->argv[1]) == C_ERR) {\n            lua_pop(lua,1); /* remove the error handler from the stack. */\n            /* The error is sent to the client by luaCreateFunction()\n             * itself when it returns C_ERR. */\n            return;\n        }\n        /* Now the following is guaranteed to return non nil */\n        lua_getglobal(lua, funcname);\n        serverAssert(!lua_isnil(lua,-1));\n    }\n\n    /* Populate the argv and keys table accordingly to the arguments that\n     * EVAL received. */\n    luaSetGlobalArray(lua,\"KEYS\",c->argv+3,numkeys);\n    luaSetGlobalArray(lua,\"ARGV\",c->argv+3+numkeys,c->argc-3-numkeys);\n\n    /* Select the right DB in the context of the Lua client */\n    selectDb(server.lua_client,c->db->id);\n\n    /* Set a hook in order to be able to stop the script execution if it\n     * is running for too much time.\n     * We set the hook only if the time limit is enabled as the hook will\n     * make the Lua script execution slower.\n     *\n     * If we are debugging, we set instead a \"line\" hook so that the\n     * debugger is call-back at every line executed by the script. */\n    server.lua_caller = c;\n    server.lua_time_start = mstime();\n    server.lua_kill = 0;\n    if (server.lua_time_limit > 0 && server.masterhost == NULL &&\n        ldb.active == 0)\n    {\n        lua_sethook(lua,luaMaskCountHook,LUA_MASKCOUNT,100000);\n        delhook = 1;\n    } else if (ldb.active) {\n        lua_sethook(server.lua,luaLdbLineHook,LUA_MASKLINE|LUA_MASKCOUNT,100000);\n        delhook = 1;\n    }\n\n    /* At this point whether this script was never seen before or if it was\n     * already defined, we can call it. We have zero arguments and expect\n     * a single return value. */\n    err = lua_pcall(lua,0,1,-2);\n\n    /* Perform some cleanup that we need to do both on error and success. */\n    if (delhook) lua_sethook(lua,NULL,0,0); /* Disable hook */\n    if (server.lua_timedout) {\n        server.lua_timedout = 0;\n        /* Restore the readable handler that was unregistered when the\n         * script timeout was detected. */\n        aeCreateFileEvent(server.el,c->fd,AE_READABLE,\n                          readQueryFromClient,c);\n    }\n    server.lua_caller = NULL;\n\n    /* Call the Lua garbage collector from time to time to avoid a\n     * full cycle performed by Lua, which adds too latency.\n     *\n     * The call is performed every LUA_GC_CYCLE_PERIOD executed commands\n     * (and for LUA_GC_CYCLE_PERIOD collection steps) because calling it\n     * for every command uses too much CPU. */\n    #define LUA_GC_CYCLE_PERIOD 50\n    {\n        static long gc_count = 0;\n\n        gc_count++;\n        if (gc_count == LUA_GC_CYCLE_PERIOD) {\n            lua_gc(lua,LUA_GCSTEP,LUA_GC_CYCLE_PERIOD);\n            gc_count = 0;\n        }\n    }\n\n    if (err) {\n        addReplyErrorFormat(c,\"Error running script (call to %s): %s\\n\",\n            funcname, lua_tostring(lua,-1));\n        lua_pop(lua,2); /* Consume the Lua reply and remove error handler. */\n    } else {\n        /* On success convert the Lua return value into Redis protocol, and\n         * send it to * the client. */\n        luaReplyToRedisReply(c,lua); /* Convert and consume the reply. */\n        lua_pop(lua,1); /* Remove the error handler. */\n    }\n\n    /* If we are using single commands replication, emit EXEC if there\n     * was at least a write. */\n    if (server.lua_replicate_commands) {\n        preventCommandPropagation(c);\n        if (server.lua_multi_emitted) {\n            robj *propargv[1];\n            propargv[0] = createStringObject(\"EXEC\",4);\n            alsoPropagate(server.execCommand,c->db->id,propargv,1,\n                PROPAGATE_AOF|PROPAGATE_REPL);\n            decrRefCount(propargv[0]);\n        }\n    }\n\n    /* EVALSHA should be propagated to Slave and AOF file as full EVAL, unless\n     * we are sure that the script was already in the context of all the\n     * attached slaves *and* the current AOF file if enabled.\n     *\n     * To do so we use a cache of SHA1s of scripts that we already propagated\n     * as full EVAL, that's called the Replication Script Cache.\n     *\n     * For repliation, everytime a new slave attaches to the master, we need to\n     * flush our cache of scripts that can be replicated as EVALSHA, while\n     * for AOF we need to do so every time we rewrite the AOF file. */\n    if (evalsha && !server.lua_replicate_commands) {\n        if (!replicationScriptCacheExists(c->argv[1]->ptr)) {\n            /* This script is not in our script cache, replicate it as\n             * EVAL, then add it into the script cache, as from now on\n             * slaves and AOF know about it. */\n            robj *script = dictFetchValue(server.lua_scripts,c->argv[1]->ptr);\n\n            replicationScriptCacheAdd(c->argv[1]->ptr);\n            serverAssertWithInfo(c,NULL,script != NULL);\n            rewriteClientCommandArgument(c,0,\n                resetRefCount(createStringObject(\"EVAL\",4)));\n            rewriteClientCommandArgument(c,1,script);\n            forceCommandPropagation(c,PROPAGATE_REPL|PROPAGATE_AOF);\n        }\n    }\n}\n\nvoid evalCommand(client *c) {\n    if (!(c->flags & CLIENT_LUA_DEBUG))\n        evalGenericCommand(c,0);\n    else\n        evalGenericCommandWithDebugging(c,0);\n}\n\nvoid evalShaCommand(client *c) {\n    if (sdslen(c->argv[1]->ptr) != 40) {\n        /* We know that a match is not possible if the provided SHA is\n         * not the right length. So we return an error ASAP, this way\n         * evalGenericCommand() can be implemented without string length\n         * sanity check */\n        addReply(c, shared.noscripterr);\n        return;\n    }\n    if (!(c->flags & CLIENT_LUA_DEBUG))\n        evalGenericCommand(c,1);\n    else {\n        addReplyError(c,\"Please use EVAL instead of EVALSHA for debugging\");\n        return;\n    }\n}\n\nvoid scriptCommand(client *c) {\n    if (c->argc == 2 && !strcasecmp(c->argv[1]->ptr,\"flush\")) {\n        scriptingReset();\n        addReply(c,shared.ok);\n        replicationScriptCacheFlush();\n        server.dirty++; /* Propagating this command is a good idea. */\n    } else if (c->argc >= 2 && !strcasecmp(c->argv[1]->ptr,\"exists\")) {\n        int j;\n\n        addReplyMultiBulkLen(c, c->argc-2);\n        for (j = 2; j < c->argc; j++) {\n            if (dictFind(server.lua_scripts,c->argv[j]->ptr))\n                addReply(c,shared.cone);\n            else\n                addReply(c,shared.czero);\n        }\n    } else if (c->argc == 3 && !strcasecmp(c->argv[1]->ptr,\"load\")) {\n        char funcname[43];\n        sds sha;\n\n        funcname[0] = 'f';\n        funcname[1] = '_';\n        sha1hex(funcname+2,c->argv[2]->ptr,sdslen(c->argv[2]->ptr));\n        sha = sdsnewlen(funcname+2,40);\n        if (dictFind(server.lua_scripts,sha) == NULL) {\n            if (luaCreateFunction(c,server.lua,funcname,c->argv[2])\n                    == C_ERR) {\n                sdsfree(sha);\n                return;\n            }\n        }\n        addReplyBulkCBuffer(c,funcname+2,40);\n        sdsfree(sha);\n        forceCommandPropagation(c,PROPAGATE_REPL|PROPAGATE_AOF);\n    } else if (c->argc == 2 && !strcasecmp(c->argv[1]->ptr,\"kill\")) {\n        if (server.lua_caller == NULL) {\n            addReplySds(c,sdsnew(\"-NOTBUSY No scripts in execution right now.\\r\\n\"));\n        } else if (server.lua_write_dirty) {\n            addReplySds(c,sdsnew(\"-UNKILLABLE Sorry the script already executed write commands against the dataset. You can either wait the script termination or kill the server in a hard way using the SHUTDOWN NOSAVE command.\\r\\n\"));\n        } else {\n            server.lua_kill = 1;\n            addReply(c,shared.ok);\n        }\n    } else if (c->argc == 3 && !strcasecmp(c->argv[1]->ptr,\"debug\")) {\n        if (clientHasPendingReplies(c)) {\n            addReplyError(c,\"SCRIPT DEBUG must be called outside a pipeline\");\n            return;\n        }\n        if (!strcasecmp(c->argv[2]->ptr,\"no\")) {\n            ldbDisable(c);\n            addReply(c,shared.ok);\n        } else if (!strcasecmp(c->argv[2]->ptr,\"yes\")) {\n            ldbEnable(c);\n            addReply(c,shared.ok);\n        } else if (!strcasecmp(c->argv[2]->ptr,\"sync\")) {\n            ldbEnable(c);\n            addReply(c,shared.ok);\n            c->flags |= CLIENT_LUA_DEBUG_SYNC;\n        } else {\n            addReplyError(c,\"Use SCRIPT DEBUG yes/sync/no\");\n        }\n    } else {\n        addReplyError(c, \"Unknown SCRIPT subcommand or wrong # of args.\");\n    }\n}\n\n/* ---------------------------------------------------------------------------\n * LDB: Redis Lua debugging facilities\n * ------------------------------------------------------------------------- */\n\n/* Initialize Lua debugger data structures. */\nvoid ldbInit(void) {\n    ldb.fd = -1;\n    ldb.active = 0;\n    ldb.logs = listCreate();\n    listSetFreeMethod(ldb.logs,(void (*)(void*))sdsfree);\n    ldb.children = listCreate();\n    ldb.src = NULL;\n    ldb.lines = 0;\n    ldb.cbuf = sdsempty();\n}\n\n/* Remove all the pending messages in the specified list. */\nvoid ldbFlushLog(list *log) {\n    listNode *ln;\n\n    while((ln = listFirst(log)) != NULL)\n        listDelNode(log,ln);\n}\n\n/* Enable debug mode of Lua scripts for this client. */\nvoid ldbEnable(client *c) {\n    c->flags |= CLIENT_LUA_DEBUG;\n    ldbFlushLog(ldb.logs);\n    ldb.fd = c->fd;\n    ldb.step = 1;\n    ldb.bpcount = 0;\n    ldb.luabp = 0;\n    sdsfree(ldb.cbuf);\n    ldb.cbuf = sdsempty();\n    ldb.maxlen = LDB_MAX_LEN_DEFAULT;\n    ldb.maxlen_hint_sent = 0;\n}\n\n/* Exit debugging mode from the POV of client. This function is not enough\n * to properly shut down a client debugging session, see ldbEndSession()\n * for more information. */\nvoid ldbDisable(client *c) {\n    c->flags &= ~(CLIENT_LUA_DEBUG|CLIENT_LUA_DEBUG_SYNC);\n}\n\n/* Append a log entry to the specified LDB log. */\nvoid ldbLog(sds entry) {\n    listAddNodeTail(ldb.logs,entry);\n}\n\n/* A version of ldbLog() which prevents producing logs greater than\n * ldb.maxlen. The first time the limit is reached an hint is generated\n * to inform the user that reply trimming can be disabled using the\n * debugger \"maxlen\" command. */\nvoid ldbLogWithMaxLen(sds entry) {\n    int trimmed = 0;\n    if (ldb.maxlen && sdslen(entry) > ldb.maxlen) {\n        sdsrange(entry,0,ldb.maxlen-1);\n        entry = sdscatlen(entry,\" ...\",4);\n        trimmed = 1;\n    }\n    ldbLog(entry);\n    if (trimmed && ldb.maxlen_hint_sent == 0) {\n        ldb.maxlen_hint_sent = 1;\n        ldbLog(sdsnew(\n        \"<hint> The above reply was trimmed. Use 'maxlen 0' to disable trimming.\"));\n    }\n}\n\n/* Send ldb.logs to the debugging client as a multi-bulk reply\n * consisting of simple strings. Log entries which include newlines have them\n * replaced with spaces. The entries sent are also consumed. */\nvoid ldbSendLogs(void) {\n    sds proto = sdsempty();\n    proto = sdscatfmt(proto,\"*%i\\r\\n\", (int)listLength(ldb.logs));\n    while(listLength(ldb.logs)) {\n        listNode *ln = listFirst(ldb.logs);\n        proto = sdscatlen(proto,\"+\",1);\n        sdsmapchars(ln->value,\"\\r\\n\",\"  \",2);\n        proto = sdscatsds(proto,ln->value);\n        proto = sdscatlen(proto,\"\\r\\n\",2);\n        listDelNode(ldb.logs,ln);\n    }\n    if (write(ldb.fd,proto,sdslen(proto)) == -1) {\n        /* Avoid warning. We don't check the return value of write()\n         * since the next read() will catch the I/O error and will\n         * close the debugging session. */\n    }\n    sdsfree(proto);\n}\n\n/* Start a debugging session before calling EVAL implementation.\n * The techique we use is to capture the client socket file descriptor,\n * in order to perform direct I/O with it from within Lua hooks. This\n * way we don't have to re-enter Redis in order to handle I/O.\n *\n * The function returns 1 if the caller should proceed to call EVAL,\n * and 0 if instead the caller should abort the operation (this happens\n * for the parent in a forked session, since it's up to the children\n * to continue, or when fork returned an error).\n *\n * The caller should call ldbEndSession() only if ldbStartSession()\n * returned 1. */\nint ldbStartSession(client *c) {\n    ldb.forked = (c->flags & CLIENT_LUA_DEBUG_SYNC) == 0;\n    if (ldb.forked) {\n        pid_t cp = fork();\n        if (cp == -1) {\n            addReplyError(c,\"Fork() failed: can't run EVAL in debugging mode.\");\n            return 0;\n        } else if (cp == 0) {\n            /* Child. Let's ignore important signals handled by the parent. */\n            struct sigaction act;\n            sigemptyset(&act.sa_mask);\n            act.sa_flags = 0;\n            act.sa_handler = SIG_IGN;\n            sigaction(SIGTERM, &act, NULL);\n            sigaction(SIGINT, &act, NULL);\n\n            /* Log the creation of the child and close the listening\n             * socket to make sure if the parent crashes a reset is sent\n             * to the clients. */\n            serverLog(LL_WARNING,\"Redis forked for debugging eval\");\n            closeListeningSockets(0);\n        } else {\n            /* Parent */\n            listAddNodeTail(ldb.children,(void*)(unsigned long)cp);\n            freeClientAsync(c); /* Close the client in the parent side. */\n            return 0;\n        }\n    } else {\n        serverLog(LL_WARNING,\n            \"Redis synchronous debugging eval session started\");\n    }\n\n    /* Setup our debugging session. */\n    anetBlock(NULL,ldb.fd);\n    anetSendTimeout(NULL,ldb.fd,5000);\n    ldb.active = 1;\n\n    /* First argument of EVAL is the script itself. We split it into different\n     * lines since this is the way the debugger accesses the source code. */\n    sds srcstring = sdsdup(c->argv[1]->ptr);\n    size_t srclen = sdslen(srcstring);\n    while(srclen && (srcstring[srclen-1] == '\\n' ||\n                     srcstring[srclen-1] == '\\r'))\n    {\n        srcstring[--srclen] = '\\0';\n    }\n    sdssetlen(srcstring,srclen);\n    ldb.src = sdssplitlen(srcstring,sdslen(srcstring),\"\\n\",1,&ldb.lines);\n    sdsfree(srcstring);\n    return 1;\n}\n\n/* End a debugging session after the EVAL call with debugging enabled\n * returned. */\nvoid ldbEndSession(client *c) {\n    /* Emit the remaining logs and an <endsession> mark. */\n    ldbLog(sdsnew(\"<endsession>\"));\n    ldbSendLogs();\n\n    /* If it's a fork()ed session, we just exit. */\n    if (ldb.forked) {\n        writeToClient(c->fd, c, 0);\n        serverLog(LL_WARNING,\"Lua debugging session child exiting\");\n        exitFromChild(0);\n    } else {\n        serverLog(LL_WARNING,\n            \"Redis synchronous debugging eval session ended\");\n    }\n\n    /* Otherwise let's restore client's state. */\n    anetNonBlock(NULL,ldb.fd);\n    anetSendTimeout(NULL,ldb.fd,0);\n\n    /* Close the client connectin after sending the final EVAL reply\n     * in order to signal the end of the debugging session. */\n    c->flags |= CLIENT_CLOSE_AFTER_REPLY;\n\n    /* Cleanup. */\n    sdsfreesplitres(ldb.src,ldb.lines);\n    ldb.lines = 0;\n    ldb.active = 0;\n}\n\n/* If the specified pid is among the list of children spawned for\n * forked debugging sessions, it is removed from the children list.\n * If the pid was found non-zero is returned. */\nint ldbRemoveChild(pid_t pid) {\n    listNode *ln = listSearchKey(ldb.children,(void*)(unsigned long)pid);\n    if (ln) {\n        listDelNode(ldb.children,ln);\n        return 1;\n    }\n    return 0;\n}\n\n/* Return the number of children we still did not received termination\n * acknowledge via wait() in the parent process. */\nint ldbPendingChildren(void) {\n    return listLength(ldb.children);\n}\n\n/* Kill all the forked sessions. */\nvoid ldbKillForkedSessions(void) {\n    listIter li;\n    listNode *ln;\n\n    listRewind(ldb.children,&li);\n    while((ln = listNext(&li))) {\n        pid_t pid = (unsigned long) ln->value;\n        serverLog(LL_WARNING,\"Killing debugging session %ld\",(long)pid);\n        kill(pid,SIGKILL);\n    }\n    listRelease(ldb.children);\n    ldb.children = listCreate();\n}\n\n/* Wrapper for EVAL / EVALSHA that enables debugging, and makes sure\n * that when EVAL returns, whatever happened, the session is ended. */\nvoid evalGenericCommandWithDebugging(client *c, int evalsha) {\n    if (ldbStartSession(c)) {\n        evalGenericCommand(c,evalsha);\n        ldbEndSession(c);\n    } else {\n        ldbDisable(c);\n    }\n}\n\n/* Return a pointer to ldb.src source code line, considering line to be\n * one-based, and returning a special string for out of range lines. */\nchar *ldbGetSourceLine(int line) {\n    int idx = line-1;\n    if (idx < 0 || idx >= ldb.lines) return \"<out of range source code line>\";\n    return ldb.src[idx];\n}\n\n/* Return true if there is a breakpoint in the specified line. */\nint ldbIsBreakpoint(int line) {\n    int j;\n\n    for (j = 0; j < ldb.bpcount; j++)\n        if (ldb.bp[j] == line) return 1;\n    return 0;\n}\n\n/* Add the specified breakpoint. Ignore it if we already reached the max.\n * Returns 1 if the breakpoint was added (or was already set). 0 if there is\n * no space for the breakpoint or if the line is invalid. */\nint ldbAddBreakpoint(int line) {\n    if (line <= 0 || line > ldb.lines) return 0;\n    if (!ldbIsBreakpoint(line) && ldb.bpcount != LDB_BREAKPOINTS_MAX) {\n        ldb.bp[ldb.bpcount++] = line;\n        return 1;\n    }\n    return 0;\n}\n\n/* Remove the specified breakpoint, returning 1 if the operation was\n * performed or 0 if there was no such breakpoint. */\nint ldbDelBreakpoint(int line) {\n    int j;\n\n    for (j = 0; j < ldb.bpcount; j++) {\n        if (ldb.bp[j] == line) {\n            ldb.bpcount--;\n            memmove(ldb.bp+j,ldb.bp+j+1,ldb.bpcount-j);\n            return 1;\n        }\n    }\n    return 0;\n}\n\n/* Expect a valid multi-bulk command in the debugging client query buffer.\n * On success the command is parsed and returned as an array of SDS strings,\n * otherwise NULL is returned and there is to read more buffer. */\nsds *ldbReplParseCommand(int *argcp) {\n    sds *argv = NULL;\n    int argc = 0;\n    if (sdslen(ldb.cbuf) == 0) return NULL;\n\n    /* Working on a copy is simpler in this case. We can modify it freely\n     * for the sake of simpler parsing. */\n    sds copy = sdsdup(ldb.cbuf);\n    char *p = copy;\n\n    /* This Redis protocol parser is a joke... just the simplest thing that\n     * works in this context. It is also very forgiving regarding broken\n     * protocol. */\n\n    /* Seek and parse *<count>\\r\\n. */\n    p = strchr(p,'*'); if (!p) goto protoerr;\n    char *plen = p+1; /* Multi bulk len pointer. */\n    p = strstr(p,\"\\r\\n\"); if (!p) goto protoerr;\n    *p = '\\0'; p += 2;\n    *argcp = atoi(plen);\n    if (*argcp <= 0 || *argcp > 1024) goto protoerr;\n\n    /* Parse each argument. */\n    argv = zmalloc(sizeof(sds)*(*argcp));\n    argc = 0;\n    while(argc < *argcp) {\n        if (*p != '$') goto protoerr;\n        plen = p+1; /* Bulk string len pointer. */\n        p = strstr(p,\"\\r\\n\"); if (!p) goto protoerr;\n        *p = '\\0'; p += 2;\n        int slen = atoi(plen); /* Length of this arg. */\n        if (slen <= 0 || slen > 1024) goto protoerr;\n        argv[argc++] = sdsnewlen(p,slen);\n        p += slen; /* Skip the already parsed argument. */\n        if (p[0] != '\\r' || p[1] != '\\n') goto protoerr;\n        p += 2; /* Skip \\r\\n. */\n    }\n    sdsfree(copy);\n    return argv;\n\nprotoerr:\n    sdsfreesplitres(argv,argc);\n    sdsfree(copy);\n    return NULL;\n}\n\n/* Log the specified line in the Lua debugger output. */\nvoid ldbLogSourceLine(int lnum) {\n    char *line = ldbGetSourceLine(lnum);\n    char *prefix;\n    int bp = ldbIsBreakpoint(lnum);\n    int current = ldb.currentline == lnum;\n\n    if (current && bp)\n        prefix = \"->#\";\n    else if (current)\n        prefix = \"-> \";\n    else if (bp)\n        prefix = \"  #\";\n    else\n        prefix = \"   \";\n    sds thisline = sdscatprintf(sdsempty(),\"%s%-3d %s\", prefix, lnum, line);\n    ldbLog(thisline);\n}\n\n/* Implement the \"list\" command of the Lua debugger. If around is 0\n * the whole file is listed, otherwise only a small portion of the file\n * around the specified line is shown. When a line number is specified\n * the amonut of context (lines before/after) is specified via the\n * 'context' argument. */\nvoid ldbList(int around, int context) {\n    int j;\n\n    for (j = 1; j <= ldb.lines; j++) {\n        if (around != 0 && abs(around-j) > context) continue;\n        ldbLogSourceLine(j);\n    }\n}\n\n/* Append an human readable representation of the Lua value at position 'idx'\n * on the stack of the 'lua' state, to the SDS string passed as argument.\n * The new SDS string with the represented value attached is returned.\n * Used in order to implement ldbLogStackValue().\n *\n * The element is not automatically removed from the stack, nor it is\n * converted to a different type. */\n#define LDB_MAX_VALUES_DEPTH (LUA_MINSTACK/2)\nsds ldbCatStackValueRec(sds s, lua_State *lua, int idx, int level) {\n    int t = lua_type(lua,idx);\n\n    if (level++ == LDB_MAX_VALUES_DEPTH)\n        return sdscat(s,\"<max recursion level reached! Nested table?>\");\n\n    switch(t) {\n    case LUA_TSTRING:\n        {\n        size_t strl;\n        char *strp = (char*)lua_tolstring(lua,idx,&strl);\n        s = sdscatrepr(s,strp,strl);\n        }\n        break;\n    case LUA_TBOOLEAN:\n        s = sdscat(s,lua_toboolean(lua,idx) ? \"true\" : \"false\");\n        break;\n    case LUA_TNUMBER:\n        s = sdscatprintf(s,\"%g\",(double)lua_tonumber(lua,idx));\n        break;\n    case LUA_TNIL:\n        s = sdscatlen(s,\"nil\",3);\n        break;\n    case LUA_TTABLE:\n        {\n        int expected_index = 1; /* First index we expect in an array. */\n        int is_array = 1; /* Will be set to null if check fails. */\n        /* Note: we create two representations at the same time, one\n         * assuming the table is an array, one assuming it is not. At the\n         * end we know what is true and select the right one. */\n        sds repr1 = sdsempty();\n        sds repr2 = sdsempty();\n        lua_pushnil(lua); /* The first key to start the iteration is nil. */\n        while (lua_next(lua,idx-1)) {\n            /* Test if so far the table looks like an array. */\n            if (is_array &&\n                (lua_type(lua,-2) != LUA_TNUMBER ||\n                 lua_tonumber(lua,-2) != expected_index)) is_array = 0;\n            /* Stack now: table, key, value */\n            /* Array repr. */\n            repr1 = ldbCatStackValueRec(repr1,lua,-1,level);\n            repr1 = sdscatlen(repr1,\"; \",2);\n            /* Full repr. */\n            repr2 = sdscatlen(repr2,\"[\",1);\n            repr2 = ldbCatStackValueRec(repr2,lua,-2,level);\n            repr2 = sdscatlen(repr2,\"]=\",2);\n            repr2 = ldbCatStackValueRec(repr2,lua,-1,level);\n            repr2 = sdscatlen(repr2,\"; \",2);\n            lua_pop(lua,1); /* Stack: table, key. Ready for next iteration. */\n            expected_index++;\n        }\n        /* Strip the last \" ;\" from both the representations. */\n        if (sdslen(repr1)) sdsrange(repr1,0,-3);\n        if (sdslen(repr2)) sdsrange(repr2,0,-3);\n        /* Select the right one and discard the other. */\n        s = sdscatlen(s,\"{\",1);\n        s = sdscatsds(s,is_array ? repr1 : repr2);\n        s = sdscatlen(s,\"}\",1);\n        sdsfree(repr1);\n        sdsfree(repr2);\n        }\n        break;\n    case LUA_TFUNCTION:\n    case LUA_TUSERDATA:\n    case LUA_TTHREAD:\n    case LUA_TLIGHTUSERDATA:\n        {\n        const void *p = lua_topointer(lua,idx);\n        char *typename = \"unknown\";\n        if (t == LUA_TFUNCTION) typename = \"function\";\n        else if (t == LUA_TUSERDATA) typename = \"userdata\";\n        else if (t == LUA_TTHREAD) typename = \"thread\";\n        else if (t == LUA_TLIGHTUSERDATA) typename = \"light-userdata\";\n        s = sdscatprintf(s,\"\\\"%s@%p\\\"\",typename,p);\n        }\n        break;\n    default:\n        s = sdscat(s,\"\\\"<unknown-lua-type>\\\"\");\n        break;\n    }\n    return s;\n}\n\n/* Higher level wrapper for ldbCatStackValueRec() that just uses an initial\n * recursion level of '0'. */\nsds ldbCatStackValue(sds s, lua_State *lua, int idx) {\n    return ldbCatStackValueRec(s,lua,idx,0);\n}\n\n/* Produce a debugger log entry representing the value of the Lua object\n * currently on the top of the stack. The element is ot popped nor modified.\n * Check ldbCatStackValue() for the actual implementation. */\nvoid ldbLogStackValue(lua_State *lua, char *prefix) {\n    sds s = sdsnew(prefix);\n    s = ldbCatStackValue(s,lua,-1);\n    ldbLogWithMaxLen(s);\n}\n\nchar *ldbRedisProtocolToHuman_Int(sds *o, char *reply);\nchar *ldbRedisProtocolToHuman_Bulk(sds *o, char *reply);\nchar *ldbRedisProtocolToHuman_Status(sds *o, char *reply);\nchar *ldbRedisProtocolToHuman_MultiBulk(sds *o, char *reply);\n\n/* Get Redis protocol from 'reply' and appends it in human readable form to\n * the passed SDS string 'o'.\n *\n * Note that the SDS string is passed by reference (pointer of pointer to\n * char*) so that we can return a modified pointer, as for SDS semantics. */\nchar *ldbRedisProtocolToHuman(sds *o, char *reply) {\n    char *p = reply;\n    switch(*p) {\n    case ':': p = ldbRedisProtocolToHuman_Int(o,reply); break;\n    case '$': p = ldbRedisProtocolToHuman_Bulk(o,reply); break;\n    case '+': p = ldbRedisProtocolToHuman_Status(o,reply); break;\n    case '-': p = ldbRedisProtocolToHuman_Status(o,reply); break;\n    case '*': p = ldbRedisProtocolToHuman_MultiBulk(o,reply); break;\n    }\n    return p;\n}\n\n/* The following functions are helpers for ldbRedisProtocolToHuman(), each\n * take care of a given Redis return type. */\n\nchar *ldbRedisProtocolToHuman_Int(sds *o, char *reply) {\n    char *p = strchr(reply+1,'\\r');\n    *o = sdscatlen(*o,reply+1,p-reply-1);\n    return p+2;\n}\n\nchar *ldbRedisProtocolToHuman_Bulk(sds *o, char *reply) {\n    char *p = strchr(reply+1,'\\r');\n    long long bulklen;\n\n    string2ll(reply+1,p-reply-1,&bulklen);\n    if (bulklen == -1) {\n        *o = sdscatlen(*o,\"NULL\",4);\n        return p+2;\n    } else {\n        *o = sdscatrepr(*o,p+2,bulklen);\n        return p+2+bulklen+2;\n    }\n}\n\nchar *ldbRedisProtocolToHuman_Status(sds *o, char *reply) {\n    char *p = strchr(reply+1,'\\r');\n\n    *o = sdscatrepr(*o,reply,p-reply);\n    return p+2;\n}\n\nchar *ldbRedisProtocolToHuman_MultiBulk(sds *o, char *reply) {\n    char *p = strchr(reply+1,'\\r');\n    long long mbulklen;\n    int j = 0;\n\n    string2ll(reply+1,p-reply-1,&mbulklen);\n    p += 2;\n    if (mbulklen == -1) {\n        *o = sdscatlen(*o,\"NULL\",4);\n        return p;\n    }\n    *o = sdscatlen(*o,\"[\",1);\n    for (j = 0; j < mbulklen; j++) {\n        p = ldbRedisProtocolToHuman(o,p);\n        if (j != mbulklen-1) *o = sdscatlen(*o,\",\",1);\n    }\n    *o = sdscatlen(*o,\"]\",1);\n    return p;\n}\n\n/* Log a Redis reply as debugger output, in an human readable format.\n * If the resulting string is longer than 'len' plus a few more chars\n * used as prefix, it gets truncated. */\nvoid ldbLogRedisReply(char *reply) {\n    sds log = sdsnew(\"<reply> \");\n    ldbRedisProtocolToHuman(&log,reply);\n    ldbLogWithMaxLen(log);\n}\n\n/* Implements the \"print <var>\" command of the Lua debugger. It scans for Lua\n * var \"varname\" starting from the current stack frame up to the top stack\n * frame. The first matching variable is printed. */\nvoid ldbPrint(lua_State *lua, char *varname) {\n    lua_Debug ar;\n\n    int l = 0; /* Stack level. */\n    while (lua_getstack(lua,l,&ar) != 0) {\n        l++;\n        const char *name;\n        int i = 1; /* Variable index. */\n        while((name = lua_getlocal(lua,&ar,i)) != NULL) {\n            i++;\n            if (strcmp(varname,name) == 0) {\n                ldbLogStackValue(lua,\"<value> \");\n                lua_pop(lua,1);\n                return;\n            } else {\n                lua_pop(lua,1); /* Discard the var name on the stack. */\n            }\n        }\n    }\n\n    /* Let's try with global vars in two selected cases */\n    if (!strcmp(varname,\"ARGV\") || !strcmp(varname,\"KEYS\")) {\n        lua_getglobal(lua, varname);\n        ldbLogStackValue(lua,\"<value> \");\n        lua_pop(lua,1);\n    } else {\n        ldbLog(sdsnew(\"No such variable.\"));\n    }\n}\n\n/* Implements the \"print\" command (without arguments) of the Lua debugger.\n * Prints all the variables in the current stack frame. */\nvoid ldbPrintAll(lua_State *lua) {\n    lua_Debug ar;\n    int vars = 0;\n\n    if (lua_getstack(lua,0,&ar) != 0) {\n        const char *name;\n        int i = 1; /* Variable index. */\n        while((name = lua_getlocal(lua,&ar,i)) != NULL) {\n            i++;\n            if (!strstr(name,\"(*temporary)\")) {\n                sds prefix = sdscatprintf(sdsempty(),\"<value> %s = \",name);\n                ldbLogStackValue(lua,prefix);\n                sdsfree(prefix);\n                vars++;\n            }\n            lua_pop(lua,1);\n        }\n    }\n\n    if (vars == 0) {\n        ldbLog(sdsnew(\"No local variables in the current context.\"));\n    }\n}\n\n/* Implements the break command to list, add and remove breakpoints. */\nvoid ldbBreak(sds *argv, int argc) {\n    if (argc == 1) {\n        if (ldb.bpcount == 0) {\n            ldbLog(sdsnew(\"No breakpoints set. Use 'b <line>' to add one.\"));\n            return;\n        } else {\n            ldbLog(sdscatfmt(sdsempty(),\"%i breakpoints set:\",ldb.bpcount));\n            int j;\n            for (j = 0; j < ldb.bpcount; j++)\n                ldbLogSourceLine(ldb.bp[j]);\n        }\n    } else {\n        int j;\n        for (j = 1; j < argc; j++) {\n            char *arg = argv[j];\n            long line;\n            if (!string2l(arg,sdslen(arg),&line)) {\n                ldbLog(sdscatfmt(sdsempty(),\"Invalid argument:'%s'\",arg));\n            } else {\n                if (line == 0) {\n                    ldb.bpcount = 0;\n                    ldbLog(sdsnew(\"All breakpoints removed.\"));\n                } else if (line > 0) {\n                    if (ldb.bpcount == LDB_BREAKPOINTS_MAX) {\n                        ldbLog(sdsnew(\"Too many breakpoints set.\"));\n                    } else if (ldbAddBreakpoint(line)) {\n                        ldbList(line,1);\n                    } else {\n                        ldbLog(sdsnew(\"Wrong line number.\"));\n                    }\n                } else if (line < 0) {\n                    if (ldbDelBreakpoint(-line))\n                        ldbLog(sdsnew(\"Breakpoint removed.\"));\n                    else\n                        ldbLog(sdsnew(\"No breakpoint in the specified line.\"));\n                }\n            }\n        }\n    }\n}\n\n/* Implements the Lua debugger \"eval\" command. It just compiles the user\n * passed fragment of code and executes it, showing the result left on\n * the stack. */\nvoid ldbEval(lua_State *lua, sds *argv, int argc) {\n    /* Glue the script together if it is composed of multiple arguments. */\n    sds code = sdsjoinsds(argv+1,argc-1,\" \",1);\n    sds expr = sdscatsds(sdsnew(\"return \"),code);\n\n    /* Try to compile it as an expression, prepending \"return \". */\n    if (luaL_loadbuffer(lua,expr,sdslen(expr),\"@ldb_eval\")) {\n        lua_pop(lua,1);\n        /* Failed? Try as a statement. */\n        if (luaL_loadbuffer(lua,code,sdslen(code),\"@ldb_eval\")) {\n            ldbLog(sdscatfmt(sdsempty(),\"<error> %s\",lua_tostring(lua,-1)));\n            lua_pop(lua,1);\n            sdsfree(code);\n            return;\n        }\n    }\n\n    /* Call it. */\n    sdsfree(code);\n    sdsfree(expr);\n    if (lua_pcall(lua,0,1,0)) {\n        ldbLog(sdscatfmt(sdsempty(),\"<error> %s\",lua_tostring(lua,-1)));\n        lua_pop(lua,1);\n        return;\n    }\n    ldbLogStackValue(lua,\"<retval> \");\n    lua_pop(lua,1);\n}\n\n/* Implement the debugger \"redis\" command. We use a trick in order to make\n * the implementation very simple: we just call the Lua redis.call() command\n * implementation, with ldb.step enabled, so as a side effect the Redis command\n * and its reply are logged. */\nvoid ldbRedis(lua_State *lua, sds *argv, int argc) {\n    int j, saved_rc = server.lua_replicate_commands;\n\n    lua_getglobal(lua,\"redis\");\n    lua_pushstring(lua,\"call\");\n    lua_gettable(lua,-2);       /* Stack: redis, redis.call */\n    for (j = 1; j < argc; j++)\n        lua_pushlstring(lua,argv[j],sdslen(argv[j]));\n    ldb.step = 1;               /* Force redis.call() to log. */\n    server.lua_replicate_commands = 1;\n    lua_pcall(lua,argc-1,1,0);  /* Stack: redis, result */\n    ldb.step = 0;               /* Disable logging. */\n    server.lua_replicate_commands = saved_rc;\n    lua_pop(lua,2);             /* Discard the result and clean the stack. */\n}\n\n/* Implements \"trace\" command of the Lua debugger. It just prints a backtrace\n * querying Lua starting from the current callframe back to the outer one. */\nvoid ldbTrace(lua_State *lua) {\n    lua_Debug ar;\n    int level = 0;\n\n    while(lua_getstack(lua,level,&ar)) {\n        lua_getinfo(lua,\"Snl\",&ar);\n        if(strstr(ar.short_src,\"user_script\") != NULL) {\n            ldbLog(sdscatprintf(sdsempty(),\"%s %s:\",\n                (level == 0) ? \"In\" : \"From\",\n                ar.name ? ar.name : \"top level\"));\n            ldbLogSourceLine(ar.currentline);\n        }\n        level++;\n    }\n    if (level == 0) {\n        ldbLog(sdsnew(\"<error> Can't retrieve Lua stack.\"));\n    }\n}\n\n/* Impleemnts the debugger \"maxlen\" command. It just queries or sets the\n * ldb.maxlen variable. */\nvoid ldbMaxlen(sds *argv, int argc) {\n    if (argc == 2) {\n        int newval = atoi(argv[1]);\n        ldb.maxlen_hint_sent = 1; /* User knows about this command. */\n        if (newval != 0 && newval <= 60) newval = 60;\n        ldb.maxlen = newval;\n    }\n    if (ldb.maxlen) {\n        ldbLog(sdscatprintf(sdsempty(),\"<value> replies are truncated at %d bytes.\",(int)ldb.maxlen));\n    } else {\n        ldbLog(sdscatprintf(sdsempty(),\"<value> replies are unlimited.\"));\n    }\n}\n\n/* Read debugging commands from client.\n * Return C_OK if the debugging session is continuing, otherwise\n * C_ERR if the client closed the connection or is timing out. */\nint ldbRepl(lua_State *lua) {\n    sds *argv;\n    int argc;\n\n    /* We continue processing commands until a command that should return\n     * to the Lua interpreter is found. */\n    while(1) {\n        while((argv = ldbReplParseCommand(&argc)) == NULL) {\n            char buf[1024];\n            int nread = read(ldb.fd,buf,sizeof(buf));\n            if (nread <= 0) {\n                /* Make sure the script runs without user input since the\n                 * client is no longer connected. */\n                ldb.step = 0;\n                ldb.bpcount = 0;\n                return C_ERR;\n            }\n            ldb.cbuf = sdscatlen(ldb.cbuf,buf,nread);\n        }\n\n        /* Flush the old buffer. */\n        sdsfree(ldb.cbuf);\n        ldb.cbuf = sdsempty();\n\n        /* Execute the command. */\n        if (!strcasecmp(argv[0],\"h\") || !strcasecmp(argv[0],\"help\")) {\nldbLog(sdsnew(\"Redis Lua debugger help:\"));\nldbLog(sdsnew(\"[h]elp               Show this help.\"));\nldbLog(sdsnew(\"[s]tep               Run current line and stop again.\"));\nldbLog(sdsnew(\"[n]ext               Alias for step.\"));\nldbLog(sdsnew(\"[c]continue          Run till next breakpoint.\"));\nldbLog(sdsnew(\"[l]list              List source code around current line.\"));\nldbLog(sdsnew(\"[l]list [line]       List source code around [line].\"));\nldbLog(sdsnew(\"                     line = 0 means: current position.\"));\nldbLog(sdsnew(\"[l]list [line] [ctx] In this form [ctx] specifies how many lines\"));\nldbLog(sdsnew(\"                     to show before/after [line].\"));\nldbLog(sdsnew(\"[w]hole              List all source code. Alias for 'list 1 1000000'.\"));\nldbLog(sdsnew(\"[p]rint              Show all the local variables.\"));\nldbLog(sdsnew(\"[p]rint <var>        Show the value of the specified variable.\"));\nldbLog(sdsnew(\"                     Can also show global vars KEYS and ARGV.\"));\nldbLog(sdsnew(\"[b]reak              Show all breakpoints.\"));\nldbLog(sdsnew(\"[b]reak <line>       Add a breakpoint to the specified line.\"));\nldbLog(sdsnew(\"[b]reak -<line>      Remove breakpoint from the specified line.\"));\nldbLog(sdsnew(\"[b]reak 0            Remove all breakpoints.\"));\nldbLog(sdsnew(\"[t]race              Show a backtrace.\"));\nldbLog(sdsnew(\"[e]eval <code>       Execute some Lua code (in a different callframe).\"));\nldbLog(sdsnew(\"[r]edis <cmd>        Execute a Redis command.\"));\nldbLog(sdsnew(\"[m]axlen [len]       Trim logged Redis replies and Lua var dumps to len.\"));\nldbLog(sdsnew(\"                     Specifying zero as <len> means unlimited.\"));\nldbLog(sdsnew(\"[a]abort             Stop the execution of the script. In sync\"));\nldbLog(sdsnew(\"                     mode dataset changes will be retained.\"));\nldbLog(sdsnew(\"\"));\nldbLog(sdsnew(\"Debugger functions you can call from Lua scripts:\"));\nldbLog(sdsnew(\"redis.debug()        Produce logs in the debugger console.\"));\nldbLog(sdsnew(\"redis.breakpoint()   Stop execution like if there was a breakpoing.\"));\nldbLog(sdsnew(\"                     in the next line of code.\"));\n            ldbSendLogs();\n        } else if (!strcasecmp(argv[0],\"s\") || !strcasecmp(argv[0],\"step\") ||\n                   !strcasecmp(argv[0],\"n\") || !strcasecmp(argv[0],\"next\")) {\n            ldb.step = 1;\n            break;\n        } else if (!strcasecmp(argv[0],\"c\") || !strcasecmp(argv[0],\"continue\")){\n            break;\n        } else if (!strcasecmp(argv[0],\"t\") || !strcasecmp(argv[0],\"trace\")) {\n            ldbTrace(lua);\n            ldbSendLogs();\n        } else if (!strcasecmp(argv[0],\"m\") || !strcasecmp(argv[0],\"maxlen\")) {\n            ldbMaxlen(argv,argc);\n            ldbSendLogs();\n        } else if (!strcasecmp(argv[0],\"b\") || !strcasecmp(argv[0],\"break\")) {\n            ldbBreak(argv,argc);\n            ldbSendLogs();\n        } else if (!strcasecmp(argv[0],\"e\") || !strcasecmp(argv[0],\"eval\")) {\n            ldbEval(lua,argv,argc);\n            ldbSendLogs();\n        } else if (!strcasecmp(argv[0],\"a\") || !strcasecmp(argv[0],\"abort\")) {\n            lua_pushstring(lua, \"script aborted for user request\");\n            lua_error(lua);\n        } else if (argc > 1 &&\n                   (!strcasecmp(argv[0],\"r\") || !strcasecmp(argv[0],\"redis\"))) {\n            ldbRedis(lua,argv,argc);\n            ldbSendLogs();\n        } else if ((!strcasecmp(argv[0],\"p\") || !strcasecmp(argv[0],\"print\"))) {\n            if (argc == 2)\n                ldbPrint(lua,argv[1]);\n            else\n                ldbPrintAll(lua);\n            ldbSendLogs();\n        } else if (!strcasecmp(argv[0],\"l\") || !strcasecmp(argv[0],\"list\")){\n            int around = ldb.currentline, ctx = 5;\n            if (argc > 1) {\n                int num = atoi(argv[1]);\n                if (num > 0) around = num;\n            }\n            if (argc > 2) ctx = atoi(argv[2]);\n            ldbList(around,ctx);\n            ldbSendLogs();\n        } else if (!strcasecmp(argv[0],\"w\") || !strcasecmp(argv[0],\"whole\")){\n            ldbList(1,1000000);\n            ldbSendLogs();\n        } else {\n            ldbLog(sdsnew(\"<error> Unknown Redis Lua debugger command or \"\n                          \"wrong number of arguments.\"));\n            ldbSendLogs();\n        }\n\n        /* Free the command vector. */\n        sdsfreesplitres(argv,argc);\n    }\n\n    /* Free the current command argv if we break inside the while loop. */\n    sdsfreesplitres(argv,argc);\n    return C_OK;\n}\n\n/* This is the core of our Lua debugger, called each time Lua is about\n * to start executing a new line. */\nvoid luaLdbLineHook(lua_State *lua, lua_Debug *ar) {\n    lua_getstack(lua,0,ar);\n    lua_getinfo(lua,\"Sl\",ar);\n    ldb.currentline = ar->currentline;\n\n    int bp = ldbIsBreakpoint(ldb.currentline) || ldb.luabp;\n    int timeout = 0;\n\n    /* Events outside our script are not interesting. */\n    if(strstr(ar->short_src,\"user_script\") == NULL) return;\n\n    /* Check if a timeout occurred. */\n    if (ar->event == LUA_HOOKCOUNT && ldb.step == 0 && bp == 0) {\n        mstime_t elapsed = mstime() - server.lua_time_start;\n        mstime_t timelimit = server.lua_time_limit ?\n                             server.lua_time_limit : 5000;\n        if (elapsed >= timelimit) {\n            timeout = 1;\n            ldb.step = 1;\n        } else {\n            return; /* No timeout, ignore the COUNT event. */\n        }\n    }\n\n    if (ldb.step || bp) {\n        char *reason = \"step over\";\n        if (bp) reason = ldb.luabp ? \"redis.breakpoint() called\" :\n                                     \"break point\";\n        else if (timeout) reason = \"timeout reached, infinite loop?\";\n        ldb.step = 0;\n        ldb.luabp = 0;\n        ldbLog(sdscatprintf(sdsempty(),\n            \"* Stopped at %d, stop reason = %s\",\n            ldb.currentline, reason));\n        ldbLogSourceLine(ldb.currentline);\n        ldbSendLogs();\n        if (ldbRepl(lua) == C_ERR && timeout) {\n            /* If the client closed the connection and we have a timeout\n             * connection, let's kill the script otherwise the process\n             * will remain blocked indefinitely. */\n            lua_pushstring(lua, \"timeout during Lua debugging with client closing connection\");\n            lua_error(lua);\n        }\n        server.lua_time_start = mstime();\n    }\n}\n\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/src/sds.c",
    "content": "/* SDSLib 2.0 -- A C dynamic strings library\n *\n * Copyright (c) 2006-2015, Salvatore Sanfilippo <antirez at gmail dot com>\n * Copyright (c) 2015, Oran Agra\n * Copyright (c) 2015, Redis Labs, Inc\n * All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions are met:\n *\n *   * Redistributions of source code must retain the above copyright notice,\n *     this list of conditions and the following disclaimer.\n *   * Redistributions in binary form must reproduce the above copyright\n *     notice, this list of conditions and the following disclaimer in the\n *     documentation and/or other materials provided with the distribution.\n *   * Neither the name of Redis nor the names of its contributors may be used\n *     to endorse or promote products derived from this software without\n *     specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\"\n * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\n * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE\n * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR\n * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF\n * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS\n * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN\n * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)\n * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE\n * POSSIBILITY OF SUCH DAMAGE.\n */\n\n#include <stdio.h>\n#include <stdlib.h>\n#include <string.h>\n#include <ctype.h>\n#include <assert.h>\n#include \"sds.h\"\n#include \"sdsalloc.h\"\n\nstatic inline int sdsHdrSize(char type) {\n    switch(type&SDS_TYPE_MASK) {\n        case SDS_TYPE_5:\n            return sizeof(struct sdshdr5);\n        case SDS_TYPE_8:\n            return sizeof(struct sdshdr8);\n        case SDS_TYPE_16:\n            return sizeof(struct sdshdr16);\n        case SDS_TYPE_32:\n            return sizeof(struct sdshdr32);\n        case SDS_TYPE_64:\n            return sizeof(struct sdshdr64);\n    }\n    return 0;\n}\n\nstatic inline char sdsReqType(size_t string_size) {\n    if (string_size < 1<<5)\n        return SDS_TYPE_5;\n    if (string_size < 1<<8)\n        return SDS_TYPE_8;\n    if (string_size < 1<<16)\n        return SDS_TYPE_16;\n    if (string_size < 1ll<<32)\n        return SDS_TYPE_32;\n    return SDS_TYPE_64;\n}\n\n/* Create a new sds string with the content specified by the 'init' pointer\n * and 'initlen'.\n * If NULL is used for 'init' the string is initialized with zero bytes.\n *\n * The string is always null-termined (all the sds strings are, always) so\n * even if you create an sds string with:\n *\n * mystring = sdsnewlen(\"abc\",3);\n *\n * You can print the string with printf() as there is an implicit \\0 at the\n * end of the string. However the string is binary safe and can contain\n * \\0 characters in the middle, as the length is stored in the sds header. */\nsds sdsnewlen(const void *init, size_t initlen) {\n    void *sh;\n    sds s;\n    char type = sdsReqType(initlen);\n    /* Empty strings are usually created in order to append. Use type 8\n     * since type 5 is not good at this. */\n    if (type == SDS_TYPE_5 && initlen == 0) type = SDS_TYPE_8;\n    int hdrlen = sdsHdrSize(type);\n    unsigned char *fp; /* flags pointer. */\n\n    sh = s_malloc(hdrlen+initlen+1);\n    if (!init)\n        memset(sh, 0, hdrlen+initlen+1);\n    if (sh == NULL) return NULL;\n    s = (char*)sh+hdrlen;\n    fp = ((unsigned char*)s)-1;\n    switch(type) {\n        case SDS_TYPE_5: {\n            *fp = type | (initlen << SDS_TYPE_BITS);\n            break;\n        }\n        case SDS_TYPE_8: {\n            SDS_HDR_VAR(8,s);\n            sh->len = initlen;\n            sh->alloc = initlen;\n            *fp = type;\n            break;\n        }\n        case SDS_TYPE_16: {\n            SDS_HDR_VAR(16,s);\n            sh->len = initlen;\n            sh->alloc = initlen;\n            *fp = type;\n            break;\n        }\n        case SDS_TYPE_32: {\n            SDS_HDR_VAR(32,s);\n            sh->len = initlen;\n            sh->alloc = initlen;\n            *fp = type;\n            break;\n        }\n        case SDS_TYPE_64: {\n            SDS_HDR_VAR(64,s);\n            sh->len = initlen;\n            sh->alloc = initlen;\n            *fp = type;\n            break;\n        }\n    }\n    if (initlen && init)\n        memcpy(s, init, initlen);\n    s[initlen] = '\\0';\n    return s;\n}\n\n/* Create an empty (zero length) sds string. Even in this case the string\n * always has an implicit null term. */\nsds sdsempty(void) {\n    return sdsnewlen(\"\",0);\n}\n\n/* Create a new sds string starting from a null terminated C string. */\nsds sdsnew(const char *init) {\n    size_t initlen = (init == NULL) ? 0 : strlen(init);\n    return sdsnewlen(init, initlen);\n}\n\n/* Duplicate an sds string. */\nsds sdsdup(const sds s) {\n    return sdsnewlen(s, sdslen(s));\n}\n\n/* Free an sds string. No operation is performed if 's' is NULL. */\nvoid sdsfree(sds s) {\n    if (s == NULL) return;\n    s_free((char*)s-sdsHdrSize(s[-1]));\n}\n\n/* Set the sds string length to the length as obtained with strlen(), so\n * considering as content only up to the first null term character.\n *\n * This function is useful when the sds string is hacked manually in some\n * way, like in the following example:\n *\n * s = sdsnew(\"foobar\");\n * s[2] = '\\0';\n * sdsupdatelen(s);\n * printf(\"%d\\n\", sdslen(s));\n *\n * The output will be \"2\", but if we comment out the call to sdsupdatelen()\n * the output will be \"6\" as the string was modified but the logical length\n * remains 6 bytes. */\nvoid sdsupdatelen(sds s) {\n    int reallen = strlen(s);\n    sdssetlen(s, reallen);\n}\n\n/* Modify an sds string in-place to make it empty (zero length).\n * However all the existing buffer is not discarded but set as free space\n * so that next append operations will not require allocations up to the\n * number of bytes previously available. */\nvoid sdsclear(sds s) {\n    sdssetlen(s, 0);\n    s[0] = '\\0';\n}\n\n/* Enlarge the free space at the end of the sds string so that the caller\n * is sure that after calling this function can overwrite up to addlen\n * bytes after the end of the string, plus one more byte for nul term.\n *\n * Note: this does not change the *length* of the sds string as returned\n * by sdslen(), but only the free buffer space we have. */\nsds sdsMakeRoomFor(sds s, size_t addlen) {\n    void *sh, *newsh;\n    size_t avail = sdsavail(s);\n    size_t len, newlen;\n    char type, oldtype = s[-1] & SDS_TYPE_MASK;\n    int hdrlen;\n\n    /* Return ASAP if there is enough space left. */\n    if (avail >= addlen) return s;\n\n    len = sdslen(s);\n    sh = (char*)s-sdsHdrSize(oldtype);\n    newlen = (len+addlen);\n    if (newlen < SDS_MAX_PREALLOC)\n        newlen *= 2;\n    else\n        newlen += SDS_MAX_PREALLOC;\n\n    type = sdsReqType(newlen);\n\n    /* Don't use type 5: the user is appending to the string and type 5 is\n     * not able to remember empty space, so sdsMakeRoomFor() must be called\n     * at every appending operation. */\n    if (type == SDS_TYPE_5) type = SDS_TYPE_8;\n\n    hdrlen = sdsHdrSize(type);\n    if (oldtype==type) {\n        newsh = s_realloc(sh, hdrlen+newlen+1);\n        if (newsh == NULL) return NULL;\n        s = (char*)newsh+hdrlen;\n    } else {\n        /* Since the header size changes, need to move the string forward,\n         * and can't use realloc */\n        newsh = s_malloc(hdrlen+newlen+1);\n        if (newsh == NULL) return NULL;\n        memcpy((char*)newsh+hdrlen, s, len+1);\n        s_free(sh);\n        s = (char*)newsh+hdrlen;\n        s[-1] = type;\n        sdssetlen(s, len);\n    }\n    sdssetalloc(s, newlen);\n    return s;\n}\n\n/* Reallocate the sds string so that it has no free space at the end. The\n * contained string remains not altered, but next concatenation operations\n * will require a reallocation.\n *\n * After the call, the passed sds string is no longer valid and all the\n * references must be substituted with the new pointer returned by the call. */\nsds sdsRemoveFreeSpace(sds s) {\n    void *sh, *newsh;\n    char type, oldtype = s[-1] & SDS_TYPE_MASK;\n    int hdrlen;\n    size_t len = sdslen(s);\n    sh = (char*)s-sdsHdrSize(oldtype);\n\n    type = sdsReqType(len);\n    hdrlen = sdsHdrSize(type);\n    if (oldtype==type) {\n        newsh = s_realloc(sh, hdrlen+len+1);\n        if (newsh == NULL) return NULL;\n        s = (char*)newsh+hdrlen;\n    } else {\n        newsh = s_malloc(hdrlen+len+1);\n        if (newsh == NULL) return NULL;\n        memcpy((char*)newsh+hdrlen, s, len+1);\n        s_free(sh);\n        s = (char*)newsh+hdrlen;\n        s[-1] = type;\n        sdssetlen(s, len);\n    }\n    sdssetalloc(s, len);\n    return s;\n}\n\n/* Return the total size of the allocation of the specifed sds string,\n * including:\n * 1) The sds header before the pointer.\n * 2) The string.\n * 3) The free buffer at the end if any.\n * 4) The implicit null term.\n */\nsize_t sdsAllocSize(sds s) {\n    size_t alloc = sdsalloc(s);\n    return sdsHdrSize(s[-1])+alloc+1;\n}\n\n/* Return the pointer of the actual SDS allocation (normally SDS strings\n * are referenced by the start of the string buffer). */\nvoid *sdsAllocPtr(sds s) {\n    return (void*) (s-sdsHdrSize(s[-1]));\n}\n\n/* Increment the sds length and decrements the left free space at the\n * end of the string according to 'incr'. Also set the null term\n * in the new end of the string.\n *\n * This function is used in order to fix the string length after the\n * user calls sdsMakeRoomFor(), writes something after the end of\n * the current string, and finally needs to set the new length.\n *\n * Note: it is possible to use a negative increment in order to\n * right-trim the string.\n *\n * Usage example:\n *\n * Using sdsIncrLen() and sdsMakeRoomFor() it is possible to mount the\n * following schema, to cat bytes coming from the kernel to the end of an\n * sds string without copying into an intermediate buffer:\n *\n * oldlen = sdslen(s);\n * s = sdsMakeRoomFor(s, BUFFER_SIZE);\n * nread = read(fd, s+oldlen, BUFFER_SIZE);\n * ... check for nread <= 0 and handle it ...\n * sdsIncrLen(s, nread);\n */\nvoid sdsIncrLen(sds s, int incr) {\n    unsigned char flags = s[-1];\n    size_t len;\n    switch(flags&SDS_TYPE_MASK) {\n        case SDS_TYPE_5: {\n            unsigned char *fp = ((unsigned char*)s)-1;\n            unsigned char oldlen = SDS_TYPE_5_LEN(flags);\n            assert((incr > 0 && oldlen+incr < 32) || (incr < 0 && oldlen >= (unsigned int)(-incr)));\n            *fp = SDS_TYPE_5 | ((oldlen+incr) << SDS_TYPE_BITS);\n            len = oldlen+incr;\n            break;\n        }\n        case SDS_TYPE_8: {\n            SDS_HDR_VAR(8,s);\n            assert((incr >= 0 && sh->alloc-sh->len >= incr) || (incr < 0 && sh->len >= (unsigned int)(-incr)));\n            len = (sh->len += incr);\n            break;\n        }\n        case SDS_TYPE_16: {\n            SDS_HDR_VAR(16,s);\n            assert((incr >= 0 && sh->alloc-sh->len >= incr) || (incr < 0 && sh->len >= (unsigned int)(-incr)));\n            len = (sh->len += incr);\n            break;\n        }\n        case SDS_TYPE_32: {\n            SDS_HDR_VAR(32,s);\n            assert((incr >= 0 && sh->alloc-sh->len >= (unsigned int)incr) || (incr < 0 && sh->len >= (unsigned int)(-incr)));\n            len = (sh->len += incr);\n            break;\n        }\n        case SDS_TYPE_64: {\n            SDS_HDR_VAR(64,s);\n            assert((incr >= 0 && sh->alloc-sh->len >= (uint64_t)incr) || (incr < 0 && sh->len >= (uint64_t)(-incr)));\n            len = (sh->len += incr);\n            break;\n        }\n        default: len = 0; /* Just to avoid compilation warnings. */\n    }\n    s[len] = '\\0';\n}\n\n/* Grow the sds to have the specified length. Bytes that were not part of\n * the original length of the sds will be set to zero.\n *\n * if the specified length is smaller than the current length, no operation\n * is performed. */\nsds sdsgrowzero(sds s, size_t len) {\n    size_t curlen = sdslen(s);\n\n    if (len <= curlen) return s;\n    s = sdsMakeRoomFor(s,len-curlen);\n    if (s == NULL) return NULL;\n\n    /* Make sure added region doesn't contain garbage */\n    memset(s+curlen,0,(len-curlen+1)); /* also set trailing \\0 byte */\n    sdssetlen(s, len);\n    return s;\n}\n\n/* Append the specified binary-safe string pointed by 't' of 'len' bytes to the\n * end of the specified sds string 's'.\n *\n * After the call, the passed sds string is no longer valid and all the\n * references must be substituted with the new pointer returned by the call. */\nsds sdscatlen(sds s, const void *t, size_t len) {\n    size_t curlen = sdslen(s);\n\n    s = sdsMakeRoomFor(s,len);\n    if (s == NULL) return NULL;\n    memcpy(s+curlen, t, len);\n    sdssetlen(s, curlen+len);\n    s[curlen+len] = '\\0';\n    return s;\n}\n\n/* Append the specified null termianted C string to the sds string 's'.\n *\n * After the call, the passed sds string is no longer valid and all the\n * references must be substituted with the new pointer returned by the call. */\nsds sdscat(sds s, const char *t) {\n    return sdscatlen(s, t, strlen(t));\n}\n\n/* Append the specified sds 't' to the existing sds 's'.\n *\n * After the call, the modified sds string is no longer valid and all the\n * references must be substituted with the new pointer returned by the call. */\nsds sdscatsds(sds s, const sds t) {\n    return sdscatlen(s, t, sdslen(t));\n}\n\n/* Destructively modify the sds string 's' to hold the specified binary\n * safe string pointed by 't' of length 'len' bytes. */\nsds sdscpylen(sds s, const char *t, size_t len) {\n    if (sdsalloc(s) < len) {\n        s = sdsMakeRoomFor(s,len-sdslen(s));\n        if (s == NULL) return NULL;\n    }\n    memcpy(s, t, len);\n    s[len] = '\\0';\n    sdssetlen(s, len);\n    return s;\n}\n\n/* Like sdscpylen() but 't' must be a null-termined string so that the length\n * of the string is obtained with strlen(). */\nsds sdscpy(sds s, const char *t) {\n    return sdscpylen(s, t, strlen(t));\n}\n\n/* Helper for sdscatlonglong() doing the actual number -> string\n * conversion. 's' must point to a string with room for at least\n * SDS_LLSTR_SIZE bytes.\n *\n * The function returns the length of the null-terminated string\n * representation stored at 's'. */\n#define SDS_LLSTR_SIZE 21\nint sdsll2str(char *s, long long value) {\n    char *p, aux;\n    unsigned long long v;\n    size_t l;\n\n    /* Generate the string representation, this method produces\n     * an reversed string. */\n    v = (value < 0) ? -value : value;\n    p = s;\n    do {\n        *p++ = '0'+(v%10);\n        v /= 10;\n    } while(v);\n    if (value < 0) *p++ = '-';\n\n    /* Compute length and add null term. */\n    l = p-s;\n    *p = '\\0';\n\n    /* Reverse the string. */\n    p--;\n    while(s < p) {\n        aux = *s;\n        *s = *p;\n        *p = aux;\n        s++;\n        p--;\n    }\n    return l;\n}\n\n/* Identical sdsll2str(), but for unsigned long long type. */\nint sdsull2str(char *s, unsigned long long v) {\n    char *p, aux;\n    size_t l;\n\n    /* Generate the string representation, this method produces\n     * an reversed string. */\n    p = s;\n    do {\n        *p++ = '0'+(v%10);\n        v /= 10;\n    } while(v);\n\n    /* Compute length and add null term. */\n    l = p-s;\n    *p = '\\0';\n\n    /* Reverse the string. */\n    p--;\n    while(s < p) {\n        aux = *s;\n        *s = *p;\n        *p = aux;\n        s++;\n        p--;\n    }\n    return l;\n}\n\n/* Create an sds string from a long long value. It is much faster than:\n *\n * sdscatprintf(sdsempty(),\"%lld\\n\", value);\n */\nsds sdsfromlonglong(long long value) {\n    char buf[SDS_LLSTR_SIZE];\n    int len = sdsll2str(buf,value);\n\n    return sdsnewlen(buf,len);\n}\n\n/* Like sdscatprintf() but gets va_list instead of being variadic. */\nsds sdscatvprintf(sds s, const char *fmt, va_list ap) {\n    va_list cpy;\n    char staticbuf[1024], *buf = staticbuf, *t;\n    size_t buflen = strlen(fmt)*2;\n\n    /* We try to start using a static buffer for speed.\n     * If not possible we revert to heap allocation. */\n    if (buflen > sizeof(staticbuf)) {\n        buf = s_malloc(buflen);\n        if (buf == NULL) return NULL;\n    } else {\n        buflen = sizeof(staticbuf);\n    }\n\n    /* Try with buffers two times bigger every time we fail to\n     * fit the string in the current buffer size. */\n    while(1) {\n        buf[buflen-2] = '\\0';\n        va_copy(cpy,ap);\n        vsnprintf(buf, buflen, fmt, cpy);\n        va_end(cpy);\n        if (buf[buflen-2] != '\\0') {\n            if (buf != staticbuf) s_free(buf);\n            buflen *= 2;\n            buf = s_malloc(buflen);\n            if (buf == NULL) return NULL;\n            continue;\n        }\n        break;\n    }\n\n    /* Finally concat the obtained string to the SDS string and return it. */\n    t = sdscat(s, buf);\n    if (buf != staticbuf) s_free(buf);\n    return t;\n}\n\n/* Append to the sds string 's' a string obtained using printf-alike format\n * specifier.\n *\n * After the call, the modified sds string is no longer valid and all the\n * references must be substituted with the new pointer returned by the call.\n *\n * Example:\n *\n * s = sdsnew(\"Sum is: \");\n * s = sdscatprintf(s,\"%d+%d = %d\",a,b,a+b).\n *\n * Often you need to create a string from scratch with the printf-alike\n * format. When this is the need, just use sdsempty() as the target string:\n *\n * s = sdscatprintf(sdsempty(), \"... your format ...\", args);\n */\nsds sdscatprintf(sds s, const char *fmt, ...) {\n    va_list ap;\n    char *t;\n    va_start(ap, fmt);\n    t = sdscatvprintf(s,fmt,ap);\n    va_end(ap);\n    return t;\n}\n\n/* This function is similar to sdscatprintf, but much faster as it does\n * not rely on sprintf() family functions implemented by the libc that\n * are often very slow. Moreover directly handling the sds string as\n * new data is concatenated provides a performance improvement.\n *\n * However this function only handles an incompatible subset of printf-alike\n * format specifiers:\n *\n * %s - C String\n * %S - SDS string\n * %i - signed int\n * %I - 64 bit signed integer (long long, int64_t)\n * %u - unsigned int\n * %U - 64 bit unsigned integer (unsigned long long, uint64_t)\n * %% - Verbatim \"%\" character.\n */\nsds sdscatfmt(sds s, char const *fmt, ...) {\n    size_t initlen = sdslen(s);\n    const char *f = fmt;\n    int i;\n    va_list ap;\n\n    va_start(ap,fmt);\n    f = fmt;    /* Next format specifier byte to process. */\n    i = initlen; /* Position of the next byte to write to dest str. */\n    while(*f) {\n        char next, *str;\n        size_t l;\n        long long num;\n        unsigned long long unum;\n\n        /* Make sure there is always space for at least 1 char. */\n        if (sdsavail(s)==0) {\n            s = sdsMakeRoomFor(s,1);\n        }\n\n        switch(*f) {\n        case '%':\n            next = *(f+1);\n            f++;\n            switch(next) {\n            case 's':\n            case 'S':\n                str = va_arg(ap,char*);\n                l = (next == 's') ? strlen(str) : sdslen(str);\n                if (sdsavail(s) < l) {\n                    s = sdsMakeRoomFor(s,l);\n                }\n                memcpy(s+i,str,l);\n                sdsinclen(s,l);\n                i += l;\n                break;\n            case 'i':\n            case 'I':\n                if (next == 'i')\n                    num = va_arg(ap,int);\n                else\n                    num = va_arg(ap,long long);\n                {\n                    char buf[SDS_LLSTR_SIZE];\n                    l = sdsll2str(buf,num);\n                    if (sdsavail(s) < l) {\n                        s = sdsMakeRoomFor(s,l);\n                    }\n                    memcpy(s+i,buf,l);\n                    sdsinclen(s,l);\n                    i += l;\n                }\n                break;\n            case 'u':\n            case 'U':\n                if (next == 'u')\n                    unum = va_arg(ap,unsigned int);\n                else\n                    unum = va_arg(ap,unsigned long long);\n                {\n                    char buf[SDS_LLSTR_SIZE];\n                    l = sdsull2str(buf,unum);\n                    if (sdsavail(s) < l) {\n                        s = sdsMakeRoomFor(s,l);\n                    }\n                    memcpy(s+i,buf,l);\n                    sdsinclen(s,l);\n                    i += l;\n                }\n                break;\n            default: /* Handle %% and generally %<unknown>. */\n                s[i++] = next;\n                sdsinclen(s,1);\n                break;\n            }\n            break;\n        default:\n            s[i++] = *f;\n            sdsinclen(s,1);\n            break;\n        }\n        f++;\n    }\n    va_end(ap);\n\n    /* Add null-term */\n    s[i] = '\\0';\n    return s;\n}\n\n/* Remove the part of the string from left and from right composed just of\n * contiguous characters found in 'cset', that is a null terminted C string.\n *\n * After the call, the modified sds string is no longer valid and all the\n * references must be substituted with the new pointer returned by the call.\n *\n * Example:\n *\n * s = sdsnew(\"AA...AA.a.aa.aHelloWorld     :::\");\n * s = sdstrim(s,\"Aa. :\");\n * printf(\"%s\\n\", s);\n *\n * Output will be just \"Hello World\".\n */\nsds sdstrim(sds s, const char *cset) {\n    char *start, *end, *sp, *ep;\n    size_t len;\n\n    sp = start = s;\n    ep = end = s+sdslen(s)-1;\n    while(sp <= end && strchr(cset, *sp)) sp++;\n    while(ep > sp && strchr(cset, *ep)) ep--;\n    len = (sp > ep) ? 0 : ((ep-sp)+1);\n    if (s != sp) memmove(s, sp, len);\n    s[len] = '\\0';\n    sdssetlen(s,len);\n    return s;\n}\n\n/* Turn the string into a smaller (or equal) string containing only the\n * substring specified by the 'start' and 'end' indexes.\n *\n * start and end can be negative, where -1 means the last character of the\n * string, -2 the penultimate character, and so forth.\n *\n * The interval is inclusive, so the start and end characters will be part\n * of the resulting string.\n *\n * The string is modified in-place.\n *\n * Example:\n *\n * s = sdsnew(\"Hello World\");\n * sdsrange(s,1,-1); => \"ello World\"\n */\nvoid sdsrange(sds s, int start, int end) {\n    size_t newlen, len = sdslen(s);\n\n    if (len == 0) return;\n    if (start < 0) {\n        start = len+start;\n        if (start < 0) start = 0;\n    }\n    if (end < 0) {\n        end = len+end;\n        if (end < 0) end = 0;\n    }\n    newlen = (start > end) ? 0 : (end-start)+1;\n    if (newlen != 0) {\n        if (start >= (signed)len) {\n            newlen = 0;\n        } else if (end >= (signed)len) {\n            end = len-1;\n            newlen = (start > end) ? 0 : (end-start)+1;\n        }\n    } else {\n        start = 0;\n    }\n    if (start && newlen) memmove(s, s+start, newlen);\n    s[newlen] = 0;\n    sdssetlen(s,newlen);\n}\n\n/* Apply tolower() to every character of the sds string 's'. */\nvoid sdstolower(sds s) {\n    int len = sdslen(s), j;\n\n    for (j = 0; j < len; j++) s[j] = tolower(s[j]);\n}\n\n/* Apply toupper() to every character of the sds string 's'. */\nvoid sdstoupper(sds s) {\n    int len = sdslen(s), j;\n\n    for (j = 0; j < len; j++) s[j] = toupper(s[j]);\n}\n\n/* Compare two sds strings s1 and s2 with memcmp().\n *\n * Return value:\n *\n *     positive if s1 > s2.\n *     negative if s1 < s2.\n *     0 if s1 and s2 are exactly the same binary string.\n *\n * If two strings share exactly the same prefix, but one of the two has\n * additional characters, the longer string is considered to be greater than\n * the smaller one. */\nint sdscmp(const sds s1, const sds s2) {\n    size_t l1, l2, minlen;\n    int cmp;\n\n    l1 = sdslen(s1);\n    l2 = sdslen(s2);\n    minlen = (l1 < l2) ? l1 : l2;\n    cmp = memcmp(s1,s2,minlen);\n    if (cmp == 0) return l1-l2;\n    return cmp;\n}\n\n/* Split 's' with separator in 'sep'. An array\n * of sds strings is returned. *count will be set\n * by reference to the number of tokens returned.\n *\n * On out of memory, zero length string, zero length\n * separator, NULL is returned.\n *\n * Note that 'sep' is able to split a string using\n * a multi-character separator. For example\n * sdssplit(\"foo_-_bar\",\"_-_\"); will return two\n * elements \"foo\" and \"bar\".\n *\n * This version of the function is binary-safe but\n * requires length arguments. sdssplit() is just the\n * same function but for zero-terminated strings.\n */\nsds *sdssplitlen(const char *s, int len, const char *sep, int seplen, int *count) {\n    int elements = 0, slots = 5, start = 0, j;\n    sds *tokens;\n\n    if (seplen < 1 || len < 0) return NULL;\n\n    tokens = s_malloc(sizeof(sds)*slots);\n    if (tokens == NULL) return NULL;\n\n    if (len == 0) {\n        *count = 0;\n        return tokens;\n    }\n    for (j = 0; j < (len-(seplen-1)); j++) {\n        /* make sure there is room for the next element and the final one */\n        if (slots < elements+2) {\n            sds *newtokens;\n\n            slots *= 2;\n            newtokens = s_realloc(tokens,sizeof(sds)*slots);\n            if (newtokens == NULL) goto cleanup;\n            tokens = newtokens;\n        }\n        /* search the separator */\n        if ((seplen == 1 && *(s+j) == sep[0]) || (memcmp(s+j,sep,seplen) == 0)) {\n            tokens[elements] = sdsnewlen(s+start,j-start);\n            if (tokens[elements] == NULL) goto cleanup;\n            elements++;\n            start = j+seplen;\n            j = j+seplen-1; /* skip the separator */\n        }\n    }\n    /* Add the final element. We are sure there is room in the tokens array. */\n    tokens[elements] = sdsnewlen(s+start,len-start);\n    if (tokens[elements] == NULL) goto cleanup;\n    elements++;\n    *count = elements;\n    return tokens;\n\ncleanup:\n    {\n        int i;\n        for (i = 0; i < elements; i++) sdsfree(tokens[i]);\n        s_free(tokens);\n        *count = 0;\n        return NULL;\n    }\n}\n\n/* Free the result returned by sdssplitlen(), or do nothing if 'tokens' is NULL. */\nvoid sdsfreesplitres(sds *tokens, int count) {\n    if (!tokens) return;\n    while(count--)\n        sdsfree(tokens[count]);\n    s_free(tokens);\n}\n\n/* Append to the sds string \"s\" an escaped string representation where\n * all the non-printable characters (tested with isprint()) are turned into\n * escapes in the form \"\\n\\r\\a....\" or \"\\x<hex-number>\".\n *\n * After the call, the modified sds string is no longer valid and all the\n * references must be substituted with the new pointer returned by the call. */\nsds sdscatrepr(sds s, const char *p, size_t len) {\n    s = sdscatlen(s,\"\\\"\",1);\n    while(len--) {\n        switch(*p) {\n        case '\\\\':\n        case '\"':\n            s = sdscatprintf(s,\"\\\\%c\",*p);\n            break;\n        case '\\n': s = sdscatlen(s,\"\\\\n\",2); break;\n        case '\\r': s = sdscatlen(s,\"\\\\r\",2); break;\n        case '\\t': s = sdscatlen(s,\"\\\\t\",2); break;\n        case '\\a': s = sdscatlen(s,\"\\\\a\",2); break;\n        case '\\b': s = sdscatlen(s,\"\\\\b\",2); break;\n        default:\n            if (isprint(*p))\n                s = sdscatprintf(s,\"%c\",*p);\n            else\n                s = sdscatprintf(s,\"\\\\x%02x\",(unsigned char)*p);\n            break;\n        }\n        p++;\n    }\n    return sdscatlen(s,\"\\\"\",1);\n}\n\n/* Helper function for sdssplitargs() that returns non zero if 'c'\n * is a valid hex digit. */\nint is_hex_digit(char c) {\n    return (c >= '0' && c <= '9') || (c >= 'a' && c <= 'f') ||\n           (c >= 'A' && c <= 'F');\n}\n\n/* Helper function for sdssplitargs() that converts a hex digit into an\n * integer from 0 to 15 */\nint hex_digit_to_int(char c) {\n    switch(c) {\n    case '0': return 0;\n    case '1': return 1;\n    case '2': return 2;\n    case '3': return 3;\n    case '4': return 4;\n    case '5': return 5;\n    case '6': return 6;\n    case '7': return 7;\n    case '8': return 8;\n    case '9': return 9;\n    case 'a': case 'A': return 10;\n    case 'b': case 'B': return 11;\n    case 'c': case 'C': return 12;\n    case 'd': case 'D': return 13;\n    case 'e': case 'E': return 14;\n    case 'f': case 'F': return 15;\n    default: return 0;\n    }\n}\n\n/* Split a line into arguments, where every argument can be in the\n * following programming-language REPL-alike form:\n *\n * foo bar \"newline are supported\\n\" and \"\\xff\\x00otherstuff\"\n *\n * The number of arguments is stored into *argc, and an array\n * of sds is returned.\n *\n * The caller should free the resulting array of sds strings with\n * sdsfreesplitres().\n *\n * Note that sdscatrepr() is able to convert back a string into\n * a quoted string in the same format sdssplitargs() is able to parse.\n *\n * The function returns the allocated tokens on success, even when the\n * input string is empty, or NULL if the input contains unbalanced\n * quotes or closed quotes followed by non space characters\n * as in: \"foo\"bar or \"foo'\n */\nsds *sdssplitargs(const char *line, int *argc) {\n    const char *p = line;\n    char *current = NULL;\n    char **vector = NULL;\n\n    *argc = 0;\n    while(1) {\n        /* skip blanks */\n        while(*p && isspace(*p)) p++;\n        if (*p) {\n            /* get a token */\n            int inq=0;  /* set to 1 if we are in \"quotes\" */\n            int insq=0; /* set to 1 if we are in 'single quotes' */\n            int done=0;\n\n            if (current == NULL) current = sdsempty();\n            while(!done) {\n                if (inq) {\n                    if (*p == '\\\\' && *(p+1) == 'x' &&\n                                             is_hex_digit(*(p+2)) &&\n                                             is_hex_digit(*(p+3)))\n                    {\n                        unsigned char byte;\n\n                        byte = (hex_digit_to_int(*(p+2))*16)+\n                                hex_digit_to_int(*(p+3));\n                        current = sdscatlen(current,(char*)&byte,1);\n                        p += 3;\n                    } else if (*p == '\\\\' && *(p+1)) {\n                        char c;\n\n                        p++;\n                        switch(*p) {\n                        case 'n': c = '\\n'; break;\n                        case 'r': c = '\\r'; break;\n                        case 't': c = '\\t'; break;\n                        case 'b': c = '\\b'; break;\n                        case 'a': c = '\\a'; break;\n                        default: c = *p; break;\n                        }\n                        current = sdscatlen(current,&c,1);\n                    } else if (*p == '\"') {\n                        /* closing quote must be followed by a space or\n                         * nothing at all. */\n                        if (*(p+1) && !isspace(*(p+1))) goto err;\n                        done=1;\n                    } else if (!*p) {\n                        /* unterminated quotes */\n                        goto err;\n                    } else {\n                        current = sdscatlen(current,p,1);\n                    }\n                } else if (insq) {\n                    if (*p == '\\\\' && *(p+1) == '\\'') {\n                        p++;\n                        current = sdscatlen(current,\"'\",1);\n                    } else if (*p == '\\'') {\n                        /* closing quote must be followed by a space or\n                         * nothing at all. */\n                        if (*(p+1) && !isspace(*(p+1))) goto err;\n                        done=1;\n                    } else if (!*p) {\n                        /* unterminated quotes */\n                        goto err;\n                    } else {\n                        current = sdscatlen(current,p,1);\n                    }\n                } else {\n                    switch(*p) {\n                    case ' ':\n                    case '\\n':\n                    case '\\r':\n                    case '\\t':\n                    case '\\0':\n                        done=1;\n                        break;\n                    case '\"':\n                        inq=1;\n                        break;\n                    case '\\'':\n                        insq=1;\n                        break;\n                    default:\n                        current = sdscatlen(current,p,1);\n                        break;\n                    }\n                }\n                if (*p) p++;\n            }\n            /* add the token to the vector */\n            vector = s_realloc(vector,((*argc)+1)*sizeof(char*));\n            vector[*argc] = current;\n            (*argc)++;\n            current = NULL;\n        } else {\n            /* Even on empty input string return something not NULL. */\n            if (vector == NULL) vector = s_malloc(sizeof(void*));\n            return vector;\n        }\n    }\n\nerr:\n    while((*argc)--)\n        sdsfree(vector[*argc]);\n    s_free(vector);\n    if (current) sdsfree(current);\n    *argc = 0;\n    return NULL;\n}\n\n/* Modify the string substituting all the occurrences of the set of\n * characters specified in the 'from' string to the corresponding character\n * in the 'to' array.\n *\n * For instance: sdsmapchars(mystring, \"ho\", \"01\", 2)\n * will have the effect of turning the string \"hello\" into \"0ell1\".\n *\n * The function returns the sds string pointer, that is always the same\n * as the input pointer since no resize is needed. */\nsds sdsmapchars(sds s, const char *from, const char *to, size_t setlen) {\n    size_t j, i, l = sdslen(s);\n\n    for (j = 0; j < l; j++) {\n        for (i = 0; i < setlen; i++) {\n            if (s[j] == from[i]) {\n                s[j] = to[i];\n                break;\n            }\n        }\n    }\n    return s;\n}\n\n/* Join an array of C strings using the specified separator (also a C string).\n * Returns the result as an sds string. */\nsds sdsjoin(char **argv, int argc, char *sep) {\n    sds join = sdsempty();\n    int j;\n\n    for (j = 0; j < argc; j++) {\n        join = sdscat(join, argv[j]);\n        if (j != argc-1) join = sdscat(join,sep);\n    }\n    return join;\n}\n\n/* Like sdsjoin, but joins an array of SDS strings. */\nsds sdsjoinsds(sds *argv, int argc, const char *sep, size_t seplen) {\n    sds join = sdsempty();\n    int j;\n\n    for (j = 0; j < argc; j++) {\n        join = sdscatsds(join, argv[j]);\n        if (j != argc-1) join = sdscatlen(join,sep,seplen);\n    }\n    return join;\n}\n\n/* Wrappers to the allocators used by SDS. Note that SDS will actually\n * just use the macros defined into sdsalloc.h in order to avoid to pay\n * the overhead of function calls. Here we define these wrappers only for\n * the programs SDS is linked to, if they want to touch the SDS internals\n * even if they use a different allocator. */\nvoid *sds_malloc(size_t size) { return s_malloc(size); }\nvoid *sds_realloc(void *ptr, size_t size) { return s_realloc(ptr,size); }\nvoid sds_free(void *ptr) { s_free(ptr); }\n\n#if defined(SDS_TEST_MAIN)\n#include <stdio.h>\n#include \"testhelp.h\"\n#include \"limits.h\"\n\n#define UNUSED(x) (void)(x)\nint sdsTest(void) {\n    {\n        sds x = sdsnew(\"foo\"), y;\n\n        test_cond(\"Create a string and obtain the length\",\n            sdslen(x) == 3 && memcmp(x,\"foo\\0\",4) == 0)\n\n        sdsfree(x);\n        x = sdsnewlen(\"foo\",2);\n        test_cond(\"Create a string with specified length\",\n            sdslen(x) == 2 && memcmp(x,\"fo\\0\",3) == 0)\n\n        x = sdscat(x,\"bar\");\n        test_cond(\"Strings concatenation\",\n            sdslen(x) == 5 && memcmp(x,\"fobar\\0\",6) == 0);\n\n        x = sdscpy(x,\"a\");\n        test_cond(\"sdscpy() against an originally longer string\",\n            sdslen(x) == 1 && memcmp(x,\"a\\0\",2) == 0)\n\n        x = sdscpy(x,\"xyzxxxxxxxxxxyyyyyyyyyykkkkkkkkkk\");\n        test_cond(\"sdscpy() against an originally shorter string\",\n            sdslen(x) == 33 &&\n            memcmp(x,\"xyzxxxxxxxxxxyyyyyyyyyykkkkkkkkkk\\0\",33) == 0)\n\n        sdsfree(x);\n        x = sdscatprintf(sdsempty(),\"%d\",123);\n        test_cond(\"sdscatprintf() seems working in the base case\",\n            sdslen(x) == 3 && memcmp(x,\"123\\0\",4) == 0)\n\n        sdsfree(x);\n        x = sdsnew(\"--\");\n        x = sdscatfmt(x, \"Hello %s World %I,%I--\", \"Hi!\", LLONG_MIN,LLONG_MAX);\n        test_cond(\"sdscatfmt() seems working in the base case\",\n            sdslen(x) == 60 &&\n            memcmp(x,\"--Hello Hi! World -9223372036854775808,\"\n                     \"9223372036854775807--\",60) == 0)\n        printf(\"[%s]\\n\",x);\n\n        sdsfree(x);\n        x = sdsnew(\"--\");\n        x = sdscatfmt(x, \"%u,%U--\", UINT_MAX, ULLONG_MAX);\n        test_cond(\"sdscatfmt() seems working with unsigned numbers\",\n            sdslen(x) == 35 &&\n            memcmp(x,\"--4294967295,18446744073709551615--\",35) == 0)\n\n        sdsfree(x);\n        x = sdsnew(\" x \");\n        sdstrim(x,\" x\");\n        test_cond(\"sdstrim() works when all chars match\",\n            sdslen(x) == 0)\n\n        sdsfree(x);\n        x = sdsnew(\" x \");\n        sdstrim(x,\" \");\n        test_cond(\"sdstrim() works when a single char remains\",\n            sdslen(x) == 1 && x[0] == 'x')\n\n        sdsfree(x);\n        x = sdsnew(\"xxciaoyyy\");\n        sdstrim(x,\"xy\");\n        test_cond(\"sdstrim() correctly trims characters\",\n            sdslen(x) == 4 && memcmp(x,\"ciao\\0\",5) == 0)\n\n        y = sdsdup(x);\n        sdsrange(y,1,1);\n        test_cond(\"sdsrange(...,1,1)\",\n            sdslen(y) == 1 && memcmp(y,\"i\\0\",2) == 0)\n\n        sdsfree(y);\n        y = sdsdup(x);\n        sdsrange(y,1,-1);\n        test_cond(\"sdsrange(...,1,-1)\",\n            sdslen(y) == 3 && memcmp(y,\"iao\\0\",4) == 0)\n\n        sdsfree(y);\n        y = sdsdup(x);\n        sdsrange(y,-2,-1);\n        test_cond(\"sdsrange(...,-2,-1)\",\n            sdslen(y) == 2 && memcmp(y,\"ao\\0\",3) == 0)\n\n        sdsfree(y);\n        y = sdsdup(x);\n        sdsrange(y,2,1);\n        test_cond(\"sdsrange(...,2,1)\",\n            sdslen(y) == 0 && memcmp(y,\"\\0\",1) == 0)\n\n        sdsfree(y);\n        y = sdsdup(x);\n        sdsrange(y,1,100);\n        test_cond(\"sdsrange(...,1,100)\",\n            sdslen(y) == 3 && memcmp(y,\"iao\\0\",4) == 0)\n\n        sdsfree(y);\n        y = sdsdup(x);\n        sdsrange(y,100,100);\n        test_cond(\"sdsrange(...,100,100)\",\n            sdslen(y) == 0 && memcmp(y,\"\\0\",1) == 0)\n\n        sdsfree(y);\n        sdsfree(x);\n        x = sdsnew(\"foo\");\n        y = sdsnew(\"foa\");\n        test_cond(\"sdscmp(foo,foa)\", sdscmp(x,y) > 0)\n\n        sdsfree(y);\n        sdsfree(x);\n        x = sdsnew(\"bar\");\n        y = sdsnew(\"bar\");\n        test_cond(\"sdscmp(bar,bar)\", sdscmp(x,y) == 0)\n\n        sdsfree(y);\n        sdsfree(x);\n        x = sdsnew(\"aar\");\n        y = sdsnew(\"bar\");\n        test_cond(\"sdscmp(bar,bar)\", sdscmp(x,y) < 0)\n\n        sdsfree(y);\n        sdsfree(x);\n        x = sdsnewlen(\"\\a\\n\\0foo\\r\",7);\n        y = sdscatrepr(sdsempty(),x,sdslen(x));\n        test_cond(\"sdscatrepr(...data...)\",\n            memcmp(y,\"\\\"\\\\a\\\\n\\\\x00foo\\\\r\\\"\",15) == 0)\n\n        {\n            unsigned int oldfree;\n            char *p;\n            int step = 10, j, i;\n\n            sdsfree(x);\n            sdsfree(y);\n            x = sdsnew(\"0\");\n            test_cond(\"sdsnew() free/len buffers\", sdslen(x) == 1 && sdsavail(x) == 0);\n\n            /* Run the test a few times in order to hit the first two\n             * SDS header types. */\n            for (i = 0; i < 10; i++) {\n                int oldlen = sdslen(x);\n                x = sdsMakeRoomFor(x,step);\n                int type = x[-1]&SDS_TYPE_MASK;\n\n                test_cond(\"sdsMakeRoomFor() len\", sdslen(x) == oldlen);\n                if (type != SDS_TYPE_5) {\n                    test_cond(\"sdsMakeRoomFor() free\", sdsavail(x) >= step);\n                    oldfree = sdsavail(x);\n                }\n                p = x+oldlen;\n                for (j = 0; j < step; j++) {\n                    p[j] = 'A'+j;\n                }\n                sdsIncrLen(x,step);\n            }\n            test_cond(\"sdsMakeRoomFor() content\",\n                memcmp(\"0ABCDEFGHIJABCDEFGHIJABCDEFGHIJABCDEFGHIJABCDEFGHIJABCDEFGHIJABCDEFGHIJABCDEFGHIJABCDEFGHIJABCDEFGHIJ\",x,101) == 0);\n            test_cond(\"sdsMakeRoomFor() final length\",sdslen(x)==101);\n\n            sdsfree(x);\n        }\n    }\n    test_report()\n    return 0;\n}\n#endif\n\n#ifdef SDS_TEST_MAIN\nint main(void) {\n    return sdsTest();\n}\n#endif\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/src/sds.h",
    "content": "/* SDSLib 2.0 -- A C dynamic strings library\n *\n * Copyright (c) 2006-2015, Salvatore Sanfilippo <antirez at gmail dot com>\n * Copyright (c) 2015, Oran Agra\n * Copyright (c) 2015, Redis Labs, Inc\n * All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions are met:\n *\n *   * Redistributions of source code must retain the above copyright notice,\n *     this list of conditions and the following disclaimer.\n *   * Redistributions in binary form must reproduce the above copyright\n *     notice, this list of conditions and the following disclaimer in the\n *     documentation and/or other materials provided with the distribution.\n *   * Neither the name of Redis nor the names of its contributors may be used\n *     to endorse or promote products derived from this software without\n *     specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\"\n * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\n * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE\n * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR\n * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF\n * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS\n * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN\n * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)\n * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE\n * POSSIBILITY OF SUCH DAMAGE.\n */\n\n#ifndef __SDS_H\n#define __SDS_H\n\n#define SDS_MAX_PREALLOC (1024*1024)\n\n#include <sys/types.h>\n#include <stdarg.h>\n#include <stdint.h>\n\ntypedef char *sds;\n\n/* Note: sdshdr5 is never used, we just access the flags byte directly.\n * However is here to document the layout of type 5 SDS strings. */\nstruct __attribute__ ((__packed__)) sdshdr5 {\n    unsigned char flags; /* 3 lsb of type, and 5 msb of string length */\n    char buf[];\n};\nstruct __attribute__ ((__packed__)) sdshdr8 {\n    uint8_t len; /* used */\n    uint8_t alloc; /* excluding the header and null terminator */\n    unsigned char flags; /* 3 lsb of type, 5 unused bits */\n    char buf[];\n};\nstruct __attribute__ ((__packed__)) sdshdr16 {\n    uint16_t len; /* used */\n    uint16_t alloc; /* excluding the header and null terminator */\n    unsigned char flags; /* 3 lsb of type, 5 unused bits */\n    char buf[];\n};\nstruct __attribute__ ((__packed__)) sdshdr32 {\n    uint32_t len; /* used */\n    uint32_t alloc; /* excluding the header and null terminator */\n    unsigned char flags; /* 3 lsb of type, 5 unused bits */\n    char buf[];\n};\nstruct __attribute__ ((__packed__)) sdshdr64 {\n    uint64_t len; /* used */\n    uint64_t alloc; /* excluding the header and null terminator */\n    unsigned char flags; /* 3 lsb of type, 5 unused bits */\n    char buf[];\n};\n\n#define SDS_TYPE_5  0\n#define SDS_TYPE_8  1\n#define SDS_TYPE_16 2\n#define SDS_TYPE_32 3\n#define SDS_TYPE_64 4\n#define SDS_TYPE_MASK 7\n#define SDS_TYPE_BITS 3\n#define SDS_HDR_VAR(T,s) struct sdshdr##T *sh = (void*)((s)-(sizeof(struct sdshdr##T)));\n#define SDS_HDR(T,s) ((struct sdshdr##T *)((s)-(sizeof(struct sdshdr##T))))\n#define SDS_TYPE_5_LEN(f) ((f)>>SDS_TYPE_BITS)\n\nstatic inline size_t sdslen(const sds s) {\n    unsigned char flags = s[-1];\n    switch(flags&SDS_TYPE_MASK) {\n        case SDS_TYPE_5:\n            return SDS_TYPE_5_LEN(flags);\n        case SDS_TYPE_8:\n            return SDS_HDR(8,s)->len;\n        case SDS_TYPE_16:\n            return SDS_HDR(16,s)->len;\n        case SDS_TYPE_32:\n            return SDS_HDR(32,s)->len;\n        case SDS_TYPE_64:\n            return SDS_HDR(64,s)->len;\n    }\n    return 0;\n}\n\nstatic inline size_t sdsavail(const sds s) {\n    unsigned char flags = s[-1];\n    switch(flags&SDS_TYPE_MASK) {\n        case SDS_TYPE_5: {\n            return 0;\n        }\n        case SDS_TYPE_8: {\n            SDS_HDR_VAR(8,s);\n            return sh->alloc - sh->len;\n        }\n        case SDS_TYPE_16: {\n            SDS_HDR_VAR(16,s);\n            return sh->alloc - sh->len;\n        }\n        case SDS_TYPE_32: {\n            SDS_HDR_VAR(32,s);\n            return sh->alloc - sh->len;\n        }\n        case SDS_TYPE_64: {\n            SDS_HDR_VAR(64,s);\n            return sh->alloc - sh->len;\n        }\n    }\n    return 0;\n}\n\nstatic inline void sdssetlen(sds s, size_t newlen) {\n    unsigned char flags = s[-1];\n    switch(flags&SDS_TYPE_MASK) {\n        case SDS_TYPE_5:\n            {\n                unsigned char *fp = ((unsigned char*)s)-1;\n                *fp = SDS_TYPE_5 | (newlen << SDS_TYPE_BITS);\n            }\n            break;\n        case SDS_TYPE_8:\n            SDS_HDR(8,s)->len = newlen;\n            break;\n        case SDS_TYPE_16:\n            SDS_HDR(16,s)->len = newlen;\n            break;\n        case SDS_TYPE_32:\n            SDS_HDR(32,s)->len = newlen;\n            break;\n        case SDS_TYPE_64:\n            SDS_HDR(64,s)->len = newlen;\n            break;\n    }\n}\n\nstatic inline void sdsinclen(sds s, size_t inc) {\n    unsigned char flags = s[-1];\n    switch(flags&SDS_TYPE_MASK) {\n        case SDS_TYPE_5:\n            {\n                unsigned char *fp = ((unsigned char*)s)-1;\n                unsigned char newlen = SDS_TYPE_5_LEN(flags)+inc;\n                *fp = SDS_TYPE_5 | (newlen << SDS_TYPE_BITS);\n            }\n            break;\n        case SDS_TYPE_8:\n            SDS_HDR(8,s)->len += inc;\n            break;\n        case SDS_TYPE_16:\n            SDS_HDR(16,s)->len += inc;\n            break;\n        case SDS_TYPE_32:\n            SDS_HDR(32,s)->len += inc;\n            break;\n        case SDS_TYPE_64:\n            SDS_HDR(64,s)->len += inc;\n            break;\n    }\n}\n\n/* sdsalloc() = sdsavail() + sdslen() */\nstatic inline size_t sdsalloc(const sds s) {\n    unsigned char flags = s[-1];\n    switch(flags&SDS_TYPE_MASK) {\n        case SDS_TYPE_5:\n            return SDS_TYPE_5_LEN(flags);\n        case SDS_TYPE_8:\n            return SDS_HDR(8,s)->alloc;\n        case SDS_TYPE_16:\n            return SDS_HDR(16,s)->alloc;\n        case SDS_TYPE_32:\n            return SDS_HDR(32,s)->alloc;\n        case SDS_TYPE_64:\n            return SDS_HDR(64,s)->alloc;\n    }\n    return 0;\n}\n\nstatic inline void sdssetalloc(sds s, size_t newlen) {\n    unsigned char flags = s[-1];\n    switch(flags&SDS_TYPE_MASK) {\n        case SDS_TYPE_5:\n            /* Nothing to do, this type has no total allocation info. */\n            break;\n        case SDS_TYPE_8:\n            SDS_HDR(8,s)->alloc = newlen;\n            break;\n        case SDS_TYPE_16:\n            SDS_HDR(16,s)->alloc = newlen;\n            break;\n        case SDS_TYPE_32:\n            SDS_HDR(32,s)->alloc = newlen;\n            break;\n        case SDS_TYPE_64:\n            SDS_HDR(64,s)->alloc = newlen;\n            break;\n    }\n}\n\nsds sdsnewlen(const void *init, size_t initlen);\nsds sdsnew(const char *init);\nsds sdsempty(void);\nsds sdsdup(const sds s);\nvoid sdsfree(sds s);\nsds sdsgrowzero(sds s, size_t len);\nsds sdscatlen(sds s, const void *t, size_t len);\nsds sdscat(sds s, const char *t);\nsds sdscatsds(sds s, const sds t);\nsds sdscpylen(sds s, const char *t, size_t len);\nsds sdscpy(sds s, const char *t);\n\nsds sdscatvprintf(sds s, const char *fmt, va_list ap);\n#ifdef __GNUC__\nsds sdscatprintf(sds s, const char *fmt, ...)\n    __attribute__((format(printf, 2, 3)));\n#else\nsds sdscatprintf(sds s, const char *fmt, ...);\n#endif\n\nsds sdscatfmt(sds s, char const *fmt, ...);\nsds sdstrim(sds s, const char *cset);\nvoid sdsrange(sds s, int start, int end);\nvoid sdsupdatelen(sds s);\nvoid sdsclear(sds s);\nint sdscmp(const sds s1, const sds s2);\nsds *sdssplitlen(const char *s, int len, const char *sep, int seplen, int *count);\nvoid sdsfreesplitres(sds *tokens, int count);\nvoid sdstolower(sds s);\nvoid sdstoupper(sds s);\nsds sdsfromlonglong(long long value);\nsds sdscatrepr(sds s, const char *p, size_t len);\nsds *sdssplitargs(const char *line, int *argc);\nsds sdsmapchars(sds s, const char *from, const char *to, size_t setlen);\nsds sdsjoin(char **argv, int argc, char *sep);\nsds sdsjoinsds(sds *argv, int argc, const char *sep, size_t seplen);\n\n/* Low level functions exposed to the user API */\nsds sdsMakeRoomFor(sds s, size_t addlen);\nvoid sdsIncrLen(sds s, int incr);\nsds sdsRemoveFreeSpace(sds s);\nsize_t sdsAllocSize(sds s);\nvoid *sdsAllocPtr(sds s);\n\n/* Export the allocator used by SDS to the program using SDS.\n * Sometimes the program SDS is linked to, may use a different set of\n * allocators, but may want to allocate or free things that SDS will\n * respectively free or allocate. */\nvoid *sds_malloc(size_t size);\nvoid *sds_realloc(void *ptr, size_t size);\nvoid sds_free(void *ptr);\n\n#ifdef REDIS_TEST\nint sdsTest(int argc, char *argv[]);\n#endif\n\n#endif\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/src/sdsalloc.h",
    "content": "/* SDSLib 2.0 -- A C dynamic strings library\n *\n * Copyright (c) 2006-2015, Salvatore Sanfilippo <antirez at gmail dot com>\n * Copyright (c) 2015, Redis Labs, Inc\n * All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions are met:\n *\n *   * Redistributions of source code must retain the above copyright notice,\n *     this list of conditions and the following disclaimer.\n *   * Redistributions in binary form must reproduce the above copyright\n *     notice, this list of conditions and the following disclaimer in the\n *     documentation and/or other materials provided with the distribution.\n *   * Neither the name of Redis nor the names of its contributors may be used\n *     to endorse or promote products derived from this software without\n *     specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\"\n * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\n * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE\n * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR\n * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF\n * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS\n * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN\n * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)\n * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE\n * POSSIBILITY OF SUCH DAMAGE.\n */\n\n/* SDS allocator selection.\n *\n * This file is used in order to change the SDS allocator at compile time.\n * Just define the following defines to what you want to use. Also add\n * the include of your alternate allocator if needed (not needed in order\n * to use the default libc allocator). */\n\n#include \"zmalloc.h\"\n#define s_malloc zmalloc\n#define s_realloc zrealloc\n#define s_free zfree\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/src/sentinel.c",
    "content": "/* Redis Sentinel implementation\n *\n * Copyright (c) 2009-2012, Salvatore Sanfilippo <antirez at gmail dot com>\n * All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions are met:\n *\n *   * Redistributions of source code must retain the above copyright notice,\n *     this list of conditions and the following disclaimer.\n *   * Redistributions in binary form must reproduce the above copyright\n *     notice, this list of conditions and the following disclaimer in the\n *     documentation and/or other materials provided with the distribution.\n *   * Neither the name of Redis nor the names of its contributors may be used\n *     to endorse or promote products derived from this software without\n *     specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\"\n * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\n * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE\n * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR\n * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF\n * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS\n * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN\n * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)\n * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE\n * POSSIBILITY OF SUCH DAMAGE.\n */\n\n#include \"server.h\"\n#include \"hiredis.h\"\n#include \"async.h\"\n\n#include <ctype.h>\n#include <arpa/inet.h>\n#include <sys/socket.h>\n#include <sys/wait.h>\n#include <fcntl.h>\n\nextern char **environ;\n\n#define REDIS_SENTINEL_PORT 26379\n\n/* ======================== Sentinel global state =========================== */\n\n/* Address object, used to describe an ip:port pair. */\ntypedef struct sentinelAddr {\n    char *ip;\n    int port;\n} sentinelAddr;\n\n/* A Sentinel Redis Instance object is monitoring. */\n#define SRI_MASTER  (1<<0)\n#define SRI_SLAVE   (1<<1)\n#define SRI_SENTINEL (1<<2)\n#define SRI_S_DOWN (1<<3)   /* Subjectively down (no quorum). */\n#define SRI_O_DOWN (1<<4)   /* Objectively down (confirmed by others). */\n#define SRI_MASTER_DOWN (1<<5) /* A Sentinel with this flag set thinks that\n                                   its master is down. */\n#define SRI_FAILOVER_IN_PROGRESS (1<<6) /* Failover is in progress for\n                                           this master. */\n#define SRI_PROMOTED (1<<7)            /* Slave selected for promotion. */\n#define SRI_RECONF_SENT (1<<8)     /* SLAVEOF <newmaster> sent. */\n#define SRI_RECONF_INPROG (1<<9)   /* Slave synchronization in progress. */\n#define SRI_RECONF_DONE (1<<10)     /* Slave synchronized with new master. */\n#define SRI_FORCE_FAILOVER (1<<11)  /* Force failover with master up. */\n#define SRI_SCRIPT_KILL_SENT (1<<12) /* SCRIPT KILL already sent on -BUSY */\n\n/* Note: times are in milliseconds. */\n#define SENTINEL_INFO_PERIOD 10000\n#define SENTINEL_PING_PERIOD 1000\n#define SENTINEL_ASK_PERIOD 1000\n#define SENTINEL_PUBLISH_PERIOD 2000\n#define SENTINEL_DEFAULT_DOWN_AFTER 30000\n#define SENTINEL_HELLO_CHANNEL \"__sentinel__:hello\"\n#define SENTINEL_TILT_TRIGGER 2000\n#define SENTINEL_TILT_PERIOD (SENTINEL_PING_PERIOD*30)\n#define SENTINEL_DEFAULT_SLAVE_PRIORITY 100\n#define SENTINEL_SLAVE_RECONF_TIMEOUT 10000\n#define SENTINEL_DEFAULT_PARALLEL_SYNCS 1\n#define SENTINEL_MIN_LINK_RECONNECT_PERIOD 15000\n#define SENTINEL_DEFAULT_FAILOVER_TIMEOUT (60*3*1000)\n#define SENTINEL_MAX_PENDING_COMMANDS 100\n#define SENTINEL_ELECTION_TIMEOUT 10000\n#define SENTINEL_MAX_DESYNC 1000\n\n/* Failover machine different states. */\n#define SENTINEL_FAILOVER_STATE_NONE 0  /* No failover in progress. */\n#define SENTINEL_FAILOVER_STATE_WAIT_START 1  /* Wait for failover_start_time*/\n#define SENTINEL_FAILOVER_STATE_SELECT_SLAVE 2 /* Select slave to promote */\n#define SENTINEL_FAILOVER_STATE_SEND_SLAVEOF_NOONE 3 /* Slave -> Master */\n#define SENTINEL_FAILOVER_STATE_WAIT_PROMOTION 4 /* Wait slave to change role */\n#define SENTINEL_FAILOVER_STATE_RECONF_SLAVES 5 /* SLAVEOF newmaster */\n#define SENTINEL_FAILOVER_STATE_UPDATE_CONFIG 6 /* Monitor promoted slave. */\n\n#define SENTINEL_MASTER_LINK_STATUS_UP 0\n#define SENTINEL_MASTER_LINK_STATUS_DOWN 1\n\n/* Generic flags that can be used with different functions.\n * They use higher bits to avoid colliding with the function specific\n * flags. */\n#define SENTINEL_NO_FLAGS 0\n#define SENTINEL_GENERATE_EVENT (1<<16)\n#define SENTINEL_LEADER (1<<17)\n#define SENTINEL_OBSERVER (1<<18)\n\n/* Script execution flags and limits. */\n#define SENTINEL_SCRIPT_NONE 0\n#define SENTINEL_SCRIPT_RUNNING 1\n#define SENTINEL_SCRIPT_MAX_QUEUE 256\n#define SENTINEL_SCRIPT_MAX_RUNNING 16\n#define SENTINEL_SCRIPT_MAX_RUNTIME 60000 /* 60 seconds max exec time. */\n#define SENTINEL_SCRIPT_MAX_RETRY 10\n#define SENTINEL_SCRIPT_RETRY_DELAY 30000 /* 30 seconds between retries. */\n\n/* SENTINEL SIMULATE-FAILURE command flags. */\n#define SENTINEL_SIMFAILURE_NONE 0\n#define SENTINEL_SIMFAILURE_CRASH_AFTER_ELECTION (1<<0)\n#define SENTINEL_SIMFAILURE_CRASH_AFTER_PROMOTION (1<<1)\n\n/* The link to a sentinelRedisInstance. When we have the same set of Sentinels\n * monitoring many masters, we have different instances representing the\n * same Sentinels, one per master, and we need to share the hiredis connections\n * among them. Oherwise if 5 Sentinels are monitoring 100 masters we create\n * 500 outgoing connections instead of 5.\n *\n * So this structure represents a reference counted link in terms of the two\n * hiredis connections for commands and Pub/Sub, and the fields needed for\n * failure detection, since the ping/pong time are now local to the link: if\n * the link is available, the instance is avaialbe. This way we don't just\n * have 5 connections instead of 500, we also send 5 pings instead of 500.\n *\n * Links are shared only for Sentinels: master and slave instances have\n * a link with refcount = 1, always. */\ntypedef struct instanceLink {\n    int refcount;          /* Number of sentinelRedisInstance owners. */\n    int disconnected;      /* Non-zero if we need to reconnect cc or pc. */\n    int pending_commands;  /* Number of commands sent waiting for a reply. */\n    redisAsyncContext *cc; /* Hiredis context for commands. */\n    redisAsyncContext *pc; /* Hiredis context for Pub / Sub. */\n    mstime_t cc_conn_time; /* cc connection time. */\n    mstime_t pc_conn_time; /* pc connection time. */\n    mstime_t pc_last_activity; /* Last time we received any message. */\n    mstime_t last_avail_time; /* Last time the instance replied to ping with\n                                 a reply we consider valid. */\n    mstime_t act_ping_time;   /* Time at which the last pending ping (no pong\n                                 received after it) was sent. This field is\n                                 set to 0 when a pong is received, and set again\n                                 to the current time if the value is 0 and a new\n                                 ping is sent. */\n    mstime_t last_ping_time;  /* Time at which we sent the last ping. This is\n                                 only used to avoid sending too many pings\n                                 during failure. Idle time is computed using\n                                 the act_ping_time field. */\n    mstime_t last_pong_time;  /* Last time the instance replied to ping,\n                                 whatever the reply was. That's used to check\n                                 if the link is idle and must be reconnected. */\n    mstime_t last_reconn_time;  /* Last reconnection attempt performed when\n                                   the link was down. */\n} instanceLink;\n\ntypedef struct sentinelRedisInstance {\n    int flags;      /* See SRI_... defines */\n    char *name;     /* Master name from the point of view of this sentinel. */\n    char *runid;    /* Run ID of this instance, or unique ID if is a Sentinel.*/\n    uint64_t config_epoch;  /* Configuration epoch. */\n    sentinelAddr *addr; /* Master host. */\n    instanceLink *link; /* Link to the instance, may be shared for Sentinels. */\n    mstime_t last_pub_time;   /* Last time we sent hello via Pub/Sub. */\n    mstime_t last_hello_time; /* Only used if SRI_SENTINEL is set. Last time\n                                 we received a hello from this Sentinel\n                                 via Pub/Sub. */\n    mstime_t last_master_down_reply_time; /* Time of last reply to\n                                             SENTINEL is-master-down command. */\n    mstime_t s_down_since_time; /* Subjectively down since time. */\n    mstime_t o_down_since_time; /* Objectively down since time. */\n    mstime_t down_after_period; /* Consider it down after that period. */\n    mstime_t info_refresh;  /* Time at which we received INFO output from it. */\n\n    /* Role and the first time we observed it.\n     * This is useful in order to delay replacing what the instance reports\n     * with our own configuration. We need to always wait some time in order\n     * to give a chance to the leader to report the new configuration before\n     * we do silly things. */\n    int role_reported;\n    mstime_t role_reported_time;\n    mstime_t slave_conf_change_time; /* Last time slave master addr changed. */\n\n    /* Master specific. */\n    dict *sentinels;    /* Other sentinels monitoring the same master. */\n    dict *slaves;       /* Slaves for this master instance. */\n    unsigned int quorum;/* Number of sentinels that need to agree on failure. */\n    int parallel_syncs; /* How many slaves to reconfigure at same time. */\n    char *auth_pass;    /* Password to use for AUTH against master & slaves. */\n\n    /* Slave specific. */\n    mstime_t master_link_down_time; /* Slave replication link down time. */\n    int slave_priority; /* Slave priority according to its INFO output. */\n    mstime_t slave_reconf_sent_time; /* Time at which we sent SLAVE OF <new> */\n    struct sentinelRedisInstance *master; /* Master instance if it's slave. */\n    char *slave_master_host;    /* Master host as reported by INFO */\n    int slave_master_port;      /* Master port as reported by INFO */\n    int slave_master_link_status; /* Master link status as reported by INFO */\n    unsigned long long slave_repl_offset; /* Slave replication offset. */\n    /* Failover */\n    char *leader;       /* If this is a master instance, this is the runid of\n                           the Sentinel that should perform the failover. If\n                           this is a Sentinel, this is the runid of the Sentinel\n                           that this Sentinel voted as leader. */\n    uint64_t leader_epoch; /* Epoch of the 'leader' field. */\n    uint64_t failover_epoch; /* Epoch of the currently started failover. */\n    int failover_state; /* See SENTINEL_FAILOVER_STATE_* defines. */\n    mstime_t failover_state_change_time;\n    mstime_t failover_start_time;   /* Last failover attempt start time. */\n    mstime_t failover_timeout;      /* Max time to refresh failover state. */\n    mstime_t failover_delay_logged; /* For what failover_start_time value we\n                                       logged the failover delay. */\n    struct sentinelRedisInstance *promoted_slave; /* Promoted slave instance. */\n    /* Scripts executed to notify admin or reconfigure clients: when they\n     * are set to NULL no script is executed. */\n    char *notification_script;\n    char *client_reconfig_script;\n    sds info; /* cached INFO output */\n} sentinelRedisInstance;\n\n/* Main state. */\nstruct sentinelState {\n    char myid[CONFIG_RUN_ID_SIZE+1]; /* This sentinel ID. */\n    uint64_t current_epoch;         /* Current epoch. */\n    dict *masters;      /* Dictionary of master sentinelRedisInstances.\n                           Key is the instance name, value is the\n                           sentinelRedisInstance structure pointer. */\n    int tilt;           /* Are we in TILT mode? */\n    int running_scripts;    /* Number of scripts in execution right now. */\n    mstime_t tilt_start_time;       /* When TITL started. */\n    mstime_t previous_time;         /* Last time we ran the time handler. */\n    list *scripts_queue;            /* Queue of user scripts to execute. */\n    char *announce_ip;  /* IP addr that is gossiped to other sentinels if\n                           not NULL. */\n    int announce_port;  /* Port that is gossiped to other sentinels if\n                           non zero. */\n    unsigned long simfailure_flags; /* Failures simulation. */\n} sentinel;\n\n/* A script execution job. */\ntypedef struct sentinelScriptJob {\n    int flags;              /* Script job flags: SENTINEL_SCRIPT_* */\n    int retry_num;          /* Number of times we tried to execute it. */\n    char **argv;            /* Arguments to call the script. */\n    mstime_t start_time;    /* Script execution time if the script is running,\n                               otherwise 0 if we are allowed to retry the\n                               execution at any time. If the script is not\n                               running and it's not 0, it means: do not run\n                               before the specified time. */\n    pid_t pid;              /* Script execution pid. */\n} sentinelScriptJob;\n\n/* ======================= hiredis ae.c adapters =============================\n * Note: this implementation is taken from hiredis/adapters/ae.h, however\n * we have our modified copy for Sentinel in order to use our allocator\n * and to have full control over how the adapter works. */\n\ntypedef struct redisAeEvents {\n    redisAsyncContext *context;\n    aeEventLoop *loop;\n    int fd;\n    int reading, writing;\n} redisAeEvents;\n\nstatic void redisAeReadEvent(aeEventLoop *el, int fd, void *privdata, int mask) {\n    ((void)el); ((void)fd); ((void)mask);\n\n    redisAeEvents *e = (redisAeEvents*)privdata;\n    redisAsyncHandleRead(e->context);\n}\n\nstatic void redisAeWriteEvent(aeEventLoop *el, int fd, void *privdata, int mask) {\n    ((void)el); ((void)fd); ((void)mask);\n\n    redisAeEvents *e = (redisAeEvents*)privdata;\n    redisAsyncHandleWrite(e->context);\n}\n\nstatic void redisAeAddRead(void *privdata) {\n    redisAeEvents *e = (redisAeEvents*)privdata;\n    aeEventLoop *loop = e->loop;\n    if (!e->reading) {\n        e->reading = 1;\n        aeCreateFileEvent(loop,e->fd,AE_READABLE,redisAeReadEvent,e);\n    }\n}\n\nstatic void redisAeDelRead(void *privdata) {\n    redisAeEvents *e = (redisAeEvents*)privdata;\n    aeEventLoop *loop = e->loop;\n    if (e->reading) {\n        e->reading = 0;\n        aeDeleteFileEvent(loop,e->fd,AE_READABLE);\n    }\n}\n\nstatic void redisAeAddWrite(void *privdata) {\n    redisAeEvents *e = (redisAeEvents*)privdata;\n    aeEventLoop *loop = e->loop;\n    if (!e->writing) {\n        e->writing = 1;\n        aeCreateFileEvent(loop,e->fd,AE_WRITABLE,redisAeWriteEvent,e);\n    }\n}\n\nstatic void redisAeDelWrite(void *privdata) {\n    redisAeEvents *e = (redisAeEvents*)privdata;\n    aeEventLoop *loop = e->loop;\n    if (e->writing) {\n        e->writing = 0;\n        aeDeleteFileEvent(loop,e->fd,AE_WRITABLE);\n    }\n}\n\nstatic void redisAeCleanup(void *privdata) {\n    redisAeEvents *e = (redisAeEvents*)privdata;\n    redisAeDelRead(privdata);\n    redisAeDelWrite(privdata);\n    zfree(e);\n}\n\nstatic int redisAeAttach(aeEventLoop *loop, redisAsyncContext *ac) {\n    redisContext *c = &(ac->c);\n    redisAeEvents *e;\n\n    /* Nothing should be attached when something is already attached */\n    if (ac->ev.data != NULL)\n        return C_ERR;\n\n    /* Create container for context and r/w events */\n    e = (redisAeEvents*)zmalloc(sizeof(*e));\n    e->context = ac;\n    e->loop = loop;\n    e->fd = c->fd;\n    e->reading = e->writing = 0;\n\n    /* Register functions to start/stop listening for events */\n    ac->ev.addRead = redisAeAddRead;\n    ac->ev.delRead = redisAeDelRead;\n    ac->ev.addWrite = redisAeAddWrite;\n    ac->ev.delWrite = redisAeDelWrite;\n    ac->ev.cleanup = redisAeCleanup;\n    ac->ev.data = e;\n\n    return C_OK;\n}\n\n/* ============================= Prototypes ================================= */\n\nvoid sentinelLinkEstablishedCallback(const redisAsyncContext *c, int status);\nvoid sentinelDisconnectCallback(const redisAsyncContext *c, int status);\nvoid sentinelReceiveHelloMessages(redisAsyncContext *c, void *reply, void *privdata);\nsentinelRedisInstance *sentinelGetMasterByName(char *name);\nchar *sentinelGetSubjectiveLeader(sentinelRedisInstance *master);\nchar *sentinelGetObjectiveLeader(sentinelRedisInstance *master);\nint yesnotoi(char *s);\nvoid instanceLinkConnectionError(const redisAsyncContext *c);\nconst char *sentinelRedisInstanceTypeStr(sentinelRedisInstance *ri);\nvoid sentinelAbortFailover(sentinelRedisInstance *ri);\nvoid sentinelEvent(int level, char *type, sentinelRedisInstance *ri, const char *fmt, ...);\nsentinelRedisInstance *sentinelSelectSlave(sentinelRedisInstance *master);\nvoid sentinelScheduleScriptExecution(char *path, ...);\nvoid sentinelStartFailover(sentinelRedisInstance *master);\nvoid sentinelDiscardReplyCallback(redisAsyncContext *c, void *reply, void *privdata);\nint sentinelSendSlaveOf(sentinelRedisInstance *ri, char *host, int port);\nchar *sentinelVoteLeader(sentinelRedisInstance *master, uint64_t req_epoch, char *req_runid, uint64_t *leader_epoch);\nvoid sentinelFlushConfig(void);\nvoid sentinelGenerateInitialMonitorEvents(void);\nint sentinelSendPing(sentinelRedisInstance *ri);\nint sentinelForceHelloUpdateForMaster(sentinelRedisInstance *master);\nsentinelRedisInstance *getSentinelRedisInstanceByAddrAndRunID(dict *instances, char *ip, int port, char *runid);\nvoid sentinelSimFailureCrash(void);\n\n/* ========================= Dictionary types =============================== */\n\nunsigned int dictSdsHash(const void *key);\nint dictSdsKeyCompare(void *privdata, const void *key1, const void *key2);\nvoid releaseSentinelRedisInstance(sentinelRedisInstance *ri);\n\nvoid dictInstancesValDestructor (void *privdata, void *obj) {\n    UNUSED(privdata);\n    releaseSentinelRedisInstance(obj);\n}\n\n/* Instance name (sds) -> instance (sentinelRedisInstance pointer)\n *\n * also used for: sentinelRedisInstance->sentinels dictionary that maps\n * sentinels ip:port to last seen time in Pub/Sub hello message. */\ndictType instancesDictType = {\n    dictSdsHash,               /* hash function */\n    NULL,                      /* key dup */\n    NULL,                      /* val dup */\n    dictSdsKeyCompare,         /* key compare */\n    NULL,                      /* key destructor */\n    dictInstancesValDestructor /* val destructor */\n};\n\n/* Instance runid (sds) -> votes (long casted to void*)\n *\n * This is useful into sentinelGetObjectiveLeader() function in order to\n * count the votes and understand who is the leader. */\ndictType leaderVotesDictType = {\n    dictSdsHash,               /* hash function */\n    NULL,                      /* key dup */\n    NULL,                      /* val dup */\n    dictSdsKeyCompare,         /* key compare */\n    NULL,                      /* key destructor */\n    NULL                       /* val destructor */\n};\n\n/* =========================== Initialization =============================== */\n\nvoid sentinelCommand(client *c);\nvoid sentinelInfoCommand(client *c);\nvoid sentinelSetCommand(client *c);\nvoid sentinelPublishCommand(client *c);\nvoid sentinelRoleCommand(client *c);\n\nstruct redisCommand sentinelcmds[] = {\n    {\"ping\",pingCommand,1,\"\",0,NULL,0,0,0,0,0},\n    {\"sentinel\",sentinelCommand,-2,\"\",0,NULL,0,0,0,0,0},\n    {\"subscribe\",subscribeCommand,-2,\"\",0,NULL,0,0,0,0,0},\n    {\"unsubscribe\",unsubscribeCommand,-1,\"\",0,NULL,0,0,0,0,0},\n    {\"psubscribe\",psubscribeCommand,-2,\"\",0,NULL,0,0,0,0,0},\n    {\"punsubscribe\",punsubscribeCommand,-1,\"\",0,NULL,0,0,0,0,0},\n    {\"publish\",sentinelPublishCommand,3,\"\",0,NULL,0,0,0,0,0},\n    {\"info\",sentinelInfoCommand,-1,\"\",0,NULL,0,0,0,0,0},\n    {\"role\",sentinelRoleCommand,1,\"l\",0,NULL,0,0,0,0,0},\n    {\"client\",clientCommand,-2,\"rs\",0,NULL,0,0,0,0,0},\n    {\"shutdown\",shutdownCommand,-1,\"\",0,NULL,0,0,0,0,0}\n};\n\n/* This function overwrites a few normal Redis config default with Sentinel\n * specific defaults. */\nvoid initSentinelConfig(void) {\n    server.port = REDIS_SENTINEL_PORT;\n}\n\n/* Perform the Sentinel mode initialization. */\nvoid initSentinel(void) {\n    unsigned int j;\n\n    /* Remove usual Redis commands from the command table, then just add\n     * the SENTINEL command. */\n    dictEmpty(server.commands,NULL);\n    for (j = 0; j < sizeof(sentinelcmds)/sizeof(sentinelcmds[0]); j++) {\n        int retval;\n        struct redisCommand *cmd = sentinelcmds+j;\n\n        retval = dictAdd(server.commands, sdsnew(cmd->name), cmd);\n        serverAssert(retval == DICT_OK);\n    }\n\n    /* Initialize various data structures. */\n    sentinel.current_epoch = 0;\n    sentinel.masters = dictCreate(&instancesDictType,NULL);\n    sentinel.tilt = 0;\n    sentinel.tilt_start_time = 0;\n    sentinel.previous_time = mstime();\n    sentinel.running_scripts = 0;\n    sentinel.scripts_queue = listCreate();\n    sentinel.announce_ip = NULL;\n    sentinel.announce_port = 0;\n    sentinel.simfailure_flags = SENTINEL_SIMFAILURE_NONE;\n    memset(sentinel.myid,0,sizeof(sentinel.myid));\n}\n\n/* This function gets called when the server is in Sentinel mode, started,\n * loaded the configuration, and is ready for normal operations. */\nvoid sentinelIsRunning(void) {\n    int j;\n\n    if (server.configfile == NULL) {\n        serverLog(LL_WARNING,\n            \"Sentinel started without a config file. Exiting...\");\n        exit(1);\n    } else if (access(server.configfile,W_OK) == -1) {\n        serverLog(LL_WARNING,\n            \"Sentinel config file %s is not writable: %s. Exiting...\",\n            server.configfile,strerror(errno));\n        exit(1);\n    }\n\n    /* If this Sentinel has yet no ID set in the configuration file, we\n     * pick a random one and persist the config on disk. From now on this\n     * will be this Sentinel ID across restarts. */\n    for (j = 0; j < CONFIG_RUN_ID_SIZE; j++)\n        if (sentinel.myid[j] != 0) break;\n\n    if (j == CONFIG_RUN_ID_SIZE) {\n        /* Pick ID and presist the config. */\n        getRandomHexChars(sentinel.myid,CONFIG_RUN_ID_SIZE);\n        sentinelFlushConfig();\n    }\n\n    /* Log its ID to make debugging of issues simpler. */\n    serverLog(LL_WARNING,\"Sentinel ID is %s\", sentinel.myid);\n\n    /* We want to generate a +monitor event for every configured master\n     * at startup. */\n    sentinelGenerateInitialMonitorEvents();\n}\n\n/* ============================== sentinelAddr ============================== */\n\n/* Create a sentinelAddr object and return it on success.\n * On error NULL is returned and errno is set to:\n *  ENOENT: Can't resolve the hostname.\n *  EINVAL: Invalid port number.\n */\nsentinelAddr *createSentinelAddr(char *hostname, int port) {\n    char ip[NET_IP_STR_LEN];\n    sentinelAddr *sa;\n\n    if (port < 0 || port > 65535) {\n        errno = EINVAL;\n        return NULL;\n    }\n    if (anetResolve(NULL,hostname,ip,sizeof(ip)) == ANET_ERR) {\n        errno = ENOENT;\n        return NULL;\n    }\n    sa = zmalloc(sizeof(*sa));\n    sa->ip = sdsnew(ip);\n    sa->port = port;\n    return sa;\n}\n\n/* Return a duplicate of the source address. */\nsentinelAddr *dupSentinelAddr(sentinelAddr *src) {\n    sentinelAddr *sa;\n\n    sa = zmalloc(sizeof(*sa));\n    sa->ip = sdsnew(src->ip);\n    sa->port = src->port;\n    return sa;\n}\n\n/* Free a Sentinel address. Can't fail. */\nvoid releaseSentinelAddr(sentinelAddr *sa) {\n    sdsfree(sa->ip);\n    zfree(sa);\n}\n\n/* Return non-zero if two addresses are equal. */\nint sentinelAddrIsEqual(sentinelAddr *a, sentinelAddr *b) {\n    return a->port == b->port && !strcasecmp(a->ip,b->ip);\n}\n\n/* =========================== Events notification ========================== */\n\n/* Send an event to log, pub/sub, user notification script.\n *\n * 'level' is the log level for logging. Only LL_WARNING events will trigger\n * the execution of the user notification script.\n *\n * 'type' is the message type, also used as a pub/sub channel name.\n *\n * 'ri', is the redis instance target of this event if applicable, and is\n * used to obtain the path of the notification script to execute.\n *\n * The remaining arguments are printf-alike.\n * If the format specifier starts with the two characters \"%@\" then ri is\n * not NULL, and the message is prefixed with an instance identifier in the\n * following format:\n *\n *  <instance type> <instance name> <ip> <port>\n *\n *  If the instance type is not master, than the additional string is\n *  added to specify the originating master:\n *\n *  @ <master name> <master ip> <master port>\n *\n *  Any other specifier after \"%@\" is processed by printf itself.\n */\nvoid sentinelEvent(int level, char *type, sentinelRedisInstance *ri,\n                   const char *fmt, ...) {\n    va_list ap;\n    char msg[LOG_MAX_LEN];\n    robj *channel, *payload;\n\n    /* Handle %@ */\n    if (fmt[0] == '%' && fmt[1] == '@') {\n        sentinelRedisInstance *master = (ri->flags & SRI_MASTER) ?\n                                         NULL : ri->master;\n\n        if (master) {\n            snprintf(msg, sizeof(msg), \"%s %s %s %d @ %s %s %d\",\n                sentinelRedisInstanceTypeStr(ri),\n                ri->name, ri->addr->ip, ri->addr->port,\n                master->name, master->addr->ip, master->addr->port);\n        } else {\n            snprintf(msg, sizeof(msg), \"%s %s %s %d\",\n                sentinelRedisInstanceTypeStr(ri),\n                ri->name, ri->addr->ip, ri->addr->port);\n        }\n        fmt += 2;\n    } else {\n        msg[0] = '\\0';\n    }\n\n    /* Use vsprintf for the rest of the formatting if any. */\n    if (fmt[0] != '\\0') {\n        va_start(ap, fmt);\n        vsnprintf(msg+strlen(msg), sizeof(msg)-strlen(msg), fmt, ap);\n        va_end(ap);\n    }\n\n    /* Log the message if the log level allows it to be logged. */\n    if (level >= server.verbosity)\n        serverLog(level,\"%s %s\",type,msg);\n\n    /* Publish the message via Pub/Sub if it's not a debugging one. */\n    if (level != LL_DEBUG) {\n        channel = createStringObject(type,strlen(type));\n        payload = createStringObject(msg,strlen(msg));\n        pubsubPublishMessage(channel,payload);\n        decrRefCount(channel);\n        decrRefCount(payload);\n    }\n\n    /* Call the notification script if applicable. */\n    if (level == LL_WARNING && ri != NULL) {\n        sentinelRedisInstance *master = (ri->flags & SRI_MASTER) ?\n                                         ri : ri->master;\n        if (master && master->notification_script) {\n            sentinelScheduleScriptExecution(master->notification_script,\n                type,msg,NULL);\n        }\n    }\n}\n\n/* This function is called only at startup and is used to generate a\n * +monitor event for every configured master. The same events are also\n * generated when a master to monitor is added at runtime via the\n * SENTINEL MONITOR command. */\nvoid sentinelGenerateInitialMonitorEvents(void) {\n    dictIterator *di;\n    dictEntry *de;\n\n    di = dictGetIterator(sentinel.masters);\n    while((de = dictNext(di)) != NULL) {\n        sentinelRedisInstance *ri = dictGetVal(de);\n        sentinelEvent(LL_WARNING,\"+monitor\",ri,\"%@ quorum %d\",ri->quorum);\n    }\n    dictReleaseIterator(di);\n}\n\n/* ============================ script execution ============================ */\n\n/* Release a script job structure and all the associated data. */\nvoid sentinelReleaseScriptJob(sentinelScriptJob *sj) {\n    int j = 0;\n\n    while(sj->argv[j]) sdsfree(sj->argv[j++]);\n    zfree(sj->argv);\n    zfree(sj);\n}\n\n#define SENTINEL_SCRIPT_MAX_ARGS 16\nvoid sentinelScheduleScriptExecution(char *path, ...) {\n    va_list ap;\n    char *argv[SENTINEL_SCRIPT_MAX_ARGS+1];\n    int argc = 1;\n    sentinelScriptJob *sj;\n\n    va_start(ap, path);\n    while(argc < SENTINEL_SCRIPT_MAX_ARGS) {\n        argv[argc] = va_arg(ap,char*);\n        if (!argv[argc]) break;\n        argv[argc] = sdsnew(argv[argc]); /* Copy the string. */\n        argc++;\n    }\n    va_end(ap);\n    argv[0] = sdsnew(path);\n\n    sj = zmalloc(sizeof(*sj));\n    sj->flags = SENTINEL_SCRIPT_NONE;\n    sj->retry_num = 0;\n    sj->argv = zmalloc(sizeof(char*)*(argc+1));\n    sj->start_time = 0;\n    sj->pid = 0;\n    memcpy(sj->argv,argv,sizeof(char*)*(argc+1));\n\n    listAddNodeTail(sentinel.scripts_queue,sj);\n\n    /* Remove the oldest non running script if we already hit the limit. */\n    if (listLength(sentinel.scripts_queue) > SENTINEL_SCRIPT_MAX_QUEUE) {\n        listNode *ln;\n        listIter li;\n\n        listRewind(sentinel.scripts_queue,&li);\n        while ((ln = listNext(&li)) != NULL) {\n            sj = ln->value;\n\n            if (sj->flags & SENTINEL_SCRIPT_RUNNING) continue;\n            /* The first node is the oldest as we add on tail. */\n            listDelNode(sentinel.scripts_queue,ln);\n            sentinelReleaseScriptJob(sj);\n            break;\n        }\n        serverAssert(listLength(sentinel.scripts_queue) <=\n                    SENTINEL_SCRIPT_MAX_QUEUE);\n    }\n}\n\n/* Lookup a script in the scripts queue via pid, and returns the list node\n * (so that we can easily remove it from the queue if needed). */\nlistNode *sentinelGetScriptListNodeByPid(pid_t pid) {\n    listNode *ln;\n    listIter li;\n\n    listRewind(sentinel.scripts_queue,&li);\n    while ((ln = listNext(&li)) != NULL) {\n        sentinelScriptJob *sj = ln->value;\n\n        if ((sj->flags & SENTINEL_SCRIPT_RUNNING) && sj->pid == pid)\n            return ln;\n    }\n    return NULL;\n}\n\n/* Run pending scripts if we are not already at max number of running\n * scripts. */\nvoid sentinelRunPendingScripts(void) {\n    listNode *ln;\n    listIter li;\n    mstime_t now = mstime();\n\n    /* Find jobs that are not running and run them, from the top to the\n     * tail of the queue, so we run older jobs first. */\n    listRewind(sentinel.scripts_queue,&li);\n    while (sentinel.running_scripts < SENTINEL_SCRIPT_MAX_RUNNING &&\n           (ln = listNext(&li)) != NULL)\n    {\n        sentinelScriptJob *sj = ln->value;\n        pid_t pid;\n\n        /* Skip if already running. */\n        if (sj->flags & SENTINEL_SCRIPT_RUNNING) continue;\n\n        /* Skip if it's a retry, but not enough time has elapsed. */\n        if (sj->start_time && sj->start_time > now) continue;\n\n        sj->flags |= SENTINEL_SCRIPT_RUNNING;\n        sj->start_time = mstime();\n        sj->retry_num++;\n        pid = fork();\n\n        if (pid == -1) {\n            /* Parent (fork error).\n             * We report fork errors as signal 99, in order to unify the\n             * reporting with other kind of errors. */\n            sentinelEvent(LL_WARNING,\"-script-error\",NULL,\n                          \"%s %d %d\", sj->argv[0], 99, 0);\n            sj->flags &= ~SENTINEL_SCRIPT_RUNNING;\n            sj->pid = 0;\n        } else if (pid == 0) {\n            /* Child */\n            execve(sj->argv[0],sj->argv,environ);\n            /* If we are here an error occurred. */\n            _exit(2); /* Don't retry execution. */\n        } else {\n            sentinel.running_scripts++;\n            sj->pid = pid;\n            sentinelEvent(LL_DEBUG,\"+script-child\",NULL,\"%ld\",(long)pid);\n        }\n    }\n}\n\n/* How much to delay the execution of a script that we need to retry after\n * an error?\n *\n * We double the retry delay for every further retry we do. So for instance\n * if RETRY_DELAY is set to 30 seconds and the max number of retries is 10\n * starting from the second attempt to execute the script the delays are:\n * 30 sec, 60 sec, 2 min, 4 min, 8 min, 16 min, 32 min, 64 min, 128 min. */\nmstime_t sentinelScriptRetryDelay(int retry_num) {\n    mstime_t delay = SENTINEL_SCRIPT_RETRY_DELAY;\n\n    while (retry_num-- > 1) delay *= 2;\n    return delay;\n}\n\n/* Check for scripts that terminated, and remove them from the queue if the\n * script terminated successfully. If instead the script was terminated by\n * a signal, or returned exit code \"1\", it is scheduled to run again if\n * the max number of retries did not already elapsed. */\nvoid sentinelCollectTerminatedScripts(void) {\n    int statloc;\n    pid_t pid;\n\n    while ((pid = wait3(&statloc,WNOHANG,NULL)) > 0) {\n        int exitcode = WEXITSTATUS(statloc);\n        int bysignal = 0;\n        listNode *ln;\n        sentinelScriptJob *sj;\n\n        if (WIFSIGNALED(statloc)) bysignal = WTERMSIG(statloc);\n        sentinelEvent(LL_DEBUG,\"-script-child\",NULL,\"%ld %d %d\",\n            (long)pid, exitcode, bysignal);\n\n        ln = sentinelGetScriptListNodeByPid(pid);\n        if (ln == NULL) {\n            serverLog(LL_WARNING,\"wait3() returned a pid (%ld) we can't find in our scripts execution queue!\", (long)pid);\n            continue;\n        }\n        sj = ln->value;\n\n        /* If the script was terminated by a signal or returns an\n         * exit code of \"1\" (that means: please retry), we reschedule it\n         * if the max number of retries is not already reached. */\n        if ((bysignal || exitcode == 1) &&\n            sj->retry_num != SENTINEL_SCRIPT_MAX_RETRY)\n        {\n            sj->flags &= ~SENTINEL_SCRIPT_RUNNING;\n            sj->pid = 0;\n            sj->start_time = mstime() +\n                             sentinelScriptRetryDelay(sj->retry_num);\n        } else {\n            /* Otherwise let's remove the script, but log the event if the\n             * execution did not terminated in the best of the ways. */\n            if (bysignal || exitcode != 0) {\n                sentinelEvent(LL_WARNING,\"-script-error\",NULL,\n                              \"%s %d %d\", sj->argv[0], bysignal, exitcode);\n            }\n            listDelNode(sentinel.scripts_queue,ln);\n            sentinelReleaseScriptJob(sj);\n            sentinel.running_scripts--;\n        }\n    }\n}\n\n/* Kill scripts in timeout, they'll be collected by the\n * sentinelCollectTerminatedScripts() function. */\nvoid sentinelKillTimedoutScripts(void) {\n    listNode *ln;\n    listIter li;\n    mstime_t now = mstime();\n\n    listRewind(sentinel.scripts_queue,&li);\n    while ((ln = listNext(&li)) != NULL) {\n        sentinelScriptJob *sj = ln->value;\n\n        if (sj->flags & SENTINEL_SCRIPT_RUNNING &&\n            (now - sj->start_time) > SENTINEL_SCRIPT_MAX_RUNTIME)\n        {\n            sentinelEvent(LL_WARNING,\"-script-timeout\",NULL,\"%s %ld\",\n                sj->argv[0], (long)sj->pid);\n            kill(sj->pid,SIGKILL);\n        }\n    }\n}\n\n/* Implements SENTINEL PENDING-SCRIPTS command. */\nvoid sentinelPendingScriptsCommand(client *c) {\n    listNode *ln;\n    listIter li;\n\n    addReplyMultiBulkLen(c,listLength(sentinel.scripts_queue));\n    listRewind(sentinel.scripts_queue,&li);\n    while ((ln = listNext(&li)) != NULL) {\n        sentinelScriptJob *sj = ln->value;\n        int j = 0;\n\n        addReplyMultiBulkLen(c,10);\n\n        addReplyBulkCString(c,\"argv\");\n        while (sj->argv[j]) j++;\n        addReplyMultiBulkLen(c,j);\n        j = 0;\n        while (sj->argv[j]) addReplyBulkCString(c,sj->argv[j++]);\n\n        addReplyBulkCString(c,\"flags\");\n        addReplyBulkCString(c,\n            (sj->flags & SENTINEL_SCRIPT_RUNNING) ? \"running\" : \"scheduled\");\n\n        addReplyBulkCString(c,\"pid\");\n        addReplyBulkLongLong(c,sj->pid);\n\n        if (sj->flags & SENTINEL_SCRIPT_RUNNING) {\n            addReplyBulkCString(c,\"run-time\");\n            addReplyBulkLongLong(c,mstime() - sj->start_time);\n        } else {\n            mstime_t delay = sj->start_time ? (sj->start_time-mstime()) : 0;\n            if (delay < 0) delay = 0;\n            addReplyBulkCString(c,\"run-delay\");\n            addReplyBulkLongLong(c,delay);\n        }\n\n        addReplyBulkCString(c,\"retry-num\");\n        addReplyBulkLongLong(c,sj->retry_num);\n    }\n}\n\n/* This function calls, if any, the client reconfiguration script with the\n * following parameters:\n *\n * <master-name> <role> <state> <from-ip> <from-port> <to-ip> <to-port>\n *\n * It is called every time a failover is performed.\n *\n * <state> is currently always \"failover\".\n * <role> is either \"leader\" or \"observer\".\n *\n * from/to fields are respectively master -> promoted slave addresses for\n * \"start\" and \"end\". */\nvoid sentinelCallClientReconfScript(sentinelRedisInstance *master, int role, char *state, sentinelAddr *from, sentinelAddr *to) {\n    char fromport[32], toport[32];\n\n    if (master->client_reconfig_script == NULL) return;\n    ll2string(fromport,sizeof(fromport),from->port);\n    ll2string(toport,sizeof(toport),to->port);\n    sentinelScheduleScriptExecution(master->client_reconfig_script,\n        master->name,\n        (role == SENTINEL_LEADER) ? \"leader\" : \"observer\",\n        state, from->ip, fromport, to->ip, toport, NULL);\n}\n\n/* =============================== instanceLink ============================= */\n\n/* Create a not yet connected link object. */\ninstanceLink *createInstanceLink(void) {\n    instanceLink *link = zmalloc(sizeof(*link));\n\n    link->refcount = 1;\n    link->disconnected = 1;\n    link->pending_commands = 0;\n    link->cc = NULL;\n    link->pc = NULL;\n    link->cc_conn_time = 0;\n    link->pc_conn_time = 0;\n    link->last_reconn_time = 0;\n    link->pc_last_activity = 0;\n    /* We set the act_ping_time to \"now\" even if we actually don't have yet\n     * a connection with the node, nor we sent a ping.\n     * This is useful to detect a timeout in case we'll not be able to connect\n     * with the node at all. */\n    link->act_ping_time = mstime();\n    link->last_ping_time = 0;\n    link->last_avail_time = mstime();\n    link->last_pong_time = mstime();\n    return link;\n}\n\n/* Disconnect an hiredis connection in the context of an instance link. */\nvoid instanceLinkCloseConnection(instanceLink *link, redisAsyncContext *c) {\n    if (c == NULL) return;\n\n    if (link->cc == c) {\n        link->cc = NULL;\n        link->pending_commands = 0;\n    }\n    if (link->pc == c) link->pc = NULL;\n    c->data = NULL;\n    link->disconnected = 1;\n    redisAsyncFree(c);\n}\n\n/* Decrement the refcount of a link object, if it drops to zero, actually\n * free it and return NULL. Otherwise don't do anything and return the pointer\n * to the object.\n *\n * If we are not going to free the link and ri is not NULL, we rebind all the\n * pending requests in link->cc (hiredis connection for commands) to a\n * callback that will just ignore them. This is useful to avoid processing\n * replies for an instance that no longer exists. */\ninstanceLink *releaseInstanceLink(instanceLink *link, sentinelRedisInstance *ri)\n{\n    serverAssert(link->refcount > 0);\n    link->refcount--;\n    if (link->refcount != 0) {\n        if (ri && ri->link->cc) {\n            /* This instance may have pending callbacks in the hiredis async\n             * context, having as 'privdata' the instance that we are going to\n             * free. Let's rewrite the callback list, directly exploiting\n             * hiredis internal data structures, in order to bind them with\n             * a callback that will ignore the reply at all. */\n            redisCallback *cb;\n            redisCallbackList *callbacks = &link->cc->replies;\n\n            cb = callbacks->head;\n            while(cb) {\n                if (cb->privdata == ri) {\n                    cb->fn = sentinelDiscardReplyCallback;\n                    cb->privdata = NULL; /* Not strictly needed. */\n                }\n                cb = cb->next;\n            }\n        }\n        return link; /* Other active users. */\n    }\n\n    instanceLinkCloseConnection(link,link->cc);\n    instanceLinkCloseConnection(link,link->pc);\n    zfree(link);\n    return NULL;\n}\n\n/* This function will attempt to share the instance link we already have\n * for the same Sentinel in the context of a different master, with the\n * instance we are passing as argument.\n *\n * This way multiple Sentinel objects that refer all to the same physical\n * Sentinel instance but in the context of different masters will use\n * a single connection, will send a single PING per second for failure\n * detection and so forth.\n *\n * Return C_OK if a matching Sentinel was found in the context of a\n * different master and sharing was performed. Otherwise C_ERR\n * is returned. */\nint sentinelTryConnectionSharing(sentinelRedisInstance *ri) {\n    serverAssert(ri->flags & SRI_SENTINEL);\n    dictIterator *di;\n    dictEntry *de;\n\n    if (ri->runid == NULL) return C_ERR; /* No way to identify it. */\n    if (ri->link->refcount > 1) return C_ERR; /* Already shared. */\n\n    di = dictGetIterator(sentinel.masters);\n    while((de = dictNext(di)) != NULL) {\n        sentinelRedisInstance *master = dictGetVal(de), *match;\n        /* We want to share with the same physical Sentinel referenced\n         * in other masters, so skip our master. */\n        if (master == ri->master) continue;\n        match = getSentinelRedisInstanceByAddrAndRunID(master->sentinels,\n                                                       NULL,0,ri->runid);\n        if (match == NULL) continue; /* No match. */\n        if (match == ri) continue; /* Should never happen but... safer. */\n\n        /* We identified a matching Sentinel, great! Let's free our link\n         * and use the one of the matching Sentinel. */\n        releaseInstanceLink(ri->link,NULL);\n        ri->link = match->link;\n        match->link->refcount++;\n        return C_OK;\n    }\n    dictReleaseIterator(di);\n    return C_ERR;\n}\n\n/* When we detect a Sentinel to switch address (reporting a different IP/port\n * pair in Hello messages), let's update all the matching Sentinels in the\n * context of other masters as well and disconnect the links, so that everybody\n * will be updated.\n *\n * Return the number of updated Sentinel addresses. */\nint sentinelUpdateSentinelAddressInAllMasters(sentinelRedisInstance *ri) {\n    serverAssert(ri->flags & SRI_SENTINEL);\n    dictIterator *di;\n    dictEntry *de;\n    int reconfigured = 0;\n\n    di = dictGetIterator(sentinel.masters);\n    while((de = dictNext(di)) != NULL) {\n        sentinelRedisInstance *master = dictGetVal(de), *match;\n        match = getSentinelRedisInstanceByAddrAndRunID(master->sentinels,\n                                                       NULL,0,ri->runid);\n        /* If there is no match, this master does not know about this\n         * Sentinel, try with the next one. */\n        if (match == NULL) continue;\n\n        /* Disconnect the old links if connected. */\n        if (match->link->cc != NULL)\n            instanceLinkCloseConnection(match->link,match->link->cc);\n        if (match->link->pc != NULL)\n            instanceLinkCloseConnection(match->link,match->link->pc);\n\n        if (match == ri) continue; /* Address already updated for it. */\n\n        /* Update the address of the matching Sentinel by copying the address\n         * of the Sentinel object that received the address update. */\n        releaseSentinelAddr(match->addr);\n        match->addr = dupSentinelAddr(ri->addr);\n        reconfigured++;\n    }\n    dictReleaseIterator(di);\n    if (reconfigured)\n        sentinelEvent(LL_NOTICE,\"+sentinel-address-update\", ri,\n                    \"%@ %d additional matching instances\", reconfigured);\n    return reconfigured;\n}\n\n/* This function is called when an hiredis connection reported an error.\n * We set it to NULL and mark the link as disconnected so that it will be\n * reconnected again.\n *\n * Note: we don't free the hiredis context as hiredis will do it for us\n * for async connections. */\nvoid instanceLinkConnectionError(const redisAsyncContext *c) {\n    instanceLink *link = c->data;\n    int pubsub;\n\n    if (!link) return;\n\n    pubsub = (link->pc == c);\n    if (pubsub)\n        link->pc = NULL;\n    else\n        link->cc = NULL;\n    link->disconnected = 1;\n}\n\n/* Hiredis connection established / disconnected callbacks. We need them\n * just to cleanup our link state. */\nvoid sentinelLinkEstablishedCallback(const redisAsyncContext *c, int status) {\n    if (status != C_OK) instanceLinkConnectionError(c);\n}\n\nvoid sentinelDisconnectCallback(const redisAsyncContext *c, int status) {\n    UNUSED(status);\n    instanceLinkConnectionError(c);\n}\n\n/* ========================== sentinelRedisInstance ========================= */\n\n/* Create a redis instance, the following fields must be populated by the\n * caller if needed:\n * runid: set to NULL but will be populated once INFO output is received.\n * info_refresh: is set to 0 to mean that we never received INFO so far.\n *\n * If SRI_MASTER is set into initial flags the instance is added to\n * sentinel.masters table.\n *\n * if SRI_SLAVE or SRI_SENTINEL is set then 'master' must be not NULL and the\n * instance is added into master->slaves or master->sentinels table.\n *\n * If the instance is a slave or sentinel, the name parameter is ignored and\n * is created automatically as hostname:port.\n *\n * The function fails if hostname can't be resolved or port is out of range.\n * When this happens NULL is returned and errno is set accordingly to the\n * createSentinelAddr() function.\n *\n * The function may also fail and return NULL with errno set to EBUSY if\n * a master with the same name, a slave with the same address, or a sentinel\n * with the same ID already exists. */\n\nsentinelRedisInstance *createSentinelRedisInstance(char *name, int flags, char *hostname, int port, int quorum, sentinelRedisInstance *master) {\n    sentinelRedisInstance *ri;\n    sentinelAddr *addr;\n    dict *table = NULL;\n    char slavename[NET_PEER_ID_LEN], *sdsname;\n\n    serverAssert(flags & (SRI_MASTER|SRI_SLAVE|SRI_SENTINEL));\n    serverAssert((flags & SRI_MASTER) || master != NULL);\n\n    /* Check address validity. */\n    addr = createSentinelAddr(hostname,port);\n    if (addr == NULL) return NULL;\n\n    /* For slaves use ip:port as name. */\n    if (flags & SRI_SLAVE) {\n        anetFormatAddr(slavename, sizeof(slavename), hostname, port);\n        name = slavename;\n    }\n\n    /* Make sure the entry is not duplicated. This may happen when the same\n     * name for a master is used multiple times inside the configuration or\n     * if we try to add multiple times a slave or sentinel with same ip/port\n     * to a master. */\n    if (flags & SRI_MASTER) table = sentinel.masters;\n    else if (flags & SRI_SLAVE) table = master->slaves;\n    else if (flags & SRI_SENTINEL) table = master->sentinels;\n    sdsname = sdsnew(name);\n    if (dictFind(table,sdsname)) {\n        releaseSentinelAddr(addr);\n        sdsfree(sdsname);\n        errno = EBUSY;\n        return NULL;\n    }\n\n    /* Create the instance object. */\n    ri = zmalloc(sizeof(*ri));\n    /* Note that all the instances are started in the disconnected state,\n     * the event loop will take care of connecting them. */\n    ri->flags = flags;\n    ri->name = sdsname;\n    ri->runid = NULL;\n    ri->config_epoch = 0;\n    ri->addr = addr;\n    ri->link = createInstanceLink();\n    ri->last_pub_time = mstime();\n    ri->last_hello_time = mstime();\n    ri->last_master_down_reply_time = mstime();\n    ri->s_down_since_time = 0;\n    ri->o_down_since_time = 0;\n    ri->down_after_period = master ? master->down_after_period :\n                            SENTINEL_DEFAULT_DOWN_AFTER;\n    ri->master_link_down_time = 0;\n    ri->auth_pass = NULL;\n    ri->slave_priority = SENTINEL_DEFAULT_SLAVE_PRIORITY;\n    ri->slave_reconf_sent_time = 0;\n    ri->slave_master_host = NULL;\n    ri->slave_master_port = 0;\n    ri->slave_master_link_status = SENTINEL_MASTER_LINK_STATUS_DOWN;\n    ri->slave_repl_offset = 0;\n    ri->sentinels = dictCreate(&instancesDictType,NULL);\n    ri->quorum = quorum;\n    ri->parallel_syncs = SENTINEL_DEFAULT_PARALLEL_SYNCS;\n    ri->master = master;\n    ri->slaves = dictCreate(&instancesDictType,NULL);\n    ri->info_refresh = 0;\n\n    /* Failover state. */\n    ri->leader = NULL;\n    ri->leader_epoch = 0;\n    ri->failover_epoch = 0;\n    ri->failover_state = SENTINEL_FAILOVER_STATE_NONE;\n    ri->failover_state_change_time = 0;\n    ri->failover_start_time = 0;\n    ri->failover_timeout = SENTINEL_DEFAULT_FAILOVER_TIMEOUT;\n    ri->failover_delay_logged = 0;\n    ri->promoted_slave = NULL;\n    ri->notification_script = NULL;\n    ri->client_reconfig_script = NULL;\n    ri->info = NULL;\n\n    /* Role */\n    ri->role_reported = ri->flags & (SRI_MASTER|SRI_SLAVE);\n    ri->role_reported_time = mstime();\n    ri->slave_conf_change_time = mstime();\n\n    /* Add into the right table. */\n    dictAdd(table, ri->name, ri);\n    return ri;\n}\n\n/* Release this instance and all its slaves, sentinels, hiredis connections.\n * This function does not take care of unlinking the instance from the main\n * masters table (if it is a master) or from its master sentinels/slaves table\n * if it is a slave or sentinel. */\nvoid releaseSentinelRedisInstance(sentinelRedisInstance *ri) {\n    /* Release all its slaves or sentinels if any. */\n    dictRelease(ri->sentinels);\n    dictRelease(ri->slaves);\n\n    /* Disconnect the instance. */\n    releaseInstanceLink(ri->link,ri);\n\n    /* Free other resources. */\n    sdsfree(ri->name);\n    sdsfree(ri->runid);\n    sdsfree(ri->notification_script);\n    sdsfree(ri->client_reconfig_script);\n    sdsfree(ri->slave_master_host);\n    sdsfree(ri->leader);\n    sdsfree(ri->auth_pass);\n    sdsfree(ri->info);\n    releaseSentinelAddr(ri->addr);\n\n    /* Clear state into the master if needed. */\n    if ((ri->flags & SRI_SLAVE) && (ri->flags & SRI_PROMOTED) && ri->master)\n        ri->master->promoted_slave = NULL;\n\n    zfree(ri);\n}\n\n/* Lookup a slave in a master Redis instance, by ip and port. */\nsentinelRedisInstance *sentinelRedisInstanceLookupSlave(\n                sentinelRedisInstance *ri, char *ip, int port)\n{\n    sds key;\n    sentinelRedisInstance *slave;\n    char buf[NET_PEER_ID_LEN];\n\n    serverAssert(ri->flags & SRI_MASTER);\n    anetFormatAddr(buf,sizeof(buf),ip,port);\n    key = sdsnew(buf);\n    slave = dictFetchValue(ri->slaves,key);\n    sdsfree(key);\n    return slave;\n}\n\n/* Return the name of the type of the instance as a string. */\nconst char *sentinelRedisInstanceTypeStr(sentinelRedisInstance *ri) {\n    if (ri->flags & SRI_MASTER) return \"master\";\n    else if (ri->flags & SRI_SLAVE) return \"slave\";\n    else if (ri->flags & SRI_SENTINEL) return \"sentinel\";\n    else return \"unknown\";\n}\n\n/* This function remove the Sentinel with the specified ID from the\n * specified master.\n *\n * If \"runid\" is NULL the function returns ASAP.\n *\n * This function is useful because on Sentinels address switch, we want to\n * remove our old entry and add a new one for the same ID but with the new\n * address.\n *\n * The function returns 1 if the matching Sentinel was removed, otherwise\n * 0 if there was no Sentinel with this ID. */\nint removeMatchingSentinelFromMaster(sentinelRedisInstance *master, char *runid) {\n    dictIterator *di;\n    dictEntry *de;\n    int removed = 0;\n\n    if (runid == NULL) return 0;\n\n    di = dictGetSafeIterator(master->sentinels);\n    while((de = dictNext(di)) != NULL) {\n        sentinelRedisInstance *ri = dictGetVal(de);\n\n        if (ri->runid && strcmp(ri->runid,runid) == 0) {\n            dictDelete(master->sentinels,ri->name);\n            removed++;\n        }\n    }\n    dictReleaseIterator(di);\n    return removed;\n}\n\n/* Search an instance with the same runid, ip and port into a dictionary\n * of instances. Return NULL if not found, otherwise return the instance\n * pointer.\n *\n * runid or ip can be NULL. In such a case the search is performed only\n * by the non-NULL field. */\nsentinelRedisInstance *getSentinelRedisInstanceByAddrAndRunID(dict *instances, char *ip, int port, char *runid) {\n    dictIterator *di;\n    dictEntry *de;\n    sentinelRedisInstance *instance = NULL;\n\n    serverAssert(ip || runid);   /* User must pass at least one search param. */\n    di = dictGetIterator(instances);\n    while((de = dictNext(di)) != NULL) {\n        sentinelRedisInstance *ri = dictGetVal(de);\n\n        if (runid && !ri->runid) continue;\n        if ((runid == NULL || strcmp(ri->runid, runid) == 0) &&\n            (ip == NULL || (strcmp(ri->addr->ip, ip) == 0 &&\n                            ri->addr->port == port)))\n        {\n            instance = ri;\n            break;\n        }\n    }\n    dictReleaseIterator(di);\n    return instance;\n}\n\n/* Master lookup by name */\nsentinelRedisInstance *sentinelGetMasterByName(char *name) {\n    sentinelRedisInstance *ri;\n    sds sdsname = sdsnew(name);\n\n    ri = dictFetchValue(sentinel.masters,sdsname);\n    sdsfree(sdsname);\n    return ri;\n}\n\n/* Add the specified flags to all the instances in the specified dictionary. */\nvoid sentinelAddFlagsToDictOfRedisInstances(dict *instances, int flags) {\n    dictIterator *di;\n    dictEntry *de;\n\n    di = dictGetIterator(instances);\n    while((de = dictNext(di)) != NULL) {\n        sentinelRedisInstance *ri = dictGetVal(de);\n        ri->flags |= flags;\n    }\n    dictReleaseIterator(di);\n}\n\n/* Remove the specified flags to all the instances in the specified\n * dictionary. */\nvoid sentinelDelFlagsToDictOfRedisInstances(dict *instances, int flags) {\n    dictIterator *di;\n    dictEntry *de;\n\n    di = dictGetIterator(instances);\n    while((de = dictNext(di)) != NULL) {\n        sentinelRedisInstance *ri = dictGetVal(de);\n        ri->flags &= ~flags;\n    }\n    dictReleaseIterator(di);\n}\n\n/* Reset the state of a monitored master:\n * 1) Remove all slaves.\n * 2) Remove all sentinels.\n * 3) Remove most of the flags resulting from runtime operations.\n * 4) Reset timers to their default value. For example after a reset it will be\n *    possible to failover again the same master ASAP, without waiting the\n *    failover timeout delay.\n * 5) In the process of doing this undo the failover if in progress.\n * 6) Disconnect the connections with the master (will reconnect automatically).\n */\n\n#define SENTINEL_RESET_NO_SENTINELS (1<<0)\nvoid sentinelResetMaster(sentinelRedisInstance *ri, int flags) {\n    serverAssert(ri->flags & SRI_MASTER);\n    dictRelease(ri->slaves);\n    ri->slaves = dictCreate(&instancesDictType,NULL);\n    if (!(flags & SENTINEL_RESET_NO_SENTINELS)) {\n        dictRelease(ri->sentinels);\n        ri->sentinels = dictCreate(&instancesDictType,NULL);\n    }\n    instanceLinkCloseConnection(ri->link,ri->link->cc);\n    instanceLinkCloseConnection(ri->link,ri->link->pc);\n    ri->flags &= SRI_MASTER;\n    if (ri->leader) {\n        sdsfree(ri->leader);\n        ri->leader = NULL;\n    }\n    ri->failover_state = SENTINEL_FAILOVER_STATE_NONE;\n    ri->failover_state_change_time = 0;\n    ri->failover_start_time = 0; /* We can failover again ASAP. */\n    ri->promoted_slave = NULL;\n    sdsfree(ri->runid);\n    sdsfree(ri->slave_master_host);\n    ri->runid = NULL;\n    ri->slave_master_host = NULL;\n    ri->link->act_ping_time = mstime();\n    ri->link->last_ping_time = 0;\n    ri->link->last_avail_time = mstime();\n    ri->link->last_pong_time = mstime();\n    ri->role_reported_time = mstime();\n    ri->role_reported = SRI_MASTER;\n    if (flags & SENTINEL_GENERATE_EVENT)\n        sentinelEvent(LL_WARNING,\"+reset-master\",ri,\"%@\");\n}\n\n/* Call sentinelResetMaster() on every master with a name matching the specified\n * pattern. */\nint sentinelResetMastersByPattern(char *pattern, int flags) {\n    dictIterator *di;\n    dictEntry *de;\n    int reset = 0;\n\n    di = dictGetIterator(sentinel.masters);\n    while((de = dictNext(di)) != NULL) {\n        sentinelRedisInstance *ri = dictGetVal(de);\n\n        if (ri->name) {\n            if (stringmatch(pattern,ri->name,0)) {\n                sentinelResetMaster(ri,flags);\n                reset++;\n            }\n        }\n    }\n    dictReleaseIterator(di);\n    return reset;\n}\n\n/* Reset the specified master with sentinelResetMaster(), and also change\n * the ip:port address, but take the name of the instance unmodified.\n *\n * This is used to handle the +switch-master event.\n *\n * The function returns C_ERR if the address can't be resolved for some\n * reason. Otherwise C_OK is returned.  */\nint sentinelResetMasterAndChangeAddress(sentinelRedisInstance *master, char *ip, int port) {\n    sentinelAddr *oldaddr, *newaddr;\n    sentinelAddr **slaves = NULL;\n    int numslaves = 0, j;\n    dictIterator *di;\n    dictEntry *de;\n\n    newaddr = createSentinelAddr(ip,port);\n    if (newaddr == NULL) return C_ERR;\n\n    /* Make a list of slaves to add back after the reset.\n     * Don't include the one having the address we are switching to. */\n    di = dictGetIterator(master->slaves);\n    while((de = dictNext(di)) != NULL) {\n        sentinelRedisInstance *slave = dictGetVal(de);\n\n        if (sentinelAddrIsEqual(slave->addr,newaddr)) continue;\n        slaves = zrealloc(slaves,sizeof(sentinelAddr*)*(numslaves+1));\n        slaves[numslaves++] = createSentinelAddr(slave->addr->ip,\n                                                 slave->addr->port);\n    }\n    dictReleaseIterator(di);\n\n    /* If we are switching to a different address, include the old address\n     * as a slave as well, so that we'll be able to sense / reconfigure\n     * the old master. */\n    if (!sentinelAddrIsEqual(newaddr,master->addr)) {\n        slaves = zrealloc(slaves,sizeof(sentinelAddr*)*(numslaves+1));\n        slaves[numslaves++] = createSentinelAddr(master->addr->ip,\n                                                 master->addr->port);\n    }\n\n    /* Reset and switch address. */\n    sentinelResetMaster(master,SENTINEL_RESET_NO_SENTINELS);\n    oldaddr = master->addr;\n    master->addr = newaddr;\n    master->o_down_since_time = 0;\n    master->s_down_since_time = 0;\n\n    /* Add slaves back. */\n    for (j = 0; j < numslaves; j++) {\n        sentinelRedisInstance *slave;\n\n        slave = createSentinelRedisInstance(NULL,SRI_SLAVE,slaves[j]->ip,\n                    slaves[j]->port, master->quorum, master);\n        releaseSentinelAddr(slaves[j]);\n        if (slave) sentinelEvent(LL_NOTICE,\"+slave\",slave,\"%@\");\n    }\n    zfree(slaves);\n\n    /* Release the old address at the end so we are safe even if the function\n     * gets the master->addr->ip and master->addr->port as arguments. */\n    releaseSentinelAddr(oldaddr);\n    sentinelFlushConfig();\n    return C_OK;\n}\n\n/* Return non-zero if there was no SDOWN or ODOWN error associated to this\n * instance in the latest 'ms' milliseconds. */\nint sentinelRedisInstanceNoDownFor(sentinelRedisInstance *ri, mstime_t ms) {\n    mstime_t most_recent;\n\n    most_recent = ri->s_down_since_time;\n    if (ri->o_down_since_time > most_recent)\n        most_recent = ri->o_down_since_time;\n    return most_recent == 0 || (mstime() - most_recent) > ms;\n}\n\n/* Return the current master address, that is, its address or the address\n * of the promoted slave if already operational. */\nsentinelAddr *sentinelGetCurrentMasterAddress(sentinelRedisInstance *master) {\n    /* If we are failing over the master, and the state is already\n     * SENTINEL_FAILOVER_STATE_RECONF_SLAVES or greater, it means that we\n     * already have the new configuration epoch in the master, and the\n     * slave acknowledged the configuration switch. Advertise the new\n     * address. */\n    if ((master->flags & SRI_FAILOVER_IN_PROGRESS) &&\n        master->promoted_slave &&\n        master->failover_state >= SENTINEL_FAILOVER_STATE_RECONF_SLAVES)\n    {\n        return master->promoted_slave->addr;\n    } else {\n        return master->addr;\n    }\n}\n\n/* This function sets the down_after_period field value in 'master' to all\n * the slaves and sentinel instances connected to this master. */\nvoid sentinelPropagateDownAfterPeriod(sentinelRedisInstance *master) {\n    dictIterator *di;\n    dictEntry *de;\n    int j;\n    dict *d[] = {master->slaves, master->sentinels, NULL};\n\n    for (j = 0; d[j]; j++) {\n        di = dictGetIterator(d[j]);\n        while((de = dictNext(di)) != NULL) {\n            sentinelRedisInstance *ri = dictGetVal(de);\n            ri->down_after_period = master->down_after_period;\n        }\n        dictReleaseIterator(di);\n    }\n}\n\nchar *sentinelGetInstanceTypeString(sentinelRedisInstance *ri) {\n    if (ri->flags & SRI_MASTER) return \"master\";\n    else if (ri->flags & SRI_SLAVE) return \"slave\";\n    else if (ri->flags & SRI_SENTINEL) return \"sentinel\";\n    else return \"unknown\";\n}\n\n/* ============================ Config handling ============================= */\nchar *sentinelHandleConfiguration(char **argv, int argc) {\n    sentinelRedisInstance *ri;\n\n    if (!strcasecmp(argv[0],\"monitor\") && argc == 5) {\n        /* monitor <name> <host> <port> <quorum> */\n        int quorum = atoi(argv[4]);\n\n        if (quorum <= 0) return \"Quorum must be 1 or greater.\";\n        if (createSentinelRedisInstance(argv[1],SRI_MASTER,argv[2],\n                                        atoi(argv[3]),quorum,NULL) == NULL)\n        {\n            switch(errno) {\n            case EBUSY: return \"Duplicated master name.\";\n            case ENOENT: return \"Can't resolve master instance hostname.\";\n            case EINVAL: return \"Invalid port number\";\n            }\n        }\n    } else if (!strcasecmp(argv[0],\"down-after-milliseconds\") && argc == 3) {\n        /* down-after-milliseconds <name> <milliseconds> */\n        ri = sentinelGetMasterByName(argv[1]);\n        if (!ri) return \"No such master with specified name.\";\n        ri->down_after_period = atoi(argv[2]);\n        if (ri->down_after_period <= 0)\n            return \"negative or zero time parameter.\";\n        sentinelPropagateDownAfterPeriod(ri);\n    } else if (!strcasecmp(argv[0],\"failover-timeout\") && argc == 3) {\n        /* failover-timeout <name> <milliseconds> */\n        ri = sentinelGetMasterByName(argv[1]);\n        if (!ri) return \"No such master with specified name.\";\n        ri->failover_timeout = atoi(argv[2]);\n        if (ri->failover_timeout <= 0)\n            return \"negative or zero time parameter.\";\n   } else if (!strcasecmp(argv[0],\"parallel-syncs\") && argc == 3) {\n        /* parallel-syncs <name> <milliseconds> */\n        ri = sentinelGetMasterByName(argv[1]);\n        if (!ri) return \"No such master with specified name.\";\n        ri->parallel_syncs = atoi(argv[2]);\n   } else if (!strcasecmp(argv[0],\"notification-script\") && argc == 3) {\n        /* notification-script <name> <path> */\n        ri = sentinelGetMasterByName(argv[1]);\n        if (!ri) return \"No such master with specified name.\";\n        if (access(argv[2],X_OK) == -1)\n            return \"Notification script seems non existing or non executable.\";\n        ri->notification_script = sdsnew(argv[2]);\n   } else if (!strcasecmp(argv[0],\"client-reconfig-script\") && argc == 3) {\n        /* client-reconfig-script <name> <path> */\n        ri = sentinelGetMasterByName(argv[1]);\n        if (!ri) return \"No such master with specified name.\";\n        if (access(argv[2],X_OK) == -1)\n            return \"Client reconfiguration script seems non existing or \"\n                   \"non executable.\";\n        ri->client_reconfig_script = sdsnew(argv[2]);\n   } else if (!strcasecmp(argv[0],\"auth-pass\") && argc == 3) {\n        /* auth-pass <name> <password> */\n        ri = sentinelGetMasterByName(argv[1]);\n        if (!ri) return \"No such master with specified name.\";\n        ri->auth_pass = sdsnew(argv[2]);\n    } else if (!strcasecmp(argv[0],\"current-epoch\") && argc == 2) {\n        /* current-epoch <epoch> */\n        unsigned long long current_epoch = strtoull(argv[1],NULL,10);\n        if (current_epoch > sentinel.current_epoch)\n            sentinel.current_epoch = current_epoch;\n    } else if (!strcasecmp(argv[0],\"myid\") && argc == 2) {\n        if (strlen(argv[1]) != CONFIG_RUN_ID_SIZE)\n            return \"Malformed Sentinel id in myid option.\";\n        memcpy(sentinel.myid,argv[1],CONFIG_RUN_ID_SIZE);\n    } else if (!strcasecmp(argv[0],\"config-epoch\") && argc == 3) {\n        /* config-epoch <name> <epoch> */\n        ri = sentinelGetMasterByName(argv[1]);\n        if (!ri) return \"No such master with specified name.\";\n        ri->config_epoch = strtoull(argv[2],NULL,10);\n        /* The following update of current_epoch is not really useful as\n         * now the current epoch is persisted on the config file, but\n         * we leave this check here for redundancy. */\n        if (ri->config_epoch > sentinel.current_epoch)\n            sentinel.current_epoch = ri->config_epoch;\n    } else if (!strcasecmp(argv[0],\"leader-epoch\") && argc == 3) {\n        /* leader-epoch <name> <epoch> */\n        ri = sentinelGetMasterByName(argv[1]);\n        if (!ri) return \"No such master with specified name.\";\n        ri->leader_epoch = strtoull(argv[2],NULL,10);\n    } else if (!strcasecmp(argv[0],\"known-slave\") && argc == 4) {\n        sentinelRedisInstance *slave;\n\n        /* known-slave <name> <ip> <port> */\n        ri = sentinelGetMasterByName(argv[1]);\n        if (!ri) return \"No such master with specified name.\";\n        if ((slave = createSentinelRedisInstance(NULL,SRI_SLAVE,argv[2],\n                    atoi(argv[3]), ri->quorum, ri)) == NULL)\n        {\n            return \"Wrong hostname or port for slave.\";\n        }\n    } else if (!strcasecmp(argv[0],\"known-sentinel\") &&\n               (argc == 4 || argc == 5)) {\n        sentinelRedisInstance *si;\n\n        if (argc == 5) { /* Ignore the old form without runid. */\n            /* known-sentinel <name> <ip> <port> [runid] */\n            ri = sentinelGetMasterByName(argv[1]);\n            if (!ri) return \"No such master with specified name.\";\n            if ((si = createSentinelRedisInstance(argv[4],SRI_SENTINEL,argv[2],\n                        atoi(argv[3]), ri->quorum, ri)) == NULL)\n            {\n                return \"Wrong hostname or port for sentinel.\";\n            }\n            si->runid = sdsnew(argv[4]);\n            sentinelTryConnectionSharing(si);\n        }\n    } else if (!strcasecmp(argv[0],\"announce-ip\") && argc == 2) {\n        /* announce-ip <ip-address> */\n        if (strlen(argv[1]))\n            sentinel.announce_ip = sdsnew(argv[1]);\n    } else if (!strcasecmp(argv[0],\"announce-port\") && argc == 2) {\n        /* announce-port <port> */\n        sentinel.announce_port = atoi(argv[1]);\n    } else {\n        return \"Unrecognized sentinel configuration statement.\";\n    }\n    return NULL;\n}\n\n/* Implements CONFIG REWRITE for \"sentinel\" option.\n * This is used not just to rewrite the configuration given by the user\n * (the configured masters) but also in order to retain the state of\n * Sentinel across restarts: config epoch of masters, associated slaves\n * and sentinel instances, and so forth. */\nvoid rewriteConfigSentinelOption(struct rewriteConfigState *state) {\n    dictIterator *di, *di2;\n    dictEntry *de;\n    sds line;\n\n    /* sentinel unique ID. */\n    line = sdscatprintf(sdsempty(), \"sentinel myid %s\", sentinel.myid);\n    rewriteConfigRewriteLine(state,\"sentinel\",line,1);\n\n    /* For every master emit a \"sentinel monitor\" config entry. */\n    di = dictGetIterator(sentinel.masters);\n    while((de = dictNext(di)) != NULL) {\n        sentinelRedisInstance *master, *ri;\n        sentinelAddr *master_addr;\n\n        /* sentinel monitor */\n        master = dictGetVal(de);\n        master_addr = sentinelGetCurrentMasterAddress(master);\n        line = sdscatprintf(sdsempty(),\"sentinel monitor %s %s %d %d\",\n            master->name, master_addr->ip, master_addr->port,\n            master->quorum);\n        rewriteConfigRewriteLine(state,\"sentinel\",line,1);\n\n        /* sentinel down-after-milliseconds */\n        if (master->down_after_period != SENTINEL_DEFAULT_DOWN_AFTER) {\n            line = sdscatprintf(sdsempty(),\n                \"sentinel down-after-milliseconds %s %ld\",\n                master->name, (long) master->down_after_period);\n            rewriteConfigRewriteLine(state,\"sentinel\",line,1);\n        }\n\n        /* sentinel failover-timeout */\n        if (master->failover_timeout != SENTINEL_DEFAULT_FAILOVER_TIMEOUT) {\n            line = sdscatprintf(sdsempty(),\n                \"sentinel failover-timeout %s %ld\",\n                master->name, (long) master->failover_timeout);\n            rewriteConfigRewriteLine(state,\"sentinel\",line,1);\n        }\n\n        /* sentinel parallel-syncs */\n        if (master->parallel_syncs != SENTINEL_DEFAULT_PARALLEL_SYNCS) {\n            line = sdscatprintf(sdsempty(),\n                \"sentinel parallel-syncs %s %d\",\n                master->name, master->parallel_syncs);\n            rewriteConfigRewriteLine(state,\"sentinel\",line,1);\n        }\n\n        /* sentinel notification-script */\n        if (master->notification_script) {\n            line = sdscatprintf(sdsempty(),\n                \"sentinel notification-script %s %s\",\n                master->name, master->notification_script);\n            rewriteConfigRewriteLine(state,\"sentinel\",line,1);\n        }\n\n        /* sentinel client-reconfig-script */\n        if (master->client_reconfig_script) {\n            line = sdscatprintf(sdsempty(),\n                \"sentinel client-reconfig-script %s %s\",\n                master->name, master->client_reconfig_script);\n            rewriteConfigRewriteLine(state,\"sentinel\",line,1);\n        }\n\n        /* sentinel auth-pass */\n        if (master->auth_pass) {\n            line = sdscatprintf(sdsempty(),\n                \"sentinel auth-pass %s %s\",\n                master->name, master->auth_pass);\n            rewriteConfigRewriteLine(state,\"sentinel\",line,1);\n        }\n\n        /* sentinel config-epoch */\n        line = sdscatprintf(sdsempty(),\n            \"sentinel config-epoch %s %llu\",\n            master->name, (unsigned long long) master->config_epoch);\n        rewriteConfigRewriteLine(state,\"sentinel\",line,1);\n\n        /* sentinel leader-epoch */\n        line = sdscatprintf(sdsempty(),\n            \"sentinel leader-epoch %s %llu\",\n            master->name, (unsigned long long) master->leader_epoch);\n        rewriteConfigRewriteLine(state,\"sentinel\",line,1);\n\n        /* sentinel known-slave */\n        di2 = dictGetIterator(master->slaves);\n        while((de = dictNext(di2)) != NULL) {\n            sentinelAddr *slave_addr;\n\n            ri = dictGetVal(de);\n            slave_addr = ri->addr;\n\n            /* If master_addr (obtained using sentinelGetCurrentMasterAddress()\n             * so it may be the address of the promoted slave) is equal to this\n             * slave's address, a failover is in progress and the slave was\n             * already successfully promoted. So as the address of this slave\n             * we use the old master address instead. */\n            if (sentinelAddrIsEqual(slave_addr,master_addr))\n                slave_addr = master->addr;\n            line = sdscatprintf(sdsempty(),\n                \"sentinel known-slave %s %s %d\",\n                master->name, slave_addr->ip, slave_addr->port);\n            rewriteConfigRewriteLine(state,\"sentinel\",line,1);\n        }\n        dictReleaseIterator(di2);\n\n        /* sentinel known-sentinel */\n        di2 = dictGetIterator(master->sentinels);\n        while((de = dictNext(di2)) != NULL) {\n            ri = dictGetVal(de);\n            if (ri->runid == NULL) continue;\n            line = sdscatprintf(sdsempty(),\n                \"sentinel known-sentinel %s %s %d %s\",\n                master->name, ri->addr->ip, ri->addr->port, ri->runid);\n            rewriteConfigRewriteLine(state,\"sentinel\",line,1);\n        }\n        dictReleaseIterator(di2);\n    }\n\n    /* sentinel current-epoch is a global state valid for all the masters. */\n    line = sdscatprintf(sdsempty(),\n        \"sentinel current-epoch %llu\", (unsigned long long) sentinel.current_epoch);\n    rewriteConfigRewriteLine(state,\"sentinel\",line,1);\n\n    /* sentinel announce-ip. */\n    if (sentinel.announce_ip) {\n        line = sdsnew(\"sentinel announce-ip \");\n        line = sdscatrepr(line, sentinel.announce_ip, sdslen(sentinel.announce_ip));\n        rewriteConfigRewriteLine(state,\"sentinel\",line,1);\n    }\n\n    /* sentinel announce-port. */\n    if (sentinel.announce_port) {\n        line = sdscatprintf(sdsempty(),\"sentinel announce-port %d\",\n                            sentinel.announce_port);\n        rewriteConfigRewriteLine(state,\"sentinel\",line,1);\n    }\n\n    dictReleaseIterator(di);\n}\n\n/* This function uses the config rewriting Redis engine in order to persist\n * the state of the Sentinel in the current configuration file.\n *\n * Before returning the function calls fsync() against the generated\n * configuration file to make sure changes are committed to disk.\n *\n * On failure the function logs a warning on the Redis log. */\nvoid sentinelFlushConfig(void) {\n    int fd = -1;\n    int saved_hz = server.hz;\n    int rewrite_status;\n\n    server.hz = CONFIG_DEFAULT_HZ;\n    rewrite_status = rewriteConfig(server.configfile);\n    server.hz = saved_hz;\n\n    if (rewrite_status == -1) goto werr;\n    if ((fd = open(server.configfile,O_RDONLY)) == -1) goto werr;\n    if (fsync(fd) == -1) goto werr;\n    if (close(fd) == EOF) goto werr;\n    return;\n\nwerr:\n    if (fd != -1) close(fd);\n    serverLog(LL_WARNING,\"WARNING: Sentinel was not able to save the new configuration on disk!!!: %s\", strerror(errno));\n}\n\n/* ====================== hiredis connection handling ======================= */\n\n/* Send the AUTH command with the specified master password if needed.\n * Note that for slaves the password set for the master is used.\n *\n * We don't check at all if the command was successfully transmitted\n * to the instance as if it fails Sentinel will detect the instance down,\n * will disconnect and reconnect the link and so forth. */\nvoid sentinelSendAuthIfNeeded(sentinelRedisInstance *ri, redisAsyncContext *c) {\n    char *auth_pass = (ri->flags & SRI_MASTER) ? ri->auth_pass :\n                                                 ri->master->auth_pass;\n\n    if (auth_pass) {\n        if (redisAsyncCommand(c, sentinelDiscardReplyCallback, ri, \"AUTH %s\",\n            auth_pass) == C_OK) ri->link->pending_commands++;\n    }\n}\n\n/* Use CLIENT SETNAME to name the connection in the Redis instance as\n * sentinel-<first_8_chars_of_runid>-<connection_type>\n * The connection type is \"cmd\" or \"pubsub\" as specified by 'type'.\n *\n * This makes it possible to list all the sentinel instances connected\n * to a Redis servewr with CLIENT LIST, grepping for a specific name format. */\nvoid sentinelSetClientName(sentinelRedisInstance *ri, redisAsyncContext *c, char *type) {\n    char name[64];\n\n    snprintf(name,sizeof(name),\"sentinel-%.8s-%s\",sentinel.myid,type);\n    if (redisAsyncCommand(c, sentinelDiscardReplyCallback, ri,\n        \"CLIENT SETNAME %s\", name) == C_OK)\n    {\n        ri->link->pending_commands++;\n    }\n}\n\n/* Create the async connections for the instance link if the link\n * is disconnected. Note that link->disconnected is true even if just\n * one of the two links (commands and pub/sub) is missing. */\nvoid sentinelReconnectInstance(sentinelRedisInstance *ri) {\n    if (ri->link->disconnected == 0) return;\n    if (ri->addr->port == 0) return; /* port == 0 means invalid address. */\n    instanceLink *link = ri->link;\n    mstime_t now = mstime();\n\n    if (now - ri->link->last_reconn_time < SENTINEL_PING_PERIOD) return;\n    ri->link->last_reconn_time = now;\n\n    /* Commands connection. */\n    if (link->cc == NULL) {\n        link->cc = redisAsyncConnectBind(ri->addr->ip,ri->addr->port,NET_FIRST_BIND_ADDR);\n        if (link->cc->err) {\n            sentinelEvent(LL_DEBUG,\"-cmd-link-reconnection\",ri,\"%@ #%s\",\n                link->cc->errstr);\n            instanceLinkCloseConnection(link,link->cc);\n        } else {\n            link->pending_commands = 0;\n            link->cc_conn_time = mstime();\n            link->cc->data = link;\n            redisAeAttach(server.el,link->cc);\n            redisAsyncSetConnectCallback(link->cc,\n                    sentinelLinkEstablishedCallback);\n            redisAsyncSetDisconnectCallback(link->cc,\n                    sentinelDisconnectCallback);\n            sentinelSendAuthIfNeeded(ri,link->cc);\n            sentinelSetClientName(ri,link->cc,\"cmd\");\n\n            /* Send a PING ASAP when reconnecting. */\n            sentinelSendPing(ri);\n        }\n    }\n    /* Pub / Sub */\n    if ((ri->flags & (SRI_MASTER|SRI_SLAVE)) && link->pc == NULL) {\n        link->pc = redisAsyncConnectBind(ri->addr->ip,ri->addr->port,NET_FIRST_BIND_ADDR);\n        if (link->pc->err) {\n            sentinelEvent(LL_DEBUG,\"-pubsub-link-reconnection\",ri,\"%@ #%s\",\n                link->pc->errstr);\n            instanceLinkCloseConnection(link,link->pc);\n        } else {\n            int retval;\n\n            link->pc_conn_time = mstime();\n            link->pc->data = link;\n            redisAeAttach(server.el,link->pc);\n            redisAsyncSetConnectCallback(link->pc,\n                    sentinelLinkEstablishedCallback);\n            redisAsyncSetDisconnectCallback(link->pc,\n                    sentinelDisconnectCallback);\n            sentinelSendAuthIfNeeded(ri,link->pc);\n            sentinelSetClientName(ri,link->pc,\"pubsub\");\n            /* Now we subscribe to the Sentinels \"Hello\" channel. */\n            retval = redisAsyncCommand(link->pc,\n                sentinelReceiveHelloMessages, ri, \"SUBSCRIBE %s\",\n                    SENTINEL_HELLO_CHANNEL);\n            if (retval != C_OK) {\n                /* If we can't subscribe, the Pub/Sub connection is useless\n                 * and we can simply disconnect it and try again. */\n                instanceLinkCloseConnection(link,link->pc);\n                return;\n            }\n        }\n    }\n    /* Clear the disconnected status only if we have both the connections\n     * (or just the commands connection if this is a sentinel instance). */\n    if (link->cc && (ri->flags & SRI_SENTINEL || link->pc))\n        link->disconnected = 0;\n}\n\n/* ======================== Redis instances pinging  ======================== */\n\n/* Return true if master looks \"sane\", that is:\n * 1) It is actually a master in the current configuration.\n * 2) It reports itself as a master.\n * 3) It is not SDOWN or ODOWN.\n * 4) We obtained last INFO no more than two times the INFO period time ago. */\nint sentinelMasterLooksSane(sentinelRedisInstance *master) {\n    return\n        master->flags & SRI_MASTER &&\n        master->role_reported == SRI_MASTER &&\n        (master->flags & (SRI_S_DOWN|SRI_O_DOWN)) == 0 &&\n        (mstime() - master->info_refresh) < SENTINEL_INFO_PERIOD*2;\n}\n\n/* Process the INFO output from masters. */\nvoid sentinelRefreshInstanceInfo(sentinelRedisInstance *ri, const char *info) {\n    sds *lines;\n    int numlines, j;\n    int role = 0;\n\n    /* cache full INFO output for instance */\n    sdsfree(ri->info);\n    ri->info = sdsnew(info);\n\n    /* The following fields must be reset to a given value in the case they\n     * are not found at all in the INFO output. */\n    ri->master_link_down_time = 0;\n\n    /* Process line by line. */\n    lines = sdssplitlen(info,strlen(info),\"\\r\\n\",2,&numlines);\n    for (j = 0; j < numlines; j++) {\n        sentinelRedisInstance *slave;\n        sds l = lines[j];\n\n        /* run_id:<40 hex chars>*/\n        if (sdslen(l) >= 47 && !memcmp(l,\"run_id:\",7)) {\n            if (ri->runid == NULL) {\n                ri->runid = sdsnewlen(l+7,40);\n            } else {\n                if (strncmp(ri->runid,l+7,40) != 0) {\n                    sentinelEvent(LL_NOTICE,\"+reboot\",ri,\"%@\");\n                    sdsfree(ri->runid);\n                    ri->runid = sdsnewlen(l+7,40);\n                }\n            }\n        }\n\n        /* old versions: slave0:<ip>,<port>,<state>\n         * new versions: slave0:ip=127.0.0.1,port=9999,... */\n        if ((ri->flags & SRI_MASTER) &&\n            sdslen(l) >= 7 &&\n            !memcmp(l,\"slave\",5) && isdigit(l[5]))\n        {\n            char *ip, *port, *end;\n\n            if (strstr(l,\"ip=\") == NULL) {\n                /* Old format. */\n                ip = strchr(l,':'); if (!ip) continue;\n                ip++; /* Now ip points to start of ip address. */\n                port = strchr(ip,','); if (!port) continue;\n                *port = '\\0'; /* nul term for easy access. */\n                port++; /* Now port points to start of port number. */\n                end = strchr(port,','); if (!end) continue;\n                *end = '\\0'; /* nul term for easy access. */\n            } else {\n                /* New format. */\n                ip = strstr(l,\"ip=\"); if (!ip) continue;\n                ip += 3; /* Now ip points to start of ip address. */\n                port = strstr(l,\"port=\"); if (!port) continue;\n                port += 5; /* Now port points to start of port number. */\n                /* Nul term both fields for easy access. */\n                end = strchr(ip,','); if (end) *end = '\\0';\n                end = strchr(port,','); if (end) *end = '\\0';\n            }\n\n            /* Check if we already have this slave into our table,\n             * otherwise add it. */\n            if (sentinelRedisInstanceLookupSlave(ri,ip,atoi(port)) == NULL) {\n                if ((slave = createSentinelRedisInstance(NULL,SRI_SLAVE,ip,\n                            atoi(port), ri->quorum, ri)) != NULL)\n                {\n                    sentinelEvent(LL_NOTICE,\"+slave\",slave,\"%@\");\n                    sentinelFlushConfig();\n                }\n            }\n        }\n\n        /* master_link_down_since_seconds:<seconds> */\n        if (sdslen(l) >= 32 &&\n            !memcmp(l,\"master_link_down_since_seconds\",30))\n        {\n            ri->master_link_down_time = strtoll(l+31,NULL,10)*1000;\n        }\n\n        /* role:<role> */\n        if (!memcmp(l,\"role:master\",11)) role = SRI_MASTER;\n        else if (!memcmp(l,\"role:slave\",10)) role = SRI_SLAVE;\n\n        if (role == SRI_SLAVE) {\n            /* master_host:<host> */\n            if (sdslen(l) >= 12 && !memcmp(l,\"master_host:\",12)) {\n                if (ri->slave_master_host == NULL ||\n                    strcasecmp(l+12,ri->slave_master_host))\n                {\n                    sdsfree(ri->slave_master_host);\n                    ri->slave_master_host = sdsnew(l+12);\n                    ri->slave_conf_change_time = mstime();\n                }\n            }\n\n            /* master_port:<port> */\n            if (sdslen(l) >= 12 && !memcmp(l,\"master_port:\",12)) {\n                int slave_master_port = atoi(l+12);\n\n                if (ri->slave_master_port != slave_master_port) {\n                    ri->slave_master_port = slave_master_port;\n                    ri->slave_conf_change_time = mstime();\n                }\n            }\n\n            /* master_link_status:<status> */\n            if (sdslen(l) >= 19 && !memcmp(l,\"master_link_status:\",19)) {\n                ri->slave_master_link_status =\n                    (strcasecmp(l+19,\"up\") == 0) ?\n                    SENTINEL_MASTER_LINK_STATUS_UP :\n                    SENTINEL_MASTER_LINK_STATUS_DOWN;\n            }\n\n            /* slave_priority:<priority> */\n            if (sdslen(l) >= 15 && !memcmp(l,\"slave_priority:\",15))\n                ri->slave_priority = atoi(l+15);\n\n            /* slave_repl_offset:<offset> */\n            if (sdslen(l) >= 18 && !memcmp(l,\"slave_repl_offset:\",18))\n                ri->slave_repl_offset = strtoull(l+18,NULL,10);\n        }\n    }\n    ri->info_refresh = mstime();\n    sdsfreesplitres(lines,numlines);\n\n    /* ---------------------------- Acting half -----------------------------\n     * Some things will not happen if sentinel.tilt is true, but some will\n     * still be processed. */\n\n    /* Remember when the role changed. */\n    if (role != ri->role_reported) {\n        ri->role_reported_time = mstime();\n        ri->role_reported = role;\n        if (role == SRI_SLAVE) ri->slave_conf_change_time = mstime();\n        /* Log the event with +role-change if the new role is coherent or\n         * with -role-change if there is a mismatch with the current config. */\n        sentinelEvent(LL_VERBOSE,\n            ((ri->flags & (SRI_MASTER|SRI_SLAVE)) == role) ?\n            \"+role-change\" : \"-role-change\",\n            ri, \"%@ new reported role is %s\",\n            role == SRI_MASTER ? \"master\" : \"slave\",\n            ri->flags & SRI_MASTER ? \"master\" : \"slave\");\n    }\n\n    /* None of the following conditions are processed when in tilt mode, so\n     * return asap. */\n    if (sentinel.tilt) return;\n\n    /* Handle master -> slave role switch. */\n    if ((ri->flags & SRI_MASTER) && role == SRI_SLAVE) {\n        /* Nothing to do, but masters claiming to be slaves are\n         * considered to be unreachable by Sentinel, so eventually\n         * a failover will be triggered. */\n    }\n\n    /* Handle slave -> master role switch. */\n    if ((ri->flags & SRI_SLAVE) && role == SRI_MASTER) {\n        /* If this is a promoted slave we can change state to the\n         * failover state machine. */\n        if ((ri->flags & SRI_PROMOTED) &&\n            (ri->master->flags & SRI_FAILOVER_IN_PROGRESS) &&\n            (ri->master->failover_state ==\n                SENTINEL_FAILOVER_STATE_WAIT_PROMOTION))\n        {\n            /* Now that we are sure the slave was reconfigured as a master\n             * set the master configuration epoch to the epoch we won the\n             * election to perform this failover. This will force the other\n             * Sentinels to update their config (assuming there is not\n             * a newer one already available). */\n            ri->master->config_epoch = ri->master->failover_epoch;\n            ri->master->failover_state = SENTINEL_FAILOVER_STATE_RECONF_SLAVES;\n            ri->master->failover_state_change_time = mstime();\n            sentinelFlushConfig();\n            sentinelEvent(LL_WARNING,\"+promoted-slave\",ri,\"%@\");\n            if (sentinel.simfailure_flags &\n                SENTINEL_SIMFAILURE_CRASH_AFTER_PROMOTION)\n                sentinelSimFailureCrash();\n            sentinelEvent(LL_WARNING,\"+failover-state-reconf-slaves\",\n                ri->master,\"%@\");\n            sentinelCallClientReconfScript(ri->master,SENTINEL_LEADER,\n                \"start\",ri->master->addr,ri->addr);\n            sentinelForceHelloUpdateForMaster(ri->master);\n        } else {\n            /* A slave turned into a master. We want to force our view and\n             * reconfigure as slave. Wait some time after the change before\n             * going forward, to receive new configs if any. */\n            mstime_t wait_time = SENTINEL_PUBLISH_PERIOD*4;\n\n            if (!(ri->flags & SRI_PROMOTED) &&\n                 sentinelMasterLooksSane(ri->master) &&\n                 sentinelRedisInstanceNoDownFor(ri,wait_time) &&\n                 mstime() - ri->role_reported_time > wait_time)\n            {\n                int retval = sentinelSendSlaveOf(ri,\n                        ri->master->addr->ip,\n                        ri->master->addr->port);\n                if (retval == C_OK)\n                    sentinelEvent(LL_NOTICE,\"+convert-to-slave\",ri,\"%@\");\n            }\n        }\n    }\n\n    /* Handle slaves replicating to a different master address. */\n    if ((ri->flags & SRI_SLAVE) &&\n        role == SRI_SLAVE &&\n        (ri->slave_master_port != ri->master->addr->port ||\n         strcasecmp(ri->slave_master_host,ri->master->addr->ip)))\n    {\n        mstime_t wait_time = ri->master->failover_timeout;\n\n        /* Make sure the master is sane before reconfiguring this instance\n         * into a slave. */\n        if (sentinelMasterLooksSane(ri->master) &&\n            sentinelRedisInstanceNoDownFor(ri,wait_time) &&\n            mstime() - ri->slave_conf_change_time > wait_time)\n        {\n            int retval = sentinelSendSlaveOf(ri,\n                    ri->master->addr->ip,\n                    ri->master->addr->port);\n            if (retval == C_OK)\n                sentinelEvent(LL_NOTICE,\"+fix-slave-config\",ri,\"%@\");\n        }\n    }\n\n    /* Detect if the slave that is in the process of being reconfigured\n     * changed state. */\n    if ((ri->flags & SRI_SLAVE) && role == SRI_SLAVE &&\n        (ri->flags & (SRI_RECONF_SENT|SRI_RECONF_INPROG)))\n    {\n        /* SRI_RECONF_SENT -> SRI_RECONF_INPROG. */\n        if ((ri->flags & SRI_RECONF_SENT) &&\n            ri->slave_master_host &&\n            strcmp(ri->slave_master_host,\n                    ri->master->promoted_slave->addr->ip) == 0 &&\n            ri->slave_master_port == ri->master->promoted_slave->addr->port)\n        {\n            ri->flags &= ~SRI_RECONF_SENT;\n            ri->flags |= SRI_RECONF_INPROG;\n            sentinelEvent(LL_NOTICE,\"+slave-reconf-inprog\",ri,\"%@\");\n        }\n\n        /* SRI_RECONF_INPROG -> SRI_RECONF_DONE */\n        if ((ri->flags & SRI_RECONF_INPROG) &&\n            ri->slave_master_link_status == SENTINEL_MASTER_LINK_STATUS_UP)\n        {\n            ri->flags &= ~SRI_RECONF_INPROG;\n            ri->flags |= SRI_RECONF_DONE;\n            sentinelEvent(LL_NOTICE,\"+slave-reconf-done\",ri,\"%@\");\n        }\n    }\n}\n\nvoid sentinelInfoReplyCallback(redisAsyncContext *c, void *reply, void *privdata) {\n    sentinelRedisInstance *ri = privdata;\n    instanceLink *link = c->data;\n    redisReply *r;\n\n    if (!reply || !link) return;\n    link->pending_commands--;\n    r = reply;\n\n    if (r->type == REDIS_REPLY_STRING)\n        sentinelRefreshInstanceInfo(ri,r->str);\n}\n\n/* Just discard the reply. We use this when we are not monitoring the return\n * value of the command but its effects directly. */\nvoid sentinelDiscardReplyCallback(redisAsyncContext *c, void *reply, void *privdata) {\n    instanceLink *link = c->data;\n    UNUSED(reply);\n    UNUSED(privdata);\n\n    if (link) link->pending_commands--;\n}\n\nvoid sentinelPingReplyCallback(redisAsyncContext *c, void *reply, void *privdata) {\n    sentinelRedisInstance *ri = privdata;\n    instanceLink *link = c->data;\n    redisReply *r;\n\n    if (!reply || !link) return;\n    link->pending_commands--;\n    r = reply;\n\n    if (r->type == REDIS_REPLY_STATUS ||\n        r->type == REDIS_REPLY_ERROR) {\n        /* Update the \"instance available\" field only if this is an\n         * acceptable reply. */\n        if (strncmp(r->str,\"PONG\",4) == 0 ||\n            strncmp(r->str,\"LOADING\",7) == 0 ||\n            strncmp(r->str,\"MASTERDOWN\",10) == 0)\n        {\n            link->last_avail_time = mstime();\n            link->act_ping_time = 0; /* Flag the pong as received. */\n        } else {\n            /* Send a SCRIPT KILL command if the instance appears to be\n             * down because of a busy script. */\n            if (strncmp(r->str,\"BUSY\",4) == 0 &&\n                (ri->flags & SRI_S_DOWN) &&\n                !(ri->flags & SRI_SCRIPT_KILL_SENT))\n            {\n                if (redisAsyncCommand(ri->link->cc,\n                        sentinelDiscardReplyCallback, ri,\n                        \"SCRIPT KILL\") == C_OK)\n                    ri->link->pending_commands++;\n                ri->flags |= SRI_SCRIPT_KILL_SENT;\n            }\n        }\n    }\n    link->last_pong_time = mstime();\n}\n\n/* This is called when we get the reply about the PUBLISH command we send\n * to the master to advertise this sentinel. */\nvoid sentinelPublishReplyCallback(redisAsyncContext *c, void *reply, void *privdata) {\n    sentinelRedisInstance *ri = privdata;\n    instanceLink *link = c->data;\n    redisReply *r;\n\n    if (!reply || !link) return;\n    link->pending_commands--;\n    r = reply;\n\n    /* Only update pub_time if we actually published our message. Otherwise\n     * we'll retry again in 100 milliseconds. */\n    if (r->type != REDIS_REPLY_ERROR)\n        ri->last_pub_time = mstime();\n}\n\n/* Process an hello message received via Pub/Sub in master or slave instance,\n * or sent directly to this sentinel via the (fake) PUBLISH command of Sentinel.\n *\n * If the master name specified in the message is not known, the message is\n * discarded. */\nvoid sentinelProcessHelloMessage(char *hello, int hello_len) {\n    /* Format is composed of 8 tokens:\n     * 0=ip,1=port,2=runid,3=current_epoch,4=master_name,\n     * 5=master_ip,6=master_port,7=master_config_epoch. */\n    int numtokens, port, removed, master_port;\n    uint64_t current_epoch, master_config_epoch;\n    char **token = sdssplitlen(hello, hello_len, \",\", 1, &numtokens);\n    sentinelRedisInstance *si, *master;\n\n    if (numtokens == 8) {\n        /* Obtain a reference to the master this hello message is about */\n        master = sentinelGetMasterByName(token[4]);\n        if (!master) goto cleanup; /* Unknown master, skip the message. */\n\n        /* First, try to see if we already have this sentinel. */\n        port = atoi(token[1]);\n        master_port = atoi(token[6]);\n        si = getSentinelRedisInstanceByAddrAndRunID(\n                        master->sentinels,token[0],port,token[2]);\n        current_epoch = strtoull(token[3],NULL,10);\n        master_config_epoch = strtoull(token[7],NULL,10);\n\n        if (!si) {\n            /* If not, remove all the sentinels that have the same runid\n             * because there was an address change, and add the same Sentinel\n             * with the new address back. */\n            removed = removeMatchingSentinelFromMaster(master,token[2]);\n            if (removed) {\n                sentinelEvent(LL_NOTICE,\"+sentinel-address-switch\",master,\n                    \"%@ ip %s port %d for %s\", token[0],port,token[2]);\n            } else {\n                /* Check if there is another Sentinel with the same address this\n                 * new one is reporting. What we do if this happens is to set its\n                 * port to 0, to signal the address is invalid. We'll update it\n                 * later if we get an HELLO message. */\n                sentinelRedisInstance *other =\n                    getSentinelRedisInstanceByAddrAndRunID(\n                        master->sentinels, token[0],port,NULL);\n                if (other) {\n                    sentinelEvent(LL_NOTICE,\"+sentinel-invalid-addr\",other,\"%@\");\n                    other->addr->port = 0; /* It means: invalid address. */\n                    sentinelUpdateSentinelAddressInAllMasters(other);\n                }\n            }\n\n            /* Add the new sentinel. */\n            si = createSentinelRedisInstance(token[2],SRI_SENTINEL,\n                            token[0],port,master->quorum,master);\n\n            if (si) {\n                if (!removed) sentinelEvent(LL_NOTICE,\"+sentinel\",si,\"%@\");\n                /* The runid is NULL after a new instance creation and\n                 * for Sentinels we don't have a later chance to fill it,\n                 * so do it now. */\n                si->runid = sdsnew(token[2]);\n                sentinelTryConnectionSharing(si);\n                if (removed) sentinelUpdateSentinelAddressInAllMasters(si);\n                sentinelFlushConfig();\n            }\n        }\n\n        /* Update local current_epoch if received current_epoch is greater.*/\n        if (current_epoch > sentinel.current_epoch) {\n            sentinel.current_epoch = current_epoch;\n            sentinelFlushConfig();\n            sentinelEvent(LL_WARNING,\"+new-epoch\",master,\"%llu\",\n                (unsigned long long) sentinel.current_epoch);\n        }\n\n        /* Update master info if received configuration is newer. */\n        if (si && master->config_epoch < master_config_epoch) {\n            master->config_epoch = master_config_epoch;\n            if (master_port != master->addr->port ||\n                strcmp(master->addr->ip, token[5]))\n            {\n                sentinelAddr *old_addr;\n\n                sentinelEvent(LL_WARNING,\"+config-update-from\",si,\"%@\");\n                sentinelEvent(LL_WARNING,\"+switch-master\",\n                    master,\"%s %s %d %s %d\",\n                    master->name,\n                    master->addr->ip, master->addr->port,\n                    token[5], master_port);\n\n                old_addr = dupSentinelAddr(master->addr);\n                sentinelResetMasterAndChangeAddress(master, token[5], master_port);\n                sentinelCallClientReconfScript(master,\n                    SENTINEL_OBSERVER,\"start\",\n                    old_addr,master->addr);\n                releaseSentinelAddr(old_addr);\n            }\n        }\n\n        /* Update the state of the Sentinel. */\n        if (si) si->last_hello_time = mstime();\n    }\n\ncleanup:\n    sdsfreesplitres(token,numtokens);\n}\n\n\n/* This is our Pub/Sub callback for the Hello channel. It's useful in order\n * to discover other sentinels attached at the same master. */\nvoid sentinelReceiveHelloMessages(redisAsyncContext *c, void *reply, void *privdata) {\n    sentinelRedisInstance *ri = privdata;\n    redisReply *r;\n    UNUSED(c);\n\n    if (!reply || !ri) return;\n    r = reply;\n\n    /* Update the last activity in the pubsub channel. Note that since we\n     * receive our messages as well this timestamp can be used to detect\n     * if the link is probably disconnected even if it seems otherwise. */\n    ri->link->pc_last_activity = mstime();\n\n    /* Sanity check in the reply we expect, so that the code that follows\n     * can avoid to check for details. */\n    if (r->type != REDIS_REPLY_ARRAY ||\n        r->elements != 3 ||\n        r->element[0]->type != REDIS_REPLY_STRING ||\n        r->element[1]->type != REDIS_REPLY_STRING ||\n        r->element[2]->type != REDIS_REPLY_STRING ||\n        strcmp(r->element[0]->str,\"message\") != 0) return;\n\n    /* We are not interested in meeting ourselves */\n    if (strstr(r->element[2]->str,sentinel.myid) != NULL) return;\n\n    sentinelProcessHelloMessage(r->element[2]->str, r->element[2]->len);\n}\n\n/* Send an \"Hello\" message via Pub/Sub to the specified 'ri' Redis\n * instance in order to broadcast the current configuraiton for this\n * master, and to advertise the existence of this Sentinel at the same time.\n *\n * The message has the following format:\n *\n * sentinel_ip,sentinel_port,sentinel_runid,current_epoch,\n * master_name,master_ip,master_port,master_config_epoch.\n *\n * Returns C_OK if the PUBLISH was queued correctly, otherwise\n * C_ERR is returned. */\nint sentinelSendHello(sentinelRedisInstance *ri) {\n    char ip[NET_IP_STR_LEN];\n    char payload[NET_IP_STR_LEN+1024];\n    int retval;\n    char *announce_ip;\n    int announce_port;\n    sentinelRedisInstance *master = (ri->flags & SRI_MASTER) ? ri : ri->master;\n    sentinelAddr *master_addr = sentinelGetCurrentMasterAddress(master);\n\n    if (ri->link->disconnected) return C_ERR;\n\n    /* Use the specified announce address if specified, otherwise try to\n     * obtain our own IP address. */\n    if (sentinel.announce_ip) {\n        announce_ip = sentinel.announce_ip;\n    } else {\n        if (anetSockName(ri->link->cc->c.fd,ip,sizeof(ip),NULL) == -1)\n            return C_ERR;\n        announce_ip = ip;\n    }\n    announce_port = sentinel.announce_port ?\n                    sentinel.announce_port : server.port;\n\n    /* Format and send the Hello message. */\n    snprintf(payload,sizeof(payload),\n        \"%s,%d,%s,%llu,\" /* Info about this sentinel. */\n        \"%s,%s,%d,%llu\", /* Info about current master. */\n        announce_ip, announce_port, sentinel.myid,\n        (unsigned long long) sentinel.current_epoch,\n        /* --- */\n        master->name,master_addr->ip,master_addr->port,\n        (unsigned long long) master->config_epoch);\n    retval = redisAsyncCommand(ri->link->cc,\n        sentinelPublishReplyCallback, ri, \"PUBLISH %s %s\",\n            SENTINEL_HELLO_CHANNEL,payload);\n    if (retval != C_OK) return C_ERR;\n    ri->link->pending_commands++;\n    return C_OK;\n}\n\n/* Reset last_pub_time in all the instances in the specified dictionary\n * in order to force the delivery of an Hello update ASAP. */\nvoid sentinelForceHelloUpdateDictOfRedisInstances(dict *instances) {\n    dictIterator *di;\n    dictEntry *de;\n\n    di = dictGetSafeIterator(instances);\n    while((de = dictNext(di)) != NULL) {\n        sentinelRedisInstance *ri = dictGetVal(de);\n        if (ri->last_pub_time >= (SENTINEL_PUBLISH_PERIOD+1))\n            ri->last_pub_time -= (SENTINEL_PUBLISH_PERIOD+1);\n    }\n    dictReleaseIterator(di);\n}\n\n/* This function forces the delivery of an \"Hello\" message (see\n * sentinelSendHello() top comment for further information) to all the Redis\n * and Sentinel instances related to the specified 'master'.\n *\n * It is technically not needed since we send an update to every instance\n * with a period of SENTINEL_PUBLISH_PERIOD milliseconds, however when a\n * Sentinel upgrades a configuration it is a good idea to deliever an update\n * to the other Sentinels ASAP. */\nint sentinelForceHelloUpdateForMaster(sentinelRedisInstance *master) {\n    if (!(master->flags & SRI_MASTER)) return C_ERR;\n    if (master->last_pub_time >= (SENTINEL_PUBLISH_PERIOD+1))\n        master->last_pub_time -= (SENTINEL_PUBLISH_PERIOD+1);\n    sentinelForceHelloUpdateDictOfRedisInstances(master->sentinels);\n    sentinelForceHelloUpdateDictOfRedisInstances(master->slaves);\n    return C_OK;\n}\n\n/* Send a PING to the specified instance and refresh the act_ping_time\n * if it is zero (that is, if we received a pong for the previous ping).\n *\n * On error zero is returned, and we can't consider the PING command\n * queued in the connection. */\nint sentinelSendPing(sentinelRedisInstance *ri) {\n    int retval = redisAsyncCommand(ri->link->cc,\n        sentinelPingReplyCallback, ri, \"PING\");\n    if (retval == C_OK) {\n        ri->link->pending_commands++;\n        ri->link->last_ping_time = mstime();\n        /* We update the active ping time only if we received the pong for\n         * the previous ping, otherwise we are technically waiting since the\n         * first ping that did not received a reply. */\n        if (ri->link->act_ping_time == 0)\n            ri->link->act_ping_time = ri->link->last_ping_time;\n        return 1;\n    } else {\n        return 0;\n    }\n}\n\n/* Send periodic PING, INFO, and PUBLISH to the Hello channel to\n * the specified master or slave instance. */\nvoid sentinelSendPeriodicCommands(sentinelRedisInstance *ri) {\n    mstime_t now = mstime();\n    mstime_t info_period, ping_period;\n    int retval;\n\n    /* Return ASAP if we have already a PING or INFO already pending, or\n     * in the case the instance is not properly connected. */\n    if (ri->link->disconnected) return;\n\n    /* For INFO, PING, PUBLISH that are not critical commands to send we\n     * also have a limit of SENTINEL_MAX_PENDING_COMMANDS. We don't\n     * want to use a lot of memory just because a link is not working\n     * properly (note that anyway there is a redundant protection about this,\n     * that is, the link will be disconnected and reconnected if a long\n     * timeout condition is detected. */\n    if (ri->link->pending_commands >=\n        SENTINEL_MAX_PENDING_COMMANDS * ri->link->refcount) return;\n\n    /* If this is a slave of a master in O_DOWN condition we start sending\n     * it INFO every second, instead of the usual SENTINEL_INFO_PERIOD\n     * period. In this state we want to closely monitor slaves in case they\n     * are turned into masters by another Sentinel, or by the sysadmin.\n     *\n     * Similarly we monitor the INFO output more often if the slave reports\n     * to be disconnected from the master, so that we can have a fresh\n     * disconnection time figure. */\n    if ((ri->flags & SRI_SLAVE) &&\n        ((ri->master->flags & (SRI_O_DOWN|SRI_FAILOVER_IN_PROGRESS)) ||\n         (ri->master_link_down_time != 0)))\n    {\n        info_period = 1000;\n    } else {\n        info_period = SENTINEL_INFO_PERIOD;\n    }\n\n    /* We ping instances every time the last received pong is older than\n     * the configured 'down-after-milliseconds' time, but every second\n     * anyway if 'down-after-milliseconds' is greater than 1 second. */\n    ping_period = ri->down_after_period;\n    if (ping_period > SENTINEL_PING_PERIOD) ping_period = SENTINEL_PING_PERIOD;\n\n    if ((ri->flags & SRI_SENTINEL) == 0 &&\n        (ri->info_refresh == 0 ||\n        (now - ri->info_refresh) > info_period))\n    {\n        /* Send INFO to masters and slaves, not sentinels. */\n        retval = redisAsyncCommand(ri->link->cc,\n            sentinelInfoReplyCallback, ri, \"INFO\");\n        if (retval == C_OK) ri->link->pending_commands++;\n    } else if ((now - ri->link->last_pong_time) > ping_period &&\n               (now - ri->link->last_ping_time) > ping_period/2) {\n        /* Send PING to all the three kinds of instances. */\n        sentinelSendPing(ri);\n    } else if ((now - ri->last_pub_time) > SENTINEL_PUBLISH_PERIOD) {\n        /* PUBLISH hello messages to all the three kinds of instances. */\n        sentinelSendHello(ri);\n    }\n}\n\n/* =========================== SENTINEL command ============================= */\n\nconst char *sentinelFailoverStateStr(int state) {\n    switch(state) {\n    case SENTINEL_FAILOVER_STATE_NONE: return \"none\";\n    case SENTINEL_FAILOVER_STATE_WAIT_START: return \"wait_start\";\n    case SENTINEL_FAILOVER_STATE_SELECT_SLAVE: return \"select_slave\";\n    case SENTINEL_FAILOVER_STATE_SEND_SLAVEOF_NOONE: return \"send_slaveof_noone\";\n    case SENTINEL_FAILOVER_STATE_WAIT_PROMOTION: return \"wait_promotion\";\n    case SENTINEL_FAILOVER_STATE_RECONF_SLAVES: return \"reconf_slaves\";\n    case SENTINEL_FAILOVER_STATE_UPDATE_CONFIG: return \"update_config\";\n    default: return \"unknown\";\n    }\n}\n\n/* Redis instance to Redis protocol representation. */\nvoid addReplySentinelRedisInstance(client *c, sentinelRedisInstance *ri) {\n    char *flags = sdsempty();\n    void *mbl;\n    int fields = 0;\n\n    mbl = addDeferredMultiBulkLength(c);\n\n    addReplyBulkCString(c,\"name\");\n    addReplyBulkCString(c,ri->name);\n    fields++;\n\n    addReplyBulkCString(c,\"ip\");\n    addReplyBulkCString(c,ri->addr->ip);\n    fields++;\n\n    addReplyBulkCString(c,\"port\");\n    addReplyBulkLongLong(c,ri->addr->port);\n    fields++;\n\n    addReplyBulkCString(c,\"runid\");\n    addReplyBulkCString(c,ri->runid ? ri->runid : \"\");\n    fields++;\n\n    addReplyBulkCString(c,\"flags\");\n    if (ri->flags & SRI_S_DOWN) flags = sdscat(flags,\"s_down,\");\n    if (ri->flags & SRI_O_DOWN) flags = sdscat(flags,\"o_down,\");\n    if (ri->flags & SRI_MASTER) flags = sdscat(flags,\"master,\");\n    if (ri->flags & SRI_SLAVE) flags = sdscat(flags,\"slave,\");\n    if (ri->flags & SRI_SENTINEL) flags = sdscat(flags,\"sentinel,\");\n    if (ri->link->disconnected) flags = sdscat(flags,\"disconnected,\");\n    if (ri->flags & SRI_MASTER_DOWN) flags = sdscat(flags,\"master_down,\");\n    if (ri->flags & SRI_FAILOVER_IN_PROGRESS)\n        flags = sdscat(flags,\"failover_in_progress,\");\n    if (ri->flags & SRI_PROMOTED) flags = sdscat(flags,\"promoted,\");\n    if (ri->flags & SRI_RECONF_SENT) flags = sdscat(flags,\"reconf_sent,\");\n    if (ri->flags & SRI_RECONF_INPROG) flags = sdscat(flags,\"reconf_inprog,\");\n    if (ri->flags & SRI_RECONF_DONE) flags = sdscat(flags,\"reconf_done,\");\n\n    if (sdslen(flags) != 0) sdsrange(flags,0,-2); /* remove last \",\" */\n    addReplyBulkCString(c,flags);\n    sdsfree(flags);\n    fields++;\n\n    addReplyBulkCString(c,\"link-pending-commands\");\n    addReplyBulkLongLong(c,ri->link->pending_commands);\n    fields++;\n\n    addReplyBulkCString(c,\"link-refcount\");\n    addReplyBulkLongLong(c,ri->link->refcount);\n    fields++;\n\n    if (ri->flags & SRI_FAILOVER_IN_PROGRESS) {\n        addReplyBulkCString(c,\"failover-state\");\n        addReplyBulkCString(c,(char*)sentinelFailoverStateStr(ri->failover_state));\n        fields++;\n    }\n\n    addReplyBulkCString(c,\"last-ping-sent\");\n    addReplyBulkLongLong(c,\n        ri->link->act_ping_time ? (mstime() - ri->link->act_ping_time) : 0);\n    fields++;\n\n    addReplyBulkCString(c,\"last-ok-ping-reply\");\n    addReplyBulkLongLong(c,mstime() - ri->link->last_avail_time);\n    fields++;\n\n    addReplyBulkCString(c,\"last-ping-reply\");\n    addReplyBulkLongLong(c,mstime() - ri->link->last_pong_time);\n    fields++;\n\n    if (ri->flags & SRI_S_DOWN) {\n        addReplyBulkCString(c,\"s-down-time\");\n        addReplyBulkLongLong(c,mstime()-ri->s_down_since_time);\n        fields++;\n    }\n\n    if (ri->flags & SRI_O_DOWN) {\n        addReplyBulkCString(c,\"o-down-time\");\n        addReplyBulkLongLong(c,mstime()-ri->o_down_since_time);\n        fields++;\n    }\n\n    addReplyBulkCString(c,\"down-after-milliseconds\");\n    addReplyBulkLongLong(c,ri->down_after_period);\n    fields++;\n\n    /* Masters and Slaves */\n    if (ri->flags & (SRI_MASTER|SRI_SLAVE)) {\n        addReplyBulkCString(c,\"info-refresh\");\n        addReplyBulkLongLong(c,mstime() - ri->info_refresh);\n        fields++;\n\n        addReplyBulkCString(c,\"role-reported\");\n        addReplyBulkCString(c, (ri->role_reported == SRI_MASTER) ? \"master\" :\n                                                                   \"slave\");\n        fields++;\n\n        addReplyBulkCString(c,\"role-reported-time\");\n        addReplyBulkLongLong(c,mstime() - ri->role_reported_time);\n        fields++;\n    }\n\n    /* Only masters */\n    if (ri->flags & SRI_MASTER) {\n        addReplyBulkCString(c,\"config-epoch\");\n        addReplyBulkLongLong(c,ri->config_epoch);\n        fields++;\n\n        addReplyBulkCString(c,\"num-slaves\");\n        addReplyBulkLongLong(c,dictSize(ri->slaves));\n        fields++;\n\n        addReplyBulkCString(c,\"num-other-sentinels\");\n        addReplyBulkLongLong(c,dictSize(ri->sentinels));\n        fields++;\n\n        addReplyBulkCString(c,\"quorum\");\n        addReplyBulkLongLong(c,ri->quorum);\n        fields++;\n\n        addReplyBulkCString(c,\"failover-timeout\");\n        addReplyBulkLongLong(c,ri->failover_timeout);\n        fields++;\n\n        addReplyBulkCString(c,\"parallel-syncs\");\n        addReplyBulkLongLong(c,ri->parallel_syncs);\n        fields++;\n\n        if (ri->notification_script) {\n            addReplyBulkCString(c,\"notification-script\");\n            addReplyBulkCString(c,ri->notification_script);\n            fields++;\n        }\n\n        if (ri->client_reconfig_script) {\n            addReplyBulkCString(c,\"client-reconfig-script\");\n            addReplyBulkCString(c,ri->client_reconfig_script);\n            fields++;\n        }\n    }\n\n    /* Only slaves */\n    if (ri->flags & SRI_SLAVE) {\n        addReplyBulkCString(c,\"master-link-down-time\");\n        addReplyBulkLongLong(c,ri->master_link_down_time);\n        fields++;\n\n        addReplyBulkCString(c,\"master-link-status\");\n        addReplyBulkCString(c,\n            (ri->slave_master_link_status == SENTINEL_MASTER_LINK_STATUS_UP) ?\n            \"ok\" : \"err\");\n        fields++;\n\n        addReplyBulkCString(c,\"master-host\");\n        addReplyBulkCString(c,\n            ri->slave_master_host ? ri->slave_master_host : \"?\");\n        fields++;\n\n        addReplyBulkCString(c,\"master-port\");\n        addReplyBulkLongLong(c,ri->slave_master_port);\n        fields++;\n\n        addReplyBulkCString(c,\"slave-priority\");\n        addReplyBulkLongLong(c,ri->slave_priority);\n        fields++;\n\n        addReplyBulkCString(c,\"slave-repl-offset\");\n        addReplyBulkLongLong(c,ri->slave_repl_offset);\n        fields++;\n    }\n\n    /* Only sentinels */\n    if (ri->flags & SRI_SENTINEL) {\n        addReplyBulkCString(c,\"last-hello-message\");\n        addReplyBulkLongLong(c,mstime() - ri->last_hello_time);\n        fields++;\n\n        addReplyBulkCString(c,\"voted-leader\");\n        addReplyBulkCString(c,ri->leader ? ri->leader : \"?\");\n        fields++;\n\n        addReplyBulkCString(c,\"voted-leader-epoch\");\n        addReplyBulkLongLong(c,ri->leader_epoch);\n        fields++;\n    }\n\n    setDeferredMultiBulkLength(c,mbl,fields*2);\n}\n\n/* Output a number of instances contained inside a dictionary as\n * Redis protocol. */\nvoid addReplyDictOfRedisInstances(client *c, dict *instances) {\n    dictIterator *di;\n    dictEntry *de;\n\n    di = dictGetIterator(instances);\n    addReplyMultiBulkLen(c,dictSize(instances));\n    while((de = dictNext(di)) != NULL) {\n        sentinelRedisInstance *ri = dictGetVal(de);\n\n        addReplySentinelRedisInstance(c,ri);\n    }\n    dictReleaseIterator(di);\n}\n\n/* Lookup the named master into sentinel.masters.\n * If the master is not found reply to the client with an error and returns\n * NULL. */\nsentinelRedisInstance *sentinelGetMasterByNameOrReplyError(client *c,\n                        robj *name)\n{\n    sentinelRedisInstance *ri;\n\n    ri = dictFetchValue(sentinel.masters,name->ptr);\n    if (!ri) {\n        addReplyError(c,\"No such master with that name\");\n        return NULL;\n    }\n    return ri;\n}\n\n#define SENTINEL_ISQR_OK 0\n#define SENTINEL_ISQR_NOQUORUM (1<<0)\n#define SENTINEL_ISQR_NOAUTH (1<<1)\nint sentinelIsQuorumReachable(sentinelRedisInstance *master, int *usableptr) {\n    dictIterator *di;\n    dictEntry *de;\n    int usable = 1; /* Number of usable Sentinels. Init to 1 to count myself. */\n    int result = SENTINEL_ISQR_OK;\n    int voters = dictSize(master->sentinels)+1; /* Known Sentinels + myself. */\n\n    di = dictGetIterator(master->sentinels);\n    while((de = dictNext(di)) != NULL) {\n        sentinelRedisInstance *ri = dictGetVal(de);\n\n        if (ri->flags & (SRI_S_DOWN|SRI_O_DOWN)) continue;\n        usable++;\n    }\n    dictReleaseIterator(di);\n\n    if (usable < (int)master->quorum) result |= SENTINEL_ISQR_NOQUORUM;\n    if (usable < voters/2+1) result |= SENTINEL_ISQR_NOAUTH;\n    if (usableptr) *usableptr = usable;\n    return result;\n}\n\nvoid sentinelCommand(client *c) {\n    if (!strcasecmp(c->argv[1]->ptr,\"masters\")) {\n        /* SENTINEL MASTERS */\n        if (c->argc != 2) goto numargserr;\n        addReplyDictOfRedisInstances(c,sentinel.masters);\n    } else if (!strcasecmp(c->argv[1]->ptr,\"master\")) {\n        /* SENTINEL MASTER <name> */\n        sentinelRedisInstance *ri;\n\n        if (c->argc != 3) goto numargserr;\n        if ((ri = sentinelGetMasterByNameOrReplyError(c,c->argv[2]))\n            == NULL) return;\n        addReplySentinelRedisInstance(c,ri);\n    } else if (!strcasecmp(c->argv[1]->ptr,\"slaves\")) {\n        /* SENTINEL SLAVES <master-name> */\n        sentinelRedisInstance *ri;\n\n        if (c->argc != 3) goto numargserr;\n        if ((ri = sentinelGetMasterByNameOrReplyError(c,c->argv[2])) == NULL)\n            return;\n        addReplyDictOfRedisInstances(c,ri->slaves);\n    } else if (!strcasecmp(c->argv[1]->ptr,\"sentinels\")) {\n        /* SENTINEL SENTINELS <master-name> */\n        sentinelRedisInstance *ri;\n\n        if (c->argc != 3) goto numargserr;\n        if ((ri = sentinelGetMasterByNameOrReplyError(c,c->argv[2])) == NULL)\n            return;\n        addReplyDictOfRedisInstances(c,ri->sentinels);\n    } else if (!strcasecmp(c->argv[1]->ptr,\"is-master-down-by-addr\")) {\n        /* SENTINEL IS-MASTER-DOWN-BY-ADDR <ip> <port> <current-epoch> <runid>\n         *\n         * Arguments:\n         *\n         * ip and port are the ip and port of the master we want to be\n         * checked by Sentinel. Note that the command will not check by\n         * name but just by master, in theory different Sentinels may monitor\n         * differnet masters with the same name.\n         *\n         * current-epoch is needed in order to understand if we are allowed\n         * to vote for a failover leader or not. Each Sentinel can vote just\n         * one time per epoch.\n         *\n         * runid is \"*\" if we are not seeking for a vote from the Sentinel\n         * in order to elect the failover leader. Otherwise it is set to the\n         * runid we want the Sentinel to vote if it did not already voted.\n         */\n        sentinelRedisInstance *ri;\n        long long req_epoch;\n        uint64_t leader_epoch = 0;\n        char *leader = NULL;\n        long port;\n        int isdown = 0;\n\n        if (c->argc != 6) goto numargserr;\n        if (getLongFromObjectOrReply(c,c->argv[3],&port,NULL) != C_OK ||\n            getLongLongFromObjectOrReply(c,c->argv[4],&req_epoch,NULL)\n                                                              != C_OK)\n            return;\n        ri = getSentinelRedisInstanceByAddrAndRunID(sentinel.masters,\n            c->argv[2]->ptr,port,NULL);\n\n        /* It exists? Is actually a master? Is subjectively down? It's down.\n         * Note: if we are in tilt mode we always reply with \"0\". */\n        if (!sentinel.tilt && ri && (ri->flags & SRI_S_DOWN) &&\n                                    (ri->flags & SRI_MASTER))\n            isdown = 1;\n\n        /* Vote for the master (or fetch the previous vote) if the request\n         * includes a runid, otherwise the sender is not seeking for a vote. */\n        if (ri && ri->flags & SRI_MASTER && strcasecmp(c->argv[5]->ptr,\"*\")) {\n            leader = sentinelVoteLeader(ri,(uint64_t)req_epoch,\n                                            c->argv[5]->ptr,\n                                            &leader_epoch);\n        }\n\n        /* Reply with a three-elements multi-bulk reply:\n         * down state, leader, vote epoch. */\n        addReplyMultiBulkLen(c,3);\n        addReply(c, isdown ? shared.cone : shared.czero);\n        addReplyBulkCString(c, leader ? leader : \"*\");\n        addReplyLongLong(c, (long long)leader_epoch);\n        if (leader) sdsfree(leader);\n    } else if (!strcasecmp(c->argv[1]->ptr,\"reset\")) {\n        /* SENTINEL RESET <pattern> */\n        if (c->argc != 3) goto numargserr;\n        addReplyLongLong(c,sentinelResetMastersByPattern(c->argv[2]->ptr,SENTINEL_GENERATE_EVENT));\n    } else if (!strcasecmp(c->argv[1]->ptr,\"get-master-addr-by-name\")) {\n        /* SENTINEL GET-MASTER-ADDR-BY-NAME <master-name> */\n        sentinelRedisInstance *ri;\n\n        if (c->argc != 3) goto numargserr;\n        ri = sentinelGetMasterByName(c->argv[2]->ptr);\n        if (ri == NULL) {\n            addReply(c,shared.nullmultibulk);\n        } else {\n            sentinelAddr *addr = sentinelGetCurrentMasterAddress(ri);\n\n            addReplyMultiBulkLen(c,2);\n            addReplyBulkCString(c,addr->ip);\n            addReplyBulkLongLong(c,addr->port);\n        }\n    } else if (!strcasecmp(c->argv[1]->ptr,\"failover\")) {\n        /* SENTINEL FAILOVER <master-name> */\n        sentinelRedisInstance *ri;\n\n        if (c->argc != 3) goto numargserr;\n        if ((ri = sentinelGetMasterByNameOrReplyError(c,c->argv[2])) == NULL)\n            return;\n        if (ri->flags & SRI_FAILOVER_IN_PROGRESS) {\n            addReplySds(c,sdsnew(\"-INPROG Failover already in progress\\r\\n\"));\n            return;\n        }\n        if (sentinelSelectSlave(ri) == NULL) {\n            addReplySds(c,sdsnew(\"-NOGOODSLAVE No suitable slave to promote\\r\\n\"));\n            return;\n        }\n        serverLog(LL_WARNING,\"Executing user requested FAILOVER of '%s'\",\n            ri->name);\n        sentinelStartFailover(ri);\n        ri->flags |= SRI_FORCE_FAILOVER;\n        addReply(c,shared.ok);\n    } else if (!strcasecmp(c->argv[1]->ptr,\"pending-scripts\")) {\n        /* SENTINEL PENDING-SCRIPTS */\n\n        if (c->argc != 2) goto numargserr;\n        sentinelPendingScriptsCommand(c);\n    } else if (!strcasecmp(c->argv[1]->ptr,\"monitor\")) {\n        /* SENTINEL MONITOR <name> <ip> <port> <quorum> */\n        sentinelRedisInstance *ri;\n        long quorum, port;\n        char ip[NET_IP_STR_LEN];\n\n        if (c->argc != 6) goto numargserr;\n        if (getLongFromObjectOrReply(c,c->argv[5],&quorum,\"Invalid quorum\")\n            != C_OK) return;\n        if (getLongFromObjectOrReply(c,c->argv[4],&port,\"Invalid port\")\n            != C_OK) return;\n\n        if (quorum <= 0) {\n            addReplyError(c, \"Quorum must be 1 or greater.\");\n            return;\n        }\n\n        /* Make sure the IP field is actually a valid IP before passing it\n         * to createSentinelRedisInstance(), otherwise we may trigger a\n         * DNS lookup at runtime. */\n        if (anetResolveIP(NULL,c->argv[3]->ptr,ip,sizeof(ip)) == ANET_ERR) {\n            addReplyError(c,\"Invalid IP address specified\");\n            return;\n        }\n\n        /* Parameters are valid. Try to create the master instance. */\n        ri = createSentinelRedisInstance(c->argv[2]->ptr,SRI_MASTER,\n                c->argv[3]->ptr,port,quorum,NULL);\n        if (ri == NULL) {\n            switch(errno) {\n            case EBUSY:\n                addReplyError(c,\"Duplicated master name\");\n                break;\n            case EINVAL:\n                addReplyError(c,\"Invalid port number\");\n                break;\n            default:\n                addReplyError(c,\"Unspecified error adding the instance\");\n                break;\n            }\n        } else {\n            sentinelFlushConfig();\n            sentinelEvent(LL_WARNING,\"+monitor\",ri,\"%@ quorum %d\",ri->quorum);\n            addReply(c,shared.ok);\n        }\n    } else if (!strcasecmp(c->argv[1]->ptr,\"flushconfig\")) {\n        if (c->argc != 2) goto numargserr;\n        sentinelFlushConfig();\n        addReply(c,shared.ok);\n        return;\n    } else if (!strcasecmp(c->argv[1]->ptr,\"remove\")) {\n        /* SENTINEL REMOVE <name> */\n        sentinelRedisInstance *ri;\n\n        if (c->argc != 3) goto numargserr;\n        if ((ri = sentinelGetMasterByNameOrReplyError(c,c->argv[2]))\n            == NULL) return;\n        sentinelEvent(LL_WARNING,\"-monitor\",ri,\"%@\");\n        dictDelete(sentinel.masters,c->argv[2]->ptr);\n        sentinelFlushConfig();\n        addReply(c,shared.ok);\n    } else if (!strcasecmp(c->argv[1]->ptr,\"ckquorum\")) {\n        /* SENTINEL CKQUORUM <name> */\n        sentinelRedisInstance *ri;\n        int usable;\n\n        if (c->argc != 3) goto numargserr;\n        if ((ri = sentinelGetMasterByNameOrReplyError(c,c->argv[2]))\n            == NULL) return;\n        int result = sentinelIsQuorumReachable(ri,&usable);\n        if (result == SENTINEL_ISQR_OK) {\n            addReplySds(c, sdscatfmt(sdsempty(),\n                \"+OK %i usable Sentinels. Quorum and failover authorization \"\n                \"can be reached\\r\\n\",usable));\n        } else {\n            sds e = sdscatfmt(sdsempty(),\n                \"-NOQUORUM %i usable Sentinels. \",usable);\n            if (result & SENTINEL_ISQR_NOQUORUM)\n                e = sdscat(e,\"Not enough available Sentinels to reach the\"\n                             \" specified quorum for this master\");\n            if (result & SENTINEL_ISQR_NOAUTH) {\n                if (result & SENTINEL_ISQR_NOQUORUM) e = sdscat(e,\". \");\n                e = sdscat(e, \"Not enough available Sentinels to reach the\"\n                              \" majority and authorize a failover\");\n            }\n            e = sdscat(e,\"\\r\\n\");\n            addReplySds(c,e);\n        }\n    } else if (!strcasecmp(c->argv[1]->ptr,\"set\")) {\n        if (c->argc < 3 || c->argc % 2 == 0) goto numargserr;\n        sentinelSetCommand(c);\n    } else if (!strcasecmp(c->argv[1]->ptr,\"info-cache\")) {\n        /* SENTINEL INFO-CACHE <name> */\n        if (c->argc < 2) goto numargserr;\n        mstime_t now = mstime();\n\n        /* Create an ad-hoc dictionary type so that we can iterate\n         * a dictionary composed of just the master groups the user\n         * requested. */\n        dictType copy_keeper = instancesDictType;\n        copy_keeper.valDestructor = NULL;\n        dict *masters_local = sentinel.masters;\n        if (c->argc > 2) {\n            masters_local = dictCreate(&copy_keeper, NULL);\n\n            for (int i = 2; i < c->argc; i++) {\n                sentinelRedisInstance *ri;\n                ri = sentinelGetMasterByName(c->argv[i]->ptr);\n                if (!ri) continue; /* ignore non-existing names */\n                dictAdd(masters_local, ri->name, ri);\n            }\n        }\n\n        /* Reply format:\n         *   1.) master name\n         *   2.) 1.) info from master\n         *       2.) info from replica\n         *       ...\n         *   3.) other master name\n         *   ...\n         */\n        addReplyMultiBulkLen(c,dictSize(masters_local) * 2);\n\n        dictIterator  *di;\n        dictEntry *de;\n        di = dictGetIterator(masters_local);\n        while ((de = dictNext(di)) != NULL) {\n            sentinelRedisInstance *ri = dictGetVal(de);\n            addReplyBulkCBuffer(c,ri->name,strlen(ri->name));\n            addReplyMultiBulkLen(c,dictSize(ri->slaves) + 1); /* +1 for self */\n            addReplyMultiBulkLen(c,2);\n            addReplyLongLong(c, now - ri->info_refresh);\n            if (ri->info)\n                addReplyBulkCBuffer(c,ri->info,sdslen(ri->info));\n            else\n                addReply(c,shared.nullbulk);\n\n            dictIterator *sdi;\n            dictEntry *sde;\n            sdi = dictGetIterator(ri->slaves);\n            while ((sde = dictNext(sdi)) != NULL) {\n                sentinelRedisInstance *sri = dictGetVal(sde);\n                addReplyMultiBulkLen(c,2);\n                addReplyLongLong(c, now - sri->info_refresh);\n                if (sri->info)\n                    addReplyBulkCBuffer(c,sri->info,sdslen(sri->info));\n                else\n                    addReply(c,shared.nullbulk);\n            }\n            dictReleaseIterator(sdi);\n        }\n        dictReleaseIterator(di);\n        if (masters_local != sentinel.masters) dictRelease(masters_local);\n    } else if (!strcasecmp(c->argv[1]->ptr,\"simulate-failure\")) {\n        /* SENTINEL SIMULATE-FAILURE <flag> <flag> ... <flag> */\n        int j;\n\n        sentinel.simfailure_flags = SENTINEL_SIMFAILURE_NONE;\n        for (j = 2; j < c->argc; j++) {\n            if (!strcasecmp(c->argv[j]->ptr,\"crash-after-election\")) {\n                sentinel.simfailure_flags |=\n                    SENTINEL_SIMFAILURE_CRASH_AFTER_ELECTION;\n                serverLog(LL_WARNING,\"Failure simulation: this Sentinel \"\n                    \"will crash after being successfully elected as failover \"\n                    \"leader\");\n            } else if (!strcasecmp(c->argv[j]->ptr,\"crash-after-promotion\")) {\n                sentinel.simfailure_flags |=\n                    SENTINEL_SIMFAILURE_CRASH_AFTER_PROMOTION;\n                serverLog(LL_WARNING,\"Failure simulation: this Sentinel \"\n                    \"will crash after promoting the selected slave to master\");\n            } else if (!strcasecmp(c->argv[j]->ptr,\"help\")) {\n                addReplyMultiBulkLen(c,2);\n                addReplyBulkCString(c,\"crash-after-election\");\n                addReplyBulkCString(c,\"crash-after-promotion\");\n            } else {\n                addReplyError(c,\"Unknown failure simulation specified\");\n                return;\n            }\n        }\n        addReply(c,shared.ok);\n    } else {\n        addReplyErrorFormat(c,\"Unknown sentinel subcommand '%s'\",\n                               (char*)c->argv[1]->ptr);\n    }\n    return;\n\nnumargserr:\n    addReplyErrorFormat(c,\"Wrong number of arguments for 'sentinel %s'\",\n                          (char*)c->argv[1]->ptr);\n}\n\n#define info_section_from_redis(section_name) do { \\\n    if (defsections || allsections || !strcasecmp(section,section_name)) { \\\n        sds redissection; \\\n        if (sections++) info = sdscat(info,\"\\r\\n\"); \\\n        redissection = genRedisInfoString(section_name); \\\n        info = sdscatlen(info,redissection,sdslen(redissection)); \\\n        sdsfree(redissection); \\\n    } \\\n} while(0)\n\n/* SENTINEL INFO [section] */\nvoid sentinelInfoCommand(client *c) {\n    if (c->argc > 2) {\n        addReply(c,shared.syntaxerr);\n        return;\n    }\n\n    int defsections = 0, allsections = 0;\n    char *section = c->argc == 2 ? c->argv[1]->ptr : NULL;\n    if (section) {\n        allsections = !strcasecmp(section,\"all\");\n        defsections = !strcasecmp(section,\"default\");\n    } else {\n        defsections = 1;\n    }\n\n    int sections = 0;\n    sds info = sdsempty();\n\n    info_section_from_redis(\"server\");\n    info_section_from_redis(\"clients\");\n    info_section_from_redis(\"cpu\");\n    info_section_from_redis(\"stats\");\n\n    if (defsections || allsections || !strcasecmp(section,\"sentinel\")) {\n        dictIterator *di;\n        dictEntry *de;\n        int master_id = 0;\n\n        if (sections++) info = sdscat(info,\"\\r\\n\");\n        info = sdscatprintf(info,\n            \"# Sentinel\\r\\n\"\n            \"sentinel_masters:%lu\\r\\n\"\n            \"sentinel_tilt:%d\\r\\n\"\n            \"sentinel_running_scripts:%d\\r\\n\"\n            \"sentinel_scripts_queue_length:%ld\\r\\n\"\n            \"sentinel_simulate_failure_flags:%lu\\r\\n\",\n            dictSize(sentinel.masters),\n            sentinel.tilt,\n            sentinel.running_scripts,\n            listLength(sentinel.scripts_queue),\n            sentinel.simfailure_flags);\n\n        di = dictGetIterator(sentinel.masters);\n        while((de = dictNext(di)) != NULL) {\n            sentinelRedisInstance *ri = dictGetVal(de);\n            char *status = \"ok\";\n\n            if (ri->flags & SRI_O_DOWN) status = \"odown\";\n            else if (ri->flags & SRI_S_DOWN) status = \"sdown\";\n            info = sdscatprintf(info,\n                \"master%d:name=%s,status=%s,address=%s:%d,\"\n                \"slaves=%lu,sentinels=%lu\\r\\n\",\n                master_id++, ri->name, status,\n                ri->addr->ip, ri->addr->port,\n                dictSize(ri->slaves),\n                dictSize(ri->sentinels)+1);\n        }\n        dictReleaseIterator(di);\n    }\n\n    addReplyBulkSds(c, info);\n}\n\n/* Implements Sentinel verison of the ROLE command. The output is\n * \"sentinel\" and the list of currently monitored master names. */\nvoid sentinelRoleCommand(client *c) {\n    dictIterator *di;\n    dictEntry *de;\n\n    addReplyMultiBulkLen(c,2);\n    addReplyBulkCBuffer(c,\"sentinel\",8);\n    addReplyMultiBulkLen(c,dictSize(sentinel.masters));\n\n    di = dictGetIterator(sentinel.masters);\n    while((de = dictNext(di)) != NULL) {\n        sentinelRedisInstance *ri = dictGetVal(de);\n\n        addReplyBulkCString(c,ri->name);\n    }\n    dictReleaseIterator(di);\n}\n\n/* SENTINEL SET <mastername> [<option> <value> ...] */\nvoid sentinelSetCommand(client *c) {\n    sentinelRedisInstance *ri;\n    int j, changes = 0;\n    char *option, *value;\n\n    if ((ri = sentinelGetMasterByNameOrReplyError(c,c->argv[2]))\n        == NULL) return;\n\n    /* Process option - value pairs. */\n    for (j = 3; j < c->argc; j += 2) {\n        option = c->argv[j]->ptr;\n        value = c->argv[j+1]->ptr;\n        robj *o = c->argv[j+1];\n        long long ll;\n\n        if (!strcasecmp(option,\"down-after-milliseconds\")) {\n            /* down-after-millisecodns <milliseconds> */\n            if (getLongLongFromObject(o,&ll) == C_ERR || ll <= 0)\n                goto badfmt;\n            ri->down_after_period = ll;\n            sentinelPropagateDownAfterPeriod(ri);\n            changes++;\n        } else if (!strcasecmp(option,\"failover-timeout\")) {\n            /* failover-timeout <milliseconds> */\n            if (getLongLongFromObject(o,&ll) == C_ERR || ll <= 0)\n                goto badfmt;\n            ri->failover_timeout = ll;\n            changes++;\n       } else if (!strcasecmp(option,\"parallel-syncs\")) {\n            /* parallel-syncs <milliseconds> */\n            if (getLongLongFromObject(o,&ll) == C_ERR || ll <= 0)\n                goto badfmt;\n            ri->parallel_syncs = ll;\n            changes++;\n       } else if (!strcasecmp(option,\"notification-script\")) {\n            /* notification-script <path> */\n            if (strlen(value) && access(value,X_OK) == -1) {\n                addReplyError(c,\n                    \"Notification script seems non existing or non executable\");\n                if (changes) sentinelFlushConfig();\n                return;\n            }\n            sdsfree(ri->notification_script);\n            ri->notification_script = strlen(value) ? sdsnew(value) : NULL;\n            changes++;\n       } else if (!strcasecmp(option,\"client-reconfig-script\")) {\n            /* client-reconfig-script <path> */\n            if (strlen(value) && access(value,X_OK) == -1) {\n                addReplyError(c,\n                    \"Client reconfiguration script seems non existing or \"\n                    \"non executable\");\n                if (changes) sentinelFlushConfig();\n                return;\n            }\n            sdsfree(ri->client_reconfig_script);\n            ri->client_reconfig_script = strlen(value) ? sdsnew(value) : NULL;\n            changes++;\n       } else if (!strcasecmp(option,\"auth-pass\")) {\n            /* auth-pass <password> */\n            sdsfree(ri->auth_pass);\n            ri->auth_pass = strlen(value) ? sdsnew(value) : NULL;\n            changes++;\n       } else if (!strcasecmp(option,\"quorum\")) {\n            /* quorum <count> */\n            if (getLongLongFromObject(o,&ll) == C_ERR || ll <= 0)\n                goto badfmt;\n            ri->quorum = ll;\n            changes++;\n        } else {\n            addReplyErrorFormat(c,\"Unknown option '%s' for SENTINEL SET\",\n                option);\n            if (changes) sentinelFlushConfig();\n            return;\n        }\n        sentinelEvent(LL_WARNING,\"+set\",ri,\"%@ %s %s\",option,value);\n    }\n\n    if (changes) sentinelFlushConfig();\n    addReply(c,shared.ok);\n    return;\n\nbadfmt: /* Bad format errors */\n    if (changes) sentinelFlushConfig();\n    addReplyErrorFormat(c,\"Invalid argument '%s' for SENTINEL SET '%s'\",\n            value, option);\n}\n\n/* Our fake PUBLISH command: it is actually useful only to receive hello messages\n * from the other sentinel instances, and publishing to a channel other than\n * SENTINEL_HELLO_CHANNEL is forbidden.\n *\n * Because we have a Sentinel PUBLISH, the code to send hello messages is the same\n * for all the three kind of instances: masters, slaves, sentinels. */\nvoid sentinelPublishCommand(client *c) {\n    if (strcmp(c->argv[1]->ptr,SENTINEL_HELLO_CHANNEL)) {\n        addReplyError(c, \"Only HELLO messages are accepted by Sentinel instances.\");\n        return;\n    }\n    sentinelProcessHelloMessage(c->argv[2]->ptr,sdslen(c->argv[2]->ptr));\n    addReplyLongLong(c,1);\n}\n\n/* ===================== SENTINEL availability checks ======================= */\n\n/* Is this instance down from our point of view? */\nvoid sentinelCheckSubjectivelyDown(sentinelRedisInstance *ri) {\n    mstime_t elapsed = 0;\n\n    if (ri->link->act_ping_time)\n        elapsed = mstime() - ri->link->act_ping_time;\n    else if (ri->link->disconnected)\n        elapsed = mstime() - ri->link->last_avail_time;\n\n    /* Check if we are in need for a reconnection of one of the\n     * links, because we are detecting low activity.\n     *\n     * 1) Check if the command link seems connected, was connected not less\n     *    than SENTINEL_MIN_LINK_RECONNECT_PERIOD, but still we have a\n     *    pending ping for more than half the timeout. */\n    if (ri->link->cc &&\n        (mstime() - ri->link->cc_conn_time) >\n        SENTINEL_MIN_LINK_RECONNECT_PERIOD &&\n        ri->link->act_ping_time != 0 && /* Ther is a pending ping... */\n        /* The pending ping is delayed, and we did not received\n         * error replies as well. */\n        (mstime() - ri->link->act_ping_time) > (ri->down_after_period/2) &&\n        (mstime() - ri->link->last_pong_time) > (ri->down_after_period/2))\n    {\n        instanceLinkCloseConnection(ri->link,ri->link->cc);\n    }\n\n    /* 2) Check if the pubsub link seems connected, was connected not less\n     *    than SENTINEL_MIN_LINK_RECONNECT_PERIOD, but still we have no\n     *    activity in the Pub/Sub channel for more than\n     *    SENTINEL_PUBLISH_PERIOD * 3.\n     */\n    if (ri->link->pc &&\n        (mstime() - ri->link->pc_conn_time) >\n         SENTINEL_MIN_LINK_RECONNECT_PERIOD &&\n        (mstime() - ri->link->pc_last_activity) > (SENTINEL_PUBLISH_PERIOD*3))\n    {\n        instanceLinkCloseConnection(ri->link,ri->link->pc);\n    }\n\n    /* Update the SDOWN flag. We believe the instance is SDOWN if:\n     *\n     * 1) It is not replying.\n     * 2) We believe it is a master, it reports to be a slave for enough time\n     *    to meet the down_after_period, plus enough time to get two times\n     *    INFO report from the instance. */\n    if (elapsed > ri->down_after_period ||\n        (ri->flags & SRI_MASTER &&\n         ri->role_reported == SRI_SLAVE &&\n         mstime() - ri->role_reported_time >\n          (ri->down_after_period+SENTINEL_INFO_PERIOD*2)))\n    {\n        /* Is subjectively down */\n        if ((ri->flags & SRI_S_DOWN) == 0) {\n            sentinelEvent(LL_WARNING,\"+sdown\",ri,\"%@\");\n            ri->s_down_since_time = mstime();\n            ri->flags |= SRI_S_DOWN;\n        }\n    } else {\n        /* Is subjectively up */\n        if (ri->flags & SRI_S_DOWN) {\n            sentinelEvent(LL_WARNING,\"-sdown\",ri,\"%@\");\n            ri->flags &= ~(SRI_S_DOWN|SRI_SCRIPT_KILL_SENT);\n        }\n    }\n}\n\n/* Is this instance down according to the configured quorum?\n *\n * Note that ODOWN is a weak quorum, it only means that enough Sentinels\n * reported in a given time range that the instance was not reachable.\n * However messages can be delayed so there are no strong guarantees about\n * N instances agreeing at the same time about the down state. */\nvoid sentinelCheckObjectivelyDown(sentinelRedisInstance *master) {\n    dictIterator *di;\n    dictEntry *de;\n    unsigned int quorum = 0, odown = 0;\n\n    if (master->flags & SRI_S_DOWN) {\n        /* Is down for enough sentinels? */\n        quorum = 1; /* the current sentinel. */\n        /* Count all the other sentinels. */\n        di = dictGetIterator(master->sentinels);\n        while((de = dictNext(di)) != NULL) {\n            sentinelRedisInstance *ri = dictGetVal(de);\n\n            if (ri->flags & SRI_MASTER_DOWN) quorum++;\n        }\n        dictReleaseIterator(di);\n        if (quorum >= master->quorum) odown = 1;\n    }\n\n    /* Set the flag accordingly to the outcome. */\n    if (odown) {\n        if ((master->flags & SRI_O_DOWN) == 0) {\n            sentinelEvent(LL_WARNING,\"+odown\",master,\"%@ #quorum %d/%d\",\n                quorum, master->quorum);\n            master->flags |= SRI_O_DOWN;\n            master->o_down_since_time = mstime();\n        }\n    } else {\n        if (master->flags & SRI_O_DOWN) {\n            sentinelEvent(LL_WARNING,\"-odown\",master,\"%@\");\n            master->flags &= ~SRI_O_DOWN;\n        }\n    }\n}\n\n/* Receive the SENTINEL is-master-down-by-addr reply, see the\n * sentinelAskMasterStateToOtherSentinels() function for more information. */\nvoid sentinelReceiveIsMasterDownReply(redisAsyncContext *c, void *reply, void *privdata) {\n    sentinelRedisInstance *ri = privdata;\n    instanceLink *link = c->data;\n    redisReply *r;\n\n    if (!reply || !link) return;\n    link->pending_commands--;\n    r = reply;\n\n    /* Ignore every error or unexpected reply.\n     * Note that if the command returns an error for any reason we'll\n     * end clearing the SRI_MASTER_DOWN flag for timeout anyway. */\n    if (r->type == REDIS_REPLY_ARRAY && r->elements == 3 &&\n        r->element[0]->type == REDIS_REPLY_INTEGER &&\n        r->element[1]->type == REDIS_REPLY_STRING &&\n        r->element[2]->type == REDIS_REPLY_INTEGER)\n    {\n        ri->last_master_down_reply_time = mstime();\n        if (r->element[0]->integer == 1) {\n            ri->flags |= SRI_MASTER_DOWN;\n        } else {\n            ri->flags &= ~SRI_MASTER_DOWN;\n        }\n        if (strcmp(r->element[1]->str,\"*\")) {\n            /* If the runid in the reply is not \"*\" the Sentinel actually\n             * replied with a vote. */\n            sdsfree(ri->leader);\n            if ((long long)ri->leader_epoch != r->element[2]->integer)\n                serverLog(LL_WARNING,\n                    \"%s voted for %s %llu\", ri->name,\n                    r->element[1]->str,\n                    (unsigned long long) r->element[2]->integer);\n            ri->leader = sdsnew(r->element[1]->str);\n            ri->leader_epoch = r->element[2]->integer;\n        }\n    }\n}\n\n/* If we think the master is down, we start sending\n * SENTINEL IS-MASTER-DOWN-BY-ADDR requests to other sentinels\n * in order to get the replies that allow to reach the quorum\n * needed to mark the master in ODOWN state and trigger a failover. */\n#define SENTINEL_ASK_FORCED (1<<0)\nvoid sentinelAskMasterStateToOtherSentinels(sentinelRedisInstance *master, int flags) {\n    dictIterator *di;\n    dictEntry *de;\n\n    di = dictGetIterator(master->sentinels);\n    while((de = dictNext(di)) != NULL) {\n        sentinelRedisInstance *ri = dictGetVal(de);\n        mstime_t elapsed = mstime() - ri->last_master_down_reply_time;\n        char port[32];\n        int retval;\n\n        /* If the master state from other sentinel is too old, we clear it. */\n        if (elapsed > SENTINEL_ASK_PERIOD*5) {\n            ri->flags &= ~SRI_MASTER_DOWN;\n            sdsfree(ri->leader);\n            ri->leader = NULL;\n        }\n\n        /* Only ask if master is down to other sentinels if:\n         *\n         * 1) We believe it is down, or there is a failover in progress.\n         * 2) Sentinel is connected.\n         * 3) We did not received the info within SENTINEL_ASK_PERIOD ms. */\n        if ((master->flags & SRI_S_DOWN) == 0) continue;\n        if (ri->link->disconnected) continue;\n        if (!(flags & SENTINEL_ASK_FORCED) &&\n            mstime() - ri->last_master_down_reply_time < SENTINEL_ASK_PERIOD)\n            continue;\n\n        /* Ask */\n        ll2string(port,sizeof(port),master->addr->port);\n        retval = redisAsyncCommand(ri->link->cc,\n                    sentinelReceiveIsMasterDownReply, ri,\n                    \"SENTINEL is-master-down-by-addr %s %s %llu %s\",\n                    master->addr->ip, port,\n                    sentinel.current_epoch,\n                    (master->failover_state > SENTINEL_FAILOVER_STATE_NONE) ?\n                    sentinel.myid : \"*\");\n        if (retval == C_OK) ri->link->pending_commands++;\n    }\n    dictReleaseIterator(di);\n}\n\n/* =============================== FAILOVER ================================= */\n\n/* Crash because of user request via SENTINEL simulate-failure command. */\nvoid sentinelSimFailureCrash(void) {\n    serverLog(LL_WARNING,\n        \"Sentinel CRASH because of SENTINEL simulate-failure\");\n    exit(99);\n}\n\n/* Vote for the sentinel with 'req_runid' or return the old vote if already\n * voted for the specifed 'req_epoch' or one greater.\n *\n * If a vote is not available returns NULL, otherwise return the Sentinel\n * runid and populate the leader_epoch with the epoch of the vote. */\nchar *sentinelVoteLeader(sentinelRedisInstance *master, uint64_t req_epoch, char *req_runid, uint64_t *leader_epoch) {\n    if (req_epoch > sentinel.current_epoch) {\n        sentinel.current_epoch = req_epoch;\n        sentinelFlushConfig();\n        sentinelEvent(LL_WARNING,\"+new-epoch\",master,\"%llu\",\n            (unsigned long long) sentinel.current_epoch);\n    }\n\n    if (master->leader_epoch < req_epoch && sentinel.current_epoch <= req_epoch)\n    {\n        sdsfree(master->leader);\n        master->leader = sdsnew(req_runid);\n        master->leader_epoch = sentinel.current_epoch;\n        sentinelFlushConfig();\n        sentinelEvent(LL_WARNING,\"+vote-for-leader\",master,\"%s %llu\",\n            master->leader, (unsigned long long) master->leader_epoch);\n        /* If we did not voted for ourselves, set the master failover start\n         * time to now, in order to force a delay before we can start a\n         * failover for the same master. */\n        if (strcasecmp(master->leader,sentinel.myid))\n            master->failover_start_time = mstime()+rand()%SENTINEL_MAX_DESYNC;\n    }\n\n    *leader_epoch = master->leader_epoch;\n    return master->leader ? sdsnew(master->leader) : NULL;\n}\n\nstruct sentinelLeader {\n    char *runid;\n    unsigned long votes;\n};\n\n/* Helper function for sentinelGetLeader, increment the counter\n * relative to the specified runid. */\nint sentinelLeaderIncr(dict *counters, char *runid) {\n    dictEntry *de = dictFind(counters,runid);\n    uint64_t oldval;\n\n    if (de) {\n        oldval = dictGetUnsignedIntegerVal(de);\n        dictSetUnsignedIntegerVal(de,oldval+1);\n        return oldval+1;\n    } else {\n        de = dictAddRaw(counters,runid);\n        serverAssert(de != NULL);\n        dictSetUnsignedIntegerVal(de,1);\n        return 1;\n    }\n}\n\n/* Scan all the Sentinels attached to this master to check if there\n * is a leader for the specified epoch.\n *\n * To be a leader for a given epoch, we should have the majority of\n * the Sentinels we know (ever seen since the last SENTINEL RESET) that\n * reported the same instance as leader for the same epoch. */\nchar *sentinelGetLeader(sentinelRedisInstance *master, uint64_t epoch) {\n    dict *counters;\n    dictIterator *di;\n    dictEntry *de;\n    unsigned int voters = 0, voters_quorum;\n    char *myvote;\n    char *winner = NULL;\n    uint64_t leader_epoch;\n    uint64_t max_votes = 0;\n\n    serverAssert(master->flags & (SRI_O_DOWN|SRI_FAILOVER_IN_PROGRESS));\n    counters = dictCreate(&leaderVotesDictType,NULL);\n\n    voters = dictSize(master->sentinels)+1; /* All the other sentinels and me. */\n\n    /* Count other sentinels votes */\n    di = dictGetIterator(master->sentinels);\n    while((de = dictNext(di)) != NULL) {\n        sentinelRedisInstance *ri = dictGetVal(de);\n        if (ri->leader != NULL && ri->leader_epoch == sentinel.current_epoch)\n            sentinelLeaderIncr(counters,ri->leader);\n    }\n    dictReleaseIterator(di);\n\n    /* Check what's the winner. For the winner to win, it needs two conditions:\n     * 1) Absolute majority between voters (50% + 1).\n     * 2) And anyway at least master->quorum votes. */\n    di = dictGetIterator(counters);\n    while((de = dictNext(di)) != NULL) {\n        uint64_t votes = dictGetUnsignedIntegerVal(de);\n\n        if (votes > max_votes) {\n            max_votes = votes;\n            winner = dictGetKey(de);\n        }\n    }\n    dictReleaseIterator(di);\n\n    /* Count this Sentinel vote:\n     * if this Sentinel did not voted yet, either vote for the most\n     * common voted sentinel, or for itself if no vote exists at all. */\n    if (winner)\n        myvote = sentinelVoteLeader(master,epoch,winner,&leader_epoch);\n    else\n        myvote = sentinelVoteLeader(master,epoch,sentinel.myid,&leader_epoch);\n\n    if (myvote && leader_epoch == epoch) {\n        uint64_t votes = sentinelLeaderIncr(counters,myvote);\n\n        if (votes > max_votes) {\n            max_votes = votes;\n            winner = myvote;\n        }\n    }\n\n    voters_quorum = voters/2+1;\n    if (winner && (max_votes < voters_quorum || max_votes < master->quorum))\n        winner = NULL;\n\n    winner = winner ? sdsnew(winner) : NULL;\n    sdsfree(myvote);\n    dictRelease(counters);\n    return winner;\n}\n\n/* Send SLAVEOF to the specified instance, always followed by a\n * CONFIG REWRITE command in order to store the new configuration on disk\n * when possible (that is, if the Redis instance is recent enough to support\n * config rewriting, and if the server was started with a configuration file).\n *\n * If Host is NULL the function sends \"SLAVEOF NO ONE\".\n *\n * The command returns C_OK if the SLAVEOF command was accepted for\n * (later) delivery otherwise C_ERR. The command replies are just\n * discarded. */\nint sentinelSendSlaveOf(sentinelRedisInstance *ri, char *host, int port) {\n    char portstr[32];\n    int retval;\n\n    ll2string(portstr,sizeof(portstr),port);\n\n    /* If host is NULL we send SLAVEOF NO ONE that will turn the instance\n     * into a master. */\n    if (host == NULL) {\n        host = \"NO\";\n        memcpy(portstr,\"ONE\",4);\n    }\n\n    /* In order to send SLAVEOF in a safe way, we send a transaction performing\n     * the following tasks:\n     * 1) Reconfigure the instance according to the specified host/port params.\n     * 2) Rewrite the configuraiton.\n     * 3) Disconnect all clients (but this one sending the commnad) in order\n     *    to trigger the ask-master-on-reconnection protocol for connected\n     *    clients.\n     *\n     * Note that we don't check the replies returned by commands, since we\n     * will observe instead the effects in the next INFO output. */\n    retval = redisAsyncCommand(ri->link->cc,\n        sentinelDiscardReplyCallback, ri, \"MULTI\");\n    if (retval == C_ERR) return retval;\n    ri->link->pending_commands++;\n\n    retval = redisAsyncCommand(ri->link->cc,\n        sentinelDiscardReplyCallback, ri, \"SLAVEOF %s %s\", host, portstr);\n    if (retval == C_ERR) return retval;\n    ri->link->pending_commands++;\n\n    retval = redisAsyncCommand(ri->link->cc,\n        sentinelDiscardReplyCallback, ri, \"CONFIG REWRITE\");\n    if (retval == C_ERR) return retval;\n    ri->link->pending_commands++;\n\n    /* CLIENT KILL TYPE <type> is only supported starting from Redis 2.8.12,\n     * however sending it to an instance not understanding this command is not\n     * an issue because CLIENT is variadic command, so Redis will not\n     * recognized as a syntax error, and the transaction will not fail (but\n     * only the unsupported command will fail). */\n    retval = redisAsyncCommand(ri->link->cc,\n        sentinelDiscardReplyCallback, ri, \"CLIENT KILL TYPE normal\");\n    if (retval == C_ERR) return retval;\n    ri->link->pending_commands++;\n\n    retval = redisAsyncCommand(ri->link->cc,\n        sentinelDiscardReplyCallback, ri, \"EXEC\");\n    if (retval == C_ERR) return retval;\n    ri->link->pending_commands++;\n\n    return C_OK;\n}\n\n/* Setup the master state to start a failover. */\nvoid sentinelStartFailover(sentinelRedisInstance *master) {\n    serverAssert(master->flags & SRI_MASTER);\n\n    master->failover_state = SENTINEL_FAILOVER_STATE_WAIT_START;\n    master->flags |= SRI_FAILOVER_IN_PROGRESS;\n    master->failover_epoch = ++sentinel.current_epoch;\n    sentinelEvent(LL_WARNING,\"+new-epoch\",master,\"%llu\",\n        (unsigned long long) sentinel.current_epoch);\n    sentinelEvent(LL_WARNING,\"+try-failover\",master,\"%@\");\n    master->failover_start_time = mstime()+rand()%SENTINEL_MAX_DESYNC;\n    master->failover_state_change_time = mstime();\n}\n\n/* This function checks if there are the conditions to start the failover,\n * that is:\n *\n * 1) Master must be in ODOWN condition.\n * 2) No failover already in progress.\n * 3) No failover already attempted recently.\n *\n * We still don't know if we'll win the election so it is possible that we\n * start the failover but that we'll not be able to act.\n *\n * Return non-zero if a failover was started. */\nint sentinelStartFailoverIfNeeded(sentinelRedisInstance *master) {\n    /* We can't failover if the master is not in O_DOWN state. */\n    if (!(master->flags & SRI_O_DOWN)) return 0;\n\n    /* Failover already in progress? */\n    if (master->flags & SRI_FAILOVER_IN_PROGRESS) return 0;\n\n    /* Last failover attempt started too little time ago? */\n    if (mstime() - master->failover_start_time <\n        master->failover_timeout*2)\n    {\n        if (master->failover_delay_logged != master->failover_start_time) {\n            time_t clock = (master->failover_start_time +\n                            master->failover_timeout*2) / 1000;\n            char ctimebuf[26];\n\n            ctime_r(&clock,ctimebuf);\n            ctimebuf[24] = '\\0'; /* Remove newline. */\n            master->failover_delay_logged = master->failover_start_time;\n            serverLog(LL_WARNING,\n                \"Next failover delay: I will not start a failover before %s\",\n                ctimebuf);\n        }\n        return 0;\n    }\n\n    sentinelStartFailover(master);\n    return 1;\n}\n\n/* Select a suitable slave to promote. The current algorithm only uses\n * the following parameters:\n *\n * 1) None of the following conditions: S_DOWN, O_DOWN, DISCONNECTED.\n * 2) Last time the slave replied to ping no more than 5 times the PING period.\n * 3) info_refresh not older than 3 times the INFO refresh period.\n * 4) master_link_down_time no more than:\n *     (now - master->s_down_since_time) + (master->down_after_period * 10).\n *    Basically since the master is down from our POV, the slave reports\n *    to be disconnected no more than 10 times the configured down-after-period.\n *    This is pretty much black magic but the idea is, the master was not\n *    available so the slave may be lagging, but not over a certain time.\n *    Anyway we'll select the best slave according to replication offset.\n * 5) Slave priority can't be zero, otherwise the slave is discarded.\n *\n * Among all the slaves matching the above conditions we select the slave\n * with, in order of sorting key:\n *\n * - lower slave_priority.\n * - bigger processed replication offset.\n * - lexicographically smaller runid.\n *\n * Basically if runid is the same, the slave that processed more commands\n * from the master is selected.\n *\n * The function returns the pointer to the selected slave, otherwise\n * NULL if no suitable slave was found.\n */\n\n/* Helper for sentinelSelectSlave(). This is used by qsort() in order to\n * sort suitable slaves in a \"better first\" order, to take the first of\n * the list. */\nint compareSlavesForPromotion(const void *a, const void *b) {\n    sentinelRedisInstance **sa = (sentinelRedisInstance **)a,\n                          **sb = (sentinelRedisInstance **)b;\n    char *sa_runid, *sb_runid;\n\n    if ((*sa)->slave_priority != (*sb)->slave_priority)\n        return (*sa)->slave_priority - (*sb)->slave_priority;\n\n    /* If priority is the same, select the slave with greater replication\n     * offset (processed more data from the master). */\n    if ((*sa)->slave_repl_offset > (*sb)->slave_repl_offset) {\n        return -1; /* a < b */\n    } else if ((*sa)->slave_repl_offset < (*sb)->slave_repl_offset) {\n        return 1; /* a > b */\n    }\n\n    /* If the replication offset is the same select the slave with that has\n     * the lexicographically smaller runid. Note that we try to handle runid\n     * == NULL as there are old Redis versions that don't publish runid in\n     * INFO. A NULL runid is considered bigger than any other runid. */\n    sa_runid = (*sa)->runid;\n    sb_runid = (*sb)->runid;\n    if (sa_runid == NULL && sb_runid == NULL) return 0;\n    else if (sa_runid == NULL) return 1;  /* a > b */\n    else if (sb_runid == NULL) return -1; /* a < b */\n    return strcasecmp(sa_runid, sb_runid);\n}\n\nsentinelRedisInstance *sentinelSelectSlave(sentinelRedisInstance *master) {\n    sentinelRedisInstance **instance =\n        zmalloc(sizeof(instance[0])*dictSize(master->slaves));\n    sentinelRedisInstance *selected = NULL;\n    int instances = 0;\n    dictIterator *di;\n    dictEntry *de;\n    mstime_t max_master_down_time = 0;\n\n    if (master->flags & SRI_S_DOWN)\n        max_master_down_time += mstime() - master->s_down_since_time;\n    max_master_down_time += master->down_after_period * 10;\n\n    di = dictGetIterator(master->slaves);\n    while((de = dictNext(di)) != NULL) {\n        sentinelRedisInstance *slave = dictGetVal(de);\n        mstime_t info_validity_time;\n\n        if (slave->flags & (SRI_S_DOWN|SRI_O_DOWN)) continue;\n        if (slave->link->disconnected) continue;\n        if (mstime() - slave->link->last_avail_time > SENTINEL_PING_PERIOD*5) continue;\n        if (slave->slave_priority == 0) continue;\n\n        /* If the master is in SDOWN state we get INFO for slaves every second.\n         * Otherwise we get it with the usual period so we need to account for\n         * a larger delay. */\n        if (master->flags & SRI_S_DOWN)\n            info_validity_time = SENTINEL_PING_PERIOD*5;\n        else\n            info_validity_time = SENTINEL_INFO_PERIOD*3;\n        if (mstime() - slave->info_refresh > info_validity_time) continue;\n        if (slave->master_link_down_time > max_master_down_time) continue;\n        instance[instances++] = slave;\n    }\n    dictReleaseIterator(di);\n    if (instances) {\n        qsort(instance,instances,sizeof(sentinelRedisInstance*),\n            compareSlavesForPromotion);\n        selected = instance[0];\n    }\n    zfree(instance);\n    return selected;\n}\n\n/* ---------------- Failover state machine implementation ------------------- */\nvoid sentinelFailoverWaitStart(sentinelRedisInstance *ri) {\n    char *leader;\n    int isleader;\n\n    /* Check if we are the leader for the failover epoch. */\n    leader = sentinelGetLeader(ri, ri->failover_epoch);\n    isleader = leader && strcasecmp(leader,sentinel.myid) == 0;\n    sdsfree(leader);\n\n    /* If I'm not the leader, and it is not a forced failover via\n     * SENTINEL FAILOVER, then I can't continue with the failover. */\n    if (!isleader && !(ri->flags & SRI_FORCE_FAILOVER)) {\n        int election_timeout = SENTINEL_ELECTION_TIMEOUT;\n\n        /* The election timeout is the MIN between SENTINEL_ELECTION_TIMEOUT\n         * and the configured failover timeout. */\n        if (election_timeout > ri->failover_timeout)\n            election_timeout = ri->failover_timeout;\n        /* Abort the failover if I'm not the leader after some time. */\n        if (mstime() - ri->failover_start_time > election_timeout) {\n            sentinelEvent(LL_WARNING,\"-failover-abort-not-elected\",ri,\"%@\");\n            sentinelAbortFailover(ri);\n        }\n        return;\n    }\n    sentinelEvent(LL_WARNING,\"+elected-leader\",ri,\"%@\");\n    if (sentinel.simfailure_flags & SENTINEL_SIMFAILURE_CRASH_AFTER_ELECTION)\n        sentinelSimFailureCrash();\n    ri->failover_state = SENTINEL_FAILOVER_STATE_SELECT_SLAVE;\n    ri->failover_state_change_time = mstime();\n    sentinelEvent(LL_WARNING,\"+failover-state-select-slave\",ri,\"%@\");\n}\n\nvoid sentinelFailoverSelectSlave(sentinelRedisInstance *ri) {\n    sentinelRedisInstance *slave = sentinelSelectSlave(ri);\n\n    /* We don't handle the timeout in this state as the function aborts\n     * the failover or go forward in the next state. */\n    if (slave == NULL) {\n        sentinelEvent(LL_WARNING,\"-failover-abort-no-good-slave\",ri,\"%@\");\n        sentinelAbortFailover(ri);\n    } else {\n        sentinelEvent(LL_WARNING,\"+selected-slave\",slave,\"%@\");\n        slave->flags |= SRI_PROMOTED;\n        ri->promoted_slave = slave;\n        ri->failover_state = SENTINEL_FAILOVER_STATE_SEND_SLAVEOF_NOONE;\n        ri->failover_state_change_time = mstime();\n        sentinelEvent(LL_NOTICE,\"+failover-state-send-slaveof-noone\",\n            slave, \"%@\");\n    }\n}\n\nvoid sentinelFailoverSendSlaveOfNoOne(sentinelRedisInstance *ri) {\n    int retval;\n\n    /* We can't send the command to the promoted slave if it is now\n     * disconnected. Retry again and again with this state until the timeout\n     * is reached, then abort the failover. */\n    if (ri->promoted_slave->link->disconnected) {\n        if (mstime() - ri->failover_state_change_time > ri->failover_timeout) {\n            sentinelEvent(LL_WARNING,\"-failover-abort-slave-timeout\",ri,\"%@\");\n            sentinelAbortFailover(ri);\n        }\n        return;\n    }\n\n    /* Send SLAVEOF NO ONE command to turn the slave into a master.\n     * We actually register a generic callback for this command as we don't\n     * really care about the reply. We check if it worked indirectly observing\n     * if INFO returns a different role (master instead of slave). */\n    retval = sentinelSendSlaveOf(ri->promoted_slave,NULL,0);\n    if (retval != C_OK) return;\n    sentinelEvent(LL_NOTICE, \"+failover-state-wait-promotion\",\n        ri->promoted_slave,\"%@\");\n    ri->failover_state = SENTINEL_FAILOVER_STATE_WAIT_PROMOTION;\n    ri->failover_state_change_time = mstime();\n}\n\n/* We actually wait for promotion indirectly checking with INFO when the\n * slave turns into a master. */\nvoid sentinelFailoverWaitPromotion(sentinelRedisInstance *ri) {\n    /* Just handle the timeout. Switching to the next state is handled\n     * by the function parsing the INFO command of the promoted slave. */\n    if (mstime() - ri->failover_state_change_time > ri->failover_timeout) {\n        sentinelEvent(LL_WARNING,\"-failover-abort-slave-timeout\",ri,\"%@\");\n        sentinelAbortFailover(ri);\n    }\n}\n\nvoid sentinelFailoverDetectEnd(sentinelRedisInstance *master) {\n    int not_reconfigured = 0, timeout = 0;\n    dictIterator *di;\n    dictEntry *de;\n    mstime_t elapsed = mstime() - master->failover_state_change_time;\n\n    /* We can't consider failover finished if the promoted slave is\n     * not reachable. */\n    if (master->promoted_slave == NULL ||\n        master->promoted_slave->flags & SRI_S_DOWN) return;\n\n    /* The failover terminates once all the reachable slaves are properly\n     * configured. */\n    di = dictGetIterator(master->slaves);\n    while((de = dictNext(di)) != NULL) {\n        sentinelRedisInstance *slave = dictGetVal(de);\n\n        if (slave->flags & (SRI_PROMOTED|SRI_RECONF_DONE)) continue;\n        if (slave->flags & SRI_S_DOWN) continue;\n        not_reconfigured++;\n    }\n    dictReleaseIterator(di);\n\n    /* Force end of failover on timeout. */\n    if (elapsed > master->failover_timeout) {\n        not_reconfigured = 0;\n        timeout = 1;\n        sentinelEvent(LL_WARNING,\"+failover-end-for-timeout\",master,\"%@\");\n    }\n\n    if (not_reconfigured == 0) {\n        sentinelEvent(LL_WARNING,\"+failover-end\",master,\"%@\");\n        master->failover_state = SENTINEL_FAILOVER_STATE_UPDATE_CONFIG;\n        master->failover_state_change_time = mstime();\n    }\n\n    /* If I'm the leader it is a good idea to send a best effort SLAVEOF\n     * command to all the slaves still not reconfigured to replicate with\n     * the new master. */\n    if (timeout) {\n        dictIterator *di;\n        dictEntry *de;\n\n        di = dictGetIterator(master->slaves);\n        while((de = dictNext(di)) != NULL) {\n            sentinelRedisInstance *slave = dictGetVal(de);\n            int retval;\n\n            if (slave->flags & (SRI_RECONF_DONE|SRI_RECONF_SENT)) continue;\n            if (slave->link->disconnected) continue;\n\n            retval = sentinelSendSlaveOf(slave,\n                    master->promoted_slave->addr->ip,\n                    master->promoted_slave->addr->port);\n            if (retval == C_OK) {\n                sentinelEvent(LL_NOTICE,\"+slave-reconf-sent-be\",slave,\"%@\");\n                slave->flags |= SRI_RECONF_SENT;\n            }\n        }\n        dictReleaseIterator(di);\n    }\n}\n\n/* Send SLAVE OF <new master address> to all the remaining slaves that\n * still don't appear to have the configuration updated. */\nvoid sentinelFailoverReconfNextSlave(sentinelRedisInstance *master) {\n    dictIterator *di;\n    dictEntry *de;\n    int in_progress = 0;\n\n    di = dictGetIterator(master->slaves);\n    while((de = dictNext(di)) != NULL) {\n        sentinelRedisInstance *slave = dictGetVal(de);\n\n        if (slave->flags & (SRI_RECONF_SENT|SRI_RECONF_INPROG))\n            in_progress++;\n    }\n    dictReleaseIterator(di);\n\n    di = dictGetIterator(master->slaves);\n    while(in_progress < master->parallel_syncs &&\n          (de = dictNext(di)) != NULL)\n    {\n        sentinelRedisInstance *slave = dictGetVal(de);\n        int retval;\n\n        /* Skip the promoted slave, and already configured slaves. */\n        if (slave->flags & (SRI_PROMOTED|SRI_RECONF_DONE)) continue;\n\n        /* If too much time elapsed without the slave moving forward to\n         * the next state, consider it reconfigured even if it is not.\n         * Sentinels will detect the slave as misconfigured and fix its\n         * configuration later. */\n        if ((slave->flags & SRI_RECONF_SENT) &&\n            (mstime() - slave->slave_reconf_sent_time) >\n            SENTINEL_SLAVE_RECONF_TIMEOUT)\n        {\n            sentinelEvent(LL_NOTICE,\"-slave-reconf-sent-timeout\",slave,\"%@\");\n            slave->flags &= ~SRI_RECONF_SENT;\n            slave->flags |= SRI_RECONF_DONE;\n        }\n\n        /* Nothing to do for instances that are disconnected or already\n         * in RECONF_SENT state. */\n        if (slave->flags & (SRI_RECONF_SENT|SRI_RECONF_INPROG)) continue;\n        if (slave->link->disconnected) continue;\n\n        /* Send SLAVEOF <new master>. */\n        retval = sentinelSendSlaveOf(slave,\n                master->promoted_slave->addr->ip,\n                master->promoted_slave->addr->port);\n        if (retval == C_OK) {\n            slave->flags |= SRI_RECONF_SENT;\n            slave->slave_reconf_sent_time = mstime();\n            sentinelEvent(LL_NOTICE,\"+slave-reconf-sent\",slave,\"%@\");\n            in_progress++;\n        }\n    }\n    dictReleaseIterator(di);\n\n    /* Check if all the slaves are reconfigured and handle timeout. */\n    sentinelFailoverDetectEnd(master);\n}\n\n/* This function is called when the slave is in\n * SENTINEL_FAILOVER_STATE_UPDATE_CONFIG state. In this state we need\n * to remove it from the master table and add the promoted slave instead. */\nvoid sentinelFailoverSwitchToPromotedSlave(sentinelRedisInstance *master) {\n    sentinelRedisInstance *ref = master->promoted_slave ?\n                                 master->promoted_slave : master;\n\n    sentinelEvent(LL_WARNING,\"+switch-master\",master,\"%s %s %d %s %d\",\n        master->name, master->addr->ip, master->addr->port,\n        ref->addr->ip, ref->addr->port);\n\n    sentinelResetMasterAndChangeAddress(master,ref->addr->ip,ref->addr->port);\n}\n\nvoid sentinelFailoverStateMachine(sentinelRedisInstance *ri) {\n    serverAssert(ri->flags & SRI_MASTER);\n\n    if (!(ri->flags & SRI_FAILOVER_IN_PROGRESS)) return;\n\n    switch(ri->failover_state) {\n        case SENTINEL_FAILOVER_STATE_WAIT_START:\n            sentinelFailoverWaitStart(ri);\n            break;\n        case SENTINEL_FAILOVER_STATE_SELECT_SLAVE:\n            sentinelFailoverSelectSlave(ri);\n            break;\n        case SENTINEL_FAILOVER_STATE_SEND_SLAVEOF_NOONE:\n            sentinelFailoverSendSlaveOfNoOne(ri);\n            break;\n        case SENTINEL_FAILOVER_STATE_WAIT_PROMOTION:\n            sentinelFailoverWaitPromotion(ri);\n            break;\n        case SENTINEL_FAILOVER_STATE_RECONF_SLAVES:\n            sentinelFailoverReconfNextSlave(ri);\n            break;\n    }\n}\n\n/* Abort a failover in progress:\n *\n * This function can only be called before the promoted slave acknowledged\n * the slave -> master switch. Otherwise the failover can't be aborted and\n * will reach its end (possibly by timeout). */\nvoid sentinelAbortFailover(sentinelRedisInstance *ri) {\n    serverAssert(ri->flags & SRI_FAILOVER_IN_PROGRESS);\n    serverAssert(ri->failover_state <= SENTINEL_FAILOVER_STATE_WAIT_PROMOTION);\n\n    ri->flags &= ~(SRI_FAILOVER_IN_PROGRESS|SRI_FORCE_FAILOVER);\n    ri->failover_state = SENTINEL_FAILOVER_STATE_NONE;\n    ri->failover_state_change_time = mstime();\n    if (ri->promoted_slave) {\n        ri->promoted_slave->flags &= ~SRI_PROMOTED;\n        ri->promoted_slave = NULL;\n    }\n}\n\n/* ======================== SENTINEL timer handler ==========================\n * This is the \"main\" our Sentinel, being sentinel completely non blocking\n * in design. The function is called every second.\n * -------------------------------------------------------------------------- */\n\n/* Perform scheduled operations for the specified Redis instance. */\nvoid sentinelHandleRedisInstance(sentinelRedisInstance *ri) {\n    /* ========== MONITORING HALF ============ */\n    /* Every kind of instance */\n    sentinelReconnectInstance(ri);\n    sentinelSendPeriodicCommands(ri);\n\n    /* ============== ACTING HALF ============= */\n    /* We don't proceed with the acting half if we are in TILT mode.\n     * TILT happens when we find something odd with the time, like a\n     * sudden change in the clock. */\n    if (sentinel.tilt) {\n        if (mstime()-sentinel.tilt_start_time < SENTINEL_TILT_PERIOD) return;\n        sentinel.tilt = 0;\n        sentinelEvent(LL_WARNING,\"-tilt\",NULL,\"#tilt mode exited\");\n    }\n\n    /* Every kind of instance */\n    sentinelCheckSubjectivelyDown(ri);\n\n    /* Masters and slaves */\n    if (ri->flags & (SRI_MASTER|SRI_SLAVE)) {\n        /* Nothing so far. */\n    }\n\n    /* Only masters */\n    if (ri->flags & SRI_MASTER) {\n        sentinelCheckObjectivelyDown(ri);\n        if (sentinelStartFailoverIfNeeded(ri))\n            sentinelAskMasterStateToOtherSentinels(ri,SENTINEL_ASK_FORCED);\n        sentinelFailoverStateMachine(ri);\n        sentinelAskMasterStateToOtherSentinels(ri,SENTINEL_NO_FLAGS);\n    }\n}\n\n/* Perform scheduled operations for all the instances in the dictionary.\n * Recursively call the function against dictionaries of slaves. */\nvoid sentinelHandleDictOfRedisInstances(dict *instances) {\n    dictIterator *di;\n    dictEntry *de;\n    sentinelRedisInstance *switch_to_promoted = NULL;\n\n    /* There are a number of things we need to perform against every master. */\n    di = dictGetIterator(instances);\n    while((de = dictNext(di)) != NULL) {\n        sentinelRedisInstance *ri = dictGetVal(de);\n\n        sentinelHandleRedisInstance(ri);\n        if (ri->flags & SRI_MASTER) {\n            sentinelHandleDictOfRedisInstances(ri->slaves);\n            sentinelHandleDictOfRedisInstances(ri->sentinels);\n            if (ri->failover_state == SENTINEL_FAILOVER_STATE_UPDATE_CONFIG) {\n                switch_to_promoted = ri;\n            }\n        }\n    }\n    if (switch_to_promoted)\n        sentinelFailoverSwitchToPromotedSlave(switch_to_promoted);\n    dictReleaseIterator(di);\n}\n\n/* This function checks if we need to enter the TITL mode.\n *\n * The TILT mode is entered if we detect that between two invocations of the\n * timer interrupt, a negative amount of time, or too much time has passed.\n * Note that we expect that more or less just 100 milliseconds will pass\n * if everything is fine. However we'll see a negative number or a\n * difference bigger than SENTINEL_TILT_TRIGGER milliseconds if one of the\n * following conditions happen:\n *\n * 1) The Sentiel process for some time is blocked, for every kind of\n * random reason: the load is huge, the computer was frozen for some time\n * in I/O or alike, the process was stopped by a signal. Everything.\n * 2) The system clock was altered significantly.\n *\n * Under both this conditions we'll see everything as timed out and failing\n * without good reasons. Instead we enter the TILT mode and wait\n * for SENTINEL_TILT_PERIOD to elapse before starting to act again.\n *\n * During TILT time we still collect information, we just do not act. */\nvoid sentinelCheckTiltCondition(void) {\n    mstime_t now = mstime();\n    mstime_t delta = now - sentinel.previous_time;\n\n    if (delta < 0 || delta > SENTINEL_TILT_TRIGGER) {\n        sentinel.tilt = 1;\n        sentinel.tilt_start_time = mstime();\n        sentinelEvent(LL_WARNING,\"+tilt\",NULL,\"#tilt mode entered\");\n    }\n    sentinel.previous_time = mstime();\n}\n\nvoid sentinelTimer(void) {\n    sentinelCheckTiltCondition();\n    sentinelHandleDictOfRedisInstances(sentinel.masters);\n    sentinelRunPendingScripts();\n    sentinelCollectTerminatedScripts();\n    sentinelKillTimedoutScripts();\n\n    /* We continuously change the frequency of the Redis \"timer interrupt\"\n     * in order to desynchronize every Sentinel from every other.\n     * This non-determinism avoids that Sentinels started at the same time\n     * exactly continue to stay synchronized asking to be voted at the\n     * same time again and again (resulting in nobody likely winning the\n     * election because of split brain voting). */\n    server.hz = CONFIG_DEFAULT_HZ + rand() % CONFIG_DEFAULT_HZ;\n}\n\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/src/server.c",
    "content": "/*\n * Copyright (c) 2009-2012, Salvatore Sanfilippo <antirez at gmail dot com>\n * All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions are met:\n *\n *   * Redistributions of source code must retain the above copyright notice,\n *     this list of conditions and the following disclaimer.\n *   * Redistributions in binary form must reproduce the above copyright\n *     notice, this list of conditions and the following disclaimer in the\n *     documentation and/or other materials provided with the distribution.\n *   * Neither the name of Redis nor the names of its contributors may be used\n *     to endorse or promote products derived from this software without\n *     specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\"\n * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\n * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE\n * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR\n * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF\n * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS\n * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN\n * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)\n * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE\n * POSSIBILITY OF SUCH DAMAGE.\n */\n\n#include \"server.h\"\n#include \"cluster.h\"\n#include \"slowlog.h\"\n#include \"bio.h\"\n#include \"latency.h\"\n\n#include <time.h>\n#include <signal.h>\n#include <sys/wait.h>\n#include <errno.h>\n#include <assert.h>\n#include <ctype.h>\n#include <stdarg.h>\n#include <arpa/inet.h>\n#include <sys/stat.h>\n#include <fcntl.h>\n#include <sys/time.h>\n#include <sys/resource.h>\n#include <sys/uio.h>\n#include <sys/un.h>\n#include <limits.h>\n#include <float.h>\n#include <math.h>\n#include <sys/resource.h>\n#include <sys/utsname.h>\n#include <locale.h>\n#include <sys/socket.h>\n\n/* Our shared \"common\" objects */\n\nstruct sharedObjectsStruct shared;\n\n/* Global vars that are actually used as constants. The following double\n * values are used for double on-disk serialization, and are initialized\n * at runtime to avoid strange compiler optimizations. */\n\ndouble R_Zero, R_PosInf, R_NegInf, R_Nan;\n\n/*================================= Globals ================================= */\n\n/* Global vars */\nstruct redisServer server; /* server global state */\n\n/* Our command table.\n *\n * Every entry is composed of the following fields:\n *\n * name: a string representing the command name.\n * function: pointer to the C function implementing the command.\n * arity: number of arguments, it is possible to use -N to say >= N\n * sflags: command flags as string. See below for a table of flags.\n * flags: flags as bitmask. Computed by Redis using the 'sflags' field.\n * get_keys_proc: an optional function to get key arguments from a command.\n *                This is only used when the following three fields are not\n *                enough to specify what arguments are keys.\n * first_key_index: first argument that is a key\n * last_key_index: last argument that is a key\n * key_step: step to get all the keys from first to last argument. For instance\n *           in MSET the step is two since arguments are key,val,key,val,...\n * microseconds: microseconds of total execution time for this command.\n * calls: total number of calls of this command.\n *\n * The flags, microseconds and calls fields are computed by Redis and should\n * always be set to zero.\n *\n * Command flags are expressed using strings where every character represents\n * a flag. Later the populateCommandTable() function will take care of\n * populating the real 'flags' field using this characters.\n *\n * This is the meaning of the flags:\n *\n * w: write command (may modify the key space).\n * r: read command  (will never modify the key space).\n * m: may increase memory usage once called. Don't allow if out of memory.\n * a: admin command, like SAVE or SHUTDOWN.\n * p: Pub/Sub related command.\n * f: force replication of this command, regardless of server.dirty.\n * s: command not allowed in scripts.\n * R: random command. Command is not deterministic, that is, the same command\n *    with the same arguments, with the same key space, may have different\n *    results. For instance SPOP and RANDOMKEY are two random commands.\n * S: Sort command output array if called from script, so that the output\n *    is deterministic.\n * l: Allow command while loading the database.\n * t: Allow command while a slave has stale data but is not allowed to\n *    server this data. Normally no command is accepted in this condition\n *    but just a few.\n * M: Do not automatically propagate the command on MONITOR.\n * k: Perform an implicit ASKING for this command, so the command will be\n *    accepted in cluster mode if the slot is marked as 'importing'.\n * F: Fast command: O(1) or O(log(N)) command that should never delay\n *    its execution as long as the kernel scheduler is giving us time.\n *    Note that commands that may trigger a DEL as a side effect (like SET)\n *    are not fast commands.\n */\nstruct redisCommand redisCommandTable[] = {\n    {\"get\",getCommand,2,\"rF\",0,NULL,1,1,1,0,0},\n    {\"set\",setCommand,-3,\"wm\",0,NULL,1,1,1,0,0},\n    {\"setnx\",setnxCommand,3,\"wmF\",0,NULL,1,1,1,0,0},\n    {\"setex\",setexCommand,4,\"wm\",0,NULL,1,1,1,0,0},\n    {\"psetex\",psetexCommand,4,\"wm\",0,NULL,1,1,1,0,0},\n    {\"append\",appendCommand,3,\"wm\",0,NULL,1,1,1,0,0},\n    {\"strlen\",strlenCommand,2,\"rF\",0,NULL,1,1,1,0,0},\n    {\"del\",delCommand,-2,\"w\",0,NULL,1,-1,1,0,0},\n    {\"exists\",existsCommand,-2,\"rF\",0,NULL,1,-1,1,0,0},\n    {\"setbit\",setbitCommand,4,\"wm\",0,NULL,1,1,1,0,0},\n    {\"getbit\",getbitCommand,3,\"rF\",0,NULL,1,1,1,0,0},\n    {\"bitfield\",bitfieldCommand,-2,\"wm\",0,NULL,1,1,1,0,0},\n    {\"setrange\",setrangeCommand,4,\"wm\",0,NULL,1,1,1,0,0},\n    {\"getrange\",getrangeCommand,4,\"r\",0,NULL,1,1,1,0,0},\n    {\"substr\",getrangeCommand,4,\"r\",0,NULL,1,1,1,0,0},\n    {\"incr\",incrCommand,2,\"wmF\",0,NULL,1,1,1,0,0},\n    {\"decr\",decrCommand,2,\"wmF\",0,NULL,1,1,1,0,0},\n    {\"mget\",mgetCommand,-2,\"r\",0,NULL,1,-1,1,0,0},\n    {\"rpush\",rpushCommand,-3,\"wmF\",0,NULL,1,1,1,0,0},\n    {\"lpush\",lpushCommand,-3,\"wmF\",0,NULL,1,1,1,0,0},\n    {\"rpushx\",rpushxCommand,3,\"wmF\",0,NULL,1,1,1,0,0},\n    {\"lpushx\",lpushxCommand,3,\"wmF\",0,NULL,1,1,1,0,0},\n    {\"linsert\",linsertCommand,5,\"wm\",0,NULL,1,1,1,0,0},\n    {\"rpop\",rpopCommand,2,\"wF\",0,NULL,1,1,1,0,0},\n    {\"lpop\",lpopCommand,2,\"wF\",0,NULL,1,1,1,0,0},\n    {\"brpop\",brpopCommand,-3,\"ws\",0,NULL,1,1,1,0,0},\n    {\"brpoplpush\",brpoplpushCommand,4,\"wms\",0,NULL,1,2,1,0,0},\n    {\"blpop\",blpopCommand,-3,\"ws\",0,NULL,1,-2,1,0,0},\n    {\"llen\",llenCommand,2,\"rF\",0,NULL,1,1,1,0,0},\n    {\"lindex\",lindexCommand,3,\"r\",0,NULL,1,1,1,0,0},\n    {\"lset\",lsetCommand,4,\"wm\",0,NULL,1,1,1,0,0},\n    {\"lrange\",lrangeCommand,4,\"r\",0,NULL,1,1,1,0,0},\n    {\"ltrim\",ltrimCommand,4,\"w\",0,NULL,1,1,1,0,0},\n    {\"lrem\",lremCommand,4,\"w\",0,NULL,1,1,1,0,0},\n    {\"rpoplpush\",rpoplpushCommand,3,\"wm\",0,NULL,1,2,1,0,0},\n    {\"sadd\",saddCommand,-3,\"wmF\",0,NULL,1,1,1,0,0},\n    {\"srem\",sremCommand,-3,\"wF\",0,NULL,1,1,1,0,0},\n    {\"smove\",smoveCommand,4,\"wF\",0,NULL,1,2,1,0,0},\n    {\"sismember\",sismemberCommand,3,\"rF\",0,NULL,1,1,1,0,0},\n    {\"scard\",scardCommand,2,\"rF\",0,NULL,1,1,1,0,0},\n    {\"spop\",spopCommand,-2,\"wRF\",0,NULL,1,1,1,0,0},\n    {\"srandmember\",srandmemberCommand,-2,\"rR\",0,NULL,1,1,1,0,0},\n    {\"sinter\",sinterCommand,-2,\"rS\",0,NULL,1,-1,1,0,0},\n    {\"sinterstore\",sinterstoreCommand,-3,\"wm\",0,NULL,1,-1,1,0,0},\n    {\"sunion\",sunionCommand,-2,\"rS\",0,NULL,1,-1,1,0,0},\n    {\"sunionstore\",sunionstoreCommand,-3,\"wm\",0,NULL,1,-1,1,0,0},\n    {\"sdiff\",sdiffCommand,-2,\"rS\",0,NULL,1,-1,1,0,0},\n    {\"sdiffstore\",sdiffstoreCommand,-3,\"wm\",0,NULL,1,-1,1,0,0},\n    {\"smembers\",sinterCommand,2,\"rS\",0,NULL,1,1,1,0,0},\n    {\"sscan\",sscanCommand,-3,\"rR\",0,NULL,1,1,1,0,0},\n    {\"zadd\",zaddCommand,-4,\"wmF\",0,NULL,1,1,1,0,0},\n    {\"zincrby\",zincrbyCommand,4,\"wmF\",0,NULL,1,1,1,0,0},\n    {\"zrem\",zremCommand,-3,\"wF\",0,NULL,1,1,1,0,0},\n    {\"zremrangebyscore\",zremrangebyscoreCommand,4,\"w\",0,NULL,1,1,1,0,0},\n    {\"zremrangebyrank\",zremrangebyrankCommand,4,\"w\",0,NULL,1,1,1,0,0},\n    {\"zremrangebylex\",zremrangebylexCommand,4,\"w\",0,NULL,1,1,1,0,0},\n    {\"zunionstore\",zunionstoreCommand,-4,\"wm\",0,zunionInterGetKeys,0,0,0,0,0},\n    {\"zinterstore\",zinterstoreCommand,-4,\"wm\",0,zunionInterGetKeys,0,0,0,0,0},\n    {\"zrange\",zrangeCommand,-4,\"r\",0,NULL,1,1,1,0,0},\n    {\"zrangebyscore\",zrangebyscoreCommand,-4,\"r\",0,NULL,1,1,1,0,0},\n    {\"zrevrangebyscore\",zrevrangebyscoreCommand,-4,\"r\",0,NULL,1,1,1,0,0},\n    {\"zrangebylex\",zrangebylexCommand,-4,\"r\",0,NULL,1,1,1,0,0},\n    {\"zrevrangebylex\",zrevrangebylexCommand,-4,\"r\",0,NULL,1,1,1,0,0},\n    {\"zcount\",zcountCommand,4,\"rF\",0,NULL,1,1,1,0,0},\n    {\"zlexcount\",zlexcountCommand,4,\"rF\",0,NULL,1,1,1,0,0},\n    {\"zrevrange\",zrevrangeCommand,-4,\"r\",0,NULL,1,1,1,0,0},\n    {\"zcard\",zcardCommand,2,\"rF\",0,NULL,1,1,1,0,0},\n    {\"zscore\",zscoreCommand,3,\"rF\",0,NULL,1,1,1,0,0},\n    {\"zrank\",zrankCommand,3,\"rF\",0,NULL,1,1,1,0,0},\n    {\"zrevrank\",zrevrankCommand,3,\"rF\",0,NULL,1,1,1,0,0},\n    {\"zscan\",zscanCommand,-3,\"rR\",0,NULL,1,1,1,0,0},\n    {\"hset\",hsetCommand,4,\"wmF\",0,NULL,1,1,1,0,0},\n    {\"hsetnx\",hsetnxCommand,4,\"wmF\",0,NULL,1,1,1,0,0},\n    {\"hget\",hgetCommand,3,\"rF\",0,NULL,1,1,1,0,0},\n    {\"hmset\",hmsetCommand,-4,\"wm\",0,NULL,1,1,1,0,0},\n    {\"hmget\",hmgetCommand,-3,\"r\",0,NULL,1,1,1,0,0},\n    {\"hincrby\",hincrbyCommand,4,\"wmF\",0,NULL,1,1,1,0,0},\n    {\"hincrbyfloat\",hincrbyfloatCommand,4,\"wmF\",0,NULL,1,1,1,0,0},\n    {\"hdel\",hdelCommand,-3,\"wF\",0,NULL,1,1,1,0,0},\n    {\"hlen\",hlenCommand,2,\"rF\",0,NULL,1,1,1,0,0},\n    {\"hstrlen\",hstrlenCommand,3,\"rF\",0,NULL,1,1,1,0,0},\n    {\"hkeys\",hkeysCommand,2,\"rS\",0,NULL,1,1,1,0,0},\n    {\"hvals\",hvalsCommand,2,\"rS\",0,NULL,1,1,1,0,0},\n    {\"hgetall\",hgetallCommand,2,\"r\",0,NULL,1,1,1,0,0},\n    {\"hexists\",hexistsCommand,3,\"rF\",0,NULL,1,1,1,0,0},\n    {\"hscan\",hscanCommand,-3,\"rR\",0,NULL,1,1,1,0,0},\n    {\"incrby\",incrbyCommand,3,\"wmF\",0,NULL,1,1,1,0,0},\n    {\"decrby\",decrbyCommand,3,\"wmF\",0,NULL,1,1,1,0,0},\n    {\"incrbyfloat\",incrbyfloatCommand,3,\"wmF\",0,NULL,1,1,1,0,0},\n    {\"getset\",getsetCommand,3,\"wm\",0,NULL,1,1,1,0,0},\n    {\"mset\",msetCommand,-3,\"wm\",0,NULL,1,-1,2,0,0},\n    {\"msetnx\",msetnxCommand,-3,\"wm\",0,NULL,1,-1,2,0,0},\n    {\"randomkey\",randomkeyCommand,1,\"rR\",0,NULL,0,0,0,0,0},\n    {\"select\",selectCommand,2,\"lF\",0,NULL,0,0,0,0,0},\n    {\"move\",moveCommand,3,\"wF\",0,NULL,1,1,1,0,0},\n    {\"rename\",renameCommand,3,\"w\",0,NULL,1,2,1,0,0},\n    {\"renamenx\",renamenxCommand,3,\"wF\",0,NULL,1,2,1,0,0},\n    {\"expire\",expireCommand,3,\"wF\",0,NULL,1,1,1,0,0},\n    {\"expireat\",expireatCommand,3,\"wF\",0,NULL,1,1,1,0,0},\n    {\"pexpire\",pexpireCommand,3,\"wF\",0,NULL,1,1,1,0,0},\n    {\"pexpireat\",pexpireatCommand,3,\"wF\",0,NULL,1,1,1,0,0},\n    {\"keys\",keysCommand,2,\"rS\",0,NULL,0,0,0,0,0},\n    {\"scan\",scanCommand,-2,\"rR\",0,NULL,0,0,0,0,0},\n    {\"dbsize\",dbsizeCommand,1,\"rF\",0,NULL,0,0,0,0,0},\n    {\"auth\",authCommand,2,\"sltF\",0,NULL,0,0,0,0,0},\n    {\"ping\",pingCommand,-1,\"tF\",0,NULL,0,0,0,0,0},\n    {\"echo\",echoCommand,2,\"F\",0,NULL,0,0,0,0,0},\n    {\"save\",saveCommand,1,\"as\",0,NULL,0,0,0,0,0},\n    {\"bgsave\",bgsaveCommand,-1,\"a\",0,NULL,0,0,0,0,0},\n    {\"bgrewriteaof\",bgrewriteaofCommand,1,\"a\",0,NULL,0,0,0,0,0},\n    {\"shutdown\",shutdownCommand,-1,\"alt\",0,NULL,0,0,0,0,0},\n    {\"lastsave\",lastsaveCommand,1,\"RF\",0,NULL,0,0,0,0,0},\n    {\"type\",typeCommand,2,\"rF\",0,NULL,1,1,1,0,0},\n    {\"multi\",multiCommand,1,\"sF\",0,NULL,0,0,0,0,0},\n    {\"exec\",execCommand,1,\"sM\",0,NULL,0,0,0,0,0},\n    {\"discard\",discardCommand,1,\"sF\",0,NULL,0,0,0,0,0},\n    {\"sync\",syncCommand,1,\"ars\",0,NULL,0,0,0,0,0},\n    {\"psync\",syncCommand,3,\"ars\",0,NULL,0,0,0,0,0},\n    {\"replconf\",replconfCommand,-1,\"aslt\",0,NULL,0,0,0,0,0},\n    {\"flushdb\",flushdbCommand,1,\"w\",0,NULL,0,0,0,0,0},\n    {\"flushall\",flushallCommand,1,\"w\",0,NULL,0,0,0,0,0},\n    {\"sort\",sortCommand,-2,\"wm\",0,sortGetKeys,1,1,1,0,0},\n    {\"info\",infoCommand,-1,\"lt\",0,NULL,0,0,0,0,0},\n    {\"monitor\",monitorCommand,1,\"as\",0,NULL,0,0,0,0,0},\n    {\"ttl\",ttlCommand,2,\"rF\",0,NULL,1,1,1,0,0},\n    {\"touch\",touchCommand,-2,\"rF\",0,NULL,1,1,1,0,0},\n    {\"pttl\",pttlCommand,2,\"rF\",0,NULL,1,1,1,0,0},\n    {\"persist\",persistCommand,2,\"wF\",0,NULL,1,1,1,0,0},\n    {\"slaveof\",slaveofCommand,3,\"ast\",0,NULL,0,0,0,0,0},\n    {\"role\",roleCommand,1,\"lst\",0,NULL,0,0,0,0,0},\n    {\"debug\",debugCommand,-1,\"as\",0,NULL,0,0,0,0,0},\n    {\"config\",configCommand,-2,\"lat\",0,NULL,0,0,0,0,0},\n    {\"subscribe\",subscribeCommand,-2,\"pslt\",0,NULL,0,0,0,0,0},\n    {\"unsubscribe\",unsubscribeCommand,-1,\"pslt\",0,NULL,0,0,0,0,0},\n    {\"psubscribe\",psubscribeCommand,-2,\"pslt\",0,NULL,0,0,0,0,0},\n    {\"punsubscribe\",punsubscribeCommand,-1,\"pslt\",0,NULL,0,0,0,0,0},\n    {\"publish\",publishCommand,3,\"pltF\",0,NULL,0,0,0,0,0},\n    {\"pubsub\",pubsubCommand,-2,\"pltR\",0,NULL,0,0,0,0,0},\n    {\"watch\",watchCommand,-2,\"sF\",0,NULL,1,-1,1,0,0},\n    {\"unwatch\",unwatchCommand,1,\"sF\",0,NULL,0,0,0,0,0},\n    {\"cluster\",clusterCommand,-2,\"a\",0,NULL,0,0,0,0,0},\n    {\"restore\",restoreCommand,-4,\"wm\",0,NULL,1,1,1,0,0},\n    {\"restore-asking\",restoreCommand,-4,\"wmk\",0,NULL,1,1,1,0,0},\n    {\"migrate\",migrateCommand,-6,\"w\",0,migrateGetKeys,0,0,0,0,0},\n    {\"asking\",askingCommand,1,\"F\",0,NULL,0,0,0,0,0},\n    {\"readonly\",readonlyCommand,1,\"F\",0,NULL,0,0,0,0,0},\n    {\"readwrite\",readwriteCommand,1,\"F\",0,NULL,0,0,0,0,0},\n    {\"dump\",dumpCommand,2,\"r\",0,NULL,1,1,1,0,0},\n    {\"object\",objectCommand,3,\"r\",0,NULL,2,2,2,0,0},\n    {\"client\",clientCommand,-2,\"as\",0,NULL,0,0,0,0,0},\n    {\"eval\",evalCommand,-3,\"s\",0,evalGetKeys,0,0,0,0,0},\n    {\"evalsha\",evalShaCommand,-3,\"s\",0,evalGetKeys,0,0,0,0,0},\n    {\"slowlog\",slowlogCommand,-2,\"a\",0,NULL,0,0,0,0,0},\n    {\"script\",scriptCommand,-2,\"s\",0,NULL,0,0,0,0,0},\n    {\"time\",timeCommand,1,\"RF\",0,NULL,0,0,0,0,0},\n    {\"bitop\",bitopCommand,-4,\"wm\",0,NULL,2,-1,1,0,0},\n    {\"bitcount\",bitcountCommand,-2,\"r\",0,NULL,1,1,1,0,0},\n    {\"bitpos\",bitposCommand,-3,\"r\",0,NULL,1,1,1,0,0},\n    {\"wait\",waitCommand,3,\"s\",0,NULL,0,0,0,0,0},\n    {\"command\",commandCommand,0,\"lt\",0,NULL,0,0,0,0,0},\n    {\"geoadd\",geoaddCommand,-5,\"wm\",0,NULL,1,1,1,0,0},\n    {\"georadius\",georadiusCommand,-6,\"w\",0,NULL,1,1,1,0,0},\n    {\"georadiusbymember\",georadiusByMemberCommand,-5,\"w\",0,NULL,1,1,1,0,0},\n    {\"geohash\",geohashCommand,-2,\"r\",0,NULL,1,1,1,0,0},\n    {\"geopos\",geoposCommand,-2,\"r\",0,NULL,1,1,1,0,0},\n    {\"geodist\",geodistCommand,-4,\"r\",0,NULL,1,1,1,0,0},\n    {\"pfselftest\",pfselftestCommand,1,\"a\",0,NULL,0,0,0,0,0},\n    {\"pfadd\",pfaddCommand,-2,\"wmF\",0,NULL,1,1,1,0,0},\n    {\"pfcount\",pfcountCommand,-2,\"r\",0,NULL,1,-1,1,0,0},\n    {\"pfmerge\",pfmergeCommand,-2,\"wm\",0,NULL,1,-1,1,0,0},\n    {\"pfdebug\",pfdebugCommand,-3,\"w\",0,NULL,0,0,0,0,0},\n    {\"latency\",latencyCommand,-2,\"aslt\",0,NULL,0,0,0,0,0},\n    {\"slotsinfo\",slotsinfoCommand,-1,\"rF\",0,NULL,0,0,0,0,0},\n    {\"slotsscan\",slotsscanCommand,-3,\"rR\",0,NULL,0,0,0,0,0},\n    {\"slotsdel\",slotsdelCommand,-2,\"w\",0,NULL,1,-1,1,0,0},\n    {\"slotsmgrtslot\",slotsmgrtslotCommand,5,\"aw\",0,NULL,0,0,0,0,0},\n    {\"slotsmgrtone\",slotsmgrtoneCommand,5,\"aw\",0,NULL,0,0,0,0,0},\n    {\"slotsmgrttagslot\",slotsmgrttagslotCommand,5,\"aw\",0,NULL,0,0,0,0,0},\n    {\"slotsmgrttagone\",slotsmgrttagoneCommand,5,\"aw\",0,NULL,0,0,0,0,0},\n    {\"slotshashkey\",slotshashkeyCommand,-1,\"rF\",0,NULL,0,0,0,0,0},\n    {\"slotscheck\",slotscheckCommand,0,\"r\",0,NULL,0,0,0,0,0},\n    {\"slotsrestore\",slotsrestoreCommand,-4,\"awm\",0,NULL,1,1,1,0,0},\n};\n\nstruct evictionPoolEntry *evictionPoolAlloc(void);\n\n/*============================ Utility functions ============================ */\n\n/* Low level logging. To use only for very big messages, otherwise\n * serverLog() is to prefer. */\nvoid serverLogRaw(int level, const char *msg) {\n    const int syslogLevelMap[] = { LOG_DEBUG, LOG_INFO, LOG_NOTICE, LOG_WARNING };\n    const char *c = \".-*#\";\n    FILE *fp;\n    char buf[64];\n    int rawmode = (level & LL_RAW);\n    int log_to_stdout = server.logfile[0] == '\\0';\n\n    level &= 0xff; /* clear flags */\n    if (level < server.verbosity) return;\n\n    fp = log_to_stdout ? stdout : fopen(server.logfile,\"a\");\n    if (!fp) return;\n\n    if (rawmode) {\n        fprintf(fp,\"%s\",msg);\n    } else {\n        int off;\n        struct timeval tv;\n        int role_char;\n        pid_t pid = getpid();\n\n        gettimeofday(&tv,NULL);\n        off = strftime(buf,sizeof(buf),\"%d %b %H:%M:%S.\",localtime(&tv.tv_sec));\n        snprintf(buf+off,sizeof(buf)-off,\"%03d\",(int)tv.tv_usec/1000);\n        if (server.sentinel_mode) {\n            role_char = 'X'; /* Sentinel. */\n        } else if (pid != server.pid) {\n            role_char = 'C'; /* RDB / AOF writing child. */\n        } else {\n            role_char = (server.masterhost ? 'S':'M'); /* Slave or Master. */\n        }\n        fprintf(fp,\"%d:%c %s %c %s\\n\",\n            (int)getpid(),role_char, buf,c[level],msg);\n    }\n    fflush(fp);\n\n    if (!log_to_stdout) fclose(fp);\n    if (server.syslog_enabled) syslog(syslogLevelMap[level], \"%s\", msg);\n}\n\n/* Like serverLogRaw() but with printf-alike support. This is the function that\n * is used across the code. The raw version is only used in order to dump\n * the INFO output on crash. */\nvoid serverLog(int level, const char *fmt, ...) {\n    va_list ap;\n    char msg[LOG_MAX_LEN];\n\n    if ((level&0xff) < server.verbosity) return;\n\n    va_start(ap, fmt);\n    vsnprintf(msg, sizeof(msg), fmt, ap);\n    va_end(ap);\n\n    serverLogRaw(level,msg);\n}\n\n/* Log a fixed message without printf-alike capabilities, in a way that is\n * safe to call from a signal handler.\n *\n * We actually use this only for signals that are not fatal from the point\n * of view of Redis. Signals that are going to kill the server anyway and\n * where we need printf-alike features are served by serverLog(). */\nvoid serverLogFromHandler(int level, const char *msg) {\n    int fd;\n    int log_to_stdout = server.logfile[0] == '\\0';\n    char buf[64];\n\n    if ((level&0xff) < server.verbosity || (log_to_stdout && server.daemonize))\n        return;\n    fd = log_to_stdout ? STDOUT_FILENO :\n                         open(server.logfile, O_APPEND|O_CREAT|O_WRONLY, 0644);\n    if (fd == -1) return;\n    ll2string(buf,sizeof(buf),getpid());\n    if (write(fd,buf,strlen(buf)) == -1) goto err;\n    if (write(fd,\":signal-handler (\",17) == -1) goto err;\n    ll2string(buf,sizeof(buf),time(NULL));\n    if (write(fd,buf,strlen(buf)) == -1) goto err;\n    if (write(fd,\") \",2) == -1) goto err;\n    if (write(fd,msg,strlen(msg)) == -1) goto err;\n    if (write(fd,\"\\n\",1) == -1) goto err;\nerr:\n    if (!log_to_stdout) close(fd);\n}\n\n/* Return the UNIX time in microseconds */\nlong long ustime(void) {\n    struct timeval tv;\n    long long ust;\n\n    gettimeofday(&tv, NULL);\n    ust = ((long long)tv.tv_sec)*1000000;\n    ust += tv.tv_usec;\n    return ust;\n}\n\n/* Return the UNIX time in milliseconds */\nmstime_t mstime(void) {\n    return ustime()/1000;\n}\n\n/* After an RDB dump or AOF rewrite we exit from children using _exit() instead of\n * exit(), because the latter may interact with the same file objects used by\n * the parent process. However if we are testing the coverage normal exit() is\n * used in order to obtain the right coverage information. */\nvoid exitFromChild(int retcode) {\n#ifdef COVERAGE_TEST\n    exit(retcode);\n#else\n    _exit(retcode);\n#endif\n}\n\n/*====================== Hash table type implementation  ==================== */\n\n/* This is a hash table type that uses the SDS dynamic strings library as\n * keys and redis objects as values (objects can hold SDS strings,\n * lists, sets). */\n\nvoid dictVanillaFree(void *privdata, void *val)\n{\n    DICT_NOTUSED(privdata);\n    zfree(val);\n}\n\nvoid dictListDestructor(void *privdata, void *val)\n{\n    DICT_NOTUSED(privdata);\n    listRelease((list*)val);\n}\n\nint dictSdsKeyCompare(void *privdata, const void *key1,\n        const void *key2)\n{\n    int l1,l2;\n    DICT_NOTUSED(privdata);\n\n    l1 = sdslen((sds)key1);\n    l2 = sdslen((sds)key2);\n    if (l1 != l2) return 0;\n    return memcmp(key1, key2, l1) == 0;\n}\n\n/* A case insensitive version used for the command lookup table and other\n * places where case insensitive non binary-safe comparison is needed. */\nint dictSdsKeyCaseCompare(void *privdata, const void *key1,\n        const void *key2)\n{\n    DICT_NOTUSED(privdata);\n\n    return strcasecmp(key1, key2) == 0;\n}\n\nvoid dictObjectDestructor(void *privdata, void *val)\n{\n    DICT_NOTUSED(privdata);\n\n    if (val == NULL) return; /* Values of swapped out keys as set to NULL */\n    decrRefCount(val);\n}\n\nvoid dictSdsDestructor(void *privdata, void *val)\n{\n    DICT_NOTUSED(privdata);\n\n    sdsfree(val);\n}\n\nint dictObjKeyCompare(void *privdata, const void *key1,\n        const void *key2)\n{\n    const robj *o1 = key1, *o2 = key2;\n    return dictSdsKeyCompare(privdata,o1->ptr,o2->ptr);\n}\n\nunsigned int dictObjHash(const void *key) {\n    const robj *o = key;\n    return dictGenHashFunction(o->ptr, sdslen((sds)o->ptr));\n}\n\nunsigned int dictSdsHash(const void *key) {\n    return dictGenHashFunction((unsigned char*)key, sdslen((char*)key));\n}\n\nunsigned int dictSdsCaseHash(const void *key) {\n    return dictGenCaseHashFunction((unsigned char*)key, sdslen((char*)key));\n}\n\nint dictEncObjKeyCompare(void *privdata, const void *key1,\n        const void *key2)\n{\n    robj *o1 = (robj*) key1, *o2 = (robj*) key2;\n    int cmp;\n\n    if (o1->encoding == OBJ_ENCODING_INT &&\n        o2->encoding == OBJ_ENCODING_INT)\n            return o1->ptr == o2->ptr;\n\n    o1 = getDecodedObject(o1);\n    o2 = getDecodedObject(o2);\n    cmp = dictSdsKeyCompare(privdata,o1->ptr,o2->ptr);\n    decrRefCount(o1);\n    decrRefCount(o2);\n    return cmp;\n}\n\nunsigned int dictEncObjHash(const void *key) {\n    robj *o = (robj*) key;\n\n    if (sdsEncodedObject(o)) {\n        return dictGenHashFunction(o->ptr, sdslen((sds)o->ptr));\n    } else {\n        if (o->encoding == OBJ_ENCODING_INT) {\n            char buf[32];\n            int len;\n\n            len = ll2string(buf,32,(long)o->ptr);\n            return dictGenHashFunction((unsigned char*)buf, len);\n        } else {\n            unsigned int hash;\n\n            o = getDecodedObject(o);\n            hash = dictGenHashFunction(o->ptr, sdslen((sds)o->ptr));\n            decrRefCount(o);\n            return hash;\n        }\n    }\n}\n\n/* Sets type hash table */\ndictType setDictType = {\n    dictEncObjHash,            /* hash function */\n    NULL,                      /* key dup */\n    NULL,                      /* val dup */\n    dictEncObjKeyCompare,      /* key compare */\n    dictObjectDestructor, /* key destructor */\n    NULL                       /* val destructor */\n};\n\n/* Sorted sets hash (note: a skiplist is used in addition to the hash table) */\ndictType zsetDictType = {\n    dictEncObjHash,            /* hash function */\n    NULL,                      /* key dup */\n    NULL,                      /* val dup */\n    dictEncObjKeyCompare,      /* key compare */\n    dictObjectDestructor, /* key destructor */\n    NULL                       /* val destructor */\n};\n\n/* Db->dict, keys are sds strings, vals are Redis objects. */\ndictType dbDictType = {\n    dictSdsHash,                /* hash function */\n    NULL,                       /* key dup */\n    NULL,                       /* val dup */\n    dictSdsKeyCompare,          /* key compare */\n    dictSdsDestructor,          /* key destructor */\n    dictObjectDestructor   /* val destructor */\n};\n\ndictType hashSlotType = {\n    dictSdsHash,                /* hash function */\n    NULL,                       /* key dup */\n    NULL,                       /* val dup */\n    dictSdsKeyCompare,          /* key compare */\n    NULL,                       /* key destructor */\n    NULL                        /* val destructor */\n};\n\n/* server.lua_scripts sha (as sds string) -> scripts (as robj) cache. */\ndictType shaScriptObjectDictType = {\n    dictSdsCaseHash,            /* hash function */\n    NULL,                       /* key dup */\n    NULL,                       /* val dup */\n    dictSdsKeyCaseCompare,      /* key compare */\n    dictSdsDestructor,          /* key destructor */\n    dictObjectDestructor   /* val destructor */\n};\n\n/* Db->expires */\ndictType keyptrDictType = {\n    dictSdsHash,               /* hash function */\n    NULL,                      /* key dup */\n    NULL,                      /* val dup */\n    dictSdsKeyCompare,         /* key compare */\n    NULL,                      /* key destructor */\n    NULL                       /* val destructor */\n};\n\n/* Command table. sds string -> command struct pointer. */\ndictType commandTableDictType = {\n    dictSdsCaseHash,           /* hash function */\n    NULL,                      /* key dup */\n    NULL,                      /* val dup */\n    dictSdsKeyCaseCompare,     /* key compare */\n    dictSdsDestructor,         /* key destructor */\n    NULL                       /* val destructor */\n};\n\n/* Hash type hash table (note that small hashes are represented with ziplists) */\ndictType hashDictType = {\n    dictEncObjHash,             /* hash function */\n    NULL,                       /* key dup */\n    NULL,                       /* val dup */\n    dictEncObjKeyCompare,       /* key compare */\n    dictObjectDestructor,  /* key destructor */\n    dictObjectDestructor   /* val destructor */\n};\n\n/* Keylist hash table type has unencoded redis objects as keys and\n * lists as values. It's used for blocking operations (BLPOP) and to\n * map swapped keys to a list of clients waiting for this keys to be loaded. */\ndictType keylistDictType = {\n    dictObjHash,                /* hash function */\n    NULL,                       /* key dup */\n    NULL,                       /* val dup */\n    dictObjKeyCompare,          /* key compare */\n    dictObjectDestructor,  /* key destructor */\n    dictListDestructor          /* val destructor */\n};\n\n/* Cluster nodes hash table, mapping nodes addresses 1.2.3.4:6379 to\n * clusterNode structures. */\ndictType clusterNodesDictType = {\n    dictSdsHash,                /* hash function */\n    NULL,                       /* key dup */\n    NULL,                       /* val dup */\n    dictSdsKeyCompare,          /* key compare */\n    dictSdsDestructor,          /* key destructor */\n    NULL                        /* val destructor */\n};\n\n/* Cluster re-addition blacklist. This maps node IDs to the time\n * we can re-add this node. The goal is to avoid readding a removed\n * node for some time. */\ndictType clusterNodesBlackListDictType = {\n    dictSdsCaseHash,            /* hash function */\n    NULL,                       /* key dup */\n    NULL,                       /* val dup */\n    dictSdsKeyCaseCompare,      /* key compare */\n    dictSdsDestructor,          /* key destructor */\n    NULL                        /* val destructor */\n};\n\n/* Migrate cache dict type. */\ndictType migrateCacheDictType = {\n    dictSdsHash,                /* hash function */\n    NULL,                       /* key dup */\n    NULL,                       /* val dup */\n    dictSdsKeyCompare,          /* key compare */\n    dictSdsDestructor,          /* key destructor */\n    NULL                        /* val destructor */\n};\n\n/* Replication cached script dict (server.repl_scriptcache_dict).\n * Keys are sds SHA1 strings, while values are not used at all in the current\n * implementation. */\ndictType replScriptCacheDictType = {\n    dictSdsCaseHash,            /* hash function */\n    NULL,                       /* key dup */\n    NULL,                       /* val dup */\n    dictSdsKeyCaseCompare,      /* key compare */\n    dictSdsDestructor,          /* key destructor */\n    NULL                        /* val destructor */\n};\n\nint htNeedsResize(dict *dict) {\n    long long size, used;\n\n    size = dictSlots(dict);\n    used = dictSize(dict);\n    return (size > DICT_HT_INITIAL_SIZE &&\n            (used*100/size < HASHTABLE_MIN_FILL));\n}\n\n/* If the percentage of used slots in the HT reaches HASHTABLE_MIN_FILL\n * we resize the hash table to save memory */\nvoid tryResizeHashTables(int dbid) {\n    if (htNeedsResize(server.db[dbid].dict)) {\n        dictResize(server.db[dbid].dict);\n        for (int i = 0; i < HASH_SLOTS_SIZE; i ++) {\n            dict *d = server.db[dbid].hash_slots[i];\n            if (htNeedsResize(d)) {\n                dictResize(d);\n            }\n        }\n    }\n    if (htNeedsResize(server.db[dbid].expires))\n        dictResize(server.db[dbid].expires);\n}\n\n/* Our hash table implementation performs rehashing incrementally while\n * we write/read from the hash table. Still if the server is idle, the hash\n * table will use two tables for a long time. So we try to use 1 millisecond\n * of CPU time at every call of this function to perform some rehahsing.\n *\n * The function returns 1 if some rehashing was performed, otherwise 0\n * is returned. */\nint incrementallyRehash(int dbid) {\n    /* Keys dictionary */\n    if (dictIsRehashing(server.db[dbid].dict)) {\n        dictRehashMilliseconds(server.db[dbid].dict,1);\n\n        long long start = timeInMilliseconds();\n        for (int i = 0; i < HASH_SLOTS_SIZE; i ++) {\n            int idx = ((i + start) & HASH_SLOTS_MASK);\n            dict *d = server.db[dbid].hash_slots[idx];\n            if (dictIsRehashing(d)) {\n                dictRehashMilliseconds(d, 1);\n                if (timeInMilliseconds() != start) {\n                    break;\n                }\n            }\n        }\n        return 1; /* already used our millisecond for this loop... */\n    }\n    /* Expires */\n    if (dictIsRehashing(server.db[dbid].expires)) {\n        dictRehashMilliseconds(server.db[dbid].expires,1);\n        return 1; /* already used our millisecond for this loop... */\n    }\n    return 0;\n}\n\n/* This function is called once a background process of some kind terminates,\n * as we want to avoid resizing the hash tables when there is a child in order\n * to play well with copy-on-write (otherwise when a resize happens lots of\n * memory pages are copied). The goal of this function is to update the ability\n * for dict.c to resize the hash tables accordingly to the fact we have o not\n * running childs. */\nvoid updateDictResizePolicy(void) {\n    if (server.rdb_child_pid == -1 && server.aof_child_pid == -1)\n        dictEnableResize();\n    else\n        dictDisableResize();\n}\n\n/* ======================= Cron: called every 100 ms ======================== */\n\n/* Helper function for the activeExpireCycle() function.\n * This function will try to expire the key that is stored in the hash table\n * entry 'de' of the 'expires' hash table of a Redis database.\n *\n * If the key is found to be expired, it is removed from the database and\n * 1 is returned. Otherwise no operation is performed and 0 is returned.\n *\n * When a key is expired, server.stat_expiredkeys is incremented.\n *\n * The parameter 'now' is the current time in milliseconds as is passed\n * to the function to avoid too many gettimeofday() syscalls. */\nint activeExpireCycleTryExpire(redisDb *db, dictEntry *de, long long now) {\n    long long t = dictGetSignedIntegerVal(de);\n    if (now > t) {\n        sds key = dictGetKey(de);\n        robj *keyobj = createStringObject(key,sdslen(key));\n\n        propagateExpire(db,keyobj);\n        dbDelete(db,keyobj);\n        notifyKeyspaceEvent(NOTIFY_EXPIRED,\n            \"expired\",keyobj,db->id);\n        decrRefCount(keyobj);\n        server.stat_expiredkeys++;\n        return 1;\n    } else {\n        return 0;\n    }\n}\n\n/* Try to expire a few timed out keys. The algorithm used is adaptive and\n * will use few CPU cycles if there are few expiring keys, otherwise\n * it will get more aggressive to avoid that too much memory is used by\n * keys that can be removed from the keyspace.\n *\n * No more than CRON_DBS_PER_CALL databases are tested at every\n * iteration.\n *\n * This kind of call is used when Redis detects that timelimit_exit is\n * true, so there is more work to do, and we do it more incrementally from\n * the beforeSleep() function of the event loop.\n *\n * Expire cycle type:\n *\n * If type is ACTIVE_EXPIRE_CYCLE_FAST the function will try to run a\n * \"fast\" expire cycle that takes no longer than EXPIRE_FAST_CYCLE_DURATION\n * microseconds, and is not repeated again before the same amount of time.\n *\n * If type is ACTIVE_EXPIRE_CYCLE_SLOW, that normal expire cycle is\n * executed, where the time limit is a percentage of the REDIS_HZ period\n * as specified by the REDIS_EXPIRELOOKUPS_TIME_PERC define. */\n\nvoid activeExpireCycle(int type) {\n    /* This function has some global state in order to continue the work\n     * incrementally across calls. */\n    static unsigned int current_db = 0; /* Last DB tested. */\n    static int timelimit_exit = 0;      /* Time limit hit in previous call? */\n    static long long last_fast_cycle = 0; /* When last fast cycle ran. */\n\n    int j, iteration = 0;\n    int dbs_per_call = CRON_DBS_PER_CALL;\n    long long start = ustime(), timelimit;\n\n    if (type == ACTIVE_EXPIRE_CYCLE_FAST) {\n        /* Don't start a fast cycle if the previous cycle did not exited\n         * for time limt. Also don't repeat a fast cycle for the same period\n         * as the fast cycle total duration itself. */\n        if (!timelimit_exit) return;\n        if (start < last_fast_cycle + ACTIVE_EXPIRE_CYCLE_FAST_DURATION*2) return;\n        last_fast_cycle = start;\n    }\n\n    /* We usually should test CRON_DBS_PER_CALL per iteration, with\n     * two exceptions:\n     *\n     * 1) Don't test more DBs than we have.\n     * 2) If last time we hit the time limit, we want to scan all DBs\n     * in this iteration, as there is work to do in some DB and we don't want\n     * expired keys to use memory for too much time. */\n    if (dbs_per_call > server.dbnum || timelimit_exit)\n        dbs_per_call = server.dbnum;\n\n    /* We can use at max ACTIVE_EXPIRE_CYCLE_SLOW_TIME_PERC percentage of CPU time\n     * per iteration. Since this function gets called with a frequency of\n     * server.hz times per second, the following is the max amount of\n     * microseconds we can spend in this function. */\n    timelimit = 1000000*ACTIVE_EXPIRE_CYCLE_SLOW_TIME_PERC/server.hz/100;\n    timelimit_exit = 0;\n    if (timelimit <= 0) timelimit = 1;\n\n    if (type == ACTIVE_EXPIRE_CYCLE_FAST)\n        timelimit = ACTIVE_EXPIRE_CYCLE_FAST_DURATION; /* in microseconds. */\n\n    for (j = 0; j < dbs_per_call; j++) {\n        int expired;\n        redisDb *db = server.db+(current_db % server.dbnum);\n\n        /* Increment the DB now so we are sure if we run out of time\n         * in the current DB we'll restart from the next. This allows to\n         * distribute the time evenly across DBs. */\n        current_db++;\n\n        /* Continue to expire if at the end of the cycle more than 25%\n         * of the keys were expired. */\n        do {\n            unsigned long num, slots;\n            long long now, ttl_sum;\n            int ttl_samples;\n\n            /* If there is nothing to expire try next DB ASAP. */\n            if ((num = dictSize(db->expires)) == 0) {\n                db->avg_ttl = 0;\n                break;\n            }\n            slots = dictSlots(db->expires);\n            now = mstime();\n\n            /* When there are less than 1% filled slots getting random\n             * keys is expensive, so stop here waiting for better times...\n             * The dictionary will be resized asap. */\n            if (num && slots > DICT_HT_INITIAL_SIZE &&\n                (num*100/slots < 1)) break;\n\n            /* The main collection cycle. Sample random keys among keys\n             * with an expire set, checking for expired ones. */\n            expired = 0;\n            ttl_sum = 0;\n            ttl_samples = 0;\n\n            if (num > ACTIVE_EXPIRE_CYCLE_LOOKUPS_PER_LOOP)\n                num = ACTIVE_EXPIRE_CYCLE_LOOKUPS_PER_LOOP;\n\n            while (num--) {\n                dictEntry *de;\n                long long ttl;\n\n                if ((de = dictGetRandomKey(db->expires)) == NULL) break;\n                ttl = dictGetSignedIntegerVal(de)-now;\n                if (activeExpireCycleTryExpire(db,de,now)) expired++;\n                if (ttl > 0) {\n                    /* We want the average TTL of keys yet not expired. */\n                    ttl_sum += ttl;\n                    ttl_samples++;\n                }\n            }\n\n            /* Update the average TTL stats for this database. */\n            if (ttl_samples) {\n                long long avg_ttl = ttl_sum/ttl_samples;\n\n                /* Do a simple running average with a few samples.\n                 * We just use the current estimate with a weight of 2%\n                 * and the previous estimate with a weight of 98%. */\n                if (db->avg_ttl == 0) db->avg_ttl = avg_ttl;\n                db->avg_ttl = (db->avg_ttl/50)*49 + (avg_ttl/50);\n            }\n\n            /* We can't block forever here even if there are many keys to\n             * expire. So after a given amount of milliseconds return to the\n             * caller waiting for the other active expire cycle. */\n            iteration++;\n            if ((iteration & 0xf) == 0) { /* check once every 16 iterations. */\n                long long elapsed = ustime()-start;\n\n                latencyAddSampleIfNeeded(\"expire-cycle\",elapsed/1000);\n                if (elapsed > timelimit) timelimit_exit = 1;\n            }\n            if (timelimit_exit) return;\n            /* We don't repeat the cycle if there are less than 25% of keys\n             * found expired in the current DB. */\n        } while (expired > ACTIVE_EXPIRE_CYCLE_LOOKUPS_PER_LOOP/4);\n    }\n}\n\nunsigned int getLRUClock(void) {\n    return (mstime()/LRU_CLOCK_RESOLUTION) & LRU_CLOCK_MAX;\n}\n\n/* Add a sample to the operations per second array of samples. */\nvoid trackInstantaneousMetric(int metric, long long current_reading) {\n    long long t = mstime() - server.inst_metric[metric].last_sample_time;\n    long long ops = current_reading -\n                    server.inst_metric[metric].last_sample_count;\n    long long ops_sec;\n\n    ops_sec = t > 0 ? (ops*1000/t) : 0;\n\n    server.inst_metric[metric].samples[server.inst_metric[metric].idx] =\n        ops_sec;\n    server.inst_metric[metric].idx++;\n    server.inst_metric[metric].idx %= STATS_METRIC_SAMPLES;\n    server.inst_metric[metric].last_sample_time = mstime();\n    server.inst_metric[metric].last_sample_count = current_reading;\n}\n\n/* Return the mean of all the samples. */\nlong long getInstantaneousMetric(int metric) {\n    int j;\n    long long sum = 0;\n\n    for (j = 0; j < STATS_METRIC_SAMPLES; j++)\n        sum += server.inst_metric[metric].samples[j];\n    return sum / STATS_METRIC_SAMPLES;\n}\n\n/* Check for timeouts. Returns non-zero if the client was terminated.\n * The function gets the current time in milliseconds as argument since\n * it gets called multiple times in a loop, so calling gettimeofday() for\n * each iteration would be costly without any actual gain. */\nint clientsCronHandleTimeout(client *c, mstime_t now_ms) {\n    time_t now = now_ms/1000;\n\n    if (server.maxidletime &&\n        !(c->flags & CLIENT_SLAVE) &&    /* no timeout for slaves */\n        !(c->flags & CLIENT_MASTER) &&   /* no timeout for masters */\n        !(c->flags & CLIENT_BLOCKED) &&  /* no timeout for BLPOP */\n        !(c->flags & CLIENT_PUBSUB) &&   /* no timeout for Pub/Sub clients */\n        (now - c->lastinteraction > server.maxidletime))\n    {\n        serverLog(LL_VERBOSE,\"Closing idle client\");\n        freeClient(c);\n        return 1;\n    } else if (c->flags & CLIENT_BLOCKED) {\n        /* Blocked OPS timeout is handled with milliseconds resolution.\n         * However note that the actual resolution is limited by\n         * server.hz. */\n\n        if (c->bpop.timeout != 0 && c->bpop.timeout < now_ms) {\n            /* Handle blocking operation specific timeout. */\n            replyToBlockedClientTimedOut(c);\n            unblockClient(c);\n        } else if (server.cluster_enabled) {\n            /* Cluster: handle unblock & redirect of clients blocked\n             * into keys no longer served by this server. */\n            if (clusterRedirectBlockedClientIfNeeded(c))\n                unblockClient(c);\n        }\n    }\n    return 0;\n}\n\n/* The client query buffer is an sds.c string that can end with a lot of\n * free space not used, this function reclaims space if needed.\n *\n * The function always returns 0 as it never terminates the client. */\nint clientsCronResizeQueryBuffer(client *c) {\n    size_t querybuf_size = sdsAllocSize(c->querybuf);\n    time_t idletime = server.unixtime - c->lastinteraction;\n\n    /* There are two conditions to resize the query buffer:\n     * 1) Query buffer is > BIG_ARG and too big for latest peak.\n     * 2) Client is inactive and the buffer is bigger than 1k. */\n    if (((querybuf_size > PROTO_MBULK_BIG_ARG) &&\n         (querybuf_size/(c->querybuf_peak+1)) > 2) ||\n         (querybuf_size > 1024 && idletime > 2))\n    {\n        /* Only resize the query buffer if it is actually wasting space. */\n        if (sdsavail(c->querybuf) > 1024) {\n            c->querybuf = sdsRemoveFreeSpace(c->querybuf);\n        }\n    }\n    /* Reset the peak again to capture the peak memory usage in the next\n     * cycle. */\n    c->querybuf_peak = 0;\n    return 0;\n}\n\n#define CLIENTS_CRON_MIN_ITERATIONS 5\nvoid clientsCron(void) {\n    /* Make sure to process at least numclients/server.hz of clients\n     * per call. Since this function is called server.hz times per second\n     * we are sure that in the worst case we process all the clients in 1\n     * second. */\n    int numclients = listLength(server.clients);\n    int iterations = numclients/server.hz;\n    mstime_t now = mstime();\n\n    /* Process at least a few clients while we are at it, even if we need\n     * to process less than CLIENTS_CRON_MIN_ITERATIONS to meet our contract\n     * of processing each client once per second. */\n    if (iterations < CLIENTS_CRON_MIN_ITERATIONS)\n        iterations = (numclients < CLIENTS_CRON_MIN_ITERATIONS) ?\n                     numclients : CLIENTS_CRON_MIN_ITERATIONS;\n\n    while(listLength(server.clients) && iterations--) {\n        client *c;\n        listNode *head;\n\n        /* Rotate the list, take the current head, process.\n         * This way if the client must be removed from the list it's the\n         * first element and we don't incur into O(N) computation. */\n        listRotate(server.clients);\n        head = listFirst(server.clients);\n        c = listNodeValue(head);\n        /* The following functions do different service checks on the client.\n         * The protocol is that they return non-zero if the client was\n         * terminated. */\n        if (clientsCronHandleTimeout(c,now)) continue;\n        if (clientsCronResizeQueryBuffer(c)) continue;\n    }\n}\n\n/* This function handles 'background' operations we are required to do\n * incrementally in Redis databases, such as active key expiring, resizing,\n * rehashing. */\nvoid databasesCron(void) {\n    /* Expire keys by random sampling. Not required for slaves\n     * as master will synthesize DELs for us. */\n    if (server.active_expire_enabled && server.masterhost == NULL)\n        activeExpireCycle(ACTIVE_EXPIRE_CYCLE_SLOW);\n\n    /* Perform hash tables rehashing if needed, but only if there are no\n     * other processes saving the DB on disk. Otherwise rehashing is bad\n     * as will cause a lot of copy-on-write of memory pages. */\n    if (server.rdb_child_pid == -1 && server.aof_child_pid == -1) {\n        /* We use global counters so if we stop the computation at a given\n         * DB we'll be able to start from the successive in the next\n         * cron loop iteration. */\n        static unsigned int resize_db = 0;\n        static unsigned int rehash_db = 0;\n        int dbs_per_call = CRON_DBS_PER_CALL;\n        int j;\n\n        /* Don't test more DBs than we have. */\n        if (dbs_per_call > server.dbnum) dbs_per_call = server.dbnum;\n\n        /* Resize */\n        for (j = 0; j < dbs_per_call; j++) {\n            tryResizeHashTables(resize_db % server.dbnum);\n            resize_db++;\n        }\n\n        /* Rehash */\n        if (server.activerehashing) {\n            for (j = 0; j < dbs_per_call; j++) {\n                int work_done = incrementallyRehash(rehash_db % server.dbnum);\n                rehash_db++;\n                if (work_done) {\n                    /* If the function did some work, stop here, we'll do\n                     * more at the next cron loop. */\n                    break;\n                }\n            }\n        }\n    }\n}\n\n/* We take a cached value of the unix time in the global state because with\n * virtual memory and aging there is to store the current time in objects at\n * every object access, and accuracy is not needed. To access a global var is\n * a lot faster than calling time(NULL) */\nvoid updateCachedTime(void) {\n    server.unixtime = time(NULL);\n    server.mstime = mstime();\n}\n\n/* This is our timer interrupt, called server.hz times per second.\n * Here is where we do a number of things that need to be done asynchronously.\n * For instance:\n *\n * - Active expired keys collection (it is also performed in a lazy way on\n *   lookup).\n * - Software watchdog.\n * - Update some statistic.\n * - Incremental rehashing of the DBs hash tables.\n * - Triggering BGSAVE / AOF rewrite, and handling of terminated children.\n * - Clients timeout of different kinds.\n * - Replication reconnection.\n * - Many more...\n *\n * Everything directly called here will be called server.hz times per second,\n * so in order to throttle execution of things we want to do less frequently\n * a macro is used: run_with_period(milliseconds) { .... }\n */\n\nint serverCron(struct aeEventLoop *eventLoop, long long id, void *clientData) {\n    int j;\n    UNUSED(eventLoop);\n    UNUSED(id);\n    UNUSED(clientData);\n\n    /* Software watchdog: deliver the SIGALRM that will reach the signal\n     * handler if we don't return here fast enough. */\n    if (server.watchdog_period) watchdogScheduleSignal(server.watchdog_period);\n\n    /* Update the time cache. */\n    updateCachedTime();\n\n    run_with_period(100) {\n        trackInstantaneousMetric(STATS_METRIC_COMMAND,server.stat_numcommands);\n        trackInstantaneousMetric(STATS_METRIC_NET_INPUT,\n                server.stat_net_input_bytes);\n        trackInstantaneousMetric(STATS_METRIC_NET_OUTPUT,\n                server.stat_net_output_bytes);\n    }\n\n    /* We have just LRU_BITS bits per object for LRU information.\n     * So we use an (eventually wrapping) LRU clock.\n     *\n     * Note that even if the counter wraps it's not a big problem,\n     * everything will still work but some object will appear younger\n     * to Redis. However for this to happen a given object should never be\n     * touched for all the time needed to the counter to wrap, which is\n     * not likely.\n     *\n     * Note that you can change the resolution altering the\n     * LRU_CLOCK_RESOLUTION define. */\n    server.lruclock = getLRUClock();\n\n    /* Record the max memory used since the server was started. */\n    if (zmalloc_used_memory() > server.stat_peak_memory)\n        server.stat_peak_memory = zmalloc_used_memory();\n\n    /* Sample the RSS here since this is a relatively slow call. */\n    server.resident_set_size = zmalloc_get_rss();\n\n    /* We received a SIGTERM, shutting down here in a safe way, as it is\n     * not ok doing so inside the signal handler. */\n    if (server.shutdown_asap) {\n        if (prepareForShutdown(SHUTDOWN_NOFLAGS) == C_OK) exit(0);\n        serverLog(LL_WARNING,\"SIGTERM received but errors trying to shut down the server, check the logs for more information\");\n        server.shutdown_asap = 0;\n    }\n\n    /* Show some info about non-empty databases */\n    run_with_period(5000) {\n        for (j = 0; j < server.dbnum; j++) {\n            long long size, used, vkeys;\n\n            size = dictSlots(server.db[j].dict);\n            used = dictSize(server.db[j].dict);\n            vkeys = dictSize(server.db[j].expires);\n            if (used || vkeys) {\n                serverLog(LL_VERBOSE,\"DB %d: %lld keys (%lld volatile) in %lld slots HT.\",j,used,vkeys,size);\n                /* dictPrintStats(server.dict); */\n            }\n        }\n    }\n\n    /* Show information about connected clients */\n    if (!server.sentinel_mode) {\n        run_with_period(5000) {\n            serverLog(LL_VERBOSE,\n                \"%lu clients connected (%lu slaves), %zu bytes in use\",\n                listLength(server.clients)-listLength(server.slaves),\n                listLength(server.slaves),\n                zmalloc_used_memory());\n        }\n    }\n\n    /* We need to do a few operations on clients asynchronously. */\n    clientsCron();\n\n    /* Handle background operations on Redis databases. */\n    databasesCron();\n\n    /* Start a scheduled AOF rewrite if this was requested by the user while\n     * a BGSAVE was in progress. */\n    if (server.rdb_child_pid == -1 && server.aof_child_pid == -1 &&\n        server.aof_rewrite_scheduled)\n    {\n        rewriteAppendOnlyFileBackground();\n    }\n\n    /* Check if a background saving or AOF rewrite in progress terminated. */\n    if (server.rdb_child_pid != -1 || server.aof_child_pid != -1 ||\n        ldbPendingChildren())\n    {\n        int statloc;\n        pid_t pid;\n\n        if ((pid = wait3(&statloc,WNOHANG,NULL)) != 0) {\n            int exitcode = WEXITSTATUS(statloc);\n            int bysignal = 0;\n\n            if (WIFSIGNALED(statloc)) bysignal = WTERMSIG(statloc);\n\n            if (pid == -1) {\n                serverLog(LL_WARNING,\"wait3() returned an error: %s. \"\n                    \"rdb_child_pid = %d, aof_child_pid = %d\",\n                    strerror(errno),\n                    (int) server.rdb_child_pid,\n                    (int) server.aof_child_pid);\n            } else if (pid == server.rdb_child_pid) {\n                backgroundSaveDoneHandler(exitcode,bysignal);\n            } else if (pid == server.aof_child_pid) {\n                backgroundRewriteDoneHandler(exitcode,bysignal);\n            } else {\n                if (!ldbRemoveChild(pid)) {\n                    serverLog(LL_WARNING,\n                        \"Warning, detected child with unmatched pid: %ld\",\n                        (long)pid);\n                }\n            }\n            updateDictResizePolicy();\n        }\n    } else {\n        /* If there is not a background saving/rewrite in progress check if\n         * we have to save/rewrite now */\n         for (j = 0; j < server.saveparamslen; j++) {\n            struct saveparam *sp = server.saveparams+j;\n\n            /* Save if we reached the given amount of changes,\n             * the given amount of seconds, and if the latest bgsave was\n             * successful or if, in case of an error, at least\n             * CONFIG_BGSAVE_RETRY_DELAY seconds already elapsed. */\n            if (server.dirty >= sp->changes &&\n                server.unixtime-server.lastsave > sp->seconds &&\n                (server.unixtime-server.lastbgsave_try >\n                 CONFIG_BGSAVE_RETRY_DELAY ||\n                 server.lastbgsave_status == C_OK))\n            {\n                serverLog(LL_NOTICE,\"%d changes in %d seconds. Saving...\",\n                    sp->changes, (int)sp->seconds);\n                rdbSaveBackground(server.rdb_filename);\n                break;\n            }\n         }\n\n         /* Trigger an AOF rewrite if needed */\n         if (server.rdb_child_pid == -1 &&\n             server.aof_child_pid == -1 &&\n             server.aof_rewrite_perc &&\n             server.aof_current_size > server.aof_rewrite_min_size)\n         {\n            long long base = server.aof_rewrite_base_size ?\n                            server.aof_rewrite_base_size : 1;\n            long long growth = (server.aof_current_size*100/base) - 100;\n            if (growth >= server.aof_rewrite_perc) {\n                serverLog(LL_NOTICE,\"Starting automatic rewriting of AOF on %lld%% growth\",growth);\n                rewriteAppendOnlyFileBackground();\n            }\n         }\n    }\n\n\n    /* AOF postponed flush: Try at every cron cycle if the slow fsync\n     * completed. */\n    if (server.aof_flush_postponed_start) flushAppendOnlyFile(0);\n\n    /* AOF write errors: in this case we have a buffer to flush as well and\n     * clear the AOF error in case of success to make the DB writable again,\n     * however to try every second is enough in case of 'hz' is set to\n     * an higher frequency. */\n    run_with_period(1000) {\n        if (server.aof_last_write_status == C_ERR)\n            flushAppendOnlyFile(0);\n    }\n\n    /* Close clients that need to be closed asynchronous */\n    freeClientsInAsyncFreeQueue();\n\n    /* Clear the paused clients flag if needed. */\n    clientsArePaused(); /* Don't check return value, just use the side effect. */\n\n    /* Replication cron function -- used to reconnect to master,\n     * detect transfer failures, start background RDB transfers and so forth. */\n    run_with_period(1000) replicationCron();\n\n    /* Run the Redis Cluster cron. */\n    run_with_period(100) {\n        if (server.cluster_enabled) clusterCron();\n    }\n\n    /* Run the Sentinel timer if we are in sentinel mode. */\n    run_with_period(100) {\n        if (server.sentinel_mode) sentinelTimer();\n    }\n\n    run_with_period(1000) {\n        slotsmgrt_cleanup();\n    }\n\n    /* Cleanup expired MIGRATE cached sockets. */\n    run_with_period(1000) {\n        migrateCloseTimedoutSockets();\n    }\n\n    /* Start a scheduled BGSAVE if the corresponding flag is set. This is\n     * useful when we are forced to postpone a BGSAVE because an AOF\n     * rewrite is in progress.\n     *\n     * Note: this code must be after the replicationCron() call above so\n     * make sure when refactoring this file to keep this order. This is useful\n     * because we want to give priority to RDB savings for replication. */\n    if (server.rdb_child_pid == -1 && server.aof_child_pid == -1 &&\n        server.rdb_bgsave_scheduled &&\n        (server.unixtime-server.lastbgsave_try > CONFIG_BGSAVE_RETRY_DELAY ||\n         server.lastbgsave_status == C_OK))\n    {\n        if (rdbSaveBackground(server.rdb_filename) == C_OK)\n            server.rdb_bgsave_scheduled = 0;\n    }\n\n    server.cronloops++;\n    return 1000/server.hz;\n}\n\n/* This function gets called every time Redis is entering the\n * main loop of the event driven library, that is, before to sleep\n * for ready file descriptors. */\nvoid beforeSleep(struct aeEventLoop *eventLoop) {\n    UNUSED(eventLoop);\n\n    /* Call the Redis Cluster before sleep function. Note that this function\n     * may change the state of Redis Cluster (from ok to fail or vice versa),\n     * so it's a good idea to call it before serving the unblocked clients\n     * later in this function. */\n    if (server.cluster_enabled) clusterBeforeSleep();\n\n    /* Run a fast expire cycle (the called function will return\n     * ASAP if a fast cycle is not needed). */\n    if (server.active_expire_enabled && server.masterhost == NULL)\n        activeExpireCycle(ACTIVE_EXPIRE_CYCLE_FAST);\n\n    /* Send all the slaves an ACK request if at least one client blocked\n     * during the previous event loop iteration. */\n    if (server.get_ack_from_slaves) {\n        robj *argv[3];\n\n        argv[0] = createStringObject(\"REPLCONF\",8);\n        argv[1] = createStringObject(\"GETACK\",6);\n        argv[2] = createStringObject(\"*\",1); /* Not used argument. */\n        replicationFeedSlaves(server.slaves, server.slaveseldb, argv, 3);\n        decrRefCount(argv[0]);\n        decrRefCount(argv[1]);\n        decrRefCount(argv[2]);\n        server.get_ack_from_slaves = 0;\n    }\n\n    /* Unblock all the clients blocked for synchronous replication\n     * in WAIT. */\n    if (listLength(server.clients_waiting_acks))\n        processClientsWaitingReplicas();\n\n    /* Try to process pending commands for clients that were just unblocked. */\n    if (listLength(server.unblocked_clients))\n        processUnblockedClients();\n\n    /* Write the AOF buffer on disk */\n    flushAppendOnlyFile(0);\n\n    /* Handle writes with pending output buffers. */\n    handleClientsWithPendingWrites();\n}\n\n/* =========================== Server initialization ======================== */\n\nvoid createSharedObjects(void) {\n    int j;\n\n    shared.crlf = createObject(OBJ_STRING,sdsnew(\"\\r\\n\"));\n    shared.ok = createObject(OBJ_STRING,sdsnew(\"+OK\\r\\n\"));\n    shared.err = createObject(OBJ_STRING,sdsnew(\"-ERR\\r\\n\"));\n    shared.emptybulk = createObject(OBJ_STRING,sdsnew(\"$0\\r\\n\\r\\n\"));\n    shared.czero = createObject(OBJ_STRING,sdsnew(\":0\\r\\n\"));\n    shared.cone = createObject(OBJ_STRING,sdsnew(\":1\\r\\n\"));\n    shared.cnegone = createObject(OBJ_STRING,sdsnew(\":-1\\r\\n\"));\n    shared.nullbulk = createObject(OBJ_STRING,sdsnew(\"$-1\\r\\n\"));\n    shared.nullmultibulk = createObject(OBJ_STRING,sdsnew(\"*-1\\r\\n\"));\n    shared.emptymultibulk = createObject(OBJ_STRING,sdsnew(\"*0\\r\\n\"));\n    shared.pong = createObject(OBJ_STRING,sdsnew(\"+PONG\\r\\n\"));\n    shared.queued = createObject(OBJ_STRING,sdsnew(\"+QUEUED\\r\\n\"));\n    shared.emptyscan = createObject(OBJ_STRING,sdsnew(\"*2\\r\\n$1\\r\\n0\\r\\n*0\\r\\n\"));\n    shared.wrongtypeerr = createObject(OBJ_STRING,sdsnew(\n        \"-WRONGTYPE Operation against a key holding the wrong kind of value\\r\\n\"));\n    shared.nokeyerr = createObject(OBJ_STRING,sdsnew(\n        \"-ERR no such key\\r\\n\"));\n    shared.syntaxerr = createObject(OBJ_STRING,sdsnew(\n        \"-ERR syntax error\\r\\n\"));\n    shared.sameobjecterr = createObject(OBJ_STRING,sdsnew(\n        \"-ERR source and destination objects are the same\\r\\n\"));\n    shared.outofrangeerr = createObject(OBJ_STRING,sdsnew(\n        \"-ERR index out of range\\r\\n\"));\n    shared.noscripterr = createObject(OBJ_STRING,sdsnew(\n        \"-NOSCRIPT No matching script. Please use EVAL.\\r\\n\"));\n    shared.loadingerr = createObject(OBJ_STRING,sdsnew(\n        \"-LOADING Redis is loading the dataset in memory\\r\\n\"));\n    shared.slowscripterr = createObject(OBJ_STRING,sdsnew(\n        \"-BUSY Redis is busy running a script. You can only call SCRIPT KILL or SHUTDOWN NOSAVE.\\r\\n\"));\n    shared.masterdownerr = createObject(OBJ_STRING,sdsnew(\n        \"-MASTERDOWN Link with MASTER is down and slave-serve-stale-data is set to 'no'.\\r\\n\"));\n    shared.bgsaveerr = createObject(OBJ_STRING,sdsnew(\n        \"-MISCONF Redis is configured to save RDB snapshots, but is currently not able to persist on disk. Commands that may modify the data set are disabled. Please check Redis logs for details about the error.\\r\\n\"));\n    shared.roslaveerr = createObject(OBJ_STRING,sdsnew(\n        \"-READONLY You can't write against a read only slave.\\r\\n\"));\n    shared.noautherr = createObject(OBJ_STRING,sdsnew(\n        \"-NOAUTH Authentication required.\\r\\n\"));\n    shared.oomerr = createObject(OBJ_STRING,sdsnew(\n        \"-OOM command not allowed when used memory > 'maxmemory'.\\r\\n\"));\n    shared.execaborterr = createObject(OBJ_STRING,sdsnew(\n        \"-EXECABORT Transaction discarded because of previous errors.\\r\\n\"));\n    shared.noreplicaserr = createObject(OBJ_STRING,sdsnew(\n        \"-NOREPLICAS Not enough good slaves to write.\\r\\n\"));\n    shared.busykeyerr = createObject(OBJ_STRING,sdsnew(\n        \"-BUSYKEY Target key name already exists.\\r\\n\"));\n    shared.space = createObject(OBJ_STRING,sdsnew(\" \"));\n    shared.colon = createObject(OBJ_STRING,sdsnew(\":\"));\n    shared.plus = createObject(OBJ_STRING,sdsnew(\"+\"));\n\n    for (j = 0; j < PROTO_SHARED_SELECT_CMDS; j++) {\n        char dictid_str[64];\n        int dictid_len;\n\n        dictid_len = ll2string(dictid_str,sizeof(dictid_str),j);\n        shared.select[j] = createObject(OBJ_STRING,\n            sdscatprintf(sdsempty(),\n                \"*2\\r\\n$6\\r\\nSELECT\\r\\n$%d\\r\\n%s\\r\\n\",\n                dictid_len, dictid_str));\n    }\n    shared.messagebulk = createStringObject(\"$7\\r\\nmessage\\r\\n\",13);\n    shared.pmessagebulk = createStringObject(\"$8\\r\\npmessage\\r\\n\",14);\n    shared.subscribebulk = createStringObject(\"$9\\r\\nsubscribe\\r\\n\",15);\n    shared.unsubscribebulk = createStringObject(\"$11\\r\\nunsubscribe\\r\\n\",18);\n    shared.psubscribebulk = createStringObject(\"$10\\r\\npsubscribe\\r\\n\",17);\n    shared.punsubscribebulk = createStringObject(\"$12\\r\\npunsubscribe\\r\\n\",19);\n    shared.del = createStringObject(\"DEL\",3);\n    shared.rpop = createStringObject(\"RPOP\",4);\n    shared.lpop = createStringObject(\"LPOP\",4);\n    shared.lpush = createStringObject(\"LPUSH\",5);\n    for (j = 0; j < OBJ_SHARED_INTEGERS; j++) {\n        shared.integers[j] = createObject(OBJ_STRING,(void*)(long)j);\n        shared.integers[j]->encoding = OBJ_ENCODING_INT;\n    }\n    for (j = 0; j < OBJ_SHARED_BULKHDR_LEN; j++) {\n        shared.mbulkhdr[j] = createObject(OBJ_STRING,\n            sdscatprintf(sdsempty(),\"*%d\\r\\n\",j));\n        shared.bulkhdr[j] = createObject(OBJ_STRING,\n            sdscatprintf(sdsempty(),\"$%d\\r\\n\",j));\n    }\n    /* The following two shared objects, minstring and maxstrings, are not\n     * actually used for their value but as a special object meaning\n     * respectively the minimum possible string and the maximum possible\n     * string in string comparisons for the ZRANGEBYLEX command. */\n    shared.minstring = createStringObject(\"minstring\",9);\n    shared.maxstring = createStringObject(\"maxstring\",9);\n}\n\nvoid initServerConfig(void) {\n    int j;\n\n    getRandomHexChars(server.runid,CONFIG_RUN_ID_SIZE);\n    server.configfile = NULL;\n    server.executable = NULL;\n    server.hz = CONFIG_DEFAULT_HZ;\n    server.runid[CONFIG_RUN_ID_SIZE] = '\\0';\n    server.arch_bits = (sizeof(long) == 8) ? 64 : 32;\n    server.port = CONFIG_DEFAULT_SERVER_PORT;\n    server.tcp_backlog = CONFIG_DEFAULT_TCP_BACKLOG;\n    server.bindaddr_count = 0;\n    server.unixsocket = NULL;\n    server.unixsocketperm = CONFIG_DEFAULT_UNIX_SOCKET_PERM;\n    server.ipfd_count = 0;\n    server.sofd = -1;\n    server.protected_mode = CONFIG_DEFAULT_PROTECTED_MODE;\n    server.dbnum = CONFIG_DEFAULT_DBNUM;\n    server.verbosity = CONFIG_DEFAULT_VERBOSITY;\n    server.maxidletime = CONFIG_DEFAULT_CLIENT_TIMEOUT;\n    server.tcpkeepalive = CONFIG_DEFAULT_TCP_KEEPALIVE;\n    server.active_expire_enabled = 1;\n    server.client_max_querybuf_len = PROTO_MAX_QUERYBUF_LEN;\n    server.saveparams = NULL;\n    server.loading = 0;\n    server.logfile = zstrdup(CONFIG_DEFAULT_LOGFILE);\n    server.syslog_enabled = CONFIG_DEFAULT_SYSLOG_ENABLED;\n    server.syslog_ident = zstrdup(CONFIG_DEFAULT_SYSLOG_IDENT);\n    server.syslog_facility = LOG_LOCAL0;\n    server.daemonize = CONFIG_DEFAULT_DAEMONIZE;\n    server.supervised = 0;\n    server.supervised_mode = SUPERVISED_NONE;\n    server.aof_state = AOF_OFF;\n    server.aof_fsync = CONFIG_DEFAULT_AOF_FSYNC;\n    server.aof_no_fsync_on_rewrite = CONFIG_DEFAULT_AOF_NO_FSYNC_ON_REWRITE;\n    server.aof_rewrite_perc = AOF_REWRITE_PERC;\n    server.aof_rewrite_min_size = AOF_REWRITE_MIN_SIZE;\n    server.aof_rewrite_base_size = 0;\n    server.aof_rewrite_scheduled = 0;\n    server.aof_last_fsync = time(NULL);\n    server.aof_rewrite_time_last = -1;\n    server.aof_rewrite_time_start = -1;\n    server.aof_lastbgrewrite_status = C_OK;\n    server.aof_delayed_fsync = 0;\n    server.aof_fd = -1;\n    server.aof_selected_db = -1; /* Make sure the first time will not match */\n    server.aof_flush_postponed_start = 0;\n    server.aof_rewrite_incremental_fsync = CONFIG_DEFAULT_AOF_REWRITE_INCREMENTAL_FSYNC;\n    server.aof_load_truncated = CONFIG_DEFAULT_AOF_LOAD_TRUNCATED;\n    server.pidfile = NULL;\n    server.rdb_filename = zstrdup(CONFIG_DEFAULT_RDB_FILENAME);\n    server.aof_filename = zstrdup(CONFIG_DEFAULT_AOF_FILENAME);\n    server.requirepass = NULL;\n    server.rdb_compression = CONFIG_DEFAULT_RDB_COMPRESSION;\n    server.rdb_checksum = CONFIG_DEFAULT_RDB_CHECKSUM;\n    server.stop_writes_on_bgsave_err = CONFIG_DEFAULT_STOP_WRITES_ON_BGSAVE_ERROR;\n    server.activerehashing = CONFIG_DEFAULT_ACTIVE_REHASHING;\n    server.notify_keyspace_events = 0;\n    server.maxclients = CONFIG_DEFAULT_MAX_CLIENTS;\n    server.bpop_blocked_clients = 0;\n    server.maxmemory = CONFIG_DEFAULT_MAXMEMORY;\n    server.maxmemory_policy = CONFIG_DEFAULT_MAXMEMORY_POLICY;\n    server.maxmemory_samples = CONFIG_DEFAULT_MAXMEMORY_SAMPLES;\n    server.hash_max_ziplist_entries = OBJ_HASH_MAX_ZIPLIST_ENTRIES;\n    server.hash_max_ziplist_value = OBJ_HASH_MAX_ZIPLIST_VALUE;\n    server.list_max_ziplist_size = OBJ_LIST_MAX_ZIPLIST_SIZE;\n    server.list_compress_depth = OBJ_LIST_COMPRESS_DEPTH;\n    server.set_max_intset_entries = OBJ_SET_MAX_INTSET_ENTRIES;\n    server.zset_max_ziplist_entries = OBJ_ZSET_MAX_ZIPLIST_ENTRIES;\n    server.zset_max_ziplist_value = OBJ_ZSET_MAX_ZIPLIST_VALUE;\n    server.hll_sparse_max_bytes = CONFIG_DEFAULT_HLL_SPARSE_MAX_BYTES;\n    server.shutdown_asap = 0;\n    server.repl_ping_slave_period = CONFIG_DEFAULT_REPL_PING_SLAVE_PERIOD;\n    server.repl_timeout = CONFIG_DEFAULT_REPL_TIMEOUT;\n    server.repl_min_slaves_to_write = CONFIG_DEFAULT_MIN_SLAVES_TO_WRITE;\n    server.repl_min_slaves_max_lag = CONFIG_DEFAULT_MIN_SLAVES_MAX_LAG;\n    server.cluster_enabled = 0;\n    server.cluster_node_timeout = CLUSTER_DEFAULT_NODE_TIMEOUT;\n    server.cluster_migration_barrier = CLUSTER_DEFAULT_MIGRATION_BARRIER;\n    server.cluster_slave_validity_factor = CLUSTER_DEFAULT_SLAVE_VALIDITY;\n    server.cluster_require_full_coverage = CLUSTER_DEFAULT_REQUIRE_FULL_COVERAGE;\n    server.cluster_configfile = zstrdup(CONFIG_DEFAULT_CLUSTER_CONFIG_FILE);\n    server.migrate_cached_sockets = dictCreate(&migrateCacheDictType,NULL);\n    server.next_client_id = 1; /* Client IDs, start from 1 .*/\n    server.loading_process_events_interval_bytes = (1024*1024*2);\n\n    server.slotsmgrt_cached_sockfds = dictCreate(&migrateCacheDictType, NULL);\n\n    server.lruclock = getLRUClock();\n    resetServerSaveParams();\n\n    appendServerSaveParams(60*60,1);  /* save after 1 hour and 1 change */\n    appendServerSaveParams(300,100);  /* save after 5 minutes and 100 changes */\n    appendServerSaveParams(60,10000); /* save after 1 minute and 10000 changes */\n    /* Replication related */\n    server.masterauth = NULL;\n    server.masterhost = NULL;\n    server.masterport = 6379;\n    server.master = NULL;\n    server.cached_master = NULL;\n    server.repl_master_initial_offset = -1;\n    server.repl_state = REPL_STATE_NONE;\n    server.repl_syncio_timeout = CONFIG_REPL_SYNCIO_TIMEOUT;\n    server.repl_serve_stale_data = CONFIG_DEFAULT_SLAVE_SERVE_STALE_DATA;\n    server.repl_slave_ro = CONFIG_DEFAULT_SLAVE_READ_ONLY;\n    server.repl_down_since = 0; /* Never connected, repl is down since EVER. */\n    server.repl_disable_tcp_nodelay = CONFIG_DEFAULT_REPL_DISABLE_TCP_NODELAY;\n    server.repl_diskless_sync = CONFIG_DEFAULT_REPL_DISKLESS_SYNC;\n    server.repl_diskless_sync_delay = CONFIG_DEFAULT_REPL_DISKLESS_SYNC_DELAY;\n    server.slave_priority = CONFIG_DEFAULT_SLAVE_PRIORITY;\n    server.slave_announce_ip = CONFIG_DEFAULT_SLAVE_ANNOUNCE_IP;\n    server.slave_announce_port = CONFIG_DEFAULT_SLAVE_ANNOUNCE_PORT;\n    server.master_repl_offset = 0;\n\n    /* Replication partial resync backlog */\n    server.repl_backlog = NULL;\n    server.repl_backlog_size = CONFIG_DEFAULT_REPL_BACKLOG_SIZE;\n    server.repl_backlog_histlen = 0;\n    server.repl_backlog_idx = 0;\n    server.repl_backlog_off = 0;\n    server.repl_backlog_time_limit = CONFIG_DEFAULT_REPL_BACKLOG_TIME_LIMIT;\n    server.repl_no_slaves_since = time(NULL);\n\n    /* Client output buffer limits */\n    for (j = 0; j < CLIENT_TYPE_OBUF_COUNT; j++)\n        server.client_obuf_limits[j] = clientBufferLimitsDefaults[j];\n\n    /* Double constants initialization */\n    R_Zero = 0.0;\n    R_PosInf = 1.0/R_Zero;\n    R_NegInf = -1.0/R_Zero;\n    R_Nan = R_Zero/R_Zero;\n\n    /* Command table -- we initiialize it here as it is part of the\n     * initial configuration, since command names may be changed via\n     * redis.conf using the rename-command directive. */\n    server.commands = dictCreate(&commandTableDictType,NULL);\n    server.orig_commands = dictCreate(&commandTableDictType,NULL);\n    populateCommandTable();\n    server.delCommand = lookupCommandByCString(\"del\");\n    server.multiCommand = lookupCommandByCString(\"multi\");\n    server.lpushCommand = lookupCommandByCString(\"lpush\");\n    server.lpopCommand = lookupCommandByCString(\"lpop\");\n    server.rpopCommand = lookupCommandByCString(\"rpop\");\n    server.sremCommand = lookupCommandByCString(\"srem\");\n    server.execCommand = lookupCommandByCString(\"exec\");\n\n    /* Slow log */\n    server.slowlog_log_slower_than = CONFIG_DEFAULT_SLOWLOG_LOG_SLOWER_THAN;\n    server.slowlog_max_len = CONFIG_DEFAULT_SLOWLOG_MAX_LEN;\n\n    /* Latency monitor */\n    server.latency_monitor_threshold = CONFIG_DEFAULT_LATENCY_MONITOR_THRESHOLD;\n\n    /* Debugging */\n    server.assert_failed = \"<no assertion failed>\";\n    server.assert_file = \"<no file>\";\n    server.assert_line = 0;\n    server.bug_report_start = 0;\n    server.watchdog_period = 0;\n}\n\nextern char **environ;\n\n/* Restart the server, executing the same executable that started this\n * instance, with the same arguments and configuration file.\n *\n * The function is designed to directly call execve() so that the new\n * server instance will retain the PID of the previous one.\n *\n * The list of flags, that may be bitwise ORed together, alter the\n * behavior of this function:\n *\n * RESTART_SERVER_NONE              No flags.\n * RESTART_SERVER_GRACEFULLY        Do a proper shutdown before restarting.\n * RESTART_SERVER_CONFIG_REWRITE    Rewrite the config file before restarting.\n *\n * On success the function does not return, because the process turns into\n * a different process. On error C_ERR is returned. */\nint restartServer(int flags, mstime_t delay) {\n    int j;\n\n    /* Check if we still have accesses to the executable that started this\n     * server instance. */\n    if (access(server.executable,X_OK) == -1) return C_ERR;\n\n    /* Config rewriting. */\n    if (flags & RESTART_SERVER_CONFIG_REWRITE &&\n        server.configfile &&\n        rewriteConfig(server.configfile) == -1) return C_ERR;\n\n    /* Perform a proper shutdown. */\n    if (flags & RESTART_SERVER_GRACEFULLY &&\n        prepareForShutdown(SHUTDOWN_NOFLAGS) != C_OK) return C_ERR;\n\n    /* Close all file descriptors, with the exception of stdin, stdout, strerr\n     * which are useful if we restart a Redis server which is not daemonized. */\n    for (j = 3; j < (int)server.maxclients + 1024; j++) close(j);\n\n    /* Execute the server with the original command line. */\n    if (delay) usleep(delay*1000);\n    execve(server.executable,server.exec_argv,environ);\n\n    /* If an error occurred here, there is nothing we can do, but exit. */\n    _exit(1);\n\n    return C_ERR; /* Never reached. */\n}\n\n/* This function will try to raise the max number of open files accordingly to\n * the configured max number of clients. It also reserves a number of file\n * descriptors (CONFIG_MIN_RESERVED_FDS) for extra operations of\n * persistence, listening sockets, log files and so forth.\n *\n * If it will not be possible to set the limit accordingly to the configured\n * max number of clients, the function will do the reverse setting\n * server.maxclients to the value that we can actually handle. */\nvoid adjustOpenFilesLimit(void) {\n    rlim_t maxfiles = server.maxclients+CONFIG_MIN_RESERVED_FDS;\n    struct rlimit limit;\n\n    if (getrlimit(RLIMIT_NOFILE,&limit) == -1) {\n        serverLog(LL_WARNING,\"Unable to obtain the current NOFILE limit (%s), assuming 1024 and setting the max clients configuration accordingly.\",\n            strerror(errno));\n        server.maxclients = 1024-CONFIG_MIN_RESERVED_FDS;\n    } else {\n        rlim_t oldlimit = limit.rlim_cur;\n\n        /* Set the max number of files if the current limit is not enough\n         * for our needs. */\n        if (oldlimit < maxfiles) {\n            rlim_t bestlimit;\n            int setrlimit_error = 0;\n\n            /* Try to set the file limit to match 'maxfiles' or at least\n             * to the higher value supported less than maxfiles. */\n            bestlimit = maxfiles;\n            while(bestlimit > oldlimit) {\n                rlim_t decr_step = 16;\n\n                limit.rlim_cur = bestlimit;\n                limit.rlim_max = bestlimit;\n                if (setrlimit(RLIMIT_NOFILE,&limit) != -1) break;\n                setrlimit_error = errno;\n\n                /* We failed to set file limit to 'bestlimit'. Try with a\n                 * smaller limit decrementing by a few FDs per iteration. */\n                if (bestlimit < decr_step) break;\n                bestlimit -= decr_step;\n            }\n\n            /* Assume that the limit we get initially is still valid if\n             * our last try was even lower. */\n            if (bestlimit < oldlimit) bestlimit = oldlimit;\n\n            if (bestlimit < maxfiles) {\n                int old_maxclients = server.maxclients;\n                server.maxclients = bestlimit-CONFIG_MIN_RESERVED_FDS;\n                if (server.maxclients < 1) {\n                    serverLog(LL_WARNING,\"Your current 'ulimit -n' \"\n                        \"of %llu is not enough for the server to start. \"\n                        \"Please increase your open file limit to at least \"\n                        \"%llu. Exiting.\",\n                        (unsigned long long) oldlimit,\n                        (unsigned long long) maxfiles);\n                    exit(1);\n                }\n                serverLog(LL_WARNING,\"You requested maxclients of %d \"\n                    \"requiring at least %llu max file descriptors.\",\n                    old_maxclients,\n                    (unsigned long long) maxfiles);\n                serverLog(LL_WARNING,\"Server can't set maximum open files \"\n                    \"to %llu because of OS error: %s.\",\n                    (unsigned long long) maxfiles, strerror(setrlimit_error));\n                serverLog(LL_WARNING,\"Current maximum open files is %llu. \"\n                    \"maxclients has been reduced to %d to compensate for \"\n                    \"low ulimit. \"\n                    \"If you need higher maxclients increase 'ulimit -n'.\",\n                    (unsigned long long) bestlimit, server.maxclients);\n            } else {\n                serverLog(LL_NOTICE,\"Increased maximum number of open files \"\n                    \"to %llu (it was originally set to %llu).\",\n                    (unsigned long long) maxfiles,\n                    (unsigned long long) oldlimit);\n            }\n        }\n    }\n}\n\n/* Check that server.tcp_backlog can be actually enforced in Linux according\n * to the value of /proc/sys/net/core/somaxconn, or warn about it. */\nvoid checkTcpBacklogSettings(void) {\n#ifdef HAVE_PROC_SOMAXCONN\n    FILE *fp = fopen(\"/proc/sys/net/core/somaxconn\",\"r\");\n    char buf[1024];\n    if (!fp) return;\n    if (fgets(buf,sizeof(buf),fp) != NULL) {\n        int somaxconn = atoi(buf);\n        if (somaxconn > 0 && somaxconn < server.tcp_backlog) {\n            serverLog(LL_WARNING,\"WARNING: The TCP backlog setting of %d cannot be enforced because /proc/sys/net/core/somaxconn is set to the lower value of %d.\", server.tcp_backlog, somaxconn);\n        }\n    }\n    fclose(fp);\n#endif\n}\n\n/* Initialize a set of file descriptors to listen to the specified 'port'\n * binding the addresses specified in the Redis server configuration.\n *\n * The listening file descriptors are stored in the integer array 'fds'\n * and their number is set in '*count'.\n *\n * The addresses to bind are specified in the global server.bindaddr array\n * and their number is server.bindaddr_count. If the server configuration\n * contains no specific addresses to bind, this function will try to\n * bind * (all addresses) for both the IPv4 and IPv6 protocols.\n *\n * On success the function returns C_OK.\n *\n * On error the function returns C_ERR. For the function to be on\n * error, at least one of the server.bindaddr addresses was\n * impossible to bind, or no bind addresses were specified in the server\n * configuration but the function is not able to bind * for at least\n * one of the IPv4 or IPv6 protocols. */\nint listenToPort(int port, int *fds, int *count) {\n    int j;\n\n    /* Force binding of 0.0.0.0 if no bind address is specified, always\n     * entering the loop if j == 0. */\n    if (server.bindaddr_count == 0) server.bindaddr[0] = NULL;\n    for (j = 0; j < server.bindaddr_count || j == 0; j++) {\n        if (server.bindaddr[j] == NULL) {\n            int unsupported = 0;\n            /* Bind * for both IPv6 and IPv4, we enter here only if\n             * server.bindaddr_count == 0. */\n            fds[*count] = anetTcp6Server(server.neterr,port,NULL,\n                server.tcp_backlog);\n            if (fds[*count] != ANET_ERR) {\n                anetNonBlock(NULL,fds[*count]);\n                (*count)++;\n            } else if (errno == EAFNOSUPPORT) {\n                unsupported++;\n                serverLog(LL_WARNING,\"Not listening to IPv6: unsupproted\");\n            }\n\n            if (*count == 1 || unsupported) {\n                /* Bind the IPv4 address as well. */\n                fds[*count] = anetTcpServer(server.neterr,port,NULL,\n                    server.tcp_backlog);\n                if (fds[*count] != ANET_ERR) {\n                    anetNonBlock(NULL,fds[*count]);\n                    (*count)++;\n                } else if (errno == EAFNOSUPPORT) {\n                    unsupported++;\n                    serverLog(LL_WARNING,\"Not listening to IPv4: unsupproted\");\n                }\n            }\n            /* Exit the loop if we were able to bind * on IPv4 and IPv6,\n             * otherwise fds[*count] will be ANET_ERR and we'll print an\n             * error and return to the caller with an error. */\n            if (*count + unsupported == 2) break;\n        } else if (strchr(server.bindaddr[j],':')) {\n            /* Bind IPv6 address. */\n            fds[*count] = anetTcp6Server(server.neterr,port,server.bindaddr[j],\n                server.tcp_backlog);\n        } else {\n            /* Bind IPv4 address. */\n            fds[*count] = anetTcpServer(server.neterr,port,server.bindaddr[j],\n                server.tcp_backlog);\n        }\n        if (fds[*count] == ANET_ERR) {\n            serverLog(LL_WARNING,\n                \"Creating Server TCP listening socket %s:%d: %s\",\n                server.bindaddr[j] ? server.bindaddr[j] : \"*\",\n                port, server.neterr);\n            return C_ERR;\n        }\n        anetNonBlock(NULL,fds[*count]);\n        (*count)++;\n    }\n    return C_OK;\n}\n\n/* Resets the stats that we expose via INFO or other means that we want\n * to reset via CONFIG RESETSTAT. The function is also used in order to\n * initialize these fields in initServer() at server startup. */\nvoid resetServerStats(void) {\n    int j;\n\n    server.stat_numcommands = 0;\n    server.stat_numconnections = 0;\n    server.stat_expiredkeys = 0;\n    server.stat_evictedkeys = 0;\n    server.stat_keyspace_misses = 0;\n    server.stat_keyspace_hits = 0;\n    server.stat_fork_time = 0;\n    server.stat_fork_rate = 0;\n    server.stat_rejected_conn = 0;\n    server.stat_sync_full = 0;\n    server.stat_sync_partial_ok = 0;\n    server.stat_sync_partial_err = 0;\n    for (j = 0; j < STATS_METRIC_COUNT; j++) {\n        server.inst_metric[j].idx = 0;\n        server.inst_metric[j].last_sample_time = mstime();\n        server.inst_metric[j].last_sample_count = 0;\n        memset(server.inst_metric[j].samples,0,\n            sizeof(server.inst_metric[j].samples));\n    }\n    server.stat_net_input_bytes = 0;\n    server.stat_net_output_bytes = 0;\n    server.aof_delayed_fsync = 0;\n}\n\nvoid initServer(void) {\n    int i, j;\n\n    signal(SIGHUP, SIG_IGN);\n    signal(SIGPIPE, SIG_IGN);\n    setupSignalHandlers();\n\n    crc32_init();\n\n    if (server.syslog_enabled) {\n        openlog(server.syslog_ident, LOG_PID | LOG_NDELAY | LOG_NOWAIT,\n            server.syslog_facility);\n    }\n\n    server.pid = getpid();\n    server.current_client = NULL;\n    server.clients = listCreate();\n    server.clients_to_close = listCreate();\n    server.slaves = listCreate();\n    server.monitors = listCreate();\n    server.clients_pending_write = listCreate();\n    server.slaveseldb = -1; /* Force to emit the first SELECT command. */\n    server.unblocked_clients = listCreate();\n    server.ready_keys = listCreate();\n    server.clients_waiting_acks = listCreate();\n    server.get_ack_from_slaves = 0;\n    server.clients_paused = 0;\n    server.system_memory_size = zmalloc_get_memory_size();\n\n    createSharedObjects();\n    adjustOpenFilesLimit();\n    server.el = aeCreateEventLoop(server.maxclients+CONFIG_FDSET_INCR);\n    server.db = zmalloc(sizeof(redisDb)*server.dbnum);\n\n    /* Open the TCP listening socket for the user commands. */\n    if (server.port != 0 &&\n        listenToPort(server.port,server.ipfd,&server.ipfd_count) == C_ERR)\n        exit(1);\n\n    /* Open the listening Unix domain socket. */\n    if (server.unixsocket != NULL) {\n        unlink(server.unixsocket); /* don't care if this fails */\n        server.sofd = anetUnixServer(server.neterr,server.unixsocket,\n            server.unixsocketperm, server.tcp_backlog);\n        if (server.sofd == ANET_ERR) {\n            serverLog(LL_WARNING, \"Opening Unix socket: %s\", server.neterr);\n            exit(1);\n        }\n        anetNonBlock(NULL,server.sofd);\n    }\n\n    /* Abort if there are no listening sockets at all. */\n    if (server.ipfd_count == 0 && server.sofd < 0) {\n        serverLog(LL_WARNING, \"Configured to not listen anywhere, exiting.\");\n        exit(1);\n    }\n\n    /* Create the Redis databases, and initialize other internal state. */\n    for (j = 0; j < server.dbnum; j++) {\n        server.db[j].dict = dictCreate(&dbDictType,NULL);\n        server.db[j].expires = dictCreate(&keyptrDictType,NULL);\n        server.db[j].blocking_keys = dictCreate(&keylistDictType,NULL);\n        server.db[j].ready_keys = dictCreate(&setDictType,NULL);\n        server.db[j].watched_keys = dictCreate(&keylistDictType,NULL);\n        server.db[j].eviction_pool = evictionPoolAlloc();\n        server.db[j].id = j;\n        server.db[j].avg_ttl = 0;\n        for (i = 0; i < HASH_SLOTS_SIZE; i ++) {\n            server.db[j].hash_slots[i] = dictCreate(&hashSlotType, NULL);\n        }\n        server.db[j].tagged_keys = zslCreate();\n    }\n    server.pubsub_channels = dictCreate(&keylistDictType,NULL);\n    server.pubsub_patterns = listCreate();\n    listSetFreeMethod(server.pubsub_patterns,freePubsubPattern);\n    listSetMatchMethod(server.pubsub_patterns,listMatchPubsubPattern);\n    server.cronloops = 0;\n    server.rdb_child_pid = -1;\n    server.aof_child_pid = -1;\n    server.rdb_child_type = RDB_CHILD_TYPE_NONE;\n    server.rdb_bgsave_scheduled = 0;\n    aofRewriteBufferReset();\n    server.aof_buf = sdsempty();\n    server.lastsave = time(NULL); /* At startup we consider the DB saved. */\n    server.lastbgsave_try = 0;    /* At startup we never tried to BGSAVE. */\n    server.rdb_save_time_last = -1;\n    server.rdb_save_time_start = -1;\n    server.dirty = 0;\n    resetServerStats();\n    /* A few stats we don't want to reset: server startup time, and peak mem. */\n    server.stat_starttime = time(NULL);\n    server.stat_peak_memory = 0;\n    server.resident_set_size = 0;\n    server.lastbgsave_status = C_OK;\n    server.aof_last_write_status = C_OK;\n    server.aof_last_write_errno = 0;\n    server.repl_good_slaves_count = 0;\n    updateCachedTime();\n\n    /* Create the serverCron() time event, that's our main way to process\n     * background operations. */\n    if(aeCreateTimeEvent(server.el, 1, serverCron, NULL, NULL) == AE_ERR) {\n        serverPanic(\"Can't create the serverCron time event.\");\n        exit(1);\n    }\n\n    /* Create an event handler for accepting new connections in TCP and Unix\n     * domain sockets. */\n    for (j = 0; j < server.ipfd_count; j++) {\n        if (aeCreateFileEvent(server.el, server.ipfd[j], AE_READABLE,\n            acceptTcpHandler,NULL) == AE_ERR)\n            {\n                serverPanic(\n                    \"Unrecoverable error creating server.ipfd file event.\");\n            }\n    }\n    if (server.sofd > 0 && aeCreateFileEvent(server.el,server.sofd,AE_READABLE,\n        acceptUnixHandler,NULL) == AE_ERR) serverPanic(\"Unrecoverable error creating server.sofd file event.\");\n\n    /* Open the AOF file if needed. */\n    if (server.aof_state == AOF_ON) {\n        server.aof_fd = open(server.aof_filename,\n                               O_WRONLY|O_APPEND|O_CREAT,0644);\n        if (server.aof_fd == -1) {\n            serverLog(LL_WARNING, \"Can't open the append-only file: %s\",\n                strerror(errno));\n            exit(1);\n        }\n    }\n\n    /* 32 bit instances are limited to 4GB of address space, so if there is\n     * no explicit limit in the user provided configuration we set a limit\n     * at 3 GB using maxmemory with 'noeviction' policy'. This avoids\n     * useless crashes of the Redis instance for out of memory. */\n    if (server.arch_bits == 32 && server.maxmemory == 0) {\n        serverLog(LL_WARNING,\"Warning: 32 bit instance detected but no memory limit set. Setting 3 GB maxmemory limit with 'noeviction' policy now.\");\n        server.maxmemory = 3072LL*(1024*1024); /* 3 GB */\n        server.maxmemory_policy = MAXMEMORY_NO_EVICTION;\n    }\n\n    if (server.cluster_enabled) clusterInit();\n    replicationScriptCacheInit();\n    scriptingInit(1);\n    slowlogInit();\n    latencyMonitorInit();\n    bioInit();\n}\n\n/* Populates the Redis Command Table starting from the hard coded list\n * we have on top of redis.c file. */\nvoid populateCommandTable(void) {\n    int j;\n    int numcommands = sizeof(redisCommandTable)/sizeof(struct redisCommand);\n\n    for (j = 0; j < numcommands; j++) {\n        struct redisCommand *c = redisCommandTable+j;\n        char *f = c->sflags;\n        int retval1, retval2;\n\n        while(*f != '\\0') {\n            switch(*f) {\n            case 'w': c->flags |= CMD_WRITE; break;\n            case 'r': c->flags |= CMD_READONLY; break;\n            case 'm': c->flags |= CMD_DENYOOM; break;\n            case 'a': c->flags |= CMD_ADMIN; break;\n            case 'p': c->flags |= CMD_PUBSUB; break;\n            case 's': c->flags |= CMD_NOSCRIPT; break;\n            case 'R': c->flags |= CMD_RANDOM; break;\n            case 'S': c->flags |= CMD_SORT_FOR_SCRIPT; break;\n            case 'l': c->flags |= CMD_LOADING; break;\n            case 't': c->flags |= CMD_STALE; break;\n            case 'M': c->flags |= CMD_SKIP_MONITOR; break;\n            case 'k': c->flags |= CMD_ASKING; break;\n            case 'F': c->flags |= CMD_FAST; break;\n            default: serverPanic(\"Unsupported command flag\"); break;\n            }\n            f++;\n        }\n\n        retval1 = dictAdd(server.commands, sdsnew(c->name), c);\n        /* Populate an additional dictionary that will be unaffected\n         * by rename-command statements in redis.conf. */\n        retval2 = dictAdd(server.orig_commands, sdsnew(c->name), c);\n        serverAssert(retval1 == DICT_OK && retval2 == DICT_OK);\n    }\n}\n\nvoid resetCommandTableStats(void) {\n    int numcommands = sizeof(redisCommandTable)/sizeof(struct redisCommand);\n    int j;\n\n    for (j = 0; j < numcommands; j++) {\n        struct redisCommand *c = redisCommandTable+j;\n\n        c->microseconds = 0;\n        c->calls = 0;\n    }\n}\n\n/* ========================== Redis OP Array API ============================ */\n\nvoid redisOpArrayInit(redisOpArray *oa) {\n    oa->ops = NULL;\n    oa->numops = 0;\n}\n\nint redisOpArrayAppend(redisOpArray *oa, struct redisCommand *cmd, int dbid,\n                       robj **argv, int argc, int target)\n{\n    redisOp *op;\n\n    oa->ops = zrealloc(oa->ops,sizeof(redisOp)*(oa->numops+1));\n    op = oa->ops+oa->numops;\n    op->cmd = cmd;\n    op->dbid = dbid;\n    op->argv = argv;\n    op->argc = argc;\n    op->target = target;\n    oa->numops++;\n    return oa->numops;\n}\n\nvoid redisOpArrayFree(redisOpArray *oa) {\n    while(oa->numops) {\n        int j;\n        redisOp *op;\n\n        oa->numops--;\n        op = oa->ops+oa->numops;\n        for (j = 0; j < op->argc; j++)\n            decrRefCount(op->argv[j]);\n        zfree(op->argv);\n    }\n    zfree(oa->ops);\n}\n\n/* ====================== Commands lookup and execution ===================== */\n\nstruct redisCommand *lookupCommand(sds name) {\n    return dictFetchValue(server.commands, name);\n}\n\nstruct redisCommand *lookupCommandByCString(char *s) {\n    struct redisCommand *cmd;\n    sds name = sdsnew(s);\n\n    cmd = dictFetchValue(server.commands, name);\n    sdsfree(name);\n    return cmd;\n}\n\n/* Lookup the command in the current table, if not found also check in\n * the original table containing the original command names unaffected by\n * redis.conf rename-command statement.\n *\n * This is used by functions rewriting the argument vector such as\n * rewriteClientCommandVector() in order to set client->cmd pointer\n * correctly even if the command was renamed. */\nstruct redisCommand *lookupCommandOrOriginal(sds name) {\n    struct redisCommand *cmd = dictFetchValue(server.commands, name);\n\n    if (!cmd) cmd = dictFetchValue(server.orig_commands,name);\n    return cmd;\n}\n\n/* Propagate the specified command (in the context of the specified database id)\n * to AOF and Slaves.\n *\n * flags are an xor between:\n * + PROPAGATE_NONE (no propagation of command at all)\n * + PROPAGATE_AOF (propagate into the AOF file if is enabled)\n * + PROPAGATE_REPL (propagate into the replication link)\n *\n * This should not be used inside commands implementation. Use instead\n * alsoPropagate(), preventCommandPropagation(), forceCommandPropagation().\n */\nvoid propagate(struct redisCommand *cmd, int dbid, robj **argv, int argc,\n               int flags)\n{\n    if (server.aof_state != AOF_OFF && flags & PROPAGATE_AOF)\n        feedAppendOnlyFile(cmd,dbid,argv,argc);\n    if (flags & PROPAGATE_REPL)\n        replicationFeedSlaves(server.slaves,dbid,argv,argc);\n}\n\n/* Used inside commands to schedule the propagation of additional commands\n * after the current command is propagated to AOF / Replication.\n *\n * 'cmd' must be a pointer to the Redis command to replicate, dbid is the\n * database ID the command should be propagated into.\n * Arguments of the command to propagte are passed as an array of redis\n * objects pointers of len 'argc', using the 'argv' vector.\n *\n * The function does not take a reference to the passed 'argv' vector,\n * so it is up to the caller to release the passed argv (but it is usually\n * stack allocated).  The function autoamtically increments ref count of\n * passed objects, so the caller does not need to. */\nvoid alsoPropagate(struct redisCommand *cmd, int dbid, robj **argv, int argc,\n                   int target)\n{\n    robj **argvcopy;\n    int j;\n\n    if (server.loading) return; /* No propagation during loading. */\n\n    argvcopy = zmalloc(sizeof(robj*)*argc);\n    for (j = 0; j < argc; j++) {\n        argvcopy[j] = argv[j];\n        incrRefCount(argv[j]);\n    }\n    redisOpArrayAppend(&server.also_propagate,cmd,dbid,argvcopy,argc,target);\n}\n\n/* It is possible to call the function forceCommandPropagation() inside a\n * Redis command implementation in order to to force the propagation of a\n * specific command execution into AOF / Replication. */\nvoid forceCommandPropagation(client *c, int flags) {\n    if (flags & PROPAGATE_REPL) c->flags |= CLIENT_FORCE_REPL;\n    if (flags & PROPAGATE_AOF) c->flags |= CLIENT_FORCE_AOF;\n}\n\n/* Avoid that the executed command is propagated at all. This way we\n * are free to just propagate what we want using the alsoPropagate()\n * API. */\nvoid preventCommandPropagation(client *c) {\n    c->flags |= CLIENT_PREVENT_PROP;\n}\n\n/* AOF specific version of preventCommandPropagation(). */\nvoid preventCommandAOF(client *c) {\n    c->flags |= CLIENT_PREVENT_AOF_PROP;\n}\n\n/* Replication specific version of preventCommandPropagation(). */\nvoid preventCommandReplication(client *c) {\n    c->flags |= CLIENT_PREVENT_REPL_PROP;\n}\n\n/* Call() is the core of Redis execution of a command.\n *\n * The following flags can be passed:\n * CMD_CALL_NONE        No flags.\n * CMD_CALL_SLOWLOG     Check command speed and log in the slow log if needed.\n * CMD_CALL_STATS       Populate command stats.\n * CMD_CALL_PROPAGATE_AOF   Append command to AOF if it modified the dataset\n *                          or if the client flags are forcing propagation.\n * CMD_CALL_PROPAGATE_REPL  Send command to salves if it modified the dataset\n *                          or if the client flags are forcing propagation.\n * CMD_CALL_PROPAGATE   Alias for PROPAGATE_AOF|PROPAGATE_REPL.\n * CMD_CALL_FULL        Alias for SLOWLOG|STATS|PROPAGATE.\n *\n * The exact propagation behavior depends on the client flags.\n * Specifically:\n *\n * 1. If the client flags CLIENT_FORCE_AOF or CLIENT_FORCE_REPL are set\n *    and assuming the corresponding CMD_CALL_PROPAGATE_AOF/REPL is set\n *    in the call flags, then the command is propagated even if the\n *    dataset was not affected by the command.\n * 2. If the client flags CLIENT_PREVENT_REPL_PROP or CLIENT_PREVENT_AOF_PROP\n *    are set, the propagation into AOF or to slaves is not performed even\n *    if the command modified the dataset.\n *\n * Note that regardless of the client flags, if CMD_CALL_PROPAGATE_AOF\n * or CMD_CALL_PROPAGATE_REPL are not set, then respectively AOF or\n * slaves propagation will never occur.\n *\n * Client flags are modified by the implementation of a given command\n * using the following API:\n *\n * forceCommandPropagation(client *c, int flags);\n * preventCommandPropagation(client *c);\n * preventCommandAOF(client *c);\n * preventCommandReplication(client *c);\n *\n */\nvoid call(client *c, int flags) {\n    long long dirty, start, duration;\n    int client_old_flags = c->flags;\n\n    /* Sent the command to clients in MONITOR mode, only if the commands are\n     * not generated from reading an AOF. */\n    if (listLength(server.monitors) &&\n        !server.loading &&\n        !(c->cmd->flags & (CMD_SKIP_MONITOR|CMD_ADMIN)))\n    {\n        replicationFeedMonitors(c,server.monitors,c->db->id,c->argv,c->argc);\n    }\n\n    /* Initialization: clear the flags that must be set by the command on\n     * demand, and initialize the array for additional commands propagation. */\n    c->flags &= ~(CLIENT_FORCE_AOF|CLIENT_FORCE_REPL|CLIENT_PREVENT_PROP);\n    redisOpArrayInit(&server.also_propagate);\n\n    /* Call the command. */\n    dirty = server.dirty;\n    start = ustime();\n    c->cmd->proc(c);\n    duration = ustime()-start;\n    dirty = server.dirty-dirty;\n    if (dirty < 0) dirty = 0;\n\n    /* When EVAL is called loading the AOF we don't want commands called\n     * from Lua to go into the slowlog or to populate statistics. */\n    if (server.loading && c->flags & CLIENT_LUA)\n        flags &= ~(CMD_CALL_SLOWLOG | CMD_CALL_STATS);\n\n    /* If the caller is Lua, we want to force the EVAL caller to propagate\n     * the script if the command flag or client flag are forcing the\n     * propagation. */\n    if (c->flags & CLIENT_LUA && server.lua_caller) {\n        if (c->flags & CLIENT_FORCE_REPL)\n            server.lua_caller->flags |= CLIENT_FORCE_REPL;\n        if (c->flags & CLIENT_FORCE_AOF)\n            server.lua_caller->flags |= CLIENT_FORCE_AOF;\n    }\n\n    /* Log the command into the Slow log if needed, and populate the\n     * per-command statistics that we show in INFO commandstats. */\n    if (flags & CMD_CALL_SLOWLOG && c->cmd->proc != execCommand) {\n        char *latency_event = (c->cmd->flags & CMD_FAST) ?\n                              \"fast-command\" : \"command\";\n        latencyAddSampleIfNeeded(latency_event,duration/1000);\n        slowlogPushEntryIfNeeded(c->argv,c->argc,duration);\n    }\n    if (flags & CMD_CALL_STATS) {\n        c->lastcmd->microseconds += duration;\n        c->lastcmd->calls++;\n    }\n\n    /* Propagate the command into the AOF and replication link */\n    if (flags & CMD_CALL_PROPAGATE &&\n        (c->flags & CLIENT_PREVENT_PROP) != CLIENT_PREVENT_PROP)\n    {\n        int propagate_flags = PROPAGATE_NONE;\n\n        /* Check if the command operated changes in the data set. If so\n         * set for replication / AOF propagation. */\n        if (dirty) propagate_flags |= (PROPAGATE_AOF|PROPAGATE_REPL);\n\n        /* If the client forced AOF / replication of the command, set\n         * the flags regardless of the command effects on the data set. */\n        if (c->flags & CLIENT_FORCE_REPL) propagate_flags |= PROPAGATE_REPL;\n        if (c->flags & CLIENT_FORCE_AOF) propagate_flags |= PROPAGATE_AOF;\n\n        /* However prevent AOF / replication propagation if the command\n         * implementatino called preventCommandPropagation() or similar,\n         * or if we don't have the call() flags to do so. */\n        if (c->flags & CLIENT_PREVENT_REPL_PROP ||\n            !(flags & CMD_CALL_PROPAGATE_REPL))\n                propagate_flags &= ~PROPAGATE_REPL;\n        if (c->flags & CLIENT_PREVENT_AOF_PROP ||\n            !(flags & CMD_CALL_PROPAGATE_AOF))\n                propagate_flags &= ~PROPAGATE_AOF;\n\n        /* Call propagate() only if at least one of AOF / replication\n         * propagation is needed. */\n        if (propagate_flags != PROPAGATE_NONE)\n            propagate(c->cmd,c->db->id,c->argv,c->argc,propagate_flags);\n    }\n\n    /* Restore the old replication flags, since call() can be executed\n     * recursively. */\n    c->flags &= ~(CLIENT_FORCE_AOF|CLIENT_FORCE_REPL|CLIENT_PREVENT_PROP);\n    c->flags |= client_old_flags &\n        (CLIENT_FORCE_AOF|CLIENT_FORCE_REPL|CLIENT_PREVENT_PROP);\n\n    /* Handle the alsoPropagate() API to handle commands that want to propagate\n     * multiple separated commands. Note that alsoPropagate() is not affected\n     * by CLIENT_PREVENT_PROP flag. */\n    if (server.also_propagate.numops) {\n        int j;\n        redisOp *rop;\n\n        if (flags & CMD_CALL_PROPAGATE) {\n            for (j = 0; j < server.also_propagate.numops; j++) {\n                rop = &server.also_propagate.ops[j];\n                int target = rop->target;\n                /* Whatever the command wish is, we honor the call() flags. */\n                if (!(flags&CMD_CALL_PROPAGATE_AOF)) target &= ~PROPAGATE_AOF;\n                if (!(flags&CMD_CALL_PROPAGATE_REPL)) target &= ~PROPAGATE_REPL;\n                if (target)\n                    propagate(rop->cmd,rop->dbid,rop->argv,rop->argc,target);\n            }\n        }\n        redisOpArrayFree(&server.also_propagate);\n    }\n    server.stat_numcommands++;\n}\n\n/* If this function gets called we already read a whole\n * command, arguments are in the client argv/argc fields.\n * processCommand() execute the command or prepare the\n * server for a bulk read from the client.\n *\n * If C_OK is returned the client is still alive and valid and\n * other operations can be performed by the caller. Otherwise\n * if C_ERR is returned the client was destroyed (i.e. after QUIT). */\nint processCommand(client *c) {\n    /* The QUIT command is handled separately. Normal command procs will\n     * go through checking for replication and QUIT will cause trouble\n     * when FORCE_REPLICATION is enabled and would be implemented in\n     * a regular command proc. */\n    if (!strcasecmp(c->argv[0]->ptr,\"quit\")) {\n        addReply(c,shared.ok);\n        c->flags |= CLIENT_CLOSE_AFTER_REPLY;\n        return C_ERR;\n    }\n\n    /* Now lookup the command and check ASAP about trivial error conditions\n     * such as wrong arity, bad command name and so forth. */\n    c->cmd = c->lastcmd = lookupCommand(c->argv[0]->ptr);\n    if (!c->cmd) {\n        flagTransaction(c);\n        addReplyErrorFormat(c,\"unknown command '%s'\",\n            (char*)c->argv[0]->ptr);\n        return C_OK;\n    } else if ((c->cmd->arity > 0 && c->cmd->arity != c->argc) ||\n               (c->argc < -c->cmd->arity)) {\n        flagTransaction(c);\n        addReplyErrorFormat(c,\"wrong number of arguments for '%s' command\",\n            c->cmd->name);\n        return C_OK;\n    }\n\n    /* Check if the user is authenticated */\n    if (server.requirepass && !c->authenticated && c->cmd->proc != authCommand)\n    {\n        flagTransaction(c);\n        addReply(c,shared.noautherr);\n        return C_OK;\n    }\n\n    /* If cluster is enabled perform the cluster redirection here.\n     * However we don't perform the redirection if:\n     * 1) The sender of this command is our master.\n     * 2) The command has no key arguments. */\n    if (server.cluster_enabled &&\n        !(c->flags & CLIENT_MASTER) &&\n        !(c->flags & CLIENT_LUA &&\n          server.lua_caller->flags & CLIENT_MASTER) &&\n        !(c->cmd->getkeys_proc == NULL && c->cmd->firstkey == 0 &&\n          c->cmd->proc != execCommand))\n    {\n        int hashslot;\n        int error_code;\n        clusterNode *n = getNodeByQuery(c,c->cmd,c->argv,c->argc,\n                                        &hashslot,&error_code);\n        if (n == NULL || n != server.cluster->myself) {\n            if (c->cmd->proc == execCommand) {\n                discardTransaction(c);\n            } else {\n                flagTransaction(c);\n            }\n            clusterRedirectClient(c,n,hashslot,error_code);\n            return C_OK;\n        }\n    }\n\n    /* Handle the maxmemory directive.\n     *\n     * First we try to free some memory if possible (if there are volatile\n     * keys in the dataset). If there are not the only thing we can do\n     * is returning an error. */\n    if (server.maxmemory) {\n        int retval = freeMemoryIfNeeded();\n        /* freeMemoryIfNeeded may flush slave output buffers. This may result\n         * into a slave, that may be the active client, to be freed. */\n        if (server.current_client == NULL) return C_ERR;\n\n        /* It was impossible to free enough memory, and the command the client\n         * is trying to execute is denied during OOM conditions? Error. */\n        if ((c->cmd->flags & CMD_DENYOOM) && retval == C_ERR) {\n            flagTransaction(c);\n            addReply(c, shared.oomerr);\n            return C_OK;\n        }\n    }\n\n    /* Don't accept write commands if there are problems persisting on disk\n     * and if this is a master instance. */\n    if (((server.stop_writes_on_bgsave_err &&\n          server.saveparamslen > 0 &&\n          server.lastbgsave_status == C_ERR) ||\n          server.aof_last_write_status == C_ERR) &&\n        server.masterhost == NULL &&\n        (c->cmd->flags & CMD_WRITE ||\n         c->cmd->proc == pingCommand))\n    {\n        flagTransaction(c);\n        if (server.aof_last_write_status == C_OK)\n            addReply(c, shared.bgsaveerr);\n        else\n            addReplySds(c,\n                sdscatprintf(sdsempty(),\n                \"-MISCONF Errors writing to the AOF file: %s\\r\\n\",\n                strerror(server.aof_last_write_errno)));\n        return C_OK;\n    }\n\n    /* Don't accept write commands if there are not enough good slaves and\n     * user configured the min-slaves-to-write option. */\n    if (server.masterhost == NULL &&\n        server.repl_min_slaves_to_write &&\n        server.repl_min_slaves_max_lag &&\n        c->cmd->flags & CMD_WRITE &&\n        server.repl_good_slaves_count < server.repl_min_slaves_to_write)\n    {\n        flagTransaction(c);\n        addReply(c, shared.noreplicaserr);\n        return C_OK;\n    }\n\n    /* Don't accept write commands if this is a read only slave. But\n     * accept write commands if this is our master. */\n    if (server.masterhost && server.repl_slave_ro &&\n        !(c->flags & CLIENT_MASTER) &&\n        c->cmd->flags & CMD_WRITE)\n    {\n        addReply(c, shared.roslaveerr);\n        return C_OK;\n    }\n\n    /* Only allow SUBSCRIBE and UNSUBSCRIBE in the context of Pub/Sub */\n    if (c->flags & CLIENT_PUBSUB &&\n        c->cmd->proc != pingCommand &&\n        c->cmd->proc != subscribeCommand &&\n        c->cmd->proc != unsubscribeCommand &&\n        c->cmd->proc != psubscribeCommand &&\n        c->cmd->proc != punsubscribeCommand) {\n        addReplyError(c,\"only (P)SUBSCRIBE / (P)UNSUBSCRIBE / PING / QUIT allowed in this context\");\n        return C_OK;\n    }\n\n    /* Only allow INFO and SLAVEOF when slave-serve-stale-data is no and\n     * we are a slave with a broken link with master. */\n    if (server.masterhost && server.repl_state != REPL_STATE_CONNECTED &&\n        server.repl_serve_stale_data == 0 &&\n        !(c->cmd->flags & CMD_STALE))\n    {\n        flagTransaction(c);\n        addReply(c, shared.masterdownerr);\n        return C_OK;\n    }\n\n    /* Loading DB? Return an error if the command has not the\n     * CMD_LOADING flag. */\n    if (server.loading && !(c->cmd->flags & CMD_LOADING)) {\n        addReply(c, shared.loadingerr);\n        return C_OK;\n    }\n\n    /* Lua script too slow? Only allow a limited number of commands. */\n    if (server.lua_timedout &&\n          c->cmd->proc != authCommand &&\n          c->cmd->proc != replconfCommand &&\n        !(c->cmd->proc == shutdownCommand &&\n          c->argc == 2 &&\n          tolower(((char*)c->argv[1]->ptr)[0]) == 'n') &&\n        !(c->cmd->proc == scriptCommand &&\n          c->argc == 2 &&\n          tolower(((char*)c->argv[1]->ptr)[0]) == 'k'))\n    {\n        flagTransaction(c);\n        addReply(c, shared.slowscripterr);\n        return C_OK;\n    }\n\n    /* Exec the command */\n    if (c->flags & CLIENT_MULTI &&\n        c->cmd->proc != execCommand && c->cmd->proc != discardCommand &&\n        c->cmd->proc != multiCommand && c->cmd->proc != watchCommand)\n    {\n        queueMultiCommand(c);\n        addReply(c,shared.queued);\n    } else {\n        call(c,CMD_CALL_FULL);\n        c->woff = server.master_repl_offset;\n        if (listLength(server.ready_keys))\n            handleClientsBlockedOnLists();\n    }\n    return C_OK;\n}\n\n/*================================== Shutdown =============================== */\n\n/* Close listening sockets. Also unlink the unix domain socket if\n * unlink_unix_socket is non-zero. */\nvoid closeListeningSockets(int unlink_unix_socket) {\n    int j;\n\n    for (j = 0; j < server.ipfd_count; j++) close(server.ipfd[j]);\n    if (server.sofd != -1) close(server.sofd);\n    if (server.cluster_enabled)\n        for (j = 0; j < server.cfd_count; j++) close(server.cfd[j]);\n    if (unlink_unix_socket && server.unixsocket) {\n        serverLog(LL_NOTICE,\"Removing the unix socket file.\");\n        unlink(server.unixsocket); /* don't care if this fails */\n    }\n}\n\nint prepareForShutdown(int flags) {\n    int save = flags & SHUTDOWN_SAVE;\n    int nosave = flags & SHUTDOWN_NOSAVE;\n\n    serverLog(LL_WARNING,\"User requested shutdown...\");\n\n    /* Kill all the Lua debugger forked sessions. */\n    ldbKillForkedSessions();\n\n    /* Kill the saving child if there is a background saving in progress.\n       We want to avoid race conditions, for instance our saving child may\n       overwrite the synchronous saving did by SHUTDOWN. */\n    if (server.rdb_child_pid != -1) {\n        serverLog(LL_WARNING,\"There is a child saving an .rdb. Killing it!\");\n        kill(server.rdb_child_pid,SIGUSR1);\n        rdbRemoveTempFile(server.rdb_child_pid);\n    }\n\n    if (server.aof_state != AOF_OFF) {\n        /* Kill the AOF saving child as the AOF we already have may be longer\n         * but contains the full dataset anyway. */\n        if (server.aof_child_pid != -1) {\n            /* If we have AOF enabled but haven't written the AOF yet, don't\n             * shutdown or else the dataset will be lost. */\n            if (server.aof_state == AOF_WAIT_REWRITE) {\n                serverLog(LL_WARNING, \"Writing initial AOF, can't exit.\");\n                return C_ERR;\n            }\n            serverLog(LL_WARNING,\n                \"There is a child rewriting the AOF. Killing it!\");\n            kill(server.aof_child_pid,SIGUSR1);\n        }\n        /* Append only file: fsync() the AOF and exit */\n        serverLog(LL_NOTICE,\"Calling fsync() on the AOF file.\");\n        aof_fsync(server.aof_fd);\n    }\n\n    /* Create a new RDB file before exiting. */\n    if ((server.saveparamslen > 0 && !nosave) || save) {\n        serverLog(LL_NOTICE,\"Saving the final RDB snapshot before exiting.\");\n        /* Snapshotting. Perform a SYNC SAVE and exit */\n        if (rdbSave(server.rdb_filename) != C_OK) {\n            /* Ooops.. error saving! The best we can do is to continue\n             * operating. Note that if there was a background saving process,\n             * in the next cron() Redis will be notified that the background\n             * saving aborted, handling special stuff like slaves pending for\n             * synchronization... */\n            serverLog(LL_WARNING,\"Error trying to save the DB, can't exit.\");\n            return C_ERR;\n        }\n    }\n\n    /* Remove the pid file if possible and needed. */\n    if (server.daemonize || server.pidfile) {\n        serverLog(LL_NOTICE,\"Removing the pid file.\");\n        unlink(server.pidfile);\n    }\n\n    /* Best effort flush of slave output buffers, so that we hopefully\n     * send them pending writes. */\n    flushSlavesOutputBuffers();\n\n    /* Close the listening sockets. Apparently this allows faster restarts. */\n    closeListeningSockets(1);\n    serverLog(LL_WARNING,\"%s is now ready to exit, bye bye...\",\n        server.sentinel_mode ? \"Sentinel\" : \"Redis\");\n    return C_OK;\n}\n\n/*================================== Commands =============================== */\n\n/* Return zero if strings are the same, non-zero if they are not.\n * The comparison is performed in a way that prevents an attacker to obtain\n * information about the nature of the strings just monitoring the execution\n * time of the function.\n *\n * Note that limiting the comparison length to strings up to 512 bytes we\n * can avoid leaking any information about the password length and any\n * possible branch misprediction related leak.\n */\nint time_independent_strcmp(char *a, char *b) {\n    char bufa[CONFIG_AUTHPASS_MAX_LEN], bufb[CONFIG_AUTHPASS_MAX_LEN];\n    /* The above two strlen perform len(a) + len(b) operations where either\n     * a or b are fixed (our password) length, and the difference is only\n     * relative to the length of the user provided string, so no information\n     * leak is possible in the following two lines of code. */\n    unsigned int alen = strlen(a);\n    unsigned int blen = strlen(b);\n    unsigned int j;\n    int diff = 0;\n\n    /* We can't compare strings longer than our static buffers.\n     * Note that this will never pass the first test in practical circumstances\n     * so there is no info leak. */\n    if (alen > sizeof(bufa) || blen > sizeof(bufb)) return 1;\n\n    memset(bufa,0,sizeof(bufa));        /* Constant time. */\n    memset(bufb,0,sizeof(bufb));        /* Constant time. */\n    /* Again the time of the following two copies is proportional to\n     * len(a) + len(b) so no info is leaked. */\n    memcpy(bufa,a,alen);\n    memcpy(bufb,b,blen);\n\n    /* Always compare all the chars in the two buffers without\n     * conditional expressions. */\n    for (j = 0; j < sizeof(bufa); j++) {\n        diff |= (bufa[j] ^ bufb[j]);\n    }\n    /* Length must be equal as well. */\n    diff |= alen ^ blen;\n    return diff; /* If zero strings are the same. */\n}\n\nvoid authCommand(client *c) {\n    if (!server.requirepass) {\n        addReplyError(c,\"Client sent AUTH, but no password is set\");\n    } else if (!time_independent_strcmp(c->argv[1]->ptr, server.requirepass)) {\n      c->authenticated = 1;\n      addReply(c,shared.ok);\n    } else {\n      c->authenticated = 0;\n      addReplyError(c,\"invalid password\");\n    }\n}\n\n/* The PING command. It works in a different way if the client is in\n * in Pub/Sub mode. */\nvoid pingCommand(client *c) {\n    /* The command takes zero or one arguments. */\n    if (c->argc > 2) {\n        addReplyErrorFormat(c,\"wrong number of arguments for '%s' command\",\n            c->cmd->name);\n        return;\n    }\n\n    if (c->flags & CLIENT_PUBSUB) {\n        addReply(c,shared.mbulkhdr[2]);\n        addReplyBulkCBuffer(c,\"pong\",4);\n        if (c->argc == 1)\n            addReplyBulkCBuffer(c,\"\",0);\n        else\n            addReplyBulk(c,c->argv[1]);\n    } else {\n        if (c->argc == 1)\n            addReply(c,shared.pong);\n        else\n            addReplyBulk(c,c->argv[1]);\n    }\n}\n\nvoid echoCommand(client *c) {\n    addReplyBulk(c,c->argv[1]);\n}\n\nvoid timeCommand(client *c) {\n    struct timeval tv;\n\n    /* gettimeofday() can only fail if &tv is a bad address so we\n     * don't check for errors. */\n    gettimeofday(&tv,NULL);\n    addReplyMultiBulkLen(c,2);\n    addReplyBulkLongLong(c,tv.tv_sec);\n    addReplyBulkLongLong(c,tv.tv_usec);\n}\n\n/* Helper function for addReplyCommand() to output flags. */\nint addReplyCommandFlag(client *c, struct redisCommand *cmd, int f, char *reply) {\n    if (cmd->flags & f) {\n        addReplyStatus(c, reply);\n        return 1;\n    }\n    return 0;\n}\n\n/* Output the representation of a Redis command. Used by the COMMAND command. */\nvoid addReplyCommand(client *c, struct redisCommand *cmd) {\n    if (!cmd) {\n        addReply(c, shared.nullbulk);\n    } else {\n        /* We are adding: command name, arg count, flags, first, last, offset */\n        addReplyMultiBulkLen(c, 6);\n        addReplyBulkCString(c, cmd->name);\n        addReplyLongLong(c, cmd->arity);\n\n        int flagcount = 0;\n        void *flaglen = addDeferredMultiBulkLength(c);\n        flagcount += addReplyCommandFlag(c,cmd,CMD_WRITE, \"write\");\n        flagcount += addReplyCommandFlag(c,cmd,CMD_READONLY, \"readonly\");\n        flagcount += addReplyCommandFlag(c,cmd,CMD_DENYOOM, \"denyoom\");\n        flagcount += addReplyCommandFlag(c,cmd,CMD_ADMIN, \"admin\");\n        flagcount += addReplyCommandFlag(c,cmd,CMD_PUBSUB, \"pubsub\");\n        flagcount += addReplyCommandFlag(c,cmd,CMD_NOSCRIPT, \"noscript\");\n        flagcount += addReplyCommandFlag(c,cmd,CMD_RANDOM, \"random\");\n        flagcount += addReplyCommandFlag(c,cmd,CMD_SORT_FOR_SCRIPT,\"sort_for_script\");\n        flagcount += addReplyCommandFlag(c,cmd,CMD_LOADING, \"loading\");\n        flagcount += addReplyCommandFlag(c,cmd,CMD_STALE, \"stale\");\n        flagcount += addReplyCommandFlag(c,cmd,CMD_SKIP_MONITOR, \"skip_monitor\");\n        flagcount += addReplyCommandFlag(c,cmd,CMD_ASKING, \"asking\");\n        flagcount += addReplyCommandFlag(c,cmd,CMD_FAST, \"fast\");\n        if (cmd->getkeys_proc) {\n            addReplyStatus(c, \"movablekeys\");\n            flagcount += 1;\n        }\n        setDeferredMultiBulkLength(c, flaglen, flagcount);\n\n        addReplyLongLong(c, cmd->firstkey);\n        addReplyLongLong(c, cmd->lastkey);\n        addReplyLongLong(c, cmd->keystep);\n    }\n}\n\n/* COMMAND <subcommand> <args> */\nvoid commandCommand(client *c) {\n    dictIterator *di;\n    dictEntry *de;\n\n    if (c->argc == 1) {\n        addReplyMultiBulkLen(c, dictSize(server.commands));\n        di = dictGetIterator(server.commands);\n        while ((de = dictNext(di)) != NULL) {\n            addReplyCommand(c, dictGetVal(de));\n        }\n        dictReleaseIterator(di);\n    } else if (!strcasecmp(c->argv[1]->ptr, \"info\")) {\n        int i;\n        addReplyMultiBulkLen(c, c->argc-2);\n        for (i = 2; i < c->argc; i++) {\n            addReplyCommand(c, dictFetchValue(server.commands, c->argv[i]->ptr));\n        }\n    } else if (!strcasecmp(c->argv[1]->ptr, \"count\") && c->argc == 2) {\n        addReplyLongLong(c, dictSize(server.commands));\n    } else if (!strcasecmp(c->argv[1]->ptr,\"getkeys\") && c->argc >= 3) {\n        struct redisCommand *cmd = lookupCommand(c->argv[2]->ptr);\n        int *keys, numkeys, j;\n\n        if (!cmd) {\n            addReplyErrorFormat(c,\"Invalid command specified\");\n            return;\n        } else if ((cmd->arity > 0 && cmd->arity != c->argc-2) ||\n                   ((c->argc-2) < -cmd->arity))\n        {\n            addReplyError(c,\"Invalid number of arguments specified for command\");\n            return;\n        }\n\n        keys = getKeysFromCommand(cmd,c->argv+2,c->argc-2,&numkeys);\n        addReplyMultiBulkLen(c,numkeys);\n        for (j = 0; j < numkeys; j++) addReplyBulk(c,c->argv[keys[j]+2]);\n        getKeysFreeResult(keys);\n    } else {\n        addReplyError(c, \"Unknown subcommand or wrong number of arguments.\");\n        return;\n    }\n}\n\n/* Convert an amount of bytes into a human readable string in the form\n * of 100B, 2G, 100M, 4K, and so forth. */\nvoid bytesToHuman(char *s, unsigned long long n) {\n    double d;\n\n    if (n < 1024) {\n        /* Bytes */\n        sprintf(s,\"%lluB\",n);\n        return;\n    } else if (n < (1024*1024)) {\n        d = (double)n/(1024);\n        sprintf(s,\"%.2fK\",d);\n    } else if (n < (1024LL*1024*1024)) {\n        d = (double)n/(1024*1024);\n        sprintf(s,\"%.2fM\",d);\n    } else if (n < (1024LL*1024*1024*1024)) {\n        d = (double)n/(1024LL*1024*1024);\n        sprintf(s,\"%.2fG\",d);\n    } else if (n < (1024LL*1024*1024*1024*1024)) {\n        d = (double)n/(1024LL*1024*1024*1024);\n        sprintf(s,\"%.2fT\",d);\n    } else if (n < (1024LL*1024*1024*1024*1024*1024)) {\n        d = (double)n/(1024LL*1024*1024*1024*1024);\n        sprintf(s,\"%.2fP\",d);\n    } else {\n        /* Let's hope we never need this */\n        sprintf(s,\"%lluB\",n);\n    }\n}\n\n/* Create the string returned by the INFO command. This is decoupled\n * by the INFO command itself as we need to report the same information\n * on memory corruption problems. */\nsds genRedisInfoString(char *section) {\n    sds info = sdsempty();\n    time_t uptime = server.unixtime-server.stat_starttime;\n    int j, numcommands;\n    struct rusage self_ru, c_ru;\n    unsigned long lol, bib;\n    int allsections = 0, defsections = 0;\n    int sections = 0;\n\n    if (section == NULL) section = \"default\";\n    allsections = strcasecmp(section,\"all\") == 0;\n    defsections = strcasecmp(section,\"default\") == 0;\n\n    getrusage(RUSAGE_SELF, &self_ru);\n    getrusage(RUSAGE_CHILDREN, &c_ru);\n    getClientsMaxBuffers(&lol,&bib);\n\n    /* Server */\n    if (allsections || defsections || !strcasecmp(section,\"server\")) {\n        static int call_uname = 1;\n        static struct utsname name;\n        char *mode;\n\n        if (server.cluster_enabled) mode = \"cluster\";\n        else if (server.sentinel_mode) mode = \"sentinel\";\n        else mode = \"standalone\";\n\n        if (sections++) info = sdscat(info,\"\\r\\n\");\n\n        if (call_uname) {\n            /* Uname can be slow and is always the same output. Cache it. */\n            uname(&name);\n            call_uname = 0;\n        }\n\n        info = sdscatprintf(info,\n            \"# Server\\r\\n\"\n            \"redis_version:%s\\r\\n\"\n            \"redis_git_sha1:%s\\r\\n\"\n            \"redis_git_dirty:%d\\r\\n\"\n            \"redis_build_id:%llx\\r\\n\"\n            \"redis_mode:%s\\r\\n\"\n            \"os:%s %s %s\\r\\n\"\n            \"arch_bits:%d\\r\\n\"\n            \"multiplexing_api:%s\\r\\n\"\n            \"gcc_version:%d.%d.%d\\r\\n\"\n            \"process_id:%ld\\r\\n\"\n            \"run_id:%s\\r\\n\"\n            \"tcp_port:%d\\r\\n\"\n            \"uptime_in_seconds:%jd\\r\\n\"\n            \"uptime_in_days:%jd\\r\\n\"\n            \"hz:%d\\r\\n\"\n            \"lru_clock:%ld\\r\\n\"\n            \"executable:%s\\r\\n\"\n            \"config_file:%s\\r\\n\",\n            REDIS_VERSION,\n            redisGitSHA1(),\n            strtol(redisGitDirty(),NULL,10) > 0,\n            (unsigned long long) redisBuildId(),\n            mode,\n            name.sysname, name.release, name.machine,\n            server.arch_bits,\n            aeGetApiName(),\n#ifdef __GNUC__\n            __GNUC__,__GNUC_MINOR__,__GNUC_PATCHLEVEL__,\n#else\n            0,0,0,\n#endif\n            (long) getpid(),\n            server.runid,\n            server.port,\n            (intmax_t)uptime,\n            (intmax_t)(uptime/(3600*24)),\n            server.hz,\n            (unsigned long) server.lruclock,\n            server.executable ? server.executable : \"\",\n            server.configfile ? server.configfile : \"\");\n    }\n\n    /* Clients */\n    if (allsections || defsections || !strcasecmp(section,\"clients\")) {\n        if (sections++) info = sdscat(info,\"\\r\\n\");\n        info = sdscatprintf(info,\n            \"# Clients\\r\\n\"\n            \"connected_clients:%lu\\r\\n\"\n            \"client_longest_output_list:%lu\\r\\n\"\n            \"client_biggest_input_buf:%lu\\r\\n\"\n            \"blocked_clients:%d\\r\\n\",\n            listLength(server.clients)-listLength(server.slaves),\n            lol, bib,\n            server.bpop_blocked_clients);\n    }\n\n    /* Memory */\n    if (allsections || defsections || !strcasecmp(section,\"memory\")) {\n        char hmem[64];\n        char peak_hmem[64];\n        char total_system_hmem[64];\n        char used_memory_lua_hmem[64];\n        char used_memory_rss_hmem[64];\n        char maxmemory_hmem[64];\n        size_t zmalloc_used = zmalloc_used_memory();\n        size_t total_system_mem = server.system_memory_size;\n        const char *evict_policy = evictPolicyToString();\n        long long memory_lua = (long long)lua_gc(server.lua,LUA_GCCOUNT,0)*1024;\n\n        /* Peak memory is updated from time to time by serverCron() so it\n         * may happen that the instantaneous value is slightly bigger than\n         * the peak value. This may confuse users, so we update the peak\n         * if found smaller than the current memory usage. */\n        if (zmalloc_used > server.stat_peak_memory)\n            server.stat_peak_memory = zmalloc_used;\n\n        bytesToHuman(hmem,zmalloc_used);\n        bytesToHuman(peak_hmem,server.stat_peak_memory);\n        bytesToHuman(total_system_hmem,total_system_mem);\n        bytesToHuman(used_memory_lua_hmem,memory_lua);\n        bytesToHuman(used_memory_rss_hmem,server.resident_set_size);\n        bytesToHuman(maxmemory_hmem,server.maxmemory);\n\n        if (sections++) info = sdscat(info,\"\\r\\n\");\n        info = sdscatprintf(info,\n            \"# Memory\\r\\n\"\n            \"used_memory:%zu\\r\\n\"\n            \"used_memory_human:%s\\r\\n\"\n            \"used_memory_rss:%zu\\r\\n\"\n            \"used_memory_rss_human:%s\\r\\n\"\n            \"used_memory_peak:%zu\\r\\n\"\n            \"used_memory_peak_human:%s\\r\\n\"\n            \"total_system_memory:%lu\\r\\n\"\n            \"total_system_memory_human:%s\\r\\n\"\n            \"used_memory_lua:%lld\\r\\n\"\n            \"used_memory_lua_human:%s\\r\\n\"\n            \"maxmemory:%lld\\r\\n\"\n            \"maxmemory_human:%s\\r\\n\"\n            \"maxmemory_policy:%s\\r\\n\"\n            \"mem_fragmentation_ratio:%.2f\\r\\n\"\n            \"mem_allocator:%s\\r\\n\",\n            zmalloc_used,\n            hmem,\n            server.resident_set_size,\n            used_memory_rss_hmem,\n            server.stat_peak_memory,\n            peak_hmem,\n            (unsigned long)total_system_mem,\n            total_system_hmem,\n            memory_lua,\n            used_memory_lua_hmem,\n            server.maxmemory,\n            maxmemory_hmem,\n            evict_policy,\n            zmalloc_get_fragmentation_ratio(server.resident_set_size),\n            ZMALLOC_LIB\n            );\n    }\n\n    /* Persistence */\n    if (allsections || defsections || !strcasecmp(section,\"persistence\")) {\n        if (sections++) info = sdscat(info,\"\\r\\n\");\n        info = sdscatprintf(info,\n            \"# Persistence\\r\\n\"\n            \"loading:%d\\r\\n\"\n            \"rdb_changes_since_last_save:%lld\\r\\n\"\n            \"rdb_bgsave_in_progress:%d\\r\\n\"\n            \"rdb_last_save_time:%jd\\r\\n\"\n            \"rdb_last_bgsave_status:%s\\r\\n\"\n            \"rdb_last_bgsave_time_sec:%jd\\r\\n\"\n            \"rdb_current_bgsave_time_sec:%jd\\r\\n\"\n            \"aof_enabled:%d\\r\\n\"\n            \"aof_rewrite_in_progress:%d\\r\\n\"\n            \"aof_rewrite_scheduled:%d\\r\\n\"\n            \"aof_last_rewrite_time_sec:%jd\\r\\n\"\n            \"aof_current_rewrite_time_sec:%jd\\r\\n\"\n            \"aof_last_bgrewrite_status:%s\\r\\n\"\n            \"aof_last_write_status:%s\\r\\n\",\n            server.loading,\n            server.dirty,\n            server.rdb_child_pid != -1,\n            (intmax_t)server.lastsave,\n            (server.lastbgsave_status == C_OK) ? \"ok\" : \"err\",\n            (intmax_t)server.rdb_save_time_last,\n            (intmax_t)((server.rdb_child_pid == -1) ?\n                -1 : time(NULL)-server.rdb_save_time_start),\n            server.aof_state != AOF_OFF,\n            server.aof_child_pid != -1,\n            server.aof_rewrite_scheduled,\n            (intmax_t)server.aof_rewrite_time_last,\n            (intmax_t)((server.aof_child_pid == -1) ?\n                -1 : time(NULL)-server.aof_rewrite_time_start),\n            (server.aof_lastbgrewrite_status == C_OK) ? \"ok\" : \"err\",\n            (server.aof_last_write_status == C_OK) ? \"ok\" : \"err\");\n\n        if (server.aof_state != AOF_OFF) {\n            info = sdscatprintf(info,\n                \"aof_current_size:%lld\\r\\n\"\n                \"aof_base_size:%lld\\r\\n\"\n                \"aof_pending_rewrite:%d\\r\\n\"\n                \"aof_buffer_length:%zu\\r\\n\"\n                \"aof_rewrite_buffer_length:%lu\\r\\n\"\n                \"aof_pending_bio_fsync:%llu\\r\\n\"\n                \"aof_delayed_fsync:%lu\\r\\n\",\n                (long long) server.aof_current_size,\n                (long long) server.aof_rewrite_base_size,\n                server.aof_rewrite_scheduled,\n                sdslen(server.aof_buf),\n                aofRewriteBufferSize(),\n                bioPendingJobsOfType(BIO_AOF_FSYNC),\n                server.aof_delayed_fsync);\n        }\n\n        if (server.loading) {\n            double perc;\n            time_t eta, elapsed;\n            off_t remaining_bytes = server.loading_total_bytes-\n                                    server.loading_loaded_bytes;\n\n            perc = ((double)server.loading_loaded_bytes /\n                   (server.loading_total_bytes+1)) * 100;\n\n            elapsed = time(NULL)-server.loading_start_time;\n            if (elapsed == 0) {\n                eta = 1; /* A fake 1 second figure if we don't have\n                            enough info */\n            } else {\n                eta = (elapsed*remaining_bytes)/(server.loading_loaded_bytes+1);\n            }\n\n            info = sdscatprintf(info,\n                \"loading_start_time:%jd\\r\\n\"\n                \"loading_total_bytes:%llu\\r\\n\"\n                \"loading_loaded_bytes:%llu\\r\\n\"\n                \"loading_loaded_perc:%.2f\\r\\n\"\n                \"loading_eta_seconds:%jd\\r\\n\",\n                (intmax_t) server.loading_start_time,\n                (unsigned long long) server.loading_total_bytes,\n                (unsigned long long) server.loading_loaded_bytes,\n                perc,\n                (intmax_t)eta\n            );\n        }\n    }\n\n    /* Stats */\n    if (allsections || defsections || !strcasecmp(section,\"stats\")) {\n        if (sections++) info = sdscat(info,\"\\r\\n\");\n        info = sdscatprintf(info,\n            \"# Stats\\r\\n\"\n            \"total_connections_received:%lld\\r\\n\"\n            \"total_commands_processed:%lld\\r\\n\"\n            \"instantaneous_ops_per_sec:%lld\\r\\n\"\n            \"total_net_input_bytes:%lld\\r\\n\"\n            \"total_net_output_bytes:%lld\\r\\n\"\n            \"instantaneous_input_kbps:%.2f\\r\\n\"\n            \"instantaneous_output_kbps:%.2f\\r\\n\"\n            \"rejected_connections:%lld\\r\\n\"\n            \"sync_full:%lld\\r\\n\"\n            \"sync_partial_ok:%lld\\r\\n\"\n            \"sync_partial_err:%lld\\r\\n\"\n            \"expired_keys:%lld\\r\\n\"\n            \"evicted_keys:%lld\\r\\n\"\n            \"keyspace_hits:%lld\\r\\n\"\n            \"keyspace_misses:%lld\\r\\n\"\n            \"pubsub_channels:%ld\\r\\n\"\n            \"pubsub_patterns:%lu\\r\\n\"\n            \"latest_fork_usec:%lld\\r\\n\"\n            \"migrate_cached_sockets:%ld\\r\\n\",\n            server.stat_numconnections,\n            server.stat_numcommands,\n            getInstantaneousMetric(STATS_METRIC_COMMAND),\n            server.stat_net_input_bytes,\n            server.stat_net_output_bytes,\n            (float)getInstantaneousMetric(STATS_METRIC_NET_INPUT)/1024,\n            (float)getInstantaneousMetric(STATS_METRIC_NET_OUTPUT)/1024,\n            server.stat_rejected_conn,\n            server.stat_sync_full,\n            server.stat_sync_partial_ok,\n            server.stat_sync_partial_err,\n            server.stat_expiredkeys,\n            server.stat_evictedkeys,\n            server.stat_keyspace_hits,\n            server.stat_keyspace_misses,\n            dictSize(server.pubsub_channels),\n            listLength(server.pubsub_patterns),\n            server.stat_fork_time,\n            dictSize(server.migrate_cached_sockets));\n    }\n\n    /* Replication */\n    if (allsections || defsections || !strcasecmp(section,\"replication\")) {\n        if (sections++) info = sdscat(info,\"\\r\\n\");\n        info = sdscatprintf(info,\n            \"# Replication\\r\\n\"\n            \"role:%s\\r\\n\",\n            server.masterhost == NULL ? \"master\" : \"slave\");\n        if (server.masterhost) {\n            long long slave_repl_offset = 1;\n\n            if (server.master)\n                slave_repl_offset = server.master->reploff;\n            else if (server.cached_master)\n                slave_repl_offset = server.cached_master->reploff;\n\n            info = sdscatprintf(info,\n                \"master_host:%s\\r\\n\"\n                \"master_port:%d\\r\\n\"\n                \"master_link_status:%s\\r\\n\"\n                \"master_last_io_seconds_ago:%d\\r\\n\"\n                \"master_sync_in_progress:%d\\r\\n\"\n                \"slave_repl_offset:%lld\\r\\n\"\n                ,server.masterhost,\n                server.masterport,\n                (server.repl_state == REPL_STATE_CONNECTED) ?\n                    \"up\" : \"down\",\n                server.master ?\n                ((int)(server.unixtime-server.master->lastinteraction)) : -1,\n                server.repl_state == REPL_STATE_TRANSFER,\n                slave_repl_offset\n            );\n\n            if (server.repl_state == REPL_STATE_TRANSFER) {\n                info = sdscatprintf(info,\n                    \"master_sync_left_bytes:%lld\\r\\n\"\n                    \"master_sync_last_io_seconds_ago:%d\\r\\n\"\n                    , (long long)\n                        (server.repl_transfer_size - server.repl_transfer_read),\n                    (int)(server.unixtime-server.repl_transfer_lastio)\n                );\n            }\n\n            if (server.repl_state != REPL_STATE_CONNECTED) {\n                info = sdscatprintf(info,\n                    \"master_link_down_since_seconds:%jd\\r\\n\",\n                    (intmax_t)server.unixtime-server.repl_down_since);\n            }\n            info = sdscatprintf(info,\n                \"slave_priority:%d\\r\\n\"\n                \"slave_read_only:%d\\r\\n\",\n                server.slave_priority,\n                server.repl_slave_ro);\n        }\n\n        info = sdscatprintf(info,\n            \"connected_slaves:%lu\\r\\n\",\n            listLength(server.slaves));\n\n        /* If min-slaves-to-write is active, write the number of slaves\n         * currently considered 'good'. */\n        if (server.repl_min_slaves_to_write &&\n            server.repl_min_slaves_max_lag) {\n            info = sdscatprintf(info,\n                \"min_slaves_good_slaves:%d\\r\\n\",\n                server.repl_good_slaves_count);\n        }\n\n        if (listLength(server.slaves)) {\n            int slaveid = 0;\n            listNode *ln;\n            listIter li;\n\n            listRewind(server.slaves,&li);\n            while((ln = listNext(&li))) {\n                client *slave = listNodeValue(ln);\n                char *state = NULL;\n                char ip[NET_IP_STR_LEN], *slaveip = slave->slave_ip;\n                int port;\n                long lag = 0;\n\n                if (slaveip[0] == '\\0') {\n                    if (anetPeerToString(slave->fd,ip,sizeof(ip),&port) == -1)\n                        continue;\n                    slaveip = ip;\n                }\n                switch(slave->replstate) {\n                case SLAVE_STATE_WAIT_BGSAVE_START:\n                case SLAVE_STATE_WAIT_BGSAVE_END:\n                    state = \"wait_bgsave\";\n                    break;\n                case SLAVE_STATE_SEND_BULK:\n                    state = \"send_bulk\";\n                    break;\n                case SLAVE_STATE_ONLINE:\n                    state = \"online\";\n                    break;\n                }\n                if (state == NULL) continue;\n                if (slave->replstate == SLAVE_STATE_ONLINE)\n                    lag = time(NULL) - slave->repl_ack_time;\n\n                info = sdscatprintf(info,\n                    \"slave%d:ip=%s,port=%d,state=%s,\"\n                    \"offset=%lld,lag=%ld\\r\\n\",\n                    slaveid,slaveip,slave->slave_listening_port,state,\n                    slave->repl_ack_off, lag);\n                slaveid++;\n            }\n        }\n        info = sdscatprintf(info,\n            \"master_repl_offset:%lld\\r\\n\"\n            \"repl_backlog_active:%d\\r\\n\"\n            \"repl_backlog_size:%lld\\r\\n\"\n            \"repl_backlog_first_byte_offset:%lld\\r\\n\"\n            \"repl_backlog_histlen:%lld\\r\\n\",\n            server.master_repl_offset,\n            server.repl_backlog != NULL,\n            server.repl_backlog_size,\n            server.repl_backlog_off,\n            server.repl_backlog_histlen);\n    }\n\n    /* CPU */\n    if (allsections || defsections || !strcasecmp(section,\"cpu\")) {\n        if (sections++) info = sdscat(info,\"\\r\\n\");\n        info = sdscatprintf(info,\n        \"# CPU\\r\\n\"\n        \"used_cpu_sys:%.2f\\r\\n\"\n        \"used_cpu_user:%.2f\\r\\n\"\n        \"used_cpu_sys_children:%.2f\\r\\n\"\n        \"used_cpu_user_children:%.2f\\r\\n\",\n        (float)self_ru.ru_stime.tv_sec+(float)self_ru.ru_stime.tv_usec/1000000,\n        (float)self_ru.ru_utime.tv_sec+(float)self_ru.ru_utime.tv_usec/1000000,\n        (float)c_ru.ru_stime.tv_sec+(float)c_ru.ru_stime.tv_usec/1000000,\n        (float)c_ru.ru_utime.tv_sec+(float)c_ru.ru_utime.tv_usec/1000000);\n    }\n\n    /* cmdtime */\n    if (allsections || !strcasecmp(section,\"commandstats\")) {\n        if (sections++) info = sdscat(info,\"\\r\\n\");\n        info = sdscatprintf(info, \"# Commandstats\\r\\n\");\n        numcommands = sizeof(redisCommandTable)/sizeof(struct redisCommand);\n        for (j = 0; j < numcommands; j++) {\n            struct redisCommand *c = redisCommandTable+j;\n\n            if (!c->calls) continue;\n            info = sdscatprintf(info,\n                \"cmdstat_%s:calls=%lld,usec=%lld,usec_per_call=%.2f\\r\\n\",\n                c->name, c->calls, c->microseconds,\n                (c->calls == 0) ? 0 : ((float)c->microseconds/c->calls));\n        }\n    }\n\n    /* Cluster */\n    if (allsections || defsections || !strcasecmp(section,\"cluster\")) {\n        if (sections++) info = sdscat(info,\"\\r\\n\");\n        info = sdscatprintf(info,\n        \"# Cluster\\r\\n\"\n        \"cluster_enabled:%d\\r\\n\",\n        server.cluster_enabled);\n    }\n\n    /* Key space */\n    if (allsections || defsections || !strcasecmp(section,\"keyspace\")) {\n        if (sections++) info = sdscat(info,\"\\r\\n\");\n        info = sdscatprintf(info, \"# Keyspace\\r\\n\");\n        for (j = 0; j < server.dbnum; j++) {\n            long long keys, vkeys;\n\n            keys = dictSize(server.db[j].dict);\n            vkeys = dictSize(server.db[j].expires);\n            if (keys || vkeys) {\n                info = sdscatprintf(info,\n                    \"db%d:keys=%lld,expires=%lld,avg_ttl=%lld\\r\\n\",\n                    j, keys, vkeys, server.db[j].avg_ttl);\n            }\n        }\n    }\n    return info;\n}\n\nvoid infoCommand(client *c) {\n    char *section = c->argc == 2 ? c->argv[1]->ptr : \"default\";\n\n    if (c->argc > 2) {\n        addReply(c,shared.syntaxerr);\n        return;\n    }\n    addReplyBulkSds(c, genRedisInfoString(section));\n}\n\nvoid monitorCommand(client *c) {\n    /* ignore MONITOR if already slave or in monitor mode */\n    if (c->flags & CLIENT_SLAVE) return;\n\n    c->flags |= (CLIENT_SLAVE|CLIENT_MONITOR);\n    listAddNodeTail(server.monitors,c);\n    addReply(c,shared.ok);\n}\n\n/* ============================ Maxmemory directive  ======================== */\n\n/* freeMemoryIfNeeded() gets called when 'maxmemory' is set on the config\n * file to limit the max memory used by the server, before processing a\n * command.\n *\n * The goal of the function is to free enough memory to keep Redis under the\n * configured memory limit.\n *\n * The function starts calculating how many bytes should be freed to keep\n * Redis under the limit, and enters a loop selecting the best keys to\n * evict accordingly to the configured policy.\n *\n * If all the bytes needed to return back under the limit were freed the\n * function returns C_OK, otherwise C_ERR is returned, and the caller\n * should block the execution of commands that will result in more memory\n * used by the server.\n *\n * ------------------------------------------------------------------------\n *\n * LRU approximation algorithm\n *\n * Redis uses an approximation of the LRU algorithm that runs in constant\n * memory. Every time there is a key to expire, we sample N keys (with\n * N very small, usually in around 5) to populate a pool of best keys to\n * evict of M keys (the pool size is defined by MAXMEMORY_EVICTION_POOL_SIZE).\n *\n * The N keys sampled are added in the pool of good keys to expire (the one\n * with an old access time) if they are better than one of the current keys\n * in the pool.\n *\n * After the pool is populated, the best key we have in the pool is expired.\n * However note that we don't remove keys from the pool when they are deleted\n * so the pool may contain keys that no longer exist.\n *\n * When we try to evict a key, and all the entries in the pool don't exist\n * we populate it again. This time we'll be sure that the pool has at least\n * one key that can be evicted, if there is at least one key that can be\n * evicted in the whole database. */\n\n/* Create a new eviction pool. */\nstruct evictionPoolEntry *evictionPoolAlloc(void) {\n    struct evictionPoolEntry *ep;\n    int j;\n\n    ep = zmalloc(sizeof(*ep)*MAXMEMORY_EVICTION_POOL_SIZE);\n    for (j = 0; j < MAXMEMORY_EVICTION_POOL_SIZE; j++) {\n        ep[j].idle = 0;\n        ep[j].key = NULL;\n    }\n    return ep;\n}\n\n/* This is an helper function for freeMemoryIfNeeded(), it is used in order\n * to populate the evictionPool with a few entries every time we want to\n * expire a key. Keys with idle time smaller than one of the current\n * keys are added. Keys are always added if there are free entries.\n *\n * We insert keys on place in ascending order, so keys with the smaller\n * idle time are on the left, and keys with the higher idle time on the\n * right. */\n\n#define EVICTION_SAMPLES_ARRAY_SIZE 16\nvoid evictionPoolPopulate(dict *sampledict, dict *keydict, struct evictionPoolEntry *pool) {\n    int j, k, count;\n    dictEntry *_samples[EVICTION_SAMPLES_ARRAY_SIZE];\n    dictEntry **samples;\n\n    /* Try to use a static buffer: this function is a big hit...\n     * Note: it was actually measured that this helps. */\n    if (server.maxmemory_samples <= EVICTION_SAMPLES_ARRAY_SIZE) {\n        samples = _samples;\n    } else {\n        samples = zmalloc(sizeof(samples[0])*server.maxmemory_samples);\n    }\n\n    count = dictGetSomeKeys(sampledict,samples,server.maxmemory_samples);\n    for (j = 0; j < count; j++) {\n        unsigned long long idle;\n        sds key;\n        robj *o;\n        dictEntry *de;\n\n        de = samples[j];\n        key = dictGetKey(de);\n        /* If the dictionary we are sampling from is not the main\n         * dictionary (but the expires one) we need to lookup the key\n         * again in the key dictionary to obtain the value object. */\n        if (sampledict != keydict) de = dictFind(keydict, key);\n        o = dictGetVal(de);\n        idle = estimateObjectIdleTime(o);\n\n        /* Insert the element inside the pool.\n         * First, find the first empty bucket or the first populated\n         * bucket that has an idle time smaller than our idle time. */\n        k = 0;\n        while (k < MAXMEMORY_EVICTION_POOL_SIZE &&\n               pool[k].key &&\n               pool[k].idle < idle) k++;\n        if (k == 0 && pool[MAXMEMORY_EVICTION_POOL_SIZE-1].key != NULL) {\n            /* Can't insert if the element is < the worst element we have\n             * and there are no empty buckets. */\n            continue;\n        } else if (k < MAXMEMORY_EVICTION_POOL_SIZE && pool[k].key == NULL) {\n            /* Inserting into empty position. No setup needed before insert. */\n        } else {\n            /* Inserting in the middle. Now k points to the first element\n             * greater than the element to insert.  */\n            if (pool[MAXMEMORY_EVICTION_POOL_SIZE-1].key == NULL) {\n                /* Free space on the right? Insert at k shifting\n                 * all the elements from k to end to the right. */\n                memmove(pool+k+1,pool+k,\n                    sizeof(pool[0])*(MAXMEMORY_EVICTION_POOL_SIZE-k-1));\n            } else {\n                /* No free space on right? Insert at k-1 */\n                k--;\n                /* Shift all elements on the left of k (included) to the\n                 * left, so we discard the element with smaller idle time. */\n                sdsfree(pool[0].key);\n                memmove(pool,pool+1,sizeof(pool[0])*k);\n            }\n        }\n        pool[k].key = sdsdup(key);\n        pool[k].idle = idle;\n    }\n    if (samples != _samples) zfree(samples);\n}\n\nint freeMemoryIfNeeded(void) {\n    size_t mem_used, mem_tofree, mem_freed;\n    int slaves = listLength(server.slaves);\n    mstime_t latency, eviction_latency;\n\n    /* Remove the size of slaves output buffers and AOF buffer from the\n     * count of used memory. */\n    mem_used = zmalloc_used_memory();\n    if (slaves) {\n        listIter li;\n        listNode *ln;\n\n        listRewind(server.slaves,&li);\n        while((ln = listNext(&li))) {\n            client *slave = listNodeValue(ln);\n            unsigned long obuf_bytes = getClientOutputBufferMemoryUsage(slave);\n            if (obuf_bytes > mem_used)\n                mem_used = 0;\n            else\n                mem_used -= obuf_bytes;\n        }\n    }\n    if (server.aof_state != AOF_OFF) {\n        mem_used -= sdslen(server.aof_buf);\n        mem_used -= aofRewriteBufferSize();\n    }\n\n    /* Check if we are over the memory limit. */\n    if (mem_used <= server.maxmemory) return C_OK;\n\n    if (server.maxmemory_policy == MAXMEMORY_NO_EVICTION)\n        return C_ERR; /* We need to free memory, but policy forbids. */\n\n    /* Compute how much memory we need to free. */\n    mem_tofree = mem_used - server.maxmemory;\n    mem_freed = 0;\n    latencyStartMonitor(latency);\n    while (mem_freed < mem_tofree) {\n        int j, k, keys_freed = 0;\n\n        for (j = 0; j < server.dbnum; j++) {\n            long bestval = 0; /* just to prevent warning */\n            sds bestkey = NULL;\n            dictEntry *de;\n            redisDb *db = server.db+j;\n            dict *dict;\n\n            if (server.maxmemory_policy == MAXMEMORY_ALLKEYS_LRU ||\n                server.maxmemory_policy == MAXMEMORY_ALLKEYS_RANDOM)\n            {\n                dict = server.db[j].dict;\n            } else {\n                dict = server.db[j].expires;\n            }\n            if (dictSize(dict) == 0) continue;\n\n            /* volatile-random and allkeys-random policy */\n            if (server.maxmemory_policy == MAXMEMORY_ALLKEYS_RANDOM ||\n                server.maxmemory_policy == MAXMEMORY_VOLATILE_RANDOM)\n            {\n                de = dictGetRandomKey(dict);\n                bestkey = dictGetKey(de);\n            }\n\n            /* volatile-lru and allkeys-lru policy */\n            else if (server.maxmemory_policy == MAXMEMORY_ALLKEYS_LRU ||\n                server.maxmemory_policy == MAXMEMORY_VOLATILE_LRU)\n            {\n                struct evictionPoolEntry *pool = db->eviction_pool;\n\n                while(bestkey == NULL) {\n                    evictionPoolPopulate(dict, db->dict, db->eviction_pool);\n                    /* Go backward from best to worst element to evict. */\n                    for (k = MAXMEMORY_EVICTION_POOL_SIZE-1; k >= 0; k--) {\n                        if (pool[k].key == NULL) continue;\n                        de = dictFind(dict,pool[k].key);\n\n                        /* Remove the entry from the pool. */\n                        sdsfree(pool[k].key);\n                        /* Shift all elements on its right to left. */\n                        memmove(pool+k,pool+k+1,\n                            sizeof(pool[0])*(MAXMEMORY_EVICTION_POOL_SIZE-k-1));\n                        /* Clear the element on the right which is empty\n                         * since we shifted one position to the left.  */\n                        pool[MAXMEMORY_EVICTION_POOL_SIZE-1].key = NULL;\n                        pool[MAXMEMORY_EVICTION_POOL_SIZE-1].idle = 0;\n\n                        /* If the key exists, is our pick. Otherwise it is\n                         * a ghost and we need to try the next element. */\n                        if (de) {\n                            bestkey = dictGetKey(de);\n                            break;\n                        } else {\n                            /* Ghost... */\n                            continue;\n                        }\n                    }\n                }\n            }\n\n            /* volatile-ttl */\n            else if (server.maxmemory_policy == MAXMEMORY_VOLATILE_TTL) {\n                for (k = 0; k < server.maxmemory_samples; k++) {\n                    sds thiskey;\n                    long thisval;\n\n                    de = dictGetRandomKey(dict);\n                    thiskey = dictGetKey(de);\n                    thisval = (long) dictGetVal(de);\n\n                    /* Expire sooner (minor expire unix timestamp) is better\n                     * candidate for deletion */\n                    if (bestkey == NULL || thisval < bestval) {\n                        bestkey = thiskey;\n                        bestval = thisval;\n                    }\n                }\n            }\n\n            /* Finally remove the selected key. */\n            if (bestkey) {\n                long long delta;\n\n                robj *keyobj = createStringObject(bestkey,sdslen(bestkey));\n                propagateExpire(db,keyobj);\n                /* We compute the amount of memory freed by dbDelete() alone.\n                 * It is possible that actually the memory needed to propagate\n                 * the DEL in AOF and replication link is greater than the one\n                 * we are freeing removing the key, but we can't account for\n                 * that otherwise we would never exit the loop.\n                 *\n                 * AOF and Output buffer memory will be freed eventually so\n                 * we only care about memory used by the key space. */\n                delta = (long long) zmalloc_used_memory();\n                latencyStartMonitor(eviction_latency);\n                dbDelete(db,keyobj);\n                latencyEndMonitor(eviction_latency);\n                latencyAddSampleIfNeeded(\"eviction-del\",eviction_latency);\n                latencyRemoveNestedEvent(latency,eviction_latency);\n                delta -= (long long) zmalloc_used_memory();\n                mem_freed += delta;\n                server.stat_evictedkeys++;\n                notifyKeyspaceEvent(NOTIFY_EVICTED, \"evicted\",\n                    keyobj, db->id);\n                decrRefCount(keyobj);\n                keys_freed++;\n\n                /* When the memory to free starts to be big enough, we may\n                 * start spending so much time here that is impossible to\n                 * deliver data to the slaves fast enough, so we force the\n                 * transmission here inside the loop. */\n                if (slaves) flushSlavesOutputBuffers();\n            }\n        }\n        if (!keys_freed) {\n            latencyEndMonitor(latency);\n            latencyAddSampleIfNeeded(\"eviction-cycle\",latency);\n            return C_ERR; /* nothing to free... */\n        }\n    }\n    latencyEndMonitor(latency);\n    latencyAddSampleIfNeeded(\"eviction-cycle\",latency);\n    return C_OK;\n}\n\n/* =================================== Main! ================================ */\n\n#ifdef __linux__\nint linuxOvercommitMemoryValue(void) {\n    FILE *fp = fopen(\"/proc/sys/vm/overcommit_memory\",\"r\");\n    char buf[64];\n\n    if (!fp) return -1;\n    if (fgets(buf,64,fp) == NULL) {\n        fclose(fp);\n        return -1;\n    }\n    fclose(fp);\n\n    return atoi(buf);\n}\n\nvoid linuxMemoryWarnings(void) {\n    if (linuxOvercommitMemoryValue() == 0) {\n        serverLog(LL_WARNING,\"WARNING overcommit_memory is set to 0! Background save may fail under low memory condition. To fix this issue add 'vm.overcommit_memory = 1' to /etc/sysctl.conf and then reboot or run the command 'sysctl vm.overcommit_memory=1' for this to take effect.\");\n    }\n    if (THPIsEnabled()) {\n        serverLog(LL_WARNING,\"WARNING you have Transparent Huge Pages (THP) support enabled in your kernel. This will create latency and memory usage issues with Redis. To fix this issue run the command 'echo never > /sys/kernel/mm/transparent_hugepage/enabled' as root, and add it to your /etc/rc.local in order to retain the setting after a reboot. Redis must be restarted after THP is disabled.\");\n    }\n}\n#endif /* __linux__ */\n\nvoid createPidFile(void) {\n    /* If pidfile requested, but no pidfile defined, use\n     * default pidfile path */\n    if (!server.pidfile) server.pidfile = zstrdup(CONFIG_DEFAULT_PID_FILE);\n\n    /* Try to write the pid file in a best-effort way. */\n    FILE *fp = fopen(server.pidfile,\"w\");\n    if (fp) {\n        fprintf(fp,\"%d\\n\",(int)getpid());\n        fclose(fp);\n    }\n}\n\nvoid daemonize(void) {\n    int fd;\n\n    if (fork() != 0) exit(0); /* parent exits */\n    setsid(); /* create a new session */\n\n    /* Every output goes to /dev/null. If Redis is daemonized but\n     * the 'logfile' is set to 'stdout' in the configuration file\n     * it will not log at all. */\n    if ((fd = open(\"/dev/null\", O_RDWR, 0)) != -1) {\n        dup2(fd, STDIN_FILENO);\n        dup2(fd, STDOUT_FILENO);\n        dup2(fd, STDERR_FILENO);\n        if (fd > STDERR_FILENO) close(fd);\n    }\n}\n\nvoid version(void) {\n    printf(\"Redis server v=%s sha=%s:%d malloc=%s bits=%d build=%llx\\n\",\n        REDIS_VERSION,\n        redisGitSHA1(),\n        atoi(redisGitDirty()) > 0,\n        ZMALLOC_LIB,\n        sizeof(long) == 4 ? 32 : 64,\n        (unsigned long long) redisBuildId());\n    exit(0);\n}\n\nvoid usage(void) {\n    fprintf(stderr,\"Usage: ./redis-server [/path/to/redis.conf] [options]\\n\");\n    fprintf(stderr,\"       ./redis-server - (read config from stdin)\\n\");\n    fprintf(stderr,\"       ./redis-server -v or --version\\n\");\n    fprintf(stderr,\"       ./redis-server -h or --help\\n\");\n    fprintf(stderr,\"       ./redis-server --test-memory <megabytes>\\n\\n\");\n    fprintf(stderr,\"Examples:\\n\");\n    fprintf(stderr,\"       ./redis-server (run the server with default conf)\\n\");\n    fprintf(stderr,\"       ./redis-server /etc/redis/6379.conf\\n\");\n    fprintf(stderr,\"       ./redis-server --port 7777\\n\");\n    fprintf(stderr,\"       ./redis-server --port 7777 --slaveof 127.0.0.1 8888\\n\");\n    fprintf(stderr,\"       ./redis-server /etc/myredis.conf --loglevel verbose\\n\\n\");\n    fprintf(stderr,\"Sentinel mode:\\n\");\n    fprintf(stderr,\"       ./redis-server /etc/sentinel.conf --sentinel\\n\");\n    exit(1);\n}\n\nvoid redisAsciiArt(void) {\n#include \"asciilogo.h\"\n    char *buf = zmalloc(1024*16);\n    char *mode;\n\n    if (server.cluster_enabled) mode = \"cluster\";\n    else if (server.sentinel_mode) mode = \"sentinel\";\n    else mode = \"standalone\";\n\n    if (server.syslog_enabled) {\n        serverLog(LL_NOTICE,\n            \"Redis %s (%s/%d) %s bit, %s mode, port %d, pid %ld ready to start.\",\n            REDIS_VERSION,\n            redisGitSHA1(),\n            strtol(redisGitDirty(),NULL,10) > 0,\n            (sizeof(long) == 8) ? \"64\" : \"32\",\n            mode, server.port,\n            (long) getpid()\n        );\n    } else {\n        snprintf(buf,1024*16,ascii_logo,\n            REDIS_VERSION,\n            redisGitSHA1(),\n            strtol(redisGitDirty(),NULL,10) > 0,\n            (sizeof(long) == 8) ? \"64\" : \"32\",\n            mode, server.port,\n            (long) getpid()\n        );\n        serverLogRaw(LL_NOTICE|LL_RAW,buf);\n    }\n    zfree(buf);\n}\n\nstatic void sigShutdownHandler(int sig) {\n    char *msg;\n\n    switch (sig) {\n    case SIGINT:\n        msg = \"Received SIGINT scheduling shutdown...\";\n        break;\n    case SIGTERM:\n        msg = \"Received SIGTERM scheduling shutdown...\";\n        break;\n    default:\n        msg = \"Received shutdown signal, scheduling shutdown...\";\n    };\n\n    /* SIGINT is often delivered via Ctrl+C in an interactive session.\n     * If we receive the signal the second time, we interpret this as\n     * the user really wanting to quit ASAP without waiting to persist\n     * on disk. */\n    if (server.shutdown_asap && sig == SIGINT) {\n        serverLogFromHandler(LL_WARNING, \"You insist... exiting now.\");\n        rdbRemoveTempFile(getpid());\n        exit(1); /* Exit with an error since this was not a clean shutdown. */\n    } else if (server.loading) {\n        exit(0);\n    }\n\n    serverLogFromHandler(LL_WARNING, msg);\n    server.shutdown_asap = 1;\n}\n\nvoid setupSignalHandlers(void) {\n    struct sigaction act;\n\n    /* When the SA_SIGINFO flag is set in sa_flags then sa_sigaction is used.\n     * Otherwise, sa_handler is used. */\n    sigemptyset(&act.sa_mask);\n    act.sa_flags = 0;\n    act.sa_handler = sigShutdownHandler;\n    sigaction(SIGTERM, &act, NULL);\n    sigaction(SIGINT, &act, NULL);\n\n#ifdef HAVE_BACKTRACE\n    sigemptyset(&act.sa_mask);\n    act.sa_flags = SA_NODEFER | SA_RESETHAND | SA_SIGINFO;\n    act.sa_sigaction = sigsegvHandler;\n    sigaction(SIGSEGV, &act, NULL);\n    sigaction(SIGBUS, &act, NULL);\n    sigaction(SIGFPE, &act, NULL);\n    sigaction(SIGILL, &act, NULL);\n#endif\n    return;\n}\n\nvoid memtest(size_t megabytes, int passes);\n\n/* Returns 1 if there is --sentinel among the arguments or if\n * argv[0] is exactly \"redis-sentinel\". */\nint checkForSentinelMode(int argc, char **argv) {\n    int j;\n\n    if (strstr(argv[0],\"redis-sentinel\") != NULL) return 1;\n    for (j = 1; j < argc; j++)\n        if (!strcmp(argv[j],\"--sentinel\")) return 1;\n    return 0;\n}\n\n/* Function called at startup to load RDB or AOF file in memory. */\nvoid loadDataFromDisk(void) {\n    long long start = ustime();\n    if (server.aof_state == AOF_ON) {\n        if (loadAppendOnlyFile(server.aof_filename) == C_OK)\n            serverLog(LL_NOTICE,\"DB loaded from append only file: %.3f seconds\",(float)(ustime()-start)/1000000);\n    } else {\n        if (rdbLoad(server.rdb_filename) == C_OK) {\n            serverLog(LL_NOTICE,\"DB loaded from disk: %.3f seconds\",\n                (float)(ustime()-start)/1000000);\n        } else if (errno != ENOENT) {\n            serverLog(LL_WARNING,\"Fatal error loading the DB: %s. Exiting.\",strerror(errno));\n            exit(1);\n        }\n    }\n}\n\nvoid redisOutOfMemoryHandler(size_t allocation_size) {\n    serverLog(LL_WARNING,\"Out Of Memory allocating %zu bytes!\",\n        allocation_size);\n    serverPanic(\"Redis aborting for OUT OF MEMORY\");\n}\n\nvoid redisSetProcTitle(char *title) {\n#ifdef USE_SETPROCTITLE\n    char *server_mode = \"\";\n    if (server.cluster_enabled) server_mode = \" [cluster]\";\n    else if (server.sentinel_mode) server_mode = \" [sentinel]\";\n\n    setproctitle(\"%s %s:%d%s\",\n        title,\n        server.bindaddr_count ? server.bindaddr[0] : \"*\",\n        server.port,\n        server_mode);\n#else\n    UNUSED(title);\n#endif\n}\n\n/*\n * Check whether systemd or upstart have been used to start redis.\n */\n\nint redisSupervisedUpstart(void) {\n    const char *upstart_job = getenv(\"UPSTART_JOB\");\n\n    if (!upstart_job) {\n        serverLog(LL_WARNING,\n                \"upstart supervision requested, but UPSTART_JOB not found\");\n        return 0;\n    }\n\n    serverLog(LL_NOTICE, \"supervised by upstart, will stop to signal readiness\");\n    raise(SIGSTOP);\n    unsetenv(\"UPSTART_JOB\");\n    return 1;\n}\n\nint redisSupervisedSystemd(void) {\n    const char *notify_socket = getenv(\"NOTIFY_SOCKET\");\n    int fd = 1;\n    struct sockaddr_un su;\n    struct iovec iov;\n    struct msghdr hdr;\n    int sendto_flags = 0;\n\n    if (!notify_socket) {\n        serverLog(LL_WARNING,\n                \"systemd supervision requested, but NOTIFY_SOCKET not found\");\n        return 0;\n    }\n\n    if ((strchr(\"@/\", notify_socket[0])) == NULL || strlen(notify_socket) < 2) {\n        return 0;\n    }\n\n    serverLog(LL_NOTICE, \"supervised by systemd, will signal readiness\");\n    if ((fd = socket(AF_UNIX, SOCK_DGRAM, 0)) == -1) {\n        serverLog(LL_WARNING,\n                \"Can't connect to systemd socket %s\", notify_socket);\n        return 0;\n    }\n\n    memset(&su, 0, sizeof(su));\n    su.sun_family = AF_UNIX;\n    strncpy (su.sun_path, notify_socket, sizeof(su.sun_path) -1);\n    su.sun_path[sizeof(su.sun_path) - 1] = '\\0';\n\n    if (notify_socket[0] == '@')\n        su.sun_path[0] = '\\0';\n\n    memset(&iov, 0, sizeof(iov));\n    iov.iov_base = \"READY=1\";\n    iov.iov_len = strlen(\"READY=1\");\n\n    memset(&hdr, 0, sizeof(hdr));\n    hdr.msg_name = &su;\n    hdr.msg_namelen = offsetof(struct sockaddr_un, sun_path) +\n        strlen(notify_socket);\n    hdr.msg_iov = &iov;\n    hdr.msg_iovlen = 1;\n\n    unsetenv(\"NOTIFY_SOCKET\");\n#ifdef HAVE_MSG_NOSIGNAL\n    sendto_flags |= MSG_NOSIGNAL;\n#endif\n    if (sendmsg(fd, &hdr, sendto_flags) < 0) {\n        serverLog(LL_WARNING, \"Can't send notification to systemd\");\n        close(fd);\n        return 0;\n    }\n    close(fd);\n    return 1;\n}\n\nint redisIsSupervised(int mode) {\n    if (mode == SUPERVISED_AUTODETECT) {\n        const char *upstart_job = getenv(\"UPSTART_JOB\");\n        const char *notify_socket = getenv(\"NOTIFY_SOCKET\");\n\n        if (upstart_job) {\n            redisSupervisedUpstart();\n        } else if (notify_socket) {\n            redisSupervisedSystemd();\n        }\n    } else if (mode == SUPERVISED_UPSTART) {\n        return redisSupervisedUpstart();\n    } else if (mode == SUPERVISED_SYSTEMD) {\n        return redisSupervisedSystemd();\n    }\n\n    return 0;\n}\n\n\nint main(int argc, char **argv) {\n    struct timeval tv;\n    int j;\n\n#ifdef REDIS_TEST\n    if (argc == 3 && !strcasecmp(argv[1], \"test\")) {\n        if (!strcasecmp(argv[2], \"ziplist\")) {\n            return ziplistTest(argc, argv);\n        } else if (!strcasecmp(argv[2], \"quicklist\")) {\n            quicklistTest(argc, argv);\n        } else if (!strcasecmp(argv[2], \"intset\")) {\n            return intsetTest(argc, argv);\n        } else if (!strcasecmp(argv[2], \"zipmap\")) {\n            return zipmapTest(argc, argv);\n        } else if (!strcasecmp(argv[2], \"sha1test\")) {\n            return sha1Test(argc, argv);\n        } else if (!strcasecmp(argv[2], \"util\")) {\n            return utilTest(argc, argv);\n        } else if (!strcasecmp(argv[2], \"sds\")) {\n            return sdsTest(argc, argv);\n        } else if (!strcasecmp(argv[2], \"endianconv\")) {\n            return endianconvTest(argc, argv);\n        } else if (!strcasecmp(argv[2], \"crc64\")) {\n            return crc64Test(argc, argv);\n        }\n\n        return -1; /* test not found */\n    }\n#endif\n\n    /* We need to initialize our libraries, and the server configuration. */\n#ifdef INIT_SETPROCTITLE_REPLACEMENT\n    spt_init(argc, argv);\n#endif\n    setlocale(LC_COLLATE,\"\");\n    zmalloc_enable_thread_safeness();\n    zmalloc_set_oom_handler(redisOutOfMemoryHandler);\n    srand(time(NULL)^getpid());\n    gettimeofday(&tv,NULL);\n    dictSetHashFunctionSeed(tv.tv_sec^tv.tv_usec^getpid());\n    server.sentinel_mode = checkForSentinelMode(argc,argv);\n    initServerConfig();\n\n    /* Store the executable path and arguments in a safe place in order\n     * to be able to restart the server later. */\n    server.executable = getAbsolutePath(argv[0]);\n    server.exec_argv = zmalloc(sizeof(char*)*(argc+1));\n    server.exec_argv[argc] = NULL;\n    for (j = 0; j < argc; j++) server.exec_argv[j] = zstrdup(argv[j]);\n\n    /* We need to init sentinel right now as parsing the configuration file\n     * in sentinel mode will have the effect of populating the sentinel\n     * data structures with master nodes to monitor. */\n    if (server.sentinel_mode) {\n        initSentinelConfig();\n        initSentinel();\n    }\n\n    /* Check if we need to start in redis-check-rdb mode. We just execute\n     * the program main. However the program is part of the Redis executable\n     * so that we can easily execute an RDB check on loading errors. */\n    if (strstr(argv[0],\"redis-check-rdb\") != NULL)\n        redis_check_rdb_main(argc,argv);\n\n    if (argc >= 2) {\n        j = 1; /* First option to parse in argv[] */\n        sds options = sdsempty();\n        char *configfile = NULL;\n\n        /* Handle special options --help and --version */\n        if (strcmp(argv[1], \"-v\") == 0 ||\n            strcmp(argv[1], \"--version\") == 0) version();\n        if (strcmp(argv[1], \"--help\") == 0 ||\n            strcmp(argv[1], \"-h\") == 0) usage();\n        if (strcmp(argv[1], \"--test-memory\") == 0) {\n            if (argc == 3) {\n                memtest(atoi(argv[2]),50);\n                exit(0);\n            } else {\n                fprintf(stderr,\"Please specify the amount of memory to test in megabytes.\\n\");\n                fprintf(stderr,\"Example: ./redis-server --test-memory 4096\\n\\n\");\n                exit(1);\n            }\n        }\n\n        /* First argument is the config file name? */\n        if (argv[j][0] != '-' || argv[j][1] != '-') {\n            configfile = argv[j];\n            server.configfile = getAbsolutePath(configfile);\n            /* Replace the config file in server.exec_argv with\n             * its absoulte path. */\n            zfree(server.exec_argv[j]);\n            server.exec_argv[j] = zstrdup(server.configfile);\n            j++;\n        }\n\n        /* All the other options are parsed and conceptually appended to the\n         * configuration file. For instance --port 6380 will generate the\n         * string \"port 6380\\n\" to be parsed after the actual file name\n         * is parsed, if any. */\n        while(j != argc) {\n            if (argv[j][0] == '-' && argv[j][1] == '-') {\n                /* Option name */\n                if (!strcmp(argv[j], \"--check-rdb\")) {\n                    /* Argument has no options, need to skip for parsing. */\n                    j++;\n                    continue;\n                }\n                if (sdslen(options)) options = sdscat(options,\"\\n\");\n                options = sdscat(options,argv[j]+2);\n                options = sdscat(options,\" \");\n            } else {\n                /* Option argument */\n                options = sdscatrepr(options,argv[j],strlen(argv[j]));\n                options = sdscat(options,\" \");\n            }\n            j++;\n        }\n        if (server.sentinel_mode && configfile && *configfile == '-') {\n            serverLog(LL_WARNING,\n                \"Sentinel config from STDIN not allowed.\");\n            serverLog(LL_WARNING,\n                \"Sentinel needs config file on disk to save state.  Exiting...\");\n            exit(1);\n        }\n        resetServerSaveParams();\n        loadServerConfig(configfile,options);\n        sdsfree(options);\n    } else {\n        serverLog(LL_WARNING, \"Warning: no config file specified, using the default config. In order to specify a config file use %s /path/to/%s.conf\", argv[0], server.sentinel_mode ? \"sentinel\" : \"redis\");\n    }\n\n    server.supervised = redisIsSupervised(server.supervised_mode);\n    int background = server.daemonize && !server.supervised;\n    if (background) daemonize();\n\n    initServer();\n    if (background || server.pidfile) createPidFile();\n    redisSetProcTitle(argv[0]);\n    redisAsciiArt();\n    checkTcpBacklogSettings();\n\n    if (!server.sentinel_mode) {\n        /* Things not needed when running in Sentinel mode. */\n        serverLog(LL_WARNING,\"Server started, Redis version \" REDIS_VERSION);\n    #ifdef __linux__\n        linuxMemoryWarnings();\n    #endif\n        loadDataFromDisk();\n        if (server.cluster_enabled) {\n            if (verifyClusterConfigWithData() == C_ERR) {\n                serverLog(LL_WARNING,\n                    \"You can't have keys in a DB different than DB 0 when in \"\n                    \"Cluster mode. Exiting.\");\n                exit(1);\n            }\n        }\n        if (server.ipfd_count > 0)\n            serverLog(LL_NOTICE,\"The server is now ready to accept connections on port %d\", server.port);\n        if (server.sofd > 0)\n            serverLog(LL_NOTICE,\"The server is now ready to accept connections at %s\", server.unixsocket);\n    } else {\n        sentinelIsRunning();\n    }\n\n    /* Warning the user about suspicious maxmemory setting. */\n    if (server.maxmemory > 0 && server.maxmemory < 1024*1024) {\n        serverLog(LL_WARNING,\"WARNING: You specified a maxmemory value that is less than 1MB (current value is %llu bytes). Are you sure this is what you really want?\", server.maxmemory);\n    }\n\n    aeSetBeforeSleepProc(server.el,beforeSleep);\n    aeMain(server.el);\n    aeDeleteEventLoop(server.el);\n    return 0;\n}\n\n/* The End */\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/src/server.h",
    "content": "/*\n * Copyright (c) 2009-2012, Salvatore Sanfilippo <antirez at gmail dot com>\n * All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions are met:\n *\n *   * Redistributions of source code must retain the above copyright notice,\n *     this list of conditions and the following disclaimer.\n *   * Redistributions in binary form must reproduce the above copyright\n *     notice, this list of conditions and the following disclaimer in the\n *     documentation and/or other materials provided with the distribution.\n *   * Neither the name of Redis nor the names of its contributors may be used\n *     to endorse or promote products derived from this software without\n *     specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\"\n * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\n * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE\n * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR\n * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF\n * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS\n * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN\n * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)\n * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE\n * POSSIBILITY OF SUCH DAMAGE.\n */\n\n#ifndef __REDIS_H\n#define __REDIS_H\n\n#include \"fmacros.h\"\n#include \"config.h\"\n#include \"solarisfixes.h\"\n\n#include <stdio.h>\n#include <stdlib.h>\n#include <string.h>\n#include <time.h>\n#include <limits.h>\n#include <unistd.h>\n#include <errno.h>\n#include <inttypes.h>\n#include <pthread.h>\n#include <syslog.h>\n#include <netinet/in.h>\n#include <lua.h>\n#include <signal.h>\n\ntypedef long long mstime_t; /* millisecond time type. */\n\n#include \"ae.h\"      /* Event driven programming library */\n#include \"sds.h\"     /* Dynamic safe strings */\n#include \"dict.h\"    /* Hash tables */\n#include \"adlist.h\"  /* Linked lists */\n#include \"zmalloc.h\" /* total memory usage aware version of malloc/free */\n#include \"anet.h\"    /* Networking the easy way */\n#include \"ziplist.h\" /* Compact list data structure */\n#include \"intset.h\"  /* Compact integer set structure */\n#include \"version.h\" /* Version macro */\n#include \"util.h\"    /* Misc functions useful in many places */\n#include \"latency.h\" /* Latency monitor API */\n#include \"sparkline.h\" /* ASCII graphs API */\n#include \"quicklist.h\"\n\n/* Following includes allow test functions to be called from Redis main() */\n#include \"zipmap.h\"\n#include \"sha1.h\"\n#include \"endianconv.h\"\n#include \"crc64.h\"\n\n/* Error codes */\n#define C_OK                    0\n#define C_ERR                   -1\n\n/* Static server configuration */\n#define CONFIG_DEFAULT_HZ        10      /* Time interrupt calls/sec. */\n#define CONFIG_MIN_HZ            1\n#define CONFIG_MAX_HZ            500\n#define CONFIG_DEFAULT_SERVER_PORT        6379    /* TCP port */\n#define CONFIG_DEFAULT_TCP_BACKLOG       511     /* TCP listen backlog */\n#define CONFIG_DEFAULT_CLIENT_TIMEOUT       0       /* default client timeout: infinite */\n#define CONFIG_DEFAULT_DBNUM     16\n#define CONFIG_MAX_LINE    1024\n#define CRON_DBS_PER_CALL 16\n#define NET_MAX_WRITES_PER_EVENT (1024*64)\n#define PROTO_SHARED_SELECT_CMDS 10\n#define OBJ_SHARED_INTEGERS 10000\n#define OBJ_SHARED_BULKHDR_LEN 32\n#define LOG_MAX_LEN    1024 /* Default maximum length of syslog messages */\n#define AOF_REWRITE_PERC  100\n#define AOF_REWRITE_MIN_SIZE (64*1024*1024)\n#define AOF_REWRITE_ITEMS_PER_CMD 64\n#define CONFIG_DEFAULT_SLOWLOG_LOG_SLOWER_THAN 10000\n#define CONFIG_DEFAULT_SLOWLOG_MAX_LEN 128\n#define CONFIG_DEFAULT_MAX_CLIENTS 10000\n#define CONFIG_AUTHPASS_MAX_LEN 512\n#define CONFIG_DEFAULT_SLAVE_PRIORITY 100\n#define CONFIG_DEFAULT_REPL_TIMEOUT 60\n#define CONFIG_DEFAULT_REPL_PING_SLAVE_PERIOD 10\n#define CONFIG_RUN_ID_SIZE 40\n#define RDB_EOF_MARK_SIZE 40\n#define CONFIG_DEFAULT_REPL_BACKLOG_SIZE (1024*1024)    /* 1mb */\n#define CONFIG_DEFAULT_REPL_BACKLOG_TIME_LIMIT (60*60)  /* 1 hour */\n#define CONFIG_REPL_BACKLOG_MIN_SIZE (1024*16)          /* 16k */\n#define CONFIG_BGSAVE_RETRY_DELAY 5 /* Wait a few secs before trying again. */\n#define CONFIG_DEFAULT_PID_FILE \"/var/run/redis.pid\"\n#define CONFIG_DEFAULT_SYSLOG_IDENT \"redis\"\n#define CONFIG_DEFAULT_CLUSTER_CONFIG_FILE \"nodes.conf\"\n#define CONFIG_DEFAULT_DAEMONIZE 0\n#define CONFIG_DEFAULT_UNIX_SOCKET_PERM 0\n#define CONFIG_DEFAULT_TCP_KEEPALIVE 300\n#define CONFIG_DEFAULT_PROTECTED_MODE 1\n#define CONFIG_DEFAULT_LOGFILE \"\"\n#define CONFIG_DEFAULT_SYSLOG_ENABLED 0\n#define CONFIG_DEFAULT_STOP_WRITES_ON_BGSAVE_ERROR 1\n#define CONFIG_DEFAULT_RDB_COMPRESSION 1\n#define CONFIG_DEFAULT_RDB_CHECKSUM 1\n#define CONFIG_DEFAULT_RDB_FILENAME \"dump.rdb\"\n#define CONFIG_DEFAULT_REPL_DISKLESS_SYNC 0\n#define CONFIG_DEFAULT_REPL_DISKLESS_SYNC_DELAY 5\n#define CONFIG_DEFAULT_SLAVE_SERVE_STALE_DATA 1\n#define CONFIG_DEFAULT_SLAVE_READ_ONLY 1\n#define CONFIG_DEFAULT_SLAVE_ANNOUNCE_IP NULL\n#define CONFIG_DEFAULT_SLAVE_ANNOUNCE_PORT 0\n#define CONFIG_DEFAULT_REPL_DISABLE_TCP_NODELAY 0\n#define CONFIG_DEFAULT_MAXMEMORY 0\n#define CONFIG_DEFAULT_MAXMEMORY_SAMPLES 5\n#define CONFIG_DEFAULT_AOF_FILENAME \"appendonly.aof\"\n#define CONFIG_DEFAULT_AOF_NO_FSYNC_ON_REWRITE 0\n#define CONFIG_DEFAULT_AOF_LOAD_TRUNCATED 1\n#define CONFIG_DEFAULT_ACTIVE_REHASHING 1\n#define CONFIG_DEFAULT_AOF_REWRITE_INCREMENTAL_FSYNC 1\n#define CONFIG_DEFAULT_MIN_SLAVES_TO_WRITE 0\n#define CONFIG_DEFAULT_MIN_SLAVES_MAX_LAG 10\n#define NET_IP_STR_LEN 46 /* INET6_ADDRSTRLEN is 46, but we need to be sure */\n#define NET_PEER_ID_LEN (NET_IP_STR_LEN+32) /* Must be enough for ip:port */\n#define CONFIG_BINDADDR_MAX 16\n#define CONFIG_MIN_RESERVED_FDS 32\n#define CONFIG_DEFAULT_LATENCY_MONITOR_THRESHOLD 0\n\n#define ACTIVE_EXPIRE_CYCLE_LOOKUPS_PER_LOOP 20 /* Loopkups per loop. */\n#define ACTIVE_EXPIRE_CYCLE_FAST_DURATION 1000 /* Microseconds */\n#define ACTIVE_EXPIRE_CYCLE_SLOW_TIME_PERC 25 /* CPU max % for keys collection */\n#define ACTIVE_EXPIRE_CYCLE_SLOW 0\n#define ACTIVE_EXPIRE_CYCLE_FAST 1\n\n/* Instantaneous metrics tracking. */\n#define STATS_METRIC_SAMPLES 16     /* Number of samples per metric. */\n#define STATS_METRIC_COMMAND 0      /* Number of commands executed. */\n#define STATS_METRIC_NET_INPUT 1    /* Bytes read to network .*/\n#define STATS_METRIC_NET_OUTPUT 2   /* Bytes written to network. */\n#define STATS_METRIC_COUNT 3\n\n/* Protocol and I/O related defines */\n#define PROTO_MAX_QUERYBUF_LEN  (1024*1024*1024) /* 1GB max query buffer. */\n#define PROTO_IOBUF_LEN         (1024*16)  /* Generic I/O buffer size */\n#define PROTO_REPLY_CHUNK_BYTES (16*1024) /* 16k output buffer */\n#define PROTO_INLINE_MAX_SIZE   (1024*64) /* Max size of inline reads */\n#define PROTO_MBULK_BIG_ARG     (1024*32)\n#define LONG_STR_SIZE      21          /* Bytes needed for long -> str + '\\0' */\n#define AOF_AUTOSYNC_BYTES (1024*1024*32) /* fdatasync every 32MB */\n\n/* When configuring the server eventloop, we setup it so that the total number\n * of file descriptors we can handle are server.maxclients + RESERVED_FDS +\n * a few more to stay safe. Since RESERVED_FDS defaults to 32, we add 96\n * in order to make sure of not over provisioning more than 128 fds. */\n#define CONFIG_FDSET_INCR (CONFIG_MIN_RESERVED_FDS+96)\n\n/* Hash table parameters */\n#define HASHTABLE_MIN_FILL        10      /* Minimal hash table fill 10% */\n\n/* Command flags. Please check the command table defined in the redis.c file\n * for more information about the meaning of every flag. */\n#define CMD_WRITE 1                   /* \"w\" flag */\n#define CMD_READONLY 2                /* \"r\" flag */\n#define CMD_DENYOOM 4                 /* \"m\" flag */\n#define CMD_NOT_USED_1 8              /* no longer used flag */\n#define CMD_ADMIN 16                  /* \"a\" flag */\n#define CMD_PUBSUB 32                 /* \"p\" flag */\n#define CMD_NOSCRIPT  64              /* \"s\" flag */\n#define CMD_RANDOM 128                /* \"R\" flag */\n#define CMD_SORT_FOR_SCRIPT 256       /* \"S\" flag */\n#define CMD_LOADING 512               /* \"l\" flag */\n#define CMD_STALE 1024                /* \"t\" flag */\n#define CMD_SKIP_MONITOR 2048         /* \"M\" flag */\n#define CMD_ASKING 4096               /* \"k\" flag */\n#define CMD_FAST 8192                 /* \"F\" flag */\n\n/* Object types */\n#define OBJ_STRING 0\n#define OBJ_LIST 1\n#define OBJ_SET 2\n#define OBJ_ZSET 3\n#define OBJ_HASH 4\n\n/* Objects encoding. Some kind of objects like Strings and Hashes can be\n * internally represented in multiple ways. The 'encoding' field of the object\n * is set to one of this fields for this object. */\n#define OBJ_ENCODING_RAW 0     /* Raw representation */\n#define OBJ_ENCODING_INT 1     /* Encoded as integer */\n#define OBJ_ENCODING_HT 2      /* Encoded as hash table */\n#define OBJ_ENCODING_ZIPMAP 3  /* Encoded as zipmap */\n#define OBJ_ENCODING_LINKEDLIST 4 /* Encoded as regular linked list */\n#define OBJ_ENCODING_ZIPLIST 5 /* Encoded as ziplist */\n#define OBJ_ENCODING_INTSET 6  /* Encoded as intset */\n#define OBJ_ENCODING_SKIPLIST 7  /* Encoded as skiplist */\n#define OBJ_ENCODING_EMBSTR 8  /* Embedded sds string encoding */\n#define OBJ_ENCODING_QUICKLIST 9 /* Encoded as linked list of ziplists */\n\n/* Defines related to the dump file format. To store 32 bits lengths for short\n * keys requires a lot of space, so we check the most significant 2 bits of\n * the first byte to interpreter the length:\n *\n * 00|000000 => if the two MSB are 00 the len is the 6 bits of this byte\n * 01|000000 00000000 =>  01, the len is 14 byes, 6 bits + 8 bits of next byte\n * 10|000000 [32 bit integer] => if it's 10, a full 32 bit len will follow\n * 11|000000 this means: specially encoded object will follow. The six bits\n *           number specify the kind of object that follows.\n *           See the RDB_ENC_* defines.\n *\n * Lengths up to 63 are stored using a single byte, most DB keys, and may\n * values, will fit inside. */\n#define RDB_6BITLEN 0\n#define RDB_14BITLEN 1\n#define RDB_32BITLEN 2\n#define RDB_ENCVAL 3\n#define RDB_LENERR UINT_MAX\n\n/* When a length of a string object stored on disk has the first two bits\n * set, the remaining two bits specify a special encoding for the object\n * accordingly to the following defines: */\n#define RDB_ENC_INT8 0        /* 8 bit signed integer */\n#define RDB_ENC_INT16 1       /* 16 bit signed integer */\n#define RDB_ENC_INT32 2       /* 32 bit signed integer */\n#define RDB_ENC_LZF 3         /* string compressed with FASTLZ */\n\n/* AOF states */\n#define AOF_OFF 0             /* AOF is off */\n#define AOF_ON 1              /* AOF is on */\n#define AOF_WAIT_REWRITE 2    /* AOF waits rewrite to start appending */\n\n/* Client flags */\n#define CLIENT_SLAVE (1<<0)   /* This client is a slave server */\n#define CLIENT_MASTER (1<<1)  /* This client is a master server */\n#define CLIENT_MONITOR (1<<2) /* This client is a slave monitor, see MONITOR */\n#define CLIENT_MULTI (1<<3)   /* This client is in a MULTI context */\n#define CLIENT_BLOCKED (1<<4) /* The client is waiting in a blocking operation */\n#define CLIENT_DIRTY_CAS (1<<5) /* Watched keys modified. EXEC will fail. */\n#define CLIENT_CLOSE_AFTER_REPLY (1<<6) /* Close after writing entire reply. */\n#define CLIENT_UNBLOCKED (1<<7) /* This client was unblocked and is stored in\n                                  server.unblocked_clients */\n#define CLIENT_LUA (1<<8) /* This is a non connected client used by Lua */\n#define CLIENT_ASKING (1<<9)     /* Client issued the ASKING command */\n#define CLIENT_CLOSE_ASAP (1<<10)/* Close this client ASAP */\n#define CLIENT_UNIX_SOCKET (1<<11) /* Client connected via Unix domain socket */\n#define CLIENT_DIRTY_EXEC (1<<12)  /* EXEC will fail for errors while queueing */\n#define CLIENT_MASTER_FORCE_REPLY (1<<13)  /* Queue replies even if is master */\n#define CLIENT_FORCE_AOF (1<<14)   /* Force AOF propagation of current cmd. */\n#define CLIENT_FORCE_REPL (1<<15)  /* Force replication of current cmd. */\n#define CLIENT_PRE_PSYNC (1<<16)   /* Instance don't understand PSYNC. */\n#define CLIENT_READONLY (1<<17)    /* Cluster client is in read-only state. */\n#define CLIENT_PUBSUB (1<<18)      /* Client is in Pub/Sub mode. */\n#define CLIENT_PREVENT_AOF_PROP (1<<19)  /* Don't propagate to AOF. */\n#define CLIENT_PREVENT_REPL_PROP (1<<20)  /* Don't propagate to slaves. */\n#define CLIENT_PREVENT_PROP (CLIENT_PREVENT_AOF_PROP|CLIENT_PREVENT_REPL_PROP)\n#define CLIENT_PENDING_WRITE (1<<21) /* Client has output to send but a write\n                                        handler is yet not installed. */\n#define CLIENT_REPLY_OFF (1<<22)   /* Don't send replies to client. */\n#define CLIENT_REPLY_SKIP_NEXT (1<<23)  /* Set CLIENT_REPLY_SKIP for next cmd */\n#define CLIENT_REPLY_SKIP (1<<24)  /* Don't send just this reply. */\n#define CLIENT_LUA_DEBUG (1<<25)  /* Run EVAL in debug mode. */\n#define CLIENT_LUA_DEBUG_SYNC (1<<26)  /* EVAL debugging without fork() */\n\n/* Client block type (btype field in client structure)\n * if CLIENT_BLOCKED flag is set. */\n#define BLOCKED_NONE 0    /* Not blocked, no CLIENT_BLOCKED flag set. */\n#define BLOCKED_LIST 1    /* BLPOP & co. */\n#define BLOCKED_WAIT 2    /* WAIT for synchronous replication. */\n\n/* Client request types */\n#define PROTO_REQ_INLINE 1\n#define PROTO_REQ_MULTIBULK 2\n\n/* Client classes for client limits, currently used only for\n * the max-client-output-buffer limit implementation. */\n#define CLIENT_TYPE_NORMAL 0 /* Normal req-reply clients + MONITORs */\n#define CLIENT_TYPE_SLAVE 1  /* Slaves. */\n#define CLIENT_TYPE_PUBSUB 2 /* Clients subscribed to PubSub channels. */\n#define CLIENT_TYPE_MASTER 3 /* Master. */\n#define CLIENT_TYPE_OBUF_COUNT 3 /* Number of clients to expose to output\n                                    buffer configuration. Just the first\n                                    three: normal, slave, pubsub. */\n\n/* Slave replication state. Used in server.repl_state for slaves to remember\n * what to do next. */\n#define REPL_STATE_NONE 0 /* No active replication */\n#define REPL_STATE_CONNECT 1 /* Must connect to master */\n#define REPL_STATE_CONNECTING 2 /* Connecting to master */\n/* --- Handshake states, must be ordered --- */\n#define REPL_STATE_RECEIVE_PONG 3 /* Wait for PING reply */\n#define REPL_STATE_SEND_AUTH 4 /* Send AUTH to master */\n#define REPL_STATE_RECEIVE_AUTH 5 /* Wait for AUTH reply */\n#define REPL_STATE_SEND_PORT 6 /* Send REPLCONF listening-port */\n#define REPL_STATE_RECEIVE_PORT 7 /* Wait for REPLCONF reply */\n#define REPL_STATE_SEND_IP 8 /* Send REPLCONF ip-address */\n#define REPL_STATE_RECEIVE_IP 9 /* Wait for REPLCONF reply */\n#define REPL_STATE_SEND_CAPA 10 /* Send REPLCONF capa */\n#define REPL_STATE_RECEIVE_CAPA 11 /* Wait for REPLCONF reply */\n#define REPL_STATE_SEND_PSYNC 12 /* Send PSYNC */\n#define REPL_STATE_RECEIVE_PSYNC 13 /* Wait for PSYNC reply */\n/* --- End of handshake states --- */\n#define REPL_STATE_TRANSFER 14 /* Receiving .rdb from master */\n#define REPL_STATE_CONNECTED 15 /* Connected to master */\n\n/* State of slaves from the POV of the master. Used in client->replstate.\n * In SEND_BULK and ONLINE state the slave receives new updates\n * in its output queue. In the WAIT_BGSAVE states instead the server is waiting\n * to start the next background saving in order to send updates to it. */\n#define SLAVE_STATE_WAIT_BGSAVE_START 6 /* We need to produce a new RDB file. */\n#define SLAVE_STATE_WAIT_BGSAVE_END 7 /* Waiting RDB file creation to finish. */\n#define SLAVE_STATE_SEND_BULK 8 /* Sending RDB file to slave. */\n#define SLAVE_STATE_ONLINE 9 /* RDB file transmitted, sending just updates. */\n\n/* Slave capabilities. */\n#define SLAVE_CAPA_NONE 0\n#define SLAVE_CAPA_EOF (1<<0)   /* Can parse the RDB EOF streaming format. */\n\n/* Synchronous read timeout - slave side */\n#define CONFIG_REPL_SYNCIO_TIMEOUT 5\n\n/* List related stuff */\n#define LIST_HEAD 0\n#define LIST_TAIL 1\n\n/* Sort operations */\n#define SORT_OP_GET 0\n\n/* Log levels */\n#define LL_DEBUG 0\n#define LL_VERBOSE 1\n#define LL_NOTICE 2\n#define LL_WARNING 3\n#define LL_RAW (1<<10) /* Modifier to log without timestamp */\n#define CONFIG_DEFAULT_VERBOSITY LL_NOTICE\n\n/* Supervision options */\n#define SUPERVISED_NONE 0\n#define SUPERVISED_AUTODETECT 1\n#define SUPERVISED_SYSTEMD 2\n#define SUPERVISED_UPSTART 3\n\n/* Anti-warning macro... */\n#define UNUSED(V) ((void) V)\n\n#define ZSKIPLIST_MAXLEVEL 32 /* Should be enough for 2^32 elements */\n#define ZSKIPLIST_P 0.25      /* Skiplist P = 1/4 */\n\n/* Append only defines */\n#define AOF_FSYNC_NO 0\n#define AOF_FSYNC_ALWAYS 1\n#define AOF_FSYNC_EVERYSEC 2\n#define CONFIG_DEFAULT_AOF_FSYNC AOF_FSYNC_EVERYSEC\n\n/* Zip structure related defaults */\n#define OBJ_HASH_MAX_ZIPLIST_ENTRIES 512\n#define OBJ_HASH_MAX_ZIPLIST_VALUE 64\n#define OBJ_SET_MAX_INTSET_ENTRIES 512\n#define OBJ_ZSET_MAX_ZIPLIST_ENTRIES 128\n#define OBJ_ZSET_MAX_ZIPLIST_VALUE 64\n\n/* List defaults */\n#define OBJ_LIST_MAX_ZIPLIST_SIZE -2\n#define OBJ_LIST_COMPRESS_DEPTH 0\n\n/* HyperLogLog defines */\n#define CONFIG_DEFAULT_HLL_SPARSE_MAX_BYTES 3000\n\n/* Sets operations codes */\n#define SET_OP_UNION 0\n#define SET_OP_DIFF 1\n#define SET_OP_INTER 2\n\n/* Redis maxmemory strategies */\n#define MAXMEMORY_VOLATILE_LRU 0\n#define MAXMEMORY_VOLATILE_TTL 1\n#define MAXMEMORY_VOLATILE_RANDOM 2\n#define MAXMEMORY_ALLKEYS_LRU 3\n#define MAXMEMORY_ALLKEYS_RANDOM 4\n#define MAXMEMORY_NO_EVICTION 5\n#define CONFIG_DEFAULT_MAXMEMORY_POLICY MAXMEMORY_NO_EVICTION\n\n/* Scripting */\n#define LUA_SCRIPT_TIME_LIMIT 5000 /* milliseconds */\n\n/* Units */\n#define UNIT_SECONDS 0\n#define UNIT_MILLISECONDS 1\n\n/* SHUTDOWN flags */\n#define SHUTDOWN_NOFLAGS 0      /* No flags. */\n#define SHUTDOWN_SAVE 1         /* Force SAVE on SHUTDOWN even if no save\n                                   points are configured. */\n#define SHUTDOWN_NOSAVE 2       /* Don't SAVE on SHUTDOWN. */\n\n/* Command call flags, see call() function */\n#define CMD_CALL_NONE 0\n#define CMD_CALL_SLOWLOG (1<<0)\n#define CMD_CALL_STATS (1<<1)\n#define CMD_CALL_PROPAGATE_AOF (1<<2)\n#define CMD_CALL_PROPAGATE_REPL (1<<3)\n#define CMD_CALL_PROPAGATE (CMD_CALL_PROPAGATE_AOF|CMD_CALL_PROPAGATE_REPL)\n#define CMD_CALL_FULL (CMD_CALL_SLOWLOG | CMD_CALL_STATS | CMD_CALL_PROPAGATE)\n\n/* Command propagation flags, see propagate() function */\n#define PROPAGATE_NONE 0\n#define PROPAGATE_AOF 1\n#define PROPAGATE_REPL 2\n\n/* RDB active child save type. */\n#define RDB_CHILD_TYPE_NONE 0\n#define RDB_CHILD_TYPE_DISK 1     /* RDB is written to disk. */\n#define RDB_CHILD_TYPE_SOCKET 2   /* RDB is written to slave socket. */\n\n/* Keyspace changes notification classes. Every class is associated with a\n * character for configuration purposes. */\n#define NOTIFY_KEYSPACE (1<<0)    /* K */\n#define NOTIFY_KEYEVENT (1<<1)    /* E */\n#define NOTIFY_GENERIC (1<<2)     /* g */\n#define NOTIFY_STRING (1<<3)      /* $ */\n#define NOTIFY_LIST (1<<4)        /* l */\n#define NOTIFY_SET (1<<5)         /* s */\n#define NOTIFY_HASH (1<<6)        /* h */\n#define NOTIFY_ZSET (1<<7)        /* z */\n#define NOTIFY_EXPIRED (1<<8)     /* x */\n#define NOTIFY_EVICTED (1<<9)     /* e */\n#define NOTIFY_ALL (NOTIFY_GENERIC | NOTIFY_STRING | NOTIFY_LIST | NOTIFY_SET | NOTIFY_HASH | NOTIFY_ZSET | NOTIFY_EXPIRED | NOTIFY_EVICTED)      /* A */\n\n/* Get the first bind addr or NULL */\n#define NET_FIRST_BIND_ADDR (server.bindaddr_count ? server.bindaddr[0] : NULL)\n\n/* Using the following macro you can run code inside serverCron() with the\n * specified period, specified in milliseconds.\n * The actual resolution depends on server.hz. */\n#define run_with_period(_ms_) if ((_ms_ <= 1000/server.hz) || !(server.cronloops%((_ms_)/(1000/server.hz))))\n\n/* We can print the stacktrace, so our assert is defined this way: */\n#define serverAssertWithInfo(_c,_o,_e) ((_e)?(void)0 : (_serverAssertWithInfo(_c,_o,#_e,__FILE__,__LINE__),_exit(1)))\n#define serverAssert(_e) ((_e)?(void)0 : (_serverAssert(#_e,__FILE__,__LINE__),_exit(1)))\n#define serverPanic(_e) _serverPanic(#_e,__FILE__,__LINE__),_exit(1)\n\n/*-----------------------------------------------------------------------------\n * Data types\n *----------------------------------------------------------------------------*/\n\n/* A redis object, that is a type able to hold a string / list / set */\n\n/* The actual Redis Object */\n#define LRU_BITS 24\n#define LRU_CLOCK_MAX ((1<<LRU_BITS)-1) /* Max value of obj->lru */\n#define LRU_CLOCK_RESOLUTION 1000 /* LRU clock resolution in ms */\ntypedef struct redisObject {\n    unsigned type:4;\n    unsigned encoding:4;\n    unsigned lru:LRU_BITS; /* lru time (relative to server.lruclock) */\n    int refcount;\n    void *ptr;\n} robj;\n\n/* Macro used to obtain the current LRU clock.\n * If the current resolution is lower than the frequency we refresh the\n * LRU clock (as it should be in production servers) we return the\n * precomputed value, otherwise we need to resort to a system call. */\n#define LRU_CLOCK() ((1000/server.hz <= LRU_CLOCK_RESOLUTION) ? server.lruclock : getLRUClock())\n\n/* Macro used to initialize a Redis object allocated on the stack.\n * Note that this macro is taken near the structure definition to make sure\n * we'll update it when the structure is changed, to avoid bugs like\n * bug #85 introduced exactly in this way. */\n#define initStaticStringObject(_var,_ptr) do { \\\n    _var.refcount = 1; \\\n    _var.type = OBJ_STRING; \\\n    _var.encoding = OBJ_ENCODING_RAW; \\\n    _var.ptr = _ptr; \\\n} while(0)\n\n/* To improve the quality of the LRU approximation we take a set of keys\n * that are good candidate for eviction across freeMemoryIfNeeded() calls.\n *\n * Entries inside the eviciton pool are taken ordered by idle time, putting\n * greater idle times to the right (ascending order).\n *\n * Empty entries have the key pointer set to NULL. */\n#define MAXMEMORY_EVICTION_POOL_SIZE 16\nstruct evictionPoolEntry {\n    unsigned long long idle;    /* Object idle time. */\n    sds key;                    /* Key name. */\n};\n\nvoid crc32_init();\nuint32_t crc32_checksum(const char *buf, int len);\n\nlong long timeInMilliseconds(void);\n\n#define HASH_SLOTS_MASK 0x000003ff\n#define HASH_SLOTS_SIZE (HASH_SLOTS_MASK + 1)\n\nstruct zskiplist;\n\n/* Redis database representation. There are multiple databases identified\n * by integers from 0 (the default database) up to the max configured\n * database. The database number is the 'id' field in the structure. */\ntypedef struct redisDb {\n    dict *dict;                 /* The keyspace for this DB */\n    dict *expires;              /* Timeout of keys with a timeout set */\n    dict *blocking_keys;        /* Keys with clients waiting for data (BLPOP) */\n    dict *ready_keys;           /* Blocked keys that received a PUSH */\n    dict *watched_keys;         /* WATCHED keys for MULTI/EXEC CAS */\n    dict *hash_slots[HASH_SLOTS_SIZE];\n    struct zskiplist *tagged_keys;\n    struct evictionPoolEntry *eviction_pool;    /* Eviction pool of keys */\n    int id;                     /* Database ID */\n    long long avg_ttl;          /* Average TTL, just for stats */\n} redisDb;\n\n/* Client MULTI/EXEC state */\ntypedef struct multiCmd {\n    robj **argv;\n    int argc;\n    struct redisCommand *cmd;\n} multiCmd;\n\ntypedef struct multiState {\n    multiCmd *commands;     /* Array of MULTI commands */\n    int count;              /* Total number of MULTI commands */\n    int minreplicas;        /* MINREPLICAS for synchronous replication */\n    time_t minreplicas_timeout; /* MINREPLICAS timeout as unixtime. */\n} multiState;\n\n/* This structure holds the blocking operation state for a client.\n * The fields used depend on client->btype. */\ntypedef struct blockingState {\n    /* Generic fields. */\n    mstime_t timeout;       /* Blocking operation timeout. If UNIX current time\n                             * is > timeout then the operation timed out. */\n\n    /* BLOCKED_LIST */\n    dict *keys;             /* The keys we are waiting to terminate a blocking\n                             * operation such as BLPOP. Otherwise NULL. */\n    robj *target;           /* The key that should receive the element,\n                             * for BRPOPLPUSH. */\n\n    /* BLOCKED_WAIT */\n    int numreplicas;        /* Number of replicas we are waiting for ACK. */\n    long long reploffset;   /* Replication offset to reach. */\n} blockingState;\n\n/* The following structure represents a node in the server.ready_keys list,\n * where we accumulate all the keys that had clients blocked with a blocking\n * operation such as B[LR]POP, but received new data in the context of the\n * last executed command.\n *\n * After the execution of every command or script, we run this list to check\n * if as a result we should serve data to clients blocked, unblocking them.\n * Note that server.ready_keys will not have duplicates as there dictionary\n * also called ready_keys in every structure representing a Redis database,\n * where we make sure to remember if a given key was already added in the\n * server.ready_keys list. */\ntypedef struct readyList {\n    redisDb *db;\n    robj *key;\n} readyList;\n\n/* With multiplexing we need to take per-client state.\n * Clients are taken in a linked list. */\ntypedef struct client {\n    uint64_t id;            /* Client incremental unique ID. */\n    int fd;                 /* Client socket. */\n    redisDb *db;            /* Pointer to currently SELECTed DB. */\n    int dictid;             /* ID of the currently SELECTed DB. */\n    robj *name;             /* As set by CLIENT SETNAME. */\n    sds querybuf;           /* Buffer we use to accumulate client queries. */\n    size_t querybuf_peak;   /* Recent (100ms or more) peak of querybuf size. */\n    int argc;               /* Num of arguments of current command. */\n    robj **argv;            /* Arguments of current command. */\n    struct redisCommand *cmd, *lastcmd;  /* Last command executed. */\n    int reqtype;            /* Request protocol type: PROTO_REQ_* */\n    int multibulklen;       /* Number of multi bulk arguments left to read. */\n    long bulklen;           /* Length of bulk argument in multi bulk request. */\n    list *reply;            /* List of reply objects to send to the client. */\n    unsigned long long reply_bytes; /* Tot bytes of objects in reply list. */\n    size_t sentlen;         /* Amount of bytes already sent in the current\n                               buffer or object being sent. */\n    time_t ctime;           /* Client creation time. */\n    time_t lastinteraction; /* Time of the last interaction, used for timeout */\n    time_t obuf_soft_limit_reached_time;\n    int flags;              /* Client flags: CLIENT_* macros. */\n    int authenticated;      /* When requirepass is non-NULL. */\n    int replstate;          /* Replication state if this is a slave. */\n    int repl_put_online_on_ack; /* Install slave write handler on ACK. */\n    int repldbfd;           /* Replication DB file descriptor. */\n    off_t repldboff;        /* Replication DB file offset. */\n    off_t repldbsize;       /* Replication DB file size. */\n    sds replpreamble;       /* Replication DB preamble. */\n    long long reploff;      /* Replication offset if this is our master. */\n    long long repl_ack_off; /* Replication ack offset, if this is a slave. */\n    long long repl_ack_time;/* Replication ack time, if this is a slave. */\n    long long psync_initial_offset; /* FULLRESYNC reply offset other slaves\n                                       copying this slave output buffer\n                                       should use. */\n    char replrunid[CONFIG_RUN_ID_SIZE+1]; /* Master run id if is a master. */\n    int slave_listening_port; /* As configured with: REPLCONF listening-port */\n    char slave_ip[NET_IP_STR_LEN]; /* Optionally given by REPLCONF ip-address */\n    int slave_capa;         /* Slave capabilities: SLAVE_CAPA_* bitwise OR. */\n    multiState mstate;      /* MULTI/EXEC state */\n    int btype;              /* Type of blocking op if CLIENT_BLOCKED. */\n    blockingState bpop;     /* blocking state */\n    long long woff;         /* Last write global replication offset. */\n    list *watched_keys;     /* Keys WATCHED for MULTI/EXEC CAS */\n    dict *pubsub_channels;  /* channels a client is interested in (SUBSCRIBE) */\n    list *pubsub_patterns;  /* patterns a client is interested in (SUBSCRIBE) */\n    sds peerid;             /* Cached peer ID. */\n\n    /* Response buffer */\n    int bufpos;\n    char buf[PROTO_REPLY_CHUNK_BYTES];\n} client;\n\nstruct saveparam {\n    time_t seconds;\n    int changes;\n};\n\nstruct sharedObjectsStruct {\n    robj *crlf, *ok, *err, *emptybulk, *czero, *cone, *cnegone, *pong, *space,\n    *colon, *nullbulk, *nullmultibulk, *queued,\n    *emptymultibulk, *wrongtypeerr, *nokeyerr, *syntaxerr, *sameobjecterr,\n    *outofrangeerr, *noscripterr, *loadingerr, *slowscripterr, *bgsaveerr,\n    *masterdownerr, *roslaveerr, *execaborterr, *noautherr, *noreplicaserr,\n    *busykeyerr, *oomerr, *plus, *messagebulk, *pmessagebulk, *subscribebulk,\n    *unsubscribebulk, *psubscribebulk, *punsubscribebulk, *del, *rpop, *lpop,\n    *lpush, *emptyscan, *minstring, *maxstring,\n    *select[PROTO_SHARED_SELECT_CMDS],\n    *integers[OBJ_SHARED_INTEGERS],\n    *mbulkhdr[OBJ_SHARED_BULKHDR_LEN], /* \"*<value>\\r\\n\" */\n    *bulkhdr[OBJ_SHARED_BULKHDR_LEN];  /* \"$<value>\\r\\n\" */\n};\n\n/* ZSETs use a specialized version of Skiplists */\ntypedef struct zskiplistNode {\n    robj *obj;\n    double score;\n    struct zskiplistNode *backward;\n    struct zskiplistLevel {\n        struct zskiplistNode *forward;\n        unsigned int span;\n    } level[];\n} zskiplistNode;\n\ntypedef struct zskiplist {\n    struct zskiplistNode *header, *tail;\n    unsigned long length;\n    int level;\n} zskiplist;\n\ntypedef struct zset {\n    dict *dict;\n    zskiplist *zsl;\n} zset;\n\ntypedef struct clientBufferLimitsConfig {\n    unsigned long long hard_limit_bytes;\n    unsigned long long soft_limit_bytes;\n    time_t soft_limit_seconds;\n} clientBufferLimitsConfig;\n\nextern clientBufferLimitsConfig clientBufferLimitsDefaults[CLIENT_TYPE_OBUF_COUNT];\n\n/* The redisOp structure defines a Redis Operation, that is an instance of\n * a command with an argument vector, database ID, propagation target\n * (PROPAGATE_*), and command pointer.\n *\n * Currently only used to additionally propagate more commands to AOF/Replication\n * after the propagation of the executed command. */\ntypedef struct redisOp {\n    robj **argv;\n    int argc, dbid, target;\n    struct redisCommand *cmd;\n} redisOp;\n\n/* Defines an array of Redis operations. There is an API to add to this\n * structure in a easy way.\n *\n * redisOpArrayInit();\n * redisOpArrayAppend();\n * redisOpArrayFree();\n */\ntypedef struct redisOpArray {\n    redisOp *ops;\n    int numops;\n} redisOpArray;\n\n/*-----------------------------------------------------------------------------\n * Global server state\n *----------------------------------------------------------------------------*/\n\nstruct clusterState;\n\n/* AIX defines hz to __hz, we don't use this define and in order to allow\n * Redis build on AIX we need to undef it. */\n#ifdef _AIX\n#undef hz\n#endif\n\nstruct redisServer {\n    /* General */\n    pid_t pid;                  /* Main process pid. */\n    char *configfile;           /* Absolute config file path, or NULL */\n    char *executable;           /* Absolute executable file path. */\n    char **exec_argv;           /* Executable argv vector (copy). */\n    int hz;                     /* serverCron() calls frequency in hertz */\n    redisDb *db;\n    dict *commands;             /* Command table */\n    dict *orig_commands;        /* Command table before command renaming. */\n    aeEventLoop *el;\n    unsigned lruclock:LRU_BITS; /* Clock for LRU eviction */\n    int shutdown_asap;          /* SHUTDOWN needed ASAP */\n    int activerehashing;        /* Incremental rehash in serverCron() */\n    char *requirepass;          /* Pass for AUTH command, or NULL */\n    char *pidfile;              /* PID file path */\n    int arch_bits;              /* 32 or 64 depending on sizeof(long) */\n    int cronloops;              /* Number of times the cron function run */\n    char runid[CONFIG_RUN_ID_SIZE+1];  /* ID always different at every exec. */\n    int sentinel_mode;          /* True if this instance is a Sentinel. */\n    /* Networking */\n    int port;                   /* TCP listening port */\n    int tcp_backlog;            /* TCP listen() backlog */\n    char *bindaddr[CONFIG_BINDADDR_MAX]; /* Addresses we should bind to */\n    int bindaddr_count;         /* Number of addresses in server.bindaddr[] */\n    char *unixsocket;           /* UNIX socket path */\n    mode_t unixsocketperm;      /* UNIX socket permission */\n    int ipfd[CONFIG_BINDADDR_MAX]; /* TCP socket file descriptors */\n    int ipfd_count;             /* Used slots in ipfd[] */\n    int sofd;                   /* Unix socket file descriptor */\n    int cfd[CONFIG_BINDADDR_MAX];/* Cluster bus listening socket */\n    int cfd_count;              /* Used slots in cfd[] */\n    list *clients;              /* List of active clients */\n    list *clients_to_close;     /* Clients to close asynchronously */\n    list *clients_pending_write; /* There is to write or install handler. */\n    list *slaves, *monitors;    /* List of slaves and MONITORs */\n    client *current_client; /* Current client, only used on crash report */\n    int clients_paused;         /* True if clients are currently paused */\n    mstime_t clients_pause_end_time; /* Time when we undo clients_paused */\n    char neterr[ANET_ERR_LEN];   /* Error buffer for anet.c */\n    dict *slotsmgrt_cached_sockfds;\n    dict *migrate_cached_sockets;/* MIGRATE cached sockets */\n    uint64_t next_client_id;    /* Next client unique ID. Incremental. */\n    int protected_mode;         /* Don't accept external connections. */\n    /* RDB / AOF loading information */\n    int loading;                /* We are loading data from disk if true */\n    off_t loading_total_bytes;\n    off_t loading_loaded_bytes;\n    time_t loading_start_time;\n    off_t loading_process_events_interval_bytes;\n    /* Fast pointers to often looked up command */\n    struct redisCommand *delCommand, *multiCommand, *lpushCommand, *lpopCommand,\n                        *rpopCommand, *sremCommand, *execCommand;\n    /* Fields used only for stats */\n    time_t stat_starttime;          /* Server start time */\n    long long stat_numcommands;     /* Number of processed commands */\n    long long stat_numconnections;  /* Number of connections received */\n    long long stat_expiredkeys;     /* Number of expired keys */\n    long long stat_evictedkeys;     /* Number of evicted keys (maxmemory) */\n    long long stat_keyspace_hits;   /* Number of successful lookups of keys */\n    long long stat_keyspace_misses; /* Number of failed lookups of keys */\n    size_t stat_peak_memory;        /* Max used memory record */\n    long long stat_fork_time;       /* Time needed to perform latest fork() */\n    double stat_fork_rate;          /* Fork rate in GB/sec. */\n    long long stat_rejected_conn;   /* Clients rejected because of maxclients */\n    long long stat_sync_full;       /* Number of full resyncs with slaves. */\n    long long stat_sync_partial_ok; /* Number of accepted PSYNC requests. */\n    long long stat_sync_partial_err;/* Number of unaccepted PSYNC requests. */\n    list *slowlog;                  /* SLOWLOG list of commands */\n    long long slowlog_entry_id;     /* SLOWLOG current entry ID */\n    long long slowlog_log_slower_than; /* SLOWLOG time limit (to get logged) */\n    unsigned long slowlog_max_len;     /* SLOWLOG max number of items logged */\n    size_t resident_set_size;       /* RSS sampled in serverCron(). */\n    long long stat_net_input_bytes; /* Bytes read from network. */\n    long long stat_net_output_bytes; /* Bytes written to network. */\n    /* The following two are used to track instantaneous metrics, like\n     * number of operations per second, network traffic. */\n    struct {\n        long long last_sample_time; /* Timestamp of last sample in ms */\n        long long last_sample_count;/* Count in last sample */\n        long long samples[STATS_METRIC_SAMPLES];\n        int idx;\n    } inst_metric[STATS_METRIC_COUNT];\n    /* Configuration */\n    int verbosity;                  /* Loglevel in redis.conf */\n    int maxidletime;                /* Client timeout in seconds */\n    int tcpkeepalive;               /* Set SO_KEEPALIVE if non-zero. */\n    int active_expire_enabled;      /* Can be disabled for testing purposes. */\n    size_t client_max_querybuf_len; /* Limit for client query buffer length */\n    int dbnum;                      /* Total number of configured DBs */\n    int supervised;                 /* 1 if supervised, 0 otherwise. */\n    int supervised_mode;            /* See SUPERVISED_* */\n    int daemonize;                  /* True if running as a daemon */\n    clientBufferLimitsConfig client_obuf_limits[CLIENT_TYPE_OBUF_COUNT];\n    /* AOF persistence */\n    int aof_state;                  /* AOF_(ON|OFF|WAIT_REWRITE) */\n    int aof_fsync;                  /* Kind of fsync() policy */\n    char *aof_filename;             /* Name of the AOF file */\n    int aof_no_fsync_on_rewrite;    /* Don't fsync if a rewrite is in prog. */\n    int aof_rewrite_perc;           /* Rewrite AOF if % growth is > M and... */\n    off_t aof_rewrite_min_size;     /* the AOF file is at least N bytes. */\n    off_t aof_rewrite_base_size;    /* AOF size on latest startup or rewrite. */\n    off_t aof_current_size;         /* AOF current size. */\n    int aof_rewrite_scheduled;      /* Rewrite once BGSAVE terminates. */\n    pid_t aof_child_pid;            /* PID if rewriting process */\n    list *aof_rewrite_buf_blocks;   /* Hold changes during an AOF rewrite. */\n    sds aof_buf;      /* AOF buffer, written before entering the event loop */\n    int aof_fd;       /* File descriptor of currently selected AOF file */\n    int aof_selected_db; /* Currently selected DB in AOF */\n    time_t aof_flush_postponed_start; /* UNIX time of postponed AOF flush */\n    time_t aof_last_fsync;            /* UNIX time of last fsync() */\n    time_t aof_rewrite_time_last;   /* Time used by last AOF rewrite run. */\n    time_t aof_rewrite_time_start;  /* Current AOF rewrite start time. */\n    int aof_lastbgrewrite_status;   /* C_OK or C_ERR */\n    unsigned long aof_delayed_fsync;  /* delayed AOF fsync() counter */\n    int aof_rewrite_incremental_fsync;/* fsync incrementally while rewriting? */\n    int aof_last_write_status;      /* C_OK or C_ERR */\n    int aof_last_write_errno;       /* Valid if aof_last_write_status is ERR */\n    int aof_load_truncated;         /* Don't stop on unexpected AOF EOF. */\n    /* AOF pipes used to communicate between parent and child during rewrite. */\n    int aof_pipe_write_data_to_child;\n    int aof_pipe_read_data_from_parent;\n    int aof_pipe_write_ack_to_parent;\n    int aof_pipe_read_ack_from_child;\n    int aof_pipe_write_ack_to_child;\n    int aof_pipe_read_ack_from_parent;\n    int aof_stop_sending_diff;     /* If true stop sending accumulated diffs\n                                      to child process. */\n    sds aof_child_diff;             /* AOF diff accumulator child side. */\n    /* RDB persistence */\n    long long dirty;                /* Changes to DB from the last save */\n    long long dirty_before_bgsave;  /* Used to restore dirty on failed BGSAVE */\n    pid_t rdb_child_pid;            /* PID of RDB saving child */\n    struct saveparam *saveparams;   /* Save points array for RDB */\n    int saveparamslen;              /* Number of saving points */\n    char *rdb_filename;             /* Name of RDB file */\n    int rdb_compression;            /* Use compression in RDB? */\n    int rdb_checksum;               /* Use RDB checksum? */\n    time_t lastsave;                /* Unix time of last successful save */\n    time_t lastbgsave_try;          /* Unix time of last attempted bgsave */\n    time_t rdb_save_time_last;      /* Time used by last RDB save run. */\n    time_t rdb_save_time_start;     /* Current RDB save start time. */\n    int rdb_bgsave_scheduled;       /* BGSAVE when possible if true. */\n    int rdb_child_type;             /* Type of save by active child. */\n    int lastbgsave_status;          /* C_OK or C_ERR */\n    int stop_writes_on_bgsave_err;  /* Don't allow writes if can't BGSAVE */\n    int rdb_pipe_write_result_to_parent; /* RDB pipes used to return the state */\n    int rdb_pipe_read_result_from_child; /* of each slave in diskless SYNC. */\n    /* Propagation of commands in AOF / replication */\n    redisOpArray also_propagate;    /* Additional command to propagate. */\n    /* Logging */\n    char *logfile;                  /* Path of log file */\n    int syslog_enabled;             /* Is syslog enabled? */\n    char *syslog_ident;             /* Syslog ident */\n    int syslog_facility;            /* Syslog facility */\n    /* Replication (master) */\n    int slaveseldb;                 /* Last SELECTed DB in replication output */\n    long long master_repl_offset;   /* Global replication offset */\n    int repl_ping_slave_period;     /* Master pings the slave every N seconds */\n    char *repl_backlog;             /* Replication backlog for partial syncs */\n    long long repl_backlog_size;    /* Backlog circular buffer size */\n    long long repl_backlog_histlen; /* Backlog actual data length */\n    long long repl_backlog_idx;     /* Backlog circular buffer current offset */\n    long long repl_backlog_off;     /* Replication offset of first byte in the\n                                       backlog buffer. */\n    time_t repl_backlog_time_limit; /* Time without slaves after the backlog\n                                       gets released. */\n    time_t repl_no_slaves_since;    /* We have no slaves since that time.\n                                       Only valid if server.slaves len is 0. */\n    int repl_min_slaves_to_write;   /* Min number of slaves to write. */\n    int repl_min_slaves_max_lag;    /* Max lag of <count> slaves to write. */\n    int repl_good_slaves_count;     /* Number of slaves with lag <= max_lag. */\n    int repl_diskless_sync;         /* Send RDB to slaves sockets directly. */\n    int repl_diskless_sync_delay;   /* Delay to start a diskless repl BGSAVE. */\n    /* Replication (slave) */\n    char *masterauth;               /* AUTH with this password with master */\n    char *masterhost;               /* Hostname of master */\n    int masterport;                 /* Port of master */\n    int repl_timeout;               /* Timeout after N seconds of master idle */\n    client *master;     /* Client that is master for this slave */\n    client *cached_master; /* Cached master to be reused for PSYNC. */\n    int repl_syncio_timeout; /* Timeout for synchronous I/O calls */\n    int repl_state;          /* Replication status if the instance is a slave */\n    off_t repl_transfer_size; /* Size of RDB to read from master during sync. */\n    off_t repl_transfer_read; /* Amount of RDB read from master during sync. */\n    off_t repl_transfer_last_fsync_off; /* Offset when we fsync-ed last time. */\n    int repl_transfer_s;     /* Slave -> Master SYNC socket */\n    int repl_transfer_fd;    /* Slave -> Master SYNC temp file descriptor */\n    char *repl_transfer_tmpfile; /* Slave-> master SYNC temp file name */\n    time_t repl_transfer_lastio; /* Unix time of the latest read, for timeout */\n    int repl_serve_stale_data; /* Serve stale data when link is down? */\n    int repl_slave_ro;          /* Slave is read only? */\n    time_t repl_down_since; /* Unix time at which link with master went down */\n    int repl_disable_tcp_nodelay;   /* Disable TCP_NODELAY after SYNC? */\n    int slave_priority;             /* Reported in INFO and used by Sentinel. */\n    int slave_announce_port;        /* Give the master this listening port. */\n    char *slave_announce_ip;        /* Give the master this ip address. */\n    char repl_master_runid[CONFIG_RUN_ID_SIZE+1];  /* Master run id for PSYNC.*/\n    long long repl_master_initial_offset;         /* Master PSYNC offset. */\n    /* Replication script cache. */\n    dict *repl_scriptcache_dict;        /* SHA1 all slaves are aware of. */\n    list *repl_scriptcache_fifo;        /* First in, first out LRU eviction. */\n    unsigned int repl_scriptcache_size; /* Max number of elements. */\n    /* Synchronous replication. */\n    list *clients_waiting_acks;         /* Clients waiting in WAIT command. */\n    int get_ack_from_slaves;            /* If true we send REPLCONF GETACK. */\n    /* Limits */\n    unsigned int maxclients;            /* Max number of simultaneous clients */\n    unsigned long long maxmemory;   /* Max number of memory bytes to use */\n    int maxmemory_policy;           /* Policy for key eviction */\n    int maxmemory_samples;          /* Pricision of random sampling */\n    /* Blocked clients */\n    unsigned int bpop_blocked_clients; /* Number of clients blocked by lists */\n    list *unblocked_clients; /* list of clients to unblock before next loop */\n    list *ready_keys;        /* List of readyList structures for BLPOP & co */\n    /* Sort parameters - qsort_r() is only available under BSD so we\n     * have to take this state global, in order to pass it to sortCompare() */\n    int sort_desc;\n    int sort_alpha;\n    int sort_bypattern;\n    int sort_store;\n    /* Zip structure config, see redis.conf for more information  */\n    size_t hash_max_ziplist_entries;\n    size_t hash_max_ziplist_value;\n    size_t set_max_intset_entries;\n    size_t zset_max_ziplist_entries;\n    size_t zset_max_ziplist_value;\n    size_t hll_sparse_max_bytes;\n    /* List parameters */\n    int list_max_ziplist_size;\n    int list_compress_depth;\n    /* time cache */\n    time_t unixtime;        /* Unix time sampled every cron cycle. */\n    long long mstime;       /* Like 'unixtime' but with milliseconds resolution. */\n    /* Pubsub */\n    dict *pubsub_channels;  /* Map channels to list of subscribed clients */\n    list *pubsub_patterns;  /* A list of pubsub_patterns */\n    int notify_keyspace_events; /* Events to propagate via Pub/Sub. This is an\n                                   xor of NOTIFY_... flags. */\n    /* Cluster */\n    int cluster_enabled;      /* Is cluster enabled? */\n    mstime_t cluster_node_timeout; /* Cluster node timeout. */\n    char *cluster_configfile; /* Cluster auto-generated config file name. */\n    struct clusterState *cluster;  /* State of the cluster */\n    int cluster_migration_barrier; /* Cluster replicas migration barrier. */\n    int cluster_slave_validity_factor; /* Slave max data age for failover. */\n    int cluster_require_full_coverage; /* If true, put the cluster down if\n                                          there is at least an uncovered slot.*/\n    /* Scripting */\n    lua_State *lua; /* The Lua interpreter. We use just one for all clients */\n    client *lua_client;   /* The \"fake client\" to query Redis from Lua */\n    client *lua_caller;   /* The client running EVAL right now, or NULL */\n    dict *lua_scripts;         /* A dictionary of SHA1 -> Lua scripts */\n    mstime_t lua_time_limit;  /* Script timeout in milliseconds */\n    mstime_t lua_time_start;  /* Start time of script, milliseconds time */\n    int lua_write_dirty;  /* True if a write command was called during the\n                             execution of the current script. */\n    int lua_random_dirty; /* True if a random command was called during the\n                             execution of the current script. */\n    int lua_replicate_commands; /* True if we are doing single commands repl. */\n    int lua_multi_emitted;/* True if we already proagated MULTI. */\n    int lua_repl;         /* Script replication flags for redis.set_repl(). */\n    int lua_timedout;     /* True if we reached the time limit for script\n                             execution. */\n    int lua_kill;         /* Kill the script if true. */\n    int lua_always_replicate_commands; /* Default replication type. */\n    /* Latency monitor */\n    long long latency_monitor_threshold;\n    dict *latency_events;\n    /* Assert & bug reporting */\n    char *assert_failed;\n    char *assert_file;\n    int assert_line;\n    int bug_report_start; /* True if bug report header was already logged. */\n    int watchdog_period;  /* Software watchdog period in ms. 0 = off */\n    /* System hardware info */\n    size_t system_memory_size;  /* Total memory in system as reported by OS */\n};\n\ntypedef struct pubsubPattern {\n    client *client;\n    robj *pattern;\n} pubsubPattern;\n\ntypedef void redisCommandProc(client *c);\ntypedef int *redisGetKeysProc(struct redisCommand *cmd, robj **argv, int argc, int *numkeys);\nstruct redisCommand {\n    char *name;\n    redisCommandProc *proc;\n    int arity;\n    char *sflags; /* Flags as string representation, one char per flag. */\n    int flags;    /* The actual flags, obtained from the 'sflags' field. */\n    /* Use a function to determine keys arguments in a command line.\n     * Used for Redis Cluster redirect. */\n    redisGetKeysProc *getkeys_proc;\n    /* What keys should be loaded in background when calling this command? */\n    int firstkey; /* The first argument that's a key (0 = no keys) */\n    int lastkey;  /* The last argument that's a key */\n    int keystep;  /* The step between first and last key */\n    long long microseconds, calls;\n};\n\nstruct redisFunctionSym {\n    char *name;\n    unsigned long pointer;\n};\n\ntypedef struct _redisSortObject {\n    robj *obj;\n    union {\n        double score;\n        robj *cmpobj;\n    } u;\n} redisSortObject;\n\ntypedef struct _redisSortOperation {\n    int type;\n    robj *pattern;\n} redisSortOperation;\n\n/* Structure to hold list iteration abstraction. */\ntypedef struct {\n    robj *subject;\n    unsigned char encoding;\n    unsigned char direction; /* Iteration direction */\n    quicklistIter *iter;\n} listTypeIterator;\n\n/* Structure for an entry while iterating over a list. */\ntypedef struct {\n    listTypeIterator *li;\n    quicklistEntry entry; /* Entry in quicklist */\n} listTypeEntry;\n\n/* Structure to hold set iteration abstraction. */\ntypedef struct {\n    robj *subject;\n    int encoding;\n    int ii; /* intset iterator */\n    dictIterator *di;\n} setTypeIterator;\n\n/* Structure to hold hash iteration abstraction. Note that iteration over\n * hashes involves both fields and values. Because it is possible that\n * not both are required, store pointers in the iterator to avoid\n * unnecessary memory allocation for fields/values. */\ntypedef struct {\n    robj *subject;\n    int encoding;\n\n    unsigned char *fptr, *vptr;\n\n    dictIterator *di;\n    dictEntry *de;\n} hashTypeIterator;\n\n#define OBJ_HASH_KEY 1\n#define OBJ_HASH_VALUE 2\n\n/*-----------------------------------------------------------------------------\n * Extern declarations\n *----------------------------------------------------------------------------*/\n\nextern struct redisServer server;\nextern struct sharedObjectsStruct shared;\nextern dictType setDictType;\nextern dictType zsetDictType;\nextern dictType clusterNodesDictType;\nextern dictType clusterNodesBlackListDictType;\nextern dictType dbDictType;\nextern dictType shaScriptObjectDictType;\nextern double R_Zero, R_PosInf, R_NegInf, R_Nan;\nextern dictType hashDictType;\nextern dictType replScriptCacheDictType;\n\n/*-----------------------------------------------------------------------------\n * Functions prototypes\n *----------------------------------------------------------------------------*/\n\n/* Utils */\nlong long ustime(void);\nlong long mstime(void);\nvoid getRandomHexChars(char *p, unsigned int len);\nuint64_t crc64(uint64_t crc, const unsigned char *s, uint64_t l);\nvoid exitFromChild(int retcode);\nsize_t redisPopcount(void *s, long count);\nvoid redisSetProcTitle(char *title);\n\n/* networking.c -- Networking and Client related operations */\nclient *createClient(int fd);\nvoid closeTimedoutClients(void);\nvoid freeClient(client *c);\nvoid freeClientAsync(client *c);\nvoid resetClient(client *c);\nvoid sendReplyToClient(aeEventLoop *el, int fd, void *privdata, int mask);\nvoid *addDeferredMultiBulkLength(client *c);\nvoid setDeferredMultiBulkLength(client *c, void *node, long length);\nvoid processInputBuffer(client *c);\nvoid acceptHandler(aeEventLoop *el, int fd, void *privdata, int mask);\nvoid acceptTcpHandler(aeEventLoop *el, int fd, void *privdata, int mask);\nvoid acceptUnixHandler(aeEventLoop *el, int fd, void *privdata, int mask);\nvoid readQueryFromClient(aeEventLoop *el, int fd, void *privdata, int mask);\nvoid addReplyBulk(client *c, robj *obj);\nvoid addReplyBulkCString(client *c, const char *s);\nvoid addReplyBulkCBuffer(client *c, const void *p, size_t len);\nvoid addReplyBulkLongLong(client *c, long long ll);\nvoid addReply(client *c, robj *obj);\nvoid addReplySds(client *c, sds s);\nvoid addReplyBulkSds(client *c, sds s);\nvoid addReplyError(client *c, const char *err);\nvoid addReplyStatus(client *c, const char *status);\nvoid addReplyDouble(client *c, double d);\nvoid addReplyHumanLongDouble(client *c, long double d);\nvoid addReplyLongLong(client *c, long long ll);\nvoid addReplyMultiBulkLen(client *c, long length);\nvoid copyClientOutputBuffer(client *dst, client *src);\nvoid *dupClientReplyValue(void *o);\nvoid getClientsMaxBuffers(unsigned long *longest_output_list,\n                          unsigned long *biggest_input_buffer);\nchar *getClientPeerId(client *client);\nsds catClientInfoString(sds s, client *client);\nsds getAllClientsInfoString(void);\nvoid rewriteClientCommandVector(client *c, int argc, ...);\nvoid rewriteClientCommandArgument(client *c, int i, robj *newval);\nvoid replaceClientCommandVector(client *c, int argc, robj **argv);\nunsigned long getClientOutputBufferMemoryUsage(client *c);\nvoid freeClientsInAsyncFreeQueue(void);\nvoid asyncCloseClientOnOutputBufferLimitReached(client *c);\nint getClientType(client *c);\nint getClientTypeByName(char *name);\nchar *getClientTypeName(int class);\nvoid flushSlavesOutputBuffers(void);\nvoid disconnectSlaves(void);\nint listenToPort(int port, int *fds, int *count);\nvoid pauseClients(mstime_t duration);\nint clientsArePaused(void);\nint processEventsWhileBlocked(void);\nint handleClientsWithPendingWrites(void);\nint clientHasPendingReplies(client *c);\nvoid unlinkClient(client *c);\nint writeToClient(int fd, client *c, int handler_installed);\n\n#ifdef __GNUC__\nvoid addReplyErrorFormat(client *c, const char *fmt, ...)\n    __attribute__((format(printf, 2, 3)));\nvoid addReplyStatusFormat(client *c, const char *fmt, ...)\n    __attribute__((format(printf, 2, 3)));\n#else\nvoid addReplyErrorFormat(client *c, const char *fmt, ...);\nvoid addReplyStatusFormat(client *c, const char *fmt, ...);\n#endif\n\n/* List data type */\nvoid listTypeTryConversion(robj *subject, robj *value);\nvoid listTypePush(robj *subject, robj *value, int where);\nrobj *listTypePop(robj *subject, int where);\nunsigned long listTypeLength(robj *subject);\nlistTypeIterator *listTypeInitIterator(robj *subject, long index, unsigned char direction);\nvoid listTypeReleaseIterator(listTypeIterator *li);\nint listTypeNext(listTypeIterator *li, listTypeEntry *entry);\nrobj *listTypeGet(listTypeEntry *entry);\nvoid listTypeInsert(listTypeEntry *entry, robj *value, int where);\nint listTypeEqual(listTypeEntry *entry, robj *o);\nvoid listTypeDelete(listTypeIterator *iter, listTypeEntry *entry);\nvoid listTypeConvert(robj *subject, int enc);\nvoid unblockClientWaitingData(client *c);\nvoid handleClientsBlockedOnLists(void);\nvoid popGenericCommand(client *c, int where);\nvoid signalListAsReady(redisDb *db, robj *key);\n\n/* MULTI/EXEC/WATCH... */\nvoid unwatchAllKeys(client *c);\nvoid initClientMultiState(client *c);\nvoid freeClientMultiState(client *c);\nvoid queueMultiCommand(client *c);\nvoid touchWatchedKey(redisDb *db, robj *key);\nvoid touchWatchedKeysOnFlush(int dbid);\nvoid discardTransaction(client *c);\nvoid flagTransaction(client *c);\nvoid execCommandPropagateMulti(client *c);\n\n/* Redis object implementation */\nvoid decrRefCount(robj *o);\nvoid decrRefCountVoid(void *o);\nvoid incrRefCount(robj *o);\nrobj *resetRefCount(robj *obj);\nvoid freeStringObject(robj *o);\nvoid freeListObject(robj *o);\nvoid freeSetObject(robj *o);\nvoid freeZsetObject(robj *o);\nvoid freeHashObject(robj *o);\nrobj *createObject(int type, void *ptr);\nrobj *createStringObject(const char *ptr, size_t len);\nrobj *createRawStringObject(const char *ptr, size_t len);\nrobj *createEmbeddedStringObject(const char *ptr, size_t len);\nrobj *dupStringObject(robj *o);\nint isObjectRepresentableAsLongLong(robj *o, long long *llongval);\nrobj *tryObjectEncoding(robj *o);\nrobj *getDecodedObject(robj *o);\nsize_t stringObjectLen(robj *o);\nrobj *createStringObjectFromLongLong(long long value);\nrobj *createStringObjectFromLongDouble(long double value, int humanfriendly);\nrobj *createQuicklistObject(void);\nrobj *createZiplistObject(void);\nrobj *createSetObject(void);\nrobj *createIntsetObject(void);\nrobj *createHashObject(void);\nrobj *createZsetObject(void);\nrobj *createZsetZiplistObject(void);\nint getLongFromObjectOrReply(client *c, robj *o, long *target, const char *msg);\nint checkType(client *c, robj *o, int type);\nint getLongLongFromObjectOrReply(client *c, robj *o, long long *target, const char *msg);\nint getDoubleFromObjectOrReply(client *c, robj *o, double *target, const char *msg);\nint getLongLongFromObject(robj *o, long long *target);\nint getLongDoubleFromObject(robj *o, long double *target);\nint getLongDoubleFromObjectOrReply(client *c, robj *o, long double *target, const char *msg);\nchar *strEncoding(int encoding);\nint compareStringObjects(robj *a, robj *b);\nint collateStringObjects(robj *a, robj *b);\nint equalStringObjects(robj *a, robj *b);\nunsigned long long estimateObjectIdleTime(robj *o);\n#define sdsEncodedObject(objptr) (objptr->encoding == OBJ_ENCODING_RAW || objptr->encoding == OBJ_ENCODING_EMBSTR)\n\n/* Synchronous I/O with timeout */\nssize_t syncWrite(int fd, char *ptr, ssize_t size, long long timeout);\nssize_t syncRead(int fd, char *ptr, ssize_t size, long long timeout);\nssize_t syncReadLine(int fd, char *ptr, ssize_t size, long long timeout);\n\n/* Replication */\nvoid replicationFeedSlaves(list *slaves, int dictid, robj **argv, int argc);\nvoid replicationFeedMonitors(client *c, list *monitors, int dictid, robj **argv, int argc);\nvoid updateSlavesWaitingBgsave(int bgsaveerr, int type);\nvoid replicationCron(void);\nvoid replicationHandleMasterDisconnection(void);\nvoid replicationCacheMaster(client *c);\nvoid resizeReplicationBacklog(long long newsize);\nvoid replicationSetMaster(char *ip, int port);\nvoid replicationUnsetMaster(void);\nvoid refreshGoodSlavesCount(void);\nvoid replicationScriptCacheInit(void);\nvoid replicationScriptCacheFlush(void);\nvoid replicationScriptCacheAdd(sds sha1);\nint replicationScriptCacheExists(sds sha1);\nvoid processClientsWaitingReplicas(void);\nvoid unblockClientWaitingReplicas(client *c);\nint replicationCountAcksByOffset(long long offset);\nvoid replicationSendNewlineToMaster(void);\nlong long replicationGetSlaveOffset(void);\nchar *replicationGetSlaveName(client *c);\nlong long getPsyncInitialOffset(void);\nint replicationSetupSlaveForFullResync(client *slave, long long offset);\n\n/* Generic persistence functions */\nvoid startLoading(FILE *fp);\nvoid loadingProgress(off_t pos);\nvoid stopLoading(void);\n\n/* RDB persistence */\n#include \"rdb.h\"\n\n/* AOF persistence */\nvoid flushAppendOnlyFile(int force);\nvoid feedAppendOnlyFile(struct redisCommand *cmd, int dictid, robj **argv, int argc);\nvoid aofRemoveTempFile(pid_t childpid);\nint rewriteAppendOnlyFileBackground(void);\nint loadAppendOnlyFile(char *filename);\nvoid stopAppendOnly(void);\nint startAppendOnly(void);\nvoid backgroundRewriteDoneHandler(int exitcode, int bysignal);\nvoid aofRewriteBufferReset(void);\nunsigned long aofRewriteBufferSize(void);\n\n/* Sorted sets data type */\n\n/* Struct to hold a inclusive/exclusive range spec by score comparison. */\ntypedef struct {\n    double min, max;\n    int minex, maxex; /* are min or max exclusive? */\n} zrangespec;\n\n/* Struct to hold an inclusive/exclusive range spec by lexicographic comparison. */\ntypedef struct {\n    robj *min, *max;  /* May be set to shared.(minstring|maxstring) */\n    int minex, maxex; /* are min or max exclusive? */\n} zlexrangespec;\n\nzskiplist *zslCreate(void);\nvoid zslFree(zskiplist *zsl);\nzskiplistNode *zslInsert(zskiplist *zsl, double score, robj *obj);\nunsigned char *zzlInsert(unsigned char *zl, robj *ele, double score);\nint zslDelete(zskiplist *zsl, double score, robj *obj);\nzskiplistNode *zslFirstInRange(zskiplist *zsl, zrangespec *range);\nzskiplistNode *zslLastInRange(zskiplist *zsl, zrangespec *range);\ndouble zzlGetScore(unsigned char *sptr);\nvoid zzlNext(unsigned char *zl, unsigned char **eptr, unsigned char **sptr);\nvoid zzlPrev(unsigned char *zl, unsigned char **eptr, unsigned char **sptr);\nunsigned int zsetLength(robj *zobj);\nvoid zsetConvert(robj *zobj, int encoding);\nvoid zsetConvertToZiplistIfNeeded(robj *zobj, size_t maxelelen);\nint zsetScore(robj *zobj, robj *member, double *score);\nunsigned long zslGetRank(zskiplist *zsl, double score, robj *o);\n\n/* Core functions */\nint freeMemoryIfNeeded(void);\nint processCommand(client *c);\nvoid setupSignalHandlers(void);\nstruct redisCommand *lookupCommand(sds name);\nstruct redisCommand *lookupCommandByCString(char *s);\nstruct redisCommand *lookupCommandOrOriginal(sds name);\nvoid call(client *c, int flags);\nvoid propagate(struct redisCommand *cmd, int dbid, robj **argv, int argc, int flags);\nvoid alsoPropagate(struct redisCommand *cmd, int dbid, robj **argv, int argc, int target);\nvoid forceCommandPropagation(client *c, int flags);\nvoid preventCommandPropagation(client *c);\nvoid preventCommandAOF(client *c);\nvoid preventCommandReplication(client *c);\nint prepareForShutdown();\n#ifdef __GNUC__\nvoid serverLog(int level, const char *fmt, ...)\n    __attribute__((format(printf, 2, 3)));\n#else\nvoid serverLog(int level, const char *fmt, ...);\n#endif\nvoid serverLogRaw(int level, const char *msg);\nvoid serverLogFromHandler(int level, const char *msg);\nvoid usage(void);\nvoid updateDictResizePolicy(void);\nint htNeedsResize(dict *dict);\nvoid populateCommandTable(void);\nvoid resetCommandTableStats(void);\nvoid adjustOpenFilesLimit(void);\nvoid closeListeningSockets(int unlink_unix_socket);\nvoid updateCachedTime(void);\nvoid resetServerStats(void);\nunsigned int getLRUClock(void);\nconst char *evictPolicyToString(void);\n\n#define RESTART_SERVER_NONE 0\n#define RESTART_SERVER_GRACEFULLY (1<<0)     /* Do proper shutdown. */\n#define RESTART_SERVER_CONFIG_REWRITE (1<<1) /* CONFIG REWRITE before restart.*/\nint restartServer(int flags, mstime_t delay);\n\n/* Set data type */\nrobj *setTypeCreate(robj *value);\nint setTypeAdd(robj *subject, robj *value);\nint setTypeRemove(robj *subject, robj *value);\nint setTypeIsMember(robj *subject, robj *value);\nsetTypeIterator *setTypeInitIterator(robj *subject);\nvoid setTypeReleaseIterator(setTypeIterator *si);\nint setTypeNext(setTypeIterator *si, robj **objele, int64_t *llele);\nrobj *setTypeNextObject(setTypeIterator *si);\nint setTypeRandomElement(robj *setobj, robj **objele, int64_t *llele);\nunsigned long setTypeRandomElements(robj *set, unsigned long count, robj *aux_set);\nunsigned long setTypeSize(robj *subject);\nvoid setTypeConvert(robj *subject, int enc);\n\n/* Hash data type */\nvoid hashTypeConvert(robj *o, int enc);\nvoid hashTypeTryConversion(robj *subject, robj **argv, int start, int end);\nvoid hashTypeTryObjectEncoding(robj *subject, robj **o1, robj **o2);\nrobj *hashTypeGetObject(robj *o, robj *key);\nint hashTypeExists(robj *o, robj *key);\nint hashTypeSet(robj *o, robj *key, robj *value);\nint hashTypeDelete(robj *o, robj *key);\nunsigned long hashTypeLength(robj *o);\nhashTypeIterator *hashTypeInitIterator(robj *subject);\nvoid hashTypeReleaseIterator(hashTypeIterator *hi);\nint hashTypeNext(hashTypeIterator *hi);\nvoid hashTypeCurrentFromZiplist(hashTypeIterator *hi, int what,\n                                unsigned char **vstr,\n                                unsigned int *vlen,\n                                long long *vll);\nvoid hashTypeCurrentFromHashTable(hashTypeIterator *hi, int what, robj **dst);\nrobj *hashTypeCurrentObject(hashTypeIterator *hi, int what);\nrobj *hashTypeLookupWriteOrCreate(client *c, robj *key);\n\n/* Pub / Sub */\nint pubsubUnsubscribeAllChannels(client *c, int notify);\nint pubsubUnsubscribeAllPatterns(client *c, int notify);\nvoid freePubsubPattern(void *p);\nint listMatchPubsubPattern(void *a, void *b);\nint pubsubPublishMessage(robj *channel, robj *message);\n\n/* Keyspace events notification */\nvoid notifyKeyspaceEvent(int type, char *event, robj *key, int dbid);\nint keyspaceEventsStringToFlags(char *classes);\nsds keyspaceEventsFlagsToString(int flags);\n\n/* Configuration */\nvoid loadServerConfig(char *filename, char *options);\nvoid appendServerSaveParams(time_t seconds, int changes);\nvoid resetServerSaveParams(void);\nstruct rewriteConfigState; /* Forward declaration to export API. */\nvoid rewriteConfigRewriteLine(struct rewriteConfigState *state, const char *option, sds line, int force);\nint rewriteConfig(char *path);\n\n/* db.c -- Keyspace access API */\nint removeExpire(redisDb *db, robj *key);\nvoid propagateExpire(redisDb *db, robj *key);\nint expireIfNeeded(redisDb *db, robj *key);\nlong long getExpire(redisDb *db, robj *key);\nvoid setExpire(redisDb *db, robj *key, long long when);\nrobj *lookupKey(redisDb *db, robj *key, int flags);\nrobj *lookupKeyRead(redisDb *db, robj *key);\nrobj *lookupKeyWrite(redisDb *db, robj *key);\nrobj *lookupKeyReadOrReply(client *c, robj *key, robj *reply);\nrobj *lookupKeyWriteOrReply(client *c, robj *key, robj *reply);\nrobj *lookupKeyReadWithFlags(redisDb *db, robj *key, int flags);\n#define LOOKUP_NONE 0\n#define LOOKUP_NOTOUCH (1<<0)\nvoid dbAdd(redisDb *db, robj *key, robj *val);\nvoid dbOverwrite(redisDb *db, robj *key, robj *val);\nvoid setKey(redisDb *db, robj *key, robj *val);\nint dbExists(redisDb *db, robj *key);\nrobj *dbRandomKey(redisDb *db);\nint dbDelete(redisDb *db, robj *key);\nrobj *dbUnshareStringValue(redisDb *db, robj *key, robj *o);\nlong long emptyDb(void(callback)(void*));\nint selectDb(client *c, int id);\nvoid signalModifiedKey(redisDb *db, robj *key);\nvoid signalFlushedDb(int dbid);\nunsigned int getKeysInSlot(unsigned int hashslot, robj **keys, unsigned int count);\nunsigned int countKeysInSlot(unsigned int hashslot);\nunsigned int delKeysInSlot(unsigned int hashslot);\nint verifyClusterConfigWithData(void);\nvoid scanGenericCommand(client *c, robj *o, unsigned long cursor);\nint parseScanCursorOrReply(client *c, robj *o, unsigned long *cursor);\n\n/* API to get key arguments from commands */\nint *getKeysFromCommand(struct redisCommand *cmd, robj **argv, int argc, int *numkeys);\nvoid getKeysFreeResult(int *result);\nint *zunionInterGetKeys(struct redisCommand *cmd,robj **argv, int argc, int *numkeys);\nint *evalGetKeys(struct redisCommand *cmd, robj **argv, int argc, int *numkeys);\nint *sortGetKeys(struct redisCommand *cmd, robj **argv, int argc, int *numkeys);\nint *migrateGetKeys(struct redisCommand *cmd, robj **argv, int argc, int *numkeys);\n\n/* Cluster */\nvoid clusterInit(void);\nunsigned short crc16(const char *buf, int len);\nunsigned int keyHashSlot(char *key, int keylen);\nvoid clusterCron(void);\nvoid clusterPropagatePublish(robj *channel, robj *message);\nvoid migrateCloseTimedoutSockets(void);\nvoid clusterBeforeSleep(void);\n\n/* Sentinel */\nvoid initSentinelConfig(void);\nvoid initSentinel(void);\nvoid sentinelTimer(void);\nchar *sentinelHandleConfiguration(char **argv, int argc);\nvoid sentinelIsRunning(void);\n\n/* redis-check-rdb */\nint redis_check_rdb(char *rdbfilename);\nint redis_check_rdb_main(int argc, char **argv);\n\n/* Scripting */\nvoid scriptingInit(int setup);\nint ldbRemoveChild(pid_t pid);\nvoid ldbKillForkedSessions(void);\nint ldbPendingChildren(void);\n\n/* Blocked clients */\nvoid processUnblockedClients(void);\nvoid blockClient(client *c, int btype);\nvoid unblockClient(client *c);\nvoid replyToBlockedClientTimedOut(client *c);\nint getTimeoutFromObjectOrReply(client *c, robj *object, mstime_t *timeout, int unit);\nvoid disconnectAllBlockedClients(void);\n\n/* Git SHA1 */\nchar *redisGitSHA1(void);\nchar *redisGitDirty(void);\nuint64_t redisBuildId(void);\n\n/* Commands prototypes */\nvoid authCommand(client *c);\nvoid pingCommand(client *c);\nvoid echoCommand(client *c);\nvoid commandCommand(client *c);\nvoid setCommand(client *c);\nvoid setnxCommand(client *c);\nvoid setexCommand(client *c);\nvoid psetexCommand(client *c);\nvoid getCommand(client *c);\nvoid delCommand(client *c);\nvoid existsCommand(client *c);\nvoid setbitCommand(client *c);\nvoid getbitCommand(client *c);\nvoid bitfieldCommand(client *c);\nvoid setrangeCommand(client *c);\nvoid getrangeCommand(client *c);\nvoid incrCommand(client *c);\nvoid decrCommand(client *c);\nvoid incrbyCommand(client *c);\nvoid decrbyCommand(client *c);\nvoid incrbyfloatCommand(client *c);\nvoid selectCommand(client *c);\nvoid randomkeyCommand(client *c);\nvoid keysCommand(client *c);\nvoid scanCommand(client *c);\nvoid dbsizeCommand(client *c);\nvoid lastsaveCommand(client *c);\nvoid saveCommand(client *c);\nvoid bgsaveCommand(client *c);\nvoid bgrewriteaofCommand(client *c);\nvoid shutdownCommand(client *c);\nvoid moveCommand(client *c);\nvoid renameCommand(client *c);\nvoid renamenxCommand(client *c);\nvoid lpushCommand(client *c);\nvoid rpushCommand(client *c);\nvoid lpushxCommand(client *c);\nvoid rpushxCommand(client *c);\nvoid linsertCommand(client *c);\nvoid lpopCommand(client *c);\nvoid rpopCommand(client *c);\nvoid llenCommand(client *c);\nvoid lindexCommand(client *c);\nvoid lrangeCommand(client *c);\nvoid ltrimCommand(client *c);\nvoid typeCommand(client *c);\nvoid lsetCommand(client *c);\nvoid saddCommand(client *c);\nvoid sremCommand(client *c);\nvoid smoveCommand(client *c);\nvoid sismemberCommand(client *c);\nvoid scardCommand(client *c);\nvoid spopCommand(client *c);\nvoid srandmemberCommand(client *c);\nvoid sinterCommand(client *c);\nvoid sinterstoreCommand(client *c);\nvoid sunionCommand(client *c);\nvoid sunionstoreCommand(client *c);\nvoid sdiffCommand(client *c);\nvoid sdiffstoreCommand(client *c);\nvoid sscanCommand(client *c);\nvoid syncCommand(client *c);\nvoid flushdbCommand(client *c);\nvoid flushallCommand(client *c);\nvoid sortCommand(client *c);\nvoid lremCommand(client *c);\nvoid rpoplpushCommand(client *c);\nvoid infoCommand(client *c);\nvoid mgetCommand(client *c);\nvoid monitorCommand(client *c);\nvoid expireCommand(client *c);\nvoid expireatCommand(client *c);\nvoid pexpireCommand(client *c);\nvoid pexpireatCommand(client *c);\nvoid getsetCommand(client *c);\nvoid ttlCommand(client *c);\nvoid touchCommand(client *c);\nvoid pttlCommand(client *c);\nvoid persistCommand(client *c);\nvoid slaveofCommand(client *c);\nvoid roleCommand(client *c);\nvoid debugCommand(client *c);\nvoid msetCommand(client *c);\nvoid msetnxCommand(client *c);\nvoid zaddCommand(client *c);\nvoid zincrbyCommand(client *c);\nvoid zrangeCommand(client *c);\nvoid zrangebyscoreCommand(client *c);\nvoid zrevrangebyscoreCommand(client *c);\nvoid zrangebylexCommand(client *c);\nvoid zrevrangebylexCommand(client *c);\nvoid zcountCommand(client *c);\nvoid zlexcountCommand(client *c);\nvoid zrevrangeCommand(client *c);\nvoid zcardCommand(client *c);\nvoid zremCommand(client *c);\nvoid zscoreCommand(client *c);\nvoid zremrangebyscoreCommand(client *c);\nvoid zremrangebylexCommand(client *c);\nvoid multiCommand(client *c);\nvoid execCommand(client *c);\nvoid discardCommand(client *c);\nvoid blpopCommand(client *c);\nvoid brpopCommand(client *c);\nvoid brpoplpushCommand(client *c);\nvoid appendCommand(client *c);\nvoid strlenCommand(client *c);\nvoid zrankCommand(client *c);\nvoid zrevrankCommand(client *c);\nvoid hsetCommand(client *c);\nvoid hsetnxCommand(client *c);\nvoid hgetCommand(client *c);\nvoid hmsetCommand(client *c);\nvoid hmgetCommand(client *c);\nvoid hdelCommand(client *c);\nvoid hlenCommand(client *c);\nvoid hstrlenCommand(client *c);\nvoid zremrangebyrankCommand(client *c);\nvoid zunionstoreCommand(client *c);\nvoid zinterstoreCommand(client *c);\nvoid zscanCommand(client *c);\nvoid hkeysCommand(client *c);\nvoid hvalsCommand(client *c);\nvoid hgetallCommand(client *c);\nvoid hexistsCommand(client *c);\nvoid hscanCommand(client *c);\nvoid configCommand(client *c);\nvoid hincrbyCommand(client *c);\nvoid hincrbyfloatCommand(client *c);\nvoid subscribeCommand(client *c);\nvoid unsubscribeCommand(client *c);\nvoid psubscribeCommand(client *c);\nvoid punsubscribeCommand(client *c);\nvoid publishCommand(client *c);\nvoid pubsubCommand(client *c);\nvoid watchCommand(client *c);\nvoid unwatchCommand(client *c);\nvoid clusterCommand(client *c);\nvoid restoreCommand(client *c);\nvoid migrateCommand(client *c);\nvoid askingCommand(client *c);\nvoid readonlyCommand(client *c);\nvoid readwriteCommand(client *c);\nvoid dumpCommand(client *c);\nvoid objectCommand(client *c);\nvoid clientCommand(client *c);\nvoid evalCommand(client *c);\nvoid evalShaCommand(client *c);\nvoid scriptCommand(client *c);\nvoid timeCommand(client *c);\nvoid bitopCommand(client *c);\nvoid bitcountCommand(client *c);\nvoid bitposCommand(client *c);\nvoid replconfCommand(client *c);\nvoid waitCommand(client *c);\nvoid geoencodeCommand(client *c);\nvoid geodecodeCommand(client *c);\nvoid georadiusByMemberCommand(client *c);\nvoid georadiusCommand(client *c);\nvoid geoaddCommand(client *c);\nvoid geohashCommand(client *c);\nvoid geoposCommand(client *c);\nvoid geodistCommand(client *c);\nvoid pfselftestCommand(client *c);\nvoid pfaddCommand(client *c);\nvoid pfcountCommand(client *c);\nvoid pfmergeCommand(client *c);\nvoid pfdebugCommand(client *c);\nvoid latencyCommand(client *c);\nvoid slotsinfoCommand(client *c);\nvoid slotsscanCommand(client *c);\nvoid slotsdelCommand(client *c);\nvoid slotsmgrtslotCommand(client *c);\nvoid slotsmgrtoneCommand(client *c);\nvoid slotsmgrttagslotCommand(client *c);\nvoid slotsmgrttagoneCommand(client *c);\nvoid slotshashkeyCommand(client *c);\nvoid slotscheckCommand(client *c);\nvoid slotsrestoreCommand(client *c);\n\nvoid slotsmgrt_cleanup();\nint slots_num(const sds s, uint32_t *pcrc, int *phastag);\n\n\n#if defined(__GNUC__)\nvoid *calloc(size_t count, size_t size) __attribute__ ((deprecated));\nvoid free(void *ptr) __attribute__ ((deprecated));\nvoid *malloc(size_t size) __attribute__ ((deprecated));\nvoid *realloc(void *ptr, size_t size) __attribute__ ((deprecated));\n#endif\n\n/* Debugging stuff */\nvoid _serverAssertWithInfo(client *c, robj *o, char *estr, char *file, int line);\nvoid _serverAssert(char *estr, char *file, int line);\nvoid _serverPanic(char *msg, char *file, int line);\nvoid bugReportStart(void);\nvoid serverLogObjectDebugInfo(robj *o);\nvoid sigsegvHandler(int sig, siginfo_t *info, void *secret);\nsds genRedisInfoString(char *section);\nvoid enableWatchdog(int period);\nvoid disableWatchdog(void);\nvoid watchdogScheduleSignal(int period);\nvoid serverLogHexDump(int level, char *descr, void *value, size_t len);\nint memtest_preserving_test(unsigned long *m, size_t bytes, int passes);\n\n#define redisDebug(fmt, ...) \\\n    printf(\"DEBUG %s:%d > \" fmt \"\\n\", __FILE__, __LINE__, __VA_ARGS__)\n#define redisDebugMark() \\\n    printf(\"-- MARK %s:%d --\\n\", __FILE__, __LINE__)\n\n#endif\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/src/setproctitle.c",
    "content": "/* ==========================================================================\n * setproctitle.c - Linux/Darwin setproctitle.\n * --------------------------------------------------------------------------\n * Copyright (C) 2010  William Ahern\n * Copyright (C) 2013  Salvatore Sanfilippo\n * Copyright (C) 2013  Stam He\n *\n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the\n * \"Software\"), to deal in the Software without restriction, including\n * without limitation the rights to use, copy, modify, merge, publish,\n * distribute, sublicense, and/or sell copies of the Software, and to permit\n * persons to whom the Software is furnished to do so, subject to the\n * following conditions:\n *\n * The above copyright notice and this permission notice shall be included\n * in all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS\n * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\n * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN\n * NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,\n * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR\n * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE\n * USE OR OTHER DEALINGS IN THE SOFTWARE.\n * ==========================================================================\n */\n#ifndef _GNU_SOURCE\n#define _GNU_SOURCE\n#endif\n\n#include <stddef.h>\t/* NULL size_t */\n#include <stdarg.h>\t/* va_list va_start va_end */\n#include <stdlib.h>\t/* malloc(3) setenv(3) clearenv(3) setproctitle(3) getprogname(3) */\n#include <stdio.h>\t/* vsnprintf(3) snprintf(3) */\n\n#include <string.h>\t/* strlen(3) strchr(3) strdup(3) memset(3) memcpy(3) */\n\n#include <errno.h>\t/* errno program_invocation_name program_invocation_short_name */\n\n#if !defined(HAVE_SETPROCTITLE)\n#define HAVE_SETPROCTITLE (defined __NetBSD__ || defined __FreeBSD__ || defined __OpenBSD__)\n#endif\n\n\n#if !HAVE_SETPROCTITLE\n#if (defined __linux || defined __APPLE__)\n\nextern char **environ;\n\nstatic struct {\n\t/* original value */\n\tconst char *arg0;\n\n\t/* title space available */\n\tchar *base, *end;\n\n\t /* pointer to original nul character within base */\n\tchar *nul;\n\n\t_Bool reset;\n\tint error;\n} SPT;\n\n\n#ifndef SPT_MIN\n#define SPT_MIN(a, b) (((a) < (b))? (a) : (b))\n#endif\n\nstatic inline size_t spt_min(size_t a, size_t b) {\n\treturn SPT_MIN(a, b);\n} /* spt_min() */\n\n\n/*\n * For discussion on the portability of the various methods, see\n * http://lists.freebsd.org/pipermail/freebsd-stable/2008-June/043136.html\n */\nstatic int spt_clearenv(void) {\n#if __GLIBC__\n\tclearenv();\n\n\treturn 0;\n#else\n\textern char **environ;\n\tstatic char **tmp;\n\n\tif (!(tmp = malloc(sizeof *tmp)))\n\t\treturn errno;\n\n\ttmp[0]  = NULL;\n\tenviron = tmp;\n\n\treturn 0;\n#endif\n} /* spt_clearenv() */\n\n\nstatic int spt_copyenv(char *oldenv[]) {\n\textern char **environ;\n\tchar *eq;\n\tint i, error;\n\n\tif (environ != oldenv)\n\t\treturn 0;\n\n\tif ((error = spt_clearenv()))\n\t\tgoto error;\n\n\tfor (i = 0; oldenv[i]; i++) {\n\t\tif (!(eq = strchr(oldenv[i], '=')))\n\t\t\tcontinue;\n\n\t\t*eq = '\\0';\n\t\terror = (0 != setenv(oldenv[i], eq + 1, 1))? errno : 0;\n\t\t*eq = '=';\n\n\t\tif (error)\n\t\t\tgoto error;\n\t}\n\n\treturn 0;\nerror:\n\tenviron = oldenv;\n\n\treturn error;\n} /* spt_copyenv() */\n\n\nstatic int spt_copyargs(int argc, char *argv[]) {\n\tchar *tmp;\n\tint i;\n\n\tfor (i = 1; i < argc || (i >= argc && argv[i]); i++) {\n\t\tif (!argv[i])\n\t\t\tcontinue;\n\n\t\tif (!(tmp = strdup(argv[i])))\n\t\t\treturn errno;\n\n\t\targv[i] = tmp;\n\t}\n\n\treturn 0;\n} /* spt_copyargs() */\n\n\nvoid spt_init(int argc, char *argv[]) {\n        char **envp = environ;\n\tchar *base, *end, *nul, *tmp;\n\tint i, error;\n\n\tif (!(base = argv[0]))\n\t\treturn;\n\n\tnul = &base[strlen(base)];\n\tend = nul + 1;\n\n\tfor (i = 0; i < argc || (i >= argc && argv[i]); i++) {\n\t\tif (!argv[i] || argv[i] < end)\n\t\t\tcontinue;\n\n\t\tend = argv[i] + strlen(argv[i]) + 1;\n\t}\n\n\tfor (i = 0; envp[i]; i++) {\n\t\tif (envp[i] < end)\n\t\t\tcontinue;\n\n\t\tend = envp[i] + strlen(envp[i]) + 1;\n\t}\n\n\tif (!(SPT.arg0 = strdup(argv[0])))\n\t\tgoto syerr;\n\n#if __GLIBC__\n\tif (!(tmp = strdup(program_invocation_name)))\n\t\tgoto syerr;\n\n\tprogram_invocation_name = tmp;\n\n\tif (!(tmp = strdup(program_invocation_short_name)))\n\t\tgoto syerr;\n\n\tprogram_invocation_short_name = tmp;\n#elif __APPLE__\n\tif (!(tmp = strdup(getprogname())))\n\t\tgoto syerr;\n\n\tsetprogname(tmp);\n#endif\n\n\n\tif ((error = spt_copyenv(envp)))\n\t\tgoto error;\n\n\tif ((error = spt_copyargs(argc, argv)))\n\t\tgoto error;\n\n\tSPT.nul  = nul;\n\tSPT.base = base;\n\tSPT.end  = end;\n\n\treturn;\nsyerr:\n\terror = errno;\nerror:\n\tSPT.error = error;\n} /* spt_init() */\n\n\n#ifndef SPT_MAXTITLE\n#define SPT_MAXTITLE 255\n#endif\n\nvoid setproctitle(const char *fmt, ...) {\n\tchar buf[SPT_MAXTITLE + 1]; /* use buffer in case argv[0] is passed */\n\tva_list ap;\n\tchar *nul;\n\tint len, error;\n\n\tif (!SPT.base)\n\t\treturn;\n\n\tif (fmt) {\n\t\tva_start(ap, fmt);\n\t\tlen = vsnprintf(buf, sizeof buf, fmt, ap);\n\t\tva_end(ap);\n\t} else {\n\t\tlen = snprintf(buf, sizeof buf, \"%s\", SPT.arg0);\n\t}\n\n\tif (len <= 0)\n\t\t{ error = errno; goto error; }\n\n\tif (!SPT.reset) {\n\t\tmemset(SPT.base, 0, SPT.end - SPT.base);\n\t\tSPT.reset = 1;\n\t} else {\n\t\tmemset(SPT.base, 0, spt_min(sizeof buf, SPT.end - SPT.base));\n\t}\n\n\tlen = spt_min(len, spt_min(sizeof buf, SPT.end - SPT.base) - 1);\n\tmemcpy(SPT.base, buf, len);\n\tnul = &SPT.base[len];\n\n\tif (nul < SPT.nul) {\n\t\t*SPT.nul = '.';\n\t} else if (nul == SPT.nul && &nul[1] < SPT.end) {\n\t\t*SPT.nul = ' ';\n\t\t*++nul = '\\0';\n\t}\n\n\treturn;\nerror:\n\tSPT.error = error;\n} /* setproctitle() */\n\n\n#endif /* __linux || __APPLE__ */\n#endif /* !HAVE_SETPROCTITLE */\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/src/sha1.c",
    "content": "\n/* from valgrind tests */\n\n/* ================ sha1.c ================ */\n/*\nSHA-1 in C\nBy Steve Reid <steve@edmweb.com>\n100% Public Domain\n\nTest Vectors (from FIPS PUB 180-1)\n\"abc\"\n  A9993E36 4706816A BA3E2571 7850C26C 9CD0D89D\n\"abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq\"\n  84983E44 1C3BD26E BAAE4AA1 F95129E5 E54670F1\nA million repetitions of \"a\"\n  34AA973C D4C4DAA4 F61EEB2B DBAD2731 6534016F\n*/\n\n/* #define LITTLE_ENDIAN * This should be #define'd already, if true. */\n/* #define SHA1HANDSOFF * Copies data before messing with it. */\n\n#define SHA1HANDSOFF\n\n#include <stdio.h>\n#include <string.h>\n#include <stdint.h>\n#include \"solarisfixes.h\"\n#include \"sha1.h\"\n#include \"config.h\"\n\n#define rol(value, bits) (((value) << (bits)) | ((value) >> (32 - (bits))))\n\n/* blk0() and blk() perform the initial expand. */\n/* I got the idea of expanding during the round function from SSLeay */\n#if BYTE_ORDER == LITTLE_ENDIAN\n#define blk0(i) (block->l[i] = (rol(block->l[i],24)&0xFF00FF00) \\\n    |(rol(block->l[i],8)&0x00FF00FF))\n#elif BYTE_ORDER == BIG_ENDIAN\n#define blk0(i) block->l[i]\n#else\n#error \"Endianness not defined!\"\n#endif\n#define blk(i) (block->l[i&15] = rol(block->l[(i+13)&15]^block->l[(i+8)&15] \\\n    ^block->l[(i+2)&15]^block->l[i&15],1))\n\n/* (R0+R1), R2, R3, R4 are the different operations used in SHA1 */\n#define R0(v,w,x,y,z,i) z+=((w&(x^y))^y)+blk0(i)+0x5A827999+rol(v,5);w=rol(w,30);\n#define R1(v,w,x,y,z,i) z+=((w&(x^y))^y)+blk(i)+0x5A827999+rol(v,5);w=rol(w,30);\n#define R2(v,w,x,y,z,i) z+=(w^x^y)+blk(i)+0x6ED9EBA1+rol(v,5);w=rol(w,30);\n#define R3(v,w,x,y,z,i) z+=(((w|x)&y)|(w&x))+blk(i)+0x8F1BBCDC+rol(v,5);w=rol(w,30);\n#define R4(v,w,x,y,z,i) z+=(w^x^y)+blk(i)+0xCA62C1D6+rol(v,5);w=rol(w,30);\n\n\n/* Hash a single 512-bit block. This is the core of the algorithm. */\n\nvoid SHA1Transform(uint32_t state[5], const unsigned char buffer[64])\n{\n    uint32_t a, b, c, d, e;\n    typedef union {\n        unsigned char c[64];\n        uint32_t l[16];\n    } CHAR64LONG16;\n#ifdef SHA1HANDSOFF\n    CHAR64LONG16 block[1];  /* use array to appear as a pointer */\n    memcpy(block, buffer, 64);\n#else\n    /* The following had better never be used because it causes the\n     * pointer-to-const buffer to be cast into a pointer to non-const.\n     * And the result is written through.  I threw a \"const\" in, hoping\n     * this will cause a diagnostic.\n     */\n    CHAR64LONG16* block = (const CHAR64LONG16*)buffer;\n#endif\n    /* Copy context->state[] to working vars */\n    a = state[0];\n    b = state[1];\n    c = state[2];\n    d = state[3];\n    e = state[4];\n    /* 4 rounds of 20 operations each. Loop unrolled. */\n    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);\n    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);\n    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);\n    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);\n    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);\n    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);\n    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);\n    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);\n    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);\n    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);\n    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);\n    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);\n    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);\n    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);\n    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);\n    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);\n    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);\n    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);\n    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);\n    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);\n    /* Add the working vars back into context.state[] */\n    state[0] += a;\n    state[1] += b;\n    state[2] += c;\n    state[3] += d;\n    state[4] += e;\n    /* Wipe variables */\n    a = b = c = d = e = 0;\n#ifdef SHA1HANDSOFF\n    memset(block, '\\0', sizeof(block));\n#endif\n}\n\n\n/* SHA1Init - Initialize new context */\n\nvoid SHA1Init(SHA1_CTX* context)\n{\n    /* SHA1 initialization constants */\n    context->state[0] = 0x67452301;\n    context->state[1] = 0xEFCDAB89;\n    context->state[2] = 0x98BADCFE;\n    context->state[3] = 0x10325476;\n    context->state[4] = 0xC3D2E1F0;\n    context->count[0] = context->count[1] = 0;\n}\n\n\n/* Run your data through this. */\n\nvoid SHA1Update(SHA1_CTX* context, const unsigned char* data, uint32_t len)\n{\n    uint32_t i, j;\n\n    j = context->count[0];\n    if ((context->count[0] += len << 3) < j)\n        context->count[1]++;\n    context->count[1] += (len>>29);\n    j = (j >> 3) & 63;\n    if ((j + len) > 63) {\n        memcpy(&context->buffer[j], data, (i = 64-j));\n        SHA1Transform(context->state, context->buffer);\n        for ( ; i + 63 < len; i += 64) {\n            SHA1Transform(context->state, &data[i]);\n        }\n        j = 0;\n    }\n    else i = 0;\n    memcpy(&context->buffer[j], &data[i], len - i);\n}\n\n\n/* Add padding and return the message digest. */\n\nvoid SHA1Final(unsigned char digest[20], SHA1_CTX* context)\n{\n    unsigned i;\n    unsigned char finalcount[8];\n    unsigned char c;\n\n#if 0\t/* untested \"improvement\" by DHR */\n    /* Convert context->count to a sequence of bytes\n     * in finalcount.  Second element first, but\n     * big-endian order within element.\n     * But we do it all backwards.\n     */\n    unsigned char *fcp = &finalcount[8];\n\n    for (i = 0; i < 2; i++)\n       {\n        uint32_t t = context->count[i];\n        int j;\n\n        for (j = 0; j < 4; t >>= 8, j++)\n\t          *--fcp = (unsigned char) t;\n    }\n#else\n    for (i = 0; i < 8; i++) {\n        finalcount[i] = (unsigned char)((context->count[(i >= 4 ? 0 : 1)]\n         >> ((3-(i & 3)) * 8) ) & 255);  /* Endian independent */\n    }\n#endif\n    c = 0200;\n    SHA1Update(context, &c, 1);\n    while ((context->count[0] & 504) != 448) {\n\tc = 0000;\n        SHA1Update(context, &c, 1);\n    }\n    SHA1Update(context, finalcount, 8);  /* Should cause a SHA1Transform() */\n    for (i = 0; i < 20; i++) {\n        digest[i] = (unsigned char)\n         ((context->state[i>>2] >> ((3-(i & 3)) * 8) ) & 255);\n    }\n    /* Wipe variables */\n    memset(context, '\\0', sizeof(*context));\n    memset(&finalcount, '\\0', sizeof(finalcount));\n}\n/* ================ end of sha1.c ================ */\n\n#ifdef REDIS_TEST\n#define BUFSIZE 4096\n\n#define UNUSED(x) (void)(x)\nint sha1Test(int argc, char **argv)\n{\n    SHA1_CTX ctx;\n    unsigned char hash[20], buf[BUFSIZE];\n    int i;\n\n    UNUSED(argc);\n    UNUSED(argv);\n\n    for(i=0;i<BUFSIZE;i++)\n        buf[i] = i;\n\n    SHA1Init(&ctx);\n    for(i=0;i<1000;i++)\n        SHA1Update(&ctx, buf, BUFSIZE);\n    SHA1Final(hash, &ctx);\n\n    printf(\"SHA1=\");\n    for(i=0;i<20;i++)\n        printf(\"%02x\", hash[i]);\n    printf(\"\\n\");\n    return 0;\n}\n#endif\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/src/sha1.h",
    "content": "#ifndef SHA1_H\n#define SHA1_H\n/* ================ sha1.h ================ */\n/*\nSHA-1 in C\nBy Steve Reid <steve@edmweb.com>\n100% Public Domain\n*/\n\ntypedef struct {\n    uint32_t state[5];\n    uint32_t count[2];\n    unsigned char buffer[64];\n} SHA1_CTX;\n\nvoid SHA1Transform(uint32_t state[5], const unsigned char buffer[64]);\nvoid SHA1Init(SHA1_CTX* context);\nvoid SHA1Update(SHA1_CTX* context, const unsigned char* data, uint32_t len);\nvoid SHA1Final(unsigned char digest[20], SHA1_CTX* context);\n\n#ifdef REDIS_TEST\nint sha1Test(int argc, char **argv);\n#endif\n#endif\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/src/slots.c",
    "content": "#include \"server.h\"\n\nextern void createDumpPayload(rio *payload, robj *o);\nextern int verifyDumpPayload(unsigned char *p, size_t len);\n\nstatic void *\nslots_tag(const sds s, int *plen) {\n    int i, j, n = sdslen(s);\n    for (i = 0; i < n && s[i] != '{'; i ++) {}\n    if (i == n) {\n        return NULL;\n    }\n    i ++;\n    for (j = i; j < n && s[j] != '}'; j ++) {}\n    if (j == n) {\n        return NULL;\n    }\n    if (plen != NULL) {\n        *plen = j - i;\n    }\n    return s + i;\n}\n\nint\nslots_num(const sds s, uint32_t *pcrc, int *phastag) {\n    int taglen;\n    int hastag = 0;\n    void *tag = slots_tag(s, &taglen);\n    if (tag == NULL) {\n        tag = s, taglen = sdslen(s);\n    } else {\n        hastag = 1;\n    }\n    uint32_t crc = crc32_checksum(tag, taglen);\n    if (pcrc != NULL) {\n        *pcrc = crc;\n    }\n    if (phastag != NULL) {\n        *phastag = hastag;\n    }\n    return crc & HASH_SLOTS_MASK;\n}\n\nstatic int\nparse_int(client *c, robj *obj, int *p) {\n    long v;\n    if (getLongFromObjectOrReply(c, obj, &v, NULL) != C_OK) {\n        return -1;\n    }\n    if (v < INT_MIN || v > INT_MAX) {\n        addReplyError(c, \"value is out of range\");\n        return -1;\n    } else {\n        *p = v;\n        return 0;\n    }\n}\n\nstatic int\nparse_timeout(client *c, robj *obj, int *p) {\n    int v;\n    if (parse_int(c, obj, &v) != 0) {\n        return -1;\n    }\n    if (v < 0) {\n        addReplyErrorFormat(c, \"invalid timeout = %d\", v);\n        return -1;\n    }\n    *p = (v == 0) ? 100 : v;\n    return 0;\n}\n\nstatic int\nparse_slot(client *c, robj *obj, int *p) {\n    int v;\n    if (parse_int(c, obj, &v) != 0) {\n        return -1;\n    }\n    if (v < 0 || v >= HASH_SLOTS_SIZE) {\n        addReplyErrorFormat(c, \"invalid slot number = %d\", v);\n        return -1;\n    }\n    *p = v;\n    return 0;\n}\n\n/* *\n * slotshashkey [key1 key2...]\n * */\nvoid\nslotshashkeyCommand(client *c) {\n    int i;\n    addReplyMultiBulkLen(c, c->argc - 1);\n    for (i = 1; i < c->argc; i ++) {\n        robj *key = c->argv[i];\n        addReplyLongLong(c, slots_num(key->ptr, NULL, NULL));\n    }\n}\n\n/* *\n * slotsinfo [start] [count]\n * */\nvoid\nslotsinfoCommand(client *c) {\n    int slots_slot[HASH_SLOTS_SIZE];\n    int slots_size[HASH_SLOTS_SIZE];\n    int n = 0, beg = 0, end = HASH_SLOTS_SIZE;\n    if (c->argc >= 2) {\n        if (parse_slot(c, c->argv[1], &beg) != 0) {\n            return;\n        }\n    }\n    if (c->argc >= 3) {\n        int v;\n        if (parse_int(c, c->argv[2], &v) != 0) {\n            return;\n        }\n        if (v < 0) {\n            addReplyErrorFormat(c, \"invalid slot count = %d\", v);\n            return;\n        }\n        if (beg + v < end) {\n            end = beg + v;\n        }\n    }\n    if (c->argc >= 4) {\n        addReplyErrorFormat(c, \"wrong number of arguments for 'slotsinfo' command\");\n        return;\n    }\n    int i;\n    for (i = beg; i < end; i ++) {\n        int s = dictSize(c->db->hash_slots[i]);\n        if (s == 0) {\n            continue;\n        }\n        slots_slot[n] = i;\n        slots_size[n] = s;\n        n ++;\n    }\n    addReplyMultiBulkLen(c, n);\n    for (i = 0; i < n; i ++) {\n        addReplyMultiBulkLen(c, 2);\n        addReplyLongLong(c, slots_slot[i]);\n        addReplyLongLong(c, slots_size[i]);\n    }\n}\n\ntypedef struct {\n    int fd;\n    int db;\n    int authorized;\n    time_t lasttime;\n} slotsmgrt_sockfd;\n\nstatic slotsmgrt_sockfd *\nslotsmgrt_get_sockfd(client *c, sds host, sds port, int timeout) {\n    sds name = sdsempty();\n    name = sdscatlen(name, host, sdslen(host));\n    name = sdscatlen(name, \":\", 1);\n    name = sdscatlen(name, port, sdslen(port));\n\n    slotsmgrt_sockfd *pfd = dictFetchValue(server.slotsmgrt_cached_sockfds, name);\n    if (pfd != NULL) {\n        sdsfree(name);\n        pfd->lasttime = server.unixtime;\n        return pfd;\n    }\n\n    int fd = anetTcpNonBlockConnect(server.neterr, host, atoi(port));\n    if (fd == -1) {\n        serverLog(LL_WARNING, \"slotsmgrt: connect to target %s:%s, error = '%s'\",\n                host, port, server.neterr);\n        sdsfree(name);\n        addReplyErrorFormat(c,\"Can't connect to target node: %s\", server.neterr);\n        return NULL;\n    }\n    anetEnableTcpNoDelay(server.neterr, fd);\n    if ((aeWait(fd, AE_WRITABLE, timeout) & AE_WRITABLE) == 0) {\n        serverLog(LL_WARNING, \"slotsmgrt: connect to target %s:%s, aewait error = '%s'\",\n                host, port, server.neterr);\n        sdsfree(name);\n        close(fd);\n        addReplySds(c, sdsnew(\"-IOERR error or timeout connecting to the client\\r\\n\"));\n        return NULL;\n    }\n    serverLog(LL_WARNING, \"slotsmgrt: connect to target %s:%s\", host, port);\n\n    pfd = zmalloc(sizeof(*pfd));\n    pfd->fd = fd;\n    pfd->db = -1;\n    pfd->authorized = (server.requirepass == NULL) ? 1 : 0;\n    pfd->lasttime = server.unixtime;\n    dictAdd(server.slotsmgrt_cached_sockfds, name, pfd);\n    return pfd;\n}\n\nstatic void\nslotsmgrt_close_socket(sds host, sds port) {\n    sds name = sdsempty();\n    name = sdscatlen(name, host, sdslen(host));\n    name = sdscatlen(name, \":\", 1);\n    name = sdscatlen(name, port, sdslen(port));\n\n    slotsmgrt_sockfd *pfd = dictFetchValue(server.slotsmgrt_cached_sockfds, name);\n    if (pfd == NULL) {\n        serverLog(LL_WARNING, \"slotsmgrt: close target %s:%s again\", host, port);\n        sdsfree(name);\n        return;\n    } else {\n        serverLog(LL_WARNING, \"slotsmgrt: close target %s:%s\", host, port);\n    }\n    dictDelete(server.slotsmgrt_cached_sockfds, name);\n    close(pfd->fd);\n    zfree(pfd);\n    sdsfree(name);\n}\n\nvoid\nslotsmgrt_cleanup() {\n    dictIterator *di = dictGetSafeIterator(server.slotsmgrt_cached_sockfds);\n    dictEntry *de;\n    while((de = dictNext(di)) != NULL) {\n        slotsmgrt_sockfd *pfd = dictGetVal(de);\n        if ((server.unixtime - pfd->lasttime) > 15) {\n            serverLog(LL_WARNING, \"slotsmgrt: timeout target %s, lasttime = %ld, now = %ld\",\n                   (char *)dictGetKey(de), pfd->lasttime, server.unixtime);\n            dictDelete(server.slotsmgrt_cached_sockfds, dictGetKey(de));\n            close(pfd->fd);\n            zfree(pfd);\n        }\n    }\n    dictReleaseIterator(di);\n}\n\nstatic int\nslotsmgrt(client *c, sds host, sds port, slotsmgrt_sockfd *pfd, int db, int timeout, robj *keys[], robj *vals[], int n) {\n    rio cmd;\n    rioInitWithBuffer(&cmd, sdsempty());\n\n    int needauth = 0;\n    if (pfd->authorized == 0 && server.requirepass != NULL) {\n        needauth = 1;\n        serverAssertWithInfo(c, NULL, rioWriteBulkCount(&cmd, '*', 2));\n        serverAssertWithInfo(c, NULL, rioWriteBulkString(&cmd, \"AUTH\", 4));\n        serverAssertWithInfo(c, NULL, rioWriteBulkString(&cmd, server.requirepass, strlen(server.requirepass)));\n    }\n\n    int selectdb = 0;\n    if (pfd->db != db) {\n        selectdb = 1;\n        serverAssertWithInfo(c, NULL, rioWriteBulkCount(&cmd, '*', 2));\n        serverAssertWithInfo(c, NULL, rioWriteBulkString(&cmd, \"SELECT\", 6));\n        serverAssertWithInfo(c, NULL, rioWriteBulkLongLong(&cmd, db));\n    }\n\n    serverAssertWithInfo(c, NULL, rioWriteBulkCount(&cmd, '*', 1 + 3 * n));\n    serverAssertWithInfo(c, NULL, rioWriteBulkString(&cmd, \"SLOTSRESTORE\", 12));\n\n    sds onekey = NULL;\n    for (int i = 0; i < n; i ++) {\n        robj *key = keys[i], *val = vals[i];\n        long long ttl = 0, expireat = getExpire(c->db, key);\n        if (expireat != -1) {\n            ttl = expireat - mstime();\n            if (ttl < 1) {\n                ttl = 1;\n            }\n        }\n        sds skey = key->ptr;\n        serverAssertWithInfo(c, NULL, rioWriteBulkString(&cmd, skey, sdslen(skey)));\n        serverAssertWithInfo(c, NULL, rioWriteBulkLongLong(&cmd, ttl));\n        do {\n            rio pld;\n            createDumpPayload(&pld, val);\n            sds buf = pld.io.buffer.ptr;\n            serverAssertWithInfo(c, NULL, rioWriteBulkString(&cmd, buf, sdslen(buf)));\n            sdsfree(buf);\n        } while (0);\n        if (onekey == NULL) {\n            onekey = skey;\n        }\n    }\n\n    do {\n        sds buf = cmd.io.buffer.ptr;\n        size_t pos = 0, towrite;\n        int nwritten = 0;\n        while ((towrite = sdslen(buf) - pos) > 0) {\n            towrite = (towrite > (64 * 1024) ? (64 * 1024) : towrite);\n            nwritten = syncWrite(pfd->fd, buf + pos, towrite, timeout);\n            if (nwritten != (signed)towrite) {\n                serverLog(LL_WARNING, \"slotsmgrt: writing to target %s:%s, error '%s', \"\n                        \"nkeys = %d, onekey = '%s', cmd.len = %ld, pos = %ld, towrite = %ld\",\n                        host, port, server.neterr, n, onekey, sdslen(buf), pos, towrite);\n                addReplySds(c, sdsnew(\"-IOERR error or timeout writing to target\\r\\n\"));\n                sdsfree(buf);\n                return -1;\n            }\n            pos += nwritten;\n        }\n        sdsfree(buf);\n    } while (0);\n\n    do {\n        char buf[1024];\n        if (needauth) {\n            if (syncReadLine(pfd->fd, buf, sizeof(buf), timeout) <= 0) {\n                serverLog(LL_WARNING, \"slotsmgrt: auth failed, reading from target %s:%s: nkeys = %d, onekey = '%s', error = '%s'\",\n                        host, port, n, onekey, server.neterr);\n                addReplySds(c, sdsnew(\"-IOERR error or timeout reading from target\\r\\n\"));\n                return -1;\n            }\n            if (buf[0] != '+') {\n                serverLog(LL_WARNING, \"slotsmgrt: auth failed, reading from target %s:%s: nkeys = %d, onekey = '%s', response = '%s'\",\n                        host, port, n, onekey, buf);\n                addReplyError(c, \"error on slotsrestore, auth failed\");\n                return -1;\n            }\n            pfd->authorized = 1;\n        }\n\n        if (selectdb) {\n            if (syncReadLine(pfd->fd, buf, sizeof(buf), timeout) <= 0) {\n                serverLog(LL_WARNING, \"slotsmgrt: select failed, reading from target %s:%s: nkeys = %d, onekey = '%s', error = '%s'\",\n                        host, port, n, onekey, server.neterr);\n                addReplySds(c, sdsnew(\"-IOERR error or timeout reading from target\\r\\n\"));\n                return -1;\n            }\n            if (buf[0] != '+') {\n                serverLog(LL_WARNING, \"slotsmgrt: select failed, reading from target %s:%s: nkeys = %d, onekey = '%s', response = '%s'\",\n                        host, port, n, onekey, buf);\n                addReplyError(c, \"error on slotsrestore, select failed\");\n                return -1;\n            }\n            pfd->db = db;\n        }\n\n        if (syncReadLine(pfd->fd, buf, sizeof(buf), timeout) <= 0) {\n            serverLog(LL_WARNING, \"slotsmgrt: migration failed, reading from target %s:%s: nkeys = %d, onekey = '%s', error = '%s'\",\n                    host, port, n, onekey, server.neterr);\n            addReplySds(c, sdsnew(\"-IOERR error or timeout reading from target\\r\\n\"));\n            return -1;\n        }\n        if (buf[0] == '-') {\n            serverLog(LL_WARNING, \"slotsmgrt: migration failed, reading from target %s:%s: nkeys = %d, onekey = '%s', response = '%s'\",\n                    host, port, n, onekey, buf);\n            addReplyError(c, \"error on slotsrestore, migration failed\");\n            return -1;\n        }\n    } while (0);\n\n    pfd->lasttime = server.unixtime;\n\n    serverLog(LL_VERBOSE, \"slotsmgrt: migrate to %s:%s, nkeys = %d, onekey = '%s'\", host, port, n, onekey);\n    return 0;\n}\n\nstatic void\nslotsremove(client *c, robj **keys, int n, int rewrite) {\n    for (int i = 0; i < n; i ++) {\n        dbDelete(c->db, keys[i]);\n        signalModifiedKey(c->db, keys[i]);\n        server.dirty ++;\n    }\n    if (!rewrite) {\n        return;\n    }\n    for (int i = 0; i < n; i ++) {\n        incrRefCount(keys[i]);\n    }\n    for (int i = 0; i < c->argc; i ++) {\n        decrRefCount(c->argv[i]);\n    }\n    zfree(c->argv);\n    c->argc = n + 1;\n    c->argv = zmalloc(sizeof(robj *) * c->argc);\n    c->argv[0] = createStringObject(\"DEL\", 3);\n    for (int i = 0; i < n; i ++) {\n        c->argv[i + 1] = keys[i];\n    }\n    c->cmd = lookupCommandOrOriginal(c->argv[0]->ptr);\n    serverAssertWithInfo(c, NULL, c->cmd != NULL);\n}\n\n/* *\n * do migrate a key-value for slotsmgrt/slotsmgrtone commands\n * return value:\n *    -1 - error happens\n *   >=0 - # of success migration (0 or 1)\n * */\nstatic int\nslotsmgrtone_command(client *c, sds host, sds port, int timeout, robj *key) {\n    slotsmgrt_sockfd *pfd = slotsmgrt_get_sockfd(c, host, port, timeout);\n    if (pfd == NULL) {\n        return -1;\n    }\n\n    robj *val = lookupKeyWrite(c->db, key);\n    if (val == NULL) {\n        return 0;\n    }\n    robj *keys[] = {key};\n    robj *vals[] = {val};\n    if (slotsmgrt(c, host, port, pfd, c->db->id, timeout, keys, vals, 1) != 0) {\n        slotsmgrt_close_socket(host, port);\n        return -1;\n    }\n    slotsremove(c, keys, 1, 1);\n    return 1;\n}\n\n/* *\n * slotsmgrtslot host port timeout slot\n * */\nvoid\nslotsmgrtslotCommand(client *c) {\n    sds host = c->argv[1]->ptr;\n    sds port = c->argv[2]->ptr;\n    int timeout, slot;\n    if (parse_timeout(c, c->argv[3], &timeout) != 0) {\n        return;\n    }\n    if (parse_slot(c, c->argv[4], &slot) != 0) {\n        return;\n    }\n\n    dict *d = c->db->hash_slots[slot];\n    int succ = 0;\n    do {\n        const dictEntry *de = dictGetRandomKey(d);\n        if (de == NULL) {\n            break;\n        }\n        sds skey = dictGetKey(de);\n        robj *key = createStringObject(skey, sdslen(skey));\n        succ = slotsmgrtone_command(c, host, port, timeout, key);\n        decrRefCount(key);\n        if (succ < 0) {\n            return;\n        }\n    } while (0);\n    addReplyMultiBulkLen(c, 2);\n    addReplyLongLong(c, succ);\n    addReplyLongLong(c, dictSize(d));\n}\n\n/* *\n * slotsmgrtone host port timeout key\n * */\nvoid\nslotsmgrtoneCommand(client *c) {\n    sds host = c->argv[1]->ptr;\n    sds port = c->argv[2]->ptr;\n    int timeout;\n    if (parse_timeout(c, c->argv[3], &timeout) != 0) {\n        return;\n    }\n\n    robj *key = c->argv[4];\n    int succ = slotsmgrtone_command(c, host, port, timeout, key);\n    if (succ < 0) {\n        return;\n    }\n    addReplyLongLong(c, succ);\n}\n\nstatic void\nslotsScanSdsKeyCallback(void *l, const dictEntry *de) {\n    sds skey = dictGetKey(de);\n    robj *key = createStringObject(skey, sdslen(skey));\n    listAddNodeTail((list *)l, key);\n}\n\n/* *\n * slotsdel slot1 [slot2 ...]\n * */\nvoid\nslotsdelCommand(client *c) {\n    int slots_slot[HASH_SLOTS_SIZE];\n    int n = 0;\n    if (c->argc <= 1) {\n        addReplyErrorFormat(c, \"wrong number of arguments for 'slotsdel' command\");\n        return;\n    }\n    int i;\n    for (i = 1; i < c->argc; i ++) {\n        int slot;\n        if (parse_slot(c, c->argv[i], &slot) != 0) {\n            return;\n        }\n        slots_slot[n] = slot;\n        n ++;\n    }\n    for (i = 0; i < n; i ++) {\n        dict *d = c->db->hash_slots[slots_slot[i]];\n        int s = dictSize(d);\n        if (s == 0) {\n            continue;\n        }\n        list *l = listCreate();\n        listSetFreeMethod(l, decrRefCountVoid);\n        unsigned long cursor = 0;\n        do {\n            cursor = dictScan(d, cursor, slotsScanSdsKeyCallback, l);\n        } while (cursor != 0);\n        while (1) {\n            listNode *head = listFirst(l);\n            if (head == NULL) {\n                break;\n            }\n            robj *key = listNodeValue(head);\n            robj *keys[] = {key};\n            slotsremove(c, keys, 1, 0);\n            listDelNode(l, head);\n        }\n        listRelease(l);\n    }\n    addReplyMultiBulkLen(c, n);\n    for (i = 0; i < n; i ++) {\n        int n = slots_slot[i];\n        int s = dictSize(c->db->hash_slots[n]);\n        addReplyMultiBulkLen(c, 2);\n        addReplyLongLong(c, n);\n        addReplyLongLong(c, s);\n    }\n}\n\n/* *\n * slotscheck\n * */\nvoid\nslotscheckCommand(client *c) {\n    sds bug = NULL;\n    int i;\n    for (i = 0; i < HASH_SLOTS_SIZE && bug == NULL; i ++) {\n        dict *d = c->db->hash_slots[i];\n        if (dictSize(d) == 0) {\n            continue;\n        }\n        list *l = listCreate();\n        listSetFreeMethod(l, decrRefCountVoid);\n        unsigned long cursor = 0;\n        do {\n            cursor = dictScan(d, cursor, slotsScanSdsKeyCallback, l);\n            while (1) {\n                listNode *head = listFirst(l);\n                if (head == NULL) {\n                    break;\n                }\n                robj *key = listNodeValue(head);\n                if (lookupKeyRead(c->db, key) == NULL) {\n                    if (bug == NULL) {\n                        bug = sdsdup(key->ptr);\n                    }\n                }\n                listDelNode(l, head);\n            }\n        } while (cursor != 0 && bug == NULL);\n        listRelease(l);\n    }\n    if (bug != NULL) {\n        addReplyErrorFormat(c, \"step 1, miss = '%s'\", bug);\n        sdsfree(bug);\n        return;\n    }\n    do {\n        dict *d = c->db->dict;\n        if (dictSize(d) == 0) {\n            break;\n        }\n        list *l = listCreate();\n        listSetFreeMethod(l, decrRefCountVoid);\n        unsigned long cursor = 0;\n        do {\n            cursor = dictScan(d, cursor, slotsScanSdsKeyCallback, l);\n            while (1) {\n                listNode *head = listFirst(l);\n                if (head == NULL) {\n                    break;\n                }\n                robj *key = listNodeValue(head);\n                int slot = slots_num(key->ptr, NULL, NULL);\n                if (dictFind(c->db->hash_slots[slot], key->ptr) == NULL) {\n                    if (bug == NULL) {\n                        bug = sdsdup(key->ptr);\n                    }\n                }\n                listDelNode(l, head);\n            }\n        } while (cursor != 0 && bug == NULL);\n        listRelease(l);\n    } while (0);\n    if (bug != NULL) {\n        addReplyErrorFormat(c, \"step 2, miss = '%s'\", bug);\n        sdsfree(bug);\n        return;\n    }\n    zskiplistNode *node = c->db->tagged_keys->header->level[0].forward;\n    while (node != NULL && bug == NULL) {\n        if (lookupKeyRead(c->db, node->obj) == NULL) {\n            bug = sdsdup(node->obj->ptr);\n        }\n        node = node->level[0].forward;\n    }\n    if (bug != NULL) {\n        addReplyErrorFormat(c, \"step 3, miss = '%s'\", bug);\n        sdsfree(bug);\n        return;\n    }\n    addReply(c, shared.ok);\n}\n\n/* *\n * slotsrestore key ttl val [key ttl val ...]\n * */\nvoid\nslotsrestoreCommand(client *c) {\n    if (c->argc < 4 || (c->argc - 1) % 3 != 0) {\n        addReplyErrorFormat(c, \"wrong number of arguments for 'slotsrestore' command\");\n        return;\n    }\n    int n = (c->argc - 1) / 3;\n\n    long long *ttls = zmalloc(sizeof(long long) * n);\n    robj **vals = zmalloc(sizeof(robj *) * n);\n    for (int i = 0; i < n; i ++) {\n        vals[i] = NULL;\n    }\n\n    for (int i = 0; i < n; i ++) {\n        robj *key = c->argv[i * 3 + 1];\n        robj *ttl = c->argv[i * 3 + 2];\n        robj *val = c->argv[i * 3 + 3];\n        if (lookupKeyWrite(c->db, key) != NULL) {\n            serverLog(LL_WARNING, \"slotsrestore: slot = %d, key = '%s' already exists\",\n                    slots_num(key->ptr, NULL, NULL), (char *)key->ptr);\n        }\n        if (getLongLongFromObjectOrReply(c, ttl, &ttls[i], NULL) != C_OK) {\n            goto cleanup;\n        } else if (ttls[i] < 0) {\n            addReplyError(c, \"invalid ttl value, must be >= 0\");\n            goto cleanup;\n        }\n        rio payload;\n        int type;\n        if (verifyDumpPayload(val->ptr, sdslen(val->ptr)) != C_OK) {\n            addReplyError(c, \"dump payload version or checksum are wrong\");\n            goto cleanup;\n        }\n        rioInitWithBuffer(&payload, val->ptr);\n        if (((type = rdbLoadObjectType(&payload)) == -1) ||\n                ((vals[i] = rdbLoadObject(type, &payload)) == NULL)) {\n            addReplyError(c, \"bad data format\");\n            goto cleanup;\n        }\n    }\n\n    for (int i = 0; i < n; i ++) {\n        robj *key = c->argv[i * 3 + 1];\n        long long ttl = ttls[i];\n        robj *val = vals[i];\n        dbDelete(c->db, key);\n        dbAdd(c->db, key, val);\n        incrRefCount(val);\n        if (ttl) {\n            setExpire(c->db, key, mstime() + ttl);\n        }\n        signalModifiedKey(c->db, key);\n        server.dirty ++;\n    }\n    addReply(c, shared.ok);\n\ncleanup:\n    for (int i = 0; i < n; i ++) {\n        if (vals[i] != NULL) {\n            decrRefCount(vals[i]);\n        }\n    }\n    zfree(vals);\n    zfree(ttls);\n}\n\n/* *\n * do migrate mutli key-value(s) for {slotsmgrt/slotsmgrtone}with tag commands\n * return value:\n *    -1 - error happens\n *   >=0 - # of success migration\n * */\nstatic int\nslotsmgrttag_command(client *c, sds host, sds port, int timeout, robj *key) {\n    uint32_t crc;\n    int hastag;\n    int slot = slots_num(key->ptr, &crc, &hastag);\n    if (!hastag) {\n        return slotsmgrtone_command(c, host, port, timeout, key);\n    }\n\n    slotsmgrt_sockfd *pfd = slotsmgrt_get_sockfd(c, host, port, timeout);\n    if (pfd == NULL) {\n        return -1;\n    }\n\n    dict *d = c->db->hash_slots[slot];\n    if (dictSize(d) == 0) {\n        return 0;\n    }\n\n    zrangespec range;\n    range.min = (double)crc;\n    range.minex = 0;\n    range.max = (double)crc;\n    range.maxex = 0;\n\n    list *l = listCreate();\n    listSetFreeMethod(l, decrRefCountVoid);\n\n    zskiplistNode *node = zslFirstInRange(c->db->tagged_keys, &range);\n    while (node != NULL && node->score == (double)crc) {\n        listAddNodeTail(l, node->obj);\n        incrRefCount(node->obj);\n        node = node->level[0].forward;\n    }\n\n    int max = listLength(l);\n    if (max == 0) {\n        listRelease(l);\n        return 0;\n    }\n\n    robj **keys = zmalloc(sizeof(robj *) * max);\n    robj **vals = zmalloc(sizeof(robj *) * max);\n\n    int n = 0;\n    for (int i = 0; i < max; i ++) {\n        listNode *head = listFirst(l);\n        robj *key = listNodeValue(head);\n        robj *val = lookupKeyWrite(c->db, key);\n        if (val != NULL) {\n            keys[n] = key;\n            vals[n] = val;\n            n ++;\n            incrRefCount(key);\n            incrRefCount(val);\n        }\n        listDelNode(l, head);\n    }\n\n    int ret = 0;\n    if (n != 0) {\n        if (slotsmgrt(c, host, port, pfd, c->db->id, timeout, keys, vals, n) != 0) {\n            slotsmgrt_close_socket(host, port);\n            ret = -1;\n        } else {\n            slotsremove(c, keys, n, 1);\n            ret = n;\n        }\n    }\n\n    listRelease(l);\n    for (int i = 0; i < n; i ++) {\n        decrRefCount(keys[i]);\n        decrRefCount(vals[i]);\n    }\n    zfree(keys);\n    zfree(vals);\n    return ret;\n}\n\n/* *\n * slotsmgrttagslot host port timeout slot\n * */\nvoid\nslotsmgrttagslotCommand(client *c) {\n    sds host = c->argv[1]->ptr;\n    sds port = c->argv[2]->ptr;\n    int timeout, slot;\n    if (parse_timeout(c, c->argv[3], &timeout) != 0) {\n        return;\n    }\n    if (parse_slot(c, c->argv[4], &slot) != 0) {\n        return;\n    }\n\n    dict *d = c->db->hash_slots[slot];\n    int succ = 0;\n    do {\n        const dictEntry *de = dictGetRandomKey(d);\n        if (de == NULL) {\n            break;\n        }\n        sds skey = dictGetKey(de);\n        robj *key = createStringObject(skey, sdslen(skey));\n        succ = slotsmgrttag_command(c, host, port, timeout, key);\n        decrRefCount(key);\n        if (succ < 0) {\n            return;\n        }\n    } while (0);\n    addReplyMultiBulkLen(c, 2);\n    addReplyLongLong(c, succ);\n    addReplyLongLong(c, dictSize(d));\n}\n\n/* *\n * slotsmgrttagone host port timeout key\n * */\nvoid\nslotsmgrttagoneCommand(client *c) {\n    sds host = c->argv[1]->ptr;\n    sds port = c->argv[2]->ptr;\n    int timeout;\n    if (parse_timeout(c, c->argv[3], &timeout) != 0) {\n        return;\n    }\n\n    robj *key = c->argv[4];\n    int succ = slotsmgrttag_command(c, host, port, timeout, key);\n    if (succ < 0) {\n        return;\n    }\n    addReplyLongLong(c, succ);\n}\n\n/* *\n * slotsscan slotnum cursor [COUNT count]\n * */\nvoid\nslotsscanCommand(client *c) {\n    int slot;\n    if (parse_slot(c, c->argv[1], &slot) != 0) {\n        return;\n    }\n    unsigned long cursor;\n    if (parseScanCursorOrReply(c, c->argv[2], &cursor) == C_ERR) {\n        return;\n    }\n    unsigned long count = 10;\n    if (c->argc != 3 && c->argc != 5) {\n        addReplyErrorFormat(c, \"wrong number of arguments for 'slotsscan' command\");\n        return;\n    }\n    if (c->argc == 5) {\n        if (strcasecmp(c->argv[3]->ptr, \"count\") != 0) {\n            addReply(c, shared.syntaxerr);\n            return;\n        }\n        int v;\n        if (parse_int(c, c->argv[4], &v) != 0) {\n            return;\n        }\n        if (v < 1) {\n            addReply(c, shared.syntaxerr);\n            return;\n        }\n        count = v;\n    }\n    dict *d = c->db->hash_slots[slot];\n    list *l = listCreate();\n    listSetFreeMethod(l, decrRefCountVoid);\n\n    long loops = count * 10;\n    do {\n        cursor = dictScan(d, cursor, slotsScanSdsKeyCallback, l);\n        loops --;\n    } while (cursor != 0 && loops > 0 && listLength(l) < count);\n\n    addReplyMultiBulkLen(c, 2);\n    addReplyBulkLongLong(c, cursor);\n\n    addReplyMultiBulkLen(c, listLength(l));\n    while (1) {\n        listNode *head = listFirst(l);\n        if (head == NULL) {\n            break;\n        }\n        robj *key = listNodeValue(head);\n        addReplyBulk(c, key);\n        listDelNode(l, head);\n    }\n\n    listRelease(l);\n}\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/src/slowlog.c",
    "content": "/* Slowlog implements a system that is able to remember the latest N\n * queries that took more than M microseconds to execute.\n *\n * The execution time to reach to be logged in the slow log is set\n * using the 'slowlog-log-slower-than' config directive, that is also\n * readable and writable using the CONFIG SET/GET command.\n *\n * The slow queries log is actually not \"logged\" in the Redis log file\n * but is accessible thanks to the SLOWLOG command.\n *\n * ----------------------------------------------------------------------------\n *\n * Copyright (c) 2009-2012, Salvatore Sanfilippo <antirez at gmail dot com>\n * All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions are met:\n *\n *   * Redistributions of source code must retain the above copyright notice,\n *     this list of conditions and the following disclaimer.\n *   * Redistributions in binary form must reproduce the above copyright\n *     notice, this list of conditions and the following disclaimer in the\n *     documentation and/or other materials provided with the distribution.\n *   * Neither the name of Redis nor the names of its contributors may be used\n *     to endorse or promote products derived from this software without\n *     specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\"\n * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\n * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE\n * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR\n * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF\n * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS\n * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN\n * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)\n * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE\n * POSSIBILITY OF SUCH DAMAGE.\n */\n\n\n#include \"server.h\"\n#include \"slowlog.h\"\n\n/* Create a new slowlog entry.\n * Incrementing the ref count of all the objects retained is up to\n * this function. */\nslowlogEntry *slowlogCreateEntry(robj **argv, int argc, long long duration) {\n    slowlogEntry *se = zmalloc(sizeof(*se));\n    int j, slargc = argc;\n\n    if (slargc > SLOWLOG_ENTRY_MAX_ARGC) slargc = SLOWLOG_ENTRY_MAX_ARGC;\n    se->argc = slargc;\n    se->argv = zmalloc(sizeof(robj*)*slargc);\n    for (j = 0; j < slargc; j++) {\n        /* Logging too many arguments is a useless memory waste, so we stop\n         * at SLOWLOG_ENTRY_MAX_ARGC, but use the last argument to specify\n         * how many remaining arguments there were in the original command. */\n        if (slargc != argc && j == slargc-1) {\n            se->argv[j] = createObject(OBJ_STRING,\n                sdscatprintf(sdsempty(),\"... (%d more arguments)\",\n                argc-slargc+1));\n        } else {\n            /* Trim too long strings as well... */\n            if (argv[j]->type == OBJ_STRING &&\n                sdsEncodedObject(argv[j]) &&\n                sdslen(argv[j]->ptr) > SLOWLOG_ENTRY_MAX_STRING)\n            {\n                sds s = sdsnewlen(argv[j]->ptr, SLOWLOG_ENTRY_MAX_STRING);\n\n                s = sdscatprintf(s,\"... (%lu more bytes)\",\n                    (unsigned long)\n                    sdslen(argv[j]->ptr) - SLOWLOG_ENTRY_MAX_STRING);\n                se->argv[j] = createObject(OBJ_STRING,s);\n            } else {\n                se->argv[j] = argv[j];\n                incrRefCount(argv[j]);\n            }\n        }\n    }\n    se->time = time(NULL);\n    se->duration = duration;\n    se->id = server.slowlog_entry_id++;\n    return se;\n}\n\n/* Free a slow log entry. The argument is void so that the prototype of this\n * function matches the one of the 'free' method of adlist.c.\n *\n * This function will take care to release all the retained object. */\nvoid slowlogFreeEntry(void *septr) {\n    slowlogEntry *se = septr;\n    int j;\n\n    for (j = 0; j < se->argc; j++)\n        decrRefCount(se->argv[j]);\n    zfree(se->argv);\n    zfree(se);\n}\n\n/* Initialize the slow log. This function should be called a single time\n * at server startup. */\nvoid slowlogInit(void) {\n    server.slowlog = listCreate();\n    server.slowlog_entry_id = 0;\n    listSetFreeMethod(server.slowlog,slowlogFreeEntry);\n}\n\n/* Push a new entry into the slow log.\n * This function will make sure to trim the slow log accordingly to the\n * configured max length. */\nvoid slowlogPushEntryIfNeeded(robj **argv, int argc, long long duration) {\n    if (server.slowlog_log_slower_than < 0) return; /* Slowlog disabled */\n    if (duration >= server.slowlog_log_slower_than)\n        listAddNodeHead(server.slowlog,slowlogCreateEntry(argv,argc,duration));\n\n    /* Remove old entries if needed. */\n    while (listLength(server.slowlog) > server.slowlog_max_len)\n        listDelNode(server.slowlog,listLast(server.slowlog));\n}\n\n/* Remove all the entries from the current slow log. */\nvoid slowlogReset(void) {\n    while (listLength(server.slowlog) > 0)\n        listDelNode(server.slowlog,listLast(server.slowlog));\n}\n\n/* The SLOWLOG command. Implements all the subcommands needed to handle the\n * Redis slow log. */\nvoid slowlogCommand(client *c) {\n    if (c->argc == 2 && !strcasecmp(c->argv[1]->ptr,\"reset\")) {\n        slowlogReset();\n        addReply(c,shared.ok);\n    } else if (c->argc == 2 && !strcasecmp(c->argv[1]->ptr,\"len\")) {\n        addReplyLongLong(c,listLength(server.slowlog));\n    } else if ((c->argc == 2 || c->argc == 3) &&\n               !strcasecmp(c->argv[1]->ptr,\"get\"))\n    {\n        long count = 10, sent = 0;\n        listIter li;\n        void *totentries;\n        listNode *ln;\n        slowlogEntry *se;\n\n        if (c->argc == 3 &&\n            getLongFromObjectOrReply(c,c->argv[2],&count,NULL) != C_OK)\n            return;\n\n        listRewind(server.slowlog,&li);\n        totentries = addDeferredMultiBulkLength(c);\n        while(count-- && (ln = listNext(&li))) {\n            int j;\n\n            se = ln->value;\n            addReplyMultiBulkLen(c,4);\n            addReplyLongLong(c,se->id);\n            addReplyLongLong(c,se->time);\n            addReplyLongLong(c,se->duration);\n            addReplyMultiBulkLen(c,se->argc);\n            for (j = 0; j < se->argc; j++)\n                addReplyBulk(c,se->argv[j]);\n            sent++;\n        }\n        setDeferredMultiBulkLength(c,totentries,sent);\n    } else {\n        addReplyError(c,\n            \"Unknown SLOWLOG subcommand or wrong # of args. Try GET, RESET, LEN.\");\n    }\n}\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/src/slowlog.h",
    "content": "/*\n * Copyright (c) 2009-2012, Salvatore Sanfilippo <antirez at gmail dot com>\n * All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions are met:\n *\n *   * Redistributions of source code must retain the above copyright notice,\n *     this list of conditions and the following disclaimer.\n *   * Redistributions in binary form must reproduce the above copyright\n *     notice, this list of conditions and the following disclaimer in the\n *     documentation and/or other materials provided with the distribution.\n *   * Neither the name of Redis nor the names of its contributors may be used\n *     to endorse or promote products derived from this software without\n *     specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\"\n * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\n * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE\n * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR\n * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF\n * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS\n * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN\n * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)\n * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE\n * POSSIBILITY OF SUCH DAMAGE.\n */\n\n#define SLOWLOG_ENTRY_MAX_ARGC 32\n#define SLOWLOG_ENTRY_MAX_STRING 128\n\n/* This structure defines an entry inside the slow log list */\ntypedef struct slowlogEntry {\n    robj **argv;\n    int argc;\n    long long id;       /* Unique entry identifier. */\n    long long duration; /* Time spent by the query, in nanoseconds. */\n    time_t time;        /* Unix time at which the query was executed. */\n} slowlogEntry;\n\n/* Exported API */\nvoid slowlogInit(void);\nvoid slowlogPushEntryIfNeeded(robj **argv, int argc, long long duration);\n\n/* Exported commands */\nvoid slowlogCommand(client *c);\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/src/solarisfixes.h",
    "content": "/* Solaris specific fixes.\n *\n * Copyright (c) 2009-2012, Salvatore Sanfilippo <antirez at gmail dot com>\n * All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions are met:\n *\n *   * Redistributions of source code must retain the above copyright notice,\n *     this list of conditions and the following disclaimer.\n *   * Redistributions in binary form must reproduce the above copyright\n *     notice, this list of conditions and the following disclaimer in the\n *     documentation and/or other materials provided with the distribution.\n *   * Neither the name of Redis nor the names of its contributors may be used\n *     to endorse or promote products derived from this software without\n *     specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\"\n * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\n * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE\n * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR\n * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF\n * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS\n * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN\n * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)\n * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE\n * POSSIBILITY OF SUCH DAMAGE.\n */\n\n#if defined(__sun)\n\n#if defined(__GNUC__)\n#include <math.h>\n#undef isnan\n#define isnan(x) \\\n     __extension__({ __typeof (x) __x_a = (x); \\\n     __builtin_expect(__x_a != __x_a, 0); })\n\n#undef isfinite\n#define isfinite(x) \\\n     __extension__ ({ __typeof (x) __x_f = (x); \\\n     __builtin_expect(!isnan(__x_f - __x_f), 1); })\n\n#undef isinf\n#define isinf(x) \\\n     __extension__ ({ __typeof (x) __x_i = (x); \\\n     __builtin_expect(!isnan(__x_i) && !isfinite(__x_i), 0); })\n\n#define u_int uint\n#define u_int32_t uint32_t\n#endif /* __GNUC__ */\n\n#endif /* __sun */\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/src/sort.c",
    "content": "/* SORT command and helper functions.\n *\n * Copyright (c) 2009-2012, Salvatore Sanfilippo <antirez at gmail dot com>\n * All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions are met:\n *\n *   * Redistributions of source code must retain the above copyright notice,\n *     this list of conditions and the following disclaimer.\n *   * Redistributions in binary form must reproduce the above copyright\n *     notice, this list of conditions and the following disclaimer in the\n *     documentation and/or other materials provided with the distribution.\n *   * Neither the name of Redis nor the names of its contributors may be used\n *     to endorse or promote products derived from this software without\n *     specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\"\n * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\n * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE\n * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR\n * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF\n * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS\n * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN\n * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)\n * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE\n * POSSIBILITY OF SUCH DAMAGE.\n */\n\n\n#include \"server.h\"\n#include \"pqsort.h\" /* Partial qsort for SORT+LIMIT */\n#include <math.h> /* isnan() */\n\nzskiplistNode* zslGetElementByRank(zskiplist *zsl, unsigned long rank);\n\nredisSortOperation *createSortOperation(int type, robj *pattern) {\n    redisSortOperation *so = zmalloc(sizeof(*so));\n    so->type = type;\n    so->pattern = pattern;\n    return so;\n}\n\n/* Return the value associated to the key with a name obtained using\n * the following rules:\n *\n * 1) The first occurrence of '*' in 'pattern' is substituted with 'subst'.\n *\n * 2) If 'pattern' matches the \"->\" string, everything on the left of\n *    the arrow is treated as the name of a hash field, and the part on the\n *    left as the key name containing a hash. The value of the specified\n *    field is returned.\n *\n * 3) If 'pattern' equals \"#\", the function simply returns 'subst' itself so\n *    that the SORT command can be used like: SORT key GET # to retrieve\n *    the Set/List elements directly.\n *\n * The returned object will always have its refcount increased by 1\n * when it is non-NULL. */\nrobj *lookupKeyByPattern(redisDb *db, robj *pattern, robj *subst) {\n    char *p, *f, *k;\n    sds spat, ssub;\n    robj *keyobj, *fieldobj = NULL, *o;\n    int prefixlen, sublen, postfixlen, fieldlen;\n\n    /* If the pattern is \"#\" return the substitution object itself in order\n     * to implement the \"SORT ... GET #\" feature. */\n    spat = pattern->ptr;\n    if (spat[0] == '#' && spat[1] == '\\0') {\n        incrRefCount(subst);\n        return subst;\n    }\n\n    /* The substitution object may be specially encoded. If so we create\n     * a decoded object on the fly. Otherwise getDecodedObject will just\n     * increment the ref count, that we'll decrement later. */\n    subst = getDecodedObject(subst);\n    ssub = subst->ptr;\n\n    /* If we can't find '*' in the pattern we return NULL as to GET a\n     * fixed key does not make sense. */\n    p = strchr(spat,'*');\n    if (!p) {\n        decrRefCount(subst);\n        return NULL;\n    }\n\n    /* Find out if we're dealing with a hash dereference. */\n    if ((f = strstr(p+1, \"->\")) != NULL && *(f+2) != '\\0') {\n        fieldlen = sdslen(spat)-(f-spat)-2;\n        fieldobj = createStringObject(f+2,fieldlen);\n    } else {\n        fieldlen = 0;\n    }\n\n    /* Perform the '*' substitution. */\n    prefixlen = p-spat;\n    sublen = sdslen(ssub);\n    postfixlen = sdslen(spat)-(prefixlen+1)-(fieldlen ? fieldlen+2 : 0);\n    keyobj = createStringObject(NULL,prefixlen+sublen+postfixlen);\n    k = keyobj->ptr;\n    memcpy(k,spat,prefixlen);\n    memcpy(k+prefixlen,ssub,sublen);\n    memcpy(k+prefixlen+sublen,p+1,postfixlen);\n    decrRefCount(subst); /* Incremented by decodeObject() */\n\n    /* Lookup substituted key */\n    o = lookupKeyRead(db,keyobj);\n    if (o == NULL) goto noobj;\n\n    if (fieldobj) {\n        if (o->type != OBJ_HASH) goto noobj;\n\n        /* Retrieve value from hash by the field name. This operation\n         * already increases the refcount of the returned object. */\n        o = hashTypeGetObject(o, fieldobj);\n    } else {\n        if (o->type != OBJ_STRING) goto noobj;\n\n        /* Every object that this function returns needs to have its refcount\n         * increased. sortCommand decreases it again. */\n        incrRefCount(o);\n    }\n    decrRefCount(keyobj);\n    if (fieldobj) decrRefCount(fieldobj);\n    return o;\n\nnoobj:\n    decrRefCount(keyobj);\n    if (fieldlen) decrRefCount(fieldobj);\n    return NULL;\n}\n\n/* sortCompare() is used by qsort in sortCommand(). Given that qsort_r with\n * the additional parameter is not standard but a BSD-specific we have to\n * pass sorting parameters via the global 'server' structure */\nint sortCompare(const void *s1, const void *s2) {\n    const redisSortObject *so1 = s1, *so2 = s2;\n    int cmp;\n\n    if (!server.sort_alpha) {\n        /* Numeric sorting. Here it's trivial as we precomputed scores */\n        if (so1->u.score > so2->u.score) {\n            cmp = 1;\n        } else if (so1->u.score < so2->u.score) {\n            cmp = -1;\n        } else {\n            /* Objects have the same score, but we don't want the comparison\n             * to be undefined, so we compare objects lexicographically.\n             * This way the result of SORT is deterministic. */\n            cmp = compareStringObjects(so1->obj,so2->obj);\n        }\n    } else {\n        /* Alphanumeric sorting */\n        if (server.sort_bypattern) {\n            if (!so1->u.cmpobj || !so2->u.cmpobj) {\n                /* At least one compare object is NULL */\n                if (so1->u.cmpobj == so2->u.cmpobj)\n                    cmp = 0;\n                else if (so1->u.cmpobj == NULL)\n                    cmp = -1;\n                else\n                    cmp = 1;\n            } else {\n                /* We have both the objects, compare them. */\n                if (server.sort_store) {\n                    cmp = compareStringObjects(so1->u.cmpobj,so2->u.cmpobj);\n                } else {\n                    /* Here we can use strcoll() directly as we are sure that\n                     * the objects are decoded string objects. */\n                    cmp = strcoll(so1->u.cmpobj->ptr,so2->u.cmpobj->ptr);\n                }\n            }\n        } else {\n            /* Compare elements directly. */\n            if (server.sort_store) {\n                cmp = compareStringObjects(so1->obj,so2->obj);\n            } else {\n                cmp = collateStringObjects(so1->obj,so2->obj);\n            }\n        }\n    }\n    return server.sort_desc ? -cmp : cmp;\n}\n\n/* The SORT command is the most complex command in Redis. Warning: this code\n * is optimized for speed and a bit less for readability */\nvoid sortCommand(client *c) {\n    list *operations;\n    unsigned int outputlen = 0;\n    int desc = 0, alpha = 0;\n    long limit_start = 0, limit_count = -1, start, end;\n    int j, dontsort = 0, vectorlen;\n    int getop = 0; /* GET operation counter */\n    int int_convertion_error = 0;\n    int syntax_error = 0;\n    robj *sortval, *sortby = NULL, *storekey = NULL;\n    redisSortObject *vector; /* Resulting vector to sort */\n\n    /* Lookup the key to sort. It must be of the right types */\n    sortval = lookupKeyRead(c->db,c->argv[1]);\n    if (sortval && sortval->type != OBJ_SET &&\n                   sortval->type != OBJ_LIST &&\n                   sortval->type != OBJ_ZSET)\n    {\n        addReply(c,shared.wrongtypeerr);\n        return;\n    }\n\n    /* Create a list of operations to perform for every sorted element.\n     * Operations can be GET */\n    operations = listCreate();\n    listSetFreeMethod(operations,zfree);\n    j = 2; /* options start at argv[2] */\n\n    /* Now we need to protect sortval incrementing its count, in the future\n     * SORT may have options able to overwrite/delete keys during the sorting\n     * and the sorted key itself may get destroyed */\n    if (sortval)\n        incrRefCount(sortval);\n    else\n        sortval = createQuicklistObject();\n\n    /* The SORT command has an SQL-alike syntax, parse it */\n    while(j < c->argc) {\n        int leftargs = c->argc-j-1;\n        if (!strcasecmp(c->argv[j]->ptr,\"asc\")) {\n            desc = 0;\n        } else if (!strcasecmp(c->argv[j]->ptr,\"desc\")) {\n            desc = 1;\n        } else if (!strcasecmp(c->argv[j]->ptr,\"alpha\")) {\n            alpha = 1;\n        } else if (!strcasecmp(c->argv[j]->ptr,\"limit\") && leftargs >= 2) {\n            if ((getLongFromObjectOrReply(c, c->argv[j+1], &limit_start, NULL)\n                 != C_OK) ||\n                (getLongFromObjectOrReply(c, c->argv[j+2], &limit_count, NULL)\n                 != C_OK))\n            {\n                syntax_error++;\n                break;\n            }\n            j+=2;\n        } else if (!strcasecmp(c->argv[j]->ptr,\"store\") && leftargs >= 1) {\n            storekey = c->argv[j+1];\n            j++;\n        } else if (!strcasecmp(c->argv[j]->ptr,\"by\") && leftargs >= 1) {\n            sortby = c->argv[j+1];\n            /* If the BY pattern does not contain '*', i.e. it is constant,\n             * we don't need to sort nor to lookup the weight keys. */\n            if (strchr(c->argv[j+1]->ptr,'*') == NULL) {\n                dontsort = 1;\n            } else {\n                /* If BY is specified with a real patter, we can't accept\n                 * it in cluster mode. */\n                if (server.cluster_enabled) {\n                    addReplyError(c,\"BY option of SORT denied in Cluster mode.\");\n                    syntax_error++;\n                    break;\n                }\n            }\n            j++;\n        } else if (!strcasecmp(c->argv[j]->ptr,\"get\") && leftargs >= 1) {\n            if (server.cluster_enabled) {\n                addReplyError(c,\"GET option of SORT denied in Cluster mode.\");\n                syntax_error++;\n                break;\n            }\n            listAddNodeTail(operations,createSortOperation(\n                SORT_OP_GET,c->argv[j+1]));\n            getop++;\n            j++;\n        } else {\n            addReply(c,shared.syntaxerr);\n            syntax_error++;\n            break;\n        }\n        j++;\n    }\n\n    /* Handle syntax errors set during options parsing. */\n    if (syntax_error) {\n        decrRefCount(sortval);\n        listRelease(operations);\n        return;\n    }\n\n    /* When sorting a set with no sort specified, we must sort the output\n     * so the result is consistent across scripting and replication.\n     *\n     * The other types (list, sorted set) will retain their native order\n     * even if no sort order is requested, so they remain stable across\n     * scripting and replication. */\n    if (dontsort &&\n        sortval->type == OBJ_SET &&\n        (storekey || c->flags & CLIENT_LUA))\n    {\n        /* Force ALPHA sorting */\n        dontsort = 0;\n        alpha = 1;\n        sortby = NULL;\n    }\n\n    /* Destructively convert encoded sorted sets for SORT. */\n    if (sortval->type == OBJ_ZSET)\n        zsetConvert(sortval, OBJ_ENCODING_SKIPLIST);\n\n    /* Objtain the length of the object to sort. */\n    switch(sortval->type) {\n    case OBJ_LIST: vectorlen = listTypeLength(sortval); break;\n    case OBJ_SET: vectorlen =  setTypeSize(sortval); break;\n    case OBJ_ZSET: vectorlen = dictSize(((zset*)sortval->ptr)->dict); break;\n    default: vectorlen = 0; serverPanic(\"Bad SORT type\"); /* Avoid GCC warning */\n    }\n\n    /* Perform LIMIT start,count sanity checking. */\n    start = (limit_start < 0) ? 0 : limit_start;\n    end = (limit_count < 0) ? vectorlen-1 : start+limit_count-1;\n    if (start >= vectorlen) {\n        start = vectorlen-1;\n        end = vectorlen-2;\n    }\n    if (end >= vectorlen) end = vectorlen-1;\n\n    /* Whenever possible, we load elements into the output array in a more\n     * direct way. This is possible if:\n     *\n     * 1) The object to sort is a sorted set or a list (internally sorted).\n     * 2) There is nothing to sort as dontsort is true (BY <constant string>).\n     *\n     * In this special case, if we have a LIMIT option that actually reduces\n     * the number of elements to fetch, we also optimize to just load the\n     * range we are interested in and allocating a vector that is big enough\n     * for the selected range length. */\n    if ((sortval->type == OBJ_ZSET || sortval->type == OBJ_LIST) &&\n        dontsort &&\n        (start != 0 || end != vectorlen-1))\n    {\n        vectorlen = end-start+1;\n    }\n\n    /* Load the sorting vector with all the objects to sort */\n    vector = zmalloc(sizeof(redisSortObject)*vectorlen);\n    j = 0;\n\n    if (sortval->type == OBJ_LIST && dontsort) {\n        /* Special handling for a list, if 'dontsort' is true.\n         * This makes sure we return elements in the list original\n         * ordering, accordingly to DESC / ASC options.\n         *\n         * Note that in this case we also handle LIMIT here in a direct\n         * way, just getting the required range, as an optimization. */\n        if (end >= start) {\n            listTypeIterator *li;\n            listTypeEntry entry;\n            li = listTypeInitIterator(sortval,\n                    desc ? (long)(listTypeLength(sortval) - start - 1) : start,\n                    desc ? LIST_HEAD : LIST_TAIL);\n\n            while(j < vectorlen && listTypeNext(li,&entry)) {\n                vector[j].obj = listTypeGet(&entry);\n                vector[j].u.score = 0;\n                vector[j].u.cmpobj = NULL;\n                j++;\n            }\n            listTypeReleaseIterator(li);\n            /* Fix start/end: output code is not aware of this optimization. */\n            end -= start;\n            start = 0;\n        }\n    } else if (sortval->type == OBJ_LIST) {\n        listTypeIterator *li = listTypeInitIterator(sortval,0,LIST_TAIL);\n        listTypeEntry entry;\n        while(listTypeNext(li,&entry)) {\n            vector[j].obj = listTypeGet(&entry);\n            vector[j].u.score = 0;\n            vector[j].u.cmpobj = NULL;\n            j++;\n        }\n        listTypeReleaseIterator(li);\n    } else if (sortval->type == OBJ_SET) {\n        setTypeIterator *si = setTypeInitIterator(sortval);\n        robj *ele;\n        while((ele = setTypeNextObject(si)) != NULL) {\n            vector[j].obj = ele;\n            vector[j].u.score = 0;\n            vector[j].u.cmpobj = NULL;\n            j++;\n        }\n        setTypeReleaseIterator(si);\n    } else if (sortval->type == OBJ_ZSET && dontsort) {\n        /* Special handling for a sorted set, if 'dontsort' is true.\n         * This makes sure we return elements in the sorted set original\n         * ordering, accordingly to DESC / ASC options.\n         *\n         * Note that in this case we also handle LIMIT here in a direct\n         * way, just getting the required range, as an optimization. */\n\n        zset *zs = sortval->ptr;\n        zskiplist *zsl = zs->zsl;\n        zskiplistNode *ln;\n        robj *ele;\n        int rangelen = vectorlen;\n\n        /* Check if starting point is trivial, before doing log(N) lookup. */\n        if (desc) {\n            long zsetlen = dictSize(((zset*)sortval->ptr)->dict);\n\n            ln = zsl->tail;\n            if (start > 0)\n                ln = zslGetElementByRank(zsl,zsetlen-start);\n        } else {\n            ln = zsl->header->level[0].forward;\n            if (start > 0)\n                ln = zslGetElementByRank(zsl,start+1);\n        }\n\n        while(rangelen--) {\n            serverAssertWithInfo(c,sortval,ln != NULL);\n            ele = ln->obj;\n            vector[j].obj = ele;\n            vector[j].u.score = 0;\n            vector[j].u.cmpobj = NULL;\n            j++;\n            ln = desc ? ln->backward : ln->level[0].forward;\n        }\n        /* Fix start/end: output code is not aware of this optimization. */\n        end -= start;\n        start = 0;\n    } else if (sortval->type == OBJ_ZSET) {\n        dict *set = ((zset*)sortval->ptr)->dict;\n        dictIterator *di;\n        dictEntry *setele;\n        di = dictGetIterator(set);\n        while((setele = dictNext(di)) != NULL) {\n            vector[j].obj = dictGetKey(setele);\n            vector[j].u.score = 0;\n            vector[j].u.cmpobj = NULL;\n            j++;\n        }\n        dictReleaseIterator(di);\n    } else {\n        serverPanic(\"Unknown type\");\n    }\n    serverAssertWithInfo(c,sortval,j == vectorlen);\n\n    /* Now it's time to load the right scores in the sorting vector */\n    if (dontsort == 0) {\n        for (j = 0; j < vectorlen; j++) {\n            robj *byval;\n            if (sortby) {\n                /* lookup value to sort by */\n                byval = lookupKeyByPattern(c->db,sortby,vector[j].obj);\n                if (!byval) continue;\n            } else {\n                /* use object itself to sort by */\n                byval = vector[j].obj;\n            }\n\n            if (alpha) {\n                if (sortby) vector[j].u.cmpobj = getDecodedObject(byval);\n            } else {\n                if (sdsEncodedObject(byval)) {\n                    char *eptr;\n\n                    vector[j].u.score = strtod(byval->ptr,&eptr);\n                    if (eptr[0] != '\\0' || errno == ERANGE ||\n                        isnan(vector[j].u.score))\n                    {\n                        int_convertion_error = 1;\n                    }\n                } else if (byval->encoding == OBJ_ENCODING_INT) {\n                    /* Don't need to decode the object if it's\n                     * integer-encoded (the only encoding supported) so\n                     * far. We can just cast it */\n                    vector[j].u.score = (long)byval->ptr;\n                } else {\n                    serverAssertWithInfo(c,sortval,1 != 1);\n                }\n            }\n\n            /* when the object was retrieved using lookupKeyByPattern,\n             * its refcount needs to be decreased. */\n            if (sortby) {\n                decrRefCount(byval);\n            }\n        }\n    }\n\n    if (dontsort == 0) {\n        server.sort_desc = desc;\n        server.sort_alpha = alpha;\n        server.sort_bypattern = sortby ? 1 : 0;\n        server.sort_store = storekey ? 1 : 0;\n        if (sortby && (start != 0 || end != vectorlen-1))\n            pqsort(vector,vectorlen,sizeof(redisSortObject),sortCompare, start,end);\n        else\n            qsort(vector,vectorlen,sizeof(redisSortObject),sortCompare);\n    }\n\n    /* Send command output to the output buffer, performing the specified\n     * GET/DEL/INCR/DECR operations if any. */\n    outputlen = getop ? getop*(end-start+1) : end-start+1;\n    if (int_convertion_error) {\n        addReplyError(c,\"One or more scores can't be converted into double\");\n    } else if (storekey == NULL) {\n        /* STORE option not specified, sent the sorting result to client */\n        addReplyMultiBulkLen(c,outputlen);\n        for (j = start; j <= end; j++) {\n            listNode *ln;\n            listIter li;\n\n            if (!getop) addReplyBulk(c,vector[j].obj);\n            listRewind(operations,&li);\n            while((ln = listNext(&li))) {\n                redisSortOperation *sop = ln->value;\n                robj *val = lookupKeyByPattern(c->db,sop->pattern,\n                    vector[j].obj);\n\n                if (sop->type == SORT_OP_GET) {\n                    if (!val) {\n                        addReply(c,shared.nullbulk);\n                    } else {\n                        addReplyBulk(c,val);\n                        decrRefCount(val);\n                    }\n                } else {\n                    /* Always fails */\n                    serverAssertWithInfo(c,sortval,sop->type == SORT_OP_GET);\n                }\n            }\n        }\n    } else {\n        robj *sobj = createQuicklistObject();\n\n        /* STORE option specified, set the sorting result as a List object */\n        for (j = start; j <= end; j++) {\n            listNode *ln;\n            listIter li;\n\n            if (!getop) {\n                listTypePush(sobj,vector[j].obj,LIST_TAIL);\n            } else {\n                listRewind(operations,&li);\n                while((ln = listNext(&li))) {\n                    redisSortOperation *sop = ln->value;\n                    robj *val = lookupKeyByPattern(c->db,sop->pattern,\n                        vector[j].obj);\n\n                    if (sop->type == SORT_OP_GET) {\n                        if (!val) val = createStringObject(\"\",0);\n\n                        /* listTypePush does an incrRefCount, so we should take care\n                         * care of the incremented refcount caused by either\n                         * lookupKeyByPattern or createStringObject(\"\",0) */\n                        listTypePush(sobj,val,LIST_TAIL);\n                        decrRefCount(val);\n                    } else {\n                        /* Always fails */\n                        serverAssertWithInfo(c,sortval,sop->type == SORT_OP_GET);\n                    }\n                }\n            }\n        }\n        if (outputlen) {\n            setKey(c->db,storekey,sobj);\n            notifyKeyspaceEvent(NOTIFY_LIST,\"sortstore\",storekey,\n                                c->db->id);\n            server.dirty += outputlen;\n        } else if (dbDelete(c->db,storekey)) {\n            signalModifiedKey(c->db,storekey);\n            notifyKeyspaceEvent(NOTIFY_GENERIC,\"del\",storekey,c->db->id);\n            server.dirty++;\n        }\n        decrRefCount(sobj);\n        addReplyLongLong(c,outputlen);\n    }\n\n    /* Cleanup */\n    if (sortval->type == OBJ_LIST || sortval->type == OBJ_SET)\n        for (j = 0; j < vectorlen; j++)\n            decrRefCount(vector[j].obj);\n    decrRefCount(sortval);\n    listRelease(operations);\n    for (j = 0; j < vectorlen; j++) {\n        if (alpha && vector[j].u.cmpobj)\n            decrRefCount(vector[j].u.cmpobj);\n    }\n    zfree(vector);\n}\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/src/sparkline.c",
    "content": "/* sparkline.c -- ASCII Sparklines\n * This code is modified from http://github.com/antirez/aspark and adapted\n * in order to return SDS strings instead of outputting directly to\n * the terminal.\n *\n * ---------------------------------------------------------------------------\n *\n * Copyright(C) 2011-2014 Salvatore Sanfilippo <antirez@gmail.com>\n * All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions are met:\n *\n *   * Redistributions of source code must retain the above copyright notice,\n *     this list of conditions and the following disclaimer.\n *   * Redistributions in binary form must reproduce the above copyright\n *     notice, this list of conditions and the following disclaimer in the\n *     documentation and/or other materials provided with the distribution.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\"\n * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\n * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE\n * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR\n * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF\n * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS\n * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN\n * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)\n * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE\n * POSSIBILITY OF SUCH DAMAGE.\n */\n\n#include \"server.h\"\n\n#include <math.h>\n\n/* This is the charset used to display the graphs, but multiple rows are used\n * to increase the resolution. */\nstatic char charset[] = \"_-`\";\nstatic char charset_fill[] = \"_o#\";\nstatic int charset_len = sizeof(charset)-1;\nstatic int label_margin_top = 1;\n\n/* ----------------------------------------------------------------------------\n * Sequences are arrays of samples we use to represent data to turn\n * into sparklines. This is the API in order to generate a sparkline:\n *\n * struct sequence *seq = createSparklineSequence();\n * sparklineSequenceAddSample(seq, 10, NULL);\n * sparklineSequenceAddSample(seq, 20, NULL);\n * sparklineSequenceAddSample(seq, 30, \"last sample label\");\n * sds output = sparklineRender(sdsempty(), seq, 80, 4, SPARKLINE_FILL);\n * freeSparklineSequence(seq);\n * ------------------------------------------------------------------------- */\n\n/* Create a new sequence. */\nstruct sequence *createSparklineSequence(void) {\n    struct sequence *seq = zmalloc(sizeof(*seq));\n    seq->length = 0;\n    seq->samples = NULL;\n    return seq;\n}\n\n/* Add a new sample into a sequence. */\nvoid sparklineSequenceAddSample(struct sequence *seq, double value, char *label) {\n    label = (label == NULL || label[0] == '\\0') ? NULL : zstrdup(label);\n    if (seq->length == 0) {\n        seq->min = seq->max = value;\n    } else {\n        if (value < seq->min) seq->min = value;\n        else if (value > seq->max) seq->max = value;\n    }\n    seq->samples = zrealloc(seq->samples,sizeof(struct sample)*(seq->length+1));\n    seq->samples[seq->length].value = value;\n    seq->samples[seq->length].label = label;\n    seq->length++;\n    if (label) seq->labels++;\n}\n\n/* Free a sequence. */\nvoid freeSparklineSequence(struct sequence *seq) {\n    int j;\n\n    for (j = 0; j < seq->length; j++)\n        zfree(seq->samples[j].label);\n    zfree(seq->samples);\n    zfree(seq);\n}\n\n/* ----------------------------------------------------------------------------\n * ASCII rendering of sequence\n * ------------------------------------------------------------------------- */\n\n/* Render part of a sequence, so that render_sequence() call call this function\n * with differnent parts in order to create the full output without overflowing\n * the current terminal columns. */\nsds sparklineRenderRange(sds output, struct sequence *seq, int rows, int offset, int len, int flags) {\n    int j;\n    double relmax = seq->max - seq->min;\n    int steps = charset_len*rows;\n    int row = 0;\n    char *chars = zmalloc(len);\n    int loop = 1;\n    int opt_fill = flags & SPARKLINE_FILL;\n    int opt_log = flags & SPARKLINE_LOG_SCALE;\n\n    if (opt_log) {\n        relmax = log(relmax+1);\n    } else if (relmax == 0) {\n        relmax = 1;\n    }\n\n    while(loop) {\n        loop = 0;\n        memset(chars,' ',len);\n        for (j = 0; j < len; j++) {\n            struct sample *s = &seq->samples[j+offset];\n            double relval = s->value - seq->min;\n            int step;\n\n            if (opt_log) relval = log(relval+1);\n            step = (int) (relval*steps)/relmax;\n            if (step < 0) step = 0;\n            if (step >= steps) step = steps-1;\n\n            if (row < rows) {\n                /* Print the character needed to create the sparkline */\n                int charidx = step-((rows-row-1)*charset_len);\n                loop = 1;\n                if (charidx >= 0 && charidx < charset_len) {\n                    chars[j] = opt_fill ? charset_fill[charidx] :\n                                          charset[charidx];\n                } else if(opt_fill && charidx >= charset_len) {\n                    chars[j] = '|';\n                }\n            } else {\n                /* Labels spacing */\n                if (seq->labels && row-rows < label_margin_top) {\n                    loop = 1;\n                    break;\n                }\n                /* Print the label if needed. */\n                if (s->label) {\n                    int label_len = strlen(s->label);\n                    int label_char = row - rows - label_margin_top;\n\n                    if (label_len > label_char) {\n                        loop = 1;\n                        chars[j] = s->label[label_char];\n                    }\n                }\n            }\n        }\n        if (loop) {\n            row++;\n            output = sdscatlen(output,chars,len);\n            output = sdscatlen(output,\"\\n\",1);\n        }\n    }\n    zfree(chars);\n    return output;\n}\n\n/* Turn a sequence into its ASCII representation */\nsds sparklineRender(sds output, struct sequence *seq, int columns, int rows, int flags) {\n    int j;\n\n    for (j = 0; j < seq->length; j += columns) {\n        int sublen = (seq->length-j) < columns ? (seq->length-j) : columns;\n\n        if (j != 0) output = sdscatlen(output,\"\\n\",1);\n        output = sparklineRenderRange(output, seq, rows, j, sublen, flags);\n    }\n    return output;\n}\n\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/src/sparkline.h",
    "content": "/* sparkline.h -- ASCII Sparklines header file\n *\n * ---------------------------------------------------------------------------\n *\n * Copyright(C) 2011-2014 Salvatore Sanfilippo <antirez@gmail.com>\n * All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions are met:\n *\n *   * Redistributions of source code must retain the above copyright notice,\n *     this list of conditions and the following disclaimer.\n *   * Redistributions in binary form must reproduce the above copyright\n *     notice, this list of conditions and the following disclaimer in the\n *     documentation and/or other materials provided with the distribution.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\"\n * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\n * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE\n * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR\n * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF\n * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS\n * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN\n * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)\n * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE\n * POSSIBILITY OF SUCH DAMAGE.\n */\n\n#ifndef __SPARKLINE_H\n#define __SPARKLINE_H\n\n/* A sequence is represented of many \"samples\" */\nstruct sample {\n    double value;\n    char *label;\n};\n\nstruct sequence {\n    int length;\n    int labels;\n    struct sample *samples;\n    double min, max;\n};\n\n#define SPARKLINE_NO_FLAGS 0\n#define SPARKLINE_FILL 1      /* Fill the area under the curve. */\n#define SPARKLINE_LOG_SCALE 2 /* Use logarithmic scale. */\n\nstruct sequence *createSparklineSequence(void);\nvoid sparklineSequenceAddSample(struct sequence *seq, double value, char *label);\nvoid freeSparklineSequence(struct sequence *seq);\nsds sparklineRenderRange(sds output, struct sequence *seq, int rows, int offset, int len, int flags);\nsds sparklineRender(sds output, struct sequence *seq, int columns, int rows, int flags);\n\n#endif /* __SPARKLINE_H */\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/src/syncio.c",
    "content": "/* Synchronous socket and file I/O operations useful across the core.\n *\n * Copyright (c) 2009-2010, Salvatore Sanfilippo <antirez at gmail dot com>\n * All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions are met:\n *\n *   * Redistributions of source code must retain the above copyright notice,\n *     this list of conditions and the following disclaimer.\n *   * Redistributions in binary form must reproduce the above copyright\n *     notice, this list of conditions and the following disclaimer in the\n *     documentation and/or other materials provided with the distribution.\n *   * Neither the name of Redis nor the names of its contributors may be used\n *     to endorse or promote products derived from this software without\n *     specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\"\n * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\n * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE\n * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR\n * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF\n * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS\n * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN\n * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)\n * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE\n * POSSIBILITY OF SUCH DAMAGE.\n */\n\n#include \"server.h\"\n\n/* ----------------- Blocking sockets I/O with timeouts --------------------- */\n\n/* Redis performs most of the I/O in a nonblocking way, with the exception\n * of the SYNC command where the slave does it in a blocking way, and\n * the MIGRATE command that must be blocking in order to be atomic from the\n * point of view of the two instances (one migrating the key and one receiving\n * the key). This is why need the following blocking I/O functions.\n *\n * All the functions take the timeout in milliseconds. */\n\n#define SYNCIO__RESOLUTION 10 /* Resolution in milliseconds */\n\n/* Write the specified payload to 'fd'. If writing the whole payload will be\n * done within 'timeout' milliseconds the operation succeeds and 'size' is\n * returned. Otherwise the operation fails, -1 is returned, and an unspecified\n * partial write could be performed against the file descriptor. */\nssize_t syncWrite(int fd, char *ptr, ssize_t size, long long timeout) {\n    ssize_t nwritten, ret = size;\n    long long start = mstime();\n    long long remaining = timeout;\n\n    while(1) {\n        long long wait = (remaining > SYNCIO__RESOLUTION) ?\n                          remaining : SYNCIO__RESOLUTION;\n        long long elapsed;\n\n        /* Optimistically try to write before checking if the file descriptor\n         * is actually writable. At worst we get EAGAIN. */\n        nwritten = write(fd,ptr,size);\n        if (nwritten == -1) {\n            if (errno != EAGAIN) return -1;\n        } else {\n            ptr += nwritten;\n            size -= nwritten;\n        }\n        if (size == 0) return ret;\n\n        /* Wait */\n        aeWait(fd,AE_WRITABLE,wait);\n        elapsed = mstime() - start;\n        if (elapsed >= timeout) {\n            errno = ETIMEDOUT;\n            return -1;\n        }\n        remaining = timeout - elapsed;\n    }\n}\n\n/* Read the specified amount of bytes from 'fd'. If all the bytes are read\n * within 'timeout' milliseconds the operation succeed and 'size' is returned.\n * Otherwise the operation fails, -1 is returned, and an unspecified amount of\n * data could be read from the file descriptor. */\nssize_t syncRead(int fd, char *ptr, ssize_t size, long long timeout) {\n    ssize_t nread, totread = 0;\n    long long start = mstime();\n    long long remaining = timeout;\n\n    if (size == 0) return 0;\n    while(1) {\n        long long wait = (remaining > SYNCIO__RESOLUTION) ?\n                          remaining : SYNCIO__RESOLUTION;\n        long long elapsed;\n\n        /* Optimistically try to read before checking if the file descriptor\n         * is actually readable. At worst we get EAGAIN. */\n        nread = read(fd,ptr,size);\n        if (nread == 0) return -1; /* short read. */\n        if (nread == -1) {\n            if (errno != EAGAIN) return -1;\n        } else {\n            ptr += nread;\n            size -= nread;\n            totread += nread;\n        }\n        if (size == 0) return totread;\n\n        /* Wait */\n        aeWait(fd,AE_READABLE,wait);\n        elapsed = mstime() - start;\n        if (elapsed >= timeout) {\n            errno = ETIMEDOUT;\n            return -1;\n        }\n        remaining = timeout - elapsed;\n    }\n}\n\n/* Read a line making sure that every char will not require more than 'timeout'\n * milliseconds to be read.\n *\n * On success the number of bytes read is returned, otherwise -1.\n * On success the string is always correctly terminated with a 0 byte. */\nssize_t syncReadLine(int fd, char *ptr, ssize_t size, long long timeout) {\n    ssize_t nread = 0;\n\n    size--;\n    while(size) {\n        char c;\n\n        if (syncRead(fd,&c,1,timeout) == -1) return -1;\n        if (c == '\\n') {\n            *ptr = '\\0';\n            if (nread && *(ptr-1) == '\\r') *(ptr-1) = '\\0';\n            return nread;\n        } else {\n            *ptr++ = c;\n            *ptr = '\\0';\n            nread++;\n        }\n        size--;\n    }\n    return nread;\n}\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/src/t_hash.c",
    "content": "/*\n * Copyright (c) 2009-2012, Salvatore Sanfilippo <antirez at gmail dot com>\n * All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions are met:\n *\n *   * Redistributions of source code must retain the above copyright notice,\n *     this list of conditions and the following disclaimer.\n *   * Redistributions in binary form must reproduce the above copyright\n *     notice, this list of conditions and the following disclaimer in the\n *     documentation and/or other materials provided with the distribution.\n *   * Neither the name of Redis nor the names of its contributors may be used\n *     to endorse or promote products derived from this software without\n *     specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\"\n * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\n * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE\n * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR\n * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF\n * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS\n * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN\n * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)\n * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE\n * POSSIBILITY OF SUCH DAMAGE.\n */\n\n#include \"server.h\"\n#include <math.h>\n\n/*-----------------------------------------------------------------------------\n * Hash type API\n *----------------------------------------------------------------------------*/\n\n/* Check the length of a number of objects to see if we need to convert a\n * ziplist to a real hash. Note that we only check string encoded objects\n * as their string length can be queried in constant time. */\nvoid hashTypeTryConversion(robj *o, robj **argv, int start, int end) {\n    int i;\n\n    if (o->encoding != OBJ_ENCODING_ZIPLIST) return;\n\n    for (i = start; i <= end; i++) {\n        if (sdsEncodedObject(argv[i]) &&\n            sdslen(argv[i]->ptr) > server.hash_max_ziplist_value)\n        {\n            hashTypeConvert(o, OBJ_ENCODING_HT);\n            break;\n        }\n    }\n}\n\n/* Encode given objects in-place when the hash uses a dict. */\nvoid hashTypeTryObjectEncoding(robj *subject, robj **o1, robj **o2) {\n    if (subject->encoding == OBJ_ENCODING_HT) {\n        if (o1) *o1 = tryObjectEncoding(*o1);\n        if (o2) *o2 = tryObjectEncoding(*o2);\n    }\n}\n\n/* Get the value from a ziplist encoded hash, identified by field.\n * Returns -1 when the field cannot be found. */\nint hashTypeGetFromZiplist(robj *o, robj *field,\n                           unsigned char **vstr,\n                           unsigned int *vlen,\n                           long long *vll)\n{\n    unsigned char *zl, *fptr = NULL, *vptr = NULL;\n    int ret;\n\n    serverAssert(o->encoding == OBJ_ENCODING_ZIPLIST);\n\n    field = getDecodedObject(field);\n\n    zl = o->ptr;\n    fptr = ziplistIndex(zl, ZIPLIST_HEAD);\n    if (fptr != NULL) {\n        fptr = ziplistFind(fptr, field->ptr, sdslen(field->ptr), 1);\n        if (fptr != NULL) {\n            /* Grab pointer to the value (fptr points to the field) */\n            vptr = ziplistNext(zl, fptr);\n            serverAssert(vptr != NULL);\n        }\n    }\n\n    decrRefCount(field);\n\n    if (vptr != NULL) {\n        ret = ziplistGet(vptr, vstr, vlen, vll);\n        serverAssert(ret);\n        return 0;\n    }\n\n    return -1;\n}\n\n/* Get the value from a hash table encoded hash, identified by field.\n * Returns -1 when the field cannot be found. */\nint hashTypeGetFromHashTable(robj *o, robj *field, robj **value) {\n    dictEntry *de;\n\n    serverAssert(o->encoding == OBJ_ENCODING_HT);\n\n    de = dictFind(o->ptr, field);\n    if (de == NULL) return -1;\n    *value = dictGetVal(de);\n    return 0;\n}\n\n/* Higher level function of hashTypeGet*() that always returns a Redis\n * object (either new or with refcount incremented), so that the caller\n * can retain a reference or call decrRefCount after the usage.\n *\n * The lower level function can prevent copy on write so it is\n * the preferred way of doing read operations. */\nrobj *hashTypeGetObject(robj *o, robj *field) {\n    robj *value = NULL;\n\n    if (o->encoding == OBJ_ENCODING_ZIPLIST) {\n        unsigned char *vstr = NULL;\n        unsigned int vlen = UINT_MAX;\n        long long vll = LLONG_MAX;\n\n        if (hashTypeGetFromZiplist(o, field, &vstr, &vlen, &vll) == 0) {\n            if (vstr) {\n                value = createStringObject((char*)vstr, vlen);\n            } else {\n                value = createStringObjectFromLongLong(vll);\n            }\n        }\n    } else if (o->encoding == OBJ_ENCODING_HT) {\n        robj *aux;\n\n        if (hashTypeGetFromHashTable(o, field, &aux) == 0) {\n            incrRefCount(aux);\n            value = aux;\n        }\n    } else {\n        serverPanic(\"Unknown hash encoding\");\n    }\n    return value;\n}\n\n/* Higher level function using hashTypeGet*() to return the length of the\n * object associated with the requested field, or 0 if the field does not\n * exist. */\nsize_t hashTypeGetValueLength(robj *o, robj *field) {\n    size_t len = 0;\n    if (o->encoding == OBJ_ENCODING_ZIPLIST) {\n        unsigned char *vstr = NULL;\n        unsigned int vlen = UINT_MAX;\n        long long vll = LLONG_MAX;\n\n        if (hashTypeGetFromZiplist(o, field, &vstr, &vlen, &vll) == 0)\n            len = vstr ? vlen : sdigits10(vll);\n    } else if (o->encoding == OBJ_ENCODING_HT) {\n        robj *aux;\n\n        if (hashTypeGetFromHashTable(o, field, &aux) == 0)\n            len = stringObjectLen(aux);\n    } else {\n        serverPanic(\"Unknown hash encoding\");\n    }\n    return len;\n}\n\n/* Test if the specified field exists in the given hash. Returns 1 if the field\n * exists, and 0 when it doesn't. */\nint hashTypeExists(robj *o, robj *field) {\n    if (o->encoding == OBJ_ENCODING_ZIPLIST) {\n        unsigned char *vstr = NULL;\n        unsigned int vlen = UINT_MAX;\n        long long vll = LLONG_MAX;\n\n        if (hashTypeGetFromZiplist(o, field, &vstr, &vlen, &vll) == 0) return 1;\n    } else if (o->encoding == OBJ_ENCODING_HT) {\n        robj *aux;\n\n        if (hashTypeGetFromHashTable(o, field, &aux) == 0) return 1;\n    } else {\n        serverPanic(\"Unknown hash encoding\");\n    }\n    return 0;\n}\n\n/* Add an element, discard the old if the key already exists.\n * Return 0 on insert and 1 on update.\n * This function will take care of incrementing the reference count of the\n * retained fields and value objects. */\nint hashTypeSet(robj *o, robj *field, robj *value) {\n    int update = 0;\n\n    if (o->encoding == OBJ_ENCODING_ZIPLIST) {\n        unsigned char *zl, *fptr, *vptr;\n\n        field = getDecodedObject(field);\n        value = getDecodedObject(value);\n\n        zl = o->ptr;\n        fptr = ziplistIndex(zl, ZIPLIST_HEAD);\n        if (fptr != NULL) {\n            fptr = ziplistFind(fptr, field->ptr, sdslen(field->ptr), 1);\n            if (fptr != NULL) {\n                /* Grab pointer to the value (fptr points to the field) */\n                vptr = ziplistNext(zl, fptr);\n                serverAssert(vptr != NULL);\n                update = 1;\n\n                /* Delete value */\n                zl = ziplistDelete(zl, &vptr);\n\n                /* Insert new value */\n                zl = ziplistInsert(zl, vptr, value->ptr, sdslen(value->ptr));\n            }\n        }\n\n        if (!update) {\n            /* Push new field/value pair onto the tail of the ziplist */\n            zl = ziplistPush(zl, field->ptr, sdslen(field->ptr), ZIPLIST_TAIL);\n            zl = ziplistPush(zl, value->ptr, sdslen(value->ptr), ZIPLIST_TAIL);\n        }\n        o->ptr = zl;\n        decrRefCount(field);\n        decrRefCount(value);\n\n        /* Check if the ziplist needs to be converted to a hash table */\n        if (hashTypeLength(o) > server.hash_max_ziplist_entries)\n            hashTypeConvert(o, OBJ_ENCODING_HT);\n    } else if (o->encoding == OBJ_ENCODING_HT) {\n        if (dictReplace(o->ptr, field, value)) { /* Insert */\n            incrRefCount(field);\n        } else { /* Update */\n            update = 1;\n        }\n        incrRefCount(value);\n    } else {\n        serverPanic(\"Unknown hash encoding\");\n    }\n    return update;\n}\n\n/* Delete an element from a hash.\n * Return 1 on deleted and 0 on not found. */\nint hashTypeDelete(robj *o, robj *field) {\n    int deleted = 0;\n\n    if (o->encoding == OBJ_ENCODING_ZIPLIST) {\n        unsigned char *zl, *fptr;\n\n        field = getDecodedObject(field);\n\n        zl = o->ptr;\n        fptr = ziplistIndex(zl, ZIPLIST_HEAD);\n        if (fptr != NULL) {\n            fptr = ziplistFind(fptr, field->ptr, sdslen(field->ptr), 1);\n            if (fptr != NULL) {\n                zl = ziplistDelete(zl,&fptr);\n                zl = ziplistDelete(zl,&fptr);\n                o->ptr = zl;\n                deleted = 1;\n            }\n        }\n\n        decrRefCount(field);\n\n    } else if (o->encoding == OBJ_ENCODING_HT) {\n        if (dictDelete((dict*)o->ptr, field) == C_OK) {\n            deleted = 1;\n\n            /* Always check if the dictionary needs a resize after a delete. */\n            if (htNeedsResize(o->ptr)) dictResize(o->ptr);\n        }\n\n    } else {\n        serverPanic(\"Unknown hash encoding\");\n    }\n\n    return deleted;\n}\n\n/* Return the number of elements in a hash. */\nunsigned long hashTypeLength(robj *o) {\n    unsigned long length = ULONG_MAX;\n\n    if (o->encoding == OBJ_ENCODING_ZIPLIST) {\n        length = ziplistLen(o->ptr) / 2;\n    } else if (o->encoding == OBJ_ENCODING_HT) {\n        length = dictSize((dict*)o->ptr);\n    } else {\n        serverPanic(\"Unknown hash encoding\");\n    }\n\n    return length;\n}\n\nhashTypeIterator *hashTypeInitIterator(robj *subject) {\n    hashTypeIterator *hi = zmalloc(sizeof(hashTypeIterator));\n    hi->subject = subject;\n    hi->encoding = subject->encoding;\n\n    if (hi->encoding == OBJ_ENCODING_ZIPLIST) {\n        hi->fptr = NULL;\n        hi->vptr = NULL;\n    } else if (hi->encoding == OBJ_ENCODING_HT) {\n        hi->di = dictGetIterator(subject->ptr);\n    } else {\n        serverPanic(\"Unknown hash encoding\");\n    }\n\n    return hi;\n}\n\nvoid hashTypeReleaseIterator(hashTypeIterator *hi) {\n    if (hi->encoding == OBJ_ENCODING_HT) {\n        dictReleaseIterator(hi->di);\n    }\n\n    zfree(hi);\n}\n\n/* Move to the next entry in the hash. Return C_OK when the next entry\n * could be found and C_ERR when the iterator reaches the end. */\nint hashTypeNext(hashTypeIterator *hi) {\n    if (hi->encoding == OBJ_ENCODING_ZIPLIST) {\n        unsigned char *zl;\n        unsigned char *fptr, *vptr;\n\n        zl = hi->subject->ptr;\n        fptr = hi->fptr;\n        vptr = hi->vptr;\n\n        if (fptr == NULL) {\n            /* Initialize cursor */\n            serverAssert(vptr == NULL);\n            fptr = ziplistIndex(zl, 0);\n        } else {\n            /* Advance cursor */\n            serverAssert(vptr != NULL);\n            fptr = ziplistNext(zl, vptr);\n        }\n        if (fptr == NULL) return C_ERR;\n\n        /* Grab pointer to the value (fptr points to the field) */\n        vptr = ziplistNext(zl, fptr);\n        serverAssert(vptr != NULL);\n\n        /* fptr, vptr now point to the first or next pair */\n        hi->fptr = fptr;\n        hi->vptr = vptr;\n    } else if (hi->encoding == OBJ_ENCODING_HT) {\n        if ((hi->de = dictNext(hi->di)) == NULL) return C_ERR;\n    } else {\n        serverPanic(\"Unknown hash encoding\");\n    }\n    return C_OK;\n}\n\n/* Get the field or value at iterator cursor, for an iterator on a hash value\n * encoded as a ziplist. Prototype is similar to `hashTypeGetFromZiplist`. */\nvoid hashTypeCurrentFromZiplist(hashTypeIterator *hi, int what,\n                                unsigned char **vstr,\n                                unsigned int *vlen,\n                                long long *vll)\n{\n    int ret;\n\n    serverAssert(hi->encoding == OBJ_ENCODING_ZIPLIST);\n\n    if (what & OBJ_HASH_KEY) {\n        ret = ziplistGet(hi->fptr, vstr, vlen, vll);\n        serverAssert(ret);\n    } else {\n        ret = ziplistGet(hi->vptr, vstr, vlen, vll);\n        serverAssert(ret);\n    }\n}\n\n/* Get the field or value at iterator cursor, for an iterator on a hash value\n * encoded as a ziplist. Prototype is similar to `hashTypeGetFromHashTable`. */\nvoid hashTypeCurrentFromHashTable(hashTypeIterator *hi, int what, robj **dst) {\n    serverAssert(hi->encoding == OBJ_ENCODING_HT);\n\n    if (what & OBJ_HASH_KEY) {\n        *dst = dictGetKey(hi->de);\n    } else {\n        *dst = dictGetVal(hi->de);\n    }\n}\n\n/* A non copy-on-write friendly but higher level version of hashTypeCurrent*()\n * that returns an object with incremented refcount (or a new object). It is up\n * to the caller to decrRefCount() the object if no reference is retained. */\nrobj *hashTypeCurrentObject(hashTypeIterator *hi, int what) {\n    robj *dst;\n\n    if (hi->encoding == OBJ_ENCODING_ZIPLIST) {\n        unsigned char *vstr = NULL;\n        unsigned int vlen = UINT_MAX;\n        long long vll = LLONG_MAX;\n\n        hashTypeCurrentFromZiplist(hi, what, &vstr, &vlen, &vll);\n        if (vstr) {\n            dst = createStringObject((char*)vstr, vlen);\n        } else {\n            dst = createStringObjectFromLongLong(vll);\n        }\n    } else if (hi->encoding == OBJ_ENCODING_HT) {\n        hashTypeCurrentFromHashTable(hi, what, &dst);\n        incrRefCount(dst);\n    } else {\n        serverPanic(\"Unknown hash encoding\");\n    }\n    return dst;\n}\n\nrobj *hashTypeLookupWriteOrCreate(client *c, robj *key) {\n    robj *o = lookupKeyWrite(c->db,key);\n    if (o == NULL) {\n        o = createHashObject();\n        dbAdd(c->db,key,o);\n    } else {\n        if (o->type != OBJ_HASH) {\n            addReply(c,shared.wrongtypeerr);\n            return NULL;\n        }\n    }\n    return o;\n}\n\nvoid hashTypeConvertZiplist(robj *o, int enc) {\n    serverAssert(o->encoding == OBJ_ENCODING_ZIPLIST);\n\n    if (enc == OBJ_ENCODING_ZIPLIST) {\n        /* Nothing to do... */\n\n    } else if (enc == OBJ_ENCODING_HT) {\n        hashTypeIterator *hi;\n        dict *dict;\n        int ret;\n\n        hi = hashTypeInitIterator(o);\n        dict = dictCreate(&hashDictType, NULL);\n\n        while (hashTypeNext(hi) != C_ERR) {\n            robj *field, *value;\n\n            field = hashTypeCurrentObject(hi, OBJ_HASH_KEY);\n            field = tryObjectEncoding(field);\n            value = hashTypeCurrentObject(hi, OBJ_HASH_VALUE);\n            value = tryObjectEncoding(value);\n            ret = dictAdd(dict, field, value);\n            if (ret != DICT_OK) {\n                serverLogHexDump(LL_WARNING,\"ziplist with dup elements dump\",\n                    o->ptr,ziplistBlobLen(o->ptr));\n                serverAssert(ret == DICT_OK);\n            }\n        }\n\n        hashTypeReleaseIterator(hi);\n        zfree(o->ptr);\n\n        o->encoding = OBJ_ENCODING_HT;\n        o->ptr = dict;\n\n    } else {\n        serverPanic(\"Unknown hash encoding\");\n    }\n}\n\nvoid hashTypeConvert(robj *o, int enc) {\n    if (o->encoding == OBJ_ENCODING_ZIPLIST) {\n        hashTypeConvertZiplist(o, enc);\n    } else if (o->encoding == OBJ_ENCODING_HT) {\n        serverPanic(\"Not implemented\");\n    } else {\n        serverPanic(\"Unknown hash encoding\");\n    }\n}\n\n/*-----------------------------------------------------------------------------\n * Hash type commands\n *----------------------------------------------------------------------------*/\n\nvoid hsetCommand(client *c) {\n    int update;\n    robj *o;\n\n    if ((o = hashTypeLookupWriteOrCreate(c,c->argv[1])) == NULL) return;\n    hashTypeTryConversion(o,c->argv,2,3);\n    hashTypeTryObjectEncoding(o,&c->argv[2], &c->argv[3]);\n    update = hashTypeSet(o,c->argv[2],c->argv[3]);\n    addReply(c, update ? shared.czero : shared.cone);\n    signalModifiedKey(c->db,c->argv[1]);\n    notifyKeyspaceEvent(NOTIFY_HASH,\"hset\",c->argv[1],c->db->id);\n    server.dirty++;\n}\n\nvoid hsetnxCommand(client *c) {\n    robj *o;\n    if ((o = hashTypeLookupWriteOrCreate(c,c->argv[1])) == NULL) return;\n    hashTypeTryConversion(o,c->argv,2,3);\n\n    if (hashTypeExists(o, c->argv[2])) {\n        addReply(c, shared.czero);\n    } else {\n        hashTypeTryObjectEncoding(o,&c->argv[2], &c->argv[3]);\n        hashTypeSet(o,c->argv[2],c->argv[3]);\n        addReply(c, shared.cone);\n        signalModifiedKey(c->db,c->argv[1]);\n        notifyKeyspaceEvent(NOTIFY_HASH,\"hset\",c->argv[1],c->db->id);\n        server.dirty++;\n    }\n}\n\nvoid hmsetCommand(client *c) {\n    int i;\n    robj *o;\n\n    if ((c->argc % 2) == 1) {\n        addReplyError(c,\"wrong number of arguments for HMSET\");\n        return;\n    }\n\n    if ((o = hashTypeLookupWriteOrCreate(c,c->argv[1])) == NULL) return;\n    hashTypeTryConversion(o,c->argv,2,c->argc-1);\n    for (i = 2; i < c->argc; i += 2) {\n        hashTypeTryObjectEncoding(o,&c->argv[i], &c->argv[i+1]);\n        hashTypeSet(o,c->argv[i],c->argv[i+1]);\n    }\n    addReply(c, shared.ok);\n    signalModifiedKey(c->db,c->argv[1]);\n    notifyKeyspaceEvent(NOTIFY_HASH,\"hset\",c->argv[1],c->db->id);\n    server.dirty++;\n}\n\nvoid hincrbyCommand(client *c) {\n    long long value, incr, oldvalue;\n    robj *o, *current, *new;\n\n    if (getLongLongFromObjectOrReply(c,c->argv[3],&incr,NULL) != C_OK) return;\n    if ((o = hashTypeLookupWriteOrCreate(c,c->argv[1])) == NULL) return;\n    if ((current = hashTypeGetObject(o,c->argv[2])) != NULL) {\n        if (getLongLongFromObjectOrReply(c,current,&value,\n            \"hash value is not an integer\") != C_OK) {\n            decrRefCount(current);\n            return;\n        }\n        decrRefCount(current);\n    } else {\n        value = 0;\n    }\n\n    oldvalue = value;\n    if ((incr < 0 && oldvalue < 0 && incr < (LLONG_MIN-oldvalue)) ||\n        (incr > 0 && oldvalue > 0 && incr > (LLONG_MAX-oldvalue))) {\n        addReplyError(c,\"increment or decrement would overflow\");\n        return;\n    }\n    value += incr;\n    new = createStringObjectFromLongLong(value);\n    hashTypeTryObjectEncoding(o,&c->argv[2],NULL);\n    hashTypeSet(o,c->argv[2],new);\n    decrRefCount(new);\n    addReplyLongLong(c,value);\n    signalModifiedKey(c->db,c->argv[1]);\n    notifyKeyspaceEvent(NOTIFY_HASH,\"hincrby\",c->argv[1],c->db->id);\n    server.dirty++;\n}\n\nvoid hincrbyfloatCommand(client *c) {\n    double long value, incr;\n    robj *o, *current, *new, *aux;\n\n    if (getLongDoubleFromObjectOrReply(c,c->argv[3],&incr,NULL) != C_OK) return;\n    if ((o = hashTypeLookupWriteOrCreate(c,c->argv[1])) == NULL) return;\n    if ((current = hashTypeGetObject(o,c->argv[2])) != NULL) {\n        if (getLongDoubleFromObjectOrReply(c,current,&value,\n            \"hash value is not a valid float\") != C_OK) {\n            decrRefCount(current);\n            return;\n        }\n        decrRefCount(current);\n    } else {\n        value = 0;\n    }\n\n    value += incr;\n    new = createStringObjectFromLongDouble(value,1);\n    hashTypeTryObjectEncoding(o,&c->argv[2],NULL);\n    hashTypeSet(o,c->argv[2],new);\n    addReplyBulk(c,new);\n    signalModifiedKey(c->db,c->argv[1]);\n    notifyKeyspaceEvent(NOTIFY_HASH,\"hincrbyfloat\",c->argv[1],c->db->id);\n    server.dirty++;\n\n    /* Always replicate HINCRBYFLOAT as an HSET command with the final value\n     * in order to make sure that differences in float pricision or formatting\n     * will not create differences in replicas or after an AOF restart. */\n    aux = createStringObject(\"HSET\",4);\n    rewriteClientCommandArgument(c,0,aux);\n    decrRefCount(aux);\n    rewriteClientCommandArgument(c,3,new);\n    decrRefCount(new);\n}\n\nstatic void addHashFieldToReply(client *c, robj *o, robj *field) {\n    int ret;\n\n    if (o == NULL) {\n        addReply(c, shared.nullbulk);\n        return;\n    }\n\n    if (o->encoding == OBJ_ENCODING_ZIPLIST) {\n        unsigned char *vstr = NULL;\n        unsigned int vlen = UINT_MAX;\n        long long vll = LLONG_MAX;\n\n        ret = hashTypeGetFromZiplist(o, field, &vstr, &vlen, &vll);\n        if (ret < 0) {\n            addReply(c, shared.nullbulk);\n        } else {\n            if (vstr) {\n                addReplyBulkCBuffer(c, vstr, vlen);\n            } else {\n                addReplyBulkLongLong(c, vll);\n            }\n        }\n\n    } else if (o->encoding == OBJ_ENCODING_HT) {\n        robj *value;\n\n        ret = hashTypeGetFromHashTable(o, field, &value);\n        if (ret < 0) {\n            addReply(c, shared.nullbulk);\n        } else {\n            addReplyBulk(c, value);\n        }\n\n    } else {\n        serverPanic(\"Unknown hash encoding\");\n    }\n}\n\nvoid hgetCommand(client *c) {\n    robj *o;\n\n    if ((o = lookupKeyReadOrReply(c,c->argv[1],shared.nullbulk)) == NULL ||\n        checkType(c,o,OBJ_HASH)) return;\n\n    addHashFieldToReply(c, o, c->argv[2]);\n}\n\nvoid hmgetCommand(client *c) {\n    robj *o;\n    int i;\n\n    /* Don't abort when the key cannot be found. Non-existing keys are empty\n     * hashes, where HMGET should respond with a series of null bulks. */\n    o = lookupKeyRead(c->db, c->argv[1]);\n    if (o != NULL && o->type != OBJ_HASH) {\n        addReply(c, shared.wrongtypeerr);\n        return;\n    }\n\n    addReplyMultiBulkLen(c, c->argc-2);\n    for (i = 2; i < c->argc; i++) {\n        addHashFieldToReply(c, o, c->argv[i]);\n    }\n}\n\nvoid hdelCommand(client *c) {\n    robj *o;\n    int j, deleted = 0, keyremoved = 0;\n\n    if ((o = lookupKeyWriteOrReply(c,c->argv[1],shared.czero)) == NULL ||\n        checkType(c,o,OBJ_HASH)) return;\n\n    for (j = 2; j < c->argc; j++) {\n        if (hashTypeDelete(o,c->argv[j])) {\n            deleted++;\n            if (hashTypeLength(o) == 0) {\n                dbDelete(c->db,c->argv[1]);\n                keyremoved = 1;\n                break;\n            }\n        }\n    }\n    if (deleted) {\n        signalModifiedKey(c->db,c->argv[1]);\n        notifyKeyspaceEvent(NOTIFY_HASH,\"hdel\",c->argv[1],c->db->id);\n        if (keyremoved)\n            notifyKeyspaceEvent(NOTIFY_GENERIC,\"del\",c->argv[1],\n                                c->db->id);\n        server.dirty += deleted;\n    }\n    addReplyLongLong(c,deleted);\n}\n\nvoid hlenCommand(client *c) {\n    robj *o;\n\n    if ((o = lookupKeyReadOrReply(c,c->argv[1],shared.czero)) == NULL ||\n        checkType(c,o,OBJ_HASH)) return;\n\n    addReplyLongLong(c,hashTypeLength(o));\n}\n\nvoid hstrlenCommand(client *c) {\n    robj *o;\n\n    if ((o = lookupKeyReadOrReply(c,c->argv[1],shared.czero)) == NULL ||\n        checkType(c,o,OBJ_HASH)) return;\n    addReplyLongLong(c,hashTypeGetValueLength(o,c->argv[2]));\n}\n\nstatic void addHashIteratorCursorToReply(client *c, hashTypeIterator *hi, int what) {\n    if (hi->encoding == OBJ_ENCODING_ZIPLIST) {\n        unsigned char *vstr = NULL;\n        unsigned int vlen = UINT_MAX;\n        long long vll = LLONG_MAX;\n\n        hashTypeCurrentFromZiplist(hi, what, &vstr, &vlen, &vll);\n        if (vstr) {\n            addReplyBulkCBuffer(c, vstr, vlen);\n        } else {\n            addReplyBulkLongLong(c, vll);\n        }\n\n    } else if (hi->encoding == OBJ_ENCODING_HT) {\n        robj *value;\n\n        hashTypeCurrentFromHashTable(hi, what, &value);\n        addReplyBulk(c, value);\n\n    } else {\n        serverPanic(\"Unknown hash encoding\");\n    }\n}\n\nvoid genericHgetallCommand(client *c, int flags) {\n    robj *o;\n    hashTypeIterator *hi;\n    int multiplier = 0;\n    int length, count = 0;\n\n    if ((o = lookupKeyReadOrReply(c,c->argv[1],shared.emptymultibulk)) == NULL\n        || checkType(c,o,OBJ_HASH)) return;\n\n    if (flags & OBJ_HASH_KEY) multiplier++;\n    if (flags & OBJ_HASH_VALUE) multiplier++;\n\n    length = hashTypeLength(o) * multiplier;\n    addReplyMultiBulkLen(c, length);\n\n    hi = hashTypeInitIterator(o);\n    while (hashTypeNext(hi) != C_ERR) {\n        if (flags & OBJ_HASH_KEY) {\n            addHashIteratorCursorToReply(c, hi, OBJ_HASH_KEY);\n            count++;\n        }\n        if (flags & OBJ_HASH_VALUE) {\n            addHashIteratorCursorToReply(c, hi, OBJ_HASH_VALUE);\n            count++;\n        }\n    }\n\n    hashTypeReleaseIterator(hi);\n    serverAssert(count == length);\n}\n\nvoid hkeysCommand(client *c) {\n    genericHgetallCommand(c,OBJ_HASH_KEY);\n}\n\nvoid hvalsCommand(client *c) {\n    genericHgetallCommand(c,OBJ_HASH_VALUE);\n}\n\nvoid hgetallCommand(client *c) {\n    genericHgetallCommand(c,OBJ_HASH_KEY|OBJ_HASH_VALUE);\n}\n\nvoid hexistsCommand(client *c) {\n    robj *o;\n    if ((o = lookupKeyReadOrReply(c,c->argv[1],shared.czero)) == NULL ||\n        checkType(c,o,OBJ_HASH)) return;\n\n    addReply(c, hashTypeExists(o,c->argv[2]) ? shared.cone : shared.czero);\n}\n\nvoid hscanCommand(client *c) {\n    robj *o;\n    unsigned long cursor;\n\n    if (parseScanCursorOrReply(c,c->argv[2],&cursor) == C_ERR) return;\n    if ((o = lookupKeyReadOrReply(c,c->argv[1],shared.emptyscan)) == NULL ||\n        checkType(c,o,OBJ_HASH)) return;\n    scanGenericCommand(c,o,cursor);\n}\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/src/t_list.c",
    "content": "/*\n * Copyright (c) 2009-2012, Salvatore Sanfilippo <antirez at gmail dot com>\n * All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions are met:\n *\n *   * Redistributions of source code must retain the above copyright notice,\n *     this list of conditions and the following disclaimer.\n *   * Redistributions in binary form must reproduce the above copyright\n *     notice, this list of conditions and the following disclaimer in the\n *     documentation and/or other materials provided with the distribution.\n *   * Neither the name of Redis nor the names of its contributors may be used\n *     to endorse or promote products derived from this software without\n *     specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\"\n * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\n * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE\n * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR\n * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF\n * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS\n * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN\n * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)\n * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE\n * POSSIBILITY OF SUCH DAMAGE.\n */\n\n#include \"server.h\"\n\n/*-----------------------------------------------------------------------------\n * List API\n *----------------------------------------------------------------------------*/\n\n/* The function pushes an element to the specified list object 'subject',\n * at head or tail position as specified by 'where'.\n *\n * There is no need for the caller to increment the refcount of 'value' as\n * the function takes care of it if needed. */\nvoid listTypePush(robj *subject, robj *value, int where) {\n    if (subject->encoding == OBJ_ENCODING_QUICKLIST) {\n        int pos = (where == LIST_HEAD) ? QUICKLIST_HEAD : QUICKLIST_TAIL;\n        value = getDecodedObject(value);\n        size_t len = sdslen(value->ptr);\n        quicklistPush(subject->ptr, value->ptr, len, pos);\n        decrRefCount(value);\n    } else {\n        serverPanic(\"Unknown list encoding\");\n    }\n}\n\nvoid *listPopSaver(unsigned char *data, unsigned int sz) {\n    return createStringObject((char*)data,sz);\n}\n\nrobj *listTypePop(robj *subject, int where) {\n    long long vlong;\n    robj *value = NULL;\n\n    int ql_where = where == LIST_HEAD ? QUICKLIST_HEAD : QUICKLIST_TAIL;\n    if (subject->encoding == OBJ_ENCODING_QUICKLIST) {\n        if (quicklistPopCustom(subject->ptr, ql_where, (unsigned char **)&value,\n                               NULL, &vlong, listPopSaver)) {\n            if (!value)\n                value = createStringObjectFromLongLong(vlong);\n        }\n    } else {\n        serverPanic(\"Unknown list encoding\");\n    }\n    return value;\n}\n\nunsigned long listTypeLength(robj *subject) {\n    if (subject->encoding == OBJ_ENCODING_QUICKLIST) {\n        return quicklistCount(subject->ptr);\n    } else {\n        serverPanic(\"Unknown list encoding\");\n    }\n}\n\n/* Initialize an iterator at the specified index. */\nlistTypeIterator *listTypeInitIterator(robj *subject, long index,\n                                       unsigned char direction) {\n    listTypeIterator *li = zmalloc(sizeof(listTypeIterator));\n    li->subject = subject;\n    li->encoding = subject->encoding;\n    li->direction = direction;\n    li->iter = NULL;\n    /* LIST_HEAD means start at TAIL and move *towards* head.\n     * LIST_TAIL means start at HEAD and move *towards tail. */\n    int iter_direction =\n        direction == LIST_HEAD ? AL_START_TAIL : AL_START_HEAD;\n    if (li->encoding == OBJ_ENCODING_QUICKLIST) {\n        li->iter = quicklistGetIteratorAtIdx(li->subject->ptr,\n                                             iter_direction, index);\n    } else {\n        serverPanic(\"Unknown list encoding\");\n    }\n    return li;\n}\n\n/* Clean up the iterator. */\nvoid listTypeReleaseIterator(listTypeIterator *li) {\n    zfree(li->iter);\n    zfree(li);\n}\n\n/* Stores pointer to current the entry in the provided entry structure\n * and advances the position of the iterator. Returns 1 when the current\n * entry is in fact an entry, 0 otherwise. */\nint listTypeNext(listTypeIterator *li, listTypeEntry *entry) {\n    /* Protect from converting when iterating */\n    serverAssert(li->subject->encoding == li->encoding);\n\n    entry->li = li;\n    if (li->encoding == OBJ_ENCODING_QUICKLIST) {\n        return quicklistNext(li->iter, &entry->entry);\n    } else {\n        serverPanic(\"Unknown list encoding\");\n    }\n    return 0;\n}\n\n/* Return entry or NULL at the current position of the iterator. */\nrobj *listTypeGet(listTypeEntry *entry) {\n    robj *value = NULL;\n    if (entry->li->encoding == OBJ_ENCODING_QUICKLIST) {\n        if (entry->entry.value) {\n            value = createStringObject((char *)entry->entry.value,\n                                       entry->entry.sz);\n        } else {\n            value = createStringObjectFromLongLong(entry->entry.longval);\n        }\n    } else {\n        serverPanic(\"Unknown list encoding\");\n    }\n    return value;\n}\n\nvoid listTypeInsert(listTypeEntry *entry, robj *value, int where) {\n    if (entry->li->encoding == OBJ_ENCODING_QUICKLIST) {\n        value = getDecodedObject(value);\n        sds str = value->ptr;\n        size_t len = sdslen(str);\n        if (where == LIST_TAIL) {\n            quicklistInsertAfter((quicklist *)entry->entry.quicklist,\n                                 &entry->entry, str, len);\n        } else if (where == LIST_HEAD) {\n            quicklistInsertBefore((quicklist *)entry->entry.quicklist,\n                                  &entry->entry, str, len);\n        }\n        decrRefCount(value);\n    } else {\n        serverPanic(\"Unknown list encoding\");\n    }\n}\n\n/* Compare the given object with the entry at the current position. */\nint listTypeEqual(listTypeEntry *entry, robj *o) {\n    if (entry->li->encoding == OBJ_ENCODING_QUICKLIST) {\n        serverAssertWithInfo(NULL,o,sdsEncodedObject(o));\n        return quicklistCompare(entry->entry.zi,o->ptr,sdslen(o->ptr));\n    } else {\n        serverPanic(\"Unknown list encoding\");\n    }\n}\n\n/* Delete the element pointed to. */\nvoid listTypeDelete(listTypeIterator *iter, listTypeEntry *entry) {\n    if (entry->li->encoding == OBJ_ENCODING_QUICKLIST) {\n        quicklistDelEntry(iter->iter, &entry->entry);\n    } else {\n        serverPanic(\"Unknown list encoding\");\n    }\n}\n\n/* Create a quicklist from a single ziplist */\nvoid listTypeConvert(robj *subject, int enc) {\n    serverAssertWithInfo(NULL,subject,subject->type==OBJ_LIST);\n    serverAssertWithInfo(NULL,subject,subject->encoding==OBJ_ENCODING_ZIPLIST);\n\n    if (enc == OBJ_ENCODING_QUICKLIST) {\n        size_t zlen = server.list_max_ziplist_size;\n        int depth = server.list_compress_depth;\n        subject->ptr = quicklistCreateFromZiplist(zlen, depth, subject->ptr);\n        subject->encoding = OBJ_ENCODING_QUICKLIST;\n    } else {\n        serverPanic(\"Unsupported list conversion\");\n    }\n}\n\n/*-----------------------------------------------------------------------------\n * List Commands\n *----------------------------------------------------------------------------*/\n\nvoid pushGenericCommand(client *c, int where) {\n    int j, waiting = 0, pushed = 0;\n    robj *lobj = lookupKeyWrite(c->db,c->argv[1]);\n\n    if (lobj && lobj->type != OBJ_LIST) {\n        addReply(c,shared.wrongtypeerr);\n        return;\n    }\n\n    for (j = 2; j < c->argc; j++) {\n        c->argv[j] = tryObjectEncoding(c->argv[j]);\n        if (!lobj) {\n            lobj = createQuicklistObject();\n            quicklistSetOptions(lobj->ptr, server.list_max_ziplist_size,\n                                server.list_compress_depth);\n            dbAdd(c->db,c->argv[1],lobj);\n        }\n        listTypePush(lobj,c->argv[j],where);\n        pushed++;\n    }\n    addReplyLongLong(c, waiting + (lobj ? listTypeLength(lobj) : 0));\n    if (pushed) {\n        char *event = (where == LIST_HEAD) ? \"lpush\" : \"rpush\";\n\n        signalModifiedKey(c->db,c->argv[1]);\n        notifyKeyspaceEvent(NOTIFY_LIST,event,c->argv[1],c->db->id);\n    }\n    server.dirty += pushed;\n}\n\nvoid lpushCommand(client *c) {\n    pushGenericCommand(c,LIST_HEAD);\n}\n\nvoid rpushCommand(client *c) {\n    pushGenericCommand(c,LIST_TAIL);\n}\n\nvoid pushxGenericCommand(client *c, robj *refval, robj *val, int where) {\n    robj *subject;\n    listTypeIterator *iter;\n    listTypeEntry entry;\n    int inserted = 0;\n\n    if ((subject = lookupKeyWriteOrReply(c,c->argv[1],shared.czero)) == NULL ||\n        checkType(c,subject,OBJ_LIST)) return;\n\n    if (refval != NULL) {\n        /* Seek refval from head to tail */\n        iter = listTypeInitIterator(subject,0,LIST_TAIL);\n        while (listTypeNext(iter,&entry)) {\n            if (listTypeEqual(&entry,refval)) {\n                listTypeInsert(&entry,val,where);\n                inserted = 1;\n                break;\n            }\n        }\n        listTypeReleaseIterator(iter);\n\n        if (inserted) {\n            signalModifiedKey(c->db,c->argv[1]);\n            notifyKeyspaceEvent(NOTIFY_LIST,\"linsert\",\n                                c->argv[1],c->db->id);\n            server.dirty++;\n        } else {\n            /* Notify client of a failed insert */\n            addReply(c,shared.cnegone);\n            return;\n        }\n    } else {\n        char *event = (where == LIST_HEAD) ? \"lpush\" : \"rpush\";\n\n        listTypePush(subject,val,where);\n        signalModifiedKey(c->db,c->argv[1]);\n        notifyKeyspaceEvent(NOTIFY_LIST,event,c->argv[1],c->db->id);\n        server.dirty++;\n    }\n\n    addReplyLongLong(c,listTypeLength(subject));\n}\n\nvoid lpushxCommand(client *c) {\n    c->argv[2] = tryObjectEncoding(c->argv[2]);\n    pushxGenericCommand(c,NULL,c->argv[2],LIST_HEAD);\n}\n\nvoid rpushxCommand(client *c) {\n    c->argv[2] = tryObjectEncoding(c->argv[2]);\n    pushxGenericCommand(c,NULL,c->argv[2],LIST_TAIL);\n}\n\nvoid linsertCommand(client *c) {\n    c->argv[4] = tryObjectEncoding(c->argv[4]);\n    if (strcasecmp(c->argv[2]->ptr,\"after\") == 0) {\n        pushxGenericCommand(c,c->argv[3],c->argv[4],LIST_TAIL);\n    } else if (strcasecmp(c->argv[2]->ptr,\"before\") == 0) {\n        pushxGenericCommand(c,c->argv[3],c->argv[4],LIST_HEAD);\n    } else {\n        addReply(c,shared.syntaxerr);\n    }\n}\n\nvoid llenCommand(client *c) {\n    robj *o = lookupKeyReadOrReply(c,c->argv[1],shared.czero);\n    if (o == NULL || checkType(c,o,OBJ_LIST)) return;\n    addReplyLongLong(c,listTypeLength(o));\n}\n\nvoid lindexCommand(client *c) {\n    robj *o = lookupKeyReadOrReply(c,c->argv[1],shared.nullbulk);\n    if (o == NULL || checkType(c,o,OBJ_LIST)) return;\n    long index;\n    robj *value = NULL;\n\n    if ((getLongFromObjectOrReply(c, c->argv[2], &index, NULL) != C_OK))\n        return;\n\n    if (o->encoding == OBJ_ENCODING_QUICKLIST) {\n        quicklistEntry entry;\n        if (quicklistIndex(o->ptr, index, &entry)) {\n            if (entry.value) {\n                value = createStringObject((char*)entry.value,entry.sz);\n            } else {\n                value = createStringObjectFromLongLong(entry.longval);\n            }\n            addReplyBulk(c,value);\n            decrRefCount(value);\n        } else {\n            addReply(c,shared.nullbulk);\n        }\n    } else {\n        serverPanic(\"Unknown list encoding\");\n    }\n}\n\nvoid lsetCommand(client *c) {\n    robj *o = lookupKeyWriteOrReply(c,c->argv[1],shared.nokeyerr);\n    if (o == NULL || checkType(c,o,OBJ_LIST)) return;\n    long index;\n    robj *value = c->argv[3];\n\n    if ((getLongFromObjectOrReply(c, c->argv[2], &index, NULL) != C_OK))\n        return;\n\n    if (o->encoding == OBJ_ENCODING_QUICKLIST) {\n        quicklist *ql = o->ptr;\n        int replaced = quicklistReplaceAtIndex(ql, index,\n                                               value->ptr, sdslen(value->ptr));\n        if (!replaced) {\n            addReply(c,shared.outofrangeerr);\n        } else {\n            addReply(c,shared.ok);\n            signalModifiedKey(c->db,c->argv[1]);\n            notifyKeyspaceEvent(NOTIFY_LIST,\"lset\",c->argv[1],c->db->id);\n            server.dirty++;\n        }\n    } else {\n        serverPanic(\"Unknown list encoding\");\n    }\n}\n\nvoid popGenericCommand(client *c, int where) {\n    robj *o = lookupKeyWriteOrReply(c,c->argv[1],shared.nullbulk);\n    if (o == NULL || checkType(c,o,OBJ_LIST)) return;\n\n    robj *value = listTypePop(o,where);\n    if (value == NULL) {\n        addReply(c,shared.nullbulk);\n    } else {\n        char *event = (where == LIST_HEAD) ? \"lpop\" : \"rpop\";\n\n        addReplyBulk(c,value);\n        decrRefCount(value);\n        notifyKeyspaceEvent(NOTIFY_LIST,event,c->argv[1],c->db->id);\n        if (listTypeLength(o) == 0) {\n            notifyKeyspaceEvent(NOTIFY_GENERIC,\"del\",\n                                c->argv[1],c->db->id);\n            dbDelete(c->db,c->argv[1]);\n        }\n        signalModifiedKey(c->db,c->argv[1]);\n        server.dirty++;\n    }\n}\n\nvoid lpopCommand(client *c) {\n    popGenericCommand(c,LIST_HEAD);\n}\n\nvoid rpopCommand(client *c) {\n    popGenericCommand(c,LIST_TAIL);\n}\n\nvoid lrangeCommand(client *c) {\n    robj *o;\n    long start, end, llen, rangelen;\n\n    if ((getLongFromObjectOrReply(c, c->argv[2], &start, NULL) != C_OK) ||\n        (getLongFromObjectOrReply(c, c->argv[3], &end, NULL) != C_OK)) return;\n\n    if ((o = lookupKeyReadOrReply(c,c->argv[1],shared.emptymultibulk)) == NULL\n         || checkType(c,o,OBJ_LIST)) return;\n    llen = listTypeLength(o);\n\n    /* convert negative indexes */\n    if (start < 0) start = llen+start;\n    if (end < 0) end = llen+end;\n    if (start < 0) start = 0;\n\n    /* Invariant: start >= 0, so this test will be true when end < 0.\n     * The range is empty when start > end or start >= length. */\n    if (start > end || start >= llen) {\n        addReply(c,shared.emptymultibulk);\n        return;\n    }\n    if (end >= llen) end = llen-1;\n    rangelen = (end-start)+1;\n\n    /* Return the result in form of a multi-bulk reply */\n    addReplyMultiBulkLen(c,rangelen);\n    if (o->encoding == OBJ_ENCODING_QUICKLIST) {\n        listTypeIterator *iter = listTypeInitIterator(o, start, LIST_TAIL);\n\n        while(rangelen--) {\n            listTypeEntry entry;\n            listTypeNext(iter, &entry);\n            quicklistEntry *qe = &entry.entry;\n            if (qe->value) {\n                addReplyBulkCBuffer(c,qe->value,qe->sz);\n            } else {\n                addReplyBulkLongLong(c,qe->longval);\n            }\n        }\n        listTypeReleaseIterator(iter);\n    } else {\n        serverPanic(\"List encoding is not QUICKLIST!\");\n    }\n}\n\nvoid ltrimCommand(client *c) {\n    robj *o;\n    long start, end, llen, ltrim, rtrim;\n\n    if ((getLongFromObjectOrReply(c, c->argv[2], &start, NULL) != C_OK) ||\n        (getLongFromObjectOrReply(c, c->argv[3], &end, NULL) != C_OK)) return;\n\n    if ((o = lookupKeyWriteOrReply(c,c->argv[1],shared.ok)) == NULL ||\n        checkType(c,o,OBJ_LIST)) return;\n    llen = listTypeLength(o);\n\n    /* convert negative indexes */\n    if (start < 0) start = llen+start;\n    if (end < 0) end = llen+end;\n    if (start < 0) start = 0;\n\n    /* Invariant: start >= 0, so this test will be true when end < 0.\n     * The range is empty when start > end or start >= length. */\n    if (start > end || start >= llen) {\n        /* Out of range start or start > end result in empty list */\n        ltrim = llen;\n        rtrim = 0;\n    } else {\n        if (end >= llen) end = llen-1;\n        ltrim = start;\n        rtrim = llen-end-1;\n    }\n\n    /* Remove list elements to perform the trim */\n    if (o->encoding == OBJ_ENCODING_QUICKLIST) {\n        quicklistDelRange(o->ptr,0,ltrim);\n        quicklistDelRange(o->ptr,-rtrim,rtrim);\n    } else {\n        serverPanic(\"Unknown list encoding\");\n    }\n\n    notifyKeyspaceEvent(NOTIFY_LIST,\"ltrim\",c->argv[1],c->db->id);\n    if (listTypeLength(o) == 0) {\n        dbDelete(c->db,c->argv[1]);\n        notifyKeyspaceEvent(NOTIFY_GENERIC,\"del\",c->argv[1],c->db->id);\n    }\n    signalModifiedKey(c->db,c->argv[1]);\n    server.dirty++;\n    addReply(c,shared.ok);\n}\n\nvoid lremCommand(client *c) {\n    robj *subject, *obj;\n    obj = c->argv[3];\n    long toremove;\n    long removed = 0;\n\n    if ((getLongFromObjectOrReply(c, c->argv[2], &toremove, NULL) != C_OK))\n        return;\n\n    subject = lookupKeyWriteOrReply(c,c->argv[1],shared.czero);\n    if (subject == NULL || checkType(c,subject,OBJ_LIST)) return;\n\n    listTypeIterator *li;\n    if (toremove < 0) {\n        toremove = -toremove;\n        li = listTypeInitIterator(subject,-1,LIST_HEAD);\n    } else {\n        li = listTypeInitIterator(subject,0,LIST_TAIL);\n    }\n\n    listTypeEntry entry;\n    while (listTypeNext(li,&entry)) {\n        if (listTypeEqual(&entry,obj)) {\n            listTypeDelete(li, &entry);\n            server.dirty++;\n            removed++;\n            if (toremove && removed == toremove) break;\n        }\n    }\n    listTypeReleaseIterator(li);\n\n    if (removed) {\n        signalModifiedKey(c->db,c->argv[1]);\n        notifyKeyspaceEvent(NOTIFY_GENERIC,\"lrem\",c->argv[1],c->db->id);\n    }\n\n    if (listTypeLength(subject) == 0) {\n        dbDelete(c->db,c->argv[1]);\n        notifyKeyspaceEvent(NOTIFY_GENERIC,\"del\",c->argv[1],c->db->id);\n    }\n\n    addReplyLongLong(c,removed);\n}\n\n/* This is the semantic of this command:\n *  RPOPLPUSH srclist dstlist:\n *    IF LLEN(srclist) > 0\n *      element = RPOP srclist\n *      LPUSH dstlist element\n *      RETURN element\n *    ELSE\n *      RETURN nil\n *    END\n *  END\n *\n * The idea is to be able to get an element from a list in a reliable way\n * since the element is not just returned but pushed against another list\n * as well. This command was originally proposed by Ezra Zygmuntowicz.\n */\n\nvoid rpoplpushHandlePush(client *c, robj *dstkey, robj *dstobj, robj *value) {\n    /* Create the list if the key does not exist */\n    if (!dstobj) {\n        dstobj = createQuicklistObject();\n        quicklistSetOptions(dstobj->ptr, server.list_max_ziplist_size,\n                            server.list_compress_depth);\n        dbAdd(c->db,dstkey,dstobj);\n    }\n    signalModifiedKey(c->db,dstkey);\n    listTypePush(dstobj,value,LIST_HEAD);\n    notifyKeyspaceEvent(NOTIFY_LIST,\"lpush\",dstkey,c->db->id);\n    /* Always send the pushed value to the client. */\n    addReplyBulk(c,value);\n}\n\nvoid rpoplpushCommand(client *c) {\n    robj *sobj, *value;\n    if ((sobj = lookupKeyWriteOrReply(c,c->argv[1],shared.nullbulk)) == NULL ||\n        checkType(c,sobj,OBJ_LIST)) return;\n\n    if (listTypeLength(sobj) == 0) {\n        /* This may only happen after loading very old RDB files. Recent\n         * versions of Redis delete keys of empty lists. */\n        addReply(c,shared.nullbulk);\n    } else {\n        robj *dobj = lookupKeyWrite(c->db,c->argv[2]);\n        robj *touchedkey = c->argv[1];\n\n        if (dobj && checkType(c,dobj,OBJ_LIST)) return;\n        value = listTypePop(sobj,LIST_TAIL);\n        /* We saved touched key, and protect it, since rpoplpushHandlePush\n         * may change the client command argument vector (it does not\n         * currently). */\n        incrRefCount(touchedkey);\n        rpoplpushHandlePush(c,c->argv[2],dobj,value);\n\n        /* listTypePop returns an object with its refcount incremented */\n        decrRefCount(value);\n\n        /* Delete the source list when it is empty */\n        notifyKeyspaceEvent(NOTIFY_LIST,\"rpop\",touchedkey,c->db->id);\n        if (listTypeLength(sobj) == 0) {\n            dbDelete(c->db,touchedkey);\n            notifyKeyspaceEvent(NOTIFY_GENERIC,\"del\",\n                                touchedkey,c->db->id);\n        }\n        signalModifiedKey(c->db,touchedkey);\n        decrRefCount(touchedkey);\n        server.dirty++;\n    }\n}\n\n/*-----------------------------------------------------------------------------\n * Blocking POP operations\n *----------------------------------------------------------------------------*/\n\n/* This is how the current blocking POP works, we use BLPOP as example:\n * - If the user calls BLPOP and the key exists and contains a non empty list\n *   then LPOP is called instead. So BLPOP is semantically the same as LPOP\n *   if blocking is not required.\n * - If instead BLPOP is called and the key does not exists or the list is\n *   empty we need to block. In order to do so we remove the notification for\n *   new data to read in the client socket (so that we'll not serve new\n *   requests if the blocking request is not served). Also we put the client\n *   in a dictionary (db->blocking_keys) mapping keys to a list of clients\n *   blocking for this keys.\n * - If a PUSH operation against a key with blocked clients waiting is\n *   performed, we mark this key as \"ready\", and after the current command,\n *   MULTI/EXEC block, or script, is executed, we serve all the clients waiting\n *   for this list, from the one that blocked first, to the last, accordingly\n *   to the number of elements we have in the ready list.\n */\n\n/* Set a client in blocking mode for the specified key, with the specified\n * timeout */\nvoid blockForKeys(client *c, robj **keys, int numkeys, mstime_t timeout, robj *target) {\n    dictEntry *de;\n    list *l;\n    int j;\n\n    c->bpop.timeout = timeout;\n    c->bpop.target = target;\n\n    if (target != NULL) incrRefCount(target);\n\n    for (j = 0; j < numkeys; j++) {\n        /* If the key already exists in the dict ignore it. */\n        if (dictAdd(c->bpop.keys,keys[j],NULL) != DICT_OK) continue;\n        incrRefCount(keys[j]);\n\n        /* And in the other \"side\", to map keys -> clients */\n        de = dictFind(c->db->blocking_keys,keys[j]);\n        if (de == NULL) {\n            int retval;\n\n            /* For every key we take a list of clients blocked for it */\n            l = listCreate();\n            retval = dictAdd(c->db->blocking_keys,keys[j],l);\n            incrRefCount(keys[j]);\n            serverAssertWithInfo(c,keys[j],retval == DICT_OK);\n        } else {\n            l = dictGetVal(de);\n        }\n        listAddNodeTail(l,c);\n    }\n    blockClient(c,BLOCKED_LIST);\n}\n\n/* Unblock a client that's waiting in a blocking operation such as BLPOP.\n * You should never call this function directly, but unblockClient() instead. */\nvoid unblockClientWaitingData(client *c) {\n    dictEntry *de;\n    dictIterator *di;\n    list *l;\n\n    serverAssertWithInfo(c,NULL,dictSize(c->bpop.keys) != 0);\n    di = dictGetIterator(c->bpop.keys);\n    /* The client may wait for multiple keys, so unblock it for every key. */\n    while((de = dictNext(di)) != NULL) {\n        robj *key = dictGetKey(de);\n\n        /* Remove this client from the list of clients waiting for this key. */\n        l = dictFetchValue(c->db->blocking_keys,key);\n        serverAssertWithInfo(c,key,l != NULL);\n        listDelNode(l,listSearchKey(l,c));\n        /* If the list is empty we need to remove it to avoid wasting memory */\n        if (listLength(l) == 0)\n            dictDelete(c->db->blocking_keys,key);\n    }\n    dictReleaseIterator(di);\n\n    /* Cleanup the client structure */\n    dictEmpty(c->bpop.keys,NULL);\n    if (c->bpop.target) {\n        decrRefCount(c->bpop.target);\n        c->bpop.target = NULL;\n    }\n}\n\n/* If the specified key has clients blocked waiting for list pushes, this\n * function will put the key reference into the server.ready_keys list.\n * Note that db->ready_keys is a hash table that allows us to avoid putting\n * the same key again and again in the list in case of multiple pushes\n * made by a script or in the context of MULTI/EXEC.\n *\n * The list will be finally processed by handleClientsBlockedOnLists() */\nvoid signalListAsReady(redisDb *db, robj *key) {\n    readyList *rl;\n\n    /* No clients blocking for this key? No need to queue it. */\n    if (dictFind(db->blocking_keys,key) == NULL) return;\n\n    /* Key was already signaled? No need to queue it again. */\n    if (dictFind(db->ready_keys,key) != NULL) return;\n\n    /* Ok, we need to queue this key into server.ready_keys. */\n    rl = zmalloc(sizeof(*rl));\n    rl->key = key;\n    rl->db = db;\n    incrRefCount(key);\n    listAddNodeTail(server.ready_keys,rl);\n\n    /* We also add the key in the db->ready_keys dictionary in order\n     * to avoid adding it multiple times into a list with a simple O(1)\n     * check. */\n    incrRefCount(key);\n    serverAssert(dictAdd(db->ready_keys,key,NULL) == DICT_OK);\n}\n\n/* This is a helper function for handleClientsBlockedOnLists(). It's work\n * is to serve a specific client (receiver) that is blocked on 'key'\n * in the context of the specified 'db', doing the following:\n *\n * 1) Provide the client with the 'value' element.\n * 2) If the dstkey is not NULL (we are serving a BRPOPLPUSH) also push the\n *    'value' element on the destination list (the LPUSH side of the command).\n * 3) Propagate the resulting BRPOP, BLPOP and additional LPUSH if any into\n *    the AOF and replication channel.\n *\n * The argument 'where' is LIST_TAIL or LIST_HEAD, and indicates if the\n * 'value' element was popped fron the head (BLPOP) or tail (BRPOP) so that\n * we can propagate the command properly.\n *\n * The function returns C_OK if we are able to serve the client, otherwise\n * C_ERR is returned to signal the caller that the list POP operation\n * should be undone as the client was not served: This only happens for\n * BRPOPLPUSH that fails to push the value to the destination key as it is\n * of the wrong type. */\nint serveClientBlockedOnList(client *receiver, robj *key, robj *dstkey, redisDb *db, robj *value, int where)\n{\n    robj *argv[3];\n\n    if (dstkey == NULL) {\n        /* Propagate the [LR]POP operation. */\n        argv[0] = (where == LIST_HEAD) ? shared.lpop :\n                                          shared.rpop;\n        argv[1] = key;\n        propagate((where == LIST_HEAD) ?\n            server.lpopCommand : server.rpopCommand,\n            db->id,argv,2,PROPAGATE_AOF|PROPAGATE_REPL);\n\n        /* BRPOP/BLPOP */\n        addReplyMultiBulkLen(receiver,2);\n        addReplyBulk(receiver,key);\n        addReplyBulk(receiver,value);\n    } else {\n        /* BRPOPLPUSH */\n        robj *dstobj =\n            lookupKeyWrite(receiver->db,dstkey);\n        if (!(dstobj &&\n             checkType(receiver,dstobj,OBJ_LIST)))\n        {\n            /* Propagate the RPOP operation. */\n            argv[0] = shared.rpop;\n            argv[1] = key;\n            propagate(server.rpopCommand,\n                db->id,argv,2,\n                PROPAGATE_AOF|\n                PROPAGATE_REPL);\n            rpoplpushHandlePush(receiver,dstkey,dstobj,\n                value);\n            /* Propagate the LPUSH operation. */\n            argv[0] = shared.lpush;\n            argv[1] = dstkey;\n            argv[2] = value;\n            propagate(server.lpushCommand,\n                db->id,argv,3,\n                PROPAGATE_AOF|\n                PROPAGATE_REPL);\n        } else {\n            /* BRPOPLPUSH failed because of wrong\n             * destination type. */\n            return C_ERR;\n        }\n    }\n    return C_OK;\n}\n\n/* This function should be called by Redis every time a single command,\n * a MULTI/EXEC block, or a Lua script, terminated its execution after\n * being called by a client.\n *\n * All the keys with at least one client blocked that received at least\n * one new element via some PUSH operation are accumulated into\n * the server.ready_keys list. This function will run the list and will\n * serve clients accordingly. Note that the function will iterate again and\n * again as a result of serving BRPOPLPUSH we can have new blocking clients\n * to serve because of the PUSH side of BRPOPLPUSH. */\nvoid handleClientsBlockedOnLists(void) {\n    while(listLength(server.ready_keys) != 0) {\n        list *l;\n\n        /* Point server.ready_keys to a fresh list and save the current one\n         * locally. This way as we run the old list we are free to call\n         * signalListAsReady() that may push new elements in server.ready_keys\n         * when handling clients blocked into BRPOPLPUSH. */\n        l = server.ready_keys;\n        server.ready_keys = listCreate();\n\n        while(listLength(l) != 0) {\n            listNode *ln = listFirst(l);\n            readyList *rl = ln->value;\n\n            /* First of all remove this key from db->ready_keys so that\n             * we can safely call signalListAsReady() against this key. */\n            dictDelete(rl->db->ready_keys,rl->key);\n\n            /* If the key exists and it's a list, serve blocked clients\n             * with data. */\n            robj *o = lookupKeyWrite(rl->db,rl->key);\n            if (o != NULL && o->type == OBJ_LIST) {\n                dictEntry *de;\n\n                /* We serve clients in the same order they blocked for\n                 * this key, from the first blocked to the last. */\n                de = dictFind(rl->db->blocking_keys,rl->key);\n                if (de) {\n                    list *clients = dictGetVal(de);\n                    int numclients = listLength(clients);\n\n                    while(numclients--) {\n                        listNode *clientnode = listFirst(clients);\n                        client *receiver = clientnode->value;\n                        robj *dstkey = receiver->bpop.target;\n                        int where = (receiver->lastcmd &&\n                                     receiver->lastcmd->proc == blpopCommand) ?\n                                    LIST_HEAD : LIST_TAIL;\n                        robj *value = listTypePop(o,where);\n\n                        if (value) {\n                            /* Protect receiver->bpop.target, that will be\n                             * freed by the next unblockClient()\n                             * call. */\n                            if (dstkey) incrRefCount(dstkey);\n                            unblockClient(receiver);\n\n                            if (serveClientBlockedOnList(receiver,\n                                rl->key,dstkey,rl->db,value,\n                                where) == C_ERR)\n                            {\n                                /* If we failed serving the client we need\n                                 * to also undo the POP operation. */\n                                    listTypePush(o,value,where);\n                            }\n\n                            if (dstkey) decrRefCount(dstkey);\n                            decrRefCount(value);\n                        } else {\n                            break;\n                        }\n                    }\n                }\n\n                if (listTypeLength(o) == 0) {\n                    dbDelete(rl->db,rl->key);\n                }\n                /* We don't call signalModifiedKey() as it was already called\n                 * when an element was pushed on the list. */\n            }\n\n            /* Free this item. */\n            decrRefCount(rl->key);\n            zfree(rl);\n            listDelNode(l,ln);\n        }\n        listRelease(l); /* We have the new list on place at this point. */\n    }\n}\n\n/* Blocking RPOP/LPOP */\nvoid blockingPopGenericCommand(client *c, int where) {\n    robj *o;\n    mstime_t timeout;\n    int j;\n\n    if (getTimeoutFromObjectOrReply(c,c->argv[c->argc-1],&timeout,UNIT_SECONDS)\n        != C_OK) return;\n\n    for (j = 1; j < c->argc-1; j++) {\n        o = lookupKeyWrite(c->db,c->argv[j]);\n        if (o != NULL) {\n            if (o->type != OBJ_LIST) {\n                addReply(c,shared.wrongtypeerr);\n                return;\n            } else {\n                if (listTypeLength(o) != 0) {\n                    /* Non empty list, this is like a non normal [LR]POP. */\n                    char *event = (where == LIST_HEAD) ? \"lpop\" : \"rpop\";\n                    robj *value = listTypePop(o,where);\n                    serverAssert(value != NULL);\n\n                    addReplyMultiBulkLen(c,2);\n                    addReplyBulk(c,c->argv[j]);\n                    addReplyBulk(c,value);\n                    decrRefCount(value);\n                    notifyKeyspaceEvent(NOTIFY_LIST,event,\n                                        c->argv[j],c->db->id);\n                    if (listTypeLength(o) == 0) {\n                        dbDelete(c->db,c->argv[j]);\n                        notifyKeyspaceEvent(NOTIFY_GENERIC,\"del\",\n                                            c->argv[j],c->db->id);\n                    }\n                    signalModifiedKey(c->db,c->argv[j]);\n                    server.dirty++;\n\n                    /* Replicate it as an [LR]POP instead of B[LR]POP. */\n                    rewriteClientCommandVector(c,2,\n                        (where == LIST_HEAD) ? shared.lpop : shared.rpop,\n                        c->argv[j]);\n                    return;\n                }\n            }\n        }\n    }\n\n    /* If we are inside a MULTI/EXEC and the list is empty the only thing\n     * we can do is treating it as a timeout (even with timeout 0). */\n    if (c->flags & CLIENT_MULTI) {\n        addReply(c,shared.nullmultibulk);\n        return;\n    }\n\n    /* If the list is empty or the key does not exists we must block */\n    blockForKeys(c, c->argv + 1, c->argc - 2, timeout, NULL);\n}\n\nvoid blpopCommand(client *c) {\n    blockingPopGenericCommand(c,LIST_HEAD);\n}\n\nvoid brpopCommand(client *c) {\n    blockingPopGenericCommand(c,LIST_TAIL);\n}\n\nvoid brpoplpushCommand(client *c) {\n    mstime_t timeout;\n\n    if (getTimeoutFromObjectOrReply(c,c->argv[3],&timeout,UNIT_SECONDS)\n        != C_OK) return;\n\n    robj *key = lookupKeyWrite(c->db, c->argv[1]);\n\n    if (key == NULL) {\n        if (c->flags & CLIENT_MULTI) {\n            /* Blocking against an empty list in a multi state\n             * returns immediately. */\n            addReply(c, shared.nullbulk);\n        } else {\n            /* The list is empty and the client blocks. */\n            blockForKeys(c, c->argv + 1, 1, timeout, c->argv[2]);\n        }\n    } else {\n        if (key->type != OBJ_LIST) {\n            addReply(c, shared.wrongtypeerr);\n        } else {\n            /* The list exists and has elements, so\n             * the regular rpoplpushCommand is executed. */\n            serverAssertWithInfo(c,key,listTypeLength(key) > 0);\n            rpoplpushCommand(c);\n        }\n    }\n}\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/src/t_set.c",
    "content": "/*\n * Copyright (c) 2009-2012, Salvatore Sanfilippo <antirez at gmail dot com>\n * All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions are met:\n *\n *   * Redistributions of source code must retain the above copyright notice,\n *     this list of conditions and the following disclaimer.\n *   * Redistributions in binary form must reproduce the above copyright\n *     notice, this list of conditions and the following disclaimer in the\n *     documentation and/or other materials provided with the distribution.\n *   * Neither the name of Redis nor the names of its contributors may be used\n *     to endorse or promote products derived from this software without\n *     specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\"\n * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\n * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE\n * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR\n * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF\n * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS\n * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN\n * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)\n * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE\n * POSSIBILITY OF SUCH DAMAGE.\n */\n\n#include \"server.h\"\n\n/*-----------------------------------------------------------------------------\n * Set Commands\n *----------------------------------------------------------------------------*/\n\nvoid sunionDiffGenericCommand(client *c, robj **setkeys, int setnum,\n                              robj *dstkey, int op);\n\n/* Factory method to return a set that *can* hold \"value\". When the object has\n * an integer-encodable value, an intset will be returned. Otherwise a regular\n * hash table. */\nrobj *setTypeCreate(robj *value) {\n    if (isObjectRepresentableAsLongLong(value,NULL) == C_OK)\n        return createIntsetObject();\n    return createSetObject();\n}\n\n/* Add the specified value into a set. The function takes care of incrementing\n * the reference count of the object if needed in order to retain a copy.\n *\n * If the value was already member of the set, nothing is done and 0 is\n * returned, otherwise the new element is added and 1 is returned. */\nint setTypeAdd(robj *subject, robj *value) {\n    long long llval;\n    if (subject->encoding == OBJ_ENCODING_HT) {\n        if (dictAdd(subject->ptr,value,NULL) == DICT_OK) {\n            incrRefCount(value);\n            return 1;\n        }\n    } else if (subject->encoding == OBJ_ENCODING_INTSET) {\n        if (isObjectRepresentableAsLongLong(value,&llval) == C_OK) {\n            uint8_t success = 0;\n            subject->ptr = intsetAdd(subject->ptr,llval,&success);\n            if (success) {\n                /* Convert to regular set when the intset contains\n                 * too many entries. */\n                if (intsetLen(subject->ptr) > server.set_max_intset_entries)\n                    setTypeConvert(subject,OBJ_ENCODING_HT);\n                return 1;\n            }\n        } else {\n            /* Failed to get integer from object, convert to regular set. */\n            setTypeConvert(subject,OBJ_ENCODING_HT);\n\n            /* The set *was* an intset and this value is not integer\n             * encodable, so dictAdd should always work. */\n            serverAssertWithInfo(NULL,value,\n                                dictAdd(subject->ptr,value,NULL) == DICT_OK);\n            incrRefCount(value);\n            return 1;\n        }\n    } else {\n        serverPanic(\"Unknown set encoding\");\n    }\n    return 0;\n}\n\nint setTypeRemove(robj *setobj, robj *value) {\n    long long llval;\n    if (setobj->encoding == OBJ_ENCODING_HT) {\n        if (dictDelete(setobj->ptr,value) == DICT_OK) {\n            if (htNeedsResize(setobj->ptr)) dictResize(setobj->ptr);\n            return 1;\n        }\n    } else if (setobj->encoding == OBJ_ENCODING_INTSET) {\n        if (isObjectRepresentableAsLongLong(value,&llval) == C_OK) {\n            int success;\n            setobj->ptr = intsetRemove(setobj->ptr,llval,&success);\n            if (success) return 1;\n        }\n    } else {\n        serverPanic(\"Unknown set encoding\");\n    }\n    return 0;\n}\n\nint setTypeIsMember(robj *subject, robj *value) {\n    long long llval;\n    if (subject->encoding == OBJ_ENCODING_HT) {\n        return dictFind((dict*)subject->ptr,value) != NULL;\n    } else if (subject->encoding == OBJ_ENCODING_INTSET) {\n        if (isObjectRepresentableAsLongLong(value,&llval) == C_OK) {\n            return intsetFind((intset*)subject->ptr,llval);\n        }\n    } else {\n        serverPanic(\"Unknown set encoding\");\n    }\n    return 0;\n}\n\nsetTypeIterator *setTypeInitIterator(robj *subject) {\n    setTypeIterator *si = zmalloc(sizeof(setTypeIterator));\n    si->subject = subject;\n    si->encoding = subject->encoding;\n    if (si->encoding == OBJ_ENCODING_HT) {\n        si->di = dictGetIterator(subject->ptr);\n    } else if (si->encoding == OBJ_ENCODING_INTSET) {\n        si->ii = 0;\n    } else {\n        serverPanic(\"Unknown set encoding\");\n    }\n    return si;\n}\n\nvoid setTypeReleaseIterator(setTypeIterator *si) {\n    if (si->encoding == OBJ_ENCODING_HT)\n        dictReleaseIterator(si->di);\n    zfree(si);\n}\n\n/* Move to the next entry in the set. Returns the object at the current\n * position.\n *\n * Since set elements can be internally be stored as redis objects or\n * simple arrays of integers, setTypeNext returns the encoding of the\n * set object you are iterating, and will populate the appropriate pointer\n * (objele) or (llele) accordingly.\n *\n * Note that both the objele and llele pointers should be passed and cannot\n * be NULL since the function will try to defensively populate the non\n * used field with values which are easy to trap if misused.\n *\n * When there are no longer elements -1 is returned.\n * Returned objects ref count is not incremented, so this function is\n * copy on write friendly. */\nint setTypeNext(setTypeIterator *si, robj **objele, int64_t *llele) {\n    if (si->encoding == OBJ_ENCODING_HT) {\n        dictEntry *de = dictNext(si->di);\n        if (de == NULL) return -1;\n        *objele = dictGetKey(de);\n        *llele = -123456789; /* Not needed. Defensive. */\n    } else if (si->encoding == OBJ_ENCODING_INTSET) {\n        if (!intsetGet(si->subject->ptr,si->ii++,llele))\n            return -1;\n        *objele = NULL; /* Not needed. Defensive. */\n    } else {\n        serverPanic(\"Wrong set encoding in setTypeNext\");\n    }\n    return si->encoding;\n}\n\n/* The not copy on write friendly version but easy to use version\n * of setTypeNext() is setTypeNextObject(), returning new objects\n * or incrementing the ref count of returned objects. So if you don't\n * retain a pointer to this object you should call decrRefCount() against it.\n *\n * This function is the way to go for write operations where COW is not\n * an issue as the result will be anyway of incrementing the ref count. */\nrobj *setTypeNextObject(setTypeIterator *si) {\n    int64_t intele;\n    robj *objele;\n    int encoding;\n\n    encoding = setTypeNext(si,&objele,&intele);\n    switch(encoding) {\n        case -1:    return NULL;\n        case OBJ_ENCODING_INTSET:\n            return createStringObjectFromLongLong(intele);\n        case OBJ_ENCODING_HT:\n            incrRefCount(objele);\n            return objele;\n        default:\n            serverPanic(\"Unsupported encoding\");\n    }\n    return NULL; /* just to suppress warnings */\n}\n\n/* Return random element from a non empty set.\n * The returned element can be a int64_t value if the set is encoded\n * as an \"intset\" blob of integers, or a redis object if the set\n * is a regular set.\n *\n * The caller provides both pointers to be populated with the right\n * object. The return value of the function is the object->encoding\n * field of the object and is used by the caller to check if the\n * int64_t pointer or the redis object pointer was populated.\n *\n * Note that both the objele and llele pointers should be passed and cannot\n * be NULL since the function will try to defensively populate the non\n * used field with values which are easy to trap if misused.\n *\n * When an object is returned (the set was a real set) the ref count\n * of the object is not incremented so this function can be considered\n * copy on write friendly. */\nint setTypeRandomElement(robj *setobj, robj **objele, int64_t *llele) {\n    if (setobj->encoding == OBJ_ENCODING_HT) {\n        dictEntry *de = dictGetRandomKey(setobj->ptr);\n        *objele = dictGetKey(de);\n        *llele = -123456789; /* Not needed. Defensive. */\n    } else if (setobj->encoding == OBJ_ENCODING_INTSET) {\n        *llele = intsetRandom(setobj->ptr);\n        *objele = NULL; /* Not needed. Defensive. */\n    } else {\n        serverPanic(\"Unknown set encoding\");\n    }\n    return setobj->encoding;\n}\n\nunsigned long setTypeSize(robj *subject) {\n    if (subject->encoding == OBJ_ENCODING_HT) {\n        return dictSize((dict*)subject->ptr);\n    } else if (subject->encoding == OBJ_ENCODING_INTSET) {\n        return intsetLen((intset*)subject->ptr);\n    } else {\n        serverPanic(\"Unknown set encoding\");\n    }\n}\n\n/* Convert the set to specified encoding. The resulting dict (when converting\n * to a hash table) is presized to hold the number of elements in the original\n * set. */\nvoid setTypeConvert(robj *setobj, int enc) {\n    setTypeIterator *si;\n    serverAssertWithInfo(NULL,setobj,setobj->type == OBJ_SET &&\n                             setobj->encoding == OBJ_ENCODING_INTSET);\n\n    if (enc == OBJ_ENCODING_HT) {\n        int64_t intele;\n        dict *d = dictCreate(&setDictType,NULL);\n        robj *element;\n\n        /* Presize the dict to avoid rehashing */\n        dictExpand(d,intsetLen(setobj->ptr));\n\n        /* To add the elements we extract integers and create redis objects */\n        si = setTypeInitIterator(setobj);\n        while (setTypeNext(si,&element,&intele) != -1) {\n            element = createStringObjectFromLongLong(intele);\n            serverAssertWithInfo(NULL,element,\n                                dictAdd(d,element,NULL) == DICT_OK);\n        }\n        setTypeReleaseIterator(si);\n\n        setobj->encoding = OBJ_ENCODING_HT;\n        zfree(setobj->ptr);\n        setobj->ptr = d;\n    } else {\n        serverPanic(\"Unsupported set conversion\");\n    }\n}\n\nvoid saddCommand(client *c) {\n    robj *set;\n    int j, added = 0;\n\n    set = lookupKeyWrite(c->db,c->argv[1]);\n    if (set == NULL) {\n        set = setTypeCreate(c->argv[2]);\n        dbAdd(c->db,c->argv[1],set);\n    } else {\n        if (set->type != OBJ_SET) {\n            addReply(c,shared.wrongtypeerr);\n            return;\n        }\n    }\n\n    for (j = 2; j < c->argc; j++) {\n        c->argv[j] = tryObjectEncoding(c->argv[j]);\n        if (setTypeAdd(set,c->argv[j])) added++;\n    }\n    if (added) {\n        signalModifiedKey(c->db,c->argv[1]);\n        notifyKeyspaceEvent(NOTIFY_SET,\"sadd\",c->argv[1],c->db->id);\n    }\n    server.dirty += added;\n    addReplyLongLong(c,added);\n}\n\nvoid sremCommand(client *c) {\n    robj *set;\n    int j, deleted = 0, keyremoved = 0;\n\n    if ((set = lookupKeyWriteOrReply(c,c->argv[1],shared.czero)) == NULL ||\n        checkType(c,set,OBJ_SET)) return;\n\n    for (j = 2; j < c->argc; j++) {\n        if (setTypeRemove(set,c->argv[j])) {\n            deleted++;\n            if (setTypeSize(set) == 0) {\n                dbDelete(c->db,c->argv[1]);\n                keyremoved = 1;\n                break;\n            }\n        }\n    }\n    if (deleted) {\n        signalModifiedKey(c->db,c->argv[1]);\n        notifyKeyspaceEvent(NOTIFY_SET,\"srem\",c->argv[1],c->db->id);\n        if (keyremoved)\n            notifyKeyspaceEvent(NOTIFY_GENERIC,\"del\",c->argv[1],\n                                c->db->id);\n        server.dirty += deleted;\n    }\n    addReplyLongLong(c,deleted);\n}\n\nvoid smoveCommand(client *c) {\n    robj *srcset, *dstset, *ele;\n    srcset = lookupKeyWrite(c->db,c->argv[1]);\n    dstset = lookupKeyWrite(c->db,c->argv[2]);\n    ele = c->argv[3] = tryObjectEncoding(c->argv[3]);\n\n    /* If the source key does not exist return 0 */\n    if (srcset == NULL) {\n        addReply(c,shared.czero);\n        return;\n    }\n\n    /* If the source key has the wrong type, or the destination key\n     * is set and has the wrong type, return with an error. */\n    if (checkType(c,srcset,OBJ_SET) ||\n        (dstset && checkType(c,dstset,OBJ_SET))) return;\n\n    /* If srcset and dstset are equal, SMOVE is a no-op */\n    if (srcset == dstset) {\n        addReply(c,setTypeIsMember(srcset,ele) ? shared.cone : shared.czero);\n        return;\n    }\n\n    /* If the element cannot be removed from the src set, return 0. */\n    if (!setTypeRemove(srcset,ele)) {\n        addReply(c,shared.czero);\n        return;\n    }\n    notifyKeyspaceEvent(NOTIFY_SET,\"srem\",c->argv[1],c->db->id);\n\n    /* Remove the src set from the database when empty */\n    if (setTypeSize(srcset) == 0) {\n        dbDelete(c->db,c->argv[1]);\n        notifyKeyspaceEvent(NOTIFY_GENERIC,\"del\",c->argv[1],c->db->id);\n    }\n\n    /* Create the destination set when it doesn't exist */\n    if (!dstset) {\n        dstset = setTypeCreate(ele);\n        dbAdd(c->db,c->argv[2],dstset);\n    }\n\n    signalModifiedKey(c->db,c->argv[1]);\n    signalModifiedKey(c->db,c->argv[2]);\n    server.dirty++;\n\n    /* An extra key has changed when ele was successfully added to dstset */\n    if (setTypeAdd(dstset,ele)) {\n        server.dirty++;\n        notifyKeyspaceEvent(NOTIFY_SET,\"sadd\",c->argv[2],c->db->id);\n    }\n    addReply(c,shared.cone);\n}\n\nvoid sismemberCommand(client *c) {\n    robj *set;\n\n    if ((set = lookupKeyReadOrReply(c,c->argv[1],shared.czero)) == NULL ||\n        checkType(c,set,OBJ_SET)) return;\n\n    c->argv[2] = tryObjectEncoding(c->argv[2]);\n    if (setTypeIsMember(set,c->argv[2]))\n        addReply(c,shared.cone);\n    else\n        addReply(c,shared.czero);\n}\n\nvoid scardCommand(client *c) {\n    robj *o;\n\n    if ((o = lookupKeyReadOrReply(c,c->argv[1],shared.czero)) == NULL ||\n        checkType(c,o,OBJ_SET)) return;\n\n    addReplyLongLong(c,setTypeSize(o));\n}\n\n/* Handle the \"SPOP key <count>\" variant. The normal version of the\n * command is handled by the spopCommand() function itself. */\n\n/* How many times bigger should be the set compared to the remaining size\n * for us to use the \"create new set\" strategy? Read later in the\n * implementation for more info. */\n#define SPOP_MOVE_STRATEGY_MUL 5\n\nvoid spopWithCountCommand(client *c) {\n    long l;\n    unsigned long count, size;\n    robj *set;\n\n    /* Get the count argument */\n    if (getLongFromObjectOrReply(c,c->argv[2],&l,NULL) != C_OK) return;\n    if (l >= 0) {\n        count = (unsigned) l;\n    } else {\n        addReply(c,shared.outofrangeerr);\n        return;\n    }\n\n    /* Make sure a key with the name inputted exists, and that it's type is\n     * indeed a set. Otherwise, return nil */\n    if ((set = lookupKeyReadOrReply(c,c->argv[1],shared.emptymultibulk))\n        == NULL || checkType(c,set,OBJ_SET)) return;\n\n    /* If count is zero, serve an empty multibulk ASAP to avoid special\n     * cases later. */\n    if (count == 0) {\n        addReply(c,shared.emptymultibulk);\n        return;\n    }\n\n    size = setTypeSize(set);\n\n    /* Generate an SPOP keyspace notification */\n    notifyKeyspaceEvent(NOTIFY_SET,\"spop\",c->argv[1],c->db->id);\n    server.dirty += count;\n\n    /* CASE 1:\n     * The number of requested elements is greater than or equal to\n     * the number of elements inside the set: simply return the whole set. */\n    if (count >= size) {\n        /* We just return the entire set */\n        sunionDiffGenericCommand(c,c->argv+1,1,NULL,SET_OP_UNION);\n\n        /* Delete the set as it is now empty */\n        dbDelete(c->db,c->argv[1]);\n        notifyKeyspaceEvent(NOTIFY_GENERIC,\"del\",c->argv[1],c->db->id);\n\n        /* Propagate this command as an DEL operation */\n        rewriteClientCommandVector(c,2,shared.del,c->argv[1]);\n        signalModifiedKey(c->db,c->argv[1]);\n        server.dirty++;\n        return;\n    }\n\n    /* Case 2 and 3 require to replicate SPOP as a set of SERM commands.\n     * Prepare our replication argument vector. Also send the array length\n     * which is common to both the code paths. */\n    robj *propargv[3];\n    propargv[0] = createStringObject(\"SREM\",4);\n    propargv[1] = c->argv[1];\n    addReplyMultiBulkLen(c,count);\n\n    /* Common iteration vars. */\n    robj *objele;\n    int encoding;\n    int64_t llele;\n    unsigned long remaining = size-count; /* Elements left after SPOP. */\n\n    /* If we are here, the number of requested elements is less than the\n     * number of elements inside the set. Also we are sure that count < size.\n     * Use two different strategies.\n     *\n     * CASE 2: The number of elements to return is small compared to the\n     * set size. We can just extract random elements and return them to\n     * the set. */\n    if (remaining*SPOP_MOVE_STRATEGY_MUL > count) {\n        while(count--) {\n            encoding = setTypeRandomElement(set,&objele,&llele);\n            if (encoding == OBJ_ENCODING_INTSET) {\n                objele = createStringObjectFromLongLong(llele);\n            } else {\n                incrRefCount(objele);\n            }\n\n            /* Return the element to the client and remove from the set. */\n            addReplyBulk(c,objele);\n            setTypeRemove(set,objele);\n\n            /* Replicate/AOF this command as an SREM operation */\n            propargv[2] = objele;\n            alsoPropagate(server.sremCommand,c->db->id,propargv,3,\n                PROPAGATE_AOF|PROPAGATE_REPL);\n            decrRefCount(objele);\n        }\n    } else {\n    /* CASE 3: The number of elements to return is very big, approaching\n     * the size of the set itself. After some time extracting random elements\n     * from such a set becomes computationally expensive, so we use\n     * a different strategy, we extract random elements that we don't\n     * want to return (the elements that will remain part of the set),\n     * creating a new set as we do this (that will be stored as the original\n     * set). Then we return the elements left in the original set and\n     * release it. */\n        robj *newset = NULL;\n\n        /* Create a new set with just the remaining elements. */\n        while(remaining--) {\n            encoding = setTypeRandomElement(set,&objele,&llele);\n            if (encoding == OBJ_ENCODING_INTSET) {\n                objele = createStringObjectFromLongLong(llele);\n            } else {\n                incrRefCount(objele);\n            }\n            if (!newset) newset = setTypeCreate(objele);\n            setTypeAdd(newset,objele);\n            setTypeRemove(set,objele);\n            decrRefCount(objele);\n        }\n\n        /* Assign the new set as the key value. */\n        incrRefCount(set); /* Protect the old set value. */\n        dbOverwrite(c->db,c->argv[1],newset);\n\n        /* Tranfer the old set to the client and release it. */\n        setTypeIterator *si;\n        si = setTypeInitIterator(set);\n        while((encoding = setTypeNext(si,&objele,&llele)) != -1) {\n            if (encoding == OBJ_ENCODING_INTSET) {\n                objele = createStringObjectFromLongLong(llele);\n            } else {\n                incrRefCount(objele);\n            }\n            addReplyBulk(c,objele);\n\n            /* Replicate/AOF this command as an SREM operation */\n            propargv[2] = objele;\n            alsoPropagate(server.sremCommand,c->db->id,propargv,3,\n                PROPAGATE_AOF|PROPAGATE_REPL);\n\n            decrRefCount(objele);\n        }\n        setTypeReleaseIterator(si);\n        decrRefCount(set);\n    }\n\n    /* Don't propagate the command itself even if we incremented the\n     * dirty counter. We don't want to propagate an SPOP command since\n     * we propagated the command as a set of SREMs operations using\n     * the alsoPropagate() API. */\n    decrRefCount(propargv[0]);\n    preventCommandPropagation(c);\n    signalModifiedKey(c->db,c->argv[1]);\n    server.dirty++;\n}\n\nvoid spopCommand(client *c) {\n    robj *set, *ele, *aux;\n    int64_t llele;\n    int encoding;\n\n    if (c->argc == 3) {\n        spopWithCountCommand(c);\n        return;\n    } else if (c->argc > 3) {\n        addReply(c,shared.syntaxerr);\n        return;\n    }\n\n    /* Make sure a key with the name inputted exists, and that it's type is\n     * indeed a set */\n    if ((set = lookupKeyWriteOrReply(c,c->argv[1],shared.nullbulk)) == NULL ||\n        checkType(c,set,OBJ_SET)) return;\n\n    /* Get a random element from the set */\n    encoding = setTypeRandomElement(set,&ele,&llele);\n\n    /* Remove the element from the set */\n    if (encoding == OBJ_ENCODING_INTSET) {\n        ele = createStringObjectFromLongLong(llele);\n        set->ptr = intsetRemove(set->ptr,llele,NULL);\n    } else {\n        incrRefCount(ele);\n        setTypeRemove(set,ele);\n    }\n\n    notifyKeyspaceEvent(NOTIFY_SET,\"spop\",c->argv[1],c->db->id);\n\n    /* Replicate/AOF this command as an SREM operation */\n    aux = createStringObject(\"SREM\",4);\n    rewriteClientCommandVector(c,3,aux,c->argv[1],ele);\n    decrRefCount(ele);\n    decrRefCount(aux);\n\n    /* Add the element to the reply */\n    addReplyBulk(c,ele);\n\n    /* Delete the set if it's empty */\n    if (setTypeSize(set) == 0) {\n        dbDelete(c->db,c->argv[1]);\n        notifyKeyspaceEvent(NOTIFY_GENERIC,\"del\",c->argv[1],c->db->id);\n    }\n\n    /* Set has been modified */\n    signalModifiedKey(c->db,c->argv[1]);\n    server.dirty++;\n}\n\n/* handle the \"SRANDMEMBER key <count>\" variant. The normal version of the\n * command is handled by the srandmemberCommand() function itself. */\n\n/* How many times bigger should be the set compared to the requested size\n * for us to don't use the \"remove elements\" strategy? Read later in the\n * implementation for more info. */\n#define SRANDMEMBER_SUB_STRATEGY_MUL 3\n\nvoid srandmemberWithCountCommand(client *c) {\n    long l;\n    unsigned long count, size;\n    int uniq = 1;\n    robj *set, *ele;\n    int64_t llele;\n    int encoding;\n\n    dict *d;\n\n    if (getLongFromObjectOrReply(c,c->argv[2],&l,NULL) != C_OK) return;\n    if (l >= 0) {\n        count = (unsigned) l;\n    } else {\n        /* A negative count means: return the same elements multiple times\n         * (i.e. don't remove the extracted element after every extraction). */\n        count = -l;\n        uniq = 0;\n    }\n\n    if ((set = lookupKeyReadOrReply(c,c->argv[1],shared.emptymultibulk))\n        == NULL || checkType(c,set,OBJ_SET)) return;\n    size = setTypeSize(set);\n\n    /* If count is zero, serve it ASAP to avoid special cases later. */\n    if (count == 0) {\n        addReply(c,shared.emptymultibulk);\n        return;\n    }\n\n    /* CASE 1: The count was negative, so the extraction method is just:\n     * \"return N random elements\" sampling the whole set every time.\n     * This case is trivial and can be served without auxiliary data\n     * structures. */\n    if (!uniq) {\n        addReplyMultiBulkLen(c,count);\n        while(count--) {\n            encoding = setTypeRandomElement(set,&ele,&llele);\n            if (encoding == OBJ_ENCODING_INTSET) {\n                addReplyBulkLongLong(c,llele);\n            } else {\n                addReplyBulk(c,ele);\n            }\n        }\n        return;\n    }\n\n    /* CASE 2:\n     * The number of requested elements is greater than the number of\n     * elements inside the set: simply return the whole set. */\n    if (count >= size) {\n        sunionDiffGenericCommand(c,c->argv+1,1,NULL,SET_OP_UNION);\n        return;\n    }\n\n    /* For CASE 3 and CASE 4 we need an auxiliary dictionary. */\n    d = dictCreate(&setDictType,NULL);\n\n    /* CASE 3:\n     * The number of elements inside the set is not greater than\n     * SRANDMEMBER_SUB_STRATEGY_MUL times the number of requested elements.\n     * In this case we create a set from scratch with all the elements, and\n     * subtract random elements to reach the requested number of elements.\n     *\n     * This is done because if the number of requsted elements is just\n     * a bit less than the number of elements in the set, the natural approach\n     * used into CASE 3 is highly inefficient. */\n    if (count*SRANDMEMBER_SUB_STRATEGY_MUL > size) {\n        setTypeIterator *si;\n\n        /* Add all the elements into the temporary dictionary. */\n        si = setTypeInitIterator(set);\n        while((encoding = setTypeNext(si,&ele,&llele)) != -1) {\n            int retval = DICT_ERR;\n\n            if (encoding == OBJ_ENCODING_INTSET) {\n                retval = dictAdd(d,createStringObjectFromLongLong(llele),NULL);\n            } else {\n                retval = dictAdd(d,dupStringObject(ele),NULL);\n            }\n            serverAssert(retval == DICT_OK);\n        }\n        setTypeReleaseIterator(si);\n        serverAssert(dictSize(d) == size);\n\n        /* Remove random elements to reach the right count. */\n        while(size > count) {\n            dictEntry *de;\n\n            de = dictGetRandomKey(d);\n            dictDelete(d,dictGetKey(de));\n            size--;\n        }\n    }\n\n    /* CASE 4: We have a big set compared to the requested number of elements.\n     * In this case we can simply get random elements from the set and add\n     * to the temporary set, trying to eventually get enough unique elements\n     * to reach the specified count. */\n    else {\n        unsigned long added = 0;\n\n        while(added < count) {\n            encoding = setTypeRandomElement(set,&ele,&llele);\n            if (encoding == OBJ_ENCODING_INTSET) {\n                ele = createStringObjectFromLongLong(llele);\n            } else {\n                ele = dupStringObject(ele);\n            }\n            /* Try to add the object to the dictionary. If it already exists\n             * free it, otherwise increment the number of objects we have\n             * in the result dictionary. */\n            if (dictAdd(d,ele,NULL) == DICT_OK)\n                added++;\n            else\n                decrRefCount(ele);\n        }\n    }\n\n    /* CASE 3 & 4: send the result to the user. */\n    {\n        dictIterator *di;\n        dictEntry *de;\n\n        addReplyMultiBulkLen(c,count);\n        di = dictGetIterator(d);\n        while((de = dictNext(di)) != NULL)\n            addReplyBulk(c,dictGetKey(de));\n        dictReleaseIterator(di);\n        dictRelease(d);\n    }\n}\n\nvoid srandmemberCommand(client *c) {\n    robj *set, *ele;\n    int64_t llele;\n    int encoding;\n\n    if (c->argc == 3) {\n        srandmemberWithCountCommand(c);\n        return;\n    } else if (c->argc > 3) {\n        addReply(c,shared.syntaxerr);\n        return;\n    }\n\n    if ((set = lookupKeyReadOrReply(c,c->argv[1],shared.nullbulk)) == NULL ||\n        checkType(c,set,OBJ_SET)) return;\n\n    encoding = setTypeRandomElement(set,&ele,&llele);\n    if (encoding == OBJ_ENCODING_INTSET) {\n        addReplyBulkLongLong(c,llele);\n    } else {\n        addReplyBulk(c,ele);\n    }\n}\n\nint qsortCompareSetsByCardinality(const void *s1, const void *s2) {\n    return setTypeSize(*(robj**)s1)-setTypeSize(*(robj**)s2);\n}\n\n/* This is used by SDIFF and in this case we can receive NULL that should\n * be handled as empty sets. */\nint qsortCompareSetsByRevCardinality(const void *s1, const void *s2) {\n    robj *o1 = *(robj**)s1, *o2 = *(robj**)s2;\n\n    return  (o2 ? setTypeSize(o2) : 0) - (o1 ? setTypeSize(o1) : 0);\n}\n\nvoid sinterGenericCommand(client *c, robj **setkeys,\n                          unsigned long setnum, robj *dstkey) {\n    robj **sets = zmalloc(sizeof(robj*)*setnum);\n    setTypeIterator *si;\n    robj *eleobj, *dstset = NULL;\n    int64_t intobj;\n    void *replylen = NULL;\n    unsigned long j, cardinality = 0;\n    int encoding;\n\n    for (j = 0; j < setnum; j++) {\n        robj *setobj = dstkey ?\n            lookupKeyWrite(c->db,setkeys[j]) :\n            lookupKeyRead(c->db,setkeys[j]);\n        if (!setobj) {\n            zfree(sets);\n            if (dstkey) {\n                if (dbDelete(c->db,dstkey)) {\n                    signalModifiedKey(c->db,dstkey);\n                    server.dirty++;\n                }\n                addReply(c,shared.czero);\n            } else {\n                addReply(c,shared.emptymultibulk);\n            }\n            return;\n        }\n        if (checkType(c,setobj,OBJ_SET)) {\n            zfree(sets);\n            return;\n        }\n        sets[j] = setobj;\n    }\n    /* Sort sets from the smallest to largest, this will improve our\n     * algorithm's performance */\n    qsort(sets,setnum,sizeof(robj*),qsortCompareSetsByCardinality);\n\n    /* The first thing we should output is the total number of elements...\n     * since this is a multi-bulk write, but at this stage we don't know\n     * the intersection set size, so we use a trick, append an empty object\n     * to the output list and save the pointer to later modify it with the\n     * right length */\n    if (!dstkey) {\n        replylen = addDeferredMultiBulkLength(c);\n    } else {\n        /* If we have a target key where to store the resulting set\n         * create this key with an empty set inside */\n        dstset = createIntsetObject();\n    }\n\n    /* Iterate all the elements of the first (smallest) set, and test\n     * the element against all the other sets, if at least one set does\n     * not include the element it is discarded */\n    si = setTypeInitIterator(sets[0]);\n    while((encoding = setTypeNext(si,&eleobj,&intobj)) != -1) {\n        for (j = 1; j < setnum; j++) {\n            if (sets[j] == sets[0]) continue;\n            if (encoding == OBJ_ENCODING_INTSET) {\n                /* intset with intset is simple... and fast */\n                if (sets[j]->encoding == OBJ_ENCODING_INTSET &&\n                    !intsetFind((intset*)sets[j]->ptr,intobj))\n                {\n                    break;\n                /* in order to compare an integer with an object we\n                 * have to use the generic function, creating an object\n                 * for this */\n                } else if (sets[j]->encoding == OBJ_ENCODING_HT) {\n                    eleobj = createStringObjectFromLongLong(intobj);\n                    if (!setTypeIsMember(sets[j],eleobj)) {\n                        decrRefCount(eleobj);\n                        break;\n                    }\n                    decrRefCount(eleobj);\n                }\n            } else if (encoding == OBJ_ENCODING_HT) {\n                /* Optimization... if the source object is integer\n                 * encoded AND the target set is an intset, we can get\n                 * a much faster path. */\n                if (eleobj->encoding == OBJ_ENCODING_INT &&\n                    sets[j]->encoding == OBJ_ENCODING_INTSET &&\n                    !intsetFind((intset*)sets[j]->ptr,(long)eleobj->ptr))\n                {\n                    break;\n                /* else... object to object check is easy as we use the\n                 * type agnostic API here. */\n                } else if (!setTypeIsMember(sets[j],eleobj)) {\n                    break;\n                }\n            }\n        }\n\n        /* Only take action when all sets contain the member */\n        if (j == setnum) {\n            if (!dstkey) {\n                if (encoding == OBJ_ENCODING_HT)\n                    addReplyBulk(c,eleobj);\n                else\n                    addReplyBulkLongLong(c,intobj);\n                cardinality++;\n            } else {\n                if (encoding == OBJ_ENCODING_INTSET) {\n                    eleobj = createStringObjectFromLongLong(intobj);\n                    setTypeAdd(dstset,eleobj);\n                    decrRefCount(eleobj);\n                } else {\n                    setTypeAdd(dstset,eleobj);\n                }\n            }\n        }\n    }\n    setTypeReleaseIterator(si);\n\n    if (dstkey) {\n        /* Store the resulting set into the target, if the intersection\n         * is not an empty set. */\n        int deleted = dbDelete(c->db,dstkey);\n        if (setTypeSize(dstset) > 0) {\n            dbAdd(c->db,dstkey,dstset);\n            addReplyLongLong(c,setTypeSize(dstset));\n            notifyKeyspaceEvent(NOTIFY_SET,\"sinterstore\",\n                dstkey,c->db->id);\n        } else {\n            decrRefCount(dstset);\n            addReply(c,shared.czero);\n            if (deleted)\n                notifyKeyspaceEvent(NOTIFY_GENERIC,\"del\",\n                    dstkey,c->db->id);\n        }\n        signalModifiedKey(c->db,dstkey);\n        server.dirty++;\n    } else {\n        setDeferredMultiBulkLength(c,replylen,cardinality);\n    }\n    zfree(sets);\n}\n\nvoid sinterCommand(client *c) {\n    sinterGenericCommand(c,c->argv+1,c->argc-1,NULL);\n}\n\nvoid sinterstoreCommand(client *c) {\n    sinterGenericCommand(c,c->argv+2,c->argc-2,c->argv[1]);\n}\n\n#define SET_OP_UNION 0\n#define SET_OP_DIFF 1\n#define SET_OP_INTER 2\n\nvoid sunionDiffGenericCommand(client *c, robj **setkeys, int setnum,\n                              robj *dstkey, int op) {\n    robj **sets = zmalloc(sizeof(robj*)*setnum);\n    setTypeIterator *si;\n    robj *ele, *dstset = NULL;\n    int j, cardinality = 0;\n    int diff_algo = 1;\n\n    for (j = 0; j < setnum; j++) {\n        robj *setobj = dstkey ?\n            lookupKeyWrite(c->db,setkeys[j]) :\n            lookupKeyRead(c->db,setkeys[j]);\n        if (!setobj) {\n            sets[j] = NULL;\n            continue;\n        }\n        if (checkType(c,setobj,OBJ_SET)) {\n            zfree(sets);\n            return;\n        }\n        sets[j] = setobj;\n    }\n\n    /* Select what DIFF algorithm to use.\n     *\n     * Algorithm 1 is O(N*M) where N is the size of the element first set\n     * and M the total number of sets.\n     *\n     * Algorithm 2 is O(N) where N is the total number of elements in all\n     * the sets.\n     *\n     * We compute what is the best bet with the current input here. */\n    if (op == SET_OP_DIFF && sets[0]) {\n        long long algo_one_work = 0, algo_two_work = 0;\n\n        for (j = 0; j < setnum; j++) {\n            if (sets[j] == NULL) continue;\n\n            algo_one_work += setTypeSize(sets[0]);\n            algo_two_work += setTypeSize(sets[j]);\n        }\n\n        /* Algorithm 1 has better constant times and performs less operations\n         * if there are elements in common. Give it some advantage. */\n        algo_one_work /= 2;\n        diff_algo = (algo_one_work <= algo_two_work) ? 1 : 2;\n\n        if (diff_algo == 1 && setnum > 1) {\n            /* With algorithm 1 it is better to order the sets to subtract\n             * by decreasing size, so that we are more likely to find\n             * duplicated elements ASAP. */\n            qsort(sets+1,setnum-1,sizeof(robj*),\n                qsortCompareSetsByRevCardinality);\n        }\n    }\n\n    /* We need a temp set object to store our union. If the dstkey\n     * is not NULL (that is, we are inside an SUNIONSTORE operation) then\n     * this set object will be the resulting object to set into the target key*/\n    dstset = createIntsetObject();\n\n    if (op == SET_OP_UNION) {\n        /* Union is trivial, just add every element of every set to the\n         * temporary set. */\n        for (j = 0; j < setnum; j++) {\n            if (!sets[j]) continue; /* non existing keys are like empty sets */\n\n            si = setTypeInitIterator(sets[j]);\n            while((ele = setTypeNextObject(si)) != NULL) {\n                if (setTypeAdd(dstset,ele)) cardinality++;\n                decrRefCount(ele);\n            }\n            setTypeReleaseIterator(si);\n        }\n    } else if (op == SET_OP_DIFF && sets[0] && diff_algo == 1) {\n        /* DIFF Algorithm 1:\n         *\n         * We perform the diff by iterating all the elements of the first set,\n         * and only adding it to the target set if the element does not exist\n         * into all the other sets.\n         *\n         * This way we perform at max N*M operations, where N is the size of\n         * the first set, and M the number of sets. */\n        si = setTypeInitIterator(sets[0]);\n        while((ele = setTypeNextObject(si)) != NULL) {\n            for (j = 1; j < setnum; j++) {\n                if (!sets[j]) continue; /* no key is an empty set. */\n                if (sets[j] == sets[0]) break; /* same set! */\n                if (setTypeIsMember(sets[j],ele)) break;\n            }\n            if (j == setnum) {\n                /* There is no other set with this element. Add it. */\n                setTypeAdd(dstset,ele);\n                cardinality++;\n            }\n            decrRefCount(ele);\n        }\n        setTypeReleaseIterator(si);\n    } else if (op == SET_OP_DIFF && sets[0] && diff_algo == 2) {\n        /* DIFF Algorithm 2:\n         *\n         * Add all the elements of the first set to the auxiliary set.\n         * Then remove all the elements of all the next sets from it.\n         *\n         * This is O(N) where N is the sum of all the elements in every\n         * set. */\n        for (j = 0; j < setnum; j++) {\n            if (!sets[j]) continue; /* non existing keys are like empty sets */\n\n            si = setTypeInitIterator(sets[j]);\n            while((ele = setTypeNextObject(si)) != NULL) {\n                if (j == 0) {\n                    if (setTypeAdd(dstset,ele)) cardinality++;\n                } else {\n                    if (setTypeRemove(dstset,ele)) cardinality--;\n                }\n                decrRefCount(ele);\n            }\n            setTypeReleaseIterator(si);\n\n            /* Exit if result set is empty as any additional removal\n             * of elements will have no effect. */\n            if (cardinality == 0) break;\n        }\n    }\n\n    /* Output the content of the resulting set, if not in STORE mode */\n    if (!dstkey) {\n        addReplyMultiBulkLen(c,cardinality);\n        si = setTypeInitIterator(dstset);\n        while((ele = setTypeNextObject(si)) != NULL) {\n            addReplyBulk(c,ele);\n            decrRefCount(ele);\n        }\n        setTypeReleaseIterator(si);\n        decrRefCount(dstset);\n    } else {\n        /* If we have a target key where to store the resulting set\n         * create this key with the result set inside */\n        int deleted = dbDelete(c->db,dstkey);\n        if (setTypeSize(dstset) > 0) {\n            dbAdd(c->db,dstkey,dstset);\n            addReplyLongLong(c,setTypeSize(dstset));\n            notifyKeyspaceEvent(NOTIFY_SET,\n                op == SET_OP_UNION ? \"sunionstore\" : \"sdiffstore\",\n                dstkey,c->db->id);\n        } else {\n            decrRefCount(dstset);\n            addReply(c,shared.czero);\n            if (deleted)\n                notifyKeyspaceEvent(NOTIFY_GENERIC,\"del\",\n                    dstkey,c->db->id);\n        }\n        signalModifiedKey(c->db,dstkey);\n        server.dirty++;\n    }\n    zfree(sets);\n}\n\nvoid sunionCommand(client *c) {\n    sunionDiffGenericCommand(c,c->argv+1,c->argc-1,NULL,SET_OP_UNION);\n}\n\nvoid sunionstoreCommand(client *c) {\n    sunionDiffGenericCommand(c,c->argv+2,c->argc-2,c->argv[1],SET_OP_UNION);\n}\n\nvoid sdiffCommand(client *c) {\n    sunionDiffGenericCommand(c,c->argv+1,c->argc-1,NULL,SET_OP_DIFF);\n}\n\nvoid sdiffstoreCommand(client *c) {\n    sunionDiffGenericCommand(c,c->argv+2,c->argc-2,c->argv[1],SET_OP_DIFF);\n}\n\nvoid sscanCommand(client *c) {\n    robj *set;\n    unsigned long cursor;\n\n    if (parseScanCursorOrReply(c,c->argv[2],&cursor) == C_ERR) return;\n    if ((set = lookupKeyReadOrReply(c,c->argv[1],shared.emptyscan)) == NULL ||\n        checkType(c,set,OBJ_SET)) return;\n    scanGenericCommand(c,set,cursor);\n}\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/src/t_string.c",
    "content": "/*\n * Copyright (c) 2009-2012, Salvatore Sanfilippo <antirez at gmail dot com>\n * All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions are met:\n *\n *   * Redistributions of source code must retain the above copyright notice,\n *     this list of conditions and the following disclaimer.\n *   * Redistributions in binary form must reproduce the above copyright\n *     notice, this list of conditions and the following disclaimer in the\n *     documentation and/or other materials provided with the distribution.\n *   * Neither the name of Redis nor the names of its contributors may be used\n *     to endorse or promote products derived from this software without\n *     specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\"\n * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\n * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE\n * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR\n * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF\n * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS\n * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN\n * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)\n * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE\n * POSSIBILITY OF SUCH DAMAGE.\n */\n\n#include \"server.h\"\n#include <math.h> /* isnan(), isinf() */\n\n/*-----------------------------------------------------------------------------\n * String Commands\n *----------------------------------------------------------------------------*/\n\nstatic int checkStringLength(client *c, long long size) {\n    if (size > 512*1024*1024) {\n        addReplyError(c,\"string exceeds maximum allowed size (512MB)\");\n        return C_ERR;\n    }\n    return C_OK;\n}\n\n/* The setGenericCommand() function implements the SET operation with different\n * options and variants. This function is called in order to implement the\n * following commands: SET, SETEX, PSETEX, SETNX.\n *\n * 'flags' changes the behavior of the command (NX or XX, see belove).\n *\n * 'expire' represents an expire to set in form of a Redis object as passed\n * by the user. It is interpreted according to the specified 'unit'.\n *\n * 'ok_reply' and 'abort_reply' is what the function will reply to the client\n * if the operation is performed, or when it is not because of NX or\n * XX flags.\n *\n * If ok_reply is NULL \"+OK\" is used.\n * If abort_reply is NULL, \"$-1\" is used. */\n\n#define OBJ_SET_NO_FLAGS 0\n#define OBJ_SET_NX (1<<0)     /* Set if key not exists. */\n#define OBJ_SET_XX (1<<1)     /* Set if key exists. */\n#define OBJ_SET_EX (1<<2)     /* Set if time in seconds is given */\n#define OBJ_SET_PX (1<<3)     /* Set if time in ms in given */\n\nvoid setGenericCommand(client *c, int flags, robj *key, robj *val, robj *expire, int unit, robj *ok_reply, robj *abort_reply) {\n    long long milliseconds = 0; /* initialized to avoid any harmness warning */\n\n    if (expire) {\n        if (getLongLongFromObjectOrReply(c, expire, &milliseconds, NULL) != C_OK)\n            return;\n        if (milliseconds <= 0) {\n            addReplyErrorFormat(c,\"invalid expire time in %s\",c->cmd->name);\n            return;\n        }\n        if (unit == UNIT_SECONDS) milliseconds *= 1000;\n    }\n\n    if ((flags & OBJ_SET_NX && lookupKeyWrite(c->db,key) != NULL) ||\n        (flags & OBJ_SET_XX && lookupKeyWrite(c->db,key) == NULL))\n    {\n        addReply(c, abort_reply ? abort_reply : shared.nullbulk);\n        return;\n    }\n    setKey(c->db,key,val);\n    server.dirty++;\n    if (expire) setExpire(c->db,key,mstime()+milliseconds);\n    notifyKeyspaceEvent(NOTIFY_STRING,\"set\",key,c->db->id);\n    if (expire) notifyKeyspaceEvent(NOTIFY_GENERIC,\n        \"expire\",key,c->db->id);\n    addReply(c, ok_reply ? ok_reply : shared.ok);\n}\n\n/* SET key value [NX] [XX] [EX <seconds>] [PX <milliseconds>] */\nvoid setCommand(client *c) {\n    int j;\n    robj *expire = NULL;\n    int unit = UNIT_SECONDS;\n    int flags = OBJ_SET_NO_FLAGS;\n\n    for (j = 3; j < c->argc; j++) {\n        char *a = c->argv[j]->ptr;\n        robj *next = (j == c->argc-1) ? NULL : c->argv[j+1];\n\n        if ((a[0] == 'n' || a[0] == 'N') &&\n            (a[1] == 'x' || a[1] == 'X') && a[2] == '\\0' &&\n            !(flags & OBJ_SET_XX))\n        {\n            flags |= OBJ_SET_NX;\n        } else if ((a[0] == 'x' || a[0] == 'X') &&\n                   (a[1] == 'x' || a[1] == 'X') && a[2] == '\\0' &&\n                   !(flags & OBJ_SET_NX))\n        {\n            flags |= OBJ_SET_XX;\n        } else if ((a[0] == 'e' || a[0] == 'E') &&\n                   (a[1] == 'x' || a[1] == 'X') && a[2] == '\\0' &&\n                   !(flags & OBJ_SET_PX) && next)\n        {\n            flags |= OBJ_SET_EX;\n            unit = UNIT_SECONDS;\n            expire = next;\n            j++;\n        } else if ((a[0] == 'p' || a[0] == 'P') &&\n                   (a[1] == 'x' || a[1] == 'X') && a[2] == '\\0' &&\n                   !(flags & OBJ_SET_EX) && next)\n        {\n            flags |= OBJ_SET_PX;\n            unit = UNIT_MILLISECONDS;\n            expire = next;\n            j++;\n        } else {\n            addReply(c,shared.syntaxerr);\n            return;\n        }\n    }\n\n    c->argv[2] = tryObjectEncoding(c->argv[2]);\n    setGenericCommand(c,flags,c->argv[1],c->argv[2],expire,unit,NULL,NULL);\n}\n\nvoid setnxCommand(client *c) {\n    c->argv[2] = tryObjectEncoding(c->argv[2]);\n    setGenericCommand(c,OBJ_SET_NX,c->argv[1],c->argv[2],NULL,0,shared.cone,shared.czero);\n}\n\nvoid setexCommand(client *c) {\n    c->argv[3] = tryObjectEncoding(c->argv[3]);\n    setGenericCommand(c,OBJ_SET_NO_FLAGS,c->argv[1],c->argv[3],c->argv[2],UNIT_SECONDS,NULL,NULL);\n}\n\nvoid psetexCommand(client *c) {\n    c->argv[3] = tryObjectEncoding(c->argv[3]);\n    setGenericCommand(c,OBJ_SET_NO_FLAGS,c->argv[1],c->argv[3],c->argv[2],UNIT_MILLISECONDS,NULL,NULL);\n}\n\nint getGenericCommand(client *c) {\n    robj *o;\n\n    if ((o = lookupKeyReadOrReply(c,c->argv[1],shared.nullbulk)) == NULL)\n        return C_OK;\n\n    if (o->type != OBJ_STRING) {\n        addReply(c,shared.wrongtypeerr);\n        return C_ERR;\n    } else {\n        addReplyBulk(c,o);\n        return C_OK;\n    }\n}\n\nvoid getCommand(client *c) {\n    getGenericCommand(c);\n}\n\nvoid getsetCommand(client *c) {\n    if (getGenericCommand(c) == C_ERR) return;\n    c->argv[2] = tryObjectEncoding(c->argv[2]);\n    setKey(c->db,c->argv[1],c->argv[2]);\n    notifyKeyspaceEvent(NOTIFY_STRING,\"set\",c->argv[1],c->db->id);\n    server.dirty++;\n}\n\nvoid setrangeCommand(client *c) {\n    robj *o;\n    long offset;\n    sds value = c->argv[3]->ptr;\n\n    if (getLongFromObjectOrReply(c,c->argv[2],&offset,NULL) != C_OK)\n        return;\n\n    if (offset < 0) {\n        addReplyError(c,\"offset is out of range\");\n        return;\n    }\n\n    o = lookupKeyWrite(c->db,c->argv[1]);\n    if (o == NULL) {\n        /* Return 0 when setting nothing on a non-existing string */\n        if (sdslen(value) == 0) {\n            addReply(c,shared.czero);\n            return;\n        }\n\n        /* Return when the resulting string exceeds allowed size */\n        if (checkStringLength(c,offset+sdslen(value)) != C_OK)\n            return;\n\n        o = createObject(OBJ_STRING,sdsnewlen(NULL, offset+sdslen(value)));\n        dbAdd(c->db,c->argv[1],o);\n    } else {\n        size_t olen;\n\n        /* Key exists, check type */\n        if (checkType(c,o,OBJ_STRING))\n            return;\n\n        /* Return existing string length when setting nothing */\n        olen = stringObjectLen(o);\n        if (sdslen(value) == 0) {\n            addReplyLongLong(c,olen);\n            return;\n        }\n\n        /* Return when the resulting string exceeds allowed size */\n        if (checkStringLength(c,offset+sdslen(value)) != C_OK)\n            return;\n\n        /* Create a copy when the object is shared or encoded. */\n        o = dbUnshareStringValue(c->db,c->argv[1],o);\n    }\n\n    if (sdslen(value) > 0) {\n        o->ptr = sdsgrowzero(o->ptr,offset+sdslen(value));\n        memcpy((char*)o->ptr+offset,value,sdslen(value));\n        signalModifiedKey(c->db,c->argv[1]);\n        notifyKeyspaceEvent(NOTIFY_STRING,\n            \"setrange\",c->argv[1],c->db->id);\n        server.dirty++;\n    }\n    addReplyLongLong(c,sdslen(o->ptr));\n}\n\nvoid getrangeCommand(client *c) {\n    robj *o;\n    long long start, end;\n    char *str, llbuf[32];\n    size_t strlen;\n\n    if (getLongLongFromObjectOrReply(c,c->argv[2],&start,NULL) != C_OK)\n        return;\n    if (getLongLongFromObjectOrReply(c,c->argv[3],&end,NULL) != C_OK)\n        return;\n    if ((o = lookupKeyReadOrReply(c,c->argv[1],shared.emptybulk)) == NULL ||\n        checkType(c,o,OBJ_STRING)) return;\n\n    if (o->encoding == OBJ_ENCODING_INT) {\n        str = llbuf;\n        strlen = ll2string(llbuf,sizeof(llbuf),(long)o->ptr);\n    } else {\n        str = o->ptr;\n        strlen = sdslen(str);\n    }\n\n    /* Convert negative indexes */\n    if (start < 0 && end < 0 && start > end) {\n        addReply(c,shared.emptybulk);\n        return;\n    }\n    if (start < 0) start = strlen+start;\n    if (end < 0) end = strlen+end;\n    if (start < 0) start = 0;\n    if (end < 0) end = 0;\n    if ((unsigned long long)end >= strlen) end = strlen-1;\n\n    /* Precondition: end >= 0 && end < strlen, so the only condition where\n     * nothing can be returned is: start > end. */\n    if (start > end || strlen == 0) {\n        addReply(c,shared.emptybulk);\n    } else {\n        addReplyBulkCBuffer(c,(char*)str+start,end-start+1);\n    }\n}\n\nvoid mgetCommand(client *c) {\n    int j;\n\n    addReplyMultiBulkLen(c,c->argc-1);\n    for (j = 1; j < c->argc; j++) {\n        robj *o = lookupKeyRead(c->db,c->argv[j]);\n        if (o == NULL) {\n            addReply(c,shared.nullbulk);\n        } else {\n            if (o->type != OBJ_STRING) {\n                addReply(c,shared.nullbulk);\n            } else {\n                addReplyBulk(c,o);\n            }\n        }\n    }\n}\n\nvoid msetGenericCommand(client *c, int nx) {\n    int j, busykeys = 0;\n\n    if ((c->argc % 2) == 0) {\n        addReplyError(c,\"wrong number of arguments for MSET\");\n        return;\n    }\n    /* Handle the NX flag. The MSETNX semantic is to return zero and don't\n     * set nothing at all if at least one already key exists. */\n    if (nx) {\n        for (j = 1; j < c->argc; j += 2) {\n            if (lookupKeyWrite(c->db,c->argv[j]) != NULL) {\n                busykeys++;\n            }\n        }\n        if (busykeys) {\n            addReply(c, shared.czero);\n            return;\n        }\n    }\n\n    for (j = 1; j < c->argc; j += 2) {\n        c->argv[j+1] = tryObjectEncoding(c->argv[j+1]);\n        setKey(c->db,c->argv[j],c->argv[j+1]);\n        notifyKeyspaceEvent(NOTIFY_STRING,\"set\",c->argv[j],c->db->id);\n    }\n    server.dirty += (c->argc-1)/2;\n    addReply(c, nx ? shared.cone : shared.ok);\n}\n\nvoid msetCommand(client *c) {\n    msetGenericCommand(c,0);\n}\n\nvoid msetnxCommand(client *c) {\n    msetGenericCommand(c,1);\n}\n\nvoid incrDecrCommand(client *c, long long incr) {\n    long long value, oldvalue;\n    robj *o, *new;\n\n    o = lookupKeyWrite(c->db,c->argv[1]);\n    if (o != NULL && checkType(c,o,OBJ_STRING)) return;\n    if (getLongLongFromObjectOrReply(c,o,&value,NULL) != C_OK) return;\n\n    oldvalue = value;\n    if ((incr < 0 && oldvalue < 0 && incr < (LLONG_MIN-oldvalue)) ||\n        (incr > 0 && oldvalue > 0 && incr > (LLONG_MAX-oldvalue))) {\n        addReplyError(c,\"increment or decrement would overflow\");\n        return;\n    }\n    value += incr;\n\n    if (o && o->refcount == 1 && o->encoding == OBJ_ENCODING_INT &&\n        (value < 0 || value >= OBJ_SHARED_INTEGERS) &&\n        value >= LONG_MIN && value <= LONG_MAX)\n    {\n        new = o;\n        o->ptr = (void*)((long)value);\n    } else {\n        new = createStringObjectFromLongLong(value);\n        if (o) {\n            dbOverwrite(c->db,c->argv[1],new);\n        } else {\n            dbAdd(c->db,c->argv[1],new);\n        }\n    }\n    signalModifiedKey(c->db,c->argv[1]);\n    notifyKeyspaceEvent(NOTIFY_STRING,\"incrby\",c->argv[1],c->db->id);\n    server.dirty++;\n    addReply(c,shared.colon);\n    addReply(c,new);\n    addReply(c,shared.crlf);\n}\n\nvoid incrCommand(client *c) {\n    incrDecrCommand(c,1);\n}\n\nvoid decrCommand(client *c) {\n    incrDecrCommand(c,-1);\n}\n\nvoid incrbyCommand(client *c) {\n    long long incr;\n\n    if (getLongLongFromObjectOrReply(c, c->argv[2], &incr, NULL) != C_OK) return;\n    incrDecrCommand(c,incr);\n}\n\nvoid decrbyCommand(client *c) {\n    long long incr;\n\n    if (getLongLongFromObjectOrReply(c, c->argv[2], &incr, NULL) != C_OK) return;\n    incrDecrCommand(c,-incr);\n}\n\nvoid incrbyfloatCommand(client *c) {\n    long double incr, value;\n    robj *o, *new, *aux;\n\n    o = lookupKeyWrite(c->db,c->argv[1]);\n    if (o != NULL && checkType(c,o,OBJ_STRING)) return;\n    if (getLongDoubleFromObjectOrReply(c,o,&value,NULL) != C_OK ||\n        getLongDoubleFromObjectOrReply(c,c->argv[2],&incr,NULL) != C_OK)\n        return;\n\n    value += incr;\n    if (isnan(value) || isinf(value)) {\n        addReplyError(c,\"increment would produce NaN or Infinity\");\n        return;\n    }\n    new = createStringObjectFromLongDouble(value,1);\n    if (o)\n        dbOverwrite(c->db,c->argv[1],new);\n    else\n        dbAdd(c->db,c->argv[1],new);\n    signalModifiedKey(c->db,c->argv[1]);\n    notifyKeyspaceEvent(NOTIFY_STRING,\"incrbyfloat\",c->argv[1],c->db->id);\n    server.dirty++;\n    addReplyBulk(c,new);\n\n    /* Always replicate INCRBYFLOAT as a SET command with the final value\n     * in order to make sure that differences in float precision or formatting\n     * will not create differences in replicas or after an AOF restart. */\n    aux = createStringObject(\"SET\",3);\n    rewriteClientCommandArgument(c,0,aux);\n    decrRefCount(aux);\n    rewriteClientCommandArgument(c,2,new);\n}\n\nvoid appendCommand(client *c) {\n    size_t totlen;\n    robj *o, *append;\n\n    o = lookupKeyWrite(c->db,c->argv[1]);\n    if (o == NULL) {\n        /* Create the key */\n        c->argv[2] = tryObjectEncoding(c->argv[2]);\n        dbAdd(c->db,c->argv[1],c->argv[2]);\n        incrRefCount(c->argv[2]);\n        totlen = stringObjectLen(c->argv[2]);\n    } else {\n        /* Key exists, check type */\n        if (checkType(c,o,OBJ_STRING))\n            return;\n\n        /* \"append\" is an argument, so always an sds */\n        append = c->argv[2];\n        totlen = stringObjectLen(o)+sdslen(append->ptr);\n        if (checkStringLength(c,totlen) != C_OK)\n            return;\n\n        /* Append the value */\n        o = dbUnshareStringValue(c->db,c->argv[1],o);\n        o->ptr = sdscatlen(o->ptr,append->ptr,sdslen(append->ptr));\n        totlen = sdslen(o->ptr);\n    }\n    signalModifiedKey(c->db,c->argv[1]);\n    notifyKeyspaceEvent(NOTIFY_STRING,\"append\",c->argv[1],c->db->id);\n    server.dirty++;\n    addReplyLongLong(c,totlen);\n}\n\nvoid strlenCommand(client *c) {\n    robj *o;\n    if ((o = lookupKeyReadOrReply(c,c->argv[1],shared.czero)) == NULL ||\n        checkType(c,o,OBJ_STRING)) return;\n    addReplyLongLong(c,stringObjectLen(o));\n}\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/src/t_zset.c",
    "content": "/*\n * Copyright (c) 2009-2012, Salvatore Sanfilippo <antirez at gmail dot com>\n * Copyright (c) 2009-2012, Pieter Noordhuis <pcnoordhuis at gmail dot com>\n * All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions are met:\n *\n *   * Redistributions of source code must retain the above copyright notice,\n *     this list of conditions and the following disclaimer.\n *   * Redistributions in binary form must reproduce the above copyright\n *     notice, this list of conditions and the following disclaimer in the\n *     documentation and/or other materials provided with the distribution.\n *   * Neither the name of Redis nor the names of its contributors may be used\n *     to endorse or promote products derived from this software without\n *     specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\"\n * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\n * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE\n * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR\n * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF\n * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS\n * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN\n * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)\n * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE\n * POSSIBILITY OF SUCH DAMAGE.\n */\n\n/*-----------------------------------------------------------------------------\n * Sorted set API\n *----------------------------------------------------------------------------*/\n\n/* ZSETs are ordered sets using two data structures to hold the same elements\n * in order to get O(log(N)) INSERT and REMOVE operations into a sorted\n * data structure.\n *\n * The elements are added to a hash table mapping Redis objects to scores.\n * At the same time the elements are added to a skip list mapping scores\n * to Redis objects (so objects are sorted by scores in this \"view\"). */\n\n/* This skiplist implementation is almost a C translation of the original\n * algorithm described by William Pugh in \"Skip Lists: A Probabilistic\n * Alternative to Balanced Trees\", modified in three ways:\n * a) this implementation allows for repeated scores.\n * b) the comparison is not just by key (our 'score') but by satellite data.\n * c) there is a back pointer, so it's a doubly linked list with the back\n * pointers being only at \"level 1\". This allows to traverse the list\n * from tail to head, useful for ZREVRANGE. */\n\n#include \"server.h\"\n#include <math.h>\n\nstatic int zslLexValueGteMin(robj *value, zlexrangespec *spec);\nstatic int zslLexValueLteMax(robj *value, zlexrangespec *spec);\n\nzskiplistNode *zslCreateNode(int level, double score, robj *obj) {\n    zskiplistNode *zn = zmalloc(sizeof(*zn)+level*sizeof(struct zskiplistLevel));\n    zn->score = score;\n    zn->obj = obj;\n    return zn;\n}\n\nzskiplist *zslCreate(void) {\n    int j;\n    zskiplist *zsl;\n\n    zsl = zmalloc(sizeof(*zsl));\n    zsl->level = 1;\n    zsl->length = 0;\n    zsl->header = zslCreateNode(ZSKIPLIST_MAXLEVEL,0,NULL);\n    for (j = 0; j < ZSKIPLIST_MAXLEVEL; j++) {\n        zsl->header->level[j].forward = NULL;\n        zsl->header->level[j].span = 0;\n    }\n    zsl->header->backward = NULL;\n    zsl->tail = NULL;\n    return zsl;\n}\n\nvoid zslFreeNode(zskiplistNode *node) {\n    decrRefCount(node->obj);\n    zfree(node);\n}\n\nvoid zslFree(zskiplist *zsl) {\n    zskiplistNode *node = zsl->header->level[0].forward, *next;\n\n    zfree(zsl->header);\n    while(node) {\n        next = node->level[0].forward;\n        zslFreeNode(node);\n        node = next;\n    }\n    zfree(zsl);\n}\n\n/* Returns a random level for the new skiplist node we are going to create.\n * The return value of this function is between 1 and ZSKIPLIST_MAXLEVEL\n * (both inclusive), with a powerlaw-alike distribution where higher\n * levels are less likely to be returned. */\nint zslRandomLevel(void) {\n    int level = 1;\n    while ((random()&0xFFFF) < (ZSKIPLIST_P * 0xFFFF))\n        level += 1;\n    return (level<ZSKIPLIST_MAXLEVEL) ? level : ZSKIPLIST_MAXLEVEL;\n}\n\nzskiplistNode *zslInsert(zskiplist *zsl, double score, robj *obj) {\n    zskiplistNode *update[ZSKIPLIST_MAXLEVEL], *x;\n    unsigned int rank[ZSKIPLIST_MAXLEVEL];\n    int i, level;\n\n    serverAssert(!isnan(score));\n    x = zsl->header;\n    for (i = zsl->level-1; i >= 0; i--) {\n        /* store rank that is crossed to reach the insert position */\n        rank[i] = i == (zsl->level-1) ? 0 : rank[i+1];\n        while (x->level[i].forward &&\n            (x->level[i].forward->score < score ||\n                (x->level[i].forward->score == score &&\n                compareStringObjects(x->level[i].forward->obj,obj) < 0))) {\n            rank[i] += x->level[i].span;\n            x = x->level[i].forward;\n        }\n        update[i] = x;\n    }\n    /* we assume the key is not already inside, since we allow duplicated\n     * scores, and the re-insertion of score and redis object should never\n     * happen since the caller of zslInsert() should test in the hash table\n     * if the element is already inside or not. */\n    level = zslRandomLevel();\n    if (level > zsl->level) {\n        for (i = zsl->level; i < level; i++) {\n            rank[i] = 0;\n            update[i] = zsl->header;\n            update[i]->level[i].span = zsl->length;\n        }\n        zsl->level = level;\n    }\n    x = zslCreateNode(level,score,obj);\n    for (i = 0; i < level; i++) {\n        x->level[i].forward = update[i]->level[i].forward;\n        update[i]->level[i].forward = x;\n\n        /* update span covered by update[i] as x is inserted here */\n        x->level[i].span = update[i]->level[i].span - (rank[0] - rank[i]);\n        update[i]->level[i].span = (rank[0] - rank[i]) + 1;\n    }\n\n    /* increment span for untouched levels */\n    for (i = level; i < zsl->level; i++) {\n        update[i]->level[i].span++;\n    }\n\n    x->backward = (update[0] == zsl->header) ? NULL : update[0];\n    if (x->level[0].forward)\n        x->level[0].forward->backward = x;\n    else\n        zsl->tail = x;\n    zsl->length++;\n    return x;\n}\n\n/* Internal function used by zslDelete, zslDeleteByScore and zslDeleteByRank */\nvoid zslDeleteNode(zskiplist *zsl, zskiplistNode *x, zskiplistNode **update) {\n    int i;\n    for (i = 0; i < zsl->level; i++) {\n        if (update[i]->level[i].forward == x) {\n            update[i]->level[i].span += x->level[i].span - 1;\n            update[i]->level[i].forward = x->level[i].forward;\n        } else {\n            update[i]->level[i].span -= 1;\n        }\n    }\n    if (x->level[0].forward) {\n        x->level[0].forward->backward = x->backward;\n    } else {\n        zsl->tail = x->backward;\n    }\n    while(zsl->level > 1 && zsl->header->level[zsl->level-1].forward == NULL)\n        zsl->level--;\n    zsl->length--;\n}\n\n/* Delete an element with matching score/object from the skiplist. */\nint zslDelete(zskiplist *zsl, double score, robj *obj) {\n    zskiplistNode *update[ZSKIPLIST_MAXLEVEL], *x;\n    int i;\n\n    x = zsl->header;\n    for (i = zsl->level-1; i >= 0; i--) {\n        while (x->level[i].forward &&\n            (x->level[i].forward->score < score ||\n                (x->level[i].forward->score == score &&\n                compareStringObjects(x->level[i].forward->obj,obj) < 0)))\n            x = x->level[i].forward;\n        update[i] = x;\n    }\n    /* We may have multiple elements with the same score, what we need\n     * is to find the element with both the right score and object. */\n    x = x->level[0].forward;\n    if (x && score == x->score && equalStringObjects(x->obj,obj)) {\n        zslDeleteNode(zsl, x, update);\n        zslFreeNode(x);\n        return 1;\n    }\n    return 0; /* not found */\n}\n\nstatic int zslValueGteMin(double value, zrangespec *spec) {\n    return spec->minex ? (value > spec->min) : (value >= spec->min);\n}\n\nint zslValueLteMax(double value, zrangespec *spec) {\n    return spec->maxex ? (value < spec->max) : (value <= spec->max);\n}\n\n/* Returns if there is a part of the zset is in range. */\nint zslIsInRange(zskiplist *zsl, zrangespec *range) {\n    zskiplistNode *x;\n\n    /* Test for ranges that will always be empty. */\n    if (range->min > range->max ||\n            (range->min == range->max && (range->minex || range->maxex)))\n        return 0;\n    x = zsl->tail;\n    if (x == NULL || !zslValueGteMin(x->score,range))\n        return 0;\n    x = zsl->header->level[0].forward;\n    if (x == NULL || !zslValueLteMax(x->score,range))\n        return 0;\n    return 1;\n}\n\n/* Find the first node that is contained in the specified range.\n * Returns NULL when no element is contained in the range. */\nzskiplistNode *zslFirstInRange(zskiplist *zsl, zrangespec *range) {\n    zskiplistNode *x;\n    int i;\n\n    /* If everything is out of range, return early. */\n    if (!zslIsInRange(zsl,range)) return NULL;\n\n    x = zsl->header;\n    for (i = zsl->level-1; i >= 0; i--) {\n        /* Go forward while *OUT* of range. */\n        while (x->level[i].forward &&\n            !zslValueGteMin(x->level[i].forward->score,range))\n                x = x->level[i].forward;\n    }\n\n    /* This is an inner range, so the next node cannot be NULL. */\n    x = x->level[0].forward;\n    serverAssert(x != NULL);\n\n    /* Check if score <= max. */\n    if (!zslValueLteMax(x->score,range)) return NULL;\n    return x;\n}\n\n/* Find the last node that is contained in the specified range.\n * Returns NULL when no element is contained in the range. */\nzskiplistNode *zslLastInRange(zskiplist *zsl, zrangespec *range) {\n    zskiplistNode *x;\n    int i;\n\n    /* If everything is out of range, return early. */\n    if (!zslIsInRange(zsl,range)) return NULL;\n\n    x = zsl->header;\n    for (i = zsl->level-1; i >= 0; i--) {\n        /* Go forward while *IN* range. */\n        while (x->level[i].forward &&\n            zslValueLteMax(x->level[i].forward->score,range))\n                x = x->level[i].forward;\n    }\n\n    /* This is an inner range, so this node cannot be NULL. */\n    serverAssert(x != NULL);\n\n    /* Check if score >= min. */\n    if (!zslValueGteMin(x->score,range)) return NULL;\n    return x;\n}\n\n/* Delete all the elements with score between min and max from the skiplist.\n * Min and max are inclusive, so a score >= min || score <= max is deleted.\n * Note that this function takes the reference to the hash table view of the\n * sorted set, in order to remove the elements from the hash table too. */\nunsigned long zslDeleteRangeByScore(zskiplist *zsl, zrangespec *range, dict *dict) {\n    zskiplistNode *update[ZSKIPLIST_MAXLEVEL], *x;\n    unsigned long removed = 0;\n    int i;\n\n    x = zsl->header;\n    for (i = zsl->level-1; i >= 0; i--) {\n        while (x->level[i].forward && (range->minex ?\n            x->level[i].forward->score <= range->min :\n            x->level[i].forward->score < range->min))\n                x = x->level[i].forward;\n        update[i] = x;\n    }\n\n    /* Current node is the last with score < or <= min. */\n    x = x->level[0].forward;\n\n    /* Delete nodes while in range. */\n    while (x &&\n           (range->maxex ? x->score < range->max : x->score <= range->max))\n    {\n        zskiplistNode *next = x->level[0].forward;\n        zslDeleteNode(zsl,x,update);\n        dictDelete(dict,x->obj);\n        zslFreeNode(x);\n        removed++;\n        x = next;\n    }\n    return removed;\n}\n\nunsigned long zslDeleteRangeByLex(zskiplist *zsl, zlexrangespec *range, dict *dict) {\n    zskiplistNode *update[ZSKIPLIST_MAXLEVEL], *x;\n    unsigned long removed = 0;\n    int i;\n\n\n    x = zsl->header;\n    for (i = zsl->level-1; i >= 0; i--) {\n        while (x->level[i].forward &&\n            !zslLexValueGteMin(x->level[i].forward->obj,range))\n                x = x->level[i].forward;\n        update[i] = x;\n    }\n\n    /* Current node is the last with score < or <= min. */\n    x = x->level[0].forward;\n\n    /* Delete nodes while in range. */\n    while (x && zslLexValueLteMax(x->obj,range)) {\n        zskiplistNode *next = x->level[0].forward;\n        zslDeleteNode(zsl,x,update);\n        dictDelete(dict,x->obj);\n        zslFreeNode(x);\n        removed++;\n        x = next;\n    }\n    return removed;\n}\n\n/* Delete all the elements with rank between start and end from the skiplist.\n * Start and end are inclusive. Note that start and end need to be 1-based */\nunsigned long zslDeleteRangeByRank(zskiplist *zsl, unsigned int start, unsigned int end, dict *dict) {\n    zskiplistNode *update[ZSKIPLIST_MAXLEVEL], *x;\n    unsigned long traversed = 0, removed = 0;\n    int i;\n\n    x = zsl->header;\n    for (i = zsl->level-1; i >= 0; i--) {\n        while (x->level[i].forward && (traversed + x->level[i].span) < start) {\n            traversed += x->level[i].span;\n            x = x->level[i].forward;\n        }\n        update[i] = x;\n    }\n\n    traversed++;\n    x = x->level[0].forward;\n    while (x && traversed <= end) {\n        zskiplistNode *next = x->level[0].forward;\n        zslDeleteNode(zsl,x,update);\n        dictDelete(dict,x->obj);\n        zslFreeNode(x);\n        removed++;\n        traversed++;\n        x = next;\n    }\n    return removed;\n}\n\n/* Find the rank for an element by both score and key.\n * Returns 0 when the element cannot be found, rank otherwise.\n * Note that the rank is 1-based due to the span of zsl->header to the\n * first element. */\nunsigned long zslGetRank(zskiplist *zsl, double score, robj *o) {\n    zskiplistNode *x;\n    unsigned long rank = 0;\n    int i;\n\n    x = zsl->header;\n    for (i = zsl->level-1; i >= 0; i--) {\n        while (x->level[i].forward &&\n            (x->level[i].forward->score < score ||\n                (x->level[i].forward->score == score &&\n                compareStringObjects(x->level[i].forward->obj,o) <= 0))) {\n            rank += x->level[i].span;\n            x = x->level[i].forward;\n        }\n\n        /* x might be equal to zsl->header, so test if obj is non-NULL */\n        if (x->obj && equalStringObjects(x->obj,o)) {\n            return rank;\n        }\n    }\n    return 0;\n}\n\n/* Finds an element by its rank. The rank argument needs to be 1-based. */\nzskiplistNode* zslGetElementByRank(zskiplist *zsl, unsigned long rank) {\n    zskiplistNode *x;\n    unsigned long traversed = 0;\n    int i;\n\n    x = zsl->header;\n    for (i = zsl->level-1; i >= 0; i--) {\n        while (x->level[i].forward && (traversed + x->level[i].span) <= rank)\n        {\n            traversed += x->level[i].span;\n            x = x->level[i].forward;\n        }\n        if (traversed == rank) {\n            return x;\n        }\n    }\n    return NULL;\n}\n\n/* Populate the rangespec according to the objects min and max. */\nstatic int zslParseRange(robj *min, robj *max, zrangespec *spec) {\n    char *eptr;\n    spec->minex = spec->maxex = 0;\n\n    /* Parse the min-max interval. If one of the values is prefixed\n     * by the \"(\" character, it's considered \"open\". For instance\n     * ZRANGEBYSCORE zset (1.5 (2.5 will match min < x < max\n     * ZRANGEBYSCORE zset 1.5 2.5 will instead match min <= x <= max */\n    if (min->encoding == OBJ_ENCODING_INT) {\n        spec->min = (long)min->ptr;\n    } else {\n        if (((char*)min->ptr)[0] == '(') {\n            spec->min = strtod((char*)min->ptr+1,&eptr);\n            if (eptr[0] != '\\0' || isnan(spec->min)) return C_ERR;\n            spec->minex = 1;\n        } else {\n            spec->min = strtod((char*)min->ptr,&eptr);\n            if (eptr[0] != '\\0' || isnan(spec->min)) return C_ERR;\n        }\n    }\n    if (max->encoding == OBJ_ENCODING_INT) {\n        spec->max = (long)max->ptr;\n    } else {\n        if (((char*)max->ptr)[0] == '(') {\n            spec->max = strtod((char*)max->ptr+1,&eptr);\n            if (eptr[0] != '\\0' || isnan(spec->max)) return C_ERR;\n            spec->maxex = 1;\n        } else {\n            spec->max = strtod((char*)max->ptr,&eptr);\n            if (eptr[0] != '\\0' || isnan(spec->max)) return C_ERR;\n        }\n    }\n\n    return C_OK;\n}\n\n/* ------------------------ Lexicographic ranges ---------------------------- */\n\n/* Parse max or min argument of ZRANGEBYLEX.\n  * (foo means foo (open interval)\n  * [foo means foo (closed interval)\n  * - means the min string possible\n  * + means the max string possible\n  *\n  * If the string is valid the *dest pointer is set to the redis object\n  * that will be used for the comparision, and ex will be set to 0 or 1\n  * respectively if the item is exclusive or inclusive. C_OK will be\n  * returned.\n  *\n  * If the string is not a valid range C_ERR is returned, and the value\n  * of *dest and *ex is undefined. */\nint zslParseLexRangeItem(robj *item, robj **dest, int *ex) {\n    char *c = item->ptr;\n\n    switch(c[0]) {\n    case '+':\n        if (c[1] != '\\0') return C_ERR;\n        *ex = 0;\n        *dest = shared.maxstring;\n        incrRefCount(shared.maxstring);\n        return C_OK;\n    case '-':\n        if (c[1] != '\\0') return C_ERR;\n        *ex = 0;\n        *dest = shared.minstring;\n        incrRefCount(shared.minstring);\n        return C_OK;\n    case '(':\n        *ex = 1;\n        *dest = createStringObject(c+1,sdslen(c)-1);\n        return C_OK;\n    case '[':\n        *ex = 0;\n        *dest = createStringObject(c+1,sdslen(c)-1);\n        return C_OK;\n    default:\n        return C_ERR;\n    }\n}\n\n/* Populate the rangespec according to the objects min and max.\n *\n * Return C_OK on success. On error C_ERR is returned.\n * When OK is returned the structure must be freed with zslFreeLexRange(),\n * otherwise no release is needed. */\nstatic int zslParseLexRange(robj *min, robj *max, zlexrangespec *spec) {\n    /* The range can't be valid if objects are integer encoded.\n     * Every item must start with ( or [. */\n    if (min->encoding == OBJ_ENCODING_INT ||\n        max->encoding == OBJ_ENCODING_INT) return C_ERR;\n\n    spec->min = spec->max = NULL;\n    if (zslParseLexRangeItem(min, &spec->min, &spec->minex) == C_ERR ||\n        zslParseLexRangeItem(max, &spec->max, &spec->maxex) == C_ERR) {\n        if (spec->min) decrRefCount(spec->min);\n        if (spec->max) decrRefCount(spec->max);\n        return C_ERR;\n    } else {\n        return C_OK;\n    }\n}\n\n/* Free a lex range structure, must be called only after zelParseLexRange()\n * populated the structure with success (C_OK returned). */\nvoid zslFreeLexRange(zlexrangespec *spec) {\n    decrRefCount(spec->min);\n    decrRefCount(spec->max);\n}\n\n/* This is just a wrapper to compareStringObjects() that is able to\n * handle shared.minstring and shared.maxstring as the equivalent of\n * -inf and +inf for strings */\nint compareStringObjectsForLexRange(robj *a, robj *b) {\n    if (a == b) return 0; /* This makes sure that we handle inf,inf and\n                             -inf,-inf ASAP. One special case less. */\n    if (a == shared.minstring || b == shared.maxstring) return -1;\n    if (a == shared.maxstring || b == shared.minstring) return 1;\n    return compareStringObjects(a,b);\n}\n\nstatic int zslLexValueGteMin(robj *value, zlexrangespec *spec) {\n    return spec->minex ?\n        (compareStringObjectsForLexRange(value,spec->min) > 0) :\n        (compareStringObjectsForLexRange(value,spec->min) >= 0);\n}\n\nstatic int zslLexValueLteMax(robj *value, zlexrangespec *spec) {\n    return spec->maxex ?\n        (compareStringObjectsForLexRange(value,spec->max) < 0) :\n        (compareStringObjectsForLexRange(value,spec->max) <= 0);\n}\n\n/* Returns if there is a part of the zset is in the lex range. */\nint zslIsInLexRange(zskiplist *zsl, zlexrangespec *range) {\n    zskiplistNode *x;\n\n    /* Test for ranges that will always be empty. */\n    if (compareStringObjectsForLexRange(range->min,range->max) > 1 ||\n            (compareStringObjects(range->min,range->max) == 0 &&\n            (range->minex || range->maxex)))\n        return 0;\n    x = zsl->tail;\n    if (x == NULL || !zslLexValueGteMin(x->obj,range))\n        return 0;\n    x = zsl->header->level[0].forward;\n    if (x == NULL || !zslLexValueLteMax(x->obj,range))\n        return 0;\n    return 1;\n}\n\n/* Find the first node that is contained in the specified lex range.\n * Returns NULL when no element is contained in the range. */\nzskiplistNode *zslFirstInLexRange(zskiplist *zsl, zlexrangespec *range) {\n    zskiplistNode *x;\n    int i;\n\n    /* If everything is out of range, return early. */\n    if (!zslIsInLexRange(zsl,range)) return NULL;\n\n    x = zsl->header;\n    for (i = zsl->level-1; i >= 0; i--) {\n        /* Go forward while *OUT* of range. */\n        while (x->level[i].forward &&\n            !zslLexValueGteMin(x->level[i].forward->obj,range))\n                x = x->level[i].forward;\n    }\n\n    /* This is an inner range, so the next node cannot be NULL. */\n    x = x->level[0].forward;\n    serverAssert(x != NULL);\n\n    /* Check if score <= max. */\n    if (!zslLexValueLteMax(x->obj,range)) return NULL;\n    return x;\n}\n\n/* Find the last node that is contained in the specified range.\n * Returns NULL when no element is contained in the range. */\nzskiplistNode *zslLastInLexRange(zskiplist *zsl, zlexrangespec *range) {\n    zskiplistNode *x;\n    int i;\n\n    /* If everything is out of range, return early. */\n    if (!zslIsInLexRange(zsl,range)) return NULL;\n\n    x = zsl->header;\n    for (i = zsl->level-1; i >= 0; i--) {\n        /* Go forward while *IN* range. */\n        while (x->level[i].forward &&\n            zslLexValueLteMax(x->level[i].forward->obj,range))\n                x = x->level[i].forward;\n    }\n\n    /* This is an inner range, so this node cannot be NULL. */\n    serverAssert(x != NULL);\n\n    /* Check if score >= min. */\n    if (!zslLexValueGteMin(x->obj,range)) return NULL;\n    return x;\n}\n\n/*-----------------------------------------------------------------------------\n * Ziplist-backed sorted set API\n *----------------------------------------------------------------------------*/\n\ndouble zzlGetScore(unsigned char *sptr) {\n    unsigned char *vstr;\n    unsigned int vlen;\n    long long vlong;\n    char buf[128];\n    double score;\n\n    serverAssert(sptr != NULL);\n    serverAssert(ziplistGet(sptr,&vstr,&vlen,&vlong));\n\n    if (vstr) {\n        memcpy(buf,vstr,vlen);\n        buf[vlen] = '\\0';\n        score = strtod(buf,NULL);\n    } else {\n        score = vlong;\n    }\n\n    return score;\n}\n\n/* Return a ziplist element as a Redis string object.\n * This simple abstraction can be used to simplifies some code at the\n * cost of some performance. */\nrobj *ziplistGetObject(unsigned char *sptr) {\n    unsigned char *vstr;\n    unsigned int vlen;\n    long long vlong;\n\n    serverAssert(sptr != NULL);\n    serverAssert(ziplistGet(sptr,&vstr,&vlen,&vlong));\n\n    if (vstr) {\n        return createStringObject((char*)vstr,vlen);\n    } else {\n        return createStringObjectFromLongLong(vlong);\n    }\n}\n\n/* Compare element in sorted set with given element. */\nint zzlCompareElements(unsigned char *eptr, unsigned char *cstr, unsigned int clen) {\n    unsigned char *vstr;\n    unsigned int vlen;\n    long long vlong;\n    unsigned char vbuf[32];\n    int minlen, cmp;\n\n    serverAssert(ziplistGet(eptr,&vstr,&vlen,&vlong));\n    if (vstr == NULL) {\n        /* Store string representation of long long in buf. */\n        vlen = ll2string((char*)vbuf,sizeof(vbuf),vlong);\n        vstr = vbuf;\n    }\n\n    minlen = (vlen < clen) ? vlen : clen;\n    cmp = memcmp(vstr,cstr,minlen);\n    if (cmp == 0) return vlen-clen;\n    return cmp;\n}\n\nunsigned int zzlLength(unsigned char *zl) {\n    return ziplistLen(zl)/2;\n}\n\n/* Move to next entry based on the values in eptr and sptr. Both are set to\n * NULL when there is no next entry. */\nvoid zzlNext(unsigned char *zl, unsigned char **eptr, unsigned char **sptr) {\n    unsigned char *_eptr, *_sptr;\n    serverAssert(*eptr != NULL && *sptr != NULL);\n\n    _eptr = ziplistNext(zl,*sptr);\n    if (_eptr != NULL) {\n        _sptr = ziplistNext(zl,_eptr);\n        serverAssert(_sptr != NULL);\n    } else {\n        /* No next entry. */\n        _sptr = NULL;\n    }\n\n    *eptr = _eptr;\n    *sptr = _sptr;\n}\n\n/* Move to the previous entry based on the values in eptr and sptr. Both are\n * set to NULL when there is no next entry. */\nvoid zzlPrev(unsigned char *zl, unsigned char **eptr, unsigned char **sptr) {\n    unsigned char *_eptr, *_sptr;\n    serverAssert(*eptr != NULL && *sptr != NULL);\n\n    _sptr = ziplistPrev(zl,*eptr);\n    if (_sptr != NULL) {\n        _eptr = ziplistPrev(zl,_sptr);\n        serverAssert(_eptr != NULL);\n    } else {\n        /* No previous entry. */\n        _eptr = NULL;\n    }\n\n    *eptr = _eptr;\n    *sptr = _sptr;\n}\n\n/* Returns if there is a part of the zset is in range. Should only be used\n * internally by zzlFirstInRange and zzlLastInRange. */\nint zzlIsInRange(unsigned char *zl, zrangespec *range) {\n    unsigned char *p;\n    double score;\n\n    /* Test for ranges that will always be empty. */\n    if (range->min > range->max ||\n            (range->min == range->max && (range->minex || range->maxex)))\n        return 0;\n\n    p = ziplistIndex(zl,-1); /* Last score. */\n    if (p == NULL) return 0; /* Empty sorted set */\n    score = zzlGetScore(p);\n    if (!zslValueGteMin(score,range))\n        return 0;\n\n    p = ziplistIndex(zl,1); /* First score. */\n    serverAssert(p != NULL);\n    score = zzlGetScore(p);\n    if (!zslValueLteMax(score,range))\n        return 0;\n\n    return 1;\n}\n\n/* Find pointer to the first element contained in the specified range.\n * Returns NULL when no element is contained in the range. */\nunsigned char *zzlFirstInRange(unsigned char *zl, zrangespec *range) {\n    unsigned char *eptr = ziplistIndex(zl,0), *sptr;\n    double score;\n\n    /* If everything is out of range, return early. */\n    if (!zzlIsInRange(zl,range)) return NULL;\n\n    while (eptr != NULL) {\n        sptr = ziplistNext(zl,eptr);\n        serverAssert(sptr != NULL);\n\n        score = zzlGetScore(sptr);\n        if (zslValueGteMin(score,range)) {\n            /* Check if score <= max. */\n            if (zslValueLteMax(score,range))\n                return eptr;\n            return NULL;\n        }\n\n        /* Move to next element. */\n        eptr = ziplistNext(zl,sptr);\n    }\n\n    return NULL;\n}\n\n/* Find pointer to the last element contained in the specified range.\n * Returns NULL when no element is contained in the range. */\nunsigned char *zzlLastInRange(unsigned char *zl, zrangespec *range) {\n    unsigned char *eptr = ziplistIndex(zl,-2), *sptr;\n    double score;\n\n    /* If everything is out of range, return early. */\n    if (!zzlIsInRange(zl,range)) return NULL;\n\n    while (eptr != NULL) {\n        sptr = ziplistNext(zl,eptr);\n        serverAssert(sptr != NULL);\n\n        score = zzlGetScore(sptr);\n        if (zslValueLteMax(score,range)) {\n            /* Check if score >= min. */\n            if (zslValueGteMin(score,range))\n                return eptr;\n            return NULL;\n        }\n\n        /* Move to previous element by moving to the score of previous element.\n         * When this returns NULL, we know there also is no element. */\n        sptr = ziplistPrev(zl,eptr);\n        if (sptr != NULL)\n            serverAssert((eptr = ziplistPrev(zl,sptr)) != NULL);\n        else\n            eptr = NULL;\n    }\n\n    return NULL;\n}\n\nstatic int zzlLexValueGteMin(unsigned char *p, zlexrangespec *spec) {\n    robj *value = ziplistGetObject(p);\n    int res = zslLexValueGteMin(value,spec);\n    decrRefCount(value);\n    return res;\n}\n\nstatic int zzlLexValueLteMax(unsigned char *p, zlexrangespec *spec) {\n    robj *value = ziplistGetObject(p);\n    int res = zslLexValueLteMax(value,spec);\n    decrRefCount(value);\n    return res;\n}\n\n/* Returns if there is a part of the zset is in range. Should only be used\n * internally by zzlFirstInRange and zzlLastInRange. */\nint zzlIsInLexRange(unsigned char *zl, zlexrangespec *range) {\n    unsigned char *p;\n\n    /* Test for ranges that will always be empty. */\n    if (compareStringObjectsForLexRange(range->min,range->max) > 1 ||\n            (compareStringObjects(range->min,range->max) == 0 &&\n            (range->minex || range->maxex)))\n        return 0;\n\n    p = ziplistIndex(zl,-2); /* Last element. */\n    if (p == NULL) return 0;\n    if (!zzlLexValueGteMin(p,range))\n        return 0;\n\n    p = ziplistIndex(zl,0); /* First element. */\n    serverAssert(p != NULL);\n    if (!zzlLexValueLteMax(p,range))\n        return 0;\n\n    return 1;\n}\n\n/* Find pointer to the first element contained in the specified lex range.\n * Returns NULL when no element is contained in the range. */\nunsigned char *zzlFirstInLexRange(unsigned char *zl, zlexrangespec *range) {\n    unsigned char *eptr = ziplistIndex(zl,0), *sptr;\n\n    /* If everything is out of range, return early. */\n    if (!zzlIsInLexRange(zl,range)) return NULL;\n\n    while (eptr != NULL) {\n        if (zzlLexValueGteMin(eptr,range)) {\n            /* Check if score <= max. */\n            if (zzlLexValueLteMax(eptr,range))\n                return eptr;\n            return NULL;\n        }\n\n        /* Move to next element. */\n        sptr = ziplistNext(zl,eptr); /* This element score. Skip it. */\n        serverAssert(sptr != NULL);\n        eptr = ziplistNext(zl,sptr); /* Next element. */\n    }\n\n    return NULL;\n}\n\n/* Find pointer to the last element contained in the specified lex range.\n * Returns NULL when no element is contained in the range. */\nunsigned char *zzlLastInLexRange(unsigned char *zl, zlexrangespec *range) {\n    unsigned char *eptr = ziplistIndex(zl,-2), *sptr;\n\n    /* If everything is out of range, return early. */\n    if (!zzlIsInLexRange(zl,range)) return NULL;\n\n    while (eptr != NULL) {\n        if (zzlLexValueLteMax(eptr,range)) {\n            /* Check if score >= min. */\n            if (zzlLexValueGteMin(eptr,range))\n                return eptr;\n            return NULL;\n        }\n\n        /* Move to previous element by moving to the score of previous element.\n         * When this returns NULL, we know there also is no element. */\n        sptr = ziplistPrev(zl,eptr);\n        if (sptr != NULL)\n            serverAssert((eptr = ziplistPrev(zl,sptr)) != NULL);\n        else\n            eptr = NULL;\n    }\n\n    return NULL;\n}\n\nunsigned char *zzlFind(unsigned char *zl, robj *ele, double *score) {\n    unsigned char *eptr = ziplistIndex(zl,0), *sptr;\n\n    ele = getDecodedObject(ele);\n    while (eptr != NULL) {\n        sptr = ziplistNext(zl,eptr);\n        serverAssertWithInfo(NULL,ele,sptr != NULL);\n\n        if (ziplistCompare(eptr,ele->ptr,sdslen(ele->ptr))) {\n            /* Matching element, pull out score. */\n            if (score != NULL) *score = zzlGetScore(sptr);\n            decrRefCount(ele);\n            return eptr;\n        }\n\n        /* Move to next element. */\n        eptr = ziplistNext(zl,sptr);\n    }\n\n    decrRefCount(ele);\n    return NULL;\n}\n\n/* Delete (element,score) pair from ziplist. Use local copy of eptr because we\n * don't want to modify the one given as argument. */\nunsigned char *zzlDelete(unsigned char *zl, unsigned char *eptr) {\n    unsigned char *p = eptr;\n\n    /* TODO: add function to ziplist API to delete N elements from offset. */\n    zl = ziplistDelete(zl,&p);\n    zl = ziplistDelete(zl,&p);\n    return zl;\n}\n\nunsigned char *zzlInsertAt(unsigned char *zl, unsigned char *eptr, robj *ele, double score) {\n    unsigned char *sptr;\n    char scorebuf[128];\n    int scorelen;\n    size_t offset;\n\n    serverAssertWithInfo(NULL,ele,sdsEncodedObject(ele));\n    scorelen = d2string(scorebuf,sizeof(scorebuf),score);\n    if (eptr == NULL) {\n        zl = ziplistPush(zl,ele->ptr,sdslen(ele->ptr),ZIPLIST_TAIL);\n        zl = ziplistPush(zl,(unsigned char*)scorebuf,scorelen,ZIPLIST_TAIL);\n    } else {\n        /* Keep offset relative to zl, as it might be re-allocated. */\n        offset = eptr-zl;\n        zl = ziplistInsert(zl,eptr,ele->ptr,sdslen(ele->ptr));\n        eptr = zl+offset;\n\n        /* Insert score after the element. */\n        serverAssertWithInfo(NULL,ele,(sptr = ziplistNext(zl,eptr)) != NULL);\n        zl = ziplistInsert(zl,sptr,(unsigned char*)scorebuf,scorelen);\n    }\n\n    return zl;\n}\n\n/* Insert (element,score) pair in ziplist. This function assumes the element is\n * not yet present in the list. */\nunsigned char *zzlInsert(unsigned char *zl, robj *ele, double score) {\n    unsigned char *eptr = ziplistIndex(zl,0), *sptr;\n    double s;\n\n    ele = getDecodedObject(ele);\n    while (eptr != NULL) {\n        sptr = ziplistNext(zl,eptr);\n        serverAssertWithInfo(NULL,ele,sptr != NULL);\n        s = zzlGetScore(sptr);\n\n        if (s > score) {\n            /* First element with score larger than score for element to be\n             * inserted. This means we should take its spot in the list to\n             * maintain ordering. */\n            zl = zzlInsertAt(zl,eptr,ele,score);\n            break;\n        } else if (s == score) {\n            /* Ensure lexicographical ordering for elements. */\n            if (zzlCompareElements(eptr,ele->ptr,sdslen(ele->ptr)) > 0) {\n                zl = zzlInsertAt(zl,eptr,ele,score);\n                break;\n            }\n        }\n\n        /* Move to next element. */\n        eptr = ziplistNext(zl,sptr);\n    }\n\n    /* Push on tail of list when it was not yet inserted. */\n    if (eptr == NULL)\n        zl = zzlInsertAt(zl,NULL,ele,score);\n\n    decrRefCount(ele);\n    return zl;\n}\n\nunsigned char *zzlDeleteRangeByScore(unsigned char *zl, zrangespec *range, unsigned long *deleted) {\n    unsigned char *eptr, *sptr;\n    double score;\n    unsigned long num = 0;\n\n    if (deleted != NULL) *deleted = 0;\n\n    eptr = zzlFirstInRange(zl,range);\n    if (eptr == NULL) return zl;\n\n    /* When the tail of the ziplist is deleted, eptr will point to the sentinel\n     * byte and ziplistNext will return NULL. */\n    while ((sptr = ziplistNext(zl,eptr)) != NULL) {\n        score = zzlGetScore(sptr);\n        if (zslValueLteMax(score,range)) {\n            /* Delete both the element and the score. */\n            zl = ziplistDelete(zl,&eptr);\n            zl = ziplistDelete(zl,&eptr);\n            num++;\n        } else {\n            /* No longer in range. */\n            break;\n        }\n    }\n\n    if (deleted != NULL) *deleted = num;\n    return zl;\n}\n\nunsigned char *zzlDeleteRangeByLex(unsigned char *zl, zlexrangespec *range, unsigned long *deleted) {\n    unsigned char *eptr, *sptr;\n    unsigned long num = 0;\n\n    if (deleted != NULL) *deleted = 0;\n\n    eptr = zzlFirstInLexRange(zl,range);\n    if (eptr == NULL) return zl;\n\n    /* When the tail of the ziplist is deleted, eptr will point to the sentinel\n     * byte and ziplistNext will return NULL. */\n    while ((sptr = ziplistNext(zl,eptr)) != NULL) {\n        if (zzlLexValueLteMax(eptr,range)) {\n            /* Delete both the element and the score. */\n            zl = ziplistDelete(zl,&eptr);\n            zl = ziplistDelete(zl,&eptr);\n            num++;\n        } else {\n            /* No longer in range. */\n            break;\n        }\n    }\n\n    if (deleted != NULL) *deleted = num;\n    return zl;\n}\n\n/* Delete all the elements with rank between start and end from the skiplist.\n * Start and end are inclusive. Note that start and end need to be 1-based */\nunsigned char *zzlDeleteRangeByRank(unsigned char *zl, unsigned int start, unsigned int end, unsigned long *deleted) {\n    unsigned int num = (end-start)+1;\n    if (deleted) *deleted = num;\n    zl = ziplistDeleteRange(zl,2*(start-1),2*num);\n    return zl;\n}\n\n/*-----------------------------------------------------------------------------\n * Common sorted set API\n *----------------------------------------------------------------------------*/\n\nunsigned int zsetLength(robj *zobj) {\n    int length = -1;\n    if (zobj->encoding == OBJ_ENCODING_ZIPLIST) {\n        length = zzlLength(zobj->ptr);\n    } else if (zobj->encoding == OBJ_ENCODING_SKIPLIST) {\n        length = ((zset*)zobj->ptr)->zsl->length;\n    } else {\n        serverPanic(\"Unknown sorted set encoding\");\n    }\n    return length;\n}\n\nvoid zsetConvert(robj *zobj, int encoding) {\n    zset *zs;\n    zskiplistNode *node, *next;\n    robj *ele;\n    double score;\n\n    if (zobj->encoding == encoding) return;\n    if (zobj->encoding == OBJ_ENCODING_ZIPLIST) {\n        unsigned char *zl = zobj->ptr;\n        unsigned char *eptr, *sptr;\n        unsigned char *vstr;\n        unsigned int vlen;\n        long long vlong;\n\n        if (encoding != OBJ_ENCODING_SKIPLIST)\n            serverPanic(\"Unknown target encoding\");\n\n        zs = zmalloc(sizeof(*zs));\n        zs->dict = dictCreate(&zsetDictType,NULL);\n        zs->zsl = zslCreate();\n\n        eptr = ziplistIndex(zl,0);\n        serverAssertWithInfo(NULL,zobj,eptr != NULL);\n        sptr = ziplistNext(zl,eptr);\n        serverAssertWithInfo(NULL,zobj,sptr != NULL);\n\n        while (eptr != NULL) {\n            score = zzlGetScore(sptr);\n            serverAssertWithInfo(NULL,zobj,ziplistGet(eptr,&vstr,&vlen,&vlong));\n            if (vstr == NULL)\n                ele = createStringObjectFromLongLong(vlong);\n            else\n                ele = createStringObject((char*)vstr,vlen);\n\n            /* Has incremented refcount since it was just created. */\n            node = zslInsert(zs->zsl,score,ele);\n            serverAssertWithInfo(NULL,zobj,dictAdd(zs->dict,ele,&node->score) == DICT_OK);\n            incrRefCount(ele); /* Added to dictionary. */\n            zzlNext(zl,&eptr,&sptr);\n        }\n\n        zfree(zobj->ptr);\n        zobj->ptr = zs;\n        zobj->encoding = OBJ_ENCODING_SKIPLIST;\n    } else if (zobj->encoding == OBJ_ENCODING_SKIPLIST) {\n        unsigned char *zl = ziplistNew();\n\n        if (encoding != OBJ_ENCODING_ZIPLIST)\n            serverPanic(\"Unknown target encoding\");\n\n        /* Approach similar to zslFree(), since we want to free the skiplist at\n         * the same time as creating the ziplist. */\n        zs = zobj->ptr;\n        dictRelease(zs->dict);\n        node = zs->zsl->header->level[0].forward;\n        zfree(zs->zsl->header);\n        zfree(zs->zsl);\n\n        while (node) {\n            ele = getDecodedObject(node->obj);\n            zl = zzlInsertAt(zl,NULL,ele,node->score);\n            decrRefCount(ele);\n\n            next = node->level[0].forward;\n            zslFreeNode(node);\n            node = next;\n        }\n\n        zfree(zs);\n        zobj->ptr = zl;\n        zobj->encoding = OBJ_ENCODING_ZIPLIST;\n    } else {\n        serverPanic(\"Unknown sorted set encoding\");\n    }\n}\n\n/* Convert the sorted set object into a ziplist if it is not already a ziplist\n * and if the number of elements and the maximum element size is within the\n * expected ranges. */\nvoid zsetConvertToZiplistIfNeeded(robj *zobj, size_t maxelelen) {\n    if (zobj->encoding == OBJ_ENCODING_ZIPLIST) return;\n    zset *zset = zobj->ptr;\n\n    if (zset->zsl->length <= server.zset_max_ziplist_entries &&\n        maxelelen <= server.zset_max_ziplist_value)\n            zsetConvert(zobj,OBJ_ENCODING_ZIPLIST);\n}\n\n/* Return (by reference) the score of the specified member of the sorted set\n * storing it into *score. If the element does not exist C_ERR is returned\n * otherwise C_OK is returned and *score is correctly populated.\n * If 'zobj' or 'member' is NULL, C_ERR is returned. */\nint zsetScore(robj *zobj, robj *member, double *score) {\n    if (!zobj || !member) return C_ERR;\n\n    if (zobj->encoding == OBJ_ENCODING_ZIPLIST) {\n        if (zzlFind(zobj->ptr, member, score) == NULL) return C_ERR;\n    } else if (zobj->encoding == OBJ_ENCODING_SKIPLIST) {\n        zset *zs = zobj->ptr;\n        dictEntry *de = dictFind(zs->dict, member);\n        if (de == NULL) return C_ERR;\n        *score = *(double*)dictGetVal(de);\n    } else {\n        serverPanic(\"Unknown sorted set encoding\");\n    }\n    return C_OK;\n}\n\n/*-----------------------------------------------------------------------------\n * Sorted set commands\n *----------------------------------------------------------------------------*/\n\n/* This generic command implements both ZADD and ZINCRBY. */\n#define ZADD_NONE 0\n#define ZADD_INCR (1<<0)    /* Increment the score instead of setting it. */\n#define ZADD_NX (1<<1)      /* Don't touch elements not already existing. */\n#define ZADD_XX (1<<2)      /* Only touch elements already exisitng. */\n#define ZADD_CH (1<<3)      /* Return num of elements added or updated. */\nvoid zaddGenericCommand(client *c, int flags) {\n    static char *nanerr = \"resulting score is not a number (NaN)\";\n    robj *key = c->argv[1];\n    robj *ele;\n    robj *zobj;\n    robj *curobj;\n    double score = 0, *scores = NULL, curscore = 0.0;\n    int j, elements;\n    int scoreidx = 0;\n    /* The following vars are used in order to track what the command actually\n     * did during the execution, to reply to the client and to trigger the\n     * notification of keyspace change. */\n    int added = 0;      /* Number of new elements added. */\n    int updated = 0;    /* Number of elements with updated score. */\n    int processed = 0;  /* Number of elements processed, may remain zero with\n                           options like XX. */\n\n    /* Parse options. At the end 'scoreidx' is set to the argument position\n     * of the score of the first score-element pair. */\n    scoreidx = 2;\n    while(scoreidx < c->argc) {\n        char *opt = c->argv[scoreidx]->ptr;\n        if (!strcasecmp(opt,\"nx\")) flags |= ZADD_NX;\n        else if (!strcasecmp(opt,\"xx\")) flags |= ZADD_XX;\n        else if (!strcasecmp(opt,\"ch\")) flags |= ZADD_CH;\n        else if (!strcasecmp(opt,\"incr\")) flags |= ZADD_INCR;\n        else break;\n        scoreidx++;\n    }\n\n    /* Turn options into simple to check vars. */\n    int incr = (flags & ZADD_INCR) != 0;\n    int nx = (flags & ZADD_NX) != 0;\n    int xx = (flags & ZADD_XX) != 0;\n    int ch = (flags & ZADD_CH) != 0;\n\n    /* After the options, we expect to have an even number of args, since\n     * we expect any number of score-element pairs. */\n    elements = c->argc-scoreidx;\n    if (elements % 2) {\n        addReply(c,shared.syntaxerr);\n        return;\n    }\n    elements /= 2; /* Now this holds the number of score-element pairs. */\n\n    /* Check for incompatible options. */\n    if (nx && xx) {\n        addReplyError(c,\n            \"XX and NX options at the same time are not compatible\");\n        return;\n    }\n\n    if (incr && elements > 1) {\n        addReplyError(c,\n            \"INCR option supports a single increment-element pair\");\n        return;\n    }\n\n    /* Start parsing all the scores, we need to emit any syntax error\n     * before executing additions to the sorted set, as the command should\n     * either execute fully or nothing at all. */\n    scores = zmalloc(sizeof(double)*elements);\n    for (j = 0; j < elements; j++) {\n        if (getDoubleFromObjectOrReply(c,c->argv[scoreidx+j*2],&scores[j],NULL)\n            != C_OK) goto cleanup;\n    }\n\n    /* Lookup the key and create the sorted set if does not exist. */\n    zobj = lookupKeyWrite(c->db,key);\n    if (zobj == NULL) {\n        if (xx) goto reply_to_client; /* No key + XX option: nothing to do. */\n        if (server.zset_max_ziplist_entries == 0 ||\n            server.zset_max_ziplist_value < sdslen(c->argv[scoreidx+1]->ptr))\n        {\n            zobj = createZsetObject();\n        } else {\n            zobj = createZsetZiplistObject();\n        }\n        dbAdd(c->db,key,zobj);\n    } else {\n        if (zobj->type != OBJ_ZSET) {\n            addReply(c,shared.wrongtypeerr);\n            goto cleanup;\n        }\n    }\n\n    for (j = 0; j < elements; j++) {\n        score = scores[j];\n\n        if (zobj->encoding == OBJ_ENCODING_ZIPLIST) {\n            unsigned char *eptr;\n\n            /* Prefer non-encoded element when dealing with ziplists. */\n            ele = c->argv[scoreidx+1+j*2];\n            if ((eptr = zzlFind(zobj->ptr,ele,&curscore)) != NULL) {\n                if (nx) continue;\n                if (incr) {\n                    score += curscore;\n                    if (isnan(score)) {\n                        addReplyError(c,nanerr);\n                        goto cleanup;\n                    }\n                }\n\n                /* Remove and re-insert when score changed. */\n                if (score != curscore) {\n                    zobj->ptr = zzlDelete(zobj->ptr,eptr);\n                    zobj->ptr = zzlInsert(zobj->ptr,ele,score);\n                    server.dirty++;\n                    updated++;\n                }\n                processed++;\n            } else if (!xx) {\n                /* Optimize: check if the element is too large or the list\n                 * becomes too long *before* executing zzlInsert. */\n                zobj->ptr = zzlInsert(zobj->ptr,ele,score);\n                if (zzlLength(zobj->ptr) > server.zset_max_ziplist_entries)\n                    zsetConvert(zobj,OBJ_ENCODING_SKIPLIST);\n                if (sdslen(ele->ptr) > server.zset_max_ziplist_value)\n                    zsetConvert(zobj,OBJ_ENCODING_SKIPLIST);\n                server.dirty++;\n                added++;\n                processed++;\n            }\n        } else if (zobj->encoding == OBJ_ENCODING_SKIPLIST) {\n            zset *zs = zobj->ptr;\n            zskiplistNode *znode;\n            dictEntry *de;\n\n            ele = c->argv[scoreidx+1+j*2] =\n                tryObjectEncoding(c->argv[scoreidx+1+j*2]);\n            de = dictFind(zs->dict,ele);\n            if (de != NULL) {\n                if (nx) continue;\n                curobj = dictGetKey(de);\n                curscore = *(double*)dictGetVal(de);\n\n                if (incr) {\n                    score += curscore;\n                    if (isnan(score)) {\n                        addReplyError(c,nanerr);\n                        /* Don't need to check if the sorted set is empty\n                         * because we know it has at least one element. */\n                        goto cleanup;\n                    }\n                }\n\n                /* Remove and re-insert when score changed. We can safely\n                 * delete the key object from the skiplist, since the\n                 * dictionary still has a reference to it. */\n                if (score != curscore) {\n                    serverAssertWithInfo(c,curobj,zslDelete(zs->zsl,curscore,curobj));\n                    znode = zslInsert(zs->zsl,score,curobj);\n                    incrRefCount(curobj); /* Re-inserted in skiplist. */\n                    dictGetVal(de) = &znode->score; /* Update score ptr. */\n                    server.dirty++;\n                    updated++;\n                }\n                processed++;\n            } else if (!xx) {\n                znode = zslInsert(zs->zsl,score,ele);\n                incrRefCount(ele); /* Inserted in skiplist. */\n                serverAssertWithInfo(c,NULL,dictAdd(zs->dict,ele,&znode->score) == DICT_OK);\n                incrRefCount(ele); /* Added to dictionary. */\n                server.dirty++;\n                added++;\n                processed++;\n            }\n        } else {\n            serverPanic(\"Unknown sorted set encoding\");\n        }\n    }\n\nreply_to_client:\n    if (incr) { /* ZINCRBY or INCR option. */\n        if (processed)\n            addReplyDouble(c,score);\n        else\n            addReply(c,shared.nullbulk);\n    } else { /* ZADD. */\n        addReplyLongLong(c,ch ? added+updated : added);\n    }\n\ncleanup:\n    zfree(scores);\n    if (added || updated) {\n        signalModifiedKey(c->db,key);\n        notifyKeyspaceEvent(NOTIFY_ZSET,\n            incr ? \"zincr\" : \"zadd\", key, c->db->id);\n    }\n}\n\nvoid zaddCommand(client *c) {\n    zaddGenericCommand(c,ZADD_NONE);\n}\n\nvoid zincrbyCommand(client *c) {\n    zaddGenericCommand(c,ZADD_INCR);\n}\n\nvoid zremCommand(client *c) {\n    robj *key = c->argv[1];\n    robj *zobj;\n    int deleted = 0, keyremoved = 0, j;\n\n    if ((zobj = lookupKeyWriteOrReply(c,key,shared.czero)) == NULL ||\n        checkType(c,zobj,OBJ_ZSET)) return;\n\n    if (zobj->encoding == OBJ_ENCODING_ZIPLIST) {\n        unsigned char *eptr;\n\n        for (j = 2; j < c->argc; j++) {\n            if ((eptr = zzlFind(zobj->ptr,c->argv[j],NULL)) != NULL) {\n                deleted++;\n                zobj->ptr = zzlDelete(zobj->ptr,eptr);\n                if (zzlLength(zobj->ptr) == 0) {\n                    dbDelete(c->db,key);\n                    keyremoved = 1;\n                    break;\n                }\n            }\n        }\n    } else if (zobj->encoding == OBJ_ENCODING_SKIPLIST) {\n        zset *zs = zobj->ptr;\n        dictEntry *de;\n        double score;\n\n        for (j = 2; j < c->argc; j++) {\n            de = dictFind(zs->dict,c->argv[j]);\n            if (de != NULL) {\n                deleted++;\n\n                /* Delete from the skiplist */\n                score = *(double*)dictGetVal(de);\n                serverAssertWithInfo(c,c->argv[j],zslDelete(zs->zsl,score,c->argv[j]));\n\n                /* Delete from the hash table */\n                dictDelete(zs->dict,c->argv[j]);\n                if (htNeedsResize(zs->dict)) dictResize(zs->dict);\n                if (dictSize(zs->dict) == 0) {\n                    dbDelete(c->db,key);\n                    keyremoved = 1;\n                    break;\n                }\n            }\n        }\n    } else {\n        serverPanic(\"Unknown sorted set encoding\");\n    }\n\n    if (deleted) {\n        notifyKeyspaceEvent(NOTIFY_ZSET,\"zrem\",key,c->db->id);\n        if (keyremoved)\n            notifyKeyspaceEvent(NOTIFY_GENERIC,\"del\",key,c->db->id);\n        signalModifiedKey(c->db,key);\n        server.dirty += deleted;\n    }\n    addReplyLongLong(c,deleted);\n}\n\n/* Implements ZREMRANGEBYRANK, ZREMRANGEBYSCORE, ZREMRANGEBYLEX commands. */\n#define ZRANGE_RANK 0\n#define ZRANGE_SCORE 1\n#define ZRANGE_LEX 2\nvoid zremrangeGenericCommand(client *c, int rangetype) {\n    robj *key = c->argv[1];\n    robj *zobj;\n    int keyremoved = 0;\n    unsigned long deleted = 0;\n    zrangespec range;\n    zlexrangespec lexrange;\n    long start, end, llen;\n\n    /* Step 1: Parse the range. */\n    if (rangetype == ZRANGE_RANK) {\n        if ((getLongFromObjectOrReply(c,c->argv[2],&start,NULL) != C_OK) ||\n            (getLongFromObjectOrReply(c,c->argv[3],&end,NULL) != C_OK))\n            return;\n    } else if (rangetype == ZRANGE_SCORE) {\n        if (zslParseRange(c->argv[2],c->argv[3],&range) != C_OK) {\n            addReplyError(c,\"min or max is not a float\");\n            return;\n        }\n    } else if (rangetype == ZRANGE_LEX) {\n        if (zslParseLexRange(c->argv[2],c->argv[3],&lexrange) != C_OK) {\n            addReplyError(c,\"min or max not valid string range item\");\n            return;\n        }\n    }\n\n    /* Step 2: Lookup & range sanity checks if needed. */\n    if ((zobj = lookupKeyWriteOrReply(c,key,shared.czero)) == NULL ||\n        checkType(c,zobj,OBJ_ZSET)) goto cleanup;\n\n    if (rangetype == ZRANGE_RANK) {\n        /* Sanitize indexes. */\n        llen = zsetLength(zobj);\n        if (start < 0) start = llen+start;\n        if (end < 0) end = llen+end;\n        if (start < 0) start = 0;\n\n        /* Invariant: start >= 0, so this test will be true when end < 0.\n         * The range is empty when start > end or start >= length. */\n        if (start > end || start >= llen) {\n            addReply(c,shared.czero);\n            goto cleanup;\n        }\n        if (end >= llen) end = llen-1;\n    }\n\n    /* Step 3: Perform the range deletion operation. */\n    if (zobj->encoding == OBJ_ENCODING_ZIPLIST) {\n        switch(rangetype) {\n        case ZRANGE_RANK:\n            zobj->ptr = zzlDeleteRangeByRank(zobj->ptr,start+1,end+1,&deleted);\n            break;\n        case ZRANGE_SCORE:\n            zobj->ptr = zzlDeleteRangeByScore(zobj->ptr,&range,&deleted);\n            break;\n        case ZRANGE_LEX:\n            zobj->ptr = zzlDeleteRangeByLex(zobj->ptr,&lexrange,&deleted);\n            break;\n        }\n        if (zzlLength(zobj->ptr) == 0) {\n            dbDelete(c->db,key);\n            keyremoved = 1;\n        }\n    } else if (zobj->encoding == OBJ_ENCODING_SKIPLIST) {\n        zset *zs = zobj->ptr;\n        switch(rangetype) {\n        case ZRANGE_RANK:\n            deleted = zslDeleteRangeByRank(zs->zsl,start+1,end+1,zs->dict);\n            break;\n        case ZRANGE_SCORE:\n            deleted = zslDeleteRangeByScore(zs->zsl,&range,zs->dict);\n            break;\n        case ZRANGE_LEX:\n            deleted = zslDeleteRangeByLex(zs->zsl,&lexrange,zs->dict);\n            break;\n        }\n        if (htNeedsResize(zs->dict)) dictResize(zs->dict);\n        if (dictSize(zs->dict) == 0) {\n            dbDelete(c->db,key);\n            keyremoved = 1;\n        }\n    } else {\n        serverPanic(\"Unknown sorted set encoding\");\n    }\n\n    /* Step 4: Notifications and reply. */\n    if (deleted) {\n        char *event[3] = {\"zremrangebyrank\",\"zremrangebyscore\",\"zremrangebylex\"};\n        signalModifiedKey(c->db,key);\n        notifyKeyspaceEvent(NOTIFY_ZSET,event[rangetype],key,c->db->id);\n        if (keyremoved)\n            notifyKeyspaceEvent(NOTIFY_GENERIC,\"del\",key,c->db->id);\n    }\n    server.dirty += deleted;\n    addReplyLongLong(c,deleted);\n\ncleanup:\n    if (rangetype == ZRANGE_LEX) zslFreeLexRange(&lexrange);\n}\n\nvoid zremrangebyrankCommand(client *c) {\n    zremrangeGenericCommand(c,ZRANGE_RANK);\n}\n\nvoid zremrangebyscoreCommand(client *c) {\n    zremrangeGenericCommand(c,ZRANGE_SCORE);\n}\n\nvoid zremrangebylexCommand(client *c) {\n    zremrangeGenericCommand(c,ZRANGE_LEX);\n}\n\ntypedef struct {\n    robj *subject;\n    int type; /* Set, sorted set */\n    int encoding;\n    double weight;\n\n    union {\n        /* Set iterators. */\n        union _iterset {\n            struct {\n                intset *is;\n                int ii;\n            } is;\n            struct {\n                dict *dict;\n                dictIterator *di;\n                dictEntry *de;\n            } ht;\n        } set;\n\n        /* Sorted set iterators. */\n        union _iterzset {\n            struct {\n                unsigned char *zl;\n                unsigned char *eptr, *sptr;\n            } zl;\n            struct {\n                zset *zs;\n                zskiplistNode *node;\n            } sl;\n        } zset;\n    } iter;\n} zsetopsrc;\n\n\n/* Use dirty flags for pointers that need to be cleaned up in the next\n * iteration over the zsetopval. The dirty flag for the long long value is\n * special, since long long values don't need cleanup. Instead, it means that\n * we already checked that \"ell\" holds a long long, or tried to convert another\n * representation into a long long value. When this was successful,\n * OPVAL_VALID_LL is set as well. */\n#define OPVAL_DIRTY_ROBJ 1\n#define OPVAL_DIRTY_LL 2\n#define OPVAL_VALID_LL 4\n\n/* Store value retrieved from the iterator. */\ntypedef struct {\n    int flags;\n    unsigned char _buf[32]; /* Private buffer. */\n    robj *ele;\n    unsigned char *estr;\n    unsigned int elen;\n    long long ell;\n    double score;\n} zsetopval;\n\ntypedef union _iterset iterset;\ntypedef union _iterzset iterzset;\n\nvoid zuiInitIterator(zsetopsrc *op) {\n    if (op->subject == NULL)\n        return;\n\n    if (op->type == OBJ_SET) {\n        iterset *it = &op->iter.set;\n        if (op->encoding == OBJ_ENCODING_INTSET) {\n            it->is.is = op->subject->ptr;\n            it->is.ii = 0;\n        } else if (op->encoding == OBJ_ENCODING_HT) {\n            it->ht.dict = op->subject->ptr;\n            it->ht.di = dictGetIterator(op->subject->ptr);\n            it->ht.de = dictNext(it->ht.di);\n        } else {\n            serverPanic(\"Unknown set encoding\");\n        }\n    } else if (op->type == OBJ_ZSET) {\n        iterzset *it = &op->iter.zset;\n        if (op->encoding == OBJ_ENCODING_ZIPLIST) {\n            it->zl.zl = op->subject->ptr;\n            it->zl.eptr = ziplistIndex(it->zl.zl,0);\n            if (it->zl.eptr != NULL) {\n                it->zl.sptr = ziplistNext(it->zl.zl,it->zl.eptr);\n                serverAssert(it->zl.sptr != NULL);\n            }\n        } else if (op->encoding == OBJ_ENCODING_SKIPLIST) {\n            it->sl.zs = op->subject->ptr;\n            it->sl.node = it->sl.zs->zsl->header->level[0].forward;\n        } else {\n            serverPanic(\"Unknown sorted set encoding\");\n        }\n    } else {\n        serverPanic(\"Unsupported type\");\n    }\n}\n\nvoid zuiClearIterator(zsetopsrc *op) {\n    if (op->subject == NULL)\n        return;\n\n    if (op->type == OBJ_SET) {\n        iterset *it = &op->iter.set;\n        if (op->encoding == OBJ_ENCODING_INTSET) {\n            UNUSED(it); /* skip */\n        } else if (op->encoding == OBJ_ENCODING_HT) {\n            dictReleaseIterator(it->ht.di);\n        } else {\n            serverPanic(\"Unknown set encoding\");\n        }\n    } else if (op->type == OBJ_ZSET) {\n        iterzset *it = &op->iter.zset;\n        if (op->encoding == OBJ_ENCODING_ZIPLIST) {\n            UNUSED(it); /* skip */\n        } else if (op->encoding == OBJ_ENCODING_SKIPLIST) {\n            UNUSED(it); /* skip */\n        } else {\n            serverPanic(\"Unknown sorted set encoding\");\n        }\n    } else {\n        serverPanic(\"Unsupported type\");\n    }\n}\n\nint zuiLength(zsetopsrc *op) {\n    if (op->subject == NULL)\n        return 0;\n\n    if (op->type == OBJ_SET) {\n        if (op->encoding == OBJ_ENCODING_INTSET) {\n            return intsetLen(op->subject->ptr);\n        } else if (op->encoding == OBJ_ENCODING_HT) {\n            dict *ht = op->subject->ptr;\n            return dictSize(ht);\n        } else {\n            serverPanic(\"Unknown set encoding\");\n        }\n    } else if (op->type == OBJ_ZSET) {\n        if (op->encoding == OBJ_ENCODING_ZIPLIST) {\n            return zzlLength(op->subject->ptr);\n        } else if (op->encoding == OBJ_ENCODING_SKIPLIST) {\n            zset *zs = op->subject->ptr;\n            return zs->zsl->length;\n        } else {\n            serverPanic(\"Unknown sorted set encoding\");\n        }\n    } else {\n        serverPanic(\"Unsupported type\");\n    }\n}\n\n/* Check if the current value is valid. If so, store it in the passed structure\n * and move to the next element. If not valid, this means we have reached the\n * end of the structure and can abort. */\nint zuiNext(zsetopsrc *op, zsetopval *val) {\n    if (op->subject == NULL)\n        return 0;\n\n    if (val->flags & OPVAL_DIRTY_ROBJ)\n        decrRefCount(val->ele);\n\n    memset(val,0,sizeof(zsetopval));\n\n    if (op->type == OBJ_SET) {\n        iterset *it = &op->iter.set;\n        if (op->encoding == OBJ_ENCODING_INTSET) {\n            int64_t ell;\n\n            if (!intsetGet(it->is.is,it->is.ii,&ell))\n                return 0;\n            val->ell = ell;\n            val->score = 1.0;\n\n            /* Move to next element. */\n            it->is.ii++;\n        } else if (op->encoding == OBJ_ENCODING_HT) {\n            if (it->ht.de == NULL)\n                return 0;\n            val->ele = dictGetKey(it->ht.de);\n            val->score = 1.0;\n\n            /* Move to next element. */\n            it->ht.de = dictNext(it->ht.di);\n        } else {\n            serverPanic(\"Unknown set encoding\");\n        }\n    } else if (op->type == OBJ_ZSET) {\n        iterzset *it = &op->iter.zset;\n        if (op->encoding == OBJ_ENCODING_ZIPLIST) {\n            /* No need to check both, but better be explicit. */\n            if (it->zl.eptr == NULL || it->zl.sptr == NULL)\n                return 0;\n            serverAssert(ziplistGet(it->zl.eptr,&val->estr,&val->elen,&val->ell));\n            val->score = zzlGetScore(it->zl.sptr);\n\n            /* Move to next element. */\n            zzlNext(it->zl.zl,&it->zl.eptr,&it->zl.sptr);\n        } else if (op->encoding == OBJ_ENCODING_SKIPLIST) {\n            if (it->sl.node == NULL)\n                return 0;\n            val->ele = it->sl.node->obj;\n            val->score = it->sl.node->score;\n\n            /* Move to next element. */\n            it->sl.node = it->sl.node->level[0].forward;\n        } else {\n            serverPanic(\"Unknown sorted set encoding\");\n        }\n    } else {\n        serverPanic(\"Unsupported type\");\n    }\n    return 1;\n}\n\nint zuiLongLongFromValue(zsetopval *val) {\n    if (!(val->flags & OPVAL_DIRTY_LL)) {\n        val->flags |= OPVAL_DIRTY_LL;\n\n        if (val->ele != NULL) {\n            if (val->ele->encoding == OBJ_ENCODING_INT) {\n                val->ell = (long)val->ele->ptr;\n                val->flags |= OPVAL_VALID_LL;\n            } else if (sdsEncodedObject(val->ele)) {\n                if (string2ll(val->ele->ptr,sdslen(val->ele->ptr),&val->ell))\n                    val->flags |= OPVAL_VALID_LL;\n            } else {\n                serverPanic(\"Unsupported element encoding\");\n            }\n        } else if (val->estr != NULL) {\n            if (string2ll((char*)val->estr,val->elen,&val->ell))\n                val->flags |= OPVAL_VALID_LL;\n        } else {\n            /* The long long was already set, flag as valid. */\n            val->flags |= OPVAL_VALID_LL;\n        }\n    }\n    return val->flags & OPVAL_VALID_LL;\n}\n\nrobj *zuiObjectFromValue(zsetopval *val) {\n    if (val->ele == NULL) {\n        if (val->estr != NULL) {\n            val->ele = createStringObject((char*)val->estr,val->elen);\n        } else {\n            val->ele = createStringObjectFromLongLong(val->ell);\n        }\n        val->flags |= OPVAL_DIRTY_ROBJ;\n    }\n    return val->ele;\n}\n\nint zuiBufferFromValue(zsetopval *val) {\n    if (val->estr == NULL) {\n        if (val->ele != NULL) {\n            if (val->ele->encoding == OBJ_ENCODING_INT) {\n                val->elen = ll2string((char*)val->_buf,sizeof(val->_buf),(long)val->ele->ptr);\n                val->estr = val->_buf;\n            } else if (sdsEncodedObject(val->ele)) {\n                val->elen = sdslen(val->ele->ptr);\n                val->estr = val->ele->ptr;\n            } else {\n                serverPanic(\"Unsupported element encoding\");\n            }\n        } else {\n            val->elen = ll2string((char*)val->_buf,sizeof(val->_buf),val->ell);\n            val->estr = val->_buf;\n        }\n    }\n    return 1;\n}\n\n/* Find value pointed to by val in the source pointer to by op. When found,\n * return 1 and store its score in target. Return 0 otherwise. */\nint zuiFind(zsetopsrc *op, zsetopval *val, double *score) {\n    if (op->subject == NULL)\n        return 0;\n\n    if (op->type == OBJ_SET) {\n        if (op->encoding == OBJ_ENCODING_INTSET) {\n            if (zuiLongLongFromValue(val) &&\n                intsetFind(op->subject->ptr,val->ell))\n            {\n                *score = 1.0;\n                return 1;\n            } else {\n                return 0;\n            }\n        } else if (op->encoding == OBJ_ENCODING_HT) {\n            dict *ht = op->subject->ptr;\n            zuiObjectFromValue(val);\n            if (dictFind(ht,val->ele) != NULL) {\n                *score = 1.0;\n                return 1;\n            } else {\n                return 0;\n            }\n        } else {\n            serverPanic(\"Unknown set encoding\");\n        }\n    } else if (op->type == OBJ_ZSET) {\n        zuiObjectFromValue(val);\n\n        if (op->encoding == OBJ_ENCODING_ZIPLIST) {\n            if (zzlFind(op->subject->ptr,val->ele,score) != NULL) {\n                /* Score is already set by zzlFind. */\n                return 1;\n            } else {\n                return 0;\n            }\n        } else if (op->encoding == OBJ_ENCODING_SKIPLIST) {\n            zset *zs = op->subject->ptr;\n            dictEntry *de;\n            if ((de = dictFind(zs->dict,val->ele)) != NULL) {\n                *score = *(double*)dictGetVal(de);\n                return 1;\n            } else {\n                return 0;\n            }\n        } else {\n            serverPanic(\"Unknown sorted set encoding\");\n        }\n    } else {\n        serverPanic(\"Unsupported type\");\n    }\n}\n\nint zuiCompareByCardinality(const void *s1, const void *s2) {\n    return zuiLength((zsetopsrc*)s1) - zuiLength((zsetopsrc*)s2);\n}\n\n#define REDIS_AGGR_SUM 1\n#define REDIS_AGGR_MIN 2\n#define REDIS_AGGR_MAX 3\n#define zunionInterDictValue(_e) (dictGetVal(_e) == NULL ? 1.0 : *(double*)dictGetVal(_e))\n\ninline static void zunionInterAggregate(double *target, double val, int aggregate) {\n    if (aggregate == REDIS_AGGR_SUM) {\n        *target = *target + val;\n        /* The result of adding two doubles is NaN when one variable\n         * is +inf and the other is -inf. When these numbers are added,\n         * we maintain the convention of the result being 0.0. */\n        if (isnan(*target)) *target = 0.0;\n    } else if (aggregate == REDIS_AGGR_MIN) {\n        *target = val < *target ? val : *target;\n    } else if (aggregate == REDIS_AGGR_MAX) {\n        *target = val > *target ? val : *target;\n    } else {\n        /* safety net */\n        serverPanic(\"Unknown ZUNION/INTER aggregate type\");\n    }\n}\n\nvoid zunionInterGenericCommand(client *c, robj *dstkey, int op) {\n    int i, j;\n    long setnum;\n    int aggregate = REDIS_AGGR_SUM;\n    zsetopsrc *src;\n    zsetopval zval;\n    robj *tmp;\n    unsigned int maxelelen = 0;\n    robj *dstobj;\n    zset *dstzset;\n    zskiplistNode *znode;\n    int touched = 0;\n\n    /* expect setnum input keys to be given */\n    if ((getLongFromObjectOrReply(c, c->argv[2], &setnum, NULL) != C_OK))\n        return;\n\n    if (setnum < 1) {\n        addReplyError(c,\n            \"at least 1 input key is needed for ZUNIONSTORE/ZINTERSTORE\");\n        return;\n    }\n\n    /* test if the expected number of keys would overflow */\n    if (setnum > c->argc-3) {\n        addReply(c,shared.syntaxerr);\n        return;\n    }\n\n    /* read keys to be used for input */\n    src = zcalloc(sizeof(zsetopsrc) * setnum);\n    for (i = 0, j = 3; i < setnum; i++, j++) {\n        robj *obj = lookupKeyWrite(c->db,c->argv[j]);\n        if (obj != NULL) {\n            if (obj->type != OBJ_ZSET && obj->type != OBJ_SET) {\n                zfree(src);\n                addReply(c,shared.wrongtypeerr);\n                return;\n            }\n\n            src[i].subject = obj;\n            src[i].type = obj->type;\n            src[i].encoding = obj->encoding;\n        } else {\n            src[i].subject = NULL;\n        }\n\n        /* Default all weights to 1. */\n        src[i].weight = 1.0;\n    }\n\n    /* parse optional extra arguments */\n    if (j < c->argc) {\n        int remaining = c->argc - j;\n\n        while (remaining) {\n            if (remaining >= (setnum + 1) && !strcasecmp(c->argv[j]->ptr,\"weights\")) {\n                j++; remaining--;\n                for (i = 0; i < setnum; i++, j++, remaining--) {\n                    if (getDoubleFromObjectOrReply(c,c->argv[j],&src[i].weight,\n                            \"weight value is not a float\") != C_OK)\n                    {\n                        zfree(src);\n                        return;\n                    }\n                }\n            } else if (remaining >= 2 && !strcasecmp(c->argv[j]->ptr,\"aggregate\")) {\n                j++; remaining--;\n                if (!strcasecmp(c->argv[j]->ptr,\"sum\")) {\n                    aggregate = REDIS_AGGR_SUM;\n                } else if (!strcasecmp(c->argv[j]->ptr,\"min\")) {\n                    aggregate = REDIS_AGGR_MIN;\n                } else if (!strcasecmp(c->argv[j]->ptr,\"max\")) {\n                    aggregate = REDIS_AGGR_MAX;\n                } else {\n                    zfree(src);\n                    addReply(c,shared.syntaxerr);\n                    return;\n                }\n                j++; remaining--;\n            } else {\n                zfree(src);\n                addReply(c,shared.syntaxerr);\n                return;\n            }\n        }\n    }\n\n    /* sort sets from the smallest to largest, this will improve our\n     * algorithm's performance */\n    qsort(src,setnum,sizeof(zsetopsrc),zuiCompareByCardinality);\n\n    dstobj = createZsetObject();\n    dstzset = dstobj->ptr;\n    memset(&zval, 0, sizeof(zval));\n\n    if (op == SET_OP_INTER) {\n        /* Skip everything if the smallest input is empty. */\n        if (zuiLength(&src[0]) > 0) {\n            /* Precondition: as src[0] is non-empty and the inputs are ordered\n             * by size, all src[i > 0] are non-empty too. */\n            zuiInitIterator(&src[0]);\n            while (zuiNext(&src[0],&zval)) {\n                double score, value;\n\n                score = src[0].weight * zval.score;\n                if (isnan(score)) score = 0;\n\n                for (j = 1; j < setnum; j++) {\n                    /* It is not safe to access the zset we are\n                     * iterating, so explicitly check for equal object. */\n                    if (src[j].subject == src[0].subject) {\n                        value = zval.score*src[j].weight;\n                        zunionInterAggregate(&score,value,aggregate);\n                    } else if (zuiFind(&src[j],&zval,&value)) {\n                        value *= src[j].weight;\n                        zunionInterAggregate(&score,value,aggregate);\n                    } else {\n                        break;\n                    }\n                }\n\n                /* Only continue when present in every input. */\n                if (j == setnum) {\n                    tmp = zuiObjectFromValue(&zval);\n                    znode = zslInsert(dstzset->zsl,score,tmp);\n                    incrRefCount(tmp); /* added to skiplist */\n                    dictAdd(dstzset->dict,tmp,&znode->score);\n                    incrRefCount(tmp); /* added to dictionary */\n\n                    if (sdsEncodedObject(tmp)) {\n                        if (sdslen(tmp->ptr) > maxelelen)\n                            maxelelen = sdslen(tmp->ptr);\n                    }\n                }\n            }\n            zuiClearIterator(&src[0]);\n        }\n    } else if (op == SET_OP_UNION) {\n        dict *accumulator = dictCreate(&setDictType,NULL);\n        dictIterator *di;\n        dictEntry *de;\n        double score;\n\n        if (setnum) {\n            /* Our union is at least as large as the largest set.\n             * Resize the dictionary ASAP to avoid useless rehashing. */\n            dictExpand(accumulator,zuiLength(&src[setnum-1]));\n        }\n\n        /* Step 1: Create a dictionary of elements -> aggregated-scores\n         * by iterating one sorted set after the other. */\n        for (i = 0; i < setnum; i++) {\n            if (zuiLength(&src[i]) == 0) continue;\n\n            zuiInitIterator(&src[i]);\n            while (zuiNext(&src[i],&zval)) {\n                /* Initialize value */\n                score = src[i].weight * zval.score;\n                if (isnan(score)) score = 0;\n\n                /* Search for this element in the accumulating dictionary. */\n                de = dictFind(accumulator,zuiObjectFromValue(&zval));\n                /* If we don't have it, we need to create a new entry. */\n                if (de == NULL) {\n                    tmp = zuiObjectFromValue(&zval);\n                    /* Remember the longest single element encountered,\n                     * to understand if it's possible to convert to ziplist\n                     * at the end. */\n                    if (sdsEncodedObject(tmp)) {\n                        if (sdslen(tmp->ptr) > maxelelen)\n                            maxelelen = sdslen(tmp->ptr);\n                    }\n                    /* Add the element with its initial score. */\n                    de = dictAddRaw(accumulator,tmp);\n                    incrRefCount(tmp);\n                    dictSetDoubleVal(de,score);\n                } else {\n                    /* Update the score with the score of the new instance\n                     * of the element found in the current sorted set.\n                     *\n                     * Here we access directly the dictEntry double\n                     * value inside the union as it is a big speedup\n                     * compared to using the getDouble/setDouble API. */\n                    zunionInterAggregate(&de->v.d,score,aggregate);\n                }\n            }\n            zuiClearIterator(&src[i]);\n        }\n\n        /* Step 2: convert the dictionary into the final sorted set. */\n        di = dictGetIterator(accumulator);\n\n        /* We now are aware of the final size of the resulting sorted set,\n         * let's resize the dictionary embedded inside the sorted set to the\n         * right size, in order to save rehashing time. */\n        dictExpand(dstzset->dict,dictSize(accumulator));\n\n        while((de = dictNext(di)) != NULL) {\n            robj *ele = dictGetKey(de);\n            score = dictGetDoubleVal(de);\n            znode = zslInsert(dstzset->zsl,score,ele);\n            incrRefCount(ele); /* added to skiplist */\n            dictAdd(dstzset->dict,ele,&znode->score);\n            incrRefCount(ele); /* added to dictionary */\n        }\n        dictReleaseIterator(di);\n\n        /* We can free the accumulator dictionary now. */\n        dictRelease(accumulator);\n    } else {\n        serverPanic(\"Unknown operator\");\n    }\n\n    if (dbDelete(c->db,dstkey))\n        touched = 1;\n    if (dstzset->zsl->length) {\n        zsetConvertToZiplistIfNeeded(dstobj,maxelelen);\n        dbAdd(c->db,dstkey,dstobj);\n        addReplyLongLong(c,zsetLength(dstobj));\n        signalModifiedKey(c->db,dstkey);\n        notifyKeyspaceEvent(NOTIFY_ZSET,\n            (op == SET_OP_UNION) ? \"zunionstore\" : \"zinterstore\",\n            dstkey,c->db->id);\n        server.dirty++;\n    } else {\n        decrRefCount(dstobj);\n        addReply(c,shared.czero);\n        if (touched) {\n            signalModifiedKey(c->db,dstkey);\n            notifyKeyspaceEvent(NOTIFY_GENERIC,\"del\",dstkey,c->db->id);\n            server.dirty++;\n        }\n    }\n    zfree(src);\n}\n\nvoid zunionstoreCommand(client *c) {\n    zunionInterGenericCommand(c,c->argv[1], SET_OP_UNION);\n}\n\nvoid zinterstoreCommand(client *c) {\n    zunionInterGenericCommand(c,c->argv[1], SET_OP_INTER);\n}\n\nvoid zrangeGenericCommand(client *c, int reverse) {\n    robj *key = c->argv[1];\n    robj *zobj;\n    int withscores = 0;\n    long start;\n    long end;\n    int llen;\n    int rangelen;\n\n    if ((getLongFromObjectOrReply(c, c->argv[2], &start, NULL) != C_OK) ||\n        (getLongFromObjectOrReply(c, c->argv[3], &end, NULL) != C_OK)) return;\n\n    if (c->argc == 5 && !strcasecmp(c->argv[4]->ptr,\"withscores\")) {\n        withscores = 1;\n    } else if (c->argc >= 5) {\n        addReply(c,shared.syntaxerr);\n        return;\n    }\n\n    if ((zobj = lookupKeyReadOrReply(c,key,shared.emptymultibulk)) == NULL\n         || checkType(c,zobj,OBJ_ZSET)) return;\n\n    /* Sanitize indexes. */\n    llen = zsetLength(zobj);\n    if (start < 0) start = llen+start;\n    if (end < 0) end = llen+end;\n    if (start < 0) start = 0;\n\n    /* Invariant: start >= 0, so this test will be true when end < 0.\n     * The range is empty when start > end or start >= length. */\n    if (start > end || start >= llen) {\n        addReply(c,shared.emptymultibulk);\n        return;\n    }\n    if (end >= llen) end = llen-1;\n    rangelen = (end-start)+1;\n\n    /* Return the result in form of a multi-bulk reply */\n    addReplyMultiBulkLen(c, withscores ? (rangelen*2) : rangelen);\n\n    if (zobj->encoding == OBJ_ENCODING_ZIPLIST) {\n        unsigned char *zl = zobj->ptr;\n        unsigned char *eptr, *sptr;\n        unsigned char *vstr;\n        unsigned int vlen;\n        long long vlong;\n\n        if (reverse)\n            eptr = ziplistIndex(zl,-2-(2*start));\n        else\n            eptr = ziplistIndex(zl,2*start);\n\n        serverAssertWithInfo(c,zobj,eptr != NULL);\n        sptr = ziplistNext(zl,eptr);\n\n        while (rangelen--) {\n            serverAssertWithInfo(c,zobj,eptr != NULL && sptr != NULL);\n            serverAssertWithInfo(c,zobj,ziplistGet(eptr,&vstr,&vlen,&vlong));\n            if (vstr == NULL)\n                addReplyBulkLongLong(c,vlong);\n            else\n                addReplyBulkCBuffer(c,vstr,vlen);\n\n            if (withscores)\n                addReplyDouble(c,zzlGetScore(sptr));\n\n            if (reverse)\n                zzlPrev(zl,&eptr,&sptr);\n            else\n                zzlNext(zl,&eptr,&sptr);\n        }\n\n    } else if (zobj->encoding == OBJ_ENCODING_SKIPLIST) {\n        zset *zs = zobj->ptr;\n        zskiplist *zsl = zs->zsl;\n        zskiplistNode *ln;\n        robj *ele;\n\n        /* Check if starting point is trivial, before doing log(N) lookup. */\n        if (reverse) {\n            ln = zsl->tail;\n            if (start > 0)\n                ln = zslGetElementByRank(zsl,llen-start);\n        } else {\n            ln = zsl->header->level[0].forward;\n            if (start > 0)\n                ln = zslGetElementByRank(zsl,start+1);\n        }\n\n        while(rangelen--) {\n            serverAssertWithInfo(c,zobj,ln != NULL);\n            ele = ln->obj;\n            addReplyBulk(c,ele);\n            if (withscores)\n                addReplyDouble(c,ln->score);\n            ln = reverse ? ln->backward : ln->level[0].forward;\n        }\n    } else {\n        serverPanic(\"Unknown sorted set encoding\");\n    }\n}\n\nvoid zrangeCommand(client *c) {\n    zrangeGenericCommand(c,0);\n}\n\nvoid zrevrangeCommand(client *c) {\n    zrangeGenericCommand(c,1);\n}\n\n/* This command implements ZRANGEBYSCORE, ZREVRANGEBYSCORE. */\nvoid genericZrangebyscoreCommand(client *c, int reverse) {\n    zrangespec range;\n    robj *key = c->argv[1];\n    robj *zobj;\n    long offset = 0, limit = -1;\n    int withscores = 0;\n    unsigned long rangelen = 0;\n    void *replylen = NULL;\n    int minidx, maxidx;\n\n    /* Parse the range arguments. */\n    if (reverse) {\n        /* Range is given as [max,min] */\n        maxidx = 2; minidx = 3;\n    } else {\n        /* Range is given as [min,max] */\n        minidx = 2; maxidx = 3;\n    }\n\n    if (zslParseRange(c->argv[minidx],c->argv[maxidx],&range) != C_OK) {\n        addReplyError(c,\"min or max is not a float\");\n        return;\n    }\n\n    /* Parse optional extra arguments. Note that ZCOUNT will exactly have\n     * 4 arguments, so we'll never enter the following code path. */\n    if (c->argc > 4) {\n        int remaining = c->argc - 4;\n        int pos = 4;\n\n        while (remaining) {\n            if (remaining >= 1 && !strcasecmp(c->argv[pos]->ptr,\"withscores\")) {\n                pos++; remaining--;\n                withscores = 1;\n            } else if (remaining >= 3 && !strcasecmp(c->argv[pos]->ptr,\"limit\")) {\n                if ((getLongFromObjectOrReply(c, c->argv[pos+1], &offset, NULL) != C_OK) ||\n                    (getLongFromObjectOrReply(c, c->argv[pos+2], &limit, NULL) != C_OK)) return;\n                pos += 3; remaining -= 3;\n            } else {\n                addReply(c,shared.syntaxerr);\n                return;\n            }\n        }\n    }\n\n    /* Ok, lookup the key and get the range */\n    if ((zobj = lookupKeyReadOrReply(c,key,shared.emptymultibulk)) == NULL ||\n        checkType(c,zobj,OBJ_ZSET)) return;\n\n    if (zobj->encoding == OBJ_ENCODING_ZIPLIST) {\n        unsigned char *zl = zobj->ptr;\n        unsigned char *eptr, *sptr;\n        unsigned char *vstr;\n        unsigned int vlen;\n        long long vlong;\n        double score;\n\n        /* If reversed, get the last node in range as starting point. */\n        if (reverse) {\n            eptr = zzlLastInRange(zl,&range);\n        } else {\n            eptr = zzlFirstInRange(zl,&range);\n        }\n\n        /* No \"first\" element in the specified interval. */\n        if (eptr == NULL) {\n            addReply(c, shared.emptymultibulk);\n            return;\n        }\n\n        /* Get score pointer for the first element. */\n        serverAssertWithInfo(c,zobj,eptr != NULL);\n        sptr = ziplistNext(zl,eptr);\n\n        /* We don't know in advance how many matching elements there are in the\n         * list, so we push this object that will represent the multi-bulk\n         * length in the output buffer, and will \"fix\" it later */\n        replylen = addDeferredMultiBulkLength(c);\n\n        /* If there is an offset, just traverse the number of elements without\n         * checking the score because that is done in the next loop. */\n        while (eptr && offset--) {\n            if (reverse) {\n                zzlPrev(zl,&eptr,&sptr);\n            } else {\n                zzlNext(zl,&eptr,&sptr);\n            }\n        }\n\n        while (eptr && limit--) {\n            score = zzlGetScore(sptr);\n\n            /* Abort when the node is no longer in range. */\n            if (reverse) {\n                if (!zslValueGteMin(score,&range)) break;\n            } else {\n                if (!zslValueLteMax(score,&range)) break;\n            }\n\n            /* We know the element exists, so ziplistGet should always succeed */\n            serverAssertWithInfo(c,zobj,ziplistGet(eptr,&vstr,&vlen,&vlong));\n\n            rangelen++;\n            if (vstr == NULL) {\n                addReplyBulkLongLong(c,vlong);\n            } else {\n                addReplyBulkCBuffer(c,vstr,vlen);\n            }\n\n            if (withscores) {\n                addReplyDouble(c,score);\n            }\n\n            /* Move to next node */\n            if (reverse) {\n                zzlPrev(zl,&eptr,&sptr);\n            } else {\n                zzlNext(zl,&eptr,&sptr);\n            }\n        }\n    } else if (zobj->encoding == OBJ_ENCODING_SKIPLIST) {\n        zset *zs = zobj->ptr;\n        zskiplist *zsl = zs->zsl;\n        zskiplistNode *ln;\n\n        /* If reversed, get the last node in range as starting point. */\n        if (reverse) {\n            ln = zslLastInRange(zsl,&range);\n        } else {\n            ln = zslFirstInRange(zsl,&range);\n        }\n\n        /* No \"first\" element in the specified interval. */\n        if (ln == NULL) {\n            addReply(c, shared.emptymultibulk);\n            return;\n        }\n\n        /* We don't know in advance how many matching elements there are in the\n         * list, so we push this object that will represent the multi-bulk\n         * length in the output buffer, and will \"fix\" it later */\n        replylen = addDeferredMultiBulkLength(c);\n\n        /* If there is an offset, just traverse the number of elements without\n         * checking the score because that is done in the next loop. */\n        while (ln && offset--) {\n            if (reverse) {\n                ln = ln->backward;\n            } else {\n                ln = ln->level[0].forward;\n            }\n        }\n\n        while (ln && limit--) {\n            /* Abort when the node is no longer in range. */\n            if (reverse) {\n                if (!zslValueGteMin(ln->score,&range)) break;\n            } else {\n                if (!zslValueLteMax(ln->score,&range)) break;\n            }\n\n            rangelen++;\n            addReplyBulk(c,ln->obj);\n\n            if (withscores) {\n                addReplyDouble(c,ln->score);\n            }\n\n            /* Move to next node */\n            if (reverse) {\n                ln = ln->backward;\n            } else {\n                ln = ln->level[0].forward;\n            }\n        }\n    } else {\n        serverPanic(\"Unknown sorted set encoding\");\n    }\n\n    if (withscores) {\n        rangelen *= 2;\n    }\n\n    setDeferredMultiBulkLength(c, replylen, rangelen);\n}\n\nvoid zrangebyscoreCommand(client *c) {\n    genericZrangebyscoreCommand(c,0);\n}\n\nvoid zrevrangebyscoreCommand(client *c) {\n    genericZrangebyscoreCommand(c,1);\n}\n\nvoid zcountCommand(client *c) {\n    robj *key = c->argv[1];\n    robj *zobj;\n    zrangespec range;\n    int count = 0;\n\n    /* Parse the range arguments */\n    if (zslParseRange(c->argv[2],c->argv[3],&range) != C_OK) {\n        addReplyError(c,\"min or max is not a float\");\n        return;\n    }\n\n    /* Lookup the sorted set */\n    if ((zobj = lookupKeyReadOrReply(c, key, shared.czero)) == NULL ||\n        checkType(c, zobj, OBJ_ZSET)) return;\n\n    if (zobj->encoding == OBJ_ENCODING_ZIPLIST) {\n        unsigned char *zl = zobj->ptr;\n        unsigned char *eptr, *sptr;\n        double score;\n\n        /* Use the first element in range as the starting point */\n        eptr = zzlFirstInRange(zl,&range);\n\n        /* No \"first\" element */\n        if (eptr == NULL) {\n            addReply(c, shared.czero);\n            return;\n        }\n\n        /* First element is in range */\n        sptr = ziplistNext(zl,eptr);\n        score = zzlGetScore(sptr);\n        serverAssertWithInfo(c,zobj,zslValueLteMax(score,&range));\n\n        /* Iterate over elements in range */\n        while (eptr) {\n            score = zzlGetScore(sptr);\n\n            /* Abort when the node is no longer in range. */\n            if (!zslValueLteMax(score,&range)) {\n                break;\n            } else {\n                count++;\n                zzlNext(zl,&eptr,&sptr);\n            }\n        }\n    } else if (zobj->encoding == OBJ_ENCODING_SKIPLIST) {\n        zset *zs = zobj->ptr;\n        zskiplist *zsl = zs->zsl;\n        zskiplistNode *zn;\n        unsigned long rank;\n\n        /* Find first element in range */\n        zn = zslFirstInRange(zsl, &range);\n\n        /* Use rank of first element, if any, to determine preliminary count */\n        if (zn != NULL) {\n            rank = zslGetRank(zsl, zn->score, zn->obj);\n            count = (zsl->length - (rank - 1));\n\n            /* Find last element in range */\n            zn = zslLastInRange(zsl, &range);\n\n            /* Use rank of last element, if any, to determine the actual count */\n            if (zn != NULL) {\n                rank = zslGetRank(zsl, zn->score, zn->obj);\n                count -= (zsl->length - rank);\n            }\n        }\n    } else {\n        serverPanic(\"Unknown sorted set encoding\");\n    }\n\n    addReplyLongLong(c, count);\n}\n\nvoid zlexcountCommand(client *c) {\n    robj *key = c->argv[1];\n    robj *zobj;\n    zlexrangespec range;\n    int count = 0;\n\n    /* Parse the range arguments */\n    if (zslParseLexRange(c->argv[2],c->argv[3],&range) != C_OK) {\n        addReplyError(c,\"min or max not valid string range item\");\n        return;\n    }\n\n    /* Lookup the sorted set */\n    if ((zobj = lookupKeyReadOrReply(c, key, shared.czero)) == NULL ||\n        checkType(c, zobj, OBJ_ZSET))\n    {\n        zslFreeLexRange(&range);\n        return;\n    }\n\n    if (zobj->encoding == OBJ_ENCODING_ZIPLIST) {\n        unsigned char *zl = zobj->ptr;\n        unsigned char *eptr, *sptr;\n\n        /* Use the first element in range as the starting point */\n        eptr = zzlFirstInLexRange(zl,&range);\n\n        /* No \"first\" element */\n        if (eptr == NULL) {\n            zslFreeLexRange(&range);\n            addReply(c, shared.czero);\n            return;\n        }\n\n        /* First element is in range */\n        sptr = ziplistNext(zl,eptr);\n        serverAssertWithInfo(c,zobj,zzlLexValueLteMax(eptr,&range));\n\n        /* Iterate over elements in range */\n        while (eptr) {\n            /* Abort when the node is no longer in range. */\n            if (!zzlLexValueLteMax(eptr,&range)) {\n                break;\n            } else {\n                count++;\n                zzlNext(zl,&eptr,&sptr);\n            }\n        }\n    } else if (zobj->encoding == OBJ_ENCODING_SKIPLIST) {\n        zset *zs = zobj->ptr;\n        zskiplist *zsl = zs->zsl;\n        zskiplistNode *zn;\n        unsigned long rank;\n\n        /* Find first element in range */\n        zn = zslFirstInLexRange(zsl, &range);\n\n        /* Use rank of first element, if any, to determine preliminary count */\n        if (zn != NULL) {\n            rank = zslGetRank(zsl, zn->score, zn->obj);\n            count = (zsl->length - (rank - 1));\n\n            /* Find last element in range */\n            zn = zslLastInLexRange(zsl, &range);\n\n            /* Use rank of last element, if any, to determine the actual count */\n            if (zn != NULL) {\n                rank = zslGetRank(zsl, zn->score, zn->obj);\n                count -= (zsl->length - rank);\n            }\n        }\n    } else {\n        serverPanic(\"Unknown sorted set encoding\");\n    }\n\n    zslFreeLexRange(&range);\n    addReplyLongLong(c, count);\n}\n\n/* This command implements ZRANGEBYLEX, ZREVRANGEBYLEX. */\nvoid genericZrangebylexCommand(client *c, int reverse) {\n    zlexrangespec range;\n    robj *key = c->argv[1];\n    robj *zobj;\n    long offset = 0, limit = -1;\n    unsigned long rangelen = 0;\n    void *replylen = NULL;\n    int minidx, maxidx;\n\n    /* Parse the range arguments. */\n    if (reverse) {\n        /* Range is given as [max,min] */\n        maxidx = 2; minidx = 3;\n    } else {\n        /* Range is given as [min,max] */\n        minidx = 2; maxidx = 3;\n    }\n\n    if (zslParseLexRange(c->argv[minidx],c->argv[maxidx],&range) != C_OK) {\n        addReplyError(c,\"min or max not valid string range item\");\n        return;\n    }\n\n    /* Parse optional extra arguments. Note that ZCOUNT will exactly have\n     * 4 arguments, so we'll never enter the following code path. */\n    if (c->argc > 4) {\n        int remaining = c->argc - 4;\n        int pos = 4;\n\n        while (remaining) {\n            if (remaining >= 3 && !strcasecmp(c->argv[pos]->ptr,\"limit\")) {\n                if ((getLongFromObjectOrReply(c, c->argv[pos+1], &offset, NULL) != C_OK) ||\n                    (getLongFromObjectOrReply(c, c->argv[pos+2], &limit, NULL) != C_OK)) return;\n                pos += 3; remaining -= 3;\n            } else {\n                zslFreeLexRange(&range);\n                addReply(c,shared.syntaxerr);\n                return;\n            }\n        }\n    }\n\n    /* Ok, lookup the key and get the range */\n    if ((zobj = lookupKeyReadOrReply(c,key,shared.emptymultibulk)) == NULL ||\n        checkType(c,zobj,OBJ_ZSET))\n    {\n        zslFreeLexRange(&range);\n        return;\n    }\n\n    if (zobj->encoding == OBJ_ENCODING_ZIPLIST) {\n        unsigned char *zl = zobj->ptr;\n        unsigned char *eptr, *sptr;\n        unsigned char *vstr;\n        unsigned int vlen;\n        long long vlong;\n\n        /* If reversed, get the last node in range as starting point. */\n        if (reverse) {\n            eptr = zzlLastInLexRange(zl,&range);\n        } else {\n            eptr = zzlFirstInLexRange(zl,&range);\n        }\n\n        /* No \"first\" element in the specified interval. */\n        if (eptr == NULL) {\n            addReply(c, shared.emptymultibulk);\n            zslFreeLexRange(&range);\n            return;\n        }\n\n        /* Get score pointer for the first element. */\n        serverAssertWithInfo(c,zobj,eptr != NULL);\n        sptr = ziplistNext(zl,eptr);\n\n        /* We don't know in advance how many matching elements there are in the\n         * list, so we push this object that will represent the multi-bulk\n         * length in the output buffer, and will \"fix\" it later */\n        replylen = addDeferredMultiBulkLength(c);\n\n        /* If there is an offset, just traverse the number of elements without\n         * checking the score because that is done in the next loop. */\n        while (eptr && offset--) {\n            if (reverse) {\n                zzlPrev(zl,&eptr,&sptr);\n            } else {\n                zzlNext(zl,&eptr,&sptr);\n            }\n        }\n\n        while (eptr && limit--) {\n            /* Abort when the node is no longer in range. */\n            if (reverse) {\n                if (!zzlLexValueGteMin(eptr,&range)) break;\n            } else {\n                if (!zzlLexValueLteMax(eptr,&range)) break;\n            }\n\n            /* We know the element exists, so ziplistGet should always\n             * succeed. */\n            serverAssertWithInfo(c,zobj,ziplistGet(eptr,&vstr,&vlen,&vlong));\n\n            rangelen++;\n            if (vstr == NULL) {\n                addReplyBulkLongLong(c,vlong);\n            } else {\n                addReplyBulkCBuffer(c,vstr,vlen);\n            }\n\n            /* Move to next node */\n            if (reverse) {\n                zzlPrev(zl,&eptr,&sptr);\n            } else {\n                zzlNext(zl,&eptr,&sptr);\n            }\n        }\n    } else if (zobj->encoding == OBJ_ENCODING_SKIPLIST) {\n        zset *zs = zobj->ptr;\n        zskiplist *zsl = zs->zsl;\n        zskiplistNode *ln;\n\n        /* If reversed, get the last node in range as starting point. */\n        if (reverse) {\n            ln = zslLastInLexRange(zsl,&range);\n        } else {\n            ln = zslFirstInLexRange(zsl,&range);\n        }\n\n        /* No \"first\" element in the specified interval. */\n        if (ln == NULL) {\n            addReply(c, shared.emptymultibulk);\n            zslFreeLexRange(&range);\n            return;\n        }\n\n        /* We don't know in advance how many matching elements there are in the\n         * list, so we push this object that will represent the multi-bulk\n         * length in the output buffer, and will \"fix\" it later */\n        replylen = addDeferredMultiBulkLength(c);\n\n        /* If there is an offset, just traverse the number of elements without\n         * checking the score because that is done in the next loop. */\n        while (ln && offset--) {\n            if (reverse) {\n                ln = ln->backward;\n            } else {\n                ln = ln->level[0].forward;\n            }\n        }\n\n        while (ln && limit--) {\n            /* Abort when the node is no longer in range. */\n            if (reverse) {\n                if (!zslLexValueGteMin(ln->obj,&range)) break;\n            } else {\n                if (!zslLexValueLteMax(ln->obj,&range)) break;\n            }\n\n            rangelen++;\n            addReplyBulk(c,ln->obj);\n\n            /* Move to next node */\n            if (reverse) {\n                ln = ln->backward;\n            } else {\n                ln = ln->level[0].forward;\n            }\n        }\n    } else {\n        serverPanic(\"Unknown sorted set encoding\");\n    }\n\n    zslFreeLexRange(&range);\n    setDeferredMultiBulkLength(c, replylen, rangelen);\n}\n\nvoid zrangebylexCommand(client *c) {\n    genericZrangebylexCommand(c,0);\n}\n\nvoid zrevrangebylexCommand(client *c) {\n    genericZrangebylexCommand(c,1);\n}\n\nvoid zcardCommand(client *c) {\n    robj *key = c->argv[1];\n    robj *zobj;\n\n    if ((zobj = lookupKeyReadOrReply(c,key,shared.czero)) == NULL ||\n        checkType(c,zobj,OBJ_ZSET)) return;\n\n    addReplyLongLong(c,zsetLength(zobj));\n}\n\nvoid zscoreCommand(client *c) {\n    robj *key = c->argv[1];\n    robj *zobj;\n    double score;\n\n    if ((zobj = lookupKeyReadOrReply(c,key,shared.nullbulk)) == NULL ||\n        checkType(c,zobj,OBJ_ZSET)) return;\n\n    if (zsetScore(zobj,c->argv[2],&score) == C_ERR) {\n        addReply(c,shared.nullbulk);\n    } else {\n        addReplyDouble(c,score);\n    }\n}\n\nvoid zrankGenericCommand(client *c, int reverse) {\n    robj *key = c->argv[1];\n    robj *ele = c->argv[2];\n    robj *zobj;\n    unsigned long llen;\n    unsigned long rank;\n\n    if ((zobj = lookupKeyReadOrReply(c,key,shared.nullbulk)) == NULL ||\n        checkType(c,zobj,OBJ_ZSET)) return;\n    llen = zsetLength(zobj);\n\n    serverAssertWithInfo(c,ele,sdsEncodedObject(ele));\n\n    if (zobj->encoding == OBJ_ENCODING_ZIPLIST) {\n        unsigned char *zl = zobj->ptr;\n        unsigned char *eptr, *sptr;\n\n        eptr = ziplistIndex(zl,0);\n        serverAssertWithInfo(c,zobj,eptr != NULL);\n        sptr = ziplistNext(zl,eptr);\n        serverAssertWithInfo(c,zobj,sptr != NULL);\n\n        rank = 1;\n        while(eptr != NULL) {\n            if (ziplistCompare(eptr,ele->ptr,sdslen(ele->ptr)))\n                break;\n            rank++;\n            zzlNext(zl,&eptr,&sptr);\n        }\n\n        if (eptr != NULL) {\n            if (reverse)\n                addReplyLongLong(c,llen-rank);\n            else\n                addReplyLongLong(c,rank-1);\n        } else {\n            addReply(c,shared.nullbulk);\n        }\n    } else if (zobj->encoding == OBJ_ENCODING_SKIPLIST) {\n        zset *zs = zobj->ptr;\n        zskiplist *zsl = zs->zsl;\n        dictEntry *de;\n        double score;\n\n        ele = c->argv[2];\n        de = dictFind(zs->dict,ele);\n        if (de != NULL) {\n            score = *(double*)dictGetVal(de);\n            rank = zslGetRank(zsl,score,ele);\n            serverAssertWithInfo(c,ele,rank); /* Existing elements always have a rank. */\n            if (reverse)\n                addReplyLongLong(c,llen-rank);\n            else\n                addReplyLongLong(c,rank-1);\n        } else {\n            addReply(c,shared.nullbulk);\n        }\n    } else {\n        serverPanic(\"Unknown sorted set encoding\");\n    }\n}\n\nvoid zrankCommand(client *c) {\n    zrankGenericCommand(c, 0);\n}\n\nvoid zrevrankCommand(client *c) {\n    zrankGenericCommand(c, 1);\n}\n\nvoid zscanCommand(client *c) {\n    robj *o;\n    unsigned long cursor;\n\n    if (parseScanCursorOrReply(c,c->argv[2],&cursor) == C_ERR) return;\n    if ((o = lookupKeyReadOrReply(c,c->argv[1],shared.emptyscan)) == NULL ||\n        checkType(c,o,OBJ_ZSET)) return;\n    scanGenericCommand(c,o,cursor);\n}\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/src/testhelp.h",
    "content": "/* This is a really minimal testing framework for C.\n *\n * Example:\n *\n * test_cond(\"Check if 1 == 1\", 1==1)\n * test_cond(\"Check if 5 > 10\", 5 > 10)\n * test_report()\n *\n * ----------------------------------------------------------------------------\n *\n * Copyright (c) 2010-2012, Salvatore Sanfilippo <antirez at gmail dot com>\n * All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions are met:\n *\n *   * Redistributions of source code must retain the above copyright notice,\n *     this list of conditions and the following disclaimer.\n *   * Redistributions in binary form must reproduce the above copyright\n *     notice, this list of conditions and the following disclaimer in the\n *     documentation and/or other materials provided with the distribution.\n *   * Neither the name of Redis nor the names of its contributors may be used\n *     to endorse or promote products derived from this software without\n *     specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\"\n * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\n * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE\n * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR\n * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF\n * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS\n * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN\n * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)\n * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE\n * POSSIBILITY OF SUCH DAMAGE.\n */\n\n#ifndef __TESTHELP_H\n#define __TESTHELP_H\n\nint __failed_tests = 0;\nint __test_num = 0;\n#define test_cond(descr,_c) do { \\\n    __test_num++; printf(\"%d - %s: \", __test_num, descr); \\\n    if(_c) printf(\"PASSED\\n\"); else {printf(\"FAILED\\n\"); __failed_tests++;} \\\n} while(0);\n#define test_report() do { \\\n    printf(\"%d tests, %d passed, %d failed\\n\", __test_num, \\\n                    __test_num-__failed_tests, __failed_tests); \\\n    if (__failed_tests) { \\\n        printf(\"=== WARNING === We have failed tests here...\\n\"); \\\n        exit(1); \\\n    } \\\n} while(0);\n\n#endif\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/src/util.c",
    "content": "/*\n * Copyright (c) 2009-2012, Salvatore Sanfilippo <antirez at gmail dot com>\n * All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions are met:\n *\n *   * Redistributions of source code must retain the above copyright notice,\n *     this list of conditions and the following disclaimer.\n *   * Redistributions in binary form must reproduce the above copyright\n *     notice, this list of conditions and the following disclaimer in the\n *     documentation and/or other materials provided with the distribution.\n *   * Neither the name of Redis nor the names of its contributors may be used\n *     to endorse or promote products derived from this software without\n *     specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\"\n * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\n * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE\n * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR\n * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF\n * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS\n * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN\n * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)\n * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE\n * POSSIBILITY OF SUCH DAMAGE.\n */\n\n#include \"fmacros.h\"\n#include <stdlib.h>\n#include <stdio.h>\n#include <string.h>\n#include <ctype.h>\n#include <limits.h>\n#include <math.h>\n#include <unistd.h>\n#include <sys/time.h>\n#include <float.h>\n#include <stdint.h>\n#include <errno.h>\n\n#include \"util.h\"\n#include \"sha1.h\"\n\n/* Glob-style pattern matching. */\nint stringmatchlen(const char *pattern, int patternLen,\n        const char *string, int stringLen, int nocase)\n{\n    while(patternLen) {\n        switch(pattern[0]) {\n        case '*':\n            while (pattern[1] == '*') {\n                pattern++;\n                patternLen--;\n            }\n            if (patternLen == 1)\n                return 1; /* match */\n            while(stringLen) {\n                if (stringmatchlen(pattern+1, patternLen-1,\n                            string, stringLen, nocase))\n                    return 1; /* match */\n                string++;\n                stringLen--;\n            }\n            return 0; /* no match */\n            break;\n        case '?':\n            if (stringLen == 0)\n                return 0; /* no match */\n            string++;\n            stringLen--;\n            break;\n        case '[':\n        {\n            int not, match;\n\n            pattern++;\n            patternLen--;\n            not = pattern[0] == '^';\n            if (not) {\n                pattern++;\n                patternLen--;\n            }\n            match = 0;\n            while(1) {\n                if (pattern[0] == '\\\\') {\n                    pattern++;\n                    patternLen--;\n                    if (pattern[0] == string[0])\n                        match = 1;\n                } else if (pattern[0] == ']') {\n                    break;\n                } else if (patternLen == 0) {\n                    pattern--;\n                    patternLen++;\n                    break;\n                } else if (pattern[1] == '-' && patternLen >= 3) {\n                    int start = pattern[0];\n                    int end = pattern[2];\n                    int c = string[0];\n                    if (start > end) {\n                        int t = start;\n                        start = end;\n                        end = t;\n                    }\n                    if (nocase) {\n                        start = tolower(start);\n                        end = tolower(end);\n                        c = tolower(c);\n                    }\n                    pattern += 2;\n                    patternLen -= 2;\n                    if (c >= start && c <= end)\n                        match = 1;\n                } else {\n                    if (!nocase) {\n                        if (pattern[0] == string[0])\n                            match = 1;\n                    } else {\n                        if (tolower((int)pattern[0]) == tolower((int)string[0]))\n                            match = 1;\n                    }\n                }\n                pattern++;\n                patternLen--;\n            }\n            if (not)\n                match = !match;\n            if (!match)\n                return 0; /* no match */\n            string++;\n            stringLen--;\n            break;\n        }\n        case '\\\\':\n            if (patternLen >= 2) {\n                pattern++;\n                patternLen--;\n            }\n            /* fall through */\n        default:\n            if (!nocase) {\n                if (pattern[0] != string[0])\n                    return 0; /* no match */\n            } else {\n                if (tolower((int)pattern[0]) != tolower((int)string[0]))\n                    return 0; /* no match */\n            }\n            string++;\n            stringLen--;\n            break;\n        }\n        pattern++;\n        patternLen--;\n        if (stringLen == 0) {\n            while(*pattern == '*') {\n                pattern++;\n                patternLen--;\n            }\n            break;\n        }\n    }\n    if (patternLen == 0 && stringLen == 0)\n        return 1;\n    return 0;\n}\n\nint stringmatch(const char *pattern, const char *string, int nocase) {\n    return stringmatchlen(pattern,strlen(pattern),string,strlen(string),nocase);\n}\n\n/* Convert a string representing an amount of memory into the number of\n * bytes, so for instance memtoll(\"1Gb\") will return 1073741824 that is\n * (1024*1024*1024).\n *\n * On parsing error, if *err is not NULL, it's set to 1, otherwise it's\n * set to 0. On error the function return value is 0, regardless of the\n * fact 'err' is NULL or not. */\nlong long memtoll(const char *p, int *err) {\n    const char *u;\n    char buf[128];\n    long mul; /* unit multiplier */\n    long long val;\n    unsigned int digits;\n\n    if (err) *err = 0;\n\n    /* Search the first non digit character. */\n    u = p;\n    if (*u == '-') u++;\n    while(*u && isdigit(*u)) u++;\n    if (*u == '\\0' || !strcasecmp(u,\"b\")) {\n        mul = 1;\n    } else if (!strcasecmp(u,\"k\")) {\n        mul = 1000;\n    } else if (!strcasecmp(u,\"kb\")) {\n        mul = 1024;\n    } else if (!strcasecmp(u,\"m\")) {\n        mul = 1000*1000;\n    } else if (!strcasecmp(u,\"mb\")) {\n        mul = 1024*1024;\n    } else if (!strcasecmp(u,\"g\")) {\n        mul = 1000L*1000*1000;\n    } else if (!strcasecmp(u,\"gb\")) {\n        mul = 1024L*1024*1024;\n    } else {\n        if (err) *err = 1;\n        return 0;\n    }\n\n    /* Copy the digits into a buffer, we'll use strtoll() to convert\n     * the digit (without the unit) into a number. */\n    digits = u-p;\n    if (digits >= sizeof(buf)) {\n        if (err) *err = 1;\n        return 0;\n    }\n    memcpy(buf,p,digits);\n    buf[digits] = '\\0';\n\n    char *endptr;\n    errno = 0;\n    val = strtoll(buf,&endptr,10);\n    if ((val == 0 && errno == EINVAL) || *endptr != '\\0') {\n        if (err) *err = 1;\n        return 0;\n    }\n    return val*mul;\n}\n\n/* Return the number of digits of 'v' when converted to string in radix 10.\n * See ll2string() for more information. */\nuint32_t digits10(uint64_t v) {\n    if (v < 10) return 1;\n    if (v < 100) return 2;\n    if (v < 1000) return 3;\n    if (v < 1000000000000UL) {\n        if (v < 100000000UL) {\n            if (v < 1000000) {\n                if (v < 10000) return 4;\n                return 5 + (v >= 100000);\n            }\n            return 7 + (v >= 10000000UL);\n        }\n        if (v < 10000000000UL) {\n            return 9 + (v >= 1000000000UL);\n        }\n        return 11 + (v >= 100000000000UL);\n    }\n    return 12 + digits10(v / 1000000000000UL);\n}\n\n/* Like digits10() but for signed values. */\nuint32_t sdigits10(int64_t v) {\n    if (v < 0) {\n        /* Abs value of LLONG_MIN requires special handling. */\n        uint64_t uv = (v != LLONG_MIN) ?\n                      (uint64_t)-v : ((uint64_t) LLONG_MAX)+1;\n        return digits10(uv)+1; /* +1 for the minus. */\n    } else {\n        return digits10(v);\n    }\n}\n\n/* Convert a long long into a string. Returns the number of\n * characters needed to represent the number.\n * If the buffer is not big enough to store the string, 0 is returned.\n *\n * Based on the following article (that apparently does not provide a\n * novel approach but only publicizes an already used technique):\n *\n * https://www.facebook.com/notes/facebook-engineering/three-optimization-tips-for-c/10151361643253920\n *\n * Modified in order to handle signed integers since the original code was\n * designed for unsigned integers. */\nint ll2string(char* dst, size_t dstlen, long long svalue) {\n    static const char digits[201] =\n        \"0001020304050607080910111213141516171819\"\n        \"2021222324252627282930313233343536373839\"\n        \"4041424344454647484950515253545556575859\"\n        \"6061626364656667686970717273747576777879\"\n        \"8081828384858687888990919293949596979899\";\n    int negative;\n    unsigned long long value;\n\n    /* The main loop works with 64bit unsigned integers for simplicity, so\n     * we convert the number here and remember if it is negative. */\n    if (svalue < 0) {\n        if (svalue != LLONG_MIN) {\n            value = -svalue;\n        } else {\n            value = ((unsigned long long) LLONG_MAX)+1;\n        }\n        negative = 1;\n    } else {\n        value = svalue;\n        negative = 0;\n    }\n\n    /* Check length. */\n    uint32_t const length = digits10(value)+negative;\n    if (length >= dstlen) return 0;\n\n    /* Null term. */\n    uint32_t next = length;\n    dst[next] = '\\0';\n    next--;\n    while (value >= 100) {\n        int const i = (value % 100) * 2;\n        value /= 100;\n        dst[next] = digits[i + 1];\n        dst[next - 1] = digits[i];\n        next -= 2;\n    }\n\n    /* Handle last 1-2 digits. */\n    if (value < 10) {\n        dst[next] = '0' + (uint32_t) value;\n    } else {\n        int i = (uint32_t) value * 2;\n        dst[next] = digits[i + 1];\n        dst[next - 1] = digits[i];\n    }\n\n    /* Add sign. */\n    if (negative) dst[0] = '-';\n    return length;\n}\n\n/* Convert a string into a long long. Returns 1 if the string could be parsed\n * into a (non-overflowing) long long, 0 otherwise. The value will be set to\n * the parsed value when appropriate. */\nint string2ll(const char *s, size_t slen, long long *value) {\n    const char *p = s;\n    size_t plen = 0;\n    int negative = 0;\n    unsigned long long v;\n\n    if (plen == slen)\n        return 0;\n\n    /* Special case: first and only digit is 0. */\n    if (slen == 1 && p[0] == '0') {\n        if (value != NULL) *value = 0;\n        return 1;\n    }\n\n    if (p[0] == '-') {\n        negative = 1;\n        p++; plen++;\n\n        /* Abort on only a negative sign. */\n        if (plen == slen)\n            return 0;\n    }\n\n    /* First digit should be 1-9, otherwise the string should just be 0. */\n    if (p[0] >= '1' && p[0] <= '9') {\n        v = p[0]-'0';\n        p++; plen++;\n    } else if (p[0] == '0' && slen == 1) {\n        *value = 0;\n        return 1;\n    } else {\n        return 0;\n    }\n\n    while (plen < slen && p[0] >= '0' && p[0] <= '9') {\n        if (v > (ULLONG_MAX / 10)) /* Overflow. */\n            return 0;\n        v *= 10;\n\n        if (v > (ULLONG_MAX - (p[0]-'0'))) /* Overflow. */\n            return 0;\n        v += p[0]-'0';\n\n        p++; plen++;\n    }\n\n    /* Return if not all bytes were used. */\n    if (plen < slen)\n        return 0;\n\n    if (negative) {\n        if (v > ((unsigned long long)(-(LLONG_MIN+1))+1)) /* Overflow. */\n            return 0;\n        if (value != NULL) *value = -v;\n    } else {\n        if (v > LLONG_MAX) /* Overflow. */\n            return 0;\n        if (value != NULL) *value = v;\n    }\n    return 1;\n}\n\n/* Convert a string into a long. Returns 1 if the string could be parsed into a\n * (non-overflowing) long, 0 otherwise. The value will be set to the parsed\n * value when appropriate. */\nint string2l(const char *s, size_t slen, long *lval) {\n    long long llval;\n\n    if (!string2ll(s,slen,&llval))\n        return 0;\n\n    if (llval < LONG_MIN || llval > LONG_MAX)\n        return 0;\n\n    *lval = (long)llval;\n    return 1;\n}\n\n/* Convert a double to a string representation. Returns the number of bytes\n * required. The representation should always be parsable by strtod(3). */\nint d2string(char *buf, size_t len, double value) {\n    if (isnan(value)) {\n        len = snprintf(buf,len,\"nan\");\n    } else if (isinf(value)) {\n        if (value < 0)\n            len = snprintf(buf,len,\"-inf\");\n        else\n            len = snprintf(buf,len,\"inf\");\n    } else if (value == 0) {\n        /* See: http://en.wikipedia.org/wiki/Signed_zero, \"Comparisons\". */\n        if (1.0/value < 0)\n            len = snprintf(buf,len,\"-0\");\n        else\n            len = snprintf(buf,len,\"0\");\n    } else {\n#if (DBL_MANT_DIG >= 52) && (LLONG_MAX == 0x7fffffffffffffffLL)\n        /* Check if the float is in a safe range to be casted into a\n         * long long. We are assuming that long long is 64 bit here.\n         * Also we are assuming that there are no implementations around where\n         * double has precision < 52 bit.\n         *\n         * Under this assumptions we test if a double is inside an interval\n         * where casting to long long is safe. Then using two castings we\n         * make sure the decimal part is zero. If all this is true we use\n         * integer printing function that is much faster. */\n        double min = -4503599627370495; /* (2^52)-1 */\n        double max = 4503599627370496; /* -(2^52) */\n        if (value > min && value < max && value == ((double)((long long)value)))\n            len = ll2string(buf,len,(long long)value);\n        else\n#endif\n            len = snprintf(buf,len,\"%.17g\",value);\n    }\n\n    return len;\n}\n\n/* Generate the Redis \"Run ID\", a SHA1-sized random number that identifies a\n * given execution of Redis, so that if you are talking with an instance\n * having run_id == A, and you reconnect and it has run_id == B, you can be\n * sure that it is either a different instance or it was restarted. */\nvoid getRandomHexChars(char *p, unsigned int len) {\n    char *charset = \"0123456789abcdef\";\n    unsigned int j;\n\n    /* Global state. */\n    static int seed_initialized = 0;\n    static unsigned char seed[20]; /* The SHA1 seed, from /dev/urandom. */\n    static uint64_t counter = 0; /* The counter we hash with the seed. */\n\n    if (!seed_initialized) {\n        /* Initialize a seed and use SHA1 in counter mode, where we hash\n         * the same seed with a progressive counter. For the goals of this\n         * function we just need non-colliding strings, there are no\n         * cryptographic security needs. */\n        FILE *fp = fopen(\"/dev/urandom\",\"r\");\n        if (fp && fread(seed,sizeof(seed),1,fp) == 1)\n            seed_initialized = 1;\n        if (fp) fclose(fp);\n    }\n\n    if (seed_initialized) {\n        while(len) {\n            unsigned char digest[20];\n            SHA1_CTX ctx;\n            unsigned int copylen = len > 20 ? 20 : len;\n\n            SHA1Init(&ctx);\n            SHA1Update(&ctx, seed, sizeof(seed));\n            SHA1Update(&ctx, (unsigned char*)&counter,sizeof(counter));\n            SHA1Final(digest, &ctx);\n            counter++;\n\n            memcpy(p,digest,copylen);\n            /* Convert to hex digits. */\n            for (j = 0; j < copylen; j++) p[j] = charset[p[j] & 0x0F];\n            len -= copylen;\n            p += copylen;\n        }\n    } else {\n        /* If we can't read from /dev/urandom, do some reasonable effort\n         * in order to create some entropy, since this function is used to\n         * generate run_id and cluster instance IDs */\n        char *x = p;\n        unsigned int l = len;\n        struct timeval tv;\n        pid_t pid = getpid();\n\n        /* Use time and PID to fill the initial array. */\n        gettimeofday(&tv,NULL);\n        if (l >= sizeof(tv.tv_usec)) {\n            memcpy(x,&tv.tv_usec,sizeof(tv.tv_usec));\n            l -= sizeof(tv.tv_usec);\n            x += sizeof(tv.tv_usec);\n        }\n        if (l >= sizeof(tv.tv_sec)) {\n            memcpy(x,&tv.tv_sec,sizeof(tv.tv_sec));\n            l -= sizeof(tv.tv_sec);\n            x += sizeof(tv.tv_sec);\n        }\n        if (l >= sizeof(pid)) {\n            memcpy(x,&pid,sizeof(pid));\n            l -= sizeof(pid);\n            x += sizeof(pid);\n        }\n        /* Finally xor it with rand() output, that was already seeded with\n         * time() at startup, and convert to hex digits. */\n        for (j = 0; j < len; j++) {\n            p[j] ^= rand();\n            p[j] = charset[p[j] & 0x0F];\n        }\n    }\n}\n\n/* Given the filename, return the absolute path as an SDS string, or NULL\n * if it fails for some reason. Note that \"filename\" may be an absolute path\n * already, this will be detected and handled correctly.\n *\n * The function does not try to normalize everything, but only the obvious\n * case of one or more \"../\" appearning at the start of \"filename\"\n * relative path. */\nsds getAbsolutePath(char *filename) {\n    char cwd[1024];\n    sds abspath;\n    sds relpath = sdsnew(filename);\n\n    relpath = sdstrim(relpath,\" \\r\\n\\t\");\n    if (relpath[0] == '/') return relpath; /* Path is already absolute. */\n\n    /* If path is relative, join cwd and relative path. */\n    if (getcwd(cwd,sizeof(cwd)) == NULL) {\n        sdsfree(relpath);\n        return NULL;\n    }\n    abspath = sdsnew(cwd);\n    if (sdslen(abspath) && abspath[sdslen(abspath)-1] != '/')\n        abspath = sdscat(abspath,\"/\");\n\n    /* At this point we have the current path always ending with \"/\", and\n     * the trimmed relative path. Try to normalize the obvious case of\n     * trailing ../ elements at the start of the path.\n     *\n     * For every \"../\" we find in the filename, we remove it and also remove\n     * the last element of the cwd, unless the current cwd is \"/\". */\n    while (sdslen(relpath) >= 3 &&\n           relpath[0] == '.' && relpath[1] == '.' && relpath[2] == '/')\n    {\n        sdsrange(relpath,3,-1);\n        if (sdslen(abspath) > 1) {\n            char *p = abspath + sdslen(abspath)-2;\n            int trimlen = 1;\n\n            while(*p != '/') {\n                p--;\n                trimlen++;\n            }\n            sdsrange(abspath,0,-(trimlen+1));\n        }\n    }\n\n    /* Finally glue the two parts together. */\n    abspath = sdscatsds(abspath,relpath);\n    sdsfree(relpath);\n    return abspath;\n}\n\n/* Return true if the specified path is just a file basename without any\n * relative or absolute path. This function just checks that no / or \\\n * character exists inside the specified path, that's enough in the\n * environments where Redis runs. */\nint pathIsBaseName(char *path) {\n    return strchr(path,'/') == NULL && strchr(path,'\\\\') == NULL;\n}\n\n#ifdef REDIS_TEST\n#include <assert.h>\n\nstatic void test_string2ll(void) {\n    char buf[32];\n    long long v;\n\n    /* May not start with +. */\n    strcpy(buf,\"+1\");\n    assert(string2ll(buf,strlen(buf),&v) == 0);\n\n    /* Leading space. */\n    strcpy(buf,\" 1\");\n    assert(string2ll(buf,strlen(buf),&v) == 0);\n\n    /* Trailing space. */\n    strcpy(buf,\"1 \");\n    assert(string2ll(buf,strlen(buf),&v) == 0);\n\n    /* May not start with 0. */\n    strcpy(buf,\"01\");\n    assert(string2ll(buf,strlen(buf),&v) == 0);\n\n    strcpy(buf,\"-1\");\n    assert(string2ll(buf,strlen(buf),&v) == 1);\n    assert(v == -1);\n\n    strcpy(buf,\"0\");\n    assert(string2ll(buf,strlen(buf),&v) == 1);\n    assert(v == 0);\n\n    strcpy(buf,\"1\");\n    assert(string2ll(buf,strlen(buf),&v) == 1);\n    assert(v == 1);\n\n    strcpy(buf,\"99\");\n    assert(string2ll(buf,strlen(buf),&v) == 1);\n    assert(v == 99);\n\n    strcpy(buf,\"-99\");\n    assert(string2ll(buf,strlen(buf),&v) == 1);\n    assert(v == -99);\n\n    strcpy(buf,\"-9223372036854775808\");\n    assert(string2ll(buf,strlen(buf),&v) == 1);\n    assert(v == LLONG_MIN);\n\n    strcpy(buf,\"-9223372036854775809\"); /* overflow */\n    assert(string2ll(buf,strlen(buf),&v) == 0);\n\n    strcpy(buf,\"9223372036854775807\");\n    assert(string2ll(buf,strlen(buf),&v) == 1);\n    assert(v == LLONG_MAX);\n\n    strcpy(buf,\"9223372036854775808\"); /* overflow */\n    assert(string2ll(buf,strlen(buf),&v) == 0);\n}\n\nstatic void test_string2l(void) {\n    char buf[32];\n    long v;\n\n    /* May not start with +. */\n    strcpy(buf,\"+1\");\n    assert(string2l(buf,strlen(buf),&v) == 0);\n\n    /* May not start with 0. */\n    strcpy(buf,\"01\");\n    assert(string2l(buf,strlen(buf),&v) == 0);\n\n    strcpy(buf,\"-1\");\n    assert(string2l(buf,strlen(buf),&v) == 1);\n    assert(v == -1);\n\n    strcpy(buf,\"0\");\n    assert(string2l(buf,strlen(buf),&v) == 1);\n    assert(v == 0);\n\n    strcpy(buf,\"1\");\n    assert(string2l(buf,strlen(buf),&v) == 1);\n    assert(v == 1);\n\n    strcpy(buf,\"99\");\n    assert(string2l(buf,strlen(buf),&v) == 1);\n    assert(v == 99);\n\n    strcpy(buf,\"-99\");\n    assert(string2l(buf,strlen(buf),&v) == 1);\n    assert(v == -99);\n\n#if LONG_MAX != LLONG_MAX\n    strcpy(buf,\"-2147483648\");\n    assert(string2l(buf,strlen(buf),&v) == 1);\n    assert(v == LONG_MIN);\n\n    strcpy(buf,\"-2147483649\"); /* overflow */\n    assert(string2l(buf,strlen(buf),&v) == 0);\n\n    strcpy(buf,\"2147483647\");\n    assert(string2l(buf,strlen(buf),&v) == 1);\n    assert(v == LONG_MAX);\n\n    strcpy(buf,\"2147483648\"); /* overflow */\n    assert(string2l(buf,strlen(buf),&v) == 0);\n#endif\n}\n\nstatic void test_ll2string(void) {\n    char buf[32];\n    long long v;\n    int sz;\n\n    v = 0;\n    sz = ll2string(buf, sizeof buf, v);\n    assert(sz == 1);\n    assert(!strcmp(buf, \"0\"));\n\n    v = -1;\n    sz = ll2string(buf, sizeof buf, v);\n    assert(sz == 2);\n    assert(!strcmp(buf, \"-1\"));\n\n    v = 99;\n    sz = ll2string(buf, sizeof buf, v);\n    assert(sz == 2);\n    assert(!strcmp(buf, \"99\"));\n\n    v = -99;\n    sz = ll2string(buf, sizeof buf, v);\n    assert(sz == 3);\n    assert(!strcmp(buf, \"-99\"));\n\n    v = -2147483648;\n    sz = ll2string(buf, sizeof buf, v);\n    assert(sz == 11);\n    assert(!strcmp(buf, \"-2147483648\"));\n\n    v = LLONG_MIN;\n    sz = ll2string(buf, sizeof buf, v);\n    assert(sz == 20);\n    assert(!strcmp(buf, \"-9223372036854775808\"));\n\n    v = LLONG_MAX;\n    sz = ll2string(buf, sizeof buf, v);\n    assert(sz == 19);\n    assert(!strcmp(buf, \"9223372036854775807\"));\n}\n\n#define UNUSED(x) (void)(x)\nint utilTest(int argc, char **argv) {\n    UNUSED(argc);\n    UNUSED(argv);\n\n    test_string2ll();\n    test_string2l();\n    test_ll2string();\n    return 0;\n}\n#endif\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/src/util.h",
    "content": "/*\n * Copyright (c) 2009-2012, Salvatore Sanfilippo <antirez at gmail dot com>\n * All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions are met:\n *\n *   * Redistributions of source code must retain the above copyright notice,\n *     this list of conditions and the following disclaimer.\n *   * Redistributions in binary form must reproduce the above copyright\n *     notice, this list of conditions and the following disclaimer in the\n *     documentation and/or other materials provided with the distribution.\n *   * Neither the name of Redis nor the names of its contributors may be used\n *     to endorse or promote products derived from this software without\n *     specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\"\n * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\n * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE\n * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR\n * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF\n * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS\n * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN\n * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)\n * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE\n * POSSIBILITY OF SUCH DAMAGE.\n */\n\n#ifndef __REDIS_UTIL_H\n#define __REDIS_UTIL_H\n\n#include <stdint.h>\n#include \"sds.h\"\n\nint stringmatchlen(const char *p, int plen, const char *s, int slen, int nocase);\nint stringmatch(const char *p, const char *s, int nocase);\nlong long memtoll(const char *p, int *err);\nuint32_t digits10(uint64_t v);\nuint32_t sdigits10(int64_t v);\nint ll2string(char *s, size_t len, long long value);\nint string2ll(const char *s, size_t slen, long long *value);\nint string2l(const char *s, size_t slen, long *value);\nint d2string(char *buf, size_t len, double value);\nsds getAbsolutePath(char *filename);\nint pathIsBaseName(char *path);\n\n#ifdef REDIS_TEST\nint utilTest(int argc, char **argv);\n#endif\n\n#endif\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/src/valgrind.sup",
    "content": "{\n   <lzf_unitialized_hash_table>\n   Memcheck:Cond\n   fun:lzf_compress\n}\n\n{\n   <lzf_unitialized_hash_table>\n   Memcheck:Value4\n   fun:lzf_compress\n}\n\n{\n   <lzf_unitialized_hash_table>\n   Memcheck:Value8\n   fun:lzf_compress\n}\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/src/version.h",
    "content": "#define REDIS_VERSION \"3.2.4\"\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/src/ziplist.c",
    "content": "/* The ziplist is a specially encoded dually linked list that is designed\n * to be very memory efficient. It stores both strings and integer values,\n * where integers are encoded as actual integers instead of a series of\n * characters. It allows push and pop operations on either side of the list\n * in O(1) time. However, because every operation requires a reallocation of\n * the memory used by the ziplist, the actual complexity is related to the\n * amount of memory used by the ziplist.\n *\n * ----------------------------------------------------------------------------\n *\n * ZIPLIST OVERALL LAYOUT:\n * The general layout of the ziplist is as follows:\n * <zlbytes><zltail><zllen><entry><entry><zlend>\n *\n * <zlbytes> is an unsigned integer to hold the number of bytes that the\n * ziplist occupies. This value needs to be stored to be able to resize the\n * entire structure without the need to traverse it first.\n *\n * <zltail> is the offset to the last entry in the list. This allows a pop\n * operation on the far side of the list without the need for full traversal.\n *\n * <zllen> is the number of entries.When this value is larger than 2**16-2,\n * we need to traverse the entire list to know how many items it holds.\n *\n * <zlend> is a single byte special value, equal to 255, which indicates the\n * end of the list.\n *\n * ZIPLIST ENTRIES:\n * Every entry in the ziplist is prefixed by a header that contains two pieces\n * of information. First, the length of the previous entry is stored to be\n * able to traverse the list from back to front. Second, the encoding with an\n * optional string length of the entry itself is stored.\n *\n * The length of the previous entry is encoded in the following way:\n * If this length is smaller than 254 bytes, it will only consume a single\n * byte that takes the length as value. When the length is greater than or\n * equal to 254, it will consume 5 bytes. The first byte is set to 254 to\n * indicate a larger value is following. The remaining 4 bytes take the\n * length of the previous entry as value.\n *\n * The other header field of the entry itself depends on the contents of the\n * entry. When the entry is a string, the first 2 bits of this header will hold\n * the type of encoding used to store the length of the string, followed by the\n * actual length of the string. When the entry is an integer the first 2 bits\n * are both set to 1. The following 2 bits are used to specify what kind of\n * integer will be stored after this header. An overview of the different\n * types and encodings is as follows:\n *\n * |00pppppp| - 1 byte\n *      String value with length less than or equal to 63 bytes (6 bits).\n * |01pppppp|qqqqqqqq| - 2 bytes\n *      String value with length less than or equal to 16383 bytes (14 bits).\n * |10______|qqqqqqqq|rrrrrrrr|ssssssss|tttttttt| - 5 bytes\n *      String value with length greater than or equal to 16384 bytes.\n * |11000000| - 1 byte\n *      Integer encoded as int16_t (2 bytes).\n * |11010000| - 1 byte\n *      Integer encoded as int32_t (4 bytes).\n * |11100000| - 1 byte\n *      Integer encoded as int64_t (8 bytes).\n * |11110000| - 1 byte\n *      Integer encoded as 24 bit signed (3 bytes).\n * |11111110| - 1 byte\n *      Integer encoded as 8 bit signed (1 byte).\n * |1111xxxx| - (with xxxx between 0000 and 1101) immediate 4 bit integer.\n *      Unsigned integer from 0 to 12. The encoded value is actually from\n *      1 to 13 because 0000 and 1111 can not be used, so 1 should be\n *      subtracted from the encoded 4 bit value to obtain the right value.\n * |11111111| - End of ziplist.\n *\n * All the integers are represented in little endian byte order.\n *\n * ----------------------------------------------------------------------------\n *\n * Copyright (c) 2009-2012, Pieter Noordhuis <pcnoordhuis at gmail dot com>\n * Copyright (c) 2009-2012, Salvatore Sanfilippo <antirez at gmail dot com>\n * All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions are met:\n *\n *   * Redistributions of source code must retain the above copyright notice,\n *     this list of conditions and the following disclaimer.\n *   * Redistributions in binary form must reproduce the above copyright\n *     notice, this list of conditions and the following disclaimer in the\n *     documentation and/or other materials provided with the distribution.\n *   * Neither the name of Redis nor the names of its contributors may be used\n *     to endorse or promote products derived from this software without\n *     specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\"\n * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\n * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE\n * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR\n * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF\n * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS\n * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN\n * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)\n * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE\n * POSSIBILITY OF SUCH DAMAGE.\n */\n\n#include <stdio.h>\n#include <stdlib.h>\n#include <string.h>\n#include <stdint.h>\n#include <limits.h>\n#include \"zmalloc.h\"\n#include \"util.h\"\n#include \"ziplist.h\"\n#include \"endianconv.h\"\n#include \"redisassert.h\"\n\n#define ZIP_END 255\n#define ZIP_BIGLEN 254\n\n/* Different encoding/length possibilities */\n#define ZIP_STR_MASK 0xc0\n#define ZIP_INT_MASK 0x30\n#define ZIP_STR_06B (0 << 6)\n#define ZIP_STR_14B (1 << 6)\n#define ZIP_STR_32B (2 << 6)\n#define ZIP_INT_16B (0xc0 | 0<<4)\n#define ZIP_INT_32B (0xc0 | 1<<4)\n#define ZIP_INT_64B (0xc0 | 2<<4)\n#define ZIP_INT_24B (0xc0 | 3<<4)\n#define ZIP_INT_8B 0xfe\n/* 4 bit integer immediate encoding */\n#define ZIP_INT_IMM_MASK 0x0f\n#define ZIP_INT_IMM_MIN 0xf1    /* 11110001 */\n#define ZIP_INT_IMM_MAX 0xfd    /* 11111101 */\n#define ZIP_INT_IMM_VAL(v) (v & ZIP_INT_IMM_MASK)\n\n#define INT24_MAX 0x7fffff\n#define INT24_MIN (-INT24_MAX - 1)\n\n/* Macro to determine type */\n#define ZIP_IS_STR(enc) (((enc) & ZIP_STR_MASK) < ZIP_STR_MASK)\n\n/* Utility macros */\n#define ZIPLIST_BYTES(zl)       (*((uint32_t*)(zl)))\n#define ZIPLIST_TAIL_OFFSET(zl) (*((uint32_t*)((zl)+sizeof(uint32_t))))\n#define ZIPLIST_LENGTH(zl)      (*((uint16_t*)((zl)+sizeof(uint32_t)*2)))\n#define ZIPLIST_HEADER_SIZE     (sizeof(uint32_t)*2+sizeof(uint16_t))\n#define ZIPLIST_END_SIZE        (sizeof(uint8_t))\n#define ZIPLIST_ENTRY_HEAD(zl)  ((zl)+ZIPLIST_HEADER_SIZE)\n#define ZIPLIST_ENTRY_TAIL(zl)  ((zl)+intrev32ifbe(ZIPLIST_TAIL_OFFSET(zl)))\n#define ZIPLIST_ENTRY_END(zl)   ((zl)+intrev32ifbe(ZIPLIST_BYTES(zl))-1)\n\n/* We know a positive increment can only be 1 because entries can only be\n * pushed one at a time. */\n#define ZIPLIST_INCR_LENGTH(zl,incr) { \\\n    if (ZIPLIST_LENGTH(zl) < UINT16_MAX) \\\n        ZIPLIST_LENGTH(zl) = intrev16ifbe(intrev16ifbe(ZIPLIST_LENGTH(zl))+incr); \\\n}\n\ntypedef struct zlentry {\n    unsigned int prevrawlensize, prevrawlen;\n    unsigned int lensize, len;\n    unsigned int headersize;\n    unsigned char encoding;\n    unsigned char *p;\n} zlentry;\n\n#define ZIPLIST_ENTRY_ZERO(zle) { \\\n    (zle)->prevrawlensize = (zle)->prevrawlen = 0; \\\n    (zle)->lensize = (zle)->len = (zle)->headersize = 0; \\\n    (zle)->encoding = 0; \\\n    (zle)->p = NULL; \\\n}\n\n/* Extract the encoding from the byte pointed by 'ptr' and set it into\n * 'encoding'. */\n#define ZIP_ENTRY_ENCODING(ptr, encoding) do {  \\\n    (encoding) = (ptr[0]); \\\n    if ((encoding) < ZIP_STR_MASK) (encoding) &= ZIP_STR_MASK; \\\n} while(0)\n\nvoid ziplistRepr(unsigned char *zl);\n\n/* Return bytes needed to store integer encoded by 'encoding' */\nstatic unsigned int zipIntSize(unsigned char encoding) {\n    switch(encoding) {\n    case ZIP_INT_8B:  return 1;\n    case ZIP_INT_16B: return 2;\n    case ZIP_INT_24B: return 3;\n    case ZIP_INT_32B: return 4;\n    case ZIP_INT_64B: return 8;\n    default: return 0; /* 4 bit immediate */\n    }\n    assert(NULL);\n    return 0;\n}\n\n/* Encode the length 'rawlen' writing it in 'p'. If p is NULL it just returns\n * the amount of bytes required to encode such a length. */\nstatic unsigned int zipEncodeLength(unsigned char *p, unsigned char encoding, unsigned int rawlen) {\n    unsigned char len = 1, buf[5];\n\n    if (ZIP_IS_STR(encoding)) {\n        /* Although encoding is given it may not be set for strings,\n         * so we determine it here using the raw length. */\n        if (rawlen <= 0x3f) {\n            if (!p) return len;\n            buf[0] = ZIP_STR_06B | rawlen;\n        } else if (rawlen <= 0x3fff) {\n            len += 1;\n            if (!p) return len;\n            buf[0] = ZIP_STR_14B | ((rawlen >> 8) & 0x3f);\n            buf[1] = rawlen & 0xff;\n        } else {\n            len += 4;\n            if (!p) return len;\n            buf[0] = ZIP_STR_32B;\n            buf[1] = (rawlen >> 24) & 0xff;\n            buf[2] = (rawlen >> 16) & 0xff;\n            buf[3] = (rawlen >> 8) & 0xff;\n            buf[4] = rawlen & 0xff;\n        }\n    } else {\n        /* Implies integer encoding, so length is always 1. */\n        if (!p) return len;\n        buf[0] = encoding;\n    }\n\n    /* Store this length at p */\n    memcpy(p,buf,len);\n    return len;\n}\n\n/* Decode the length encoded in 'ptr'. The 'encoding' variable will hold the\n * entries encoding, the 'lensize' variable will hold the number of bytes\n * required to encode the entries length, and the 'len' variable will hold the\n * entries length. */\n#define ZIP_DECODE_LENGTH(ptr, encoding, lensize, len) do {                    \\\n    ZIP_ENTRY_ENCODING((ptr), (encoding));                                     \\\n    if ((encoding) < ZIP_STR_MASK) {                                           \\\n        if ((encoding) == ZIP_STR_06B) {                                       \\\n            (lensize) = 1;                                                     \\\n            (len) = (ptr)[0] & 0x3f;                                           \\\n        } else if ((encoding) == ZIP_STR_14B) {                                \\\n            (lensize) = 2;                                                     \\\n            (len) = (((ptr)[0] & 0x3f) << 8) | (ptr)[1];                       \\\n        } else if (encoding == ZIP_STR_32B) {                                  \\\n            (lensize) = 5;                                                     \\\n            (len) = ((ptr)[1] << 24) |                                         \\\n                    ((ptr)[2] << 16) |                                         \\\n                    ((ptr)[3] <<  8) |                                         \\\n                    ((ptr)[4]);                                                \\\n        } else {                                                               \\\n            assert(NULL);                                                      \\\n        }                                                                      \\\n    } else {                                                                   \\\n        (lensize) = 1;                                                         \\\n        (len) = zipIntSize(encoding);                                          \\\n    }                                                                          \\\n} while(0);\n\n/* Encode the length of the previous entry and write it to \"p\". Return the\n * number of bytes needed to encode this length if \"p\" is NULL. */\nstatic unsigned int zipPrevEncodeLength(unsigned char *p, unsigned int len) {\n    if (p == NULL) {\n        return (len < ZIP_BIGLEN) ? 1 : sizeof(len)+1;\n    } else {\n        if (len < ZIP_BIGLEN) {\n            p[0] = len;\n            return 1;\n        } else {\n            p[0] = ZIP_BIGLEN;\n            memcpy(p+1,&len,sizeof(len));\n            memrev32ifbe(p+1);\n            return 1+sizeof(len);\n        }\n    }\n}\n\n/* Encode the length of the previous entry and write it to \"p\". This only\n * uses the larger encoding (required in __ziplistCascadeUpdate). */\nstatic void zipPrevEncodeLengthForceLarge(unsigned char *p, unsigned int len) {\n    if (p == NULL) return;\n    p[0] = ZIP_BIGLEN;\n    memcpy(p+1,&len,sizeof(len));\n    memrev32ifbe(p+1);\n}\n\n/* Decode the number of bytes required to store the length of the previous\n * element, from the perspective of the entry pointed to by 'ptr'. */\n#define ZIP_DECODE_PREVLENSIZE(ptr, prevlensize) do {                          \\\n    if ((ptr)[0] < ZIP_BIGLEN) {                                               \\\n        (prevlensize) = 1;                                                     \\\n    } else {                                                                   \\\n        (prevlensize) = 5;                                                     \\\n    }                                                                          \\\n} while(0);\n\n/* Decode the length of the previous element, from the perspective of the entry\n * pointed to by 'ptr'. */\n#define ZIP_DECODE_PREVLEN(ptr, prevlensize, prevlen) do {                     \\\n    ZIP_DECODE_PREVLENSIZE(ptr, prevlensize);                                  \\\n    if ((prevlensize) == 1) {                                                  \\\n        (prevlen) = (ptr)[0];                                                  \\\n    } else if ((prevlensize) == 5) {                                           \\\n        assert(sizeof((prevlensize)) == 4);                                    \\\n        memcpy(&(prevlen), ((char*)(ptr)) + 1, 4);                             \\\n        memrev32ifbe(&prevlen);                                                \\\n    }                                                                          \\\n} while(0);\n\n/* Return the difference in number of bytes needed to store the length of the\n * previous element 'len', in the entry pointed to by 'p'. */\nstatic int zipPrevLenByteDiff(unsigned char *p, unsigned int len) {\n    unsigned int prevlensize;\n    ZIP_DECODE_PREVLENSIZE(p, prevlensize);\n    return zipPrevEncodeLength(NULL, len) - prevlensize;\n}\n\n/* Return the total number of bytes used by the entry pointed to by 'p'. */\nstatic unsigned int zipRawEntryLength(unsigned char *p) {\n    unsigned int prevlensize, encoding, lensize, len;\n    ZIP_DECODE_PREVLENSIZE(p, prevlensize);\n    ZIP_DECODE_LENGTH(p + prevlensize, encoding, lensize, len);\n    return prevlensize + lensize + len;\n}\n\n/* Check if string pointed to by 'entry' can be encoded as an integer.\n * Stores the integer value in 'v' and its encoding in 'encoding'. */\nstatic int zipTryEncoding(unsigned char *entry, unsigned int entrylen, long long *v, unsigned char *encoding) {\n    long long value;\n\n    if (entrylen >= 32 || entrylen == 0) return 0;\n    if (string2ll((char*)entry,entrylen,&value)) {\n        /* Great, the string can be encoded. Check what's the smallest\n         * of our encoding types that can hold this value. */\n        if (value >= 0 && value <= 12) {\n            *encoding = ZIP_INT_IMM_MIN+value;\n        } else if (value >= INT8_MIN && value <= INT8_MAX) {\n            *encoding = ZIP_INT_8B;\n        } else if (value >= INT16_MIN && value <= INT16_MAX) {\n            *encoding = ZIP_INT_16B;\n        } else if (value >= INT24_MIN && value <= INT24_MAX) {\n            *encoding = ZIP_INT_24B;\n        } else if (value >= INT32_MIN && value <= INT32_MAX) {\n            *encoding = ZIP_INT_32B;\n        } else {\n            *encoding = ZIP_INT_64B;\n        }\n        *v = value;\n        return 1;\n    }\n    return 0;\n}\n\n/* Store integer 'value' at 'p', encoded as 'encoding' */\nstatic void zipSaveInteger(unsigned char *p, int64_t value, unsigned char encoding) {\n    int16_t i16;\n    int32_t i32;\n    int64_t i64;\n    if (encoding == ZIP_INT_8B) {\n        ((int8_t*)p)[0] = (int8_t)value;\n    } else if (encoding == ZIP_INT_16B) {\n        i16 = value;\n        memcpy(p,&i16,sizeof(i16));\n        memrev16ifbe(p);\n    } else if (encoding == ZIP_INT_24B) {\n        i32 = value<<8;\n        memrev32ifbe(&i32);\n        memcpy(p,((uint8_t*)&i32)+1,sizeof(i32)-sizeof(uint8_t));\n    } else if (encoding == ZIP_INT_32B) {\n        i32 = value;\n        memcpy(p,&i32,sizeof(i32));\n        memrev32ifbe(p);\n    } else if (encoding == ZIP_INT_64B) {\n        i64 = value;\n        memcpy(p,&i64,sizeof(i64));\n        memrev64ifbe(p);\n    } else if (encoding >= ZIP_INT_IMM_MIN && encoding <= ZIP_INT_IMM_MAX) {\n        /* Nothing to do, the value is stored in the encoding itself. */\n    } else {\n        assert(NULL);\n    }\n}\n\n/* Read integer encoded as 'encoding' from 'p' */\nstatic int64_t zipLoadInteger(unsigned char *p, unsigned char encoding) {\n    int16_t i16;\n    int32_t i32;\n    int64_t i64, ret = 0;\n    if (encoding == ZIP_INT_8B) {\n        ret = ((int8_t*)p)[0];\n    } else if (encoding == ZIP_INT_16B) {\n        memcpy(&i16,p,sizeof(i16));\n        memrev16ifbe(&i16);\n        ret = i16;\n    } else if (encoding == ZIP_INT_32B) {\n        memcpy(&i32,p,sizeof(i32));\n        memrev32ifbe(&i32);\n        ret = i32;\n    } else if (encoding == ZIP_INT_24B) {\n        i32 = 0;\n        memcpy(((uint8_t*)&i32)+1,p,sizeof(i32)-sizeof(uint8_t));\n        memrev32ifbe(&i32);\n        ret = i32>>8;\n    } else if (encoding == ZIP_INT_64B) {\n        memcpy(&i64,p,sizeof(i64));\n        memrev64ifbe(&i64);\n        ret = i64;\n    } else if (encoding >= ZIP_INT_IMM_MIN && encoding <= ZIP_INT_IMM_MAX) {\n        ret = (encoding & ZIP_INT_IMM_MASK)-1;\n    } else {\n        assert(NULL);\n    }\n    return ret;\n}\n\n/* Return a struct with all information about an entry. */\nstatic void zipEntry(unsigned char *p, zlentry *e) {\n\n    ZIP_DECODE_PREVLEN(p, e->prevrawlensize, e->prevrawlen);\n    ZIP_DECODE_LENGTH(p + e->prevrawlensize, e->encoding, e->lensize, e->len);\n    e->headersize = e->prevrawlensize + e->lensize;\n    e->p = p;\n}\n\n/* Create a new empty ziplist. */\nunsigned char *ziplistNew(void) {\n    unsigned int bytes = ZIPLIST_HEADER_SIZE+1;\n    unsigned char *zl = zmalloc(bytes);\n    ZIPLIST_BYTES(zl) = intrev32ifbe(bytes);\n    ZIPLIST_TAIL_OFFSET(zl) = intrev32ifbe(ZIPLIST_HEADER_SIZE);\n    ZIPLIST_LENGTH(zl) = 0;\n    zl[bytes-1] = ZIP_END;\n    return zl;\n}\n\n/* Resize the ziplist. */\nstatic unsigned char *ziplistResize(unsigned char *zl, unsigned int len) {\n    zl = zrealloc(zl,len);\n    ZIPLIST_BYTES(zl) = intrev32ifbe(len);\n    zl[len-1] = ZIP_END;\n    return zl;\n}\n\n/* When an entry is inserted, we need to set the prevlen field of the next\n * entry to equal the length of the inserted entry. It can occur that this\n * length cannot be encoded in 1 byte and the next entry needs to be grow\n * a bit larger to hold the 5-byte encoded prevlen. This can be done for free,\n * because this only happens when an entry is already being inserted (which\n * causes a realloc and memmove). However, encoding the prevlen may require\n * that this entry is grown as well. This effect may cascade throughout\n * the ziplist when there are consecutive entries with a size close to\n * ZIP_BIGLEN, so we need to check that the prevlen can be encoded in every\n * consecutive entry.\n *\n * Note that this effect can also happen in reverse, where the bytes required\n * to encode the prevlen field can shrink. This effect is deliberately ignored,\n * because it can cause a \"flapping\" effect where a chain prevlen fields is\n * first grown and then shrunk again after consecutive inserts. Rather, the\n * field is allowed to stay larger than necessary, because a large prevlen\n * field implies the ziplist is holding large entries anyway.\n *\n * The pointer \"p\" points to the first entry that does NOT need to be\n * updated, i.e. consecutive fields MAY need an update. */\nstatic unsigned char *__ziplistCascadeUpdate(unsigned char *zl, unsigned char *p) {\n    size_t curlen = intrev32ifbe(ZIPLIST_BYTES(zl)), rawlen, rawlensize;\n    size_t offset, noffset, extra;\n    unsigned char *np;\n    zlentry cur, next;\n\n    while (p[0] != ZIP_END) {\n        zipEntry(p, &cur);\n        rawlen = cur.headersize + cur.len;\n        rawlensize = zipPrevEncodeLength(NULL,rawlen);\n\n        /* Abort if there is no next entry. */\n        if (p[rawlen] == ZIP_END) break;\n        zipEntry(p+rawlen, &next);\n\n        /* Abort when \"prevlen\" has not changed. */\n        if (next.prevrawlen == rawlen) break;\n\n        if (next.prevrawlensize < rawlensize) {\n            /* The \"prevlen\" field of \"next\" needs more bytes to hold\n             * the raw length of \"cur\". */\n            offset = p-zl;\n            extra = rawlensize-next.prevrawlensize;\n            zl = ziplistResize(zl,curlen+extra);\n            p = zl+offset;\n\n            /* Current pointer and offset for next element. */\n            np = p+rawlen;\n            noffset = np-zl;\n\n            /* Update tail offset when next element is not the tail element. */\n            if ((zl+intrev32ifbe(ZIPLIST_TAIL_OFFSET(zl))) != np) {\n                ZIPLIST_TAIL_OFFSET(zl) =\n                    intrev32ifbe(intrev32ifbe(ZIPLIST_TAIL_OFFSET(zl))+extra);\n            }\n\n            /* Move the tail to the back. */\n            memmove(np+rawlensize,\n                np+next.prevrawlensize,\n                curlen-noffset-next.prevrawlensize-1);\n            zipPrevEncodeLength(np,rawlen);\n\n            /* Advance the cursor */\n            p += rawlen;\n            curlen += extra;\n        } else {\n            if (next.prevrawlensize > rawlensize) {\n                /* This would result in shrinking, which we want to avoid.\n                 * So, set \"rawlen\" in the available bytes. */\n                zipPrevEncodeLengthForceLarge(p+rawlen,rawlen);\n            } else {\n                zipPrevEncodeLength(p+rawlen,rawlen);\n            }\n\n            /* Stop here, as the raw length of \"next\" has not changed. */\n            break;\n        }\n    }\n    return zl;\n}\n\n/* Delete \"num\" entries, starting at \"p\". Returns pointer to the ziplist. */\nstatic unsigned char *__ziplistDelete(unsigned char *zl, unsigned char *p, unsigned int num) {\n    unsigned int i, totlen, deleted = 0;\n    size_t offset;\n    int nextdiff = 0;\n    zlentry first, tail;\n\n    zipEntry(p, &first);\n    for (i = 0; p[0] != ZIP_END && i < num; i++) {\n        p += zipRawEntryLength(p);\n        deleted++;\n    }\n\n    totlen = p-first.p;\n    if (totlen > 0) {\n        if (p[0] != ZIP_END) {\n            /* Storing `prevrawlen` in this entry may increase or decrease the\n             * number of bytes required compare to the current `prevrawlen`.\n             * There always is room to store this, because it was previously\n             * stored by an entry that is now being deleted. */\n            nextdiff = zipPrevLenByteDiff(p,first.prevrawlen);\n            p -= nextdiff;\n            zipPrevEncodeLength(p,first.prevrawlen);\n\n            /* Update offset for tail */\n            ZIPLIST_TAIL_OFFSET(zl) =\n                intrev32ifbe(intrev32ifbe(ZIPLIST_TAIL_OFFSET(zl))-totlen);\n\n            /* When the tail contains more than one entry, we need to take\n             * \"nextdiff\" in account as well. Otherwise, a change in the\n             * size of prevlen doesn't have an effect on the *tail* offset. */\n            zipEntry(p, &tail);\n            if (p[tail.headersize+tail.len] != ZIP_END) {\n                ZIPLIST_TAIL_OFFSET(zl) =\n                   intrev32ifbe(intrev32ifbe(ZIPLIST_TAIL_OFFSET(zl))+nextdiff);\n            }\n\n            /* Move tail to the front of the ziplist */\n            memmove(first.p,p,\n                intrev32ifbe(ZIPLIST_BYTES(zl))-(p-zl)-1);\n        } else {\n            /* The entire tail was deleted. No need to move memory. */\n            ZIPLIST_TAIL_OFFSET(zl) =\n                intrev32ifbe((first.p-zl)-first.prevrawlen);\n        }\n\n        /* Resize and update length */\n        offset = first.p-zl;\n        zl = ziplistResize(zl, intrev32ifbe(ZIPLIST_BYTES(zl))-totlen+nextdiff);\n        ZIPLIST_INCR_LENGTH(zl,-deleted);\n        p = zl+offset;\n\n        /* When nextdiff != 0, the raw length of the next entry has changed, so\n         * we need to cascade the update throughout the ziplist */\n        if (nextdiff != 0)\n            zl = __ziplistCascadeUpdate(zl,p);\n    }\n    return zl;\n}\n\n/* Insert item at \"p\". */\nstatic unsigned char *__ziplistInsert(unsigned char *zl, unsigned char *p, unsigned char *s, unsigned int slen) {\n    size_t curlen = intrev32ifbe(ZIPLIST_BYTES(zl)), reqlen;\n    unsigned int prevlensize, prevlen = 0;\n    size_t offset;\n    int nextdiff = 0;\n    unsigned char encoding = 0;\n    long long value = 123456789; /* initialized to avoid warning. Using a value\n                                    that is easy to see if for some reason\n                                    we use it uninitialized. */\n    zlentry tail;\n\n    /* Find out prevlen for the entry that is inserted. */\n    if (p[0] != ZIP_END) {\n        ZIP_DECODE_PREVLEN(p, prevlensize, prevlen);\n    } else {\n        unsigned char *ptail = ZIPLIST_ENTRY_TAIL(zl);\n        if (ptail[0] != ZIP_END) {\n            prevlen = zipRawEntryLength(ptail);\n        }\n    }\n\n    /* See if the entry can be encoded */\n    if (zipTryEncoding(s,slen,&value,&encoding)) {\n        /* 'encoding' is set to the appropriate integer encoding */\n        reqlen = zipIntSize(encoding);\n    } else {\n        /* 'encoding' is untouched, however zipEncodeLength will use the\n         * string length to figure out how to encode it. */\n        reqlen = slen;\n    }\n    /* We need space for both the length of the previous entry and\n     * the length of the payload. */\n    reqlen += zipPrevEncodeLength(NULL,prevlen);\n    reqlen += zipEncodeLength(NULL,encoding,slen);\n\n    /* When the insert position is not equal to the tail, we need to\n     * make sure that the next entry can hold this entry's length in\n     * its prevlen field. */\n    nextdiff = (p[0] != ZIP_END) ? zipPrevLenByteDiff(p,reqlen) : 0;\n\n    /* Store offset because a realloc may change the address of zl. */\n    offset = p-zl;\n    zl = ziplistResize(zl,curlen+reqlen+nextdiff);\n    p = zl+offset;\n\n    /* Apply memory move when necessary and update tail offset. */\n    if (p[0] != ZIP_END) {\n        /* Subtract one because of the ZIP_END bytes */\n        memmove(p+reqlen,p-nextdiff,curlen-offset-1+nextdiff);\n\n        /* Encode this entry's raw length in the next entry. */\n        zipPrevEncodeLength(p+reqlen,reqlen);\n\n        /* Update offset for tail */\n        ZIPLIST_TAIL_OFFSET(zl) =\n            intrev32ifbe(intrev32ifbe(ZIPLIST_TAIL_OFFSET(zl))+reqlen);\n\n        /* When the tail contains more than one entry, we need to take\n         * \"nextdiff\" in account as well. Otherwise, a change in the\n         * size of prevlen doesn't have an effect on the *tail* offset. */\n        zipEntry(p+reqlen, &tail);\n        if (p[reqlen+tail.headersize+tail.len] != ZIP_END) {\n            ZIPLIST_TAIL_OFFSET(zl) =\n                intrev32ifbe(intrev32ifbe(ZIPLIST_TAIL_OFFSET(zl))+nextdiff);\n        }\n    } else {\n        /* This element will be the new tail. */\n        ZIPLIST_TAIL_OFFSET(zl) = intrev32ifbe(p-zl);\n    }\n\n    /* When nextdiff != 0, the raw length of the next entry has changed, so\n     * we need to cascade the update throughout the ziplist */\n    if (nextdiff != 0) {\n        offset = p-zl;\n        zl = __ziplistCascadeUpdate(zl,p+reqlen);\n        p = zl+offset;\n    }\n\n    /* Write the entry */\n    p += zipPrevEncodeLength(p,prevlen);\n    p += zipEncodeLength(p,encoding,slen);\n    if (ZIP_IS_STR(encoding)) {\n        memcpy(p,s,slen);\n    } else {\n        zipSaveInteger(p,value,encoding);\n    }\n    ZIPLIST_INCR_LENGTH(zl,1);\n    return zl;\n}\n\n/* Merge ziplists 'first' and 'second' by appending 'second' to 'first'.\n *\n * NOTE: The larger ziplist is reallocated to contain the new merged ziplist.\n * Either 'first' or 'second' can be used for the result.  The parameter not\n * used will be free'd and set to NULL.\n *\n * After calling this function, the input parameters are no longer valid since\n * they are changed and free'd in-place.\n *\n * The result ziplist is the contents of 'first' followed by 'second'.\n *\n * On failure: returns NULL if the merge is impossible.\n * On success: returns the merged ziplist (which is expanded version of either\n * 'first' or 'second', also frees the other unused input ziplist, and sets the\n * input ziplist argument equal to newly reallocated ziplist return value. */\nunsigned char *ziplistMerge(unsigned char **first, unsigned char **second) {\n    /* If any params are null, we can't merge, so NULL. */\n    if (first == NULL || *first == NULL || second == NULL || *second == NULL)\n        return NULL;\n\n    /* Can't merge same list into itself. */\n    if (*first == *second)\n        return NULL;\n\n    size_t first_bytes = intrev32ifbe(ZIPLIST_BYTES(*first));\n    size_t first_len = intrev16ifbe(ZIPLIST_LENGTH(*first));\n\n    size_t second_bytes = intrev32ifbe(ZIPLIST_BYTES(*second));\n    size_t second_len = intrev16ifbe(ZIPLIST_LENGTH(*second));\n\n    int append;\n    unsigned char *source, *target;\n    size_t target_bytes, source_bytes;\n    /* Pick the largest ziplist so we can resize easily in-place.\n     * We must also track if we are now appending or prepending to\n     * the target ziplist. */\n    if (first_len >= second_len) {\n        /* retain first, append second to first. */\n        target = *first;\n        target_bytes = first_bytes;\n        source = *second;\n        source_bytes = second_bytes;\n        append = 1;\n    } else {\n        /* else, retain second, prepend first to second. */\n        target = *second;\n        target_bytes = second_bytes;\n        source = *first;\n        source_bytes = first_bytes;\n        append = 0;\n    }\n\n    /* Calculate final bytes (subtract one pair of metadata) */\n    size_t zlbytes = first_bytes + second_bytes -\n                     ZIPLIST_HEADER_SIZE - ZIPLIST_END_SIZE;\n    size_t zllength = first_len + second_len;\n\n    /* Combined zl length should be limited within UINT16_MAX */\n    zllength = zllength < UINT16_MAX ? zllength : UINT16_MAX;\n\n    /* Save offset positions before we start ripping memory apart. */\n    size_t first_offset = intrev32ifbe(ZIPLIST_TAIL_OFFSET(*first));\n    size_t second_offset = intrev32ifbe(ZIPLIST_TAIL_OFFSET(*second));\n\n    /* Extend target to new zlbytes then append or prepend source. */\n    target = zrealloc(target, zlbytes);\n    if (append) {\n        /* append == appending to target */\n        /* Copy source after target (copying over original [END]):\n         *   [TARGET - END, SOURCE - HEADER] */\n        memcpy(target + target_bytes - ZIPLIST_END_SIZE,\n               source + ZIPLIST_HEADER_SIZE,\n               source_bytes - ZIPLIST_HEADER_SIZE);\n    } else {\n        /* !append == prepending to target */\n        /* Move target *contents* exactly size of (source - [END]),\n         * then copy source into vacataed space (source - [END]):\n         *   [SOURCE - END, TARGET - HEADER] */\n        memmove(target + source_bytes - ZIPLIST_END_SIZE,\n                target + ZIPLIST_HEADER_SIZE,\n                target_bytes - ZIPLIST_HEADER_SIZE);\n        memcpy(target, source, source_bytes - ZIPLIST_END_SIZE);\n    }\n\n    /* Update header metadata. */\n    ZIPLIST_BYTES(target) = intrev32ifbe(zlbytes);\n    ZIPLIST_LENGTH(target) = intrev16ifbe(zllength);\n    /* New tail offset is:\n     *   + N bytes of first ziplist\n     *   - 1 byte for [END] of first ziplist\n     *   + M bytes for the offset of the original tail of the second ziplist\n     *   - J bytes for HEADER because second_offset keeps no header. */\n    ZIPLIST_TAIL_OFFSET(target) = intrev32ifbe(\n                                   (first_bytes - ZIPLIST_END_SIZE) +\n                                   (second_offset - ZIPLIST_HEADER_SIZE));\n\n    /* __ziplistCascadeUpdate just fixes the prev length values until it finds a\n     * correct prev length value (then it assumes the rest of the list is okay).\n     * We tell CascadeUpdate to start at the first ziplist's tail element to fix\n     * the merge seam. */\n    target = __ziplistCascadeUpdate(target, target+first_offset);\n\n    /* Now free and NULL out what we didn't realloc */\n    if (append) {\n        zfree(*second);\n        *second = NULL;\n        *first = target;\n    } else {\n        zfree(*first);\n        *first = NULL;\n        *second = target;\n    }\n    return target;\n}\n\nunsigned char *ziplistPush(unsigned char *zl, unsigned char *s, unsigned int slen, int where) {\n    unsigned char *p;\n    p = (where == ZIPLIST_HEAD) ? ZIPLIST_ENTRY_HEAD(zl) : ZIPLIST_ENTRY_END(zl);\n    return __ziplistInsert(zl,p,s,slen);\n}\n\n/* Returns an offset to use for iterating with ziplistNext. When the given\n * index is negative, the list is traversed back to front. When the list\n * doesn't contain an element at the provided index, NULL is returned. */\nunsigned char *ziplistIndex(unsigned char *zl, int index) {\n    unsigned char *p;\n    unsigned int prevlensize, prevlen = 0;\n    if (index < 0) {\n        index = (-index)-1;\n        p = ZIPLIST_ENTRY_TAIL(zl);\n        if (p[0] != ZIP_END) {\n            ZIP_DECODE_PREVLEN(p, prevlensize, prevlen);\n            while (prevlen > 0 && index--) {\n                p -= prevlen;\n                ZIP_DECODE_PREVLEN(p, prevlensize, prevlen);\n            }\n        }\n    } else {\n        p = ZIPLIST_ENTRY_HEAD(zl);\n        while (p[0] != ZIP_END && index--) {\n            p += zipRawEntryLength(p);\n        }\n    }\n    return (p[0] == ZIP_END || index > 0) ? NULL : p;\n}\n\n/* Return pointer to next entry in ziplist.\n *\n * zl is the pointer to the ziplist\n * p is the pointer to the current element\n *\n * The element after 'p' is returned, otherwise NULL if we are at the end. */\nunsigned char *ziplistNext(unsigned char *zl, unsigned char *p) {\n    ((void) zl);\n\n    /* \"p\" could be equal to ZIP_END, caused by ziplistDelete,\n     * and we should return NULL. Otherwise, we should return NULL\n     * when the *next* element is ZIP_END (there is no next entry). */\n    if (p[0] == ZIP_END) {\n        return NULL;\n    }\n\n    p += zipRawEntryLength(p);\n    if (p[0] == ZIP_END) {\n        return NULL;\n    }\n\n    return p;\n}\n\n/* Return pointer to previous entry in ziplist. */\nunsigned char *ziplistPrev(unsigned char *zl, unsigned char *p) {\n    unsigned int prevlensize, prevlen = 0;\n\n    /* Iterating backwards from ZIP_END should return the tail. When \"p\" is\n     * equal to the first element of the list, we're already at the head,\n     * and should return NULL. */\n    if (p[0] == ZIP_END) {\n        p = ZIPLIST_ENTRY_TAIL(zl);\n        return (p[0] == ZIP_END) ? NULL : p;\n    } else if (p == ZIPLIST_ENTRY_HEAD(zl)) {\n        return NULL;\n    } else {\n        ZIP_DECODE_PREVLEN(p, prevlensize, prevlen);\n        assert(prevlen > 0);\n        return p-prevlen;\n    }\n}\n\n/* Get entry pointed to by 'p' and store in either '*sstr' or 'sval' depending\n * on the encoding of the entry. '*sstr' is always set to NULL to be able\n * to find out whether the string pointer or the integer value was set.\n * Return 0 if 'p' points to the end of the ziplist, 1 otherwise. */\nunsigned int ziplistGet(unsigned char *p, unsigned char **sstr, unsigned int *slen, long long *sval) {\n    zlentry entry;\n    if (p == NULL || p[0] == ZIP_END) return 0;\n    if (sstr) *sstr = NULL;\n\n    zipEntry(p, &entry);\n    if (ZIP_IS_STR(entry.encoding)) {\n        if (sstr) {\n            *slen = entry.len;\n            *sstr = p+entry.headersize;\n        }\n    } else {\n        if (sval) {\n            *sval = zipLoadInteger(p+entry.headersize,entry.encoding);\n        }\n    }\n    return 1;\n}\n\n/* Insert an entry at \"p\". */\nunsigned char *ziplistInsert(unsigned char *zl, unsigned char *p, unsigned char *s, unsigned int slen) {\n    return __ziplistInsert(zl,p,s,slen);\n}\n\n/* Delete a single entry from the ziplist, pointed to by *p.\n * Also update *p in place, to be able to iterate over the\n * ziplist, while deleting entries. */\nunsigned char *ziplistDelete(unsigned char *zl, unsigned char **p) {\n    size_t offset = *p-zl;\n    zl = __ziplistDelete(zl,*p,1);\n\n    /* Store pointer to current element in p, because ziplistDelete will\n     * do a realloc which might result in a different \"zl\"-pointer.\n     * When the delete direction is back to front, we might delete the last\n     * entry and end up with \"p\" pointing to ZIP_END, so check this. */\n    *p = zl+offset;\n    return zl;\n}\n\n/* Delete a range of entries from the ziplist. */\nunsigned char *ziplistDeleteRange(unsigned char *zl, int index, unsigned int num) {\n    unsigned char *p = ziplistIndex(zl,index);\n    return (p == NULL) ? zl : __ziplistDelete(zl,p,num);\n}\n\n/* Compare entry pointer to by 'p' with 'sstr' of length 'slen'. */\n/* Return 1 if equal. */\nunsigned int ziplistCompare(unsigned char *p, unsigned char *sstr, unsigned int slen) {\n    zlentry entry;\n    unsigned char sencoding;\n    long long zval, sval;\n    if (p[0] == ZIP_END) return 0;\n\n    zipEntry(p, &entry);\n    if (ZIP_IS_STR(entry.encoding)) {\n        /* Raw compare */\n        if (entry.len == slen) {\n            return memcmp(p+entry.headersize,sstr,slen) == 0;\n        } else {\n            return 0;\n        }\n    } else {\n        /* Try to compare encoded values. Don't compare encoding because\n         * different implementations may encoded integers differently. */\n        if (zipTryEncoding(sstr,slen,&sval,&sencoding)) {\n          zval = zipLoadInteger(p+entry.headersize,entry.encoding);\n          return zval == sval;\n        }\n    }\n    return 0;\n}\n\n/* Find pointer to the entry equal to the specified entry. Skip 'skip' entries\n * between every comparison. Returns NULL when the field could not be found. */\nunsigned char *ziplistFind(unsigned char *p, unsigned char *vstr, unsigned int vlen, unsigned int skip) {\n    int skipcnt = 0;\n    unsigned char vencoding = 0;\n    long long vll = 0;\n\n    while (p[0] != ZIP_END) {\n        unsigned int prevlensize, encoding, lensize, len;\n        unsigned char *q;\n\n        ZIP_DECODE_PREVLENSIZE(p, prevlensize);\n        ZIP_DECODE_LENGTH(p + prevlensize, encoding, lensize, len);\n        q = p + prevlensize + lensize;\n\n        if (skipcnt == 0) {\n            /* Compare current entry with specified entry */\n            if (ZIP_IS_STR(encoding)) {\n                if (len == vlen && memcmp(q, vstr, vlen) == 0) {\n                    return p;\n                }\n            } else {\n                /* Find out if the searched field can be encoded. Note that\n                 * we do it only the first time, once done vencoding is set\n                 * to non-zero and vll is set to the integer value. */\n                if (vencoding == 0) {\n                    if (!zipTryEncoding(vstr, vlen, &vll, &vencoding)) {\n                        /* If the entry can't be encoded we set it to\n                         * UCHAR_MAX so that we don't retry again the next\n                         * time. */\n                        vencoding = UCHAR_MAX;\n                    }\n                    /* Must be non-zero by now */\n                    assert(vencoding);\n                }\n\n                /* Compare current entry with specified entry, do it only\n                 * if vencoding != UCHAR_MAX because if there is no encoding\n                 * possible for the field it can't be a valid integer. */\n                if (vencoding != UCHAR_MAX) {\n                    long long ll = zipLoadInteger(q, encoding);\n                    if (ll == vll) {\n                        return p;\n                    }\n                }\n            }\n\n            /* Reset skip count */\n            skipcnt = skip;\n        } else {\n            /* Skip entry */\n            skipcnt--;\n        }\n\n        /* Move to next entry */\n        p = q + len;\n    }\n\n    return NULL;\n}\n\n/* Return length of ziplist. */\nunsigned int ziplistLen(unsigned char *zl) {\n    unsigned int len = 0;\n    if (intrev16ifbe(ZIPLIST_LENGTH(zl)) < UINT16_MAX) {\n        len = intrev16ifbe(ZIPLIST_LENGTH(zl));\n    } else {\n        unsigned char *p = zl+ZIPLIST_HEADER_SIZE;\n        while (*p != ZIP_END) {\n            p += zipRawEntryLength(p);\n            len++;\n        }\n\n        /* Re-store length if small enough */\n        if (len < UINT16_MAX) ZIPLIST_LENGTH(zl) = intrev16ifbe(len);\n    }\n    return len;\n}\n\n/* Return ziplist blob size in bytes. */\nsize_t ziplistBlobLen(unsigned char *zl) {\n    return intrev32ifbe(ZIPLIST_BYTES(zl));\n}\n\nvoid ziplistRepr(unsigned char *zl) {\n    unsigned char *p;\n    int index = 0;\n    zlentry entry;\n\n    printf(\n        \"{total bytes %d} \"\n        \"{length %u}\\n\"\n        \"{tail offset %u}\\n\",\n        intrev32ifbe(ZIPLIST_BYTES(zl)),\n        intrev16ifbe(ZIPLIST_LENGTH(zl)),\n        intrev32ifbe(ZIPLIST_TAIL_OFFSET(zl)));\n    p = ZIPLIST_ENTRY_HEAD(zl);\n    while(*p != ZIP_END) {\n        zipEntry(p, &entry);\n        printf(\n            \"{\"\n                \"addr 0x%08lx, \"\n                \"index %2d, \"\n                \"offset %5ld, \"\n                \"rl: %5u, \"\n                \"hs %2u, \"\n                \"pl: %5u, \"\n                \"pls: %2u, \"\n                \"payload %5u\"\n            \"} \",\n            (long unsigned)p,\n            index,\n            (unsigned long) (p-zl),\n            entry.headersize+entry.len,\n            entry.headersize,\n            entry.prevrawlen,\n            entry.prevrawlensize,\n            entry.len);\n        p += entry.headersize;\n        if (ZIP_IS_STR(entry.encoding)) {\n            if (entry.len > 40) {\n                if (fwrite(p,40,1,stdout) == 0) perror(\"fwrite\");\n                printf(\"...\");\n            } else {\n                if (entry.len &&\n                    fwrite(p,entry.len,1,stdout) == 0) perror(\"fwrite\");\n            }\n        } else {\n            printf(\"%lld\", (long long) zipLoadInteger(p,entry.encoding));\n        }\n        printf(\"\\n\");\n        p += entry.len;\n        index++;\n    }\n    printf(\"{end}\\n\\n\");\n}\n\n#ifdef REDIS_TEST\n#include <sys/time.h>\n#include \"adlist.h\"\n#include \"sds.h\"\n\n#define debug(f, ...) { if (DEBUG) printf(f, __VA_ARGS__); }\n\nstatic unsigned char *createList() {\n    unsigned char *zl = ziplistNew();\n    zl = ziplistPush(zl, (unsigned char*)\"foo\", 3, ZIPLIST_TAIL);\n    zl = ziplistPush(zl, (unsigned char*)\"quux\", 4, ZIPLIST_TAIL);\n    zl = ziplistPush(zl, (unsigned char*)\"hello\", 5, ZIPLIST_HEAD);\n    zl = ziplistPush(zl, (unsigned char*)\"1024\", 4, ZIPLIST_TAIL);\n    return zl;\n}\n\nstatic unsigned char *createIntList() {\n    unsigned char *zl = ziplistNew();\n    char buf[32];\n\n    sprintf(buf, \"100\");\n    zl = ziplistPush(zl, (unsigned char*)buf, strlen(buf), ZIPLIST_TAIL);\n    sprintf(buf, \"128000\");\n    zl = ziplistPush(zl, (unsigned char*)buf, strlen(buf), ZIPLIST_TAIL);\n    sprintf(buf, \"-100\");\n    zl = ziplistPush(zl, (unsigned char*)buf, strlen(buf), ZIPLIST_HEAD);\n    sprintf(buf, \"4294967296\");\n    zl = ziplistPush(zl, (unsigned char*)buf, strlen(buf), ZIPLIST_HEAD);\n    sprintf(buf, \"non integer\");\n    zl = ziplistPush(zl, (unsigned char*)buf, strlen(buf), ZIPLIST_TAIL);\n    sprintf(buf, \"much much longer non integer\");\n    zl = ziplistPush(zl, (unsigned char*)buf, strlen(buf), ZIPLIST_TAIL);\n    return zl;\n}\n\nstatic long long usec(void) {\n    struct timeval tv;\n    gettimeofday(&tv,NULL);\n    return (((long long)tv.tv_sec)*1000000)+tv.tv_usec;\n}\n\nstatic void stress(int pos, int num, int maxsize, int dnum) {\n    int i,j,k;\n    unsigned char *zl;\n    char posstr[2][5] = { \"HEAD\", \"TAIL\" };\n    long long start;\n    for (i = 0; i < maxsize; i+=dnum) {\n        zl = ziplistNew();\n        for (j = 0; j < i; j++) {\n            zl = ziplistPush(zl,(unsigned char*)\"quux\",4,ZIPLIST_TAIL);\n        }\n\n        /* Do num times a push+pop from pos */\n        start = usec();\n        for (k = 0; k < num; k++) {\n            zl = ziplistPush(zl,(unsigned char*)\"quux\",4,pos);\n            zl = ziplistDeleteRange(zl,0,1);\n        }\n        printf(\"List size: %8d, bytes: %8d, %dx push+pop (%s): %6lld usec\\n\",\n            i,intrev32ifbe(ZIPLIST_BYTES(zl)),num,posstr[pos],usec()-start);\n        zfree(zl);\n    }\n}\n\nstatic unsigned char *pop(unsigned char *zl, int where) {\n    unsigned char *p, *vstr;\n    unsigned int vlen;\n    long long vlong;\n\n    p = ziplistIndex(zl,where == ZIPLIST_HEAD ? 0 : -1);\n    if (ziplistGet(p,&vstr,&vlen,&vlong)) {\n        if (where == ZIPLIST_HEAD)\n            printf(\"Pop head: \");\n        else\n            printf(\"Pop tail: \");\n\n        if (vstr) {\n            if (vlen && fwrite(vstr,vlen,1,stdout) == 0) perror(\"fwrite\");\n        }\n        else {\n            printf(\"%lld\", vlong);\n        }\n\n        printf(\"\\n\");\n        return ziplistDelete(zl,&p);\n    } else {\n        printf(\"ERROR: Could not pop\\n\");\n        exit(1);\n    }\n}\n\nstatic int randstring(char *target, unsigned int min, unsigned int max) {\n    int p = 0;\n    int len = min+rand()%(max-min+1);\n    int minval, maxval;\n    switch(rand() % 3) {\n    case 0:\n        minval = 0;\n        maxval = 255;\n    break;\n    case 1:\n        minval = 48;\n        maxval = 122;\n    break;\n    case 2:\n        minval = 48;\n        maxval = 52;\n    break;\n    default:\n        assert(NULL);\n    }\n\n    while(p < len)\n        target[p++] = minval+rand()%(maxval-minval+1);\n    return len;\n}\n\nstatic void verify(unsigned char *zl, zlentry *e) {\n    int len = ziplistLen(zl);\n    zlentry _e;\n\n    ZIPLIST_ENTRY_ZERO(&_e);\n\n    for (int i = 0; i < len; i++) {\n        memset(&e[i], 0, sizeof(zlentry));\n        zipEntry(ziplistIndex(zl, i), &e[i]);\n\n        memset(&_e, 0, sizeof(zlentry));\n        zipEntry(ziplistIndex(zl, -len+i), &_e);\n\n        assert(memcmp(&e[i], &_e, sizeof(zlentry)) == 0);\n    }\n}\n\nint ziplistTest(int argc, char **argv) {\n    unsigned char *zl, *p;\n    unsigned char *entry;\n    unsigned int elen;\n    long long value;\n\n    /* If an argument is given, use it as the random seed. */\n    if (argc == 2)\n        srand(atoi(argv[1]));\n\n    zl = createIntList();\n    ziplistRepr(zl);\n\n    zfree(zl);\n\n    zl = createList();\n    ziplistRepr(zl);\n\n    zl = pop(zl,ZIPLIST_TAIL);\n    ziplistRepr(zl);\n\n    zl = pop(zl,ZIPLIST_HEAD);\n    ziplistRepr(zl);\n\n    zl = pop(zl,ZIPLIST_TAIL);\n    ziplistRepr(zl);\n\n    zl = pop(zl,ZIPLIST_TAIL);\n    ziplistRepr(zl);\n\n    zfree(zl);\n\n    printf(\"Get element at index 3:\\n\");\n    {\n        zl = createList();\n        p = ziplistIndex(zl, 3);\n        if (!ziplistGet(p, &entry, &elen, &value)) {\n            printf(\"ERROR: Could not access index 3\\n\");\n            return 1;\n        }\n        if (entry) {\n            if (elen && fwrite(entry,elen,1,stdout) == 0) perror(\"fwrite\");\n            printf(\"\\n\");\n        } else {\n            printf(\"%lld\\n\", value);\n        }\n        printf(\"\\n\");\n        zfree(zl);\n    }\n\n    printf(\"Get element at index 4 (out of range):\\n\");\n    {\n        zl = createList();\n        p = ziplistIndex(zl, 4);\n        if (p == NULL) {\n            printf(\"No entry\\n\");\n        } else {\n            printf(\"ERROR: Out of range index should return NULL, returned offset: %ld\\n\", p-zl);\n            return 1;\n        }\n        printf(\"\\n\");\n        zfree(zl);\n    }\n\n    printf(\"Get element at index -1 (last element):\\n\");\n    {\n        zl = createList();\n        p = ziplistIndex(zl, -1);\n        if (!ziplistGet(p, &entry, &elen, &value)) {\n            printf(\"ERROR: Could not access index -1\\n\");\n            return 1;\n        }\n        if (entry) {\n            if (elen && fwrite(entry,elen,1,stdout) == 0) perror(\"fwrite\");\n            printf(\"\\n\");\n        } else {\n            printf(\"%lld\\n\", value);\n        }\n        printf(\"\\n\");\n        zfree(zl);\n    }\n\n    printf(\"Get element at index -4 (first element):\\n\");\n    {\n        zl = createList();\n        p = ziplistIndex(zl, -4);\n        if (!ziplistGet(p, &entry, &elen, &value)) {\n            printf(\"ERROR: Could not access index -4\\n\");\n            return 1;\n        }\n        if (entry) {\n            if (elen && fwrite(entry,elen,1,stdout) == 0) perror(\"fwrite\");\n            printf(\"\\n\");\n        } else {\n            printf(\"%lld\\n\", value);\n        }\n        printf(\"\\n\");\n        zfree(zl);\n    }\n\n    printf(\"Get element at index -5 (reverse out of range):\\n\");\n    {\n        zl = createList();\n        p = ziplistIndex(zl, -5);\n        if (p == NULL) {\n            printf(\"No entry\\n\");\n        } else {\n            printf(\"ERROR: Out of range index should return NULL, returned offset: %ld\\n\", p-zl);\n            return 1;\n        }\n        printf(\"\\n\");\n        zfree(zl);\n    }\n\n    printf(\"Iterate list from 0 to end:\\n\");\n    {\n        zl = createList();\n        p = ziplistIndex(zl, 0);\n        while (ziplistGet(p, &entry, &elen, &value)) {\n            printf(\"Entry: \");\n            if (entry) {\n                if (elen && fwrite(entry,elen,1,stdout) == 0) perror(\"fwrite\");\n            } else {\n                printf(\"%lld\", value);\n            }\n            p = ziplistNext(zl,p);\n            printf(\"\\n\");\n        }\n        printf(\"\\n\");\n        zfree(zl);\n    }\n\n    printf(\"Iterate list from 1 to end:\\n\");\n    {\n        zl = createList();\n        p = ziplistIndex(zl, 1);\n        while (ziplistGet(p, &entry, &elen, &value)) {\n            printf(\"Entry: \");\n            if (entry) {\n                if (elen && fwrite(entry,elen,1,stdout) == 0) perror(\"fwrite\");\n            } else {\n                printf(\"%lld\", value);\n            }\n            p = ziplistNext(zl,p);\n            printf(\"\\n\");\n        }\n        printf(\"\\n\");\n        zfree(zl);\n    }\n\n    printf(\"Iterate list from 2 to end:\\n\");\n    {\n        zl = createList();\n        p = ziplistIndex(zl, 2);\n        while (ziplistGet(p, &entry, &elen, &value)) {\n            printf(\"Entry: \");\n            if (entry) {\n                if (elen && fwrite(entry,elen,1,stdout) == 0) perror(\"fwrite\");\n            } else {\n                printf(\"%lld\", value);\n            }\n            p = ziplistNext(zl,p);\n            printf(\"\\n\");\n        }\n        printf(\"\\n\");\n        zfree(zl);\n    }\n\n    printf(\"Iterate starting out of range:\\n\");\n    {\n        zl = createList();\n        p = ziplistIndex(zl, 4);\n        if (!ziplistGet(p, &entry, &elen, &value)) {\n            printf(\"No entry\\n\");\n        } else {\n            printf(\"ERROR\\n\");\n        }\n        printf(\"\\n\");\n        zfree(zl);\n    }\n\n    printf(\"Iterate from back to front:\\n\");\n    {\n        zl = createList();\n        p = ziplistIndex(zl, -1);\n        while (ziplistGet(p, &entry, &elen, &value)) {\n            printf(\"Entry: \");\n            if (entry) {\n                if (elen && fwrite(entry,elen,1,stdout) == 0) perror(\"fwrite\");\n            } else {\n                printf(\"%lld\", value);\n            }\n            p = ziplistPrev(zl,p);\n            printf(\"\\n\");\n        }\n        printf(\"\\n\");\n        zfree(zl);\n    }\n\n    printf(\"Iterate from back to front, deleting all items:\\n\");\n    {\n        zl = createList();\n        p = ziplistIndex(zl, -1);\n        while (ziplistGet(p, &entry, &elen, &value)) {\n            printf(\"Entry: \");\n            if (entry) {\n                if (elen && fwrite(entry,elen,1,stdout) == 0) perror(\"fwrite\");\n            } else {\n                printf(\"%lld\", value);\n            }\n            zl = ziplistDelete(zl,&p);\n            p = ziplistPrev(zl,p);\n            printf(\"\\n\");\n        }\n        printf(\"\\n\");\n        zfree(zl);\n    }\n\n    printf(\"Delete inclusive range 0,0:\\n\");\n    {\n        zl = createList();\n        zl = ziplistDeleteRange(zl, 0, 1);\n        ziplistRepr(zl);\n        zfree(zl);\n    }\n\n    printf(\"Delete inclusive range 0,1:\\n\");\n    {\n        zl = createList();\n        zl = ziplistDeleteRange(zl, 0, 2);\n        ziplistRepr(zl);\n        zfree(zl);\n    }\n\n    printf(\"Delete inclusive range 1,2:\\n\");\n    {\n        zl = createList();\n        zl = ziplistDeleteRange(zl, 1, 2);\n        ziplistRepr(zl);\n        zfree(zl);\n    }\n\n    printf(\"Delete with start index out of range:\\n\");\n    {\n        zl = createList();\n        zl = ziplistDeleteRange(zl, 5, 1);\n        ziplistRepr(zl);\n        zfree(zl);\n    }\n\n    printf(\"Delete with num overflow:\\n\");\n    {\n        zl = createList();\n        zl = ziplistDeleteRange(zl, 1, 5);\n        ziplistRepr(zl);\n        zfree(zl);\n    }\n\n    printf(\"Delete foo while iterating:\\n\");\n    {\n        zl = createList();\n        p = ziplistIndex(zl,0);\n        while (ziplistGet(p,&entry,&elen,&value)) {\n            if (entry && strncmp(\"foo\",(char*)entry,elen) == 0) {\n                printf(\"Delete foo\\n\");\n                zl = ziplistDelete(zl,&p);\n            } else {\n                printf(\"Entry: \");\n                if (entry) {\n                    if (elen && fwrite(entry,elen,1,stdout) == 0)\n                        perror(\"fwrite\");\n                } else {\n                    printf(\"%lld\",value);\n                }\n                p = ziplistNext(zl,p);\n                printf(\"\\n\");\n            }\n        }\n        printf(\"\\n\");\n        ziplistRepr(zl);\n        zfree(zl);\n    }\n\n    printf(\"Regression test for >255 byte strings:\\n\");\n    {\n        char v1[257] = {0}, v2[257] = {0};\n        memset(v1,'x',256);\n        memset(v2,'y',256);\n        zl = ziplistNew();\n        zl = ziplistPush(zl,(unsigned char*)v1,strlen(v1),ZIPLIST_TAIL);\n        zl = ziplistPush(zl,(unsigned char*)v2,strlen(v2),ZIPLIST_TAIL);\n\n        /* Pop values again and compare their value. */\n        p = ziplistIndex(zl,0);\n        assert(ziplistGet(p,&entry,&elen,&value));\n        assert(strncmp(v1,(char*)entry,elen) == 0);\n        p = ziplistIndex(zl,1);\n        assert(ziplistGet(p,&entry,&elen,&value));\n        assert(strncmp(v2,(char*)entry,elen) == 0);\n        printf(\"SUCCESS\\n\\n\");\n        zfree(zl);\n    }\n\n    printf(\"Regression test deleting next to last entries:\\n\");\n    {\n        char v[3][257] = {{0}};\n        zlentry e[3] = {{.prevrawlensize = 0, .prevrawlen = 0, .lensize = 0,\n                         .len = 0, .headersize = 0, .encoding = 0, .p = NULL}};\n        size_t i;\n\n        for (i = 0; i < (sizeof(v)/sizeof(v[0])); i++) {\n            memset(v[i], 'a' + i, sizeof(v[0]));\n        }\n\n        v[0][256] = '\\0';\n        v[1][  1] = '\\0';\n        v[2][256] = '\\0';\n\n        zl = ziplistNew();\n        for (i = 0; i < (sizeof(v)/sizeof(v[0])); i++) {\n            zl = ziplistPush(zl, (unsigned char *) v[i], strlen(v[i]), ZIPLIST_TAIL);\n        }\n\n        verify(zl, e);\n\n        assert(e[0].prevrawlensize == 1);\n        assert(e[1].prevrawlensize == 5);\n        assert(e[2].prevrawlensize == 1);\n\n        /* Deleting entry 1 will increase `prevrawlensize` for entry 2 */\n        unsigned char *p = e[1].p;\n        zl = ziplistDelete(zl, &p);\n\n        verify(zl, e);\n\n        assert(e[0].prevrawlensize == 1);\n        assert(e[1].prevrawlensize == 5);\n\n        printf(\"SUCCESS\\n\\n\");\n        zfree(zl);\n    }\n\n    printf(\"Create long list and check indices:\\n\");\n    {\n        zl = ziplistNew();\n        char buf[32];\n        int i,len;\n        for (i = 0; i < 1000; i++) {\n            len = sprintf(buf,\"%d\",i);\n            zl = ziplistPush(zl,(unsigned char*)buf,len,ZIPLIST_TAIL);\n        }\n        for (i = 0; i < 1000; i++) {\n            p = ziplistIndex(zl,i);\n            assert(ziplistGet(p,NULL,NULL,&value));\n            assert(i == value);\n\n            p = ziplistIndex(zl,-i-1);\n            assert(ziplistGet(p,NULL,NULL,&value));\n            assert(999-i == value);\n        }\n        printf(\"SUCCESS\\n\\n\");\n        zfree(zl);\n    }\n\n    printf(\"Compare strings with ziplist entries:\\n\");\n    {\n        zl = createList();\n        p = ziplistIndex(zl,0);\n        if (!ziplistCompare(p,(unsigned char*)\"hello\",5)) {\n            printf(\"ERROR: not \\\"hello\\\"\\n\");\n            return 1;\n        }\n        if (ziplistCompare(p,(unsigned char*)\"hella\",5)) {\n            printf(\"ERROR: \\\"hella\\\"\\n\");\n            return 1;\n        }\n\n        p = ziplistIndex(zl,3);\n        if (!ziplistCompare(p,(unsigned char*)\"1024\",4)) {\n            printf(\"ERROR: not \\\"1024\\\"\\n\");\n            return 1;\n        }\n        if (ziplistCompare(p,(unsigned char*)\"1025\",4)) {\n            printf(\"ERROR: \\\"1025\\\"\\n\");\n            return 1;\n        }\n        printf(\"SUCCESS\\n\\n\");\n        zfree(zl);\n    }\n\n    printf(\"Merge test:\\n\");\n    {\n        /* create list gives us: [hello, foo, quux, 1024] */\n        zl = createList();\n        unsigned char *zl2 = createList();\n\n        unsigned char *zl3 = ziplistNew();\n        unsigned char *zl4 = ziplistNew();\n\n        if (ziplistMerge(&zl4, &zl4)) {\n            printf(\"ERROR: Allowed merging of one ziplist into itself.\\n\");\n            return 1;\n        }\n\n        /* Merge two empty ziplists, get empty result back. */\n        zl4 = ziplistMerge(&zl3, &zl4);\n        ziplistRepr(zl4);\n        if (ziplistLen(zl4)) {\n            printf(\"ERROR: Merging two empty ziplists created entries.\\n\");\n            return 1;\n        }\n        zfree(zl4);\n\n        zl2 = ziplistMerge(&zl, &zl2);\n        /* merge gives us: [hello, foo, quux, 1024, hello, foo, quux, 1024] */\n        ziplistRepr(zl2);\n\n        if (ziplistLen(zl2) != 8) {\n            printf(\"ERROR: Merged length not 8, but: %u\\n\", ziplistLen(zl2));\n            return 1;\n        }\n\n        p = ziplistIndex(zl2,0);\n        if (!ziplistCompare(p,(unsigned char*)\"hello\",5)) {\n            printf(\"ERROR: not \\\"hello\\\"\\n\");\n            return 1;\n        }\n        if (ziplistCompare(p,(unsigned char*)\"hella\",5)) {\n            printf(\"ERROR: \\\"hella\\\"\\n\");\n            return 1;\n        }\n\n        p = ziplistIndex(zl2,3);\n        if (!ziplistCompare(p,(unsigned char*)\"1024\",4)) {\n            printf(\"ERROR: not \\\"1024\\\"\\n\");\n            return 1;\n        }\n        if (ziplistCompare(p,(unsigned char*)\"1025\",4)) {\n            printf(\"ERROR: \\\"1025\\\"\\n\");\n            return 1;\n        }\n\n        p = ziplistIndex(zl2,4);\n        if (!ziplistCompare(p,(unsigned char*)\"hello\",5)) {\n            printf(\"ERROR: not \\\"hello\\\"\\n\");\n            return 1;\n        }\n        if (ziplistCompare(p,(unsigned char*)\"hella\",5)) {\n            printf(\"ERROR: \\\"hella\\\"\\n\");\n            return 1;\n        }\n\n        p = ziplistIndex(zl2,7);\n        if (!ziplistCompare(p,(unsigned char*)\"1024\",4)) {\n            printf(\"ERROR: not \\\"1024\\\"\\n\");\n            return 1;\n        }\n        if (ziplistCompare(p,(unsigned char*)\"1025\",4)) {\n            printf(\"ERROR: \\\"1025\\\"\\n\");\n            return 1;\n        }\n        printf(\"SUCCESS\\n\\n\");\n        zfree(zl);\n    }\n\n    printf(\"Stress with random payloads of different encoding:\\n\");\n    {\n        int i,j,len,where;\n        unsigned char *p;\n        char buf[1024];\n        int buflen;\n        list *ref;\n        listNode *refnode;\n\n        /* Hold temp vars from ziplist */\n        unsigned char *sstr;\n        unsigned int slen;\n        long long sval;\n\n        for (i = 0; i < 20000; i++) {\n            zl = ziplistNew();\n            ref = listCreate();\n            listSetFreeMethod(ref,(void (*)(void*))sdsfree);\n            len = rand() % 256;\n\n            /* Create lists */\n            for (j = 0; j < len; j++) {\n                where = (rand() & 1) ? ZIPLIST_HEAD : ZIPLIST_TAIL;\n                if (rand() % 2) {\n                    buflen = randstring(buf,1,sizeof(buf)-1);\n                } else {\n                    switch(rand() % 3) {\n                    case 0:\n                        buflen = sprintf(buf,\"%lld\",(0LL + rand()) >> 20);\n                        break;\n                    case 1:\n                        buflen = sprintf(buf,\"%lld\",(0LL + rand()));\n                        break;\n                    case 2:\n                        buflen = sprintf(buf,\"%lld\",(0LL + rand()) << 20);\n                        break;\n                    default:\n                        assert(NULL);\n                    }\n                }\n\n                /* Add to ziplist */\n                zl = ziplistPush(zl, (unsigned char*)buf, buflen, where);\n\n                /* Add to reference list */\n                if (where == ZIPLIST_HEAD) {\n                    listAddNodeHead(ref,sdsnewlen(buf, buflen));\n                } else if (where == ZIPLIST_TAIL) {\n                    listAddNodeTail(ref,sdsnewlen(buf, buflen));\n                } else {\n                    assert(NULL);\n                }\n            }\n\n            assert(listLength(ref) == ziplistLen(zl));\n            for (j = 0; j < len; j++) {\n                /* Naive way to get elements, but similar to the stresser\n                 * executed from the Tcl test suite. */\n                p = ziplistIndex(zl,j);\n                refnode = listIndex(ref,j);\n\n                assert(ziplistGet(p,&sstr,&slen,&sval));\n                if (sstr == NULL) {\n                    buflen = sprintf(buf,\"%lld\",sval);\n                } else {\n                    buflen = slen;\n                    memcpy(buf,sstr,buflen);\n                    buf[buflen] = '\\0';\n                }\n                assert(memcmp(buf,listNodeValue(refnode),buflen) == 0);\n            }\n            zfree(zl);\n            listRelease(ref);\n        }\n        printf(\"SUCCESS\\n\\n\");\n    }\n\n    printf(\"Stress with variable ziplist size:\\n\");\n    {\n        stress(ZIPLIST_HEAD,100000,16384,256);\n        stress(ZIPLIST_TAIL,100000,16384,256);\n    }\n\n    return 0;\n}\n#endif\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/src/ziplist.h",
    "content": "/*\n * Copyright (c) 2009-2012, Pieter Noordhuis <pcnoordhuis at gmail dot com>\n * Copyright (c) 2009-2012, Salvatore Sanfilippo <antirez at gmail dot com>\n * All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions are met:\n *\n *   * Redistributions of source code must retain the above copyright notice,\n *     this list of conditions and the following disclaimer.\n *   * Redistributions in binary form must reproduce the above copyright\n *     notice, this list of conditions and the following disclaimer in the\n *     documentation and/or other materials provided with the distribution.\n *   * Neither the name of Redis nor the names of its contributors may be used\n *     to endorse or promote products derived from this software without\n *     specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\"\n * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\n * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE\n * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR\n * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF\n * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS\n * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN\n * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)\n * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE\n * POSSIBILITY OF SUCH DAMAGE.\n */\n\n#ifndef _ZIPLIST_H\n#define _ZIPLIST_H\n\n#define ZIPLIST_HEAD 0\n#define ZIPLIST_TAIL 1\n\nunsigned char *ziplistNew(void);\nunsigned char *ziplistMerge(unsigned char **first, unsigned char **second);\nunsigned char *ziplistPush(unsigned char *zl, unsigned char *s, unsigned int slen, int where);\nunsigned char *ziplistIndex(unsigned char *zl, int index);\nunsigned char *ziplistNext(unsigned char *zl, unsigned char *p);\nunsigned char *ziplistPrev(unsigned char *zl, unsigned char *p);\nunsigned int ziplistGet(unsigned char *p, unsigned char **sval, unsigned int *slen, long long *lval);\nunsigned char *ziplistInsert(unsigned char *zl, unsigned char *p, unsigned char *s, unsigned int slen);\nunsigned char *ziplistDelete(unsigned char *zl, unsigned char **p);\nunsigned char *ziplistDeleteRange(unsigned char *zl, int index, unsigned int num);\nunsigned int ziplistCompare(unsigned char *p, unsigned char *s, unsigned int slen);\nunsigned char *ziplistFind(unsigned char *p, unsigned char *vstr, unsigned int vlen, unsigned int skip);\nunsigned int ziplistLen(unsigned char *zl);\nsize_t ziplistBlobLen(unsigned char *zl);\n\n#ifdef REDIS_TEST\nint ziplistTest(int argc, char *argv[]);\n#endif\n\n#endif /* _ZIPLIST_H */\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/src/zipmap.c",
    "content": "/* String -> String Map data structure optimized for size.\n * This file implements a data structure mapping strings to other strings\n * implementing an O(n) lookup data structure designed to be very memory\n * efficient.\n *\n * The Redis Hash type uses this data structure for hashes composed of a small\n * number of elements, to switch to a hash table once a given number of\n * elements is reached.\n *\n * Given that many times Redis Hashes are used to represent objects composed\n * of few fields, this is a very big win in terms of used memory.\n *\n * --------------------------------------------------------------------------\n *\n * Copyright (c) 2009-2010, Salvatore Sanfilippo <antirez at gmail dot com>\n * All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions are met:\n *\n *   * Redistributions of source code must retain the above copyright notice,\n *     this list of conditions and the following disclaimer.\n *   * Redistributions in binary form must reproduce the above copyright\n *     notice, this list of conditions and the following disclaimer in the\n *     documentation and/or other materials provided with the distribution.\n *   * Neither the name of Redis nor the names of its contributors may be used\n *     to endorse or promote products derived from this software without\n *     specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\"\n * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\n * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE\n * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR\n * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF\n * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS\n * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN\n * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)\n * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE\n * POSSIBILITY OF SUCH DAMAGE.\n */\n\n/* Memory layout of a zipmap, for the map \"foo\" => \"bar\", \"hello\" => \"world\":\n *\n * <zmlen><len>\"foo\"<len><free>\"bar\"<len>\"hello\"<len><free>\"world\"\n *\n * <zmlen> is 1 byte length that holds the current size of the zipmap.\n * When the zipmap length is greater than or equal to 254, this value\n * is not used and the zipmap needs to be traversed to find out the length.\n *\n * <len> is the length of the following string (key or value).\n * <len> lengths are encoded in a single value or in a 5 bytes value.\n * If the first byte value (as an unsigned 8 bit value) is between 0 and\n * 253, it's a single-byte length. If it is 254 then a four bytes unsigned\n * integer follows (in the host byte ordering). A value of 255 is used to\n * signal the end of the hash.\n *\n * <free> is the number of free unused bytes after the string, resulting\n * from modification of values associated to a key. For instance if \"foo\"\n * is set to \"bar\", and later \"foo\" will be set to \"hi\", it will have a\n * free byte to use if the value will enlarge again later, or even in\n * order to add a key/value pair if it fits.\n *\n * <free> is always an unsigned 8 bit number, because if after an\n * update operation there are more than a few free bytes, the zipmap will be\n * reallocated to make sure it is as small as possible.\n *\n * The most compact representation of the above two elements hash is actually:\n *\n * \"\\x02\\x03foo\\x03\\x00bar\\x05hello\\x05\\x00world\\xff\"\n *\n * Note that because keys and values are prefixed length \"objects\",\n * the lookup will take O(N) where N is the number of elements\n * in the zipmap and *not* the number of bytes needed to represent the zipmap.\n * This lowers the constant times considerably.\n */\n\n#include <stdio.h>\n#include <string.h>\n#include \"zmalloc.h\"\n#include \"endianconv.h\"\n\n#define ZIPMAP_BIGLEN 254\n#define ZIPMAP_END 255\n\n/* The following defines the max value for the <free> field described in the\n * comments above, that is, the max number of trailing bytes in a value. */\n#define ZIPMAP_VALUE_MAX_FREE 4\n\n/* The following macro returns the number of bytes needed to encode the length\n * for the integer value _l, that is, 1 byte for lengths < ZIPMAP_BIGLEN and\n * 5 bytes for all the other lengths. */\n#define ZIPMAP_LEN_BYTES(_l) (((_l) < ZIPMAP_BIGLEN) ? 1 : sizeof(unsigned int)+1)\n\n/* Create a new empty zipmap. */\nunsigned char *zipmapNew(void) {\n    unsigned char *zm = zmalloc(2);\n\n    zm[0] = 0; /* Length */\n    zm[1] = ZIPMAP_END;\n    return zm;\n}\n\n/* Decode the encoded length pointed by 'p' */\nstatic unsigned int zipmapDecodeLength(unsigned char *p) {\n    unsigned int len = *p;\n\n    if (len < ZIPMAP_BIGLEN) return len;\n    memcpy(&len,p+1,sizeof(unsigned int));\n    memrev32ifbe(&len);\n    return len;\n}\n\n/* Encode the length 'l' writing it in 'p'. If p is NULL it just returns\n * the amount of bytes required to encode such a length. */\nstatic unsigned int zipmapEncodeLength(unsigned char *p, unsigned int len) {\n    if (p == NULL) {\n        return ZIPMAP_LEN_BYTES(len);\n    } else {\n        if (len < ZIPMAP_BIGLEN) {\n            p[0] = len;\n            return 1;\n        } else {\n            p[0] = ZIPMAP_BIGLEN;\n            memcpy(p+1,&len,sizeof(len));\n            memrev32ifbe(p+1);\n            return 1+sizeof(len);\n        }\n    }\n}\n\n/* Search for a matching key, returning a pointer to the entry inside the\n * zipmap. Returns NULL if the key is not found.\n *\n * If NULL is returned, and totlen is not NULL, it is set to the entire\n * size of the zimap, so that the calling function will be able to\n * reallocate the original zipmap to make room for more entries. */\nstatic unsigned char *zipmapLookupRaw(unsigned char *zm, unsigned char *key, unsigned int klen, unsigned int *totlen) {\n    unsigned char *p = zm+1, *k = NULL;\n    unsigned int l,llen;\n\n    while(*p != ZIPMAP_END) {\n        unsigned char free;\n\n        /* Match or skip the key */\n        l = zipmapDecodeLength(p);\n        llen = zipmapEncodeLength(NULL,l);\n        if (key != NULL && k == NULL && l == klen && !memcmp(p+llen,key,l)) {\n            /* Only return when the user doesn't care\n             * for the total length of the zipmap. */\n            if (totlen != NULL) {\n                k = p;\n            } else {\n                return p;\n            }\n        }\n        p += llen+l;\n        /* Skip the value as well */\n        l = zipmapDecodeLength(p);\n        p += zipmapEncodeLength(NULL,l);\n        free = p[0];\n        p += l+1+free; /* +1 to skip the free byte */\n    }\n    if (totlen != NULL) *totlen = (unsigned int)(p-zm)+1;\n    return k;\n}\n\nstatic unsigned long zipmapRequiredLength(unsigned int klen, unsigned int vlen) {\n    unsigned int l;\n\n    l = klen+vlen+3;\n    if (klen >= ZIPMAP_BIGLEN) l += 4;\n    if (vlen >= ZIPMAP_BIGLEN) l += 4;\n    return l;\n}\n\n/* Return the total amount used by a key (encoded length + payload) */\nstatic unsigned int zipmapRawKeyLength(unsigned char *p) {\n    unsigned int l = zipmapDecodeLength(p);\n    return zipmapEncodeLength(NULL,l) + l;\n}\n\n/* Return the total amount used by a value\n * (encoded length + single byte free count + payload) */\nstatic unsigned int zipmapRawValueLength(unsigned char *p) {\n    unsigned int l = zipmapDecodeLength(p);\n    unsigned int used;\n\n    used = zipmapEncodeLength(NULL,l);\n    used += p[used] + 1 + l;\n    return used;\n}\n\n/* If 'p' points to a key, this function returns the total amount of\n * bytes used to store this entry (entry = key + associated value + trailing\n * free space if any). */\nstatic unsigned int zipmapRawEntryLength(unsigned char *p) {\n    unsigned int l = zipmapRawKeyLength(p);\n    return l + zipmapRawValueLength(p+l);\n}\n\nstatic inline unsigned char *zipmapResize(unsigned char *zm, unsigned int len) {\n    zm = zrealloc(zm, len);\n    zm[len-1] = ZIPMAP_END;\n    return zm;\n}\n\n/* Set key to value, creating the key if it does not already exist.\n * If 'update' is not NULL, *update is set to 1 if the key was\n * already preset, otherwise to 0. */\nunsigned char *zipmapSet(unsigned char *zm, unsigned char *key, unsigned int klen, unsigned char *val, unsigned int vlen, int *update) {\n    unsigned int zmlen, offset;\n    unsigned int freelen, reqlen = zipmapRequiredLength(klen,vlen);\n    unsigned int empty, vempty;\n    unsigned char *p;\n\n    freelen = reqlen;\n    if (update) *update = 0;\n    p = zipmapLookupRaw(zm,key,klen,&zmlen);\n    if (p == NULL) {\n        /* Key not found: enlarge */\n        zm = zipmapResize(zm, zmlen+reqlen);\n        p = zm+zmlen-1;\n        zmlen = zmlen+reqlen;\n\n        /* Increase zipmap length (this is an insert) */\n        if (zm[0] < ZIPMAP_BIGLEN) zm[0]++;\n    } else {\n        /* Key found. Is there enough space for the new value? */\n        /* Compute the total length: */\n        if (update) *update = 1;\n        freelen = zipmapRawEntryLength(p);\n        if (freelen < reqlen) {\n            /* Store the offset of this key within the current zipmap, so\n             * it can be resized. Then, move the tail backwards so this\n             * pair fits at the current position. */\n            offset = p-zm;\n            zm = zipmapResize(zm, zmlen-freelen+reqlen);\n            p = zm+offset;\n\n            /* The +1 in the number of bytes to be moved is caused by the\n             * end-of-zipmap byte. Note: the *original* zmlen is used. */\n            memmove(p+reqlen, p+freelen, zmlen-(offset+freelen+1));\n            zmlen = zmlen-freelen+reqlen;\n            freelen = reqlen;\n        }\n    }\n\n    /* We now have a suitable block where the key/value entry can\n     * be written. If there is too much free space, move the tail\n     * of the zipmap a few bytes to the front and shrink the zipmap,\n     * as we want zipmaps to be very space efficient. */\n    empty = freelen-reqlen;\n    if (empty >= ZIPMAP_VALUE_MAX_FREE) {\n        /* First, move the tail <empty> bytes to the front, then resize\n         * the zipmap to be <empty> bytes smaller. */\n        offset = p-zm;\n        memmove(p+reqlen, p+freelen, zmlen-(offset+freelen+1));\n        zmlen -= empty;\n        zm = zipmapResize(zm, zmlen);\n        p = zm+offset;\n        vempty = 0;\n    } else {\n        vempty = empty;\n    }\n\n    /* Just write the key + value and we are done. */\n    /* Key: */\n    p += zipmapEncodeLength(p,klen);\n    memcpy(p,key,klen);\n    p += klen;\n    /* Value: */\n    p += zipmapEncodeLength(p,vlen);\n    *p++ = vempty;\n    memcpy(p,val,vlen);\n    return zm;\n}\n\n/* Remove the specified key. If 'deleted' is not NULL the pointed integer is\n * set to 0 if the key was not found, to 1 if it was found and deleted. */\nunsigned char *zipmapDel(unsigned char *zm, unsigned char *key, unsigned int klen, int *deleted) {\n    unsigned int zmlen, freelen;\n    unsigned char *p = zipmapLookupRaw(zm,key,klen,&zmlen);\n    if (p) {\n        freelen = zipmapRawEntryLength(p);\n        memmove(p, p+freelen, zmlen-((p-zm)+freelen+1));\n        zm = zipmapResize(zm, zmlen-freelen);\n\n        /* Decrease zipmap length */\n        if (zm[0] < ZIPMAP_BIGLEN) zm[0]--;\n\n        if (deleted) *deleted = 1;\n    } else {\n        if (deleted) *deleted = 0;\n    }\n    return zm;\n}\n\n/* Call before iterating through elements via zipmapNext() */\nunsigned char *zipmapRewind(unsigned char *zm) {\n    return zm+1;\n}\n\n/* This function is used to iterate through all the zipmap elements.\n * In the first call the first argument is the pointer to the zipmap + 1.\n * In the next calls what zipmapNext returns is used as first argument.\n * Example:\n *\n * unsigned char *i = zipmapRewind(my_zipmap);\n * while((i = zipmapNext(i,&key,&klen,&value,&vlen)) != NULL) {\n *     printf(\"%d bytes key at $p\\n\", klen, key);\n *     printf(\"%d bytes value at $p\\n\", vlen, value);\n * }\n */\nunsigned char *zipmapNext(unsigned char *zm, unsigned char **key, unsigned int *klen, unsigned char **value, unsigned int *vlen) {\n    if (zm[0] == ZIPMAP_END) return NULL;\n    if (key) {\n        *key = zm;\n        *klen = zipmapDecodeLength(zm);\n        *key += ZIPMAP_LEN_BYTES(*klen);\n    }\n    zm += zipmapRawKeyLength(zm);\n    if (value) {\n        *value = zm+1;\n        *vlen = zipmapDecodeLength(zm);\n        *value += ZIPMAP_LEN_BYTES(*vlen);\n    }\n    zm += zipmapRawValueLength(zm);\n    return zm;\n}\n\n/* Search a key and retrieve the pointer and len of the associated value.\n * If the key is found the function returns 1, otherwise 0. */\nint zipmapGet(unsigned char *zm, unsigned char *key, unsigned int klen, unsigned char **value, unsigned int *vlen) {\n    unsigned char *p;\n\n    if ((p = zipmapLookupRaw(zm,key,klen,NULL)) == NULL) return 0;\n    p += zipmapRawKeyLength(p);\n    *vlen = zipmapDecodeLength(p);\n    *value = p + ZIPMAP_LEN_BYTES(*vlen) + 1;\n    return 1;\n}\n\n/* Return 1 if the key exists, otherwise 0 is returned. */\nint zipmapExists(unsigned char *zm, unsigned char *key, unsigned int klen) {\n    return zipmapLookupRaw(zm,key,klen,NULL) != NULL;\n}\n\n/* Return the number of entries inside a zipmap */\nunsigned int zipmapLen(unsigned char *zm) {\n    unsigned int len = 0;\n    if (zm[0] < ZIPMAP_BIGLEN) {\n        len = zm[0];\n    } else {\n        unsigned char *p = zipmapRewind(zm);\n        while((p = zipmapNext(p,NULL,NULL,NULL,NULL)) != NULL) len++;\n\n        /* Re-store length if small enough */\n        if (len < ZIPMAP_BIGLEN) zm[0] = len;\n    }\n    return len;\n}\n\n/* Return the raw size in bytes of a zipmap, so that we can serialize\n * the zipmap on disk (or everywhere is needed) just writing the returned\n * amount of bytes of the C array starting at the zipmap pointer. */\nsize_t zipmapBlobLen(unsigned char *zm) {\n    unsigned int totlen;\n    zipmapLookupRaw(zm,NULL,0,&totlen);\n    return totlen;\n}\n\n#ifdef REDIS_TEST\nstatic void zipmapRepr(unsigned char *p) {\n    unsigned int l;\n\n    printf(\"{status %u}\",*p++);\n    while(1) {\n        if (p[0] == ZIPMAP_END) {\n            printf(\"{end}\");\n            break;\n        } else {\n            unsigned char e;\n\n            l = zipmapDecodeLength(p);\n            printf(\"{key %u}\",l);\n            p += zipmapEncodeLength(NULL,l);\n            if (l != 0 && fwrite(p,l,1,stdout) == 0) perror(\"fwrite\");\n            p += l;\n\n            l = zipmapDecodeLength(p);\n            printf(\"{value %u}\",l);\n            p += zipmapEncodeLength(NULL,l);\n            e = *p++;\n            if (l != 0 && fwrite(p,l,1,stdout) == 0) perror(\"fwrite\");\n            p += l+e;\n            if (e) {\n                printf(\"[\");\n                while(e--) printf(\".\");\n                printf(\"]\");\n            }\n        }\n    }\n    printf(\"\\n\");\n}\n\n#define UNUSED(x) (void)(x)\nint zipmapTest(int argc, char *argv[]) {\n    unsigned char *zm;\n\n    UNUSED(argc);\n    UNUSED(argv);\n\n    zm = zipmapNew();\n\n    zm = zipmapSet(zm,(unsigned char*) \"name\",4, (unsigned char*) \"foo\",3,NULL);\n    zm = zipmapSet(zm,(unsigned char*) \"surname\",7, (unsigned char*) \"foo\",3,NULL);\n    zm = zipmapSet(zm,(unsigned char*) \"age\",3, (unsigned char*) \"foo\",3,NULL);\n    zipmapRepr(zm);\n\n    zm = zipmapSet(zm,(unsigned char*) \"hello\",5, (unsigned char*) \"world!\",6,NULL);\n    zm = zipmapSet(zm,(unsigned char*) \"foo\",3, (unsigned char*) \"bar\",3,NULL);\n    zm = zipmapSet(zm,(unsigned char*) \"foo\",3, (unsigned char*) \"!\",1,NULL);\n    zipmapRepr(zm);\n    zm = zipmapSet(zm,(unsigned char*) \"foo\",3, (unsigned char*) \"12345\",5,NULL);\n    zipmapRepr(zm);\n    zm = zipmapSet(zm,(unsigned char*) \"new\",3, (unsigned char*) \"xx\",2,NULL);\n    zm = zipmapSet(zm,(unsigned char*) \"noval\",5, (unsigned char*) \"\",0,NULL);\n    zipmapRepr(zm);\n    zm = zipmapDel(zm,(unsigned char*) \"new\",3,NULL);\n    zipmapRepr(zm);\n\n    printf(\"\\nLook up large key:\\n\");\n    {\n        unsigned char buf[512];\n        unsigned char *value;\n        unsigned int vlen, i;\n        for (i = 0; i < 512; i++) buf[i] = 'a';\n\n        zm = zipmapSet(zm,buf,512,(unsigned char*) \"long\",4,NULL);\n        if (zipmapGet(zm,buf,512,&value,&vlen)) {\n            printf(\"  <long key> is associated to the %d bytes value: %.*s\\n\",\n                vlen, vlen, value);\n        }\n    }\n\n    printf(\"\\nPerform a direct lookup:\\n\");\n    {\n        unsigned char *value;\n        unsigned int vlen;\n\n        if (zipmapGet(zm,(unsigned char*) \"foo\",3,&value,&vlen)) {\n            printf(\"  foo is associated to the %d bytes value: %.*s\\n\",\n                vlen, vlen, value);\n        }\n    }\n    printf(\"\\nIterate through elements:\\n\");\n    {\n        unsigned char *i = zipmapRewind(zm);\n        unsigned char *key, *value;\n        unsigned int klen, vlen;\n\n        while((i = zipmapNext(i,&key,&klen,&value,&vlen)) != NULL) {\n            printf(\"  %d:%.*s => %d:%.*s\\n\", klen, klen, key, vlen, vlen, value);\n        }\n    }\n    return 0;\n}\n#endif\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/src/zipmap.h",
    "content": "/* String -> String Map data structure optimized for size.\n *\n * See zipmap.c for more info.\n *\n * --------------------------------------------------------------------------\n *\n * Copyright (c) 2009-2010, Salvatore Sanfilippo <antirez at gmail dot com>\n * All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions are met:\n *\n *   * Redistributions of source code must retain the above copyright notice,\n *     this list of conditions and the following disclaimer.\n *   * Redistributions in binary form must reproduce the above copyright\n *     notice, this list of conditions and the following disclaimer in the\n *     documentation and/or other materials provided with the distribution.\n *   * Neither the name of Redis nor the names of its contributors may be used\n *     to endorse or promote products derived from this software without\n *     specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\"\n * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\n * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE\n * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR\n * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF\n * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS\n * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN\n * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)\n * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE\n * POSSIBILITY OF SUCH DAMAGE.\n */\n\n#ifndef _ZIPMAP_H\n#define _ZIPMAP_H\n\nunsigned char *zipmapNew(void);\nunsigned char *zipmapSet(unsigned char *zm, unsigned char *key, unsigned int klen, unsigned char *val, unsigned int vlen, int *update);\nunsigned char *zipmapDel(unsigned char *zm, unsigned char *key, unsigned int klen, int *deleted);\nunsigned char *zipmapRewind(unsigned char *zm);\nunsigned char *zipmapNext(unsigned char *zm, unsigned char **key, unsigned int *klen, unsigned char **value, unsigned int *vlen);\nint zipmapGet(unsigned char *zm, unsigned char *key, unsigned int klen, unsigned char **value, unsigned int *vlen);\nint zipmapExists(unsigned char *zm, unsigned char *key, unsigned int klen);\nunsigned int zipmapLen(unsigned char *zm);\nsize_t zipmapBlobLen(unsigned char *zm);\nvoid zipmapRepr(unsigned char *p);\n\n#ifdef REDIS_TEST\nint zipmapTest(int argc, char *argv[]);\n#endif\n\n#endif\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/src/zmalloc.c",
    "content": "/* zmalloc - total amount of allocated memory aware version of malloc()\n *\n * Copyright (c) 2009-2010, Salvatore Sanfilippo <antirez at gmail dot com>\n * All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions are met:\n *\n *   * Redistributions of source code must retain the above copyright notice,\n *     this list of conditions and the following disclaimer.\n *   * Redistributions in binary form must reproduce the above copyright\n *     notice, this list of conditions and the following disclaimer in the\n *     documentation and/or other materials provided with the distribution.\n *   * Neither the name of Redis nor the names of its contributors may be used\n *     to endorse or promote products derived from this software without\n *     specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\"\n * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\n * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE\n * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR\n * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF\n * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS\n * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN\n * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)\n * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE\n * POSSIBILITY OF SUCH DAMAGE.\n */\n\n#include <stdio.h>\n#include <stdlib.h>\n\n/* This function provide us access to the original libc free(). This is useful\n * for instance to free results obtained by backtrace_symbols(). We need\n * to define this function before including zmalloc.h that may shadow the\n * free implementation if we use jemalloc or another non standard allocator. */\nvoid zlibc_free(void *ptr) {\n    free(ptr);\n}\n\n#include <string.h>\n#include <pthread.h>\n#include \"config.h\"\n#include \"zmalloc.h\"\n\n#ifdef HAVE_MALLOC_SIZE\n#define PREFIX_SIZE (0)\n#else\n#if defined(__sun) || defined(__sparc) || defined(__sparc__)\n#define PREFIX_SIZE (sizeof(long long))\n#else\n#define PREFIX_SIZE (sizeof(size_t))\n#endif\n#endif\n\n/* Explicitly override malloc/free etc when using tcmalloc. */\n#if defined(USE_TCMALLOC)\n#define malloc(size) tc_malloc(size)\n#define calloc(count,size) tc_calloc(count,size)\n#define realloc(ptr,size) tc_realloc(ptr,size)\n#define free(ptr) tc_free(ptr)\n#elif defined(USE_JEMALLOC)\n#define malloc(size) je_malloc(size)\n#define calloc(count,size) je_calloc(count,size)\n#define realloc(ptr,size) je_realloc(ptr,size)\n#define free(ptr) je_free(ptr)\n#endif\n\n#if defined(__ATOMIC_RELAXED)\n#define update_zmalloc_stat_add(__n) __atomic_add_fetch(&used_memory, (__n), __ATOMIC_RELAXED)\n#define update_zmalloc_stat_sub(__n) __atomic_sub_fetch(&used_memory, (__n), __ATOMIC_RELAXED)\n#elif defined(HAVE_ATOMIC)\n#define update_zmalloc_stat_add(__n) __sync_add_and_fetch(&used_memory, (__n))\n#define update_zmalloc_stat_sub(__n) __sync_sub_and_fetch(&used_memory, (__n))\n#else\n#define update_zmalloc_stat_add(__n) do { \\\n    pthread_mutex_lock(&used_memory_mutex); \\\n    used_memory += (__n); \\\n    pthread_mutex_unlock(&used_memory_mutex); \\\n} while(0)\n\n#define update_zmalloc_stat_sub(__n) do { \\\n    pthread_mutex_lock(&used_memory_mutex); \\\n    used_memory -= (__n); \\\n    pthread_mutex_unlock(&used_memory_mutex); \\\n} while(0)\n\n#endif\n\n#define update_zmalloc_stat_alloc(__n) do { \\\n    size_t _n = (__n); \\\n    if (_n&(sizeof(long)-1)) _n += sizeof(long)-(_n&(sizeof(long)-1)); \\\n    if (zmalloc_thread_safe) { \\\n        update_zmalloc_stat_add(_n); \\\n    } else { \\\n        used_memory += _n; \\\n    } \\\n} while(0)\n\n#define update_zmalloc_stat_free(__n) do { \\\n    size_t _n = (__n); \\\n    if (_n&(sizeof(long)-1)) _n += sizeof(long)-(_n&(sizeof(long)-1)); \\\n    if (zmalloc_thread_safe) { \\\n        update_zmalloc_stat_sub(_n); \\\n    } else { \\\n        used_memory -= _n; \\\n    } \\\n} while(0)\n\nstatic size_t used_memory = 0;\nstatic int zmalloc_thread_safe = 0;\npthread_mutex_t used_memory_mutex = PTHREAD_MUTEX_INITIALIZER;\n\nstatic void zmalloc_default_oom(size_t size) {\n    fprintf(stderr, \"zmalloc: Out of memory trying to allocate %zu bytes\\n\",\n        size);\n    fflush(stderr);\n    abort();\n}\n\nstatic void (*zmalloc_oom_handler)(size_t) = zmalloc_default_oom;\n\nvoid *zmalloc(size_t size) {\n    void *ptr = malloc(size+PREFIX_SIZE);\n\n    if (!ptr) zmalloc_oom_handler(size);\n#ifdef HAVE_MALLOC_SIZE\n    update_zmalloc_stat_alloc(zmalloc_size(ptr));\n    return ptr;\n#else\n    *((size_t*)ptr) = size;\n    update_zmalloc_stat_alloc(size+PREFIX_SIZE);\n    return (char*)ptr+PREFIX_SIZE;\n#endif\n}\n\nvoid *zcalloc(size_t size) {\n    void *ptr = calloc(1, size+PREFIX_SIZE);\n\n    if (!ptr) zmalloc_oom_handler(size);\n#ifdef HAVE_MALLOC_SIZE\n    update_zmalloc_stat_alloc(zmalloc_size(ptr));\n    return ptr;\n#else\n    *((size_t*)ptr) = size;\n    update_zmalloc_stat_alloc(size+PREFIX_SIZE);\n    return (char*)ptr+PREFIX_SIZE;\n#endif\n}\n\nvoid *zrealloc(void *ptr, size_t size) {\n#ifndef HAVE_MALLOC_SIZE\n    void *realptr;\n#endif\n    size_t oldsize;\n    void *newptr;\n\n    if (ptr == NULL) return zmalloc(size);\n#ifdef HAVE_MALLOC_SIZE\n    oldsize = zmalloc_size(ptr);\n    newptr = realloc(ptr,size);\n    if (!newptr) zmalloc_oom_handler(size);\n\n    update_zmalloc_stat_free(oldsize);\n    update_zmalloc_stat_alloc(zmalloc_size(newptr));\n    return newptr;\n#else\n    realptr = (char*)ptr-PREFIX_SIZE;\n    oldsize = *((size_t*)realptr);\n    newptr = realloc(realptr,size+PREFIX_SIZE);\n    if (!newptr) zmalloc_oom_handler(size);\n\n    *((size_t*)newptr) = size;\n    update_zmalloc_stat_free(oldsize);\n    update_zmalloc_stat_alloc(size);\n    return (char*)newptr+PREFIX_SIZE;\n#endif\n}\n\n/* Provide zmalloc_size() for systems where this function is not provided by\n * malloc itself, given that in that case we store a header with this\n * information as the first bytes of every allocation. */\n#ifndef HAVE_MALLOC_SIZE\nsize_t zmalloc_size(void *ptr) {\n    void *realptr = (char*)ptr-PREFIX_SIZE;\n    size_t size = *((size_t*)realptr);\n    /* Assume at least that all the allocations are padded at sizeof(long) by\n     * the underlying allocator. */\n    if (size&(sizeof(long)-1)) size += sizeof(long)-(size&(sizeof(long)-1));\n    return size+PREFIX_SIZE;\n}\n#endif\n\nvoid zfree(void *ptr) {\n#ifndef HAVE_MALLOC_SIZE\n    void *realptr;\n    size_t oldsize;\n#endif\n\n    if (ptr == NULL) return;\n#ifdef HAVE_MALLOC_SIZE\n    update_zmalloc_stat_free(zmalloc_size(ptr));\n    free(ptr);\n#else\n    realptr = (char*)ptr-PREFIX_SIZE;\n    oldsize = *((size_t*)realptr);\n    update_zmalloc_stat_free(oldsize+PREFIX_SIZE);\n    free(realptr);\n#endif\n}\n\nchar *zstrdup(const char *s) {\n    size_t l = strlen(s)+1;\n    char *p = zmalloc(l);\n\n    memcpy(p,s,l);\n    return p;\n}\n\nsize_t zmalloc_used_memory(void) {\n    size_t um;\n\n    if (zmalloc_thread_safe) {\n#if defined(__ATOMIC_RELAXED) || defined(HAVE_ATOMIC)\n        um = update_zmalloc_stat_add(0);\n#else\n        pthread_mutex_lock(&used_memory_mutex);\n        um = used_memory;\n        pthread_mutex_unlock(&used_memory_mutex);\n#endif\n    }\n    else {\n        um = used_memory;\n    }\n\n    return um;\n}\n\nvoid zmalloc_enable_thread_safeness(void) {\n    zmalloc_thread_safe = 1;\n}\n\nvoid zmalloc_set_oom_handler(void (*oom_handler)(size_t)) {\n    zmalloc_oom_handler = oom_handler;\n}\n\n/* Get the RSS information in an OS-specific way.\n *\n * WARNING: the function zmalloc_get_rss() is not designed to be fast\n * and may not be called in the busy loops where Redis tries to release\n * memory expiring or swapping out objects.\n *\n * For this kind of \"fast RSS reporting\" usages use instead the\n * function RedisEstimateRSS() that is a much faster (and less precise)\n * version of the function. */\n\n#if defined(HAVE_PROC_STAT)\n#include <unistd.h>\n#include <sys/types.h>\n#include <sys/stat.h>\n#include <fcntl.h>\n\nsize_t zmalloc_get_rss(void) {\n    int page = sysconf(_SC_PAGESIZE);\n    size_t rss;\n    char buf[4096];\n    char filename[256];\n    int fd, count;\n    char *p, *x;\n\n    snprintf(filename,256,\"/proc/%d/stat\",getpid());\n    if ((fd = open(filename,O_RDONLY)) == -1) return 0;\n    if (read(fd,buf,4096) <= 0) {\n        close(fd);\n        return 0;\n    }\n    close(fd);\n\n    p = buf;\n    count = 23; /* RSS is the 24th field in /proc/<pid>/stat */\n    while(p && count--) {\n        p = strchr(p,' ');\n        if (p) p++;\n    }\n    if (!p) return 0;\n    x = strchr(p,' ');\n    if (!x) return 0;\n    *x = '\\0';\n\n    rss = strtoll(p,NULL,10);\n    rss *= page;\n    return rss;\n}\n#elif defined(HAVE_TASKINFO)\n#include <unistd.h>\n#include <stdio.h>\n#include <stdlib.h>\n#include <sys/types.h>\n#include <sys/sysctl.h>\n#include <mach/task.h>\n#include <mach/mach_init.h>\n\nsize_t zmalloc_get_rss(void) {\n    task_t task = MACH_PORT_NULL;\n    struct task_basic_info t_info;\n    mach_msg_type_number_t t_info_count = TASK_BASIC_INFO_COUNT;\n\n    if (task_for_pid(current_task(), getpid(), &task) != KERN_SUCCESS)\n        return 0;\n    task_info(task, TASK_BASIC_INFO, (task_info_t)&t_info, &t_info_count);\n\n    return t_info.resident_size;\n}\n#else\nsize_t zmalloc_get_rss(void) {\n    /* If we can't get the RSS in an OS-specific way for this system just\n     * return the memory usage we estimated in zmalloc()..\n     *\n     * Fragmentation will appear to be always 1 (no fragmentation)\n     * of course... */\n    return zmalloc_used_memory();\n}\n#endif\n\n/* Fragmentation = RSS / allocated-bytes */\nfloat zmalloc_get_fragmentation_ratio(size_t rss) {\n    return (float)rss/zmalloc_used_memory();\n}\n\n/* Get the sum of the specified field (converted form kb to bytes) in\n * /proc/self/smaps. The field must be specified with trailing \":\" as it\n * apperas in the smaps output.\n *\n * Example: zmalloc_get_smap_bytes_by_field(\"Rss:\");\n */\n#if defined(HAVE_PROC_SMAPS)\nsize_t zmalloc_get_smap_bytes_by_field(char *field) {\n    char line[1024];\n    size_t bytes = 0;\n    FILE *fp = fopen(\"/proc/self/smaps\",\"r\");\n    int flen = strlen(field);\n\n    if (!fp) return 0;\n    while(fgets(line,sizeof(line),fp) != NULL) {\n        if (strncmp(line,field,flen) == 0) {\n            char *p = strchr(line,'k');\n            if (p) {\n                *p = '\\0';\n                bytes += strtol(line+flen,NULL,10) * 1024;\n            }\n        }\n    }\n    fclose(fp);\n    return bytes;\n}\n#else\nsize_t zmalloc_get_smap_bytes_by_field(char *field) {\n    ((void) field);\n    return 0;\n}\n#endif\n\nsize_t zmalloc_get_private_dirty(void) {\n    return zmalloc_get_smap_bytes_by_field(\"Private_Dirty:\");\n}\n\n/* Returns the size of physical memory (RAM) in bytes.\n * It looks ugly, but this is the cleanest way to achive cross platform results.\n * Cleaned up from:\n *\n * http://nadeausoftware.com/articles/2012/09/c_c_tip_how_get_physical_memory_size_system\n *\n * Note that this function:\n * 1) Was released under the following CC attribution license:\n *    http://creativecommons.org/licenses/by/3.0/deed.en_US.\n * 2) Was originally implemented by David Robert Nadeau.\n * 3) Was modified for Redis by Matt Stancliff.\n * 4) This note exists in order to comply with the original license.\n */\nsize_t zmalloc_get_memory_size(void) {\n#if defined(__unix__) || defined(__unix) || defined(unix) || \\\n    (defined(__APPLE__) && defined(__MACH__))\n#if defined(CTL_HW) && (defined(HW_MEMSIZE) || defined(HW_PHYSMEM64))\n    int mib[2];\n    mib[0] = CTL_HW;\n#if defined(HW_MEMSIZE)\n    mib[1] = HW_MEMSIZE;            /* OSX. --------------------- */\n#elif defined(HW_PHYSMEM64)\n    mib[1] = HW_PHYSMEM64;          /* NetBSD, OpenBSD. --------- */\n#endif\n    int64_t size = 0;               /* 64-bit */\n    size_t len = sizeof(size);\n    if (sysctl( mib, 2, &size, &len, NULL, 0) == 0)\n        return (size_t)size;\n    return 0L;          /* Failed? */\n\n#elif defined(_SC_PHYS_PAGES) && defined(_SC_PAGESIZE)\n    /* FreeBSD, Linux, OpenBSD, and Solaris. -------------------- */\n    return (size_t)sysconf(_SC_PHYS_PAGES) * (size_t)sysconf(_SC_PAGESIZE);\n\n#elif defined(CTL_HW) && (defined(HW_PHYSMEM) || defined(HW_REALMEM))\n    /* DragonFly BSD, FreeBSD, NetBSD, OpenBSD, and OSX. -------- */\n    int mib[2];\n    mib[0] = CTL_HW;\n#if defined(HW_REALMEM)\n    mib[1] = HW_REALMEM;        /* FreeBSD. ----------------- */\n#elif defined(HW_PYSMEM)\n    mib[1] = HW_PHYSMEM;        /* Others. ------------------ */\n#endif\n    unsigned int size = 0;      /* 32-bit */\n    size_t len = sizeof(size);\n    if (sysctl(mib, 2, &size, &len, NULL, 0) == 0)\n        return (size_t)size;\n    return 0L;          /* Failed? */\n#endif /* sysctl and sysconf variants */\n\n#else\n    return 0L;          /* Unknown OS. */\n#endif\n}\n\n\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/src/zmalloc.h",
    "content": "/* zmalloc - total amount of allocated memory aware version of malloc()\n *\n * Copyright (c) 2009-2010, Salvatore Sanfilippo <antirez at gmail dot com>\n * All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions are met:\n *\n *   * Redistributions of source code must retain the above copyright notice,\n *     this list of conditions and the following disclaimer.\n *   * Redistributions in binary form must reproduce the above copyright\n *     notice, this list of conditions and the following disclaimer in the\n *     documentation and/or other materials provided with the distribution.\n *   * Neither the name of Redis nor the names of its contributors may be used\n *     to endorse or promote products derived from this software without\n *     specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\"\n * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\n * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE\n * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR\n * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF\n * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS\n * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN\n * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)\n * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE\n * POSSIBILITY OF SUCH DAMAGE.\n */\n\n#ifndef __ZMALLOC_H\n#define __ZMALLOC_H\n\n/* Double expansion needed for stringification of macro values. */\n#define __xstr(s) __str(s)\n#define __str(s) #s\n\n#if defined(USE_TCMALLOC)\n#define ZMALLOC_LIB (\"tcmalloc-\" __xstr(TC_VERSION_MAJOR) \".\" __xstr(TC_VERSION_MINOR))\n#include <google/tcmalloc.h>\n#if (TC_VERSION_MAJOR == 1 && TC_VERSION_MINOR >= 6) || (TC_VERSION_MAJOR > 1)\n#define HAVE_MALLOC_SIZE 1\n#define zmalloc_size(p) tc_malloc_size(p)\n#else\n#error \"Newer version of tcmalloc required\"\n#endif\n\n#elif defined(USE_JEMALLOC)\n#define ZMALLOC_LIB (\"jemalloc-\" __xstr(JEMALLOC_VERSION_MAJOR) \".\" __xstr(JEMALLOC_VERSION_MINOR) \".\" __xstr(JEMALLOC_VERSION_BUGFIX))\n#include <jemalloc/jemalloc.h>\n#if (JEMALLOC_VERSION_MAJOR == 2 && JEMALLOC_VERSION_MINOR >= 1) || (JEMALLOC_VERSION_MAJOR > 2)\n#define HAVE_MALLOC_SIZE 1\n#define zmalloc_size(p) je_malloc_usable_size(p)\n#else\n#error \"Newer version of jemalloc required\"\n#endif\n\n#elif defined(__APPLE__)\n#include <malloc/malloc.h>\n#define HAVE_MALLOC_SIZE 1\n#define zmalloc_size(p) malloc_size(p)\n#endif\n\n#ifndef ZMALLOC_LIB\n#define ZMALLOC_LIB \"libc\"\n#endif\n\nvoid *zmalloc(size_t size);\nvoid *zcalloc(size_t size);\nvoid *zrealloc(void *ptr, size_t size);\nvoid zfree(void *ptr);\nchar *zstrdup(const char *s);\nsize_t zmalloc_used_memory(void);\nvoid zmalloc_enable_thread_safeness(void);\nvoid zmalloc_set_oom_handler(void (*oom_handler)(size_t));\nfloat zmalloc_get_fragmentation_ratio(size_t rss);\nsize_t zmalloc_get_rss(void);\nsize_t zmalloc_get_private_dirty(void);\nsize_t zmalloc_get_smap_bytes_by_field(char *field);\nsize_t zmalloc_get_memory_size(void);\nvoid zlibc_free(void *ptr);\n\n#ifndef HAVE_MALLOC_SIZE\nsize_t zmalloc_size(void *ptr);\n#endif\n\n#endif /* __ZMALLOC_H */\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/tests/assets/default.conf",
    "content": "# Redis configuration for testing.\n\nnotify-keyspace-events KEA\ndaemonize no\npidfile /var/run/redis.pid\nport 6379\ntimeout 0\nbind 127.0.0.1\nloglevel verbose\nlogfile ''\ndatabases 16\nlatency-monitor-threshold 1\n\nsave 900 1\nsave 300 10\nsave 60 10000\n\nrdbcompression yes\ndbfilename dump.rdb\ndir ./\n\nslave-serve-stale-data yes\nappendonly no\nappendfsync everysec\nno-appendfsync-on-rewrite no\nactiverehashing yes\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/tests/cluster/cluster.tcl",
    "content": "# Cluster-specific test functions.\n#\n# Copyright (C) 2014 Salvatore Sanfilippo antirez@gmail.com\n# This software is released under the BSD License. See the COPYING file for\n# more information.\n\n# Returns a parsed CLUSTER NODES output as a list of dictionaries.\nproc get_cluster_nodes id {\n    set lines [split [R $id cluster nodes] \"\\r\\n\"]\n    set nodes {}\n    foreach l $lines {\n        set l [string trim $l]\n        if {$l eq {}} continue\n        set args [split $l]\n        set node [dict create \\\n            id [lindex $args 0] \\\n            addr [lindex $args 1] \\\n            flags [split [lindex $args 2] ,] \\\n            slaveof [lindex $args 3] \\\n            ping_sent [lindex $args 4] \\\n            pong_recv [lindex $args 5] \\\n            config_epoch [lindex $args 6] \\\n            linkstate [lindex $args 7] \\\n            slots [lrange $args 8 -1] \\\n        ]\n        lappend nodes $node\n    }\n    return $nodes\n}\n\n# Test node for flag.\nproc has_flag {node flag} {\n    expr {[lsearch -exact [dict get $node flags] $flag] != -1}\n}\n\n# Returns the parsed myself node entry as a dictionary.\nproc get_myself id {\n    set nodes [get_cluster_nodes $id]\n    foreach n $nodes {\n        if {[has_flag $n myself]} {return $n}\n    }\n    return {}\n}\n\n# Return the value of the specified CLUSTER INFO field.\nproc CI {n field} {\n    get_info_field [R $n cluster info] $field\n}\n\n# Assuming nodes are reest, this function performs slots allocation.\n# Only the first 'n' nodes are used.\nproc cluster_allocate_slots {n} {\n    set slot 16383\n    while {$slot >= 0} {\n        # Allocate successive slots to random nodes.\n        set node [randomInt $n]\n        lappend slots_$node $slot\n        incr slot -1\n    }\n    for {set j 0} {$j < $n} {incr j} {\n        R $j cluster addslots {*}[set slots_${j}]\n    }\n}\n\n# Check that cluster nodes agree about \"state\", or raise an error.\nproc assert_cluster_state {state} {\n    foreach_redis_id id {\n        if {[instance_is_killed redis $id]} continue\n        wait_for_condition 1000 50 {\n            [CI $id cluster_state] eq $state\n        } else {\n            fail \"Cluster node $id cluster_state:[CI $id cluster_state]\"\n        }\n    }\n}\n\n# Search the first node starting from ID $first that is not\n# already configured as a slave.\nproc cluster_find_available_slave {first} {\n    foreach_redis_id id {\n        if {$id < $first} continue\n        if {[instance_is_killed redis $id]} continue\n        set me [get_myself $id]\n        if {[dict get $me slaveof] eq {-}} {return $id}\n    }\n    fail \"No available slaves\"\n}\n\n# Add 'slaves' slaves to a cluster composed of 'masters' masters.\n# It assumes that masters are allocated sequentially from instance ID 0\n# to N-1.\nproc cluster_allocate_slaves {masters slaves} {\n    for {set j 0} {$j < $slaves} {incr j} {\n        set master_id [expr {$j % $masters}]\n        set slave_id [cluster_find_available_slave $masters]\n        set master_myself [get_myself $master_id]\n        R $slave_id cluster replicate [dict get $master_myself id]\n    }\n}\n\n# Create a cluster composed of the specified number of masters and slaves.\nproc create_cluster {masters slaves} {\n    cluster_allocate_slots $masters\n    if {$slaves} {\n        cluster_allocate_slaves $masters $slaves\n    }\n    assert_cluster_state ok\n}\n\n# Set the cluster node-timeout to all the reachalbe nodes.\nproc set_cluster_node_timeout {to} {\n    foreach_redis_id id {\n        catch {R $id CONFIG SET cluster-node-timeout $to}\n    }\n}\n\n# Check if the cluster is writable and readable. Use node \"id\"\n# as a starting point to talk with the cluster.\nproc cluster_write_test {id} {\n    set prefix [randstring 20 20 alpha]\n    set port [get_instance_attrib redis $id port]\n    set cluster [redis_cluster 127.0.0.1:$port]\n    for {set j 0} {$j < 100} {incr j} {\n        $cluster set key.$j $prefix.$j\n    }\n    for {set j 0} {$j < 100} {incr j} {\n        assert {[$cluster get key.$j] eq \"$prefix.$j\"}\n    }\n    $cluster close\n}\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/tests/cluster/run.tcl",
    "content": "# Cluster test suite. Copyright (C) 2014 Salvatore Sanfilippo antirez@gmail.com\n# This software is released under the BSD License. See the COPYING file for\n# more information.\n\ncd tests/cluster\nsource cluster.tcl\nsource ../instances.tcl\nsource ../../support/cluster.tcl ; # Redis Cluster client.\n\nset ::instances_count 20 ; # How many instances we use at max.\n\nproc main {} {\n    parse_options\n    spawn_instance redis $::redis_base_port $::instances_count {\n        \"cluster-enabled yes\"\n        \"appendonly yes\"\n    }\n    run_tests\n    cleanup\n    end_tests\n}\n\nif {[catch main e]} {\n    puts $::errorInfo\n    if {$::pause_on_error} pause_on_error\n    cleanup\n    exit 1\n}\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/tests/cluster/tests/00-base.tcl",
    "content": "# Check the basic monitoring and failover capabilities.\n\nsource \"../tests/includes/init-tests.tcl\"\n\nif {$::simulate_error} {\n    test \"This test will fail\" {\n        fail \"Simulated error\"\n    }\n}\n\ntest \"Different nodes have different IDs\" {\n    set ids {}\n    set numnodes 0\n    foreach_redis_id id {\n        incr numnodes\n        # Every node should just know itself.\n        set nodeid [dict get [get_myself $id] id]\n        assert {$nodeid ne {}}\n        lappend ids $nodeid\n    }\n    set numids [llength [lsort -unique $ids]]\n    assert {$numids == $numnodes}\n}\n\ntest \"It is possible to perform slot allocation\" {\n    cluster_allocate_slots 5\n}\n\ntest \"After the join, every node gets a different config epoch\" {\n    set trynum 60\n    while {[incr trynum -1] != 0} {\n        # We check that this condition is true for *all* the nodes.\n        set ok 1 ; # Will be set to 0 every time a node is not ok.\n        foreach_redis_id id {\n            set epochs {}\n            foreach n [get_cluster_nodes $id] {\n                lappend epochs [dict get $n config_epoch]\n            }\n            if {[lsort $epochs] != [lsort -unique $epochs]} {\n                set ok 0 ; # At least one collision!\n            }\n        }\n        if {$ok} break\n        after 1000\n        puts -nonewline .\n        flush stdout\n    }\n    if {$trynum == 0} {\n        fail \"Config epoch conflict resolution is not working.\"\n    }\n}\n\ntest \"Nodes should report cluster_state is ok now\" {\n    assert_cluster_state ok\n}\n\ntest \"It is possible to write and read from the cluster\" {\n    cluster_write_test 0\n}\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/tests/cluster/tests/01-faildet.tcl",
    "content": "# Check the basic monitoring and failover capabilities.\n\nsource \"../tests/includes/init-tests.tcl\"\n\ntest \"Create a 5 nodes cluster\" {\n    create_cluster 5 5\n}\n\ntest \"Cluster should start ok\" {\n    assert_cluster_state ok\n}\n\ntest \"Killing two slave nodes\" {\n    kill_instance redis 5\n    kill_instance redis 6\n}\n\ntest \"Cluster should be still up\" {\n    assert_cluster_state ok\n}\n\ntest \"Killing one master node\" {\n    kill_instance redis 0\n}\n\n# Note: the only slave of instance 0 is already down so no\n# failover is possible, that would change the state back to ok.\ntest \"Cluster should be down now\" {\n    assert_cluster_state fail\n}\n\ntest \"Restarting master node\" {\n    restart_instance redis 0\n}\n\ntest \"Cluster should be up again\" {\n    assert_cluster_state ok\n}\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/tests/cluster/tests/02-failover.tcl",
    "content": "# Check the basic monitoring and failover capabilities.\n\nsource \"../tests/includes/init-tests.tcl\"\n\ntest \"Create a 5 nodes cluster\" {\n    create_cluster 5 5\n}\n\ntest \"Cluster is up\" {\n    assert_cluster_state ok\n}\n\ntest \"Cluster is writable\" {\n    cluster_write_test 0\n}\n\ntest \"Instance #5 is a slave\" {\n    assert {[RI 5 role] eq {slave}}\n}\n\ntest \"Instance #5 synced with the master\" {\n    wait_for_condition 1000 50 {\n        [RI 5 master_link_status] eq {up}\n    } else {\n        fail \"Instance #5 master link status is not up\"\n    }\n}\n\nset current_epoch [CI 1 cluster_current_epoch]\n\ntest \"Killing one master node\" {\n    kill_instance redis 0\n}\n\ntest \"Wait for failover\" {\n    wait_for_condition 1000 50 {\n        [CI 1 cluster_current_epoch] > $current_epoch\n    } else {\n        fail \"No failover detected\"\n    }\n}\n\ntest \"Cluster should eventually be up again\" {\n    assert_cluster_state ok\n}\n\ntest \"Cluster is writable\" {\n    cluster_write_test 1\n}\n\ntest \"Instance #5 is now a master\" {\n    assert {[RI 5 role] eq {master}}\n}\n\ntest \"Restarting the previously killed master node\" {\n    restart_instance redis 0\n}\n\ntest \"Instance #0 gets converted into a slave\" {\n    wait_for_condition 1000 50 {\n        [RI 0 role] eq {slave}\n    } else {\n        fail \"Old master was not converted into slave\"\n    }\n}\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/tests/cluster/tests/03-failover-loop.tcl",
    "content": "# Failover stress test.\n# In this test a different node is killed in a loop for N\n# iterations. The test checks that certain properties\n# are preseved across iterations.\n\nsource \"../tests/includes/init-tests.tcl\"\n\ntest \"Create a 5 nodes cluster\" {\n    create_cluster 5 5\n}\n\ntest \"Cluster is up\" {\n    assert_cluster_state ok\n}\n\nset iterations 20\nset cluster [redis_cluster 127.0.0.1:[get_instance_attrib redis 0 port]]\n\nwhile {[incr iterations -1]} {\n    set tokill [randomInt 10]\n    set other [expr {($tokill+1)%10}] ; # Some other instance.\n    set key [randstring 20 20 alpha]\n    set val [randstring 20 20 alpha]\n    set role [RI $tokill role]\n    if {$role eq {master}} {\n        set slave {}\n        set myid [dict get [get_myself $tokill] id]\n        foreach_redis_id id {\n            if {$id == $tokill} continue\n            if {[dict get [get_myself $id] slaveof] eq $myid} {\n                set slave $id\n            }\n        }\n        if {$slave eq {}} {\n            fail \"Unable to retrieve slave's ID for master #$tokill\"\n        }\n    }\n\n    puts \"--- Iteration $iterations ---\"\n\n    if {$role eq {master}} {\n        test \"Wait for slave of #$tokill to sync\" {\n            wait_for_condition 1000 50 {\n                [string match {*state=online*} [RI $tokill slave0]]\n            } else {\n                fail \"Slave of node #$tokill is not ok\"\n            }\n        }\n        set slave_config_epoch [CI $slave cluster_my_epoch]\n    }\n\n    test \"Cluster is writable before failover\" {\n        for {set i 0} {$i < 100} {incr i} {\n            catch {$cluster set $key:$i $val:$i} err\n            assert {$err eq {OK}}\n        }\n        # Wait for the write to propagate to the slave if we\n        # are going to kill a master.\n        if {$role eq {master}} {\n            R $tokill wait 1 20000\n        }\n    }\n\n    test \"Killing node #$tokill\" {\n        kill_instance redis $tokill\n    }\n\n    if {$role eq {master}} {\n        test \"Wait failover by #$slave with old epoch $slave_config_epoch\" {\n            wait_for_condition 1000 50 {\n                [CI $slave cluster_my_epoch] > $slave_config_epoch\n            } else {\n                fail \"No failover detected, epoch is still [CI $slave cluster_my_epoch]\"\n            }\n        }\n    }\n\n    test \"Cluster should eventually be up again\" {\n        assert_cluster_state ok\n    }\n\n    test \"Cluster is writable again\" {\n        for {set i 0} {$i < 100} {incr i} {\n            catch {$cluster set $key:$i:2 $val:$i:2} err\n            assert {$err eq {OK}}\n        }\n    }\n\n    test \"Restarting node #$tokill\" {\n        restart_instance redis $tokill\n    }\n\n    test \"Instance #$tokill is now a slave\" {\n        wait_for_condition 1000 50 {\n            [RI $tokill role] eq {slave}\n        } else {\n            fail \"Restarted instance is not a slave\"\n        }\n    }\n\n    test \"We can read back the value we set before\" {\n        for {set i 0} {$i < 100} {incr i} {\n            catch {$cluster get $key:$i} err\n            assert {$err eq \"$val:$i\"}\n            catch {$cluster get $key:$i:2} err\n            assert {$err eq \"$val:$i:2\"}\n        }\n    }\n}\n\ntest \"Post condition: current_epoch >= my_epoch everywhere\" {\n    foreach_redis_id id {\n        assert {[CI $id cluster_current_epoch] >= [CI $id cluster_my_epoch]}\n    }\n}\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/tests/cluster/tests/04-resharding.tcl",
    "content": "# Failover stress test.\n# In this test a different node is killed in a loop for N\n# iterations. The test checks that certain properties\n# are preseved across iterations.\n\nsource \"../tests/includes/init-tests.tcl\"\n\ntest \"Create a 5 nodes cluster\" {\n    create_cluster 5 5\n}\n\ntest \"Cluster is up\" {\n    assert_cluster_state ok\n}\n\ntest \"Enable AOF in all the instances\" {\n    foreach_redis_id id {\n        R $id config set appendonly yes\n        # We use \"appendfsync no\" because it's fast but also guarantees that\n        # write(2) is performed before replying to client.\n        R $id config set appendfsync no\n    }\n\n    foreach_redis_id id {\n        wait_for_condition 1000 500 {\n            [RI $id aof_rewrite_in_progress] == 0 &&\n            [RI $id aof_enabled] == 1\n        } else {\n            fail \"Failed to enable AOF on instance #$id\"\n        }\n    }\n}\n\n# Return nno-zero if the specified PID is about a process still in execution,\n# otherwise 0 is returned.\nproc process_is_running {pid} {\n    # PS should return with an error if PID is non existing,\n    # and catch will return non-zero. We want to return non-zero if\n    # the PID exists, so we invert the return value with expr not operator.\n    expr {![catch {exec ps -p $pid}]}\n}\n\n# Our resharding test performs the following actions:\n#\n# - N commands are sent to the cluster in the course of the test.\n# - Every command selects a random key from key:0 to key:MAX-1.\n# - The operation RPUSH key <randomvalue> is perforemd.\n# - Tcl remembers into an array all the values pushed to each list.\n# - After N/2 commands, the resharding process is started in background.\n# - The test continues while the resharding is in progress.\n# - At the end of the test, we wait for the resharding process to stop.\n# - Finally the keys are checked to see if they contain the value they should.\n\nset numkeys 50000\nset numops 200000\nset cluster [redis_cluster 127.0.0.1:[get_instance_attrib redis 0 port]]\ncatch {unset content}\narray set content {}\nset tribpid {}\n\ntest \"Cluster consistency during live resharding\" {\n    for {set j 0} {$j < $numops} {incr j} {\n        # Trigger the resharding once we execute half the ops.\n        if {$tribpid ne {} &&\n            ($j % 10000) == 0 &&\n            ![process_is_running $tribpid]} {\n            set tribpid {}\n        }\n\n        if {$j >= $numops/2 && $tribpid eq {}} {\n            puts -nonewline \"...Starting resharding...\"\n            flush stdout\n            set target [dict get [get_myself [randomInt 5]] id]\n            set tribpid [lindex [exec \\\n                ../../../src/redis-trib.rb reshard \\\n                --from all \\\n                --to $target \\\n                --slots 100 \\\n                --yes \\\n                127.0.0.1:[get_instance_attrib redis 0 port] \\\n                | [info nameofexecutable] \\\n                ../tests/helpers/onlydots.tcl \\\n                &] 0]\n        }\n\n        # Write random data to random list.\n        set listid [randomInt $numkeys]\n        set key \"key:$listid\"\n        set ele [randomValue]\n        # We write both with Lua scripts and with plain commands.\n        # This way we are able to stress Lua -> Redis command invocation\n        # as well, that has tests to prevent Lua to write into wrong\n        # hash slots.\n        if {$listid % 2} {\n            $cluster rpush $key $ele\n        } else {\n            $cluster eval {redis.call(\"rpush\",KEYS[1],ARGV[1])} 1 $key $ele\n        }\n        lappend content($key) $ele\n\n        if {($j % 1000) == 0} {\n            puts -nonewline W; flush stdout\n        }\n    }\n\n    # Wait for the resharding process to end\n    wait_for_condition 1000 500 {\n        [process_is_running $tribpid] == 0\n    } else {\n        fail \"Resharding is not terminating after some time.\"\n    }\n\n}\n\ntest \"Verify $numkeys keys for consistency with logical content\" {\n    # Check that the Redis Cluster content matches our logical content.\n    foreach {key value} [array get content] {\n        assert {[$cluster lrange $key 0 -1] eq $value}\n    }\n}\n\ntest \"Crash and restart all the instances\" {\n    foreach_redis_id id {\n        kill_instance redis $id\n        restart_instance redis $id\n    }\n}\n\ntest \"Cluster should eventually be up again\" {\n    assert_cluster_state ok\n}\n\ntest \"Verify $numkeys keys after the crash & restart\" {\n    # Check that the Redis Cluster content matches our logical content.\n    foreach {key value} [array get content] {\n        assert {[$cluster lrange $key 0 -1] eq $value}\n    }\n}\n\ntest \"Disable AOF in all the instances\" {\n    foreach_redis_id id {\n        R $id config set appendonly no\n    }\n}\n\ntest \"Verify slaves consistency\" {\n    set verified_masters 0\n    foreach_redis_id id {\n        set role [R $id role]\n        lassign $role myrole myoffset slaves\n        if {$myrole eq {slave}} continue\n        set masterport [get_instance_attrib redis $id port]\n        set masterdigest [R $id debug digest]\n        foreach_redis_id sid {\n            set srole [R $sid role]\n            if {[lindex $srole 0] eq {master}} continue\n            if {[lindex $srole 2] != $masterport} continue\n            wait_for_condition 1000 500 {\n                [R $sid debug digest] eq $masterdigest\n            } else {\n                fail \"Master and slave data digest are different\"\n            }\n            incr verified_masters\n        }\n    }\n    assert {$verified_masters >= 5}\n}\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/tests/cluster/tests/05-slave-selection.tcl",
    "content": "# Slave selection test\n# Check the algorithm trying to pick the slave with the most complete history.\n\nsource \"../tests/includes/init-tests.tcl\"\n\n# Create a cluster with 5 master and 10 slaves, so that we have 2\n# slaves for each master.\ntest \"Create a 5 nodes cluster\" {\n    create_cluster 5 10\n}\n\ntest \"Cluster is up\" {\n    assert_cluster_state ok\n}\n\ntest \"The first master has actually two slaves\" {\n    assert {[llength [lindex [R 0 role] 2]] == 2}\n}\n\ntest {Slaves of #0 are instance #5 and #10 as expected} {\n    set port0 [get_instance_attrib redis 0 port]\n    assert {[lindex [R 5 role] 2] == $port0}\n    assert {[lindex [R 10 role] 2] == $port0}\n}\n\ntest \"Instance #5 and #10 synced with the master\" {\n    wait_for_condition 1000 50 {\n        [RI 5 master_link_status] eq {up} &&\n        [RI 10 master_link_status] eq {up}\n    } else {\n        fail \"Instance #5 or #10 master link status is not up\"\n    }\n}\n\nset cluster [redis_cluster 127.0.0.1:[get_instance_attrib redis 0 port]]\n\ntest \"Slaves are both able to receive and acknowledge writes\" {\n    for {set j 0} {$j < 100} {incr j} {\n        $cluster set $j $j\n    }\n    assert {[R 0 wait 2 60000] == 2}\n}\n\ntest \"Write data while slave #10 is paused and can't receive it\" {\n    # Stop the slave with a multi/exec transaction so that the master will\n    # be killed as soon as it can accept writes again.\n    R 10 multi\n    R 10 debug sleep 10\n    R 10 client kill 127.0.0.1:$port0\n    R 10 deferred 1\n    R 10 exec\n\n    # Write some data the slave can't receive.\n    for {set j 0} {$j < 100} {incr j} {\n        $cluster set $j $j\n    }\n\n    # Prevent the master from accepting new slaves.\n    # Use a large pause value since we'll kill it anyway.\n    R 0 CLIENT PAUSE 60000\n\n    # Wait for the slave to return available again\n    R 10 deferred 0\n    assert {[R 10 read] eq {OK OK}}\n\n    # Kill the master so that a reconnection will not be possible.\n    kill_instance redis 0\n}\n\ntest \"Wait for instance #5 (and not #10) to turn into a master\" {\n    wait_for_condition 1000 50 {\n        [RI 5 role] eq {master}\n    } else {\n        fail \"No failover detected\"\n    }\n}\n\ntest \"Wait for the node #10 to return alive before ending the test\" {\n    R 10 ping\n}\n\ntest \"Cluster should eventually be up again\" {\n    assert_cluster_state ok\n}\n\ntest \"Node #10 should eventually replicate node #5\" {\n    set port5 [get_instance_attrib redis 5 port]\n    wait_for_condition 1000 50 {\n        ([lindex [R 10 role] 2] == $port5) &&\n        ([lindex [R 10 role] 3] eq {connected})\n    } else {\n        fail \"#10 didn't became slave of #5\"\n    }\n}\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/tests/cluster/tests/06-slave-stop-cond.tcl",
    "content": "# Slave stop condition test\n# Check that if there is a disconnection time limit, the slave will not try\n# to failover its master.\n\nsource \"../tests/includes/init-tests.tcl\"\n\n# Create a cluster with 5 master and 5 slaves.\ntest \"Create a 5 nodes cluster\" {\n    create_cluster 5 5\n}\n\ntest \"Cluster is up\" {\n    assert_cluster_state ok\n}\n\ntest \"The first master has actually one slave\" {\n    assert {[llength [lindex [R 0 role] 2]] == 1}\n}\n\ntest {Slaves of #0 is instance #5 as expected} {\n    set port0 [get_instance_attrib redis 0 port]\n    assert {[lindex [R 5 role] 2] == $port0}\n}\n\ntest \"Instance #5 synced with the master\" {\n    wait_for_condition 1000 50 {\n        [RI 5 master_link_status] eq {up}\n    } else {\n        fail \"Instance #5 master link status is not up\"\n    }\n}\n\ntest \"Lower the slave validity factor of #5 to the value of 2\" {\n    assert {[R 5 config set cluster-slave-validity-factor 2] eq {OK}}\n}\n\ntest \"Break master-slave link and prevent further reconnections\" {\n    # Stop the slave with a multi/exec transaction so that the master will\n    # be killed as soon as it can accept writes again.\n    R 5 multi\n    R 5 client kill 127.0.0.1:$port0\n    # here we should sleep 6 or more seconds (node_timeout * slave_validity)\n    # but the actual validity time is actually incremented by the\n    # repl-ping-slave-period value which is 10 seconds by default. So we\n    # need to wait more than 16 seconds.\n    R 5 debug sleep 20\n    R 5 deferred 1\n    R 5 exec\n\n    # Prevent the master from accepting new slaves.\n    # Use a large pause value since we'll kill it anyway.\n    R 0 CLIENT PAUSE 60000\n\n    # Wait for the slave to return available again\n    R 5 deferred 0\n    assert {[R 5 read] eq {OK OK}}\n\n    # Kill the master so that a reconnection will not be possible.\n    kill_instance redis 0\n}\n\ntest \"Slave #5 is reachable and alive\" {\n    assert {[R 5 ping] eq {PONG}}\n}\n\ntest \"Slave #5 should not be able to failover\" {\n    after 10000\n    assert {[RI 5 role] eq {slave}}\n}\n\ntest \"Cluster should be down\" {\n    assert_cluster_state fail\n}\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/tests/cluster/tests/07-replica-migration.tcl",
    "content": "# Replica migration test.\n# Check that orphaned masters are joined by replicas of masters having\n# multiple replicas attached, according to the migration barrier settings.\n\nsource \"../tests/includes/init-tests.tcl\"\n\n# Create a cluster with 5 master and 10 slaves, so that we have 2\n# slaves for each master.\ntest \"Create a 5 nodes cluster\" {\n    create_cluster 5 10\n}\n\ntest \"Cluster is up\" {\n    assert_cluster_state ok\n}\n\ntest \"Each master should have two replicas attached\" {\n    foreach_redis_id id {\n        if {$id < 5} {\n            wait_for_condition 1000 50 {\n                [llength [lindex [R 0 role] 2]] == 2\n            } else {\n                fail \"Master #$id does not have 2 slaves as expected\"\n            }\n        }\n    }\n}\n\ntest \"Killing all the slaves of master #0 and #1\" {\n    kill_instance redis 5\n    kill_instance redis 10\n    kill_instance redis 6\n    kill_instance redis 11\n    after 4000\n}\n\nforeach_redis_id id {\n    if {$id < 5} {\n        test \"Master #$id should have at least one replica\" {\n            wait_for_condition 1000 50 {\n                [llength [lindex [R $id role] 2]] >= 1\n            } else {\n                fail \"Master #$id has no replicas\"\n            }\n        }\n    }\n}\n\n# Now test the migration to a master which used to be a slave, after\n# a failver.\n\nsource \"../tests/includes/init-tests.tcl\"\n\n# Create a cluster with 5 master and 10 slaves, so that we have 2\n# slaves for each master.\ntest \"Create a 5 nodes cluster\" {\n    create_cluster 5 10\n}\n\ntest \"Cluster is up\" {\n    assert_cluster_state ok\n}\n\ntest \"Kill slave #7 of master #2. Only slave left is #12 now\" {\n    kill_instance redis 7\n}\n\nset current_epoch [CI 1 cluster_current_epoch]\n\ntest \"Killing master node #2, #12 should failover\" {\n    kill_instance redis 2\n}\n\ntest \"Wait for failover\" {\n    wait_for_condition 1000 50 {\n        [CI 1 cluster_current_epoch] > $current_epoch\n    } else {\n        fail \"No failover detected\"\n    }\n}\n\ntest \"Cluster should eventually be up again\" {\n    assert_cluster_state ok\n}\n\ntest \"Cluster is writable\" {\n    cluster_write_test 1\n}\n\ntest \"Instance 12 is now a master without slaves\" {\n    assert {[RI 12 role] eq {master}}\n}\n\n# The remaining instance is now without slaves. Some other slave\n# should migrate to it.\n\ntest \"Master #12 should get at least one migrated replica\" {\n    wait_for_condition 1000 50 {\n        [llength [lindex [R 12 role] 2]] >= 1\n    } else {\n        fail \"Master #12 has no replicas\"\n    }\n}\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/tests/cluster/tests/08-update-msg.tcl",
    "content": "# Test UPDATE messages sent by other nodes when the currently authorirative\n# master is unavaialble. The test is performed in the following steps:\n#\n# 1) Master goes down.\n# 2) Slave failover and becomes new master.\n# 3) New master is partitoned away.\n# 4) Old master returns.\n# 5) At this point we expect the old master to turn into a slave ASAP because\n#    of the UPDATE messages it will receive from the other nodes when its\n#    configuration will be found to be outdated.\n\nsource \"../tests/includes/init-tests.tcl\"\n\ntest \"Create a 5 nodes cluster\" {\n    create_cluster 5 5\n}\n\ntest \"Cluster is up\" {\n    assert_cluster_state ok\n}\n\ntest \"Cluster is writable\" {\n    cluster_write_test 0\n}\n\ntest \"Instance #5 is a slave\" {\n    assert {[RI 5 role] eq {slave}}\n}\n\ntest \"Instance #5 synced with the master\" {\n    wait_for_condition 1000 50 {\n        [RI 5 master_link_status] eq {up}\n    } else {\n        fail \"Instance #5 master link status is not up\"\n    }\n}\n\nset current_epoch [CI 1 cluster_current_epoch]\n\ntest \"Killing one master node\" {\n    kill_instance redis 0\n}\n\ntest \"Wait for failover\" {\n    wait_for_condition 1000 50 {\n        [CI 1 cluster_current_epoch] > $current_epoch\n    } else {\n        fail \"No failover detected\"\n    }\n}\n\ntest \"Cluster should eventually be up again\" {\n    assert_cluster_state ok\n}\n\ntest \"Cluster is writable\" {\n    cluster_write_test 1\n}\n\ntest \"Instance #5 is now a master\" {\n    assert {[RI 5 role] eq {master}}\n}\n\ntest \"Killing the new master #5\" {\n    kill_instance redis 5\n}\n\ntest \"Cluster should be down now\" {\n    assert_cluster_state fail\n}\n\ntest \"Restarting the old master node\" {\n    restart_instance redis 0\n}\n\ntest \"Instance #0 gets converted into a slave\" {\n    wait_for_condition 1000 50 {\n        [RI 0 role] eq {slave}\n    } else {\n        fail \"Old master was not converted into slave\"\n    }\n}\n\ntest \"Restarting the new master node\" {\n    restart_instance redis 5\n}\n\ntest \"Cluster is up again\" {\n    assert_cluster_state ok\n}\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/tests/cluster/tests/09-pubsub.tcl",
    "content": "# Test PUBLISH propagation across the cluster.\n\nsource \"../tests/includes/init-tests.tcl\"\n\ntest \"Create a 5 nodes cluster\" {\n    create_cluster 5 5\n}\n\nproc test_cluster_publish {instance instances} {\n    # Subscribe all the instances but the one we use to send.\n    for {set j 0} {$j < $instances} {incr j} {\n        if {$j != $instance} {\n            R $j deferred 1\n            R $j subscribe testchannel\n            R $j read; # Read the subscribe reply\n        }\n    }\n\n    set data [randomValue]\n    R $instance PUBLISH testchannel $data\n\n    # Read the message back from all the nodes.\n    for {set j 0} {$j < $instances} {incr j} {\n        if {$j != $instance} {\n            set msg [R $j read]\n            assert {$data eq [lindex $msg 2]}\n            R $j unsubscribe testchannel\n            R $j read; # Read the unsubscribe reply\n            R $j deferred 0\n        }\n    }\n}\n\ntest \"Test publishing to master\" {\n    test_cluster_publish 0 10\n}\n\ntest \"Test publishing to slave\" {\n    test_cluster_publish 5 10\n}\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/tests/cluster/tests/10-manual-failover.tcl",
    "content": "# Check the manual failover\n\nsource \"../tests/includes/init-tests.tcl\"\n\ntest \"Create a 5 nodes cluster\" {\n    create_cluster 5 5\n}\n\ntest \"Cluster is up\" {\n    assert_cluster_state ok\n}\n\ntest \"Cluster is writable\" {\n    cluster_write_test 0\n}\n\ntest \"Instance #5 is a slave\" {\n    assert {[RI 5 role] eq {slave}}\n}\n\ntest \"Instance #5 synced with the master\" {\n    wait_for_condition 1000 50 {\n        [RI 5 master_link_status] eq {up}\n    } else {\n        fail \"Instance #5 master link status is not up\"\n    }\n}\n\nset current_epoch [CI 1 cluster_current_epoch]\n\nset numkeys 50000\nset numops 10000\nset cluster [redis_cluster 127.0.0.1:[get_instance_attrib redis 0 port]]\ncatch {unset content}\narray set content {}\n\ntest \"Send CLUSTER FAILOVER to #5, during load\" {\n    for {set j 0} {$j < $numops} {incr j} {\n        # Write random data to random list.\n        set listid [randomInt $numkeys]\n        set key \"key:$listid\"\n        set ele [randomValue]\n        # We write both with Lua scripts and with plain commands.\n        # This way we are able to stress Lua -> Redis command invocation\n        # as well, that has tests to prevent Lua to write into wrong\n        # hash slots.\n        if {$listid % 2} {\n            $cluster rpush $key $ele\n        } else {\n           $cluster eval {redis.call(\"rpush\",KEYS[1],ARGV[1])} 1 $key $ele\n        }\n        lappend content($key) $ele\n\n        if {($j % 1000) == 0} {\n            puts -nonewline W; flush stdout\n        }\n\n        if {$j == $numops/2} {R 5 cluster failover}\n    }\n}\n\ntest \"Wait for failover\" {\n    wait_for_condition 1000 50 {\n        [CI 1 cluster_current_epoch] > $current_epoch\n    } else {\n        fail \"No failover detected\"\n    }\n}\n\ntest \"Cluster should eventually be up again\" {\n    assert_cluster_state ok\n}\n\ntest \"Cluster is writable\" {\n    cluster_write_test 1\n}\n\ntest \"Instance #5 is now a master\" {\n    assert {[RI 5 role] eq {master}}\n}\n\ntest \"Verify $numkeys keys for consistency with logical content\" {\n    # Check that the Redis Cluster content matches our logical content.\n    foreach {key value} [array get content] {\n        assert {[$cluster lrange $key 0 -1] eq $value}\n    }\n}\n\ntest \"Instance #0 gets converted into a slave\" {\n    wait_for_condition 1000 50 {\n        [RI 0 role] eq {slave}\n    } else {\n        fail \"Old master was not converted into slave\"\n    }\n}\n\n## Check that manual failover does not happen if we can't talk with the master.\n\nsource \"../tests/includes/init-tests.tcl\"\n\ntest \"Create a 5 nodes cluster\" {\n    create_cluster 5 5\n}\n\ntest \"Cluster is up\" {\n    assert_cluster_state ok\n}\n\ntest \"Cluster is writable\" {\n    cluster_write_test 0\n}\n\ntest \"Instance #5 is a slave\" {\n    assert {[RI 5 role] eq {slave}}\n}\n\ntest \"Instance #5 synced with the master\" {\n    wait_for_condition 1000 50 {\n        [RI 5 master_link_status] eq {up}\n    } else {\n        fail \"Instance #5 master link status is not up\"\n    }\n}\n\ntest \"Make instance #0 unreachable without killing it\" {\n    R 0 deferred 1\n    R 0 DEBUG SLEEP 10\n}\n\ntest \"Send CLUSTER FAILOVER to instance #5\" {\n    R 5 cluster failover\n}\n\ntest \"Instance #5 is still a slave after some time (no failover)\" {\n    after 5000\n    assert {[RI 5 role] eq {master}}\n}\n\ntest \"Wait for instance #0 to return back alive\" {\n    R 0 deferred 0\n    assert {[R 0 read] eq {OK}}\n}\n\n## Check with \"force\" failover happens anyway.\n\nsource \"../tests/includes/init-tests.tcl\"\n\ntest \"Create a 5 nodes cluster\" {\n    create_cluster 5 5\n}\n\ntest \"Cluster is up\" {\n    assert_cluster_state ok\n}\n\ntest \"Cluster is writable\" {\n    cluster_write_test 0\n}\n\ntest \"Instance #5 is a slave\" {\n    assert {[RI 5 role] eq {slave}}\n}\n\ntest \"Instance #5 synced with the master\" {\n    wait_for_condition 1000 50 {\n        [RI 5 master_link_status] eq {up}\n    } else {\n        fail \"Instance #5 master link status is not up\"\n    }\n}\n\ntest \"Make instance #0 unreachable without killing it\" {\n    R 0 deferred 1\n    R 0 DEBUG SLEEP 10\n}\n\ntest \"Send CLUSTER FAILOVER to instance #5\" {\n    R 5 cluster failover force\n}\n\ntest \"Instance #5 is a master after some time\" {\n    wait_for_condition 1000 50 {\n        [RI 5 role] eq {master}\n    } else {\n        fail \"Instance #5 is not a master after some time regardless of FORCE\"\n    }\n}\n\ntest \"Wait for instance #0 to return back alive\" {\n    R 0 deferred 0\n    assert {[R 0 read] eq {OK}}\n}\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/tests/cluster/tests/11-manual-takeover.tcl",
    "content": "# Manual takeover test\n\nsource \"../tests/includes/init-tests.tcl\"\n\ntest \"Create a 5 nodes cluster\" {\n    create_cluster 5 5\n}\n\ntest \"Cluster is up\" {\n    assert_cluster_state ok\n}\n\ntest \"Cluster is writable\" {\n    cluster_write_test 0\n}\n\ntest \"Killing majority of master nodes\" {\n    kill_instance redis 0\n    kill_instance redis 1\n    kill_instance redis 2\n}\n\ntest \"Cluster should eventually be down\" {\n    assert_cluster_state fail\n}\n\ntest \"Use takeover to bring slaves back\" {\n    R 5 cluster failover takeover\n    R 6 cluster failover takeover\n    R 7 cluster failover takeover\n}\n\ntest \"Cluster should eventually be up again\" {\n    assert_cluster_state ok\n}\n\ntest \"Cluster is writable\" {\n    cluster_write_test 4\n}\n\ntest \"Instance #5, #6, #7 are now masters\" {\n    assert {[RI 5 role] eq {master}}\n    assert {[RI 6 role] eq {master}}\n    assert {[RI 7 role] eq {master}}\n}\n\ntest \"Restarting the previously killed master nodes\" {\n    restart_instance redis 0\n    restart_instance redis 1\n    restart_instance redis 2\n}\n\ntest \"Instance #0, #1, #2 gets converted into a slaves\" {\n    wait_for_condition 1000 50 {\n        [RI 0 role] eq {slave} && [RI 1 role] eq {slave} && [RI 2 role] eq {slave}\n    } else {\n        fail \"Old masters not converted into slaves\"\n    }\n}\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/tests/cluster/tests/12-replica-migration-2.tcl",
    "content": "# Replica migration test #2.\n#\n# Check that the status of master that can be targeted by replica migration\n# is acquired again, after being getting slots again, in a cluster where the\n# other masters have slaves.\n\nsource \"../tests/includes/init-tests.tcl\"\n\n# Create a cluster with 5 master and 15 slaves, to make sure there are no\n# empty masters and make rebalancing simpler to handle during the test.\ntest \"Create a 5 nodes cluster\" {\n    create_cluster 5 15\n}\n\ntest \"Cluster is up\" {\n    assert_cluster_state ok\n}\n\ntest \"Each master should have at least two replicas attached\" {\n    foreach_redis_id id {\n        if {$id < 5} {\n            wait_for_condition 1000 50 {\n                [llength [lindex [R 0 role] 2]] >= 2\n            } else {\n                fail \"Master #$id does not have 2 slaves as expected\"\n            }\n        }\n    }\n}\n\nset master0_id [dict get [get_myself 0] id]\ntest \"Resharding all the master #0 slots away from it\" {\n    set output [exec \\\n        ../../../src/redis-trib.rb rebalance \\\n        --weight ${master0_id}=0 \\\n        127.0.0.1:[get_instance_attrib redis 0 port] >@ stdout]\n}\n\ntest \"Master #0 should lose its replicas\" {\n    wait_for_condition 1000 50 {\n        [llength [lindex [R 0 role] 2]] == 0\n    } else {\n        fail \"Master #0 still has replicas\"\n    }\n}\n\ntest \"Resharding back some slot to master #0\" {\n    # Wait for the cluster config to propagate before attempting a\n    # new resharding.\n    after 10000\n    set output [exec \\\n        ../../../src/redis-trib.rb rebalance \\\n        --weight ${master0_id}=.01 \\\n        --use-empty-masters \\\n        127.0.0.1:[get_instance_attrib redis 0 port] >@ stdout]\n}\n\ntest \"Master #0 should re-acquire one or more replicas\" {\n    wait_for_condition 1000 50 {\n        [llength [lindex [R 0 role] 2]] >= 1\n    } else {\n        fail \"Master #0 has no has replicas\"\n    }\n}\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/tests/cluster/tests/helpers/onlydots.tcl",
    "content": "# Read the standard input and only shows dots in the output, filtering out\n# all the other characters. Designed to avoid bufferization so that when\n# we get the output of redis-trib and want to show just the dots, we'll see\n# the dots as soon as redis-trib will output them.\n\nfconfigure stdin -buffering none\n\nwhile 1 {\n    set c [read stdin 1]\n    if {$c eq {}} {\n        exit 0; # EOF\n    } elseif {$c eq {.}} {\n        puts -nonewline .\n        flush stdout\n    }\n}\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/tests/cluster/tests/includes/init-tests.tcl",
    "content": "# Initialization tests -- most units will start including this.\n\ntest \"(init) Restart killed instances\" {\n    foreach type {redis} {\n        foreach_${type}_id id {\n            if {[get_instance_attrib $type $id pid] == -1} {\n                puts -nonewline \"$type/$id \"\n                flush stdout\n                restart_instance $type $id\n            }\n        }\n    }\n}\n\ntest \"Cluster nodes are reachable\" {\n    foreach_redis_id id {\n        # Every node should be reachable.\n        wait_for_condition 1000 50 {\n            ([catch {R $id ping} ping_reply] == 0) &&\n            ($ping_reply eq {PONG})\n        } else {\n            catch {R $id ping} err\n            fail \"Node #$id keeps replying '$err' to PING.\"\n        }\n    }\n}\n\ntest \"Cluster nodes hard reset\" {\n    foreach_redis_id id {\n        if {$::valgrind} {\n            set node_timeout 10000\n        } else {\n            set node_timeout 3000\n        }\n        catch {R $id flushall} ; # May fail for readonly slaves.\n        R $id MULTI\n        R $id cluster reset hard\n        R $id cluster set-config-epoch [expr {$id+1}]\n        R $id EXEC\n        R $id config set cluster-node-timeout $node_timeout\n        R $id config set cluster-slave-validity-factor 10\n        R $id config rewrite\n    }\n}\n\ntest \"Cluster Join and auto-discovery test\" {\n    # Join node 0 with 1, 1 with 2, ... and so forth.\n    # If auto-discovery works all nodes will know every other node\n    # eventually.\n    set ids {}\n    foreach_redis_id id {lappend ids $id}\n    for {set j 0} {$j < [expr [llength $ids]-1]} {incr j} {\n        set a [lindex $ids $j]\n        set b [lindex $ids [expr $j+1]]\n        set b_port [get_instance_attrib redis $b port]\n        R $a cluster meet 127.0.0.1 $b_port\n    }\n\n    foreach_redis_id id {\n        wait_for_condition 1000 50 {\n            [llength [get_cluster_nodes $id]] == [llength $ids]\n        } else {\n            fail \"Cluster failed to join into a full mesh.\"\n        }\n    }\n}\n\ntest \"Before slots allocation, all nodes report cluster failure\" {\n    assert_cluster_state fail\n}\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/tests/cluster/tmp/.gitignore",
    "content": "redis_*\nsentinel_*\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/tests/helpers/bg_complex_data.tcl",
    "content": "source tests/support/redis.tcl\nsource tests/support/util.tcl\n\nproc bg_complex_data {host port db ops} {\n    set r [redis $host $port]\n    $r select $db\n    createComplexDataset $r $ops\n}\n\nbg_complex_data [lindex $argv 0] [lindex $argv 1] [lindex $argv 2] [lindex $argv 3]\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/tests/helpers/gen_write_load.tcl",
    "content": "source tests/support/redis.tcl\n\nproc gen_write_load {host port seconds} {\n    set start_time [clock seconds]\n    set r [redis $host $port 1]\n    $r select 9\n    while 1 {\n        $r set [expr rand()] [expr rand()]\n        if {[clock seconds]-$start_time > $seconds} {\n            exit 0\n        }\n    }\n}\n\ngen_write_load [lindex $argv 0] [lindex $argv 1] [lindex $argv 2]\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/tests/instances.tcl",
    "content": "# Multi-instance test framework.\n# This is used in order to test Sentinel and Redis Cluster, and provides\n# basic capabilities for spawning and handling N parallel Redis / Sentinel\n# instances.\n#\n# Copyright (C) 2014 Salvatore Sanfilippo antirez@gmail.com\n# This software is released under the BSD License. See the COPYING file for\n# more information.\n\npackage require Tcl 8.5\n\nset tcl_precision 17\nsource ../support/redis.tcl\nsource ../support/util.tcl\nsource ../support/server.tcl\nsource ../support/test.tcl\n\nset ::verbose 0\nset ::valgrind 0\nset ::pause_on_error 0\nset ::simulate_error 0\nset ::failed 0\nset ::sentinel_instances {}\nset ::redis_instances {}\nset ::sentinel_base_port 20000\nset ::redis_base_port 30000\nset ::pids {} ; # We kill everything at exit\nset ::dirs {} ; # We remove all the temp dirs at exit\nset ::run_matching {} ; # If non empty, only tests matching pattern are run.\n\nif {[catch {cd tmp}]} {\n    puts \"tmp directory not found.\"\n    puts \"Please run this test from the Redis source root.\"\n    exit 1\n}\n\n# Execute the specified instance of the server specified by 'type', using\n# the provided configuration file. Returns the PID of the process.\nproc exec_instance {type cfgfile} {\n    if {$type eq \"redis\"} {\n        set prgname redis-server\n    } elseif {$type eq \"sentinel\"} {\n        set prgname redis-sentinel\n    } else {\n        error \"Unknown instance type.\"\n    }\n\n    if {$::valgrind} {\n        set pid [exec valgrind --track-origins=yes --suppressions=../../../src/valgrind.sup --show-reachable=no --show-possibly-lost=no --leak-check=full ../../../src/${prgname} $cfgfile &]\n    } else {\n        set pid [exec ../../../src/${prgname} $cfgfile &]\n    }\n    return $pid\n}\n\n# Spawn a redis or sentinel instance, depending on 'type'.\nproc spawn_instance {type base_port count {conf {}}} {\n    for {set j 0} {$j < $count} {incr j} {\n        set port [find_available_port $base_port]\n        incr base_port\n        puts \"Starting $type #$j at port $port\"\n\n        # Create a directory for this instance.\n        set dirname \"${type}_${j}\"\n        lappend ::dirs $dirname\n        catch {exec rm -rf $dirname}\n        file mkdir $dirname\n\n        # Write the instance config file.\n        set cfgfile [file join $dirname $type.conf]\n        set cfg [open $cfgfile w]\n        puts $cfg \"port $port\"\n        puts $cfg \"dir ./$dirname\"\n        puts $cfg \"logfile log.txt\"\n        # Add additional config files\n        foreach directive $conf {\n            puts $cfg $directive\n        }\n        close $cfg\n\n        # Finally exec it and remember the pid for later cleanup.\n        set pid [exec_instance $type $cfgfile]\n        lappend ::pids $pid\n\n        # Check availability\n        if {[server_is_up 127.0.0.1 $port 100] == 0} {\n            abort_sentinel_test \"Problems starting $type #$j: ping timeout\"\n        }\n\n        # Push the instance into the right list\n        set link [redis 127.0.0.1 $port]\n        $link reconnect 1\n        lappend ::${type}_instances [list \\\n            pid $pid \\\n            host 127.0.0.1 \\\n            port $port \\\n            link $link \\\n        ]\n    }\n}\n\nproc log_crashes {} {\n    set start_pattern {*REDIS BUG REPORT START*}\n    set logs [glob */log.txt]\n    foreach log $logs {\n        set fd [open $log]\n        set found 0\n        while {[gets $fd line] >= 0} {\n            if {[string match $start_pattern $line]} {\n                puts \"\\n*** Crash report found in $log ***\"\n                set found 1\n            }\n            if {$found} {puts $line}\n        }\n    }\n}\n\nproc cleanup {} {\n    puts \"Cleaning up...\"\n    log_crashes\n    foreach pid $::pids {\n        catch {exec kill -9 $pid}\n    }\n    foreach dir $::dirs {\n        catch {exec rm -rf $dir}\n    }\n}\n\nproc abort_sentinel_test msg {\n    incr ::failed\n    puts \"WARNING: Aborting the test.\"\n    puts \">>>>>>>> $msg\"\n    if {$::pause_on_error} pause_on_error\n    cleanup\n    exit 1\n}\n\nproc parse_options {} {\n    for {set j 0} {$j < [llength $::argv]} {incr j} {\n        set opt [lindex $::argv $j]\n        set val [lindex $::argv [expr $j+1]]\n        if {$opt eq \"--single\"} {\n            incr j\n            set ::run_matching \"*${val}*\"\n        } elseif {$opt eq \"--pause-on-error\"} {\n            set ::pause_on_error 1\n        } elseif {$opt eq \"--fail\"} {\n            set ::simulate_error 1\n        } elseif {$opt eq {--valgrind}} {\n            set ::valgrind 1\n        } elseif {$opt eq \"--help\"} {\n            puts \"Hello, I'm sentinel.tcl and I run Sentinel unit tests.\"\n            puts \"\\nOptions:\"\n            puts \"--single <pattern>      Only runs tests specified by pattern.\"\n            puts \"--pause-on-error        Pause for manual inspection on error.\"\n            puts \"--fail                  Simulate a test failure.\"\n            puts \"--valgrind              Run with valgrind.\"\n            puts \"--help                  Shows this help.\"\n            exit 0\n        } else {\n            puts \"Unknown option $opt\"\n            exit 1\n        }\n    }\n}\n\n# If --pause-on-error option was passed at startup this function is called\n# on error in order to give the developer a chance to understand more about\n# the error condition while the instances are still running.\nproc pause_on_error {} {\n    puts \"\"\n    puts [colorstr yellow \"*** Please inspect the error now ***\"]\n    puts \"\\nType \\\"continue\\\" to resume the test, \\\"help\\\" for help screen.\\n\"\n    while 1 {\n        puts -nonewline \"> \"\n        flush stdout\n        set line [gets stdin]\n        set argv [split $line \" \"]\n        set cmd [lindex $argv 0]\n        if {$cmd eq {continue}} {\n            break\n        } elseif {$cmd eq {show-redis-logs}} {\n            set count 10\n            if {[lindex $argv 1] ne {}} {set count [lindex $argv 1]}\n            foreach_redis_id id {\n                puts \"=== REDIS $id ====\"\n                puts [exec tail -$count redis_$id/log.txt]\n                puts \"---------------------\\n\"\n            }\n        } elseif {$cmd eq {show-sentinel-logs}} {\n            set count 10\n            if {[lindex $argv 1] ne {}} {set count [lindex $argv 1]}\n            foreach_sentinel_id id {\n                puts \"=== SENTINEL $id ====\"\n                puts [exec tail -$count sentinel_$id/log.txt]\n                puts \"---------------------\\n\"\n            }\n        } elseif {$cmd eq {ls}} {\n            foreach_redis_id id {\n                puts -nonewline \"Redis $id\"\n                set errcode [catch {\n                    set str {}\n                    append str \"@[RI $id tcp_port]: \"\n                    append str \"[RI $id role] \"\n                    if {[RI $id role] eq {slave}} {\n                        append str \"[RI $id master_host]:[RI $id master_port]\"\n                    }\n                    set str\n                } retval]\n                if {$errcode} {\n                    puts \" -- $retval\"\n                } else {\n                    puts $retval\n                }\n            }\n            foreach_sentinel_id id {\n                puts -nonewline \"Sentinel $id\"\n                set errcode [catch {\n                    set str {}\n                    append str \"@[SI $id tcp_port]: \"\n                    append str \"[join [S $id sentinel get-master-addr-by-name mymaster]]\"\n                    set str\n                } retval]\n                if {$errcode} {\n                    puts \" -- $retval\"\n                } else {\n                    puts $retval\n                }\n            }\n        } elseif {$cmd eq {help}} {\n            puts \"ls                     List Sentinel and Redis instances.\"\n            puts \"show-sentinel-logs \\[N\\] Show latest N lines of logs.\"\n            puts \"show-redis-logs \\[N\\]    Show latest N lines of logs.\"\n            puts \"S <id> cmd ... arg     Call command in Sentinel <id>.\"\n            puts \"R <id> cmd ... arg     Call command in Redis <id>.\"\n            puts \"SI <id> <field>        Show Sentinel <id> INFO <field>.\"\n            puts \"RI <id> <field>        Show Sentinel <id> INFO <field>.\"\n            puts \"continue               Resume test.\"\n        } else {\n            set errcode [catch {eval $line} retval]\n            if {$retval ne {}} {puts \"$retval\"}\n        }\n    }\n}\n\n# We redefine 'test' as for Sentinel we don't use the server-client\n# architecture for the test, everything is sequential.\nproc test {descr code} {\n    set ts [clock format [clock seconds] -format %H:%M:%S]\n    puts -nonewline \"$ts> $descr: \"\n    flush stdout\n\n    if {[catch {set retval [uplevel 1 $code]} error]} {\n        incr ::failed\n        if {[string match \"assertion:*\" $error]} {\n            set msg [string range $error 10 end]\n            puts [colorstr red $msg]\n            if {$::pause_on_error} pause_on_error\n            puts \"(Jumping to next unit after error)\"\n            return -code continue\n        } else {\n            # Re-raise, let handler up the stack take care of this.\n            error $error $::errorInfo\n        }\n    } else {\n        puts [colorstr green OK]\n    }\n}\n\n# Check memory leaks when running on OSX using the \"leaks\" utility.\nproc check_leaks instance_types {\n    if {[string match {*Darwin*} [exec uname -a]]} {\n        puts -nonewline \"Testing for memory leaks...\"; flush stdout\n        foreach type $instance_types {\n            foreach_instance_id [set ::${type}_instances] id {\n                if {[instance_is_killed $type $id]} continue\n                set pid [get_instance_attrib $type $id pid]\n                set output {0 leaks}\n                catch {exec leaks $pid} output\n                if {[string match {*process does not exist*} $output] ||\n                    [string match {*cannot examine*} $output]} {\n                    # In a few tests we kill the server process.\n                    set output \"0 leaks\"\n                } else {\n                    puts -nonewline \"$type/$pid \"\n                    flush stdout\n                }\n                if {![string match {*0 leaks*} $output]} {\n                    puts [colorstr red \"=== MEMORY LEAK DETECTED ===\"]\n                    puts \"Instance type $type, ID $id:\"\n                    puts $output\n                    puts \"===\"\n                    incr ::failed\n                }\n            }\n        }\n        puts \"\"\n    }\n}\n\n# Execute all the units inside the 'tests' directory.\nproc run_tests {} {\n    set tests [lsort [glob ../tests/*]]\n    foreach test $tests {\n        if {$::run_matching ne {} && [string match $::run_matching $test] == 0} {\n            continue\n        }\n        if {[file isdirectory $test]} continue\n        puts [colorstr yellow \"Testing unit: [lindex [file split $test] end]\"]\n        source $test\n        check_leaks {redis sentinel}\n    }\n}\n\n# Print a message and exists with 0 / 1 according to zero or more failures.\nproc end_tests {} {\n    if {$::failed == 0} {\n        puts \"GOOD! No errors.\"\n        exit 0\n    } else {\n        puts \"WARNING $::failed tests faield.\"\n        exit 1\n    }\n}\n\n# The \"S\" command is used to interact with the N-th Sentinel.\n# The general form is:\n#\n# S <sentinel-id> command arg arg arg ...\n#\n# Example to ping the Sentinel 0 (first instance): S 0 PING\nproc S {n args} {\n    set s [lindex $::sentinel_instances $n]\n    [dict get $s link] {*}$args\n}\n\n# Like R but to chat with Redis instances.\nproc R {n args} {\n    set r [lindex $::redis_instances $n]\n    [dict get $r link] {*}$args\n}\n\nproc get_info_field {info field} {\n    set fl [string length $field]\n    append field :\n    foreach line [split $info \"\\n\"] {\n        set line [string trim $line \"\\r\\n \"]\n        if {[string range $line 0 $fl] eq $field} {\n            return [string range $line [expr {$fl+1}] end]\n        }\n    }\n    return {}\n}\n\nproc SI {n field} {\n    get_info_field [S $n info] $field\n}\n\nproc RI {n field} {\n    get_info_field [R $n info] $field\n}\n\n# Iterate over IDs of sentinel or redis instances.\nproc foreach_instance_id {instances idvar code} {\n    upvar 1 $idvar id\n    for {set id 0} {$id < [llength $instances]} {incr id} {\n        set errcode [catch {uplevel 1 $code} result]\n        if {$errcode == 1} {\n            error $result $::errorInfo $::errorCode\n        } elseif {$errcode == 4} {\n            continue\n        } elseif {$errcode == 3} {\n            break\n        } elseif {$errcode != 0} {\n            return -code $errcode $result\n        }\n    }\n}\n\nproc foreach_sentinel_id {idvar code} {\n    set errcode [catch {uplevel 1 [list foreach_instance_id $::sentinel_instances $idvar $code]} result]\n    return -code $errcode $result\n}\n\nproc foreach_redis_id {idvar code} {\n    set errcode [catch {uplevel 1 [list foreach_instance_id $::redis_instances $idvar $code]} result]\n    return -code $errcode $result\n}\n\n# Get the specific attribute of the specified instance type, id.\nproc get_instance_attrib {type id attrib} {\n    dict get [lindex [set ::${type}_instances] $id] $attrib\n}\n\n# Set the specific attribute of the specified instance type, id.\nproc set_instance_attrib {type id attrib newval} {\n    set d [lindex [set ::${type}_instances] $id]\n    dict set d $attrib $newval\n    lset ::${type}_instances $id $d\n}\n\n# Create a master-slave cluster of the given number of total instances.\n# The first instance \"0\" is the master, all others are configured as\n# slaves.\nproc create_redis_master_slave_cluster n {\n    foreach_redis_id id {\n        if {$id == 0} {\n            # Our master.\n            R $id slaveof no one\n            R $id flushall\n        } elseif {$id < $n} {\n            R $id slaveof [get_instance_attrib redis 0 host] \\\n                          [get_instance_attrib redis 0 port]\n        } else {\n            # Instances not part of the cluster.\n            R $id slaveof no one\n        }\n    }\n    # Wait for all the slaves to sync.\n    wait_for_condition 1000 50 {\n        [RI 0 connected_slaves] == ($n-1)\n    } else {\n        fail \"Unable to create a master-slaves cluster.\"\n    }\n}\n\nproc get_instance_id_by_port {type port} {\n    foreach_${type}_id id {\n        if {[get_instance_attrib $type $id port] == $port} {\n            return $id\n        }\n    }\n    fail \"Instance $type port $port not found.\"\n}\n\n# Kill an instance of the specified type/id with SIGKILL.\n# This function will mark the instance PID as -1 to remember that this instance\n# is no longer running and will remove its PID from the list of pids that\n# we kill at cleanup.\n#\n# The instance can be restarted with restart-instance.\nproc kill_instance {type id} {\n    set pid [get_instance_attrib $type $id pid]\n    set port [get_instance_attrib $type $id port]\n\n    if {$pid == -1} {\n        error \"You tried to kill $type $id twice.\"\n    }\n\n    exec kill -9 $pid\n    set_instance_attrib $type $id pid -1\n    set_instance_attrib $type $id link you_tried_to_talk_with_killed_instance\n\n    # Remove the PID from the list of pids to kill at exit.\n    set ::pids [lsearch -all -inline -not -exact $::pids $pid]\n\n    # Wait for the port it was using to be available again, so that's not\n    # an issue to start a new server ASAP with the same port.\n    set retry 10\n    while {[incr retry -1]} {\n        set port_is_free [catch {set s [socket 127.0.01 $port]}]\n        if {$port_is_free} break\n        catch {close $s}\n        after 1000\n    }\n    if {$retry == 0} {\n        error \"Port $port does not return available after killing instance.\"\n    }\n}\n\n# Return true of the instance of the specified type/id is killed.\nproc instance_is_killed {type id} {\n    set pid [get_instance_attrib $type $id pid]\n    expr {$pid == -1}\n}\n\n# Restart an instance previously killed by kill_instance\nproc restart_instance {type id} {\n    set dirname \"${type}_${id}\"\n    set cfgfile [file join $dirname $type.conf]\n    set port [get_instance_attrib $type $id port]\n\n    # Execute the instance with its old setup and append the new pid\n    # file for cleanup.\n    set pid [exec_instance $type $cfgfile]\n    set_instance_attrib $type $id pid $pid\n    lappend ::pids $pid\n\n    # Check that the instance is running\n    if {[server_is_up 127.0.0.1 $port 100] == 0} {\n        abort_sentinel_test \"Problems starting $type #$id: ping timeout\"\n    }\n\n    # Connect with it with a fresh link\n    set link [redis 127.0.0.1 $port]\n    $link reconnect 1\n    set_instance_attrib $type $id link $link\n\n    # Make sure the instance is not loading the dataset when this\n    # function returns.\n    while 1 {\n        catch {[$link ping]} retval\n        if {[string match {*LOADING*} $retval]} {\n            after 100\n            continue\n        } else {\n            break\n        }\n    }\n}\n\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/tests/integration/aof-race.tcl",
    "content": "set defaults { appendonly {yes} appendfilename {appendonly.aof} }\nset server_path [tmpdir server.aof]\nset aof_path \"$server_path/appendonly.aof\"\n\nproc start_server_aof {overrides code} {\n    upvar defaults defaults srv srv server_path server_path\n    set config [concat $defaults $overrides]\n    start_server [list overrides $config] $code\n}\n\ntags {\"aof\"} {\n    # Specific test for a regression where internal buffers were not properly\n    # cleaned after a child responsible for an AOF rewrite exited. This buffer\n    # was subsequently appended to the new AOF, resulting in duplicate commands.\n    start_server_aof [list dir $server_path] {\n        set client [redis [srv host] [srv port]]\n        set bench [open \"|src/redis-benchmark -q -p [srv port] -c 20 -n 20000 incr foo\" \"r+\"]\n        after 100\n\n        # Benchmark should be running by now: start background rewrite\n        $client bgrewriteaof\n\n        # Read until benchmark pipe reaches EOF\n        while {[string length [read $bench]] > 0} {}\n\n        # Check contents of foo\n        assert_equal 20000 [$client get foo]\n    }\n\n    # Restart server to replay AOF\n    start_server_aof [list dir $server_path] {\n        set client [redis [srv host] [srv port]]\n        assert_equal 20000 [$client get foo]\n    }\n}\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/tests/integration/aof.tcl",
    "content": "set defaults { appendonly {yes} appendfilename {appendonly.aof} }\nset server_path [tmpdir server.aof]\nset aof_path \"$server_path/appendonly.aof\"\n\nproc append_to_aof {str} {\n    upvar fp fp\n    puts -nonewline $fp $str\n}\n\nproc create_aof {code} {\n    upvar fp fp aof_path aof_path\n    set fp [open $aof_path w+]\n    uplevel 1 $code\n    close $fp\n}\n\nproc start_server_aof {overrides code} {\n    upvar defaults defaults srv srv server_path server_path\n    set config [concat $defaults $overrides]\n    set srv [start_server [list overrides $config]]\n    uplevel 1 $code\n    kill_server $srv\n}\n\ntags {\"aof\"} {\n    ## Server can start when aof-load-truncated is set to yes and AOF\n    ## is truncated, with an incomplete MULTI block.\n    create_aof {\n        append_to_aof [formatCommand set foo hello]\n        append_to_aof [formatCommand multi]\n        append_to_aof [formatCommand set bar world]\n    }\n\n    start_server_aof [list dir $server_path aof-load-truncated yes] {\n        test \"Unfinished MULTI: Server should start if load-truncated is yes\" {\n            assert_equal 1 [is_alive $srv]\n        }\n    }\n\n    ## Should also start with truncated AOF without incomplete MULTI block.\n    create_aof {\n        append_to_aof [formatCommand incr foo]\n        append_to_aof [formatCommand incr foo]\n        append_to_aof [formatCommand incr foo]\n        append_to_aof [formatCommand incr foo]\n        append_to_aof [formatCommand incr foo]\n        append_to_aof [string range [formatCommand incr foo] 0 end-1]\n    }\n\n    start_server_aof [list dir $server_path aof-load-truncated yes] {\n        test \"Short read: Server should start if load-truncated is yes\" {\n            assert_equal 1 [is_alive $srv]\n        }\n\n        set client [redis [dict get $srv host] [dict get $srv port]]\n\n        test \"Truncated AOF loaded: we expect foo to be equal to 5\" {\n            assert {[$client get foo] eq \"5\"}\n        }\n\n        test \"Append a new command after loading an incomplete AOF\" {\n            $client incr foo\n        }\n    }\n\n    # Now the AOF file is expected to be correct\n    start_server_aof [list dir $server_path aof-load-truncated yes] {\n        test \"Short read + command: Server should start\" {\n            assert_equal 1 [is_alive $srv]\n        }\n\n        set client [redis [dict get $srv host] [dict get $srv port]]\n\n        test \"Truncated AOF loaded: we expect foo to be equal to 6 now\" {\n            assert {[$client get foo] eq \"6\"}\n        }\n    }\n\n    ## Test that the server exits when the AOF contains a format error\n    create_aof {\n        append_to_aof [formatCommand set foo hello]\n        append_to_aof \"!!!\"\n        append_to_aof [formatCommand set foo hello]\n    }\n\n    start_server_aof [list dir $server_path aof-load-truncated yes] {\n        test \"Bad format: Server should have logged an error\" {\n            set pattern \"*Bad file format reading the append only file*\"\n            set retry 10\n            while {$retry} {\n                set result [exec tail -n1 < [dict get $srv stdout]]\n                if {[string match $pattern $result]} {\n                    break\n                }\n                incr retry -1\n                after 1000\n            }\n            if {$retry == 0} {\n                error \"assertion:expected error not found on config file\"\n            }\n        }\n    }\n\n    ## Test the server doesn't start when the AOF contains an unfinished MULTI\n    create_aof {\n        append_to_aof [formatCommand set foo hello]\n        append_to_aof [formatCommand multi]\n        append_to_aof [formatCommand set bar world]\n    }\n\n    start_server_aof [list dir $server_path aof-load-truncated no] {\n        test \"Unfinished MULTI: Server should have logged an error\" {\n            set pattern \"*Unexpected end of file reading the append only file*\"\n            set retry 10\n            while {$retry} {\n                set result [exec tail -n1 < [dict get $srv stdout]]\n                if {[string match $pattern $result]} {\n                    break\n                }\n                incr retry -1\n                after 1000\n            }\n            if {$retry == 0} {\n                error \"assertion:expected error not found on config file\"\n            }\n        }\n    }\n\n    ## Test that the server exits when the AOF contains a short read\n    create_aof {\n        append_to_aof [formatCommand set foo hello]\n        append_to_aof [string range [formatCommand set bar world] 0 end-1]\n    }\n\n    start_server_aof [list dir $server_path aof-load-truncated no] {\n        test \"Short read: Server should have logged an error\" {\n            set pattern \"*Unexpected end of file reading the append only file*\"\n            set retry 10\n            while {$retry} {\n                set result [exec tail -n1 < [dict get $srv stdout]]\n                if {[string match $pattern $result]} {\n                    break\n                }\n                incr retry -1\n                after 1000\n            }\n            if {$retry == 0} {\n                error \"assertion:expected error not found on config file\"\n            }\n        }\n    }\n\n    ## Test that redis-check-aof indeed sees this AOF is not valid\n    test \"Short read: Utility should confirm the AOF is not valid\" {\n        catch {\n            exec src/redis-check-aof $aof_path\n        } result\n        assert_match \"*not valid*\" $result\n    }\n\n    test \"Short read: Utility should be able to fix the AOF\" {\n        set result [exec src/redis-check-aof --fix $aof_path << \"y\\n\"]\n        assert_match \"*Successfully truncated AOF*\" $result\n    }\n\n    ## Test that the server can be started using the truncated AOF\n    start_server_aof [list dir $server_path aof-load-truncated no] {\n        test \"Fixed AOF: Server should have been started\" {\n            assert_equal 1 [is_alive $srv]\n        }\n\n        test \"Fixed AOF: Keyspace should contain values that were parseable\" {\n            set client [redis [dict get $srv host] [dict get $srv port]]\n            wait_for_condition 50 100 {\n                [catch {$client ping} e] == 0\n            } else {\n                fail \"Loading DB is taking too much time.\"\n            }\n            assert_equal \"hello\" [$client get foo]\n            assert_equal \"\" [$client get bar]\n        }\n    }\n\n    ## Test that SPOP (that modifies the client's argc/argv) is correctly free'd\n    create_aof {\n        append_to_aof [formatCommand sadd set foo]\n        append_to_aof [formatCommand sadd set bar]\n        append_to_aof [formatCommand spop set]\n    }\n\n    start_server_aof [list dir $server_path aof-load-truncated no] {\n        test \"AOF+SPOP: Server should have been started\" {\n            assert_equal 1 [is_alive $srv]\n        }\n\n        test \"AOF+SPOP: Set should have 1 member\" {\n            set client [redis [dict get $srv host] [dict get $srv port]]\n            wait_for_condition 50 100 {\n                [catch {$client ping} e] == 0\n            } else {\n                fail \"Loading DB is taking too much time.\"\n            }\n            assert_equal 1 [$client scard set]\n        }\n    }\n\n    ## Uses the alsoPropagate() API.\n    create_aof {\n        append_to_aof [formatCommand sadd set foo]\n        append_to_aof [formatCommand sadd set bar]\n        append_to_aof [formatCommand sadd set gah]\n        append_to_aof [formatCommand spop set 2]\n    }\n\n    start_server_aof [list dir $server_path] {\n        test \"AOF+SPOP: Server should have been started\" {\n            assert_equal 1 [is_alive $srv]\n        }\n\n        test \"AOF+SPOP: Set should have 1 member\" {\n            set client [redis [dict get $srv host] [dict get $srv port]]\n            wait_for_condition 50 100 {\n                [catch {$client ping} e] == 0\n            } else {\n                fail \"Loading DB is taking too much time.\"\n            }\n            assert_equal 1 [$client scard set]\n        }\n    }\n\n    ## Test that EXPIREAT is loaded correctly\n    create_aof {\n        append_to_aof [formatCommand rpush list foo]\n        append_to_aof [formatCommand expireat list 1000]\n        append_to_aof [formatCommand rpush list bar]\n    }\n\n    start_server_aof [list dir $server_path aof-load-truncated no] {\n        test \"AOF+EXPIRE: Server should have been started\" {\n            assert_equal 1 [is_alive $srv]\n        }\n\n        test \"AOF+EXPIRE: List should be empty\" {\n            set client [redis [dict get $srv host] [dict get $srv port]]\n            wait_for_condition 50 100 {\n                [catch {$client ping} e] == 0\n            } else {\n                fail \"Loading DB is taking too much time.\"\n            }\n            assert_equal 0 [$client llen list]\n        }\n    }\n\n    start_server {overrides {appendonly {yes} appendfilename {appendonly.aof}}} {\n        test {Redis should not try to convert DEL into EXPIREAT for EXPIRE -1} {\n            r set x 10\n            r expire x -1\n        }\n    }\n}\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/tests/integration/convert-zipmap-hash-on-load.tcl",
    "content": "# Copy RDB with zipmap encoded hash to server path\nset server_path [tmpdir \"server.convert-zipmap-hash-on-load\"]\n\nexec cp -f tests/assets/hash-zipmap.rdb $server_path\nstart_server [list overrides [list \"dir\" $server_path \"dbfilename\" \"hash-zipmap.rdb\"]] {\n  test \"RDB load zipmap hash: converts to ziplist\" {\n    r select 0\n\n    assert_match \"*ziplist*\" [r debug object hash]\n    assert_equal 2 [r hlen hash]\n    assert_match {v1 v2} [r hmget hash f1 f2]\n  }\n}\n\nexec cp -f tests/assets/hash-zipmap.rdb $server_path\nstart_server [list overrides [list \"dir\" $server_path \"dbfilename\" \"hash-zipmap.rdb\" \"hash-max-ziplist-entries\" 1]] {\n  test \"RDB load zipmap hash: converts to hash table when hash-max-ziplist-entries is exceeded\" {\n    r select 0\n\n    assert_match \"*hashtable*\" [r debug object hash]\n    assert_equal 2 [r hlen hash]\n    assert_match {v1 v2} [r hmget hash f1 f2]\n  }\n}\n\nexec cp -f tests/assets/hash-zipmap.rdb $server_path\nstart_server [list overrides [list \"dir\" $server_path \"dbfilename\" \"hash-zipmap.rdb\" \"hash-max-ziplist-value\" 1]] {\n  test \"RDB load zipmap hash: converts to hash table when hash-max-ziplist-value is exceeded\" {\n    r select 0\n\n    assert_match \"*hashtable*\" [r debug object hash]\n    assert_equal 2 [r hlen hash]\n    assert_match {v1 v2} [r hmget hash f1 f2]\n  }\n}\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/tests/integration/logging.tcl",
    "content": "set server_path [tmpdir server.log]\nset system_name [string tolower [exec uname -s]]\n\nif {$system_name eq {linux} || $system_name eq {darwin}} {\n    start_server [list overrides [list dir $server_path]] {\n        test \"Server is able to generate a stack trace on selected systems\" {\n            r config set watchdog-period 200\n            r debug sleep 1\n            set pattern \"*debugCommand*\"\n            set retry 10\n            while {$retry} {\n                set result [exec tail -100 < [srv 0 stdout]]\n                if {[string match $pattern $result]} {\n                    break\n                }\n                incr retry -1\n                after 1000\n            }\n            if {$retry == 0} {\n                error \"assertion:expected stack trace not found into log file\"\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/tests/integration/rdb.tcl",
    "content": "set server_path [tmpdir \"server.rdb-encoding-test\"]\n\n# Copy RDB with different encodings in server path\nexec cp tests/assets/encodings.rdb $server_path\n\nstart_server [list overrides [list \"dir\" $server_path \"dbfilename\" \"encodings.rdb\"]] {\n  test \"RDB encoding loading test\" {\n    r select 0\n    csvdump r\n  } {\"0\",\"compressible\",\"string\",\"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\"\n\"0\",\"hash\",\"hash\",\"a\",\"1\",\"aa\",\"10\",\"aaa\",\"100\",\"b\",\"2\",\"bb\",\"20\",\"bbb\",\"200\",\"c\",\"3\",\"cc\",\"30\",\"ccc\",\"300\",\"ddd\",\"400\",\"eee\",\"5000000000\",\n\"0\",\"hash_zipped\",\"hash\",\"a\",\"1\",\"b\",\"2\",\"c\",\"3\",\n\"0\",\"list\",\"list\",\"1\",\"2\",\"3\",\"a\",\"b\",\"c\",\"100000\",\"6000000000\",\"1\",\"2\",\"3\",\"a\",\"b\",\"c\",\"100000\",\"6000000000\",\"1\",\"2\",\"3\",\"a\",\"b\",\"c\",\"100000\",\"6000000000\",\n\"0\",\"list_zipped\",\"list\",\"1\",\"2\",\"3\",\"a\",\"b\",\"c\",\"100000\",\"6000000000\",\n\"0\",\"number\",\"string\",\"10\"\n\"0\",\"set\",\"set\",\"1\",\"100000\",\"2\",\"3\",\"6000000000\",\"a\",\"b\",\"c\",\n\"0\",\"set_zipped_1\",\"set\",\"1\",\"2\",\"3\",\"4\",\n\"0\",\"set_zipped_2\",\"set\",\"100000\",\"200000\",\"300000\",\"400000\",\n\"0\",\"set_zipped_3\",\"set\",\"1000000000\",\"2000000000\",\"3000000000\",\"4000000000\",\"5000000000\",\"6000000000\",\n\"0\",\"string\",\"string\",\"Hello World\"\n\"0\",\"zset\",\"zset\",\"a\",\"1\",\"b\",\"2\",\"c\",\"3\",\"aa\",\"10\",\"bb\",\"20\",\"cc\",\"30\",\"aaa\",\"100\",\"bbb\",\"200\",\"ccc\",\"300\",\"aaaa\",\"1000\",\"cccc\",\"123456789\",\"bbbb\",\"5000000000\",\n\"0\",\"zset_zipped\",\"zset\",\"a\",\"1\",\"b\",\"2\",\"c\",\"3\",\n}\n}\n\nset server_path [tmpdir \"server.rdb-startup-test\"]\n\nstart_server [list overrides [list \"dir\" $server_path]] {\n    test {Server started empty with non-existing RDB file} {\n        r debug digest\n    } {0000000000000000000000000000000000000000}\n    # Save an RDB file, needed for the next test.\n    r save\n}\n\nstart_server [list overrides [list \"dir\" $server_path]] {\n    test {Server started empty with empty RDB file} {\n        r debug digest\n    } {0000000000000000000000000000000000000000}\n}\n\n# Helper function to start a server and kill it, just to check the error\n# logged.\nset defaults {}\nproc start_server_and_kill_it {overrides code} {\n    upvar defaults defaults srv srv server_path server_path\n    set config [concat $defaults $overrides]\n    set srv [start_server [list overrides $config]]\n    uplevel 1 $code\n    kill_server $srv\n}\n\n# Make the RDB file unreadable\nfile attributes [file join $server_path dump.rdb] -permissions 0222\n\n# Detect root account (it is able to read the file even with 002 perm)\nset isroot 0\ncatch {\n    open [file join $server_path dump.rdb]\n    set isroot 1\n}\n\n# Now make sure the server aborted with an error\nif {!$isroot} {\n    start_server_and_kill_it [list \"dir\" $server_path] {\n        test {Server should not start if RDB file can't be open} {\n            wait_for_condition 50 100 {\n                [string match {*Fatal error loading*} \\\n                    [exec tail -n1 < [dict get $srv stdout]]]\n            } else {\n                fail \"Server started even if RDB was unreadable!\"\n            }\n        }\n    }\n}\n\n# Fix permissions of the RDB file.\nfile attributes [file join $server_path dump.rdb] -permissions 0666\n\n# Corrupt its CRC64 checksum.\nset filesize [file size [file join $server_path dump.rdb]]\nset fd [open [file join $server_path dump.rdb] r+]\nfconfigure $fd -translation binary\nseek $fd -8 end\nputs -nonewline $fd \"foobar00\"; # Corrupt the checksum\nclose $fd\n\n# Now make sure the server aborted with an error\nstart_server_and_kill_it [list \"dir\" $server_path] {\n    test {Server should not start if RDB is corrupted} {\n        wait_for_condition 50 100 {\n            [string match {*CRC error*} \\\n                [exec tail -n10 < [dict get $srv stdout]]]\n        } else {\n            fail \"Server started even if RDB was corrupted!\"\n        }\n    }\n}\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/tests/integration/redis-cli.tcl",
    "content": "start_server {tags {\"cli\"}} {\n    proc open_cli {} {\n        set ::env(TERM) dumb\n        set fd [open [format \"|src/redis-cli -p %d -n 9\" [srv port]] \"r+\"]\n        fconfigure $fd -buffering none\n        fconfigure $fd -blocking false\n        fconfigure $fd -translation binary\n        assert_equal \"redis> \" [read_cli $fd]\n        set _ $fd\n    }\n\n    proc close_cli {fd} {\n        close $fd\n    }\n\n    proc read_cli {fd} {\n        set buf [read $fd]\n        while {[string length $buf] == 0} {\n            # wait some time and try again\n            after 10\n            set buf [read $fd]\n        }\n        set _ $buf\n    }\n\n    proc write_cli {fd buf} {\n        puts $fd $buf\n        flush $fd\n    }\n\n    # Helpers to run tests in interactive mode\n    proc run_command {fd cmd} {\n        write_cli $fd $cmd\n        set lines [split [read_cli $fd] \"\\n\"]\n        assert_equal \"redis> \" [lindex $lines end]\n        join [lrange $lines 0 end-1] \"\\n\"\n    }\n\n    proc test_interactive_cli {name code} {\n        set ::env(FAKETTY) 1\n        set fd [open_cli]\n        test \"Interactive CLI: $name\" $code\n        close_cli $fd\n        unset ::env(FAKETTY)\n    }\n\n    # Helpers to run tests where stdout is not a tty\n    proc write_tmpfile {contents} {\n        set tmp [tmpfile \"cli\"]\n        set tmpfd [open $tmp \"w\"]\n        puts -nonewline $tmpfd $contents\n        close $tmpfd\n        set _ $tmp\n    }\n\n    proc _run_cli {opts args} {\n        set cmd [format \"src/redis-cli -p %d -n 9 $args\" [srv port]]\n        foreach {key value} $opts {\n            if {$key eq \"pipe\"} {\n                set cmd \"sh -c \\\"$value | $cmd\\\"\"\n            }\n            if {$key eq \"path\"} {\n                set cmd \"$cmd < $value\"\n            }\n        }\n\n        set fd [open \"|$cmd\" \"r\"]\n        fconfigure $fd -buffering none\n        fconfigure $fd -translation binary\n        set resp [read $fd 1048576]\n        close $fd\n        set _ $resp\n    }\n\n    proc run_cli {args} {\n        _run_cli {} {*}$args\n    }\n\n    proc run_cli_with_input_pipe {cmd args} {\n        _run_cli [list pipe $cmd] {*}$args\n    }\n\n    proc run_cli_with_input_file {path args} {\n        _run_cli [list path $path] {*}$args\n    }\n\n    proc test_nontty_cli {name code} {\n        test \"Non-interactive non-TTY CLI: $name\" $code\n    }\n\n    # Helpers to run tests where stdout is a tty (fake it)\n    proc test_tty_cli {name code} {\n        set ::env(FAKETTY) 1\n        test \"Non-interactive TTY CLI: $name\" $code\n        unset ::env(FAKETTY)\n    }\n\n    test_interactive_cli \"INFO response should be printed raw\" {\n        set lines [split [run_command $fd info] \"\\n\"]\n        foreach line $lines {\n            assert [regexp {^[a-z0-9_]+:[a-z0-9_]+} $line]\n        }\n    }\n\n    test_interactive_cli \"Status reply\" {\n        assert_equal \"OK\" [run_command $fd \"set key foo\"]\n    }\n\n    test_interactive_cli \"Integer reply\" {\n        assert_equal \"(integer) 1\" [run_command $fd \"incr counter\"]\n    }\n\n    test_interactive_cli \"Bulk reply\" {\n        r set key foo\n        assert_equal \"\\\"foo\\\"\" [run_command $fd \"get key\"]\n    }\n\n    test_interactive_cli \"Multi-bulk reply\" {\n        r rpush list foo\n        r rpush list bar\n        assert_equal \"1. \\\"foo\\\"\\n2. \\\"bar\\\"\" [run_command $fd \"lrange list 0 -1\"]\n    }\n\n    test_interactive_cli \"Parsing quotes\" {\n        assert_equal \"OK\" [run_command $fd \"set key \\\"bar\\\"\"]\n        assert_equal \"bar\" [r get key]\n        assert_equal \"OK\" [run_command $fd \"set key \\\" bar \\\"\"]\n        assert_equal \" bar \" [r get key]\n        assert_equal \"OK\" [run_command $fd \"set key \\\"\\\\\\\"bar\\\\\\\"\\\"\"]\n        assert_equal \"\\\"bar\\\"\" [r get key]\n        assert_equal \"OK\" [run_command $fd \"set key \\\"\\tbar\\t\\\"\"]\n        assert_equal \"\\tbar\\t\" [r get key]\n\n        # invalid quotation\n        assert_equal \"Invalid argument(s)\" [run_command $fd \"get \\\"\\\"key\"]\n        assert_equal \"Invalid argument(s)\" [run_command $fd \"get \\\"key\\\"x\"]\n\n        # quotes after the argument are weird, but should be allowed\n        assert_equal \"OK\" [run_command $fd \"set key\\\"\\\" bar\"]\n        assert_equal \"bar\" [r get key]\n    }\n\n    test_tty_cli \"Status reply\" {\n        assert_equal \"OK\\n\" [run_cli set key bar]\n        assert_equal \"bar\" [r get key]\n    }\n\n    test_tty_cli \"Integer reply\" {\n        r del counter\n        assert_equal \"(integer) 1\\n\" [run_cli incr counter]\n    }\n\n    test_tty_cli \"Bulk reply\" {\n        r set key \"tab\\tnewline\\n\"\n        assert_equal \"\\\"tab\\\\tnewline\\\\n\\\"\\n\" [run_cli get key]\n    }\n\n    test_tty_cli \"Multi-bulk reply\" {\n        r del list\n        r rpush list foo\n        r rpush list bar\n        assert_equal \"1. \\\"foo\\\"\\n2. \\\"bar\\\"\\n\" [run_cli lrange list 0 -1]\n    }\n\n    test_tty_cli \"Read last argument from pipe\" {\n        assert_equal \"OK\\n\" [run_cli_with_input_pipe \"echo foo\" set key]\n        assert_equal \"foo\\n\" [r get key]\n    }\n\n    test_tty_cli \"Read last argument from file\" {\n        set tmpfile [write_tmpfile \"from file\"]\n        assert_equal \"OK\\n\" [run_cli_with_input_file $tmpfile set key]\n        assert_equal \"from file\" [r get key]\n    }\n\n    test_nontty_cli \"Status reply\" {\n        assert_equal \"OK\" [run_cli set key bar]\n        assert_equal \"bar\" [r get key]\n    }\n\n    test_nontty_cli \"Integer reply\" {\n        r del counter\n        assert_equal \"1\" [run_cli incr counter]\n    }\n\n    test_nontty_cli \"Bulk reply\" {\n        r set key \"tab\\tnewline\\n\"\n        assert_equal \"tab\\tnewline\\n\" [run_cli get key]\n    }\n\n    test_nontty_cli \"Multi-bulk reply\" {\n        r del list\n        r rpush list foo\n        r rpush list bar\n        assert_equal \"foo\\nbar\" [run_cli lrange list 0 -1]\n    }\n\n    test_nontty_cli \"Read last argument from pipe\" {\n        assert_equal \"OK\" [run_cli_with_input_pipe \"echo foo\" set key]\n        assert_equal \"foo\\n\" [r get key]\n    }\n\n    test_nontty_cli \"Read last argument from file\" {\n        set tmpfile [write_tmpfile \"from file\"]\n        assert_equal \"OK\" [run_cli_with_input_file $tmpfile set key]\n        assert_equal \"from file\" [r get key]\n    }\n}\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/tests/integration/replication-2.tcl",
    "content": "start_server {tags {\"repl\"}} {\n    start_server {} {\n        test {First server should have role slave after SLAVEOF} {\n            r -1 slaveof [srv 0 host] [srv 0 port]\n            after 1000\n            s -1 role\n        } {slave}\n\n        test {If min-slaves-to-write is honored, write is accepted} {\n            r config set min-slaves-to-write 1\n            r config set min-slaves-max-lag 10\n            r set foo 12345\n            wait_for_condition 50 100 {\n                [r -1 get foo] eq {12345}\n            } else {\n                fail \"Write did not reached slave\"\n            }\n        }\n\n        test {No write if min-slaves-to-write is < attached slaves} {\n            r config set min-slaves-to-write 2\n            r config set min-slaves-max-lag 10\n            catch {r set foo 12345} err\n            set err\n        } {NOREPLICAS*}\n\n        test {If min-slaves-to-write is honored, write is accepted (again)} {\n            r config set min-slaves-to-write 1\n            r config set min-slaves-max-lag 10\n            r set foo 12345\n            wait_for_condition 50 100 {\n                [r -1 get foo] eq {12345}\n            } else {\n                fail \"Write did not reached slave\"\n            }\n        }\n\n        test {No write if min-slaves-max-lag is > of the slave lag} {\n            r -1 deferred 1\n            r config set min-slaves-to-write 1\n            r config set min-slaves-max-lag 2\n            r -1 debug sleep 6\n            assert {[r set foo 12345] eq {OK}}\n            after 4000\n            catch {r set foo 12345} err\n            assert {[r -1 read] eq {OK}}\n            r -1 deferred 0\n            set err\n        } {NOREPLICAS*}\n\n        test {min-slaves-to-write is ignored by slaves} {\n            r config set min-slaves-to-write 1\n            r config set min-slaves-max-lag 10\n            r -1 config set min-slaves-to-write 1\n            r -1 config set min-slaves-max-lag 10\n            r set foo aaabbb\n            wait_for_condition 50 100 {\n                [r -1 get foo] eq {aaabbb}\n            } else {\n                fail \"Write did not reached slave\"\n            }\n        }\n\n        # Fix parameters for the next test to work\n        r config set min-slaves-to-write 0\n        r -1 config set min-slaves-to-write 0\n        r flushall\n\n        test {MASTER and SLAVE dataset should be identical after complex ops} {\n            createComplexDataset r 10000\n            after 500\n            if {[r debug digest] ne [r -1 debug digest]} {\n                set csv1 [csvdump r]\n                set csv2 [csvdump {r -1}]\n                set fd [open /tmp/repldump1.txt w]\n                puts -nonewline $fd $csv1\n                close $fd\n                set fd [open /tmp/repldump2.txt w]\n                puts -nonewline $fd $csv2\n                close $fd\n                puts \"Master - Slave inconsistency\"\n                puts \"Run diff -u against /tmp/repldump*.txt for more info\"\n            }\n            assert_equal [r debug digest] [r -1 debug digest]\n        }\n    }\n}\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/tests/integration/replication-3.tcl",
    "content": "start_server {tags {\"repl\"}} {\n    start_server {} {\n        test {First server should have role slave after SLAVEOF} {\n            r -1 slaveof [srv 0 host] [srv 0 port]\n            wait_for_condition 50 100 {\n                [s -1 master_link_status] eq {up}\n            } else {\n                fail \"Replication not started.\"\n            }\n        }\n\n        if {$::accurate} {set numops 50000} else {set numops 5000}\n\n        test {MASTER and SLAVE consistency with expire} {\n            createComplexDataset r $numops useexpire\n            after 4000 ;# Make sure everything expired before taking the digest\n            r keys *   ;# Force DEL syntesizing to slave\n            after 1000 ;# Wait another second. Now everything should be fine.\n            if {[r debug digest] ne [r -1 debug digest]} {\n                set csv1 [csvdump r]\n                set csv2 [csvdump {r -1}]\n                set fd [open /tmp/repldump1.txt w]\n                puts -nonewline $fd $csv1\n                close $fd\n                set fd [open /tmp/repldump2.txt w]\n                puts -nonewline $fd $csv2\n                close $fd\n                puts \"Master - Slave inconsistency\"\n                puts \"Run diff -u against /tmp/repldump*.txt for more info\"\n            }\n            assert_equal [r debug digest] [r -1 debug digest]\n        }\n    }\n}\n\nstart_server {tags {\"repl\"}} {\n    start_server {} {\n        test {First server should have role slave after SLAVEOF} {\n            r -1 slaveof [srv 0 host] [srv 0 port]\n            wait_for_condition 50 100 {\n                [s -1 master_link_status] eq {up}\n            } else {\n                fail \"Replication not started.\"\n            }\n        }\n\n        set numops 20000 ;# Enough to trigger the Script Cache LRU eviction.\n\n        # While we are at it, enable AOF to test it will be consistent as well\n        # after the test.\n        r config set appendonly yes\n\n        test {MASTER and SLAVE consistency with EVALSHA replication} {\n            array set oldsha {}\n            for {set j 0} {$j < $numops} {incr j} {\n                set key \"key:$j\"\n                # Make sure to create scripts that have different SHA1s\n                set script \"return redis.call('incr','$key')\"\n                set sha1 [r eval \"return redis.sha1hex(\\\"$script\\\")\" 0]\n                set oldsha($j) $sha1\n                r eval $script 0\n                set res [r evalsha $sha1 0]\n                assert {$res == 2}\n                # Additionally call one of the old scripts as well, at random.\n                set res [r evalsha $oldsha([randomInt $j]) 0]\n                assert {$res > 2}\n\n                # Trigger an AOF rewrite while we are half-way, this also\n                # forces the flush of the script cache, and we will cover\n                # more code as a result.\n                if {$j == $numops / 2} {\n                    catch {r bgrewriteaof}\n                }\n            }\n\n            wait_for_condition 50 100 {\n                [r dbsize] == $numops &&\n                [r -1 dbsize] == $numops &&\n                [r debug digest] eq [r -1 debug digest]\n            } else {\n                set csv1 [csvdump r]\n                set csv2 [csvdump {r -1}]\n                set fd [open /tmp/repldump1.txt w]\n                puts -nonewline $fd $csv1\n                close $fd\n                set fd [open /tmp/repldump2.txt w]\n                puts -nonewline $fd $csv2\n                close $fd\n                puts \"Master - Slave inconsistency\"\n                puts \"Run diff -u against /tmp/repldump*.txt for more info\"\n\n            }\n\n            set old_digest [r debug digest]\n            r config set appendonly no\n            r debug loadaof\n            set new_digest [r debug digest]\n            assert {$old_digest eq $new_digest}\n        }\n    }\n}\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/tests/integration/replication-4.tcl",
    "content": "proc start_bg_complex_data {host port db ops} {\n    set tclsh [info nameofexecutable]\n    exec $tclsh tests/helpers/bg_complex_data.tcl $host $port $db $ops &\n}\n\nproc stop_bg_complex_data {handle} {\n    catch {exec /bin/kill -9 $handle}\n}\n\nstart_server {tags {\"repl\"}} {\n    start_server {} {\n\n        set master [srv -1 client]\n        set master_host [srv -1 host]\n        set master_port [srv -1 port]\n        set slave [srv 0 client]\n\n        set load_handle0 [start_bg_complex_data $master_host $master_port 9 100000]\n        set load_handle1 [start_bg_complex_data $master_host $master_port 11 100000]\n        set load_handle2 [start_bg_complex_data $master_host $master_port 12 100000]\n\n        test {First server should have role slave after SLAVEOF} {\n            $slave slaveof $master_host $master_port\n            after 1000\n            s 0 role\n        } {slave}\n\n        test {Test replication with parallel clients writing in differnet DBs} {\n            after 5000\n            stop_bg_complex_data $load_handle0\n            stop_bg_complex_data $load_handle1\n            stop_bg_complex_data $load_handle2\n            set retry 10\n            while {$retry && ([$master debug digest] ne [$slave debug digest])}\\\n            {\n                after 1000\n                incr retry -1\n            }\n            assert {[$master dbsize] > 0}\n\n            if {[$master debug digest] ne [$slave debug digest]} {\n                set csv1 [csvdump r]\n                set csv2 [csvdump {r -1}]\n                set fd [open /tmp/repldump1.txt w]\n                puts -nonewline $fd $csv1\n                close $fd\n                set fd [open /tmp/repldump2.txt w]\n                puts -nonewline $fd $csv2\n                close $fd\n                puts \"Master - Slave inconsistency\"\n                puts \"Run diff -u against /tmp/repldump*.txt for more info\"\n            }\n            assert_equal [r debug digest] [r -1 debug digest]\n        }\n    }\n}\n\nstart_server {tags {\"repl\"}} {\n    start_server {} {\n        set master [srv -1 client]\n        set master_host [srv -1 host]\n        set master_port [srv -1 port]\n        set slave [srv 0 client]\n\n        test {First server should have role slave after SLAVEOF} {\n            $slave slaveof $master_host $master_port\n            wait_for_condition 50 100 {\n                [s 0 master_link_status] eq {up}\n            } else {\n                fail \"Replication not started.\"\n            }\n        }\n\n        test {With min-slaves-to-write (1,3): master should be writable} {\n            $master config set min-slaves-max-lag 3\n            $master config set min-slaves-to-write 1\n            $master set foo bar\n        } {OK}\n\n        test {With min-slaves-to-write (2,3): master should not be writable} {\n            $master config set min-slaves-max-lag 3\n            $master config set min-slaves-to-write 2\n            catch {$master set foo bar} e\n            set e\n        } {NOREPLICAS*}\n\n        test {With min-slaves-to-write: master not writable with lagged slave} {\n            $master config set min-slaves-max-lag 2\n            $master config set min-slaves-to-write 1\n            assert {[$master set foo bar] eq {OK}}\n            $slave deferred 1\n            $slave debug sleep 6\n            after 4000\n            catch {$master set foo bar} e\n            set e\n        } {NOREPLICAS*}\n    }\n}\n\nstart_server {tags {\"repl\"}} {\n    start_server {} {\n        set master [srv -1 client]\n        set master_host [srv -1 host]\n        set master_port [srv -1 port]\n        set slave [srv 0 client]\n\n        test {First server should have role slave after SLAVEOF} {\n            $slave slaveof $master_host $master_port\n            wait_for_condition 50 100 {\n                [s 0 role] eq {slave}\n            } else {\n                fail \"Replication not started.\"\n            }\n        }\n\n        test {Replication: commands with many arguments (issue #1221)} {\n            # We now issue large MSET commands, that may trigger a specific\n            # class of bugs, see issue #1221.\n            for {set j 0} {$j < 100} {incr j} {\n                set cmd [list mset]\n                for {set x 0} {$x < 1000} {incr x} {\n                    lappend cmd [randomKey] [randomValue]\n                }\n                $master {*}$cmd\n            }\n\n            set retry 10\n            while {$retry && ([$master debug digest] ne [$slave debug digest])}\\\n            {\n                after 1000\n                incr retry -1\n            }\n            assert {[$master dbsize] > 0}\n        }\n\n        test {Replication of SPOP command -- alsoPropagate() API} {\n            $master del myset\n            set size [expr 1+[randomInt 100]]\n            set content {}\n            for {set j 0} {$j < $size} {incr j} {\n                lappend content [randomValue]\n            }\n            $master sadd myset {*}$content\n\n            set count [randomInt 100]\n            set result [$master spop myset $count]\n\n            wait_for_condition 50 100 {\n                [$master debug digest] eq [$slave debug digest]\n            } else {\n                fail \"SPOP replication inconsistency\"\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/tests/integration/replication-psync.tcl",
    "content": "proc start_bg_complex_data {host port db ops} {\n    set tclsh [info nameofexecutable]\n    exec $tclsh tests/helpers/bg_complex_data.tcl $host $port $db $ops &\n}\n\nproc stop_bg_complex_data {handle} {\n    catch {exec /bin/kill -9 $handle}\n}\n\n# Creates a master-slave pair and breaks the link continuously to force\n# partial resyncs attempts, all this while flooding the master with\n# write queries.\n#\n# You can specifiy backlog size, ttl, delay before reconnection, test duration\n# in seconds, and an additional condition to verify at the end.\n#\n# If reconnect is > 0, the test actually try to break the connection and\n# reconnect with the master, otherwise just the initial synchronization is\n# checked for consistency.\nproc test_psync {descr duration backlog_size backlog_ttl delay cond diskless reconnect} {\n    start_server {tags {\"repl\"}} {\n        start_server {} {\n\n            set master [srv -1 client]\n            set master_host [srv -1 host]\n            set master_port [srv -1 port]\n            set slave [srv 0 client]\n\n            $master config set repl-backlog-size $backlog_size\n            $master config set repl-backlog-ttl $backlog_ttl\n            $master config set repl-diskless-sync $diskless\n            $master config set repl-diskless-sync-delay 1\n\n            set load_handle0 [start_bg_complex_data $master_host $master_port 9 100000]\n            set load_handle1 [start_bg_complex_data $master_host $master_port 11 100000]\n            set load_handle2 [start_bg_complex_data $master_host $master_port 12 100000]\n\n            test {Slave should be able to synchronize with the master} {\n                $slave slaveof $master_host $master_port\n                wait_for_condition 50 100 {\n                    [lindex [r role] 0] eq {slave} &&\n                    [lindex [r role] 3] eq {connected}\n                } else {\n                    fail \"Replication not started.\"\n                }\n            }\n\n            # Check that the background clients are actually writing.\n            test {Detect write load to master} {\n                wait_for_condition 50 100 {\n                    [$master dbsize] > 100\n                } else {\n                    fail \"Can't detect write load from background clients.\"\n                }\n            }\n\n            test \"Test replication partial resync: $descr (diskless: $diskless, reconnect: $reconnect)\" {\n                # Now while the clients are writing data, break the maste-slave\n                # link multiple times.\n                if ($reconnect) {\n                    for {set j 0} {$j < $duration*10} {incr j} {\n                        after 100\n                        # catch {puts \"MASTER [$master dbsize] keys, SLAVE [$slave dbsize] keys\"}\n\n                        if {($j % 20) == 0} {\n                            catch {\n                                if {$delay} {\n                                    $slave multi\n                                    $slave client kill $master_host:$master_port\n                                    $slave debug sleep $delay\n                                    $slave exec\n                                } else {\n                                    $slave client kill $master_host:$master_port\n                                }\n                            }\n                        }\n                    }\n                }\n                stop_bg_complex_data $load_handle0\n                stop_bg_complex_data $load_handle1\n                stop_bg_complex_data $load_handle2\n                set retry 10\n                while {$retry && ([$master debug digest] ne [$slave debug digest])}\\\n                {\n                    after 1000\n                    incr retry -1\n                }\n                assert {[$master dbsize] > 0}\n\n                if {[$master debug digest] ne [$slave debug digest]} {\n                    set csv1 [csvdump r]\n                    set csv2 [csvdump {r -1}]\n                    set fd [open /tmp/repldump1.txt w]\n                    puts -nonewline $fd $csv1\n                    close $fd\n                    set fd [open /tmp/repldump2.txt w]\n                    puts -nonewline $fd $csv2\n                    close $fd\n                    puts \"Master - Slave inconsistency\"\n                    puts \"Run diff -u against /tmp/repldump*.txt for more info\"\n                }\n                assert_equal [r debug digest] [r -1 debug digest]\n                eval $cond\n            }\n        }\n    }\n}\n\nforeach diskless {no yes} {\n    test_psync {no reconnection, just sync} 6 1000000 3600 0 {\n    } $diskless 0\n\n    test_psync {ok psync} 6 1000000 3600 0 {\n        assert {[s -1 sync_partial_ok] > 0}\n    } $diskless 1\n\n    test_psync {no backlog} 6 100 3600 0.5 {\n        assert {[s -1 sync_partial_err] > 0}\n    } $diskless 1\n\n    test_psync {ok after delay} 3 100000000 3600 3 {\n        assert {[s -1 sync_partial_ok] > 0}\n    } $diskless 1\n\n    test_psync {backlog expired} 3 100000000 1 3 {\n        assert {[s -1 sync_partial_err] > 0}\n    } $diskless 1\n}\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/tests/integration/replication.tcl",
    "content": "proc log_file_matches {log pattern} {\n    set fp [open $log r]\n    set content [read $fp]\n    close $fp\n    string match $pattern $content\n}\n\nstart_server {tags {\"repl\"}} {\n    set slave [srv 0 client]\n    set slave_host [srv 0 host]\n    set slave_port [srv 0 port]\n    set slave_log [srv 0 stdout]\n    start_server {} {\n        set master [srv 0 client]\n        set master_host [srv 0 host]\n        set master_port [srv 0 port]\n\n        # Configure the master in order to hang waiting for the BGSAVE\n        # operation, so that the slave remains in the handshake state.\n        $master config set repl-diskless-sync yes\n        $master config set repl-diskless-sync-delay 1000\n\n        # Use a short replication timeout on the slave, so that if there\n        # are no bugs the timeout is triggered in a reasonable amount\n        # of time.\n        $slave config set repl-timeout 5\n\n        # Start the replication process...\n        $slave slaveof $master_host $master_port\n\n        test {Slave enters handshake} {\n            wait_for_condition 50 1000 {\n                [string match *handshake* [$slave role]]\n            } else {\n                fail \"Slave does not enter handshake state\"\n            }\n        }\n\n        # But make the master unable to send\n        # the periodic newlines to refresh the connection. The slave\n        # should detect the timeout.\n        $master debug sleep 10\n\n        test {Slave is able to detect timeout during handshake} {\n            wait_for_condition 50 1000 {\n                [log_file_matches $slave_log \"*Timeout connecting to the MASTER*\"]\n            } else {\n                fail \"Slave is not able to detect timeout\"\n            }\n        }\n    }\n}\n\nstart_server {tags {\"repl\"}} {\n    set A [srv 0 client]\n    set A_host [srv 0 host]\n    set A_port [srv 0 port]\n    start_server {} {\n        set B [srv 0 client]\n        set B_host [srv 0 host]\n        set B_port [srv 0 port]\n\n        test {Set instance A as slave of B} {\n            $A slaveof $B_host $B_port\n            wait_for_condition 50 100 {\n                [lindex [$A role] 0] eq {slave} &&\n                [string match {*master_link_status:up*} [$A info replication]]\n            } else {\n                fail \"Can't turn the instance into a slave\"\n            }\n        }\n\n        test {BRPOPLPUSH replication, when blocking against empty list} {\n            set rd [redis_deferring_client]\n            $rd brpoplpush a b 5\n            r lpush a foo\n            wait_for_condition 50 100 {\n                [$A debug digest] eq [$B debug digest]\n            } else {\n                fail \"Master and slave have different digest: [$A debug digest] VS [$B debug digest]\"\n            }\n        }\n\n        test {BRPOPLPUSH replication, list exists} {\n            set rd [redis_deferring_client]\n            r lpush c 1\n            r lpush c 2\n            r lpush c 3\n            $rd brpoplpush c d 5\n            after 1000\n            assert_equal [$A debug digest] [$B debug digest]\n        }\n\n        test {BLPOP followed by role change, issue #2473} {\n            set rd [redis_deferring_client]\n            $rd blpop foo 0 ; # Block while B is a master\n\n            # Turn B into master of A\n            $A slaveof no one\n            $B slaveof $A_host $A_port\n            wait_for_condition 50 100 {\n                [lindex [$B role] 0] eq {slave} &&\n                [string match {*master_link_status:up*} [$B info replication]]\n            } else {\n                fail \"Can't turn the instance into a slave\"\n            }\n\n            # Push elements into the \"foo\" list of the new slave.\n            # If the client is still attached to the instance, we'll get\n            # a desync between the two instances.\n            $A rpush foo a b c\n            after 100\n\n            wait_for_condition 50 100 {\n                [$A debug digest] eq [$B debug digest] &&\n                [$A lrange foo 0 -1] eq {a b c} &&\n                [$B lrange foo 0 -1] eq {a b c}\n            } else {\n                fail \"Master and slave have different digest: [$A debug digest] VS [$B debug digest]\"\n            }\n        }\n    }\n}\n\nstart_server {tags {\"repl\"}} {\n    r set mykey foo\n\n    start_server {} {\n        test {Second server should have role master at first} {\n            s role\n        } {master}\n\n        test {SLAVEOF should start with link status \"down\"} {\n            r slaveof [srv -1 host] [srv -1 port]\n            s master_link_status\n        } {down}\n\n        test {The role should immediately be changed to \"slave\"} {\n            s role\n        } {slave}\n\n        wait_for_sync r\n        test {Sync should have transferred keys from master} {\n            r get mykey\n        } {foo}\n\n        test {The link status should be up} {\n            s master_link_status\n        } {up}\n\n        test {SET on the master should immediately propagate} {\n            r -1 set mykey bar\n\n            wait_for_condition 500 100 {\n                [r  0 get mykey] eq {bar}\n            } else {\n                fail \"SET on master did not propagated on slave\"\n            }\n        }\n\n        test {FLUSHALL should replicate} {\n            r -1 flushall\n            if {$::valgrind} {after 2000}\n            list [r -1 dbsize] [r 0 dbsize]\n        } {0 0}\n\n        test {ROLE in master reports master with a slave} {\n            set res [r -1 role]\n            lassign $res role offset slaves\n            assert {$role eq {master}}\n            assert {$offset > 0}\n            assert {[llength $slaves] == 1}\n            lassign [lindex $slaves 0] master_host master_port slave_offset\n            assert {$slave_offset <= $offset}\n        }\n\n        test {ROLE in slave reports slave in connected state} {\n            set res [r role]\n            lassign $res role master_host master_port slave_state slave_offset\n            assert {$role eq {slave}}\n            assert {$slave_state eq {connected}}\n        }\n    }\n}\n\nforeach dl {no yes} {\n    start_server {tags {\"repl\"}} {\n        set master [srv 0 client]\n        $master config set repl-diskless-sync $dl\n        set master_host [srv 0 host]\n        set master_port [srv 0 port]\n        set slaves {}\n        set load_handle0 [start_write_load $master_host $master_port 3]\n        set load_handle1 [start_write_load $master_host $master_port 5]\n        set load_handle2 [start_write_load $master_host $master_port 20]\n        set load_handle3 [start_write_load $master_host $master_port 8]\n        set load_handle4 [start_write_load $master_host $master_port 4]\n        start_server {} {\n            lappend slaves [srv 0 client]\n            start_server {} {\n                lappend slaves [srv 0 client]\n                start_server {} {\n                    lappend slaves [srv 0 client]\n                    test \"Connect multiple slaves at the same time (issue #141), diskless=$dl\" {\n                        # Send SLAVEOF commands to slaves\n                        [lindex $slaves 0] slaveof $master_host $master_port\n                        [lindex $slaves 1] slaveof $master_host $master_port\n                        [lindex $slaves 2] slaveof $master_host $master_port\n\n                        # Wait for all the three slaves to reach the \"online\"\n                        # state from the POV of the master.\n                        set retry 500\n                        while {$retry} {\n                            set info [r -3 info]\n                            if {[string match {*slave0:*state=online*slave1:*state=online*slave2:*state=online*} $info]} {\n                                break\n                            } else {\n                                incr retry -1\n                                after 100\n                            }\n                        }\n                        if {$retry == 0} {\n                            error \"assertion:Slaves not correctly synchronized\"\n                        }\n\n                        # Wait that slaves acknowledge they are online so\n                        # we are sure that DBSIZE and DEBUG DIGEST will not\n                        # fail because of timing issues.\n                        wait_for_condition 500 100 {\n                            [lindex [[lindex $slaves 0] role] 3] eq {connected} &&\n                            [lindex [[lindex $slaves 1] role] 3] eq {connected} &&\n                            [lindex [[lindex $slaves 2] role] 3] eq {connected}\n                        } else {\n                            fail \"Slaves still not connected after some time\"\n                        }\n\n                        # Stop the write load\n                        stop_write_load $load_handle0\n                        stop_write_load $load_handle1\n                        stop_write_load $load_handle2\n                        stop_write_load $load_handle3\n                        stop_write_load $load_handle4\n\n                        # Make sure that slaves and master have same\n                        # number of keys\n                        wait_for_condition 500 100 {\n                            [$master dbsize] == [[lindex $slaves 0] dbsize] &&\n                            [$master dbsize] == [[lindex $slaves 1] dbsize] &&\n                            [$master dbsize] == [[lindex $slaves 2] dbsize]\n                        } else {\n                            fail \"Different number of keys between masted and slave after too long time.\"\n                        }\n\n                        # Check digests\n                        set digest [$master debug digest]\n                        set digest0 [[lindex $slaves 0] debug digest]\n                        set digest1 [[lindex $slaves 1] debug digest]\n                        set digest2 [[lindex $slaves 2] debug digest]\n                        assert {$digest ne 0000000000000000000000000000000000000000}\n                        assert {$digest eq $digest0}\n                        assert {$digest eq $digest1}\n                        assert {$digest eq $digest2}\n                    }\n               }\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/tests/sentinel/run.tcl",
    "content": "# Sentinel test suite. Copyright (C) 2014 Salvatore Sanfilippo antirez@gmail.com\n# This software is released under the BSD License. See the COPYING file for\n# more information.\n\ncd tests/sentinel\nsource ../instances.tcl\n\nset ::instances_count 5 ; # How many instances we use at max.\n\nproc main {} {\n    parse_options\n    spawn_instance sentinel $::sentinel_base_port $::instances_count\n    spawn_instance redis $::redis_base_port $::instances_count\n    run_tests\n    cleanup\n    end_tests\n}\n\nif {[catch main e]} {\n    puts $::errorInfo\n    cleanup\n    exit 1\n}\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/tests/sentinel/tests/00-base.tcl",
    "content": "# Check the basic monitoring and failover capabilities.\n\nsource \"../tests/includes/init-tests.tcl\"\n\nif {$::simulate_error} {\n    test \"This test will fail\" {\n        fail \"Simulated error\"\n    }\n}\n\ntest \"Basic failover works if the master is down\" {\n    set old_port [RI $master_id tcp_port]\n    set addr [S 0 SENTINEL GET-MASTER-ADDR-BY-NAME mymaster]\n    assert {[lindex $addr 1] == $old_port}\n    kill_instance redis $master_id\n    foreach_sentinel_id id {\n        wait_for_condition 1000 50 {\n            [lindex [S $id SENTINEL GET-MASTER-ADDR-BY-NAME mymaster] 1] != $old_port\n        } else {\n            fail \"At least one Sentinel did not received failover info\"\n        }\n    }\n    restart_instance redis $master_id\n    set addr [S 0 SENTINEL GET-MASTER-ADDR-BY-NAME mymaster]\n    set master_id [get_instance_id_by_port redis [lindex $addr 1]]\n}\n\ntest \"New master [join $addr {:}] role matches\" {\n    assert {[RI $master_id role] eq {master}}\n}\n\ntest \"All the other slaves now point to the new master\" {\n    foreach_redis_id id {\n        if {$id != $master_id && $id != 0} {\n            wait_for_condition 1000 50 {\n                [RI $id master_port] == [lindex $addr 1]\n            } else {\n                fail \"Redis ID $id not configured to replicate with new master\"\n            }\n        }\n    }\n}\n\ntest \"The old master eventually gets reconfigured as a slave\" {\n    wait_for_condition 1000 50 {\n        [RI 0 master_port] == [lindex $addr 1]\n    } else {\n        fail \"Old master not reconfigured as slave of new master\"\n    }\n}\n\ntest \"ODOWN is not possible without N (quorum) Sentinels reports\" {\n    foreach_sentinel_id id {\n        S $id SENTINEL SET mymaster quorum [expr $sentinels+1]\n    }\n    set old_port [RI $master_id tcp_port]\n    set addr [S 0 SENTINEL GET-MASTER-ADDR-BY-NAME mymaster]\n    assert {[lindex $addr 1] == $old_port}\n    kill_instance redis $master_id\n\n    # Make sure failover did not happened.\n    set addr [S 0 SENTINEL GET-MASTER-ADDR-BY-NAME mymaster]\n    assert {[lindex $addr 1] == $old_port}\n    restart_instance redis $master_id\n}\n\ntest \"Failover is not possible without majority agreement\" {\n    foreach_sentinel_id id {\n        S $id SENTINEL SET mymaster quorum $quorum\n    }\n\n    # Crash majority of sentinels\n    for {set id 0} {$id < $quorum} {incr id} {\n        kill_instance sentinel $id\n    }\n\n    # Kill the current master\n    kill_instance redis $master_id\n\n    # Make sure failover did not happened.\n    set addr [S $quorum SENTINEL GET-MASTER-ADDR-BY-NAME mymaster]\n    assert {[lindex $addr 1] == $old_port}\n    restart_instance redis $master_id\n\n    # Cleanup: restart Sentinels to monitor the master.\n    for {set id 0} {$id < $quorum} {incr id} {\n        restart_instance sentinel $id\n    }\n}\n\ntest \"Failover works if we configure for absolute agreement\" {\n    foreach_sentinel_id id {\n        S $id SENTINEL SET mymaster quorum $sentinels\n    }\n\n    # Wait for Sentinels to monitor the master again\n    foreach_sentinel_id id {\n        wait_for_condition 1000 50 {\n            [dict get [S $id SENTINEL MASTER mymaster] info-refresh] < 100000\n        } else {\n            fail \"At least one Sentinel is not monitoring the master\"\n        }\n    }\n\n    kill_instance redis $master_id\n\n    foreach_sentinel_id id {\n        wait_for_condition 1000 50 {\n            [lindex [S $id SENTINEL GET-MASTER-ADDR-BY-NAME mymaster] 1] != $old_port\n        } else {\n            fail \"At least one Sentinel did not received failover info\"\n        }\n    }\n    restart_instance redis $master_id\n    set addr [S 0 SENTINEL GET-MASTER-ADDR-BY-NAME mymaster]\n    set master_id [get_instance_id_by_port redis [lindex $addr 1]]\n\n    # Set the min ODOWN agreement back to strict majority.\n    foreach_sentinel_id id {\n        S $id SENTINEL SET mymaster quorum $quorum\n    }\n}\n\ntest \"New master [join $addr {:}] role matches\" {\n    assert {[RI $master_id role] eq {master}}\n}\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/tests/sentinel/tests/01-conf-update.tcl",
    "content": "# Test Sentinel configuration consistency after partitions heal.\n\nsource \"../tests/includes/init-tests.tcl\"\n\ntest \"We can failover with Sentinel 1 crashed\" {\n    set old_port [RI $master_id tcp_port]\n    set addr [S 0 SENTINEL GET-MASTER-ADDR-BY-NAME mymaster]\n    assert {[lindex $addr 1] == $old_port}\n\n    # Crash Sentinel 1\n    kill_instance sentinel 1\n\n    kill_instance redis $master_id\n    foreach_sentinel_id id {\n        if {$id != 1} {\n            wait_for_condition 1000 50 {\n                [lindex [S $id SENTINEL GET-MASTER-ADDR-BY-NAME mymaster] 1] != $old_port\n            } else {\n                fail \"Sentinel $id did not received failover info\"\n            }\n        }\n    }\n    restart_instance redis $master_id\n    set addr [S 0 SENTINEL GET-MASTER-ADDR-BY-NAME mymaster]\n    set master_id [get_instance_id_by_port redis [lindex $addr 1]]\n}\n\ntest \"After Sentinel 1 is restarted, its config gets updated\" {\n    restart_instance sentinel 1\n    wait_for_condition 1000 50 {\n        [lindex [S 1 SENTINEL GET-MASTER-ADDR-BY-NAME mymaster] 1] != $old_port\n    } else {\n        fail \"Restarted Sentinel did not received failover info\"\n    }\n}\n\ntest \"New master [join $addr {:}] role matches\" {\n    assert {[RI $master_id role] eq {master}}\n}\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/tests/sentinel/tests/02-slaves-reconf.tcl",
    "content": "# Check that slaves are reconfigured at a latter time if they are partitioned.\n#\n# Here we should test:\n# 1) That slaves point to the new master after failover.\n# 2) That partitioned slaves point to new master when they are partitioned\n#    away during failover and return at a latter time.\n\nsource \"../tests/includes/init-tests.tcl\"\n\nproc 02_test_slaves_replication {} {\n    uplevel 1 {\n        test \"Check that slaves replicate from current master\" {\n            set master_port [RI $master_id tcp_port]\n            foreach_redis_id id {\n                if {$id == $master_id} continue\n                if {[instance_is_killed redis $id]} continue\n                wait_for_condition 1000 50 {\n                    ([RI $id master_port] == $master_port) &&\n                    ([RI $id master_link_status] eq {up})\n                } else {\n                    fail \"Redis slave $id is replicating from wrong master\"\n                }\n            }\n        }\n    }\n}\n\nproc 02_crash_and_failover {} {\n    uplevel 1 {\n        test \"Crash the master and force a failover\" {\n            set old_port [RI $master_id tcp_port]\n            set addr [S 0 SENTINEL GET-MASTER-ADDR-BY-NAME mymaster]\n            assert {[lindex $addr 1] == $old_port}\n            kill_instance redis $master_id\n            foreach_sentinel_id id {\n                wait_for_condition 1000 50 {\n                    [lindex [S $id SENTINEL GET-MASTER-ADDR-BY-NAME mymaster] 1] != $old_port\n                } else {\n                    fail \"At least one Sentinel did not received failover info\"\n                }\n            }\n            restart_instance redis $master_id\n            set addr [S 0 SENTINEL GET-MASTER-ADDR-BY-NAME mymaster]\n            set master_id [get_instance_id_by_port redis [lindex $addr 1]]\n        }\n    }\n}\n\n02_test_slaves_replication\n02_crash_and_failover\n02_test_slaves_replication\n\ntest \"Kill a slave instance\" {\n    foreach_redis_id id {\n        if {$id == $master_id} continue\n        set killed_slave_id $id\n        kill_instance redis $id\n        break\n    }\n}\n\n02_crash_and_failover\n02_test_slaves_replication\n\ntest \"Wait for failover to end\" {\n    set inprogress 1\n    while {$inprogress} {\n        set inprogress 0\n        foreach_sentinel_id id {\n            if {[dict exists [S $id SENTINEL MASTER mymaster] failover-state]} {\n                incr inprogress\n            }\n        }\n        if {$inprogress} {after 100}\n    }\n}\n\ntest \"Restart killed slave and test replication of slaves again...\" {\n    restart_instance redis $killed_slave_id\n}\n\n# Now we check if the slave rejoining the partition is reconfigured even\n# if the failover finished.\n02_test_slaves_replication\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/tests/sentinel/tests/03-runtime-reconf.tcl",
    "content": "# Test runtime reconfiguration command SENTINEL SET.\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/tests/sentinel/tests/04-slave-selection.tcl",
    "content": "# Test slave selection algorithm.\n#\n# This unit should test:\n# 1) That when there are no suitable slaves no failover is performed.\n# 2) That among the available slaves, the one with better offset is picked.\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/tests/sentinel/tests/05-manual.tcl",
    "content": "# Test manual failover\n\nsource \"../tests/includes/init-tests.tcl\"\n\ntest \"Manual failover works\" {\n    set old_port [RI $master_id tcp_port]\n    set addr [S 0 SENTINEL GET-MASTER-ADDR-BY-NAME mymaster]\n    assert {[lindex $addr 1] == $old_port}\n    catch {S 0 SENTINEL FAILOVER mymaster} reply\n    assert {$reply eq \"OK\"}\n    foreach_sentinel_id id {\n        wait_for_condition 1000 50 {\n            [lindex [S $id SENTINEL GET-MASTER-ADDR-BY-NAME mymaster] 1] != $old_port\n        } else {\n            fail \"At least one Sentinel did not received failover info\"\n        }\n    }\n    set addr [S 0 SENTINEL GET-MASTER-ADDR-BY-NAME mymaster]\n    set master_id [get_instance_id_by_port redis [lindex $addr 1]]\n}\n\ntest \"New master [join $addr {:}] role matches\" {\n    assert {[RI $master_id role] eq {master}}\n}\n\ntest \"All the other slaves now point to the new master\" {\n    foreach_redis_id id {\n        if {$id != $master_id && $id != 0} {\n            wait_for_condition 1000 50 {\n                [RI $id master_port] == [lindex $addr 1]\n            } else {\n                fail \"Redis ID $id not configured to replicate with new master\"\n            }\n        }\n    }\n}\n\ntest \"The old master eventually gets reconfigured as a slave\" {\n    wait_for_condition 1000 50 {\n        [RI 0 master_port] == [lindex $addr 1]\n    } else {\n        fail \"Old master not reconfigured as slave of new master\"\n    }\n}\n\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/tests/sentinel/tests/06-ckquorum.tcl",
    "content": "# Test for the SENTINEL CKQUORUM command\n\nsource \"../tests/includes/init-tests.tcl\"\nset num_sentinels [llength $::sentinel_instances]\n\ntest \"CKQUORUM reports OK and the right amount of Sentinels\" {\n    foreach_sentinel_id id {\n        assert_match \"*OK $num_sentinels usable*\" [S $id SENTINEL CKQUORUM mymaster]\n    }\n}\n\ntest \"CKQUORUM detects quorum cannot be reached\" {\n    set orig_quorum [expr {$num_sentinels/2+1}]\n    S 0 SENTINEL SET mymaster quorum [expr {$num_sentinels+1}]\n    catch {[S 0 SENTINEL CKQUORUM mymaster]} err\n    assert_match \"*NOQUORUM*\" $err\n    S 0 SENTINEL SET mymaster quorum $orig_quorum\n}\n\ntest \"CKQUORUM detects failover authorization cannot be reached\" {\n    set orig_quorum [expr {$num_sentinels/2+1}]\n    S 0 SENTINEL SET mymaster quorum 1\n    kill_instance sentinel 1\n    kill_instance sentinel 2\n    kill_instance sentinel 3\n    after 5000\n    catch {[S 0 SENTINEL CKQUORUM mymaster]} err\n    assert_match \"*NOQUORUM*\" $err\n    S 0 SENTINEL SET mymaster quorum $orig_quorum\n    restart_instance sentinel 1\n    restart_instance sentinel 2\n    restart_instance sentinel 3\n}\n\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/tests/sentinel/tests/07-down-conditions.tcl",
    "content": "# Test conditions where an instance is considered to be down\n\nsource \"../tests/includes/init-tests.tcl\"\n\nproc ensure_master_up {} {\n    wait_for_condition 1000 50 {\n        [dict get [S 4 sentinel master mymaster] flags] eq \"master\"\n    } else {\n        fail \"Master flags are not just 'master'\"\n    }\n}\n\nproc ensure_master_down {} {\n    wait_for_condition 1000 50 {\n        [string match *down* \\\n            [dict get [S 4 sentinel master mymaster] flags]]\n    } else {\n        fail \"Master is not flagged SDOWN\"\n    }\n}\n\ntest \"Crash the majority of Sentinels to prevent failovers for this unit\" {\n    for {set id 0} {$id < $quorum} {incr id} {\n        kill_instance sentinel $id\n    }\n}\n\ntest \"SDOWN is triggered by non-responding but not crashed instance\" {\n    lassign [S 4 SENTINEL GET-MASTER-ADDR-BY-NAME mymaster] host port\n    ensure_master_up\n    exec ../../../src/redis-cli -h $host -p $port debug sleep 10 > /dev/null &\n    ensure_master_down\n    ensure_master_up\n}\n\ntest \"SDOWN is triggered by crashed instance\" {\n    lassign [S 4 SENTINEL GET-MASTER-ADDR-BY-NAME mymaster] host port\n    ensure_master_up\n    kill_instance redis 0\n    ensure_master_down\n    restart_instance redis 0\n    ensure_master_up\n}\n\ntest \"SDOWN is triggered by masters advertising as slaves\" {\n    ensure_master_up\n    R 0 slaveof 127.0.0.1 34567\n    ensure_master_down\n    R 0 slaveof no one\n    ensure_master_up\n}\n\ntest \"SDOWN is triggered by misconfigured instance repling with errors\" {\n    ensure_master_up\n    set orig_dir [lindex [R 0 config get dir] 1]\n    set orig_save [lindex [R 0 config get save] 1]\n    # Set dir to / and filename to \"tmp\" to make sure it will fail.\n    R 0 config set dir /\n    R 0 config set dbfilename tmp\n    R 0 config set save \"1000000 1000000\"\n    R 0 bgsave\n    ensure_master_down\n    R 0 config set save $orig_save\n    R 0 config set dir $orig_dir\n    R 0 config set dbfilename dump.rdb\n    R 0 bgsave\n    ensure_master_up\n}\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/tests/sentinel/tests/includes/init-tests.tcl",
    "content": "# Initialization tests -- most units will start including this.\n\ntest \"(init) Restart killed instances\" {\n    foreach type {redis sentinel} {\n        foreach_${type}_id id {\n            if {[get_instance_attrib $type $id pid] == -1} {\n                puts -nonewline \"$type/$id \"\n                flush stdout\n                restart_instance $type $id\n            }\n        }\n    }\n}\n\ntest \"(init) Remove old master entry from sentinels\" {\n    foreach_sentinel_id id {\n        catch {S $id SENTINEL REMOVE mymaster}\n    }\n}\n\nset redis_slaves 4\ntest \"(init) Create a master-slaves cluster of [expr $redis_slaves+1] instances\" {\n    create_redis_master_slave_cluster [expr {$redis_slaves+1}]\n}\nset master_id 0\n\ntest \"(init) Sentinels can start monitoring a master\" {\n    set sentinels [llength $::sentinel_instances]\n    set quorum [expr {$sentinels/2+1}]\n    foreach_sentinel_id id {\n        S $id SENTINEL MONITOR mymaster \\\n              [get_instance_attrib redis $master_id host] \\\n              [get_instance_attrib redis $master_id port] $quorum\n    }\n    foreach_sentinel_id id {\n        assert {[S $id sentinel master mymaster] ne {}}\n        S $id SENTINEL SET mymaster down-after-milliseconds 2000\n        S $id SENTINEL SET mymaster failover-timeout 20000\n        S $id SENTINEL SET mymaster parallel-syncs 10\n    }\n}\n\ntest \"(init) Sentinels can talk with the master\" {\n    foreach_sentinel_id id {\n        wait_for_condition 1000 50 {\n            [catch {S $id SENTINEL GET-MASTER-ADDR-BY-NAME mymaster}] == 0\n        } else {\n            fail \"Sentinel $id can't talk with the master.\"\n        }\n    }\n}\n\ntest \"(init) Sentinels are able to auto-discover other sentinels\" {\n    set sentinels [llength $::sentinel_instances]\n    foreach_sentinel_id id {\n        wait_for_condition 1000 50 {\n            [dict get [S $id SENTINEL MASTER mymaster] num-other-sentinels] == ($sentinels-1)\n        } else {\n            fail \"At least some sentinel can't detect some other sentinel\"\n        }\n    }\n}\n\ntest \"(init) Sentinels are able to auto-discover slaves\" {\n    foreach_sentinel_id id {\n        wait_for_condition 1000 50 {\n            [dict get [S $id SENTINEL MASTER mymaster] num-slaves] == $redis_slaves\n        } else {\n            fail \"At least some sentinel can't detect some slave\"\n        }\n    }\n}\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/tests/sentinel/tmp/.gitignore",
    "content": "redis_*\nsentinel_*\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/tests/support/cluster.tcl",
    "content": "# Tcl redis cluster client as a wrapper of redis.rb.\n# Copyright (C) 2014 Salvatore Sanfilippo\n# Released under the BSD license like Redis itself\n#\n# Example usage:\n#\n# set c [redis_cluster 127.0.0.1 6379 127.0.0.1 6380]\n# $c set foo\n# $c get foo\n# $c close\n\npackage require Tcl 8.5\npackage provide redis_cluster 0.1\n\nnamespace eval redis_cluster {}\nset ::redis_cluster::id 0\narray set ::redis_cluster::startup_nodes {}\narray set ::redis_cluster::nodes {}\narray set ::redis_cluster::slots {}\n\n# List of \"plain\" commands, which are commands where the sole key is always\n# the first argument.\nset ::redis_cluster::plain_commands {\n    get set setnx setex psetex append strlen exists setbit getbit\n    setrange getrange substr incr decr rpush lpush rpushx lpushx\n    linsert rpop lpop brpop llen lindex lset lrange ltrim lrem\n    sadd srem sismember scard spop srandmember smembers sscan zadd\n    zincrby zrem zremrangebyscore zremrangebyrank zremrangebylex zrange\n    zrangebyscore zrevrangebyscore zrangebylex zrevrangebylex zcount\n    zlexcount zrevrange zcard zscore zrank zrevrank zscan hset hsetnx\n    hget hmset hmget hincrby hincrbyfloat hdel hlen hkeys hvals\n    hgetall hexists hscan incrby decrby incrbyfloat getset move\n    expire expireat pexpire pexpireat type ttl pttl persist restore\n    dump bitcount bitpos pfadd pfcount\n}\n\nproc redis_cluster {nodes} {\n    set id [incr ::redis_cluster::id]\n    set ::redis_cluster::startup_nodes($id) $nodes\n    set ::redis_cluster::nodes($id) {}\n    set ::redis_cluster::slots($id) {}\n    set handle [interp alias {} ::redis_cluster::instance$id {} ::redis_cluster::__dispatch__ $id]\n    $handle refresh_nodes_map\n    return $handle\n}\n\n# Totally reset the slots / nodes state for the client, calls\n# CLUSTER NODES in the first startup node available, populates the\n# list of nodes ::redis_cluster::nodes($id) with an hash mapping node\n# ip:port to a representation of the node (another hash), and finally\n# maps ::redis_cluster::slots($id) with an hash mapping slot numbers\n# to node IDs.\n#\n# This function is called when a new Redis Cluster client is initialized\n# and every time we get a -MOVED redirection error.\nproc ::redis_cluster::__method__refresh_nodes_map {id} {\n    # Contact the first responding startup node.\n    set idx 0; # Index of the node that will respond.\n    set errmsg {}\n    foreach start_node $::redis_cluster::startup_nodes($id) {\n        lassign [split $start_node :] start_host start_port\n        if {[catch {\n            set r {}\n            set r [redis $start_host $start_port]\n            set nodes_descr [$r cluster nodes]\n            $r close\n        } e]} {\n            if {$r ne {}} {catch {$r close}}\n            incr idx\n            if {[string length $errmsg] < 200} {\n                append errmsg \" $start_node: $e\"\n            }\n            continue ; # Try next.\n        } else {\n            break; # Good node found.\n        }\n    }\n\n    if {$idx == [llength $::redis_cluster::startup_nodes($id)]} {\n        error \"No good startup node found. $errmsg\"\n    }\n\n    # Put the node that responded as first in the list if it is not\n    # already the first.\n    if {$idx != 0} {\n        set l $::redis_cluster::startup_nodes($id)\n        set left [lrange $l 0 [expr {$idx-1}]]\n        set right [lrange $l [expr {$idx+1}] end]\n        set l [concat [lindex $l $idx] $left $right]\n        set ::redis_cluster::startup_nodes($id) $l\n    }\n\n    # Parse CLUSTER NODES output to populate the nodes description.\n    set nodes {} ; # addr -> node description hash.\n    foreach line [split $nodes_descr \"\\n\"] {\n        set line [string trim $line]\n        if {$line eq {}} continue\n        set args [split $line \" \"]\n        lassign $args nodeid addr flags slaveof pingsent pongrecv configepoch linkstate\n        set slots [lrange $args 8 end]\n        if {$addr eq {:0}} {\n            set addr $start_host:$start_port\n        }\n        lassign [split $addr :] host port\n\n        # Connect to the node\n        set link {}\n        catch {set link [redis $host $port]}\n\n        # Build this node description as an hash.\n        set node [dict create \\\n            id $nodeid \\\n            addr $addr \\\n            host $host \\\n            port $port \\\n            flags $flags \\\n            slaveof $slaveof \\\n            slots $slots \\\n            link $link \\\n        ]\n        dict set nodes $addr $node\n        lappend ::redis_cluster::startup_nodes($id) $addr\n    }\n\n    # Close all the existing links in the old nodes map, and set the new\n    # map as current.\n    foreach n $::redis_cluster::nodes($id) {\n        catch {\n            [dict get $n link] close\n        }\n    }\n    set ::redis_cluster::nodes($id) $nodes\n\n    # Populates the slots -> nodes map.\n    dict for {addr node} $nodes {\n        foreach slotrange [dict get $node slots] {\n            lassign [split $slotrange -] start end\n            if {$end == {}} {set end $start}\n            for {set j $start} {$j <= $end} {incr j} {\n                dict set ::redis_cluster::slots($id) $j $addr\n            }\n        }\n    }\n\n    # Only retain unique entries in the startup nodes list\n    set ::redis_cluster::startup_nodes($id) [lsort -unique $::redis_cluster::startup_nodes($id)]\n}\n\n# Free a redis_cluster handle.\nproc ::redis_cluster::__method__close {id} {\n    catch {\n        set nodes $::redis_cluster::nodes($id)\n        dict for {addr node} $nodes {\n            catch {\n                [dict get $node link] close\n            }\n        }\n    }\n    catch {unset ::redis_cluster::startup_nodes($id)}\n    catch {unset ::redis_cluster::nodes($id)}\n    catch {unset ::redis_cluster::slots($id)}\n    catch {interp alias {} ::redis_cluster::instance$id {}}\n}\n\nproc ::redis_cluster::__dispatch__ {id method args} {\n    if {[info command ::redis_cluster::__method__$method] eq {}} {\n        # Get the keys from the command.\n        set keys [::redis_cluster::get_keys_from_command $method $args]\n        if {$keys eq {}} {\n            error \"Redis command '$method' is not supported by redis_cluster.\"\n        }\n\n        # Resolve the keys in the corresponding hash slot they hash to.\n        set slot [::redis_cluster::get_slot_from_keys $keys]\n        if {$slot eq {}} {\n            error \"Invalid command: multiple keys not hashing to the same slot.\"\n        }\n\n        # Get the node mapped to this slot.\n        set node_addr [dict get $::redis_cluster::slots($id) $slot]\n        if {$node_addr eq {}} {\n            error \"No mapped node for slot $slot.\"\n        }\n\n        # Execute the command in the node we think is the slot owner.\n        set retry 100\n        while {[incr retry -1]} {\n            if {$retry < 5} {after 100}\n            set node [dict get $::redis_cluster::nodes($id) $node_addr]\n            set link [dict get $node link]\n            if {[catch {$link $method {*}$args} e]} {\n                if {$link eq {} || \\\n                    [string range $e 0 4] eq {MOVED} || \\\n                    [string range $e 0 2] eq {I/O} \\\n                } {\n                    # MOVED redirection.\n                    ::redis_cluster::__method__refresh_nodes_map $id\n                    set node_addr [dict get $::redis_cluster::slots($id) $slot]\n                    continue\n                } elseif {[string range $e 0 2] eq {ASK}} {\n                    # ASK redirection.\n                    set node_addr [lindex $e 2]\n                    continue\n                } else {\n                    # Non redirecting error.\n                    error $e $::errorInfo $::errorCode\n                }\n            } else {\n                # OK query went fine\n                return $e\n            }\n        }\n        error \"Too many redirections or failures contacting Redis Cluster.\"\n    } else {\n        uplevel 1 [list ::redis_cluster::__method__$method $id] $args\n    }\n}\n\nproc ::redis_cluster::get_keys_from_command {cmd argv} {\n    set cmd [string tolower $cmd]\n    # Most Redis commands get just one key as first argument.\n    if {[lsearch -exact $::redis_cluster::plain_commands $cmd] != -1} {\n        return [list [lindex $argv 0]]\n    }\n\n    # Special handling for other commands\n    switch -exact $cmd {\n        mget {return $argv}\n        eval {return [lrange $argv 2 1+[lindex $argv 1]]}\n        evalsha {return [lrange $argv 2 1+[lindex $argv 1]]}\n    }\n\n    # All the remaining commands are not handled.\n    return {}\n}\n\n# Returns the CRC16 of the specified string.\n# The CRC parameters are described in the Redis Cluster specification.\nset ::redis_cluster::XMODEMCRC16Lookup {\n    0x0000 0x1021 0x2042 0x3063 0x4084 0x50a5 0x60c6 0x70e7\n    0x8108 0x9129 0xa14a 0xb16b 0xc18c 0xd1ad 0xe1ce 0xf1ef\n    0x1231 0x0210 0x3273 0x2252 0x52b5 0x4294 0x72f7 0x62d6\n    0x9339 0x8318 0xb37b 0xa35a 0xd3bd 0xc39c 0xf3ff 0xe3de\n    0x2462 0x3443 0x0420 0x1401 0x64e6 0x74c7 0x44a4 0x5485\n    0xa56a 0xb54b 0x8528 0x9509 0xe5ee 0xf5cf 0xc5ac 0xd58d\n    0x3653 0x2672 0x1611 0x0630 0x76d7 0x66f6 0x5695 0x46b4\n    0xb75b 0xa77a 0x9719 0x8738 0xf7df 0xe7fe 0xd79d 0xc7bc\n    0x48c4 0x58e5 0x6886 0x78a7 0x0840 0x1861 0x2802 0x3823\n    0xc9cc 0xd9ed 0xe98e 0xf9af 0x8948 0x9969 0xa90a 0xb92b\n    0x5af5 0x4ad4 0x7ab7 0x6a96 0x1a71 0x0a50 0x3a33 0x2a12\n    0xdbfd 0xcbdc 0xfbbf 0xeb9e 0x9b79 0x8b58 0xbb3b 0xab1a\n    0x6ca6 0x7c87 0x4ce4 0x5cc5 0x2c22 0x3c03 0x0c60 0x1c41\n    0xedae 0xfd8f 0xcdec 0xddcd 0xad2a 0xbd0b 0x8d68 0x9d49\n    0x7e97 0x6eb6 0x5ed5 0x4ef4 0x3e13 0x2e32 0x1e51 0x0e70\n    0xff9f 0xefbe 0xdfdd 0xcffc 0xbf1b 0xaf3a 0x9f59 0x8f78\n    0x9188 0x81a9 0xb1ca 0xa1eb 0xd10c 0xc12d 0xf14e 0xe16f\n    0x1080 0x00a1 0x30c2 0x20e3 0x5004 0x4025 0x7046 0x6067\n    0x83b9 0x9398 0xa3fb 0xb3da 0xc33d 0xd31c 0xe37f 0xf35e\n    0x02b1 0x1290 0x22f3 0x32d2 0x4235 0x5214 0x6277 0x7256\n    0xb5ea 0xa5cb 0x95a8 0x8589 0xf56e 0xe54f 0xd52c 0xc50d\n    0x34e2 0x24c3 0x14a0 0x0481 0x7466 0x6447 0x5424 0x4405\n    0xa7db 0xb7fa 0x8799 0x97b8 0xe75f 0xf77e 0xc71d 0xd73c\n    0x26d3 0x36f2 0x0691 0x16b0 0x6657 0x7676 0x4615 0x5634\n    0xd94c 0xc96d 0xf90e 0xe92f 0x99c8 0x89e9 0xb98a 0xa9ab\n    0x5844 0x4865 0x7806 0x6827 0x18c0 0x08e1 0x3882 0x28a3\n    0xcb7d 0xdb5c 0xeb3f 0xfb1e 0x8bf9 0x9bd8 0xabbb 0xbb9a\n    0x4a75 0x5a54 0x6a37 0x7a16 0x0af1 0x1ad0 0x2ab3 0x3a92\n    0xfd2e 0xed0f 0xdd6c 0xcd4d 0xbdaa 0xad8b 0x9de8 0x8dc9\n    0x7c26 0x6c07 0x5c64 0x4c45 0x3ca2 0x2c83 0x1ce0 0x0cc1\n    0xef1f 0xff3e 0xcf5d 0xdf7c 0xaf9b 0xbfba 0x8fd9 0x9ff8\n    0x6e17 0x7e36 0x4e55 0x5e74 0x2e93 0x3eb2 0x0ed1 0x1ef0\n}\n\nproc ::redis_cluster::crc16 {s} {\n    set s [encoding convertto ascii $s]\n    set crc 0\n    foreach char [split $s {}] {\n        scan $char %c byte\n        set crc [expr {(($crc<<8)&0xffff) ^ [lindex $::redis_cluster::XMODEMCRC16Lookup [expr {(($crc>>8)^$byte) & 0xff}]]}]\n    }\n    return $crc\n}\n\n# Hash a single key returning the slot it belongs to, Implemented hash\n# tags as described in the Redis Cluster specification.\nproc ::redis_cluster::hash {key} {\n    # TODO: Handle hash slots.\n    expr {[::redis_cluster::crc16 $key] & 16383}\n}\n\n# Return the slot the specified keys hash to.\n# If the keys hash to multiple slots, an empty string is returned to\n# signal that the command can't be run in Redis Cluster.\nproc ::redis_cluster::get_slot_from_keys {keys} {\n    set slot {}\n    foreach k $keys {\n        set s [::redis_cluster::hash $k]\n        if {$slot eq {}} {\n            set slot $s\n        } elseif {$slot != $s} {\n            return {} ; # Error\n        }\n    }\n    return $slot\n}\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/tests/support/redis.tcl",
    "content": "# Tcl client library - used by the Redis test\n# Copyright (C) 2009-2014 Salvatore Sanfilippo\n# Released under the BSD license like Redis itself\n#\n# Example usage:\n#\n# set r [redis 127.0.0.1 6379]\n# $r lpush mylist foo\n# $r lpush mylist bar\n# $r lrange mylist 0 -1\n# $r close\n#\n# Non blocking usage example:\n#\n# proc handlePong {r type reply} {\n#     puts \"PONG $type '$reply'\"\n#     if {$reply ne \"PONG\"} {\n#         $r ping [list handlePong]\n#     }\n# }\n#\n# set r [redis]\n# $r blocking 0\n# $r get fo [list handlePong]\n#\n# vwait forever\n\npackage require Tcl 8.5\npackage provide redis 0.1\n\nnamespace eval redis {}\nset ::redis::id 0\narray set ::redis::fd {}\narray set ::redis::addr {}\narray set ::redis::blocking {}\narray set ::redis::deferred {}\narray set ::redis::reconnect {}\narray set ::redis::callback {}\narray set ::redis::state {} ;# State in non-blocking reply reading\narray set ::redis::statestack {} ;# Stack of states, for nested mbulks\n\nproc redis {{server 127.0.0.1} {port 6379} {defer 0}} {\n    set fd [socket $server $port]\n    fconfigure $fd -translation binary\n    set id [incr ::redis::id]\n    set ::redis::fd($id) $fd\n    set ::redis::addr($id) [list $server $port]\n    set ::redis::blocking($id) 1\n    set ::redis::deferred($id) $defer\n    set ::redis::reconnect($id) 0\n    ::redis::redis_reset_state $id\n    interp alias {} ::redis::redisHandle$id {} ::redis::__dispatch__ $id\n}\n\n# This is a wrapper to the actual dispatching procedure that handles\n# reconnection if needed.\nproc ::redis::__dispatch__ {id method args} {\n    set errorcode [catch {::redis::__dispatch__raw__ $id $method $args} retval]\n    if {$errorcode && $::redis::reconnect($id) && $::redis::fd($id) eq {}} {\n        # Try again if the connection was lost.\n        # FIXME: we don't re-select the previously selected DB, nor we check\n        # if we are inside a transaction that needs to be re-issued from\n        # scratch.\n        set errorcode [catch {::redis::__dispatch__raw__ $id $method $args} retval]\n    }\n    return -code $errorcode $retval\n}\n\nproc ::redis::__dispatch__raw__ {id method argv} {\n    set fd $::redis::fd($id)\n\n    # Reconnect the link if needed.\n    if {$fd eq {}} {\n        lassign $::redis::addr($id) host port\n        set ::redis::fd($id) [socket $host $port]\n        fconfigure $::redis::fd($id) -translation binary\n        set fd $::redis::fd($id)\n    }\n\n    set blocking $::redis::blocking($id)\n    set deferred $::redis::deferred($id)\n    if {$blocking == 0} {\n        if {[llength $argv] == 0} {\n            error \"Please provide a callback in non-blocking mode\"\n        }\n        set callback [lindex $argv end]\n        set argv [lrange $argv 0 end-1]\n    }\n    if {[info command ::redis::__method__$method] eq {}} {\n        set cmd \"*[expr {[llength $argv]+1}]\\r\\n\"\n        append cmd \"$[string length $method]\\r\\n$method\\r\\n\"\n        foreach a $argv {\n            append cmd \"$[string length $a]\\r\\n$a\\r\\n\"\n        }\n        ::redis::redis_write $fd $cmd\n        if {[catch {flush $fd}]} {\n            set ::redis::fd($id) {}\n            return -code error \"I/O error reading reply\"\n        }\n\n        if {!$deferred} {\n            if {$blocking} {\n                ::redis::redis_read_reply $id $fd\n            } else {\n                # Every well formed reply read will pop an element from this\n                # list and use it as a callback. So pipelining is supported\n                # in non blocking mode.\n                lappend ::redis::callback($id) $callback\n                fileevent $fd readable [list ::redis::redis_readable $fd $id]\n            }\n        }\n    } else {\n        uplevel 1 [list ::redis::__method__$method $id $fd] $argv\n    }\n}\n\nproc ::redis::__method__blocking {id fd val} {\n    set ::redis::blocking($id) $val\n    fconfigure $fd -blocking $val\n}\n\nproc ::redis::__method__reconnect {id fd val} {\n    set ::redis::reconnect($id) $val\n}\n\nproc ::redis::__method__read {id fd} {\n    ::redis::redis_read_reply $id $fd\n}\n\nproc ::redis::__method__write {id fd buf} {\n    ::redis::redis_write $fd $buf\n}\n\nproc ::redis::__method__flush {id fd} {\n    flush $fd\n}\n\nproc ::redis::__method__close {id fd} {\n    catch {close $fd}\n    catch {unset ::redis::fd($id)}\n    catch {unset ::redis::addr($id)}\n    catch {unset ::redis::blocking($id)}\n    catch {unset ::redis::deferred($id)}\n    catch {unset ::redis::reconnect($id)}\n    catch {unset ::redis::state($id)}\n    catch {unset ::redis::statestack($id)}\n    catch {unset ::redis::callback($id)}\n    catch {interp alias {} ::redis::redisHandle$id {}}\n}\n\nproc ::redis::__method__channel {id fd} {\n    return $fd\n}\n\nproc ::redis::__method__deferred {id fd val} {\n    set ::redis::deferred($id) $val\n}\n\nproc ::redis::redis_write {fd buf} {\n    puts -nonewline $fd $buf\n}\n\nproc ::redis::redis_writenl {fd buf} {\n    redis_write $fd $buf\n    redis_write $fd \"\\r\\n\"\n    flush $fd\n}\n\nproc ::redis::redis_readnl {fd len} {\n    set buf [read $fd $len]\n    read $fd 2 ; # discard CR LF\n    return $buf\n}\n\nproc ::redis::redis_bulk_read {fd} {\n    set count [redis_read_line $fd]\n    if {$count == -1} return {}\n    set buf [redis_readnl $fd $count]\n    return $buf\n}\n\nproc ::redis::redis_multi_bulk_read {id fd} {\n    set count [redis_read_line $fd]\n    if {$count == -1} return {}\n    set l {}\n    set err {}\n    for {set i 0} {$i < $count} {incr i} {\n        if {[catch {\n            lappend l [redis_read_reply $id $fd]\n        } e] && $err eq {}} {\n            set err $e\n        }\n    }\n    if {$err ne {}} {return -code error $err}\n    return $l\n}\n\nproc ::redis::redis_read_line fd {\n    string trim [gets $fd]\n}\n\nproc ::redis::redis_read_reply {id fd} {\n    set type [read $fd 1]\n    switch -exact -- $type {\n        : -\n        + {redis_read_line $fd}\n        - {return -code error [redis_read_line $fd]}\n        $ {redis_bulk_read $fd}\n        * {redis_multi_bulk_read $id $fd}\n        default {\n            if {$type eq {}} {\n                set ::redis::fd($id) {}\n                return -code error \"I/O error reading reply\"\n            }\n            return -code error \"Bad protocol, '$type' as reply type byte\"\n        }\n    }\n}\n\nproc ::redis::redis_reset_state id {\n    set ::redis::state($id) [dict create buf {} mbulk -1 bulk -1 reply {}]\n    set ::redis::statestack($id) {}\n}\n\nproc ::redis::redis_call_callback {id type reply} {\n    set cb [lindex $::redis::callback($id) 0]\n    set ::redis::callback($id) [lrange $::redis::callback($id) 1 end]\n    uplevel #0 $cb [list ::redis::redisHandle$id $type $reply]\n    ::redis::redis_reset_state $id\n}\n\n# Read a reply in non-blocking mode.\nproc ::redis::redis_readable {fd id} {\n    if {[eof $fd]} {\n        redis_call_callback $id eof {}\n        ::redis::__method__close $id $fd\n        return\n    }\n    if {[dict get $::redis::state($id) bulk] == -1} {\n        set line [gets $fd]\n        if {$line eq {}} return ;# No complete line available, return\n        switch -exact -- [string index $line 0] {\n            : -\n            + {redis_call_callback $id reply [string range $line 1 end-1]}\n            - {redis_call_callback $id err [string range $line 1 end-1]}\n            $ {\n                dict set ::redis::state($id) bulk \\\n                    [expr [string range $line 1 end-1]+2]\n                if {[dict get $::redis::state($id) bulk] == 1} {\n                    # We got a $-1, hack the state to play well with this.\n                    dict set ::redis::state($id) bulk 2\n                    dict set ::redis::state($id) buf \"\\r\\n\"\n                    ::redis::redis_readable $fd $id\n                }\n            }\n            * {\n                dict set ::redis::state($id) mbulk [string range $line 1 end-1]\n                # Handle *-1\n                if {[dict get $::redis::state($id) mbulk] == -1} {\n                    redis_call_callback $id reply {}\n                }\n            }\n            default {\n                redis_call_callback $id err \\\n                    \"Bad protocol, $type as reply type byte\"\n            }\n        }\n    } else {\n        set totlen [dict get $::redis::state($id) bulk]\n        set buflen [string length [dict get $::redis::state($id) buf]]\n        set toread [expr {$totlen-$buflen}]\n        set data [read $fd $toread]\n        set nread [string length $data]\n        dict append ::redis::state($id) buf $data\n        # Check if we read a complete bulk reply\n        if {[string length [dict get $::redis::state($id) buf]] ==\n            [dict get $::redis::state($id) bulk]} {\n            if {[dict get $::redis::state($id) mbulk] == -1} {\n                redis_call_callback $id reply \\\n                    [string range [dict get $::redis::state($id) buf] 0 end-2]\n            } else {\n                dict with ::redis::state($id) {\n                    lappend reply [string range $buf 0 end-2]\n                    incr mbulk -1\n                    set bulk -1\n                }\n                if {[dict get $::redis::state($id) mbulk] == 0} {\n                    redis_call_callback $id reply \\\n                        [dict get $::redis::state($id) reply]\n                }\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/tests/support/server.tcl",
    "content": "set ::global_overrides {}\nset ::tags {}\nset ::valgrind_errors {}\n\nproc start_server_error {config_file error} {\n    set err {}\n    append err \"Cant' start the Redis server\\n\"\n    append err \"CONFIGURATION:\"\n    append err [exec cat $config_file]\n    append err \"\\nERROR:\"\n    append err [string trim $error]\n    send_data_packet $::test_server_fd err $err\n}\n\nproc check_valgrind_errors stderr {\n    set fd [open $stderr]\n    set buf [read $fd]\n    close $fd\n\n    if {[regexp -- { at 0x} $buf] ||\n        (![regexp -- {definitely lost: 0 bytes} $buf] &&\n         ![regexp -- {no leaks are possible} $buf])} {\n        send_data_packet $::test_server_fd err \"Valgrind error: $buf\\n\"\n    }\n}\n\nproc kill_server config {\n    # nothing to kill when running against external server\n    if {$::external} return\n\n    # nevermind if its already dead\n    if {![is_alive $config]} { return }\n    set pid [dict get $config pid]\n\n    # check for leaks\n    if {![dict exists $config \"skipleaks\"]} {\n        catch {\n            if {[string match {*Darwin*} [exec uname -a]]} {\n                tags {\"leaks\"} {\n                    test \"Check for memory leaks (pid $pid)\" {\n                        set output {0 leaks}\n                        catch {exec leaks $pid} output\n                        if {[string match {*process does not exist*} $output] ||\n                            [string match {*cannot examine*} $output]} {\n                            # In a few tests we kill the server process.\n                            set output \"0 leaks\"\n                        }\n                        set output\n                    } {*0 leaks*}\n                }\n            }\n        }\n    }\n\n    # kill server and wait for the process to be totally exited\n    catch {exec kill $pid}\n    if {$::valgrind} {\n        set max_wait 60000\n    } else {\n        set max_wait 10000\n    }\n    while {[is_alive $config]} {\n        incr wait 10\n\n        if {$wait >= $max_wait} {\n            puts \"Forcing process $pid to exit...\"\n            catch {exec kill -KILL $pid}\n        } elseif {$wait % 1000 == 0} {\n            puts \"Waiting for process $pid to exit...\"\n        }\n        after 10\n    }\n\n    # Check valgrind errors if needed\n    if {$::valgrind} {\n        check_valgrind_errors [dict get $config stderr]\n    }\n\n    # Remove this pid from the set of active pids in the test server.\n    send_data_packet $::test_server_fd server-killed $pid\n}\n\nproc is_alive config {\n    set pid [dict get $config pid]\n    if {[catch {exec ps -p $pid} err]} {\n        return 0\n    } else {\n        return 1\n    }\n}\n\nproc ping_server {host port} {\n    set retval 0\n    if {[catch {\n        set fd [socket $host $port]\n        fconfigure $fd -translation binary\n        puts $fd \"PING\\r\\n\"\n        flush $fd\n        set reply [gets $fd]\n        if {[string range $reply 0 0] eq {+} ||\n            [string range $reply 0 0] eq {-}} {\n            set retval 1\n        }\n        close $fd\n    } e]} {\n        if {$::verbose} {\n            puts -nonewline \".\"\n        }\n    } else {\n        if {$::verbose} {\n            puts -nonewline \"ok\"\n        }\n    }\n    return $retval\n}\n\n# Return 1 if the server at the specified addr is reachable by PING, otherwise\n# returns 0. Performs a try every 50 milliseconds for the specified number\n# of retries.\nproc server_is_up {host port retrynum} {\n    after 10 ;# Use a small delay to make likely a first-try success.\n    set retval 0\n    while {[incr retrynum -1]} {\n        if {[catch {ping_server $host $port} ping]} {\n            set ping 0\n        }\n        if {$ping} {return 1}\n        after 50\n    }\n    return 0\n}\n\n# doesn't really belong here, but highly coupled to code in start_server\nproc tags {tags code} {\n    set ::tags [concat $::tags $tags]\n    uplevel 1 $code\n    set ::tags [lrange $::tags 0 end-[llength $tags]]\n}\n\nproc start_server {options {code undefined}} {\n    # If we are running against an external server, we just push the\n    # host/port pair in the stack the first time\n    if {$::external} {\n        if {[llength $::servers] == 0} {\n            set srv {}\n            dict set srv \"host\" $::host\n            dict set srv \"port\" $::port\n            set client [redis $::host $::port]\n            dict set srv \"client\" $client\n            $client select 9\n\n            # append the server to the stack\n            lappend ::servers $srv\n        }\n        uplevel 1 $code\n        return\n    }\n\n    # setup defaults\n    set baseconfig \"default.conf\"\n    set overrides {}\n    set tags {}\n\n    # parse options\n    foreach {option value} $options {\n        switch $option {\n            \"config\" {\n                set baseconfig $value }\n            \"overrides\" {\n                set overrides $value }\n            \"tags\" {\n                set tags $value\n                set ::tags [concat $::tags $value] }\n            default {\n                error \"Unknown option $option\" }\n        }\n    }\n\n    set data [split [exec cat \"tests/assets/$baseconfig\"] \"\\n\"]\n    set config {}\n    foreach line $data {\n        if {[string length $line] > 0 && [string index $line 0] ne \"#\"} {\n            set elements [split $line \" \"]\n            set directive [lrange $elements 0 0]\n            set arguments [lrange $elements 1 end]\n            dict set config $directive $arguments\n        }\n    }\n\n    # use a different directory every time a server is started\n    dict set config dir [tmpdir server]\n\n    # start every server on a different port\n    set ::port [find_available_port [expr {$::port+1}]]\n    dict set config port $::port\n\n    # apply overrides from global space and arguments\n    foreach {directive arguments} [concat $::global_overrides $overrides] {\n        dict set config $directive $arguments\n    }\n\n    # write new configuration to temporary file\n    set config_file [tmpfile redis.conf]\n    set fp [open $config_file w+]\n    foreach directive [dict keys $config] {\n        puts -nonewline $fp \"$directive \"\n        puts $fp [dict get $config $directive]\n    }\n    close $fp\n\n    set stdout [format \"%s/%s\" [dict get $config \"dir\"] \"stdout\"]\n    set stderr [format \"%s/%s\" [dict get $config \"dir\"] \"stderr\"]\n\n    if {$::valgrind} {\n        set pid [exec valgrind --track-origins=yes --suppressions=src/valgrind.sup --show-reachable=no --show-possibly-lost=no --leak-check=full src/redis-server $config_file > $stdout 2> $stderr &]\n    } else {\n        set pid [exec src/redis-server $config_file > $stdout 2> $stderr &]\n    }\n\n    # Tell the test server about this new instance.\n    send_data_packet $::test_server_fd server-spawned $pid\n\n    # check that the server actually started\n    # ugly but tries to be as fast as possible...\n    if {$::valgrind} {set retrynum 1000} else {set retrynum 100}\n\n    if {$::verbose} {\n        puts -nonewline \"=== ($tags) Starting server ${::host}:${::port} \"\n    }\n\n    if {$code ne \"undefined\"} {\n        set serverisup [server_is_up $::host $::port $retrynum]\n    } else {\n        set serverisup 1\n    }\n\n    if {$::verbose} {\n        puts \"\"\n    }\n\n    if {!$serverisup} {\n        set err {}\n        append err [exec cat $stdout] \"\\n\" [exec cat $stderr]\n        start_server_error $config_file $err\n        return\n    }\n\n    # Wait for actual startup\n    while {![info exists _pid]} {\n        regexp {PID:\\s(\\d+)} [exec cat $stdout] _ _pid\n        after 100\n    }\n\n    # setup properties to be able to initialize a client object\n    set host $::host\n    set port $::port\n    if {[dict exists $config bind]} { set host [dict get $config bind] }\n    if {[dict exists $config port]} { set port [dict get $config port] }\n\n    # setup config dict\n    dict set srv \"config_file\" $config_file\n    dict set srv \"config\" $config\n    dict set srv \"pid\" $pid\n    dict set srv \"host\" $host\n    dict set srv \"port\" $port\n    dict set srv \"stdout\" $stdout\n    dict set srv \"stderr\" $stderr\n\n    # if a block of code is supplied, we wait for the server to become\n    # available, create a client object and kill the server afterwards\n    if {$code ne \"undefined\"} {\n        set line [exec head -n1 $stdout]\n        if {[string match {*already in use*} $line]} {\n            error_and_quit $config_file $line\n        }\n\n        while 1 {\n            # check that the server actually started and is ready for connections\n            if {[exec grep \"ready to accept\" | wc -l < $stdout] > 0} {\n                break\n            }\n            after 10\n        }\n\n        # append the server to the stack\n        lappend ::servers $srv\n\n        # connect client (after server dict is put on the stack)\n        reconnect\n\n        # execute provided block\n        set num_tests $::num_tests\n        if {[catch { uplevel 1 $code } error]} {\n            set backtrace $::errorInfo\n\n            # Kill the server without checking for leaks\n            dict set srv \"skipleaks\" 1\n            kill_server $srv\n\n            # Print warnings from log\n            puts [format \"\\nLogged warnings (pid %d):\" [dict get $srv \"pid\"]]\n            set warnings [warnings_from_file [dict get $srv \"stdout\"]]\n            if {[string length $warnings] > 0} {\n                puts \"$warnings\"\n            } else {\n                puts \"(none)\"\n            }\n            puts \"\"\n\n            error $error $backtrace\n        }\n\n        # Don't do the leak check when no tests were run\n        if {$num_tests == $::num_tests} {\n            dict set srv \"skipleaks\" 1\n        }\n\n        # pop the server object\n        set ::servers [lrange $::servers 0 end-1]\n\n        set ::tags [lrange $::tags 0 end-[llength $tags]]\n        kill_server $srv\n    } else {\n        set ::tags [lrange $::tags 0 end-[llength $tags]]\n        set _ $srv\n    }\n}\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/tests/support/test.tcl",
    "content": "set ::num_tests 0\nset ::num_passed 0\nset ::num_failed 0\nset ::tests_failed {}\n\nproc fail {msg} {\n    error \"assertion:$msg\"\n}\n\nproc assert {condition} {\n    if {![uplevel 1 [list expr $condition]]} {\n        error \"assertion:Expected condition '$condition' to be true ([uplevel 1 [list subst -nocommands $condition]])\"\n    }\n}\n\nproc assert_match {pattern value} {\n    if {![string match $pattern $value]} {\n        error \"assertion:Expected '$value' to match '$pattern'\"\n    }\n}\n\nproc assert_equal {expected value {detail \"\"}} {\n    if {$expected ne $value} {\n        if {$detail ne \"\"} {\n            set detail \" (detail: $detail)\"\n        }\n        error \"assertion:Expected '$value' to be equal to '$expected'$detail\"\n    }\n}\n\nproc assert_error {pattern code} {\n    if {[catch {uplevel 1 $code} error]} {\n        assert_match $pattern $error\n    } else {\n        error \"assertion:Expected an error but nothing was caught\"\n    }\n}\n\nproc assert_encoding {enc key} {\n    set dbg [r debug object $key]\n    assert_match \"* encoding:$enc *\" $dbg\n}\n\nproc assert_type {type key} {\n    assert_equal $type [r type $key]\n}\n\n# Wait for the specified condition to be true, with the specified number of\n# max retries and delay between retries. Otherwise the 'elsescript' is\n# executed.\nproc wait_for_condition {maxtries delay e _else_ elsescript} {\n    while {[incr maxtries -1] >= 0} {\n        set errcode [catch {uplevel 1 [list expr $e]} result]\n        if {$errcode == 0} {\n            if {$result} break\n        } else {\n            return -code $errcode $result\n        }\n        after $delay\n    }\n    if {$maxtries == -1} {\n        set errcode [catch [uplevel 1 $elsescript] result]\n        return -code $errcode $result\n    }\n}\n\nproc test {name code {okpattern undefined}} {\n    # abort if tagged with a tag to deny\n    foreach tag $::denytags {\n        if {[lsearch $::tags $tag] >= 0} {\n            return\n        }\n    }\n\n    # check if tagged with at least 1 tag to allow when there *is* a list\n    # of tags to allow, because default policy is to run everything\n    if {[llength $::allowtags] > 0} {\n        set matched 0\n        foreach tag $::allowtags {\n            if {[lsearch $::tags $tag] >= 0} {\n                incr matched\n            }\n        }\n        if {$matched < 1} {\n            return\n        }\n    }\n\n    incr ::num_tests\n    set details {}\n    lappend details \"$name in $::curfile\"\n\n    send_data_packet $::test_server_fd testing $name\n\n    if {[catch {set retval [uplevel 1 $code]} error]} {\n        if {[string match \"assertion:*\" $error]} {\n            set msg [string range $error 10 end]\n            lappend details $msg\n            lappend ::tests_failed $details\n\n            incr ::num_failed\n            send_data_packet $::test_server_fd err [join $details \"\\n\"]\n        } else {\n            # Re-raise, let handler up the stack take care of this.\n            error $error $::errorInfo\n        }\n    } else {\n        if {$okpattern eq \"undefined\" || $okpattern eq $retval || [string match $okpattern $retval]} {\n            incr ::num_passed\n            send_data_packet $::test_server_fd ok $name\n        } else {\n            set msg \"Expected '$okpattern' to equal or match '$retval'\"\n            lappend details $msg\n            lappend ::tests_failed $details\n\n            incr ::num_failed\n            send_data_packet $::test_server_fd err [join $details \"\\n\"]\n        }\n    }\n\n    if {$::traceleaks} {\n        set output [exec leaks redis-server]\n        if {![string match {*0 leaks*} $output]} {\n            send_data_packet $::test_server_fd err \"Detected a memory leak in test '$name': $output\"\n        }\n    }\n}\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/tests/support/tmpfile.tcl",
    "content": "set ::tmpcounter 0\nset ::tmproot \"./tests/tmp\"\nfile mkdir $::tmproot\n\n# returns a dirname unique to this process to write to\nproc tmpdir {basename} {\n    set dir [file join $::tmproot $basename.[pid].[incr ::tmpcounter]]\n    file mkdir $dir\n    set _ $dir\n}\n\n# return a filename unique to this process to write to\nproc tmpfile {basename} {\n    file join $::tmproot $basename.[pid].[incr ::tmpcounter]\n}\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/tests/support/util.tcl",
    "content": "proc randstring {min max {type binary}} {\n    set len [expr {$min+int(rand()*($max-$min+1))}]\n    set output {}\n    if {$type eq {binary}} {\n        set minval 0\n        set maxval 255\n    } elseif {$type eq {alpha}} {\n        set minval 48\n        set maxval 122\n    } elseif {$type eq {compr}} {\n        set minval 48\n        set maxval 52\n    }\n    while {$len} {\n        append output [format \"%c\" [expr {$minval+int(rand()*($maxval-$minval+1))}]]\n        incr len -1\n    }\n    return $output\n}\n\n# Useful for some test\nproc zlistAlikeSort {a b} {\n    if {[lindex $a 0] > [lindex $b 0]} {return 1}\n    if {[lindex $a 0] < [lindex $b 0]} {return -1}\n    string compare [lindex $a 1] [lindex $b 1]\n}\n\n# Return all log lines starting with the first line that contains a warning.\n# Generally, this will be an assertion error with a stack trace.\nproc warnings_from_file {filename} {\n    set lines [split [exec cat $filename] \"\\n\"]\n    set matched 0\n    set logall 0\n    set result {}\n    foreach line $lines {\n        if {[string match {*REDIS BUG REPORT START*} $line]} {\n            set logall 1\n        }\n        if {[regexp {^\\[\\d+\\]\\s+\\d+\\s+\\w+\\s+\\d{2}:\\d{2}:\\d{2} \\#} $line]} {\n            set matched 1\n        }\n        if {$logall || $matched} {\n            lappend result $line\n        }\n    }\n    join $result \"\\n\"\n}\n\n# Return value for INFO property\nproc status {r property} {\n    if {[regexp \"\\r\\n$property:(.*?)\\r\\n\" [{*}$r info] _ value]} {\n        set _ $value\n    }\n}\n\nproc waitForBgsave r {\n    while 1 {\n        if {[status r rdb_bgsave_in_progress] eq 1} {\n            if {$::verbose} {\n                puts -nonewline \"\\nWaiting for background save to finish... \"\n                flush stdout\n            }\n            after 1000\n        } else {\n            break\n        }\n    }\n}\n\nproc waitForBgrewriteaof r {\n    while 1 {\n        if {[status r aof_rewrite_in_progress] eq 1} {\n            if {$::verbose} {\n                puts -nonewline \"\\nWaiting for background AOF rewrite to finish... \"\n                flush stdout\n            }\n            after 1000\n        } else {\n            break\n        }\n    }\n}\n\nproc wait_for_sync r {\n    while 1 {\n        if {[status $r master_link_status] eq \"down\"} {\n            after 10\n        } else {\n            break\n        }\n    }\n}\n\n# Random integer between 0 and max (excluded).\nproc randomInt {max} {\n    expr {int(rand()*$max)}\n}\n\n# Random signed integer between -max and max (both extremes excluded).\nproc randomSignedInt {max} {\n    set i [randomInt $max]\n    if {rand() > 0.5} {\n        set i -$i\n    }\n    return $i\n}\n\nproc randpath args {\n    set path [expr {int(rand()*[llength $args])}]\n    uplevel 1 [lindex $args $path]\n}\n\nproc randomValue {} {\n    randpath {\n        # Small enough to likely collide\n        randomSignedInt 1000\n    } {\n        # 32 bit compressible signed/unsigned\n        randpath {randomSignedInt 2000000000} {randomSignedInt 4000000000}\n    } {\n        # 64 bit\n        randpath {randomSignedInt 1000000000000}\n    } {\n        # Random string\n        randpath {randstring 0 256 alpha} \\\n                {randstring 0 256 compr} \\\n                {randstring 0 256 binary}\n    }\n}\n\nproc randomKey {} {\n    randpath {\n        # Small enough to likely collide\n        randomInt 1000\n    } {\n        # 32 bit compressible signed/unsigned\n        randpath {randomInt 2000000000} {randomInt 4000000000}\n    } {\n        # 64 bit\n        randpath {randomInt 1000000000000}\n    } {\n        # Random string\n        randpath {randstring 1 256 alpha} \\\n                {randstring 1 256 compr}\n    }\n}\n\nproc findKeyWithType {r type} {\n    for {set j 0} {$j < 20} {incr j} {\n        set k [{*}$r randomkey]\n        if {$k eq {}} {\n            return {}\n        }\n        if {[{*}$r type $k] eq $type} {\n            return $k\n        }\n    }\n    return {}\n}\n\nproc createComplexDataset {r ops {opt {}}} {\n    for {set j 0} {$j < $ops} {incr j} {\n        set k [randomKey]\n        set k2 [randomKey]\n        set f [randomValue]\n        set v [randomValue]\n\n        if {[lsearch -exact $opt useexpire] != -1} {\n            if {rand() < 0.1} {\n                {*}$r expire [randomKey] [randomInt 2]\n            }\n        }\n\n        randpath {\n            set d [expr {rand()}]\n        } {\n            set d [expr {rand()}]\n        } {\n            set d [expr {rand()}]\n        } {\n            set d [expr {rand()}]\n        } {\n            set d [expr {rand()}]\n        } {\n            randpath {set d +inf} {set d -inf}\n        }\n        set t [{*}$r type $k]\n\n        if {$t eq {none}} {\n            randpath {\n                {*}$r set $k $v\n            } {\n                {*}$r lpush $k $v\n            } {\n                {*}$r sadd $k $v\n            } {\n                {*}$r zadd $k $d $v\n            } {\n                {*}$r hset $k $f $v\n            } {\n                {*}$r del $k\n            }\n            set t [{*}$r type $k]\n        }\n\n        switch $t {\n            {string} {\n                # Nothing to do\n            }\n            {list} {\n                randpath {{*}$r lpush $k $v} \\\n                        {{*}$r rpush $k $v} \\\n                        {{*}$r lrem $k 0 $v} \\\n                        {{*}$r rpop $k} \\\n                        {{*}$r lpop $k}\n            }\n            {set} {\n                randpath {{*}$r sadd $k $v} \\\n                        {{*}$r srem $k $v} \\\n                        {\n                            set otherset [findKeyWithType {*}$r set]\n                            if {$otherset ne {}} {\n                                randpath {\n                                    {*}$r sunionstore $k2 $k $otherset\n                                } {\n                                    {*}$r sinterstore $k2 $k $otherset\n                                } {\n                                    {*}$r sdiffstore $k2 $k $otherset\n                                }\n                            }\n                        }\n            }\n            {zset} {\n                randpath {{*}$r zadd $k $d $v} \\\n                        {{*}$r zrem $k $v} \\\n                        {\n                            set otherzset [findKeyWithType {*}$r zset]\n                            if {$otherzset ne {}} {\n                                randpath {\n                                    {*}$r zunionstore $k2 2 $k $otherzset\n                                } {\n                                    {*}$r zinterstore $k2 2 $k $otherzset\n                                }\n                            }\n                        }\n            }\n            {hash} {\n                randpath {{*}$r hset $k $f $v} \\\n                        {{*}$r hdel $k $f}\n            }\n        }\n    }\n}\n\nproc formatCommand {args} {\n    set cmd \"*[llength $args]\\r\\n\"\n    foreach a $args {\n        append cmd \"$[string length $a]\\r\\n$a\\r\\n\"\n    }\n    set _ $cmd\n}\n\nproc csvdump r {\n    set o {}\n    for {set db 0} {$db < 16} {incr db} {\n        {*}$r select $db\n        foreach k [lsort [{*}$r keys *]] {\n            set type [{*}$r type $k]\n            append o [csvstring $db] , [csvstring $k] , [csvstring $type] ,\n            switch $type {\n                string {\n                    append o [csvstring [{*}$r get $k]] \"\\n\"\n                }\n                list {\n                    foreach e [{*}$r lrange $k 0 -1] {\n                        append o [csvstring $e] ,\n                    }\n                    append o \"\\n\"\n                }\n                set {\n                    foreach e [lsort [{*}$r smembers $k]] {\n                        append o [csvstring $e] ,\n                    }\n                    append o \"\\n\"\n                }\n                zset {\n                    foreach e [{*}$r zrange $k 0 -1 withscores] {\n                        append o [csvstring $e] ,\n                    }\n                    append o \"\\n\"\n                }\n                hash {\n                    set fields [{*}$r hgetall $k]\n                    set newfields {}\n                    foreach {k v} $fields {\n                        lappend newfields [list $k $v]\n                    }\n                    set fields [lsort -index 0 $newfields]\n                    foreach kv $fields {\n                        append o [csvstring [lindex $kv 0]] ,\n                        append o [csvstring [lindex $kv 1]] ,\n                    }\n                    append o \"\\n\"\n                }\n            }\n        }\n    }\n    {*}$r select 9\n    return $o\n}\n\nproc csvstring s {\n    return \"\\\"$s\\\"\"\n}\n\nproc roundFloat f {\n    format \"%.10g\" $f\n}\n\nproc find_available_port start {\n    for {set j $start} {$j < $start+1024} {incr j} {\n        if {[catch {set fd1 [socket 127.0.0.1 $j]}] &&\n            [catch {set fd2 [socket 127.0.0.1 [expr $j+10000]]}]} {\n            return $j\n        } else {\n            catch {\n                close $fd1\n                close $fd2\n            }\n        }\n    }\n    if {$j == $start+1024} {\n        error \"Can't find a non busy port in the $start-[expr {$start+1023}] range.\"\n    }\n}\n\n# Test if TERM looks like to support colors\nproc color_term {} {\n    expr {[info exists ::env(TERM)] && [string match *xterm* $::env(TERM)]}\n}\n\nproc colorstr {color str} {\n    if {[color_term]} {\n        set b 0\n        if {[string range $color 0 4] eq {bold-}} {\n            set b 1\n            set color [string range $color 5 end]\n        }\n        switch $color {\n            red {set colorcode {31}}\n            green {set colorcode {32}}\n            yellow {set colorcode {33}}\n            blue {set colorcode {34}}\n            magenta {set colorcode {35}}\n            cyan {set colorcode {36}}\n            white {set colorcode {37}}\n            default {set colorcode {37}}\n        }\n        if {$colorcode ne {}} {\n            return \"\\033\\[$b;${colorcode};49m$str\\033\\[0m\"\n        }\n    } else {\n        return $str\n    }\n}\n\n# Execute a background process writing random data for the specified number\n# of seconds to the specified Redis instance.\nproc start_write_load {host port seconds} {\n    set tclsh [info nameofexecutable]\n    exec $tclsh tests/helpers/gen_write_load.tcl $host $port $seconds &\n}\n\n# Stop a process generating write load executed with start_write_load.\nproc stop_write_load {handle} {\n    catch {exec /bin/kill -9 $handle}\n}\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/tests/test_helper.tcl",
    "content": "# Redis test suite. Copyright (C) 2009 Salvatore Sanfilippo antirez@gmail.com\n# This software is released under the BSD License. See the COPYING file for\n# more information.\n\npackage require Tcl 8.5\n\nset tcl_precision 17\nsource tests/support/redis.tcl\nsource tests/support/server.tcl\nsource tests/support/tmpfile.tcl\nsource tests/support/test.tcl\nsource tests/support/util.tcl\n\nset ::all_tests {\n    unit/printver\n    unit/dump\n    unit/auth\n    unit/protocol\n    unit/keyspace\n    unit/scan\n    unit/type/string\n    unit/type/incr\n    unit/type/list\n    unit/type/list-2\n    unit/type/list-3\n    unit/type/set\n    unit/type/zset\n    unit/type/hash\n    unit/sort\n    unit/expire\n    unit/other\n    unit/multi\n    unit/quit\n    unit/aofrw\n    integration/replication\n    integration/replication-2\n    integration/replication-3\n    integration/replication-4\n    integration/replication-psync\n    integration/aof\n    integration/rdb\n    integration/convert-zipmap-hash-on-load\n    integration/logging\n    unit/pubsub\n    unit/slowlog\n    unit/scripting\n    unit/maxmemory\n    unit/introspection\n    unit/introspection-2\n    unit/limits\n    unit/obuf-limits\n    unit/bitops\n    unit/bitfield\n    unit/geo\n    unit/memefficiency\n    unit/hyperloglog\n}\n# Index to the next test to run in the ::all_tests list.\nset ::next_test 0\n\nset ::host 127.0.0.1\nset ::port 21111\nset ::traceleaks 0\nset ::valgrind 0\nset ::verbose 0\nset ::quiet 0\nset ::denytags {}\nset ::allowtags {}\nset ::external 0; # If \"1\" this means, we are running against external instance\nset ::file \"\"; # If set, runs only the tests in this comma separated list\nset ::curfile \"\"; # Hold the filename of the current suite\nset ::accurate 0; # If true runs fuzz tests with more iterations\nset ::force_failure 0\nset ::timeout 600; # 10 minutes without progresses will quit the test.\nset ::last_progress [clock seconds]\nset ::active_servers {} ; # Pids of active Redis instances.\n\n# Set to 1 when we are running in client mode. The Redis test uses a\n# server-client model to run tests simultaneously. The server instance\n# runs the specified number of client instances that will actually run tests.\n# The server is responsible of showing the result to the user, and exit with\n# the appropriate exit code depending on the test outcome.\nset ::client 0\nset ::numclients 16\n\nproc execute_tests name {\n    set path \"tests/$name.tcl\"\n    set ::curfile $path\n    source $path\n    send_data_packet $::test_server_fd done \"$name\"\n}\n\n# Setup a list to hold a stack of server configs. When calls to start_server\n# are nested, use \"srv 0 pid\" to get the pid of the inner server. To access\n# outer servers, use \"srv -1 pid\" etcetera.\nset ::servers {}\nproc srv {args} {\n    set level 0\n    if {[string is integer [lindex $args 0]]} {\n        set level [lindex $args 0]\n        set property [lindex $args 1]\n    } else {\n        set property [lindex $args 0]\n    }\n    set srv [lindex $::servers end+$level]\n    dict get $srv $property\n}\n\n# Provide easy access to the client for the inner server. It's possible to\n# prepend the argument list with a negative level to access clients for\n# servers running in outer blocks.\nproc r {args} {\n    set level 0\n    if {[string is integer [lindex $args 0]]} {\n        set level [lindex $args 0]\n        set args [lrange $args 1 end]\n    }\n    [srv $level \"client\"] {*}$args\n}\n\nproc reconnect {args} {\n    set level [lindex $args 0]\n    if {[string length $level] == 0 || ![string is integer $level]} {\n        set level 0\n    }\n\n    set srv [lindex $::servers end+$level]\n    set host [dict get $srv \"host\"]\n    set port [dict get $srv \"port\"]\n    set config [dict get $srv \"config\"]\n    set client [redis $host $port]\n    dict set srv \"client\" $client\n\n    # select the right db when we don't have to authenticate\n    if {![dict exists $config \"requirepass\"]} {\n        $client select 9\n    }\n\n    # re-set $srv in the servers list\n    lset ::servers end+$level $srv\n}\n\nproc redis_deferring_client {args} {\n    set level 0\n    if {[llength $args] > 0 && [string is integer [lindex $args 0]]} {\n        set level [lindex $args 0]\n        set args [lrange $args 1 end]\n    }\n\n    # create client that defers reading reply\n    set client [redis [srv $level \"host\"] [srv $level \"port\"] 1]\n\n    # select the right db and read the response (OK)\n    $client select 9\n    $client read\n    return $client\n}\n\n# Provide easy access to INFO properties. Same semantic as \"proc r\".\nproc s {args} {\n    set level 0\n    if {[string is integer [lindex $args 0]]} {\n        set level [lindex $args 0]\n        set args [lrange $args 1 end]\n    }\n    status [srv $level \"client\"] [lindex $args 0]\n}\n\nproc cleanup {} {\n    if {!$::quiet} {puts -nonewline \"Cleanup: may take some time... \"}\n    flush stdout\n    catch {exec rm -rf {*}[glob tests/tmp/redis.conf.*]}\n    catch {exec rm -rf {*}[glob tests/tmp/server.*]}\n    if {!$::quiet} {puts \"OK\"}\n}\n\nproc test_server_main {} {\n    cleanup\n    set tclsh [info nameofexecutable]\n    # Open a listening socket, trying different ports in order to find a\n    # non busy one.\n    set port [find_available_port 11111]\n    if {!$::quiet} {\n        puts \"Starting test server at port $port\"\n    }\n    socket -server accept_test_clients -myaddr 127.0.0.1 $port\n\n    # Start the client instances\n    set ::clients_pids {}\n    set start_port [expr {$::port+100}]\n    for {set j 0} {$j < $::numclients} {incr j} {\n        set start_port [find_available_port $start_port]\n        set p [exec $tclsh [info script] {*}$::argv \\\n            --client $port --port $start_port &]\n        lappend ::clients_pids $p\n        incr start_port 10\n    }\n\n    # Setup global state for the test server\n    set ::idle_clients {}\n    set ::active_clients {}\n    array set ::active_clients_task {}\n    array set ::clients_start_time {}\n    set ::clients_time_history {}\n    set ::failed_tests {}\n\n    # Enter the event loop to handle clients I/O\n    after 100 test_server_cron\n    vwait forever\n}\n\n# This function gets called 10 times per second.\nproc test_server_cron {} {\n    set elapsed [expr {[clock seconds]-$::last_progress}]\n\n    if {$elapsed > $::timeout} {\n        set err \"\\[[colorstr red TIMEOUT]\\]: clients state report follows.\"\n        puts $err\n        show_clients_state\n        kill_clients\n        force_kill_all_servers\n        the_end\n    }\n\n    after 100 test_server_cron\n}\n\nproc accept_test_clients {fd addr port} {\n    fconfigure $fd -encoding binary\n    fileevent $fd readable [list read_from_test_client $fd]\n}\n\n# This is the readable handler of our test server. Clients send us messages\n# in the form of a status code such and additional data. Supported\n# status types are:\n#\n# ready: the client is ready to execute the command. Only sent at client\n#        startup. The server will queue the client FD in the list of idle\n#        clients.\n# testing: just used to signal that a given test started.\n# ok: a test was executed with success.\n# err: a test was executed with an error.\n# exception: there was a runtime exception while executing the test.\n# done: all the specified test file was processed, this test client is\n#       ready to accept a new task.\nproc read_from_test_client fd {\n    set bytes [gets $fd]\n    set payload [read $fd $bytes]\n    foreach {status data} $payload break\n    set ::last_progress [clock seconds]\n\n    if {$status eq {ready}} {\n        if {!$::quiet} {\n            puts \"\\[$status\\]: $data\"\n        }\n        signal_idle_client $fd\n    } elseif {$status eq {done}} {\n        set elapsed [expr {[clock seconds]-$::clients_start_time($fd)}]\n        set all_tests_count [llength $::all_tests]\n        set running_tests_count [expr {[llength $::active_clients]-1}]\n        set completed_tests_count [expr {$::next_test-$running_tests_count}]\n        puts \"\\[$completed_tests_count/$all_tests_count [colorstr yellow $status]\\]: $data ($elapsed seconds)\"\n        lappend ::clients_time_history $elapsed $data\n        signal_idle_client $fd\n        set ::active_clients_task($fd) DONE\n    } elseif {$status eq {ok}} {\n        if {!$::quiet} {\n            puts \"\\[[colorstr green $status]\\]: $data\"\n        }\n        set ::active_clients_task($fd) \"(OK) $data\"\n    } elseif {$status eq {err}} {\n        set err \"\\[[colorstr red $status]\\]: $data\"\n        puts $err\n        lappend ::failed_tests $err\n        set ::active_clients_task($fd) \"(ERR) $data\"\n    } elseif {$status eq {exception}} {\n        puts \"\\[[colorstr red $status]\\]: $data\"\n        kill_clients\n        force_kill_all_servers\n        exit 1\n    } elseif {$status eq {testing}} {\n        set ::active_clients_task($fd) \"(IN PROGRESS) $data\"\n    } elseif {$status eq {server-spawned}} {\n        lappend ::active_servers $data\n    } elseif {$status eq {server-killed}} {\n        set ::active_servers [lsearch -all -inline -not -exact $::active_servers $data]\n    } else {\n        if {!$::quiet} {\n            puts \"\\[$status\\]: $data\"\n        }\n    }\n}\n\nproc show_clients_state {} {\n    # The following loop is only useful for debugging tests that may\n    # enter an infinite loop. Commented out normally.\n    foreach x $::active_clients {\n        if {[info exist ::active_clients_task($x)]} {\n            puts \"$x => $::active_clients_task($x)\"\n        } else {\n            puts \"$x => ???\"\n        }\n    }\n}\n\nproc kill_clients {} {\n    foreach p $::clients_pids {\n        catch {exec kill $p}\n    }\n}\n\nproc force_kill_all_servers {} {\n    foreach p $::active_servers {\n        puts \"Killing still running Redis server $p\"\n        catch {exec kill -9 $p}\n    }\n}\n\n# A new client is idle. Remove it from the list of active clients and\n# if there are still test units to run, launch them.\nproc signal_idle_client fd {\n    # Remove this fd from the list of active clients.\n    set ::active_clients \\\n        [lsearch -all -inline -not -exact $::active_clients $fd]\n\n    if 0 {show_clients_state}\n\n    # New unit to process?\n    if {$::next_test != [llength $::all_tests]} {\n        if {!$::quiet} {\n            puts [colorstr bold-white \"Testing [lindex $::all_tests $::next_test]\"]\n            set ::active_clients_task($fd) \"ASSIGNED: $fd ([lindex $::all_tests $::next_test])\"\n        }\n        set ::clients_start_time($fd) [clock seconds]\n        send_data_packet $fd run [lindex $::all_tests $::next_test]\n        lappend ::active_clients $fd\n        incr ::next_test\n    } else {\n        lappend ::idle_clients $fd\n        if {[llength $::active_clients] == 0} {\n            the_end\n        }\n    }\n}\n\n# The the_end function gets called when all the test units were already\n# executed, so the test finished.\nproc the_end {} {\n    # TODO: print the status, exit with the rigth exit code.\n    puts \"\\n                   The End\\n\"\n    puts \"Execution time of different units:\"\n    foreach {time name} $::clients_time_history {\n        puts \"  $time seconds - $name\"\n    }\n    if {[llength $::failed_tests]} {\n        puts \"\\n[colorstr bold-red {!!! WARNING}] The following tests failed:\\n\"\n        foreach failed $::failed_tests {\n            puts \"*** $failed\"\n        }\n        cleanup\n        exit 1\n    } else {\n        puts \"\\n[colorstr bold-white {\\o/}] [colorstr bold-green {All tests passed without errors!}]\\n\"\n        cleanup\n        exit 0\n    }\n}\n\n# The client is not even driven (the test server is instead) as we just need\n# to read the command, execute, reply... all this in a loop.\nproc test_client_main server_port {\n    set ::test_server_fd [socket localhost $server_port]\n    fconfigure $::test_server_fd -encoding binary\n    send_data_packet $::test_server_fd ready [pid]\n    while 1 {\n        set bytes [gets $::test_server_fd]\n        set payload [read $::test_server_fd $bytes]\n        foreach {cmd data} $payload break\n        if {$cmd eq {run}} {\n            execute_tests $data\n        } else {\n            error \"Unknown test client command: $cmd\"\n        }\n    }\n}\n\nproc send_data_packet {fd status data} {\n    set payload [list $status $data]\n    puts $fd [string length $payload]\n    puts -nonewline $fd $payload\n    flush $fd\n}\n\nproc print_help_screen {} {\n    puts [join {\n        \"--valgrind         Run the test over valgrind.\"\n        \"--accurate         Run slow randomized tests for more iterations.\"\n        \"--quiet            Don't show individual tests.\"\n        \"--single <unit>    Just execute the specified unit (see next option).\"\n        \"--list-tests       List all the available test units.\"\n        \"--clients <num>    Number of test clients (default 16).\"\n        \"--timeout <sec>    Test timeout in seconds (default 10 min).\"\n        \"--force-failure    Force the execution of a test that always fails.\"\n        \"--help             Print this help screen.\"\n    } \"\\n\"]\n}\n\n# parse arguments\nfor {set j 0} {$j < [llength $argv]} {incr j} {\n    set opt [lindex $argv $j]\n    set arg [lindex $argv [expr $j+1]]\n    if {$opt eq {--tags}} {\n        foreach tag $arg {\n            if {[string index $tag 0] eq \"-\"} {\n                lappend ::denytags [string range $tag 1 end]\n            } else {\n                lappend ::allowtags $tag\n            }\n        }\n        incr j\n    } elseif {$opt eq {--valgrind}} {\n        set ::valgrind 1\n    } elseif {$opt eq {--quiet}} {\n        set ::quiet 1\n    } elseif {$opt eq {--host}} {\n        set ::external 1\n        set ::host $arg\n        incr j\n    } elseif {$opt eq {--port}} {\n        set ::port $arg\n        incr j\n    } elseif {$opt eq {--accurate}} {\n        set ::accurate 1\n    } elseif {$opt eq {--force-failure}} {\n        set ::force_failure 1\n    } elseif {$opt eq {--single}} {\n        set ::all_tests $arg\n        incr j\n    } elseif {$opt eq {--list-tests}} {\n        foreach t $::all_tests {\n            puts $t\n        }\n        exit 0\n    } elseif {$opt eq {--client}} {\n        set ::client 1\n        set ::test_server_port $arg\n        incr j\n    } elseif {$opt eq {--clients}} {\n        set ::numclients $arg\n        incr j\n    } elseif {$opt eq {--timeout}} {\n        set ::timeout $arg\n        incr j\n    } elseif {$opt eq {--help}} {\n        print_help_screen\n        exit 0\n    } else {\n        puts \"Wrong argument: $opt\"\n        exit 1\n    }\n}\n\nproc attach_to_replication_stream {} {\n    set s [socket [srv 0 \"host\"] [srv 0 \"port\"]]\n    fconfigure $s -translation binary\n    puts -nonewline $s \"SYNC\\r\\n\"\n    flush $s\n\n    # Get the count\n    while 1 {\n        set count [gets $s]\n        set prefix [string range $count 0 0]\n        if {$prefix ne {}} break; # Newlines are allowed as PINGs.\n    }\n    if {$prefix ne {$}} {\n        error \"attach_to_replication_stream error. Received '$count' as count.\"\n    }\n    set count [string range $count 1 end]\n\n    # Consume the bulk payload\n    while {$count} {\n        set buf [read $s $count]\n        set count [expr {$count-[string length $buf]}]\n    }\n    return $s\n}\n\nproc read_from_replication_stream {s} {\n    fconfigure $s -blocking 0\n    set attempt 0\n    while {[gets $s count] == -1} {\n        if {[incr attempt] == 10} return \"\"\n        after 100\n    }\n    fconfigure $s -blocking 1\n    set count [string range $count 1 end]\n\n    # Return a list of arguments for the command.\n    set res {}\n    for {set j 0} {$j < $count} {incr j} {\n        read $s 1\n        set arg [::redis::redis_bulk_read $s]\n        if {$j == 0} {set arg [string tolower $arg]}\n        lappend res $arg\n    }\n    return $res\n}\n\nproc assert_replication_stream {s patterns} {\n    for {set j 0} {$j < [llength $patterns]} {incr j} {\n        assert_match [lindex $patterns $j] [read_from_replication_stream $s]\n    }\n}\n\nproc close_replication_stream {s} {\n    close $s\n}\n\n# With the parallel test running multiple Redis instances at the same time\n# we need a fast enough computer, otherwise a lot of tests may generate\n# false positives.\n# If the computer is too slow we revert the sequential test without any\n# parallelism, that is, clients == 1.\nproc is_a_slow_computer {} {\n    set start [clock milliseconds]\n    for {set j 0} {$j < 1000000} {incr j} {}\n    set elapsed [expr [clock milliseconds]-$start]\n    expr {$elapsed > 200}\n}\n\nif {$::client} {\n    if {[catch { test_client_main $::test_server_port } err]} {\n        set estr \"Executing test client: $err.\\n$::errorInfo\"\n        if {[catch {send_data_packet $::test_server_fd exception $estr}]} {\n            puts $estr\n        }\n        exit 1\n    }\n} else {\n    if {[is_a_slow_computer]} {\n        puts \"** SLOW COMPUTER ** Using a single client to avoid false positives.\"\n        set ::numclients 1\n    }\n\n    if {[catch { test_server_main } err]} {\n        if {[string length $err] > 0} {\n            # only display error when not generated by the test suite\n            if {$err ne \"exception\"} {\n                puts $::errorInfo\n            }\n            exit 1\n        }\n    }\n}\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/tests/unit/aofrw.tcl",
    "content": "start_server {tags {\"aofrw\"}} {\n    # Enable the AOF\n    r config set appendonly yes\n    r config set auto-aof-rewrite-percentage 0 ; # Disable auto-rewrite.\n    waitForBgrewriteaof r\n\n    test {AOF rewrite during write load} {\n        # Start a write load for 10 seconds\n        set master [srv 0 client]\n        set master_host [srv 0 host]\n        set master_port [srv 0 port]\n        set load_handle0 [start_write_load $master_host $master_port 10]\n        set load_handle1 [start_write_load $master_host $master_port 10]\n        set load_handle2 [start_write_load $master_host $master_port 10]\n        set load_handle3 [start_write_load $master_host $master_port 10]\n        set load_handle4 [start_write_load $master_host $master_port 10]\n\n        # Make sure the instance is really receiving data\n        wait_for_condition 50 100 {\n            [r dbsize] > 0\n        } else {\n            fail \"No write load detected.\"\n        }\n\n        # After 3 seconds, start a rewrite, while the write load is still\n        # active.\n        after 3000\n        r bgrewriteaof\n        waitForBgrewriteaof r\n\n        # Let it run a bit more so that we'll append some data to the new\n        # AOF.\n        after 1000\n\n        # Stop the processes generating the load if they are still active\n        stop_write_load $load_handle0\n        stop_write_load $load_handle1\n        stop_write_load $load_handle2\n        stop_write_load $load_handle3\n        stop_write_load $load_handle4\n\n        # Make sure that we remain the only connected client.\n        # This step is needed to make sure there are no pending writes\n        # that will be processed between the two \"debug digest\" calls.\n        wait_for_condition 50 100 {\n            [llength [split [string trim [r client list]] \"\\n\"]] == 1\n        } else {\n            puts [r client list]\n            fail \"Clients generating loads are not disconnecting\"\n        }\n\n        # Get the data set digest\n        set d1 [r debug digest]\n\n        # Load the AOF\n        r debug loadaof\n        set d2 [r debug digest]\n\n        # Make sure they are the same\n        assert {$d1 eq $d2}\n    }\n}\n\nstart_server {tags {\"aofrw\"}} {\n    test {Turning off AOF kills the background writing child if any} {\n        r config set appendonly yes\n        waitForBgrewriteaof r\n        r multi\n        r bgrewriteaof\n        r config set appendonly no\n        r exec\n        wait_for_condition 50 100 {\n            [string match {*Killing*AOF*child*} [exec tail -n5 < [srv 0 stdout]]]\n        } else {\n            fail \"Can't find 'Killing AOF child' into recent logs\"\n        }\n    }\n\n    foreach d {string int} {\n        foreach e {quicklist} {\n            test \"AOF rewrite of list with $e encoding, $d data\" {\n                r flushall\n                set len 1000\n                for {set j 0} {$j < $len} {incr j} {\n                    if {$d eq {string}} {\n                        set data [randstring 0 16 alpha]\n                    } else {\n                        set data [randomInt 4000000000]\n                    }\n                    r lpush key $data\n                }\n                assert_equal [r object encoding key] $e\n                set d1 [r debug digest]\n                r bgrewriteaof\n                waitForBgrewriteaof r\n                r debug loadaof\n                set d2 [r debug digest]\n                if {$d1 ne $d2} {\n                    error \"assertion:$d1 is not equal to $d2\"\n                }\n            }\n        }\n    }\n\n    foreach d {string int} {\n        foreach e {intset hashtable} {\n            test \"AOF rewrite of set with $e encoding, $d data\" {\n                r flushall\n                if {$e eq {intset}} {set len 10} else {set len 1000}\n                for {set j 0} {$j < $len} {incr j} {\n                    if {$d eq {string}} {\n                        set data [randstring 0 16 alpha]\n                    } else {\n                        set data [randomInt 4000000000]\n                    }\n                    r sadd key $data\n                }\n                if {$d ne {string}} {\n                    assert_equal [r object encoding key] $e\n                }\n                set d1 [r debug digest]\n                r bgrewriteaof\n                waitForBgrewriteaof r\n                r debug loadaof\n                set d2 [r debug digest]\n                if {$d1 ne $d2} {\n                    error \"assertion:$d1 is not equal to $d2\"\n                }\n            }\n        }\n    }\n\n    foreach d {string int} {\n        foreach e {ziplist hashtable} {\n            test \"AOF rewrite of hash with $e encoding, $d data\" {\n                r flushall\n                if {$e eq {ziplist}} {set len 10} else {set len 1000}\n                for {set j 0} {$j < $len} {incr j} {\n                    if {$d eq {string}} {\n                        set data [randstring 0 16 alpha]\n                    } else {\n                        set data [randomInt 4000000000]\n                    }\n                    r hset key $data $data\n                }\n                assert_equal [r object encoding key] $e\n                set d1 [r debug digest]\n                r bgrewriteaof\n                waitForBgrewriteaof r\n                r debug loadaof\n                set d2 [r debug digest]\n                if {$d1 ne $d2} {\n                    error \"assertion:$d1 is not equal to $d2\"\n                }\n            }\n        }\n    }\n\n    foreach d {string int} {\n        foreach e {ziplist skiplist} {\n            test \"AOF rewrite of zset with $e encoding, $d data\" {\n                r flushall\n                if {$e eq {ziplist}} {set len 10} else {set len 1000}\n                for {set j 0} {$j < $len} {incr j} {\n                    if {$d eq {string}} {\n                        set data [randstring 0 16 alpha]\n                    } else {\n                        set data [randomInt 4000000000]\n                    }\n                    r zadd key [expr rand()] $data\n                }\n                assert_equal [r object encoding key] $e\n                set d1 [r debug digest]\n                r bgrewriteaof\n                waitForBgrewriteaof r\n                r debug loadaof\n                set d2 [r debug digest]\n                if {$d1 ne $d2} {\n                    error \"assertion:$d1 is not equal to $d2\"\n                }\n            }\n        }\n    }\n\n    test {BGREWRITEAOF is delayed if BGSAVE is in progress} {\n        r multi\n        r bgsave\n        r bgrewriteaof\n        r info persistence\n        set res [r exec]\n        assert_match {*scheduled*} [lindex $res 1]\n        assert_match {*aof_rewrite_scheduled:1*} [lindex $res 2]\n        while {[string match {*aof_rewrite_scheduled:1*} [r info persistence]]} {\n            after 100\n        }\n    }\n\n    test {BGREWRITEAOF is refused if already in progress} {\n        catch {\n            r multi\n            r bgrewriteaof\n            r bgrewriteaof\n            r exec\n        } e\n        assert_match {*ERR*already*} $e\n        while {[string match {*aof_rewrite_scheduled:1*} [r info persistence]]} {\n            after 100\n        }\n    }\n}\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/tests/unit/auth.tcl",
    "content": "start_server {tags {\"auth\"}} {\n    test {AUTH fails if there is no password configured server side} {\n        catch {r auth foo} err\n        set _ $err\n    } {ERR*no password*}\n}\n\nstart_server {tags {\"auth\"} overrides {requirepass foobar}} {\n    test {AUTH fails when a wrong password is given} {\n        catch {r auth wrong!} err\n        set _ $err\n    } {ERR*invalid password}\n\n    test {Arbitrary command gives an error when AUTH is required} {\n        catch {r set foo bar} err\n        set _ $err\n    } {NOAUTH*}\n\n    test {AUTH succeeds when the right password is given} {\n        r auth foobar\n    } {OK}\n\n    test {Once AUTH succeeded we can actually send commands to the server} {\n        r set foo 100\n        r incr foo\n    } {101}\n}\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/tests/unit/bitfield.tcl",
    "content": "start_server {tags {\"bitops\"}} {\n    test {BITFIELD signed SET and GET basics} {\n        r del bits\n        set results {}\n        lappend results [r bitfield bits set i8 0 -100]\n        lappend results [r bitfield bits set i8 0 101]\n        lappend results [r bitfield bits get i8 0]\n        set results\n    } {0 -100 101}\n\n    test {BITFIELD unsigned SET and GET basics} {\n        r del bits\n        set results {}\n        lappend results [r bitfield bits set u8 0 255]\n        lappend results [r bitfield bits set u8 0 100]\n        lappend results [r bitfield bits get u8 0]\n        set results\n    } {0 255 100}\n\n    test {BITFIELD #<idx> form} {\n        r del bits\n        set results {}\n        r bitfield bits set u8 #0 65\n        r bitfield bits set u8 #1 66\n        r bitfield bits set u8 #2 67\n        r get bits\n    } {ABC}\n\n    test {BITFIELD basic INCRBY form} {\n        r del bits\n        set results {}\n        r bitfield bits set u8 #0 10\n        lappend results [r bitfield bits incrby u8 #0 100]\n        lappend results [r bitfield bits incrby u8 #0 100]\n        set results\n    } {110 210}\n\n    test {BITFIELD chaining of multiple commands} {\n        r del bits\n        set results {}\n        r bitfield bits set u8 #0 10\n        lappend results [r bitfield bits incrby u8 #0 100 incrby u8 #0 100]\n        set results\n    } {{110 210}}\n\n    test {BITFIELD unsigned overflow wrap} {\n        r del bits\n        set results {}\n        r bitfield bits set u8 #0 100\n        lappend results [r bitfield bits overflow wrap incrby u8 #0 257]\n        lappend results [r bitfield bits get u8 #0]\n        lappend results [r bitfield bits overflow wrap incrby u8 #0 255]\n        lappend results [r bitfield bits get u8 #0]\n    } {101 101 100 100}\n\n    test {BITFIELD unsigned overflow sat} {\n        r del bits\n        set results {}\n        r bitfield bits set u8 #0 100\n        lappend results [r bitfield bits overflow sat incrby u8 #0 257]\n        lappend results [r bitfield bits get u8 #0]\n        lappend results [r bitfield bits overflow sat incrby u8 #0 -255]\n        lappend results [r bitfield bits get u8 #0]\n    } {255 255 0 0}\n\n    test {BITFIELD signed overflow wrap} {\n        r del bits\n        set results {}\n        r bitfield bits set i8 #0 100\n        lappend results [r bitfield bits overflow wrap incrby i8 #0 257]\n        lappend results [r bitfield bits get i8 #0]\n        lappend results [r bitfield bits overflow wrap incrby i8 #0 255]\n        lappend results [r bitfield bits get i8 #0]\n    } {101 101 100 100}\n\n    test {BITFIELD signed overflow sat} {\n        r del bits\n        set results {}\n        r bitfield bits set u8 #0 100\n        lappend results [r bitfield bits overflow sat incrby i8 #0 257]\n        lappend results [r bitfield bits get i8 #0]\n        lappend results [r bitfield bits overflow sat incrby i8 #0 -255]\n        lappend results [r bitfield bits get i8 #0]\n    } {127 127 -128 -128}\n\n    test {BITFIELD overflow detection fuzzing} {\n        for {set j 0} {$j < 1000} {incr j} {\n            set bits [expr {[randomInt 64]+1}]\n            set sign [randomInt 2]\n            set range [expr {2**$bits}]\n            if {$bits == 64} {set sign 1} ; # u64 is not supported by BITFIELD.\n            if {$sign} {\n                set min [expr {-($range/2)}]\n                set type \"i$bits\"\n            } else {\n                set min 0\n                set type \"u$bits\"\n            }\n            set max [expr {$min+$range-1}]\n\n            # Compare Tcl vs Redis\n            set range2 [expr {$range*2}]\n            set value [expr {($min*2)+[randomInt $range2]}]\n            set increment [expr {($min*2)+[randomInt $range2]}]\n            if {$value > 9223372036854775807} {\n                set value 9223372036854775807\n            }\n            if {$value < -9223372036854775808} {\n                set value -9223372036854775808\n            }\n            if {$increment > 9223372036854775807} {\n                set increment 9223372036854775807\n            }\n            if {$increment < -9223372036854775808} {\n                set increment -9223372036854775808\n            }\n\n            set overflow 0\n            if {$value > $max || $value < $min} {set overflow 1}\n            if {($value + $increment) > $max} {set overflow 1}\n            if {($value + $increment) < $min} {set overflow 1}\n\n            r del bits\n            set res1 [r bitfield bits overflow fail set $type 0 $value]\n            set res2 [r bitfield bits overflow fail incrby $type 0 $increment]\n\n            if {$overflow && [lindex $res1 0] ne {} &&\n                             [lindex $res2 0] ne {}} {\n                fail \"OW not detected where needed: $type $value+$increment\"\n            }\n            if {!$overflow && ([lindex $res1 0] eq {} ||\n                               [lindex $res2 0] eq {})} {\n                fail \"OW detected where NOT needed: $type $value+$increment\"\n            }\n        }\n    }\n\n    test {BITFIELD overflow wrap fuzzing} {\n        for {set j 0} {$j < 1000} {incr j} {\n            set bits [expr {[randomInt 64]+1}]\n            set sign [randomInt 2]\n            set range [expr {2**$bits}]\n            if {$bits == 64} {set sign 1} ; # u64 is not supported by BITFIELD.\n            if {$sign} {\n                set min [expr {-($range/2)}]\n                set type \"i$bits\"\n            } else {\n                set min 0\n                set type \"u$bits\"\n            }\n            set max [expr {$min+$range-1}]\n\n            # Compare Tcl vs Redis\n            set range2 [expr {$range*2}]\n            set value [expr {($min*2)+[randomInt $range2]}]\n            set increment [expr {($min*2)+[randomInt $range2]}]\n            if {$value > 9223372036854775807} {\n                set value 9223372036854775807\n            }\n            if {$value < -9223372036854775808} {\n                set value -9223372036854775808\n            }\n            if {$increment > 9223372036854775807} {\n                set increment 9223372036854775807\n            }\n            if {$increment < -9223372036854775808} {\n                set increment -9223372036854775808\n            }\n\n            r del bits\n            r bitfield bits overflow wrap set $type 0 $value\n            r bitfield bits overflow wrap incrby $type 0 $increment\n            set res [lindex [r bitfield bits get $type 0] 0]\n\n            set expected 0\n            if {$sign} {incr expected [expr {$max+1}]}\n            incr expected $value\n            incr expected $increment\n            set expected [expr {$expected % $range}]\n            if {$sign} {incr expected $min}\n\n            if {$res != $expected} {\n                fail \"WRAP error: $type $value+$increment = $res, should be $expected\"\n            }\n        }\n    }\n\n    test {BITFIELD regression for #3221} {\n        r set bits 1\n        r bitfield bits get u1 0\n    } {0}\n}\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/tests/unit/bitops.tcl",
    "content": "# Compare Redis commands against Tcl implementations of the same commands.\nproc count_bits s {\n    binary scan $s b* bits\n    string length [regsub -all {0} $bits {}]\n}\n\nproc simulate_bit_op {op args} {\n    set maxlen 0\n    set j 0\n    set count [llength $args]\n    foreach a $args {\n        binary scan $a b* bits\n        set b($j) $bits\n        if {[string length $bits] > $maxlen} {\n            set maxlen [string length $bits]\n        }\n        incr j\n    }\n    for {set j 0} {$j < $count} {incr j} {\n        if {[string length $b($j)] < $maxlen} {\n            append b($j) [string repeat 0 [expr $maxlen-[string length $b($j)]]]\n        }\n    }\n    set out {}\n    for {set x 0} {$x < $maxlen} {incr x} {\n        set bit [string range $b(0) $x $x]\n        if {$op eq {not}} {set bit [expr {!$bit}]}\n        for {set j 1} {$j < $count} {incr j} {\n            set bit2 [string range $b($j) $x $x]\n            switch $op {\n                and {set bit [expr {$bit & $bit2}]}\n                or  {set bit [expr {$bit | $bit2}]}\n                xor {set bit [expr {$bit ^ $bit2}]}\n            }\n        }\n        append out $bit\n    }\n    binary format b* $out\n}\n\nstart_server {tags {\"bitops\"}} {\n    test {BITCOUNT returns 0 against non existing key} {\n        r bitcount no-key\n    } 0\n\n    test {BITCOUNT returns 0 with out of range indexes} {\n        r set str \"xxxx\"\n        r bitcount str 4 10\n    } 0\n\n    test {BITCOUNT returns 0 with negative indexes where start > end} {\n        r set str \"xxxx\"\n        r bitcount str -6 -7\n    } 0\n\n    catch {unset num}\n    foreach vec [list \"\" \"\\xaa\" \"\\x00\\x00\\xff\" \"foobar\" \"123\"] {\n        incr num\n        test \"BITCOUNT against test vector #$num\" {\n            r set str $vec\n            assert {[r bitcount str] == [count_bits $vec]}\n        }\n    }\n\n    test {BITCOUNT fuzzing without start/end} {\n        for {set j 0} {$j < 100} {incr j} {\n            set str [randstring 0 3000]\n            r set str $str\n            assert {[r bitcount str] == [count_bits $str]}\n        }\n    }\n\n    test {BITCOUNT fuzzing with start/end} {\n        for {set j 0} {$j < 100} {incr j} {\n            set str [randstring 0 3000]\n            r set str $str\n            set l [string length $str]\n            set start [randomInt $l]\n            set end [randomInt $l]\n            if {$start > $end} {\n                lassign [list $end $start] start end\n            }\n            assert {[r bitcount str $start $end] == [count_bits [string range $str $start $end]]}\n        }\n    }\n\n    test {BITCOUNT with start, end} {\n        r set s \"foobar\"\n        assert_equal [r bitcount s 0 -1] [count_bits \"foobar\"]\n        assert_equal [r bitcount s 1 -2] [count_bits \"ooba\"]\n        assert_equal [r bitcount s -2 1] [count_bits \"\"]\n        assert_equal [r bitcount s 0 1000] [count_bits \"foobar\"]\n    }\n\n    test {BITCOUNT syntax error #1} {\n        catch {r bitcount s 0} e\n        set e\n    } {ERR*syntax*}\n\n    test {BITCOUNT regression test for github issue #582} {\n        r del foo\n        r setbit foo 0 1\n        if {[catch {r bitcount foo 0 4294967296} e]} {\n            assert_match {*ERR*out of range*} $e\n            set _ 1\n        } else {\n            set e\n        }\n    } {1}\n\n    test {BITCOUNT misaligned prefix} {\n        r del str\n        r set str ab\n        r bitcount str 1 -1\n    } {3}\n\n    test {BITCOUNT misaligned prefix + full words + remainder} {\n        r del str\n        r set str __PPxxxxxxxxxxxxxxxxRR__\n        r bitcount str 2 -3\n    } {74}\n\n    test {BITOP NOT (empty string)} {\n        r set s \"\"\n        r bitop not dest s\n        r get dest\n    } {}\n\n    test {BITOP NOT (known string)} {\n        r set s \"\\xaa\\x00\\xff\\x55\"\n        r bitop not dest s\n        r get dest\n    } \"\\x55\\xff\\x00\\xaa\"\n\n    test {BITOP where dest and target are the same key} {\n        r set s \"\\xaa\\x00\\xff\\x55\"\n        r bitop not s s\n        r get s\n    } \"\\x55\\xff\\x00\\xaa\"\n\n    test {BITOP AND|OR|XOR don't change the string with single input key} {\n        r set a \"\\x01\\x02\\xff\"\n        r bitop and res1 a\n        r bitop or  res2 a\n        r bitop xor res3 a\n        list [r get res1] [r get res2] [r get res3]\n    } [list \"\\x01\\x02\\xff\" \"\\x01\\x02\\xff\" \"\\x01\\x02\\xff\"]\n\n    test {BITOP missing key is considered a stream of zero} {\n        r set a \"\\x01\\x02\\xff\"\n        r bitop and res1 no-suck-key a\n        r bitop or  res2 no-suck-key a no-such-key\n        r bitop xor res3 no-such-key a\n        list [r get res1] [r get res2] [r get res3]\n    } [list \"\\x00\\x00\\x00\" \"\\x01\\x02\\xff\" \"\\x01\\x02\\xff\"]\n\n    test {BITOP shorter keys are zero-padded to the key with max length} {\n        r set a \"\\x01\\x02\\xff\\xff\"\n        r set b \"\\x01\\x02\\xff\"\n        r bitop and res1 a b\n        r bitop or  res2 a b\n        r bitop xor res3 a b\n        list [r get res1] [r get res2] [r get res3]\n    } [list \"\\x01\\x02\\xff\\x00\" \"\\x01\\x02\\xff\\xff\" \"\\x00\\x00\\x00\\xff\"]\n\n    foreach op {and or xor} {\n        test \"BITOP $op fuzzing\" {\n            for {set i 0} {$i < 10} {incr i} {\n                r flushall\n                set vec {}\n                set veckeys {}\n                set numvec [expr {[randomInt 10]+1}]\n                for {set j 0} {$j < $numvec} {incr j} {\n                    set str [randstring 0 1000]\n                    lappend vec $str\n                    lappend veckeys vector_$j\n                    r set vector_$j $str\n                }\n                r bitop $op target {*}$veckeys\n                assert_equal [r get target] [simulate_bit_op $op {*}$vec]\n            }\n        }\n    }\n\n    test {BITOP NOT fuzzing} {\n        for {set i 0} {$i < 10} {incr i} {\n            r flushall\n            set str [randstring 0 1000]\n            r set str $str\n            r bitop not target str\n            assert_equal [r get target] [simulate_bit_op not $str]\n        }\n    }\n\n    test {BITOP with integer encoded source objects} {\n        r set a 1\n        r set b 2\n        r bitop xor dest a b a\n        r get dest\n    } {2}\n\n    test {BITOP with non string source key} {\n        r del c\n        r set a 1\n        r set b 2\n        r lpush c foo\n        catch {r bitop xor dest a b c d} e\n        set e\n    } {WRONGTYPE*}\n\n    test {BITOP with empty string after non empty string (issue #529)} {\n        r flushdb\n        r set a \"\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\"\n        r bitop or x a b\n    } {32}\n\n    test {BITPOS bit=0 with empty key returns 0} {\n        r del str\n        r bitpos str 0\n    } {0}\n\n    test {BITPOS bit=1 with empty key returns -1} {\n        r del str\n        r bitpos str 1\n    } {-1}\n\n    test {BITPOS bit=0 with string less than 1 word works} {\n        r set str \"\\xff\\xf0\\x00\"\n        r bitpos str 0\n    } {12}\n\n    test {BITPOS bit=1 with string less than 1 word works} {\n        r set str \"\\x00\\x0f\\x00\"\n        r bitpos str 1\n    } {12}\n\n    test {BITPOS bit=0 starting at unaligned address} {\n        r set str \"\\xff\\xf0\\x00\"\n        r bitpos str 0 1\n    } {12}\n\n    test {BITPOS bit=1 starting at unaligned address} {\n        r set str \"\\x00\\x0f\\xff\"\n        r bitpos str 1 1\n    } {12}\n\n    test {BITPOS bit=0 unaligned+full word+reminder} {\n        r del str\n        r set str \"\\xff\\xff\\xff\" ; # Prefix\n        # Followed by two (or four in 32 bit systems) full words\n        r append str \"\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xff\"\n        r append str \"\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xff\"\n        r append str \"\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xff\"\n        # First zero bit.\n        r append str \"\\x0f\"\n        assert {[r bitpos str 0] == 216}\n        assert {[r bitpos str 0 1] == 216}\n        assert {[r bitpos str 0 2] == 216}\n        assert {[r bitpos str 0 3] == 216}\n        assert {[r bitpos str 0 4] == 216}\n        assert {[r bitpos str 0 5] == 216}\n        assert {[r bitpos str 0 6] == 216}\n        assert {[r bitpos str 0 7] == 216}\n        assert {[r bitpos str 0 8] == 216}\n    }\n\n    test {BITPOS bit=1 unaligned+full word+reminder} {\n        r del str\n        r set str \"\\x00\\x00\\x00\" ; # Prefix\n        # Followed by two (or four in 32 bit systems) full words\n        r append str \"\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\"\n        r append str \"\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\"\n        r append str \"\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\"\n        # First zero bit.\n        r append str \"\\xf0\"\n        assert {[r bitpos str 1] == 216}\n        assert {[r bitpos str 1 1] == 216}\n        assert {[r bitpos str 1 2] == 216}\n        assert {[r bitpos str 1 3] == 216}\n        assert {[r bitpos str 1 4] == 216}\n        assert {[r bitpos str 1 5] == 216}\n        assert {[r bitpos str 1 6] == 216}\n        assert {[r bitpos str 1 7] == 216}\n        assert {[r bitpos str 1 8] == 216}\n    }\n\n    test {BITPOS bit=1 returns -1 if string is all 0 bits} {\n        r set str \"\"\n        for {set j 0} {$j < 20} {incr j} {\n            assert {[r bitpos str 1] == -1}\n            r append str \"\\x00\"\n        }\n    }\n\n    test {BITPOS bit=0 works with intervals} {\n        r set str \"\\x00\\xff\\x00\"\n        assert {[r bitpos str 0 0 -1] == 0}\n        assert {[r bitpos str 0 1 -1] == 16}\n        assert {[r bitpos str 0 2 -1] == 16}\n        assert {[r bitpos str 0 2 200] == 16}\n        assert {[r bitpos str 0 1 1] == -1}\n    }\n\n    test {BITPOS bit=1 works with intervals} {\n        r set str \"\\x00\\xff\\x00\"\n        assert {[r bitpos str 1 0 -1] == 8}\n        assert {[r bitpos str 1 1 -1] == 8}\n        assert {[r bitpos str 1 2 -1] == -1}\n        assert {[r bitpos str 1 2 200] == -1}\n        assert {[r bitpos str 1 1 1] == 8}\n    }\n\n    test {BITPOS bit=0 changes behavior if end is given} {\n        r set str \"\\xff\\xff\\xff\"\n        assert {[r bitpos str 0] == 24}\n        assert {[r bitpos str 0 0] == 24}\n        assert {[r bitpos str 0 0 -1] == -1}\n    }\n\n    test {BITPOS bit=1 fuzzy testing using SETBIT} {\n        r del str\n        set max 524288; # 64k\n        set first_one_pos -1\n        for {set j 0} {$j < 1000} {incr j} {\n            assert {[r bitpos str 1] == $first_one_pos}\n            set pos [randomInt $max]\n            r setbit str $pos 1\n            if {$first_one_pos == -1 || $first_one_pos > $pos} {\n                # Update the position of the first 1 bit in the array\n                # if the bit we set is on the left of the previous one.\n                set first_one_pos $pos\n            }\n        }\n    }\n\n    test {BITPOS bit=0 fuzzy testing using SETBIT} {\n        set max 524288; # 64k\n        set first_zero_pos $max\n        r set str [string repeat \"\\xff\" [expr $max/8]]\n        for {set j 0} {$j < 1000} {incr j} {\n            assert {[r bitpos str 0] == $first_zero_pos}\n            set pos [randomInt $max]\n            r setbit str $pos 0\n            if {$first_zero_pos > $pos} {\n                # Update the position of the first 0 bit in the array\n                # if the bit we clear is on the left of the previous one.\n                set first_zero_pos $pos\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/tests/unit/dump.tcl",
    "content": "start_server {tags {\"dump\"}} {\n    test {DUMP / RESTORE are able to serialize / unserialize a simple key} {\n        r set foo bar\n        set encoded [r dump foo]\n        r del foo\n        list [r exists foo] [r restore foo 0 $encoded] [r ttl foo] [r get foo]\n    } {0 OK -1 bar}\n\n    test {RESTORE can set an arbitrary expire to the materialized key} {\n        r set foo bar\n        set encoded [r dump foo]\n        r del foo\n        r restore foo 5000 $encoded\n        set ttl [r pttl foo]\n        assert {$ttl >= 3000 && $ttl <= 5000}\n        r get foo\n    } {bar}\n\n    test {RESTORE can set an expire that overflows a 32 bit integer} {\n        r set foo bar\n        set encoded [r dump foo]\n        r del foo\n        r restore foo 2569591501 $encoded\n        set ttl [r pttl foo]\n        assert {$ttl >= (2569591501-3000) && $ttl <= 2569591501}\n        r get foo\n    } {bar}\n\n    test {RESTORE returns an error of the key already exists} {\n        r set foo bar\n        set e {}\n        catch {r restore foo 0 \"...\"} e\n        set e\n    } {*BUSYKEY*}\n\n    test {RESTORE can overwrite an existing key with REPLACE} {\n        r set foo bar1\n        set encoded1 [r dump foo]\n        r set foo bar2\n        set encoded2 [r dump foo]\n        r del foo\n        r restore foo 0 $encoded1\n        r restore foo 0 $encoded2 replace\n        r get foo\n    } {bar2}\n\n    test {RESTORE can detect a syntax error for unrecongized options} {\n        catch {r restore foo 0 \"...\" invalid-option} e\n        set e\n    } {*syntax*}\n\n    test {DUMP of non existing key returns nil} {\n        r dump nonexisting_key\n    } {}\n\n    test {MIGRATE is caching connections} {\n        # Note, we run this as first test so that the connection cache\n        # is empty.\n        set first [srv 0 client]\n        r set key \"Some Value\"\n        start_server {tags {\"repl\"}} {\n            set second [srv 0 client]\n            set second_host [srv 0 host]\n            set second_port [srv 0 port]\n\n            assert_match {*migrate_cached_sockets:0*} [r -1 info]\n            r -1 migrate $second_host $second_port key 9 1000\n            assert_match {*migrate_cached_sockets:1*} [r -1 info]\n        }\n    }\n\n    test {MIGRATE cached connections are released after some time} {\n        after 15000\n        assert_match {*migrate_cached_sockets:0*} [r info]\n    }\n\n    test {MIGRATE is able to migrate a key between two instances} {\n        set first [srv 0 client]\n        r set key \"Some Value\"\n        start_server {tags {\"repl\"}} {\n            set second [srv 0 client]\n            set second_host [srv 0 host]\n            set second_port [srv 0 port]\n\n            assert {[$first exists key] == 1}\n            assert {[$second exists key] == 0}\n            set ret [r -1 migrate $second_host $second_port key 9 5000]\n            assert {$ret eq {OK}}\n            assert {[$first exists key] == 0}\n            assert {[$second exists key] == 1}\n            assert {[$second get key] eq {Some Value}}\n            assert {[$second ttl key] == -1}\n        }\n    }\n\n    test {MIGRATE is able to copy a key between two instances} {\n        set first [srv 0 client]\n        r del list\n        r lpush list a b c d\n        start_server {tags {\"repl\"}} {\n            set second [srv 0 client]\n            set second_host [srv 0 host]\n            set second_port [srv 0 port]\n\n            assert {[$first exists list] == 1}\n            assert {[$second exists list] == 0}\n            set ret [r -1 migrate $second_host $second_port list 9 5000 copy]\n            assert {$ret eq {OK}}\n            assert {[$first exists list] == 1}\n            assert {[$second exists list] == 1}\n            assert {[$first lrange list 0 -1] eq [$second lrange list 0 -1]}\n        }\n    }\n\n    test {MIGRATE will not overwrite existing keys, unless REPLACE is used} {\n        set first [srv 0 client]\n        r del list\n        r lpush list a b c d\n        start_server {tags {\"repl\"}} {\n            set second [srv 0 client]\n            set second_host [srv 0 host]\n            set second_port [srv 0 port]\n\n            assert {[$first exists list] == 1}\n            assert {[$second exists list] == 0}\n            $second set list somevalue\n            catch {r -1 migrate $second_host $second_port list 9 5000 copy} e\n            assert_match {ERR*} $e\n            set res [r -1 migrate $second_host $second_port list 9 5000 copy replace]\n            assert {$ret eq {OK}}\n            assert {[$first exists list] == 1}\n            assert {[$second exists list] == 1}\n            assert {[$first lrange list 0 -1] eq [$second lrange list 0 -1]}\n        }\n    }\n\n    test {MIGRATE propagates TTL correctly} {\n        set first [srv 0 client]\n        r set key \"Some Value\"\n        start_server {tags {\"repl\"}} {\n            set second [srv 0 client]\n            set second_host [srv 0 host]\n            set second_port [srv 0 port]\n\n            assert {[$first exists key] == 1}\n            assert {[$second exists key] == 0}\n            $first expire key 10\n            set ret [r -1 migrate $second_host $second_port key 9 5000]\n            assert {$ret eq {OK}}\n            assert {[$first exists key] == 0}\n            assert {[$second exists key] == 1}\n            assert {[$second get key] eq {Some Value}}\n            assert {[$second ttl key] >= 7 && [$second ttl key] <= 10}\n        }\n    }\n\n    test {MIGRATE can correctly transfer large values} {\n        set first [srv 0 client]\n        r del key\n        for {set j 0} {$j < 40000} {incr j} {\n            r rpush key 1 2 3 4 5 6 7 8 9 10\n            r rpush key \"item 1\" \"item 2\" \"item 3\" \"item 4\" \"item 5\" \\\n                        \"item 6\" \"item 7\" \"item 8\" \"item 9\" \"item 10\"\n        }\n        assert {[string length [r dump key]] > (1024*64)}\n        start_server {tags {\"repl\"}} {\n            set second [srv 0 client]\n            set second_host [srv 0 host]\n            set second_port [srv 0 port]\n\n            assert {[$first exists key] == 1}\n            assert {[$second exists key] == 0}\n            set ret [r -1 migrate $second_host $second_port key 9 10000]\n            assert {$ret eq {OK}}\n            assert {[$first exists key] == 0}\n            assert {[$second exists key] == 1}\n            assert {[$second ttl key] == -1}\n            assert {[$second llen key] == 40000*20}\n        }\n    }\n\n    test {MIGRATE can correctly transfer hashes} {\n        set first [srv 0 client]\n        r del key\n        r hmset key field1 \"item 1\" field2 \"item 2\" field3 \"item 3\" \\\n                    field4 \"item 4\" field5 \"item 5\" field6 \"item 6\"\n        start_server {tags {\"repl\"}} {\n            set second [srv 0 client]\n            set second_host [srv 0 host]\n            set second_port [srv 0 port]\n\n            assert {[$first exists key] == 1}\n            assert {[$second exists key] == 0}\n            set ret [r -1 migrate $second_host $second_port key 9 10000]\n            assert {$ret eq {OK}}\n            assert {[$first exists key] == 0}\n            assert {[$second exists key] == 1}\n            assert {[$second ttl key] == -1}\n        }\n    }\n\n    test {MIGRATE timeout actually works} {\n        set first [srv 0 client]\n        r set key \"Some Value\"\n        start_server {tags {\"repl\"}} {\n            set second [srv 0 client]\n            set second_host [srv 0 host]\n            set second_port [srv 0 port]\n\n            assert {[$first exists key] == 1}\n            assert {[$second exists key] == 0}\n\n            set rd [redis_deferring_client]\n            $rd debug sleep 1.0 ; # Make second server unable to reply.\n            set e {}\n            catch {r -1 migrate $second_host $second_port key 9 500} e\n            assert_match {IOERR*} $e\n        }\n    }\n\n    test {MIGRATE can migrate multiple keys at once} {\n        set first [srv 0 client]\n        r set key1 \"v1\"\n        r set key2 \"v2\"\n        r set key3 \"v3\"\n        start_server {tags {\"repl\"}} {\n            set second [srv 0 client]\n            set second_host [srv 0 host]\n            set second_port [srv 0 port]\n\n            assert {[$first exists key1] == 1}\n            assert {[$second exists key1] == 0}\n            set ret [r -1 migrate $second_host $second_port \"\" 9 5000 keys key1 key2 key3]\n            assert {$ret eq {OK}}\n            assert {[$first exists key1] == 0}\n            assert {[$first exists key2] == 0}\n            assert {[$first exists key3] == 0}\n            assert {[$second get key1] eq {v1}}\n            assert {[$second get key2] eq {v2}}\n            assert {[$second get key3] eq {v3}}\n        }\n    }\n\n    test {MIGRATE with multiple keys must have empty key arg} {\n        catch {r MIGRATE 127.0.0.1 6379 NotEmpty 9 5000 keys a b c} e\n        set e\n    } {*empty string*}\n\n    test {MIGRATE with mutliple keys migrate just existing ones} {\n        set first [srv 0 client]\n        r set key1 \"v1\"\n        r set key2 \"v2\"\n        r set key3 \"v3\"\n        start_server {tags {\"repl\"}} {\n            set second [srv 0 client]\n            set second_host [srv 0 host]\n            set second_port [srv 0 port]\n\n            set ret [r -1 migrate $second_host $second_port \"\" 9 5000 keys nokey-1 nokey-2 nokey-2]\n            assert {$ret eq {NOKEY}}\n\n            assert {[$first exists key1] == 1}\n            assert {[$second exists key1] == 0}\n            set ret [r -1 migrate $second_host $second_port \"\" 9 5000 keys nokey-1 key1 nokey-2 key2 nokey-3 key3]\n            assert {$ret eq {OK}}\n            assert {[$first exists key1] == 0}\n            assert {[$first exists key2] == 0}\n            assert {[$first exists key3] == 0}\n            assert {[$second get key1] eq {v1}}\n            assert {[$second get key2] eq {v2}}\n            assert {[$second get key3] eq {v3}}\n        }\n    }\n\n    test {MIGRATE with multiple keys: stress command rewriting} {\n        set first [srv 0 client]\n        r flushdb\n        r mset a 1 b 2 c 3 d 4 c 5 e 6 f 7 g 8 h 9 i 10 l 11 m 12 n 13 o 14 p 15 q 16\n        start_server {tags {\"repl\"}} {\n            set second [srv 0 client]\n            set second_host [srv 0 host]\n            set second_port [srv 0 port]\n\n            set ret [r -1 migrate $second_host $second_port \"\" 9 5000 keys a b c d e f g h i l m n o p q]\n\n            assert {[$first dbsize] == 0}\n            assert {[$second dbsize] == 15}\n        }\n    }\n\n    test {MIGRATE with multiple keys: delete just ack keys} {\n        set first [srv 0 client]\n        r flushdb\n        r mset a 1 b 2 c 3 d 4 c 5 e 6 f 7 g 8 h 9 i 10 l 11 m 12 n 13 o 14 p 15 q 16\n        start_server {tags {\"repl\"}} {\n            set second [srv 0 client]\n            set second_host [srv 0 host]\n            set second_port [srv 0 port]\n\n            $second mset c _ d _; # Two busy keys and no REPLACE used\n\n            catch {r -1 migrate $second_host $second_port \"\" 9 5000 keys a b c d e f g h i l m n o p q} e\n\n            assert {[$first dbsize] == 2}\n            assert {[$second dbsize] == 15}\n            assert {[$first exists c] == 1}\n            assert {[$first exists d] == 1}\n        }\n    }\n\n}\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/tests/unit/expire.tcl",
    "content": "start_server {tags {\"expire\"}} {\n    test {EXPIRE - set timeouts multiple times} {\n        r set x foobar\n        set v1 [r expire x 5]\n        set v2 [r ttl x]\n        set v3 [r expire x 10]\n        set v4 [r ttl x]\n        r expire x 2\n        list $v1 $v2 $v3 $v4\n    } {1 [45] 1 10}\n\n    test {EXPIRE - It should be still possible to read 'x'} {\n        r get x\n    } {foobar}\n\n    tags {\"slow\"} {\n        test {EXPIRE - After 2.1 seconds the key should no longer be here} {\n            after 2100\n            list [r get x] [r exists x]\n        } {{} 0}\n    }\n\n    test {EXPIRE - write on expire should work} {\n        r del x\n        r lpush x foo\n        r expire x 1000\n        r lpush x bar\n        r lrange x 0 -1\n    } {bar foo}\n\n    test {EXPIREAT - Check for EXPIRE alike behavior} {\n        r del x\n        r set x foo\n        r expireat x [expr [clock seconds]+15]\n        r ttl x\n    } {1[345]}\n\n    test {SETEX - Set + Expire combo operation. Check for TTL} {\n        r setex x 12 test\n        r ttl x\n    } {1[012]}\n\n    test {SETEX - Check value} {\n        r get x\n    } {test}\n\n    test {SETEX - Overwrite old key} {\n        r setex y 1 foo\n        r get y\n    } {foo}\n\n    tags {\"slow\"} {\n        test {SETEX - Wait for the key to expire} {\n            after 1100\n            r get y\n        } {}\n    }\n\n    test {SETEX - Wrong time parameter} {\n        catch {r setex z -10 foo} e\n        set _ $e\n    } {*invalid expire*}\n\n    test {PERSIST can undo an EXPIRE} {\n        r set x foo\n        r expire x 50\n        list [r ttl x] [r persist x] [r ttl x] [r get x]\n    } {50 1 -1 foo}\n\n    test {PERSIST returns 0 against non existing or non volatile keys} {\n        r set x foo\n        list [r persist foo] [r persist nokeyatall]\n    } {0 0}\n\n    test {EXPIRE pricision is now the millisecond} {\n        # This test is very likely to do a false positive if the\n        # server is under pressure, so if it does not work give it a few more\n        # chances.\n        for {set j 0} {$j < 3} {incr j} {\n            r del x\n            r setex x 1 somevalue\n            after 900\n            set a [r get x]\n            after 1100\n            set b [r get x]\n            if {$a eq {somevalue} && $b eq {}} break\n        }\n        list $a $b\n    } {somevalue {}}\n\n    test {PEXPIRE/PSETEX/PEXPIREAT can set sub-second expires} {\n        # This test is very likely to do a false positive if the\n        # server is under pressure, so if it does not work give it a few more\n        # chances.\n        for {set j 0} {$j < 3} {incr j} {\n            r del x y z\n            r psetex x 100 somevalue\n            after 80\n            set a [r get x]\n            after 120\n            set b [r get x]\n\n            r set x somevalue\n            r pexpire x 100\n            after 80\n            set c [r get x]\n            after 120\n            set d [r get x]\n\n            r set x somevalue\n            r pexpireat x [expr ([clock seconds]*1000)+100]\n            after 80\n            set e [r get x]\n            after 120\n            set f [r get x]\n\n            if {$a eq {somevalue} && $b eq {} &&\n                $c eq {somevalue} && $d eq {} &&\n                $e eq {somevalue} && $f eq {}} break\n        }\n        list $a $b\n    } {somevalue {}}\n\n    test {TTL returns tiem to live in seconds} {\n        r del x\n        r setex x 10 somevalue\n        set ttl [r ttl x]\n        assert {$ttl > 8 && $ttl <= 10}\n    }\n\n    test {PTTL returns time to live in milliseconds} {\n        r del x\n        r setex x 1 somevalue\n        set ttl [r pttl x]\n        assert {$ttl > 900 && $ttl <= 1000}\n    }\n\n    test {TTL / PTTL return -1 if key has no expire} {\n        r del x\n        r set x hello\n        list [r ttl x] [r pttl x]\n    } {-1 -1}\n\n    test {TTL / PTTL return -2 if key does not exit} {\n        r del x\n        list [r ttl x] [r pttl x]\n    } {-2 -2}\n\n    test {Redis should actively expire keys incrementally} {\n        r flushdb\n        r psetex key1 500 a\n        r psetex key2 500 a\n        r psetex key3 500 a\n        set size1 [r dbsize]\n        # Redis expires random keys ten times every second so we are\n        # fairly sure that all the three keys should be evicted after\n        # one second.\n        after 1000\n        set size2 [r dbsize]\n        list $size1 $size2\n    } {3 0}\n\n    test {Redis should lazy expire keys} {\n        r flushdb\n        r debug set-active-expire 0\n        r psetex key1 500 a\n        r psetex key2 500 a\n        r psetex key3 500 a\n        set size1 [r dbsize]\n        # Redis expires random keys ten times every second so we are\n        # fairly sure that all the three keys should be evicted after\n        # one second.\n        after 1000\n        set size2 [r dbsize]\n        r mget key1 key2 key3\n        set size3 [r dbsize]\n        r debug set-active-expire 1\n        list $size1 $size2 $size3\n    } {3 3 0}\n\n    test {EXPIRE should not resurrect keys (issue #1026)} {\n        r debug set-active-expire 0\n        r set foo bar\n        r pexpire foo 500\n        after 1000\n        r expire foo 10\n        r debug set-active-expire 1\n        r exists foo\n    } {0}\n\n    test {5 keys in, 5 keys out} {\n        r flushdb\n        r set a c\n        r expire a 5\n        r set t c\n        r set e c\n        r set s c\n        r set foo b\n        lsort [r keys *]\n    } {a e foo s t}\n\n    test {EXPIRE with empty string as TTL should report an error} {\n        r set foo bar\n        catch {r expire foo \"\"} e\n        set e\n    } {*not an integer*}\n}\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/tests/unit/geo.tcl",
    "content": "# Helper functions to simulate search-in-radius in the Tcl side in order to\n# verify the Redis implementation with a fuzzy test.\nproc geo_degrad deg {expr {$deg*atan(1)*8/360}}\n\nproc geo_distance {lon1d lat1d lon2d lat2d} {\n    set lon1r [geo_degrad $lon1d]\n    set lat1r [geo_degrad $lat1d]\n    set lon2r [geo_degrad $lon2d]\n    set lat2r [geo_degrad $lat2d]\n    set v [expr {sin(($lon2r - $lon1r) / 2)}]\n    set u [expr {sin(($lat2r - $lat1r) / 2)}]\n    expr {2.0 * 6372797.560856 * \\\n            asin(sqrt($u * $u + cos($lat1r) * cos($lat2r) * $v * $v))}\n}\n\nproc geo_random_point {lonvar latvar} {\n    upvar 1 $lonvar lon\n    upvar 1 $latvar lat\n    # Note that the actual latitude limit should be -85 to +85, we restrict\n    # the test to -70 to +70 since in this range the algorithm is more precise\n    # while outside this range occasionally some element may be missing.\n    set lon [expr {-180 + rand()*360}]\n    set lat [expr {-70 + rand()*140}]\n}\n\n# Return elements non common to both the lists.\n# This code is from http://wiki.tcl.tk/15489\nproc compare_lists {List1 List2} {\n   set DiffList {}\n   foreach Item $List1 {\n      if {[lsearch -exact $List2 $Item] == -1} {\n         lappend DiffList $Item\n      }\n   }\n   foreach Item $List2 {\n      if {[lsearch -exact $List1 $Item] == -1} {\n         if {[lsearch -exact $DiffList $Item] == -1} {\n            lappend DiffList $Item\n         }\n      }\n   }\n   return $DiffList\n}\n\n# The following list represents sets of random seed, search position\n# and radius that caused bugs in the past. It is used by the randomized\n# test later as a starting point. When the regression vectors are scanned\n# the code reverts to using random data.\n#\n# The format is: seed km lon lat\nset regression_vectors {\n    {1412 156 149.29737817929004 15.95807862745508}\n    {441574 143 59.235461856813856 66.269555127373678}\n    {160645 187 -101.88575239939883 49.061997951502917}\n    {750269 154 -90.187939661642517 66.615930412251487}\n    {342880 145 163.03472387745728 64.012747720821181}\n    {729955 143 137.86663517256579 63.986745399416776}\n    {939895 151 59.149620271823181 65.204186651485145}\n    {1412 156 149.29737817929004 15.95807862745508}\n    {564862 149 84.062063109158544 -65.685403922426232}\n}\nset rv_idx 0\n\nstart_server {tags {\"geo\"}} {\n    test {GEOADD create} {\n        r geoadd nyc -73.9454966 40.747533 \"lic market\"\n    } {1}\n\n    test {GEOADD update} {\n        r geoadd nyc -73.9454966 40.747533 \"lic market\"\n    } {0}\n\n    test {GEOADD invalid coordinates} {\n        catch {\n            r geoadd nyc -73.9454966 40.747533 \"lic market\" \\\n                foo bar \"luck market\"\n        } err\n        set err\n    } {*valid*}\n\n    test {GEOADD multi add} {\n        r geoadd nyc -73.9733487 40.7648057 \"central park n/q/r\" -73.9903085 40.7362513 \"union square\" -74.0131604 40.7126674 \"wtc one\" -73.7858139 40.6428986 \"jfk\" -73.9375699 40.7498929 \"q4\" -73.9564142 40.7480973 4545\n    } {6}\n\n    test {Check geoset values} {\n        r zrange nyc 0 -1 withscores\n    } {{wtc one} 1791873972053020 {union square} 1791875485187452 {central park n/q/r} 1791875761332224 4545 1791875796750882 {lic market} 1791875804419201 q4 1791875830079666 jfk 1791895905559723}\n\n    test {GEORADIUS simple (sorted)} {\n        r georadius nyc -73.9798091 40.7598464 3 km asc\n    } {{central park n/q/r} 4545 {union square}}\n\n    test {GEORADIUS withdist (sorted)} {\n        r georadius nyc -73.9798091 40.7598464 3 km withdist asc\n    } {{{central park n/q/r} 0.7750} {4545 2.3651} {{union square} 2.7697}}\n\n    test {GEORADIUS with COUNT} {\n        r georadius nyc -73.9798091 40.7598464 10 km COUNT 3\n    } {{central park n/q/r} 4545 {union square}}\n\n    test {GEORADIUS with COUNT but missing integer argument} {\n        catch {r georadius nyc -73.9798091 40.7598464 10 km COUNT} e\n        set e\n    } {ERR*syntax*}\n\n    test {GEORADIUS with COUNT DESC} {\n        r georadius nyc -73.9798091 40.7598464 10 km COUNT 2 DESC\n    } {{wtc one} q4}\n\n    test {GEORADIUS HUGE, issue #2767} {\n        r geoadd users -47.271613776683807 -54.534504198047678 user_000000\n        llength [r GEORADIUS users 0 0 50000 km WITHCOORD]\n    } {1}\n\n    test {GEORADIUSBYMEMBER simple (sorted)} {\n        r georadiusbymember nyc \"wtc one\" 7 km\n    } {{wtc one} {union square} {central park n/q/r} 4545 {lic market}}\n\n    test {GEORADIUSBYMEMBER withdist (sorted)} {\n        r georadiusbymember nyc \"wtc one\" 7 km withdist\n    } {{{wtc one} 0.0000} {{union square} 3.2544} {{central park n/q/r} 6.7000} {4545 6.1975} {{lic market} 6.8969}}\n\n    test {GEOHASH is able to return geohash strings} {\n        # Example from Wikipedia.\n        r del points\n        r geoadd points -5.6 42.6 test\n        lindex [r geohash points test] 0\n    } {ezs42e44yx0}\n\n    test {GEOPOS simple} {\n        r del points\n        r geoadd points 10 20 a 30 40 b\n        lassign [lindex [r geopos points a b] 0] x1 y1\n        lassign [lindex [r geopos points a b] 1] x2 y2\n        assert {abs($x1 - 10) < 0.001}\n        assert {abs($y1 - 20) < 0.001}\n        assert {abs($x2 - 30) < 0.001}\n        assert {abs($y2 - 40) < 0.001}\n    }\n\n    test {GEOPOS missing element} {\n        r del points\n        r geoadd points 10 20 a 30 40 b\n        lindex [r geopos points a x b] 1\n    } {}\n\n    test {GEODIST simple & unit} {\n        r del points\n        r geoadd points 13.361389 38.115556 \"Palermo\" \\\n                        15.087269 37.502669 \"Catania\"\n        set m [r geodist points Palermo Catania]\n        assert {$m > 166274 && $m < 166275}\n        set km [r geodist points Palermo Catania km]\n        assert {$km > 166.2 && $km < 166.3}\n    }\n\n    test {GEODIST missing elements} {\n        r del points\n        r geoadd points 13.361389 38.115556 \"Palermo\" \\\n                        15.087269 37.502669 \"Catania\"\n        set m [r geodist points Palermo Agrigento]\n        assert {$m eq {}}\n        set m [r geodist points Ragusa Agrigento]\n        assert {$m eq {}}\n        set m [r geodist empty_key Palermo Catania]\n        assert {$m eq {}}\n    }\n\n    test {GEORADIUS STORE option: syntax error} {\n        r del points\n        r geoadd points 13.361389 38.115556 \"Palermo\" \\\n                        15.087269 37.502669 \"Catania\"\n        catch {r georadius points 13.361389 38.115556 50 km store} e\n        set e\n    } {*ERR*syntax*}\n\n    test {GEORANGE STORE option: incompatible options} {\n        r del points\n        r geoadd points 13.361389 38.115556 \"Palermo\" \\\n                        15.087269 37.502669 \"Catania\"\n        catch {r georadius points 13.361389 38.115556 50 km store points2 withdist} e\n        assert_match {*ERR*} $e\n        catch {r georadius points 13.361389 38.115556 50 km store points2 withhash} e\n        assert_match {*ERR*} $e\n        catch {r georadius points 13.361389 38.115556 50 km store points2 withcoords} e\n        assert_match {*ERR*} $e\n    }\n\n    test {GEORANGE STORE option: plain usage} {\n        r del points\n        r geoadd points 13.361389 38.115556 \"Palermo\" \\\n                        15.087269 37.502669 \"Catania\"\n        r georadius points 13.361389 38.115556 500 km store points2\n        assert_equal [r zrange points 0 -1] [r zrange points2 0 -1]\n    }\n\n    test {GEORANGE STOREDIST option: plain usage} {\n        r del points\n        r geoadd points 13.361389 38.115556 \"Palermo\" \\\n                        15.087269 37.502669 \"Catania\"\n        r georadius points 13.361389 38.115556 500 km storedist points2\n        set res [r zrange points2 0 -1 withscores]\n        assert {[lindex $res 1] < 1}\n        assert {[lindex $res 3] > 166}\n        assert {[lindex $res 3] < 167}\n    }\n\n    test {GEORANGE STOREDIST option: COUNT ASC and DESC} {\n        r del points\n        r geoadd points 13.361389 38.115556 \"Palermo\" \\\n                        15.087269 37.502669 \"Catania\"\n        r georadius points 13.361389 38.115556 500 km storedist points2 asc count 1\n        assert {[r zcard points2] == 1}\n        set res [r zrange points2 0 -1 withscores]\n        assert {[lindex $res 0] eq \"Palermo\"}\n\n        r georadius points 13.361389 38.115556 500 km storedist points2 desc count 1\n        assert {[r zcard points2] == 1}\n        set res [r zrange points2 0 -1 withscores]\n        assert {[lindex $res 0] eq \"Catania\"}\n    }\n\n    test {GEOADD + GEORANGE randomized test} {\n        set attempt 20\n        while {[incr attempt -1]} {\n            set rv [lindex $regression_vectors $rv_idx]\n            incr rv_idx\n\n            unset -nocomplain debuginfo\n            set srand_seed [randomInt 1000000]\n            if {$rv ne {}} {set srand_seed [lindex $rv 0]}\n            lappend debuginfo \"srand_seed is $srand_seed\"\n            expr {srand($srand_seed)} ; # If you need a reproducible run\n            r del mypoints\n            set radius_km [expr {[randomInt 200]+10}]\n            if {$rv ne {}} {set radius_km [lindex $rv 1]}\n            set radius_m [expr {$radius_km*1000}]\n            geo_random_point search_lon search_lat\n            if {$rv ne {}} {\n                set search_lon [lindex $rv 2]\n                set search_lat [lindex $rv 3]\n            }\n            lappend debuginfo \"Search area: $search_lon,$search_lat $radius_km km\"\n            set tcl_result {}\n            set argv {}\n            for {set j 0} {$j < 20000} {incr j} {\n                geo_random_point lon lat\n                lappend argv $lon $lat \"place:$j\"\n                if {[geo_distance $lon $lat $search_lon $search_lat] < $radius_m} {\n                    lappend tcl_result \"place:$j\"\n                    lappend debuginfo \"place:$j $lon $lat [expr {[geo_distance $lon $lat $search_lon $search_lat]/1000}] km\"\n                }\n            }\n            r geoadd mypoints {*}$argv\n            set res [lsort [r georadius mypoints $search_lon $search_lat $radius_km km]]\n            set res2 [lsort $tcl_result]\n            set test_result OK\n\n            if {$res != $res2} {\n                set rounding_errors 0\n                set diff [compare_lists $res $res2]\n                foreach place $diff {\n                    set mydist [geo_distance $lon $lat $search_lon $search_lat]\n                    set mydist [expr $mydist/1000]\n                    if {($mydist / $radius_km) > 0.999} {incr rounding_errors}\n                }\n                # Make sure this is a real error and not a rounidng issue.\n                if {[llength $diff] == $rounding_errors} {\n                    set res $res2; # Error silenced\n                }\n            }\n\n            if {$res != $res2} {\n                set diff [compare_lists $res $res2]\n                puts \"*** Possible problem in GEO radius query ***\"\n                puts \"Redis: $res\"\n                puts \"Tcl  : $res2\"\n                puts \"Diff : $diff\"\n                puts [join $debuginfo \"\\n\"]\n                foreach place $diff {\n                    if {[lsearch -exact $res2 $place] != -1} {\n                        set where \"(only in Tcl)\"\n                    } else {\n                        set where \"(only in Redis)\"\n                    }\n                    lassign [lindex [r geopos mypoints $place] 0] lon lat\n                    set mydist [geo_distance $lon $lat $search_lon $search_lat]\n                    set mydist [expr $mydist/1000]\n                    puts \"$place -> [r geopos mypoints $place] $mydist $where\"\n                    if {($mydist / $radius_km) > 0.999} {incr rounding_errors}\n                }\n                set test_result FAIL\n            }\n            unset -nocomplain debuginfo\n            if {$test_result ne {OK}} break\n        }\n        set test_result\n    } {OK}\n}\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/tests/unit/hyperloglog.tcl",
    "content": "start_server {tags {\"hll\"}} {\n    test {HyperLogLog self test passes} {\n        catch {r pfselftest} e\n        set e\n    } {OK}\n\n    test {PFADD without arguments creates an HLL value} {\n        r pfadd hll\n        r exists hll\n    } {1}\n\n    test {Approximated cardinality after creation is zero} {\n        r pfcount hll\n    } {0}\n\n    test {PFADD returns 1 when at least 1 reg was modified} {\n        r pfadd hll a b c\n    } {1}\n\n    test {PFADD returns 0 when no reg was modified} {\n        r pfadd hll a b c\n    } {0}\n\n    test {PFADD works with empty string (regression)} {\n        r pfadd hll \"\"\n    }\n\n    # Note that the self test stresses much better the\n    # cardinality estimation error. We are testing just the\n    # command implementation itself here.\n    test {PFCOUNT returns approximated cardinality of set} {\n        r del hll\n        set res {}\n        r pfadd hll 1 2 3 4 5\n        lappend res [r pfcount hll]\n        # Call it again to test cached value invalidation.\n        r pfadd hll 6 7 8 8 9 10\n        lappend res [r pfcount hll]\n        set res\n    } {5 10}\n\n    test {HyperLogLogs are promote from sparse to dense} {\n        r del hll\n        r config set hll-sparse-max-bytes 3000\n        set n 0\n        while {$n < 100000} {\n            set elements {}\n            for {set j 0} {$j < 100} {incr j} {lappend elements [expr rand()]}\n            incr n 100\n            r pfadd hll {*}$elements\n            set card [r pfcount hll]\n            set err [expr {abs($card-$n)}]\n            assert {$err < (double($card)/100)*5}\n            if {$n < 1000} {\n                assert {[r pfdebug encoding hll] eq {sparse}}\n            } elseif {$n > 10000} {\n                assert {[r pfdebug encoding hll] eq {dense}}\n            }\n        }\n    }\n\n    test {HyperLogLog sparse encoding stress test} {\n        for {set x 0} {$x < 1000} {incr x} {\n            r del hll1 hll2\n            set numele [randomInt 100]\n            set elements {}\n            for {set j 0} {$j < $numele} {incr j} {\n                lappend elements [expr rand()]\n            }\n            # Force dense representation of hll2\n            r pfadd hll2\n            r pfdebug todense hll2\n            r pfadd hll1 {*}$elements\n            r pfadd hll2 {*}$elements\n            assert {[r pfdebug encoding hll1] eq {sparse}}\n            assert {[r pfdebug encoding hll2] eq {dense}}\n            # Cardinality estimated should match exactly.\n            assert {[r pfcount hll1] eq [r pfcount hll2]}\n        }\n    }\n\n    test {Corrupted sparse HyperLogLogs are detected: Additionl at tail} {\n        r del hll\n        r pfadd hll a b c\n        r append hll \"hello\"\n        set e {}\n        catch {r pfcount hll} e\n        set e\n    } {*INVALIDOBJ*}\n\n    test {Corrupted sparse HyperLogLogs are detected: Broken magic} {\n        r del hll\n        r pfadd hll a b c\n        r setrange hll 0 \"0123\"\n        set e {}\n        catch {r pfcount hll} e\n        set e\n    } {*WRONGTYPE*}\n\n    test {Corrupted sparse HyperLogLogs are detected: Invalid encoding} {\n        r del hll\n        r pfadd hll a b c\n        r setrange hll 4 \"x\"\n        set e {}\n        catch {r pfcount hll} e\n        set e\n    } {*WRONGTYPE*}\n\n    test {Corrupted dense HyperLogLogs are detected: Wrong length} {\n        r del hll\n        r pfadd hll a b c\n        r setrange hll 4 \"\\x00\"\n        set e {}\n        catch {r pfcount hll} e\n        set e\n    } {*WRONGTYPE*}\n\n    test {PFADD, PFCOUNT, PFMERGE type checking works} {\n        r set foo bar\n        catch {r pfadd foo 1} e\n        assert_match {*WRONGTYPE*} $e\n        catch {r pfcount foo} e\n        assert_match {*WRONGTYPE*} $e\n        catch {r pfmerge bar foo} e\n        assert_match {*WRONGTYPE*} $e\n        catch {r pfmerge foo bar} e\n        assert_match {*WRONGTYPE*} $e\n    }\n\n    test {PFMERGE results on the cardinality of union of sets} {\n        r del hll hll1 hll2 hll3\n        r pfadd hll1 a b c\n        r pfadd hll2 b c d\n        r pfadd hll3 c d e\n        r pfmerge hll hll1 hll2 hll3\n        r pfcount hll\n    } {5}\n\n    test {PFCOUNT multiple-keys merge returns cardinality of union #1} {\n        r del hll1 hll2 hll3\n        for {set x 1} {$x < 10000} {incr x} {\n            r pfadd hll1 \"foo-$x\"\n            r pfadd hll2 \"bar-$x\"\n            r pfadd hll3 \"zap-$x\"\n\n            set card [r pfcount hll1 hll2 hll3]\n            set realcard [expr {$x*3}]\n            set err [expr {abs($card-$realcard)}]\n            assert {$err < (double($card)/100)*5}\n        }\n    }\n\n    test {PFCOUNT multiple-keys merge returns cardinality of union #2} {\n        r del hll1 hll2 hll3\n        set elements {}\n        for {set x 1} {$x < 10000} {incr x} {\n            for {set j 1} {$j <= 3} {incr j} {\n                set rint [randomInt 20000]\n                r pfadd hll$j $rint\n                lappend elements $rint\n            }\n        }\n        set realcard [llength [lsort -unique $elements]]\n        set card [r pfcount hll1 hll2 hll3]\n        set err [expr {abs($card-$realcard)}]\n        assert {$err < (double($card)/100)*5}\n    }\n\n    test {PFDEBUG GETREG returns the HyperLogLog raw registers} {\n        r del hll\n        r pfadd hll 1 2 3\n        llength [r pfdebug getreg hll]\n    } {16384}\n\n    test {PFADD / PFCOUNT cache invalidation works} {\n        r del hll\n        r pfadd hll a b c\n        r pfcount hll\n        assert {[r getrange hll 15 15] eq \"\\x00\"}\n        r pfadd hll a b c\n        assert {[r getrange hll 15 15] eq \"\\x00\"}\n        r pfadd hll 1 2 3\n        assert {[r getrange hll 15 15] eq \"\\x80\"}\n    }\n}\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/tests/unit/introspection-2.tcl",
    "content": "start_server {tags {\"introspection\"}} {\n    test {TTL and TYPYE do not alter the last access time of a key} {\n        r set foo bar\n        after 3000\n        r ttl foo\n        r type foo\n        assert {[r object idletime foo] >= 2}\n    }\n\n    test {TOUCH alters the last access time of a key} {\n        r set foo bar\n        after 3000\n        r touch foo\n        assert {[r object idletime foo] < 2}\n    }\n\n    test {TOUCH returns the number of existing keys specified} {\n        r flushdb\n        r set key1 1\n        r set key2 2\n        r touch key0 key1 key2 key3\n    } 2\n}\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/tests/unit/introspection.tcl",
    "content": "start_server {tags {\"introspection\"}} {\n    test {CLIENT LIST} {\n        r client list\n    } {*addr=*:* fd=* age=* idle=* flags=N db=9 sub=0 psub=0 multi=-1 qbuf=0 qbuf-free=* obl=0 oll=0 omem=0 events=r cmd=client*}\n\n    test {MONITOR can log executed commands} {\n        set rd [redis_deferring_client]\n        $rd monitor\n        r set foo bar\n        r get foo\n        list [$rd read] [$rd read] [$rd read]\n    } {*OK*\"set\" \"foo\"*\"get\" \"foo\"*}\n\n    test {MONITOR can log commands issued by the scripting engine} {\n        set rd [redis_deferring_client]\n        $rd monitor\n        r eval {redis.call('set',KEYS[1],ARGV[1])} 1 foo bar\n        $rd read ;# Discard the OK\n        assert_match {*eval*} [$rd read]\n        assert_match {*lua*\"set\"*\"foo\"*\"bar\"*} [$rd read]\n    }\n\n    test {CLIENT GETNAME should return NIL if name is not assigned} {\n        r client getname\n    } {}\n\n    test {CLIENT LIST shows empty fields for unassigned names} {\n        r client list\n    } {*name= *}\n\n    test {CLIENT SETNAME does not accept spaces} {\n        catch {r client setname \"foo bar\"} e\n        set e\n    } {ERR*}\n\n    test {CLIENT SETNAME can assign a name to this connection} {\n        assert_equal [r client setname myname] {OK}\n        r client list\n    } {*name=myname*}\n\n    test {CLIENT SETNAME can change the name of an existing connection} {\n        assert_equal [r client setname someothername] {OK}\n        r client list\n    } {*name=someothername*}\n\n    test {After CLIENT SETNAME, connection can still be closed} {\n        set rd [redis_deferring_client]\n        $rd client setname foobar\n        assert_equal [$rd read] \"OK\"\n        assert_match {*foobar*} [r client list]\n        $rd close\n        # Now the client should no longer be listed\n        wait_for_condition 50 100 {\n            [string match {*foobar*} [r client list]] == 0\n        } else {\n            fail \"Client still listed in CLIENT LIST after SETNAME.\"\n        }\n    }\n}\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/tests/unit/keyspace.tcl",
    "content": "start_server {tags {\"keyspace\"}} {\n    test {DEL against a single item} {\n        r set x foo\n        assert {[r get x] eq \"foo\"}\n        r del x\n        r get x\n    } {}\n\n    test {Vararg DEL} {\n        r set foo1 a\n        r set foo2 b\n        r set foo3 c\n        list [r del foo1 foo2 foo3 foo4] [r mget foo1 foo2 foo3]\n    } {3 {{} {} {}}}\n\n    test {KEYS with pattern} {\n        foreach key {key_x key_y key_z foo_a foo_b foo_c} {\n            r set $key hello\n        }\n        lsort [r keys foo*]\n    } {foo_a foo_b foo_c}\n\n    test {KEYS to get all keys} {\n        lsort [r keys *]\n    } {foo_a foo_b foo_c key_x key_y key_z}\n\n    test {DBSIZE} {\n        r dbsize\n    } {6}\n\n    test {DEL all keys} {\n        foreach key [r keys *] {r del $key}\n        r dbsize\n    } {0}\n\n    test \"DEL against expired key\" {\n        r debug set-active-expire 0\n        r setex keyExpire 1 valExpire\n        after 1100\n        assert_equal 0 [r del keyExpire]\n        r debug set-active-expire 1\n    }\n\n    test {EXISTS} {\n        set res {}\n        r set newkey test\n        append res [r exists newkey]\n        r del newkey\n        append res [r exists newkey]\n    } {10}\n\n    test {Zero length value in key. SET/GET/EXISTS} {\n        r set emptykey {}\n        set res [r get emptykey]\n        append res [r exists emptykey]\n        r del emptykey\n        append res [r exists emptykey]\n    } {10}\n\n    test {Commands pipelining} {\n        set fd [r channel]\n        puts -nonewline $fd \"SET k1 xyzk\\r\\nGET k1\\r\\nPING\\r\\n\"\n        flush $fd\n        set res {}\n        append res [string match OK* [r read]]\n        append res [r read]\n        append res [string match PONG* [r read]]\n        format $res\n    } {1xyzk1}\n\n    test {Non existing command} {\n        catch {r foobaredcommand} err\n        string match ERR* $err\n    } {1}\n\n    test {RENAME basic usage} {\n        r set mykey hello\n        r rename mykey mykey1\n        r rename mykey1 mykey2\n        r get mykey2\n    } {hello}\n\n    test {RENAME source key should no longer exist} {\n        r exists mykey\n    } {0}\n\n    test {RENAME against already existing key} {\n        r set mykey a\n        r set mykey2 b\n        r rename mykey2 mykey\n        set res [r get mykey]\n        append res [r exists mykey2]\n    } {b0}\n\n    test {RENAMENX basic usage} {\n        r del mykey\n        r del mykey2\n        r set mykey foobar\n        r renamenx mykey mykey2\n        set res [r get mykey2]\n        append res [r exists mykey]\n    } {foobar0}\n\n    test {RENAMENX against already existing key} {\n        r set mykey foo\n        r set mykey2 bar\n        r renamenx mykey mykey2\n    } {0}\n\n    test {RENAMENX against already existing key (2)} {\n        set res [r get mykey]\n        append res [r get mykey2]\n    } {foobar}\n\n    test {RENAME against non existing source key} {\n        catch {r rename nokey foobar} err\n        format $err\n    } {ERR*}\n\n    test {RENAME where source and dest key are the same (existing)} {\n        r set mykey foo\n        r rename mykey mykey\n    } {OK}\n\n    test {RENAMENX where source and dest key are the same (existing)} {\n        r set mykey foo\n        r renamenx mykey mykey\n    } {0}\n\n    test {RENAME where source and dest key are the same (non existing)} {\n        r del mykey\n        catch {r rename mykey mykey} err\n        format $err\n    } {ERR*}\n\n    test {RENAME with volatile key, should move the TTL as well} {\n        r del mykey mykey2\n        r set mykey foo\n        r expire mykey 100\n        assert {[r ttl mykey] > 95 && [r ttl mykey] <= 100}\n        r rename mykey mykey2\n        assert {[r ttl mykey2] > 95 && [r ttl mykey2] <= 100}\n    }\n\n    test {RENAME with volatile key, should not inherit TTL of target key} {\n        r del mykey mykey2\n        r set mykey foo\n        r set mykey2 bar\n        r expire mykey2 100\n        assert {[r ttl mykey] == -1 && [r ttl mykey2] > 0}\n        r rename mykey mykey2\n        r ttl mykey2\n    } {-1}\n\n    test {DEL all keys again (DB 0)} {\n        foreach key [r keys *] {\n            r del $key\n        }\n        r dbsize\n    } {0}\n\n    test {DEL all keys again (DB 1)} {\n        r select 10\n        foreach key [r keys *] {\n            r del $key\n        }\n        set res [r dbsize]\n        r select 9\n        format $res\n    } {0}\n\n    test {MOVE basic usage} {\n        r set mykey foobar\n        r move mykey 10\n        set res {}\n        lappend res [r exists mykey]\n        lappend res [r dbsize]\n        r select 10\n        lappend res [r get mykey]\n        lappend res [r dbsize]\n        r select 9\n        format $res\n    } [list 0 0 foobar 1]\n\n    test {MOVE against key existing in the target DB} {\n        r set mykey hello\n        r move mykey 10\n    } {0}\n\n    test {MOVE against non-integer DB (#1428)} {\n        r set mykey hello\n        catch {r move mykey notanumber} e\n        set e\n    } {*ERR*index out of range}\n\n    test {MOVE can move key expire metadata as well} {\n        r select 10\n        r flushdb\n        r select 9\n        r set mykey foo ex 100\n        r move mykey 10\n        assert {[r ttl mykey] == -2}\n        r select 10\n        assert {[r ttl mykey] > 0 && [r ttl mykey] <= 100}\n        assert {[r get mykey] eq \"foo\"}\n        r select 9\n    }\n\n    test {MOVE does not create an expire if it does not exist} {\n        r select 10\n        r flushdb\n        r select 9\n        r set mykey foo\n        r move mykey 10\n        assert {[r ttl mykey] == -2}\n        r select 10\n        assert {[r ttl mykey] == -1}\n        assert {[r get mykey] eq \"foo\"}\n        r select 9\n    }\n\n    test {SET/GET keys in different DBs} {\n        r set a hello\n        r set b world\n        r select 10\n        r set a foo\n        r set b bared\n        r select 9\n        set res {}\n        lappend res [r get a]\n        lappend res [r get b]\n        r select 10\n        lappend res [r get a]\n        lappend res [r get b]\n        r select 9\n        format $res\n    } {hello world foo bared}\n\n    test {RANDOMKEY} {\n        r flushdb\n        r set foo x\n        r set bar y\n        set foo_seen 0\n        set bar_seen 0\n        for {set i 0} {$i < 100} {incr i} {\n            set rkey [r randomkey]\n            if {$rkey eq {foo}} {\n                set foo_seen 1\n            }\n            if {$rkey eq {bar}} {\n                set bar_seen 1\n            }\n        }\n        list $foo_seen $bar_seen\n    } {1 1}\n\n    test {RANDOMKEY against empty DB} {\n        r flushdb\n        r randomkey\n    } {}\n\n    test {RANDOMKEY regression 1} {\n        r flushdb\n        r set x 10\n        r del x\n        r randomkey\n    } {}\n\n    test {KEYS * two times with long key, Github issue #1208} {\n        r flushdb\n        r set dlskeriewrioeuwqoirueioqwrueoqwrueqw test\n        r keys *\n        r keys *\n    } {dlskeriewrioeuwqoirueioqwrueoqwrueqw}\n}\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/tests/unit/latency-monitor.tcl",
    "content": "start_server {tags {\"latency-monitor\"}} {\n    # Set a threshold high enough to avoid spurious latency events.\n    r config set latency-monitor-threshold 200\n    r latency reset\n\n    test {Test latency events logging} {\n        r debug sleep 0.3\n        after 1100\n        r debug sleep 0.4\n        after 1100\n        r debug sleep 0.5\n        assert {[r latency history command] >= 3}\n    }\n\n    test {LATENCY HISTORY output is ok} {\n        set min 250\n        set max 450\n        foreach event [r latency history command] {\n            lassign $event time latency\n            assert {$latency >= $min && $latency <= $max}\n            incr min 100\n            incr max 100\n            set last_time $time ; # Used in the next test\n        }\n    }\n\n    test {LATENCY LATEST output is ok} {\n        foreach event [r latency latest] {\n            lassign $event eventname time latency max\n            assert {$eventname eq \"command\"}\n            assert {$max >= 450 & $max <= 650}\n            assert {$time == $last_time}\n            break\n        }\n    }\n\n    test {LATENCY HISTORY / RESET with wrong event name is fine} {\n        assert {[llength [r latency history blabla]] == 0}\n        assert {[r latency reset blabla] == 0}\n    }\n\n    test {LATENCY DOCTOR produces some output} {\n        assert {[string length [r latency doctor]] > 0}\n    }\n\n    test {LATENCY RESET is able to reset events} {\n        assert {[r latency reset] > 0}\n        assert {[r latency latest] eq {}}\n    }\n}\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/tests/unit/limits.tcl",
    "content": "start_server {tags {\"limits\"} overrides {maxclients 10}} {\n    test {Check if maxclients works refusing connections} {\n        set c 0\n        catch {\n            while {$c < 50} {\n                incr c\n                set rd [redis_deferring_client]\n                $rd ping\n                $rd read\n                after 100\n            }\n        } e\n        assert {$c > 8 && $c <= 10}\n        set e\n    } {*ERR max*reached*}\n}\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/tests/unit/maxmemory.tcl",
    "content": "start_server {tags {\"maxmemory\"}} {\n    test \"Without maxmemory small integers are shared\" {\n        r config set maxmemory 0\n        r set a 1\n        assert {[r object refcount a] > 1}\n    }\n\n    test \"With maxmemory and non-LRU policy integers are still shared\" {\n        r config set maxmemory 1073741824\n        r config set maxmemory-policy allkeys-random\n        r set a 1\n        assert {[r object refcount a] > 1}\n    }\n\n    test \"With maxmemory and LRU policy integers are not shared\" {\n        r config set maxmemory 1073741824\n        r config set maxmemory-policy allkeys-lru\n        r set a 1\n        r config set maxmemory-policy volatile-lru\n        r set b 1\n        assert {[r object refcount a] == 1}\n        assert {[r object refcount b] == 1}\n        r config set maxmemory 0\n    }\n\n    foreach policy {\n        allkeys-random allkeys-lru volatile-lru volatile-random volatile-ttl\n    } {\n        test \"maxmemory - is the memory limit honoured? (policy $policy)\" {\n            # make sure to start with a blank instance\n            r flushall\n            # Get the current memory limit and calculate a new limit.\n            # We just add 100k to the current memory size so that it is\n            # fast for us to reach that limit.\n            set used [s used_memory]\n            set limit [expr {$used+100*1024}]\n            r config set maxmemory $limit\n            r config set maxmemory-policy $policy\n            # Now add keys until the limit is almost reached.\n            set numkeys 0\n            while 1 {\n                r setex [randomKey] 10000 x\n                incr numkeys\n                if {[s used_memory]+4096 > $limit} {\n                    assert {$numkeys > 10}\n                    break\n                }\n            }\n            # If we add the same number of keys already added again, we\n            # should still be under the limit.\n            for {set j 0} {$j < $numkeys} {incr j} {\n                r setex [randomKey] 10000 x\n            }\n            assert {[s used_memory] < ($limit+4096)}\n        }\n    }\n\n    foreach policy {\n        allkeys-random allkeys-lru volatile-lru volatile-random volatile-ttl\n    } {\n        test \"maxmemory - only allkeys-* should remove non-volatile keys ($policy)\" {\n            # make sure to start with a blank instance\n            r flushall\n            # Get the current memory limit and calculate a new limit.\n            # We just add 100k to the current memory size so that it is\n            # fast for us to reach that limit.\n            set used [s used_memory]\n            set limit [expr {$used+100*1024}]\n            r config set maxmemory $limit\n            r config set maxmemory-policy $policy\n            # Now add keys until the limit is almost reached.\n            set numkeys 0\n            while 1 {\n                r set [randomKey] x\n                incr numkeys\n                if {[s used_memory]+4096 > $limit} {\n                    assert {$numkeys > 10}\n                    break\n                }\n            }\n            # If we add the same number of keys already added again and\n            # the policy is allkeys-* we should still be under the limit.\n            # Otherwise we should see an error reported by Redis.\n            set err 0\n            for {set j 0} {$j < $numkeys} {incr j} {\n                if {[catch {r set [randomKey] x} e]} {\n                    if {[string match {*used memory*} $e]} {\n                        set err 1\n                    }\n                }\n            }\n            if {[string match allkeys-* $policy]} {\n                assert {[s used_memory] < ($limit+4096)}\n            } else {\n                assert {$err == 1}\n            }\n        }\n    }\n\n    foreach policy {\n        volatile-lru volatile-random volatile-ttl\n    } {\n        test \"maxmemory - policy $policy should only remove volatile keys.\" {\n            # make sure to start with a blank instance\n            r flushall\n            # Get the current memory limit and calculate a new limit.\n            # We just add 100k to the current memory size so that it is\n            # fast for us to reach that limit.\n            set used [s used_memory]\n            set limit [expr {$used+100*1024}]\n            r config set maxmemory $limit\n            r config set maxmemory-policy $policy\n            # Now add keys until the limit is almost reached.\n            set numkeys 0\n            while 1 {\n                # Odd keys are volatile\n                # Even keys are non volatile\n                if {$numkeys % 2} {\n                    r setex \"key:$numkeys\" 10000 x\n                } else {\n                    r set \"key:$numkeys\" x\n                }\n                if {[s used_memory]+4096 > $limit} {\n                    assert {$numkeys > 10}\n                    break\n                }\n                incr numkeys\n            }\n            # Now we add the same number of volatile keys already added.\n            # We expect Redis to evict only volatile keys in order to make\n            # space.\n            set err 0\n            for {set j 0} {$j < $numkeys} {incr j} {\n                catch {r setex \"foo:$j\" 10000 x}\n            }\n            # We should still be under the limit.\n            assert {[s used_memory] < ($limit+4096)}\n            # However all our non volatile keys should be here.\n            for {set j 0} {$j < $numkeys} {incr j 2} {\n                assert {[r exists \"key:$j\"]}\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/tests/unit/memefficiency.tcl",
    "content": "proc test_memory_efficiency {range} {\n    r flushall\n    set rd [redis_deferring_client]\n    set base_mem [s used_memory]\n    set written 0\n    for {set j 0} {$j < 10000} {incr j} {\n        set key key:$j\n        set val [string repeat A [expr {int(rand()*$range)}]]\n        $rd set $key $val\n        incr written [string length $key]\n        incr written [string length $val]\n        incr written 2 ;# A separator is the minimum to store key-value data.\n    }\n    for {set j 0} {$j < 10000} {incr j} {\n        $rd read ; # Discard replies\n    }\n\n    set current_mem [s used_memory]\n    set used [expr {$current_mem-$base_mem}]\n    set efficiency [expr {double($written)/$used}]\n    return $efficiency\n}\n\nstart_server {tags {\"memefficiency\"}} {\n    foreach {size_range expected_min_efficiency} {\n        32    0.15\n        64    0.25\n        128   0.35\n        1024  0.75\n        16384 0.82\n    } {\n        test \"Memory efficiency with values in range $size_range\" {\n            set efficiency [test_memory_efficiency $size_range]\n            assert {$efficiency >= $expected_min_efficiency}\n        }\n    }\n}\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/tests/unit/multi.tcl",
    "content": "start_server {tags {\"multi\"}} {\n    test {MUTLI / EXEC basics} {\n        r del mylist\n        r rpush mylist a\n        r rpush mylist b\n        r rpush mylist c\n        r multi\n        set v1 [r lrange mylist 0 -1]\n        set v2 [r ping]\n        set v3 [r exec]\n        list $v1 $v2 $v3\n    } {QUEUED QUEUED {{a b c} PONG}}\n\n    test {DISCARD} {\n        r del mylist\n        r rpush mylist a\n        r rpush mylist b\n        r rpush mylist c\n        r multi\n        set v1 [r del mylist]\n        set v2 [r discard]\n        set v3 [r lrange mylist 0 -1]\n        list $v1 $v2 $v3\n    } {QUEUED OK {a b c}}\n\n    test {Nested MULTI are not allowed} {\n        set err {}\n        r multi\n        catch {[r multi]} err\n        r exec\n        set _ $err\n    } {*ERR MULTI*}\n\n    test {MULTI where commands alter argc/argv} {\n        r sadd myset a\n        r multi\n        r spop myset\n        list [r exec] [r exists myset]\n    } {a 0}\n\n    test {WATCH inside MULTI is not allowed} {\n        set err {}\n        r multi\n        catch {[r watch x]} err\n        r exec\n        set _ $err\n    } {*ERR WATCH*}\n\n    test {EXEC fails if there are errors while queueing commands #1} {\n        r del foo1 foo2\n        r multi\n        r set foo1 bar1\n        catch {r non-existing-command}\n        r set foo2 bar2\n        catch {r exec} e\n        assert_match {EXECABORT*} $e\n        list [r exists foo1] [r exists foo2]\n    } {0 0}\n\n    test {EXEC fails if there are errors while queueing commands #2} {\n        set rd [redis_deferring_client]\n        r del foo1 foo2\n        r multi\n        r set foo1 bar1\n        $rd config set maxmemory 1\n        assert  {[$rd read] eq {OK}}\n        catch {r lpush mylist myvalue}\n        $rd config set maxmemory 0\n        assert  {[$rd read] eq {OK}}\n        r set foo2 bar2\n        catch {r exec} e\n        assert_match {EXECABORT*} $e\n        $rd close\n        list [r exists foo1] [r exists foo2]\n    } {0 0}\n\n    test {If EXEC aborts, the client MULTI state is cleared} {\n        r del foo1 foo2\n        r multi\n        r set foo1 bar1\n        catch {r non-existing-command}\n        r set foo2 bar2\n        catch {r exec} e\n        assert_match {EXECABORT*} $e\n        r ping\n    } {PONG}\n\n    test {EXEC works on WATCHed key not modified} {\n        r watch x y z\n        r watch k\n        r multi\n        r ping\n        r exec\n    } {PONG}\n\n    test {EXEC fail on WATCHed key modified (1 key of 1 watched)} {\n        r set x 30\n        r watch x\n        r set x 40\n        r multi\n        r ping\n        r exec\n    } {}\n\n    test {EXEC fail on WATCHed key modified (1 key of 5 watched)} {\n        r set x 30\n        r watch a b x k z\n        r set x 40\n        r multi\n        r ping\n        r exec\n    } {}\n\n    test {EXEC fail on WATCHed key modified by SORT with STORE even if the result is empty} {\n        r flushdb\n        r lpush foo bar\n        r watch foo\n        r sort emptylist store foo\n        r multi\n        r ping\n        r exec\n    } {}\n\n    test {After successful EXEC key is no longer watched} {\n        r set x 30\n        r watch x\n        r multi\n        r ping\n        r exec\n        r set x 40\n        r multi\n        r ping\n        r exec\n    } {PONG}\n\n    test {After failed EXEC key is no longer watched} {\n        r set x 30\n        r watch x\n        r set x 40\n        r multi\n        r ping\n        r exec\n        r set x 40\n        r multi\n        r ping\n        r exec\n    } {PONG}\n\n    test {It is possible to UNWATCH} {\n        r set x 30\n        r watch x\n        r set x 40\n        r unwatch\n        r multi\n        r ping\n        r exec\n    } {PONG}\n\n    test {UNWATCH when there is nothing watched works as expected} {\n        r unwatch\n    } {OK}\n\n    test {FLUSHALL is able to touch the watched keys} {\n        r set x 30\n        r watch x\n        r flushall\n        r multi\n        r ping\n        r exec\n    } {}\n\n    test {FLUSHALL does not touch non affected keys} {\n        r del x\n        r watch x\n        r flushall\n        r multi\n        r ping\n        r exec\n    } {PONG}\n\n    test {FLUSHDB is able to touch the watched keys} {\n        r set x 30\n        r watch x\n        r flushdb\n        r multi\n        r ping\n        r exec\n    } {}\n\n    test {FLUSHDB does not touch non affected keys} {\n        r del x\n        r watch x\n        r flushdb\n        r multi\n        r ping\n        r exec\n    } {PONG}\n\n    test {WATCH is able to remember the DB a key belongs to} {\n        r select 5\n        r set x 30\n        r watch x\n        r select 1\n        r set x 10\n        r select 5\n        r multi\n        r ping\n        set res [r exec]\n        # Restore original DB\n        r select 9\n        set res\n    } {PONG}\n\n    test {WATCH will consider touched keys target of EXPIRE} {\n        r del x\n        r set x foo\n        r watch x\n        r expire x 10\n        r multi\n        r ping\n        r exec\n    } {}\n\n    test {WATCH will not consider touched expired keys} {\n        r del x\n        r set x foo\n        r expire x 1\n        r watch x\n        after 1100\n        r multi\n        r ping\n        r exec\n    } {PONG}\n\n    test {DISCARD should clear the WATCH dirty flag on the client} {\n        r watch x\n        r set x 10\n        r multi\n        r discard\n        r multi\n        r incr x\n        r exec\n    } {11}\n\n    test {DISCARD should UNWATCH all the keys} {\n        r watch x\n        r set x 10\n        r multi\n        r discard\n        r set x 10\n        r multi\n        r incr x\n        r exec\n    } {11}\n\n    test {MULTI / EXEC is propagated correctly (single write command)} {\n        set repl [attach_to_replication_stream]\n        r multi\n        r set foo bar\n        r exec\n        assert_replication_stream $repl {\n            {select *}\n            {multi}\n            {set foo bar}\n            {exec}\n        }\n        close_replication_stream $repl\n    }\n\n    test {MULTI / EXEC is propagated correctly (empty transaction)} {\n        set repl [attach_to_replication_stream]\n        r multi\n        r exec\n        r set foo bar\n        assert_replication_stream $repl {\n            {select *}\n            {set foo bar}\n        }\n        close_replication_stream $repl\n    }\n\n    test {MULTI / EXEC is propagated correctly (read-only commands)} {\n        r set foo value1\n        set repl [attach_to_replication_stream]\n        r multi\n        r get foo\n        r exec\n        r set foo value2\n        assert_replication_stream $repl {\n            {select *}\n            {set foo value2}\n        }\n        close_replication_stream $repl\n    }\n\n    test {MULTI / EXEC is propagated correctly (write command, no effect)} {\n        r del bar foo bar\n        set repl [attach_to_replication_stream]\n        r multi\n        r del foo\n        r exec\n        assert_replication_stream $repl {\n            {select *}\n            {multi}\n            {exec}\n        }\n        close_replication_stream $repl\n    }\n}\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/tests/unit/obuf-limits.tcl",
    "content": "start_server {tags {\"obuf-limits\"}} {\n    test {Client output buffer hard limit is enforced} {\n        r config set client-output-buffer-limit {pubsub 100000 0 0}\n        set rd1 [redis_deferring_client]\n\n        $rd1 subscribe foo\n        set reply [$rd1 read]\n        assert {$reply eq \"subscribe foo 1\"}\n\n        set omem 0\n        while 1 {\n            r publish foo bar\n            set clients [split [r client list] \"\\r\\n\"]\n            set c [split [lindex $clients 1] \" \"]\n            if {![regexp {omem=([0-9]+)} $c - omem]} break\n            if {$omem > 200000} break\n        }\n        assert {$omem >= 90000 && $omem < 200000}\n        $rd1 close\n    }\n\n    test {Client output buffer soft limit is not enforced if time is not overreached} {\n        r config set client-output-buffer-limit {pubsub 0 100000 10}\n        set rd1 [redis_deferring_client]\n\n        $rd1 subscribe foo\n        set reply [$rd1 read]\n        assert {$reply eq \"subscribe foo 1\"}\n\n        set omem 0\n        set start_time 0\n        set time_elapsed 0\n        while 1 {\n            r publish foo bar\n            set clients [split [r client list] \"\\r\\n\"]\n            set c [split [lindex $clients 1] \" \"]\n            if {![regexp {omem=([0-9]+)} $c - omem]} break\n            if {$omem > 100000} {\n                if {$start_time == 0} {set start_time [clock seconds]}\n                set time_elapsed [expr {[clock seconds]-$start_time}]\n                if {$time_elapsed >= 5} break\n            }\n        }\n        assert {$omem >= 100000 && $time_elapsed >= 5 && $time_elapsed <= 10}\n        $rd1 close\n    }\n\n    test {Client output buffer soft limit is enforced if time is overreached} {\n        r config set client-output-buffer-limit {pubsub 0 100000 3}\n        set rd1 [redis_deferring_client]\n\n        $rd1 subscribe foo\n        set reply [$rd1 read]\n        assert {$reply eq \"subscribe foo 1\"}\n\n        set omem 0\n        set start_time 0\n        set time_elapsed 0\n        while 1 {\n            r publish foo bar\n            set clients [split [r client list] \"\\r\\n\"]\n            set c [split [lindex $clients 1] \" \"]\n            if {![regexp {omem=([0-9]+)} $c - omem]} break\n            if {$omem > 100000} {\n                if {$start_time == 0} {set start_time [clock seconds]}\n                set time_elapsed [expr {[clock seconds]-$start_time}]\n                if {$time_elapsed >= 10} break\n            }\n        }\n        assert {$omem >= 100000 && $time_elapsed < 6}\n        $rd1 close\n    }\n}\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/tests/unit/other.tcl",
    "content": "start_server {tags {\"other\"}} {\n    if {$::force_failure} {\n        # This is used just for test suite development purposes.\n        test {Failing test} {\n            format err\n        } {ok}\n    }\n\n    test {SAVE - make sure there are all the types as values} {\n        # Wait for a background saving in progress to terminate\n        waitForBgsave r\n        r lpush mysavelist hello\n        r lpush mysavelist world\n        r set myemptykey {}\n        r set mynormalkey {blablablba}\n        r zadd mytestzset 10 a\n        r zadd mytestzset 20 b\n        r zadd mytestzset 30 c\n        r save\n    } {OK}\n\n    tags {slow} {\n        if {$::accurate} {set iterations 10000} else {set iterations 1000}\n        foreach fuzztype {binary alpha compr} {\n            test \"FUZZ stresser with data model $fuzztype\" {\n                set err 0\n                for {set i 0} {$i < $iterations} {incr i} {\n                    set fuzz [randstring 0 512 $fuzztype]\n                    r set foo $fuzz\n                    set got [r get foo]\n                    if {$got ne $fuzz} {\n                        set err [list $fuzz $got]\n                        break\n                    }\n                }\n                set _ $err\n            } {0}\n        }\n    }\n\n    test {BGSAVE} {\n        waitForBgsave r\n        r flushdb\n        r save\n        r set x 10\n        r bgsave\n        waitForBgsave r\n        r debug reload\n        r get x\n    } {10}\n\n    test {SELECT an out of range DB} {\n        catch {r select 1000000} err\n        set _ $err\n    } {*invalid*}\n\n    tags {consistency} {\n        if {![catch {package require sha1}]} {\n            if {$::accurate} {set numops 10000} else {set numops 1000}\n            test {Check consistency of different data types after a reload} {\n                r flushdb\n                createComplexDataset r $numops\n                set dump [csvdump r]\n                set sha1 [r debug digest]\n                r debug reload\n                set sha1_after [r debug digest]\n                if {$sha1 eq $sha1_after} {\n                    set _ 1\n                } else {\n                    set newdump [csvdump r]\n                    puts \"Consistency test failed!\"\n                    puts \"You can inspect the two dumps in /tmp/repldump*.txt\"\n\n                    set fd [open /tmp/repldump1.txt w]\n                    puts $fd $dump\n                    close $fd\n                    set fd [open /tmp/repldump2.txt w]\n                    puts $fd $newdump\n                    close $fd\n\n                    set _ 0\n                }\n            } {1}\n\n            test {Same dataset digest if saving/reloading as AOF?} {\n                r bgrewriteaof\n                waitForBgrewriteaof r\n                r debug loadaof\n                set sha1_after [r debug digest]\n                if {$sha1 eq $sha1_after} {\n                    set _ 1\n                } else {\n                    set newdump [csvdump r]\n                    puts \"Consistency test failed!\"\n                    puts \"You can inspect the two dumps in /tmp/aofdump*.txt\"\n\n                    set fd [open /tmp/aofdump1.txt w]\n                    puts $fd $dump\n                    close $fd\n                    set fd [open /tmp/aofdump2.txt w]\n                    puts $fd $newdump\n                    close $fd\n\n                    set _ 0\n                }\n            } {1}\n        }\n    }\n\n    test {EXPIRES after a reload (snapshot + append only file rewrite)} {\n        r flushdb\n        r set x 10\n        r expire x 1000\n        r save\n        r debug reload\n        set ttl [r ttl x]\n        set e1 [expr {$ttl > 900 && $ttl <= 1000}]\n        r bgrewriteaof\n        waitForBgrewriteaof r\n        r debug loadaof\n        set ttl [r ttl x]\n        set e2 [expr {$ttl > 900 && $ttl <= 1000}]\n        list $e1 $e2\n    } {1 1}\n\n    test {EXPIRES after AOF reload (without rewrite)} {\n        r flushdb\n        r config set appendonly yes\n        r set x somevalue\n        r expire x 1000\n        r setex y 2000 somevalue\n        r set z somevalue\n        r expireat z [expr {[clock seconds]+3000}]\n\n        # Milliseconds variants\n        r set px somevalue\n        r pexpire px 1000000\n        r psetex py 2000000 somevalue\n        r set pz somevalue\n        r pexpireat pz [expr {([clock seconds]+3000)*1000}]\n\n        # Reload and check\n        waitForBgrewriteaof r\n        # We need to wait two seconds to avoid false positives here, otherwise\n        # the DEBUG LOADAOF command may read a partial file.\n        # Another solution would be to set the fsync policy to no, since this\n        # prevents write() to be delayed by the completion of fsync().\n        after 2000\n        r debug loadaof\n        set ttl [r ttl x]\n        assert {$ttl > 900 && $ttl <= 1000}\n        set ttl [r ttl y]\n        assert {$ttl > 1900 && $ttl <= 2000}\n        set ttl [r ttl z]\n        assert {$ttl > 2900 && $ttl <= 3000}\n        set ttl [r ttl px]\n        assert {$ttl > 900 && $ttl <= 1000}\n        set ttl [r ttl py]\n        assert {$ttl > 1900 && $ttl <= 2000}\n        set ttl [r ttl pz]\n        assert {$ttl > 2900 && $ttl <= 3000}\n        r config set appendonly no\n    }\n\n    tags {protocol} {\n        test {PIPELINING stresser (also a regression for the old epoll bug)} {\n            set fd2 [socket $::host $::port]\n            fconfigure $fd2 -encoding binary -translation binary\n            puts -nonewline $fd2 \"SELECT 9\\r\\n\"\n            flush $fd2\n            gets $fd2\n\n            for {set i 0} {$i < 100000} {incr i} {\n                set q {}\n                set val \"0000${i}0000\"\n                append q \"SET key:$i $val\\r\\n\"\n                puts -nonewline $fd2 $q\n                set q {}\n                append q \"GET key:$i\\r\\n\"\n                puts -nonewline $fd2 $q\n            }\n            flush $fd2\n\n            for {set i 0} {$i < 100000} {incr i} {\n                gets $fd2 line\n                gets $fd2 count\n                set count [string range $count 1 end]\n                set val [read $fd2 $count]\n                read $fd2 2\n            }\n            close $fd2\n            set _ 1\n        } {1}\n    }\n\n    test {APPEND basics} {\n        r del foo\n        list [r append foo bar] [r get foo] \\\n             [r append foo 100] [r get foo]\n    } {3 bar 6 bar100}\n\n    test {APPEND basics, integer encoded values} {\n        set res {}\n        r del foo\n        r append foo 1\n        r append foo 2\n        lappend res [r get foo]\n        r set foo 1\n        r append foo 2\n        lappend res [r get foo]\n    } {12 12}\n\n    test {APPEND fuzzing} {\n        set err {}\n        foreach type {binary alpha compr} {\n            set buf {}\n            r del x\n            for {set i 0} {$i < 1000} {incr i} {\n                set bin [randstring 0 10 $type]\n                append buf $bin\n                r append x $bin\n            }\n            if {$buf != [r get x]} {\n                set err \"Expected '$buf' found '[r get x]'\"\n                break\n            }\n        }\n        set _ $err\n    } {}\n\n    # Leave the user with a clean DB before to exit\n    test {FLUSHDB} {\n        set aux {}\n        r select 9\n        r flushdb\n        lappend aux [r dbsize]\n        r select 10\n        r flushdb\n        lappend aux [r dbsize]\n    } {0 0}\n\n    test {Perform a final SAVE to leave a clean DB on disk} {\n        waitForBgsave r\n        r save\n    } {OK}\n}\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/tests/unit/printver.tcl",
    "content": "start_server {} {\n    set i [r info]\n    regexp {redis_version:(.*?)\\r\\n} $i - version\n    regexp {redis_git_sha1:(.*?)\\r\\n} $i - sha1\n    puts \"Testing Redis version $version ($sha1)\"\n}\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/tests/unit/protocol.tcl",
    "content": "start_server {tags {\"protocol\"}} {\n    test \"Handle an empty query\" {\n        reconnect\n        r write \"\\r\\n\"\n        r flush\n        assert_equal \"PONG\" [r ping]\n    }\n\n    test \"Negative multibulk length\" {\n        reconnect\n        r write \"*-10\\r\\n\"\n        r flush\n        assert_equal PONG [r ping]\n    }\n\n    test \"Out of range multibulk length\" {\n        reconnect\n        r write \"*20000000\\r\\n\"\n        r flush\n        assert_error \"*invalid multibulk length*\" {r read}\n    }\n\n    test \"Wrong multibulk payload header\" {\n        reconnect\n        r write \"*3\\r\\n\\$3\\r\\nSET\\r\\n\\$1\\r\\nx\\r\\nfooz\\r\\n\"\n        r flush\n        assert_error \"*expected '$', got 'f'*\" {r read}\n    }\n\n    test \"Negative multibulk payload length\" {\n        reconnect\n        r write \"*3\\r\\n\\$3\\r\\nSET\\r\\n\\$1\\r\\nx\\r\\n\\$-10\\r\\n\"\n        r flush\n        assert_error \"*invalid bulk length*\" {r read}\n    }\n\n    test \"Out of range multibulk payload length\" {\n        reconnect\n        r write \"*3\\r\\n\\$3\\r\\nSET\\r\\n\\$1\\r\\nx\\r\\n\\$2000000000\\r\\n\"\n        r flush\n        assert_error \"*invalid bulk length*\" {r read}\n    }\n\n    test \"Non-number multibulk payload length\" {\n        reconnect\n        r write \"*3\\r\\n\\$3\\r\\nSET\\r\\n\\$1\\r\\nx\\r\\n\\$blabla\\r\\n\"\n        r flush\n        assert_error \"*invalid bulk length*\" {r read}\n    }\n\n    test \"Multi bulk request not followed by bulk arguments\" {\n        reconnect\n        r write \"*1\\r\\nfoo\\r\\n\"\n        r flush\n        assert_error \"*expected '$', got 'f'*\" {r read}\n    }\n\n    test \"Generic wrong number of args\" {\n        reconnect\n        assert_error \"*wrong*arguments*ping*\" {r ping x y z}\n    }\n\n    test \"Unbalanced number of quotes\" {\n        reconnect\n        r write \"set \\\"\\\"\\\"test-key\\\"\\\"\\\" test-value\\r\\n\"\n        r write \"ping\\r\\n\"\n        r flush\n        assert_error \"*unbalanced*\" {r read}\n    }\n\n    set c 0\n    foreach seq [list \"\\x00\" \"*\\x00\" \"$\\x00\"] {\n        incr c\n        test \"Protocol desync regression test #$c\" {\n            set s [socket [srv 0 host] [srv 0 port]]\n            puts -nonewline $s $seq\n            set payload [string repeat A 1024]\"\\n\"\n            set test_start [clock seconds]\n            set test_time_limit 30\n            while 1 {\n                if {[catch {\n                    puts -nonewline $s payload\n                    flush $s\n                    incr payload_size [string length $payload]\n                }]} {\n                    set retval [gets $s]\n                    close $s\n                    break\n                } else {\n                    set elapsed [expr {[clock seconds]-$test_start}]\n                    if {$elapsed > $test_time_limit} {\n                        close $s\n                        error \"assertion:Redis did not closed connection after protocol desync\"\n                    }\n                }\n            }\n            set retval\n        } {*Protocol error*}\n    }\n    unset c\n}\n\nstart_server {tags {\"regression\"}} {\n    test \"Regression for a crash with blocking ops and pipelining\" {\n        set rd [redis_deferring_client]\n        set fd [r channel]\n        set proto \"*3\\r\\n\\$5\\r\\nBLPOP\\r\\n\\$6\\r\\nnolist\\r\\n\\$1\\r\\n0\\r\\n\"\n        puts -nonewline $fd $proto$proto\n        flush $fd\n        set res {}\n\n        $rd rpush nolist a\n        $rd read\n        $rd rpush nolist a\n        $rd read\n    }\n}\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/tests/unit/pubsub.tcl",
    "content": "start_server {tags {\"pubsub\"}} {\n    proc __consume_subscribe_messages {client type channels} {\n        set numsub -1\n        set counts {}\n\n        for {set i [llength $channels]} {$i > 0} {incr i -1} {\n            set msg [$client read]\n            assert_equal $type [lindex $msg 0]\n\n            # when receiving subscribe messages the channels names\n            # are ordered. when receiving unsubscribe messages\n            # they are unordered\n            set idx [lsearch -exact $channels [lindex $msg 1]]\n            if {[string match \"*unsubscribe\" $type]} {\n                assert {$idx >= 0}\n            } else {\n                assert {$idx == 0}\n            }\n            set channels [lreplace $channels $idx $idx]\n\n            # aggregate the subscription count to return to the caller\n            lappend counts [lindex $msg 2]\n        }\n\n        # we should have received messages for channels\n        assert {[llength $channels] == 0}\n        return $counts\n    }\n\n    proc subscribe {client channels} {\n        $client subscribe {*}$channels\n        __consume_subscribe_messages $client subscribe $channels\n    }\n\n    proc unsubscribe {client {channels {}}} {\n        $client unsubscribe {*}$channels\n        __consume_subscribe_messages $client unsubscribe $channels\n    }\n\n    proc psubscribe {client channels} {\n        $client psubscribe {*}$channels\n        __consume_subscribe_messages $client psubscribe $channels\n    }\n\n    proc punsubscribe {client {channels {}}} {\n        $client punsubscribe {*}$channels\n        __consume_subscribe_messages $client punsubscribe $channels\n    }\n\n    test \"Pub/Sub PING\" {\n        set rd1 [redis_deferring_client]\n        subscribe $rd1 somechannel\n        # While subscribed to non-zero channels PING works in Pub/Sub mode.\n        $rd1 ping\n        $rd1 ping \"foo\"\n        set reply1 [$rd1 read]\n        set reply2 [$rd1 read]\n        unsubscribe $rd1 somechannel\n        # Now we are unsubscribed, PING should just return PONG.\n        $rd1 ping\n        set reply3 [$rd1 read]\n        $rd1 close\n        list $reply1 $reply2 $reply3\n    } {{pong {}} {pong foo} PONG}\n\n    test \"PUBLISH/SUBSCRIBE basics\" {\n        set rd1 [redis_deferring_client]\n\n        # subscribe to two channels\n        assert_equal {1 2} [subscribe $rd1 {chan1 chan2}]\n        assert_equal 1 [r publish chan1 hello]\n        assert_equal 1 [r publish chan2 world]\n        assert_equal {message chan1 hello} [$rd1 read]\n        assert_equal {message chan2 world} [$rd1 read]\n\n        # unsubscribe from one of the channels\n        unsubscribe $rd1 {chan1}\n        assert_equal 0 [r publish chan1 hello]\n        assert_equal 1 [r publish chan2 world]\n        assert_equal {message chan2 world} [$rd1 read]\n\n        # unsubscribe from the remaining channel\n        unsubscribe $rd1 {chan2}\n        assert_equal 0 [r publish chan1 hello]\n        assert_equal 0 [r publish chan2 world]\n\n        # clean up clients\n        $rd1 close\n    }\n\n    test \"PUBLISH/SUBSCRIBE with two clients\" {\n        set rd1 [redis_deferring_client]\n        set rd2 [redis_deferring_client]\n\n        assert_equal {1} [subscribe $rd1 {chan1}]\n        assert_equal {1} [subscribe $rd2 {chan1}]\n        assert_equal 2 [r publish chan1 hello]\n        assert_equal {message chan1 hello} [$rd1 read]\n        assert_equal {message chan1 hello} [$rd2 read]\n\n        # clean up clients\n        $rd1 close\n        $rd2 close\n    }\n\n    test \"PUBLISH/SUBSCRIBE after UNSUBSCRIBE without arguments\" {\n        set rd1 [redis_deferring_client]\n        assert_equal {1 2 3} [subscribe $rd1 {chan1 chan2 chan3}]\n        unsubscribe $rd1\n        assert_equal 0 [r publish chan1 hello]\n        assert_equal 0 [r publish chan2 hello]\n        assert_equal 0 [r publish chan3 hello]\n\n        # clean up clients\n        $rd1 close\n    }\n\n    test \"SUBSCRIBE to one channel more than once\" {\n        set rd1 [redis_deferring_client]\n        assert_equal {1 1 1} [subscribe $rd1 {chan1 chan1 chan1}]\n        assert_equal 1 [r publish chan1 hello]\n        assert_equal {message chan1 hello} [$rd1 read]\n\n        # clean up clients\n        $rd1 close\n    }\n\n    test \"UNSUBSCRIBE from non-subscribed channels\" {\n        set rd1 [redis_deferring_client]\n        assert_equal {0 0 0} [unsubscribe $rd1 {foo bar quux}]\n\n        # clean up clients\n        $rd1 close\n    }\n\n    test \"PUBLISH/PSUBSCRIBE basics\" {\n        set rd1 [redis_deferring_client]\n\n        # subscribe to two patterns\n        assert_equal {1 2} [psubscribe $rd1 {foo.* bar.*}]\n        assert_equal 1 [r publish foo.1 hello]\n        assert_equal 1 [r publish bar.1 hello]\n        assert_equal 0 [r publish foo1 hello]\n        assert_equal 0 [r publish barfoo.1 hello]\n        assert_equal 0 [r publish qux.1 hello]\n        assert_equal {pmessage foo.* foo.1 hello} [$rd1 read]\n        assert_equal {pmessage bar.* bar.1 hello} [$rd1 read]\n\n        # unsubscribe from one of the patterns\n        assert_equal {1} [punsubscribe $rd1 {foo.*}]\n        assert_equal 0 [r publish foo.1 hello]\n        assert_equal 1 [r publish bar.1 hello]\n        assert_equal {pmessage bar.* bar.1 hello} [$rd1 read]\n\n        # unsubscribe from the remaining pattern\n        assert_equal {0} [punsubscribe $rd1 {bar.*}]\n        assert_equal 0 [r publish foo.1 hello]\n        assert_equal 0 [r publish bar.1 hello]\n\n        # clean up clients\n        $rd1 close\n    }\n\n    test \"PUBLISH/PSUBSCRIBE with two clients\" {\n        set rd1 [redis_deferring_client]\n        set rd2 [redis_deferring_client]\n\n        assert_equal {1} [psubscribe $rd1 {chan.*}]\n        assert_equal {1} [psubscribe $rd2 {chan.*}]\n        assert_equal 2 [r publish chan.foo hello]\n        assert_equal {pmessage chan.* chan.foo hello} [$rd1 read]\n        assert_equal {pmessage chan.* chan.foo hello} [$rd2 read]\n\n        # clean up clients\n        $rd1 close\n        $rd2 close\n    }\n\n    test \"PUBLISH/PSUBSCRIBE after PUNSUBSCRIBE without arguments\" {\n        set rd1 [redis_deferring_client]\n        assert_equal {1 2 3} [psubscribe $rd1 {chan1.* chan2.* chan3.*}]\n        punsubscribe $rd1\n        assert_equal 0 [r publish chan1.hi hello]\n        assert_equal 0 [r publish chan2.hi hello]\n        assert_equal 0 [r publish chan3.hi hello]\n\n        # clean up clients\n        $rd1 close\n    }\n\n    test \"PUNSUBSCRIBE from non-subscribed channels\" {\n        set rd1 [redis_deferring_client]\n        assert_equal {0 0 0} [punsubscribe $rd1 {foo.* bar.* quux.*}]\n\n        # clean up clients\n        $rd1 close\n    }\n\n    test \"NUMSUB returns numbers, not strings (#1561)\" {\n        r pubsub numsub abc def\n    } {abc 0 def 0}\n\n    test \"Mix SUBSCRIBE and PSUBSCRIBE\" {\n        set rd1 [redis_deferring_client]\n        assert_equal {1} [subscribe $rd1 {foo.bar}]\n        assert_equal {2} [psubscribe $rd1 {foo.*}]\n\n        assert_equal 2 [r publish foo.bar hello]\n        assert_equal {message foo.bar hello} [$rd1 read]\n        assert_equal {pmessage foo.* foo.bar hello} [$rd1 read]\n\n        # clean up clients\n        $rd1 close\n    }\n\n    test \"PUNSUBSCRIBE and UNSUBSCRIBE should always reply\" {\n        # Make sure we are not subscribed to any channel at all.\n        r punsubscribe\n        r unsubscribe\n        # Now check if the commands still reply correctly.\n        set reply1 [r punsubscribe]\n        set reply2 [r unsubscribe]\n        concat $reply1 $reply2\n    } {punsubscribe {} 0 unsubscribe {} 0}\n\n    ### Keyspace events notification tests\n\n    test \"Keyspace notifications: we receive keyspace notifications\" {\n        r config set notify-keyspace-events KA\n        set rd1 [redis_deferring_client]\n        assert_equal {1} [psubscribe $rd1 *]\n        r set foo bar\n        assert_equal {pmessage * __keyspace@9__:foo set} [$rd1 read]\n        $rd1 close\n    }\n\n    test \"Keyspace notifications: we receive keyevent notifications\" {\n        r config set notify-keyspace-events EA\n        set rd1 [redis_deferring_client]\n        assert_equal {1} [psubscribe $rd1 *]\n        r set foo bar\n        assert_equal {pmessage * __keyevent@9__:set foo} [$rd1 read]\n        $rd1 close\n    }\n\n    test \"Keyspace notifications: we can receive both kind of events\" {\n        r config set notify-keyspace-events KEA\n        set rd1 [redis_deferring_client]\n        assert_equal {1} [psubscribe $rd1 *]\n        r set foo bar\n        assert_equal {pmessage * __keyspace@9__:foo set} [$rd1 read]\n        assert_equal {pmessage * __keyevent@9__:set foo} [$rd1 read]\n        $rd1 close\n    }\n\n    test \"Keyspace notifications: we are able to mask events\" {\n        r config set notify-keyspace-events KEl\n        r del mylist\n        set rd1 [redis_deferring_client]\n        assert_equal {1} [psubscribe $rd1 *]\n        r set foo bar\n        r lpush mylist a\n        # No notification for set, because only list commands are enabled.\n        assert_equal {pmessage * __keyspace@9__:mylist lpush} [$rd1 read]\n        assert_equal {pmessage * __keyevent@9__:lpush mylist} [$rd1 read]\n        $rd1 close\n    }\n\n    test \"Keyspace notifications: general events test\" {\n        r config set notify-keyspace-events KEg\n        set rd1 [redis_deferring_client]\n        assert_equal {1} [psubscribe $rd1 *]\n        r set foo bar\n        r expire foo 1\n        r del foo\n        assert_equal {pmessage * __keyspace@9__:foo expire} [$rd1 read]\n        assert_equal {pmessage * __keyevent@9__:expire foo} [$rd1 read]\n        assert_equal {pmessage * __keyspace@9__:foo del} [$rd1 read]\n        assert_equal {pmessage * __keyevent@9__:del foo} [$rd1 read]\n        $rd1 close\n    }\n\n    test \"Keyspace notifications: list events test\" {\n        r config set notify-keyspace-events KEl\n        r del mylist\n        set rd1 [redis_deferring_client]\n        assert_equal {1} [psubscribe $rd1 *]\n        r lpush mylist a\n        r rpush mylist a\n        r rpop mylist\n        assert_equal {pmessage * __keyspace@9__:mylist lpush} [$rd1 read]\n        assert_equal {pmessage * __keyevent@9__:lpush mylist} [$rd1 read]\n        assert_equal {pmessage * __keyspace@9__:mylist rpush} [$rd1 read]\n        assert_equal {pmessage * __keyevent@9__:rpush mylist} [$rd1 read]\n        assert_equal {pmessage * __keyspace@9__:mylist rpop} [$rd1 read]\n        assert_equal {pmessage * __keyevent@9__:rpop mylist} [$rd1 read]\n        $rd1 close\n    }\n\n    test \"Keyspace notifications: set events test\" {\n        r config set notify-keyspace-events Ks\n        r del myset\n        set rd1 [redis_deferring_client]\n        assert_equal {1} [psubscribe $rd1 *]\n        r sadd myset a b c d\n        r srem myset x\n        r sadd myset x y z\n        r srem myset x\n        assert_equal {pmessage * __keyspace@9__:myset sadd} [$rd1 read]\n        assert_equal {pmessage * __keyspace@9__:myset sadd} [$rd1 read]\n        assert_equal {pmessage * __keyspace@9__:myset srem} [$rd1 read]\n        $rd1 close\n    }\n\n    test \"Keyspace notifications: zset events test\" {\n        r config set notify-keyspace-events Kz\n        r del myzset\n        set rd1 [redis_deferring_client]\n        assert_equal {1} [psubscribe $rd1 *]\n        r zadd myzset 1 a 2 b\n        r zrem myzset x\n        r zadd myzset 3 x 4 y 5 z\n        r zrem myzset x\n        assert_equal {pmessage * __keyspace@9__:myzset zadd} [$rd1 read]\n        assert_equal {pmessage * __keyspace@9__:myzset zadd} [$rd1 read]\n        assert_equal {pmessage * __keyspace@9__:myzset zrem} [$rd1 read]\n        $rd1 close\n    }\n\n    test \"Keyspace notifications: hash events test\" {\n        r config set notify-keyspace-events Kh\n        r del myhash\n        set rd1 [redis_deferring_client]\n        assert_equal {1} [psubscribe $rd1 *]\n        r hmset myhash yes 1 no 0\n        r hincrby myhash yes 10\n        assert_equal {pmessage * __keyspace@9__:myhash hset} [$rd1 read]\n        assert_equal {pmessage * __keyspace@9__:myhash hincrby} [$rd1 read]\n        $rd1 close\n    }\n\n    test \"Keyspace notifications: expired events (triggered expire)\" {\n        r config set notify-keyspace-events Ex\n        r del foo\n        set rd1 [redis_deferring_client]\n        assert_equal {1} [psubscribe $rd1 *]\n        r psetex foo 100 1\n        wait_for_condition 50 100 {\n            [r exists foo] == 0\n        } else {\n            fail \"Key does not expire?!\"\n        }\n        assert_equal {pmessage * __keyevent@9__:expired foo} [$rd1 read]\n        $rd1 close\n    }\n\n    test \"Keyspace notifications: expired events (background expire)\" {\n        r config set notify-keyspace-events Ex\n        r del foo\n        set rd1 [redis_deferring_client]\n        assert_equal {1} [psubscribe $rd1 *]\n        r psetex foo 100 1\n        assert_equal {pmessage * __keyevent@9__:expired foo} [$rd1 read]\n        $rd1 close\n    }\n\n    test \"Keyspace notifications: evicted events\" {\n        r config set notify-keyspace-events Ee\n        r config set maxmemory-policy allkeys-lru\n        r flushdb\n        set rd1 [redis_deferring_client]\n        assert_equal {1} [psubscribe $rd1 *]\n        r set foo bar\n        r config set maxmemory 1\n        assert_equal {pmessage * __keyevent@9__:evicted foo} [$rd1 read]\n        r config set maxmemory 0\n        $rd1 close\n    }\n\n    test \"Keyspace notifications: test CONFIG GET/SET of event flags\" {\n        r config set notify-keyspace-events gKE\n        assert_equal {gKE} [lindex [r config get notify-keyspace-events] 1]\n        r config set notify-keyspace-events {$lshzxeKE}\n        assert_equal {$lshzxeKE} [lindex [r config get notify-keyspace-events] 1]\n        r config set notify-keyspace-events KA\n        assert_equal {AK} [lindex [r config get notify-keyspace-events] 1]\n        r config set notify-keyspace-events EA\n        assert_equal {AE} [lindex [r config get notify-keyspace-events] 1]\n    }\n}\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/tests/unit/quit.tcl",
    "content": "start_server {tags {\"quit\"}} {\n    proc format_command {args} {\n        set cmd \"*[llength $args]\\r\\n\"\n        foreach a $args {\n            append cmd \"$[string length $a]\\r\\n$a\\r\\n\"\n        }\n        set _ $cmd\n    }\n\n    test \"QUIT returns OK\" {\n        reconnect\n        assert_equal OK [r quit]\n        assert_error * {r ping}\n    }\n\n    test \"Pipelined commands after QUIT must not be executed\" {\n        reconnect\n        r write [format_command quit]\n        r write [format_command set foo bar]\n        r flush\n        assert_equal OK [r read]\n        assert_error * {r read}\n\n        reconnect\n        assert_equal {} [r get foo]\n    }\n\n    test \"Pipelined commands after QUIT that exceed read buffer size\" {\n        reconnect\n        r write [format_command quit]\n        r write [format_command set foo [string repeat \"x\" 1024]]\n        r flush\n        assert_equal OK [r read]\n        assert_error * {r read}\n\n        reconnect\n        assert_equal {} [r get foo]\n\n    }\n}\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/tests/unit/scan.tcl",
    "content": "start_server {tags {\"scan\"}} {\n    test \"SCAN basic\" {\n        r flushdb\n        r debug populate 1000\n\n        set cur 0\n        set keys {}\n        while 1 {\n            set res [r scan $cur]\n            set cur [lindex $res 0]\n            set k [lindex $res 1]\n            lappend keys {*}$k\n            if {$cur == 0} break\n        }\n\n        set keys [lsort -unique $keys]\n        assert_equal 1000 [llength $keys]\n    }\n\n    test \"SCAN COUNT\" {\n        r flushdb\n        r debug populate 1000\n\n        set cur 0\n        set keys {}\n        while 1 {\n            set res [r scan $cur count 5]\n            set cur [lindex $res 0]\n            set k [lindex $res 1]\n            lappend keys {*}$k\n            if {$cur == 0} break\n        }\n\n        set keys [lsort -unique $keys]\n        assert_equal 1000 [llength $keys]\n    }\n\n    test \"SCAN MATCH\" {\n        r flushdb\n        r debug populate 1000\n\n        set cur 0\n        set keys {}\n        while 1 {\n            set res [r scan $cur match \"key:1??\"]\n            set cur [lindex $res 0]\n            set k [lindex $res 1]\n            lappend keys {*}$k\n            if {$cur == 0} break\n        }\n\n        set keys [lsort -unique $keys]\n        assert_equal 100 [llength $keys]\n    }\n\n    foreach enc {intset hashtable} {\n        test \"SSCAN with encoding $enc\" {\n            # Create the Set\n            r del set\n            if {$enc eq {intset}} {\n                set prefix \"\"\n            } else {\n                set prefix \"ele:\"\n            }\n            set elements {}\n            for {set j 0} {$j < 100} {incr j} {\n                lappend elements ${prefix}${j}\n            }\n            r sadd set {*}$elements\n\n            # Verify that the encoding matches.\n            assert {[r object encoding set] eq $enc}\n\n            # Test SSCAN\n            set cur 0\n            set keys {}\n            while 1 {\n                set res [r sscan set $cur]\n                set cur [lindex $res 0]\n                set k [lindex $res 1]\n                lappend keys {*}$k\n                if {$cur == 0} break\n            }\n\n            set keys [lsort -unique $keys]\n            assert_equal 100 [llength $keys]\n        }\n    }\n\n    foreach enc {ziplist hashtable} {\n        test \"HSCAN with encoding $enc\" {\n            # Create the Hash\n            r del hash\n            if {$enc eq {ziplist}} {\n                set count 30\n            } else {\n                set count 1000\n            }\n            set elements {}\n            for {set j 0} {$j < $count} {incr j} {\n                lappend elements key:$j $j\n            }\n            r hmset hash {*}$elements\n\n            # Verify that the encoding matches.\n            assert {[r object encoding hash] eq $enc}\n\n            # Test HSCAN\n            set cur 0\n            set keys {}\n            while 1 {\n                set res [r hscan hash $cur]\n                set cur [lindex $res 0]\n                set k [lindex $res 1]\n                lappend keys {*}$k\n                if {$cur == 0} break\n            }\n\n            set keys2 {}\n            foreach {k v} $keys {\n                assert {$k eq \"key:$v\"}\n                lappend keys2 $k\n            }\n\n            set keys2 [lsort -unique $keys2]\n            assert_equal $count [llength $keys2]\n        }\n    }\n\n    foreach enc {ziplist skiplist} {\n        test \"ZSCAN with encoding $enc\" {\n            # Create the Sorted Set\n            r del zset\n            if {$enc eq {ziplist}} {\n                set count 30\n            } else {\n                set count 1000\n            }\n            set elements {}\n            for {set j 0} {$j < $count} {incr j} {\n                lappend elements $j key:$j\n            }\n            r zadd zset {*}$elements\n\n            # Verify that the encoding matches.\n            assert {[r object encoding zset] eq $enc}\n\n            # Test ZSCAN\n            set cur 0\n            set keys {}\n            while 1 {\n                set res [r zscan zset $cur]\n                set cur [lindex $res 0]\n                set k [lindex $res 1]\n                lappend keys {*}$k\n                if {$cur == 0} break\n            }\n\n            set keys2 {}\n            foreach {k v} $keys {\n                assert {$k eq \"key:$v\"}\n                lappend keys2 $k\n            }\n\n            set keys2 [lsort -unique $keys2]\n            assert_equal $count [llength $keys2]\n        }\n    }\n\n    test \"SCAN guarantees check under write load\" {\n        r flushdb\n        r debug populate 100\n\n        # We start scanning here, so keys from 0 to 99 should all be\n        # reported at the end of the iteration.\n        set keys {}\n        while 1 {\n            set res [r scan $cur]\n            set cur [lindex $res 0]\n            set k [lindex $res 1]\n            lappend keys {*}$k\n            if {$cur == 0} break\n            # Write 10 random keys at every SCAN iteration.\n            for {set j 0} {$j < 10} {incr j} {\n                r set addedkey:[randomInt 1000] foo\n            }\n        }\n\n        set keys2 {}\n        foreach k $keys {\n            if {[string length $k] > 6} continue\n            lappend keys2 $k\n        }\n\n        set keys2 [lsort -unique $keys2]\n        assert_equal 100 [llength $keys2]\n    }\n\n    test \"SSCAN with integer encoded object (issue #1345)\" {\n        set objects {1 a}\n        r del set\n        r sadd set {*}$objects\n        set res [r sscan set 0 MATCH *a* COUNT 100]\n        assert_equal [lsort -unique [lindex $res 1]] {a}\n        set res [r sscan set 0 MATCH *1* COUNT 100]\n        assert_equal [lsort -unique [lindex $res 1]] {1}\n    }\n\n    test \"SSCAN with PATTERN\" {\n        r del mykey\n        r sadd mykey foo fab fiz foobar 1 2 3 4\n        set res [r sscan mykey 0 MATCH foo* COUNT 10000]\n        lsort -unique [lindex $res 1]\n    } {foo foobar}\n\n    test \"HSCAN with PATTERN\" {\n        r del mykey\n        r hmset mykey foo 1 fab 2 fiz 3 foobar 10 1 a 2 b 3 c 4 d\n        set res [r hscan mykey 0 MATCH foo* COUNT 10000]\n        lsort -unique [lindex $res 1]\n    } {1 10 foo foobar}\n\n    test \"ZSCAN with PATTERN\" {\n        r del mykey\n        r zadd mykey 1 foo 2 fab 3 fiz 10 foobar\n        set res [r zscan mykey 0 MATCH foo* COUNT 10000]\n        lsort -unique [lindex $res 1]\n    }\n\n    test \"ZSCAN scores: regression test for issue #2175\" {\n        r del mykey\n        for {set j 0} {$j < 500} {incr j} {\n            r zadd mykey 9.8813129168249309e-323 $j\n        }\n        set res [lindex [r zscan mykey 0] 1]\n        set first_score [lindex $res 1]\n        assert {$first_score != 0}\n    }\n}\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/tests/unit/scripting.tcl",
    "content": "start_server {tags {\"scripting\"}} {\n    test {EVAL - Does Lua interpreter replies to our requests?} {\n        r eval {return 'hello'} 0\n    } {hello}\n\n    test {EVAL - Lua integer -> Redis protocol type conversion} {\n        r eval {return 100.5} 0\n    } {100}\n\n    test {EVAL - Lua string -> Redis protocol type conversion} {\n        r eval {return 'hello world'} 0\n    } {hello world}\n\n    test {EVAL - Lua true boolean -> Redis protocol type conversion} {\n        r eval {return true} 0\n    } {1}\n\n    test {EVAL - Lua false boolean -> Redis protocol type conversion} {\n        r eval {return false} 0\n    } {}\n\n    test {EVAL - Lua status code reply -> Redis protocol type conversion} {\n        r eval {return {ok='fine'}} 0\n    } {fine}\n\n    test {EVAL - Lua error reply -> Redis protocol type conversion} {\n        catch {\n            r eval {return {err='this is an error'}} 0\n        } e\n        set _ $e\n    } {this is an error}\n\n    test {EVAL - Lua table -> Redis protocol type conversion} {\n        r eval {return {1,2,3,'ciao',{1,2}}} 0\n    } {1 2 3 ciao {1 2}}\n\n    test {EVAL - Are the KEYS and ARGV arrays populated correctly?} {\n        r eval {return {KEYS[1],KEYS[2],ARGV[1],ARGV[2]}} 2 a b c d\n    } {a b c d}\n\n    test {EVAL - is Lua able to call Redis API?} {\n        r set mykey myval\n        r eval {return redis.call('get',KEYS[1])} 1 mykey\n    } {myval}\n\n    test {EVALSHA - Can we call a SHA1 if already defined?} {\n        r evalsha fd758d1589d044dd850a6f05d52f2eefd27f033f 1 mykey\n    } {myval}\n\n    test {EVALSHA - Can we call a SHA1 in uppercase?} {\n        r evalsha FD758D1589D044DD850A6F05D52F2EEFD27F033F 1 mykey\n    } {myval}\n\n    test {EVALSHA - Do we get an error on invalid SHA1?} {\n        catch {r evalsha NotValidShaSUM 0} e\n        set _ $e\n    } {NOSCRIPT*}\n\n    test {EVALSHA - Do we get an error on non defined SHA1?} {\n        catch {r evalsha ffd632c7d33e571e9f24556ebed26c3479a87130 0} e\n        set _ $e\n    } {NOSCRIPT*}\n\n    test {EVAL - Redis integer -> Lua type conversion} {\n        r set x 0\n        r eval {\n            local foo = redis.pcall('incr',KEYS[1])\n            return {type(foo),foo}\n        } 1 x\n    } {number 1}\n\n    test {EVAL - Redis bulk -> Lua type conversion} {\n        r set mykey myval\n        r eval {\n            local foo = redis.pcall('get',KEYS[1])\n            return {type(foo),foo}\n        } 1 mykey\n    } {string myval}\n\n    test {EVAL - Redis multi bulk -> Lua type conversion} {\n        r del mylist\n        r rpush mylist a\n        r rpush mylist b\n        r rpush mylist c\n        r eval {\n            local foo = redis.pcall('lrange',KEYS[1],0,-1)\n            return {type(foo),foo[1],foo[2],foo[3],# foo}\n        } 1 mylist\n    } {table a b c 3}\n\n    test {EVAL - Redis status reply -> Lua type conversion} {\n        r eval {\n            local foo = redis.pcall('set',KEYS[1],'myval')\n            return {type(foo),foo['ok']}\n        } 1 mykey\n    } {table OK}\n\n    test {EVAL - Redis error reply -> Lua type conversion} {\n        r set mykey myval\n        r eval {\n            local foo = redis.pcall('incr',KEYS[1])\n            return {type(foo),foo['err']}\n        } 1 mykey\n    } {table {ERR value is not an integer or out of range}}\n\n    test {EVAL - Redis nil bulk reply -> Lua type conversion} {\n        r del mykey\n        r eval {\n            local foo = redis.pcall('get',KEYS[1])\n            return {type(foo),foo == false}\n        } 1 mykey\n    } {boolean 1}\n\n    test {EVAL - Is the Lua client using the currently selected DB?} {\n        r set mykey \"this is DB 9\"\n        r select 10\n        r set mykey \"this is DB 10\"\n        r eval {return redis.pcall('get',KEYS[1])} 1 mykey\n    } {this is DB 10}\n\n    test {EVAL - SELECT inside Lua should not affect the caller} {\n        # here we DB 10 is selected\n        r set mykey \"original value\"\n        r eval {return redis.pcall('select','9')} 0\n        set res [r get mykey]\n        r select 9\n        set res\n    } {original value}\n\n    if 0 {\n        test {EVAL - Script can't run more than configured time limit} {\n            r config set lua-time-limit 1\n            catch {\n                r eval {\n                    local i = 0\n                    while true do i=i+1 end\n                } 0\n            } e\n            set _ $e\n        } {*execution time*}\n    }\n\n    test {EVAL - Scripts can't run certain commands} {\n        set e {}\n        catch {r eval {return redis.pcall('blpop','x',0)} 0} e\n        set e\n    } {*not allowed*}\n\n    test {EVAL - Scripts can't run certain commands} {\n        set e {}\n        catch {\n            r eval \"redis.pcall('randomkey'); return redis.pcall('set','x','ciao')\" 0\n        } e\n        set e\n    } {*not allowed after*}\n\n    test {EVAL - No arguments to redis.call/pcall is considered an error} {\n        set e {}\n        catch {r eval {return redis.call()} 0} e\n        set e\n    } {*one argument*}\n\n    test {EVAL - redis.call variant raises a Lua error on Redis cmd error (1)} {\n        set e {}\n        catch {\n            r eval \"redis.call('nosuchcommand')\" 0\n        } e\n        set e\n    } {*Unknown Redis*}\n\n    test {EVAL - redis.call variant raises a Lua error on Redis cmd error (1)} {\n        set e {}\n        catch {\n            r eval \"redis.call('get','a','b','c')\" 0\n        } e\n        set e\n    } {*number of args*}\n\n    test {EVAL - redis.call variant raises a Lua error on Redis cmd error (1)} {\n        set e {}\n        r set foo bar\n        catch {\n            r eval {redis.call('lpush',KEYS[1],'val')} 1 foo\n        } e\n        set e\n    } {*against a key*}\n\n    test {EVAL - JSON numeric decoding} {\n        # We must return the table as a string because otherwise\n        # Redis converts floats to ints and we get 0 and 1023 instead\n        # of 0.0003 and 1023.2 as the parsed output.\n        r eval {return\n                 table.concat(\n                   cjson.decode(\n                    \"[0.0, -5e3, -1, 0.3e-3, 1023.2, 0e10]\"), \" \")\n        } 0\n    } {0 -5000 -1 0.0003 1023.2 0}\n\n    test {EVAL - JSON string decoding} {\n        r eval {local decoded = cjson.decode('{\"keya\": \"a\", \"keyb\": \"b\"}')\n                return {decoded.keya, decoded.keyb}\n        } 0\n    } {a b}\n\n    test {EVAL - cmsgpack can pack double?} {\n        r eval {local encoded = cmsgpack.pack(0.1)\n                local h = \"\"\n                for i = 1, #encoded do\n                    h = h .. string.format(\"%02x\",string.byte(encoded,i))\n                end\n                return h\n        } 0\n    } {cb3fb999999999999a}\n\n    test {EVAL - cmsgpack can pack negative int64?} {\n        r eval {local encoded = cmsgpack.pack(-1099511627776)\n                local h = \"\"\n                for i = 1, #encoded do\n                    h = h .. string.format(\"%02x\",string.byte(encoded,i))\n                end\n                return h\n        } 0\n    } {d3ffffff0000000000}\n\n    test {EVAL - cmsgpack can pack and unpack circular references?} {\n        r eval {local a = {x=nil,y=5}\n                local b = {x=a}\n                a['x'] = b\n                local encoded = cmsgpack.pack(a)\n                local h = \"\"\n                -- cmsgpack encodes to a depth of 16, but can't encode\n                -- references, so the encoded object has a deep copy recusive\n                -- depth of 16.\n                for i = 1, #encoded do\n                    h = h .. string.format(\"%02x\",string.byte(encoded,i))\n                end\n                -- when unpacked, re.x.x != re because the unpack creates\n                -- individual tables down to a depth of 16.\n                -- (that's why the encoded output is so large)\n                local re = cmsgpack.unpack(encoded)\n                assert(re)\n                assert(re.x)\n                assert(re.x.x.y == re.y)\n                assert(re.x.x.x.x.y == re.y)\n                assert(re.x.x.x.x.x.x.y == re.y)\n                assert(re.x.x.x.x.x.x.x.x.x.x.y == re.y)\n                -- maximum working depth:\n                assert(re.x.x.x.x.x.x.x.x.x.x.x.x.x.x.y == re.y)\n                -- now the last x would be b above and has no y\n                assert(re.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x)\n                -- so, the final x.x is at the depth limit and was assigned nil\n                assert(re.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x == nil)\n                return {h, re.x.x.x.x.x.x.x.x.y == re.y, re.y == 5}\n        } 0\n    } {82a17905a17881a17882a17905a17881a17882a17905a17881a17882a17905a17881a17882a17905a17881a17882a17905a17881a17882a17905a17881a17882a17905a17881a178c0 1 1}\n\n    test {EVAL - Numerical sanity check from bitop} {\n        r eval {assert(0x7fffffff == 2147483647, \"broken hex literals\");\n                assert(0xffffffff == -1 or 0xffffffff == 2^32-1,\n                    \"broken hex literals\");\n                assert(tostring(-1) == \"-1\", \"broken tostring()\");\n                assert(tostring(0xffffffff) == \"-1\" or\n                    tostring(0xffffffff) == \"4294967295\",\n                    \"broken tostring()\")\n        } 0\n    } {}\n\n    test {EVAL - Verify minimal bitop functionality} {\n        r eval {assert(bit.tobit(1) == 1);\n                assert(bit.band(1) == 1);\n                assert(bit.bxor(1,2) == 3);\n                assert(bit.bor(1,2,4,8,16,32,64,128) == 255)\n        } 0\n    } {}\n\n    test {EVAL - Able to parse trailing comments} {\n        r eval {return 'hello' --trailing comment} 0\n    } {hello}\n\n    test {SCRIPTING FLUSH - is able to clear the scripts cache?} {\n        r set mykey myval\n        set v [r evalsha fd758d1589d044dd850a6f05d52f2eefd27f033f 1 mykey]\n        assert_equal $v myval\n        set e \"\"\n        r script flush\n        catch {r evalsha fd758d1589d044dd850a6f05d52f2eefd27f033f 1 mykey} e\n        set e\n    } {NOSCRIPT*}\n\n    test {SCRIPT EXISTS - can detect already defined scripts?} {\n        r eval \"return 1+1\" 0\n        r script exists a27e7e8a43702b7046d4f6a7ccf5b60cef6b9bd9 a27e7e8a43702b7046d4f6a7ccf5b60cef6b9bda\n    } {1 0}\n\n    test {SCRIPT LOAD - is able to register scripts in the scripting cache} {\n        list \\\n            [r script load \"return 'loaded'\"] \\\n            [r evalsha b534286061d4b9e4026607613b95c06c06015ae8 0]\n    } {b534286061d4b9e4026607613b95c06c06015ae8 loaded}\n\n    test \"In the context of Lua the output of random commands gets ordered\" {\n        r del myset\n        r sadd myset a b c d e f g h i l m n o p q r s t u v z aa aaa azz\n        r eval {return redis.call('smembers',KEYS[1])} 1 myset\n    } {a aa aaa azz b c d e f g h i l m n o p q r s t u v z}\n\n    test \"SORT is normally not alpha re-ordered for the scripting engine\" {\n        r del myset\n        r sadd myset 1 2 3 4 10\n        r eval {return redis.call('sort',KEYS[1],'desc')} 1 myset\n    } {10 4 3 2 1}\n\n    test \"SORT BY <constant> output gets ordered for scripting\" {\n        r del myset\n        r sadd myset a b c d e f g h i l m n o p q r s t u v z aa aaa azz\n        r eval {return redis.call('sort',KEYS[1],'by','_')} 1 myset\n    } {a aa aaa azz b c d e f g h i l m n o p q r s t u v z}\n\n    test \"SORT BY <constant> with GET gets ordered for scripting\" {\n        r del myset\n        r sadd myset a b c\n        r eval {return redis.call('sort',KEYS[1],'by','_','get','#','get','_:*')} 1 myset\n    } {a {} b {} c {}}\n\n    test \"redis.sha1hex() implementation\" {\n        list [r eval {return redis.sha1hex('')} 0] \\\n             [r eval {return redis.sha1hex('Pizza & Mandolino')} 0]\n    } {da39a3ee5e6b4b0d3255bfef95601890afd80709 74822d82031af7493c20eefa13bd07ec4fada82f}\n\n    test {Globals protection reading an undeclared global variable} {\n        catch {r eval {return a} 0} e\n        set e\n    } {*ERR*attempted to access unexisting global*}\n\n    test {Globals protection setting an undeclared global*} {\n        catch {r eval {a=10} 0} e\n        set e\n    } {*ERR*attempted to create global*}\n\n    test {Test an example script DECR_IF_GT} {\n        set decr_if_gt {\n            local current\n\n            current = redis.call('get',KEYS[1])\n            if not current then return nil end\n            if current > ARGV[1] then\n                return redis.call('decr',KEYS[1])\n            else\n                return redis.call('get',KEYS[1])\n            end\n        }\n        r set foo 5\n        set res {}\n        lappend res [r eval $decr_if_gt 1 foo 2]\n        lappend res [r eval $decr_if_gt 1 foo 2]\n        lappend res [r eval $decr_if_gt 1 foo 2]\n        lappend res [r eval $decr_if_gt 1 foo 2]\n        lappend res [r eval $decr_if_gt 1 foo 2]\n        set res\n    } {4 3 2 2 2}\n\n    test {Scripting engine resets PRNG at every script execution} {\n        set rand1 [r eval {return tostring(math.random())} 0]\n        set rand2 [r eval {return tostring(math.random())} 0]\n        assert_equal $rand1 $rand2\n    }\n\n    test {Scripting engine PRNG can be seeded correctly} {\n        set rand1 [r eval {\n            math.randomseed(ARGV[1]); return tostring(math.random())\n        } 0 10]\n        set rand2 [r eval {\n            math.randomseed(ARGV[1]); return tostring(math.random())\n        } 0 10]\n        set rand3 [r eval {\n            math.randomseed(ARGV[1]); return tostring(math.random())\n        } 0 20]\n        assert_equal $rand1 $rand2\n        assert {$rand2 ne $rand3}\n    }\n\n    test {EVAL does not leak in the Lua stack} {\n        r set x 0\n        # Use a non blocking client to speedup the loop.\n        set rd [redis_deferring_client]\n        for {set j 0} {$j < 10000} {incr j} {\n            $rd eval {return redis.call(\"incr\",KEYS[1])} 1 x\n        }\n        for {set j 0} {$j < 10000} {incr j} {\n            $rd read\n        }\n        assert {[s used_memory_lua] < 1024*100}\n        $rd close\n        r get x\n    } {10000}\n\n    test {EVAL processes writes from AOF in read-only slaves} {\n        r flushall\n        r config set appendonly yes\n        r eval {redis.call(\"set\",KEYS[1],\"100\")} 1 foo\n        r eval {redis.call(\"incr\",KEYS[1])} 1 foo\n        r eval {redis.call(\"incr\",KEYS[1])} 1 foo\n        wait_for_condition 50 100 {\n            [s aof_rewrite_in_progress] == 0\n        } else {\n            fail \"AOF rewrite can't complete after CONFIG SET appendonly yes.\"\n        }\n        r config set slave-read-only yes\n        r slaveof 127.0.0.1 0\n        r debug loadaof\n        set res [r get foo]\n        r slaveof no one\n        set res\n    } {102}\n\n    test {We can call scripts rewriting client->argv from Lua} {\n        r del myset\n        r sadd myset a b c\n        r mset a 1 b 2 c 3 d 4\n        assert {[r spop myset] ne {}}\n        assert {[r spop myset 1] ne {}}\n        assert {[r spop myset] ne {}}\n        assert {[r mget a b c d] eq {1 2 3 4}}\n        assert {[r spop myset] eq {}}\n    }\n\n    test {Call Redis command with many args from Lua (issue #1764)} {\n        r eval {\n            local i\n            local x={}\n            redis.call('del','mylist')\n            for i=1,100 do\n                table.insert(x,i)\n            end\n            redis.call('rpush','mylist',unpack(x))\n            return redis.call('lrange','mylist',0,-1)\n        } 0\n    } {1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100}\n\n    test {Number conversion precision test (issue #1118)} {\n        r eval {\n              local value = 9007199254740991\n              redis.call(\"set\",\"foo\",value)\n              return redis.call(\"get\",\"foo\")\n        } 0\n    } {9007199254740991}\n\n    test {String containing number precision test (regression of issue #1118)} {\n        r eval {\n            redis.call(\"set\", \"key\", \"12039611435714932082\")\n            return redis.call(\"get\", \"key\")\n        } 0\n    } {12039611435714932082}\n\n    test {Verify negative arg count is error instead of crash (issue #1842)} {\n        catch { r eval { return \"hello\" } -12 } e\n        set e\n    } {ERR Number of keys can't be negative}\n\n    test {Correct handling of reused argv (issue #1939)} {\n        r eval {\n              for i = 0, 10 do\n                  redis.call('SET', 'a', '1')\n                  redis.call('MGET', 'a', 'b', 'c')\n                  redis.call('EXPIRE', 'a', 0)\n                  redis.call('GET', 'a')\n                  redis.call('MGET', 'a', 'b', 'c')\n              end\n        } 0\n    }\n\n    test {Functions in the Redis namespace are able to report errors} {\n        catch {\n            r eval {\n                  redis.sha1hex()\n            } 0\n        } e\n        set e\n    } {*wrong number*}\n}\n\n# Start a new server since the last test in this stanza will kill the\n# instance at all.\nstart_server {tags {\"scripting\"}} {\n    test {Timedout read-only scripts can be killed by SCRIPT KILL} {\n        set rd [redis_deferring_client]\n        r config set lua-time-limit 10\n        $rd eval {while true do end} 0\n        after 200\n        catch {r ping} e\n        assert_match {BUSY*} $e\n        r script kill\n        after 200 ; # Give some time to Lua to call the hook again...\n        assert_equal [r ping] \"PONG\"\n    }\n\n    test {Timedout script link is still usable after Lua returns} {\n        r config set lua-time-limit 10\n        r eval {for i=1,100000 do redis.call('ping') end return 'ok'} 0\n        r ping\n    } {PONG}\n\n    test {Timedout scripts that modified data can't be killed by SCRIPT KILL} {\n        set rd [redis_deferring_client]\n        r config set lua-time-limit 10\n        $rd eval {redis.call('set',KEYS[1],'y'); while true do end} 1 x\n        after 200\n        catch {r ping} e\n        assert_match {BUSY*} $e\n        catch {r script kill} e\n        assert_match {UNKILLABLE*} $e\n        catch {r ping} e\n        assert_match {BUSY*} $e\n    }\n\n    # Note: keep this test at the end of this server stanza because it\n    # kills the server.\n    test {SHUTDOWN NOSAVE can kill a timedout script anyway} {\n        # The server sould be still unresponding to normal commands.\n        catch {r ping} e\n        assert_match {BUSY*} $e\n        catch {r shutdown nosave}\n        # Make sure the server was killed\n        catch {set rd [redis_deferring_client]} e\n        assert_match {*connection refused*} $e\n    }\n}\n\nforeach cmdrepl {0 1} {\n    start_server {tags {\"scripting repl\"}} {\n        start_server {} {\n            if {$cmdrepl == 1} {\n                set rt \"(commmands replication)\"\n            } else {\n                set rt \"(scripts replication)\"\n                r debug lua-always-replicate-commands 1\n            }\n\n            test \"Before the slave connects we issue two EVAL commands $rt\" {\n                # One with an error, but still executing a command.\n                # SHA is: 67164fc43fa971f76fd1aaeeaf60c1c178d25876\n                catch {\n                    r eval {redis.call('incr',KEYS[1]); redis.call('nonexisting')} 1 x\n                }\n                # One command is correct:\n                # SHA is: 6f5ade10a69975e903c6d07b10ea44c6382381a5\n                r eval {return redis.call('incr',KEYS[1])} 1 x\n            } {2}\n\n            test \"Connect a slave to the master instance $rt\" {\n                r -1 slaveof [srv 0 host] [srv 0 port]\n                wait_for_condition 50 100 {\n                    [s -1 role] eq {slave} &&\n                    [string match {*master_link_status:up*} [r -1 info replication]]\n                } else {\n                    fail \"Can't turn the instance into a slave\"\n                }\n            }\n\n            test \"Now use EVALSHA against the master, with both SHAs $rt\" {\n                # The server should replicate successful and unsuccessful\n                # commands as EVAL instead of EVALSHA.\n                catch {\n                    r evalsha 67164fc43fa971f76fd1aaeeaf60c1c178d25876 1 x\n                }\n                r evalsha 6f5ade10a69975e903c6d07b10ea44c6382381a5 1 x\n            } {4}\n\n            test \"If EVALSHA was replicated as EVAL, 'x' should be '4' $rt\" {\n                wait_for_condition 50 100 {\n                    [r -1 get x] eq {4}\n                } else {\n                    fail \"Expected 4 in x, but value is '[r -1 get x]'\"\n                }\n            }\n\n            test \"Replication of script multiple pushes to list with BLPOP $rt\" {\n                set rd [redis_deferring_client]\n                $rd brpop a 0\n                r eval {\n                    redis.call(\"lpush\",KEYS[1],\"1\");\n                    redis.call(\"lpush\",KEYS[1],\"2\");\n                } 1 a\n                set res [$rd read]\n                $rd close\n                wait_for_condition 50 100 {\n                    [r -1 lrange a 0 -1] eq [r lrange a 0 -1]\n                } else {\n                    fail \"Expected list 'a' in slave and master to be the same, but they are respectively '[r -1 lrange a 0 -1]' and '[r lrange a 0 -1]'\"\n                }\n                set res\n            } {a 1}\n\n            test \"EVALSHA replication when first call is readonly $rt\" {\n                r del x\n                r eval {if tonumber(ARGV[1]) > 0 then redis.call('incr', KEYS[1]) end} 1 x 0\n                r evalsha 6e0e2745aa546d0b50b801a20983b70710aef3ce 1 x 0\n                r evalsha 6e0e2745aa546d0b50b801a20983b70710aef3ce 1 x 1\n                wait_for_condition 50 100 {\n                    [r -1 get x] eq {1}\n                } else {\n                    fail \"Expected 1 in x, but value is '[r -1 get x]'\"\n                }\n            }\n\n            test \"Lua scripts using SELECT are replicated correctly $rt\" {\n                r eval {\n                    redis.call(\"set\",\"foo1\",\"bar1\")\n                    redis.call(\"select\",\"10\")\n                    redis.call(\"incr\",\"x\")\n                    redis.call(\"select\",\"11\")\n                    redis.call(\"incr\",\"z\")\n                } 0\n                r eval {\n                    redis.call(\"set\",\"foo1\",\"bar1\")\n                    redis.call(\"select\",\"10\")\n                    redis.call(\"incr\",\"x\")\n                    redis.call(\"select\",\"11\")\n                    redis.call(\"incr\",\"z\")\n                } 0\n                wait_for_condition 50 100 {\n                    [r -1 debug digest] eq [r debug digest]\n                } else {\n                    fail \"Master-Slave desync after Lua script using SELECT.\"\n                }\n            }\n        }\n    }\n}\n\nstart_server {tags {\"scripting repl\"}} {\n    start_server {overrides {appendonly yes}} {\n        test \"Connect a slave to the master instance\" {\n            r -1 slaveof [srv 0 host] [srv 0 port]\n            wait_for_condition 50 100 {\n                [s -1 role] eq {slave} &&\n                [string match {*master_link_status:up*} [r -1 info replication]]\n            } else {\n                fail \"Can't turn the instance into a slave\"\n            }\n        }\n\n        test \"Redis.replicate_commands() must be issued before any write\" {\n            r eval {\n                redis.call('set','foo','bar');\n                return redis.replicate_commands();\n            } 0\n        } {}\n\n        test \"Redis.replicate_commands() must be issued before any write (2)\" {\n            r eval {\n                return redis.replicate_commands();\n            } 0\n        } {1}\n\n        test \"Redis.set_repl() must be issued after replicate_commands()\" {\n            catch {\n                r eval {\n                    redis.set_repl(redis.REPL_ALL);\n                } 0\n            } e\n            set e\n        } {*only after turning on*}\n\n        test \"Redis.set_repl() don't accept invalid values\" {\n            catch {\n                r eval {\n                    redis.replicate_commands();\n                    redis.set_repl(12345);\n                } 0\n            } e\n            set e\n        } {*Invalid*flags*}\n\n        test \"Test selective replication of certain Redis commands from Lua\" {\n            r del a b c d\n            r eval {\n                redis.replicate_commands();\n                redis.call('set','a','1');\n                redis.set_repl(redis.REPL_NONE);\n                redis.call('set','b','2');\n                redis.set_repl(redis.REPL_AOF);\n                redis.call('set','c','3');\n                redis.set_repl(redis.REPL_ALL);\n                redis.call('set','d','4');\n            } 0\n\n            wait_for_condition 50 100 {\n                [r -1 mget a b c d] eq {1 {} {} 4}\n            } else {\n                fail \"Only a and c should be replicated to slave\"\n            }\n\n            # Master should have everything right now\n            assert {[r mget a b c d] eq {1 2 3 4}}\n\n            # After an AOF reload only a, c and d should exist\n            r debug loadaof\n\n            assert {[r mget a b c d] eq {1 {} 3 4}}\n        }\n\n        test \"PRNG is seeded randomly for command replication\" {\n            set a [\n                r eval {\n                    redis.replicate_commands();\n                    return math.random()*100000;\n                } 0\n            ]\n            set b [\n                r eval {\n                    redis.replicate_commands();\n                    return math.random()*100000;\n                } 0\n            ]\n            assert {$a ne $b}\n        }\n\n        test \"Using side effects is not a problem with command replication\" {\n            r eval {\n                redis.replicate_commands();\n                redis.call('set','time',redis.call('time')[1])\n            } 0\n\n            assert {[r get time] ne {}}\n\n            wait_for_condition 50 100 {\n                [r get time] eq [r -1 get time]\n            } else {\n                fail \"Time key does not match between master and slave\"\n            }\n        }\n    }\n}\n\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/tests/unit/slowlog.tcl",
    "content": "start_server {tags {\"slowlog\"} overrides {slowlog-log-slower-than 1000000}} {\n    test {SLOWLOG - check that it starts with an empty log} {\n        r slowlog len\n    } {0}\n\n    test {SLOWLOG - only logs commands taking more time than specified} {\n        r config set slowlog-log-slower-than 100000\n        r ping\n        assert_equal [r slowlog len] 0\n        r debug sleep 0.2\n        assert_equal [r slowlog len] 1\n    }\n\n    test {SLOWLOG - max entries is correctly handled} {\n        r config set slowlog-log-slower-than 0\n        r config set slowlog-max-len 10\n        for {set i 0} {$i < 100} {incr i} {\n            r ping\n        }\n        r slowlog len\n    } {10}\n\n    test {SLOWLOG - GET optional argument to limit output len works} {\n        llength [r slowlog get 5]\n    } {5}\n\n    test {SLOWLOG - RESET subcommand works} {\n        r config set slowlog-log-slower-than 100000\n        r slowlog reset\n        r slowlog len\n    } {0}\n\n    test {SLOWLOG - logged entry sanity check} {\n        r debug sleep 0.2\n        set e [lindex [r slowlog get] 0]\n        assert_equal [llength $e] 4\n        assert_equal [lindex $e 0] 105\n        assert_equal [expr {[lindex $e 2] > 100000}] 1\n        assert_equal [lindex $e 3] {debug sleep 0.2}\n    }\n\n    test {SLOWLOG - commands with too many arguments are trimmed} {\n        r config set slowlog-log-slower-than 0\n        r slowlog reset\n        r sadd set 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33\n        set e [lindex [r slowlog get] 0]\n        lindex $e 3\n    } {sadd set 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 {... (2 more arguments)}}\n\n    test {SLOWLOG - too long arguments are trimmed} {\n        r config set slowlog-log-slower-than 0\n        r slowlog reset\n        set arg [string repeat A 129]\n        r sadd set foo $arg\n        set e [lindex [r slowlog get] 0]\n        lindex $e 3\n    } {sadd set foo {AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA... (1 more bytes)}}\n\n    test {SLOWLOG - EXEC is not logged, just executed commands} {\n        r config set slowlog-log-slower-than 100000\n        r slowlog reset\n        assert_equal [r slowlog len] 0\n        r multi\n        r debug sleep 0.2\n        r exec\n        assert_equal [r slowlog len] 1\n        set e [lindex [r slowlog get] 0]\n        assert_equal [lindex $e 3] {debug sleep 0.2}\n    }\n}\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/tests/unit/sort.tcl",
    "content": "start_server {\n    tags {\"sort\"}\n    overrides {\n        \"list-max-ziplist-size\" 32\n        \"set-max-intset-entries\" 32\n    }\n} {\n    proc create_random_dataset {num cmd} {\n        set tosort {}\n        set result {}\n        array set seenrand {}\n        r del tosort\n        for {set i 0} {$i < $num} {incr i} {\n            # Make sure all the weights are different because\n            # Redis does not use a stable sort but Tcl does.\n            while 1 {\n                randpath {\n                    set rint [expr int(rand()*1000000)]\n                } {\n                    set rint [expr rand()]\n                }\n                if {![info exists seenrand($rint)]} break\n            }\n            set seenrand($rint) x\n            r $cmd tosort $i\n            r set weight_$i $rint\n            r hset wobj_$i weight $rint\n            lappend tosort [list $i $rint]\n        }\n        set sorted [lsort -index 1 -real $tosort]\n        for {set i 0} {$i < $num} {incr i} {\n            lappend result [lindex $sorted $i 0]\n        }\n        set _ $result\n    }\n\n    foreach {num cmd enc title} {\n        16 lpush quicklist \"Old Ziplist\"\n        1000 lpush quicklist \"Old Linked list\"\n        10000 lpush quicklist \"Old Big Linked list\"\n        16 sadd intset \"Intset\"\n        1000 sadd hashtable \"Hash table\"\n        10000 sadd hashtable \"Big Hash table\"\n    } {\n        set result [create_random_dataset $num $cmd]\n        assert_encoding $enc tosort\n\n        test \"$title: SORT BY key\" {\n            assert_equal $result [r sort tosort BY weight_*]\n        }\n\n        test \"$title: SORT BY key with limit\" {\n            assert_equal [lrange $result 5 9] [r sort tosort BY weight_* LIMIT 5 5]\n        }\n\n        test \"$title: SORT BY hash field\" {\n            assert_equal $result [r sort tosort BY wobj_*->weight]\n        }\n    }\n\n    set result [create_random_dataset 16 lpush]\n    test \"SORT GET #\" {\n        assert_equal [lsort -integer $result] [r sort tosort GET #]\n    }\n\n    test \"SORT GET <const>\" {\n        r del foo\n        set res [r sort tosort GET foo]\n        assert_equal 16 [llength $res]\n        foreach item $res { assert_equal {} $item }\n    }\n\n    test \"SORT GET (key and hash) with sanity check\" {\n        set l1 [r sort tosort GET # GET weight_*]\n        set l2 [r sort tosort GET # GET wobj_*->weight]\n        foreach {id1 w1} $l1 {id2 w2} $l2 {\n            assert_equal $id1 $id2\n            assert_equal $w1 [r get weight_$id1]\n            assert_equal $w2 [r get weight_$id1]\n        }\n    }\n\n    test \"SORT BY key STORE\" {\n        r sort tosort BY weight_* store sort-res\n        assert_equal $result [r lrange sort-res 0 -1]\n        assert_equal 16 [r llen sort-res]\n        assert_encoding quicklist sort-res\n    }\n\n    test \"SORT BY hash field STORE\" {\n        r sort tosort BY wobj_*->weight store sort-res\n        assert_equal $result [r lrange sort-res 0 -1]\n        assert_equal 16 [r llen sort-res]\n        assert_encoding quicklist sort-res\n    }\n\n    test \"SORT extracts STORE correctly\" {\n        r command getkeys sort abc store def\n    } {abc def}\n\n    test \"SORT extracts multiple STORE correctly\" {\n        r command getkeys sort abc store invalid store stillbad store def\n    } {abc def}\n\n    test \"SORT DESC\" {\n        assert_equal [lsort -decreasing -integer $result] [r sort tosort DESC]\n    }\n\n    test \"SORT ALPHA against integer encoded strings\" {\n        r del mylist\n        r lpush mylist 2\n        r lpush mylist 1\n        r lpush mylist 3\n        r lpush mylist 10\n        r sort mylist alpha\n    } {1 10 2 3}\n\n    test \"SORT sorted set\" {\n        r del zset\n        r zadd zset 1 a\n        r zadd zset 5 b\n        r zadd zset 2 c\n        r zadd zset 10 d\n        r zadd zset 3 e\n        r sort zset alpha desc\n    } {e d c b a}\n\n    test \"SORT sorted set BY nosort should retain ordering\" {\n        r del zset\n        r zadd zset 1 a\n        r zadd zset 5 b\n        r zadd zset 2 c\n        r zadd zset 10 d\n        r zadd zset 3 e\n        r multi\n        r sort zset by nosort asc\n        r sort zset by nosort desc\n        r exec\n    } {{a c e b d} {d b e c a}}\n\n    test \"SORT sorted set BY nosort + LIMIT\" {\n        r del zset\n        r zadd zset 1 a\n        r zadd zset 5 b\n        r zadd zset 2 c\n        r zadd zset 10 d\n        r zadd zset 3 e\n        assert_equal [r sort zset by nosort asc limit 0 1] {a}\n        assert_equal [r sort zset by nosort desc limit 0 1] {d}\n        assert_equal [r sort zset by nosort asc limit 0 2] {a c}\n        assert_equal [r sort zset by nosort desc limit 0 2] {d b}\n        assert_equal [r sort zset by nosort limit 5 10] {}\n        assert_equal [r sort zset by nosort limit -10 100] {a c e b d}\n    }\n\n    test \"SORT sorted set BY nosort works as expected from scripts\" {\n        r del zset\n        r zadd zset 1 a\n        r zadd zset 5 b\n        r zadd zset 2 c\n        r zadd zset 10 d\n        r zadd zset 3 e\n        r eval {\n            return {redis.call('sort',KEYS[1],'by','nosort','asc'),\n                    redis.call('sort',KEYS[1],'by','nosort','desc')}\n        } 1 zset\n    } {{a c e b d} {d b e c a}}\n\n    test \"SORT sorted set: +inf and -inf handling\" {\n        r del zset\n        r zadd zset -100 a\n        r zadd zset 200 b\n        r zadd zset -300 c\n        r zadd zset 1000000 d\n        r zadd zset +inf max\n        r zadd zset -inf min\n        r zrange zset 0 -1\n    } {min c a b d max}\n\n    test \"SORT regression for issue #19, sorting floats\" {\n        r flushdb\n        set floats {1.1 5.10 3.10 7.44 2.1 5.75 6.12 0.25 1.15}\n        foreach x $floats {\n            r lpush mylist $x\n        }\n        assert_equal [lsort -real $floats] [r sort mylist]\n    }\n\n    test \"SORT with STORE returns zero if result is empty (github issue 224)\" {\n        r flushdb\n        r sort foo store bar\n    } {0}\n\n    test \"SORT with STORE does not create empty lists (github issue 224)\" {\n        r flushdb\n        r lpush foo bar\n        r sort foo alpha limit 10 10 store zap\n        r exists zap\n    } {0}\n\n    test \"SORT with STORE removes key if result is empty (github issue 227)\" {\n        r flushdb\n        r lpush foo bar\n        r sort emptylist store foo\n        r exists foo\n    } {0}\n\n    test \"SORT with BY <constant> and STORE should still order output\" {\n        r del myset mylist\n        r sadd myset a b c d e f g h i l m n o p q r s t u v z aa aaa azz\n        r sort myset alpha by _ store mylist\n        r lrange mylist 0 -1\n    } {a aa aaa azz b c d e f g h i l m n o p q r s t u v z}\n\n    test \"SORT will complain with numerical sorting and bad doubles (1)\" {\n        r del myset\n        r sadd myset 1 2 3 4 not-a-double\n        set e {}\n        catch {r sort myset} e\n        set e\n    } {*ERR*double*}\n\n    test \"SORT will complain with numerical sorting and bad doubles (2)\" {\n        r del myset\n        r sadd myset 1 2 3 4\n        r mset score:1 10 score:2 20 score:3 30 score:4 not-a-double\n        set e {}\n        catch {r sort myset by score:*} e\n        set e\n    } {*ERR*double*}\n\n    test \"SORT BY sub-sorts lexicographically if score is the same\" {\n        r del myset\n        r sadd myset a b c d e f g h i l m n o p q r s t u v z aa aaa azz\n        foreach ele {a aa aaa azz b c d e f g h i l m n o p q r s t u v z} {\n            set score:$ele 100\n        }\n        r sort myset by score:*\n    } {a aa aaa azz b c d e f g h i l m n o p q r s t u v z}\n\n    test \"SORT GET with pattern ending with just -> does not get hash field\" {\n        r del mylist\n        r lpush mylist a\n        r set x:a-> 100\n        r sort mylist by num get x:*->\n    } {100}\n\n    test \"SORT by nosort retains native order for lists\" {\n        r del testa\n        r lpush testa 2 1 4 3 5\n        r sort testa by nosort\n    } {5 3 4 1 2}\n\n    test \"SORT by nosort plus store retains native order for lists\" {\n        r del testa\n        r lpush testa 2 1 4 3 5\n        r sort testa by nosort store testb\n        r lrange testb 0 -1\n    } {5 3 4 1 2}\n\n    test \"SORT by nosort with limit returns based on original list order\" {\n        r sort testa by nosort limit 0 3 store testb\n        r lrange testb 0 -1\n    } {5 3 4}\n\n    tags {\"slow\"} {\n        set num 100\n        set res [create_random_dataset $num lpush]\n\n        test \"SORT speed, $num element list BY key, 100 times\" {\n            set start [clock clicks -milliseconds]\n            for {set i 0} {$i < 100} {incr i} {\n                set sorted [r sort tosort BY weight_* LIMIT 0 10]\n            }\n            set elapsed [expr [clock clicks -milliseconds]-$start]\n            if {$::verbose} {\n                puts -nonewline \"\\n  Average time to sort: [expr double($elapsed)/100] milliseconds \"\n                flush stdout\n            }\n        }\n\n        test \"SORT speed, $num element list BY hash field, 100 times\" {\n            set start [clock clicks -milliseconds]\n            for {set i 0} {$i < 100} {incr i} {\n                set sorted [r sort tosort BY wobj_*->weight LIMIT 0 10]\n            }\n            set elapsed [expr [clock clicks -milliseconds]-$start]\n            if {$::verbose} {\n                puts -nonewline \"\\n  Average time to sort: [expr double($elapsed)/100] milliseconds \"\n                flush stdout\n            }\n        }\n\n        test \"SORT speed, $num element list directly, 100 times\" {\n            set start [clock clicks -milliseconds]\n            for {set i 0} {$i < 100} {incr i} {\n                set sorted [r sort tosort LIMIT 0 10]\n            }\n            set elapsed [expr [clock clicks -milliseconds]-$start]\n            if {$::verbose} {\n                puts -nonewline \"\\n  Average time to sort: [expr double($elapsed)/100] milliseconds \"\n                flush stdout\n            }\n        }\n\n        test \"SORT speed, $num element list BY <const>, 100 times\" {\n            set start [clock clicks -milliseconds]\n            for {set i 0} {$i < 100} {incr i} {\n                set sorted [r sort tosort BY nokey LIMIT 0 10]\n            }\n            set elapsed [expr [clock clicks -milliseconds]-$start]\n            if {$::verbose} {\n                puts -nonewline \"\\n  Average time to sort: [expr double($elapsed)/100] milliseconds \"\n                flush stdout\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/tests/unit/type/hash.tcl",
    "content": "start_server {tags {\"hash\"}} {\n    test {HSET/HLEN - Small hash creation} {\n        array set smallhash {}\n        for {set i 0} {$i < 8} {incr i} {\n            set key __avoid_collisions__[randstring 0 8 alpha]\n            set val __avoid_collisions__[randstring 0 8 alpha]\n            if {[info exists smallhash($key)]} {\n                incr i -1\n                continue\n            }\n            r hset smallhash $key $val\n            set smallhash($key) $val\n        }\n        list [r hlen smallhash]\n    } {8}\n\n    test {Is the small hash encoded with a ziplist?} {\n        assert_encoding ziplist smallhash\n    }\n\n    test {HSET/HLEN - Big hash creation} {\n        array set bighash {}\n        for {set i 0} {$i < 1024} {incr i} {\n            set key __avoid_collisions__[randstring 0 8 alpha]\n            set val __avoid_collisions__[randstring 0 8 alpha]\n            if {[info exists bighash($key)]} {\n                incr i -1\n                continue\n            }\n            r hset bighash $key $val\n            set bighash($key) $val\n        }\n        list [r hlen bighash]\n    } {1024}\n\n    test {Is the big hash encoded with an hash table?} {\n        assert_encoding hashtable bighash\n    }\n\n    test {HGET against the small hash} {\n        set err {}\n        foreach k [array names smallhash *] {\n            if {$smallhash($k) ne [r hget smallhash $k]} {\n                set err \"$smallhash($k) != [r hget smallhash $k]\"\n                break\n            }\n        }\n        set _ $err\n    } {}\n\n    test {HGET against the big hash} {\n        set err {}\n        foreach k [array names bighash *] {\n            if {$bighash($k) ne [r hget bighash $k]} {\n                set err \"$bighash($k) != [r hget bighash $k]\"\n                break\n            }\n        }\n        set _ $err\n    } {}\n\n    test {HGET against non existing key} {\n        set rv {}\n        lappend rv [r hget smallhash __123123123__]\n        lappend rv [r hget bighash __123123123__]\n        set _ $rv\n    } {{} {}}\n\n    test {HSET in update and insert mode} {\n        set rv {}\n        set k [lindex [array names smallhash *] 0]\n        lappend rv [r hset smallhash $k newval1]\n        set smallhash($k) newval1\n        lappend rv [r hget smallhash $k]\n        lappend rv [r hset smallhash __foobar123__ newval]\n        set k [lindex [array names bighash *] 0]\n        lappend rv [r hset bighash $k newval2]\n        set bighash($k) newval2\n        lappend rv [r hget bighash $k]\n        lappend rv [r hset bighash __foobar123__ newval]\n        lappend rv [r hdel smallhash __foobar123__]\n        lappend rv [r hdel bighash __foobar123__]\n        set _ $rv\n    } {0 newval1 1 0 newval2 1 1 1}\n\n    test {HSETNX target key missing - small hash} {\n        r hsetnx smallhash __123123123__ foo\n        r hget smallhash __123123123__\n    } {foo}\n\n    test {HSETNX target key exists - small hash} {\n        r hsetnx smallhash __123123123__ bar\n        set result [r hget smallhash __123123123__]\n        r hdel smallhash __123123123__\n        set _ $result\n    } {foo}\n\n    test {HSETNX target key missing - big hash} {\n        r hsetnx bighash __123123123__ foo\n        r hget bighash __123123123__\n    } {foo}\n\n    test {HSETNX target key exists - big hash} {\n        r hsetnx bighash __123123123__ bar\n        set result [r hget bighash __123123123__]\n        r hdel bighash __123123123__\n        set _ $result\n    } {foo}\n\n    test {HMSET wrong number of args} {\n        catch {r hmset smallhash key1 val1 key2} err\n        format $err\n    } {*wrong number*}\n\n    test {HMSET - small hash} {\n        set args {}\n        foreach {k v} [array get smallhash] {\n            set newval [randstring 0 8 alpha]\n            set smallhash($k) $newval\n            lappend args $k $newval\n        }\n        r hmset smallhash {*}$args\n    } {OK}\n\n    test {HMSET - big hash} {\n        set args {}\n        foreach {k v} [array get bighash] {\n            set newval [randstring 0 8 alpha]\n            set bighash($k) $newval\n            lappend args $k $newval\n        }\n        r hmset bighash {*}$args\n    } {OK}\n\n    test {HMGET against non existing key and fields} {\n        set rv {}\n        lappend rv [r hmget doesntexist __123123123__ __456456456__]\n        lappend rv [r hmget smallhash __123123123__ __456456456__]\n        lappend rv [r hmget bighash __123123123__ __456456456__]\n        set _ $rv\n    } {{{} {}} {{} {}} {{} {}}}\n\n    test {HMGET against wrong type} {\n        r set wrongtype somevalue\n        assert_error \"*wrong*\" {r hmget wrongtype field1 field2}\n    }\n\n    test {HMGET - small hash} {\n        set keys {}\n        set vals {}\n        foreach {k v} [array get smallhash] {\n            lappend keys $k\n            lappend vals $v\n        }\n        set err {}\n        set result [r hmget smallhash {*}$keys]\n        if {$vals ne $result} {\n            set err \"$vals != $result\"\n            break\n        }\n        set _ $err\n    } {}\n\n    test {HMGET - big hash} {\n        set keys {}\n        set vals {}\n        foreach {k v} [array get bighash] {\n            lappend keys $k\n            lappend vals $v\n        }\n        set err {}\n        set result [r hmget bighash {*}$keys]\n        if {$vals ne $result} {\n            set err \"$vals != $result\"\n            break\n        }\n        set _ $err\n    } {}\n\n    test {HKEYS - small hash} {\n        lsort [r hkeys smallhash]\n    } [lsort [array names smallhash *]]\n\n    test {HKEYS - big hash} {\n        lsort [r hkeys bighash]\n    } [lsort [array names bighash *]]\n\n    test {HVALS - small hash} {\n        set vals {}\n        foreach {k v} [array get smallhash] {\n            lappend vals $v\n        }\n        set _ [lsort $vals]\n    } [lsort [r hvals smallhash]]\n\n    test {HVALS - big hash} {\n        set vals {}\n        foreach {k v} [array get bighash] {\n            lappend vals $v\n        }\n        set _ [lsort $vals]\n    } [lsort [r hvals bighash]]\n\n    test {HGETALL - small hash} {\n        lsort [r hgetall smallhash]\n    } [lsort [array get smallhash]]\n\n    test {HGETALL - big hash} {\n        lsort [r hgetall bighash]\n    } [lsort [array get bighash]]\n\n    test {HDEL and return value} {\n        set rv {}\n        lappend rv [r hdel smallhash nokey]\n        lappend rv [r hdel bighash nokey]\n        set k [lindex [array names smallhash *] 0]\n        lappend rv [r hdel smallhash $k]\n        lappend rv [r hdel smallhash $k]\n        lappend rv [r hget smallhash $k]\n        unset smallhash($k)\n        set k [lindex [array names bighash *] 0]\n        lappend rv [r hdel bighash $k]\n        lappend rv [r hdel bighash $k]\n        lappend rv [r hget bighash $k]\n        unset bighash($k)\n        set _ $rv\n    } {0 0 1 0 {} 1 0 {}}\n\n    test {HDEL - more than a single value} {\n        set rv {}\n        r del myhash\n        r hmset myhash a 1 b 2 c 3\n        assert_equal 0 [r hdel myhash x y]\n        assert_equal 2 [r hdel myhash a c f]\n        r hgetall myhash\n    } {b 2}\n\n    test {HDEL - hash becomes empty before deleting all specified fields} {\n        r del myhash\n        r hmset myhash a 1 b 2 c 3\n        assert_equal 3 [r hdel myhash a b c d e]\n        assert_equal 0 [r exists myhash]\n    }\n\n    test {HEXISTS} {\n        set rv {}\n        set k [lindex [array names smallhash *] 0]\n        lappend rv [r hexists smallhash $k]\n        lappend rv [r hexists smallhash nokey]\n        set k [lindex [array names bighash *] 0]\n        lappend rv [r hexists bighash $k]\n        lappend rv [r hexists bighash nokey]\n    } {1 0 1 0}\n\n    test {Is a ziplist encoded Hash promoted on big payload?} {\n        r hset smallhash foo [string repeat a 1024]\n        r debug object smallhash\n    } {*hashtable*}\n\n    test {HINCRBY against non existing database key} {\n        r del htest\n        list [r hincrby htest foo 2]\n    } {2}\n\n    test {HINCRBY against non existing hash key} {\n        set rv {}\n        r hdel smallhash tmp\n        r hdel bighash tmp\n        lappend rv [r hincrby smallhash tmp 2]\n        lappend rv [r hget smallhash tmp]\n        lappend rv [r hincrby bighash tmp 2]\n        lappend rv [r hget bighash tmp]\n    } {2 2 2 2}\n\n    test {HINCRBY against hash key created by hincrby itself} {\n        set rv {}\n        lappend rv [r hincrby smallhash tmp 3]\n        lappend rv [r hget smallhash tmp]\n        lappend rv [r hincrby bighash tmp 3]\n        lappend rv [r hget bighash tmp]\n    } {5 5 5 5}\n\n    test {HINCRBY against hash key originally set with HSET} {\n        r hset smallhash tmp 100\n        r hset bighash tmp 100\n        list [r hincrby smallhash tmp 2] [r hincrby bighash tmp 2]\n    } {102 102}\n\n    test {HINCRBY over 32bit value} {\n        r hset smallhash tmp 17179869184\n        r hset bighash tmp 17179869184\n        list [r hincrby smallhash tmp 1] [r hincrby bighash tmp 1]\n    } {17179869185 17179869185}\n\n    test {HINCRBY over 32bit value with over 32bit increment} {\n        r hset smallhash tmp 17179869184\n        r hset bighash tmp 17179869184\n        list [r hincrby smallhash tmp 17179869184] [r hincrby bighash tmp 17179869184]\n    } {34359738368 34359738368}\n\n    test {HINCRBY fails against hash value with spaces (left)} {\n        r hset smallhash str \" 11\"\n        r hset bighash str \" 11\"\n        catch {r hincrby smallhash str 1} smallerr\n        catch {r hincrby smallhash str 1} bigerr\n        set rv {}\n        lappend rv [string match \"ERR*not an integer*\" $smallerr]\n        lappend rv [string match \"ERR*not an integer*\" $bigerr]\n    } {1 1}\n\n    test {HINCRBY fails against hash value with spaces (right)} {\n        r hset smallhash str \"11 \"\n        r hset bighash str \"11 \"\n        catch {r hincrby smallhash str 1} smallerr\n        catch {r hincrby smallhash str 1} bigerr\n        set rv {}\n        lappend rv [string match \"ERR*not an integer*\" $smallerr]\n        lappend rv [string match \"ERR*not an integer*\" $bigerr]\n    } {1 1}\n\n    test {HINCRBY can detect overflows} {\n        set e {}\n        r hset hash n -9223372036854775484\n        assert {[r hincrby hash n -1] == -9223372036854775485}\n        catch {r hincrby hash n -10000} e\n        set e\n    } {*overflow*}\n\n    test {HINCRBYFLOAT against non existing database key} {\n        r del htest\n        list [r hincrbyfloat htest foo 2.5]\n    } {2.5}\n\n    test {HINCRBYFLOAT against non existing hash key} {\n        set rv {}\n        r hdel smallhash tmp\n        r hdel bighash tmp\n        lappend rv [roundFloat [r hincrbyfloat smallhash tmp 2.5]]\n        lappend rv [roundFloat [r hget smallhash tmp]]\n        lappend rv [roundFloat [r hincrbyfloat bighash tmp 2.5]]\n        lappend rv [roundFloat [r hget bighash tmp]]\n    } {2.5 2.5 2.5 2.5}\n\n    test {HINCRBYFLOAT against hash key created by hincrby itself} {\n        set rv {}\n        lappend rv [roundFloat [r hincrbyfloat smallhash tmp 3.5]]\n        lappend rv [roundFloat [r hget smallhash tmp]]\n        lappend rv [roundFloat [r hincrbyfloat bighash tmp 3.5]]\n        lappend rv [roundFloat [r hget bighash tmp]]\n    } {6 6 6 6}\n\n    test {HINCRBYFLOAT against hash key originally set with HSET} {\n        r hset smallhash tmp 100\n        r hset bighash tmp 100\n        list [roundFloat [r hincrbyfloat smallhash tmp 2.5]] \\\n             [roundFloat [r hincrbyfloat bighash tmp 2.5]]\n    } {102.5 102.5}\n\n    test {HINCRBYFLOAT over 32bit value} {\n        r hset smallhash tmp 17179869184\n        r hset bighash tmp 17179869184\n        list [r hincrbyfloat smallhash tmp 1] \\\n             [r hincrbyfloat bighash tmp 1]\n    } {17179869185 17179869185}\n\n    test {HINCRBYFLOAT over 32bit value with over 32bit increment} {\n        r hset smallhash tmp 17179869184\n        r hset bighash tmp 17179869184\n        list [r hincrbyfloat smallhash tmp 17179869184] \\\n             [r hincrbyfloat bighash tmp 17179869184]\n    } {34359738368 34359738368}\n\n    test {HINCRBYFLOAT fails against hash value with spaces (left)} {\n        r hset smallhash str \" 11\"\n        r hset bighash str \" 11\"\n        catch {r hincrbyfloat smallhash str 1} smallerr\n        catch {r hincrbyfloat smallhash str 1} bigerr\n        set rv {}\n        lappend rv [string match \"ERR*not*float*\" $smallerr]\n        lappend rv [string match \"ERR*not*float*\" $bigerr]\n    } {1 1}\n\n    test {HINCRBYFLOAT fails against hash value with spaces (right)} {\n        r hset smallhash str \"11 \"\n        r hset bighash str \"11 \"\n        catch {r hincrbyfloat smallhash str 1} smallerr\n        catch {r hincrbyfloat smallhash str 1} bigerr\n        set rv {}\n        lappend rv [string match \"ERR*not*float*\" $smallerr]\n        lappend rv [string match \"ERR*not*float*\" $bigerr]\n    } {1 1}\n\n    test {HSTRLEN against the small hash} {\n        set err {}\n        foreach k [array names smallhash *] {\n            if {[string length $smallhash($k)] ne [r hstrlen smallhash $k]} {\n                set err \"[string length $smallhash($k)] != [r hstrlen smallhash $k]\"\n                break\n            }\n        }\n        set _ $err\n    } {}\n\n    test {HSTRLEN against the big hash} {\n        set err {}\n        foreach k [array names bighash *] {\n            if {[string length $bighash($k)] ne [r hstrlen bighash $k]} {\n                set err \"[string length $bighash($k)] != [r hstrlen bighash $k]\"\n                puts \"HSTRLEN and logical length mismatch:\"\n                puts \"key: $k\"\n                puts \"Logical content: $bighash($k)\"\n                puts \"Server  content: [r hget bighash $k]\"\n            }\n        }\n        set _ $err\n    } {}\n\n    test {HSTRLEN against non existing field} {\n        set rv {}\n        lappend rv [r hstrlen smallhash __123123123__]\n        lappend rv [r hstrlen bighash __123123123__]\n        set _ $rv\n    } {0 0}\n\n    test {HSTRLEN corner cases} {\n        set vals {\n            -9223372036854775808 9223372036854775807 9223372036854775808\n            {} 0 -1 x\n        }\n        foreach v $vals {\n            r hmset smallhash field $v\n            r hmset bighash field $v\n            set len1 [string length $v]\n            set len2 [r hstrlen smallhash field]\n            set len3 [r hstrlen bighash field]\n            assert {$len1 == $len2}\n            assert {$len2 == $len3}\n        }\n    }\n\n    test {Hash ziplist regression test for large keys} {\n        r hset hash kkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkk a\n        r hset hash kkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkk b\n        r hget hash kkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkk\n    } {b}\n\n    foreach size {10 512} {\n        test \"Hash fuzzing #1 - $size fields\" {\n            for {set times 0} {$times < 10} {incr times} {\n                catch {unset hash}\n                array set hash {}\n                r del hash\n\n                # Create\n                for {set j 0} {$j < $size} {incr j} {\n                    set field [randomValue]\n                    set value [randomValue]\n                    r hset hash $field $value\n                    set hash($field) $value\n                }\n\n                # Verify\n                foreach {k v} [array get hash] {\n                    assert_equal $v [r hget hash $k]\n                }\n                assert_equal [array size hash] [r hlen hash]\n            }\n        }\n\n        test \"Hash fuzzing #2 - $size fields\" {\n            for {set times 0} {$times < 10} {incr times} {\n                catch {unset hash}\n                array set hash {}\n                r del hash\n\n                # Create\n                for {set j 0} {$j < $size} {incr j} {\n                    randpath {\n                        set field [randomValue]\n                        set value [randomValue]\n                        r hset hash $field $value\n                        set hash($field) $value\n                    } {\n                        set field [randomSignedInt 512]\n                        set value [randomSignedInt 512]\n                        r hset hash $field $value\n                        set hash($field) $value\n                    } {\n                        randpath {\n                            set field [randomValue]\n                        } {\n                            set field [randomSignedInt 512]\n                        }\n                        r hdel hash $field\n                        unset -nocomplain hash($field)\n                    }\n                }\n\n                # Verify\n                foreach {k v} [array get hash] {\n                    assert_equal $v [r hget hash $k]\n                }\n                assert_equal [array size hash] [r hlen hash]\n            }\n        }\n    }\n\n    test {Stress test the hash ziplist -> hashtable encoding conversion} {\n        r config set hash-max-ziplist-entries 32\n        for {set j 0} {$j < 100} {incr j} {\n            r del myhash\n            for {set i 0} {$i < 64} {incr i} {\n                r hset myhash [randomValue] [randomValue]\n            }\n            assert {[r object encoding myhash] eq {hashtable}}\n        }\n    }\n}\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/tests/unit/type/incr.tcl",
    "content": "start_server {tags {\"incr\"}} {\n    test {INCR against non existing key} {\n        set res {}\n        append res [r incr novar]\n        append res [r get novar]\n    } {11}\n\n    test {INCR against key created by incr itself} {\n        r incr novar\n    } {2}\n\n    test {INCR against key originally set with SET} {\n        r set novar 100\n        r incr novar\n    } {101}\n\n    test {INCR over 32bit value} {\n        r set novar 17179869184\n        r incr novar\n    } {17179869185}\n\n    test {INCRBY over 32bit value with over 32bit increment} {\n        r set novar 17179869184\n        r incrby novar 17179869184\n    } {34359738368}\n\n    test {INCR fails against key with spaces (left)} {\n        r set novar \"    11\"\n        catch {r incr novar} err\n        format $err\n    } {ERR*}\n\n    test {INCR fails against key with spaces (right)} {\n        r set novar \"11    \"\n        catch {r incr novar} err\n        format $err\n    } {ERR*}\n\n    test {INCR fails against key with spaces (both)} {\n        r set novar \"    11    \"\n        catch {r incr novar} err\n        format $err\n    } {ERR*}\n\n    test {INCR fails against a key holding a list} {\n        r rpush mylist 1\n        catch {r incr mylist} err\n        r rpop mylist\n        format $err\n    } {WRONGTYPE*}\n\n    test {DECRBY over 32bit value with over 32bit increment, negative res} {\n        r set novar 17179869184\n        r decrby novar 17179869185\n    } {-1}\n\n    test {INCR uses shared objects in the 0-9999 range} {\n        r set foo -1\n        r incr foo\n        assert {[r object refcount foo] > 1}\n        r set foo 9998\n        r incr foo\n        assert {[r object refcount foo] > 1}\n        r incr foo\n        assert {[r object refcount foo] == 1}\n    }\n\n    test {INCR can modify objects in-place} {\n        r set foo 20000\n        r incr foo\n        assert {[r object refcount foo] == 1}\n        set old [lindex [split [r debug object foo]] 1]\n        r incr foo\n        set new [lindex [split [r debug object foo]] 1]\n        assert {[string range $old 0 2] eq \"at:\"}\n        assert {[string range $new 0 2] eq \"at:\"}\n        assert {$old eq $new}\n    }\n\n    test {INCRBYFLOAT against non existing key} {\n        r del novar\n        list    [roundFloat [r incrbyfloat novar 1]] \\\n                [roundFloat [r get novar]] \\\n                [roundFloat [r incrbyfloat novar 0.25]] \\\n                [roundFloat [r get novar]]\n    } {1 1 1.25 1.25}\n\n    test {INCRBYFLOAT against key originally set with SET} {\n        r set novar 1.5\n        roundFloat [r incrbyfloat novar 1.5]\n    } {3}\n\n    test {INCRBYFLOAT over 32bit value} {\n        r set novar 17179869184\n        r incrbyfloat novar 1.5\n    } {17179869185.5}\n\n    test {INCRBYFLOAT over 32bit value with over 32bit increment} {\n        r set novar 17179869184\n        r incrbyfloat novar 17179869184\n    } {34359738368}\n\n    test {INCRBYFLOAT fails against key with spaces (left)} {\n        set err {}\n        r set novar \"    11\"\n        catch {r incrbyfloat novar 1.0} err\n        format $err\n    } {ERR*valid*}\n\n    test {INCRBYFLOAT fails against key with spaces (right)} {\n        set err {}\n        r set novar \"11    \"\n        catch {r incrbyfloat novar 1.0} err\n        format $err\n    } {ERR*valid*}\n\n    test {INCRBYFLOAT fails against key with spaces (both)} {\n        set err {}\n        r set novar \" 11 \"\n        catch {r incrbyfloat novar 1.0} err\n        format $err\n    } {ERR*valid*}\n\n    test {INCRBYFLOAT fails against a key holding a list} {\n        r del mylist\n        set err {}\n        r rpush mylist 1\n        catch {r incrbyfloat mylist 1.0} err\n        r del mylist\n        format $err\n    } {WRONGTYPE*}\n\n    test {INCRBYFLOAT does not allow NaN or Infinity} {\n        r set foo 0\n        set err {}\n        catch {r incrbyfloat foo +inf} err\n        set err\n        # p.s. no way I can force NaN to test it from the API because\n        # there is no way to increment / decrement by infinity nor to\n        # perform divisions.\n    } {ERR*would produce*}\n\n    test {INCRBYFLOAT decrement} {\n        r set foo 1\n        roundFloat [r incrbyfloat foo -1.1]\n    } {-0.1}\n}\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/tests/unit/type/list-2.tcl",
    "content": "start_server {\n    tags {\"list\"}\n    overrides {\n        \"list-max-ziplist-size\" 4\n    }\n} {\n    source \"tests/unit/type/list-common.tcl\"\n\n    foreach {type large} [array get largevalue] {\n        tags {\"slow\"} {\n            test \"LTRIM stress testing - $type\" {\n                set mylist {}\n                set startlen 32\n                r del mylist\n\n                # Start with the large value to ensure the\n                # right encoding is used.\n                r rpush mylist $large\n                lappend mylist $large\n\n                for {set i 0} {$i < $startlen} {incr i} {\n                    set str [randomInt 9223372036854775807]\n                    r rpush mylist $str\n                    lappend mylist $str\n                }\n\n                for {set i 0} {$i < 1000} {incr i} {\n                    set min [expr {int(rand()*$startlen)}]\n                    set max [expr {$min+int(rand()*$startlen)}]\n                    set before_len [llength $mylist]\n                    set before_len_r [r llen mylist]\n                    set mylist [lrange $mylist $min $max]\n                    r ltrim mylist $min $max\n                    assert_equal $mylist [r lrange mylist 0 -1] \"failed trim\"\n\n                    set starting [r llen mylist]\n                    for {set j [r llen mylist]} {$j < $startlen} {incr j} {\n                        set str [randomInt 9223372036854775807]\n                        r rpush mylist $str\n                        lappend mylist $str\n                        assert_equal $mylist [r lrange mylist 0 -1] \"failed append match\"\n                    }\n                }\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/tests/unit/type/list-3.tcl",
    "content": "start_server {\n    tags {list ziplist}\n    overrides {\n        \"list-max-ziplist-size\" 16\n    }\n} {\n    test {Explicit regression for a list bug} {\n        set mylist {49376042582 {BkG2o\\pIC]4YYJa9cJ4GWZalG[4tin;1D2whSkCOW`mX;SFXGyS8sedcff3fQI^tgPCC@^Nu1J6o]meM@Lko]t_jRyo<xSJ1oObDYd`ppZuW6P@fS278YaOx=s6lvdFlMbP0[SbkI^Kr\\HBXtuFaA^mDx:yzS4a[skiiPWhT<nNfAf=aQVfclcuwDrfe;iVuKdNvB9kbfq>tK?tH[\\EvWqS]b`o2OCtjg:?nUTwdjpcUm]y:pg5q24q7LlCOwQE^}}\n        r del l\n        r rpush l [lindex $mylist 0]\n        r rpush l [lindex $mylist 1]\n        assert_equal [r lindex l 0] [lindex $mylist 0]\n        assert_equal [r lindex l 1] [lindex $mylist 1]\n    }\n\n    test {Regression for quicklist #3343 bug} {\n        r del mylist\n        r lpush mylist 401\n        r lpush mylist 392\n        r rpush mylist [string repeat x 5105]\"799\"\n        r lset mylist -1 [string repeat x 1014]\"702\"\n        r lpop mylist\n        r lset mylist -1 [string repeat x 4149]\"852\"\n        r linsert mylist before 401 [string repeat x 9927]\"12\"\n        r lrange mylist 0 -1\n        r ping ; # It's enough if the server is still alive\n    } {PONG}\n\n    test {Stress tester for #3343-alike bugs} {\n        r del key\n        for {set j 0} {$j < 10000} {incr j} {\n            set op [randomInt 6]\n            set small_signed_count [expr 5-[randomInt 10]]\n            if {[randomInt 2] == 0} {\n                set ele [randomInt 1000]\n            } else {\n                set ele [string repeat x [randomInt 10000]][randomInt 1000]\n            }\n            switch $op {\n                0 {r lpush key $ele}\n                1 {r rpush key $ele}\n                2 {r lpop key}\n                3 {r rpop key}\n                4 {\n                    catch {r lset key $small_signed_count $ele}\n                }\n                5 {\n                    set otherele [randomInt 1000]\n                    if {[randomInt 2] == 0} {\n                        set where before\n                    } else {\n                        set where after\n                    }\n                    r linsert key $where $otherele $ele\n                }\n            }\n        }\n    }\n\n    tags {slow} {\n        test {ziplist implementation: value encoding and backlink} {\n            if {$::accurate} {set iterations 100} else {set iterations 10}\n            for {set j 0} {$j < $iterations} {incr j} {\n                r del l\n                set l {}\n                for {set i 0} {$i < 200} {incr i} {\n                    randpath {\n                        set data [string repeat x [randomInt 100000]]\n                    } {\n                        set data [randomInt 65536]\n                    } {\n                        set data [randomInt 4294967296]\n                    } {\n                        set data [randomInt 18446744073709551616]\n                    } {\n                        set data -[randomInt 65536]\n                        if {$data eq {-0}} {set data 0}\n                    } {\n                        set data -[randomInt 4294967296]\n                        if {$data eq {-0}} {set data 0}\n                    } {\n                        set data -[randomInt 18446744073709551616]\n                        if {$data eq {-0}} {set data 0}\n                    }\n                    lappend l $data\n                    r rpush l $data\n                }\n                assert_equal [llength $l] [r llen l]\n                # Traverse backward\n                for {set i 199} {$i >= 0} {incr i -1} {\n                    if {[lindex $l $i] ne [r lindex l $i]} {\n                        assert_equal [lindex $l $i] [r lindex l $i]\n                    }\n                }\n            }\n        }\n\n        test {ziplist implementation: encoding stress testing} {\n            for {set j 0} {$j < 200} {incr j} {\n                r del l\n                set l {}\n                set len [randomInt 400]\n                for {set i 0} {$i < $len} {incr i} {\n                    set rv [randomValue]\n                    randpath {\n                        lappend l $rv\n                        r rpush l $rv\n                    } {\n                        set l [concat [list $rv] $l]\n                        r lpush l $rv\n                    }\n                }\n                assert_equal [llength $l] [r llen l]\n                for {set i 0} {$i < $len} {incr i} {\n                    if {[lindex $l $i] ne [r lindex l $i]} {\n                        assert_equal [lindex $l $i] [r lindex l $i]\n                    }\n                }\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/tests/unit/type/list-common.tcl",
    "content": "# We need a value larger than list-max-ziplist-value to make sure\n# the list has the right encoding when it is swapped in again.\narray set largevalue {}\nset largevalue(ziplist) \"hello\"\nset largevalue(linkedlist) [string repeat \"hello\" 4]\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/tests/unit/type/list.tcl",
    "content": "start_server {\n    tags {\"list\"}\n    overrides {\n        \"list-max-ziplist-size\" 5\n    }\n} {\n    source \"tests/unit/type/list-common.tcl\"\n\n    test {LPUSH, RPUSH, LLENGTH, LINDEX, LPOP - ziplist} {\n        # first lpush then rpush\n        assert_equal 1 [r lpush myziplist1 aa]\n        assert_equal 2 [r rpush myziplist1 bb]\n        assert_equal 3 [r rpush myziplist1 cc]\n        assert_equal 3 [r llen myziplist1]\n        assert_equal aa [r lindex myziplist1 0]\n        assert_equal bb [r lindex myziplist1 1]\n        assert_equal cc [r lindex myziplist1 2]\n        assert_equal {} [r lindex myziplist2 3]\n        assert_equal cc [r rpop myziplist1]\n        assert_equal aa [r lpop myziplist1]\n        assert_encoding quicklist myziplist1\n\n        # first rpush then lpush\n        assert_equal 1 [r rpush myziplist2 a]\n        assert_equal 2 [r lpush myziplist2 b]\n        assert_equal 3 [r lpush myziplist2 c]\n        assert_equal 3 [r llen myziplist2]\n        assert_equal c [r lindex myziplist2 0]\n        assert_equal b [r lindex myziplist2 1]\n        assert_equal a [r lindex myziplist2 2]\n        assert_equal {} [r lindex myziplist2 3]\n        assert_equal a [r rpop myziplist2]\n        assert_equal c [r lpop myziplist2]\n        assert_encoding quicklist myziplist2\n    }\n\n    test {LPUSH, RPUSH, LLENGTH, LINDEX, LPOP - regular list} {\n        # first lpush then rpush\n        assert_equal 1 [r lpush mylist1 $largevalue(linkedlist)]\n        assert_encoding quicklist mylist1\n        assert_equal 2 [r rpush mylist1 b]\n        assert_equal 3 [r rpush mylist1 c]\n        assert_equal 3 [r llen mylist1]\n        assert_equal $largevalue(linkedlist) [r lindex mylist1 0]\n        assert_equal b [r lindex mylist1 1]\n        assert_equal c [r lindex mylist1 2]\n        assert_equal {} [r lindex mylist1 3]\n        assert_equal c [r rpop mylist1]\n        assert_equal $largevalue(linkedlist) [r lpop mylist1]\n\n        # first rpush then lpush\n        assert_equal 1 [r rpush mylist2 $largevalue(linkedlist)]\n        assert_encoding quicklist mylist2\n        assert_equal 2 [r lpush mylist2 b]\n        assert_equal 3 [r lpush mylist2 c]\n        assert_equal 3 [r llen mylist2]\n        assert_equal c [r lindex mylist2 0]\n        assert_equal b [r lindex mylist2 1]\n        assert_equal $largevalue(linkedlist) [r lindex mylist2 2]\n        assert_equal {} [r lindex mylist2 3]\n        assert_equal $largevalue(linkedlist) [r rpop mylist2]\n        assert_equal c [r lpop mylist2]\n    }\n\n    test {R/LPOP against empty list} {\n        r lpop non-existing-list\n    } {}\n\n    test {Variadic RPUSH/LPUSH} {\n        r del mylist\n        assert_equal 4 [r lpush mylist a b c d]\n        assert_equal 8 [r rpush mylist 0 1 2 3]\n        assert_equal {d c b a 0 1 2 3} [r lrange mylist 0 -1]\n    }\n\n    test {DEL a list} {\n        assert_equal 1 [r del mylist2]\n        assert_equal 0 [r exists mylist2]\n        assert_equal 0 [r llen mylist2]\n    }\n\n    proc create_list {key entries} {\n        r del $key\n        foreach entry $entries { r rpush $key $entry }\n        assert_encoding quicklist $key\n    }\n\n    foreach {type large} [array get largevalue] {\n        test \"BLPOP, BRPOP: single existing list - $type\" {\n            set rd [redis_deferring_client]\n            create_list blist \"a b $large c d\"\n\n            $rd blpop blist 1\n            assert_equal {blist a} [$rd read]\n            $rd brpop blist 1\n            assert_equal {blist d} [$rd read]\n\n            $rd blpop blist 1\n            assert_equal {blist b} [$rd read]\n            $rd brpop blist 1\n            assert_equal {blist c} [$rd read]\n        }\n\n        test \"BLPOP, BRPOP: multiple existing lists - $type\" {\n            set rd [redis_deferring_client]\n            create_list blist1 \"a $large c\"\n            create_list blist2 \"d $large f\"\n\n            $rd blpop blist1 blist2 1\n            assert_equal {blist1 a} [$rd read]\n            $rd brpop blist1 blist2 1\n            assert_equal {blist1 c} [$rd read]\n            assert_equal 1 [r llen blist1]\n            assert_equal 3 [r llen blist2]\n\n            $rd blpop blist2 blist1 1\n            assert_equal {blist2 d} [$rd read]\n            $rd brpop blist2 blist1 1\n            assert_equal {blist2 f} [$rd read]\n            assert_equal 1 [r llen blist1]\n            assert_equal 1 [r llen blist2]\n        }\n\n        test \"BLPOP, BRPOP: second list has an entry - $type\" {\n            set rd [redis_deferring_client]\n            r del blist1\n            create_list blist2 \"d $large f\"\n\n            $rd blpop blist1 blist2 1\n            assert_equal {blist2 d} [$rd read]\n            $rd brpop blist1 blist2 1\n            assert_equal {blist2 f} [$rd read]\n            assert_equal 0 [r llen blist1]\n            assert_equal 1 [r llen blist2]\n        }\n\n        test \"BRPOPLPUSH - $type\" {\n            r del target\n\n            set rd [redis_deferring_client]\n            create_list blist \"a b $large c d\"\n\n            $rd brpoplpush blist target 1\n            assert_equal d [$rd read]\n\n            assert_equal d [r rpop target]\n            assert_equal \"a b $large c\" [r lrange blist 0 -1]\n        }\n    }\n\n    test \"BLPOP, LPUSH + DEL should not awake blocked client\" {\n        set rd [redis_deferring_client]\n        r del list\n\n        $rd blpop list 0\n        r multi\n        r lpush list a\n        r del list\n        r exec\n        r del list\n        r lpush list b\n        $rd read\n    } {list b}\n\n    test \"BLPOP, LPUSH + DEL + SET should not awake blocked client\" {\n        set rd [redis_deferring_client]\n        r del list\n\n        $rd blpop list 0\n        r multi\n        r lpush list a\n        r del list\n        r set list foo\n        r exec\n        r del list\n        r lpush list b\n        $rd read\n    } {list b}\n\n    test \"BLPOP with same key multiple times should work (issue #801)\" {\n        set rd [redis_deferring_client]\n        r del list1 list2\n\n        # Data arriving after the BLPOP.\n        $rd blpop list1 list2 list2 list1 0\n        r lpush list1 a\n        assert_equal [$rd read] {list1 a}\n        $rd blpop list1 list2 list2 list1 0\n        r lpush list2 b\n        assert_equal [$rd read] {list2 b}\n\n        # Data already there.\n        r lpush list1 a\n        r lpush list2 b\n        $rd blpop list1 list2 list2 list1 0\n        assert_equal [$rd read] {list1 a}\n        $rd blpop list1 list2 list2 list1 0\n        assert_equal [$rd read] {list2 b}\n    }\n\n    test \"MULTI/EXEC is isolated from the point of view of BLPOP\" {\n        set rd [redis_deferring_client]\n        r del list\n        $rd blpop list 0\n        r multi\n        r lpush list a\n        r lpush list b\n        r lpush list c\n        r exec\n        $rd read\n    } {list c}\n\n    test \"BLPOP with variadic LPUSH\" {\n        set rd [redis_deferring_client]\n        r del blist target\n        if {$::valgrind} {after 100}\n        $rd blpop blist 0\n        if {$::valgrind} {after 100}\n        assert_equal 2 [r lpush blist foo bar]\n        if {$::valgrind} {after 100}\n        assert_equal {blist bar} [$rd read]\n        assert_equal foo [lindex [r lrange blist 0 -1] 0]\n    }\n\n    test \"BRPOPLPUSH with zero timeout should block indefinitely\" {\n        set rd [redis_deferring_client]\n        r del blist target\n        $rd brpoplpush blist target 0\n        after 1000\n        r rpush blist foo\n        assert_equal foo [$rd read]\n        assert_equal {foo} [r lrange target 0 -1]\n    }\n\n    test \"BRPOPLPUSH with a client BLPOPing the target list\" {\n        set rd [redis_deferring_client]\n        set rd2 [redis_deferring_client]\n        r del blist target\n        $rd2 blpop target 0\n        $rd brpoplpush blist target 0\n        after 1000\n        r rpush blist foo\n        assert_equal foo [$rd read]\n        assert_equal {target foo} [$rd2 read]\n        assert_equal 0 [r exists target]\n    }\n\n    test \"BRPOPLPUSH with wrong source type\" {\n        set rd [redis_deferring_client]\n        r del blist target\n        r set blist nolist\n        $rd brpoplpush blist target 1\n        assert_error \"WRONGTYPE*\" {$rd read}\n    }\n\n    test \"BRPOPLPUSH with wrong destination type\" {\n        set rd [redis_deferring_client]\n        r del blist target\n        r set target nolist\n        r lpush blist foo\n        $rd brpoplpush blist target 1\n        assert_error \"WRONGTYPE*\" {$rd read}\n\n        set rd [redis_deferring_client]\n        r del blist target\n        r set target nolist\n        $rd brpoplpush blist target 0\n        after 1000\n        r rpush blist foo\n        assert_error \"WRONGTYPE*\" {$rd read}\n        assert_equal {foo} [r lrange blist 0 -1]\n    }\n\n    test \"BRPOPLPUSH maintains order of elements after failure\" {\n        set rd [redis_deferring_client]\n        r del blist target\n        r set target nolist\n        $rd brpoplpush blist target 0\n        r rpush blist a b c\n        assert_error \"WRONGTYPE*\" {$rd read}\n        r lrange blist 0 -1\n    } {a b c}\n\n    test \"BRPOPLPUSH with multiple blocked clients\" {\n        set rd1 [redis_deferring_client]\n        set rd2 [redis_deferring_client]\n        r del blist target1 target2\n        r set target1 nolist\n        $rd1 brpoplpush blist target1 0\n        $rd2 brpoplpush blist target2 0\n        r lpush blist foo\n\n        assert_error \"WRONGTYPE*\" {$rd1 read}\n        assert_equal {foo} [$rd2 read]\n        assert_equal {foo} [r lrange target2 0 -1]\n    }\n\n    test \"Linked BRPOPLPUSH\" {\n      set rd1 [redis_deferring_client]\n      set rd2 [redis_deferring_client]\n\n      r del list1 list2 list3\n\n      $rd1 brpoplpush list1 list2 0\n      $rd2 brpoplpush list2 list3 0\n\n      r rpush list1 foo\n\n      assert_equal {} [r lrange list1 0 -1]\n      assert_equal {} [r lrange list2 0 -1]\n      assert_equal {foo} [r lrange list3 0 -1]\n    }\n\n    test \"Circular BRPOPLPUSH\" {\n      set rd1 [redis_deferring_client]\n      set rd2 [redis_deferring_client]\n\n      r del list1 list2\n\n      $rd1 brpoplpush list1 list2 0\n      $rd2 brpoplpush list2 list1 0\n\n      r rpush list1 foo\n\n      assert_equal {foo} [r lrange list1 0 -1]\n      assert_equal {} [r lrange list2 0 -1]\n    }\n\n    test \"Self-referential BRPOPLPUSH\" {\n      set rd [redis_deferring_client]\n\n      r del blist\n\n      $rd brpoplpush blist blist 0\n\n      r rpush blist foo\n\n      assert_equal {foo} [r lrange blist 0 -1]\n    }\n\n    test \"BRPOPLPUSH inside a transaction\" {\n        r del xlist target\n        r lpush xlist foo\n        r lpush xlist bar\n\n        r multi\n        r brpoplpush xlist target 0\n        r brpoplpush xlist target 0\n        r brpoplpush xlist target 0\n        r lrange xlist 0 -1\n        r lrange target 0 -1\n        r exec\n    } {foo bar {} {} {bar foo}}\n\n    test \"PUSH resulting from BRPOPLPUSH affect WATCH\" {\n        set blocked_client [redis_deferring_client]\n        set watching_client [redis_deferring_client]\n        r del srclist dstlist somekey\n        r set somekey somevalue\n        $blocked_client brpoplpush srclist dstlist 0\n        $watching_client watch dstlist\n        $watching_client read\n        $watching_client multi\n        $watching_client read\n        $watching_client get somekey\n        $watching_client read\n        r lpush srclist element\n        $watching_client exec\n        $watching_client read\n    } {}\n\n    test \"BRPOPLPUSH does not affect WATCH while still blocked\" {\n        set blocked_client [redis_deferring_client]\n        set watching_client [redis_deferring_client]\n        r del srclist dstlist somekey\n        r set somekey somevalue\n        $blocked_client brpoplpush srclist dstlist 0\n        $watching_client watch dstlist\n        $watching_client read\n        $watching_client multi\n        $watching_client read\n        $watching_client get somekey\n        $watching_client read\n        $watching_client exec\n        # Blocked BLPOPLPUSH may create problems, unblock it.\n        r lpush srclist element\n        $watching_client read\n    } {somevalue}\n\n    test {BRPOPLPUSH timeout} {\n      set rd [redis_deferring_client]\n\n      $rd brpoplpush foo_list bar_list 1\n      after 2000\n      $rd read\n    } {}\n\n    test \"BLPOP when new key is moved into place\" {\n        set rd [redis_deferring_client]\n\n        $rd blpop foo 5\n        r lpush bob abc def hij\n        r rename bob foo\n        $rd read\n    } {foo hij}\n\n    test \"BLPOP when result key is created by SORT..STORE\" {\n        set rd [redis_deferring_client]\n\n        # zero out list from previous test without explicit delete\n        r lpop foo\n        r lpop foo\n        r lpop foo\n\n        $rd blpop foo 5\n        r lpush notfoo hello hola aguacate konichiwa zanzibar\n        r sort notfoo ALPHA store foo\n        $rd read\n    } {foo aguacate}\n\n    foreach {pop} {BLPOP BRPOP} {\n        test \"$pop: with single empty list argument\" {\n            set rd [redis_deferring_client]\n            r del blist1\n            $rd $pop blist1 1\n            r rpush blist1 foo\n            assert_equal {blist1 foo} [$rd read]\n            assert_equal 0 [r exists blist1]\n        }\n\n        test \"$pop: with negative timeout\" {\n            set rd [redis_deferring_client]\n            $rd $pop blist1 -1\n            assert_error \"ERR*is negative*\" {$rd read}\n        }\n\n        test \"$pop: with non-integer timeout\" {\n            set rd [redis_deferring_client]\n            $rd $pop blist1 1.1\n            assert_error \"ERR*not an integer*\" {$rd read}\n        }\n\n        test \"$pop: with zero timeout should block indefinitely\" {\n            # To test this, use a timeout of 0 and wait a second.\n            # The blocking pop should still be waiting for a push.\n            set rd [redis_deferring_client]\n            $rd $pop blist1 0\n            after 1000\n            r rpush blist1 foo\n            assert_equal {blist1 foo} [$rd read]\n        }\n\n        test \"$pop: second argument is not a list\" {\n            set rd [redis_deferring_client]\n            r del blist1 blist2\n            r set blist2 nolist\n            $rd $pop blist1 blist2 1\n            assert_error \"WRONGTYPE*\" {$rd read}\n        }\n\n        test \"$pop: timeout\" {\n            set rd [redis_deferring_client]\n            r del blist1 blist2\n            $rd $pop blist1 blist2 1\n            assert_equal {} [$rd read]\n        }\n\n        test \"$pop: arguments are empty\" {\n            set rd [redis_deferring_client]\n            r del blist1 blist2\n\n            $rd $pop blist1 blist2 1\n            r rpush blist1 foo\n            assert_equal {blist1 foo} [$rd read]\n            assert_equal 0 [r exists blist1]\n            assert_equal 0 [r exists blist2]\n\n            $rd $pop blist1 blist2 1\n            r rpush blist2 foo\n            assert_equal {blist2 foo} [$rd read]\n            assert_equal 0 [r exists blist1]\n            assert_equal 0 [r exists blist2]\n        }\n    }\n\n    test {BLPOP inside a transaction} {\n        r del xlist\n        r lpush xlist foo\n        r lpush xlist bar\n        r multi\n        r blpop xlist 0\n        r blpop xlist 0\n        r blpop xlist 0\n        r exec\n    } {{xlist bar} {xlist foo} {}}\n\n    test {LPUSHX, RPUSHX - generic} {\n        r del xlist\n        assert_equal 0 [r lpushx xlist a]\n        assert_equal 0 [r llen xlist]\n        assert_equal 0 [r rpushx xlist a]\n        assert_equal 0 [r llen xlist]\n    }\n\n    foreach {type large} [array get largevalue] {\n        test \"LPUSHX, RPUSHX - $type\" {\n            create_list xlist \"$large c\"\n            assert_equal 3 [r rpushx xlist d]\n            assert_equal 4 [r lpushx xlist a]\n            assert_equal \"a $large c d\" [r lrange xlist 0 -1]\n        }\n\n        test \"LINSERT - $type\" {\n            create_list xlist \"a $large c d\"\n            assert_equal 5 [r linsert xlist before c zz] \"before c\"\n            assert_equal \"a $large zz c d\" [r lrange xlist 0 10] \"lrangeA\"\n            assert_equal 6 [r linsert xlist after c yy] \"after c\"\n            assert_equal \"a $large zz c yy d\" [r lrange xlist 0 10] \"lrangeB\"\n            assert_equal 7 [r linsert xlist after d dd] \"after d\"\n            assert_equal -1 [r linsert xlist after bad ddd] \"after bad\"\n            assert_equal \"a $large zz c yy d dd\" [r lrange xlist 0 10] \"lrangeC\"\n            assert_equal 8 [r linsert xlist before a aa] \"before a\"\n            assert_equal -1 [r linsert xlist before bad aaa] \"before bad\"\n            assert_equal \"aa a $large zz c yy d dd\" [r lrange xlist 0 10] \"lrangeD\"\n\n            # check inserting integer encoded value\n            assert_equal 9 [r linsert xlist before aa 42] \"before aa\"\n            assert_equal 42 [r lrange xlist 0 0] \"lrangeE\"\n        }\n    }\n\n    test {LINSERT raise error on bad syntax} {\n        catch {[r linsert xlist aft3r aa 42]} e\n        set e\n    } {*ERR*syntax*error*}\n\n    foreach {type num} {quicklist 250 quicklist 500} {\n        proc check_numbered_list_consistency {key} {\n            set len [r llen $key]\n            for {set i 0} {$i < $len} {incr i} {\n                assert_equal $i [r lindex $key $i]\n                assert_equal [expr $len-1-$i] [r lindex $key [expr (-$i)-1]]\n            }\n        }\n\n        proc check_random_access_consistency {key} {\n            set len [r llen $key]\n            for {set i 0} {$i < $len} {incr i} {\n                set rint [expr int(rand()*$len)]\n                assert_equal $rint [r lindex $key $rint]\n                assert_equal [expr $len-1-$rint] [r lindex $key [expr (-$rint)-1]]\n            }\n        }\n\n        test \"LINDEX consistency test - $type\" {\n            r del mylist\n            for {set i 0} {$i < $num} {incr i} {\n                r rpush mylist $i\n            }\n            assert_encoding $type mylist\n            check_numbered_list_consistency mylist\n        }\n\n        test \"LINDEX random access - $type\" {\n            assert_encoding $type mylist\n            check_random_access_consistency mylist\n        }\n\n        test \"Check if list is still ok after a DEBUG RELOAD - $type\" {\n            r debug reload\n            assert_encoding $type mylist\n            check_numbered_list_consistency mylist\n            check_random_access_consistency mylist\n        }\n    }\n\n    test {LLEN against non-list value error} {\n        r del mylist\n        r set mylist foobar\n        assert_error WRONGTYPE* {r llen mylist}\n    }\n\n    test {LLEN against non existing key} {\n        assert_equal 0 [r llen not-a-key]\n    }\n\n    test {LINDEX against non-list value error} {\n        assert_error WRONGTYPE* {r lindex mylist 0}\n    }\n\n    test {LINDEX against non existing key} {\n        assert_equal \"\" [r lindex not-a-key 10]\n    }\n\n    test {LPUSH against non-list value error} {\n        assert_error WRONGTYPE* {r lpush mylist 0}\n    }\n\n    test {RPUSH against non-list value error} {\n        assert_error WRONGTYPE* {r rpush mylist 0}\n    }\n\n    foreach {type large} [array get largevalue] {\n        test \"RPOPLPUSH base case - $type\" {\n            r del mylist1 mylist2\n            create_list mylist1 \"a $large c d\"\n            assert_equal d [r rpoplpush mylist1 mylist2]\n            assert_equal c [r rpoplpush mylist1 mylist2]\n            assert_equal \"a $large\" [r lrange mylist1 0 -1]\n            assert_equal \"c d\" [r lrange mylist2 0 -1]\n            assert_encoding quicklist mylist2\n        }\n\n        test \"RPOPLPUSH with the same list as src and dst - $type\" {\n            create_list mylist \"a $large c\"\n            assert_equal \"a $large c\" [r lrange mylist 0 -1]\n            assert_equal c [r rpoplpush mylist mylist]\n            assert_equal \"c a $large\" [r lrange mylist 0 -1]\n        }\n\n        foreach {othertype otherlarge} [array get largevalue] {\n            test \"RPOPLPUSH with $type source and existing target $othertype\" {\n                create_list srclist \"a b c $large\"\n                create_list dstlist \"$otherlarge\"\n                assert_equal $large [r rpoplpush srclist dstlist]\n                assert_equal c [r rpoplpush srclist dstlist]\n                assert_equal \"a b\" [r lrange srclist 0 -1]\n                assert_equal \"c $large $otherlarge\" [r lrange dstlist 0 -1]\n\n                # When we rpoplpush'ed a large value, dstlist should be\n                # converted to the same encoding as srclist.\n                if {$type eq \"linkedlist\"} {\n                    assert_encoding quicklist dstlist\n                }\n            }\n        }\n    }\n\n    test {RPOPLPUSH against non existing key} {\n        r del srclist dstlist\n        assert_equal {} [r rpoplpush srclist dstlist]\n        assert_equal 0 [r exists srclist]\n        assert_equal 0 [r exists dstlist]\n    }\n\n    test {RPOPLPUSH against non list src key} {\n        r del srclist dstlist\n        r set srclist x\n        assert_error WRONGTYPE* {r rpoplpush srclist dstlist}\n        assert_type string srclist\n        assert_equal 0 [r exists newlist]\n    }\n\n    test {RPOPLPUSH against non list dst key} {\n        create_list srclist {a b c d}\n        r set dstlist x\n        assert_error WRONGTYPE* {r rpoplpush srclist dstlist}\n        assert_type string dstlist\n        assert_equal {a b c d} [r lrange srclist 0 -1]\n    }\n\n    test {RPOPLPUSH against non existing src key} {\n        r del srclist dstlist\n        assert_equal {} [r rpoplpush srclist dstlist]\n    } {}\n\n    foreach {type large} [array get largevalue] {\n        test \"Basic LPOP/RPOP - $type\" {\n            create_list mylist \"$large 1 2\"\n            assert_equal $large [r lpop mylist]\n            assert_equal 2 [r rpop mylist]\n            assert_equal 1 [r lpop mylist]\n            assert_equal 0 [r llen mylist]\n\n            # pop on empty list\n            assert_equal {} [r lpop mylist]\n            assert_equal {} [r rpop mylist]\n        }\n    }\n\n    test {LPOP/RPOP against non list value} {\n        r set notalist foo\n        assert_error WRONGTYPE* {r lpop notalist}\n        assert_error WRONGTYPE* {r rpop notalist}\n    }\n\n    foreach {type num} {quicklist 250 quicklist 500} {\n        test \"Mass RPOP/LPOP - $type\" {\n            r del mylist\n            set sum1 0\n            for {set i 0} {$i < $num} {incr i} {\n                r lpush mylist $i\n                incr sum1 $i\n            }\n            assert_encoding $type mylist\n            set sum2 0\n            for {set i 0} {$i < [expr $num/2]} {incr i} {\n                incr sum2 [r lpop mylist]\n                incr sum2 [r rpop mylist]\n            }\n            assert_equal $sum1 $sum2\n        }\n    }\n\n    foreach {type large} [array get largevalue] {\n        test \"LRANGE basics - $type\" {\n            create_list mylist \"$large 1 2 3 4 5 6 7 8 9\"\n            assert_equal {1 2 3 4 5 6 7 8} [r lrange mylist 1 -2]\n            assert_equal {7 8 9} [r lrange mylist -3 -1]\n            assert_equal {4} [r lrange mylist 4 4]\n        }\n\n        test \"LRANGE inverted indexes - $type\" {\n            create_list mylist \"$large 1 2 3 4 5 6 7 8 9\"\n            assert_equal {} [r lrange mylist 6 2]\n        }\n\n        test \"LRANGE out of range indexes including the full list - $type\" {\n            create_list mylist \"$large 1 2 3\"\n            assert_equal \"$large 1 2 3\" [r lrange mylist -1000 1000]\n        }\n\n        test \"LRANGE out of range negative end index - $type\" {\n            create_list mylist \"$large 1 2 3\"\n            assert_equal $large [r lrange mylist 0 -4]\n            assert_equal {} [r lrange mylist 0 -5]\n        }\n    }\n\n    test {LRANGE against non existing key} {\n        assert_equal {} [r lrange nosuchkey 0 1]\n    }\n\n    foreach {type large} [array get largevalue] {\n        proc trim_list {type min max} {\n            upvar 1 large large\n            r del mylist\n            create_list mylist \"1 2 3 4 $large\"\n            r ltrim mylist $min $max\n            r lrange mylist 0 -1\n        }\n\n        test \"LTRIM basics - $type\" {\n            assert_equal \"1\" [trim_list $type 0 0]\n            assert_equal \"1 2\" [trim_list $type 0 1]\n            assert_equal \"1 2 3\" [trim_list $type 0 2]\n            assert_equal \"2 3\" [trim_list $type 1 2]\n            assert_equal \"2 3 4 $large\" [trim_list $type 1 -1]\n            assert_equal \"2 3 4\" [trim_list $type 1 -2]\n            assert_equal \"4 $large\" [trim_list $type -2 -1]\n            assert_equal \"$large\" [trim_list $type -1 -1]\n            assert_equal \"1 2 3 4 $large\" [trim_list $type -5 -1]\n            assert_equal \"1 2 3 4 $large\" [trim_list $type -10 10]\n            assert_equal \"1 2 3 4 $large\" [trim_list $type 0 5]\n            assert_equal \"1 2 3 4 $large\" [trim_list $type 0 10]\n        }\n\n        test \"LTRIM out of range negative end index - $type\" {\n            assert_equal {1} [trim_list $type 0 -5]\n            assert_equal {} [trim_list $type 0 -6]\n        }\n\n    }\n\n    foreach {type large} [array get largevalue] {\n        test \"LSET - $type\" {\n            create_list mylist \"99 98 $large 96 95\"\n            r lset mylist 1 foo\n            r lset mylist -1 bar\n            assert_equal \"99 foo $large 96 bar\" [r lrange mylist 0 -1]\n        }\n\n        test \"LSET out of range index - $type\" {\n            assert_error ERR*range* {r lset mylist 10 foo}\n        }\n    }\n\n    test {LSET against non existing key} {\n        assert_error ERR*key* {r lset nosuchkey 10 foo}\n    }\n\n    test {LSET against non list value} {\n        r set nolist foobar\n        assert_error WRONGTYPE* {r lset nolist 0 foo}\n    }\n\n    foreach {type e} [array get largevalue] {\n        test \"LREM remove all the occurrences - $type\" {\n            create_list mylist \"$e foo bar foobar foobared zap bar test foo\"\n            assert_equal 2 [r lrem mylist 0 bar]\n            assert_equal \"$e foo foobar foobared zap test foo\" [r lrange mylist 0 -1]\n        }\n\n        test \"LREM remove the first occurrence - $type\" {\n            assert_equal 1 [r lrem mylist 1 foo]\n            assert_equal \"$e foobar foobared zap test foo\" [r lrange mylist 0 -1]\n        }\n\n        test \"LREM remove non existing element - $type\" {\n            assert_equal 0 [r lrem mylist 1 nosuchelement]\n            assert_equal \"$e foobar foobared zap test foo\" [r lrange mylist 0 -1]\n        }\n\n        test \"LREM starting from tail with negative count - $type\" {\n            create_list mylist \"$e foo bar foobar foobared zap bar test foo foo\"\n            assert_equal 1 [r lrem mylist -1 bar]\n            assert_equal \"$e foo bar foobar foobared zap test foo foo\" [r lrange mylist 0 -1]\n        }\n\n        test \"LREM starting from tail with negative count (2) - $type\" {\n            assert_equal 2 [r lrem mylist -2 foo]\n            assert_equal \"$e foo bar foobar foobared zap test\" [r lrange mylist 0 -1]\n        }\n\n        test \"LREM deleting objects that may be int encoded - $type\" {\n            create_list myotherlist \"$e 1 2 3\"\n            assert_equal 1 [r lrem myotherlist 1 2]\n            assert_equal 3 [r llen myotherlist]\n        }\n    }\n\n    test \"Regression for bug 593 - chaining BRPOPLPUSH with other blocking cmds\" {\n        set rd1 [redis_deferring_client]\n        set rd2 [redis_deferring_client]\n\n        $rd1 brpoplpush a b 0\n        $rd1 brpoplpush a b 0\n        $rd2 brpoplpush b c 0\n        after 1000\n        r lpush a data\n        $rd1 close\n        $rd2 close\n        r ping\n    } {PONG}\n}\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/tests/unit/type/set.tcl",
    "content": "start_server {\n    tags {\"set\"}\n    overrides {\n        \"set-max-intset-entries\" 512\n    }\n} {\n    proc create_set {key entries} {\n        r del $key\n        foreach entry $entries { r sadd $key $entry }\n    }\n\n    test {SADD, SCARD, SISMEMBER, SMEMBERS basics - regular set} {\n        create_set myset {foo}\n        assert_encoding hashtable myset\n        assert_equal 1 [r sadd myset bar]\n        assert_equal 0 [r sadd myset bar]\n        assert_equal 2 [r scard myset]\n        assert_equal 1 [r sismember myset foo]\n        assert_equal 1 [r sismember myset bar]\n        assert_equal 0 [r sismember myset bla]\n        assert_equal {bar foo} [lsort [r smembers myset]]\n    }\n\n    test {SADD, SCARD, SISMEMBER, SMEMBERS basics - intset} {\n        create_set myset {17}\n        assert_encoding intset myset\n        assert_equal 1 [r sadd myset 16]\n        assert_equal 0 [r sadd myset 16]\n        assert_equal 2 [r scard myset]\n        assert_equal 1 [r sismember myset 16]\n        assert_equal 1 [r sismember myset 17]\n        assert_equal 0 [r sismember myset 18]\n        assert_equal {16 17} [lsort [r smembers myset]]\n    }\n\n    test {SADD against non set} {\n        r lpush mylist foo\n        assert_error WRONGTYPE* {r sadd mylist bar}\n    }\n\n    test \"SADD a non-integer against an intset\" {\n        create_set myset {1 2 3}\n        assert_encoding intset myset\n        assert_equal 1 [r sadd myset a]\n        assert_encoding hashtable myset\n    }\n\n    test \"SADD an integer larger than 64 bits\" {\n        create_set myset {213244124402402314402033402}\n        assert_encoding hashtable myset\n        assert_equal 1 [r sismember myset 213244124402402314402033402]\n    }\n\n    test \"SADD overflows the maximum allowed integers in an intset\" {\n        r del myset\n        for {set i 0} {$i < 512} {incr i} { r sadd myset $i }\n        assert_encoding intset myset\n        assert_equal 1 [r sadd myset 512]\n        assert_encoding hashtable myset\n    }\n\n    test {Variadic SADD} {\n        r del myset\n        assert_equal 3 [r sadd myset a b c]\n        assert_equal 2 [r sadd myset A a b c B]\n        assert_equal [lsort {A a b c B}] [lsort [r smembers myset]]\n    }\n\n    test \"Set encoding after DEBUG RELOAD\" {\n        r del myintset myhashset mylargeintset\n        for {set i 0} {$i <  100} {incr i} { r sadd myintset $i }\n        for {set i 0} {$i < 1280} {incr i} { r sadd mylargeintset $i }\n        for {set i 0} {$i <  256} {incr i} { r sadd myhashset [format \"i%03d\" $i] }\n        assert_encoding intset myintset\n        assert_encoding hashtable mylargeintset\n        assert_encoding hashtable myhashset\n\n        r debug reload\n        assert_encoding intset myintset\n        assert_encoding hashtable mylargeintset\n        assert_encoding hashtable myhashset\n    }\n\n    test {SREM basics - regular set} {\n        create_set myset {foo bar ciao}\n        assert_encoding hashtable myset\n        assert_equal 0 [r srem myset qux]\n        assert_equal 1 [r srem myset foo]\n        assert_equal {bar ciao} [lsort [r smembers myset]]\n    }\n\n    test {SREM basics - intset} {\n        create_set myset {3 4 5}\n        assert_encoding intset myset\n        assert_equal 0 [r srem myset 6]\n        assert_equal 1 [r srem myset 4]\n        assert_equal {3 5} [lsort [r smembers myset]]\n    }\n\n    test {SREM with multiple arguments} {\n        r del myset\n        r sadd myset a b c d\n        assert_equal 0 [r srem myset k k k]\n        assert_equal 2 [r srem myset b d x y]\n        lsort [r smembers myset]\n    } {a c}\n\n    test {SREM variadic version with more args needed to destroy the key} {\n        r del myset\n        r sadd myset 1 2 3\n        r srem myset 1 2 3 4 5 6 7 8\n    } {3}\n\n    foreach {type} {hashtable intset} {\n        for {set i 1} {$i <= 5} {incr i} {\n            r del [format \"set%d\" $i]\n        }\n        for {set i 0} {$i < 200} {incr i} {\n            r sadd set1 $i\n            r sadd set2 [expr $i+195]\n        }\n        foreach i {199 195 1000 2000} {\n            r sadd set3 $i\n        }\n        for {set i 5} {$i < 200} {incr i} {\n            r sadd set4 $i\n        }\n        r sadd set5 0\n\n        # To make sure the sets are encoded as the type we are testing -- also\n        # when the VM is enabled and the values may be swapped in and out\n        # while the tests are running -- an extra element is added to every\n        # set that determines its encoding.\n        set large 200\n        if {$type eq \"hashtable\"} {\n            set large foo\n        }\n\n        for {set i 1} {$i <= 5} {incr i} {\n            r sadd [format \"set%d\" $i] $large\n        }\n\n        test \"Generated sets must be encoded as $type\" {\n            for {set i 1} {$i <= 5} {incr i} {\n                assert_encoding $type [format \"set%d\" $i]\n            }\n        }\n\n        test \"SINTER with two sets - $type\" {\n            assert_equal [list 195 196 197 198 199 $large] [lsort [r sinter set1 set2]]\n        }\n\n        test \"SINTERSTORE with two sets - $type\" {\n            r sinterstore setres set1 set2\n            assert_encoding $type setres\n            assert_equal [list 195 196 197 198 199 $large] [lsort [r smembers setres]]\n        }\n\n        test \"SINTERSTORE with two sets, after a DEBUG RELOAD - $type\" {\n            r debug reload\n            r sinterstore setres set1 set2\n            assert_encoding $type setres\n            assert_equal [list 195 196 197 198 199 $large] [lsort [r smembers setres]]\n        }\n\n        test \"SUNION with two sets - $type\" {\n            set expected [lsort -uniq \"[r smembers set1] [r smembers set2]\"]\n            assert_equal $expected [lsort [r sunion set1 set2]]\n        }\n\n        test \"SUNIONSTORE with two sets - $type\" {\n            r sunionstore setres set1 set2\n            assert_encoding $type setres\n            set expected [lsort -uniq \"[r smembers set1] [r smembers set2]\"]\n            assert_equal $expected [lsort [r smembers setres]]\n        }\n\n        test \"SINTER against three sets - $type\" {\n            assert_equal [list 195 199 $large] [lsort [r sinter set1 set2 set3]]\n        }\n\n        test \"SINTERSTORE with three sets - $type\" {\n            r sinterstore setres set1 set2 set3\n            assert_equal [list 195 199 $large] [lsort [r smembers setres]]\n        }\n\n        test \"SUNION with non existing keys - $type\" {\n            set expected [lsort -uniq \"[r smembers set1] [r smembers set2]\"]\n            assert_equal $expected [lsort [r sunion nokey1 set1 set2 nokey2]]\n        }\n\n        test \"SDIFF with two sets - $type\" {\n            assert_equal {0 1 2 3 4} [lsort [r sdiff set1 set4]]\n        }\n\n        test \"SDIFF with three sets - $type\" {\n            assert_equal {1 2 3 4} [lsort [r sdiff set1 set4 set5]]\n        }\n\n        test \"SDIFFSTORE with three sets - $type\" {\n            r sdiffstore setres set1 set4 set5\n            # When we start with intsets, we should always end with intsets.\n            if {$type eq {intset}} {\n                assert_encoding intset setres\n            }\n            assert_equal {1 2 3 4} [lsort [r smembers setres]]\n        }\n    }\n\n    test \"SDIFF with first set empty\" {\n        r del set1 set2 set3\n        r sadd set2 1 2 3 4\n        r sadd set3 a b c d\n        r sdiff set1 set2 set3\n    } {}\n\n    test \"SDIFF with same set two times\" {\n        r del set1\n        r sadd set1 a b c 1 2 3 4 5 6\n        r sdiff set1 set1\n    } {}\n\n    test \"SDIFF fuzzing\" {\n        for {set j 0} {$j < 100} {incr j} {\n            unset -nocomplain s\n            array set s {}\n            set args {}\n            set num_sets [expr {[randomInt 10]+1}]\n            for {set i 0} {$i < $num_sets} {incr i} {\n                set num_elements [randomInt 100]\n                r del set_$i\n                lappend args set_$i\n                while {$num_elements} {\n                    set ele [randomValue]\n                    r sadd set_$i $ele\n                    if {$i == 0} {\n                        set s($ele) x\n                    } else {\n                        unset -nocomplain s($ele)\n                    }\n                    incr num_elements -1\n                }\n            }\n            set result [lsort [r sdiff {*}$args]]\n            assert_equal $result [lsort [array names s]]\n        }\n    }\n\n    test \"SINTER against non-set should throw error\" {\n        r set key1 x\n        assert_error \"WRONGTYPE*\" {r sinter key1 noset}\n    }\n\n    test \"SUNION against non-set should throw error\" {\n        r set key1 x\n        assert_error \"WRONGTYPE*\" {r sunion key1 noset}\n    }\n\n    test \"SINTER should handle non existing key as empty\" {\n        r del set1 set2 set3\n        r sadd set1 a b c\n        r sadd set2 b c d\n        r sinter set1 set2 set3\n    } {}\n\n    test \"SINTER with same integer elements but different encoding\" {\n        r del set1 set2\n        r sadd set1 1 2 3\n        r sadd set2 1 2 3 a\n        r srem set2 a\n        assert_encoding intset set1\n        assert_encoding hashtable set2\n        lsort [r sinter set1 set2]\n    } {1 2 3}\n\n    test \"SINTERSTORE against non existing keys should delete dstkey\" {\n        r set setres xxx\n        assert_equal 0 [r sinterstore setres foo111 bar222]\n        assert_equal 0 [r exists setres]\n    }\n\n    test \"SUNIONSTORE against non existing keys should delete dstkey\" {\n        r set setres xxx\n        assert_equal 0 [r sunionstore setres foo111 bar222]\n        assert_equal 0 [r exists setres]\n    }\n\n    foreach {type contents} {hashtable {a b c} intset {1 2 3}} {\n        test \"SPOP basics - $type\" {\n            create_set myset $contents\n            assert_encoding $type myset\n            assert_equal $contents [lsort [list [r spop myset] [r spop myset] [r spop myset]]]\n            assert_equal 0 [r scard myset]\n        }\n\n        test \"SPOP with <count>=1 - $type\" {\n            create_set myset $contents\n            assert_encoding $type myset\n            assert_equal $contents [lsort [list [r spop myset 1] [r spop myset 1] [r spop myset 1]]]\n            assert_equal 0 [r scard myset]\n        }\n\n        test \"SRANDMEMBER - $type\" {\n            create_set myset $contents\n            unset -nocomplain myset\n            array set myset {}\n            for {set i 0} {$i < 100} {incr i} {\n                set myset([r srandmember myset]) 1\n            }\n            assert_equal $contents [lsort [array names myset]]\n        }\n    }\n\n    foreach {type contents} {\n        hashtable {a b c d e f g h i j k l m n o p q r s t u v w x y z} \n        intset {1 10 11 12 13 14 15 16 17 18 19 2 20 21 22 23 24 25 26 3 4 5 6 7 8 9}\n    } {\n        test \"SPOP with <count>\" {\n            create_set myset $contents\n            assert_encoding $type myset\n            assert_equal $contents [lsort [concat [r spop myset 11] [r spop myset 9] [r spop myset 0] [r spop myset 4] [r spop myset 1] [r spop myset 0] [r spop myset 1] [r spop myset 0]]]\n            assert_equal 0 [r scard myset]\n        }\n    }\n\n    # As seen in intsetRandomMembers\n    test \"SPOP using integers, testing Knuth's and Floyd's algorithm\" {\n        create_set myset {1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20}\n        assert_encoding intset myset\n        assert_equal 20 [r scard myset]\n        r spop myset 1\n        assert_equal 19 [r scard myset]\n        r spop myset 2\n        assert_equal 17 [r scard myset]\n        r spop myset 3\n        assert_equal 14 [r scard myset]\n        r spop myset 10\n        assert_equal 4 [r scard myset]\n        r spop myset 10\n        assert_equal 0 [r scard myset]\n        r spop myset 1\n        assert_equal 0 [r scard myset]\n    } {}\n\n    test \"SPOP using integers with Knuth's algorithm\" {\n        r spop nonexisting_key 100\n    } {}\n\n    test \"SPOP new implementation: code path #1\" {\n        set content {1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20}\n        create_set myset $content\n        set res [r spop myset 30]\n        assert {[lsort $content] eq [lsort $res]}\n    }\n\n    test \"SPOP new implementation: code path #2\" {\n        set content {1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20}\n        create_set myset $content\n        set res [r spop myset 2]\n        assert {[llength $res] == 2}\n        assert {[r scard myset] == 18}\n        set union [concat [r smembers myset] $res]\n        assert {[lsort $union] eq [lsort $content]}\n    }\n\n    test \"SPOP new implementation: code path #3\" {\n        set content {1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20}\n        create_set myset $content\n        set res [r spop myset 18]\n        assert {[llength $res] == 18}\n        assert {[r scard myset] == 2}\n        set union [concat [r smembers myset] $res]\n        assert {[lsort $union] eq [lsort $content]}\n    }\n\n    test \"SRANDMEMBER with <count> against non existing key\" {\n        r srandmember nonexisting_key 100\n    } {}\n\n    foreach {type contents} {\n        hashtable {\n            1 5 10 50 125 50000 33959417 4775547 65434162\n            12098459 427716 483706 2726473884 72615637475\n            MARY PATRICIA LINDA BARBARA ELIZABETH JENNIFER MARIA\n            SUSAN MARGARET DOROTHY LISA NANCY KAREN BETTY HELEN\n            SANDRA DONNA CAROL RUTH SHARON MICHELLE LAURA SARAH\n            KIMBERLY DEBORAH JESSICA SHIRLEY CYNTHIA ANGELA MELISSA\n            BRENDA AMY ANNA REBECCA VIRGINIA KATHLEEN\n        }\n        intset {\n            0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19\n            20 21 22 23 24 25 26 27 28 29\n            30 31 32 33 34 35 36 37 38 39\n            40 41 42 43 44 45 46 47 48 49\n        }\n    } {\n        test \"SRANDMEMBER with <count> - $type\" {\n            create_set myset $contents\n            unset -nocomplain myset\n            array set myset {}\n            foreach ele [r smembers myset] {\n                set myset($ele) 1\n            }\n            assert_equal [lsort $contents] [lsort [array names myset]]\n\n            # Make sure that a count of 0 is handled correctly.\n            assert_equal [r srandmember myset 0] {}\n\n            # We'll stress different parts of the code, see the implementation\n            # of SRANDMEMBER for more information, but basically there are\n            # four different code paths.\n            #\n            # PATH 1: Use negative count.\n            #\n            # 1) Check that it returns repeated elements.\n            set res [r srandmember myset -100]\n            assert_equal [llength $res] 100\n\n            # 2) Check that all the elements actually belong to the\n            # original set.\n            foreach ele $res {\n                assert {[info exists myset($ele)]}\n            }\n\n            # 3) Check that eventually all the elements are returned.\n            unset -nocomplain auxset\n            set iterations 1000\n            while {$iterations != 0} {\n                incr iterations -1\n                set res [r srandmember myset -10]\n                foreach ele $res {\n                    set auxset($ele) 1\n                }\n                if {[lsort [array names myset]] eq\n                    [lsort [array names auxset]]} {\n                    break;\n                }\n            }\n            assert {$iterations != 0}\n\n            # PATH 2: positive count (unique behavior) with requested size\n            # equal or greater than set size.\n            foreach size {50 100} {\n                set res [r srandmember myset $size]\n                assert_equal [llength $res] 50\n                assert_equal [lsort $res] [lsort [array names myset]]\n            }\n\n            # PATH 3: Ask almost as elements as there are in the set.\n            # In this case the implementation will duplicate the original\n            # set and will remove random elements up to the requested size.\n            #\n            # PATH 4: Ask a number of elements definitely smaller than\n            # the set size.\n            #\n            # We can test both the code paths just changing the size but\n            # using the same code.\n\n            foreach size {45 5} {\n                set res [r srandmember myset $size]\n                assert_equal [llength $res] $size\n\n                # 1) Check that all the elements actually belong to the\n                # original set.\n                foreach ele $res {\n                    assert {[info exists myset($ele)]}\n                }\n\n                # 2) Check that eventually all the elements are returned.\n                unset -nocomplain auxset\n                set iterations 1000\n                while {$iterations != 0} {\n                    incr iterations -1\n                    set res [r srandmember myset -10]\n                    foreach ele $res {\n                        set auxset($ele) 1\n                    }\n                    if {[lsort [array names myset]] eq\n                        [lsort [array names auxset]]} {\n                        break;\n                    }\n                }\n                assert {$iterations != 0}\n            }\n        }\n    }\n\n    proc setup_move {} {\n        r del myset3 myset4\n        create_set myset1 {1 a b}\n        create_set myset2 {2 3 4}\n        assert_encoding hashtable myset1\n        assert_encoding intset myset2\n    }\n\n    test \"SMOVE basics - from regular set to intset\" {\n        # move a non-integer element to an intset should convert encoding\n        setup_move\n        assert_equal 1 [r smove myset1 myset2 a]\n        assert_equal {1 b} [lsort [r smembers myset1]]\n        assert_equal {2 3 4 a} [lsort [r smembers myset2]]\n        assert_encoding hashtable myset2\n\n        # move an integer element should not convert the encoding\n        setup_move\n        assert_equal 1 [r smove myset1 myset2 1]\n        assert_equal {a b} [lsort [r smembers myset1]]\n        assert_equal {1 2 3 4} [lsort [r smembers myset2]]\n        assert_encoding intset myset2\n    }\n\n    test \"SMOVE basics - from intset to regular set\" {\n        setup_move\n        assert_equal 1 [r smove myset2 myset1 2]\n        assert_equal {1 2 a b} [lsort [r smembers myset1]]\n        assert_equal {3 4} [lsort [r smembers myset2]]\n    }\n\n    test \"SMOVE non existing key\" {\n        setup_move\n        assert_equal 0 [r smove myset1 myset2 foo]\n        assert_equal 0 [r smove myset1 myset1 foo]\n        assert_equal {1 a b} [lsort [r smembers myset1]]\n        assert_equal {2 3 4} [lsort [r smembers myset2]]\n    }\n\n    test \"SMOVE non existing src set\" {\n        setup_move\n        assert_equal 0 [r smove noset myset2 foo]\n        assert_equal {2 3 4} [lsort [r smembers myset2]]\n    }\n\n    test \"SMOVE from regular set to non existing destination set\" {\n        setup_move\n        assert_equal 1 [r smove myset1 myset3 a]\n        assert_equal {1 b} [lsort [r smembers myset1]]\n        assert_equal {a} [lsort [r smembers myset3]]\n        assert_encoding hashtable myset3\n    }\n\n    test \"SMOVE from intset to non existing destination set\" {\n        setup_move\n        assert_equal 1 [r smove myset2 myset3 2]\n        assert_equal {3 4} [lsort [r smembers myset2]]\n        assert_equal {2} [lsort [r smembers myset3]]\n        assert_encoding intset myset3\n    }\n\n    test \"SMOVE wrong src key type\" {\n        r set x 10\n        assert_error \"WRONGTYPE*\" {r smove x myset2 foo}\n    }\n\n    test \"SMOVE wrong dst key type\" {\n        r set x 10\n        assert_error \"WRONGTYPE*\" {r smove myset2 x foo}\n    }\n\n    test \"SMOVE with identical source and destination\" {\n        r del set\n        r sadd set a b c\n        r smove set set b\n        lsort [r smembers set]\n    } {a b c}\n\n    tags {slow} {\n        test {intsets implementation stress testing} {\n            for {set j 0} {$j < 20} {incr j} {\n                unset -nocomplain s\n                array set s {}\n                r del s\n                set len [randomInt 1024]\n                for {set i 0} {$i < $len} {incr i} {\n                    randpath {\n                        set data [randomInt 65536]\n                    } {\n                        set data [randomInt 4294967296]\n                    } {\n                        set data [randomInt 18446744073709551616]\n                    }\n                    set s($data) {}\n                    r sadd s $data\n                }\n                assert_equal [lsort [r smembers s]] [lsort [array names s]]\n                set len [array size s]\n                for {set i 0} {$i < $len} {incr i} {\n                    set e [r spop s]\n                    if {![info exists s($e)]} {\n                        puts \"Can't find '$e' on local array\"\n                        puts \"Local array: [lsort [r smembers s]]\"\n                        puts \"Remote array: [lsort [array names s]]\"\n                        error \"exception\"\n                    }\n                    array unset s $e\n                }\n                assert_equal [r scard s] 0\n                assert_equal [array size s] 0\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/tests/unit/type/string.tcl",
    "content": "start_server {tags {\"string\"}} {\n    test {SET and GET an item} {\n        r set x foobar\n        r get x\n    } {foobar}\n\n    test {SET and GET an empty item} {\n        r set x {}\n        r get x\n    } {}\n\n    test {Very big payload in GET/SET} {\n        set buf [string repeat \"abcd\" 1000000]\n        r set foo $buf\n        r get foo\n    } [string repeat \"abcd\" 1000000]\n\n    tags {\"slow\"} {\n        test {Very big payload random access} {\n            set err {}\n            array set payload {}\n            for {set j 0} {$j < 100} {incr j} {\n                set size [expr 1+[randomInt 100000]]\n                set buf [string repeat \"pl-$j\" $size]\n                set payload($j) $buf\n                r set bigpayload_$j $buf\n            }\n            for {set j 0} {$j < 1000} {incr j} {\n                set index [randomInt 100]\n                set buf [r get bigpayload_$index]\n                if {$buf != $payload($index)} {\n                    set err \"Values differ: I set '$payload($index)' but I read back '$buf'\"\n                    break\n                }\n            }\n            unset payload\n            set _ $err\n        } {}\n\n        test {SET 10000 numeric keys and access all them in reverse order} {\n            r flushdb\n            set err {}\n            for {set x 0} {$x < 10000} {incr x} {\n                r set $x $x\n            }\n            set sum 0\n            for {set x 9999} {$x >= 0} {incr x -1} {\n                set val [r get $x]\n                if {$val ne $x} {\n                    set err \"Element at position $x is $val instead of $x\"\n                    break\n                }\n            }\n            set _ $err\n        } {}\n\n        test {DBSIZE should be 10000 now} {\n            r dbsize\n        } {10000}\n    }\n\n    test \"SETNX target key missing\" {\n        r del novar\n        assert_equal 1 [r setnx novar foobared]\n        assert_equal \"foobared\" [r get novar]\n    }\n\n    test \"SETNX target key exists\" {\n        r set novar foobared\n        assert_equal 0 [r setnx novar blabla]\n        assert_equal \"foobared\" [r get novar]\n    }\n\n    test \"SETNX against not-expired volatile key\" {\n        r set x 10\n        r expire x 10000\n        assert_equal 0 [r setnx x 20]\n        assert_equal 10 [r get x]\n    }\n\n    test \"SETNX against expired volatile key\" {\n        # Make it very unlikely for the key this test uses to be expired by the\n        # active expiry cycle. This is tightly coupled to the implementation of\n        # active expiry and dbAdd() but currently the only way to test that\n        # SETNX expires a key when it should have been.\n        for {set x 0} {$x < 9999} {incr x} {\n            r setex key-$x 3600 value\n        }\n\n        # This will be one of 10000 expiring keys. A cycle is executed every\n        # 100ms, sampling 10 keys for being expired or not.  This key will be\n        # expired for at most 1s when we wait 2s, resulting in a total sample\n        # of 100 keys. The probability of the success of this test being a\n        # false positive is therefore approx. 1%.\n        r set x 10\n        r expire x 1\n\n        # Wait for the key to expire\n        after 2000\n\n        assert_equal 1 [r setnx x 20]\n        assert_equal 20 [r get x]\n    }\n\n    test {MGET} {\n        r flushdb\n        r set foo BAR\n        r set bar FOO\n        r mget foo bar\n    } {BAR FOO}\n\n    test {MGET against non existing key} {\n        r mget foo baazz bar\n    } {BAR {} FOO}\n\n    test {MGET against non-string key} {\n        r sadd myset ciao\n        r sadd myset bau\n        r mget foo baazz bar myset\n    } {BAR {} FOO {}}\n\n    test {GETSET (set new value)} {\n        r del foo\n        list [r getset foo xyz] [r get foo]\n    } {{} xyz}\n\n    test {GETSET (replace old value)} {\n        r set foo bar\n        list [r getset foo xyz] [r get foo]\n    } {bar xyz}\n\n    test {MSET base case} {\n        r mset x 10 y \"foo bar\" z \"x x x x x x x\\n\\n\\r\\n\"\n        r mget x y z\n    } [list 10 {foo bar} \"x x x x x x x\\n\\n\\r\\n\"]\n\n    test {MSET wrong number of args} {\n        catch {r mset x 10 y \"foo bar\" z} err\n        format $err\n    } {*wrong number*}\n\n    test {MSETNX with already existent key} {\n        list [r msetnx x1 xxx y2 yyy x 20] [r exists x1] [r exists y2]\n    } {0 0 0}\n\n    test {MSETNX with not existing keys} {\n        list [r msetnx x1 xxx y2 yyy] [r get x1] [r get y2]\n    } {1 xxx yyy}\n\n    test \"STRLEN against non-existing key\" {\n        assert_equal 0 [r strlen notakey]\n    }\n\n    test \"STRLEN against integer-encoded value\" {\n        r set myinteger -555\n        assert_equal 4 [r strlen myinteger]\n    }\n\n    test \"STRLEN against plain string\" {\n        r set mystring \"foozzz0123456789 baz\"\n        assert_equal 20 [r strlen mystring]\n    }\n\n    test \"SETBIT against non-existing key\" {\n        r del mykey\n        assert_equal 0 [r setbit mykey 1 1]\n        assert_equal [binary format B* 01000000] [r get mykey]\n    }\n\n    test \"SETBIT against string-encoded key\" {\n        # Ascii \"@\" is integer 64 = 01 00 00 00\n        r set mykey \"@\"\n\n        assert_equal 0 [r setbit mykey 2 1]\n        assert_equal [binary format B* 01100000] [r get mykey]\n        assert_equal 1 [r setbit mykey 1 0]\n        assert_equal [binary format B* 00100000] [r get mykey]\n    }\n\n    test \"SETBIT against integer-encoded key\" {\n        # Ascii \"1\" is integer 49 = 00 11 00 01\n        r set mykey 1\n        assert_encoding int mykey\n\n        assert_equal 0 [r setbit mykey 6 1]\n        assert_equal [binary format B* 00110011] [r get mykey]\n        assert_equal 1 [r setbit mykey 2 0]\n        assert_equal [binary format B* 00010011] [r get mykey]\n    }\n\n    test \"SETBIT against key with wrong type\" {\n        r del mykey\n        r lpush mykey \"foo\"\n        assert_error \"WRONGTYPE*\" {r setbit mykey 0 1}\n    }\n\n    test \"SETBIT with out of range bit offset\" {\n        r del mykey\n        assert_error \"*out of range*\" {r setbit mykey [expr 4*1024*1024*1024] 1}\n        assert_error \"*out of range*\" {r setbit mykey -1 1}\n    }\n\n    test \"SETBIT with non-bit argument\" {\n        r del mykey\n        assert_error \"*out of range*\" {r setbit mykey 0 -1}\n        assert_error \"*out of range*\" {r setbit mykey 0  2}\n        assert_error \"*out of range*\" {r setbit mykey 0 10}\n        assert_error \"*out of range*\" {r setbit mykey 0 20}\n    }\n\n    test \"SETBIT fuzzing\" {\n        set str \"\"\n        set len [expr 256*8]\n        r del mykey\n\n        for {set i 0} {$i < 2000} {incr i} {\n            set bitnum [randomInt $len]\n            set bitval [randomInt 2]\n            set fmt [format \"%%-%ds%%d%%-s\" $bitnum]\n            set head [string range $str 0 $bitnum-1]\n            set tail [string range $str $bitnum+1 end]\n            set str [string map {\" \" 0} [format $fmt $head $bitval $tail]]\n\n            r setbit mykey $bitnum $bitval\n            assert_equal [binary format B* $str] [r get mykey]\n        }\n    }\n\n    test \"GETBIT against non-existing key\" {\n        r del mykey\n        assert_equal 0 [r getbit mykey 0]\n    }\n\n    test \"GETBIT against string-encoded key\" {\n        # Single byte with 2nd and 3rd bit set\n        r set mykey \"`\"\n\n        # In-range\n        assert_equal 0 [r getbit mykey 0]\n        assert_equal 1 [r getbit mykey 1]\n        assert_equal 1 [r getbit mykey 2]\n        assert_equal 0 [r getbit mykey 3]\n\n        # Out-range\n        assert_equal 0 [r getbit mykey 8]\n        assert_equal 0 [r getbit mykey 100]\n        assert_equal 0 [r getbit mykey 10000]\n    }\n\n    test \"GETBIT against integer-encoded key\" {\n        r set mykey 1\n        assert_encoding int mykey\n\n        # Ascii \"1\" is integer 49 = 00 11 00 01\n        assert_equal 0 [r getbit mykey 0]\n        assert_equal 0 [r getbit mykey 1]\n        assert_equal 1 [r getbit mykey 2]\n        assert_equal 1 [r getbit mykey 3]\n\n        # Out-range\n        assert_equal 0 [r getbit mykey 8]\n        assert_equal 0 [r getbit mykey 100]\n        assert_equal 0 [r getbit mykey 10000]\n    }\n\n    test \"SETRANGE against non-existing key\" {\n        r del mykey\n        assert_equal 3 [r setrange mykey 0 foo]\n        assert_equal \"foo\" [r get mykey]\n\n        r del mykey\n        assert_equal 0 [r setrange mykey 0 \"\"]\n        assert_equal 0 [r exists mykey]\n\n        r del mykey\n        assert_equal 4 [r setrange mykey 1 foo]\n        assert_equal \"\\000foo\" [r get mykey]\n    }\n\n    test \"SETRANGE against string-encoded key\" {\n        r set mykey \"foo\"\n        assert_equal 3 [r setrange mykey 0 b]\n        assert_equal \"boo\" [r get mykey]\n\n        r set mykey \"foo\"\n        assert_equal 3 [r setrange mykey 0 \"\"]\n        assert_equal \"foo\" [r get mykey]\n\n        r set mykey \"foo\"\n        assert_equal 3 [r setrange mykey 1 b]\n        assert_equal \"fbo\" [r get mykey]\n\n        r set mykey \"foo\"\n        assert_equal 7 [r setrange mykey 4 bar]\n        assert_equal \"foo\\000bar\" [r get mykey]\n    }\n\n    test \"SETRANGE against integer-encoded key\" {\n        r set mykey 1234\n        assert_encoding int mykey\n        assert_equal 4 [r setrange mykey 0 2]\n        assert_encoding raw mykey\n        assert_equal 2234 [r get mykey]\n\n        # Shouldn't change encoding when nothing is set\n        r set mykey 1234\n        assert_encoding int mykey\n        assert_equal 4 [r setrange mykey 0 \"\"]\n        assert_encoding int mykey\n        assert_equal 1234 [r get mykey]\n\n        r set mykey 1234\n        assert_encoding int mykey\n        assert_equal 4 [r setrange mykey 1 3]\n        assert_encoding raw mykey\n        assert_equal 1334 [r get mykey]\n\n        r set mykey 1234\n        assert_encoding int mykey\n        assert_equal 6 [r setrange mykey 5 2]\n        assert_encoding raw mykey\n        assert_equal \"1234\\0002\" [r get mykey]\n    }\n\n    test \"SETRANGE against key with wrong type\" {\n        r del mykey\n        r lpush mykey \"foo\"\n        assert_error \"WRONGTYPE*\" {r setrange mykey 0 bar}\n    }\n\n    test \"SETRANGE with out of range offset\" {\n        r del mykey\n        assert_error \"*maximum allowed size*\" {r setrange mykey [expr 512*1024*1024-4] world}\n\n        r set mykey \"hello\"\n        assert_error \"*out of range*\" {r setrange mykey -1 world}\n        assert_error \"*maximum allowed size*\" {r setrange mykey [expr 512*1024*1024-4] world}\n    }\n\n    test \"GETRANGE against non-existing key\" {\n        r del mykey\n        assert_equal \"\" [r getrange mykey 0 -1]\n    }\n\n    test \"GETRANGE against string value\" {\n        r set mykey \"Hello World\"\n        assert_equal \"Hell\" [r getrange mykey 0 3]\n        assert_equal \"Hello World\" [r getrange mykey 0 -1]\n        assert_equal \"orld\" [r getrange mykey -4 -1]\n        assert_equal \"\" [r getrange mykey 5 3]\n        assert_equal \" World\" [r getrange mykey 5 5000]\n        assert_equal \"Hello World\" [r getrange mykey -5000 10000]\n    }\n\n    test \"GETRANGE against integer-encoded value\" {\n        r set mykey 1234\n        assert_equal \"123\" [r getrange mykey 0 2]\n        assert_equal \"1234\" [r getrange mykey 0 -1]\n        assert_equal \"234\" [r getrange mykey -3 -1]\n        assert_equal \"\" [r getrange mykey 5 3]\n        assert_equal \"4\" [r getrange mykey 3 5000]\n        assert_equal \"1234\" [r getrange mykey -5000 10000]\n    }\n\n    test \"GETRANGE fuzzing\" {\n        for {set i 0} {$i < 1000} {incr i} {\n            r set bin [set bin [randstring 0 1024 binary]]\n            set _start [set start [randomInt 1500]]\n            set _end [set end [randomInt 1500]]\n            if {$_start < 0} {set _start \"end-[abs($_start)-1]\"}\n            if {$_end < 0} {set _end \"end-[abs($_end)-1]\"}\n            assert_equal [string range $bin $_start $_end] [r getrange bin $start $end]\n        }\n    }\n\n    test {Extended SET can detect syntax errors} {\n        set e {}\n        catch {r set foo bar non-existing-option} e\n        set e\n    } {*syntax*}\n\n    test {Extended SET NX option} {\n        r del foo\n        set v1 [r set foo 1 nx]\n        set v2 [r set foo 2 nx]\n        list $v1 $v2 [r get foo]\n    } {OK {} 1}\n\n    test {Extended SET XX option} {\n        r del foo\n        set v1 [r set foo 1 xx]\n        r set foo bar\n        set v2 [r set foo 2 xx]\n        list $v1 $v2 [r get foo]\n    } {{} OK 2}\n\n    test {Extended SET EX option} {\n        r del foo\n        r set foo bar ex 10\n        set ttl [r ttl foo]\n        assert {$ttl <= 10 && $ttl > 5}\n    }\n\n    test {Extended SET PX option} {\n        r del foo\n        r set foo bar px 10000\n        set ttl [r ttl foo]\n        assert {$ttl <= 10 && $ttl > 5}\n    }\n\n    test {Extended SET using multiple options at once} {\n        r set foo val\n        assert {[r set foo bar xx px 10000] eq {OK}}\n        set ttl [r ttl foo]\n        assert {$ttl <= 10 && $ttl > 5}\n    }\n\n    test {GETRANGE with huge ranges, Github issue #1844} {\n        r set foo bar\n        r getrange foo 0 4294967297\n    } {bar}\n}\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/tests/unit/type/zset.tcl",
    "content": "start_server {tags {\"zset\"}} {\n    proc create_zset {key items} {\n        r del $key\n        foreach {score entry} $items {\n            r zadd $key $score $entry\n        }\n    }\n\n    proc basics {encoding} {\n        if {$encoding == \"ziplist\"} {\n            r config set zset-max-ziplist-entries 128\n            r config set zset-max-ziplist-value 64\n        } elseif {$encoding == \"skiplist\"} {\n            r config set zset-max-ziplist-entries 0\n            r config set zset-max-ziplist-value 0\n        } else {\n            puts \"Unknown sorted set encoding\"\n            exit\n        }\n\n        test \"Check encoding - $encoding\" {\n            r del ztmp\n            r zadd ztmp 10 x\n            assert_encoding $encoding ztmp\n        }\n\n        test \"ZSET basic ZADD and score update - $encoding\" {\n            r del ztmp\n            r zadd ztmp 10 x\n            r zadd ztmp 20 y\n            r zadd ztmp 30 z\n            assert_equal {x y z} [r zrange ztmp 0 -1]\n\n            r zadd ztmp 1 y\n            assert_equal {y x z} [r zrange ztmp 0 -1]\n        }\n\n        test \"ZSET element can't be set to NaN with ZADD - $encoding\" {\n            assert_error \"*not*float*\" {r zadd myzset nan abc}\n        }\n\n        test \"ZSET element can't be set to NaN with ZINCRBY\" {\n            assert_error \"*not*float*\" {r zadd myzset nan abc}\n        }\n\n        test \"ZADD with options syntax error with incomplete pair\" {\n            r del ztmp\n            catch {r zadd ztmp xx 10 x 20} err\n            set err\n        } {ERR*}\n\n        test \"ZADD XX option without key - $encoding\" {\n            r del ztmp\n            assert {[r zadd ztmp xx 10 x] == 0}\n            assert {[r type ztmp] eq {none}}\n        }\n\n        test \"ZADD XX existing key - $encoding\" {\n            r del ztmp\n            r zadd ztmp 10 x\n            assert {[r zadd ztmp xx 20 y] == 0}\n            assert {[r zcard ztmp] == 1}\n        }\n\n        test \"ZADD XX returns the number of elements actually added\" {\n            r del ztmp\n            r zadd ztmp 10 x\n            set retval [r zadd ztmp 10 x 20 y 30 z]\n            assert {$retval == 2}\n        }\n\n        test \"ZADD XX updates existing elements score\" {\n            r del ztmp\n            r zadd ztmp 10 x 20 y 30 z\n            r zadd ztmp xx 5 foo 11 x 21 y 40 zap\n            assert {[r zcard ztmp] == 3}\n            assert {[r zscore ztmp x] == 11}\n            assert {[r zscore ztmp y] == 21}\n        }\n\n        test \"ZADD XX and NX are not compatible\" {\n            r del ztmp\n            catch {r zadd ztmp xx nx 10 x} err\n            set err\n        } {ERR*}\n\n        test \"ZADD NX with non exisitng key\" {\n            r del ztmp\n            r zadd ztmp nx 10 x 20 y 30 z\n            assert {[r zcard ztmp] == 3}\n        }\n\n        test \"ZADD NX only add new elements without updating old ones\" {\n            r del ztmp\n            r zadd ztmp 10 x 20 y 30 z\n            assert {[r zadd ztmp nx 11 x 21 y 100 a 200 b] == 2}\n            assert {[r zscore ztmp x] == 10}\n            assert {[r zscore ztmp y] == 20}\n            assert {[r zscore ztmp a] == 100}\n            assert {[r zscore ztmp b] == 200}\n        }\n\n        test \"ZADD INCR works like ZINCRBY\" {\n            r del ztmp\n            r zadd ztmp 10 x 20 y 30 z\n            r zadd ztmp INCR 15 x\n            assert {[r zscore ztmp x] == 25}\n        }\n\n        test \"ZADD INCR works with a single score-elemenet pair\" {\n            r del ztmp\n            r zadd ztmp 10 x 20 y 30 z\n            catch {r zadd ztmp INCR 15 x 10 y} err\n            set err\n        } {ERR*}\n\n        test \"ZADD CH option changes return value to all changed elements\" {\n            r del ztmp\n            r zadd ztmp 10 x 20 y 30 z\n            assert {[r zadd ztmp 11 x 21 y 30 z] == 0}\n            assert {[r zadd ztmp ch 12 x 22 y 30 z] == 2}\n        }\n\n        test \"ZINCRBY calls leading to NaN result in error\" {\n            r zincrby myzset +inf abc\n            assert_error \"*NaN*\" {r zincrby myzset -inf abc}\n        }\n\n        test {ZADD - Variadic version base case} {\n            r del myzset\n            list [r zadd myzset 10 a 20 b 30 c] [r zrange myzset 0 -1 withscores]\n        } {3 {a 10 b 20 c 30}}\n\n        test {ZADD - Return value is the number of actually added items} {\n            list [r zadd myzset 5 x 20 b 30 c] [r zrange myzset 0 -1 withscores]\n        } {1 {x 5 a 10 b 20 c 30}}\n\n        test {ZADD - Variadic version does not add nothing on single parsing err} {\n            r del myzset\n            catch {r zadd myzset 10 a 20 b 30.badscore c} e\n            assert_match {*ERR*not*float*} $e\n            r exists myzset\n        } {0}\n\n        test {ZADD - Variadic version will raise error on missing arg} {\n            r del myzset\n            catch {r zadd myzset 10 a 20 b 30 c 40} e\n            assert_match {*ERR*syntax*} $e\n        }\n\n        test {ZINCRBY does not work variadic even if shares ZADD implementation} {\n            r del myzset\n            catch {r zincrby myzset 10 a 20 b 30 c} e\n            assert_match {*ERR*wrong*number*arg*} $e\n        }\n\n        test \"ZCARD basics - $encoding\" {\n            r del ztmp\n            r zadd ztmp 10 a 20 b 30 c\n            assert_equal 3 [r zcard ztmp]\n            assert_equal 0 [r zcard zdoesntexist]\n        }\n\n        test \"ZREM removes key after last element is removed\" {\n            r del ztmp\n            r zadd ztmp 10 x\n            r zadd ztmp 20 y\n\n            assert_equal 1 [r exists ztmp]\n            assert_equal 0 [r zrem ztmp z]\n            assert_equal 1 [r zrem ztmp y]\n            assert_equal 1 [r zrem ztmp x]\n            assert_equal 0 [r exists ztmp]\n        }\n\n        test \"ZREM variadic version\" {\n            r del ztmp\n            r zadd ztmp 10 a 20 b 30 c\n            assert_equal 2 [r zrem ztmp x y a b k]\n            assert_equal 0 [r zrem ztmp foo bar]\n            assert_equal 1 [r zrem ztmp c]\n            r exists ztmp\n        } {0}\n\n        test \"ZREM variadic version -- remove elements after key deletion\" {\n            r del ztmp\n            r zadd ztmp 10 a 20 b 30 c\n            r zrem ztmp a b c d e f g\n        } {3}\n\n        test \"ZRANGE basics - $encoding\" {\n            r del ztmp\n            r zadd ztmp 1 a\n            r zadd ztmp 2 b\n            r zadd ztmp 3 c\n            r zadd ztmp 4 d\n\n            assert_equal {a b c d} [r zrange ztmp 0 -1]\n            assert_equal {a b c} [r zrange ztmp 0 -2]\n            assert_equal {b c d} [r zrange ztmp 1 -1]\n            assert_equal {b c} [r zrange ztmp 1 -2]\n            assert_equal {c d} [r zrange ztmp -2 -1]\n            assert_equal {c} [r zrange ztmp -2 -2]\n\n            # out of range start index\n            assert_equal {a b c} [r zrange ztmp -5 2]\n            assert_equal {a b} [r zrange ztmp -5 1]\n            assert_equal {} [r zrange ztmp 5 -1]\n            assert_equal {} [r zrange ztmp 5 -2]\n\n            # out of range end index\n            assert_equal {a b c d} [r zrange ztmp 0 5]\n            assert_equal {b c d} [r zrange ztmp 1 5]\n            assert_equal {} [r zrange ztmp 0 -5]\n            assert_equal {} [r zrange ztmp 1 -5]\n\n            # withscores\n            assert_equal {a 1 b 2 c 3 d 4} [r zrange ztmp 0 -1 withscores]\n        }\n\n        test \"ZREVRANGE basics - $encoding\" {\n            r del ztmp\n            r zadd ztmp 1 a\n            r zadd ztmp 2 b\n            r zadd ztmp 3 c\n            r zadd ztmp 4 d\n\n            assert_equal {d c b a} [r zrevrange ztmp 0 -1]\n            assert_equal {d c b} [r zrevrange ztmp 0 -2]\n            assert_equal {c b a} [r zrevrange ztmp 1 -1]\n            assert_equal {c b} [r zrevrange ztmp 1 -2]\n            assert_equal {b a} [r zrevrange ztmp -2 -1]\n            assert_equal {b} [r zrevrange ztmp -2 -2]\n\n            # out of range start index\n            assert_equal {d c b} [r zrevrange ztmp -5 2]\n            assert_equal {d c} [r zrevrange ztmp -5 1]\n            assert_equal {} [r zrevrange ztmp 5 -1]\n            assert_equal {} [r zrevrange ztmp 5 -2]\n\n            # out of range end index\n            assert_equal {d c b a} [r zrevrange ztmp 0 5]\n            assert_equal {c b a} [r zrevrange ztmp 1 5]\n            assert_equal {} [r zrevrange ztmp 0 -5]\n            assert_equal {} [r zrevrange ztmp 1 -5]\n\n            # withscores\n            assert_equal {d 4 c 3 b 2 a 1} [r zrevrange ztmp 0 -1 withscores]\n        }\n\n        test \"ZRANK/ZREVRANK basics - $encoding\" {\n            r del zranktmp\n            r zadd zranktmp 10 x\n            r zadd zranktmp 20 y\n            r zadd zranktmp 30 z\n            assert_equal 0 [r zrank zranktmp x]\n            assert_equal 1 [r zrank zranktmp y]\n            assert_equal 2 [r zrank zranktmp z]\n            assert_equal \"\" [r zrank zranktmp foo]\n            assert_equal 2 [r zrevrank zranktmp x]\n            assert_equal 1 [r zrevrank zranktmp y]\n            assert_equal 0 [r zrevrank zranktmp z]\n            assert_equal \"\" [r zrevrank zranktmp foo]\n        }\n\n        test \"ZRANK - after deletion - $encoding\" {\n            r zrem zranktmp y\n            assert_equal 0 [r zrank zranktmp x]\n            assert_equal 1 [r zrank zranktmp z]\n        }\n\n        test \"ZINCRBY - can create a new sorted set - $encoding\" {\n            r del zset\n            r zincrby zset 1 foo\n            assert_equal {foo} [r zrange zset 0 -1]\n            assert_equal 1 [r zscore zset foo]\n        }\n\n        test \"ZINCRBY - increment and decrement - $encoding\" {\n            r zincrby zset 2 foo\n            r zincrby zset 1 bar\n            assert_equal {bar foo} [r zrange zset 0 -1]\n\n            r zincrby zset 10 bar\n            r zincrby zset -5 foo\n            r zincrby zset -5 bar\n            assert_equal {foo bar} [r zrange zset 0 -1]\n\n            assert_equal -2 [r zscore zset foo]\n            assert_equal  6 [r zscore zset bar]\n        }\n\n        test \"ZINCRBY return value\" {\n            r del ztmp\n            set retval [r zincrby ztmp 1.0 x]\n            assert {$retval == 1.0}\n        }\n\n        proc create_default_zset {} {\n            create_zset zset {-inf a 1 b 2 c 3 d 4 e 5 f +inf g}\n        }\n\n        test \"ZRANGEBYSCORE/ZREVRANGEBYSCORE/ZCOUNT basics\" {\n            create_default_zset\n\n            # inclusive range\n            assert_equal {a b c} [r zrangebyscore zset -inf 2]\n            assert_equal {b c d} [r zrangebyscore zset 0 3]\n            assert_equal {d e f} [r zrangebyscore zset 3 6]\n            assert_equal {e f g} [r zrangebyscore zset 4 +inf]\n            assert_equal {c b a} [r zrevrangebyscore zset 2 -inf]\n            assert_equal {d c b} [r zrevrangebyscore zset 3 0]\n            assert_equal {f e d} [r zrevrangebyscore zset 6 3]\n            assert_equal {g f e} [r zrevrangebyscore zset +inf 4]\n            assert_equal 3 [r zcount zset 0 3]\n\n            # exclusive range\n            assert_equal {b}   [r zrangebyscore zset (-inf (2]\n            assert_equal {b c} [r zrangebyscore zset (0 (3]\n            assert_equal {e f} [r zrangebyscore zset (3 (6]\n            assert_equal {f}   [r zrangebyscore zset (4 (+inf]\n            assert_equal {b}   [r zrevrangebyscore zset (2 (-inf]\n            assert_equal {c b} [r zrevrangebyscore zset (3 (0]\n            assert_equal {f e} [r zrevrangebyscore zset (6 (3]\n            assert_equal {f}   [r zrevrangebyscore zset (+inf (4]\n            assert_equal 2 [r zcount zset (0 (3]\n\n            # test empty ranges\n            r zrem zset a\n            r zrem zset g\n\n            # inclusive\n            assert_equal {} [r zrangebyscore zset 4 2]\n            assert_equal {} [r zrangebyscore zset 6 +inf]\n            assert_equal {} [r zrangebyscore zset -inf -6]\n            assert_equal {} [r zrevrangebyscore zset +inf 6]\n            assert_equal {} [r zrevrangebyscore zset -6 -inf]\n\n            # exclusive\n            assert_equal {} [r zrangebyscore zset (4 (2]\n            assert_equal {} [r zrangebyscore zset 2 (2]\n            assert_equal {} [r zrangebyscore zset (2 2]\n            assert_equal {} [r zrangebyscore zset (6 (+inf]\n            assert_equal {} [r zrangebyscore zset (-inf (-6]\n            assert_equal {} [r zrevrangebyscore zset (+inf (6]\n            assert_equal {} [r zrevrangebyscore zset (-6 (-inf]\n\n            # empty inner range\n            assert_equal {} [r zrangebyscore zset 2.4 2.6]\n            assert_equal {} [r zrangebyscore zset (2.4 2.6]\n            assert_equal {} [r zrangebyscore zset 2.4 (2.6]\n            assert_equal {} [r zrangebyscore zset (2.4 (2.6]\n        }\n\n        test \"ZRANGEBYSCORE with WITHSCORES\" {\n            create_default_zset\n            assert_equal {b 1 c 2 d 3} [r zrangebyscore zset 0 3 withscores]\n            assert_equal {d 3 c 2 b 1} [r zrevrangebyscore zset 3 0 withscores]\n        }\n\n        test \"ZRANGEBYSCORE with LIMIT\" {\n            create_default_zset\n            assert_equal {b c}   [r zrangebyscore zset 0 10 LIMIT 0 2]\n            assert_equal {d e f} [r zrangebyscore zset 0 10 LIMIT 2 3]\n            assert_equal {d e f} [r zrangebyscore zset 0 10 LIMIT 2 10]\n            assert_equal {}      [r zrangebyscore zset 0 10 LIMIT 20 10]\n            assert_equal {f e}   [r zrevrangebyscore zset 10 0 LIMIT 0 2]\n            assert_equal {d c b} [r zrevrangebyscore zset 10 0 LIMIT 2 3]\n            assert_equal {d c b} [r zrevrangebyscore zset 10 0 LIMIT 2 10]\n            assert_equal {}      [r zrevrangebyscore zset 10 0 LIMIT 20 10]\n        }\n\n        test \"ZRANGEBYSCORE with LIMIT and WITHSCORES\" {\n            create_default_zset\n            assert_equal {e 4 f 5} [r zrangebyscore zset 2 5 LIMIT 2 3 WITHSCORES]\n            assert_equal {d 3 c 2} [r zrevrangebyscore zset 5 2 LIMIT 2 3 WITHSCORES]\n        }\n\n        test \"ZRANGEBYSCORE with non-value min or max\" {\n            assert_error \"*not*float*\" {r zrangebyscore fooz str 1}\n            assert_error \"*not*float*\" {r zrangebyscore fooz 1 str}\n            assert_error \"*not*float*\" {r zrangebyscore fooz 1 NaN}\n        }\n\n        proc create_default_lex_zset {} {\n            create_zset zset {0 alpha 0 bar 0 cool 0 down\n                              0 elephant 0 foo 0 great 0 hill\n                              0 omega}\n        }\n\n        test \"ZRANGEBYLEX/ZREVRANGEBYLEX/ZCOUNT basics\" {\n            create_default_lex_zset\n\n            # inclusive range\n            assert_equal {alpha bar cool} [r zrangebylex zset - \\[cool]\n            assert_equal {bar cool down} [r zrangebylex zset \\[bar \\[down]\n            assert_equal {great hill omega} [r zrangebylex zset \\[g +]\n            assert_equal {cool bar alpha} [r zrevrangebylex zset \\[cool -]\n            assert_equal {down cool bar} [r zrevrangebylex zset \\[down \\[bar]\n            assert_equal {omega hill great foo elephant down} [r zrevrangebylex zset + \\[d]\n            assert_equal 3 [r zlexcount zset \\[ele \\[h]\n\n            # exclusive range\n            assert_equal {alpha bar} [r zrangebylex zset - (cool]\n            assert_equal {cool} [r zrangebylex zset (bar (down]\n            assert_equal {hill omega} [r zrangebylex zset (great +]\n            assert_equal {bar alpha} [r zrevrangebylex zset (cool -]\n            assert_equal {cool} [r zrevrangebylex zset (down (bar]\n            assert_equal {omega hill} [r zrevrangebylex zset + (great]\n            assert_equal 2 [r zlexcount zset (ele (great]\n\n            # inclusive and exclusive\n            assert_equal {} [r zrangebylex zset (az (b]\n            assert_equal {} [r zrangebylex zset (z +]\n            assert_equal {} [r zrangebylex zset - \\[aaaa]\n            assert_equal {} [r zrevrangebylex zset \\[elez \\[elex]\n            assert_equal {} [r zrevrangebylex zset (hill (omega]\n        }\n\n        test \"ZRANGEBYSLEX with LIMIT\" {\n            create_default_lex_zset\n            assert_equal {alpha bar} [r zrangebylex zset - \\[cool LIMIT 0 2]\n            assert_equal {bar cool} [r zrangebylex zset - \\[cool LIMIT 1 2]\n            assert_equal {} [r zrangebylex zset \\[bar \\[down LIMIT 0 0]\n            assert_equal {} [r zrangebylex zset \\[bar \\[down LIMIT 2 0]\n            assert_equal {bar} [r zrangebylex zset \\[bar \\[down LIMIT 0 1]\n            assert_equal {cool} [r zrangebylex zset \\[bar \\[down LIMIT 1 1]\n            assert_equal {bar cool down} [r zrangebylex zset \\[bar \\[down LIMIT 0 100]\n            assert_equal {omega hill great foo elephant} [r zrevrangebylex zset + \\[d LIMIT 0 5]\n            assert_equal {omega hill great foo} [r zrevrangebylex zset + \\[d LIMIT 0 4]\n        }\n\n        test \"ZRANGEBYLEX with invalid lex range specifiers\" {\n            assert_error \"*not*string*\" {r zrangebylex fooz foo bar}\n            assert_error \"*not*string*\" {r zrangebylex fooz \\[foo bar}\n            assert_error \"*not*string*\" {r zrangebylex fooz foo \\[bar}\n            assert_error \"*not*string*\" {r zrangebylex fooz +x \\[bar}\n            assert_error \"*not*string*\" {r zrangebylex fooz -x \\[bar}\n        }\n\n        test \"ZREMRANGEBYSCORE basics\" {\n            proc remrangebyscore {min max} {\n                create_zset zset {1 a 2 b 3 c 4 d 5 e}\n                assert_equal 1 [r exists zset]\n                r zremrangebyscore zset $min $max\n            }\n\n            # inner range\n            assert_equal 3 [remrangebyscore 2 4]\n            assert_equal {a e} [r zrange zset 0 -1]\n\n            # start underflow\n            assert_equal 1 [remrangebyscore -10 1]\n            assert_equal {b c d e} [r zrange zset 0 -1]\n\n            # end overflow\n            assert_equal 1 [remrangebyscore 5 10]\n            assert_equal {a b c d} [r zrange zset 0 -1]\n\n            # switch min and max\n            assert_equal 0 [remrangebyscore 4 2]\n            assert_equal {a b c d e} [r zrange zset 0 -1]\n\n            # -inf to mid\n            assert_equal 3 [remrangebyscore -inf 3]\n            assert_equal {d e} [r zrange zset 0 -1]\n\n            # mid to +inf\n            assert_equal 3 [remrangebyscore 3 +inf]\n            assert_equal {a b} [r zrange zset 0 -1]\n\n            # -inf to +inf\n            assert_equal 5 [remrangebyscore -inf +inf]\n            assert_equal {} [r zrange zset 0 -1]\n\n            # exclusive min\n            assert_equal 4 [remrangebyscore (1 5]\n            assert_equal {a} [r zrange zset 0 -1]\n            assert_equal 3 [remrangebyscore (2 5]\n            assert_equal {a b} [r zrange zset 0 -1]\n\n            # exclusive max\n            assert_equal 4 [remrangebyscore 1 (5]\n            assert_equal {e} [r zrange zset 0 -1]\n            assert_equal 3 [remrangebyscore 1 (4]\n            assert_equal {d e} [r zrange zset 0 -1]\n\n            # exclusive min and max\n            assert_equal 3 [remrangebyscore (1 (5]\n            assert_equal {a e} [r zrange zset 0 -1]\n\n            # destroy when empty\n            assert_equal 5 [remrangebyscore 1 5]\n            assert_equal 0 [r exists zset]\n        }\n\n        test \"ZREMRANGEBYSCORE with non-value min or max\" {\n            assert_error \"*not*float*\" {r zremrangebyscore fooz str 1}\n            assert_error \"*not*float*\" {r zremrangebyscore fooz 1 str}\n            assert_error \"*not*float*\" {r zremrangebyscore fooz 1 NaN}\n        }\n\n        test \"ZREMRANGEBYRANK basics\" {\n            proc remrangebyrank {min max} {\n                create_zset zset {1 a 2 b 3 c 4 d 5 e}\n                assert_equal 1 [r exists zset]\n                r zremrangebyrank zset $min $max\n            }\n\n            # inner range\n            assert_equal 3 [remrangebyrank 1 3]\n            assert_equal {a e} [r zrange zset 0 -1]\n\n            # start underflow\n            assert_equal 1 [remrangebyrank -10 0]\n            assert_equal {b c d e} [r zrange zset 0 -1]\n\n            # start overflow\n            assert_equal 0 [remrangebyrank 10 -1]\n            assert_equal {a b c d e} [r zrange zset 0 -1]\n\n            # end underflow\n            assert_equal 0 [remrangebyrank 0 -10]\n            assert_equal {a b c d e} [r zrange zset 0 -1]\n\n            # end overflow\n            assert_equal 5 [remrangebyrank 0 10]\n            assert_equal {} [r zrange zset 0 -1]\n\n            # destroy when empty\n            assert_equal 5 [remrangebyrank 0 4]\n            assert_equal 0 [r exists zset]\n        }\n\n        test \"ZUNIONSTORE against non-existing key doesn't set destination - $encoding\" {\n            r del zseta\n            assert_equal 0 [r zunionstore dst_key 1 zseta]\n            assert_equal 0 [r exists dst_key]\n        }\n\n        test \"ZUNIONSTORE with empty set - $encoding\" {\n            r del zseta zsetb\n            r zadd zseta 1 a\n            r zadd zseta 2 b\n            r zunionstore zsetc 2 zseta zsetb\n            r zrange zsetc 0 -1 withscores\n        } {a 1 b 2}\n\n        test \"ZUNIONSTORE basics - $encoding\" {\n            r del zseta zsetb zsetc\n            r zadd zseta 1 a\n            r zadd zseta 2 b\n            r zadd zseta 3 c\n            r zadd zsetb 1 b\n            r zadd zsetb 2 c\n            r zadd zsetb 3 d\n\n            assert_equal 4 [r zunionstore zsetc 2 zseta zsetb]\n            assert_equal {a 1 b 3 d 3 c 5} [r zrange zsetc 0 -1 withscores]\n        }\n\n        test \"ZUNIONSTORE with weights - $encoding\" {\n            assert_equal 4 [r zunionstore zsetc 2 zseta zsetb weights 2 3]\n            assert_equal {a 2 b 7 d 9 c 12} [r zrange zsetc 0 -1 withscores]\n        }\n\n        test \"ZUNIONSTORE with a regular set and weights - $encoding\" {\n            r del seta\n            r sadd seta a\n            r sadd seta b\n            r sadd seta c\n\n            assert_equal 4 [r zunionstore zsetc 2 seta zsetb weights 2 3]\n            assert_equal {a 2 b 5 c 8 d 9} [r zrange zsetc 0 -1 withscores]\n        }\n\n        test \"ZUNIONSTORE with AGGREGATE MIN - $encoding\" {\n            assert_equal 4 [r zunionstore zsetc 2 zseta zsetb aggregate min]\n            assert_equal {a 1 b 1 c 2 d 3} [r zrange zsetc 0 -1 withscores]\n        }\n\n        test \"ZUNIONSTORE with AGGREGATE MAX - $encoding\" {\n            assert_equal 4 [r zunionstore zsetc 2 zseta zsetb aggregate max]\n            assert_equal {a 1 b 2 c 3 d 3} [r zrange zsetc 0 -1 withscores]\n        }\n\n        test \"ZINTERSTORE basics - $encoding\" {\n            assert_equal 2 [r zinterstore zsetc 2 zseta zsetb]\n            assert_equal {b 3 c 5} [r zrange zsetc 0 -1 withscores]\n        }\n\n        test \"ZINTERSTORE with weights - $encoding\" {\n            assert_equal 2 [r zinterstore zsetc 2 zseta zsetb weights 2 3]\n            assert_equal {b 7 c 12} [r zrange zsetc 0 -1 withscores]\n        }\n\n        test \"ZINTERSTORE with a regular set and weights - $encoding\" {\n            r del seta\n            r sadd seta a\n            r sadd seta b\n            r sadd seta c\n            assert_equal 2 [r zinterstore zsetc 2 seta zsetb weights 2 3]\n            assert_equal {b 5 c 8} [r zrange zsetc 0 -1 withscores]\n        }\n\n        test \"ZINTERSTORE with AGGREGATE MIN - $encoding\" {\n            assert_equal 2 [r zinterstore zsetc 2 zseta zsetb aggregate min]\n            assert_equal {b 1 c 2} [r zrange zsetc 0 -1 withscores]\n        }\n\n        test \"ZINTERSTORE with AGGREGATE MAX - $encoding\" {\n            assert_equal 2 [r zinterstore zsetc 2 zseta zsetb aggregate max]\n            assert_equal {b 2 c 3} [r zrange zsetc 0 -1 withscores]\n        }\n\n        foreach cmd {ZUNIONSTORE ZINTERSTORE} {\n            test \"$cmd with +inf/-inf scores - $encoding\" {\n                r del zsetinf1 zsetinf2\n\n                r zadd zsetinf1 +inf key\n                r zadd zsetinf2 +inf key\n                r $cmd zsetinf3 2 zsetinf1 zsetinf2\n                assert_equal inf [r zscore zsetinf3 key]\n\n                r zadd zsetinf1 -inf key\n                r zadd zsetinf2 +inf key\n                r $cmd zsetinf3 2 zsetinf1 zsetinf2\n                assert_equal 0 [r zscore zsetinf3 key]\n\n                r zadd zsetinf1 +inf key\n                r zadd zsetinf2 -inf key\n                r $cmd zsetinf3 2 zsetinf1 zsetinf2\n                assert_equal 0 [r zscore zsetinf3 key]\n\n                r zadd zsetinf1 -inf key\n                r zadd zsetinf2 -inf key\n                r $cmd zsetinf3 2 zsetinf1 zsetinf2\n                assert_equal -inf [r zscore zsetinf3 key]\n            }\n\n            test \"$cmd with NaN weights $encoding\" {\n                r del zsetinf1 zsetinf2\n\n                r zadd zsetinf1 1.0 key\n                r zadd zsetinf2 1.0 key\n                assert_error \"*weight*not*float*\" {\n                    r $cmd zsetinf3 2 zsetinf1 zsetinf2 weights nan nan\n                }\n            }\n        }\n    }\n\n    basics ziplist\n    basics skiplist\n\n    test {ZINTERSTORE regression with two sets, intset+hashtable} {\n        r del seta setb setc\n        r sadd set1 a\n        r sadd set2 10\n        r zinterstore set3 2 set1 set2\n    } {0}\n\n    test {ZUNIONSTORE regression, should not create NaN in scores} {\n        r zadd z -inf neginf\n        r zunionstore out 1 z weights 0\n        r zrange out 0 -1 withscores\n    } {neginf 0}\n\n    test {ZINTERSTORE #516 regression, mixed sets and ziplist zsets} {\n        r sadd one 100 101 102 103\n        r sadd two 100 200 201 202\n        r zadd three 1 500 1 501 1 502 1 503 1 100\n        r zinterstore to_here 3 one two three WEIGHTS 0 0 1\n        r zrange to_here 0 -1\n    } {100}\n\n    test {ZUNIONSTORE result is sorted} {\n        # Create two sets with common and not common elements, perform\n        # the UNION, check that elements are still sorted.\n        r del one two dest\n        set cmd1 [list r zadd one]\n        set cmd2 [list r zadd two]\n        for {set j 0} {$j < 1000} {incr j} {\n            lappend cmd1 [expr rand()] [randomInt 1000]\n            lappend cmd2 [expr rand()] [randomInt 1000]\n        }\n        {*}$cmd1\n        {*}$cmd2\n        assert {[r zcard one] > 100}\n        assert {[r zcard two] > 100}\n        r zunionstore dest 2 one two\n        set oldscore 0\n        foreach {ele score} [r zrange dest 0 -1 withscores] {\n            assert {$score >= $oldscore}\n            set oldscore $score\n        }\n    }\n\n    proc stressers {encoding} {\n        if {$encoding == \"ziplist\"} {\n            # Little extra to allow proper fuzzing in the sorting stresser\n            r config set zset-max-ziplist-entries 256\n            r config set zset-max-ziplist-value 64\n            set elements 128\n        } elseif {$encoding == \"skiplist\"} {\n            r config set zset-max-ziplist-entries 0\n            r config set zset-max-ziplist-value 0\n            if {$::accurate} {set elements 1000} else {set elements 100}\n        } else {\n            puts \"Unknown sorted set encoding\"\n            exit\n        }\n\n        test \"ZSCORE - $encoding\" {\n            r del zscoretest\n            set aux {}\n            for {set i 0} {$i < $elements} {incr i} {\n                set score [expr rand()]\n                lappend aux $score\n                r zadd zscoretest $score $i\n            }\n\n            assert_encoding $encoding zscoretest\n            for {set i 0} {$i < $elements} {incr i} {\n                assert_equal [lindex $aux $i] [r zscore zscoretest $i]\n            }\n        }\n\n        test \"ZSCORE after a DEBUG RELOAD - $encoding\" {\n            r del zscoretest\n            set aux {}\n            for {set i 0} {$i < $elements} {incr i} {\n                set score [expr rand()]\n                lappend aux $score\n                r zadd zscoretest $score $i\n            }\n\n            r debug reload\n            assert_encoding $encoding zscoretest\n            for {set i 0} {$i < $elements} {incr i} {\n                assert_equal [lindex $aux $i] [r zscore zscoretest $i]\n            }\n        }\n\n        test \"ZSET sorting stresser - $encoding\" {\n            set delta 0\n            for {set test 0} {$test < 2} {incr test} {\n                unset -nocomplain auxarray\n                array set auxarray {}\n                set auxlist {}\n                r del myzset\n                for {set i 0} {$i < $elements} {incr i} {\n                    if {$test == 0} {\n                        set score [expr rand()]\n                    } else {\n                        set score [expr int(rand()*10)]\n                    }\n                    set auxarray($i) $score\n                    r zadd myzset $score $i\n                    # Random update\n                    if {[expr rand()] < .2} {\n                        set j [expr int(rand()*1000)]\n                        if {$test == 0} {\n                            set score [expr rand()]\n                        } else {\n                            set score [expr int(rand()*10)]\n                        }\n                        set auxarray($j) $score\n                        r zadd myzset $score $j\n                    }\n                }\n                foreach {item score} [array get auxarray] {\n                    lappend auxlist [list $score $item]\n                }\n                set sorted [lsort -command zlistAlikeSort $auxlist]\n                set auxlist {}\n                foreach x $sorted {\n                    lappend auxlist [lindex $x 1]\n                }\n\n                assert_encoding $encoding myzset\n                set fromredis [r zrange myzset 0 -1]\n                set delta 0\n                for {set i 0} {$i < [llength $fromredis]} {incr i} {\n                    if {[lindex $fromredis $i] != [lindex $auxlist $i]} {\n                        incr delta\n                    }\n                }\n            }\n            assert_equal 0 $delta\n        }\n\n        test \"ZRANGEBYSCORE fuzzy test, 100 ranges in $elements element sorted set - $encoding\" {\n            set err {}\n            r del zset\n            for {set i 0} {$i < $elements} {incr i} {\n                r zadd zset [expr rand()] $i\n            }\n\n            assert_encoding $encoding zset\n            for {set i 0} {$i < 100} {incr i} {\n                set min [expr rand()]\n                set max [expr rand()]\n                if {$min > $max} {\n                    set aux $min\n                    set min $max\n                    set max $aux\n                }\n                set low [r zrangebyscore zset -inf $min]\n                set ok [r zrangebyscore zset $min $max]\n                set high [r zrangebyscore zset $max +inf]\n                set lowx [r zrangebyscore zset -inf ($min]\n                set okx [r zrangebyscore zset ($min ($max]\n                set highx [r zrangebyscore zset ($max +inf]\n\n                if {[r zcount zset -inf $min] != [llength $low]} {\n                    append err \"Error, len does not match zcount\\n\"\n                }\n                if {[r zcount zset $min $max] != [llength $ok]} {\n                    append err \"Error, len does not match zcount\\n\"\n                }\n                if {[r zcount zset $max +inf] != [llength $high]} {\n                    append err \"Error, len does not match zcount\\n\"\n                }\n                if {[r zcount zset -inf ($min] != [llength $lowx]} {\n                    append err \"Error, len does not match zcount\\n\"\n                }\n                if {[r zcount zset ($min ($max] != [llength $okx]} {\n                    append err \"Error, len does not match zcount\\n\"\n                }\n                if {[r zcount zset ($max +inf] != [llength $highx]} {\n                    append err \"Error, len does not match zcount\\n\"\n                }\n\n                foreach x $low {\n                    set score [r zscore zset $x]\n                    if {$score > $min} {\n                        append err \"Error, score for $x is $score > $min\\n\"\n                    }\n                }\n                foreach x $lowx {\n                    set score [r zscore zset $x]\n                    if {$score >= $min} {\n                        append err \"Error, score for $x is $score >= $min\\n\"\n                    }\n                }\n                foreach x $ok {\n                    set score [r zscore zset $x]\n                    if {$score < $min || $score > $max} {\n                        append err \"Error, score for $x is $score outside $min-$max range\\n\"\n                    }\n                }\n                foreach x $okx {\n                    set score [r zscore zset $x]\n                    if {$score <= $min || $score >= $max} {\n                        append err \"Error, score for $x is $score outside $min-$max open range\\n\"\n                    }\n                }\n                foreach x $high {\n                    set score [r zscore zset $x]\n                    if {$score < $max} {\n                        append err \"Error, score for $x is $score < $max\\n\"\n                    }\n                }\n                foreach x $highx {\n                    set score [r zscore zset $x]\n                    if {$score <= $max} {\n                        append err \"Error, score for $x is $score <= $max\\n\"\n                    }\n                }\n            }\n            assert_equal {} $err\n        }\n\n        test \"ZRANGEBYLEX fuzzy test, 100 ranges in $elements element sorted set - $encoding\" {\n            set lexset {}\n            r del zset\n            for {set j 0} {$j < $elements} {incr j} {\n                set e [randstring 0 30 alpha]\n                lappend lexset $e\n                r zadd zset 0 $e\n            }\n            set lexset [lsort -unique $lexset]\n            for {set j 0} {$j < 100} {incr j} {\n                set min [randstring 0 30 alpha]\n                set max [randstring 0 30 alpha]\n                set mininc [randomInt 2]\n                set maxinc [randomInt 2]\n                if {$mininc} {set cmin \"\\[$min\"} else {set cmin \"($min\"}\n                if {$maxinc} {set cmax \"\\[$max\"} else {set cmax \"($max\"}\n                set rev [randomInt 2]\n                if {$rev} {\n                    set cmd zrevrangebylex\n                } else {\n                    set cmd zrangebylex\n                }\n\n                # Make sure data is the same in both sides\n                assert {[r zrange zset 0 -1] eq $lexset}\n\n                # Get the Redis output\n                set output [r $cmd zset $cmin $cmax]\n                if {$rev} {\n                    set outlen [r zlexcount zset $cmax $cmin]\n                } else {\n                    set outlen [r zlexcount zset $cmin $cmax]\n                }\n\n                # Compute the same output via Tcl\n                set o {}\n                set copy $lexset\n                if {(!$rev && [string compare $min $max] > 0) ||\n                    ($rev && [string compare $max $min] > 0)} {\n                    # Empty output when ranges are inverted.\n                } else {\n                    if {$rev} {\n                        # Invert the Tcl array using Redis itself.\n                        set copy [r zrevrange zset 0 -1]\n                        # Invert min / max as well\n                        lassign [list $min $max $mininc $maxinc] \\\n                            max min maxinc mininc\n                    }\n                    foreach e $copy {\n                        set mincmp [string compare $e $min]\n                        set maxcmp [string compare $e $max]\n                        if {\n                             ($mininc && $mincmp >= 0 || !$mininc && $mincmp > 0)\n                             &&\n                             ($maxinc && $maxcmp <= 0 || !$maxinc && $maxcmp < 0)\n                        } {\n                            lappend o $e\n                        }\n                    }\n                }\n                assert {$o eq $output}\n                assert {$outlen eq [llength $output]}\n            }\n        }\n\n        test \"ZREMRANGEBYLEX fuzzy test, 100 ranges in $elements element sorted set - $encoding\" {\n            set lexset {}\n            r del zset zsetcopy\n            for {set j 0} {$j < $elements} {incr j} {\n                set e [randstring 0 30 alpha]\n                lappend lexset $e\n                r zadd zset 0 $e\n            }\n            set lexset [lsort -unique $lexset]\n            for {set j 0} {$j < 100} {incr j} {\n                # Copy...\n                r zunionstore zsetcopy 1 zset\n                set lexsetcopy $lexset\n\n                set min [randstring 0 30 alpha]\n                set max [randstring 0 30 alpha]\n                set mininc [randomInt 2]\n                set maxinc [randomInt 2]\n                if {$mininc} {set cmin \"\\[$min\"} else {set cmin \"($min\"}\n                if {$maxinc} {set cmax \"\\[$max\"} else {set cmax \"($max\"}\n\n                # Make sure data is the same in both sides\n                assert {[r zrange zset 0 -1] eq $lexset}\n\n                # Get the range we are going to remove\n                set torem [r zrangebylex zset $cmin $cmax]\n                set toremlen [r zlexcount zset $cmin $cmax]\n                r zremrangebylex zsetcopy $cmin $cmax\n                set output [r zrange zsetcopy 0 -1]\n\n                # Remove the range with Tcl from the original list\n                if {$toremlen} {\n                    set first [lsearch -exact $lexsetcopy [lindex $torem 0]]\n                    set last [expr {$first+$toremlen-1}]\n                    set lexsetcopy [lreplace $lexsetcopy $first $last]\n                }\n                assert {$lexsetcopy eq $output}\n            }\n        }\n\n        test \"ZSETs skiplist implementation backlink consistency test - $encoding\" {\n            set diff 0\n            for {set j 0} {$j < $elements} {incr j} {\n                r zadd myzset [expr rand()] \"Element-$j\"\n                r zrem myzset \"Element-[expr int(rand()*$elements)]\"\n            }\n\n            assert_encoding $encoding myzset\n            set l1 [r zrange myzset 0 -1]\n            set l2 [r zrevrange myzset 0 -1]\n            for {set j 0} {$j < [llength $l1]} {incr j} {\n                if {[lindex $l1 $j] ne [lindex $l2 end-$j]} {\n                    incr diff\n                }\n            }\n            assert_equal 0 $diff\n        }\n\n        test \"ZSETs ZRANK augmented skip list stress testing - $encoding\" {\n            set err {}\n            r del myzset\n            for {set k 0} {$k < 2000} {incr k} {\n                set i [expr {$k % $elements}]\n                if {[expr rand()] < .2} {\n                    r zrem myzset $i\n                } else {\n                    set score [expr rand()]\n                    r zadd myzset $score $i\n                    assert_encoding $encoding myzset\n                }\n\n                set card [r zcard myzset]\n                if {$card > 0} {\n                    set index [randomInt $card]\n                    set ele [lindex [r zrange myzset $index $index] 0]\n                    set rank [r zrank myzset $ele]\n                    if {$rank != $index} {\n                        set err \"$ele RANK is wrong! ($rank != $index)\"\n                        break\n                    }\n                }\n            }\n            assert_equal {} $err\n        }\n    }\n\n    tags {\"slow\"} {\n        stressers ziplist\n        stressers skiplist\n    }\n}\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/utils/build-static-symbols.tcl",
    "content": "# Build a symbol table for static symbols of redis.c\n# Useful to get stack traces on segfault without a debugger. See redis.c\n# for more information.\n#\n# Copyright(C) 2009 Salvatore Sanfilippo, under the BSD license.\n\nset fd [open redis.c]\nset symlist {}\nwhile {[gets $fd line] != -1} {\n    if {[regexp {^static +[A-z0-9]+[ *]+([A-z0-9]*)\\(} $line - sym]} {\n        lappend symlist $sym\n    }\n}\nset symlist [lsort -unique $symlist]\nputs \"static struct redisFunctionSym symsTable\\[\\] = {\"\nforeach sym $symlist {\n    puts \"{\\\"$sym\\\",(unsigned long)$sym},\"\n}\nputs \"{NULL,0}\"\nputs \"};\"\n\nclose $fd\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/utils/cluster_fail_time.tcl",
    "content": "# This simple script is used in order to estimate the average PFAIL->FAIL\n# state switch after a failure.\n\nset ::sleep_time 10     ; # How much to sleep to trigger PFAIL.\nset ::fail_port 30016   ; # Node to put in sleep.\nset ::other_port 30001  ; # Node to use to monitor the flag switch.\n\nproc avg vector {\n    set sum 0.0\n    foreach x $vector {\n        set sum [expr {$sum+$x}]\n    }\n    expr {$sum/[llength $vector]}\n}\n\nset samples {}\nwhile 1 {\n    exec redis-cli -p $::fail_port debug sleep $::sleep_time > /dev/null &\n\n    # Wait for fail? to appear.\n    while 1 {\n        set output [exec redis-cli -p $::other_port cluster nodes]\n        if {[string match {*fail\\?*} $output]} break\n        after 100\n    }\n\n    puts \"FAIL?\"\n    set start [clock milliseconds]\n\n    # Wait for fail? to disappear.\n    while 1 {\n        set output [exec redis-cli -p $::other_port cluster nodes]\n        if {![string match {*fail\\?*} $output]} break\n        after 100\n    }\n\n    puts \"FAIL\"\n    set now [clock milliseconds]\n    set elapsed [expr {$now-$start}]\n    puts $elapsed\n    lappend samples $elapsed\n\n    puts \"AVG([llength $samples]): [avg $samples]\"\n\n    # Wait for the instance to be available again.\n    exec redis-cli -p $::fail_port ping\n\n    # Wait for the fail flag to be cleared.\n    after 2000\n}\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/utils/corrupt_rdb.c",
    "content": "/* Trivia program to corrupt an RDB file in order to check the RDB check\n * program behavior and effectiveness.\n *\n * Copyright (C) 2016 Salvatore Sanfilippo.\n * This software is released in the 3-clause BSD license. */\n\n#include <stdio.h>\n#include <fcntl.h>\n#include <sys/stat.h>\n#include <stdlib.h>\n#include <unistd.h>\n#include <time.h>\n\nint main(int argc, char **argv) {\n    struct stat stat;\n    int fd, cycles;\n\n    if (argc != 3) {\n        fprintf(stderr,\"Usage: <filename> <cycles>\\n\");\n        exit(1);\n    }\n\n    srand(time(NULL));\n    cycles = atoi(argv[2]);\n    fd = open(\"dump.rdb\",O_RDWR);\n    if (fd == -1) {\n        perror(\"open\");\n        exit(1);\n    }\n    fstat(fd,&stat);\n\n    while(cycles--) {\n        unsigned char buf[32];\n        unsigned long offset = rand()%stat.st_size;\n        int writelen = 1+rand()%31;\n        int j;\n\n        for (j = 0; j < writelen; j++) buf[j] = (char)rand();\n        lseek(fd,offset,SEEK_SET);\n        printf(\"Writing %d bytes at offset %lu\\n\", writelen, offset);\n        write(fd,buf,writelen);\n    }\n    return 0;\n}\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/utils/create-cluster/.gitignore",
    "content": "config.sh\n*.rdb\n*.aof\n*.conf\n*.log\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/utils/create-cluster/README",
    "content": "Create-custer is a small script used to easily start a big number of Redis\ninstances configured to run in cluster mode. Its main goal is to allow manual\ntesting in a condition which is not easy to replicate with the Redis cluster\nunit tests, for example when a lot of instances are needed in order to trigger\na give bug.\n\nThe tool can also be used just to easily create a number of instances in a\nRedis Cluster in order to experiment a bit with the system.\n\nUSAGE\n---\n\nTo create a cluster, follow this steps:\n\n1. Edit create-cluster and change the start / end port, depending on the\nnumber of instances you want to create.\n2. Use \"./create-cluster start\" in order to run the instances.\n3. Use \"./create-cluster create\" in order to execute redis-trib create, so that\nan actual Redis cluster will be created.\n4. Now you are ready to play with the cluster. AOF files and logs for each instances are created in the current directory.\n\nIn order to stop a cluster:\n\n1. Use \"./craete-cluster stop\" to stop all the instances. After you stopped the instances you can use \"./create-cluster start\" to restart them if you change ideas.\n2. Use \"./create-cluster clean\" to remove all the AOF / log files to restat with a clean environment.\n\nUse the command \"./create-cluster help\" to get the full list of features.\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/utils/create-cluster/create-cluster",
    "content": "#!/bin/bash\n\n# Settings\nPORT=30000\nTIMEOUT=2000\nNODES=6\nREPLICAS=1\n\n# You may want to put the above config parameters into config.sh in order to\n# override the defaults without modifying this script.\n\nif [ -a config.sh ]\nthen\n    source \"config.sh\"\nfi\n\n# Computed vars\nENDPORT=$((PORT+NODES))\n\nif [ \"$1\" == \"start\" ]\nthen\n    while [ $((PORT < ENDPORT)) != \"0\" ]; do\n        PORT=$((PORT+1))\n        echo \"Starting $PORT\"\n        ../../src/redis-server --port $PORT --cluster-enabled yes --cluster-config-file nodes-${PORT}.conf --cluster-node-timeout $TIMEOUT --appendonly yes --appendfilename appendonly-${PORT}.aof --dbfilename dump-${PORT}.rdb --logfile ${PORT}.log --daemonize yes\n    done\n    exit 0\nfi\n\nif [ \"$1\" == \"create\" ]\nthen\n    HOSTS=\"\"\n    while [ $((PORT < ENDPORT)) != \"0\" ]; do\n        PORT=$((PORT+1))\n        HOSTS=\"$HOSTS 127.0.0.1:$PORT\"\n    done\n    ../../src/redis-trib.rb create --replicas $REPLICAS $HOSTS\n    exit 0\nfi\n\nif [ \"$1\" == \"stop\" ]\nthen\n    while [ $((PORT < ENDPORT)) != \"0\" ]; do\n        PORT=$((PORT+1))\n        echo \"Stopping $PORT\"\n        ../../src/redis-cli -p $PORT shutdown nosave\n    done\n    exit 0\nfi\n\nif [ \"$1\" == \"watch\" ]\nthen\n    PORT=$((PORT+1))\n    while [ 1 ]; do\n        clear\n        date\n        ../../src/redis-cli -p $PORT cluster nodes | head -30\n        sleep 1\n    done\n    exit 0\nfi\n\nif [ \"$1\" == \"tail\" ]\nthen\n    INSTANCE=$2\n    PORT=$((PORT+INSTANCE))\n    tail -f ${PORT}.log\n    exit 0\nfi\n\nif [ \"$1\" == \"call\" ]\nthen\n    while [ $((PORT < ENDPORT)) != \"0\" ]; do\n        PORT=$((PORT+1))\n        ../../src/redis-cli -p $PORT $2 $3 $4 $5 $6 $7 $8 $9\n    done\n    exit 0\nfi\n\nif [ \"$1\" == \"clean\" ]\nthen\n    rm -rf *.log\n    rm -rf appendonly*.aof\n    rm -rf dump*.rdb\n    rm -rf nodes*.conf\n    exit 0\nfi\n\necho \"Usage: $0 [start|create|stop|watch|tail|clean]\"\necho \"start       -- Launch Redis Cluster instances.\"\necho \"create      -- Create a cluster using redis-trib create.\"\necho \"stop        -- Stop Redis Cluster instances.\"\necho \"watch       -- Show CLUSTER NODES output (first 30 lines) of first node.\"\necho \"tail <id>   -- Run tail -f of instance at base port + ID.\"\necho \"clean       -- Remove all instances data, logs, configs.\"\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/utils/generate-command-help.rb",
    "content": "#!/usr/bin/env ruby\n\nGROUPS = [\n  \"generic\",\n  \"string\",\n  \"list\",\n  \"set\",\n  \"sorted_set\",\n  \"hash\",\n  \"pubsub\",\n  \"transactions\",\n  \"connection\",\n  \"server\",\n  \"scripting\",\n  \"hyperloglog\",\n  \"cluster\",\n  \"geo\"\n].freeze\n\nGROUPS_BY_NAME = Hash[*\n  GROUPS.each_with_index.map do |n,i|\n    [n,i]\n  end.flatten\n].freeze\n\ndef argument arg\n  name = arg[\"name\"].is_a?(Array) ? arg[\"name\"].join(\" \") : arg[\"name\"]\n  name = arg[\"enum\"].join \"|\" if \"enum\" == arg[\"type\"]\n  name = arg[\"command\"] + \" \" + name if arg[\"command\"]\n  if arg[\"multiple\"]\n    name = \"#{name} [#{name} ...]\"\n  end\n  if arg[\"optional\"]\n    name = \"[#{name}]\"\n  end\n  name\nend\n\ndef arguments command\n  return \"-\" unless command[\"arguments\"]\n  command[\"arguments\"].map do |arg|\n    argument arg\n  end.join \" \"\nend\n\ndef commands\n  return @commands if @commands\n\n  require \"rubygems\"\n  require \"net/http\"\n  require \"net/https\"\n  require \"json\"\n  require \"uri\"\n\n  url = URI.parse \"https://raw.githubusercontent.com/antirez/redis-doc/master/commands.json\"\n  client = Net::HTTP.new url.host, url.port\n  client.use_ssl = true\n  response = client.get url.path\n  if response.is_a?(Net::HTTPSuccess)\n    @commands = JSON.parse(response.body)\n  else\n    response.error!\n  end\nend\n\ndef generate_groups\n  GROUPS.map do |n|\n    \"\\\"#{n}\\\"\"\n  end.join(\",\\n    \");\nend\n\ndef generate_commands\n  commands.to_a.sort do |x,y|\n    x[0] <=> y[0]\n  end.map do |key, command|\n    group = GROUPS_BY_NAME[command[\"group\"]]\n    if group.nil?\n      STDERR.puts \"Please update groups array in #{__FILE__}\"\n      raise \"Unknown group #{command[\"group\"]}\"\n    end\n\n    ret = <<-SPEC\n{ \"#{key}\",\n    \"#{arguments(command)}\",\n    \"#{command[\"summary\"]}\",\n    #{group},\n    \"#{command[\"since\"]}\" }\n    SPEC\n    ret.strip\n  end.join(\",\\n    \")\nend\n\n# Write to stdout\nputs <<-HELP_H\n/* Automatically generated by #{__FILE__}, do not edit. */\n\n#ifndef __REDIS_HELP_H\n#define __REDIS_HELP_H\n\nstatic char *commandGroups[] = {\n    #{generate_groups}\n};\n\nstruct commandHelp {\n  char *name;\n  char *params;\n  char *summary;\n  int group;\n  char *since;\n} commandHelp[] = {\n    #{generate_commands}\n};\n\n#endif\nHELP_H\n\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/utils/hashtable/README",
    "content": "Hash table implementation related utilities.\n\nrehashing.c\n---\n\nVisually show buckets in the two hash tables between rehashings. Also stress\ntest getRandomKeys() implementation, that may actually disappear from\nRedis soon, however visualizaiton some code is reusable in new bugs\ninvestigation.\n\nCompile with:\n\n    cc -I ../../src/ rehashing.c ../../src/zmalloc.c ../../src/dict.c -o rehashing_test\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/utils/hashtable/rehashing.c",
    "content": "#include \"redis.h\"\n#include \"dict.h\"\n\nvoid _redisAssert(char *x, char *y, int l) {\n    printf(\"ASSERT: %s %s %d\\n\",x,y,l);\n    exit(1);\n}\n\nunsigned int dictKeyHash(const void *keyp) {\n    unsigned long key = (unsigned long)keyp;\n    key = dictGenHashFunction(&key,sizeof(key));\n    key += ~(key << 15);\n    key ^=  (key >> 10);\n    key +=  (key << 3);\n    key ^=  (key >> 6);\n    key += ~(key << 11);\n    key ^=  (key >> 16);\n    return key;\n}\n\nint dictKeyCompare(void *privdata, const void *key1, const void *key2) {\n    unsigned long k1 = (unsigned long)key1;\n    unsigned long k2 = (unsigned long)key2;\n    return k1 == k2;\n}\n\ndictType dictTypeTest = {\n    dictKeyHash,                   /* hash function */\n    NULL,                          /* key dup */\n    NULL,                          /* val dup */\n    dictKeyCompare,                /* key compare */\n    NULL,                          /* key destructor */\n    NULL                           /* val destructor */\n};\n\nvoid showBuckets(dictht ht) {\n    if (ht.table == NULL) {\n        printf(\"NULL\\n\");\n    } else {\n        int j;\n        for (j = 0; j < ht.size; j++) {\n            printf(\"%c\", ht.table[j] ? '1' : '0');\n        }\n        printf(\"\\n\");\n    }\n}\n\nvoid show(dict *d) {\n    int j;\n    if (d->rehashidx != -1) {\n        printf(\"rhidx: \");\n        for (j = 0; j < d->rehashidx; j++)\n            printf(\".\");\n        printf(\"|\\n\");\n    }\n    printf(\"ht[0]: \");\n    showBuckets(d->ht[0]);\n    printf(\"ht[1]: \");\n    showBuckets(d->ht[1]);\n    printf(\"\\n\");\n}\n\nint sortPointers(const void *a, const void *b) {\n    unsigned long la, lb;\n\n    la = (long) (*((dictEntry**)a));\n    lb = (long) (*((dictEntry**)b));\n    return la-lb;\n}\n\nvoid stressGetKeys(dict *d, int times, int *perfect_run, int *approx_run) {\n    int j;\n\n    dictEntry **des = zmalloc(sizeof(dictEntry*)*dictSize(d));\n    for (j = 0; j < times; j++) {\n        int requested = rand() % (dictSize(d)+1);\n        int returned = dictGetSomeKeys(d, des, requested);\n        int dup = 0;\n\n        qsort(des,returned,sizeof(dictEntry*),sortPointers);\n        if (returned > 1) {\n            int i;\n            for (i = 0; i < returned-1; i++) {\n                if (des[i] == des[i+1]) dup++;\n            }\n        }\n\n        if (requested == returned && dup == 0) {\n            (*perfect_run)++;\n        } else {\n            (*approx_run)++;\n            printf(\"Requested, returned, duplicated: %d %d %d\\n\",\n                requested, returned, dup);\n        }\n    }\n    zfree(des);\n}\n\n#define MAX1 120\n#define MAX2 1000\nint main(void) {\n    dict *d = dictCreate(&dictTypeTest,NULL);\n    unsigned long i;\n    srand(time(NULL));\n\n    for (i = 0; i < MAX1; i++) {\n        dictAdd(d,(void*)i,NULL);\n        show(d);\n    }\n    printf(\"Size: %d\\n\", (int)dictSize(d));\n\n    for (i = 0; i < MAX1; i++) {\n        dictDelete(d,(void*)i);\n        dictResize(d);\n        show(d);\n    }\n    dictRelease(d);\n\n    d = dictCreate(&dictTypeTest,NULL);\n\n    printf(\"Stress testing dictGetSomeKeys\\n\");\n    int perfect_run = 0, approx_run = 0;\n\n    for (i = 0; i < MAX2; i++) {\n        dictAdd(d,(void*)i,NULL);\n        stressGetKeys(d,100,&perfect_run,&approx_run);\n    }\n\n    for (i = 0; i < MAX2; i++) {\n        dictDelete(d,(void*)i);\n        dictResize(d);\n        stressGetKeys(d,100,&perfect_run,&approx_run);\n    }\n\n    printf(\"dictGetSomeKey, %d perfect runs, %d approximated runs\\n\",\n        perfect_run, approx_run);\n\n    dictRelease(d);\n\n    printf(\"TEST PASSED!\\n\");\n    return 0;\n}\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/utils/hyperloglog/.gitignore",
    "content": "*.txt\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/utils/hyperloglog/hll-err.rb",
    "content": "# hll-err.rb - Copyright (C) 2014 Salvatore Sanfilippo\n# BSD license, See the COPYING file for more information.\n#\n# Check error of HyperLogLog Redis implementation for different set sizes.\n\nrequire 'rubygems'\nrequire 'redis'\nrequire 'digest/sha1'\n\nr = Redis.new\nr.del('hll')\ni = 0\nwhile true do\n    100.times {\n        elements = []\n        1000.times {\n            ele = Digest::SHA1.hexdigest(i.to_s)\n            elements << ele\n            i += 1\n        }\n        r.pfadd('hll',*elements)\n    }\n    approx = r.pfcount('hll')\n    abs_err = (approx-i).abs\n    rel_err = 100.to_f*abs_err/i\n    puts \"#{i} vs #{approx}: #{rel_err}%\"\nend\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/utils/hyperloglog/hll-gnuplot-graph.rb",
    "content": "# hll-err.rb - Copyright (C) 2014 Salvatore Sanfilippo\n# BSD license, See the COPYING file for more information.\n#\n# This program is suited to output average and maximum errors of\n# the Redis HyperLogLog implementation in a format suitable to print\n# graphs using gnuplot.\n\nrequire 'rubygems'\nrequire 'redis'\nrequire 'digest/sha1'\n\n# Generate an array of [cardinality,relative_error] pairs\n# in the 0 - max range, with the specified step.\n#\n# 'r' is the Redis object used to perform the queries.\n# 'seed' must be different every time you want a test performed\n# with a different set. The function guarantees that if 'seed' is the\n# same, exactly the same dataset is used, and when it is different,\n# a totally unrelated different data set is used (without any common\n# element in practice).\ndef run_experiment(r,seed,max,step)\n    r.del('hll')\n    i = 0\n    samples = []\n    step = 1000 if step > 1000\n    while i < max do\n        elements = []\n        step.times {\n            ele = Digest::SHA1.hexdigest(i.to_s+seed.to_s)\n            elements << ele\n            i += 1\n        }\n        r.pfadd('hll',*elements)\n        approx = r.pfcount('hll')\n        err = approx-i\n        rel_err = 100.to_f*err/i\n        samples << [i,rel_err]\n    end\n    samples\nend\n\ndef filter_samples(numsets,max,step,filter)\n    r = Redis.new\n    dataset = {}\n    (0...numsets).each{|i|\n        dataset[i] = run_experiment(r,i,max,step)\n        STDERR.puts \"Set #{i}\"\n    }\n    dataset[0].each_with_index{|ele,index|\n        if filter == :max\n            card=ele[0]\n            err=ele[1].abs\n            (1...numsets).each{|i|\n                err = dataset[i][index][1] if err < dataset[i][index][1]\n            }\n            puts \"#{card} #{err}\"\n        elsif filter == :avg\n            card=ele[0]\n            err = 0\n            (0...numsets).each{|i|\n                err += dataset[i][index][1]\n            }\n            err /= numsets\n            puts \"#{card} #{err}\"\n        elsif filter == :absavg\n            card=ele[0]\n            err = 0\n            (0...numsets).each{|i|\n                err += dataset[i][index][1].abs\n            }\n            err /= numsets\n            puts \"#{card} #{err}\"\n        elsif filter == :all\n            (0...numsets).each{|i|\n                card,err = dataset[i][index]\n                puts \"#{card} #{err}\"\n            }\n        else\n            raise \"Unknown filter #{filter}\"\n        end\n    }\nend\n\nif ARGV.length != 4\n    puts \"Usage: hll-gnuplot-graph <samples> <max> <step> (max|avg|absavg|all)\"\n    exit 1\nend\nfilter_samples(ARGV[0].to_i,ARGV[1].to_i,ARGV[2].to_i,ARGV[3].to_sym)\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/utils/install_server.sh",
    "content": "#!/bin/sh\n\n# Copyright 2011 Dvir Volk <dvirsk at gmail dot com>. All rights reserved.\n#\n# Redistribution and use in source and binary forms, with or without\n# modification, are permitted provided that the following conditions are met:\n#\n#   1. Redistributions of source code must retain the above copyright notice,\n#   this list of conditions and the following disclaimer.\n#\n#   2. Redistributions in binary form must reproduce the above copyright\n#   notice, this list of conditions and the following disclaimer in the\n#   documentation and/or other materials provided with the distribution.\n#\n# THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED\n# WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF\n# MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO\n# EVENT SHALL Dvir Volk OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,\n# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\n# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,\n# OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF\n# LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING\n# NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,\n# EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n#\n################################################################################\n#\n# Interactive service installer for redis server\n# this generates a redis config file and an /etc/init.d script, and installs them\n# this scripts should be run as root\n\ndie () {\n\techo \"ERROR: $1. Aborting!\"\n\texit 1\n}\n\n\n#Absolute path to this script\nSCRIPT=$(readlink -f $0)\n#Absolute path this script is in\nSCRIPTPATH=$(dirname $SCRIPT)\n\n#Initial defaults\n_REDIS_PORT=6379\n\necho \"Welcome to the redis service installer\"\necho \"This script will help you easily set up a running redis server\"\necho\n\n#check for root user\nif [ \"$(id -u)\" -ne 0 ] ; then\n\techo \"You must run this script as root. Sorry!\"\n\texit 1\nfi\n\n#Read the redis port\nread  -p \"Please select the redis port for this instance: [$_REDIS_PORT] \" REDIS_PORT\nif ! echo $REDIS_PORT | egrep -q '^[0-9]+$' ; then\n\techo \"Selecting default: $_REDIS_PORT\"\n\tREDIS_PORT=$_REDIS_PORT\nfi\n\n#read the redis config file\n_REDIS_CONFIG_FILE=\"/etc/redis/$REDIS_PORT.conf\"\nread -p \"Please select the redis config file name [$_REDIS_CONFIG_FILE] \" REDIS_CONFIG_FILE\nif [ -z \"$REDIS_CONFIG_FILE\" ] ; then\n\tREDIS_CONFIG_FILE=$_REDIS_CONFIG_FILE\n\techo \"Selected default - $REDIS_CONFIG_FILE\"\nfi\n\n#read the redis log file path\n_REDIS_LOG_FILE=\"/var/log/redis_$REDIS_PORT.log\"\nread -p \"Please select the redis log file name [$_REDIS_LOG_FILE] \" REDIS_LOG_FILE\nif [ -z \"$REDIS_LOG_FILE\" ] ; then\n\tREDIS_LOG_FILE=$_REDIS_LOG_FILE\n\techo \"Selected default - $REDIS_LOG_FILE\"\nfi\n\n\n#get the redis data directory\n_REDIS_DATA_DIR=\"/var/lib/redis/$REDIS_PORT\"\nread -p \"Please select the data directory for this instance [$_REDIS_DATA_DIR] \" REDIS_DATA_DIR\nif [ -z \"$REDIS_DATA_DIR\" ] ; then\n\tREDIS_DATA_DIR=$_REDIS_DATA_DIR\n\techo \"Selected default - $REDIS_DATA_DIR\"\nfi\n\n#get the redis executable path\n_REDIS_EXECUTABLE=`command -v redis-server`\nread -p \"Please select the redis executable path [$_REDIS_EXECUTABLE] \" REDIS_EXECUTABLE\nif [ ! -x \"$REDIS_EXECUTABLE\" ] ; then\n\tREDIS_EXECUTABLE=$_REDIS_EXECUTABLE\n\n\tif [ ! -x \"$REDIS_EXECUTABLE\" ] ; then\n\t\techo \"Mmmmm...  it seems like you don't have a redis executable. Did you run make install yet?\"\n\t\texit 1\n\tfi\nfi\n\n#check the default for redis cli\nCLI_EXEC=`command -v redis-cli`\nif [ -z \"$CLI_EXEC\" ] ; then\n\tCLI_EXEC=`dirname $REDIS_EXECUTABLE`\"/redis-cli\"\nfi\n\necho \"Selected config:\"\n\necho \"Port           : $REDIS_PORT\"\necho \"Config file    : $REDIS_CONFIG_FILE\"\necho \"Log file       : $REDIS_LOG_FILE\"\necho \"Data dir       : $REDIS_DATA_DIR\"\necho \"Executable     : $REDIS_EXECUTABLE\"\necho \"Cli Executable : $CLI_EXEC\"\n\nread -p \"Is this ok? Then press ENTER to go on or Ctrl-C to abort.\" _UNUSED_\n\nmkdir -p `dirname \"$REDIS_CONFIG_FILE\"` || die \"Could not create redis config directory\"\nmkdir -p `dirname \"$REDIS_LOG_FILE\"` || die \"Could not create redis log dir\"\nmkdir -p \"$REDIS_DATA_DIR\" || die \"Could not create redis data directory\"\n\n#render the templates\nTMP_FILE=\"/tmp/${REDIS_PORT}.conf\"\nDEFAULT_CONFIG=\"${SCRIPTPATH}/../redis.conf\"\nINIT_TPL_FILE=\"${SCRIPTPATH}/redis_init_script.tpl\"\nINIT_SCRIPT_DEST=\"/etc/init.d/redis_${REDIS_PORT}\"\nPIDFILE=\"/var/run/redis_${REDIS_PORT}.pid\"\n\nif [ ! -f \"$DEFAULT_CONFIG\" ]; then\n\techo \"Mmmmm... the default config is missing. Did you switch to the utils directory?\"\n\texit 1\nfi\n\n#Generate config file from the default config file as template\n#changing only the stuff we're controlling from this script\necho \"## Generated by install_server.sh ##\" > $TMP_FILE\n\nread -r SED_EXPR <<-EOF\ns#^port [0-9]{4}\\$#port ${REDIS_PORT}#; \\\ns#^logfile .+\\$#logfile ${REDIS_LOG_FILE}#; \\\ns#^dir .+\\$#dir ${REDIS_DATA_DIR}#; \\\ns#^pidfile .+\\$#pidfile ${PIDFILE}#; \\\ns#^daemonize no\\$#daemonize yes#;\nEOF\nsed -r \"$SED_EXPR\" $DEFAULT_CONFIG  >> $TMP_FILE\n\n#cat $TPL_FILE | while read line; do eval \"echo \\\"$line\\\"\" >> $TMP_FILE; done\ncp $TMP_FILE $REDIS_CONFIG_FILE || die \"Could not write redis config file $REDIS_CONFIG_FILE\"\n\n#Generate sample script from template file\nrm -f $TMP_FILE\n\n#we hard code the configs here to avoid issues with templates containing env vars\n#kinda lame but works!\nREDIS_INIT_HEADER=\\\n\"#!/bin/sh\\n\n#Configurations injected by install_server below....\\n\\n\nEXEC=$REDIS_EXECUTABLE\\n\nCLIEXEC=$CLI_EXEC\\n\nPIDFILE=\\\"$PIDFILE\\\"\\n\nCONF=\\\"$REDIS_CONFIG_FILE\\\"\\n\\n\nREDISPORT=\\\"$REDIS_PORT\\\"\\n\\n\n###############\\n\\n\"\n\nREDIS_CHKCONFIG_INFO=\\\n\"# REDHAT chkconfig header\\n\\n\n# chkconfig: - 58 74\\n\n# description: redis_${REDIS_PORT} is the redis daemon.\\n\n### BEGIN INIT INFO\\n\n# Provides: redis_6379\\n\n# Required-Start: \\$network \\$local_fs \\$remote_fs\\n\n# Required-Stop: \\$network \\$local_fs \\$remote_fs\\n\n# Default-Start: 2 3 4 5\\n\n# Default-Stop: 0 1 6\\n\n# Should-Start: \\$syslog \\$named\\n\n# Should-Stop: \\$syslog \\$named\\n\n# Short-Description: start and stop redis_${REDIS_PORT}\\n\n# Description: Redis daemon\\n\n### END INIT INFO\\n\\n\"\n\nif command -v chkconfig >/dev/null; then\n\t#if we're a box with chkconfig on it we want to include info for chkconfig\n\techo \"$REDIS_INIT_HEADER\" \"$REDIS_CHKCONFIG_INFO\" > $TMP_FILE && cat $INIT_TPL_FILE >> $TMP_FILE || die \"Could not write init script to $TMP_FILE\"\nelse\n\t#combine the header and the template (which is actually a static footer)\n\techo \"$REDIS_INIT_HEADER\" > $TMP_FILE && cat $INIT_TPL_FILE >> $TMP_FILE || die \"Could not write init script to $TMP_FILE\"\nfi\n\n###\n# Generate sample script from template file\n# - No need to check which system we are on. The init info are comments and\n#   do not interfere with update_rc.d systems. Additionally:\n#     Ubuntu/debian by default does not come with chkconfig, but does issue a\n#     warning if init info is not available.\n\ncat > ${TMP_FILE} <<EOT\n#!/bin/sh\n#Configurations injected by install_server below....\n\nEXEC=$REDIS_EXECUTABLE\nCLIEXEC=$CLI_EXEC\nPIDFILE=$PIDFILE\nCONF=\"$REDIS_CONFIG_FILE\"\nREDISPORT=\"$REDIS_PORT\"\n###############\n# SysV Init Information\n# chkconfig: - 58 74\n# description: redis_${REDIS_PORT} is the redis daemon.\n### BEGIN INIT INFO\n# Provides: redis_${REDIS_PORT}\n# Required-Start: \\$network \\$local_fs \\$remote_fs\n# Required-Stop: \\$network \\$local_fs \\$remote_fs\n# Default-Start: 2 3 4 5\n# Default-Stop: 0 1 6\n# Should-Start: \\$syslog \\$named\n# Should-Stop: \\$syslog \\$named\n# Short-Description: start and stop redis_${REDIS_PORT}\n# Description: Redis daemon\n### END INIT INFO\n\nEOT\ncat ${INIT_TPL_FILE} >> ${TMP_FILE}\n\n#copy to /etc/init.d\ncp $TMP_FILE $INIT_SCRIPT_DEST && \\\n\tchmod +x $INIT_SCRIPT_DEST || die \"Could not copy redis init script to  $INIT_SCRIPT_DEST\"\necho \"Copied $TMP_FILE => $INIT_SCRIPT_DEST\"\n\n#Install the service\necho \"Installing service...\"\nif command -v chkconfig >/dev/null 2>&1; then\n\t# we're chkconfig, so lets add to chkconfig and put in runlevel 345\n\tchkconfig --add redis_${REDIS_PORT} && echo \"Successfully added to chkconfig!\"\n\tchkconfig --level 345 redis_${REDIS_PORT} on && echo \"Successfully added to runlevels 345!\"\nelif command -v update-rc.d >/dev/null 2>&1; then\n\t#if we're not a chkconfig box assume we're able to use update-rc.d\n\tupdate-rc.d redis_${REDIS_PORT} defaults && echo \"Success!\"\nelse\n\techo \"No supported init tool found.\"\nfi\n\n/etc/init.d/redis_$REDIS_PORT start || die \"Failed starting service...\"\n\n#tada\necho \"Installation successful!\"\nexit 0\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/utils/lru/README",
    "content": "The test-lru.rb program can be used in order to check the behavior of the\nRedis approximated LRU algorithm against the theoretical output of true\nLRU algorithm.\n\nIn order to use the program you need to recompile Redis setting the define\nREDIS_LRU_CLOCK_RESOLUTION to 1, by editing redis.h.\nThis allows to execute the program in a fast way since the 1 ms resolution\nis enough for all the objects to have a different enough time stamp during\nthe test.\n\nThe program is executed like this:\n\n    ruby test-lru.rb > /tmp/lru.html\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/utils/lru/test-lru.rb",
    "content": "require 'rubygems'\nrequire 'redis'\n\nr = Redis.new\nr.config(\"SET\",\"maxmemory\",\"2000000\")\nr.config(\"SET\",\"maxmemory-policy\",\"allkeys-lru\")\nr.config(\"SET\",\"maxmemory-samples\",5)\nr.config(\"RESETSTAT\")\nr.flushall\n\nputs <<EOF\n<html>\n<body>\n<style>\n.box {\n    width:5px;\n    height:5px;\n    float:left;\n    margin: 1px;\n}\n\n.old {\n    border: 1px black solid;\n}\n\n.new {\n    border: 1px green solid;\n}\n\n.ex {\n    background-color: #666;\n}\n</style>\n<pre>\nEOF\n\n# Fill\noldsize = r.dbsize\nid = 0\nwhile true\n    id += 1\n    r.set(id,\"foo\")\n    newsize = r.dbsize\n    break if newsize == oldsize\n    oldsize = newsize\nend\n\ninserted = r.dbsize\nfirst_set_max_id = id\nputs \"#{r.dbsize} keys inserted\"\n\n# Access keys sequentially\n\nputs \"Access keys sequentially\"\n(1..first_set_max_id).each{|id|\n    r.get(id)\n#    sleep 0.001\n}\n\n# Insert more 50% keys. We expect that the new keys\nhalf = inserted/2\nputs \"Insert enough keys to evict half the keys we inserted\"\nadd = 0\nwhile true\n    add += 1\n    id += 1\n    r.set(id,\"foo\")\n    break if r.info['evicted_keys'].to_i >= half\nend\n\nputs \"#{add} additional keys added.\"\nputs \"#{r.dbsize} keys in DB\"\n\n# Check if evicted keys respect LRU\n# We consider errors from 1 to N progressively more serious as they violate\n# more the access pattern.\n\nerrors = 0\ne = 1\nedecr = 1.0/(first_set_max_id/2)\n(1..(first_set_max_id/2)).each{|id|\n    e -= edecr if e > 0\n    e = 0 if e < 0\n    if r.exists(id)\n        errors += e\n    end\n}\n\nputs \"#{errors} errors!\"\nputs \"</pre>\"\n\n# Generate the graphical representation\n(1..id).each{|id|\n    # Mark first set and added items in a different way.\n    c = \"box\"\n    if id <= first_set_max_id\n        c << \" old\"\n    else\n        c << \" new\"\n    end\n\n    # Add class if exists\n    c << \" ex\" if r.exists(id)\n    puts \"<div class=\\\"#{c}\\\"></div>\"\n}\n\n# Close HTML page\n\nputs <<EOF\n</body>\n</html>\nEOF\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/utils/redis-copy.rb",
    "content": "# redis-copy.rb - Copyright (C) 2009-2010 Salvatore Sanfilippo\n# BSD license, See the COPYING file for more information.\n#\n# Copy the whole dataset from one Redis instance to another one\n#\n# WARNING: this utility is deprecated and serves as a legacy adapter\n#          for the more-robust redis-copy gem.\n\nrequire 'shellwords'\n\ndef redisCopy(opts={})\n  src = \"#{opts[:srchost]}:#{opts[:srcport]}\"\n  dst = \"#{opts[:dsthost]}:#{opts[:dstport]}\"\n  `redis-copy #{src.shellescape} #{dst.shellescape}`\nrescue Errno::ENOENT\n  $stderr.puts 'This utility requires the redis-copy executable',\n               'from the redis-copy gem on https://rubygems.org',\n               'To install it, run `gem install redis-copy`.'\n  exit 1\nend\n\n$stderr.puts \"This utility is deprecated. Use the redis-copy gem instead.\"\nif ARGV.length != 4\n    puts \"Usage: redis-copy.rb <srchost> <srcport> <dsthost> <dstport>\"\n    exit 1\nend\nputs \"WARNING: it's up to you to FLUSHDB the destination host before to continue, press any key when ready.\"\nSTDIN.gets\nsrchost = ARGV[0]\nsrcport = ARGV[1]\ndsthost = ARGV[2]\ndstport = ARGV[3]\nputs \"Copying #{srchost}:#{srcport} into #{dsthost}:#{dstport}\"\nredisCopy(:srchost => srchost, :srcport => srcport.to_i,\n          :dsthost => dsthost, :dstport => dstport.to_i)\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/utils/redis-sha1.rb",
    "content": "# redis-sha1.rb - Copyright (C) 2009 Salvatore Sanfilippo\n# BSD license, See the COPYING file for more information.\n#\n# Performs the SHA1 sum of the whole datset.\n# This is useful to spot bugs in persistence related code and to make sure\n# Slaves and Masters are in SYNC.\n#\n# If you hack this code make sure to sort keys and set elements as this are\n# unsorted elements. Otherwise the sum may differ with equal dataset.\n\nrequire 'rubygems'\nrequire 'redis'\nrequire 'digest/sha1'\n\ndef redisSha1(opts={})\n    sha1=\"\"\n    r = Redis.new(opts)\n    r.keys('*').sort.each{|k|\n        vtype = r.type?(k)\n        if vtype == \"string\"\n            len = 1\n            sha1 = Digest::SHA1.hexdigest(sha1+k)\n            sha1 = Digest::SHA1.hexdigest(sha1+r.get(k))\n        elsif vtype == \"list\"\n            len = r.llen(k)\n            if len != 0\n                sha1 = Digest::SHA1.hexdigest(sha1+k)\n                sha1 = Digest::SHA1.hexdigest(sha1+r.list_range(k,0,-1).join(\"\\x01\"))\n            end\n        elsif vtype == \"set\"\n            len = r.scard(k)\n            if len != 0\n                sha1 = Digest::SHA1.hexdigest(sha1+k)\n                sha1 = Digest::SHA1.hexdigest(sha1+r.set_members(k).to_a.sort.join(\"\\x02\"))\n            end\n        elsif vtype == \"zset\"\n            len = r.zcard(k)\n            if len != 0\n                sha1 = Digest::SHA1.hexdigest(sha1+k)\n                sha1 = Digest::SHA1.hexdigest(sha1+r.zrange(k,0,-1).join(\"\\x01\"))\n            end\n        end\n        # puts \"#{k} => #{sha1}\" if len != 0\n    }\n    sha1\nend\n\nhost = ARGV[0] || \"127.0.0.1\"\nport = ARGV[1] || \"6379\"\ndb = ARGV[2] || \"0\"\nputs \"Performing SHA1 of Redis server #{host} #{port} DB: #{db}\"\np \"Dataset SHA1: #{redisSha1(:host => host, :port => port.to_i, :db => db)}\"\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/utils/redis_init_script",
    "content": "#!/bin/sh\n#\n# Simple Redis init.d script conceived to work on Linux systems\n# as it does use of the /proc filesystem.\n\nREDISPORT=6379\nEXEC=/usr/local/bin/redis-server\nCLIEXEC=/usr/local/bin/redis-cli\n\nPIDFILE=/var/run/redis_${REDISPORT}.pid\nCONF=\"/etc/redis/${REDISPORT}.conf\"\n\ncase \"$1\" in\n    start)\n        if [ -f $PIDFILE ]\n        then\n                echo \"$PIDFILE exists, process is already running or crashed\"\n        else\n                echo \"Starting Redis server...\"\n                $EXEC $CONF\n        fi\n        ;;\n    stop)\n        if [ ! -f $PIDFILE ]\n        then\n                echo \"$PIDFILE does not exist, process is not running\"\n        else\n                PID=$(cat $PIDFILE)\n                echo \"Stopping ...\"\n                $CLIEXEC -p $REDISPORT shutdown\n                while [ -x /proc/${PID} ]\n                do\n                    echo \"Waiting for Redis to shutdown ...\"\n                    sleep 1\n                done\n                echo \"Redis stopped\"\n        fi\n        ;;\n    *)\n        echo \"Please use start or stop as first argument\"\n        ;;\nesac\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/utils/redis_init_script.tpl",
    "content": "\ncase \"$1\" in\n    start)\n        if [ -f $PIDFILE ]\n        then\n            echo \"$PIDFILE exists, process is already running or crashed\"\n        else\n            echo \"Starting Redis server...\"\n            $EXEC $CONF\n        fi\n        ;;\n    stop)\n        if [ ! -f $PIDFILE ]\n        then\n            echo \"$PIDFILE does not exist, process is not running\"\n        else\n            PID=$(cat $PIDFILE)\n            echo \"Stopping ...\"\n            $CLIEXEC -p $REDISPORT shutdown\n            while [ -x /proc/${PID} ]\n            do\n                echo \"Waiting for Redis to shutdown ...\"\n                sleep 1\n            done\n            echo \"Redis stopped\"\n        fi\n        ;;\n    status)\n        PID=$(cat $PIDFILE)\n        if [ ! -x /proc/${PID} ]\n        then\n            echo 'Redis is not running'\n        else\n            echo \"Redis is running ($PID)\"\n        fi\n        ;;\n    restart)\n        $0 stop\n        $0 start\n        ;;\n    *)\n        echo \"Please use start, stop, restart or status as first argument\"\n        ;;\nesac\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/utils/releasetools/01_create_tarball.sh",
    "content": "#!/bin/sh\nif [ $# != \"1\" ]\nthen\n    echo \"Usage: ./mkrelease.sh <git-ref>\"\n    exit 1\nfi\n\nTAG=$1\nTARNAME=\"redis-${TAG}.tar\"\necho \"Generating /tmp/${TARNAME}\"\ncd ~/hack/redis\ngit archive $TAG --prefix redis-${TAG}/ > /tmp/$TARNAME || exit 1\necho \"Gizipping the archive\"\nrm -f /tmp/$TARNAME.gz\ngzip -9 /tmp/$TARNAME\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/utils/releasetools/02_upload_tarball.sh",
    "content": "#!/bin/bash\necho \"Uploading...\"\nscp /tmp/redis-${1}.tar.gz antirez@antirez.com:/var/virtual/download.redis.io/httpdocs/releases/\necho \"Updating web site... (press any key if it is a stable release, or Ctrl+C)\"\nread x\nssh antirez@antirez.com \"cd /var/virtual/download.redis.io/httpdocs; ./update.sh ${1}\"\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/utils/releasetools/03_test_release.sh",
    "content": "#!/bin/sh\nif [ $# != \"1\" ]\nthen\n    echo \"Usage: ${0} <git-ref>\"\n    exit 1\nfi\n\nTAG=$1\nTARNAME=\"redis-${TAG}.tar.gz\"\nDOWNLOADURL=\"http://download.redis.io/releases/${TARNAME}\"\n\nssh antirez@metal \"export TERM=xterm;\n                   cd /tmp;\n                   rm -rf test_release_tmp_dir;\n                   cd test_release_tmp_dir;\n                   wget $DOWNLOADURL;\n                   tar xvzf $TARNAME;\n                   cd redis-${TAG};\n                   make;\n                   ./runtest;\n                   ./runtest-sentinel;\n                   if [ -x runtest-cluster ]; then\n                       ./runtest-cluster;\n                   fi\"\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/utils/releasetools/04_release_hash.sh",
    "content": "#!/bin/bash\nSHA=$(curl -s http://download.redis.io/releases/redis-${1}.tar.gz | shasum | cut -f 1 -d' ')\nENTRY=\"hash redis-${1}.tar.gz sha1 $SHA http://download.redis.io/releases/redis-${1}.tar.gz\"\necho $ENTRY >> ~/hack/redis-hashes/README\nvi ~/hack/redis-hashes/README\necho \"Press any key to commit, Ctrl-C to abort).\"\nread yes\n(cd ~/hack/redis-hashes; git commit -a -m \"${1} hash.\"; git push)\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/utils/speed-regression.tcl",
    "content": "#!/usr/bin/env tclsh8.5\n# Copyright (C) 2011 Salvatore Sanfilippo\n# Released under the BSD license like Redis itself\n\nsource ../tests/support/redis.tcl\nset ::port 12123\nset ::tests {PING,SET,GET,INCR,LPUSH,LPOP,SADD,SPOP,LRANGE_100,LRANGE_600,MSET}\nset ::datasize 16\nset ::requests 100000\n\nproc run-tests branches {\n    set runs {}\n    set branch_id 0\n    foreach b $branches {\n        cd ../src\n        puts \"Benchmarking $b\"\n        exec -ignorestderr git checkout $b 2> /dev/null\n        exec -ignorestderr make clean 2> /dev/null\n        puts \"  compiling...\"\n        exec -ignorestderr make 2> /dev/null\n\n        if {$branch_id == 0} {\n            puts \"  copy redis-benchmark from unstable to /tmp...\"\n            exec -ignorestderr cp ./redis-benchmark /tmp\n            incr branch_id\n            continue\n        }\n\n        # Start the Redis server\n        puts \"  starting the server... [exec ./redis-server -v]\"\n        set pids [exec echo \"port $::port\\nloglevel warning\\n\" | ./redis-server - > /dev/null 2> /dev/null &]\n        puts \"  pids: $pids\"\n        after 1000\n        puts \"  running the benchmark\"\n\n        set r [redis 127.0.0.1 $::port]\n        set i [$r info]\n        puts \"  redis INFO shows version: [lindex [split $i] 0]\"\n        $r close\n\n        set output [exec /tmp/redis-benchmark -n $::requests -t $::tests -d $::datasize --csv -p $::port]\n        lappend runs $b $output\n        puts \"  killing server...\"\n        catch {exec kill -9 [lindex $pids 0]}\n        catch {exec kill -9 [lindex $pids 1]}\n        incr branch_id\n    }\n    return $runs\n}\n\nproc get-result-with-name {output name} {\n    foreach line [split $output \"\\n\"] {\n        lassign [split $line \",\"] key value\n        set key [string tolower [string range $key 1 end-1]]\n        set value [string range $value 1 end-1]\n        if {$key eq [string tolower $name]} {\n            return $value\n        }\n    }\n    return \"n/a\"\n}\n\nproc get-test-names output {\n    set names {}\n    foreach line [split $output \"\\n\"] {\n        lassign [split $line \",\"] key value\n        set key [string tolower [string range $key 1 end-1]]\n        lappend names $key\n    }\n    return $names\n}\n\nproc combine-results {results} {\n    set tests [get-test-names [lindex $results 1]]\n    foreach test $tests {\n        puts $test\n        foreach {branch output} $results {\n            puts [format \"%-20s %s\" \\\n                $branch [get-result-with-name $output $test]]\n        }\n        puts {}\n    }\n}\n\nproc main {} {\n    # Note: the first branch is only used in order to get the redis-benchmark\n    # executable. Tests are performed starting from the second branch.\n    set branches {\n        slowset 2.2.0 2.4.0 unstable slowset\n    }\n    set results [run-tests $branches]\n    puts \"\\n\"\n    puts \"# Test results: datasize=$::datasize requests=$::requests\"\n    puts [combine-results $results]\n}\n\n# Force the user to run the script from the 'utils' directory.\nif {![file exists speed-regression.tcl]} {\n    puts \"Please make sure to run speed-regression.tcl while inside /utils.\"\n    puts \"Example: cd utils; ./speed-regression.tcl\"\n    exit 1\n}\n\n# Make sure there is not already a server runnign on port 12123\nset is_not_running [catch {set r [redis 127.0.0.1 $::port]}]\nif {!$is_not_running} {\n    puts \"Sorry, you have a running server on port $::port\"\n    exit 1\n}\n\n# parse arguments\nfor {set j 0} {$j < [llength $argv]} {incr j} {\n    set opt [lindex $argv $j]\n    set arg [lindex $argv [expr $j+1]]\n    if {$opt eq {--tests}} {\n        set ::tests $arg\n        incr j\n    } elseif {$opt eq {--datasize}} {\n        set ::datasize $arg\n        incr j\n    } elseif {$opt eq {--requests}} {\n        set ::requests $arg\n        incr j\n    } else {\n        puts \"Wrong argument: $opt\"\n        exit 1\n    }\n}\n\nmain\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.4/utils/whatisdoing.sh",
    "content": "# This script is from http://poormansprofiler.org/\n#\n# NOTE: Instead of using this script, you should use the Redis\n# Software Watchdog, which provides a similar functionality but in\n# a more reliable / easy to use way.\n#\n# Check http://redis.io/topics/latency for more information.\n\n#!/bin/bash\nnsamples=1\nsleeptime=0\npid=$(ps auxww | grep '[r]edis-server' | awk '{print $2}')\n\nfor x in $(seq 1 $nsamples)\n  do\n    gdb -ex \"set pagination 0\" -ex \"thread apply all bt\" -batch -p $pid\n    sleep $sleeptime\n  done | \\\nawk '\n  BEGIN { s = \"\"; } \n  /Thread/ { print s; s = \"\"; } \n  /^\\#/ { if (s != \"\" ) { s = s \",\" $4} else { s = $4 } } \n  END { print s }' | \\\nsort | uniq -c | sort -r -n -k 1,1\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.8/.gitignore",
    "content": ".*.swp\n*.o\n*.log\ndump.rdb\nredis-benchmark\nredis-check-aof\nredis-check-rdb\nredis-check-dump\nredis-cli\nredis-sentinel\nredis-server\ndoc-tools\nrelease\nmisc/*\nsrc/release.h\nappendonly.aof\nSHORT_TERM_TODO\nrelease.h\nsrc/transfer.sh\nsrc/configs\nredis.ds\nsrc/redis.conf\nsrc/nodes.conf\ndeps/lua/src/lua\ndeps/lua/src/luac\ndeps/lua/src/liblua.a\n.make-*\n.prerequisites\n*.dSYM\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.8/00-RELEASENOTES",
    "content": "Redis 3.2 release notes\n=======================\n\n--------------------------------------------------------------------------------\nUpgrade urgency levels:\n\nLOW:      No need to upgrade unless there are new features you want to use.\nMODERATE: Program an upgrade of the server, but it's not urgent.\nHIGH:     There is a critical bug that may affect a subset of users. Upgrade!\nCRITICAL: There is a critical bug affecting MOST USERS. Upgrade ASAP.\n--------------------------------------------------------------------------------\n\n================================================================================\nRedis 3.2.9     Released Mon May 17 17:35:38 CEST 2017\n================================================================================\n\nUpgrade urgency LOW: A few rarely harmful bugs were fixed.\n\nThis release just fixes bugs that are unlikely to cause serious problems\nso there is no need to update ASAP. Please, see the list of commits\nfor the details on the bugs fixed and credits:\n\nantirez in commit 3b46cf97:\n redis-cli --bigkeys: show error when TYPE fails.\n 1 file changed, 7 insertions(+), 2 deletions(-)\n\nantirez in commit f59b4b93:\n Fix preprocessor if/else chain broken in order to fix #3927.\n 1 file changed, 3 insertions(+)\n\nantirez in commit dd80fedf:\n Fix zmalloc_get_memory_size() ifdefs to actually use the else branch.\n 1 file changed, 2 deletions(-)\n\nantirez in commit 697d3abe:\n Set lua-time-limit default value at safe place.\n 2 files changed, 1 insertion(+), 1 deletion(-)\n\nantirez in commit c9c04b11:\n Fix #3848 by closing the descriptor on error.\n 1 file changed, 2 insertions(+), 1 deletion(-)\n\n张文康 in commit d3b49924:\n update block->free after some diff data are written to the child process\n 1 file changed, 1 insertion(+)\n\nantirez in commit 6a33952b:\n Test: fix, hopefully, false PSYNC failure like in issue #2715.\n 1 file changed, 1 insertion(+), 1 deletion(-)\n\nJohn.Koepi in commit b83f9fea:\n fix #2883, #2857 pipe fds leak when fork() failed on bg aof rw\n 1 file changed, 1 insertion(+)\n\nantirez in commit 10dbb5cd:\n Don't leak file descriptor on syncWithMaster().\n 1 file changed, 2 insertions(+), 1 deletion(-)\n\n================================================================================\nRedis 3.2.8     Released Sun Feb 12 16:11:18 CET 2017\n================================================================================\n\nUpgrade urgency CRITICAL: This release reverts back the Jemalloc upgrade\n                          that is believed to potentially cause a server\n                          deadlock. A MIGRATE crash is also fixed.\n\nTwo important bug fixes, the first of one is critical:\n\n1. Apparently Jemalloc 4.4.0 may contain a deadlock under particular\n   conditions. See https://github.com/antirez/redis/issues/3799.\n   We reverted back to the previously used Jemalloc versions and plan\n   to upgrade Jemalloc again after having more info about the\n   cause of the bug.\n\n2. MIGRATE could crash the server after a socket error. See for reference:\n   https://github.com/antirez/redis/issues/3796.\n\nList of commits:\n\nantirez in commit 7178cac:\n Revert \"Jemalloc updated to 4.4.0.\"\n 150 files changed, 6330 insertions(+), 17245 deletions(-)\n\nantirez in commit 33fad43:\n Fix MIGRATE closing of cached socket on error.\n 1 file changed, 23 insertions(+), 6 deletions(-)\n\n================================================================================\nRedis 3.2.7     Released Tue Jan 31 16:21:41 CET 2017\n================================================================================\n\nUpgrade urgency HIGH: This release fixes important security and correctness\n                      issues. It is especially important to upgrade for Redis\n                      Cluster users and for users running Redis in their laptop\n                      since a cross-scripting attack is fixed in this release.\n\nMain bugs fixes and improvements in this release:\n\n1. MIGRATE could incorrectly move keys between Redis Cluster nodes by turning\n   keys with an expire set into persisting keys. This bug was introduced with\n   the multiple-keys migration recently. It is now fixed. Only applies to\n   Redis Cluster users that use the resharding features of Redis Cluster.\n\n2. As Redis 4.0 beta and the unstable branch already did (for some months at\n   this point), Redis 3.2.7 also aliases the Host: and POST commands to QUIT\n   avoiding to process the remaining pipeline if there are pending commands.\n   This is a security protection against a \"Cross Scripting\" attack, that\n   usually involves trying to feed Redis with HTTP in order to execute commands.\n   Example: a developer is running a local copy of Redis for development\n   purposes. She also runs a web browser in the same computer. The web browser\n   could send an HTTP request to http://127.0.0.1:6379 in order to access the\n   Redis instance, since a specially crafted HTTP requesta may also be partially\n   valid Redis protocol. However if POST and Host: break the connection, this\n   problem should be avoided. IMPORTANT: It is important to realize that it\n   is not impossible that another way will be found to talk with a localhost\n   Redis using a Cross Protocol attack not involving sending POST or Host: so\n   this is only a layer of protection but not a definitive fix for this class\n   of issues.\n\n3. A ziplist bug that could cause data corruption, could crash the server and\n   MAY ALSO HAVE SECURITY IMPLICATIONS was fixed. The bug looks complex to\n   exploit, but attacks always get worse, never better (cit). The bug is very\n   very hard to catch in practice, it required manual analysis of the ziplist\n   code in order to be found. However it is also possible that rarely it\n   happened in the wild. Upgrading is required if you use LINSERT and other\n   in-the-middle list manipulation commands.\n\n4. We upgraded to Jemalloc 4.4.0 since the version we used to ship with Redis\n   was an early 4.0 release of Jemalloc. This version may have several\n   improvements including the ability to better reclaim/use the memory of\n   system.\n\nThe following is the list of commits:\n\nantirez in commit 3876d98:\n Ziplist: insertion bug under particular conditions fixed.\n 1 file changed, 9 insertions(+), 1 deletion(-)\n\nantirez in commit 153f2f0:\n Jemalloc updated to 4.4.0.\n 150 files changed, 17271 insertions(+), 6356 deletions(-)\n\nmiter in commit ca532c9:\n Change switch statment to if statment\n 1 file changed, 2 insertions(+), 4 deletions(-)\n\noranagra in commit a735035:\n fix rare assertion in DEBUG DIGEST\n 1 file changed, 1 insertion(+), 1 deletion(-)\n\nItamar Haber in commit b917e3f:\n Verify pairs are provided after subcommands\n 1 file changed, 1 insertion(+), 1 deletion(-)\n\nantirez in commit 1177cf6:\n Avoid geo.c warning in initialization.\n 1 file changed, 1 insertion(+), 1 deletion(-)\n\nantirez in commit 874804d:\n Security: Cross Protocol Scripting protection.\n 3 files changed, 27 insertions(+), 2 deletions(-)\n\nantirez in commit 273cd7f:\n Ziplist: remove static from functions, they prevent good crash reports.\n 1 file changed, 14 insertions(+), 14 deletions(-)\n\nJan-Erik Rediger in commit 389b9f5:\n Initialize help only in repl mode\n 1 file changed, 5 insertions(+), 5 deletions(-)\n\nYossi Gottlieb in commit 1370a88:\n Fix redis-cli rare crash.\n 1 file changed, 4 insertions(+)\n\nantirez in commit 68aab8e:\n MIGRATE: Remove upfront ttl initialization.\n 1 file changed, 3 insertions(+), 4 deletions(-)\n\nJan-Erik Rediger in commit 788e892:\n Reset the ttl for additional keys\n 1 file changed, 1 insertion(+)\n\n================================================================================\nRedis 3.2.6     Released Tue Dec 06 09:33:29 CET 2016\n================================================================================\n\nUpgrade urgency MODERATE: GEORADIUS, BITFIELD and Redis Cluster minor fixes.\n\nThis release mainly fixes three bugs:\n\n1. A bug with BITFIELD that may cause the bitmap corruption when setting offsets\n   larger than the current string size.\n\n2. A GEORADIUS bug that may happen when using very large radius lengths, in\n   the range of 10000km or alike, due to wrong bounding box calculation.\n\n3. A bug with Redis Cluster which crashes when reading a nodes configuration\n   file with zero bytes at the end, which sometimes happens with certain ext4\n   configurations after a system crash.\n\nThe following is the list of commits:\n\nantirez in commit f20f3ea:\n Geo: improve fuzz test.\n 1 file changed, 11 insertions(+), 3 deletions(-)\n\nantirez in commit 8c22086:\n Geo: fix computation of bounding box.\n 2 files changed, 33 insertions(+), 27 deletions(-)\n\nantirez in commit 92958df:\n Cluster: handle zero bytes at the end of nodes.conf.\n 1 file changed, 1 insertion(+), 1 deletion(-)\n\nantirez in commit 0ee28ae:\n Test: regression test for #3564 added.\n 1 file changed, 9 insertions(+)\n\nsunhe in commit 289fadb:\n bitops.c/bitfieldCommand: update higest_write_offset with check\n 1 file changed, 3 insertions(+), 2 deletions(-)\n\njybaek in commit f4f7d2c:\n Add missing fclose()\n 1 file changed, 1 insertion(+)\n\n================================================================================\nRedis 3.2.5     Released Wed Oct 26 09:16:40 CEST 2016\n================================================================================\n\nUpgrade urgency LOW: This release only fixes a compilation issue due to the\n                     missing -ldl at linking time.\n\nzach shipko in commit 4736407:\n BSDs don't have -ldl\n 1 file changed, 15 insertions(+), 5 deletions(-)\n\nantirez in commit 9ada818:\n Fix modules compilation when libc malloc is used.\n 1 file changed, 2 insertions(+), 2 deletions(-)\n\n================================================================================\nRedis 3.2.4     Released Mon Sep 26 08:58:21 CEST 2016\n================================================================================\n\nUpgrade urgency CRITICAL: Redis 3.2 and unstable contained a security\n                          vulnerability fixed by this release.\n\nHello Redis Wizards of the Memory Stores Empire,\n\nthis is a Redis critical release in order to fix a security issue\nwhich is documented clearly here:\n\n    https://github.com/antirez/redis/commit/6d9f8e2462fc2c426d48c941edeb78e5df7d2977\n\nThanks to Cory Duplantis of Cisco Talos for reporting the issue.\n\nIMPACT:\n\nThe gist is that using CONFIG SET calls (or by manipulating redis.conf)\nan attacker is able to compromise certain fields of the \"server\" global\nstructure, including the aof filename pointer, that could be made pointing\nto something else. In turn the AOF name is used in different contexts such\nas logging, rename(2) and open(2) syscalls, leading to potential problems.\n\nPlease note that since having access to CONFIG SET also means to be able\nto change the AOF filename (and many other things) directly, this issue\nactual real world impact is quite small, so I would not panik: if you\nhave CONFIG SET level of access, you can do more and more easily.\n\nAFFECTED VERSIONS:\n\nAll Redis 3.2.x versions are affected.\n\nOTHER CHANGES IN THIS RELEASE:\n\nThis release also includes other things:\n\n* TCP binding bug fixed when only certain addresses were available for\na given port.\n\n* A much better crash report that includes part of the Redis binary:\nthis will allow to fix bugs even when we just have a crash log and\nno other help from the original poster oft the issue.\n\n* A fix for Redis Cluster redis-trib displaying of info after creating\na new cluster.\n\nPlease check the following list of commits for credits about who did what.\nThanks to all the contributors and a special thank to Oran Agra for the\nhelp in this release.\n\nList of commits:\n\nantirez in commit 0539634:\n Security: CONFIG SET client-output-buffer-limit overflow fixed.\n 1 file changed, 5 insertions(+), 3 deletions(-)\n\nantirez in commit c01abcd:\n fix the fix for the TCP binding.\n 1 file changed, 15 insertions(+), 10 deletions(-)\n\noranagra in commit a6d0698:\n fix tcp binding when IPv6 is unsupported\n 2 files changed, 14 insertions(+), 10 deletions(-)\n\nantirez in commit 22b6c28:\n debug.c: no need to define _GNU_SOURCE, is defined in fmacros.h.\n 1 file changed, 1 deletion(-)\n\nantirez in commit 9e9d398:\n crash log - improve code dump with more info and called symbols.\n 1 file changed, 59 insertions(+), 20 deletions(-)\n\noranagra in commit 3745c5d:\n crash log - add hex dump of function code\n 1 file changed, 22 insertions(+)\n\nantirez in commit c1cc07b:\n Sentinel example config: warn about protected mode.\n 1 file changed, 16 insertions(+), 1 deletion(-)\n\nrojingeorge in commit 011dc9f:\n Display the nodes summary once the cluster is established using redis-trib.rb\n 1 file changed, 5 insertions(+)\n\nGuo Xiao in commit f4e3a94:\n Use the standard predefined identifier __func__ (since C99)\n 1 file changed, 1 insertion(+), 1 deletion(-)\n\n================================================================================\nRedis 3.2.3     Released Tue Aug 02 10:55:24 CEST 2016\n================================================================================\n\nUpgrade urgency MODERATE: Fix replication delay and redis-cli security issue.\n\nHello,\n\nthis is a minor release of Redis addressing two bugs:\n\n1. There was an inverted if statement logic problem in replication.c causing\n   a replication delay. This is not an actual problem since things work\n   as expected, but worth to fix ASAP anyway.\n\n2. Redis-cli created the history file with insecure permissions, allowing\n   reding from the file. This was actually a bug in linenoise which is\n   now fixed. The applied fix is from Chris Lamb.\n\nList of commits:\n\nQu Chen in commit e67ad1d:\n Fix a bug to delay bgsave while AOF rewrite in progress for replication\n 1 file changed, 1 insertion(+), 1 deletion(-)\n\nantirez in commit 7153668:\n Update linenoise to fix insecure redis-cli history file creation.\n 1 file changed, 6 insertions(+), 1 deletion(-)\n\n================================================================================\nRedis 3.2.2     Released Thu Jul 28 14:14:54 CEST 2016\n================================================================================\n\nUpgrade urgency MODERATE: A Redis server and a Sentinel crash are now fixed.\n                          GEORADIUS errors in reported entries are fixed.\n\nHi all! Redis 3.2.2 is finally out with non trivial bugfixes and a few new\nfeatures. Let's start from the bugs:\n\n1. There was a bug in the List type implementation, able to cause the\n   crash of the server under certain (non trivial to replicate) circumstances\n   when the LSET command was used. Now the bug is fixed and a new stress tester\n   that was able to easily trigger the bug was added to the test suite.\n\n2. Redis Sentinel, when monitoring multiple masters, could crash after\n   a Sentinel address update event.\n\n3. Redis Sentinel now checks slaves INFO state more often when disconnected.\n   This is not really a bug fix, but may allow to more easily detect that\n   a slave is able to fail over its master reducing certain delays.\n\n4. It was possible, under a variety of conditions, that the AOF and RDB children\n   process could spawn at the same time. This is known to trash disk I/O,\n   AOF performances, and to ultimately create latency in the Redis server.\n   Normally Redis avoids to have the two writing children at the same time, but\n   there were edge cases discovered by Oran Agra (that also co-authored the\n   fix with me) where the double-fork could happen. In order to fix this bug\n   non trivial changes to the replication code were operated, however it was\n   important to back port this fix into 3.2.2 because the bug could lead to\n   bad latency experiences in certain cases.\n\n5. Many GEORADIUS bugs are now fixed \\o/. This started as a failing CI\n   test. I grepped for more clues and there were a number of random failures\n   in the points reported by GEORADIUS. The errors were found to be related\n   to three different bugs (one of these was a bug in the test itself).\n   It's not a critical bug: the effect is to, sometimes, don't report objects\n   that are near the radius, but only with specific sets of coordinates\n   and radius settings. However now the issues are fixed and the error\n   vectors were added as regression tests.\n\nAnd now the good news (not that bug fixes are not good...), that is, the\nnew features!\n\n1. Now slaves support the slave-announce-ip and slave-announce-port options.\n   Using these features a slave can be reported by the master `INFO` output\n   and `ROLE` command as having arbitrary IP and port. This allows to have\n   Sentinel deployments when working with containers or NAT-ed environments\n   more easily.\n\n2. The RDB check utlity is now part of Redis and uses the same RDB code that\n   Redis uses in order to load the dataset in memory, so a given version\n   of Redis is always able to check the RDB it produced... without another\n   external check tool which is supposed to be taken in sync with the\n   rdb.c implementation. This in turn also means that the new RDB checking\n   is able to spot more complex bugs, since it really loads the dataset\n   instead of just skipping bytes.\n\nAbout the redis-check-dump utility, now it is also able to show certain\ninformation about the RDB file, like the version that produced it, when\nit was produced, and so forth. Example:\n\n    ./redis-check-rdb dump.rdb\n    [offset 0] Checking RDB file dump.rdb\n    [offset 32] AUX FIELD redis-ver = '3.2.2'\n    [offset 46] AUX FIELD redis-bits = '64'\n    [offset 58] AUX FIELD ctime = '1469710178'\n    [offset 73] AUX FIELD used-mem = '1186528'\n\nThe ability to check how much memory was used by the instance that produced\nthe RDB file can be especially useful.\n\nFor credits and the full change log, see the list of commits below, that was\nmodified in order to be a bit less verbose compared to the last releases.\n\nEnjoy!\nSalvatore\n\nantirez in commit 0a45fbc:\n Ability of slave to announce arbitrary ip/port to master.\n 6 files changed, 129 insertions(+), 17 deletions(-)\n\nantirez in commit c3982c0:\n redis-benchmark: new option to show server errors on stdout.\n 1 file changed, 17 insertions(+), 1 deletion(-)\n\nantirez in commit fdafe23:\n Multiple GEORADIUS bugs fixed.\n 6 files changed, 177 insertions(+), 21 deletions(-)\n\nantirez in commit a1bfe22:\n Replication: when possible start RDB saving ASAP.\n 1 file changed, 8 insertions(+), 2 deletions(-)\n\nantirez in commit 7ca69af:\n Sentinel: new test unit 07 that tests master down conditions.\n 1 file changed, 68 insertions(+)\n\nantirez in commit 5b5e652:\n Sentinel: check Slave INFO state more often when disconnected.\n 2 files changed, 10 insertions(+), 3 deletions(-)\n\nantirez in commit 21cffc2:\n Avoid simultaneous RDB and AOF child process.\n 4 files changed, 51 insertions(+), 8 deletions(-)\n\nantirez in commit 017378e:\n Replication: start BGSAVE for replication always in replicationCron().\n 1 file changed, 15 insertions(+), 12 deletions(-)\n\nantirez in commit 940be9a:\n Regression test for issue #3333.\n 1 file changed, 6 insertions(+)\n\nantirez in commit 21736b4:\n getLongLongFromObject: use string2ll() instead of strict_strtoll().\n 1 file changed, 1 insertion(+), 6 deletions(-)\n\nantirez in commit 0b748e9:\n redis-cli: check SELECT reply type just in state updated.\n 1 file changed, 1 insertion(+), 1 deletion(-)\n\nsskorgal in commit 1158386:\n Fix for redis_cli printing default DB when select command fails.\n 1 file changed, 1 insertion(+), 1 deletion(-)\n\nantirez in commit 026f9fc:\n Sentinel: fix cross-master Sentinel address update.\n 1 file changed, 9 insertions(+), 2 deletions(-)\n\nantirez in commit 11523b3:\n CONFIG GET is now no longer case sensitive.\n 1 file changed, 12 insertions(+), 12 deletions(-)\n\nantirez in commit f5a7f4f:\n Fix test for new RDB checksum failure message.\n 1 file changed, 1 insertion(+), 1 deletion(-)\n\nantirez in commit 4c6ff74:\n Make tcp-keepalive default to 300 in internal conf.\n 1 file changed, 1 insertion(+), 1 deletion(-)\n\nantirez in commit 27dbec2:\n In Redis RDB check: more details in error reportings.\n 1 file changed, 24 insertions(+), 13 deletions(-)\n\nantirez in commit 41f3004:\n In Redis RDB check: log decompression errors.\n 2 files changed, 23 insertions(+), 2 deletions(-)\n\nantirez in commit 278fe3e:\n In Redis RDB check: log object type on error.\n 1 file changed, 27 insertions(+), 2 deletions(-)\n\nantirez in commit a117dfa:\n Added a trivial program to randomly corrupt RDB files in /utils.\n 1 file changed, 44 insertions(+)\n\nantirez in commit f5110c3:\n In Redis RDB check: minor output message changes.\n 1 file changed, 4 insertions(+), 1 deletion(-)\n\nantirez in commit 35b18bf:\n In Redis RDB check: better error reporting.\n 4 files changed, 71 insertions(+), 14 deletions(-)\n\nantirez in commit f578f08:\n In Redis RDB check: initial POC.\n 2 files changed, 189 insertions(+), 647 deletions(-)\n\ntielei in commit 7f1e1ca:\n A string with 21 chars is not representable as a 64-bit integer.\n 1 file changed, 2 insertions(+), 2 deletions(-)\n\nantirez in commit 7a3a595:\n Test: new randomized stress tester for #3343 alike bugs.\n 1 file changed, 27 insertions(+), 2 deletions(-)\n\nantirez in commit c75ca10:\n Stress tester WIP.\n 1 file changed, 3 insertions(+)\n\nantirez in commit 2c3fcf8:\n Regression test for issue #3343 exact min crash sequence.\n 1 file changed, 16 insertions(+)\n\nantirez in commit 7041967:\n Fix quicklistReplaceAtIndex() by updating the quicklist ziplist size.\n 1 file changed, 1 insertion(+)\n\n================================================================================\nRedis 3.2.1     Released Fri Jun 17 15:01:56 CEST 2016\n================================================================================\n\nUpgrade urgency HIGH: Critical fix to Redis Sentinel, due to 3.2.0 regression\n                      compared to 3.0.\n\nHey, this is Redis 3.2.1, and this release should bring some grain of\nmaturity to Redis 3.2. The list of commits following this note will tell\nyou the details, but the main things addressed in this release are the\nfollowing:\n\n1. A critical bug in Sentinel was hopefully fixed. During the big 3.2\n   refactoring of Redis Sentinel, in order to implement connection sharing\n   to make Sentinel able to scale better (few Sentinels to monitor many\n   masters), a bug was introduced that mis-counted the number of pending\n   commands in the Redis link. This in turn resulted into an inability to talk\n   with certain Redis instances. A common result of this bug was the inability\n   of Redis Sentinel to reconfigure back the old master, after a failover,\n   when it is reachable again, as the slave of the new master. This was due\n   to the inability to talk with the old master at all.\n\n2. BITFIELD bugs fixed.\n\n3. GEO commands fixes on syntax errors and edge cases.\n\n4. RESTORE now accepts dumps generated by older Redis versions.\n\n5. Jemalloc now is really configured to save you memory, for a problem a\n   change in the jemalloc configuration did not really survived when the\n   3.2.0 release was finalized.\n\n6. TTL and TYPE command no longer alter the last access time of a key, for\n   LRU evictions purposes. A new TOUCH command was introduced *just* to\n   update the access time of a key.\n\n7. A bug was fixed in redis-cli, that connected to the instance running on the\n   port 6379 if there was one, regardless of what was specified.\n\n8. TCP keep alive is now enabled by default. This should fix most ghost\n   connections problems without resulting in any practical change in otherwise\n   sane deployments.\n\n9. A Sentinel crash that could happen during failovers was fixed.\n\nAnd of course, more minor things that you can read in the detailed log\nbelow. There are still reported bugs for 3.2 that were not fixed in this\nrelease, but nothing critical AFAIK, and I wanted to release this one ASAP,\nso likely a new release will not be too far.\n\nEnjoy,\nSalvatore\n\n+-------------------------------------------------------------------------------\n| config set list-max-ziplist-size didn't support negative values, unlike config file\n| By oranagra, 2016-05-22 20:35:14 +0300\n+--------------------------------------------------------------------------------\nhttps://github.com/antirez/redis/commit/8207e828043e37a0d7e058530d2886bb3ff395ff\n\n\n src/config.c | 6 +++---\n 1 file changed, 3 insertions(+), 3 deletions(-)\n\n+-------------------------------------------------------------------------------\n| Fix Sentinel pending commands counting.\n| By antirez, 2016-06-16 19:24:34 +0200\n+--------------------------------------------------------------------------------\nhttps://github.com/antirez/redis/commit/6ad0371c9b4206a7a6692d50c9a301457baf9b6d\n\nThis bug most experienced effect was an inability of Redis to\nreconfigure back old masters to slaves after they are reachable again\nafter a failover. This was due to failing to reset the count of the\npending commands properly, so the master appeared fovever down.\n\nWas introduced in Redis 3.2 new Sentinel connection sharing feature\nwhich is a lot more complex than the 3.0 code, but more scalable.\n\nMany thanks to people reporting the issue, and especially to\n@sskorgal for investigating the issue in depth.\n\nHopefully closes #3285.\n\n src/sentinel.c | 1 +\n 1 file changed, 1 insertion(+)\n\n+-------------------------------------------------------------------------------\n| redis-cli: really connect to the right server.\n| By antirez, 2016-06-16 17:23:31 +0200\n+--------------------------------------------------------------------------------\nhttps://github.com/antirez/redis/commit/58f1d446c35e8fe62df7c9ebe10f3c40a386c022\n\nI recently introduced populating the autocomplete help array with the\nCOMMAND command if available. However this was performed before parsing\nthe arguments, defaulting to instance 6379. After the connection is\nperformed it remains stable.\n\nThe effect is that if there is an instance running on port 6339,\nwhatever port you specify is ignored and 6379 is connected to instead.\nThe right port will be selected only after a reconnection.\n\nClose #3314.\n\n src/redis-cli.c | 7 +++++--\n 1 file changed, 5 insertions(+), 2 deletions(-)\n\n+-------------------------------------------------------------------------------\n| Remove debug printing\n| By Jan-Erik Rediger, 2016-05-21 13:50:01 +0200\n+--------------------------------------------------------------------------------\nhttps://github.com/antirez/redis/commit/b6007b324b81dbd4ffe519b3bdb19ab65fbb407f\n\n\n src/redis-cli.c | 3 ---\n 1 file changed, 3 deletions(-)\n\n+-------------------------------------------------------------------------------\n| RESTORE: accept RDB dumps with older versions.\n| By antirez, 2016-06-16 15:53:57 +0200\n+--------------------------------------------------------------------------------\nhttps://github.com/antirez/redis/commit/f592b4d3178963878084a522b4fd050772c335ae\n\nReference issue #3218.\n\nChecking the code I can't find a reason why the original RESTORE\ncode was so opinionated about restoring only the current version. The\ncode in to `rdb.c` appears to be capable as always to restore data from\nolder versions of Redis, and the only places where it is needed the\ncurrent version in order to correctly restore data, is while loading the\nopcodes, not the values itself as it happens in the case of RESTORE.\n\nFor the above reasons, this commit enables RESTORE to accept older\nversions of values payloads.\n\n src/cluster.c | 2 +-\n 1 file changed, 1 insertion(+), 1 deletion(-)\n\n+-------------------------------------------------------------------------------\n| CLIENT error message was out of date\n| By oranagra, 2016-05-23 11:42:21 +0300\n+--------------------------------------------------------------------------------\nhttps://github.com/antirez/redis/commit/047ced4473ee35485e22e45db8b8b4a272bf1177\n\n\n src/networking.c | 2 +-\n 1 file changed, 1 insertion(+), 1 deletion(-)\n\n+-------------------------------------------------------------------------------\n| fix georadius returns multiple replies\n| By oranagra, 2016-05-23 13:58:50 +0300\n+--------------------------------------------------------------------------------\nhttps://github.com/antirez/redis/commit/14e04847ac2960aefe31dccbec63d2503cf09ca5\n\n\n src/geo.c | 7 +++++--\n 1 file changed, 5 insertions(+), 2 deletions(-)\n\n+-------------------------------------------------------------------------------\n| Minor aesthetic fixes to PR #3264.\n| By antirez, 2016-06-16 12:54:33 +0200\n+--------------------------------------------------------------------------------\nhttps://github.com/antirez/redis/commit/bd23ea3f9f3defbbdf512864ee1a88fd02665a7f\n\nComment format fixed + local var modified from camel case to underscore\nseparators as Redis code base normally does (camel case is mostly used\nfor global symbols like structure names, function names, global vars,\n...).\n\n src/bitops.c | 10 +++++-----\n 1 file changed, 5 insertions(+), 5 deletions(-)\n\n+-------------------------------------------------------------------------------\n| check WRONGTYPE in BITFIELD before looping on the operations.\n| By oranagra, 2016-05-24 23:31:36 +0300\n+--------------------------------------------------------------------------------\nhttps://github.com/antirez/redis/commit/2a3ee58ec73b6abdeeb4890937b25191119bce35\n\noptimization: lookup key only once, and grow at once to the max need\nfixes #3259 and #3221, and also an early return if wrongtype is discovered by SET\n\n src/bitops.c | 27 ++++++++++++++++++---------\n 1 file changed, 18 insertions(+), 9 deletions(-)\n\n+-------------------------------------------------------------------------------\n| fix crash in BITFIELD GET on non existing key or wrong type see #3259\n| By oranagra, 2016-05-24 14:52:43 +0300\n+--------------------------------------------------------------------------------\nhttps://github.com/antirez/redis/commit/a2e27b810edfad18b3ecc9c176a4606f94a2f0e4\n\nthis was a bug in the recent refactoring: bee963c4459223d874e3294a0d8638a588d33c8e\n\n src/bitops.c | 8 +++++---\n 1 file changed, 5 insertions(+), 3 deletions(-)\n\n+-------------------------------------------------------------------------------\n| fix check when can't send the command to the promoted slave\n| By MOON_CLJ, 2016-05-26 13:10:12 +0800\n+--------------------------------------------------------------------------------\nhttps://github.com/antirez/redis/commit/26555f5e008b099b888ef39cabec632f4b31a038\n\n\n src/sentinel.c | 2 +-\n 1 file changed, 1 insertion(+), 1 deletion(-)\n\n+-------------------------------------------------------------------------------\n| Test TOUCH and new TTL / TYPE behavior about object access time.\n| By antirez, 2016-06-15 17:15:18 +0200\n+--------------------------------------------------------------------------------\nhttps://github.com/antirez/redis/commit/f1c237cb6a647ad5400b0ebce124fd9802ea7f89\n\n\n tests/test_helper.tcl          |  1 +\n tests/unit/introspection-2.tcl | 23 +++++++++++++++++++++++\n 2 files changed, 24 insertions(+)\n\n+-------------------------------------------------------------------------------\n| GETRANGE: return empty string with negative, inverted start/end.\n| By antirez, 2016-06-15 12:48:58 +0200\n+--------------------------------------------------------------------------------\nhttps://github.com/antirez/redis/commit/d4831e328759bf5bd07c2c6e6ce1d60e84ba196f\n\n\n src/bitops.c   | 4 ++--\n src/t_string.c | 4 ++++\n 2 files changed, 6 insertions(+), 2 deletions(-)\n\n+-------------------------------------------------------------------------------\n| Remove additional round brackets from fix for #3282.\n| By antirez, 2016-06-15 12:16:39 +0200\n+--------------------------------------------------------------------------------\nhttps://github.com/antirez/redis/commit/9942070f5a41fa3bc953e9628a7248aeb7c0befa\n\n\n src/bitops.c | 2 +-\n 1 file changed, 1 insertion(+), 1 deletion(-)\n\n+-------------------------------------------------------------------------------\n| bitcount bug:return non-zero value when start > end (both negative)\n| By wenduo, 2016-05-30 16:21:08 +0800\n+--------------------------------------------------------------------------------\nhttps://github.com/antirez/redis/commit/f45fa5d05f47a5729786a69962119c9b3dc12645\n\n\n src/bitops.c | 4 ++++\n 1 file changed, 4 insertions(+)\n\n+-------------------------------------------------------------------------------\n| Regression test for #3282.\n| By antirez, 2016-06-15 11:49:49 +0200\n+--------------------------------------------------------------------------------\nhttps://github.com/antirez/redis/commit/0cb86064e602a093a23b56943a7321fe1af64984\n\n\n tests/unit/bitops.tcl | 10 ++++++++++\n 1 file changed, 10 insertions(+)\n\n+-------------------------------------------------------------------------------\n| TTL and TYPE LRU access fixed. TOUCH implemented.\n| By antirez, 2016-06-14 15:33:59 +0200\n+--------------------------------------------------------------------------------\nhttps://github.com/antirez/redis/commit/b23aa6706ac79a1c86c64aef07bd35e38f10f842\n\n\n src/db.c     | 61 +++++++++++++++++++++++++++++++++++++++++++++++++++++-------\n src/server.c |  1 +\n src/server.h |  6 +++++-\n 3 files changed, 60 insertions(+), 8 deletions(-)\n\n+-------------------------------------------------------------------------------\n| redis-cli help.h updated.\n| By antirez, 2016-06-14 14:45:48 +0200\n+--------------------------------------------------------------------------------\nhttps://github.com/antirez/redis/commit/6e4204fec9c78f3300d887ebc3db014df2c8b33e\n\n\n src/help.h | 43 +++++++++++++++++++++++++++++--------------\n 1 file changed, 29 insertions(+), 14 deletions(-)\n\n+-------------------------------------------------------------------------------\n| Fix GEORADIUS wrong output with radius > Earth radius.\n| By antirez, 2016-05-30 12:45:49 +0200\n+--------------------------------------------------------------------------------\nhttps://github.com/antirez/redis/commit/bb43f4cab2f756c0412ca2b94d9e29c3db5025ab\n\nClose #3266\n\n deps/geohash-int/geohash_helper.c | 2 ++\n 1 file changed, 2 insertions(+)\n\n+-------------------------------------------------------------------------------\n| Geo: fix typo in geohashEstimateStepsByRadius().\n| By antirez, 2016-05-30 15:31:19 +0200\n+--------------------------------------------------------------------------------\nhttps://github.com/antirez/redis/commit/16102bc0af0912a0c9a92aedddf796eb24a80b9e\n\nI'm the author of this line but I can't see a good reason for it to\ndon't be a typo, a step of 26 should be valid with 52 bits per\ncoordinate, moreover the line was:\n\n    if (step > 26) step = 25;\n\nSo a step of 26 was actually already used, except when one of 27 was\ncomputed (which is invalid) only then it was trimmed to 25 instead of\n26.\n\nAll tests passing after the change.\n\n deps/geohash-int/geohash_helper.c | 2 +-\n 1 file changed, 1 insertion(+), 1 deletion(-)\n\n+-------------------------------------------------------------------------------\n| Avoid undefined behavior in BITFIELD implementation.\n| By antirez, 2016-05-31 11:52:07 +0200\n+--------------------------------------------------------------------------------\nhttps://github.com/antirez/redis/commit/014bf8044285c6d401d83e6e24829d276ab837f9\n\nProbably there is no compiler that will actaully break the code or raise\na signal for unsigned -> signed overflowing conversion, still it was\napparently possible to write it in a more correct way.\n\nAll tests passing.\n\n src/bitops.c | 23 +++++++++++++++--------\n 1 file changed, 15 insertions(+), 8 deletions(-)\n\n+-------------------------------------------------------------------------------\n| Now that SPOP can be called by scripts use BLPOP on 's' flag test.\n| By antirez, 2016-05-31 16:43:21 +0200\n+--------------------------------------------------------------------------------\nhttps://github.com/antirez/redis/commit/b4e5e2ec1ad7e9d1f4e7e559b61e0ecd4e50f2da\n\n\n tests/unit/scripting.tcl | 2 +-\n 1 file changed, 1 insertion(+), 1 deletion(-)\n\n+-------------------------------------------------------------------------------\n| Test: run GEO tests by default.\n| By antirez, 2016-05-31 16:43:49 +0200\n+--------------------------------------------------------------------------------\nhttps://github.com/antirez/redis/commit/df419281a19e13429b27814a3e384f6f029c3519\n\nThanks to @oranagra for noticing it was missing.\n\n tests/test_helper.tcl | 1 +\n 1 file changed, 1 insertion(+)\n\n+-------------------------------------------------------------------------------\n| Enable tcp-keepalive by default.\n| By antirez, 2016-06-13 12:03:14 +0200\n+--------------------------------------------------------------------------------\nhttps://github.com/antirez/redis/commit/40cfe13141c7178d22fd43e4ffbecc37686e0b43\n\n\n redis.conf | 5 +++--\n 1 file changed, 3 insertions(+), 2 deletions(-)\n\n+-------------------------------------------------------------------------------\n| fix some compiler warnings\n| By Pierre Chapuis, 2016-06-05 15:34:43 +0200\n+--------------------------------------------------------------------------------\nhttps://github.com/antirez/redis/commit/a650aaaf4f074ec428b450ef88799db1dcd34b0f\n\n\n src/bitops.c | 4 ++--\n 1 file changed, 2 insertions(+), 2 deletions(-)\n\n+-------------------------------------------------------------------------------\n| Fixed typo in Sentinel compareSlavesForPromotion() comment.\n| By antirez, 2016-06-10 09:15:01 +0200\n+--------------------------------------------------------------------------------\nhttps://github.com/antirez/redis/commit/3fd4baf1e77f125a306d57b788b72de5026c0564\n\n\n src/sentinel.c | 2 +-\n 1 file changed, 1 insertion(+), 1 deletion(-)\n\n+-------------------------------------------------------------------------------\n| fix comment \"b>a\" to \"a > b\"\n| By andyli, 2016-06-07 14:42:50 +0800\n+--------------------------------------------------------------------------------\nhttps://github.com/antirez/redis/commit/8d029a5950f4ef40723c02b5c486b171aff0189c\n\n\n src/sentinel.c | 2 +-\n 1 file changed, 1 insertion(+), 1 deletion(-)\n\n+-------------------------------------------------------------------------------\n| fix pidfile in redis.conf\n| By bogdanvlviv, 2016-04-19 14:43:06 +0300\n+--------------------------------------------------------------------------------\nhttps://github.com/antirez/redis/commit/6937f5960d1803ca0eda1ab6f4bc60023f50c914\n\n\n redis.conf | 2 +-\n 1 file changed, 1 insertion(+), 1 deletion(-)\n\n+-------------------------------------------------------------------------------\n| Include 'fd_set' type name\n| By jspraul, 2016-06-07 16:46:00 -0400\n+--------------------------------------------------------------------------------\nhttps://github.com/antirez/redis/commit/b5758cc5ce6c51ff75c86f9216214fe4d5e4c257\n\nFix an MSYS2-build-breaking error: unknown type name ‘fd_set’\n src/ae_select.c | 1 +\n 1 file changed, 1 insertion(+)\n\n+-------------------------------------------------------------------------------\n| Allow SPOP from Lua scripts\n| By Itamar Haber, 2016-05-28 20:01:46 +0300\n+--------------------------------------------------------------------------------\nhttps://github.com/antirez/redis/commit/620783e3b582e9ba6e1d8fbd47987281ce0b6317\n\nThe existing `R` flag appears to be sufficient and there's no apparent reason why the command should be blocked.\n src/server.c | 2 +-\n 1 file changed, 1 insertion(+), 1 deletion(-)\n\n+-------------------------------------------------------------------------------\n| minor fixes - mainly signalModifiedKey, and GEORADIUS\n| By oranagra, 2016-05-09 09:12:38 +0300\n+--------------------------------------------------------------------------------\nhttps://github.com/antirez/redis/commit/603234076f4e59967f331bc97de3c0db9947c8ef\n\n\n src/geo.c    |  1 +\n src/sds.c    |  8 ++++----\n src/server.c |  2 +-\n src/server.h |  3 +--\n src/t_set.c  |  9 ++++++---\n src/t_zset.c | 12 ++++++------\n 6 files changed, 19 insertions(+), 16 deletions(-)\n\n+-------------------------------------------------------------------------------\n| Code to access object string bytes repeated 3x refactored into 1 function.\n| By antirez, 2016-05-18 15:35:17 +0200\n+--------------------------------------------------------------------------------\nhttps://github.com/antirez/redis/commit/2e6b99499abb5ff1fbeee3bac4d064e5ff4ea256\n\n\n src/bitops.c | 74 ++++++++++++++++++++++++++++++++----------------------------\n 1 file changed, 39 insertions(+), 35 deletions(-)\n\n+-------------------------------------------------------------------------------\n| fix crash in BITFIELD GET when key is integer encoded\n| By oranagra, 2016-05-10 11:19:45 +0300\n+--------------------------------------------------------------------------------\nhttps://github.com/antirez/redis/commit/dcaeafc8280eb8329e7ce68e7ab02c67d98f0cf4\n\n\n src/bitops.c | 18 +++++++++++++++---\n 1 file changed, 15 insertions(+), 3 deletions(-)\n\n+-------------------------------------------------------------------------------\n| Clarify that the LOG_STR_SIZE includes null term.\n| By antirez, 2016-05-18 15:23:18 +0200\n+--------------------------------------------------------------------------------\nhttps://github.com/antirez/redis/commit/4ad088818a3353ebd619e8d43847b5d58108af20\n\n\n src/server.h | 2 +-\n 1 file changed, 1 insertion(+), 1 deletion(-)\n\n+-------------------------------------------------------------------------------\n| Test for BITFIELD regression #3221.\n| By antirez, 2016-05-18 14:53:30 +0200\n+--------------------------------------------------------------------------------\nhttps://github.com/antirez/redis/commit/f991cdc3e19c187035855355808575efd6b4c149\n\n\n tests/unit/bitfield.tcl | 5 +++++\n 1 file changed, 5 insertions(+)\n\n+-------------------------------------------------------------------------------\n| reduce struct padding by reordering members\n| By oranagra, 2016-05-16 20:12:11 +0300\n+--------------------------------------------------------------------------------\nhttps://github.com/antirez/redis/commit/cb3e89e2cb0753d2d111eaeadc9c73cbe24025ab\n\n\n src/quicklist.h | 2 +-\n 1 file changed, 1 insertion(+), 1 deletion(-)\n\n+-------------------------------------------------------------------------------\n| Actually use --with-lg-quantum=3 to build jemalloc.\n| By antirez, 2016-05-18 11:58:36 +0200\n+--------------------------------------------------------------------------------\nhttps://github.com/antirez/redis/commit/a7f0fb448c110e125eece44dc955d6939e494daa\n\nThis change is documented in deps/README.md but was lost in one way or\nthe other, neutralizing the benefits of 24 bytes size classes (and\nothers).\n\nClose #3208.\n\n deps/Makefile | 2 +-\n 1 file changed, 1 insertion(+), 1 deletion(-)\n\n+-------------------------------------------------------------------------------\n| redis-cli: integrate help.h with COMMAND output.\n| By antirez, 2016-05-07 13:03:25 +0200\n+--------------------------------------------------------------------------------\nhttps://github.com/antirez/redis/commit/029dc0d97fd492a2fd579796d4c1cc04053c7190\n\nUse the COMMAND output to fill with partial information the built-in\nhelp. This makes redis-cli able to at least complete commands that are\nexported by the Redis server it is connected to, but were not available\nin the help.h file when the redis-cli binary was compiled.\n\n src/redis-cli.c | 80 +++++++++++++++++++++++++++++++++++++++++++++++++--------\n 1 file changed, 70 insertions(+), 10 deletions(-)\n\n+-------------------------------------------------------------------------------\n| Removed dofile() from Lua\n| By Adam Baldwin, 2012-10-25 20:27:10 -0700\n+--------------------------------------------------------------------------------\nhttps://github.com/antirez/redis/commit/95def3aee044468504bb07633084afd49b085db3\n\n\n src/scripting.c | 2 ++\n 1 file changed, 2 insertions(+)\n\n\n================================================================================\nRedis 3.2.0     Released Fri May 06 08:47:10 CEST 2016\n================================================================================\n\nUpgrade urgency HIGH: 3.2-RC users should upgrade ASAP to this more\n                      stable release of Redis.\n\nHello, this is Redis 3.2.0 stable! And with the new release there is a new\nformat for the changelog. Now it is composed of a \"letter\" like the one\nyou are reading, followed by all the commits composing the release for people\ninterested in the details.\n\nThere are a few changes between the latest release candidate of Redis 3.2\nand the final 3.2.0 release. The main ones are the obvious bug fixes you\ncan find detailed below, also a few new things:\n\nCritical bugs fixed:\n\n* There was a problem in the way a cluster instance loaded the AOF that\n  could cause data written via scripts to be lost during reshardings.\n\nNew things:\n\n* There is a new very powerful BITFIELD command. Check the documentation\n  here: http://redis.io/commands/BITFIELD\n\n* CONFIG GET is allowed during the loading of the dataset.\n\n* The DEBUG command have new features and can show an help with DEBUG HELP.\n\n* redis-cli show hits about the commands arguments to the right.\n\n* GEORADIUS got a STORE / STOREDIST option to store the result into a target\n  key (as as orted set) instead of reporting it to the user.\n\n* Redis Cluster replicas migration now works in a slightly different way. In\n  the past a slave could migrate only to a master that used to have slaves\n  in the past (and if there was still trace of this information). Now instead\n  if a new slave gets at least a slot, and at least one other master in the\n  cluster has a slave, then the new master is considered a valid target for\n  replica migration. So if it will be orphaned and there is a spare slave\n  it will get one.\n\n* CLUSTER SLOTS output now includes the node ID (in a backward compatible\n  manner).\n\n* A lot of bug fixes you can read in the commits details below, with the\n  authors that kindly provided many useful patches. Thanks.\n\nAs usually what \"stable\" means is that we are confident the release is mature,\nhowever do your tests before putting it into production in your environemnt\nas it's fresh meat anyway.\n\nCheers,\nSalvatore\n\n+-------------------------------------------------------------------------------\n| Cluster: don't check scripts key slots during AOF loading.\n| By antirez, 2016-05-05 23:37:08 +0200\n+--------------------------------------------------------------------------------\nhttps://github.com/antirez/redis/commit/746e1bebb4baf876c1e8cd2fe2d468a1c41e5dc3\n\n\n src/scripting.c | 6 ++++--\n 1 file changed, 4 insertions(+), 2 deletions(-)\n\n+-------------------------------------------------------------------------------\n| redis-cli: remove debugging message.\n| By antirez, 2016-05-05 18:05:37 +0200\n+--------------------------------------------------------------------------------\nhttps://github.com/antirez/redis/commit/3907b059280898c6340b53982b3b65957535da7c\n\n\n src/redis-cli.c | 1 -\n 1 file changed, 1 deletion(-)\n\n+-------------------------------------------------------------------------------\n| Revert \"Fix commandCommand arity\"\n| By antirez, 2016-05-05 17:35:33 +0200\n+--------------------------------------------------------------------------------\nhttps://github.com/antirez/redis/commit/f01a2714582a9a916b41e6cb90e42474a104925d\n\nThis reverts commit 1189a4eae6d009fc0da8d50fd542ba1391542165.\n\nActually this is wrong, the command can be called without args at all.\n\n src/server.c | 2 +-\n 1 file changed, 1 insertion(+), 1 deletion(-)\n\n+-------------------------------------------------------------------------------\n| Fix commandCommand arity\n| By Ruben Bridgewater, 2016-01-04 11:39:45 +0100\n+--------------------------------------------------------------------------------\nhttps://github.com/antirez/redis/commit/1189a4eae6d009fc0da8d50fd542ba1391542165\n\n\n src/server.c | 2 +-\n 1 file changed, 1 insertion(+), 1 deletion(-)\n\n+-------------------------------------------------------------------------------\n| Fix a possible race condition of sdown detection if the connection to master/slave/sentinel decames disconnected just after the last PONG and before the next PING.\n| By Daniel Shih, 2016-01-12 17:06:47 +0800\n+--------------------------------------------------------------------------------\nhttps://github.com/antirez/redis/commit/d9dc0d777b775f2fe4f23f42e1b4130f4de1ed72\n\n\n src/sentinel.c | 2 ++\n 1 file changed, 2 insertions(+)\n\n+-------------------------------------------------------------------------------\n| Fix nanosecond conversion\n| By Jan-Erik Rediger, 2016-01-13 10:22:29 -0700\n+--------------------------------------------------------------------------------\nhttps://github.com/antirez/redis/commit/13bd702844eda7bccc7c672b6ff77f53e21ab841\n\n1 microsecond = 1000 nanoseconds\n1e3 = 1000\n10e3 = 10000\n\n src/redis-cli.c | 2 +-\n 1 file changed, 1 insertion(+), 1 deletion(-)\n\n+-------------------------------------------------------------------------------\n| redis-cli: don't free historyfile, is used later.\n| By antirez, 2016-05-05 13:57:57 +0200\n+--------------------------------------------------------------------------------\nhttps://github.com/antirez/redis/commit/f6b7df3aec1d8fddf3121c4315fea4bf45cc4cfe\n\n\n src/redis-cli.c | 2 +-\n 1 file changed, 1 insertion(+), 1 deletion(-)\n\n+-------------------------------------------------------------------------------\n| Cluster test 12: reshard back just a few slots to speedup the test.\n| By antirez, 2016-05-05 11:49:27 +0200\n+--------------------------------------------------------------------------------\nhttps://github.com/antirez/redis/commit/97ce72fa2d348f914fc40ccf0a32008c7362b817\n\n\n tests/cluster/tests/12-replica-migration-2.tcl | 14 +++++++-------\n 1 file changed, 7 insertions(+), 7 deletions(-)\n\n+-------------------------------------------------------------------------------\n| Cluster: make getNodeByQuery() responsible of -CLUSTERDOWN errors.\n| By antirez, 2016-05-05 11:33:43 +0200\n+--------------------------------------------------------------------------------\nhttps://github.com/antirez/redis/commit/708f486c77b455fa7ae1e87cf31278474eb9d432\n\nThis fixes a bug introduced by d827dbf, and makes the code consistent\nwith the logic of always allowing, while the cluster is down, commands\nthat don't target any key.\n\nAs a side effect the code is also simpler now.\n\n src/cluster.c | 13 +++++++++++--\n src/server.c  | 26 ++++++++++----------------\n 2 files changed, 21 insertions(+), 18 deletions(-)\n\n+-------------------------------------------------------------------------------\n| Fixes a typo\n| By Itamar Haber, 2016-01-28 21:47:18 +0200\n+--------------------------------------------------------------------------------\nhttps://github.com/antirez/redis/commit/1fc2ed61bec2f2bf266b48e566a197c5214b4350\n\n\n src/cluster.c | 2 +-\n 1 file changed, 1 insertion(+), 1 deletion(-)\n\n+-------------------------------------------------------------------------------\n| Reverse redirect address parse\n| By David Cavar, 2016-02-09 15:04:42 +0100\n+--------------------------------------------------------------------------------\nhttps://github.com/antirez/redis/commit/787d5ab9be45bf4feb6cfa8a227c185c93aaadae\n\nFix issue in case the redirect address is in ipv6 format. Parse from behind to extract last part of the response which represents actual port.\n src/redis-cli.c | 2 +-\n 1 file changed, 1 insertion(+), 1 deletion(-)\n\n+-------------------------------------------------------------------------------\n| Bind both IPv4 and IPv6 or exit with an error by default.\n| By antirez, 2016-05-05 10:02:42 +0200\n+--------------------------------------------------------------------------------\nhttps://github.com/antirez/redis/commit/0fda06225f19b18a370d63ac650a8bb61020235d\n\nThanks to @tushar2708 for the PR. I applied a slightly different fix.\nThanks to @cespare for reporting.\n\nClose #3024\nClose #3020\n\n src/server.c | 18 ++++++++++--------\n 1 file changed, 10 insertions(+), 8 deletions(-)\n\n+-------------------------------------------------------------------------------\n| Quick fix to avoid false positive in replica migration test.\n| By antirez, 2016-05-05 09:45:31 +0200\n+--------------------------------------------------------------------------------\nhttps://github.com/antirez/redis/commit/65707fa6b5bb38b5818af57ab93b9b1da47d708a\n\n\n tests/cluster/tests/12-replica-migration-2.tcl | 5 ++++-\n 1 file changed, 4 insertions(+), 1 deletion(-)\n\n+-------------------------------------------------------------------------------\n| Ensure slots are rechecked on EXEC.\n| By Chris Thunes, 2016-03-11 15:22:36 -0500\n+--------------------------------------------------------------------------------\nhttps://github.com/antirez/redis/commit/1f3ed652e2a6cfcbbd5300a31f5771f2ce842e98\n\nFixes #2515.\n\n src/server.c | 9 +++++++--\n 1 file changed, 7 insertions(+), 2 deletions(-)\n\n+-------------------------------------------------------------------------------\n| fix for #3187\n| By therealbill, 2016-04-22 10:43:48 -0500\n+--------------------------------------------------------------------------------\nhttps://github.com/antirez/redis/commit/3a4810678904af013901a896ab0bb3c71856644c\n\nI've renamed maxmemoryToString to evictPolicyToString since that is\nmore accurate (and easier to mentally connect with the correct data), as\nwell as updated the function to user server.maxmemory_policy rather than\nserver.maxmemory. Now with a default config it is actually returning\nthe correct policy rather than volatile-lru.\n\n src/config.c | 4 ++--\n src/server.c | 2 +-\n src/server.h | 2 +-\n 3 files changed, 4 insertions(+), 4 deletions(-)\n\n+-------------------------------------------------------------------------------\n| Fixed typo in README.md\n| By Seth Bergman, 2016-04-30 11:58:48 -0500\n+--------------------------------------------------------------------------------\nhttps://github.com/antirez/redis/commit/bba53d7fc7a759b53d72a7c3be17a00abe32039e\n\n\n README.md | 2 +-\n 1 file changed, 1 insertion(+), 1 deletion(-)\n\n+-------------------------------------------------------------------------------\n| fix variable\n| By Ryosuke Hasebe, 2016-03-30 23:09:36 +0900\n+--------------------------------------------------------------------------------\nhttps://github.com/antirez/redis/commit/ab7581489871eebcf0253915acc26efb27f5df23\n\n\n src/redis-trib.rb | 10 +++++-----\n 1 file changed, 5 insertions(+), 5 deletions(-)\n\n+-------------------------------------------------------------------------------\n| fix check_open_slots\n| By Ryosuke Hasebe, 2016-03-30 21:56:22 +0900\n+--------------------------------------------------------------------------------\nhttps://github.com/antirez/redis/commit/0fcf896ac14c6e5c57e3b79e836dd8bf7dad94b5\n\n\n src/redis-trib.rb | 3 ++-\n 1 file changed, 2 insertions(+), 1 deletion(-)\n\n+-------------------------------------------------------------------------------\n| Minor redis-cli wording change in --help output.\n| By antirez, 2016-05-04 22:34:17 +0200\n+--------------------------------------------------------------------------------\nhttps://github.com/antirez/redis/commit/b8a63635e39ce312b2c5664f2c2a59184849b8fb\n\n\n src/redis-cli.c | 3 ++-\n 1 file changed, 2 insertions(+), 1 deletion(-)\n\n+-------------------------------------------------------------------------------\n| Allow CONFIG GET during loading.\n| By antirez, 2016-05-04 15:45:38 +0200\n+--------------------------------------------------------------------------------\nhttps://github.com/antirez/redis/commit/ae95de93312d6bb2c8c365c31f2a3fd0b6d2c100\n\nThanks to @oranagra for the idea of allowing CONFIG GET during loading.\n\n src/config.c | 6 ++++++\n src/server.c | 2 +-\n 2 files changed, 7 insertions(+), 1 deletion(-)\n\n+-------------------------------------------------------------------------------\n| Command \"r\" flag removed from commands not accessing the key space.\n| By antirez, 2016-05-04 15:42:14 +0200\n+--------------------------------------------------------------------------------\nhttps://github.com/antirez/redis/commit/3ff8f57ef32e3b1ddd407b65d474f610881bef34\n\nThanks to @oranagra for the hint about misplaced 'r' flags.\n\n src/server.c | 70 ++++++++++++++++++++++++++++++------------------------------\n 1 file changed, 35 insertions(+), 35 deletions(-)\n\n+-------------------------------------------------------------------------------\n| DEBUG command self documentation.\n| By antirez, 2016-05-04 12:45:55 +0200\n+--------------------------------------------------------------------------------\nhttps://github.com/antirez/redis/commit/07b852d24ec8d7cb47044b096baf0af1410c69ed\n\n\n src/debug.c  | 49 ++++++++++++++++++++++++++++++++++++++++++++++++-\n src/server.c |  2 +-\n 2 files changed, 49 insertions(+), 2 deletions(-)\n\n+-------------------------------------------------------------------------------\n| various cleanups and minor fixes\n| By Oran Agra, 2016-04-25 16:49:57 +0300\n+--------------------------------------------------------------------------------\nhttps://github.com/antirez/redis/commit/cfc08b65b04cf972ebeadf3be9f39f2acd7672b3\n\n\n src/adlist.c             | 18 ++++++------------\n src/ae_epoll.c           |  6 ++----\n src/aof.c                |  5 ++++-\n src/db.c                 |  2 +-\n src/rdb.c                |  6 ++++--\n src/rio.c                |  5 +++--\n src/rio.h                |  2 ++\n src/server.h             |  3 +--\n tests/support/test.tcl   |  6 ------\n tests/unit/bitops.tcl    |  2 +-\n tests/unit/other.tcl     |  1 +\n tests/unit/scripting.tcl | 27 ++++++++++++++-------------\n 12 files changed, 39 insertions(+), 44 deletions(-)\n\n+-------------------------------------------------------------------------------\n| dict.c minor optimization\n| By Oran Agra, 2016-04-25 16:48:25 +0300\n+--------------------------------------------------------------------------------\nhttps://github.com/antirez/redis/commit/6710c8dc15680b756de26d1d45df110987b951b3\n\n\n src/dict.c | 8 ++++----\n 1 file changed, 4 insertions(+), 4 deletions(-)\n\n+-------------------------------------------------------------------------------\n| networking.c minor optimization\n| By Oran Agra, 2016-04-25 16:48:09 +0300\n+--------------------------------------------------------------------------------\nhttps://github.com/antirez/redis/commit/be5c0869821b16f18104d9ea62ab42bfa0615816\n\n\n src/networking.c | 11 +++++------\n 1 file changed, 5 insertions(+), 6 deletions(-)\n\n+-------------------------------------------------------------------------------\n| add DEBUG JEMALLC PURGE and JEMALLOC INFO cleanup\n| By Oran Agra, 2016-04-25 16:47:42 +0300\n+--------------------------------------------------------------------------------\nhttps://github.com/antirez/redis/commit/3ede6c7a506bcff3c7d2147c8af140dd4102a36e\n\n\n src/debug.c     | 17 ++++++++++++++++-\n src/redis-cli.c |  2 +-\n 2 files changed, 17 insertions(+), 2 deletions(-)\n\n+-------------------------------------------------------------------------------\n| fix small issues in redis 3.2\n| By Oran Agra, 2016-04-25 14:19:28 +0300\n+--------------------------------------------------------------------------------\nhttps://github.com/antirez/redis/commit/e2fab184efd01ffa0d510739f4d819a30b1d6787\n\n\n src/config.c | 2 ++\n src/rdb.c    | 2 +-\n 2 files changed, 3 insertions(+), 1 deletion(-)\n\n+-------------------------------------------------------------------------------\n| additional fix to issue #2948\n| By Oran Agra, 2016-04-25 14:18:40 +0300\n+--------------------------------------------------------------------------------\nhttps://github.com/antirez/redis/commit/9d57ceec08687545c2a63a2c18c28e2bcaf74664\n\n\n src/networking.c | 3 +++\n 1 file changed, 3 insertions(+)\n\n+-------------------------------------------------------------------------------\n| Reply with error on negative geo radius.\n| By antirez, 2016-05-04 08:59:56 +0200\n+--------------------------------------------------------------------------------\nhttps://github.com/antirez/redis/commit/7ba2cf5f8bea9cd125e773de147e3ea9b19ee2b0\n\nThanks to @tidwall for reporting.\nClose #3194.\n\n src/geo.c | 5 ++++-\n 1 file changed, 4 insertions(+), 1 deletion(-)\n\n+-------------------------------------------------------------------------------\n| Cluster regression test for #3043.\n| By antirez, 2016-05-02 18:36:09 +0200\n+--------------------------------------------------------------------------------\nhttps://github.com/antirez/redis/commit/38cf2bd257d09b360be6adf450d59592a359696d\n\nThe test works but is very slow so far, since it involves resharding\n1/5 of all the cluster slots from master 0 to the other 4 masters and\nback into the original master.\n\n tests/cluster/tests/12-replica-migration-2.tcl | 61 ++++++++++++++++++++++++++\n 1 file changed, 61 insertions(+)\n\n+-------------------------------------------------------------------------------\n| New masters with slots are now targets of migration if others are.\n| By antirez, 2016-05-02 16:41:56 +0200\n+--------------------------------------------------------------------------------\nhttps://github.com/antirez/redis/commit/7b618823c189c24313effbccda7022d167ea419c\n\nThis fixes issue #3043.\n\nBefore this fix, after a complete resharding of a master slots\nto other nodes, the master remains empty and the slaves migrate away\nto other masters with non-zero nodes. However the old master now empty,\nis no longer considered a target for migration, because the system has\nno way to tell it had slaves in the past.\n\nThis fix leaves the algorithm used in the past untouched, but adds a\nnew rule. When a new or old master which is empty and without slaves,\nare assigend with their first slot, if other masters in the cluster have\nslaves, they are automatically considered to be targets for replicas\nmigration.\n\n src/cluster.c | 36 +++++++++++++++++++++++++++++++++++-\n 1 file changed, 35 insertions(+), 1 deletion(-)\n\n+-------------------------------------------------------------------------------\n| Test ZINCRBY return value.\n| By antirez, 2016-05-02 08:57:30 +0200\n+--------------------------------------------------------------------------------\nhttps://github.com/antirez/redis/commit/1101b515c73dcb0ff4a868ba38a91dcebb5b85cc\n\n\n tests/unit/type/zset.tcl | 6 ++++++\n 1 file changed, 6 insertions(+)\n\n+-------------------------------------------------------------------------------\n| redis-cli preferences and rc file support.\n| By antirez, 2016-04-13 13:58:30 +0200\n+--------------------------------------------------------------------------------\nhttps://github.com/antirez/redis/commit/bbf93108ef2a7ac7bd53e26c96bf838f7c5e72df\n\n\n src/redis-cli.c | 102 ++++++++++++++++++++++++++++++++++++++++++++++----------\n 1 file changed, 85 insertions(+), 17 deletions(-)\n\n+-------------------------------------------------------------------------------\n| redis-cli hints.\n| By antirez, 2016-04-13 12:34:14 +0200\n+--------------------------------------------------------------------------------\nhttps://github.com/antirez/redis/commit/3fd3fca0dd38cb21c900e4ba98e3d41f333335aa\n\n\n deps/linenoise/linenoise.c |  8 +++++++\n deps/linenoise/linenoise.h |  2 +-\n src/redis-cli.c            | 53 ++++++++++++++++++++++++++++++++++++++++++++++\n 3 files changed, 62 insertions(+), 1 deletion(-)\n\n+-------------------------------------------------------------------------------\n| Linenoise updated again (hints support).\n| By antirez, 2016-04-12 23:39:18 +0200\n+--------------------------------------------------------------------------------\nhttps://github.com/antirez/redis/commit/34354473ffe8d60b80acdbc8c16b194f8bbd70a0\n\n\n deps/linenoise/README.markdown | 176 ++++++++++++++++++++++++++++++++++++++++-\n deps/linenoise/example.c       |  10 +++\n deps/linenoise/linenoise.c     |  55 ++++++++++++-\n deps/linenoise/linenoise.h     |  15 +++-\n 4 files changed, 248 insertions(+), 8 deletions(-)\n\n+-------------------------------------------------------------------------------\n| Linenoise updated.\n| By antirez, 2016-04-06 13:37:27 +0200\n+--------------------------------------------------------------------------------\nhttps://github.com/antirez/redis/commit/58229cd766fa02f399267310b5b488aac2c55a6a\n\nAs a side effect, cat commands.txt | redis-cli now is able to handle\nlines more than 4096 bytes.\n\n deps/linenoise/linenoise.c | 60 ++++++++++++++++++++++++++++++++++------------\n 1 file changed, 45 insertions(+), 15 deletions(-)\n\n+-------------------------------------------------------------------------------\n| ae.c: Fix delay until next timer event.\n| By antirez, 2016-04-04 14:08:16 +0200\n+--------------------------------------------------------------------------------\nhttps://github.com/antirez/redis/commit/29645f1f44926ac2662ed768fe1e369775a30b66\n\nThis fix was written by Anthony LaTorre.\nThe old code mis-calculated the amount of time to wait till next event.\n\n src/ae.c | 21 ++++++++++++---------\n 1 file changed, 12 insertions(+), 9 deletions(-)\n\n+-------------------------------------------------------------------------------\n| ae.c: comment to explain why we have a useless maxId check.\n| By antirez, 2016-04-04 12:23:10 +0200\n+--------------------------------------------------------------------------------\nhttps://github.com/antirez/redis/commit/aa79c1f1c1d288e4cc2c0f4689ad01488678bf9d\n\n\n src/ae.c | 6 +++++-\n 1 file changed, 5 insertions(+), 1 deletion(-)\n\n+-------------------------------------------------------------------------------\n| Fix ae.c to avoid timers infinite loop.\n| By antirez, 2016-01-08 15:05:14 +0100\n+--------------------------------------------------------------------------------\nhttps://github.com/antirez/redis/commit/0b69c9865619b54b75576e67aaafe7b018734bec\n\nThis fix was suggested by Anthony LaTorre, that provided also a good\ntest case that was used to verify the fix.\n\nThe problem with the old implementation is that, the time returned by\na timer event (that is the time after it want to run again) is added\nto the event *start time*. So if the event takes, in order to run, more\nthan the time it says it want to be scheduled again for running, an\ninfinite loop is triggered.\n\n src/ae.c          | 51 ++++++++++++++++++++++-----------------------------\n src/ae.h          |  3 +++\n src/anet.h        |  2 ++\n src/redis-trib.rb |  2 +-\n 4 files changed, 28 insertions(+), 30 deletions(-)\n\n+-------------------------------------------------------------------------------\n| BITFIELD: overflow wrap behavior fuzz tester.\n| By antirez, 2016-03-02 17:22:42 +0100\n+--------------------------------------------------------------------------------\nhttps://github.com/antirez/redis/commit/258857cd62e0eb70da32742651a55213fbc28a53\n\n\n tests/unit/bitfield.tcl | 51 +++++++++++++++++++++++++++++++++++++++++++++++++\n 1 file changed, 51 insertions(+)\n\n+-------------------------------------------------------------------------------\n| BITFIELD basic unit tests.\n| By antirez, 2016-03-02 16:31:02 +0100\n+--------------------------------------------------------------------------------\nhttps://github.com/antirez/redis/commit/35d05d6dc5d7fb810e732f9de7b05c6b14933fb6\n\n\n tests/unit/bitfield.tcl | 86 ++++++++++++++++++++++++++++++++++++++++++++++++-\n 1 file changed, 85 insertions(+), 1 deletion(-)\n\n+-------------------------------------------------------------------------------\n| BITFIELD: Farest bit set is offset+bits-1. Off by one error fixed.\n| By antirez, 2016-03-02 16:20:28 +0100\n+--------------------------------------------------------------------------------\nhttps://github.com/antirez/redis/commit/6cf83feffad7f7b7693a207a9d63278354769ece\n\n\n src/bitops.c | 6 ++++--\n 1 file changed, 4 insertions(+), 2 deletions(-)\n\n+-------------------------------------------------------------------------------\n| BITFIELD: overflow fuzzy testing.\n| By antirez, 2016-03-02 15:15:18 +0100\n+--------------------------------------------------------------------------------\nhttps://github.com/antirez/redis/commit/b4d65c9501be01531eb8fbeb4ba2b444e35d6494\n\n\n tests/test_helper.tcl   |  1 +\n tests/unit/bitfield.tcl | 52 +++++++++++++++++++++++++++++++++++++++++++++++++\n 2 files changed, 53 insertions(+)\n\n+-------------------------------------------------------------------------------\n| Fix typo in bitops.tcl comment.\n| By antirez, 2016-03-02 15:14:53 +0100\n+--------------------------------------------------------------------------------\nhttps://github.com/antirez/redis/commit/d75e0fdbe6ecf3074b18c4dd1e8b71a474254ccc\n\n\n tests/unit/bitops.tcl | 2 +-\n 1 file changed, 1 insertion(+), 1 deletion(-)\n\n+-------------------------------------------------------------------------------\n| More BITFIELD fixes. Overflow conditional simplified.\n| By antirez, 2016-03-02 15:13:45 +0100\n+--------------------------------------------------------------------------------\nhttps://github.com/antirez/redis/commit/5f3ef73ed41be6e051daad9fdb7efa91b4ca682d\n\nSee issue #3114.\n\n src/bitops.c | 17 ++++++++---------\n 1 file changed, 8 insertions(+), 9 deletions(-)\n\n+-------------------------------------------------------------------------------\n| bitops/bitfield: fix length, overflow condition and *sign\n| By Sun He, 2016-03-02 18:11:30 +0800\n+--------------------------------------------------------------------------------\nhttps://github.com/antirez/redis/commit/5b9aa5026204fb6c8b0098d4e47c2e001cf06151\n\n\n src/bitops.c | 13 ++++++++-----\n 1 file changed, 8 insertions(+), 5 deletions(-)\n\n+-------------------------------------------------------------------------------\n| Fix INFO commandstats reporting when argv is rewritten.\n| By antirez, 2016-03-02 08:51:27 +0100\n+--------------------------------------------------------------------------------\nhttps://github.com/antirez/redis/commit/ba9154d7e7bf959b002533384319a1e90545447b\n\nWe want to report the original command in the stats, for example GEOADD,\neven when what is actually executed is the ZADD implementation.\n\n src/scripting.c | 2 +-\n src/server.c    | 4 ++--\n 2 files changed, 3 insertions(+), 3 deletions(-)\n\n+-------------------------------------------------------------------------------\n| BITFIELD: refactoring & fix of retval on FAIL.\n| By antirez, 2016-02-29 09:08:46 +0100\n+--------------------------------------------------------------------------------\nhttps://github.com/antirez/redis/commit/76b22e3728e37fe11582b71802bf98a2be09623f\n\n\n src/bitops.c | 32 ++++++++++++++++++++++++--------\n 1 file changed, 24 insertions(+), 8 deletions(-)\n\n+-------------------------------------------------------------------------------\n| BITFIELD: Fix #<index> form parsing.\n| By antirez, 2016-02-26 15:53:29 +0100\n+--------------------------------------------------------------------------------\nhttps://github.com/antirez/redis/commit/c333a9e2d7873190b22aaee8835a188bc55b60dc\n\n\n src/bitops.c | 10 ++++------\n 1 file changed, 4 insertions(+), 6 deletions(-)\n\n+-------------------------------------------------------------------------------\n| BITFIELD: Support #<index> offsets form.\n| By antirez, 2016-02-26 15:16:24 +0100\n+--------------------------------------------------------------------------------\nhttps://github.com/antirez/redis/commit/f84871cb5dd3bb3c04bfd7ac53b6e06b246f511f\n\n\n src/bitops.c | 29 +++++++++++++++++++++++------\n 1 file changed, 23 insertions(+), 6 deletions(-)\n\n+-------------------------------------------------------------------------------\n| BITFIELD command initial implementation.\n| By antirez, 2016-02-25 23:31:45 +0100\n+--------------------------------------------------------------------------------\nhttps://github.com/antirez/redis/commit/761a77287107ce53dbf4755f1435cc9660b6c86d\n\nThe new bitfield command is an extension to the Redis bit operations,\nwhere not just single bit operations are performed, but the array of\nbits composing a string, can be addressed at random, not aligned\noffsets, with any width unsigned and signed integers like u8, s5, u10\n(up to 64 bit signed integers and 63 bit unsigned integers).\n\nThe BITFIELD command supports subcommands that can SET, GET, or INCRBY\nthose arbitrary bit counters, with multiple overflow semantics.\n\nTrivial and credits:\n\nA similar command was imagined a few times in the past, but for\nsome reason looked a bit far fetched or not well specified.\nFinally the command was proposed again in a clear form by\nYoav Steinberg from Redis Labs, that proposed a set of commands on\narbitrary sized integers stored at bit offsets.\n\nStarting from this proposal I wrote an initial specification of a single\ncommand with sub-commands similar to what Yoav envisioned, using short\nnames for types definitions, and adding control on the overflow.\n\nThis commit is the resulting implementation.\n\nExamples:\n\n    BITFIELD mykey OVERFLOW wrap INCRBY i2 10 -1 GET i2 10\n\n src/bitops.c | 506 +++++++++++++++++++++++++++++++++++++++++++++++++++++++----\n src/server.c |   1 +\n src/server.h |   1 +\n 3 files changed, 476 insertions(+), 32 deletions(-)\n\n+-------------------------------------------------------------------------------\n| Eliminates engineers near the equator & prime meridian\n| By Itamar Haber, 2016-02-18 15:11:30 -0800\n+--------------------------------------------------------------------------------\nhttps://github.com/antirez/redis/commit/4b89ea3a95ef72353e14e0eb5cbf293bf2dc8b48\n\n\n src/geo.c | 8 ++++----\n 1 file changed, 4 insertions(+), 4 deletions(-)\n\n+-------------------------------------------------------------------------------\n| Fixes a typo in a comment\n| By Itamar Haber, 2016-02-18 15:01:34 -0800\n+--------------------------------------------------------------------------------\nhttps://github.com/antirez/redis/commit/0f46f9bd423a146f96e1993aca6221e1305f9a28\n\n\n src/geo.c | 2 +-\n 1 file changed, 1 insertion(+), 1 deletion(-)\n\n+-------------------------------------------------------------------------------\n| Adjusts accuracy for GEODIST\n| By Itamar Haber, 2016-02-18 15:00:39 -0800\n+--------------------------------------------------------------------------------\nhttps://github.com/antirez/redis/commit/9de844603c5203ae6ff6e7882a3dcb47a9f79a85\n\n\n src/geo.c | 2 +-\n 1 file changed, 1 insertion(+), 1 deletion(-)\n\n+-------------------------------------------------------------------------------\n| addReplyHumanLongDouble() API added.\n| By antirez, 2016-02-18 22:08:47 +0100\n+--------------------------------------------------------------------------------\nhttps://github.com/antirez/redis/commit/79e553a58d7f814fd08482b118561fcf9854b1df\n\nSend a long double or double as a bulk reply, in a human friendly\nformat.\n\n src/networking.c | 9 +++++++++\n src/server.h     | 1 +\n 2 files changed, 10 insertions(+)\n\n+-------------------------------------------------------------------------------\n| Fix GEORADIUS STORE/DIST refcount after backport to 3.2.\n| By antirez, 2016-02-18 15:33:02 +0100\n+--------------------------------------------------------------------------------\nhttps://github.com/antirez/redis/commit/158d1e2fbf6badb881a4d78623fd1bffde34cc49\n\n\n src/geo.c | 2 ++\n 1 file changed, 2 insertions(+)\n\n+-------------------------------------------------------------------------------\n| GEOADD STORE/STOREDIST tests.\n| By antirez, 2016-02-18 14:42:42 +0100\n+--------------------------------------------------------------------------------\nhttps://github.com/antirez/redis/commit/123cd88286127cc20684bf0457cb51107a67cfa2\n\n\n tests/unit/geo.tcl | 54 ++++++++++++++++++++++++++++++++++++++++++++++++++++++\n 1 file changed, 54 insertions(+)\n\n+-------------------------------------------------------------------------------\n| New options for GEORADIUS: STORE and STOREDIST.\n| By antirez, 2016-02-18 10:24:11 +0100\n+--------------------------------------------------------------------------------\nhttps://github.com/antirez/redis/commit/0b6daf5a6b27447f03c76387b8b707ce0ab7b08d\n\nRelated to issue #3019.\n\n src/geo.c    | 143 +++++++++++++++++++++++++++++++++++++++++------------------\n src/server.c |   4 +-\n src/server.h |   1 +\n src/t_zset.c |  18 +++++---\n 4 files changed, 117 insertions(+), 49 deletions(-)\n\n+-------------------------------------------------------------------------------\n| Include full paths on RDB/AOF files errors.\n| By antirez, 2016-02-15 16:14:56 +0100\n+--------------------------------------------------------------------------------\nhttps://github.com/antirez/redis/commit/f7af1beaab938b7e319d1b91d7736f043b7ef682\n\nClose #3086.\n\n src/aof.c | 17 +++++++++++++++--\n src/rdb.c | 19 +++++++++++++++++--\n 2 files changed, 32 insertions(+), 4 deletions(-)\n\n+-------------------------------------------------------------------------------\n| Remove Lua state reference from buffers in lua_cmsgpack.\n| By antirez, 2016-02-10 09:12:17 +0100\n+--------------------------------------------------------------------------------\nhttps://github.com/antirez/redis/commit/0b4a628fc716ab6b88c9823b143de174601a790d\n\n\n deps/lua/src/lua_cmsgpack.c | 53 +++++++++++++++++++++------------------------\n 1 file changed, 25 insertions(+), 28 deletions(-)\n\n+-------------------------------------------------------------------------------\n| cmsgpack: pass correct osize values to lua allocator, update correct buf free space in cmsgpack\n| By yoav@monfort.co.il, 2016-02-07 20:24:28 +0200\n+--------------------------------------------------------------------------------\nhttps://github.com/antirez/redis/commit/43509f686452fba68966aa89b87d1be065b50e17\n\n\n deps/lua/src/lua_cmsgpack.c | 8 ++++----\n 1 file changed, 4 insertions(+), 4 deletions(-)\n\n+-------------------------------------------------------------------------------\n| Fixes a typo\n| By Itamar Haber, 2016-02-03 11:04:09 -0800\n+--------------------------------------------------------------------------------\nhttps://github.com/antirez/redis/commit/cd9f7c6976f81c0e9ffae9e34b31eda19384a7dd\n\n\n src/server.c | 4 ++--\n 1 file changed, 2 insertions(+), 2 deletions(-)\n\n+-------------------------------------------------------------------------------\n| Adds keyspace notifications for lrem\n| By Itamar Haber, 2016-02-02 09:58:19 -0800\n+--------------------------------------------------------------------------------\nhttps://github.com/antirez/redis/commit/bf30f5a73922e5111d6a39da7351e22357213134\n\n\n src/t_list.c | 7 ++++++-\n 1 file changed, 6 insertions(+), 1 deletion(-)\n\n+-------------------------------------------------------------------------------\n| Typo ASII -> ASCII fixed in comment.\n| By antirez, 2016-01-29 12:08:10 +0100\n+--------------------------------------------------------------------------------\nhttps://github.com/antirez/redis/commit/0c7c7631d206964b8bf1dae3db286a3acda4edad\n\n\n src/server.h | 2 +-\n 1 file changed, 1 insertion(+), 1 deletion(-)\n\n+-------------------------------------------------------------------------------\n| Cluster: include node IDs in SLOTS output.\n| By antirez, 2016-01-29 12:00:38 +0100\n+--------------------------------------------------------------------------------\nhttps://github.com/antirez/redis/commit/0f3fb0097ae70e36ee65468b79f0be4160934bb4\n\nCLUSTER SLOTS now includes IDs in the nodes description associated with\na given slot range. Certain client libraries implementations need a way\nto reference a node in an unique way, so they were relying on CLUSTER\nNODES, that is not a stable API and may change frequently depending on\nRedis Cluster future requirements.\n\n src/cluster.c | 8 ++++++--\n 1 file changed, 6 insertions(+), 2 deletions(-)\n\n\n~~~~~~~~~~~~~~~~~~~~~~~~~~ OLD STYLE CHANGELOG ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n\n--[ Redis 3.2.0 RC3 (version 3.1.103) ] Release date: 28 jan 2016\n\nUpgrade urgency MODERATE: this release fixes a non trivial Sentinel crash.\n\n* [FIX] avg_ttl reporting in INFO improved. (Salvatore Sanfilippo)\n* [FIX] Sentinel: improve handling of known Sentinel instances.\n        (Salvatore Sanfilippo, thanks to Paweł Kowalczykf or the original\n         crash report).\n* [FIX] Redis Cluster address update (via gossip section) processing improved\n        to avoid initiating inwanted handshakes.\n\n--[ Redis 3.2.0 RC2 (version 3.1.102) ] Release date: 25 jan 2016\n\nUpgrade urgency MODERATE: this release fixes important Redis Cluster bugs.\n\n* [FIX] Many fixes to MIGRATE multiple keys implementation. The command\n        could handle errors in a faulty way leading to crashes or other\n        unexpected behaviors. MIGRATE command refactoring.\n        (The analysis of the faulty conditions was conducted by\n         Kevin McGehee. The fix was developed by Salvatore Sanfilippo)\n* [FIX] A Redis Cluster node crash was fixed because of wrong handling of\n        node->slaveof pointers.\n        (Reported by JackyWoo, fixed by Salvatore Sanfilippo)\n* [FIX] Fix redis-trib rebalance when nodes need to be left empty because\n        the specified weight is zero.\n        (Reported by Shahar Mor, fixed by Salvatore Sanfilippo)\n* [FIX] MIGRATE: Never send -ASK redirections for MIGRATE when there are\n        open slots. Redis-trib and other cluster management utility must\n        always be free to move keys between nodes about open slots, in order\n        to reshard, fix the cluster configuration, and so forth.\n        (Salvatore Sanfilippo)\n* [FIX] Lua debugger crash when printing too deeply nested objects.\n        (Reported by Paul Kulchenko, fixed by Salvatore Sanfilippo)\n* [FIX] Redis-cli implementation of Lua debugging now allows to use the\n        SCRIPT DEBUG command directly, switching to debugging mode as needed.\n        (Reported by Paul Kulchenko, fixed by Salvatore Sanfilippo)\n* [FIX] Redis-trib is now able to fix more errors. A new CLUSTER subcommand\n        called BUMPEPOCH was introduced in order to support new modes\n        for the \"fix\" subcommand. (Salvatore Sanfilippo)\n* [NEW] Redis proctected mode: this feature improves Redis security and makes\n        harder to run Redis in a configuration that is unsecure because no\n        firewalling was used in order to protect Redis from external accesses.\n        See this Reddit post for more info: https://www.reddit.com/r/redis/comments/3zv85m/new_security_feature_redis_protected_mode/ (Salvatore Sanfilippo)\n* [NEW] Cluster/Sentinel tests now use OSX leak to perform leak detection\n        at the end of every unit. (Salvatore Sanfilippo)\n* [NEW] Detect and show server crashes during Cluster/Sentinel tests.\n        (Salvatore Sanfilippo)\n* [NEW] More reliable Cluster/Sentinel test becuase of timing errors and\n        -LOADING errors. (Salvatore Sanfilippo)\n\n--[ Redis 3.2.0 RC1 (version 3.1.101) ] Release date: 23 dec 2015\n\nThis is the first release candidate of Redis 3.2. The changelog above shows\nwhat's new in this release. In the next of the following weeks we'll test\nin depth every feature and we'll release new RCs as bugs are discovered\nand fixed. Note that while 3.2 looks solid already, it contains many changes\nto its internals. It's still fresh code compared to 3.0.\n\nGeneral changes:\n\n* [NEW] Lua scripts \"effect replication\". Makes possible to write scripts\n        with side effects, use of random commands, and so forth.\n        (Salvatore Sanfilippo)\n* [NEW] Lua scripts selective replication. Makes possible to replicate to\n        slaves and AOF only selected parts of a script. (Design by\n        Yossi Gottlieb and Salvatore Sanfilippo, implemented by Salvatore)\n* [NEW] Geo indexing support via GEOADD, GEORADIUS and other commands.\n        See http://redis.io/commands/geoadd for more information.\n        (Initially implemented in a fork of Redis called \"Ardb\".\n         Matt Stancliff \"imported back\" the work to Redis and created the\n         initial API and implementation. Salvatore Sanfilippo modified\n         the API and the implementation, fixed bugs, improved performances\n         and unified the duplicated code with t_zset.c)\n* [NEW] Lua debugger. A complete stepping, remote debugger for Lua scripts.\n        Video here: https://www.youtube.com/watch?v=IMvRfStaoyM\n        (Salvatore Sanfilippo with many feedbacks and testing from\n         Itamar Haber)\n* [NEW] SDS improvements for speed and maximum string length.\n        This makes Redis more memory efficient in different use cases.\n        (Design and implementation by Oran Agra, some additional work\n         by Salvatore Sanfilippo)\n* [NEW] Modify Jemalloc size classes to make certain Redis objects fit\n        better, improving memory efficiency. (Oran Agra)\n* [NEW] Better consistency behavior between masters and slaves for expired\n        keys. The slaves are only able to logically consider a key expired\n        even before receiving the `DEL` command from the master. This avoids\n        the delay there is sometimes between the natural expire of the key\n        and the moment the slave is notified. (Salvatore Sanfilippo)\n* [NEW] Support daemon supervision by upstart or systemd (Pierre-Yves Ritschard)\n* [NEW] New encoding for the List type: Quicklists. Very important memory\n        savings and storage space in RDB gains (up to 10x sometimes).\n        (Design and implementation by Matt Stancliff. RDB storage reworked\n         by Salvatore Sanfilippo)\n* [NEW] SPOP with optional count argument. (Initial implementation by\n        Alon Diamant, mostly reimplemented by Salvatore Sanfilippo for speed\n        and in order to make the replication of a this class of commands,\n        having as logical effect the execution of multiple commands, possible).\n* [NEW] Support for RDB AUX fields. Now RDB files contain additional info\n        like the creation date, version of Redis generating it and so forth.\n        (Salvatore Sanfilippo)\n* [NEW] Faster RDB loading via the RESIZEDB opcode to avoid useless hash tables\n        rehashings. (Salvatore Sanfilippo)\n* [NEW] HSTRLEN command. (@landmime and Salvatore Sanfilippo)\n* [NEW] CONFIG SET/GET implementations refactored, partially rewritten,\n        now exposing more config options. (Salvatore Sanfilippo)\n* [NEW] CLUSTER NODES major speedup. (Salvatore Sanfilippo)\n* [NEW] CLIENT KILL TYPE MASTER, to kill (disconnect) masters from slaves.\n        (Salvatore Sanfilippo)\n* [NEW] Jemalloc updated to 4.0.3 (Salvatore Sanfilippo)\n* [NEW] DEBUG RESTART/CRASH-AND-RECOVER [delay] (Salvatore Sanfilippo)\n* [NEW] CLIENT REPLY command implemented: ON, OFF and SKIP modes.\n        (Salvatore Sanfilippo)\n* [NEW] Crash report produced by Redis on crash improved. (Salvatore Sanfilippo)\n* [NEW] Better memory test on crash. (Salvatore Sanfilippo)\n\nRedis Cluster changes:\n\nAll the Redis Cluster changes in 3.2 were backported to 3.0, so there is\ntechnically nothing new for now in this release. The most important things\nare:\n\n* Cluster rebalancing.\n* A pipelined MIGRATE command which is 10x faster and makes resharding\n  and rebalancing faster.\n* Improved replicas migration.\n* As a side effect of quicklists encoding (see above items), moving big\n  lists between nodes is now a lot faster.\n\nRedis Sentinel changes:\n\n* [NEW] Sentinel connection sharing. Makes Sentinels able to scale to\n        monitor many masters. (Salvatore Sanfilippo)\n* [NEW] New SENTINEL INFO-CACHE command. (Matt Stancliff)\n* More things backported to Redis 3.0 in the past, so no longer news of 3.2.\n\nMigrating from 3.0 to 3.2\n=========================\n\nRedis 3.0 is mostly a strict subset of 3.2, you should not have any problem\nupgrading your application from 3.0 to 3.2. However this is a list of small\nnon-backward compatible changes introduced in the 3.2 release:\n\n* The default configuration file now binds to 127.0.0.1.\n* Slaves try to no longer expose stale data about already expired keys.\n* The RDB format changed. Redis 3.2 is still able to read 3.0 (and all the\n  past versions) files, but not the other way around.\n* Behavior on crash may be different. The crash log format changed and\n  the memory test executed is now different.\n\n--------------------------------------------------------------------------------\n\nCredits: For each release, a list of changes with the relative author is\nprovided. Where not specified the implementation and design is done by\nSalvatore Sanfilippo. Thanks to Redis Labs for making all this possible.\nAlso many thanks to all the other contributors and the amazing community\nwe have.\n\nCommit messages may contain additional credits.\n\nCheers,\nSalvatore\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.8/BUGS",
    "content": "Please check https://github.com/antirez/redis/issues\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.8/CONTRIBUTING",
    "content": "Note: by contributing code to the Redis project in any form, including sending\na pull request via Github, a code fragment or patch via private email or\npublic discussion groups, you agree to release your code under the terms\nof the BSD license that you can find in the COPYING file included in the Redis\nsource distribution. You will include BSD license in the COPYING file within\neach source file that you contribute.\n\n# IMPORTANT: HOW TO USE REDIS GITHUB ISSUES\n\n* Github issues SHOULD ONLY BE USED to report bugs, and for DETAILED feature\n  requests. Everything else belongs to the Redis Google Group.\n\n  PLEASE DO NOT POST GENERAL QUESTIONS that are not about bugs or suspected\n  bugs in the Github issues system. We'll be very happy to help you and provide\n  all the support Reddit sub:\n\n      http://reddit.com/r/redis\n\n  There is also an active community of Redis users at Stack Overflow:\n\n      http://stackoverflow.com/questions/tagged/redis\n\n# How to provide a patch for a new feature\n\n1. If it is a major feature or a semantical change, please post it as a new submission in r/redis on Reddit at http://reddit.com/r/redis. Try to be passionate about why the feature is needed, make users upvote your proposal to gain traction and so forth. Read feedbacks about the community. But in this first step **please don't write code yet**.\n\n2. If in step 1 you get an acknowledge from the project leaders, use the\n   following procedure to submit a patch:\n\n    a. Fork Redis on github ( http://help.github.com/fork-a-repo/ )\n    b. Create a topic branch (git checkout -b my_branch)\n    c. Push to your branch (git push origin my_branch)\n    d. Initiate a pull request on github ( http://help.github.com/send-pull-requests/ )\n    e. Done :)\n\nFor minor fixes just open a pull request on Github.\n\nThanks!\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.8/COPYING",
    "content": "Copyright (c) 2006-2015, Salvatore Sanfilippo\nAll rights reserved.\n\nRedistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:\n\n    * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.\n    * 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.\n    * Neither the name of Redis nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.\n\nTHIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT OWNER 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.\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.8/INSTALL",
    "content": "See README\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.8/MANIFESTO",
    "content": "[Note: this is the Redis manifesto, for general information about\n       installing and running Redis read the README file instead.]\n\nRedis Manifesto\n===============\n\n1 - A DSL for Abstract Data Types. Redis is a DSL (Domain Specific Language)\n    that manipulates abstract data types and implemented as a TCP daemon.\n    Commands manipulate a key space where keys are binary-safe strings and\n    values are different kinds of abstract data types. Every data type\n    represents an abstract version of a fundamental data structure. For instance\n    Redis Lists are an abstract representation of linked lists. In Redis, the\n    essence of a data type isn't just the kind of operations that the data types\n    support, but also the space and time complexity of the data type and the\n    operations performed upon it.\n\n2 - Memory storage is #1. The Redis data set, composed of defined key-value\n    pairs, is primarily stored in the computer's memory. The amount of memory in\n    all kinds of computers, including entry-level servers, is increasing\n    significantly each year. Memory is fast, and allows Redis to have very\n    predictable performance. Datasets composed of 10k or 40 millions keys will\n    perform similarly. Complex data types like Redis Sorted Sets are easy to\n    implement and manipulate in memory with good performance, making Redis very\n    simple. Redis will continue to explore alternative options (where data can\n    be optionally stored on disk, say) but the main goal of the project remains\n    the development of an in-memory database.\n\n3 - Fundamental data structures for a fundamental API. The Redis API is a direct\n    consequence of fundamental data structures. APIs can often be arbitrary but\n    not an API that resembles the nature of fundamental data structures. If we\n    ever meet intelligent life forms from another part of the universe, they'll\n    likely know, understand and recognize the same basic data structures we have\n    in our computer science books. Redis will avoid intermediate layers in API,\n    so that the complexity is obvious and more complex operations can be\n    performed as the sum of the basic operations.\n\n4 - Code is like a poem; it's not just something we write to reach some\n    practical result. Sometimes people that are far from the Redis philosophy\n    suggest using other code written by other authors (frequently in other\n    languages) in order to implement something Redis currently lacks. But to us\n    this is like if Shakespeare decided to end Enrico IV using the Paradiso from\n    the Divina Commedia. Is using any external code a bad idea? Not at all. Like\n    in \"One Thousand and One Nights\" smaller self contained stories are embedded\n    in a bigger story, we'll be happy to use beautiful self contained libraries\n    when needed. At the same time, when writing the Redis story we're trying to\n    write smaller stories that will fit in to other code.\n\n5 - We're against complexity. We believe designing systems is a fight against\n    complexity. We'll accept to fight the complexity when it's worthwhile but\n    we'll try hard to recognize when a small feature is not worth 1000s of lines\n    of code. Most of the time the best way to fight complexity is by not\n    creating it at all.\n\n6 - Two levels of API. The Redis API has two levels: 1) a subset of the API fits\n    naturally into a distributed version of Redis and 2) a more complex API that\n    supports multi-key operations. Both are useful if used judiciously but\n    there's no way to make the more complex multi-keys API distributed in an\n    opaque way without violating our other principles. We don't want to provide\n    the illusion of something that will work magically when actually it can't in\n    all cases. Instead we'll provide commands to quickly migrate keys from one\n    instance to another to perform multi-key operations and expose the tradeoffs\n    to the user.\n\n7 - We optimize for joy. We believe writing code is a lot of hard work, and the\n    only way it can be worth is by enjoying it. When there is no longer joy in\n    writing code, the best thing to do is stop. To prevent this, we'll avoid\n    taking paths that will make Redis less of a joy to develop.\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.8/Makefile",
    "content": "# Top level makefile, the real shit is at src/Makefile\n\ndefault: all\n\n.DEFAULT:\n\tcd src && $(MAKE) $@\n\ninstall:\n\tcd src && $(MAKE) $@\n\n.PHONY: install\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.8/README.md",
    "content": "This README is just a fast *quick start* document. You can find more detailed documentation at http://redis.io.\n\nWhat is Redis?\n--------------\n\nRedis is often referred as a *data structures* server. What this means is that Redis provides access to mutable data structures via a set of commands, which are sent using a *server-client* model with TCP sockets and a simple protocol. So different processes can query and modify the same data structures in a shared way.\n\nData structures implemented into Redis have a few special properties:\n\n* Redis cares to store them on disk, even if they are always served and modified into the server memory. This means that Redis is fast, but that is also non-volatile.\n* Implementation of data structures stress on memory efficiency, so data structures inside Redis will likely use less memory compared to the same data structure modeled using an high level programming language.\n* Redis offers a number of features that are natural to find in a database, like replication, tunable levels of durability, cluster, high availability.\n\nAnother good example is to think of Redis as a more complex version of memcached, where the operations are not just SETs and GETs, but operations to work with complex data types like Lists, Sets, ordered data structures, and so forth.\n\nIf you want to know more, this is a list of selected starting points:\n\n* Introduction to Redis data types. http://redis.io/topics/data-types-intro\n* Try Redis directly inside your browser. http://try.redis.io\n* The full list of Redis commands. http://redis.io/commands\n* There is much more inside the Redis official documentation. http://redis.io/documentation\n\nBuilding Redis\n--------------\n\nRedis can be compiled and used on Linux, OSX, OpenBSD, NetBSD, FreeBSD.\nWe support big endian and little endian architectures, and both 32 bit\nand 64 bit systems.\n\nIt may compile on Solaris derived systems (for instance SmartOS) but our\nsupport for this platform is *best effort* and Redis is not guaranteed to\nwork as well as in Linux, OSX, and \\*BSD there.\n\nIt is as simple as:\n\n    % make\n\nYou can run a 32 bit Redis binary using:\n\n    % make 32bit\n\nAfter building Redis is a good idea to test it, using:\n\n    % make test\n\nFixing build problems with dependencies or cached build options\n---------\n\nRedis has some dependencies which are included into the `deps` directory.\n`make` does not rebuild dependencies automatically, even if something in the\nsource code of dependencies is changed.\n\nWhen you update the source code with `git pull` or when code inside the\ndependencies tree is modified in any other way, make sure to use the following\ncommand in order to really clean everything and rebuild from scratch:\n\n    make distclean\n\nThis will clean: jemalloc, lua, hiredis, linenoise.\n\nAlso if you force certain build options like 32bit target, no C compiler\noptimizations (for debugging purposes), and other similar build time options,\nthose options are cached indefinitely until you issue a `make distclean`\ncommand.\n\nFixing problems building 32 bit binaries\n---------\n\nIf after building Redis with a 32 bit target you need to rebuild it\nwith a 64 bit target, or the other way around, you need to perform a\n`make distclean` in the root directory of the Redis distribution.\n\nIn case of build errors when trying to build a 32 bit binary of Redis, try\nthe following steps:\n\n* Install the packages libc6-dev-i386 (also try g++-multilib).\n* Try using the following command line instead of `make 32bit`:\n  `make CFLAGS=\"-m32 -march=native\" LDFLAGS=\"-m32\"`\n\nAllocator\n---------\n\nSelecting a non-default memory allocator when building Redis is done by setting\nthe `MALLOC` environment variable. Redis is compiled and linked against libc\nmalloc by default, with the exception of jemalloc being the default on Linux\nsystems. This default was picked because jemalloc has proven to have fewer\nfragmentation problems than libc malloc.\n\nTo force compiling against libc malloc, use:\n\n    % make MALLOC=libc\n\nTo compile against jemalloc on Mac OS X systems, use:\n\n    % make MALLOC=jemalloc\n\nVerbose build\n-------------\n\nRedis will build with a user friendly colorized output by default.\nIf you want to see a more verbose output use the following:\n\n    % make V=1\n\nRunning Redis\n-------------\n\nTo run Redis with the default configuration just type:\n\n    % cd src\n    % ./redis-server\n    \nIf you want to provide your redis.conf, you have to run it using an additional\nparameter (the path of the configuration file):\n\n    % cd src\n    % ./redis-server /path/to/redis.conf\n\nIt is possible to alter the Redis configuration passing parameters directly\nas options using the command line. Examples:\n\n    % ./redis-server --port 9999 --slaveof 127.0.0.1 6379\n    % ./redis-server /etc/redis/6379.conf --loglevel debug\n\nAll the options in redis.conf are also supported as options using the command\nline, with exactly the same name.\n\nPlaying with Redis\n------------------\n\nYou can use redis-cli to play with Redis. Start a redis-server instance,\nthen in another terminal try the following:\n\n    % cd src\n    % ./redis-cli\n    redis> ping\n    PONG\n    redis> set foo bar\n    OK\n    redis> get foo\n    \"bar\"\n    redis> incr mycounter\n    (integer) 1\n    redis> incr mycounter\n    (integer) 2\n    redis>\n\nYou can find the list of all the available commands at http://redis.io/commands.\n\nInstalling Redis\n-----------------\n\nIn order to install Redis binaries into /usr/local/bin just use:\n\n    % make install\n\nYou can use `make PREFIX=/some/other/directory install` if you wish to use a\ndifferent destination.\n\nMake install will just install binaries in your system, but will not configure\ninit scripts and configuration files in the appropriate place. This is not\nneeded if you want just to play a bit with Redis, but if you are installing\nit the proper way for a production system, we have a script doing this\nfor Ubuntu and Debian systems:\n\n    % cd utils\n    % ./install_server.sh\n\nThe script will ask you a few questions and will setup everything you need\nto run Redis properly as a background daemon that will start again on\nsystem reboots.\n\nYou'll be able to stop and start Redis using the script named\n`/etc/init.d/redis_<portnumber>`, for instance `/etc/init.d/redis_6379`.\n\nCode contributions\n---\n\nNote: by contributing code to the Redis project in any form, including sending\na pull request via Github, a code fragment or patch via private email or\npublic discussion groups, you agree to release your code under the terms\nof the BSD license that you can find in the [COPYING][1] file included in the Redis\nsource distribution.\n\nPlease see the [CONTRIBUTING][2] file in this source distribution for more\ninformation.\n\nEnjoy!\n\n[1]: https://github.com/antirez/redis/blob/unstable/COPYING\n[2]: https://github.com/antirez/redis/blob/unstable/CONTRIBUTING\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.8/deps/Makefile",
    "content": "# Redis dependency Makefile\n\nuname_S:= $(shell sh -c 'uname -s 2>/dev/null || echo not')\n\nCCCOLOR=\"\\033[34m\"\nLINKCOLOR=\"\\033[34;1m\"\nSRCCOLOR=\"\\033[33m\"\nBINCOLOR=\"\\033[37;1m\"\nMAKECOLOR=\"\\033[32;1m\"\nENDCOLOR=\"\\033[0m\"\n\ndefault:\n\t@echo \"Explicit target required\"\n\n.PHONY: default\n\n# Prerequisites target\n.make-prerequisites:\n\t@touch $@\n\n# Clean everything when CFLAGS is different\nifneq ($(shell sh -c '[ -f .make-cflags ] && cat .make-cflags || echo none'), $(CFLAGS))\n.make-cflags: distclean\n\t-(echo \"$(CFLAGS)\" > .make-cflags)\n.make-prerequisites: .make-cflags\nendif\n\n# Clean everything when LDFLAGS is different\nifneq ($(shell sh -c '[ -f .make-ldflags ] && cat .make-ldflags || echo none'), $(LDFLAGS))\n.make-ldflags: distclean\n\t-(echo \"$(LDFLAGS)\" > .make-ldflags)\n.make-prerequisites: .make-ldflags\nendif\n\ndistclean:\n\t-(cd hiredis && $(MAKE) clean) > /dev/null || true\n\t-(cd linenoise && $(MAKE) clean) > /dev/null || true\n\t-(cd lua && $(MAKE) clean) > /dev/null || true\n\t-(cd geohash-int && $(MAKE) clean) > /dev/null || true\n\t-(cd jemalloc && [ -f Makefile ] && $(MAKE) distclean) > /dev/null || true\n\t-(rm -f .make-*)\n\n.PHONY: distclean\n\nhiredis: .make-prerequisites\n\t@printf '%b %b\\n' $(MAKECOLOR)MAKE$(ENDCOLOR) $(BINCOLOR)$@$(ENDCOLOR)\n\tcd hiredis && $(MAKE) static\n\n.PHONY: hiredis\n\nlinenoise: .make-prerequisites\n\t@printf '%b %b\\n' $(MAKECOLOR)MAKE$(ENDCOLOR) $(BINCOLOR)$@$(ENDCOLOR)\n\tcd linenoise && $(MAKE)\n\n.PHONY: linenoise\n\nifeq ($(uname_S),SunOS)\n\t# Make isinf() available\n\tLUA_CFLAGS= -D__C99FEATURES__=1\nendif\n\nLUA_CFLAGS+= -O2 -Wall -DLUA_ANSI -DENABLE_CJSON_GLOBAL -DREDIS_STATIC='' $(CFLAGS)\nLUA_LDFLAGS+= $(LDFLAGS)\n# lua's Makefile defines AR=\"ar rcu\", which is unusual, and makes it more\n# challenging to cross-compile lua (and redis).  These defines make it easier\n# to fit redis into cross-compilation environments, which typically set AR.\nAR=ar\nARFLAGS=rcu\n\nlua: .make-prerequisites\n\t@printf '%b %b\\n' $(MAKECOLOR)MAKE$(ENDCOLOR) $(BINCOLOR)$@$(ENDCOLOR)\n\tcd lua/src && $(MAKE) all CFLAGS=\"$(LUA_CFLAGS)\" MYLDFLAGS=\"$(LUA_LDFLAGS)\" AR=\"$(AR) $(ARFLAGS)\"\n\n.PHONY: lua\n\nJEMALLOC_CFLAGS= -std=gnu99 -Wall -pipe -g3 -O3 -funroll-loops $(CFLAGS)\nJEMALLOC_LDFLAGS= $(LDFLAGS)\n\njemalloc: .make-prerequisites\n\t@printf '%b %b\\n' $(MAKECOLOR)MAKE$(ENDCOLOR) $(BINCOLOR)$@$(ENDCOLOR)\n\tcd jemalloc && ./configure --with-lg-quantum=3 --with-jemalloc-prefix=je_ --enable-cc-silence CFLAGS=\"$(JEMALLOC_CFLAGS)\" LDFLAGS=\"$(JEMALLOC_LDFLAGS)\"\n\tcd jemalloc && $(MAKE) CFLAGS=\"$(JEMALLOC_CFLAGS)\" LDFLAGS=\"$(JEMALLOC_LDFLAGS)\" lib/libjemalloc.a\n\n.PHONY: jemalloc\n\ngeohash-int: .make-prerequisites\n\t@printf '%b %b\\n' $(MAKECOLOR)MAKE$(ENDCOLOR) $(BINCOLOR)$@$(ENDCOLOR)\n\tcd geohash-int && $(MAKE)\n\n.PHONY: geohash-int\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.8/deps/README.md",
    "content": "This directory contains all Redis dependencies, except for the libc that\nshould be provided by the operating system.\n\n* **Jemalloc** is our memory allocator, used as replacement for libc malloc on Linux by default. It has good performances and excellent fragmentation behavior. This component is upgraded from time to time.\n* **geohash-int** is inside the dependencies directory but is actually part of the Redis project, since it is our private fork (heavily modified) of a library initially developed for Ardb, which is in turn a fork of Redis.\n* **hiredis** is the official C client library for Redis. It is used by redis-cli, redis-benchmark and Redis Sentinel. It is part of the Redis official ecosystem but is developed externally from the Redis repository, so we just upgrade it as needed.\n* **linenoise** is a readline replacement. It is developed by the same authors of Redis but is managed as a separated project and updated as needed.\n* **lua** is Lua 5.1 with minor changes for security and additional libraries.\n\nHow to upgrade the above dependencies\n===\n\nJemalloc\n---\n\nJemalloc is unmodified. We only change settings via the `configure` script of Jemalloc using the `--with-lg-quantum` option, setting it to the value of 3 instead of 4. This provides us with more size classes that better suit the Redis data structures, in order to gain memory efficiency.\n\nSo in order to upgrade jemalloc:\n\n1. Remove the jemalloc directory.\n2. Substitute it with the new jemalloc source tree.\n\nGeohash\n---\n\nThis is never upgraded since it's part of the Redis project. If there are changes to merge from Ardb there is the need to manually check differences, but at this point the source code is pretty different.\n\nHiredis\n---\n\nHiredis uses the SDS string library, that must be the same version used inside Redis itself. Hiredis is also very critical for Sentinel. Historically Redis often used forked versions of hiredis in a way or the other. In order to upgrade it is adviced to take a lot of care:\n\n1. Check with diff if hiredis API changed and what impact it could have in Redis.\n2. Make sure thet the SDS library inside Hiredis and inside Redis are compatible.\n3. After the upgrade, run the Redis Sentinel test.\n4. Check manually that redis-cli and redis-benchmark behave as expecteed, since we have no tests for CLI utilities currently.\n\nLinenoise\n---\n\nLinenoise is rarely upgraded as needed. The upgrade process is trivial since\nRedis uses a non modified version of linenoise, so to upgrade just do the\nfollowing:\n\n1. Remove the linenoise directory.\n2. Substitute it with the new linenoise source tree.\n\nLua\n---\n\nWe use Lua 5.1 and no upgrade is planned currently, since we don't want to break\nLua scripts for new Lua features: in the context of Redis Lua scripts the\ncapabilities of 5.1 are usually more than enough, the release is rock solid,\nand we definitely don't want to break old scripts.\n\nSo upgrading of Lua is up to the Redis project maintainers and should be a\nmanual procedure performed by taking a diff between the different versions.\n\nCurrently we have at least the following differences between official Lua 5.1\nand our version:\n\n1. Makefile is modified to allow a different compiler than GCC.\n2. We have the implementation source code, and directly link to the following external libraries: `lua_cjson.o`, `lua_struct.o`, `lua_cmsgpack.o` and `lua_bit.o`.\n3. There is a security fix in `ldo.c`, line 498: The check for `LUA_SIGNATURE[0]` is removed in order toa void direct bytecode exectuion.\n\n\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.8/deps/geohash-int/Makefile",
    "content": "STD=\nWARN= -Wall\nOPT= -O2\n\nR_CFLAGS= $(STD) $(WARN) $(OPT) $(DEBUG) $(CFLAGS)\nR_LDFLAGS= $(LDFLAGS)\nDEBUG= -g\n\nR_CC=$(CC) $(R_CFLAGS)\nR_LD=$(CC) $(R_LDFLAGS)\n\nall: geohash.o geohash_helper.o\n\n.PHONY: all\n\ngeohash.o: geohash.h geohash.c\ngeohash_helper.o: geohash.h geohash_helper.h geohash_helper.c\n\n.c.o:\n\t$(R_CC) -c $<\n\nclean:\n\trm -f *.o\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.8/deps/geohash-int/geohash.c",
    "content": "/*\n * Copyright (c) 2013-2014, yinqiwen <yinqiwen@gmail.com>\n * Copyright (c) 2014, Matt Stancliff <matt@genges.com>.\n * Copyright (c) 2015-2016, Salvatore Sanfilippo <antirez@gmail.com>.\n * All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions are met:\n *\n *  * Redistributions of source code must retain the above copyright notice,\n *    this list of conditions and the following disclaimer.\n *  * Redistributions in binary form must reproduce the above copyright\n *    notice, this list of conditions and the following disclaimer in the\n *    documentation and/or other materials provided with the distribution.\n *  * Neither the name of Redis nor the names of its contributors may be used\n *    to endorse or promote products derived from this software without\n *    specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\"\n * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\n * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS\n * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR\n * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF\n * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS\n * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN\n * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)\n * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF\n * THE POSSIBILITY OF SUCH DAMAGE.\n */\n#include \"geohash.h\"\n\n/**\n * Hashing works like this:\n * Divide the world into 4 buckets.  Label each one as such:\n *  -----------------\n *  |       |       |\n *  |       |       |\n *  | 0,1   | 1,1   |\n *  -----------------\n *  |       |       |\n *  |       |       |\n *  | 0,0   | 1,0   |\n *  -----------------\n */\n\n/* Interleave lower bits of x and y, so the bits of x\n * are in the even positions and bits from y in the odd;\n * x and y must initially be less than 2**32 (65536).\n * From:  https://graphics.stanford.edu/~seander/bithacks.html#InterleaveBMN\n */\nstatic inline uint64_t interleave64(uint32_t xlo, uint32_t ylo) {\n    static const uint64_t B[] = {0x5555555555555555ULL, 0x3333333333333333ULL,\n                                 0x0F0F0F0F0F0F0F0FULL, 0x00FF00FF00FF00FFULL,\n                                 0x0000FFFF0000FFFFULL};\n    static const unsigned int S[] = {1, 2, 4, 8, 16};\n\n    uint64_t x = xlo;\n    uint64_t y = ylo;\n\n    x = (x | (x << S[4])) & B[4];\n    y = (y | (y << S[4])) & B[4];\n\n    x = (x | (x << S[3])) & B[3];\n    y = (y | (y << S[3])) & B[3];\n\n    x = (x | (x << S[2])) & B[2];\n    y = (y | (y << S[2])) & B[2];\n\n    x = (x | (x << S[1])) & B[1];\n    y = (y | (y << S[1])) & B[1];\n\n    x = (x | (x << S[0])) & B[0];\n    y = (y | (y << S[0])) & B[0];\n\n    return x | (y << 1);\n}\n\n/* reverse the interleave process\n * derived from http://stackoverflow.com/questions/4909263\n */\nstatic inline uint64_t deinterleave64(uint64_t interleaved) {\n    static const uint64_t B[] = {0x5555555555555555ULL, 0x3333333333333333ULL,\n                                 0x0F0F0F0F0F0F0F0FULL, 0x00FF00FF00FF00FFULL,\n                                 0x0000FFFF0000FFFFULL, 0x00000000FFFFFFFFULL};\n    static const unsigned int S[] = {0, 1, 2, 4, 8, 16};\n\n    uint64_t x = interleaved;\n    uint64_t y = interleaved >> 1;\n\n    x = (x | (x >> S[0])) & B[0];\n    y = (y | (y >> S[0])) & B[0];\n\n    x = (x | (x >> S[1])) & B[1];\n    y = (y | (y >> S[1])) & B[1];\n\n    x = (x | (x >> S[2])) & B[2];\n    y = (y | (y >> S[2])) & B[2];\n\n    x = (x | (x >> S[3])) & B[3];\n    y = (y | (y >> S[3])) & B[3];\n\n    x = (x | (x >> S[4])) & B[4];\n    y = (y | (y >> S[4])) & B[4];\n\n    x = (x | (x >> S[5])) & B[5];\n    y = (y | (y >> S[5])) & B[5];\n\n    return x | (y << 32);\n}\n\nvoid geohashGetCoordRange(GeoHashRange *long_range, GeoHashRange *lat_range) {\n    /* These are constraints from EPSG:900913 / EPSG:3785 / OSGEO:41001 */\n    /* We can't geocode at the north/south pole. */\n    long_range->max = GEO_LONG_MAX;\n    long_range->min = GEO_LONG_MIN;\n    lat_range->max = GEO_LAT_MAX;\n    lat_range->min = GEO_LAT_MIN;\n}\n\nint geohashEncode(const GeoHashRange *long_range, const GeoHashRange *lat_range,\n                  double longitude, double latitude, uint8_t step,\n                  GeoHashBits *hash) {\n    /* Check basic arguments sanity. */\n    if (hash == NULL || step > 32 || step == 0 ||\n        RANGEPISZERO(lat_range) || RANGEPISZERO(long_range)) return 0;\n\n    /* Return an error when trying to index outside the supported\n     * constraints. */\n    if (longitude > 180 || longitude < -180 ||\n        latitude > 85.05112878 || latitude < -85.05112878) return 0;\n\n    hash->bits = 0;\n    hash->step = step;\n\n    if (latitude < lat_range->min || latitude > lat_range->max ||\n        longitude < long_range->min || longitude > long_range->max) {\n        return 0;\n    }\n\n    double lat_offset =\n        (latitude - lat_range->min) / (lat_range->max - lat_range->min);\n    double long_offset =\n        (longitude - long_range->min) / (long_range->max - long_range->min);\n\n    /* convert to fixed point based on the step size */\n    lat_offset *= (1 << step);\n    long_offset *= (1 << step);\n    hash->bits = interleave64(lat_offset, long_offset);\n    return 1;\n}\n\nint geohashEncodeType(double longitude, double latitude, uint8_t step, GeoHashBits *hash) {\n    GeoHashRange r[2] = { { 0 } };\n    geohashGetCoordRange(&r[0], &r[1]);\n    return geohashEncode(&r[0], &r[1], longitude, latitude, step, hash);\n}\n\nint geohashEncodeWGS84(double longitude, double latitude, uint8_t step,\n                       GeoHashBits *hash) {\n    return geohashEncodeType(longitude, latitude, step, hash);\n}\n\nint geohashDecode(const GeoHashRange long_range, const GeoHashRange lat_range,\n                   const GeoHashBits hash, GeoHashArea *area) {\n    if (HASHISZERO(hash) || NULL == area || RANGEISZERO(lat_range) ||\n        RANGEISZERO(long_range)) {\n        return 0;\n    }\n\n    area->hash = hash;\n    uint8_t step = hash.step;\n    uint64_t hash_sep = deinterleave64(hash.bits); /* hash = [LAT][LONG] */\n\n    double lat_scale = lat_range.max - lat_range.min;\n    double long_scale = long_range.max - long_range.min;\n\n    uint32_t ilato = hash_sep;       /* get lat part of deinterleaved hash */\n    uint32_t ilono = hash_sep >> 32; /* shift over to get long part of hash */\n\n    /* divide by 2**step.\n     * Then, for 0-1 coordinate, multiply times scale and add\n       to the min to get the absolute coordinate. */\n    area->latitude.min =\n        lat_range.min + (ilato * 1.0 / (1ull << step)) * lat_scale;\n    area->latitude.max =\n        lat_range.min + ((ilato + 1) * 1.0 / (1ull << step)) * lat_scale;\n    area->longitude.min =\n        long_range.min + (ilono * 1.0 / (1ull << step)) * long_scale;\n    area->longitude.max =\n        long_range.min + ((ilono + 1) * 1.0 / (1ull << step)) * long_scale;\n\n    return 1;\n}\n\nint geohashDecodeType(const GeoHashBits hash, GeoHashArea *area) {\n    GeoHashRange r[2] = { { 0 } };\n    geohashGetCoordRange(&r[0], &r[1]);\n    return geohashDecode(r[0], r[1], hash, area);\n}\n\nint geohashDecodeWGS84(const GeoHashBits hash, GeoHashArea *area) {\n    return geohashDecodeType(hash, area);\n}\n\nint geohashDecodeAreaToLongLat(const GeoHashArea *area, double *xy) {\n    if (!xy) return 0;\n    xy[0] = (area->longitude.min + area->longitude.max) / 2;\n    xy[1] = (area->latitude.min + area->latitude.max) / 2;\n    return 1;\n}\n\nint geohashDecodeToLongLatType(const GeoHashBits hash, double *xy) {\n    GeoHashArea area = { { 0 } };\n    if (!xy || !geohashDecodeType(hash, &area))\n        return 0;\n    return geohashDecodeAreaToLongLat(&area, xy);\n}\n\nint geohashDecodeToLongLatWGS84(const GeoHashBits hash, double *xy) {\n    return geohashDecodeToLongLatType(hash, xy);\n}\n\nstatic void geohash_move_x(GeoHashBits *hash, int8_t d) {\n    if (d == 0)\n        return;\n\n    uint64_t x = hash->bits & 0xaaaaaaaaaaaaaaaaULL;\n    uint64_t y = hash->bits & 0x5555555555555555ULL;\n\n    uint64_t zz = 0x5555555555555555ULL >> (64 - hash->step * 2);\n\n    if (d > 0) {\n        x = x + (zz + 1);\n    } else {\n        x = x | zz;\n        x = x - (zz + 1);\n    }\n\n    x &= (0xaaaaaaaaaaaaaaaaULL >> (64 - hash->step * 2));\n    hash->bits = (x | y);\n}\n\nstatic void geohash_move_y(GeoHashBits *hash, int8_t d) {\n    if (d == 0)\n        return;\n\n    uint64_t x = hash->bits & 0xaaaaaaaaaaaaaaaaULL;\n    uint64_t y = hash->bits & 0x5555555555555555ULL;\n\n    uint64_t zz = 0xaaaaaaaaaaaaaaaaULL >> (64 - hash->step * 2);\n    if (d > 0) {\n        y = y + (zz + 1);\n    } else {\n        y = y | zz;\n        y = y - (zz + 1);\n    }\n    y &= (0x5555555555555555ULL >> (64 - hash->step * 2));\n    hash->bits = (x | y);\n}\n\nvoid geohashNeighbors(const GeoHashBits *hash, GeoHashNeighbors *neighbors) {\n    neighbors->east = *hash;\n    neighbors->west = *hash;\n    neighbors->north = *hash;\n    neighbors->south = *hash;\n    neighbors->south_east = *hash;\n    neighbors->south_west = *hash;\n    neighbors->north_east = *hash;\n    neighbors->north_west = *hash;\n\n    geohash_move_x(&neighbors->east, 1);\n    geohash_move_y(&neighbors->east, 0);\n\n    geohash_move_x(&neighbors->west, -1);\n    geohash_move_y(&neighbors->west, 0);\n\n    geohash_move_x(&neighbors->south, 0);\n    geohash_move_y(&neighbors->south, -1);\n\n    geohash_move_x(&neighbors->north, 0);\n    geohash_move_y(&neighbors->north, 1);\n\n    geohash_move_x(&neighbors->north_west, -1);\n    geohash_move_y(&neighbors->north_west, 1);\n\n    geohash_move_x(&neighbors->north_east, 1);\n    geohash_move_y(&neighbors->north_east, 1);\n\n    geohash_move_x(&neighbors->south_east, 1);\n    geohash_move_y(&neighbors->south_east, -1);\n\n    geohash_move_x(&neighbors->south_west, -1);\n    geohash_move_y(&neighbors->south_west, -1);\n}\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.8/deps/geohash-int/geohash.h",
    "content": "/*\n * Copyright (c) 2013-2014, yinqiwen <yinqiwen@gmail.com>\n * Copyright (c) 2014, Matt Stancliff <matt@genges.com>.\n * Copyright (c) 2015, Salvatore Sanfilippo <antirez@gmail.com>.\n * All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions are met:\n *\n *  * Redistributions of source code must retain the above copyright notice,\n *    this list of conditions and the following disclaimer.\n *  * Redistributions in binary form must reproduce the above copyright\n *    notice, this list of conditions and the following disclaimer in the\n *    documentation and/or other materials provided with the distribution.\n *  * Neither the name of Redis nor the names of its contributors may be used\n *    to endorse or promote products derived from this software without\n *    specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\"\n * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\n * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS\n * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR\n * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF\n * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS\n * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN\n * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)\n * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF\n * THE POSSIBILITY OF SUCH DAMAGE.\n */\n\n#ifndef GEOHASH_H_\n#define GEOHASH_H_\n\n#include <stddef.h>\n#include <stdint.h>\n#include <stdint.h>\n\n#if defined(__cplusplus)\nextern \"C\" {\n#endif\n\n#define HASHISZERO(r) (!(r).bits && !(r).step)\n#define RANGEISZERO(r) (!(r).max && !(r).min)\n#define RANGEPISZERO(r) (r == NULL || RANGEISZERO(*r))\n\n#define GEO_STEP_MAX 26 /* 26*2 = 52 bits. */\n\n/* Limits from EPSG:900913 / EPSG:3785 / OSGEO:41001 */\n#define GEO_LAT_MIN -85.05112878\n#define GEO_LAT_MAX 85.05112878\n#define GEO_LONG_MIN -180\n#define GEO_LONG_MAX 180\n\ntypedef enum {\n    GEOHASH_NORTH = 0,\n    GEOHASH_EAST,\n    GEOHASH_WEST,\n    GEOHASH_SOUTH,\n    GEOHASH_SOUTH_WEST,\n    GEOHASH_SOUTH_EAST,\n    GEOHASH_NORT_WEST,\n    GEOHASH_NORT_EAST\n} GeoDirection;\n\ntypedef struct {\n    uint64_t bits;\n    uint8_t step;\n} GeoHashBits;\n\ntypedef struct {\n    double min;\n    double max;\n} GeoHashRange;\n\ntypedef struct {\n    GeoHashBits hash;\n    GeoHashRange longitude;\n    GeoHashRange latitude;\n} GeoHashArea;\n\ntypedef struct {\n    GeoHashBits north;\n    GeoHashBits east;\n    GeoHashBits west;\n    GeoHashBits south;\n    GeoHashBits north_east;\n    GeoHashBits south_east;\n    GeoHashBits north_west;\n    GeoHashBits south_west;\n} GeoHashNeighbors;\n\n/*\n * 0:success\n * -1:failed\n */\nvoid geohashGetCoordRange(GeoHashRange *long_range, GeoHashRange *lat_range);\nint geohashEncode(const GeoHashRange *long_range, const GeoHashRange *lat_range,\n                  double longitude, double latitude, uint8_t step,\n                  GeoHashBits *hash);\nint geohashEncodeType(double longitude, double latitude,\n                      uint8_t step, GeoHashBits *hash);\nint geohashEncodeWGS84(double longitude, double latitude, uint8_t step,\n                       GeoHashBits *hash);\nint geohashDecode(const GeoHashRange long_range, const GeoHashRange lat_range,\n                  const GeoHashBits hash, GeoHashArea *area);\nint geohashDecodeType(const GeoHashBits hash, GeoHashArea *area);\nint geohashDecodeWGS84(const GeoHashBits hash, GeoHashArea *area);\nint geohashDecodeAreaToLongLat(const GeoHashArea *area, double *xy);\nint geohashDecodeToLongLatType(const GeoHashBits hash, double *xy);\nint geohashDecodeToLongLatWGS84(const GeoHashBits hash, double *xy);\nint geohashDecodeToLongLatMercator(const GeoHashBits hash, double *xy);\nvoid geohashNeighbors(const GeoHashBits *hash, GeoHashNeighbors *neighbors);\n\n#if defined(__cplusplus)\n}\n#endif\n#endif /* GEOHASH_H_ */\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.8/deps/geohash-int/geohash_helper.c",
    "content": "/*\n * Copyright (c) 2013-2014, yinqiwen <yinqiwen@gmail.com>\n * Copyright (c) 2014, Matt Stancliff <matt@genges.com>.\n * Copyright (c) 2015-2016, Salvatore Sanfilippo <antirez@gmail.com>.\n * All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions are met:\n *\n *  * Redistributions of source code must retain the above copyright notice,\n *    this list of conditions and the following disclaimer.\n *  * Redistributions in binary form must reproduce the above copyright\n *    notice, this list of conditions and the following disclaimer in the\n *    documentation and/or other materials provided with the distribution.\n *  * Neither the name of Redis nor the names of its contributors may be used\n *    to endorse or promote products derived from this software without\n *    specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\"\n * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\n * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS\n * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR\n * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF\n * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS\n * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN\n * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)\n * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF\n * THE POSSIBILITY OF SUCH DAMAGE.\n */\n\n/* This is a C++ to C conversion from the ardb project.\n * This file started out as:\n * https://github.com/yinqiwen/ardb/blob/d42503/src/geo/geohash_helper.cpp\n */\n\n#include \"geohash_helper.h\"\n#include <math.h>\n\n#define D_R (M_PI / 180.0)\n#define R_MAJOR 6378137.0\n#define R_MINOR 6356752.3142\n#define RATIO (R_MINOR / R_MAJOR)\n#define ECCENT (sqrt(1.0 - (RATIO *RATIO)))\n#define COM (0.5 * ECCENT)\n\n/// @brief The usual PI/180 constant\nconst double DEG_TO_RAD = 0.017453292519943295769236907684886;\n/// @brief Earth's quatratic mean radius for WGS-84\nconst double EARTH_RADIUS_IN_METERS = 6372797.560856;\n\nconst double MERCATOR_MAX = 20037726.37;\nconst double MERCATOR_MIN = -20037726.37;\n\nstatic inline double deg_rad(double ang) { return ang * D_R; }\nstatic inline double rad_deg(double ang) { return ang / D_R; }\n\n/* This function is used in order to estimate the step (bits precision)\n * of the 9 search area boxes during radius queries. */\nuint8_t geohashEstimateStepsByRadius(double range_meters, double lat) {\n    if (range_meters == 0) return 26;\n    int step = 1;\n    while (range_meters < MERCATOR_MAX) {\n        range_meters *= 2;\n        step++;\n    }\n    step -= 2; /* Make sure range is included in most of the base cases. */\n\n    /* Wider range torwards the poles... Note: it is possible to do better\n     * than this approximation by computing the distance between meridians\n     * at this latitude, but this does the trick for now. */\n    if (lat > 66 || lat < -66) {\n        step--;\n        if (lat > 80 || lat < -80) step--;\n    }\n\n    /* Frame to valid range. */\n    if (step < 1) step = 1;\n    if (step > 26) step = 26;\n    return step;\n}\n\n/* Return the bounding box of the search area centered at latitude,longitude\n * having a radius of radius_meter. bounds[0] - bounds[2] is the minimum\n * and maxium longitude, while bounds[1] - bounds[3] is the minimum and\n * maximum latitude. */\nint geohashBoundingBox(double longitude, double latitude, double radius_meters,\n                       double *bounds) {\n    if (!bounds) return 0;\n\n    bounds[0] = longitude - rad_deg(radius_meters/EARTH_RADIUS_IN_METERS/cos(deg_rad(latitude)));\n    bounds[2] = longitude + rad_deg(radius_meters/EARTH_RADIUS_IN_METERS/cos(deg_rad(latitude)));\n    bounds[1] = latitude - rad_deg(radius_meters/EARTH_RADIUS_IN_METERS);\n    bounds[3] = latitude + rad_deg(radius_meters/EARTH_RADIUS_IN_METERS);\n    return 1;\n}\n\n/* Return a set of areas (center + 8) that are able to cover a range query\n * for the specified position and radius. */\nGeoHashRadius geohashGetAreasByRadius(double longitude, double latitude, double radius_meters) {\n    GeoHashRange long_range, lat_range;\n    GeoHashRadius radius;\n    GeoHashBits hash;\n    GeoHashNeighbors neighbors;\n    GeoHashArea area;\n    double min_lon, max_lon, min_lat, max_lat;\n    double bounds[4];\n    int steps;\n\n    geohashBoundingBox(longitude, latitude, radius_meters, bounds);\n    min_lon = bounds[0];\n    min_lat = bounds[1];\n    max_lon = bounds[2];\n    max_lat = bounds[3];\n\n    steps = geohashEstimateStepsByRadius(radius_meters,latitude);\n\n    geohashGetCoordRange(&long_range,&lat_range);\n    geohashEncode(&long_range,&lat_range,longitude,latitude,steps,&hash);\n    geohashNeighbors(&hash,&neighbors);\n    geohashDecode(long_range,lat_range,hash,&area);\n\n    /* Check if the step is enough at the limits of the covered area.\n     * Sometimes when the search area is near an edge of the\n     * area, the estimated step is not small enough, since one of the\n     * north / south / west / east square is too near to the search area\n     * to cover everything. */\n    int decrease_step = 0;\n    {\n        GeoHashArea north, south, east, west;\n\n        geohashDecode(long_range, lat_range, neighbors.north, &north);\n        geohashDecode(long_range, lat_range, neighbors.south, &south);\n        geohashDecode(long_range, lat_range, neighbors.east, &east);\n        geohashDecode(long_range, lat_range, neighbors.west, &west);\n\n        if (geohashGetDistance(longitude,latitude,longitude,north.latitude.max)\n            < radius_meters) decrease_step = 1;\n        if (geohashGetDistance(longitude,latitude,longitude,south.latitude.min)\n            < radius_meters) decrease_step = 1;\n        if (geohashGetDistance(longitude,latitude,east.longitude.max,latitude)\n            < radius_meters) decrease_step = 1;\n        if (geohashGetDistance(longitude,latitude,west.longitude.min,latitude)\n            < radius_meters) decrease_step = 1;\n    }\n\n    if (steps > 1 && decrease_step) {\n        steps--;\n        geohashEncode(&long_range,&lat_range,longitude,latitude,steps,&hash);\n        geohashNeighbors(&hash,&neighbors);\n        geohashDecode(long_range,lat_range,hash,&area);\n    }\n\n    /* Exclude the search areas that are useless. */\n    if (area.latitude.min < min_lat) {\n        GZERO(neighbors.south);\n        GZERO(neighbors.south_west);\n        GZERO(neighbors.south_east);\n    }\n    if (area.latitude.max > max_lat) {\n        GZERO(neighbors.north);\n        GZERO(neighbors.north_east);\n        GZERO(neighbors.north_west);\n    }\n    if (area.longitude.min < min_lon) {\n        GZERO(neighbors.west);\n        GZERO(neighbors.south_west);\n        GZERO(neighbors.north_west);\n    }\n    if (area.longitude.max > max_lon) {\n        GZERO(neighbors.east);\n        GZERO(neighbors.south_east);\n        GZERO(neighbors.north_east);\n    }\n    radius.hash = hash;\n    radius.neighbors = neighbors;\n    radius.area = area;\n    return radius;\n}\n\nGeoHashRadius geohashGetAreasByRadiusWGS84(double longitude, double latitude,\n                                           double radius_meters) {\n    return geohashGetAreasByRadius(longitude, latitude, radius_meters);\n}\n\nGeoHashFix52Bits geohashAlign52Bits(const GeoHashBits hash) {\n    uint64_t bits = hash.bits;\n    bits <<= (52 - hash.step * 2);\n    return bits;\n}\n\n/* Calculate distance using haversin great circle distance formula. */\ndouble geohashGetDistance(double lon1d, double lat1d, double lon2d, double lat2d) {\n    double lat1r, lon1r, lat2r, lon2r, u, v;\n    lat1r = deg_rad(lat1d);\n    lon1r = deg_rad(lon1d);\n    lat2r = deg_rad(lat2d);\n    lon2r = deg_rad(lon2d);\n    u = sin((lat2r - lat1r) / 2);\n    v = sin((lon2r - lon1r) / 2);\n    return 2.0 * EARTH_RADIUS_IN_METERS *\n           asin(sqrt(u * u + cos(lat1r) * cos(lat2r) * v * v));\n}\n\nint geohashGetDistanceIfInRadius(double x1, double y1,\n                                 double x2, double y2, double radius,\n                                 double *distance) {\n    *distance = geohashGetDistance(x1, y1, x2, y2);\n    if (*distance > radius) return 0;\n    return 1;\n}\n\nint geohashGetDistanceIfInRadiusWGS84(double x1, double y1, double x2,\n                                      double y2, double radius,\n                                      double *distance) {\n    return geohashGetDistanceIfInRadius(x1, y1, x2, y2, radius, distance);\n}\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.8/deps/geohash-int/geohash_helper.h",
    "content": "/*\n * Copyright (c) 2013-2014, yinqiwen <yinqiwen@gmail.com>\n * Copyright (c) 2014, Matt Stancliff <matt@genges.com>.\n * Copyright (c) 2015, Salvatore Sanfilippo <antirez@gmail.com>.\n * All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions are met:\n *\n *  * Redistributions of source code must retain the above copyright notice,\n *    this list of conditions and the following disclaimer.\n *  * Redistributions in binary form must reproduce the above copyright\n *    notice, this list of conditions and the following disclaimer in the\n *    documentation and/or other materials provided with the distribution.\n *  * Neither the name of Redis nor the names of its contributors may be used\n *    to endorse or promote products derived from this software without\n *    specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\"\n * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\n * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS\n * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR\n * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF\n * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS\n * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN\n * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)\n * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF\n * THE POSSIBILITY OF SUCH DAMAGE.\n */\n\n#ifndef GEOHASH_HELPER_HPP_\n#define GEOHASH_HELPER_HPP_\n\n#include <math.h>\n#include \"geohash.h\"\n\n#define GZERO(s) s.bits = s.step = 0;\n#define GISZERO(s) (!s.bits && !s.step)\n#define GISNOTZERO(s) (s.bits || s.step)\n\ntypedef uint64_t GeoHashFix52Bits;\ntypedef uint64_t GeoHashVarBits;\n\ntypedef struct {\n    GeoHashBits hash;\n    GeoHashArea area;\n    GeoHashNeighbors neighbors;\n} GeoHashRadius;\n\nint GeoHashBitsComparator(const GeoHashBits *a, const GeoHashBits *b);\nuint8_t geohashEstimateStepsByRadius(double range_meters, double lat);\nint geohashBoundingBox(double longitude, double latitude, double radius_meters,\n                        double *bounds);\nGeoHashRadius geohashGetAreasByRadius(double longitude,\n                                      double latitude, double radius_meters);\nGeoHashRadius geohashGetAreasByRadiusWGS84(double longitude, double latitude,\n                                           double radius_meters);\nGeoHashRadius geohashGetAreasByRadiusMercator(double longitude, double latitude,\n                                              double radius_meters);\nGeoHashFix52Bits geohashAlign52Bits(const GeoHashBits hash);\ndouble geohashGetDistance(double lon1d, double lat1d,\n                          double lon2d, double lat2d);\nint geohashGetDistanceIfInRadius(double x1, double y1,\n                                 double x2, double y2, double radius,\n                                 double *distance);\nint geohashGetDistanceIfInRadiusWGS84(double x1, double y1, double x2,\n                                      double y2, double radius,\n                                      double *distance);\n\n#endif /* GEOHASH_HELPER_HPP_ */\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.8/deps/hiredis/.gitignore",
    "content": "/hiredis-test\n/examples/hiredis-example*\n/*.o\n/*.so\n/*.dylib\n/*.a\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.8/deps/hiredis/.travis.yml",
    "content": "language: c\ncompiler:\n  - gcc\n  - clang\n\nscript: make && make check\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.8/deps/hiredis/CHANGELOG.md",
    "content": "### 0.11.0\n\n* Increase the maximum multi-bulk reply depth to 7.\n\n* Increase the read buffer size from 2k to 16k.\n\n* Use poll(2) instead of select(2) to support large fds (>= 1024).\n\n### 0.10.1\n\n* Makefile overhaul. Important to check out if you override one or more\n  variables using environment variables or via arguments to the \"make\" tool.\n\n* Issue #45: Fix potential memory leak for a multi bulk reply with 0 elements\n  being created by the default reply object functions.\n\n* Issue #43: Don't crash in an asynchronous context when Redis returns an error\n  reply after the connection has been made (this happens when the maximum\n  number of connections is reached).\n\n### 0.10.0\n\n* See commit log.\n\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.8/deps/hiredis/COPYING",
    "content": "Copyright (c) 2009-2011, Salvatore Sanfilippo <antirez at gmail dot com>\nCopyright (c) 2010-2011, Pieter Noordhuis <pcnoordhuis at gmail dot com>\n\nAll rights reserved.\n\nRedistribution and use in source and binary forms, with or without\nmodification, are permitted provided that the following conditions are met:\n\n* Redistributions of source code must retain the above copyright notice,\n  this list of conditions and the following disclaimer.\n\n* Redistributions in binary form must reproduce the above copyright notice,\n  this list of conditions and the following disclaimer in the documentation\n  and/or other materials provided with the distribution.\n\n* Neither the name of Redis nor the names of its contributors may be used\n  to endorse or promote products derived from this software without specific\n  prior written permission.\n\nTHIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND\nANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\nWARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\nDISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR\nANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\nLOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON\nANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\nSOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.8/deps/hiredis/Makefile",
    "content": "# Hiredis Makefile\n# Copyright (C) 2010-2011 Salvatore Sanfilippo <antirez at gmail dot com>\n# Copyright (C) 2010-2011 Pieter Noordhuis <pcnoordhuis at gmail dot com>\n# This file is released under the BSD license, see the COPYING file\n\nOBJ=net.o hiredis.o sds.o async.o\nEXAMPLES=hiredis-example hiredis-example-libevent hiredis-example-libev\nTESTS=hiredis-test\nLIBNAME=libhiredis\n\nHIREDIS_MAJOR=0\nHIREDIS_MINOR=11\n\n# redis-server configuration used for testing\nREDIS_PORT=56379\nREDIS_SERVER=redis-server\ndefine REDIS_TEST_CONFIG\n\tdaemonize yes\n\tpidfile /tmp/hiredis-test-redis.pid\n\tport $(REDIS_PORT)\n\tbind 127.0.0.1\n\tunixsocket /tmp/hiredis-test-redis.sock\nendef\nexport REDIS_TEST_CONFIG\n\n# Fallback to gcc when $CC is not in $PATH.\nCC:=$(shell sh -c 'type $(CC) >/dev/null 2>/dev/null && echo $(CC) || echo gcc')\nOPTIMIZATION?=-O3\nWARNINGS=-Wall -W -Wstrict-prototypes -Wwrite-strings\nDEBUG?= -g -ggdb\nREAL_CFLAGS=$(OPTIMIZATION) -fPIC $(CFLAGS) $(WARNINGS) $(DEBUG) $(ARCH)\nREAL_LDFLAGS=$(LDFLAGS) $(ARCH)\n\nDYLIBSUFFIX=so\nSTLIBSUFFIX=a\nDYLIB_MINOR_NAME=$(LIBNAME).$(DYLIBSUFFIX).$(HIREDIS_MAJOR).$(HIREDIS_MINOR)\nDYLIB_MAJOR_NAME=$(LIBNAME).$(DYLIBSUFFIX).$(HIREDIS_MAJOR)\nDYLIBNAME=$(LIBNAME).$(DYLIBSUFFIX)\nDYLIB_MAKE_CMD=$(CC) -shared -Wl,-soname,$(DYLIB_MINOR_NAME) -o $(DYLIBNAME) $(LDFLAGS)\nSTLIBNAME=$(LIBNAME).$(STLIBSUFFIX)\nSTLIB_MAKE_CMD=ar rcs $(STLIBNAME)\n\n# Platform-specific overrides\nuname_S := $(shell sh -c 'uname -s 2>/dev/null || echo not')\nifeq ($(uname_S),SunOS)\n  REAL_LDFLAGS+= -ldl -lnsl -lsocket\n  DYLIB_MAKE_CMD=$(CC) -G -o $(DYLIBNAME) -h $(DYLIB_MINOR_NAME) $(LDFLAGS)\n  INSTALL= cp -r\nendif\nifeq ($(uname_S),Darwin)\n  DYLIBSUFFIX=dylib\n  DYLIB_MINOR_NAME=$(LIBNAME).$(HIREDIS_MAJOR).$(HIREDIS_MINOR).$(DYLIBSUFFIX)\n  DYLIB_MAJOR_NAME=$(LIBNAME).$(HIREDIS_MAJOR).$(DYLIBSUFFIX)\n  DYLIB_MAKE_CMD=$(CC) -shared -Wl,-install_name,$(DYLIB_MINOR_NAME) -o $(DYLIBNAME) $(LDFLAGS)\nendif\n\nall: $(DYLIBNAME)\n\n# Deps (use make dep to generate this)\nnet.o: net.c fmacros.h net.h hiredis.h\nasync.o: async.c async.h hiredis.h sds.h dict.c dict.h\nhiredis.o: hiredis.c fmacros.h hiredis.h net.h sds.h\nsds.o: sds.c sds.h\ntest.o: test.c hiredis.h\n\n$(DYLIBNAME): $(OBJ)\n\t$(DYLIB_MAKE_CMD) $(OBJ)\n\n$(STLIBNAME): $(OBJ)\n\t$(STLIB_MAKE_CMD) $(OBJ)\n\ndynamic: $(DYLIBNAME)\nstatic: $(STLIBNAME)\n\n# Binaries:\nhiredis-example-libevent: examples/example-libevent.c adapters/libevent.h $(STLIBNAME)\n\t$(CC) -o examples/$@ $(REAL_CFLAGS) $(REAL_LDFLAGS) -I. $< -levent $(STLIBNAME)\n\nhiredis-example-libev: examples/example-libev.c adapters/libev.h $(STLIBNAME)\n\t$(CC) -o examples/$@ $(REAL_CFLAGS) $(REAL_LDFLAGS) -I. $< -lev $(STLIBNAME)\n\nifndef AE_DIR\nhiredis-example-ae:\n\t@echo \"Please specify AE_DIR (e.g. <redis repository>/src)\"\n\t@false\nelse\nhiredis-example-ae: examples/example-ae.c adapters/ae.h $(STLIBNAME)\n\t$(CC) -o examples/$@ $(REAL_CFLAGS) $(REAL_LDFLAGS) -I. -I$(AE_DIR) $< $(AE_DIR)/ae.o $(AE_DIR)/zmalloc.o $(AE_DIR)/../deps/jemalloc/lib/libjemalloc.a -pthread $(STLIBNAME)\nendif\n\nifndef LIBUV_DIR\nhiredis-example-libuv:\n\t@echo \"Please specify LIBUV_DIR (e.g. ../libuv/)\"\n\t@false\nelse\nhiredis-example-libuv: examples/example-libuv.c adapters/libuv.h $(STLIBNAME)\n\t$(CC) -o examples/$@ $(REAL_CFLAGS) $(REAL_LDFLAGS) -I. -I$(LIBUV_DIR)/include $< $(LIBUV_DIR)/.libs/libuv.a -lpthread $(STLIBNAME)\nendif\n\nhiredis-example: examples/example.c $(STLIBNAME)\n\t$(CC) -o examples/$@ $(REAL_CFLAGS) $(REAL_LDFLAGS) -I. $< $(STLIBNAME)\n\nexamples: $(EXAMPLES)\n\nhiredis-test: test.o $(STLIBNAME)\n\t$(CC) -o $@ $(REAL_LDFLAGS) $< $(STLIBNAME)\n\ntest: hiredis-test\n\t./hiredis-test\n\ncheck: hiredis-test\n\t@echo \"$$REDIS_TEST_CONFIG\" | $(REDIS_SERVER) -\n\t./hiredis-test -h 127.0.0.1 -p $(REDIS_PORT) -s /tmp/hiredis-test-redis.sock || \\\n\t\t\t( kill `cat /tmp/hiredis-test-redis.pid` && false )\n\tkill `cat /tmp/hiredis-test-redis.pid`\n\n.c.o:\n\t$(CC) -std=c99 -pedantic -c $(REAL_CFLAGS) $<\n\nclean:\n\trm -rf $(DYLIBNAME) $(STLIBNAME) $(TESTS) examples/hiredis-example* *.o *.gcda *.gcno *.gcov\n\ndep:\n\t$(CC) -MM *.c\n\n# Installation related variables and target\nPREFIX?=/usr/local\nINSTALL_INCLUDE_PATH= $(PREFIX)/include/hiredis\nINSTALL_LIBRARY_PATH= $(PREFIX)/lib\n\nifeq ($(uname_S),SunOS)\n  INSTALL?= cp -r\nendif\n\nINSTALL?= cp -a\n\ninstall: $(DYLIBNAME) $(STLIBNAME)\n\tmkdir -p $(INSTALL_INCLUDE_PATH) $(INSTALL_LIBRARY_PATH)\n\t$(INSTALL) hiredis.h async.h adapters $(INSTALL_INCLUDE_PATH)\n\t$(INSTALL) $(DYLIBNAME) $(INSTALL_LIBRARY_PATH)/$(DYLIB_MINOR_NAME)\n\tcd $(INSTALL_LIBRARY_PATH) && ln -sf $(DYLIB_MINOR_NAME) $(DYLIB_MAJOR_NAME)\n\tcd $(INSTALL_LIBRARY_PATH) && ln -sf $(DYLIB_MAJOR_NAME) $(DYLIBNAME)\n\t$(INSTALL) $(STLIBNAME) $(INSTALL_LIBRARY_PATH)\n\n32bit:\n\t@echo \"\"\n\t@echo \"WARNING: if this fails under Linux you probably need to install libc6-dev-i386\"\n\t@echo \"\"\n\t$(MAKE) CFLAGS=\"-m32\" LDFLAGS=\"-m32\"\n\ngprof:\n\t$(MAKE) CFLAGS=\"-pg\" LDFLAGS=\"-pg\"\n\ngcov:\n\t$(MAKE) CFLAGS=\"-fprofile-arcs -ftest-coverage\" LDFLAGS=\"-fprofile-arcs\"\n\ncoverage: gcov\n\tmake check\n\tmkdir -p tmp/lcov\n\tlcov -d . -c -o tmp/lcov/hiredis.info\n\tgenhtml --legend -o tmp/lcov/report tmp/lcov/hiredis.info\n\nnoopt:\n\t$(MAKE) OPTIMIZATION=\"\"\n\n.PHONY: all test check clean dep install 32bit gprof gcov noopt\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.8/deps/hiredis/README.md",
    "content": "[![Build Status](https://travis-ci.org/redis/hiredis.png)](https://travis-ci.org/redis/hiredis)\n\n# HIREDIS\n\nHiredis is a minimalistic C client library for the [Redis](http://redis.io/) database.\n\nIt is minimalistic because it just adds minimal support for the protocol, but\nat the same time it uses an high level printf-alike API in order to make it\nmuch higher level than otherwise suggested by its minimal code base and the\nlack of explicit bindings for every Redis command.\n\nApart from supporting sending commands and receiving replies, it comes with\na reply parser that is decoupled from the I/O layer. It\nis a stream parser designed for easy reusability, which can for instance be used\nin higher level language bindings for efficient reply parsing.\n\nHiredis only supports the binary-safe Redis protocol, so you can use it with any\nRedis version >= 1.2.0.\n\nThe library comes with multiple APIs. There is the\n*synchronous API*, the *asynchronous API* and the *reply parsing API*.\n\n## UPGRADING\n\nVersion 0.9.0 is a major overhaul of hiredis in every aspect. However, upgrading existing\ncode using hiredis should not be a big pain. The key thing to keep in mind when\nupgrading is that hiredis >= 0.9.0 uses a `redisContext*` to keep state, in contrast to\nthe stateless 0.0.1 that only has a file descriptor to work with.\n\n## Synchronous API\n\nTo consume the synchronous API, there are only a few function calls that need to be introduced:\n\n    redisContext *redisConnect(const char *ip, int port);\n    void *redisCommand(redisContext *c, const char *format, ...);\n    void freeReplyObject(void *reply);\n\n### Connecting\n\nThe function `redisConnect` is used to create a so-called `redisContext`. The\ncontext is where Hiredis holds state for a connection. The `redisContext`\nstruct has an integer `err` field that is non-zero when an the connection is in\nan error state. The field `errstr` will contain a string with a description of\nthe error. More information on errors can be found in the **Errors** section.\nAfter trying to connect to Redis using `redisConnect` you should\ncheck the `err` field to see if establishing the connection was successful:\n\n    redisContext *c = redisConnect(\"127.0.0.1\", 6379);\n    if (c != NULL && c->err) {\n        printf(\"Error: %s\\n\", c->errstr);\n        // handle error\n    }\n\n### Sending commands\n\nThere are several ways to issue commands to Redis. The first that will be introduced is\n`redisCommand`. This function takes a format similar to printf. In the simplest form,\nit is used like this:\n\n    reply = redisCommand(context, \"SET foo bar\");\n\nThe specifier `%s` interpolates a string in the command, and uses `strlen` to\ndetermine the length of the string:\n\n    reply = redisCommand(context, \"SET foo %s\", value);\n\nWhen you need to pass binary safe strings in a command, the `%b` specifier can be\nused. Together with a pointer to the string, it requires a `size_t` length argument\nof the string:\n\n    reply = redisCommand(context, \"SET foo %b\", value, (size_t) valuelen);\n\nInternally, Hiredis splits the command in different arguments and will\nconvert it to the protocol used to communicate with Redis.\nOne or more spaces separates arguments, so you can use the specifiers\nanywhere in an argument:\n\n    reply = redisCommand(context, \"SET key:%s %s\", myid, value);\n\n### Using replies\n\nThe return value of `redisCommand` holds a reply when the command was\nsuccessfully executed. When an error occurs, the return value is `NULL` and\nthe `err` field in the context will be set (see section on **Errors**).\nOnce an error is returned the context cannot be reused and you should set up\na new connection.\n\nThe standard replies that `redisCommand` are of the type `redisReply`. The\n`type` field in the `redisReply` should be used to test what kind of reply\nwas received:\n\n* **`REDIS_REPLY_STATUS`**:\n    * The command replied with a status reply. The status string can be accessed using `reply->str`.\n      The length of this string can be accessed using `reply->len`.\n\n* **`REDIS_REPLY_ERROR`**:\n    *  The command replied with an error. The error string can be accessed identical to `REDIS_REPLY_STATUS`.\n\n* **`REDIS_REPLY_INTEGER`**:\n    * The command replied with an integer. The integer value can be accessed using the\n      `reply->integer` field of type `long long`.\n\n* **`REDIS_REPLY_NIL`**:\n    * The command replied with a **nil** object. There is no data to access.\n\n* **`REDIS_REPLY_STRING`**:\n    * A bulk (string) reply. The value of the reply can be accessed using `reply->str`.\n      The length of this string can be accessed using `reply->len`.\n\n* **`REDIS_REPLY_ARRAY`**:\n    * A multi bulk reply. The number of elements in the multi bulk reply is stored in\n      `reply->elements`. Every element in the multi bulk reply is a `redisReply` object as well\n      and can be accessed via `reply->element[..index..]`.\n      Redis may reply with nested arrays but this is fully supported.\n\nReplies should be freed using the `freeReplyObject()` function.\nNote that this function will take care of freeing sub-replies objects\ncontained in arrays and nested arrays, so there is no need for the user to\nfree the sub replies (it is actually harmful and will corrupt the memory).\n\n**Important:** the current version of hiredis (0.10.0) free's replies when the\nasynchronous API is used. This means you should not call `freeReplyObject` when\nyou use this API. The reply is cleaned up by hiredis _after_ the callback\nreturns. This behavior will probably change in future releases, so make sure to\nkeep an eye on the changelog when upgrading (see issue #39).\n\n### Cleaning up\n\nTo disconnect and free the context the following function can be used:\n\n    void redisFree(redisContext *c);\n\nThis function immediately closes the socket and then free's the allocations done in\ncreating the context.\n\n### Sending commands (cont'd)\n\nTogether with `redisCommand`, the function `redisCommandArgv` can be used to issue commands.\nIt has the following prototype:\n\n    void *redisCommandArgv(redisContext *c, int argc, const char **argv, const size_t *argvlen);\n\nIt takes the number of arguments `argc`, an array of strings `argv` and the lengths of the\narguments `argvlen`. For convenience, `argvlen` may be set to `NULL` and the function will\nuse `strlen(3)` on every argument to determine its length. Obviously, when any of the arguments\nneed to be binary safe, the entire array of lengths `argvlen` should be provided.\n\nThe return value has the same semantic as `redisCommand`.\n\n### Pipelining\n\nTo explain how Hiredis supports pipelining in a blocking connection, there needs to be\nunderstanding of the internal execution flow.\n\nWhen any of the functions in the `redisCommand` family is called, Hiredis first formats the\ncommand according to the Redis protocol. The formatted command is then put in the output buffer\nof the context. This output buffer is dynamic, so it can hold any number of commands.\nAfter the command is put in the output buffer, `redisGetReply` is called. This function has the\nfollowing two execution paths:\n\n1. The input buffer is non-empty:\n    * Try to parse a single reply from the input buffer and return it\n    * If no reply could be parsed, continue at *2*\n2. The input buffer is empty:\n    * Write the **entire** output buffer to the socket\n    * Read from the socket until a single reply could be parsed\n\nThe function `redisGetReply` is exported as part of the Hiredis API and can be used when a reply\nis expected on the socket. To pipeline commands, the only things that needs to be done is\nfilling up the output buffer. For this cause, two commands can be used that are identical\nto the `redisCommand` family, apart from not returning a reply:\n\n    void redisAppendCommand(redisContext *c, const char *format, ...);\n    void redisAppendCommandArgv(redisContext *c, int argc, const char **argv, const size_t *argvlen);\n\nAfter calling either function one or more times, `redisGetReply` can be used to receive the\nsubsequent replies. The return value for this function is either `REDIS_OK` or `REDIS_ERR`, where\nthe latter means an error occurred while reading a reply. Just as with the other commands,\nthe `err` field in the context can be used to find out what the cause of this error is.\n\nThe following examples shows a simple pipeline (resulting in only a single call to `write(2)` and\na single call to `read(2)`):\n\n    redisReply *reply;\n    redisAppendCommand(context,\"SET foo bar\");\n    redisAppendCommand(context,\"GET foo\");\n    redisGetReply(context,&reply); // reply for SET\n    freeReplyObject(reply);\n    redisGetReply(context,&reply); // reply for GET\n    freeReplyObject(reply);\n\nThis API can also be used to implement a blocking subscriber:\n\n    reply = redisCommand(context,\"SUBSCRIBE foo\");\n    freeReplyObject(reply);\n    while(redisGetReply(context,&reply) == REDIS_OK) {\n        // consume message\n        freeReplyObject(reply);\n    }\n\n### Errors\n\nWhen a function call is not successful, depending on the function either `NULL` or `REDIS_ERR` is\nreturned. The `err` field inside the context will be non-zero and set to one of the\nfollowing constants:\n\n* **`REDIS_ERR_IO`**:\n    There was an I/O error while creating the connection, trying to write\n    to the socket or read from the socket. If you included `errno.h` in your\n    application, you can use the global `errno` variable to find out what is\n    wrong.\n\n* **`REDIS_ERR_EOF`**:\n    The server closed the connection which resulted in an empty read.\n\n* **`REDIS_ERR_PROTOCOL`**:\n    There was an error while parsing the protocol.\n\n* **`REDIS_ERR_OTHER`**:\n    Any other error. Currently, it is only used when a specified hostname to connect\n    to cannot be resolved.\n\nIn every case, the `errstr` field in the context will be set to hold a string representation\nof the error.\n\n## Asynchronous API\n\nHiredis comes with an asynchronous API that works easily with any event library.\nExamples are bundled that show using Hiredis with [libev](http://software.schmorp.de/pkg/libev.html)\nand [libevent](http://monkey.org/~provos/libevent/).\n\n### Connecting\n\nThe function `redisAsyncConnect` can be used to establish a non-blocking connection to\nRedis. It returns a pointer to the newly created `redisAsyncContext` struct. The `err` field\nshould be checked after creation to see if there were errors creating the connection.\nBecause the connection that will be created is non-blocking, the kernel is not able to\ninstantly return if the specified host and port is able to accept a connection.\n\n    redisAsyncContext *c = redisAsyncConnect(\"127.0.0.1\", 6379);\n    if (c->err) {\n        printf(\"Error: %s\\n\", c->errstr);\n        // handle error\n    }\n\nThe asynchronous context can hold a disconnect callback function that is called when the\nconnection is disconnected (either because of an error or per user request). This function should\nhave the following prototype:\n\n    void(const redisAsyncContext *c, int status);\n\nOn a disconnect, the `status` argument is set to `REDIS_OK` when disconnection was initiated by the\nuser, or `REDIS_ERR` when the disconnection was caused by an error. When it is `REDIS_ERR`, the `err`\nfield in the context can be accessed to find out the cause of the error.\n\nThe context object is always free'd after the disconnect callback fired. When a reconnect is needed,\nthe disconnect callback is a good point to do so.\n\nSetting the disconnect callback can only be done once per context. For subsequent calls it will\nreturn `REDIS_ERR`. The function to set the disconnect callback has the following prototype:\n\n    int redisAsyncSetDisconnectCallback(redisAsyncContext *ac, redisDisconnectCallback *fn);\n\n### Sending commands and their callbacks\n\nIn an asynchronous context, commands are automatically pipelined due to the nature of an event loop.\nTherefore, unlike the synchronous API, there is only a single way to send commands.\nBecause commands are sent to Redis asynchronously, issuing a command requires a callback function\nthat is called when the reply is received. Reply callbacks should have the following prototype:\n\n    void(redisAsyncContext *c, void *reply, void *privdata);\n\nThe `privdata` argument can be used to curry arbitrary data to the callback from the point where\nthe command is initially queued for execution.\n\nThe functions that can be used to issue commands in an asynchronous context are:\n\n    int redisAsyncCommand(\n      redisAsyncContext *ac, redisCallbackFn *fn, void *privdata,\n      const char *format, ...);\n    int redisAsyncCommandArgv(\n      redisAsyncContext *ac, redisCallbackFn *fn, void *privdata,\n      int argc, const char **argv, const size_t *argvlen);\n\nBoth functions work like their blocking counterparts. The return value is `REDIS_OK` when the command\nwas successfully added to the output buffer and `REDIS_ERR` otherwise. Example: when the connection\nis being disconnected per user-request, no new commands may be added to the output buffer and `REDIS_ERR` is\nreturned on calls to the `redisAsyncCommand` family.\n\nIf the reply for a command with a `NULL` callback is read, it is immediately free'd. When the callback\nfor a command is non-`NULL`, the memory is free'd immediately following the callback: the reply is only\nvalid for the duration of the callback.\n\nAll pending callbacks are called with a `NULL` reply when the context encountered an error.\n\n### Disconnecting\n\nAn asynchronous connection can be terminated using:\n\n    void redisAsyncDisconnect(redisAsyncContext *ac);\n\nWhen this function is called, the connection is **not** immediately terminated. Instead, new\ncommands are no longer accepted and the connection is only terminated when all pending commands\nhave been written to the socket, their respective replies have been read and their respective\ncallbacks have been executed. After this, the disconnection callback is executed with the\n`REDIS_OK` status and the context object is free'd.\n\n### Hooking it up to event library *X*\n\nThere are a few hooks that need to be set on the context object after it is created.\nSee the `adapters/` directory for bindings to *libev* and *libevent*.\n\n## Reply parsing API\n\nHiredis comes with a reply parsing API that makes it easy for writing higher\nlevel language bindings.\n\nThe reply parsing API consists of the following functions:\n\n    redisReader *redisReaderCreate(void);\n    void redisReaderFree(redisReader *reader);\n    int redisReaderFeed(redisReader *reader, const char *buf, size_t len);\n    int redisReaderGetReply(redisReader *reader, void **reply);\n\nThe same set of functions are used internally by hiredis when creating a\nnormal Redis context, the above API just exposes it to the user for a direct\nusage.\n\n### Usage\n\nThe function `redisReaderCreate` creates a `redisReader` structure that holds a\nbuffer with unparsed data and state for the protocol parser.\n\nIncoming data -- most likely from a socket -- can be placed in the internal\nbuffer of the `redisReader` using `redisReaderFeed`. This function will make a\ncopy of the buffer pointed to by `buf` for `len` bytes. This data is parsed\nwhen `redisReaderGetReply` is called. This function returns an integer status\nand a reply object (as described above) via `void **reply`. The returned status\ncan be either `REDIS_OK` or `REDIS_ERR`, where the latter means something went\nwrong (either a protocol error, or an out of memory error).\n\nThe parser limits the level of nesting for multi bulk payloads to 7. If the\nmulti bulk nesting level is higher than this, the parser returns an error.\n\n### Customizing replies\n\nThe function `redisReaderGetReply` creates `redisReply` and makes the function\nargument `reply` point to the created `redisReply` variable. For instance, if\nthe response of type `REDIS_REPLY_STATUS` then the `str` field of `redisReply`\nwill hold the status as a vanilla C string. However, the functions that are\nresponsible for creating instances of the `redisReply` can be customized by\nsetting the `fn` field on the `redisReader` struct. This should be done\nimmediately after creating the `redisReader`.\n\nFor example, [hiredis-rb](https://github.com/pietern/hiredis-rb/blob/master/ext/hiredis_ext/reader.c)\nuses customized reply object functions to create Ruby objects.\n\n### Reader max buffer\n\nBoth when using the Reader API directly or when using it indirectly via a\nnormal Redis context, the redisReader structure uses a buffer in order to\naccumulate data from the server.\nUsually this buffer is destroyed when it is empty and is larger than 16\nkb in order to avoid wasting memory in unused buffers\n\nHowever when working with very big payloads destroying the buffer may slow\ndown performances considerably, so it is possible to modify the max size of\nan idle buffer changing the value of the `maxbuf` field of the reader structure\nto the desired value. The special value of 0 means that there is no maximum\nvalue for an idle buffer, so the buffer will never get freed.\n\nFor instance if you have a normal Redis context you can set the maximum idle\nbuffer to zero (unlimited) just with:\n\n    context->reader->maxbuf = 0;\n\nThis should be done only in order to maximize performances when working with\nlarge payloads. The context should be set back to `REDIS_READER_MAX_BUF` again\nas soon as possible in order to prevent allocation of useless memory.\n\n## AUTHORS\n\nHiredis was written by Salvatore Sanfilippo (antirez at gmail) and\nPieter Noordhuis (pcnoordhuis at gmail) and is released under the BSD license.\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.8/deps/hiredis/adapters/ae.h",
    "content": "/*\n * Copyright (c) 2010-2011, Pieter Noordhuis <pcnoordhuis at gmail dot com>\n *\n * All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions are met:\n *\n *   * Redistributions of source code must retain the above copyright notice,\n *     this list of conditions and the following disclaimer.\n *   * Redistributions in binary form must reproduce the above copyright\n *     notice, this list of conditions and the following disclaimer in the\n *     documentation and/or other materials provided with the distribution.\n *   * Neither the name of Redis nor the names of its contributors may be used\n *     to endorse or promote products derived from this software without\n *     specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\"\n * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\n * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE\n * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR\n * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF\n * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS\n * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN\n * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)\n * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE\n * POSSIBILITY OF SUCH DAMAGE.\n */\n\n#ifndef __HIREDIS_AE_H__\n#define __HIREDIS_AE_H__\n#include <sys/types.h>\n#include <ae.h>\n#include \"../hiredis.h\"\n#include \"../async.h\"\n\ntypedef struct redisAeEvents {\n    redisAsyncContext *context;\n    aeEventLoop *loop;\n    int fd;\n    int reading, writing;\n} redisAeEvents;\n\nstatic void redisAeReadEvent(aeEventLoop *el, int fd, void *privdata, int mask) {\n    ((void)el); ((void)fd); ((void)mask);\n\n    redisAeEvents *e = (redisAeEvents*)privdata;\n    redisAsyncHandleRead(e->context);\n}\n\nstatic void redisAeWriteEvent(aeEventLoop *el, int fd, void *privdata, int mask) {\n    ((void)el); ((void)fd); ((void)mask);\n\n    redisAeEvents *e = (redisAeEvents*)privdata;\n    redisAsyncHandleWrite(e->context);\n}\n\nstatic void redisAeAddRead(void *privdata) {\n    redisAeEvents *e = (redisAeEvents*)privdata;\n    aeEventLoop *loop = e->loop;\n    if (!e->reading) {\n        e->reading = 1;\n        aeCreateFileEvent(loop,e->fd,AE_READABLE,redisAeReadEvent,e);\n    }\n}\n\nstatic void redisAeDelRead(void *privdata) {\n    redisAeEvents *e = (redisAeEvents*)privdata;\n    aeEventLoop *loop = e->loop;\n    if (e->reading) {\n        e->reading = 0;\n        aeDeleteFileEvent(loop,e->fd,AE_READABLE);\n    }\n}\n\nstatic void redisAeAddWrite(void *privdata) {\n    redisAeEvents *e = (redisAeEvents*)privdata;\n    aeEventLoop *loop = e->loop;\n    if (!e->writing) {\n        e->writing = 1;\n        aeCreateFileEvent(loop,e->fd,AE_WRITABLE,redisAeWriteEvent,e);\n    }\n}\n\nstatic void redisAeDelWrite(void *privdata) {\n    redisAeEvents *e = (redisAeEvents*)privdata;\n    aeEventLoop *loop = e->loop;\n    if (e->writing) {\n        e->writing = 0;\n        aeDeleteFileEvent(loop,e->fd,AE_WRITABLE);\n    }\n}\n\nstatic void redisAeCleanup(void *privdata) {\n    redisAeEvents *e = (redisAeEvents*)privdata;\n    redisAeDelRead(privdata);\n    redisAeDelWrite(privdata);\n    free(e);\n}\n\nstatic int redisAeAttach(aeEventLoop *loop, redisAsyncContext *ac) {\n    redisContext *c = &(ac->c);\n    redisAeEvents *e;\n\n    /* Nothing should be attached when something is already attached */\n    if (ac->ev.data != NULL)\n        return REDIS_ERR;\n\n    /* Create container for context and r/w events */\n    e = (redisAeEvents*)malloc(sizeof(*e));\n    e->context = ac;\n    e->loop = loop;\n    e->fd = c->fd;\n    e->reading = e->writing = 0;\n\n    /* Register functions to start/stop listening for events */\n    ac->ev.addRead = redisAeAddRead;\n    ac->ev.delRead = redisAeDelRead;\n    ac->ev.addWrite = redisAeAddWrite;\n    ac->ev.delWrite = redisAeDelWrite;\n    ac->ev.cleanup = redisAeCleanup;\n    ac->ev.data = e;\n\n    return REDIS_OK;\n}\n#endif\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.8/deps/hiredis/adapters/libev.h",
    "content": "/*\n * Copyright (c) 2010-2011, Pieter Noordhuis <pcnoordhuis at gmail dot com>\n *\n * All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions are met:\n *\n *   * Redistributions of source code must retain the above copyright notice,\n *     this list of conditions and the following disclaimer.\n *   * Redistributions in binary form must reproduce the above copyright\n *     notice, this list of conditions and the following disclaimer in the\n *     documentation and/or other materials provided with the distribution.\n *   * Neither the name of Redis nor the names of its contributors may be used\n *     to endorse or promote products derived from this software without\n *     specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\"\n * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\n * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE\n * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR\n * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF\n * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS\n * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN\n * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)\n * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE\n * POSSIBILITY OF SUCH DAMAGE.\n */\n\n#ifndef __HIREDIS_LIBEV_H__\n#define __HIREDIS_LIBEV_H__\n#include <stdlib.h>\n#include <sys/types.h>\n#include <ev.h>\n#include \"../hiredis.h\"\n#include \"../async.h\"\n\ntypedef struct redisLibevEvents {\n    redisAsyncContext *context;\n    struct ev_loop *loop;\n    int reading, writing;\n    ev_io rev, wev;\n} redisLibevEvents;\n\nstatic void redisLibevReadEvent(EV_P_ ev_io *watcher, int revents) {\n#if EV_MULTIPLICITY\n    ((void)loop);\n#endif\n    ((void)revents);\n\n    redisLibevEvents *e = (redisLibevEvents*)watcher->data;\n    redisAsyncHandleRead(e->context);\n}\n\nstatic void redisLibevWriteEvent(EV_P_ ev_io *watcher, int revents) {\n#if EV_MULTIPLICITY\n    ((void)loop);\n#endif\n    ((void)revents);\n\n    redisLibevEvents *e = (redisLibevEvents*)watcher->data;\n    redisAsyncHandleWrite(e->context);\n}\n\nstatic void redisLibevAddRead(void *privdata) {\n    redisLibevEvents *e = (redisLibevEvents*)privdata;\n    struct ev_loop *loop = e->loop;\n    ((void)loop);\n    if (!e->reading) {\n        e->reading = 1;\n        ev_io_start(EV_A_ &e->rev);\n    }\n}\n\nstatic void redisLibevDelRead(void *privdata) {\n    redisLibevEvents *e = (redisLibevEvents*)privdata;\n    struct ev_loop *loop = e->loop;\n    ((void)loop);\n    if (e->reading) {\n        e->reading = 0;\n        ev_io_stop(EV_A_ &e->rev);\n    }\n}\n\nstatic void redisLibevAddWrite(void *privdata) {\n    redisLibevEvents *e = (redisLibevEvents*)privdata;\n    struct ev_loop *loop = e->loop;\n    ((void)loop);\n    if (!e->writing) {\n        e->writing = 1;\n        ev_io_start(EV_A_ &e->wev);\n    }\n}\n\nstatic void redisLibevDelWrite(void *privdata) {\n    redisLibevEvents *e = (redisLibevEvents*)privdata;\n    struct ev_loop *loop = e->loop;\n    ((void)loop);\n    if (e->writing) {\n        e->writing = 0;\n        ev_io_stop(EV_A_ &e->wev);\n    }\n}\n\nstatic void redisLibevCleanup(void *privdata) {\n    redisLibevEvents *e = (redisLibevEvents*)privdata;\n    redisLibevDelRead(privdata);\n    redisLibevDelWrite(privdata);\n    free(e);\n}\n\nstatic int redisLibevAttach(EV_P_ redisAsyncContext *ac) {\n    redisContext *c = &(ac->c);\n    redisLibevEvents *e;\n\n    /* Nothing should be attached when something is already attached */\n    if (ac->ev.data != NULL)\n        return REDIS_ERR;\n\n    /* Create container for context and r/w events */\n    e = (redisLibevEvents*)malloc(sizeof(*e));\n    e->context = ac;\n#if EV_MULTIPLICITY\n    e->loop = loop;\n#else\n    e->loop = NULL;\n#endif\n    e->reading = e->writing = 0;\n    e->rev.data = e;\n    e->wev.data = e;\n\n    /* Register functions to start/stop listening for events */\n    ac->ev.addRead = redisLibevAddRead;\n    ac->ev.delRead = redisLibevDelRead;\n    ac->ev.addWrite = redisLibevAddWrite;\n    ac->ev.delWrite = redisLibevDelWrite;\n    ac->ev.cleanup = redisLibevCleanup;\n    ac->ev.data = e;\n\n    /* Initialize read/write events */\n    ev_io_init(&e->rev,redisLibevReadEvent,c->fd,EV_READ);\n    ev_io_init(&e->wev,redisLibevWriteEvent,c->fd,EV_WRITE);\n    return REDIS_OK;\n}\n\n#endif\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.8/deps/hiredis/adapters/libevent.h",
    "content": "/*\n * Copyright (c) 2010-2011, Pieter Noordhuis <pcnoordhuis at gmail dot com>\n *\n * All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions are met:\n *\n *   * Redistributions of source code must retain the above copyright notice,\n *     this list of conditions and the following disclaimer.\n *   * Redistributions in binary form must reproduce the above copyright\n *     notice, this list of conditions and the following disclaimer in the\n *     documentation and/or other materials provided with the distribution.\n *   * Neither the name of Redis nor the names of its contributors may be used\n *     to endorse or promote products derived from this software without\n *     specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\"\n * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\n * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE\n * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR\n * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF\n * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS\n * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN\n * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)\n * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE\n * POSSIBILITY OF SUCH DAMAGE.\n */\n\n#ifndef __HIREDIS_LIBEVENT_H__\n#define __HIREDIS_LIBEVENT_H__\n#include <event.h>\n#include \"../hiredis.h\"\n#include \"../async.h\"\n\ntypedef struct redisLibeventEvents {\n    redisAsyncContext *context;\n    struct event rev, wev;\n} redisLibeventEvents;\n\nstatic void redisLibeventReadEvent(int fd, short event, void *arg) {\n    ((void)fd); ((void)event);\n    redisLibeventEvents *e = (redisLibeventEvents*)arg;\n    redisAsyncHandleRead(e->context);\n}\n\nstatic void redisLibeventWriteEvent(int fd, short event, void *arg) {\n    ((void)fd); ((void)event);\n    redisLibeventEvents *e = (redisLibeventEvents*)arg;\n    redisAsyncHandleWrite(e->context);\n}\n\nstatic void redisLibeventAddRead(void *privdata) {\n    redisLibeventEvents *e = (redisLibeventEvents*)privdata;\n    event_add(&e->rev,NULL);\n}\n\nstatic void redisLibeventDelRead(void *privdata) {\n    redisLibeventEvents *e = (redisLibeventEvents*)privdata;\n    event_del(&e->rev);\n}\n\nstatic void redisLibeventAddWrite(void *privdata) {\n    redisLibeventEvents *e = (redisLibeventEvents*)privdata;\n    event_add(&e->wev,NULL);\n}\n\nstatic void redisLibeventDelWrite(void *privdata) {\n    redisLibeventEvents *e = (redisLibeventEvents*)privdata;\n    event_del(&e->wev);\n}\n\nstatic void redisLibeventCleanup(void *privdata) {\n    redisLibeventEvents *e = (redisLibeventEvents*)privdata;\n    event_del(&e->rev);\n    event_del(&e->wev);\n    free(e);\n}\n\nstatic int redisLibeventAttach(redisAsyncContext *ac, struct event_base *base) {\n    redisContext *c = &(ac->c);\n    redisLibeventEvents *e;\n\n    /* Nothing should be attached when something is already attached */\n    if (ac->ev.data != NULL)\n        return REDIS_ERR;\n\n    /* Create container for context and r/w events */\n    e = (redisLibeventEvents*)malloc(sizeof(*e));\n    e->context = ac;\n\n    /* Register functions to start/stop listening for events */\n    ac->ev.addRead = redisLibeventAddRead;\n    ac->ev.delRead = redisLibeventDelRead;\n    ac->ev.addWrite = redisLibeventAddWrite;\n    ac->ev.delWrite = redisLibeventDelWrite;\n    ac->ev.cleanup = redisLibeventCleanup;\n    ac->ev.data = e;\n\n    /* Initialize and install read/write events */\n    event_set(&e->rev,c->fd,EV_READ,redisLibeventReadEvent,e);\n    event_set(&e->wev,c->fd,EV_WRITE,redisLibeventWriteEvent,e);\n    event_base_set(base,&e->rev);\n    event_base_set(base,&e->wev);\n    return REDIS_OK;\n}\n#endif\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.8/deps/hiredis/adapters/libuv.h",
    "content": "#ifndef __HIREDIS_LIBUV_H__\n#define __HIREDIS_LIBUV_H__\n#include <uv.h>\n#include \"../hiredis.h\"\n#include \"../async.h\"\n#include <string.h>\n\ntypedef struct redisLibuvEvents {\n  redisAsyncContext* context;\n  uv_poll_t          handle;\n  int                events;\n} redisLibuvEvents;\n\nint redisLibuvAttach(redisAsyncContext*, uv_loop_t*);\n\nstatic void redisLibuvPoll(uv_poll_t* handle, int status, int events) {\n  redisLibuvEvents* p = (redisLibuvEvents*)handle->data;\n\n  if (status != 0) {\n    return;\n  }\n\n  if (events & UV_READABLE) {\n    redisAsyncHandleRead(p->context);\n  }\n  if (events & UV_WRITABLE) {\n    redisAsyncHandleWrite(p->context);\n  }\n}\n\n\nstatic void redisLibuvAddRead(void *privdata) {\n  redisLibuvEvents* p = (redisLibuvEvents*)privdata;\n\n  p->events |= UV_READABLE;\n\n  uv_poll_start(&p->handle, p->events, redisLibuvPoll);\n}\n\n\nstatic void redisLibuvDelRead(void *privdata) {\n  redisLibuvEvents* p = (redisLibuvEvents*)privdata;\n\n  p->events &= ~UV_READABLE;\n\n  if (p->events) {\n    uv_poll_start(&p->handle, p->events, redisLibuvPoll);\n  } else {\n    uv_poll_stop(&p->handle);\n  }\n}\n\n\nstatic void redisLibuvAddWrite(void *privdata) {\n  redisLibuvEvents* p = (redisLibuvEvents*)privdata;\n\n  p->events |= UV_WRITABLE;\n\n  uv_poll_start(&p->handle, p->events, redisLibuvPoll);\n}\n\n\nstatic void redisLibuvDelWrite(void *privdata) {\n  redisLibuvEvents* p = (redisLibuvEvents*)privdata;\n\n  p->events &= ~UV_WRITABLE;\n\n  if (p->events) {\n    uv_poll_start(&p->handle, p->events, redisLibuvPoll);\n  } else {\n    uv_poll_stop(&p->handle);\n  }\n}\n\n\nstatic void on_close(uv_handle_t* handle) {\n  redisLibuvEvents* p = (redisLibuvEvents*)handle->data;\n\n  free(p);\n}\n\n\nstatic void redisLibuvCleanup(void *privdata) {\n  redisLibuvEvents* p = (redisLibuvEvents*)privdata;\n\n  uv_close((uv_handle_t*)&p->handle, on_close);\n}\n\n\nstatic int redisLibuvAttach(redisAsyncContext* ac, uv_loop_t* loop) {\n  redisContext *c = &(ac->c);\n\n  if (ac->ev.data != NULL) {\n    return REDIS_ERR;\n  }\n\n  ac->ev.addRead  = redisLibuvAddRead;\n  ac->ev.delRead  = redisLibuvDelRead;\n  ac->ev.addWrite = redisLibuvAddWrite;\n  ac->ev.delWrite = redisLibuvDelWrite;\n  ac->ev.cleanup  = redisLibuvCleanup;\n\n  redisLibuvEvents* p = (redisLibuvEvents*)malloc(sizeof(*p));\n\n  if (!p) {\n    return REDIS_ERR;\n  }\n\n  memset(p, 0, sizeof(*p));\n\n  if (uv_poll_init(loop, &p->handle, c->fd) != 0) {\n    return REDIS_ERR;\n  }\n\n  ac->ev.data    = p;\n  p->handle.data = p;\n  p->context     = ac;\n\n  return REDIS_OK;\n}\n#endif\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.8/deps/hiredis/async.c",
    "content": "/*\n * Copyright (c) 2009-2011, Salvatore Sanfilippo <antirez at gmail dot com>\n * Copyright (c) 2010-2011, Pieter Noordhuis <pcnoordhuis at gmail dot com>\n *\n * All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions are met:\n *\n *   * Redistributions of source code must retain the above copyright notice,\n *     this list of conditions and the following disclaimer.\n *   * Redistributions in binary form must reproduce the above copyright\n *     notice, this list of conditions and the following disclaimer in the\n *     documentation and/or other materials provided with the distribution.\n *   * Neither the name of Redis nor the names of its contributors may be used\n *     to endorse or promote products derived from this software without\n *     specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\"\n * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\n * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE\n * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR\n * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF\n * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS\n * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN\n * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)\n * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE\n * POSSIBILITY OF SUCH DAMAGE.\n */\n\n#include \"fmacros.h\"\n#include <stdlib.h>\n#include <string.h>\n#include <strings.h>\n#include <assert.h>\n#include <ctype.h>\n#include <errno.h>\n#include \"async.h\"\n#include \"net.h\"\n#include \"dict.c\"\n#include \"sds.h\"\n\n#define _EL_ADD_READ(ctx) do { \\\n        if ((ctx)->ev.addRead) (ctx)->ev.addRead((ctx)->ev.data); \\\n    } while(0)\n#define _EL_DEL_READ(ctx) do { \\\n        if ((ctx)->ev.delRead) (ctx)->ev.delRead((ctx)->ev.data); \\\n    } while(0)\n#define _EL_ADD_WRITE(ctx) do { \\\n        if ((ctx)->ev.addWrite) (ctx)->ev.addWrite((ctx)->ev.data); \\\n    } while(0)\n#define _EL_DEL_WRITE(ctx) do { \\\n        if ((ctx)->ev.delWrite) (ctx)->ev.delWrite((ctx)->ev.data); \\\n    } while(0)\n#define _EL_CLEANUP(ctx) do { \\\n        if ((ctx)->ev.cleanup) (ctx)->ev.cleanup((ctx)->ev.data); \\\n    } while(0);\n\n/* Forward declaration of function in hiredis.c */\nvoid __redisAppendCommand(redisContext *c, char *cmd, size_t len);\n\n/* Functions managing dictionary of callbacks for pub/sub. */\nstatic unsigned int callbackHash(const void *key) {\n    return dictGenHashFunction((const unsigned char *)key,\n                               sdslen((const sds)key));\n}\n\nstatic void *callbackValDup(void *privdata, const void *src) {\n    ((void) privdata);\n    redisCallback *dup = malloc(sizeof(*dup));\n    memcpy(dup,src,sizeof(*dup));\n    return dup;\n}\n\nstatic int callbackKeyCompare(void *privdata, const void *key1, const void *key2) {\n    int l1, l2;\n    ((void) privdata);\n\n    l1 = sdslen((const sds)key1);\n    l2 = sdslen((const sds)key2);\n    if (l1 != l2) return 0;\n    return memcmp(key1,key2,l1) == 0;\n}\n\nstatic void callbackKeyDestructor(void *privdata, void *key) {\n    ((void) privdata);\n    sdsfree((sds)key);\n}\n\nstatic void callbackValDestructor(void *privdata, void *val) {\n    ((void) privdata);\n    free(val);\n}\n\nstatic dictType callbackDict = {\n    callbackHash,\n    NULL,\n    callbackValDup,\n    callbackKeyCompare,\n    callbackKeyDestructor,\n    callbackValDestructor\n};\n\nstatic redisAsyncContext *redisAsyncInitialize(redisContext *c) {\n    redisAsyncContext *ac;\n\n    ac = realloc(c,sizeof(redisAsyncContext));\n    if (ac == NULL)\n        return NULL;\n\n    c = &(ac->c);\n\n    /* The regular connect functions will always set the flag REDIS_CONNECTED.\n     * For the async API, we want to wait until the first write event is\n     * received up before setting this flag, so reset it here. */\n    c->flags &= ~REDIS_CONNECTED;\n\n    ac->err = 0;\n    ac->errstr = NULL;\n    ac->data = NULL;\n\n    ac->ev.data = NULL;\n    ac->ev.addRead = NULL;\n    ac->ev.delRead = NULL;\n    ac->ev.addWrite = NULL;\n    ac->ev.delWrite = NULL;\n    ac->ev.cleanup = NULL;\n\n    ac->onConnect = NULL;\n    ac->onDisconnect = NULL;\n\n    ac->replies.head = NULL;\n    ac->replies.tail = NULL;\n    ac->sub.invalid.head = NULL;\n    ac->sub.invalid.tail = NULL;\n    ac->sub.channels = dictCreate(&callbackDict,NULL);\n    ac->sub.patterns = dictCreate(&callbackDict,NULL);\n    return ac;\n}\n\n/* We want the error field to be accessible directly instead of requiring\n * an indirection to the redisContext struct. */\nstatic void __redisAsyncCopyError(redisAsyncContext *ac) {\n    redisContext *c = &(ac->c);\n    ac->err = c->err;\n    ac->errstr = c->errstr;\n}\n\nredisAsyncContext *redisAsyncConnect(const char *ip, int port) {\n    redisContext *c;\n    redisAsyncContext *ac;\n\n    c = redisConnectNonBlock(ip,port);\n    if (c == NULL)\n        return NULL;\n\n    ac = redisAsyncInitialize(c);\n    if (ac == NULL) {\n        redisFree(c);\n        return NULL;\n    }\n\n    __redisAsyncCopyError(ac);\n    return ac;\n}\n\nredisAsyncContext *redisAsyncConnectBind(const char *ip, int port,\n                                         const char *source_addr) {\n    redisContext *c = redisConnectBindNonBlock(ip,port,source_addr);\n    redisAsyncContext *ac = redisAsyncInitialize(c);\n    __redisAsyncCopyError(ac);\n    return ac;\n}\n\nredisAsyncContext *redisAsyncConnectUnix(const char *path) {\n    redisContext *c;\n    redisAsyncContext *ac;\n\n    c = redisConnectUnixNonBlock(path);\n    if (c == NULL)\n        return NULL;\n\n    ac = redisAsyncInitialize(c);\n    if (ac == NULL) {\n        redisFree(c);\n        return NULL;\n    }\n\n    __redisAsyncCopyError(ac);\n    return ac;\n}\n\nint redisAsyncSetConnectCallback(redisAsyncContext *ac, redisConnectCallback *fn) {\n    if (ac->onConnect == NULL) {\n        ac->onConnect = fn;\n\n        /* The common way to detect an established connection is to wait for\n         * the first write event to be fired. This assumes the related event\n         * library functions are already set. */\n        _EL_ADD_WRITE(ac);\n        return REDIS_OK;\n    }\n    return REDIS_ERR;\n}\n\nint redisAsyncSetDisconnectCallback(redisAsyncContext *ac, redisDisconnectCallback *fn) {\n    if (ac->onDisconnect == NULL) {\n        ac->onDisconnect = fn;\n        return REDIS_OK;\n    }\n    return REDIS_ERR;\n}\n\n/* Helper functions to push/shift callbacks */\nstatic int __redisPushCallback(redisCallbackList *list, redisCallback *source) {\n    redisCallback *cb;\n\n    /* Copy callback from stack to heap */\n    cb = malloc(sizeof(*cb));\n    if (cb == NULL)\n        return REDIS_ERR_OOM;\n\n    if (source != NULL) {\n        memcpy(cb,source,sizeof(*cb));\n        cb->next = NULL;\n    }\n\n    /* Store callback in list */\n    if (list->head == NULL)\n        list->head = cb;\n    if (list->tail != NULL)\n        list->tail->next = cb;\n    list->tail = cb;\n    return REDIS_OK;\n}\n\nstatic int __redisShiftCallback(redisCallbackList *list, redisCallback *target) {\n    redisCallback *cb = list->head;\n    if (cb != NULL) {\n        list->head = cb->next;\n        if (cb == list->tail)\n            list->tail = NULL;\n\n        /* Copy callback from heap to stack */\n        if (target != NULL)\n            memcpy(target,cb,sizeof(*cb));\n        free(cb);\n        return REDIS_OK;\n    }\n    return REDIS_ERR;\n}\n\nstatic void __redisRunCallback(redisAsyncContext *ac, redisCallback *cb, redisReply *reply) {\n    redisContext *c = &(ac->c);\n    if (cb->fn != NULL) {\n        c->flags |= REDIS_IN_CALLBACK;\n        cb->fn(ac,reply,cb->privdata);\n        c->flags &= ~REDIS_IN_CALLBACK;\n    }\n}\n\n/* Helper function to free the context. */\nstatic void __redisAsyncFree(redisAsyncContext *ac) {\n    redisContext *c = &(ac->c);\n    redisCallback cb;\n    dictIterator *it;\n    dictEntry *de;\n\n    /* Execute pending callbacks with NULL reply. */\n    while (__redisShiftCallback(&ac->replies,&cb) == REDIS_OK)\n        __redisRunCallback(ac,&cb,NULL);\n\n    /* Execute callbacks for invalid commands */\n    while (__redisShiftCallback(&ac->sub.invalid,&cb) == REDIS_OK)\n        __redisRunCallback(ac,&cb,NULL);\n\n    /* Run subscription callbacks callbacks with NULL reply */\n    it = dictGetIterator(ac->sub.channels);\n    while ((de = dictNext(it)) != NULL)\n        __redisRunCallback(ac,dictGetEntryVal(de),NULL);\n    dictReleaseIterator(it);\n    dictRelease(ac->sub.channels);\n\n    it = dictGetIterator(ac->sub.patterns);\n    while ((de = dictNext(it)) != NULL)\n        __redisRunCallback(ac,dictGetEntryVal(de),NULL);\n    dictReleaseIterator(it);\n    dictRelease(ac->sub.patterns);\n\n    /* Signal event lib to clean up */\n    _EL_CLEANUP(ac);\n\n    /* Execute disconnect callback. When redisAsyncFree() initiated destroying\n     * this context, the status will always be REDIS_OK. */\n    if (ac->onDisconnect && (c->flags & REDIS_CONNECTED)) {\n        if (c->flags & REDIS_FREEING) {\n            ac->onDisconnect(ac,REDIS_OK);\n        } else {\n            ac->onDisconnect(ac,(ac->err == 0) ? REDIS_OK : REDIS_ERR);\n        }\n    }\n\n    /* Cleanup self */\n    redisFree(c);\n}\n\n/* Free the async context. When this function is called from a callback,\n * control needs to be returned to redisProcessCallbacks() before actual\n * free'ing. To do so, a flag is set on the context which is picked up by\n * redisProcessCallbacks(). Otherwise, the context is immediately free'd. */\nvoid redisAsyncFree(redisAsyncContext *ac) {\n    redisContext *c = &(ac->c);\n    c->flags |= REDIS_FREEING;\n    if (!(c->flags & REDIS_IN_CALLBACK))\n        __redisAsyncFree(ac);\n}\n\n/* Helper function to make the disconnect happen and clean up. */\nstatic void __redisAsyncDisconnect(redisAsyncContext *ac) {\n    redisContext *c = &(ac->c);\n\n    /* Make sure error is accessible if there is any */\n    __redisAsyncCopyError(ac);\n\n    if (ac->err == 0) {\n        /* For clean disconnects, there should be no pending callbacks. */\n        assert(__redisShiftCallback(&ac->replies,NULL) == REDIS_ERR);\n    } else {\n        /* Disconnection is caused by an error, make sure that pending\n         * callbacks cannot call new commands. */\n        c->flags |= REDIS_DISCONNECTING;\n    }\n\n    /* For non-clean disconnects, __redisAsyncFree() will execute pending\n     * callbacks with a NULL-reply. */\n    __redisAsyncFree(ac);\n}\n\n/* Tries to do a clean disconnect from Redis, meaning it stops new commands\n * from being issued, but tries to flush the output buffer and execute\n * callbacks for all remaining replies. When this function is called from a\n * callback, there might be more replies and we can safely defer disconnecting\n * to redisProcessCallbacks(). Otherwise, we can only disconnect immediately\n * when there are no pending callbacks. */\nvoid redisAsyncDisconnect(redisAsyncContext *ac) {\n    redisContext *c = &(ac->c);\n    c->flags |= REDIS_DISCONNECTING;\n    if (!(c->flags & REDIS_IN_CALLBACK) && ac->replies.head == NULL)\n        __redisAsyncDisconnect(ac);\n}\n\nstatic int __redisGetSubscribeCallback(redisAsyncContext *ac, redisReply *reply, redisCallback *dstcb) {\n    redisContext *c = &(ac->c);\n    dict *callbacks;\n    dictEntry *de;\n    int pvariant;\n    char *stype;\n    sds sname;\n\n    /* Custom reply functions are not supported for pub/sub. This will fail\n     * very hard when they are used... */\n    if (reply->type == REDIS_REPLY_ARRAY) {\n        assert(reply->elements >= 2);\n        assert(reply->element[0]->type == REDIS_REPLY_STRING);\n        stype = reply->element[0]->str;\n        pvariant = (tolower(stype[0]) == 'p') ? 1 : 0;\n\n        if (pvariant)\n            callbacks = ac->sub.patterns;\n        else\n            callbacks = ac->sub.channels;\n\n        /* Locate the right callback */\n        assert(reply->element[1]->type == REDIS_REPLY_STRING);\n        sname = sdsnewlen(reply->element[1]->str,reply->element[1]->len);\n        de = dictFind(callbacks,sname);\n        if (de != NULL) {\n            memcpy(dstcb,dictGetEntryVal(de),sizeof(*dstcb));\n\n            /* If this is an unsubscribe message, remove it. */\n            if (strcasecmp(stype+pvariant,\"unsubscribe\") == 0) {\n                dictDelete(callbacks,sname);\n\n                /* If this was the last unsubscribe message, revert to\n                 * non-subscribe mode. */\n                assert(reply->element[2]->type == REDIS_REPLY_INTEGER);\n                if (reply->element[2]->integer == 0)\n                    c->flags &= ~REDIS_SUBSCRIBED;\n            }\n        }\n        sdsfree(sname);\n    } else {\n        /* Shift callback for invalid commands. */\n        __redisShiftCallback(&ac->sub.invalid,dstcb);\n    }\n    return REDIS_OK;\n}\n\nvoid redisProcessCallbacks(redisAsyncContext *ac) {\n    redisContext *c = &(ac->c);\n    redisCallback cb = {NULL, NULL, NULL};\n    void *reply = NULL;\n    int status;\n\n    while((status = redisGetReply(c,&reply)) == REDIS_OK) {\n        if (reply == NULL) {\n            /* When the connection is being disconnected and there are\n             * no more replies, this is the cue to really disconnect. */\n            if (c->flags & REDIS_DISCONNECTING && sdslen(c->obuf) == 0) {\n                __redisAsyncDisconnect(ac);\n                return;\n            }\n\n            /* If monitor mode, repush callback */\n            if(c->flags & REDIS_MONITORING) {\n                __redisPushCallback(&ac->replies,&cb);\n            }\n\n            /* When the connection is not being disconnected, simply stop\n             * trying to get replies and wait for the next loop tick. */\n            break;\n        }\n\n        /* Even if the context is subscribed, pending regular callbacks will\n         * get a reply before pub/sub messages arrive. */\n        if (__redisShiftCallback(&ac->replies,&cb) != REDIS_OK) {\n            /*\n             * A spontaneous reply in a not-subscribed context can be the error\n             * reply that is sent when a new connection exceeds the maximum\n             * number of allowed connections on the server side.\n             *\n             * This is seen as an error instead of a regular reply because the\n             * server closes the connection after sending it.\n             *\n             * To prevent the error from being overwritten by an EOF error the\n             * connection is closed here. See issue #43.\n             *\n             * Another possibility is that the server is loading its dataset.\n             * In this case we also want to close the connection, and have the\n             * user wait until the server is ready to take our request.\n             */\n            if (((redisReply*)reply)->type == REDIS_REPLY_ERROR) {\n                c->err = REDIS_ERR_OTHER;\n                snprintf(c->errstr,sizeof(c->errstr),\"%s\",((redisReply*)reply)->str);\n                c->reader->fn->freeObject(reply);\n                __redisAsyncDisconnect(ac);\n                return;\n            }\n            /* No more regular callbacks and no errors, the context *must* be subscribed or monitoring. */\n            assert((c->flags & REDIS_SUBSCRIBED || c->flags & REDIS_MONITORING));\n            if(c->flags & REDIS_SUBSCRIBED)\n                __redisGetSubscribeCallback(ac,reply,&cb);\n        }\n\n        if (cb.fn != NULL) {\n            __redisRunCallback(ac,&cb,reply);\n            c->reader->fn->freeObject(reply);\n\n            /* Proceed with free'ing when redisAsyncFree() was called. */\n            if (c->flags & REDIS_FREEING) {\n                __redisAsyncFree(ac);\n                return;\n            }\n        } else {\n            /* No callback for this reply. This can either be a NULL callback,\n             * or there were no callbacks to begin with. Either way, don't\n             * abort with an error, but simply ignore it because the client\n             * doesn't know what the server will spit out over the wire. */\n            c->reader->fn->freeObject(reply);\n        }\n    }\n\n    /* Disconnect when there was an error reading the reply */\n    if (status != REDIS_OK)\n        __redisAsyncDisconnect(ac);\n}\n\n/* Internal helper function to detect socket status the first time a read or\n * write event fires. When connecting was not succesful, the connect callback\n * is called with a REDIS_ERR status and the context is free'd. */\nstatic int __redisAsyncHandleConnect(redisAsyncContext *ac) {\n    redisContext *c = &(ac->c);\n\n    if (redisCheckSocketError(c) == REDIS_ERR) {\n        /* Try again later when connect(2) is still in progress. */\n        if (errno == EINPROGRESS)\n            return REDIS_OK;\n\n        if (ac->onConnect) ac->onConnect(ac,REDIS_ERR);\n        __redisAsyncDisconnect(ac);\n        return REDIS_ERR;\n    }\n\n    /* Mark context as connected. */\n    c->flags |= REDIS_CONNECTED;\n    if (ac->onConnect) ac->onConnect(ac,REDIS_OK);\n    return REDIS_OK;\n}\n\n/* This function should be called when the socket is readable.\n * It processes all replies that can be read and executes their callbacks.\n */\nvoid redisAsyncHandleRead(redisAsyncContext *ac) {\n    redisContext *c = &(ac->c);\n\n    if (!(c->flags & REDIS_CONNECTED)) {\n        /* Abort connect was not successful. */\n        if (__redisAsyncHandleConnect(ac) != REDIS_OK)\n            return;\n        /* Try again later when the context is still not connected. */\n        if (!(c->flags & REDIS_CONNECTED))\n            return;\n    }\n\n    if (redisBufferRead(c) == REDIS_ERR) {\n        __redisAsyncDisconnect(ac);\n    } else {\n        /* Always re-schedule reads */\n        _EL_ADD_READ(ac);\n        redisProcessCallbacks(ac);\n    }\n}\n\nvoid redisAsyncHandleWrite(redisAsyncContext *ac) {\n    redisContext *c = &(ac->c);\n    int done = 0;\n\n    if (!(c->flags & REDIS_CONNECTED)) {\n        /* Abort connect was not successful. */\n        if (__redisAsyncHandleConnect(ac) != REDIS_OK)\n            return;\n        /* Try again later when the context is still not connected. */\n        if (!(c->flags & REDIS_CONNECTED))\n            return;\n    }\n\n    if (redisBufferWrite(c,&done) == REDIS_ERR) {\n        __redisAsyncDisconnect(ac);\n    } else {\n        /* Continue writing when not done, stop writing otherwise */\n        if (!done)\n            _EL_ADD_WRITE(ac);\n        else\n            _EL_DEL_WRITE(ac);\n\n        /* Always schedule reads after writes */\n        _EL_ADD_READ(ac);\n    }\n}\n\n/* Sets a pointer to the first argument and its length starting at p. Returns\n * the number of bytes to skip to get to the following argument. */\nstatic char *nextArgument(char *start, char **str, size_t *len) {\n    char *p = start;\n    if (p[0] != '$') {\n        p = strchr(p,'$');\n        if (p == NULL) return NULL;\n    }\n\n    *len = (int)strtol(p+1,NULL,10);\n    p = strchr(p,'\\r');\n    assert(p);\n    *str = p+2;\n    return p+2+(*len)+2;\n}\n\n/* Helper function for the redisAsyncCommand* family of functions. Writes a\n * formatted command to the output buffer and registers the provided callback\n * function with the context. */\nstatic int __redisAsyncCommand(redisAsyncContext *ac, redisCallbackFn *fn, void *privdata, char *cmd, size_t len) {\n    redisContext *c = &(ac->c);\n    redisCallback cb;\n    int pvariant, hasnext;\n    char *cstr, *astr;\n    size_t clen, alen;\n    char *p;\n    sds sname;\n\n    /* Don't accept new commands when the connection is about to be closed. */\n    if (c->flags & (REDIS_DISCONNECTING | REDIS_FREEING)) return REDIS_ERR;\n\n    /* Setup callback */\n    cb.fn = fn;\n    cb.privdata = privdata;\n\n    /* Find out which command will be appended. */\n    p = nextArgument(cmd,&cstr,&clen);\n    assert(p != NULL);\n    hasnext = (p[0] == '$');\n    pvariant = (tolower(cstr[0]) == 'p') ? 1 : 0;\n    cstr += pvariant;\n    clen -= pvariant;\n\n    if (hasnext && strncasecmp(cstr,\"subscribe\\r\\n\",11) == 0) {\n        c->flags |= REDIS_SUBSCRIBED;\n\n        /* Add every channel/pattern to the list of subscription callbacks. */\n        while ((p = nextArgument(p,&astr,&alen)) != NULL) {\n            sname = sdsnewlen(astr,alen);\n            if (pvariant)\n                dictReplace(ac->sub.patterns,sname,&cb);\n            else\n                dictReplace(ac->sub.channels,sname,&cb);\n        }\n    } else if (strncasecmp(cstr,\"unsubscribe\\r\\n\",13) == 0) {\n        /* It is only useful to call (P)UNSUBSCRIBE when the context is\n         * subscribed to one or more channels or patterns. */\n        if (!(c->flags & REDIS_SUBSCRIBED)) return REDIS_ERR;\n\n        /* (P)UNSUBSCRIBE does not have its own response: every channel or\n         * pattern that is unsubscribed will receive a message. This means we\n         * should not append a callback function for this command. */\n     } else if(strncasecmp(cstr,\"monitor\\r\\n\",9) == 0) {\n         /* Set monitor flag and push callback */\n         c->flags |= REDIS_MONITORING;\n         __redisPushCallback(&ac->replies,&cb);\n    } else {\n        if (c->flags & REDIS_SUBSCRIBED)\n            /* This will likely result in an error reply, but it needs to be\n             * received and passed to the callback. */\n            __redisPushCallback(&ac->sub.invalid,&cb);\n        else\n            __redisPushCallback(&ac->replies,&cb);\n    }\n\n    __redisAppendCommand(c,cmd,len);\n\n    /* Always schedule a write when the write buffer is non-empty */\n    _EL_ADD_WRITE(ac);\n\n    return REDIS_OK;\n}\n\nint redisvAsyncCommand(redisAsyncContext *ac, redisCallbackFn *fn, void *privdata, const char *format, va_list ap) {\n    char *cmd;\n    int len;\n    int status;\n    len = redisvFormatCommand(&cmd,format,ap);\n    status = __redisAsyncCommand(ac,fn,privdata,cmd,len);\n    free(cmd);\n    return status;\n}\n\nint redisAsyncCommand(redisAsyncContext *ac, redisCallbackFn *fn, void *privdata, const char *format, ...) {\n    va_list ap;\n    int status;\n    va_start(ap,format);\n    status = redisvAsyncCommand(ac,fn,privdata,format,ap);\n    va_end(ap);\n    return status;\n}\n\nint redisAsyncCommandArgv(redisAsyncContext *ac, redisCallbackFn *fn, void *privdata, int argc, const char **argv, const size_t *argvlen) {\n    char *cmd;\n    int len;\n    int status;\n    len = redisFormatCommandArgv(&cmd,argc,argv,argvlen);\n    status = __redisAsyncCommand(ac,fn,privdata,cmd,len);\n    free(cmd);\n    return status;\n}\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.8/deps/hiredis/async.h",
    "content": "/*\n * Copyright (c) 2009-2011, Salvatore Sanfilippo <antirez at gmail dot com>\n * Copyright (c) 2010-2011, Pieter Noordhuis <pcnoordhuis at gmail dot com>\n *\n * All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions are met:\n *\n *   * Redistributions of source code must retain the above copyright notice,\n *     this list of conditions and the following disclaimer.\n *   * Redistributions in binary form must reproduce the above copyright\n *     notice, this list of conditions and the following disclaimer in the\n *     documentation and/or other materials provided with the distribution.\n *   * Neither the name of Redis nor the names of its contributors may be used\n *     to endorse or promote products derived from this software without\n *     specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\"\n * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\n * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE\n * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR\n * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF\n * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS\n * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN\n * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)\n * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE\n * POSSIBILITY OF SUCH DAMAGE.\n */\n\n#ifndef __HIREDIS_ASYNC_H\n#define __HIREDIS_ASYNC_H\n#include \"hiredis.h\"\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\nstruct redisAsyncContext; /* need forward declaration of redisAsyncContext */\nstruct dict; /* dictionary header is included in async.c */\n\n/* Reply callback prototype and container */\ntypedef void (redisCallbackFn)(struct redisAsyncContext*, void*, void*);\ntypedef struct redisCallback {\n    struct redisCallback *next; /* simple singly linked list */\n    redisCallbackFn *fn;\n    void *privdata;\n} redisCallback;\n\n/* List of callbacks for either regular replies or pub/sub */\ntypedef struct redisCallbackList {\n    redisCallback *head, *tail;\n} redisCallbackList;\n\n/* Connection callback prototypes */\ntypedef void (redisDisconnectCallback)(const struct redisAsyncContext*, int status);\ntypedef void (redisConnectCallback)(const struct redisAsyncContext*, int status);\n\n/* Context for an async connection to Redis */\ntypedef struct redisAsyncContext {\n    /* Hold the regular context, so it can be realloc'ed. */\n    redisContext c;\n\n    /* Setup error flags so they can be used directly. */\n    int err;\n    char *errstr;\n\n    /* Not used by hiredis */\n    void *data;\n\n    /* Event library data and hooks */\n    struct {\n        void *data;\n\n        /* Hooks that are called when the library expects to start\n         * reading/writing. These functions should be idempotent. */\n        void (*addRead)(void *privdata);\n        void (*delRead)(void *privdata);\n        void (*addWrite)(void *privdata);\n        void (*delWrite)(void *privdata);\n        void (*cleanup)(void *privdata);\n    } ev;\n\n    /* Called when either the connection is terminated due to an error or per\n     * user request. The status is set accordingly (REDIS_OK, REDIS_ERR). */\n    redisDisconnectCallback *onDisconnect;\n\n    /* Called when the first write event was received. */\n    redisConnectCallback *onConnect;\n\n    /* Regular command callbacks */\n    redisCallbackList replies;\n\n    /* Subscription callbacks */\n    struct {\n        redisCallbackList invalid;\n        struct dict *channels;\n        struct dict *patterns;\n    } sub;\n} redisAsyncContext;\n\n/* Functions that proxy to hiredis */\nredisAsyncContext *redisAsyncConnect(const char *ip, int port);\nredisAsyncContext *redisAsyncConnectBind(const char *ip, int port, const char *source_addr);\nredisAsyncContext *redisAsyncConnectUnix(const char *path);\nint redisAsyncSetConnectCallback(redisAsyncContext *ac, redisConnectCallback *fn);\nint redisAsyncSetDisconnectCallback(redisAsyncContext *ac, redisDisconnectCallback *fn);\nvoid redisAsyncDisconnect(redisAsyncContext *ac);\nvoid redisAsyncFree(redisAsyncContext *ac);\n\n/* Handle read/write events */\nvoid redisAsyncHandleRead(redisAsyncContext *ac);\nvoid redisAsyncHandleWrite(redisAsyncContext *ac);\n\n/* Command functions for an async context. Write the command to the\n * output buffer and register the provided callback. */\nint redisvAsyncCommand(redisAsyncContext *ac, redisCallbackFn *fn, void *privdata, const char *format, va_list ap);\nint redisAsyncCommand(redisAsyncContext *ac, redisCallbackFn *fn, void *privdata, const char *format, ...);\nint redisAsyncCommandArgv(redisAsyncContext *ac, redisCallbackFn *fn, void *privdata, int argc, const char **argv, const size_t *argvlen);\n\n#ifdef __cplusplus\n}\n#endif\n\n#endif\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.8/deps/hiredis/dict.c",
    "content": "/* Hash table implementation.\n *\n * This file implements in memory hash tables with insert/del/replace/find/\n * get-random-element operations. Hash tables will auto resize if needed\n * tables of power of two in size are used, collisions are handled by\n * chaining. See the source code for more information... :)\n *\n * Copyright (c) 2006-2010, Salvatore Sanfilippo <antirez at gmail dot com>\n * All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions are met:\n *\n *   * Redistributions of source code must retain the above copyright notice,\n *     this list of conditions and the following disclaimer.\n *   * Redistributions in binary form must reproduce the above copyright\n *     notice, this list of conditions and the following disclaimer in the\n *     documentation and/or other materials provided with the distribution.\n *   * Neither the name of Redis nor the names of its contributors may be used\n *     to endorse or promote products derived from this software without\n *     specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\"\n * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\n * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE\n * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR\n * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF\n * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS\n * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN\n * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)\n * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE\n * POSSIBILITY OF SUCH DAMAGE.\n */\n\n#include \"fmacros.h\"\n#include <stdlib.h>\n#include <assert.h>\n#include <limits.h>\n#include \"dict.h\"\n\n/* -------------------------- private prototypes ---------------------------- */\n\nstatic int _dictExpandIfNeeded(dict *ht);\nstatic unsigned long _dictNextPower(unsigned long size);\nstatic int _dictKeyIndex(dict *ht, const void *key);\nstatic int _dictInit(dict *ht, dictType *type, void *privDataPtr);\n\n/* -------------------------- hash functions -------------------------------- */\n\n/* Generic hash function (a popular one from Bernstein).\n * I tested a few and this was the best. */\nstatic unsigned int dictGenHashFunction(const unsigned char *buf, int len) {\n    unsigned int hash = 5381;\n\n    while (len--)\n        hash = ((hash << 5) + hash) + (*buf++); /* hash * 33 + c */\n    return hash;\n}\n\n/* ----------------------------- API implementation ------------------------- */\n\n/* Reset an hashtable already initialized with ht_init().\n * NOTE: This function should only called by ht_destroy(). */\nstatic void _dictReset(dict *ht) {\n    ht->table = NULL;\n    ht->size = 0;\n    ht->sizemask = 0;\n    ht->used = 0;\n}\n\n/* Create a new hash table */\nstatic dict *dictCreate(dictType *type, void *privDataPtr) {\n    dict *ht = malloc(sizeof(*ht));\n    _dictInit(ht,type,privDataPtr);\n    return ht;\n}\n\n/* Initialize the hash table */\nstatic int _dictInit(dict *ht, dictType *type, void *privDataPtr) {\n    _dictReset(ht);\n    ht->type = type;\n    ht->privdata = privDataPtr;\n    return DICT_OK;\n}\n\n/* Expand or create the hashtable */\nstatic int dictExpand(dict *ht, unsigned long size) {\n    dict n; /* the new hashtable */\n    unsigned long realsize = _dictNextPower(size), i;\n\n    /* the size is invalid if it is smaller than the number of\n     * elements already inside the hashtable */\n    if (ht->used > size)\n        return DICT_ERR;\n\n    _dictInit(&n, ht->type, ht->privdata);\n    n.size = realsize;\n    n.sizemask = realsize-1;\n    n.table = calloc(realsize,sizeof(dictEntry*));\n\n    /* Copy all the elements from the old to the new table:\n     * note that if the old hash table is empty ht->size is zero,\n     * so dictExpand just creates an hash table. */\n    n.used = ht->used;\n    for (i = 0; i < ht->size && ht->used > 0; i++) {\n        dictEntry *he, *nextHe;\n\n        if (ht->table[i] == NULL) continue;\n\n        /* For each hash entry on this slot... */\n        he = ht->table[i];\n        while(he) {\n            unsigned int h;\n\n            nextHe = he->next;\n            /* Get the new element index */\n            h = dictHashKey(ht, he->key) & n.sizemask;\n            he->next = n.table[h];\n            n.table[h] = he;\n            ht->used--;\n            /* Pass to the next element */\n            he = nextHe;\n        }\n    }\n    assert(ht->used == 0);\n    free(ht->table);\n\n    /* Remap the new hashtable in the old */\n    *ht = n;\n    return DICT_OK;\n}\n\n/* Add an element to the target hash table */\nstatic int dictAdd(dict *ht, void *key, void *val) {\n    int index;\n    dictEntry *entry;\n\n    /* Get the index of the new element, or -1 if\n     * the element already exists. */\n    if ((index = _dictKeyIndex(ht, key)) == -1)\n        return DICT_ERR;\n\n    /* Allocates the memory and stores key */\n    entry = malloc(sizeof(*entry));\n    entry->next = ht->table[index];\n    ht->table[index] = entry;\n\n    /* Set the hash entry fields. */\n    dictSetHashKey(ht, entry, key);\n    dictSetHashVal(ht, entry, val);\n    ht->used++;\n    return DICT_OK;\n}\n\n/* Add an element, discarding the old if the key already exists.\n * Return 1 if the key was added from scratch, 0 if there was already an\n * element with such key and dictReplace() just performed a value update\n * operation. */\nstatic int dictReplace(dict *ht, void *key, void *val) {\n    dictEntry *entry, auxentry;\n\n    /* Try to add the element. If the key\n     * does not exists dictAdd will suceed. */\n    if (dictAdd(ht, key, val) == DICT_OK)\n        return 1;\n    /* It already exists, get the entry */\n    entry = dictFind(ht, key);\n    /* Free the old value and set the new one */\n    /* Set the new value and free the old one. Note that it is important\n     * to do that in this order, as the value may just be exactly the same\n     * as the previous one. In this context, think to reference counting,\n     * you want to increment (set), and then decrement (free), and not the\n     * reverse. */\n    auxentry = *entry;\n    dictSetHashVal(ht, entry, val);\n    dictFreeEntryVal(ht, &auxentry);\n    return 0;\n}\n\n/* Search and remove an element */\nstatic int dictDelete(dict *ht, const void *key) {\n    unsigned int h;\n    dictEntry *de, *prevde;\n\n    if (ht->size == 0)\n        return DICT_ERR;\n    h = dictHashKey(ht, key) & ht->sizemask;\n    de = ht->table[h];\n\n    prevde = NULL;\n    while(de) {\n        if (dictCompareHashKeys(ht,key,de->key)) {\n            /* Unlink the element from the list */\n            if (prevde)\n                prevde->next = de->next;\n            else\n                ht->table[h] = de->next;\n\n            dictFreeEntryKey(ht,de);\n            dictFreeEntryVal(ht,de);\n            free(de);\n            ht->used--;\n            return DICT_OK;\n        }\n        prevde = de;\n        de = de->next;\n    }\n    return DICT_ERR; /* not found */\n}\n\n/* Destroy an entire hash table */\nstatic int _dictClear(dict *ht) {\n    unsigned long i;\n\n    /* Free all the elements */\n    for (i = 0; i < ht->size && ht->used > 0; i++) {\n        dictEntry *he, *nextHe;\n\n        if ((he = ht->table[i]) == NULL) continue;\n        while(he) {\n            nextHe = he->next;\n            dictFreeEntryKey(ht, he);\n            dictFreeEntryVal(ht, he);\n            free(he);\n            ht->used--;\n            he = nextHe;\n        }\n    }\n    /* Free the table and the allocated cache structure */\n    free(ht->table);\n    /* Re-initialize the table */\n    _dictReset(ht);\n    return DICT_OK; /* never fails */\n}\n\n/* Clear & Release the hash table */\nstatic void dictRelease(dict *ht) {\n    _dictClear(ht);\n    free(ht);\n}\n\nstatic dictEntry *dictFind(dict *ht, const void *key) {\n    dictEntry *he;\n    unsigned int h;\n\n    if (ht->size == 0) return NULL;\n    h = dictHashKey(ht, key) & ht->sizemask;\n    he = ht->table[h];\n    while(he) {\n        if (dictCompareHashKeys(ht, key, he->key))\n            return he;\n        he = he->next;\n    }\n    return NULL;\n}\n\nstatic dictIterator *dictGetIterator(dict *ht) {\n    dictIterator *iter = malloc(sizeof(*iter));\n\n    iter->ht = ht;\n    iter->index = -1;\n    iter->entry = NULL;\n    iter->nextEntry = NULL;\n    return iter;\n}\n\nstatic dictEntry *dictNext(dictIterator *iter) {\n    while (1) {\n        if (iter->entry == NULL) {\n            iter->index++;\n            if (iter->index >=\n                    (signed)iter->ht->size) break;\n            iter->entry = iter->ht->table[iter->index];\n        } else {\n            iter->entry = iter->nextEntry;\n        }\n        if (iter->entry) {\n            /* We need to save the 'next' here, the iterator user\n             * may delete the entry we are returning. */\n            iter->nextEntry = iter->entry->next;\n            return iter->entry;\n        }\n    }\n    return NULL;\n}\n\nstatic void dictReleaseIterator(dictIterator *iter) {\n    free(iter);\n}\n\n/* ------------------------- private functions ------------------------------ */\n\n/* Expand the hash table if needed */\nstatic int _dictExpandIfNeeded(dict *ht) {\n    /* If the hash table is empty expand it to the intial size,\n     * if the table is \"full\" dobule its size. */\n    if (ht->size == 0)\n        return dictExpand(ht, DICT_HT_INITIAL_SIZE);\n    if (ht->used == ht->size)\n        return dictExpand(ht, ht->size*2);\n    return DICT_OK;\n}\n\n/* Our hash table capability is a power of two */\nstatic unsigned long _dictNextPower(unsigned long size) {\n    unsigned long i = DICT_HT_INITIAL_SIZE;\n\n    if (size >= LONG_MAX) return LONG_MAX;\n    while(1) {\n        if (i >= size)\n            return i;\n        i *= 2;\n    }\n}\n\n/* Returns the index of a free slot that can be populated with\n * an hash entry for the given 'key'.\n * If the key already exists, -1 is returned. */\nstatic int _dictKeyIndex(dict *ht, const void *key) {\n    unsigned int h;\n    dictEntry *he;\n\n    /* Expand the hashtable if needed */\n    if (_dictExpandIfNeeded(ht) == DICT_ERR)\n        return -1;\n    /* Compute the key hash value */\n    h = dictHashKey(ht, key) & ht->sizemask;\n    /* Search if this slot does not already contain the given key */\n    he = ht->table[h];\n    while(he) {\n        if (dictCompareHashKeys(ht, key, he->key))\n            return -1;\n        he = he->next;\n    }\n    return h;\n}\n\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.8/deps/hiredis/dict.h",
    "content": "/* Hash table implementation.\n *\n * This file implements in memory hash tables with insert/del/replace/find/\n * get-random-element operations. Hash tables will auto resize if needed\n * tables of power of two in size are used, collisions are handled by\n * chaining. See the source code for more information... :)\n *\n * Copyright (c) 2006-2010, Salvatore Sanfilippo <antirez at gmail dot com>\n * All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions are met:\n *\n *   * Redistributions of source code must retain the above copyright notice,\n *     this list of conditions and the following disclaimer.\n *   * Redistributions in binary form must reproduce the above copyright\n *     notice, this list of conditions and the following disclaimer in the\n *     documentation and/or other materials provided with the distribution.\n *   * Neither the name of Redis nor the names of its contributors may be used\n *     to endorse or promote products derived from this software without\n *     specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\"\n * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\n * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE\n * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR\n * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF\n * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS\n * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN\n * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)\n * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE\n * POSSIBILITY OF SUCH DAMAGE.\n */\n\n#ifndef __DICT_H\n#define __DICT_H\n\n#define DICT_OK 0\n#define DICT_ERR 1\n\n/* Unused arguments generate annoying warnings... */\n#define DICT_NOTUSED(V) ((void) V)\n\ntypedef struct dictEntry {\n    void *key;\n    void *val;\n    struct dictEntry *next;\n} dictEntry;\n\ntypedef struct dictType {\n    unsigned int (*hashFunction)(const void *key);\n    void *(*keyDup)(void *privdata, const void *key);\n    void *(*valDup)(void *privdata, const void *obj);\n    int (*keyCompare)(void *privdata, const void *key1, const void *key2);\n    void (*keyDestructor)(void *privdata, void *key);\n    void (*valDestructor)(void *privdata, void *obj);\n} dictType;\n\ntypedef struct dict {\n    dictEntry **table;\n    dictType *type;\n    unsigned long size;\n    unsigned long sizemask;\n    unsigned long used;\n    void *privdata;\n} dict;\n\ntypedef struct dictIterator {\n    dict *ht;\n    int index;\n    dictEntry *entry, *nextEntry;\n} dictIterator;\n\n/* This is the initial size of every hash table */\n#define DICT_HT_INITIAL_SIZE     4\n\n/* ------------------------------- Macros ------------------------------------*/\n#define dictFreeEntryVal(ht, entry) \\\n    if ((ht)->type->valDestructor) \\\n        (ht)->type->valDestructor((ht)->privdata, (entry)->val)\n\n#define dictSetHashVal(ht, entry, _val_) do { \\\n    if ((ht)->type->valDup) \\\n        entry->val = (ht)->type->valDup((ht)->privdata, _val_); \\\n    else \\\n        entry->val = (_val_); \\\n} while(0)\n\n#define dictFreeEntryKey(ht, entry) \\\n    if ((ht)->type->keyDestructor) \\\n        (ht)->type->keyDestructor((ht)->privdata, (entry)->key)\n\n#define dictSetHashKey(ht, entry, _key_) do { \\\n    if ((ht)->type->keyDup) \\\n        entry->key = (ht)->type->keyDup((ht)->privdata, _key_); \\\n    else \\\n        entry->key = (_key_); \\\n} while(0)\n\n#define dictCompareHashKeys(ht, key1, key2) \\\n    (((ht)->type->keyCompare) ? \\\n        (ht)->type->keyCompare((ht)->privdata, key1, key2) : \\\n        (key1) == (key2))\n\n#define dictHashKey(ht, key) (ht)->type->hashFunction(key)\n\n#define dictGetEntryKey(he) ((he)->key)\n#define dictGetEntryVal(he) ((he)->val)\n#define dictSlots(ht) ((ht)->size)\n#define dictSize(ht) ((ht)->used)\n\n/* API */\nstatic unsigned int dictGenHashFunction(const unsigned char *buf, int len);\nstatic dict *dictCreate(dictType *type, void *privDataPtr);\nstatic int dictExpand(dict *ht, unsigned long size);\nstatic int dictAdd(dict *ht, void *key, void *val);\nstatic int dictReplace(dict *ht, void *key, void *val);\nstatic int dictDelete(dict *ht, const void *key);\nstatic void dictRelease(dict *ht);\nstatic dictEntry * dictFind(dict *ht, const void *key);\nstatic dictIterator *dictGetIterator(dict *ht);\nstatic dictEntry *dictNext(dictIterator *iter);\nstatic void dictReleaseIterator(dictIterator *iter);\n\n#endif /* __DICT_H */\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.8/deps/hiredis/examples/example-ae.c",
    "content": "#include <stdio.h>\n#include <stdlib.h>\n#include <string.h>\n#include <signal.h>\n\n#include <hiredis.h>\n#include <async.h>\n#include <adapters/ae.h>\n\n/* Put event loop in the global scope, so it can be explicitly stopped */\nstatic aeEventLoop *loop;\n\nvoid getCallback(redisAsyncContext *c, void *r, void *privdata) {\n    redisReply *reply = r;\n    if (reply == NULL) return;\n    printf(\"argv[%s]: %s\\n\", (char*)privdata, reply->str);\n\n    /* Disconnect after receiving the reply to GET */\n    redisAsyncDisconnect(c);\n}\n\nvoid connectCallback(const redisAsyncContext *c, int status) {\n    if (status != REDIS_OK) {\n        printf(\"Error: %s\\n\", c->errstr);\n        aeStop(loop);\n        return;\n    }\n\n    printf(\"Connected...\\n\");\n}\n\nvoid disconnectCallback(const redisAsyncContext *c, int status) {\n    if (status != REDIS_OK) {\n        printf(\"Error: %s\\n\", c->errstr);\n        aeStop(loop);\n        return;\n    }\n\n    printf(\"Disconnected...\\n\");\n    aeStop(loop);\n}\n\nint main (int argc, char **argv) {\n    signal(SIGPIPE, SIG_IGN);\n\n    redisAsyncContext *c = redisAsyncConnect(\"127.0.0.1\", 6379);\n    if (c->err) {\n        /* Let *c leak for now... */\n        printf(\"Error: %s\\n\", c->errstr);\n        return 1;\n    }\n\n    loop = aeCreateEventLoop(64);\n    redisAeAttach(loop, c);\n    redisAsyncSetConnectCallback(c,connectCallback);\n    redisAsyncSetDisconnectCallback(c,disconnectCallback);\n    redisAsyncCommand(c, NULL, NULL, \"SET key %b\", argv[argc-1], strlen(argv[argc-1]));\n    redisAsyncCommand(c, getCallback, (char*)\"end-1\", \"GET key\");\n    aeMain(loop);\n    return 0;\n}\n\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.8/deps/hiredis/examples/example-libev.c",
    "content": "#include <stdio.h>\n#include <stdlib.h>\n#include <string.h>\n#include <signal.h>\n\n#include <hiredis.h>\n#include <async.h>\n#include <adapters/libev.h>\n\nvoid getCallback(redisAsyncContext *c, void *r, void *privdata) {\n    redisReply *reply = r;\n    if (reply == NULL) return;\n    printf(\"argv[%s]: %s\\n\", (char*)privdata, reply->str);\n\n    /* Disconnect after receiving the reply to GET */\n    redisAsyncDisconnect(c);\n}\n\nvoid connectCallback(const redisAsyncContext *c, int status) {\n    if (status != REDIS_OK) {\n        printf(\"Error: %s\\n\", c->errstr);\n        return;\n    }\n    printf(\"Connected...\\n\");\n}\n\nvoid disconnectCallback(const redisAsyncContext *c, int status) {\n    if (status != REDIS_OK) {\n        printf(\"Error: %s\\n\", c->errstr);\n        return;\n    }\n    printf(\"Disconnected...\\n\");\n}\n\nint main (int argc, char **argv) {\n    signal(SIGPIPE, SIG_IGN);\n\n    redisAsyncContext *c = redisAsyncConnect(\"127.0.0.1\", 6379);\n    if (c->err) {\n        /* Let *c leak for now... */\n        printf(\"Error: %s\\n\", c->errstr);\n        return 1;\n    }\n\n    redisLibevAttach(EV_DEFAULT_ c);\n    redisAsyncSetConnectCallback(c,connectCallback);\n    redisAsyncSetDisconnectCallback(c,disconnectCallback);\n    redisAsyncCommand(c, NULL, NULL, \"SET key %b\", argv[argc-1], strlen(argv[argc-1]));\n    redisAsyncCommand(c, getCallback, (char*)\"end-1\", \"GET key\");\n    ev_loop(EV_DEFAULT_ 0);\n    return 0;\n}\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.8/deps/hiredis/examples/example-libevent.c",
    "content": "#include <stdio.h>\n#include <stdlib.h>\n#include <string.h>\n#include <signal.h>\n\n#include <hiredis.h>\n#include <async.h>\n#include <adapters/libevent.h>\n\nvoid getCallback(redisAsyncContext *c, void *r, void *privdata) {\n    redisReply *reply = r;\n    if (reply == NULL) return;\n    printf(\"argv[%s]: %s\\n\", (char*)privdata, reply->str);\n\n    /* Disconnect after receiving the reply to GET */\n    redisAsyncDisconnect(c);\n}\n\nvoid connectCallback(const redisAsyncContext *c, int status) {\n    if (status != REDIS_OK) {\n        printf(\"Error: %s\\n\", c->errstr);\n        return;\n    }\n    printf(\"Connected...\\n\");\n}\n\nvoid disconnectCallback(const redisAsyncContext *c, int status) {\n    if (status != REDIS_OK) {\n        printf(\"Error: %s\\n\", c->errstr);\n        return;\n    }\n    printf(\"Disconnected...\\n\");\n}\n\nint main (int argc, char **argv) {\n    signal(SIGPIPE, SIG_IGN);\n    struct event_base *base = event_base_new();\n\n    redisAsyncContext *c = redisAsyncConnect(\"127.0.0.1\", 6379);\n    if (c->err) {\n        /* Let *c leak for now... */\n        printf(\"Error: %s\\n\", c->errstr);\n        return 1;\n    }\n\n    redisLibeventAttach(c,base);\n    redisAsyncSetConnectCallback(c,connectCallback);\n    redisAsyncSetDisconnectCallback(c,disconnectCallback);\n    redisAsyncCommand(c, NULL, NULL, \"SET key %b\", argv[argc-1], strlen(argv[argc-1]));\n    redisAsyncCommand(c, getCallback, (char*)\"end-1\", \"GET key\");\n    event_base_dispatch(base);\n    return 0;\n}\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.8/deps/hiredis/examples/example-libuv.c",
    "content": "#include <stdio.h>\n#include <stdlib.h>\n#include <string.h>\n#include <signal.h>\n\n#include <hiredis.h>\n#include <async.h>\n#include <adapters/libuv.h>\n\nvoid getCallback(redisAsyncContext *c, void *r, void *privdata) {\n    redisReply *reply = r;\n    if (reply == NULL) return;\n    printf(\"argv[%s]: %s\\n\", (char*)privdata, reply->str);\n\n    /* Disconnect after receiving the reply to GET */\n    redisAsyncDisconnect(c);\n}\n\nvoid connectCallback(const redisAsyncContext *c, int status) {\n    if (status != REDIS_OK) {\n        printf(\"Error: %s\\n\", c->errstr);\n        return;\n    }\n    printf(\"Connected...\\n\");\n}\n\nvoid disconnectCallback(const redisAsyncContext *c, int status) {\n    if (status != REDIS_OK) {\n        printf(\"Error: %s\\n\", c->errstr);\n        return;\n    }\n    printf(\"Disconnected...\\n\");\n}\n\nint main (int argc, char **argv) {\n    signal(SIGPIPE, SIG_IGN);\n    uv_loop_t* loop = uv_default_loop();\n\n    redisAsyncContext *c = redisAsyncConnect(\"127.0.0.1\", 6379);\n    if (c->err) {\n        /* Let *c leak for now... */\n        printf(\"Error: %s\\n\", c->errstr);\n        return 1;\n    }\n\n    redisLibuvAttach(c,loop);\n    redisAsyncSetConnectCallback(c,connectCallback);\n    redisAsyncSetDisconnectCallback(c,disconnectCallback);\n    redisAsyncCommand(c, NULL, NULL, \"SET key %b\", argv[argc-1], strlen(argv[argc-1]));\n    redisAsyncCommand(c, getCallback, (char*)\"end-1\", \"GET key\");\n    uv_run(loop, UV_RUN_DEFAULT);\n    return 0;\n}\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.8/deps/hiredis/examples/example.c",
    "content": "#include <stdio.h>\n#include <stdlib.h>\n#include <string.h>\n\n#include <hiredis.h>\n\nint main(int argc, char **argv) {\n    unsigned int j;\n    redisContext *c;\n    redisReply *reply;\n    const char *hostname = (argc > 1) ? argv[1] : \"127.0.0.1\";\n    int port = (argc > 2) ? atoi(argv[2]) : 6379;\n\n    struct timeval timeout = { 1, 500000 }; // 1.5 seconds\n    c = redisConnectWithTimeout(hostname, port, timeout);\n    if (c == NULL || c->err) {\n        if (c) {\n            printf(\"Connection error: %s\\n\", c->errstr);\n            redisFree(c);\n        } else {\n            printf(\"Connection error: can't allocate redis context\\n\");\n        }\n        exit(1);\n    }\n\n    /* PING server */\n    reply = redisCommand(c,\"PING\");\n    printf(\"PING: %s\\n\", reply->str);\n    freeReplyObject(reply);\n\n    /* Set a key */\n    reply = redisCommand(c,\"SET %s %s\", \"foo\", \"hello world\");\n    printf(\"SET: %s\\n\", reply->str);\n    freeReplyObject(reply);\n\n    /* Set a key using binary safe API */\n    reply = redisCommand(c,\"SET %b %b\", \"bar\", (size_t) 3, \"hello\", (size_t) 5);\n    printf(\"SET (binary API): %s\\n\", reply->str);\n    freeReplyObject(reply);\n\n    /* Try a GET and two INCR */\n    reply = redisCommand(c,\"GET foo\");\n    printf(\"GET foo: %s\\n\", reply->str);\n    freeReplyObject(reply);\n\n    reply = redisCommand(c,\"INCR counter\");\n    printf(\"INCR counter: %lld\\n\", reply->integer);\n    freeReplyObject(reply);\n    /* again ... */\n    reply = redisCommand(c,\"INCR counter\");\n    printf(\"INCR counter: %lld\\n\", reply->integer);\n    freeReplyObject(reply);\n\n    /* Create a list of numbers, from 0 to 9 */\n    reply = redisCommand(c,\"DEL mylist\");\n    freeReplyObject(reply);\n    for (j = 0; j < 10; j++) {\n        char buf[64];\n\n        snprintf(buf,64,\"%d\",j);\n        reply = redisCommand(c,\"LPUSH mylist element-%s\", buf);\n        freeReplyObject(reply);\n    }\n\n    /* Let's check what we have inside the list */\n    reply = redisCommand(c,\"LRANGE mylist 0 -1\");\n    if (reply->type == REDIS_REPLY_ARRAY) {\n        for (j = 0; j < reply->elements; j++) {\n            printf(\"%u) %s\\n\", j, reply->element[j]->str);\n        }\n    }\n    freeReplyObject(reply);\n\n    /* Disconnects and frees the context */\n    redisFree(c);\n\n    return 0;\n}\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.8/deps/hiredis/fmacros.h",
    "content": "#ifndef __HIREDIS_FMACRO_H\n#define __HIREDIS_FMACRO_H\n\n#if !defined(_BSD_SOURCE)\n#define _BSD_SOURCE\n#endif\n\n#if defined(_AIX)\n#define _ALL_SOURCE\n#endif\n\n#if defined(__sun__)\n#define _POSIX_C_SOURCE 200112L\n#elif defined(__linux__) || defined(__OpenBSD__) || defined(__NetBSD__)\n#define _XOPEN_SOURCE 600\n#else\n#define _XOPEN_SOURCE\n#endif\n\n#if __APPLE__ && __MACH__\n#define _OSX\n#endif\n\n#endif\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.8/deps/hiredis/hiredis.c",
    "content": "/*\n * Copyright (c) 2009-2011, Salvatore Sanfilippo <antirez at gmail dot com>\n * Copyright (c) 2010-2011, Pieter Noordhuis <pcnoordhuis at gmail dot com>\n *\n * All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions are met:\n *\n *   * Redistributions of source code must retain the above copyright notice,\n *     this list of conditions and the following disclaimer.\n *   * Redistributions in binary form must reproduce the above copyright\n *     notice, this list of conditions and the following disclaimer in the\n *     documentation and/or other materials provided with the distribution.\n *   * Neither the name of Redis nor the names of its contributors may be used\n *     to endorse or promote products derived from this software without\n *     specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\"\n * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\n * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE\n * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR\n * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF\n * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS\n * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN\n * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)\n * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE\n * POSSIBILITY OF SUCH DAMAGE.\n */\n\n#include \"fmacros.h\"\n#include <string.h>\n#include <stdlib.h>\n#include <unistd.h>\n#include <assert.h>\n#include <errno.h>\n#include <ctype.h>\n\n#include \"hiredis.h\"\n#include \"net.h\"\n#include \"sds.h\"\n\nstatic redisReply *createReplyObject(int type);\nstatic void *createStringObject(const redisReadTask *task, char *str, size_t len);\nstatic void *createArrayObject(const redisReadTask *task, int elements);\nstatic void *createIntegerObject(const redisReadTask *task, long long value);\nstatic void *createNilObject(const redisReadTask *task);\n\n/* Default set of functions to build the reply. Keep in mind that such a\n * function returning NULL is interpreted as OOM. */\nstatic redisReplyObjectFunctions defaultFunctions = {\n    createStringObject,\n    createArrayObject,\n    createIntegerObject,\n    createNilObject,\n    freeReplyObject\n};\n\n/* Create a reply object */\nstatic redisReply *createReplyObject(int type) {\n    redisReply *r = calloc(1,sizeof(*r));\n\n    if (r == NULL)\n        return NULL;\n\n    r->type = type;\n    return r;\n}\n\n/* Free a reply object */\nvoid freeReplyObject(void *reply) {\n    redisReply *r = reply;\n    size_t j;\n\n    switch(r->type) {\n    case REDIS_REPLY_INTEGER:\n        break; /* Nothing to free */\n    case REDIS_REPLY_ARRAY:\n        if (r->element != NULL) {\n            for (j = 0; j < r->elements; j++)\n                if (r->element[j] != NULL)\n                    freeReplyObject(r->element[j]);\n            free(r->element);\n        }\n        break;\n    case REDIS_REPLY_ERROR:\n    case REDIS_REPLY_STATUS:\n    case REDIS_REPLY_STRING:\n        if (r->str != NULL)\n            free(r->str);\n        break;\n    }\n    free(r);\n}\n\nstatic void *createStringObject(const redisReadTask *task, char *str, size_t len) {\n    redisReply *r, *parent;\n    char *buf;\n\n    r = createReplyObject(task->type);\n    if (r == NULL)\n        return NULL;\n\n    buf = malloc(len+1);\n    if (buf == NULL) {\n        freeReplyObject(r);\n        return NULL;\n    }\n\n    assert(task->type == REDIS_REPLY_ERROR  ||\n           task->type == REDIS_REPLY_STATUS ||\n           task->type == REDIS_REPLY_STRING);\n\n    /* Copy string value */\n    memcpy(buf,str,len);\n    buf[len] = '\\0';\n    r->str = buf;\n    r->len = len;\n\n    if (task->parent) {\n        parent = task->parent->obj;\n        assert(parent->type == REDIS_REPLY_ARRAY);\n        parent->element[task->idx] = r;\n    }\n    return r;\n}\n\nstatic void *createArrayObject(const redisReadTask *task, int elements) {\n    redisReply *r, *parent;\n\n    r = createReplyObject(REDIS_REPLY_ARRAY);\n    if (r == NULL)\n        return NULL;\n\n    if (elements > 0) {\n        r->element = calloc(elements,sizeof(redisReply*));\n        if (r->element == NULL) {\n            freeReplyObject(r);\n            return NULL;\n        }\n    }\n\n    r->elements = elements;\n\n    if (task->parent) {\n        parent = task->parent->obj;\n        assert(parent->type == REDIS_REPLY_ARRAY);\n        parent->element[task->idx] = r;\n    }\n    return r;\n}\n\nstatic void *createIntegerObject(const redisReadTask *task, long long value) {\n    redisReply *r, *parent;\n\n    r = createReplyObject(REDIS_REPLY_INTEGER);\n    if (r == NULL)\n        return NULL;\n\n    r->integer = value;\n\n    if (task->parent) {\n        parent = task->parent->obj;\n        assert(parent->type == REDIS_REPLY_ARRAY);\n        parent->element[task->idx] = r;\n    }\n    return r;\n}\n\nstatic void *createNilObject(const redisReadTask *task) {\n    redisReply *r, *parent;\n\n    r = createReplyObject(REDIS_REPLY_NIL);\n    if (r == NULL)\n        return NULL;\n\n    if (task->parent) {\n        parent = task->parent->obj;\n        assert(parent->type == REDIS_REPLY_ARRAY);\n        parent->element[task->idx] = r;\n    }\n    return r;\n}\n\nstatic void __redisReaderSetError(redisReader *r, int type, const char *str) {\n    size_t len;\n\n    if (r->reply != NULL && r->fn && r->fn->freeObject) {\n        r->fn->freeObject(r->reply);\n        r->reply = NULL;\n    }\n\n    /* Clear input buffer on errors. */\n    if (r->buf != NULL) {\n        sdsfree(r->buf);\n        r->buf = NULL;\n        r->pos = r->len = 0;\n    }\n\n    /* Reset task stack. */\n    r->ridx = -1;\n\n    /* Set error. */\n    r->err = type;\n    len = strlen(str);\n    len = len < (sizeof(r->errstr)-1) ? len : (sizeof(r->errstr)-1);\n    memcpy(r->errstr,str,len);\n    r->errstr[len] = '\\0';\n}\n\nstatic size_t chrtos(char *buf, size_t size, char byte) {\n    size_t len = 0;\n\n    switch(byte) {\n    case '\\\\':\n    case '\"':\n        len = snprintf(buf,size,\"\\\"\\\\%c\\\"\",byte);\n        break;\n    case '\\n': len = snprintf(buf,size,\"\\\"\\\\n\\\"\"); break;\n    case '\\r': len = snprintf(buf,size,\"\\\"\\\\r\\\"\"); break;\n    case '\\t': len = snprintf(buf,size,\"\\\"\\\\t\\\"\"); break;\n    case '\\a': len = snprintf(buf,size,\"\\\"\\\\a\\\"\"); break;\n    case '\\b': len = snprintf(buf,size,\"\\\"\\\\b\\\"\"); break;\n    default:\n        if (isprint(byte))\n            len = snprintf(buf,size,\"\\\"%c\\\"\",byte);\n        else\n            len = snprintf(buf,size,\"\\\"\\\\x%02x\\\"\",(unsigned char)byte);\n        break;\n    }\n\n    return len;\n}\n\nstatic void __redisReaderSetErrorProtocolByte(redisReader *r, char byte) {\n    char cbuf[8], sbuf[128];\n\n    chrtos(cbuf,sizeof(cbuf),byte);\n    snprintf(sbuf,sizeof(sbuf),\n        \"Protocol error, got %s as reply type byte\", cbuf);\n    __redisReaderSetError(r,REDIS_ERR_PROTOCOL,sbuf);\n}\n\nstatic void __redisReaderSetErrorOOM(redisReader *r) {\n    __redisReaderSetError(r,REDIS_ERR_OOM,\"Out of memory\");\n}\n\nstatic char *readBytes(redisReader *r, unsigned int bytes) {\n    char *p;\n    if (r->len-r->pos >= bytes) {\n        p = r->buf+r->pos;\n        r->pos += bytes;\n        return p;\n    }\n    return NULL;\n}\n\n/* Find pointer to \\r\\n. */\nstatic char *seekNewline(char *s, size_t len) {\n    int pos = 0;\n    int _len = len-1;\n\n    /* Position should be < len-1 because the character at \"pos\" should be\n     * followed by a \\n. Note that strchr cannot be used because it doesn't\n     * allow to search a limited length and the buffer that is being searched\n     * might not have a trailing NULL character. */\n    while (pos < _len) {\n        while(pos < _len && s[pos] != '\\r') pos++;\n        if (s[pos] != '\\r') {\n            /* Not found. */\n            return NULL;\n        } else {\n            if (s[pos+1] == '\\n') {\n                /* Found. */\n                return s+pos;\n            } else {\n                /* Continue searching. */\n                pos++;\n            }\n        }\n    }\n    return NULL;\n}\n\n/* Read a long long value starting at *s, under the assumption that it will be\n * terminated by \\r\\n. Ambiguously returns -1 for unexpected input. */\nstatic long long readLongLong(char *s) {\n    long long v = 0;\n    int dec, mult = 1;\n    char c;\n\n    if (*s == '-') {\n        mult = -1;\n        s++;\n    } else if (*s == '+') {\n        mult = 1;\n        s++;\n    }\n\n    while ((c = *(s++)) != '\\r') {\n        dec = c - '0';\n        if (dec >= 0 && dec < 10) {\n            v *= 10;\n            v += dec;\n        } else {\n            /* Should not happen... */\n            return -1;\n        }\n    }\n\n    return mult*v;\n}\n\nstatic char *readLine(redisReader *r, int *_len) {\n    char *p, *s;\n    int len;\n\n    p = r->buf+r->pos;\n    s = seekNewline(p,(r->len-r->pos));\n    if (s != NULL) {\n        len = s-(r->buf+r->pos);\n        r->pos += len+2; /* skip \\r\\n */\n        if (_len) *_len = len;\n        return p;\n    }\n    return NULL;\n}\n\nstatic void moveToNextTask(redisReader *r) {\n    redisReadTask *cur, *prv;\n    while (r->ridx >= 0) {\n        /* Return a.s.a.p. when the stack is now empty. */\n        if (r->ridx == 0) {\n            r->ridx--;\n            return;\n        }\n\n        cur = &(r->rstack[r->ridx]);\n        prv = &(r->rstack[r->ridx-1]);\n        assert(prv->type == REDIS_REPLY_ARRAY);\n        if (cur->idx == prv->elements-1) {\n            r->ridx--;\n        } else {\n            /* Reset the type because the next item can be anything */\n            assert(cur->idx < prv->elements);\n            cur->type = -1;\n            cur->elements = -1;\n            cur->idx++;\n            return;\n        }\n    }\n}\n\nstatic int processLineItem(redisReader *r) {\n    redisReadTask *cur = &(r->rstack[r->ridx]);\n    void *obj;\n    char *p;\n    int len;\n\n    if ((p = readLine(r,&len)) != NULL) {\n        if (cur->type == REDIS_REPLY_INTEGER) {\n            if (r->fn && r->fn->createInteger)\n                obj = r->fn->createInteger(cur,readLongLong(p));\n            else\n                obj = (void*)REDIS_REPLY_INTEGER;\n        } else {\n            /* Type will be error or status. */\n            if (r->fn && r->fn->createString)\n                obj = r->fn->createString(cur,p,len);\n            else\n                obj = (void*)(size_t)(cur->type);\n        }\n\n        if (obj == NULL) {\n            __redisReaderSetErrorOOM(r);\n            return REDIS_ERR;\n        }\n\n        /* Set reply if this is the root object. */\n        if (r->ridx == 0) r->reply = obj;\n        moveToNextTask(r);\n        return REDIS_OK;\n    }\n\n    return REDIS_ERR;\n}\n\nstatic int processBulkItem(redisReader *r) {\n    redisReadTask *cur = &(r->rstack[r->ridx]);\n    void *obj = NULL;\n    char *p, *s;\n    long len;\n    unsigned long bytelen;\n    int success = 0;\n\n    p = r->buf+r->pos;\n    s = seekNewline(p,r->len-r->pos);\n    if (s != NULL) {\n        p = r->buf+r->pos;\n        bytelen = s-(r->buf+r->pos)+2; /* include \\r\\n */\n        len = readLongLong(p);\n\n        if (len < 0) {\n            /* The nil object can always be created. */\n            if (r->fn && r->fn->createNil)\n                obj = r->fn->createNil(cur);\n            else\n                obj = (void*)REDIS_REPLY_NIL;\n            success = 1;\n        } else {\n            /* Only continue when the buffer contains the entire bulk item. */\n            bytelen += len+2; /* include \\r\\n */\n            if (r->pos+bytelen <= r->len) {\n                if (r->fn && r->fn->createString)\n                    obj = r->fn->createString(cur,s+2,len);\n                else\n                    obj = (void*)REDIS_REPLY_STRING;\n                success = 1;\n            }\n        }\n\n        /* Proceed when obj was created. */\n        if (success) {\n            if (obj == NULL) {\n                __redisReaderSetErrorOOM(r);\n                return REDIS_ERR;\n            }\n\n            r->pos += bytelen;\n\n            /* Set reply if this is the root object. */\n            if (r->ridx == 0) r->reply = obj;\n            moveToNextTask(r);\n            return REDIS_OK;\n        }\n    }\n\n    return REDIS_ERR;\n}\n\nstatic int processMultiBulkItem(redisReader *r) {\n    redisReadTask *cur = &(r->rstack[r->ridx]);\n    void *obj;\n    char *p;\n    long elements;\n    int root = 0;\n\n    /* Set error for nested multi bulks with depth > 7 */\n    if (r->ridx == 8) {\n        __redisReaderSetError(r,REDIS_ERR_PROTOCOL,\n            \"No support for nested multi bulk replies with depth > 7\");\n        return REDIS_ERR;\n    }\n\n    if ((p = readLine(r,NULL)) != NULL) {\n        elements = readLongLong(p);\n        root = (r->ridx == 0);\n\n        if (elements == -1) {\n            if (r->fn && r->fn->createNil)\n                obj = r->fn->createNil(cur);\n            else\n                obj = (void*)REDIS_REPLY_NIL;\n\n            if (obj == NULL) {\n                __redisReaderSetErrorOOM(r);\n                return REDIS_ERR;\n            }\n\n            moveToNextTask(r);\n        } else {\n            if (r->fn && r->fn->createArray)\n                obj = r->fn->createArray(cur,elements);\n            else\n                obj = (void*)REDIS_REPLY_ARRAY;\n\n            if (obj == NULL) {\n                __redisReaderSetErrorOOM(r);\n                return REDIS_ERR;\n            }\n\n            /* Modify task stack when there are more than 0 elements. */\n            if (elements > 0) {\n                cur->elements = elements;\n                cur->obj = obj;\n                r->ridx++;\n                r->rstack[r->ridx].type = -1;\n                r->rstack[r->ridx].elements = -1;\n                r->rstack[r->ridx].idx = 0;\n                r->rstack[r->ridx].obj = NULL;\n                r->rstack[r->ridx].parent = cur;\n                r->rstack[r->ridx].privdata = r->privdata;\n            } else {\n                moveToNextTask(r);\n            }\n        }\n\n        /* Set reply if this is the root object. */\n        if (root) r->reply = obj;\n        return REDIS_OK;\n    }\n\n    return REDIS_ERR;\n}\n\nstatic int processItem(redisReader *r) {\n    redisReadTask *cur = &(r->rstack[r->ridx]);\n    char *p;\n\n    /* check if we need to read type */\n    if (cur->type < 0) {\n        if ((p = readBytes(r,1)) != NULL) {\n            switch (p[0]) {\n            case '-':\n                cur->type = REDIS_REPLY_ERROR;\n                break;\n            case '+':\n                cur->type = REDIS_REPLY_STATUS;\n                break;\n            case ':':\n                cur->type = REDIS_REPLY_INTEGER;\n                break;\n            case '$':\n                cur->type = REDIS_REPLY_STRING;\n                break;\n            case '*':\n                cur->type = REDIS_REPLY_ARRAY;\n                break;\n            default:\n                __redisReaderSetErrorProtocolByte(r,*p);\n                return REDIS_ERR;\n            }\n        } else {\n            /* could not consume 1 byte */\n            return REDIS_ERR;\n        }\n    }\n\n    /* process typed item */\n    switch(cur->type) {\n    case REDIS_REPLY_ERROR:\n    case REDIS_REPLY_STATUS:\n    case REDIS_REPLY_INTEGER:\n        return processLineItem(r);\n    case REDIS_REPLY_STRING:\n        return processBulkItem(r);\n    case REDIS_REPLY_ARRAY:\n        return processMultiBulkItem(r);\n    default:\n        assert(NULL);\n        return REDIS_ERR; /* Avoid warning. */\n    }\n}\n\nredisReader *redisReaderCreate(void) {\n    redisReader *r;\n\n    r = calloc(sizeof(redisReader),1);\n    if (r == NULL)\n        return NULL;\n\n    r->err = 0;\n    r->errstr[0] = '\\0';\n    r->fn = &defaultFunctions;\n    r->buf = sdsempty();\n    r->maxbuf = REDIS_READER_MAX_BUF;\n    if (r->buf == NULL) {\n        free(r);\n        return NULL;\n    }\n\n    r->ridx = -1;\n    return r;\n}\n\nvoid redisReaderFree(redisReader *r) {\n    if (r->reply != NULL && r->fn && r->fn->freeObject)\n        r->fn->freeObject(r->reply);\n    if (r->buf != NULL)\n        sdsfree(r->buf);\n    free(r);\n}\n\nint redisReaderFeed(redisReader *r, const char *buf, size_t len) {\n    sds newbuf;\n\n    /* Return early when this reader is in an erroneous state. */\n    if (r->err)\n        return REDIS_ERR;\n\n    /* Copy the provided buffer. */\n    if (buf != NULL && len >= 1) {\n        /* Destroy internal buffer when it is empty and is quite large. */\n        if (r->len == 0 && r->maxbuf != 0 && sdsavail(r->buf) > r->maxbuf) {\n            sdsfree(r->buf);\n            r->buf = sdsempty();\n            r->pos = 0;\n\n            /* r->buf should not be NULL since we just free'd a larger one. */\n            assert(r->buf != NULL);\n        }\n\n        newbuf = sdscatlen(r->buf,buf,len);\n        if (newbuf == NULL) {\n            __redisReaderSetErrorOOM(r);\n            return REDIS_ERR;\n        }\n\n        r->buf = newbuf;\n        r->len = sdslen(r->buf);\n    }\n\n    return REDIS_OK;\n}\n\nint redisReaderGetReply(redisReader *r, void **reply) {\n    /* Default target pointer to NULL. */\n    if (reply != NULL)\n        *reply = NULL;\n\n    /* Return early when this reader is in an erroneous state. */\n    if (r->err)\n        return REDIS_ERR;\n\n    /* When the buffer is empty, there will never be a reply. */\n    if (r->len == 0)\n        return REDIS_OK;\n\n    /* Set first item to process when the stack is empty. */\n    if (r->ridx == -1) {\n        r->rstack[0].type = -1;\n        r->rstack[0].elements = -1;\n        r->rstack[0].idx = -1;\n        r->rstack[0].obj = NULL;\n        r->rstack[0].parent = NULL;\n        r->rstack[0].privdata = r->privdata;\n        r->ridx = 0;\n    }\n\n    /* Process items in reply. */\n    while (r->ridx >= 0)\n        if (processItem(r) != REDIS_OK)\n            break;\n\n    /* Return ASAP when an error occurred. */\n    if (r->err)\n        return REDIS_ERR;\n\n    /* Discard part of the buffer when we've consumed at least 1k, to avoid\n     * doing unnecessary calls to memmove() in sds.c. */\n    if (r->pos >= 1024) {\n        sdsrange(r->buf,r->pos,-1);\n        r->pos = 0;\n        r->len = sdslen(r->buf);\n    }\n\n    /* Emit a reply when there is one. */\n    if (r->ridx == -1) {\n        if (reply != NULL)\n            *reply = r->reply;\n        r->reply = NULL;\n    }\n    return REDIS_OK;\n}\n\n/* Calculate the number of bytes needed to represent an integer as string. */\nstatic int intlen(int i) {\n    int len = 0;\n    if (i < 0) {\n        len++;\n        i = -i;\n    }\n    do {\n        len++;\n        i /= 10;\n    } while(i);\n    return len;\n}\n\n/* Helper that calculates the bulk length given a certain string length. */\nstatic size_t bulklen(size_t len) {\n    return 1+intlen(len)+2+len+2;\n}\n\nint redisvFormatCommand(char **target, const char *format, va_list ap) {\n    const char *c = format;\n    char *cmd = NULL; /* final command */\n    int pos; /* position in final command */\n    sds curarg, newarg; /* current argument */\n    int touched = 0; /* was the current argument touched? */\n    char **curargv = NULL, **newargv = NULL;\n    int argc = 0;\n    int totlen = 0;\n    int j;\n\n    /* Abort if there is not target to set */\n    if (target == NULL)\n        return -1;\n\n    /* Build the command string accordingly to protocol */\n    curarg = sdsempty();\n    if (curarg == NULL)\n        return -1;\n\n    while(*c != '\\0') {\n        if (*c != '%' || c[1] == '\\0') {\n            if (*c == ' ') {\n                if (touched) {\n                    newargv = realloc(curargv,sizeof(char*)*(argc+1));\n                    if (newargv == NULL) goto err;\n                    curargv = newargv;\n                    curargv[argc++] = curarg;\n                    totlen += bulklen(sdslen(curarg));\n\n                    /* curarg is put in argv so it can be overwritten. */\n                    curarg = sdsempty();\n                    if (curarg == NULL) goto err;\n                    touched = 0;\n                }\n            } else {\n                newarg = sdscatlen(curarg,c,1);\n                if (newarg == NULL) goto err;\n                curarg = newarg;\n                touched = 1;\n            }\n        } else {\n            char *arg;\n            size_t size;\n\n            /* Set newarg so it can be checked even if it is not touched. */\n            newarg = curarg;\n\n            switch(c[1]) {\n            case 's':\n                arg = va_arg(ap,char*);\n                size = strlen(arg);\n                if (size > 0)\n                    newarg = sdscatlen(curarg,arg,size);\n                break;\n            case 'b':\n                arg = va_arg(ap,char*);\n                size = va_arg(ap,size_t);\n                if (size > 0)\n                    newarg = sdscatlen(curarg,arg,size);\n                break;\n            case '%':\n                newarg = sdscat(curarg,\"%\");\n                break;\n            default:\n                /* Try to detect printf format */\n                {\n                    static const char intfmts[] = \"diouxX\";\n                    char _format[16];\n                    const char *_p = c+1;\n                    size_t _l = 0;\n                    va_list _cpy;\n\n                    /* Flags */\n                    if (*_p != '\\0' && *_p == '#') _p++;\n                    if (*_p != '\\0' && *_p == '0') _p++;\n                    if (*_p != '\\0' && *_p == '-') _p++;\n                    if (*_p != '\\0' && *_p == ' ') _p++;\n                    if (*_p != '\\0' && *_p == '+') _p++;\n\n                    /* Field width */\n                    while (*_p != '\\0' && isdigit(*_p)) _p++;\n\n                    /* Precision */\n                    if (*_p == '.') {\n                        _p++;\n                        while (*_p != '\\0' && isdigit(*_p)) _p++;\n                    }\n\n                    /* Copy va_list before consuming with va_arg */\n                    va_copy(_cpy,ap);\n\n                    /* Integer conversion (without modifiers) */\n                    if (strchr(intfmts,*_p) != NULL) {\n                        va_arg(ap,int);\n                        goto fmt_valid;\n                    }\n\n                    /* Double conversion (without modifiers) */\n                    if (strchr(\"eEfFgGaA\",*_p) != NULL) {\n                        va_arg(ap,double);\n                        goto fmt_valid;\n                    }\n\n                    /* Size: char */\n                    if (_p[0] == 'h' && _p[1] == 'h') {\n                        _p += 2;\n                        if (*_p != '\\0' && strchr(intfmts,*_p) != NULL) {\n                            va_arg(ap,int); /* char gets promoted to int */\n                            goto fmt_valid;\n                        }\n                        goto fmt_invalid;\n                    }\n\n                    /* Size: short */\n                    if (_p[0] == 'h') {\n                        _p += 1;\n                        if (*_p != '\\0' && strchr(intfmts,*_p) != NULL) {\n                            va_arg(ap,int); /* short gets promoted to int */\n                            goto fmt_valid;\n                        }\n                        goto fmt_invalid;\n                    }\n\n                    /* Size: long long */\n                    if (_p[0] == 'l' && _p[1] == 'l') {\n                        _p += 2;\n                        if (*_p != '\\0' && strchr(intfmts,*_p) != NULL) {\n                            va_arg(ap,long long);\n                            goto fmt_valid;\n                        }\n                        goto fmt_invalid;\n                    }\n\n                    /* Size: long */\n                    if (_p[0] == 'l') {\n                        _p += 1;\n                        if (*_p != '\\0' && strchr(intfmts,*_p) != NULL) {\n                            va_arg(ap,long);\n                            goto fmt_valid;\n                        }\n                        goto fmt_invalid;\n                    }\n\n                fmt_invalid:\n                    va_end(_cpy);\n                    goto err;\n\n                fmt_valid:\n                    _l = (_p+1)-c;\n                    if (_l < sizeof(_format)-2) {\n                        memcpy(_format,c,_l);\n                        _format[_l] = '\\0';\n                        newarg = sdscatvprintf(curarg,_format,_cpy);\n\n                        /* Update current position (note: outer blocks\n                         * increment c twice so compensate here) */\n                        c = _p-1;\n                    }\n\n                    va_end(_cpy);\n                    break;\n                }\n            }\n\n            if (newarg == NULL) goto err;\n            curarg = newarg;\n\n            touched = 1;\n            c++;\n        }\n        c++;\n    }\n\n    /* Add the last argument if needed */\n    if (touched) {\n        newargv = realloc(curargv,sizeof(char*)*(argc+1));\n        if (newargv == NULL) goto err;\n        curargv = newargv;\n        curargv[argc++] = curarg;\n        totlen += bulklen(sdslen(curarg));\n    } else {\n        sdsfree(curarg);\n    }\n\n    /* Clear curarg because it was put in curargv or was free'd. */\n    curarg = NULL;\n\n    /* Add bytes needed to hold multi bulk count */\n    totlen += 1+intlen(argc)+2;\n\n    /* Build the command at protocol level */\n    cmd = malloc(totlen+1);\n    if (cmd == NULL) goto err;\n\n    pos = sprintf(cmd,\"*%d\\r\\n\",argc);\n    for (j = 0; j < argc; j++) {\n        pos += sprintf(cmd+pos,\"$%zu\\r\\n\",sdslen(curargv[j]));\n        memcpy(cmd+pos,curargv[j],sdslen(curargv[j]));\n        pos += sdslen(curargv[j]);\n        sdsfree(curargv[j]);\n        cmd[pos++] = '\\r';\n        cmd[pos++] = '\\n';\n    }\n    assert(pos == totlen);\n    cmd[pos] = '\\0';\n\n    free(curargv);\n    *target = cmd;\n    return totlen;\n\nerr:\n    while(argc--)\n        sdsfree(curargv[argc]);\n    free(curargv);\n\n    if (curarg != NULL)\n        sdsfree(curarg);\n\n    /* No need to check cmd since it is the last statement that can fail,\n     * but do it anyway to be as defensive as possible. */\n    if (cmd != NULL)\n        free(cmd);\n\n    return -1;\n}\n\n/* Format a command according to the Redis protocol. This function\n * takes a format similar to printf:\n *\n * %s represents a C null terminated string you want to interpolate\n * %b represents a binary safe string\n *\n * When using %b you need to provide both the pointer to the string\n * and the length in bytes as a size_t. Examples:\n *\n * len = redisFormatCommand(target, \"GET %s\", mykey);\n * len = redisFormatCommand(target, \"SET %s %b\", mykey, myval, myvallen);\n */\nint redisFormatCommand(char **target, const char *format, ...) {\n    va_list ap;\n    int len;\n    va_start(ap,format);\n    len = redisvFormatCommand(target,format,ap);\n    va_end(ap);\n    return len;\n}\n\n/* Format a command according to the Redis protocol. This function takes the\n * number of arguments, an array with arguments and an array with their\n * lengths. If the latter is set to NULL, strlen will be used to compute the\n * argument lengths.\n */\nint redisFormatCommandArgv(char **target, int argc, const char **argv, const size_t *argvlen) {\n    char *cmd = NULL; /* final command */\n    int pos; /* position in final command */\n    size_t len;\n    int totlen, j;\n\n    /* Calculate number of bytes needed for the command */\n    totlen = 1+intlen(argc)+2;\n    for (j = 0; j < argc; j++) {\n        len = argvlen ? argvlen[j] : strlen(argv[j]);\n        totlen += bulklen(len);\n    }\n\n    /* Build the command at protocol level */\n    cmd = malloc(totlen+1);\n    if (cmd == NULL)\n        return -1;\n\n    pos = sprintf(cmd,\"*%d\\r\\n\",argc);\n    for (j = 0; j < argc; j++) {\n        len = argvlen ? argvlen[j] : strlen(argv[j]);\n        pos += sprintf(cmd+pos,\"$%zu\\r\\n\",len);\n        memcpy(cmd+pos,argv[j],len);\n        pos += len;\n        cmd[pos++] = '\\r';\n        cmd[pos++] = '\\n';\n    }\n    assert(pos == totlen);\n    cmd[pos] = '\\0';\n\n    *target = cmd;\n    return totlen;\n}\n\nvoid __redisSetError(redisContext *c, int type, const char *str) {\n    size_t len;\n\n    c->err = type;\n    if (str != NULL) {\n        len = strlen(str);\n        len = len < (sizeof(c->errstr)-1) ? len : (sizeof(c->errstr)-1);\n        memcpy(c->errstr,str,len);\n        c->errstr[len] = '\\0';\n    } else {\n        /* Only REDIS_ERR_IO may lack a description! */\n        assert(type == REDIS_ERR_IO);\n        strerror_r(errno,c->errstr,sizeof(c->errstr));\n    }\n}\n\nstatic redisContext *redisContextInit(void) {\n    redisContext *c;\n\n    c = calloc(1,sizeof(redisContext));\n    if (c == NULL)\n        return NULL;\n\n    c->err = 0;\n    c->errstr[0] = '\\0';\n    c->obuf = sdsempty();\n    c->reader = redisReaderCreate();\n    return c;\n}\n\nvoid redisFree(redisContext *c) {\n    if (c->fd > 0)\n        close(c->fd);\n    if (c->obuf != NULL)\n        sdsfree(c->obuf);\n    if (c->reader != NULL)\n        redisReaderFree(c->reader);\n    free(c);\n}\n\nint redisFreeKeepFd(redisContext *c) {\n\tint fd = c->fd;\n\tc->fd = -1;\n\tredisFree(c);\n\treturn fd;\n}\n\n/* Connect to a Redis instance. On error the field error in the returned\n * context will be set to the return value of the error function.\n * When no set of reply functions is given, the default set will be used. */\nredisContext *redisConnect(const char *ip, int port) {\n    redisContext *c;\n\n    c = redisContextInit();\n    if (c == NULL)\n        return NULL;\n\n    c->flags |= REDIS_BLOCK;\n    redisContextConnectTcp(c,ip,port,NULL);\n    return c;\n}\n\nredisContext *redisConnectWithTimeout(const char *ip, int port, const struct timeval tv) {\n    redisContext *c;\n\n    c = redisContextInit();\n    if (c == NULL)\n        return NULL;\n\n    c->flags |= REDIS_BLOCK;\n    redisContextConnectTcp(c,ip,port,&tv);\n    return c;\n}\n\nredisContext *redisConnectNonBlock(const char *ip, int port) {\n    redisContext *c;\n\n    c = redisContextInit();\n    if (c == NULL)\n        return NULL;\n\n    c->flags &= ~REDIS_BLOCK;\n    redisContextConnectTcp(c,ip,port,NULL);\n    return c;\n}\n\nredisContext *redisConnectBindNonBlock(const char *ip, int port,\n                                       const char *source_addr) {\n    redisContext *c = redisContextInit();\n    c->flags &= ~REDIS_BLOCK;\n    redisContextConnectBindTcp(c,ip,port,NULL,source_addr);\n    return c;\n}\n\nredisContext *redisConnectUnix(const char *path) {\n    redisContext *c;\n\n    c = redisContextInit();\n    if (c == NULL)\n        return NULL;\n\n    c->flags |= REDIS_BLOCK;\n    redisContextConnectUnix(c,path,NULL);\n    return c;\n}\n\nredisContext *redisConnectUnixWithTimeout(const char *path, const struct timeval tv) {\n    redisContext *c;\n\n    c = redisContextInit();\n    if (c == NULL)\n        return NULL;\n\n    c->flags |= REDIS_BLOCK;\n    redisContextConnectUnix(c,path,&tv);\n    return c;\n}\n\nredisContext *redisConnectUnixNonBlock(const char *path) {\n    redisContext *c;\n\n    c = redisContextInit();\n    if (c == NULL)\n        return NULL;\n\n    c->flags &= ~REDIS_BLOCK;\n    redisContextConnectUnix(c,path,NULL);\n    return c;\n}\n\nredisContext *redisConnectFd(int fd) {\n    redisContext *c;\n\n    c = redisContextInit();\n    if (c == NULL)\n        return NULL;\n\n    c->fd = fd;\n    c->flags |= REDIS_BLOCK | REDIS_CONNECTED;\n    return c;\n}\n\n/* Set read/write timeout on a blocking socket. */\nint redisSetTimeout(redisContext *c, const struct timeval tv) {\n    if (c->flags & REDIS_BLOCK)\n        return redisContextSetTimeout(c,tv);\n    return REDIS_ERR;\n}\n\n/* Enable connection KeepAlive. */\nint redisEnableKeepAlive(redisContext *c) {\n    if (redisKeepAlive(c, REDIS_KEEPALIVE_INTERVAL) != REDIS_OK)\n        return REDIS_ERR;\n    return REDIS_OK;\n}\n\n/* Use this function to handle a read event on the descriptor. It will try\n * and read some bytes from the socket and feed them to the reply parser.\n *\n * After this function is called, you may use redisContextReadReply to\n * see if there is a reply available. */\nint redisBufferRead(redisContext *c) {\n    char buf[1024*16];\n    int nread;\n\n    /* Return early when the context has seen an error. */\n    if (c->err)\n        return REDIS_ERR;\n\n    nread = read(c->fd,buf,sizeof(buf));\n    if (nread == -1) {\n        if ((errno == EAGAIN && !(c->flags & REDIS_BLOCK)) || (errno == EINTR)) {\n            /* Try again later */\n        } else {\n            __redisSetError(c,REDIS_ERR_IO,NULL);\n            return REDIS_ERR;\n        }\n    } else if (nread == 0) {\n        __redisSetError(c,REDIS_ERR_EOF,\"Server closed the connection\");\n        return REDIS_ERR;\n    } else {\n        if (redisReaderFeed(c->reader,buf,nread) != REDIS_OK) {\n            __redisSetError(c,c->reader->err,c->reader->errstr);\n            return REDIS_ERR;\n        }\n    }\n    return REDIS_OK;\n}\n\n/* Write the output buffer to the socket.\n *\n * Returns REDIS_OK when the buffer is empty, or (a part of) the buffer was\n * succesfully written to the socket. When the buffer is empty after the\n * write operation, \"done\" is set to 1 (if given).\n *\n * Returns REDIS_ERR if an error occured trying to write and sets\n * c->errstr to hold the appropriate error string.\n */\nint redisBufferWrite(redisContext *c, int *done) {\n    int nwritten;\n\n    /* Return early when the context has seen an error. */\n    if (c->err)\n        return REDIS_ERR;\n\n    if (sdslen(c->obuf) > 0) {\n        nwritten = write(c->fd,c->obuf,sdslen(c->obuf));\n        if (nwritten == -1) {\n            if ((errno == EAGAIN && !(c->flags & REDIS_BLOCK)) || (errno == EINTR)) {\n                /* Try again later */\n            } else {\n                __redisSetError(c,REDIS_ERR_IO,NULL);\n                return REDIS_ERR;\n            }\n        } else if (nwritten > 0) {\n            if (nwritten == (signed)sdslen(c->obuf)) {\n                sdsfree(c->obuf);\n                c->obuf = sdsempty();\n            } else {\n                sdsrange(c->obuf,nwritten,-1);\n            }\n        }\n    }\n    if (done != NULL) *done = (sdslen(c->obuf) == 0);\n    return REDIS_OK;\n}\n\n/* Internal helper function to try and get a reply from the reader,\n * or set an error in the context otherwise. */\nint redisGetReplyFromReader(redisContext *c, void **reply) {\n    if (redisReaderGetReply(c->reader,reply) == REDIS_ERR) {\n        __redisSetError(c,c->reader->err,c->reader->errstr);\n        return REDIS_ERR;\n    }\n    return REDIS_OK;\n}\n\nint redisGetReply(redisContext *c, void **reply) {\n    int wdone = 0;\n    void *aux = NULL;\n\n    /* Try to read pending replies */\n    if (redisGetReplyFromReader(c,&aux) == REDIS_ERR)\n        return REDIS_ERR;\n\n    /* For the blocking context, flush output buffer and read reply */\n    if (aux == NULL && c->flags & REDIS_BLOCK) {\n        /* Write until done */\n        do {\n            if (redisBufferWrite(c,&wdone) == REDIS_ERR)\n                return REDIS_ERR;\n        } while (!wdone);\n\n        /* Read until there is a reply */\n        do {\n            if (redisBufferRead(c) == REDIS_ERR)\n                return REDIS_ERR;\n            if (redisGetReplyFromReader(c,&aux) == REDIS_ERR)\n                return REDIS_ERR;\n        } while (aux == NULL);\n    }\n\n    /* Set reply object */\n    if (reply != NULL) *reply = aux;\n    return REDIS_OK;\n}\n\n\n/* Helper function for the redisAppendCommand* family of functions.\n *\n * Write a formatted command to the output buffer. When this family\n * is used, you need to call redisGetReply yourself to retrieve\n * the reply (or replies in pub/sub).\n */\nint __redisAppendCommand(redisContext *c, const char *cmd, size_t len) {\n    sds newbuf;\n\n    newbuf = sdscatlen(c->obuf,cmd,len);\n    if (newbuf == NULL) {\n        __redisSetError(c,REDIS_ERR_OOM,\"Out of memory\");\n        return REDIS_ERR;\n    }\n\n    c->obuf = newbuf;\n    return REDIS_OK;\n}\n\nint redisAppendFormattedCommand(redisContext *c, const char *cmd, size_t len) {\n\n    if (__redisAppendCommand(c, cmd, len) != REDIS_OK) {\n        return REDIS_ERR;\n    }\n\n    return REDIS_OK;\n}\n\nint redisvAppendCommand(redisContext *c, const char *format, va_list ap) {\n    char *cmd;\n    int len;\n\n    len = redisvFormatCommand(&cmd,format,ap);\n    if (len == -1) {\n        __redisSetError(c,REDIS_ERR_OOM,\"Out of memory\");\n        return REDIS_ERR;\n    }\n\n    if (__redisAppendCommand(c,cmd,len) != REDIS_OK) {\n        free(cmd);\n        return REDIS_ERR;\n    }\n\n    free(cmd);\n    return REDIS_OK;\n}\n\nint redisAppendCommand(redisContext *c, const char *format, ...) {\n    va_list ap;\n    int ret;\n\n    va_start(ap,format);\n    ret = redisvAppendCommand(c,format,ap);\n    va_end(ap);\n    return ret;\n}\n\nint redisAppendCommandArgv(redisContext *c, int argc, const char **argv, const size_t *argvlen) {\n    char *cmd;\n    int len;\n\n    len = redisFormatCommandArgv(&cmd,argc,argv,argvlen);\n    if (len == -1) {\n        __redisSetError(c,REDIS_ERR_OOM,\"Out of memory\");\n        return REDIS_ERR;\n    }\n\n    if (__redisAppendCommand(c,cmd,len) != REDIS_OK) {\n        free(cmd);\n        return REDIS_ERR;\n    }\n\n    free(cmd);\n    return REDIS_OK;\n}\n\n/* Helper function for the redisCommand* family of functions.\n *\n * Write a formatted command to the output buffer. If the given context is\n * blocking, immediately read the reply into the \"reply\" pointer. When the\n * context is non-blocking, the \"reply\" pointer will not be used and the\n * command is simply appended to the write buffer.\n *\n * Returns the reply when a reply was succesfully retrieved. Returns NULL\n * otherwise. When NULL is returned in a blocking context, the error field\n * in the context will be set.\n */\nstatic void *__redisBlockForReply(redisContext *c) {\n    void *reply;\n\n    if (c->flags & REDIS_BLOCK) {\n        if (redisGetReply(c,&reply) != REDIS_OK)\n            return NULL;\n        return reply;\n    }\n    return NULL;\n}\n\nvoid *redisvCommand(redisContext *c, const char *format, va_list ap) {\n    if (redisvAppendCommand(c,format,ap) != REDIS_OK)\n        return NULL;\n    return __redisBlockForReply(c);\n}\n\nvoid *redisCommand(redisContext *c, const char *format, ...) {\n    va_list ap;\n    void *reply = NULL;\n    va_start(ap,format);\n    reply = redisvCommand(c,format,ap);\n    va_end(ap);\n    return reply;\n}\n\nvoid *redisCommandArgv(redisContext *c, int argc, const char **argv, const size_t *argvlen) {\n    if (redisAppendCommandArgv(c,argc,argv,argvlen) != REDIS_OK)\n        return NULL;\n    return __redisBlockForReply(c);\n}\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.8/deps/hiredis/hiredis.h",
    "content": "/*\n * Copyright (c) 2009-2011, Salvatore Sanfilippo <antirez at gmail dot com>\n * Copyright (c) 2010-2011, Pieter Noordhuis <pcnoordhuis at gmail dot com>\n *\n * All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions are met:\n *\n *   * Redistributions of source code must retain the above copyright notice,\n *     this list of conditions and the following disclaimer.\n *   * Redistributions in binary form must reproduce the above copyright\n *     notice, this list of conditions and the following disclaimer in the\n *     documentation and/or other materials provided with the distribution.\n *   * Neither the name of Redis nor the names of its contributors may be used\n *     to endorse or promote products derived from this software without\n *     specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\"\n * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\n * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE\n * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR\n * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF\n * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS\n * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN\n * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)\n * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE\n * POSSIBILITY OF SUCH DAMAGE.\n */\n\n#ifndef __HIREDIS_H\n#define __HIREDIS_H\n#include <stdio.h> /* for size_t */\n#include <stdarg.h> /* for va_list */\n#include <sys/time.h> /* for struct timeval */\n\n#define HIREDIS_MAJOR 0\n#define HIREDIS_MINOR 11\n#define HIREDIS_PATCH 0\n\n#define REDIS_ERR -1\n#define REDIS_OK 0\n\n/* When an error occurs, the err flag in a context is set to hold the type of\n * error that occured. REDIS_ERR_IO means there was an I/O error and you\n * should use the \"errno\" variable to find out what is wrong.\n * For other values, the \"errstr\" field will hold a description. */\n#define REDIS_ERR_IO 1 /* Error in read or write */\n#define REDIS_ERR_EOF 3 /* End of file */\n#define REDIS_ERR_PROTOCOL 4 /* Protocol error */\n#define REDIS_ERR_OOM 5 /* Out of memory */\n#define REDIS_ERR_OTHER 2 /* Everything else... */\n\n/* Connection type can be blocking or non-blocking and is set in the\n * least significant bit of the flags field in redisContext. */\n#define REDIS_BLOCK 0x1\n\n/* Connection may be disconnected before being free'd. The second bit\n * in the flags field is set when the context is connected. */\n#define REDIS_CONNECTED 0x2\n\n/* The async API might try to disconnect cleanly and flush the output\n * buffer and read all subsequent replies before disconnecting.\n * This flag means no new commands can come in and the connection\n * should be terminated once all replies have been read. */\n#define REDIS_DISCONNECTING 0x4\n\n/* Flag specific to the async API which means that the context should be clean\n * up as soon as possible. */\n#define REDIS_FREEING 0x8\n\n/* Flag that is set when an async callback is executed. */\n#define REDIS_IN_CALLBACK 0x10\n\n/* Flag that is set when the async context has one or more subscriptions. */\n#define REDIS_SUBSCRIBED 0x20\n\n/* Flag that is set when monitor mode is active */\n#define REDIS_MONITORING 0x40\n\n#define REDIS_REPLY_STRING 1\n#define REDIS_REPLY_ARRAY 2\n#define REDIS_REPLY_INTEGER 3\n#define REDIS_REPLY_NIL 4\n#define REDIS_REPLY_STATUS 5\n#define REDIS_REPLY_ERROR 6\n\n#define REDIS_READER_MAX_BUF (1024*16)  /* Default max unused reader buffer. */\n\n#define REDIS_KEEPALIVE_INTERVAL 15 /* seconds */\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n/* This is the reply object returned by redisCommand() */\ntypedef struct redisReply {\n    int type; /* REDIS_REPLY_* */\n    long long integer; /* The integer when type is REDIS_REPLY_INTEGER */\n    int len; /* Length of string */\n    char *str; /* Used for both REDIS_REPLY_ERROR and REDIS_REPLY_STRING */\n    size_t elements; /* number of elements, for REDIS_REPLY_ARRAY */\n    struct redisReply **element; /* elements vector for REDIS_REPLY_ARRAY */\n} redisReply;\n\ntypedef struct redisReadTask {\n    int type;\n    int elements; /* number of elements in multibulk container */\n    int idx; /* index in parent (array) object */\n    void *obj; /* holds user-generated value for a read task */\n    struct redisReadTask *parent; /* parent task */\n    void *privdata; /* user-settable arbitrary field */\n} redisReadTask;\n\ntypedef struct redisReplyObjectFunctions {\n    void *(*createString)(const redisReadTask*, char*, size_t);\n    void *(*createArray)(const redisReadTask*, int);\n    void *(*createInteger)(const redisReadTask*, long long);\n    void *(*createNil)(const redisReadTask*);\n    void (*freeObject)(void*);\n} redisReplyObjectFunctions;\n\n/* State for the protocol parser */\ntypedef struct redisReader {\n    int err; /* Error flags, 0 when there is no error */\n    char errstr[128]; /* String representation of error when applicable */\n\n    char *buf; /* Read buffer */\n    size_t pos; /* Buffer cursor */\n    size_t len; /* Buffer length */\n    size_t maxbuf; /* Max length of unused buffer */\n\n    redisReadTask rstack[9];\n    int ridx; /* Index of current read task */\n    void *reply; /* Temporary reply pointer */\n\n    redisReplyObjectFunctions *fn;\n    void *privdata;\n} redisReader;\n\n/* Public API for the protocol parser. */\nredisReader *redisReaderCreate(void);\nvoid redisReaderFree(redisReader *r);\nint redisReaderFeed(redisReader *r, const char *buf, size_t len);\nint redisReaderGetReply(redisReader *r, void **reply);\n\n/* Backwards compatibility, can be removed on big version bump. */\n#define redisReplyReaderCreate redisReaderCreate\n#define redisReplyReaderFree redisReaderFree\n#define redisReplyReaderFeed redisReaderFeed\n#define redisReplyReaderGetReply redisReaderGetReply\n#define redisReplyReaderSetPrivdata(_r, _p) (int)(((redisReader*)(_r))->privdata = (_p))\n#define redisReplyReaderGetObject(_r) (((redisReader*)(_r))->reply)\n#define redisReplyReaderGetError(_r) (((redisReader*)(_r))->errstr)\n\n/* Function to free the reply objects hiredis returns by default. */\nvoid freeReplyObject(void *reply);\n\n/* Functions to format a command according to the protocol. */\nint redisvFormatCommand(char **target, const char *format, va_list ap);\nint redisFormatCommand(char **target, const char *format, ...);\nint redisFormatCommandArgv(char **target, int argc, const char **argv, const size_t *argvlen);\n\n/* Context for a connection to Redis */\ntypedef struct redisContext {\n    int err; /* Error flags, 0 when there is no error */\n    char errstr[128]; /* String representation of error when applicable */\n    int fd;\n    int flags;\n    char *obuf; /* Write buffer */\n    redisReader *reader; /* Protocol reader */\n} redisContext;\n\nredisContext *redisConnect(const char *ip, int port);\nredisContext *redisConnectWithTimeout(const char *ip, int port, const struct timeval tv);\nredisContext *redisConnectNonBlock(const char *ip, int port);\nredisContext *redisConnectBindNonBlock(const char *ip, int port, const char *source_addr);\nredisContext *redisConnectUnix(const char *path);\nredisContext *redisConnectUnixWithTimeout(const char *path, const struct timeval tv);\nredisContext *redisConnectUnixNonBlock(const char *path);\nredisContext *redisConnectFd(int fd);\nint redisSetTimeout(redisContext *c, const struct timeval tv);\nint redisEnableKeepAlive(redisContext *c);\nvoid redisFree(redisContext *c);\nint redisFreeKeepFd(redisContext *c);\nint redisBufferRead(redisContext *c);\nint redisBufferWrite(redisContext *c, int *done);\n\n/* In a blocking context, this function first checks if there are unconsumed\n * replies to return and returns one if so. Otherwise, it flushes the output\n * buffer to the socket and reads until it has a reply. In a non-blocking\n * context, it will return unconsumed replies until there are no more. */\nint redisGetReply(redisContext *c, void **reply);\nint redisGetReplyFromReader(redisContext *c, void **reply);\n\n/* Write a formatted command to the output buffer. Use these functions in blocking mode\n * to get a pipeline of commands. */\nint redisAppendFormattedCommand(redisContext *c, const char *cmd, size_t len);\n\n/* Write a command to the output buffer. Use these functions in blocking mode\n * to get a pipeline of commands. */\nint redisvAppendCommand(redisContext *c, const char *format, va_list ap);\nint redisAppendCommand(redisContext *c, const char *format, ...);\nint redisAppendCommandArgv(redisContext *c, int argc, const char **argv, const size_t *argvlen);\n\n/* Issue a command to Redis. In a blocking context, it is identical to calling\n * redisAppendCommand, followed by redisGetReply. The function will return\n * NULL if there was an error in performing the request, otherwise it will\n * return the reply. In a non-blocking context, it is identical to calling\n * only redisAppendCommand and will always return NULL. */\nvoid *redisvCommand(redisContext *c, const char *format, va_list ap);\nvoid *redisCommand(redisContext *c, const char *format, ...);\nvoid *redisCommandArgv(redisContext *c, int argc, const char **argv, const size_t *argvlen);\n\n#ifdef __cplusplus\n}\n#endif\n\n#endif\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.8/deps/hiredis/net.c",
    "content": "/* Extracted from anet.c to work properly with Hiredis error reporting.\n *\n * Copyright (c) 2006-2011, Salvatore Sanfilippo <antirez at gmail dot com>\n * Copyright (c) 2010-2011, Pieter Noordhuis <pcnoordhuis at gmail dot com>\n *\n * All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions are met:\n *\n *   * Redistributions of source code must retain the above copyright notice,\n *     this list of conditions and the following disclaimer.\n *   * Redistributions in binary form must reproduce the above copyright\n *     notice, this list of conditions and the following disclaimer in the\n *     documentation and/or other materials provided with the distribution.\n *   * Neither the name of Redis nor the names of its contributors may be used\n *     to endorse or promote products derived from this software without\n *     specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\"\n * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\n * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE\n * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR\n * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF\n * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS\n * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN\n * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)\n * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE\n * POSSIBILITY OF SUCH DAMAGE.\n */\n\n#include \"fmacros.h\"\n#include <sys/types.h>\n#include <sys/socket.h>\n#include <sys/select.h>\n#include <sys/un.h>\n#include <netinet/in.h>\n#include <netinet/tcp.h>\n#include <arpa/inet.h>\n#include <unistd.h>\n#include <fcntl.h>\n#include <string.h>\n#include <netdb.h>\n#include <errno.h>\n#include <stdarg.h>\n#include <stdio.h>\n#include <poll.h>\n#include <limits.h>\n\n#include \"net.h\"\n#include \"sds.h\"\n\n/* Defined in hiredis.c */\nvoid __redisSetError(redisContext *c, int type, const char *str);\n\nstatic void redisContextCloseFd(redisContext *c) {\n    if (c && c->fd >= 0) {\n        close(c->fd);\n        c->fd = -1;\n    }\n}\n\nstatic void __redisSetErrorFromErrno(redisContext *c, int type, const char *prefix) {\n    char buf[128] = { 0 };\n    size_t len = 0;\n\n    if (prefix != NULL)\n        len = snprintf(buf,sizeof(buf),\"%s: \",prefix);\n    strerror_r(errno,buf+len,sizeof(buf)-len);\n    __redisSetError(c,type,buf);\n}\n\nstatic int redisSetReuseAddr(redisContext *c) {\n    int on = 1;\n    if (setsockopt(c->fd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)) == -1) {\n        __redisSetErrorFromErrno(c,REDIS_ERR_IO,NULL);\n        redisContextCloseFd(c);\n        return REDIS_ERR;\n    }\n    return REDIS_OK;\n}\n\nstatic int redisCreateSocket(redisContext *c, int type) {\n    int s;\n    if ((s = socket(type, SOCK_STREAM, 0)) == -1) {\n        __redisSetErrorFromErrno(c,REDIS_ERR_IO,NULL);\n        return REDIS_ERR;\n    }\n    c->fd = s;\n    if (type == AF_INET) {\n        if (redisSetReuseAddr(c) == REDIS_ERR) {\n            return REDIS_ERR;\n        }\n    }\n    return REDIS_OK;\n}\n\nstatic int redisSetBlocking(redisContext *c, int blocking) {\n    int flags;\n\n    /* Set the socket nonblocking.\n     * Note that fcntl(2) for F_GETFL and F_SETFL can't be\n     * interrupted by a signal. */\n    if ((flags = fcntl(c->fd, F_GETFL)) == -1) {\n        __redisSetErrorFromErrno(c,REDIS_ERR_IO,\"fcntl(F_GETFL)\");\n        redisContextCloseFd(c);\n        return REDIS_ERR;\n    }\n\n    if (blocking)\n        flags &= ~O_NONBLOCK;\n    else\n        flags |= O_NONBLOCK;\n\n    if (fcntl(c->fd, F_SETFL, flags) == -1) {\n        __redisSetErrorFromErrno(c,REDIS_ERR_IO,\"fcntl(F_SETFL)\");\n        redisContextCloseFd(c);\n        return REDIS_ERR;\n    }\n    return REDIS_OK;\n}\n\nint redisKeepAlive(redisContext *c, int interval) {\n    int val = 1;\n    int fd = c->fd;\n\n    if (setsockopt(fd, SOL_SOCKET, SO_KEEPALIVE, &val, sizeof(val)) == -1){\n        __redisSetError(c,REDIS_ERR_OTHER,strerror(errno));\n        return REDIS_ERR;\n    }\n\n    val = interval;\n\n#ifdef _OSX\n    if (setsockopt(fd, IPPROTO_TCP, TCP_KEEPALIVE, &val, sizeof(val)) < 0) {\n        __redisSetError(c,REDIS_ERR_OTHER,strerror(errno));\n        return REDIS_ERR;\n    }\n#else\n#ifndef __sun\n    val = interval;\n    if (setsockopt(fd, IPPROTO_TCP, TCP_KEEPIDLE, &val, sizeof(val)) < 0) {\n        __redisSetError(c,REDIS_ERR_OTHER,strerror(errno));\n        return REDIS_ERR;\n    }\n\n    val = interval/3;\n    if (val == 0) val = 1;\n    if (setsockopt(fd, IPPROTO_TCP, TCP_KEEPINTVL, &val, sizeof(val)) < 0) {\n        __redisSetError(c,REDIS_ERR_OTHER,strerror(errno));\n        return REDIS_ERR;\n    }\n\n    val = 3;\n    if (setsockopt(fd, IPPROTO_TCP, TCP_KEEPCNT, &val, sizeof(val)) < 0) {\n        __redisSetError(c,REDIS_ERR_OTHER,strerror(errno));\n        return REDIS_ERR;\n    }\n#endif\n#endif\n\n    return REDIS_OK;\n}\n\nstatic int redisSetTcpNoDelay(redisContext *c) {\n    int yes = 1;\n    if (setsockopt(c->fd, IPPROTO_TCP, TCP_NODELAY, &yes, sizeof(yes)) == -1) {\n        __redisSetErrorFromErrno(c,REDIS_ERR_IO,\"setsockopt(TCP_NODELAY)\");\n        redisContextCloseFd(c);\n        return REDIS_ERR;\n    }\n    return REDIS_OK;\n}\n\n#define __MAX_MSEC (((LONG_MAX) - 999) / 1000)\n\nstatic int redisContextWaitReady(redisContext *c, const struct timeval *timeout) {\n    struct pollfd   wfd[1];\n    long msec;\n\n    msec          = -1;\n    wfd[0].fd     = c->fd;\n    wfd[0].events = POLLOUT;\n\n    /* Only use timeout when not NULL. */\n    if (timeout != NULL) {\n        if (timeout->tv_usec > 1000000 || timeout->tv_sec > __MAX_MSEC) {\n            __redisSetErrorFromErrno(c, REDIS_ERR_IO, NULL);\n            redisContextCloseFd(c);\n            return REDIS_ERR;\n        }\n\n        msec = (timeout->tv_sec * 1000) + ((timeout->tv_usec + 999) / 1000);\n\n        if (msec < 0 || msec > INT_MAX) {\n            msec = INT_MAX;\n        }\n    }\n\n    if (errno == EINPROGRESS) {\n        int res;\n\n        if ((res = poll(wfd, 1, msec)) == -1) {\n            __redisSetErrorFromErrno(c, REDIS_ERR_IO, \"poll(2)\");\n            redisContextCloseFd(c);\n            return REDIS_ERR;\n        } else if (res == 0) {\n            errno = ETIMEDOUT;\n            __redisSetErrorFromErrno(c,REDIS_ERR_IO,NULL);\n            redisContextCloseFd(c);\n            return REDIS_ERR;\n        }\n\n        if (redisCheckSocketError(c) != REDIS_OK)\n            return REDIS_ERR;\n\n        return REDIS_OK;\n    }\n\n    __redisSetErrorFromErrno(c,REDIS_ERR_IO,NULL);\n    redisContextCloseFd(c);\n    return REDIS_ERR;\n}\n\nint redisCheckSocketError(redisContext *c) {\n    int err = 0;\n    socklen_t errlen = sizeof(err);\n\n    if (getsockopt(c->fd, SOL_SOCKET, SO_ERROR, &err, &errlen) == -1) {\n        __redisSetErrorFromErrno(c,REDIS_ERR_IO,\"getsockopt(SO_ERROR)\");\n        return REDIS_ERR;\n    }\n\n    if (err) {\n        errno = err;\n        __redisSetErrorFromErrno(c,REDIS_ERR_IO,NULL);\n        return REDIS_ERR;\n    }\n\n    return REDIS_OK;\n}\n\nint redisContextSetTimeout(redisContext *c, const struct timeval tv) {\n    if (setsockopt(c->fd,SOL_SOCKET,SO_RCVTIMEO,&tv,sizeof(tv)) == -1) {\n        __redisSetErrorFromErrno(c,REDIS_ERR_IO,\"setsockopt(SO_RCVTIMEO)\");\n        return REDIS_ERR;\n    }\n    if (setsockopt(c->fd,SOL_SOCKET,SO_SNDTIMEO,&tv,sizeof(tv)) == -1) {\n        __redisSetErrorFromErrno(c,REDIS_ERR_IO,\"setsockopt(SO_SNDTIMEO)\");\n        return REDIS_ERR;\n    }\n    return REDIS_OK;\n}\n\nstatic int _redisContextConnectTcp(redisContext *c, const char *addr, int port,\n                                   const struct timeval *timeout,\n                                   const char *source_addr) {\n    int s, rv;\n    char _port[6];  /* strlen(\"65535\"); */\n    struct addrinfo hints, *servinfo, *bservinfo, *p, *b;\n    int blocking = (c->flags & REDIS_BLOCK);\n\n    snprintf(_port, 6, \"%d\", port);\n    memset(&hints,0,sizeof(hints));\n    hints.ai_family = AF_INET;\n    hints.ai_socktype = SOCK_STREAM;\n\n    /* Try with IPv6 if no IPv4 address was found. We do it in this order since\n     * in a Redis client you can't afford to test if you have IPv6 connectivity\n     * as this would add latency to every connect. Otherwise a more sensible\n     * route could be: Use IPv6 if both addresses are available and there is IPv6\n     * connectivity. */\n    if ((rv = getaddrinfo(addr,_port,&hints,&servinfo)) != 0) {\n         hints.ai_family = AF_INET6;\n         if ((rv = getaddrinfo(addr,_port,&hints,&servinfo)) != 0) {\n            __redisSetError(c,REDIS_ERR_OTHER,gai_strerror(rv));\n            return REDIS_ERR;\n        }\n    }\n    for (p = servinfo; p != NULL; p = p->ai_next) {\n        if ((s = socket(p->ai_family,p->ai_socktype,p->ai_protocol)) == -1)\n            continue;\n\n        c->fd = s;\n        if (redisSetBlocking(c,0) != REDIS_OK)\n            goto error;\n        if (source_addr) {\n            int bound = 0;\n            /* Using getaddrinfo saves us from self-determining IPv4 vs IPv6 */\n            if ((rv = getaddrinfo(source_addr, NULL, &hints, &bservinfo)) != 0) {\n                char buf[128];\n                snprintf(buf,sizeof(buf),\"Can't get addr: %s\",gai_strerror(rv));\n                __redisSetError(c,REDIS_ERR_OTHER,buf);\n                goto error;\n            }\n            for (b = bservinfo; b != NULL; b = b->ai_next) {\n                if (bind(s,b->ai_addr,b->ai_addrlen) != -1) {\n                    bound = 1;\n                    break;\n                }\n            }\n            freeaddrinfo(bservinfo);\n            if (!bound) {\n                char buf[128];\n                snprintf(buf,sizeof(buf),\"Can't bind socket: %s\",strerror(errno));\n                __redisSetError(c,REDIS_ERR_OTHER,buf);\n                goto error;\n            }\n        }\n        if (connect(s,p->ai_addr,p->ai_addrlen) == -1) {\n            if (errno == EHOSTUNREACH) {\n                redisContextCloseFd(c);\n                continue;\n            } else if (errno == EINPROGRESS && !blocking) {\n                /* This is ok. */\n            } else {\n                if (redisContextWaitReady(c,timeout) != REDIS_OK)\n                    goto error;\n            }\n        }\n        if (blocking && redisSetBlocking(c,1) != REDIS_OK)\n            goto error;\n        if (redisSetTcpNoDelay(c) != REDIS_OK)\n            goto error;\n\n        c->flags |= REDIS_CONNECTED;\n        rv = REDIS_OK;\n        goto end;\n    }\n    if (p == NULL) {\n        char buf[128];\n        snprintf(buf,sizeof(buf),\"Can't create socket: %s\",strerror(errno));\n        __redisSetError(c,REDIS_ERR_OTHER,buf);\n        goto error;\n    }\n\nerror:\n    rv = REDIS_ERR;\nend:\n    freeaddrinfo(servinfo);\n    return rv;  // Need to return REDIS_OK if alright\n}\n\nint redisContextConnectTcp(redisContext *c, const char *addr, int port,\n                           const struct timeval *timeout) {\n    return _redisContextConnectTcp(c, addr, port, timeout, NULL);\n}\n\nint redisContextConnectBindTcp(redisContext *c, const char *addr, int port,\n                               const struct timeval *timeout,\n                               const char *source_addr) {\n    return _redisContextConnectTcp(c, addr, port, timeout, source_addr);\n}\n\nint redisContextConnectUnix(redisContext *c, const char *path, const struct timeval *timeout) {\n    int blocking = (c->flags & REDIS_BLOCK);\n    struct sockaddr_un sa;\n\n    if (redisCreateSocket(c,AF_LOCAL) < 0)\n        return REDIS_ERR;\n    if (redisSetBlocking(c,0) != REDIS_OK)\n        return REDIS_ERR;\n\n    sa.sun_family = AF_LOCAL;\n    strncpy(sa.sun_path,path,sizeof(sa.sun_path)-1);\n    if (connect(c->fd, (struct sockaddr*)&sa, sizeof(sa)) == -1) {\n        if (errno == EINPROGRESS && !blocking) {\n            /* This is ok. */\n        } else {\n            if (redisContextWaitReady(c,timeout) != REDIS_OK)\n                return REDIS_ERR;\n        }\n    }\n\n    /* Reset socket to be blocking after connect(2). */\n    if (blocking && redisSetBlocking(c,1) != REDIS_OK)\n        return REDIS_ERR;\n\n    c->flags |= REDIS_CONNECTED;\n    return REDIS_OK;\n}\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.8/deps/hiredis/net.h",
    "content": "/* Extracted from anet.c to work properly with Hiredis error reporting.\n *\n * Copyright (c) 2006-2011, Salvatore Sanfilippo <antirez at gmail dot com>\n * Copyright (c) 2010-2011, Pieter Noordhuis <pcnoordhuis at gmail dot com>\n *\n * All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions are met:\n *\n *   * Redistributions of source code must retain the above copyright notice,\n *     this list of conditions and the following disclaimer.\n *   * Redistributions in binary form must reproduce the above copyright\n *     notice, this list of conditions and the following disclaimer in the\n *     documentation and/or other materials provided with the distribution.\n *   * Neither the name of Redis nor the names of its contributors may be used\n *     to endorse or promote products derived from this software without\n *     specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\"\n * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\n * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE\n * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR\n * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF\n * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS\n * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN\n * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)\n * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE\n * POSSIBILITY OF SUCH DAMAGE.\n */\n\n#ifndef __NET_H\n#define __NET_H\n\n#include \"hiredis.h\"\n\n#if defined(__sun) || defined(_AIX)\n#define AF_LOCAL AF_UNIX\n#endif\n\nint redisCheckSocketError(redisContext *c);\nint redisContextSetTimeout(redisContext *c, const struct timeval tv);\nint redisContextConnectTcp(redisContext *c, const char *addr, int port, const struct timeval *timeout);\nint redisContextConnectBindTcp(redisContext *c, const char *addr, int port,\n                               const struct timeval *timeout,\n                               const char *source_addr);\nint redisContextConnectUnix(redisContext *c, const char *path, const struct timeval *timeout);\nint redisKeepAlive(redisContext *c, int interval);\n\n#endif\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.8/deps/hiredis/sds.c",
    "content": "/* SDSLib 2.0 -- A C dynamic strings library\n *\n * Copyright (c) 2006-2015, Salvatore Sanfilippo <antirez at gmail dot com>\n * Copyright (c) 2015, Oran Agra\n * Copyright (c) 2015, Redis Labs, Inc\n * All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions are met:\n *\n *   * Redistributions of source code must retain the above copyright notice,\n *     this list of conditions and the following disclaimer.\n *   * Redistributions in binary form must reproduce the above copyright\n *     notice, this list of conditions and the following disclaimer in the\n *     documentation and/or other materials provided with the distribution.\n *   * Neither the name of Redis nor the names of its contributors may be used\n *     to endorse or promote products derived from this software without\n *     specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\"\n * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\n * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE\n * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR\n * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF\n * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS\n * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN\n * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)\n * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE\n * POSSIBILITY OF SUCH DAMAGE.\n */\n\n#include <stdio.h>\n#include <stdlib.h>\n#include <string.h>\n#include <ctype.h>\n#include <assert.h>\n#include \"sds.h\"\n#include \"sdsalloc.h\"\n\nstatic inline int sdsHdrSize(char type) {\n    switch(type&SDS_TYPE_MASK) {\n        case SDS_TYPE_5:\n            return sizeof(struct sdshdr5);\n        case SDS_TYPE_8:\n            return sizeof(struct sdshdr8);\n        case SDS_TYPE_16:\n            return sizeof(struct sdshdr16);\n        case SDS_TYPE_32:\n            return sizeof(struct sdshdr32);\n        case SDS_TYPE_64:\n            return sizeof(struct sdshdr64);\n    }\n    return 0;\n}\n\nstatic inline char sdsReqType(size_t string_size) {\n    if (string_size < 32)\n        return SDS_TYPE_5;\n    if (string_size < 0xff)\n        return SDS_TYPE_8;\n    if (string_size < 0xffff)\n        return SDS_TYPE_16;\n    if (string_size < 0xffffffff)\n        return SDS_TYPE_32;\n    return SDS_TYPE_64;\n}\n\n/* Create a new sds string with the content specified by the 'init' pointer\n * and 'initlen'.\n * If NULL is used for 'init' the string is initialized with zero bytes.\n *\n * The string is always null-termined (all the sds strings are, always) so\n * even if you create an sds string with:\n *\n * mystring = sdsnewlen(\"abc\",3);\n *\n * You can print the string with printf() as there is an implicit \\0 at the\n * end of the string. However the string is binary safe and can contain\n * \\0 characters in the middle, as the length is stored in the sds header. */\nsds sdsnewlen(const void *init, size_t initlen) {\n    void *sh;\n    sds s;\n    char type = sdsReqType(initlen);\n    /* Empty strings are usually created in order to append. Use type 8\n     * since type 5 is not good at this. */\n    if (type == SDS_TYPE_5 && initlen == 0) type = SDS_TYPE_8;\n    int hdrlen = sdsHdrSize(type);\n    unsigned char *fp; /* flags pointer. */\n\n    sh = s_malloc(hdrlen+initlen+1);\n    if (!init)\n        memset(sh, 0, hdrlen+initlen+1);\n    if (sh == NULL) return NULL;\n    s = (char*)sh+hdrlen;\n    fp = ((unsigned char*)s)-1;\n    switch(type) {\n        case SDS_TYPE_5: {\n            *fp = type | (initlen << SDS_TYPE_BITS);\n            break;\n        }\n        case SDS_TYPE_8: {\n            SDS_HDR_VAR(8,s);\n            sh->len = initlen;\n            sh->alloc = initlen;\n            *fp = type;\n            break;\n        }\n        case SDS_TYPE_16: {\n            SDS_HDR_VAR(16,s);\n            sh->len = initlen;\n            sh->alloc = initlen;\n            *fp = type;\n            break;\n        }\n        case SDS_TYPE_32: {\n            SDS_HDR_VAR(32,s);\n            sh->len = initlen;\n            sh->alloc = initlen;\n            *fp = type;\n            break;\n        }\n        case SDS_TYPE_64: {\n            SDS_HDR_VAR(64,s);\n            sh->len = initlen;\n            sh->alloc = initlen;\n            *fp = type;\n            break;\n        }\n    }\n    if (initlen && init)\n        memcpy(s, init, initlen);\n    s[initlen] = '\\0';\n    return s;\n}\n\n/* Create an empty (zero length) sds string. Even in this case the string\n * always has an implicit null term. */\nsds sdsempty(void) {\n    return sdsnewlen(\"\",0);\n}\n\n/* Create a new sds string starting from a null terminated C string. */\nsds sdsnew(const char *init) {\n    size_t initlen = (init == NULL) ? 0 : strlen(init);\n    return sdsnewlen(init, initlen);\n}\n\n/* Duplicate an sds string. */\nsds sdsdup(const sds s) {\n    return sdsnewlen(s, sdslen(s));\n}\n\n/* Free an sds string. No operation is performed if 's' is NULL. */\nvoid sdsfree(sds s) {\n    if (s == NULL) return;\n    s_free((char*)s-sdsHdrSize(s[-1]));\n}\n\n/* Set the sds string length to the length as obtained with strlen(), so\n * considering as content only up to the first null term character.\n *\n * This function is useful when the sds string is hacked manually in some\n * way, like in the following example:\n *\n * s = sdsnew(\"foobar\");\n * s[2] = '\\0';\n * sdsupdatelen(s);\n * printf(\"%d\\n\", sdslen(s));\n *\n * The output will be \"2\", but if we comment out the call to sdsupdatelen()\n * the output will be \"6\" as the string was modified but the logical length\n * remains 6 bytes. */\nvoid sdsupdatelen(sds s) {\n    int reallen = strlen(s);\n    sdssetlen(s, reallen);\n}\n\n/* Modify an sds string in-place to make it empty (zero length).\n * However all the existing buffer is not discarded but set as free space\n * so that next append operations will not require allocations up to the\n * number of bytes previously available. */\nvoid sdsclear(sds s) {\n    sdssetlen(s, 0);\n    s[0] = '\\0';\n}\n\n/* Enlarge the free space at the end of the sds string so that the caller\n * is sure that after calling this function can overwrite up to addlen\n * bytes after the end of the string, plus one more byte for nul term.\n *\n * Note: this does not change the *length* of the sds string as returned\n * by sdslen(), but only the free buffer space we have. */\nsds sdsMakeRoomFor(sds s, size_t addlen) {\n    void *sh, *newsh;\n    size_t avail = sdsavail(s);\n    size_t len, newlen;\n    char type, oldtype = s[-1] & SDS_TYPE_MASK;\n    int hdrlen;\n\n    /* Return ASAP if there is enough space left. */\n    if (avail >= addlen) return s;\n\n    len = sdslen(s);\n    sh = (char*)s-sdsHdrSize(oldtype);\n    newlen = (len+addlen);\n    if (newlen < SDS_MAX_PREALLOC)\n        newlen *= 2;\n    else\n        newlen += SDS_MAX_PREALLOC;\n\n    type = sdsReqType(newlen);\n\n    /* Don't use type 5: the user is appending to the string and type 5 is\n     * not able to remember empty space, so sdsMakeRoomFor() must be called\n     * at every appending operation. */\n    if (type == SDS_TYPE_5) type = SDS_TYPE_8;\n\n    hdrlen = sdsHdrSize(type);\n    if (oldtype==type) {\n        newsh = s_realloc(sh, hdrlen+newlen+1);\n        if (newsh == NULL) return NULL;\n        s = (char*)newsh+hdrlen;\n    } else {\n        /* Since the header size changes, need to move the string forward,\n         * and can't use realloc */\n        newsh = s_malloc(hdrlen+newlen+1);\n        if (newsh == NULL) return NULL;\n        memcpy((char*)newsh+hdrlen, s, len+1);\n        s_free(sh);\n        s = (char*)newsh+hdrlen;\n        s[-1] = type;\n        sdssetlen(s, len);\n    }\n    sdssetalloc(s, newlen);\n    return s;\n}\n\n/* Reallocate the sds string so that it has no free space at the end. The\n * contained string remains not altered, but next concatenation operations\n * will require a reallocation.\n *\n * After the call, the passed sds string is no longer valid and all the\n * references must be substituted with the new pointer returned by the call. */\nsds sdsRemoveFreeSpace(sds s) {\n    void *sh, *newsh;\n    char type, oldtype = s[-1] & SDS_TYPE_MASK;\n    int hdrlen;\n    size_t len = sdslen(s);\n    sh = (char*)s-sdsHdrSize(oldtype);\n\n    type = sdsReqType(len);\n    hdrlen = sdsHdrSize(type);\n    if (oldtype==type) {\n        newsh = s_realloc(sh, hdrlen+len+1);\n        if (newsh == NULL) return NULL;\n        s = (char*)newsh+hdrlen;\n    } else {\n        newsh = s_malloc(hdrlen+len+1);\n        if (newsh == NULL) return NULL;\n        memcpy((char*)newsh+hdrlen, s, len+1);\n        s_free(sh);\n        s = (char*)newsh+hdrlen;\n        s[-1] = type;\n        sdssetlen(s, len);\n    }\n    sdssetalloc(s, len);\n    return s;\n}\n\n/* Return the total size of the allocation of the specifed sds string,\n * including:\n * 1) The sds header before the pointer.\n * 2) The string.\n * 3) The free buffer at the end if any.\n * 4) The implicit null term.\n */\nsize_t sdsAllocSize(sds s) {\n    size_t alloc = sdsalloc(s);\n    return sdsHdrSize(s[-1])+alloc+1;\n}\n\n/* Return the pointer of the actual SDS allocation (normally SDS strings\n * are referenced by the start of the string buffer). */\nvoid *sdsAllocPtr(sds s) {\n    return (void*) (s-sdsHdrSize(s[-1]));\n}\n\n/* Increment the sds length and decrements the left free space at the\n * end of the string according to 'incr'. Also set the null term\n * in the new end of the string.\n *\n * This function is used in order to fix the string length after the\n * user calls sdsMakeRoomFor(), writes something after the end of\n * the current string, and finally needs to set the new length.\n *\n * Note: it is possible to use a negative increment in order to\n * right-trim the string.\n *\n * Usage example:\n *\n * Using sdsIncrLen() and sdsMakeRoomFor() it is possible to mount the\n * following schema, to cat bytes coming from the kernel to the end of an\n * sds string without copying into an intermediate buffer:\n *\n * oldlen = sdslen(s);\n * s = sdsMakeRoomFor(s, BUFFER_SIZE);\n * nread = read(fd, s+oldlen, BUFFER_SIZE);\n * ... check for nread <= 0 and handle it ...\n * sdsIncrLen(s, nread);\n */\nvoid sdsIncrLen(sds s, int incr) {\n    unsigned char flags = s[-1];\n    size_t len;\n    switch(flags&SDS_TYPE_MASK) {\n        case SDS_TYPE_5: {\n            unsigned char *fp = ((unsigned char*)s)-1;\n            unsigned char oldlen = SDS_TYPE_5_LEN(flags);\n            assert((incr > 0 && oldlen+incr < 32) || (incr < 0 && oldlen >= (unsigned int)(-incr)));\n            *fp = SDS_TYPE_5 | ((oldlen+incr) << SDS_TYPE_BITS);\n            len = oldlen+incr;\n            break;\n        }\n        case SDS_TYPE_8: {\n            SDS_HDR_VAR(8,s);\n            assert((incr >= 0 && sh->alloc-sh->len >= incr) || (incr < 0 && sh->len >= (unsigned int)(-incr)));\n            len = (sh->len += incr);\n            break;\n        }\n        case SDS_TYPE_16: {\n            SDS_HDR_VAR(16,s);\n            assert((incr >= 0 && sh->alloc-sh->len >= incr) || (incr < 0 && sh->len >= (unsigned int)(-incr)));\n            len = (sh->len += incr);\n            break;\n        }\n        case SDS_TYPE_32: {\n            SDS_HDR_VAR(32,s);\n            assert((incr >= 0 && sh->alloc-sh->len >= (unsigned int)incr) || (incr < 0 && sh->len >= (unsigned int)(-incr)));\n            len = (sh->len += incr);\n            break;\n        }\n        case SDS_TYPE_64: {\n            SDS_HDR_VAR(64,s);\n            assert((incr >= 0 && sh->alloc-sh->len >= (uint64_t)incr) || (incr < 0 && sh->len >= (uint64_t)(-incr)));\n            len = (sh->len += incr);\n            break;\n        }\n        default: len = 0; /* Just to avoid compilation warnings. */\n    }\n    s[len] = '\\0';\n}\n\n/* Grow the sds to have the specified length. Bytes that were not part of\n * the original length of the sds will be set to zero.\n *\n * if the specified length is smaller than the current length, no operation\n * is performed. */\nsds sdsgrowzero(sds s, size_t len) {\n    size_t curlen = sdslen(s);\n\n    if (len <= curlen) return s;\n    s = sdsMakeRoomFor(s,len-curlen);\n    if (s == NULL) return NULL;\n\n    /* Make sure added region doesn't contain garbage */\n    memset(s+curlen,0,(len-curlen+1)); /* also set trailing \\0 byte */\n    sdssetlen(s, len);\n    return s;\n}\n\n/* Append the specified binary-safe string pointed by 't' of 'len' bytes to the\n * end of the specified sds string 's'.\n *\n * After the call, the passed sds string is no longer valid and all the\n * references must be substituted with the new pointer returned by the call. */\nsds sdscatlen(sds s, const void *t, size_t len) {\n    size_t curlen = sdslen(s);\n\n    s = sdsMakeRoomFor(s,len);\n    if (s == NULL) return NULL;\n    memcpy(s+curlen, t, len);\n    sdssetlen(s, curlen+len);\n    s[curlen+len] = '\\0';\n    return s;\n}\n\n/* Append the specified null termianted C string to the sds string 's'.\n *\n * After the call, the passed sds string is no longer valid and all the\n * references must be substituted with the new pointer returned by the call. */\nsds sdscat(sds s, const char *t) {\n    return sdscatlen(s, t, strlen(t));\n}\n\n/* Append the specified sds 't' to the existing sds 's'.\n *\n * After the call, the modified sds string is no longer valid and all the\n * references must be substituted with the new pointer returned by the call. */\nsds sdscatsds(sds s, const sds t) {\n    return sdscatlen(s, t, sdslen(t));\n}\n\n/* Destructively modify the sds string 's' to hold the specified binary\n * safe string pointed by 't' of length 'len' bytes. */\nsds sdscpylen(sds s, const char *t, size_t len) {\n    if (sdsalloc(s) < len) {\n        s = sdsMakeRoomFor(s,len-sdslen(s));\n        if (s == NULL) return NULL;\n    }\n    memcpy(s, t, len);\n    s[len] = '\\0';\n    sdssetlen(s, len);\n    return s;\n}\n\n/* Like sdscpylen() but 't' must be a null-termined string so that the length\n * of the string is obtained with strlen(). */\nsds sdscpy(sds s, const char *t) {\n    return sdscpylen(s, t, strlen(t));\n}\n\n/* Helper for sdscatlonglong() doing the actual number -> string\n * conversion. 's' must point to a string with room for at least\n * SDS_LLSTR_SIZE bytes.\n *\n * The function returns the length of the null-terminated string\n * representation stored at 's'. */\n#define SDS_LLSTR_SIZE 21\nint sdsll2str(char *s, long long value) {\n    char *p, aux;\n    unsigned long long v;\n    size_t l;\n\n    /* Generate the string representation, this method produces\n     * an reversed string. */\n    v = (value < 0) ? -value : value;\n    p = s;\n    do {\n        *p++ = '0'+(v%10);\n        v /= 10;\n    } while(v);\n    if (value < 0) *p++ = '-';\n\n    /* Compute length and add null term. */\n    l = p-s;\n    *p = '\\0';\n\n    /* Reverse the string. */\n    p--;\n    while(s < p) {\n        aux = *s;\n        *s = *p;\n        *p = aux;\n        s++;\n        p--;\n    }\n    return l;\n}\n\n/* Identical sdsll2str(), but for unsigned long long type. */\nint sdsull2str(char *s, unsigned long long v) {\n    char *p, aux;\n    size_t l;\n\n    /* Generate the string representation, this method produces\n     * an reversed string. */\n    p = s;\n    do {\n        *p++ = '0'+(v%10);\n        v /= 10;\n    } while(v);\n\n    /* Compute length and add null term. */\n    l = p-s;\n    *p = '\\0';\n\n    /* Reverse the string. */\n    p--;\n    while(s < p) {\n        aux = *s;\n        *s = *p;\n        *p = aux;\n        s++;\n        p--;\n    }\n    return l;\n}\n\n/* Create an sds string from a long long value. It is much faster than:\n *\n * sdscatprintf(sdsempty(),\"%lld\\n\", value);\n */\nsds sdsfromlonglong(long long value) {\n    char buf[SDS_LLSTR_SIZE];\n    int len = sdsll2str(buf,value);\n\n    return sdsnewlen(buf,len);\n}\n\n/* Like sdscatprintf() but gets va_list instead of being variadic. */\nsds sdscatvprintf(sds s, const char *fmt, va_list ap) {\n    va_list cpy;\n    char staticbuf[1024], *buf = staticbuf, *t;\n    size_t buflen = strlen(fmt)*2;\n\n    /* We try to start using a static buffer for speed.\n     * If not possible we revert to heap allocation. */\n    if (buflen > sizeof(staticbuf)) {\n        buf = s_malloc(buflen);\n        if (buf == NULL) return NULL;\n    } else {\n        buflen = sizeof(staticbuf);\n    }\n\n    /* Try with buffers two times bigger every time we fail to\n     * fit the string in the current buffer size. */\n    while(1) {\n        buf[buflen-2] = '\\0';\n        va_copy(cpy,ap);\n        vsnprintf(buf, buflen, fmt, cpy);\n        va_end(cpy);\n        if (buf[buflen-2] != '\\0') {\n            if (buf != staticbuf) s_free(buf);\n            buflen *= 2;\n            buf = s_malloc(buflen);\n            if (buf == NULL) return NULL;\n            continue;\n        }\n        break;\n    }\n\n    /* Finally concat the obtained string to the SDS string and return it. */\n    t = sdscat(s, buf);\n    if (buf != staticbuf) s_free(buf);\n    return t;\n}\n\n/* Append to the sds string 's' a string obtained using printf-alike format\n * specifier.\n *\n * After the call, the modified sds string is no longer valid and all the\n * references must be substituted with the new pointer returned by the call.\n *\n * Example:\n *\n * s = sdsnew(\"Sum is: \");\n * s = sdscatprintf(s,\"%d+%d = %d\",a,b,a+b).\n *\n * Often you need to create a string from scratch with the printf-alike\n * format. When this is the need, just use sdsempty() as the target string:\n *\n * s = sdscatprintf(sdsempty(), \"... your format ...\", args);\n */\nsds sdscatprintf(sds s, const char *fmt, ...) {\n    va_list ap;\n    char *t;\n    va_start(ap, fmt);\n    t = sdscatvprintf(s,fmt,ap);\n    va_end(ap);\n    return t;\n}\n\n/* This function is similar to sdscatprintf, but much faster as it does\n * not rely on sprintf() family functions implemented by the libc that\n * are often very slow. Moreover directly handling the sds string as\n * new data is concatenated provides a performance improvement.\n *\n * However this function only handles an incompatible subset of printf-alike\n * format specifiers:\n *\n * %s - C String\n * %S - SDS string\n * %i - signed int\n * %I - 64 bit signed integer (long long, int64_t)\n * %u - unsigned int\n * %U - 64 bit unsigned integer (unsigned long long, uint64_t)\n * %% - Verbatim \"%\" character.\n */\nsds sdscatfmt(sds s, char const *fmt, ...) {\n    size_t initlen = sdslen(s);\n    const char *f = fmt;\n    int i;\n    va_list ap;\n\n    va_start(ap,fmt);\n    f = fmt;    /* Next format specifier byte to process. */\n    i = initlen; /* Position of the next byte to write to dest str. */\n    while(*f) {\n        char next, *str;\n        size_t l;\n        long long num;\n        unsigned long long unum;\n\n        /* Make sure there is always space for at least 1 char. */\n        if (sdsavail(s)==0) {\n            s = sdsMakeRoomFor(s,1);\n        }\n\n        switch(*f) {\n        case '%':\n            next = *(f+1);\n            f++;\n            switch(next) {\n            case 's':\n            case 'S':\n                str = va_arg(ap,char*);\n                l = (next == 's') ? strlen(str) : sdslen(str);\n                if (sdsavail(s) < l) {\n                    s = sdsMakeRoomFor(s,l);\n                }\n                memcpy(s+i,str,l);\n                sdsinclen(s,l);\n                i += l;\n                break;\n            case 'i':\n            case 'I':\n                if (next == 'i')\n                    num = va_arg(ap,int);\n                else\n                    num = va_arg(ap,long long);\n                {\n                    char buf[SDS_LLSTR_SIZE];\n                    l = sdsll2str(buf,num);\n                    if (sdsavail(s) < l) {\n                        s = sdsMakeRoomFor(s,l);\n                    }\n                    memcpy(s+i,buf,l);\n                    sdsinclen(s,l);\n                    i += l;\n                }\n                break;\n            case 'u':\n            case 'U':\n                if (next == 'u')\n                    unum = va_arg(ap,unsigned int);\n                else\n                    unum = va_arg(ap,unsigned long long);\n                {\n                    char buf[SDS_LLSTR_SIZE];\n                    l = sdsull2str(buf,unum);\n                    if (sdsavail(s) < l) {\n                        s = sdsMakeRoomFor(s,l);\n                    }\n                    memcpy(s+i,buf,l);\n                    sdsinclen(s,l);\n                    i += l;\n                }\n                break;\n            default: /* Handle %% and generally %<unknown>. */\n                s[i++] = next;\n                sdsinclen(s,1);\n                break;\n            }\n            break;\n        default:\n            s[i++] = *f;\n            sdsinclen(s,1);\n            break;\n        }\n        f++;\n    }\n    va_end(ap);\n\n    /* Add null-term */\n    s[i] = '\\0';\n    return s;\n}\n\n/* Remove the part of the string from left and from right composed just of\n * contiguous characters found in 'cset', that is a null terminted C string.\n *\n * After the call, the modified sds string is no longer valid and all the\n * references must be substituted with the new pointer returned by the call.\n *\n * Example:\n *\n * s = sdsnew(\"AA...AA.a.aa.aHelloWorld     :::\");\n * s = sdstrim(s,\"Aa. :\");\n * printf(\"%s\\n\", s);\n *\n * Output will be just \"Hello World\".\n */\nsds sdstrim(sds s, const char *cset) {\n    char *start, *end, *sp, *ep;\n    size_t len;\n\n    sp = start = s;\n    ep = end = s+sdslen(s)-1;\n    while(sp <= end && strchr(cset, *sp)) sp++;\n    while(ep > sp && strchr(cset, *ep)) ep--;\n    len = (sp > ep) ? 0 : ((ep-sp)+1);\n    if (s != sp) memmove(s, sp, len);\n    s[len] = '\\0';\n    sdssetlen(s,len);\n    return s;\n}\n\n/* Turn the string into a smaller (or equal) string containing only the\n * substring specified by the 'start' and 'end' indexes.\n *\n * start and end can be negative, where -1 means the last character of the\n * string, -2 the penultimate character, and so forth.\n *\n * The interval is inclusive, so the start and end characters will be part\n * of the resulting string.\n *\n * The string is modified in-place.\n *\n * Example:\n *\n * s = sdsnew(\"Hello World\");\n * sdsrange(s,1,-1); => \"ello World\"\n */\nvoid sdsrange(sds s, int start, int end) {\n    size_t newlen, len = sdslen(s);\n\n    if (len == 0) return;\n    if (start < 0) {\n        start = len+start;\n        if (start < 0) start = 0;\n    }\n    if (end < 0) {\n        end = len+end;\n        if (end < 0) end = 0;\n    }\n    newlen = (start > end) ? 0 : (end-start)+1;\n    if (newlen != 0) {\n        if (start >= (signed)len) {\n            newlen = 0;\n        } else if (end >= (signed)len) {\n            end = len-1;\n            newlen = (start > end) ? 0 : (end-start)+1;\n        }\n    } else {\n        start = 0;\n    }\n    if (start && newlen) memmove(s, s+start, newlen);\n    s[newlen] = 0;\n    sdssetlen(s,newlen);\n}\n\n/* Apply tolower() to every character of the sds string 's'. */\nvoid sdstolower(sds s) {\n    int len = sdslen(s), j;\n\n    for (j = 0; j < len; j++) s[j] = tolower(s[j]);\n}\n\n/* Apply toupper() to every character of the sds string 's'. */\nvoid sdstoupper(sds s) {\n    int len = sdslen(s), j;\n\n    for (j = 0; j < len; j++) s[j] = toupper(s[j]);\n}\n\n/* Compare two sds strings s1 and s2 with memcmp().\n *\n * Return value:\n *\n *     positive if s1 > s2.\n *     negative if s1 < s2.\n *     0 if s1 and s2 are exactly the same binary string.\n *\n * If two strings share exactly the same prefix, but one of the two has\n * additional characters, the longer string is considered to be greater than\n * the smaller one. */\nint sdscmp(const sds s1, const sds s2) {\n    size_t l1, l2, minlen;\n    int cmp;\n\n    l1 = sdslen(s1);\n    l2 = sdslen(s2);\n    minlen = (l1 < l2) ? l1 : l2;\n    cmp = memcmp(s1,s2,minlen);\n    if (cmp == 0) return l1-l2;\n    return cmp;\n}\n\n/* Split 's' with separator in 'sep'. An array\n * of sds strings is returned. *count will be set\n * by reference to the number of tokens returned.\n *\n * On out of memory, zero length string, zero length\n * separator, NULL is returned.\n *\n * Note that 'sep' is able to split a string using\n * a multi-character separator. For example\n * sdssplit(\"foo_-_bar\",\"_-_\"); will return two\n * elements \"foo\" and \"bar\".\n *\n * This version of the function is binary-safe but\n * requires length arguments. sdssplit() is just the\n * same function but for zero-terminated strings.\n */\nsds *sdssplitlen(const char *s, int len, const char *sep, int seplen, int *count) {\n    int elements = 0, slots = 5, start = 0, j;\n    sds *tokens;\n\n    if (seplen < 1 || len < 0) return NULL;\n\n    tokens = s_malloc(sizeof(sds)*slots);\n    if (tokens == NULL) return NULL;\n\n    if (len == 0) {\n        *count = 0;\n        return tokens;\n    }\n    for (j = 0; j < (len-(seplen-1)); j++) {\n        /* make sure there is room for the next element and the final one */\n        if (slots < elements+2) {\n            sds *newtokens;\n\n            slots *= 2;\n            newtokens = s_realloc(tokens,sizeof(sds)*slots);\n            if (newtokens == NULL) goto cleanup;\n            tokens = newtokens;\n        }\n        /* search the separator */\n        if ((seplen == 1 && *(s+j) == sep[0]) || (memcmp(s+j,sep,seplen) == 0)) {\n            tokens[elements] = sdsnewlen(s+start,j-start);\n            if (tokens[elements] == NULL) goto cleanup;\n            elements++;\n            start = j+seplen;\n            j = j+seplen-1; /* skip the separator */\n        }\n    }\n    /* Add the final element. We are sure there is room in the tokens array. */\n    tokens[elements] = sdsnewlen(s+start,len-start);\n    if (tokens[elements] == NULL) goto cleanup;\n    elements++;\n    *count = elements;\n    return tokens;\n\ncleanup:\n    {\n        int i;\n        for (i = 0; i < elements; i++) sdsfree(tokens[i]);\n        s_free(tokens);\n        *count = 0;\n        return NULL;\n    }\n}\n\n/* Free the result returned by sdssplitlen(), or do nothing if 'tokens' is NULL. */\nvoid sdsfreesplitres(sds *tokens, int count) {\n    if (!tokens) return;\n    while(count--)\n        sdsfree(tokens[count]);\n    s_free(tokens);\n}\n\n/* Append to the sds string \"s\" an escaped string representation where\n * all the non-printable characters (tested with isprint()) are turned into\n * escapes in the form \"\\n\\r\\a....\" or \"\\x<hex-number>\".\n *\n * After the call, the modified sds string is no longer valid and all the\n * references must be substituted with the new pointer returned by the call. */\nsds sdscatrepr(sds s, const char *p, size_t len) {\n    s = sdscatlen(s,\"\\\"\",1);\n    while(len--) {\n        switch(*p) {\n        case '\\\\':\n        case '\"':\n            s = sdscatprintf(s,\"\\\\%c\",*p);\n            break;\n        case '\\n': s = sdscatlen(s,\"\\\\n\",2); break;\n        case '\\r': s = sdscatlen(s,\"\\\\r\",2); break;\n        case '\\t': s = sdscatlen(s,\"\\\\t\",2); break;\n        case '\\a': s = sdscatlen(s,\"\\\\a\",2); break;\n        case '\\b': s = sdscatlen(s,\"\\\\b\",2); break;\n        default:\n            if (isprint(*p))\n                s = sdscatprintf(s,\"%c\",*p);\n            else\n                s = sdscatprintf(s,\"\\\\x%02x\",(unsigned char)*p);\n            break;\n        }\n        p++;\n    }\n    return sdscatlen(s,\"\\\"\",1);\n}\n\n/* Helper function for sdssplitargs() that returns non zero if 'c'\n * is a valid hex digit. */\nint is_hex_digit(char c) {\n    return (c >= '0' && c <= '9') || (c >= 'a' && c <= 'f') ||\n           (c >= 'A' && c <= 'F');\n}\n\n/* Helper function for sdssplitargs() that converts a hex digit into an\n * integer from 0 to 15 */\nint hex_digit_to_int(char c) {\n    switch(c) {\n    case '0': return 0;\n    case '1': return 1;\n    case '2': return 2;\n    case '3': return 3;\n    case '4': return 4;\n    case '5': return 5;\n    case '6': return 6;\n    case '7': return 7;\n    case '8': return 8;\n    case '9': return 9;\n    case 'a': case 'A': return 10;\n    case 'b': case 'B': return 11;\n    case 'c': case 'C': return 12;\n    case 'd': case 'D': return 13;\n    case 'e': case 'E': return 14;\n    case 'f': case 'F': return 15;\n    default: return 0;\n    }\n}\n\n/* Split a line into arguments, where every argument can be in the\n * following programming-language REPL-alike form:\n *\n * foo bar \"newline are supported\\n\" and \"\\xff\\x00otherstuff\"\n *\n * The number of arguments is stored into *argc, and an array\n * of sds is returned.\n *\n * The caller should free the resulting array of sds strings with\n * sdsfreesplitres().\n *\n * Note that sdscatrepr() is able to convert back a string into\n * a quoted string in the same format sdssplitargs() is able to parse.\n *\n * The function returns the allocated tokens on success, even when the\n * input string is empty, or NULL if the input contains unbalanced\n * quotes or closed quotes followed by non space characters\n * as in: \"foo\"bar or \"foo'\n */\nsds *sdssplitargs(const char *line, int *argc) {\n    const char *p = line;\n    char *current = NULL;\n    char **vector = NULL;\n\n    *argc = 0;\n    while(1) {\n        /* skip blanks */\n        while(*p && isspace(*p)) p++;\n        if (*p) {\n            /* get a token */\n            int inq=0;  /* set to 1 if we are in \"quotes\" */\n            int insq=0; /* set to 1 if we are in 'single quotes' */\n            int done=0;\n\n            if (current == NULL) current = sdsempty();\n            while(!done) {\n                if (inq) {\n                    if (*p == '\\\\' && *(p+1) == 'x' &&\n                                             is_hex_digit(*(p+2)) &&\n                                             is_hex_digit(*(p+3)))\n                    {\n                        unsigned char byte;\n\n                        byte = (hex_digit_to_int(*(p+2))*16)+\n                                hex_digit_to_int(*(p+3));\n                        current = sdscatlen(current,(char*)&byte,1);\n                        p += 3;\n                    } else if (*p == '\\\\' && *(p+1)) {\n                        char c;\n\n                        p++;\n                        switch(*p) {\n                        case 'n': c = '\\n'; break;\n                        case 'r': c = '\\r'; break;\n                        case 't': c = '\\t'; break;\n                        case 'b': c = '\\b'; break;\n                        case 'a': c = '\\a'; break;\n                        default: c = *p; break;\n                        }\n                        current = sdscatlen(current,&c,1);\n                    } else if (*p == '\"') {\n                        /* closing quote must be followed by a space or\n                         * nothing at all. */\n                        if (*(p+1) && !isspace(*(p+1))) goto err;\n                        done=1;\n                    } else if (!*p) {\n                        /* unterminated quotes */\n                        goto err;\n                    } else {\n                        current = sdscatlen(current,p,1);\n                    }\n                } else if (insq) {\n                    if (*p == '\\\\' && *(p+1) == '\\'') {\n                        p++;\n                        current = sdscatlen(current,\"'\",1);\n                    } else if (*p == '\\'') {\n                        /* closing quote must be followed by a space or\n                         * nothing at all. */\n                        if (*(p+1) && !isspace(*(p+1))) goto err;\n                        done=1;\n                    } else if (!*p) {\n                        /* unterminated quotes */\n                        goto err;\n                    } else {\n                        current = sdscatlen(current,p,1);\n                    }\n                } else {\n                    switch(*p) {\n                    case ' ':\n                    case '\\n':\n                    case '\\r':\n                    case '\\t':\n                    case '\\0':\n                        done=1;\n                        break;\n                    case '\"':\n                        inq=1;\n                        break;\n                    case '\\'':\n                        insq=1;\n                        break;\n                    default:\n                        current = sdscatlen(current,p,1);\n                        break;\n                    }\n                }\n                if (*p) p++;\n            }\n            /* add the token to the vector */\n            vector = s_realloc(vector,((*argc)+1)*sizeof(char*));\n            vector[*argc] = current;\n            (*argc)++;\n            current = NULL;\n        } else {\n            /* Even on empty input string return something not NULL. */\n            if (vector == NULL) vector = s_malloc(sizeof(void*));\n            return vector;\n        }\n    }\n\nerr:\n    while((*argc)--)\n        sdsfree(vector[*argc]);\n    s_free(vector);\n    if (current) sdsfree(current);\n    *argc = 0;\n    return NULL;\n}\n\n/* Modify the string substituting all the occurrences of the set of\n * characters specified in the 'from' string to the corresponding character\n * in the 'to' array.\n *\n * For instance: sdsmapchars(mystring, \"ho\", \"01\", 2)\n * will have the effect of turning the string \"hello\" into \"0ell1\".\n *\n * The function returns the sds string pointer, that is always the same\n * as the input pointer since no resize is needed. */\nsds sdsmapchars(sds s, const char *from, const char *to, size_t setlen) {\n    size_t j, i, l = sdslen(s);\n\n    for (j = 0; j < l; j++) {\n        for (i = 0; i < setlen; i++) {\n            if (s[j] == from[i]) {\n                s[j] = to[i];\n                break;\n            }\n        }\n    }\n    return s;\n}\n\n/* Join an array of C strings using the specified separator (also a C string).\n * Returns the result as an sds string. */\nsds sdsjoin(char **argv, int argc, char *sep) {\n    sds join = sdsempty();\n    int j;\n\n    for (j = 0; j < argc; j++) {\n        join = sdscat(join, argv[j]);\n        if (j != argc-1) join = sdscat(join,sep);\n    }\n    return join;\n}\n\n/* Like sdsjoin, but joins an array of SDS strings. */\nsds sdsjoinsds(sds *argv, int argc, const char *sep, size_t seplen) {\n    sds join = sdsempty();\n    int j;\n\n    for (j = 0; j < argc; j++) {\n        join = sdscatsds(join, argv[j]);\n        if (j != argc-1) join = sdscatlen(join,sep,seplen);\n    }\n    return join;\n}\n\n/* Wrappers to the allocators used by SDS. Note that SDS will actually\n * just use the macros defined into sdsalloc.h in order to avoid to pay\n * the overhead of function calls. Here we define these wrappers only for\n * the programs SDS is linked to, if they want to touch the SDS internals\n * even if they use a different allocator. */\nvoid *sds_malloc(size_t size) { return s_malloc(size); }\nvoid *sds_realloc(void *ptr, size_t size) { return s_realloc(ptr,size); }\nvoid sds_free(void *ptr) { s_free(ptr); }\n\n#if defined(SDS_TEST_MAIN)\n#include <stdio.h>\n#include \"testhelp.h\"\n#include \"limits.h\"\n\n#define UNUSED(x) (void)(x)\nint sdsTest(void) {\n    {\n        sds x = sdsnew(\"foo\"), y;\n\n        test_cond(\"Create a string and obtain the length\",\n            sdslen(x) == 3 && memcmp(x,\"foo\\0\",4) == 0)\n\n        sdsfree(x);\n        x = sdsnewlen(\"foo\",2);\n        test_cond(\"Create a string with specified length\",\n            sdslen(x) == 2 && memcmp(x,\"fo\\0\",3) == 0)\n\n        x = sdscat(x,\"bar\");\n        test_cond(\"Strings concatenation\",\n            sdslen(x) == 5 && memcmp(x,\"fobar\\0\",6) == 0);\n\n        x = sdscpy(x,\"a\");\n        test_cond(\"sdscpy() against an originally longer string\",\n            sdslen(x) == 1 && memcmp(x,\"a\\0\",2) == 0)\n\n        x = sdscpy(x,\"xyzxxxxxxxxxxyyyyyyyyyykkkkkkkkkk\");\n        test_cond(\"sdscpy() against an originally shorter string\",\n            sdslen(x) == 33 &&\n            memcmp(x,\"xyzxxxxxxxxxxyyyyyyyyyykkkkkkkkkk\\0\",33) == 0)\n\n        sdsfree(x);\n        x = sdscatprintf(sdsempty(),\"%d\",123);\n        test_cond(\"sdscatprintf() seems working in the base case\",\n            sdslen(x) == 3 && memcmp(x,\"123\\0\",4) == 0)\n\n        sdsfree(x);\n        x = sdsnew(\"--\");\n        x = sdscatfmt(x, \"Hello %s World %I,%I--\", \"Hi!\", LLONG_MIN,LLONG_MAX);\n        test_cond(\"sdscatfmt() seems working in the base case\",\n            sdslen(x) == 60 &&\n            memcmp(x,\"--Hello Hi! World -9223372036854775808,\"\n                     \"9223372036854775807--\",60) == 0)\n        printf(\"[%s]\\n\",x);\n\n        sdsfree(x);\n        x = sdsnew(\"--\");\n        x = sdscatfmt(x, \"%u,%U--\", UINT_MAX, ULLONG_MAX);\n        test_cond(\"sdscatfmt() seems working with unsigned numbers\",\n            sdslen(x) == 35 &&\n            memcmp(x,\"--4294967295,18446744073709551615--\",35) == 0)\n\n        sdsfree(x);\n        x = sdsnew(\" x \");\n        sdstrim(x,\" x\");\n        test_cond(\"sdstrim() works when all chars match\",\n            sdslen(x) == 0)\n\n        sdsfree(x);\n        x = sdsnew(\" x \");\n        sdstrim(x,\" \");\n        test_cond(\"sdstrim() works when a single char remains\",\n            sdslen(x) == 1 && x[0] == 'x')\n\n        sdsfree(x);\n        x = sdsnew(\"xxciaoyyy\");\n        sdstrim(x,\"xy\");\n        test_cond(\"sdstrim() correctly trims characters\",\n            sdslen(x) == 4 && memcmp(x,\"ciao\\0\",5) == 0)\n\n        y = sdsdup(x);\n        sdsrange(y,1,1);\n        test_cond(\"sdsrange(...,1,1)\",\n            sdslen(y) == 1 && memcmp(y,\"i\\0\",2) == 0)\n\n        sdsfree(y);\n        y = sdsdup(x);\n        sdsrange(y,1,-1);\n        test_cond(\"sdsrange(...,1,-1)\",\n            sdslen(y) == 3 && memcmp(y,\"iao\\0\",4) == 0)\n\n        sdsfree(y);\n        y = sdsdup(x);\n        sdsrange(y,-2,-1);\n        test_cond(\"sdsrange(...,-2,-1)\",\n            sdslen(y) == 2 && memcmp(y,\"ao\\0\",3) == 0)\n\n        sdsfree(y);\n        y = sdsdup(x);\n        sdsrange(y,2,1);\n        test_cond(\"sdsrange(...,2,1)\",\n            sdslen(y) == 0 && memcmp(y,\"\\0\",1) == 0)\n\n        sdsfree(y);\n        y = sdsdup(x);\n        sdsrange(y,1,100);\n        test_cond(\"sdsrange(...,1,100)\",\n            sdslen(y) == 3 && memcmp(y,\"iao\\0\",4) == 0)\n\n        sdsfree(y);\n        y = sdsdup(x);\n        sdsrange(y,100,100);\n        test_cond(\"sdsrange(...,100,100)\",\n            sdslen(y) == 0 && memcmp(y,\"\\0\",1) == 0)\n\n        sdsfree(y);\n        sdsfree(x);\n        x = sdsnew(\"foo\");\n        y = sdsnew(\"foa\");\n        test_cond(\"sdscmp(foo,foa)\", sdscmp(x,y) > 0)\n\n        sdsfree(y);\n        sdsfree(x);\n        x = sdsnew(\"bar\");\n        y = sdsnew(\"bar\");\n        test_cond(\"sdscmp(bar,bar)\", sdscmp(x,y) == 0)\n\n        sdsfree(y);\n        sdsfree(x);\n        x = sdsnew(\"aar\");\n        y = sdsnew(\"bar\");\n        test_cond(\"sdscmp(bar,bar)\", sdscmp(x,y) < 0)\n\n        sdsfree(y);\n        sdsfree(x);\n        x = sdsnewlen(\"\\a\\n\\0foo\\r\",7);\n        y = sdscatrepr(sdsempty(),x,sdslen(x));\n        test_cond(\"sdscatrepr(...data...)\",\n            memcmp(y,\"\\\"\\\\a\\\\n\\\\x00foo\\\\r\\\"\",15) == 0)\n\n        {\n            unsigned int oldfree;\n            char *p;\n            int step = 10, j, i;\n\n            sdsfree(x);\n            sdsfree(y);\n            x = sdsnew(\"0\");\n            test_cond(\"sdsnew() free/len buffers\", sdslen(x) == 1 && sdsavail(x) == 0);\n\n            /* Run the test a few times in order to hit the first two\n             * SDS header types. */\n            for (i = 0; i < 10; i++) {\n                int oldlen = sdslen(x);\n                x = sdsMakeRoomFor(x,step);\n                int type = x[-1]&SDS_TYPE_MASK;\n\n                test_cond(\"sdsMakeRoomFor() len\", sdslen(x) == oldlen);\n                if (type != SDS_TYPE_5) {\n                    test_cond(\"sdsMakeRoomFor() free\", sdsavail(x) >= step);\n                    oldfree = sdsavail(x);\n                }\n                p = x+oldlen;\n                for (j = 0; j < step; j++) {\n                    p[j] = 'A'+j;\n                }\n                sdsIncrLen(x,step);\n            }\n            test_cond(\"sdsMakeRoomFor() content\",\n                memcmp(\"0ABCDEFGHIJABCDEFGHIJABCDEFGHIJABCDEFGHIJABCDEFGHIJABCDEFGHIJABCDEFGHIJABCDEFGHIJABCDEFGHIJABCDEFGHIJ\",x,101) == 0);\n            test_cond(\"sdsMakeRoomFor() final length\",sdslen(x)==101);\n\n            sdsfree(x);\n        }\n    }\n    test_report()\n    return 0;\n}\n#endif\n\n#ifdef SDS_TEST_MAIN\nint main(void) {\n    return sdsTest();\n}\n#endif\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.8/deps/hiredis/sds.h",
    "content": "/* SDSLib 2.0 -- A C dynamic strings library\n *\n * Copyright (c) 2006-2015, Salvatore Sanfilippo <antirez at gmail dot com>\n * Copyright (c) 2015, Oran Agra\n * Copyright (c) 2015, Redis Labs, Inc\n * All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions are met:\n *\n *   * Redistributions of source code must retain the above copyright notice,\n *     this list of conditions and the following disclaimer.\n *   * Redistributions in binary form must reproduce the above copyright\n *     notice, this list of conditions and the following disclaimer in the\n *     documentation and/or other materials provided with the distribution.\n *   * Neither the name of Redis nor the names of its contributors may be used\n *     to endorse or promote products derived from this software without\n *     specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\"\n * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\n * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE\n * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR\n * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF\n * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS\n * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN\n * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)\n * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE\n * POSSIBILITY OF SUCH DAMAGE.\n */\n\n#ifndef __SDS_H\n#define __SDS_H\n\n#define SDS_MAX_PREALLOC (1024*1024)\n\n#include <sys/types.h>\n#include <stdarg.h>\n#include <stdint.h>\n\ntypedef char *sds;\n\n/* Note: sdshdr5 is never used, we just access the flags byte directly.\n * However is here to document the layout of type 5 SDS strings. */\nstruct __attribute__ ((__packed__)) sdshdr5 {\n    unsigned char flags; /* 3 lsb of type, and 5 msb of string length */\n    char buf[];\n};\nstruct __attribute__ ((__packed__)) sdshdr8 {\n    uint8_t len; /* used */\n    uint8_t alloc; /* excluding the header and null terminator */\n    unsigned char flags; /* 3 lsb of type, 5 unused bits */\n    char buf[];\n};\nstruct __attribute__ ((__packed__)) sdshdr16 {\n    uint16_t len; /* used */\n    uint16_t alloc; /* excluding the header and null terminator */\n    unsigned char flags; /* 3 lsb of type, 5 unused bits */\n    char buf[];\n};\nstruct __attribute__ ((__packed__)) sdshdr32 {\n    uint32_t len; /* used */\n    uint32_t alloc; /* excluding the header and null terminator */\n    unsigned char flags; /* 3 lsb of type, 5 unused bits */\n    char buf[];\n};\nstruct __attribute__ ((__packed__)) sdshdr64 {\n    uint64_t len; /* used */\n    uint64_t alloc; /* excluding the header and null terminator */\n    unsigned char flags; /* 3 lsb of type, 5 unused bits */\n    char buf[];\n};\n\n#define SDS_TYPE_5  0\n#define SDS_TYPE_8  1\n#define SDS_TYPE_16 2\n#define SDS_TYPE_32 3\n#define SDS_TYPE_64 4\n#define SDS_TYPE_MASK 7\n#define SDS_TYPE_BITS 3\n#define SDS_HDR_VAR(T,s) struct sdshdr##T *sh = (void*)((s)-(sizeof(struct sdshdr##T)));\n#define SDS_HDR(T,s) ((struct sdshdr##T *)((s)-(sizeof(struct sdshdr##T))))\n#define SDS_TYPE_5_LEN(f) ((f)>>SDS_TYPE_BITS)\n\nstatic inline size_t sdslen(const sds s) {\n    unsigned char flags = s[-1];\n    switch(flags&SDS_TYPE_MASK) {\n        case SDS_TYPE_5:\n            return SDS_TYPE_5_LEN(flags);\n        case SDS_TYPE_8:\n            return SDS_HDR(8,s)->len;\n        case SDS_TYPE_16:\n            return SDS_HDR(16,s)->len;\n        case SDS_TYPE_32:\n            return SDS_HDR(32,s)->len;\n        case SDS_TYPE_64:\n            return SDS_HDR(64,s)->len;\n    }\n    return 0;\n}\n\nstatic inline size_t sdsavail(const sds s) {\n    unsigned char flags = s[-1];\n    switch(flags&SDS_TYPE_MASK) {\n        case SDS_TYPE_5: {\n            return 0;\n        }\n        case SDS_TYPE_8: {\n            SDS_HDR_VAR(8,s);\n            return sh->alloc - sh->len;\n        }\n        case SDS_TYPE_16: {\n            SDS_HDR_VAR(16,s);\n            return sh->alloc - sh->len;\n        }\n        case SDS_TYPE_32: {\n            SDS_HDR_VAR(32,s);\n            return sh->alloc - sh->len;\n        }\n        case SDS_TYPE_64: {\n            SDS_HDR_VAR(64,s);\n            return sh->alloc - sh->len;\n        }\n    }\n    return 0;\n}\n\nstatic inline void sdssetlen(sds s, size_t newlen) {\n    unsigned char flags = s[-1];\n    switch(flags&SDS_TYPE_MASK) {\n        case SDS_TYPE_5:\n            {\n                unsigned char *fp = ((unsigned char*)s)-1;\n                *fp = SDS_TYPE_5 | (newlen << SDS_TYPE_BITS);\n            }\n            break;\n        case SDS_TYPE_8:\n            SDS_HDR(8,s)->len = newlen;\n            break;\n        case SDS_TYPE_16:\n            SDS_HDR(16,s)->len = newlen;\n            break;\n        case SDS_TYPE_32:\n            SDS_HDR(32,s)->len = newlen;\n            break;\n        case SDS_TYPE_64:\n            SDS_HDR(64,s)->len = newlen;\n            break;\n    }\n}\n\nstatic inline void sdsinclen(sds s, size_t inc) {\n    unsigned char flags = s[-1];\n    switch(flags&SDS_TYPE_MASK) {\n        case SDS_TYPE_5:\n            {\n                unsigned char *fp = ((unsigned char*)s)-1;\n                unsigned char newlen = SDS_TYPE_5_LEN(flags)+inc;\n                *fp = SDS_TYPE_5 | (newlen << SDS_TYPE_BITS);\n            }\n            break;\n        case SDS_TYPE_8:\n            SDS_HDR(8,s)->len += inc;\n            break;\n        case SDS_TYPE_16:\n            SDS_HDR(16,s)->len += inc;\n            break;\n        case SDS_TYPE_32:\n            SDS_HDR(32,s)->len += inc;\n            break;\n        case SDS_TYPE_64:\n            SDS_HDR(64,s)->len += inc;\n            break;\n    }\n}\n\n/* sdsalloc() = sdsavail() + sdslen() */\nstatic inline size_t sdsalloc(const sds s) {\n    unsigned char flags = s[-1];\n    switch(flags&SDS_TYPE_MASK) {\n        case SDS_TYPE_5:\n            return SDS_TYPE_5_LEN(flags);\n        case SDS_TYPE_8:\n            return SDS_HDR(8,s)->alloc;\n        case SDS_TYPE_16:\n            return SDS_HDR(16,s)->alloc;\n        case SDS_TYPE_32:\n            return SDS_HDR(32,s)->alloc;\n        case SDS_TYPE_64:\n            return SDS_HDR(64,s)->alloc;\n    }\n    return 0;\n}\n\nstatic inline void sdssetalloc(sds s, size_t newlen) {\n    unsigned char flags = s[-1];\n    switch(flags&SDS_TYPE_MASK) {\n        case SDS_TYPE_5:\n            /* Nothing to do, this type has no total allocation info. */\n            break;\n        case SDS_TYPE_8:\n            SDS_HDR(8,s)->alloc = newlen;\n            break;\n        case SDS_TYPE_16:\n            SDS_HDR(16,s)->alloc = newlen;\n            break;\n        case SDS_TYPE_32:\n            SDS_HDR(32,s)->alloc = newlen;\n            break;\n        case SDS_TYPE_64:\n            SDS_HDR(64,s)->alloc = newlen;\n            break;\n    }\n}\n\nsds sdsnewlen(const void *init, size_t initlen);\nsds sdsnew(const char *init);\nsds sdsempty(void);\nsds sdsdup(const sds s);\nvoid sdsfree(sds s);\nsds sdsgrowzero(sds s, size_t len);\nsds sdscatlen(sds s, const void *t, size_t len);\nsds sdscat(sds s, const char *t);\nsds sdscatsds(sds s, const sds t);\nsds sdscpylen(sds s, const char *t, size_t len);\nsds sdscpy(sds s, const char *t);\n\nsds sdscatvprintf(sds s, const char *fmt, va_list ap);\n#ifdef __GNUC__\nsds sdscatprintf(sds s, const char *fmt, ...)\n    __attribute__((format(printf, 2, 3)));\n#else\nsds sdscatprintf(sds s, const char *fmt, ...);\n#endif\n\nsds sdscatfmt(sds s, char const *fmt, ...);\nsds sdstrim(sds s, const char *cset);\nvoid sdsrange(sds s, int start, int end);\nvoid sdsupdatelen(sds s);\nvoid sdsclear(sds s);\nint sdscmp(const sds s1, const sds s2);\nsds *sdssplitlen(const char *s, int len, const char *sep, int seplen, int *count);\nvoid sdsfreesplitres(sds *tokens, int count);\nvoid sdstolower(sds s);\nvoid sdstoupper(sds s);\nsds sdsfromlonglong(long long value);\nsds sdscatrepr(sds s, const char *p, size_t len);\nsds *sdssplitargs(const char *line, int *argc);\nsds sdsmapchars(sds s, const char *from, const char *to, size_t setlen);\nsds sdsjoin(char **argv, int argc, char *sep);\nsds sdsjoinsds(sds *argv, int argc, const char *sep, size_t seplen);\n\n/* Low level functions exposed to the user API */\nsds sdsMakeRoomFor(sds s, size_t addlen);\nvoid sdsIncrLen(sds s, int incr);\nsds sdsRemoveFreeSpace(sds s);\nsize_t sdsAllocSize(sds s);\nvoid *sdsAllocPtr(sds s);\n\n/* Export the allocator used by SDS to the program using SDS.\n * Sometimes the program SDS is linked to, may use a different set of\n * allocators, but may want to allocate or free things that SDS will\n * respectively free or allocate. */\nvoid *sds_malloc(size_t size);\nvoid *sds_realloc(void *ptr, size_t size);\nvoid sds_free(void *ptr);\n\n#ifdef REDIS_TEST\nint sdsTest(int argc, char *argv[]);\n#endif\n\n#endif\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.8/deps/hiredis/sdsalloc.h",
    "content": "/* SDSLib 2.0 -- A C dynamic strings library\n *\n * Copyright (c) 2006-2015, Salvatore Sanfilippo <antirez at gmail dot com>\n * Copyright (c) 2015, Redis Labs, Inc\n * All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions are met:\n *\n *   * Redistributions of source code must retain the above copyright notice,\n *     this list of conditions and the following disclaimer.\n *   * Redistributions in binary form must reproduce the above copyright\n *     notice, this list of conditions and the following disclaimer in the\n *     documentation and/or other materials provided with the distribution.\n *   * Neither the name of Redis nor the names of its contributors may be used\n *     to endorse or promote products derived from this software without\n *     specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\"\n * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\n * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE\n * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR\n * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF\n * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS\n * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN\n * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)\n * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE\n * POSSIBILITY OF SUCH DAMAGE.\n */\n\n/* SDS allocator selection.\n *\n * This file is used in order to change the SDS allocator at compile time.\n * Just define the following defines to what you want to use. Also add\n * the include of your alternate allocator if needed (not needed in order\n * to use the default libc allocator). */\n\n#include \"zmalloc.h\"\n#define s_malloc zmalloc\n#define s_realloc zrealloc\n#define s_free zfree\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.8/deps/hiredis/test.c",
    "content": "#include \"fmacros.h\"\n#include <stdio.h>\n#include <stdlib.h>\n#include <string.h>\n#include <strings.h>\n#include <sys/time.h>\n#include <assert.h>\n#include <unistd.h>\n#include <signal.h>\n#include <errno.h>\n#include <limits.h>\n\n#include \"hiredis.h\"\n\nenum connection_type {\n    CONN_TCP,\n    CONN_UNIX,\n    CONN_FD\n};\n\nstruct config {\n    enum connection_type type;\n\n    struct {\n        const char *host;\n        int port;\n        struct timeval timeout;\n    } tcp;\n\n    struct {\n        const char *path;\n    } unix;\n};\n\n/* The following lines make up our testing \"framework\" :) */\nstatic int tests = 0, fails = 0;\n#define test(_s) { printf(\"#%02d \", ++tests); printf(_s); }\n#define test_cond(_c) if(_c) printf(\"\\033[0;32mPASSED\\033[0;0m\\n\"); else {printf(\"\\033[0;31mFAILED\\033[0;0m\\n\"); fails++;}\n\nstatic long long usec(void) {\n    struct timeval tv;\n    gettimeofday(&tv,NULL);\n    return (((long long)tv.tv_sec)*1000000)+tv.tv_usec;\n}\n\nstatic redisContext *select_database(redisContext *c) {\n    redisReply *reply;\n\n    /* Switch to DB 9 for testing, now that we know we can chat. */\n    reply = redisCommand(c,\"SELECT 9\");\n    assert(reply != NULL);\n    freeReplyObject(reply);\n\n    /* Make sure the DB is empty */\n    reply = redisCommand(c,\"DBSIZE\");\n    assert(reply != NULL);\n    if (reply->type == REDIS_REPLY_INTEGER && reply->integer == 0) {\n        /* Awesome, DB 9 is empty and we can continue. */\n        freeReplyObject(reply);\n    } else {\n        printf(\"Database #9 is not empty, test can not continue\\n\");\n        exit(1);\n    }\n\n    return c;\n}\n\nstatic int disconnect(redisContext *c, int keep_fd) {\n    redisReply *reply;\n\n    /* Make sure we're on DB 9. */\n    reply = redisCommand(c,\"SELECT 9\");\n    assert(reply != NULL);\n    freeReplyObject(reply);\n    reply = redisCommand(c,\"FLUSHDB\");\n    assert(reply != NULL);\n    freeReplyObject(reply);\n\n    /* Free the context as well, but keep the fd if requested. */\n    if (keep_fd)\n        return redisFreeKeepFd(c);\n    redisFree(c);\n    return -1;\n}\n\nstatic redisContext *connect(struct config config) {\n    redisContext *c = NULL;\n\n    if (config.type == CONN_TCP) {\n        c = redisConnect(config.tcp.host, config.tcp.port);\n    } else if (config.type == CONN_UNIX) {\n        c = redisConnectUnix(config.unix.path);\n    } else if (config.type == CONN_FD) {\n        /* Create a dummy connection just to get an fd to inherit */\n        redisContext *dummy_ctx = redisConnectUnix(config.unix.path);\n        if (dummy_ctx) {\n            int fd = disconnect(dummy_ctx, 1);\n            printf(\"Connecting to inherited fd %d\\n\", fd);\n            c = redisConnectFd(fd);\n        }\n    } else {\n        assert(NULL);\n    }\n\n    if (c == NULL) {\n        printf(\"Connection error: can't allocate redis context\\n\");\n        exit(1);\n    } else if (c->err) {\n        printf(\"Connection error: %s\\n\", c->errstr);\n        exit(1);\n    }\n\n    return select_database(c);\n}\n\nstatic void test_format_commands(void) {\n    char *cmd;\n    int len;\n\n    test(\"Format command without interpolation: \");\n    len = redisFormatCommand(&cmd,\"SET foo bar\");\n    test_cond(strncmp(cmd,\"*3\\r\\n$3\\r\\nSET\\r\\n$3\\r\\nfoo\\r\\n$3\\r\\nbar\\r\\n\",len) == 0 &&\n        len == 4+4+(3+2)+4+(3+2)+4+(3+2));\n    free(cmd);\n\n    test(\"Format command with %%s string interpolation: \");\n    len = redisFormatCommand(&cmd,\"SET %s %s\",\"foo\",\"bar\");\n    test_cond(strncmp(cmd,\"*3\\r\\n$3\\r\\nSET\\r\\n$3\\r\\nfoo\\r\\n$3\\r\\nbar\\r\\n\",len) == 0 &&\n        len == 4+4+(3+2)+4+(3+2)+4+(3+2));\n    free(cmd);\n\n    test(\"Format command with %%s and an empty string: \");\n    len = redisFormatCommand(&cmd,\"SET %s %s\",\"foo\",\"\");\n    test_cond(strncmp(cmd,\"*3\\r\\n$3\\r\\nSET\\r\\n$3\\r\\nfoo\\r\\n$0\\r\\n\\r\\n\",len) == 0 &&\n        len == 4+4+(3+2)+4+(3+2)+4+(0+2));\n    free(cmd);\n\n    test(\"Format command with an empty string in between proper interpolations: \");\n    len = redisFormatCommand(&cmd,\"SET %s %s\",\"\",\"foo\");\n    test_cond(strncmp(cmd,\"*3\\r\\n$3\\r\\nSET\\r\\n$0\\r\\n\\r\\n$3\\r\\nfoo\\r\\n\",len) == 0 &&\n        len == 4+4+(3+2)+4+(0+2)+4+(3+2));\n    free(cmd);\n\n    test(\"Format command with %%b string interpolation: \");\n    len = redisFormatCommand(&cmd,\"SET %b %b\",\"foo\",(size_t)3,\"b\\0r\",(size_t)3);\n    test_cond(strncmp(cmd,\"*3\\r\\n$3\\r\\nSET\\r\\n$3\\r\\nfoo\\r\\n$3\\r\\nb\\0r\\r\\n\",len) == 0 &&\n        len == 4+4+(3+2)+4+(3+2)+4+(3+2));\n    free(cmd);\n\n    test(\"Format command with %%b and an empty string: \");\n    len = redisFormatCommand(&cmd,\"SET %b %b\",\"foo\",(size_t)3,\"\",(size_t)0);\n    test_cond(strncmp(cmd,\"*3\\r\\n$3\\r\\nSET\\r\\n$3\\r\\nfoo\\r\\n$0\\r\\n\\r\\n\",len) == 0 &&\n        len == 4+4+(3+2)+4+(3+2)+4+(0+2));\n    free(cmd);\n\n    test(\"Format command with literal %%: \");\n    len = redisFormatCommand(&cmd,\"SET %% %%\");\n    test_cond(strncmp(cmd,\"*3\\r\\n$3\\r\\nSET\\r\\n$1\\r\\n%\\r\\n$1\\r\\n%\\r\\n\",len) == 0 &&\n        len == 4+4+(3+2)+4+(1+2)+4+(1+2));\n    free(cmd);\n\n    /* Vararg width depends on the type. These tests make sure that the\n     * width is correctly determined using the format and subsequent varargs\n     * can correctly be interpolated. */\n#define INTEGER_WIDTH_TEST(fmt, type) do {                                                \\\n    type value = 123;                                                                     \\\n    test(\"Format command with printf-delegation (\" #type \"): \");                          \\\n    len = redisFormatCommand(&cmd,\"key:%08\" fmt \" str:%s\", value, \"hello\");               \\\n    test_cond(strncmp(cmd,\"*2\\r\\n$12\\r\\nkey:00000123\\r\\n$9\\r\\nstr:hello\\r\\n\",len) == 0 && \\\n        len == 4+5+(12+2)+4+(9+2));                                                       \\\n    free(cmd);                                                                            \\\n} while(0)\n\n#define FLOAT_WIDTH_TEST(type) do {                                                       \\\n    type value = 123.0;                                                                   \\\n    test(\"Format command with printf-delegation (\" #type \"): \");                          \\\n    len = redisFormatCommand(&cmd,\"key:%08.3f str:%s\", value, \"hello\");                   \\\n    test_cond(strncmp(cmd,\"*2\\r\\n$12\\r\\nkey:0123.000\\r\\n$9\\r\\nstr:hello\\r\\n\",len) == 0 && \\\n        len == 4+5+(12+2)+4+(9+2));                                                       \\\n    free(cmd);                                                                            \\\n} while(0)\n\n    INTEGER_WIDTH_TEST(\"d\", int);\n    INTEGER_WIDTH_TEST(\"hhd\", char);\n    INTEGER_WIDTH_TEST(\"hd\", short);\n    INTEGER_WIDTH_TEST(\"ld\", long);\n    INTEGER_WIDTH_TEST(\"lld\", long long);\n    INTEGER_WIDTH_TEST(\"u\", unsigned int);\n    INTEGER_WIDTH_TEST(\"hhu\", unsigned char);\n    INTEGER_WIDTH_TEST(\"hu\", unsigned short);\n    INTEGER_WIDTH_TEST(\"lu\", unsigned long);\n    INTEGER_WIDTH_TEST(\"llu\", unsigned long long);\n    FLOAT_WIDTH_TEST(float);\n    FLOAT_WIDTH_TEST(double);\n\n    test(\"Format command with invalid printf format: \");\n    len = redisFormatCommand(&cmd,\"key:%08p %b\",(void*)1234,\"foo\",(size_t)3);\n    test_cond(len == -1);\n\n    const char *argv[3];\n    argv[0] = \"SET\";\n    argv[1] = \"foo\\0xxx\";\n    argv[2] = \"bar\";\n    size_t lens[3] = { 3, 7, 3 };\n    int argc = 3;\n\n    test(\"Format command by passing argc/argv without lengths: \");\n    len = redisFormatCommandArgv(&cmd,argc,argv,NULL);\n    test_cond(strncmp(cmd,\"*3\\r\\n$3\\r\\nSET\\r\\n$3\\r\\nfoo\\r\\n$3\\r\\nbar\\r\\n\",len) == 0 &&\n        len == 4+4+(3+2)+4+(3+2)+4+(3+2));\n    free(cmd);\n\n    test(\"Format command by passing argc/argv with lengths: \");\n    len = redisFormatCommandArgv(&cmd,argc,argv,lens);\n    test_cond(strncmp(cmd,\"*3\\r\\n$3\\r\\nSET\\r\\n$7\\r\\nfoo\\0xxx\\r\\n$3\\r\\nbar\\r\\n\",len) == 0 &&\n        len == 4+4+(3+2)+4+(7+2)+4+(3+2));\n    free(cmd);\n}\n\nstatic void test_append_formatted_commands(struct config config) {\n    redisContext *c;\n    redisReply *reply;\n    char *cmd;\n    int len;\n\n    c = connect(config);\n\n    test(\"Append format command: \");\n\n    len = redisFormatCommand(&cmd, \"SET foo bar\");\n\n    test_cond(redisAppendFormattedCommand(c, cmd, len) == REDIS_OK);\n\n    assert(redisGetReply(c, (void*)&reply) == REDIS_OK);\n\n    free(cmd);\n    freeReplyObject(reply);\n\n    disconnect(c, 0);\n}\n\nstatic void test_reply_reader(void) {\n    redisReader *reader;\n    void *reply;\n    int ret;\n    int i;\n\n    test(\"Error handling in reply parser: \");\n    reader = redisReaderCreate();\n    redisReaderFeed(reader,(char*)\"@foo\\r\\n\",6);\n    ret = redisReaderGetReply(reader,NULL);\n    test_cond(ret == REDIS_ERR &&\n              strcasecmp(reader->errstr,\"Protocol error, got \\\"@\\\" as reply type byte\") == 0);\n    redisReaderFree(reader);\n\n    /* when the reply already contains multiple items, they must be free'd\n     * on an error. valgrind will bark when this doesn't happen. */\n    test(\"Memory cleanup in reply parser: \");\n    reader = redisReaderCreate();\n    redisReaderFeed(reader,(char*)\"*2\\r\\n\",4);\n    redisReaderFeed(reader,(char*)\"$5\\r\\nhello\\r\\n\",11);\n    redisReaderFeed(reader,(char*)\"@foo\\r\\n\",6);\n    ret = redisReaderGetReply(reader,NULL);\n    test_cond(ret == REDIS_ERR &&\n              strcasecmp(reader->errstr,\"Protocol error, got \\\"@\\\" as reply type byte\") == 0);\n    redisReaderFree(reader);\n\n    test(\"Set error on nested multi bulks with depth > 7: \");\n    reader = redisReaderCreate();\n\n    for (i = 0; i < 9; i++) {\n        redisReaderFeed(reader,(char*)\"*1\\r\\n\",4);\n    }\n\n    ret = redisReaderGetReply(reader,NULL);\n    test_cond(ret == REDIS_ERR &&\n              strncasecmp(reader->errstr,\"No support for\",14) == 0);\n    redisReaderFree(reader);\n\n    test(\"Works with NULL functions for reply: \");\n    reader = redisReaderCreate();\n    reader->fn = NULL;\n    redisReaderFeed(reader,(char*)\"+OK\\r\\n\",5);\n    ret = redisReaderGetReply(reader,&reply);\n    test_cond(ret == REDIS_OK && reply == (void*)REDIS_REPLY_STATUS);\n    redisReaderFree(reader);\n\n    test(\"Works when a single newline (\\\\r\\\\n) covers two calls to feed: \");\n    reader = redisReaderCreate();\n    reader->fn = NULL;\n    redisReaderFeed(reader,(char*)\"+OK\\r\",4);\n    ret = redisReaderGetReply(reader,&reply);\n    assert(ret == REDIS_OK && reply == NULL);\n    redisReaderFeed(reader,(char*)\"\\n\",1);\n    ret = redisReaderGetReply(reader,&reply);\n    test_cond(ret == REDIS_OK && reply == (void*)REDIS_REPLY_STATUS);\n    redisReaderFree(reader);\n\n    test(\"Don't reset state after protocol error: \");\n    reader = redisReaderCreate();\n    reader->fn = NULL;\n    redisReaderFeed(reader,(char*)\"x\",1);\n    ret = redisReaderGetReply(reader,&reply);\n    assert(ret == REDIS_ERR);\n    ret = redisReaderGetReply(reader,&reply);\n    test_cond(ret == REDIS_ERR && reply == NULL);\n    redisReaderFree(reader);\n\n    /* Regression test for issue #45 on GitHub. */\n    test(\"Don't do empty allocation for empty multi bulk: \");\n    reader = redisReaderCreate();\n    redisReaderFeed(reader,(char*)\"*0\\r\\n\",4);\n    ret = redisReaderGetReply(reader,&reply);\n    test_cond(ret == REDIS_OK &&\n        ((redisReply*)reply)->type == REDIS_REPLY_ARRAY &&\n        ((redisReply*)reply)->elements == 0);\n    freeReplyObject(reply);\n    redisReaderFree(reader);\n}\n\nstatic void test_blocking_connection_errors(void) {\n    redisContext *c;\n\n    test(\"Returns error when host cannot be resolved: \");\n    c = redisConnect((char*)\"idontexist.local\", 6379);\n    test_cond(c->err == REDIS_ERR_OTHER &&\n        (strcmp(c->errstr,\"Name or service not known\") == 0 ||\n         strcmp(c->errstr,\"Can't resolve: idontexist.local\") == 0 ||\n         strcmp(c->errstr,\"nodename nor servname provided, or not known\") == 0 ||\n         strcmp(c->errstr,\"No address associated with hostname\") == 0 ||\n         strcmp(c->errstr,\"no address associated with name\") == 0));\n    redisFree(c);\n\n    test(\"Returns error when the port is not open: \");\n    c = redisConnect((char*)\"localhost\", 1);\n    test_cond(c->err == REDIS_ERR_IO &&\n        strcmp(c->errstr,\"Connection refused\") == 0);\n    redisFree(c);\n\n    test(\"Returns error when the unix socket path doesn't accept connections: \");\n    c = redisConnectUnix((char*)\"/tmp/idontexist.sock\");\n    test_cond(c->err == REDIS_ERR_IO); /* Don't care about the message... */\n    redisFree(c);\n}\n\nstatic void test_blocking_connection(struct config config) {\n    redisContext *c;\n    redisReply *reply;\n\n    c = connect(config);\n\n    test(\"Is able to deliver commands: \");\n    reply = redisCommand(c,\"PING\");\n    test_cond(reply->type == REDIS_REPLY_STATUS &&\n        strcasecmp(reply->str,\"pong\") == 0)\n    freeReplyObject(reply);\n\n    test(\"Is a able to send commands verbatim: \");\n    reply = redisCommand(c,\"SET foo bar\");\n    test_cond (reply->type == REDIS_REPLY_STATUS &&\n        strcasecmp(reply->str,\"ok\") == 0)\n    freeReplyObject(reply);\n\n    test(\"%%s String interpolation works: \");\n    reply = redisCommand(c,\"SET %s %s\",\"foo\",\"hello world\");\n    freeReplyObject(reply);\n    reply = redisCommand(c,\"GET foo\");\n    test_cond(reply->type == REDIS_REPLY_STRING &&\n        strcmp(reply->str,\"hello world\") == 0);\n    freeReplyObject(reply);\n\n    test(\"%%b String interpolation works: \");\n    reply = redisCommand(c,\"SET %b %b\",\"foo\",(size_t)3,\"hello\\x00world\",(size_t)11);\n    freeReplyObject(reply);\n    reply = redisCommand(c,\"GET foo\");\n    test_cond(reply->type == REDIS_REPLY_STRING &&\n        memcmp(reply->str,\"hello\\x00world\",11) == 0)\n\n    test(\"Binary reply length is correct: \");\n    test_cond(reply->len == 11)\n    freeReplyObject(reply);\n\n    test(\"Can parse nil replies: \");\n    reply = redisCommand(c,\"GET nokey\");\n    test_cond(reply->type == REDIS_REPLY_NIL)\n    freeReplyObject(reply);\n\n    /* test 7 */\n    test(\"Can parse integer replies: \");\n    reply = redisCommand(c,\"INCR mycounter\");\n    test_cond(reply->type == REDIS_REPLY_INTEGER && reply->integer == 1)\n    freeReplyObject(reply);\n\n    test(\"Can parse multi bulk replies: \");\n    freeReplyObject(redisCommand(c,\"LPUSH mylist foo\"));\n    freeReplyObject(redisCommand(c,\"LPUSH mylist bar\"));\n    reply = redisCommand(c,\"LRANGE mylist 0 -1\");\n    test_cond(reply->type == REDIS_REPLY_ARRAY &&\n              reply->elements == 2 &&\n              !memcmp(reply->element[0]->str,\"bar\",3) &&\n              !memcmp(reply->element[1]->str,\"foo\",3))\n    freeReplyObject(reply);\n\n    /* m/e with multi bulk reply *before* other reply.\n     * specifically test ordering of reply items to parse. */\n    test(\"Can handle nested multi bulk replies: \");\n    freeReplyObject(redisCommand(c,\"MULTI\"));\n    freeReplyObject(redisCommand(c,\"LRANGE mylist 0 -1\"));\n    freeReplyObject(redisCommand(c,\"PING\"));\n    reply = (redisCommand(c,\"EXEC\"));\n    test_cond(reply->type == REDIS_REPLY_ARRAY &&\n              reply->elements == 2 &&\n              reply->element[0]->type == REDIS_REPLY_ARRAY &&\n              reply->element[0]->elements == 2 &&\n              !memcmp(reply->element[0]->element[0]->str,\"bar\",3) &&\n              !memcmp(reply->element[0]->element[1]->str,\"foo\",3) &&\n              reply->element[1]->type == REDIS_REPLY_STATUS &&\n              strcasecmp(reply->element[1]->str,\"pong\") == 0);\n    freeReplyObject(reply);\n\n    disconnect(c, 0);\n}\n\nstatic void test_blocking_io_errors(struct config config) {\n    redisContext *c;\n    redisReply *reply;\n    void *_reply;\n    int major, minor;\n\n    /* Connect to target given by config. */\n    c = connect(config);\n    {\n        /* Find out Redis version to determine the path for the next test */\n        const char *field = \"redis_version:\";\n        char *p, *eptr;\n\n        reply = redisCommand(c,\"INFO\");\n        p = strstr(reply->str,field);\n        major = strtol(p+strlen(field),&eptr,10);\n        p = eptr+1; /* char next to the first \".\" */\n        minor = strtol(p,&eptr,10);\n        freeReplyObject(reply);\n    }\n\n    test(\"Returns I/O error when the connection is lost: \");\n    reply = redisCommand(c,\"QUIT\");\n    if (major >= 2 && minor > 0) {\n        /* > 2.0 returns OK on QUIT and read() should be issued once more\n         * to know the descriptor is at EOF. */\n        test_cond(strcasecmp(reply->str,\"OK\") == 0 &&\n            redisGetReply(c,&_reply) == REDIS_ERR);\n        freeReplyObject(reply);\n    } else {\n        test_cond(reply == NULL);\n    }\n\n    /* On 2.0, QUIT will cause the connection to be closed immediately and\n     * the read(2) for the reply on QUIT will set the error to EOF.\n     * On >2.0, QUIT will return with OK and another read(2) needed to be\n     * issued to find out the socket was closed by the server. In both\n     * conditions, the error will be set to EOF. */\n    assert(c->err == REDIS_ERR_EOF &&\n        strcmp(c->errstr,\"Server closed the connection\") == 0);\n    redisFree(c);\n\n    c = connect(config);\n    test(\"Returns I/O error on socket timeout: \");\n    struct timeval tv = { 0, 1000 };\n    assert(redisSetTimeout(c,tv) == REDIS_OK);\n    test_cond(redisGetReply(c,&_reply) == REDIS_ERR &&\n        c->err == REDIS_ERR_IO && errno == EAGAIN);\n    redisFree(c);\n}\n\nstatic void test_invalid_timeout_errors(struct config config) {\n    redisContext *c;\n\n    test(\"Set error when an invalid timeout usec value is given to redisConnectWithTimeout: \");\n\n    config.tcp.timeout.tv_sec = 0;\n    config.tcp.timeout.tv_usec = 10000001;\n\n    c = redisConnectWithTimeout(config.tcp.host, config.tcp.port, config.tcp.timeout);\n\n    test_cond(c->err == REDIS_ERR_IO);\n\n    test(\"Set error when an invalid timeout sec value is given to redisConnectWithTimeout: \");\n\n    config.tcp.timeout.tv_sec = (((LONG_MAX) - 999) / 1000) + 1;\n    config.tcp.timeout.tv_usec = 0;\n\n    c = redisConnectWithTimeout(config.tcp.host, config.tcp.port, config.tcp.timeout);\n\n    test_cond(c->err == REDIS_ERR_IO);\n\n    redisFree(c);\n}\n\nstatic void test_throughput(struct config config) {\n    redisContext *c = connect(config);\n    redisReply **replies;\n    int i, num;\n    long long t1, t2;\n\n    test(\"Throughput:\\n\");\n    for (i = 0; i < 500; i++)\n        freeReplyObject(redisCommand(c,\"LPUSH mylist foo\"));\n\n    num = 1000;\n    replies = malloc(sizeof(redisReply*)*num);\n    t1 = usec();\n    for (i = 0; i < num; i++) {\n        replies[i] = redisCommand(c,\"PING\");\n        assert(replies[i] != NULL && replies[i]->type == REDIS_REPLY_STATUS);\n    }\n    t2 = usec();\n    for (i = 0; i < num; i++) freeReplyObject(replies[i]);\n    free(replies);\n    printf(\"\\t(%dx PING: %.3fs)\\n\", num, (t2-t1)/1000000.0);\n\n    replies = malloc(sizeof(redisReply*)*num);\n    t1 = usec();\n    for (i = 0; i < num; i++) {\n        replies[i] = redisCommand(c,\"LRANGE mylist 0 499\");\n        assert(replies[i] != NULL && replies[i]->type == REDIS_REPLY_ARRAY);\n        assert(replies[i] != NULL && replies[i]->elements == 500);\n    }\n    t2 = usec();\n    for (i = 0; i < num; i++) freeReplyObject(replies[i]);\n    free(replies);\n    printf(\"\\t(%dx LRANGE with 500 elements: %.3fs)\\n\", num, (t2-t1)/1000000.0);\n\n    num = 10000;\n    replies = malloc(sizeof(redisReply*)*num);\n    for (i = 0; i < num; i++)\n        redisAppendCommand(c,\"PING\");\n    t1 = usec();\n    for (i = 0; i < num; i++) {\n        assert(redisGetReply(c, (void*)&replies[i]) == REDIS_OK);\n        assert(replies[i] != NULL && replies[i]->type == REDIS_REPLY_STATUS);\n    }\n    t2 = usec();\n    for (i = 0; i < num; i++) freeReplyObject(replies[i]);\n    free(replies);\n    printf(\"\\t(%dx PING (pipelined): %.3fs)\\n\", num, (t2-t1)/1000000.0);\n\n    replies = malloc(sizeof(redisReply*)*num);\n    for (i = 0; i < num; i++)\n        redisAppendCommand(c,\"LRANGE mylist 0 499\");\n    t1 = usec();\n    for (i = 0; i < num; i++) {\n        assert(redisGetReply(c, (void*)&replies[i]) == REDIS_OK);\n        assert(replies[i] != NULL && replies[i]->type == REDIS_REPLY_ARRAY);\n        assert(replies[i] != NULL && replies[i]->elements == 500);\n    }\n    t2 = usec();\n    for (i = 0; i < num; i++) freeReplyObject(replies[i]);\n    free(replies);\n    printf(\"\\t(%dx LRANGE with 500 elements (pipelined): %.3fs)\\n\", num, (t2-t1)/1000000.0);\n\n    disconnect(c, 0);\n}\n\n// static long __test_callback_flags = 0;\n// static void __test_callback(redisContext *c, void *privdata) {\n//     ((void)c);\n//     /* Shift to detect execution order */\n//     __test_callback_flags <<= 8;\n//     __test_callback_flags |= (long)privdata;\n// }\n//\n// static void __test_reply_callback(redisContext *c, redisReply *reply, void *privdata) {\n//     ((void)c);\n//     /* Shift to detect execution order */\n//     __test_callback_flags <<= 8;\n//     __test_callback_flags |= (long)privdata;\n//     if (reply) freeReplyObject(reply);\n// }\n//\n// static redisContext *__connect_nonblock() {\n//     /* Reset callback flags */\n//     __test_callback_flags = 0;\n//     return redisConnectNonBlock(\"127.0.0.1\", port, NULL);\n// }\n//\n// static void test_nonblocking_connection() {\n//     redisContext *c;\n//     int wdone = 0;\n//\n//     test(\"Calls command callback when command is issued: \");\n//     c = __connect_nonblock();\n//     redisSetCommandCallback(c,__test_callback,(void*)1);\n//     redisCommand(c,\"PING\");\n//     test_cond(__test_callback_flags == 1);\n//     redisFree(c);\n//\n//     test(\"Calls disconnect callback on redisDisconnect: \");\n//     c = __connect_nonblock();\n//     redisSetDisconnectCallback(c,__test_callback,(void*)2);\n//     redisDisconnect(c);\n//     test_cond(__test_callback_flags == 2);\n//     redisFree(c);\n//\n//     test(\"Calls disconnect callback and free callback on redisFree: \");\n//     c = __connect_nonblock();\n//     redisSetDisconnectCallback(c,__test_callback,(void*)2);\n//     redisSetFreeCallback(c,__test_callback,(void*)4);\n//     redisFree(c);\n//     test_cond(__test_callback_flags == ((2 << 8) | 4));\n//\n//     test(\"redisBufferWrite against empty write buffer: \");\n//     c = __connect_nonblock();\n//     test_cond(redisBufferWrite(c,&wdone) == REDIS_OK && wdone == 1);\n//     redisFree(c);\n//\n//     test(\"redisBufferWrite against not yet connected fd: \");\n//     c = __connect_nonblock();\n//     redisCommand(c,\"PING\");\n//     test_cond(redisBufferWrite(c,NULL) == REDIS_ERR &&\n//               strncmp(c->error,\"write:\",6) == 0);\n//     redisFree(c);\n//\n//     test(\"redisBufferWrite against closed fd: \");\n//     c = __connect_nonblock();\n//     redisCommand(c,\"PING\");\n//     redisDisconnect(c);\n//     test_cond(redisBufferWrite(c,NULL) == REDIS_ERR &&\n//               strncmp(c->error,\"write:\",6) == 0);\n//     redisFree(c);\n//\n//     test(\"Process callbacks in the right sequence: \");\n//     c = __connect_nonblock();\n//     redisCommandWithCallback(c,__test_reply_callback,(void*)1,\"PING\");\n//     redisCommandWithCallback(c,__test_reply_callback,(void*)2,\"PING\");\n//     redisCommandWithCallback(c,__test_reply_callback,(void*)3,\"PING\");\n//\n//     /* Write output buffer */\n//     wdone = 0;\n//     while(!wdone) {\n//         usleep(500);\n//         redisBufferWrite(c,&wdone);\n//     }\n//\n//     /* Read until at least one callback is executed (the 3 replies will\n//      * arrive in a single packet, causing all callbacks to be executed in\n//      * a single pass). */\n//     while(__test_callback_flags == 0) {\n//         assert(redisBufferRead(c) == REDIS_OK);\n//         redisProcessCallbacks(c);\n//     }\n//     test_cond(__test_callback_flags == 0x010203);\n//     redisFree(c);\n//\n//     test(\"redisDisconnect executes pending callbacks with NULL reply: \");\n//     c = __connect_nonblock();\n//     redisSetDisconnectCallback(c,__test_callback,(void*)1);\n//     redisCommandWithCallback(c,__test_reply_callback,(void*)2,\"PING\");\n//     redisDisconnect(c);\n//     test_cond(__test_callback_flags == 0x0201);\n//     redisFree(c);\n// }\n\nint main(int argc, char **argv) {\n    struct config cfg = {\n        .tcp = {\n            .host = \"127.0.0.1\",\n            .port = 6379\n        },\n        .unix = {\n            .path = \"/tmp/redis.sock\"\n        }\n    };\n    int throughput = 1;\n    int test_inherit_fd = 1;\n\n    /* Ignore broken pipe signal (for I/O error tests). */\n    signal(SIGPIPE, SIG_IGN);\n\n    /* Parse command line options. */\n    argv++; argc--;\n    while (argc) {\n        if (argc >= 2 && !strcmp(argv[0],\"-h\")) {\n            argv++; argc--;\n            cfg.tcp.host = argv[0];\n        } else if (argc >= 2 && !strcmp(argv[0],\"-p\")) {\n            argv++; argc--;\n            cfg.tcp.port = atoi(argv[0]);\n        } else if (argc >= 2 && !strcmp(argv[0],\"-s\")) {\n            argv++; argc--;\n            cfg.unix.path = argv[0];\n        } else if (argc >= 1 && !strcmp(argv[0],\"--skip-throughput\")) {\n            throughput = 0;\n        } else if (argc >= 1 && !strcmp(argv[0],\"--skip-inherit-fd\")) {\n            test_inherit_fd = 0;\n        } else {\n            fprintf(stderr, \"Invalid argument: %s\\n\", argv[0]);\n            exit(1);\n        }\n        argv++; argc--;\n    }\n\n    test_format_commands();\n    test_reply_reader();\n    test_blocking_connection_errors();\n\n    printf(\"\\nTesting against TCP connection (%s:%d):\\n\", cfg.tcp.host, cfg.tcp.port);\n    cfg.type = CONN_TCP;\n    test_blocking_connection(cfg);\n    test_blocking_io_errors(cfg);\n    test_invalid_timeout_errors(cfg);\n    test_append_formatted_commands(cfg);\n    if (throughput) test_throughput(cfg);\n\n    printf(\"\\nTesting against Unix socket connection (%s):\\n\", cfg.unix.path);\n    cfg.type = CONN_UNIX;\n    test_blocking_connection(cfg);\n    test_blocking_io_errors(cfg);\n    if (throughput) test_throughput(cfg);\n\n    if (test_inherit_fd) {\n        printf(\"\\nTesting against inherited fd (%s):\\n\", cfg.unix.path);\n        cfg.type = CONN_FD;\n        test_blocking_connection(cfg);\n    }\n\n    if (fails) {\n        printf(\"*** %d TESTS FAILED ***\\n\", fails);\n        return 1;\n    }\n\n    printf(\"ALL TESTS PASSED\\n\");\n    return 0;\n}\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.8/deps/hiredis/zmalloc.h",
    "content": "/* Drop in replacement for zmalloc.h in order to just use libc malloc without\n * any wrappering. */\n\n#ifndef ZMALLOC_H\n#define ZMALLOC_H\n\n#define zmalloc malloc\n#define zrealloc realloc\n#define zcalloc(x) calloc(x,1)\n#define zfree free\n#define zstrdup strdup\n\n#endif\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.8/deps/jemalloc/.autom4te.cfg",
    "content": "begin-language: \"Autoconf-without-aclocal-m4\"\nargs: --no-cache\nend-language: \"Autoconf-without-aclocal-m4\"\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.8/deps/jemalloc/.gitattributes",
    "content": "* text=auto eol=lf\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.8/deps/jemalloc/.gitignore",
    "content": "/*.gcov.*\n\n/bin/jemalloc-config\n/bin/jemalloc.sh\n/bin/jeprof\n\n/config.stamp\n/config.log\n/config.status\n/configure\n\n/doc/html.xsl\n/doc/manpages.xsl\n/doc/jemalloc.xml\n/doc/jemalloc.html\n/doc/jemalloc.3\n\n/jemalloc.pc\n\n/lib/\n\n/Makefile\n\n/include/jemalloc/internal/jemalloc_internal.h\n/include/jemalloc/internal/jemalloc_internal_defs.h\n/include/jemalloc/internal/private_namespace.h\n/include/jemalloc/internal/private_unnamespace.h\n/include/jemalloc/internal/public_namespace.h\n/include/jemalloc/internal/public_symbols.txt\n/include/jemalloc/internal/public_unnamespace.h\n/include/jemalloc/internal/size_classes.h\n/include/jemalloc/jemalloc.h\n/include/jemalloc/jemalloc_defs.h\n/include/jemalloc/jemalloc_macros.h\n/include/jemalloc/jemalloc_mangle.h\n/include/jemalloc/jemalloc_mangle_jet.h\n/include/jemalloc/jemalloc_protos.h\n/include/jemalloc/jemalloc_protos_jet.h\n/include/jemalloc/jemalloc_rename.h\n/include/jemalloc/jemalloc_typedefs.h\n\n/src/*.[od]\n/src/*.gcda\n/src/*.gcno\n\n/test/test.sh\ntest/include/test/jemalloc_test.h\ntest/include/test/jemalloc_test_defs.h\n\n/test/integration/[A-Za-z]*\n!/test/integration/[A-Za-z]*.*\n/test/integration/*.[od]\n/test/integration/*.gcda\n/test/integration/*.gcno\n/test/integration/*.out\n\n/test/src/*.[od]\n/test/src/*.gcda\n/test/src/*.gcno\n\n/test/stress/[A-Za-z]*\n!/test/stress/[A-Za-z]*.*\n/test/stress/*.[od]\n/test/stress/*.gcda\n/test/stress/*.gcno\n/test/stress/*.out\n\n/test/unit/[A-Za-z]*\n!/test/unit/[A-Za-z]*.*\n/test/unit/*.[od]\n/test/unit/*.gcda\n/test/unit/*.gcno\n/test/unit/*.out\n\n/VERSION\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.8/deps/jemalloc/COPYING",
    "content": "Unless otherwise specified, files in the jemalloc source distribution are\nsubject to the following license:\n--------------------------------------------------------------------------------\nCopyright (C) 2002-2015 Jason Evans <jasone@canonware.com>.\nAll rights reserved.\nCopyright (C) 2007-2012 Mozilla Foundation.  All rights reserved.\nCopyright (C) 2009-2015 Facebook, Inc.  All rights reserved.\n\nRedistribution and use in source and binary forms, with or without\nmodification, are permitted provided that the following conditions are met:\n1. Redistributions of source code must retain the above copyright notice(s),\n   this list of conditions and the following disclaimer.\n2. Redistributions in binary form must reproduce the above copyright notice(s),\n   this list of conditions and the following disclaimer in the documentation\n   and/or other materials provided with the distribution.\n\nTHIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER(S) ``AS IS'' AND ANY EXPRESS\nOR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF\nMERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO\nEVENT SHALL THE COPYRIGHT HOLDER(S) BE LIABLE FOR ANY DIRECT, INDIRECT,\nINCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\nLIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR\nPROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF\nLIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE\nOR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF\nADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n--------------------------------------------------------------------------------\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.8/deps/jemalloc/ChangeLog",
    "content": "Following are change highlights associated with official releases.  Important\nbug fixes are all mentioned, but some internal enhancements are omitted here for\nbrevity.  Much more detail can be found in the git revision history:\n\n    https://github.com/jemalloc/jemalloc\n\n* 4.0.3 (September 24, 2015)\n\n  This bugfix release continues the trend of xallocx() and heap profiling fixes.\n\n  Bug fixes:\n  - Fix xallocx(..., MALLOCX_ZERO) to zero all trailing bytes of large\n    allocations when --enable-cache-oblivious configure option is enabled.\n  - Fix xallocx(..., MALLOCX_ZERO) to zero trailing bytes of huge allocations\n    when resizing from/to a size class that is not a multiple of the chunk size.\n  - Fix prof_tctx_dump_iter() to filter out nodes that were created after heap\n    profile dumping started.\n  - Work around a potentially bad thread-specific data initialization\n    interaction with NPTL (glibc's pthreads implementation).\n\n* 4.0.2 (September 21, 2015)\n\n  This bugfix release addresses a few bugs specific to heap profiling.\n\n  Bug fixes:\n  - Fix ixallocx_prof_sample() to never modify nor create sampled small\n    allocations.  xallocx() is in general incapable of moving small allocations,\n    so this fix removes buggy code without loss of generality.\n  - Fix irallocx_prof_sample() to always allocate large regions, even when\n    alignment is non-zero.\n  - Fix prof_alloc_rollback() to read tdata from thread-specific data rather\n    than dereferencing a potentially invalid tctx.\n\n* 4.0.1 (September 15, 2015)\n\n  This is a bugfix release that is somewhat high risk due to the amount of\n  refactoring required to address deep xallocx() problems.  As a side effect of\n  these fixes, xallocx() now tries harder to partially fulfill requests for\n  optional extra space.  Note that a couple of minor heap profiling\n  optimizations are included, but these are better thought of as performance\n  fixes that were integral to disovering most of the other bugs.\n\n  Optimizations:\n  - Avoid a chunk metadata read in arena_prof_tctx_set(), since it is in the\n    fast path when heap profiling is enabled.  Additionally, split a special\n    case out into arena_prof_tctx_reset(), which also avoids chunk metadata\n    reads.\n  - Optimize irallocx_prof() to optimistically update the sampler state.  The\n    prior implementation appears to have been a holdover from when\n    rallocx()/xallocx() functionality was combined as rallocm().\n\n  Bug fixes:\n  - Fix TLS configuration such that it is enabled by default for platforms on\n    which it works correctly.\n  - Fix arenas_cache_cleanup() and arena_get_hard() to handle\n    allocation/deallocation within the application's thread-specific data\n    cleanup functions even after arenas_cache is torn down.\n  - Fix xallocx() bugs related to size+extra exceeding HUGE_MAXCLASS.\n  - Fix chunk purge hook calls for in-place huge shrinking reallocation to\n    specify the old chunk size rather than the new chunk size.  This bug caused\n    no correctness issues for the default chunk purge function, but was\n    visible to custom functions set via the \"arena.<i>.chunk_hooks\" mallctl.\n  - Fix heap profiling bugs:\n    + Fix heap profiling to distinguish among otherwise identical sample sites\n      with interposed resets (triggered via the \"prof.reset\" mallctl).  This bug\n      could cause data structure corruption that would most likely result in a\n      segfault.\n    + Fix irealloc_prof() to prof_alloc_rollback() on OOM.\n    + Make one call to prof_active_get_unlocked() per allocation event, and use\n      the result throughout the relevant functions that handle an allocation\n      event.  Also add a missing check in prof_realloc().  These fixes protect\n      allocation events against concurrent prof_active changes.\n    + Fix ixallocx_prof() to pass usize_max and zero to ixallocx_prof_sample()\n      in the correct order.\n    + Fix prof_realloc() to call prof_free_sampled_object() after calling\n      prof_malloc_sample_object().  Prior to this fix, if tctx and old_tctx were\n      the same, the tctx could have been prematurely destroyed.\n  - Fix portability bugs:\n    + Don't bitshift by negative amounts when encoding/decoding run sizes in\n      chunk header maps.  This affected systems with page sizes greater than 8\n      KiB.\n    + Rename index_t to szind_t to avoid an existing type on Solaris.\n    + Add JEMALLOC_CXX_THROW to the memalign() function prototype, in order to\n      match glibc and avoid compilation errors when including both\n      jemalloc/jemalloc.h and malloc.h in C++ code.\n    + Don't assume that /bin/sh is appropriate when running size_classes.sh\n      during configuration.\n    + Consider __sparcv9 a synonym for __sparc64__ when defining LG_QUANTUM.\n    + Link tests to librt if it contains clock_gettime(2).\n\n* 4.0.0 (August 17, 2015)\n\n  This version contains many speed and space optimizations, both minor and\n  major.  The major themes are generalization, unification, and simplification.\n  Although many of these optimizations cause no visible behavior change, their\n  cumulative effect is substantial.\n\n  New features:\n  - Normalize size class spacing to be consistent across the complete size\n    range.  By default there are four size classes per size doubling, but this\n    is now configurable via the --with-lg-size-class-group option.  Also add the\n    --with-lg-page, --with-lg-page-sizes, --with-lg-quantum, and\n    --with-lg-tiny-min options, which can be used to tweak page and size class\n    settings.  Impacts:\n    + Worst case performance for incrementally growing/shrinking reallocation\n      is improved because there are far fewer size classes, and therefore\n      copying happens less often.\n    + Internal fragmentation is limited to 20% for all but the smallest size\n      classes (those less than four times the quantum).  (1B + 4 KiB)\n      and (1B + 4 MiB) previously suffered nearly 50% internal fragmentation.\n    + Chunk fragmentation tends to be lower because there are fewer distinct run\n      sizes to pack.\n  - Add support for explicit tcaches.  The \"tcache.create\", \"tcache.flush\", and\n    \"tcache.destroy\" mallctls control tcache lifetime and flushing, and the\n    MALLOCX_TCACHE(tc) and MALLOCX_TCACHE_NONE flags to the *allocx() API\n    control which tcache is used for each operation.\n  - Implement per thread heap profiling, as well as the ability to\n    enable/disable heap profiling on a per thread basis.  Add the \"prof.reset\",\n    \"prof.lg_sample\", \"thread.prof.name\", \"thread.prof.active\",\n    \"opt.prof_thread_active_init\", \"prof.thread_active_init\", and\n    \"thread.prof.active\" mallctls.\n  - Add support for per arena application-specified chunk allocators, configured\n    via the \"arena.<i>.chunk_hooks\" mallctl.\n  - Refactor huge allocation to be managed by arenas, so that arenas now\n    function as general purpose independent allocators.  This is important in\n    the context of user-specified chunk allocators, aside from the scalability\n    benefits.  Related new statistics:\n    + The \"stats.arenas.<i>.huge.allocated\", \"stats.arenas.<i>.huge.nmalloc\",\n      \"stats.arenas.<i>.huge.ndalloc\", and \"stats.arenas.<i>.huge.nrequests\"\n      mallctls provide high level per arena huge allocation statistics.\n    + The \"arenas.nhchunks\", \"arenas.hchunk.<i>.size\",\n      \"stats.arenas.<i>.hchunks.<j>.nmalloc\",\n      \"stats.arenas.<i>.hchunks.<j>.ndalloc\",\n      \"stats.arenas.<i>.hchunks.<j>.nrequests\", and\n      \"stats.arenas.<i>.hchunks.<j>.curhchunks\" mallctls provide per size class\n      statistics.\n  - Add the 'util' column to malloc_stats_print() output, which reports the\n    proportion of available regions that are currently in use for each small\n    size class.\n  - Add \"alloc\" and \"free\" modes for for junk filling (see the \"opt.junk\"\n    mallctl), so that it is possible to separately enable junk filling for\n    allocation versus deallocation.\n  - Add the jemalloc-config script, which provides information about how\n    jemalloc was configured, and how to integrate it into application builds.\n  - Add metadata statistics, which are accessible via the \"stats.metadata\",\n    \"stats.arenas.<i>.metadata.mapped\", and\n    \"stats.arenas.<i>.metadata.allocated\" mallctls.\n  - Add the \"stats.resident\" mallctl, which reports the upper limit of\n    physically resident memory mapped by the allocator.\n  - Add per arena control over unused dirty page purging, via the\n    \"arenas.lg_dirty_mult\", \"arena.<i>.lg_dirty_mult\", and\n    \"stats.arenas.<i>.lg_dirty_mult\" mallctls.\n  - Add the \"prof.gdump\" mallctl, which makes it possible to toggle the gdump\n    feature on/off during program execution.\n  - Add sdallocx(), which implements sized deallocation.  The primary\n    optimization over dallocx() is the removal of a metadata read, which often\n    suffers an L1 cache miss.\n  - Add missing header includes in jemalloc/jemalloc.h, so that applications\n    only have to #include <jemalloc/jemalloc.h>.\n  - Add support for additional platforms:\n    + Bitrig\n    + Cygwin\n    + DragonFlyBSD\n    + iOS\n    + OpenBSD\n    + OpenRISC/or1k\n\n  Optimizations:\n  - Maintain dirty runs in per arena LRUs rather than in per arena trees of\n    dirty-run-containing chunks.  In practice this change significantly reduces\n    dirty page purging volume.\n  - Integrate whole chunks into the unused dirty page purging machinery.  This\n    reduces the cost of repeated huge allocation/deallocation, because it\n    effectively introduces a cache of chunks.\n  - Split the arena chunk map into two separate arrays, in order to increase\n    cache locality for the frequently accessed bits.\n  - Move small run metadata out of runs, into arena chunk headers.  This reduces\n    run fragmentation, smaller runs reduce external fragmentation for small size\n    classes, and packed (less uniformly aligned) metadata layout improves CPU\n    cache set distribution.\n  - Randomly distribute large allocation base pointer alignment relative to page\n    boundaries in order to more uniformly utilize CPU cache sets.  This can be\n    disabled via the --disable-cache-oblivious configure option, and queried via\n    the \"config.cache_oblivious\" mallctl.\n  - Micro-optimize the fast paths for the public API functions.\n  - Refactor thread-specific data to reside in a single structure.  This assures\n    that only a single TLS read is necessary per call into the public API.\n  - Implement in-place huge allocation growing and shrinking.\n  - Refactor rtree (radix tree for chunk lookups) to be lock-free, and make\n    additional optimizations that reduce maximum lookup depth to one or two\n    levels.  This resolves what was a concurrency bottleneck for per arena huge\n    allocation, because a global data structure is critical for determining\n    which arenas own which huge allocations.\n\n  Incompatible changes:\n  - Replace --enable-cc-silence with --disable-cc-silence to suppress spurious\n    warnings by default.\n  - Assure that the constness of malloc_usable_size()'s return type matches that\n    of the system implementation.\n  - Change the heap profile dump format to support per thread heap profiling,\n    rename pprof to jeprof, and enhance it with the --thread=<n> option.  As a\n    result, the bundled jeprof must now be used rather than the upstream\n    (gperftools) pprof.\n  - Disable \"opt.prof_final\" by default, in order to avoid atexit(3), which can\n    internally deadlock on some platforms.\n  - Change the \"arenas.nlruns\" mallctl type from size_t to unsigned.\n  - Replace the \"stats.arenas.<i>.bins.<j>.allocated\" mallctl with\n    \"stats.arenas.<i>.bins.<j>.curregs\".\n  - Ignore MALLOC_CONF in set{uid,gid,cap} binaries.\n  - Ignore MALLOCX_ARENA(a) in dallocx(), in favor of using the\n    MALLOCX_TCACHE(tc) and MALLOCX_TCACHE_NONE flags to control tcache usage.\n\n  Removed features:\n  - Remove the *allocm() API, which is superseded by the *allocx() API.\n  - Remove the --enable-dss options, and make dss non-optional on all platforms\n    which support sbrk(2).\n  - Remove the \"arenas.purge\" mallctl, which was obsoleted by the\n    \"arena.<i>.purge\" mallctl in 3.1.0.\n  - Remove the unnecessary \"opt.valgrind\" mallctl; jemalloc automatically\n    detects whether it is running inside Valgrind.\n  - Remove the \"stats.huge.allocated\", \"stats.huge.nmalloc\", and\n    \"stats.huge.ndalloc\" mallctls.\n  - Remove the --enable-mremap option.\n  - Remove the \"stats.chunks.current\", \"stats.chunks.total\", and\n    \"stats.chunks.high\" mallctls.\n\n  Bug fixes:\n  - Fix the cactive statistic to decrease (rather than increase) when active\n    memory decreases.  This regression was first released in 3.5.0.\n  - Fix OOM handling in memalign() and valloc().  A variant of this bug existed\n    in all releases since 2.0.0, which introduced these functions.\n  - Fix an OOM-related regression in arena_tcache_fill_small(), which could\n    cause cache corruption on OOM.  This regression was present in all releases\n    from 2.2.0 through 3.6.0.\n  - Fix size class overflow handling for malloc(), posix_memalign(), memalign(),\n    calloc(), and realloc() when profiling is enabled.\n  - Fix the \"arena.<i>.dss\" mallctl to return an error if \"primary\" or\n    \"secondary\" precedence is specified, but sbrk(2) is not supported.\n  - Fix fallback lg_floor() implementations to handle extremely large inputs.\n  - Ensure the default purgeable zone is after the default zone on OS X.\n  - Fix latent bugs in atomic_*().\n  - Fix the \"arena.<i>.dss\" mallctl to handle read-only calls.\n  - Fix tls_model configuration to enable the initial-exec model when possible.\n  - Mark malloc_conf as a weak symbol so that the application can override it.\n  - Correctly detect glibc's adaptive pthread mutexes.\n  - Fix the --without-export configure option.\n\n* 3.6.0 (March 31, 2014)\n\n  This version contains a critical bug fix for a regression present in 3.5.0 and\n  3.5.1.\n\n  Bug fixes:\n  - Fix a regression in arena_chunk_alloc() that caused crashes during\n    small/large allocation if chunk allocation failed.  In the absence of this\n    bug, chunk allocation failure would result in allocation failure, e.g.  NULL\n    return from malloc().  This regression was introduced in 3.5.0.\n  - Fix backtracing for gcc intrinsics-based backtracing by specifying\n    -fno-omit-frame-pointer to gcc.  Note that the application (and all the\n    libraries it links to) must also be compiled with this option for\n    backtracing to be reliable.\n  - Use dss allocation precedence for huge allocations as well as small/large\n    allocations.\n  - Fix test assertion failure message formatting.  This bug did not manifest on\n    x86_64 systems because of implementation subtleties in va_list.\n  - Fix inconsequential test failures for hash and SFMT code.\n\n  New features:\n  - Support heap profiling on FreeBSD.  This feature depends on the proc\n    filesystem being mounted during heap profile dumping.\n\n* 3.5.1 (February 25, 2014)\n\n  This version primarily addresses minor bugs in test code.\n\n  Bug fixes:\n  - Configure Solaris/Illumos to use MADV_FREE.\n  - Fix junk filling for mremap(2)-based huge reallocation.  This is only\n    relevant if configuring with the --enable-mremap option specified.\n  - Avoid compilation failure if 'restrict' C99 keyword is not supported by the\n    compiler.\n  - Add a configure test for SSE2 rather than assuming it is usable on i686\n    systems.  This fixes test compilation errors, especially on 32-bit Linux\n    systems.\n  - Fix mallctl argument size mismatches (size_t vs. uint64_t) in the stats unit\n    test.\n  - Fix/remove flawed alignment-related overflow tests.\n  - Prevent compiler optimizations that could change backtraces in the\n    prof_accum unit test.\n\n* 3.5.0 (January 22, 2014)\n\n  This version focuses on refactoring and automated testing, though it also\n  includes some non-trivial heap profiling optimizations not mentioned below.\n\n  New features:\n  - Add the *allocx() API, which is a successor to the experimental *allocm()\n    API.  The *allocx() functions are slightly simpler to use because they have\n    fewer parameters, they directly return the results of primary interest, and\n    mallocx()/rallocx() avoid the strict aliasing pitfall that\n    allocm()/rallocm() share with posix_memalign().  Note that *allocm() is\n    slated for removal in the next non-bugfix release.\n  - Add support for LinuxThreads.\n\n  Bug fixes:\n  - Unless heap profiling is enabled, disable floating point code and don't link\n    with libm.  This, in combination with e.g. EXTRA_CFLAGS=-mno-sse on x64\n    systems, makes it possible to completely disable floating point register\n    use.  Some versions of glibc neglect to save/restore caller-saved floating\n    point registers during dynamic lazy symbol loading, and the symbol loading\n    code uses whatever malloc the application happens to have linked/loaded\n    with, the result being potential floating point register corruption.\n  - Report ENOMEM rather than EINVAL if an OOM occurs during heap profiling\n    backtrace creation in imemalign().  This bug impacted posix_memalign() and\n    aligned_alloc().\n  - Fix a file descriptor leak in a prof_dump_maps() error path.\n  - Fix prof_dump() to close the dump file descriptor for all relevant error\n    paths.\n  - Fix rallocm() to use the arena specified by the ALLOCM_ARENA(s) flag for\n    allocation, not just deallocation.\n  - Fix a data race for large allocation stats counters.\n  - Fix a potential infinite loop during thread exit.  This bug occurred on\n    Solaris, and could affect other platforms with similar pthreads TSD\n    implementations.\n  - Don't junk-fill reallocations unless usable size changes.  This fixes a\n    violation of the *allocx()/*allocm() semantics.\n  - Fix growing large reallocation to junk fill new space.\n  - Fix huge deallocation to junk fill when munmap is disabled.\n  - Change the default private namespace prefix from empty to je_, and change\n    --with-private-namespace-prefix so that it prepends an additional prefix\n    rather than replacing je_.  This reduces the likelihood of applications\n    which statically link jemalloc experiencing symbol name collisions.\n  - Add missing private namespace mangling (relevant when\n    --with-private-namespace is specified).\n  - Add and use JEMALLOC_INLINE_C so that static inline functions are marked as\n    static even for debug builds.\n  - Add a missing mutex unlock in a malloc_init_hard() error path.  In practice\n    this error path is never executed.\n  - Fix numerous bugs in malloc_strotumax() error handling/reporting.  These\n    bugs had no impact except for malformed inputs.\n  - Fix numerous bugs in malloc_snprintf().  These bugs were not exercised by\n    existing calls, so they had no impact.\n\n* 3.4.1 (October 20, 2013)\n\n  Bug fixes:\n  - Fix a race in the \"arenas.extend\" mallctl that could cause memory corruption\n    of internal data structures and subsequent crashes.\n  - Fix Valgrind integration flaws that caused Valgrind warnings about reads of\n    uninitialized memory in:\n    + arena chunk headers\n    + internal zero-initialized data structures (relevant to tcache and prof\n      code)\n  - Preserve errno during the first allocation.  A readlink(2) call during\n    initialization fails unless /etc/malloc.conf exists, so errno was typically\n    set during the first allocation prior to this fix.\n  - Fix compilation warnings reported by gcc 4.8.1.\n\n* 3.4.0 (June 2, 2013)\n\n  This version is essentially a small bugfix release, but the addition of\n  aarch64 support requires that the minor version be incremented.\n\n  Bug fixes:\n  - Fix race-triggered deadlocks in chunk_record().  These deadlocks were\n    typically triggered by multiple threads concurrently deallocating huge\n    objects.\n\n  New features:\n  - Add support for the aarch64 architecture.\n\n* 3.3.1 (March 6, 2013)\n\n  This version fixes bugs that are typically encountered only when utilizing\n  custom run-time options.\n\n  Bug fixes:\n  - Fix a locking order bug that could cause deadlock during fork if heap\n    profiling were enabled.\n  - Fix a chunk recycling bug that could cause the allocator to lose track of\n    whether a chunk was zeroed.  On FreeBSD, NetBSD, and OS X, it could cause\n    corruption if allocating via sbrk(2) (unlikely unless running with the\n    \"dss:primary\" option specified).  This was completely harmless on Linux\n    unless using mlockall(2) (and unlikely even then, unless the\n    --disable-munmap configure option or the \"dss:primary\" option was\n    specified).  This regression was introduced in 3.1.0 by the\n    mlockall(2)/madvise(2) interaction fix.\n  - Fix TLS-related memory corruption that could occur during thread exit if the\n    thread never allocated memory.  Only the quarantine and prof facilities were\n    susceptible.\n  - Fix two quarantine bugs:\n    + Internal reallocation of the quarantined object array leaked the old\n      array.\n    + Reallocation failure for internal reallocation of the quarantined object\n      array (very unlikely) resulted in memory corruption.\n  - Fix Valgrind integration to annotate all internally allocated memory in a\n    way that keeps Valgrind happy about internal data structure access.\n  - Fix building for s390 systems.\n\n* 3.3.0 (January 23, 2013)\n\n  This version includes a few minor performance improvements in addition to the\n  listed new features and bug fixes.\n\n  New features:\n  - Add clipping support to lg_chunk option processing.\n  - Add the --enable-ivsalloc option.\n  - Add the --without-export option.\n  - Add the --disable-zone-allocator option.\n\n  Bug fixes:\n  - Fix \"arenas.extend\" mallctl to output the number of arenas.\n  - Fix chunk_recycle() to unconditionally inform Valgrind that returned memory\n    is undefined.\n  - Fix build break on FreeBSD related to alloca.h.\n\n* 3.2.0 (November 9, 2012)\n\n  In addition to a couple of bug fixes, this version modifies page run\n  allocation and dirty page purging algorithms in order to better control\n  page-level virtual memory fragmentation.\n\n  Incompatible changes:\n  - Change the \"opt.lg_dirty_mult\" default from 5 to 3 (32:1 to 8:1).\n\n  Bug fixes:\n  - Fix dss/mmap allocation precedence code to use recyclable mmap memory only\n    after primary dss allocation fails.\n  - Fix deadlock in the \"arenas.purge\" mallctl.  This regression was introduced\n    in 3.1.0 by the addition of the \"arena.<i>.purge\" mallctl.\n\n* 3.1.0 (October 16, 2012)\n\n  New features:\n  - Auto-detect whether running inside Valgrind, thus removing the need to\n    manually specify MALLOC_CONF=valgrind:true.\n  - Add the \"arenas.extend\" mallctl, which allows applications to create\n    manually managed arenas.\n  - Add the ALLOCM_ARENA() flag for {,r,d}allocm().\n  - Add the \"opt.dss\", \"arena.<i>.dss\", and \"stats.arenas.<i>.dss\" mallctls,\n    which provide control over dss/mmap precedence.\n  - Add the \"arena.<i>.purge\" mallctl, which obsoletes \"arenas.purge\".\n  - Define LG_QUANTUM for hppa.\n\n  Incompatible changes:\n  - Disable tcache by default if running inside Valgrind, in order to avoid\n    making unallocated objects appear reachable to Valgrind.\n  - Drop const from malloc_usable_size() argument on Linux.\n\n  Bug fixes:\n  - Fix heap profiling crash if sampled object is freed via realloc(p, 0).\n  - Remove const from __*_hook variable declarations, so that glibc can modify\n    them during process forking.\n  - Fix mlockall(2)/madvise(2) interaction.\n  - Fix fork(2)-related deadlocks.\n  - Fix error return value for \"thread.tcache.enabled\" mallctl.\n\n* 3.0.0 (May 11, 2012)\n\n  Although this version adds some major new features, the primary focus is on\n  internal code cleanup that facilitates maintainability and portability, most\n  of which is not reflected in the ChangeLog.  This is the first release to\n  incorporate substantial contributions from numerous other developers, and the\n  result is a more broadly useful allocator (see the git revision history for\n  contribution details).  Note that the license has been unified, thanks to\n  Facebook granting a license under the same terms as the other copyright\n  holders (see COPYING).\n\n  New features:\n  - Implement Valgrind support, redzones, and quarantine.\n  - Add support for additional platforms:\n    + FreeBSD\n    + Mac OS X Lion\n    + MinGW\n    + Windows (no support yet for replacing the system malloc)\n  - Add support for additional architectures:\n    + MIPS\n    + SH4\n    + Tilera\n  - Add support for cross compiling.\n  - Add nallocm(), which rounds a request size up to the nearest size class\n    without actually allocating.\n  - Implement aligned_alloc() (blame C11).\n  - Add the \"thread.tcache.enabled\" mallctl.\n  - Add the \"opt.prof_final\" mallctl.\n  - Update pprof (from gperftools 2.0).\n  - Add the --with-mangling option.\n  - Add the --disable-experimental option.\n  - Add the --disable-munmap option, and make it the default on Linux.\n  - Add the --enable-mremap option, which disables use of mremap(2) by default.\n\n  Incompatible changes:\n  - Enable stats by default.\n  - Enable fill by default.\n  - Disable lazy locking by default.\n  - Rename the \"tcache.flush\" mallctl to \"thread.tcache.flush\".\n  - Rename the \"arenas.pagesize\" mallctl to \"arenas.page\".\n  - Change the \"opt.lg_prof_sample\" default from 0 to 19 (1 B to 512 KiB).\n  - Change the \"opt.prof_accum\" default from true to false.\n\n  Removed features:\n  - Remove the swap feature, including the \"config.swap\", \"swap.avail\",\n    \"swap.prezeroed\", \"swap.nfds\", and \"swap.fds\" mallctls.\n  - Remove highruns statistics, including the\n    \"stats.arenas.<i>.bins.<j>.highruns\" and\n    \"stats.arenas.<i>.lruns.<j>.highruns\" mallctls.\n  - As part of small size class refactoring, remove the \"opt.lg_[qc]space_max\",\n    \"arenas.cacheline\", \"arenas.subpage\", \"arenas.[tqcs]space_{min,max}\", and\n    \"arenas.[tqcs]bins\" mallctls.\n  - Remove the \"arenas.chunksize\" mallctl.\n  - Remove the \"opt.lg_prof_tcmax\" option.\n  - Remove the \"opt.lg_prof_bt_max\" option.\n  - Remove the \"opt.lg_tcache_gc_sweep\" option.\n  - Remove the --disable-tiny option, including the \"config.tiny\" mallctl.\n  - Remove the --enable-dynamic-page-shift configure option.\n  - Remove the --enable-sysv configure option.\n\n  Bug fixes:\n  - Fix a statistics-related bug in the \"thread.arena\" mallctl that could cause\n    invalid statistics and crashes.\n  - Work around TLS deallocation via free() on Linux.  This bug could cause\n    write-after-free memory corruption.\n  - Fix a potential deadlock that could occur during interval- and\n    growth-triggered heap profile dumps.\n  - Fix large calloc() zeroing bugs due to dropping chunk map unzeroed flags.\n  - Fix chunk_alloc_dss() to stop claiming memory is zeroed.  This bug could\n    cause memory corruption and crashes with --enable-dss specified.\n  - Fix fork-related bugs that could cause deadlock in children between fork\n    and exec.\n  - Fix malloc_stats_print() to honor 'b' and 'l' in the opts parameter.\n  - Fix realloc(p, 0) to act like free(p).\n  - Do not enforce minimum alignment in memalign().\n  - Check for NULL pointer in malloc_usable_size().\n  - Fix an off-by-one heap profile statistics bug that could be observed in\n    interval- and growth-triggered heap profiles.\n  - Fix the \"epoch\" mallctl to update cached stats even if the passed in epoch\n    is 0.\n  - Fix bin->runcur management to fix a layout policy bug.  This bug did not\n    affect correctness.\n  - Fix a bug in choose_arena_hard() that potentially caused more arenas to be\n    initialized than necessary.\n  - Add missing \"opt.lg_tcache_max\" mallctl implementation.\n  - Use glibc allocator hooks to make mixed allocator usage less likely.\n  - Fix build issues for --disable-tcache.\n  - Don't mangle pthread_create() when --with-private-namespace is specified.\n\n* 2.2.5 (November 14, 2011)\n\n  Bug fixes:\n  - Fix huge_ralloc() race when using mremap(2).  This is a serious bug that\n    could cause memory corruption and/or crashes.\n  - Fix huge_ralloc() to maintain chunk statistics.\n  - Fix malloc_stats_print(..., \"a\") output.\n\n* 2.2.4 (November 5, 2011)\n\n  Bug fixes:\n  - Initialize arenas_tsd before using it.  This bug existed for 2.2.[0-3], as\n    well as for --disable-tls builds in earlier releases.\n  - Do not assume a 4 KiB page size in test/rallocm.c.\n\n* 2.2.3 (August 31, 2011)\n\n  This version fixes numerous bugs related to heap profiling.\n\n  Bug fixes:\n  - Fix a prof-related race condition.  This bug could cause memory corruption,\n    but only occurred in non-default configurations (prof_accum:false).\n  - Fix off-by-one backtracing issues (make sure that prof_alloc_prep() is\n    excluded from backtraces).\n  - Fix a prof-related bug in realloc() (only triggered by OOM errors).\n  - Fix prof-related bugs in allocm() and rallocm().\n  - Fix prof_tdata_cleanup() for --disable-tls builds.\n  - Fix a relative include path, to fix objdir builds.\n\n* 2.2.2 (July 30, 2011)\n\n  Bug fixes:\n  - Fix a build error for --disable-tcache.\n  - Fix assertions in arena_purge() (for real this time).\n  - Add the --with-private-namespace option.  This is a workaround for symbol\n    conflicts that can inadvertently arise when using static libraries.\n\n* 2.2.1 (March 30, 2011)\n\n  Bug fixes:\n  - Implement atomic operations for x86/x64.  This fixes compilation failures\n    for versions of gcc that are still in wide use.\n  - Fix an assertion in arena_purge().\n\n* 2.2.0 (March 22, 2011)\n\n  This version incorporates several improvements to algorithms and data\n  structures that tend to reduce fragmentation and increase speed.\n\n  New features:\n  - Add the \"stats.cactive\" mallctl.\n  - Update pprof (from google-perftools 1.7).\n  - Improve backtracing-related configuration logic, and add the\n    --disable-prof-libgcc option.\n\n  Bug fixes:\n  - Change default symbol visibility from \"internal\", to \"hidden\", which\n    decreases the overhead of library-internal function calls.\n  - Fix symbol visibility so that it is also set on OS X.\n  - Fix a build dependency regression caused by the introduction of the .pic.o\n    suffix for PIC object files.\n  - Add missing checks for mutex initialization failures.\n  - Don't use libgcc-based backtracing except on x64, where it is known to work.\n  - Fix deadlocks on OS X that were due to memory allocation in\n    pthread_mutex_lock().\n  - Heap profiling-specific fixes:\n    + Fix memory corruption due to integer overflow in small region index\n      computation, when using a small enough sample interval that profiling\n      context pointers are stored in small run headers.\n    + Fix a bootstrap ordering bug that only occurred with TLS disabled.\n    + Fix a rallocm() rsize bug.\n    + Fix error detection bugs for aligned memory allocation.\n\n* 2.1.3 (March 14, 2011)\n\n  Bug fixes:\n  - Fix a cpp logic regression (due to the \"thread.{de,}allocatedp\" mallctl fix\n    for OS X in 2.1.2).\n  - Fix a \"thread.arena\" mallctl bug.\n  - Fix a thread cache stats merging bug.\n\n* 2.1.2 (March 2, 2011)\n\n  Bug fixes:\n  - Fix \"thread.{de,}allocatedp\" mallctl for OS X.\n  - Add missing jemalloc.a to build system.\n\n* 2.1.1 (January 31, 2011)\n\n  Bug fixes:\n  - Fix aligned huge reallocation (affected allocm()).\n  - Fix the ALLOCM_LG_ALIGN macro definition.\n  - Fix a heap dumping deadlock.\n  - Fix a \"thread.arena\" mallctl bug.\n\n* 2.1.0 (December 3, 2010)\n\n  This version incorporates some optimizations that can't quite be considered\n  bug fixes.\n\n  New features:\n  - Use Linux's mremap(2) for huge object reallocation when possible.\n  - Avoid locking in mallctl*() when possible.\n  - Add the \"thread.[de]allocatedp\" mallctl's.\n  - Convert the manual page source from roff to DocBook, and generate both roff\n    and HTML manuals.\n\n  Bug fixes:\n  - Fix a crash due to incorrect bootstrap ordering.  This only impacted\n    --enable-debug --enable-dss configurations.\n  - Fix a minor statistics bug for mallctl(\"swap.avail\", ...).\n\n* 2.0.1 (October 29, 2010)\n\n  Bug fixes:\n  - Fix a race condition in heap profiling that could cause undefined behavior\n    if \"opt.prof_accum\" were disabled.\n  - Add missing mutex unlocks for some OOM error paths in the heap profiling\n    code.\n  - Fix a compilation error for non-C99 builds.\n\n* 2.0.0 (October 24, 2010)\n\n  This version focuses on the experimental *allocm() API, and on improved\n  run-time configuration/introspection.  Nonetheless, numerous performance\n  improvements are also included.\n\n  New features:\n  - Implement the experimental {,r,s,d}allocm() API, which provides a superset\n    of the functionality available via malloc(), calloc(), posix_memalign(),\n    realloc(), malloc_usable_size(), and free().  These functions can be used to\n    allocate/reallocate aligned zeroed memory, ask for optional extra memory\n    during reallocation, prevent object movement during reallocation, etc.\n  - Replace JEMALLOC_OPTIONS/JEMALLOC_PROF_PREFIX with MALLOC_CONF, which is\n    more human-readable, and more flexible.  For example:\n      JEMALLOC_OPTIONS=AJP\n    is now:\n      MALLOC_CONF=abort:true,fill:true,stats_print:true\n  - Port to Apple OS X.  Sponsored by Mozilla.\n  - Make it possible for the application to control thread-->arena mappings via\n    the \"thread.arena\" mallctl.\n  - Add compile-time support for all TLS-related functionality via pthreads TSD.\n    This is mainly of interest for OS X, which does not support TLS, but has a\n    TSD implementation with similar performance.\n  - Override memalign() and valloc() if they are provided by the system.\n  - Add the \"arenas.purge\" mallctl, which can be used to synchronously purge all\n    dirty unused pages.\n  - Make cumulative heap profiling data optional, so that it is possible to\n    limit the amount of memory consumed by heap profiling data structures.\n  - Add per thread allocation counters that can be accessed via the\n    \"thread.allocated\" and \"thread.deallocated\" mallctls.\n\n  Incompatible changes:\n  - Remove JEMALLOC_OPTIONS and malloc_options (see MALLOC_CONF above).\n  - Increase default backtrace depth from 4 to 128 for heap profiling.\n  - Disable interval-based profile dumps by default.\n\n  Bug fixes:\n  - Remove bad assertions in fork handler functions.  These assertions could\n    cause aborts for some combinations of configure settings.\n  - Fix strerror_r() usage to deal with non-standard semantics in GNU libc.\n  - Fix leak context reporting.  This bug tended to cause the number of contexts\n    to be underreported (though the reported number of objects and bytes were\n    correct).\n  - Fix a realloc() bug for large in-place growing reallocation.  This bug could\n    cause memory corruption, but it was hard to trigger.\n  - Fix an allocation bug for small allocations that could be triggered if\n    multiple threads raced to create a new run of backing pages.\n  - Enhance the heap profiler to trigger samples based on usable size, rather\n    than request size.\n  - Fix a heap profiling bug due to sometimes losing track of requested object\n    size for sampled objects.\n\n* 1.0.3 (August 12, 2010)\n\n  Bug fixes:\n  - Fix the libunwind-based implementation of stack backtracing (used for heap\n    profiling).  This bug could cause zero-length backtraces to be reported.\n  - Add a missing mutex unlock in library initialization code.  If multiple\n    threads raced to initialize malloc, some of them could end up permanently\n    blocked.\n\n* 1.0.2 (May 11, 2010)\n\n  Bug fixes:\n  - Fix junk filling of large objects, which could cause memory corruption.\n  - Add MAP_NORESERVE support for chunk mapping, because otherwise virtual\n    memory limits could cause swap file configuration to fail.  Contributed by\n    Jordan DeLong.\n\n* 1.0.1 (April 14, 2010)\n\n  Bug fixes:\n  - Fix compilation when --enable-fill is specified.\n  - Fix threads-related profiling bugs that affected accuracy and caused memory\n    to be leaked during thread exit.\n  - Fix dirty page purging race conditions that could cause crashes.\n  - Fix crash in tcache flushing code during thread destruction.\n\n* 1.0.0 (April 11, 2010)\n\n  This release focuses on speed and run-time introspection.  Numerous\n  algorithmic improvements make this release substantially faster than its\n  predecessors.\n\n  New features:\n  - Implement autoconf-based configuration system.\n  - Add mallctl*(), for the purposes of introspection and run-time\n    configuration.\n  - Make it possible for the application to manually flush a thread's cache, via\n    the \"tcache.flush\" mallctl.\n  - Base maximum dirty page count on proportion of active memory.\n  - Compute various additional run-time statistics, including per size class\n    statistics for large objects.\n  - Expose malloc_stats_print(), which can be called repeatedly by the\n    application.\n  - Simplify the malloc_message() signature to only take one string argument,\n    and incorporate an opaque data pointer argument for use by the application\n    in combination with malloc_stats_print().\n  - Add support for allocation backed by one or more swap files, and allow the\n    application to disable over-commit if swap files are in use.\n  - Implement allocation profiling and leak checking.\n\n  Removed features:\n  - Remove the dynamic arena rebalancing code, since thread-specific caching\n    reduces its utility.\n\n  Bug fixes:\n  - Modify chunk allocation to work when address space layout randomization\n    (ASLR) is in use.\n  - Fix thread cleanup bugs related to TLS destruction.\n  - Handle 0-size allocation requests in posix_memalign().\n  - Fix a chunk leak.  The leaked chunks were never touched, so this impacted\n    virtual memory usage, but not physical memory usage.\n\n* linux_2008082[78]a (August 27/28, 2008)\n\n  These snapshot releases are the simple result of incorporating Linux-specific\n  support into the FreeBSD malloc sources.\n\n--------------------------------------------------------------------------------\nvim:filetype=text:textwidth=80\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.8/deps/jemalloc/INSTALL",
    "content": "Building and installing a packaged release of jemalloc can be as simple as\ntyping the following while in the root directory of the source tree:\n\n    ./configure\n    make\n    make install\n\nIf building from unpackaged developer sources, the simplest command sequence\nthat might work is:\n\n    ./autogen.sh\n    make dist\n    make\n    make install\n\nNote that documentation is not built by the default target because doing so\nwould create a dependency on xsltproc in packaged releases, hence the\nrequirement to either run 'make dist' or avoid installing docs via the various\ninstall_* targets documented below.\n\n=== Advanced configuration =====================================================\n\nThe 'configure' script supports numerous options that allow control of which\nfunctionality is enabled, where jemalloc is installed, etc.  Optionally, pass\nany of the following arguments (not a definitive list) to 'configure':\n\n--help\n    Print a definitive list of options.\n\n--prefix=<install-root-dir>\n    Set the base directory in which to install.  For example:\n\n        ./configure --prefix=/usr/local\n\n    will cause files to be installed into /usr/local/include, /usr/local/lib,\n    and /usr/local/man.\n\n--with-rpath=<colon-separated-rpath>\n    Embed one or more library paths, so that libjemalloc can find the libraries\n    it is linked to.  This works only on ELF-based systems.\n\n--with-mangling=<map>\n    Mangle public symbols specified in <map> which is a comma-separated list of\n    name:mangled pairs.\n\n    For example, to use ld's --wrap option as an alternative method for\n    overriding libc's malloc implementation, specify something like:\n\n      --with-mangling=malloc:__wrap_malloc,free:__wrap_free[...]\n\n    Note that mangling happens prior to application of the prefix specified by\n    --with-jemalloc-prefix, and mangled symbols are then ignored when applying\n    the prefix.\n\n--with-jemalloc-prefix=<prefix>\n    Prefix all public APIs with <prefix>.  For example, if <prefix> is\n    \"prefix_\", API changes like the following occur:\n\n      malloc()         --> prefix_malloc()\n      malloc_conf      --> prefix_malloc_conf\n      /etc/malloc.conf --> /etc/prefix_malloc.conf\n      MALLOC_CONF      --> PREFIX_MALLOC_CONF\n\n    This makes it possible to use jemalloc at the same time as the system\n    allocator, or even to use multiple copies of jemalloc simultaneously.\n\n    By default, the prefix is \"\", except on OS X, where it is \"je_\".  On OS X,\n    jemalloc overlays the default malloc zone, but makes no attempt to actually\n    replace the \"malloc\", \"calloc\", etc. symbols.\n\n--without-export\n    Don't export public APIs.  This can be useful when building jemalloc as a\n    static library, or to avoid exporting public APIs when using the zone\n    allocator on OSX.\n\n--with-private-namespace=<prefix>\n    Prefix all library-private APIs with <prefix>je_.  For shared libraries,\n    symbol visibility mechanisms prevent these symbols from being exported, but\n    for static libraries, naming collisions are a real possibility.  By\n    default, <prefix> is empty, which results in a symbol prefix of je_ .\n\n--with-install-suffix=<suffix>\n    Append <suffix> to the base name of all installed files, such that multiple\n    versions of jemalloc can coexist in the same installation directory.  For\n    example, libjemalloc.so.0 becomes libjemalloc<suffix>.so.0.\n\n--disable-cc-silence\n    Disable code that silences non-useful compiler warnings.  This is mainly\n    useful during development when auditing the set of warnings that are being\n    silenced.\n\n--enable-debug\n    Enable assertions and validation code.  This incurs a substantial\n    performance hit, but is very useful during application development.\n    Implies --enable-ivsalloc.\n\n--enable-code-coverage\n    Enable code coverage support, for use during jemalloc test development.\n    Additional testing targets are available if this option is enabled:\n\n      coverage\n      coverage_unit\n      coverage_integration\n      coverage_stress\n\n    These targets do not clear code coverage results from previous runs, and\n    there are interactions between the various coverage targets, so it is\n    usually advisable to run 'make clean' between repeated code coverage runs.\n\n--disable-stats\n    Disable statistics gathering functionality.  See the \"opt.stats_print\"\n    option documentation for usage details.\n\n--enable-ivsalloc\n    Enable validation code, which verifies that pointers reside within\n    jemalloc-owned chunks before dereferencing them.  This incurs a minor\n    performance hit.\n\n--enable-prof\n    Enable heap profiling and leak detection functionality.  See the \"opt.prof\"\n    option documentation for usage details.  When enabled, there are several\n    approaches to backtracing, and the configure script chooses the first one\n    in the following list that appears to function correctly:\n\n    + libunwind      (requires --enable-prof-libunwind)\n    + libgcc         (unless --disable-prof-libgcc)\n    + gcc intrinsics (unless --disable-prof-gcc)\n\n--enable-prof-libunwind\n    Use the libunwind library (http://www.nongnu.org/libunwind/) for stack\n    backtracing.\n\n--disable-prof-libgcc\n    Disable the use of libgcc's backtracing functionality.\n\n--disable-prof-gcc\n    Disable the use of gcc intrinsics for backtracing.\n\n--with-static-libunwind=<libunwind.a>\n    Statically link against the specified libunwind.a rather than dynamically\n    linking with -lunwind.\n\n--disable-tcache\n    Disable thread-specific caches for small objects.  Objects are cached and\n    released in bulk, thus reducing the total number of mutex operations.  See\n    the \"opt.tcache\" option for usage details.\n\n--disable-munmap\n    Disable virtual memory deallocation via munmap(2); instead keep track of\n    the virtual memory for later use.  munmap() is disabled by default (i.e.\n    --disable-munmap is implied) on Linux, which has a quirk in its virtual\n    memory allocation algorithm that causes semi-permanent VM map holes under\n    normal jemalloc operation.\n\n--disable-fill\n    Disable support for junk/zero filling of memory, quarantine, and redzones.\n    See the \"opt.junk\", \"opt.zero\", \"opt.quarantine\", and \"opt.redzone\" option\n    documentation for usage details.\n\n--disable-valgrind\n    Disable support for Valgrind.\n\n--disable-zone-allocator\n    Disable zone allocator for Darwin.  This means jemalloc won't be hooked as\n    the default allocator on OSX/iOS.\n\n--enable-utrace\n    Enable utrace(2)-based allocation tracing.  This feature is not broadly\n    portable (FreeBSD has it, but Linux and OS X do not).\n\n--enable-xmalloc\n    Enable support for optional immediate termination due to out-of-memory\n    errors, as is commonly implemented by \"xmalloc\" wrapper function for malloc.\n    See the \"opt.xmalloc\" option documentation for usage details.\n\n--enable-lazy-lock\n    Enable code that wraps pthread_create() to detect when an application\n    switches from single-threaded to multi-threaded mode, so that it can avoid\n    mutex locking/unlocking operations while in single-threaded mode.  In\n    practice, this feature usually has little impact on performance unless\n    thread-specific caching is disabled.\n\n--disable-tls\n    Disable thread-local storage (TLS), which allows for fast access to\n    thread-local variables via the __thread keyword.  If TLS is available,\n    jemalloc uses it for several purposes.\n\n--disable-cache-oblivious\n    Disable cache-oblivious large allocation alignment for large allocation\n    requests with no alignment constraints.  If this feature is disabled, all\n    large allocations are page-aligned as an implementation artifact, which can\n    severely harm CPU cache utilization.  However, the cache-oblivious layout\n    comes at the cost of one extra page per large allocation, which in the\n    most extreme case increases physical memory usage for the 16 KiB size class\n    to 20 KiB.\n\n--with-xslroot=<path>\n    Specify where to find DocBook XSL stylesheets when building the\n    documentation.\n\n--with-lg-page=<lg-page>\n    Specify the base 2 log of the system page size.  This option is only useful\n    when cross compiling, since the configure script automatically determines\n    the host's page size by default.\n\n--with-lg-page-sizes=<lg-page-sizes>\n    Specify the comma-separated base 2 logs of the page sizes to support.  This\n    option may be useful when cross-compiling in combination with\n    --with-lg-page, but its primary use case is for integration with FreeBSD's\n    libc, wherein jemalloc is embedded.\n\n--with-lg-size-class-group=<lg-size-class-group>\n    Specify the base 2 log of how many size classes to use for each doubling in\n    size.  By default jemalloc uses <lg-size-class-group>=2, which results in\n    e.g. the following size classes:\n\n      [...], 64,\n      80, 96, 112, 128,\n      160, [...]\n\n    <lg-size-class-group>=3 results in e.g. the following size classes:\n\n      [...], 64,\n      72, 80, 88, 96, 104, 112, 120, 128,\n      144, [...]\n\n    The minimal <lg-size-class-group>=0 causes jemalloc to only provide size\n    classes that are powers of 2:\n\n      [...],\n      64,\n      128,\n      256,\n      [...]\n\n    An implementation detail currently limits the total number of small size\n    classes to 255, and a compilation error will result if the\n    <lg-size-class-group> you specify cannot be supported.  The limit is\n    roughly <lg-size-class-group>=4, depending on page size.\n\n--with-lg-quantum=<lg-quantum>\n    Specify the base 2 log of the minimum allocation alignment.  jemalloc needs\n    to know the minimum alignment that meets the following C standard\n    requirement (quoted from the April 12, 2011 draft of the C11 standard):\n\n      The pointer returned if the allocation succeeds is suitably aligned so\n      that it may be assigned to a pointer to any type of object with a\n      fundamental alignment requirement and then used to access such an object\n      or an array of such objects in the space allocated [...]\n\n    This setting is architecture-specific, and although jemalloc includes known\n    safe values for the most commonly used modern architectures, there is a\n    wrinkle related to GNU libc (glibc) that may impact your choice of\n    <lg-quantum>.  On most modern architectures, this mandates 16-byte alignment\n    (<lg-quantum>=4), but the glibc developers chose not to meet this\n    requirement for performance reasons.  An old discussion can be found at\n    https://sourceware.org/bugzilla/show_bug.cgi?id=206 .  Unlike glibc,\n    jemalloc does follow the C standard by default (caveat: jemalloc\n    technically cheats if --with-lg-tiny-min is smaller than\n    --with-lg-quantum), but the fact that Linux systems already work around\n    this allocator noncompliance means that it is generally safe in practice to\n    let jemalloc's minimum alignment follow glibc's lead.  If you specify\n    --with-lg-quantum=3 during configuration, jemalloc will provide additional\n    size classes that are not 16-byte-aligned (24, 40, and 56, assuming\n    --with-lg-size-class-group=2).\n\n--with-lg-tiny-min=<lg-tiny-min>\n    Specify the base 2 log of the minimum tiny size class to support.  Tiny\n    size classes are powers of 2 less than the quantum, and are only\n    incorporated if <lg-tiny-min> is less than <lg-quantum> (see\n    --with-lg-quantum).  Tiny size classes technically violate the C standard\n    requirement for minimum alignment, and crashes could conceivably result if\n    the compiler were to generate instructions that made alignment assumptions,\n    both because illegal instruction traps could result, and because accesses\n    could straddle page boundaries and cause segmentation faults due to\n    accessing unmapped addresses.\n\n    The default of <lg-tiny-min>=3 works well in practice even on architectures\n    that technically require 16-byte alignment, probably for the same reason\n    --with-lg-quantum=3 works.  Smaller tiny size classes can, and will, cause\n    crashes (see https://bugzilla.mozilla.org/show_bug.cgi?id=691003 for an\n    example).\n\n    This option is rarely useful, and is mainly provided as documentation of a\n    subtle implementation detail.  If you do use this option, specify a\n    value in [3, ..., <lg-quantum>].\n\nThe following environment variables (not a definitive list) impact configure's\nbehavior:\n\nCFLAGS=\"?\"\n    Pass these flags to the compiler.  You probably shouldn't define this unless\n    you know what you are doing.  (Use EXTRA_CFLAGS instead.)\n\nEXTRA_CFLAGS=\"?\"\n    Append these flags to CFLAGS.  This makes it possible to add flags such as\n    -Werror, while allowing the configure script to determine what other flags\n    are appropriate for the specified configuration.\n\n    The configure script specifically checks whether an optimization flag (-O*)\n    is specified in EXTRA_CFLAGS, and refrains from specifying an optimization\n    level if it finds that one has already been specified.\n\nCPPFLAGS=\"?\"\n    Pass these flags to the C preprocessor.  Note that CFLAGS is not passed to\n    'cpp' when 'configure' is looking for include files, so you must use\n    CPPFLAGS instead if you need to help 'configure' find header files.\n\nLD_LIBRARY_PATH=\"?\"\n    'ld' uses this colon-separated list to find libraries.\n\nLDFLAGS=\"?\"\n    Pass these flags when linking.\n\nPATH=\"?\"\n    'configure' uses this to find programs.\n\n=== Advanced compilation =======================================================\n\nTo build only parts of jemalloc, use the following targets:\n\n    build_lib_shared\n    build_lib_static\n    build_lib\n    build_doc_html\n    build_doc_man\n    build_doc\n\nTo install only parts of jemalloc, use the following targets:\n\n    install_bin\n    install_include\n    install_lib_shared\n    install_lib_static\n    install_lib\n    install_doc_html\n    install_doc_man\n    install_doc\n\nTo clean up build results to varying degrees, use the following make targets:\n\n    clean\n    distclean\n    relclean\n\n=== Advanced installation ======================================================\n\nOptionally, define make variables when invoking make, including (not\nexclusively):\n\nINCLUDEDIR=\"?\"\n    Use this as the installation prefix for header files.\n\nLIBDIR=\"?\"\n    Use this as the installation prefix for libraries.\n\nMANDIR=\"?\"\n    Use this as the installation prefix for man pages.\n\nDESTDIR=\"?\"\n    Prepend DESTDIR to INCLUDEDIR, LIBDIR, DATADIR, and MANDIR.  This is useful\n    when installing to a different path than was specified via --prefix.\n\nCC=\"?\"\n    Use this to invoke the C compiler.\n\nCFLAGS=\"?\"\n    Pass these flags to the compiler.\n\nCPPFLAGS=\"?\"\n    Pass these flags to the C preprocessor.\n\nLDFLAGS=\"?\"\n    Pass these flags when linking.\n\nPATH=\"?\"\n    Use this to search for programs used during configuration and building.\n\n=== Development ================================================================\n\nIf you intend to make non-trivial changes to jemalloc, use the 'autogen.sh'\nscript rather than 'configure'.  This re-generates 'configure', enables\nconfiguration dependency rules, and enables re-generation of automatically\ngenerated source files.\n\nThe build system supports using an object directory separate from the source\ntree.  For example, you can create an 'obj' directory, and from within that\ndirectory, issue configuration and build commands:\n\n    autoconf\n    mkdir obj\n    cd obj\n    ../configure --enable-autogen\n    make\n\n=== Documentation ==============================================================\n\nThe manual page is generated in both html and roff formats.  Any web browser\ncan be used to view the html manual.  The roff manual page can be formatted\nprior to installation via the following command:\n\n    nroff -man -t doc/jemalloc.3\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.8/deps/jemalloc/Makefile.in",
    "content": "# Clear out all vpaths, then set just one (default vpath) for the main build\n# directory.\nvpath\nvpath % .\n\n# Clear the default suffixes, so that built-in rules are not used.\n.SUFFIXES :\n\nSHELL := /bin/sh\n\nCC := @CC@\n\n# Configuration parameters.\nDESTDIR =\nBINDIR := $(DESTDIR)@BINDIR@\nINCLUDEDIR := $(DESTDIR)@INCLUDEDIR@\nLIBDIR := $(DESTDIR)@LIBDIR@\nDATADIR := $(DESTDIR)@DATADIR@\nMANDIR := $(DESTDIR)@MANDIR@\nsrcroot := @srcroot@\nobjroot := @objroot@\nabs_srcroot := @abs_srcroot@\nabs_objroot := @abs_objroot@\n\n# Build parameters.\nCPPFLAGS := @CPPFLAGS@ -I$(srcroot)include -I$(objroot)include\nCFLAGS := @CFLAGS@\nLDFLAGS := @LDFLAGS@\nEXTRA_LDFLAGS := @EXTRA_LDFLAGS@\nLIBS := @LIBS@\nTESTLIBS := @TESTLIBS@\nRPATH_EXTRA := @RPATH_EXTRA@\nSO := @so@\nIMPORTLIB := @importlib@\nO := @o@\nA := @a@\nEXE := @exe@\nLIBPREFIX := @libprefix@\nREV := @rev@\ninstall_suffix := @install_suffix@\nABI := @abi@\nXSLTPROC := @XSLTPROC@\nAUTOCONF := @AUTOCONF@\n_RPATH = @RPATH@\nRPATH = $(if $(1),$(call _RPATH,$(1)))\ncfghdrs_in := $(addprefix $(srcroot),@cfghdrs_in@)\ncfghdrs_out := @cfghdrs_out@\ncfgoutputs_in := $(addprefix $(srcroot),@cfgoutputs_in@)\ncfgoutputs_out := @cfgoutputs_out@\nenable_autogen := @enable_autogen@\nenable_code_coverage := @enable_code_coverage@\nenable_prof := @enable_prof@\nenable_valgrind := @enable_valgrind@\nenable_zone_allocator := @enable_zone_allocator@\nMALLOC_CONF := @JEMALLOC_CPREFIX@MALLOC_CONF\nDSO_LDFLAGS = @DSO_LDFLAGS@\nSOREV = @SOREV@\nPIC_CFLAGS = @PIC_CFLAGS@\nCTARGET = @CTARGET@\nLDTARGET = @LDTARGET@\nMKLIB = @MKLIB@\nAR = @AR@\nARFLAGS = @ARFLAGS@\nCC_MM = @CC_MM@\n\nifeq (macho, $(ABI))\nTEST_LIBRARY_PATH := DYLD_FALLBACK_LIBRARY_PATH=\"$(objroot)lib\"\nelse\nifeq (pecoff, $(ABI))\nTEST_LIBRARY_PATH := PATH=\"$(PATH):$(objroot)lib\"\nelse\nTEST_LIBRARY_PATH :=\nendif\nendif\n\nLIBJEMALLOC := $(LIBPREFIX)jemalloc$(install_suffix)\n\n# Lists of files.\nBINS := $(objroot)bin/jemalloc-config $(objroot)bin/jemalloc.sh $(objroot)bin/jeprof\nC_HDRS := $(objroot)include/jemalloc/jemalloc$(install_suffix).h\nC_SRCS := $(srcroot)src/jemalloc.c $(srcroot)src/arena.c \\\n\t$(srcroot)src/atomic.c $(srcroot)src/base.c $(srcroot)src/bitmap.c \\\n\t$(srcroot)src/chunk.c $(srcroot)src/chunk_dss.c \\\n\t$(srcroot)src/chunk_mmap.c $(srcroot)src/ckh.c $(srcroot)src/ctl.c \\\n\t$(srcroot)src/extent.c $(srcroot)src/hash.c $(srcroot)src/huge.c \\\n\t$(srcroot)src/mb.c $(srcroot)src/mutex.c $(srcroot)src/pages.c \\\n\t$(srcroot)src/prof.c $(srcroot)src/quarantine.c $(srcroot)src/rtree.c \\\n\t$(srcroot)src/stats.c $(srcroot)src/tcache.c $(srcroot)src/util.c \\\n\t$(srcroot)src/tsd.c\nifeq ($(enable_valgrind), 1)\nC_SRCS += $(srcroot)src/valgrind.c\nendif\nifeq ($(enable_zone_allocator), 1)\nC_SRCS += $(srcroot)src/zone.c\nendif\nifeq ($(IMPORTLIB),$(SO))\nSTATIC_LIBS := $(objroot)lib/$(LIBJEMALLOC).$(A)\nendif\nifdef PIC_CFLAGS\nSTATIC_LIBS += $(objroot)lib/$(LIBJEMALLOC)_pic.$(A)\nelse\nSTATIC_LIBS += $(objroot)lib/$(LIBJEMALLOC)_s.$(A)\nendif\nDSOS := $(objroot)lib/$(LIBJEMALLOC).$(SOREV)\nifneq ($(SOREV),$(SO))\nDSOS += $(objroot)lib/$(LIBJEMALLOC).$(SO)\nendif\nPC := $(objroot)jemalloc.pc\nMAN3 := $(objroot)doc/jemalloc$(install_suffix).3\nDOCS_XML := $(objroot)doc/jemalloc$(install_suffix).xml\nDOCS_HTML := $(DOCS_XML:$(objroot)%.xml=$(objroot)%.html)\nDOCS_MAN3 := $(DOCS_XML:$(objroot)%.xml=$(objroot)%.3)\nDOCS := $(DOCS_HTML) $(DOCS_MAN3)\nC_TESTLIB_SRCS := $(srcroot)test/src/btalloc.c $(srcroot)test/src/btalloc_0.c \\\n\t$(srcroot)test/src/btalloc_1.c $(srcroot)test/src/math.c \\\n\t$(srcroot)test/src/mtx.c $(srcroot)test/src/mq.c \\\n\t$(srcroot)test/src/SFMT.c $(srcroot)test/src/test.c \\\n\t$(srcroot)test/src/thd.c $(srcroot)test/src/timer.c\nC_UTIL_INTEGRATION_SRCS := $(srcroot)src/util.c\nTESTS_UNIT := $(srcroot)test/unit/atomic.c \\\n\t$(srcroot)test/unit/bitmap.c \\\n\t$(srcroot)test/unit/ckh.c \\\n\t$(srcroot)test/unit/hash.c \\\n\t$(srcroot)test/unit/junk.c \\\n\t$(srcroot)test/unit/junk_alloc.c \\\n\t$(srcroot)test/unit/junk_free.c \\\n\t$(srcroot)test/unit/lg_chunk.c \\\n\t$(srcroot)test/unit/mallctl.c \\\n\t$(srcroot)test/unit/math.c \\\n\t$(srcroot)test/unit/mq.c \\\n\t$(srcroot)test/unit/mtx.c \\\n\t$(srcroot)test/unit/prof_accum.c \\\n\t$(srcroot)test/unit/prof_active.c \\\n\t$(srcroot)test/unit/prof_gdump.c \\\n\t$(srcroot)test/unit/prof_idump.c \\\n\t$(srcroot)test/unit/prof_reset.c \\\n\t$(srcroot)test/unit/prof_thread_name.c \\\n\t$(srcroot)test/unit/ql.c \\\n\t$(srcroot)test/unit/qr.c \\\n\t$(srcroot)test/unit/quarantine.c \\\n\t$(srcroot)test/unit/rb.c \\\n\t$(srcroot)test/unit/rtree.c \\\n\t$(srcroot)test/unit/SFMT.c \\\n\t$(srcroot)test/unit/size_classes.c \\\n\t$(srcroot)test/unit/stats.c \\\n\t$(srcroot)test/unit/tsd.c \\\n\t$(srcroot)test/unit/util.c \\\n\t$(srcroot)test/unit/zero.c\nTESTS_INTEGRATION := $(srcroot)test/integration/aligned_alloc.c \\\n\t$(srcroot)test/integration/allocated.c \\\n\t$(srcroot)test/integration/sdallocx.c \\\n\t$(srcroot)test/integration/mallocx.c \\\n\t$(srcroot)test/integration/MALLOCX_ARENA.c \\\n\t$(srcroot)test/integration/overflow.c \\\n\t$(srcroot)test/integration/posix_memalign.c \\\n\t$(srcroot)test/integration/rallocx.c \\\n\t$(srcroot)test/integration/thread_arena.c \\\n\t$(srcroot)test/integration/thread_tcache_enabled.c \\\n\t$(srcroot)test/integration/xallocx.c \\\n\t$(srcroot)test/integration/chunk.c\nTESTS_STRESS := $(srcroot)test/stress/microbench.c\nTESTS := $(TESTS_UNIT) $(TESTS_INTEGRATION) $(TESTS_STRESS)\n\nC_OBJS := $(C_SRCS:$(srcroot)%.c=$(objroot)%.$(O))\nC_PIC_OBJS := $(C_SRCS:$(srcroot)%.c=$(objroot)%.pic.$(O))\nC_JET_OBJS := $(C_SRCS:$(srcroot)%.c=$(objroot)%.jet.$(O))\nC_TESTLIB_UNIT_OBJS := $(C_TESTLIB_SRCS:$(srcroot)%.c=$(objroot)%.unit.$(O))\nC_TESTLIB_INTEGRATION_OBJS := $(C_TESTLIB_SRCS:$(srcroot)%.c=$(objroot)%.integration.$(O))\nC_UTIL_INTEGRATION_OBJS := $(C_UTIL_INTEGRATION_SRCS:$(srcroot)%.c=$(objroot)%.integration.$(O))\nC_TESTLIB_STRESS_OBJS := $(C_TESTLIB_SRCS:$(srcroot)%.c=$(objroot)%.stress.$(O))\nC_TESTLIB_OBJS := $(C_TESTLIB_UNIT_OBJS) $(C_TESTLIB_INTEGRATION_OBJS) $(C_UTIL_INTEGRATION_OBJS) $(C_TESTLIB_STRESS_OBJS)\n\nTESTS_UNIT_OBJS := $(TESTS_UNIT:$(srcroot)%.c=$(objroot)%.$(O))\nTESTS_INTEGRATION_OBJS := $(TESTS_INTEGRATION:$(srcroot)%.c=$(objroot)%.$(O))\nTESTS_STRESS_OBJS := $(TESTS_STRESS:$(srcroot)%.c=$(objroot)%.$(O))\nTESTS_OBJS := $(TESTS_UNIT_OBJS) $(TESTS_INTEGRATION_OBJS) $(TESTS_STRESS_OBJS)\n\n.PHONY: all dist build_doc_html build_doc_man build_doc\n.PHONY: install_bin install_include install_lib\n.PHONY: install_doc_html install_doc_man install_doc install\n.PHONY: tests check clean distclean relclean\n\n.SECONDARY : $(TESTS_OBJS)\n\n# Default target.\nall: build_lib\n\ndist: build_doc\n\n$(objroot)doc/%.html : $(objroot)doc/%.xml $(srcroot)doc/stylesheet.xsl $(objroot)doc/html.xsl\n\t$(XSLTPROC) -o $@ $(objroot)doc/html.xsl $<\n\n$(objroot)doc/%.3 : $(objroot)doc/%.xml $(srcroot)doc/stylesheet.xsl $(objroot)doc/manpages.xsl\n\t$(XSLTPROC) -o $@ $(objroot)doc/manpages.xsl $<\n\nbuild_doc_html: $(DOCS_HTML)\nbuild_doc_man: $(DOCS_MAN3)\nbuild_doc: $(DOCS)\n\n#\n# Include generated dependency files.\n#\nifdef CC_MM\n-include $(C_OBJS:%.$(O)=%.d)\n-include $(C_PIC_OBJS:%.$(O)=%.d)\n-include $(C_JET_OBJS:%.$(O)=%.d)\n-include $(C_TESTLIB_OBJS:%.$(O)=%.d)\n-include $(TESTS_OBJS:%.$(O)=%.d)\nendif\n\n$(C_OBJS): $(objroot)src/%.$(O): $(srcroot)src/%.c\n$(C_PIC_OBJS): $(objroot)src/%.pic.$(O): $(srcroot)src/%.c\n$(C_PIC_OBJS): CFLAGS += $(PIC_CFLAGS)\n$(C_JET_OBJS): $(objroot)src/%.jet.$(O): $(srcroot)src/%.c\n$(C_JET_OBJS): CFLAGS += -DJEMALLOC_JET\n$(C_TESTLIB_UNIT_OBJS): $(objroot)test/src/%.unit.$(O): $(srcroot)test/src/%.c\n$(C_TESTLIB_UNIT_OBJS): CPPFLAGS += -DJEMALLOC_UNIT_TEST\n$(C_TESTLIB_INTEGRATION_OBJS): $(objroot)test/src/%.integration.$(O): $(srcroot)test/src/%.c\n$(C_TESTLIB_INTEGRATION_OBJS): CPPFLAGS += -DJEMALLOC_INTEGRATION_TEST\n$(C_UTIL_INTEGRATION_OBJS): $(objroot)src/%.integration.$(O): $(srcroot)src/%.c\n$(C_TESTLIB_STRESS_OBJS): $(objroot)test/src/%.stress.$(O): $(srcroot)test/src/%.c\n$(C_TESTLIB_STRESS_OBJS): CPPFLAGS += -DJEMALLOC_STRESS_TEST -DJEMALLOC_STRESS_TESTLIB\n$(C_TESTLIB_OBJS): CPPFLAGS += -I$(srcroot)test/include -I$(objroot)test/include\n$(TESTS_UNIT_OBJS): CPPFLAGS += -DJEMALLOC_UNIT_TEST\n$(TESTS_INTEGRATION_OBJS): CPPFLAGS += -DJEMALLOC_INTEGRATION_TEST\n$(TESTS_STRESS_OBJS): CPPFLAGS += -DJEMALLOC_STRESS_TEST\n$(TESTS_OBJS): $(objroot)test/%.$(O): $(srcroot)test/%.c\n$(TESTS_OBJS): CPPFLAGS += -I$(srcroot)test/include -I$(objroot)test/include\nifneq ($(IMPORTLIB),$(SO))\n$(C_OBJS) $(C_JET_OBJS): CPPFLAGS += -DDLLEXPORT\nendif\n\nifndef CC_MM\n# Dependencies.\nHEADER_DIRS = $(srcroot)include/jemalloc/internal \\\n\t$(objroot)include/jemalloc $(objroot)include/jemalloc/internal\nHEADERS = $(wildcard $(foreach dir,$(HEADER_DIRS),$(dir)/*.h))\n$(C_OBJS) $(C_PIC_OBJS) $(C_JET_OBJS) $(C_TESTLIB_OBJS) $(TESTS_OBJS): $(HEADERS)\n$(TESTS_OBJS): $(objroot)test/include/test/jemalloc_test.h\nendif\n\n$(C_OBJS) $(C_PIC_OBJS) $(C_JET_OBJS) $(C_TESTLIB_OBJS) $(TESTS_OBJS): %.$(O):\n\t@mkdir -p $(@D)\n\t$(CC) $(CFLAGS) -c $(CPPFLAGS) $(CTARGET) $<\nifdef CC_MM\n\t@$(CC) -MM $(CPPFLAGS) -MT $@ -o $(@:%.$(O)=%.d) $<\nendif\n\nifneq ($(SOREV),$(SO))\n%.$(SO) : %.$(SOREV)\n\t@mkdir -p $(@D)\n\tln -sf $(<F) $@\nendif\n\n$(objroot)lib/$(LIBJEMALLOC).$(SOREV) : $(if $(PIC_CFLAGS),$(C_PIC_OBJS),$(C_OBJS))\n\t@mkdir -p $(@D)\n\t$(CC) $(DSO_LDFLAGS) $(call RPATH,$(RPATH_EXTRA)) $(LDTARGET) $+ $(LDFLAGS) $(LIBS) $(EXTRA_LDFLAGS)\n\n$(objroot)lib/$(LIBJEMALLOC)_pic.$(A) : $(C_PIC_OBJS)\n$(objroot)lib/$(LIBJEMALLOC).$(A) : $(C_OBJS)\n$(objroot)lib/$(LIBJEMALLOC)_s.$(A) : $(C_OBJS)\n\n$(STATIC_LIBS):\n\t@mkdir -p $(@D)\n\t$(AR) $(ARFLAGS)@AROUT@ $+\n\n$(objroot)test/unit/%$(EXE): $(objroot)test/unit/%.$(O) $(TESTS_UNIT_LINK_OBJS) $(C_JET_OBJS) $(C_TESTLIB_UNIT_OBJS)\n\t@mkdir -p $(@D)\n\t$(CC) $(LDTARGET) $(filter %.$(O),$^) $(call RPATH,$(objroot)lib) $(LDFLAGS) $(filter-out -lm,$(LIBS)) -lm $(TESTLIBS) $(EXTRA_LDFLAGS)\n\n$(objroot)test/integration/%$(EXE): $(objroot)test/integration/%.$(O) $(C_TESTLIB_INTEGRATION_OBJS) $(C_UTIL_INTEGRATION_OBJS) $(objroot)lib/$(LIBJEMALLOC).$(IMPORTLIB)\n\t@mkdir -p $(@D)\n\t$(CC) $(LDTARGET) $(filter %.$(O),$^) $(call RPATH,$(objroot)lib) $(objroot)lib/$(LIBJEMALLOC).$(IMPORTLIB) $(LDFLAGS) $(filter-out -lm,$(filter -lpthread,$(LIBS))) -lm $(TESTLIBS) $(EXTRA_LDFLAGS)\n\n$(objroot)test/stress/%$(EXE): $(objroot)test/stress/%.$(O) $(C_JET_OBJS) $(C_TESTLIB_STRESS_OBJS) $(objroot)lib/$(LIBJEMALLOC).$(IMPORTLIB)\n\t@mkdir -p $(@D)\n\t$(CC) $(LDTARGET) $(filter %.$(O),$^) $(call RPATH,$(objroot)lib) $(objroot)lib/$(LIBJEMALLOC).$(IMPORTLIB) $(LDFLAGS) $(filter-out -lm,$(LIBS)) -lm $(TESTLIBS) $(EXTRA_LDFLAGS)\n\nbuild_lib_shared: $(DSOS)\nbuild_lib_static: $(STATIC_LIBS)\nbuild_lib: build_lib_shared build_lib_static\n\ninstall_bin:\n\tinstall -d $(BINDIR)\n\t@for b in $(BINS); do \\\n\techo \"install -m 755 $$b $(BINDIR)\"; \\\n\tinstall -m 755 $$b $(BINDIR); \\\ndone\n\ninstall_include:\n\tinstall -d $(INCLUDEDIR)/jemalloc\n\t@for h in $(C_HDRS); do \\\n\techo \"install -m 644 $$h $(INCLUDEDIR)/jemalloc\"; \\\n\tinstall -m 644 $$h $(INCLUDEDIR)/jemalloc; \\\ndone\n\ninstall_lib_shared: $(DSOS)\n\tinstall -d $(LIBDIR)\n\tinstall -m 755 $(objroot)lib/$(LIBJEMALLOC).$(SOREV) $(LIBDIR)\nifneq ($(SOREV),$(SO))\n\tln -sf $(LIBJEMALLOC).$(SOREV) $(LIBDIR)/$(LIBJEMALLOC).$(SO)\nendif\n\ninstall_lib_static: $(STATIC_LIBS)\n\tinstall -d $(LIBDIR)\n\t@for l in $(STATIC_LIBS); do \\\n\techo \"install -m 755 $$l $(LIBDIR)\"; \\\n\tinstall -m 755 $$l $(LIBDIR); \\\ndone\n\ninstall_lib_pc: $(PC)\n\tinstall -d $(LIBDIR)/pkgconfig\n\t@for l in $(PC); do \\\n\techo \"install -m 644 $$l $(LIBDIR)/pkgconfig\"; \\\n\tinstall -m 644 $$l $(LIBDIR)/pkgconfig; \\\ndone\n\ninstall_lib: install_lib_shared install_lib_static install_lib_pc\n\ninstall_doc_html:\n\tinstall -d $(DATADIR)/doc/jemalloc$(install_suffix)\n\t@for d in $(DOCS_HTML); do \\\n\techo \"install -m 644 $$d $(DATADIR)/doc/jemalloc$(install_suffix)\"; \\\n\tinstall -m 644 $$d $(DATADIR)/doc/jemalloc$(install_suffix); \\\ndone\n\ninstall_doc_man:\n\tinstall -d $(MANDIR)/man3\n\t@for d in $(DOCS_MAN3); do \\\n\techo \"install -m 644 $$d $(MANDIR)/man3\"; \\\n\tinstall -m 644 $$d $(MANDIR)/man3; \\\ndone\n\ninstall_doc: install_doc_html install_doc_man\n\ninstall: install_bin install_include install_lib install_doc\n\ntests_unit: $(TESTS_UNIT:$(srcroot)%.c=$(objroot)%$(EXE))\ntests_integration: $(TESTS_INTEGRATION:$(srcroot)%.c=$(objroot)%$(EXE))\ntests_stress: $(TESTS_STRESS:$(srcroot)%.c=$(objroot)%$(EXE))\ntests: tests_unit tests_integration tests_stress\n\ncheck_unit_dir:\n\t@mkdir -p $(objroot)test/unit\ncheck_integration_dir:\n\t@mkdir -p $(objroot)test/integration\nstress_dir:\n\t@mkdir -p $(objroot)test/stress\ncheck_dir: check_unit_dir check_integration_dir\n\ncheck_unit: tests_unit check_unit_dir\n\t$(SHELL) $(objroot)test/test.sh $(TESTS_UNIT:$(srcroot)%.c=$(objroot)%)\ncheck_integration_prof: tests_integration check_integration_dir\nifeq ($(enable_prof), 1)\n\t$(MALLOC_CONF)=\"prof:true\" $(SHELL) $(objroot)test/test.sh $(TESTS_INTEGRATION:$(srcroot)%.c=$(objroot)%)\n\t$(MALLOC_CONF)=\"prof:true,prof_active:false\" $(SHELL) $(objroot)test/test.sh $(TESTS_INTEGRATION:$(srcroot)%.c=$(objroot)%)\nendif\ncheck_integration: tests_integration check_integration_dir\n\t$(SHELL) $(objroot)test/test.sh $(TESTS_INTEGRATION:$(srcroot)%.c=$(objroot)%)\nstress: tests_stress stress_dir\n\t$(SHELL) $(objroot)test/test.sh $(TESTS_STRESS:$(srcroot)%.c=$(objroot)%)\ncheck: tests check_dir check_integration_prof\n\t$(SHELL) $(objroot)test/test.sh $(TESTS_UNIT:$(srcroot)%.c=$(objroot)%) $(TESTS_INTEGRATION:$(srcroot)%.c=$(objroot)%)\n\nifeq ($(enable_code_coverage), 1)\ncoverage_unit: check_unit\n\t$(SHELL) $(srcroot)coverage.sh $(srcroot)src jet $(C_JET_OBJS)\n\t$(SHELL) $(srcroot)coverage.sh $(srcroot)test/src unit $(C_TESTLIB_UNIT_OBJS)\n\t$(SHELL) $(srcroot)coverage.sh $(srcroot)test/unit unit $(TESTS_UNIT_OBJS)\n\ncoverage_integration: check_integration\n\t$(SHELL) $(srcroot)coverage.sh $(srcroot)src pic $(C_PIC_OBJS)\n\t$(SHELL) $(srcroot)coverage.sh $(srcroot)src integration $(C_UTIL_INTEGRATION_OBJS)\n\t$(SHELL) $(srcroot)coverage.sh $(srcroot)test/src integration $(C_TESTLIB_INTEGRATION_OBJS)\n\t$(SHELL) $(srcroot)coverage.sh $(srcroot)test/integration integration $(TESTS_INTEGRATION_OBJS)\n\ncoverage_stress: stress\n\t$(SHELL) $(srcroot)coverage.sh $(srcroot)src pic $(C_PIC_OBJS)\n\t$(SHELL) $(srcroot)coverage.sh $(srcroot)src jet $(C_JET_OBJS)\n\t$(SHELL) $(srcroot)coverage.sh $(srcroot)test/src stress $(C_TESTLIB_STRESS_OBJS)\n\t$(SHELL) $(srcroot)coverage.sh $(srcroot)test/stress stress $(TESTS_STRESS_OBJS)\n\ncoverage: check\n\t$(SHELL) $(srcroot)coverage.sh $(srcroot)src pic $(C_PIC_OBJS)\n\t$(SHELL) $(srcroot)coverage.sh $(srcroot)src jet $(C_JET_OBJS)\n\t$(SHELL) $(srcroot)coverage.sh $(srcroot)src integration $(C_UTIL_INTEGRATION_OBJS)\n\t$(SHELL) $(srcroot)coverage.sh $(srcroot)test/src unit $(C_TESTLIB_UNIT_OBJS)\n\t$(SHELL) $(srcroot)coverage.sh $(srcroot)test/src integration $(C_TESTLIB_INTEGRATION_OBJS)\n\t$(SHELL) $(srcroot)coverage.sh $(srcroot)test/src stress $(C_TESTLIB_STRESS_OBJS)\n\t$(SHELL) $(srcroot)coverage.sh $(srcroot)test/unit unit $(TESTS_UNIT_OBJS) $(TESTS_UNIT_AUX_OBJS)\n\t$(SHELL) $(srcroot)coverage.sh $(srcroot)test/integration integration $(TESTS_INTEGRATION_OBJS)\n\t$(SHELL) $(srcroot)coverage.sh $(srcroot)test/stress integration $(TESTS_STRESS_OBJS)\nendif\n\nclean:\n\trm -f $(C_OBJS)\n\trm -f $(C_PIC_OBJS)\n\trm -f $(C_JET_OBJS)\n\trm -f $(C_TESTLIB_OBJS)\n\trm -f $(C_OBJS:%.$(O)=%.d)\n\trm -f $(C_OBJS:%.$(O)=%.gcda)\n\trm -f $(C_OBJS:%.$(O)=%.gcno)\n\trm -f $(C_PIC_OBJS:%.$(O)=%.d)\n\trm -f $(C_PIC_OBJS:%.$(O)=%.gcda)\n\trm -f $(C_PIC_OBJS:%.$(O)=%.gcno)\n\trm -f $(C_JET_OBJS:%.$(O)=%.d)\n\trm -f $(C_JET_OBJS:%.$(O)=%.gcda)\n\trm -f $(C_JET_OBJS:%.$(O)=%.gcno)\n\trm -f $(C_TESTLIB_OBJS:%.$(O)=%.d)\n\trm -f $(C_TESTLIB_OBJS:%.$(O)=%.gcda)\n\trm -f $(C_TESTLIB_OBJS:%.$(O)=%.gcno)\n\trm -f $(TESTS_OBJS:%.$(O)=%$(EXE))\n\trm -f $(TESTS_OBJS)\n\trm -f $(TESTS_OBJS:%.$(O)=%.d)\n\trm -f $(TESTS_OBJS:%.$(O)=%.gcda)\n\trm -f $(TESTS_OBJS:%.$(O)=%.gcno)\n\trm -f $(TESTS_OBJS:%.$(O)=%.out)\n\trm -f $(DSOS) $(STATIC_LIBS)\n\trm -f $(objroot)*.gcov.*\n\ndistclean: clean\n\trm -f $(objroot)bin/jemalloc-config\n\trm -f $(objroot)bin/jemalloc.sh\n\trm -f $(objroot)bin/jeprof\n\trm -f $(objroot)config.log\n\trm -f $(objroot)config.status\n\trm -f $(objroot)config.stamp\n\trm -f $(cfghdrs_out)\n\trm -f $(cfgoutputs_out)\n\nrelclean: distclean\n\trm -f $(objroot)configure\n\trm -f $(objroot)VERSION\n\trm -f $(DOCS_HTML)\n\trm -f $(DOCS_MAN3)\n\n#===============================================================================\n# Re-configuration rules.\n\nifeq ($(enable_autogen), 1)\n$(srcroot)configure : $(srcroot)configure.ac\n\tcd ./$(srcroot) && $(AUTOCONF)\n\n$(objroot)config.status : $(srcroot)configure\n\t./$(objroot)config.status --recheck\n\n$(srcroot)config.stamp.in : $(srcroot)configure.ac\n\techo stamp > $(srcroot)config.stamp.in\n\n$(objroot)config.stamp : $(cfgoutputs_in) $(cfghdrs_in) $(srcroot)configure\n\t./$(objroot)config.status\n\t@touch $@\n\n# There must be some action in order for make to re-read Makefile when it is\n# out of date.\n$(cfgoutputs_out) $(cfghdrs_out) : $(objroot)config.stamp\n\t@true\nendif\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.8/deps/jemalloc/README",
    "content": "jemalloc is a general purpose malloc(3) implementation that emphasizes\nfragmentation avoidance and scalable concurrency support.  jemalloc first came\ninto use as the FreeBSD libc allocator in 2005, and since then it has found its\nway into numerous applications that rely on its predictable behavior.  In 2010\njemalloc development efforts broadened to include developer support features\nsuch as heap profiling, Valgrind integration, and extensive monitoring/tuning\nhooks.  Modern jemalloc releases continue to be integrated back into FreeBSD,\nand therefore versatility remains critical.  Ongoing development efforts trend\ntoward making jemalloc among the best allocators for a broad range of demanding\napplications, and eliminating/mitigating weaknesses that have practical\nrepercussions for real world applications.\n\nThe COPYING file contains copyright and licensing information.\n\nThe INSTALL file contains information on how to configure, build, and install\njemalloc.\n\nThe ChangeLog file contains a brief summary of changes for each release.\n\nURL: http://www.canonware.com/jemalloc/\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.8/deps/jemalloc/VERSION",
    "content": "4.0.3-0-ge9192eacf8935e29fc62fddc2701f7942b1cc02c\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.8/deps/jemalloc/autogen.sh",
    "content": "#!/bin/sh\n\nfor i in autoconf; do\n    echo \"$i\"\n    $i\n    if [ $? -ne 0 ]; then\n\techo \"Error $? in $i\"\n\texit 1\n    fi\ndone\n\necho \"./configure --enable-autogen $@\"\n./configure --enable-autogen $@\nif [ $? -ne 0 ]; then\n    echo \"Error $? in ./configure\"\n    exit 1\nfi\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.8/deps/jemalloc/bin/jemalloc-config.in",
    "content": "#!/bin/sh\n\nusage() {\n\tcat <<EOF\nUsage:\n  @BINDIR@/jemalloc-config <option>\nOptions:\n  --help | -h  : Print usage.\n  --version    : Print jemalloc version.\n  --revision   : Print shared library revision number.\n  --config     : Print configure options used to build jemalloc.\n  --prefix     : Print installation directory prefix.\n  --bindir     : Print binary installation directory.\n  --datadir    : Print data installation directory.\n  --includedir : Print include installation directory.\n  --libdir     : Print library installation directory.\n  --mandir     : Print manual page installation directory.\n  --cc         : Print compiler used to build jemalloc.\n  --cflags     : Print compiler flags used to build jemalloc.\n  --cppflags   : Print preprocessor flags used to build jemalloc.\n  --ldflags    : Print library flags used to build jemalloc.\n  --libs       : Print libraries jemalloc was linked against.\nEOF\n}\n\nprefix=\"@prefix@\"\nexec_prefix=\"@exec_prefix@\"\n\ncase \"$1\" in\n--help | -h)\n\tusage\n\texit 0\n\t;;\n--version)\n\techo \"@jemalloc_version@\"\n\t;;\n--revision)\n\techo \"@rev@\"\n\t;;\n--config)\n\techo \"@CONFIG@\"\n\t;;\n--prefix)\n\techo \"@PREFIX@\"\n\t;;\n--bindir)\n\techo \"@BINDIR@\"\n\t;;\n--datadir)\n\techo \"@DATADIR@\"\n\t;;\n--includedir)\n\techo \"@INCLUDEDIR@\"\n\t;;\n--libdir)\n\techo \"@LIBDIR@\"\n\t;;\n--mandir)\n\techo \"@MANDIR@\"\n\t;;\n--cc)\n\techo \"@CC@\"\n\t;;\n--cflags)\n\techo \"@CFLAGS@\"\n\t;;\n--cppflags)\n\techo \"@CPPFLAGS@\"\n\t;;\n--ldflags)\n\techo \"@LDFLAGS@ @EXTRA_LDFLAGS@\"\n\t;;\n--libs)\n\techo \"@LIBS@\"\n\t;;\n*)\n\tusage\n\texit 1\nesac\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.8/deps/jemalloc/bin/jemalloc.sh.in",
    "content": "#!/bin/sh\n\nprefix=@prefix@\nexec_prefix=@exec_prefix@\nlibdir=@libdir@\n\n@LD_PRELOAD_VAR@=${libdir}/libjemalloc.@SOREV@\nexport @LD_PRELOAD_VAR@\nexec \"$@\"\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.8/deps/jemalloc/bin/jeprof.in",
    "content": "#! /usr/bin/env perl\n\n# Copyright (c) 1998-2007, Google Inc.\n# All rights reserved.\n#\n# Redistribution and use in source and binary forms, with or without\n# modification, are permitted provided that the following conditions are\n# met:\n#\n#     * Redistributions of source code must retain the above copyright\n# notice, this list of conditions and the following disclaimer.\n#     * Redistributions in binary form must reproduce the above\n# copyright notice, this list of conditions and the following disclaimer\n# in the documentation and/or other materials provided with the\n# distribution.\n#     * Neither the name of Google Inc. nor the names of its\n# contributors may be used to endorse or promote products derived from\n# this software without specific prior written permission.\n#\n# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n# \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\n# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\n# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\n# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\n# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n\n# ---\n# Program for printing the profile generated by common/profiler.cc,\n# or by the heap profiler (common/debugallocation.cc)\n#\n# The profile contains a sequence of entries of the form:\n#       <count> <stack trace>\n# This program parses the profile, and generates user-readable\n# output.\n#\n# Examples:\n#\n# % tools/jeprof \"program\" \"profile\"\n#   Enters \"interactive\" mode\n#\n# % tools/jeprof --text \"program\" \"profile\"\n#   Generates one line per procedure\n#\n# % tools/jeprof --gv \"program\" \"profile\"\n#   Generates annotated call-graph and displays via \"gv\"\n#\n# % tools/jeprof --gv --focus=Mutex \"program\" \"profile\"\n#   Restrict to code paths that involve an entry that matches \"Mutex\"\n#\n# % tools/jeprof --gv --focus=Mutex --ignore=string \"program\" \"profile\"\n#   Restrict to code paths that involve an entry that matches \"Mutex\"\n#   and does not match \"string\"\n#\n# % tools/jeprof --list=IBF_CheckDocid \"program\" \"profile\"\n#   Generates disassembly listing of all routines with at least one\n#   sample that match the --list=<regexp> pattern.  The listing is\n#   annotated with the flat and cumulative sample counts at each line.\n#\n# % tools/jeprof --disasm=IBF_CheckDocid \"program\" \"profile\"\n#   Generates disassembly listing of all routines with at least one\n#   sample that match the --disasm=<regexp> pattern.  The listing is\n#   annotated with the flat and cumulative sample counts at each PC value.\n#\n# TODO: Use color to indicate files?\n\nuse strict;\nuse warnings;\nuse Getopt::Long;\n\nmy $JEPROF_VERSION = \"@jemalloc_version@\";\nmy $PPROF_VERSION = \"2.0\";\n\n# These are the object tools we use which can come from a\n# user-specified location using --tools, from the JEPROF_TOOLS\n# environment variable, or from the environment.\nmy %obj_tool_map = (\n  \"objdump\" => \"objdump\",\n  \"nm\" => \"nm\",\n  \"addr2line\" => \"addr2line\",\n  \"c++filt\" => \"c++filt\",\n  ## ConfigureObjTools may add architecture-specific entries:\n  #\"nm_pdb\" => \"nm-pdb\",       # for reading windows (PDB-format) executables\n  #\"addr2line_pdb\" => \"addr2line-pdb\",                                # ditto\n  #\"otool\" => \"otool\",         # equivalent of objdump on OS X\n);\n# NOTE: these are lists, so you can put in commandline flags if you want.\nmy @DOT = (\"dot\");          # leave non-absolute, since it may be in /usr/local\nmy @GV = (\"gv\");\nmy @EVINCE = (\"evince\");    # could also be xpdf or perhaps acroread\nmy @KCACHEGRIND = (\"kcachegrind\");\nmy @PS2PDF = (\"ps2pdf\");\n# These are used for dynamic profiles\nmy @URL_FETCHER = (\"curl\", \"-s\");\n\n# These are the web pages that servers need to support for dynamic profiles\nmy $HEAP_PAGE = \"/pprof/heap\";\nmy $PROFILE_PAGE = \"/pprof/profile\";   # must support cgi-param \"?seconds=#\"\nmy $PMUPROFILE_PAGE = \"/pprof/pmuprofile(?:\\\\?.*)?\"; # must support cgi-param\n                                                # ?seconds=#&event=x&period=n\nmy $GROWTH_PAGE = \"/pprof/growth\";\nmy $CONTENTION_PAGE = \"/pprof/contention\";\nmy $WALL_PAGE = \"/pprof/wall(?:\\\\?.*)?\";  # accepts options like namefilter\nmy $FILTEREDPROFILE_PAGE = \"/pprof/filteredprofile(?:\\\\?.*)?\";\nmy $CENSUSPROFILE_PAGE = \"/pprof/censusprofile(?:\\\\?.*)?\"; # must support cgi-param\n                                                       # \"?seconds=#\",\n                                                       # \"?tags_regexp=#\" and\n                                                       # \"?type=#\".\nmy $SYMBOL_PAGE = \"/pprof/symbol\";     # must support symbol lookup via POST\nmy $PROGRAM_NAME_PAGE = \"/pprof/cmdline\";\n\n# These are the web pages that can be named on the command line.\n# All the alternatives must begin with /.\nmy $PROFILES = \"($HEAP_PAGE|$PROFILE_PAGE|$PMUPROFILE_PAGE|\" .\n               \"$GROWTH_PAGE|$CONTENTION_PAGE|$WALL_PAGE|\" .\n               \"$FILTEREDPROFILE_PAGE|$CENSUSPROFILE_PAGE)\";\n\n# default binary name\nmy $UNKNOWN_BINARY = \"(unknown)\";\n\n# There is a pervasive dependency on the length (in hex characters,\n# i.e., nibbles) of an address, distinguishing between 32-bit and\n# 64-bit profiles.  To err on the safe size, default to 64-bit here:\nmy $address_length = 16;\n\nmy $dev_null = \"/dev/null\";\nif (! -e $dev_null && $^O =~ /MSWin/) {    # $^O is the OS perl was built for\n  $dev_null = \"nul\";\n}\n\n# A list of paths to search for shared object files\nmy @prefix_list = ();\n\n# Special routine name that should not have any symbols.\n# Used as separator to parse \"addr2line -i\" output.\nmy $sep_symbol = '_fini';\nmy $sep_address = undef;\n\n##### Argument parsing #####\n\nsub usage_string {\n  return <<EOF;\nUsage:\njeprof [options] <program> <profiles>\n   <profiles> is a space separated list of profile names.\njeprof [options] <symbolized-profiles>\n   <symbolized-profiles> is a list of profile files where each file contains\n   the necessary symbol mappings  as well as profile data (likely generated\n   with --raw).\njeprof [options] <profile>\n   <profile> is a remote form.  Symbols are obtained from host:port$SYMBOL_PAGE\n\n   Each name can be:\n   /path/to/profile        - a path to a profile file\n   host:port[/<service>]   - a location of a service to get profile from\n\n   The /<service> can be $HEAP_PAGE, $PROFILE_PAGE, /pprof/pmuprofile,\n                         $GROWTH_PAGE, $CONTENTION_PAGE, /pprof/wall,\n                         $CENSUSPROFILE_PAGE, or /pprof/filteredprofile.\n   For instance:\n     jeprof http://myserver.com:80$HEAP_PAGE\n   If /<service> is omitted, the service defaults to $PROFILE_PAGE (cpu profiling).\njeprof --symbols <program>\n   Maps addresses to symbol names.  In this mode, stdin should be a\n   list of library mappings, in the same format as is found in the heap-\n   and cpu-profile files (this loosely matches that of /proc/self/maps\n   on linux), followed by a list of hex addresses to map, one per line.\n\n   For more help with querying remote servers, including how to add the\n   necessary server-side support code, see this filename (or one like it):\n\n   /usr/doc/gperftools-$PPROF_VERSION/pprof_remote_servers.html\n\nOptions:\n   --cum               Sort by cumulative data\n   --base=<base>       Subtract <base> from <profile> before display\n   --interactive       Run in interactive mode (interactive \"help\" gives help) [default]\n   --seconds=<n>       Length of time for dynamic profiles [default=30 secs]\n   --add_lib=<file>    Read additional symbols and line info from the given library\n   --lib_prefix=<dir>  Comma separated list of library path prefixes\n\nReporting Granularity:\n   --addresses         Report at address level\n   --lines             Report at source line level\n   --functions         Report at function level [default]\n   --files             Report at source file level\n\nOutput type:\n   --text              Generate text report\n   --callgrind         Generate callgrind format to stdout\n   --gv                Generate Postscript and display\n   --evince            Generate PDF and display\n   --web               Generate SVG and display\n   --list=<regexp>     Generate source listing of matching routines\n   --disasm=<regexp>   Generate disassembly of matching routines\n   --symbols           Print demangled symbol names found at given addresses\n   --dot               Generate DOT file to stdout\n   --ps                Generate Postcript to stdout\n   --pdf               Generate PDF to stdout\n   --svg               Generate SVG to stdout\n   --gif               Generate GIF to stdout\n   --raw               Generate symbolized jeprof data (useful with remote fetch)\n\nHeap-Profile Options:\n   --inuse_space       Display in-use (mega)bytes [default]\n   --inuse_objects     Display in-use objects\n   --alloc_space       Display allocated (mega)bytes\n   --alloc_objects     Display allocated objects\n   --show_bytes        Display space in bytes\n   --drop_negative     Ignore negative differences\n\nContention-profile options:\n   --total_delay       Display total delay at each region [default]\n   --contentions       Display number of delays at each region\n   --mean_delay        Display mean delay at each region\n\nCall-graph Options:\n   --nodecount=<n>     Show at most so many nodes [default=80]\n   --nodefraction=<f>  Hide nodes below <f>*total [default=.005]\n   --edgefraction=<f>  Hide edges below <f>*total [default=.001]\n   --maxdegree=<n>     Max incoming/outgoing edges per node [default=8]\n   --focus=<regexp>    Focus on nodes matching <regexp>\n   --thread=<n>        Show profile for thread <n>\n   --ignore=<regexp>   Ignore nodes matching <regexp>\n   --scale=<n>         Set GV scaling [default=0]\n   --heapcheck         Make nodes with non-0 object counts\n                       (i.e. direct leak generators) more visible\n\nMiscellaneous:\n   --tools=<prefix or binary:fullpath>[,...]   \\$PATH for object tool pathnames\n   --test              Run unit tests\n   --help              This message\n   --version           Version information\n\nEnvironment Variables:\n   JEPROF_TMPDIR        Profiles directory. Defaults to \\$HOME/jeprof\n   JEPROF_TOOLS         Prefix for object tools pathnames\n\nExamples:\n\njeprof /bin/ls ls.prof\n                       Enters \"interactive\" mode\njeprof --text /bin/ls ls.prof\n                       Outputs one line per procedure\njeprof --web /bin/ls ls.prof\n                       Displays annotated call-graph in web browser\njeprof --gv /bin/ls ls.prof\n                       Displays annotated call-graph via 'gv'\njeprof --gv --focus=Mutex /bin/ls ls.prof\n                       Restricts to code paths including a .*Mutex.* entry\njeprof --gv --focus=Mutex --ignore=string /bin/ls ls.prof\n                       Code paths including Mutex but not string\njeprof --list=getdir /bin/ls ls.prof\n                       (Per-line) annotated source listing for getdir()\njeprof --disasm=getdir /bin/ls ls.prof\n                       (Per-PC) annotated disassembly for getdir()\n\njeprof http://localhost:1234/\n                       Enters \"interactive\" mode\njeprof --text localhost:1234\n                       Outputs one line per procedure for localhost:1234\njeprof --raw localhost:1234 > ./local.raw\njeprof --text ./local.raw\n                       Fetches a remote profile for later analysis and then\n                       analyzes it in text mode.\nEOF\n}\n\nsub version_string {\n  return <<EOF\njeprof (part of jemalloc $JEPROF_VERSION)\nbased on pprof (part of gperftools $PPROF_VERSION)\n\nCopyright 1998-2007 Google Inc.\n\nThis is BSD licensed software; see the source for copying conditions\nand license information.\nThere is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A\nPARTICULAR PURPOSE.\nEOF\n}\n\nsub usage {\n  my $msg = shift;\n  print STDERR \"$msg\\n\\n\";\n  print STDERR usage_string();\n  print STDERR \"\\nFATAL ERROR: $msg\\n\";    # just as a reminder\n  exit(1);\n}\n\nsub Init() {\n  # Setup tmp-file name and handler to clean it up.\n  # We do this in the very beginning so that we can use\n  # error() and cleanup() function anytime here after.\n  $main::tmpfile_sym = \"/tmp/jeprof$$.sym\";\n  $main::tmpfile_ps = \"/tmp/jeprof$$\";\n  $main::next_tmpfile = 0;\n  $SIG{'INT'} = \\&sighandler;\n\n  # Cache from filename/linenumber to source code\n  $main::source_cache = ();\n\n  $main::opt_help = 0;\n  $main::opt_version = 0;\n\n  $main::opt_cum = 0;\n  $main::opt_base = '';\n  $main::opt_addresses = 0;\n  $main::opt_lines = 0;\n  $main::opt_functions = 0;\n  $main::opt_files = 0;\n  $main::opt_lib_prefix = \"\";\n\n  $main::opt_text = 0;\n  $main::opt_callgrind = 0;\n  $main::opt_list = \"\";\n  $main::opt_disasm = \"\";\n  $main::opt_symbols = 0;\n  $main::opt_gv = 0;\n  $main::opt_evince = 0;\n  $main::opt_web = 0;\n  $main::opt_dot = 0;\n  $main::opt_ps = 0;\n  $main::opt_pdf = 0;\n  $main::opt_gif = 0;\n  $main::opt_svg = 0;\n  $main::opt_raw = 0;\n\n  $main::opt_nodecount = 80;\n  $main::opt_nodefraction = 0.005;\n  $main::opt_edgefraction = 0.001;\n  $main::opt_maxdegree = 8;\n  $main::opt_focus = '';\n  $main::opt_thread = undef;\n  $main::opt_ignore = '';\n  $main::opt_scale = 0;\n  $main::opt_heapcheck = 0;\n  $main::opt_seconds = 30;\n  $main::opt_lib = \"\";\n\n  $main::opt_inuse_space   = 0;\n  $main::opt_inuse_objects = 0;\n  $main::opt_alloc_space   = 0;\n  $main::opt_alloc_objects = 0;\n  $main::opt_show_bytes    = 0;\n  $main::opt_drop_negative = 0;\n  $main::opt_interactive   = 0;\n\n  $main::opt_total_delay = 0;\n  $main::opt_contentions = 0;\n  $main::opt_mean_delay = 0;\n\n  $main::opt_tools   = \"\";\n  $main::opt_debug   = 0;\n  $main::opt_test    = 0;\n\n  # These are undocumented flags used only by unittests.\n  $main::opt_test_stride = 0;\n\n  # Are we using $SYMBOL_PAGE?\n  $main::use_symbol_page = 0;\n\n  # Files returned by TempName.\n  %main::tempnames = ();\n\n  # Type of profile we are dealing with\n  # Supported types:\n  #     cpu\n  #     heap\n  #     growth\n  #     contention\n  $main::profile_type = '';     # Empty type means \"unknown\"\n\n  GetOptions(\"help!\"          => \\$main::opt_help,\n             \"version!\"       => \\$main::opt_version,\n             \"cum!\"           => \\$main::opt_cum,\n             \"base=s\"         => \\$main::opt_base,\n             \"seconds=i\"      => \\$main::opt_seconds,\n             \"add_lib=s\"      => \\$main::opt_lib,\n             \"lib_prefix=s\"   => \\$main::opt_lib_prefix,\n             \"functions!\"     => \\$main::opt_functions,\n             \"lines!\"         => \\$main::opt_lines,\n             \"addresses!\"     => \\$main::opt_addresses,\n             \"files!\"         => \\$main::opt_files,\n             \"text!\"          => \\$main::opt_text,\n             \"callgrind!\"     => \\$main::opt_callgrind,\n             \"list=s\"         => \\$main::opt_list,\n             \"disasm=s\"       => \\$main::opt_disasm,\n             \"symbols!\"       => \\$main::opt_symbols,\n             \"gv!\"            => \\$main::opt_gv,\n             \"evince!\"        => \\$main::opt_evince,\n             \"web!\"           => \\$main::opt_web,\n             \"dot!\"           => \\$main::opt_dot,\n             \"ps!\"            => \\$main::opt_ps,\n             \"pdf!\"           => \\$main::opt_pdf,\n             \"svg!\"           => \\$main::opt_svg,\n             \"gif!\"           => \\$main::opt_gif,\n             \"raw!\"           => \\$main::opt_raw,\n             \"interactive!\"   => \\$main::opt_interactive,\n             \"nodecount=i\"    => \\$main::opt_nodecount,\n             \"nodefraction=f\" => \\$main::opt_nodefraction,\n             \"edgefraction=f\" => \\$main::opt_edgefraction,\n             \"maxdegree=i\"    => \\$main::opt_maxdegree,\n             \"focus=s\"        => \\$main::opt_focus,\n             \"thread=s\"       => \\$main::opt_thread,\n             \"ignore=s\"       => \\$main::opt_ignore,\n             \"scale=i\"        => \\$main::opt_scale,\n             \"heapcheck\"      => \\$main::opt_heapcheck,\n             \"inuse_space!\"   => \\$main::opt_inuse_space,\n             \"inuse_objects!\" => \\$main::opt_inuse_objects,\n             \"alloc_space!\"   => \\$main::opt_alloc_space,\n             \"alloc_objects!\" => \\$main::opt_alloc_objects,\n             \"show_bytes!\"    => \\$main::opt_show_bytes,\n             \"drop_negative!\" => \\$main::opt_drop_negative,\n             \"total_delay!\"   => \\$main::opt_total_delay,\n             \"contentions!\"   => \\$main::opt_contentions,\n             \"mean_delay!\"    => \\$main::opt_mean_delay,\n             \"tools=s\"        => \\$main::opt_tools,\n             \"test!\"          => \\$main::opt_test,\n             \"debug!\"         => \\$main::opt_debug,\n             # Undocumented flags used only by unittests:\n             \"test_stride=i\"  => \\$main::opt_test_stride,\n      ) || usage(\"Invalid option(s)\");\n\n  # Deal with the standard --help and --version\n  if ($main::opt_help) {\n    print usage_string();\n    exit(0);\n  }\n\n  if ($main::opt_version) {\n    print version_string();\n    exit(0);\n  }\n\n  # Disassembly/listing/symbols mode requires address-level info\n  if ($main::opt_disasm || $main::opt_list || $main::opt_symbols) {\n    $main::opt_functions = 0;\n    $main::opt_lines = 0;\n    $main::opt_addresses = 1;\n    $main::opt_files = 0;\n  }\n\n  # Check heap-profiling flags\n  if ($main::opt_inuse_space +\n      $main::opt_inuse_objects +\n      $main::opt_alloc_space +\n      $main::opt_alloc_objects > 1) {\n    usage(\"Specify at most on of --inuse/--alloc options\");\n  }\n\n  # Check output granularities\n  my $grains =\n      $main::opt_functions +\n      $main::opt_lines +\n      $main::opt_addresses +\n      $main::opt_files +\n      0;\n  if ($grains > 1) {\n    usage(\"Only specify one output granularity option\");\n  }\n  if ($grains == 0) {\n    $main::opt_functions = 1;\n  }\n\n  # Check output modes\n  my $modes =\n      $main::opt_text +\n      $main::opt_callgrind +\n      ($main::opt_list eq '' ? 0 : 1) +\n      ($main::opt_disasm eq '' ? 0 : 1) +\n      ($main::opt_symbols == 0 ? 0 : 1) +\n      $main::opt_gv +\n      $main::opt_evince +\n      $main::opt_web +\n      $main::opt_dot +\n      $main::opt_ps +\n      $main::opt_pdf +\n      $main::opt_svg +\n      $main::opt_gif +\n      $main::opt_raw +\n      $main::opt_interactive +\n      0;\n  if ($modes > 1) {\n    usage(\"Only specify one output mode\");\n  }\n  if ($modes == 0) {\n    if (-t STDOUT) {  # If STDOUT is a tty, activate interactive mode\n      $main::opt_interactive = 1;\n    } else {\n      $main::opt_text = 1;\n    }\n  }\n\n  if ($main::opt_test) {\n    RunUnitTests();\n    # Should not return\n    exit(1);\n  }\n\n  # Binary name and profile arguments list\n  $main::prog = \"\";\n  @main::pfile_args = ();\n\n  # Remote profiling without a binary (using $SYMBOL_PAGE instead)\n  if (@ARGV > 0) {\n    if (IsProfileURL($ARGV[0])) {\n      $main::use_symbol_page = 1;\n    } elsif (IsSymbolizedProfileFile($ARGV[0])) {\n      $main::use_symbolized_profile = 1;\n      $main::prog = $UNKNOWN_BINARY;  # will be set later from the profile file\n    }\n  }\n\n  if ($main::use_symbol_page || $main::use_symbolized_profile) {\n    # We don't need a binary!\n    my %disabled = ('--lines' => $main::opt_lines,\n                    '--disasm' => $main::opt_disasm);\n    for my $option (keys %disabled) {\n      usage(\"$option cannot be used without a binary\") if $disabled{$option};\n    }\n    # Set $main::prog later...\n    scalar(@ARGV) || usage(\"Did not specify profile file\");\n  } elsif ($main::opt_symbols) {\n    # --symbols needs a binary-name (to run nm on, etc) but not profiles\n    $main::prog = shift(@ARGV) || usage(\"Did not specify program\");\n  } else {\n    $main::prog = shift(@ARGV) || usage(\"Did not specify program\");\n    scalar(@ARGV) || usage(\"Did not specify profile file\");\n  }\n\n  # Parse profile file/location arguments\n  foreach my $farg (@ARGV) {\n    if ($farg =~ m/(.*)\\@([0-9]+)(|\\/.*)$/ ) {\n      my $machine = $1;\n      my $num_machines = $2;\n      my $path = $3;\n      for (my $i = 0; $i < $num_machines; $i++) {\n        unshift(@main::pfile_args, \"$i.$machine$path\");\n      }\n    } else {\n      unshift(@main::pfile_args, $farg);\n    }\n  }\n\n  if ($main::use_symbol_page) {\n    unless (IsProfileURL($main::pfile_args[0])) {\n      error(\"The first profile should be a remote form to use $SYMBOL_PAGE\\n\");\n    }\n    CheckSymbolPage();\n    $main::prog = FetchProgramName();\n  } elsif (!$main::use_symbolized_profile) {  # may not need objtools!\n    ConfigureObjTools($main::prog)\n  }\n\n  # Break the opt_lib_prefix into the prefix_list array\n  @prefix_list = split (',', $main::opt_lib_prefix);\n\n  # Remove trailing / from the prefixes, in the list to prevent\n  # searching things like /my/path//lib/mylib.so\n  foreach (@prefix_list) {\n    s|/+$||;\n  }\n}\n\nsub FilterAndPrint {\n  my ($profile, $symbols, $libs, $thread) = @_;\n\n  # Get total data in profile\n  my $total = TotalProfile($profile);\n\n  # Remove uniniteresting stack items\n  $profile = RemoveUninterestingFrames($symbols, $profile);\n\n  # Focus?\n  if ($main::opt_focus ne '') {\n    $profile = FocusProfile($symbols, $profile, $main::opt_focus);\n  }\n\n  # Ignore?\n  if ($main::opt_ignore ne '') {\n    $profile = IgnoreProfile($symbols, $profile, $main::opt_ignore);\n  }\n\n  my $calls = ExtractCalls($symbols, $profile);\n\n  # Reduce profiles to required output granularity, and also clean\n  # each stack trace so a given entry exists at most once.\n  my $reduced = ReduceProfile($symbols, $profile);\n\n  # Get derived profiles\n  my $flat = FlatProfile($reduced);\n  my $cumulative = CumulativeProfile($reduced);\n\n  # Print\n  if (!$main::opt_interactive) {\n    if ($main::opt_disasm) {\n      PrintDisassembly($libs, $flat, $cumulative, $main::opt_disasm);\n    } elsif ($main::opt_list) {\n      PrintListing($total, $libs, $flat, $cumulative, $main::opt_list, 0);\n    } elsif ($main::opt_text) {\n      # Make sure the output is empty when have nothing to report\n      # (only matters when --heapcheck is given but we must be\n      # compatible with old branches that did not pass --heapcheck always):\n      if ($total != 0) {\n        printf(\"Total%s: %s %s\\n\",\n               (defined($thread) ? \" (t$thread)\" : \"\"),\n               Unparse($total), Units());\n      }\n      PrintText($symbols, $flat, $cumulative, -1);\n    } elsif ($main::opt_raw) {\n      PrintSymbolizedProfile($symbols, $profile, $main::prog);\n    } elsif ($main::opt_callgrind) {\n      PrintCallgrind($calls);\n    } else {\n      if (PrintDot($main::prog, $symbols, $profile, $flat, $cumulative, $total)) {\n        if ($main::opt_gv) {\n          RunGV(TempName($main::next_tmpfile, \"ps\"), \"\");\n        } elsif ($main::opt_evince) {\n          RunEvince(TempName($main::next_tmpfile, \"pdf\"), \"\");\n        } elsif ($main::opt_web) {\n          my $tmp = TempName($main::next_tmpfile, \"svg\");\n          RunWeb($tmp);\n          # The command we run might hand the file name off\n          # to an already running browser instance and then exit.\n          # Normally, we'd remove $tmp on exit (right now),\n          # but fork a child to remove $tmp a little later, so that the\n          # browser has time to load it first.\n          delete $main::tempnames{$tmp};\n          if (fork() == 0) {\n            sleep 5;\n            unlink($tmp);\n            exit(0);\n          }\n        }\n      } else {\n        cleanup();\n        exit(1);\n      }\n    }\n  } else {\n    InteractiveMode($profile, $symbols, $libs, $total);\n  }\n}\n\nsub Main() {\n  Init();\n  $main::collected_profile = undef;\n  @main::profile_files = ();\n  $main::op_time = time();\n\n  # Printing symbols is special and requires a lot less info that most.\n  if ($main::opt_symbols) {\n    PrintSymbols(*STDIN);   # Get /proc/maps and symbols output from stdin\n    return;\n  }\n\n  # Fetch all profile data\n  FetchDynamicProfiles();\n\n  # this will hold symbols that we read from the profile files\n  my $symbol_map = {};\n\n  # Read one profile, pick the last item on the list\n  my $data = ReadProfile($main::prog, pop(@main::profile_files));\n  my $profile = $data->{profile};\n  my $pcs = $data->{pcs};\n  my $libs = $data->{libs};   # Info about main program and shared libraries\n  $symbol_map = MergeSymbols($symbol_map, $data->{symbols});\n\n  # Add additional profiles, if available.\n  if (scalar(@main::profile_files) > 0) {\n    foreach my $pname (@main::profile_files) {\n      my $data2 = ReadProfile($main::prog, $pname);\n      $profile = AddProfile($profile, $data2->{profile});\n      $pcs = AddPcs($pcs, $data2->{pcs});\n      $symbol_map = MergeSymbols($symbol_map, $data2->{symbols});\n    }\n  }\n\n  # Subtract base from profile, if specified\n  if ($main::opt_base ne '') {\n    my $base = ReadProfile($main::prog, $main::opt_base);\n    $profile = SubtractProfile($profile, $base->{profile});\n    $pcs = AddPcs($pcs, $base->{pcs});\n    $symbol_map = MergeSymbols($symbol_map, $base->{symbols});\n  }\n\n  # Collect symbols\n  my $symbols;\n  if ($main::use_symbolized_profile) {\n    $symbols = FetchSymbols($pcs, $symbol_map);\n  } elsif ($main::use_symbol_page) {\n    $symbols = FetchSymbols($pcs);\n  } else {\n    # TODO(csilvers): $libs uses the /proc/self/maps data from profile1,\n    # which may differ from the data from subsequent profiles, especially\n    # if they were run on different machines.  Use appropriate libs for\n    # each pc somehow.\n    $symbols = ExtractSymbols($libs, $pcs);\n  }\n\n  if (!defined($main::opt_thread)) {\n    FilterAndPrint($profile, $symbols, $libs);\n  }\n  if (defined($data->{threads})) {\n    foreach my $thread (sort { $a <=> $b } keys(%{$data->{threads}})) {\n      if (defined($main::opt_thread) &&\n          ($main::opt_thread eq '*' || $main::opt_thread == $thread)) {\n        my $thread_profile = $data->{threads}{$thread};\n        FilterAndPrint($thread_profile, $symbols, $libs, $thread);\n      }\n    }\n  }\n\n  cleanup();\n  exit(0);\n}\n\n##### Entry Point #####\n\nMain();\n\n# Temporary code to detect if we're running on a Goobuntu system.\n# These systems don't have the right stuff installed for the special\n# Readline libraries to work, so as a temporary workaround, we default\n# to using the normal stdio code, rather than the fancier readline-based\n# code\nsub ReadlineMightFail {\n  if (-e '/lib/libtermcap.so.2') {\n    return 0;  # libtermcap exists, so readline should be okay\n  } else {\n    return 1;\n  }\n}\n\nsub RunGV {\n  my $fname = shift;\n  my $bg = shift;       # \"\" or \" &\" if we should run in background\n  if (!system(ShellEscape(@GV, \"--version\") . \" >$dev_null 2>&1\")) {\n    # Options using double dash are supported by this gv version.\n    # Also, turn on noantialias to better handle bug in gv for\n    # postscript files with large dimensions.\n    # TODO: Maybe we should not pass the --noantialias flag\n    # if the gv version is known to work properly without the flag.\n    system(ShellEscape(@GV, \"--scale=$main::opt_scale\", \"--noantialias\", $fname)\n           . $bg);\n  } else {\n    # Old gv version - only supports options that use single dash.\n    print STDERR ShellEscape(@GV, \"-scale\", $main::opt_scale) . \"\\n\";\n    system(ShellEscape(@GV, \"-scale\", \"$main::opt_scale\", $fname) . $bg);\n  }\n}\n\nsub RunEvince {\n  my $fname = shift;\n  my $bg = shift;       # \"\" or \" &\" if we should run in background\n  system(ShellEscape(@EVINCE, $fname) . $bg);\n}\n\nsub RunWeb {\n  my $fname = shift;\n  print STDERR \"Loading web page file:///$fname\\n\";\n\n  if (`uname` =~ /Darwin/) {\n    # OS X: open will use standard preference for SVG files.\n    system(\"/usr/bin/open\", $fname);\n    return;\n  }\n\n  # Some kind of Unix; try generic symlinks, then specific browsers.\n  # (Stop once we find one.)\n  # Works best if the browser is already running.\n  my @alt = (\n    \"/etc/alternatives/gnome-www-browser\",\n    \"/etc/alternatives/x-www-browser\",\n    \"google-chrome\",\n    \"firefox\",\n  );\n  foreach my $b (@alt) {\n    if (system($b, $fname) == 0) {\n      return;\n    }\n  }\n\n  print STDERR \"Could not load web browser.\\n\";\n}\n\nsub RunKcachegrind {\n  my $fname = shift;\n  my $bg = shift;       # \"\" or \" &\" if we should run in background\n  print STDERR \"Starting '@KCACHEGRIND \" . $fname . $bg . \"'\\n\";\n  system(ShellEscape(@KCACHEGRIND, $fname) . $bg);\n}\n\n\n##### Interactive helper routines #####\n\nsub InteractiveMode {\n  $| = 1;  # Make output unbuffered for interactive mode\n  my ($orig_profile, $symbols, $libs, $total) = @_;\n\n  print STDERR \"Welcome to jeprof!  For help, type 'help'.\\n\";\n\n  # Use ReadLine if it's installed and input comes from a console.\n  if ( -t STDIN &&\n       !ReadlineMightFail() &&\n       defined(eval {require Term::ReadLine}) ) {\n    my $term = new Term::ReadLine 'jeprof';\n    while ( defined ($_ = $term->readline('(jeprof) '))) {\n      $term->addhistory($_) if /\\S/;\n      if (!InteractiveCommand($orig_profile, $symbols, $libs, $total, $_)) {\n        last;    # exit when we get an interactive command to quit\n      }\n    }\n  } else {       # don't have readline\n    while (1) {\n      print STDERR \"(jeprof) \";\n      $_ = <STDIN>;\n      last if ! defined $_ ;\n      s/\\r//g;         # turn windows-looking lines into unix-looking lines\n\n      # Save some flags that might be reset by InteractiveCommand()\n      my $save_opt_lines = $main::opt_lines;\n\n      if (!InteractiveCommand($orig_profile, $symbols, $libs, $total, $_)) {\n        last;    # exit when we get an interactive command to quit\n      }\n\n      # Restore flags\n      $main::opt_lines = $save_opt_lines;\n    }\n  }\n}\n\n# Takes two args: orig profile, and command to run.\n# Returns 1 if we should keep going, or 0 if we were asked to quit\nsub InteractiveCommand {\n  my($orig_profile, $symbols, $libs, $total, $command) = @_;\n  $_ = $command;                # just to make future m//'s easier\n  if (!defined($_)) {\n    print STDERR \"\\n\";\n    return 0;\n  }\n  if (m/^\\s*quit/) {\n    return 0;\n  }\n  if (m/^\\s*help/) {\n    InteractiveHelpMessage();\n    return 1;\n  }\n  # Clear all the mode options -- mode is controlled by \"$command\"\n  $main::opt_text = 0;\n  $main::opt_callgrind = 0;\n  $main::opt_disasm = 0;\n  $main::opt_list = 0;\n  $main::opt_gv = 0;\n  $main::opt_evince = 0;\n  $main::opt_cum = 0;\n\n  if (m/^\\s*(text|top)(\\d*)\\s*(.*)/) {\n    $main::opt_text = 1;\n\n    my $line_limit = ($2 ne \"\") ? int($2) : 10;\n\n    my $routine;\n    my $ignore;\n    ($routine, $ignore) = ParseInteractiveArgs($3);\n\n    my $profile = ProcessProfile($total, $orig_profile, $symbols, \"\", $ignore);\n    my $reduced = ReduceProfile($symbols, $profile);\n\n    # Get derived profiles\n    my $flat = FlatProfile($reduced);\n    my $cumulative = CumulativeProfile($reduced);\n\n    PrintText($symbols, $flat, $cumulative, $line_limit);\n    return 1;\n  }\n  if (m/^\\s*callgrind\\s*([^ \\n]*)/) {\n    $main::opt_callgrind = 1;\n\n    # Get derived profiles\n    my $calls = ExtractCalls($symbols, $orig_profile);\n    my $filename = $1;\n    if ( $1 eq '' ) {\n      $filename = TempName($main::next_tmpfile, \"callgrind\");\n    }\n    PrintCallgrind($calls, $filename);\n    if ( $1 eq '' ) {\n      RunKcachegrind($filename, \" & \");\n      $main::next_tmpfile++;\n    }\n\n    return 1;\n  }\n  if (m/^\\s*(web)?list\\s*(.+)/) {\n    my $html = (defined($1) && ($1 eq \"web\"));\n    $main::opt_list = 1;\n\n    my $routine;\n    my $ignore;\n    ($routine, $ignore) = ParseInteractiveArgs($2);\n\n    my $profile = ProcessProfile($total, $orig_profile, $symbols, \"\", $ignore);\n    my $reduced = ReduceProfile($symbols, $profile);\n\n    # Get derived profiles\n    my $flat = FlatProfile($reduced);\n    my $cumulative = CumulativeProfile($reduced);\n\n    PrintListing($total, $libs, $flat, $cumulative, $routine, $html);\n    return 1;\n  }\n  if (m/^\\s*disasm\\s*(.+)/) {\n    $main::opt_disasm = 1;\n\n    my $routine;\n    my $ignore;\n    ($routine, $ignore) = ParseInteractiveArgs($1);\n\n    # Process current profile to account for various settings\n    my $profile = ProcessProfile($total, $orig_profile, $symbols, \"\", $ignore);\n    my $reduced = ReduceProfile($symbols, $profile);\n\n    # Get derived profiles\n    my $flat = FlatProfile($reduced);\n    my $cumulative = CumulativeProfile($reduced);\n\n    PrintDisassembly($libs, $flat, $cumulative, $routine);\n    return 1;\n  }\n  if (m/^\\s*(gv|web|evince)\\s*(.*)/) {\n    $main::opt_gv = 0;\n    $main::opt_evince = 0;\n    $main::opt_web = 0;\n    if ($1 eq \"gv\") {\n      $main::opt_gv = 1;\n    } elsif ($1 eq \"evince\") {\n      $main::opt_evince = 1;\n    } elsif ($1 eq \"web\") {\n      $main::opt_web = 1;\n    }\n\n    my $focus;\n    my $ignore;\n    ($focus, $ignore) = ParseInteractiveArgs($2);\n\n    # Process current profile to account for various settings\n    my $profile = ProcessProfile($total, $orig_profile, $symbols,\n                                 $focus, $ignore);\n    my $reduced = ReduceProfile($symbols, $profile);\n\n    # Get derived profiles\n    my $flat = FlatProfile($reduced);\n    my $cumulative = CumulativeProfile($reduced);\n\n    if (PrintDot($main::prog, $symbols, $profile, $flat, $cumulative, $total)) {\n      if ($main::opt_gv) {\n        RunGV(TempName($main::next_tmpfile, \"ps\"), \" &\");\n      } elsif ($main::opt_evince) {\n        RunEvince(TempName($main::next_tmpfile, \"pdf\"), \" &\");\n      } elsif ($main::opt_web) {\n        RunWeb(TempName($main::next_tmpfile, \"svg\"));\n      }\n      $main::next_tmpfile++;\n    }\n    return 1;\n  }\n  if (m/^\\s*$/) {\n    return 1;\n  }\n  print STDERR \"Unknown command: try 'help'.\\n\";\n  return 1;\n}\n\n\nsub ProcessProfile {\n  my $total_count = shift;\n  my $orig_profile = shift;\n  my $symbols = shift;\n  my $focus = shift;\n  my $ignore = shift;\n\n  # Process current profile to account for various settings\n  my $profile = $orig_profile;\n  printf(\"Total: %s %s\\n\", Unparse($total_count), Units());\n  if ($focus ne '') {\n    $profile = FocusProfile($symbols, $profile, $focus);\n    my $focus_count = TotalProfile($profile);\n    printf(\"After focusing on '%s': %s %s of %s (%0.1f%%)\\n\",\n           $focus,\n           Unparse($focus_count), Units(),\n           Unparse($total_count), ($focus_count*100.0) / $total_count);\n  }\n  if ($ignore ne '') {\n    $profile = IgnoreProfile($symbols, $profile, $ignore);\n    my $ignore_count = TotalProfile($profile);\n    printf(\"After ignoring '%s': %s %s of %s (%0.1f%%)\\n\",\n           $ignore,\n           Unparse($ignore_count), Units(),\n           Unparse($total_count),\n           ($ignore_count*100.0) / $total_count);\n  }\n\n  return $profile;\n}\n\nsub InteractiveHelpMessage {\n  print STDERR <<ENDOFHELP;\nInteractive jeprof mode\n\nCommands:\n  gv\n  gv [focus] [-ignore1] [-ignore2]\n      Show graphical hierarchical display of current profile.  Without\n      any arguments, shows all samples in the profile.  With the optional\n      \"focus\" argument, restricts the samples shown to just those where\n      the \"focus\" regular expression matches a routine name on the stack\n      trace.\n\n  web\n  web [focus] [-ignore1] [-ignore2]\n      Like GV, but displays profile in your web browser instead of using\n      Ghostview. Works best if your web browser is already running.\n      To change the browser that gets used:\n      On Linux, set the /etc/alternatives/gnome-www-browser symlink.\n      On OS X, change the Finder association for SVG files.\n\n  list [routine_regexp] [-ignore1] [-ignore2]\n      Show source listing of routines whose names match \"routine_regexp\"\n\n  weblist [routine_regexp] [-ignore1] [-ignore2]\n     Displays a source listing of routines whose names match \"routine_regexp\"\n     in a web browser.  You can click on source lines to view the\n     corresponding disassembly.\n\n  top [--cum] [-ignore1] [-ignore2]\n  top20 [--cum] [-ignore1] [-ignore2]\n  top37 [--cum] [-ignore1] [-ignore2]\n      Show top lines ordered by flat profile count, or cumulative count\n      if --cum is specified.  If a number is present after 'top', the\n      top K routines will be shown (defaults to showing the top 10)\n\n  disasm [routine_regexp] [-ignore1] [-ignore2]\n      Show disassembly of routines whose names match \"routine_regexp\",\n      annotated with sample counts.\n\n  callgrind\n  callgrind [filename]\n      Generates callgrind file. If no filename is given, kcachegrind is called.\n\n  help - This listing\n  quit or ^D - End jeprof\n\nFor commands that accept optional -ignore tags, samples where any routine in\nthe stack trace matches the regular expression in any of the -ignore\nparameters will be ignored.\n\nFurther pprof details are available at this location (or one similar):\n\n /usr/doc/gperftools-$PPROF_VERSION/cpu_profiler.html\n /usr/doc/gperftools-$PPROF_VERSION/heap_profiler.html\n\nENDOFHELP\n}\nsub ParseInteractiveArgs {\n  my $args = shift;\n  my $focus = \"\";\n  my $ignore = \"\";\n  my @x = split(/ +/, $args);\n  foreach $a (@x) {\n    if ($a =~ m/^(--|-)lines$/) {\n      $main::opt_lines = 1;\n    } elsif ($a =~ m/^(--|-)cum$/) {\n      $main::opt_cum = 1;\n    } elsif ($a =~ m/^-(.*)/) {\n      $ignore .= (($ignore ne \"\") ? \"|\" : \"\" ) . $1;\n    } else {\n      $focus .= (($focus ne \"\") ? \"|\" : \"\" ) . $a;\n    }\n  }\n  if ($ignore ne \"\") {\n    print STDERR \"Ignoring samples in call stacks that match '$ignore'\\n\";\n  }\n  return ($focus, $ignore);\n}\n\n##### Output code #####\n\nsub TempName {\n  my $fnum = shift;\n  my $ext = shift;\n  my $file = \"$main::tmpfile_ps.$fnum.$ext\";\n  $main::tempnames{$file} = 1;\n  return $file;\n}\n\n# Print profile data in packed binary format (64-bit) to standard out\nsub PrintProfileData {\n  my $profile = shift;\n\n  # print header (64-bit style)\n  # (zero) (header-size) (version) (sample-period) (zero)\n  print pack('L*', 0, 0, 3, 0, 0, 0, 1, 0, 0, 0);\n\n  foreach my $k (keys(%{$profile})) {\n    my $count = $profile->{$k};\n    my @addrs = split(/\\n/, $k);\n    if ($#addrs >= 0) {\n      my $depth = $#addrs + 1;\n      # int(foo / 2**32) is the only reliable way to get rid of bottom\n      # 32 bits on both 32- and 64-bit systems.\n      print pack('L*', $count & 0xFFFFFFFF, int($count / 2**32));\n      print pack('L*', $depth & 0xFFFFFFFF, int($depth / 2**32));\n\n      foreach my $full_addr (@addrs) {\n        my $addr = $full_addr;\n        $addr =~ s/0x0*//;  # strip off leading 0x, zeroes\n        if (length($addr) > 16) {\n          print STDERR \"Invalid address in profile: $full_addr\\n\";\n          next;\n        }\n        my $low_addr = substr($addr, -8);       # get last 8 hex chars\n        my $high_addr = substr($addr, -16, 8);  # get up to 8 more hex chars\n        print pack('L*', hex('0x' . $low_addr), hex('0x' . $high_addr));\n      }\n    }\n  }\n}\n\n# Print symbols and profile data\nsub PrintSymbolizedProfile {\n  my $symbols = shift;\n  my $profile = shift;\n  my $prog = shift;\n\n  $SYMBOL_PAGE =~ m,[^/]+$,;    # matches everything after the last slash\n  my $symbol_marker = $&;\n\n  print '--- ', $symbol_marker, \"\\n\";\n  if (defined($prog)) {\n    print 'binary=', $prog, \"\\n\";\n  }\n  while (my ($pc, $name) = each(%{$symbols})) {\n    my $sep = ' ';\n    print '0x', $pc;\n    # We have a list of function names, which include the inlined\n    # calls.  They are separated (and terminated) by --, which is\n    # illegal in function names.\n    for (my $j = 2; $j <= $#{$name}; $j += 3) {\n      print $sep, $name->[$j];\n      $sep = '--';\n    }\n    print \"\\n\";\n  }\n  print '---', \"\\n\";\n\n  $PROFILE_PAGE =~ m,[^/]+$,;    # matches everything after the last slash\n  my $profile_marker = $&;\n  print '--- ', $profile_marker, \"\\n\";\n  if (defined($main::collected_profile)) {\n    # if used with remote fetch, simply dump the collected profile to output.\n    open(SRC, \"<$main::collected_profile\");\n    while (<SRC>) {\n      print $_;\n    }\n    close(SRC);\n  } else {\n    # dump a cpu-format profile to standard out\n    PrintProfileData($profile);\n  }\n}\n\n# Print text output\nsub PrintText {\n  my $symbols = shift;\n  my $flat = shift;\n  my $cumulative = shift;\n  my $line_limit = shift;\n\n  my $total = TotalProfile($flat);\n\n  # Which profile to sort by?\n  my $s = $main::opt_cum ? $cumulative : $flat;\n\n  my $running_sum = 0;\n  my $lines = 0;\n  foreach my $k (sort { GetEntry($s, $b) <=> GetEntry($s, $a) || $a cmp $b }\n                 keys(%{$cumulative})) {\n    my $f = GetEntry($flat, $k);\n    my $c = GetEntry($cumulative, $k);\n    $running_sum += $f;\n\n    my $sym = $k;\n    if (exists($symbols->{$k})) {\n      $sym = $symbols->{$k}->[0] . \" \" . $symbols->{$k}->[1];\n      if ($main::opt_addresses) {\n        $sym = $k . \" \" . $sym;\n      }\n    }\n\n    if ($f != 0 || $c != 0) {\n      printf(\"%8s %6s %6s %8s %6s %s\\n\",\n             Unparse($f),\n             Percent($f, $total),\n             Percent($running_sum, $total),\n             Unparse($c),\n             Percent($c, $total),\n             $sym);\n    }\n    $lines++;\n    last if ($line_limit >= 0 && $lines >= $line_limit);\n  }\n}\n\n# Callgrind format has a compression for repeated function and file\n# names.  You show the name the first time, and just use its number\n# subsequently.  This can cut down the file to about a third or a\n# quarter of its uncompressed size.  $key and $val are the key/value\n# pair that would normally be printed by callgrind; $map is a map from\n# value to number.\nsub CompressedCGName {\n  my($key, $val, $map) = @_;\n  my $idx = $map->{$val};\n  # For very short keys, providing an index hurts rather than helps.\n  if (length($val) <= 3) {\n    return \"$key=$val\\n\";\n  } elsif (defined($idx)) {\n    return \"$key=($idx)\\n\";\n  } else {\n    # scalar(keys $map) gives the number of items in the map.\n    $idx = scalar(keys(%{$map})) + 1;\n    $map->{$val} = $idx;\n    return \"$key=($idx) $val\\n\";\n  }\n}\n\n# Print the call graph in a way that's suiteable for callgrind.\nsub PrintCallgrind {\n  my $calls = shift;\n  my $filename;\n  my %filename_to_index_map;\n  my %fnname_to_index_map;\n\n  if ($main::opt_interactive) {\n    $filename = shift;\n    print STDERR \"Writing callgrind file to '$filename'.\\n\"\n  } else {\n    $filename = \"&STDOUT\";\n  }\n  open(CG, \">$filename\");\n  printf CG (\"events: Hits\\n\\n\");\n  foreach my $call ( map { $_->[0] }\n                     sort { $a->[1] cmp $b ->[1] ||\n                            $a->[2] <=> $b->[2] }\n                     map { /([^:]+):(\\d+):([^ ]+)( -> ([^:]+):(\\d+):(.+))?/;\n                           [$_, $1, $2] }\n                     keys %$calls ) {\n    my $count = int($calls->{$call});\n    $call =~ /([^:]+):(\\d+):([^ ]+)( -> ([^:]+):(\\d+):(.+))?/;\n    my ( $caller_file, $caller_line, $caller_function,\n         $callee_file, $callee_line, $callee_function ) =\n       ( $1, $2, $3, $5, $6, $7 );\n\n    # TODO(csilvers): for better compression, collect all the\n    # caller/callee_files and functions first, before printing\n    # anything, and only compress those referenced more than once.\n    printf CG CompressedCGName(\"fl\", $caller_file, \\%filename_to_index_map);\n    printf CG CompressedCGName(\"fn\", $caller_function, \\%fnname_to_index_map);\n    if (defined $6) {\n      printf CG CompressedCGName(\"cfl\", $callee_file, \\%filename_to_index_map);\n      printf CG CompressedCGName(\"cfn\", $callee_function, \\%fnname_to_index_map);\n      printf CG (\"calls=$count $callee_line\\n\");\n    }\n    printf CG (\"$caller_line $count\\n\\n\");\n  }\n}\n\n# Print disassembly for all all routines that match $main::opt_disasm\nsub PrintDisassembly {\n  my $libs = shift;\n  my $flat = shift;\n  my $cumulative = shift;\n  my $disasm_opts = shift;\n\n  my $total = TotalProfile($flat);\n\n  foreach my $lib (@{$libs}) {\n    my $symbol_table = GetProcedureBoundaries($lib->[0], $disasm_opts);\n    my $offset = AddressSub($lib->[1], $lib->[3]);\n    foreach my $routine (sort ByName keys(%{$symbol_table})) {\n      my $start_addr = $symbol_table->{$routine}->[0];\n      my $end_addr = $symbol_table->{$routine}->[1];\n      # See if there are any samples in this routine\n      my $length = hex(AddressSub($end_addr, $start_addr));\n      my $addr = AddressAdd($start_addr, $offset);\n      for (my $i = 0; $i < $length; $i++) {\n        if (defined($cumulative->{$addr})) {\n          PrintDisassembledFunction($lib->[0], $offset,\n                                    $routine, $flat, $cumulative,\n                                    $start_addr, $end_addr, $total);\n          last;\n        }\n        $addr = AddressInc($addr);\n      }\n    }\n  }\n}\n\n# Return reference to array of tuples of the form:\n#       [start_address, filename, linenumber, instruction, limit_address]\n# E.g.,\n#       [\"0x806c43d\", \"/foo/bar.cc\", 131, \"ret\", \"0x806c440\"]\nsub Disassemble {\n  my $prog = shift;\n  my $offset = shift;\n  my $start_addr = shift;\n  my $end_addr = shift;\n\n  my $objdump = $obj_tool_map{\"objdump\"};\n  my $cmd = ShellEscape($objdump, \"-C\", \"-d\", \"-l\", \"--no-show-raw-insn\",\n                        \"--start-address=0x$start_addr\",\n                        \"--stop-address=0x$end_addr\", $prog);\n  open(OBJDUMP, \"$cmd |\") || error(\"$cmd: $!\\n\");\n  my @result = ();\n  my $filename = \"\";\n  my $linenumber = -1;\n  my $last = [\"\", \"\", \"\", \"\"];\n  while (<OBJDUMP>) {\n    s/\\r//g;         # turn windows-looking lines into unix-looking lines\n    chop;\n    if (m|\\s*([^:\\s]+):(\\d+)\\s*$|) {\n      # Location line of the form:\n      #   <filename>:<linenumber>\n      $filename = $1;\n      $linenumber = $2;\n    } elsif (m/^ +([0-9a-f]+):\\s*(.*)/) {\n      # Disassembly line -- zero-extend address to full length\n      my $addr = HexExtend($1);\n      my $k = AddressAdd($addr, $offset);\n      $last->[4] = $k;   # Store ending address for previous instruction\n      $last = [$k, $filename, $linenumber, $2, $end_addr];\n      push(@result, $last);\n    }\n  }\n  close(OBJDUMP);\n  return @result;\n}\n\n# The input file should contain lines of the form /proc/maps-like\n# output (same format as expected from the profiles) or that looks\n# like hex addresses (like \"0xDEADBEEF\").  We will parse all\n# /proc/maps output, and for all the hex addresses, we will output\n# \"short\" symbol names, one per line, in the same order as the input.\nsub PrintSymbols {\n  my $maps_and_symbols_file = shift;\n\n  # ParseLibraries expects pcs to be in a set.  Fine by us...\n  my @pclist = ();   # pcs in sorted order\n  my $pcs = {};\n  my $map = \"\";\n  foreach my $line (<$maps_and_symbols_file>) {\n    $line =~ s/\\r//g;    # turn windows-looking lines into unix-looking lines\n    if ($line =~ /\\b(0x[0-9a-f]+)\\b/i) {\n      push(@pclist, HexExtend($1));\n      $pcs->{$pclist[-1]} = 1;\n    } else {\n      $map .= $line;\n    }\n  }\n\n  my $libs = ParseLibraries($main::prog, $map, $pcs);\n  my $symbols = ExtractSymbols($libs, $pcs);\n\n  foreach my $pc (@pclist) {\n    # ->[0] is the shortname, ->[2] is the full name\n    print(($symbols->{$pc}->[0] || \"??\") . \"\\n\");\n  }\n}\n\n\n# For sorting functions by name\nsub ByName {\n  return ShortFunctionName($a) cmp ShortFunctionName($b);\n}\n\n# Print source-listing for all all routines that match $list_opts\nsub PrintListing {\n  my $total = shift;\n  my $libs = shift;\n  my $flat = shift;\n  my $cumulative = shift;\n  my $list_opts = shift;\n  my $html = shift;\n\n  my $output = \\*STDOUT;\n  my $fname = \"\";\n\n  if ($html) {\n    # Arrange to write the output to a temporary file\n    $fname = TempName($main::next_tmpfile, \"html\");\n    $main::next_tmpfile++;\n    if (!open(TEMP, \">$fname\")) {\n      print STDERR \"$fname: $!\\n\";\n      return;\n    }\n    $output = \\*TEMP;\n    print $output HtmlListingHeader();\n    printf $output (\"<div class=\\\"legend\\\">%s<br>Total: %s %s</div>\\n\",\n                    $main::prog, Unparse($total), Units());\n  }\n\n  my $listed = 0;\n  foreach my $lib (@{$libs}) {\n    my $symbol_table = GetProcedureBoundaries($lib->[0], $list_opts);\n    my $offset = AddressSub($lib->[1], $lib->[3]);\n    foreach my $routine (sort ByName keys(%{$symbol_table})) {\n      # Print if there are any samples in this routine\n      my $start_addr = $symbol_table->{$routine}->[0];\n      my $end_addr = $symbol_table->{$routine}->[1];\n      my $length = hex(AddressSub($end_addr, $start_addr));\n      my $addr = AddressAdd($start_addr, $offset);\n      for (my $i = 0; $i < $length; $i++) {\n        if (defined($cumulative->{$addr})) {\n          $listed += PrintSource(\n            $lib->[0], $offset,\n            $routine, $flat, $cumulative,\n            $start_addr, $end_addr,\n            $html,\n            $output);\n          last;\n        }\n        $addr = AddressInc($addr);\n      }\n    }\n  }\n\n  if ($html) {\n    if ($listed > 0) {\n      print $output HtmlListingFooter();\n      close($output);\n      RunWeb($fname);\n    } else {\n      close($output);\n      unlink($fname);\n    }\n  }\n}\n\nsub HtmlListingHeader {\n  return <<'EOF';\n<DOCTYPE html>\n<html>\n<head>\n<title>Pprof listing</title>\n<style type=\"text/css\">\nbody {\n  font-family: sans-serif;\n}\nh1 {\n  font-size: 1.5em;\n  margin-bottom: 4px;\n}\n.legend {\n  font-size: 1.25em;\n}\n.line {\n  color: #aaaaaa;\n}\n.nop {\n  color: #aaaaaa;\n}\n.unimportant {\n  color: #cccccc;\n}\n.disasmloc {\n  color: #000000;\n}\n.deadsrc {\n  cursor: pointer;\n}\n.deadsrc:hover {\n  background-color: #eeeeee;\n}\n.livesrc {\n  color: #0000ff;\n  cursor: pointer;\n}\n.livesrc:hover {\n  background-color: #eeeeee;\n}\n.asm {\n  color: #008800;\n  display: none;\n}\n</style>\n<script type=\"text/javascript\">\nfunction jeprof_toggle_asm(e) {\n  var target;\n  if (!e) e = window.event;\n  if (e.target) target = e.target;\n  else if (e.srcElement) target = e.srcElement;\n\n  if (target) {\n    var asm = target.nextSibling;\n    if (asm && asm.className == \"asm\") {\n      asm.style.display = (asm.style.display == \"block\" ? \"\" : \"block\");\n      e.preventDefault();\n      return false;\n    }\n  }\n}\n</script>\n</head>\n<body>\nEOF\n}\n\nsub HtmlListingFooter {\n  return <<'EOF';\n</body>\n</html>\nEOF\n}\n\nsub HtmlEscape {\n  my $text = shift;\n  $text =~ s/&/&amp;/g;\n  $text =~ s/</&lt;/g;\n  $text =~ s/>/&gt;/g;\n  return $text;\n}\n\n# Returns the indentation of the line, if it has any non-whitespace\n# characters.  Otherwise, returns -1.\nsub Indentation {\n  my $line = shift;\n  if (m/^(\\s*)\\S/) {\n    return length($1);\n  } else {\n    return -1;\n  }\n}\n\n# If the symbol table contains inlining info, Disassemble() may tag an\n# instruction with a location inside an inlined function.  But for\n# source listings, we prefer to use the location in the function we\n# are listing.  So use MapToSymbols() to fetch full location\n# information for each instruction and then pick out the first\n# location from a location list (location list contains callers before\n# callees in case of inlining).\n#\n# After this routine has run, each entry in $instructions contains:\n#   [0] start address\n#   [1] filename for function we are listing\n#   [2] line number for function we are listing\n#   [3] disassembly\n#   [4] limit address\n#   [5] most specific filename (may be different from [1] due to inlining)\n#   [6] most specific line number (may be different from [2] due to inlining)\nsub GetTopLevelLineNumbers {\n  my ($lib, $offset, $instructions) = @_;\n  my $pcs = [];\n  for (my $i = 0; $i <= $#{$instructions}; $i++) {\n    push(@{$pcs}, $instructions->[$i]->[0]);\n  }\n  my $symbols = {};\n  MapToSymbols($lib, $offset, $pcs, $symbols);\n  for (my $i = 0; $i <= $#{$instructions}; $i++) {\n    my $e = $instructions->[$i];\n    push(@{$e}, $e->[1]);\n    push(@{$e}, $e->[2]);\n    my $addr = $e->[0];\n    my $sym = $symbols->{$addr};\n    if (defined($sym)) {\n      if ($#{$sym} >= 2 && $sym->[1] =~ m/^(.*):(\\d+)$/) {\n        $e->[1] = $1;  # File name\n        $e->[2] = $2;  # Line number\n      }\n    }\n  }\n}\n\n# Print source-listing for one routine\nsub PrintSource {\n  my $prog = shift;\n  my $offset = shift;\n  my $routine = shift;\n  my $flat = shift;\n  my $cumulative = shift;\n  my $start_addr = shift;\n  my $end_addr = shift;\n  my $html = shift;\n  my $output = shift;\n\n  # Disassemble all instructions (just to get line numbers)\n  my @instructions = Disassemble($prog, $offset, $start_addr, $end_addr);\n  GetTopLevelLineNumbers($prog, $offset, \\@instructions);\n\n  # Hack 1: assume that the first source file encountered in the\n  # disassembly contains the routine\n  my $filename = undef;\n  for (my $i = 0; $i <= $#instructions; $i++) {\n    if ($instructions[$i]->[2] >= 0) {\n      $filename = $instructions[$i]->[1];\n      last;\n    }\n  }\n  if (!defined($filename)) {\n    print STDERR \"no filename found in $routine\\n\";\n    return 0;\n  }\n\n  # Hack 2: assume that the largest line number from $filename is the\n  # end of the procedure.  This is typically safe since if P1 contains\n  # an inlined call to P2, then P2 usually occurs earlier in the\n  # source file.  If this does not work, we might have to compute a\n  # density profile or just print all regions we find.\n  my $lastline = 0;\n  for (my $i = 0; $i <= $#instructions; $i++) {\n    my $f = $instructions[$i]->[1];\n    my $l = $instructions[$i]->[2];\n    if (($f eq $filename) && ($l > $lastline)) {\n      $lastline = $l;\n    }\n  }\n\n  # Hack 3: assume the first source location from \"filename\" is the start of\n  # the source code.\n  my $firstline = 1;\n  for (my $i = 0; $i <= $#instructions; $i++) {\n    if ($instructions[$i]->[1] eq $filename) {\n      $firstline = $instructions[$i]->[2];\n      last;\n    }\n  }\n\n  # Hack 4: Extend last line forward until its indentation is less than\n  # the indentation we saw on $firstline\n  my $oldlastline = $lastline;\n  {\n    if (!open(FILE, \"<$filename\")) {\n      print STDERR \"$filename: $!\\n\";\n      return 0;\n    }\n    my $l = 0;\n    my $first_indentation = -1;\n    while (<FILE>) {\n      s/\\r//g;         # turn windows-looking lines into unix-looking lines\n      $l++;\n      my $indent = Indentation($_);\n      if ($l >= $firstline) {\n        if ($first_indentation < 0 && $indent >= 0) {\n          $first_indentation = $indent;\n          last if ($first_indentation == 0);\n        }\n      }\n      if ($l >= $lastline && $indent >= 0) {\n        if ($indent >= $first_indentation) {\n          $lastline = $l+1;\n        } else {\n          last;\n        }\n      }\n    }\n    close(FILE);\n  }\n\n  # Assign all samples to the range $firstline,$lastline,\n  # Hack 4: If an instruction does not occur in the range, its samples\n  # are moved to the next instruction that occurs in the range.\n  my $samples1 = {};        # Map from line number to flat count\n  my $samples2 = {};        # Map from line number to cumulative count\n  my $running1 = 0;         # Unassigned flat counts\n  my $running2 = 0;         # Unassigned cumulative counts\n  my $total1 = 0;           # Total flat counts\n  my $total2 = 0;           # Total cumulative counts\n  my %disasm = ();          # Map from line number to disassembly\n  my $running_disasm = \"\";  # Unassigned disassembly\n  my $skip_marker = \"---\\n\";\n  if ($html) {\n    $skip_marker = \"\";\n    for (my $l = $firstline; $l <= $lastline; $l++) {\n      $disasm{$l} = \"\";\n    }\n  }\n  my $last_dis_filename = '';\n  my $last_dis_linenum = -1;\n  my $last_touched_line = -1;  # To detect gaps in disassembly for a line\n  foreach my $e (@instructions) {\n    # Add up counts for all address that fall inside this instruction\n    my $c1 = 0;\n    my $c2 = 0;\n    for (my $a = $e->[0]; $a lt $e->[4]; $a = AddressInc($a)) {\n      $c1 += GetEntry($flat, $a);\n      $c2 += GetEntry($cumulative, $a);\n    }\n\n    if ($html) {\n      my $dis = sprintf(\"      %6s %6s \\t\\t%8s: %s \",\n                        HtmlPrintNumber($c1),\n                        HtmlPrintNumber($c2),\n                        UnparseAddress($offset, $e->[0]),\n                        CleanDisassembly($e->[3]));\n\n      # Append the most specific source line associated with this instruction\n      if (length($dis) < 80) { $dis .= (' ' x (80 - length($dis))) };\n      $dis = HtmlEscape($dis);\n      my $f = $e->[5];\n      my $l = $e->[6];\n      if ($f ne $last_dis_filename) {\n        $dis .= sprintf(\"<span class=disasmloc>%s:%d</span>\",\n                        HtmlEscape(CleanFileName($f)), $l);\n      } elsif ($l ne $last_dis_linenum) {\n        # De-emphasize the unchanged file name portion\n        $dis .= sprintf(\"<span class=unimportant>%s</span>\" .\n                        \"<span class=disasmloc>:%d</span>\",\n                        HtmlEscape(CleanFileName($f)), $l);\n      } else {\n        # De-emphasize the entire location\n        $dis .= sprintf(\"<span class=unimportant>%s:%d</span>\",\n                        HtmlEscape(CleanFileName($f)), $l);\n      }\n      $last_dis_filename = $f;\n      $last_dis_linenum = $l;\n      $running_disasm .= $dis;\n      $running_disasm .= \"\\n\";\n    }\n\n    $running1 += $c1;\n    $running2 += $c2;\n    $total1 += $c1;\n    $total2 += $c2;\n    my $file = $e->[1];\n    my $line = $e->[2];\n    if (($file eq $filename) &&\n        ($line >= $firstline) &&\n        ($line <= $lastline)) {\n      # Assign all accumulated samples to this line\n      AddEntry($samples1, $line, $running1);\n      AddEntry($samples2, $line, $running2);\n      $running1 = 0;\n      $running2 = 0;\n      if ($html) {\n        if ($line != $last_touched_line && $disasm{$line} ne '') {\n          $disasm{$line} .= \"\\n\";\n        }\n        $disasm{$line} .= $running_disasm;\n        $running_disasm = '';\n        $last_touched_line = $line;\n      }\n    }\n  }\n\n  # Assign any leftover samples to $lastline\n  AddEntry($samples1, $lastline, $running1);\n  AddEntry($samples2, $lastline, $running2);\n  if ($html) {\n    if ($lastline != $last_touched_line && $disasm{$lastline} ne '') {\n      $disasm{$lastline} .= \"\\n\";\n    }\n    $disasm{$lastline} .= $running_disasm;\n  }\n\n  if ($html) {\n    printf $output (\n      \"<h1>%s</h1>%s\\n<pre onClick=\\\"jeprof_toggle_asm()\\\">\\n\" .\n      \"Total:%6s %6s (flat / cumulative %s)\\n\",\n      HtmlEscape(ShortFunctionName($routine)),\n      HtmlEscape(CleanFileName($filename)),\n      Unparse($total1),\n      Unparse($total2),\n      Units());\n  } else {\n    printf $output (\n      \"ROUTINE ====================== %s in %s\\n\" .\n      \"%6s %6s Total %s (flat / cumulative)\\n\",\n      ShortFunctionName($routine),\n      CleanFileName($filename),\n      Unparse($total1),\n      Unparse($total2),\n      Units());\n  }\n  if (!open(FILE, \"<$filename\")) {\n    print STDERR \"$filename: $!\\n\";\n    return 0;\n  }\n  my $l = 0;\n  while (<FILE>) {\n    s/\\r//g;         # turn windows-looking lines into unix-looking lines\n    $l++;\n    if ($l >= $firstline - 5 &&\n        (($l <= $oldlastline + 5) || ($l <= $lastline))) {\n      chop;\n      my $text = $_;\n      if ($l == $firstline) { print $output $skip_marker; }\n      my $n1 = GetEntry($samples1, $l);\n      my $n2 = GetEntry($samples2, $l);\n      if ($html) {\n        # Emit a span that has one of the following classes:\n        #    livesrc -- has samples\n        #    deadsrc -- has disassembly, but with no samples\n        #    nop     -- has no matching disasembly\n        # Also emit an optional span containing disassembly.\n        my $dis = $disasm{$l};\n        my $asm = \"\";\n        if (defined($dis) && $dis ne '') {\n          $asm = \"<span class=\\\"asm\\\">\" . $dis . \"</span>\";\n        }\n        my $source_class = (($n1 + $n2 > 0)\n                            ? \"livesrc\"\n                            : (($asm ne \"\") ? \"deadsrc\" : \"nop\"));\n        printf $output (\n          \"<span class=\\\"line\\\">%5d</span> \" .\n          \"<span class=\\\"%s\\\">%6s %6s %s</span>%s\\n\",\n          $l, $source_class,\n          HtmlPrintNumber($n1),\n          HtmlPrintNumber($n2),\n          HtmlEscape($text),\n          $asm);\n      } else {\n        printf $output(\n          \"%6s %6s %4d: %s\\n\",\n          UnparseAlt($n1),\n          UnparseAlt($n2),\n          $l,\n          $text);\n      }\n      if ($l == $lastline)  { print $output $skip_marker; }\n    };\n  }\n  close(FILE);\n  if ($html) {\n    print $output \"</pre>\\n\";\n  }\n  return 1;\n}\n\n# Return the source line for the specified file/linenumber.\n# Returns undef if not found.\nsub SourceLine {\n  my $file = shift;\n  my $line = shift;\n\n  # Look in cache\n  if (!defined($main::source_cache{$file})) {\n    if (100 < scalar keys(%main::source_cache)) {\n      # Clear the cache when it gets too big\n      $main::source_cache = ();\n    }\n\n    # Read all lines from the file\n    if (!open(FILE, \"<$file\")) {\n      print STDERR \"$file: $!\\n\";\n      $main::source_cache{$file} = [];  # Cache the negative result\n      return undef;\n    }\n    my $lines = [];\n    push(@{$lines}, \"\");        # So we can use 1-based line numbers as indices\n    while (<FILE>) {\n      push(@{$lines}, $_);\n    }\n    close(FILE);\n\n    # Save the lines in the cache\n    $main::source_cache{$file} = $lines;\n  }\n\n  my $lines = $main::source_cache{$file};\n  if (($line < 0) || ($line > $#{$lines})) {\n    return undef;\n  } else {\n    return $lines->[$line];\n  }\n}\n\n# Print disassembly for one routine with interspersed source if available\nsub PrintDisassembledFunction {\n  my $prog = shift;\n  my $offset = shift;\n  my $routine = shift;\n  my $flat = shift;\n  my $cumulative = shift;\n  my $start_addr = shift;\n  my $end_addr = shift;\n  my $total = shift;\n\n  # Disassemble all instructions\n  my @instructions = Disassemble($prog, $offset, $start_addr, $end_addr);\n\n  # Make array of counts per instruction\n  my @flat_count = ();\n  my @cum_count = ();\n  my $flat_total = 0;\n  my $cum_total = 0;\n  foreach my $e (@instructions) {\n    # Add up counts for all address that fall inside this instruction\n    my $c1 = 0;\n    my $c2 = 0;\n    for (my $a = $e->[0]; $a lt $e->[4]; $a = AddressInc($a)) {\n      $c1 += GetEntry($flat, $a);\n      $c2 += GetEntry($cumulative, $a);\n    }\n    push(@flat_count, $c1);\n    push(@cum_count, $c2);\n    $flat_total += $c1;\n    $cum_total += $c2;\n  }\n\n  # Print header with total counts\n  printf(\"ROUTINE ====================== %s\\n\" .\n         \"%6s %6s %s (flat, cumulative) %.1f%% of total\\n\",\n         ShortFunctionName($routine),\n         Unparse($flat_total),\n         Unparse($cum_total),\n         Units(),\n         ($cum_total * 100.0) / $total);\n\n  # Process instructions in order\n  my $current_file = \"\";\n  for (my $i = 0; $i <= $#instructions; ) {\n    my $e = $instructions[$i];\n\n    # Print the new file name whenever we switch files\n    if ($e->[1] ne $current_file) {\n      $current_file = $e->[1];\n      my $fname = $current_file;\n      $fname =~ s|^\\./||;   # Trim leading \"./\"\n\n      # Shorten long file names\n      if (length($fname) >= 58) {\n        $fname = \"...\" . substr($fname, -55);\n      }\n      printf(\"-------------------- %s\\n\", $fname);\n    }\n\n    # TODO: Compute range of lines to print together to deal with\n    # small reorderings.\n    my $first_line = $e->[2];\n    my $last_line = $first_line;\n    my %flat_sum = ();\n    my %cum_sum = ();\n    for (my $l = $first_line; $l <= $last_line; $l++) {\n      $flat_sum{$l} = 0;\n      $cum_sum{$l} = 0;\n    }\n\n    # Find run of instructions for this range of source lines\n    my $first_inst = $i;\n    while (($i <= $#instructions) &&\n           ($instructions[$i]->[2] >= $first_line) &&\n           ($instructions[$i]->[2] <= $last_line)) {\n      $e = $instructions[$i];\n      $flat_sum{$e->[2]} += $flat_count[$i];\n      $cum_sum{$e->[2]} += $cum_count[$i];\n      $i++;\n    }\n    my $last_inst = $i - 1;\n\n    # Print source lines\n    for (my $l = $first_line; $l <= $last_line; $l++) {\n      my $line = SourceLine($current_file, $l);\n      if (!defined($line)) {\n        $line = \"?\\n\";\n        next;\n      } else {\n        $line =~ s/^\\s+//;\n      }\n      printf(\"%6s %6s %5d: %s\",\n             UnparseAlt($flat_sum{$l}),\n             UnparseAlt($cum_sum{$l}),\n             $l,\n             $line);\n    }\n\n    # Print disassembly\n    for (my $x = $first_inst; $x <= $last_inst; $x++) {\n      my $e = $instructions[$x];\n      printf(\"%6s %6s    %8s: %6s\\n\",\n             UnparseAlt($flat_count[$x]),\n             UnparseAlt($cum_count[$x]),\n             UnparseAddress($offset, $e->[0]),\n             CleanDisassembly($e->[3]));\n    }\n  }\n}\n\n# Print DOT graph\nsub PrintDot {\n  my $prog = shift;\n  my $symbols = shift;\n  my $raw = shift;\n  my $flat = shift;\n  my $cumulative = shift;\n  my $overall_total = shift;\n\n  # Get total\n  my $local_total = TotalProfile($flat);\n  my $nodelimit = int($main::opt_nodefraction * $local_total);\n  my $edgelimit = int($main::opt_edgefraction * $local_total);\n  my $nodecount = $main::opt_nodecount;\n\n  # Find nodes to include\n  my @list = (sort { abs(GetEntry($cumulative, $b)) <=>\n                     abs(GetEntry($cumulative, $a))\n                     || $a cmp $b }\n              keys(%{$cumulative}));\n  my $last = $nodecount - 1;\n  if ($last > $#list) {\n    $last = $#list;\n  }\n  while (($last >= 0) &&\n         (abs(GetEntry($cumulative, $list[$last])) <= $nodelimit)) {\n    $last--;\n  }\n  if ($last < 0) {\n    print STDERR \"No nodes to print\\n\";\n    return 0;\n  }\n\n  if ($nodelimit > 0 || $edgelimit > 0) {\n    printf STDERR (\"Dropping nodes with <= %s %s; edges with <= %s abs(%s)\\n\",\n                   Unparse($nodelimit), Units(),\n                   Unparse($edgelimit), Units());\n  }\n\n  # Open DOT output file\n  my $output;\n  my $escaped_dot = ShellEscape(@DOT);\n  my $escaped_ps2pdf = ShellEscape(@PS2PDF);\n  if ($main::opt_gv) {\n    my $escaped_outfile = ShellEscape(TempName($main::next_tmpfile, \"ps\"));\n    $output = \"| $escaped_dot -Tps2 >$escaped_outfile\";\n  } elsif ($main::opt_evince) {\n    my $escaped_outfile = ShellEscape(TempName($main::next_tmpfile, \"pdf\"));\n    $output = \"| $escaped_dot -Tps2 | $escaped_ps2pdf - $escaped_outfile\";\n  } elsif ($main::opt_ps) {\n    $output = \"| $escaped_dot -Tps2\";\n  } elsif ($main::opt_pdf) {\n    $output = \"| $escaped_dot -Tps2 | $escaped_ps2pdf - -\";\n  } elsif ($main::opt_web || $main::opt_svg) {\n    # We need to post-process the SVG, so write to a temporary file always.\n    my $escaped_outfile = ShellEscape(TempName($main::next_tmpfile, \"svg\"));\n    $output = \"| $escaped_dot -Tsvg >$escaped_outfile\";\n  } elsif ($main::opt_gif) {\n    $output = \"| $escaped_dot -Tgif\";\n  } else {\n    $output = \">&STDOUT\";\n  }\n  open(DOT, $output) || error(\"$output: $!\\n\");\n\n  # Title\n  printf DOT (\"digraph \\\"%s; %s %s\\\" {\\n\",\n              $prog,\n              Unparse($overall_total),\n              Units());\n  if ($main::opt_pdf) {\n    # The output is more printable if we set the page size for dot.\n    printf DOT (\"size=\\\"8,11\\\"\\n\");\n  }\n  printf DOT (\"node [width=0.375,height=0.25];\\n\");\n\n  # Print legend\n  printf DOT (\"Legend [shape=box,fontsize=24,shape=plaintext,\" .\n              \"label=\\\"%s\\\\l%s\\\\l%s\\\\l%s\\\\l%s\\\\l\\\"];\\n\",\n              $prog,\n              sprintf(\"Total %s: %s\", Units(), Unparse($overall_total)),\n              sprintf(\"Focusing on: %s\", Unparse($local_total)),\n              sprintf(\"Dropped nodes with <= %s abs(%s)\",\n                      Unparse($nodelimit), Units()),\n              sprintf(\"Dropped edges with <= %s %s\",\n                      Unparse($edgelimit), Units())\n              );\n\n  # Print nodes\n  my %node = ();\n  my $nextnode = 1;\n  foreach my $a (@list[0..$last]) {\n    # Pick font size\n    my $f = GetEntry($flat, $a);\n    my $c = GetEntry($cumulative, $a);\n\n    my $fs = 8;\n    if ($local_total > 0) {\n      $fs = 8 + (50.0 * sqrt(abs($f * 1.0 / $local_total)));\n    }\n\n    $node{$a} = $nextnode++;\n    my $sym = $a;\n    $sym =~ s/\\s+/\\\\n/g;\n    $sym =~ s/::/\\\\n/g;\n\n    # Extra cumulative info to print for non-leaves\n    my $extra = \"\";\n    if ($f != $c) {\n      $extra = sprintf(\"\\\\rof %s (%s)\",\n                       Unparse($c),\n                       Percent($c, $local_total));\n    }\n    my $style = \"\";\n    if ($main::opt_heapcheck) {\n      if ($f > 0) {\n        # make leak-causing nodes more visible (add a background)\n        $style = \",style=filled,fillcolor=gray\"\n      } elsif ($f < 0) {\n        # make anti-leak-causing nodes (which almost never occur)\n        # stand out as well (triple border)\n        $style = \",peripheries=3\"\n      }\n    }\n\n    printf DOT (\"N%d [label=\\\"%s\\\\n%s (%s)%s\\\\r\" .\n                \"\\\",shape=box,fontsize=%.1f%s];\\n\",\n                $node{$a},\n                $sym,\n                Unparse($f),\n                Percent($f, $local_total),\n                $extra,\n                $fs,\n                $style,\n               );\n  }\n\n  # Get edges and counts per edge\n  my %edge = ();\n  my $n;\n  my $fullname_to_shortname_map = {};\n  FillFullnameToShortnameMap($symbols, $fullname_to_shortname_map);\n  foreach my $k (keys(%{$raw})) {\n    # TODO: omit low %age edges\n    $n = $raw->{$k};\n    my @translated = TranslateStack($symbols, $fullname_to_shortname_map, $k);\n    for (my $i = 1; $i <= $#translated; $i++) {\n      my $src = $translated[$i];\n      my $dst = $translated[$i-1];\n      #next if ($src eq $dst);  # Avoid self-edges?\n      if (exists($node{$src}) && exists($node{$dst})) {\n        my $edge_label = \"$src\\001$dst\";\n        if (!exists($edge{$edge_label})) {\n          $edge{$edge_label} = 0;\n        }\n        $edge{$edge_label} += $n;\n      }\n    }\n  }\n\n  # Print edges (process in order of decreasing counts)\n  my %indegree = ();   # Number of incoming edges added per node so far\n  my %outdegree = ();  # Number of outgoing edges added per node so far\n  foreach my $e (sort { $edge{$b} <=> $edge{$a} } keys(%edge)) {\n    my @x = split(/\\001/, $e);\n    $n = $edge{$e};\n\n    # Initialize degree of kept incoming and outgoing edges if necessary\n    my $src = $x[0];\n    my $dst = $x[1];\n    if (!exists($outdegree{$src})) { $outdegree{$src} = 0; }\n    if (!exists($indegree{$dst})) { $indegree{$dst} = 0; }\n\n    my $keep;\n    if ($indegree{$dst} == 0) {\n      # Keep edge if needed for reachability\n      $keep = 1;\n    } elsif (abs($n) <= $edgelimit) {\n      # Drop if we are below --edgefraction\n      $keep = 0;\n    } elsif ($outdegree{$src} >= $main::opt_maxdegree ||\n             $indegree{$dst} >= $main::opt_maxdegree) {\n      # Keep limited number of in/out edges per node\n      $keep = 0;\n    } else {\n      $keep = 1;\n    }\n\n    if ($keep) {\n      $outdegree{$src}++;\n      $indegree{$dst}++;\n\n      # Compute line width based on edge count\n      my $fraction = abs($local_total ? (3 * ($n / $local_total)) : 0);\n      if ($fraction > 1) { $fraction = 1; }\n      my $w = $fraction * 2;\n      if ($w < 1 && ($main::opt_web || $main::opt_svg)) {\n        # SVG output treats line widths < 1 poorly.\n        $w = 1;\n      }\n\n      # Dot sometimes segfaults if given edge weights that are too large, so\n      # we cap the weights at a large value\n      my $edgeweight = abs($n) ** 0.7;\n      if ($edgeweight > 100000) { $edgeweight = 100000; }\n      $edgeweight = int($edgeweight);\n\n      my $style = sprintf(\"setlinewidth(%f)\", $w);\n      if ($x[1] =~ m/\\(inline\\)/) {\n        $style .= \",dashed\";\n      }\n\n      # Use a slightly squashed function of the edge count as the weight\n      printf DOT (\"N%s -> N%s [label=%s, weight=%d, style=\\\"%s\\\"];\\n\",\n                  $node{$x[0]},\n                  $node{$x[1]},\n                  Unparse($n),\n                  $edgeweight,\n                  $style);\n    }\n  }\n\n  print DOT (\"}\\n\");\n  close(DOT);\n\n  if ($main::opt_web || $main::opt_svg) {\n    # Rewrite SVG to be more usable inside web browser.\n    RewriteSvg(TempName($main::next_tmpfile, \"svg\"));\n  }\n\n  return 1;\n}\n\nsub RewriteSvg {\n  my $svgfile = shift;\n\n  open(SVG, $svgfile) || die \"open temp svg: $!\";\n  my @svg = <SVG>;\n  close(SVG);\n  unlink $svgfile;\n  my $svg = join('', @svg);\n\n  # Dot's SVG output is\n  #\n  #    <svg width=\"___\" height=\"___\"\n  #     viewBox=\"___\" xmlns=...>\n  #    <g id=\"graph0\" transform=\"...\">\n  #    ...\n  #    </g>\n  #    </svg>\n  #\n  # Change it to\n  #\n  #    <svg width=\"100%\" height=\"100%\"\n  #     xmlns=...>\n  #    $svg_javascript\n  #    <g id=\"viewport\" transform=\"translate(0,0)\">\n  #    <g id=\"graph0\" transform=\"...\">\n  #    ...\n  #    </g>\n  #    </g>\n  #    </svg>\n\n  # Fix width, height; drop viewBox.\n  $svg =~ s/(?s)<svg width=\"[^\"]+\" height=\"[^\"]+\"(.*?)viewBox=\"[^\"]+\"/<svg width=\"100%\" height=\"100%\"$1/;\n\n  # Insert script, viewport <g> above first <g>\n  my $svg_javascript = SvgJavascript();\n  my $viewport = \"<g id=\\\"viewport\\\" transform=\\\"translate(0,0)\\\">\\n\";\n  $svg =~ s/<g id=\"graph\\d\"/$svg_javascript$viewport$&/;\n\n  # Insert final </g> above </svg>.\n  $svg =~ s/(.*)(<\\/svg>)/$1<\\/g>$2/;\n  $svg =~ s/<g id=\"graph\\d\"(.*?)/<g id=\"viewport\"$1/;\n\n  if ($main::opt_svg) {\n    # --svg: write to standard output.\n    print $svg;\n  } else {\n    # Write back to temporary file.\n    open(SVG, \">$svgfile\") || die \"open $svgfile: $!\";\n    print SVG $svg;\n    close(SVG);\n  }\n}\n\nsub SvgJavascript {\n  return <<'EOF';\n<script type=\"text/ecmascript\"><![CDATA[\n// SVGPan\n// http://www.cyberz.org/blog/2009/12/08/svgpan-a-javascript-svg-panzoomdrag-library/\n// Local modification: if(true || ...) below to force panning, never moving.\n\n/**\n *  SVGPan library 1.2\n * ====================\n *\n * Given an unique existing element with id \"viewport\", including the\n * the library into any SVG adds the following capabilities:\n *\n *  - Mouse panning\n *  - Mouse zooming (using the wheel)\n *  - Object dargging\n *\n * Known issues:\n *\n *  - Zooming (while panning) on Safari has still some issues\n *\n * Releases:\n *\n * 1.2, Sat Mar 20 08:42:50 GMT 2010, Zeng Xiaohui\n *\tFixed a bug with browser mouse handler interaction\n *\n * 1.1, Wed Feb  3 17:39:33 GMT 2010, Zeng Xiaohui\n *\tUpdated the zoom code to support the mouse wheel on Safari/Chrome\n *\n * 1.0, Andrea Leofreddi\n *\tFirst release\n *\n * This code is licensed under the following BSD license:\n *\n * Copyright 2009-2010 Andrea Leofreddi <a.leofreddi@itcharm.com>. All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without modification, are\n * permitted provided that the following conditions are met:\n *\n *    1. Redistributions of source code must retain the above copyright notice, this list of\n *       conditions and the following disclaimer.\n *\n *    2. Redistributions in binary form must reproduce the above copyright notice, this list\n *       of conditions and the following disclaimer in the documentation and/or other materials\n *       provided with the distribution.\n *\n * THIS SOFTWARE IS PROVIDED BY Andrea Leofreddi ``AS IS'' AND ANY EXPRESS OR IMPLIED\n * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND\n * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL Andrea Leofreddi OR\n * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR\n * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR\n * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON\n * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING\n * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF\n * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n *\n * The views and conclusions contained in the software and documentation are those of the\n * authors and should not be interpreted as representing official policies, either expressed\n * or implied, of Andrea Leofreddi.\n */\n\nvar root = document.documentElement;\n\nvar state = 'none', stateTarget, stateOrigin, stateTf;\n\nsetupHandlers(root);\n\n/**\n * Register handlers\n */\nfunction setupHandlers(root){\n\tsetAttributes(root, {\n\t\t\"onmouseup\" : \"add(evt)\",\n\t\t\"onmousedown\" : \"handleMouseDown(evt)\",\n\t\t\"onmousemove\" : \"handleMouseMove(evt)\",\n\t\t\"onmouseup\" : \"handleMouseUp(evt)\",\n\t\t//\"onmouseout\" : \"handleMouseUp(evt)\", // Decomment this to stop the pan functionality when dragging out of the SVG element\n\t});\n\n\tif(navigator.userAgent.toLowerCase().indexOf('webkit') >= 0)\n\t\twindow.addEventListener('mousewheel', handleMouseWheel, false); // Chrome/Safari\n\telse\n\t\twindow.addEventListener('DOMMouseScroll', handleMouseWheel, false); // Others\n\n\tvar g = svgDoc.getElementById(\"svg\");\n\tg.width = \"100%\";\n\tg.height = \"100%\";\n}\n\n/**\n * Instance an SVGPoint object with given event coordinates.\n */\nfunction getEventPoint(evt) {\n\tvar p = root.createSVGPoint();\n\n\tp.x = evt.clientX;\n\tp.y = evt.clientY;\n\n\treturn p;\n}\n\n/**\n * Sets the current transform matrix of an element.\n */\nfunction setCTM(element, matrix) {\n\tvar s = \"matrix(\" + matrix.a + \",\" + matrix.b + \",\" + matrix.c + \",\" + matrix.d + \",\" + matrix.e + \",\" + matrix.f + \")\";\n\n\telement.setAttribute(\"transform\", s);\n}\n\n/**\n * Dumps a matrix to a string (useful for debug).\n */\nfunction dumpMatrix(matrix) {\n\tvar s = \"[ \" + matrix.a + \", \" + matrix.c + \", \" + matrix.e + \"\\n  \" + matrix.b + \", \" + matrix.d + \", \" + matrix.f + \"\\n  0, 0, 1 ]\";\n\n\treturn s;\n}\n\n/**\n * Sets attributes of an element.\n */\nfunction setAttributes(element, attributes){\n\tfor (i in attributes)\n\t\telement.setAttributeNS(null, i, attributes[i]);\n}\n\n/**\n * Handle mouse move event.\n */\nfunction handleMouseWheel(evt) {\n\tif(evt.preventDefault)\n\t\tevt.preventDefault();\n\n\tevt.returnValue = false;\n\n\tvar svgDoc = evt.target.ownerDocument;\n\n\tvar delta;\n\n\tif(evt.wheelDelta)\n\t\tdelta = evt.wheelDelta / 3600; // Chrome/Safari\n\telse\n\t\tdelta = evt.detail / -90; // Mozilla\n\n\tvar z = 1 + delta; // Zoom factor: 0.9/1.1\n\n\tvar g = svgDoc.getElementById(\"viewport\");\n\n\tvar p = getEventPoint(evt);\n\n\tp = p.matrixTransform(g.getCTM().inverse());\n\n\t// Compute new scale matrix in current mouse position\n\tvar k = root.createSVGMatrix().translate(p.x, p.y).scale(z).translate(-p.x, -p.y);\n\n        setCTM(g, g.getCTM().multiply(k));\n\n\tstateTf = stateTf.multiply(k.inverse());\n}\n\n/**\n * Handle mouse move event.\n */\nfunction handleMouseMove(evt) {\n\tif(evt.preventDefault)\n\t\tevt.preventDefault();\n\n\tevt.returnValue = false;\n\n\tvar svgDoc = evt.target.ownerDocument;\n\n\tvar g = svgDoc.getElementById(\"viewport\");\n\n\tif(state == 'pan') {\n\t\t// Pan mode\n\t\tvar p = getEventPoint(evt).matrixTransform(stateTf);\n\n\t\tsetCTM(g, stateTf.inverse().translate(p.x - stateOrigin.x, p.y - stateOrigin.y));\n\t} else if(state == 'move') {\n\t\t// Move mode\n\t\tvar p = getEventPoint(evt).matrixTransform(g.getCTM().inverse());\n\n\t\tsetCTM(stateTarget, root.createSVGMatrix().translate(p.x - stateOrigin.x, p.y - stateOrigin.y).multiply(g.getCTM().inverse()).multiply(stateTarget.getCTM()));\n\n\t\tstateOrigin = p;\n\t}\n}\n\n/**\n * Handle click event.\n */\nfunction handleMouseDown(evt) {\n\tif(evt.preventDefault)\n\t\tevt.preventDefault();\n\n\tevt.returnValue = false;\n\n\tvar svgDoc = evt.target.ownerDocument;\n\n\tvar g = svgDoc.getElementById(\"viewport\");\n\n\tif(true || evt.target.tagName == \"svg\") {\n\t\t// Pan mode\n\t\tstate = 'pan';\n\n\t\tstateTf = g.getCTM().inverse();\n\n\t\tstateOrigin = getEventPoint(evt).matrixTransform(stateTf);\n\t} else {\n\t\t// Move mode\n\t\tstate = 'move';\n\n\t\tstateTarget = evt.target;\n\n\t\tstateTf = g.getCTM().inverse();\n\n\t\tstateOrigin = getEventPoint(evt).matrixTransform(stateTf);\n\t}\n}\n\n/**\n * Handle mouse button release event.\n */\nfunction handleMouseUp(evt) {\n\tif(evt.preventDefault)\n\t\tevt.preventDefault();\n\n\tevt.returnValue = false;\n\n\tvar svgDoc = evt.target.ownerDocument;\n\n\tif(state == 'pan' || state == 'move') {\n\t\t// Quit pan mode\n\t\tstate = '';\n\t}\n}\n\n]]></script>\nEOF\n}\n\n# Provides a map from fullname to shortname for cases where the\n# shortname is ambiguous.  The symlist has both the fullname and\n# shortname for all symbols, which is usually fine, but sometimes --\n# such as overloaded functions -- two different fullnames can map to\n# the same shortname.  In that case, we use the address of the\n# function to disambiguate the two.  This function fills in a map that\n# maps fullnames to modified shortnames in such cases.  If a fullname\n# is not present in the map, the 'normal' shortname provided by the\n# symlist is the appropriate one to use.\nsub FillFullnameToShortnameMap {\n  my $symbols = shift;\n  my $fullname_to_shortname_map = shift;\n  my $shortnames_seen_once = {};\n  my $shortnames_seen_more_than_once = {};\n\n  foreach my $symlist (values(%{$symbols})) {\n    # TODO(csilvers): deal with inlined symbols too.\n    my $shortname = $symlist->[0];\n    my $fullname = $symlist->[2];\n    if ($fullname !~ /<[0-9a-fA-F]+>$/) {  # fullname doesn't end in an address\n      next;       # the only collisions we care about are when addresses differ\n    }\n    if (defined($shortnames_seen_once->{$shortname}) &&\n        $shortnames_seen_once->{$shortname} ne $fullname) {\n      $shortnames_seen_more_than_once->{$shortname} = 1;\n    } else {\n      $shortnames_seen_once->{$shortname} = $fullname;\n    }\n  }\n\n  foreach my $symlist (values(%{$symbols})) {\n    my $shortname = $symlist->[0];\n    my $fullname = $symlist->[2];\n    # TODO(csilvers): take in a list of addresses we care about, and only\n    # store in the map if $symlist->[1] is in that list.  Saves space.\n    next if defined($fullname_to_shortname_map->{$fullname});\n    if (defined($shortnames_seen_more_than_once->{$shortname})) {\n      if ($fullname =~ /<0*([^>]*)>$/) {   # fullname has address at end of it\n        $fullname_to_shortname_map->{$fullname} = \"$shortname\\@$1\";\n      }\n    }\n  }\n}\n\n# Return a small number that identifies the argument.\n# Multiple calls with the same argument will return the same number.\n# Calls with different arguments will return different numbers.\nsub ShortIdFor {\n  my $key = shift;\n  my $id = $main::uniqueid{$key};\n  if (!defined($id)) {\n    $id = keys(%main::uniqueid) + 1;\n    $main::uniqueid{$key} = $id;\n  }\n  return $id;\n}\n\n# Translate a stack of addresses into a stack of symbols\nsub TranslateStack {\n  my $symbols = shift;\n  my $fullname_to_shortname_map = shift;\n  my $k = shift;\n\n  my @addrs = split(/\\n/, $k);\n  my @result = ();\n  for (my $i = 0; $i <= $#addrs; $i++) {\n    my $a = $addrs[$i];\n\n    # Skip large addresses since they sometimes show up as fake entries on RH9\n    if (length($a) > 8 && $a gt \"7fffffffffffffff\") {\n      next;\n    }\n\n    if ($main::opt_disasm || $main::opt_list) {\n      # We want just the address for the key\n      push(@result, $a);\n      next;\n    }\n\n    my $symlist = $symbols->{$a};\n    if (!defined($symlist)) {\n      $symlist = [$a, \"\", $a];\n    }\n\n    # We can have a sequence of symbols for a particular entry\n    # (more than one symbol in the case of inlining).  Callers\n    # come before callees in symlist, so walk backwards since\n    # the translated stack should contain callees before callers.\n    for (my $j = $#{$symlist}; $j >= 2; $j -= 3) {\n      my $func = $symlist->[$j-2];\n      my $fileline = $symlist->[$j-1];\n      my $fullfunc = $symlist->[$j];\n      if (defined($fullname_to_shortname_map->{$fullfunc})) {\n        $func = $fullname_to_shortname_map->{$fullfunc};\n      }\n      if ($j > 2) {\n        $func = \"$func (inline)\";\n      }\n\n      # Do not merge nodes corresponding to Callback::Run since that\n      # causes confusing cycles in dot display.  Instead, we synthesize\n      # a unique name for this frame per caller.\n      if ($func =~ m/Callback.*::Run$/) {\n        my $caller = ($i > 0) ? $addrs[$i-1] : 0;\n        $func = \"Run#\" . ShortIdFor($caller);\n      }\n\n      if ($main::opt_addresses) {\n        push(@result, \"$a $func $fileline\");\n      } elsif ($main::opt_lines) {\n        if ($func eq '??' && $fileline eq '??:0') {\n          push(@result, \"$a\");\n        } else {\n          push(@result, \"$func $fileline\");\n        }\n      } elsif ($main::opt_functions) {\n        if ($func eq '??') {\n          push(@result, \"$a\");\n        } else {\n          push(@result, $func);\n        }\n      } elsif ($main::opt_files) {\n        if ($fileline eq '??:0' || $fileline eq '') {\n          push(@result, \"$a\");\n        } else {\n          my $f = $fileline;\n          $f =~ s/:\\d+$//;\n          push(@result, $f);\n        }\n      } else {\n        push(@result, $a);\n        last;  # Do not print inlined info\n      }\n    }\n  }\n\n  # print join(\",\", @addrs), \" => \", join(\",\", @result), \"\\n\";\n  return @result;\n}\n\n# Generate percent string for a number and a total\nsub Percent {\n  my $num = shift;\n  my $tot = shift;\n  if ($tot != 0) {\n    return sprintf(\"%.1f%%\", $num * 100.0 / $tot);\n  } else {\n    return ($num == 0) ? \"nan\" : (($num > 0) ? \"+inf\" : \"-inf\");\n  }\n}\n\n# Generate pretty-printed form of number\nsub Unparse {\n  my $num = shift;\n  if ($main::profile_type eq 'heap' || $main::profile_type eq 'growth') {\n    if ($main::opt_inuse_objects || $main::opt_alloc_objects) {\n      return sprintf(\"%d\", $num);\n    } else {\n      if ($main::opt_show_bytes) {\n        return sprintf(\"%d\", $num);\n      } else {\n        return sprintf(\"%.1f\", $num / 1048576.0);\n      }\n    }\n  } elsif ($main::profile_type eq 'contention' && !$main::opt_contentions) {\n    return sprintf(\"%.3f\", $num / 1e9); # Convert nanoseconds to seconds\n  } else {\n    return sprintf(\"%d\", $num);\n  }\n}\n\n# Alternate pretty-printed form: 0 maps to \".\"\nsub UnparseAlt {\n  my $num = shift;\n  if ($num == 0) {\n    return \".\";\n  } else {\n    return Unparse($num);\n  }\n}\n\n# Alternate pretty-printed form: 0 maps to \"\"\nsub HtmlPrintNumber {\n  my $num = shift;\n  if ($num == 0) {\n    return \"\";\n  } else {\n    return Unparse($num);\n  }\n}\n\n# Return output units\nsub Units {\n  if ($main::profile_type eq 'heap' || $main::profile_type eq 'growth') {\n    if ($main::opt_inuse_objects || $main::opt_alloc_objects) {\n      return \"objects\";\n    } else {\n      if ($main::opt_show_bytes) {\n        return \"B\";\n      } else {\n        return \"MB\";\n      }\n    }\n  } elsif ($main::profile_type eq 'contention' && !$main::opt_contentions) {\n    return \"seconds\";\n  } else {\n    return \"samples\";\n  }\n}\n\n##### Profile manipulation code #####\n\n# Generate flattened profile:\n# If count is charged to stack [a,b,c,d], in generated profile,\n# it will be charged to [a]\nsub FlatProfile {\n  my $profile = shift;\n  my $result = {};\n  foreach my $k (keys(%{$profile})) {\n    my $count = $profile->{$k};\n    my @addrs = split(/\\n/, $k);\n    if ($#addrs >= 0) {\n      AddEntry($result, $addrs[0], $count);\n    }\n  }\n  return $result;\n}\n\n# Generate cumulative profile:\n# If count is charged to stack [a,b,c,d], in generated profile,\n# it will be charged to [a], [b], [c], [d]\nsub CumulativeProfile {\n  my $profile = shift;\n  my $result = {};\n  foreach my $k (keys(%{$profile})) {\n    my $count = $profile->{$k};\n    my @addrs = split(/\\n/, $k);\n    foreach my $a (@addrs) {\n      AddEntry($result, $a, $count);\n    }\n  }\n  return $result;\n}\n\n# If the second-youngest PC on the stack is always the same, returns\n# that pc.  Otherwise, returns undef.\nsub IsSecondPcAlwaysTheSame {\n  my $profile = shift;\n\n  my $second_pc = undef;\n  foreach my $k (keys(%{$profile})) {\n    my @addrs = split(/\\n/, $k);\n    if ($#addrs < 1) {\n      return undef;\n    }\n    if (not defined $second_pc) {\n      $second_pc = $addrs[1];\n    } else {\n      if ($second_pc ne $addrs[1]) {\n        return undef;\n      }\n    }\n  }\n  return $second_pc;\n}\n\nsub ExtractSymbolLocation {\n  my $symbols = shift;\n  my $address = shift;\n  # 'addr2line' outputs \"??:0\" for unknown locations; we do the\n  # same to be consistent.\n  my $location = \"??:0:unknown\";\n  if (exists $symbols->{$address}) {\n    my $file = $symbols->{$address}->[1];\n    if ($file eq \"?\") {\n      $file = \"??:0\"\n    }\n    $location = $file . \":\" . $symbols->{$address}->[0];\n  }\n  return $location;\n}\n\n# Extracts a graph of calls.\nsub ExtractCalls {\n  my $symbols = shift;\n  my $profile = shift;\n\n  my $calls = {};\n  while( my ($stack_trace, $count) = each %$profile ) {\n    my @address = split(/\\n/, $stack_trace);\n    my $destination = ExtractSymbolLocation($symbols, $address[0]);\n    AddEntry($calls, $destination, $count);\n    for (my $i = 1; $i <= $#address; $i++) {\n      my $source = ExtractSymbolLocation($symbols, $address[$i]);\n      my $call = \"$source -> $destination\";\n      AddEntry($calls, $call, $count);\n      $destination = $source;\n    }\n  }\n\n  return $calls;\n}\n\nsub RemoveUninterestingFrames {\n  my $symbols = shift;\n  my $profile = shift;\n\n  # List of function names to skip\n  my %skip = ();\n  my $skip_regexp = 'NOMATCH';\n  if ($main::profile_type eq 'heap' || $main::profile_type eq 'growth') {\n    foreach my $name ('calloc',\n                      'cfree',\n                      'malloc',\n                      'free',\n                      'memalign',\n                      'posix_memalign',\n                      'aligned_alloc',\n                      'pvalloc',\n                      'valloc',\n                      'realloc',\n                      'mallocx', # jemalloc\n                      'rallocx', # jemalloc\n                      'xallocx', # jemalloc\n                      'dallocx', # jemalloc\n                      'sdallocx', # jemalloc\n                      'tc_calloc',\n                      'tc_cfree',\n                      'tc_malloc',\n                      'tc_free',\n                      'tc_memalign',\n                      'tc_posix_memalign',\n                      'tc_pvalloc',\n                      'tc_valloc',\n                      'tc_realloc',\n                      'tc_new',\n                      'tc_delete',\n                      'tc_newarray',\n                      'tc_deletearray',\n                      'tc_new_nothrow',\n                      'tc_newarray_nothrow',\n                      'do_malloc',\n                      '::do_malloc',   # new name -- got moved to an unnamed ns\n                      '::do_malloc_or_cpp_alloc',\n                      'DoSampledAllocation',\n                      'simple_alloc::allocate',\n                      '__malloc_alloc_template::allocate',\n                      '__builtin_delete',\n                      '__builtin_new',\n                      '__builtin_vec_delete',\n                      '__builtin_vec_new',\n                      'operator new',\n                      'operator new[]',\n                      # The entry to our memory-allocation routines on OS X\n                      'malloc_zone_malloc',\n                      'malloc_zone_calloc',\n                      'malloc_zone_valloc',\n                      'malloc_zone_realloc',\n                      'malloc_zone_memalign',\n                      'malloc_zone_free',\n                      # These mark the beginning/end of our custom sections\n                      '__start_google_malloc',\n                      '__stop_google_malloc',\n                      '__start_malloc_hook',\n                      '__stop_malloc_hook') {\n      $skip{$name} = 1;\n      $skip{\"_\" . $name} = 1;   # Mach (OS X) adds a _ prefix to everything\n    }\n    # TODO: Remove TCMalloc once everything has been\n    # moved into the tcmalloc:: namespace and we have flushed\n    # old code out of the system.\n    $skip_regexp = \"TCMalloc|^tcmalloc::\";\n  } elsif ($main::profile_type eq 'contention') {\n    foreach my $vname ('base::RecordLockProfileData',\n                       'base::SubmitMutexProfileData',\n                       'base::SubmitSpinLockProfileData',\n                       'Mutex::Unlock',\n                       'Mutex::UnlockSlow',\n                       'Mutex::ReaderUnlock',\n                       'MutexLock::~MutexLock',\n                       'SpinLock::Unlock',\n                       'SpinLock::SlowUnlock',\n                       'SpinLockHolder::~SpinLockHolder') {\n      $skip{$vname} = 1;\n    }\n  } elsif ($main::profile_type eq 'cpu') {\n    # Drop signal handlers used for CPU profile collection\n    # TODO(dpeng): this should not be necessary; it's taken\n    # care of by the general 2nd-pc mechanism below.\n    foreach my $name ('ProfileData::Add',           # historical\n                      'ProfileData::prof_handler',  # historical\n                      'CpuProfiler::prof_handler',\n                      '__FRAME_END__',\n                      '__pthread_sighandler',\n                      '__restore') {\n      $skip{$name} = 1;\n    }\n  } else {\n    # Nothing skipped for unknown types\n  }\n\n  if ($main::profile_type eq 'cpu') {\n    # If all the second-youngest program counters are the same,\n    # this STRONGLY suggests that it is an artifact of measurement,\n    # i.e., stack frames pushed by the CPU profiler signal handler.\n    # Hence, we delete them.\n    # (The topmost PC is read from the signal structure, not from\n    # the stack, so it does not get involved.)\n    while (my $second_pc = IsSecondPcAlwaysTheSame($profile)) {\n      my $result = {};\n      my $func = '';\n      if (exists($symbols->{$second_pc})) {\n        $second_pc = $symbols->{$second_pc}->[0];\n      }\n      print STDERR \"Removing $second_pc from all stack traces.\\n\";\n      foreach my $k (keys(%{$profile})) {\n        my $count = $profile->{$k};\n        my @addrs = split(/\\n/, $k);\n        splice @addrs, 1, 1;\n        my $reduced_path = join(\"\\n\", @addrs);\n        AddEntry($result, $reduced_path, $count);\n      }\n      $profile = $result;\n    }\n  }\n\n  my $result = {};\n  foreach my $k (keys(%{$profile})) {\n    my $count = $profile->{$k};\n    my @addrs = split(/\\n/, $k);\n    my @path = ();\n    foreach my $a (@addrs) {\n      if (exists($symbols->{$a})) {\n        my $func = $symbols->{$a}->[0];\n        if ($skip{$func} || ($func =~ m/$skip_regexp/)) {\n          # Throw away the portion of the backtrace seen so far, under the\n          # assumption that previous frames were for functions internal to the\n          # allocator.\n          @path = ();\n          next;\n        }\n      }\n      push(@path, $a);\n    }\n    my $reduced_path = join(\"\\n\", @path);\n    AddEntry($result, $reduced_path, $count);\n  }\n  return $result;\n}\n\n# Reduce profile to granularity given by user\nsub ReduceProfile {\n  my $symbols = shift;\n  my $profile = shift;\n  my $result = {};\n  my $fullname_to_shortname_map = {};\n  FillFullnameToShortnameMap($symbols, $fullname_to_shortname_map);\n  foreach my $k (keys(%{$profile})) {\n    my $count = $profile->{$k};\n    my @translated = TranslateStack($symbols, $fullname_to_shortname_map, $k);\n    my @path = ();\n    my %seen = ();\n    $seen{''} = 1;      # So that empty keys are skipped\n    foreach my $e (@translated) {\n      # To avoid double-counting due to recursion, skip a stack-trace\n      # entry if it has already been seen\n      if (!$seen{$e}) {\n        $seen{$e} = 1;\n        push(@path, $e);\n      }\n    }\n    my $reduced_path = join(\"\\n\", @path);\n    AddEntry($result, $reduced_path, $count);\n  }\n  return $result;\n}\n\n# Does the specified symbol array match the regexp?\nsub SymbolMatches {\n  my $sym = shift;\n  my $re = shift;\n  if (defined($sym)) {\n    for (my $i = 0; $i < $#{$sym}; $i += 3) {\n      if ($sym->[$i] =~ m/$re/ || $sym->[$i+1] =~ m/$re/) {\n        return 1;\n      }\n    }\n  }\n  return 0;\n}\n\n# Focus only on paths involving specified regexps\nsub FocusProfile {\n  my $symbols = shift;\n  my $profile = shift;\n  my $focus = shift;\n  my $result = {};\n  foreach my $k (keys(%{$profile})) {\n    my $count = $profile->{$k};\n    my @addrs = split(/\\n/, $k);\n    foreach my $a (@addrs) {\n      # Reply if it matches either the address/shortname/fileline\n      if (($a =~ m/$focus/) || SymbolMatches($symbols->{$a}, $focus)) {\n        AddEntry($result, $k, $count);\n        last;\n      }\n    }\n  }\n  return $result;\n}\n\n# Focus only on paths not involving specified regexps\nsub IgnoreProfile {\n  my $symbols = shift;\n  my $profile = shift;\n  my $ignore = shift;\n  my $result = {};\n  foreach my $k (keys(%{$profile})) {\n    my $count = $profile->{$k};\n    my @addrs = split(/\\n/, $k);\n    my $matched = 0;\n    foreach my $a (@addrs) {\n      # Reply if it matches either the address/shortname/fileline\n      if (($a =~ m/$ignore/) || SymbolMatches($symbols->{$a}, $ignore)) {\n        $matched = 1;\n        last;\n      }\n    }\n    if (!$matched) {\n      AddEntry($result, $k, $count);\n    }\n  }\n  return $result;\n}\n\n# Get total count in profile\nsub TotalProfile {\n  my $profile = shift;\n  my $result = 0;\n  foreach my $k (keys(%{$profile})) {\n    $result += $profile->{$k};\n  }\n  return $result;\n}\n\n# Add A to B\nsub AddProfile {\n  my $A = shift;\n  my $B = shift;\n\n  my $R = {};\n  # add all keys in A\n  foreach my $k (keys(%{$A})) {\n    my $v = $A->{$k};\n    AddEntry($R, $k, $v);\n  }\n  # add all keys in B\n  foreach my $k (keys(%{$B})) {\n    my $v = $B->{$k};\n    AddEntry($R, $k, $v);\n  }\n  return $R;\n}\n\n# Merges symbol maps\nsub MergeSymbols {\n  my $A = shift;\n  my $B = shift;\n\n  my $R = {};\n  foreach my $k (keys(%{$A})) {\n    $R->{$k} = $A->{$k};\n  }\n  if (defined($B)) {\n    foreach my $k (keys(%{$B})) {\n      $R->{$k} = $B->{$k};\n    }\n  }\n  return $R;\n}\n\n\n# Add A to B\nsub AddPcs {\n  my $A = shift;\n  my $B = shift;\n\n  my $R = {};\n  # add all keys in A\n  foreach my $k (keys(%{$A})) {\n    $R->{$k} = 1\n  }\n  # add all keys in B\n  foreach my $k (keys(%{$B})) {\n    $R->{$k} = 1\n  }\n  return $R;\n}\n\n# Subtract B from A\nsub SubtractProfile {\n  my $A = shift;\n  my $B = shift;\n\n  my $R = {};\n  foreach my $k (keys(%{$A})) {\n    my $v = $A->{$k} - GetEntry($B, $k);\n    if ($v < 0 && $main::opt_drop_negative) {\n      $v = 0;\n    }\n    AddEntry($R, $k, $v);\n  }\n  if (!$main::opt_drop_negative) {\n    # Take care of when subtracted profile has more entries\n    foreach my $k (keys(%{$B})) {\n      if (!exists($A->{$k})) {\n        AddEntry($R, $k, 0 - $B->{$k});\n      }\n    }\n  }\n  return $R;\n}\n\n# Get entry from profile; zero if not present\nsub GetEntry {\n  my $profile = shift;\n  my $k = shift;\n  if (exists($profile->{$k})) {\n    return $profile->{$k};\n  } else {\n    return 0;\n  }\n}\n\n# Add entry to specified profile\nsub AddEntry {\n  my $profile = shift;\n  my $k = shift;\n  my $n = shift;\n  if (!exists($profile->{$k})) {\n    $profile->{$k} = 0;\n  }\n  $profile->{$k} += $n;\n}\n\n# Add a stack of entries to specified profile, and add them to the $pcs\n# list.\nsub AddEntries {\n  my $profile = shift;\n  my $pcs = shift;\n  my $stack = shift;\n  my $count = shift;\n  my @k = ();\n\n  foreach my $e (split(/\\s+/, $stack)) {\n    my $pc = HexExtend($e);\n    $pcs->{$pc} = 1;\n    push @k, $pc;\n  }\n  AddEntry($profile, (join \"\\n\", @k), $count);\n}\n\n##### Code to profile a server dynamically #####\n\nsub CheckSymbolPage {\n  my $url = SymbolPageURL();\n  my $command = ShellEscape(@URL_FETCHER, $url);\n  open(SYMBOL, \"$command |\") or error($command);\n  my $line = <SYMBOL>;\n  $line =~ s/\\r//g;         # turn windows-looking lines into unix-looking lines\n  close(SYMBOL);\n  unless (defined($line)) {\n    error(\"$url doesn't exist\\n\");\n  }\n\n  if ($line =~ /^num_symbols:\\s+(\\d+)$/) {\n    if ($1 == 0) {\n      error(\"Stripped binary. No symbols available.\\n\");\n    }\n  } else {\n    error(\"Failed to get the number of symbols from $url\\n\");\n  }\n}\n\nsub IsProfileURL {\n  my $profile_name = shift;\n  if (-f $profile_name) {\n    printf STDERR \"Using local file $profile_name.\\n\";\n    return 0;\n  }\n  return 1;\n}\n\nsub ParseProfileURL {\n  my $profile_name = shift;\n\n  if (!defined($profile_name) || $profile_name eq \"\") {\n    return ();\n  }\n\n  # Split profile URL - matches all non-empty strings, so no test.\n  $profile_name =~ m,^(https?://)?([^/]+)(.*?)(/|$PROFILES)?$,;\n\n  my $proto = $1 || \"http://\";\n  my $hostport = $2;\n  my $prefix = $3;\n  my $profile = $4 || \"/\";\n\n  my $host = $hostport;\n  $host =~ s/:.*//;\n\n  my $baseurl = \"$proto$hostport$prefix\";\n  return ($host, $baseurl, $profile);\n}\n\n# We fetch symbols from the first profile argument.\nsub SymbolPageURL {\n  my ($host, $baseURL, $path) = ParseProfileURL($main::pfile_args[0]);\n  return \"$baseURL$SYMBOL_PAGE\";\n}\n\nsub FetchProgramName() {\n  my ($host, $baseURL, $path) = ParseProfileURL($main::pfile_args[0]);\n  my $url = \"$baseURL$PROGRAM_NAME_PAGE\";\n  my $command_line = ShellEscape(@URL_FETCHER, $url);\n  open(CMDLINE, \"$command_line |\") or error($command_line);\n  my $cmdline = <CMDLINE>;\n  $cmdline =~ s/\\r//g;   # turn windows-looking lines into unix-looking lines\n  close(CMDLINE);\n  error(\"Failed to get program name from $url\\n\") unless defined($cmdline);\n  $cmdline =~ s/\\x00.+//;  # Remove argv[1] and latters.\n  $cmdline =~ s!\\n!!g;  # Remove LFs.\n  return $cmdline;\n}\n\n# Gee, curl's -L (--location) option isn't reliable at least\n# with its 7.12.3 version.  Curl will forget to post data if\n# there is a redirection.  This function is a workaround for\n# curl.  Redirection happens on borg hosts.\nsub ResolveRedirectionForCurl {\n  my $url = shift;\n  my $command_line = ShellEscape(@URL_FETCHER, \"--head\", $url);\n  open(CMDLINE, \"$command_line |\") or error($command_line);\n  while (<CMDLINE>) {\n    s/\\r//g;         # turn windows-looking lines into unix-looking lines\n    if (/^Location: (.*)/) {\n      $url = $1;\n    }\n  }\n  close(CMDLINE);\n  return $url;\n}\n\n# Add a timeout flat to URL_FETCHER.  Returns a new list.\nsub AddFetchTimeout {\n  my $timeout = shift;\n  my @fetcher = shift;\n  if (defined($timeout)) {\n    if (join(\" \", @fetcher) =~ m/\\bcurl -s/) {\n      push(@fetcher, \"--max-time\", sprintf(\"%d\", $timeout));\n    } elsif (join(\" \", @fetcher) =~ m/\\brpcget\\b/) {\n      push(@fetcher, sprintf(\"--deadline=%d\", $timeout));\n    }\n  }\n  return @fetcher;\n}\n\n# Reads a symbol map from the file handle name given as $1, returning\n# the resulting symbol map.  Also processes variables relating to symbols.\n# Currently, the only variable processed is 'binary=<value>' which updates\n# $main::prog to have the correct program name.\nsub ReadSymbols {\n  my $in = shift;\n  my $map = {};\n  while (<$in>) {\n    s/\\r//g;         # turn windows-looking lines into unix-looking lines\n    # Removes all the leading zeroes from the symbols, see comment below.\n    if (m/^0x0*([0-9a-f]+)\\s+(.+)/) {\n      $map->{$1} = $2;\n    } elsif (m/^---/) {\n      last;\n    } elsif (m/^([a-z][^=]*)=(.*)$/ ) {\n      my ($variable, $value) = ($1, $2);\n      for ($variable, $value) {\n        s/^\\s+//;\n        s/\\s+$//;\n      }\n      if ($variable eq \"binary\") {\n        if ($main::prog ne $UNKNOWN_BINARY && $main::prog ne $value) {\n          printf STDERR (\"Warning: Mismatched binary name '%s', using '%s'.\\n\",\n                         $main::prog, $value);\n        }\n        $main::prog = $value;\n      } else {\n        printf STDERR (\"Ignoring unknown variable in symbols list: \" .\n            \"'%s' = '%s'\\n\", $variable, $value);\n      }\n    }\n  }\n  return $map;\n}\n\n# Fetches and processes symbols to prepare them for use in the profile output\n# code.  If the optional 'symbol_map' arg is not given, fetches symbols from\n# $SYMBOL_PAGE for all PC values found in profile.  Otherwise, the raw symbols\n# are assumed to have already been fetched into 'symbol_map' and are simply\n# extracted and processed.\nsub FetchSymbols {\n  my $pcset = shift;\n  my $symbol_map = shift;\n\n  my %seen = ();\n  my @pcs = grep { !$seen{$_}++ } keys(%$pcset);  # uniq\n\n  if (!defined($symbol_map)) {\n    my $post_data = join(\"+\", sort((map {\"0x\" . \"$_\"} @pcs)));\n\n    open(POSTFILE, \">$main::tmpfile_sym\");\n    print POSTFILE $post_data;\n    close(POSTFILE);\n\n    my $url = SymbolPageURL();\n\n    my $command_line;\n    if (join(\" \", @URL_FETCHER) =~ m/\\bcurl -s/) {\n      $url = ResolveRedirectionForCurl($url);\n      $command_line = ShellEscape(@URL_FETCHER, \"-d\", \"\\@$main::tmpfile_sym\",\n                                  $url);\n    } else {\n      $command_line = (ShellEscape(@URL_FETCHER, \"--post\", $url)\n                       . \" < \" . ShellEscape($main::tmpfile_sym));\n    }\n    # We use c++filt in case $SYMBOL_PAGE gives us mangled symbols.\n    my $escaped_cppfilt = ShellEscape($obj_tool_map{\"c++filt\"});\n    open(SYMBOL, \"$command_line | $escaped_cppfilt |\") or error($command_line);\n    $symbol_map = ReadSymbols(*SYMBOL{IO});\n    close(SYMBOL);\n  }\n\n  my $symbols = {};\n  foreach my $pc (@pcs) {\n    my $fullname;\n    # For 64 bits binaries, symbols are extracted with 8 leading zeroes.\n    # Then /symbol reads the long symbols in as uint64, and outputs\n    # the result with a \"0x%08llx\" format which get rid of the zeroes.\n    # By removing all the leading zeroes in both $pc and the symbols from\n    # /symbol, the symbols match and are retrievable from the map.\n    my $shortpc = $pc;\n    $shortpc =~ s/^0*//;\n    # Each line may have a list of names, which includes the function\n    # and also other functions it has inlined.  They are separated (in\n    # PrintSymbolizedProfile), by --, which is illegal in function names.\n    my $fullnames;\n    if (defined($symbol_map->{$shortpc})) {\n      $fullnames = $symbol_map->{$shortpc};\n    } else {\n      $fullnames = \"0x\" . $pc;  # Just use addresses\n    }\n    my $sym = [];\n    $symbols->{$pc} = $sym;\n    foreach my $fullname (split(\"--\", $fullnames)) {\n      my $name = ShortFunctionName($fullname);\n      push(@{$sym}, $name, \"?\", $fullname);\n    }\n  }\n  return $symbols;\n}\n\nsub BaseName {\n  my $file_name = shift;\n  $file_name =~ s!^.*/!!;  # Remove directory name\n  return $file_name;\n}\n\nsub MakeProfileBaseName {\n  my ($binary_name, $profile_name) = @_;\n  my ($host, $baseURL, $path) = ParseProfileURL($profile_name);\n  my $binary_shortname = BaseName($binary_name);\n  return sprintf(\"%s.%s.%s\",\n                 $binary_shortname, $main::op_time, $host);\n}\n\nsub FetchDynamicProfile {\n  my $binary_name = shift;\n  my $profile_name = shift;\n  my $fetch_name_only = shift;\n  my $encourage_patience = shift;\n\n  if (!IsProfileURL($profile_name)) {\n    return $profile_name;\n  } else {\n    my ($host, $baseURL, $path) = ParseProfileURL($profile_name);\n    if ($path eq \"\" || $path eq \"/\") {\n      # Missing type specifier defaults to cpu-profile\n      $path = $PROFILE_PAGE;\n    }\n\n    my $profile_file = MakeProfileBaseName($binary_name, $profile_name);\n\n    my $url = \"$baseURL$path\";\n    my $fetch_timeout = undef;\n    if ($path =~ m/$PROFILE_PAGE|$PMUPROFILE_PAGE/) {\n      if ($path =~ m/[?]/) {\n        $url .= \"&\";\n      } else {\n        $url .= \"?\";\n      }\n      $url .= sprintf(\"seconds=%d\", $main::opt_seconds);\n      $fetch_timeout = $main::opt_seconds * 1.01 + 60;\n    } else {\n      # For non-CPU profiles, we add a type-extension to\n      # the target profile file name.\n      my $suffix = $path;\n      $suffix =~ s,/,.,g;\n      $profile_file .= $suffix;\n    }\n\n    my $profile_dir = $ENV{\"JEPROF_TMPDIR\"} || ($ENV{HOME} . \"/jeprof\");\n    if (! -d $profile_dir) {\n      mkdir($profile_dir)\n          || die(\"Unable to create profile directory $profile_dir: $!\\n\");\n    }\n    my $tmp_profile = \"$profile_dir/.tmp.$profile_file\";\n    my $real_profile = \"$profile_dir/$profile_file\";\n\n    if ($fetch_name_only > 0) {\n      return $real_profile;\n    }\n\n    my @fetcher = AddFetchTimeout($fetch_timeout, @URL_FETCHER);\n    my $cmd = ShellEscape(@fetcher, $url) . \" > \" . ShellEscape($tmp_profile);\n    if ($path =~ m/$PROFILE_PAGE|$PMUPROFILE_PAGE|$CENSUSPROFILE_PAGE/){\n      print STDERR \"Gathering CPU profile from $url for $main::opt_seconds seconds to\\n  ${real_profile}\\n\";\n      if ($encourage_patience) {\n        print STDERR \"Be patient...\\n\";\n      }\n    } else {\n      print STDERR \"Fetching $path profile from $url to\\n  ${real_profile}\\n\";\n    }\n\n    (system($cmd) == 0) || error(\"Failed to get profile: $cmd: $!\\n\");\n    (system(\"mv\", $tmp_profile, $real_profile) == 0) || error(\"Unable to rename profile\\n\");\n    print STDERR \"Wrote profile to $real_profile\\n\";\n    $main::collected_profile = $real_profile;\n    return $main::collected_profile;\n  }\n}\n\n# Collect profiles in parallel\nsub FetchDynamicProfiles {\n  my $items = scalar(@main::pfile_args);\n  my $levels = log($items) / log(2);\n\n  if ($items == 1) {\n    $main::profile_files[0] = FetchDynamicProfile($main::prog, $main::pfile_args[0], 0, 1);\n  } else {\n    # math rounding issues\n    if ((2 ** $levels) < $items) {\n     $levels++;\n    }\n    my $count = scalar(@main::pfile_args);\n    for (my $i = 0; $i < $count; $i++) {\n      $main::profile_files[$i] = FetchDynamicProfile($main::prog, $main::pfile_args[$i], 1, 0);\n    }\n    print STDERR \"Fetching $count profiles, Be patient...\\n\";\n    FetchDynamicProfilesRecurse($levels, 0, 0);\n    $main::collected_profile = join(\" \\\\\\n    \", @main::profile_files);\n  }\n}\n\n# Recursively fork a process to get enough processes\n# collecting profiles\nsub FetchDynamicProfilesRecurse {\n  my $maxlevel = shift;\n  my $level = shift;\n  my $position = shift;\n\n  if (my $pid = fork()) {\n    $position = 0 | ($position << 1);\n    TryCollectProfile($maxlevel, $level, $position);\n    wait;\n  } else {\n    $position = 1 | ($position << 1);\n    TryCollectProfile($maxlevel, $level, $position);\n    cleanup();\n    exit(0);\n  }\n}\n\n# Collect a single profile\nsub TryCollectProfile {\n  my $maxlevel = shift;\n  my $level = shift;\n  my $position = shift;\n\n  if ($level >= ($maxlevel - 1)) {\n    if ($position < scalar(@main::pfile_args)) {\n      FetchDynamicProfile($main::prog, $main::pfile_args[$position], 0, 0);\n    }\n  } else {\n    FetchDynamicProfilesRecurse($maxlevel, $level+1, $position);\n  }\n}\n\n##### Parsing code #####\n\n# Provide a small streaming-read module to handle very large\n# cpu-profile files.  Stream in chunks along a sliding window.\n# Provides an interface to get one 'slot', correctly handling\n# endian-ness differences.  A slot is one 32-bit or 64-bit word\n# (depending on the input profile).  We tell endianness and bit-size\n# for the profile by looking at the first 8 bytes: in cpu profiles,\n# the second slot is always 3 (we'll accept anything that's not 0).\nBEGIN {\n  package CpuProfileStream;\n\n  sub new {\n    my ($class, $file, $fname) = @_;\n    my $self = { file        => $file,\n                 base        => 0,\n                 stride      => 512 * 1024,   # must be a multiple of bitsize/8\n                 slots       => [],\n                 unpack_code => \"\",           # N for big-endian, V for little\n                 perl_is_64bit => 1,          # matters if profile is 64-bit\n    };\n    bless $self, $class;\n    # Let unittests adjust the stride\n    if ($main::opt_test_stride > 0) {\n      $self->{stride} = $main::opt_test_stride;\n    }\n    # Read the first two slots to figure out bitsize and endianness.\n    my $slots = $self->{slots};\n    my $str;\n    read($self->{file}, $str, 8);\n    # Set the global $address_length based on what we see here.\n    # 8 is 32-bit (8 hexadecimal chars); 16 is 64-bit (16 hexadecimal chars).\n    $address_length = ($str eq (chr(0)x8)) ? 16 : 8;\n    if ($address_length == 8) {\n      if (substr($str, 6, 2) eq chr(0)x2) {\n        $self->{unpack_code} = 'V';  # Little-endian.\n      } elsif (substr($str, 4, 2) eq chr(0)x2) {\n        $self->{unpack_code} = 'N';  # Big-endian\n      } else {\n        ::error(\"$fname: header size >= 2**16\\n\");\n      }\n      @$slots = unpack($self->{unpack_code} . \"*\", $str);\n    } else {\n      # If we're a 64-bit profile, check if we're a 64-bit-capable\n      # perl.  Otherwise, each slot will be represented as a float\n      # instead of an int64, losing precision and making all the\n      # 64-bit addresses wrong.  We won't complain yet, but will\n      # later if we ever see a value that doesn't fit in 32 bits.\n      my $has_q = 0;\n      eval { $has_q = pack(\"Q\", \"1\") ? 1 : 1; };\n      if (!$has_q) {\n        $self->{perl_is_64bit} = 0;\n      }\n      read($self->{file}, $str, 8);\n      if (substr($str, 4, 4) eq chr(0)x4) {\n        # We'd love to use 'Q', but it's a) not universal, b) not endian-proof.\n        $self->{unpack_code} = 'V';  # Little-endian.\n      } elsif (substr($str, 0, 4) eq chr(0)x4) {\n        $self->{unpack_code} = 'N';  # Big-endian\n      } else {\n        ::error(\"$fname: header size >= 2**32\\n\");\n      }\n      my @pair = unpack($self->{unpack_code} . \"*\", $str);\n      # Since we know one of the pair is 0, it's fine to just add them.\n      @$slots = (0, $pair[0] + $pair[1]);\n    }\n    return $self;\n  }\n\n  # Load more data when we access slots->get(X) which is not yet in memory.\n  sub overflow {\n    my ($self) = @_;\n    my $slots = $self->{slots};\n    $self->{base} += $#$slots + 1;   # skip over data we're replacing\n    my $str;\n    read($self->{file}, $str, $self->{stride});\n    if ($address_length == 8) {      # the 32-bit case\n      # This is the easy case: unpack provides 32-bit unpacking primitives.\n      @$slots = unpack($self->{unpack_code} . \"*\", $str);\n    } else {\n      # We need to unpack 32 bits at a time and combine.\n      my @b32_values = unpack($self->{unpack_code} . \"*\", $str);\n      my @b64_values = ();\n      for (my $i = 0; $i < $#b32_values; $i += 2) {\n        # TODO(csilvers): if this is a 32-bit perl, the math below\n        #    could end up in a too-large int, which perl will promote\n        #    to a double, losing necessary precision.  Deal with that.\n        #    Right now, we just die.\n        my ($lo, $hi) = ($b32_values[$i], $b32_values[$i+1]);\n        if ($self->{unpack_code} eq 'N') {    # big-endian\n          ($lo, $hi) = ($hi, $lo);\n        }\n        my $value = $lo + $hi * (2**32);\n        if (!$self->{perl_is_64bit} &&   # check value is exactly represented\n            (($value % (2**32)) != $lo || int($value / (2**32)) != $hi)) {\n          ::error(\"Need a 64-bit perl to process this 64-bit profile.\\n\");\n        }\n        push(@b64_values, $value);\n      }\n      @$slots = @b64_values;\n    }\n  }\n\n  # Access the i-th long in the file (logically), or -1 at EOF.\n  sub get {\n    my ($self, $idx) = @_;\n    my $slots = $self->{slots};\n    while ($#$slots >= 0) {\n      if ($idx < $self->{base}) {\n        # The only time we expect a reference to $slots[$i - something]\n        # after referencing $slots[$i] is reading the very first header.\n        # Since $stride > |header|, that shouldn't cause any lookback\n        # errors.  And everything after the header is sequential.\n        print STDERR \"Unexpected look-back reading CPU profile\";\n        return -1;   # shrug, don't know what better to return\n      } elsif ($idx > $self->{base} + $#$slots) {\n        $self->overflow();\n      } else {\n        return $slots->[$idx - $self->{base}];\n      }\n    }\n    # If we get here, $slots is [], which means we've reached EOF\n    return -1;  # unique since slots is supposed to hold unsigned numbers\n  }\n}\n\n# Reads the top, 'header' section of a profile, and returns the last\n# line of the header, commonly called a 'header line'.  The header\n# section of a profile consists of zero or more 'command' lines that\n# are instructions to jeprof, which jeprof executes when reading the\n# header.  All 'command' lines start with a %.  After the command\n# lines is the 'header line', which is a profile-specific line that\n# indicates what type of profile it is, and perhaps other global\n# information about the profile.  For instance, here's a header line\n# for a heap profile:\n#   heap profile:     53:    38236 [  5525:  1284029] @ heapprofile\n# For historical reasons, the CPU profile does not contain a text-\n# readable header line.  If the profile looks like a CPU profile,\n# this function returns \"\".  If no header line could be found, this\n# function returns undef.\n#\n# The following commands are recognized:\n#   %warn -- emit the rest of this line to stderr, prefixed by 'WARNING:'\n#\n# The input file should be in binmode.\nsub ReadProfileHeader {\n  local *PROFILE = shift;\n  my $firstchar = \"\";\n  my $line = \"\";\n  read(PROFILE, $firstchar, 1);\n  seek(PROFILE, -1, 1);                    # unread the firstchar\n  if ($firstchar !~ /[[:print:]]/) {       # is not a text character\n    return \"\";\n  }\n  while (defined($line = <PROFILE>)) {\n    $line =~ s/\\r//g;   # turn windows-looking lines into unix-looking lines\n    if ($line =~ /^%warn\\s+(.*)/) {        # 'warn' command\n      # Note this matches both '%warn blah\\n' and '%warn\\n'.\n      print STDERR \"WARNING: $1\\n\";        # print the rest of the line\n    } elsif ($line =~ /^%/) {\n      print STDERR \"Ignoring unknown command from profile header: $line\";\n    } else {\n      # End of commands, must be the header line.\n      return $line;\n    }\n  }\n  return undef;     # got to EOF without seeing a header line\n}\n\nsub IsSymbolizedProfileFile {\n  my $file_name = shift;\n  if (!(-e $file_name) || !(-r $file_name)) {\n    return 0;\n  }\n  # Check if the file contains a symbol-section marker.\n  open(TFILE, \"<$file_name\");\n  binmode TFILE;\n  my $firstline = ReadProfileHeader(*TFILE);\n  close(TFILE);\n  if (!$firstline) {\n    return 0;\n  }\n  $SYMBOL_PAGE =~ m,[^/]+$,;    # matches everything after the last slash\n  my $symbol_marker = $&;\n  return $firstline =~ /^--- *$symbol_marker/;\n}\n\n# Parse profile generated by common/profiler.cc and return a reference\n# to a map:\n#      $result->{version}     Version number of profile file\n#      $result->{period}      Sampling period (in microseconds)\n#      $result->{profile}     Profile object\n#      $result->{threads}     Map of thread IDs to profile objects\n#      $result->{map}         Memory map info from profile\n#      $result->{pcs}         Hash of all PC values seen, key is hex address\nsub ReadProfile {\n  my $prog = shift;\n  my $fname = shift;\n  my $result;            # return value\n\n  $CONTENTION_PAGE =~ m,[^/]+$,;    # matches everything after the last slash\n  my $contention_marker = $&;\n  $GROWTH_PAGE  =~ m,[^/]+$,;    # matches everything after the last slash\n  my $growth_marker = $&;\n  $SYMBOL_PAGE =~ m,[^/]+$,;    # matches everything after the last slash\n  my $symbol_marker = $&;\n  $PROFILE_PAGE =~ m,[^/]+$,;    # matches everything after the last slash\n  my $profile_marker = $&;\n\n  # Look at first line to see if it is a heap or a CPU profile.\n  # CPU profile may start with no header at all, and just binary data\n  # (starting with \\0\\0\\0\\0) -- in that case, don't try to read the\n  # whole firstline, since it may be gigabytes(!) of data.\n  open(PROFILE, \"<$fname\") || error(\"$fname: $!\\n\");\n  binmode PROFILE;      # New perls do UTF-8 processing\n  my $header = ReadProfileHeader(*PROFILE);\n  if (!defined($header)) {   # means \"at EOF\"\n    error(\"Profile is empty.\\n\");\n  }\n\n  my $symbols;\n  if ($header =~ m/^--- *$symbol_marker/o) {\n    # Verify that the user asked for a symbolized profile\n    if (!$main::use_symbolized_profile) {\n      # we have both a binary and symbolized profiles, abort\n      error(\"FATAL ERROR: Symbolized profile\\n   $fname\\ncannot be used with \" .\n            \"a binary arg. Try again without passing\\n   $prog\\n\");\n    }\n    # Read the symbol section of the symbolized profile file.\n    $symbols = ReadSymbols(*PROFILE{IO});\n    # Read the next line to get the header for the remaining profile.\n    $header = ReadProfileHeader(*PROFILE) || \"\";\n  }\n\n  $main::profile_type = '';\n  if ($header =~ m/^heap profile:.*$growth_marker/o) {\n    $main::profile_type = 'growth';\n    $result =  ReadHeapProfile($prog, *PROFILE, $header);\n  } elsif ($header =~ m/^heap profile:/) {\n    $main::profile_type = 'heap';\n    $result =  ReadHeapProfile($prog, *PROFILE, $header);\n  } elsif ($header =~ m/^heap/) {\n    $main::profile_type = 'heap';\n    $result = ReadThreadedHeapProfile($prog, $fname, $header);\n  } elsif ($header =~ m/^--- *$contention_marker/o) {\n    $main::profile_type = 'contention';\n    $result = ReadSynchProfile($prog, *PROFILE);\n  } elsif ($header =~ m/^--- *Stacks:/) {\n    print STDERR\n      \"Old format contention profile: mistakenly reports \" .\n      \"condition variable signals as lock contentions.\\n\";\n    $main::profile_type = 'contention';\n    $result = ReadSynchProfile($prog, *PROFILE);\n  } elsif ($header =~ m/^--- *$profile_marker/) {\n    # the binary cpu profile data starts immediately after this line\n    $main::profile_type = 'cpu';\n    $result = ReadCPUProfile($prog, $fname, *PROFILE);\n  } else {\n    if (defined($symbols)) {\n      # a symbolized profile contains a format we don't recognize, bail out\n      error(\"$fname: Cannot recognize profile section after symbols.\\n\");\n    }\n    # no ascii header present -- must be a CPU profile\n    $main::profile_type = 'cpu';\n    $result = ReadCPUProfile($prog, $fname, *PROFILE);\n  }\n\n  close(PROFILE);\n\n  # if we got symbols along with the profile, return those as well\n  if (defined($symbols)) {\n    $result->{symbols} = $symbols;\n  }\n\n  return $result;\n}\n\n# Subtract one from caller pc so we map back to call instr.\n# However, don't do this if we're reading a symbolized profile\n# file, in which case the subtract-one was done when the file\n# was written.\n#\n# We apply the same logic to all readers, though ReadCPUProfile uses an\n# independent implementation.\nsub FixCallerAddresses {\n  my $stack = shift;\n  if ($main::use_symbolized_profile) {\n    return $stack;\n  } else {\n    $stack =~ /(\\s)/;\n    my $delimiter = $1;\n    my @addrs = split(' ', $stack);\n    my @fixedaddrs;\n    $#fixedaddrs = $#addrs;\n    if ($#addrs >= 0) {\n      $fixedaddrs[0] = $addrs[0];\n    }\n    for (my $i = 1; $i <= $#addrs; $i++) {\n      $fixedaddrs[$i] = AddressSub($addrs[$i], \"0x1\");\n    }\n    return join $delimiter, @fixedaddrs;\n  }\n}\n\n# CPU profile reader\nsub ReadCPUProfile {\n  my $prog = shift;\n  my $fname = shift;       # just used for logging\n  local *PROFILE = shift;\n  my $version;\n  my $period;\n  my $i;\n  my $profile = {};\n  my $pcs = {};\n\n  # Parse string into array of slots.\n  my $slots = CpuProfileStream->new(*PROFILE, $fname);\n\n  # Read header.  The current header version is a 5-element structure\n  # containing:\n  #   0: header count (always 0)\n  #   1: header \"words\" (after this one: 3)\n  #   2: format version (0)\n  #   3: sampling period (usec)\n  #   4: unused padding (always 0)\n  if ($slots->get(0) != 0 ) {\n    error(\"$fname: not a profile file, or old format profile file\\n\");\n  }\n  $i = 2 + $slots->get(1);\n  $version = $slots->get(2);\n  $period = $slots->get(3);\n  # Do some sanity checking on these header values.\n  if ($version > (2**32) || $period > (2**32) || $i > (2**32) || $i < 5) {\n    error(\"$fname: not a profile file, or corrupted profile file\\n\");\n  }\n\n  # Parse profile\n  while ($slots->get($i) != -1) {\n    my $n = $slots->get($i++);\n    my $d = $slots->get($i++);\n    if ($d > (2**16)) {  # TODO(csilvers): what's a reasonable max-stack-depth?\n      my $addr = sprintf(\"0%o\", $i * ($address_length == 8 ? 4 : 8));\n      print STDERR \"At index $i (address $addr):\\n\";\n      error(\"$fname: stack trace depth >= 2**32\\n\");\n    }\n    if ($slots->get($i) == 0) {\n      # End of profile data marker\n      $i += $d;\n      last;\n    }\n\n    # Make key out of the stack entries\n    my @k = ();\n    for (my $j = 0; $j < $d; $j++) {\n      my $pc = $slots->get($i+$j);\n      # Subtract one from caller pc so we map back to call instr.\n      # However, don't do this if we're reading a symbolized profile\n      # file, in which case the subtract-one was done when the file\n      # was written.\n      if ($j > 0 && !$main::use_symbolized_profile) {\n        $pc--;\n      }\n      $pc = sprintf(\"%0*x\", $address_length, $pc);\n      $pcs->{$pc} = 1;\n      push @k, $pc;\n    }\n\n    AddEntry($profile, (join \"\\n\", @k), $n);\n    $i += $d;\n  }\n\n  # Parse map\n  my $map = '';\n  seek(PROFILE, $i * 4, 0);\n  read(PROFILE, $map, (stat PROFILE)[7]);\n\n  my $r = {};\n  $r->{version} = $version;\n  $r->{period} = $period;\n  $r->{profile} = $profile;\n  $r->{libs} = ParseLibraries($prog, $map, $pcs);\n  $r->{pcs} = $pcs;\n\n  return $r;\n}\n\nsub HeapProfileIndex {\n  my $index = 1;\n  if ($main::opt_inuse_space) {\n    $index = 1;\n  } elsif ($main::opt_inuse_objects) {\n    $index = 0;\n  } elsif ($main::opt_alloc_space) {\n    $index = 3;\n  } elsif ($main::opt_alloc_objects) {\n    $index = 2;\n  }\n  return $index;\n}\n\nsub ReadMappedLibraries {\n  my $fh = shift;\n  my $map = \"\";\n  # Read the /proc/self/maps data\n  while (<$fh>) {\n    s/\\r//g;         # turn windows-looking lines into unix-looking lines\n    $map .= $_;\n  }\n  return $map;\n}\n\nsub ReadMemoryMap {\n  my $fh = shift;\n  my $map = \"\";\n  # Read /proc/self/maps data as formatted by DumpAddressMap()\n  my $buildvar = \"\";\n  while (<PROFILE>) {\n    s/\\r//g;         # turn windows-looking lines into unix-looking lines\n    # Parse \"build=<dir>\" specification if supplied\n    if (m/^\\s*build=(.*)\\n/) {\n      $buildvar = $1;\n    }\n\n    # Expand \"$build\" variable if available\n    $_ =~ s/\\$build\\b/$buildvar/g;\n\n    $map .= $_;\n  }\n  return $map;\n}\n\nsub AdjustSamples {\n  my ($sample_adjustment, $sampling_algorithm, $n1, $s1, $n2, $s2) = @_;\n  if ($sample_adjustment) {\n    if ($sampling_algorithm == 2) {\n      # Remote-heap version 2\n      # The sampling frequency is the rate of a Poisson process.\n      # This means that the probability of sampling an allocation of\n      # size X with sampling rate Y is 1 - exp(-X/Y)\n      if ($n1 != 0) {\n        my $ratio = (($s1*1.0)/$n1)/($sample_adjustment);\n        my $scale_factor = 1/(1 - exp(-$ratio));\n        $n1 *= $scale_factor;\n        $s1 *= $scale_factor;\n      }\n      if ($n2 != 0) {\n        my $ratio = (($s2*1.0)/$n2)/($sample_adjustment);\n        my $scale_factor = 1/(1 - exp(-$ratio));\n        $n2 *= $scale_factor;\n        $s2 *= $scale_factor;\n      }\n    } else {\n      # Remote-heap version 1\n      my $ratio;\n      $ratio = (($s1*1.0)/$n1)/($sample_adjustment);\n      if ($ratio < 1) {\n        $n1 /= $ratio;\n        $s1 /= $ratio;\n      }\n      $ratio = (($s2*1.0)/$n2)/($sample_adjustment);\n      if ($ratio < 1) {\n        $n2 /= $ratio;\n        $s2 /= $ratio;\n      }\n    }\n  }\n  return ($n1, $s1, $n2, $s2);\n}\n\nsub ReadHeapProfile {\n  my $prog = shift;\n  local *PROFILE = shift;\n  my $header = shift;\n\n  my $index = HeapProfileIndex();\n\n  # Find the type of this profile.  The header line looks like:\n  #    heap profile:   1246:  8800744 [  1246:  8800744] @ <heap-url>/266053\n  # There are two pairs <count: size>, the first inuse objects/space, and the\n  # second allocated objects/space.  This is followed optionally by a profile\n  # type, and if that is present, optionally by a sampling frequency.\n  # For remote heap profiles (v1):\n  # The interpretation of the sampling frequency is that the profiler, for\n  # each sample, calculates a uniformly distributed random integer less than\n  # the given value, and records the next sample after that many bytes have\n  # been allocated.  Therefore, the expected sample interval is half of the\n  # given frequency.  By default, if not specified, the expected sample\n  # interval is 128KB.  Only remote-heap-page profiles are adjusted for\n  # sample size.\n  # For remote heap profiles (v2):\n  # The sampling frequency is the rate of a Poisson process. This means that\n  # the probability of sampling an allocation of size X with sampling rate Y\n  # is 1 - exp(-X/Y)\n  # For version 2, a typical header line might look like this:\n  # heap profile:   1922: 127792360 [  1922: 127792360] @ <heap-url>_v2/524288\n  # the trailing number (524288) is the sampling rate. (Version 1 showed\n  # double the 'rate' here)\n  my $sampling_algorithm = 0;\n  my $sample_adjustment = 0;\n  chomp($header);\n  my $type = \"unknown\";\n  if ($header =~ m\"^heap profile:\\s*(\\d+):\\s+(\\d+)\\s+\\[\\s*(\\d+):\\s+(\\d+)\\](\\s*@\\s*([^/]*)(/(\\d+))?)?\") {\n    if (defined($6) && ($6 ne '')) {\n      $type = $6;\n      my $sample_period = $8;\n      # $type is \"heapprofile\" for profiles generated by the\n      # heap-profiler, and either \"heap\" or \"heap_v2\" for profiles\n      # generated by sampling directly within tcmalloc.  It can also\n      # be \"growth\" for heap-growth profiles.  The first is typically\n      # found for profiles generated locally, and the others for\n      # remote profiles.\n      if (($type eq \"heapprofile\") || ($type !~ /heap/) ) {\n        # No need to adjust for the sampling rate with heap-profiler-derived data\n        $sampling_algorithm = 0;\n      } elsif ($type =~ /_v2/) {\n        $sampling_algorithm = 2;     # version 2 sampling\n        if (defined($sample_period) && ($sample_period ne '')) {\n          $sample_adjustment = int($sample_period);\n        }\n      } else {\n        $sampling_algorithm = 1;     # version 1 sampling\n        if (defined($sample_period) && ($sample_period ne '')) {\n          $sample_adjustment = int($sample_period)/2;\n        }\n      }\n    } else {\n      # We detect whether or not this is a remote-heap profile by checking\n      # that the total-allocated stats ($n2,$s2) are exactly the\n      # same as the in-use stats ($n1,$s1).  It is remotely conceivable\n      # that a non-remote-heap profile may pass this check, but it is hard\n      # to imagine how that could happen.\n      # In this case it's so old it's guaranteed to be remote-heap version 1.\n      my ($n1, $s1, $n2, $s2) = ($1, $2, $3, $4);\n      if (($n1 == $n2) && ($s1 == $s2)) {\n        # This is likely to be a remote-heap based sample profile\n        $sampling_algorithm = 1;\n      }\n    }\n  }\n\n  if ($sampling_algorithm > 0) {\n    # For remote-heap generated profiles, adjust the counts and sizes to\n    # account for the sample rate (we sample once every 128KB by default).\n    if ($sample_adjustment == 0) {\n      # Turn on profile adjustment.\n      $sample_adjustment = 128*1024;\n      print STDERR \"Adjusting heap profiles for 1-in-128KB sampling rate\\n\";\n    } else {\n      printf STDERR (\"Adjusting heap profiles for 1-in-%d sampling rate\\n\",\n                     $sample_adjustment);\n    }\n    if ($sampling_algorithm > 1) {\n      # We don't bother printing anything for the original version (version 1)\n      printf STDERR \"Heap version $sampling_algorithm\\n\";\n    }\n  }\n\n  my $profile = {};\n  my $pcs = {};\n  my $map = \"\";\n\n  while (<PROFILE>) {\n    s/\\r//g;         # turn windows-looking lines into unix-looking lines\n    if (/^MAPPED_LIBRARIES:/) {\n      $map .= ReadMappedLibraries(*PROFILE);\n      last;\n    }\n\n    if (/^--- Memory map:/) {\n      $map .= ReadMemoryMap(*PROFILE);\n      last;\n    }\n\n    # Read entry of the form:\n    #  <count1>: <bytes1> [<count2>: <bytes2>] @ a1 a2 a3 ... an\n    s/^\\s*//;\n    s/\\s*$//;\n    if (m/^\\s*(\\d+):\\s+(\\d+)\\s+\\[\\s*(\\d+):\\s+(\\d+)\\]\\s+@\\s+(.*)$/) {\n      my $stack = $5;\n      my ($n1, $s1, $n2, $s2) = ($1, $2, $3, $4);\n      my @counts = AdjustSamples($sample_adjustment, $sampling_algorithm,\n                                 $n1, $s1, $n2, $s2);\n      AddEntries($profile, $pcs, FixCallerAddresses($stack), $counts[$index]);\n    }\n  }\n\n  my $r = {};\n  $r->{version} = \"heap\";\n  $r->{period} = 1;\n  $r->{profile} = $profile;\n  $r->{libs} = ParseLibraries($prog, $map, $pcs);\n  $r->{pcs} = $pcs;\n  return $r;\n}\n\nsub ReadThreadedHeapProfile {\n  my ($prog, $fname, $header) = @_;\n\n  my $index = HeapProfileIndex();\n  my $sampling_algorithm = 0;\n  my $sample_adjustment = 0;\n  chomp($header);\n  my $type = \"unknown\";\n  # Assuming a very specific type of header for now.\n  if ($header =~ m\"^heap_v2/(\\d+)\") {\n    $type = \"_v2\";\n    $sampling_algorithm = 2;\n    $sample_adjustment = int($1);\n  }\n  if ($type ne \"_v2\" || !defined($sample_adjustment)) {\n    die \"Threaded heap profiles require v2 sampling with a sample rate\\n\";\n  }\n\n  my $profile = {};\n  my $thread_profiles = {};\n  my $pcs = {};\n  my $map = \"\";\n  my $stack = \"\";\n\n  while (<PROFILE>) {\n    s/\\r//g;\n    if (/^MAPPED_LIBRARIES:/) {\n      $map .= ReadMappedLibraries(*PROFILE);\n      last;\n    }\n\n    if (/^--- Memory map:/) {\n      $map .= ReadMemoryMap(*PROFILE);\n      last;\n    }\n\n    # Read entry of the form:\n    # @ a1 a2 ... an\n    #   t*: <count1>: <bytes1> [<count2>: <bytes2>]\n    #   t1: <count1>: <bytes1> [<count2>: <bytes2>]\n    #     ...\n    #   tn: <count1>: <bytes1> [<count2>: <bytes2>]\n    s/^\\s*//;\n    s/\\s*$//;\n    if (m/^@\\s+(.*)$/) {\n      $stack = $1;\n    } elsif (m/^\\s*(t(\\*|\\d+)):\\s+(\\d+):\\s+(\\d+)\\s+\\[\\s*(\\d+):\\s+(\\d+)\\]$/) {\n      if ($stack eq \"\") {\n        # Still in the header, so this is just a per-thread summary.\n        next;\n      }\n      my $thread = $2;\n      my ($n1, $s1, $n2, $s2) = ($3, $4, $5, $6);\n      my @counts = AdjustSamples($sample_adjustment, $sampling_algorithm,\n                                 $n1, $s1, $n2, $s2);\n      if ($thread eq \"*\") {\n        AddEntries($profile, $pcs, FixCallerAddresses($stack), $counts[$index]);\n      } else {\n        if (!exists($thread_profiles->{$thread})) {\n          $thread_profiles->{$thread} = {};\n        }\n        AddEntries($thread_profiles->{$thread}, $pcs,\n                   FixCallerAddresses($stack), $counts[$index]);\n      }\n    }\n  }\n\n  my $r = {};\n  $r->{version} = \"heap\";\n  $r->{period} = 1;\n  $r->{profile} = $profile;\n  $r->{threads} = $thread_profiles;\n  $r->{libs} = ParseLibraries($prog, $map, $pcs);\n  $r->{pcs} = $pcs;\n  return $r;\n}\n\nsub ReadSynchProfile {\n  my $prog = shift;\n  local *PROFILE = shift;\n  my $header = shift;\n\n  my $map = '';\n  my $profile = {};\n  my $pcs = {};\n  my $sampling_period = 1;\n  my $cyclespernanosec = 2.8;   # Default assumption for old binaries\n  my $seen_clockrate = 0;\n  my $line;\n\n  my $index = 0;\n  if ($main::opt_total_delay) {\n    $index = 0;\n  } elsif ($main::opt_contentions) {\n    $index = 1;\n  } elsif ($main::opt_mean_delay) {\n    $index = 2;\n  }\n\n  while ( $line = <PROFILE> ) {\n    $line =~ s/\\r//g;      # turn windows-looking lines into unix-looking lines\n    if ( $line =~ /^\\s*(\\d+)\\s+(\\d+) \\@\\s*(.*?)\\s*$/ ) {\n      my ($cycles, $count, $stack) = ($1, $2, $3);\n\n      # Convert cycles to nanoseconds\n      $cycles /= $cyclespernanosec;\n\n      # Adjust for sampling done by application\n      $cycles *= $sampling_period;\n      $count *= $sampling_period;\n\n      my @values = ($cycles, $count, $cycles / $count);\n      AddEntries($profile, $pcs, FixCallerAddresses($stack), $values[$index]);\n\n    } elsif ( $line =~ /^(slow release).*thread \\d+  \\@\\s*(.*?)\\s*$/ ||\n              $line =~ /^\\s*(\\d+) \\@\\s*(.*?)\\s*$/ ) {\n      my ($cycles, $stack) = ($1, $2);\n      if ($cycles !~ /^\\d+$/) {\n        next;\n      }\n\n      # Convert cycles to nanoseconds\n      $cycles /= $cyclespernanosec;\n\n      # Adjust for sampling done by application\n      $cycles *= $sampling_period;\n\n      AddEntries($profile, $pcs, FixCallerAddresses($stack), $cycles);\n\n    } elsif ( $line =~ m/^([a-z][^=]*)=(.*)$/ ) {\n      my ($variable, $value) = ($1,$2);\n      for ($variable, $value) {\n        s/^\\s+//;\n        s/\\s+$//;\n      }\n      if ($variable eq \"cycles/second\") {\n        $cyclespernanosec = $value / 1e9;\n        $seen_clockrate = 1;\n      } elsif ($variable eq \"sampling period\") {\n        $sampling_period = $value;\n      } elsif ($variable eq \"ms since reset\") {\n        # Currently nothing is done with this value in jeprof\n        # So we just silently ignore it for now\n      } elsif ($variable eq \"discarded samples\") {\n        # Currently nothing is done with this value in jeprof\n        # So we just silently ignore it for now\n      } else {\n        printf STDERR (\"Ignoring unnknown variable in /contention output: \" .\n                       \"'%s' = '%s'\\n\",$variable,$value);\n      }\n    } else {\n      # Memory map entry\n      $map .= $line;\n    }\n  }\n\n  if (!$seen_clockrate) {\n    printf STDERR (\"No cycles/second entry in profile; Guessing %.1f GHz\\n\",\n                   $cyclespernanosec);\n  }\n\n  my $r = {};\n  $r->{version} = 0;\n  $r->{period} = $sampling_period;\n  $r->{profile} = $profile;\n  $r->{libs} = ParseLibraries($prog, $map, $pcs);\n  $r->{pcs} = $pcs;\n  return $r;\n}\n\n# Given a hex value in the form \"0x1abcd\" or \"1abcd\", return either\n# \"0001abcd\" or \"000000000001abcd\", depending on the current (global)\n# address length.\nsub HexExtend {\n  my $addr = shift;\n\n  $addr =~ s/^(0x)?0*//;\n  my $zeros_needed = $address_length - length($addr);\n  if ($zeros_needed < 0) {\n    printf STDERR \"Warning: address $addr is longer than address length $address_length\\n\";\n    return $addr;\n  }\n  return (\"0\" x $zeros_needed) . $addr;\n}\n\n##### Symbol extraction #####\n\n# Aggressively search the lib_prefix values for the given library\n# If all else fails, just return the name of the library unmodified.\n# If the lib_prefix is \"/my/path,/other/path\" and $file is \"/lib/dir/mylib.so\"\n# it will search the following locations in this order, until it finds a file:\n#   /my/path/lib/dir/mylib.so\n#   /other/path/lib/dir/mylib.so\n#   /my/path/dir/mylib.so\n#   /other/path/dir/mylib.so\n#   /my/path/mylib.so\n#   /other/path/mylib.so\n#   /lib/dir/mylib.so              (returned as last resort)\nsub FindLibrary {\n  my $file = shift;\n  my $suffix = $file;\n\n  # Search for the library as described above\n  do {\n    foreach my $prefix (@prefix_list) {\n      my $fullpath = $prefix . $suffix;\n      if (-e $fullpath) {\n        return $fullpath;\n      }\n    }\n  } while ($suffix =~ s|^/[^/]+/|/|);\n  return $file;\n}\n\n# Return path to library with debugging symbols.\n# For libc libraries, the copy in /usr/lib/debug contains debugging symbols\nsub DebuggingLibrary {\n  my $file = shift;\n  if ($file =~ m|^/|) {\n      if (-f \"/usr/lib/debug$file\") {\n        return \"/usr/lib/debug$file\";\n      } elsif (-f \"/usr/lib/debug$file.debug\") {\n        return \"/usr/lib/debug$file.debug\";\n      }\n  }\n  return undef;\n}\n\n# Parse text section header of a library using objdump\nsub ParseTextSectionHeaderFromObjdump {\n  my $lib = shift;\n\n  my $size = undef;\n  my $vma;\n  my $file_offset;\n  # Get objdump output from the library file to figure out how to\n  # map between mapped addresses and addresses in the library.\n  my $cmd = ShellEscape($obj_tool_map{\"objdump\"}, \"-h\", $lib);\n  open(OBJDUMP, \"$cmd |\") || error(\"$cmd: $!\\n\");\n  while (<OBJDUMP>) {\n    s/\\r//g;         # turn windows-looking lines into unix-looking lines\n    # Idx Name          Size      VMA       LMA       File off  Algn\n    #  10 .text         00104b2c  420156f0  420156f0  000156f0  2**4\n    # For 64-bit objects, VMA and LMA will be 16 hex digits, size and file\n    # offset may still be 8.  But AddressSub below will still handle that.\n    my @x = split;\n    if (($#x >= 6) && ($x[1] eq '.text')) {\n      $size = $x[2];\n      $vma = $x[3];\n      $file_offset = $x[5];\n      last;\n    }\n  }\n  close(OBJDUMP);\n\n  if (!defined($size)) {\n    return undef;\n  }\n\n  my $r = {};\n  $r->{size} = $size;\n  $r->{vma} = $vma;\n  $r->{file_offset} = $file_offset;\n\n  return $r;\n}\n\n# Parse text section header of a library using otool (on OS X)\nsub ParseTextSectionHeaderFromOtool {\n  my $lib = shift;\n\n  my $size = undef;\n  my $vma = undef;\n  my $file_offset = undef;\n  # Get otool output from the library file to figure out how to\n  # map between mapped addresses and addresses in the library.\n  my $command = ShellEscape($obj_tool_map{\"otool\"}, \"-l\", $lib);\n  open(OTOOL, \"$command |\") || error(\"$command: $!\\n\");\n  my $cmd = \"\";\n  my $sectname = \"\";\n  my $segname = \"\";\n  foreach my $line (<OTOOL>) {\n    $line =~ s/\\r//g;      # turn windows-looking lines into unix-looking lines\n    # Load command <#>\n    #       cmd LC_SEGMENT\n    # [...]\n    # Section\n    #   sectname __text\n    #    segname __TEXT\n    #       addr 0x000009f8\n    #       size 0x00018b9e\n    #     offset 2552\n    #      align 2^2 (4)\n    # We will need to strip off the leading 0x from the hex addresses,\n    # and convert the offset into hex.\n    if ($line =~ /Load command/) {\n      $cmd = \"\";\n      $sectname = \"\";\n      $segname = \"\";\n    } elsif ($line =~ /Section/) {\n      $sectname = \"\";\n      $segname = \"\";\n    } elsif ($line =~ /cmd (\\w+)/) {\n      $cmd = $1;\n    } elsif ($line =~ /sectname (\\w+)/) {\n      $sectname = $1;\n    } elsif ($line =~ /segname (\\w+)/) {\n      $segname = $1;\n    } elsif (!(($cmd eq \"LC_SEGMENT\" || $cmd eq \"LC_SEGMENT_64\") &&\n               $sectname eq \"__text\" &&\n               $segname eq \"__TEXT\")) {\n      next;\n    } elsif ($line =~ /\\baddr 0x([0-9a-fA-F]+)/) {\n      $vma = $1;\n    } elsif ($line =~ /\\bsize 0x([0-9a-fA-F]+)/) {\n      $size = $1;\n    } elsif ($line =~ /\\boffset ([0-9]+)/) {\n      $file_offset = sprintf(\"%016x\", $1);\n    }\n    if (defined($vma) && defined($size) && defined($file_offset)) {\n      last;\n    }\n  }\n  close(OTOOL);\n\n  if (!defined($vma) || !defined($size) || !defined($file_offset)) {\n     return undef;\n  }\n\n  my $r = {};\n  $r->{size} = $size;\n  $r->{vma} = $vma;\n  $r->{file_offset} = $file_offset;\n\n  return $r;\n}\n\nsub ParseTextSectionHeader {\n  # obj_tool_map(\"otool\") is only defined if we're in a Mach-O environment\n  if (defined($obj_tool_map{\"otool\"})) {\n    my $r = ParseTextSectionHeaderFromOtool(@_);\n    if (defined($r)){\n      return $r;\n    }\n  }\n  # If otool doesn't work, or we don't have it, fall back to objdump\n  return ParseTextSectionHeaderFromObjdump(@_);\n}\n\n# Split /proc/pid/maps dump into a list of libraries\nsub ParseLibraries {\n  return if $main::use_symbol_page;  # We don't need libraries info.\n  my $prog = shift;\n  my $map = shift;\n  my $pcs = shift;\n\n  my $result = [];\n  my $h = \"[a-f0-9]+\";\n  my $zero_offset = HexExtend(\"0\");\n\n  my $buildvar = \"\";\n  foreach my $l (split(\"\\n\", $map)) {\n    if ($l =~ m/^\\s*build=(.*)$/) {\n      $buildvar = $1;\n    }\n\n    my $start;\n    my $finish;\n    my $offset;\n    my $lib;\n    if ($l =~ /^($h)-($h)\\s+..x.\\s+($h)\\s+\\S+:\\S+\\s+\\d+\\s+(\\S+\\.(so|dll|dylib|bundle)((\\.\\d+)+\\w*(\\.\\d+){0,3})?)$/i) {\n      # Full line from /proc/self/maps.  Example:\n      #   40000000-40015000 r-xp 00000000 03:01 12845071   /lib/ld-2.3.2.so\n      $start = HexExtend($1);\n      $finish = HexExtend($2);\n      $offset = HexExtend($3);\n      $lib = $4;\n      $lib =~ s|\\\\|/|g;     # turn windows-style paths into unix-style paths\n    } elsif ($l =~ /^\\s*($h)-($h):\\s*(\\S+\\.so(\\.\\d+)*)/) {\n      # Cooked line from DumpAddressMap.  Example:\n      #   40000000-40015000: /lib/ld-2.3.2.so\n      $start = HexExtend($1);\n      $finish = HexExtend($2);\n      $offset = $zero_offset;\n      $lib = $3;\n    }\n    # FreeBSD 10.0 virtual memory map /proc/curproc/map as defined in\n    # function procfs_doprocmap (sys/fs/procfs/procfs_map.c)\n    #\n    # Example:\n    # 0x800600000 0x80061a000 26 0 0xfffff800035a0000 r-x 75 33 0x1004 COW NC vnode /libexec/ld-elf.s\n    # o.1 NCH -1\n    elsif ($l =~ /^(0x$h)\\s(0x$h)\\s\\d+\\s\\d+\\s0x$h\\sr-x\\s\\d+\\s\\d+\\s0x\\d+\\s(COW|NCO)\\s(NC|NNC)\\svnode\\s(\\S+\\.so(\\.\\d+)*)/) {\n      $start = HexExtend($1);\n      $finish = HexExtend($2);\n      $offset = $zero_offset;\n      $lib = FindLibrary($5);\n\n    } else {\n      next;\n    }\n\n    # Expand \"$build\" variable if available\n    $lib =~ s/\\$build\\b/$buildvar/g;\n\n    $lib = FindLibrary($lib);\n\n    # Check for pre-relocated libraries, which use pre-relocated symbol tables\n    # and thus require adjusting the offset that we'll use to translate\n    # VM addresses into symbol table addresses.\n    # Only do this if we're not going to fetch the symbol table from a\n    # debugging copy of the library.\n    if (!DebuggingLibrary($lib)) {\n      my $text = ParseTextSectionHeader($lib);\n      if (defined($text)) {\n         my $vma_offset = AddressSub($text->{vma}, $text->{file_offset});\n         $offset = AddressAdd($offset, $vma_offset);\n      }\n    }\n\n    if($main::opt_debug) { printf STDERR \"$start:$finish ($offset) $lib\\n\"; }\n    push(@{$result}, [$lib, $start, $finish, $offset]);\n  }\n\n  # Append special entry for additional library (not relocated)\n  if ($main::opt_lib ne \"\") {\n    my $text = ParseTextSectionHeader($main::opt_lib);\n    if (defined($text)) {\n       my $start = $text->{vma};\n       my $finish = AddressAdd($start, $text->{size});\n\n       push(@{$result}, [$main::opt_lib, $start, $finish, $start]);\n    }\n  }\n\n  # Append special entry for the main program.  This covers\n  # 0..max_pc_value_seen, so that we assume pc values not found in one\n  # of the library ranges will be treated as coming from the main\n  # program binary.\n  my $min_pc = HexExtend(\"0\");\n  my $max_pc = $min_pc;          # find the maximal PC value in any sample\n  foreach my $pc (keys(%{$pcs})) {\n    if (HexExtend($pc) gt $max_pc) { $max_pc = HexExtend($pc); }\n  }\n  push(@{$result}, [$prog, $min_pc, $max_pc, $zero_offset]);\n\n  return $result;\n}\n\n# Add two hex addresses of length $address_length.\n# Run jeprof --test for unit test if this is changed.\nsub AddressAdd {\n  my $addr1 = shift;\n  my $addr2 = shift;\n  my $sum;\n\n  if ($address_length == 8) {\n    # Perl doesn't cope with wraparound arithmetic, so do it explicitly:\n    $sum = (hex($addr1)+hex($addr2)) % (0x10000000 * 16);\n    return sprintf(\"%08x\", $sum);\n\n  } else {\n    # Do the addition in 7-nibble chunks to trivialize carry handling.\n\n    if ($main::opt_debug and $main::opt_test) {\n      print STDERR \"AddressAdd $addr1 + $addr2 = \";\n    }\n\n    my $a1 = substr($addr1,-7);\n    $addr1 = substr($addr1,0,-7);\n    my $a2 = substr($addr2,-7);\n    $addr2 = substr($addr2,0,-7);\n    $sum = hex($a1) + hex($a2);\n    my $c = 0;\n    if ($sum > 0xfffffff) {\n      $c = 1;\n      $sum -= 0x10000000;\n    }\n    my $r = sprintf(\"%07x\", $sum);\n\n    $a1 = substr($addr1,-7);\n    $addr1 = substr($addr1,0,-7);\n    $a2 = substr($addr2,-7);\n    $addr2 = substr($addr2,0,-7);\n    $sum = hex($a1) + hex($a2) + $c;\n    $c = 0;\n    if ($sum > 0xfffffff) {\n      $c = 1;\n      $sum -= 0x10000000;\n    }\n    $r = sprintf(\"%07x\", $sum) . $r;\n\n    $sum = hex($addr1) + hex($addr2) + $c;\n    if ($sum > 0xff) { $sum -= 0x100; }\n    $r = sprintf(\"%02x\", $sum) . $r;\n\n    if ($main::opt_debug and $main::opt_test) { print STDERR \"$r\\n\"; }\n\n    return $r;\n  }\n}\n\n\n# Subtract two hex addresses of length $address_length.\n# Run jeprof --test for unit test if this is changed.\nsub AddressSub {\n  my $addr1 = shift;\n  my $addr2 = shift;\n  my $diff;\n\n  if ($address_length == 8) {\n    # Perl doesn't cope with wraparound arithmetic, so do it explicitly:\n    $diff = (hex($addr1)-hex($addr2)) % (0x10000000 * 16);\n    return sprintf(\"%08x\", $diff);\n\n  } else {\n    # Do the addition in 7-nibble chunks to trivialize borrow handling.\n    # if ($main::opt_debug) { print STDERR \"AddressSub $addr1 - $addr2 = \"; }\n\n    my $a1 = hex(substr($addr1,-7));\n    $addr1 = substr($addr1,0,-7);\n    my $a2 = hex(substr($addr2,-7));\n    $addr2 = substr($addr2,0,-7);\n    my $b = 0;\n    if ($a2 > $a1) {\n      $b = 1;\n      $a1 += 0x10000000;\n    }\n    $diff = $a1 - $a2;\n    my $r = sprintf(\"%07x\", $diff);\n\n    $a1 = hex(substr($addr1,-7));\n    $addr1 = substr($addr1,0,-7);\n    $a2 = hex(substr($addr2,-7)) + $b;\n    $addr2 = substr($addr2,0,-7);\n    $b = 0;\n    if ($a2 > $a1) {\n      $b = 1;\n      $a1 += 0x10000000;\n    }\n    $diff = $a1 - $a2;\n    $r = sprintf(\"%07x\", $diff) . $r;\n\n    $a1 = hex($addr1);\n    $a2 = hex($addr2) + $b;\n    if ($a2 > $a1) { $a1 += 0x100; }\n    $diff = $a1 - $a2;\n    $r = sprintf(\"%02x\", $diff) . $r;\n\n    # if ($main::opt_debug) { print STDERR \"$r\\n\"; }\n\n    return $r;\n  }\n}\n\n# Increment a hex addresses of length $address_length.\n# Run jeprof --test for unit test if this is changed.\nsub AddressInc {\n  my $addr = shift;\n  my $sum;\n\n  if ($address_length == 8) {\n    # Perl doesn't cope with wraparound arithmetic, so do it explicitly:\n    $sum = (hex($addr)+1) % (0x10000000 * 16);\n    return sprintf(\"%08x\", $sum);\n\n  } else {\n    # Do the addition in 7-nibble chunks to trivialize carry handling.\n    # We are always doing this to step through the addresses in a function,\n    # and will almost never overflow the first chunk, so we check for this\n    # case and exit early.\n\n    # if ($main::opt_debug) { print STDERR \"AddressInc $addr1 = \"; }\n\n    my $a1 = substr($addr,-7);\n    $addr = substr($addr,0,-7);\n    $sum = hex($a1) + 1;\n    my $r = sprintf(\"%07x\", $sum);\n    if ($sum <= 0xfffffff) {\n      $r = $addr . $r;\n      # if ($main::opt_debug) { print STDERR \"$r\\n\"; }\n      return HexExtend($r);\n    } else {\n      $r = \"0000000\";\n    }\n\n    $a1 = substr($addr,-7);\n    $addr = substr($addr,0,-7);\n    $sum = hex($a1) + 1;\n    $r = sprintf(\"%07x\", $sum) . $r;\n    if ($sum <= 0xfffffff) {\n      $r = $addr . $r;\n      # if ($main::opt_debug) { print STDERR \"$r\\n\"; }\n      return HexExtend($r);\n    } else {\n      $r = \"00000000000000\";\n    }\n\n    $sum = hex($addr) + 1;\n    if ($sum > 0xff) { $sum -= 0x100; }\n    $r = sprintf(\"%02x\", $sum) . $r;\n\n    # if ($main::opt_debug) { print STDERR \"$r\\n\"; }\n    return $r;\n  }\n}\n\n# Extract symbols for all PC values found in profile\nsub ExtractSymbols {\n  my $libs = shift;\n  my $pcset = shift;\n\n  my $symbols = {};\n\n  # Map each PC value to the containing library.  To make this faster,\n  # we sort libraries by their starting pc value (highest first), and\n  # advance through the libraries as we advance the pc.  Sometimes the\n  # addresses of libraries may overlap with the addresses of the main\n  # binary, so to make sure the libraries 'win', we iterate over the\n  # libraries in reverse order (which assumes the binary doesn't start\n  # in the middle of a library, which seems a fair assumption).\n  my @pcs = (sort { $a cmp $b } keys(%{$pcset}));  # pcset is 0-extended strings\n  foreach my $lib (sort {$b->[1] cmp $a->[1]} @{$libs}) {\n    my $libname = $lib->[0];\n    my $start = $lib->[1];\n    my $finish = $lib->[2];\n    my $offset = $lib->[3];\n\n    # Use debug library if it exists\n    my $debug_libname = DebuggingLibrary($libname);\n    if ($debug_libname) {\n        $libname = $debug_libname;\n    }\n\n    # Get list of pcs that belong in this library.\n    my $contained = [];\n    my ($start_pc_index, $finish_pc_index);\n    # Find smallest finish_pc_index such that $finish < $pc[$finish_pc_index].\n    for ($finish_pc_index = $#pcs + 1; $finish_pc_index > 0;\n         $finish_pc_index--) {\n      last if $pcs[$finish_pc_index - 1] le $finish;\n    }\n    # Find smallest start_pc_index such that $start <= $pc[$start_pc_index].\n    for ($start_pc_index = $finish_pc_index; $start_pc_index > 0;\n         $start_pc_index--) {\n      last if $pcs[$start_pc_index - 1] lt $start;\n    }\n    # This keeps PC values higher than $pc[$finish_pc_index] in @pcs,\n    # in case there are overlaps in libraries and the main binary.\n    @{$contained} = splice(@pcs, $start_pc_index,\n                           $finish_pc_index - $start_pc_index);\n    # Map to symbols\n    MapToSymbols($libname, AddressSub($start, $offset), $contained, $symbols);\n  }\n\n  return $symbols;\n}\n\n# Map list of PC values to symbols for a given image\nsub MapToSymbols {\n  my $image = shift;\n  my $offset = shift;\n  my $pclist = shift;\n  my $symbols = shift;\n\n  my $debug = 0;\n\n  # Ignore empty binaries\n  if ($#{$pclist} < 0) { return; }\n\n  # Figure out the addr2line command to use\n  my $addr2line = $obj_tool_map{\"addr2line\"};\n  my $cmd = ShellEscape($addr2line, \"-f\", \"-C\", \"-e\", $image);\n  if (exists $obj_tool_map{\"addr2line_pdb\"}) {\n    $addr2line = $obj_tool_map{\"addr2line_pdb\"};\n    $cmd = ShellEscape($addr2line, \"--demangle\", \"-f\", \"-C\", \"-e\", $image);\n  }\n\n  # If \"addr2line\" isn't installed on the system at all, just use\n  # nm to get what info we can (function names, but not line numbers).\n  if (system(ShellEscape($addr2line, \"--help\") . \" >$dev_null 2>&1\") != 0) {\n    MapSymbolsWithNM($image, $offset, $pclist, $symbols);\n    return;\n  }\n\n  # \"addr2line -i\" can produce a variable number of lines per input\n  # address, with no separator that allows us to tell when data for\n  # the next address starts.  So we find the address for a special\n  # symbol (_fini) and interleave this address between all real\n  # addresses passed to addr2line.  The name of this special symbol\n  # can then be used as a separator.\n  $sep_address = undef;  # May be filled in by MapSymbolsWithNM()\n  my $nm_symbols = {};\n  MapSymbolsWithNM($image, $offset, $pclist, $nm_symbols);\n  if (defined($sep_address)) {\n    # Only add \" -i\" to addr2line if the binary supports it.\n    # addr2line --help returns 0, but not if it sees an unknown flag first.\n    if (system(\"$cmd -i --help >$dev_null 2>&1\") == 0) {\n      $cmd .= \" -i\";\n    } else {\n      $sep_address = undef;   # no need for sep_address if we don't support -i\n    }\n  }\n\n  # Make file with all PC values with intervening 'sep_address' so\n  # that we can reliably detect the end of inlined function list\n  open(ADDRESSES, \">$main::tmpfile_sym\") || error(\"$main::tmpfile_sym: $!\\n\");\n  if ($debug) { print(\"---- $image ---\\n\"); }\n  for (my $i = 0; $i <= $#{$pclist}; $i++) {\n    # addr2line always reads hex addresses, and does not need '0x' prefix.\n    if ($debug) { printf STDERR (\"%s\\n\", $pclist->[$i]); }\n    printf ADDRESSES (\"%s\\n\", AddressSub($pclist->[$i], $offset));\n    if (defined($sep_address)) {\n      printf ADDRESSES (\"%s\\n\", $sep_address);\n    }\n  }\n  close(ADDRESSES);\n  if ($debug) {\n    print(\"----\\n\");\n    system(\"cat\", $main::tmpfile_sym);\n    print(\"----\\n\");\n    system(\"$cmd < \" . ShellEscape($main::tmpfile_sym));\n    print(\"----\\n\");\n  }\n\n  open(SYMBOLS, \"$cmd <\" . ShellEscape($main::tmpfile_sym) . \" |\")\n      || error(\"$cmd: $!\\n\");\n  my $count = 0;   # Index in pclist\n  while (<SYMBOLS>) {\n    # Read fullfunction and filelineinfo from next pair of lines\n    s/\\r?\\n$//g;\n    my $fullfunction = $_;\n    $_ = <SYMBOLS>;\n    s/\\r?\\n$//g;\n    my $filelinenum = $_;\n\n    if (defined($sep_address) && $fullfunction eq $sep_symbol) {\n      # Terminating marker for data for this address\n      $count++;\n      next;\n    }\n\n    $filelinenum =~ s|\\\\|/|g; # turn windows-style paths into unix-style paths\n\n    my $pcstr = $pclist->[$count];\n    my $function = ShortFunctionName($fullfunction);\n    my $nms = $nm_symbols->{$pcstr};\n    if (defined($nms)) {\n      if ($fullfunction eq '??') {\n        # nm found a symbol for us.\n        $function = $nms->[0];\n        $fullfunction = $nms->[2];\n      } else {\n\t# MapSymbolsWithNM tags each routine with its starting address,\n\t# useful in case the image has multiple occurrences of this\n\t# routine.  (It uses a syntax that resembles template paramters,\n\t# that are automatically stripped out by ShortFunctionName().)\n\t# addr2line does not provide the same information.  So we check\n\t# if nm disambiguated our symbol, and if so take the annotated\n\t# (nm) version of the routine-name.  TODO(csilvers): this won't\n\t# catch overloaded, inlined symbols, which nm doesn't see.\n\t# Better would be to do a check similar to nm's, in this fn.\n\tif ($nms->[2] =~ m/^\\Q$function\\E/) {  # sanity check it's the right fn\n\t  $function = $nms->[0];\n\t  $fullfunction = $nms->[2];\n\t}\n      }\n    }\n\n    # Prepend to accumulated symbols for pcstr\n    # (so that caller comes before callee)\n    my $sym = $symbols->{$pcstr};\n    if (!defined($sym)) {\n      $sym = [];\n      $symbols->{$pcstr} = $sym;\n    }\n    unshift(@{$sym}, $function, $filelinenum, $fullfunction);\n    if ($debug) { printf STDERR (\"%s => [%s]\\n\", $pcstr, join(\" \", @{$sym})); }\n    if (!defined($sep_address)) {\n      # Inlining is off, so this entry ends immediately\n      $count++;\n    }\n  }\n  close(SYMBOLS);\n}\n\n# Use nm to map the list of referenced PCs to symbols.  Return true iff we\n# are able to read procedure information via nm.\nsub MapSymbolsWithNM {\n  my $image = shift;\n  my $offset = shift;\n  my $pclist = shift;\n  my $symbols = shift;\n\n  # Get nm output sorted by increasing address\n  my $symbol_table = GetProcedureBoundaries($image, \".\");\n  if (!%{$symbol_table}) {\n    return 0;\n  }\n  # Start addresses are already the right length (8 or 16 hex digits).\n  my @names = sort { $symbol_table->{$a}->[0] cmp $symbol_table->{$b}->[0] }\n    keys(%{$symbol_table});\n\n  if ($#names < 0) {\n    # No symbols: just use addresses\n    foreach my $pc (@{$pclist}) {\n      my $pcstr = \"0x\" . $pc;\n      $symbols->{$pc} = [$pcstr, \"?\", $pcstr];\n    }\n    return 0;\n  }\n\n  # Sort addresses so we can do a join against nm output\n  my $index = 0;\n  my $fullname = $names[0];\n  my $name = ShortFunctionName($fullname);\n  foreach my $pc (sort { $a cmp $b } @{$pclist}) {\n    # Adjust for mapped offset\n    my $mpc = AddressSub($pc, $offset);\n    while (($index < $#names) && ($mpc ge $symbol_table->{$fullname}->[1])){\n      $index++;\n      $fullname = $names[$index];\n      $name = ShortFunctionName($fullname);\n    }\n    if ($mpc lt $symbol_table->{$fullname}->[1]) {\n      $symbols->{$pc} = [$name, \"?\", $fullname];\n    } else {\n      my $pcstr = \"0x\" . $pc;\n      $symbols->{$pc} = [$pcstr, \"?\", $pcstr];\n    }\n  }\n  return 1;\n}\n\nsub ShortFunctionName {\n  my $function = shift;\n  while ($function =~ s/\\([^()]*\\)(\\s*const)?//g) { }   # Argument types\n  while ($function =~ s/<[^<>]*>//g)  { }    # Remove template arguments\n  $function =~ s/^.*\\s+(\\w+::)/$1/;          # Remove leading type\n  return $function;\n}\n\n# Trim overly long symbols found in disassembler output\nsub CleanDisassembly {\n  my $d = shift;\n  while ($d =~ s/\\([^()%]*\\)(\\s*const)?//g) { } # Argument types, not (%rax)\n  while ($d =~ s/(\\w+)<[^<>]*>/$1/g)  { }       # Remove template arguments\n  return $d;\n}\n\n# Clean file name for display\nsub CleanFileName {\n  my ($f) = @_;\n  $f =~ s|^/proc/self/cwd/||;\n  $f =~ s|^\\./||;\n  return $f;\n}\n\n# Make address relative to section and clean up for display\nsub UnparseAddress {\n  my ($offset, $address) = @_;\n  $address = AddressSub($address, $offset);\n  $address =~ s/^0x//;\n  $address =~ s/^0*//;\n  return $address;\n}\n\n##### Miscellaneous #####\n\n# Find the right versions of the above object tools to use.  The\n# argument is the program file being analyzed, and should be an ELF\n# 32-bit or ELF 64-bit executable file.  The location of the tools\n# is determined by considering the following options in this order:\n#   1) --tools option, if set\n#   2) JEPROF_TOOLS environment variable, if set\n#   3) the environment\nsub ConfigureObjTools {\n  my $prog_file = shift;\n\n  # Check for the existence of $prog_file because /usr/bin/file does not\n  # predictably return error status in prod.\n  (-e $prog_file)  || error(\"$prog_file does not exist.\\n\");\n\n  my $file_type = undef;\n  if (-e \"/usr/bin/file\") {\n    # Follow symlinks (at least for systems where \"file\" supports that).\n    my $escaped_prog_file = ShellEscape($prog_file);\n    $file_type = `/usr/bin/file -L $escaped_prog_file 2>$dev_null ||\n                  /usr/bin/file $escaped_prog_file`;\n  } elsif ($^O == \"MSWin32\") {\n    $file_type = \"MS Windows\";\n  } else {\n    print STDERR \"WARNING: Can't determine the file type of $prog_file\";\n  }\n\n  if ($file_type =~ /64-bit/) {\n    # Change $address_length to 16 if the program file is ELF 64-bit.\n    # We can't detect this from many (most?) heap or lock contention\n    # profiles, since the actual addresses referenced are generally in low\n    # memory even for 64-bit programs.\n    $address_length = 16;\n  }\n\n  if ($file_type =~ /MS Windows/) {\n    # For windows, we provide a version of nm and addr2line as part of\n    # the opensource release, which is capable of parsing\n    # Windows-style PDB executables.  It should live in the path, or\n    # in the same directory as jeprof.\n    $obj_tool_map{\"nm_pdb\"} = \"nm-pdb\";\n    $obj_tool_map{\"addr2line_pdb\"} = \"addr2line-pdb\";\n  }\n\n  if ($file_type =~ /Mach-O/) {\n    # OS X uses otool to examine Mach-O files, rather than objdump.\n    $obj_tool_map{\"otool\"} = \"otool\";\n    $obj_tool_map{\"addr2line\"} = \"false\";  # no addr2line\n    $obj_tool_map{\"objdump\"} = \"false\";  # no objdump\n  }\n\n  # Go fill in %obj_tool_map with the pathnames to use:\n  foreach my $tool (keys %obj_tool_map) {\n    $obj_tool_map{$tool} = ConfigureTool($obj_tool_map{$tool});\n  }\n}\n\n# Returns the path of a caller-specified object tool.  If --tools or\n# JEPROF_TOOLS are specified, then returns the full path to the tool\n# with that prefix.  Otherwise, returns the path unmodified (which\n# means we will look for it on PATH).\nsub ConfigureTool {\n  my $tool = shift;\n  my $path;\n\n  # --tools (or $JEPROF_TOOLS) is a comma separated list, where each\n  # item is either a) a pathname prefix, or b) a map of the form\n  # <tool>:<path>.  First we look for an entry of type (b) for our\n  # tool.  If one is found, we use it.  Otherwise, we consider all the\n  # pathname prefixes in turn, until one yields an existing file.  If\n  # none does, we use a default path.\n  my $tools = $main::opt_tools || $ENV{\"JEPROF_TOOLS\"} || \"\";\n  if ($tools =~ m/(,|^)\\Q$tool\\E:([^,]*)/) {\n    $path = $2;\n    # TODO(csilvers): sanity-check that $path exists?  Hard if it's relative.\n  } elsif ($tools ne '') {\n    foreach my $prefix (split(',', $tools)) {\n      next if ($prefix =~ /:/);    # ignore \"tool:fullpath\" entries in the list\n      if (-x $prefix . $tool) {\n        $path = $prefix . $tool;\n        last;\n      }\n    }\n    if (!$path) {\n      error(\"No '$tool' found with prefix specified by \" .\n            \"--tools (or \\$JEPROF_TOOLS) '$tools'\\n\");\n    }\n  } else {\n    # ... otherwise use the version that exists in the same directory as\n    # jeprof.  If there's nothing there, use $PATH.\n    $0 =~ m,[^/]*$,;     # this is everything after the last slash\n    my $dirname = $`;    # this is everything up to and including the last slash\n    if (-x \"$dirname$tool\") {\n      $path = \"$dirname$tool\";\n    } else {\n      $path = $tool;\n    }\n  }\n  if ($main::opt_debug) { print STDERR \"Using '$path' for '$tool'.\\n\"; }\n  return $path;\n}\n\nsub ShellEscape {\n  my @escaped_words = ();\n  foreach my $word (@_) {\n    my $escaped_word = $word;\n    if ($word =~ m![^a-zA-Z0-9/.,_=-]!) {  # check for anything not in whitelist\n      $escaped_word =~ s/'/'\\\\''/;\n      $escaped_word = \"'$escaped_word'\";\n    }\n    push(@escaped_words, $escaped_word);\n  }\n  return join(\" \", @escaped_words);\n}\n\nsub cleanup {\n  unlink($main::tmpfile_sym);\n  unlink(keys %main::tempnames);\n\n  # We leave any collected profiles in $HOME/jeprof in case the user wants\n  # to look at them later.  We print a message informing them of this.\n  if ((scalar(@main::profile_files) > 0) &&\n      defined($main::collected_profile)) {\n    if (scalar(@main::profile_files) == 1) {\n      print STDERR \"Dynamically gathered profile is in $main::collected_profile\\n\";\n    }\n    print STDERR \"If you want to investigate this profile further, you can do:\\n\";\n    print STDERR \"\\n\";\n    print STDERR \"  jeprof \\\\\\n\";\n    print STDERR \"    $main::prog \\\\\\n\";\n    print STDERR \"    $main::collected_profile\\n\";\n    print STDERR \"\\n\";\n  }\n}\n\nsub sighandler {\n  cleanup();\n  exit(1);\n}\n\nsub error {\n  my $msg = shift;\n  print STDERR $msg;\n  cleanup();\n  exit(1);\n}\n\n\n# Run $nm_command and get all the resulting procedure boundaries whose\n# names match \"$regexp\" and returns them in a hashtable mapping from\n# procedure name to a two-element vector of [start address, end address]\nsub GetProcedureBoundariesViaNm {\n  my $escaped_nm_command = shift;    # shell-escaped\n  my $regexp = shift;\n\n  my $symbol_table = {};\n  open(NM, \"$escaped_nm_command |\") || error(\"$escaped_nm_command: $!\\n\");\n  my $last_start = \"0\";\n  my $routine = \"\";\n  while (<NM>) {\n    s/\\r//g;         # turn windows-looking lines into unix-looking lines\n    if (m/^\\s*([0-9a-f]+) (.) (..*)/) {\n      my $start_val = $1;\n      my $type = $2;\n      my $this_routine = $3;\n\n      # It's possible for two symbols to share the same address, if\n      # one is a zero-length variable (like __start_google_malloc) or\n      # one symbol is a weak alias to another (like __libc_malloc).\n      # In such cases, we want to ignore all values except for the\n      # actual symbol, which in nm-speak has type \"T\".  The logic\n      # below does this, though it's a bit tricky: what happens when\n      # we have a series of lines with the same address, is the first\n      # one gets queued up to be processed.  However, it won't\n      # *actually* be processed until later, when we read a line with\n      # a different address.  That means that as long as we're reading\n      # lines with the same address, we have a chance to replace that\n      # item in the queue, which we do whenever we see a 'T' entry --\n      # that is, a line with type 'T'.  If we never see a 'T' entry,\n      # we'll just go ahead and process the first entry (which never\n      # got touched in the queue), and ignore the others.\n      if ($start_val eq $last_start && $type =~ /t/i) {\n        # We are the 'T' symbol at this address, replace previous symbol.\n        $routine = $this_routine;\n        next;\n      } elsif ($start_val eq $last_start) {\n        # We're not the 'T' symbol at this address, so ignore us.\n        next;\n      }\n\n      if ($this_routine eq $sep_symbol) {\n        $sep_address = HexExtend($start_val);\n      }\n\n      # Tag this routine with the starting address in case the image\n      # has multiple occurrences of this routine.  We use a syntax\n      # that resembles template parameters that are automatically\n      # stripped out by ShortFunctionName()\n      $this_routine .= \"<$start_val>\";\n\n      if (defined($routine) && $routine =~ m/$regexp/) {\n        $symbol_table->{$routine} = [HexExtend($last_start),\n                                     HexExtend($start_val)];\n      }\n      $last_start = $start_val;\n      $routine = $this_routine;\n    } elsif (m/^Loaded image name: (.+)/) {\n      # The win32 nm workalike emits information about the binary it is using.\n      if ($main::opt_debug) { print STDERR \"Using Image $1\\n\"; }\n    } elsif (m/^PDB file name: (.+)/) {\n      # The win32 nm workalike emits information about the pdb it is using.\n      if ($main::opt_debug) { print STDERR \"Using PDB $1\\n\"; }\n    }\n  }\n  close(NM);\n  # Handle the last line in the nm output.  Unfortunately, we don't know\n  # how big this last symbol is, because we don't know how big the file\n  # is.  For now, we just give it a size of 0.\n  # TODO(csilvers): do better here.\n  if (defined($routine) && $routine =~ m/$regexp/) {\n    $symbol_table->{$routine} = [HexExtend($last_start),\n                                 HexExtend($last_start)];\n  }\n  return $symbol_table;\n}\n\n# Gets the procedure boundaries for all routines in \"$image\" whose names\n# match \"$regexp\" and returns them in a hashtable mapping from procedure\n# name to a two-element vector of [start address, end address].\n# Will return an empty map if nm is not installed or not working properly.\nsub GetProcedureBoundaries {\n  my $image = shift;\n  my $regexp = shift;\n\n  # If $image doesn't start with /, then put ./ in front of it.  This works\n  # around an obnoxious bug in our probing of nm -f behavior.\n  # \"nm -f $image\" is supposed to fail on GNU nm, but if:\n  #\n  # a. $image starts with [BbSsPp] (for example, bin/foo/bar), AND\n  # b. you have a.out in your current directory (a not uncommon occurence)\n  #\n  # then \"nm -f $image\" succeeds because -f only looks at the first letter of\n  # the argument, which looks valid because it's [BbSsPp], and then since\n  # there's no image provided, it looks for a.out and finds it.\n  #\n  # This regex makes sure that $image starts with . or /, forcing the -f\n  # parsing to fail since . and / are not valid formats.\n  $image =~ s#^[^/]#./$&#;\n\n  # For libc libraries, the copy in /usr/lib/debug contains debugging symbols\n  my $debugging = DebuggingLibrary($image);\n  if ($debugging) {\n    $image = $debugging;\n  }\n\n  my $nm = $obj_tool_map{\"nm\"};\n  my $cppfilt = $obj_tool_map{\"c++filt\"};\n\n  # nm can fail for two reasons: 1) $image isn't a debug library; 2) nm\n  # binary doesn't support --demangle.  In addition, for OS X we need\n  # to use the -f flag to get 'flat' nm output (otherwise we don't sort\n  # properly and get incorrect results).  Unfortunately, GNU nm uses -f\n  # in an incompatible way.  So first we test whether our nm supports\n  # --demangle and -f.\n  my $demangle_flag = \"\";\n  my $cppfilt_flag = \"\";\n  my $to_devnull = \">$dev_null 2>&1\";\n  if (system(ShellEscape($nm, \"--demangle\", \"image\") . $to_devnull) == 0) {\n    # In this mode, we do \"nm --demangle <foo>\"\n    $demangle_flag = \"--demangle\";\n    $cppfilt_flag = \"\";\n  } elsif (system(ShellEscape($cppfilt, $image) . $to_devnull) == 0) {\n    # In this mode, we do \"nm <foo> | c++filt\"\n    $cppfilt_flag = \" | \" . ShellEscape($cppfilt);\n  };\n  my $flatten_flag = \"\";\n  if (system(ShellEscape($nm, \"-f\", $image) . $to_devnull) == 0) {\n    $flatten_flag = \"-f\";\n  }\n\n  # Finally, in the case $imagie isn't a debug library, we try again with\n  # -D to at least get *exported* symbols.  If we can't use --demangle,\n  # we use c++filt instead, if it exists on this system.\n  my @nm_commands = (ShellEscape($nm, \"-n\", $flatten_flag, $demangle_flag,\n                                 $image) . \" 2>$dev_null $cppfilt_flag\",\n                     ShellEscape($nm, \"-D\", \"-n\", $flatten_flag, $demangle_flag,\n                                 $image) . \" 2>$dev_null $cppfilt_flag\",\n                     # 6nm is for Go binaries\n                     ShellEscape(\"6nm\", \"$image\") . \" 2>$dev_null | sort\",\n                     );\n\n  # If the executable is an MS Windows PDB-format executable, we'll\n  # have set up obj_tool_map(\"nm_pdb\").  In this case, we actually\n  # want to use both unix nm and windows-specific nm_pdb, since\n  # PDB-format executables can apparently include dwarf .o files.\n  if (exists $obj_tool_map{\"nm_pdb\"}) {\n    push(@nm_commands,\n         ShellEscape($obj_tool_map{\"nm_pdb\"}, \"--demangle\", $image)\n         . \" 2>$dev_null\");\n  }\n\n  foreach my $nm_command (@nm_commands) {\n    my $symbol_table = GetProcedureBoundariesViaNm($nm_command, $regexp);\n    return $symbol_table if (%{$symbol_table});\n  }\n  my $symbol_table = {};\n  return $symbol_table;\n}\n\n\n# The test vectors for AddressAdd/Sub/Inc are 8-16-nibble hex strings.\n# To make them more readable, we add underscores at interesting places.\n# This routine removes the underscores, producing the canonical representation\n# used by jeprof to represent addresses, particularly in the tested routines.\nsub CanonicalHex {\n  my $arg = shift;\n  return join '', (split '_',$arg);\n}\n\n\n# Unit test for AddressAdd:\nsub AddressAddUnitTest {\n  my $test_data_8 = shift;\n  my $test_data_16 = shift;\n  my $error_count = 0;\n  my $fail_count = 0;\n  my $pass_count = 0;\n  # print STDERR \"AddressAddUnitTest: \", 1+$#{$test_data_8}, \" tests\\n\";\n\n  # First a few 8-nibble addresses.  Note that this implementation uses\n  # plain old arithmetic, so a quick sanity check along with verifying what\n  # happens to overflow (we want it to wrap):\n  $address_length = 8;\n  foreach my $row (@{$test_data_8}) {\n    if ($main::opt_debug and $main::opt_test) { print STDERR \"@{$row}\\n\"; }\n    my $sum = AddressAdd ($row->[0], $row->[1]);\n    if ($sum ne $row->[2]) {\n      printf STDERR \"ERROR: %s != %s + %s = %s\\n\", $sum,\n             $row->[0], $row->[1], $row->[2];\n      ++$fail_count;\n    } else {\n      ++$pass_count;\n    }\n  }\n  printf STDERR \"AddressAdd 32-bit tests: %d passes, %d failures\\n\",\n         $pass_count, $fail_count;\n  $error_count = $fail_count;\n  $fail_count = 0;\n  $pass_count = 0;\n\n  # Now 16-nibble addresses.\n  $address_length = 16;\n  foreach my $row (@{$test_data_16}) {\n    if ($main::opt_debug and $main::opt_test) { print STDERR \"@{$row}\\n\"; }\n    my $sum = AddressAdd (CanonicalHex($row->[0]), CanonicalHex($row->[1]));\n    my $expected = join '', (split '_',$row->[2]);\n    if ($sum ne CanonicalHex($row->[2])) {\n      printf STDERR \"ERROR: %s != %s + %s = %s\\n\", $sum,\n             $row->[0], $row->[1], $row->[2];\n      ++$fail_count;\n    } else {\n      ++$pass_count;\n    }\n  }\n  printf STDERR \"AddressAdd 64-bit tests: %d passes, %d failures\\n\",\n         $pass_count, $fail_count;\n  $error_count += $fail_count;\n\n  return $error_count;\n}\n\n\n# Unit test for AddressSub:\nsub AddressSubUnitTest {\n  my $test_data_8 = shift;\n  my $test_data_16 = shift;\n  my $error_count = 0;\n  my $fail_count = 0;\n  my $pass_count = 0;\n  # print STDERR \"AddressSubUnitTest: \", 1+$#{$test_data_8}, \" tests\\n\";\n\n  # First a few 8-nibble addresses.  Note that this implementation uses\n  # plain old arithmetic, so a quick sanity check along with verifying what\n  # happens to overflow (we want it to wrap):\n  $address_length = 8;\n  foreach my $row (@{$test_data_8}) {\n    if ($main::opt_debug and $main::opt_test) { print STDERR \"@{$row}\\n\"; }\n    my $sum = AddressSub ($row->[0], $row->[1]);\n    if ($sum ne $row->[3]) {\n      printf STDERR \"ERROR: %s != %s - %s = %s\\n\", $sum,\n             $row->[0], $row->[1], $row->[3];\n      ++$fail_count;\n    } else {\n      ++$pass_count;\n    }\n  }\n  printf STDERR \"AddressSub 32-bit tests: %d passes, %d failures\\n\",\n         $pass_count, $fail_count;\n  $error_count = $fail_count;\n  $fail_count = 0;\n  $pass_count = 0;\n\n  # Now 16-nibble addresses.\n  $address_length = 16;\n  foreach my $row (@{$test_data_16}) {\n    if ($main::opt_debug and $main::opt_test) { print STDERR \"@{$row}\\n\"; }\n    my $sum = AddressSub (CanonicalHex($row->[0]), CanonicalHex($row->[1]));\n    if ($sum ne CanonicalHex($row->[3])) {\n      printf STDERR \"ERROR: %s != %s - %s = %s\\n\", $sum,\n             $row->[0], $row->[1], $row->[3];\n      ++$fail_count;\n    } else {\n      ++$pass_count;\n    }\n  }\n  printf STDERR \"AddressSub 64-bit tests: %d passes, %d failures\\n\",\n         $pass_count, $fail_count;\n  $error_count += $fail_count;\n\n  return $error_count;\n}\n\n\n# Unit test for AddressInc:\nsub AddressIncUnitTest {\n  my $test_data_8 = shift;\n  my $test_data_16 = shift;\n  my $error_count = 0;\n  my $fail_count = 0;\n  my $pass_count = 0;\n  # print STDERR \"AddressIncUnitTest: \", 1+$#{$test_data_8}, \" tests\\n\";\n\n  # First a few 8-nibble addresses.  Note that this implementation uses\n  # plain old arithmetic, so a quick sanity check along with verifying what\n  # happens to overflow (we want it to wrap):\n  $address_length = 8;\n  foreach my $row (@{$test_data_8}) {\n    if ($main::opt_debug and $main::opt_test) { print STDERR \"@{$row}\\n\"; }\n    my $sum = AddressInc ($row->[0]);\n    if ($sum ne $row->[4]) {\n      printf STDERR \"ERROR: %s != %s + 1 = %s\\n\", $sum,\n             $row->[0], $row->[4];\n      ++$fail_count;\n    } else {\n      ++$pass_count;\n    }\n  }\n  printf STDERR \"AddressInc 32-bit tests: %d passes, %d failures\\n\",\n         $pass_count, $fail_count;\n  $error_count = $fail_count;\n  $fail_count = 0;\n  $pass_count = 0;\n\n  # Now 16-nibble addresses.\n  $address_length = 16;\n  foreach my $row (@{$test_data_16}) {\n    if ($main::opt_debug and $main::opt_test) { print STDERR \"@{$row}\\n\"; }\n    my $sum = AddressInc (CanonicalHex($row->[0]));\n    if ($sum ne CanonicalHex($row->[4])) {\n      printf STDERR \"ERROR: %s != %s + 1 = %s\\n\", $sum,\n             $row->[0], $row->[4];\n      ++$fail_count;\n    } else {\n      ++$pass_count;\n    }\n  }\n  printf STDERR \"AddressInc 64-bit tests: %d passes, %d failures\\n\",\n         $pass_count, $fail_count;\n  $error_count += $fail_count;\n\n  return $error_count;\n}\n\n\n# Driver for unit tests.\n# Currently just the address add/subtract/increment routines for 64-bit.\nsub RunUnitTests {\n  my $error_count = 0;\n\n  # This is a list of tuples [a, b, a+b, a-b, a+1]\n  my $unit_test_data_8 = [\n    [qw(aaaaaaaa 50505050 fafafafa 5a5a5a5a aaaaaaab)],\n    [qw(50505050 aaaaaaaa fafafafa a5a5a5a6 50505051)],\n    [qw(ffffffff aaaaaaaa aaaaaaa9 55555555 00000000)],\n    [qw(00000001 ffffffff 00000000 00000002 00000002)],\n    [qw(00000001 fffffff0 fffffff1 00000011 00000002)],\n  ];\n  my $unit_test_data_16 = [\n    # The implementation handles data in 7-nibble chunks, so those are the\n    # interesting boundaries.\n    [qw(aaaaaaaa 50505050\n        00_000000f_afafafa 00_0000005_a5a5a5a 00_000000a_aaaaaab)],\n    [qw(50505050 aaaaaaaa\n        00_000000f_afafafa ff_ffffffa_5a5a5a6 00_0000005_0505051)],\n    [qw(ffffffff aaaaaaaa\n        00_000001a_aaaaaa9 00_0000005_5555555 00_0000010_0000000)],\n    [qw(00000001 ffffffff\n        00_0000010_0000000 ff_ffffff0_0000002 00_0000000_0000002)],\n    [qw(00000001 fffffff0\n        00_000000f_ffffff1 ff_ffffff0_0000011 00_0000000_0000002)],\n\n    [qw(00_a00000a_aaaaaaa 50505050\n        00_a00000f_afafafa 00_a000005_a5a5a5a 00_a00000a_aaaaaab)],\n    [qw(0f_fff0005_0505050 aaaaaaaa\n        0f_fff000f_afafafa 0f_ffefffa_5a5a5a6 0f_fff0005_0505051)],\n    [qw(00_000000f_fffffff 01_800000a_aaaaaaa\n        01_800001a_aaaaaa9 fe_8000005_5555555 00_0000010_0000000)],\n    [qw(00_0000000_0000001 ff_fffffff_fffffff\n        00_0000000_0000000 00_0000000_0000002 00_0000000_0000002)],\n    [qw(00_0000000_0000001 ff_fffffff_ffffff0\n        ff_fffffff_ffffff1 00_0000000_0000011 00_0000000_0000002)],\n  ];\n\n  $error_count += AddressAddUnitTest($unit_test_data_8, $unit_test_data_16);\n  $error_count += AddressSubUnitTest($unit_test_data_8, $unit_test_data_16);\n  $error_count += AddressIncUnitTest($unit_test_data_8, $unit_test_data_16);\n  if ($error_count > 0) {\n    print STDERR $error_count, \" errors: FAILED\\n\";\n  } else {\n    print STDERR \"PASS\\n\";\n  }\n  exit ($error_count);\n}\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.8/deps/jemalloc/config.guess",
    "content": "#! /bin/sh\n# Attempt to guess a canonical system name.\n#   Copyright 1992-2014 Free Software Foundation, Inc.\n\ntimestamp='2014-03-23'\n\n# This file is free software; you can redistribute it and/or modify it\n# under the terms of the GNU General Public License as published by\n# the Free Software Foundation; either version 3 of the License, or\n# (at your option) any later version.\n#\n# This program is distributed in the hope that it will be useful, but\n# WITHOUT ANY WARRANTY; without even the implied warranty of\n# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n# General Public License for more details.\n#\n# You should have received a copy of the GNU General Public License\n# along with this program; if not, see <http://www.gnu.org/licenses/>.\n#\n# As a special exception to the GNU General Public License, if you\n# distribute this file as part of a program that contains a\n# configuration script generated by Autoconf, you may include it under\n# the same distribution terms that you use for the rest of that\n# program.  This Exception is an additional permission under section 7\n# of the GNU General Public License, version 3 (\"GPLv3\").\n#\n# Originally written by Per Bothner.\n#\n# You can get the latest version of this script from:\n# http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.guess;hb=HEAD\n#\n# Please send patches with a ChangeLog entry to config-patches@gnu.org.\n\n\nme=`echo \"$0\" | sed -e 's,.*/,,'`\n\nusage=\"\\\nUsage: $0 [OPTION]\n\nOutput the configuration name of the system \\`$me' is run on.\n\nOperation modes:\n  -h, --help         print this help, then exit\n  -t, --time-stamp   print date of last modification, then exit\n  -v, --version      print version number, then exit\n\nReport bugs and patches to <config-patches@gnu.org>.\"\n\nversion=\"\\\nGNU config.guess ($timestamp)\n\nOriginally written by Per Bothner.\nCopyright 1992-2014 Free Software Foundation, Inc.\n\nThis is free software; see the source for copying conditions.  There is NO\nwarranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\"\n\nhelp=\"\nTry \\`$me --help' for more information.\"\n\n# Parse command line\nwhile test $# -gt 0 ; do\n  case $1 in\n    --time-stamp | --time* | -t )\n       echo \"$timestamp\" ; exit ;;\n    --version | -v )\n       echo \"$version\" ; exit ;;\n    --help | --h* | -h )\n       echo \"$usage\"; exit ;;\n    -- )     # Stop option processing\n       shift; break ;;\n    - )\t# Use stdin as input.\n       break ;;\n    -* )\n       echo \"$me: invalid option $1$help\" >&2\n       exit 1 ;;\n    * )\n       break ;;\n  esac\ndone\n\nif test $# != 0; then\n  echo \"$me: too many arguments$help\" >&2\n  exit 1\nfi\n\ntrap 'exit 1' 1 2 15\n\n# CC_FOR_BUILD -- compiler used by this script. Note that the use of a\n# compiler to aid in system detection is discouraged as it requires\n# temporary files to be created and, as you can see below, it is a\n# headache to deal with in a portable fashion.\n\n# Historically, `CC_FOR_BUILD' used to be named `HOST_CC'. We still\n# use `HOST_CC' if defined, but it is deprecated.\n\n# Portable tmp directory creation inspired by the Autoconf team.\n\nset_cc_for_build='\ntrap \"exitcode=\\$?; (rm -f \\$tmpfiles 2>/dev/null; rmdir \\$tmp 2>/dev/null) && exit \\$exitcode\" 0 ;\ntrap \"rm -f \\$tmpfiles 2>/dev/null; rmdir \\$tmp 2>/dev/null; exit 1\" 1 2 13 15 ;\n: ${TMPDIR=/tmp} ;\n { tmp=`(umask 077 && mktemp -d \"$TMPDIR/cgXXXXXX\") 2>/dev/null` && test -n \"$tmp\" && test -d \"$tmp\" ; } ||\n { test -n \"$RANDOM\" && tmp=$TMPDIR/cg$$-$RANDOM && (umask 077 && mkdir $tmp) ; } ||\n { tmp=$TMPDIR/cg-$$ && (umask 077 && mkdir $tmp) && echo \"Warning: creating insecure temp directory\" >&2 ; } ||\n { echo \"$me: cannot create a temporary directory in $TMPDIR\" >&2 ; exit 1 ; } ;\ndummy=$tmp/dummy ;\ntmpfiles=\"$dummy.c $dummy.o $dummy.rel $dummy\" ;\ncase $CC_FOR_BUILD,$HOST_CC,$CC in\n ,,)    echo \"int x;\" > $dummy.c ;\n\tfor c in cc gcc c89 c99 ; do\n\t  if ($c -c -o $dummy.o $dummy.c) >/dev/null 2>&1 ; then\n\t     CC_FOR_BUILD=\"$c\"; break ;\n\t  fi ;\n\tdone ;\n\tif test x\"$CC_FOR_BUILD\" = x ; then\n\t  CC_FOR_BUILD=no_compiler_found ;\n\tfi\n\t;;\n ,,*)   CC_FOR_BUILD=$CC ;;\n ,*,*)  CC_FOR_BUILD=$HOST_CC ;;\nesac ; set_cc_for_build= ;'\n\n# This is needed to find uname on a Pyramid OSx when run in the BSD universe.\n# (ghazi@noc.rutgers.edu 1994-08-24)\nif (test -f /.attbin/uname) >/dev/null 2>&1 ; then\n\tPATH=$PATH:/.attbin ; export PATH\nfi\n\nUNAME_MACHINE=`(uname -m) 2>/dev/null` || UNAME_MACHINE=unknown\nUNAME_RELEASE=`(uname -r) 2>/dev/null` || UNAME_RELEASE=unknown\nUNAME_SYSTEM=`(uname -s) 2>/dev/null`  || UNAME_SYSTEM=unknown\nUNAME_VERSION=`(uname -v) 2>/dev/null` || UNAME_VERSION=unknown\n\ncase \"${UNAME_SYSTEM}\" in\nLinux|GNU|GNU/*)\n\t# If the system lacks a compiler, then just pick glibc.\n\t# We could probably try harder.\n\tLIBC=gnu\n\n\teval $set_cc_for_build\n\tcat <<-EOF > $dummy.c\n\t#include <features.h>\n\t#if defined(__UCLIBC__)\n\tLIBC=uclibc\n\t#elif defined(__dietlibc__)\n\tLIBC=dietlibc\n\t#else\n\tLIBC=gnu\n\t#endif\n\tEOF\n\teval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep '^LIBC' | sed 's, ,,g'`\n\t;;\nesac\n\n# Note: order is significant - the case branches are not exclusive.\n\ncase \"${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}\" in\n    *:NetBSD:*:*)\n\t# NetBSD (nbsd) targets should (where applicable) match one or\n\t# more of the tuples: *-*-netbsdelf*, *-*-netbsdaout*,\n\t# *-*-netbsdecoff* and *-*-netbsd*.  For targets that recently\n\t# switched to ELF, *-*-netbsd* would select the old\n\t# object file format.  This provides both forward\n\t# compatibility and a consistent mechanism for selecting the\n\t# object file format.\n\t#\n\t# Note: NetBSD doesn't particularly care about the vendor\n\t# portion of the name.  We always set it to \"unknown\".\n\tsysctl=\"sysctl -n hw.machine_arch\"\n\tUNAME_MACHINE_ARCH=`(/sbin/$sysctl 2>/dev/null || \\\n\t    /usr/sbin/$sysctl 2>/dev/null || echo unknown)`\n\tcase \"${UNAME_MACHINE_ARCH}\" in\n\t    armeb) machine=armeb-unknown ;;\n\t    arm*) machine=arm-unknown ;;\n\t    sh3el) machine=shl-unknown ;;\n\t    sh3eb) machine=sh-unknown ;;\n\t    sh5el) machine=sh5le-unknown ;;\n\t    *) machine=${UNAME_MACHINE_ARCH}-unknown ;;\n\tesac\n\t# The Operating System including object format, if it has switched\n\t# to ELF recently, or will in the future.\n\tcase \"${UNAME_MACHINE_ARCH}\" in\n\t    arm*|i386|m68k|ns32k|sh3*|sparc|vax)\n\t\teval $set_cc_for_build\n\t\tif echo __ELF__ | $CC_FOR_BUILD -E - 2>/dev/null \\\n\t\t\t| grep -q __ELF__\n\t\tthen\n\t\t    # Once all utilities can be ECOFF (netbsdecoff) or a.out (netbsdaout).\n\t\t    # Return netbsd for either.  FIX?\n\t\t    os=netbsd\n\t\telse\n\t\t    os=netbsdelf\n\t\tfi\n\t\t;;\n\t    *)\n\t\tos=netbsd\n\t\t;;\n\tesac\n\t# The OS release\n\t# Debian GNU/NetBSD machines have a different userland, and\n\t# thus, need a distinct triplet. However, they do not need\n\t# kernel version information, so it can be replaced with a\n\t# suitable tag, in the style of linux-gnu.\n\tcase \"${UNAME_VERSION}\" in\n\t    Debian*)\n\t\trelease='-gnu'\n\t\t;;\n\t    *)\n\t\trelease=`echo ${UNAME_RELEASE}|sed -e 's/[-_].*/\\./'`\n\t\t;;\n\tesac\n\t# Since CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM:\n\t# contains redundant information, the shorter form:\n\t# CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM is used.\n\techo \"${machine}-${os}${release}\"\n\texit ;;\n    *:Bitrig:*:*)\n\tUNAME_MACHINE_ARCH=`arch | sed 's/Bitrig.//'`\n\techo ${UNAME_MACHINE_ARCH}-unknown-bitrig${UNAME_RELEASE}\n\texit ;;\n    *:OpenBSD:*:*)\n\tUNAME_MACHINE_ARCH=`arch | sed 's/OpenBSD.//'`\n\techo ${UNAME_MACHINE_ARCH}-unknown-openbsd${UNAME_RELEASE}\n\texit ;;\n    *:ekkoBSD:*:*)\n\techo ${UNAME_MACHINE}-unknown-ekkobsd${UNAME_RELEASE}\n\texit ;;\n    *:SolidBSD:*:*)\n\techo ${UNAME_MACHINE}-unknown-solidbsd${UNAME_RELEASE}\n\texit ;;\n    macppc:MirBSD:*:*)\n\techo powerpc-unknown-mirbsd${UNAME_RELEASE}\n\texit ;;\n    *:MirBSD:*:*)\n\techo ${UNAME_MACHINE}-unknown-mirbsd${UNAME_RELEASE}\n\texit ;;\n    alpha:OSF1:*:*)\n\tcase $UNAME_RELEASE in\n\t*4.0)\n\t\tUNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $3}'`\n\t\t;;\n\t*5.*)\n\t\tUNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $4}'`\n\t\t;;\n\tesac\n\t# According to Compaq, /usr/sbin/psrinfo has been available on\n\t# OSF/1 and Tru64 systems produced since 1995.  I hope that\n\t# covers most systems running today.  This code pipes the CPU\n\t# types through head -n 1, so we only detect the type of CPU 0.\n\tALPHA_CPU_TYPE=`/usr/sbin/psrinfo -v | sed -n -e 's/^  The alpha \\(.*\\) processor.*$/\\1/p' | head -n 1`\n\tcase \"$ALPHA_CPU_TYPE\" in\n\t    \"EV4 (21064)\")\n\t\tUNAME_MACHINE=\"alpha\" ;;\n\t    \"EV4.5 (21064)\")\n\t\tUNAME_MACHINE=\"alpha\" ;;\n\t    \"LCA4 (21066/21068)\")\n\t\tUNAME_MACHINE=\"alpha\" ;;\n\t    \"EV5 (21164)\")\n\t\tUNAME_MACHINE=\"alphaev5\" ;;\n\t    \"EV5.6 (21164A)\")\n\t\tUNAME_MACHINE=\"alphaev56\" ;;\n\t    \"EV5.6 (21164PC)\")\n\t\tUNAME_MACHINE=\"alphapca56\" ;;\n\t    \"EV5.7 (21164PC)\")\n\t\tUNAME_MACHINE=\"alphapca57\" ;;\n\t    \"EV6 (21264)\")\n\t\tUNAME_MACHINE=\"alphaev6\" ;;\n\t    \"EV6.7 (21264A)\")\n\t\tUNAME_MACHINE=\"alphaev67\" ;;\n\t    \"EV6.8CB (21264C)\")\n\t\tUNAME_MACHINE=\"alphaev68\" ;;\n\t    \"EV6.8AL (21264B)\")\n\t\tUNAME_MACHINE=\"alphaev68\" ;;\n\t    \"EV6.8CX (21264D)\")\n\t\tUNAME_MACHINE=\"alphaev68\" ;;\n\t    \"EV6.9A (21264/EV69A)\")\n\t\tUNAME_MACHINE=\"alphaev69\" ;;\n\t    \"EV7 (21364)\")\n\t\tUNAME_MACHINE=\"alphaev7\" ;;\n\t    \"EV7.9 (21364A)\")\n\t\tUNAME_MACHINE=\"alphaev79\" ;;\n\tesac\n\t# A Pn.n version is a patched version.\n\t# A Vn.n version is a released version.\n\t# A Tn.n version is a released field test version.\n\t# A Xn.n version is an unreleased experimental baselevel.\n\t# 1.2 uses \"1.2\" for uname -r.\n\techo ${UNAME_MACHINE}-dec-osf`echo ${UNAME_RELEASE} | sed -e 's/^[PVTX]//' | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'`\n\t# Reset EXIT trap before exiting to avoid spurious non-zero exit code.\n\texitcode=$?\n\ttrap '' 0\n\texit $exitcode ;;\n    Alpha\\ *:Windows_NT*:*)\n\t# How do we know it's Interix rather than the generic POSIX subsystem?\n\t# Should we change UNAME_MACHINE based on the output of uname instead\n\t# of the specific Alpha model?\n\techo alpha-pc-interix\n\texit ;;\n    21064:Windows_NT:50:3)\n\techo alpha-dec-winnt3.5\n\texit ;;\n    Amiga*:UNIX_System_V:4.0:*)\n\techo m68k-unknown-sysv4\n\texit ;;\n    *:[Aa]miga[Oo][Ss]:*:*)\n\techo ${UNAME_MACHINE}-unknown-amigaos\n\texit ;;\n    *:[Mm]orph[Oo][Ss]:*:*)\n\techo ${UNAME_MACHINE}-unknown-morphos\n\texit ;;\n    *:OS/390:*:*)\n\techo i370-ibm-openedition\n\texit ;;\n    *:z/VM:*:*)\n\techo s390-ibm-zvmoe\n\texit ;;\n    *:OS400:*:*)\n\techo powerpc-ibm-os400\n\texit ;;\n    arm:RISC*:1.[012]*:*|arm:riscix:1.[012]*:*)\n\techo arm-acorn-riscix${UNAME_RELEASE}\n\texit ;;\n    arm*:riscos:*:*|arm*:RISCOS:*:*)\n\techo arm-unknown-riscos\n\texit ;;\n    SR2?01:HI-UX/MPP:*:* | SR8000:HI-UX/MPP:*:*)\n\techo hppa1.1-hitachi-hiuxmpp\n\texit ;;\n    Pyramid*:OSx*:*:* | MIS*:OSx*:*:* | MIS*:SMP_DC-OSx*:*:*)\n\t# akee@wpdis03.wpafb.af.mil (Earle F. Ake) contributed MIS and NILE.\n\tif test \"`(/bin/universe) 2>/dev/null`\" = att ; then\n\t\techo pyramid-pyramid-sysv3\n\telse\n\t\techo pyramid-pyramid-bsd\n\tfi\n\texit ;;\n    NILE*:*:*:dcosx)\n\techo pyramid-pyramid-svr4\n\texit ;;\n    DRS?6000:unix:4.0:6*)\n\techo sparc-icl-nx6\n\texit ;;\n    DRS?6000:UNIX_SV:4.2*:7* | DRS?6000:isis:4.2*:7*)\n\tcase `/usr/bin/uname -p` in\n\t    sparc) echo sparc-icl-nx7; exit ;;\n\tesac ;;\n    s390x:SunOS:*:*)\n\techo ${UNAME_MACHINE}-ibm-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`\n\texit ;;\n    sun4H:SunOS:5.*:*)\n\techo sparc-hal-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`\n\texit ;;\n    sun4*:SunOS:5.*:* | tadpole*:SunOS:5.*:*)\n\techo sparc-sun-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`\n\texit ;;\n    i86pc:AuroraUX:5.*:* | i86xen:AuroraUX:5.*:*)\n\techo i386-pc-auroraux${UNAME_RELEASE}\n\texit ;;\n    i86pc:SunOS:5.*:* | i86xen:SunOS:5.*:*)\n\teval $set_cc_for_build\n\tSUN_ARCH=\"i386\"\n\t# If there is a compiler, see if it is configured for 64-bit objects.\n\t# Note that the Sun cc does not turn __LP64__ into 1 like gcc does.\n\t# This test works for both compilers.\n\tif [ \"$CC_FOR_BUILD\" != 'no_compiler_found' ]; then\n\t    if (echo '#ifdef __amd64'; echo IS_64BIT_ARCH; echo '#endif') | \\\n\t\t(CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) | \\\n\t\tgrep IS_64BIT_ARCH >/dev/null\n\t    then\n\t\tSUN_ARCH=\"x86_64\"\n\t    fi\n\tfi\n\techo ${SUN_ARCH}-pc-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`\n\texit ;;\n    sun4*:SunOS:6*:*)\n\t# According to config.sub, this is the proper way to canonicalize\n\t# SunOS6.  Hard to guess exactly what SunOS6 will be like, but\n\t# it's likely to be more like Solaris than SunOS4.\n\techo sparc-sun-solaris3`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`\n\texit ;;\n    sun4*:SunOS:*:*)\n\tcase \"`/usr/bin/arch -k`\" in\n\t    Series*|S4*)\n\t\tUNAME_RELEASE=`uname -v`\n\t\t;;\n\tesac\n\t# Japanese Language versions have a version number like `4.1.3-JL'.\n\techo sparc-sun-sunos`echo ${UNAME_RELEASE}|sed -e 's/-/_/'`\n\texit ;;\n    sun3*:SunOS:*:*)\n\techo m68k-sun-sunos${UNAME_RELEASE}\n\texit ;;\n    sun*:*:4.2BSD:*)\n\tUNAME_RELEASE=`(sed 1q /etc/motd | awk '{print substr($5,1,3)}') 2>/dev/null`\n\ttest \"x${UNAME_RELEASE}\" = \"x\" && UNAME_RELEASE=3\n\tcase \"`/bin/arch`\" in\n\t    sun3)\n\t\techo m68k-sun-sunos${UNAME_RELEASE}\n\t\t;;\n\t    sun4)\n\t\techo sparc-sun-sunos${UNAME_RELEASE}\n\t\t;;\n\tesac\n\texit ;;\n    aushp:SunOS:*:*)\n\techo sparc-auspex-sunos${UNAME_RELEASE}\n\texit ;;\n    # The situation for MiNT is a little confusing.  The machine name\n    # can be virtually everything (everything which is not\n    # \"atarist\" or \"atariste\" at least should have a processor\n    # > m68000).  The system name ranges from \"MiNT\" over \"FreeMiNT\"\n    # to the lowercase version \"mint\" (or \"freemint\").  Finally\n    # the system name \"TOS\" denotes a system which is actually not\n    # MiNT.  But MiNT is downward compatible to TOS, so this should\n    # be no problem.\n    atarist[e]:*MiNT:*:* | atarist[e]:*mint:*:* | atarist[e]:*TOS:*:*)\n\techo m68k-atari-mint${UNAME_RELEASE}\n\texit ;;\n    atari*:*MiNT:*:* | atari*:*mint:*:* | atarist[e]:*TOS:*:*)\n\techo m68k-atari-mint${UNAME_RELEASE}\n\texit ;;\n    *falcon*:*MiNT:*:* | *falcon*:*mint:*:* | *falcon*:*TOS:*:*)\n\techo m68k-atari-mint${UNAME_RELEASE}\n\texit ;;\n    milan*:*MiNT:*:* | milan*:*mint:*:* | *milan*:*TOS:*:*)\n\techo m68k-milan-mint${UNAME_RELEASE}\n\texit ;;\n    hades*:*MiNT:*:* | hades*:*mint:*:* | *hades*:*TOS:*:*)\n\techo m68k-hades-mint${UNAME_RELEASE}\n\texit ;;\n    *:*MiNT:*:* | *:*mint:*:* | *:*TOS:*:*)\n\techo m68k-unknown-mint${UNAME_RELEASE}\n\texit ;;\n    m68k:machten:*:*)\n\techo m68k-apple-machten${UNAME_RELEASE}\n\texit ;;\n    powerpc:machten:*:*)\n\techo powerpc-apple-machten${UNAME_RELEASE}\n\texit ;;\n    RISC*:Mach:*:*)\n\techo mips-dec-mach_bsd4.3\n\texit ;;\n    RISC*:ULTRIX:*:*)\n\techo mips-dec-ultrix${UNAME_RELEASE}\n\texit ;;\n    VAX*:ULTRIX*:*:*)\n\techo vax-dec-ultrix${UNAME_RELEASE}\n\texit ;;\n    2020:CLIX:*:* | 2430:CLIX:*:*)\n\techo clipper-intergraph-clix${UNAME_RELEASE}\n\texit ;;\n    mips:*:*:UMIPS | mips:*:*:RISCos)\n\teval $set_cc_for_build\n\tsed 's/^\t//' << EOF >$dummy.c\n#ifdef __cplusplus\n#include <stdio.h>  /* for printf() prototype */\n\tint main (int argc, char *argv[]) {\n#else\n\tint main (argc, argv) int argc; char *argv[]; {\n#endif\n\t#if defined (host_mips) && defined (MIPSEB)\n\t#if defined (SYSTYPE_SYSV)\n\t  printf (\"mips-mips-riscos%ssysv\\n\", argv[1]); exit (0);\n\t#endif\n\t#if defined (SYSTYPE_SVR4)\n\t  printf (\"mips-mips-riscos%ssvr4\\n\", argv[1]); exit (0);\n\t#endif\n\t#if defined (SYSTYPE_BSD43) || defined(SYSTYPE_BSD)\n\t  printf (\"mips-mips-riscos%sbsd\\n\", argv[1]); exit (0);\n\t#endif\n\t#endif\n\t  exit (-1);\n\t}\nEOF\n\t$CC_FOR_BUILD -o $dummy $dummy.c &&\n\t  dummyarg=`echo \"${UNAME_RELEASE}\" | sed -n 's/\\([0-9]*\\).*/\\1/p'` &&\n\t  SYSTEM_NAME=`$dummy $dummyarg` &&\n\t    { echo \"$SYSTEM_NAME\"; exit; }\n\techo mips-mips-riscos${UNAME_RELEASE}\n\texit ;;\n    Motorola:PowerMAX_OS:*:*)\n\techo powerpc-motorola-powermax\n\texit ;;\n    Motorola:*:4.3:PL8-*)\n\techo powerpc-harris-powermax\n\texit ;;\n    Night_Hawk:*:*:PowerMAX_OS | Synergy:PowerMAX_OS:*:*)\n\techo powerpc-harris-powermax\n\texit ;;\n    Night_Hawk:Power_UNIX:*:*)\n\techo powerpc-harris-powerunix\n\texit ;;\n    m88k:CX/UX:7*:*)\n\techo m88k-harris-cxux7\n\texit ;;\n    m88k:*:4*:R4*)\n\techo m88k-motorola-sysv4\n\texit ;;\n    m88k:*:3*:R3*)\n\techo m88k-motorola-sysv3\n\texit ;;\n    AViiON:dgux:*:*)\n\t# DG/UX returns AViiON for all architectures\n\tUNAME_PROCESSOR=`/usr/bin/uname -p`\n\tif [ $UNAME_PROCESSOR = mc88100 ] || [ $UNAME_PROCESSOR = mc88110 ]\n\tthen\n\t    if [ ${TARGET_BINARY_INTERFACE}x = m88kdguxelfx ] || \\\n\t       [ ${TARGET_BINARY_INTERFACE}x = x ]\n\t    then\n\t\techo m88k-dg-dgux${UNAME_RELEASE}\n\t    else\n\t\techo m88k-dg-dguxbcs${UNAME_RELEASE}\n\t    fi\n\telse\n\t    echo i586-dg-dgux${UNAME_RELEASE}\n\tfi\n\texit ;;\n    M88*:DolphinOS:*:*)\t# DolphinOS (SVR3)\n\techo m88k-dolphin-sysv3\n\texit ;;\n    M88*:*:R3*:*)\n\t# Delta 88k system running SVR3\n\techo m88k-motorola-sysv3\n\texit ;;\n    XD88*:*:*:*) # Tektronix XD88 system running UTekV (SVR3)\n\techo m88k-tektronix-sysv3\n\texit ;;\n    Tek43[0-9][0-9]:UTek:*:*) # Tektronix 4300 system running UTek (BSD)\n\techo m68k-tektronix-bsd\n\texit ;;\n    *:IRIX*:*:*)\n\techo mips-sgi-irix`echo ${UNAME_RELEASE}|sed -e 's/-/_/g'`\n\texit ;;\n    ????????:AIX?:[12].1:2)   # AIX 2.2.1 or AIX 2.1.1 is RT/PC AIX.\n\techo romp-ibm-aix     # uname -m gives an 8 hex-code CPU id\n\texit ;;               # Note that: echo \"'`uname -s`'\" gives 'AIX '\n    i*86:AIX:*:*)\n\techo i386-ibm-aix\n\texit ;;\n    ia64:AIX:*:*)\n\tif [ -x /usr/bin/oslevel ] ; then\n\t\tIBM_REV=`/usr/bin/oslevel`\n\telse\n\t\tIBM_REV=${UNAME_VERSION}.${UNAME_RELEASE}\n\tfi\n\techo ${UNAME_MACHINE}-ibm-aix${IBM_REV}\n\texit ;;\n    *:AIX:2:3)\n\tif grep bos325 /usr/include/stdio.h >/dev/null 2>&1; then\n\t\teval $set_cc_for_build\n\t\tsed 's/^\t\t//' << EOF >$dummy.c\n\t\t#include <sys/systemcfg.h>\n\n\t\tmain()\n\t\t\t{\n\t\t\tif (!__power_pc())\n\t\t\t\texit(1);\n\t\t\tputs(\"powerpc-ibm-aix3.2.5\");\n\t\t\texit(0);\n\t\t\t}\nEOF\n\t\tif $CC_FOR_BUILD -o $dummy $dummy.c && SYSTEM_NAME=`$dummy`\n\t\tthen\n\t\t\techo \"$SYSTEM_NAME\"\n\t\telse\n\t\t\techo rs6000-ibm-aix3.2.5\n\t\tfi\n\telif grep bos324 /usr/include/stdio.h >/dev/null 2>&1; then\n\t\techo rs6000-ibm-aix3.2.4\n\telse\n\t\techo rs6000-ibm-aix3.2\n\tfi\n\texit ;;\n    *:AIX:*:[4567])\n\tIBM_CPU_ID=`/usr/sbin/lsdev -C -c processor -S available | sed 1q | awk '{ print $1 }'`\n\tif /usr/sbin/lsattr -El ${IBM_CPU_ID} | grep ' POWER' >/dev/null 2>&1; then\n\t\tIBM_ARCH=rs6000\n\telse\n\t\tIBM_ARCH=powerpc\n\tfi\n\tif [ -x /usr/bin/oslevel ] ; then\n\t\tIBM_REV=`/usr/bin/oslevel`\n\telse\n\t\tIBM_REV=${UNAME_VERSION}.${UNAME_RELEASE}\n\tfi\n\techo ${IBM_ARCH}-ibm-aix${IBM_REV}\n\texit ;;\n    *:AIX:*:*)\n\techo rs6000-ibm-aix\n\texit ;;\n    ibmrt:4.4BSD:*|romp-ibm:BSD:*)\n\techo romp-ibm-bsd4.4\n\texit ;;\n    ibmrt:*BSD:*|romp-ibm:BSD:*)            # covers RT/PC BSD and\n\techo romp-ibm-bsd${UNAME_RELEASE}   # 4.3 with uname added to\n\texit ;;                             # report: romp-ibm BSD 4.3\n    *:BOSX:*:*)\n\techo rs6000-bull-bosx\n\texit ;;\n    DPX/2?00:B.O.S.:*:*)\n\techo m68k-bull-sysv3\n\texit ;;\n    9000/[34]??:4.3bsd:1.*:*)\n\techo m68k-hp-bsd\n\texit ;;\n    hp300:4.4BSD:*:* | 9000/[34]??:4.3bsd:2.*:*)\n\techo m68k-hp-bsd4.4\n\texit ;;\n    9000/[34678]??:HP-UX:*:*)\n\tHPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'`\n\tcase \"${UNAME_MACHINE}\" in\n\t    9000/31? )            HP_ARCH=m68000 ;;\n\t    9000/[34]?? )         HP_ARCH=m68k ;;\n\t    9000/[678][0-9][0-9])\n\t\tif [ -x /usr/bin/getconf ]; then\n\t\t    sc_cpu_version=`/usr/bin/getconf SC_CPU_VERSION 2>/dev/null`\n\t\t    sc_kernel_bits=`/usr/bin/getconf SC_KERNEL_BITS 2>/dev/null`\n\t\t    case \"${sc_cpu_version}\" in\n\t\t      523) HP_ARCH=\"hppa1.0\" ;; # CPU_PA_RISC1_0\n\t\t      528) HP_ARCH=\"hppa1.1\" ;; # CPU_PA_RISC1_1\n\t\t      532)                      # CPU_PA_RISC2_0\n\t\t\tcase \"${sc_kernel_bits}\" in\n\t\t\t  32) HP_ARCH=\"hppa2.0n\" ;;\n\t\t\t  64) HP_ARCH=\"hppa2.0w\" ;;\n\t\t\t  '') HP_ARCH=\"hppa2.0\" ;;   # HP-UX 10.20\n\t\t\tesac ;;\n\t\t    esac\n\t\tfi\n\t\tif [ \"${HP_ARCH}\" = \"\" ]; then\n\t\t    eval $set_cc_for_build\n\t\t    sed 's/^\t\t//' << EOF >$dummy.c\n\n\t\t#define _HPUX_SOURCE\n\t\t#include <stdlib.h>\n\t\t#include <unistd.h>\n\n\t\tint main ()\n\t\t{\n\t\t#if defined(_SC_KERNEL_BITS)\n\t\t    long bits = sysconf(_SC_KERNEL_BITS);\n\t\t#endif\n\t\t    long cpu  = sysconf (_SC_CPU_VERSION);\n\n\t\t    switch (cpu)\n\t\t\t{\n\t\t\tcase CPU_PA_RISC1_0: puts (\"hppa1.0\"); break;\n\t\t\tcase CPU_PA_RISC1_1: puts (\"hppa1.1\"); break;\n\t\t\tcase CPU_PA_RISC2_0:\n\t\t#if defined(_SC_KERNEL_BITS)\n\t\t\t    switch (bits)\n\t\t\t\t{\n\t\t\t\tcase 64: puts (\"hppa2.0w\"); break;\n\t\t\t\tcase 32: puts (\"hppa2.0n\"); break;\n\t\t\t\tdefault: puts (\"hppa2.0\"); break;\n\t\t\t\t} break;\n\t\t#else  /* !defined(_SC_KERNEL_BITS) */\n\t\t\t    puts (\"hppa2.0\"); break;\n\t\t#endif\n\t\t\tdefault: puts (\"hppa1.0\"); break;\n\t\t\t}\n\t\t    exit (0);\n\t\t}\nEOF\n\t\t    (CCOPTS= $CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null) && HP_ARCH=`$dummy`\n\t\t    test -z \"$HP_ARCH\" && HP_ARCH=hppa\n\t\tfi ;;\n\tesac\n\tif [ ${HP_ARCH} = \"hppa2.0w\" ]\n\tthen\n\t    eval $set_cc_for_build\n\n\t    # hppa2.0w-hp-hpux* has a 64-bit kernel and a compiler generating\n\t    # 32-bit code.  hppa64-hp-hpux* has the same kernel and a compiler\n\t    # generating 64-bit code.  GNU and HP use different nomenclature:\n\t    #\n\t    # $ CC_FOR_BUILD=cc ./config.guess\n\t    # => hppa2.0w-hp-hpux11.23\n\t    # $ CC_FOR_BUILD=\"cc +DA2.0w\" ./config.guess\n\t    # => hppa64-hp-hpux11.23\n\n\t    if echo __LP64__ | (CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) |\n\t\tgrep -q __LP64__\n\t    then\n\t\tHP_ARCH=\"hppa2.0w\"\n\t    else\n\t\tHP_ARCH=\"hppa64\"\n\t    fi\n\tfi\n\techo ${HP_ARCH}-hp-hpux${HPUX_REV}\n\texit ;;\n    ia64:HP-UX:*:*)\n\tHPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'`\n\techo ia64-hp-hpux${HPUX_REV}\n\texit ;;\n    3050*:HI-UX:*:*)\n\teval $set_cc_for_build\n\tsed 's/^\t//' << EOF >$dummy.c\n\t#include <unistd.h>\n\tint\n\tmain ()\n\t{\n\t  long cpu = sysconf (_SC_CPU_VERSION);\n\t  /* The order matters, because CPU_IS_HP_MC68K erroneously returns\n\t     true for CPU_PA_RISC1_0.  CPU_IS_PA_RISC returns correct\n\t     results, however.  */\n\t  if (CPU_IS_PA_RISC (cpu))\n\t    {\n\t      switch (cpu)\n\t\t{\n\t\t  case CPU_PA_RISC1_0: puts (\"hppa1.0-hitachi-hiuxwe2\"); break;\n\t\t  case CPU_PA_RISC1_1: puts (\"hppa1.1-hitachi-hiuxwe2\"); break;\n\t\t  case CPU_PA_RISC2_0: puts (\"hppa2.0-hitachi-hiuxwe2\"); break;\n\t\t  default: puts (\"hppa-hitachi-hiuxwe2\"); break;\n\t\t}\n\t    }\n\t  else if (CPU_IS_HP_MC68K (cpu))\n\t    puts (\"m68k-hitachi-hiuxwe2\");\n\t  else puts (\"unknown-hitachi-hiuxwe2\");\n\t  exit (0);\n\t}\nEOF\n\t$CC_FOR_BUILD -o $dummy $dummy.c && SYSTEM_NAME=`$dummy` &&\n\t\t{ echo \"$SYSTEM_NAME\"; exit; }\n\techo unknown-hitachi-hiuxwe2\n\texit ;;\n    9000/7??:4.3bsd:*:* | 9000/8?[79]:4.3bsd:*:* )\n\techo hppa1.1-hp-bsd\n\texit ;;\n    9000/8??:4.3bsd:*:*)\n\techo hppa1.0-hp-bsd\n\texit ;;\n    *9??*:MPE/iX:*:* | *3000*:MPE/iX:*:*)\n\techo hppa1.0-hp-mpeix\n\texit ;;\n    hp7??:OSF1:*:* | hp8?[79]:OSF1:*:* )\n\techo hppa1.1-hp-osf\n\texit ;;\n    hp8??:OSF1:*:*)\n\techo hppa1.0-hp-osf\n\texit ;;\n    i*86:OSF1:*:*)\n\tif [ -x /usr/sbin/sysversion ] ; then\n\t    echo ${UNAME_MACHINE}-unknown-osf1mk\n\telse\n\t    echo ${UNAME_MACHINE}-unknown-osf1\n\tfi\n\texit ;;\n    parisc*:Lites*:*:*)\n\techo hppa1.1-hp-lites\n\texit ;;\n    C1*:ConvexOS:*:* | convex:ConvexOS:C1*:*)\n\techo c1-convex-bsd\n\texit ;;\n    C2*:ConvexOS:*:* | convex:ConvexOS:C2*:*)\n\tif getsysinfo -f scalar_acc\n\tthen echo c32-convex-bsd\n\telse echo c2-convex-bsd\n\tfi\n\texit ;;\n    C34*:ConvexOS:*:* | convex:ConvexOS:C34*:*)\n\techo c34-convex-bsd\n\texit ;;\n    C38*:ConvexOS:*:* | convex:ConvexOS:C38*:*)\n\techo c38-convex-bsd\n\texit ;;\n    C4*:ConvexOS:*:* | convex:ConvexOS:C4*:*)\n\techo c4-convex-bsd\n\texit ;;\n    CRAY*Y-MP:*:*:*)\n\techo ymp-cray-unicos${UNAME_RELEASE} | sed -e 's/\\.[^.]*$/.X/'\n\texit ;;\n    CRAY*[A-Z]90:*:*:*)\n\techo ${UNAME_MACHINE}-cray-unicos${UNAME_RELEASE} \\\n\t| sed -e 's/CRAY.*\\([A-Z]90\\)/\\1/' \\\n\t      -e y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/ \\\n\t      -e 's/\\.[^.]*$/.X/'\n\texit ;;\n    CRAY*TS:*:*:*)\n\techo t90-cray-unicos${UNAME_RELEASE} | sed -e 's/\\.[^.]*$/.X/'\n\texit ;;\n    CRAY*T3E:*:*:*)\n\techo alphaev5-cray-unicosmk${UNAME_RELEASE} | sed -e 's/\\.[^.]*$/.X/'\n\texit ;;\n    CRAY*SV1:*:*:*)\n\techo sv1-cray-unicos${UNAME_RELEASE} | sed -e 's/\\.[^.]*$/.X/'\n\texit ;;\n    *:UNICOS/mp:*:*)\n\techo craynv-cray-unicosmp${UNAME_RELEASE} | sed -e 's/\\.[^.]*$/.X/'\n\texit ;;\n    F30[01]:UNIX_System_V:*:* | F700:UNIX_System_V:*:*)\n\tFUJITSU_PROC=`uname -m | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'`\n\tFUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\\///'`\n\tFUJITSU_REL=`echo ${UNAME_RELEASE} | sed -e 's/ /_/'`\n\techo \"${FUJITSU_PROC}-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}\"\n\texit ;;\n    5000:UNIX_System_V:4.*:*)\n\tFUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\\///'`\n\tFUJITSU_REL=`echo ${UNAME_RELEASE} | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/ /_/'`\n\techo \"sparc-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}\"\n\texit ;;\n    i*86:BSD/386:*:* | i*86:BSD/OS:*:* | *:Ascend\\ Embedded/OS:*:*)\n\techo ${UNAME_MACHINE}-pc-bsdi${UNAME_RELEASE}\n\texit ;;\n    sparc*:BSD/OS:*:*)\n\techo sparc-unknown-bsdi${UNAME_RELEASE}\n\texit ;;\n    *:BSD/OS:*:*)\n\techo ${UNAME_MACHINE}-unknown-bsdi${UNAME_RELEASE}\n\texit ;;\n    *:FreeBSD:*:*)\n\tUNAME_PROCESSOR=`/usr/bin/uname -p`\n\tcase ${UNAME_PROCESSOR} in\n\t    amd64)\n\t\techo x86_64-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;;\n\t    *)\n\t\techo ${UNAME_PROCESSOR}-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;;\n\tesac\n\texit ;;\n    i*:CYGWIN*:*)\n\techo ${UNAME_MACHINE}-pc-cygwin\n\texit ;;\n    *:MINGW64*:*)\n\techo ${UNAME_MACHINE}-pc-mingw64\n\texit ;;\n    *:MINGW*:*)\n\techo ${UNAME_MACHINE}-pc-mingw32\n\texit ;;\n    *:MSYS*:*)\n\techo ${UNAME_MACHINE}-pc-msys\n\texit ;;\n    i*:windows32*:*)\n\t# uname -m includes \"-pc\" on this system.\n\techo ${UNAME_MACHINE}-mingw32\n\texit ;;\n    i*:PW*:*)\n\techo ${UNAME_MACHINE}-pc-pw32\n\texit ;;\n    *:Interix*:*)\n\tcase ${UNAME_MACHINE} in\n\t    x86)\n\t\techo i586-pc-interix${UNAME_RELEASE}\n\t\texit ;;\n\t    authenticamd | genuineintel | EM64T)\n\t\techo x86_64-unknown-interix${UNAME_RELEASE}\n\t\texit ;;\n\t    IA64)\n\t\techo ia64-unknown-interix${UNAME_RELEASE}\n\t\texit ;;\n\tesac ;;\n    [345]86:Windows_95:* | [345]86:Windows_98:* | [345]86:Windows_NT:*)\n\techo i${UNAME_MACHINE}-pc-mks\n\texit ;;\n    8664:Windows_NT:*)\n\techo x86_64-pc-mks\n\texit ;;\n    i*:Windows_NT*:* | Pentium*:Windows_NT*:*)\n\t# How do we know it's Interix rather than the generic POSIX subsystem?\n\t# It also conflicts with pre-2.0 versions of AT&T UWIN. Should we\n\t# UNAME_MACHINE based on the output of uname instead of i386?\n\techo i586-pc-interix\n\texit ;;\n    i*:UWIN*:*)\n\techo ${UNAME_MACHINE}-pc-uwin\n\texit ;;\n    amd64:CYGWIN*:*:* | x86_64:CYGWIN*:*:*)\n\techo x86_64-unknown-cygwin\n\texit ;;\n    p*:CYGWIN*:*)\n\techo powerpcle-unknown-cygwin\n\texit ;;\n    prep*:SunOS:5.*:*)\n\techo powerpcle-unknown-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`\n\texit ;;\n    *:GNU:*:*)\n\t# the GNU system\n\techo `echo ${UNAME_MACHINE}|sed -e 's,[-/].*$,,'`-unknown-${LIBC}`echo ${UNAME_RELEASE}|sed -e 's,/.*$,,'`\n\texit ;;\n    *:GNU/*:*:*)\n\t# other systems with GNU libc and userland\n\techo ${UNAME_MACHINE}-unknown-`echo ${UNAME_SYSTEM} | sed 's,^[^/]*/,,' | tr '[A-Z]' '[a-z]'``echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`-${LIBC}\n\texit ;;\n    i*86:Minix:*:*)\n\techo ${UNAME_MACHINE}-pc-minix\n\texit ;;\n    aarch64:Linux:*:*)\n\techo ${UNAME_MACHINE}-unknown-linux-${LIBC}\n\texit ;;\n    aarch64_be:Linux:*:*)\n\tUNAME_MACHINE=aarch64_be\n\techo ${UNAME_MACHINE}-unknown-linux-${LIBC}\n\texit ;;\n    alpha:Linux:*:*)\n\tcase `sed -n '/^cpu model/s/^.*: \\(.*\\)/\\1/p' < /proc/cpuinfo` in\n\t  EV5)   UNAME_MACHINE=alphaev5 ;;\n\t  EV56)  UNAME_MACHINE=alphaev56 ;;\n\t  PCA56) UNAME_MACHINE=alphapca56 ;;\n\t  PCA57) UNAME_MACHINE=alphapca56 ;;\n\t  EV6)   UNAME_MACHINE=alphaev6 ;;\n\t  EV67)  UNAME_MACHINE=alphaev67 ;;\n\t  EV68*) UNAME_MACHINE=alphaev68 ;;\n\tesac\n\tobjdump --private-headers /bin/sh | grep -q ld.so.1\n\tif test \"$?\" = 0 ; then LIBC=\"gnulibc1\" ; fi\n\techo ${UNAME_MACHINE}-unknown-linux-${LIBC}\n\texit ;;\n    arc:Linux:*:* | arceb:Linux:*:*)\n\techo ${UNAME_MACHINE}-unknown-linux-${LIBC}\n\texit ;;\n    arm*:Linux:*:*)\n\teval $set_cc_for_build\n\tif echo __ARM_EABI__ | $CC_FOR_BUILD -E - 2>/dev/null \\\n\t    | grep -q __ARM_EABI__\n\tthen\n\t    echo ${UNAME_MACHINE}-unknown-linux-${LIBC}\n\telse\n\t    if echo __ARM_PCS_VFP | $CC_FOR_BUILD -E - 2>/dev/null \\\n\t\t| grep -q __ARM_PCS_VFP\n\t    then\n\t\techo ${UNAME_MACHINE}-unknown-linux-${LIBC}eabi\n\t    else\n\t\techo ${UNAME_MACHINE}-unknown-linux-${LIBC}eabihf\n\t    fi\n\tfi\n\texit ;;\n    avr32*:Linux:*:*)\n\techo ${UNAME_MACHINE}-unknown-linux-${LIBC}\n\texit ;;\n    cris:Linux:*:*)\n\techo ${UNAME_MACHINE}-axis-linux-${LIBC}\n\texit ;;\n    crisv32:Linux:*:*)\n\techo ${UNAME_MACHINE}-axis-linux-${LIBC}\n\texit ;;\n    frv:Linux:*:*)\n\techo ${UNAME_MACHINE}-unknown-linux-${LIBC}\n\texit ;;\n    hexagon:Linux:*:*)\n\techo ${UNAME_MACHINE}-unknown-linux-${LIBC}\n\texit ;;\n    i*86:Linux:*:*)\n\techo ${UNAME_MACHINE}-pc-linux-${LIBC}\n\texit ;;\n    ia64:Linux:*:*)\n\techo ${UNAME_MACHINE}-unknown-linux-${LIBC}\n\texit ;;\n    m32r*:Linux:*:*)\n\techo ${UNAME_MACHINE}-unknown-linux-${LIBC}\n\texit ;;\n    m68*:Linux:*:*)\n\techo ${UNAME_MACHINE}-unknown-linux-${LIBC}\n\texit ;;\n    mips:Linux:*:* | mips64:Linux:*:*)\n\teval $set_cc_for_build\n\tsed 's/^\t//' << EOF >$dummy.c\n\t#undef CPU\n\t#undef ${UNAME_MACHINE}\n\t#undef ${UNAME_MACHINE}el\n\t#if defined(__MIPSEL__) || defined(__MIPSEL) || defined(_MIPSEL) || defined(MIPSEL)\n\tCPU=${UNAME_MACHINE}el\n\t#else\n\t#if defined(__MIPSEB__) || defined(__MIPSEB) || defined(_MIPSEB) || defined(MIPSEB)\n\tCPU=${UNAME_MACHINE}\n\t#else\n\tCPU=\n\t#endif\n\t#endif\nEOF\n\teval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep '^CPU'`\n\ttest x\"${CPU}\" != x && { echo \"${CPU}-unknown-linux-${LIBC}\"; exit; }\n\t;;\n    openrisc*:Linux:*:*)\n\techo or1k-unknown-linux-${LIBC}\n\texit ;;\n    or32:Linux:*:* | or1k*:Linux:*:*)\n\techo ${UNAME_MACHINE}-unknown-linux-${LIBC}\n\texit ;;\n    padre:Linux:*:*)\n\techo sparc-unknown-linux-${LIBC}\n\texit ;;\n    parisc64:Linux:*:* | hppa64:Linux:*:*)\n\techo hppa64-unknown-linux-${LIBC}\n\texit ;;\n    parisc:Linux:*:* | hppa:Linux:*:*)\n\t# Look for CPU level\n\tcase `grep '^cpu[^a-z]*:' /proc/cpuinfo 2>/dev/null | cut -d' ' -f2` in\n\t  PA7*) echo hppa1.1-unknown-linux-${LIBC} ;;\n\t  PA8*) echo hppa2.0-unknown-linux-${LIBC} ;;\n\t  *)    echo hppa-unknown-linux-${LIBC} ;;\n\tesac\n\texit ;;\n    ppc64:Linux:*:*)\n\techo powerpc64-unknown-linux-${LIBC}\n\texit ;;\n    ppc:Linux:*:*)\n\techo powerpc-unknown-linux-${LIBC}\n\texit ;;\n    ppc64le:Linux:*:*)\n\techo powerpc64le-unknown-linux-${LIBC}\n\texit ;;\n    ppcle:Linux:*:*)\n\techo powerpcle-unknown-linux-${LIBC}\n\texit ;;\n    s390:Linux:*:* | s390x:Linux:*:*)\n\techo ${UNAME_MACHINE}-ibm-linux-${LIBC}\n\texit ;;\n    sh64*:Linux:*:*)\n\techo ${UNAME_MACHINE}-unknown-linux-${LIBC}\n\texit ;;\n    sh*:Linux:*:*)\n\techo ${UNAME_MACHINE}-unknown-linux-${LIBC}\n\texit ;;\n    sparc:Linux:*:* | sparc64:Linux:*:*)\n\techo ${UNAME_MACHINE}-unknown-linux-${LIBC}\n\texit ;;\n    tile*:Linux:*:*)\n\techo ${UNAME_MACHINE}-unknown-linux-${LIBC}\n\texit ;;\n    vax:Linux:*:*)\n\techo ${UNAME_MACHINE}-dec-linux-${LIBC}\n\texit ;;\n    x86_64:Linux:*:*)\n\techo ${UNAME_MACHINE}-unknown-linux-${LIBC}\n\texit ;;\n    xtensa*:Linux:*:*)\n\techo ${UNAME_MACHINE}-unknown-linux-${LIBC}\n\texit ;;\n    i*86:DYNIX/ptx:4*:*)\n\t# ptx 4.0 does uname -s correctly, with DYNIX/ptx in there.\n\t# earlier versions are messed up and put the nodename in both\n\t# sysname and nodename.\n\techo i386-sequent-sysv4\n\texit ;;\n    i*86:UNIX_SV:4.2MP:2.*)\n\t# Unixware is an offshoot of SVR4, but it has its own version\n\t# number series starting with 2...\n\t# I am not positive that other SVR4 systems won't match this,\n\t# I just have to hope.  -- rms.\n\t# Use sysv4.2uw... so that sysv4* matches it.\n\techo ${UNAME_MACHINE}-pc-sysv4.2uw${UNAME_VERSION}\n\texit ;;\n    i*86:OS/2:*:*)\n\t# If we were able to find `uname', then EMX Unix compatibility\n\t# is probably installed.\n\techo ${UNAME_MACHINE}-pc-os2-emx\n\texit ;;\n    i*86:XTS-300:*:STOP)\n\techo ${UNAME_MACHINE}-unknown-stop\n\texit ;;\n    i*86:atheos:*:*)\n\techo ${UNAME_MACHINE}-unknown-atheos\n\texit ;;\n    i*86:syllable:*:*)\n\techo ${UNAME_MACHINE}-pc-syllable\n\texit ;;\n    i*86:LynxOS:2.*:* | i*86:LynxOS:3.[01]*:* | i*86:LynxOS:4.[02]*:*)\n\techo i386-unknown-lynxos${UNAME_RELEASE}\n\texit ;;\n    i*86:*DOS:*:*)\n\techo ${UNAME_MACHINE}-pc-msdosdjgpp\n\texit ;;\n    i*86:*:4.*:* | i*86:SYSTEM_V:4.*:*)\n\tUNAME_REL=`echo ${UNAME_RELEASE} | sed 's/\\/MP$//'`\n\tif grep Novell /usr/include/link.h >/dev/null 2>/dev/null; then\n\t\techo ${UNAME_MACHINE}-univel-sysv${UNAME_REL}\n\telse\n\t\techo ${UNAME_MACHINE}-pc-sysv${UNAME_REL}\n\tfi\n\texit ;;\n    i*86:*:5:[678]*)\n\t# UnixWare 7.x, OpenUNIX and OpenServer 6.\n\tcase `/bin/uname -X | grep \"^Machine\"` in\n\t    *486*)\t     UNAME_MACHINE=i486 ;;\n\t    *Pentium)\t     UNAME_MACHINE=i586 ;;\n\t    *Pent*|*Celeron) UNAME_MACHINE=i686 ;;\n\tesac\n\techo ${UNAME_MACHINE}-unknown-sysv${UNAME_RELEASE}${UNAME_SYSTEM}${UNAME_VERSION}\n\texit ;;\n    i*86:*:3.2:*)\n\tif test -f /usr/options/cb.name; then\n\t\tUNAME_REL=`sed -n 's/.*Version //p' </usr/options/cb.name`\n\t\techo ${UNAME_MACHINE}-pc-isc$UNAME_REL\n\telif /bin/uname -X 2>/dev/null >/dev/null ; then\n\t\tUNAME_REL=`(/bin/uname -X|grep Release|sed -e 's/.*= //')`\n\t\t(/bin/uname -X|grep i80486 >/dev/null) && UNAME_MACHINE=i486\n\t\t(/bin/uname -X|grep '^Machine.*Pentium' >/dev/null) \\\n\t\t\t&& UNAME_MACHINE=i586\n\t\t(/bin/uname -X|grep '^Machine.*Pent *II' >/dev/null) \\\n\t\t\t&& UNAME_MACHINE=i686\n\t\t(/bin/uname -X|grep '^Machine.*Pentium Pro' >/dev/null) \\\n\t\t\t&& UNAME_MACHINE=i686\n\t\techo ${UNAME_MACHINE}-pc-sco$UNAME_REL\n\telse\n\t\techo ${UNAME_MACHINE}-pc-sysv32\n\tfi\n\texit ;;\n    pc:*:*:*)\n\t# Left here for compatibility:\n\t# uname -m prints for DJGPP always 'pc', but it prints nothing about\n\t# the processor, so we play safe by assuming i586.\n\t# Note: whatever this is, it MUST be the same as what config.sub\n\t# prints for the \"djgpp\" host, or else GDB configury will decide that\n\t# this is a cross-build.\n\techo i586-pc-msdosdjgpp\n\texit ;;\n    Intel:Mach:3*:*)\n\techo i386-pc-mach3\n\texit ;;\n    paragon:*:*:*)\n\techo i860-intel-osf1\n\texit ;;\n    i860:*:4.*:*) # i860-SVR4\n\tif grep Stardent /usr/include/sys/uadmin.h >/dev/null 2>&1 ; then\n\t  echo i860-stardent-sysv${UNAME_RELEASE} # Stardent Vistra i860-SVR4\n\telse # Add other i860-SVR4 vendors below as they are discovered.\n\t  echo i860-unknown-sysv${UNAME_RELEASE}  # Unknown i860-SVR4\n\tfi\n\texit ;;\n    mini*:CTIX:SYS*5:*)\n\t# \"miniframe\"\n\techo m68010-convergent-sysv\n\texit ;;\n    mc68k:UNIX:SYSTEM5:3.51m)\n\techo m68k-convergent-sysv\n\texit ;;\n    M680?0:D-NIX:5.3:*)\n\techo m68k-diab-dnix\n\texit ;;\n    M68*:*:R3V[5678]*:*)\n\ttest -r /sysV68 && { echo 'm68k-motorola-sysv'; exit; } ;;\n    3[345]??:*:4.0:3.0 | 3[34]??A:*:4.0:3.0 | 3[34]??,*:*:4.0:3.0 | 3[34]??/*:*:4.0:3.0 | 4400:*:4.0:3.0 | 4850:*:4.0:3.0 | SKA40:*:4.0:3.0 | SDS2:*:4.0:3.0 | SHG2:*:4.0:3.0 | S7501*:*:4.0:3.0)\n\tOS_REL=''\n\ttest -r /etc/.relid \\\n\t&& OS_REL=.`sed -n 's/[^ ]* [^ ]* \\([0-9][0-9]\\).*/\\1/p' < /etc/.relid`\n\t/bin/uname -p 2>/dev/null | grep 86 >/dev/null \\\n\t  && { echo i486-ncr-sysv4.3${OS_REL}; exit; }\n\t/bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \\\n\t  && { echo i586-ncr-sysv4.3${OS_REL}; exit; } ;;\n    3[34]??:*:4.0:* | 3[34]??,*:*:4.0:*)\n\t/bin/uname -p 2>/dev/null | grep 86 >/dev/null \\\n\t  && { echo i486-ncr-sysv4; exit; } ;;\n    NCR*:*:4.2:* | MPRAS*:*:4.2:*)\n\tOS_REL='.3'\n\ttest -r /etc/.relid \\\n\t    && OS_REL=.`sed -n 's/[^ ]* [^ ]* \\([0-9][0-9]\\).*/\\1/p' < /etc/.relid`\n\t/bin/uname -p 2>/dev/null | grep 86 >/dev/null \\\n\t    && { echo i486-ncr-sysv4.3${OS_REL}; exit; }\n\t/bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \\\n\t    && { echo i586-ncr-sysv4.3${OS_REL}; exit; }\n\t/bin/uname -p 2>/dev/null | /bin/grep pteron >/dev/null \\\n\t    && { echo i586-ncr-sysv4.3${OS_REL}; exit; } ;;\n    m68*:LynxOS:2.*:* | m68*:LynxOS:3.0*:*)\n\techo m68k-unknown-lynxos${UNAME_RELEASE}\n\texit ;;\n    mc68030:UNIX_System_V:4.*:*)\n\techo m68k-atari-sysv4\n\texit ;;\n    TSUNAMI:LynxOS:2.*:*)\n\techo sparc-unknown-lynxos${UNAME_RELEASE}\n\texit ;;\n    rs6000:LynxOS:2.*:*)\n\techo rs6000-unknown-lynxos${UNAME_RELEASE}\n\texit ;;\n    PowerPC:LynxOS:2.*:* | PowerPC:LynxOS:3.[01]*:* | PowerPC:LynxOS:4.[02]*:*)\n\techo powerpc-unknown-lynxos${UNAME_RELEASE}\n\texit ;;\n    SM[BE]S:UNIX_SV:*:*)\n\techo mips-dde-sysv${UNAME_RELEASE}\n\texit ;;\n    RM*:ReliantUNIX-*:*:*)\n\techo mips-sni-sysv4\n\texit ;;\n    RM*:SINIX-*:*:*)\n\techo mips-sni-sysv4\n\texit ;;\n    *:SINIX-*:*:*)\n\tif uname -p 2>/dev/null >/dev/null ; then\n\t\tUNAME_MACHINE=`(uname -p) 2>/dev/null`\n\t\techo ${UNAME_MACHINE}-sni-sysv4\n\telse\n\t\techo ns32k-sni-sysv\n\tfi\n\texit ;;\n    PENTIUM:*:4.0*:*)\t# Unisys `ClearPath HMP IX 4000' SVR4/MP effort\n\t\t\t# says <Richard.M.Bartel@ccMail.Census.GOV>\n\techo i586-unisys-sysv4\n\texit ;;\n    *:UNIX_System_V:4*:FTX*)\n\t# From Gerald Hewes <hewes@openmarket.com>.\n\t# How about differentiating between stratus architectures? -djm\n\techo hppa1.1-stratus-sysv4\n\texit ;;\n    *:*:*:FTX*)\n\t# From seanf@swdc.stratus.com.\n\techo i860-stratus-sysv4\n\texit ;;\n    i*86:VOS:*:*)\n\t# From Paul.Green@stratus.com.\n\techo ${UNAME_MACHINE}-stratus-vos\n\texit ;;\n    *:VOS:*:*)\n\t# From Paul.Green@stratus.com.\n\techo hppa1.1-stratus-vos\n\texit ;;\n    mc68*:A/UX:*:*)\n\techo m68k-apple-aux${UNAME_RELEASE}\n\texit ;;\n    news*:NEWS-OS:6*:*)\n\techo mips-sony-newsos6\n\texit ;;\n    R[34]000:*System_V*:*:* | R4000:UNIX_SYSV:*:* | R*000:UNIX_SV:*:*)\n\tif [ -d /usr/nec ]; then\n\t\techo mips-nec-sysv${UNAME_RELEASE}\n\telse\n\t\techo mips-unknown-sysv${UNAME_RELEASE}\n\tfi\n\texit ;;\n    BeBox:BeOS:*:*)\t# BeOS running on hardware made by Be, PPC only.\n\techo powerpc-be-beos\n\texit ;;\n    BeMac:BeOS:*:*)\t# BeOS running on Mac or Mac clone, PPC only.\n\techo powerpc-apple-beos\n\texit ;;\n    BePC:BeOS:*:*)\t# BeOS running on Intel PC compatible.\n\techo i586-pc-beos\n\texit ;;\n    BePC:Haiku:*:*)\t# Haiku running on Intel PC compatible.\n\techo i586-pc-haiku\n\texit ;;\n    x86_64:Haiku:*:*)\n\techo x86_64-unknown-haiku\n\texit ;;\n    SX-4:SUPER-UX:*:*)\n\techo sx4-nec-superux${UNAME_RELEASE}\n\texit ;;\n    SX-5:SUPER-UX:*:*)\n\techo sx5-nec-superux${UNAME_RELEASE}\n\texit ;;\n    SX-6:SUPER-UX:*:*)\n\techo sx6-nec-superux${UNAME_RELEASE}\n\texit ;;\n    SX-7:SUPER-UX:*:*)\n\techo sx7-nec-superux${UNAME_RELEASE}\n\texit ;;\n    SX-8:SUPER-UX:*:*)\n\techo sx8-nec-superux${UNAME_RELEASE}\n\texit ;;\n    SX-8R:SUPER-UX:*:*)\n\techo sx8r-nec-superux${UNAME_RELEASE}\n\texit ;;\n    Power*:Rhapsody:*:*)\n\techo powerpc-apple-rhapsody${UNAME_RELEASE}\n\texit ;;\n    *:Rhapsody:*:*)\n\techo ${UNAME_MACHINE}-apple-rhapsody${UNAME_RELEASE}\n\texit ;;\n    *:Darwin:*:*)\n\tUNAME_PROCESSOR=`uname -p` || UNAME_PROCESSOR=unknown\n\teval $set_cc_for_build\n\tif test \"$UNAME_PROCESSOR\" = unknown ; then\n\t    UNAME_PROCESSOR=powerpc\n\tfi\n\tif test `echo \"$UNAME_RELEASE\" | sed -e 's/\\..*//'` -le 10 ; then\n\t    if [ \"$CC_FOR_BUILD\" != 'no_compiler_found' ]; then\n\t\tif (echo '#ifdef __LP64__'; echo IS_64BIT_ARCH; echo '#endif') | \\\n\t\t    (CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) | \\\n\t\t    grep IS_64BIT_ARCH >/dev/null\n\t\tthen\n\t\t    case $UNAME_PROCESSOR in\n\t\t\ti386) UNAME_PROCESSOR=x86_64 ;;\n\t\t\tpowerpc) UNAME_PROCESSOR=powerpc64 ;;\n\t\t    esac\n\t\tfi\n\t    fi\n\telif test \"$UNAME_PROCESSOR\" = i386 ; then\n\t    # Avoid executing cc on OS X 10.9, as it ships with a stub\n\t    # that puts up a graphical alert prompting to install\n\t    # developer tools.  Any system running Mac OS X 10.7 or\n\t    # later (Darwin 11 and later) is required to have a 64-bit\n\t    # processor. This is not true of the ARM version of Darwin\n\t    # that Apple uses in portable devices.\n\t    UNAME_PROCESSOR=x86_64\n\tfi\n\techo ${UNAME_PROCESSOR}-apple-darwin${UNAME_RELEASE}\n\texit ;;\n    *:procnto*:*:* | *:QNX:[0123456789]*:*)\n\tUNAME_PROCESSOR=`uname -p`\n\tif test \"$UNAME_PROCESSOR\" = \"x86\"; then\n\t\tUNAME_PROCESSOR=i386\n\t\tUNAME_MACHINE=pc\n\tfi\n\techo ${UNAME_PROCESSOR}-${UNAME_MACHINE}-nto-qnx${UNAME_RELEASE}\n\texit ;;\n    *:QNX:*:4*)\n\techo i386-pc-qnx\n\texit ;;\n    NEO-?:NONSTOP_KERNEL:*:*)\n\techo neo-tandem-nsk${UNAME_RELEASE}\n\texit ;;\n    NSE-*:NONSTOP_KERNEL:*:*)\n\techo nse-tandem-nsk${UNAME_RELEASE}\n\texit ;;\n    NSR-?:NONSTOP_KERNEL:*:*)\n\techo nsr-tandem-nsk${UNAME_RELEASE}\n\texit ;;\n    *:NonStop-UX:*:*)\n\techo mips-compaq-nonstopux\n\texit ;;\n    BS2000:POSIX*:*:*)\n\techo bs2000-siemens-sysv\n\texit ;;\n    DS/*:UNIX_System_V:*:*)\n\techo ${UNAME_MACHINE}-${UNAME_SYSTEM}-${UNAME_RELEASE}\n\texit ;;\n    *:Plan9:*:*)\n\t# \"uname -m\" is not consistent, so use $cputype instead. 386\n\t# is converted to i386 for consistency with other x86\n\t# operating systems.\n\tif test \"$cputype\" = \"386\"; then\n\t    UNAME_MACHINE=i386\n\telse\n\t    UNAME_MACHINE=\"$cputype\"\n\tfi\n\techo ${UNAME_MACHINE}-unknown-plan9\n\texit ;;\n    *:TOPS-10:*:*)\n\techo pdp10-unknown-tops10\n\texit ;;\n    *:TENEX:*:*)\n\techo pdp10-unknown-tenex\n\texit ;;\n    KS10:TOPS-20:*:* | KL10:TOPS-20:*:* | TYPE4:TOPS-20:*:*)\n\techo pdp10-dec-tops20\n\texit ;;\n    XKL-1:TOPS-20:*:* | TYPE5:TOPS-20:*:*)\n\techo pdp10-xkl-tops20\n\texit ;;\n    *:TOPS-20:*:*)\n\techo pdp10-unknown-tops20\n\texit ;;\n    *:ITS:*:*)\n\techo pdp10-unknown-its\n\texit ;;\n    SEI:*:*:SEIUX)\n\techo mips-sei-seiux${UNAME_RELEASE}\n\texit ;;\n    *:DragonFly:*:*)\n\techo ${UNAME_MACHINE}-unknown-dragonfly`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`\n\texit ;;\n    *:*VMS:*:*)\n\tUNAME_MACHINE=`(uname -p) 2>/dev/null`\n\tcase \"${UNAME_MACHINE}\" in\n\t    A*) echo alpha-dec-vms ; exit ;;\n\t    I*) echo ia64-dec-vms ; exit ;;\n\t    V*) echo vax-dec-vms ; exit ;;\n\tesac ;;\n    *:XENIX:*:SysV)\n\techo i386-pc-xenix\n\texit ;;\n    i*86:skyos:*:*)\n\techo ${UNAME_MACHINE}-pc-skyos`echo ${UNAME_RELEASE}` | sed -e 's/ .*$//'\n\texit ;;\n    i*86:rdos:*:*)\n\techo ${UNAME_MACHINE}-pc-rdos\n\texit ;;\n    i*86:AROS:*:*)\n\techo ${UNAME_MACHINE}-pc-aros\n\texit ;;\n    x86_64:VMkernel:*:*)\n\techo ${UNAME_MACHINE}-unknown-esx\n\texit ;;\nesac\n\ncat >&2 <<EOF\n$0: unable to guess system type\n\nThis script, last modified $timestamp, has failed to recognize\nthe operating system you are using. It is advised that you\ndownload the most up to date version of the config scripts from\n\n  http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.guess;hb=HEAD\nand\n  http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.sub;hb=HEAD\n\nIf the version you run ($0) is already up to date, please\nsend the following data and any information you think might be\npertinent to <config-patches@gnu.org> in order to provide the needed\ninformation to handle your system.\n\nconfig.guess timestamp = $timestamp\n\nuname -m = `(uname -m) 2>/dev/null || echo unknown`\nuname -r = `(uname -r) 2>/dev/null || echo unknown`\nuname -s = `(uname -s) 2>/dev/null || echo unknown`\nuname -v = `(uname -v) 2>/dev/null || echo unknown`\n\n/usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null`\n/bin/uname -X     = `(/bin/uname -X) 2>/dev/null`\n\nhostinfo               = `(hostinfo) 2>/dev/null`\n/bin/universe          = `(/bin/universe) 2>/dev/null`\n/usr/bin/arch -k       = `(/usr/bin/arch -k) 2>/dev/null`\n/bin/arch              = `(/bin/arch) 2>/dev/null`\n/usr/bin/oslevel       = `(/usr/bin/oslevel) 2>/dev/null`\n/usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null`\n\nUNAME_MACHINE = ${UNAME_MACHINE}\nUNAME_RELEASE = ${UNAME_RELEASE}\nUNAME_SYSTEM  = ${UNAME_SYSTEM}\nUNAME_VERSION = ${UNAME_VERSION}\nEOF\n\nexit 1\n\n# Local variables:\n# eval: (add-hook 'write-file-hooks 'time-stamp)\n# time-stamp-start: \"timestamp='\"\n# time-stamp-format: \"%:y-%02m-%02d\"\n# time-stamp-end: \"'\"\n# End:\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.8/deps/jemalloc/config.stamp.in",
    "content": ""
  },
  {
    "path": "extern/deprecated/redis-3.2.8/deps/jemalloc/config.sub",
    "content": "#! /bin/sh\n# Configuration validation subroutine script.\n#   Copyright 1992-2014 Free Software Foundation, Inc.\n\ntimestamp='2014-05-01'\n\n# This file is free software; you can redistribute it and/or modify it\n# under the terms of the GNU General Public License as published by\n# the Free Software Foundation; either version 3 of the License, or\n# (at your option) any later version.\n#\n# This program is distributed in the hope that it will be useful, but\n# WITHOUT ANY WARRANTY; without even the implied warranty of\n# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n# General Public License for more details.\n#\n# You should have received a copy of the GNU General Public License\n# along with this program; if not, see <http://www.gnu.org/licenses/>.\n#\n# As a special exception to the GNU General Public License, if you\n# distribute this file as part of a program that contains a\n# configuration script generated by Autoconf, you may include it under\n# the same distribution terms that you use for the rest of that\n# program.  This Exception is an additional permission under section 7\n# of the GNU General Public License, version 3 (\"GPLv3\").\n\n\n# Please send patches with a ChangeLog entry to config-patches@gnu.org.\n#\n# Configuration subroutine to validate and canonicalize a configuration type.\n# Supply the specified configuration type as an argument.\n# If it is invalid, we print an error message on stderr and exit with code 1.\n# Otherwise, we print the canonical config type on stdout and succeed.\n\n# You can get the latest version of this script from:\n# http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.sub;hb=HEAD\n\n# This file is supposed to be the same for all GNU packages\n# and recognize all the CPU types, system types and aliases\n# that are meaningful with *any* GNU software.\n# Each package is responsible for reporting which valid configurations\n# it does not support.  The user should be able to distinguish\n# a failure to support a valid configuration from a meaningless\n# configuration.\n\n# The goal of this file is to map all the various variations of a given\n# machine specification into a single specification in the form:\n#\tCPU_TYPE-MANUFACTURER-OPERATING_SYSTEM\n# or in some cases, the newer four-part form:\n#\tCPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM\n# It is wrong to echo any other type of specification.\n\nme=`echo \"$0\" | sed -e 's,.*/,,'`\n\nusage=\"\\\nUsage: $0 [OPTION] CPU-MFR-OPSYS\n       $0 [OPTION] ALIAS\n\nCanonicalize a configuration name.\n\nOperation modes:\n  -h, --help         print this help, then exit\n  -t, --time-stamp   print date of last modification, then exit\n  -v, --version      print version number, then exit\n\nReport bugs and patches to <config-patches@gnu.org>.\"\n\nversion=\"\\\nGNU config.sub ($timestamp)\n\nCopyright 1992-2014 Free Software Foundation, Inc.\n\nThis is free software; see the source for copying conditions.  There is NO\nwarranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\"\n\nhelp=\"\nTry \\`$me --help' for more information.\"\n\n# Parse command line\nwhile test $# -gt 0 ; do\n  case $1 in\n    --time-stamp | --time* | -t )\n       echo \"$timestamp\" ; exit ;;\n    --version | -v )\n       echo \"$version\" ; exit ;;\n    --help | --h* | -h )\n       echo \"$usage\"; exit ;;\n    -- )     # Stop option processing\n       shift; break ;;\n    - )\t# Use stdin as input.\n       break ;;\n    -* )\n       echo \"$me: invalid option $1$help\"\n       exit 1 ;;\n\n    *local*)\n       # First pass through any local machine types.\n       echo $1\n       exit ;;\n\n    * )\n       break ;;\n  esac\ndone\n\ncase $# in\n 0) echo \"$me: missing argument$help\" >&2\n    exit 1;;\n 1) ;;\n *) echo \"$me: too many arguments$help\" >&2\n    exit 1;;\nesac\n\n# Separate what the user gave into CPU-COMPANY and OS or KERNEL-OS (if any).\n# Here we must recognize all the valid KERNEL-OS combinations.\nmaybe_os=`echo $1 | sed 's/^\\(.*\\)-\\([^-]*-[^-]*\\)$/\\2/'`\ncase $maybe_os in\n  nto-qnx* | linux-gnu* | linux-android* | linux-dietlibc | linux-newlib* | \\\n  linux-musl* | linux-uclibc* | uclinux-uclibc* | uclinux-gnu* | kfreebsd*-gnu* | \\\n  knetbsd*-gnu* | netbsd*-gnu* | \\\n  kopensolaris*-gnu* | \\\n  storm-chaos* | os2-emx* | rtmk-nova*)\n    os=-$maybe_os\n    basic_machine=`echo $1 | sed 's/^\\(.*\\)-\\([^-]*-[^-]*\\)$/\\1/'`\n    ;;\n  android-linux)\n    os=-linux-android\n    basic_machine=`echo $1 | sed 's/^\\(.*\\)-\\([^-]*-[^-]*\\)$/\\1/'`-unknown\n    ;;\n  *)\n    basic_machine=`echo $1 | sed 's/-[^-]*$//'`\n    if [ $basic_machine != $1 ]\n    then os=`echo $1 | sed 's/.*-/-/'`\n    else os=; fi\n    ;;\nesac\n\n### Let's recognize common machines as not being operating systems so\n### that things like config.sub decstation-3100 work.  We also\n### recognize some manufacturers as not being operating systems, so we\n### can provide default operating systems below.\ncase $os in\n\t-sun*os*)\n\t\t# Prevent following clause from handling this invalid input.\n\t\t;;\n\t-dec* | -mips* | -sequent* | -encore* | -pc532* | -sgi* | -sony* | \\\n\t-att* | -7300* | -3300* | -delta* | -motorola* | -sun[234]* | \\\n\t-unicom* | -ibm* | -next | -hp | -isi* | -apollo | -altos* | \\\n\t-convergent* | -ncr* | -news | -32* | -3600* | -3100* | -hitachi* |\\\n\t-c[123]* | -convex* | -sun | -crds | -omron* | -dg | -ultra | -tti* | \\\n\t-harris | -dolphin | -highlevel | -gould | -cbm | -ns | -masscomp | \\\n\t-apple | -axis | -knuth | -cray | -microblaze*)\n\t\tos=\n\t\tbasic_machine=$1\n\t\t;;\n\t-bluegene*)\n\t\tos=-cnk\n\t\t;;\n\t-sim | -cisco | -oki | -wec | -winbond)\n\t\tos=\n\t\tbasic_machine=$1\n\t\t;;\n\t-scout)\n\t\t;;\n\t-wrs)\n\t\tos=-vxworks\n\t\tbasic_machine=$1\n\t\t;;\n\t-chorusos*)\n\t\tos=-chorusos\n\t\tbasic_machine=$1\n\t\t;;\n\t-chorusrdb)\n\t\tos=-chorusrdb\n\t\tbasic_machine=$1\n\t\t;;\n\t-hiux*)\n\t\tos=-hiuxwe2\n\t\t;;\n\t-sco6)\n\t\tos=-sco5v6\n\t\tbasic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`\n\t\t;;\n\t-sco5)\n\t\tos=-sco3.2v5\n\t\tbasic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`\n\t\t;;\n\t-sco4)\n\t\tos=-sco3.2v4\n\t\tbasic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`\n\t\t;;\n\t-sco3.2.[4-9]*)\n\t\tos=`echo $os | sed -e 's/sco3.2./sco3.2v/'`\n\t\tbasic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`\n\t\t;;\n\t-sco3.2v[4-9]*)\n\t\t# Don't forget version if it is 3.2v4 or newer.\n\t\tbasic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`\n\t\t;;\n\t-sco5v6*)\n\t\t# Don't forget version if it is 3.2v4 or newer.\n\t\tbasic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`\n\t\t;;\n\t-sco*)\n\t\tos=-sco3.2v2\n\t\tbasic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`\n\t\t;;\n\t-udk*)\n\t\tbasic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`\n\t\t;;\n\t-isc)\n\t\tos=-isc2.2\n\t\tbasic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`\n\t\t;;\n\t-clix*)\n\t\tbasic_machine=clipper-intergraph\n\t\t;;\n\t-isc*)\n\t\tbasic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`\n\t\t;;\n\t-lynx*178)\n\t\tos=-lynxos178\n\t\t;;\n\t-lynx*5)\n\t\tos=-lynxos5\n\t\t;;\n\t-lynx*)\n\t\tos=-lynxos\n\t\t;;\n\t-ptx*)\n\t\tbasic_machine=`echo $1 | sed -e 's/86-.*/86-sequent/'`\n\t\t;;\n\t-windowsnt*)\n\t\tos=`echo $os | sed -e 's/windowsnt/winnt/'`\n\t\t;;\n\t-psos*)\n\t\tos=-psos\n\t\t;;\n\t-mint | -mint[0-9]*)\n\t\tbasic_machine=m68k-atari\n\t\tos=-mint\n\t\t;;\nesac\n\n# Decode aliases for certain CPU-COMPANY combinations.\ncase $basic_machine in\n\t# Recognize the basic CPU types without company name.\n\t# Some are omitted here because they have special meanings below.\n\t1750a | 580 \\\n\t| a29k \\\n\t| aarch64 | aarch64_be \\\n\t| alpha | alphaev[4-8] | alphaev56 | alphaev6[78] | alphapca5[67] \\\n\t| alpha64 | alpha64ev[4-8] | alpha64ev56 | alpha64ev6[78] | alpha64pca5[67] \\\n\t| am33_2.0 \\\n\t| arc | arceb \\\n\t| arm | arm[bl]e | arme[lb] | armv[2-8] | armv[3-8][lb] | armv7[arm] \\\n\t| avr | avr32 \\\n\t| be32 | be64 \\\n\t| bfin \\\n\t| c4x | c8051 | clipper \\\n\t| d10v | d30v | dlx | dsp16xx \\\n\t| epiphany \\\n\t| fido | fr30 | frv \\\n\t| h8300 | h8500 | hppa | hppa1.[01] | hppa2.0 | hppa2.0[nw] | hppa64 \\\n\t| hexagon \\\n\t| i370 | i860 | i960 | ia64 \\\n\t| ip2k | iq2000 \\\n\t| k1om \\\n\t| le32 | le64 \\\n\t| lm32 \\\n\t| m32c | m32r | m32rle | m68000 | m68k | m88k \\\n\t| maxq | mb | microblaze | microblazeel | mcore | mep | metag \\\n\t| mips | mipsbe | mipseb | mipsel | mipsle \\\n\t| mips16 \\\n\t| mips64 | mips64el \\\n\t| mips64octeon | mips64octeonel \\\n\t| mips64orion | mips64orionel \\\n\t| mips64r5900 | mips64r5900el \\\n\t| mips64vr | mips64vrel \\\n\t| mips64vr4100 | mips64vr4100el \\\n\t| mips64vr4300 | mips64vr4300el \\\n\t| mips64vr5000 | mips64vr5000el \\\n\t| mips64vr5900 | mips64vr5900el \\\n\t| mipsisa32 | mipsisa32el \\\n\t| mipsisa32r2 | mipsisa32r2el \\\n\t| mipsisa32r6 | mipsisa32r6el \\\n\t| mipsisa64 | mipsisa64el \\\n\t| mipsisa64r2 | mipsisa64r2el \\\n\t| mipsisa64r6 | mipsisa64r6el \\\n\t| mipsisa64sb1 | mipsisa64sb1el \\\n\t| mipsisa64sr71k | mipsisa64sr71kel \\\n\t| mipsr5900 | mipsr5900el \\\n\t| mipstx39 | mipstx39el \\\n\t| mn10200 | mn10300 \\\n\t| moxie \\\n\t| mt \\\n\t| msp430 \\\n\t| nds32 | nds32le | nds32be \\\n\t| nios | nios2 | nios2eb | nios2el \\\n\t| ns16k | ns32k \\\n\t| open8 | or1k | or1knd | or32 \\\n\t| pdp10 | pdp11 | pj | pjl \\\n\t| powerpc | powerpc64 | powerpc64le | powerpcle \\\n\t| pyramid \\\n\t| rl78 | rx \\\n\t| score \\\n\t| sh | sh[1234] | sh[24]a | sh[24]aeb | sh[23]e | sh[34]eb | sheb | shbe | shle | sh[1234]le | sh3ele \\\n\t| sh64 | sh64le \\\n\t| sparc | sparc64 | sparc64b | sparc64v | sparc86x | sparclet | sparclite \\\n\t| sparcv8 | sparcv9 | sparcv9b | sparcv9v \\\n\t| spu \\\n\t| tahoe | tic4x | tic54x | tic55x | tic6x | tic80 | tron \\\n\t| ubicom32 \\\n\t| v850 | v850e | v850e1 | v850e2 | v850es | v850e2v3 \\\n\t| we32k \\\n\t| x86 | xc16x | xstormy16 | xtensa \\\n\t| z8k | z80)\n\t\tbasic_machine=$basic_machine-unknown\n\t\t;;\n\tc54x)\n\t\tbasic_machine=tic54x-unknown\n\t\t;;\n\tc55x)\n\t\tbasic_machine=tic55x-unknown\n\t\t;;\n\tc6x)\n\t\tbasic_machine=tic6x-unknown\n\t\t;;\n\tm6811 | m68hc11 | m6812 | m68hc12 | m68hcs12x | nvptx | picochip)\n\t\tbasic_machine=$basic_machine-unknown\n\t\tos=-none\n\t\t;;\n\tm88110 | m680[12346]0 | m683?2 | m68360 | m5200 | v70 | w65 | z8k)\n\t\t;;\n\tms1)\n\t\tbasic_machine=mt-unknown\n\t\t;;\n\n\tstrongarm | thumb | xscale)\n\t\tbasic_machine=arm-unknown\n\t\t;;\n\txgate)\n\t\tbasic_machine=$basic_machine-unknown\n\t\tos=-none\n\t\t;;\n\txscaleeb)\n\t\tbasic_machine=armeb-unknown\n\t\t;;\n\n\txscaleel)\n\t\tbasic_machine=armel-unknown\n\t\t;;\n\n\t# We use `pc' rather than `unknown'\n\t# because (1) that's what they normally are, and\n\t# (2) the word \"unknown\" tends to confuse beginning users.\n\ti*86 | x86_64)\n\t  basic_machine=$basic_machine-pc\n\t  ;;\n\t# Object if more than one company name word.\n\t*-*-*)\n\t\techo Invalid configuration \\`$1\\': machine \\`$basic_machine\\' not recognized 1>&2\n\t\texit 1\n\t\t;;\n\t# Recognize the basic CPU types with company name.\n\t580-* \\\n\t| a29k-* \\\n\t| aarch64-* | aarch64_be-* \\\n\t| alpha-* | alphaev[4-8]-* | alphaev56-* | alphaev6[78]-* \\\n\t| alpha64-* | alpha64ev[4-8]-* | alpha64ev56-* | alpha64ev6[78]-* \\\n\t| alphapca5[67]-* | alpha64pca5[67]-* | arc-* | arceb-* \\\n\t| arm-*  | armbe-* | armle-* | armeb-* | armv*-* \\\n\t| avr-* | avr32-* \\\n\t| be32-* | be64-* \\\n\t| bfin-* | bs2000-* \\\n\t| c[123]* | c30-* | [cjt]90-* | c4x-* \\\n\t| c8051-* | clipper-* | craynv-* | cydra-* \\\n\t| d10v-* | d30v-* | dlx-* \\\n\t| elxsi-* \\\n\t| f30[01]-* | f700-* | fido-* | fr30-* | frv-* | fx80-* \\\n\t| h8300-* | h8500-* \\\n\t| hppa-* | hppa1.[01]-* | hppa2.0-* | hppa2.0[nw]-* | hppa64-* \\\n\t| hexagon-* \\\n\t| i*86-* | i860-* | i960-* | ia64-* \\\n\t| ip2k-* | iq2000-* \\\n\t| k1om-* \\\n\t| le32-* | le64-* \\\n\t| lm32-* \\\n\t| m32c-* | m32r-* | m32rle-* \\\n\t| m68000-* | m680[012346]0-* | m68360-* | m683?2-* | m68k-* \\\n\t| m88110-* | m88k-* | maxq-* | mcore-* | metag-* \\\n\t| microblaze-* | microblazeel-* \\\n\t| mips-* | mipsbe-* | mipseb-* | mipsel-* | mipsle-* \\\n\t| mips16-* \\\n\t| mips64-* | mips64el-* \\\n\t| mips64octeon-* | mips64octeonel-* \\\n\t| mips64orion-* | mips64orionel-* \\\n\t| mips64r5900-* | mips64r5900el-* \\\n\t| mips64vr-* | mips64vrel-* \\\n\t| mips64vr4100-* | mips64vr4100el-* \\\n\t| mips64vr4300-* | mips64vr4300el-* \\\n\t| mips64vr5000-* | mips64vr5000el-* \\\n\t| mips64vr5900-* | mips64vr5900el-* \\\n\t| mipsisa32-* | mipsisa32el-* \\\n\t| mipsisa32r2-* | mipsisa32r2el-* \\\n\t| mipsisa32r6-* | mipsisa32r6el-* \\\n\t| mipsisa64-* | mipsisa64el-* \\\n\t| mipsisa64r2-* | mipsisa64r2el-* \\\n\t| mipsisa64r6-* | mipsisa64r6el-* \\\n\t| mipsisa64sb1-* | mipsisa64sb1el-* \\\n\t| mipsisa64sr71k-* | mipsisa64sr71kel-* \\\n\t| mipsr5900-* | mipsr5900el-* \\\n\t| mipstx39-* | mipstx39el-* \\\n\t| mmix-* \\\n\t| mt-* \\\n\t| msp430-* \\\n\t| nds32-* | nds32le-* | nds32be-* \\\n\t| nios-* | nios2-* | nios2eb-* | nios2el-* \\\n\t| none-* | np1-* | ns16k-* | ns32k-* \\\n\t| open8-* \\\n\t| or1k*-* \\\n\t| orion-* \\\n\t| pdp10-* | pdp11-* | pj-* | pjl-* | pn-* | power-* \\\n\t| powerpc-* | powerpc64-* | powerpc64le-* | powerpcle-* \\\n\t| pyramid-* \\\n\t| rl78-* | romp-* | rs6000-* | rx-* \\\n\t| sh-* | sh[1234]-* | sh[24]a-* | sh[24]aeb-* | sh[23]e-* | sh[34]eb-* | sheb-* | shbe-* \\\n\t| shle-* | sh[1234]le-* | sh3ele-* | sh64-* | sh64le-* \\\n\t| sparc-* | sparc64-* | sparc64b-* | sparc64v-* | sparc86x-* | sparclet-* \\\n\t| sparclite-* \\\n\t| sparcv8-* | sparcv9-* | sparcv9b-* | sparcv9v-* | sv1-* | sx?-* \\\n\t| tahoe-* \\\n\t| tic30-* | tic4x-* | tic54x-* | tic55x-* | tic6x-* | tic80-* \\\n\t| tile*-* \\\n\t| tron-* \\\n\t| ubicom32-* \\\n\t| v850-* | v850e-* | v850e1-* | v850es-* | v850e2-* | v850e2v3-* \\\n\t| vax-* \\\n\t| we32k-* \\\n\t| x86-* | x86_64-* | xc16x-* | xps100-* \\\n\t| xstormy16-* | xtensa*-* \\\n\t| ymp-* \\\n\t| z8k-* | z80-*)\n\t\t;;\n\t# Recognize the basic CPU types without company name, with glob match.\n\txtensa*)\n\t\tbasic_machine=$basic_machine-unknown\n\t\t;;\n\t# Recognize the various machine names and aliases which stand\n\t# for a CPU type and a company and sometimes even an OS.\n\t386bsd)\n\t\tbasic_machine=i386-unknown\n\t\tos=-bsd\n\t\t;;\n\t3b1 | 7300 | 7300-att | att-7300 | pc7300 | safari | unixpc)\n\t\tbasic_machine=m68000-att\n\t\t;;\n\t3b*)\n\t\tbasic_machine=we32k-att\n\t\t;;\n\ta29khif)\n\t\tbasic_machine=a29k-amd\n\t\tos=-udi\n\t\t;;\n\tabacus)\n\t\tbasic_machine=abacus-unknown\n\t\t;;\n\tadobe68k)\n\t\tbasic_machine=m68010-adobe\n\t\tos=-scout\n\t\t;;\n\talliant | fx80)\n\t\tbasic_machine=fx80-alliant\n\t\t;;\n\taltos | altos3068)\n\t\tbasic_machine=m68k-altos\n\t\t;;\n\tam29k)\n\t\tbasic_machine=a29k-none\n\t\tos=-bsd\n\t\t;;\n\tamd64)\n\t\tbasic_machine=x86_64-pc\n\t\t;;\n\tamd64-*)\n\t\tbasic_machine=x86_64-`echo $basic_machine | sed 's/^[^-]*-//'`\n\t\t;;\n\tamdahl)\n\t\tbasic_machine=580-amdahl\n\t\tos=-sysv\n\t\t;;\n\tamiga | amiga-*)\n\t\tbasic_machine=m68k-unknown\n\t\t;;\n\tamigaos | amigados)\n\t\tbasic_machine=m68k-unknown\n\t\tos=-amigaos\n\t\t;;\n\tamigaunix | amix)\n\t\tbasic_machine=m68k-unknown\n\t\tos=-sysv4\n\t\t;;\n\tapollo68)\n\t\tbasic_machine=m68k-apollo\n\t\tos=-sysv\n\t\t;;\n\tapollo68bsd)\n\t\tbasic_machine=m68k-apollo\n\t\tos=-bsd\n\t\t;;\n\taros)\n\t\tbasic_machine=i386-pc\n\t\tos=-aros\n\t\t;;\n\taux)\n\t\tbasic_machine=m68k-apple\n\t\tos=-aux\n\t\t;;\n\tbalance)\n\t\tbasic_machine=ns32k-sequent\n\t\tos=-dynix\n\t\t;;\n\tblackfin)\n\t\tbasic_machine=bfin-unknown\n\t\tos=-linux\n\t\t;;\n\tblackfin-*)\n\t\tbasic_machine=bfin-`echo $basic_machine | sed 's/^[^-]*-//'`\n\t\tos=-linux\n\t\t;;\n\tbluegene*)\n\t\tbasic_machine=powerpc-ibm\n\t\tos=-cnk\n\t\t;;\n\tc54x-*)\n\t\tbasic_machine=tic54x-`echo $basic_machine | sed 's/^[^-]*-//'`\n\t\t;;\n\tc55x-*)\n\t\tbasic_machine=tic55x-`echo $basic_machine | sed 's/^[^-]*-//'`\n\t\t;;\n\tc6x-*)\n\t\tbasic_machine=tic6x-`echo $basic_machine | sed 's/^[^-]*-//'`\n\t\t;;\n\tc90)\n\t\tbasic_machine=c90-cray\n\t\tos=-unicos\n\t\t;;\n\tcegcc)\n\t\tbasic_machine=arm-unknown\n\t\tos=-cegcc\n\t\t;;\n\tconvex-c1)\n\t\tbasic_machine=c1-convex\n\t\tos=-bsd\n\t\t;;\n\tconvex-c2)\n\t\tbasic_machine=c2-convex\n\t\tos=-bsd\n\t\t;;\n\tconvex-c32)\n\t\tbasic_machine=c32-convex\n\t\tos=-bsd\n\t\t;;\n\tconvex-c34)\n\t\tbasic_machine=c34-convex\n\t\tos=-bsd\n\t\t;;\n\tconvex-c38)\n\t\tbasic_machine=c38-convex\n\t\tos=-bsd\n\t\t;;\n\tcray | j90)\n\t\tbasic_machine=j90-cray\n\t\tos=-unicos\n\t\t;;\n\tcraynv)\n\t\tbasic_machine=craynv-cray\n\t\tos=-unicosmp\n\t\t;;\n\tcr16 | cr16-*)\n\t\tbasic_machine=cr16-unknown\n\t\tos=-elf\n\t\t;;\n\tcrds | unos)\n\t\tbasic_machine=m68k-crds\n\t\t;;\n\tcrisv32 | crisv32-* | etraxfs*)\n\t\tbasic_machine=crisv32-axis\n\t\t;;\n\tcris | cris-* | etrax*)\n\t\tbasic_machine=cris-axis\n\t\t;;\n\tcrx)\n\t\tbasic_machine=crx-unknown\n\t\tos=-elf\n\t\t;;\n\tda30 | da30-*)\n\t\tbasic_machine=m68k-da30\n\t\t;;\n\tdecstation | decstation-3100 | pmax | pmax-* | pmin | dec3100 | decstatn)\n\t\tbasic_machine=mips-dec\n\t\t;;\n\tdecsystem10* | dec10*)\n\t\tbasic_machine=pdp10-dec\n\t\tos=-tops10\n\t\t;;\n\tdecsystem20* | dec20*)\n\t\tbasic_machine=pdp10-dec\n\t\tos=-tops20\n\t\t;;\n\tdelta | 3300 | motorola-3300 | motorola-delta \\\n\t      | 3300-motorola | delta-motorola)\n\t\tbasic_machine=m68k-motorola\n\t\t;;\n\tdelta88)\n\t\tbasic_machine=m88k-motorola\n\t\tos=-sysv3\n\t\t;;\n\tdicos)\n\t\tbasic_machine=i686-pc\n\t\tos=-dicos\n\t\t;;\n\tdjgpp)\n\t\tbasic_machine=i586-pc\n\t\tos=-msdosdjgpp\n\t\t;;\n\tdpx20 | dpx20-*)\n\t\tbasic_machine=rs6000-bull\n\t\tos=-bosx\n\t\t;;\n\tdpx2* | dpx2*-bull)\n\t\tbasic_machine=m68k-bull\n\t\tos=-sysv3\n\t\t;;\n\tebmon29k)\n\t\tbasic_machine=a29k-amd\n\t\tos=-ebmon\n\t\t;;\n\telxsi)\n\t\tbasic_machine=elxsi-elxsi\n\t\tos=-bsd\n\t\t;;\n\tencore | umax | mmax)\n\t\tbasic_machine=ns32k-encore\n\t\t;;\n\tes1800 | OSE68k | ose68k | ose | OSE)\n\t\tbasic_machine=m68k-ericsson\n\t\tos=-ose\n\t\t;;\n\tfx2800)\n\t\tbasic_machine=i860-alliant\n\t\t;;\n\tgenix)\n\t\tbasic_machine=ns32k-ns\n\t\t;;\n\tgmicro)\n\t\tbasic_machine=tron-gmicro\n\t\tos=-sysv\n\t\t;;\n\tgo32)\n\t\tbasic_machine=i386-pc\n\t\tos=-go32\n\t\t;;\n\th3050r* | hiux*)\n\t\tbasic_machine=hppa1.1-hitachi\n\t\tos=-hiuxwe2\n\t\t;;\n\th8300hms)\n\t\tbasic_machine=h8300-hitachi\n\t\tos=-hms\n\t\t;;\n\th8300xray)\n\t\tbasic_machine=h8300-hitachi\n\t\tos=-xray\n\t\t;;\n\th8500hms)\n\t\tbasic_machine=h8500-hitachi\n\t\tos=-hms\n\t\t;;\n\tharris)\n\t\tbasic_machine=m88k-harris\n\t\tos=-sysv3\n\t\t;;\n\thp300-*)\n\t\tbasic_machine=m68k-hp\n\t\t;;\n\thp300bsd)\n\t\tbasic_machine=m68k-hp\n\t\tos=-bsd\n\t\t;;\n\thp300hpux)\n\t\tbasic_machine=m68k-hp\n\t\tos=-hpux\n\t\t;;\n\thp3k9[0-9][0-9] | hp9[0-9][0-9])\n\t\tbasic_machine=hppa1.0-hp\n\t\t;;\n\thp9k2[0-9][0-9] | hp9k31[0-9])\n\t\tbasic_machine=m68000-hp\n\t\t;;\n\thp9k3[2-9][0-9])\n\t\tbasic_machine=m68k-hp\n\t\t;;\n\thp9k6[0-9][0-9] | hp6[0-9][0-9])\n\t\tbasic_machine=hppa1.0-hp\n\t\t;;\n\thp9k7[0-79][0-9] | hp7[0-79][0-9])\n\t\tbasic_machine=hppa1.1-hp\n\t\t;;\n\thp9k78[0-9] | hp78[0-9])\n\t\t# FIXME: really hppa2.0-hp\n\t\tbasic_machine=hppa1.1-hp\n\t\t;;\n\thp9k8[67]1 | hp8[67]1 | hp9k80[24] | hp80[24] | hp9k8[78]9 | hp8[78]9 | hp9k893 | hp893)\n\t\t# FIXME: really hppa2.0-hp\n\t\tbasic_machine=hppa1.1-hp\n\t\t;;\n\thp9k8[0-9][13679] | hp8[0-9][13679])\n\t\tbasic_machine=hppa1.1-hp\n\t\t;;\n\thp9k8[0-9][0-9] | hp8[0-9][0-9])\n\t\tbasic_machine=hppa1.0-hp\n\t\t;;\n\thppa-next)\n\t\tos=-nextstep3\n\t\t;;\n\thppaosf)\n\t\tbasic_machine=hppa1.1-hp\n\t\tos=-osf\n\t\t;;\n\thppro)\n\t\tbasic_machine=hppa1.1-hp\n\t\tos=-proelf\n\t\t;;\n\ti370-ibm* | ibm*)\n\t\tbasic_machine=i370-ibm\n\t\t;;\n\ti*86v32)\n\t\tbasic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`\n\t\tos=-sysv32\n\t\t;;\n\ti*86v4*)\n\t\tbasic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`\n\t\tos=-sysv4\n\t\t;;\n\ti*86v)\n\t\tbasic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`\n\t\tos=-sysv\n\t\t;;\n\ti*86sol2)\n\t\tbasic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`\n\t\tos=-solaris2\n\t\t;;\n\ti386mach)\n\t\tbasic_machine=i386-mach\n\t\tos=-mach\n\t\t;;\n\ti386-vsta | vsta)\n\t\tbasic_machine=i386-unknown\n\t\tos=-vsta\n\t\t;;\n\tiris | iris4d)\n\t\tbasic_machine=mips-sgi\n\t\tcase $os in\n\t\t    -irix*)\n\t\t\t;;\n\t\t    *)\n\t\t\tos=-irix4\n\t\t\t;;\n\t\tesac\n\t\t;;\n\tisi68 | isi)\n\t\tbasic_machine=m68k-isi\n\t\tos=-sysv\n\t\t;;\n\tm68knommu)\n\t\tbasic_machine=m68k-unknown\n\t\tos=-linux\n\t\t;;\n\tm68knommu-*)\n\t\tbasic_machine=m68k-`echo $basic_machine | sed 's/^[^-]*-//'`\n\t\tos=-linux\n\t\t;;\n\tm88k-omron*)\n\t\tbasic_machine=m88k-omron\n\t\t;;\n\tmagnum | m3230)\n\t\tbasic_machine=mips-mips\n\t\tos=-sysv\n\t\t;;\n\tmerlin)\n\t\tbasic_machine=ns32k-utek\n\t\tos=-sysv\n\t\t;;\n\tmicroblaze*)\n\t\tbasic_machine=microblaze-xilinx\n\t\t;;\n\tmingw64)\n\t\tbasic_machine=x86_64-pc\n\t\tos=-mingw64\n\t\t;;\n\tmingw32)\n\t\tbasic_machine=i686-pc\n\t\tos=-mingw32\n\t\t;;\n\tmingw32ce)\n\t\tbasic_machine=arm-unknown\n\t\tos=-mingw32ce\n\t\t;;\n\tminiframe)\n\t\tbasic_machine=m68000-convergent\n\t\t;;\n\t*mint | -mint[0-9]* | *MiNT | *MiNT[0-9]*)\n\t\tbasic_machine=m68k-atari\n\t\tos=-mint\n\t\t;;\n\tmips3*-*)\n\t\tbasic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'`\n\t\t;;\n\tmips3*)\n\t\tbasic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'`-unknown\n\t\t;;\n\tmonitor)\n\t\tbasic_machine=m68k-rom68k\n\t\tos=-coff\n\t\t;;\n\tmorphos)\n\t\tbasic_machine=powerpc-unknown\n\t\tos=-morphos\n\t\t;;\n\tmsdos)\n\t\tbasic_machine=i386-pc\n\t\tos=-msdos\n\t\t;;\n\tms1-*)\n\t\tbasic_machine=`echo $basic_machine | sed -e 's/ms1-/mt-/'`\n\t\t;;\n\tmsys)\n\t\tbasic_machine=i686-pc\n\t\tos=-msys\n\t\t;;\n\tmvs)\n\t\tbasic_machine=i370-ibm\n\t\tos=-mvs\n\t\t;;\n\tnacl)\n\t\tbasic_machine=le32-unknown\n\t\tos=-nacl\n\t\t;;\n\tncr3000)\n\t\tbasic_machine=i486-ncr\n\t\tos=-sysv4\n\t\t;;\n\tnetbsd386)\n\t\tbasic_machine=i386-unknown\n\t\tos=-netbsd\n\t\t;;\n\tnetwinder)\n\t\tbasic_machine=armv4l-rebel\n\t\tos=-linux\n\t\t;;\n\tnews | news700 | news800 | news900)\n\t\tbasic_machine=m68k-sony\n\t\tos=-newsos\n\t\t;;\n\tnews1000)\n\t\tbasic_machine=m68030-sony\n\t\tos=-newsos\n\t\t;;\n\tnews-3600 | risc-news)\n\t\tbasic_machine=mips-sony\n\t\tos=-newsos\n\t\t;;\n\tnecv70)\n\t\tbasic_machine=v70-nec\n\t\tos=-sysv\n\t\t;;\n\tnext | m*-next )\n\t\tbasic_machine=m68k-next\n\t\tcase $os in\n\t\t    -nextstep* )\n\t\t\t;;\n\t\t    -ns2*)\n\t\t      os=-nextstep2\n\t\t\t;;\n\t\t    *)\n\t\t      os=-nextstep3\n\t\t\t;;\n\t\tesac\n\t\t;;\n\tnh3000)\n\t\tbasic_machine=m68k-harris\n\t\tos=-cxux\n\t\t;;\n\tnh[45]000)\n\t\tbasic_machine=m88k-harris\n\t\tos=-cxux\n\t\t;;\n\tnindy960)\n\t\tbasic_machine=i960-intel\n\t\tos=-nindy\n\t\t;;\n\tmon960)\n\t\tbasic_machine=i960-intel\n\t\tos=-mon960\n\t\t;;\n\tnonstopux)\n\t\tbasic_machine=mips-compaq\n\t\tos=-nonstopux\n\t\t;;\n\tnp1)\n\t\tbasic_machine=np1-gould\n\t\t;;\n\tneo-tandem)\n\t\tbasic_machine=neo-tandem\n\t\t;;\n\tnse-tandem)\n\t\tbasic_machine=nse-tandem\n\t\t;;\n\tnsr-tandem)\n\t\tbasic_machine=nsr-tandem\n\t\t;;\n\top50n-* | op60c-*)\n\t\tbasic_machine=hppa1.1-oki\n\t\tos=-proelf\n\t\t;;\n\topenrisc | openrisc-*)\n\t\tbasic_machine=or32-unknown\n\t\t;;\n\tos400)\n\t\tbasic_machine=powerpc-ibm\n\t\tos=-os400\n\t\t;;\n\tOSE68000 | ose68000)\n\t\tbasic_machine=m68000-ericsson\n\t\tos=-ose\n\t\t;;\n\tos68k)\n\t\tbasic_machine=m68k-none\n\t\tos=-os68k\n\t\t;;\n\tpa-hitachi)\n\t\tbasic_machine=hppa1.1-hitachi\n\t\tos=-hiuxwe2\n\t\t;;\n\tparagon)\n\t\tbasic_machine=i860-intel\n\t\tos=-osf\n\t\t;;\n\tparisc)\n\t\tbasic_machine=hppa-unknown\n\t\tos=-linux\n\t\t;;\n\tparisc-*)\n\t\tbasic_machine=hppa-`echo $basic_machine | sed 's/^[^-]*-//'`\n\t\tos=-linux\n\t\t;;\n\tpbd)\n\t\tbasic_machine=sparc-tti\n\t\t;;\n\tpbb)\n\t\tbasic_machine=m68k-tti\n\t\t;;\n\tpc532 | pc532-*)\n\t\tbasic_machine=ns32k-pc532\n\t\t;;\n\tpc98)\n\t\tbasic_machine=i386-pc\n\t\t;;\n\tpc98-*)\n\t\tbasic_machine=i386-`echo $basic_machine | sed 's/^[^-]*-//'`\n\t\t;;\n\tpentium | p5 | k5 | k6 | nexgen | viac3)\n\t\tbasic_machine=i586-pc\n\t\t;;\n\tpentiumpro | p6 | 6x86 | athlon | athlon_*)\n\t\tbasic_machine=i686-pc\n\t\t;;\n\tpentiumii | pentium2 | pentiumiii | pentium3)\n\t\tbasic_machine=i686-pc\n\t\t;;\n\tpentium4)\n\t\tbasic_machine=i786-pc\n\t\t;;\n\tpentium-* | p5-* | k5-* | k6-* | nexgen-* | viac3-*)\n\t\tbasic_machine=i586-`echo $basic_machine | sed 's/^[^-]*-//'`\n\t\t;;\n\tpentiumpro-* | p6-* | 6x86-* | athlon-*)\n\t\tbasic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'`\n\t\t;;\n\tpentiumii-* | pentium2-* | pentiumiii-* | pentium3-*)\n\t\tbasic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'`\n\t\t;;\n\tpentium4-*)\n\t\tbasic_machine=i786-`echo $basic_machine | sed 's/^[^-]*-//'`\n\t\t;;\n\tpn)\n\t\tbasic_machine=pn-gould\n\t\t;;\n\tpower)\tbasic_machine=power-ibm\n\t\t;;\n\tppc | ppcbe)\tbasic_machine=powerpc-unknown\n\t\t;;\n\tppc-* | ppcbe-*)\n\t\tbasic_machine=powerpc-`echo $basic_machine | sed 's/^[^-]*-//'`\n\t\t;;\n\tppcle | powerpclittle | ppc-le | powerpc-little)\n\t\tbasic_machine=powerpcle-unknown\n\t\t;;\n\tppcle-* | powerpclittle-*)\n\t\tbasic_machine=powerpcle-`echo $basic_machine | sed 's/^[^-]*-//'`\n\t\t;;\n\tppc64)\tbasic_machine=powerpc64-unknown\n\t\t;;\n\tppc64-*) basic_machine=powerpc64-`echo $basic_machine | sed 's/^[^-]*-//'`\n\t\t;;\n\tppc64le | powerpc64little | ppc64-le | powerpc64-little)\n\t\tbasic_machine=powerpc64le-unknown\n\t\t;;\n\tppc64le-* | powerpc64little-*)\n\t\tbasic_machine=powerpc64le-`echo $basic_machine | sed 's/^[^-]*-//'`\n\t\t;;\n\tps2)\n\t\tbasic_machine=i386-ibm\n\t\t;;\n\tpw32)\n\t\tbasic_machine=i586-unknown\n\t\tos=-pw32\n\t\t;;\n\trdos | rdos64)\n\t\tbasic_machine=x86_64-pc\n\t\tos=-rdos\n\t\t;;\n\trdos32)\n\t\tbasic_machine=i386-pc\n\t\tos=-rdos\n\t\t;;\n\trom68k)\n\t\tbasic_machine=m68k-rom68k\n\t\tos=-coff\n\t\t;;\n\trm[46]00)\n\t\tbasic_machine=mips-siemens\n\t\t;;\n\trtpc | rtpc-*)\n\t\tbasic_machine=romp-ibm\n\t\t;;\n\ts390 | s390-*)\n\t\tbasic_machine=s390-ibm\n\t\t;;\n\ts390x | s390x-*)\n\t\tbasic_machine=s390x-ibm\n\t\t;;\n\tsa29200)\n\t\tbasic_machine=a29k-amd\n\t\tos=-udi\n\t\t;;\n\tsb1)\n\t\tbasic_machine=mipsisa64sb1-unknown\n\t\t;;\n\tsb1el)\n\t\tbasic_machine=mipsisa64sb1el-unknown\n\t\t;;\n\tsde)\n\t\tbasic_machine=mipsisa32-sde\n\t\tos=-elf\n\t\t;;\n\tsei)\n\t\tbasic_machine=mips-sei\n\t\tos=-seiux\n\t\t;;\n\tsequent)\n\t\tbasic_machine=i386-sequent\n\t\t;;\n\tsh)\n\t\tbasic_machine=sh-hitachi\n\t\tos=-hms\n\t\t;;\n\tsh5el)\n\t\tbasic_machine=sh5le-unknown\n\t\t;;\n\tsh64)\n\t\tbasic_machine=sh64-unknown\n\t\t;;\n\tsparclite-wrs | simso-wrs)\n\t\tbasic_machine=sparclite-wrs\n\t\tos=-vxworks\n\t\t;;\n\tsps7)\n\t\tbasic_machine=m68k-bull\n\t\tos=-sysv2\n\t\t;;\n\tspur)\n\t\tbasic_machine=spur-unknown\n\t\t;;\n\tst2000)\n\t\tbasic_machine=m68k-tandem\n\t\t;;\n\tstratus)\n\t\tbasic_machine=i860-stratus\n\t\tos=-sysv4\n\t\t;;\n\tstrongarm-* | thumb-*)\n\t\tbasic_machine=arm-`echo $basic_machine | sed 's/^[^-]*-//'`\n\t\t;;\n\tsun2)\n\t\tbasic_machine=m68000-sun\n\t\t;;\n\tsun2os3)\n\t\tbasic_machine=m68000-sun\n\t\tos=-sunos3\n\t\t;;\n\tsun2os4)\n\t\tbasic_machine=m68000-sun\n\t\tos=-sunos4\n\t\t;;\n\tsun3os3)\n\t\tbasic_machine=m68k-sun\n\t\tos=-sunos3\n\t\t;;\n\tsun3os4)\n\t\tbasic_machine=m68k-sun\n\t\tos=-sunos4\n\t\t;;\n\tsun4os3)\n\t\tbasic_machine=sparc-sun\n\t\tos=-sunos3\n\t\t;;\n\tsun4os4)\n\t\tbasic_machine=sparc-sun\n\t\tos=-sunos4\n\t\t;;\n\tsun4sol2)\n\t\tbasic_machine=sparc-sun\n\t\tos=-solaris2\n\t\t;;\n\tsun3 | sun3-*)\n\t\tbasic_machine=m68k-sun\n\t\t;;\n\tsun4)\n\t\tbasic_machine=sparc-sun\n\t\t;;\n\tsun386 | sun386i | roadrunner)\n\t\tbasic_machine=i386-sun\n\t\t;;\n\tsv1)\n\t\tbasic_machine=sv1-cray\n\t\tos=-unicos\n\t\t;;\n\tsymmetry)\n\t\tbasic_machine=i386-sequent\n\t\tos=-dynix\n\t\t;;\n\tt3e)\n\t\tbasic_machine=alphaev5-cray\n\t\tos=-unicos\n\t\t;;\n\tt90)\n\t\tbasic_machine=t90-cray\n\t\tos=-unicos\n\t\t;;\n\ttile*)\n\t\tbasic_machine=$basic_machine-unknown\n\t\tos=-linux-gnu\n\t\t;;\n\ttx39)\n\t\tbasic_machine=mipstx39-unknown\n\t\t;;\n\ttx39el)\n\t\tbasic_machine=mipstx39el-unknown\n\t\t;;\n\ttoad1)\n\t\tbasic_machine=pdp10-xkl\n\t\tos=-tops20\n\t\t;;\n\ttower | tower-32)\n\t\tbasic_machine=m68k-ncr\n\t\t;;\n\ttpf)\n\t\tbasic_machine=s390x-ibm\n\t\tos=-tpf\n\t\t;;\n\tudi29k)\n\t\tbasic_machine=a29k-amd\n\t\tos=-udi\n\t\t;;\n\tultra3)\n\t\tbasic_machine=a29k-nyu\n\t\tos=-sym1\n\t\t;;\n\tv810 | necv810)\n\t\tbasic_machine=v810-nec\n\t\tos=-none\n\t\t;;\n\tvaxv)\n\t\tbasic_machine=vax-dec\n\t\tos=-sysv\n\t\t;;\n\tvms)\n\t\tbasic_machine=vax-dec\n\t\tos=-vms\n\t\t;;\n\tvpp*|vx|vx-*)\n\t\tbasic_machine=f301-fujitsu\n\t\t;;\n\tvxworks960)\n\t\tbasic_machine=i960-wrs\n\t\tos=-vxworks\n\t\t;;\n\tvxworks68)\n\t\tbasic_machine=m68k-wrs\n\t\tos=-vxworks\n\t\t;;\n\tvxworks29k)\n\t\tbasic_machine=a29k-wrs\n\t\tos=-vxworks\n\t\t;;\n\tw65*)\n\t\tbasic_machine=w65-wdc\n\t\tos=-none\n\t\t;;\n\tw89k-*)\n\t\tbasic_machine=hppa1.1-winbond\n\t\tos=-proelf\n\t\t;;\n\txbox)\n\t\tbasic_machine=i686-pc\n\t\tos=-mingw32\n\t\t;;\n\txps | xps100)\n\t\tbasic_machine=xps100-honeywell\n\t\t;;\n\txscale-* | xscalee[bl]-*)\n\t\tbasic_machine=`echo $basic_machine | sed 's/^xscale/arm/'`\n\t\t;;\n\tymp)\n\t\tbasic_machine=ymp-cray\n\t\tos=-unicos\n\t\t;;\n\tz8k-*-coff)\n\t\tbasic_machine=z8k-unknown\n\t\tos=-sim\n\t\t;;\n\tz80-*-coff)\n\t\tbasic_machine=z80-unknown\n\t\tos=-sim\n\t\t;;\n\tnone)\n\t\tbasic_machine=none-none\n\t\tos=-none\n\t\t;;\n\n# Here we handle the default manufacturer of certain CPU types.  It is in\n# some cases the only manufacturer, in others, it is the most popular.\n\tw89k)\n\t\tbasic_machine=hppa1.1-winbond\n\t\t;;\n\top50n)\n\t\tbasic_machine=hppa1.1-oki\n\t\t;;\n\top60c)\n\t\tbasic_machine=hppa1.1-oki\n\t\t;;\n\tromp)\n\t\tbasic_machine=romp-ibm\n\t\t;;\n\tmmix)\n\t\tbasic_machine=mmix-knuth\n\t\t;;\n\trs6000)\n\t\tbasic_machine=rs6000-ibm\n\t\t;;\n\tvax)\n\t\tbasic_machine=vax-dec\n\t\t;;\n\tpdp10)\n\t\t# there are many clones, so DEC is not a safe bet\n\t\tbasic_machine=pdp10-unknown\n\t\t;;\n\tpdp11)\n\t\tbasic_machine=pdp11-dec\n\t\t;;\n\twe32k)\n\t\tbasic_machine=we32k-att\n\t\t;;\n\tsh[1234] | sh[24]a | sh[24]aeb | sh[34]eb | sh[1234]le | sh[23]ele)\n\t\tbasic_machine=sh-unknown\n\t\t;;\n\tsparc | sparcv8 | sparcv9 | sparcv9b | sparcv9v)\n\t\tbasic_machine=sparc-sun\n\t\t;;\n\tcydra)\n\t\tbasic_machine=cydra-cydrome\n\t\t;;\n\torion)\n\t\tbasic_machine=orion-highlevel\n\t\t;;\n\torion105)\n\t\tbasic_machine=clipper-highlevel\n\t\t;;\n\tmac | mpw | mac-mpw)\n\t\tbasic_machine=m68k-apple\n\t\t;;\n\tpmac | pmac-mpw)\n\t\tbasic_machine=powerpc-apple\n\t\t;;\n\t*-unknown)\n\t\t# Make sure to match an already-canonicalized machine name.\n\t\t;;\n\t*)\n\t\techo Invalid configuration \\`$1\\': machine \\`$basic_machine\\' not recognized 1>&2\n\t\texit 1\n\t\t;;\nesac\n\n# Here we canonicalize certain aliases for manufacturers.\ncase $basic_machine in\n\t*-digital*)\n\t\tbasic_machine=`echo $basic_machine | sed 's/digital.*/dec/'`\n\t\t;;\n\t*-commodore*)\n\t\tbasic_machine=`echo $basic_machine | sed 's/commodore.*/cbm/'`\n\t\t;;\n\t*)\n\t\t;;\nesac\n\n# Decode manufacturer-specific aliases for certain operating systems.\n\nif [ x\"$os\" != x\"\" ]\nthen\ncase $os in\n\t# First match some system type aliases\n\t# that might get confused with valid system types.\n\t# -solaris* is a basic system type, with this one exception.\n\t-auroraux)\n\t\tos=-auroraux\n\t\t;;\n\t-solaris1 | -solaris1.*)\n\t\tos=`echo $os | sed -e 's|solaris1|sunos4|'`\n\t\t;;\n\t-solaris)\n\t\tos=-solaris2\n\t\t;;\n\t-svr4*)\n\t\tos=-sysv4\n\t\t;;\n\t-unixware*)\n\t\tos=-sysv4.2uw\n\t\t;;\n\t-gnu/linux*)\n\t\tos=`echo $os | sed -e 's|gnu/linux|linux-gnu|'`\n\t\t;;\n\t# First accept the basic system types.\n\t# The portable systems comes first.\n\t# Each alternative MUST END IN A *, to match a version number.\n\t# -sysv* is not here because it comes later, after sysvr4.\n\t-gnu* | -bsd* | -mach* | -minix* | -genix* | -ultrix* | -irix* \\\n\t      | -*vms* | -sco* | -esix* | -isc* | -aix* | -cnk* | -sunos | -sunos[34]*\\\n\t      | -hpux* | -unos* | -osf* | -luna* | -dgux* | -auroraux* | -solaris* \\\n\t      | -sym* | -kopensolaris* | -plan9* \\\n\t      | -amigaos* | -amigados* | -msdos* | -newsos* | -unicos* | -aof* \\\n\t      | -aos* | -aros* \\\n\t      | -nindy* | -vxsim* | -vxworks* | -ebmon* | -hms* | -mvs* \\\n\t      | -clix* | -riscos* | -uniplus* | -iris* | -rtu* | -xenix* \\\n\t      | -hiux* | -386bsd* | -knetbsd* | -mirbsd* | -netbsd* \\\n\t      | -bitrig* | -openbsd* | -solidbsd* \\\n\t      | -ekkobsd* | -kfreebsd* | -freebsd* | -riscix* | -lynxos* \\\n\t      | -bosx* | -nextstep* | -cxux* | -aout* | -elf* | -oabi* \\\n\t      | -ptx* | -coff* | -ecoff* | -winnt* | -domain* | -vsta* \\\n\t      | -udi* | -eabi* | -lites* | -ieee* | -go32* | -aux* \\\n\t      | -chorusos* | -chorusrdb* | -cegcc* \\\n\t      | -cygwin* | -msys* | -pe* | -psos* | -moss* | -proelf* | -rtems* \\\n\t      | -mingw32* | -mingw64* | -linux-gnu* | -linux-android* \\\n\t      | -linux-newlib* | -linux-musl* | -linux-uclibc* \\\n\t      | -uxpv* | -beos* | -mpeix* | -udk* \\\n\t      | -interix* | -uwin* | -mks* | -rhapsody* | -darwin* | -opened* \\\n\t      | -openstep* | -oskit* | -conix* | -pw32* | -nonstopux* \\\n\t      | -storm-chaos* | -tops10* | -tenex* | -tops20* | -its* \\\n\t      | -os2* | -vos* | -palmos* | -uclinux* | -nucleus* \\\n\t      | -morphos* | -superux* | -rtmk* | -rtmk-nova* | -windiss* \\\n\t      | -powermax* | -dnix* | -nx6 | -nx7 | -sei* | -dragonfly* \\\n\t      | -skyos* | -haiku* | -rdos* | -toppers* | -drops* | -es* | -tirtos*)\n\t# Remember, each alternative MUST END IN *, to match a version number.\n\t\t;;\n\t-qnx*)\n\t\tcase $basic_machine in\n\t\t    x86-* | i*86-*)\n\t\t\t;;\n\t\t    *)\n\t\t\tos=-nto$os\n\t\t\t;;\n\t\tesac\n\t\t;;\n\t-nto-qnx*)\n\t\t;;\n\t-nto*)\n\t\tos=`echo $os | sed -e 's|nto|nto-qnx|'`\n\t\t;;\n\t-sim | -es1800* | -hms* | -xray | -os68k* | -none* | -v88r* \\\n\t      | -windows* | -osx | -abug | -netware* | -os9* | -beos* | -haiku* \\\n\t      | -macos* | -mpw* | -magic* | -mmixware* | -mon960* | -lnews*)\n\t\t;;\n\t-mac*)\n\t\tos=`echo $os | sed -e 's|mac|macos|'`\n\t\t;;\n\t# Apple iOS\n\t-ios*)\n\t\t;;\n\t-linux-dietlibc)\n\t\tos=-linux-dietlibc\n\t\t;;\n\t-linux*)\n\t\tos=`echo $os | sed -e 's|linux|linux-gnu|'`\n\t\t;;\n\t-sunos5*)\n\t\tos=`echo $os | sed -e 's|sunos5|solaris2|'`\n\t\t;;\n\t-sunos6*)\n\t\tos=`echo $os | sed -e 's|sunos6|solaris3|'`\n\t\t;;\n\t-opened*)\n\t\tos=-openedition\n\t\t;;\n\t-os400*)\n\t\tos=-os400\n\t\t;;\n\t-wince*)\n\t\tos=-wince\n\t\t;;\n\t-osfrose*)\n\t\tos=-osfrose\n\t\t;;\n\t-osf*)\n\t\tos=-osf\n\t\t;;\n\t-utek*)\n\t\tos=-bsd\n\t\t;;\n\t-dynix*)\n\t\tos=-bsd\n\t\t;;\n\t-acis*)\n\t\tos=-aos\n\t\t;;\n\t-atheos*)\n\t\tos=-atheos\n\t\t;;\n\t-syllable*)\n\t\tos=-syllable\n\t\t;;\n\t-386bsd)\n\t\tos=-bsd\n\t\t;;\n\t-ctix* | -uts*)\n\t\tos=-sysv\n\t\t;;\n\t-nova*)\n\t\tos=-rtmk-nova\n\t\t;;\n\t-ns2 )\n\t\tos=-nextstep2\n\t\t;;\n\t-nsk*)\n\t\tos=-nsk\n\t\t;;\n\t# Preserve the version number of sinix5.\n\t-sinix5.*)\n\t\tos=`echo $os | sed -e 's|sinix|sysv|'`\n\t\t;;\n\t-sinix*)\n\t\tos=-sysv4\n\t\t;;\n\t-tpf*)\n\t\tos=-tpf\n\t\t;;\n\t-triton*)\n\t\tos=-sysv3\n\t\t;;\n\t-oss*)\n\t\tos=-sysv3\n\t\t;;\n\t-svr4)\n\t\tos=-sysv4\n\t\t;;\n\t-svr3)\n\t\tos=-sysv3\n\t\t;;\n\t-sysvr4)\n\t\tos=-sysv4\n\t\t;;\n\t# This must come after -sysvr4.\n\t-sysv*)\n\t\t;;\n\t-ose*)\n\t\tos=-ose\n\t\t;;\n\t-es1800*)\n\t\tos=-ose\n\t\t;;\n\t-xenix)\n\t\tos=-xenix\n\t\t;;\n\t-*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*)\n\t\tos=-mint\n\t\t;;\n\t-aros*)\n\t\tos=-aros\n\t\t;;\n\t-zvmoe)\n\t\tos=-zvmoe\n\t\t;;\n\t-dicos*)\n\t\tos=-dicos\n\t\t;;\n\t-nacl*)\n\t\t;;\n\t-none)\n\t\t;;\n\t*)\n\t\t# Get rid of the `-' at the beginning of $os.\n\t\tos=`echo $os | sed 's/[^-]*-//'`\n\t\techo Invalid configuration \\`$1\\': system \\`$os\\' not recognized 1>&2\n\t\texit 1\n\t\t;;\nesac\nelse\n\n# Here we handle the default operating systems that come with various machines.\n# The value should be what the vendor currently ships out the door with their\n# machine or put another way, the most popular os provided with the machine.\n\n# Note that if you're going to try to match \"-MANUFACTURER\" here (say,\n# \"-sun\"), then you have to tell the case statement up towards the top\n# that MANUFACTURER isn't an operating system.  Otherwise, code above\n# will signal an error saying that MANUFACTURER isn't an operating\n# system, and we'll never get to this point.\n\ncase $basic_machine in\n\tscore-*)\n\t\tos=-elf\n\t\t;;\n\tspu-*)\n\t\tos=-elf\n\t\t;;\n\t*-acorn)\n\t\tos=-riscix1.2\n\t\t;;\n\tarm*-rebel)\n\t\tos=-linux\n\t\t;;\n\tarm*-semi)\n\t\tos=-aout\n\t\t;;\n\tc4x-* | tic4x-*)\n\t\tos=-coff\n\t\t;;\n\tc8051-*)\n\t\tos=-elf\n\t\t;;\n\thexagon-*)\n\t\tos=-elf\n\t\t;;\n\ttic54x-*)\n\t\tos=-coff\n\t\t;;\n\ttic55x-*)\n\t\tos=-coff\n\t\t;;\n\ttic6x-*)\n\t\tos=-coff\n\t\t;;\n\t# This must come before the *-dec entry.\n\tpdp10-*)\n\t\tos=-tops20\n\t\t;;\n\tpdp11-*)\n\t\tos=-none\n\t\t;;\n\t*-dec | vax-*)\n\t\tos=-ultrix4.2\n\t\t;;\n\tm68*-apollo)\n\t\tos=-domain\n\t\t;;\n\ti386-sun)\n\t\tos=-sunos4.0.2\n\t\t;;\n\tm68000-sun)\n\t\tos=-sunos3\n\t\t;;\n\tm68*-cisco)\n\t\tos=-aout\n\t\t;;\n\tmep-*)\n\t\tos=-elf\n\t\t;;\n\tmips*-cisco)\n\t\tos=-elf\n\t\t;;\n\tmips*-*)\n\t\tos=-elf\n\t\t;;\n\tor32-*)\n\t\tos=-coff\n\t\t;;\n\t*-tti)\t# must be before sparc entry or we get the wrong os.\n\t\tos=-sysv3\n\t\t;;\n\tsparc-* | *-sun)\n\t\tos=-sunos4.1.1\n\t\t;;\n\t*-be)\n\t\tos=-beos\n\t\t;;\n\t*-haiku)\n\t\tos=-haiku\n\t\t;;\n\t*-ibm)\n\t\tos=-aix\n\t\t;;\n\t*-knuth)\n\t\tos=-mmixware\n\t\t;;\n\t*-wec)\n\t\tos=-proelf\n\t\t;;\n\t*-winbond)\n\t\tos=-proelf\n\t\t;;\n\t*-oki)\n\t\tos=-proelf\n\t\t;;\n\t*-hp)\n\t\tos=-hpux\n\t\t;;\n\t*-hitachi)\n\t\tos=-hiux\n\t\t;;\n\ti860-* | *-att | *-ncr | *-altos | *-motorola | *-convergent)\n\t\tos=-sysv\n\t\t;;\n\t*-cbm)\n\t\tos=-amigaos\n\t\t;;\n\t*-dg)\n\t\tos=-dgux\n\t\t;;\n\t*-dolphin)\n\t\tos=-sysv3\n\t\t;;\n\tm68k-ccur)\n\t\tos=-rtu\n\t\t;;\n\tm88k-omron*)\n\t\tos=-luna\n\t\t;;\n\t*-next )\n\t\tos=-nextstep\n\t\t;;\n\t*-sequent)\n\t\tos=-ptx\n\t\t;;\n\t*-crds)\n\t\tos=-unos\n\t\t;;\n\t*-ns)\n\t\tos=-genix\n\t\t;;\n\ti370-*)\n\t\tos=-mvs\n\t\t;;\n\t*-next)\n\t\tos=-nextstep3\n\t\t;;\n\t*-gould)\n\t\tos=-sysv\n\t\t;;\n\t*-highlevel)\n\t\tos=-bsd\n\t\t;;\n\t*-encore)\n\t\tos=-bsd\n\t\t;;\n\t*-sgi)\n\t\tos=-irix\n\t\t;;\n\t*-siemens)\n\t\tos=-sysv4\n\t\t;;\n\t*-masscomp)\n\t\tos=-rtu\n\t\t;;\n\tf30[01]-fujitsu | f700-fujitsu)\n\t\tos=-uxpv\n\t\t;;\n\t*-rom68k)\n\t\tos=-coff\n\t\t;;\n\t*-*bug)\n\t\tos=-coff\n\t\t;;\n\t*-apple)\n\t\tos=-macos\n\t\t;;\n\t*-atari*)\n\t\tos=-mint\n\t\t;;\n\t*)\n\t\tos=-none\n\t\t;;\nesac\nfi\n\n# Here we handle the case where we know the os, and the CPU type, but not the\n# manufacturer.  We pick the logical manufacturer.\nvendor=unknown\ncase $basic_machine in\n\t*-unknown)\n\t\tcase $os in\n\t\t\t-riscix*)\n\t\t\t\tvendor=acorn\n\t\t\t\t;;\n\t\t\t-sunos*)\n\t\t\t\tvendor=sun\n\t\t\t\t;;\n\t\t\t-cnk*|-aix*)\n\t\t\t\tvendor=ibm\n\t\t\t\t;;\n\t\t\t-beos*)\n\t\t\t\tvendor=be\n\t\t\t\t;;\n\t\t\t-hpux*)\n\t\t\t\tvendor=hp\n\t\t\t\t;;\n\t\t\t-mpeix*)\n\t\t\t\tvendor=hp\n\t\t\t\t;;\n\t\t\t-hiux*)\n\t\t\t\tvendor=hitachi\n\t\t\t\t;;\n\t\t\t-unos*)\n\t\t\t\tvendor=crds\n\t\t\t\t;;\n\t\t\t-dgux*)\n\t\t\t\tvendor=dg\n\t\t\t\t;;\n\t\t\t-luna*)\n\t\t\t\tvendor=omron\n\t\t\t\t;;\n\t\t\t-genix*)\n\t\t\t\tvendor=ns\n\t\t\t\t;;\n\t\t\t-mvs* | -opened*)\n\t\t\t\tvendor=ibm\n\t\t\t\t;;\n\t\t\t-os400*)\n\t\t\t\tvendor=ibm\n\t\t\t\t;;\n\t\t\t-ptx*)\n\t\t\t\tvendor=sequent\n\t\t\t\t;;\n\t\t\t-tpf*)\n\t\t\t\tvendor=ibm\n\t\t\t\t;;\n\t\t\t-vxsim* | -vxworks* | -windiss*)\n\t\t\t\tvendor=wrs\n\t\t\t\t;;\n\t\t\t-aux*)\n\t\t\t\tvendor=apple\n\t\t\t\t;;\n\t\t\t-hms*)\n\t\t\t\tvendor=hitachi\n\t\t\t\t;;\n\t\t\t-mpw* | -macos*)\n\t\t\t\tvendor=apple\n\t\t\t\t;;\n\t\t\t-*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*)\n\t\t\t\tvendor=atari\n\t\t\t\t;;\n\t\t\t-vos*)\n\t\t\t\tvendor=stratus\n\t\t\t\t;;\n\t\tesac\n\t\tbasic_machine=`echo $basic_machine | sed \"s/unknown/$vendor/\"`\n\t\t;;\nesac\n\necho $basic_machine$os\nexit\n\n# Local variables:\n# eval: (add-hook 'write-file-hooks 'time-stamp)\n# time-stamp-start: \"timestamp='\"\n# time-stamp-format: \"%:y-%02m-%02d\"\n# time-stamp-end: \"'\"\n# End:\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.8/deps/jemalloc/configure",
    "content": "#! /bin/sh\n# Guess values for system-dependent variables and create Makefiles.\n# Generated by GNU Autoconf 2.69.\n#\n#\n# Copyright (C) 1992-1996, 1998-2012 Free Software Foundation, Inc.\n#\n#\n# This configure script is free software; the Free Software Foundation\n# gives unlimited permission to copy, distribute and modify it.\n## -------------------- ##\n## M4sh Initialization. ##\n## -------------------- ##\n\n# Be more Bourne compatible\nDUALCASE=1; export DUALCASE # for MKS sh\nif test -n \"${ZSH_VERSION+set}\" && (emulate sh) >/dev/null 2>&1; then :\n  emulate sh\n  NULLCMD=:\n  # Pre-4.2 versions of Zsh do word splitting on ${1+\"$@\"}, which\n  # is contrary to our usage.  Disable this feature.\n  alias -g '${1+\"$@\"}'='\"$@\"'\n  setopt NO_GLOB_SUBST\nelse\n  case `(set -o) 2>/dev/null` in #(\n  *posix*) :\n    set -o posix ;; #(\n  *) :\n     ;;\nesac\nfi\n\n\nas_nl='\n'\nexport as_nl\n# Printing a long string crashes Solaris 7 /usr/bin/printf.\nas_echo='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\'\nas_echo=$as_echo$as_echo$as_echo$as_echo$as_echo\nas_echo=$as_echo$as_echo$as_echo$as_echo$as_echo$as_echo\n# Prefer a ksh shell builtin over an external printf program on Solaris,\n# but without wasting forks for bash or zsh.\nif test -z \"$BASH_VERSION$ZSH_VERSION\" \\\n    && (test \"X`print -r -- $as_echo`\" = \"X$as_echo\") 2>/dev/null; then\n  as_echo='print -r --'\n  as_echo_n='print -rn --'\nelif (test \"X`printf %s $as_echo`\" = \"X$as_echo\") 2>/dev/null; then\n  as_echo='printf %s\\n'\n  as_echo_n='printf %s'\nelse\n  if test \"X`(/usr/ucb/echo -n -n $as_echo) 2>/dev/null`\" = \"X-n $as_echo\"; then\n    as_echo_body='eval /usr/ucb/echo -n \"$1$as_nl\"'\n    as_echo_n='/usr/ucb/echo -n'\n  else\n    as_echo_body='eval expr \"X$1\" : \"X\\\\(.*\\\\)\"'\n    as_echo_n_body='eval\n      arg=$1;\n      case $arg in #(\n      *\"$as_nl\"*)\n\texpr \"X$arg\" : \"X\\\\(.*\\\\)$as_nl\";\n\targ=`expr \"X$arg\" : \".*$as_nl\\\\(.*\\\\)\"`;;\n      esac;\n      expr \"X$arg\" : \"X\\\\(.*\\\\)\" | tr -d \"$as_nl\"\n    '\n    export as_echo_n_body\n    as_echo_n='sh -c $as_echo_n_body as_echo'\n  fi\n  export as_echo_body\n  as_echo='sh -c $as_echo_body as_echo'\nfi\n\n# The user is always right.\nif test \"${PATH_SEPARATOR+set}\" != set; then\n  PATH_SEPARATOR=:\n  (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && {\n    (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 ||\n      PATH_SEPARATOR=';'\n  }\nfi\n\n\n# IFS\n# We need space, tab and new line, in precisely that order.  Quoting is\n# there to prevent editors from complaining about space-tab.\n# (If _AS_PATH_WALK were called with IFS unset, it would disable word\n# splitting by setting IFS to empty value.)\nIFS=\" \"\"\t$as_nl\"\n\n# Find who we are.  Look in the path if we contain no directory separator.\nas_myself=\ncase $0 in #((\n  *[\\\\/]* ) as_myself=$0 ;;\n  *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR\nfor as_dir in $PATH\ndo\n  IFS=$as_save_IFS\n  test -z \"$as_dir\" && as_dir=.\n    test -r \"$as_dir/$0\" && as_myself=$as_dir/$0 && break\n  done\nIFS=$as_save_IFS\n\n     ;;\nesac\n# We did not find ourselves, most probably we were run as `sh COMMAND'\n# in which case we are not to be found in the path.\nif test \"x$as_myself\" = x; then\n  as_myself=$0\nfi\nif test ! -f \"$as_myself\"; then\n  $as_echo \"$as_myself: error: cannot find myself; rerun with an absolute file name\" >&2\n  exit 1\nfi\n\n# Unset variables that we do not need and which cause bugs (e.g. in\n# pre-3.0 UWIN ksh).  But do not cause bugs in bash 2.01; the \"|| exit 1\"\n# suppresses any \"Segmentation fault\" message there.  '((' could\n# trigger a bug in pdksh 5.2.14.\nfor as_var in BASH_ENV ENV MAIL MAILPATH\ndo eval test x\\${$as_var+set} = xset \\\n  && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || :\ndone\nPS1='$ '\nPS2='> '\nPS4='+ '\n\n# NLS nuisances.\nLC_ALL=C\nexport LC_ALL\nLANGUAGE=C\nexport LANGUAGE\n\n# CDPATH.\n(unset CDPATH) >/dev/null 2>&1 && unset CDPATH\n\n# Use a proper internal environment variable to ensure we don't fall\n  # into an infinite loop, continuously re-executing ourselves.\n  if test x\"${_as_can_reexec}\" != xno && test \"x$CONFIG_SHELL\" != x; then\n    _as_can_reexec=no; export _as_can_reexec;\n    # We cannot yet assume a decent shell, so we have to provide a\n# neutralization value for shells without unset; and this also\n# works around shells that cannot unset nonexistent variables.\n# Preserve -v and -x to the replacement shell.\nBASH_ENV=/dev/null\nENV=/dev/null\n(unset BASH_ENV) >/dev/null 2>&1 && unset BASH_ENV ENV\ncase $- in # ((((\n  *v*x* | *x*v* ) as_opts=-vx ;;\n  *v* ) as_opts=-v ;;\n  *x* ) as_opts=-x ;;\n  * ) as_opts= ;;\nesac\nexec $CONFIG_SHELL $as_opts \"$as_myself\" ${1+\"$@\"}\n# Admittedly, this is quite paranoid, since all the known shells bail\n# out after a failed `exec'.\n$as_echo \"$0: could not re-execute with $CONFIG_SHELL\" >&2\nas_fn_exit 255\n  fi\n  # We don't want this to propagate to other subprocesses.\n          { _as_can_reexec=; unset _as_can_reexec;}\nif test \"x$CONFIG_SHELL\" = x; then\n  as_bourne_compatible=\"if test -n \\\"\\${ZSH_VERSION+set}\\\" && (emulate sh) >/dev/null 2>&1; then :\n  emulate sh\n  NULLCMD=:\n  # Pre-4.2 versions of Zsh do word splitting on \\${1+\\\"\\$@\\\"}, which\n  # is contrary to our usage.  Disable this feature.\n  alias -g '\\${1+\\\"\\$@\\\"}'='\\\"\\$@\\\"'\n  setopt NO_GLOB_SUBST\nelse\n  case \\`(set -o) 2>/dev/null\\` in #(\n  *posix*) :\n    set -o posix ;; #(\n  *) :\n     ;;\nesac\nfi\n\"\n  as_required=\"as_fn_return () { (exit \\$1); }\nas_fn_success () { as_fn_return 0; }\nas_fn_failure () { as_fn_return 1; }\nas_fn_ret_success () { return 0; }\nas_fn_ret_failure () { return 1; }\n\nexitcode=0\nas_fn_success || { exitcode=1; echo as_fn_success failed.; }\nas_fn_failure && { exitcode=1; echo as_fn_failure succeeded.; }\nas_fn_ret_success || { exitcode=1; echo as_fn_ret_success failed.; }\nas_fn_ret_failure && { exitcode=1; echo as_fn_ret_failure succeeded.; }\nif ( set x; as_fn_ret_success y && test x = \\\"\\$1\\\" ); then :\n\nelse\n  exitcode=1; echo positional parameters were not saved.\nfi\ntest x\\$exitcode = x0 || exit 1\ntest -x / || exit 1\"\n  as_suggested=\"  as_lineno_1=\";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested\" as_lineno_1a=\\$LINENO\n  as_lineno_2=\";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested\" as_lineno_2a=\\$LINENO\n  eval 'test \\\"x\\$as_lineno_1'\\$as_run'\\\" != \\\"x\\$as_lineno_2'\\$as_run'\\\" &&\n  test \\\"x\\`expr \\$as_lineno_1'\\$as_run' + 1\\`\\\" = \\\"x\\$as_lineno_2'\\$as_run'\\\"' || exit 1\ntest \\$(( 1 + 1 )) = 2 || exit 1\"\n  if (eval \"$as_required\") 2>/dev/null; then :\n  as_have_required=yes\nelse\n  as_have_required=no\nfi\n  if test x$as_have_required = xyes && (eval \"$as_suggested\") 2>/dev/null; then :\n\nelse\n  as_save_IFS=$IFS; IFS=$PATH_SEPARATOR\nas_found=false\nfor as_dir in /bin$PATH_SEPARATOR/usr/bin$PATH_SEPARATOR$PATH\ndo\n  IFS=$as_save_IFS\n  test -z \"$as_dir\" && as_dir=.\n  as_found=:\n  case $as_dir in #(\n\t /*)\n\t   for as_base in sh bash ksh sh5; do\n\t     # Try only shells that exist, to save several forks.\n\t     as_shell=$as_dir/$as_base\n\t     if { test -f \"$as_shell\" || test -f \"$as_shell.exe\"; } &&\n\t\t    { $as_echo \"$as_bourne_compatible\"\"$as_required\" | as_run=a \"$as_shell\"; } 2>/dev/null; then :\n  CONFIG_SHELL=$as_shell as_have_required=yes\n\t\t   if { $as_echo \"$as_bourne_compatible\"\"$as_suggested\" | as_run=a \"$as_shell\"; } 2>/dev/null; then :\n  break 2\nfi\nfi\n\t   done;;\n       esac\n  as_found=false\ndone\n$as_found || { if { test -f \"$SHELL\" || test -f \"$SHELL.exe\"; } &&\n\t      { $as_echo \"$as_bourne_compatible\"\"$as_required\" | as_run=a \"$SHELL\"; } 2>/dev/null; then :\n  CONFIG_SHELL=$SHELL as_have_required=yes\nfi; }\nIFS=$as_save_IFS\n\n\n      if test \"x$CONFIG_SHELL\" != x; then :\n  export CONFIG_SHELL\n             # We cannot yet assume a decent shell, so we have to provide a\n# neutralization value for shells without unset; and this also\n# works around shells that cannot unset nonexistent variables.\n# Preserve -v and -x to the replacement shell.\nBASH_ENV=/dev/null\nENV=/dev/null\n(unset BASH_ENV) >/dev/null 2>&1 && unset BASH_ENV ENV\ncase $- in # ((((\n  *v*x* | *x*v* ) as_opts=-vx ;;\n  *v* ) as_opts=-v ;;\n  *x* ) as_opts=-x ;;\n  * ) as_opts= ;;\nesac\nexec $CONFIG_SHELL $as_opts \"$as_myself\" ${1+\"$@\"}\n# Admittedly, this is quite paranoid, since all the known shells bail\n# out after a failed `exec'.\n$as_echo \"$0: could not re-execute with $CONFIG_SHELL\" >&2\nexit 255\nfi\n\n    if test x$as_have_required = xno; then :\n  $as_echo \"$0: This script requires a shell more modern than all\"\n  $as_echo \"$0: the shells that I found on your system.\"\n  if test x${ZSH_VERSION+set} = xset ; then\n    $as_echo \"$0: In particular, zsh $ZSH_VERSION has bugs and should\"\n    $as_echo \"$0: be upgraded to zsh 4.3.4 or later.\"\n  else\n    $as_echo \"$0: Please tell bug-autoconf@gnu.org about your system,\n$0: including any error possibly output before this\n$0: message. Then install a modern shell, or manually run\n$0: the script under such a shell if you do have one.\"\n  fi\n  exit 1\nfi\nfi\nfi\nSHELL=${CONFIG_SHELL-/bin/sh}\nexport SHELL\n# Unset more variables known to interfere with behavior of common tools.\nCLICOLOR_FORCE= GREP_OPTIONS=\nunset CLICOLOR_FORCE GREP_OPTIONS\n\n## --------------------- ##\n## M4sh Shell Functions. ##\n## --------------------- ##\n# as_fn_unset VAR\n# ---------------\n# Portably unset VAR.\nas_fn_unset ()\n{\n  { eval $1=; unset $1;}\n}\nas_unset=as_fn_unset\n\n# as_fn_set_status STATUS\n# -----------------------\n# Set $? to STATUS, without forking.\nas_fn_set_status ()\n{\n  return $1\n} # as_fn_set_status\n\n# as_fn_exit STATUS\n# -----------------\n# Exit the shell with STATUS, even in a \"trap 0\" or \"set -e\" context.\nas_fn_exit ()\n{\n  set +e\n  as_fn_set_status $1\n  exit $1\n} # as_fn_exit\n\n# as_fn_mkdir_p\n# -------------\n# Create \"$as_dir\" as a directory, including parents if necessary.\nas_fn_mkdir_p ()\n{\n\n  case $as_dir in #(\n  -*) as_dir=./$as_dir;;\n  esac\n  test -d \"$as_dir\" || eval $as_mkdir_p || {\n    as_dirs=\n    while :; do\n      case $as_dir in #(\n      *\\'*) as_qdir=`$as_echo \"$as_dir\" | sed \"s/'/'\\\\\\\\\\\\\\\\''/g\"`;; #'(\n      *) as_qdir=$as_dir;;\n      esac\n      as_dirs=\"'$as_qdir' $as_dirs\"\n      as_dir=`$as_dirname -- \"$as_dir\" ||\n$as_expr X\"$as_dir\" : 'X\\(.*[^/]\\)//*[^/][^/]*/*$' \\| \\\n\t X\"$as_dir\" : 'X\\(//\\)[^/]' \\| \\\n\t X\"$as_dir\" : 'X\\(//\\)$' \\| \\\n\t X\"$as_dir\" : 'X\\(/\\)' \\| . 2>/dev/null ||\n$as_echo X\"$as_dir\" |\n    sed '/^X\\(.*[^/]\\)\\/\\/*[^/][^/]*\\/*$/{\n\t    s//\\1/\n\t    q\n\t  }\n\t  /^X\\(\\/\\/\\)[^/].*/{\n\t    s//\\1/\n\t    q\n\t  }\n\t  /^X\\(\\/\\/\\)$/{\n\t    s//\\1/\n\t    q\n\t  }\n\t  /^X\\(\\/\\).*/{\n\t    s//\\1/\n\t    q\n\t  }\n\t  s/.*/./; q'`\n      test -d \"$as_dir\" && break\n    done\n    test -z \"$as_dirs\" || eval \"mkdir $as_dirs\"\n  } || test -d \"$as_dir\" || as_fn_error $? \"cannot create directory $as_dir\"\n\n\n} # as_fn_mkdir_p\n\n# as_fn_executable_p FILE\n# -----------------------\n# Test if FILE is an executable regular file.\nas_fn_executable_p ()\n{\n  test -f \"$1\" && test -x \"$1\"\n} # as_fn_executable_p\n# as_fn_append VAR VALUE\n# ----------------------\n# Append the text in VALUE to the end of the definition contained in VAR. Take\n# advantage of any shell optimizations that allow amortized linear growth over\n# repeated appends, instead of the typical quadratic growth present in naive\n# implementations.\nif (eval \"as_var=1; as_var+=2; test x\\$as_var = x12\") 2>/dev/null; then :\n  eval 'as_fn_append ()\n  {\n    eval $1+=\\$2\n  }'\nelse\n  as_fn_append ()\n  {\n    eval $1=\\$$1\\$2\n  }\nfi # as_fn_append\n\n# as_fn_arith ARG...\n# ------------------\n# Perform arithmetic evaluation on the ARGs, and store the result in the\n# global $as_val. Take advantage of shells that can avoid forks. The arguments\n# must be portable across $(()) and expr.\nif (eval \"test \\$(( 1 + 1 )) = 2\") 2>/dev/null; then :\n  eval 'as_fn_arith ()\n  {\n    as_val=$(( $* ))\n  }'\nelse\n  as_fn_arith ()\n  {\n    as_val=`expr \"$@\" || test $? -eq 1`\n  }\nfi # as_fn_arith\n\n\n# as_fn_error STATUS ERROR [LINENO LOG_FD]\n# ----------------------------------------\n# Output \"`basename $0`: error: ERROR\" to stderr. If LINENO and LOG_FD are\n# provided, also output the error to LOG_FD, referencing LINENO. Then exit the\n# script with STATUS, using 1 if that was 0.\nas_fn_error ()\n{\n  as_status=$1; test $as_status -eq 0 && as_status=1\n  if test \"$4\"; then\n    as_lineno=${as_lineno-\"$3\"} as_lineno_stack=as_lineno_stack=$as_lineno_stack\n    $as_echo \"$as_me:${as_lineno-$LINENO}: error: $2\" >&$4\n  fi\n  $as_echo \"$as_me: error: $2\" >&2\n  as_fn_exit $as_status\n} # as_fn_error\n\nif expr a : '\\(a\\)' >/dev/null 2>&1 &&\n   test \"X`expr 00001 : '.*\\(...\\)'`\" = X001; then\n  as_expr=expr\nelse\n  as_expr=false\nfi\n\nif (basename -- /) >/dev/null 2>&1 && test \"X`basename -- / 2>&1`\" = \"X/\"; then\n  as_basename=basename\nelse\n  as_basename=false\nfi\n\nif (as_dir=`dirname -- /` && test \"X$as_dir\" = X/) >/dev/null 2>&1; then\n  as_dirname=dirname\nelse\n  as_dirname=false\nfi\n\nas_me=`$as_basename -- \"$0\" ||\n$as_expr X/\"$0\" : '.*/\\([^/][^/]*\\)/*$' \\| \\\n\t X\"$0\" : 'X\\(//\\)$' \\| \\\n\t X\"$0\" : 'X\\(/\\)' \\| . 2>/dev/null ||\n$as_echo X/\"$0\" |\n    sed '/^.*\\/\\([^/][^/]*\\)\\/*$/{\n\t    s//\\1/\n\t    q\n\t  }\n\t  /^X\\/\\(\\/\\/\\)$/{\n\t    s//\\1/\n\t    q\n\t  }\n\t  /^X\\/\\(\\/\\).*/{\n\t    s//\\1/\n\t    q\n\t  }\n\t  s/.*/./; q'`\n\n# Avoid depending upon Character Ranges.\nas_cr_letters='abcdefghijklmnopqrstuvwxyz'\nas_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ'\nas_cr_Letters=$as_cr_letters$as_cr_LETTERS\nas_cr_digits='0123456789'\nas_cr_alnum=$as_cr_Letters$as_cr_digits\n\n\n  as_lineno_1=$LINENO as_lineno_1a=$LINENO\n  as_lineno_2=$LINENO as_lineno_2a=$LINENO\n  eval 'test \"x$as_lineno_1'$as_run'\" != \"x$as_lineno_2'$as_run'\" &&\n  test \"x`expr $as_lineno_1'$as_run' + 1`\" = \"x$as_lineno_2'$as_run'\"' || {\n  # Blame Lee E. McMahon (1931-1989) for sed's syntax.  :-)\n  sed -n '\n    p\n    /[$]LINENO/=\n  ' <$as_myself |\n    sed '\n      s/[$]LINENO.*/&-/\n      t lineno\n      b\n      :lineno\n      N\n      :loop\n      s/[$]LINENO\\([^'$as_cr_alnum'_].*\\n\\)\\(.*\\)/\\2\\1\\2/\n      t loop\n      s/-\\n.*//\n    ' >$as_me.lineno &&\n  chmod +x \"$as_me.lineno\" ||\n    { $as_echo \"$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell\" >&2; as_fn_exit 1; }\n\n  # If we had to re-execute with $CONFIG_SHELL, we're ensured to have\n  # already done that, so ensure we don't try to do so again and fall\n  # in an infinite loop.  This has already happened in practice.\n  _as_can_reexec=no; export _as_can_reexec\n  # Don't try to exec as it changes $[0], causing all sort of problems\n  # (the dirname of $[0] is not the place where we might find the\n  # original and so on.  Autoconf is especially sensitive to this).\n  . \"./$as_me.lineno\"\n  # Exit status is that of the last command.\n  exit\n}\n\nECHO_C= ECHO_N= ECHO_T=\ncase `echo -n x` in #(((((\n-n*)\n  case `echo 'xy\\c'` in\n  *c*) ECHO_T='\t';;\t# ECHO_T is single tab character.\n  xy)  ECHO_C='\\c';;\n  *)   echo `echo ksh88 bug on AIX 6.1` > /dev/null\n       ECHO_T='\t';;\n  esac;;\n*)\n  ECHO_N='-n';;\nesac\n\nrm -f conf$$ conf$$.exe conf$$.file\nif test -d conf$$.dir; then\n  rm -f conf$$.dir/conf$$.file\nelse\n  rm -f conf$$.dir\n  mkdir conf$$.dir 2>/dev/null\nfi\nif (echo >conf$$.file) 2>/dev/null; then\n  if ln -s conf$$.file conf$$ 2>/dev/null; then\n    as_ln_s='ln -s'\n    # ... but there are two gotchas:\n    # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail.\n    # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable.\n    # In both cases, we have to default to `cp -pR'.\n    ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe ||\n      as_ln_s='cp -pR'\n  elif ln conf$$.file conf$$ 2>/dev/null; then\n    as_ln_s=ln\n  else\n    as_ln_s='cp -pR'\n  fi\nelse\n  as_ln_s='cp -pR'\nfi\nrm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file\nrmdir conf$$.dir 2>/dev/null\n\nif mkdir -p . 2>/dev/null; then\n  as_mkdir_p='mkdir -p \"$as_dir\"'\nelse\n  test -d ./-p && rmdir ./-p\n  as_mkdir_p=false\nfi\n\nas_test_x='test -x'\nas_executable_p=as_fn_executable_p\n\n# Sed expression to map a string onto a valid CPP name.\nas_tr_cpp=\"eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'\"\n\n# Sed expression to map a string onto a valid variable name.\nas_tr_sh=\"eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'\"\n\n\ntest -n \"$DJDIR\" || exec 7<&0 </dev/null\nexec 6>&1\n\n# Name of the host.\n# hostname on some systems (SVR3.2, old GNU/Linux) returns a bogus exit status,\n# so uname gets run too.\nac_hostname=`(hostname || uname -n) 2>/dev/null | sed 1q`\n\n#\n# Initializations.\n#\nac_default_prefix=/usr/local\nac_clean_files=\nac_config_libobj_dir=.\nLIBOBJS=\ncross_compiling=no\nsubdirs=\nMFLAGS=\nMAKEFLAGS=\n\n# Identity of this package.\nPACKAGE_NAME=\nPACKAGE_TARNAME=\nPACKAGE_VERSION=\nPACKAGE_STRING=\nPACKAGE_BUGREPORT=\nPACKAGE_URL=\n\nac_unique_file=\"Makefile.in\"\n# Factoring default headers for most tests.\nac_includes_default=\"\\\n#include <stdio.h>\n#ifdef HAVE_SYS_TYPES_H\n# include <sys/types.h>\n#endif\n#ifdef HAVE_SYS_STAT_H\n# include <sys/stat.h>\n#endif\n#ifdef STDC_HEADERS\n# include <stdlib.h>\n# include <stddef.h>\n#else\n# ifdef HAVE_STDLIB_H\n#  include <stdlib.h>\n# endif\n#endif\n#ifdef HAVE_STRING_H\n# if !defined STDC_HEADERS && defined HAVE_MEMORY_H\n#  include <memory.h>\n# endif\n# include <string.h>\n#endif\n#ifdef HAVE_STRINGS_H\n# include <strings.h>\n#endif\n#ifdef HAVE_INTTYPES_H\n# include <inttypes.h>\n#endif\n#ifdef HAVE_STDINT_H\n# include <stdint.h>\n#endif\n#ifdef HAVE_UNISTD_H\n# include <unistd.h>\n#endif\"\n\nac_subst_vars='LTLIBOBJS\nLIBOBJS\ncfgoutputs_out\ncfgoutputs_in\ncfghdrs_out\ncfghdrs_in\nenable_zone_allocator\nenable_tls\nenable_lazy_lock\nTESTLIBS\njemalloc_version_gid\njemalloc_version_nrev\njemalloc_version_bugfix\njemalloc_version_minor\njemalloc_version_major\njemalloc_version\nenable_cache_oblivious\nenable_xmalloc\nenable_valgrind\nenable_utrace\nenable_fill\nenable_munmap\nenable_tcache\nenable_prof\nenable_stats\nenable_debug\nje_\ninstall_suffix\nprivate_namespace\nJEMALLOC_CPREFIX\nenable_code_coverage\nAUTOCONF\nLD\nRANLIB\nINSTALL_DATA\nINSTALL_SCRIPT\nINSTALL_PROGRAM\nenable_autogen\nRPATH_EXTRA\nCC_MM\nAROUT\nARFLAGS\nMKLIB\nLDTARGET\nCTARGET\nPIC_CFLAGS\nSOREV\nEXTRA_LDFLAGS\nDSO_LDFLAGS\nlibprefix\nexe\na\no\nimportlib\nso\nLD_PRELOAD_VAR\nRPATH\nabi\nAR\nhost_os\nhost_vendor\nhost_cpu\nhost\nbuild_os\nbuild_vendor\nbuild_cpu\nbuild\nEGREP\nGREP\nCPP\nOBJEXT\nEXEEXT\nac_ct_CC\nCPPFLAGS\nLDFLAGS\nCFLAGS\nCC\nXSLROOT\nXSLTPROC\nMANDIR\nDATADIR\nLIBDIR\nINCLUDEDIR\nBINDIR\nPREFIX\nabs_objroot\nobjroot\nabs_srcroot\nsrcroot\nrev\nCONFIG\ntarget_alias\nhost_alias\nbuild_alias\nLIBS\nECHO_T\nECHO_N\nECHO_C\nDEFS\nmandir\nlocaledir\nlibdir\npsdir\npdfdir\ndvidir\nhtmldir\ninfodir\ndocdir\noldincludedir\nincludedir\nlocalstatedir\nsharedstatedir\nsysconfdir\ndatadir\ndatarootdir\nlibexecdir\nsbindir\nbindir\nprogram_transform_name\nprefix\nexec_prefix\nPACKAGE_URL\nPACKAGE_BUGREPORT\nPACKAGE_STRING\nPACKAGE_VERSION\nPACKAGE_TARNAME\nPACKAGE_NAME\nPATH_SEPARATOR\nSHELL'\nac_subst_files=''\nac_user_opts='\nenable_option_checking\nwith_xslroot\nwith_rpath\nenable_autogen\nenable_code_coverage\nwith_mangling\nwith_jemalloc_prefix\nwith_export\nwith_private_namespace\nwith_install_suffix\nenable_cc_silence\nenable_debug\nenable_ivsalloc\nenable_stats\nenable_prof\nenable_prof_libunwind\nwith_static_libunwind\nenable_prof_libgcc\nenable_prof_gcc\nenable_tcache\nenable_munmap\nenable_fill\nenable_utrace\nenable_valgrind\nenable_xmalloc\nenable_cache_oblivious\nwith_lg_tiny_min\nwith_lg_quantum\nwith_lg_page\nwith_lg_page_sizes\nwith_lg_size_class_group\nenable_lazy_lock\nenable_tls\nenable_zone_allocator\n'\n      ac_precious_vars='build_alias\nhost_alias\ntarget_alias\nCC\nCFLAGS\nLDFLAGS\nLIBS\nCPPFLAGS\nCPP'\n\n\n# Initialize some variables set by options.\nac_init_help=\nac_init_version=false\nac_unrecognized_opts=\nac_unrecognized_sep=\n# The variables have the same names as the options, with\n# dashes changed to underlines.\ncache_file=/dev/null\nexec_prefix=NONE\nno_create=\nno_recursion=\nprefix=NONE\nprogram_prefix=NONE\nprogram_suffix=NONE\nprogram_transform_name=s,x,x,\nsilent=\nsite=\nsrcdir=\nverbose=\nx_includes=NONE\nx_libraries=NONE\n\n# Installation directory options.\n# These are left unexpanded so users can \"make install exec_prefix=/foo\"\n# and all the variables that are supposed to be based on exec_prefix\n# by default will actually change.\n# Use braces instead of parens because sh, perl, etc. also accept them.\n# (The list follows the same order as the GNU Coding Standards.)\nbindir='${exec_prefix}/bin'\nsbindir='${exec_prefix}/sbin'\nlibexecdir='${exec_prefix}/libexec'\ndatarootdir='${prefix}/share'\ndatadir='${datarootdir}'\nsysconfdir='${prefix}/etc'\nsharedstatedir='${prefix}/com'\nlocalstatedir='${prefix}/var'\nincludedir='${prefix}/include'\noldincludedir='/usr/include'\ndocdir='${datarootdir}/doc/${PACKAGE}'\ninfodir='${datarootdir}/info'\nhtmldir='${docdir}'\ndvidir='${docdir}'\npdfdir='${docdir}'\npsdir='${docdir}'\nlibdir='${exec_prefix}/lib'\nlocaledir='${datarootdir}/locale'\nmandir='${datarootdir}/man'\n\nac_prev=\nac_dashdash=\nfor ac_option\ndo\n  # If the previous option needs an argument, assign it.\n  if test -n \"$ac_prev\"; then\n    eval $ac_prev=\\$ac_option\n    ac_prev=\n    continue\n  fi\n\n  case $ac_option in\n  *=?*) ac_optarg=`expr \"X$ac_option\" : '[^=]*=\\(.*\\)'` ;;\n  *=)   ac_optarg= ;;\n  *)    ac_optarg=yes ;;\n  esac\n\n  # Accept the important Cygnus configure options, so we can diagnose typos.\n\n  case $ac_dashdash$ac_option in\n  --)\n    ac_dashdash=yes ;;\n\n  -bindir | --bindir | --bindi | --bind | --bin | --bi)\n    ac_prev=bindir ;;\n  -bindir=* | --bindir=* | --bindi=* | --bind=* | --bin=* | --bi=*)\n    bindir=$ac_optarg ;;\n\n  -build | --build | --buil | --bui | --bu)\n    ac_prev=build_alias ;;\n  -build=* | --build=* | --buil=* | --bui=* | --bu=*)\n    build_alias=$ac_optarg ;;\n\n  -cache-file | --cache-file | --cache-fil | --cache-fi \\\n  | --cache-f | --cache- | --cache | --cach | --cac | --ca | --c)\n    ac_prev=cache_file ;;\n  -cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \\\n  | --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* | --c=*)\n    cache_file=$ac_optarg ;;\n\n  --config-cache | -C)\n    cache_file=config.cache ;;\n\n  -datadir | --datadir | --datadi | --datad)\n    ac_prev=datadir ;;\n  -datadir=* | --datadir=* | --datadi=* | --datad=*)\n    datadir=$ac_optarg ;;\n\n  -datarootdir | --datarootdir | --datarootdi | --datarootd | --dataroot \\\n  | --dataroo | --dataro | --datar)\n    ac_prev=datarootdir ;;\n  -datarootdir=* | --datarootdir=* | --datarootdi=* | --datarootd=* \\\n  | --dataroot=* | --dataroo=* | --dataro=* | --datar=*)\n    datarootdir=$ac_optarg ;;\n\n  -disable-* | --disable-*)\n    ac_useropt=`expr \"x$ac_option\" : 'x-*disable-\\(.*\\)'`\n    # Reject names that are not valid shell variable names.\n    expr \"x$ac_useropt\" : \".*[^-+._$as_cr_alnum]\" >/dev/null &&\n      as_fn_error $? \"invalid feature name: $ac_useropt\"\n    ac_useropt_orig=$ac_useropt\n    ac_useropt=`$as_echo \"$ac_useropt\" | sed 's/[-+.]/_/g'`\n    case $ac_user_opts in\n      *\"\n\"enable_$ac_useropt\"\n\"*) ;;\n      *) ac_unrecognized_opts=\"$ac_unrecognized_opts$ac_unrecognized_sep--disable-$ac_useropt_orig\"\n\t ac_unrecognized_sep=', ';;\n    esac\n    eval enable_$ac_useropt=no ;;\n\n  -docdir | --docdir | --docdi | --doc | --do)\n    ac_prev=docdir ;;\n  -docdir=* | --docdir=* | --docdi=* | --doc=* | --do=*)\n    docdir=$ac_optarg ;;\n\n  -dvidir | --dvidir | --dvidi | --dvid | --dvi | --dv)\n    ac_prev=dvidir ;;\n  -dvidir=* | --dvidir=* | --dvidi=* | --dvid=* | --dvi=* | --dv=*)\n    dvidir=$ac_optarg ;;\n\n  -enable-* | --enable-*)\n    ac_useropt=`expr \"x$ac_option\" : 'x-*enable-\\([^=]*\\)'`\n    # Reject names that are not valid shell variable names.\n    expr \"x$ac_useropt\" : \".*[^-+._$as_cr_alnum]\" >/dev/null &&\n      as_fn_error $? \"invalid feature name: $ac_useropt\"\n    ac_useropt_orig=$ac_useropt\n    ac_useropt=`$as_echo \"$ac_useropt\" | sed 's/[-+.]/_/g'`\n    case $ac_user_opts in\n      *\"\n\"enable_$ac_useropt\"\n\"*) ;;\n      *) ac_unrecognized_opts=\"$ac_unrecognized_opts$ac_unrecognized_sep--enable-$ac_useropt_orig\"\n\t ac_unrecognized_sep=', ';;\n    esac\n    eval enable_$ac_useropt=\\$ac_optarg ;;\n\n  -exec-prefix | --exec_prefix | --exec-prefix | --exec-prefi \\\n  | --exec-pref | --exec-pre | --exec-pr | --exec-p | --exec- \\\n  | --exec | --exe | --ex)\n    ac_prev=exec_prefix ;;\n  -exec-prefix=* | --exec_prefix=* | --exec-prefix=* | --exec-prefi=* \\\n  | --exec-pref=* | --exec-pre=* | --exec-pr=* | --exec-p=* | --exec-=* \\\n  | --exec=* | --exe=* | --ex=*)\n    exec_prefix=$ac_optarg ;;\n\n  -gas | --gas | --ga | --g)\n    # Obsolete; use --with-gas.\n    with_gas=yes ;;\n\n  -help | --help | --hel | --he | -h)\n    ac_init_help=long ;;\n  -help=r* | --help=r* | --hel=r* | --he=r* | -hr*)\n    ac_init_help=recursive ;;\n  -help=s* | --help=s* | --hel=s* | --he=s* | -hs*)\n    ac_init_help=short ;;\n\n  -host | --host | --hos | --ho)\n    ac_prev=host_alias ;;\n  -host=* | --host=* | --hos=* | --ho=*)\n    host_alias=$ac_optarg ;;\n\n  -htmldir | --htmldir | --htmldi | --htmld | --html | --htm | --ht)\n    ac_prev=htmldir ;;\n  -htmldir=* | --htmldir=* | --htmldi=* | --htmld=* | --html=* | --htm=* \\\n  | --ht=*)\n    htmldir=$ac_optarg ;;\n\n  -includedir | --includedir | --includedi | --included | --include \\\n  | --includ | --inclu | --incl | --inc)\n    ac_prev=includedir ;;\n  -includedir=* | --includedir=* | --includedi=* | --included=* | --include=* \\\n  | --includ=* | --inclu=* | --incl=* | --inc=*)\n    includedir=$ac_optarg ;;\n\n  -infodir | --infodir | --infodi | --infod | --info | --inf)\n    ac_prev=infodir ;;\n  -infodir=* | --infodir=* | --infodi=* | --infod=* | --info=* | --inf=*)\n    infodir=$ac_optarg ;;\n\n  -libdir | --libdir | --libdi | --libd)\n    ac_prev=libdir ;;\n  -libdir=* | --libdir=* | --libdi=* | --libd=*)\n    libdir=$ac_optarg ;;\n\n  -libexecdir | --libexecdir | --libexecdi | --libexecd | --libexec \\\n  | --libexe | --libex | --libe)\n    ac_prev=libexecdir ;;\n  -libexecdir=* | --libexecdir=* | --libexecdi=* | --libexecd=* | --libexec=* \\\n  | --libexe=* | --libex=* | --libe=*)\n    libexecdir=$ac_optarg ;;\n\n  -localedir | --localedir | --localedi | --localed | --locale)\n    ac_prev=localedir ;;\n  -localedir=* | --localedir=* | --localedi=* | --localed=* | --locale=*)\n    localedir=$ac_optarg ;;\n\n  -localstatedir | --localstatedir | --localstatedi | --localstated \\\n  | --localstate | --localstat | --localsta | --localst | --locals)\n    ac_prev=localstatedir ;;\n  -localstatedir=* | --localstatedir=* | --localstatedi=* | --localstated=* \\\n  | --localstate=* | --localstat=* | --localsta=* | --localst=* | --locals=*)\n    localstatedir=$ac_optarg ;;\n\n  -mandir | --mandir | --mandi | --mand | --man | --ma | --m)\n    ac_prev=mandir ;;\n  -mandir=* | --mandir=* | --mandi=* | --mand=* | --man=* | --ma=* | --m=*)\n    mandir=$ac_optarg ;;\n\n  -nfp | --nfp | --nf)\n    # Obsolete; use --without-fp.\n    with_fp=no ;;\n\n  -no-create | --no-create | --no-creat | --no-crea | --no-cre \\\n  | --no-cr | --no-c | -n)\n    no_create=yes ;;\n\n  -no-recursion | --no-recursion | --no-recursio | --no-recursi \\\n  | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r)\n    no_recursion=yes ;;\n\n  -oldincludedir | --oldincludedir | --oldincludedi | --oldincluded \\\n  | --oldinclude | --oldinclud | --oldinclu | --oldincl | --oldinc \\\n  | --oldin | --oldi | --old | --ol | --o)\n    ac_prev=oldincludedir ;;\n  -oldincludedir=* | --oldincludedir=* | --oldincludedi=* | --oldincluded=* \\\n  | --oldinclude=* | --oldinclud=* | --oldinclu=* | --oldincl=* | --oldinc=* \\\n  | --oldin=* | --oldi=* | --old=* | --ol=* | --o=*)\n    oldincludedir=$ac_optarg ;;\n\n  -prefix | --prefix | --prefi | --pref | --pre | --pr | --p)\n    ac_prev=prefix ;;\n  -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*)\n    prefix=$ac_optarg ;;\n\n  -program-prefix | --program-prefix | --program-prefi | --program-pref \\\n  | --program-pre | --program-pr | --program-p)\n    ac_prev=program_prefix ;;\n  -program-prefix=* | --program-prefix=* | --program-prefi=* \\\n  | --program-pref=* | --program-pre=* | --program-pr=* | --program-p=*)\n    program_prefix=$ac_optarg ;;\n\n  -program-suffix | --program-suffix | --program-suffi | --program-suff \\\n  | --program-suf | --program-su | --program-s)\n    ac_prev=program_suffix ;;\n  -program-suffix=* | --program-suffix=* | --program-suffi=* \\\n  | --program-suff=* | --program-suf=* | --program-su=* | --program-s=*)\n    program_suffix=$ac_optarg ;;\n\n  -program-transform-name | --program-transform-name \\\n  | --program-transform-nam | --program-transform-na \\\n  | --program-transform-n | --program-transform- \\\n  | --program-transform | --program-transfor \\\n  | --program-transfo | --program-transf \\\n  | --program-trans | --program-tran \\\n  | --progr-tra | --program-tr | --program-t)\n    ac_prev=program_transform_name ;;\n  -program-transform-name=* | --program-transform-name=* \\\n  | --program-transform-nam=* | --program-transform-na=* \\\n  | --program-transform-n=* | --program-transform-=* \\\n  | --program-transform=* | --program-transfor=* \\\n  | --program-transfo=* | --program-transf=* \\\n  | --program-trans=* | --program-tran=* \\\n  | --progr-tra=* | --program-tr=* | --program-t=*)\n    program_transform_name=$ac_optarg ;;\n\n  -pdfdir | --pdfdir | --pdfdi | --pdfd | --pdf | --pd)\n    ac_prev=pdfdir ;;\n  -pdfdir=* | --pdfdir=* | --pdfdi=* | --pdfd=* | --pdf=* | --pd=*)\n    pdfdir=$ac_optarg ;;\n\n  -psdir | --psdir | --psdi | --psd | --ps)\n    ac_prev=psdir ;;\n  -psdir=* | --psdir=* | --psdi=* | --psd=* | --ps=*)\n    psdir=$ac_optarg ;;\n\n  -q | -quiet | --quiet | --quie | --qui | --qu | --q \\\n  | -silent | --silent | --silen | --sile | --sil)\n    silent=yes ;;\n\n  -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb)\n    ac_prev=sbindir ;;\n  -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \\\n  | --sbi=* | --sb=*)\n    sbindir=$ac_optarg ;;\n\n  -sharedstatedir | --sharedstatedir | --sharedstatedi \\\n  | --sharedstated | --sharedstate | --sharedstat | --sharedsta \\\n  | --sharedst | --shareds | --shared | --share | --shar \\\n  | --sha | --sh)\n    ac_prev=sharedstatedir ;;\n  -sharedstatedir=* | --sharedstatedir=* | --sharedstatedi=* \\\n  | --sharedstated=* | --sharedstate=* | --sharedstat=* | --sharedsta=* \\\n  | --sharedst=* | --shareds=* | --shared=* | --share=* | --shar=* \\\n  | --sha=* | --sh=*)\n    sharedstatedir=$ac_optarg ;;\n\n  -site | --site | --sit)\n    ac_prev=site ;;\n  -site=* | --site=* | --sit=*)\n    site=$ac_optarg ;;\n\n  -srcdir | --srcdir | --srcdi | --srcd | --src | --sr)\n    ac_prev=srcdir ;;\n  -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*)\n    srcdir=$ac_optarg ;;\n\n  -sysconfdir | --sysconfdir | --sysconfdi | --sysconfd | --sysconf \\\n  | --syscon | --sysco | --sysc | --sys | --sy)\n    ac_prev=sysconfdir ;;\n  -sysconfdir=* | --sysconfdir=* | --sysconfdi=* | --sysconfd=* | --sysconf=* \\\n  | --syscon=* | --sysco=* | --sysc=* | --sys=* | --sy=*)\n    sysconfdir=$ac_optarg ;;\n\n  -target | --target | --targe | --targ | --tar | --ta | --t)\n    ac_prev=target_alias ;;\n  -target=* | --target=* | --targe=* | --targ=* | --tar=* | --ta=* | --t=*)\n    target_alias=$ac_optarg ;;\n\n  -v | -verbose | --verbose | --verbos | --verbo | --verb)\n    verbose=yes ;;\n\n  -version | --version | --versio | --versi | --vers | -V)\n    ac_init_version=: ;;\n\n  -with-* | --with-*)\n    ac_useropt=`expr \"x$ac_option\" : 'x-*with-\\([^=]*\\)'`\n    # Reject names that are not valid shell variable names.\n    expr \"x$ac_useropt\" : \".*[^-+._$as_cr_alnum]\" >/dev/null &&\n      as_fn_error $? \"invalid package name: $ac_useropt\"\n    ac_useropt_orig=$ac_useropt\n    ac_useropt=`$as_echo \"$ac_useropt\" | sed 's/[-+.]/_/g'`\n    case $ac_user_opts in\n      *\"\n\"with_$ac_useropt\"\n\"*) ;;\n      *) ac_unrecognized_opts=\"$ac_unrecognized_opts$ac_unrecognized_sep--with-$ac_useropt_orig\"\n\t ac_unrecognized_sep=', ';;\n    esac\n    eval with_$ac_useropt=\\$ac_optarg ;;\n\n  -without-* | --without-*)\n    ac_useropt=`expr \"x$ac_option\" : 'x-*without-\\(.*\\)'`\n    # Reject names that are not valid shell variable names.\n    expr \"x$ac_useropt\" : \".*[^-+._$as_cr_alnum]\" >/dev/null &&\n      as_fn_error $? \"invalid package name: $ac_useropt\"\n    ac_useropt_orig=$ac_useropt\n    ac_useropt=`$as_echo \"$ac_useropt\" | sed 's/[-+.]/_/g'`\n    case $ac_user_opts in\n      *\"\n\"with_$ac_useropt\"\n\"*) ;;\n      *) ac_unrecognized_opts=\"$ac_unrecognized_opts$ac_unrecognized_sep--without-$ac_useropt_orig\"\n\t ac_unrecognized_sep=', ';;\n    esac\n    eval with_$ac_useropt=no ;;\n\n  --x)\n    # Obsolete; use --with-x.\n    with_x=yes ;;\n\n  -x-includes | --x-includes | --x-include | --x-includ | --x-inclu \\\n  | --x-incl | --x-inc | --x-in | --x-i)\n    ac_prev=x_includes ;;\n  -x-includes=* | --x-includes=* | --x-include=* | --x-includ=* | --x-inclu=* \\\n  | --x-incl=* | --x-inc=* | --x-in=* | --x-i=*)\n    x_includes=$ac_optarg ;;\n\n  -x-libraries | --x-libraries | --x-librarie | --x-librari \\\n  | --x-librar | --x-libra | --x-libr | --x-lib | --x-li | --x-l)\n    ac_prev=x_libraries ;;\n  -x-libraries=* | --x-libraries=* | --x-librarie=* | --x-librari=* \\\n  | --x-librar=* | --x-libra=* | --x-libr=* | --x-lib=* | --x-li=* | --x-l=*)\n    x_libraries=$ac_optarg ;;\n\n  -*) as_fn_error $? \"unrecognized option: \\`$ac_option'\nTry \\`$0 --help' for more information\"\n    ;;\n\n  *=*)\n    ac_envvar=`expr \"x$ac_option\" : 'x\\([^=]*\\)='`\n    # Reject names that are not valid shell variable names.\n    case $ac_envvar in #(\n      '' | [0-9]* | *[!_$as_cr_alnum]* )\n      as_fn_error $? \"invalid variable name: \\`$ac_envvar'\" ;;\n    esac\n    eval $ac_envvar=\\$ac_optarg\n    export $ac_envvar ;;\n\n  *)\n    # FIXME: should be removed in autoconf 3.0.\n    $as_echo \"$as_me: WARNING: you should use --build, --host, --target\" >&2\n    expr \"x$ac_option\" : \".*[^-._$as_cr_alnum]\" >/dev/null &&\n      $as_echo \"$as_me: WARNING: invalid host type: $ac_option\" >&2\n    : \"${build_alias=$ac_option} ${host_alias=$ac_option} ${target_alias=$ac_option}\"\n    ;;\n\n  esac\ndone\n\nif test -n \"$ac_prev\"; then\n  ac_option=--`echo $ac_prev | sed 's/_/-/g'`\n  as_fn_error $? \"missing argument to $ac_option\"\nfi\n\nif test -n \"$ac_unrecognized_opts\"; then\n  case $enable_option_checking in\n    no) ;;\n    fatal) as_fn_error $? \"unrecognized options: $ac_unrecognized_opts\" ;;\n    *)     $as_echo \"$as_me: WARNING: unrecognized options: $ac_unrecognized_opts\" >&2 ;;\n  esac\nfi\n\n# Check all directory arguments for consistency.\nfor ac_var in\texec_prefix prefix bindir sbindir libexecdir datarootdir \\\n\t\tdatadir sysconfdir sharedstatedir localstatedir includedir \\\n\t\toldincludedir docdir infodir htmldir dvidir pdfdir psdir \\\n\t\tlibdir localedir mandir\ndo\n  eval ac_val=\\$$ac_var\n  # Remove trailing slashes.\n  case $ac_val in\n    */ )\n      ac_val=`expr \"X$ac_val\" : 'X\\(.*[^/]\\)' \\| \"X$ac_val\" : 'X\\(.*\\)'`\n      eval $ac_var=\\$ac_val;;\n  esac\n  # Be sure to have absolute directory names.\n  case $ac_val in\n    [\\\\/$]* | ?:[\\\\/]* )  continue;;\n    NONE | '' ) case $ac_var in *prefix ) continue;; esac;;\n  esac\n  as_fn_error $? \"expected an absolute directory name for --$ac_var: $ac_val\"\ndone\n\n# There might be people who depend on the old broken behavior: `$host'\n# used to hold the argument of --host etc.\n# FIXME: To remove some day.\nbuild=$build_alias\nhost=$host_alias\ntarget=$target_alias\n\n# FIXME: To remove some day.\nif test \"x$host_alias\" != x; then\n  if test \"x$build_alias\" = x; then\n    cross_compiling=maybe\n  elif test \"x$build_alias\" != \"x$host_alias\"; then\n    cross_compiling=yes\n  fi\nfi\n\nac_tool_prefix=\ntest -n \"$host_alias\" && ac_tool_prefix=$host_alias-\n\ntest \"$silent\" = yes && exec 6>/dev/null\n\n\nac_pwd=`pwd` && test -n \"$ac_pwd\" &&\nac_ls_di=`ls -di .` &&\nac_pwd_ls_di=`cd \"$ac_pwd\" && ls -di .` ||\n  as_fn_error $? \"working directory cannot be determined\"\ntest \"X$ac_ls_di\" = \"X$ac_pwd_ls_di\" ||\n  as_fn_error $? \"pwd does not report name of working directory\"\n\n\n# Find the source files, if location was not specified.\nif test -z \"$srcdir\"; then\n  ac_srcdir_defaulted=yes\n  # Try the directory containing this script, then the parent directory.\n  ac_confdir=`$as_dirname -- \"$as_myself\" ||\n$as_expr X\"$as_myself\" : 'X\\(.*[^/]\\)//*[^/][^/]*/*$' \\| \\\n\t X\"$as_myself\" : 'X\\(//\\)[^/]' \\| \\\n\t X\"$as_myself\" : 'X\\(//\\)$' \\| \\\n\t X\"$as_myself\" : 'X\\(/\\)' \\| . 2>/dev/null ||\n$as_echo X\"$as_myself\" |\n    sed '/^X\\(.*[^/]\\)\\/\\/*[^/][^/]*\\/*$/{\n\t    s//\\1/\n\t    q\n\t  }\n\t  /^X\\(\\/\\/\\)[^/].*/{\n\t    s//\\1/\n\t    q\n\t  }\n\t  /^X\\(\\/\\/\\)$/{\n\t    s//\\1/\n\t    q\n\t  }\n\t  /^X\\(\\/\\).*/{\n\t    s//\\1/\n\t    q\n\t  }\n\t  s/.*/./; q'`\n  srcdir=$ac_confdir\n  if test ! -r \"$srcdir/$ac_unique_file\"; then\n    srcdir=..\n  fi\nelse\n  ac_srcdir_defaulted=no\nfi\nif test ! -r \"$srcdir/$ac_unique_file\"; then\n  test \"$ac_srcdir_defaulted\" = yes && srcdir=\"$ac_confdir or ..\"\n  as_fn_error $? \"cannot find sources ($ac_unique_file) in $srcdir\"\nfi\nac_msg=\"sources are in $srcdir, but \\`cd $srcdir' does not work\"\nac_abs_confdir=`(\n\tcd \"$srcdir\" && test -r \"./$ac_unique_file\" || as_fn_error $? \"$ac_msg\"\n\tpwd)`\n# When building in place, set srcdir=.\nif test \"$ac_abs_confdir\" = \"$ac_pwd\"; then\n  srcdir=.\nfi\n# Remove unnecessary trailing slashes from srcdir.\n# Double slashes in file names in object file debugging info\n# mess up M-x gdb in Emacs.\ncase $srcdir in\n*/) srcdir=`expr \"X$srcdir\" : 'X\\(.*[^/]\\)' \\| \"X$srcdir\" : 'X\\(.*\\)'`;;\nesac\nfor ac_var in $ac_precious_vars; do\n  eval ac_env_${ac_var}_set=\\${${ac_var}+set}\n  eval ac_env_${ac_var}_value=\\$${ac_var}\n  eval ac_cv_env_${ac_var}_set=\\${${ac_var}+set}\n  eval ac_cv_env_${ac_var}_value=\\$${ac_var}\ndone\n\n#\n# Report the --help message.\n#\nif test \"$ac_init_help\" = \"long\"; then\n  # Omit some internal or obsolete options to make the list less imposing.\n  # This message is too long to be a string in the A/UX 3.1 sh.\n  cat <<_ACEOF\n\\`configure' configures this package to adapt to many kinds of systems.\n\nUsage: $0 [OPTION]... [VAR=VALUE]...\n\nTo assign environment variables (e.g., CC, CFLAGS...), specify them as\nVAR=VALUE.  See below for descriptions of some of the useful variables.\n\nDefaults for the options are specified in brackets.\n\nConfiguration:\n  -h, --help              display this help and exit\n      --help=short        display options specific to this package\n      --help=recursive    display the short help of all the included packages\n  -V, --version           display version information and exit\n  -q, --quiet, --silent   do not print \\`checking ...' messages\n      --cache-file=FILE   cache test results in FILE [disabled]\n  -C, --config-cache      alias for \\`--cache-file=config.cache'\n  -n, --no-create         do not create output files\n      --srcdir=DIR        find the sources in DIR [configure dir or \\`..']\n\nInstallation directories:\n  --prefix=PREFIX         install architecture-independent files in PREFIX\n                          [$ac_default_prefix]\n  --exec-prefix=EPREFIX   install architecture-dependent files in EPREFIX\n                          [PREFIX]\n\nBy default, \\`make install' will install all the files in\n\\`$ac_default_prefix/bin', \\`$ac_default_prefix/lib' etc.  You can specify\nan installation prefix other than \\`$ac_default_prefix' using \\`--prefix',\nfor instance \\`--prefix=\\$HOME'.\n\nFor better control, use the options below.\n\nFine tuning of the installation directories:\n  --bindir=DIR            user executables [EPREFIX/bin]\n  --sbindir=DIR           system admin executables [EPREFIX/sbin]\n  --libexecdir=DIR        program executables [EPREFIX/libexec]\n  --sysconfdir=DIR        read-only single-machine data [PREFIX/etc]\n  --sharedstatedir=DIR    modifiable architecture-independent data [PREFIX/com]\n  --localstatedir=DIR     modifiable single-machine data [PREFIX/var]\n  --libdir=DIR            object code libraries [EPREFIX/lib]\n  --includedir=DIR        C header files [PREFIX/include]\n  --oldincludedir=DIR     C header files for non-gcc [/usr/include]\n  --datarootdir=DIR       read-only arch.-independent data root [PREFIX/share]\n  --datadir=DIR           read-only architecture-independent data [DATAROOTDIR]\n  --infodir=DIR           info documentation [DATAROOTDIR/info]\n  --localedir=DIR         locale-dependent data [DATAROOTDIR/locale]\n  --mandir=DIR            man documentation [DATAROOTDIR/man]\n  --docdir=DIR            documentation root [DATAROOTDIR/doc/PACKAGE]\n  --htmldir=DIR           html documentation [DOCDIR]\n  --dvidir=DIR            dvi documentation [DOCDIR]\n  --pdfdir=DIR            pdf documentation [DOCDIR]\n  --psdir=DIR             ps documentation [DOCDIR]\n_ACEOF\n\n  cat <<\\_ACEOF\n\nSystem types:\n  --build=BUILD     configure for building on BUILD [guessed]\n  --host=HOST       cross-compile to build programs to run on HOST [BUILD]\n_ACEOF\nfi\n\nif test -n \"$ac_init_help\"; then\n\n  cat <<\\_ACEOF\n\nOptional Features:\n  --disable-option-checking  ignore unrecognized --enable/--with options\n  --disable-FEATURE       do not include FEATURE (same as --enable-FEATURE=no)\n  --enable-FEATURE[=ARG]  include FEATURE [ARG=yes]\n  --enable-autogen        Automatically regenerate configure output\n  --enable-code-coverage  Enable code coverage\n  --disable-cc-silence    Do not silence irrelevant compiler warnings\n  --enable-debug          Build debugging code (implies --enable-ivsalloc)\n  --enable-ivsalloc       Validate pointers passed through the public API\n  --disable-stats         Disable statistics calculation/reporting\n  --enable-prof           Enable allocation profiling\n  --enable-prof-libunwind Use libunwind for backtracing\n  --disable-prof-libgcc   Do not use libgcc for backtracing\n  --disable-prof-gcc      Do not use gcc intrinsics for backtracing\n  --disable-tcache        Disable per thread caches\n  --disable-munmap        Disable VM deallocation via munmap(2)\n  --disable-fill          Disable support for junk/zero filling, quarantine,\n                          and redzones\n  --enable-utrace         Enable utrace(2)-based tracing\n  --disable-valgrind      Disable support for Valgrind\n  --enable-xmalloc        Support xmalloc option\n  --disable-cache-oblivious\n                          Disable support for cache-oblivious allocation\n                          alignment\n  --enable-lazy-lock      Enable lazy locking (only lock when multi-threaded)\n  --disable-tls           Disable thread-local storage (__thread keyword)\n  --disable-zone-allocator\n                          Disable zone allocator for Darwin\n\nOptional Packages:\n  --with-PACKAGE[=ARG]    use PACKAGE [ARG=yes]\n  --without-PACKAGE       do not use PACKAGE (same as --with-PACKAGE=no)\n  --with-xslroot=<path>   XSL stylesheet root path\n  --with-rpath=<rpath>    Colon-separated rpath (ELF systems only)\n  --with-mangling=<map>   Mangle symbols in <map>\n  --with-jemalloc-prefix=<prefix>\n                          Prefix to prepend to all public APIs\n  --without-export        disable exporting jemalloc public APIs\n  --with-private-namespace=<prefix>\n                          Prefix to prepend to all library-private APIs\n  --with-install-suffix=<suffix>\n                          Suffix to append to all installed files\n  --with-static-libunwind=<libunwind.a>\n                          Path to static libunwind library; use rather than\n                          dynamically linking\n  --with-lg-tiny-min=<lg-tiny-min>\n                          Base 2 log of minimum tiny size class to support\n  --with-lg-quantum=<lg-quantum>\n                          Base 2 log of minimum allocation alignment\n  --with-lg-page=<lg-page>\n                          Base 2 log of system page size\n  --with-lg-page-sizes=<lg-page-sizes>\n                          Base 2 logs of system page sizes to support\n  --with-lg-size-class-group=<lg-size-class-group>\n                          Base 2 log of size classes per doubling\n\nSome influential environment variables:\n  CC          C compiler command\n  CFLAGS      C compiler flags\n  LDFLAGS     linker flags, e.g. -L<lib dir> if you have libraries in a\n              nonstandard directory <lib dir>\n  LIBS        libraries to pass to the linker, e.g. -l<library>\n  CPPFLAGS    (Objective) C/C++ preprocessor flags, e.g. -I<include dir> if\n              you have headers in a nonstandard directory <include dir>\n  CPP         C preprocessor\n\nUse these variables to override the choices made by `configure' or to help\nit to find libraries and programs with nonstandard names/locations.\n\nReport bugs to the package provider.\n_ACEOF\nac_status=$?\nfi\n\nif test \"$ac_init_help\" = \"recursive\"; then\n  # If there are subdirs, report their specific --help.\n  for ac_dir in : $ac_subdirs_all; do test \"x$ac_dir\" = x: && continue\n    test -d \"$ac_dir\" ||\n      { cd \"$srcdir\" && ac_pwd=`pwd` && srcdir=. && test -d \"$ac_dir\"; } ||\n      continue\n    ac_builddir=.\n\ncase \"$ac_dir\" in\n.) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;;\n*)\n  ac_dir_suffix=/`$as_echo \"$ac_dir\" | sed 's|^\\.[\\\\/]||'`\n  # A \"..\" for each directory in $ac_dir_suffix.\n  ac_top_builddir_sub=`$as_echo \"$ac_dir_suffix\" | sed 's|/[^\\\\/]*|/..|g;s|/||'`\n  case $ac_top_builddir_sub in\n  \"\") ac_top_builddir_sub=. ac_top_build_prefix= ;;\n  *)  ac_top_build_prefix=$ac_top_builddir_sub/ ;;\n  esac ;;\nesac\nac_abs_top_builddir=$ac_pwd\nac_abs_builddir=$ac_pwd$ac_dir_suffix\n# for backward compatibility:\nac_top_builddir=$ac_top_build_prefix\n\ncase $srcdir in\n  .)  # We are building in place.\n    ac_srcdir=.\n    ac_top_srcdir=$ac_top_builddir_sub\n    ac_abs_top_srcdir=$ac_pwd ;;\n  [\\\\/]* | ?:[\\\\/]* )  # Absolute name.\n    ac_srcdir=$srcdir$ac_dir_suffix;\n    ac_top_srcdir=$srcdir\n    ac_abs_top_srcdir=$srcdir ;;\n  *) # Relative name.\n    ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix\n    ac_top_srcdir=$ac_top_build_prefix$srcdir\n    ac_abs_top_srcdir=$ac_pwd/$srcdir ;;\nesac\nac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix\n\n    cd \"$ac_dir\" || { ac_status=$?; continue; }\n    # Check for guested configure.\n    if test -f \"$ac_srcdir/configure.gnu\"; then\n      echo &&\n      $SHELL \"$ac_srcdir/configure.gnu\" --help=recursive\n    elif test -f \"$ac_srcdir/configure\"; then\n      echo &&\n      $SHELL \"$ac_srcdir/configure\" --help=recursive\n    else\n      $as_echo \"$as_me: WARNING: no configuration information is in $ac_dir\" >&2\n    fi || ac_status=$?\n    cd \"$ac_pwd\" || { ac_status=$?; break; }\n  done\nfi\n\ntest -n \"$ac_init_help\" && exit $ac_status\nif $ac_init_version; then\n  cat <<\\_ACEOF\nconfigure\ngenerated by GNU Autoconf 2.69\n\nCopyright (C) 2012 Free Software Foundation, Inc.\nThis configure script is free software; the Free Software Foundation\ngives unlimited permission to copy, distribute and modify it.\n_ACEOF\n  exit\nfi\n\n## ------------------------ ##\n## Autoconf initialization. ##\n## ------------------------ ##\n\n# ac_fn_c_try_compile LINENO\n# --------------------------\n# Try to compile conftest.$ac_ext, and return whether this succeeded.\nac_fn_c_try_compile ()\n{\n  as_lineno=${as_lineno-\"$1\"} as_lineno_stack=as_lineno_stack=$as_lineno_stack\n  rm -f conftest.$ac_objext\n  if { { ac_try=\"$ac_compile\"\ncase \"(($ac_try\" in\n  *\\\"* | *\\`* | *\\\\*) ac_try_echo=\\$ac_try;;\n  *) ac_try_echo=$ac_try;;\nesac\neval ac_try_echo=\"\\\"\\$as_me:${as_lineno-$LINENO}: $ac_try_echo\\\"\"\n$as_echo \"$ac_try_echo\"; } >&5\n  (eval \"$ac_compile\") 2>conftest.err\n  ac_status=$?\n  if test -s conftest.err; then\n    grep -v '^ *+' conftest.err >conftest.er1\n    cat conftest.er1 >&5\n    mv -f conftest.er1 conftest.err\n  fi\n  $as_echo \"$as_me:${as_lineno-$LINENO}: \\$? = $ac_status\" >&5\n  test $ac_status = 0; } && {\n\t test -z \"$ac_c_werror_flag\" ||\n\t test ! -s conftest.err\n       } && test -s conftest.$ac_objext; then :\n  ac_retval=0\nelse\n  $as_echo \"$as_me: failed program was:\" >&5\nsed 's/^/| /' conftest.$ac_ext >&5\n\n\tac_retval=1\nfi\n  eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno\n  as_fn_set_status $ac_retval\n\n} # ac_fn_c_try_compile\n\n# ac_fn_c_try_cpp LINENO\n# ----------------------\n# Try to preprocess conftest.$ac_ext, and return whether this succeeded.\nac_fn_c_try_cpp ()\n{\n  as_lineno=${as_lineno-\"$1\"} as_lineno_stack=as_lineno_stack=$as_lineno_stack\n  if { { ac_try=\"$ac_cpp conftest.$ac_ext\"\ncase \"(($ac_try\" in\n  *\\\"* | *\\`* | *\\\\*) ac_try_echo=\\$ac_try;;\n  *) ac_try_echo=$ac_try;;\nesac\neval ac_try_echo=\"\\\"\\$as_me:${as_lineno-$LINENO}: $ac_try_echo\\\"\"\n$as_echo \"$ac_try_echo\"; } >&5\n  (eval \"$ac_cpp conftest.$ac_ext\") 2>conftest.err\n  ac_status=$?\n  if test -s conftest.err; then\n    grep -v '^ *+' conftest.err >conftest.er1\n    cat conftest.er1 >&5\n    mv -f conftest.er1 conftest.err\n  fi\n  $as_echo \"$as_me:${as_lineno-$LINENO}: \\$? = $ac_status\" >&5\n  test $ac_status = 0; } > conftest.i && {\n\t test -z \"$ac_c_preproc_warn_flag$ac_c_werror_flag\" ||\n\t test ! -s conftest.err\n       }; then :\n  ac_retval=0\nelse\n  $as_echo \"$as_me: failed program was:\" >&5\nsed 's/^/| /' conftest.$ac_ext >&5\n\n    ac_retval=1\nfi\n  eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno\n  as_fn_set_status $ac_retval\n\n} # ac_fn_c_try_cpp\n\n# ac_fn_c_try_run LINENO\n# ----------------------\n# Try to link conftest.$ac_ext, and return whether this succeeded. Assumes\n# that executables *can* be run.\nac_fn_c_try_run ()\n{\n  as_lineno=${as_lineno-\"$1\"} as_lineno_stack=as_lineno_stack=$as_lineno_stack\n  if { { ac_try=\"$ac_link\"\ncase \"(($ac_try\" in\n  *\\\"* | *\\`* | *\\\\*) ac_try_echo=\\$ac_try;;\n  *) ac_try_echo=$ac_try;;\nesac\neval ac_try_echo=\"\\\"\\$as_me:${as_lineno-$LINENO}: $ac_try_echo\\\"\"\n$as_echo \"$ac_try_echo\"; } >&5\n  (eval \"$ac_link\") 2>&5\n  ac_status=$?\n  $as_echo \"$as_me:${as_lineno-$LINENO}: \\$? = $ac_status\" >&5\n  test $ac_status = 0; } && { ac_try='./conftest$ac_exeext'\n  { { case \"(($ac_try\" in\n  *\\\"* | *\\`* | *\\\\*) ac_try_echo=\\$ac_try;;\n  *) ac_try_echo=$ac_try;;\nesac\neval ac_try_echo=\"\\\"\\$as_me:${as_lineno-$LINENO}: $ac_try_echo\\\"\"\n$as_echo \"$ac_try_echo\"; } >&5\n  (eval \"$ac_try\") 2>&5\n  ac_status=$?\n  $as_echo \"$as_me:${as_lineno-$LINENO}: \\$? = $ac_status\" >&5\n  test $ac_status = 0; }; }; then :\n  ac_retval=0\nelse\n  $as_echo \"$as_me: program exited with status $ac_status\" >&5\n       $as_echo \"$as_me: failed program was:\" >&5\nsed 's/^/| /' conftest.$ac_ext >&5\n\n       ac_retval=$ac_status\nfi\n  rm -rf conftest.dSYM conftest_ipa8_conftest.oo\n  eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno\n  as_fn_set_status $ac_retval\n\n} # ac_fn_c_try_run\n\n# ac_fn_c_check_header_compile LINENO HEADER VAR INCLUDES\n# -------------------------------------------------------\n# Tests whether HEADER exists and can be compiled using the include files in\n# INCLUDES, setting the cache variable VAR accordingly.\nac_fn_c_check_header_compile ()\n{\n  as_lineno=${as_lineno-\"$1\"} as_lineno_stack=as_lineno_stack=$as_lineno_stack\n  { $as_echo \"$as_me:${as_lineno-$LINENO}: checking for $2\" >&5\n$as_echo_n \"checking for $2... \" >&6; }\nif eval \\${$3+:} false; then :\n  $as_echo_n \"(cached) \" >&6\nelse\n  cat confdefs.h - <<_ACEOF >conftest.$ac_ext\n/* end confdefs.h.  */\n$4\n#include <$2>\n_ACEOF\nif ac_fn_c_try_compile \"$LINENO\"; then :\n  eval \"$3=yes\"\nelse\n  eval \"$3=no\"\nfi\nrm -f core conftest.err conftest.$ac_objext conftest.$ac_ext\nfi\neval ac_res=\\$$3\n\t       { $as_echo \"$as_me:${as_lineno-$LINENO}: result: $ac_res\" >&5\n$as_echo \"$ac_res\" >&6; }\n  eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno\n\n} # ac_fn_c_check_header_compile\n\n# ac_fn_c_compute_int LINENO EXPR VAR INCLUDES\n# --------------------------------------------\n# Tries to find the compile-time value of EXPR in a program that includes\n# INCLUDES, setting VAR accordingly. Returns whether the value could be\n# computed\nac_fn_c_compute_int ()\n{\n  as_lineno=${as_lineno-\"$1\"} as_lineno_stack=as_lineno_stack=$as_lineno_stack\n  if test \"$cross_compiling\" = yes; then\n    # Depending upon the size, compute the lo and hi bounds.\ncat confdefs.h - <<_ACEOF >conftest.$ac_ext\n/* end confdefs.h.  */\n$4\nint\nmain ()\n{\nstatic int test_array [1 - 2 * !(($2) >= 0)];\ntest_array [0] = 0;\nreturn test_array [0];\n\n  ;\n  return 0;\n}\n_ACEOF\nif ac_fn_c_try_compile \"$LINENO\"; then :\n  ac_lo=0 ac_mid=0\n  while :; do\n    cat confdefs.h - <<_ACEOF >conftest.$ac_ext\n/* end confdefs.h.  */\n$4\nint\nmain ()\n{\nstatic int test_array [1 - 2 * !(($2) <= $ac_mid)];\ntest_array [0] = 0;\nreturn test_array [0];\n\n  ;\n  return 0;\n}\n_ACEOF\nif ac_fn_c_try_compile \"$LINENO\"; then :\n  ac_hi=$ac_mid; break\nelse\n  as_fn_arith $ac_mid + 1 && ac_lo=$as_val\n\t\t\tif test $ac_lo -le $ac_mid; then\n\t\t\t  ac_lo= ac_hi=\n\t\t\t  break\n\t\t\tfi\n\t\t\tas_fn_arith 2 '*' $ac_mid + 1 && ac_mid=$as_val\nfi\nrm -f core conftest.err conftest.$ac_objext conftest.$ac_ext\n  done\nelse\n  cat confdefs.h - <<_ACEOF >conftest.$ac_ext\n/* end confdefs.h.  */\n$4\nint\nmain ()\n{\nstatic int test_array [1 - 2 * !(($2) < 0)];\ntest_array [0] = 0;\nreturn test_array [0];\n\n  ;\n  return 0;\n}\n_ACEOF\nif ac_fn_c_try_compile \"$LINENO\"; then :\n  ac_hi=-1 ac_mid=-1\n  while :; do\n    cat confdefs.h - <<_ACEOF >conftest.$ac_ext\n/* end confdefs.h.  */\n$4\nint\nmain ()\n{\nstatic int test_array [1 - 2 * !(($2) >= $ac_mid)];\ntest_array [0] = 0;\nreturn test_array [0];\n\n  ;\n  return 0;\n}\n_ACEOF\nif ac_fn_c_try_compile \"$LINENO\"; then :\n  ac_lo=$ac_mid; break\nelse\n  as_fn_arith '(' $ac_mid ')' - 1 && ac_hi=$as_val\n\t\t\tif test $ac_mid -le $ac_hi; then\n\t\t\t  ac_lo= ac_hi=\n\t\t\t  break\n\t\t\tfi\n\t\t\tas_fn_arith 2 '*' $ac_mid && ac_mid=$as_val\nfi\nrm -f core conftest.err conftest.$ac_objext conftest.$ac_ext\n  done\nelse\n  ac_lo= ac_hi=\nfi\nrm -f core conftest.err conftest.$ac_objext conftest.$ac_ext\nfi\nrm -f core conftest.err conftest.$ac_objext conftest.$ac_ext\n# Binary search between lo and hi bounds.\nwhile test \"x$ac_lo\" != \"x$ac_hi\"; do\n  as_fn_arith '(' $ac_hi - $ac_lo ')' / 2 + $ac_lo && ac_mid=$as_val\n  cat confdefs.h - <<_ACEOF >conftest.$ac_ext\n/* end confdefs.h.  */\n$4\nint\nmain ()\n{\nstatic int test_array [1 - 2 * !(($2) <= $ac_mid)];\ntest_array [0] = 0;\nreturn test_array [0];\n\n  ;\n  return 0;\n}\n_ACEOF\nif ac_fn_c_try_compile \"$LINENO\"; then :\n  ac_hi=$ac_mid\nelse\n  as_fn_arith '(' $ac_mid ')' + 1 && ac_lo=$as_val\nfi\nrm -f core conftest.err conftest.$ac_objext conftest.$ac_ext\ndone\ncase $ac_lo in #((\n?*) eval \"$3=\\$ac_lo\"; ac_retval=0 ;;\n'') ac_retval=1 ;;\nesac\n  else\n    cat confdefs.h - <<_ACEOF >conftest.$ac_ext\n/* end confdefs.h.  */\n$4\nstatic long int longval () { return $2; }\nstatic unsigned long int ulongval () { return $2; }\n#include <stdio.h>\n#include <stdlib.h>\nint\nmain ()\n{\n\n  FILE *f = fopen (\"conftest.val\", \"w\");\n  if (! f)\n    return 1;\n  if (($2) < 0)\n    {\n      long int i = longval ();\n      if (i != ($2))\n\treturn 1;\n      fprintf (f, \"%ld\", i);\n    }\n  else\n    {\n      unsigned long int i = ulongval ();\n      if (i != ($2))\n\treturn 1;\n      fprintf (f, \"%lu\", i);\n    }\n  /* Do not output a trailing newline, as this causes \\r\\n confusion\n     on some platforms.  */\n  return ferror (f) || fclose (f) != 0;\n\n  ;\n  return 0;\n}\n_ACEOF\nif ac_fn_c_try_run \"$LINENO\"; then :\n  echo >>conftest.val; read $3 <conftest.val; ac_retval=0\nelse\n  ac_retval=1\nfi\nrm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \\\n  conftest.$ac_objext conftest.beam conftest.$ac_ext\nrm -f conftest.val\n\n  fi\n  eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno\n  as_fn_set_status $ac_retval\n\n} # ac_fn_c_compute_int\n\n# ac_fn_c_try_link LINENO\n# -----------------------\n# Try to link conftest.$ac_ext, and return whether this succeeded.\nac_fn_c_try_link ()\n{\n  as_lineno=${as_lineno-\"$1\"} as_lineno_stack=as_lineno_stack=$as_lineno_stack\n  rm -f conftest.$ac_objext conftest$ac_exeext\n  if { { ac_try=\"$ac_link\"\ncase \"(($ac_try\" in\n  *\\\"* | *\\`* | *\\\\*) ac_try_echo=\\$ac_try;;\n  *) ac_try_echo=$ac_try;;\nesac\neval ac_try_echo=\"\\\"\\$as_me:${as_lineno-$LINENO}: $ac_try_echo\\\"\"\n$as_echo \"$ac_try_echo\"; } >&5\n  (eval \"$ac_link\") 2>conftest.err\n  ac_status=$?\n  if test -s conftest.err; then\n    grep -v '^ *+' conftest.err >conftest.er1\n    cat conftest.er1 >&5\n    mv -f conftest.er1 conftest.err\n  fi\n  $as_echo \"$as_me:${as_lineno-$LINENO}: \\$? = $ac_status\" >&5\n  test $ac_status = 0; } && {\n\t test -z \"$ac_c_werror_flag\" ||\n\t test ! -s conftest.err\n       } && test -s conftest$ac_exeext && {\n\t test \"$cross_compiling\" = yes ||\n\t test -x conftest$ac_exeext\n       }; then :\n  ac_retval=0\nelse\n  $as_echo \"$as_me: failed program was:\" >&5\nsed 's/^/| /' conftest.$ac_ext >&5\n\n\tac_retval=1\nfi\n  # Delete the IPA/IPO (Inter Procedural Analysis/Optimization) information\n  # created by the PGI compiler (conftest_ipa8_conftest.oo), as it would\n  # interfere with the next link command; also delete a directory that is\n  # left behind by Apple's compiler.  We do this before executing the actions.\n  rm -rf conftest.dSYM conftest_ipa8_conftest.oo\n  eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno\n  as_fn_set_status $ac_retval\n\n} # ac_fn_c_try_link\n\n# ac_fn_c_check_header_mongrel LINENO HEADER VAR INCLUDES\n# -------------------------------------------------------\n# Tests whether HEADER exists, giving a warning if it cannot be compiled using\n# the include files in INCLUDES and setting the cache variable VAR\n# accordingly.\nac_fn_c_check_header_mongrel ()\n{\n  as_lineno=${as_lineno-\"$1\"} as_lineno_stack=as_lineno_stack=$as_lineno_stack\n  if eval \\${$3+:} false; then :\n  { $as_echo \"$as_me:${as_lineno-$LINENO}: checking for $2\" >&5\n$as_echo_n \"checking for $2... \" >&6; }\nif eval \\${$3+:} false; then :\n  $as_echo_n \"(cached) \" >&6\nfi\neval ac_res=\\$$3\n\t       { $as_echo \"$as_me:${as_lineno-$LINENO}: result: $ac_res\" >&5\n$as_echo \"$ac_res\" >&6; }\nelse\n  # Is the header compilable?\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: checking $2 usability\" >&5\n$as_echo_n \"checking $2 usability... \" >&6; }\ncat confdefs.h - <<_ACEOF >conftest.$ac_ext\n/* end confdefs.h.  */\n$4\n#include <$2>\n_ACEOF\nif ac_fn_c_try_compile \"$LINENO\"; then :\n  ac_header_compiler=yes\nelse\n  ac_header_compiler=no\nfi\nrm -f core conftest.err conftest.$ac_objext conftest.$ac_ext\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: result: $ac_header_compiler\" >&5\n$as_echo \"$ac_header_compiler\" >&6; }\n\n# Is the header present?\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: checking $2 presence\" >&5\n$as_echo_n \"checking $2 presence... \" >&6; }\ncat confdefs.h - <<_ACEOF >conftest.$ac_ext\n/* end confdefs.h.  */\n#include <$2>\n_ACEOF\nif ac_fn_c_try_cpp \"$LINENO\"; then :\n  ac_header_preproc=yes\nelse\n  ac_header_preproc=no\nfi\nrm -f conftest.err conftest.i conftest.$ac_ext\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: result: $ac_header_preproc\" >&5\n$as_echo \"$ac_header_preproc\" >&6; }\n\n# So?  What about this header?\ncase $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in #((\n  yes:no: )\n    { $as_echo \"$as_me:${as_lineno-$LINENO}: WARNING: $2: accepted by the compiler, rejected by the preprocessor!\" >&5\n$as_echo \"$as_me: WARNING: $2: accepted by the compiler, rejected by the preprocessor!\" >&2;}\n    { $as_echo \"$as_me:${as_lineno-$LINENO}: WARNING: $2: proceeding with the compiler's result\" >&5\n$as_echo \"$as_me: WARNING: $2: proceeding with the compiler's result\" >&2;}\n    ;;\n  no:yes:* )\n    { $as_echo \"$as_me:${as_lineno-$LINENO}: WARNING: $2: present but cannot be compiled\" >&5\n$as_echo \"$as_me: WARNING: $2: present but cannot be compiled\" >&2;}\n    { $as_echo \"$as_me:${as_lineno-$LINENO}: WARNING: $2:     check for missing prerequisite headers?\" >&5\n$as_echo \"$as_me: WARNING: $2:     check for missing prerequisite headers?\" >&2;}\n    { $as_echo \"$as_me:${as_lineno-$LINENO}: WARNING: $2: see the Autoconf documentation\" >&5\n$as_echo \"$as_me: WARNING: $2: see the Autoconf documentation\" >&2;}\n    { $as_echo \"$as_me:${as_lineno-$LINENO}: WARNING: $2:     section \\\"Present But Cannot Be Compiled\\\"\" >&5\n$as_echo \"$as_me: WARNING: $2:     section \\\"Present But Cannot Be Compiled\\\"\" >&2;}\n    { $as_echo \"$as_me:${as_lineno-$LINENO}: WARNING: $2: proceeding with the compiler's result\" >&5\n$as_echo \"$as_me: WARNING: $2: proceeding with the compiler's result\" >&2;}\n    ;;\nesac\n  { $as_echo \"$as_me:${as_lineno-$LINENO}: checking for $2\" >&5\n$as_echo_n \"checking for $2... \" >&6; }\nif eval \\${$3+:} false; then :\n  $as_echo_n \"(cached) \" >&6\nelse\n  eval \"$3=\\$ac_header_compiler\"\nfi\neval ac_res=\\$$3\n\t       { $as_echo \"$as_me:${as_lineno-$LINENO}: result: $ac_res\" >&5\n$as_echo \"$ac_res\" >&6; }\nfi\n  eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno\n\n} # ac_fn_c_check_header_mongrel\n\n# ac_fn_c_check_func LINENO FUNC VAR\n# ----------------------------------\n# Tests whether FUNC exists, setting the cache variable VAR accordingly\nac_fn_c_check_func ()\n{\n  as_lineno=${as_lineno-\"$1\"} as_lineno_stack=as_lineno_stack=$as_lineno_stack\n  { $as_echo \"$as_me:${as_lineno-$LINENO}: checking for $2\" >&5\n$as_echo_n \"checking for $2... \" >&6; }\nif eval \\${$3+:} false; then :\n  $as_echo_n \"(cached) \" >&6\nelse\n  cat confdefs.h - <<_ACEOF >conftest.$ac_ext\n/* end confdefs.h.  */\n/* Define $2 to an innocuous variant, in case <limits.h> declares $2.\n   For example, HP-UX 11i <limits.h> declares gettimeofday.  */\n#define $2 innocuous_$2\n\n/* System header to define __stub macros and hopefully few prototypes,\n    which can conflict with char $2 (); below.\n    Prefer <limits.h> to <assert.h> if __STDC__ is defined, since\n    <limits.h> exists even on freestanding compilers.  */\n\n#ifdef __STDC__\n# include <limits.h>\n#else\n# include <assert.h>\n#endif\n\n#undef $2\n\n/* Override any GCC internal prototype to avoid an error.\n   Use char because int might match the return type of a GCC\n   builtin and then its argument prototype would still apply.  */\n#ifdef __cplusplus\nextern \"C\"\n#endif\nchar $2 ();\n/* The GNU C library defines this for functions which it implements\n    to always fail with ENOSYS.  Some functions are actually named\n    something starting with __ and the normal name is an alias.  */\n#if defined __stub_$2 || defined __stub___$2\nchoke me\n#endif\n\nint\nmain ()\n{\nreturn $2 ();\n  ;\n  return 0;\n}\n_ACEOF\nif ac_fn_c_try_link \"$LINENO\"; then :\n  eval \"$3=yes\"\nelse\n  eval \"$3=no\"\nfi\nrm -f core conftest.err conftest.$ac_objext \\\n    conftest$ac_exeext conftest.$ac_ext\nfi\neval ac_res=\\$$3\n\t       { $as_echo \"$as_me:${as_lineno-$LINENO}: result: $ac_res\" >&5\n$as_echo \"$ac_res\" >&6; }\n  eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno\n\n} # ac_fn_c_check_func\n\n# ac_fn_c_check_type LINENO TYPE VAR INCLUDES\n# -------------------------------------------\n# Tests whether TYPE exists after having included INCLUDES, setting cache\n# variable VAR accordingly.\nac_fn_c_check_type ()\n{\n  as_lineno=${as_lineno-\"$1\"} as_lineno_stack=as_lineno_stack=$as_lineno_stack\n  { $as_echo \"$as_me:${as_lineno-$LINENO}: checking for $2\" >&5\n$as_echo_n \"checking for $2... \" >&6; }\nif eval \\${$3+:} false; then :\n  $as_echo_n \"(cached) \" >&6\nelse\n  eval \"$3=no\"\n  cat confdefs.h - <<_ACEOF >conftest.$ac_ext\n/* end confdefs.h.  */\n$4\nint\nmain ()\n{\nif (sizeof ($2))\n\t return 0;\n  ;\n  return 0;\n}\n_ACEOF\nif ac_fn_c_try_compile \"$LINENO\"; then :\n  cat confdefs.h - <<_ACEOF >conftest.$ac_ext\n/* end confdefs.h.  */\n$4\nint\nmain ()\n{\nif (sizeof (($2)))\n\t    return 0;\n  ;\n  return 0;\n}\n_ACEOF\nif ac_fn_c_try_compile \"$LINENO\"; then :\n\nelse\n  eval \"$3=yes\"\nfi\nrm -f core conftest.err conftest.$ac_objext conftest.$ac_ext\nfi\nrm -f core conftest.err conftest.$ac_objext conftest.$ac_ext\nfi\neval ac_res=\\$$3\n\t       { $as_echo \"$as_me:${as_lineno-$LINENO}: result: $ac_res\" >&5\n$as_echo \"$ac_res\" >&6; }\n  eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno\n\n} # ac_fn_c_check_type\ncat >config.log <<_ACEOF\nThis file contains any messages produced by compilers while\nrunning configure, to aid debugging if configure makes a mistake.\n\nIt was created by $as_me, which was\ngenerated by GNU Autoconf 2.69.  Invocation command line was\n\n  $ $0 $@\n\n_ACEOF\nexec 5>>config.log\n{\ncat <<_ASUNAME\n## --------- ##\n## Platform. ##\n## --------- ##\n\nhostname = `(hostname || uname -n) 2>/dev/null | sed 1q`\nuname -m = `(uname -m) 2>/dev/null || echo unknown`\nuname -r = `(uname -r) 2>/dev/null || echo unknown`\nuname -s = `(uname -s) 2>/dev/null || echo unknown`\nuname -v = `(uname -v) 2>/dev/null || echo unknown`\n\n/usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null || echo unknown`\n/bin/uname -X     = `(/bin/uname -X) 2>/dev/null     || echo unknown`\n\n/bin/arch              = `(/bin/arch) 2>/dev/null              || echo unknown`\n/usr/bin/arch -k       = `(/usr/bin/arch -k) 2>/dev/null       || echo unknown`\n/usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null || echo unknown`\n/usr/bin/hostinfo      = `(/usr/bin/hostinfo) 2>/dev/null      || echo unknown`\n/bin/machine           = `(/bin/machine) 2>/dev/null           || echo unknown`\n/usr/bin/oslevel       = `(/usr/bin/oslevel) 2>/dev/null       || echo unknown`\n/bin/universe          = `(/bin/universe) 2>/dev/null          || echo unknown`\n\n_ASUNAME\n\nas_save_IFS=$IFS; IFS=$PATH_SEPARATOR\nfor as_dir in $PATH\ndo\n  IFS=$as_save_IFS\n  test -z \"$as_dir\" && as_dir=.\n    $as_echo \"PATH: $as_dir\"\n  done\nIFS=$as_save_IFS\n\n} >&5\n\ncat >&5 <<_ACEOF\n\n\n## ----------- ##\n## Core tests. ##\n## ----------- ##\n\n_ACEOF\n\n\n# Keep a trace of the command line.\n# Strip out --no-create and --no-recursion so they do not pile up.\n# Strip out --silent because we don't want to record it for future runs.\n# Also quote any args containing shell meta-characters.\n# Make two passes to allow for proper duplicate-argument suppression.\nac_configure_args=\nac_configure_args0=\nac_configure_args1=\nac_must_keep_next=false\nfor ac_pass in 1 2\ndo\n  for ac_arg\n  do\n    case $ac_arg in\n    -no-create | --no-c* | -n | -no-recursion | --no-r*) continue ;;\n    -q | -quiet | --quiet | --quie | --qui | --qu | --q \\\n    | -silent | --silent | --silen | --sile | --sil)\n      continue ;;\n    *\\'*)\n      ac_arg=`$as_echo \"$ac_arg\" | sed \"s/'/'\\\\\\\\\\\\\\\\''/g\"` ;;\n    esac\n    case $ac_pass in\n    1) as_fn_append ac_configure_args0 \" '$ac_arg'\" ;;\n    2)\n      as_fn_append ac_configure_args1 \" '$ac_arg'\"\n      if test $ac_must_keep_next = true; then\n\tac_must_keep_next=false # Got value, back to normal.\n      else\n\tcase $ac_arg in\n\t  *=* | --config-cache | -C | -disable-* | --disable-* \\\n\t  | -enable-* | --enable-* | -gas | --g* | -nfp | --nf* \\\n\t  | -q | -quiet | --q* | -silent | --sil* | -v | -verb* \\\n\t  | -with-* | --with-* | -without-* | --without-* | --x)\n\t    case \"$ac_configure_args0 \" in\n\t      \"$ac_configure_args1\"*\" '$ac_arg' \"* ) continue ;;\n\t    esac\n\t    ;;\n\t  -* ) ac_must_keep_next=true ;;\n\tesac\n      fi\n      as_fn_append ac_configure_args \" '$ac_arg'\"\n      ;;\n    esac\n  done\ndone\n{ ac_configure_args0=; unset ac_configure_args0;}\n{ ac_configure_args1=; unset ac_configure_args1;}\n\n# When interrupted or exit'd, cleanup temporary files, and complete\n# config.log.  We remove comments because anyway the quotes in there\n# would cause problems or look ugly.\n# WARNING: Use '\\'' to represent an apostrophe within the trap.\n# WARNING: Do not start the trap code with a newline, due to a FreeBSD 4.0 bug.\ntrap 'exit_status=$?\n  # Save into config.log some information that might help in debugging.\n  {\n    echo\n\n    $as_echo \"## ---------------- ##\n## Cache variables. ##\n## ---------------- ##\"\n    echo\n    # The following way of writing the cache mishandles newlines in values,\n(\n  for ac_var in `(set) 2>&1 | sed -n '\\''s/^\\([a-zA-Z_][a-zA-Z0-9_]*\\)=.*/\\1/p'\\''`; do\n    eval ac_val=\\$$ac_var\n    case $ac_val in #(\n    *${as_nl}*)\n      case $ac_var in #(\n      *_cv_*) { $as_echo \"$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline\" >&5\n$as_echo \"$as_me: WARNING: cache variable $ac_var contains a newline\" >&2;} ;;\n      esac\n      case $ac_var in #(\n      _ | IFS | as_nl) ;; #(\n      BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #(\n      *) { eval $ac_var=; unset $ac_var;} ;;\n      esac ;;\n    esac\n  done\n  (set) 2>&1 |\n    case $as_nl`(ac_space='\\'' '\\''; set) 2>&1` in #(\n    *${as_nl}ac_space=\\ *)\n      sed -n \\\n\t\"s/'\\''/'\\''\\\\\\\\'\\'''\\''/g;\n\t  s/^\\\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\\\)=\\\\(.*\\\\)/\\\\1='\\''\\\\2'\\''/p\"\n      ;; #(\n    *)\n      sed -n \"/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p\"\n      ;;\n    esac |\n    sort\n)\n    echo\n\n    $as_echo \"## ----------------- ##\n## Output variables. ##\n## ----------------- ##\"\n    echo\n    for ac_var in $ac_subst_vars\n    do\n      eval ac_val=\\$$ac_var\n      case $ac_val in\n      *\\'\\''*) ac_val=`$as_echo \"$ac_val\" | sed \"s/'\\''/'\\''\\\\\\\\\\\\\\\\'\\'''\\''/g\"`;;\n      esac\n      $as_echo \"$ac_var='\\''$ac_val'\\''\"\n    done | sort\n    echo\n\n    if test -n \"$ac_subst_files\"; then\n      $as_echo \"## ------------------- ##\n## File substitutions. ##\n## ------------------- ##\"\n      echo\n      for ac_var in $ac_subst_files\n      do\n\teval ac_val=\\$$ac_var\n\tcase $ac_val in\n\t*\\'\\''*) ac_val=`$as_echo \"$ac_val\" | sed \"s/'\\''/'\\''\\\\\\\\\\\\\\\\'\\'''\\''/g\"`;;\n\tesac\n\t$as_echo \"$ac_var='\\''$ac_val'\\''\"\n      done | sort\n      echo\n    fi\n\n    if test -s confdefs.h; then\n      $as_echo \"## ----------- ##\n## confdefs.h. ##\n## ----------- ##\"\n      echo\n      cat confdefs.h\n      echo\n    fi\n    test \"$ac_signal\" != 0 &&\n      $as_echo \"$as_me: caught signal $ac_signal\"\n    $as_echo \"$as_me: exit $exit_status\"\n  } >&5\n  rm -f core *.core core.conftest.* &&\n    rm -f -r conftest* confdefs* conf$$* $ac_clean_files &&\n    exit $exit_status\n' 0\nfor ac_signal in 1 2 13 15; do\n  trap 'ac_signal='$ac_signal'; as_fn_exit 1' $ac_signal\ndone\nac_signal=0\n\n# confdefs.h avoids OS command line length limits that DEFS can exceed.\nrm -f -r conftest* confdefs.h\n\n$as_echo \"/* confdefs.h */\" > confdefs.h\n\n# Predefined preprocessor variables.\n\ncat >>confdefs.h <<_ACEOF\n#define PACKAGE_NAME \"$PACKAGE_NAME\"\n_ACEOF\n\ncat >>confdefs.h <<_ACEOF\n#define PACKAGE_TARNAME \"$PACKAGE_TARNAME\"\n_ACEOF\n\ncat >>confdefs.h <<_ACEOF\n#define PACKAGE_VERSION \"$PACKAGE_VERSION\"\n_ACEOF\n\ncat >>confdefs.h <<_ACEOF\n#define PACKAGE_STRING \"$PACKAGE_STRING\"\n_ACEOF\n\ncat >>confdefs.h <<_ACEOF\n#define PACKAGE_BUGREPORT \"$PACKAGE_BUGREPORT\"\n_ACEOF\n\ncat >>confdefs.h <<_ACEOF\n#define PACKAGE_URL \"$PACKAGE_URL\"\n_ACEOF\n\n\n# Let the site file select an alternate cache file if it wants to.\n# Prefer an explicitly selected file to automatically selected ones.\nac_site_file1=NONE\nac_site_file2=NONE\nif test -n \"$CONFIG_SITE\"; then\n  # We do not want a PATH search for config.site.\n  case $CONFIG_SITE in #((\n    -*)  ac_site_file1=./$CONFIG_SITE;;\n    */*) ac_site_file1=$CONFIG_SITE;;\n    *)   ac_site_file1=./$CONFIG_SITE;;\n  esac\nelif test \"x$prefix\" != xNONE; then\n  ac_site_file1=$prefix/share/config.site\n  ac_site_file2=$prefix/etc/config.site\nelse\n  ac_site_file1=$ac_default_prefix/share/config.site\n  ac_site_file2=$ac_default_prefix/etc/config.site\nfi\nfor ac_site_file in \"$ac_site_file1\" \"$ac_site_file2\"\ndo\n  test \"x$ac_site_file\" = xNONE && continue\n  if test /dev/null != \"$ac_site_file\" && test -r \"$ac_site_file\"; then\n    { $as_echo \"$as_me:${as_lineno-$LINENO}: loading site script $ac_site_file\" >&5\n$as_echo \"$as_me: loading site script $ac_site_file\" >&6;}\n    sed 's/^/| /' \"$ac_site_file\" >&5\n    . \"$ac_site_file\" \\\n      || { { $as_echo \"$as_me:${as_lineno-$LINENO}: error: in \\`$ac_pwd':\" >&5\n$as_echo \"$as_me: error: in \\`$ac_pwd':\" >&2;}\nas_fn_error $? \"failed to load site script $ac_site_file\nSee \\`config.log' for more details\" \"$LINENO\" 5; }\n  fi\ndone\n\nif test -r \"$cache_file\"; then\n  # Some versions of bash will fail to source /dev/null (special files\n  # actually), so we avoid doing that.  DJGPP emulates it as a regular file.\n  if test /dev/null != \"$cache_file\" && test -f \"$cache_file\"; then\n    { $as_echo \"$as_me:${as_lineno-$LINENO}: loading cache $cache_file\" >&5\n$as_echo \"$as_me: loading cache $cache_file\" >&6;}\n    case $cache_file in\n      [\\\\/]* | ?:[\\\\/]* ) . \"$cache_file\";;\n      *)                      . \"./$cache_file\";;\n    esac\n  fi\nelse\n  { $as_echo \"$as_me:${as_lineno-$LINENO}: creating cache $cache_file\" >&5\n$as_echo \"$as_me: creating cache $cache_file\" >&6;}\n  >$cache_file\nfi\n\n# Check that the precious variables saved in the cache have kept the same\n# value.\nac_cache_corrupted=false\nfor ac_var in $ac_precious_vars; do\n  eval ac_old_set=\\$ac_cv_env_${ac_var}_set\n  eval ac_new_set=\\$ac_env_${ac_var}_set\n  eval ac_old_val=\\$ac_cv_env_${ac_var}_value\n  eval ac_new_val=\\$ac_env_${ac_var}_value\n  case $ac_old_set,$ac_new_set in\n    set,)\n      { $as_echo \"$as_me:${as_lineno-$LINENO}: error: \\`$ac_var' was set to \\`$ac_old_val' in the previous run\" >&5\n$as_echo \"$as_me: error: \\`$ac_var' was set to \\`$ac_old_val' in the previous run\" >&2;}\n      ac_cache_corrupted=: ;;\n    ,set)\n      { $as_echo \"$as_me:${as_lineno-$LINENO}: error: \\`$ac_var' was not set in the previous run\" >&5\n$as_echo \"$as_me: error: \\`$ac_var' was not set in the previous run\" >&2;}\n      ac_cache_corrupted=: ;;\n    ,);;\n    *)\n      if test \"x$ac_old_val\" != \"x$ac_new_val\"; then\n\t# differences in whitespace do not lead to failure.\n\tac_old_val_w=`echo x $ac_old_val`\n\tac_new_val_w=`echo x $ac_new_val`\n\tif test \"$ac_old_val_w\" != \"$ac_new_val_w\"; then\n\t  { $as_echo \"$as_me:${as_lineno-$LINENO}: error: \\`$ac_var' has changed since the previous run:\" >&5\n$as_echo \"$as_me: error: \\`$ac_var' has changed since the previous run:\" >&2;}\n\t  ac_cache_corrupted=:\n\telse\n\t  { $as_echo \"$as_me:${as_lineno-$LINENO}: warning: ignoring whitespace changes in \\`$ac_var' since the previous run:\" >&5\n$as_echo \"$as_me: warning: ignoring whitespace changes in \\`$ac_var' since the previous run:\" >&2;}\n\t  eval $ac_var=\\$ac_old_val\n\tfi\n\t{ $as_echo \"$as_me:${as_lineno-$LINENO}:   former value:  \\`$ac_old_val'\" >&5\n$as_echo \"$as_me:   former value:  \\`$ac_old_val'\" >&2;}\n\t{ $as_echo \"$as_me:${as_lineno-$LINENO}:   current value: \\`$ac_new_val'\" >&5\n$as_echo \"$as_me:   current value: \\`$ac_new_val'\" >&2;}\n      fi;;\n  esac\n  # Pass precious variables to config.status.\n  if test \"$ac_new_set\" = set; then\n    case $ac_new_val in\n    *\\'*) ac_arg=$ac_var=`$as_echo \"$ac_new_val\" | sed \"s/'/'\\\\\\\\\\\\\\\\''/g\"` ;;\n    *) ac_arg=$ac_var=$ac_new_val ;;\n    esac\n    case \" $ac_configure_args \" in\n      *\" '$ac_arg' \"*) ;; # Avoid dups.  Use of quotes ensures accuracy.\n      *) as_fn_append ac_configure_args \" '$ac_arg'\" ;;\n    esac\n  fi\ndone\nif $ac_cache_corrupted; then\n  { $as_echo \"$as_me:${as_lineno-$LINENO}: error: in \\`$ac_pwd':\" >&5\n$as_echo \"$as_me: error: in \\`$ac_pwd':\" >&2;}\n  { $as_echo \"$as_me:${as_lineno-$LINENO}: error: changes in the environment can compromise the build\" >&5\n$as_echo \"$as_me: error: changes in the environment can compromise the build\" >&2;}\n  as_fn_error $? \"run \\`make distclean' and/or \\`rm $cache_file' and start over\" \"$LINENO\" 5\nfi\n## -------------------- ##\n## Main body of script. ##\n## -------------------- ##\n\nac_ext=c\nac_cpp='$CPP $CPPFLAGS'\nac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'\nac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'\nac_compiler_gnu=$ac_cv_c_compiler_gnu\n\n\n\n\n\n\n\n\n\nCONFIG=`echo ${ac_configure_args} | sed -e 's#'\"'\"'\\([^ ]*\\)'\"'\"'#\\1#g'`\n\n\nrev=2\n\n\nsrcroot=$srcdir\nif test \"x${srcroot}\" = \"x.\" ; then\n  srcroot=\"\"\nelse\n  srcroot=\"${srcroot}/\"\nfi\n\nabs_srcroot=\"`cd \\\"${srcdir}\\\"; pwd`/\"\n\n\nobjroot=\"\"\n\nabs_objroot=\"`pwd`/\"\n\n\nif test \"x$prefix\" = \"xNONE\" ; then\n  prefix=\"/usr/local\"\nfi\nif test \"x$exec_prefix\" = \"xNONE\" ; then\n  exec_prefix=$prefix\nfi\nPREFIX=$prefix\n\nBINDIR=`eval echo $bindir`\nBINDIR=`eval echo $BINDIR`\n\nINCLUDEDIR=`eval echo $includedir`\nINCLUDEDIR=`eval echo $INCLUDEDIR`\n\nLIBDIR=`eval echo $libdir`\nLIBDIR=`eval echo $LIBDIR`\n\nDATADIR=`eval echo $datadir`\nDATADIR=`eval echo $DATADIR`\n\nMANDIR=`eval echo $mandir`\nMANDIR=`eval echo $MANDIR`\n\n\n# Extract the first word of \"xsltproc\", so it can be a program name with args.\nset dummy xsltproc; ac_word=$2\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: checking for $ac_word\" >&5\n$as_echo_n \"checking for $ac_word... \" >&6; }\nif ${ac_cv_path_XSLTPROC+:} false; then :\n  $as_echo_n \"(cached) \" >&6\nelse\n  case $XSLTPROC in\n  [\\\\/]* | ?:[\\\\/]*)\n  ac_cv_path_XSLTPROC=\"$XSLTPROC\" # Let the user override the test with a path.\n  ;;\n  *)\n  as_save_IFS=$IFS; IFS=$PATH_SEPARATOR\nfor as_dir in $PATH\ndo\n  IFS=$as_save_IFS\n  test -z \"$as_dir\" && as_dir=.\n    for ac_exec_ext in '' $ac_executable_extensions; do\n  if as_fn_executable_p \"$as_dir/$ac_word$ac_exec_ext\"; then\n    ac_cv_path_XSLTPROC=\"$as_dir/$ac_word$ac_exec_ext\"\n    $as_echo \"$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext\" >&5\n    break 2\n  fi\ndone\n  done\nIFS=$as_save_IFS\n\n  test -z \"$ac_cv_path_XSLTPROC\" && ac_cv_path_XSLTPROC=\"false\"\n  ;;\nesac\nfi\nXSLTPROC=$ac_cv_path_XSLTPROC\nif test -n \"$XSLTPROC\"; then\n  { $as_echo \"$as_me:${as_lineno-$LINENO}: result: $XSLTPROC\" >&5\n$as_echo \"$XSLTPROC\" >&6; }\nelse\n  { $as_echo \"$as_me:${as_lineno-$LINENO}: result: no\" >&5\n$as_echo \"no\" >&6; }\nfi\n\n\nif test -d \"/usr/share/xml/docbook/stylesheet/docbook-xsl\" ; then\n  DEFAULT_XSLROOT=\"/usr/share/xml/docbook/stylesheet/docbook-xsl\"\nelif test -d \"/usr/share/sgml/docbook/xsl-stylesheets\" ; then\n  DEFAULT_XSLROOT=\"/usr/share/sgml/docbook/xsl-stylesheets\"\nelse\n    DEFAULT_XSLROOT=\"\"\nfi\n\n# Check whether --with-xslroot was given.\nif test \"${with_xslroot+set}\" = set; then :\n  withval=$with_xslroot;\nif test \"x$with_xslroot\" = \"xno\" ; then\n  XSLROOT=\"${DEFAULT_XSLROOT}\"\nelse\n  XSLROOT=\"${with_xslroot}\"\nfi\n\nelse\n  XSLROOT=\"${DEFAULT_XSLROOT}\"\n\nfi\n\n\n\nCFLAGS=$CFLAGS\nac_ext=c\nac_cpp='$CPP $CPPFLAGS'\nac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'\nac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'\nac_compiler_gnu=$ac_cv_c_compiler_gnu\nif test -n \"$ac_tool_prefix\"; then\n  # Extract the first word of \"${ac_tool_prefix}gcc\", so it can be a program name with args.\nset dummy ${ac_tool_prefix}gcc; ac_word=$2\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: checking for $ac_word\" >&5\n$as_echo_n \"checking for $ac_word... \" >&6; }\nif ${ac_cv_prog_CC+:} false; then :\n  $as_echo_n \"(cached) \" >&6\nelse\n  if test -n \"$CC\"; then\n  ac_cv_prog_CC=\"$CC\" # Let the user override the test.\nelse\nas_save_IFS=$IFS; IFS=$PATH_SEPARATOR\nfor as_dir in $PATH\ndo\n  IFS=$as_save_IFS\n  test -z \"$as_dir\" && as_dir=.\n    for ac_exec_ext in '' $ac_executable_extensions; do\n  if as_fn_executable_p \"$as_dir/$ac_word$ac_exec_ext\"; then\n    ac_cv_prog_CC=\"${ac_tool_prefix}gcc\"\n    $as_echo \"$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext\" >&5\n    break 2\n  fi\ndone\n  done\nIFS=$as_save_IFS\n\nfi\nfi\nCC=$ac_cv_prog_CC\nif test -n \"$CC\"; then\n  { $as_echo \"$as_me:${as_lineno-$LINENO}: result: $CC\" >&5\n$as_echo \"$CC\" >&6; }\nelse\n  { $as_echo \"$as_me:${as_lineno-$LINENO}: result: no\" >&5\n$as_echo \"no\" >&6; }\nfi\n\n\nfi\nif test -z \"$ac_cv_prog_CC\"; then\n  ac_ct_CC=$CC\n  # Extract the first word of \"gcc\", so it can be a program name with args.\nset dummy gcc; ac_word=$2\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: checking for $ac_word\" >&5\n$as_echo_n \"checking for $ac_word... \" >&6; }\nif ${ac_cv_prog_ac_ct_CC+:} false; then :\n  $as_echo_n \"(cached) \" >&6\nelse\n  if test -n \"$ac_ct_CC\"; then\n  ac_cv_prog_ac_ct_CC=\"$ac_ct_CC\" # Let the user override the test.\nelse\nas_save_IFS=$IFS; IFS=$PATH_SEPARATOR\nfor as_dir in $PATH\ndo\n  IFS=$as_save_IFS\n  test -z \"$as_dir\" && as_dir=.\n    for ac_exec_ext in '' $ac_executable_extensions; do\n  if as_fn_executable_p \"$as_dir/$ac_word$ac_exec_ext\"; then\n    ac_cv_prog_ac_ct_CC=\"gcc\"\n    $as_echo \"$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext\" >&5\n    break 2\n  fi\ndone\n  done\nIFS=$as_save_IFS\n\nfi\nfi\nac_ct_CC=$ac_cv_prog_ac_ct_CC\nif test -n \"$ac_ct_CC\"; then\n  { $as_echo \"$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC\" >&5\n$as_echo \"$ac_ct_CC\" >&6; }\nelse\n  { $as_echo \"$as_me:${as_lineno-$LINENO}: result: no\" >&5\n$as_echo \"no\" >&6; }\nfi\n\n  if test \"x$ac_ct_CC\" = x; then\n    CC=\"\"\n  else\n    case $cross_compiling:$ac_tool_warned in\nyes:)\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet\" >&5\n$as_echo \"$as_me: WARNING: using cross tools not prefixed with host triplet\" >&2;}\nac_tool_warned=yes ;;\nesac\n    CC=$ac_ct_CC\n  fi\nelse\n  CC=\"$ac_cv_prog_CC\"\nfi\n\nif test -z \"$CC\"; then\n          if test -n \"$ac_tool_prefix\"; then\n    # Extract the first word of \"${ac_tool_prefix}cc\", so it can be a program name with args.\nset dummy ${ac_tool_prefix}cc; ac_word=$2\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: checking for $ac_word\" >&5\n$as_echo_n \"checking for $ac_word... \" >&6; }\nif ${ac_cv_prog_CC+:} false; then :\n  $as_echo_n \"(cached) \" >&6\nelse\n  if test -n \"$CC\"; then\n  ac_cv_prog_CC=\"$CC\" # Let the user override the test.\nelse\nas_save_IFS=$IFS; IFS=$PATH_SEPARATOR\nfor as_dir in $PATH\ndo\n  IFS=$as_save_IFS\n  test -z \"$as_dir\" && as_dir=.\n    for ac_exec_ext in '' $ac_executable_extensions; do\n  if as_fn_executable_p \"$as_dir/$ac_word$ac_exec_ext\"; then\n    ac_cv_prog_CC=\"${ac_tool_prefix}cc\"\n    $as_echo \"$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext\" >&5\n    break 2\n  fi\ndone\n  done\nIFS=$as_save_IFS\n\nfi\nfi\nCC=$ac_cv_prog_CC\nif test -n \"$CC\"; then\n  { $as_echo \"$as_me:${as_lineno-$LINENO}: result: $CC\" >&5\n$as_echo \"$CC\" >&6; }\nelse\n  { $as_echo \"$as_me:${as_lineno-$LINENO}: result: no\" >&5\n$as_echo \"no\" >&6; }\nfi\n\n\n  fi\nfi\nif test -z \"$CC\"; then\n  # Extract the first word of \"cc\", so it can be a program name with args.\nset dummy cc; ac_word=$2\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: checking for $ac_word\" >&5\n$as_echo_n \"checking for $ac_word... \" >&6; }\nif ${ac_cv_prog_CC+:} false; then :\n  $as_echo_n \"(cached) \" >&6\nelse\n  if test -n \"$CC\"; then\n  ac_cv_prog_CC=\"$CC\" # Let the user override the test.\nelse\n  ac_prog_rejected=no\nas_save_IFS=$IFS; IFS=$PATH_SEPARATOR\nfor as_dir in $PATH\ndo\n  IFS=$as_save_IFS\n  test -z \"$as_dir\" && as_dir=.\n    for ac_exec_ext in '' $ac_executable_extensions; do\n  if as_fn_executable_p \"$as_dir/$ac_word$ac_exec_ext\"; then\n    if test \"$as_dir/$ac_word$ac_exec_ext\" = \"/usr/ucb/cc\"; then\n       ac_prog_rejected=yes\n       continue\n     fi\n    ac_cv_prog_CC=\"cc\"\n    $as_echo \"$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext\" >&5\n    break 2\n  fi\ndone\n  done\nIFS=$as_save_IFS\n\nif test $ac_prog_rejected = yes; then\n  # We found a bogon in the path, so make sure we never use it.\n  set dummy $ac_cv_prog_CC\n  shift\n  if test $# != 0; then\n    # We chose a different compiler from the bogus one.\n    # However, it has the same basename, so the bogon will be chosen\n    # first if we set CC to just the basename; use the full file name.\n    shift\n    ac_cv_prog_CC=\"$as_dir/$ac_word${1+' '}$@\"\n  fi\nfi\nfi\nfi\nCC=$ac_cv_prog_CC\nif test -n \"$CC\"; then\n  { $as_echo \"$as_me:${as_lineno-$LINENO}: result: $CC\" >&5\n$as_echo \"$CC\" >&6; }\nelse\n  { $as_echo \"$as_me:${as_lineno-$LINENO}: result: no\" >&5\n$as_echo \"no\" >&6; }\nfi\n\n\nfi\nif test -z \"$CC\"; then\n  if test -n \"$ac_tool_prefix\"; then\n  for ac_prog in cl.exe\n  do\n    # Extract the first word of \"$ac_tool_prefix$ac_prog\", so it can be a program name with args.\nset dummy $ac_tool_prefix$ac_prog; ac_word=$2\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: checking for $ac_word\" >&5\n$as_echo_n \"checking for $ac_word... \" >&6; }\nif ${ac_cv_prog_CC+:} false; then :\n  $as_echo_n \"(cached) \" >&6\nelse\n  if test -n \"$CC\"; then\n  ac_cv_prog_CC=\"$CC\" # Let the user override the test.\nelse\nas_save_IFS=$IFS; IFS=$PATH_SEPARATOR\nfor as_dir in $PATH\ndo\n  IFS=$as_save_IFS\n  test -z \"$as_dir\" && as_dir=.\n    for ac_exec_ext in '' $ac_executable_extensions; do\n  if as_fn_executable_p \"$as_dir/$ac_word$ac_exec_ext\"; then\n    ac_cv_prog_CC=\"$ac_tool_prefix$ac_prog\"\n    $as_echo \"$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext\" >&5\n    break 2\n  fi\ndone\n  done\nIFS=$as_save_IFS\n\nfi\nfi\nCC=$ac_cv_prog_CC\nif test -n \"$CC\"; then\n  { $as_echo \"$as_me:${as_lineno-$LINENO}: result: $CC\" >&5\n$as_echo \"$CC\" >&6; }\nelse\n  { $as_echo \"$as_me:${as_lineno-$LINENO}: result: no\" >&5\n$as_echo \"no\" >&6; }\nfi\n\n\n    test -n \"$CC\" && break\n  done\nfi\nif test -z \"$CC\"; then\n  ac_ct_CC=$CC\n  for ac_prog in cl.exe\ndo\n  # Extract the first word of \"$ac_prog\", so it can be a program name with args.\nset dummy $ac_prog; ac_word=$2\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: checking for $ac_word\" >&5\n$as_echo_n \"checking for $ac_word... \" >&6; }\nif ${ac_cv_prog_ac_ct_CC+:} false; then :\n  $as_echo_n \"(cached) \" >&6\nelse\n  if test -n \"$ac_ct_CC\"; then\n  ac_cv_prog_ac_ct_CC=\"$ac_ct_CC\" # Let the user override the test.\nelse\nas_save_IFS=$IFS; IFS=$PATH_SEPARATOR\nfor as_dir in $PATH\ndo\n  IFS=$as_save_IFS\n  test -z \"$as_dir\" && as_dir=.\n    for ac_exec_ext in '' $ac_executable_extensions; do\n  if as_fn_executable_p \"$as_dir/$ac_word$ac_exec_ext\"; then\n    ac_cv_prog_ac_ct_CC=\"$ac_prog\"\n    $as_echo \"$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext\" >&5\n    break 2\n  fi\ndone\n  done\nIFS=$as_save_IFS\n\nfi\nfi\nac_ct_CC=$ac_cv_prog_ac_ct_CC\nif test -n \"$ac_ct_CC\"; then\n  { $as_echo \"$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC\" >&5\n$as_echo \"$ac_ct_CC\" >&6; }\nelse\n  { $as_echo \"$as_me:${as_lineno-$LINENO}: result: no\" >&5\n$as_echo \"no\" >&6; }\nfi\n\n\n  test -n \"$ac_ct_CC\" && break\ndone\n\n  if test \"x$ac_ct_CC\" = x; then\n    CC=\"\"\n  else\n    case $cross_compiling:$ac_tool_warned in\nyes:)\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet\" >&5\n$as_echo \"$as_me: WARNING: using cross tools not prefixed with host triplet\" >&2;}\nac_tool_warned=yes ;;\nesac\n    CC=$ac_ct_CC\n  fi\nfi\n\nfi\n\n\ntest -z \"$CC\" && { { $as_echo \"$as_me:${as_lineno-$LINENO}: error: in \\`$ac_pwd':\" >&5\n$as_echo \"$as_me: error: in \\`$ac_pwd':\" >&2;}\nas_fn_error $? \"no acceptable C compiler found in \\$PATH\nSee \\`config.log' for more details\" \"$LINENO\" 5; }\n\n# Provide some information about the compiler.\n$as_echo \"$as_me:${as_lineno-$LINENO}: checking for C compiler version\" >&5\nset X $ac_compile\nac_compiler=$2\nfor ac_option in --version -v -V -qversion; do\n  { { ac_try=\"$ac_compiler $ac_option >&5\"\ncase \"(($ac_try\" in\n  *\\\"* | *\\`* | *\\\\*) ac_try_echo=\\$ac_try;;\n  *) ac_try_echo=$ac_try;;\nesac\neval ac_try_echo=\"\\\"\\$as_me:${as_lineno-$LINENO}: $ac_try_echo\\\"\"\n$as_echo \"$ac_try_echo\"; } >&5\n  (eval \"$ac_compiler $ac_option >&5\") 2>conftest.err\n  ac_status=$?\n  if test -s conftest.err; then\n    sed '10a\\\n... rest of stderr output deleted ...\n         10q' conftest.err >conftest.er1\n    cat conftest.er1 >&5\n  fi\n  rm -f conftest.er1 conftest.err\n  $as_echo \"$as_me:${as_lineno-$LINENO}: \\$? = $ac_status\" >&5\n  test $ac_status = 0; }\ndone\n\ncat confdefs.h - <<_ACEOF >conftest.$ac_ext\n/* end confdefs.h.  */\n\nint\nmain ()\n{\n\n  ;\n  return 0;\n}\n_ACEOF\nac_clean_files_save=$ac_clean_files\nac_clean_files=\"$ac_clean_files a.out a.out.dSYM a.exe b.out\"\n# Try to create an executable without -o first, disregard a.out.\n# It will help us diagnose broken compilers, and finding out an intuition\n# of exeext.\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: checking whether the C compiler works\" >&5\n$as_echo_n \"checking whether the C compiler works... \" >&6; }\nac_link_default=`$as_echo \"$ac_link\" | sed 's/ -o *conftest[^ ]*//'`\n\n# The possible output files:\nac_files=\"a.out conftest.exe conftest a.exe a_out.exe b.out conftest.*\"\n\nac_rmfiles=\nfor ac_file in $ac_files\ndo\n  case $ac_file in\n    *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;;\n    * ) ac_rmfiles=\"$ac_rmfiles $ac_file\";;\n  esac\ndone\nrm -f $ac_rmfiles\n\nif { { ac_try=\"$ac_link_default\"\ncase \"(($ac_try\" in\n  *\\\"* | *\\`* | *\\\\*) ac_try_echo=\\$ac_try;;\n  *) ac_try_echo=$ac_try;;\nesac\neval ac_try_echo=\"\\\"\\$as_me:${as_lineno-$LINENO}: $ac_try_echo\\\"\"\n$as_echo \"$ac_try_echo\"; } >&5\n  (eval \"$ac_link_default\") 2>&5\n  ac_status=$?\n  $as_echo \"$as_me:${as_lineno-$LINENO}: \\$? = $ac_status\" >&5\n  test $ac_status = 0; }; then :\n  # Autoconf-2.13 could set the ac_cv_exeext variable to `no'.\n# So ignore a value of `no', otherwise this would lead to `EXEEXT = no'\n# in a Makefile.  We should not override ac_cv_exeext if it was cached,\n# so that the user can short-circuit this test for compilers unknown to\n# Autoconf.\nfor ac_file in $ac_files ''\ndo\n  test -f \"$ac_file\" || continue\n  case $ac_file in\n    *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj )\n\t;;\n    [ab].out )\n\t# We found the default executable, but exeext='' is most\n\t# certainly right.\n\tbreak;;\n    *.* )\n\tif test \"${ac_cv_exeext+set}\" = set && test \"$ac_cv_exeext\" != no;\n\tthen :; else\n\t   ac_cv_exeext=`expr \"$ac_file\" : '[^.]*\\(\\..*\\)'`\n\tfi\n\t# We set ac_cv_exeext here because the later test for it is not\n\t# safe: cross compilers may not add the suffix if given an `-o'\n\t# argument, so we may need to know it at that point already.\n\t# Even if this section looks crufty: it has the advantage of\n\t# actually working.\n\tbreak;;\n    * )\n\tbreak;;\n  esac\ndone\ntest \"$ac_cv_exeext\" = no && ac_cv_exeext=\n\nelse\n  ac_file=''\nfi\nif test -z \"$ac_file\"; then :\n  { $as_echo \"$as_me:${as_lineno-$LINENO}: result: no\" >&5\n$as_echo \"no\" >&6; }\n$as_echo \"$as_me: failed program was:\" >&5\nsed 's/^/| /' conftest.$ac_ext >&5\n\n{ { $as_echo \"$as_me:${as_lineno-$LINENO}: error: in \\`$ac_pwd':\" >&5\n$as_echo \"$as_me: error: in \\`$ac_pwd':\" >&2;}\nas_fn_error 77 \"C compiler cannot create executables\nSee \\`config.log' for more details\" \"$LINENO\" 5; }\nelse\n  { $as_echo \"$as_me:${as_lineno-$LINENO}: result: yes\" >&5\n$as_echo \"yes\" >&6; }\nfi\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: checking for C compiler default output file name\" >&5\n$as_echo_n \"checking for C compiler default output file name... \" >&6; }\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: result: $ac_file\" >&5\n$as_echo \"$ac_file\" >&6; }\nac_exeext=$ac_cv_exeext\n\nrm -f -r a.out a.out.dSYM a.exe conftest$ac_cv_exeext b.out\nac_clean_files=$ac_clean_files_save\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: checking for suffix of executables\" >&5\n$as_echo_n \"checking for suffix of executables... \" >&6; }\nif { { ac_try=\"$ac_link\"\ncase \"(($ac_try\" in\n  *\\\"* | *\\`* | *\\\\*) ac_try_echo=\\$ac_try;;\n  *) ac_try_echo=$ac_try;;\nesac\neval ac_try_echo=\"\\\"\\$as_me:${as_lineno-$LINENO}: $ac_try_echo\\\"\"\n$as_echo \"$ac_try_echo\"; } >&5\n  (eval \"$ac_link\") 2>&5\n  ac_status=$?\n  $as_echo \"$as_me:${as_lineno-$LINENO}: \\$? = $ac_status\" >&5\n  test $ac_status = 0; }; then :\n  # If both `conftest.exe' and `conftest' are `present' (well, observable)\n# catch `conftest.exe'.  For instance with Cygwin, `ls conftest' will\n# work properly (i.e., refer to `conftest.exe'), while it won't with\n# `rm'.\nfor ac_file in conftest.exe conftest conftest.*; do\n  test -f \"$ac_file\" || continue\n  case $ac_file in\n    *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;;\n    *.* ) ac_cv_exeext=`expr \"$ac_file\" : '[^.]*\\(\\..*\\)'`\n\t  break;;\n    * ) break;;\n  esac\ndone\nelse\n  { { $as_echo \"$as_me:${as_lineno-$LINENO}: error: in \\`$ac_pwd':\" >&5\n$as_echo \"$as_me: error: in \\`$ac_pwd':\" >&2;}\nas_fn_error $? \"cannot compute suffix of executables: cannot compile and link\nSee \\`config.log' for more details\" \"$LINENO\" 5; }\nfi\nrm -f conftest conftest$ac_cv_exeext\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: result: $ac_cv_exeext\" >&5\n$as_echo \"$ac_cv_exeext\" >&6; }\n\nrm -f conftest.$ac_ext\nEXEEXT=$ac_cv_exeext\nac_exeext=$EXEEXT\ncat confdefs.h - <<_ACEOF >conftest.$ac_ext\n/* end confdefs.h.  */\n#include <stdio.h>\nint\nmain ()\n{\nFILE *f = fopen (\"conftest.out\", \"w\");\n return ferror (f) || fclose (f) != 0;\n\n  ;\n  return 0;\n}\n_ACEOF\nac_clean_files=\"$ac_clean_files conftest.out\"\n# Check that the compiler produces executables we can run.  If not, either\n# the compiler is broken, or we cross compile.\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: checking whether we are cross compiling\" >&5\n$as_echo_n \"checking whether we are cross compiling... \" >&6; }\nif test \"$cross_compiling\" != yes; then\n  { { ac_try=\"$ac_link\"\ncase \"(($ac_try\" in\n  *\\\"* | *\\`* | *\\\\*) ac_try_echo=\\$ac_try;;\n  *) ac_try_echo=$ac_try;;\nesac\neval ac_try_echo=\"\\\"\\$as_me:${as_lineno-$LINENO}: $ac_try_echo\\\"\"\n$as_echo \"$ac_try_echo\"; } >&5\n  (eval \"$ac_link\") 2>&5\n  ac_status=$?\n  $as_echo \"$as_me:${as_lineno-$LINENO}: \\$? = $ac_status\" >&5\n  test $ac_status = 0; }\n  if { ac_try='./conftest$ac_cv_exeext'\n  { { case \"(($ac_try\" in\n  *\\\"* | *\\`* | *\\\\*) ac_try_echo=\\$ac_try;;\n  *) ac_try_echo=$ac_try;;\nesac\neval ac_try_echo=\"\\\"\\$as_me:${as_lineno-$LINENO}: $ac_try_echo\\\"\"\n$as_echo \"$ac_try_echo\"; } >&5\n  (eval \"$ac_try\") 2>&5\n  ac_status=$?\n  $as_echo \"$as_me:${as_lineno-$LINENO}: \\$? = $ac_status\" >&5\n  test $ac_status = 0; }; }; then\n    cross_compiling=no\n  else\n    if test \"$cross_compiling\" = maybe; then\n\tcross_compiling=yes\n    else\n\t{ { $as_echo \"$as_me:${as_lineno-$LINENO}: error: in \\`$ac_pwd':\" >&5\n$as_echo \"$as_me: error: in \\`$ac_pwd':\" >&2;}\nas_fn_error $? \"cannot run C compiled programs.\nIf you meant to cross compile, use \\`--host'.\nSee \\`config.log' for more details\" \"$LINENO\" 5; }\n    fi\n  fi\nfi\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: result: $cross_compiling\" >&5\n$as_echo \"$cross_compiling\" >&6; }\n\nrm -f conftest.$ac_ext conftest$ac_cv_exeext conftest.out\nac_clean_files=$ac_clean_files_save\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: checking for suffix of object files\" >&5\n$as_echo_n \"checking for suffix of object files... \" >&6; }\nif ${ac_cv_objext+:} false; then :\n  $as_echo_n \"(cached) \" >&6\nelse\n  cat confdefs.h - <<_ACEOF >conftest.$ac_ext\n/* end confdefs.h.  */\n\nint\nmain ()\n{\n\n  ;\n  return 0;\n}\n_ACEOF\nrm -f conftest.o conftest.obj\nif { { ac_try=\"$ac_compile\"\ncase \"(($ac_try\" in\n  *\\\"* | *\\`* | *\\\\*) ac_try_echo=\\$ac_try;;\n  *) ac_try_echo=$ac_try;;\nesac\neval ac_try_echo=\"\\\"\\$as_me:${as_lineno-$LINENO}: $ac_try_echo\\\"\"\n$as_echo \"$ac_try_echo\"; } >&5\n  (eval \"$ac_compile\") 2>&5\n  ac_status=$?\n  $as_echo \"$as_me:${as_lineno-$LINENO}: \\$? = $ac_status\" >&5\n  test $ac_status = 0; }; then :\n  for ac_file in conftest.o conftest.obj conftest.*; do\n  test -f \"$ac_file\" || continue;\n  case $ac_file in\n    *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM ) ;;\n    *) ac_cv_objext=`expr \"$ac_file\" : '.*\\.\\(.*\\)'`\n       break;;\n  esac\ndone\nelse\n  $as_echo \"$as_me: failed program was:\" >&5\nsed 's/^/| /' conftest.$ac_ext >&5\n\n{ { $as_echo \"$as_me:${as_lineno-$LINENO}: error: in \\`$ac_pwd':\" >&5\n$as_echo \"$as_me: error: in \\`$ac_pwd':\" >&2;}\nas_fn_error $? \"cannot compute suffix of object files: cannot compile\nSee \\`config.log' for more details\" \"$LINENO\" 5; }\nfi\nrm -f conftest.$ac_cv_objext conftest.$ac_ext\nfi\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: result: $ac_cv_objext\" >&5\n$as_echo \"$ac_cv_objext\" >&6; }\nOBJEXT=$ac_cv_objext\nac_objext=$OBJEXT\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: checking whether we are using the GNU C compiler\" >&5\n$as_echo_n \"checking whether we are using the GNU C compiler... \" >&6; }\nif ${ac_cv_c_compiler_gnu+:} false; then :\n  $as_echo_n \"(cached) \" >&6\nelse\n  cat confdefs.h - <<_ACEOF >conftest.$ac_ext\n/* end confdefs.h.  */\n\nint\nmain ()\n{\n#ifndef __GNUC__\n       choke me\n#endif\n\n  ;\n  return 0;\n}\n_ACEOF\nif ac_fn_c_try_compile \"$LINENO\"; then :\n  ac_compiler_gnu=yes\nelse\n  ac_compiler_gnu=no\nfi\nrm -f core conftest.err conftest.$ac_objext conftest.$ac_ext\nac_cv_c_compiler_gnu=$ac_compiler_gnu\n\nfi\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_compiler_gnu\" >&5\n$as_echo \"$ac_cv_c_compiler_gnu\" >&6; }\nif test $ac_compiler_gnu = yes; then\n  GCC=yes\nelse\n  GCC=\nfi\nac_test_CFLAGS=${CFLAGS+set}\nac_save_CFLAGS=$CFLAGS\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: checking whether $CC accepts -g\" >&5\n$as_echo_n \"checking whether $CC accepts -g... \" >&6; }\nif ${ac_cv_prog_cc_g+:} false; then :\n  $as_echo_n \"(cached) \" >&6\nelse\n  ac_save_c_werror_flag=$ac_c_werror_flag\n   ac_c_werror_flag=yes\n   ac_cv_prog_cc_g=no\n   CFLAGS=\"-g\"\n   cat confdefs.h - <<_ACEOF >conftest.$ac_ext\n/* end confdefs.h.  */\n\nint\nmain ()\n{\n\n  ;\n  return 0;\n}\n_ACEOF\nif ac_fn_c_try_compile \"$LINENO\"; then :\n  ac_cv_prog_cc_g=yes\nelse\n  CFLAGS=\"\"\n      cat confdefs.h - <<_ACEOF >conftest.$ac_ext\n/* end confdefs.h.  */\n\nint\nmain ()\n{\n\n  ;\n  return 0;\n}\n_ACEOF\nif ac_fn_c_try_compile \"$LINENO\"; then :\n\nelse\n  ac_c_werror_flag=$ac_save_c_werror_flag\n\t CFLAGS=\"-g\"\n\t cat confdefs.h - <<_ACEOF >conftest.$ac_ext\n/* end confdefs.h.  */\n\nint\nmain ()\n{\n\n  ;\n  return 0;\n}\n_ACEOF\nif ac_fn_c_try_compile \"$LINENO\"; then :\n  ac_cv_prog_cc_g=yes\nfi\nrm -f core conftest.err conftest.$ac_objext conftest.$ac_ext\nfi\nrm -f core conftest.err conftest.$ac_objext conftest.$ac_ext\nfi\nrm -f core conftest.err conftest.$ac_objext conftest.$ac_ext\n   ac_c_werror_flag=$ac_save_c_werror_flag\nfi\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_g\" >&5\n$as_echo \"$ac_cv_prog_cc_g\" >&6; }\nif test \"$ac_test_CFLAGS\" = set; then\n  CFLAGS=$ac_save_CFLAGS\nelif test $ac_cv_prog_cc_g = yes; then\n  if test \"$GCC\" = yes; then\n    CFLAGS=\"-g -O2\"\n  else\n    CFLAGS=\"-g\"\n  fi\nelse\n  if test \"$GCC\" = yes; then\n    CFLAGS=\"-O2\"\n  else\n    CFLAGS=\n  fi\nfi\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: checking for $CC option to accept ISO C89\" >&5\n$as_echo_n \"checking for $CC option to accept ISO C89... \" >&6; }\nif ${ac_cv_prog_cc_c89+:} false; then :\n  $as_echo_n \"(cached) \" >&6\nelse\n  ac_cv_prog_cc_c89=no\nac_save_CC=$CC\ncat confdefs.h - <<_ACEOF >conftest.$ac_ext\n/* end confdefs.h.  */\n#include <stdarg.h>\n#include <stdio.h>\nstruct stat;\n/* Most of the following tests are stolen from RCS 5.7's src/conf.sh.  */\nstruct buf { int x; };\nFILE * (*rcsopen) (struct buf *, struct stat *, int);\nstatic char *e (p, i)\n     char **p;\n     int i;\n{\n  return p[i];\n}\nstatic char *f (char * (*g) (char **, int), char **p, ...)\n{\n  char *s;\n  va_list v;\n  va_start (v,p);\n  s = g (p, va_arg (v,int));\n  va_end (v);\n  return s;\n}\n\n/* OSF 4.0 Compaq cc is some sort of almost-ANSI by default.  It has\n   function prototypes and stuff, but not '\\xHH' hex character constants.\n   These don't provoke an error unfortunately, instead are silently treated\n   as 'x'.  The following induces an error, until -std is added to get\n   proper ANSI mode.  Curiously '\\x00'!='x' always comes out true, for an\n   array size at least.  It's necessary to write '\\x00'==0 to get something\n   that's true only with -std.  */\nint osf4_cc_array ['\\x00' == 0 ? 1 : -1];\n\n/* IBM C 6 for AIX is almost-ANSI by default, but it replaces macro parameters\n   inside strings and character constants.  */\n#define FOO(x) 'x'\nint xlc6_cc_array[FOO(a) == 'x' ? 1 : -1];\n\nint test (int i, double x);\nstruct s1 {int (*f) (int a);};\nstruct s2 {int (*f) (double a);};\nint pairnames (int, char **, FILE *(*)(struct buf *, struct stat *, int), int, int);\nint argc;\nchar **argv;\nint\nmain ()\n{\nreturn f (e, argv, 0) != argv[0]  ||  f (e, argv, 1) != argv[1];\n  ;\n  return 0;\n}\n_ACEOF\nfor ac_arg in '' -qlanglvl=extc89 -qlanglvl=ansi -std \\\n\t-Ae \"-Aa -D_HPUX_SOURCE\" \"-Xc -D__EXTENSIONS__\"\ndo\n  CC=\"$ac_save_CC $ac_arg\"\n  if ac_fn_c_try_compile \"$LINENO\"; then :\n  ac_cv_prog_cc_c89=$ac_arg\nfi\nrm -f core conftest.err conftest.$ac_objext\n  test \"x$ac_cv_prog_cc_c89\" != \"xno\" && break\ndone\nrm -f conftest.$ac_ext\nCC=$ac_save_CC\n\nfi\n# AC_CACHE_VAL\ncase \"x$ac_cv_prog_cc_c89\" in\n  x)\n    { $as_echo \"$as_me:${as_lineno-$LINENO}: result: none needed\" >&5\n$as_echo \"none needed\" >&6; } ;;\n  xno)\n    { $as_echo \"$as_me:${as_lineno-$LINENO}: result: unsupported\" >&5\n$as_echo \"unsupported\" >&6; } ;;\n  *)\n    CC=\"$CC $ac_cv_prog_cc_c89\"\n    { $as_echo \"$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_c89\" >&5\n$as_echo \"$ac_cv_prog_cc_c89\" >&6; } ;;\nesac\nif test \"x$ac_cv_prog_cc_c89\" != xno; then :\n\nfi\n\nac_ext=c\nac_cpp='$CPP $CPPFLAGS'\nac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'\nac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'\nac_compiler_gnu=$ac_cv_c_compiler_gnu\n\nif test \"x$GCC\" != \"xyes\" ; then\n\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: checking whether compiler is MSVC\" >&5\n$as_echo_n \"checking whether compiler is MSVC... \" >&6; }\nif ${je_cv_msvc+:} false; then :\n  $as_echo_n \"(cached) \" >&6\nelse\n  cat confdefs.h - <<_ACEOF >conftest.$ac_ext\n/* end confdefs.h.  */\n\nint\nmain ()\n{\n\n#ifndef _MSC_VER\n  int fail-1;\n#endif\n\n  ;\n  return 0;\n}\n_ACEOF\nif ac_fn_c_try_compile \"$LINENO\"; then :\n  je_cv_msvc=yes\nelse\n  je_cv_msvc=no\nfi\nrm -f core conftest.err conftest.$ac_objext conftest.$ac_ext\nfi\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: result: $je_cv_msvc\" >&5\n$as_echo \"$je_cv_msvc\" >&6; }\nfi\n\nif test \"x$CFLAGS\" = \"x\" ; then\n  no_CFLAGS=\"yes\"\n  if test \"x$GCC\" = \"xyes\" ; then\n\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: checking whether compiler supports -std=gnu99\" >&5\n$as_echo_n \"checking whether compiler supports -std=gnu99... \" >&6; }\nTCFLAGS=\"${CFLAGS}\"\nif test \"x${CFLAGS}\" = \"x\" ; then\n  CFLAGS=\"-std=gnu99\"\nelse\n  CFLAGS=\"${CFLAGS} -std=gnu99\"\nfi\ncat confdefs.h - <<_ACEOF >conftest.$ac_ext\n/* end confdefs.h.  */\n\n\nint\nmain ()\n{\n\n    return 0;\n\n  ;\n  return 0;\n}\n_ACEOF\nif ac_fn_c_try_compile \"$LINENO\"; then :\n  je_cv_cflags_appended=-std=gnu99\n              { $as_echo \"$as_me:${as_lineno-$LINENO}: result: yes\" >&5\n$as_echo \"yes\" >&6; }\nelse\n  je_cv_cflags_appended=\n              { $as_echo \"$as_me:${as_lineno-$LINENO}: result: no\" >&5\n$as_echo \"no\" >&6; }\n              CFLAGS=\"${TCFLAGS}\"\n\nfi\nrm -f core conftest.err conftest.$ac_objext conftest.$ac_ext\n\n    if test \"x$je_cv_cflags_appended\" = \"x-std=gnu99\" ; then\n      cat >>confdefs.h <<_ACEOF\n#define JEMALLOC_HAS_RESTRICT 1\n_ACEOF\n\n    fi\n\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: checking whether compiler supports -Wall\" >&5\n$as_echo_n \"checking whether compiler supports -Wall... \" >&6; }\nTCFLAGS=\"${CFLAGS}\"\nif test \"x${CFLAGS}\" = \"x\" ; then\n  CFLAGS=\"-Wall\"\nelse\n  CFLAGS=\"${CFLAGS} -Wall\"\nfi\ncat confdefs.h - <<_ACEOF >conftest.$ac_ext\n/* end confdefs.h.  */\n\n\nint\nmain ()\n{\n\n    return 0;\n\n  ;\n  return 0;\n}\n_ACEOF\nif ac_fn_c_try_compile \"$LINENO\"; then :\n  je_cv_cflags_appended=-Wall\n              { $as_echo \"$as_me:${as_lineno-$LINENO}: result: yes\" >&5\n$as_echo \"yes\" >&6; }\nelse\n  je_cv_cflags_appended=\n              { $as_echo \"$as_me:${as_lineno-$LINENO}: result: no\" >&5\n$as_echo \"no\" >&6; }\n              CFLAGS=\"${TCFLAGS}\"\n\nfi\nrm -f core conftest.err conftest.$ac_objext conftest.$ac_ext\n\n\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: checking whether compiler supports -Werror=declaration-after-statement\" >&5\n$as_echo_n \"checking whether compiler supports -Werror=declaration-after-statement... \" >&6; }\nTCFLAGS=\"${CFLAGS}\"\nif test \"x${CFLAGS}\" = \"x\" ; then\n  CFLAGS=\"-Werror=declaration-after-statement\"\nelse\n  CFLAGS=\"${CFLAGS} -Werror=declaration-after-statement\"\nfi\ncat confdefs.h - <<_ACEOF >conftest.$ac_ext\n/* end confdefs.h.  */\n\n\nint\nmain ()\n{\n\n    return 0;\n\n  ;\n  return 0;\n}\n_ACEOF\nif ac_fn_c_try_compile \"$LINENO\"; then :\n  je_cv_cflags_appended=-Werror=declaration-after-statement\n              { $as_echo \"$as_me:${as_lineno-$LINENO}: result: yes\" >&5\n$as_echo \"yes\" >&6; }\nelse\n  je_cv_cflags_appended=\n              { $as_echo \"$as_me:${as_lineno-$LINENO}: result: no\" >&5\n$as_echo \"no\" >&6; }\n              CFLAGS=\"${TCFLAGS}\"\n\nfi\nrm -f core conftest.err conftest.$ac_objext conftest.$ac_ext\n\n\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: checking whether compiler supports -pipe\" >&5\n$as_echo_n \"checking whether compiler supports -pipe... \" >&6; }\nTCFLAGS=\"${CFLAGS}\"\nif test \"x${CFLAGS}\" = \"x\" ; then\n  CFLAGS=\"-pipe\"\nelse\n  CFLAGS=\"${CFLAGS} -pipe\"\nfi\ncat confdefs.h - <<_ACEOF >conftest.$ac_ext\n/* end confdefs.h.  */\n\n\nint\nmain ()\n{\n\n    return 0;\n\n  ;\n  return 0;\n}\n_ACEOF\nif ac_fn_c_try_compile \"$LINENO\"; then :\n  je_cv_cflags_appended=-pipe\n              { $as_echo \"$as_me:${as_lineno-$LINENO}: result: yes\" >&5\n$as_echo \"yes\" >&6; }\nelse\n  je_cv_cflags_appended=\n              { $as_echo \"$as_me:${as_lineno-$LINENO}: result: no\" >&5\n$as_echo \"no\" >&6; }\n              CFLAGS=\"${TCFLAGS}\"\n\nfi\nrm -f core conftest.err conftest.$ac_objext conftest.$ac_ext\n\n\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: checking whether compiler supports -g3\" >&5\n$as_echo_n \"checking whether compiler supports -g3... \" >&6; }\nTCFLAGS=\"${CFLAGS}\"\nif test \"x${CFLAGS}\" = \"x\" ; then\n  CFLAGS=\"-g3\"\nelse\n  CFLAGS=\"${CFLAGS} -g3\"\nfi\ncat confdefs.h - <<_ACEOF >conftest.$ac_ext\n/* end confdefs.h.  */\n\n\nint\nmain ()\n{\n\n    return 0;\n\n  ;\n  return 0;\n}\n_ACEOF\nif ac_fn_c_try_compile \"$LINENO\"; then :\n  je_cv_cflags_appended=-g3\n              { $as_echo \"$as_me:${as_lineno-$LINENO}: result: yes\" >&5\n$as_echo \"yes\" >&6; }\nelse\n  je_cv_cflags_appended=\n              { $as_echo \"$as_me:${as_lineno-$LINENO}: result: no\" >&5\n$as_echo \"no\" >&6; }\n              CFLAGS=\"${TCFLAGS}\"\n\nfi\nrm -f core conftest.err conftest.$ac_objext conftest.$ac_ext\n\n  elif test \"x$je_cv_msvc\" = \"xyes\" ; then\n    CC=\"$CC -nologo\"\n\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: checking whether compiler supports -Zi\" >&5\n$as_echo_n \"checking whether compiler supports -Zi... \" >&6; }\nTCFLAGS=\"${CFLAGS}\"\nif test \"x${CFLAGS}\" = \"x\" ; then\n  CFLAGS=\"-Zi\"\nelse\n  CFLAGS=\"${CFLAGS} -Zi\"\nfi\ncat confdefs.h - <<_ACEOF >conftest.$ac_ext\n/* end confdefs.h.  */\n\n\nint\nmain ()\n{\n\n    return 0;\n\n  ;\n  return 0;\n}\n_ACEOF\nif ac_fn_c_try_compile \"$LINENO\"; then :\n  je_cv_cflags_appended=-Zi\n              { $as_echo \"$as_me:${as_lineno-$LINENO}: result: yes\" >&5\n$as_echo \"yes\" >&6; }\nelse\n  je_cv_cflags_appended=\n              { $as_echo \"$as_me:${as_lineno-$LINENO}: result: no\" >&5\n$as_echo \"no\" >&6; }\n              CFLAGS=\"${TCFLAGS}\"\n\nfi\nrm -f core conftest.err conftest.$ac_objext conftest.$ac_ext\n\n\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: checking whether compiler supports -MT\" >&5\n$as_echo_n \"checking whether compiler supports -MT... \" >&6; }\nTCFLAGS=\"${CFLAGS}\"\nif test \"x${CFLAGS}\" = \"x\" ; then\n  CFLAGS=\"-MT\"\nelse\n  CFLAGS=\"${CFLAGS} -MT\"\nfi\ncat confdefs.h - <<_ACEOF >conftest.$ac_ext\n/* end confdefs.h.  */\n\n\nint\nmain ()\n{\n\n    return 0;\n\n  ;\n  return 0;\n}\n_ACEOF\nif ac_fn_c_try_compile \"$LINENO\"; then :\n  je_cv_cflags_appended=-MT\n              { $as_echo \"$as_me:${as_lineno-$LINENO}: result: yes\" >&5\n$as_echo \"yes\" >&6; }\nelse\n  je_cv_cflags_appended=\n              { $as_echo \"$as_me:${as_lineno-$LINENO}: result: no\" >&5\n$as_echo \"no\" >&6; }\n              CFLAGS=\"${TCFLAGS}\"\n\nfi\nrm -f core conftest.err conftest.$ac_objext conftest.$ac_ext\n\n\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: checking whether compiler supports -W3\" >&5\n$as_echo_n \"checking whether compiler supports -W3... \" >&6; }\nTCFLAGS=\"${CFLAGS}\"\nif test \"x${CFLAGS}\" = \"x\" ; then\n  CFLAGS=\"-W3\"\nelse\n  CFLAGS=\"${CFLAGS} -W3\"\nfi\ncat confdefs.h - <<_ACEOF >conftest.$ac_ext\n/* end confdefs.h.  */\n\n\nint\nmain ()\n{\n\n    return 0;\n\n  ;\n  return 0;\n}\n_ACEOF\nif ac_fn_c_try_compile \"$LINENO\"; then :\n  je_cv_cflags_appended=-W3\n              { $as_echo \"$as_me:${as_lineno-$LINENO}: result: yes\" >&5\n$as_echo \"yes\" >&6; }\nelse\n  je_cv_cflags_appended=\n              { $as_echo \"$as_me:${as_lineno-$LINENO}: result: no\" >&5\n$as_echo \"no\" >&6; }\n              CFLAGS=\"${TCFLAGS}\"\n\nfi\nrm -f core conftest.err conftest.$ac_objext conftest.$ac_ext\n\n\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: checking whether compiler supports -FS\" >&5\n$as_echo_n \"checking whether compiler supports -FS... \" >&6; }\nTCFLAGS=\"${CFLAGS}\"\nif test \"x${CFLAGS}\" = \"x\" ; then\n  CFLAGS=\"-FS\"\nelse\n  CFLAGS=\"${CFLAGS} -FS\"\nfi\ncat confdefs.h - <<_ACEOF >conftest.$ac_ext\n/* end confdefs.h.  */\n\n\nint\nmain ()\n{\n\n    return 0;\n\n  ;\n  return 0;\n}\n_ACEOF\nif ac_fn_c_try_compile \"$LINENO\"; then :\n  je_cv_cflags_appended=-FS\n              { $as_echo \"$as_me:${as_lineno-$LINENO}: result: yes\" >&5\n$as_echo \"yes\" >&6; }\nelse\n  je_cv_cflags_appended=\n              { $as_echo \"$as_me:${as_lineno-$LINENO}: result: no\" >&5\n$as_echo \"no\" >&6; }\n              CFLAGS=\"${TCFLAGS}\"\n\nfi\nrm -f core conftest.err conftest.$ac_objext conftest.$ac_ext\n\n    CPPFLAGS=\"$CPPFLAGS -I${srcdir}/include/msvc_compat\"\n  fi\nfi\nif test \"x$EXTRA_CFLAGS\" != \"x\" ; then\n\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: checking whether compiler supports $EXTRA_CFLAGS\" >&5\n$as_echo_n \"checking whether compiler supports $EXTRA_CFLAGS... \" >&6; }\nTCFLAGS=\"${CFLAGS}\"\nif test \"x${CFLAGS}\" = \"x\" ; then\n  CFLAGS=\"$EXTRA_CFLAGS\"\nelse\n  CFLAGS=\"${CFLAGS} $EXTRA_CFLAGS\"\nfi\ncat confdefs.h - <<_ACEOF >conftest.$ac_ext\n/* end confdefs.h.  */\n\n\nint\nmain ()\n{\n\n    return 0;\n\n  ;\n  return 0;\n}\n_ACEOF\nif ac_fn_c_try_compile \"$LINENO\"; then :\n  je_cv_cflags_appended=$EXTRA_CFLAGS\n              { $as_echo \"$as_me:${as_lineno-$LINENO}: result: yes\" >&5\n$as_echo \"yes\" >&6; }\nelse\n  je_cv_cflags_appended=\n              { $as_echo \"$as_me:${as_lineno-$LINENO}: result: no\" >&5\n$as_echo \"no\" >&6; }\n              CFLAGS=\"${TCFLAGS}\"\n\nfi\nrm -f core conftest.err conftest.$ac_objext conftest.$ac_ext\n\nfi\nac_ext=c\nac_cpp='$CPP $CPPFLAGS'\nac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'\nac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'\nac_compiler_gnu=$ac_cv_c_compiler_gnu\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: checking how to run the C preprocessor\" >&5\n$as_echo_n \"checking how to run the C preprocessor... \" >&6; }\n# On Suns, sometimes $CPP names a directory.\nif test -n \"$CPP\" && test -d \"$CPP\"; then\n  CPP=\nfi\nif test -z \"$CPP\"; then\n  if ${ac_cv_prog_CPP+:} false; then :\n  $as_echo_n \"(cached) \" >&6\nelse\n      # Double quotes because CPP needs to be expanded\n    for CPP in \"$CC -E\" \"$CC -E -traditional-cpp\" \"/lib/cpp\"\n    do\n      ac_preproc_ok=false\nfor ac_c_preproc_warn_flag in '' yes\ndo\n  # Use a header file that comes with gcc, so configuring glibc\n  # with a fresh cross-compiler works.\n  # Prefer <limits.h> to <assert.h> if __STDC__ is defined, since\n  # <limits.h> exists even on freestanding compilers.\n  # On the NeXT, cc -E runs the code through the compiler's parser,\n  # not just through cpp. \"Syntax error\" is here to catch this case.\n  cat confdefs.h - <<_ACEOF >conftest.$ac_ext\n/* end confdefs.h.  */\n#ifdef __STDC__\n# include <limits.h>\n#else\n# include <assert.h>\n#endif\n\t\t     Syntax error\n_ACEOF\nif ac_fn_c_try_cpp \"$LINENO\"; then :\n\nelse\n  # Broken: fails on valid input.\ncontinue\nfi\nrm -f conftest.err conftest.i conftest.$ac_ext\n\n  # OK, works on sane cases.  Now check whether nonexistent headers\n  # can be detected and how.\n  cat confdefs.h - <<_ACEOF >conftest.$ac_ext\n/* end confdefs.h.  */\n#include <ac_nonexistent.h>\n_ACEOF\nif ac_fn_c_try_cpp \"$LINENO\"; then :\n  # Broken: success on invalid input.\ncontinue\nelse\n  # Passes both tests.\nac_preproc_ok=:\nbreak\nfi\nrm -f conftest.err conftest.i conftest.$ac_ext\n\ndone\n# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped.\nrm -f conftest.i conftest.err conftest.$ac_ext\nif $ac_preproc_ok; then :\n  break\nfi\n\n    done\n    ac_cv_prog_CPP=$CPP\n\nfi\n  CPP=$ac_cv_prog_CPP\nelse\n  ac_cv_prog_CPP=$CPP\nfi\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: result: $CPP\" >&5\n$as_echo \"$CPP\" >&6; }\nac_preproc_ok=false\nfor ac_c_preproc_warn_flag in '' yes\ndo\n  # Use a header file that comes with gcc, so configuring glibc\n  # with a fresh cross-compiler works.\n  # Prefer <limits.h> to <assert.h> if __STDC__ is defined, since\n  # <limits.h> exists even on freestanding compilers.\n  # On the NeXT, cc -E runs the code through the compiler's parser,\n  # not just through cpp. \"Syntax error\" is here to catch this case.\n  cat confdefs.h - <<_ACEOF >conftest.$ac_ext\n/* end confdefs.h.  */\n#ifdef __STDC__\n# include <limits.h>\n#else\n# include <assert.h>\n#endif\n\t\t     Syntax error\n_ACEOF\nif ac_fn_c_try_cpp \"$LINENO\"; then :\n\nelse\n  # Broken: fails on valid input.\ncontinue\nfi\nrm -f conftest.err conftest.i conftest.$ac_ext\n\n  # OK, works on sane cases.  Now check whether nonexistent headers\n  # can be detected and how.\n  cat confdefs.h - <<_ACEOF >conftest.$ac_ext\n/* end confdefs.h.  */\n#include <ac_nonexistent.h>\n_ACEOF\nif ac_fn_c_try_cpp \"$LINENO\"; then :\n  # Broken: success on invalid input.\ncontinue\nelse\n  # Passes both tests.\nac_preproc_ok=:\nbreak\nfi\nrm -f conftest.err conftest.i conftest.$ac_ext\n\ndone\n# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped.\nrm -f conftest.i conftest.err conftest.$ac_ext\nif $ac_preproc_ok; then :\n\nelse\n  { { $as_echo \"$as_me:${as_lineno-$LINENO}: error: in \\`$ac_pwd':\" >&5\n$as_echo \"$as_me: error: in \\`$ac_pwd':\" >&2;}\nas_fn_error $? \"C preprocessor \\\"$CPP\\\" fails sanity check\nSee \\`config.log' for more details\" \"$LINENO\" 5; }\nfi\n\nac_ext=c\nac_cpp='$CPP $CPPFLAGS'\nac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'\nac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'\nac_compiler_gnu=$ac_cv_c_compiler_gnu\n\n\n\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: checking for grep that handles long lines and -e\" >&5\n$as_echo_n \"checking for grep that handles long lines and -e... \" >&6; }\nif ${ac_cv_path_GREP+:} false; then :\n  $as_echo_n \"(cached) \" >&6\nelse\n  if test -z \"$GREP\"; then\n  ac_path_GREP_found=false\n  # Loop through the user's path and test for each of PROGNAME-LIST\n  as_save_IFS=$IFS; IFS=$PATH_SEPARATOR\nfor as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin\ndo\n  IFS=$as_save_IFS\n  test -z \"$as_dir\" && as_dir=.\n    for ac_prog in grep ggrep; do\n    for ac_exec_ext in '' $ac_executable_extensions; do\n      ac_path_GREP=\"$as_dir/$ac_prog$ac_exec_ext\"\n      as_fn_executable_p \"$ac_path_GREP\" || continue\n# Check for GNU ac_path_GREP and select it if it is found.\n  # Check for GNU $ac_path_GREP\ncase `\"$ac_path_GREP\" --version 2>&1` in\n*GNU*)\n  ac_cv_path_GREP=\"$ac_path_GREP\" ac_path_GREP_found=:;;\n*)\n  ac_count=0\n  $as_echo_n 0123456789 >\"conftest.in\"\n  while :\n  do\n    cat \"conftest.in\" \"conftest.in\" >\"conftest.tmp\"\n    mv \"conftest.tmp\" \"conftest.in\"\n    cp \"conftest.in\" \"conftest.nl\"\n    $as_echo 'GREP' >> \"conftest.nl\"\n    \"$ac_path_GREP\" -e 'GREP$' -e '-(cannot match)-' < \"conftest.nl\" >\"conftest.out\" 2>/dev/null || break\n    diff \"conftest.out\" \"conftest.nl\" >/dev/null 2>&1 || break\n    as_fn_arith $ac_count + 1 && ac_count=$as_val\n    if test $ac_count -gt ${ac_path_GREP_max-0}; then\n      # Best one so far, save it but keep looking for a better one\n      ac_cv_path_GREP=\"$ac_path_GREP\"\n      ac_path_GREP_max=$ac_count\n    fi\n    # 10*(2^10) chars as input seems more than enough\n    test $ac_count -gt 10 && break\n  done\n  rm -f conftest.in conftest.tmp conftest.nl conftest.out;;\nesac\n\n      $ac_path_GREP_found && break 3\n    done\n  done\n  done\nIFS=$as_save_IFS\n  if test -z \"$ac_cv_path_GREP\"; then\n    as_fn_error $? \"no acceptable grep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin\" \"$LINENO\" 5\n  fi\nelse\n  ac_cv_path_GREP=$GREP\nfi\n\nfi\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_GREP\" >&5\n$as_echo \"$ac_cv_path_GREP\" >&6; }\n GREP=\"$ac_cv_path_GREP\"\n\n\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: checking for egrep\" >&5\n$as_echo_n \"checking for egrep... \" >&6; }\nif ${ac_cv_path_EGREP+:} false; then :\n  $as_echo_n \"(cached) \" >&6\nelse\n  if echo a | $GREP -E '(a|b)' >/dev/null 2>&1\n   then ac_cv_path_EGREP=\"$GREP -E\"\n   else\n     if test -z \"$EGREP\"; then\n  ac_path_EGREP_found=false\n  # Loop through the user's path and test for each of PROGNAME-LIST\n  as_save_IFS=$IFS; IFS=$PATH_SEPARATOR\nfor as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin\ndo\n  IFS=$as_save_IFS\n  test -z \"$as_dir\" && as_dir=.\n    for ac_prog in egrep; do\n    for ac_exec_ext in '' $ac_executable_extensions; do\n      ac_path_EGREP=\"$as_dir/$ac_prog$ac_exec_ext\"\n      as_fn_executable_p \"$ac_path_EGREP\" || continue\n# Check for GNU ac_path_EGREP and select it if it is found.\n  # Check for GNU $ac_path_EGREP\ncase `\"$ac_path_EGREP\" --version 2>&1` in\n*GNU*)\n  ac_cv_path_EGREP=\"$ac_path_EGREP\" ac_path_EGREP_found=:;;\n*)\n  ac_count=0\n  $as_echo_n 0123456789 >\"conftest.in\"\n  while :\n  do\n    cat \"conftest.in\" \"conftest.in\" >\"conftest.tmp\"\n    mv \"conftest.tmp\" \"conftest.in\"\n    cp \"conftest.in\" \"conftest.nl\"\n    $as_echo 'EGREP' >> \"conftest.nl\"\n    \"$ac_path_EGREP\" 'EGREP$' < \"conftest.nl\" >\"conftest.out\" 2>/dev/null || break\n    diff \"conftest.out\" \"conftest.nl\" >/dev/null 2>&1 || break\n    as_fn_arith $ac_count + 1 && ac_count=$as_val\n    if test $ac_count -gt ${ac_path_EGREP_max-0}; then\n      # Best one so far, save it but keep looking for a better one\n      ac_cv_path_EGREP=\"$ac_path_EGREP\"\n      ac_path_EGREP_max=$ac_count\n    fi\n    # 10*(2^10) chars as input seems more than enough\n    test $ac_count -gt 10 && break\n  done\n  rm -f conftest.in conftest.tmp conftest.nl conftest.out;;\nesac\n\n      $ac_path_EGREP_found && break 3\n    done\n  done\n  done\nIFS=$as_save_IFS\n  if test -z \"$ac_cv_path_EGREP\"; then\n    as_fn_error $? \"no acceptable egrep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin\" \"$LINENO\" 5\n  fi\nelse\n  ac_cv_path_EGREP=$EGREP\nfi\n\n   fi\nfi\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_EGREP\" >&5\n$as_echo \"$ac_cv_path_EGREP\" >&6; }\n EGREP=\"$ac_cv_path_EGREP\"\n\n\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: checking for ANSI C header files\" >&5\n$as_echo_n \"checking for ANSI C header files... \" >&6; }\nif ${ac_cv_header_stdc+:} false; then :\n  $as_echo_n \"(cached) \" >&6\nelse\n  cat confdefs.h - <<_ACEOF >conftest.$ac_ext\n/* end confdefs.h.  */\n#include <stdlib.h>\n#include <stdarg.h>\n#include <string.h>\n#include <float.h>\n\nint\nmain ()\n{\n\n  ;\n  return 0;\n}\n_ACEOF\nif ac_fn_c_try_compile \"$LINENO\"; then :\n  ac_cv_header_stdc=yes\nelse\n  ac_cv_header_stdc=no\nfi\nrm -f core conftest.err conftest.$ac_objext conftest.$ac_ext\n\nif test $ac_cv_header_stdc = yes; then\n  # SunOS 4.x string.h does not declare mem*, contrary to ANSI.\n  cat confdefs.h - <<_ACEOF >conftest.$ac_ext\n/* end confdefs.h.  */\n#include <string.h>\n\n_ACEOF\nif (eval \"$ac_cpp conftest.$ac_ext\") 2>&5 |\n  $EGREP \"memchr\" >/dev/null 2>&1; then :\n\nelse\n  ac_cv_header_stdc=no\nfi\nrm -f conftest*\n\nfi\n\nif test $ac_cv_header_stdc = yes; then\n  # ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI.\n  cat confdefs.h - <<_ACEOF >conftest.$ac_ext\n/* end confdefs.h.  */\n#include <stdlib.h>\n\n_ACEOF\nif (eval \"$ac_cpp conftest.$ac_ext\") 2>&5 |\n  $EGREP \"free\" >/dev/null 2>&1; then :\n\nelse\n  ac_cv_header_stdc=no\nfi\nrm -f conftest*\n\nfi\n\nif test $ac_cv_header_stdc = yes; then\n  # /bin/cc in Irix-4.0.5 gets non-ANSI ctype macros unless using -ansi.\n  if test \"$cross_compiling\" = yes; then :\n  :\nelse\n  cat confdefs.h - <<_ACEOF >conftest.$ac_ext\n/* end confdefs.h.  */\n#include <ctype.h>\n#include <stdlib.h>\n#if ((' ' & 0x0FF) == 0x020)\n# define ISLOWER(c) ('a' <= (c) && (c) <= 'z')\n# define TOUPPER(c) (ISLOWER(c) ? 'A' + ((c) - 'a') : (c))\n#else\n# define ISLOWER(c) \\\n\t\t   (('a' <= (c) && (c) <= 'i') \\\n\t\t     || ('j' <= (c) && (c) <= 'r') \\\n\t\t     || ('s' <= (c) && (c) <= 'z'))\n# define TOUPPER(c) (ISLOWER(c) ? ((c) | 0x40) : (c))\n#endif\n\n#define XOR(e, f) (((e) && !(f)) || (!(e) && (f)))\nint\nmain ()\n{\n  int i;\n  for (i = 0; i < 256; i++)\n    if (XOR (islower (i), ISLOWER (i))\n\t|| toupper (i) != TOUPPER (i))\n      return 2;\n  return 0;\n}\n_ACEOF\nif ac_fn_c_try_run \"$LINENO\"; then :\n\nelse\n  ac_cv_header_stdc=no\nfi\nrm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \\\n  conftest.$ac_objext conftest.beam conftest.$ac_ext\nfi\n\nfi\nfi\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: result: $ac_cv_header_stdc\" >&5\n$as_echo \"$ac_cv_header_stdc\" >&6; }\nif test $ac_cv_header_stdc = yes; then\n\n$as_echo \"#define STDC_HEADERS 1\" >>confdefs.h\n\nfi\n\n# On IRIX 5.3, sys/types and inttypes.h are conflicting.\nfor ac_header in sys/types.h sys/stat.h stdlib.h string.h memory.h strings.h \\\n\t\t  inttypes.h stdint.h unistd.h\ndo :\n  as_ac_Header=`$as_echo \"ac_cv_header_$ac_header\" | $as_tr_sh`\nac_fn_c_check_header_compile \"$LINENO\" \"$ac_header\" \"$as_ac_Header\" \"$ac_includes_default\n\"\nif eval test \\\"x\\$\"$as_ac_Header\"\\\" = x\"yes\"; then :\n  cat >>confdefs.h <<_ACEOF\n#define `$as_echo \"HAVE_$ac_header\" | $as_tr_cpp` 1\n_ACEOF\n\nfi\n\ndone\n\n\n { $as_echo \"$as_me:${as_lineno-$LINENO}: checking whether byte ordering is bigendian\" >&5\n$as_echo_n \"checking whether byte ordering is bigendian... \" >&6; }\nif ${ac_cv_c_bigendian+:} false; then :\n  $as_echo_n \"(cached) \" >&6\nelse\n  ac_cv_c_bigendian=unknown\n    # See if we're dealing with a universal compiler.\n    cat confdefs.h - <<_ACEOF >conftest.$ac_ext\n/* end confdefs.h.  */\n#ifndef __APPLE_CC__\n\t       not a universal capable compiler\n\t     #endif\n\t     typedef int dummy;\n\n_ACEOF\nif ac_fn_c_try_compile \"$LINENO\"; then :\n\n\t# Check for potential -arch flags.  It is not universal unless\n\t# there are at least two -arch flags with different values.\n\tac_arch=\n\tac_prev=\n\tfor ac_word in $CC $CFLAGS $CPPFLAGS $LDFLAGS; do\n\t if test -n \"$ac_prev\"; then\n\t   case $ac_word in\n\t     i?86 | x86_64 | ppc | ppc64)\n\t       if test -z \"$ac_arch\" || test \"$ac_arch\" = \"$ac_word\"; then\n\t\t ac_arch=$ac_word\n\t       else\n\t\t ac_cv_c_bigendian=universal\n\t\t break\n\t       fi\n\t       ;;\n\t   esac\n\t   ac_prev=\n\t elif test \"x$ac_word\" = \"x-arch\"; then\n\t   ac_prev=arch\n\t fi\n       done\nfi\nrm -f core conftest.err conftest.$ac_objext conftest.$ac_ext\n    if test $ac_cv_c_bigendian = unknown; then\n      # See if sys/param.h defines the BYTE_ORDER macro.\n      cat confdefs.h - <<_ACEOF >conftest.$ac_ext\n/* end confdefs.h.  */\n#include <sys/types.h>\n\t     #include <sys/param.h>\n\nint\nmain ()\n{\n#if ! (defined BYTE_ORDER && defined BIG_ENDIAN \\\n\t\t     && defined LITTLE_ENDIAN && BYTE_ORDER && BIG_ENDIAN \\\n\t\t     && LITTLE_ENDIAN)\n\t      bogus endian macros\n\t     #endif\n\n  ;\n  return 0;\n}\n_ACEOF\nif ac_fn_c_try_compile \"$LINENO\"; then :\n  # It does; now see whether it defined to BIG_ENDIAN or not.\n\t cat confdefs.h - <<_ACEOF >conftest.$ac_ext\n/* end confdefs.h.  */\n#include <sys/types.h>\n\t\t#include <sys/param.h>\n\nint\nmain ()\n{\n#if BYTE_ORDER != BIG_ENDIAN\n\t\t not big endian\n\t\t#endif\n\n  ;\n  return 0;\n}\n_ACEOF\nif ac_fn_c_try_compile \"$LINENO\"; then :\n  ac_cv_c_bigendian=yes\nelse\n  ac_cv_c_bigendian=no\nfi\nrm -f core conftest.err conftest.$ac_objext conftest.$ac_ext\nfi\nrm -f core conftest.err conftest.$ac_objext conftest.$ac_ext\n    fi\n    if test $ac_cv_c_bigendian = unknown; then\n      # See if <limits.h> defines _LITTLE_ENDIAN or _BIG_ENDIAN (e.g., Solaris).\n      cat confdefs.h - <<_ACEOF >conftest.$ac_ext\n/* end confdefs.h.  */\n#include <limits.h>\n\nint\nmain ()\n{\n#if ! (defined _LITTLE_ENDIAN || defined _BIG_ENDIAN)\n\t      bogus endian macros\n\t     #endif\n\n  ;\n  return 0;\n}\n_ACEOF\nif ac_fn_c_try_compile \"$LINENO\"; then :\n  # It does; now see whether it defined to _BIG_ENDIAN or not.\n\t cat confdefs.h - <<_ACEOF >conftest.$ac_ext\n/* end confdefs.h.  */\n#include <limits.h>\n\nint\nmain ()\n{\n#ifndef _BIG_ENDIAN\n\t\t not big endian\n\t\t#endif\n\n  ;\n  return 0;\n}\n_ACEOF\nif ac_fn_c_try_compile \"$LINENO\"; then :\n  ac_cv_c_bigendian=yes\nelse\n  ac_cv_c_bigendian=no\nfi\nrm -f core conftest.err conftest.$ac_objext conftest.$ac_ext\nfi\nrm -f core conftest.err conftest.$ac_objext conftest.$ac_ext\n    fi\n    if test $ac_cv_c_bigendian = unknown; then\n      # Compile a test program.\n      if test \"$cross_compiling\" = yes; then :\n  # Try to guess by grepping values from an object file.\n\t cat confdefs.h - <<_ACEOF >conftest.$ac_ext\n/* end confdefs.h.  */\nshort int ascii_mm[] =\n\t\t  { 0x4249, 0x4765, 0x6E44, 0x6961, 0x6E53, 0x7953, 0 };\n\t\tshort int ascii_ii[] =\n\t\t  { 0x694C, 0x5454, 0x656C, 0x6E45, 0x6944, 0x6E61, 0 };\n\t\tint use_ascii (int i) {\n\t\t  return ascii_mm[i] + ascii_ii[i];\n\t\t}\n\t\tshort int ebcdic_ii[] =\n\t\t  { 0x89D3, 0xE3E3, 0x8593, 0x95C5, 0x89C4, 0x9581, 0 };\n\t\tshort int ebcdic_mm[] =\n\t\t  { 0xC2C9, 0xC785, 0x95C4, 0x8981, 0x95E2, 0xA8E2, 0 };\n\t\tint use_ebcdic (int i) {\n\t\t  return ebcdic_mm[i] + ebcdic_ii[i];\n\t\t}\n\t\textern int foo;\n\nint\nmain ()\n{\nreturn use_ascii (foo) == use_ebcdic (foo);\n  ;\n  return 0;\n}\n_ACEOF\nif ac_fn_c_try_compile \"$LINENO\"; then :\n  if grep BIGenDianSyS conftest.$ac_objext >/dev/null; then\n\t      ac_cv_c_bigendian=yes\n\t    fi\n\t    if grep LiTTleEnDian conftest.$ac_objext >/dev/null ; then\n\t      if test \"$ac_cv_c_bigendian\" = unknown; then\n\t\tac_cv_c_bigendian=no\n\t      else\n\t\t# finding both strings is unlikely to happen, but who knows?\n\t\tac_cv_c_bigendian=unknown\n\t      fi\n\t    fi\nfi\nrm -f core conftest.err conftest.$ac_objext conftest.$ac_ext\nelse\n  cat confdefs.h - <<_ACEOF >conftest.$ac_ext\n/* end confdefs.h.  */\n$ac_includes_default\nint\nmain ()\n{\n\n\t     /* Are we little or big endian?  From Harbison&Steele.  */\n\t     union\n\t     {\n\t       long int l;\n\t       char c[sizeof (long int)];\n\t     } u;\n\t     u.l = 1;\n\t     return u.c[sizeof (long int) - 1] == 1;\n\n  ;\n  return 0;\n}\n_ACEOF\nif ac_fn_c_try_run \"$LINENO\"; then :\n  ac_cv_c_bigendian=no\nelse\n  ac_cv_c_bigendian=yes\nfi\nrm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \\\n  conftest.$ac_objext conftest.beam conftest.$ac_ext\nfi\n\n    fi\nfi\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_bigendian\" >&5\n$as_echo \"$ac_cv_c_bigendian\" >&6; }\n case $ac_cv_c_bigendian in #(\n   yes)\n     ac_cv_big_endian=1;; #(\n   no)\n     ac_cv_big_endian=0 ;; #(\n   universal)\n\n$as_echo \"#define AC_APPLE_UNIVERSAL_BUILD 1\" >>confdefs.h\n\n     ;; #(\n   *)\n     as_fn_error $? \"unknown endianness\n presetting ac_cv_c_bigendian=no (or yes) will help\" \"$LINENO\" 5 ;;\n esac\n\nif test \"x${ac_cv_big_endian}\" = \"x1\" ; then\n  cat >>confdefs.h <<_ACEOF\n#define JEMALLOC_BIG_ENDIAN\n_ACEOF\n\nfi\n\nif test \"x${je_cv_msvc}\" = \"xyes\" -a \"x${ac_cv_header_inttypes_h}\" = \"xno\"; then\n  CPPFLAGS=\"$CPPFLAGS -I${srcdir}/include/msvc_compat/C99\"\nfi\n\n# The cast to long int works around a bug in the HP C Compiler\n# version HP92453-01 B.11.11.23709.GP, which incorrectly rejects\n# declarations like `int a3[[(sizeof (unsigned char)) >= 0]];'.\n# This bug is HP SR number 8606223364.\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: checking size of void *\" >&5\n$as_echo_n \"checking size of void *... \" >&6; }\nif ${ac_cv_sizeof_void_p+:} false; then :\n  $as_echo_n \"(cached) \" >&6\nelse\n  if ac_fn_c_compute_int \"$LINENO\" \"(long int) (sizeof (void *))\" \"ac_cv_sizeof_void_p\"        \"$ac_includes_default\"; then :\n\nelse\n  if test \"$ac_cv_type_void_p\" = yes; then\n     { { $as_echo \"$as_me:${as_lineno-$LINENO}: error: in \\`$ac_pwd':\" >&5\n$as_echo \"$as_me: error: in \\`$ac_pwd':\" >&2;}\nas_fn_error 77 \"cannot compute sizeof (void *)\nSee \\`config.log' for more details\" \"$LINENO\" 5; }\n   else\n     ac_cv_sizeof_void_p=0\n   fi\nfi\n\nfi\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: result: $ac_cv_sizeof_void_p\" >&5\n$as_echo \"$ac_cv_sizeof_void_p\" >&6; }\n\n\n\ncat >>confdefs.h <<_ACEOF\n#define SIZEOF_VOID_P $ac_cv_sizeof_void_p\n_ACEOF\n\n\nif test \"x${ac_cv_sizeof_void_p}\" = \"x8\" ; then\n  LG_SIZEOF_PTR=3\nelif test \"x${ac_cv_sizeof_void_p}\" = \"x4\" ; then\n  LG_SIZEOF_PTR=2\nelse\n  as_fn_error $? \"Unsupported pointer size: ${ac_cv_sizeof_void_p}\" \"$LINENO\" 5\nfi\ncat >>confdefs.h <<_ACEOF\n#define LG_SIZEOF_PTR $LG_SIZEOF_PTR\n_ACEOF\n\n\n# The cast to long int works around a bug in the HP C Compiler\n# version HP92453-01 B.11.11.23709.GP, which incorrectly rejects\n# declarations like `int a3[[(sizeof (unsigned char)) >= 0]];'.\n# This bug is HP SR number 8606223364.\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: checking size of int\" >&5\n$as_echo_n \"checking size of int... \" >&6; }\nif ${ac_cv_sizeof_int+:} false; then :\n  $as_echo_n \"(cached) \" >&6\nelse\n  if ac_fn_c_compute_int \"$LINENO\" \"(long int) (sizeof (int))\" \"ac_cv_sizeof_int\"        \"$ac_includes_default\"; then :\n\nelse\n  if test \"$ac_cv_type_int\" = yes; then\n     { { $as_echo \"$as_me:${as_lineno-$LINENO}: error: in \\`$ac_pwd':\" >&5\n$as_echo \"$as_me: error: in \\`$ac_pwd':\" >&2;}\nas_fn_error 77 \"cannot compute sizeof (int)\nSee \\`config.log' for more details\" \"$LINENO\" 5; }\n   else\n     ac_cv_sizeof_int=0\n   fi\nfi\n\nfi\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: result: $ac_cv_sizeof_int\" >&5\n$as_echo \"$ac_cv_sizeof_int\" >&6; }\n\n\n\ncat >>confdefs.h <<_ACEOF\n#define SIZEOF_INT $ac_cv_sizeof_int\n_ACEOF\n\n\nif test \"x${ac_cv_sizeof_int}\" = \"x8\" ; then\n  LG_SIZEOF_INT=3\nelif test \"x${ac_cv_sizeof_int}\" = \"x4\" ; then\n  LG_SIZEOF_INT=2\nelse\n  as_fn_error $? \"Unsupported int size: ${ac_cv_sizeof_int}\" \"$LINENO\" 5\nfi\ncat >>confdefs.h <<_ACEOF\n#define LG_SIZEOF_INT $LG_SIZEOF_INT\n_ACEOF\n\n\n# The cast to long int works around a bug in the HP C Compiler\n# version HP92453-01 B.11.11.23709.GP, which incorrectly rejects\n# declarations like `int a3[[(sizeof (unsigned char)) >= 0]];'.\n# This bug is HP SR number 8606223364.\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: checking size of long\" >&5\n$as_echo_n \"checking size of long... \" >&6; }\nif ${ac_cv_sizeof_long+:} false; then :\n  $as_echo_n \"(cached) \" >&6\nelse\n  if ac_fn_c_compute_int \"$LINENO\" \"(long int) (sizeof (long))\" \"ac_cv_sizeof_long\"        \"$ac_includes_default\"; then :\n\nelse\n  if test \"$ac_cv_type_long\" = yes; then\n     { { $as_echo \"$as_me:${as_lineno-$LINENO}: error: in \\`$ac_pwd':\" >&5\n$as_echo \"$as_me: error: in \\`$ac_pwd':\" >&2;}\nas_fn_error 77 \"cannot compute sizeof (long)\nSee \\`config.log' for more details\" \"$LINENO\" 5; }\n   else\n     ac_cv_sizeof_long=0\n   fi\nfi\n\nfi\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: result: $ac_cv_sizeof_long\" >&5\n$as_echo \"$ac_cv_sizeof_long\" >&6; }\n\n\n\ncat >>confdefs.h <<_ACEOF\n#define SIZEOF_LONG $ac_cv_sizeof_long\n_ACEOF\n\n\nif test \"x${ac_cv_sizeof_long}\" = \"x8\" ; then\n  LG_SIZEOF_LONG=3\nelif test \"x${ac_cv_sizeof_long}\" = \"x4\" ; then\n  LG_SIZEOF_LONG=2\nelse\n  as_fn_error $? \"Unsupported long size: ${ac_cv_sizeof_long}\" \"$LINENO\" 5\nfi\ncat >>confdefs.h <<_ACEOF\n#define LG_SIZEOF_LONG $LG_SIZEOF_LONG\n_ACEOF\n\n\n# The cast to long int works around a bug in the HP C Compiler\n# version HP92453-01 B.11.11.23709.GP, which incorrectly rejects\n# declarations like `int a3[[(sizeof (unsigned char)) >= 0]];'.\n# This bug is HP SR number 8606223364.\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: checking size of intmax_t\" >&5\n$as_echo_n \"checking size of intmax_t... \" >&6; }\nif ${ac_cv_sizeof_intmax_t+:} false; then :\n  $as_echo_n \"(cached) \" >&6\nelse\n  if ac_fn_c_compute_int \"$LINENO\" \"(long int) (sizeof (intmax_t))\" \"ac_cv_sizeof_intmax_t\"        \"$ac_includes_default\"; then :\n\nelse\n  if test \"$ac_cv_type_intmax_t\" = yes; then\n     { { $as_echo \"$as_me:${as_lineno-$LINENO}: error: in \\`$ac_pwd':\" >&5\n$as_echo \"$as_me: error: in \\`$ac_pwd':\" >&2;}\nas_fn_error 77 \"cannot compute sizeof (intmax_t)\nSee \\`config.log' for more details\" \"$LINENO\" 5; }\n   else\n     ac_cv_sizeof_intmax_t=0\n   fi\nfi\n\nfi\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: result: $ac_cv_sizeof_intmax_t\" >&5\n$as_echo \"$ac_cv_sizeof_intmax_t\" >&6; }\n\n\n\ncat >>confdefs.h <<_ACEOF\n#define SIZEOF_INTMAX_T $ac_cv_sizeof_intmax_t\n_ACEOF\n\n\nif test \"x${ac_cv_sizeof_intmax_t}\" = \"x16\" ; then\n  LG_SIZEOF_INTMAX_T=4\nelif test \"x${ac_cv_sizeof_intmax_t}\" = \"x8\" ; then\n  LG_SIZEOF_INTMAX_T=3\nelif test \"x${ac_cv_sizeof_intmax_t}\" = \"x4\" ; then\n  LG_SIZEOF_INTMAX_T=2\nelse\n  as_fn_error $? \"Unsupported intmax_t size: ${ac_cv_sizeof_intmax_t}\" \"$LINENO\" 5\nfi\ncat >>confdefs.h <<_ACEOF\n#define LG_SIZEOF_INTMAX_T $LG_SIZEOF_INTMAX_T\n_ACEOF\n\n\nac_aux_dir=\nfor ac_dir in \"$srcdir\" \"$srcdir/..\" \"$srcdir/../..\"; do\n  if test -f \"$ac_dir/install-sh\"; then\n    ac_aux_dir=$ac_dir\n    ac_install_sh=\"$ac_aux_dir/install-sh -c\"\n    break\n  elif test -f \"$ac_dir/install.sh\"; then\n    ac_aux_dir=$ac_dir\n    ac_install_sh=\"$ac_aux_dir/install.sh -c\"\n    break\n  elif test -f \"$ac_dir/shtool\"; then\n    ac_aux_dir=$ac_dir\n    ac_install_sh=\"$ac_aux_dir/shtool install -c\"\n    break\n  fi\ndone\nif test -z \"$ac_aux_dir\"; then\n  as_fn_error $? \"cannot find install-sh, install.sh, or shtool in \\\"$srcdir\\\" \\\"$srcdir/..\\\" \\\"$srcdir/../..\\\"\" \"$LINENO\" 5\nfi\n\n# These three variables are undocumented and unsupported,\n# and are intended to be withdrawn in a future Autoconf release.\n# They can cause serious problems if a builder's source tree is in a directory\n# whose full name contains unusual characters.\nac_config_guess=\"$SHELL $ac_aux_dir/config.guess\"  # Please don't use this var.\nac_config_sub=\"$SHELL $ac_aux_dir/config.sub\"  # Please don't use this var.\nac_configure=\"$SHELL $ac_aux_dir/configure\"  # Please don't use this var.\n\n\n# Make sure we can run config.sub.\n$SHELL \"$ac_aux_dir/config.sub\" sun4 >/dev/null 2>&1 ||\n  as_fn_error $? \"cannot run $SHELL $ac_aux_dir/config.sub\" \"$LINENO\" 5\n\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: checking build system type\" >&5\n$as_echo_n \"checking build system type... \" >&6; }\nif ${ac_cv_build+:} false; then :\n  $as_echo_n \"(cached) \" >&6\nelse\n  ac_build_alias=$build_alias\ntest \"x$ac_build_alias\" = x &&\n  ac_build_alias=`$SHELL \"$ac_aux_dir/config.guess\"`\ntest \"x$ac_build_alias\" = x &&\n  as_fn_error $? \"cannot guess build type; you must specify one\" \"$LINENO\" 5\nac_cv_build=`$SHELL \"$ac_aux_dir/config.sub\" $ac_build_alias` ||\n  as_fn_error $? \"$SHELL $ac_aux_dir/config.sub $ac_build_alias failed\" \"$LINENO\" 5\n\nfi\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: result: $ac_cv_build\" >&5\n$as_echo \"$ac_cv_build\" >&6; }\ncase $ac_cv_build in\n*-*-*) ;;\n*) as_fn_error $? \"invalid value of canonical build\" \"$LINENO\" 5;;\nesac\nbuild=$ac_cv_build\nac_save_IFS=$IFS; IFS='-'\nset x $ac_cv_build\nshift\nbuild_cpu=$1\nbuild_vendor=$2\nshift; shift\n# Remember, the first character of IFS is used to create $*,\n# except with old shells:\nbuild_os=$*\nIFS=$ac_save_IFS\ncase $build_os in *\\ *) build_os=`echo \"$build_os\" | sed 's/ /-/g'`;; esac\n\n\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: checking host system type\" >&5\n$as_echo_n \"checking host system type... \" >&6; }\nif ${ac_cv_host+:} false; then :\n  $as_echo_n \"(cached) \" >&6\nelse\n  if test \"x$host_alias\" = x; then\n  ac_cv_host=$ac_cv_build\nelse\n  ac_cv_host=`$SHELL \"$ac_aux_dir/config.sub\" $host_alias` ||\n    as_fn_error $? \"$SHELL $ac_aux_dir/config.sub $host_alias failed\" \"$LINENO\" 5\nfi\n\nfi\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: result: $ac_cv_host\" >&5\n$as_echo \"$ac_cv_host\" >&6; }\ncase $ac_cv_host in\n*-*-*) ;;\n*) as_fn_error $? \"invalid value of canonical host\" \"$LINENO\" 5;;\nesac\nhost=$ac_cv_host\nac_save_IFS=$IFS; IFS='-'\nset x $ac_cv_host\nshift\nhost_cpu=$1\nhost_vendor=$2\nshift; shift\n# Remember, the first character of IFS is used to create $*,\n# except with old shells:\nhost_os=$*\nIFS=$ac_save_IFS\ncase $host_os in *\\ *) host_os=`echo \"$host_os\" | sed 's/ /-/g'`;; esac\n\n\nCPU_SPINWAIT=\"\"\ncase \"${host_cpu}\" in\n  i686|x86_64)\n\tif ${je_cv_pause+:} false; then :\n  $as_echo_n \"(cached) \" >&6\nelse\n\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: checking whether pause instruction is compilable\" >&5\n$as_echo_n \"checking whether pause instruction is compilable... \" >&6; }\nif ${je_cv_pause+:} false; then :\n  $as_echo_n \"(cached) \" >&6\nelse\n  cat confdefs.h - <<_ACEOF >conftest.$ac_ext\n/* end confdefs.h.  */\n\nint\nmain ()\n{\n__asm__ volatile(\"pause\"); return 0;\n  ;\n  return 0;\n}\n_ACEOF\nif ac_fn_c_try_link \"$LINENO\"; then :\n  je_cv_pause=yes\nelse\n  je_cv_pause=no\nfi\nrm -f core conftest.err conftest.$ac_objext \\\n    conftest$ac_exeext conftest.$ac_ext\nfi\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: result: $je_cv_pause\" >&5\n$as_echo \"$je_cv_pause\" >&6; }\n\nfi\n\n\tif test \"x${je_cv_pause}\" = \"xyes\" ; then\n\t    CPU_SPINWAIT='__asm__ volatile(\"pause\")'\n\tfi\n\t;;\n  powerpc)\n\tcat >>confdefs.h <<_ACEOF\n#define HAVE_ALTIVEC\n_ACEOF\n\n\t;;\n  *)\n\t;;\nesac\ncat >>confdefs.h <<_ACEOF\n#define CPU_SPINWAIT $CPU_SPINWAIT\n_ACEOF\n\n\nLD_PRELOAD_VAR=\"LD_PRELOAD\"\nso=\"so\"\nimportlib=\"${so}\"\no=\"$ac_objext\"\na=\"a\"\nexe=\"$ac_exeext\"\nlibprefix=\"lib\"\nDSO_LDFLAGS='-shared -Wl,-soname,$(@F)'\nRPATH='-Wl,-rpath,$(1)'\nSOREV=\"${so}.${rev}\"\nPIC_CFLAGS='-fPIC -DPIC'\nCTARGET='-o $@'\nLDTARGET='-o $@'\nEXTRA_LDFLAGS=\nARFLAGS='crus'\nAROUT=' $@'\nCC_MM=1\n\n\n\n\nif test -n \"$ac_tool_prefix\"; then\n  # Extract the first word of \"${ac_tool_prefix}ar\", so it can be a program name with args.\nset dummy ${ac_tool_prefix}ar; ac_word=$2\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: checking for $ac_word\" >&5\n$as_echo_n \"checking for $ac_word... \" >&6; }\nif ${ac_cv_prog_AR+:} false; then :\n  $as_echo_n \"(cached) \" >&6\nelse\n  if test -n \"$AR\"; then\n  ac_cv_prog_AR=\"$AR\" # Let the user override the test.\nelse\nas_save_IFS=$IFS; IFS=$PATH_SEPARATOR\nfor as_dir in $PATH\ndo\n  IFS=$as_save_IFS\n  test -z \"$as_dir\" && as_dir=.\n    for ac_exec_ext in '' $ac_executable_extensions; do\n  if as_fn_executable_p \"$as_dir/$ac_word$ac_exec_ext\"; then\n    ac_cv_prog_AR=\"${ac_tool_prefix}ar\"\n    $as_echo \"$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext\" >&5\n    break 2\n  fi\ndone\n  done\nIFS=$as_save_IFS\n\nfi\nfi\nAR=$ac_cv_prog_AR\nif test -n \"$AR\"; then\n  { $as_echo \"$as_me:${as_lineno-$LINENO}: result: $AR\" >&5\n$as_echo \"$AR\" >&6; }\nelse\n  { $as_echo \"$as_me:${as_lineno-$LINENO}: result: no\" >&5\n$as_echo \"no\" >&6; }\nfi\n\n\nfi\nif test -z \"$ac_cv_prog_AR\"; then\n  ac_ct_AR=$AR\n  # Extract the first word of \"ar\", so it can be a program name with args.\nset dummy ar; ac_word=$2\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: checking for $ac_word\" >&5\n$as_echo_n \"checking for $ac_word... \" >&6; }\nif ${ac_cv_prog_ac_ct_AR+:} false; then :\n  $as_echo_n \"(cached) \" >&6\nelse\n  if test -n \"$ac_ct_AR\"; then\n  ac_cv_prog_ac_ct_AR=\"$ac_ct_AR\" # Let the user override the test.\nelse\nas_save_IFS=$IFS; IFS=$PATH_SEPARATOR\nfor as_dir in $PATH\ndo\n  IFS=$as_save_IFS\n  test -z \"$as_dir\" && as_dir=.\n    for ac_exec_ext in '' $ac_executable_extensions; do\n  if as_fn_executable_p \"$as_dir/$ac_word$ac_exec_ext\"; then\n    ac_cv_prog_ac_ct_AR=\"ar\"\n    $as_echo \"$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext\" >&5\n    break 2\n  fi\ndone\n  done\nIFS=$as_save_IFS\n\nfi\nfi\nac_ct_AR=$ac_cv_prog_ac_ct_AR\nif test -n \"$ac_ct_AR\"; then\n  { $as_echo \"$as_me:${as_lineno-$LINENO}: result: $ac_ct_AR\" >&5\n$as_echo \"$ac_ct_AR\" >&6; }\nelse\n  { $as_echo \"$as_me:${as_lineno-$LINENO}: result: no\" >&5\n$as_echo \"no\" >&6; }\nfi\n\n  if test \"x$ac_ct_AR\" = x; then\n    AR=\":\"\n  else\n    case $cross_compiling:$ac_tool_warned in\nyes:)\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet\" >&5\n$as_echo \"$as_me: WARNING: using cross tools not prefixed with host triplet\" >&2;}\nac_tool_warned=yes ;;\nesac\n    AR=$ac_ct_AR\n  fi\nelse\n  AR=\"$ac_cv_prog_AR\"\nfi\n\n\ndefault_munmap=\"1\"\nmaps_coalesce=\"1\"\ncase \"${host}\" in\n  *-*-darwin* | *-*-ios*)\n\tCFLAGS=\"$CFLAGS\"\n\tabi=\"macho\"\n\t$as_echo \"#define JEMALLOC_PURGE_MADVISE_FREE  \" >>confdefs.h\n\n\tRPATH=\"\"\n\tLD_PRELOAD_VAR=\"DYLD_INSERT_LIBRARIES\"\n\tso=\"dylib\"\n\timportlib=\"${so}\"\n\tforce_tls=\"0\"\n\tDSO_LDFLAGS='-shared -Wl,-install_name,$(LIBDIR)/$(@F)'\n\tSOREV=\"${rev}.${so}\"\n\tsbrk_deprecated=\"1\"\n\t;;\n  *-*-freebsd*)\n\tCFLAGS=\"$CFLAGS\"\n\tabi=\"elf\"\n\t$as_echo \"#define JEMALLOC_PURGE_MADVISE_FREE  \" >>confdefs.h\n\n\tforce_lazy_lock=\"1\"\n\t;;\n  *-*-dragonfly*)\n\tCFLAGS=\"$CFLAGS\"\n\tabi=\"elf\"\n\t$as_echo \"#define JEMALLOC_PURGE_MADVISE_FREE  \" >>confdefs.h\n\n\t;;\n  *-*-openbsd*)\n\tCFLAGS=\"$CFLAGS\"\n\tabi=\"elf\"\n\t$as_echo \"#define JEMALLOC_PURGE_MADVISE_FREE  \" >>confdefs.h\n\n\tforce_tls=\"0\"\n\t;;\n  *-*-bitrig*)\n\tCFLAGS=\"$CFLAGS\"\n\tabi=\"elf\"\n\t$as_echo \"#define JEMALLOC_PURGE_MADVISE_FREE  \" >>confdefs.h\n\n\t;;\n  *-*-linux*)\n\tCFLAGS=\"$CFLAGS\"\n\tCPPFLAGS=\"$CPPFLAGS -D_GNU_SOURCE\"\n\tabi=\"elf\"\n\t$as_echo \"#define JEMALLOC_HAS_ALLOCA_H 1\" >>confdefs.h\n\n\t$as_echo \"#define JEMALLOC_PURGE_MADVISE_DONTNEED  \" >>confdefs.h\n\n\t$as_echo \"#define JEMALLOC_THREADED_INIT  \" >>confdefs.h\n\n\t$as_echo \"#define JEMALLOC_USE_CXX_THROW  \" >>confdefs.h\n\n\tdefault_munmap=\"0\"\n\t;;\n  *-*-netbsd*)\n\t{ $as_echo \"$as_me:${as_lineno-$LINENO}: checking ABI\" >&5\n$as_echo_n \"checking ABI... \" >&6; }\n        cat confdefs.h - <<_ACEOF >conftest.$ac_ext\n/* end confdefs.h.  */\n#ifdef __ELF__\n/* ELF */\n#else\n#error aout\n#endif\n\nint\nmain ()\n{\n\n  ;\n  return 0;\n}\n_ACEOF\nif ac_fn_c_try_compile \"$LINENO\"; then :\n  CFLAGS=\"$CFLAGS\"; abi=\"elf\"\nelse\n  abi=\"aout\"\nfi\nrm -f core conftest.err conftest.$ac_objext conftest.$ac_ext\n\t{ $as_echo \"$as_me:${as_lineno-$LINENO}: result: $abi\" >&5\n$as_echo \"$abi\" >&6; }\n\t$as_echo \"#define JEMALLOC_PURGE_MADVISE_FREE  \" >>confdefs.h\n\n\t;;\n  *-*-solaris2*)\n\tCFLAGS=\"$CFLAGS\"\n\tabi=\"elf\"\n\t$as_echo \"#define JEMALLOC_PURGE_MADVISE_FREE  \" >>confdefs.h\n\n\tRPATH='-Wl,-R,$(1)'\n\t\tCPPFLAGS=\"$CPPFLAGS -D_POSIX_PTHREAD_SEMANTICS\"\n\tLIBS=\"$LIBS -lposix4 -lsocket -lnsl\"\n\t;;\n  *-ibm-aix*)\n\tif \"$LG_SIZEOF_PTR\" = \"8\"; then\n\t  \t  LD_PRELOAD_VAR=\"LDR_PRELOAD64\"\n\telse\n\t  \t  LD_PRELOAD_VAR=\"LDR_PRELOAD\"\n\tfi\n\tabi=\"xcoff\"\n\t;;\n  *-*-mingw* | *-*-cygwin*)\n\tabi=\"pecoff\"\n\tforce_tls=\"0\"\n\tforce_lazy_lock=\"1\"\n\tmaps_coalesce=\"0\"\n\tRPATH=\"\"\n\tso=\"dll\"\n\tif test \"x$je_cv_msvc\" = \"xyes\" ; then\n\t  importlib=\"lib\"\n\t  DSO_LDFLAGS=\"-LD\"\n\t  EXTRA_LDFLAGS=\"-link -DEBUG\"\n\t  CTARGET='-Fo$@'\n\t  LDTARGET='-Fe$@'\n\t  AR='lib'\n\t  ARFLAGS='-nologo -out:'\n\t  AROUT='$@'\n\t  CC_MM=\n        else\n\t  importlib=\"${so}\"\n\t  DSO_LDFLAGS=\"-shared\"\n\tfi\n\ta=\"lib\"\n\tlibprefix=\"\"\n\tSOREV=\"${so}\"\n\tPIC_CFLAGS=\"\"\n\t;;\n  *)\n\t{ $as_echo \"$as_me:${as_lineno-$LINENO}: result: Unsupported operating system: ${host}\" >&5\n$as_echo \"Unsupported operating system: ${host}\" >&6; }\n\tabi=\"elf\"\n\t;;\nesac\n\nJEMALLOC_USABLE_SIZE_CONST=const\nfor ac_header in malloc.h\ndo :\n  ac_fn_c_check_header_mongrel \"$LINENO\" \"malloc.h\" \"ac_cv_header_malloc_h\" \"$ac_includes_default\"\nif test \"x$ac_cv_header_malloc_h\" = xyes; then :\n  cat >>confdefs.h <<_ACEOF\n#define HAVE_MALLOC_H 1\n_ACEOF\n\n  { $as_echo \"$as_me:${as_lineno-$LINENO}: checking whether malloc_usable_size definition can use const argument\" >&5\n$as_echo_n \"checking whether malloc_usable_size definition can use const argument... \" >&6; }\n  cat confdefs.h - <<_ACEOF >conftest.$ac_ext\n/* end confdefs.h.  */\n#include <malloc.h>\n     #include <stddef.h>\n    size_t malloc_usable_size(const void *ptr);\n\nint\nmain ()\n{\n\n  ;\n  return 0;\n}\n_ACEOF\nif ac_fn_c_try_compile \"$LINENO\"; then :\n\n                { $as_echo \"$as_me:${as_lineno-$LINENO}: result: yes\" >&5\n$as_echo \"yes\" >&6; }\n\nelse\n\n                JEMALLOC_USABLE_SIZE_CONST=\n                { $as_echo \"$as_me:${as_lineno-$LINENO}: result: no\" >&5\n$as_echo \"no\" >&6; }\n\nfi\nrm -f core conftest.err conftest.$ac_objext conftest.$ac_ext\n\nfi\n\ndone\n\ncat >>confdefs.h <<_ACEOF\n#define JEMALLOC_USABLE_SIZE_CONST $JEMALLOC_USABLE_SIZE_CONST\n_ACEOF\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: checking whether __attribute__ syntax is compilable\" >&5\n$as_echo_n \"checking whether __attribute__ syntax is compilable... \" >&6; }\nif ${je_cv_attribute+:} false; then :\n  $as_echo_n \"(cached) \" >&6\nelse\n  cat confdefs.h - <<_ACEOF >conftest.$ac_ext\n/* end confdefs.h.  */\nstatic __attribute__((unused)) void foo(void){}\nint\nmain ()\n{\n\n  ;\n  return 0;\n}\n_ACEOF\nif ac_fn_c_try_link \"$LINENO\"; then :\n  je_cv_attribute=yes\nelse\n  je_cv_attribute=no\nfi\nrm -f core conftest.err conftest.$ac_objext \\\n    conftest$ac_exeext conftest.$ac_ext\nfi\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: result: $je_cv_attribute\" >&5\n$as_echo \"$je_cv_attribute\" >&6; }\n\nif test \"x${je_cv_attribute}\" = \"xyes\" ; then\n  $as_echo \"#define JEMALLOC_HAVE_ATTR  \" >>confdefs.h\n\n  if test \"x${GCC}\" = \"xyes\" -a \"x${abi}\" = \"xelf\"; then\n\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: checking whether compiler supports -fvisibility=hidden\" >&5\n$as_echo_n \"checking whether compiler supports -fvisibility=hidden... \" >&6; }\nTCFLAGS=\"${CFLAGS}\"\nif test \"x${CFLAGS}\" = \"x\" ; then\n  CFLAGS=\"-fvisibility=hidden\"\nelse\n  CFLAGS=\"${CFLAGS} -fvisibility=hidden\"\nfi\ncat confdefs.h - <<_ACEOF >conftest.$ac_ext\n/* end confdefs.h.  */\n\n\nint\nmain ()\n{\n\n    return 0;\n\n  ;\n  return 0;\n}\n_ACEOF\nif ac_fn_c_try_compile \"$LINENO\"; then :\n  je_cv_cflags_appended=-fvisibility=hidden\n              { $as_echo \"$as_me:${as_lineno-$LINENO}: result: yes\" >&5\n$as_echo \"yes\" >&6; }\nelse\n  je_cv_cflags_appended=\n              { $as_echo \"$as_me:${as_lineno-$LINENO}: result: no\" >&5\n$as_echo \"no\" >&6; }\n              CFLAGS=\"${TCFLAGS}\"\n\nfi\nrm -f core conftest.err conftest.$ac_objext conftest.$ac_ext\n\n  fi\nfi\nSAVED_CFLAGS=\"${CFLAGS}\"\n\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: checking whether compiler supports -Werror\" >&5\n$as_echo_n \"checking whether compiler supports -Werror... \" >&6; }\nTCFLAGS=\"${CFLAGS}\"\nif test \"x${CFLAGS}\" = \"x\" ; then\n  CFLAGS=\"-Werror\"\nelse\n  CFLAGS=\"${CFLAGS} -Werror\"\nfi\ncat confdefs.h - <<_ACEOF >conftest.$ac_ext\n/* end confdefs.h.  */\n\n\nint\nmain ()\n{\n\n    return 0;\n\n  ;\n  return 0;\n}\n_ACEOF\nif ac_fn_c_try_compile \"$LINENO\"; then :\n  je_cv_cflags_appended=-Werror\n              { $as_echo \"$as_me:${as_lineno-$LINENO}: result: yes\" >&5\n$as_echo \"yes\" >&6; }\nelse\n  je_cv_cflags_appended=\n              { $as_echo \"$as_me:${as_lineno-$LINENO}: result: no\" >&5\n$as_echo \"no\" >&6; }\n              CFLAGS=\"${TCFLAGS}\"\n\nfi\nrm -f core conftest.err conftest.$ac_objext conftest.$ac_ext\n\n\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: checking whether tls_model attribute is compilable\" >&5\n$as_echo_n \"checking whether tls_model attribute is compilable... \" >&6; }\nif ${je_cv_tls_model+:} false; then :\n  $as_echo_n \"(cached) \" >&6\nelse\n  cat confdefs.h - <<_ACEOF >conftest.$ac_ext\n/* end confdefs.h.  */\n\nint\nmain ()\n{\nstatic __thread int\n               __attribute__((tls_model(\"initial-exec\"), unused)) foo;\n               foo = 0;\n  ;\n  return 0;\n}\n_ACEOF\nif ac_fn_c_try_link \"$LINENO\"; then :\n  je_cv_tls_model=yes\nelse\n  je_cv_tls_model=no\nfi\nrm -f core conftest.err conftest.$ac_objext \\\n    conftest$ac_exeext conftest.$ac_ext\nfi\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: result: $je_cv_tls_model\" >&5\n$as_echo \"$je_cv_tls_model\" >&6; }\n\nCFLAGS=\"${SAVED_CFLAGS}\"\nif test \"x${je_cv_tls_model}\" = \"xyes\" ; then\n  $as_echo \"#define JEMALLOC_TLS_MODEL __attribute__((tls_model(\\\"initial-exec\\\")))\" >>confdefs.h\n\nelse\n  $as_echo \"#define JEMALLOC_TLS_MODEL  \" >>confdefs.h\n\nfi\nSAVED_CFLAGS=\"${CFLAGS}\"\n\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: checking whether compiler supports -Werror\" >&5\n$as_echo_n \"checking whether compiler supports -Werror... \" >&6; }\nTCFLAGS=\"${CFLAGS}\"\nif test \"x${CFLAGS}\" = \"x\" ; then\n  CFLAGS=\"-Werror\"\nelse\n  CFLAGS=\"${CFLAGS} -Werror\"\nfi\ncat confdefs.h - <<_ACEOF >conftest.$ac_ext\n/* end confdefs.h.  */\n\n\nint\nmain ()\n{\n\n    return 0;\n\n  ;\n  return 0;\n}\n_ACEOF\nif ac_fn_c_try_compile \"$LINENO\"; then :\n  je_cv_cflags_appended=-Werror\n              { $as_echo \"$as_me:${as_lineno-$LINENO}: result: yes\" >&5\n$as_echo \"yes\" >&6; }\nelse\n  je_cv_cflags_appended=\n              { $as_echo \"$as_me:${as_lineno-$LINENO}: result: no\" >&5\n$as_echo \"no\" >&6; }\n              CFLAGS=\"${TCFLAGS}\"\n\nfi\nrm -f core conftest.err conftest.$ac_objext conftest.$ac_ext\n\n\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: checking whether alloc_size attribute is compilable\" >&5\n$as_echo_n \"checking whether alloc_size attribute is compilable... \" >&6; }\nif ${je_cv_alloc_size+:} false; then :\n  $as_echo_n \"(cached) \" >&6\nelse\n  cat confdefs.h - <<_ACEOF >conftest.$ac_ext\n/* end confdefs.h.  */\n#include <stdlib.h>\nint\nmain ()\n{\nvoid *foo(size_t size) __attribute__((alloc_size(1)));\n  ;\n  return 0;\n}\n_ACEOF\nif ac_fn_c_try_link \"$LINENO\"; then :\n  je_cv_alloc_size=yes\nelse\n  je_cv_alloc_size=no\nfi\nrm -f core conftest.err conftest.$ac_objext \\\n    conftest$ac_exeext conftest.$ac_ext\nfi\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: result: $je_cv_alloc_size\" >&5\n$as_echo \"$je_cv_alloc_size\" >&6; }\n\nCFLAGS=\"${SAVED_CFLAGS}\"\nif test \"x${je_cv_alloc_size}\" = \"xyes\" ; then\n  $as_echo \"#define JEMALLOC_HAVE_ATTR_ALLOC_SIZE  \" >>confdefs.h\n\nfi\nSAVED_CFLAGS=\"${CFLAGS}\"\n\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: checking whether compiler supports -Werror\" >&5\n$as_echo_n \"checking whether compiler supports -Werror... \" >&6; }\nTCFLAGS=\"${CFLAGS}\"\nif test \"x${CFLAGS}\" = \"x\" ; then\n  CFLAGS=\"-Werror\"\nelse\n  CFLAGS=\"${CFLAGS} -Werror\"\nfi\ncat confdefs.h - <<_ACEOF >conftest.$ac_ext\n/* end confdefs.h.  */\n\n\nint\nmain ()\n{\n\n    return 0;\n\n  ;\n  return 0;\n}\n_ACEOF\nif ac_fn_c_try_compile \"$LINENO\"; then :\n  je_cv_cflags_appended=-Werror\n              { $as_echo \"$as_me:${as_lineno-$LINENO}: result: yes\" >&5\n$as_echo \"yes\" >&6; }\nelse\n  je_cv_cflags_appended=\n              { $as_echo \"$as_me:${as_lineno-$LINENO}: result: no\" >&5\n$as_echo \"no\" >&6; }\n              CFLAGS=\"${TCFLAGS}\"\n\nfi\nrm -f core conftest.err conftest.$ac_objext conftest.$ac_ext\n\n\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: checking whether format(gnu_printf, ...) attribute is compilable\" >&5\n$as_echo_n \"checking whether format(gnu_printf, ...) attribute is compilable... \" >&6; }\nif ${je_cv_format_gnu_printf+:} false; then :\n  $as_echo_n \"(cached) \" >&6\nelse\n  cat confdefs.h - <<_ACEOF >conftest.$ac_ext\n/* end confdefs.h.  */\n#include <stdlib.h>\nint\nmain ()\n{\nvoid *foo(const char *format, ...) __attribute__((format(gnu_printf, 1, 2)));\n  ;\n  return 0;\n}\n_ACEOF\nif ac_fn_c_try_link \"$LINENO\"; then :\n  je_cv_format_gnu_printf=yes\nelse\n  je_cv_format_gnu_printf=no\nfi\nrm -f core conftest.err conftest.$ac_objext \\\n    conftest$ac_exeext conftest.$ac_ext\nfi\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: result: $je_cv_format_gnu_printf\" >&5\n$as_echo \"$je_cv_format_gnu_printf\" >&6; }\n\nCFLAGS=\"${SAVED_CFLAGS}\"\nif test \"x${je_cv_format_gnu_printf}\" = \"xyes\" ; then\n  $as_echo \"#define JEMALLOC_HAVE_ATTR_FORMAT_GNU_PRINTF  \" >>confdefs.h\n\nfi\nSAVED_CFLAGS=\"${CFLAGS}\"\n\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: checking whether compiler supports -Werror\" >&5\n$as_echo_n \"checking whether compiler supports -Werror... \" >&6; }\nTCFLAGS=\"${CFLAGS}\"\nif test \"x${CFLAGS}\" = \"x\" ; then\n  CFLAGS=\"-Werror\"\nelse\n  CFLAGS=\"${CFLAGS} -Werror\"\nfi\ncat confdefs.h - <<_ACEOF >conftest.$ac_ext\n/* end confdefs.h.  */\n\n\nint\nmain ()\n{\n\n    return 0;\n\n  ;\n  return 0;\n}\n_ACEOF\nif ac_fn_c_try_compile \"$LINENO\"; then :\n  je_cv_cflags_appended=-Werror\n              { $as_echo \"$as_me:${as_lineno-$LINENO}: result: yes\" >&5\n$as_echo \"yes\" >&6; }\nelse\n  je_cv_cflags_appended=\n              { $as_echo \"$as_me:${as_lineno-$LINENO}: result: no\" >&5\n$as_echo \"no\" >&6; }\n              CFLAGS=\"${TCFLAGS}\"\n\nfi\nrm -f core conftest.err conftest.$ac_objext conftest.$ac_ext\n\n\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: checking whether format(printf, ...) attribute is compilable\" >&5\n$as_echo_n \"checking whether format(printf, ...) attribute is compilable... \" >&6; }\nif ${je_cv_format_printf+:} false; then :\n  $as_echo_n \"(cached) \" >&6\nelse\n  cat confdefs.h - <<_ACEOF >conftest.$ac_ext\n/* end confdefs.h.  */\n#include <stdlib.h>\nint\nmain ()\n{\nvoid *foo(const char *format, ...) __attribute__((format(printf, 1, 2)));\n  ;\n  return 0;\n}\n_ACEOF\nif ac_fn_c_try_link \"$LINENO\"; then :\n  je_cv_format_printf=yes\nelse\n  je_cv_format_printf=no\nfi\nrm -f core conftest.err conftest.$ac_objext \\\n    conftest$ac_exeext conftest.$ac_ext\nfi\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: result: $je_cv_format_printf\" >&5\n$as_echo \"$je_cv_format_printf\" >&6; }\n\nCFLAGS=\"${SAVED_CFLAGS}\"\nif test \"x${je_cv_format_printf}\" = \"xyes\" ; then\n  $as_echo \"#define JEMALLOC_HAVE_ATTR_FORMAT_PRINTF  \" >>confdefs.h\n\nfi\n\n\n# Check whether --with-rpath was given.\nif test \"${with_rpath+set}\" = set; then :\n  withval=$with_rpath; if test \"x$with_rpath\" = \"xno\" ; then\n  RPATH_EXTRA=\nelse\n  RPATH_EXTRA=\"`echo $with_rpath | tr \\\":\\\" \\\" \\\"`\"\nfi\nelse\n  RPATH_EXTRA=\n\nfi\n\n\n\n# Check whether --enable-autogen was given.\nif test \"${enable_autogen+set}\" = set; then :\n  enableval=$enable_autogen; if test \"x$enable_autogen\" = \"xno\" ; then\n  enable_autogen=\"0\"\nelse\n  enable_autogen=\"1\"\nfi\n\nelse\n  enable_autogen=\"0\"\n\nfi\n\n\n\n# Find a good install program.  We prefer a C program (faster),\n# so one script is as good as another.  But avoid the broken or\n# incompatible versions:\n# SysV /etc/install, /usr/sbin/install\n# SunOS /usr/etc/install\n# IRIX /sbin/install\n# AIX /bin/install\n# AmigaOS /C/install, which installs bootblocks on floppy discs\n# AIX 4 /usr/bin/installbsd, which doesn't work without a -g flag\n# AFS /usr/afsws/bin/install, which mishandles nonexistent args\n# SVR4 /usr/ucb/install, which tries to use the nonexistent group \"staff\"\n# OS/2's system install, which has a completely different semantic\n# ./install, which can be erroneously created by make from ./install.sh.\n# Reject install programs that cannot install multiple files.\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: checking for a BSD-compatible install\" >&5\n$as_echo_n \"checking for a BSD-compatible install... \" >&6; }\nif test -z \"$INSTALL\"; then\nif ${ac_cv_path_install+:} false; then :\n  $as_echo_n \"(cached) \" >&6\nelse\n  as_save_IFS=$IFS; IFS=$PATH_SEPARATOR\nfor as_dir in $PATH\ndo\n  IFS=$as_save_IFS\n  test -z \"$as_dir\" && as_dir=.\n    # Account for people who put trailing slashes in PATH elements.\ncase $as_dir/ in #((\n  ./ | .// | /[cC]/* | \\\n  /etc/* | /usr/sbin/* | /usr/etc/* | /sbin/* | /usr/afsws/bin/* | \\\n  ?:[\\\\/]os2[\\\\/]install[\\\\/]* | ?:[\\\\/]OS2[\\\\/]INSTALL[\\\\/]* | \\\n  /usr/ucb/* ) ;;\n  *)\n    # OSF1 and SCO ODT 3.0 have their own names for install.\n    # Don't use installbsd from OSF since it installs stuff as root\n    # by default.\n    for ac_prog in ginstall scoinst install; do\n      for ac_exec_ext in '' $ac_executable_extensions; do\n\tif as_fn_executable_p \"$as_dir/$ac_prog$ac_exec_ext\"; then\n\t  if test $ac_prog = install &&\n\t    grep dspmsg \"$as_dir/$ac_prog$ac_exec_ext\" >/dev/null 2>&1; then\n\t    # AIX install.  It has an incompatible calling convention.\n\t    :\n\t  elif test $ac_prog = install &&\n\t    grep pwplus \"$as_dir/$ac_prog$ac_exec_ext\" >/dev/null 2>&1; then\n\t    # program-specific install script used by HP pwplus--don't use.\n\t    :\n\t  else\n\t    rm -rf conftest.one conftest.two conftest.dir\n\t    echo one > conftest.one\n\t    echo two > conftest.two\n\t    mkdir conftest.dir\n\t    if \"$as_dir/$ac_prog$ac_exec_ext\" -c conftest.one conftest.two \"`pwd`/conftest.dir\" &&\n\t      test -s conftest.one && test -s conftest.two &&\n\t      test -s conftest.dir/conftest.one &&\n\t      test -s conftest.dir/conftest.two\n\t    then\n\t      ac_cv_path_install=\"$as_dir/$ac_prog$ac_exec_ext -c\"\n\t      break 3\n\t    fi\n\t  fi\n\tfi\n      done\n    done\n    ;;\nesac\n\n  done\nIFS=$as_save_IFS\n\nrm -rf conftest.one conftest.two conftest.dir\n\nfi\n  if test \"${ac_cv_path_install+set}\" = set; then\n    INSTALL=$ac_cv_path_install\n  else\n    # As a last resort, use the slow shell script.  Don't cache a\n    # value for INSTALL within a source directory, because that will\n    # break other packages using the cache if that directory is\n    # removed, or if the value is a relative name.\n    INSTALL=$ac_install_sh\n  fi\nfi\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: result: $INSTALL\" >&5\n$as_echo \"$INSTALL\" >&6; }\n\n# Use test -z because SunOS4 sh mishandles braces in ${var-val}.\n# It thinks the first close brace ends the variable substitution.\ntest -z \"$INSTALL_PROGRAM\" && INSTALL_PROGRAM='${INSTALL}'\n\ntest -z \"$INSTALL_SCRIPT\" && INSTALL_SCRIPT='${INSTALL}'\n\ntest -z \"$INSTALL_DATA\" && INSTALL_DATA='${INSTALL} -m 644'\n\nif test -n \"$ac_tool_prefix\"; then\n  # Extract the first word of \"${ac_tool_prefix}ranlib\", so it can be a program name with args.\nset dummy ${ac_tool_prefix}ranlib; ac_word=$2\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: checking for $ac_word\" >&5\n$as_echo_n \"checking for $ac_word... \" >&6; }\nif ${ac_cv_prog_RANLIB+:} false; then :\n  $as_echo_n \"(cached) \" >&6\nelse\n  if test -n \"$RANLIB\"; then\n  ac_cv_prog_RANLIB=\"$RANLIB\" # Let the user override the test.\nelse\nas_save_IFS=$IFS; IFS=$PATH_SEPARATOR\nfor as_dir in $PATH\ndo\n  IFS=$as_save_IFS\n  test -z \"$as_dir\" && as_dir=.\n    for ac_exec_ext in '' $ac_executable_extensions; do\n  if as_fn_executable_p \"$as_dir/$ac_word$ac_exec_ext\"; then\n    ac_cv_prog_RANLIB=\"${ac_tool_prefix}ranlib\"\n    $as_echo \"$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext\" >&5\n    break 2\n  fi\ndone\n  done\nIFS=$as_save_IFS\n\nfi\nfi\nRANLIB=$ac_cv_prog_RANLIB\nif test -n \"$RANLIB\"; then\n  { $as_echo \"$as_me:${as_lineno-$LINENO}: result: $RANLIB\" >&5\n$as_echo \"$RANLIB\" >&6; }\nelse\n  { $as_echo \"$as_me:${as_lineno-$LINENO}: result: no\" >&5\n$as_echo \"no\" >&6; }\nfi\n\n\nfi\nif test -z \"$ac_cv_prog_RANLIB\"; then\n  ac_ct_RANLIB=$RANLIB\n  # Extract the first word of \"ranlib\", so it can be a program name with args.\nset dummy ranlib; ac_word=$2\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: checking for $ac_word\" >&5\n$as_echo_n \"checking for $ac_word... \" >&6; }\nif ${ac_cv_prog_ac_ct_RANLIB+:} false; then :\n  $as_echo_n \"(cached) \" >&6\nelse\n  if test -n \"$ac_ct_RANLIB\"; then\n  ac_cv_prog_ac_ct_RANLIB=\"$ac_ct_RANLIB\" # Let the user override the test.\nelse\nas_save_IFS=$IFS; IFS=$PATH_SEPARATOR\nfor as_dir in $PATH\ndo\n  IFS=$as_save_IFS\n  test -z \"$as_dir\" && as_dir=.\n    for ac_exec_ext in '' $ac_executable_extensions; do\n  if as_fn_executable_p \"$as_dir/$ac_word$ac_exec_ext\"; then\n    ac_cv_prog_ac_ct_RANLIB=\"ranlib\"\n    $as_echo \"$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext\" >&5\n    break 2\n  fi\ndone\n  done\nIFS=$as_save_IFS\n\nfi\nfi\nac_ct_RANLIB=$ac_cv_prog_ac_ct_RANLIB\nif test -n \"$ac_ct_RANLIB\"; then\n  { $as_echo \"$as_me:${as_lineno-$LINENO}: result: $ac_ct_RANLIB\" >&5\n$as_echo \"$ac_ct_RANLIB\" >&6; }\nelse\n  { $as_echo \"$as_me:${as_lineno-$LINENO}: result: no\" >&5\n$as_echo \"no\" >&6; }\nfi\n\n  if test \"x$ac_ct_RANLIB\" = x; then\n    RANLIB=\":\"\n  else\n    case $cross_compiling:$ac_tool_warned in\nyes:)\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet\" >&5\n$as_echo \"$as_me: WARNING: using cross tools not prefixed with host triplet\" >&2;}\nac_tool_warned=yes ;;\nesac\n    RANLIB=$ac_ct_RANLIB\n  fi\nelse\n  RANLIB=\"$ac_cv_prog_RANLIB\"\nfi\n\n# Extract the first word of \"ld\", so it can be a program name with args.\nset dummy ld; ac_word=$2\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: checking for $ac_word\" >&5\n$as_echo_n \"checking for $ac_word... \" >&6; }\nif ${ac_cv_path_LD+:} false; then :\n  $as_echo_n \"(cached) \" >&6\nelse\n  case $LD in\n  [\\\\/]* | ?:[\\\\/]*)\n  ac_cv_path_LD=\"$LD\" # Let the user override the test with a path.\n  ;;\n  *)\n  as_save_IFS=$IFS; IFS=$PATH_SEPARATOR\nfor as_dir in $PATH\ndo\n  IFS=$as_save_IFS\n  test -z \"$as_dir\" && as_dir=.\n    for ac_exec_ext in '' $ac_executable_extensions; do\n  if as_fn_executable_p \"$as_dir/$ac_word$ac_exec_ext\"; then\n    ac_cv_path_LD=\"$as_dir/$ac_word$ac_exec_ext\"\n    $as_echo \"$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext\" >&5\n    break 2\n  fi\ndone\n  done\nIFS=$as_save_IFS\n\n  test -z \"$ac_cv_path_LD\" && ac_cv_path_LD=\"false\"\n  ;;\nesac\nfi\nLD=$ac_cv_path_LD\nif test -n \"$LD\"; then\n  { $as_echo \"$as_me:${as_lineno-$LINENO}: result: $LD\" >&5\n$as_echo \"$LD\" >&6; }\nelse\n  { $as_echo \"$as_me:${as_lineno-$LINENO}: result: no\" >&5\n$as_echo \"no\" >&6; }\nfi\n\n\n# Extract the first word of \"autoconf\", so it can be a program name with args.\nset dummy autoconf; ac_word=$2\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: checking for $ac_word\" >&5\n$as_echo_n \"checking for $ac_word... \" >&6; }\nif ${ac_cv_path_AUTOCONF+:} false; then :\n  $as_echo_n \"(cached) \" >&6\nelse\n  case $AUTOCONF in\n  [\\\\/]* | ?:[\\\\/]*)\n  ac_cv_path_AUTOCONF=\"$AUTOCONF\" # Let the user override the test with a path.\n  ;;\n  *)\n  as_save_IFS=$IFS; IFS=$PATH_SEPARATOR\nfor as_dir in $PATH\ndo\n  IFS=$as_save_IFS\n  test -z \"$as_dir\" && as_dir=.\n    for ac_exec_ext in '' $ac_executable_extensions; do\n  if as_fn_executable_p \"$as_dir/$ac_word$ac_exec_ext\"; then\n    ac_cv_path_AUTOCONF=\"$as_dir/$ac_word$ac_exec_ext\"\n    $as_echo \"$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext\" >&5\n    break 2\n  fi\ndone\n  done\nIFS=$as_save_IFS\n\n  test -z \"$ac_cv_path_AUTOCONF\" && ac_cv_path_AUTOCONF=\"false\"\n  ;;\nesac\nfi\nAUTOCONF=$ac_cv_path_AUTOCONF\nif test -n \"$AUTOCONF\"; then\n  { $as_echo \"$as_me:${as_lineno-$LINENO}: result: $AUTOCONF\" >&5\n$as_echo \"$AUTOCONF\" >&6; }\nelse\n  { $as_echo \"$as_me:${as_lineno-$LINENO}: result: no\" >&5\n$as_echo \"no\" >&6; }\nfi\n\n\n\npublic_syms=\"malloc_conf malloc_message malloc calloc posix_memalign aligned_alloc realloc free mallocx rallocx xallocx sallocx dallocx sdallocx nallocx mallctl mallctlnametomib mallctlbymib malloc_stats_print malloc_usable_size\"\n\nac_fn_c_check_func \"$LINENO\" \"memalign\" \"ac_cv_func_memalign\"\nif test \"x$ac_cv_func_memalign\" = xyes; then :\n  $as_echo \"#define JEMALLOC_OVERRIDE_MEMALIGN  \" >>confdefs.h\n\n\t       public_syms=\"${public_syms} memalign\"\nfi\n\nac_fn_c_check_func \"$LINENO\" \"valloc\" \"ac_cv_func_valloc\"\nif test \"x$ac_cv_func_valloc\" = xyes; then :\n  $as_echo \"#define JEMALLOC_OVERRIDE_VALLOC  \" >>confdefs.h\n\n\t       public_syms=\"${public_syms} valloc\"\nfi\n\n\nGCOV_FLAGS=\n# Check whether --enable-code-coverage was given.\nif test \"${enable_code_coverage+set}\" = set; then :\n  enableval=$enable_code_coverage; if test \"x$enable_code_coverage\" = \"xno\" ; then\n  enable_code_coverage=\"0\"\nelse\n  enable_code_coverage=\"1\"\nfi\n\nelse\n  enable_code_coverage=\"0\"\n\nfi\n\nif test \"x$enable_code_coverage\" = \"x1\" ; then\n  deoptimize=\"no\"\n  echo \"$CFLAGS $EXTRA_CFLAGS\" | grep '\\-O' >/dev/null || deoptimize=\"yes\"\n  if test \"x${deoptimize}\" = \"xyes\" ; then\n\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: checking whether compiler supports -O0\" >&5\n$as_echo_n \"checking whether compiler supports -O0... \" >&6; }\nTCFLAGS=\"${CFLAGS}\"\nif test \"x${CFLAGS}\" = \"x\" ; then\n  CFLAGS=\"-O0\"\nelse\n  CFLAGS=\"${CFLAGS} -O0\"\nfi\ncat confdefs.h - <<_ACEOF >conftest.$ac_ext\n/* end confdefs.h.  */\n\n\nint\nmain ()\n{\n\n    return 0;\n\n  ;\n  return 0;\n}\n_ACEOF\nif ac_fn_c_try_compile \"$LINENO\"; then :\n  je_cv_cflags_appended=-O0\n              { $as_echo \"$as_me:${as_lineno-$LINENO}: result: yes\" >&5\n$as_echo \"yes\" >&6; }\nelse\n  je_cv_cflags_appended=\n              { $as_echo \"$as_me:${as_lineno-$LINENO}: result: no\" >&5\n$as_echo \"no\" >&6; }\n              CFLAGS=\"${TCFLAGS}\"\n\nfi\nrm -f core conftest.err conftest.$ac_objext conftest.$ac_ext\n\n  fi\n\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: checking whether compiler supports -fprofile-arcs -ftest-coverage\" >&5\n$as_echo_n \"checking whether compiler supports -fprofile-arcs -ftest-coverage... \" >&6; }\nTCFLAGS=\"${CFLAGS}\"\nif test \"x${CFLAGS}\" = \"x\" ; then\n  CFLAGS=\"-fprofile-arcs -ftest-coverage\"\nelse\n  CFLAGS=\"${CFLAGS} -fprofile-arcs -ftest-coverage\"\nfi\ncat confdefs.h - <<_ACEOF >conftest.$ac_ext\n/* end confdefs.h.  */\n\n\nint\nmain ()\n{\n\n    return 0;\n\n  ;\n  return 0;\n}\n_ACEOF\nif ac_fn_c_try_compile \"$LINENO\"; then :\n  je_cv_cflags_appended=-fprofile-arcs -ftest-coverage\n              { $as_echo \"$as_me:${as_lineno-$LINENO}: result: yes\" >&5\n$as_echo \"yes\" >&6; }\nelse\n  je_cv_cflags_appended=\n              { $as_echo \"$as_me:${as_lineno-$LINENO}: result: no\" >&5\n$as_echo \"no\" >&6; }\n              CFLAGS=\"${TCFLAGS}\"\n\nfi\nrm -f core conftest.err conftest.$ac_objext conftest.$ac_ext\n\n  EXTRA_LDFLAGS=\"$EXTRA_LDFLAGS -fprofile-arcs -ftest-coverage\"\n  $as_echo \"#define JEMALLOC_CODE_COVERAGE  \" >>confdefs.h\n\nfi\n\n\n\n# Check whether --with-mangling was given.\nif test \"${with_mangling+set}\" = set; then :\n  withval=$with_mangling; mangling_map=\"$with_mangling\"\nelse\n  mangling_map=\"\"\nfi\n\n\n\n# Check whether --with-jemalloc_prefix was given.\nif test \"${with_jemalloc_prefix+set}\" = set; then :\n  withval=$with_jemalloc_prefix; JEMALLOC_PREFIX=\"$with_jemalloc_prefix\"\nelse\n  if test \"x$abi\" != \"xmacho\" -a \"x$abi\" != \"xpecoff\"; then\n  JEMALLOC_PREFIX=\"\"\nelse\n  JEMALLOC_PREFIX=\"je_\"\nfi\n\nfi\n\nif test \"x$JEMALLOC_PREFIX\" != \"x\" ; then\n  JEMALLOC_CPREFIX=`echo ${JEMALLOC_PREFIX} | tr \"a-z\" \"A-Z\"`\n  cat >>confdefs.h <<_ACEOF\n#define JEMALLOC_PREFIX \"$JEMALLOC_PREFIX\"\n_ACEOF\n\n  cat >>confdefs.h <<_ACEOF\n#define JEMALLOC_CPREFIX \"$JEMALLOC_CPREFIX\"\n_ACEOF\n\nfi\n\n\n\n# Check whether --with-export was given.\nif test \"${with_export+set}\" = set; then :\n  withval=$with_export; if test \"x$with_export\" = \"xno\"; then\n  $as_echo \"#define JEMALLOC_EXPORT /**/\" >>confdefs.h\n\nfi\n\nfi\n\n\n\n# Check whether --with-private_namespace was given.\nif test \"${with_private_namespace+set}\" = set; then :\n  withval=$with_private_namespace; JEMALLOC_PRIVATE_NAMESPACE=\"${with_private_namespace}je_\"\nelse\n  JEMALLOC_PRIVATE_NAMESPACE=\"je_\"\n\nfi\n\ncat >>confdefs.h <<_ACEOF\n#define JEMALLOC_PRIVATE_NAMESPACE $JEMALLOC_PRIVATE_NAMESPACE\n_ACEOF\n\nprivate_namespace=\"$JEMALLOC_PRIVATE_NAMESPACE\"\n\n\n\n# Check whether --with-install_suffix was given.\nif test \"${with_install_suffix+set}\" = set; then :\n  withval=$with_install_suffix; INSTALL_SUFFIX=\"$with_install_suffix\"\nelse\n  INSTALL_SUFFIX=\n\nfi\n\ninstall_suffix=\"$INSTALL_SUFFIX\"\n\n\nje_=\"je_\"\n\n\ncfgoutputs_in=\"Makefile.in\"\ncfgoutputs_in=\"${cfgoutputs_in} jemalloc.pc.in\"\ncfgoutputs_in=\"${cfgoutputs_in} doc/html.xsl.in\"\ncfgoutputs_in=\"${cfgoutputs_in} doc/manpages.xsl.in\"\ncfgoutputs_in=\"${cfgoutputs_in} doc/jemalloc.xml.in\"\ncfgoutputs_in=\"${cfgoutputs_in} include/jemalloc/jemalloc_macros.h.in\"\ncfgoutputs_in=\"${cfgoutputs_in} include/jemalloc/jemalloc_protos.h.in\"\ncfgoutputs_in=\"${cfgoutputs_in} include/jemalloc/jemalloc_typedefs.h.in\"\ncfgoutputs_in=\"${cfgoutputs_in} include/jemalloc/internal/jemalloc_internal.h.in\"\ncfgoutputs_in=\"${cfgoutputs_in} test/test.sh.in\"\ncfgoutputs_in=\"${cfgoutputs_in} test/include/test/jemalloc_test.h.in\"\n\ncfgoutputs_out=\"Makefile\"\ncfgoutputs_out=\"${cfgoutputs_out} jemalloc.pc\"\ncfgoutputs_out=\"${cfgoutputs_out} doc/html.xsl\"\ncfgoutputs_out=\"${cfgoutputs_out} doc/manpages.xsl\"\ncfgoutputs_out=\"${cfgoutputs_out} doc/jemalloc.xml\"\ncfgoutputs_out=\"${cfgoutputs_out} include/jemalloc/jemalloc_macros.h\"\ncfgoutputs_out=\"${cfgoutputs_out} include/jemalloc/jemalloc_protos.h\"\ncfgoutputs_out=\"${cfgoutputs_out} include/jemalloc/jemalloc_typedefs.h\"\ncfgoutputs_out=\"${cfgoutputs_out} include/jemalloc/internal/jemalloc_internal.h\"\ncfgoutputs_out=\"${cfgoutputs_out} test/test.sh\"\ncfgoutputs_out=\"${cfgoutputs_out} test/include/test/jemalloc_test.h\"\n\ncfgoutputs_tup=\"Makefile\"\ncfgoutputs_tup=\"${cfgoutputs_tup} jemalloc.pc:jemalloc.pc.in\"\ncfgoutputs_tup=\"${cfgoutputs_tup} doc/html.xsl:doc/html.xsl.in\"\ncfgoutputs_tup=\"${cfgoutputs_tup} doc/manpages.xsl:doc/manpages.xsl.in\"\ncfgoutputs_tup=\"${cfgoutputs_tup} doc/jemalloc.xml:doc/jemalloc.xml.in\"\ncfgoutputs_tup=\"${cfgoutputs_tup} include/jemalloc/jemalloc_macros.h:include/jemalloc/jemalloc_macros.h.in\"\ncfgoutputs_tup=\"${cfgoutputs_tup} include/jemalloc/jemalloc_protos.h:include/jemalloc/jemalloc_protos.h.in\"\ncfgoutputs_tup=\"${cfgoutputs_tup} include/jemalloc/jemalloc_typedefs.h:include/jemalloc/jemalloc_typedefs.h.in\"\ncfgoutputs_tup=\"${cfgoutputs_tup} include/jemalloc/internal/jemalloc_internal.h\"\ncfgoutputs_tup=\"${cfgoutputs_tup} test/test.sh:test/test.sh.in\"\ncfgoutputs_tup=\"${cfgoutputs_tup} test/include/test/jemalloc_test.h:test/include/test/jemalloc_test.h.in\"\n\ncfghdrs_in=\"include/jemalloc/jemalloc_defs.h.in\"\ncfghdrs_in=\"${cfghdrs_in} include/jemalloc/internal/jemalloc_internal_defs.h.in\"\ncfghdrs_in=\"${cfghdrs_in} include/jemalloc/internal/private_namespace.sh\"\ncfghdrs_in=\"${cfghdrs_in} include/jemalloc/internal/private_unnamespace.sh\"\ncfghdrs_in=\"${cfghdrs_in} include/jemalloc/internal/private_symbols.txt\"\ncfghdrs_in=\"${cfghdrs_in} include/jemalloc/internal/public_namespace.sh\"\ncfghdrs_in=\"${cfghdrs_in} include/jemalloc/internal/public_unnamespace.sh\"\ncfghdrs_in=\"${cfghdrs_in} include/jemalloc/internal/size_classes.sh\"\ncfghdrs_in=\"${cfghdrs_in} include/jemalloc/jemalloc_rename.sh\"\ncfghdrs_in=\"${cfghdrs_in} include/jemalloc/jemalloc_mangle.sh\"\ncfghdrs_in=\"${cfghdrs_in} include/jemalloc/jemalloc.sh\"\ncfghdrs_in=\"${cfghdrs_in} test/include/test/jemalloc_test_defs.h.in\"\n\ncfghdrs_out=\"include/jemalloc/jemalloc_defs.h\"\ncfghdrs_out=\"${cfghdrs_out} include/jemalloc/jemalloc${install_suffix}.h\"\ncfghdrs_out=\"${cfghdrs_out} include/jemalloc/internal/private_namespace.h\"\ncfghdrs_out=\"${cfghdrs_out} include/jemalloc/internal/private_unnamespace.h\"\ncfghdrs_out=\"${cfghdrs_out} include/jemalloc/internal/public_symbols.txt\"\ncfghdrs_out=\"${cfghdrs_out} include/jemalloc/internal/public_namespace.h\"\ncfghdrs_out=\"${cfghdrs_out} include/jemalloc/internal/public_unnamespace.h\"\ncfghdrs_out=\"${cfghdrs_out} include/jemalloc/internal/size_classes.h\"\ncfghdrs_out=\"${cfghdrs_out} include/jemalloc/jemalloc_protos_jet.h\"\ncfghdrs_out=\"${cfghdrs_out} include/jemalloc/jemalloc_rename.h\"\ncfghdrs_out=\"${cfghdrs_out} include/jemalloc/jemalloc_mangle.h\"\ncfghdrs_out=\"${cfghdrs_out} include/jemalloc/jemalloc_mangle_jet.h\"\ncfghdrs_out=\"${cfghdrs_out} include/jemalloc/internal/jemalloc_internal_defs.h\"\ncfghdrs_out=\"${cfghdrs_out} test/include/test/jemalloc_test_defs.h\"\n\ncfghdrs_tup=\"include/jemalloc/jemalloc_defs.h:include/jemalloc/jemalloc_defs.h.in\"\ncfghdrs_tup=\"${cfghdrs_tup} include/jemalloc/internal/jemalloc_internal_defs.h:include/jemalloc/internal/jemalloc_internal_defs.h.in\"\ncfghdrs_tup=\"${cfghdrs_tup} test/include/test/jemalloc_test_defs.h:test/include/test/jemalloc_test_defs.h.in\"\n\n# Check whether --enable-cc-silence was given.\nif test \"${enable_cc_silence+set}\" = set; then :\n  enableval=$enable_cc_silence; if test \"x$enable_cc_silence\" = \"xno\" ; then\n  enable_cc_silence=\"0\"\nelse\n  enable_cc_silence=\"1\"\nfi\n\nelse\n  enable_cc_silence=\"1\"\n\nfi\n\nif test \"x$enable_cc_silence\" = \"x1\" ; then\n  $as_echo \"#define JEMALLOC_CC_SILENCE  \" >>confdefs.h\n\nfi\n\n# Check whether --enable-debug was given.\nif test \"${enable_debug+set}\" = set; then :\n  enableval=$enable_debug; if test \"x$enable_debug\" = \"xno\" ; then\n  enable_debug=\"0\"\nelse\n  enable_debug=\"1\"\nfi\n\nelse\n  enable_debug=\"0\"\n\nfi\n\nif test \"x$enable_debug\" = \"x1\" ; then\n  $as_echo \"#define JEMALLOC_DEBUG  \" >>confdefs.h\n\nfi\nif test \"x$enable_debug\" = \"x1\" ; then\n  $as_echo \"#define JEMALLOC_DEBUG  \" >>confdefs.h\n\n  enable_ivsalloc=\"1\"\nfi\n\n\n# Check whether --enable-ivsalloc was given.\nif test \"${enable_ivsalloc+set}\" = set; then :\n  enableval=$enable_ivsalloc; if test \"x$enable_ivsalloc\" = \"xno\" ; then\n  enable_ivsalloc=\"0\"\nelse\n  enable_ivsalloc=\"1\"\nfi\n\nelse\n  enable_ivsalloc=\"0\"\n\nfi\n\nif test \"x$enable_ivsalloc\" = \"x1\" ; then\n  $as_echo \"#define JEMALLOC_IVSALLOC  \" >>confdefs.h\n\nfi\n\nif test \"x$enable_debug\" = \"x0\" -a \"x$no_CFLAGS\" = \"xyes\" ; then\n    optimize=\"no\"\n  echo \"$CFLAGS $EXTRA_CFLAGS\" | grep '\\-O' >/dev/null || optimize=\"yes\"\n  if test \"x${optimize}\" = \"xyes\" ; then\n    if test \"x$GCC\" = \"xyes\" ; then\n\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: checking whether compiler supports -O3\" >&5\n$as_echo_n \"checking whether compiler supports -O3... \" >&6; }\nTCFLAGS=\"${CFLAGS}\"\nif test \"x${CFLAGS}\" = \"x\" ; then\n  CFLAGS=\"-O3\"\nelse\n  CFLAGS=\"${CFLAGS} -O3\"\nfi\ncat confdefs.h - <<_ACEOF >conftest.$ac_ext\n/* end confdefs.h.  */\n\n\nint\nmain ()\n{\n\n    return 0;\n\n  ;\n  return 0;\n}\n_ACEOF\nif ac_fn_c_try_compile \"$LINENO\"; then :\n  je_cv_cflags_appended=-O3\n              { $as_echo \"$as_me:${as_lineno-$LINENO}: result: yes\" >&5\n$as_echo \"yes\" >&6; }\nelse\n  je_cv_cflags_appended=\n              { $as_echo \"$as_me:${as_lineno-$LINENO}: result: no\" >&5\n$as_echo \"no\" >&6; }\n              CFLAGS=\"${TCFLAGS}\"\n\nfi\nrm -f core conftest.err conftest.$ac_objext conftest.$ac_ext\n\n\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: checking whether compiler supports -funroll-loops\" >&5\n$as_echo_n \"checking whether compiler supports -funroll-loops... \" >&6; }\nTCFLAGS=\"${CFLAGS}\"\nif test \"x${CFLAGS}\" = \"x\" ; then\n  CFLAGS=\"-funroll-loops\"\nelse\n  CFLAGS=\"${CFLAGS} -funroll-loops\"\nfi\ncat confdefs.h - <<_ACEOF >conftest.$ac_ext\n/* end confdefs.h.  */\n\n\nint\nmain ()\n{\n\n    return 0;\n\n  ;\n  return 0;\n}\n_ACEOF\nif ac_fn_c_try_compile \"$LINENO\"; then :\n  je_cv_cflags_appended=-funroll-loops\n              { $as_echo \"$as_me:${as_lineno-$LINENO}: result: yes\" >&5\n$as_echo \"yes\" >&6; }\nelse\n  je_cv_cflags_appended=\n              { $as_echo \"$as_me:${as_lineno-$LINENO}: result: no\" >&5\n$as_echo \"no\" >&6; }\n              CFLAGS=\"${TCFLAGS}\"\n\nfi\nrm -f core conftest.err conftest.$ac_objext conftest.$ac_ext\n\n    elif test \"x$je_cv_msvc\" = \"xyes\" ; then\n\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: checking whether compiler supports -O2\" >&5\n$as_echo_n \"checking whether compiler supports -O2... \" >&6; }\nTCFLAGS=\"${CFLAGS}\"\nif test \"x${CFLAGS}\" = \"x\" ; then\n  CFLAGS=\"-O2\"\nelse\n  CFLAGS=\"${CFLAGS} -O2\"\nfi\ncat confdefs.h - <<_ACEOF >conftest.$ac_ext\n/* end confdefs.h.  */\n\n\nint\nmain ()\n{\n\n    return 0;\n\n  ;\n  return 0;\n}\n_ACEOF\nif ac_fn_c_try_compile \"$LINENO\"; then :\n  je_cv_cflags_appended=-O2\n              { $as_echo \"$as_me:${as_lineno-$LINENO}: result: yes\" >&5\n$as_echo \"yes\" >&6; }\nelse\n  je_cv_cflags_appended=\n              { $as_echo \"$as_me:${as_lineno-$LINENO}: result: no\" >&5\n$as_echo \"no\" >&6; }\n              CFLAGS=\"${TCFLAGS}\"\n\nfi\nrm -f core conftest.err conftest.$ac_objext conftest.$ac_ext\n\n    else\n\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: checking whether compiler supports -O\" >&5\n$as_echo_n \"checking whether compiler supports -O... \" >&6; }\nTCFLAGS=\"${CFLAGS}\"\nif test \"x${CFLAGS}\" = \"x\" ; then\n  CFLAGS=\"-O\"\nelse\n  CFLAGS=\"${CFLAGS} -O\"\nfi\ncat confdefs.h - <<_ACEOF >conftest.$ac_ext\n/* end confdefs.h.  */\n\n\nint\nmain ()\n{\n\n    return 0;\n\n  ;\n  return 0;\n}\n_ACEOF\nif ac_fn_c_try_compile \"$LINENO\"; then :\n  je_cv_cflags_appended=-O\n              { $as_echo \"$as_me:${as_lineno-$LINENO}: result: yes\" >&5\n$as_echo \"yes\" >&6; }\nelse\n  je_cv_cflags_appended=\n              { $as_echo \"$as_me:${as_lineno-$LINENO}: result: no\" >&5\n$as_echo \"no\" >&6; }\n              CFLAGS=\"${TCFLAGS}\"\n\nfi\nrm -f core conftest.err conftest.$ac_objext conftest.$ac_ext\n\n    fi\n  fi\nfi\n\n# Check whether --enable-stats was given.\nif test \"${enable_stats+set}\" = set; then :\n  enableval=$enable_stats; if test \"x$enable_stats\" = \"xno\" ; then\n  enable_stats=\"0\"\nelse\n  enable_stats=\"1\"\nfi\n\nelse\n  enable_stats=\"1\"\n\nfi\n\nif test \"x$enable_stats\" = \"x1\" ; then\n  $as_echo \"#define JEMALLOC_STATS  \" >>confdefs.h\n\nfi\n\n\n# Check whether --enable-prof was given.\nif test \"${enable_prof+set}\" = set; then :\n  enableval=$enable_prof; if test \"x$enable_prof\" = \"xno\" ; then\n  enable_prof=\"0\"\nelse\n  enable_prof=\"1\"\nfi\n\nelse\n  enable_prof=\"0\"\n\nfi\n\nif test \"x$enable_prof\" = \"x1\" ; then\n  backtrace_method=\"\"\nelse\n  backtrace_method=\"N/A\"\nfi\n\n# Check whether --enable-prof-libunwind was given.\nif test \"${enable_prof_libunwind+set}\" = set; then :\n  enableval=$enable_prof_libunwind; if test \"x$enable_prof_libunwind\" = \"xno\" ; then\n  enable_prof_libunwind=\"0\"\nelse\n  enable_prof_libunwind=\"1\"\nfi\n\nelse\n  enable_prof_libunwind=\"0\"\n\nfi\n\n\n# Check whether --with-static_libunwind was given.\nif test \"${with_static_libunwind+set}\" = set; then :\n  withval=$with_static_libunwind; if test \"x$with_static_libunwind\" = \"xno\" ; then\n  LUNWIND=\"-lunwind\"\nelse\n  if test ! -f \"$with_static_libunwind\" ; then\n    as_fn_error $? \"Static libunwind not found: $with_static_libunwind\" \"$LINENO\" 5\n  fi\n  LUNWIND=\"$with_static_libunwind\"\nfi\nelse\n  LUNWIND=\"-lunwind\"\n\nfi\n\nif test \"x$backtrace_method\" = \"x\" -a \"x$enable_prof_libunwind\" = \"x1\" ; then\n  for ac_header in libunwind.h\ndo :\n  ac_fn_c_check_header_mongrel \"$LINENO\" \"libunwind.h\" \"ac_cv_header_libunwind_h\" \"$ac_includes_default\"\nif test \"x$ac_cv_header_libunwind_h\" = xyes; then :\n  cat >>confdefs.h <<_ACEOF\n#define HAVE_LIBUNWIND_H 1\n_ACEOF\n\nelse\n  enable_prof_libunwind=\"0\"\nfi\n\ndone\n\n  if test \"x$LUNWIND\" = \"x-lunwind\" ; then\n    { $as_echo \"$as_me:${as_lineno-$LINENO}: checking for unw_backtrace in -lunwind\" >&5\n$as_echo_n \"checking for unw_backtrace in -lunwind... \" >&6; }\nif ${ac_cv_lib_unwind_unw_backtrace+:} false; then :\n  $as_echo_n \"(cached) \" >&6\nelse\n  ac_check_lib_save_LIBS=$LIBS\nLIBS=\"-lunwind  $LIBS\"\ncat confdefs.h - <<_ACEOF >conftest.$ac_ext\n/* end confdefs.h.  */\n\n/* Override any GCC internal prototype to avoid an error.\n   Use char because int might match the return type of a GCC\n   builtin and then its argument prototype would still apply.  */\n#ifdef __cplusplus\nextern \"C\"\n#endif\nchar unw_backtrace ();\nint\nmain ()\n{\nreturn unw_backtrace ();\n  ;\n  return 0;\n}\n_ACEOF\nif ac_fn_c_try_link \"$LINENO\"; then :\n  ac_cv_lib_unwind_unw_backtrace=yes\nelse\n  ac_cv_lib_unwind_unw_backtrace=no\nfi\nrm -f core conftest.err conftest.$ac_objext \\\n    conftest$ac_exeext conftest.$ac_ext\nLIBS=$ac_check_lib_save_LIBS\nfi\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_unwind_unw_backtrace\" >&5\n$as_echo \"$ac_cv_lib_unwind_unw_backtrace\" >&6; }\nif test \"x$ac_cv_lib_unwind_unw_backtrace\" = xyes; then :\n  LIBS=\"$LIBS $LUNWIND\"\nelse\n  enable_prof_libunwind=\"0\"\nfi\n\n  else\n    LIBS=\"$LIBS $LUNWIND\"\n  fi\n  if test \"x${enable_prof_libunwind}\" = \"x1\" ; then\n    backtrace_method=\"libunwind\"\n    $as_echo \"#define JEMALLOC_PROF_LIBUNWIND  \" >>confdefs.h\n\n  fi\nfi\n\n# Check whether --enable-prof-libgcc was given.\nif test \"${enable_prof_libgcc+set}\" = set; then :\n  enableval=$enable_prof_libgcc; if test \"x$enable_prof_libgcc\" = \"xno\" ; then\n  enable_prof_libgcc=\"0\"\nelse\n  enable_prof_libgcc=\"1\"\nfi\n\nelse\n  enable_prof_libgcc=\"1\"\n\nfi\n\nif test \"x$backtrace_method\" = \"x\" -a \"x$enable_prof_libgcc\" = \"x1\" \\\n     -a \"x$GCC\" = \"xyes\" ; then\n  for ac_header in unwind.h\ndo :\n  ac_fn_c_check_header_mongrel \"$LINENO\" \"unwind.h\" \"ac_cv_header_unwind_h\" \"$ac_includes_default\"\nif test \"x$ac_cv_header_unwind_h\" = xyes; then :\n  cat >>confdefs.h <<_ACEOF\n#define HAVE_UNWIND_H 1\n_ACEOF\n\nelse\n  enable_prof_libgcc=\"0\"\nfi\n\ndone\n\n  { $as_echo \"$as_me:${as_lineno-$LINENO}: checking for _Unwind_Backtrace in -lgcc\" >&5\n$as_echo_n \"checking for _Unwind_Backtrace in -lgcc... \" >&6; }\nif ${ac_cv_lib_gcc__Unwind_Backtrace+:} false; then :\n  $as_echo_n \"(cached) \" >&6\nelse\n  ac_check_lib_save_LIBS=$LIBS\nLIBS=\"-lgcc  $LIBS\"\ncat confdefs.h - <<_ACEOF >conftest.$ac_ext\n/* end confdefs.h.  */\n\n/* Override any GCC internal prototype to avoid an error.\n   Use char because int might match the return type of a GCC\n   builtin and then its argument prototype would still apply.  */\n#ifdef __cplusplus\nextern \"C\"\n#endif\nchar _Unwind_Backtrace ();\nint\nmain ()\n{\nreturn _Unwind_Backtrace ();\n  ;\n  return 0;\n}\n_ACEOF\nif ac_fn_c_try_link \"$LINENO\"; then :\n  ac_cv_lib_gcc__Unwind_Backtrace=yes\nelse\n  ac_cv_lib_gcc__Unwind_Backtrace=no\nfi\nrm -f core conftest.err conftest.$ac_objext \\\n    conftest$ac_exeext conftest.$ac_ext\nLIBS=$ac_check_lib_save_LIBS\nfi\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_gcc__Unwind_Backtrace\" >&5\n$as_echo \"$ac_cv_lib_gcc__Unwind_Backtrace\" >&6; }\nif test \"x$ac_cv_lib_gcc__Unwind_Backtrace\" = xyes; then :\n  LIBS=\"$LIBS -lgcc\"\nelse\n  enable_prof_libgcc=\"0\"\nfi\n\n  if test \"x${enable_prof_libgcc}\" = \"x1\" ; then\n    backtrace_method=\"libgcc\"\n    $as_echo \"#define JEMALLOC_PROF_LIBGCC  \" >>confdefs.h\n\n  fi\nelse\n  enable_prof_libgcc=\"0\"\nfi\n\n# Check whether --enable-prof-gcc was given.\nif test \"${enable_prof_gcc+set}\" = set; then :\n  enableval=$enable_prof_gcc; if test \"x$enable_prof_gcc\" = \"xno\" ; then\n  enable_prof_gcc=\"0\"\nelse\n  enable_prof_gcc=\"1\"\nfi\n\nelse\n  enable_prof_gcc=\"1\"\n\nfi\n\nif test \"x$backtrace_method\" = \"x\" -a \"x$enable_prof_gcc\" = \"x1\" \\\n     -a \"x$GCC\" = \"xyes\" ; then\n\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: checking whether compiler supports -fno-omit-frame-pointer\" >&5\n$as_echo_n \"checking whether compiler supports -fno-omit-frame-pointer... \" >&6; }\nTCFLAGS=\"${CFLAGS}\"\nif test \"x${CFLAGS}\" = \"x\" ; then\n  CFLAGS=\"-fno-omit-frame-pointer\"\nelse\n  CFLAGS=\"${CFLAGS} -fno-omit-frame-pointer\"\nfi\ncat confdefs.h - <<_ACEOF >conftest.$ac_ext\n/* end confdefs.h.  */\n\n\nint\nmain ()\n{\n\n    return 0;\n\n  ;\n  return 0;\n}\n_ACEOF\nif ac_fn_c_try_compile \"$LINENO\"; then :\n  je_cv_cflags_appended=-fno-omit-frame-pointer\n              { $as_echo \"$as_me:${as_lineno-$LINENO}: result: yes\" >&5\n$as_echo \"yes\" >&6; }\nelse\n  je_cv_cflags_appended=\n              { $as_echo \"$as_me:${as_lineno-$LINENO}: result: no\" >&5\n$as_echo \"no\" >&6; }\n              CFLAGS=\"${TCFLAGS}\"\n\nfi\nrm -f core conftest.err conftest.$ac_objext conftest.$ac_ext\n\n  backtrace_method=\"gcc intrinsics\"\n  $as_echo \"#define JEMALLOC_PROF_GCC  \" >>confdefs.h\n\nelse\n  enable_prof_gcc=\"0\"\nfi\n\nif test \"x$backtrace_method\" = \"x\" ; then\n  backtrace_method=\"none (disabling profiling)\"\n  enable_prof=\"0\"\nfi\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: checking configured backtracing method\" >&5\n$as_echo_n \"checking configured backtracing method... \" >&6; }\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: result: $backtrace_method\" >&5\n$as_echo \"$backtrace_method\" >&6; }\nif test \"x$enable_prof\" = \"x1\" ; then\n  if test \"x$abi\" != \"xpecoff\"; then\n        LIBS=\"$LIBS -lm\"\n  fi\n\n  $as_echo \"#define JEMALLOC_PROF  \" >>confdefs.h\n\nfi\n\n\n# Check whether --enable-tcache was given.\nif test \"${enable_tcache+set}\" = set; then :\n  enableval=$enable_tcache; if test \"x$enable_tcache\" = \"xno\" ; then\n  enable_tcache=\"0\"\nelse\n  enable_tcache=\"1\"\nfi\n\nelse\n  enable_tcache=\"1\"\n\nfi\n\nif test \"x$enable_tcache\" = \"x1\" ; then\n  $as_echo \"#define JEMALLOC_TCACHE  \" >>confdefs.h\n\nfi\n\n\nif test \"x${maps_coalesce}\" = \"x1\" ; then\n  $as_echo \"#define JEMALLOC_MAPS_COALESCE  \" >>confdefs.h\n\nfi\n\n# Check whether --enable-munmap was given.\nif test \"${enable_munmap+set}\" = set; then :\n  enableval=$enable_munmap; if test \"x$enable_munmap\" = \"xno\" ; then\n  enable_munmap=\"0\"\nelse\n  enable_munmap=\"1\"\nfi\n\nelse\n  enable_munmap=\"${default_munmap}\"\n\nfi\n\nif test \"x$enable_munmap\" = \"x1\" ; then\n  $as_echo \"#define JEMALLOC_MUNMAP  \" >>confdefs.h\n\nfi\n\n\nhave_dss=\"1\"\nac_fn_c_check_func \"$LINENO\" \"sbrk\" \"ac_cv_func_sbrk\"\nif test \"x$ac_cv_func_sbrk\" = xyes; then :\n  have_sbrk=\"1\"\nelse\n  have_sbrk=\"0\"\nfi\n\nif test \"x$have_sbrk\" = \"x1\" ; then\n  if test \"x$sbrk_deprecated\" = \"x1\" ; then\n    { $as_echo \"$as_me:${as_lineno-$LINENO}: result: Disabling dss allocation because sbrk is deprecated\" >&5\n$as_echo \"Disabling dss allocation because sbrk is deprecated\" >&6; }\n    have_dss=\"0\"\n  fi\nelse\n  have_dss=\"0\"\nfi\n\nif test \"x$have_dss\" = \"x1\" ; then\n  $as_echo \"#define JEMALLOC_DSS  \" >>confdefs.h\n\nfi\n\n# Check whether --enable-fill was given.\nif test \"${enable_fill+set}\" = set; then :\n  enableval=$enable_fill; if test \"x$enable_fill\" = \"xno\" ; then\n  enable_fill=\"0\"\nelse\n  enable_fill=\"1\"\nfi\n\nelse\n  enable_fill=\"1\"\n\nfi\n\nif test \"x$enable_fill\" = \"x1\" ; then\n  $as_echo \"#define JEMALLOC_FILL  \" >>confdefs.h\n\nfi\n\n\n# Check whether --enable-utrace was given.\nif test \"${enable_utrace+set}\" = set; then :\n  enableval=$enable_utrace; if test \"x$enable_utrace\" = \"xno\" ; then\n  enable_utrace=\"0\"\nelse\n  enable_utrace=\"1\"\nfi\n\nelse\n  enable_utrace=\"0\"\n\nfi\n\n\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: checking whether utrace(2) is compilable\" >&5\n$as_echo_n \"checking whether utrace(2) is compilable... \" >&6; }\nif ${je_cv_utrace+:} false; then :\n  $as_echo_n \"(cached) \" >&6\nelse\n  cat confdefs.h - <<_ACEOF >conftest.$ac_ext\n/* end confdefs.h.  */\n\n#include <sys/types.h>\n#include <sys/param.h>\n#include <sys/time.h>\n#include <sys/uio.h>\n#include <sys/ktrace.h>\n\nint\nmain ()\n{\n\n\tutrace((void *)0, 0);\n\n  ;\n  return 0;\n}\n_ACEOF\nif ac_fn_c_try_link \"$LINENO\"; then :\n  je_cv_utrace=yes\nelse\n  je_cv_utrace=no\nfi\nrm -f core conftest.err conftest.$ac_objext \\\n    conftest$ac_exeext conftest.$ac_ext\nfi\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: result: $je_cv_utrace\" >&5\n$as_echo \"$je_cv_utrace\" >&6; }\n\nif test \"x${je_cv_utrace}\" = \"xno\" ; then\n  enable_utrace=\"0\"\nfi\nif test \"x$enable_utrace\" = \"x1\" ; then\n  $as_echo \"#define JEMALLOC_UTRACE  \" >>confdefs.h\n\nfi\n\n\n# Check whether --enable-valgrind was given.\nif test \"${enable_valgrind+set}\" = set; then :\n  enableval=$enable_valgrind; if test \"x$enable_valgrind\" = \"xno\" ; then\n  enable_valgrind=\"0\"\nelse\n  enable_valgrind=\"1\"\nfi\n\nelse\n  enable_valgrind=\"1\"\n\nfi\n\nif test \"x$enable_valgrind\" = \"x1\" ; then\n\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: checking whether valgrind is compilable\" >&5\n$as_echo_n \"checking whether valgrind is compilable... \" >&6; }\nif ${je_cv_valgrind+:} false; then :\n  $as_echo_n \"(cached) \" >&6\nelse\n  cat confdefs.h - <<_ACEOF >conftest.$ac_ext\n/* end confdefs.h.  */\n\n#include <valgrind/valgrind.h>\n#include <valgrind/memcheck.h>\n\n#if !defined(VALGRIND_RESIZEINPLACE_BLOCK)\n#  error \"Incompatible Valgrind version\"\n#endif\n\nint\nmain ()\n{\n\n  ;\n  return 0;\n}\n_ACEOF\nif ac_fn_c_try_link \"$LINENO\"; then :\n  je_cv_valgrind=yes\nelse\n  je_cv_valgrind=no\nfi\nrm -f core conftest.err conftest.$ac_objext \\\n    conftest$ac_exeext conftest.$ac_ext\nfi\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: result: $je_cv_valgrind\" >&5\n$as_echo \"$je_cv_valgrind\" >&6; }\n\n  if test \"x${je_cv_valgrind}\" = \"xno\" ; then\n    enable_valgrind=\"0\"\n  fi\n  if test \"x$enable_valgrind\" = \"x1\" ; then\n    $as_echo \"#define JEMALLOC_VALGRIND  \" >>confdefs.h\n\n  fi\nfi\n\n\n# Check whether --enable-xmalloc was given.\nif test \"${enable_xmalloc+set}\" = set; then :\n  enableval=$enable_xmalloc; if test \"x$enable_xmalloc\" = \"xno\" ; then\n  enable_xmalloc=\"0\"\nelse\n  enable_xmalloc=\"1\"\nfi\n\nelse\n  enable_xmalloc=\"0\"\n\nfi\n\nif test \"x$enable_xmalloc\" = \"x1\" ; then\n  $as_echo \"#define JEMALLOC_XMALLOC  \" >>confdefs.h\n\nfi\n\n\n# Check whether --enable-cache-oblivious was given.\nif test \"${enable_cache_oblivious+set}\" = set; then :\n  enableval=$enable_cache_oblivious; if test \"x$enable_cache_oblivious\" = \"xno\" ; then\n  enable_cache_oblivious=\"0\"\nelse\n  enable_cache_oblivious=\"1\"\nfi\n\nelse\n  enable_cache_oblivious=\"1\"\n\nfi\n\nif test \"x$enable_cache_oblivious\" = \"x1\" ; then\n  $as_echo \"#define JEMALLOC_CACHE_OBLIVIOUS  \" >>confdefs.h\n\nfi\n\n\n\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: checking whether a program using __builtin_ffsl is compilable\" >&5\n$as_echo_n \"checking whether a program using __builtin_ffsl is compilable... \" >&6; }\nif ${je_cv_gcc_builtin_ffsl+:} false; then :\n  $as_echo_n \"(cached) \" >&6\nelse\n  cat confdefs.h - <<_ACEOF >conftest.$ac_ext\n/* end confdefs.h.  */\n\n#include <stdio.h>\n#include <strings.h>\n#include <string.h>\n\nint\nmain ()\n{\n\n\t{\n\t\tint rv = __builtin_ffsl(0x08);\n\t\tprintf(\"%d\\n\", rv);\n\t}\n\n  ;\n  return 0;\n}\n_ACEOF\nif ac_fn_c_try_link \"$LINENO\"; then :\n  je_cv_gcc_builtin_ffsl=yes\nelse\n  je_cv_gcc_builtin_ffsl=no\nfi\nrm -f core conftest.err conftest.$ac_objext \\\n    conftest$ac_exeext conftest.$ac_ext\nfi\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: result: $je_cv_gcc_builtin_ffsl\" >&5\n$as_echo \"$je_cv_gcc_builtin_ffsl\" >&6; }\n\nif test \"x${je_cv_gcc_builtin_ffsl}\" = \"xyes\" ; then\n  $as_echo \"#define JEMALLOC_INTERNAL_FFSL __builtin_ffsl\" >>confdefs.h\n\n  $as_echo \"#define JEMALLOC_INTERNAL_FFS __builtin_ffs\" >>confdefs.h\n\nelse\n\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: checking whether a program using ffsl is compilable\" >&5\n$as_echo_n \"checking whether a program using ffsl is compilable... \" >&6; }\nif ${je_cv_function_ffsl+:} false; then :\n  $as_echo_n \"(cached) \" >&6\nelse\n  cat confdefs.h - <<_ACEOF >conftest.$ac_ext\n/* end confdefs.h.  */\n\n  #include <stdio.h>\n  #include <strings.h>\n  #include <string.h>\n\nint\nmain ()\n{\n\n\t{\n\t\tint rv = ffsl(0x08);\n\t\tprintf(\"%d\\n\", rv);\n\t}\n\n  ;\n  return 0;\n}\n_ACEOF\nif ac_fn_c_try_link \"$LINENO\"; then :\n  je_cv_function_ffsl=yes\nelse\n  je_cv_function_ffsl=no\nfi\nrm -f core conftest.err conftest.$ac_objext \\\n    conftest$ac_exeext conftest.$ac_ext\nfi\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: result: $je_cv_function_ffsl\" >&5\n$as_echo \"$je_cv_function_ffsl\" >&6; }\n\n  if test \"x${je_cv_function_ffsl}\" = \"xyes\" ; then\n    $as_echo \"#define JEMALLOC_INTERNAL_FFSL ffsl\" >>confdefs.h\n\n    $as_echo \"#define JEMALLOC_INTERNAL_FFS ffs\" >>confdefs.h\n\n  else\n    as_fn_error $? \"Cannot build without ffsl(3) or __builtin_ffsl()\" \"$LINENO\" 5\n  fi\nfi\n\n\n# Check whether --with-lg_tiny_min was given.\nif test \"${with_lg_tiny_min+set}\" = set; then :\n  withval=$with_lg_tiny_min; LG_TINY_MIN=\"$with_lg_tiny_min\"\nelse\n  LG_TINY_MIN=\"3\"\nfi\n\ncat >>confdefs.h <<_ACEOF\n#define LG_TINY_MIN $LG_TINY_MIN\n_ACEOF\n\n\n\n# Check whether --with-lg_quantum was given.\nif test \"${with_lg_quantum+set}\" = set; then :\n  withval=$with_lg_quantum; LG_QUANTA=\"$with_lg_quantum\"\nelse\n  LG_QUANTA=\"3 4\"\nfi\n\nif test \"x$with_lg_quantum\" != \"x\" ; then\n  cat >>confdefs.h <<_ACEOF\n#define LG_QUANTUM $with_lg_quantum\n_ACEOF\n\nfi\n\n\n# Check whether --with-lg_page was given.\nif test \"${with_lg_page+set}\" = set; then :\n  withval=$with_lg_page; LG_PAGE=\"$with_lg_page\"\nelse\n  LG_PAGE=\"detect\"\nfi\n\nif test \"x$LG_PAGE\" = \"xdetect\"; then\n  { $as_echo \"$as_me:${as_lineno-$LINENO}: checking LG_PAGE\" >&5\n$as_echo_n \"checking LG_PAGE... \" >&6; }\nif ${je_cv_lg_page+:} false; then :\n  $as_echo_n \"(cached) \" >&6\nelse\n  if test \"$cross_compiling\" = yes; then :\n  je_cv_lg_page=12\nelse\n  cat confdefs.h - <<_ACEOF >conftest.$ac_ext\n/* end confdefs.h.  */\n\n#include <strings.h>\n#ifdef _WIN32\n#include <windows.h>\n#else\n#include <unistd.h>\n#endif\n#include <stdio.h>\n\nint\nmain ()\n{\n\n    int result;\n    FILE *f;\n\n#ifdef _WIN32\n    SYSTEM_INFO si;\n    GetSystemInfo(&si);\n    result = si.dwPageSize;\n#else\n    result = sysconf(_SC_PAGESIZE);\n#endif\n    if (result == -1) {\n\treturn 1;\n    }\n    result = JEMALLOC_INTERNAL_FFSL(result) - 1;\n\n    f = fopen(\"conftest.out\", \"w\");\n    if (f == NULL) {\n\treturn 1;\n    }\n    fprintf(f, \"%d\\n\", result);\n    fclose(f);\n\n    return 0;\n\n  ;\n  return 0;\n}\n_ACEOF\nif ac_fn_c_try_run \"$LINENO\"; then :\n  je_cv_lg_page=`cat conftest.out`\nelse\n  je_cv_lg_page=undefined\nfi\nrm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \\\n  conftest.$ac_objext conftest.beam conftest.$ac_ext\nfi\n\nfi\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: result: $je_cv_lg_page\" >&5\n$as_echo \"$je_cv_lg_page\" >&6; }\nfi\nif test \"x${je_cv_lg_page}\" != \"x\" ; then\n  LG_PAGE=\"${je_cv_lg_page}\"\nfi\nif test \"x${LG_PAGE}\" != \"xundefined\" ; then\n   cat >>confdefs.h <<_ACEOF\n#define LG_PAGE $LG_PAGE\n_ACEOF\n\nelse\n   as_fn_error $? \"cannot determine value for LG_PAGE\" \"$LINENO\" 5\nfi\n\n\n# Check whether --with-lg_page_sizes was given.\nif test \"${with_lg_page_sizes+set}\" = set; then :\n  withval=$with_lg_page_sizes; LG_PAGE_SIZES=\"$with_lg_page_sizes\"\nelse\n  LG_PAGE_SIZES=\"$LG_PAGE\"\nfi\n\n\n\n# Check whether --with-lg_size_class_group was given.\nif test \"${with_lg_size_class_group+set}\" = set; then :\n  withval=$with_lg_size_class_group; LG_SIZE_CLASS_GROUP=\"$with_lg_size_class_group\"\nelse\n  LG_SIZE_CLASS_GROUP=\"2\"\nfi\n\n\nif test ! -e \"${objroot}VERSION\" ; then\n  if test ! -e \"${srcroot}VERSION\" ; then\n    { $as_echo \"$as_me:${as_lineno-$LINENO}: result: Missing VERSION file, and unable to generate it; creating bogus VERSION\" >&5\n$as_echo \"Missing VERSION file, and unable to generate it; creating bogus VERSION\" >&6; }\n    echo \"0.0.0-0-g0000000000000000000000000000000000000000\" > \"${objroot}VERSION\"\n  else\n    cp ${srcroot}VERSION ${objroot}VERSION\n  fi\nfi\njemalloc_version=`cat \"${objroot}VERSION\"`\njemalloc_version_major=`echo ${jemalloc_version} | tr \".g-\" \" \" | awk '{print $1}'`\njemalloc_version_minor=`echo ${jemalloc_version} | tr \".g-\" \" \" | awk '{print $2}'`\njemalloc_version_bugfix=`echo ${jemalloc_version} | tr \".g-\" \" \" | awk '{print $3}'`\njemalloc_version_nrev=`echo ${jemalloc_version} | tr \".g-\" \" \" | awk '{print $4}'`\njemalloc_version_gid=`echo ${jemalloc_version} | tr \".g-\" \" \" | awk '{print $5}'`\n\n\n\n\n\n\n\n\nif test \"x$abi\" != \"xpecoff\" ; then\n  for ac_header in pthread.h\ndo :\n  ac_fn_c_check_header_mongrel \"$LINENO\" \"pthread.h\" \"ac_cv_header_pthread_h\" \"$ac_includes_default\"\nif test \"x$ac_cv_header_pthread_h\" = xyes; then :\n  cat >>confdefs.h <<_ACEOF\n#define HAVE_PTHREAD_H 1\n_ACEOF\n\nelse\n  as_fn_error $? \"pthread.h is missing\" \"$LINENO\" 5\nfi\n\ndone\n\n      { $as_echo \"$as_me:${as_lineno-$LINENO}: checking for pthread_create in -lpthread\" >&5\n$as_echo_n \"checking for pthread_create in -lpthread... \" >&6; }\nif ${ac_cv_lib_pthread_pthread_create+:} false; then :\n  $as_echo_n \"(cached) \" >&6\nelse\n  ac_check_lib_save_LIBS=$LIBS\nLIBS=\"-lpthread  $LIBS\"\ncat confdefs.h - <<_ACEOF >conftest.$ac_ext\n/* end confdefs.h.  */\n\n/* Override any GCC internal prototype to avoid an error.\n   Use char because int might match the return type of a GCC\n   builtin and then its argument prototype would still apply.  */\n#ifdef __cplusplus\nextern \"C\"\n#endif\nchar pthread_create ();\nint\nmain ()\n{\nreturn pthread_create ();\n  ;\n  return 0;\n}\n_ACEOF\nif ac_fn_c_try_link \"$LINENO\"; then :\n  ac_cv_lib_pthread_pthread_create=yes\nelse\n  ac_cv_lib_pthread_pthread_create=no\nfi\nrm -f core conftest.err conftest.$ac_objext \\\n    conftest$ac_exeext conftest.$ac_ext\nLIBS=$ac_check_lib_save_LIBS\nfi\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_pthread_pthread_create\" >&5\n$as_echo \"$ac_cv_lib_pthread_pthread_create\" >&6; }\nif test \"x$ac_cv_lib_pthread_pthread_create\" = xyes; then :\n  LIBS=\"$LIBS -lpthread\"\nelse\n  { $as_echo \"$as_me:${as_lineno-$LINENO}: checking for library containing pthread_create\" >&5\n$as_echo_n \"checking for library containing pthread_create... \" >&6; }\nif ${ac_cv_search_pthread_create+:} false; then :\n  $as_echo_n \"(cached) \" >&6\nelse\n  ac_func_search_save_LIBS=$LIBS\ncat confdefs.h - <<_ACEOF >conftest.$ac_ext\n/* end confdefs.h.  */\n\n/* Override any GCC internal prototype to avoid an error.\n   Use char because int might match the return type of a GCC\n   builtin and then its argument prototype would still apply.  */\n#ifdef __cplusplus\nextern \"C\"\n#endif\nchar pthread_create ();\nint\nmain ()\n{\nreturn pthread_create ();\n  ;\n  return 0;\n}\n_ACEOF\nfor ac_lib in '' ; do\n  if test -z \"$ac_lib\"; then\n    ac_res=\"none required\"\n  else\n    ac_res=-l$ac_lib\n    LIBS=\"-l$ac_lib  $ac_func_search_save_LIBS\"\n  fi\n  if ac_fn_c_try_link \"$LINENO\"; then :\n  ac_cv_search_pthread_create=$ac_res\nfi\nrm -f core conftest.err conftest.$ac_objext \\\n    conftest$ac_exeext\n  if ${ac_cv_search_pthread_create+:} false; then :\n  break\nfi\ndone\nif ${ac_cv_search_pthread_create+:} false; then :\n\nelse\n  ac_cv_search_pthread_create=no\nfi\nrm conftest.$ac_ext\nLIBS=$ac_func_search_save_LIBS\nfi\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_pthread_create\" >&5\n$as_echo \"$ac_cv_search_pthread_create\" >&6; }\nac_res=$ac_cv_search_pthread_create\nif test \"$ac_res\" != no; then :\n  test \"$ac_res\" = \"none required\" || LIBS=\"$ac_res $LIBS\"\n\nelse\n  as_fn_error $? \"libpthread is missing\" \"$LINENO\" 5\nfi\n\nfi\n\nfi\n\nCPPFLAGS=\"$CPPFLAGS -D_REENTRANT\"\n\nSAVED_LIBS=\"${LIBS}\"\nLIBS=\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: checking for library containing clock_gettime\" >&5\n$as_echo_n \"checking for library containing clock_gettime... \" >&6; }\nif ${ac_cv_search_clock_gettime+:} false; then :\n  $as_echo_n \"(cached) \" >&6\nelse\n  ac_func_search_save_LIBS=$LIBS\ncat confdefs.h - <<_ACEOF >conftest.$ac_ext\n/* end confdefs.h.  */\n\n/* Override any GCC internal prototype to avoid an error.\n   Use char because int might match the return type of a GCC\n   builtin and then its argument prototype would still apply.  */\n#ifdef __cplusplus\nextern \"C\"\n#endif\nchar clock_gettime ();\nint\nmain ()\n{\nreturn clock_gettime ();\n  ;\n  return 0;\n}\n_ACEOF\nfor ac_lib in '' rt; do\n  if test -z \"$ac_lib\"; then\n    ac_res=\"none required\"\n  else\n    ac_res=-l$ac_lib\n    LIBS=\"-l$ac_lib  $ac_func_search_save_LIBS\"\n  fi\n  if ac_fn_c_try_link \"$LINENO\"; then :\n  ac_cv_search_clock_gettime=$ac_res\nfi\nrm -f core conftest.err conftest.$ac_objext \\\n    conftest$ac_exeext\n  if ${ac_cv_search_clock_gettime+:} false; then :\n  break\nfi\ndone\nif ${ac_cv_search_clock_gettime+:} false; then :\n\nelse\n  ac_cv_search_clock_gettime=no\nfi\nrm conftest.$ac_ext\nLIBS=$ac_func_search_save_LIBS\nfi\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_clock_gettime\" >&5\n$as_echo \"$ac_cv_search_clock_gettime\" >&6; }\nac_res=$ac_cv_search_clock_gettime\nif test \"$ac_res\" != no; then :\n  test \"$ac_res\" = \"none required\" || LIBS=\"$ac_res $LIBS\"\n  TESTLIBS=\"${LIBS}\"\nfi\n\n\nLIBS=\"${SAVED_LIBS}\"\n\nac_fn_c_check_func \"$LINENO\" \"secure_getenv\" \"ac_cv_func_secure_getenv\"\nif test \"x$ac_cv_func_secure_getenv\" = xyes; then :\n  have_secure_getenv=\"1\"\nelse\n  have_secure_getenv=\"0\"\n\nfi\n\nif test \"x$have_secure_getenv\" = \"x1\" ; then\n  $as_echo \"#define JEMALLOC_HAVE_SECURE_GETENV  \" >>confdefs.h\n\nfi\n\nac_fn_c_check_func \"$LINENO\" \"issetugid\" \"ac_cv_func_issetugid\"\nif test \"x$ac_cv_func_issetugid\" = xyes; then :\n  have_issetugid=\"1\"\nelse\n  have_issetugid=\"0\"\n\nfi\n\nif test \"x$have_issetugid\" = \"x1\" ; then\n  $as_echo \"#define JEMALLOC_HAVE_ISSETUGID  \" >>confdefs.h\n\nfi\n\nac_fn_c_check_func \"$LINENO\" \"_malloc_thread_cleanup\" \"ac_cv_func__malloc_thread_cleanup\"\nif test \"x$ac_cv_func__malloc_thread_cleanup\" = xyes; then :\n  have__malloc_thread_cleanup=\"1\"\nelse\n  have__malloc_thread_cleanup=\"0\"\n\nfi\n\nif test \"x$have__malloc_thread_cleanup\" = \"x1\" ; then\n  $as_echo \"#define JEMALLOC_MALLOC_THREAD_CLEANUP  \" >>confdefs.h\n\n  force_tls=\"1\"\nfi\n\nac_fn_c_check_func \"$LINENO\" \"_pthread_mutex_init_calloc_cb\" \"ac_cv_func__pthread_mutex_init_calloc_cb\"\nif test \"x$ac_cv_func__pthread_mutex_init_calloc_cb\" = xyes; then :\n  have__pthread_mutex_init_calloc_cb=\"1\"\nelse\n  have__pthread_mutex_init_calloc_cb=\"0\"\n\nfi\n\nif test \"x$have__pthread_mutex_init_calloc_cb\" = \"x1\" ; then\n  $as_echo \"#define JEMALLOC_MUTEX_INIT_CB 1\" >>confdefs.h\n\nfi\n\n# Check whether --enable-lazy_lock was given.\nif test \"${enable_lazy_lock+set}\" = set; then :\n  enableval=$enable_lazy_lock; if test \"x$enable_lazy_lock\" = \"xno\" ; then\n  enable_lazy_lock=\"0\"\nelse\n  enable_lazy_lock=\"1\"\nfi\n\nelse\n  enable_lazy_lock=\"\"\n\nfi\n\nif test \"x$enable_lazy_lock\" = \"x\" -a \"x${force_lazy_lock}\" = \"x1\" ; then\n  { $as_echo \"$as_me:${as_lineno-$LINENO}: result: Forcing lazy-lock to avoid allocator/threading bootstrap issues\" >&5\n$as_echo \"Forcing lazy-lock to avoid allocator/threading bootstrap issues\" >&6; }\n  enable_lazy_lock=\"1\"\nfi\nif test \"x$enable_lazy_lock\" = \"x1\" ; then\n  if test \"x$abi\" != \"xpecoff\" ; then\n    for ac_header in dlfcn.h\ndo :\n  ac_fn_c_check_header_mongrel \"$LINENO\" \"dlfcn.h\" \"ac_cv_header_dlfcn_h\" \"$ac_includes_default\"\nif test \"x$ac_cv_header_dlfcn_h\" = xyes; then :\n  cat >>confdefs.h <<_ACEOF\n#define HAVE_DLFCN_H 1\n_ACEOF\n\nelse\n  as_fn_error $? \"dlfcn.h is missing\" \"$LINENO\" 5\nfi\n\ndone\n\n    ac_fn_c_check_func \"$LINENO\" \"dlsym\" \"ac_cv_func_dlsym\"\nif test \"x$ac_cv_func_dlsym\" = xyes; then :\n\nelse\n  { $as_echo \"$as_me:${as_lineno-$LINENO}: checking for dlsym in -ldl\" >&5\n$as_echo_n \"checking for dlsym in -ldl... \" >&6; }\nif ${ac_cv_lib_dl_dlsym+:} false; then :\n  $as_echo_n \"(cached) \" >&6\nelse\n  ac_check_lib_save_LIBS=$LIBS\nLIBS=\"-ldl  $LIBS\"\ncat confdefs.h - <<_ACEOF >conftest.$ac_ext\n/* end confdefs.h.  */\n\n/* Override any GCC internal prototype to avoid an error.\n   Use char because int might match the return type of a GCC\n   builtin and then its argument prototype would still apply.  */\n#ifdef __cplusplus\nextern \"C\"\n#endif\nchar dlsym ();\nint\nmain ()\n{\nreturn dlsym ();\n  ;\n  return 0;\n}\n_ACEOF\nif ac_fn_c_try_link \"$LINENO\"; then :\n  ac_cv_lib_dl_dlsym=yes\nelse\n  ac_cv_lib_dl_dlsym=no\nfi\nrm -f core conftest.err conftest.$ac_objext \\\n    conftest$ac_exeext conftest.$ac_ext\nLIBS=$ac_check_lib_save_LIBS\nfi\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dl_dlsym\" >&5\n$as_echo \"$ac_cv_lib_dl_dlsym\" >&6; }\nif test \"x$ac_cv_lib_dl_dlsym\" = xyes; then :\n  LIBS=\"$LIBS -ldl\"\nelse\n  as_fn_error $? \"libdl is missing\" \"$LINENO\" 5\nfi\n\n\nfi\n\n  fi\n  $as_echo \"#define JEMALLOC_LAZY_LOCK  \" >>confdefs.h\n\nelse\n  enable_lazy_lock=\"0\"\nfi\n\n\n# Check whether --enable-tls was given.\nif test \"${enable_tls+set}\" = set; then :\n  enableval=$enable_tls; if test \"x$enable_tls\" = \"xno\" ; then\n  enable_tls=\"0\"\nelse\n  enable_tls=\"1\"\nfi\n\nelse\n  enable_tls=\"\"\n\nfi\n\nif test \"x${enable_tls}\" = \"x\" ; then\n  if test \"x${force_tls}\" = \"x1\" ; then\n    { $as_echo \"$as_me:${as_lineno-$LINENO}: result: Forcing TLS to avoid allocator/threading bootstrap issues\" >&5\n$as_echo \"Forcing TLS to avoid allocator/threading bootstrap issues\" >&6; }\n    enable_tls=\"1\"\n  elif test \"x${force_tls}\" = \"x0\" ; then\n    { $as_echo \"$as_me:${as_lineno-$LINENO}: result: Forcing no TLS to avoid allocator/threading bootstrap issues\" >&5\n$as_echo \"Forcing no TLS to avoid allocator/threading bootstrap issues\" >&6; }\n    enable_tls=\"0\"\n  else\n    enable_tls=\"1\"\n  fi\nfi\nif test \"x${enable_tls}\" = \"x1\" ; then\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: checking for TLS\" >&5\n$as_echo_n \"checking for TLS... \" >&6; }\ncat confdefs.h - <<_ACEOF >conftest.$ac_ext\n/* end confdefs.h.  */\n\n    __thread int x;\n\nint\nmain ()\n{\n\n    x = 42;\n\n    return 0;\n\n  ;\n  return 0;\n}\n_ACEOF\nif ac_fn_c_try_compile \"$LINENO\"; then :\n  { $as_echo \"$as_me:${as_lineno-$LINENO}: result: yes\" >&5\n$as_echo \"yes\" >&6; }\nelse\n  { $as_echo \"$as_me:${as_lineno-$LINENO}: result: no\" >&5\n$as_echo \"no\" >&6; }\n              enable_tls=\"0\"\nfi\nrm -f core conftest.err conftest.$ac_objext conftest.$ac_ext\nelse\n  enable_tls=\"0\"\nfi\n\nif test \"x${enable_tls}\" = \"x1\" ; then\n  if test \"x${force_tls}\" = \"x0\" ; then\n    { $as_echo \"$as_me:${as_lineno-$LINENO}: WARNING: TLS enabled despite being marked unusable on this platform\" >&5\n$as_echo \"$as_me: WARNING: TLS enabled despite being marked unusable on this platform\" >&2;}\n  fi\n  cat >>confdefs.h <<_ACEOF\n#define JEMALLOC_TLS\n_ACEOF\n\nelif test \"x${force_tls}\" = \"x1\" ; then\n  { $as_echo \"$as_me:${as_lineno-$LINENO}: WARNING: TLS disabled despite being marked critical on this platform\" >&5\n$as_echo \"$as_me: WARNING: TLS disabled despite being marked critical on this platform\" >&2;}\nfi\n\n\n\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: checking whether C11 atomics is compilable\" >&5\n$as_echo_n \"checking whether C11 atomics is compilable... \" >&6; }\nif ${je_cv_c11atomics+:} false; then :\n  $as_echo_n \"(cached) \" >&6\nelse\n  cat confdefs.h - <<_ACEOF >conftest.$ac_ext\n/* end confdefs.h.  */\n\n#include <stdint.h>\n#if (__STDC_VERSION__ >= 201112L) && !defined(__STDC_NO_ATOMICS__)\n#include <stdatomic.h>\n#else\n#error Atomics not available\n#endif\n\nint\nmain ()\n{\n\n    uint64_t *p = (uint64_t *)0;\n    uint64_t x = 1;\n    volatile atomic_uint_least64_t *a = (volatile atomic_uint_least64_t *)p;\n    uint64_t r = atomic_fetch_add(a, x) + x;\n    return (r == 0);\n\n  ;\n  return 0;\n}\n_ACEOF\nif ac_fn_c_try_link \"$LINENO\"; then :\n  je_cv_c11atomics=yes\nelse\n  je_cv_c11atomics=no\nfi\nrm -f core conftest.err conftest.$ac_objext \\\n    conftest$ac_exeext conftest.$ac_ext\nfi\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: result: $je_cv_c11atomics\" >&5\n$as_echo \"$je_cv_c11atomics\" >&6; }\n\nif test \"x${je_cv_c11atomics}\" = \"xyes\" ; then\n  $as_echo \"#define JEMALLOC_C11ATOMICS 1\" >>confdefs.h\n\nfi\n\n\n\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: checking whether atomic(9) is compilable\" >&5\n$as_echo_n \"checking whether atomic(9) is compilable... \" >&6; }\nif ${je_cv_atomic9+:} false; then :\n  $as_echo_n \"(cached) \" >&6\nelse\n  cat confdefs.h - <<_ACEOF >conftest.$ac_ext\n/* end confdefs.h.  */\n\n#include <sys/types.h>\n#include <machine/atomic.h>\n#include <inttypes.h>\n\nint\nmain ()\n{\n\n\t{\n\t\tuint32_t x32 = 0;\n\t\tvolatile uint32_t *x32p = &x32;\n\t\tatomic_fetchadd_32(x32p, 1);\n\t}\n\t{\n\t\tunsigned long xlong = 0;\n\t\tvolatile unsigned long *xlongp = &xlong;\n\t\tatomic_fetchadd_long(xlongp, 1);\n\t}\n\n  ;\n  return 0;\n}\n_ACEOF\nif ac_fn_c_try_link \"$LINENO\"; then :\n  je_cv_atomic9=yes\nelse\n  je_cv_atomic9=no\nfi\nrm -f core conftest.err conftest.$ac_objext \\\n    conftest$ac_exeext conftest.$ac_ext\nfi\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: result: $je_cv_atomic9\" >&5\n$as_echo \"$je_cv_atomic9\" >&6; }\n\nif test \"x${je_cv_atomic9}\" = \"xyes\" ; then\n  $as_echo \"#define JEMALLOC_ATOMIC9 1\" >>confdefs.h\n\nfi\n\n\n\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: checking whether Darwin OSAtomic*() is compilable\" >&5\n$as_echo_n \"checking whether Darwin OSAtomic*() is compilable... \" >&6; }\nif ${je_cv_osatomic+:} false; then :\n  $as_echo_n \"(cached) \" >&6\nelse\n  cat confdefs.h - <<_ACEOF >conftest.$ac_ext\n/* end confdefs.h.  */\n\n#include <libkern/OSAtomic.h>\n#include <inttypes.h>\n\nint\nmain ()\n{\n\n\t{\n\t\tint32_t x32 = 0;\n\t\tvolatile int32_t *x32p = &x32;\n\t\tOSAtomicAdd32(1, x32p);\n\t}\n\t{\n\t\tint64_t x64 = 0;\n\t\tvolatile int64_t *x64p = &x64;\n\t\tOSAtomicAdd64(1, x64p);\n\t}\n\n  ;\n  return 0;\n}\n_ACEOF\nif ac_fn_c_try_link \"$LINENO\"; then :\n  je_cv_osatomic=yes\nelse\n  je_cv_osatomic=no\nfi\nrm -f core conftest.err conftest.$ac_objext \\\n    conftest$ac_exeext conftest.$ac_ext\nfi\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: result: $je_cv_osatomic\" >&5\n$as_echo \"$je_cv_osatomic\" >&6; }\n\nif test \"x${je_cv_osatomic}\" = \"xyes\" ; then\n  $as_echo \"#define JEMALLOC_OSATOMIC  \" >>confdefs.h\n\nfi\n\n\n\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: checking whether madvise(2) is compilable\" >&5\n$as_echo_n \"checking whether madvise(2) is compilable... \" >&6; }\nif ${je_cv_madvise+:} false; then :\n  $as_echo_n \"(cached) \" >&6\nelse\n  cat confdefs.h - <<_ACEOF >conftest.$ac_ext\n/* end confdefs.h.  */\n\n#include <sys/mman.h>\n\nint\nmain ()\n{\n\n\t{\n\t\tmadvise((void *)0, 0, 0);\n\t}\n\n  ;\n  return 0;\n}\n_ACEOF\nif ac_fn_c_try_link \"$LINENO\"; then :\n  je_cv_madvise=yes\nelse\n  je_cv_madvise=no\nfi\nrm -f core conftest.err conftest.$ac_objext \\\n    conftest$ac_exeext conftest.$ac_ext\nfi\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: result: $je_cv_madvise\" >&5\n$as_echo \"$je_cv_madvise\" >&6; }\n\nif test \"x${je_cv_madvise}\" = \"xyes\" ; then\n  $as_echo \"#define JEMALLOC_HAVE_MADVISE  \" >>confdefs.h\n\nfi\n\n\n\n\nif test \"x${je_cv_atomic9}\" != \"xyes\" -a \"x${je_cv_osatomic}\" != \"xyes\" ; then\n\n  { $as_echo \"$as_me:${as_lineno-$LINENO}: checking whether to force 32-bit __sync_{add,sub}_and_fetch()\" >&5\n$as_echo_n \"checking whether to force 32-bit __sync_{add,sub}_and_fetch()... \" >&6; }\nif ${je_cv_sync_compare_and_swap_4+:} false; then :\n  $as_echo_n \"(cached) \" >&6\nelse\n  cat confdefs.h - <<_ACEOF >conftest.$ac_ext\n/* end confdefs.h.  */\n\n                                                 #include <stdint.h>\n\nint\nmain ()\n{\n\n                                                 #ifndef __GCC_HAVE_SYNC_COMPARE_AND_SWAP_4\n                                                 {\n                                                    uint32_t x32 = 0;\n                                                    __sync_add_and_fetch(&x32, 42);\n                                                    __sync_sub_and_fetch(&x32, 1);\n                                                 }\n                                                 #else\n                                                 #error __GCC_HAVE_SYNC_COMPARE_AND_SWAP_4 is defined, no need to force\n                                                 #endif\n\n  ;\n  return 0;\n}\n_ACEOF\nif ac_fn_c_try_link \"$LINENO\"; then :\n  je_cv_sync_compare_and_swap_4=yes\nelse\n  je_cv_sync_compare_and_swap_4=no\nfi\nrm -f core conftest.err conftest.$ac_objext \\\n    conftest$ac_exeext conftest.$ac_ext\nfi\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: result: $je_cv_sync_compare_and_swap_4\" >&5\n$as_echo \"$je_cv_sync_compare_and_swap_4\" >&6; }\n\n  if test \"x${je_cv_sync_compare_and_swap_4}\" = \"xyes\" ; then\n    $as_echo \"#define JE_FORCE_SYNC_COMPARE_AND_SWAP_4  \" >>confdefs.h\n\n  fi\n\n\n  { $as_echo \"$as_me:${as_lineno-$LINENO}: checking whether to force 64-bit __sync_{add,sub}_and_fetch()\" >&5\n$as_echo_n \"checking whether to force 64-bit __sync_{add,sub}_and_fetch()... \" >&6; }\nif ${je_cv_sync_compare_and_swap_8+:} false; then :\n  $as_echo_n \"(cached) \" >&6\nelse\n  cat confdefs.h - <<_ACEOF >conftest.$ac_ext\n/* end confdefs.h.  */\n\n                                                 #include <stdint.h>\n\nint\nmain ()\n{\n\n                                                 #ifndef __GCC_HAVE_SYNC_COMPARE_AND_SWAP_8\n                                                 {\n                                                    uint64_t x64 = 0;\n                                                    __sync_add_and_fetch(&x64, 42);\n                                                    __sync_sub_and_fetch(&x64, 1);\n                                                 }\n                                                 #else\n                                                 #error __GCC_HAVE_SYNC_COMPARE_AND_SWAP_8 is defined, no need to force\n                                                 #endif\n\n  ;\n  return 0;\n}\n_ACEOF\nif ac_fn_c_try_link \"$LINENO\"; then :\n  je_cv_sync_compare_and_swap_8=yes\nelse\n  je_cv_sync_compare_and_swap_8=no\nfi\nrm -f core conftest.err conftest.$ac_objext \\\n    conftest$ac_exeext conftest.$ac_ext\nfi\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: result: $je_cv_sync_compare_and_swap_8\" >&5\n$as_echo \"$je_cv_sync_compare_and_swap_8\" >&6; }\n\n  if test \"x${je_cv_sync_compare_and_swap_8}\" = \"xyes\" ; then\n    $as_echo \"#define JE_FORCE_SYNC_COMPARE_AND_SWAP_8  \" >>confdefs.h\n\n  fi\n\nfi\n\n\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: checking for __builtin_clz\" >&5\n$as_echo_n \"checking for __builtin_clz... \" >&6; }\nif ${je_cv_builtin_clz+:} false; then :\n  $as_echo_n \"(cached) \" >&6\nelse\n  cat confdefs.h - <<_ACEOF >conftest.$ac_ext\n/* end confdefs.h.  */\n\nint\nmain ()\n{\n\n                                                {\n                                                        unsigned x = 0;\n                                                        int y = __builtin_clz(x);\n                                                }\n                                                {\n                                                        unsigned long x = 0;\n                                                        int y = __builtin_clzl(x);\n                                                }\n\n  ;\n  return 0;\n}\n_ACEOF\nif ac_fn_c_try_link \"$LINENO\"; then :\n  je_cv_builtin_clz=yes\nelse\n  je_cv_builtin_clz=no\nfi\nrm -f core conftest.err conftest.$ac_objext \\\n    conftest$ac_exeext conftest.$ac_ext\nfi\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: result: $je_cv_builtin_clz\" >&5\n$as_echo \"$je_cv_builtin_clz\" >&6; }\n\nif test \"x${je_cv_builtin_clz}\" = \"xyes\" ; then\n  $as_echo \"#define JEMALLOC_HAVE_BUILTIN_CLZ  \" >>confdefs.h\n\nfi\n\n\n\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: checking whether Darwin OSSpin*() is compilable\" >&5\n$as_echo_n \"checking whether Darwin OSSpin*() is compilable... \" >&6; }\nif ${je_cv_osspin+:} false; then :\n  $as_echo_n \"(cached) \" >&6\nelse\n  cat confdefs.h - <<_ACEOF >conftest.$ac_ext\n/* end confdefs.h.  */\n\n#include <libkern/OSAtomic.h>\n#include <inttypes.h>\n\nint\nmain ()\n{\n\n\tOSSpinLock lock = 0;\n\tOSSpinLockLock(&lock);\n\tOSSpinLockUnlock(&lock);\n\n  ;\n  return 0;\n}\n_ACEOF\nif ac_fn_c_try_link \"$LINENO\"; then :\n  je_cv_osspin=yes\nelse\n  je_cv_osspin=no\nfi\nrm -f core conftest.err conftest.$ac_objext \\\n    conftest$ac_exeext conftest.$ac_ext\nfi\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: result: $je_cv_osspin\" >&5\n$as_echo \"$je_cv_osspin\" >&6; }\n\nif test \"x${je_cv_osspin}\" = \"xyes\" ; then\n  $as_echo \"#define JEMALLOC_OSSPIN  \" >>confdefs.h\n\nfi\n\n\n# Check whether --enable-zone-allocator was given.\nif test \"${enable_zone_allocator+set}\" = set; then :\n  enableval=$enable_zone_allocator; if test \"x$enable_zone_allocator\" = \"xno\" ; then\n  enable_zone_allocator=\"0\"\nelse\n  enable_zone_allocator=\"1\"\nfi\n\nelse\n  if test \"x${abi}\" = \"xmacho\"; then\n  enable_zone_allocator=\"1\"\nfi\n\n\nfi\n\n\n\nif test \"x${enable_zone_allocator}\" = \"x1\" ; then\n  if test \"x${abi}\" != \"xmacho\"; then\n    as_fn_error $? \"--enable-zone-allocator is only supported on Darwin\" \"$LINENO\" 5\n  fi\n  $as_echo \"#define JEMALLOC_ZONE  \" >>confdefs.h\n\n\n        { $as_echo \"$as_me:${as_lineno-$LINENO}: checking malloc zone version\" >&5\n$as_echo_n \"checking malloc zone version... \" >&6; }\n\n\n  cat confdefs.h - <<_ACEOF >conftest.$ac_ext\n/* end confdefs.h.  */\n#include <malloc/malloc.h>\nint\nmain ()\n{\nstatic int foo[sizeof(malloc_zone_t) == sizeof(void *) * 14 ? 1 : -1]\n\n  ;\n  return 0;\n}\n_ACEOF\nif ac_fn_c_try_compile \"$LINENO\"; then :\n  JEMALLOC_ZONE_VERSION=3\nelse\n\n  cat confdefs.h - <<_ACEOF >conftest.$ac_ext\n/* end confdefs.h.  */\n#include <malloc/malloc.h>\nint\nmain ()\n{\nstatic int foo[sizeof(malloc_zone_t) == sizeof(void *) * 15 ? 1 : -1]\n\n  ;\n  return 0;\n}\n_ACEOF\nif ac_fn_c_try_compile \"$LINENO\"; then :\n  JEMALLOC_ZONE_VERSION=5\nelse\n\n  cat confdefs.h - <<_ACEOF >conftest.$ac_ext\n/* end confdefs.h.  */\n#include <malloc/malloc.h>\nint\nmain ()\n{\nstatic int foo[sizeof(malloc_zone_t) == sizeof(void *) * 16 ? 1 : -1]\n\n  ;\n  return 0;\n}\n_ACEOF\nif ac_fn_c_try_compile \"$LINENO\"; then :\n\n    cat confdefs.h - <<_ACEOF >conftest.$ac_ext\n/* end confdefs.h.  */\n#include <malloc/malloc.h>\nint\nmain ()\n{\nstatic int foo[sizeof(malloc_introspection_t) == sizeof(void *) * 9 ? 1 : -1]\n\n  ;\n  return 0;\n}\n_ACEOF\nif ac_fn_c_try_compile \"$LINENO\"; then :\n  JEMALLOC_ZONE_VERSION=6\nelse\n\n    cat confdefs.h - <<_ACEOF >conftest.$ac_ext\n/* end confdefs.h.  */\n#include <malloc/malloc.h>\nint\nmain ()\n{\nstatic int foo[sizeof(malloc_introspection_t) == sizeof(void *) * 13 ? 1 : -1]\n\n  ;\n  return 0;\n}\n_ACEOF\nif ac_fn_c_try_compile \"$LINENO\"; then :\n  JEMALLOC_ZONE_VERSION=7\nelse\n  JEMALLOC_ZONE_VERSION=\n\nfi\nrm -f core conftest.err conftest.$ac_objext conftest.$ac_ext\nfi\nrm -f core conftest.err conftest.$ac_objext conftest.$ac_ext\nelse\n\n  cat confdefs.h - <<_ACEOF >conftest.$ac_ext\n/* end confdefs.h.  */\n#include <malloc/malloc.h>\nint\nmain ()\n{\nstatic int foo[sizeof(malloc_zone_t) == sizeof(void *) * 17 ? 1 : -1]\n\n  ;\n  return 0;\n}\n_ACEOF\nif ac_fn_c_try_compile \"$LINENO\"; then :\n  JEMALLOC_ZONE_VERSION=8\nelse\n\n  cat confdefs.h - <<_ACEOF >conftest.$ac_ext\n/* end confdefs.h.  */\n#include <malloc/malloc.h>\nint\nmain ()\n{\nstatic int foo[sizeof(malloc_zone_t) > sizeof(void *) * 17 ? 1 : -1]\n\n  ;\n  return 0;\n}\n_ACEOF\nif ac_fn_c_try_compile \"$LINENO\"; then :\n  JEMALLOC_ZONE_VERSION=9\nelse\n  JEMALLOC_ZONE_VERSION=\n\nfi\nrm -f core conftest.err conftest.$ac_objext conftest.$ac_ext\nfi\nrm -f core conftest.err conftest.$ac_objext conftest.$ac_ext\nfi\nrm -f core conftest.err conftest.$ac_objext conftest.$ac_ext\nfi\nrm -f core conftest.err conftest.$ac_objext conftest.$ac_ext\nfi\nrm -f core conftest.err conftest.$ac_objext conftest.$ac_ext\n  if test \"x${JEMALLOC_ZONE_VERSION}\" = \"x\"; then\n    { $as_echo \"$as_me:${as_lineno-$LINENO}: result: unsupported\" >&5\n$as_echo \"unsupported\" >&6; }\n    as_fn_error $? \"Unsupported malloc zone version\" \"$LINENO\" 5\n  fi\n  if test \"${JEMALLOC_ZONE_VERSION}\" = 9; then\n    JEMALLOC_ZONE_VERSION=8\n    { $as_echo \"$as_me:${as_lineno-$LINENO}: result: > 8\" >&5\n$as_echo \"> 8\" >&6; }\n  else\n    { $as_echo \"$as_me:${as_lineno-$LINENO}: result: $JEMALLOC_ZONE_VERSION\" >&5\n$as_echo \"$JEMALLOC_ZONE_VERSION\" >&6; }\n  fi\n  cat >>confdefs.h <<_ACEOF\n#define JEMALLOC_ZONE_VERSION $JEMALLOC_ZONE_VERSION\n_ACEOF\n\nfi\n\n\n\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: checking whether glibc malloc hook is compilable\" >&5\n$as_echo_n \"checking whether glibc malloc hook is compilable... \" >&6; }\nif ${je_cv_glibc_malloc_hook+:} false; then :\n  $as_echo_n \"(cached) \" >&6\nelse\n  cat confdefs.h - <<_ACEOF >conftest.$ac_ext\n/* end confdefs.h.  */\n\n#include <stddef.h>\n\nextern void (* __free_hook)(void *ptr);\nextern void *(* __malloc_hook)(size_t size);\nextern void *(* __realloc_hook)(void *ptr, size_t size);\n\nint\nmain ()\n{\n\n  void *ptr = 0L;\n  if (__malloc_hook) ptr = __malloc_hook(1);\n  if (__realloc_hook) ptr = __realloc_hook(ptr, 2);\n  if (__free_hook && ptr) __free_hook(ptr);\n\n  ;\n  return 0;\n}\n_ACEOF\nif ac_fn_c_try_link \"$LINENO\"; then :\n  je_cv_glibc_malloc_hook=yes\nelse\n  je_cv_glibc_malloc_hook=no\nfi\nrm -f core conftest.err conftest.$ac_objext \\\n    conftest$ac_exeext conftest.$ac_ext\nfi\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: result: $je_cv_glibc_malloc_hook\" >&5\n$as_echo \"$je_cv_glibc_malloc_hook\" >&6; }\n\nif test \"x${je_cv_glibc_malloc_hook}\" = \"xyes\" ; then\n  $as_echo \"#define JEMALLOC_GLIBC_MALLOC_HOOK  \" >>confdefs.h\n\nfi\n\n\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: checking whether glibc memalign hook is compilable\" >&5\n$as_echo_n \"checking whether glibc memalign hook is compilable... \" >&6; }\nif ${je_cv_glibc_memalign_hook+:} false; then :\n  $as_echo_n \"(cached) \" >&6\nelse\n  cat confdefs.h - <<_ACEOF >conftest.$ac_ext\n/* end confdefs.h.  */\n\n#include <stddef.h>\n\nextern void *(* __memalign_hook)(size_t alignment, size_t size);\n\nint\nmain ()\n{\n\n  void *ptr = 0L;\n  if (__memalign_hook) ptr = __memalign_hook(16, 7);\n\n  ;\n  return 0;\n}\n_ACEOF\nif ac_fn_c_try_link \"$LINENO\"; then :\n  je_cv_glibc_memalign_hook=yes\nelse\n  je_cv_glibc_memalign_hook=no\nfi\nrm -f core conftest.err conftest.$ac_objext \\\n    conftest$ac_exeext conftest.$ac_ext\nfi\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: result: $je_cv_glibc_memalign_hook\" >&5\n$as_echo \"$je_cv_glibc_memalign_hook\" >&6; }\n\nif test \"x${je_cv_glibc_memalign_hook}\" = \"xyes\" ; then\n  $as_echo \"#define JEMALLOC_GLIBC_MEMALIGN_HOOK  \" >>confdefs.h\n\nfi\n\n\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: checking whether pthreads adaptive mutexes is compilable\" >&5\n$as_echo_n \"checking whether pthreads adaptive mutexes is compilable... \" >&6; }\nif ${je_cv_pthread_mutex_adaptive_np+:} false; then :\n  $as_echo_n \"(cached) \" >&6\nelse\n  cat confdefs.h - <<_ACEOF >conftest.$ac_ext\n/* end confdefs.h.  */\n\n#include <pthread.h>\n\nint\nmain ()\n{\n\n  pthread_mutexattr_t attr;\n  pthread_mutexattr_init(&attr);\n  pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_ADAPTIVE_NP);\n  pthread_mutexattr_destroy(&attr);\n\n  ;\n  return 0;\n}\n_ACEOF\nif ac_fn_c_try_link \"$LINENO\"; then :\n  je_cv_pthread_mutex_adaptive_np=yes\nelse\n  je_cv_pthread_mutex_adaptive_np=no\nfi\nrm -f core conftest.err conftest.$ac_objext \\\n    conftest$ac_exeext conftest.$ac_ext\nfi\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: result: $je_cv_pthread_mutex_adaptive_np\" >&5\n$as_echo \"$je_cv_pthread_mutex_adaptive_np\" >&6; }\n\nif test \"x${je_cv_pthread_mutex_adaptive_np}\" = \"xyes\" ; then\n  $as_echo \"#define JEMALLOC_HAVE_PTHREAD_MUTEX_ADAPTIVE_NP  \" >>confdefs.h\n\nfi\n\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: checking for stdbool.h that conforms to C99\" >&5\n$as_echo_n \"checking for stdbool.h that conforms to C99... \" >&6; }\nif ${ac_cv_header_stdbool_h+:} false; then :\n  $as_echo_n \"(cached) \" >&6\nelse\n  cat confdefs.h - <<_ACEOF >conftest.$ac_ext\n/* end confdefs.h.  */\n\n             #include <stdbool.h>\n             #ifndef bool\n              \"error: bool is not defined\"\n             #endif\n             #ifndef false\n              \"error: false is not defined\"\n             #endif\n             #if false\n              \"error: false is not 0\"\n             #endif\n             #ifndef true\n              \"error: true is not defined\"\n             #endif\n             #if true != 1\n              \"error: true is not 1\"\n             #endif\n             #ifndef __bool_true_false_are_defined\n              \"error: __bool_true_false_are_defined is not defined\"\n             #endif\n\n             struct s { _Bool s: 1; _Bool t; } s;\n\n             char a[true == 1 ? 1 : -1];\n             char b[false == 0 ? 1 : -1];\n             char c[__bool_true_false_are_defined == 1 ? 1 : -1];\n             char d[(bool) 0.5 == true ? 1 : -1];\n             /* See body of main program for 'e'.  */\n             char f[(_Bool) 0.0 == false ? 1 : -1];\n             char g[true];\n             char h[sizeof (_Bool)];\n             char i[sizeof s.t];\n             enum { j = false, k = true, l = false * true, m = true * 256 };\n             /* The following fails for\n                HP aC++/ANSI C B3910B A.05.55 [Dec 04 2003]. */\n             _Bool n[m];\n             char o[sizeof n == m * sizeof n[0] ? 1 : -1];\n             char p[-1 - (_Bool) 0 < 0 && -1 - (bool) 0 < 0 ? 1 : -1];\n             /* Catch a bug in an HP-UX C compiler.  See\n                http://gcc.gnu.org/ml/gcc-patches/2003-12/msg02303.html\n                http://lists.gnu.org/archive/html/bug-coreutils/2005-11/msg00161.html\n              */\n             _Bool q = true;\n             _Bool *pq = &q;\n\nint\nmain ()\n{\n\n             bool e = &s;\n             *pq |= q;\n             *pq |= ! q;\n             /* Refer to every declared value, to avoid compiler optimizations.  */\n             return (!a + !b + !c + !d + !e + !f + !g + !h + !i + !!j + !k + !!l\n                     + !m + !n + !o + !p + !q + !pq);\n\n  ;\n  return 0;\n}\n_ACEOF\nif ac_fn_c_try_compile \"$LINENO\"; then :\n  ac_cv_header_stdbool_h=yes\nelse\n  ac_cv_header_stdbool_h=no\nfi\nrm -f core conftest.err conftest.$ac_objext conftest.$ac_ext\nfi\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: result: $ac_cv_header_stdbool_h\" >&5\n$as_echo \"$ac_cv_header_stdbool_h\" >&6; }\n   ac_fn_c_check_type \"$LINENO\" \"_Bool\" \"ac_cv_type__Bool\" \"$ac_includes_default\"\nif test \"x$ac_cv_type__Bool\" = xyes; then :\n\ncat >>confdefs.h <<_ACEOF\n#define HAVE__BOOL 1\n_ACEOF\n\n\nfi\n\n\nif test $ac_cv_header_stdbool_h = yes; then\n\n$as_echo \"#define HAVE_STDBOOL_H 1\" >>confdefs.h\n\nfi\n\n\n\nac_config_commands=\"$ac_config_commands include/jemalloc/internal/private_namespace.h\"\n\nac_config_commands=\"$ac_config_commands include/jemalloc/internal/private_unnamespace.h\"\n\nac_config_commands=\"$ac_config_commands include/jemalloc/internal/public_symbols.txt\"\n\nac_config_commands=\"$ac_config_commands include/jemalloc/internal/public_namespace.h\"\n\nac_config_commands=\"$ac_config_commands include/jemalloc/internal/public_unnamespace.h\"\n\nac_config_commands=\"$ac_config_commands include/jemalloc/internal/size_classes.h\"\n\nac_config_commands=\"$ac_config_commands include/jemalloc/jemalloc_protos_jet.h\"\n\nac_config_commands=\"$ac_config_commands include/jemalloc/jemalloc_rename.h\"\n\nac_config_commands=\"$ac_config_commands include/jemalloc/jemalloc_mangle.h\"\n\nac_config_commands=\"$ac_config_commands include/jemalloc/jemalloc_mangle_jet.h\"\n\nac_config_commands=\"$ac_config_commands include/jemalloc/jemalloc.h\"\n\n\n\n\nac_config_headers=\"$ac_config_headers $cfghdrs_tup\"\n\n\n\nac_config_files=\"$ac_config_files $cfgoutputs_tup config.stamp bin/jemalloc-config bin/jemalloc.sh bin/jeprof\"\n\n\n\ncat >confcache <<\\_ACEOF\n# This file is a shell script that caches the results of configure\n# tests run on this system so they can be shared between configure\n# scripts and configure runs, see configure's option --config-cache.\n# It is not useful on other systems.  If it contains results you don't\n# want to keep, you may remove or edit it.\n#\n# config.status only pays attention to the cache file if you give it\n# the --recheck option to rerun configure.\n#\n# `ac_cv_env_foo' variables (set or unset) will be overridden when\n# loading this file, other *unset* `ac_cv_foo' will be assigned the\n# following values.\n\n_ACEOF\n\n# The following way of writing the cache mishandles newlines in values,\n# but we know of no workaround that is simple, portable, and efficient.\n# So, we kill variables containing newlines.\n# Ultrix sh set writes to stderr and can't be redirected directly,\n# and sets the high bit in the cache file unless we assign to the vars.\n(\n  for ac_var in `(set) 2>&1 | sed -n 's/^\\([a-zA-Z_][a-zA-Z0-9_]*\\)=.*/\\1/p'`; do\n    eval ac_val=\\$$ac_var\n    case $ac_val in #(\n    *${as_nl}*)\n      case $ac_var in #(\n      *_cv_*) { $as_echo \"$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline\" >&5\n$as_echo \"$as_me: WARNING: cache variable $ac_var contains a newline\" >&2;} ;;\n      esac\n      case $ac_var in #(\n      _ | IFS | as_nl) ;; #(\n      BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #(\n      *) { eval $ac_var=; unset $ac_var;} ;;\n      esac ;;\n    esac\n  done\n\n  (set) 2>&1 |\n    case $as_nl`(ac_space=' '; set) 2>&1` in #(\n    *${as_nl}ac_space=\\ *)\n      # `set' does not quote correctly, so add quotes: double-quote\n      # substitution turns \\\\\\\\ into \\\\, and sed turns \\\\ into \\.\n      sed -n \\\n\t\"s/'/'\\\\\\\\''/g;\n\t  s/^\\\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\\\)=\\\\(.*\\\\)/\\\\1='\\\\2'/p\"\n      ;; #(\n    *)\n      # `set' quotes correctly as required by POSIX, so do not add quotes.\n      sed -n \"/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p\"\n      ;;\n    esac |\n    sort\n) |\n  sed '\n     /^ac_cv_env_/b end\n     t clear\n     :clear\n     s/^\\([^=]*\\)=\\(.*[{}].*\\)$/test \"${\\1+set}\" = set || &/\n     t end\n     s/^\\([^=]*\\)=\\(.*\\)$/\\1=${\\1=\\2}/\n     :end' >>confcache\nif diff \"$cache_file\" confcache >/dev/null 2>&1; then :; else\n  if test -w \"$cache_file\"; then\n    if test \"x$cache_file\" != \"x/dev/null\"; then\n      { $as_echo \"$as_me:${as_lineno-$LINENO}: updating cache $cache_file\" >&5\n$as_echo \"$as_me: updating cache $cache_file\" >&6;}\n      if test ! -f \"$cache_file\" || test -h \"$cache_file\"; then\n\tcat confcache >\"$cache_file\"\n      else\n        case $cache_file in #(\n        */* | ?:*)\n\t  mv -f confcache \"$cache_file\"$$ &&\n\t  mv -f \"$cache_file\"$$ \"$cache_file\" ;; #(\n        *)\n\t  mv -f confcache \"$cache_file\" ;;\n\tesac\n      fi\n    fi\n  else\n    { $as_echo \"$as_me:${as_lineno-$LINENO}: not updating unwritable cache $cache_file\" >&5\n$as_echo \"$as_me: not updating unwritable cache $cache_file\" >&6;}\n  fi\nfi\nrm -f confcache\n\ntest \"x$prefix\" = xNONE && prefix=$ac_default_prefix\n# Let make expand exec_prefix.\ntest \"x$exec_prefix\" = xNONE && exec_prefix='${prefix}'\n\nDEFS=-DHAVE_CONFIG_H\n\nac_libobjs=\nac_ltlibobjs=\nU=\nfor ac_i in : $LIBOBJS; do test \"x$ac_i\" = x: && continue\n  # 1. Remove the extension, and $U if already installed.\n  ac_script='s/\\$U\\././;s/\\.o$//;s/\\.obj$//'\n  ac_i=`$as_echo \"$ac_i\" | sed \"$ac_script\"`\n  # 2. Prepend LIBOBJDIR.  When used with automake>=1.10 LIBOBJDIR\n  #    will be set to the directory where LIBOBJS objects are built.\n  as_fn_append ac_libobjs \" \\${LIBOBJDIR}$ac_i\\$U.$ac_objext\"\n  as_fn_append ac_ltlibobjs \" \\${LIBOBJDIR}$ac_i\"'$U.lo'\ndone\nLIBOBJS=$ac_libobjs\n\nLTLIBOBJS=$ac_ltlibobjs\n\n\n\n\n: \"${CONFIG_STATUS=./config.status}\"\nac_write_fail=0\nac_clean_files_save=$ac_clean_files\nac_clean_files=\"$ac_clean_files $CONFIG_STATUS\"\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: creating $CONFIG_STATUS\" >&5\n$as_echo \"$as_me: creating $CONFIG_STATUS\" >&6;}\nas_write_fail=0\ncat >$CONFIG_STATUS <<_ASEOF || as_write_fail=1\n#! $SHELL\n# Generated by $as_me.\n# Run this file to recreate the current configuration.\n# Compiler output produced by configure, useful for debugging\n# configure, is in config.log if it exists.\n\ndebug=false\nac_cs_recheck=false\nac_cs_silent=false\n\nSHELL=\\${CONFIG_SHELL-$SHELL}\nexport SHELL\n_ASEOF\ncat >>$CONFIG_STATUS <<\\_ASEOF || as_write_fail=1\n## -------------------- ##\n## M4sh Initialization. ##\n## -------------------- ##\n\n# Be more Bourne compatible\nDUALCASE=1; export DUALCASE # for MKS sh\nif test -n \"${ZSH_VERSION+set}\" && (emulate sh) >/dev/null 2>&1; then :\n  emulate sh\n  NULLCMD=:\n  # Pre-4.2 versions of Zsh do word splitting on ${1+\"$@\"}, which\n  # is contrary to our usage.  Disable this feature.\n  alias -g '${1+\"$@\"}'='\"$@\"'\n  setopt NO_GLOB_SUBST\nelse\n  case `(set -o) 2>/dev/null` in #(\n  *posix*) :\n    set -o posix ;; #(\n  *) :\n     ;;\nesac\nfi\n\n\nas_nl='\n'\nexport as_nl\n# Printing a long string crashes Solaris 7 /usr/bin/printf.\nas_echo='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\'\nas_echo=$as_echo$as_echo$as_echo$as_echo$as_echo\nas_echo=$as_echo$as_echo$as_echo$as_echo$as_echo$as_echo\n# Prefer a ksh shell builtin over an external printf program on Solaris,\n# but without wasting forks for bash or zsh.\nif test -z \"$BASH_VERSION$ZSH_VERSION\" \\\n    && (test \"X`print -r -- $as_echo`\" = \"X$as_echo\") 2>/dev/null; then\n  as_echo='print -r --'\n  as_echo_n='print -rn --'\nelif (test \"X`printf %s $as_echo`\" = \"X$as_echo\") 2>/dev/null; then\n  as_echo='printf %s\\n'\n  as_echo_n='printf %s'\nelse\n  if test \"X`(/usr/ucb/echo -n -n $as_echo) 2>/dev/null`\" = \"X-n $as_echo\"; then\n    as_echo_body='eval /usr/ucb/echo -n \"$1$as_nl\"'\n    as_echo_n='/usr/ucb/echo -n'\n  else\n    as_echo_body='eval expr \"X$1\" : \"X\\\\(.*\\\\)\"'\n    as_echo_n_body='eval\n      arg=$1;\n      case $arg in #(\n      *\"$as_nl\"*)\n\texpr \"X$arg\" : \"X\\\\(.*\\\\)$as_nl\";\n\targ=`expr \"X$arg\" : \".*$as_nl\\\\(.*\\\\)\"`;;\n      esac;\n      expr \"X$arg\" : \"X\\\\(.*\\\\)\" | tr -d \"$as_nl\"\n    '\n    export as_echo_n_body\n    as_echo_n='sh -c $as_echo_n_body as_echo'\n  fi\n  export as_echo_body\n  as_echo='sh -c $as_echo_body as_echo'\nfi\n\n# The user is always right.\nif test \"${PATH_SEPARATOR+set}\" != set; then\n  PATH_SEPARATOR=:\n  (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && {\n    (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 ||\n      PATH_SEPARATOR=';'\n  }\nfi\n\n\n# IFS\n# We need space, tab and new line, in precisely that order.  Quoting is\n# there to prevent editors from complaining about space-tab.\n# (If _AS_PATH_WALK were called with IFS unset, it would disable word\n# splitting by setting IFS to empty value.)\nIFS=\" \"\"\t$as_nl\"\n\n# Find who we are.  Look in the path if we contain no directory separator.\nas_myself=\ncase $0 in #((\n  *[\\\\/]* ) as_myself=$0 ;;\n  *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR\nfor as_dir in $PATH\ndo\n  IFS=$as_save_IFS\n  test -z \"$as_dir\" && as_dir=.\n    test -r \"$as_dir/$0\" && as_myself=$as_dir/$0 && break\n  done\nIFS=$as_save_IFS\n\n     ;;\nesac\n# We did not find ourselves, most probably we were run as `sh COMMAND'\n# in which case we are not to be found in the path.\nif test \"x$as_myself\" = x; then\n  as_myself=$0\nfi\nif test ! -f \"$as_myself\"; then\n  $as_echo \"$as_myself: error: cannot find myself; rerun with an absolute file name\" >&2\n  exit 1\nfi\n\n# Unset variables that we do not need and which cause bugs (e.g. in\n# pre-3.0 UWIN ksh).  But do not cause bugs in bash 2.01; the \"|| exit 1\"\n# suppresses any \"Segmentation fault\" message there.  '((' could\n# trigger a bug in pdksh 5.2.14.\nfor as_var in BASH_ENV ENV MAIL MAILPATH\ndo eval test x\\${$as_var+set} = xset \\\n  && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || :\ndone\nPS1='$ '\nPS2='> '\nPS4='+ '\n\n# NLS nuisances.\nLC_ALL=C\nexport LC_ALL\nLANGUAGE=C\nexport LANGUAGE\n\n# CDPATH.\n(unset CDPATH) >/dev/null 2>&1 && unset CDPATH\n\n\n# as_fn_error STATUS ERROR [LINENO LOG_FD]\n# ----------------------------------------\n# Output \"`basename $0`: error: ERROR\" to stderr. If LINENO and LOG_FD are\n# provided, also output the error to LOG_FD, referencing LINENO. Then exit the\n# script with STATUS, using 1 if that was 0.\nas_fn_error ()\n{\n  as_status=$1; test $as_status -eq 0 && as_status=1\n  if test \"$4\"; then\n    as_lineno=${as_lineno-\"$3\"} as_lineno_stack=as_lineno_stack=$as_lineno_stack\n    $as_echo \"$as_me:${as_lineno-$LINENO}: error: $2\" >&$4\n  fi\n  $as_echo \"$as_me: error: $2\" >&2\n  as_fn_exit $as_status\n} # as_fn_error\n\n\n# as_fn_set_status STATUS\n# -----------------------\n# Set $? to STATUS, without forking.\nas_fn_set_status ()\n{\n  return $1\n} # as_fn_set_status\n\n# as_fn_exit STATUS\n# -----------------\n# Exit the shell with STATUS, even in a \"trap 0\" or \"set -e\" context.\nas_fn_exit ()\n{\n  set +e\n  as_fn_set_status $1\n  exit $1\n} # as_fn_exit\n\n# as_fn_unset VAR\n# ---------------\n# Portably unset VAR.\nas_fn_unset ()\n{\n  { eval $1=; unset $1;}\n}\nas_unset=as_fn_unset\n# as_fn_append VAR VALUE\n# ----------------------\n# Append the text in VALUE to the end of the definition contained in VAR. Take\n# advantage of any shell optimizations that allow amortized linear growth over\n# repeated appends, instead of the typical quadratic growth present in naive\n# implementations.\nif (eval \"as_var=1; as_var+=2; test x\\$as_var = x12\") 2>/dev/null; then :\n  eval 'as_fn_append ()\n  {\n    eval $1+=\\$2\n  }'\nelse\n  as_fn_append ()\n  {\n    eval $1=\\$$1\\$2\n  }\nfi # as_fn_append\n\n# as_fn_arith ARG...\n# ------------------\n# Perform arithmetic evaluation on the ARGs, and store the result in the\n# global $as_val. Take advantage of shells that can avoid forks. The arguments\n# must be portable across $(()) and expr.\nif (eval \"test \\$(( 1 + 1 )) = 2\") 2>/dev/null; then :\n  eval 'as_fn_arith ()\n  {\n    as_val=$(( $* ))\n  }'\nelse\n  as_fn_arith ()\n  {\n    as_val=`expr \"$@\" || test $? -eq 1`\n  }\nfi # as_fn_arith\n\n\nif expr a : '\\(a\\)' >/dev/null 2>&1 &&\n   test \"X`expr 00001 : '.*\\(...\\)'`\" = X001; then\n  as_expr=expr\nelse\n  as_expr=false\nfi\n\nif (basename -- /) >/dev/null 2>&1 && test \"X`basename -- / 2>&1`\" = \"X/\"; then\n  as_basename=basename\nelse\n  as_basename=false\nfi\n\nif (as_dir=`dirname -- /` && test \"X$as_dir\" = X/) >/dev/null 2>&1; then\n  as_dirname=dirname\nelse\n  as_dirname=false\nfi\n\nas_me=`$as_basename -- \"$0\" ||\n$as_expr X/\"$0\" : '.*/\\([^/][^/]*\\)/*$' \\| \\\n\t X\"$0\" : 'X\\(//\\)$' \\| \\\n\t X\"$0\" : 'X\\(/\\)' \\| . 2>/dev/null ||\n$as_echo X/\"$0\" |\n    sed '/^.*\\/\\([^/][^/]*\\)\\/*$/{\n\t    s//\\1/\n\t    q\n\t  }\n\t  /^X\\/\\(\\/\\/\\)$/{\n\t    s//\\1/\n\t    q\n\t  }\n\t  /^X\\/\\(\\/\\).*/{\n\t    s//\\1/\n\t    q\n\t  }\n\t  s/.*/./; q'`\n\n# Avoid depending upon Character Ranges.\nas_cr_letters='abcdefghijklmnopqrstuvwxyz'\nas_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ'\nas_cr_Letters=$as_cr_letters$as_cr_LETTERS\nas_cr_digits='0123456789'\nas_cr_alnum=$as_cr_Letters$as_cr_digits\n\nECHO_C= ECHO_N= ECHO_T=\ncase `echo -n x` in #(((((\n-n*)\n  case `echo 'xy\\c'` in\n  *c*) ECHO_T='\t';;\t# ECHO_T is single tab character.\n  xy)  ECHO_C='\\c';;\n  *)   echo `echo ksh88 bug on AIX 6.1` > /dev/null\n       ECHO_T='\t';;\n  esac;;\n*)\n  ECHO_N='-n';;\nesac\n\nrm -f conf$$ conf$$.exe conf$$.file\nif test -d conf$$.dir; then\n  rm -f conf$$.dir/conf$$.file\nelse\n  rm -f conf$$.dir\n  mkdir conf$$.dir 2>/dev/null\nfi\nif (echo >conf$$.file) 2>/dev/null; then\n  if ln -s conf$$.file conf$$ 2>/dev/null; then\n    as_ln_s='ln -s'\n    # ... but there are two gotchas:\n    # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail.\n    # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable.\n    # In both cases, we have to default to `cp -pR'.\n    ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe ||\n      as_ln_s='cp -pR'\n  elif ln conf$$.file conf$$ 2>/dev/null; then\n    as_ln_s=ln\n  else\n    as_ln_s='cp -pR'\n  fi\nelse\n  as_ln_s='cp -pR'\nfi\nrm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file\nrmdir conf$$.dir 2>/dev/null\n\n\n# as_fn_mkdir_p\n# -------------\n# Create \"$as_dir\" as a directory, including parents if necessary.\nas_fn_mkdir_p ()\n{\n\n  case $as_dir in #(\n  -*) as_dir=./$as_dir;;\n  esac\n  test -d \"$as_dir\" || eval $as_mkdir_p || {\n    as_dirs=\n    while :; do\n      case $as_dir in #(\n      *\\'*) as_qdir=`$as_echo \"$as_dir\" | sed \"s/'/'\\\\\\\\\\\\\\\\''/g\"`;; #'(\n      *) as_qdir=$as_dir;;\n      esac\n      as_dirs=\"'$as_qdir' $as_dirs\"\n      as_dir=`$as_dirname -- \"$as_dir\" ||\n$as_expr X\"$as_dir\" : 'X\\(.*[^/]\\)//*[^/][^/]*/*$' \\| \\\n\t X\"$as_dir\" : 'X\\(//\\)[^/]' \\| \\\n\t X\"$as_dir\" : 'X\\(//\\)$' \\| \\\n\t X\"$as_dir\" : 'X\\(/\\)' \\| . 2>/dev/null ||\n$as_echo X\"$as_dir\" |\n    sed '/^X\\(.*[^/]\\)\\/\\/*[^/][^/]*\\/*$/{\n\t    s//\\1/\n\t    q\n\t  }\n\t  /^X\\(\\/\\/\\)[^/].*/{\n\t    s//\\1/\n\t    q\n\t  }\n\t  /^X\\(\\/\\/\\)$/{\n\t    s//\\1/\n\t    q\n\t  }\n\t  /^X\\(\\/\\).*/{\n\t    s//\\1/\n\t    q\n\t  }\n\t  s/.*/./; q'`\n      test -d \"$as_dir\" && break\n    done\n    test -z \"$as_dirs\" || eval \"mkdir $as_dirs\"\n  } || test -d \"$as_dir\" || as_fn_error $? \"cannot create directory $as_dir\"\n\n\n} # as_fn_mkdir_p\nif mkdir -p . 2>/dev/null; then\n  as_mkdir_p='mkdir -p \"$as_dir\"'\nelse\n  test -d ./-p && rmdir ./-p\n  as_mkdir_p=false\nfi\n\n\n# as_fn_executable_p FILE\n# -----------------------\n# Test if FILE is an executable regular file.\nas_fn_executable_p ()\n{\n  test -f \"$1\" && test -x \"$1\"\n} # as_fn_executable_p\nas_test_x='test -x'\nas_executable_p=as_fn_executable_p\n\n# Sed expression to map a string onto a valid CPP name.\nas_tr_cpp=\"eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'\"\n\n# Sed expression to map a string onto a valid variable name.\nas_tr_sh=\"eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'\"\n\n\nexec 6>&1\n## ----------------------------------- ##\n## Main body of $CONFIG_STATUS script. ##\n## ----------------------------------- ##\n_ASEOF\ntest $as_write_fail = 0 && chmod +x $CONFIG_STATUS || ac_write_fail=1\n\ncat >>$CONFIG_STATUS <<\\_ACEOF || ac_write_fail=1\n# Save the log message, to keep $0 and so on meaningful, and to\n# report actual input values of CONFIG_FILES etc. instead of their\n# values after options handling.\nac_log=\"\nThis file was extended by $as_me, which was\ngenerated by GNU Autoconf 2.69.  Invocation command line was\n\n  CONFIG_FILES    = $CONFIG_FILES\n  CONFIG_HEADERS  = $CONFIG_HEADERS\n  CONFIG_LINKS    = $CONFIG_LINKS\n  CONFIG_COMMANDS = $CONFIG_COMMANDS\n  $ $0 $@\n\non `(hostname || uname -n) 2>/dev/null | sed 1q`\n\"\n\n_ACEOF\n\ncase $ac_config_files in *\"\n\"*) set x $ac_config_files; shift; ac_config_files=$*;;\nesac\n\ncase $ac_config_headers in *\"\n\"*) set x $ac_config_headers; shift; ac_config_headers=$*;;\nesac\n\n\ncat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1\n# Files that config.status was made for.\nconfig_files=\"$ac_config_files\"\nconfig_headers=\"$ac_config_headers\"\nconfig_commands=\"$ac_config_commands\"\n\n_ACEOF\n\ncat >>$CONFIG_STATUS <<\\_ACEOF || ac_write_fail=1\nac_cs_usage=\"\\\n\\`$as_me' instantiates files and other configuration actions\nfrom templates according to the current configuration.  Unless the files\nand actions are specified as TAGs, all are instantiated by default.\n\nUsage: $0 [OPTION]... [TAG]...\n\n  -h, --help       print this help, then exit\n  -V, --version    print version number and configuration settings, then exit\n      --config     print configuration, then exit\n  -q, --quiet, --silent\n                   do not print progress messages\n  -d, --debug      don't remove temporary files\n      --recheck    update $as_me by reconfiguring in the same conditions\n      --file=FILE[:TEMPLATE]\n                   instantiate the configuration file FILE\n      --header=FILE[:TEMPLATE]\n                   instantiate the configuration header FILE\n\nConfiguration files:\n$config_files\n\nConfiguration headers:\n$config_headers\n\nConfiguration commands:\n$config_commands\n\nReport bugs to the package provider.\"\n\n_ACEOF\ncat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1\nac_cs_config=\"`$as_echo \"$ac_configure_args\" | sed 's/^ //; s/[\\\\\"\"\\`\\$]/\\\\\\\\&/g'`\"\nac_cs_version=\"\\\\\nconfig.status\nconfigured by $0, generated by GNU Autoconf 2.69,\n  with options \\\\\"\\$ac_cs_config\\\\\"\n\nCopyright (C) 2012 Free Software Foundation, Inc.\nThis config.status script is free software; the Free Software Foundation\ngives unlimited permission to copy, distribute and modify it.\"\n\nac_pwd='$ac_pwd'\nsrcdir='$srcdir'\nINSTALL='$INSTALL'\ntest -n \"\\$AWK\" || AWK=awk\n_ACEOF\n\ncat >>$CONFIG_STATUS <<\\_ACEOF || ac_write_fail=1\n# The default lists apply if the user does not specify any file.\nac_need_defaults=:\nwhile test $# != 0\ndo\n  case $1 in\n  --*=?*)\n    ac_option=`expr \"X$1\" : 'X\\([^=]*\\)='`\n    ac_optarg=`expr \"X$1\" : 'X[^=]*=\\(.*\\)'`\n    ac_shift=:\n    ;;\n  --*=)\n    ac_option=`expr \"X$1\" : 'X\\([^=]*\\)='`\n    ac_optarg=\n    ac_shift=:\n    ;;\n  *)\n    ac_option=$1\n    ac_optarg=$2\n    ac_shift=shift\n    ;;\n  esac\n\n  case $ac_option in\n  # Handling of the options.\n  -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r)\n    ac_cs_recheck=: ;;\n  --version | --versio | --versi | --vers | --ver | --ve | --v | -V )\n    $as_echo \"$ac_cs_version\"; exit ;;\n  --config | --confi | --conf | --con | --co | --c )\n    $as_echo \"$ac_cs_config\"; exit ;;\n  --debug | --debu | --deb | --de | --d | -d )\n    debug=: ;;\n  --file | --fil | --fi | --f )\n    $ac_shift\n    case $ac_optarg in\n    *\\'*) ac_optarg=`$as_echo \"$ac_optarg\" | sed \"s/'/'\\\\\\\\\\\\\\\\''/g\"` ;;\n    '') as_fn_error $? \"missing file argument\" ;;\n    esac\n    as_fn_append CONFIG_FILES \" '$ac_optarg'\"\n    ac_need_defaults=false;;\n  --header | --heade | --head | --hea )\n    $ac_shift\n    case $ac_optarg in\n    *\\'*) ac_optarg=`$as_echo \"$ac_optarg\" | sed \"s/'/'\\\\\\\\\\\\\\\\''/g\"` ;;\n    esac\n    as_fn_append CONFIG_HEADERS \" '$ac_optarg'\"\n    ac_need_defaults=false;;\n  --he | --h)\n    # Conflict between --help and --header\n    as_fn_error $? \"ambiguous option: \\`$1'\nTry \\`$0 --help' for more information.\";;\n  --help | --hel | -h )\n    $as_echo \"$ac_cs_usage\"; exit ;;\n  -q | -quiet | --quiet | --quie | --qui | --qu | --q \\\n  | -silent | --silent | --silen | --sile | --sil | --si | --s)\n    ac_cs_silent=: ;;\n\n  # This is an error.\n  -*) as_fn_error $? \"unrecognized option: \\`$1'\nTry \\`$0 --help' for more information.\" ;;\n\n  *) as_fn_append ac_config_targets \" $1\"\n     ac_need_defaults=false ;;\n\n  esac\n  shift\ndone\n\nac_configure_extra_args=\n\nif $ac_cs_silent; then\n  exec 6>/dev/null\n  ac_configure_extra_args=\"$ac_configure_extra_args --silent\"\nfi\n\n_ACEOF\ncat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1\nif \\$ac_cs_recheck; then\n  set X $SHELL '$0' $ac_configure_args \\$ac_configure_extra_args --no-create --no-recursion\n  shift\n  \\$as_echo \"running CONFIG_SHELL=$SHELL \\$*\" >&6\n  CONFIG_SHELL='$SHELL'\n  export CONFIG_SHELL\n  exec \"\\$@\"\nfi\n\n_ACEOF\ncat >>$CONFIG_STATUS <<\\_ACEOF || ac_write_fail=1\nexec 5>>config.log\n{\n  echo\n  sed 'h;s/./-/g;s/^.../## /;s/...$/ ##/;p;x;p;x' <<_ASBOX\n## Running $as_me. ##\n_ASBOX\n  $as_echo \"$ac_log\"\n} >&5\n\n_ACEOF\ncat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1\n#\n# INIT-COMMANDS\n#\n\n  srcdir=\"${srcdir}\"\n  objroot=\"${objroot}\"\n\n\n  srcdir=\"${srcdir}\"\n  objroot=\"${objroot}\"\n\n\n  srcdir=\"${srcdir}\"\n  objroot=\"${objroot}\"\n  mangling_map=\"${mangling_map}\"\n  public_syms=\"${public_syms}\"\n  JEMALLOC_PREFIX=\"${JEMALLOC_PREFIX}\"\n\n\n  srcdir=\"${srcdir}\"\n  objroot=\"${objroot}\"\n\n\n  srcdir=\"${srcdir}\"\n  objroot=\"${objroot}\"\n\n\n  SHELL=\"${SHELL}\"\n  srcdir=\"${srcdir}\"\n  objroot=\"${objroot}\"\n  LG_QUANTA=\"${LG_QUANTA}\"\n  LG_TINY_MIN=${LG_TINY_MIN}\n  LG_PAGE_SIZES=\"${LG_PAGE_SIZES}\"\n  LG_SIZE_CLASS_GROUP=${LG_SIZE_CLASS_GROUP}\n\n\n  srcdir=\"${srcdir}\"\n  objroot=\"${objroot}\"\n\n\n  srcdir=\"${srcdir}\"\n  objroot=\"${objroot}\"\n\n\n  srcdir=\"${srcdir}\"\n  objroot=\"${objroot}\"\n\n\n  srcdir=\"${srcdir}\"\n  objroot=\"${objroot}\"\n\n\n  srcdir=\"${srcdir}\"\n  objroot=\"${objroot}\"\n  install_suffix=\"${install_suffix}\"\n\n\n_ACEOF\n\ncat >>$CONFIG_STATUS <<\\_ACEOF || ac_write_fail=1\n\n# Handling of arguments.\nfor ac_config_target in $ac_config_targets\ndo\n  case $ac_config_target in\n    \"include/jemalloc/internal/private_namespace.h\") CONFIG_COMMANDS=\"$CONFIG_COMMANDS include/jemalloc/internal/private_namespace.h\" ;;\n    \"include/jemalloc/internal/private_unnamespace.h\") CONFIG_COMMANDS=\"$CONFIG_COMMANDS include/jemalloc/internal/private_unnamespace.h\" ;;\n    \"include/jemalloc/internal/public_symbols.txt\") CONFIG_COMMANDS=\"$CONFIG_COMMANDS include/jemalloc/internal/public_symbols.txt\" ;;\n    \"include/jemalloc/internal/public_namespace.h\") CONFIG_COMMANDS=\"$CONFIG_COMMANDS include/jemalloc/internal/public_namespace.h\" ;;\n    \"include/jemalloc/internal/public_unnamespace.h\") CONFIG_COMMANDS=\"$CONFIG_COMMANDS include/jemalloc/internal/public_unnamespace.h\" ;;\n    \"include/jemalloc/internal/size_classes.h\") CONFIG_COMMANDS=\"$CONFIG_COMMANDS include/jemalloc/internal/size_classes.h\" ;;\n    \"include/jemalloc/jemalloc_protos_jet.h\") CONFIG_COMMANDS=\"$CONFIG_COMMANDS include/jemalloc/jemalloc_protos_jet.h\" ;;\n    \"include/jemalloc/jemalloc_rename.h\") CONFIG_COMMANDS=\"$CONFIG_COMMANDS include/jemalloc/jemalloc_rename.h\" ;;\n    \"include/jemalloc/jemalloc_mangle.h\") CONFIG_COMMANDS=\"$CONFIG_COMMANDS include/jemalloc/jemalloc_mangle.h\" ;;\n    \"include/jemalloc/jemalloc_mangle_jet.h\") CONFIG_COMMANDS=\"$CONFIG_COMMANDS include/jemalloc/jemalloc_mangle_jet.h\" ;;\n    \"include/jemalloc/jemalloc.h\") CONFIG_COMMANDS=\"$CONFIG_COMMANDS include/jemalloc/jemalloc.h\" ;;\n    \"$cfghdrs_tup\") CONFIG_HEADERS=\"$CONFIG_HEADERS $cfghdrs_tup\" ;;\n    \"$cfgoutputs_tup\") CONFIG_FILES=\"$CONFIG_FILES $cfgoutputs_tup\" ;;\n    \"config.stamp\") CONFIG_FILES=\"$CONFIG_FILES config.stamp\" ;;\n    \"bin/jemalloc-config\") CONFIG_FILES=\"$CONFIG_FILES bin/jemalloc-config\" ;;\n    \"bin/jemalloc.sh\") CONFIG_FILES=\"$CONFIG_FILES bin/jemalloc.sh\" ;;\n    \"bin/jeprof\") CONFIG_FILES=\"$CONFIG_FILES bin/jeprof\" ;;\n\n  *) as_fn_error $? \"invalid argument: \\`$ac_config_target'\" \"$LINENO\" 5;;\n  esac\ndone\n\n\n# If the user did not use the arguments to specify the items to instantiate,\n# then the envvar interface is used.  Set only those that are not.\n# We use the long form for the default assignment because of an extremely\n# bizarre bug on SunOS 4.1.3.\nif $ac_need_defaults; then\n  test \"${CONFIG_FILES+set}\" = set || CONFIG_FILES=$config_files\n  test \"${CONFIG_HEADERS+set}\" = set || CONFIG_HEADERS=$config_headers\n  test \"${CONFIG_COMMANDS+set}\" = set || CONFIG_COMMANDS=$config_commands\nfi\n\n# Have a temporary directory for convenience.  Make it in the build tree\n# simply because there is no reason against having it here, and in addition,\n# creating and moving files from /tmp can sometimes cause problems.\n# Hook for its removal unless debugging.\n# Note that there is a small window in which the directory will not be cleaned:\n# after its creation but before its name has been assigned to `$tmp'.\n$debug ||\n{\n  tmp= ac_tmp=\n  trap 'exit_status=$?\n  : \"${ac_tmp:=$tmp}\"\n  { test ! -d \"$ac_tmp\" || rm -fr \"$ac_tmp\"; } && exit $exit_status\n' 0\n  trap 'as_fn_exit 1' 1 2 13 15\n}\n# Create a (secure) tmp directory for tmp files.\n\n{\n  tmp=`(umask 077 && mktemp -d \"./confXXXXXX\") 2>/dev/null` &&\n  test -d \"$tmp\"\n}  ||\n{\n  tmp=./conf$$-$RANDOM\n  (umask 077 && mkdir \"$tmp\")\n} || as_fn_error $? \"cannot create a temporary directory in .\" \"$LINENO\" 5\nac_tmp=$tmp\n\n# Set up the scripts for CONFIG_FILES section.\n# No need to generate them if there are no CONFIG_FILES.\n# This happens for instance with `./config.status config.h'.\nif test -n \"$CONFIG_FILES\"; then\n\n\nac_cr=`echo X | tr X '\\015'`\n# On cygwin, bash can eat \\r inside `` if the user requested igncr.\n# But we know of no other shell where ac_cr would be empty at this\n# point, so we can use a bashism as a fallback.\nif test \"x$ac_cr\" = x; then\n  eval ac_cr=\\$\\'\\\\r\\'\nfi\nac_cs_awk_cr=`$AWK 'BEGIN { print \"a\\rb\" }' </dev/null 2>/dev/null`\nif test \"$ac_cs_awk_cr\" = \"a${ac_cr}b\"; then\n  ac_cs_awk_cr='\\\\r'\nelse\n  ac_cs_awk_cr=$ac_cr\nfi\n\necho 'BEGIN {' >\"$ac_tmp/subs1.awk\" &&\n_ACEOF\n\n\n{\n  echo \"cat >conf$$subs.awk <<_ACEOF\" &&\n  echo \"$ac_subst_vars\" | sed 's/.*/&!$&$ac_delim/' &&\n  echo \"_ACEOF\"\n} >conf$$subs.sh ||\n  as_fn_error $? \"could not make $CONFIG_STATUS\" \"$LINENO\" 5\nac_delim_num=`echo \"$ac_subst_vars\" | grep -c '^'`\nac_delim='%!_!# '\nfor ac_last_try in false false false false false :; do\n  . ./conf$$subs.sh ||\n    as_fn_error $? \"could not make $CONFIG_STATUS\" \"$LINENO\" 5\n\n  ac_delim_n=`sed -n \"s/.*$ac_delim\\$/X/p\" conf$$subs.awk | grep -c X`\n  if test $ac_delim_n = $ac_delim_num; then\n    break\n  elif $ac_last_try; then\n    as_fn_error $? \"could not make $CONFIG_STATUS\" \"$LINENO\" 5\n  else\n    ac_delim=\"$ac_delim!$ac_delim _$ac_delim!! \"\n  fi\ndone\nrm -f conf$$subs.sh\n\ncat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1\ncat >>\"\\$ac_tmp/subs1.awk\" <<\\\\_ACAWK &&\n_ACEOF\nsed -n '\nh\ns/^/S[\"/; s/!.*/\"]=/\np\ng\ns/^[^!]*!//\n:repl\nt repl\ns/'\"$ac_delim\"'$//\nt delim\n:nl\nh\ns/\\(.\\{148\\}\\)..*/\\1/\nt more1\ns/[\"\\\\]/\\\\&/g; s/^/\"/; s/$/\\\\n\"\\\\/\np\nn\nb repl\n:more1\ns/[\"\\\\]/\\\\&/g; s/^/\"/; s/$/\"\\\\/\np\ng\ns/.\\{148\\}//\nt nl\n:delim\nh\ns/\\(.\\{148\\}\\)..*/\\1/\nt more2\ns/[\"\\\\]/\\\\&/g; s/^/\"/; s/$/\"/\np\nb\n:more2\ns/[\"\\\\]/\\\\&/g; s/^/\"/; s/$/\"\\\\/\np\ng\ns/.\\{148\\}//\nt delim\n' <conf$$subs.awk | sed '\n/^[^\"\"]/{\n  N\n  s/\\n//\n}\n' >>$CONFIG_STATUS || ac_write_fail=1\nrm -f conf$$subs.awk\ncat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1\n_ACAWK\ncat >>\"\\$ac_tmp/subs1.awk\" <<_ACAWK &&\n  for (key in S) S_is_set[key] = 1\n  FS = \"\u0007\"\n\n}\n{\n  line = $ 0\n  nfields = split(line, field, \"@\")\n  substed = 0\n  len = length(field[1])\n  for (i = 2; i < nfields; i++) {\n    key = field[i]\n    keylen = length(key)\n    if (S_is_set[key]) {\n      value = S[key]\n      line = substr(line, 1, len) \"\" value \"\" substr(line, len + keylen + 3)\n      len += length(value) + length(field[++i])\n      substed = 1\n    } else\n      len += 1 + keylen\n  }\n\n  print line\n}\n\n_ACAWK\n_ACEOF\ncat >>$CONFIG_STATUS <<\\_ACEOF || ac_write_fail=1\nif sed \"s/$ac_cr//\" < /dev/null > /dev/null 2>&1; then\n  sed \"s/$ac_cr\\$//; s/$ac_cr/$ac_cs_awk_cr/g\"\nelse\n  cat\nfi < \"$ac_tmp/subs1.awk\" > \"$ac_tmp/subs.awk\" \\\n  || as_fn_error $? \"could not setup config files machinery\" \"$LINENO\" 5\n_ACEOF\n\n# VPATH may cause trouble with some makes, so we remove sole $(srcdir),\n# ${srcdir} and @srcdir@ entries from VPATH if srcdir is \".\", strip leading and\n# trailing colons and then remove the whole line if VPATH becomes empty\n# (actually we leave an empty line to preserve line numbers).\nif test \"x$srcdir\" = x.; then\n  ac_vpsub='/^[\t ]*VPATH[\t ]*=[\t ]*/{\nh\ns///\ns/^/:/\ns/[\t ]*$/:/\ns/:\\$(srcdir):/:/g\ns/:\\${srcdir}:/:/g\ns/:@srcdir@:/:/g\ns/^:*//\ns/:*$//\nx\ns/\\(=[\t ]*\\).*/\\1/\nG\ns/\\n//\ns/^[^=]*=[\t ]*$//\n}'\nfi\n\ncat >>$CONFIG_STATUS <<\\_ACEOF || ac_write_fail=1\nfi # test -n \"$CONFIG_FILES\"\n\n# Set up the scripts for CONFIG_HEADERS section.\n# No need to generate them if there are no CONFIG_HEADERS.\n# This happens for instance with `./config.status Makefile'.\nif test -n \"$CONFIG_HEADERS\"; then\ncat >\"$ac_tmp/defines.awk\" <<\\_ACAWK ||\nBEGIN {\n_ACEOF\n\n# Transform confdefs.h into an awk script `defines.awk', embedded as\n# here-document in config.status, that substitutes the proper values into\n# config.h.in to produce config.h.\n\n# Create a delimiter string that does not exist in confdefs.h, to ease\n# handling of long lines.\nac_delim='%!_!# '\nfor ac_last_try in false false :; do\n  ac_tt=`sed -n \"/$ac_delim/p\" confdefs.h`\n  if test -z \"$ac_tt\"; then\n    break\n  elif $ac_last_try; then\n    as_fn_error $? \"could not make $CONFIG_HEADERS\" \"$LINENO\" 5\n  else\n    ac_delim=\"$ac_delim!$ac_delim _$ac_delim!! \"\n  fi\ndone\n\n# For the awk script, D is an array of macro values keyed by name,\n# likewise P contains macro parameters if any.  Preserve backslash\n# newline sequences.\n\nac_word_re=[_$as_cr_Letters][_$as_cr_alnum]*\nsed -n '\ns/.\\{148\\}/&'\"$ac_delim\"'/g\nt rset\n:rset\ns/^[\t ]*#[\t ]*define[\t ][\t ]*/ /\nt def\nd\n:def\ns/\\\\$//\nt bsnl\ns/[\"\\\\]/\\\\&/g\ns/^ \\('\"$ac_word_re\"'\\)\\(([^()]*)\\)[\t ]*\\(.*\\)/P[\"\\1\"]=\"\\2\"\\\nD[\"\\1\"]=\" \\3\"/p\ns/^ \\('\"$ac_word_re\"'\\)[\t ]*\\(.*\\)/D[\"\\1\"]=\" \\2\"/p\nd\n:bsnl\ns/[\"\\\\]/\\\\&/g\ns/^ \\('\"$ac_word_re\"'\\)\\(([^()]*)\\)[\t ]*\\(.*\\)/P[\"\\1\"]=\"\\2\"\\\nD[\"\\1\"]=\" \\3\\\\\\\\\\\\n\"\\\\/p\nt cont\ns/^ \\('\"$ac_word_re\"'\\)[\t ]*\\(.*\\)/D[\"\\1\"]=\" \\2\\\\\\\\\\\\n\"\\\\/p\nt cont\nd\n:cont\nn\ns/.\\{148\\}/&'\"$ac_delim\"'/g\nt clear\n:clear\ns/\\\\$//\nt bsnlc\ns/[\"\\\\]/\\\\&/g; s/^/\"/; s/$/\"/p\nd\n:bsnlc\ns/[\"\\\\]/\\\\&/g; s/^/\"/; s/$/\\\\\\\\\\\\n\"\\\\/p\nb cont\n' <confdefs.h | sed '\ns/'\"$ac_delim\"'/\"\\\\\\\n\"/g' >>$CONFIG_STATUS || ac_write_fail=1\n\ncat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1\n  for (key in D) D_is_set[key] = 1\n  FS = \"\u0007\"\n}\n/^[\\t ]*#[\\t ]*(define|undef)[\\t ]+$ac_word_re([\\t (]|\\$)/ {\n  line = \\$ 0\n  split(line, arg, \" \")\n  if (arg[1] == \"#\") {\n    defundef = arg[2]\n    mac1 = arg[3]\n  } else {\n    defundef = substr(arg[1], 2)\n    mac1 = arg[2]\n  }\n  split(mac1, mac2, \"(\") #)\n  macro = mac2[1]\n  prefix = substr(line, 1, index(line, defundef) - 1)\n  if (D_is_set[macro]) {\n    # Preserve the white space surrounding the \"#\".\n    print prefix \"define\", macro P[macro] D[macro]\n    next\n  } else {\n    # Replace #undef with comments.  This is necessary, for example,\n    # in the case of _POSIX_SOURCE, which is predefined and required\n    # on some systems where configure will not decide to define it.\n    if (defundef == \"undef\") {\n      print \"/*\", prefix defundef, macro, \"*/\"\n      next\n    }\n  }\n}\n{ print }\n_ACAWK\n_ACEOF\ncat >>$CONFIG_STATUS <<\\_ACEOF || ac_write_fail=1\n  as_fn_error $? \"could not setup config headers machinery\" \"$LINENO\" 5\nfi # test -n \"$CONFIG_HEADERS\"\n\n\neval set X \"  :F $CONFIG_FILES  :H $CONFIG_HEADERS    :C $CONFIG_COMMANDS\"\nshift\nfor ac_tag\ndo\n  case $ac_tag in\n  :[FHLC]) ac_mode=$ac_tag; continue;;\n  esac\n  case $ac_mode$ac_tag in\n  :[FHL]*:*);;\n  :L* | :C*:*) as_fn_error $? \"invalid tag \\`$ac_tag'\" \"$LINENO\" 5;;\n  :[FH]-) ac_tag=-:-;;\n  :[FH]*) ac_tag=$ac_tag:$ac_tag.in;;\n  esac\n  ac_save_IFS=$IFS\n  IFS=:\n  set x $ac_tag\n  IFS=$ac_save_IFS\n  shift\n  ac_file=$1\n  shift\n\n  case $ac_mode in\n  :L) ac_source=$1;;\n  :[FH])\n    ac_file_inputs=\n    for ac_f\n    do\n      case $ac_f in\n      -) ac_f=\"$ac_tmp/stdin\";;\n      *) # Look for the file first in the build tree, then in the source tree\n\t # (if the path is not absolute).  The absolute path cannot be DOS-style,\n\t # because $ac_f cannot contain `:'.\n\t test -f \"$ac_f\" ||\n\t   case $ac_f in\n\t   [\\\\/$]*) false;;\n\t   *) test -f \"$srcdir/$ac_f\" && ac_f=\"$srcdir/$ac_f\";;\n\t   esac ||\n\t   as_fn_error 1 \"cannot find input file: \\`$ac_f'\" \"$LINENO\" 5;;\n      esac\n      case $ac_f in *\\'*) ac_f=`$as_echo \"$ac_f\" | sed \"s/'/'\\\\\\\\\\\\\\\\''/g\"`;; esac\n      as_fn_append ac_file_inputs \" '$ac_f'\"\n    done\n\n    # Let's still pretend it is `configure' which instantiates (i.e., don't\n    # use $as_me), people would be surprised to read:\n    #    /* config.h.  Generated by config.status.  */\n    configure_input='Generated from '`\n\t  $as_echo \"$*\" | sed 's|^[^:]*/||;s|:[^:]*/|, |g'\n\t`' by configure.'\n    if test x\"$ac_file\" != x-; then\n      configure_input=\"$ac_file.  $configure_input\"\n      { $as_echo \"$as_me:${as_lineno-$LINENO}: creating $ac_file\" >&5\n$as_echo \"$as_me: creating $ac_file\" >&6;}\n    fi\n    # Neutralize special characters interpreted by sed in replacement strings.\n    case $configure_input in #(\n    *\\&* | *\\|* | *\\\\* )\n       ac_sed_conf_input=`$as_echo \"$configure_input\" |\n       sed 's/[\\\\\\\\&|]/\\\\\\\\&/g'`;; #(\n    *) ac_sed_conf_input=$configure_input;;\n    esac\n\n    case $ac_tag in\n    *:-:* | *:-) cat >\"$ac_tmp/stdin\" \\\n      || as_fn_error $? \"could not create $ac_file\" \"$LINENO\" 5 ;;\n    esac\n    ;;\n  esac\n\n  ac_dir=`$as_dirname -- \"$ac_file\" ||\n$as_expr X\"$ac_file\" : 'X\\(.*[^/]\\)//*[^/][^/]*/*$' \\| \\\n\t X\"$ac_file\" : 'X\\(//\\)[^/]' \\| \\\n\t X\"$ac_file\" : 'X\\(//\\)$' \\| \\\n\t X\"$ac_file\" : 'X\\(/\\)' \\| . 2>/dev/null ||\n$as_echo X\"$ac_file\" |\n    sed '/^X\\(.*[^/]\\)\\/\\/*[^/][^/]*\\/*$/{\n\t    s//\\1/\n\t    q\n\t  }\n\t  /^X\\(\\/\\/\\)[^/].*/{\n\t    s//\\1/\n\t    q\n\t  }\n\t  /^X\\(\\/\\/\\)$/{\n\t    s//\\1/\n\t    q\n\t  }\n\t  /^X\\(\\/\\).*/{\n\t    s//\\1/\n\t    q\n\t  }\n\t  s/.*/./; q'`\n  as_dir=\"$ac_dir\"; as_fn_mkdir_p\n  ac_builddir=.\n\ncase \"$ac_dir\" in\n.) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;;\n*)\n  ac_dir_suffix=/`$as_echo \"$ac_dir\" | sed 's|^\\.[\\\\/]||'`\n  # A \"..\" for each directory in $ac_dir_suffix.\n  ac_top_builddir_sub=`$as_echo \"$ac_dir_suffix\" | sed 's|/[^\\\\/]*|/..|g;s|/||'`\n  case $ac_top_builddir_sub in\n  \"\") ac_top_builddir_sub=. ac_top_build_prefix= ;;\n  *)  ac_top_build_prefix=$ac_top_builddir_sub/ ;;\n  esac ;;\nesac\nac_abs_top_builddir=$ac_pwd\nac_abs_builddir=$ac_pwd$ac_dir_suffix\n# for backward compatibility:\nac_top_builddir=$ac_top_build_prefix\n\ncase $srcdir in\n  .)  # We are building in place.\n    ac_srcdir=.\n    ac_top_srcdir=$ac_top_builddir_sub\n    ac_abs_top_srcdir=$ac_pwd ;;\n  [\\\\/]* | ?:[\\\\/]* )  # Absolute name.\n    ac_srcdir=$srcdir$ac_dir_suffix;\n    ac_top_srcdir=$srcdir\n    ac_abs_top_srcdir=$srcdir ;;\n  *) # Relative name.\n    ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix\n    ac_top_srcdir=$ac_top_build_prefix$srcdir\n    ac_abs_top_srcdir=$ac_pwd/$srcdir ;;\nesac\nac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix\n\n\n  case $ac_mode in\n  :F)\n  #\n  # CONFIG_FILE\n  #\n\n  case $INSTALL in\n  [\\\\/$]* | ?:[\\\\/]* ) ac_INSTALL=$INSTALL ;;\n  *) ac_INSTALL=$ac_top_build_prefix$INSTALL ;;\n  esac\n_ACEOF\n\ncat >>$CONFIG_STATUS <<\\_ACEOF || ac_write_fail=1\n# If the template does not know about datarootdir, expand it.\n# FIXME: This hack should be removed a few years after 2.60.\nac_datarootdir_hack=; ac_datarootdir_seen=\nac_sed_dataroot='\n/datarootdir/ {\n  p\n  q\n}\n/@datadir@/p\n/@docdir@/p\n/@infodir@/p\n/@localedir@/p\n/@mandir@/p'\ncase `eval \"sed -n \\\"\\$ac_sed_dataroot\\\" $ac_file_inputs\"` in\n*datarootdir*) ac_datarootdir_seen=yes;;\n*@datadir@*|*@docdir@*|*@infodir@*|*@localedir@*|*@mandir@*)\n  { $as_echo \"$as_me:${as_lineno-$LINENO}: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting\" >&5\n$as_echo \"$as_me: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting\" >&2;}\n_ACEOF\ncat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1\n  ac_datarootdir_hack='\n  s&@datadir@&$datadir&g\n  s&@docdir@&$docdir&g\n  s&@infodir@&$infodir&g\n  s&@localedir@&$localedir&g\n  s&@mandir@&$mandir&g\n  s&\\\\\\${datarootdir}&$datarootdir&g' ;;\nesac\n_ACEOF\n\n# Neutralize VPATH when `$srcdir' = `.'.\n# Shell code in configure.ac might set extrasub.\n# FIXME: do we really want to maintain this feature?\ncat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1\nac_sed_extra=\"$ac_vpsub\n$extrasub\n_ACEOF\ncat >>$CONFIG_STATUS <<\\_ACEOF || ac_write_fail=1\n:t\n/@[a-zA-Z_][a-zA-Z_0-9]*@/!b\ns|@configure_input@|$ac_sed_conf_input|;t t\ns&@top_builddir@&$ac_top_builddir_sub&;t t\ns&@top_build_prefix@&$ac_top_build_prefix&;t t\ns&@srcdir@&$ac_srcdir&;t t\ns&@abs_srcdir@&$ac_abs_srcdir&;t t\ns&@top_srcdir@&$ac_top_srcdir&;t t\ns&@abs_top_srcdir@&$ac_abs_top_srcdir&;t t\ns&@builddir@&$ac_builddir&;t t\ns&@abs_builddir@&$ac_abs_builddir&;t t\ns&@abs_top_builddir@&$ac_abs_top_builddir&;t t\ns&@INSTALL@&$ac_INSTALL&;t t\n$ac_datarootdir_hack\n\"\neval sed \\\"\\$ac_sed_extra\\\" \"$ac_file_inputs\" | $AWK -f \"$ac_tmp/subs.awk\" \\\n  >$ac_tmp/out || as_fn_error $? \"could not create $ac_file\" \"$LINENO\" 5\n\ntest -z \"$ac_datarootdir_hack$ac_datarootdir_seen\" &&\n  { ac_out=`sed -n '/\\${datarootdir}/p' \"$ac_tmp/out\"`; test -n \"$ac_out\"; } &&\n  { ac_out=`sed -n '/^[\t ]*datarootdir[\t ]*:*=/p' \\\n      \"$ac_tmp/out\"`; test -z \"$ac_out\"; } &&\n  { $as_echo \"$as_me:${as_lineno-$LINENO}: WARNING: $ac_file contains a reference to the variable \\`datarootdir'\nwhich seems to be undefined.  Please make sure it is defined\" >&5\n$as_echo \"$as_me: WARNING: $ac_file contains a reference to the variable \\`datarootdir'\nwhich seems to be undefined.  Please make sure it is defined\" >&2;}\n\n  rm -f \"$ac_tmp/stdin\"\n  case $ac_file in\n  -) cat \"$ac_tmp/out\" && rm -f \"$ac_tmp/out\";;\n  *) rm -f \"$ac_file\" && mv \"$ac_tmp/out\" \"$ac_file\";;\n  esac \\\n  || as_fn_error $? \"could not create $ac_file\" \"$LINENO\" 5\n ;;\n  :H)\n  #\n  # CONFIG_HEADER\n  #\n  if test x\"$ac_file\" != x-; then\n    {\n      $as_echo \"/* $configure_input  */\" \\\n      && eval '$AWK -f \"$ac_tmp/defines.awk\"' \"$ac_file_inputs\"\n    } >\"$ac_tmp/config.h\" \\\n      || as_fn_error $? \"could not create $ac_file\" \"$LINENO\" 5\n    if diff \"$ac_file\" \"$ac_tmp/config.h\" >/dev/null 2>&1; then\n      { $as_echo \"$as_me:${as_lineno-$LINENO}: $ac_file is unchanged\" >&5\n$as_echo \"$as_me: $ac_file is unchanged\" >&6;}\n    else\n      rm -f \"$ac_file\"\n      mv \"$ac_tmp/config.h\" \"$ac_file\" \\\n\t|| as_fn_error $? \"could not create $ac_file\" \"$LINENO\" 5\n    fi\n  else\n    $as_echo \"/* $configure_input  */\" \\\n      && eval '$AWK -f \"$ac_tmp/defines.awk\"' \"$ac_file_inputs\" \\\n      || as_fn_error $? \"could not create -\" \"$LINENO\" 5\n  fi\n ;;\n\n  :C)  { $as_echo \"$as_me:${as_lineno-$LINENO}: executing $ac_file commands\" >&5\n$as_echo \"$as_me: executing $ac_file commands\" >&6;}\n ;;\n  esac\n\n\n  case $ac_file$ac_mode in\n    \"include/jemalloc/internal/private_namespace.h\":C)\n  mkdir -p \"${objroot}include/jemalloc/internal\"\n  \"${srcdir}/include/jemalloc/internal/private_namespace.sh\" \"${srcdir}/include/jemalloc/internal/private_symbols.txt\" > \"${objroot}include/jemalloc/internal/private_namespace.h\"\n ;;\n    \"include/jemalloc/internal/private_unnamespace.h\":C)\n  mkdir -p \"${objroot}include/jemalloc/internal\"\n  \"${srcdir}/include/jemalloc/internal/private_unnamespace.sh\" \"${srcdir}/include/jemalloc/internal/private_symbols.txt\" > \"${objroot}include/jemalloc/internal/private_unnamespace.h\"\n ;;\n    \"include/jemalloc/internal/public_symbols.txt\":C)\n  f=\"${objroot}include/jemalloc/internal/public_symbols.txt\"\n  mkdir -p \"${objroot}include/jemalloc/internal\"\n  cp /dev/null \"${f}\"\n  for nm in `echo ${mangling_map} |tr ',' ' '` ; do\n    n=`echo ${nm} |tr ':' ' ' |awk '{print $1}'`\n    m=`echo ${nm} |tr ':' ' ' |awk '{print $2}'`\n    echo \"${n}:${m}\" >> \"${f}\"\n        public_syms=`for sym in ${public_syms}; do echo \"${sym}\"; done |grep -v \"^${n}\\$\" |tr '\\n' ' '`\n  done\n  for sym in ${public_syms} ; do\n    n=\"${sym}\"\n    m=\"${JEMALLOC_PREFIX}${sym}\"\n    echo \"${n}:${m}\" >> \"${f}\"\n  done\n ;;\n    \"include/jemalloc/internal/public_namespace.h\":C)\n  mkdir -p \"${objroot}include/jemalloc/internal\"\n  \"${srcdir}/include/jemalloc/internal/public_namespace.sh\" \"${objroot}include/jemalloc/internal/public_symbols.txt\" > \"${objroot}include/jemalloc/internal/public_namespace.h\"\n ;;\n    \"include/jemalloc/internal/public_unnamespace.h\":C)\n  mkdir -p \"${objroot}include/jemalloc/internal\"\n  \"${srcdir}/include/jemalloc/internal/public_unnamespace.sh\" \"${objroot}include/jemalloc/internal/public_symbols.txt\" > \"${objroot}include/jemalloc/internal/public_unnamespace.h\"\n ;;\n    \"include/jemalloc/internal/size_classes.h\":C)\n  mkdir -p \"${objroot}include/jemalloc/internal\"\n  \"${SHELL}\" \"${srcdir}/include/jemalloc/internal/size_classes.sh\" \"${LG_QUANTA}\" ${LG_TINY_MIN} \"${LG_PAGE_SIZES}\" ${LG_SIZE_CLASS_GROUP} > \"${objroot}include/jemalloc/internal/size_classes.h\"\n ;;\n    \"include/jemalloc/jemalloc_protos_jet.h\":C)\n  mkdir -p \"${objroot}include/jemalloc\"\n  cat \"${srcdir}/include/jemalloc/jemalloc_protos.h.in\" | sed -e 's/@je_@/jet_/g' > \"${objroot}include/jemalloc/jemalloc_protos_jet.h\"\n ;;\n    \"include/jemalloc/jemalloc_rename.h\":C)\n  mkdir -p \"${objroot}include/jemalloc\"\n  \"${srcdir}/include/jemalloc/jemalloc_rename.sh\" \"${objroot}include/jemalloc/internal/public_symbols.txt\" > \"${objroot}include/jemalloc/jemalloc_rename.h\"\n ;;\n    \"include/jemalloc/jemalloc_mangle.h\":C)\n  mkdir -p \"${objroot}include/jemalloc\"\n  \"${srcdir}/include/jemalloc/jemalloc_mangle.sh\" \"${objroot}include/jemalloc/internal/public_symbols.txt\" je_ > \"${objroot}include/jemalloc/jemalloc_mangle.h\"\n ;;\n    \"include/jemalloc/jemalloc_mangle_jet.h\":C)\n  mkdir -p \"${objroot}include/jemalloc\"\n  \"${srcdir}/include/jemalloc/jemalloc_mangle.sh\" \"${objroot}include/jemalloc/internal/public_symbols.txt\" jet_ > \"${objroot}include/jemalloc/jemalloc_mangle_jet.h\"\n ;;\n    \"include/jemalloc/jemalloc.h\":C)\n  mkdir -p \"${objroot}include/jemalloc\"\n  \"${srcdir}/include/jemalloc/jemalloc.sh\" \"${objroot}\" > \"${objroot}include/jemalloc/jemalloc${install_suffix}.h\"\n ;;\n\n  esac\ndone # for ac_tag\n\n\nas_fn_exit 0\n_ACEOF\nac_clean_files=$ac_clean_files_save\n\ntest $ac_write_fail = 0 ||\n  as_fn_error $? \"write failure creating $CONFIG_STATUS\" \"$LINENO\" 5\n\n\n# configure is writing to config.log, and then calls config.status.\n# config.status does its own redirection, appending to config.log.\n# Unfortunately, on DOS this fails, as config.log is still kept open\n# by configure, so config.status won't be able to write to it; its\n# output is simply discarded.  So we exec the FD to /dev/null,\n# effectively closing config.log, so it can be properly (re)opened and\n# appended to by config.status.  When coming back to configure, we\n# need to make the FD available again.\nif test \"$no_create\" != yes; then\n  ac_cs_success=:\n  ac_config_status_args=\n  test \"$silent\" = yes &&\n    ac_config_status_args=\"$ac_config_status_args --quiet\"\n  exec 5>/dev/null\n  $SHELL $CONFIG_STATUS $ac_config_status_args || ac_cs_success=false\n  exec 5>>config.log\n  # Use ||, not &&, to avoid exiting from the if with $? = 1, which\n  # would make configure fail if this is the last instruction.\n  $ac_cs_success || as_fn_exit 1\nfi\nif test -n \"$ac_unrecognized_opts\" && test \"$enable_option_checking\" != no; then\n  { $as_echo \"$as_me:${as_lineno-$LINENO}: WARNING: unrecognized options: $ac_unrecognized_opts\" >&5\n$as_echo \"$as_me: WARNING: unrecognized options: $ac_unrecognized_opts\" >&2;}\nfi\n\n\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: result: ===============================================================================\" >&5\n$as_echo \"===============================================================================\" >&6; }\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: result: jemalloc version   : ${jemalloc_version}\" >&5\n$as_echo \"jemalloc version   : ${jemalloc_version}\" >&6; }\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: result: library revision   : ${rev}\" >&5\n$as_echo \"library revision   : ${rev}\" >&6; }\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: result: \" >&5\n$as_echo \"\" >&6; }\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: result: CONFIG             : ${CONFIG}\" >&5\n$as_echo \"CONFIG             : ${CONFIG}\" >&6; }\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: result: CC                 : ${CC}\" >&5\n$as_echo \"CC                 : ${CC}\" >&6; }\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: result: CFLAGS             : ${CFLAGS}\" >&5\n$as_echo \"CFLAGS             : ${CFLAGS}\" >&6; }\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: result: CPPFLAGS           : ${CPPFLAGS}\" >&5\n$as_echo \"CPPFLAGS           : ${CPPFLAGS}\" >&6; }\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: result: LDFLAGS            : ${LDFLAGS}\" >&5\n$as_echo \"LDFLAGS            : ${LDFLAGS}\" >&6; }\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: result: EXTRA_LDFLAGS      : ${EXTRA_LDFLAGS}\" >&5\n$as_echo \"EXTRA_LDFLAGS      : ${EXTRA_LDFLAGS}\" >&6; }\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: result: LIBS               : ${LIBS}\" >&5\n$as_echo \"LIBS               : ${LIBS}\" >&6; }\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: result: TESTLIBS           : ${TESTLIBS}\" >&5\n$as_echo \"TESTLIBS           : ${TESTLIBS}\" >&6; }\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: result: RPATH_EXTRA        : ${RPATH_EXTRA}\" >&5\n$as_echo \"RPATH_EXTRA        : ${RPATH_EXTRA}\" >&6; }\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: result: \" >&5\n$as_echo \"\" >&6; }\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: result: XSLTPROC           : ${XSLTPROC}\" >&5\n$as_echo \"XSLTPROC           : ${XSLTPROC}\" >&6; }\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: result: XSLROOT            : ${XSLROOT}\" >&5\n$as_echo \"XSLROOT            : ${XSLROOT}\" >&6; }\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: result: \" >&5\n$as_echo \"\" >&6; }\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: result: PREFIX             : ${PREFIX}\" >&5\n$as_echo \"PREFIX             : ${PREFIX}\" >&6; }\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: result: BINDIR             : ${BINDIR}\" >&5\n$as_echo \"BINDIR             : ${BINDIR}\" >&6; }\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: result: DATADIR            : ${DATADIR}\" >&5\n$as_echo \"DATADIR            : ${DATADIR}\" >&6; }\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: result: INCLUDEDIR         : ${INCLUDEDIR}\" >&5\n$as_echo \"INCLUDEDIR         : ${INCLUDEDIR}\" >&6; }\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: result: LIBDIR             : ${LIBDIR}\" >&5\n$as_echo \"LIBDIR             : ${LIBDIR}\" >&6; }\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: result: MANDIR             : ${MANDIR}\" >&5\n$as_echo \"MANDIR             : ${MANDIR}\" >&6; }\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: result: \" >&5\n$as_echo \"\" >&6; }\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: result: srcroot            : ${srcroot}\" >&5\n$as_echo \"srcroot            : ${srcroot}\" >&6; }\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: result: abs_srcroot        : ${abs_srcroot}\" >&5\n$as_echo \"abs_srcroot        : ${abs_srcroot}\" >&6; }\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: result: objroot            : ${objroot}\" >&5\n$as_echo \"objroot            : ${objroot}\" >&6; }\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: result: abs_objroot        : ${abs_objroot}\" >&5\n$as_echo \"abs_objroot        : ${abs_objroot}\" >&6; }\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: result: \" >&5\n$as_echo \"\" >&6; }\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: result: JEMALLOC_PREFIX    : ${JEMALLOC_PREFIX}\" >&5\n$as_echo \"JEMALLOC_PREFIX    : ${JEMALLOC_PREFIX}\" >&6; }\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: result: JEMALLOC_PRIVATE_NAMESPACE\" >&5\n$as_echo \"JEMALLOC_PRIVATE_NAMESPACE\" >&6; }\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: result:                    : ${JEMALLOC_PRIVATE_NAMESPACE}\" >&5\n$as_echo \"                   : ${JEMALLOC_PRIVATE_NAMESPACE}\" >&6; }\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: result: install_suffix     : ${install_suffix}\" >&5\n$as_echo \"install_suffix     : ${install_suffix}\" >&6; }\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: result: autogen            : ${enable_autogen}\" >&5\n$as_echo \"autogen            : ${enable_autogen}\" >&6; }\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: result: cc-silence         : ${enable_cc_silence}\" >&5\n$as_echo \"cc-silence         : ${enable_cc_silence}\" >&6; }\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: result: debug              : ${enable_debug}\" >&5\n$as_echo \"debug              : ${enable_debug}\" >&6; }\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: result: code-coverage      : ${enable_code_coverage}\" >&5\n$as_echo \"code-coverage      : ${enable_code_coverage}\" >&6; }\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: result: stats              : ${enable_stats}\" >&5\n$as_echo \"stats              : ${enable_stats}\" >&6; }\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: result: prof               : ${enable_prof}\" >&5\n$as_echo \"prof               : ${enable_prof}\" >&6; }\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: result: prof-libunwind     : ${enable_prof_libunwind}\" >&5\n$as_echo \"prof-libunwind     : ${enable_prof_libunwind}\" >&6; }\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: result: prof-libgcc        : ${enable_prof_libgcc}\" >&5\n$as_echo \"prof-libgcc        : ${enable_prof_libgcc}\" >&6; }\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: result: prof-gcc           : ${enable_prof_gcc}\" >&5\n$as_echo \"prof-gcc           : ${enable_prof_gcc}\" >&6; }\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: result: tcache             : ${enable_tcache}\" >&5\n$as_echo \"tcache             : ${enable_tcache}\" >&6; }\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: result: fill               : ${enable_fill}\" >&5\n$as_echo \"fill               : ${enable_fill}\" >&6; }\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: result: utrace             : ${enable_utrace}\" >&5\n$as_echo \"utrace             : ${enable_utrace}\" >&6; }\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: result: valgrind           : ${enable_valgrind}\" >&5\n$as_echo \"valgrind           : ${enable_valgrind}\" >&6; }\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: result: xmalloc            : ${enable_xmalloc}\" >&5\n$as_echo \"xmalloc            : ${enable_xmalloc}\" >&6; }\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: result: munmap             : ${enable_munmap}\" >&5\n$as_echo \"munmap             : ${enable_munmap}\" >&6; }\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: result: lazy_lock          : ${enable_lazy_lock}\" >&5\n$as_echo \"lazy_lock          : ${enable_lazy_lock}\" >&6; }\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: result: tls                : ${enable_tls}\" >&5\n$as_echo \"tls                : ${enable_tls}\" >&6; }\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: result: cache-oblivious    : ${enable_cache_oblivious}\" >&5\n$as_echo \"cache-oblivious    : ${enable_cache_oblivious}\" >&6; }\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: result: ===============================================================================\" >&5\n$as_echo \"===============================================================================\" >&6; }\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.8/deps/jemalloc/configure.ac",
    "content": "dnl Process this file with autoconf to produce a configure script.\nAC_INIT([Makefile.in])\n\ndnl ============================================================================\ndnl Custom macro definitions.\n\ndnl JE_CFLAGS_APPEND(cflag)\nAC_DEFUN([JE_CFLAGS_APPEND],\n[\nAC_MSG_CHECKING([whether compiler supports $1])\nTCFLAGS=\"${CFLAGS}\"\nif test \"x${CFLAGS}\" = \"x\" ; then\n  CFLAGS=\"$1\"\nelse\n  CFLAGS=\"${CFLAGS} $1\"\nfi\nAC_COMPILE_IFELSE([AC_LANG_PROGRAM(\n[[\n]], [[\n    return 0;\n]])],\n              [je_cv_cflags_appended=$1]\n              AC_MSG_RESULT([yes]),\n              [je_cv_cflags_appended=]\n              AC_MSG_RESULT([no])\n              [CFLAGS=\"${TCFLAGS}\"]\n)\n])\n\ndnl JE_COMPILABLE(label, hcode, mcode, rvar)\ndnl \ndnl Use AC_LINK_IFELSE() rather than AC_COMPILE_IFELSE() so that linker errors\ndnl cause failure.\nAC_DEFUN([JE_COMPILABLE],\n[\nAC_CACHE_CHECK([whether $1 is compilable],\n               [$4],\n               [AC_LINK_IFELSE([AC_LANG_PROGRAM([$2],\n                                                [$3])],\n                               [$4=yes],\n                               [$4=no])])\n])\n\ndnl ============================================================================\n\nCONFIG=`echo ${ac_configure_args} | sed -e 's#'\"'\"'\\([^ ]*\\)'\"'\"'#\\1#g'`\nAC_SUBST([CONFIG])\n\ndnl Library revision.\nrev=2\nAC_SUBST([rev])\n\nsrcroot=$srcdir\nif test \"x${srcroot}\" = \"x.\" ; then\n  srcroot=\"\"\nelse\n  srcroot=\"${srcroot}/\"\nfi\nAC_SUBST([srcroot])\nabs_srcroot=\"`cd \\\"${srcdir}\\\"; pwd`/\"\nAC_SUBST([abs_srcroot])\n\nobjroot=\"\"\nAC_SUBST([objroot])\nabs_objroot=\"`pwd`/\"\nAC_SUBST([abs_objroot])\n\ndnl Munge install path variables.\nif test \"x$prefix\" = \"xNONE\" ; then\n  prefix=\"/usr/local\"\nfi\nif test \"x$exec_prefix\" = \"xNONE\" ; then\n  exec_prefix=$prefix\nfi\nPREFIX=$prefix\nAC_SUBST([PREFIX])\nBINDIR=`eval echo $bindir`\nBINDIR=`eval echo $BINDIR`\nAC_SUBST([BINDIR])\nINCLUDEDIR=`eval echo $includedir`\nINCLUDEDIR=`eval echo $INCLUDEDIR`\nAC_SUBST([INCLUDEDIR])\nLIBDIR=`eval echo $libdir`\nLIBDIR=`eval echo $LIBDIR`\nAC_SUBST([LIBDIR])\nDATADIR=`eval echo $datadir`\nDATADIR=`eval echo $DATADIR`\nAC_SUBST([DATADIR])\nMANDIR=`eval echo $mandir`\nMANDIR=`eval echo $MANDIR`\nAC_SUBST([MANDIR])\n\ndnl Support for building documentation.\nAC_PATH_PROG([XSLTPROC], [xsltproc], [false], [$PATH])\nif test -d \"/usr/share/xml/docbook/stylesheet/docbook-xsl\" ; then\n  DEFAULT_XSLROOT=\"/usr/share/xml/docbook/stylesheet/docbook-xsl\"\nelif test -d \"/usr/share/sgml/docbook/xsl-stylesheets\" ; then\n  DEFAULT_XSLROOT=\"/usr/share/sgml/docbook/xsl-stylesheets\"\nelse\n  dnl Documentation building will fail if this default gets used.\n  DEFAULT_XSLROOT=\"\"\nfi\nAC_ARG_WITH([xslroot],\n  [AS_HELP_STRING([--with-xslroot=<path>], [XSL stylesheet root path])], [\nif test \"x$with_xslroot\" = \"xno\" ; then\n  XSLROOT=\"${DEFAULT_XSLROOT}\"\nelse\n  XSLROOT=\"${with_xslroot}\"\nfi\n],\n  XSLROOT=\"${DEFAULT_XSLROOT}\"\n)\nAC_SUBST([XSLROOT])\n\ndnl If CFLAGS isn't defined, set CFLAGS to something reasonable.  Otherwise,\ndnl just prevent autoconf from molesting CFLAGS.\nCFLAGS=$CFLAGS\nAC_PROG_CC\nif test \"x$GCC\" != \"xyes\" ; then\n  AC_CACHE_CHECK([whether compiler is MSVC],\n                 [je_cv_msvc],\n                 [AC_COMPILE_IFELSE([AC_LANG_PROGRAM([],\n                                                     [\n#ifndef _MSC_VER\n  int fail[-1];\n#endif\n])],\n                               [je_cv_msvc=yes],\n                               [je_cv_msvc=no])])\nfi\n\nif test \"x$CFLAGS\" = \"x\" ; then\n  no_CFLAGS=\"yes\"\n  if test \"x$GCC\" = \"xyes\" ; then\n    JE_CFLAGS_APPEND([-std=gnu99])\n    if test \"x$je_cv_cflags_appended\" = \"x-std=gnu99\" ; then\n      AC_DEFINE_UNQUOTED([JEMALLOC_HAS_RESTRICT])\n    fi\n    JE_CFLAGS_APPEND([-Wall])\n    JE_CFLAGS_APPEND([-Werror=declaration-after-statement])\n    JE_CFLAGS_APPEND([-pipe])\n    JE_CFLAGS_APPEND([-g3])\n  elif test \"x$je_cv_msvc\" = \"xyes\" ; then\n    CC=\"$CC -nologo\"\n    JE_CFLAGS_APPEND([-Zi])\n    JE_CFLAGS_APPEND([-MT])\n    JE_CFLAGS_APPEND([-W3])\n    JE_CFLAGS_APPEND([-FS])\n    CPPFLAGS=\"$CPPFLAGS -I${srcdir}/include/msvc_compat\"\n  fi\nfi\ndnl Append EXTRA_CFLAGS to CFLAGS, if defined.\nif test \"x$EXTRA_CFLAGS\" != \"x\" ; then\n  JE_CFLAGS_APPEND([$EXTRA_CFLAGS])\nfi\nAC_PROG_CPP\n\nAC_C_BIGENDIAN([ac_cv_big_endian=1], [ac_cv_big_endian=0])\nif test \"x${ac_cv_big_endian}\" = \"x1\" ; then\n  AC_DEFINE_UNQUOTED([JEMALLOC_BIG_ENDIAN], [ ])\nfi\n\nif test \"x${je_cv_msvc}\" = \"xyes\" -a \"x${ac_cv_header_inttypes_h}\" = \"xno\"; then\n  CPPFLAGS=\"$CPPFLAGS -I${srcdir}/include/msvc_compat/C99\"\nfi\n\nAC_CHECK_SIZEOF([void *])\nif test \"x${ac_cv_sizeof_void_p}\" = \"x8\" ; then\n  LG_SIZEOF_PTR=3\nelif test \"x${ac_cv_sizeof_void_p}\" = \"x4\" ; then\n  LG_SIZEOF_PTR=2\nelse\n  AC_MSG_ERROR([Unsupported pointer size: ${ac_cv_sizeof_void_p}])\nfi\nAC_DEFINE_UNQUOTED([LG_SIZEOF_PTR], [$LG_SIZEOF_PTR])\n\nAC_CHECK_SIZEOF([int])\nif test \"x${ac_cv_sizeof_int}\" = \"x8\" ; then\n  LG_SIZEOF_INT=3\nelif test \"x${ac_cv_sizeof_int}\" = \"x4\" ; then\n  LG_SIZEOF_INT=2\nelse\n  AC_MSG_ERROR([Unsupported int size: ${ac_cv_sizeof_int}])\nfi\nAC_DEFINE_UNQUOTED([LG_SIZEOF_INT], [$LG_SIZEOF_INT])\n\nAC_CHECK_SIZEOF([long])\nif test \"x${ac_cv_sizeof_long}\" = \"x8\" ; then\n  LG_SIZEOF_LONG=3\nelif test \"x${ac_cv_sizeof_long}\" = \"x4\" ; then\n  LG_SIZEOF_LONG=2\nelse\n  AC_MSG_ERROR([Unsupported long size: ${ac_cv_sizeof_long}])\nfi\nAC_DEFINE_UNQUOTED([LG_SIZEOF_LONG], [$LG_SIZEOF_LONG])\n\nAC_CHECK_SIZEOF([intmax_t])\nif test \"x${ac_cv_sizeof_intmax_t}\" = \"x16\" ; then\n  LG_SIZEOF_INTMAX_T=4\nelif test \"x${ac_cv_sizeof_intmax_t}\" = \"x8\" ; then\n  LG_SIZEOF_INTMAX_T=3\nelif test \"x${ac_cv_sizeof_intmax_t}\" = \"x4\" ; then\n  LG_SIZEOF_INTMAX_T=2\nelse\n  AC_MSG_ERROR([Unsupported intmax_t size: ${ac_cv_sizeof_intmax_t}])\nfi\nAC_DEFINE_UNQUOTED([LG_SIZEOF_INTMAX_T], [$LG_SIZEOF_INTMAX_T])\n\nAC_CANONICAL_HOST\ndnl CPU-specific settings.\nCPU_SPINWAIT=\"\"\ncase \"${host_cpu}\" in\n  i686|x86_64)\n\tAC_CACHE_VAL([je_cv_pause],\n\t  [JE_COMPILABLE([pause instruction], [],\n\t                [[__asm__ volatile(\"pause\"); return 0;]],\n\t                [je_cv_pause])])\n\tif test \"x${je_cv_pause}\" = \"xyes\" ; then\n\t    CPU_SPINWAIT='__asm__ volatile(\"pause\")'\n\tfi\n\t;;\n  powerpc)\n\tAC_DEFINE_UNQUOTED([HAVE_ALTIVEC], [ ])\n\t;;\n  *)\n\t;;\nesac\nAC_DEFINE_UNQUOTED([CPU_SPINWAIT], [$CPU_SPINWAIT])\n\nLD_PRELOAD_VAR=\"LD_PRELOAD\"\nso=\"so\"\nimportlib=\"${so}\"\no=\"$ac_objext\"\na=\"a\"\nexe=\"$ac_exeext\"\nlibprefix=\"lib\"\nDSO_LDFLAGS='-shared -Wl,-soname,$(@F)'\nRPATH='-Wl,-rpath,$(1)'\nSOREV=\"${so}.${rev}\"\nPIC_CFLAGS='-fPIC -DPIC'\nCTARGET='-o $@'\nLDTARGET='-o $@'\nEXTRA_LDFLAGS=\nARFLAGS='crus'\nAROUT=' $@'\nCC_MM=1\n\nAN_MAKEVAR([AR], [AC_PROG_AR])\nAN_PROGRAM([ar], [AC_PROG_AR])\nAC_DEFUN([AC_PROG_AR], [AC_CHECK_TOOL(AR, ar, :)])\nAC_PROG_AR\n\ndnl Platform-specific settings.  abi and RPATH can probably be determined\ndnl programmatically, but doing so is error-prone, which makes it generally\ndnl not worth the trouble.\ndnl \ndnl Define cpp macros in CPPFLAGS, rather than doing AC_DEFINE(macro), since the\ndnl definitions need to be seen before any headers are included, which is a pain\ndnl to make happen otherwise.\ndefault_munmap=\"1\"\nmaps_coalesce=\"1\"\ncase \"${host}\" in\n  *-*-darwin* | *-*-ios*)\n\tCFLAGS=\"$CFLAGS\"\n\tabi=\"macho\"\n\tAC_DEFINE([JEMALLOC_PURGE_MADVISE_FREE], [ ])\n\tRPATH=\"\"\n\tLD_PRELOAD_VAR=\"DYLD_INSERT_LIBRARIES\"\n\tso=\"dylib\"\n\timportlib=\"${so}\"\n\tforce_tls=\"0\"\n\tDSO_LDFLAGS='-shared -Wl,-install_name,$(LIBDIR)/$(@F)'\n\tSOREV=\"${rev}.${so}\"\n\tsbrk_deprecated=\"1\"\n\t;;\n  *-*-freebsd*)\n\tCFLAGS=\"$CFLAGS\"\n\tabi=\"elf\"\n\tAC_DEFINE([JEMALLOC_PURGE_MADVISE_FREE], [ ])\n\tforce_lazy_lock=\"1\"\n\t;;\n  *-*-dragonfly*)\n\tCFLAGS=\"$CFLAGS\"\n\tabi=\"elf\"\n\tAC_DEFINE([JEMALLOC_PURGE_MADVISE_FREE], [ ])\n\t;;\n  *-*-openbsd*)\n\tCFLAGS=\"$CFLAGS\"\n\tabi=\"elf\"\n\tAC_DEFINE([JEMALLOC_PURGE_MADVISE_FREE], [ ])\n\tforce_tls=\"0\"\n\t;;\n  *-*-bitrig*)\n\tCFLAGS=\"$CFLAGS\"\n\tabi=\"elf\"\n\tAC_DEFINE([JEMALLOC_PURGE_MADVISE_FREE], [ ])\n\t;;\n  *-*-linux*)\n\tCFLAGS=\"$CFLAGS\"\n\tCPPFLAGS=\"$CPPFLAGS -D_GNU_SOURCE\"\n\tabi=\"elf\"\n\tAC_DEFINE([JEMALLOC_HAS_ALLOCA_H])\n\tAC_DEFINE([JEMALLOC_PURGE_MADVISE_DONTNEED], [ ])\n\tAC_DEFINE([JEMALLOC_THREADED_INIT], [ ])\n\tAC_DEFINE([JEMALLOC_USE_CXX_THROW], [ ])\n\tdefault_munmap=\"0\"\n\t;;\n  *-*-netbsd*)\n\tAC_MSG_CHECKING([ABI])\n        AC_COMPILE_IFELSE([AC_LANG_PROGRAM(\n[[#ifdef __ELF__\n/* ELF */\n#else\n#error aout\n#endif\n]])],\n                          [CFLAGS=\"$CFLAGS\"; abi=\"elf\"],\n                          [abi=\"aout\"])\n\tAC_MSG_RESULT([$abi])\n\tAC_DEFINE([JEMALLOC_PURGE_MADVISE_FREE], [ ])\n\t;;\n  *-*-solaris2*)\n\tCFLAGS=\"$CFLAGS\"\n\tabi=\"elf\"\n\tAC_DEFINE([JEMALLOC_PURGE_MADVISE_FREE], [ ])\n\tRPATH='-Wl,-R,$(1)'\n\tdnl Solaris needs this for sigwait().\n\tCPPFLAGS=\"$CPPFLAGS -D_POSIX_PTHREAD_SEMANTICS\"\n\tLIBS=\"$LIBS -lposix4 -lsocket -lnsl\"\n\t;;\n  *-ibm-aix*)\n\tif \"$LG_SIZEOF_PTR\" = \"8\"; then\n\t  dnl 64bit AIX\n\t  LD_PRELOAD_VAR=\"LDR_PRELOAD64\"\n\telse\n\t  dnl 32bit AIX\n\t  LD_PRELOAD_VAR=\"LDR_PRELOAD\"\n\tfi\n\tabi=\"xcoff\"\n\t;;\n  *-*-mingw* | *-*-cygwin*)\n\tabi=\"pecoff\"\n\tforce_tls=\"0\"\n\tforce_lazy_lock=\"1\"\n\tmaps_coalesce=\"0\"\n\tRPATH=\"\"\n\tso=\"dll\"\n\tif test \"x$je_cv_msvc\" = \"xyes\" ; then\n\t  importlib=\"lib\"\n\t  DSO_LDFLAGS=\"-LD\"\n\t  EXTRA_LDFLAGS=\"-link -DEBUG\"\n\t  CTARGET='-Fo$@'\n\t  LDTARGET='-Fe$@'\n\t  AR='lib'\n\t  ARFLAGS='-nologo -out:'\n\t  AROUT='$@'\n\t  CC_MM=\n        else\n\t  importlib=\"${so}\"\n\t  DSO_LDFLAGS=\"-shared\"\n\tfi\n\ta=\"lib\"\n\tlibprefix=\"\"\n\tSOREV=\"${so}\"\n\tPIC_CFLAGS=\"\"\n\t;;\n  *)\n\tAC_MSG_RESULT([Unsupported operating system: ${host}])\n\tabi=\"elf\"\n\t;;\nesac\n\nJEMALLOC_USABLE_SIZE_CONST=const\nAC_CHECK_HEADERS([malloc.h], [\n  AC_MSG_CHECKING([whether malloc_usable_size definition can use const argument])\n  AC_COMPILE_IFELSE([AC_LANG_PROGRAM(\n    [#include <malloc.h>\n     #include <stddef.h>\n    size_t malloc_usable_size(const void *ptr);\n    ],\n    [])],[\n                AC_MSG_RESULT([yes])\n         ],[\n                JEMALLOC_USABLE_SIZE_CONST=\n                AC_MSG_RESULT([no])\n         ])\n])\nAC_DEFINE_UNQUOTED([JEMALLOC_USABLE_SIZE_CONST], [$JEMALLOC_USABLE_SIZE_CONST])\nAC_SUBST([abi])\nAC_SUBST([RPATH])\nAC_SUBST([LD_PRELOAD_VAR])\nAC_SUBST([so])\nAC_SUBST([importlib])\nAC_SUBST([o])\nAC_SUBST([a])\nAC_SUBST([exe])\nAC_SUBST([libprefix])\nAC_SUBST([DSO_LDFLAGS])\nAC_SUBST([EXTRA_LDFLAGS])\nAC_SUBST([SOREV])\nAC_SUBST([PIC_CFLAGS])\nAC_SUBST([CTARGET])\nAC_SUBST([LDTARGET])\nAC_SUBST([MKLIB])\nAC_SUBST([ARFLAGS])\nAC_SUBST([AROUT])\nAC_SUBST([CC_MM])\n\nJE_COMPILABLE([__attribute__ syntax],\n              [static __attribute__((unused)) void foo(void){}],\n              [],\n              [je_cv_attribute])\nif test \"x${je_cv_attribute}\" = \"xyes\" ; then\n  AC_DEFINE([JEMALLOC_HAVE_ATTR], [ ])\n  if test \"x${GCC}\" = \"xyes\" -a \"x${abi}\" = \"xelf\"; then\n    JE_CFLAGS_APPEND([-fvisibility=hidden])\n  fi\nfi\ndnl Check for tls_model attribute support (clang 3.0 still lacks support).\nSAVED_CFLAGS=\"${CFLAGS}\"\nJE_CFLAGS_APPEND([-Werror])\nJE_COMPILABLE([tls_model attribute], [],\n              [static __thread int\n               __attribute__((tls_model(\"initial-exec\"), unused)) foo;\n               foo = 0;],\n              [je_cv_tls_model])\nCFLAGS=\"${SAVED_CFLAGS}\"\nif test \"x${je_cv_tls_model}\" = \"xyes\" ; then\n  AC_DEFINE([JEMALLOC_TLS_MODEL],\n            [__attribute__((tls_model(\"initial-exec\")))])\nelse\n  AC_DEFINE([JEMALLOC_TLS_MODEL], [ ])\nfi\ndnl Check for alloc_size attribute support.\nSAVED_CFLAGS=\"${CFLAGS}\"\nJE_CFLAGS_APPEND([-Werror])\nJE_COMPILABLE([alloc_size attribute], [#include <stdlib.h>],\n              [void *foo(size_t size) __attribute__((alloc_size(1)));],\n              [je_cv_alloc_size])\nCFLAGS=\"${SAVED_CFLAGS}\"\nif test \"x${je_cv_alloc_size}\" = \"xyes\" ; then\n  AC_DEFINE([JEMALLOC_HAVE_ATTR_ALLOC_SIZE], [ ])\nfi\ndnl Check for format(gnu_printf, ...) attribute support.\nSAVED_CFLAGS=\"${CFLAGS}\"\nJE_CFLAGS_APPEND([-Werror])\nJE_COMPILABLE([format(gnu_printf, ...) attribute], [#include <stdlib.h>],\n              [void *foo(const char *format, ...) __attribute__((format(gnu_printf, 1, 2)));],\n              [je_cv_format_gnu_printf])\nCFLAGS=\"${SAVED_CFLAGS}\"\nif test \"x${je_cv_format_gnu_printf}\" = \"xyes\" ; then\n  AC_DEFINE([JEMALLOC_HAVE_ATTR_FORMAT_GNU_PRINTF], [ ])\nfi\ndnl Check for format(printf, ...) attribute support.\nSAVED_CFLAGS=\"${CFLAGS}\"\nJE_CFLAGS_APPEND([-Werror])\nJE_COMPILABLE([format(printf, ...) attribute], [#include <stdlib.h>],\n              [void *foo(const char *format, ...) __attribute__((format(printf, 1, 2)));],\n              [je_cv_format_printf])\nCFLAGS=\"${SAVED_CFLAGS}\"\nif test \"x${je_cv_format_printf}\" = \"xyes\" ; then\n  AC_DEFINE([JEMALLOC_HAVE_ATTR_FORMAT_PRINTF], [ ])\nfi\n\ndnl Support optional additions to rpath.\nAC_ARG_WITH([rpath],\n  [AS_HELP_STRING([--with-rpath=<rpath>], [Colon-separated rpath (ELF systems only)])],\nif test \"x$with_rpath\" = \"xno\" ; then\n  RPATH_EXTRA=\nelse\n  RPATH_EXTRA=\"`echo $with_rpath | tr \\\":\\\" \\\" \\\"`\"\nfi,\n  RPATH_EXTRA=\n)\nAC_SUBST([RPATH_EXTRA])\n\ndnl Disable rules that do automatic regeneration of configure output by default.\nAC_ARG_ENABLE([autogen],\n  [AS_HELP_STRING([--enable-autogen], [Automatically regenerate configure output])],\nif test \"x$enable_autogen\" = \"xno\" ; then\n  enable_autogen=\"0\"\nelse\n  enable_autogen=\"1\"\nfi\n,\nenable_autogen=\"0\"\n)\nAC_SUBST([enable_autogen])\n\nAC_PROG_INSTALL\nAC_PROG_RANLIB\nAC_PATH_PROG([LD], [ld], [false], [$PATH])\nAC_PATH_PROG([AUTOCONF], [autoconf], [false], [$PATH])\n\npublic_syms=\"malloc_conf malloc_message malloc calloc posix_memalign aligned_alloc realloc free mallocx rallocx xallocx sallocx dallocx sdallocx nallocx mallctl mallctlnametomib mallctlbymib malloc_stats_print malloc_usable_size\"\n\ndnl Check for allocator-related functions that should be wrapped.\nAC_CHECK_FUNC([memalign],\n\t      [AC_DEFINE([JEMALLOC_OVERRIDE_MEMALIGN], [ ])\n\t       public_syms=\"${public_syms} memalign\"])\nAC_CHECK_FUNC([valloc],\n\t      [AC_DEFINE([JEMALLOC_OVERRIDE_VALLOC], [ ])\n\t       public_syms=\"${public_syms} valloc\"])\n\ndnl Do not compute test code coverage by default.\nGCOV_FLAGS=\nAC_ARG_ENABLE([code-coverage],\n  [AS_HELP_STRING([--enable-code-coverage],\n   [Enable code coverage])],\n[if test \"x$enable_code_coverage\" = \"xno\" ; then\n  enable_code_coverage=\"0\"\nelse\n  enable_code_coverage=\"1\"\nfi\n],\n[enable_code_coverage=\"0\"]\n)\nif test \"x$enable_code_coverage\" = \"x1\" ; then\n  deoptimize=\"no\"\n  echo \"$CFLAGS $EXTRA_CFLAGS\" | grep '\\-O' >/dev/null || deoptimize=\"yes\"\n  if test \"x${deoptimize}\" = \"xyes\" ; then\n    JE_CFLAGS_APPEND([-O0])\n  fi\n  JE_CFLAGS_APPEND([-fprofile-arcs -ftest-coverage])\n  EXTRA_LDFLAGS=\"$EXTRA_LDFLAGS -fprofile-arcs -ftest-coverage\"\n  AC_DEFINE([JEMALLOC_CODE_COVERAGE], [ ])\nfi\nAC_SUBST([enable_code_coverage])\n\ndnl Perform no name mangling by default.\nAC_ARG_WITH([mangling],\n  [AS_HELP_STRING([--with-mangling=<map>], [Mangle symbols in <map>])],\n  [mangling_map=\"$with_mangling\"], [mangling_map=\"\"])\n\ndnl Do not prefix public APIs by default.\nAC_ARG_WITH([jemalloc_prefix],\n  [AS_HELP_STRING([--with-jemalloc-prefix=<prefix>], [Prefix to prepend to all public APIs])],\n  [JEMALLOC_PREFIX=\"$with_jemalloc_prefix\"],\n  [if test \"x$abi\" != \"xmacho\" -a \"x$abi\" != \"xpecoff\"; then\n  JEMALLOC_PREFIX=\"\"\nelse\n  JEMALLOC_PREFIX=\"je_\"\nfi]\n)\nif test \"x$JEMALLOC_PREFIX\" != \"x\" ; then\n  JEMALLOC_CPREFIX=`echo ${JEMALLOC_PREFIX} | tr \"a-z\" \"A-Z\"`\n  AC_DEFINE_UNQUOTED([JEMALLOC_PREFIX], [\"$JEMALLOC_PREFIX\"])\n  AC_DEFINE_UNQUOTED([JEMALLOC_CPREFIX], [\"$JEMALLOC_CPREFIX\"])\nfi\nAC_SUBST([JEMALLOC_CPREFIX])\n\nAC_ARG_WITH([export],\n  [AS_HELP_STRING([--without-export], [disable exporting jemalloc public APIs])],\n  [if test \"x$with_export\" = \"xno\"; then\n  AC_DEFINE([JEMALLOC_EXPORT],[])\nfi]\n)\n\ndnl Mangle library-private APIs.\nAC_ARG_WITH([private_namespace],\n  [AS_HELP_STRING([--with-private-namespace=<prefix>], [Prefix to prepend to all library-private APIs])],\n  [JEMALLOC_PRIVATE_NAMESPACE=\"${with_private_namespace}je_\"],\n  [JEMALLOC_PRIVATE_NAMESPACE=\"je_\"]\n)\nAC_DEFINE_UNQUOTED([JEMALLOC_PRIVATE_NAMESPACE], [$JEMALLOC_PRIVATE_NAMESPACE])\nprivate_namespace=\"$JEMALLOC_PRIVATE_NAMESPACE\"\nAC_SUBST([private_namespace])\n\ndnl Do not add suffix to installed files by default.\nAC_ARG_WITH([install_suffix],\n  [AS_HELP_STRING([--with-install-suffix=<suffix>], [Suffix to append to all installed files])],\n  [INSTALL_SUFFIX=\"$with_install_suffix\"],\n  [INSTALL_SUFFIX=]\n)\ninstall_suffix=\"$INSTALL_SUFFIX\"\nAC_SUBST([install_suffix])\n\ndnl Substitute @je_@ in jemalloc_protos.h.in, primarily to make generation of\ndnl jemalloc_protos_jet.h easy.\nje_=\"je_\"\nAC_SUBST([je_])\n\ncfgoutputs_in=\"Makefile.in\"\ncfgoutputs_in=\"${cfgoutputs_in} jemalloc.pc.in\"\ncfgoutputs_in=\"${cfgoutputs_in} doc/html.xsl.in\"\ncfgoutputs_in=\"${cfgoutputs_in} doc/manpages.xsl.in\"\ncfgoutputs_in=\"${cfgoutputs_in} doc/jemalloc.xml.in\"\ncfgoutputs_in=\"${cfgoutputs_in} include/jemalloc/jemalloc_macros.h.in\"\ncfgoutputs_in=\"${cfgoutputs_in} include/jemalloc/jemalloc_protos.h.in\"\ncfgoutputs_in=\"${cfgoutputs_in} include/jemalloc/jemalloc_typedefs.h.in\"\ncfgoutputs_in=\"${cfgoutputs_in} include/jemalloc/internal/jemalloc_internal.h.in\"\ncfgoutputs_in=\"${cfgoutputs_in} test/test.sh.in\"\ncfgoutputs_in=\"${cfgoutputs_in} test/include/test/jemalloc_test.h.in\"\n\ncfgoutputs_out=\"Makefile\"\ncfgoutputs_out=\"${cfgoutputs_out} jemalloc.pc\"\ncfgoutputs_out=\"${cfgoutputs_out} doc/html.xsl\"\ncfgoutputs_out=\"${cfgoutputs_out} doc/manpages.xsl\"\ncfgoutputs_out=\"${cfgoutputs_out} doc/jemalloc.xml\"\ncfgoutputs_out=\"${cfgoutputs_out} include/jemalloc/jemalloc_macros.h\"\ncfgoutputs_out=\"${cfgoutputs_out} include/jemalloc/jemalloc_protos.h\"\ncfgoutputs_out=\"${cfgoutputs_out} include/jemalloc/jemalloc_typedefs.h\"\ncfgoutputs_out=\"${cfgoutputs_out} include/jemalloc/internal/jemalloc_internal.h\"\ncfgoutputs_out=\"${cfgoutputs_out} test/test.sh\"\ncfgoutputs_out=\"${cfgoutputs_out} test/include/test/jemalloc_test.h\"\n\ncfgoutputs_tup=\"Makefile\"\ncfgoutputs_tup=\"${cfgoutputs_tup} jemalloc.pc:jemalloc.pc.in\"\ncfgoutputs_tup=\"${cfgoutputs_tup} doc/html.xsl:doc/html.xsl.in\"\ncfgoutputs_tup=\"${cfgoutputs_tup} doc/manpages.xsl:doc/manpages.xsl.in\"\ncfgoutputs_tup=\"${cfgoutputs_tup} doc/jemalloc.xml:doc/jemalloc.xml.in\"\ncfgoutputs_tup=\"${cfgoutputs_tup} include/jemalloc/jemalloc_macros.h:include/jemalloc/jemalloc_macros.h.in\"\ncfgoutputs_tup=\"${cfgoutputs_tup} include/jemalloc/jemalloc_protos.h:include/jemalloc/jemalloc_protos.h.in\"\ncfgoutputs_tup=\"${cfgoutputs_tup} include/jemalloc/jemalloc_typedefs.h:include/jemalloc/jemalloc_typedefs.h.in\"\ncfgoutputs_tup=\"${cfgoutputs_tup} include/jemalloc/internal/jemalloc_internal.h\"\ncfgoutputs_tup=\"${cfgoutputs_tup} test/test.sh:test/test.sh.in\"\ncfgoutputs_tup=\"${cfgoutputs_tup} test/include/test/jemalloc_test.h:test/include/test/jemalloc_test.h.in\"\n\ncfghdrs_in=\"include/jemalloc/jemalloc_defs.h.in\"\ncfghdrs_in=\"${cfghdrs_in} include/jemalloc/internal/jemalloc_internal_defs.h.in\"\ncfghdrs_in=\"${cfghdrs_in} include/jemalloc/internal/private_namespace.sh\"\ncfghdrs_in=\"${cfghdrs_in} include/jemalloc/internal/private_unnamespace.sh\"\ncfghdrs_in=\"${cfghdrs_in} include/jemalloc/internal/private_symbols.txt\"\ncfghdrs_in=\"${cfghdrs_in} include/jemalloc/internal/public_namespace.sh\"\ncfghdrs_in=\"${cfghdrs_in} include/jemalloc/internal/public_unnamespace.sh\"\ncfghdrs_in=\"${cfghdrs_in} include/jemalloc/internal/size_classes.sh\"\ncfghdrs_in=\"${cfghdrs_in} include/jemalloc/jemalloc_rename.sh\"\ncfghdrs_in=\"${cfghdrs_in} include/jemalloc/jemalloc_mangle.sh\"\ncfghdrs_in=\"${cfghdrs_in} include/jemalloc/jemalloc.sh\"\ncfghdrs_in=\"${cfghdrs_in} test/include/test/jemalloc_test_defs.h.in\"\n\ncfghdrs_out=\"include/jemalloc/jemalloc_defs.h\"\ncfghdrs_out=\"${cfghdrs_out} include/jemalloc/jemalloc${install_suffix}.h\"\ncfghdrs_out=\"${cfghdrs_out} include/jemalloc/internal/private_namespace.h\"\ncfghdrs_out=\"${cfghdrs_out} include/jemalloc/internal/private_unnamespace.h\"\ncfghdrs_out=\"${cfghdrs_out} include/jemalloc/internal/public_symbols.txt\"\ncfghdrs_out=\"${cfghdrs_out} include/jemalloc/internal/public_namespace.h\"\ncfghdrs_out=\"${cfghdrs_out} include/jemalloc/internal/public_unnamespace.h\"\ncfghdrs_out=\"${cfghdrs_out} include/jemalloc/internal/size_classes.h\"\ncfghdrs_out=\"${cfghdrs_out} include/jemalloc/jemalloc_protos_jet.h\"\ncfghdrs_out=\"${cfghdrs_out} include/jemalloc/jemalloc_rename.h\"\ncfghdrs_out=\"${cfghdrs_out} include/jemalloc/jemalloc_mangle.h\"\ncfghdrs_out=\"${cfghdrs_out} include/jemalloc/jemalloc_mangle_jet.h\"\ncfghdrs_out=\"${cfghdrs_out} include/jemalloc/internal/jemalloc_internal_defs.h\"\ncfghdrs_out=\"${cfghdrs_out} test/include/test/jemalloc_test_defs.h\"\n\ncfghdrs_tup=\"include/jemalloc/jemalloc_defs.h:include/jemalloc/jemalloc_defs.h.in\"\ncfghdrs_tup=\"${cfghdrs_tup} include/jemalloc/internal/jemalloc_internal_defs.h:include/jemalloc/internal/jemalloc_internal_defs.h.in\"\ncfghdrs_tup=\"${cfghdrs_tup} test/include/test/jemalloc_test_defs.h:test/include/test/jemalloc_test_defs.h.in\"\n\ndnl Silence irrelevant compiler warnings by default.\nAC_ARG_ENABLE([cc-silence],\n  [AS_HELP_STRING([--disable-cc-silence],\n                  [Do not silence irrelevant compiler warnings])],\n[if test \"x$enable_cc_silence\" = \"xno\" ; then\n  enable_cc_silence=\"0\"\nelse\n  enable_cc_silence=\"1\"\nfi\n],\n[enable_cc_silence=\"1\"]\n)\nif test \"x$enable_cc_silence\" = \"x1\" ; then\n  AC_DEFINE([JEMALLOC_CC_SILENCE], [ ])\nfi\n\ndnl Do not compile with debugging by default.\nAC_ARG_ENABLE([debug],\n  [AS_HELP_STRING([--enable-debug],\n                  [Build debugging code (implies --enable-ivsalloc)])],\n[if test \"x$enable_debug\" = \"xno\" ; then\n  enable_debug=\"0\"\nelse\n  enable_debug=\"1\"\nfi\n],\n[enable_debug=\"0\"]\n)\nif test \"x$enable_debug\" = \"x1\" ; then\n  AC_DEFINE([JEMALLOC_DEBUG], [ ])\nfi\nif test \"x$enable_debug\" = \"x1\" ; then\n  AC_DEFINE([JEMALLOC_DEBUG], [ ])\n  enable_ivsalloc=\"1\"\nfi\nAC_SUBST([enable_debug])\n\ndnl Do not validate pointers by default.\nAC_ARG_ENABLE([ivsalloc],\n  [AS_HELP_STRING([--enable-ivsalloc],\n                  [Validate pointers passed through the public API])],\n[if test \"x$enable_ivsalloc\" = \"xno\" ; then\n  enable_ivsalloc=\"0\"\nelse\n  enable_ivsalloc=\"1\"\nfi\n],\n[enable_ivsalloc=\"0\"]\n)\nif test \"x$enable_ivsalloc\" = \"x1\" ; then\n  AC_DEFINE([JEMALLOC_IVSALLOC], [ ])\nfi\n\ndnl Only optimize if not debugging.\nif test \"x$enable_debug\" = \"x0\" -a \"x$no_CFLAGS\" = \"xyes\" ; then\n  dnl Make sure that an optimization flag was not specified in EXTRA_CFLAGS.\n  optimize=\"no\"\n  echo \"$CFLAGS $EXTRA_CFLAGS\" | grep '\\-O' >/dev/null || optimize=\"yes\"\n  if test \"x${optimize}\" = \"xyes\" ; then\n    if test \"x$GCC\" = \"xyes\" ; then\n      JE_CFLAGS_APPEND([-O3])\n      JE_CFLAGS_APPEND([-funroll-loops])\n    elif test \"x$je_cv_msvc\" = \"xyes\" ; then\n      JE_CFLAGS_APPEND([-O2])\n    else\n      JE_CFLAGS_APPEND([-O])\n    fi\n  fi\nfi\n\ndnl Enable statistics calculation by default.\nAC_ARG_ENABLE([stats],\n  [AS_HELP_STRING([--disable-stats],\n                  [Disable statistics calculation/reporting])],\n[if test \"x$enable_stats\" = \"xno\" ; then\n  enable_stats=\"0\"\nelse\n  enable_stats=\"1\"\nfi\n],\n[enable_stats=\"1\"]\n)\nif test \"x$enable_stats\" = \"x1\" ; then\n  AC_DEFINE([JEMALLOC_STATS], [ ])\nfi\nAC_SUBST([enable_stats])\n\ndnl Do not enable profiling by default.\nAC_ARG_ENABLE([prof],\n  [AS_HELP_STRING([--enable-prof], [Enable allocation profiling])],\n[if test \"x$enable_prof\" = \"xno\" ; then\n  enable_prof=\"0\"\nelse\n  enable_prof=\"1\"\nfi\n],\n[enable_prof=\"0\"]\n)\nif test \"x$enable_prof\" = \"x1\" ; then\n  backtrace_method=\"\"\nelse\n  backtrace_method=\"N/A\"\nfi\n\nAC_ARG_ENABLE([prof-libunwind],\n  [AS_HELP_STRING([--enable-prof-libunwind], [Use libunwind for backtracing])],\n[if test \"x$enable_prof_libunwind\" = \"xno\" ; then\n  enable_prof_libunwind=\"0\"\nelse\n  enable_prof_libunwind=\"1\"\nfi\n],\n[enable_prof_libunwind=\"0\"]\n)\nAC_ARG_WITH([static_libunwind],\n  [AS_HELP_STRING([--with-static-libunwind=<libunwind.a>],\n  [Path to static libunwind library; use rather than dynamically linking])],\nif test \"x$with_static_libunwind\" = \"xno\" ; then\n  LUNWIND=\"-lunwind\"\nelse\n  if test ! -f \"$with_static_libunwind\" ; then\n    AC_MSG_ERROR([Static libunwind not found: $with_static_libunwind])\n  fi\n  LUNWIND=\"$with_static_libunwind\"\nfi,\n  LUNWIND=\"-lunwind\"\n)\nif test \"x$backtrace_method\" = \"x\" -a \"x$enable_prof_libunwind\" = \"x1\" ; then\n  AC_CHECK_HEADERS([libunwind.h], , [enable_prof_libunwind=\"0\"])\n  if test \"x$LUNWIND\" = \"x-lunwind\" ; then\n    AC_CHECK_LIB([unwind], [unw_backtrace], [LIBS=\"$LIBS $LUNWIND\"],\n                 [enable_prof_libunwind=\"0\"])\n  else\n    LIBS=\"$LIBS $LUNWIND\"\n  fi\n  if test \"x${enable_prof_libunwind}\" = \"x1\" ; then\n    backtrace_method=\"libunwind\"\n    AC_DEFINE([JEMALLOC_PROF_LIBUNWIND], [ ])\n  fi\nfi\n\nAC_ARG_ENABLE([prof-libgcc],\n  [AS_HELP_STRING([--disable-prof-libgcc],\n  [Do not use libgcc for backtracing])],\n[if test \"x$enable_prof_libgcc\" = \"xno\" ; then\n  enable_prof_libgcc=\"0\"\nelse\n  enable_prof_libgcc=\"1\"\nfi\n],\n[enable_prof_libgcc=\"1\"]\n)\nif test \"x$backtrace_method\" = \"x\" -a \"x$enable_prof_libgcc\" = \"x1\" \\\n     -a \"x$GCC\" = \"xyes\" ; then\n  AC_CHECK_HEADERS([unwind.h], , [enable_prof_libgcc=\"0\"])\n  AC_CHECK_LIB([gcc], [_Unwind_Backtrace], [LIBS=\"$LIBS -lgcc\"], [enable_prof_libgcc=\"0\"])\n  if test \"x${enable_prof_libgcc}\" = \"x1\" ; then\n    backtrace_method=\"libgcc\"\n    AC_DEFINE([JEMALLOC_PROF_LIBGCC], [ ])\n  fi\nelse\n  enable_prof_libgcc=\"0\"\nfi\n\nAC_ARG_ENABLE([prof-gcc],\n  [AS_HELP_STRING([--disable-prof-gcc],\n  [Do not use gcc intrinsics for backtracing])],\n[if test \"x$enable_prof_gcc\" = \"xno\" ; then\n  enable_prof_gcc=\"0\"\nelse\n  enable_prof_gcc=\"1\"\nfi\n],\n[enable_prof_gcc=\"1\"]\n)\nif test \"x$backtrace_method\" = \"x\" -a \"x$enable_prof_gcc\" = \"x1\" \\\n     -a \"x$GCC\" = \"xyes\" ; then\n  JE_CFLAGS_APPEND([-fno-omit-frame-pointer])\n  backtrace_method=\"gcc intrinsics\"\n  AC_DEFINE([JEMALLOC_PROF_GCC], [ ])\nelse\n  enable_prof_gcc=\"0\"\nfi\n\nif test \"x$backtrace_method\" = \"x\" ; then\n  backtrace_method=\"none (disabling profiling)\"\n  enable_prof=\"0\"\nfi\nAC_MSG_CHECKING([configured backtracing method])\nAC_MSG_RESULT([$backtrace_method])\nif test \"x$enable_prof\" = \"x1\" ; then\n  if test \"x$abi\" != \"xpecoff\"; then\n    dnl Heap profiling uses the log(3) function.\n    LIBS=\"$LIBS -lm\"\n  fi\n\n  AC_DEFINE([JEMALLOC_PROF], [ ])\nfi\nAC_SUBST([enable_prof])\n\ndnl Enable thread-specific caching by default.\nAC_ARG_ENABLE([tcache],\n  [AS_HELP_STRING([--disable-tcache], [Disable per thread caches])],\n[if test \"x$enable_tcache\" = \"xno\" ; then\n  enable_tcache=\"0\"\nelse\n  enable_tcache=\"1\"\nfi\n],\n[enable_tcache=\"1\"]\n)\nif test \"x$enable_tcache\" = \"x1\" ; then\n  AC_DEFINE([JEMALLOC_TCACHE], [ ])\nfi\nAC_SUBST([enable_tcache])\n\ndnl Indicate whether adjacent virtual memory mappings automatically coalesce\ndnl (and fragment on demand).\nif test \"x${maps_coalesce}\" = \"x1\" ; then\n  AC_DEFINE([JEMALLOC_MAPS_COALESCE], [ ])\nfi\n\ndnl Enable VM deallocation via munmap() by default.\nAC_ARG_ENABLE([munmap],\n  [AS_HELP_STRING([--disable-munmap], [Disable VM deallocation via munmap(2)])],\n[if test \"x$enable_munmap\" = \"xno\" ; then\n  enable_munmap=\"0\"\nelse\n  enable_munmap=\"1\"\nfi\n],\n[enable_munmap=\"${default_munmap}\"]\n)\nif test \"x$enable_munmap\" = \"x1\" ; then\n  AC_DEFINE([JEMALLOC_MUNMAP], [ ])\nfi\nAC_SUBST([enable_munmap])\n\ndnl Enable allocation from DSS if supported by the OS.\nhave_dss=\"1\"\ndnl Check whether the BSD/SUSv1 sbrk() exists.  If not, disable DSS support.\nAC_CHECK_FUNC([sbrk], [have_sbrk=\"1\"], [have_sbrk=\"0\"])\nif test \"x$have_sbrk\" = \"x1\" ; then\n  if test \"x$sbrk_deprecated\" = \"x1\" ; then\n    AC_MSG_RESULT([Disabling dss allocation because sbrk is deprecated])\n    have_dss=\"0\"\n  fi\nelse\n  have_dss=\"0\"\nfi\n\nif test \"x$have_dss\" = \"x1\" ; then\n  AC_DEFINE([JEMALLOC_DSS], [ ])\nfi\n\ndnl Support the junk/zero filling option by default.\nAC_ARG_ENABLE([fill],\n  [AS_HELP_STRING([--disable-fill],\n                  [Disable support for junk/zero filling, quarantine, and redzones])],\n[if test \"x$enable_fill\" = \"xno\" ; then\n  enable_fill=\"0\"\nelse\n  enable_fill=\"1\"\nfi\n],\n[enable_fill=\"1\"]\n)\nif test \"x$enable_fill\" = \"x1\" ; then\n  AC_DEFINE([JEMALLOC_FILL], [ ])\nfi\nAC_SUBST([enable_fill])\n\ndnl Disable utrace(2)-based tracing by default.\nAC_ARG_ENABLE([utrace],\n  [AS_HELP_STRING([--enable-utrace], [Enable utrace(2)-based tracing])],\n[if test \"x$enable_utrace\" = \"xno\" ; then\n  enable_utrace=\"0\"\nelse\n  enable_utrace=\"1\"\nfi\n],\n[enable_utrace=\"0\"]\n)\nJE_COMPILABLE([utrace(2)], [\n#include <sys/types.h>\n#include <sys/param.h>\n#include <sys/time.h>\n#include <sys/uio.h>\n#include <sys/ktrace.h>\n], [\n\tutrace((void *)0, 0);\n], [je_cv_utrace])\nif test \"x${je_cv_utrace}\" = \"xno\" ; then\n  enable_utrace=\"0\"\nfi\nif test \"x$enable_utrace\" = \"x1\" ; then\n  AC_DEFINE([JEMALLOC_UTRACE], [ ])\nfi\nAC_SUBST([enable_utrace])\n\ndnl Support Valgrind by default.\nAC_ARG_ENABLE([valgrind],\n  [AS_HELP_STRING([--disable-valgrind], [Disable support for Valgrind])],\n[if test \"x$enable_valgrind\" = \"xno\" ; then\n  enable_valgrind=\"0\"\nelse\n  enable_valgrind=\"1\"\nfi\n],\n[enable_valgrind=\"1\"]\n)\nif test \"x$enable_valgrind\" = \"x1\" ; then\n  JE_COMPILABLE([valgrind], [\n#include <valgrind/valgrind.h>\n#include <valgrind/memcheck.h>\n\n#if !defined(VALGRIND_RESIZEINPLACE_BLOCK)\n#  error \"Incompatible Valgrind version\"\n#endif\n], [], [je_cv_valgrind])\n  if test \"x${je_cv_valgrind}\" = \"xno\" ; then\n    enable_valgrind=\"0\"\n  fi\n  if test \"x$enable_valgrind\" = \"x1\" ; then\n    AC_DEFINE([JEMALLOC_VALGRIND], [ ])\n  fi\nfi\nAC_SUBST([enable_valgrind])\n\ndnl Do not support the xmalloc option by default.\nAC_ARG_ENABLE([xmalloc],\n  [AS_HELP_STRING([--enable-xmalloc], [Support xmalloc option])],\n[if test \"x$enable_xmalloc\" = \"xno\" ; then\n  enable_xmalloc=\"0\"\nelse\n  enable_xmalloc=\"1\"\nfi\n],\n[enable_xmalloc=\"0\"]\n)\nif test \"x$enable_xmalloc\" = \"x1\" ; then\n  AC_DEFINE([JEMALLOC_XMALLOC], [ ])\nfi\nAC_SUBST([enable_xmalloc])\n\ndnl Support cache-oblivious allocation alignment by default.\nAC_ARG_ENABLE([cache-oblivious],\n  [AS_HELP_STRING([--disable-cache-oblivious],\n                  [Disable support for cache-oblivious allocation alignment])],\n[if test \"x$enable_cache_oblivious\" = \"xno\" ; then\n  enable_cache_oblivious=\"0\"\nelse\n  enable_cache_oblivious=\"1\"\nfi\n],\n[enable_cache_oblivious=\"1\"]\n)\nif test \"x$enable_cache_oblivious\" = \"x1\" ; then\n  AC_DEFINE([JEMALLOC_CACHE_OBLIVIOUS], [ ])\nfi\nAC_SUBST([enable_cache_oblivious])\n\ndnl ============================================================================\ndnl Check for  __builtin_ffsl(), then ffsl(3), and fail if neither are found.\ndnl One of those two functions should (theoretically) exist on all platforms\ndnl that jemalloc currently has a chance of functioning on without modification.\ndnl We additionally assume ffs() or __builtin_ffs() are defined if\ndnl ffsl() or __builtin_ffsl() are defined, respectively.\nJE_COMPILABLE([a program using __builtin_ffsl], [\n#include <stdio.h>\n#include <strings.h>\n#include <string.h>\n], [\n\t{\n\t\tint rv = __builtin_ffsl(0x08);\n\t\tprintf(\"%d\\n\", rv);\n\t}\n], [je_cv_gcc_builtin_ffsl])\nif test \"x${je_cv_gcc_builtin_ffsl}\" = \"xyes\" ; then\n  AC_DEFINE([JEMALLOC_INTERNAL_FFSL], [__builtin_ffsl])\n  AC_DEFINE([JEMALLOC_INTERNAL_FFS], [__builtin_ffs])\nelse\n  JE_COMPILABLE([a program using ffsl], [\n  #include <stdio.h>\n  #include <strings.h>\n  #include <string.h>\n  ], [\n\t{\n\t\tint rv = ffsl(0x08);\n\t\tprintf(\"%d\\n\", rv);\n\t}\n  ], [je_cv_function_ffsl])\n  if test \"x${je_cv_function_ffsl}\" = \"xyes\" ; then\n    AC_DEFINE([JEMALLOC_INTERNAL_FFSL], [ffsl])\n    AC_DEFINE([JEMALLOC_INTERNAL_FFS], [ffs])\n  else\n    AC_MSG_ERROR([Cannot build without ffsl(3) or __builtin_ffsl()])\n  fi\nfi\n\nAC_ARG_WITH([lg_tiny_min],\n  [AS_HELP_STRING([--with-lg-tiny-min=<lg-tiny-min>],\n   [Base 2 log of minimum tiny size class to support])],\n  [LG_TINY_MIN=\"$with_lg_tiny_min\"],\n  [LG_TINY_MIN=\"3\"])\nAC_DEFINE_UNQUOTED([LG_TINY_MIN], [$LG_TINY_MIN])\n\nAC_ARG_WITH([lg_quantum],\n  [AS_HELP_STRING([--with-lg-quantum=<lg-quantum>],\n   [Base 2 log of minimum allocation alignment])],\n  [LG_QUANTA=\"$with_lg_quantum\"],\n  [LG_QUANTA=\"3 4\"])\nif test \"x$with_lg_quantum\" != \"x\" ; then\n  AC_DEFINE_UNQUOTED([LG_QUANTUM], [$with_lg_quantum])\nfi\n\nAC_ARG_WITH([lg_page],\n  [AS_HELP_STRING([--with-lg-page=<lg-page>], [Base 2 log of system page size])],\n  [LG_PAGE=\"$with_lg_page\"], [LG_PAGE=\"detect\"])\nif test \"x$LG_PAGE\" = \"xdetect\"; then\n  AC_CACHE_CHECK([LG_PAGE],\n               [je_cv_lg_page],\n               AC_RUN_IFELSE([AC_LANG_PROGRAM(\n[[\n#include <strings.h>\n#ifdef _WIN32\n#include <windows.h>\n#else\n#include <unistd.h>\n#endif\n#include <stdio.h>\n]],\n[[\n    int result;\n    FILE *f;\n\n#ifdef _WIN32\n    SYSTEM_INFO si;\n    GetSystemInfo(&si);\n    result = si.dwPageSize;\n#else\n    result = sysconf(_SC_PAGESIZE);\n#endif\n    if (result == -1) {\n\treturn 1;\n    }\n    result = JEMALLOC_INTERNAL_FFSL(result) - 1;\n\n    f = fopen(\"conftest.out\", \"w\");\n    if (f == NULL) {\n\treturn 1;\n    }\n    fprintf(f, \"%d\\n\", result);\n    fclose(f);\n\n    return 0;\n]])],\n                             [je_cv_lg_page=`cat conftest.out`],\n                             [je_cv_lg_page=undefined],\n                             [je_cv_lg_page=12]))\nfi\nif test \"x${je_cv_lg_page}\" != \"x\" ; then\n  LG_PAGE=\"${je_cv_lg_page}\"\nfi\nif test \"x${LG_PAGE}\" != \"xundefined\" ; then\n   AC_DEFINE_UNQUOTED([LG_PAGE], [$LG_PAGE])\nelse\n   AC_MSG_ERROR([cannot determine value for LG_PAGE])\nfi\n\nAC_ARG_WITH([lg_page_sizes],\n  [AS_HELP_STRING([--with-lg-page-sizes=<lg-page-sizes>],\n   [Base 2 logs of system page sizes to support])],\n  [LG_PAGE_SIZES=\"$with_lg_page_sizes\"], [LG_PAGE_SIZES=\"$LG_PAGE\"])\n\nAC_ARG_WITH([lg_size_class_group],\n  [AS_HELP_STRING([--with-lg-size-class-group=<lg-size-class-group>],\n   [Base 2 log of size classes per doubling])],\n  [LG_SIZE_CLASS_GROUP=\"$with_lg_size_class_group\"],\n  [LG_SIZE_CLASS_GROUP=\"2\"])\n\ndnl ============================================================================\ndnl jemalloc configuration.\ndnl \n\ndnl Set VERSION if source directory is inside a git repository.\nif test \"x`test ! \\\"${srcroot}\\\" && cd \\\"${srcroot}\\\"; git rev-parse --is-inside-work-tree 2>/dev/null`\" = \"xtrue\" ; then\n  dnl Pattern globs aren't powerful enough to match both single- and\n  dnl double-digit version numbers, so iterate over patterns to support up to\n  dnl version 99.99.99 without any accidental matches.\n  rm -f \"${objroot}VERSION\"\n  for pattern in ['[0-9].[0-9].[0-9]' '[0-9].[0-9].[0-9][0-9]' \\\n                 '[0-9].[0-9][0-9].[0-9]' '[0-9].[0-9][0-9].[0-9][0-9]' \\\n                 '[0-9][0-9].[0-9].[0-9]' '[0-9][0-9].[0-9].[0-9][0-9]' \\\n                 '[0-9][0-9].[0-9][0-9].[0-9]' \\\n                 '[0-9][0-9].[0-9][0-9].[0-9][0-9]']; do\n    if test ! -e \"${objroot}VERSION\" ; then\n      (test ! \"${srcroot}\" && cd \"${srcroot}\"; git describe --long --abbrev=40 --match=\"${pattern}\") > \"${objroot}VERSION.tmp\" 2>/dev/null\n      if test $? -eq 0 ; then\n        mv \"${objroot}VERSION.tmp\" \"${objroot}VERSION\"\n        break\n      fi\n    fi\n  done\nfi\nrm -f \"${objroot}VERSION.tmp\"\nif test ! -e \"${objroot}VERSION\" ; then\n  if test ! -e \"${srcroot}VERSION\" ; then\n    AC_MSG_RESULT(\n      [Missing VERSION file, and unable to generate it; creating bogus VERSION])\n    echo \"0.0.0-0-g0000000000000000000000000000000000000000\" > \"${objroot}VERSION\"\n  else\n    cp ${srcroot}VERSION ${objroot}VERSION\n  fi\nfi\njemalloc_version=`cat \"${objroot}VERSION\"`\njemalloc_version_major=`echo ${jemalloc_version} | tr \".g-\" \" \" | awk '{print [$]1}'`\njemalloc_version_minor=`echo ${jemalloc_version} | tr \".g-\" \" \" | awk '{print [$]2}'`\njemalloc_version_bugfix=`echo ${jemalloc_version} | tr \".g-\" \" \" | awk '{print [$]3}'`\njemalloc_version_nrev=`echo ${jemalloc_version} | tr \".g-\" \" \" | awk '{print [$]4}'`\njemalloc_version_gid=`echo ${jemalloc_version} | tr \".g-\" \" \" | awk '{print [$]5}'`\nAC_SUBST([jemalloc_version])\nAC_SUBST([jemalloc_version_major])\nAC_SUBST([jemalloc_version_minor])\nAC_SUBST([jemalloc_version_bugfix])\nAC_SUBST([jemalloc_version_nrev])\nAC_SUBST([jemalloc_version_gid])\n\ndnl ============================================================================\ndnl Configure pthreads.\n\nif test \"x$abi\" != \"xpecoff\" ; then\n  AC_CHECK_HEADERS([pthread.h], , [AC_MSG_ERROR([pthread.h is missing])])\n  dnl Some systems may embed pthreads functionality in libc; check for libpthread\n  dnl first, but try libc too before failing.\n  AC_CHECK_LIB([pthread], [pthread_create], [LIBS=\"$LIBS -lpthread\"],\n               [AC_SEARCH_LIBS([pthread_create], , ,\n                               AC_MSG_ERROR([libpthread is missing]))])\nfi\n\nCPPFLAGS=\"$CPPFLAGS -D_REENTRANT\"\n\ndnl Check whether clock_gettime(2) is in libc or librt.  This function is only\ndnl used in test code, so save the result to TESTLIBS to avoid poluting LIBS.\nSAVED_LIBS=\"${LIBS}\"\nLIBS=\nAC_SEARCH_LIBS([clock_gettime], [rt], [TESTLIBS=\"${LIBS}\"])\nAC_SUBST([TESTLIBS])\nLIBS=\"${SAVED_LIBS}\"\n\ndnl Check if the GNU-specific secure_getenv function exists.\nAC_CHECK_FUNC([secure_getenv],\n              [have_secure_getenv=\"1\"],\n              [have_secure_getenv=\"0\"]\n             )\nif test \"x$have_secure_getenv\" = \"x1\" ; then\n  AC_DEFINE([JEMALLOC_HAVE_SECURE_GETENV], [ ])\nfi\n\ndnl Check if the Solaris/BSD issetugid function exists.\nAC_CHECK_FUNC([issetugid],\n              [have_issetugid=\"1\"],\n              [have_issetugid=\"0\"]\n             )\nif test \"x$have_issetugid\" = \"x1\" ; then\n  AC_DEFINE([JEMALLOC_HAVE_ISSETUGID], [ ])\nfi\n\ndnl Check whether the BSD-specific _malloc_thread_cleanup() exists.  If so, use\ndnl it rather than pthreads TSD cleanup functions to support cleanup during\ndnl thread exit, in order to avoid pthreads library recursion during\ndnl bootstrapping.\nAC_CHECK_FUNC([_malloc_thread_cleanup],\n              [have__malloc_thread_cleanup=\"1\"],\n              [have__malloc_thread_cleanup=\"0\"]\n             )\nif test \"x$have__malloc_thread_cleanup\" = \"x1\" ; then\n  AC_DEFINE([JEMALLOC_MALLOC_THREAD_CLEANUP], [ ])\n  force_tls=\"1\"\nfi\n\ndnl Check whether the BSD-specific _pthread_mutex_init_calloc_cb() exists.  If\ndnl so, mutex initialization causes allocation, and we need to implement this\ndnl callback function in order to prevent recursive allocation.\nAC_CHECK_FUNC([_pthread_mutex_init_calloc_cb],\n              [have__pthread_mutex_init_calloc_cb=\"1\"],\n              [have__pthread_mutex_init_calloc_cb=\"0\"]\n             )\nif test \"x$have__pthread_mutex_init_calloc_cb\" = \"x1\" ; then\n  AC_DEFINE([JEMALLOC_MUTEX_INIT_CB])\nfi\n\ndnl Disable lazy locking by default.\nAC_ARG_ENABLE([lazy_lock],\n  [AS_HELP_STRING([--enable-lazy-lock],\n  [Enable lazy locking (only lock when multi-threaded)])],\n[if test \"x$enable_lazy_lock\" = \"xno\" ; then\n  enable_lazy_lock=\"0\"\nelse\n  enable_lazy_lock=\"1\"\nfi\n],\n[enable_lazy_lock=\"\"]\n)\nif test \"x$enable_lazy_lock\" = \"x\" -a \"x${force_lazy_lock}\" = \"x1\" ; then\n  AC_MSG_RESULT([Forcing lazy-lock to avoid allocator/threading bootstrap issues])\n  enable_lazy_lock=\"1\"\nfi\nif test \"x$enable_lazy_lock\" = \"x1\" ; then\n  if test \"x$abi\" != \"xpecoff\" ; then\n    AC_CHECK_HEADERS([dlfcn.h], , [AC_MSG_ERROR([dlfcn.h is missing])])\n    AC_CHECK_FUNC([dlsym], [],\n      [AC_CHECK_LIB([dl], [dlsym], [LIBS=\"$LIBS -ldl\"],\n                    [AC_MSG_ERROR([libdl is missing])])\n      ])\n  fi\n  AC_DEFINE([JEMALLOC_LAZY_LOCK], [ ])\nelse\n  enable_lazy_lock=\"0\"\nfi\nAC_SUBST([enable_lazy_lock])\n\nAC_ARG_ENABLE([tls],\n  [AS_HELP_STRING([--disable-tls], [Disable thread-local storage (__thread keyword)])],\nif test \"x$enable_tls\" = \"xno\" ; then\n  enable_tls=\"0\"\nelse\n  enable_tls=\"1\"\nfi\n,\nenable_tls=\"\"\n)\nif test \"x${enable_tls}\" = \"x\" ; then\n  if test \"x${force_tls}\" = \"x1\" ; then\n    AC_MSG_RESULT([Forcing TLS to avoid allocator/threading bootstrap issues])\n    enable_tls=\"1\"\n  elif test \"x${force_tls}\" = \"x0\" ; then\n    AC_MSG_RESULT([Forcing no TLS to avoid allocator/threading bootstrap issues])\n    enable_tls=\"0\"\n  else\n    enable_tls=\"1\"\n  fi\nfi\nif test \"x${enable_tls}\" = \"x1\" ; then\nAC_MSG_CHECKING([for TLS])\nAC_COMPILE_IFELSE([AC_LANG_PROGRAM(\n[[\n    __thread int x;\n]], [[\n    x = 42;\n\n    return 0;\n]])],\n              AC_MSG_RESULT([yes]),\n              AC_MSG_RESULT([no])\n              enable_tls=\"0\")\nelse\n  enable_tls=\"0\"\nfi\nAC_SUBST([enable_tls])\nif test \"x${enable_tls}\" = \"x1\" ; then\n  if test \"x${force_tls}\" = \"x0\" ; then\n    AC_MSG_WARN([TLS enabled despite being marked unusable on this platform])\n  fi\n  AC_DEFINE_UNQUOTED([JEMALLOC_TLS], [ ])\nelif test \"x${force_tls}\" = \"x1\" ; then\n  AC_MSG_WARN([TLS disabled despite being marked critical on this platform])\nfi\n\ndnl ============================================================================\ndnl Check for C11 atomics.\n\nJE_COMPILABLE([C11 atomics], [\n#include <stdint.h>\n#if (__STDC_VERSION__ >= 201112L) && !defined(__STDC_NO_ATOMICS__)\n#include <stdatomic.h>\n#else\n#error Atomics not available\n#endif\n], [\n    uint64_t *p = (uint64_t *)0;\n    uint64_t x = 1;\n    volatile atomic_uint_least64_t *a = (volatile atomic_uint_least64_t *)p;\n    uint64_t r = atomic_fetch_add(a, x) + x;\n    return (r == 0);\n], [je_cv_c11atomics])\nif test \"x${je_cv_c11atomics}\" = \"xyes\" ; then\n  AC_DEFINE([JEMALLOC_C11ATOMICS])\nfi\n\ndnl ============================================================================\ndnl Check for atomic(9) operations as provided on FreeBSD.\n\nJE_COMPILABLE([atomic(9)], [\n#include <sys/types.h>\n#include <machine/atomic.h>\n#include <inttypes.h>\n], [\n\t{\n\t\tuint32_t x32 = 0;\n\t\tvolatile uint32_t *x32p = &x32;\n\t\tatomic_fetchadd_32(x32p, 1);\n\t}\n\t{\n\t\tunsigned long xlong = 0;\n\t\tvolatile unsigned long *xlongp = &xlong;\n\t\tatomic_fetchadd_long(xlongp, 1);\n\t}\n], [je_cv_atomic9])\nif test \"x${je_cv_atomic9}\" = \"xyes\" ; then\n  AC_DEFINE([JEMALLOC_ATOMIC9])\nfi\n\ndnl ============================================================================\ndnl Check for atomic(3) operations as provided on Darwin.\n\nJE_COMPILABLE([Darwin OSAtomic*()], [\n#include <libkern/OSAtomic.h>\n#include <inttypes.h>\n], [\n\t{\n\t\tint32_t x32 = 0;\n\t\tvolatile int32_t *x32p = &x32;\n\t\tOSAtomicAdd32(1, x32p);\n\t}\n\t{\n\t\tint64_t x64 = 0;\n\t\tvolatile int64_t *x64p = &x64;\n\t\tOSAtomicAdd64(1, x64p);\n\t}\n], [je_cv_osatomic])\nif test \"x${je_cv_osatomic}\" = \"xyes\" ; then\n  AC_DEFINE([JEMALLOC_OSATOMIC], [ ])\nfi\n\ndnl ============================================================================\ndnl Check for madvise(2).\n\nJE_COMPILABLE([madvise(2)], [\n#include <sys/mman.h>\n], [\n\t{\n\t\tmadvise((void *)0, 0, 0);\n\t}\n], [je_cv_madvise])\nif test \"x${je_cv_madvise}\" = \"xyes\" ; then\n  AC_DEFINE([JEMALLOC_HAVE_MADVISE], [ ])\nfi\n\ndnl ============================================================================\ndnl Check whether __sync_{add,sub}_and_fetch() are available despite\ndnl __GCC_HAVE_SYNC_COMPARE_AND_SWAP_n macros being undefined.\n\nAC_DEFUN([JE_SYNC_COMPARE_AND_SWAP_CHECK],[\n  AC_CACHE_CHECK([whether to force $1-bit __sync_{add,sub}_and_fetch()],\n               [je_cv_sync_compare_and_swap_$2],\n               [AC_LINK_IFELSE([AC_LANG_PROGRAM([\n                                                 #include <stdint.h>\n                                                ],\n                                                [\n                                                 #ifndef __GCC_HAVE_SYNC_COMPARE_AND_SWAP_$2\n                                                 {\n                                                    uint$1_t x$1 = 0;\n                                                    __sync_add_and_fetch(&x$1, 42);\n                                                    __sync_sub_and_fetch(&x$1, 1);\n                                                 }\n                                                 #else\n                                                 #error __GCC_HAVE_SYNC_COMPARE_AND_SWAP_$2 is defined, no need to force\n                                                 #endif\n                                                ])],\n                               [je_cv_sync_compare_and_swap_$2=yes],\n                               [je_cv_sync_compare_and_swap_$2=no])])\n\n  if test \"x${je_cv_sync_compare_and_swap_$2}\" = \"xyes\" ; then\n    AC_DEFINE([JE_FORCE_SYNC_COMPARE_AND_SWAP_$2], [ ])\n  fi\n])\n\nif test \"x${je_cv_atomic9}\" != \"xyes\" -a \"x${je_cv_osatomic}\" != \"xyes\" ; then\n  JE_SYNC_COMPARE_AND_SWAP_CHECK(32, 4)\n  JE_SYNC_COMPARE_AND_SWAP_CHECK(64, 8)\nfi\n\ndnl ============================================================================\ndnl Check for __builtin_clz() and __builtin_clzl().\n\nAC_CACHE_CHECK([for __builtin_clz],\n               [je_cv_builtin_clz],\n               [AC_LINK_IFELSE([AC_LANG_PROGRAM([],\n                                                [\n                                                {\n                                                        unsigned x = 0;\n                                                        int y = __builtin_clz(x);\n                                                }\n                                                {\n                                                        unsigned long x = 0;\n                                                        int y = __builtin_clzl(x);\n                                                }\n                                                ])],\n                               [je_cv_builtin_clz=yes],\n                               [je_cv_builtin_clz=no])])\n\nif test \"x${je_cv_builtin_clz}\" = \"xyes\" ; then\n  AC_DEFINE([JEMALLOC_HAVE_BUILTIN_CLZ], [ ])\nfi\n\ndnl ============================================================================\ndnl Check for spinlock(3) operations as provided on Darwin.\n\nJE_COMPILABLE([Darwin OSSpin*()], [\n#include <libkern/OSAtomic.h>\n#include <inttypes.h>\n], [\n\tOSSpinLock lock = 0;\n\tOSSpinLockLock(&lock);\n\tOSSpinLockUnlock(&lock);\n], [je_cv_osspin])\nif test \"x${je_cv_osspin}\" = \"xyes\" ; then\n  AC_DEFINE([JEMALLOC_OSSPIN], [ ])\nfi\n\ndnl ============================================================================\ndnl Darwin-related configuration.\n\nAC_ARG_ENABLE([zone-allocator],\n  [AS_HELP_STRING([--disable-zone-allocator],\n                  [Disable zone allocator for Darwin])],\n[if test \"x$enable_zone_allocator\" = \"xno\" ; then\n  enable_zone_allocator=\"0\"\nelse\n  enable_zone_allocator=\"1\"\nfi\n],\n[if test \"x${abi}\" = \"xmacho\"; then\n  enable_zone_allocator=\"1\"\nfi\n]\n)\nAC_SUBST([enable_zone_allocator])\n\nif test \"x${enable_zone_allocator}\" = \"x1\" ; then\n  if test \"x${abi}\" != \"xmacho\"; then\n    AC_MSG_ERROR([--enable-zone-allocator is only supported on Darwin])\n  fi\n  AC_DEFINE([JEMALLOC_ZONE], [ ])\n\n  dnl The szone version jumped from 3 to 6 between the OS X 10.5.x and 10.6\n  dnl releases.  malloc_zone_t and malloc_introspection_t have new fields in\n  dnl 10.6, which is the only source-level indication of the change.\n  AC_MSG_CHECKING([malloc zone version])\n  AC_DEFUN([JE_ZONE_PROGRAM],\n    [AC_LANG_PROGRAM(\n      [#include <malloc/malloc.h>],\n      [static int foo[[sizeof($1) $2 sizeof(void *) * $3 ? 1 : -1]]]\n    )])\n\n  AC_COMPILE_IFELSE([JE_ZONE_PROGRAM(malloc_zone_t,==,14)],[JEMALLOC_ZONE_VERSION=3],[\n  AC_COMPILE_IFELSE([JE_ZONE_PROGRAM(malloc_zone_t,==,15)],[JEMALLOC_ZONE_VERSION=5],[\n  AC_COMPILE_IFELSE([JE_ZONE_PROGRAM(malloc_zone_t,==,16)],[\n    AC_COMPILE_IFELSE([JE_ZONE_PROGRAM(malloc_introspection_t,==,9)],[JEMALLOC_ZONE_VERSION=6],[\n    AC_COMPILE_IFELSE([JE_ZONE_PROGRAM(malloc_introspection_t,==,13)],[JEMALLOC_ZONE_VERSION=7],[JEMALLOC_ZONE_VERSION=]\n  )])],[\n  AC_COMPILE_IFELSE([JE_ZONE_PROGRAM(malloc_zone_t,==,17)],[JEMALLOC_ZONE_VERSION=8],[\n  AC_COMPILE_IFELSE([JE_ZONE_PROGRAM(malloc_zone_t,>,17)],[JEMALLOC_ZONE_VERSION=9],[JEMALLOC_ZONE_VERSION=]\n  )])])])])\n  if test \"x${JEMALLOC_ZONE_VERSION}\" = \"x\"; then\n    AC_MSG_RESULT([unsupported])\n    AC_MSG_ERROR([Unsupported malloc zone version])\n  fi\n  if test \"${JEMALLOC_ZONE_VERSION}\" = 9; then\n    JEMALLOC_ZONE_VERSION=8\n    AC_MSG_RESULT([> 8])\n  else\n    AC_MSG_RESULT([$JEMALLOC_ZONE_VERSION])\n  fi\n  AC_DEFINE_UNQUOTED(JEMALLOC_ZONE_VERSION, [$JEMALLOC_ZONE_VERSION])\nfi\n\ndnl ============================================================================\ndnl Check for glibc malloc hooks\n\nJE_COMPILABLE([glibc malloc hook], [\n#include <stddef.h>\n\nextern void (* __free_hook)(void *ptr);\nextern void *(* __malloc_hook)(size_t size);\nextern void *(* __realloc_hook)(void *ptr, size_t size);\n], [\n  void *ptr = 0L;\n  if (__malloc_hook) ptr = __malloc_hook(1);\n  if (__realloc_hook) ptr = __realloc_hook(ptr, 2);\n  if (__free_hook && ptr) __free_hook(ptr);\n], [je_cv_glibc_malloc_hook])\nif test \"x${je_cv_glibc_malloc_hook}\" = \"xyes\" ; then\n  AC_DEFINE([JEMALLOC_GLIBC_MALLOC_HOOK], [ ])\nfi\n\nJE_COMPILABLE([glibc memalign hook], [\n#include <stddef.h>\n\nextern void *(* __memalign_hook)(size_t alignment, size_t size);\n], [\n  void *ptr = 0L;\n  if (__memalign_hook) ptr = __memalign_hook(16, 7);\n], [je_cv_glibc_memalign_hook])\nif test \"x${je_cv_glibc_memalign_hook}\" = \"xyes\" ; then\n  AC_DEFINE([JEMALLOC_GLIBC_MEMALIGN_HOOK], [ ])\nfi\n\nJE_COMPILABLE([pthreads adaptive mutexes], [\n#include <pthread.h>\n], [\n  pthread_mutexattr_t attr;\n  pthread_mutexattr_init(&attr);\n  pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_ADAPTIVE_NP);\n  pthread_mutexattr_destroy(&attr);\n], [je_cv_pthread_mutex_adaptive_np])\nif test \"x${je_cv_pthread_mutex_adaptive_np}\" = \"xyes\" ; then\n  AC_DEFINE([JEMALLOC_HAVE_PTHREAD_MUTEX_ADAPTIVE_NP], [ ])\nfi\n\ndnl ============================================================================\ndnl Check for typedefs, structures, and compiler characteristics.\nAC_HEADER_STDBOOL\n\ndnl ============================================================================\ndnl Define commands that generate output files.\n\nAC_CONFIG_COMMANDS([include/jemalloc/internal/private_namespace.h], [\n  mkdir -p \"${objroot}include/jemalloc/internal\"\n  \"${srcdir}/include/jemalloc/internal/private_namespace.sh\" \"${srcdir}/include/jemalloc/internal/private_symbols.txt\" > \"${objroot}include/jemalloc/internal/private_namespace.h\"\n], [\n  srcdir=\"${srcdir}\"\n  objroot=\"${objroot}\"\n])\nAC_CONFIG_COMMANDS([include/jemalloc/internal/private_unnamespace.h], [\n  mkdir -p \"${objroot}include/jemalloc/internal\"\n  \"${srcdir}/include/jemalloc/internal/private_unnamespace.sh\" \"${srcdir}/include/jemalloc/internal/private_symbols.txt\" > \"${objroot}include/jemalloc/internal/private_unnamespace.h\"\n], [\n  srcdir=\"${srcdir}\"\n  objroot=\"${objroot}\"\n])\nAC_CONFIG_COMMANDS([include/jemalloc/internal/public_symbols.txt], [\n  f=\"${objroot}include/jemalloc/internal/public_symbols.txt\"\n  mkdir -p \"${objroot}include/jemalloc/internal\"\n  cp /dev/null \"${f}\"\n  for nm in `echo ${mangling_map} |tr ',' ' '` ; do\n    n=`echo ${nm} |tr ':' ' ' |awk '{print $[]1}'`\n    m=`echo ${nm} |tr ':' ' ' |awk '{print $[]2}'`\n    echo \"${n}:${m}\" >> \"${f}\"\n    dnl Remove name from public_syms so that it isn't redefined later.\n    public_syms=`for sym in ${public_syms}; do echo \"${sym}\"; done |grep -v \"^${n}\\$\" |tr '\\n' ' '`\n  done\n  for sym in ${public_syms} ; do\n    n=\"${sym}\"\n    m=\"${JEMALLOC_PREFIX}${sym}\"\n    echo \"${n}:${m}\" >> \"${f}\"\n  done\n], [\n  srcdir=\"${srcdir}\"\n  objroot=\"${objroot}\"\n  mangling_map=\"${mangling_map}\"\n  public_syms=\"${public_syms}\"\n  JEMALLOC_PREFIX=\"${JEMALLOC_PREFIX}\"\n])\nAC_CONFIG_COMMANDS([include/jemalloc/internal/public_namespace.h], [\n  mkdir -p \"${objroot}include/jemalloc/internal\"\n  \"${srcdir}/include/jemalloc/internal/public_namespace.sh\" \"${objroot}include/jemalloc/internal/public_symbols.txt\" > \"${objroot}include/jemalloc/internal/public_namespace.h\"\n], [\n  srcdir=\"${srcdir}\"\n  objroot=\"${objroot}\"\n])\nAC_CONFIG_COMMANDS([include/jemalloc/internal/public_unnamespace.h], [\n  mkdir -p \"${objroot}include/jemalloc/internal\"\n  \"${srcdir}/include/jemalloc/internal/public_unnamespace.sh\" \"${objroot}include/jemalloc/internal/public_symbols.txt\" > \"${objroot}include/jemalloc/internal/public_unnamespace.h\"\n], [\n  srcdir=\"${srcdir}\"\n  objroot=\"${objroot}\"\n])\nAC_CONFIG_COMMANDS([include/jemalloc/internal/size_classes.h], [\n  mkdir -p \"${objroot}include/jemalloc/internal\"\n  \"${SHELL}\" \"${srcdir}/include/jemalloc/internal/size_classes.sh\" \"${LG_QUANTA}\" ${LG_TINY_MIN} \"${LG_PAGE_SIZES}\" ${LG_SIZE_CLASS_GROUP} > \"${objroot}include/jemalloc/internal/size_classes.h\"\n], [\n  SHELL=\"${SHELL}\"\n  srcdir=\"${srcdir}\"\n  objroot=\"${objroot}\"\n  LG_QUANTA=\"${LG_QUANTA}\"\n  LG_TINY_MIN=${LG_TINY_MIN}\n  LG_PAGE_SIZES=\"${LG_PAGE_SIZES}\"\n  LG_SIZE_CLASS_GROUP=${LG_SIZE_CLASS_GROUP}\n])\nAC_CONFIG_COMMANDS([include/jemalloc/jemalloc_protos_jet.h], [\n  mkdir -p \"${objroot}include/jemalloc\"\n  cat \"${srcdir}/include/jemalloc/jemalloc_protos.h.in\" | sed -e 's/@je_@/jet_/g' > \"${objroot}include/jemalloc/jemalloc_protos_jet.h\"\n], [\n  srcdir=\"${srcdir}\"\n  objroot=\"${objroot}\"\n])\nAC_CONFIG_COMMANDS([include/jemalloc/jemalloc_rename.h], [\n  mkdir -p \"${objroot}include/jemalloc\"\n  \"${srcdir}/include/jemalloc/jemalloc_rename.sh\" \"${objroot}include/jemalloc/internal/public_symbols.txt\" > \"${objroot}include/jemalloc/jemalloc_rename.h\"\n], [\n  srcdir=\"${srcdir}\"\n  objroot=\"${objroot}\"\n])\nAC_CONFIG_COMMANDS([include/jemalloc/jemalloc_mangle.h], [\n  mkdir -p \"${objroot}include/jemalloc\"\n  \"${srcdir}/include/jemalloc/jemalloc_mangle.sh\" \"${objroot}include/jemalloc/internal/public_symbols.txt\" je_ > \"${objroot}include/jemalloc/jemalloc_mangle.h\"\n], [\n  srcdir=\"${srcdir}\"\n  objroot=\"${objroot}\"\n])\nAC_CONFIG_COMMANDS([include/jemalloc/jemalloc_mangle_jet.h], [\n  mkdir -p \"${objroot}include/jemalloc\"\n  \"${srcdir}/include/jemalloc/jemalloc_mangle.sh\" \"${objroot}include/jemalloc/internal/public_symbols.txt\" jet_ > \"${objroot}include/jemalloc/jemalloc_mangle_jet.h\"\n], [\n  srcdir=\"${srcdir}\"\n  objroot=\"${objroot}\"\n])\nAC_CONFIG_COMMANDS([include/jemalloc/jemalloc.h], [\n  mkdir -p \"${objroot}include/jemalloc\"\n  \"${srcdir}/include/jemalloc/jemalloc.sh\" \"${objroot}\" > \"${objroot}include/jemalloc/jemalloc${install_suffix}.h\"\n], [\n  srcdir=\"${srcdir}\"\n  objroot=\"${objroot}\"\n  install_suffix=\"${install_suffix}\"\n])\n\ndnl Process .in files.\nAC_SUBST([cfghdrs_in])\nAC_SUBST([cfghdrs_out])\nAC_CONFIG_HEADERS([$cfghdrs_tup])\n\ndnl ============================================================================\ndnl Generate outputs.\n\nAC_CONFIG_FILES([$cfgoutputs_tup config.stamp bin/jemalloc-config bin/jemalloc.sh bin/jeprof])\nAC_SUBST([cfgoutputs_in])\nAC_SUBST([cfgoutputs_out])\nAC_OUTPUT\n\ndnl ============================================================================\ndnl Print out the results of configuration.\nAC_MSG_RESULT([===============================================================================])\nAC_MSG_RESULT([jemalloc version   : ${jemalloc_version}])\nAC_MSG_RESULT([library revision   : ${rev}])\nAC_MSG_RESULT([])\nAC_MSG_RESULT([CONFIG             : ${CONFIG}])\nAC_MSG_RESULT([CC                 : ${CC}])\nAC_MSG_RESULT([CFLAGS             : ${CFLAGS}])\nAC_MSG_RESULT([CPPFLAGS           : ${CPPFLAGS}])\nAC_MSG_RESULT([LDFLAGS            : ${LDFLAGS}])\nAC_MSG_RESULT([EXTRA_LDFLAGS      : ${EXTRA_LDFLAGS}])\nAC_MSG_RESULT([LIBS               : ${LIBS}])\nAC_MSG_RESULT([TESTLIBS           : ${TESTLIBS}])\nAC_MSG_RESULT([RPATH_EXTRA        : ${RPATH_EXTRA}])\nAC_MSG_RESULT([])\nAC_MSG_RESULT([XSLTPROC           : ${XSLTPROC}])\nAC_MSG_RESULT([XSLROOT            : ${XSLROOT}])\nAC_MSG_RESULT([])\nAC_MSG_RESULT([PREFIX             : ${PREFIX}])\nAC_MSG_RESULT([BINDIR             : ${BINDIR}])\nAC_MSG_RESULT([DATADIR            : ${DATADIR}])\nAC_MSG_RESULT([INCLUDEDIR         : ${INCLUDEDIR}])\nAC_MSG_RESULT([LIBDIR             : ${LIBDIR}])\nAC_MSG_RESULT([MANDIR             : ${MANDIR}])\nAC_MSG_RESULT([])\nAC_MSG_RESULT([srcroot            : ${srcroot}])\nAC_MSG_RESULT([abs_srcroot        : ${abs_srcroot}])\nAC_MSG_RESULT([objroot            : ${objroot}])\nAC_MSG_RESULT([abs_objroot        : ${abs_objroot}])\nAC_MSG_RESULT([])\nAC_MSG_RESULT([JEMALLOC_PREFIX    : ${JEMALLOC_PREFIX}])\nAC_MSG_RESULT([JEMALLOC_PRIVATE_NAMESPACE])\nAC_MSG_RESULT([                   : ${JEMALLOC_PRIVATE_NAMESPACE}])\nAC_MSG_RESULT([install_suffix     : ${install_suffix}])\nAC_MSG_RESULT([autogen            : ${enable_autogen}])\nAC_MSG_RESULT([cc-silence         : ${enable_cc_silence}])\nAC_MSG_RESULT([debug              : ${enable_debug}])\nAC_MSG_RESULT([code-coverage      : ${enable_code_coverage}])\nAC_MSG_RESULT([stats              : ${enable_stats}])\nAC_MSG_RESULT([prof               : ${enable_prof}])\nAC_MSG_RESULT([prof-libunwind     : ${enable_prof_libunwind}])\nAC_MSG_RESULT([prof-libgcc        : ${enable_prof_libgcc}])\nAC_MSG_RESULT([prof-gcc           : ${enable_prof_gcc}])\nAC_MSG_RESULT([tcache             : ${enable_tcache}])\nAC_MSG_RESULT([fill               : ${enable_fill}])\nAC_MSG_RESULT([utrace             : ${enable_utrace}])\nAC_MSG_RESULT([valgrind           : ${enable_valgrind}])\nAC_MSG_RESULT([xmalloc            : ${enable_xmalloc}])\nAC_MSG_RESULT([munmap             : ${enable_munmap}])\nAC_MSG_RESULT([lazy_lock          : ${enable_lazy_lock}])\nAC_MSG_RESULT([tls                : ${enable_tls}])\nAC_MSG_RESULT([cache-oblivious    : ${enable_cache_oblivious}])\nAC_MSG_RESULT([===============================================================================])\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.8/deps/jemalloc/coverage.sh",
    "content": "#!/bin/sh\n\nset -e\n\nobjdir=$1\nsuffix=$2\nshift 2\nobjs=$@\n\ngcov -b -p -f -o \"${objdir}\" ${objs}\n\n# Move gcov outputs so that subsequent gcov invocations won't clobber results\n# for the same sources with different compilation flags.\nfor f in `find . -maxdepth 1 -type f -name '*.gcov'` ; do\n  mv \"${f}\" \"${f}.${suffix}\"\ndone\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.8/deps/jemalloc/doc/html.xsl.in",
    "content": "<xsl:stylesheet xmlns:xsl=\"http://www.w3.org/1999/XSL/Transform\" version=\"1.0\">\n  <xsl:import href=\"@XSLROOT@/html/docbook.xsl\"/>\n  <xsl:import href=\"@abs_srcroot@doc/stylesheet.xsl\"/>\n</xsl:stylesheet>\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.8/deps/jemalloc/doc/jemalloc.xml.in",
    "content": "<?xml version='1.0' encoding='UTF-8'?>\n<?xml-stylesheet type=\"text/xsl\"\n        href=\"http://docbook.sourceforge.net/release/xsl/current/manpages/docbook.xsl\"?>\n<!DOCTYPE refentry PUBLIC \"-//OASIS//DTD DocBook XML V4.4//EN\"\n        \"http://www.oasis-open.org/docbook/xml/4.4/docbookx.dtd\" [\n]>\n\n<refentry>\n  <refentryinfo>\n    <title>User Manual</title>\n    <productname>jemalloc</productname>\n    <releaseinfo role=\"version\">@jemalloc_version@</releaseinfo>\n    <authorgroup>\n      <author>\n        <firstname>Jason</firstname>\n        <surname>Evans</surname>\n        <personblurb>Author</personblurb>\n      </author>\n    </authorgroup>\n  </refentryinfo>\n  <refmeta>\n    <refentrytitle>JEMALLOC</refentrytitle>\n    <manvolnum>3</manvolnum>\n  </refmeta>\n  <refnamediv>\n    <refdescriptor>jemalloc</refdescriptor>\n    <refname>jemalloc</refname>\n    <!-- Each refname causes a man page file to be created.  Only if this were\n         the system malloc(3) implementation would these files be appropriate.\n    <refname>malloc</refname>\n    <refname>calloc</refname>\n    <refname>posix_memalign</refname>\n    <refname>aligned_alloc</refname>\n    <refname>realloc</refname>\n    <refname>free</refname>\n    <refname>mallocx</refname>\n    <refname>rallocx</refname>\n    <refname>xallocx</refname>\n    <refname>sallocx</refname>\n    <refname>dallocx</refname>\n    <refname>sdallocx</refname>\n    <refname>nallocx</refname>\n    <refname>mallctl</refname>\n    <refname>mallctlnametomib</refname>\n    <refname>mallctlbymib</refname>\n    <refname>malloc_stats_print</refname>\n    <refname>malloc_usable_size</refname>\n    -->\n    <refpurpose>general purpose memory allocation functions</refpurpose>\n  </refnamediv>\n  <refsect1 id=\"library\">\n    <title>LIBRARY</title>\n    <para>This manual describes jemalloc @jemalloc_version@.  More information\n    can be found at the <ulink\n    url=\"http://www.canonware.com/jemalloc/\">jemalloc website</ulink>.</para>\n  </refsect1>\n  <refsynopsisdiv>\n    <title>SYNOPSIS</title>\n    <funcsynopsis>\n      <funcsynopsisinfo>#include &lt;<filename class=\"headerfile\">jemalloc/jemalloc.h</filename>&gt;</funcsynopsisinfo>\n      <refsect2>\n        <title>Standard API</title>\n        <funcprototype>\n          <funcdef>void *<function>malloc</function></funcdef>\n          <paramdef>size_t <parameter>size</parameter></paramdef>\n        </funcprototype>\n        <funcprototype>\n          <funcdef>void *<function>calloc</function></funcdef>\n          <paramdef>size_t <parameter>number</parameter></paramdef>\n          <paramdef>size_t <parameter>size</parameter></paramdef>\n        </funcprototype>\n        <funcprototype>\n          <funcdef>int <function>posix_memalign</function></funcdef>\n          <paramdef>void **<parameter>ptr</parameter></paramdef>\n          <paramdef>size_t <parameter>alignment</parameter></paramdef>\n          <paramdef>size_t <parameter>size</parameter></paramdef>\n        </funcprototype>\n        <funcprototype>\n          <funcdef>void *<function>aligned_alloc</function></funcdef>\n          <paramdef>size_t <parameter>alignment</parameter></paramdef>\n          <paramdef>size_t <parameter>size</parameter></paramdef>\n        </funcprototype>\n        <funcprototype>\n          <funcdef>void *<function>realloc</function></funcdef>\n          <paramdef>void *<parameter>ptr</parameter></paramdef>\n          <paramdef>size_t <parameter>size</parameter></paramdef>\n        </funcprototype>\n        <funcprototype>\n          <funcdef>void <function>free</function></funcdef>\n          <paramdef>void *<parameter>ptr</parameter></paramdef>\n        </funcprototype>\n      </refsect2>\n      <refsect2>\n        <title>Non-standard API</title>\n        <funcprototype>\n          <funcdef>void *<function>mallocx</function></funcdef>\n          <paramdef>size_t <parameter>size</parameter></paramdef>\n          <paramdef>int <parameter>flags</parameter></paramdef>\n        </funcprototype>\n        <funcprototype>\n          <funcdef>void *<function>rallocx</function></funcdef>\n          <paramdef>void *<parameter>ptr</parameter></paramdef>\n          <paramdef>size_t <parameter>size</parameter></paramdef>\n          <paramdef>int <parameter>flags</parameter></paramdef>\n        </funcprototype>\n        <funcprototype>\n          <funcdef>size_t <function>xallocx</function></funcdef>\n          <paramdef>void *<parameter>ptr</parameter></paramdef>\n          <paramdef>size_t <parameter>size</parameter></paramdef>\n          <paramdef>size_t <parameter>extra</parameter></paramdef>\n          <paramdef>int <parameter>flags</parameter></paramdef>\n        </funcprototype>\n        <funcprototype>\n          <funcdef>size_t <function>sallocx</function></funcdef>\n          <paramdef>void *<parameter>ptr</parameter></paramdef>\n          <paramdef>int <parameter>flags</parameter></paramdef>\n        </funcprototype>\n        <funcprototype>\n          <funcdef>void <function>dallocx</function></funcdef>\n          <paramdef>void *<parameter>ptr</parameter></paramdef>\n          <paramdef>int <parameter>flags</parameter></paramdef>\n        </funcprototype>\n        <funcprototype>\n          <funcdef>void <function>sdallocx</function></funcdef>\n          <paramdef>void *<parameter>ptr</parameter></paramdef>\n          <paramdef>size_t <parameter>size</parameter></paramdef>\n          <paramdef>int <parameter>flags</parameter></paramdef>\n        </funcprototype>\n        <funcprototype>\n          <funcdef>size_t <function>nallocx</function></funcdef>\n          <paramdef>size_t <parameter>size</parameter></paramdef>\n          <paramdef>int <parameter>flags</parameter></paramdef>\n        </funcprototype>\n        <funcprototype>\n          <funcdef>int <function>mallctl</function></funcdef>\n          <paramdef>const char *<parameter>name</parameter></paramdef>\n          <paramdef>void *<parameter>oldp</parameter></paramdef>\n          <paramdef>size_t *<parameter>oldlenp</parameter></paramdef>\n          <paramdef>void *<parameter>newp</parameter></paramdef>\n          <paramdef>size_t <parameter>newlen</parameter></paramdef>\n        </funcprototype>\n        <funcprototype>\n          <funcdef>int <function>mallctlnametomib</function></funcdef>\n          <paramdef>const char *<parameter>name</parameter></paramdef>\n          <paramdef>size_t *<parameter>mibp</parameter></paramdef>\n          <paramdef>size_t *<parameter>miblenp</parameter></paramdef>\n        </funcprototype>\n        <funcprototype>\n          <funcdef>int <function>mallctlbymib</function></funcdef>\n          <paramdef>const size_t *<parameter>mib</parameter></paramdef>\n          <paramdef>size_t <parameter>miblen</parameter></paramdef>\n          <paramdef>void *<parameter>oldp</parameter></paramdef>\n          <paramdef>size_t *<parameter>oldlenp</parameter></paramdef>\n          <paramdef>void *<parameter>newp</parameter></paramdef>\n          <paramdef>size_t <parameter>newlen</parameter></paramdef>\n        </funcprototype>\n        <funcprototype>\n          <funcdef>void <function>malloc_stats_print</function></funcdef>\n          <paramdef>void <parameter>(*write_cb)</parameter>\n            <funcparams>void *, const char *</funcparams>\n          </paramdef>\n          <paramdef>void *<parameter>cbopaque</parameter></paramdef>\n          <paramdef>const char *<parameter>opts</parameter></paramdef>\n        </funcprototype>\n        <funcprototype>\n          <funcdef>size_t <function>malloc_usable_size</function></funcdef>\n          <paramdef>const void *<parameter>ptr</parameter></paramdef>\n        </funcprototype>\n        <funcprototype>\n          <funcdef>void <function>(*malloc_message)</function></funcdef>\n          <paramdef>void *<parameter>cbopaque</parameter></paramdef>\n          <paramdef>const char *<parameter>s</parameter></paramdef>\n        </funcprototype>\n        <para><type>const char *</type><varname>malloc_conf</varname>;</para>\n      </refsect2>\n    </funcsynopsis>\n  </refsynopsisdiv>\n  <refsect1 id=\"description\">\n    <title>DESCRIPTION</title>\n    <refsect2>\n      <title>Standard API</title>\n\n      <para>The <function>malloc<parameter/></function> function allocates\n      <parameter>size</parameter> bytes of uninitialized memory.  The allocated\n      space is suitably aligned (after possible pointer coercion) for storage\n      of any type of object.</para>\n\n      <para>The <function>calloc<parameter/></function> function allocates\n      space for <parameter>number</parameter> objects, each\n      <parameter>size</parameter> bytes in length.  The result is identical to\n      calling <function>malloc<parameter/></function> with an argument of\n      <parameter>number</parameter> * <parameter>size</parameter>, with the\n      exception that the allocated memory is explicitly initialized to zero\n      bytes.</para>\n\n      <para>The <function>posix_memalign<parameter/></function> function\n      allocates <parameter>size</parameter> bytes of memory such that the\n      allocation's base address is a multiple of\n      <parameter>alignment</parameter>, and returns the allocation in the value\n      pointed to by <parameter>ptr</parameter>.  The requested\n      <parameter>alignment</parameter> must be a power of 2 at least as large as\n      <code language=\"C\">sizeof(<type>void *</type>)</code>.</para>\n\n      <para>The <function>aligned_alloc<parameter/></function> function\n      allocates <parameter>size</parameter> bytes of memory such that the\n      allocation's base address is a multiple of\n      <parameter>alignment</parameter>.  The requested\n      <parameter>alignment</parameter> must be a power of 2.  Behavior is\n      undefined if <parameter>size</parameter> is not an integral multiple of\n      <parameter>alignment</parameter>.</para>\n\n      <para>The <function>realloc<parameter/></function> function changes the\n      size of the previously allocated memory referenced by\n      <parameter>ptr</parameter> to <parameter>size</parameter> bytes.  The\n      contents of the memory are unchanged up to the lesser of the new and old\n      sizes.  If the new size is larger, the contents of the newly allocated\n      portion of the memory are undefined.  Upon success, the memory referenced\n      by <parameter>ptr</parameter> is freed and a pointer to the newly\n      allocated memory is returned.  Note that\n      <function>realloc<parameter/></function> may move the memory allocation,\n      resulting in a different return value than <parameter>ptr</parameter>.\n      If <parameter>ptr</parameter> is <constant>NULL</constant>, the\n      <function>realloc<parameter/></function> function behaves identically to\n      <function>malloc<parameter/></function> for the specified size.</para>\n\n      <para>The <function>free<parameter/></function> function causes the\n      allocated memory referenced by <parameter>ptr</parameter> to be made\n      available for future allocations.  If <parameter>ptr</parameter> is\n      <constant>NULL</constant>, no action occurs.</para>\n    </refsect2>\n    <refsect2>\n      <title>Non-standard API</title>\n      <para>The <function>mallocx<parameter/></function>,\n      <function>rallocx<parameter/></function>,\n      <function>xallocx<parameter/></function>,\n      <function>sallocx<parameter/></function>,\n      <function>dallocx<parameter/></function>,\n      <function>sdallocx<parameter/></function>, and\n      <function>nallocx<parameter/></function> functions all have a\n      <parameter>flags</parameter> argument that can be used to specify\n      options.  The functions only check the options that are contextually\n      relevant.  Use bitwise or (<code language=\"C\">|</code>) operations to\n      specify one or more of the following:\n        <variablelist>\n          <varlistentry id=\"MALLOCX_LG_ALIGN\">\n            <term><constant>MALLOCX_LG_ALIGN(<parameter>la</parameter>)\n            </constant></term>\n\n            <listitem><para>Align the memory allocation to start at an address\n            that is a multiple of <code language=\"C\">(1 &lt;&lt;\n            <parameter>la</parameter>)</code>.  This macro does not validate\n            that <parameter>la</parameter> is within the valid\n            range.</para></listitem>\n          </varlistentry>\n          <varlistentry id=\"MALLOCX_ALIGN\">\n            <term><constant>MALLOCX_ALIGN(<parameter>a</parameter>)\n            </constant></term>\n\n            <listitem><para>Align the memory allocation to start at an address\n            that is a multiple of <parameter>a</parameter>, where\n            <parameter>a</parameter> is a power of two.  This macro does not\n            validate that <parameter>a</parameter> is a power of 2.\n            </para></listitem>\n          </varlistentry>\n          <varlistentry id=\"MALLOCX_ZERO\">\n            <term><constant>MALLOCX_ZERO</constant></term>\n\n            <listitem><para>Initialize newly allocated memory to contain zero\n            bytes.  In the growing reallocation case, the real size prior to\n            reallocation defines the boundary between untouched bytes and those\n            that are initialized to contain zero bytes.  If this macro is\n            absent, newly allocated memory is uninitialized.</para></listitem>\n          </varlistentry>\n          <varlistentry id=\"MALLOCX_TCACHE\">\n            <term><constant>MALLOCX_TCACHE(<parameter>tc</parameter>)\n            </constant></term>\n\n            <listitem><para>Use the thread-specific cache (tcache) specified by\n            the identifier <parameter>tc</parameter>, which must have been\n            acquired via the <link\n            linkend=\"tcache.create\"><mallctl>tcache.create</mallctl></link>\n            mallctl.  This macro does not validate that\n            <parameter>tc</parameter> specifies a valid\n            identifier.</para></listitem>\n          </varlistentry>\n          <varlistentry id=\"MALLOC_TCACHE_NONE\">\n            <term><constant>MALLOCX_TCACHE_NONE</constant></term>\n\n            <listitem><para>Do not use a thread-specific cache (tcache).  Unless\n            <constant>MALLOCX_TCACHE(<parameter>tc</parameter>)</constant> or\n            <constant>MALLOCX_TCACHE_NONE</constant> is specified, an\n            automatically managed tcache will be used under many circumstances.\n            This macro cannot be used in the same <parameter>flags</parameter>\n            argument as\n            <constant>MALLOCX_TCACHE(<parameter>tc</parameter>)</constant>.</para></listitem>\n          </varlistentry>\n          <varlistentry id=\"MALLOCX_ARENA\">\n            <term><constant>MALLOCX_ARENA(<parameter>a</parameter>)\n            </constant></term>\n\n            <listitem><para>Use the arena specified by the index\n            <parameter>a</parameter>.  This macro has no effect for regions that\n            were allocated via an arena other than the one specified.  This\n            macro does not validate that <parameter>a</parameter> specifies an\n            arena index in the valid range.</para></listitem>\n          </varlistentry>\n        </variablelist>\n      </para>\n\n      <para>The <function>mallocx<parameter/></function> function allocates at\n      least <parameter>size</parameter> bytes of memory, and returns a pointer\n      to the base address of the allocation.  Behavior is undefined if\n      <parameter>size</parameter> is <constant>0</constant>, or if request size\n      overflows due to size class and/or alignment constraints.</para>\n\n      <para>The <function>rallocx<parameter/></function> function resizes the\n      allocation at <parameter>ptr</parameter> to be at least\n      <parameter>size</parameter> bytes, and returns a pointer to the base\n      address of the resulting allocation, which may or may not have moved from\n      its original location.  Behavior is undefined if\n      <parameter>size</parameter> is <constant>0</constant>, or if request size\n      overflows due to size class and/or alignment constraints.</para>\n\n      <para>The <function>xallocx<parameter/></function> function resizes the\n      allocation at <parameter>ptr</parameter> in place to be at least\n      <parameter>size</parameter> bytes, and returns the real size of the\n      allocation.  If <parameter>extra</parameter> is non-zero, an attempt is\n      made to resize the allocation to be at least <code\n      language=\"C\">(<parameter>size</parameter> +\n      <parameter>extra</parameter>)</code> bytes, though inability to allocate\n      the extra byte(s) will not by itself result in failure to resize.\n      Behavior is undefined if <parameter>size</parameter> is\n      <constant>0</constant>, or if <code\n      language=\"C\">(<parameter>size</parameter> + <parameter>extra</parameter>\n      &gt; <constant>SIZE_T_MAX</constant>)</code>.</para>\n\n      <para>The <function>sallocx<parameter/></function> function returns the\n      real size of the allocation at <parameter>ptr</parameter>.</para>\n\n      <para>The <function>dallocx<parameter/></function> function causes the\n      memory referenced by <parameter>ptr</parameter> to be made available for\n      future allocations.</para>\n\n      <para>The <function>sdallocx<parameter/></function> function is an\n      extension of <function>dallocx<parameter/></function> with a\n      <parameter>size</parameter> parameter to allow the caller to pass in the\n      allocation size as an optimization.  The minimum valid input size is the\n      original requested size of the allocation, and the maximum valid input\n      size is the corresponding value returned by\n      <function>nallocx<parameter/></function> or\n      <function>sallocx<parameter/></function>.</para>\n\n      <para>The <function>nallocx<parameter/></function> function allocates no\n      memory, but it performs the same size computation as the\n      <function>mallocx<parameter/></function> function, and returns the real\n      size of the allocation that would result from the equivalent\n      <function>mallocx<parameter/></function> function call.  Behavior is\n      undefined if <parameter>size</parameter> is <constant>0</constant>, or if\n      request size overflows due to size class and/or alignment\n      constraints.</para>\n\n      <para>The <function>mallctl<parameter/></function> function provides a\n      general interface for introspecting the memory allocator, as well as\n      setting modifiable parameters and triggering actions.  The\n      period-separated <parameter>name</parameter> argument specifies a\n      location in a tree-structured namespace; see the <xref\n      linkend=\"mallctl_namespace\" xrefstyle=\"template:%t\"/> section for\n      documentation on the tree contents.  To read a value, pass a pointer via\n      <parameter>oldp</parameter> to adequate space to contain the value, and a\n      pointer to its length via <parameter>oldlenp</parameter>; otherwise pass\n      <constant>NULL</constant> and <constant>NULL</constant>.  Similarly, to\n      write a value, pass a pointer to the value via\n      <parameter>newp</parameter>, and its length via\n      <parameter>newlen</parameter>; otherwise pass <constant>NULL</constant>\n      and <constant>0</constant>.</para>\n\n      <para>The <function>mallctlnametomib<parameter/></function> function\n      provides a way to avoid repeated name lookups for applications that\n      repeatedly query the same portion of the namespace, by translating a name\n      to a &ldquo;Management Information Base&rdquo; (MIB) that can be passed\n      repeatedly to <function>mallctlbymib<parameter/></function>.  Upon\n      successful return from <function>mallctlnametomib<parameter/></function>,\n      <parameter>mibp</parameter> contains an array of\n      <parameter>*miblenp</parameter> integers, where\n      <parameter>*miblenp</parameter> is the lesser of the number of components\n      in <parameter>name</parameter> and the input value of\n      <parameter>*miblenp</parameter>.  Thus it is possible to pass a\n      <parameter>*miblenp</parameter> that is smaller than the number of\n      period-separated name components, which results in a partial MIB that can\n      be used as the basis for constructing a complete MIB.  For name\n      components that are integers (e.g. the 2 in\n      <link\n      linkend=\"arenas.bin.i.size\"><mallctl>arenas.bin.2.size</mallctl></link>),\n      the corresponding MIB component will always be that integer.  Therefore,\n      it is legitimate to construct code like the following: <programlisting\n      language=\"C\"><![CDATA[\nunsigned nbins, i;\nsize_t mib[4];\nsize_t len, miblen;\n\nlen = sizeof(nbins);\nmallctl(\"arenas.nbins\", &nbins, &len, NULL, 0);\n\nmiblen = 4;\nmallctlnametomib(\"arenas.bin.0.size\", mib, &miblen);\nfor (i = 0; i < nbins; i++) {\n\tsize_t bin_size;\n\n\tmib[2] = i;\n\tlen = sizeof(bin_size);\n\tmallctlbymib(mib, miblen, &bin_size, &len, NULL, 0);\n\t/* Do something with bin_size... */\n}]]></programlisting></para>\n\n      <para>The <function>malloc_stats_print<parameter/></function> function\n      writes human-readable summary statistics via the\n      <parameter>write_cb</parameter> callback function pointer and\n      <parameter>cbopaque</parameter> data passed to\n      <parameter>write_cb</parameter>, or\n      <function>malloc_message<parameter/></function> if\n      <parameter>write_cb</parameter> is <constant>NULL</constant>.  This\n      function can be called repeatedly.  General information that never\n      changes during execution can be omitted by specifying \"g\" as a character\n      within the <parameter>opts</parameter> string.  Note that\n      <function>malloc_message<parameter/></function> uses the\n      <function>mallctl*<parameter/></function> functions internally, so\n      inconsistent statistics can be reported if multiple threads use these\n      functions simultaneously.  If <option>--enable-stats</option> is\n      specified during configuration, &ldquo;m&rdquo; and &ldquo;a&rdquo; can\n      be specified to omit merged arena and per arena statistics, respectively;\n      &ldquo;b&rdquo;, &ldquo;l&rdquo;, and &ldquo;h&rdquo; can be specified to\n      omit per size class statistics for bins, large objects, and huge objects,\n      respectively.  Unrecognized characters are silently ignored.  Note that\n      thread caching may prevent some statistics from being completely up to\n      date, since extra locking would be required to merge counters that track\n      thread cache operations.\n      </para>\n\n      <para>The <function>malloc_usable_size<parameter/></function> function\n      returns the usable size of the allocation pointed to by\n      <parameter>ptr</parameter>.  The return value may be larger than the size\n      that was requested during allocation.  The\n      <function>malloc_usable_size<parameter/></function> function is not a\n      mechanism for in-place <function>realloc<parameter/></function>; rather\n      it is provided solely as a tool for introspection purposes.  Any\n      discrepancy between the requested allocation size and the size reported\n      by <function>malloc_usable_size<parameter/></function> should not be\n      depended on, since such behavior is entirely implementation-dependent.\n      </para>\n    </refsect2>\n  </refsect1>\n  <refsect1 id=\"tuning\">\n    <title>TUNING</title>\n    <para>Once, when the first call is made to one of the memory allocation\n    routines, the allocator initializes its internals based in part on various\n    options that can be specified at compile- or run-time.</para>\n\n    <para>The string pointed to by the global variable\n    <varname>malloc_conf</varname>, the &ldquo;name&rdquo; of the file\n    referenced by the symbolic link named <filename\n    class=\"symlink\">/etc/malloc.conf</filename>, and the value of the\n    environment variable <envar>MALLOC_CONF</envar>, will be interpreted, in\n    that order, from left to right as options.  Note that\n    <varname>malloc_conf</varname> may be read before\n    <function>main<parameter/></function> is entered, so the declaration of\n    <varname>malloc_conf</varname> should specify an initializer that contains\n    the final value to be read by jemalloc.  <varname>malloc_conf</varname> is\n    a compile-time setting, whereas <filename\n    class=\"symlink\">/etc/malloc.conf</filename> and <envar>MALLOC_CONF</envar>\n    can be safely set any time prior to program invocation.</para>\n\n    <para>An options string is a comma-separated list of option:value pairs.\n    There is one key corresponding to each <link\n    linkend=\"opt.abort\"><mallctl>opt.*</mallctl></link> mallctl (see the <xref\n    linkend=\"mallctl_namespace\" xrefstyle=\"template:%t\"/> section for options\n    documentation).  For example, <literal>abort:true,narenas:1</literal> sets\n    the <link linkend=\"opt.abort\"><mallctl>opt.abort</mallctl></link> and <link\n    linkend=\"opt.narenas\"><mallctl>opt.narenas</mallctl></link> options.  Some\n    options have boolean values (true/false), others have integer values (base\n    8, 10, or 16, depending on prefix), and yet others have raw string\n    values.</para>\n  </refsect1>\n  <refsect1 id=\"implementation_notes\">\n    <title>IMPLEMENTATION NOTES</title>\n    <para>Traditionally, allocators have used\n    <citerefentry><refentrytitle>sbrk</refentrytitle>\n    <manvolnum>2</manvolnum></citerefentry> to obtain memory, which is\n    suboptimal for several reasons, including race conditions, increased\n    fragmentation, and artificial limitations on maximum usable memory.  If\n    <citerefentry><refentrytitle>sbrk</refentrytitle>\n    <manvolnum>2</manvolnum></citerefentry> is supported by the operating\n    system, this allocator uses both\n    <citerefentry><refentrytitle>mmap</refentrytitle>\n    <manvolnum>2</manvolnum></citerefentry> and\n    <citerefentry><refentrytitle>sbrk</refentrytitle>\n    <manvolnum>2</manvolnum></citerefentry>, in that order of preference;\n    otherwise only <citerefentry><refentrytitle>mmap</refentrytitle>\n    <manvolnum>2</manvolnum></citerefentry> is used.</para>\n\n    <para>This allocator uses multiple arenas in order to reduce lock\n    contention for threaded programs on multi-processor systems.  This works\n    well with regard to threading scalability, but incurs some costs.  There is\n    a small fixed per-arena overhead, and additionally, arenas manage memory\n    completely independently of each other, which means a small fixed increase\n    in overall memory fragmentation.  These overheads are not generally an\n    issue, given the number of arenas normally used.  Note that using\n    substantially more arenas than the default is not likely to improve\n    performance, mainly due to reduced cache performance.  However, it may make\n    sense to reduce the number of arenas if an application does not make much\n    use of the allocation functions.</para>\n\n    <para>In addition to multiple arenas, unless\n    <option>--disable-tcache</option> is specified during configuration, this\n    allocator supports thread-specific caching for small and large objects, in\n    order to make it possible to completely avoid synchronization for most\n    allocation requests.  Such caching allows very fast allocation in the\n    common case, but it increases memory usage and fragmentation, since a\n    bounded number of objects can remain allocated in each thread cache.</para>\n\n    <para>Memory is conceptually broken into equal-sized chunks, where the\n    chunk size is a power of two that is greater than the page size.  Chunks\n    are always aligned to multiples of the chunk size.  This alignment makes it\n    possible to find metadata for user objects very quickly.</para>\n\n    <para>User objects are broken into three categories according to size:\n    small, large, and huge.  Small and large objects are managed entirely by\n    arenas; huge objects are additionally aggregated in a single data structure\n    that is shared by all threads.  Huge objects are typically used by\n    applications infrequently enough that this single data structure is not a\n    scalability issue.</para>\n\n    <para>Each chunk that is managed by an arena tracks its contents as runs of\n    contiguous pages (unused, backing a set of small objects, or backing one\n    large object).  The combination of chunk alignment and chunk page maps\n    makes it possible to determine all metadata regarding small and large\n    allocations in constant time.</para>\n\n    <para>Small objects are managed in groups by page runs.  Each run maintains\n    a bitmap to track which regions are in use.  Allocation requests that are no\n    more than half the quantum (8 or 16, depending on architecture) are rounded\n    up to the nearest power of two that is at least <code\n    language=\"C\">sizeof(<type>double</type>)</code>.  All other object size\n    classes are multiples of the quantum, spaced such that there are four size\n    classes for each doubling in size, which limits internal fragmentation to\n    approximately 20% for all but the smallest size classes.  Small size classes\n    are smaller than four times the page size, large size classes are smaller\n    than the chunk size (see the <link\n    linkend=\"opt.lg_chunk\"><mallctl>opt.lg_chunk</mallctl></link> option), and\n    huge size classes extend from the chunk size up to one size class less than\n    the full address space size.</para>\n\n    <para>Allocations are packed tightly together, which can be an issue for\n    multi-threaded applications.  If you need to assure that allocations do not\n    suffer from cacheline sharing, round your allocation requests up to the\n    nearest multiple of the cacheline size, or specify cacheline alignment when\n    allocating.</para>\n\n    <para>The <function>realloc<parameter/></function>,\n    <function>rallocx<parameter/></function>, and\n    <function>xallocx<parameter/></function> functions may resize allocations\n    without moving them under limited circumstances.  Unlike the\n    <function>*allocx<parameter/></function> API, the standard API does not\n    officially round up the usable size of an allocation to the nearest size\n    class, so technically it is necessary to call\n    <function>realloc<parameter/></function> to grow e.g. a 9-byte allocation to\n    16 bytes, or shrink a 16-byte allocation to 9 bytes.  Growth and shrinkage\n    trivially succeeds in place as long as the pre-size and post-size both round\n    up to the same size class.  No other API guarantees are made regarding\n    in-place resizing, but the current implementation also tries to resize large\n    and huge allocations in place, as long as the pre-size and post-size are\n    both large or both huge.  In such cases shrinkage always succeeds for large\n    size classes, but for huge size classes the chunk allocator must support\n    splitting (see <link\n    linkend=\"arena.i.chunk_hooks\"><mallctl>arena.&lt;i&gt;.chunk_hooks</mallctl></link>).\n    Growth only succeeds if the trailing memory is currently available, and\n    additionally for huge size classes the chunk allocator must support\n    merging.</para>\n\n    <para>Assuming 2 MiB chunks, 4 KiB pages, and a 16-byte quantum on a\n    64-bit system, the size classes in each category are as shown in <xref\n    linkend=\"size_classes\" xrefstyle=\"template:Table %n\"/>.</para>\n\n    <table xml:id=\"size_classes\" frame=\"all\">\n      <title>Size classes</title>\n      <tgroup cols=\"3\" colsep=\"1\" rowsep=\"1\">\n      <colspec colname=\"c1\" align=\"left\"/>\n      <colspec colname=\"c2\" align=\"right\"/>\n      <colspec colname=\"c3\" align=\"left\"/>\n      <thead>\n        <row>\n          <entry>Category</entry>\n          <entry>Spacing</entry>\n          <entry>Size</entry>\n        </row>\n      </thead>\n      <tbody>\n        <row>\n          <entry morerows=\"8\">Small</entry>\n          <entry>lg</entry>\n          <entry>[8]</entry>\n        </row>\n        <row>\n          <entry>16</entry>\n          <entry>[16, 32, 48, 64, 80, 96, 112, 128]</entry>\n        </row>\n        <row>\n          <entry>32</entry>\n          <entry>[160, 192, 224, 256]</entry>\n        </row>\n        <row>\n          <entry>64</entry>\n          <entry>[320, 384, 448, 512]</entry>\n        </row>\n        <row>\n          <entry>128</entry>\n          <entry>[640, 768, 896, 1024]</entry>\n        </row>\n        <row>\n          <entry>256</entry>\n          <entry>[1280, 1536, 1792, 2048]</entry>\n        </row>\n        <row>\n          <entry>512</entry>\n          <entry>[2560, 3072, 3584, 4096]</entry>\n        </row>\n        <row>\n          <entry>1 KiB</entry>\n          <entry>[5 KiB, 6 KiB, 7 KiB, 8 KiB]</entry>\n        </row>\n        <row>\n          <entry>2 KiB</entry>\n          <entry>[10 KiB, 12 KiB, 14 KiB]</entry>\n        </row>\n        <row>\n          <entry morerows=\"7\">Large</entry>\n          <entry>2 KiB</entry>\n          <entry>[16 KiB]</entry>\n        </row>\n        <row>\n          <entry>4 KiB</entry>\n          <entry>[20 KiB, 24 KiB, 28 KiB, 32 KiB]</entry>\n        </row>\n        <row>\n          <entry>8 KiB</entry>\n          <entry>[40 KiB, 48 KiB, 54 KiB, 64 KiB]</entry>\n        </row>\n        <row>\n          <entry>16 KiB</entry>\n          <entry>[80 KiB, 96 KiB, 112 KiB, 128 KiB]</entry>\n        </row>\n        <row>\n          <entry>32 KiB</entry>\n          <entry>[160 KiB, 192 KiB, 224 KiB, 256 KiB]</entry>\n        </row>\n        <row>\n          <entry>64 KiB</entry>\n          <entry>[320 KiB, 384 KiB, 448 KiB, 512 KiB]</entry>\n        </row>\n        <row>\n          <entry>128 KiB</entry>\n          <entry>[640 KiB, 768 KiB, 896 KiB, 1 MiB]</entry>\n        </row>\n        <row>\n          <entry>256 KiB</entry>\n          <entry>[1280 KiB, 1536 KiB, 1792 KiB]</entry>\n        </row>\n        <row>\n          <entry morerows=\"6\">Huge</entry>\n          <entry>256 KiB</entry>\n          <entry>[2 MiB]</entry>\n        </row>\n        <row>\n          <entry>512 KiB</entry>\n          <entry>[2560 KiB, 3 MiB, 3584 KiB, 4 MiB]</entry>\n        </row>\n        <row>\n          <entry>1 MiB</entry>\n          <entry>[5 MiB, 6 MiB, 7 MiB, 8 MiB]</entry>\n        </row>\n        <row>\n          <entry>2 MiB</entry>\n          <entry>[10 MiB, 12 MiB, 14 MiB, 16 MiB]</entry>\n        </row>\n        <row>\n          <entry>4 MiB</entry>\n          <entry>[20 MiB, 24 MiB, 28 MiB, 32 MiB]</entry>\n        </row>\n        <row>\n          <entry>8 MiB</entry>\n          <entry>[40 MiB, 48 MiB, 56 MiB, 64 MiB]</entry>\n        </row>\n        <row>\n          <entry>...</entry>\n          <entry>...</entry>\n        </row>\n      </tbody>\n      </tgroup>\n    </table>\n  </refsect1>\n  <refsect1 id=\"mallctl_namespace\">\n    <title>MALLCTL NAMESPACE</title>\n    <para>The following names are defined in the namespace accessible via the\n    <function>mallctl*<parameter/></function> functions.  Value types are\n    specified in parentheses, their readable/writable statuses are encoded as\n    <literal>rw</literal>, <literal>r-</literal>, <literal>-w</literal>, or\n    <literal>--</literal>, and required build configuration flags follow, if\n    any.  A name element encoded as <literal>&lt;i&gt;</literal> or\n    <literal>&lt;j&gt;</literal> indicates an integer component, where the\n    integer varies from 0 to some upper value that must be determined via\n    introspection.  In the case of <mallctl>stats.arenas.&lt;i&gt;.*</mallctl>,\n    <literal>&lt;i&gt;</literal> equal to <link\n    linkend=\"arenas.narenas\"><mallctl>arenas.narenas</mallctl></link> can be\n    used to access the summation of statistics from all arenas.  Take special\n    note of the <link linkend=\"epoch\"><mallctl>epoch</mallctl></link> mallctl,\n    which controls refreshing of cached dynamic statistics.</para>\n\n    <variablelist>\n      <varlistentry id=\"version\">\n        <term>\n          <mallctl>version</mallctl>\n          (<type>const char *</type>)\n          <literal>r-</literal>\n        </term>\n        <listitem><para>Return the jemalloc version string.</para></listitem>\n      </varlistentry>\n\n      <varlistentry id=\"epoch\">\n        <term>\n          <mallctl>epoch</mallctl>\n          (<type>uint64_t</type>)\n          <literal>rw</literal>\n        </term>\n        <listitem><para>If a value is passed in, refresh the data from which\n        the <function>mallctl*<parameter/></function> functions report values,\n        and increment the epoch.  Return the current epoch.  This is useful for\n        detecting whether another thread caused a refresh.</para></listitem>\n      </varlistentry>\n\n      <varlistentry id=\"config.cache_oblivious\">\n        <term>\n          <mallctl>config.cache_oblivious</mallctl>\n          (<type>bool</type>)\n          <literal>r-</literal>\n        </term>\n        <listitem><para><option>--enable-cache-oblivious</option> was specified\n        during build configuration.</para></listitem>\n      </varlistentry>\n\n      <varlistentry id=\"config.debug\">\n        <term>\n          <mallctl>config.debug</mallctl>\n          (<type>bool</type>)\n          <literal>r-</literal>\n        </term>\n        <listitem><para><option>--enable-debug</option> was specified during\n        build configuration.</para></listitem>\n      </varlistentry>\n\n      <varlistentry id=\"config.fill\">\n        <term>\n          <mallctl>config.fill</mallctl>\n          (<type>bool</type>)\n          <literal>r-</literal>\n        </term>\n        <listitem><para><option>--enable-fill</option> was specified during\n        build configuration.</para></listitem>\n      </varlistentry>\n\n      <varlistentry id=\"config.lazy_lock\">\n        <term>\n          <mallctl>config.lazy_lock</mallctl>\n          (<type>bool</type>)\n          <literal>r-</literal>\n        </term>\n        <listitem><para><option>--enable-lazy-lock</option> was specified\n        during build configuration.</para></listitem>\n      </varlistentry>\n\n      <varlistentry id=\"config.munmap\">\n        <term>\n          <mallctl>config.munmap</mallctl>\n          (<type>bool</type>)\n          <literal>r-</literal>\n        </term>\n        <listitem><para><option>--enable-munmap</option> was specified during\n        build configuration.</para></listitem>\n      </varlistentry>\n\n      <varlistentry id=\"config.prof\">\n        <term>\n          <mallctl>config.prof</mallctl>\n          (<type>bool</type>)\n          <literal>r-</literal>\n        </term>\n        <listitem><para><option>--enable-prof</option> was specified during\n        build configuration.</para></listitem>\n      </varlistentry>\n\n      <varlistentry id=\"config.prof_libgcc\">\n        <term>\n          <mallctl>config.prof_libgcc</mallctl>\n          (<type>bool</type>)\n          <literal>r-</literal>\n        </term>\n        <listitem><para><option>--disable-prof-libgcc</option> was not\n        specified during build configuration.</para></listitem>\n      </varlistentry>\n\n      <varlistentry id=\"config.prof_libunwind\">\n        <term>\n          <mallctl>config.prof_libunwind</mallctl>\n          (<type>bool</type>)\n          <literal>r-</literal>\n        </term>\n        <listitem><para><option>--enable-prof-libunwind</option> was specified\n        during build configuration.</para></listitem>\n      </varlistentry>\n\n      <varlistentry id=\"config.stats\">\n        <term>\n          <mallctl>config.stats</mallctl>\n          (<type>bool</type>)\n          <literal>r-</literal>\n        </term>\n        <listitem><para><option>--enable-stats</option> was specified during\n        build configuration.</para></listitem>\n      </varlistentry>\n\n      <varlistentry id=\"config.tcache\">\n        <term>\n          <mallctl>config.tcache</mallctl>\n          (<type>bool</type>)\n          <literal>r-</literal>\n        </term>\n        <listitem><para><option>--disable-tcache</option> was not specified\n        during build configuration.</para></listitem>\n      </varlistentry>\n\n      <varlistentry id=\"config.tls\">\n        <term>\n          <mallctl>config.tls</mallctl>\n          (<type>bool</type>)\n          <literal>r-</literal>\n        </term>\n        <listitem><para><option>--disable-tls</option> was not specified during\n        build configuration.</para></listitem>\n      </varlistentry>\n\n      <varlistentry id=\"config.utrace\">\n        <term>\n          <mallctl>config.utrace</mallctl>\n          (<type>bool</type>)\n          <literal>r-</literal>\n        </term>\n        <listitem><para><option>--enable-utrace</option> was specified during\n        build configuration.</para></listitem>\n      </varlistentry>\n\n      <varlistentry id=\"config.valgrind\">\n        <term>\n          <mallctl>config.valgrind</mallctl>\n          (<type>bool</type>)\n          <literal>r-</literal>\n        </term>\n        <listitem><para><option>--enable-valgrind</option> was specified during\n        build configuration.</para></listitem>\n      </varlistentry>\n\n      <varlistentry id=\"config.xmalloc\">\n        <term>\n          <mallctl>config.xmalloc</mallctl>\n          (<type>bool</type>)\n          <literal>r-</literal>\n        </term>\n        <listitem><para><option>--enable-xmalloc</option> was specified during\n        build configuration.</para></listitem>\n      </varlistentry>\n\n      <varlistentry id=\"opt.abort\">\n        <term>\n          <mallctl>opt.abort</mallctl>\n          (<type>bool</type>)\n          <literal>r-</literal>\n        </term>\n        <listitem><para>Abort-on-warning enabled/disabled.  If true, most\n        warnings are fatal.  The process will call\n        <citerefentry><refentrytitle>abort</refentrytitle>\n        <manvolnum>3</manvolnum></citerefentry> in these cases.  This option is\n        disabled by default unless <option>--enable-debug</option> is\n        specified during configuration, in which case it is enabled by default.\n        </para></listitem>\n      </varlistentry>\n\n      <varlistentry id=\"opt.dss\">\n        <term>\n          <mallctl>opt.dss</mallctl>\n          (<type>const char *</type>)\n          <literal>r-</literal>\n        </term>\n        <listitem><para>dss (<citerefentry><refentrytitle>sbrk</refentrytitle>\n        <manvolnum>2</manvolnum></citerefentry>) allocation precedence as\n        related to <citerefentry><refentrytitle>mmap</refentrytitle>\n        <manvolnum>2</manvolnum></citerefentry> allocation.  The following\n        settings are supported if\n        <citerefentry><refentrytitle>sbrk</refentrytitle>\n        <manvolnum>2</manvolnum></citerefentry> is supported by the operating\n        system: &ldquo;disabled&rdquo;, &ldquo;primary&rdquo;, and\n        &ldquo;secondary&rdquo;; otherwise only &ldquo;disabled&rdquo; is\n        supported.  The default is &ldquo;secondary&rdquo; if\n        <citerefentry><refentrytitle>sbrk</refentrytitle>\n        <manvolnum>2</manvolnum></citerefentry> is supported by the operating\n        system; &ldquo;disabled&rdquo; otherwise.\n        </para></listitem>\n      </varlistentry>\n\n      <varlistentry id=\"opt.lg_chunk\">\n        <term>\n          <mallctl>opt.lg_chunk</mallctl>\n          (<type>size_t</type>)\n          <literal>r-</literal>\n        </term>\n        <listitem><para>Virtual memory chunk size (log base 2).  If a chunk\n        size outside the supported size range is specified, the size is\n        silently clipped to the minimum/maximum supported size.  The default\n        chunk size is 2 MiB (2^21).\n        </para></listitem>\n      </varlistentry>\n\n      <varlistentry id=\"opt.narenas\">\n        <term>\n          <mallctl>opt.narenas</mallctl>\n          (<type>size_t</type>)\n          <literal>r-</literal>\n        </term>\n        <listitem><para>Maximum number of arenas to use for automatic\n        multiplexing of threads and arenas.  The default is four times the\n        number of CPUs, or one if there is a single CPU.</para></listitem>\n      </varlistentry>\n\n      <varlistentry id=\"opt.lg_dirty_mult\">\n        <term>\n          <mallctl>opt.lg_dirty_mult</mallctl>\n          (<type>ssize_t</type>)\n          <literal>r-</literal>\n        </term>\n        <listitem><para>Per-arena minimum ratio (log base 2) of active to dirty\n        pages.  Some dirty unused pages may be allowed to accumulate, within\n        the limit set by the ratio (or one chunk worth of dirty pages,\n        whichever is greater), before informing the kernel about some of those\n        pages via <citerefentry><refentrytitle>madvise</refentrytitle>\n        <manvolnum>2</manvolnum></citerefentry> or a similar system call.  This\n        provides the kernel with sufficient information to recycle dirty pages\n        if physical memory becomes scarce and the pages remain unused.  The\n        default minimum ratio is 8:1 (2^3:1); an option value of -1 will\n        disable dirty page purging.  See <link\n        linkend=\"arenas.lg_dirty_mult\"><mallctl>arenas.lg_dirty_mult</mallctl></link>\n        and <link\n        linkend=\"arena.i.lg_dirty_mult\"><mallctl>arena.&lt;i&gt;.lg_dirty_mult</mallctl></link>\n        for related dynamic control options.</para></listitem>\n      </varlistentry>\n\n      <varlistentry id=\"opt.stats_print\">\n        <term>\n          <mallctl>opt.stats_print</mallctl>\n          (<type>bool</type>)\n          <literal>r-</literal>\n        </term>\n        <listitem><para>Enable/disable statistics printing at exit.  If\n        enabled, the <function>malloc_stats_print<parameter/></function>\n        function is called at program exit via an\n        <citerefentry><refentrytitle>atexit</refentrytitle>\n        <manvolnum>3</manvolnum></citerefentry> function.  If\n        <option>--enable-stats</option> is specified during configuration, this\n        has the potential to cause deadlock for a multi-threaded process that\n        exits while one or more threads are executing in the memory allocation\n        functions.  Furthermore, <function>atexit<parameter/></function> may\n        allocate memory during application initialization and then deadlock\n        internally when jemalloc in turn calls\n        <function>atexit<parameter/></function>, so this option is not\n        univerally usable (though the application can register its own\n        <function>atexit<parameter/></function> function with equivalent\n        functionality).  Therefore, this option should only be used with care;\n        it is primarily intended as a performance tuning aid during application\n        development.  This option is disabled by default.</para></listitem>\n      </varlistentry>\n\n      <varlistentry id=\"opt.junk\">\n        <term>\n          <mallctl>opt.junk</mallctl>\n          (<type>const char *</type>)\n          <literal>r-</literal>\n          [<option>--enable-fill</option>]\n        </term>\n        <listitem><para>Junk filling.  If set to \"alloc\", each byte of\n        uninitialized allocated memory will be initialized to\n        <literal>0xa5</literal>.  If set to \"free\", all deallocated memory will\n        be initialized to <literal>0x5a</literal>.  If set to \"true\", both\n        allocated and deallocated memory will be initialized, and if set to\n        \"false\", junk filling be disabled entirely.  This is intended for\n        debugging and will impact performance negatively.  This option is\n        \"false\" by default unless <option>--enable-debug</option> is specified\n        during configuration, in which case it is \"true\" by default unless\n        running inside <ulink\n        url=\"http://valgrind.org/\">Valgrind</ulink>.</para></listitem>\n      </varlistentry>\n\n      <varlistentry id=\"opt.quarantine\">\n        <term>\n          <mallctl>opt.quarantine</mallctl>\n          (<type>size_t</type>)\n          <literal>r-</literal>\n          [<option>--enable-fill</option>]\n        </term>\n        <listitem><para>Per thread quarantine size in bytes.  If non-zero, each\n        thread maintains a FIFO object quarantine that stores up to the\n        specified number of bytes of memory.  The quarantined memory is not\n        freed until it is released from quarantine, though it is immediately\n        junk-filled if the <link\n        linkend=\"opt.junk\"><mallctl>opt.junk</mallctl></link> option is\n        enabled.  This feature is of particular use in combination with <ulink\n        url=\"http://valgrind.org/\">Valgrind</ulink>, which can detect attempts\n        to access quarantined objects.  This is intended for debugging and will\n        impact performance negatively.  The default quarantine size is 0 unless\n        running inside Valgrind, in which case the default is 16\n        MiB.</para></listitem>\n      </varlistentry>\n\n      <varlistentry id=\"opt.redzone\">\n        <term>\n          <mallctl>opt.redzone</mallctl>\n          (<type>bool</type>)\n          <literal>r-</literal>\n          [<option>--enable-fill</option>]\n        </term>\n        <listitem><para>Redzones enabled/disabled.  If enabled, small\n        allocations have redzones before and after them.  Furthermore, if the\n        <link linkend=\"opt.junk\"><mallctl>opt.junk</mallctl></link> option is\n        enabled, the redzones are checked for corruption during deallocation.\n        However, the primary intended purpose of this feature is to be used in\n        combination with <ulink url=\"http://valgrind.org/\">Valgrind</ulink>,\n        which needs redzones in order to do effective buffer overflow/underflow\n        detection.  This option is intended for debugging and will impact\n        performance negatively.  This option is disabled by\n        default unless running inside Valgrind.</para></listitem>\n      </varlistentry>\n\n      <varlistentry id=\"opt.zero\">\n        <term>\n          <mallctl>opt.zero</mallctl>\n          (<type>bool</type>)\n          <literal>r-</literal>\n          [<option>--enable-fill</option>]\n        </term>\n        <listitem><para>Zero filling enabled/disabled.  If enabled, each byte\n        of uninitialized allocated memory will be initialized to 0.  Note that\n        this initialization only happens once for each byte, so\n        <function>realloc<parameter/></function> and\n        <function>rallocx<parameter/></function> calls do not zero memory that\n        was previously allocated.  This is intended for debugging and will\n        impact performance negatively.  This option is disabled by default.\n        </para></listitem>\n      </varlistentry>\n\n      <varlistentry id=\"opt.utrace\">\n        <term>\n          <mallctl>opt.utrace</mallctl>\n          (<type>bool</type>)\n          <literal>r-</literal>\n          [<option>--enable-utrace</option>]\n        </term>\n        <listitem><para>Allocation tracing based on\n        <citerefentry><refentrytitle>utrace</refentrytitle>\n        <manvolnum>2</manvolnum></citerefentry> enabled/disabled.  This option\n        is disabled by default.</para></listitem>\n      </varlistentry>\n\n      <varlistentry id=\"opt.xmalloc\">\n        <term>\n          <mallctl>opt.xmalloc</mallctl>\n          (<type>bool</type>)\n          <literal>r-</literal>\n          [<option>--enable-xmalloc</option>]\n        </term>\n        <listitem><para>Abort-on-out-of-memory enabled/disabled.  If enabled,\n        rather than returning failure for any allocation function, display a\n        diagnostic message on <constant>STDERR_FILENO</constant> and cause the\n        program to drop core (using\n        <citerefentry><refentrytitle>abort</refentrytitle>\n        <manvolnum>3</manvolnum></citerefentry>).  If an application is\n        designed to depend on this behavior, set the option at compile time by\n        including the following in the source code:\n        <programlisting language=\"C\"><![CDATA[\nmalloc_conf = \"xmalloc:true\";]]></programlisting>\n        This option is disabled by default.</para></listitem>\n      </varlistentry>\n\n      <varlistentry id=\"opt.tcache\">\n        <term>\n          <mallctl>opt.tcache</mallctl>\n          (<type>bool</type>)\n          <literal>r-</literal>\n          [<option>--enable-tcache</option>]\n        </term>\n        <listitem><para>Thread-specific caching (tcache) enabled/disabled.  When\n        there are multiple threads, each thread uses a tcache for objects up to\n        a certain size.  Thread-specific caching allows many allocations to be\n        satisfied without performing any thread synchronization, at the cost of\n        increased memory use.  See the <link\n        linkend=\"opt.lg_tcache_max\"><mallctl>opt.lg_tcache_max</mallctl></link>\n        option for related tuning information.  This option is enabled by\n        default unless running inside <ulink\n        url=\"http://valgrind.org/\">Valgrind</ulink>, in which case it is\n        forcefully disabled.</para></listitem>\n      </varlistentry>\n\n      <varlistentry id=\"opt.lg_tcache_max\">\n        <term>\n          <mallctl>opt.lg_tcache_max</mallctl>\n          (<type>size_t</type>)\n          <literal>r-</literal>\n          [<option>--enable-tcache</option>]\n        </term>\n        <listitem><para>Maximum size class (log base 2) to cache in the\n        thread-specific cache (tcache).  At a minimum, all small size classes\n        are cached, and at a maximum all large size classes are cached.  The\n        default maximum is 32 KiB (2^15).</para></listitem>\n      </varlistentry>\n\n      <varlistentry id=\"opt.prof\">\n        <term>\n          <mallctl>opt.prof</mallctl>\n          (<type>bool</type>)\n          <literal>r-</literal>\n          [<option>--enable-prof</option>]\n        </term>\n        <listitem><para>Memory profiling enabled/disabled.  If enabled, profile\n        memory allocation activity.  See the <link\n        linkend=\"opt.prof_active\"><mallctl>opt.prof_active</mallctl></link>\n        option for on-the-fly activation/deactivation.  See the <link\n        linkend=\"opt.lg_prof_sample\"><mallctl>opt.lg_prof_sample</mallctl></link>\n        option for probabilistic sampling control.  See the <link\n        linkend=\"opt.prof_accum\"><mallctl>opt.prof_accum</mallctl></link>\n        option for control of cumulative sample reporting.  See the <link\n        linkend=\"opt.lg_prof_interval\"><mallctl>opt.lg_prof_interval</mallctl></link>\n        option for information on interval-triggered profile dumping, the <link\n        linkend=\"opt.prof_gdump\"><mallctl>opt.prof_gdump</mallctl></link>\n        option for information on high-water-triggered profile dumping, and the\n        <link linkend=\"opt.prof_final\"><mallctl>opt.prof_final</mallctl></link>\n        option for final profile dumping.  Profile output is compatible with\n        the <command>jeprof</command> command, which is based on the\n        <command>pprof</command> that is developed as part of the <ulink\n        url=\"http://code.google.com/p/gperftools/\">gperftools\n        package</ulink>.</para></listitem>\n      </varlistentry>\n\n      <varlistentry id=\"opt.prof_prefix\">\n        <term>\n          <mallctl>opt.prof_prefix</mallctl>\n          (<type>const char *</type>)\n          <literal>r-</literal>\n          [<option>--enable-prof</option>]\n        </term>\n        <listitem><para>Filename prefix for profile dumps.  If the prefix is\n        set to the empty string, no automatic dumps will occur; this is\n        primarily useful for disabling the automatic final heap dump (which\n        also disables leak reporting, if enabled).  The default prefix is\n        <filename>jeprof</filename>.</para></listitem>\n      </varlistentry>\n\n      <varlistentry id=\"opt.prof_active\">\n        <term>\n          <mallctl>opt.prof_active</mallctl>\n          (<type>bool</type>)\n          <literal>r-</literal>\n          [<option>--enable-prof</option>]\n        </term>\n        <listitem><para>Profiling activated/deactivated.  This is a secondary\n        control mechanism that makes it possible to start the application with\n        profiling enabled (see the <link\n        linkend=\"opt.prof\"><mallctl>opt.prof</mallctl></link> option) but\n        inactive, then toggle profiling at any time during program execution\n        with the <link\n        linkend=\"prof.active\"><mallctl>prof.active</mallctl></link> mallctl.\n        This option is enabled by default.</para></listitem>\n      </varlistentry>\n\n      <varlistentry id=\"opt.prof_thread_active_init\">\n        <term>\n          <mallctl>opt.prof_thread_active_init</mallctl>\n          (<type>bool</type>)\n          <literal>r-</literal>\n          [<option>--enable-prof</option>]\n        </term>\n        <listitem><para>Initial setting for <link\n        linkend=\"thread.prof.active\"><mallctl>thread.prof.active</mallctl></link>\n        in newly created threads.  The initial setting for newly created threads\n        can also be changed during execution via the <link\n        linkend=\"prof.thread_active_init\"><mallctl>prof.thread_active_init</mallctl></link>\n        mallctl.  This option is enabled by default.</para></listitem>\n      </varlistentry>\n\n      <varlistentry id=\"opt.lg_prof_sample\">\n        <term>\n          <mallctl>opt.lg_prof_sample</mallctl>\n          (<type>size_t</type>)\n          <literal>r-</literal>\n          [<option>--enable-prof</option>]\n        </term>\n        <listitem><para>Average interval (log base 2) between allocation\n        samples, as measured in bytes of allocation activity.  Increasing the\n        sampling interval decreases profile fidelity, but also decreases the\n        computational overhead.  The default sample interval is 512 KiB (2^19\n        B).</para></listitem>\n      </varlistentry>\n\n      <varlistentry id=\"opt.prof_accum\">\n        <term>\n          <mallctl>opt.prof_accum</mallctl>\n          (<type>bool</type>)\n          <literal>r-</literal>\n          [<option>--enable-prof</option>]\n        </term>\n        <listitem><para>Reporting of cumulative object/byte counts in profile\n        dumps enabled/disabled.  If this option is enabled, every unique\n        backtrace must be stored for the duration of execution.  Depending on\n        the application, this can impose a large memory overhead, and the\n        cumulative counts are not always of interest.  This option is disabled\n        by default.</para></listitem>\n      </varlistentry>\n\n      <varlistentry id=\"opt.lg_prof_interval\">\n        <term>\n          <mallctl>opt.lg_prof_interval</mallctl>\n          (<type>ssize_t</type>)\n          <literal>r-</literal>\n          [<option>--enable-prof</option>]\n        </term>\n        <listitem><para>Average interval (log base 2) between memory profile\n        dumps, as measured in bytes of allocation activity.  The actual\n        interval between dumps may be sporadic because decentralized allocation\n        counters are used to avoid synchronization bottlenecks.  Profiles are\n        dumped to files named according to the pattern\n        <filename>&lt;prefix&gt;.&lt;pid&gt;.&lt;seq&gt;.i&lt;iseq&gt;.heap</filename>,\n        where <literal>&lt;prefix&gt;</literal> is controlled by the\n        <link\n        linkend=\"opt.prof_prefix\"><mallctl>opt.prof_prefix</mallctl></link>\n        option.  By default, interval-triggered profile dumping is disabled\n        (encoded as -1).\n        </para></listitem>\n      </varlistentry>\n\n      <varlistentry id=\"opt.prof_gdump\">\n        <term>\n          <mallctl>opt.prof_gdump</mallctl>\n          (<type>bool</type>)\n          <literal>r-</literal>\n          [<option>--enable-prof</option>]\n        </term>\n        <listitem><para>Set the initial state of <link\n        linkend=\"prof.gdump\"><mallctl>prof.gdump</mallctl></link>, which when\n        enabled triggers a memory profile dump every time the total virtual\n        memory exceeds the previous maximum.  This option is disabled by\n        default.</para></listitem>\n      </varlistentry>\n\n      <varlistentry id=\"opt.prof_final\">\n        <term>\n          <mallctl>opt.prof_final</mallctl>\n          (<type>bool</type>)\n          <literal>r-</literal>\n          [<option>--enable-prof</option>]\n        </term>\n        <listitem><para>Use an\n        <citerefentry><refentrytitle>atexit</refentrytitle>\n        <manvolnum>3</manvolnum></citerefentry> function to dump final memory\n        usage to a file named according to the pattern\n        <filename>&lt;prefix&gt;.&lt;pid&gt;.&lt;seq&gt;.f.heap</filename>,\n        where <literal>&lt;prefix&gt;</literal> is controlled by the <link\n        linkend=\"opt.prof_prefix\"><mallctl>opt.prof_prefix</mallctl></link>\n        option.  Note that <function>atexit<parameter/></function> may allocate\n        memory during application initialization and then deadlock internally\n        when jemalloc in turn calls <function>atexit<parameter/></function>, so\n        this option is not univerally usable (though the application can\n        register its own <function>atexit<parameter/></function> function with\n        equivalent functionality).  This option is disabled by\n        default.</para></listitem>\n      </varlistentry>\n\n      <varlistentry id=\"opt.prof_leak\">\n        <term>\n          <mallctl>opt.prof_leak</mallctl>\n          (<type>bool</type>)\n          <literal>r-</literal>\n          [<option>--enable-prof</option>]\n        </term>\n        <listitem><para>Leak reporting enabled/disabled.  If enabled, use an\n        <citerefentry><refentrytitle>atexit</refentrytitle>\n        <manvolnum>3</manvolnum></citerefentry> function to report memory leaks\n        detected by allocation sampling.  See the\n        <link linkend=\"opt.prof\"><mallctl>opt.prof</mallctl></link> option for\n        information on analyzing heap profile output.  This option is disabled\n        by default.</para></listitem>\n      </varlistentry>\n\n      <varlistentry id=\"thread.arena\">\n        <term>\n          <mallctl>thread.arena</mallctl>\n          (<type>unsigned</type>)\n          <literal>rw</literal>\n        </term>\n        <listitem><para>Get or set the arena associated with the calling\n        thread.  If the specified arena was not initialized beforehand (see the\n        <link\n        linkend=\"arenas.initialized\"><mallctl>arenas.initialized</mallctl></link>\n        mallctl), it will be automatically initialized as a side effect of\n        calling this interface.</para></listitem>\n      </varlistentry>\n\n      <varlistentry id=\"thread.allocated\">\n        <term>\n          <mallctl>thread.allocated</mallctl>\n          (<type>uint64_t</type>)\n          <literal>r-</literal>\n          [<option>--enable-stats</option>]\n        </term>\n        <listitem><para>Get the total number of bytes ever allocated by the\n        calling thread.  This counter has the potential to wrap around; it is\n        up to the application to appropriately interpret the counter in such\n        cases.</para></listitem>\n      </varlistentry>\n\n      <varlistentry id=\"thread.allocatedp\">\n        <term>\n          <mallctl>thread.allocatedp</mallctl>\n          (<type>uint64_t *</type>)\n          <literal>r-</literal>\n          [<option>--enable-stats</option>]\n        </term>\n        <listitem><para>Get a pointer to the the value that is returned by the\n        <link\n        linkend=\"thread.allocated\"><mallctl>thread.allocated</mallctl></link>\n        mallctl.  This is useful for avoiding the overhead of repeated\n        <function>mallctl*<parameter/></function> calls.</para></listitem>\n      </varlistentry>\n\n      <varlistentry id=\"thread.deallocated\">\n        <term>\n          <mallctl>thread.deallocated</mallctl>\n          (<type>uint64_t</type>)\n          <literal>r-</literal>\n          [<option>--enable-stats</option>]\n        </term>\n        <listitem><para>Get the total number of bytes ever deallocated by the\n        calling thread.  This counter has the potential to wrap around; it is\n        up to the application to appropriately interpret the counter in such\n        cases.</para></listitem>\n      </varlistentry>\n\n      <varlistentry id=\"thread.deallocatedp\">\n        <term>\n          <mallctl>thread.deallocatedp</mallctl>\n          (<type>uint64_t *</type>)\n          <literal>r-</literal>\n          [<option>--enable-stats</option>]\n        </term>\n        <listitem><para>Get a pointer to the the value that is returned by the\n        <link\n        linkend=\"thread.deallocated\"><mallctl>thread.deallocated</mallctl></link>\n        mallctl.  This is useful for avoiding the overhead of repeated\n        <function>mallctl*<parameter/></function> calls.</para></listitem>\n      </varlistentry>\n\n      <varlistentry id=\"thread.tcache.enabled\">\n        <term>\n          <mallctl>thread.tcache.enabled</mallctl>\n          (<type>bool</type>)\n          <literal>rw</literal>\n          [<option>--enable-tcache</option>]\n        </term>\n        <listitem><para>Enable/disable calling thread's tcache.  The tcache is\n        implicitly flushed as a side effect of becoming\n        disabled (see <link\n        linkend=\"thread.tcache.flush\"><mallctl>thread.tcache.flush</mallctl></link>).\n        </para></listitem>\n      </varlistentry>\n\n      <varlistentry id=\"thread.tcache.flush\">\n        <term>\n          <mallctl>thread.tcache.flush</mallctl>\n          (<type>void</type>)\n          <literal>--</literal>\n          [<option>--enable-tcache</option>]\n        </term>\n        <listitem><para>Flush calling thread's thread-specific cache (tcache).\n        This interface releases all cached objects and internal data structures\n        associated with the calling thread's tcache.  Ordinarily, this interface\n        need not be called, since automatic periodic incremental garbage\n        collection occurs, and the thread cache is automatically discarded when\n        a thread exits.  However, garbage collection is triggered by allocation\n        activity, so it is possible for a thread that stops\n        allocating/deallocating to retain its cache indefinitely, in which case\n        the developer may find manual flushing useful.</para></listitem>\n      </varlistentry>\n\n      <varlistentry id=\"thread.prof.name\">\n        <term>\n          <mallctl>thread.prof.name</mallctl>\n          (<type>const char *</type>)\n          <literal>r-</literal> or\n          <literal>-w</literal>\n          [<option>--enable-prof</option>]\n        </term>\n        <listitem><para>Get/set the descriptive name associated with the calling\n        thread in memory profile dumps.  An internal copy of the name string is\n        created, so the input string need not be maintained after this interface\n        completes execution.  The output string of this interface should be\n        copied for non-ephemeral uses, because multiple implementation details\n        can cause asynchronous string deallocation.  Furthermore, each\n        invocation of this interface can only read or write; simultaneous\n        read/write is not supported due to string lifetime limitations.  The\n        name string must nil-terminated and comprised only of characters in the\n        sets recognized\n        by <citerefentry><refentrytitle>isgraph</refentrytitle>\n        <manvolnum>3</manvolnum></citerefentry> and\n        <citerefentry><refentrytitle>isblank</refentrytitle>\n        <manvolnum>3</manvolnum></citerefentry>.</para></listitem>\n      </varlistentry>\n\n      <varlistentry id=\"thread.prof.active\">\n        <term>\n          <mallctl>thread.prof.active</mallctl>\n          (<type>bool</type>)\n          <literal>rw</literal>\n          [<option>--enable-prof</option>]\n        </term>\n        <listitem><para>Control whether sampling is currently active for the\n        calling thread.  This is an activation mechanism in addition to <link\n        linkend=\"prof.active\"><mallctl>prof.active</mallctl></link>; both must\n        be active for the calling thread to sample.  This flag is enabled by\n        default.</para></listitem>\n      </varlistentry>\n\n      <varlistentry id=\"tcache.create\">\n        <term>\n          <mallctl>tcache.create</mallctl>\n          (<type>unsigned</type>)\n          <literal>r-</literal>\n          [<option>--enable-tcache</option>]\n        </term>\n        <listitem><para>Create an explicit thread-specific cache (tcache) and\n        return an identifier that can be passed to the <link\n        linkend=\"MALLOCX_TCACHE\"><constant>MALLOCX_TCACHE(<parameter>tc</parameter>)</constant></link>\n        macro to explicitly use the specified cache rather than the\n        automatically managed one that is used by default.  Each explicit cache\n        can be used by only one thread at a time; the application must assure\n        that this constraint holds.\n        </para></listitem>\n      </varlistentry>\n\n      <varlistentry id=\"tcache.flush\">\n        <term>\n          <mallctl>tcache.flush</mallctl>\n          (<type>unsigned</type>)\n          <literal>-w</literal>\n          [<option>--enable-tcache</option>]\n        </term>\n        <listitem><para>Flush the specified thread-specific cache (tcache).  The\n        same considerations apply to this interface as to <link\n        linkend=\"thread.tcache.flush\"><mallctl>thread.tcache.flush</mallctl></link>,\n        except that the tcache will never be automatically be discarded.\n        </para></listitem>\n      </varlistentry>\n\n      <varlistentry id=\"tcache.destroy\">\n        <term>\n          <mallctl>tcache.destroy</mallctl>\n          (<type>unsigned</type>)\n          <literal>-w</literal>\n          [<option>--enable-tcache</option>]\n        </term>\n        <listitem><para>Flush the specified thread-specific cache (tcache) and\n        make the identifier available for use during a future tcache creation.\n        </para></listitem>\n      </varlistentry>\n\n      <varlistentry id=\"arena.i.purge\">\n        <term>\n          <mallctl>arena.&lt;i&gt;.purge</mallctl>\n          (<type>void</type>)\n          <literal>--</literal>\n        </term>\n        <listitem><para>Purge unused dirty pages for arena &lt;i&gt;, or for\n        all arenas if &lt;i&gt; equals <link\n        linkend=\"arenas.narenas\"><mallctl>arenas.narenas</mallctl></link>.\n        </para></listitem>\n      </varlistentry>\n\n      <varlistentry id=\"arena.i.dss\">\n        <term>\n          <mallctl>arena.&lt;i&gt;.dss</mallctl>\n          (<type>const char *</type>)\n          <literal>rw</literal>\n        </term>\n        <listitem><para>Set the precedence of dss allocation as related to mmap\n        allocation for arena &lt;i&gt;, or for all arenas if &lt;i&gt; equals\n        <link\n        linkend=\"arenas.narenas\"><mallctl>arenas.narenas</mallctl></link>.  See\n        <link linkend=\"opt.dss\"><mallctl>opt.dss</mallctl></link> for supported\n        settings.</para></listitem>\n      </varlistentry>\n\n      <varlistentry id=\"arena.i.lg_dirty_mult\">\n        <term>\n          <mallctl>arena.&lt;i&gt;.lg_dirty_mult</mallctl>\n          (<type>ssize_t</type>)\n          <literal>rw</literal>\n        </term>\n        <listitem><para>Current per-arena minimum ratio (log base 2) of active\n        to dirty pages for arena &lt;i&gt;.  Each time this interface is set and\n        the ratio is increased, pages are synchronously purged as necessary to\n        impose the new ratio.  See <link\n        linkend=\"opt.lg_dirty_mult\"><mallctl>opt.lg_dirty_mult</mallctl></link>\n        for additional information.</para></listitem>\n      </varlistentry>\n\n      <varlistentry id=\"arena.i.chunk_hooks\">\n        <term>\n          <mallctl>arena.&lt;i&gt;.chunk_hooks</mallctl>\n          (<type>chunk_hooks_t</type>)\n          <literal>rw</literal>\n        </term>\n        <listitem><para>Get or set the chunk management hook functions for arena\n        &lt;i&gt;.  The functions must be capable of operating on all extant\n        chunks associated with arena &lt;i&gt;, usually by passing unknown\n        chunks to the replaced functions.  In practice, it is feasible to\n        control allocation for arenas created via <link\n        linkend=\"arenas.extend\"><mallctl>arenas.extend</mallctl></link> such\n        that all chunks originate from an application-supplied chunk allocator\n        (by setting custom chunk hook functions just after arena creation), but\n        the automatically created arenas may have already created chunks prior\n        to the application having an opportunity to take over chunk\n        allocation.</para>\n\n        <programlisting language=\"C\"><![CDATA[\ntypedef struct {\n\tchunk_alloc_t\t\t*alloc;\n\tchunk_dalloc_t\t\t*dalloc;\n\tchunk_commit_t\t\t*commit;\n\tchunk_decommit_t\t*decommit;\n\tchunk_purge_t\t\t*purge;\n\tchunk_split_t\t\t*split;\n\tchunk_merge_t\t\t*merge;\n} chunk_hooks_t;]]></programlisting>\n        <para>The <type>chunk_hooks_t</type> structure comprises function\n        pointers which are described individually below.  jemalloc uses these\n        functions to manage chunk lifetime, which starts off with allocation of\n        mapped committed memory, in the simplest case followed by deallocation.\n        However, there are performance and platform reasons to retain chunks for\n        later reuse.  Cleanup attempts cascade from deallocation to decommit to\n        purging, which gives the chunk management functions opportunities to\n        reject the most permanent cleanup operations in favor of less permanent\n        (and often less costly) operations.  The chunk splitting and merging\n        operations can also be opted out of, but this is mainly intended to\n        support platforms on which virtual memory mappings provided by the\n        operating system kernel do not automatically coalesce and split, e.g.\n        Windows.</para>\n\n        <funcsynopsis><funcprototype>\n          <funcdef>typedef void *<function>(chunk_alloc_t)</function></funcdef>\n          <paramdef>void *<parameter>chunk</parameter></paramdef>\n          <paramdef>size_t <parameter>size</parameter></paramdef>\n          <paramdef>size_t <parameter>alignment</parameter></paramdef>\n          <paramdef>bool *<parameter>zero</parameter></paramdef>\n          <paramdef>bool *<parameter>commit</parameter></paramdef>\n          <paramdef>unsigned <parameter>arena_ind</parameter></paramdef>\n        </funcprototype></funcsynopsis>\n        <literallayout></literallayout>\n        <para>A chunk allocation function conforms to the\n        <type>chunk_alloc_t</type> type and upon success returns a pointer to\n        <parameter>size</parameter> bytes of mapped memory on behalf of arena\n        <parameter>arena_ind</parameter> such that the chunk's base address is a\n        multiple of <parameter>alignment</parameter>, as well as setting\n        <parameter>*zero</parameter> to indicate whether the chunk is zeroed and\n        <parameter>*commit</parameter> to indicate whether the chunk is\n        committed.  Upon error the function returns <constant>NULL</constant>\n        and leaves <parameter>*zero</parameter> and\n        <parameter>*commit</parameter> unmodified.  The\n        <parameter>size</parameter> parameter is always a multiple of the chunk\n        size.  The <parameter>alignment</parameter> parameter is always a power\n        of two at least as large as the chunk size.  Zeroing is mandatory if\n        <parameter>*zero</parameter> is true upon function entry.  Committing is\n        mandatory if <parameter>*commit</parameter> is true upon function entry.\n        If <parameter>chunk</parameter> is not <constant>NULL</constant>, the\n        returned pointer must be <parameter>chunk</parameter> on success or\n        <constant>NULL</constant> on error.  Committed memory may be committed\n        in absolute terms as on a system that does not overcommit, or in\n        implicit terms as on a system that overcommits and satisfies physical\n        memory needs on demand via soft page faults.  Note that replacing the\n        default chunk allocation function makes the arena's <link\n        linkend=\"arena.i.dss\"><mallctl>arena.&lt;i&gt;.dss</mallctl></link>\n        setting irrelevant.</para>\n\n        <funcsynopsis><funcprototype>\n          <funcdef>typedef bool <function>(chunk_dalloc_t)</function></funcdef>\n          <paramdef>void *<parameter>chunk</parameter></paramdef>\n          <paramdef>size_t <parameter>size</parameter></paramdef>\n          <paramdef>bool <parameter>committed</parameter></paramdef>\n          <paramdef>unsigned <parameter>arena_ind</parameter></paramdef>\n        </funcprototype></funcsynopsis>\n        <literallayout></literallayout>\n        <para>\n        A chunk deallocation function conforms to the\n        <type>chunk_dalloc_t</type> type and deallocates a\n        <parameter>chunk</parameter> of given <parameter>size</parameter> with\n        <parameter>committed</parameter>/decommited memory as indicated, on\n        behalf of arena <parameter>arena_ind</parameter>, returning false upon\n        success.  If the function returns true, this indicates opt-out from\n        deallocation; the virtual memory mapping associated with the chunk\n        remains mapped, in the same commit state, and available for future use,\n        in which case it will be automatically retained for later reuse.</para>\n\n        <funcsynopsis><funcprototype>\n          <funcdef>typedef bool <function>(chunk_commit_t)</function></funcdef>\n          <paramdef>void *<parameter>chunk</parameter></paramdef>\n          <paramdef>size_t <parameter>size</parameter></paramdef>\n          <paramdef>size_t <parameter>offset</parameter></paramdef>\n          <paramdef>size_t <parameter>length</parameter></paramdef>\n          <paramdef>unsigned <parameter>arena_ind</parameter></paramdef>\n        </funcprototype></funcsynopsis>\n        <literallayout></literallayout>\n        <para>A chunk commit function conforms to the\n        <type>chunk_commit_t</type> type and commits zeroed physical memory to\n        back pages within a <parameter>chunk</parameter> of given\n        <parameter>size</parameter> at <parameter>offset</parameter> bytes,\n        extending for <parameter>length</parameter> on behalf of arena\n        <parameter>arena_ind</parameter>, returning false upon success.\n        Committed memory may be committed in absolute terms as on a system that\n        does not overcommit, or in implicit terms as on a system that\n        overcommits and satisfies physical memory needs on demand via soft page\n        faults. If the function returns true, this indicates insufficient\n        physical memory to satisfy the request.</para>\n\n        <funcsynopsis><funcprototype>\n          <funcdef>typedef bool <function>(chunk_decommit_t)</function></funcdef>\n          <paramdef>void *<parameter>chunk</parameter></paramdef>\n          <paramdef>size_t <parameter>size</parameter></paramdef>\n          <paramdef>size_t <parameter>offset</parameter></paramdef>\n          <paramdef>size_t <parameter>length</parameter></paramdef>\n          <paramdef>unsigned <parameter>arena_ind</parameter></paramdef>\n        </funcprototype></funcsynopsis>\n        <literallayout></literallayout>\n        <para>A chunk decommit function conforms to the\n        <type>chunk_decommit_t</type> type and decommits any physical memory\n        that is backing pages within a <parameter>chunk</parameter> of given\n        <parameter>size</parameter> at <parameter>offset</parameter> bytes,\n        extending for <parameter>length</parameter> on behalf of arena\n        <parameter>arena_ind</parameter>, returning false upon success, in which\n        case the pages will be committed via the chunk commit function before\n        being reused.  If the function returns true, this indicates opt-out from\n        decommit; the memory remains committed and available for future use, in\n        which case it will be automatically retained for later reuse.</para>\n\n        <funcsynopsis><funcprototype>\n          <funcdef>typedef bool <function>(chunk_purge_t)</function></funcdef>\n          <paramdef>void *<parameter>chunk</parameter></paramdef>\n          <paramdef>size_t<parameter>size</parameter></paramdef>\n          <paramdef>size_t <parameter>offset</parameter></paramdef>\n          <paramdef>size_t <parameter>length</parameter></paramdef>\n          <paramdef>unsigned <parameter>arena_ind</parameter></paramdef>\n        </funcprototype></funcsynopsis>\n        <literallayout></literallayout>\n        <para>A chunk purge function conforms to the <type>chunk_purge_t</type>\n        type and optionally discards physical pages within the virtual memory\n        mapping associated with <parameter>chunk</parameter> of given\n        <parameter>size</parameter> at <parameter>offset</parameter> bytes,\n        extending for <parameter>length</parameter> on behalf of arena\n        <parameter>arena_ind</parameter>, returning false if pages within the\n        purged virtual memory range will be zero-filled the next time they are\n        accessed.</para>\n\n        <funcsynopsis><funcprototype>\n          <funcdef>typedef bool <function>(chunk_split_t)</function></funcdef>\n          <paramdef>void *<parameter>chunk</parameter></paramdef>\n          <paramdef>size_t <parameter>size</parameter></paramdef>\n          <paramdef>size_t <parameter>size_a</parameter></paramdef>\n          <paramdef>size_t <parameter>size_b</parameter></paramdef>\n          <paramdef>bool <parameter>committed</parameter></paramdef>\n          <paramdef>unsigned <parameter>arena_ind</parameter></paramdef>\n        </funcprototype></funcsynopsis>\n        <literallayout></literallayout>\n        <para>A chunk split function conforms to the <type>chunk_split_t</type>\n        type and optionally splits <parameter>chunk</parameter> of given\n        <parameter>size</parameter> into two adjacent chunks, the first of\n        <parameter>size_a</parameter> bytes, and the second of\n        <parameter>size_b</parameter> bytes, operating on\n        <parameter>committed</parameter>/decommitted memory as indicated, on\n        behalf of arena <parameter>arena_ind</parameter>, returning false upon\n        success.  If the function returns true, this indicates that the chunk\n        remains unsplit and therefore should continue to be operated on as a\n        whole.</para>\n\n        <funcsynopsis><funcprototype>\n          <funcdef>typedef bool <function>(chunk_merge_t)</function></funcdef>\n          <paramdef>void *<parameter>chunk_a</parameter></paramdef>\n          <paramdef>size_t <parameter>size_a</parameter></paramdef>\n          <paramdef>void *<parameter>chunk_b</parameter></paramdef>\n          <paramdef>size_t <parameter>size_b</parameter></paramdef>\n          <paramdef>bool <parameter>committed</parameter></paramdef>\n          <paramdef>unsigned <parameter>arena_ind</parameter></paramdef>\n        </funcprototype></funcsynopsis>\n        <literallayout></literallayout>\n        <para>A chunk merge function conforms to the <type>chunk_merge_t</type>\n        type and optionally merges adjacent chunks,\n        <parameter>chunk_a</parameter> of given <parameter>size_a</parameter>\n        and <parameter>chunk_b</parameter> of given\n        <parameter>size_b</parameter> into one contiguous chunk, operating on\n        <parameter>committed</parameter>/decommitted memory as indicated, on\n        behalf of arena <parameter>arena_ind</parameter>, returning false upon\n        success.  If the function returns true, this indicates that the chunks\n        remain distinct mappings and therefore should continue to be operated on\n        independently.</para>\n        </listitem>\n      </varlistentry>\n\n      <varlistentry id=\"arenas.narenas\">\n        <term>\n          <mallctl>arenas.narenas</mallctl>\n          (<type>unsigned</type>)\n          <literal>r-</literal>\n        </term>\n        <listitem><para>Current limit on number of arenas.</para></listitem>\n      </varlistentry>\n\n      <varlistentry id=\"arenas.initialized\">\n        <term>\n          <mallctl>arenas.initialized</mallctl>\n          (<type>bool *</type>)\n          <literal>r-</literal>\n        </term>\n        <listitem><para>An array of <link\n        linkend=\"arenas.narenas\"><mallctl>arenas.narenas</mallctl></link>\n        booleans.  Each boolean indicates whether the corresponding arena is\n        initialized.</para></listitem>\n      </varlistentry>\n\n      <varlistentry id=\"arenas.lg_dirty_mult\">\n        <term>\n          <mallctl>arenas.lg_dirty_mult</mallctl>\n          (<type>ssize_t</type>)\n          <literal>rw</literal>\n        </term>\n        <listitem><para>Current default per-arena minimum ratio (log base 2) of\n        active to dirty pages, used to initialize <link\n        linkend=\"arena.i.lg_dirty_mult\"><mallctl>arena.&lt;i&gt;.lg_dirty_mult</mallctl></link>\n        during arena creation.  See <link\n        linkend=\"opt.lg_dirty_mult\"><mallctl>opt.lg_dirty_mult</mallctl></link>\n        for additional information.</para></listitem>\n      </varlistentry>\n\n      <varlistentry id=\"arenas.quantum\">\n        <term>\n          <mallctl>arenas.quantum</mallctl>\n          (<type>size_t</type>)\n          <literal>r-</literal>\n        </term>\n        <listitem><para>Quantum size.</para></listitem>\n      </varlistentry>\n\n      <varlistentry id=\"arenas.page\">\n        <term>\n          <mallctl>arenas.page</mallctl>\n          (<type>size_t</type>)\n          <literal>r-</literal>\n        </term>\n        <listitem><para>Page size.</para></listitem>\n      </varlistentry>\n\n      <varlistentry id=\"arenas.tcache_max\">\n        <term>\n          <mallctl>arenas.tcache_max</mallctl>\n          (<type>size_t</type>)\n          <literal>r-</literal>\n          [<option>--enable-tcache</option>]\n        </term>\n        <listitem><para>Maximum thread-cached size class.</para></listitem>\n      </varlistentry>\n\n      <varlistentry id=\"arenas.nbins\">\n        <term>\n          <mallctl>arenas.nbins</mallctl>\n          (<type>unsigned</type>)\n          <literal>r-</literal>\n        </term>\n        <listitem><para>Number of bin size classes.</para></listitem>\n      </varlistentry>\n\n      <varlistentry id=\"arenas.nhbins\">\n        <term>\n          <mallctl>arenas.nhbins</mallctl>\n          (<type>unsigned</type>)\n          <literal>r-</literal>\n          [<option>--enable-tcache</option>]\n        </term>\n        <listitem><para>Total number of thread cache bin size\n        classes.</para></listitem>\n      </varlistentry>\n\n      <varlistentry id=\"arenas.bin.i.size\">\n        <term>\n          <mallctl>arenas.bin.&lt;i&gt;.size</mallctl>\n          (<type>size_t</type>)\n          <literal>r-</literal>\n        </term>\n        <listitem><para>Maximum size supported by size class.</para></listitem>\n      </varlistentry>\n\n      <varlistentry id=\"arenas.bin.i.nregs\">\n        <term>\n          <mallctl>arenas.bin.&lt;i&gt;.nregs</mallctl>\n          (<type>uint32_t</type>)\n          <literal>r-</literal>\n        </term>\n        <listitem><para>Number of regions per page run.</para></listitem>\n      </varlistentry>\n\n      <varlistentry id=\"arenas.bin.i.run_size\">\n        <term>\n          <mallctl>arenas.bin.&lt;i&gt;.run_size</mallctl>\n          (<type>size_t</type>)\n          <literal>r-</literal>\n        </term>\n        <listitem><para>Number of bytes per page run.</para></listitem>\n      </varlistentry>\n\n      <varlistentry id=\"arenas.nlruns\">\n        <term>\n          <mallctl>arenas.nlruns</mallctl>\n          (<type>unsigned</type>)\n          <literal>r-</literal>\n        </term>\n        <listitem><para>Total number of large size classes.</para></listitem>\n      </varlistentry>\n\n      <varlistentry id=\"arenas.lrun.i.size\">\n        <term>\n          <mallctl>arenas.lrun.&lt;i&gt;.size</mallctl>\n          (<type>size_t</type>)\n          <literal>r-</literal>\n        </term>\n        <listitem><para>Maximum size supported by this large size\n        class.</para></listitem>\n      </varlistentry>\n\n      <varlistentry id=\"arenas.nhchunks\">\n        <term>\n          <mallctl>arenas.nhchunks</mallctl>\n          (<type>unsigned</type>)\n          <literal>r-</literal>\n        </term>\n        <listitem><para>Total number of huge size classes.</para></listitem>\n      </varlistentry>\n\n      <varlistentry id=\"arenas.hchunk.i.size\">\n        <term>\n          <mallctl>arenas.hchunk.&lt;i&gt;.size</mallctl>\n          (<type>size_t</type>)\n          <literal>r-</literal>\n        </term>\n        <listitem><para>Maximum size supported by this huge size\n        class.</para></listitem>\n      </varlistentry>\n\n      <varlistentry id=\"arenas.extend\">\n        <term>\n          <mallctl>arenas.extend</mallctl>\n          (<type>unsigned</type>)\n          <literal>r-</literal>\n        </term>\n        <listitem><para>Extend the array of arenas by appending a new arena,\n        and returning the new arena index.</para></listitem>\n      </varlistentry>\n\n      <varlistentry id=\"prof.thread_active_init\">\n        <term>\n          <mallctl>prof.thread_active_init</mallctl>\n          (<type>bool</type>)\n          <literal>rw</literal>\n          [<option>--enable-prof</option>]\n        </term>\n        <listitem><para>Control the initial setting for <link\n        linkend=\"thread.prof.active\"><mallctl>thread.prof.active</mallctl></link>\n        in newly created threads.  See the <link\n        linkend=\"opt.prof_thread_active_init\"><mallctl>opt.prof_thread_active_init</mallctl></link>\n        option for additional information.</para></listitem>\n      </varlistentry>\n\n      <varlistentry id=\"prof.active\">\n        <term>\n          <mallctl>prof.active</mallctl>\n          (<type>bool</type>)\n          <literal>rw</literal>\n          [<option>--enable-prof</option>]\n        </term>\n        <listitem><para>Control whether sampling is currently active.  See the\n        <link\n        linkend=\"opt.prof_active\"><mallctl>opt.prof_active</mallctl></link>\n        option for additional information, as well as the interrelated <link\n        linkend=\"thread.prof.active\"><mallctl>thread.prof.active</mallctl></link>\n        mallctl.</para></listitem>\n      </varlistentry>\n\n      <varlistentry id=\"prof.dump\">\n        <term>\n          <mallctl>prof.dump</mallctl>\n          (<type>const char *</type>)\n          <literal>-w</literal>\n          [<option>--enable-prof</option>]\n        </term>\n        <listitem><para>Dump a memory profile to the specified file, or if NULL\n        is specified, to a file according to the pattern\n        <filename>&lt;prefix&gt;.&lt;pid&gt;.&lt;seq&gt;.m&lt;mseq&gt;.heap</filename>,\n        where <literal>&lt;prefix&gt;</literal> is controlled by the\n        <link\n        linkend=\"opt.prof_prefix\"><mallctl>opt.prof_prefix</mallctl></link>\n        option.</para></listitem>\n      </varlistentry>\n\n      <varlistentry id=\"prof.gdump\">\n        <term>\n          <mallctl>prof.gdump</mallctl>\n          (<type>bool</type>)\n          <literal>rw</literal>\n          [<option>--enable-prof</option>]\n        </term>\n        <listitem><para>When enabled, trigger a memory profile dump every time\n        the total virtual memory exceeds the previous maximum.  Profiles are\n        dumped to files named according to the pattern\n        <filename>&lt;prefix&gt;.&lt;pid&gt;.&lt;seq&gt;.u&lt;useq&gt;.heap</filename>,\n        where <literal>&lt;prefix&gt;</literal> is controlled by the <link\n        linkend=\"opt.prof_prefix\"><mallctl>opt.prof_prefix</mallctl></link>\n        option.</para></listitem>\n      </varlistentry>\n\n      <varlistentry id=\"prof.reset\">\n        <term>\n          <mallctl>prof.reset</mallctl>\n          (<type>size_t</type>)\n          <literal>-w</literal>\n          [<option>--enable-prof</option>]\n        </term>\n        <listitem><para>Reset all memory profile statistics, and optionally\n        update the sample rate (see <link\n        linkend=\"opt.lg_prof_sample\"><mallctl>opt.lg_prof_sample</mallctl></link>\n        and <link\n        linkend=\"prof.lg_sample\"><mallctl>prof.lg_sample</mallctl></link>).\n        </para></listitem>\n      </varlistentry>\n\n      <varlistentry id=\"prof.lg_sample\">\n        <term>\n          <mallctl>prof.lg_sample</mallctl>\n          (<type>size_t</type>)\n          <literal>r-</literal>\n          [<option>--enable-prof</option>]\n        </term>\n        <listitem><para>Get the current sample rate (see <link\n        linkend=\"opt.lg_prof_sample\"><mallctl>opt.lg_prof_sample</mallctl></link>).\n        </para></listitem>\n      </varlistentry>\n\n      <varlistentry id=\"prof.interval\">\n        <term>\n          <mallctl>prof.interval</mallctl>\n          (<type>uint64_t</type>)\n          <literal>r-</literal>\n          [<option>--enable-prof</option>]\n        </term>\n        <listitem><para>Average number of bytes allocated between\n        inverval-based profile dumps.  See the\n        <link\n        linkend=\"opt.lg_prof_interval\"><mallctl>opt.lg_prof_interval</mallctl></link>\n        option for additional information.</para></listitem>\n      </varlistentry>\n\n      <varlistentry id=\"stats.cactive\">\n        <term>\n          <mallctl>stats.cactive</mallctl>\n          (<type>size_t *</type>)\n          <literal>r-</literal>\n          [<option>--enable-stats</option>]\n        </term>\n        <listitem><para>Pointer to a counter that contains an approximate count\n        of the current number of bytes in active pages.  The estimate may be\n        high, but never low, because each arena rounds up when computing its\n        contribution to the counter.  Note that the <link\n        linkend=\"epoch\"><mallctl>epoch</mallctl></link> mallctl has no bearing\n        on this counter.  Furthermore, counter consistency is maintained via\n        atomic operations, so it is necessary to use an atomic operation in\n        order to guarantee a consistent read when dereferencing the pointer.\n        </para></listitem>\n      </varlistentry>\n\n      <varlistentry id=\"stats.allocated\">\n        <term>\n          <mallctl>stats.allocated</mallctl>\n          (<type>size_t</type>)\n          <literal>r-</literal>\n          [<option>--enable-stats</option>]\n        </term>\n        <listitem><para>Total number of bytes allocated by the\n        application.</para></listitem>\n      </varlistentry>\n\n      <varlistentry id=\"stats.active\">\n        <term>\n          <mallctl>stats.active</mallctl>\n          (<type>size_t</type>)\n          <literal>r-</literal>\n          [<option>--enable-stats</option>]\n        </term>\n        <listitem><para>Total number of bytes in active pages allocated by the\n        application.  This is a multiple of the page size, and greater than or\n        equal to <link\n        linkend=\"stats.allocated\"><mallctl>stats.allocated</mallctl></link>.\n        This does not include <link linkend=\"stats.arenas.i.pdirty\">\n        <mallctl>stats.arenas.&lt;i&gt;.pdirty</mallctl></link>, nor pages\n        entirely devoted to allocator metadata.</para></listitem>\n      </varlistentry>\n\n      <varlistentry id=\"stats.metadata\">\n        <term>\n          <mallctl>stats.metadata</mallctl>\n          (<type>size_t</type>)\n          <literal>r-</literal>\n          [<option>--enable-stats</option>]\n        </term>\n        <listitem><para>Total number of bytes dedicated to metadata, which\n        comprise base allocations used for bootstrap-sensitive internal\n        allocator data structures, arena chunk headers (see <link\n        linkend=\"stats.arenas.i.metadata.mapped\"><mallctl>stats.arenas.&lt;i&gt;.metadata.mapped</mallctl></link>),\n        and internal allocations (see <link\n        linkend=\"stats.arenas.i.metadata.allocated\"><mallctl>stats.arenas.&lt;i&gt;.metadata.allocated</mallctl></link>).</para></listitem>\n      </varlistentry>\n\n      <varlistentry id=\"stats.resident\">\n        <term>\n          <mallctl>stats.resident</mallctl>\n          (<type>size_t</type>)\n          <literal>r-</literal>\n          [<option>--enable-stats</option>]\n        </term>\n        <listitem><para>Maximum number of bytes in physically resident data\n        pages mapped by the allocator, comprising all pages dedicated to\n        allocator metadata, pages backing active allocations, and unused dirty\n        pages.  This is a maximum rather than precise because pages may not\n        actually be physically resident if they correspond to demand-zeroed\n        virtual memory that has not yet been touched.  This is a multiple of the\n        page size, and is larger than <link\n        linkend=\"stats.active\"><mallctl>stats.active</mallctl></link>.</para></listitem>\n      </varlistentry>\n\n      <varlistentry id=\"stats.mapped\">\n        <term>\n          <mallctl>stats.mapped</mallctl>\n          (<type>size_t</type>)\n          <literal>r-</literal>\n          [<option>--enable-stats</option>]\n        </term>\n        <listitem><para>Total number of bytes in active chunks mapped by the\n        allocator.  This is a multiple of the chunk size, and is larger than\n        <link linkend=\"stats.active\"><mallctl>stats.active</mallctl></link>.\n        This does not include inactive chunks, even those that contain unused\n        dirty pages, which means that there is no strict ordering between this\n        and <link\n        linkend=\"stats.resident\"><mallctl>stats.resident</mallctl></link>.</para></listitem>\n      </varlistentry>\n\n      <varlistentry id=\"stats.arenas.i.dss\">\n        <term>\n          <mallctl>stats.arenas.&lt;i&gt;.dss</mallctl>\n          (<type>const char *</type>)\n          <literal>r-</literal>\n        </term>\n        <listitem><para>dss (<citerefentry><refentrytitle>sbrk</refentrytitle>\n        <manvolnum>2</manvolnum></citerefentry>) allocation precedence as\n        related to <citerefentry><refentrytitle>mmap</refentrytitle>\n        <manvolnum>2</manvolnum></citerefentry> allocation.  See <link\n        linkend=\"opt.dss\"><mallctl>opt.dss</mallctl></link> for details.\n        </para></listitem>\n      </varlistentry>\n\n      <varlistentry id=\"stats.arenas.i.lg_dirty_mult\">\n        <term>\n          <mallctl>stats.arenas.&lt;i&gt;.lg_dirty_mult</mallctl>\n          (<type>ssize_t</type>)\n          <literal>r-</literal>\n        </term>\n        <listitem><para>Minimum ratio (log base 2) of active to dirty pages.\n        See <link\n        linkend=\"opt.lg_dirty_mult\"><mallctl>opt.lg_dirty_mult</mallctl></link>\n        for details.</para></listitem>\n      </varlistentry>\n\n      <varlistentry id=\"stats.arenas.i.nthreads\">\n        <term>\n          <mallctl>stats.arenas.&lt;i&gt;.nthreads</mallctl>\n          (<type>unsigned</type>)\n          <literal>r-</literal>\n        </term>\n        <listitem><para>Number of threads currently assigned to\n        arena.</para></listitem>\n      </varlistentry>\n\n      <varlistentry id=\"stats.arenas.i.pactive\">\n        <term>\n          <mallctl>stats.arenas.&lt;i&gt;.pactive</mallctl>\n          (<type>size_t</type>)\n          <literal>r-</literal>\n        </term>\n        <listitem><para>Number of pages in active runs.</para></listitem>\n      </varlistentry>\n\n      <varlistentry id=\"stats.arenas.i.pdirty\">\n        <term>\n          <mallctl>stats.arenas.&lt;i&gt;.pdirty</mallctl>\n          (<type>size_t</type>)\n          <literal>r-</literal>\n        </term>\n        <listitem><para>Number of pages within unused runs that are potentially\n        dirty, and for which <function>madvise<parameter>...</parameter>\n        <parameter><constant>MADV_DONTNEED</constant></parameter></function> or\n        similar has not been called.</para></listitem>\n      </varlistentry>\n\n      <varlistentry id=\"stats.arenas.i.mapped\">\n        <term>\n          <mallctl>stats.arenas.&lt;i&gt;.mapped</mallctl>\n          (<type>size_t</type>)\n          <literal>r-</literal>\n          [<option>--enable-stats</option>]\n        </term>\n        <listitem><para>Number of mapped bytes.</para></listitem>\n      </varlistentry>\n\n      <varlistentry id=\"stats.arenas.i.metadata.mapped\">\n        <term>\n          <mallctl>stats.arenas.&lt;i&gt;.metadata.mapped</mallctl>\n          (<type>size_t</type>)\n          <literal>r-</literal>\n          [<option>--enable-stats</option>]\n        </term>\n        <listitem><para>Number of mapped bytes in arena chunk headers, which\n        track the states of the non-metadata pages.</para></listitem>\n      </varlistentry>\n\n      <varlistentry id=\"stats.arenas.i.metadata.allocated\">\n        <term>\n          <mallctl>stats.arenas.&lt;i&gt;.metadata.allocated</mallctl>\n          (<type>size_t</type>)\n          <literal>r-</literal>\n          [<option>--enable-stats</option>]\n        </term>\n        <listitem><para>Number of bytes dedicated to internal allocations.\n        Internal allocations differ from application-originated allocations in\n        that they are for internal use, and that they are omitted from heap\n        profiles.  This statistic is reported separately from <link\n        linkend=\"stats.metadata\"><mallctl>stats.metadata</mallctl></link> and\n        <link\n        linkend=\"stats.arenas.i.metadata.mapped\"><mallctl>stats.arenas.&lt;i&gt;.metadata.mapped</mallctl></link>\n        because it overlaps with e.g. the <link\n        linkend=\"stats.allocated\"><mallctl>stats.allocated</mallctl></link> and\n        <link linkend=\"stats.active\"><mallctl>stats.active</mallctl></link>\n        statistics, whereas the other metadata statistics do\n        not.</para></listitem>\n      </varlistentry>\n\n      <varlistentry id=\"stats.arenas.i.npurge\">\n        <term>\n          <mallctl>stats.arenas.&lt;i&gt;.npurge</mallctl>\n          (<type>uint64_t</type>)\n          <literal>r-</literal>\n          [<option>--enable-stats</option>]\n        </term>\n        <listitem><para>Number of dirty page purge sweeps performed.\n        </para></listitem>\n      </varlistentry>\n\n      <varlistentry id=\"stats.arenas.i.nmadvise\">\n        <term>\n          <mallctl>stats.arenas.&lt;i&gt;.nmadvise</mallctl>\n          (<type>uint64_t</type>)\n          <literal>r-</literal>\n          [<option>--enable-stats</option>]\n        </term>\n        <listitem><para>Number of <function>madvise<parameter>...</parameter>\n        <parameter><constant>MADV_DONTNEED</constant></parameter></function> or\n        similar calls made to purge dirty pages.</para></listitem>\n      </varlistentry>\n\n      <varlistentry id=\"stats.arenas.i.purged\">\n        <term>\n          <mallctl>stats.arenas.&lt;i&gt;.purged</mallctl>\n          (<type>uint64_t</type>)\n          <literal>r-</literal>\n          [<option>--enable-stats</option>]\n        </term>\n        <listitem><para>Number of pages purged.</para></listitem>\n      </varlistentry>\n\n      <varlistentry id=\"stats.arenas.i.small.allocated\">\n        <term>\n          <mallctl>stats.arenas.&lt;i&gt;.small.allocated</mallctl>\n          (<type>size_t</type>)\n          <literal>r-</literal>\n          [<option>--enable-stats</option>]\n        </term>\n        <listitem><para>Number of bytes currently allocated by small objects.\n        </para></listitem>\n      </varlistentry>\n\n      <varlistentry id=\"stats.arenas.i.small.nmalloc\">\n        <term>\n          <mallctl>stats.arenas.&lt;i&gt;.small.nmalloc</mallctl>\n          (<type>uint64_t</type>)\n          <literal>r-</literal>\n          [<option>--enable-stats</option>]\n        </term>\n        <listitem><para>Cumulative number of allocation requests served by\n        small bins.</para></listitem>\n      </varlistentry>\n\n      <varlistentry id=\"stats.arenas.i.small.ndalloc\">\n        <term>\n          <mallctl>stats.arenas.&lt;i&gt;.small.ndalloc</mallctl>\n          (<type>uint64_t</type>)\n          <literal>r-</literal>\n          [<option>--enable-stats</option>]\n        </term>\n        <listitem><para>Cumulative number of small objects returned to bins.\n        </para></listitem>\n      </varlistentry>\n\n      <varlistentry id=\"stats.arenas.i.small.nrequests\">\n        <term>\n          <mallctl>stats.arenas.&lt;i&gt;.small.nrequests</mallctl>\n          (<type>uint64_t</type>)\n          <literal>r-</literal>\n          [<option>--enable-stats</option>]\n        </term>\n        <listitem><para>Cumulative number of small allocation requests.\n        </para></listitem>\n      </varlistentry>\n\n      <varlistentry id=\"stats.arenas.i.large.allocated\">\n        <term>\n          <mallctl>stats.arenas.&lt;i&gt;.large.allocated</mallctl>\n          (<type>size_t</type>)\n          <literal>r-</literal>\n          [<option>--enable-stats</option>]\n        </term>\n        <listitem><para>Number of bytes currently allocated by large objects.\n        </para></listitem>\n      </varlistentry>\n\n      <varlistentry id=\"stats.arenas.i.large.nmalloc\">\n        <term>\n          <mallctl>stats.arenas.&lt;i&gt;.large.nmalloc</mallctl>\n          (<type>uint64_t</type>)\n          <literal>r-</literal>\n          [<option>--enable-stats</option>]\n        </term>\n        <listitem><para>Cumulative number of large allocation requests served\n        directly by the arena.</para></listitem>\n      </varlistentry>\n\n      <varlistentry id=\"stats.arenas.i.large.ndalloc\">\n        <term>\n          <mallctl>stats.arenas.&lt;i&gt;.large.ndalloc</mallctl>\n          (<type>uint64_t</type>)\n          <literal>r-</literal>\n          [<option>--enable-stats</option>]\n        </term>\n        <listitem><para>Cumulative number of large deallocation requests served\n        directly by the arena.</para></listitem>\n      </varlistentry>\n\n      <varlistentry id=\"stats.arenas.i.large.nrequests\">\n        <term>\n          <mallctl>stats.arenas.&lt;i&gt;.large.nrequests</mallctl>\n          (<type>uint64_t</type>)\n          <literal>r-</literal>\n          [<option>--enable-stats</option>]\n        </term>\n        <listitem><para>Cumulative number of large allocation requests.\n        </para></listitem>\n      </varlistentry>\n\n      <varlistentry id=\"stats.arenas.i.huge.allocated\">\n        <term>\n          <mallctl>stats.arenas.&lt;i&gt;.huge.allocated</mallctl>\n          (<type>size_t</type>)\n          <literal>r-</literal>\n          [<option>--enable-stats</option>]\n        </term>\n        <listitem><para>Number of bytes currently allocated by huge objects.\n        </para></listitem>\n      </varlistentry>\n\n      <varlistentry id=\"stats.arenas.i.huge.nmalloc\">\n        <term>\n          <mallctl>stats.arenas.&lt;i&gt;.huge.nmalloc</mallctl>\n          (<type>uint64_t</type>)\n          <literal>r-</literal>\n          [<option>--enable-stats</option>]\n        </term>\n        <listitem><para>Cumulative number of huge allocation requests served\n        directly by the arena.</para></listitem>\n      </varlistentry>\n\n      <varlistentry id=\"stats.arenas.i.huge.ndalloc\">\n        <term>\n          <mallctl>stats.arenas.&lt;i&gt;.huge.ndalloc</mallctl>\n          (<type>uint64_t</type>)\n          <literal>r-</literal>\n          [<option>--enable-stats</option>]\n        </term>\n        <listitem><para>Cumulative number of huge deallocation requests served\n        directly by the arena.</para></listitem>\n      </varlistentry>\n\n      <varlistentry id=\"stats.arenas.i.huge.nrequests\">\n        <term>\n          <mallctl>stats.arenas.&lt;i&gt;.huge.nrequests</mallctl>\n          (<type>uint64_t</type>)\n          <literal>r-</literal>\n          [<option>--enable-stats</option>]\n        </term>\n        <listitem><para>Cumulative number of huge allocation requests.\n        </para></listitem>\n      </varlistentry>\n\n      <varlistentry id=\"stats.arenas.i.bins.j.nmalloc\">\n        <term>\n          <mallctl>stats.arenas.&lt;i&gt;.bins.&lt;j&gt;.nmalloc</mallctl>\n          (<type>uint64_t</type>)\n          <literal>r-</literal>\n          [<option>--enable-stats</option>]\n        </term>\n        <listitem><para>Cumulative number of allocations served by bin.\n        </para></listitem>\n      </varlistentry>\n\n      <varlistentry id=\"stats.arenas.i.bins.j.ndalloc\">\n        <term>\n          <mallctl>stats.arenas.&lt;i&gt;.bins.&lt;j&gt;.ndalloc</mallctl>\n          (<type>uint64_t</type>)\n          <literal>r-</literal>\n          [<option>--enable-stats</option>]\n        </term>\n        <listitem><para>Cumulative number of allocations returned to bin.\n        </para></listitem>\n      </varlistentry>\n\n      <varlistentry id=\"stats.arenas.i.bins.j.nrequests\">\n        <term>\n          <mallctl>stats.arenas.&lt;i&gt;.bins.&lt;j&gt;.nrequests</mallctl>\n          (<type>uint64_t</type>)\n          <literal>r-</literal>\n          [<option>--enable-stats</option>]\n        </term>\n        <listitem><para>Cumulative number of allocation\n        requests.</para></listitem>\n      </varlistentry>\n\n      <varlistentry id=\"stats.arenas.i.bins.j.curregs\">\n        <term>\n          <mallctl>stats.arenas.&lt;i&gt;.bins.&lt;j&gt;.curregs</mallctl>\n          (<type>size_t</type>)\n          <literal>r-</literal>\n          [<option>--enable-stats</option>]\n        </term>\n        <listitem><para>Current number of regions for this size\n        class.</para></listitem>\n      </varlistentry>\n\n      <varlistentry id=\"stats.arenas.i.bins.j.nfills\">\n        <term>\n          <mallctl>stats.arenas.&lt;i&gt;.bins.&lt;j&gt;.nfills</mallctl>\n          (<type>uint64_t</type>)\n          <literal>r-</literal>\n          [<option>--enable-stats</option> <option>--enable-tcache</option>]\n        </term>\n        <listitem><para>Cumulative number of tcache fills.</para></listitem>\n      </varlistentry>\n\n      <varlistentry id=\"stats.arenas.i.bins.j.nflushes\">\n        <term>\n          <mallctl>stats.arenas.&lt;i&gt;.bins.&lt;j&gt;.nflushes</mallctl>\n          (<type>uint64_t</type>)\n          <literal>r-</literal>\n          [<option>--enable-stats</option> <option>--enable-tcache</option>]\n        </term>\n        <listitem><para>Cumulative number of tcache flushes.</para></listitem>\n      </varlistentry>\n\n      <varlistentry id=\"stats.arenas.i.bins.j.nruns\">\n        <term>\n          <mallctl>stats.arenas.&lt;i&gt;.bins.&lt;j&gt;.nruns</mallctl>\n          (<type>uint64_t</type>)\n          <literal>r-</literal>\n          [<option>--enable-stats</option>]\n        </term>\n        <listitem><para>Cumulative number of runs created.</para></listitem>\n      </varlistentry>\n\n      <varlistentry id=\"stats.arenas.i.bins.j.nreruns\">\n        <term>\n          <mallctl>stats.arenas.&lt;i&gt;.bins.&lt;j&gt;.nreruns</mallctl>\n          (<type>uint64_t</type>)\n          <literal>r-</literal>\n          [<option>--enable-stats</option>]\n        </term>\n        <listitem><para>Cumulative number of times the current run from which\n        to allocate changed.</para></listitem>\n      </varlistentry>\n\n      <varlistentry id=\"stats.arenas.i.bins.j.curruns\">\n        <term>\n          <mallctl>stats.arenas.&lt;i&gt;.bins.&lt;j&gt;.curruns</mallctl>\n          (<type>size_t</type>)\n          <literal>r-</literal>\n          [<option>--enable-stats</option>]\n        </term>\n        <listitem><para>Current number of runs.</para></listitem>\n      </varlistentry>\n\n      <varlistentry id=\"stats.arenas.i.lruns.j.nmalloc\">\n        <term>\n          <mallctl>stats.arenas.&lt;i&gt;.lruns.&lt;j&gt;.nmalloc</mallctl>\n          (<type>uint64_t</type>)\n          <literal>r-</literal>\n          [<option>--enable-stats</option>]\n        </term>\n        <listitem><para>Cumulative number of allocation requests for this size\n        class served directly by the arena.</para></listitem>\n      </varlistentry>\n\n      <varlistentry id=\"stats.arenas.i.lruns.j.ndalloc\">\n        <term>\n          <mallctl>stats.arenas.&lt;i&gt;.lruns.&lt;j&gt;.ndalloc</mallctl>\n          (<type>uint64_t</type>)\n          <literal>r-</literal>\n          [<option>--enable-stats</option>]\n        </term>\n        <listitem><para>Cumulative number of deallocation requests for this\n        size class served directly by the arena.</para></listitem>\n      </varlistentry>\n\n      <varlistentry id=\"stats.arenas.i.lruns.j.nrequests\">\n        <term>\n          <mallctl>stats.arenas.&lt;i&gt;.lruns.&lt;j&gt;.nrequests</mallctl>\n          (<type>uint64_t</type>)\n          <literal>r-</literal>\n          [<option>--enable-stats</option>]\n        </term>\n        <listitem><para>Cumulative number of allocation requests for this size\n        class.</para></listitem>\n      </varlistentry>\n\n      <varlistentry id=\"stats.arenas.i.lruns.j.curruns\">\n        <term>\n          <mallctl>stats.arenas.&lt;i&gt;.lruns.&lt;j&gt;.curruns</mallctl>\n          (<type>size_t</type>)\n          <literal>r-</literal>\n          [<option>--enable-stats</option>]\n        </term>\n        <listitem><para>Current number of runs for this size class.\n        </para></listitem>\n      </varlistentry>\n\n      <varlistentry id=\"stats.arenas.i.hchunks.j.nmalloc\">\n        <term>\n          <mallctl>stats.arenas.&lt;i&gt;.hchunks.&lt;j&gt;.nmalloc</mallctl>\n          (<type>uint64_t</type>)\n          <literal>r-</literal>\n          [<option>--enable-stats</option>]\n        </term>\n        <listitem><para>Cumulative number of allocation requests for this size\n        class served directly by the arena.</para></listitem>\n      </varlistentry>\n\n      <varlistentry id=\"stats.arenas.i.hchunks.j.ndalloc\">\n        <term>\n          <mallctl>stats.arenas.&lt;i&gt;.hchunks.&lt;j&gt;.ndalloc</mallctl>\n          (<type>uint64_t</type>)\n          <literal>r-</literal>\n          [<option>--enable-stats</option>]\n        </term>\n        <listitem><para>Cumulative number of deallocation requests for this\n        size class served directly by the arena.</para></listitem>\n      </varlistentry>\n\n      <varlistentry id=\"stats.arenas.i.hchunks.j.nrequests\">\n        <term>\n          <mallctl>stats.arenas.&lt;i&gt;.hchunks.&lt;j&gt;.nrequests</mallctl>\n          (<type>uint64_t</type>)\n          <literal>r-</literal>\n          [<option>--enable-stats</option>]\n        </term>\n        <listitem><para>Cumulative number of allocation requests for this size\n        class.</para></listitem>\n      </varlistentry>\n\n      <varlistentry id=\"stats.arenas.i.hchunks.j.curhchunks\">\n        <term>\n          <mallctl>stats.arenas.&lt;i&gt;.hchunks.&lt;j&gt;.curhchunks</mallctl>\n          (<type>size_t</type>)\n          <literal>r-</literal>\n          [<option>--enable-stats</option>]\n        </term>\n        <listitem><para>Current number of huge allocations for this size class.\n        </para></listitem>\n      </varlistentry>\n    </variablelist>\n  </refsect1>\n  <refsect1 id=\"debugging_malloc_problems\">\n    <title>DEBUGGING MALLOC PROBLEMS</title>\n    <para>When debugging, it is a good idea to configure/build jemalloc with\n    the <option>--enable-debug</option> and <option>--enable-fill</option>\n    options, and recompile the program with suitable options and symbols for\n    debugger support.  When so configured, jemalloc incorporates a wide variety\n    of run-time assertions that catch application errors such as double-free,\n    write-after-free, etc.</para>\n\n    <para>Programs often accidentally depend on &ldquo;uninitialized&rdquo;\n    memory actually being filled with zero bytes.  Junk filling\n    (see the <link linkend=\"opt.junk\"><mallctl>opt.junk</mallctl></link>\n    option) tends to expose such bugs in the form of obviously incorrect\n    results and/or coredumps.  Conversely, zero\n    filling (see the <link\n    linkend=\"opt.zero\"><mallctl>opt.zero</mallctl></link> option) eliminates\n    the symptoms of such bugs.  Between these two options, it is usually\n    possible to quickly detect, diagnose, and eliminate such bugs.</para>\n\n    <para>This implementation does not provide much detail about the problems\n    it detects, because the performance impact for storing such information\n    would be prohibitive.  However, jemalloc does integrate with the most\n    excellent <ulink url=\"http://valgrind.org/\">Valgrind</ulink> tool if the\n    <option>--enable-valgrind</option> configuration option is enabled.</para>\n  </refsect1>\n  <refsect1 id=\"diagnostic_messages\">\n    <title>DIAGNOSTIC MESSAGES</title>\n    <para>If any of the memory allocation/deallocation functions detect an\n    error or warning condition, a message will be printed to file descriptor\n    <constant>STDERR_FILENO</constant>.  Errors will result in the process\n    dumping core.  If the <link\n    linkend=\"opt.abort\"><mallctl>opt.abort</mallctl></link> option is set, most\n    warnings are treated as errors.</para>\n\n    <para>The <varname>malloc_message</varname> variable allows the programmer\n    to override the function which emits the text strings forming the errors\n    and warnings if for some reason the <constant>STDERR_FILENO</constant> file\n    descriptor is not suitable for this.\n    <function>malloc_message<parameter/></function> takes the\n    <parameter>cbopaque</parameter> pointer argument that is\n    <constant>NULL</constant> unless overridden by the arguments in a call to\n    <function>malloc_stats_print<parameter/></function>, followed by a string\n    pointer.  Please note that doing anything which tries to allocate memory in\n    this function is likely to result in a crash or deadlock.</para>\n\n    <para>All messages are prefixed by\n    &ldquo;<computeroutput>&lt;jemalloc&gt;: </computeroutput>&rdquo;.</para>\n  </refsect1>\n  <refsect1 id=\"return_values\">\n    <title>RETURN VALUES</title>\n    <refsect2>\n      <title>Standard API</title>\n      <para>The <function>malloc<parameter/></function> and\n      <function>calloc<parameter/></function> functions return a pointer to the\n      allocated memory if successful; otherwise a <constant>NULL</constant>\n      pointer is returned and <varname>errno</varname> is set to\n      <errorname>ENOMEM</errorname>.</para>\n\n      <para>The <function>posix_memalign<parameter/></function> function\n      returns the value 0 if successful; otherwise it returns an error value.\n      The <function>posix_memalign<parameter/></function> function will fail\n      if:\n        <variablelist>\n          <varlistentry>\n            <term><errorname>EINVAL</errorname></term>\n\n            <listitem><para>The <parameter>alignment</parameter> parameter is\n            not a power of 2 at least as large as\n            <code language=\"C\">sizeof(<type>void *</type>)</code>.\n            </para></listitem>\n          </varlistentry>\n          <varlistentry>\n            <term><errorname>ENOMEM</errorname></term>\n\n            <listitem><para>Memory allocation error.</para></listitem>\n          </varlistentry>\n        </variablelist>\n      </para>\n\n      <para>The <function>aligned_alloc<parameter/></function> function returns\n      a pointer to the allocated memory if successful; otherwise a\n      <constant>NULL</constant> pointer is returned and\n      <varname>errno</varname> is set.  The\n      <function>aligned_alloc<parameter/></function> function will fail if:\n        <variablelist>\n          <varlistentry>\n            <term><errorname>EINVAL</errorname></term>\n\n            <listitem><para>The <parameter>alignment</parameter> parameter is\n            not a power of 2.\n            </para></listitem>\n          </varlistentry>\n          <varlistentry>\n            <term><errorname>ENOMEM</errorname></term>\n\n            <listitem><para>Memory allocation error.</para></listitem>\n          </varlistentry>\n        </variablelist>\n      </para>\n\n      <para>The <function>realloc<parameter/></function> function returns a\n      pointer, possibly identical to <parameter>ptr</parameter>, to the\n      allocated memory if successful; otherwise a <constant>NULL</constant>\n      pointer is returned, and <varname>errno</varname> is set to\n      <errorname>ENOMEM</errorname> if the error was the result of an\n      allocation failure.  The <function>realloc<parameter/></function>\n      function always leaves the original buffer intact when an error occurs.\n      </para>\n\n      <para>The <function>free<parameter/></function> function returns no\n      value.</para>\n    </refsect2>\n    <refsect2>\n      <title>Non-standard API</title>\n      <para>The <function>mallocx<parameter/></function> and\n      <function>rallocx<parameter/></function> functions return a pointer to\n      the allocated memory if successful; otherwise a <constant>NULL</constant>\n      pointer is returned to indicate insufficient contiguous memory was\n      available to service the allocation request.  </para>\n\n      <para>The <function>xallocx<parameter/></function> function returns the\n      real size of the resulting resized allocation pointed to by\n      <parameter>ptr</parameter>, which is a value less than\n      <parameter>size</parameter> if the allocation could not be adequately\n      grown in place.  </para>\n\n      <para>The <function>sallocx<parameter/></function> function returns the\n      real size of the allocation pointed to by <parameter>ptr</parameter>.\n      </para>\n\n      <para>The <function>nallocx<parameter/></function> returns the real size\n      that would result from a successful equivalent\n      <function>mallocx<parameter/></function> function call, or zero if\n      insufficient memory is available to perform the size computation.  </para>\n\n      <para>The <function>mallctl<parameter/></function>,\n      <function>mallctlnametomib<parameter/></function>, and\n      <function>mallctlbymib<parameter/></function> functions return 0 on\n      success; otherwise they return an error value.  The functions will fail\n      if:\n        <variablelist>\n          <varlistentry>\n            <term><errorname>EINVAL</errorname></term>\n\n            <listitem><para><parameter>newp</parameter> is not\n            <constant>NULL</constant>, and <parameter>newlen</parameter> is too\n            large or too small.  Alternatively, <parameter>*oldlenp</parameter>\n            is too large or too small; in this case as much data as possible\n            are read despite the error.</para></listitem>\n          </varlistentry>\n          <varlistentry>\n            <term><errorname>ENOENT</errorname></term>\n\n            <listitem><para><parameter>name</parameter> or\n            <parameter>mib</parameter> specifies an unknown/invalid\n            value.</para></listitem>\n          </varlistentry>\n          <varlistentry>\n            <term><errorname>EPERM</errorname></term>\n\n            <listitem><para>Attempt to read or write void value, or attempt to\n            write read-only value.</para></listitem>\n          </varlistentry>\n          <varlistentry>\n            <term><errorname>EAGAIN</errorname></term>\n\n            <listitem><para>A memory allocation failure\n            occurred.</para></listitem>\n          </varlistentry>\n          <varlistentry>\n            <term><errorname>EFAULT</errorname></term>\n\n            <listitem><para>An interface with side effects failed in some way\n            not directly related to <function>mallctl*<parameter/></function>\n            read/write processing.</para></listitem>\n          </varlistentry>\n        </variablelist>\n      </para>\n\n      <para>The <function>malloc_usable_size<parameter/></function> function\n      returns the usable size of the allocation pointed to by\n      <parameter>ptr</parameter>.  </para>\n    </refsect2>\n  </refsect1>\n  <refsect1 id=\"environment\">\n    <title>ENVIRONMENT</title>\n    <para>The following environment variable affects the execution of the\n    allocation functions:\n      <variablelist>\n        <varlistentry>\n          <term><envar>MALLOC_CONF</envar></term>\n\n          <listitem><para>If the environment variable\n          <envar>MALLOC_CONF</envar> is set, the characters it contains\n          will be interpreted as options.</para></listitem>\n        </varlistentry>\n      </variablelist>\n    </para>\n  </refsect1>\n  <refsect1 id=\"examples\">\n    <title>EXAMPLES</title>\n    <para>To dump core whenever a problem occurs:\n      <screen>ln -s 'abort:true' /etc/malloc.conf</screen>\n    </para>\n    <para>To specify in the source a chunk size that is 16 MiB:\n      <programlisting language=\"C\"><![CDATA[\nmalloc_conf = \"lg_chunk:24\";]]></programlisting></para>\n  </refsect1>\n  <refsect1 id=\"see_also\">\n    <title>SEE ALSO</title>\n    <para><citerefentry><refentrytitle>madvise</refentrytitle>\n    <manvolnum>2</manvolnum></citerefentry>,\n    <citerefentry><refentrytitle>mmap</refentrytitle>\n    <manvolnum>2</manvolnum></citerefentry>,\n    <citerefentry><refentrytitle>sbrk</refentrytitle>\n    <manvolnum>2</manvolnum></citerefentry>,\n    <citerefentry><refentrytitle>utrace</refentrytitle>\n    <manvolnum>2</manvolnum></citerefentry>,\n    <citerefentry><refentrytitle>alloca</refentrytitle>\n    <manvolnum>3</manvolnum></citerefentry>,\n    <citerefentry><refentrytitle>atexit</refentrytitle>\n    <manvolnum>3</manvolnum></citerefentry>,\n    <citerefentry><refentrytitle>getpagesize</refentrytitle>\n    <manvolnum>3</manvolnum></citerefentry></para>\n  </refsect1>\n  <refsect1 id=\"standards\">\n    <title>STANDARDS</title>\n    <para>The <function>malloc<parameter/></function>,\n    <function>calloc<parameter/></function>,\n    <function>realloc<parameter/></function>, and\n    <function>free<parameter/></function> functions conform to ISO/IEC\n    9899:1990 (&ldquo;ISO C90&rdquo;).</para>\n\n    <para>The <function>posix_memalign<parameter/></function> function conforms\n    to IEEE Std 1003.1-2001 (&ldquo;POSIX.1&rdquo;).</para>\n  </refsect1>\n</refentry>\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.8/deps/jemalloc/doc/manpages.xsl.in",
    "content": "<xsl:stylesheet xmlns:xsl=\"http://www.w3.org/1999/XSL/Transform\" version=\"1.0\">\n  <xsl:import href=\"@XSLROOT@/manpages/docbook.xsl\"/>\n  <xsl:import href=\"@abs_srcroot@doc/stylesheet.xsl\"/>\n</xsl:stylesheet>\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.8/deps/jemalloc/doc/stylesheet.xsl",
    "content": "<xsl:stylesheet xmlns:xsl=\"http://www.w3.org/1999/XSL/Transform\" version=\"1.0\">\n  <xsl:param name=\"funcsynopsis.style\">ansi</xsl:param>\n  <xsl:param name=\"function.parens\" select=\"1\"/>\n  <xsl:template match=\"mallctl\">\n    \"<xsl:call-template name=\"inline.monoseq\"/>\"\n  </xsl:template>\n</xsl:stylesheet>\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.8/deps/jemalloc/include/jemalloc/internal/arena.h",
    "content": "/******************************************************************************/\n#ifdef JEMALLOC_H_TYPES\n\n#define\tLARGE_MINCLASS\t\t(ZU(1) << LG_LARGE_MINCLASS)\n\n/* Maximum number of regions in one run. */\n#define\tLG_RUN_MAXREGS\t\t(LG_PAGE - LG_TINY_MIN)\n#define\tRUN_MAXREGS\t\t(1U << LG_RUN_MAXREGS)\n\n/*\n * Minimum redzone size.  Redzones may be larger than this if necessary to\n * preserve region alignment.\n */\n#define\tREDZONE_MINSIZE\t\t16\n\n/*\n * The minimum ratio of active:dirty pages per arena is computed as:\n *\n *   (nactive >> lg_dirty_mult) >= ndirty\n *\n * So, supposing that lg_dirty_mult is 3, there can be no less than 8 times as\n * many active pages as dirty pages.\n */\n#define\tLG_DIRTY_MULT_DEFAULT\t3\n\ntypedef struct arena_runs_dirty_link_s arena_runs_dirty_link_t;\ntypedef struct arena_run_s arena_run_t;\ntypedef struct arena_chunk_map_bits_s arena_chunk_map_bits_t;\ntypedef struct arena_chunk_map_misc_s arena_chunk_map_misc_t;\ntypedef struct arena_chunk_s arena_chunk_t;\ntypedef struct arena_bin_info_s arena_bin_info_t;\ntypedef struct arena_bin_s arena_bin_t;\ntypedef struct arena_s arena_t;\n\n#endif /* JEMALLOC_H_TYPES */\n/******************************************************************************/\n#ifdef JEMALLOC_H_STRUCTS\n\n#ifdef JEMALLOC_ARENA_STRUCTS_A\nstruct arena_run_s {\n\t/* Index of bin this run is associated with. */\n\tszind_t\t\tbinind;\n\n\t/* Number of free regions in run. */\n\tunsigned\tnfree;\n\n\t/* Per region allocated/deallocated bitmap. */\n\tbitmap_t\tbitmap[BITMAP_GROUPS_MAX];\n};\n\n/* Each element of the chunk map corresponds to one page within the chunk. */\nstruct arena_chunk_map_bits_s {\n\t/*\n\t * Run address (or size) and various flags are stored together.  The bit\n\t * layout looks like (assuming 32-bit system):\n\t *\n\t *   ???????? ???????? ???nnnnn nnndumla\n\t *\n\t * ? : Unallocated: Run address for first/last pages, unset for internal\n\t *                  pages.\n\t *     Small: Run page offset.\n\t *     Large: Run page count for first page, unset for trailing pages.\n\t * n : binind for small size class, BININD_INVALID for large size class.\n\t * d : dirty?\n\t * u : unzeroed?\n\t * m : decommitted?\n\t * l : large?\n\t * a : allocated?\n\t *\n\t * Following are example bit patterns for the three types of runs.\n\t *\n\t * p : run page offset\n\t * s : run size\n\t * n : binind for size class; large objects set these to BININD_INVALID\n\t * x : don't care\n\t * - : 0\n\t * + : 1\n\t * [DUMLA] : bit set\n\t * [dumla] : bit unset\n\t *\n\t *   Unallocated (clean):\n\t *     ssssssss ssssssss sss+++++ +++dum-a\n\t *     xxxxxxxx xxxxxxxx xxxxxxxx xxx-Uxxx\n\t *     ssssssss ssssssss sss+++++ +++dUm-a\n\t *\n\t *   Unallocated (dirty):\n\t *     ssssssss ssssssss sss+++++ +++D-m-a\n\t *     xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx\n\t *     ssssssss ssssssss sss+++++ +++D-m-a\n\t *\n\t *   Small:\n\t *     pppppppp pppppppp pppnnnnn nnnd---A\n\t *     pppppppp pppppppp pppnnnnn nnn----A\n\t *     pppppppp pppppppp pppnnnnn nnnd---A\n\t *\n\t *   Large:\n\t *     ssssssss ssssssss sss+++++ +++D--LA\n\t *     xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx\n\t *     -------- -------- ---+++++ +++D--LA\n\t *\n\t *   Large (sampled, size <= LARGE_MINCLASS):\n\t *     ssssssss ssssssss sssnnnnn nnnD--LA\n\t *     xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx\n\t *     -------- -------- ---+++++ +++D--LA\n\t *\n\t *   Large (not sampled, size == LARGE_MINCLASS):\n\t *     ssssssss ssssssss sss+++++ +++D--LA\n\t *     xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx\n\t *     -------- -------- ---+++++ +++D--LA\n\t */\n\tsize_t\t\t\t\tbits;\n#define\tCHUNK_MAP_ALLOCATED\t((size_t)0x01U)\n#define\tCHUNK_MAP_LARGE\t\t((size_t)0x02U)\n#define\tCHUNK_MAP_STATE_MASK\t((size_t)0x3U)\n\n#define\tCHUNK_MAP_DECOMMITTED\t((size_t)0x04U)\n#define\tCHUNK_MAP_UNZEROED\t((size_t)0x08U)\n#define\tCHUNK_MAP_DIRTY\t\t((size_t)0x10U)\n#define\tCHUNK_MAP_FLAGS_MASK\t((size_t)0x1cU)\n\n#define\tCHUNK_MAP_BININD_SHIFT\t5\n#define\tBININD_INVALID\t\t((size_t)0xffU)\n#define\tCHUNK_MAP_BININD_MASK\t(BININD_INVALID << CHUNK_MAP_BININD_SHIFT)\n#define\tCHUNK_MAP_BININD_INVALID CHUNK_MAP_BININD_MASK\n\n#define\tCHUNK_MAP_RUNIND_SHIFT\t(CHUNK_MAP_BININD_SHIFT + 8)\n#define\tCHUNK_MAP_SIZE_SHIFT\t(CHUNK_MAP_RUNIND_SHIFT - LG_PAGE)\n#define\tCHUNK_MAP_SIZE_MASK\t\t\t\t\t\t\\\n    (~(CHUNK_MAP_BININD_MASK | CHUNK_MAP_FLAGS_MASK | CHUNK_MAP_STATE_MASK))\n};\n\nstruct arena_runs_dirty_link_s {\n\tqr(arena_runs_dirty_link_t)\trd_link;\n};\n\n/*\n * Each arena_chunk_map_misc_t corresponds to one page within the chunk, just\n * like arena_chunk_map_bits_t.  Two separate arrays are stored within each\n * chunk header in order to improve cache locality.\n */\nstruct arena_chunk_map_misc_s {\n\t/*\n\t * Linkage for run trees.  There are two disjoint uses:\n\t *\n\t * 1) arena_t's runs_avail tree.\n\t * 2) arena_run_t conceptually uses this linkage for in-use non-full\n\t *    runs, rather than directly embedding linkage.\n\t */\n\trb_node(arena_chunk_map_misc_t)\t\trb_link;\n\n\tunion {\n\t\t/* Linkage for list of dirty runs. */\n\t\tarena_runs_dirty_link_t\t\trd;\n\n\t\t/* Profile counters, used for large object runs. */\n\t\tunion {\n\t\t\tvoid\t\t\t\t*prof_tctx_pun;\n\t\t\tprof_tctx_t\t\t\t*prof_tctx;\n\t\t};\n\n\t\t/* Small region run metadata. */\n\t\tarena_run_t\t\t\trun;\n\t};\n};\ntypedef rb_tree(arena_chunk_map_misc_t) arena_avail_tree_t;\ntypedef rb_tree(arena_chunk_map_misc_t) arena_run_tree_t;\n#endif /* JEMALLOC_ARENA_STRUCTS_A */\n\n#ifdef JEMALLOC_ARENA_STRUCTS_B\n/* Arena chunk header. */\nstruct arena_chunk_s {\n\t/*\n\t * A pointer to the arena that owns the chunk is stored within the node.\n\t * This field as a whole is used by chunks_rtree to support both\n\t * ivsalloc() and core-based debugging.\n\t */\n\textent_node_t\t\tnode;\n\n\t/*\n\t * Map of pages within chunk that keeps track of free/large/small.  The\n\t * first map_bias entries are omitted, since the chunk header does not\n\t * need to be tracked in the map.  This omission saves a header page\n\t * for common chunk sizes (e.g. 4 MiB).\n\t */\n\tarena_chunk_map_bits_t\tmap_bits[1]; /* Dynamically sized. */\n};\n\n/*\n * Read-only information associated with each element of arena_t's bins array\n * is stored separately, partly to reduce memory usage (only one copy, rather\n * than one per arena), but mainly to avoid false cacheline sharing.\n *\n * Each run has the following layout:\n *\n *               /--------------------\\\n *               | pad?               |\n *               |--------------------|\n *               | redzone            |\n *   reg0_offset | region 0           |\n *               | redzone            |\n *               |--------------------| \\\n *               | redzone            | |\n *               | region 1           |  > reg_interval\n *               | redzone            | /\n *               |--------------------|\n *               | ...                |\n *               | ...                |\n *               | ...                |\n *               |--------------------|\n *               | redzone            |\n *               | region nregs-1     |\n *               | redzone            |\n *               |--------------------|\n *               | alignment pad?     |\n *               \\--------------------/\n *\n * reg_interval has at least the same minimum alignment as reg_size; this\n * preserves the alignment constraint that sa2u() depends on.  Alignment pad is\n * either 0 or redzone_size; it is present only if needed to align reg0_offset.\n */\nstruct arena_bin_info_s {\n\t/* Size of regions in a run for this bin's size class. */\n\tsize_t\t\treg_size;\n\n\t/* Redzone size. */\n\tsize_t\t\tredzone_size;\n\n\t/* Interval between regions (reg_size + (redzone_size << 1)). */\n\tsize_t\t\treg_interval;\n\n\t/* Total size of a run for this bin's size class. */\n\tsize_t\t\trun_size;\n\n\t/* Total number of regions in a run for this bin's size class. */\n\tuint32_t\tnregs;\n\n\t/*\n\t * Metadata used to manipulate bitmaps for runs associated with this\n\t * bin.\n\t */\n\tbitmap_info_t\tbitmap_info;\n\n\t/* Offset of first region in a run for this bin's size class. */\n\tuint32_t\treg0_offset;\n};\n\nstruct arena_bin_s {\n\t/*\n\t * All operations on runcur, runs, and stats require that lock be\n\t * locked.  Run allocation/deallocation are protected by the arena lock,\n\t * which may be acquired while holding one or more bin locks, but not\n\t * vise versa.\n\t */\n\tmalloc_mutex_t\tlock;\n\n\t/*\n\t * Current run being used to service allocations of this bin's size\n\t * class.\n\t */\n\tarena_run_t\t*runcur;\n\n\t/*\n\t * Tree of non-full runs.  This tree is used when looking for an\n\t * existing run when runcur is no longer usable.  We choose the\n\t * non-full run that is lowest in memory; this policy tends to keep\n\t * objects packed well, and it can also help reduce the number of\n\t * almost-empty chunks.\n\t */\n\tarena_run_tree_t runs;\n\n\t/* Bin statistics. */\n\tmalloc_bin_stats_t stats;\n};\n\nstruct arena_s {\n\t/* This arena's index within the arenas array. */\n\tunsigned\t\tind;\n\n\t/*\n\t * Number of threads currently assigned to this arena.  This field is\n\t * protected by arenas_lock.\n\t */\n\tunsigned\t\tnthreads;\n\n\t/*\n\t * There are three classes of arena operations from a locking\n\t * perspective:\n\t * 1) Thread assignment (modifies nthreads) is protected by arenas_lock.\n\t * 2) Bin-related operations are protected by bin locks.\n\t * 3) Chunk- and run-related operations are protected by this mutex.\n\t */\n\tmalloc_mutex_t\t\tlock;\n\n\tarena_stats_t\t\tstats;\n\t/*\n\t * List of tcaches for extant threads associated with this arena.\n\t * Stats from these are merged incrementally, and at exit if\n\t * opt_stats_print is enabled.\n\t */\n\tql_head(tcache_t)\ttcache_ql;\n\n\tuint64_t\t\tprof_accumbytes;\n\n\t/*\n\t * PRNG state for cache index randomization of large allocation base\n\t * pointers.\n\t */\n\tuint64_t\t\toffset_state;\n\n\tdss_prec_t\t\tdss_prec;\n\n\t/*\n\t * In order to avoid rapid chunk allocation/deallocation when an arena\n\t * oscillates right on the cusp of needing a new chunk, cache the most\n\t * recently freed chunk.  The spare is left in the arena's chunk trees\n\t * until it is deleted.\n\t *\n\t * There is one spare chunk per arena, rather than one spare total, in\n\t * order to avoid interactions between multiple threads that could make\n\t * a single spare inadequate.\n\t */\n\tarena_chunk_t\t\t*spare;\n\n\t/* Minimum ratio (log base 2) of nactive:ndirty. */\n\tssize_t\t\t\tlg_dirty_mult;\n\n\t/* True if a thread is currently executing arena_purge(). */\n\tbool\t\t\tpurging;\n\n\t/* Number of pages in active runs and huge regions. */\n\tsize_t\t\t\tnactive;\n\n\t/*\n\t * Current count of pages within unused runs that are potentially\n\t * dirty, and for which madvise(... MADV_DONTNEED) has not been called.\n\t * By tracking this, we can institute a limit on how much dirty unused\n\t * memory is mapped for each arena.\n\t */\n\tsize_t\t\t\tndirty;\n\n\t/*\n\t * Size/address-ordered tree of this arena's available runs.  The tree\n\t * is used for first-best-fit run allocation.\n\t */\n\tarena_avail_tree_t\truns_avail;\n\n\t/*\n\t * Unused dirty memory this arena manages.  Dirty memory is conceptually\n\t * tracked as an arbitrarily interleaved LRU of dirty runs and cached\n\t * chunks, but the list linkage is actually semi-duplicated in order to\n\t * avoid extra arena_chunk_map_misc_t space overhead.\n\t *\n\t *   LRU-----------------------------------------------------------MRU\n\t *\n\t *        /-- arena ---\\\n\t *        |            |\n\t *        |            |\n\t *        |------------|                             /- chunk -\\\n\t *   ...->|chunks_cache|<--------------------------->|  /----\\ |<--...\n\t *        |------------|                             |  |node| |\n\t *        |            |                             |  |    | |\n\t *        |            |    /- run -\\    /- run -\\   |  |    | |\n\t *        |            |    |       |    |       |   |  |    | |\n\t *        |            |    |       |    |       |   |  |    | |\n\t *        |------------|    |-------|    |-------|   |  |----| |\n\t *   ...->|runs_dirty  |<-->|rd     |<-->|rd     |<---->|rd  |<----...\n\t *        |------------|    |-------|    |-------|   |  |----| |\n\t *        |            |    |       |    |       |   |  |    | |\n\t *        |            |    |       |    |       |   |  \\----/ |\n\t *        |            |    \\-------/    \\-------/   |         |\n\t *        |            |                             |         |\n\t *        |            |                             |         |\n\t *        \\------------/                             \\---------/\n\t */\n\tarena_runs_dirty_link_t\truns_dirty;\n\textent_node_t\t\tchunks_cache;\n\n\t/* Extant huge allocations. */\n\tql_head(extent_node_t)\thuge;\n\t/* Synchronizes all huge allocation/update/deallocation. */\n\tmalloc_mutex_t\t\thuge_mtx;\n\n\t/*\n\t * Trees of chunks that were previously allocated (trees differ only in\n\t * node ordering).  These are used when allocating chunks, in an attempt\n\t * to re-use address space.  Depending on function, different tree\n\t * orderings are needed, which is why there are two trees with the same\n\t * contents.\n\t */\n\textent_tree_t\t\tchunks_szad_cached;\n\textent_tree_t\t\tchunks_ad_cached;\n\textent_tree_t\t\tchunks_szad_retained;\n\textent_tree_t\t\tchunks_ad_retained;\n\n\tmalloc_mutex_t\t\tchunks_mtx;\n\t/* Cache of nodes that were allocated via base_alloc(). */\n\tql_head(extent_node_t)\tnode_cache;\n\tmalloc_mutex_t\t\tnode_cache_mtx;\n\n\t/* User-configurable chunk hook functions. */\n\tchunk_hooks_t\t\tchunk_hooks;\n\n\t/* bins is used to store trees of free regions. */\n\tarena_bin_t\t\tbins[NBINS];\n};\n#endif /* JEMALLOC_ARENA_STRUCTS_B */\n\n#endif /* JEMALLOC_H_STRUCTS */\n/******************************************************************************/\n#ifdef JEMALLOC_H_EXTERNS\n\nstatic const size_t\tlarge_pad =\n#ifdef JEMALLOC_CACHE_OBLIVIOUS\n    PAGE\n#else\n    0\n#endif\n    ;\n\nextern ssize_t\t\topt_lg_dirty_mult;\n\nextern arena_bin_info_t\tarena_bin_info[NBINS];\n\nextern size_t\t\tmap_bias; /* Number of arena chunk header pages. */\nextern size_t\t\tmap_misc_offset;\nextern size_t\t\tarena_maxrun; /* Max run size for arenas. */\nextern size_t\t\tlarge_maxclass; /* Max large size class. */\nextern unsigned\t\tnlclasses; /* Number of large size classes. */\nextern unsigned\t\tnhclasses; /* Number of huge size classes. */\n\nvoid\tarena_chunk_cache_maybe_insert(arena_t *arena, extent_node_t *node,\n    bool cache);\nvoid\tarena_chunk_cache_maybe_remove(arena_t *arena, extent_node_t *node,\n    bool cache);\nextent_node_t\t*arena_node_alloc(arena_t *arena);\nvoid\tarena_node_dalloc(arena_t *arena, extent_node_t *node);\nvoid\t*arena_chunk_alloc_huge(arena_t *arena, size_t usize, size_t alignment,\n    bool *zero);\nvoid\tarena_chunk_dalloc_huge(arena_t *arena, void *chunk, size_t usize);\nvoid\tarena_chunk_ralloc_huge_similar(arena_t *arena, void *chunk,\n    size_t oldsize, size_t usize);\nvoid\tarena_chunk_ralloc_huge_shrink(arena_t *arena, void *chunk,\n    size_t oldsize, size_t usize);\nbool\tarena_chunk_ralloc_huge_expand(arena_t *arena, void *chunk,\n    size_t oldsize, size_t usize, bool *zero);\nssize_t\tarena_lg_dirty_mult_get(arena_t *arena);\nbool\tarena_lg_dirty_mult_set(arena_t *arena, ssize_t lg_dirty_mult);\nvoid\tarena_maybe_purge(arena_t *arena);\nvoid\tarena_purge_all(arena_t *arena);\nvoid\tarena_tcache_fill_small(arena_t *arena, tcache_bin_t *tbin,\n    szind_t binind, uint64_t prof_accumbytes);\nvoid\tarena_alloc_junk_small(void *ptr, arena_bin_info_t *bin_info,\n    bool zero);\n#ifdef JEMALLOC_JET\ntypedef void (arena_redzone_corruption_t)(void *, size_t, bool, size_t,\n    uint8_t);\nextern arena_redzone_corruption_t *arena_redzone_corruption;\ntypedef void (arena_dalloc_junk_small_t)(void *, arena_bin_info_t *);\nextern arena_dalloc_junk_small_t *arena_dalloc_junk_small;\n#else\nvoid\tarena_dalloc_junk_small(void *ptr, arena_bin_info_t *bin_info);\n#endif\nvoid\tarena_quarantine_junk_small(void *ptr, size_t usize);\nvoid\t*arena_malloc_small(arena_t *arena, size_t size, bool zero);\nvoid\t*arena_malloc_large(arena_t *arena, size_t size, bool zero);\nvoid\t*arena_palloc(tsd_t *tsd, arena_t *arena, size_t usize,\n    size_t alignment, bool zero, tcache_t *tcache);\nvoid\tarena_prof_promoted(const void *ptr, size_t size);\nvoid\tarena_dalloc_bin_junked_locked(arena_t *arena, arena_chunk_t *chunk,\n    void *ptr, arena_chunk_map_bits_t *bitselm);\nvoid\tarena_dalloc_bin(arena_t *arena, arena_chunk_t *chunk, void *ptr,\n    size_t pageind, arena_chunk_map_bits_t *bitselm);\nvoid\tarena_dalloc_small(arena_t *arena, arena_chunk_t *chunk, void *ptr,\n    size_t pageind);\n#ifdef JEMALLOC_JET\ntypedef void (arena_dalloc_junk_large_t)(void *, size_t);\nextern arena_dalloc_junk_large_t *arena_dalloc_junk_large;\n#else\nvoid\tarena_dalloc_junk_large(void *ptr, size_t usize);\n#endif\nvoid\tarena_dalloc_large_junked_locked(arena_t *arena, arena_chunk_t *chunk,\n    void *ptr);\nvoid\tarena_dalloc_large(arena_t *arena, arena_chunk_t *chunk, void *ptr);\n#ifdef JEMALLOC_JET\ntypedef void (arena_ralloc_junk_large_t)(void *, size_t, size_t);\nextern arena_ralloc_junk_large_t *arena_ralloc_junk_large;\n#endif\nbool\tarena_ralloc_no_move(void *ptr, size_t oldsize, size_t size,\n    size_t extra, bool zero);\nvoid\t*arena_ralloc(tsd_t *tsd, arena_t *arena, void *ptr, size_t oldsize,\n    size_t size, size_t alignment, bool zero, tcache_t *tcache);\ndss_prec_t\tarena_dss_prec_get(arena_t *arena);\nbool\tarena_dss_prec_set(arena_t *arena, dss_prec_t dss_prec);\nssize_t\tarena_lg_dirty_mult_default_get(void);\nbool\tarena_lg_dirty_mult_default_set(ssize_t lg_dirty_mult);\nvoid\tarena_stats_merge(arena_t *arena, const char **dss,\n    ssize_t *lg_dirty_mult, size_t *nactive, size_t *ndirty,\n    arena_stats_t *astats, malloc_bin_stats_t *bstats,\n    malloc_large_stats_t *lstats, malloc_huge_stats_t *hstats);\narena_t\t*arena_new(unsigned ind);\nbool\tarena_boot(void);\nvoid\tarena_prefork(arena_t *arena);\nvoid\tarena_postfork_parent(arena_t *arena);\nvoid\tarena_postfork_child(arena_t *arena);\n\n#endif /* JEMALLOC_H_EXTERNS */\n/******************************************************************************/\n#ifdef JEMALLOC_H_INLINES\n\n#ifndef JEMALLOC_ENABLE_INLINE\narena_chunk_map_bits_t\t*arena_bitselm_get(arena_chunk_t *chunk,\n    size_t pageind);\narena_chunk_map_misc_t\t*arena_miscelm_get(arena_chunk_t *chunk,\n    size_t pageind);\nsize_t\tarena_miscelm_to_pageind(arena_chunk_map_misc_t *miscelm);\nvoid\t*arena_miscelm_to_rpages(arena_chunk_map_misc_t *miscelm);\narena_chunk_map_misc_t\t*arena_rd_to_miscelm(arena_runs_dirty_link_t *rd);\narena_chunk_map_misc_t\t*arena_run_to_miscelm(arena_run_t *run);\nsize_t\t*arena_mapbitsp_get(arena_chunk_t *chunk, size_t pageind);\nsize_t\tarena_mapbitsp_read(size_t *mapbitsp);\nsize_t\tarena_mapbits_get(arena_chunk_t *chunk, size_t pageind);\nsize_t\tarena_mapbits_size_decode(size_t mapbits);\nsize_t\tarena_mapbits_unallocated_size_get(arena_chunk_t *chunk,\n    size_t pageind);\nsize_t\tarena_mapbits_large_size_get(arena_chunk_t *chunk, size_t pageind);\nsize_t\tarena_mapbits_small_runind_get(arena_chunk_t *chunk, size_t pageind);\nszind_t\tarena_mapbits_binind_get(arena_chunk_t *chunk, size_t pageind);\nsize_t\tarena_mapbits_dirty_get(arena_chunk_t *chunk, size_t pageind);\nsize_t\tarena_mapbits_unzeroed_get(arena_chunk_t *chunk, size_t pageind);\nsize_t\tarena_mapbits_decommitted_get(arena_chunk_t *chunk, size_t pageind);\nsize_t\tarena_mapbits_large_get(arena_chunk_t *chunk, size_t pageind);\nsize_t\tarena_mapbits_allocated_get(arena_chunk_t *chunk, size_t pageind);\nvoid\tarena_mapbitsp_write(size_t *mapbitsp, size_t mapbits);\nsize_t\tarena_mapbits_size_encode(size_t size);\nvoid\tarena_mapbits_unallocated_set(arena_chunk_t *chunk, size_t pageind,\n    size_t size, size_t flags);\nvoid\tarena_mapbits_unallocated_size_set(arena_chunk_t *chunk, size_t pageind,\n    size_t size);\nvoid\tarena_mapbits_internal_set(arena_chunk_t *chunk, size_t pageind,\n    size_t flags);\nvoid\tarena_mapbits_large_set(arena_chunk_t *chunk, size_t pageind,\n    size_t size, size_t flags);\nvoid\tarena_mapbits_large_binind_set(arena_chunk_t *chunk, size_t pageind,\n    szind_t binind);\nvoid\tarena_mapbits_small_set(arena_chunk_t *chunk, size_t pageind,\n    size_t runind, szind_t binind, size_t flags);\nvoid\tarena_metadata_allocated_add(arena_t *arena, size_t size);\nvoid\tarena_metadata_allocated_sub(arena_t *arena, size_t size);\nsize_t\tarena_metadata_allocated_get(arena_t *arena);\nbool\tarena_prof_accum_impl(arena_t *arena, uint64_t accumbytes);\nbool\tarena_prof_accum_locked(arena_t *arena, uint64_t accumbytes);\nbool\tarena_prof_accum(arena_t *arena, uint64_t accumbytes);\nszind_t\tarena_ptr_small_binind_get(const void *ptr, size_t mapbits);\nszind_t\tarena_bin_index(arena_t *arena, arena_bin_t *bin);\nunsigned\tarena_run_regind(arena_run_t *run, arena_bin_info_t *bin_info,\n    const void *ptr);\nprof_tctx_t\t*arena_prof_tctx_get(const void *ptr);\nvoid\tarena_prof_tctx_set(const void *ptr, size_t usize, prof_tctx_t *tctx);\nvoid\tarena_prof_tctx_reset(const void *ptr, size_t usize,\n    const void *old_ptr, prof_tctx_t *old_tctx);\nvoid\t*arena_malloc(tsd_t *tsd, arena_t *arena, size_t size, bool zero,\n    tcache_t *tcache);\narena_t\t*arena_aalloc(const void *ptr);\nsize_t\tarena_salloc(const void *ptr, bool demote);\nvoid\tarena_dalloc(tsd_t *tsd, void *ptr, tcache_t *tcache);\nvoid\tarena_sdalloc(tsd_t *tsd, void *ptr, size_t size, tcache_t *tcache);\n#endif\n\n#if (defined(JEMALLOC_ENABLE_INLINE) || defined(JEMALLOC_ARENA_C_))\n#  ifdef JEMALLOC_ARENA_INLINE_A\nJEMALLOC_ALWAYS_INLINE arena_chunk_map_bits_t *\narena_bitselm_get(arena_chunk_t *chunk, size_t pageind)\n{\n\n\tassert(pageind >= map_bias);\n\tassert(pageind < chunk_npages);\n\n\treturn (&chunk->map_bits[pageind-map_bias]);\n}\n\nJEMALLOC_ALWAYS_INLINE arena_chunk_map_misc_t *\narena_miscelm_get(arena_chunk_t *chunk, size_t pageind)\n{\n\n\tassert(pageind >= map_bias);\n\tassert(pageind < chunk_npages);\n\n\treturn ((arena_chunk_map_misc_t *)((uintptr_t)chunk +\n\t    (uintptr_t)map_misc_offset) + pageind-map_bias);\n}\n\nJEMALLOC_ALWAYS_INLINE size_t\narena_miscelm_to_pageind(arena_chunk_map_misc_t *miscelm)\n{\n\tarena_chunk_t *chunk = (arena_chunk_t *)CHUNK_ADDR2BASE(miscelm);\n\tsize_t pageind = ((uintptr_t)miscelm - ((uintptr_t)chunk +\n\t    map_misc_offset)) / sizeof(arena_chunk_map_misc_t) + map_bias;\n\n\tassert(pageind >= map_bias);\n\tassert(pageind < chunk_npages);\n\n\treturn (pageind);\n}\n\nJEMALLOC_ALWAYS_INLINE void *\narena_miscelm_to_rpages(arena_chunk_map_misc_t *miscelm)\n{\n\tarena_chunk_t *chunk = (arena_chunk_t *)CHUNK_ADDR2BASE(miscelm);\n\tsize_t pageind = arena_miscelm_to_pageind(miscelm);\n\n\treturn ((void *)((uintptr_t)chunk + (pageind << LG_PAGE)));\n}\n\nJEMALLOC_ALWAYS_INLINE arena_chunk_map_misc_t *\narena_rd_to_miscelm(arena_runs_dirty_link_t *rd)\n{\n\tarena_chunk_map_misc_t *miscelm = (arena_chunk_map_misc_t\n\t    *)((uintptr_t)rd - offsetof(arena_chunk_map_misc_t, rd));\n\n\tassert(arena_miscelm_to_pageind(miscelm) >= map_bias);\n\tassert(arena_miscelm_to_pageind(miscelm) < chunk_npages);\n\n\treturn (miscelm);\n}\n\nJEMALLOC_ALWAYS_INLINE arena_chunk_map_misc_t *\narena_run_to_miscelm(arena_run_t *run)\n{\n\tarena_chunk_map_misc_t *miscelm = (arena_chunk_map_misc_t\n\t    *)((uintptr_t)run - offsetof(arena_chunk_map_misc_t, run));\n\n\tassert(arena_miscelm_to_pageind(miscelm) >= map_bias);\n\tassert(arena_miscelm_to_pageind(miscelm) < chunk_npages);\n\n\treturn (miscelm);\n}\n\nJEMALLOC_ALWAYS_INLINE size_t *\narena_mapbitsp_get(arena_chunk_t *chunk, size_t pageind)\n{\n\n\treturn (&arena_bitselm_get(chunk, pageind)->bits);\n}\n\nJEMALLOC_ALWAYS_INLINE size_t\narena_mapbitsp_read(size_t *mapbitsp)\n{\n\n\treturn (*mapbitsp);\n}\n\nJEMALLOC_ALWAYS_INLINE size_t\narena_mapbits_get(arena_chunk_t *chunk, size_t pageind)\n{\n\n\treturn (arena_mapbitsp_read(arena_mapbitsp_get(chunk, pageind)));\n}\n\nJEMALLOC_ALWAYS_INLINE size_t\narena_mapbits_size_decode(size_t mapbits)\n{\n\tsize_t size;\n\n#if CHUNK_MAP_SIZE_SHIFT > 0\n\tsize = (mapbits & CHUNK_MAP_SIZE_MASK) >> CHUNK_MAP_SIZE_SHIFT;\n#elif CHUNK_MAP_SIZE_SHIFT == 0\n\tsize = mapbits & CHUNK_MAP_SIZE_MASK;\n#else\n\tsize = (mapbits & CHUNK_MAP_SIZE_MASK) << -CHUNK_MAP_SIZE_SHIFT;\n#endif\n\n\treturn (size);\n}\n\nJEMALLOC_ALWAYS_INLINE size_t\narena_mapbits_unallocated_size_get(arena_chunk_t *chunk, size_t pageind)\n{\n\tsize_t mapbits;\n\n\tmapbits = arena_mapbits_get(chunk, pageind);\n\tassert((mapbits & (CHUNK_MAP_LARGE|CHUNK_MAP_ALLOCATED)) == 0);\n\treturn (arena_mapbits_size_decode(mapbits));\n}\n\nJEMALLOC_ALWAYS_INLINE size_t\narena_mapbits_large_size_get(arena_chunk_t *chunk, size_t pageind)\n{\n\tsize_t mapbits;\n\n\tmapbits = arena_mapbits_get(chunk, pageind);\n\tassert((mapbits & (CHUNK_MAP_LARGE|CHUNK_MAP_ALLOCATED)) ==\n\t    (CHUNK_MAP_LARGE|CHUNK_MAP_ALLOCATED));\n\treturn (arena_mapbits_size_decode(mapbits));\n}\n\nJEMALLOC_ALWAYS_INLINE size_t\narena_mapbits_small_runind_get(arena_chunk_t *chunk, size_t pageind)\n{\n\tsize_t mapbits;\n\n\tmapbits = arena_mapbits_get(chunk, pageind);\n\tassert((mapbits & (CHUNK_MAP_LARGE|CHUNK_MAP_ALLOCATED)) ==\n\t    CHUNK_MAP_ALLOCATED);\n\treturn (mapbits >> CHUNK_MAP_RUNIND_SHIFT);\n}\n\nJEMALLOC_ALWAYS_INLINE szind_t\narena_mapbits_binind_get(arena_chunk_t *chunk, size_t pageind)\n{\n\tsize_t mapbits;\n\tszind_t binind;\n\n\tmapbits = arena_mapbits_get(chunk, pageind);\n\tbinind = (mapbits & CHUNK_MAP_BININD_MASK) >> CHUNK_MAP_BININD_SHIFT;\n\tassert(binind < NBINS || binind == BININD_INVALID);\n\treturn (binind);\n}\n\nJEMALLOC_ALWAYS_INLINE size_t\narena_mapbits_dirty_get(arena_chunk_t *chunk, size_t pageind)\n{\n\tsize_t mapbits;\n\n\tmapbits = arena_mapbits_get(chunk, pageind);\n\tassert((mapbits & CHUNK_MAP_DECOMMITTED) == 0 || (mapbits &\n\t    (CHUNK_MAP_DIRTY|CHUNK_MAP_UNZEROED)) == 0);\n\treturn (mapbits & CHUNK_MAP_DIRTY);\n}\n\nJEMALLOC_ALWAYS_INLINE size_t\narena_mapbits_unzeroed_get(arena_chunk_t *chunk, size_t pageind)\n{\n\tsize_t mapbits;\n\n\tmapbits = arena_mapbits_get(chunk, pageind);\n\tassert((mapbits & CHUNK_MAP_DECOMMITTED) == 0 || (mapbits &\n\t    (CHUNK_MAP_DIRTY|CHUNK_MAP_UNZEROED)) == 0);\n\treturn (mapbits & CHUNK_MAP_UNZEROED);\n}\n\nJEMALLOC_ALWAYS_INLINE size_t\narena_mapbits_decommitted_get(arena_chunk_t *chunk, size_t pageind)\n{\n\tsize_t mapbits;\n\n\tmapbits = arena_mapbits_get(chunk, pageind);\n\tassert((mapbits & CHUNK_MAP_DECOMMITTED) == 0 || (mapbits &\n\t    (CHUNK_MAP_DIRTY|CHUNK_MAP_UNZEROED)) == 0);\n\treturn (mapbits & CHUNK_MAP_DECOMMITTED);\n}\n\nJEMALLOC_ALWAYS_INLINE size_t\narena_mapbits_large_get(arena_chunk_t *chunk, size_t pageind)\n{\n\tsize_t mapbits;\n\n\tmapbits = arena_mapbits_get(chunk, pageind);\n\treturn (mapbits & CHUNK_MAP_LARGE);\n}\n\nJEMALLOC_ALWAYS_INLINE size_t\narena_mapbits_allocated_get(arena_chunk_t *chunk, size_t pageind)\n{\n\tsize_t mapbits;\n\n\tmapbits = arena_mapbits_get(chunk, pageind);\n\treturn (mapbits & CHUNK_MAP_ALLOCATED);\n}\n\nJEMALLOC_ALWAYS_INLINE void\narena_mapbitsp_write(size_t *mapbitsp, size_t mapbits)\n{\n\n\t*mapbitsp = mapbits;\n}\n\nJEMALLOC_ALWAYS_INLINE size_t\narena_mapbits_size_encode(size_t size)\n{\n\tsize_t mapbits;\n\n#if CHUNK_MAP_SIZE_SHIFT > 0\n\tmapbits = size << CHUNK_MAP_SIZE_SHIFT;\n#elif CHUNK_MAP_SIZE_SHIFT == 0\n\tmapbits = size;\n#else\n\tmapbits = size >> -CHUNK_MAP_SIZE_SHIFT;\n#endif\n\n\tassert((mapbits & ~CHUNK_MAP_SIZE_MASK) == 0);\n\treturn (mapbits);\n}\n\nJEMALLOC_ALWAYS_INLINE void\narena_mapbits_unallocated_set(arena_chunk_t *chunk, size_t pageind, size_t size,\n    size_t flags)\n{\n\tsize_t *mapbitsp = arena_mapbitsp_get(chunk, pageind);\n\n\tassert((size & PAGE_MASK) == 0);\n\tassert((flags & CHUNK_MAP_FLAGS_MASK) == flags);\n\tassert((flags & CHUNK_MAP_DECOMMITTED) == 0 || (flags &\n\t    (CHUNK_MAP_DIRTY|CHUNK_MAP_UNZEROED)) == 0);\n\tarena_mapbitsp_write(mapbitsp, arena_mapbits_size_encode(size) |\n\t    CHUNK_MAP_BININD_INVALID | flags);\n}\n\nJEMALLOC_ALWAYS_INLINE void\narena_mapbits_unallocated_size_set(arena_chunk_t *chunk, size_t pageind,\n    size_t size)\n{\n\tsize_t *mapbitsp = arena_mapbitsp_get(chunk, pageind);\n\tsize_t mapbits = arena_mapbitsp_read(mapbitsp);\n\n\tassert((size & PAGE_MASK) == 0);\n\tassert((mapbits & (CHUNK_MAP_LARGE|CHUNK_MAP_ALLOCATED)) == 0);\n\tarena_mapbitsp_write(mapbitsp, arena_mapbits_size_encode(size) |\n\t    (mapbits & ~CHUNK_MAP_SIZE_MASK));\n}\n\nJEMALLOC_ALWAYS_INLINE void\narena_mapbits_internal_set(arena_chunk_t *chunk, size_t pageind, size_t flags)\n{\n\tsize_t *mapbitsp = arena_mapbitsp_get(chunk, pageind);\n\n\tassert((flags & CHUNK_MAP_UNZEROED) == flags);\n\tarena_mapbitsp_write(mapbitsp, flags);\n}\n\nJEMALLOC_ALWAYS_INLINE void\narena_mapbits_large_set(arena_chunk_t *chunk, size_t pageind, size_t size,\n    size_t flags)\n{\n\tsize_t *mapbitsp = arena_mapbitsp_get(chunk, pageind);\n\n\tassert((size & PAGE_MASK) == 0);\n\tassert((flags & CHUNK_MAP_FLAGS_MASK) == flags);\n\tassert((flags & CHUNK_MAP_DECOMMITTED) == 0 || (flags &\n\t    (CHUNK_MAP_DIRTY|CHUNK_MAP_UNZEROED)) == 0);\n\tarena_mapbitsp_write(mapbitsp, arena_mapbits_size_encode(size) |\n\t    CHUNK_MAP_BININD_INVALID | flags | CHUNK_MAP_LARGE |\n\t    CHUNK_MAP_ALLOCATED);\n}\n\nJEMALLOC_ALWAYS_INLINE void\narena_mapbits_large_binind_set(arena_chunk_t *chunk, size_t pageind,\n    szind_t binind)\n{\n\tsize_t *mapbitsp = arena_mapbitsp_get(chunk, pageind);\n\tsize_t mapbits = arena_mapbitsp_read(mapbitsp);\n\n\tassert(binind <= BININD_INVALID);\n\tassert(arena_mapbits_large_size_get(chunk, pageind) == LARGE_MINCLASS +\n\t    large_pad);\n\tarena_mapbitsp_write(mapbitsp, (mapbits & ~CHUNK_MAP_BININD_MASK) |\n\t    (binind << CHUNK_MAP_BININD_SHIFT));\n}\n\nJEMALLOC_ALWAYS_INLINE void\narena_mapbits_small_set(arena_chunk_t *chunk, size_t pageind, size_t runind,\n    szind_t binind, size_t flags)\n{\n\tsize_t *mapbitsp = arena_mapbitsp_get(chunk, pageind);\n\n\tassert(binind < BININD_INVALID);\n\tassert(pageind - runind >= map_bias);\n\tassert((flags & CHUNK_MAP_UNZEROED) == flags);\n\tarena_mapbitsp_write(mapbitsp, (runind << CHUNK_MAP_RUNIND_SHIFT) |\n\t    (binind << CHUNK_MAP_BININD_SHIFT) | flags | CHUNK_MAP_ALLOCATED);\n}\n\nJEMALLOC_INLINE void\narena_metadata_allocated_add(arena_t *arena, size_t size)\n{\n\n\tatomic_add_z(&arena->stats.metadata_allocated, size);\n}\n\nJEMALLOC_INLINE void\narena_metadata_allocated_sub(arena_t *arena, size_t size)\n{\n\n\tatomic_sub_z(&arena->stats.metadata_allocated, size);\n}\n\nJEMALLOC_INLINE size_t\narena_metadata_allocated_get(arena_t *arena)\n{\n\n\treturn (atomic_read_z(&arena->stats.metadata_allocated));\n}\n\nJEMALLOC_INLINE bool\narena_prof_accum_impl(arena_t *arena, uint64_t accumbytes)\n{\n\n\tcassert(config_prof);\n\tassert(prof_interval != 0);\n\n\tarena->prof_accumbytes += accumbytes;\n\tif (arena->prof_accumbytes >= prof_interval) {\n\t\tarena->prof_accumbytes -= prof_interval;\n\t\treturn (true);\n\t}\n\treturn (false);\n}\n\nJEMALLOC_INLINE bool\narena_prof_accum_locked(arena_t *arena, uint64_t accumbytes)\n{\n\n\tcassert(config_prof);\n\n\tif (likely(prof_interval == 0))\n\t\treturn (false);\n\treturn (arena_prof_accum_impl(arena, accumbytes));\n}\n\nJEMALLOC_INLINE bool\narena_prof_accum(arena_t *arena, uint64_t accumbytes)\n{\n\n\tcassert(config_prof);\n\n\tif (likely(prof_interval == 0))\n\t\treturn (false);\n\n\t{\n\t\tbool ret;\n\n\t\tmalloc_mutex_lock(&arena->lock);\n\t\tret = arena_prof_accum_impl(arena, accumbytes);\n\t\tmalloc_mutex_unlock(&arena->lock);\n\t\treturn (ret);\n\t}\n}\n\nJEMALLOC_ALWAYS_INLINE szind_t\narena_ptr_small_binind_get(const void *ptr, size_t mapbits)\n{\n\tszind_t binind;\n\n\tbinind = (mapbits & CHUNK_MAP_BININD_MASK) >> CHUNK_MAP_BININD_SHIFT;\n\n\tif (config_debug) {\n\t\tarena_chunk_t *chunk;\n\t\tarena_t *arena;\n\t\tsize_t pageind;\n\t\tsize_t actual_mapbits;\n\t\tsize_t rpages_ind;\n\t\tarena_run_t *run;\n\t\tarena_bin_t *bin;\n\t\tszind_t run_binind, actual_binind;\n\t\tarena_bin_info_t *bin_info;\n\t\tarena_chunk_map_misc_t *miscelm;\n\t\tvoid *rpages;\n\n\t\tassert(binind != BININD_INVALID);\n\t\tassert(binind < NBINS);\n\t\tchunk = (arena_chunk_t *)CHUNK_ADDR2BASE(ptr);\n\t\tarena = extent_node_arena_get(&chunk->node);\n\t\tpageind = ((uintptr_t)ptr - (uintptr_t)chunk) >> LG_PAGE;\n\t\tactual_mapbits = arena_mapbits_get(chunk, pageind);\n\t\tassert(mapbits == actual_mapbits);\n\t\tassert(arena_mapbits_large_get(chunk, pageind) == 0);\n\t\tassert(arena_mapbits_allocated_get(chunk, pageind) != 0);\n\t\trpages_ind = pageind - arena_mapbits_small_runind_get(chunk,\n\t\t    pageind);\n\t\tmiscelm = arena_miscelm_get(chunk, rpages_ind);\n\t\trun = &miscelm->run;\n\t\trun_binind = run->binind;\n\t\tbin = &arena->bins[run_binind];\n\t\tactual_binind = bin - arena->bins;\n\t\tassert(run_binind == actual_binind);\n\t\tbin_info = &arena_bin_info[actual_binind];\n\t\trpages = arena_miscelm_to_rpages(miscelm);\n\t\tassert(((uintptr_t)ptr - ((uintptr_t)rpages +\n\t\t    (uintptr_t)bin_info->reg0_offset)) % bin_info->reg_interval\n\t\t    == 0);\n\t}\n\n\treturn (binind);\n}\n#  endif /* JEMALLOC_ARENA_INLINE_A */\n\n#  ifdef JEMALLOC_ARENA_INLINE_B\nJEMALLOC_INLINE szind_t\narena_bin_index(arena_t *arena, arena_bin_t *bin)\n{\n\tszind_t binind = bin - arena->bins;\n\tassert(binind < NBINS);\n\treturn (binind);\n}\n\nJEMALLOC_INLINE unsigned\narena_run_regind(arena_run_t *run, arena_bin_info_t *bin_info, const void *ptr)\n{\n\tunsigned shift, diff, regind;\n\tsize_t interval;\n\tarena_chunk_map_misc_t *miscelm = arena_run_to_miscelm(run);\n\tvoid *rpages = arena_miscelm_to_rpages(miscelm);\n\n\t/*\n\t * Freeing a pointer lower than region zero can cause assertion\n\t * failure.\n\t */\n\tassert((uintptr_t)ptr >= (uintptr_t)rpages +\n\t    (uintptr_t)bin_info->reg0_offset);\n\n\t/*\n\t * Avoid doing division with a variable divisor if possible.  Using\n\t * actual division here can reduce allocator throughput by over 20%!\n\t */\n\tdiff = (unsigned)((uintptr_t)ptr - (uintptr_t)rpages -\n\t    bin_info->reg0_offset);\n\n\t/* Rescale (factor powers of 2 out of the numerator and denominator). */\n\tinterval = bin_info->reg_interval;\n\tshift = jemalloc_ffs(interval) - 1;\n\tdiff >>= shift;\n\tinterval >>= shift;\n\n\tif (interval == 1) {\n\t\t/* The divisor was a power of 2. */\n\t\tregind = diff;\n\t} else {\n\t\t/*\n\t\t * To divide by a number D that is not a power of two we\n\t\t * multiply by (2^21 / D) and then right shift by 21 positions.\n\t\t *\n\t\t *   X / D\n\t\t *\n\t\t * becomes\n\t\t *\n\t\t *   (X * interval_invs[D - 3]) >> SIZE_INV_SHIFT\n\t\t *\n\t\t * We can omit the first three elements, because we never\n\t\t * divide by 0, and 1 and 2 are both powers of two, which are\n\t\t * handled above.\n\t\t */\n#define\tSIZE_INV_SHIFT\t((sizeof(unsigned) << 3) - LG_RUN_MAXREGS)\n#define\tSIZE_INV(s)\t(((1U << SIZE_INV_SHIFT) / (s)) + 1)\n\t\tstatic const unsigned interval_invs[] = {\n\t\t    SIZE_INV(3),\n\t\t    SIZE_INV(4), SIZE_INV(5), SIZE_INV(6), SIZE_INV(7),\n\t\t    SIZE_INV(8), SIZE_INV(9), SIZE_INV(10), SIZE_INV(11),\n\t\t    SIZE_INV(12), SIZE_INV(13), SIZE_INV(14), SIZE_INV(15),\n\t\t    SIZE_INV(16), SIZE_INV(17), SIZE_INV(18), SIZE_INV(19),\n\t\t    SIZE_INV(20), SIZE_INV(21), SIZE_INV(22), SIZE_INV(23),\n\t\t    SIZE_INV(24), SIZE_INV(25), SIZE_INV(26), SIZE_INV(27),\n\t\t    SIZE_INV(28), SIZE_INV(29), SIZE_INV(30), SIZE_INV(31)\n\t\t};\n\n\t\tif (likely(interval <= ((sizeof(interval_invs) /\n\t\t    sizeof(unsigned)) + 2))) {\n\t\t\tregind = (diff * interval_invs[interval - 3]) >>\n\t\t\t    SIZE_INV_SHIFT;\n\t\t} else\n\t\t\tregind = diff / interval;\n#undef SIZE_INV\n#undef SIZE_INV_SHIFT\n\t}\n\tassert(diff == regind * interval);\n\tassert(regind < bin_info->nregs);\n\n\treturn (regind);\n}\n\nJEMALLOC_INLINE prof_tctx_t *\narena_prof_tctx_get(const void *ptr)\n{\n\tprof_tctx_t *ret;\n\tarena_chunk_t *chunk;\n\n\tcassert(config_prof);\n\tassert(ptr != NULL);\n\n\tchunk = (arena_chunk_t *)CHUNK_ADDR2BASE(ptr);\n\tif (likely(chunk != ptr)) {\n\t\tsize_t pageind = ((uintptr_t)ptr - (uintptr_t)chunk) >> LG_PAGE;\n\t\tsize_t mapbits = arena_mapbits_get(chunk, pageind);\n\t\tassert((mapbits & CHUNK_MAP_ALLOCATED) != 0);\n\t\tif (likely((mapbits & CHUNK_MAP_LARGE) == 0))\n\t\t\tret = (prof_tctx_t *)(uintptr_t)1U;\n\t\telse {\n\t\t\tarena_chunk_map_misc_t *elm = arena_miscelm_get(chunk,\n\t\t\t    pageind);\n\t\t\tret = atomic_read_p(&elm->prof_tctx_pun);\n\t\t}\n\t} else\n\t\tret = huge_prof_tctx_get(ptr);\n\n\treturn (ret);\n}\n\nJEMALLOC_INLINE void\narena_prof_tctx_set(const void *ptr, size_t usize, prof_tctx_t *tctx)\n{\n\tarena_chunk_t *chunk;\n\n\tcassert(config_prof);\n\tassert(ptr != NULL);\n\n\tchunk = (arena_chunk_t *)CHUNK_ADDR2BASE(ptr);\n\tif (likely(chunk != ptr)) {\n\t\tsize_t pageind = ((uintptr_t)ptr - (uintptr_t)chunk) >> LG_PAGE;\n\n\t\tassert(arena_mapbits_allocated_get(chunk, pageind) != 0);\n\n\t\tif (unlikely(usize > SMALL_MAXCLASS || (uintptr_t)tctx >\n\t\t    (uintptr_t)1U)) {\n\t\t\tarena_chunk_map_misc_t *elm;\n\n\t\t\tassert(arena_mapbits_large_get(chunk, pageind) != 0);\n\n\t\t\telm = arena_miscelm_get(chunk, pageind);\n\t\t\tatomic_write_p(&elm->prof_tctx_pun, tctx);\n\t\t} else {\n\t\t\t/*\n\t\t\t * tctx must always be initialized for large runs.\n\t\t\t * Assert that the surrounding conditional logic is\n\t\t\t * equivalent to checking whether ptr refers to a large\n\t\t\t * run.\n\t\t\t */\n\t\t\tassert(arena_mapbits_large_get(chunk, pageind) == 0);\n\t\t}\n\t} else\n\t\thuge_prof_tctx_set(ptr, tctx);\n}\n\nJEMALLOC_INLINE void\narena_prof_tctx_reset(const void *ptr, size_t usize, const void *old_ptr,\n    prof_tctx_t *old_tctx)\n{\n\n\tcassert(config_prof);\n\tassert(ptr != NULL);\n\n\tif (unlikely(usize > SMALL_MAXCLASS || (ptr == old_ptr &&\n\t    (uintptr_t)old_tctx > (uintptr_t)1U))) {\n\t\tarena_chunk_t *chunk = (arena_chunk_t *)CHUNK_ADDR2BASE(ptr);\n\t\tif (likely(chunk != ptr)) {\n\t\t\tsize_t pageind;\n\t\t\tarena_chunk_map_misc_t *elm;\n\n\t\t\tpageind = ((uintptr_t)ptr - (uintptr_t)chunk) >>\n\t\t\t    LG_PAGE;\n\t\t\tassert(arena_mapbits_allocated_get(chunk, pageind) !=\n\t\t\t    0);\n\t\t\tassert(arena_mapbits_large_get(chunk, pageind) != 0);\n\n\t\t\telm = arena_miscelm_get(chunk, pageind);\n\t\t\tatomic_write_p(&elm->prof_tctx_pun,\n\t\t\t    (prof_tctx_t *)(uintptr_t)1U);\n\t\t} else\n\t\t\thuge_prof_tctx_reset(ptr);\n\t}\n}\n\nJEMALLOC_ALWAYS_INLINE void *\narena_malloc(tsd_t *tsd, arena_t *arena, size_t size, bool zero,\n    tcache_t *tcache)\n{\n\n\tassert(size != 0);\n\n\tarena = arena_choose(tsd, arena);\n\tif (unlikely(arena == NULL))\n\t\treturn (NULL);\n\n\tif (likely(size <= SMALL_MAXCLASS)) {\n\t\tif (likely(tcache != NULL)) {\n\t\t\treturn (tcache_alloc_small(tsd, arena, tcache, size,\n\t\t\t    zero));\n\t\t} else\n\t\t\treturn (arena_malloc_small(arena, size, zero));\n\t} else if (likely(size <= large_maxclass)) {\n\t\t/*\n\t\t * Initialize tcache after checking size in order to avoid\n\t\t * infinite recursion during tcache initialization.\n\t\t */\n\t\tif (likely(tcache != NULL) && size <= tcache_maxclass) {\n\t\t\treturn (tcache_alloc_large(tsd, arena, tcache, size,\n\t\t\t    zero));\n\t\t} else\n\t\t\treturn (arena_malloc_large(arena, size, zero));\n\t} else\n\t\treturn (huge_malloc(tsd, arena, size, zero, tcache));\n}\n\nJEMALLOC_ALWAYS_INLINE arena_t *\narena_aalloc(const void *ptr)\n{\n\tarena_chunk_t *chunk;\n\n\tchunk = (arena_chunk_t *)CHUNK_ADDR2BASE(ptr);\n\tif (likely(chunk != ptr))\n\t\treturn (extent_node_arena_get(&chunk->node));\n\telse\n\t\treturn (huge_aalloc(ptr));\n}\n\n/* Return the size of the allocation pointed to by ptr. */\nJEMALLOC_ALWAYS_INLINE size_t\narena_salloc(const void *ptr, bool demote)\n{\n\tsize_t ret;\n\tarena_chunk_t *chunk;\n\tsize_t pageind;\n\tszind_t binind;\n\n\tassert(ptr != NULL);\n\n\tchunk = (arena_chunk_t *)CHUNK_ADDR2BASE(ptr);\n\tif (likely(chunk != ptr)) {\n\t\tpageind = ((uintptr_t)ptr - (uintptr_t)chunk) >> LG_PAGE;\n\t\tassert(arena_mapbits_allocated_get(chunk, pageind) != 0);\n\t\tbinind = arena_mapbits_binind_get(chunk, pageind);\n\t\tif (unlikely(binind == BININD_INVALID || (config_prof && !demote\n\t\t    && arena_mapbits_large_get(chunk, pageind) != 0))) {\n\t\t\t/*\n\t\t\t * Large allocation.  In the common case (demote), and\n\t\t\t * as this is an inline function, most callers will only\n\t\t\t * end up looking at binind to determine that ptr is a\n\t\t\t * small allocation.\n\t\t\t */\n\t\t\tassert(config_cache_oblivious || ((uintptr_t)ptr &\n\t\t\t    PAGE_MASK) == 0);\n\t\t\tret = arena_mapbits_large_size_get(chunk, pageind) -\n\t\t\t    large_pad;\n\t\t\tassert(ret != 0);\n\t\t\tassert(pageind + ((ret+large_pad)>>LG_PAGE) <=\n\t\t\t    chunk_npages);\n\t\t\tassert(arena_mapbits_dirty_get(chunk, pageind) ==\n\t\t\t    arena_mapbits_dirty_get(chunk,\n\t\t\t    pageind+((ret+large_pad)>>LG_PAGE)-1));\n\t\t} else {\n\t\t\t/*\n\t\t\t * Small allocation (possibly promoted to a large\n\t\t\t * object).\n\t\t\t */\n\t\t\tassert(arena_mapbits_large_get(chunk, pageind) != 0 ||\n\t\t\t    arena_ptr_small_binind_get(ptr,\n\t\t\t    arena_mapbits_get(chunk, pageind)) == binind);\n\t\t\tret = index2size(binind);\n\t\t}\n\t} else\n\t\tret = huge_salloc(ptr);\n\n\treturn (ret);\n}\n\nJEMALLOC_ALWAYS_INLINE void\narena_dalloc(tsd_t *tsd, void *ptr, tcache_t *tcache)\n{\n\tarena_chunk_t *chunk;\n\tsize_t pageind, mapbits;\n\n\tassert(ptr != NULL);\n\n\tchunk = (arena_chunk_t *)CHUNK_ADDR2BASE(ptr);\n\tif (likely(chunk != ptr)) {\n\t\tpageind = ((uintptr_t)ptr - (uintptr_t)chunk) >> LG_PAGE;\n\t\tmapbits = arena_mapbits_get(chunk, pageind);\n\t\tassert(arena_mapbits_allocated_get(chunk, pageind) != 0);\n\t\tif (likely((mapbits & CHUNK_MAP_LARGE) == 0)) {\n\t\t\t/* Small allocation. */\n\t\t\tif (likely(tcache != NULL)) {\n\t\t\t\tszind_t binind = arena_ptr_small_binind_get(ptr,\n\t\t\t\t    mapbits);\n\t\t\t\ttcache_dalloc_small(tsd, tcache, ptr, binind);\n\t\t\t} else {\n\t\t\t\tarena_dalloc_small(extent_node_arena_get(\n\t\t\t\t    &chunk->node), chunk, ptr, pageind);\n\t\t\t}\n\t\t} else {\n\t\t\tsize_t size = arena_mapbits_large_size_get(chunk,\n\t\t\t    pageind);\n\n\t\t\tassert(config_cache_oblivious || ((uintptr_t)ptr &\n\t\t\t    PAGE_MASK) == 0);\n\n\t\t\tif (likely(tcache != NULL) && size - large_pad <=\n\t\t\t    tcache_maxclass) {\n\t\t\t\ttcache_dalloc_large(tsd, tcache, ptr, size -\n\t\t\t\t    large_pad);\n\t\t\t} else {\n\t\t\t\tarena_dalloc_large(extent_node_arena_get(\n\t\t\t\t    &chunk->node), chunk, ptr);\n\t\t\t}\n\t\t}\n\t} else\n\t\thuge_dalloc(tsd, ptr, tcache);\n}\n\nJEMALLOC_ALWAYS_INLINE void\narena_sdalloc(tsd_t *tsd, void *ptr, size_t size, tcache_t *tcache)\n{\n\tarena_chunk_t *chunk;\n\n\tchunk = (arena_chunk_t *)CHUNK_ADDR2BASE(ptr);\n\tif (likely(chunk != ptr)) {\n\t\tif (config_prof && opt_prof) {\n\t\t\tsize_t pageind = ((uintptr_t)ptr - (uintptr_t)chunk) >>\n\t\t\t    LG_PAGE;\n\t\t\tassert(arena_mapbits_allocated_get(chunk, pageind) != 0);\n\t\t\tif (arena_mapbits_large_get(chunk, pageind) != 0) {\n\t\t\t\t/*\n\t\t\t\t * Make sure to use promoted size, not request\n\t\t\t\t * size.\n\t\t\t\t */\n\t\t\t\tsize = arena_mapbits_large_size_get(chunk,\n\t\t\t\t    pageind) - large_pad;\n\t\t\t}\n\t\t}\n\t\tassert(s2u(size) == s2u(arena_salloc(ptr, false)));\n\n\t\tif (likely(size <= SMALL_MAXCLASS)) {\n\t\t\t/* Small allocation. */\n\t\t\tif (likely(tcache != NULL)) {\n\t\t\t\tszind_t binind = size2index(size);\n\t\t\t\ttcache_dalloc_small(tsd, tcache, ptr, binind);\n\t\t\t} else {\n\t\t\t\tsize_t pageind = ((uintptr_t)ptr -\n\t\t\t\t    (uintptr_t)chunk) >> LG_PAGE;\n\t\t\t\tarena_dalloc_small(extent_node_arena_get(\n\t\t\t\t    &chunk->node), chunk, ptr, pageind);\n\t\t\t}\n\t\t} else {\n\t\t\tassert(config_cache_oblivious || ((uintptr_t)ptr &\n\t\t\t    PAGE_MASK) == 0);\n\n\t\t\tif (likely(tcache != NULL) && size <= tcache_maxclass)\n\t\t\t\ttcache_dalloc_large(tsd, tcache, ptr, size);\n\t\t\telse {\n\t\t\t\tarena_dalloc_large(extent_node_arena_get(\n\t\t\t\t    &chunk->node), chunk, ptr);\n\t\t\t}\n\t\t}\n\t} else\n\t\thuge_dalloc(tsd, ptr, tcache);\n}\n#  endif /* JEMALLOC_ARENA_INLINE_B */\n#endif\n\n#endif /* JEMALLOC_H_INLINES */\n/******************************************************************************/\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.8/deps/jemalloc/include/jemalloc/internal/atomic.h",
    "content": "/******************************************************************************/\n#ifdef JEMALLOC_H_TYPES\n\n#endif /* JEMALLOC_H_TYPES */\n/******************************************************************************/\n#ifdef JEMALLOC_H_STRUCTS\n\n#endif /* JEMALLOC_H_STRUCTS */\n/******************************************************************************/\n#ifdef JEMALLOC_H_EXTERNS\n\n#define\tatomic_read_uint64(p)\tatomic_add_uint64(p, 0)\n#define\tatomic_read_uint32(p)\tatomic_add_uint32(p, 0)\n#define\tatomic_read_p(p)\tatomic_add_p(p, NULL)\n#define\tatomic_read_z(p)\tatomic_add_z(p, 0)\n#define\tatomic_read_u(p)\tatomic_add_u(p, 0)\n\n#endif /* JEMALLOC_H_EXTERNS */\n/******************************************************************************/\n#ifdef JEMALLOC_H_INLINES\n\n/*\n * All arithmetic functions return the arithmetic result of the atomic\n * operation.  Some atomic operation APIs return the value prior to mutation, in\n * which case the following functions must redundantly compute the result so\n * that it can be returned.  These functions are normally inlined, so the extra\n * operations can be optimized away if the return values aren't used by the\n * callers.\n *\n *   <t> atomic_read_<t>(<t> *p) { return (*p); }\n *   <t> atomic_add_<t>(<t> *p, <t> x) { return (*p + x); }\n *   <t> atomic_sub_<t>(<t> *p, <t> x) { return (*p - x); }\n *   bool atomic_cas_<t>(<t> *p, <t> c, <t> s)\n *   {\n *     if (*p != c)\n *       return (true);\n *     *p = s;\n *     return (false);\n *   }\n *   void atomic_write_<t>(<t> *p, <t> x) { *p = x; }\n */\n\n#ifndef JEMALLOC_ENABLE_INLINE\nuint64_t\tatomic_add_uint64(uint64_t *p, uint64_t x);\nuint64_t\tatomic_sub_uint64(uint64_t *p, uint64_t x);\nbool\tatomic_cas_uint64(uint64_t *p, uint64_t c, uint64_t s);\nvoid\tatomic_write_uint64(uint64_t *p, uint64_t x);\nuint32_t\tatomic_add_uint32(uint32_t *p, uint32_t x);\nuint32_t\tatomic_sub_uint32(uint32_t *p, uint32_t x);\nbool\tatomic_cas_uint32(uint32_t *p, uint32_t c, uint32_t s);\nvoid\tatomic_write_uint32(uint32_t *p, uint32_t x);\nvoid\t*atomic_add_p(void **p, void *x);\nvoid\t*atomic_sub_p(void **p, void *x);\nbool\tatomic_cas_p(void **p, void *c, void *s);\nvoid\tatomic_write_p(void **p, const void *x);\nsize_t\tatomic_add_z(size_t *p, size_t x);\nsize_t\tatomic_sub_z(size_t *p, size_t x);\nbool\tatomic_cas_z(size_t *p, size_t c, size_t s);\nvoid\tatomic_write_z(size_t *p, size_t x);\nunsigned\tatomic_add_u(unsigned *p, unsigned x);\nunsigned\tatomic_sub_u(unsigned *p, unsigned x);\nbool\tatomic_cas_u(unsigned *p, unsigned c, unsigned s);\nvoid\tatomic_write_u(unsigned *p, unsigned x);\n#endif\n\n#if (defined(JEMALLOC_ENABLE_INLINE) || defined(JEMALLOC_ATOMIC_C_))\n/******************************************************************************/\n/* 64-bit operations. */\n#if (LG_SIZEOF_PTR == 3 || LG_SIZEOF_INT == 3)\n#  if (defined(__amd64__) || defined(__x86_64__))\nJEMALLOC_INLINE uint64_t\natomic_add_uint64(uint64_t *p, uint64_t x)\n{\n\tuint64_t t = x;\n\n\tasm volatile (\n\t    \"lock; xaddq %0, %1;\"\n\t    : \"+r\" (t), \"=m\" (*p) /* Outputs. */\n\t    : \"m\" (*p) /* Inputs. */\n\t    );\n\n\treturn (t + x);\n}\n\nJEMALLOC_INLINE uint64_t\natomic_sub_uint64(uint64_t *p, uint64_t x)\n{\n\tuint64_t t;\n\n\tx = (uint64_t)(-(int64_t)x);\n\tt = x;\n\tasm volatile (\n\t    \"lock; xaddq %0, %1;\"\n\t    : \"+r\" (t), \"=m\" (*p) /* Outputs. */\n\t    : \"m\" (*p) /* Inputs. */\n\t    );\n\n\treturn (t + x);\n}\n\nJEMALLOC_INLINE bool\natomic_cas_uint64(uint64_t *p, uint64_t c, uint64_t s)\n{\n\tuint8_t success;\n\n\tasm volatile (\n\t    \"lock; cmpxchgq %4, %0;\"\n\t    \"sete %1;\"\n\t    : \"=m\" (*p), \"=a\" (success) /* Outputs. */\n\t    : \"m\" (*p), \"a\" (c), \"r\" (s) /* Inputs. */\n\t    : \"memory\" /* Clobbers. */\n\t    );\n\n\treturn (!(bool)success);\n}\n\nJEMALLOC_INLINE void\natomic_write_uint64(uint64_t *p, uint64_t x)\n{\n\n\tasm volatile (\n\t    \"xchgq %1, %0;\" /* Lock is implied by xchgq. */\n\t    : \"=m\" (*p), \"+r\" (x) /* Outputs. */\n\t    : \"m\" (*p) /* Inputs. */\n\t    : \"memory\" /* Clobbers. */\n\t    );\n}\n#  elif (defined(JEMALLOC_C11ATOMICS))\nJEMALLOC_INLINE uint64_t\natomic_add_uint64(uint64_t *p, uint64_t x)\n{\n\tvolatile atomic_uint_least64_t *a = (volatile atomic_uint_least64_t *)p;\n\treturn (atomic_fetch_add(a, x) + x);\n}\n\nJEMALLOC_INLINE uint64_t\natomic_sub_uint64(uint64_t *p, uint64_t x)\n{\n\tvolatile atomic_uint_least64_t *a = (volatile atomic_uint_least64_t *)p;\n\treturn (atomic_fetch_sub(a, x) - x);\n}\n\nJEMALLOC_INLINE bool\natomic_cas_uint64(uint64_t *p, uint64_t c, uint64_t s)\n{\n\tvolatile atomic_uint_least64_t *a = (volatile atomic_uint_least64_t *)p;\n\treturn (!atomic_compare_exchange_strong(a, &c, s));\n}\n\nJEMALLOC_INLINE void\natomic_write_uint64(uint64_t *p, uint64_t x)\n{\n\tvolatile atomic_uint_least64_t *a = (volatile atomic_uint_least64_t *)p;\n\tatomic_store(a, x);\n}\n#  elif (defined(JEMALLOC_ATOMIC9))\nJEMALLOC_INLINE uint64_t\natomic_add_uint64(uint64_t *p, uint64_t x)\n{\n\n\t/*\n\t * atomic_fetchadd_64() doesn't exist, but we only ever use this\n\t * function on LP64 systems, so atomic_fetchadd_long() will do.\n\t */\n\tassert(sizeof(uint64_t) == sizeof(unsigned long));\n\n\treturn (atomic_fetchadd_long(p, (unsigned long)x) + x);\n}\n\nJEMALLOC_INLINE uint64_t\natomic_sub_uint64(uint64_t *p, uint64_t x)\n{\n\n\tassert(sizeof(uint64_t) == sizeof(unsigned long));\n\n\treturn (atomic_fetchadd_long(p, (unsigned long)(-(long)x)) - x);\n}\n\nJEMALLOC_INLINE bool\natomic_cas_uint64(uint64_t *p, uint64_t c, uint64_t s)\n{\n\n\tassert(sizeof(uint64_t) == sizeof(unsigned long));\n\n\treturn (!atomic_cmpset_long(p, (unsigned long)c, (unsigned long)s));\n}\n\nJEMALLOC_INLINE void\natomic_write_uint64(uint64_t *p, uint64_t x)\n{\n\n\tassert(sizeof(uint64_t) == sizeof(unsigned long));\n\n\tatomic_store_rel_long(p, x);\n}\n#  elif (defined(JEMALLOC_OSATOMIC))\nJEMALLOC_INLINE uint64_t\natomic_add_uint64(uint64_t *p, uint64_t x)\n{\n\n\treturn (OSAtomicAdd64((int64_t)x, (int64_t *)p));\n}\n\nJEMALLOC_INLINE uint64_t\natomic_sub_uint64(uint64_t *p, uint64_t x)\n{\n\n\treturn (OSAtomicAdd64(-((int64_t)x), (int64_t *)p));\n}\n\nJEMALLOC_INLINE bool\natomic_cas_uint64(uint64_t *p, uint64_t c, uint64_t s)\n{\n\n\treturn (!OSAtomicCompareAndSwap64(c, s, (int64_t *)p));\n}\n\nJEMALLOC_INLINE void\natomic_write_uint64(uint64_t *p, uint64_t x)\n{\n\tuint64_t o;\n\n\t/*The documented OSAtomic*() API does not expose an atomic exchange. */\n\tdo {\n\t\to = atomic_read_uint64(p);\n\t} while (atomic_cas_uint64(p, o, x));\n}\n#  elif (defined(_MSC_VER))\nJEMALLOC_INLINE uint64_t\natomic_add_uint64(uint64_t *p, uint64_t x)\n{\n\n\treturn (InterlockedExchangeAdd64(p, x) + x);\n}\n\nJEMALLOC_INLINE uint64_t\natomic_sub_uint64(uint64_t *p, uint64_t x)\n{\n\n\treturn (InterlockedExchangeAdd64(p, -((int64_t)x)) - x);\n}\n\nJEMALLOC_INLINE bool\natomic_cas_uint64(uint64_t *p, uint64_t c, uint64_t s)\n{\n\tuint64_t o;\n\n\to = InterlockedCompareExchange64(p, s, c);\n\treturn (o != c);\n}\n\nJEMALLOC_INLINE void\natomic_write_uint64(uint64_t *p, uint64_t x)\n{\n\n\tInterlockedExchange64(p, x);\n}\n#  elif (defined(__GCC_HAVE_SYNC_COMPARE_AND_SWAP_8) || \\\n    defined(JE_FORCE_SYNC_COMPARE_AND_SWAP_8))\nJEMALLOC_INLINE uint64_t\natomic_add_uint64(uint64_t *p, uint64_t x)\n{\n\n\treturn (__sync_add_and_fetch(p, x));\n}\n\nJEMALLOC_INLINE uint64_t\natomic_sub_uint64(uint64_t *p, uint64_t x)\n{\n\n\treturn (__sync_sub_and_fetch(p, x));\n}\n\nJEMALLOC_INLINE bool\natomic_cas_uint64(uint64_t *p, uint64_t c, uint64_t s)\n{\n\n\treturn (!__sync_bool_compare_and_swap(p, c, s));\n}\n\nJEMALLOC_INLINE void\natomic_write_uint64(uint64_t *p, uint64_t x)\n{\n\n\t__sync_lock_test_and_set(p, x);\n}\n#  else\n#    error \"Missing implementation for 64-bit atomic operations\"\n#  endif\n#endif\n\n/******************************************************************************/\n/* 32-bit operations. */\n#if (defined(__i386__) || defined(__amd64__) || defined(__x86_64__))\nJEMALLOC_INLINE uint32_t\natomic_add_uint32(uint32_t *p, uint32_t x)\n{\n\tuint32_t t = x;\n\n\tasm volatile (\n\t    \"lock; xaddl %0, %1;\"\n\t    : \"+r\" (t), \"=m\" (*p) /* Outputs. */\n\t    : \"m\" (*p) /* Inputs. */\n\t    );\n\n\treturn (t + x);\n}\n\nJEMALLOC_INLINE uint32_t\natomic_sub_uint32(uint32_t *p, uint32_t x)\n{\n\tuint32_t t;\n\n\tx = (uint32_t)(-(int32_t)x);\n\tt = x;\n\tasm volatile (\n\t    \"lock; xaddl %0, %1;\"\n\t    : \"+r\" (t), \"=m\" (*p) /* Outputs. */\n\t    : \"m\" (*p) /* Inputs. */\n\t    );\n\n\treturn (t + x);\n}\n\nJEMALLOC_INLINE bool\natomic_cas_uint32(uint32_t *p, uint32_t c, uint32_t s)\n{\n\tuint8_t success;\n\n\tasm volatile (\n\t    \"lock; cmpxchgl %4, %0;\"\n\t    \"sete %1;\"\n\t    : \"=m\" (*p), \"=a\" (success) /* Outputs. */\n\t    : \"m\" (*p), \"a\" (c), \"r\" (s) /* Inputs. */\n\t    : \"memory\"\n\t    );\n\n\treturn (!(bool)success);\n}\n\nJEMALLOC_INLINE void\natomic_write_uint32(uint32_t *p, uint32_t x)\n{\n\n\tasm volatile (\n\t    \"xchgl %1, %0;\" /* Lock is implied by xchgl. */\n\t    : \"=m\" (*p), \"+r\" (x) /* Outputs. */\n\t    : \"m\" (*p) /* Inputs. */\n\t    : \"memory\" /* Clobbers. */\n\t    );\n}\n#  elif (defined(JEMALLOC_C11ATOMICS))\nJEMALLOC_INLINE uint32_t\natomic_add_uint32(uint32_t *p, uint32_t x)\n{\n\tvolatile atomic_uint_least32_t *a = (volatile atomic_uint_least32_t *)p;\n\treturn (atomic_fetch_add(a, x) + x);\n}\n\nJEMALLOC_INLINE uint32_t\natomic_sub_uint32(uint32_t *p, uint32_t x)\n{\n\tvolatile atomic_uint_least32_t *a = (volatile atomic_uint_least32_t *)p;\n\treturn (atomic_fetch_sub(a, x) - x);\n}\n\nJEMALLOC_INLINE bool\natomic_cas_uint32(uint32_t *p, uint32_t c, uint32_t s)\n{\n\tvolatile atomic_uint_least32_t *a = (volatile atomic_uint_least32_t *)p;\n\treturn (!atomic_compare_exchange_strong(a, &c, s));\n}\n\nJEMALLOC_INLINE void\natomic_write_uint32(uint32_t *p, uint32_t x)\n{\n\tvolatile atomic_uint_least32_t *a = (volatile atomic_uint_least32_t *)p;\n\tatomic_store(a, x);\n}\n#elif (defined(JEMALLOC_ATOMIC9))\nJEMALLOC_INLINE uint32_t\natomic_add_uint32(uint32_t *p, uint32_t x)\n{\n\n\treturn (atomic_fetchadd_32(p, x) + x);\n}\n\nJEMALLOC_INLINE uint32_t\natomic_sub_uint32(uint32_t *p, uint32_t x)\n{\n\n\treturn (atomic_fetchadd_32(p, (uint32_t)(-(int32_t)x)) - x);\n}\n\nJEMALLOC_INLINE bool\natomic_cas_uint32(uint32_t *p, uint32_t c, uint32_t s)\n{\n\n\treturn (!atomic_cmpset_32(p, c, s));\n}\n\nJEMALLOC_INLINE void\natomic_write_uint32(uint32_t *p, uint32_t x)\n{\n\n\tatomic_store_rel_32(p, x);\n}\n#elif (defined(JEMALLOC_OSATOMIC))\nJEMALLOC_INLINE uint32_t\natomic_add_uint32(uint32_t *p, uint32_t x)\n{\n\n\treturn (OSAtomicAdd32((int32_t)x, (int32_t *)p));\n}\n\nJEMALLOC_INLINE uint32_t\natomic_sub_uint32(uint32_t *p, uint32_t x)\n{\n\n\treturn (OSAtomicAdd32(-((int32_t)x), (int32_t *)p));\n}\n\nJEMALLOC_INLINE bool\natomic_cas_uint32(uint32_t *p, uint32_t c, uint32_t s)\n{\n\n\treturn (!OSAtomicCompareAndSwap32(c, s, (int32_t *)p));\n}\n\nJEMALLOC_INLINE void\natomic_write_uint32(uint32_t *p, uint32_t x)\n{\n\tuint32_t o;\n\n\t/*The documented OSAtomic*() API does not expose an atomic exchange. */\n\tdo {\n\t\to = atomic_read_uint32(p);\n\t} while (atomic_cas_uint32(p, o, x));\n}\n#elif (defined(_MSC_VER))\nJEMALLOC_INLINE uint32_t\natomic_add_uint32(uint32_t *p, uint32_t x)\n{\n\n\treturn (InterlockedExchangeAdd(p, x) + x);\n}\n\nJEMALLOC_INLINE uint32_t\natomic_sub_uint32(uint32_t *p, uint32_t x)\n{\n\n\treturn (InterlockedExchangeAdd(p, -((int32_t)x)) - x);\n}\n\nJEMALLOC_INLINE bool\natomic_cas_uint32(uint32_t *p, uint32_t c, uint32_t s)\n{\n\tuint32_t o;\n\n\to = InterlockedCompareExchange(p, s, c);\n\treturn (o != c);\n}\n\nJEMALLOC_INLINE void\natomic_write_uint32(uint32_t *p, uint32_t x)\n{\n\n\tInterlockedExchange(p, x);\n}\n#elif (defined(__GCC_HAVE_SYNC_COMPARE_AND_SWAP_4) || \\\n defined(JE_FORCE_SYNC_COMPARE_AND_SWAP_4))\nJEMALLOC_INLINE uint32_t\natomic_add_uint32(uint32_t *p, uint32_t x)\n{\n\n\treturn (__sync_add_and_fetch(p, x));\n}\n\nJEMALLOC_INLINE uint32_t\natomic_sub_uint32(uint32_t *p, uint32_t x)\n{\n\n\treturn (__sync_sub_and_fetch(p, x));\n}\n\nJEMALLOC_INLINE bool\natomic_cas_uint32(uint32_t *p, uint32_t c, uint32_t s)\n{\n\n\treturn (!__sync_bool_compare_and_swap(p, c, s));\n}\n\nJEMALLOC_INLINE void\natomic_write_uint32(uint32_t *p, uint32_t x)\n{\n\n\t__sync_lock_test_and_set(p, x);\n}\n#else\n#  error \"Missing implementation for 32-bit atomic operations\"\n#endif\n\n/******************************************************************************/\n/* Pointer operations. */\nJEMALLOC_INLINE void *\natomic_add_p(void **p, void *x)\n{\n\n#if (LG_SIZEOF_PTR == 3)\n\treturn ((void *)atomic_add_uint64((uint64_t *)p, (uint64_t)x));\n#elif (LG_SIZEOF_PTR == 2)\n\treturn ((void *)atomic_add_uint32((uint32_t *)p, (uint32_t)x));\n#endif\n}\n\nJEMALLOC_INLINE void *\natomic_sub_p(void **p, void *x)\n{\n\n#if (LG_SIZEOF_PTR == 3)\n\treturn ((void *)atomic_add_uint64((uint64_t *)p,\n\t    (uint64_t)-((int64_t)x)));\n#elif (LG_SIZEOF_PTR == 2)\n\treturn ((void *)atomic_add_uint32((uint32_t *)p,\n\t    (uint32_t)-((int32_t)x)));\n#endif\n}\n\nJEMALLOC_INLINE bool\natomic_cas_p(void **p, void *c, void *s)\n{\n\n#if (LG_SIZEOF_PTR == 3)\n\treturn (atomic_cas_uint64((uint64_t *)p, (uint64_t)c, (uint64_t)s));\n#elif (LG_SIZEOF_PTR == 2)\n\treturn (atomic_cas_uint32((uint32_t *)p, (uint32_t)c, (uint32_t)s));\n#endif\n}\n\nJEMALLOC_INLINE void\natomic_write_p(void **p, const void *x)\n{\n\n#if (LG_SIZEOF_PTR == 3)\n\tatomic_write_uint64((uint64_t *)p, (uint64_t)x);\n#elif (LG_SIZEOF_PTR == 2)\n\tatomic_write_uint32((uint32_t *)p, (uint32_t)x);\n#endif\n}\n\n/******************************************************************************/\n/* size_t operations. */\nJEMALLOC_INLINE size_t\natomic_add_z(size_t *p, size_t x)\n{\n\n#if (LG_SIZEOF_PTR == 3)\n\treturn ((size_t)atomic_add_uint64((uint64_t *)p, (uint64_t)x));\n#elif (LG_SIZEOF_PTR == 2)\n\treturn ((size_t)atomic_add_uint32((uint32_t *)p, (uint32_t)x));\n#endif\n}\n\nJEMALLOC_INLINE size_t\natomic_sub_z(size_t *p, size_t x)\n{\n\n#if (LG_SIZEOF_PTR == 3)\n\treturn ((size_t)atomic_add_uint64((uint64_t *)p,\n\t    (uint64_t)-((int64_t)x)));\n#elif (LG_SIZEOF_PTR == 2)\n\treturn ((size_t)atomic_add_uint32((uint32_t *)p,\n\t    (uint32_t)-((int32_t)x)));\n#endif\n}\n\nJEMALLOC_INLINE bool\natomic_cas_z(size_t *p, size_t c, size_t s)\n{\n\n#if (LG_SIZEOF_PTR == 3)\n\treturn (atomic_cas_uint64((uint64_t *)p, (uint64_t)c, (uint64_t)s));\n#elif (LG_SIZEOF_PTR == 2)\n\treturn (atomic_cas_uint32((uint32_t *)p, (uint32_t)c, (uint32_t)s));\n#endif\n}\n\nJEMALLOC_INLINE void\natomic_write_z(size_t *p, size_t x)\n{\n\n#if (LG_SIZEOF_PTR == 3)\n\tatomic_write_uint64((uint64_t *)p, (uint64_t)x);\n#elif (LG_SIZEOF_PTR == 2)\n\tatomic_write_uint32((uint32_t *)p, (uint32_t)x);\n#endif\n}\n\n/******************************************************************************/\n/* unsigned operations. */\nJEMALLOC_INLINE unsigned\natomic_add_u(unsigned *p, unsigned x)\n{\n\n#if (LG_SIZEOF_INT == 3)\n\treturn ((unsigned)atomic_add_uint64((uint64_t *)p, (uint64_t)x));\n#elif (LG_SIZEOF_INT == 2)\n\treturn ((unsigned)atomic_add_uint32((uint32_t *)p, (uint32_t)x));\n#endif\n}\n\nJEMALLOC_INLINE unsigned\natomic_sub_u(unsigned *p, unsigned x)\n{\n\n#if (LG_SIZEOF_INT == 3)\n\treturn ((unsigned)atomic_add_uint64((uint64_t *)p,\n\t    (uint64_t)-((int64_t)x)));\n#elif (LG_SIZEOF_INT == 2)\n\treturn ((unsigned)atomic_add_uint32((uint32_t *)p,\n\t    (uint32_t)-((int32_t)x)));\n#endif\n}\n\nJEMALLOC_INLINE bool\natomic_cas_u(unsigned *p, unsigned c, unsigned s)\n{\n\n#if (LG_SIZEOF_INT == 3)\n\treturn (atomic_cas_uint64((uint64_t *)p, (uint64_t)c, (uint64_t)s));\n#elif (LG_SIZEOF_INT == 2)\n\treturn (atomic_cas_uint32((uint32_t *)p, (uint32_t)c, (uint32_t)s));\n#endif\n}\n\nJEMALLOC_INLINE void\natomic_write_u(unsigned *p, unsigned x)\n{\n\n#if (LG_SIZEOF_INT == 3)\n\tatomic_write_uint64((uint64_t *)p, (uint64_t)x);\n#elif (LG_SIZEOF_INT == 2)\n\tatomic_write_uint32((uint32_t *)p, (uint32_t)x);\n#endif\n}\n\n/******************************************************************************/\n#endif\n\n#endif /* JEMALLOC_H_INLINES */\n/******************************************************************************/\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.8/deps/jemalloc/include/jemalloc/internal/base.h",
    "content": "/******************************************************************************/\n#ifdef JEMALLOC_H_TYPES\n\n#endif /* JEMALLOC_H_TYPES */\n/******************************************************************************/\n#ifdef JEMALLOC_H_STRUCTS\n\n#endif /* JEMALLOC_H_STRUCTS */\n/******************************************************************************/\n#ifdef JEMALLOC_H_EXTERNS\n\nvoid\t*base_alloc(size_t size);\nvoid\tbase_stats_get(size_t *allocated, size_t *resident, size_t *mapped);\nbool\tbase_boot(void);\nvoid\tbase_prefork(void);\nvoid\tbase_postfork_parent(void);\nvoid\tbase_postfork_child(void);\n\n#endif /* JEMALLOC_H_EXTERNS */\n/******************************************************************************/\n#ifdef JEMALLOC_H_INLINES\n\n#endif /* JEMALLOC_H_INLINES */\n/******************************************************************************/\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.8/deps/jemalloc/include/jemalloc/internal/bitmap.h",
    "content": "/******************************************************************************/\n#ifdef JEMALLOC_H_TYPES\n\n/* Maximum bitmap bit count is 2^LG_BITMAP_MAXBITS. */\n#define\tLG_BITMAP_MAXBITS\tLG_RUN_MAXREGS\n#define\tBITMAP_MAXBITS\t\t(ZU(1) << LG_BITMAP_MAXBITS)\n\ntypedef struct bitmap_level_s bitmap_level_t;\ntypedef struct bitmap_info_s bitmap_info_t;\ntypedef unsigned long bitmap_t;\n#define\tLG_SIZEOF_BITMAP\tLG_SIZEOF_LONG\n\n/* Number of bits per group. */\n#define\tLG_BITMAP_GROUP_NBITS\t\t(LG_SIZEOF_BITMAP + 3)\n#define\tBITMAP_GROUP_NBITS\t\t(ZU(1) << LG_BITMAP_GROUP_NBITS)\n#define\tBITMAP_GROUP_NBITS_MASK\t\t(BITMAP_GROUP_NBITS-1)\n\n/* Number of groups required to store a given number of bits. */\n#define\tBITMAP_BITS2GROUPS(nbits)\t\t\t\t\t\\\n    ((nbits + BITMAP_GROUP_NBITS_MASK) >> LG_BITMAP_GROUP_NBITS)\n\n/*\n * Number of groups required at a particular level for a given number of bits.\n */\n#define\tBITMAP_GROUPS_L0(nbits)\t\t\t\t\t\t\\\n    BITMAP_BITS2GROUPS(nbits)\n#define\tBITMAP_GROUPS_L1(nbits)\t\t\t\t\t\t\\\n    BITMAP_BITS2GROUPS(BITMAP_BITS2GROUPS(nbits))\n#define\tBITMAP_GROUPS_L2(nbits)\t\t\t\t\t\t\\\n    BITMAP_BITS2GROUPS(BITMAP_BITS2GROUPS(BITMAP_BITS2GROUPS((nbits))))\n#define\tBITMAP_GROUPS_L3(nbits)\t\t\t\t\t\t\\\n    BITMAP_BITS2GROUPS(BITMAP_BITS2GROUPS(BITMAP_BITS2GROUPS(\t\t\\\n\tBITMAP_BITS2GROUPS((nbits)))))\n\n/*\n * Assuming the number of levels, number of groups required for a given number\n * of bits.\n */\n#define\tBITMAP_GROUPS_1_LEVEL(nbits)\t\t\t\t\t\\\n    BITMAP_GROUPS_L0(nbits)\n#define\tBITMAP_GROUPS_2_LEVEL(nbits)\t\t\t\t\t\\\n    (BITMAP_GROUPS_1_LEVEL(nbits) + BITMAP_GROUPS_L1(nbits))\n#define\tBITMAP_GROUPS_3_LEVEL(nbits)\t\t\t\t\t\\\n    (BITMAP_GROUPS_2_LEVEL(nbits) + BITMAP_GROUPS_L2(nbits))\n#define\tBITMAP_GROUPS_4_LEVEL(nbits)\t\t\t\t\t\\\n    (BITMAP_GROUPS_3_LEVEL(nbits) + BITMAP_GROUPS_L3(nbits))\n\n/*\n * Maximum number of groups required to support LG_BITMAP_MAXBITS.\n */\n#if LG_BITMAP_MAXBITS <= LG_BITMAP_GROUP_NBITS\n#  define BITMAP_GROUPS_MAX\tBITMAP_GROUPS_1_LEVEL(BITMAP_MAXBITS)\n#elif LG_BITMAP_MAXBITS <= LG_BITMAP_GROUP_NBITS * 2\n#  define BITMAP_GROUPS_MAX\tBITMAP_GROUPS_2_LEVEL(BITMAP_MAXBITS)\n#elif LG_BITMAP_MAXBITS <= LG_BITMAP_GROUP_NBITS * 3\n#  define BITMAP_GROUPS_MAX\tBITMAP_GROUPS_3_LEVEL(BITMAP_MAXBITS)\n#elif LG_BITMAP_MAXBITS <= LG_BITMAP_GROUP_NBITS * 4\n#  define BITMAP_GROUPS_MAX\tBITMAP_GROUPS_4_LEVEL(BITMAP_MAXBITS)\n#else\n#  error \"Unsupported bitmap size\"\n#endif\n\n/* Maximum number of levels possible. */\n#define\tBITMAP_MAX_LEVELS\t\t\t\t\t\t\\\n    (LG_BITMAP_MAXBITS / LG_SIZEOF_BITMAP)\t\t\t\t\\\n    + !!(LG_BITMAP_MAXBITS % LG_SIZEOF_BITMAP)\n\n#endif /* JEMALLOC_H_TYPES */\n/******************************************************************************/\n#ifdef JEMALLOC_H_STRUCTS\n\nstruct bitmap_level_s {\n\t/* Offset of this level's groups within the array of groups. */\n\tsize_t group_offset;\n};\n\nstruct bitmap_info_s {\n\t/* Logical number of bits in bitmap (stored at bottom level). */\n\tsize_t nbits;\n\n\t/* Number of levels necessary for nbits. */\n\tunsigned nlevels;\n\n\t/*\n\t * Only the first (nlevels+1) elements are used, and levels are ordered\n\t * bottom to top (e.g. the bottom level is stored in levels[0]).\n\t */\n\tbitmap_level_t levels[BITMAP_MAX_LEVELS+1];\n};\n\n#endif /* JEMALLOC_H_STRUCTS */\n/******************************************************************************/\n#ifdef JEMALLOC_H_EXTERNS\n\nvoid\tbitmap_info_init(bitmap_info_t *binfo, size_t nbits);\nsize_t\tbitmap_info_ngroups(const bitmap_info_t *binfo);\nsize_t\tbitmap_size(size_t nbits);\nvoid\tbitmap_init(bitmap_t *bitmap, const bitmap_info_t *binfo);\n\n#endif /* JEMALLOC_H_EXTERNS */\n/******************************************************************************/\n#ifdef JEMALLOC_H_INLINES\n\n#ifndef JEMALLOC_ENABLE_INLINE\nbool\tbitmap_full(bitmap_t *bitmap, const bitmap_info_t *binfo);\nbool\tbitmap_get(bitmap_t *bitmap, const bitmap_info_t *binfo, size_t bit);\nvoid\tbitmap_set(bitmap_t *bitmap, const bitmap_info_t *binfo, size_t bit);\nsize_t\tbitmap_sfu(bitmap_t *bitmap, const bitmap_info_t *binfo);\nvoid\tbitmap_unset(bitmap_t *bitmap, const bitmap_info_t *binfo, size_t bit);\n#endif\n\n#if (defined(JEMALLOC_ENABLE_INLINE) || defined(JEMALLOC_BITMAP_C_))\nJEMALLOC_INLINE bool\nbitmap_full(bitmap_t *bitmap, const bitmap_info_t *binfo)\n{\n\tunsigned rgoff = binfo->levels[binfo->nlevels].group_offset - 1;\n\tbitmap_t rg = bitmap[rgoff];\n\t/* The bitmap is full iff the root group is 0. */\n\treturn (rg == 0);\n}\n\nJEMALLOC_INLINE bool\nbitmap_get(bitmap_t *bitmap, const bitmap_info_t *binfo, size_t bit)\n{\n\tsize_t goff;\n\tbitmap_t g;\n\n\tassert(bit < binfo->nbits);\n\tgoff = bit >> LG_BITMAP_GROUP_NBITS;\n\tg = bitmap[goff];\n\treturn (!(g & (1LU << (bit & BITMAP_GROUP_NBITS_MASK))));\n}\n\nJEMALLOC_INLINE void\nbitmap_set(bitmap_t *bitmap, const bitmap_info_t *binfo, size_t bit)\n{\n\tsize_t goff;\n\tbitmap_t *gp;\n\tbitmap_t g;\n\n\tassert(bit < binfo->nbits);\n\tassert(!bitmap_get(bitmap, binfo, bit));\n\tgoff = bit >> LG_BITMAP_GROUP_NBITS;\n\tgp = &bitmap[goff];\n\tg = *gp;\n\tassert(g & (1LU << (bit & BITMAP_GROUP_NBITS_MASK)));\n\tg ^= 1LU << (bit & BITMAP_GROUP_NBITS_MASK);\n\t*gp = g;\n\tassert(bitmap_get(bitmap, binfo, bit));\n\t/* Propagate group state transitions up the tree. */\n\tif (g == 0) {\n\t\tunsigned i;\n\t\tfor (i = 1; i < binfo->nlevels; i++) {\n\t\t\tbit = goff;\n\t\t\tgoff = bit >> LG_BITMAP_GROUP_NBITS;\n\t\t\tgp = &bitmap[binfo->levels[i].group_offset + goff];\n\t\t\tg = *gp;\n\t\t\tassert(g & (1LU << (bit & BITMAP_GROUP_NBITS_MASK)));\n\t\t\tg ^= 1LU << (bit & BITMAP_GROUP_NBITS_MASK);\n\t\t\t*gp = g;\n\t\t\tif (g != 0)\n\t\t\t\tbreak;\n\t\t}\n\t}\n}\n\n/* sfu: set first unset. */\nJEMALLOC_INLINE size_t\nbitmap_sfu(bitmap_t *bitmap, const bitmap_info_t *binfo)\n{\n\tsize_t bit;\n\tbitmap_t g;\n\tunsigned i;\n\n\tassert(!bitmap_full(bitmap, binfo));\n\n\ti = binfo->nlevels - 1;\n\tg = bitmap[binfo->levels[i].group_offset];\n\tbit = jemalloc_ffsl(g) - 1;\n\twhile (i > 0) {\n\t\ti--;\n\t\tg = bitmap[binfo->levels[i].group_offset + bit];\n\t\tbit = (bit << LG_BITMAP_GROUP_NBITS) + (jemalloc_ffsl(g) - 1);\n\t}\n\n\tbitmap_set(bitmap, binfo, bit);\n\treturn (bit);\n}\n\nJEMALLOC_INLINE void\nbitmap_unset(bitmap_t *bitmap, const bitmap_info_t *binfo, size_t bit)\n{\n\tsize_t goff;\n\tbitmap_t *gp;\n\tbitmap_t g;\n\tbool propagate;\n\n\tassert(bit < binfo->nbits);\n\tassert(bitmap_get(bitmap, binfo, bit));\n\tgoff = bit >> LG_BITMAP_GROUP_NBITS;\n\tgp = &bitmap[goff];\n\tg = *gp;\n\tpropagate = (g == 0);\n\tassert((g & (1LU << (bit & BITMAP_GROUP_NBITS_MASK))) == 0);\n\tg ^= 1LU << (bit & BITMAP_GROUP_NBITS_MASK);\n\t*gp = g;\n\tassert(!bitmap_get(bitmap, binfo, bit));\n\t/* Propagate group state transitions up the tree. */\n\tif (propagate) {\n\t\tunsigned i;\n\t\tfor (i = 1; i < binfo->nlevels; i++) {\n\t\t\tbit = goff;\n\t\t\tgoff = bit >> LG_BITMAP_GROUP_NBITS;\n\t\t\tgp = &bitmap[binfo->levels[i].group_offset + goff];\n\t\t\tg = *gp;\n\t\t\tpropagate = (g == 0);\n\t\t\tassert((g & (1LU << (bit & BITMAP_GROUP_NBITS_MASK)))\n\t\t\t    == 0);\n\t\t\tg ^= 1LU << (bit & BITMAP_GROUP_NBITS_MASK);\n\t\t\t*gp = g;\n\t\t\tif (!propagate)\n\t\t\t\tbreak;\n\t\t}\n\t}\n}\n\n#endif\n\n#endif /* JEMALLOC_H_INLINES */\n/******************************************************************************/\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.8/deps/jemalloc/include/jemalloc/internal/chunk.h",
    "content": "/******************************************************************************/\n#ifdef JEMALLOC_H_TYPES\n\n/*\n * Size and alignment of memory chunks that are allocated by the OS's virtual\n * memory system.\n */\n#define\tLG_CHUNK_DEFAULT\t21\n\n/* Return the chunk address for allocation address a. */\n#define\tCHUNK_ADDR2BASE(a)\t\t\t\t\t\t\\\n\t((void *)((uintptr_t)(a) & ~chunksize_mask))\n\n/* Return the chunk offset of address a. */\n#define\tCHUNK_ADDR2OFFSET(a)\t\t\t\t\t\t\\\n\t((size_t)((uintptr_t)(a) & chunksize_mask))\n\n/* Return the smallest chunk multiple that is >= s. */\n#define\tCHUNK_CEILING(s)\t\t\t\t\t\t\\\n\t(((s) + chunksize_mask) & ~chunksize_mask)\n\n#define\tCHUNK_HOOKS_INITIALIZER {\t\t\t\t\t\\\n    NULL,\t\t\t\t\t\t\t\t\\\n    NULL,\t\t\t\t\t\t\t\t\\\n    NULL,\t\t\t\t\t\t\t\t\\\n    NULL,\t\t\t\t\t\t\t\t\\\n    NULL,\t\t\t\t\t\t\t\t\\\n    NULL,\t\t\t\t\t\t\t\t\\\n    NULL\t\t\t\t\t\t\t\t\\\n}\n\n#endif /* JEMALLOC_H_TYPES */\n/******************************************************************************/\n#ifdef JEMALLOC_H_STRUCTS\n\n#endif /* JEMALLOC_H_STRUCTS */\n/******************************************************************************/\n#ifdef JEMALLOC_H_EXTERNS\n\nextern size_t\t\topt_lg_chunk;\nextern const char\t*opt_dss;\n\nextern rtree_t\t\tchunks_rtree;\n\nextern size_t\t\tchunksize;\nextern size_t\t\tchunksize_mask; /* (chunksize - 1). */\nextern size_t\t\tchunk_npages;\n\nextern const chunk_hooks_t\tchunk_hooks_default;\n\nchunk_hooks_t\tchunk_hooks_get(arena_t *arena);\nchunk_hooks_t\tchunk_hooks_set(arena_t *arena,\n    const chunk_hooks_t *chunk_hooks);\n\nbool\tchunk_register(const void *chunk, const extent_node_t *node);\nvoid\tchunk_deregister(const void *chunk, const extent_node_t *node);\nvoid\t*chunk_alloc_base(size_t size);\nvoid\t*chunk_alloc_cache(arena_t *arena, chunk_hooks_t *chunk_hooks,\n    void *new_addr, size_t size, size_t alignment, bool *zero,\n    bool dalloc_node);\nvoid\t*chunk_alloc_wrapper(arena_t *arena, chunk_hooks_t *chunk_hooks,\n    void *new_addr, size_t size, size_t alignment, bool *zero, bool *commit);\nvoid\tchunk_dalloc_cache(arena_t *arena, chunk_hooks_t *chunk_hooks,\n    void *chunk, size_t size, bool committed);\nvoid\tchunk_dalloc_arena(arena_t *arena, chunk_hooks_t *chunk_hooks,\n    void *chunk, size_t size, bool zeroed, bool committed);\nvoid\tchunk_dalloc_wrapper(arena_t *arena, chunk_hooks_t *chunk_hooks,\n    void *chunk, size_t size, bool committed);\nbool\tchunk_purge_arena(arena_t *arena, void *chunk, size_t offset,\n    size_t length);\nbool\tchunk_purge_wrapper(arena_t *arena, chunk_hooks_t *chunk_hooks,\n    void *chunk, size_t size, size_t offset, size_t length);\nbool\tchunk_boot(void);\nvoid\tchunk_prefork(void);\nvoid\tchunk_postfork_parent(void);\nvoid\tchunk_postfork_child(void);\n\n#endif /* JEMALLOC_H_EXTERNS */\n/******************************************************************************/\n#ifdef JEMALLOC_H_INLINES\n\n#ifndef JEMALLOC_ENABLE_INLINE\nextent_node_t\t*chunk_lookup(const void *chunk, bool dependent);\n#endif\n\n#if (defined(JEMALLOC_ENABLE_INLINE) || defined(JEMALLOC_CHUNK_C_))\nJEMALLOC_INLINE extent_node_t *\nchunk_lookup(const void *ptr, bool dependent)\n{\n\n\treturn (rtree_get(&chunks_rtree, (uintptr_t)ptr, dependent));\n}\n#endif\n\n#endif /* JEMALLOC_H_INLINES */\n/******************************************************************************/\n\n#include \"jemalloc/internal/chunk_dss.h\"\n#include \"jemalloc/internal/chunk_mmap.h\"\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.8/deps/jemalloc/include/jemalloc/internal/chunk_dss.h",
    "content": "/******************************************************************************/\n#ifdef JEMALLOC_H_TYPES\n\ntypedef enum {\n\tdss_prec_disabled  = 0,\n\tdss_prec_primary   = 1,\n\tdss_prec_secondary = 2,\n\n\tdss_prec_limit     = 3\n} dss_prec_t;\n#define\tDSS_PREC_DEFAULT\tdss_prec_secondary\n#define\tDSS_DEFAULT\t\t\"secondary\"\n\n#endif /* JEMALLOC_H_TYPES */\n/******************************************************************************/\n#ifdef JEMALLOC_H_STRUCTS\n\nextern const char *dss_prec_names[];\n\n#endif /* JEMALLOC_H_STRUCTS */\n/******************************************************************************/\n#ifdef JEMALLOC_H_EXTERNS\n\ndss_prec_t\tchunk_dss_prec_get(void);\nbool\tchunk_dss_prec_set(dss_prec_t dss_prec);\nvoid\t*chunk_alloc_dss(arena_t *arena, void *new_addr, size_t size,\n    size_t alignment, bool *zero, bool *commit);\nbool\tchunk_in_dss(void *chunk);\nbool\tchunk_dss_boot(void);\nvoid\tchunk_dss_prefork(void);\nvoid\tchunk_dss_postfork_parent(void);\nvoid\tchunk_dss_postfork_child(void);\n\n#endif /* JEMALLOC_H_EXTERNS */\n/******************************************************************************/\n#ifdef JEMALLOC_H_INLINES\n\n#endif /* JEMALLOC_H_INLINES */\n/******************************************************************************/\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.8/deps/jemalloc/include/jemalloc/internal/chunk_mmap.h",
    "content": "/******************************************************************************/\n#ifdef JEMALLOC_H_TYPES\n\n#endif /* JEMALLOC_H_TYPES */\n/******************************************************************************/\n#ifdef JEMALLOC_H_STRUCTS\n\n#endif /* JEMALLOC_H_STRUCTS */\n/******************************************************************************/\n#ifdef JEMALLOC_H_EXTERNS\n\nvoid\t*chunk_alloc_mmap(size_t size, size_t alignment, bool *zero,\n    bool *commit);\nbool\tchunk_dalloc_mmap(void *chunk, size_t size);\n\n#endif /* JEMALLOC_H_EXTERNS */\n/******************************************************************************/\n#ifdef JEMALLOC_H_INLINES\n\n#endif /* JEMALLOC_H_INLINES */\n/******************************************************************************/\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.8/deps/jemalloc/include/jemalloc/internal/ckh.h",
    "content": "/******************************************************************************/\n#ifdef JEMALLOC_H_TYPES\n\ntypedef struct ckh_s ckh_t;\ntypedef struct ckhc_s ckhc_t;\n\n/* Typedefs to allow easy function pointer passing. */\ntypedef void ckh_hash_t (const void *, size_t[2]);\ntypedef bool ckh_keycomp_t (const void *, const void *);\n\n/* Maintain counters used to get an idea of performance. */\n/* #define\tCKH_COUNT */\n/* Print counter values in ckh_delete() (requires CKH_COUNT). */\n/* #define\tCKH_VERBOSE */\n\n/*\n * There are 2^LG_CKH_BUCKET_CELLS cells in each hash table bucket.  Try to fit\n * one bucket per L1 cache line.\n */\n#define\tLG_CKH_BUCKET_CELLS (LG_CACHELINE - LG_SIZEOF_PTR - 1)\n\n#endif /* JEMALLOC_H_TYPES */\n/******************************************************************************/\n#ifdef JEMALLOC_H_STRUCTS\n\n/* Hash table cell. */\nstruct ckhc_s {\n\tconst void\t*key;\n\tconst void\t*data;\n};\n\nstruct ckh_s {\n#ifdef CKH_COUNT\n\t/* Counters used to get an idea of performance. */\n\tuint64_t\tngrows;\n\tuint64_t\tnshrinks;\n\tuint64_t\tnshrinkfails;\n\tuint64_t\tninserts;\n\tuint64_t\tnrelocs;\n#endif\n\n\t/* Used for pseudo-random number generation. */\n#define\tCKH_A\t\t1103515241\n#define\tCKH_C\t\t12347\n\tuint32_t\tprng_state;\n\n\t/* Total number of items. */\n\tsize_t\t\tcount;\n\n\t/*\n\t * Minimum and current number of hash table buckets.  There are\n\t * 2^LG_CKH_BUCKET_CELLS cells per bucket.\n\t */\n\tunsigned\tlg_minbuckets;\n\tunsigned\tlg_curbuckets;\n\n\t/* Hash and comparison functions. */\n\tckh_hash_t\t*hash;\n\tckh_keycomp_t\t*keycomp;\n\n\t/* Hash table with 2^lg_curbuckets buckets. */\n\tckhc_t\t\t*tab;\n};\n\n#endif /* JEMALLOC_H_STRUCTS */\n/******************************************************************************/\n#ifdef JEMALLOC_H_EXTERNS\n\nbool\tckh_new(tsd_t *tsd, ckh_t *ckh, size_t minitems, ckh_hash_t *hash,\n    ckh_keycomp_t *keycomp);\nvoid\tckh_delete(tsd_t *tsd, ckh_t *ckh);\nsize_t\tckh_count(ckh_t *ckh);\nbool\tckh_iter(ckh_t *ckh, size_t *tabind, void **key, void **data);\nbool\tckh_insert(tsd_t *tsd, ckh_t *ckh, const void *key, const void *data);\nbool\tckh_remove(tsd_t *tsd, ckh_t *ckh, const void *searchkey, void **key,\n    void **data);\nbool\tckh_search(ckh_t *ckh, const void *seachkey, void **key, void **data);\nvoid\tckh_string_hash(const void *key, size_t r_hash[2]);\nbool\tckh_string_keycomp(const void *k1, const void *k2);\nvoid\tckh_pointer_hash(const void *key, size_t r_hash[2]);\nbool\tckh_pointer_keycomp(const void *k1, const void *k2);\n\n#endif /* JEMALLOC_H_EXTERNS */\n/******************************************************************************/\n#ifdef JEMALLOC_H_INLINES\n\n#endif /* JEMALLOC_H_INLINES */\n/******************************************************************************/\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.8/deps/jemalloc/include/jemalloc/internal/ctl.h",
    "content": "/******************************************************************************/\n#ifdef JEMALLOC_H_TYPES\n\ntypedef struct ctl_node_s ctl_node_t;\ntypedef struct ctl_named_node_s ctl_named_node_t;\ntypedef struct ctl_indexed_node_s ctl_indexed_node_t;\ntypedef struct ctl_arena_stats_s ctl_arena_stats_t;\ntypedef struct ctl_stats_s ctl_stats_t;\n\n#endif /* JEMALLOC_H_TYPES */\n/******************************************************************************/\n#ifdef JEMALLOC_H_STRUCTS\n\nstruct ctl_node_s {\n\tbool\t\t\tnamed;\n};\n\nstruct ctl_named_node_s {\n\tstruct ctl_node_s\tnode;\n\tconst char\t\t*name;\n\t/* If (nchildren == 0), this is a terminal node. */\n\tunsigned\t\tnchildren;\n\tconst\t\t\tctl_node_t *children;\n\tint\t\t\t(*ctl)(const size_t *, size_t, void *, size_t *,\n\t    void *, size_t);\n};\n\nstruct ctl_indexed_node_s {\n\tstruct ctl_node_s\tnode;\n\tconst ctl_named_node_t\t*(*index)(const size_t *, size_t, size_t);\n};\n\nstruct ctl_arena_stats_s {\n\tbool\t\t\tinitialized;\n\tunsigned\t\tnthreads;\n\tconst char\t\t*dss;\n\tssize_t\t\t\tlg_dirty_mult;\n\tsize_t\t\t\tpactive;\n\tsize_t\t\t\tpdirty;\n\tarena_stats_t\t\tastats;\n\n\t/* Aggregate stats for small size classes, based on bin stats. */\n\tsize_t\t\t\tallocated_small;\n\tuint64_t\t\tnmalloc_small;\n\tuint64_t\t\tndalloc_small;\n\tuint64_t\t\tnrequests_small;\n\n\tmalloc_bin_stats_t\tbstats[NBINS];\n\tmalloc_large_stats_t\t*lstats;\t/* nlclasses elements. */\n\tmalloc_huge_stats_t\t*hstats;\t/* nhclasses elements. */\n};\n\nstruct ctl_stats_s {\n\tsize_t\t\t\tallocated;\n\tsize_t\t\t\tactive;\n\tsize_t\t\t\tmetadata;\n\tsize_t\t\t\tresident;\n\tsize_t\t\t\tmapped;\n\tunsigned\t\tnarenas;\n\tctl_arena_stats_t\t*arenas;\t/* (narenas + 1) elements. */\n};\n\n#endif /* JEMALLOC_H_STRUCTS */\n/******************************************************************************/\n#ifdef JEMALLOC_H_EXTERNS\n\nint\tctl_byname(const char *name, void *oldp, size_t *oldlenp, void *newp,\n    size_t newlen);\nint\tctl_nametomib(const char *name, size_t *mibp, size_t *miblenp);\n\nint\tctl_bymib(const size_t *mib, size_t miblen, void *oldp, size_t *oldlenp,\n    void *newp, size_t newlen);\nbool\tctl_boot(void);\nvoid\tctl_prefork(void);\nvoid\tctl_postfork_parent(void);\nvoid\tctl_postfork_child(void);\n\n#define\txmallctl(name, oldp, oldlenp, newp, newlen) do {\t\t\\\n\tif (je_mallctl(name, oldp, oldlenp, newp, newlen)\t\t\\\n\t    != 0) {\t\t\t\t\t\t\t\\\n\t\tmalloc_printf(\t\t\t\t\t\t\\\n\t\t    \"<jemalloc>: Failure in xmallctl(\\\"%s\\\", ...)\\n\",\t\\\n\t\t    name);\t\t\t\t\t\t\\\n\t\tabort();\t\t\t\t\t\t\\\n\t}\t\t\t\t\t\t\t\t\\\n} while (0)\n\n#define\txmallctlnametomib(name, mibp, miblenp) do {\t\t\t\\\n\tif (je_mallctlnametomib(name, mibp, miblenp) != 0) {\t\t\\\n\t\tmalloc_printf(\"<jemalloc>: Failure in \"\t\t\t\\\n\t\t    \"xmallctlnametomib(\\\"%s\\\", ...)\\n\", name);\t\t\\\n\t\tabort();\t\t\t\t\t\t\\\n\t}\t\t\t\t\t\t\t\t\\\n} while (0)\n\n#define\txmallctlbymib(mib, miblen, oldp, oldlenp, newp, newlen) do {\t\\\n\tif (je_mallctlbymib(mib, miblen, oldp, oldlenp, newp,\t\t\\\n\t    newlen) != 0) {\t\t\t\t\t\t\\\n\t\tmalloc_write(\t\t\t\t\t\t\\\n\t\t    \"<jemalloc>: Failure in xmallctlbymib()\\n\");\t\\\n\t\tabort();\t\t\t\t\t\t\\\n\t}\t\t\t\t\t\t\t\t\\\n} while (0)\n\n#endif /* JEMALLOC_H_EXTERNS */\n/******************************************************************************/\n#ifdef JEMALLOC_H_INLINES\n\n#endif /* JEMALLOC_H_INLINES */\n/******************************************************************************/\n\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.8/deps/jemalloc/include/jemalloc/internal/extent.h",
    "content": "/******************************************************************************/\n#ifdef JEMALLOC_H_TYPES\n\ntypedef struct extent_node_s extent_node_t;\n\n#endif /* JEMALLOC_H_TYPES */\n/******************************************************************************/\n#ifdef JEMALLOC_H_STRUCTS\n\n/* Tree of extents.  Use accessor functions for en_* fields. */\nstruct extent_node_s {\n\t/* Arena from which this extent came, if any. */\n\tarena_t\t\t\t*en_arena;\n\n\t/* Pointer to the extent that this tree node is responsible for. */\n\tvoid\t\t\t*en_addr;\n\n\t/* Total region size. */\n\tsize_t\t\t\ten_size;\n\n\t/*\n\t * The zeroed flag is used by chunk recycling code to track whether\n\t * memory is zero-filled.\n\t */\n\tbool\t\t\ten_zeroed;\n\n\t/*\n\t * True if physical memory is committed to the extent, whether\n\t * explicitly or implicitly as on a system that overcommits and\n\t * satisfies physical memory needs on demand via soft page faults.\n\t */\n\tbool\t\t\ten_committed;\n\n\t/*\n\t * The achunk flag is used to validate that huge allocation lookups\n\t * don't return arena chunks.\n\t */\n\tbool\t\t\ten_achunk;\n\n\t/* Profile counters, used for huge objects. */\n\tprof_tctx_t\t\t*en_prof_tctx;\n\n\t/* Linkage for arena's runs_dirty and chunks_cache rings. */\n\tarena_runs_dirty_link_t\trd;\n\tqr(extent_node_t)\tcc_link;\n\n\tunion {\n\t\t/* Linkage for the size/address-ordered tree. */\n\t\trb_node(extent_node_t)\tszad_link;\n\n\t\t/* Linkage for arena's huge and node_cache lists. */\n\t\tql_elm(extent_node_t)\tql_link;\n\t};\n\n\t/* Linkage for the address-ordered tree. */\n\trb_node(extent_node_t)\tad_link;\n};\ntypedef rb_tree(extent_node_t) extent_tree_t;\n\n#endif /* JEMALLOC_H_STRUCTS */\n/******************************************************************************/\n#ifdef JEMALLOC_H_EXTERNS\n\nrb_proto(, extent_tree_szad_, extent_tree_t, extent_node_t)\n\nrb_proto(, extent_tree_ad_, extent_tree_t, extent_node_t)\n\n#endif /* JEMALLOC_H_EXTERNS */\n/******************************************************************************/\n#ifdef JEMALLOC_H_INLINES\n\n#ifndef JEMALLOC_ENABLE_INLINE\narena_t\t*extent_node_arena_get(const extent_node_t *node);\nvoid\t*extent_node_addr_get(const extent_node_t *node);\nsize_t\textent_node_size_get(const extent_node_t *node);\nbool\textent_node_zeroed_get(const extent_node_t *node);\nbool\textent_node_committed_get(const extent_node_t *node);\nbool\textent_node_achunk_get(const extent_node_t *node);\nprof_tctx_t\t*extent_node_prof_tctx_get(const extent_node_t *node);\nvoid\textent_node_arena_set(extent_node_t *node, arena_t *arena);\nvoid\textent_node_addr_set(extent_node_t *node, void *addr);\nvoid\textent_node_size_set(extent_node_t *node, size_t size);\nvoid\textent_node_zeroed_set(extent_node_t *node, bool zeroed);\nvoid\textent_node_committed_set(extent_node_t *node, bool committed);\nvoid\textent_node_achunk_set(extent_node_t *node, bool achunk);\nvoid\textent_node_prof_tctx_set(extent_node_t *node, prof_tctx_t *tctx);\nvoid\textent_node_init(extent_node_t *node, arena_t *arena, void *addr,\n    size_t size, bool zeroed, bool committed);\nvoid\textent_node_dirty_linkage_init(extent_node_t *node);\nvoid\textent_node_dirty_insert(extent_node_t *node,\n    arena_runs_dirty_link_t *runs_dirty, extent_node_t *chunks_dirty);\nvoid\textent_node_dirty_remove(extent_node_t *node);\n#endif\n\n#if (defined(JEMALLOC_ENABLE_INLINE) || defined(JEMALLOC_EXTENT_C_))\nJEMALLOC_INLINE arena_t *\nextent_node_arena_get(const extent_node_t *node)\n{\n\n\treturn (node->en_arena);\n}\n\nJEMALLOC_INLINE void *\nextent_node_addr_get(const extent_node_t *node)\n{\n\n\treturn (node->en_addr);\n}\n\nJEMALLOC_INLINE size_t\nextent_node_size_get(const extent_node_t *node)\n{\n\n\treturn (node->en_size);\n}\n\nJEMALLOC_INLINE bool\nextent_node_zeroed_get(const extent_node_t *node)\n{\n\n\treturn (node->en_zeroed);\n}\n\nJEMALLOC_INLINE bool\nextent_node_committed_get(const extent_node_t *node)\n{\n\n\tassert(!node->en_achunk);\n\treturn (node->en_committed);\n}\n\nJEMALLOC_INLINE bool\nextent_node_achunk_get(const extent_node_t *node)\n{\n\n\treturn (node->en_achunk);\n}\n\nJEMALLOC_INLINE prof_tctx_t *\nextent_node_prof_tctx_get(const extent_node_t *node)\n{\n\n\treturn (node->en_prof_tctx);\n}\n\nJEMALLOC_INLINE void\nextent_node_arena_set(extent_node_t *node, arena_t *arena)\n{\n\n\tnode->en_arena = arena;\n}\n\nJEMALLOC_INLINE void\nextent_node_addr_set(extent_node_t *node, void *addr)\n{\n\n\tnode->en_addr = addr;\n}\n\nJEMALLOC_INLINE void\nextent_node_size_set(extent_node_t *node, size_t size)\n{\n\n\tnode->en_size = size;\n}\n\nJEMALLOC_INLINE void\nextent_node_zeroed_set(extent_node_t *node, bool zeroed)\n{\n\n\tnode->en_zeroed = zeroed;\n}\n\nJEMALLOC_INLINE void\nextent_node_committed_set(extent_node_t *node, bool committed)\n{\n\n\tnode->en_committed = committed;\n}\n\nJEMALLOC_INLINE void\nextent_node_achunk_set(extent_node_t *node, bool achunk)\n{\n\n\tnode->en_achunk = achunk;\n}\n\nJEMALLOC_INLINE void\nextent_node_prof_tctx_set(extent_node_t *node, prof_tctx_t *tctx)\n{\n\n\tnode->en_prof_tctx = tctx;\n}\n\nJEMALLOC_INLINE void\nextent_node_init(extent_node_t *node, arena_t *arena, void *addr, size_t size,\n    bool zeroed, bool committed)\n{\n\n\textent_node_arena_set(node, arena);\n\textent_node_addr_set(node, addr);\n\textent_node_size_set(node, size);\n\textent_node_zeroed_set(node, zeroed);\n\textent_node_committed_set(node, committed);\n\textent_node_achunk_set(node, false);\n\tif (config_prof)\n\t\textent_node_prof_tctx_set(node, NULL);\n}\n\nJEMALLOC_INLINE void\nextent_node_dirty_linkage_init(extent_node_t *node)\n{\n\n\tqr_new(&node->rd, rd_link);\n\tqr_new(node, cc_link);\n}\n\nJEMALLOC_INLINE void\nextent_node_dirty_insert(extent_node_t *node,\n    arena_runs_dirty_link_t *runs_dirty, extent_node_t *chunks_dirty)\n{\n\n\tqr_meld(runs_dirty, &node->rd, rd_link);\n\tqr_meld(chunks_dirty, node, cc_link);\n}\n\nJEMALLOC_INLINE void\nextent_node_dirty_remove(extent_node_t *node)\n{\n\n\tqr_remove(&node->rd, rd_link);\n\tqr_remove(node, cc_link);\n}\n\n#endif\n\n#endif /* JEMALLOC_H_INLINES */\n/******************************************************************************/\n\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.8/deps/jemalloc/include/jemalloc/internal/hash.h",
    "content": "/*\n * The following hash function is based on MurmurHash3, placed into the public\n * domain by Austin Appleby.  See http://code.google.com/p/smhasher/ for\n * details.\n */\n/******************************************************************************/\n#ifdef JEMALLOC_H_TYPES\n\n#endif /* JEMALLOC_H_TYPES */\n/******************************************************************************/\n#ifdef JEMALLOC_H_STRUCTS\n\n#endif /* JEMALLOC_H_STRUCTS */\n/******************************************************************************/\n#ifdef JEMALLOC_H_EXTERNS\n\n#endif /* JEMALLOC_H_EXTERNS */\n/******************************************************************************/\n#ifdef JEMALLOC_H_INLINES\n\n#ifndef JEMALLOC_ENABLE_INLINE\nuint32_t\thash_x86_32(const void *key, int len, uint32_t seed);\nvoid\thash_x86_128(const void *key, const int len, uint32_t seed,\n    uint64_t r_out[2]);\nvoid\thash_x64_128(const void *key, const int len, const uint32_t seed,\n    uint64_t r_out[2]);\nvoid\thash(const void *key, size_t len, const uint32_t seed,\n    size_t r_hash[2]);\n#endif\n\n#if (defined(JEMALLOC_ENABLE_INLINE) || defined(JEMALLOC_HASH_C_))\n/******************************************************************************/\n/* Internal implementation. */\nJEMALLOC_INLINE uint32_t\nhash_rotl_32(uint32_t x, int8_t r)\n{\n\n\treturn ((x << r) | (x >> (32 - r)));\n}\n\nJEMALLOC_INLINE uint64_t\nhash_rotl_64(uint64_t x, int8_t r)\n{\n\n\treturn ((x << r) | (x >> (64 - r)));\n}\n\nJEMALLOC_INLINE uint32_t\nhash_get_block_32(const uint32_t *p, int i)\n{\n\n\treturn (p[i]);\n}\n\nJEMALLOC_INLINE uint64_t\nhash_get_block_64(const uint64_t *p, int i)\n{\n\n\treturn (p[i]);\n}\n\nJEMALLOC_INLINE uint32_t\nhash_fmix_32(uint32_t h)\n{\n\n\th ^= h >> 16;\n\th *= 0x85ebca6b;\n\th ^= h >> 13;\n\th *= 0xc2b2ae35;\n\th ^= h >> 16;\n\n\treturn (h);\n}\n\nJEMALLOC_INLINE uint64_t\nhash_fmix_64(uint64_t k)\n{\n\n\tk ^= k >> 33;\n\tk *= KQU(0xff51afd7ed558ccd);\n\tk ^= k >> 33;\n\tk *= KQU(0xc4ceb9fe1a85ec53);\n\tk ^= k >> 33;\n\n\treturn (k);\n}\n\nJEMALLOC_INLINE uint32_t\nhash_x86_32(const void *key, int len, uint32_t seed)\n{\n\tconst uint8_t *data = (const uint8_t *) key;\n\tconst int nblocks = len / 4;\n\n\tuint32_t h1 = seed;\n\n\tconst uint32_t c1 = 0xcc9e2d51;\n\tconst uint32_t c2 = 0x1b873593;\n\n\t/* body */\n\t{\n\t\tconst uint32_t *blocks = (const uint32_t *) (data + nblocks*4);\n\t\tint i;\n\n\t\tfor (i = -nblocks; i; i++) {\n\t\t\tuint32_t k1 = hash_get_block_32(blocks, i);\n\n\t\t\tk1 *= c1;\n\t\t\tk1 = hash_rotl_32(k1, 15);\n\t\t\tk1 *= c2;\n\n\t\t\th1 ^= k1;\n\t\t\th1 = hash_rotl_32(h1, 13);\n\t\t\th1 = h1*5 + 0xe6546b64;\n\t\t}\n\t}\n\n\t/* tail */\n\t{\n\t\tconst uint8_t *tail = (const uint8_t *) (data + nblocks*4);\n\n\t\tuint32_t k1 = 0;\n\n\t\tswitch (len & 3) {\n\t\tcase 3: k1 ^= tail[2] << 16;\n\t\tcase 2: k1 ^= tail[1] << 8;\n\t\tcase 1: k1 ^= tail[0]; k1 *= c1; k1 = hash_rotl_32(k1, 15);\n\t\t\tk1 *= c2; h1 ^= k1;\n\t\t}\n\t}\n\n\t/* finalization */\n\th1 ^= len;\n\n\th1 = hash_fmix_32(h1);\n\n\treturn (h1);\n}\n\nUNUSED JEMALLOC_INLINE void\nhash_x86_128(const void *key, const int len, uint32_t seed,\n    uint64_t r_out[2])\n{\n\tconst uint8_t * data = (const uint8_t *) key;\n\tconst int nblocks = len / 16;\n\n\tuint32_t h1 = seed;\n\tuint32_t h2 = seed;\n\tuint32_t h3 = seed;\n\tuint32_t h4 = seed;\n\n\tconst uint32_t c1 = 0x239b961b;\n\tconst uint32_t c2 = 0xab0e9789;\n\tconst uint32_t c3 = 0x38b34ae5;\n\tconst uint32_t c4 = 0xa1e38b93;\n\n\t/* body */\n\t{\n\t\tconst uint32_t *blocks = (const uint32_t *) (data + nblocks*16);\n\t\tint i;\n\n\t\tfor (i = -nblocks; i; i++) {\n\t\t\tuint32_t k1 = hash_get_block_32(blocks, i*4 + 0);\n\t\t\tuint32_t k2 = hash_get_block_32(blocks, i*4 + 1);\n\t\t\tuint32_t k3 = hash_get_block_32(blocks, i*4 + 2);\n\t\t\tuint32_t k4 = hash_get_block_32(blocks, i*4 + 3);\n\n\t\t\tk1 *= c1; k1 = hash_rotl_32(k1, 15); k1 *= c2; h1 ^= k1;\n\n\t\t\th1 = hash_rotl_32(h1, 19); h1 += h2;\n\t\t\th1 = h1*5 + 0x561ccd1b;\n\n\t\t\tk2 *= c2; k2 = hash_rotl_32(k2, 16); k2 *= c3; h2 ^= k2;\n\n\t\t\th2 = hash_rotl_32(h2, 17); h2 += h3;\n\t\t\th2 = h2*5 + 0x0bcaa747;\n\n\t\t\tk3 *= c3; k3 = hash_rotl_32(k3, 17); k3 *= c4; h3 ^= k3;\n\n\t\t\th3 = hash_rotl_32(h3, 15); h3 += h4;\n\t\t\th3 = h3*5 + 0x96cd1c35;\n\n\t\t\tk4 *= c4; k4 = hash_rotl_32(k4, 18); k4 *= c1; h4 ^= k4;\n\n\t\t\th4 = hash_rotl_32(h4, 13); h4 += h1;\n\t\t\th4 = h4*5 + 0x32ac3b17;\n\t\t}\n\t}\n\n\t/* tail */\n\t{\n\t\tconst uint8_t *tail = (const uint8_t *) (data + nblocks*16);\n\t\tuint32_t k1 = 0;\n\t\tuint32_t k2 = 0;\n\t\tuint32_t k3 = 0;\n\t\tuint32_t k4 = 0;\n\n\t\tswitch (len & 15) {\n\t\tcase 15: k4 ^= tail[14] << 16;\n\t\tcase 14: k4 ^= tail[13] << 8;\n\t\tcase 13: k4 ^= tail[12] << 0;\n\t\t\tk4 *= c4; k4 = hash_rotl_32(k4, 18); k4 *= c1; h4 ^= k4;\n\n\t\tcase 12: k3 ^= tail[11] << 24;\n\t\tcase 11: k3 ^= tail[10] << 16;\n\t\tcase 10: k3 ^= tail[ 9] << 8;\n\t\tcase  9: k3 ^= tail[ 8] << 0;\n\t\t     k3 *= c3; k3 = hash_rotl_32(k3, 17); k3 *= c4; h3 ^= k3;\n\n\t\tcase  8: k2 ^= tail[ 7] << 24;\n\t\tcase  7: k2 ^= tail[ 6] << 16;\n\t\tcase  6: k2 ^= tail[ 5] << 8;\n\t\tcase  5: k2 ^= tail[ 4] << 0;\n\t\t\tk2 *= c2; k2 = hash_rotl_32(k2, 16); k2 *= c3; h2 ^= k2;\n\n\t\tcase  4: k1 ^= tail[ 3] << 24;\n\t\tcase  3: k1 ^= tail[ 2] << 16;\n\t\tcase  2: k1 ^= tail[ 1] << 8;\n\t\tcase  1: k1 ^= tail[ 0] << 0;\n\t\t\tk1 *= c1; k1 = hash_rotl_32(k1, 15); k1 *= c2; h1 ^= k1;\n\t\t}\n\t}\n\n\t/* finalization */\n\th1 ^= len; h2 ^= len; h3 ^= len; h4 ^= len;\n\n\th1 += h2; h1 += h3; h1 += h4;\n\th2 += h1; h3 += h1; h4 += h1;\n\n\th1 = hash_fmix_32(h1);\n\th2 = hash_fmix_32(h2);\n\th3 = hash_fmix_32(h3);\n\th4 = hash_fmix_32(h4);\n\n\th1 += h2; h1 += h3; h1 += h4;\n\th2 += h1; h3 += h1; h4 += h1;\n\n\tr_out[0] = (((uint64_t) h2) << 32) | h1;\n\tr_out[1] = (((uint64_t) h4) << 32) | h3;\n}\n\nUNUSED JEMALLOC_INLINE void\nhash_x64_128(const void *key, const int len, const uint32_t seed,\n    uint64_t r_out[2])\n{\n\tconst uint8_t *data = (const uint8_t *) key;\n\tconst int nblocks = len / 16;\n\n\tuint64_t h1 = seed;\n\tuint64_t h2 = seed;\n\n\tconst uint64_t c1 = KQU(0x87c37b91114253d5);\n\tconst uint64_t c2 = KQU(0x4cf5ad432745937f);\n\n\t/* body */\n\t{\n\t\tconst uint64_t *blocks = (const uint64_t *) (data);\n\t\tint i;\n\n\t\tfor (i = 0; i < nblocks; i++) {\n\t\t\tuint64_t k1 = hash_get_block_64(blocks, i*2 + 0);\n\t\t\tuint64_t k2 = hash_get_block_64(blocks, i*2 + 1);\n\n\t\t\tk1 *= c1; k1 = hash_rotl_64(k1, 31); k1 *= c2; h1 ^= k1;\n\n\t\t\th1 = hash_rotl_64(h1, 27); h1 += h2;\n\t\t\th1 = h1*5 + 0x52dce729;\n\n\t\t\tk2 *= c2; k2 = hash_rotl_64(k2, 33); k2 *= c1; h2 ^= k2;\n\n\t\t\th2 = hash_rotl_64(h2, 31); h2 += h1;\n\t\t\th2 = h2*5 + 0x38495ab5;\n\t\t}\n\t}\n\n\t/* tail */\n\t{\n\t\tconst uint8_t *tail = (const uint8_t*)(data + nblocks*16);\n\t\tuint64_t k1 = 0;\n\t\tuint64_t k2 = 0;\n\n\t\tswitch (len & 15) {\n\t\tcase 15: k2 ^= ((uint64_t)(tail[14])) << 48;\n\t\tcase 14: k2 ^= ((uint64_t)(tail[13])) << 40;\n\t\tcase 13: k2 ^= ((uint64_t)(tail[12])) << 32;\n\t\tcase 12: k2 ^= ((uint64_t)(tail[11])) << 24;\n\t\tcase 11: k2 ^= ((uint64_t)(tail[10])) << 16;\n\t\tcase 10: k2 ^= ((uint64_t)(tail[ 9])) << 8;\n\t\tcase  9: k2 ^= ((uint64_t)(tail[ 8])) << 0;\n\t\t\tk2 *= c2; k2 = hash_rotl_64(k2, 33); k2 *= c1; h2 ^= k2;\n\n\t\tcase  8: k1 ^= ((uint64_t)(tail[ 7])) << 56;\n\t\tcase  7: k1 ^= ((uint64_t)(tail[ 6])) << 48;\n\t\tcase  6: k1 ^= ((uint64_t)(tail[ 5])) << 40;\n\t\tcase  5: k1 ^= ((uint64_t)(tail[ 4])) << 32;\n\t\tcase  4: k1 ^= ((uint64_t)(tail[ 3])) << 24;\n\t\tcase  3: k1 ^= ((uint64_t)(tail[ 2])) << 16;\n\t\tcase  2: k1 ^= ((uint64_t)(tail[ 1])) << 8;\n\t\tcase  1: k1 ^= ((uint64_t)(tail[ 0])) << 0;\n\t\t\tk1 *= c1; k1 = hash_rotl_64(k1, 31); k1 *= c2; h1 ^= k1;\n\t\t}\n\t}\n\n\t/* finalization */\n\th1 ^= len; h2 ^= len;\n\n\th1 += h2;\n\th2 += h1;\n\n\th1 = hash_fmix_64(h1);\n\th2 = hash_fmix_64(h2);\n\n\th1 += h2;\n\th2 += h1;\n\n\tr_out[0] = h1;\n\tr_out[1] = h2;\n}\n\n/******************************************************************************/\n/* API. */\nJEMALLOC_INLINE void\nhash(const void *key, size_t len, const uint32_t seed, size_t r_hash[2])\n{\n#if (LG_SIZEOF_PTR == 3 && !defined(JEMALLOC_BIG_ENDIAN))\n\thash_x64_128(key, len, seed, (uint64_t *)r_hash);\n#else\n\tuint64_t hashes[2];\n\thash_x86_128(key, len, seed, hashes);\n\tr_hash[0] = (size_t)hashes[0];\n\tr_hash[1] = (size_t)hashes[1];\n#endif\n}\n#endif\n\n#endif /* JEMALLOC_H_INLINES */\n/******************************************************************************/\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.8/deps/jemalloc/include/jemalloc/internal/huge.h",
    "content": "/******************************************************************************/\n#ifdef JEMALLOC_H_TYPES\n\n#endif /* JEMALLOC_H_TYPES */\n/******************************************************************************/\n#ifdef JEMALLOC_H_STRUCTS\n\n#endif /* JEMALLOC_H_STRUCTS */\n/******************************************************************************/\n#ifdef JEMALLOC_H_EXTERNS\n\nvoid\t*huge_malloc(tsd_t *tsd, arena_t *arena, size_t size, bool zero,\n    tcache_t *tcache);\nvoid\t*huge_palloc(tsd_t *tsd, arena_t *arena, size_t size, size_t alignment,\n    bool zero, tcache_t *tcache);\nbool\thuge_ralloc_no_move(void *ptr, size_t oldsize, size_t usize_min,\n    size_t usize_max, bool zero);\nvoid\t*huge_ralloc(tsd_t *tsd, arena_t *arena, void *ptr, size_t oldsize,\n    size_t usize, size_t alignment, bool zero, tcache_t *tcache);\n#ifdef JEMALLOC_JET\ntypedef void (huge_dalloc_junk_t)(void *, size_t);\nextern huge_dalloc_junk_t *huge_dalloc_junk;\n#endif\nvoid\thuge_dalloc(tsd_t *tsd, void *ptr, tcache_t *tcache);\narena_t\t*huge_aalloc(const void *ptr);\nsize_t\thuge_salloc(const void *ptr);\nprof_tctx_t\t*huge_prof_tctx_get(const void *ptr);\nvoid\thuge_prof_tctx_set(const void *ptr, prof_tctx_t *tctx);\nvoid\thuge_prof_tctx_reset(const void *ptr);\n\n#endif /* JEMALLOC_H_EXTERNS */\n/******************************************************************************/\n#ifdef JEMALLOC_H_INLINES\n\n#endif /* JEMALLOC_H_INLINES */\n/******************************************************************************/\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.8/deps/jemalloc/include/jemalloc/internal/jemalloc_internal.h.in",
    "content": "#ifndef JEMALLOC_INTERNAL_H\n#define\tJEMALLOC_INTERNAL_H\n\n#include \"jemalloc_internal_defs.h\"\n#include \"jemalloc/internal/jemalloc_internal_decls.h\"\n\n#ifdef JEMALLOC_UTRACE\n#include <sys/ktrace.h>\n#endif\n\n#define\tJEMALLOC_NO_DEMANGLE\n#ifdef JEMALLOC_JET\n#  define JEMALLOC_N(n) jet_##n\n#  include \"jemalloc/internal/public_namespace.h\"\n#  define JEMALLOC_NO_RENAME\n#  include \"../jemalloc@install_suffix@.h\"\n#  undef JEMALLOC_NO_RENAME\n#else\n#  define JEMALLOC_N(n) @private_namespace@##n\n#  include \"../jemalloc@install_suffix@.h\"\n#endif\n#include \"jemalloc/internal/private_namespace.h\"\n\nstatic const bool config_debug =\n#ifdef JEMALLOC_DEBUG\n    true\n#else\n    false\n#endif\n    ;\nstatic const bool have_dss =\n#ifdef JEMALLOC_DSS\n    true\n#else\n    false\n#endif\n    ;\nstatic const bool config_fill =\n#ifdef JEMALLOC_FILL\n    true\n#else\n    false\n#endif\n    ;\nstatic const bool config_lazy_lock =\n#ifdef JEMALLOC_LAZY_LOCK\n    true\n#else\n    false\n#endif\n    ;\nstatic const bool config_prof =\n#ifdef JEMALLOC_PROF\n    true\n#else\n    false\n#endif\n    ;\nstatic const bool config_prof_libgcc =\n#ifdef JEMALLOC_PROF_LIBGCC\n    true\n#else\n    false\n#endif\n    ;\nstatic const bool config_prof_libunwind =\n#ifdef JEMALLOC_PROF_LIBUNWIND\n    true\n#else\n    false\n#endif\n    ;\nstatic const bool maps_coalesce =\n#ifdef JEMALLOC_MAPS_COALESCE\n    true\n#else\n    false\n#endif\n    ;\nstatic const bool config_munmap =\n#ifdef JEMALLOC_MUNMAP\n    true\n#else\n    false\n#endif\n    ;\nstatic const bool config_stats =\n#ifdef JEMALLOC_STATS\n    true\n#else\n    false\n#endif\n    ;\nstatic const bool config_tcache =\n#ifdef JEMALLOC_TCACHE\n    true\n#else\n    false\n#endif\n    ;\nstatic const bool config_tls =\n#ifdef JEMALLOC_TLS\n    true\n#else\n    false\n#endif\n    ;\nstatic const bool config_utrace =\n#ifdef JEMALLOC_UTRACE\n    true\n#else\n    false\n#endif\n    ;\nstatic const bool config_valgrind =\n#ifdef JEMALLOC_VALGRIND\n    true\n#else\n    false\n#endif\n    ;\nstatic const bool config_xmalloc =\n#ifdef JEMALLOC_XMALLOC\n    true\n#else\n    false\n#endif\n    ;\nstatic const bool config_ivsalloc =\n#ifdef JEMALLOC_IVSALLOC\n    true\n#else\n    false\n#endif\n    ;\nstatic const bool config_cache_oblivious =\n#ifdef JEMALLOC_CACHE_OBLIVIOUS\n    true\n#else\n    false\n#endif\n    ;\n\n#ifdef JEMALLOC_C11ATOMICS\n#include <stdatomic.h>\n#endif\n\n#ifdef JEMALLOC_ATOMIC9\n#include <machine/atomic.h>\n#endif\n\n#if (defined(JEMALLOC_OSATOMIC) || defined(JEMALLOC_OSSPIN))\n#include <libkern/OSAtomic.h>\n#endif\n\n#ifdef JEMALLOC_ZONE\n#include <mach/mach_error.h>\n#include <mach/mach_init.h>\n#include <mach/vm_map.h>\n#include <malloc/malloc.h>\n#endif\n\n#define\tRB_COMPACT\n#include \"jemalloc/internal/rb.h\"\n#include \"jemalloc/internal/qr.h\"\n#include \"jemalloc/internal/ql.h\"\n\n/*\n * jemalloc can conceptually be broken into components (arena, tcache, etc.),\n * but there are circular dependencies that cannot be broken without\n * substantial performance degradation.  In order to reduce the effect on\n * visual code flow, read the header files in multiple passes, with one of the\n * following cpp variables defined during each pass:\n *\n *   JEMALLOC_H_TYPES   : Preprocessor-defined constants and psuedo-opaque data\n *                        types.\n *   JEMALLOC_H_STRUCTS : Data structures.\n *   JEMALLOC_H_EXTERNS : Extern data declarations and function prototypes.\n *   JEMALLOC_H_INLINES : Inline functions.\n */\n/******************************************************************************/\n#define\tJEMALLOC_H_TYPES\n\n#include \"jemalloc/internal/jemalloc_internal_macros.h\"\n\n/* Size class index type. */\ntypedef unsigned szind_t;\n\n/*\n * Flags bits:\n *\n * a: arena\n * t: tcache\n * 0: unused\n * z: zero\n * n: alignment\n *\n * aaaaaaaa aaaatttt tttttttt 0znnnnnn\n */\n#define\tMALLOCX_ARENA_MASK\t((int)~0xfffff)\n#define\tMALLOCX_ARENA_MAX\t0xffe\n#define\tMALLOCX_TCACHE_MASK\t((int)~0xfff000ffU)\n#define\tMALLOCX_TCACHE_MAX\t0xffd\n#define\tMALLOCX_LG_ALIGN_MASK\t((int)0x3f)\n/* Use MALLOCX_ALIGN_GET() if alignment may not be specified in flags. */\n#define\tMALLOCX_ALIGN_GET_SPECIFIED(flags)\t\t\t\t\\\n    (ZU(1) << (flags & MALLOCX_LG_ALIGN_MASK))\n#define\tMALLOCX_ALIGN_GET(flags)\t\t\t\t\t\\\n    (MALLOCX_ALIGN_GET_SPECIFIED(flags) & (SIZE_T_MAX-1))\n#define\tMALLOCX_ZERO_GET(flags)\t\t\t\t\t\t\\\n    ((bool)(flags & MALLOCX_ZERO))\n\n#define\tMALLOCX_TCACHE_GET(flags)\t\t\t\t\t\\\n    (((unsigned)((flags & MALLOCX_TCACHE_MASK) >> 8)) - 2)\n#define\tMALLOCX_ARENA_GET(flags)\t\t\t\t\t\\\n    (((unsigned)(((unsigned)flags) >> 20)) - 1)\n\n/* Smallest size class to support. */\n#define\tTINY_MIN\t\t(1U << LG_TINY_MIN)\n\n/*\n * Minimum allocation alignment is 2^LG_QUANTUM bytes (ignoring tiny size\n * classes).\n */\n#ifndef LG_QUANTUM\n#  if (defined(__i386__) || defined(_M_IX86))\n#    define LG_QUANTUM\t\t4\n#  endif\n#  ifdef __ia64__\n#    define LG_QUANTUM\t\t4\n#  endif\n#  ifdef __alpha__\n#    define LG_QUANTUM\t\t4\n#  endif\n#  if (defined(__sparc64__) || defined(__sparcv9))\n#    define LG_QUANTUM\t\t4\n#  endif\n#  if (defined(__amd64__) || defined(__x86_64__) || defined(_M_X64))\n#    define LG_QUANTUM\t\t4\n#  endif\n#  ifdef __arm__\n#    define LG_QUANTUM\t\t3\n#  endif\n#  ifdef __aarch64__\n#    define LG_QUANTUM\t\t4\n#  endif\n#  ifdef __hppa__\n#    define LG_QUANTUM\t\t4\n#  endif\n#  ifdef __mips__\n#    define LG_QUANTUM\t\t3\n#  endif\n#  ifdef __or1k__\n#    define LG_QUANTUM\t\t3\n#  endif\n#  ifdef __powerpc__\n#    define LG_QUANTUM\t\t4\n#  endif\n#  ifdef __s390__\n#    define LG_QUANTUM\t\t4\n#  endif\n#  ifdef __SH4__\n#    define LG_QUANTUM\t\t4\n#  endif\n#  ifdef __tile__\n#    define LG_QUANTUM\t\t4\n#  endif\n#  ifdef __le32__\n#    define LG_QUANTUM\t\t4\n#  endif\n#  ifndef LG_QUANTUM\n#    error \"Unknown minimum alignment for architecture; specify via \"\n\t \"--with-lg-quantum\"\n#  endif\n#endif\n\n#define\tQUANTUM\t\t\t((size_t)(1U << LG_QUANTUM))\n#define\tQUANTUM_MASK\t\t(QUANTUM - 1)\n\n/* Return the smallest quantum multiple that is >= a. */\n#define\tQUANTUM_CEILING(a)\t\t\t\t\t\t\\\n\t(((a) + QUANTUM_MASK) & ~QUANTUM_MASK)\n\n#define\tLONG\t\t\t((size_t)(1U << LG_SIZEOF_LONG))\n#define\tLONG_MASK\t\t(LONG - 1)\n\n/* Return the smallest long multiple that is >= a. */\n#define\tLONG_CEILING(a)\t\t\t\t\t\t\t\\\n\t(((a) + LONG_MASK) & ~LONG_MASK)\n\n#define\tSIZEOF_PTR\t\t(1U << LG_SIZEOF_PTR)\n#define\tPTR_MASK\t\t(SIZEOF_PTR - 1)\n\n/* Return the smallest (void *) multiple that is >= a. */\n#define\tPTR_CEILING(a)\t\t\t\t\t\t\t\\\n\t(((a) + PTR_MASK) & ~PTR_MASK)\n\n/*\n * Maximum size of L1 cache line.  This is used to avoid cache line aliasing.\n * In addition, this controls the spacing of cacheline-spaced size classes.\n *\n * CACHELINE cannot be based on LG_CACHELINE because __declspec(align()) can\n * only handle raw constants.\n */\n#define\tLG_CACHELINE\t\t6\n#define\tCACHELINE\t\t64\n#define\tCACHELINE_MASK\t\t(CACHELINE - 1)\n\n/* Return the smallest cacheline multiple that is >= s. */\n#define\tCACHELINE_CEILING(s)\t\t\t\t\t\t\\\n\t(((s) + CACHELINE_MASK) & ~CACHELINE_MASK)\n\n/* Page size.  LG_PAGE is determined by the configure script. */\n#ifdef PAGE_MASK\n#  undef PAGE_MASK\n#endif\n#define\tPAGE\t\t((size_t)(1U << LG_PAGE))\n#define\tPAGE_MASK\t((size_t)(PAGE - 1))\n\n/* Return the smallest pagesize multiple that is >= s. */\n#define\tPAGE_CEILING(s)\t\t\t\t\t\t\t\\\n\t(((s) + PAGE_MASK) & ~PAGE_MASK)\n\n/* Return the nearest aligned address at or below a. */\n#define\tALIGNMENT_ADDR2BASE(a, alignment)\t\t\t\t\\\n\t((void *)((uintptr_t)(a) & (-(alignment))))\n\n/* Return the offset between a and the nearest aligned address at or below a. */\n#define\tALIGNMENT_ADDR2OFFSET(a, alignment)\t\t\t\t\\\n\t((size_t)((uintptr_t)(a) & (alignment - 1)))\n\n/* Return the smallest alignment multiple that is >= s. */\n#define\tALIGNMENT_CEILING(s, alignment)\t\t\t\t\t\\\n\t(((s) + (alignment - 1)) & (-(alignment)))\n\n/* Declare a variable-length array. */\n#if __STDC_VERSION__ < 199901L\n#  ifdef _MSC_VER\n#    include <malloc.h>\n#    define alloca _alloca\n#  else\n#    ifdef JEMALLOC_HAS_ALLOCA_H\n#      include <alloca.h>\n#    else\n#      include <stdlib.h>\n#    endif\n#  endif\n#  define VARIABLE_ARRAY(type, name, count) \\\n\ttype *name = alloca(sizeof(type) * (count))\n#else\n#  define VARIABLE_ARRAY(type, name, count) type name[(count)]\n#endif\n\n#include \"jemalloc/internal/valgrind.h\"\n#include \"jemalloc/internal/util.h\"\n#include \"jemalloc/internal/atomic.h\"\n#include \"jemalloc/internal/prng.h\"\n#include \"jemalloc/internal/ckh.h\"\n#include \"jemalloc/internal/size_classes.h\"\n#include \"jemalloc/internal/stats.h\"\n#include \"jemalloc/internal/ctl.h\"\n#include \"jemalloc/internal/mutex.h\"\n#include \"jemalloc/internal/tsd.h\"\n#include \"jemalloc/internal/mb.h\"\n#include \"jemalloc/internal/extent.h\"\n#include \"jemalloc/internal/arena.h\"\n#include \"jemalloc/internal/bitmap.h\"\n#include \"jemalloc/internal/base.h\"\n#include \"jemalloc/internal/rtree.h\"\n#include \"jemalloc/internal/pages.h\"\n#include \"jemalloc/internal/chunk.h\"\n#include \"jemalloc/internal/huge.h\"\n#include \"jemalloc/internal/tcache.h\"\n#include \"jemalloc/internal/hash.h\"\n#include \"jemalloc/internal/quarantine.h\"\n#include \"jemalloc/internal/prof.h\"\n\n#undef JEMALLOC_H_TYPES\n/******************************************************************************/\n#define\tJEMALLOC_H_STRUCTS\n\n#include \"jemalloc/internal/valgrind.h\"\n#include \"jemalloc/internal/util.h\"\n#include \"jemalloc/internal/atomic.h\"\n#include \"jemalloc/internal/prng.h\"\n#include \"jemalloc/internal/ckh.h\"\n#include \"jemalloc/internal/size_classes.h\"\n#include \"jemalloc/internal/stats.h\"\n#include \"jemalloc/internal/ctl.h\"\n#include \"jemalloc/internal/mutex.h\"\n#include \"jemalloc/internal/mb.h\"\n#include \"jemalloc/internal/bitmap.h\"\n#define\tJEMALLOC_ARENA_STRUCTS_A\n#include \"jemalloc/internal/arena.h\"\n#undef JEMALLOC_ARENA_STRUCTS_A\n#include \"jemalloc/internal/extent.h\"\n#define\tJEMALLOC_ARENA_STRUCTS_B\n#include \"jemalloc/internal/arena.h\"\n#undef JEMALLOC_ARENA_STRUCTS_B\n#include \"jemalloc/internal/base.h\"\n#include \"jemalloc/internal/rtree.h\"\n#include \"jemalloc/internal/pages.h\"\n#include \"jemalloc/internal/chunk.h\"\n#include \"jemalloc/internal/huge.h\"\n#include \"jemalloc/internal/tcache.h\"\n#include \"jemalloc/internal/hash.h\"\n#include \"jemalloc/internal/quarantine.h\"\n#include \"jemalloc/internal/prof.h\"\n\n#include \"jemalloc/internal/tsd.h\"\n\n#undef JEMALLOC_H_STRUCTS\n/******************************************************************************/\n#define\tJEMALLOC_H_EXTERNS\n\nextern bool\topt_abort;\nextern const char\t*opt_junk;\nextern bool\topt_junk_alloc;\nextern bool\topt_junk_free;\nextern size_t\topt_quarantine;\nextern bool\topt_redzone;\nextern bool\topt_utrace;\nextern bool\topt_xmalloc;\nextern bool\topt_zero;\nextern size_t\topt_narenas;\n\nextern bool\tin_valgrind;\n\n/* Number of CPUs. */\nextern unsigned\t\tncpus;\n\n/*\n * index2size_tab encodes the same information as could be computed (at\n * unacceptable cost in some code paths) by index2size_compute().\n */\nextern size_t const\tindex2size_tab[NSIZES];\n/*\n * size2index_tab is a compact lookup table that rounds request sizes up to\n * size classes.  In order to reduce cache footprint, the table is compressed,\n * and all accesses are via size2index().\n */\nextern uint8_t const\tsize2index_tab[];\n\narena_t\t*a0get(void);\nvoid\t*a0malloc(size_t size);\nvoid\ta0dalloc(void *ptr);\nvoid\t*bootstrap_malloc(size_t size);\nvoid\t*bootstrap_calloc(size_t num, size_t size);\nvoid\tbootstrap_free(void *ptr);\narena_t\t*arenas_extend(unsigned ind);\narena_t\t*arena_init(unsigned ind);\nunsigned\tnarenas_total_get(void);\narena_t\t*arena_get_hard(tsd_t *tsd, unsigned ind, bool init_if_missing);\narena_t\t*arena_choose_hard(tsd_t *tsd);\nvoid\tarena_migrate(tsd_t *tsd, unsigned oldind, unsigned newind);\nunsigned\tarena_nbound(unsigned ind);\nvoid\tthread_allocated_cleanup(tsd_t *tsd);\nvoid\tthread_deallocated_cleanup(tsd_t *tsd);\nvoid\tarena_cleanup(tsd_t *tsd);\nvoid\tarenas_cache_cleanup(tsd_t *tsd);\nvoid\tnarenas_cache_cleanup(tsd_t *tsd);\nvoid\tarenas_cache_bypass_cleanup(tsd_t *tsd);\nvoid\tjemalloc_prefork(void);\nvoid\tjemalloc_postfork_parent(void);\nvoid\tjemalloc_postfork_child(void);\n\n#include \"jemalloc/internal/valgrind.h\"\n#include \"jemalloc/internal/util.h\"\n#include \"jemalloc/internal/atomic.h\"\n#include \"jemalloc/internal/prng.h\"\n#include \"jemalloc/internal/ckh.h\"\n#include \"jemalloc/internal/size_classes.h\"\n#include \"jemalloc/internal/stats.h\"\n#include \"jemalloc/internal/ctl.h\"\n#include \"jemalloc/internal/mutex.h\"\n#include \"jemalloc/internal/mb.h\"\n#include \"jemalloc/internal/bitmap.h\"\n#include \"jemalloc/internal/extent.h\"\n#include \"jemalloc/internal/arena.h\"\n#include \"jemalloc/internal/base.h\"\n#include \"jemalloc/internal/rtree.h\"\n#include \"jemalloc/internal/pages.h\"\n#include \"jemalloc/internal/chunk.h\"\n#include \"jemalloc/internal/huge.h\"\n#include \"jemalloc/internal/tcache.h\"\n#include \"jemalloc/internal/hash.h\"\n#include \"jemalloc/internal/quarantine.h\"\n#include \"jemalloc/internal/prof.h\"\n#include \"jemalloc/internal/tsd.h\"\n\n#undef JEMALLOC_H_EXTERNS\n/******************************************************************************/\n#define\tJEMALLOC_H_INLINES\n\n#include \"jemalloc/internal/valgrind.h\"\n#include \"jemalloc/internal/util.h\"\n#include \"jemalloc/internal/atomic.h\"\n#include \"jemalloc/internal/prng.h\"\n#include \"jemalloc/internal/ckh.h\"\n#include \"jemalloc/internal/size_classes.h\"\n#include \"jemalloc/internal/stats.h\"\n#include \"jemalloc/internal/ctl.h\"\n#include \"jemalloc/internal/mutex.h\"\n#include \"jemalloc/internal/tsd.h\"\n#include \"jemalloc/internal/mb.h\"\n#include \"jemalloc/internal/extent.h\"\n#include \"jemalloc/internal/base.h\"\n#include \"jemalloc/internal/rtree.h\"\n#include \"jemalloc/internal/pages.h\"\n#include \"jemalloc/internal/chunk.h\"\n#include \"jemalloc/internal/huge.h\"\n\n#ifndef JEMALLOC_ENABLE_INLINE\nszind_t\tsize2index_compute(size_t size);\nszind_t\tsize2index_lookup(size_t size);\nszind_t\tsize2index(size_t size);\nsize_t\tindex2size_compute(szind_t index);\nsize_t\tindex2size_lookup(szind_t index);\nsize_t\tindex2size(szind_t index);\nsize_t\ts2u_compute(size_t size);\nsize_t\ts2u_lookup(size_t size);\nsize_t\ts2u(size_t size);\nsize_t\tsa2u(size_t size, size_t alignment);\narena_t\t*arena_choose(tsd_t *tsd, arena_t *arena);\narena_t\t*arena_get(tsd_t *tsd, unsigned ind, bool init_if_missing,\n    bool refresh_if_missing);\n#endif\n\n#if (defined(JEMALLOC_ENABLE_INLINE) || defined(JEMALLOC_C_))\nJEMALLOC_INLINE szind_t\nsize2index_compute(size_t size)\n{\n\n#if (NTBINS != 0)\n\tif (size <= (ZU(1) << LG_TINY_MAXCLASS)) {\n\t\tsize_t lg_tmin = LG_TINY_MAXCLASS - NTBINS + 1;\n\t\tsize_t lg_ceil = lg_floor(pow2_ceil(size));\n\t\treturn (lg_ceil < lg_tmin ? 0 : lg_ceil - lg_tmin);\n\t}\n#endif\n\t{\n\t\tsize_t x = unlikely(ZI(size) < 0) ? ((size<<1) ?\n\t\t    (ZU(1)<<(LG_SIZEOF_PTR+3)) : ((ZU(1)<<(LG_SIZEOF_PTR+3))-1))\n\t\t    : lg_floor((size<<1)-1);\n\t\tsize_t shift = (x < LG_SIZE_CLASS_GROUP + LG_QUANTUM) ? 0 :\n\t\t    x - (LG_SIZE_CLASS_GROUP + LG_QUANTUM);\n\t\tsize_t grp = shift << LG_SIZE_CLASS_GROUP;\n\n\t\tsize_t lg_delta = (x < LG_SIZE_CLASS_GROUP + LG_QUANTUM + 1)\n\t\t    ? LG_QUANTUM : x - LG_SIZE_CLASS_GROUP - 1;\n\n\t\tsize_t delta_inverse_mask = ZI(-1) << lg_delta;\n\t\tsize_t mod = ((((size-1) & delta_inverse_mask) >> lg_delta)) &\n\t\t    ((ZU(1) << LG_SIZE_CLASS_GROUP) - 1);\n\n\t\tsize_t index = NTBINS + grp + mod;\n\t\treturn (index);\n\t}\n}\n\nJEMALLOC_ALWAYS_INLINE szind_t\nsize2index_lookup(size_t size)\n{\n\n\tassert(size <= LOOKUP_MAXCLASS);\n\t{\n\t\tsize_t ret = ((size_t)(size2index_tab[(size-1) >>\n\t\t    LG_TINY_MIN]));\n\t\tassert(ret == size2index_compute(size));\n\t\treturn (ret);\n\t}\n}\n\nJEMALLOC_ALWAYS_INLINE szind_t\nsize2index(size_t size)\n{\n\n\tassert(size > 0);\n\tif (likely(size <= LOOKUP_MAXCLASS))\n\t\treturn (size2index_lookup(size));\n\treturn (size2index_compute(size));\n}\n\nJEMALLOC_INLINE size_t\nindex2size_compute(szind_t index)\n{\n\n#if (NTBINS > 0)\n\tif (index < NTBINS)\n\t\treturn (ZU(1) << (LG_TINY_MAXCLASS - NTBINS + 1 + index));\n#endif\n\t{\n\t\tsize_t reduced_index = index - NTBINS;\n\t\tsize_t grp = reduced_index >> LG_SIZE_CLASS_GROUP;\n\t\tsize_t mod = reduced_index & ((ZU(1) << LG_SIZE_CLASS_GROUP) -\n\t\t    1);\n\n\t\tsize_t grp_size_mask = ~((!!grp)-1);\n\t\tsize_t grp_size = ((ZU(1) << (LG_QUANTUM +\n\t\t    (LG_SIZE_CLASS_GROUP-1))) << grp) & grp_size_mask;\n\n\t\tsize_t shift = (grp == 0) ? 1 : grp;\n\t\tsize_t lg_delta = shift + (LG_QUANTUM-1);\n\t\tsize_t mod_size = (mod+1) << lg_delta;\n\n\t\tsize_t usize = grp_size + mod_size;\n\t\treturn (usize);\n\t}\n}\n\nJEMALLOC_ALWAYS_INLINE size_t\nindex2size_lookup(szind_t index)\n{\n\tsize_t ret = (size_t)index2size_tab[index];\n\tassert(ret == index2size_compute(index));\n\treturn (ret);\n}\n\nJEMALLOC_ALWAYS_INLINE size_t\nindex2size(szind_t index)\n{\n\n\tassert(index < NSIZES);\n\treturn (index2size_lookup(index));\n}\n\nJEMALLOC_ALWAYS_INLINE size_t\ns2u_compute(size_t size)\n{\n\n#if (NTBINS > 0)\n\tif (size <= (ZU(1) << LG_TINY_MAXCLASS)) {\n\t\tsize_t lg_tmin = LG_TINY_MAXCLASS - NTBINS + 1;\n\t\tsize_t lg_ceil = lg_floor(pow2_ceil(size));\n\t\treturn (lg_ceil < lg_tmin ? (ZU(1) << lg_tmin) :\n\t\t    (ZU(1) << lg_ceil));\n\t}\n#endif\n\t{\n\t\tsize_t x = unlikely(ZI(size) < 0) ? ((size<<1) ?\n\t\t    (ZU(1)<<(LG_SIZEOF_PTR+3)) : ((ZU(1)<<(LG_SIZEOF_PTR+3))-1))\n\t\t    : lg_floor((size<<1)-1);\n\t\tsize_t lg_delta = (x < LG_SIZE_CLASS_GROUP + LG_QUANTUM + 1)\n\t\t    ?  LG_QUANTUM : x - LG_SIZE_CLASS_GROUP - 1;\n\t\tsize_t delta = ZU(1) << lg_delta;\n\t\tsize_t delta_mask = delta - 1;\n\t\tsize_t usize = (size + delta_mask) & ~delta_mask;\n\t\treturn (usize);\n\t}\n}\n\nJEMALLOC_ALWAYS_INLINE size_t\ns2u_lookup(size_t size)\n{\n\tsize_t ret = index2size_lookup(size2index_lookup(size));\n\n\tassert(ret == s2u_compute(size));\n\treturn (ret);\n}\n\n/*\n * Compute usable size that would result from allocating an object with the\n * specified size.\n */\nJEMALLOC_ALWAYS_INLINE size_t\ns2u(size_t size)\n{\n\n\tassert(size > 0);\n\tif (likely(size <= LOOKUP_MAXCLASS))\n\t\treturn (s2u_lookup(size));\n\treturn (s2u_compute(size));\n}\n\n/*\n * Compute usable size that would result from allocating an object with the\n * specified size and alignment.\n */\nJEMALLOC_ALWAYS_INLINE size_t\nsa2u(size_t size, size_t alignment)\n{\n\tsize_t usize;\n\n\tassert(alignment != 0 && ((alignment - 1) & alignment) == 0);\n\n\t/* Try for a small size class. */\n\tif (size <= SMALL_MAXCLASS && alignment < PAGE) {\n\t\t/*\n\t\t * Round size up to the nearest multiple of alignment.\n\t\t *\n\t\t * This done, we can take advantage of the fact that for each\n\t\t * small size class, every object is aligned at the smallest\n\t\t * power of two that is non-zero in the base two representation\n\t\t * of the size.  For example:\n\t\t *\n\t\t *   Size |   Base 2 | Minimum alignment\n\t\t *   -----+----------+------------------\n\t\t *     96 |  1100000 |  32\n\t\t *    144 | 10100000 |  32\n\t\t *    192 | 11000000 |  64\n\t\t */\n\t\tusize = s2u(ALIGNMENT_CEILING(size, alignment));\n\t\tif (usize < LARGE_MINCLASS)\n\t\t\treturn (usize);\n\t}\n\n\t/* Try for a large size class. */\n\tif (likely(size <= large_maxclass) && likely(alignment < chunksize)) {\n\t\t/*\n\t\t * We can't achieve subpage alignment, so round up alignment\n\t\t * to the minimum that can actually be supported.\n\t\t */\n\t\talignment = PAGE_CEILING(alignment);\n\n\t\t/* Make sure result is a large size class. */\n\t\tusize = (size <= LARGE_MINCLASS) ? LARGE_MINCLASS : s2u(size);\n\n\t\t/*\n\t\t * Calculate the size of the over-size run that arena_palloc()\n\t\t * would need to allocate in order to guarantee the alignment.\n\t\t */\n\t\tif (usize + large_pad + alignment - PAGE <= arena_maxrun)\n\t\t\treturn (usize);\n\t}\n\n\t/* Huge size class.  Beware of size_t overflow. */\n\n\t/*\n\t * We can't achieve subchunk alignment, so round up alignment to the\n\t * minimum that can actually be supported.\n\t */\n\talignment = CHUNK_CEILING(alignment);\n\tif (alignment == 0) {\n\t\t/* size_t overflow. */\n\t\treturn (0);\n\t}\n\n\t/* Make sure result is a huge size class. */\n\tif (size <= chunksize)\n\t\tusize = chunksize;\n\telse {\n\t\tusize = s2u(size);\n\t\tif (usize < size) {\n\t\t\t/* size_t overflow. */\n\t\t\treturn (0);\n\t\t}\n\t}\n\n\t/*\n\t * Calculate the multi-chunk mapping that huge_palloc() would need in\n\t * order to guarantee the alignment.\n\t */\n\tif (usize + alignment - PAGE < usize) {\n\t\t/* size_t overflow. */\n\t\treturn (0);\n\t}\n\treturn (usize);\n}\n\n/* Choose an arena based on a per-thread value. */\nJEMALLOC_INLINE arena_t *\narena_choose(tsd_t *tsd, arena_t *arena)\n{\n\tarena_t *ret;\n\n\tif (arena != NULL)\n\t\treturn (arena);\n\n\tif (unlikely((ret = tsd_arena_get(tsd)) == NULL))\n\t\tret = arena_choose_hard(tsd);\n\n\treturn (ret);\n}\n\nJEMALLOC_INLINE arena_t *\narena_get(tsd_t *tsd, unsigned ind, bool init_if_missing,\n    bool refresh_if_missing)\n{\n\tarena_t *arena;\n\tarena_t **arenas_cache = tsd_arenas_cache_get(tsd);\n\n\t/* init_if_missing requires refresh_if_missing. */\n\tassert(!init_if_missing || refresh_if_missing);\n\n\tif (unlikely(arenas_cache == NULL)) {\n\t\t/* arenas_cache hasn't been initialized yet. */\n\t\treturn (arena_get_hard(tsd, ind, init_if_missing));\n\t}\n\tif (unlikely(ind >= tsd_narenas_cache_get(tsd))) {\n\t\t/*\n\t\t * ind is invalid, cache is old (too small), or arena to be\n\t\t * initialized.\n\t\t */\n\t\treturn (refresh_if_missing ? arena_get_hard(tsd, ind,\n\t\t    init_if_missing) : NULL);\n\t}\n\tarena = arenas_cache[ind];\n\tif (likely(arena != NULL) || !refresh_if_missing)\n\t\treturn (arena);\n\treturn (arena_get_hard(tsd, ind, init_if_missing));\n}\n#endif\n\n#include \"jemalloc/internal/bitmap.h\"\n/*\n * Include portions of arena.h interleaved with tcache.h in order to resolve\n * circular dependencies.\n */\n#define\tJEMALLOC_ARENA_INLINE_A\n#include \"jemalloc/internal/arena.h\"\n#undef JEMALLOC_ARENA_INLINE_A\n#include \"jemalloc/internal/tcache.h\"\n#define\tJEMALLOC_ARENA_INLINE_B\n#include \"jemalloc/internal/arena.h\"\n#undef JEMALLOC_ARENA_INLINE_B\n#include \"jemalloc/internal/hash.h\"\n#include \"jemalloc/internal/quarantine.h\"\n\n#ifndef JEMALLOC_ENABLE_INLINE\narena_t\t*iaalloc(const void *ptr);\nsize_t\tisalloc(const void *ptr, bool demote);\nvoid\t*iallocztm(tsd_t *tsd, size_t size, bool zero, tcache_t *tcache,\n    bool is_metadata, arena_t *arena);\nvoid\t*imalloct(tsd_t *tsd, size_t size, tcache_t *tcache, arena_t *arena);\nvoid\t*imalloc(tsd_t *tsd, size_t size);\nvoid\t*icalloct(tsd_t *tsd, size_t size, tcache_t *tcache, arena_t *arena);\nvoid\t*icalloc(tsd_t *tsd, size_t size);\nvoid\t*ipallocztm(tsd_t *tsd, size_t usize, size_t alignment, bool zero,\n    tcache_t *tcache, bool is_metadata, arena_t *arena);\nvoid\t*ipalloct(tsd_t *tsd, size_t usize, size_t alignment, bool zero,\n    tcache_t *tcache, arena_t *arena);\nvoid\t*ipalloc(tsd_t *tsd, size_t usize, size_t alignment, bool zero);\nsize_t\tivsalloc(const void *ptr, bool demote);\nsize_t\tu2rz(size_t usize);\nsize_t\tp2rz(const void *ptr);\nvoid\tidalloctm(tsd_t *tsd, void *ptr, tcache_t *tcache, bool is_metadata);\nvoid\tidalloct(tsd_t *tsd, void *ptr, tcache_t *tcache);\nvoid\tidalloc(tsd_t *tsd, void *ptr);\nvoid\tiqalloc(tsd_t *tsd, void *ptr, tcache_t *tcache);\nvoid\tisdalloct(tsd_t *tsd, void *ptr, size_t size, tcache_t *tcache);\nvoid\tisqalloc(tsd_t *tsd, void *ptr, size_t size, tcache_t *tcache);\nvoid\t*iralloct_realign(tsd_t *tsd, void *ptr, size_t oldsize, size_t size,\n    size_t extra, size_t alignment, bool zero, tcache_t *tcache,\n    arena_t *arena);\nvoid\t*iralloct(tsd_t *tsd, void *ptr, size_t oldsize, size_t size,\n    size_t alignment, bool zero, tcache_t *tcache, arena_t *arena);\nvoid\t*iralloc(tsd_t *tsd, void *ptr, size_t oldsize, size_t size,\n    size_t alignment, bool zero);\nbool\tixalloc(void *ptr, size_t oldsize, size_t size, size_t extra,\n    size_t alignment, bool zero);\n#endif\n\n#if (defined(JEMALLOC_ENABLE_INLINE) || defined(JEMALLOC_C_))\nJEMALLOC_ALWAYS_INLINE arena_t *\niaalloc(const void *ptr)\n{\n\n\tassert(ptr != NULL);\n\n\treturn (arena_aalloc(ptr));\n}\n\n/*\n * Typical usage:\n *   void *ptr = [...]\n *   size_t sz = isalloc(ptr, config_prof);\n */\nJEMALLOC_ALWAYS_INLINE size_t\nisalloc(const void *ptr, bool demote)\n{\n\n\tassert(ptr != NULL);\n\t/* Demotion only makes sense if config_prof is true. */\n\tassert(config_prof || !demote);\n\n\treturn (arena_salloc(ptr, demote));\n}\n\nJEMALLOC_ALWAYS_INLINE void *\niallocztm(tsd_t *tsd, size_t size, bool zero, tcache_t *tcache, bool is_metadata,\n    arena_t *arena)\n{\n\tvoid *ret;\n\n\tassert(size != 0);\n\n\tret = arena_malloc(tsd, arena, size, zero, tcache);\n\tif (config_stats && is_metadata && likely(ret != NULL)) {\n\t\tarena_metadata_allocated_add(iaalloc(ret), isalloc(ret,\n\t\t    config_prof));\n\t}\n\treturn (ret);\n}\n\nJEMALLOC_ALWAYS_INLINE void *\nimalloct(tsd_t *tsd, size_t size, tcache_t *tcache, arena_t *arena)\n{\n\n\treturn (iallocztm(tsd, size, false, tcache, false, arena));\n}\n\nJEMALLOC_ALWAYS_INLINE void *\nimalloc(tsd_t *tsd, size_t size)\n{\n\n\treturn (iallocztm(tsd, size, false, tcache_get(tsd, true), false, NULL));\n}\n\nJEMALLOC_ALWAYS_INLINE void *\nicalloct(tsd_t *tsd, size_t size, tcache_t *tcache, arena_t *arena)\n{\n\n\treturn (iallocztm(tsd, size, true, tcache, false, arena));\n}\n\nJEMALLOC_ALWAYS_INLINE void *\nicalloc(tsd_t *tsd, size_t size)\n{\n\n\treturn (iallocztm(tsd, size, true, tcache_get(tsd, true), false, NULL));\n}\n\nJEMALLOC_ALWAYS_INLINE void *\nipallocztm(tsd_t *tsd, size_t usize, size_t alignment, bool zero,\n    tcache_t *tcache, bool is_metadata, arena_t *arena)\n{\n\tvoid *ret;\n\n\tassert(usize != 0);\n\tassert(usize == sa2u(usize, alignment));\n\n\tret = arena_palloc(tsd, arena, usize, alignment, zero, tcache);\n\tassert(ALIGNMENT_ADDR2BASE(ret, alignment) == ret);\n\tif (config_stats && is_metadata && likely(ret != NULL)) {\n\t\tarena_metadata_allocated_add(iaalloc(ret), isalloc(ret,\n\t\t    config_prof));\n\t}\n\treturn (ret);\n}\n\nJEMALLOC_ALWAYS_INLINE void *\nipalloct(tsd_t *tsd, size_t usize, size_t alignment, bool zero,\n    tcache_t *tcache, arena_t *arena)\n{\n\n\treturn (ipallocztm(tsd, usize, alignment, zero, tcache, false, arena));\n}\n\nJEMALLOC_ALWAYS_INLINE void *\nipalloc(tsd_t *tsd, size_t usize, size_t alignment, bool zero)\n{\n\n\treturn (ipallocztm(tsd, usize, alignment, zero, tcache_get(tsd,\n\t    NULL), false, NULL));\n}\n\nJEMALLOC_ALWAYS_INLINE size_t\nivsalloc(const void *ptr, bool demote)\n{\n\textent_node_t *node;\n\n\t/* Return 0 if ptr is not within a chunk managed by jemalloc. */\n\tnode = chunk_lookup(ptr, false);\n\tif (node == NULL)\n\t\treturn (0);\n\t/* Only arena chunks should be looked up via interior pointers. */\n\tassert(extent_node_addr_get(node) == ptr ||\n\t    extent_node_achunk_get(node));\n\n\treturn (isalloc(ptr, demote));\n}\n\nJEMALLOC_INLINE size_t\nu2rz(size_t usize)\n{\n\tsize_t ret;\n\n\tif (usize <= SMALL_MAXCLASS) {\n\t\tszind_t binind = size2index(usize);\n\t\tret = arena_bin_info[binind].redzone_size;\n\t} else\n\t\tret = 0;\n\n\treturn (ret);\n}\n\nJEMALLOC_INLINE size_t\np2rz(const void *ptr)\n{\n\tsize_t usize = isalloc(ptr, false);\n\n\treturn (u2rz(usize));\n}\n\nJEMALLOC_ALWAYS_INLINE void\nidalloctm(tsd_t *tsd, void *ptr, tcache_t *tcache, bool is_metadata)\n{\n\n\tassert(ptr != NULL);\n\tif (config_stats && is_metadata) {\n\t\tarena_metadata_allocated_sub(iaalloc(ptr), isalloc(ptr,\n\t\t    config_prof));\n\t}\n\n\tarena_dalloc(tsd, ptr, tcache);\n}\n\nJEMALLOC_ALWAYS_INLINE void\nidalloct(tsd_t *tsd, void *ptr, tcache_t *tcache)\n{\n\n\tidalloctm(tsd, ptr, tcache, false);\n}\n\nJEMALLOC_ALWAYS_INLINE void\nidalloc(tsd_t *tsd, void *ptr)\n{\n\n\tidalloctm(tsd, ptr, tcache_get(tsd, false), false);\n}\n\nJEMALLOC_ALWAYS_INLINE void\niqalloc(tsd_t *tsd, void *ptr, tcache_t *tcache)\n{\n\n\tif (config_fill && unlikely(opt_quarantine))\n\t\tquarantine(tsd, ptr);\n\telse\n\t\tidalloctm(tsd, ptr, tcache, false);\n}\n\nJEMALLOC_ALWAYS_INLINE void\nisdalloct(tsd_t *tsd, void *ptr, size_t size, tcache_t *tcache)\n{\n\n\tarena_sdalloc(tsd, ptr, size, tcache);\n}\n\nJEMALLOC_ALWAYS_INLINE void\nisqalloc(tsd_t *tsd, void *ptr, size_t size, tcache_t *tcache)\n{\n\n\tif (config_fill && unlikely(opt_quarantine))\n\t\tquarantine(tsd, ptr);\n\telse\n\t\tisdalloct(tsd, ptr, size, tcache);\n}\n\nJEMALLOC_ALWAYS_INLINE void *\niralloct_realign(tsd_t *tsd, void *ptr, size_t oldsize, size_t size,\n    size_t extra, size_t alignment, bool zero, tcache_t *tcache, arena_t *arena)\n{\n\tvoid *p;\n\tsize_t usize, copysize;\n\n\tusize = sa2u(size + extra, alignment);\n\tif (usize == 0)\n\t\treturn (NULL);\n\tp = ipalloct(tsd, usize, alignment, zero, tcache, arena);\n\tif (p == NULL) {\n\t\tif (extra == 0)\n\t\t\treturn (NULL);\n\t\t/* Try again, without extra this time. */\n\t\tusize = sa2u(size, alignment);\n\t\tif (usize == 0)\n\t\t\treturn (NULL);\n\t\tp = ipalloct(tsd, usize, alignment, zero, tcache, arena);\n\t\tif (p == NULL)\n\t\t\treturn (NULL);\n\t}\n\t/*\n\t * Copy at most size bytes (not size+extra), since the caller has no\n\t * expectation that the extra bytes will be reliably preserved.\n\t */\n\tcopysize = (size < oldsize) ? size : oldsize;\n\tmemcpy(p, ptr, copysize);\n\tisqalloc(tsd, ptr, oldsize, tcache);\n\treturn (p);\n}\n\nJEMALLOC_ALWAYS_INLINE void *\niralloct(tsd_t *tsd, void *ptr, size_t oldsize, size_t size, size_t alignment,\n    bool zero, tcache_t *tcache, arena_t *arena)\n{\n\n\tassert(ptr != NULL);\n\tassert(size != 0);\n\n\tif (alignment != 0 && ((uintptr_t)ptr & ((uintptr_t)alignment-1))\n\t    != 0) {\n\t\t/*\n\t\t * Existing object alignment is inadequate; allocate new space\n\t\t * and copy.\n\t\t */\n\t\treturn (iralloct_realign(tsd, ptr, oldsize, size, 0, alignment,\n\t\t    zero, tcache, arena));\n\t}\n\n\treturn (arena_ralloc(tsd, arena, ptr, oldsize, size, alignment, zero,\n\t    tcache));\n}\n\nJEMALLOC_ALWAYS_INLINE void *\niralloc(tsd_t *tsd, void *ptr, size_t oldsize, size_t size, size_t alignment,\n    bool zero)\n{\n\n\treturn (iralloct(tsd, ptr, oldsize, size, alignment, zero,\n\t    tcache_get(tsd, true), NULL));\n}\n\nJEMALLOC_ALWAYS_INLINE bool\nixalloc(void *ptr, size_t oldsize, size_t size, size_t extra, size_t alignment,\n    bool zero)\n{\n\n\tassert(ptr != NULL);\n\tassert(size != 0);\n\n\tif (alignment != 0 && ((uintptr_t)ptr & ((uintptr_t)alignment-1))\n\t    != 0) {\n\t\t/* Existing object alignment is inadequate. */\n\t\treturn (true);\n\t}\n\n\treturn (arena_ralloc_no_move(ptr, oldsize, size, extra, zero));\n}\n#endif\n\n#include \"jemalloc/internal/prof.h\"\n\n#undef JEMALLOC_H_INLINES\n/******************************************************************************/\n#endif /* JEMALLOC_INTERNAL_H */\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.8/deps/jemalloc/include/jemalloc/internal/jemalloc_internal_decls.h",
    "content": "#ifndef JEMALLOC_INTERNAL_DECLS_H\n#define\tJEMALLOC_INTERNAL_DECLS_H\n\n#include <math.h>\n#ifdef _WIN32\n#  include <windows.h>\n#  include \"msvc_compat/windows_extra.h\"\n\n#else\n#  include <sys/param.h>\n#  include <sys/mman.h>\n#  if !defined(__pnacl__) && !defined(__native_client__)\n#    include <sys/syscall.h>\n#    if !defined(SYS_write) && defined(__NR_write)\n#      define SYS_write __NR_write\n#    endif\n#    include <sys/uio.h>\n#  endif\n#  include <pthread.h>\n#  include <errno.h>\n#endif\n#include <sys/types.h>\n\n#include <limits.h>\n#ifndef SIZE_T_MAX\n#  define SIZE_T_MAX\tSIZE_MAX\n#endif\n#include <stdarg.h>\n#include <stdbool.h>\n#include <stdio.h>\n#include <stdlib.h>\n#include <stdint.h>\n#include <stddef.h>\n#ifndef offsetof\n#  define offsetof(type, member)\t((size_t)&(((type *)NULL)->member))\n#endif\n#include <string.h>\n#include <strings.h>\n#include <ctype.h>\n#ifdef _MSC_VER\n#  include <io.h>\ntypedef intptr_t ssize_t;\n#  define PATH_MAX 1024\n#  define STDERR_FILENO 2\n#  define __func__ __FUNCTION__\n#  ifdef JEMALLOC_HAS_RESTRICT\n#    define restrict __restrict\n#  endif\n/* Disable warnings about deprecated system functions. */\n#  pragma warning(disable: 4996)\n#if _MSC_VER < 1800\nstatic int\nisblank(int c)\n{\n\n\treturn (c == '\\t' || c == ' ');\n}\n#endif\n#else\n#  include <unistd.h>\n#endif\n#include <fcntl.h>\n\n#endif /* JEMALLOC_INTERNAL_H */\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.8/deps/jemalloc/include/jemalloc/internal/jemalloc_internal_defs.h.in",
    "content": "#ifndef JEMALLOC_INTERNAL_DEFS_H_\n#define\tJEMALLOC_INTERNAL_DEFS_H_\n/*\n * If JEMALLOC_PREFIX is defined via --with-jemalloc-prefix, it will cause all\n * public APIs to be prefixed.  This makes it possible, with some care, to use\n * multiple allocators simultaneously.\n */\n#undef JEMALLOC_PREFIX\n#undef JEMALLOC_CPREFIX\n\n/*\n * JEMALLOC_PRIVATE_NAMESPACE is used as a prefix for all library-private APIs.\n * For shared libraries, symbol visibility mechanisms prevent these symbols\n * from being exported, but for static libraries, naming collisions are a real\n * possibility.\n */\n#undef JEMALLOC_PRIVATE_NAMESPACE\n\n/*\n * Hyper-threaded CPUs may need a special instruction inside spin loops in\n * order to yield to another virtual CPU.\n */\n#undef CPU_SPINWAIT\n\n/* Defined if C11 atomics are available. */\n#undef JEMALLOC_C11ATOMICS\n\n/* Defined if the equivalent of FreeBSD's atomic(9) functions are available. */\n#undef JEMALLOC_ATOMIC9\n\n/*\n * Defined if OSAtomic*() functions are available, as provided by Darwin, and\n * documented in the atomic(3) manual page.\n */\n#undef JEMALLOC_OSATOMIC\n\n/*\n * Defined if __sync_add_and_fetch(uint32_t *, uint32_t) and\n * __sync_sub_and_fetch(uint32_t *, uint32_t) are available, despite\n * __GCC_HAVE_SYNC_COMPARE_AND_SWAP_4 not being defined (which means the\n * functions are defined in libgcc instead of being inlines).\n */\n#undef JE_FORCE_SYNC_COMPARE_AND_SWAP_4\n\n/*\n * Defined if __sync_add_and_fetch(uint64_t *, uint64_t) and\n * __sync_sub_and_fetch(uint64_t *, uint64_t) are available, despite\n * __GCC_HAVE_SYNC_COMPARE_AND_SWAP_8 not being defined (which means the\n * functions are defined in libgcc instead of being inlines).\n */\n#undef JE_FORCE_SYNC_COMPARE_AND_SWAP_8\n\n/*\n * Defined if __builtin_clz() and __builtin_clzl() are available.\n */\n#undef JEMALLOC_HAVE_BUILTIN_CLZ\n\n/*\n * Defined if madvise(2) is available.\n */\n#undef JEMALLOC_HAVE_MADVISE\n\n/*\n * Defined if OSSpin*() functions are available, as provided by Darwin, and\n * documented in the spinlock(3) manual page.\n */\n#undef JEMALLOC_OSSPIN\n\n/*\n * Defined if secure_getenv(3) is available.\n */\n#undef JEMALLOC_HAVE_SECURE_GETENV\n\n/*\n * Defined if issetugid(2) is available.\n */\n#undef JEMALLOC_HAVE_ISSETUGID\n\n/*\n * Defined if _malloc_thread_cleanup() exists.  At least in the case of\n * FreeBSD, pthread_key_create() allocates, which if used during malloc\n * bootstrapping will cause recursion into the pthreads library.  Therefore, if\n * _malloc_thread_cleanup() exists, use it as the basis for thread cleanup in\n * malloc_tsd.\n */\n#undef JEMALLOC_MALLOC_THREAD_CLEANUP\n\n/*\n * Defined if threaded initialization is known to be safe on this platform.\n * Among other things, it must be possible to initialize a mutex without\n * triggering allocation in order for threaded allocation to be safe.\n */\n#undef JEMALLOC_THREADED_INIT\n\n/*\n * Defined if the pthreads implementation defines\n * _pthread_mutex_init_calloc_cb(), in which case the function is used in order\n * to avoid recursive allocation during mutex initialization.\n */\n#undef JEMALLOC_MUTEX_INIT_CB\n\n/* Non-empty if the tls_model attribute is supported. */\n#undef JEMALLOC_TLS_MODEL\n\n/* JEMALLOC_CC_SILENCE enables code that silences unuseful compiler warnings. */\n#undef JEMALLOC_CC_SILENCE\n\n/* JEMALLOC_CODE_COVERAGE enables test code coverage analysis. */\n#undef JEMALLOC_CODE_COVERAGE\n\n/*\n * JEMALLOC_DEBUG enables assertions and other sanity checks, and disables\n * inline functions.\n */\n#undef JEMALLOC_DEBUG\n\n/* JEMALLOC_STATS enables statistics calculation. */\n#undef JEMALLOC_STATS\n\n/* JEMALLOC_PROF enables allocation profiling. */\n#undef JEMALLOC_PROF\n\n/* Use libunwind for profile backtracing if defined. */\n#undef JEMALLOC_PROF_LIBUNWIND\n\n/* Use libgcc for profile backtracing if defined. */\n#undef JEMALLOC_PROF_LIBGCC\n\n/* Use gcc intrinsics for profile backtracing if defined. */\n#undef JEMALLOC_PROF_GCC\n\n/*\n * JEMALLOC_TCACHE enables a thread-specific caching layer for small objects.\n * This makes it possible to allocate/deallocate objects without any locking\n * when the cache is in the steady state.\n */\n#undef JEMALLOC_TCACHE\n\n/*\n * JEMALLOC_DSS enables use of sbrk(2) to allocate chunks from the data storage\n * segment (DSS).\n */\n#undef JEMALLOC_DSS\n\n/* Support memory filling (junk/zero/quarantine/redzone). */\n#undef JEMALLOC_FILL\n\n/* Support utrace(2)-based tracing. */\n#undef JEMALLOC_UTRACE\n\n/* Support Valgrind. */\n#undef JEMALLOC_VALGRIND\n\n/* Support optional abort() on OOM. */\n#undef JEMALLOC_XMALLOC\n\n/* Support lazy locking (avoid locking unless a second thread is launched). */\n#undef JEMALLOC_LAZY_LOCK\n\n/* Minimum size class to support is 2^LG_TINY_MIN bytes. */\n#undef LG_TINY_MIN\n\n/*\n * Minimum allocation alignment is 2^LG_QUANTUM bytes (ignoring tiny size\n * classes).\n */\n#undef LG_QUANTUM\n\n/* One page is 2^LG_PAGE bytes. */\n#undef LG_PAGE\n\n/*\n * If defined, adjacent virtual memory mappings with identical attributes\n * automatically coalesce, and they fragment when changes are made to subranges.\n * This is the normal order of things for mmap()/munmap(), but on Windows\n * VirtualAlloc()/VirtualFree() operations must be precisely matched, i.e.\n * mappings do *not* coalesce/fragment.\n */\n#undef JEMALLOC_MAPS_COALESCE\n\n/*\n * If defined, use munmap() to unmap freed chunks, rather than storing them for\n * later reuse.  This is disabled by default on Linux because common sequences\n * of mmap()/munmap() calls will cause virtual memory map holes.\n */\n#undef JEMALLOC_MUNMAP\n\n/* TLS is used to map arenas and magazine caches to threads. */\n#undef JEMALLOC_TLS\n\n/*\n * ffs()/ffsl() functions to use for bitmapping.  Don't use these directly;\n * instead, use jemalloc_ffs() or jemalloc_ffsl() from util.h.\n */\n#undef JEMALLOC_INTERNAL_FFSL\n#undef JEMALLOC_INTERNAL_FFS\n\n/*\n * JEMALLOC_IVSALLOC enables ivsalloc(), which verifies that pointers reside\n * within jemalloc-owned chunks before dereferencing them.\n */\n#undef JEMALLOC_IVSALLOC\n\n/*\n * If defined, explicitly attempt to more uniformly distribute large allocation\n * pointer alignments across all cache indices.\n */\n#undef JEMALLOC_CACHE_OBLIVIOUS\n\n/*\n * Darwin (OS X) uses zones to work around Mach-O symbol override shortcomings.\n */\n#undef JEMALLOC_ZONE\n#undef JEMALLOC_ZONE_VERSION\n\n/*\n * Methods for purging unused pages differ between operating systems.\n *\n *   madvise(..., MADV_DONTNEED) : On Linux, this immediately discards pages,\n *                                 such that new pages will be demand-zeroed if\n *                                 the address region is later touched.\n *   madvise(..., MADV_FREE) : On FreeBSD and Darwin, this marks pages as being\n *                             unused, such that they will be discarded rather\n *                             than swapped out.\n */\n#undef JEMALLOC_PURGE_MADVISE_DONTNEED\n#undef JEMALLOC_PURGE_MADVISE_FREE\n\n/* Define if operating system has alloca.h header. */\n#undef JEMALLOC_HAS_ALLOCA_H\n\n/* C99 restrict keyword supported. */\n#undef JEMALLOC_HAS_RESTRICT\n\n/* For use by hash code. */\n#undef JEMALLOC_BIG_ENDIAN\n\n/* sizeof(int) == 2^LG_SIZEOF_INT. */\n#undef LG_SIZEOF_INT\n\n/* sizeof(long) == 2^LG_SIZEOF_LONG. */\n#undef LG_SIZEOF_LONG\n\n/* sizeof(intmax_t) == 2^LG_SIZEOF_INTMAX_T. */\n#undef LG_SIZEOF_INTMAX_T\n\n/* glibc malloc hooks (__malloc_hook, __realloc_hook, __free_hook). */\n#undef JEMALLOC_GLIBC_MALLOC_HOOK\n\n/* glibc memalign hook. */\n#undef JEMALLOC_GLIBC_MEMALIGN_HOOK\n\n/* Adaptive mutex support in pthreads. */\n#undef JEMALLOC_HAVE_PTHREAD_MUTEX_ADAPTIVE_NP\n\n/*\n * If defined, jemalloc symbols are not exported (doesn't work when\n * JEMALLOC_PREFIX is not defined).\n */\n#undef JEMALLOC_EXPORT\n\n#endif /* JEMALLOC_INTERNAL_DEFS_H_ */\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.8/deps/jemalloc/include/jemalloc/internal/jemalloc_internal_macros.h",
    "content": "/*\n * JEMALLOC_ALWAYS_INLINE and JEMALLOC_INLINE are used within header files for\n * functions that are static inline functions if inlining is enabled, and\n * single-definition library-private functions if inlining is disabled.\n *\n * JEMALLOC_ALWAYS_INLINE_C and JEMALLOC_INLINE_C are for use in .c files, in\n * which case the denoted functions are always static, regardless of whether\n * inlining is enabled.\n */\n#if defined(JEMALLOC_DEBUG) || defined(JEMALLOC_CODE_COVERAGE)\n   /* Disable inlining to make debugging/profiling easier. */\n#  define JEMALLOC_ALWAYS_INLINE\n#  define JEMALLOC_ALWAYS_INLINE_C static\n#  define JEMALLOC_INLINE\n#  define JEMALLOC_INLINE_C static\n#  define inline\n#else\n#  define JEMALLOC_ENABLE_INLINE\n#  ifdef JEMALLOC_HAVE_ATTR\n#    define JEMALLOC_ALWAYS_INLINE \\\n\t static inline JEMALLOC_ATTR(unused) JEMALLOC_ATTR(always_inline)\n#    define JEMALLOC_ALWAYS_INLINE_C \\\n\t static inline JEMALLOC_ATTR(always_inline)\n#  else\n#    define JEMALLOC_ALWAYS_INLINE static inline\n#    define JEMALLOC_ALWAYS_INLINE_C static inline\n#  endif\n#  define JEMALLOC_INLINE static inline\n#  define JEMALLOC_INLINE_C static inline\n#  ifdef _MSC_VER\n#    define inline _inline\n#  endif\n#endif\n\n#ifdef JEMALLOC_CC_SILENCE\n#  define UNUSED JEMALLOC_ATTR(unused)\n#else\n#  define UNUSED\n#endif\n\n#define\tZU(z)\t((size_t)z)\n#define\tZI(z)\t((ssize_t)z)\n#define\tQU(q)\t((uint64_t)q)\n#define\tQI(q)\t((int64_t)q)\n\n#define\tKZU(z)\tZU(z##ULL)\n#define\tKZI(z)\tZI(z##LL)\n#define\tKQU(q)\tQU(q##ULL)\n#define\tKQI(q)\tQI(q##LL)\n\n#ifndef __DECONST\n#  define\t__DECONST(type, var)\t((type)(uintptr_t)(const void *)(var))\n#endif\n\n#ifndef JEMALLOC_HAS_RESTRICT\n#  define restrict\n#endif\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.8/deps/jemalloc/include/jemalloc/internal/mb.h",
    "content": "/******************************************************************************/\n#ifdef JEMALLOC_H_TYPES\n\n#endif /* JEMALLOC_H_TYPES */\n/******************************************************************************/\n#ifdef JEMALLOC_H_STRUCTS\n\n#endif /* JEMALLOC_H_STRUCTS */\n/******************************************************************************/\n#ifdef JEMALLOC_H_EXTERNS\n\n#endif /* JEMALLOC_H_EXTERNS */\n/******************************************************************************/\n#ifdef JEMALLOC_H_INLINES\n\n#ifndef JEMALLOC_ENABLE_INLINE\nvoid\tmb_write(void);\n#endif\n\n#if (defined(JEMALLOC_ENABLE_INLINE) || defined(JEMALLOC_MB_C_))\n#ifdef __i386__\n/*\n * According to the Intel Architecture Software Developer's Manual, current\n * processors execute instructions in order from the perspective of other\n * processors in a multiprocessor system, but 1) Intel reserves the right to\n * change that, and 2) the compiler's optimizer could re-order instructions if\n * there weren't some form of barrier.  Therefore, even if running on an\n * architecture that does not need memory barriers (everything through at least\n * i686), an \"optimizer barrier\" is necessary.\n */\nJEMALLOC_INLINE void\nmb_write(void)\n{\n\n#  if 0\n\t/* This is a true memory barrier. */\n\tasm volatile (\"pusha;\"\n\t    \"xor  %%eax,%%eax;\"\n\t    \"cpuid;\"\n\t    \"popa;\"\n\t    : /* Outputs. */\n\t    : /* Inputs. */\n\t    : \"memory\" /* Clobbers. */\n\t    );\n#else\n\t/*\n\t * This is hopefully enough to keep the compiler from reordering\n\t * instructions around this one.\n\t */\n\tasm volatile (\"nop;\"\n\t    : /* Outputs. */\n\t    : /* Inputs. */\n\t    : \"memory\" /* Clobbers. */\n\t    );\n#endif\n}\n#elif (defined(__amd64__) || defined(__x86_64__))\nJEMALLOC_INLINE void\nmb_write(void)\n{\n\n\tasm volatile (\"sfence\"\n\t    : /* Outputs. */\n\t    : /* Inputs. */\n\t    : \"memory\" /* Clobbers. */\n\t    );\n}\n#elif defined(__powerpc__)\nJEMALLOC_INLINE void\nmb_write(void)\n{\n\n\tasm volatile (\"eieio\"\n\t    : /* Outputs. */\n\t    : /* Inputs. */\n\t    : \"memory\" /* Clobbers. */\n\t    );\n}\n#elif defined(__sparc64__)\nJEMALLOC_INLINE void\nmb_write(void)\n{\n\n\tasm volatile (\"membar #StoreStore\"\n\t    : /* Outputs. */\n\t    : /* Inputs. */\n\t    : \"memory\" /* Clobbers. */\n\t    );\n}\n#elif defined(__tile__)\nJEMALLOC_INLINE void\nmb_write(void)\n{\n\n\t__sync_synchronize();\n}\n#else\n/*\n * This is much slower than a simple memory barrier, but the semantics of mutex\n * unlock make this work.\n */\nJEMALLOC_INLINE void\nmb_write(void)\n{\n\tmalloc_mutex_t mtx;\n\n\tmalloc_mutex_init(&mtx);\n\tmalloc_mutex_lock(&mtx);\n\tmalloc_mutex_unlock(&mtx);\n}\n#endif\n#endif\n\n#endif /* JEMALLOC_H_INLINES */\n/******************************************************************************/\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.8/deps/jemalloc/include/jemalloc/internal/mutex.h",
    "content": "/******************************************************************************/\n#ifdef JEMALLOC_H_TYPES\n\ntypedef struct malloc_mutex_s malloc_mutex_t;\n\n#ifdef _WIN32\n#  define MALLOC_MUTEX_INITIALIZER\n#elif (defined(JEMALLOC_OSSPIN))\n#  define MALLOC_MUTEX_INITIALIZER {0}\n#elif (defined(JEMALLOC_MUTEX_INIT_CB))\n#  define MALLOC_MUTEX_INITIALIZER {PTHREAD_MUTEX_INITIALIZER, NULL}\n#else\n#  if (defined(JEMALLOC_HAVE_PTHREAD_MUTEX_ADAPTIVE_NP) &&\t\t\\\n       defined(PTHREAD_ADAPTIVE_MUTEX_INITIALIZER_NP))\n#    define MALLOC_MUTEX_TYPE PTHREAD_MUTEX_ADAPTIVE_NP\n#    define MALLOC_MUTEX_INITIALIZER {PTHREAD_ADAPTIVE_MUTEX_INITIALIZER_NP}\n#  else\n#    define MALLOC_MUTEX_TYPE PTHREAD_MUTEX_DEFAULT\n#    define MALLOC_MUTEX_INITIALIZER {PTHREAD_MUTEX_INITIALIZER}\n#  endif\n#endif\n\n#endif /* JEMALLOC_H_TYPES */\n/******************************************************************************/\n#ifdef JEMALLOC_H_STRUCTS\n\nstruct malloc_mutex_s {\n#ifdef _WIN32\n#  if _WIN32_WINNT >= 0x0600\n\tSRWLOCK         \tlock;\n#  else\n\tCRITICAL_SECTION\tlock;\n#  endif\n#elif (defined(JEMALLOC_OSSPIN))\n\tOSSpinLock\t\tlock;\n#elif (defined(JEMALLOC_MUTEX_INIT_CB))\n\tpthread_mutex_t\t\tlock;\n\tmalloc_mutex_t\t\t*postponed_next;\n#else\n\tpthread_mutex_t\t\tlock;\n#endif\n};\n\n#endif /* JEMALLOC_H_STRUCTS */\n/******************************************************************************/\n#ifdef JEMALLOC_H_EXTERNS\n\n#ifdef JEMALLOC_LAZY_LOCK\nextern bool isthreaded;\n#else\n#  undef isthreaded /* Undo private_namespace.h definition. */\n#  define isthreaded true\n#endif\n\nbool\tmalloc_mutex_init(malloc_mutex_t *mutex);\nvoid\tmalloc_mutex_prefork(malloc_mutex_t *mutex);\nvoid\tmalloc_mutex_postfork_parent(malloc_mutex_t *mutex);\nvoid\tmalloc_mutex_postfork_child(malloc_mutex_t *mutex);\nbool\tmutex_boot(void);\n\n#endif /* JEMALLOC_H_EXTERNS */\n/******************************************************************************/\n#ifdef JEMALLOC_H_INLINES\n\n#ifndef JEMALLOC_ENABLE_INLINE\nvoid\tmalloc_mutex_lock(malloc_mutex_t *mutex);\nvoid\tmalloc_mutex_unlock(malloc_mutex_t *mutex);\n#endif\n\n#if (defined(JEMALLOC_ENABLE_INLINE) || defined(JEMALLOC_MUTEX_C_))\nJEMALLOC_INLINE void\nmalloc_mutex_lock(malloc_mutex_t *mutex)\n{\n\n\tif (isthreaded) {\n#ifdef _WIN32\n#  if _WIN32_WINNT >= 0x0600\n\t\tAcquireSRWLockExclusive(&mutex->lock);\n#  else\n\t\tEnterCriticalSection(&mutex->lock);\n#  endif\n#elif (defined(JEMALLOC_OSSPIN))\n\t\tOSSpinLockLock(&mutex->lock);\n#else\n\t\tpthread_mutex_lock(&mutex->lock);\n#endif\n\t}\n}\n\nJEMALLOC_INLINE void\nmalloc_mutex_unlock(malloc_mutex_t *mutex)\n{\n\n\tif (isthreaded) {\n#ifdef _WIN32\n#  if _WIN32_WINNT >= 0x0600\n\t\tReleaseSRWLockExclusive(&mutex->lock);\n#  else\n\t\tLeaveCriticalSection(&mutex->lock);\n#  endif\n#elif (defined(JEMALLOC_OSSPIN))\n\t\tOSSpinLockUnlock(&mutex->lock);\n#else\n\t\tpthread_mutex_unlock(&mutex->lock);\n#endif\n\t}\n}\n#endif\n\n#endif /* JEMALLOC_H_INLINES */\n/******************************************************************************/\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.8/deps/jemalloc/include/jemalloc/internal/pages.h",
    "content": "/******************************************************************************/\n#ifdef JEMALLOC_H_TYPES\n\n#endif /* JEMALLOC_H_TYPES */\n/******************************************************************************/\n#ifdef JEMALLOC_H_STRUCTS\n\n#endif /* JEMALLOC_H_STRUCTS */\n/******************************************************************************/\n#ifdef JEMALLOC_H_EXTERNS\n\nvoid\t*pages_map(void *addr, size_t size);\nvoid\tpages_unmap(void *addr, size_t size);\nvoid\t*pages_trim(void *addr, size_t alloc_size, size_t leadsize,\n    size_t size);\nbool\tpages_commit(void *addr, size_t size);\nbool\tpages_decommit(void *addr, size_t size);\nbool\tpages_purge(void *addr, size_t size);\n\n#endif /* JEMALLOC_H_EXTERNS */\n/******************************************************************************/\n#ifdef JEMALLOC_H_INLINES\n\n#endif /* JEMALLOC_H_INLINES */\n/******************************************************************************/\n\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.8/deps/jemalloc/include/jemalloc/internal/private_namespace.sh",
    "content": "#!/bin/sh\n\nfor symbol in `cat $1` ; do\n  echo \"#define\t${symbol} JEMALLOC_N(${symbol})\"\ndone\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.8/deps/jemalloc/include/jemalloc/internal/private_symbols.txt",
    "content": "a0dalloc\na0get\na0malloc\narena_aalloc\narena_alloc_junk_small\narena_bin_index\narena_bin_info\narena_bitselm_get\narena_boot\narena_choose\narena_choose_hard\narena_chunk_alloc_huge\narena_chunk_cache_maybe_insert\narena_chunk_cache_maybe_remove\narena_chunk_dalloc_huge\narena_chunk_ralloc_huge_expand\narena_chunk_ralloc_huge_shrink\narena_chunk_ralloc_huge_similar\narena_cleanup\narena_dalloc\narena_dalloc_bin\narena_dalloc_bin_junked_locked\narena_dalloc_junk_large\narena_dalloc_junk_small\narena_dalloc_large\narena_dalloc_large_junked_locked\narena_dalloc_small\narena_dss_prec_get\narena_dss_prec_set\narena_get\narena_get_hard\narena_init\narena_lg_dirty_mult_default_get\narena_lg_dirty_mult_default_set\narena_lg_dirty_mult_get\narena_lg_dirty_mult_set\narena_malloc\narena_malloc_large\narena_malloc_small\narena_mapbits_allocated_get\narena_mapbits_binind_get\narena_mapbits_decommitted_get\narena_mapbits_dirty_get\narena_mapbits_get\narena_mapbits_internal_set\narena_mapbits_large_binind_set\narena_mapbits_large_get\narena_mapbits_large_set\narena_mapbits_large_size_get\narena_mapbitsp_get\narena_mapbitsp_read\narena_mapbitsp_write\narena_mapbits_size_decode\narena_mapbits_size_encode\narena_mapbits_small_runind_get\narena_mapbits_small_set\narena_mapbits_unallocated_set\narena_mapbits_unallocated_size_get\narena_mapbits_unallocated_size_set\narena_mapbits_unzeroed_get\narena_maxrun\narena_maybe_purge\narena_metadata_allocated_add\narena_metadata_allocated_get\narena_metadata_allocated_sub\narena_migrate\narena_miscelm_get\narena_miscelm_to_pageind\narena_miscelm_to_rpages\narena_nbound\narena_new\narena_node_alloc\narena_node_dalloc\narena_palloc\narena_postfork_child\narena_postfork_parent\narena_prefork\narena_prof_accum\narena_prof_accum_impl\narena_prof_accum_locked\narena_prof_promoted\narena_prof_tctx_get\narena_prof_tctx_reset\narena_prof_tctx_set\narena_ptr_small_binind_get\narena_purge_all\narena_quarantine_junk_small\narena_ralloc\narena_ralloc_junk_large\narena_ralloc_no_move\narena_rd_to_miscelm\narena_redzone_corruption\narena_run_regind\narena_run_to_miscelm\narena_salloc\narenas_cache_bypass_cleanup\narenas_cache_cleanup\narena_sdalloc\narena_stats_merge\narena_tcache_fill_small\natomic_add_p\natomic_add_u\natomic_add_uint32\natomic_add_uint64\natomic_add_z\natomic_cas_p\natomic_cas_u\natomic_cas_uint32\natomic_cas_uint64\natomic_cas_z\natomic_sub_p\natomic_sub_u\natomic_sub_uint32\natomic_sub_uint64\natomic_sub_z\nbase_alloc\nbase_boot\nbase_postfork_child\nbase_postfork_parent\nbase_prefork\nbase_stats_get\nbitmap_full\nbitmap_get\nbitmap_info_init\nbitmap_info_ngroups\nbitmap_init\nbitmap_set\nbitmap_sfu\nbitmap_size\nbitmap_unset\nbootstrap_calloc\nbootstrap_free\nbootstrap_malloc\nbt_init\nbuferror\nchunk_alloc_base\nchunk_alloc_cache\nchunk_alloc_dss\nchunk_alloc_mmap\nchunk_alloc_wrapper\nchunk_boot\nchunk_dalloc_arena\nchunk_dalloc_cache\nchunk_dalloc_mmap\nchunk_dalloc_wrapper\nchunk_deregister\nchunk_dss_boot\nchunk_dss_postfork_child\nchunk_dss_postfork_parent\nchunk_dss_prec_get\nchunk_dss_prec_set\nchunk_dss_prefork\nchunk_hooks_default\nchunk_hooks_get\nchunk_hooks_set\nchunk_in_dss\nchunk_lookup\nchunk_npages\nchunk_postfork_child\nchunk_postfork_parent\nchunk_prefork\nchunk_purge_arena\nchunk_purge_wrapper\nchunk_register\nchunksize\nchunksize_mask\nchunks_rtree\nckh_count\nckh_delete\nckh_insert\nckh_iter\nckh_new\nckh_pointer_hash\nckh_pointer_keycomp\nckh_remove\nckh_search\nckh_string_hash\nckh_string_keycomp\nctl_boot\nctl_bymib\nctl_byname\nctl_nametomib\nctl_postfork_child\nctl_postfork_parent\nctl_prefork\ndss_prec_names\nextent_node_achunk_get\nextent_node_achunk_set\nextent_node_addr_get\nextent_node_addr_set\nextent_node_arena_get\nextent_node_arena_set\nextent_node_dirty_insert\nextent_node_dirty_linkage_init\nextent_node_dirty_remove\nextent_node_init\nextent_node_prof_tctx_get\nextent_node_prof_tctx_set\nextent_node_size_get\nextent_node_size_set\nextent_node_zeroed_get\nextent_node_zeroed_set\nextent_tree_ad_empty\nextent_tree_ad_first\nextent_tree_ad_insert\nextent_tree_ad_iter\nextent_tree_ad_iter_recurse\nextent_tree_ad_iter_start\nextent_tree_ad_last\nextent_tree_ad_new\nextent_tree_ad_next\nextent_tree_ad_nsearch\nextent_tree_ad_prev\nextent_tree_ad_psearch\nextent_tree_ad_remove\nextent_tree_ad_reverse_iter\nextent_tree_ad_reverse_iter_recurse\nextent_tree_ad_reverse_iter_start\nextent_tree_ad_search\nextent_tree_szad_empty\nextent_tree_szad_first\nextent_tree_szad_insert\nextent_tree_szad_iter\nextent_tree_szad_iter_recurse\nextent_tree_szad_iter_start\nextent_tree_szad_last\nextent_tree_szad_new\nextent_tree_szad_next\nextent_tree_szad_nsearch\nextent_tree_szad_prev\nextent_tree_szad_psearch\nextent_tree_szad_remove\nextent_tree_szad_reverse_iter\nextent_tree_szad_reverse_iter_recurse\nextent_tree_szad_reverse_iter_start\nextent_tree_szad_search\nget_errno\nhash\nhash_fmix_32\nhash_fmix_64\nhash_get_block_32\nhash_get_block_64\nhash_rotl_32\nhash_rotl_64\nhash_x64_128\nhash_x86_128\nhash_x86_32\nhuge_aalloc\nhuge_dalloc\nhuge_dalloc_junk\nhuge_malloc\nhuge_palloc\nhuge_prof_tctx_get\nhuge_prof_tctx_reset\nhuge_prof_tctx_set\nhuge_ralloc\nhuge_ralloc_no_move\nhuge_salloc\niaalloc\niallocztm\nicalloc\nicalloct\nidalloc\nidalloct\nidalloctm\nimalloc\nimalloct\nindex2size\nindex2size_compute\nindex2size_lookup\nindex2size_tab\nin_valgrind\nipalloc\nipalloct\nipallocztm\niqalloc\niralloc\niralloct\niralloct_realign\nisalloc\nisdalloct\nisqalloc\nisthreaded\nivsalloc\nixalloc\njemalloc_postfork_child\njemalloc_postfork_parent\njemalloc_prefork\nlarge_maxclass\nlg_floor\nmalloc_cprintf\nmalloc_mutex_init\nmalloc_mutex_lock\nmalloc_mutex_postfork_child\nmalloc_mutex_postfork_parent\nmalloc_mutex_prefork\nmalloc_mutex_unlock\nmalloc_printf\nmalloc_snprintf\nmalloc_strtoumax\nmalloc_tsd_boot0\nmalloc_tsd_boot1\nmalloc_tsd_cleanup_register\nmalloc_tsd_dalloc\nmalloc_tsd_malloc\nmalloc_tsd_no_cleanup\nmalloc_vcprintf\nmalloc_vsnprintf\nmalloc_write\nmap_bias\nmap_misc_offset\nmb_write\nmutex_boot\nnarenas_cache_cleanup\nnarenas_total_get\nncpus\nnhbins\nopt_abort\nopt_dss\nopt_junk\nopt_junk_alloc\nopt_junk_free\nopt_lg_chunk\nopt_lg_dirty_mult\nopt_lg_prof_interval\nopt_lg_prof_sample\nopt_lg_tcache_max\nopt_narenas\nopt_prof\nopt_prof_accum\nopt_prof_active\nopt_prof_final\nopt_prof_gdump\nopt_prof_leak\nopt_prof_prefix\nopt_prof_thread_active_init\nopt_quarantine\nopt_redzone\nopt_stats_print\nopt_tcache\nopt_utrace\nopt_xmalloc\nopt_zero\np2rz\npages_commit\npages_decommit\npages_map\npages_purge\npages_trim\npages_unmap\npow2_ceil\nprof_active_get\nprof_active_get_unlocked\nprof_active_set\nprof_alloc_prep\nprof_alloc_rollback\nprof_backtrace\nprof_boot0\nprof_boot1\nprof_boot2\nprof_dump_header\nprof_dump_open\nprof_free\nprof_free_sampled_object\nprof_gdump\nprof_gdump_get\nprof_gdump_get_unlocked\nprof_gdump_set\nprof_gdump_val\nprof_idump\nprof_interval\nprof_lookup\nprof_malloc\nprof_malloc_sample_object\nprof_mdump\nprof_postfork_child\nprof_postfork_parent\nprof_prefork\nprof_realloc\nprof_reset\nprof_sample_accum_update\nprof_sample_threshold_update\nprof_tctx_get\nprof_tctx_reset\nprof_tctx_set\nprof_tdata_cleanup\nprof_tdata_get\nprof_tdata_init\nprof_tdata_reinit\nprof_thread_active_get\nprof_thread_active_init_get\nprof_thread_active_init_set\nprof_thread_active_set\nprof_thread_name_get\nprof_thread_name_set\nquarantine\nquarantine_alloc_hook\nquarantine_alloc_hook_work\nquarantine_cleanup\nregister_zone\nrtree_child_read\nrtree_child_read_hard\nrtree_child_tryread\nrtree_delete\nrtree_get\nrtree_new\nrtree_node_valid\nrtree_set\nrtree_start_level\nrtree_subkey\nrtree_subtree_read\nrtree_subtree_read_hard\nrtree_subtree_tryread\nrtree_val_read\nrtree_val_write\ns2u\ns2u_compute\ns2u_lookup\nsa2u\nset_errno\nsize2index\nsize2index_compute\nsize2index_lookup\nsize2index_tab\nstats_cactive\nstats_cactive_add\nstats_cactive_get\nstats_cactive_sub\nstats_print\ntcache_alloc_easy\ntcache_alloc_large\ntcache_alloc_small\ntcache_alloc_small_hard\ntcache_arena_associate\ntcache_arena_dissociate\ntcache_arena_reassociate\ntcache_bin_flush_large\ntcache_bin_flush_small\ntcache_bin_info\ntcache_boot\ntcache_cleanup\ntcache_create\ntcache_dalloc_large\ntcache_dalloc_small\ntcache_enabled_cleanup\ntcache_enabled_get\ntcache_enabled_set\ntcache_event\ntcache_event_hard\ntcache_flush\ntcache_get\ntcache_get_hard\ntcache_maxclass\ntcaches\ntcache_salloc\ntcaches_create\ntcaches_destroy\ntcaches_flush\ntcaches_get\ntcache_stats_merge\nthread_allocated_cleanup\nthread_deallocated_cleanup\ntsd_arena_get\ntsd_arena_set\ntsd_boot\ntsd_boot0\ntsd_boot1\ntsd_booted\ntsd_cleanup\ntsd_cleanup_wrapper\ntsd_fetch\ntsd_get\ntsd_wrapper_get\ntsd_wrapper_set\ntsd_initialized\ntsd_init_check_recursion\ntsd_init_finish\ntsd_init_head\ntsd_nominal\ntsd_quarantine_get\ntsd_quarantine_set\ntsd_set\ntsd_tcache_enabled_get\ntsd_tcache_enabled_set\ntsd_tcache_get\ntsd_tcache_set\ntsd_tls\ntsd_tsd\ntsd_prof_tdata_get\ntsd_prof_tdata_set\ntsd_thread_allocated_get\ntsd_thread_allocated_set\ntsd_thread_deallocated_get\ntsd_thread_deallocated_set\nu2rz\nvalgrind_freelike_block\nvalgrind_make_mem_defined\nvalgrind_make_mem_noaccess\nvalgrind_make_mem_undefined\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.8/deps/jemalloc/include/jemalloc/internal/private_unnamespace.sh",
    "content": "#!/bin/sh\n\nfor symbol in `cat $1` ; do\n  echo \"#undef ${symbol}\"\ndone\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.8/deps/jemalloc/include/jemalloc/internal/prng.h",
    "content": "/******************************************************************************/\n#ifdef JEMALLOC_H_TYPES\n\n/*\n * Simple linear congruential pseudo-random number generator:\n *\n *   prng(y) = (a*x + c) % m\n *\n * where the following constants ensure maximal period:\n *\n *   a == Odd number (relatively prime to 2^n), and (a-1) is a multiple of 4.\n *   c == Odd number (relatively prime to 2^n).\n *   m == 2^32\n *\n * See Knuth's TAOCP 3rd Ed., Vol. 2, pg. 17 for details on these constraints.\n *\n * This choice of m has the disadvantage that the quality of the bits is\n * proportional to bit position.  For example, the lowest bit has a cycle of 2,\n * the next has a cycle of 4, etc.  For this reason, we prefer to use the upper\n * bits.\n *\n * Macro parameters:\n *   uint32_t r          : Result.\n *   unsigned lg_range   : (0..32], number of least significant bits to return.\n *   uint32_t state      : Seed value.\n *   const uint32_t a, c : See above discussion.\n */\n#define\tprng32(r, lg_range, state, a, c) do {\t\t\t\t\\\n\tassert((lg_range) > 0);\t\t\t\t\t\t\\\n\tassert((lg_range) <= 32);\t\t\t\t\t\\\n\t\t\t\t\t\t\t\t\t\\\n\tr = (state * (a)) + (c);\t\t\t\t\t\\\n\tstate = r;\t\t\t\t\t\t\t\\\n\tr >>= (32 - (lg_range));\t\t\t\t\t\\\n} while (false)\n\n/* Same as prng32(), but 64 bits of pseudo-randomness, using uint64_t. */\n#define\tprng64(r, lg_range, state, a, c) do {\t\t\t\t\\\n\tassert((lg_range) > 0);\t\t\t\t\t\t\\\n\tassert((lg_range) <= 64);\t\t\t\t\t\\\n\t\t\t\t\t\t\t\t\t\\\n\tr = (state * (a)) + (c);\t\t\t\t\t\\\n\tstate = r;\t\t\t\t\t\t\t\\\n\tr >>= (64 - (lg_range));\t\t\t\t\t\\\n} while (false)\n\n#endif /* JEMALLOC_H_TYPES */\n/******************************************************************************/\n#ifdef JEMALLOC_H_STRUCTS\n\n#endif /* JEMALLOC_H_STRUCTS */\n/******************************************************************************/\n#ifdef JEMALLOC_H_EXTERNS\n\n#endif /* JEMALLOC_H_EXTERNS */\n/******************************************************************************/\n#ifdef JEMALLOC_H_INLINES\n\n#endif /* JEMALLOC_H_INLINES */\n/******************************************************************************/\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.8/deps/jemalloc/include/jemalloc/internal/prof.h",
    "content": "/******************************************************************************/\n#ifdef JEMALLOC_H_TYPES\n\ntypedef struct prof_bt_s prof_bt_t;\ntypedef struct prof_cnt_s prof_cnt_t;\ntypedef struct prof_tctx_s prof_tctx_t;\ntypedef struct prof_gctx_s prof_gctx_t;\ntypedef struct prof_tdata_s prof_tdata_t;\n\n/* Option defaults. */\n#ifdef JEMALLOC_PROF\n#  define PROF_PREFIX_DEFAULT\t\t\"jeprof\"\n#else\n#  define PROF_PREFIX_DEFAULT\t\t\"\"\n#endif\n#define\tLG_PROF_SAMPLE_DEFAULT\t\t19\n#define\tLG_PROF_INTERVAL_DEFAULT\t-1\n\n/*\n * Hard limit on stack backtrace depth.  The version of prof_backtrace() that\n * is based on __builtin_return_address() necessarily has a hard-coded number\n * of backtrace frame handlers, and should be kept in sync with this setting.\n */\n#define\tPROF_BT_MAX\t\t\t128\n\n/* Initial hash table size. */\n#define\tPROF_CKH_MINITEMS\t\t64\n\n/* Size of memory buffer to use when writing dump files. */\n#define\tPROF_DUMP_BUFSIZE\t\t65536\n\n/* Size of stack-allocated buffer used by prof_printf(). */\n#define\tPROF_PRINTF_BUFSIZE\t\t128\n\n/*\n * Number of mutexes shared among all gctx's.  No space is allocated for these\n * unless profiling is enabled, so it's okay to over-provision.\n */\n#define\tPROF_NCTX_LOCKS\t\t\t1024\n\n/*\n * Number of mutexes shared among all tdata's.  No space is allocated for these\n * unless profiling is enabled, so it's okay to over-provision.\n */\n#define\tPROF_NTDATA_LOCKS\t\t256\n\n/*\n * prof_tdata pointers close to NULL are used to encode state information that\n * is used for cleaning up during thread shutdown.\n */\n#define\tPROF_TDATA_STATE_REINCARNATED\t((prof_tdata_t *)(uintptr_t)1)\n#define\tPROF_TDATA_STATE_PURGATORY\t((prof_tdata_t *)(uintptr_t)2)\n#define\tPROF_TDATA_STATE_MAX\t\tPROF_TDATA_STATE_PURGATORY\n\n#endif /* JEMALLOC_H_TYPES */\n/******************************************************************************/\n#ifdef JEMALLOC_H_STRUCTS\n\nstruct prof_bt_s {\n\t/* Backtrace, stored as len program counters. */\n\tvoid\t\t**vec;\n\tunsigned\tlen;\n};\n\n#ifdef JEMALLOC_PROF_LIBGCC\n/* Data structure passed to libgcc _Unwind_Backtrace() callback functions. */\ntypedef struct {\n\tprof_bt_t\t*bt;\n\tunsigned\tmax;\n} prof_unwind_data_t;\n#endif\n\nstruct prof_cnt_s {\n\t/* Profiling counters. */\n\tuint64_t\tcurobjs;\n\tuint64_t\tcurbytes;\n\tuint64_t\taccumobjs;\n\tuint64_t\taccumbytes;\n};\n\ntypedef enum {\n\tprof_tctx_state_initializing,\n\tprof_tctx_state_nominal,\n\tprof_tctx_state_dumping,\n\tprof_tctx_state_purgatory /* Dumper must finish destroying. */\n} prof_tctx_state_t;\n\nstruct prof_tctx_s {\n\t/* Thread data for thread that performed the allocation. */\n\tprof_tdata_t\t\t*tdata;\n\n\t/*\n\t * Copy of tdata->thr_{uid,discrim}, necessary because tdata may be\n\t * defunct during teardown.\n\t */\n\tuint64_t\t\tthr_uid;\n\tuint64_t\t\tthr_discrim;\n\n\t/* Profiling counters, protected by tdata->lock. */\n\tprof_cnt_t\t\tcnts;\n\n\t/* Associated global context. */\n\tprof_gctx_t\t\t*gctx;\n\n\t/*\n\t * UID that distinguishes multiple tctx's created by the same thread,\n\t * but coexisting in gctx->tctxs.  There are two ways that such\n\t * coexistence can occur:\n\t * - A dumper thread can cause a tctx to be retained in the purgatory\n\t *   state.\n\t * - Although a single \"producer\" thread must create all tctx's which\n\t *   share the same thr_uid, multiple \"consumers\" can each concurrently\n\t *   execute portions of prof_tctx_destroy().  prof_tctx_destroy() only\n\t *   gets called once each time cnts.cur{objs,bytes} drop to 0, but this\n\t *   threshold can be hit again before the first consumer finishes\n\t *   executing prof_tctx_destroy().\n\t */\n\tuint64_t\t\ttctx_uid;\n\n\t/* Linkage into gctx's tctxs. */\n\trb_node(prof_tctx_t)\ttctx_link;\n\n\t/*\n\t * True during prof_alloc_prep()..prof_malloc_sample_object(), prevents\n\t * sample vs destroy race.\n\t */\n\tbool\t\t\tprepared;\n\n\t/* Current dump-related state, protected by gctx->lock. */\n\tprof_tctx_state_t\tstate;\n\n\t/*\n\t * Copy of cnts snapshotted during early dump phase, protected by\n\t * dump_mtx.\n\t */\n\tprof_cnt_t\t\tdump_cnts;\n};\ntypedef rb_tree(prof_tctx_t) prof_tctx_tree_t;\n\nstruct prof_gctx_s {\n\t/* Protects nlimbo, cnt_summed, and tctxs. */\n\tmalloc_mutex_t\t\t*lock;\n\n\t/*\n\t * Number of threads that currently cause this gctx to be in a state of\n\t * limbo due to one of:\n\t *   - Initializing this gctx.\n\t *   - Initializing per thread counters associated with this gctx.\n\t *   - Preparing to destroy this gctx.\n\t *   - Dumping a heap profile that includes this gctx.\n\t * nlimbo must be 1 (single destroyer) in order to safely destroy the\n\t * gctx.\n\t */\n\tunsigned\t\tnlimbo;\n\n\t/*\n\t * Tree of profile counters, one for each thread that has allocated in\n\t * this context.\n\t */\n\tprof_tctx_tree_t\ttctxs;\n\n\t/* Linkage for tree of contexts to be dumped. */\n\trb_node(prof_gctx_t)\tdump_link;\n\n\t/* Temporary storage for summation during dump. */\n\tprof_cnt_t\t\tcnt_summed;\n\n\t/* Associated backtrace. */\n\tprof_bt_t\t\tbt;\n\n\t/* Backtrace vector, variable size, referred to by bt. */\n\tvoid\t\t\t*vec[1];\n};\ntypedef rb_tree(prof_gctx_t) prof_gctx_tree_t;\n\nstruct prof_tdata_s {\n\tmalloc_mutex_t\t\t*lock;\n\n\t/* Monotonically increasing unique thread identifier. */\n\tuint64_t\t\tthr_uid;\n\n\t/*\n\t * Monotonically increasing discriminator among tdata structures\n\t * associated with the same thr_uid.\n\t */\n\tuint64_t\t\tthr_discrim;\n\n\t/* Included in heap profile dumps if non-NULL. */\n\tchar\t\t\t*thread_name;\n\n\tbool\t\t\tattached;\n\tbool\t\t\texpired;\n\n\trb_node(prof_tdata_t)\ttdata_link;\n\n\t/*\n\t * Counter used to initialize prof_tctx_t's tctx_uid.  No locking is\n\t * necessary when incrementing this field, because only one thread ever\n\t * does so.\n\t */\n\tuint64_t\t\ttctx_uid_next;\n\n\t/*\n\t * Hash of (prof_bt_t *)-->(prof_tctx_t *).  Each thread tracks\n\t * backtraces for which it has non-zero allocation/deallocation counters\n\t * associated with thread-specific prof_tctx_t objects.  Other threads\n\t * may write to prof_tctx_t contents when freeing associated objects.\n\t */\n\tckh_t\t\t\tbt2tctx;\n\n\t/* Sampling state. */\n\tuint64_t\t\tprng_state;\n\tuint64_t\t\tbytes_until_sample;\n\n\t/* State used to avoid dumping while operating on prof internals. */\n\tbool\t\t\tenq;\n\tbool\t\t\tenq_idump;\n\tbool\t\t\tenq_gdump;\n\n\t/*\n\t * Set to true during an early dump phase for tdata's which are\n\t * currently being dumped.  New threads' tdata's have this initialized\n\t * to false so that they aren't accidentally included in later dump\n\t * phases.\n\t */\n\tbool\t\t\tdumping;\n\n\t/*\n\t * True if profiling is active for this tdata's thread\n\t * (thread.prof.active mallctl).\n\t */\n\tbool\t\t\tactive;\n\n\t/* Temporary storage for summation during dump. */\n\tprof_cnt_t\t\tcnt_summed;\n\n\t/* Backtrace vector, used for calls to prof_backtrace(). */\n\tvoid\t\t\t*vec[PROF_BT_MAX];\n};\ntypedef rb_tree(prof_tdata_t) prof_tdata_tree_t;\n\n#endif /* JEMALLOC_H_STRUCTS */\n/******************************************************************************/\n#ifdef JEMALLOC_H_EXTERNS\n\nextern bool\topt_prof;\nextern bool\topt_prof_active;\nextern bool\topt_prof_thread_active_init;\nextern size_t\topt_lg_prof_sample;   /* Mean bytes between samples. */\nextern ssize_t\topt_lg_prof_interval; /* lg(prof_interval). */\nextern bool\topt_prof_gdump;       /* High-water memory dumping. */\nextern bool\topt_prof_final;       /* Final profile dumping. */\nextern bool\topt_prof_leak;        /* Dump leak summary at exit. */\nextern bool\topt_prof_accum;       /* Report cumulative bytes. */\nextern char\topt_prof_prefix[\n    /* Minimize memory bloat for non-prof builds. */\n#ifdef JEMALLOC_PROF\n    PATH_MAX +\n#endif\n    1];\n\n/* Accessed via prof_active_[gs]et{_unlocked,}(). */\nextern bool\tprof_active;\n\n/* Accessed via prof_gdump_[gs]et{_unlocked,}(). */\nextern bool\tprof_gdump_val;\n\n/*\n * Profile dump interval, measured in bytes allocated.  Each arena triggers a\n * profile dump when it reaches this threshold.  The effect is that the\n * interval between profile dumps averages prof_interval, though the actual\n * interval between dumps will tend to be sporadic, and the interval will be a\n * maximum of approximately (prof_interval * narenas).\n */\nextern uint64_t\tprof_interval;\n\n/*\n * Initialized as opt_lg_prof_sample, and potentially modified during profiling\n * resets.\n */\nextern size_t\tlg_prof_sample;\n\nvoid\tprof_alloc_rollback(tsd_t *tsd, prof_tctx_t *tctx, bool updated);\nvoid\tprof_malloc_sample_object(const void *ptr, size_t usize,\n    prof_tctx_t *tctx);\nvoid\tprof_free_sampled_object(tsd_t *tsd, size_t usize, prof_tctx_t *tctx);\nvoid\tbt_init(prof_bt_t *bt, void **vec);\nvoid\tprof_backtrace(prof_bt_t *bt);\nprof_tctx_t\t*prof_lookup(tsd_t *tsd, prof_bt_t *bt);\n#ifdef JEMALLOC_JET\nsize_t\tprof_tdata_count(void);\nsize_t\tprof_bt_count(void);\nconst prof_cnt_t *prof_cnt_all(void);\ntypedef int (prof_dump_open_t)(bool, const char *);\nextern prof_dump_open_t *prof_dump_open;\ntypedef bool (prof_dump_header_t)(bool, const prof_cnt_t *);\nextern prof_dump_header_t *prof_dump_header;\n#endif\nvoid\tprof_idump(void);\nbool\tprof_mdump(const char *filename);\nvoid\tprof_gdump(void);\nprof_tdata_t\t*prof_tdata_init(tsd_t *tsd);\nprof_tdata_t\t*prof_tdata_reinit(tsd_t *tsd, prof_tdata_t *tdata);\nvoid\tprof_reset(tsd_t *tsd, size_t lg_sample);\nvoid\tprof_tdata_cleanup(tsd_t *tsd);\nconst char\t*prof_thread_name_get(void);\nbool\tprof_active_get(void);\nbool\tprof_active_set(bool active);\nint\tprof_thread_name_set(tsd_t *tsd, const char *thread_name);\nbool\tprof_thread_active_get(void);\nbool\tprof_thread_active_set(bool active);\nbool\tprof_thread_active_init_get(void);\nbool\tprof_thread_active_init_set(bool active_init);\nbool\tprof_gdump_get(void);\nbool\tprof_gdump_set(bool active);\nvoid\tprof_boot0(void);\nvoid\tprof_boot1(void);\nbool\tprof_boot2(void);\nvoid\tprof_prefork(void);\nvoid\tprof_postfork_parent(void);\nvoid\tprof_postfork_child(void);\nvoid\tprof_sample_threshold_update(prof_tdata_t *tdata);\n\n#endif /* JEMALLOC_H_EXTERNS */\n/******************************************************************************/\n#ifdef JEMALLOC_H_INLINES\n\n#ifndef JEMALLOC_ENABLE_INLINE\nbool\tprof_active_get_unlocked(void);\nbool\tprof_gdump_get_unlocked(void);\nprof_tdata_t\t*prof_tdata_get(tsd_t *tsd, bool create);\nbool\tprof_sample_accum_update(tsd_t *tsd, size_t usize, bool commit,\n    prof_tdata_t **tdata_out);\nprof_tctx_t\t*prof_alloc_prep(tsd_t *tsd, size_t usize, bool prof_active,\n    bool update);\nprof_tctx_t\t*prof_tctx_get(const void *ptr);\nvoid\tprof_tctx_set(const void *ptr, size_t usize, prof_tctx_t *tctx);\nvoid\tprof_tctx_reset(const void *ptr, size_t usize, const void *old_ptr,\n    prof_tctx_t *tctx);\nvoid\tprof_malloc_sample_object(const void *ptr, size_t usize,\n    prof_tctx_t *tctx);\nvoid\tprof_malloc(const void *ptr, size_t usize, prof_tctx_t *tctx);\nvoid\tprof_realloc(tsd_t *tsd, const void *ptr, size_t usize,\n    prof_tctx_t *tctx, bool prof_active, bool updated, const void *old_ptr,\n    size_t old_usize, prof_tctx_t *old_tctx);\nvoid\tprof_free(tsd_t *tsd, const void *ptr, size_t usize);\n#endif\n\n#if (defined(JEMALLOC_ENABLE_INLINE) || defined(JEMALLOC_PROF_C_))\nJEMALLOC_ALWAYS_INLINE bool\nprof_active_get_unlocked(void)\n{\n\n\t/*\n\t * Even if opt_prof is true, sampling can be temporarily disabled by\n\t * setting prof_active to false.  No locking is used when reading\n\t * prof_active in the fast path, so there are no guarantees regarding\n\t * how long it will take for all threads to notice state changes.\n\t */\n\treturn (prof_active);\n}\n\nJEMALLOC_ALWAYS_INLINE bool\nprof_gdump_get_unlocked(void)\n{\n\n\t/*\n\t * No locking is used when reading prof_gdump_val in the fast path, so\n\t * there are no guarantees regarding how long it will take for all\n\t * threads to notice state changes.\n\t */\n\treturn (prof_gdump_val);\n}\n\nJEMALLOC_ALWAYS_INLINE prof_tdata_t *\nprof_tdata_get(tsd_t *tsd, bool create)\n{\n\tprof_tdata_t *tdata;\n\n\tcassert(config_prof);\n\n\ttdata = tsd_prof_tdata_get(tsd);\n\tif (create) {\n\t\tif (unlikely(tdata == NULL)) {\n\t\t\tif (tsd_nominal(tsd)) {\n\t\t\t\ttdata = prof_tdata_init(tsd);\n\t\t\t\ttsd_prof_tdata_set(tsd, tdata);\n\t\t\t}\n\t\t} else if (unlikely(tdata->expired)) {\n\t\t\ttdata = prof_tdata_reinit(tsd, tdata);\n\t\t\ttsd_prof_tdata_set(tsd, tdata);\n\t\t}\n\t\tassert(tdata == NULL || tdata->attached);\n\t}\n\n\treturn (tdata);\n}\n\nJEMALLOC_ALWAYS_INLINE prof_tctx_t *\nprof_tctx_get(const void *ptr)\n{\n\n\tcassert(config_prof);\n\tassert(ptr != NULL);\n\n\treturn (arena_prof_tctx_get(ptr));\n}\n\nJEMALLOC_ALWAYS_INLINE void\nprof_tctx_set(const void *ptr, size_t usize, prof_tctx_t *tctx)\n{\n\n\tcassert(config_prof);\n\tassert(ptr != NULL);\n\n\tarena_prof_tctx_set(ptr, usize, tctx);\n}\n\nJEMALLOC_ALWAYS_INLINE void\nprof_tctx_reset(const void *ptr, size_t usize, const void *old_ptr,\n    prof_tctx_t *old_tctx)\n{\n\n\tcassert(config_prof);\n\tassert(ptr != NULL);\n\n\tarena_prof_tctx_reset(ptr, usize, old_ptr, old_tctx);\n}\n\nJEMALLOC_ALWAYS_INLINE bool\nprof_sample_accum_update(tsd_t *tsd, size_t usize, bool update,\n    prof_tdata_t **tdata_out)\n{\n\tprof_tdata_t *tdata;\n\n\tcassert(config_prof);\n\n\ttdata = prof_tdata_get(tsd, true);\n\tif ((uintptr_t)tdata <= (uintptr_t)PROF_TDATA_STATE_MAX)\n\t\ttdata = NULL;\n\n\tif (tdata_out != NULL)\n\t\t*tdata_out = tdata;\n\n\tif (tdata == NULL)\n\t\treturn (true);\n\n\tif (tdata->bytes_until_sample >= usize) {\n\t\tif (update)\n\t\t\ttdata->bytes_until_sample -= usize;\n\t\treturn (true);\n\t} else {\n\t\t/* Compute new sample threshold. */\n\t\tif (update)\n\t\t\tprof_sample_threshold_update(tdata);\n\t\treturn (!tdata->active);\n\t}\n}\n\nJEMALLOC_ALWAYS_INLINE prof_tctx_t *\nprof_alloc_prep(tsd_t *tsd, size_t usize, bool prof_active, bool update)\n{\n\tprof_tctx_t *ret;\n\tprof_tdata_t *tdata;\n\tprof_bt_t bt;\n\n\tassert(usize == s2u(usize));\n\n\tif (!prof_active || likely(prof_sample_accum_update(tsd, usize, update,\n\t    &tdata)))\n\t\tret = (prof_tctx_t *)(uintptr_t)1U;\n\telse {\n\t\tbt_init(&bt, tdata->vec);\n\t\tprof_backtrace(&bt);\n\t\tret = prof_lookup(tsd, &bt);\n\t}\n\n\treturn (ret);\n}\n\nJEMALLOC_ALWAYS_INLINE void\nprof_malloc(const void *ptr, size_t usize, prof_tctx_t *tctx)\n{\n\n\tcassert(config_prof);\n\tassert(ptr != NULL);\n\tassert(usize == isalloc(ptr, true));\n\n\tif (unlikely((uintptr_t)tctx > (uintptr_t)1U))\n\t\tprof_malloc_sample_object(ptr, usize, tctx);\n\telse\n\t\tprof_tctx_set(ptr, usize, (prof_tctx_t *)(uintptr_t)1U);\n}\n\nJEMALLOC_ALWAYS_INLINE void\nprof_realloc(tsd_t *tsd, const void *ptr, size_t usize, prof_tctx_t *tctx,\n    bool prof_active, bool updated, const void *old_ptr, size_t old_usize,\n    prof_tctx_t *old_tctx)\n{\n\tbool sampled, old_sampled;\n\n\tcassert(config_prof);\n\tassert(ptr != NULL || (uintptr_t)tctx <= (uintptr_t)1U);\n\n\tif (prof_active && !updated && ptr != NULL) {\n\t\tassert(usize == isalloc(ptr, true));\n\t\tif (prof_sample_accum_update(tsd, usize, true, NULL)) {\n\t\t\t/*\n\t\t\t * Don't sample.  The usize passed to prof_alloc_prep()\n\t\t\t * was larger than what actually got allocated, so a\n\t\t\t * backtrace was captured for this allocation, even\n\t\t\t * though its actual usize was insufficient to cross the\n\t\t\t * sample threshold.\n\t\t\t */\n\t\t\ttctx = (prof_tctx_t *)(uintptr_t)1U;\n\t\t}\n\t}\n\n\tsampled = ((uintptr_t)tctx > (uintptr_t)1U);\n\told_sampled = ((uintptr_t)old_tctx > (uintptr_t)1U);\n\n\tif (unlikely(sampled))\n\t\tprof_malloc_sample_object(ptr, usize, tctx);\n\telse\n\t\tprof_tctx_reset(ptr, usize, old_ptr, old_tctx);\n\n\tif (unlikely(old_sampled))\n\t\tprof_free_sampled_object(tsd, old_usize, old_tctx);\n}\n\nJEMALLOC_ALWAYS_INLINE void\nprof_free(tsd_t *tsd, const void *ptr, size_t usize)\n{\n\tprof_tctx_t *tctx = prof_tctx_get(ptr);\n\n\tcassert(config_prof);\n\tassert(usize == isalloc(ptr, true));\n\n\tif (unlikely((uintptr_t)tctx > (uintptr_t)1U))\n\t\tprof_free_sampled_object(tsd, usize, tctx);\n}\n#endif\n\n#endif /* JEMALLOC_H_INLINES */\n/******************************************************************************/\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.8/deps/jemalloc/include/jemalloc/internal/public_namespace.sh",
    "content": "#!/bin/sh\n\nfor nm in `cat $1` ; do\n  n=`echo ${nm} |tr ':' ' ' |awk '{print $1}'`\n  echo \"#define\tje_${n} JEMALLOC_N(${n})\"\ndone\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.8/deps/jemalloc/include/jemalloc/internal/public_unnamespace.sh",
    "content": "#!/bin/sh\n\nfor nm in `cat $1` ; do\n  n=`echo ${nm} |tr ':' ' ' |awk '{print $1}'`\n  echo \"#undef je_${n}\"\ndone\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.8/deps/jemalloc/include/jemalloc/internal/ql.h",
    "content": "/* List definitions. */\n#define\tql_head(a_type)\t\t\t\t\t\t\t\\\nstruct {\t\t\t\t\t\t\t\t\\\n\ta_type *qlh_first;\t\t\t\t\t\t\\\n}\n\n#define\tql_head_initializer(a_head) {NULL}\n\n#define\tql_elm(a_type)\tqr(a_type)\n\n/* List functions. */\n#define\tql_new(a_head) do {\t\t\t\t\t\t\\\n\t(a_head)->qlh_first = NULL;\t\t\t\t\t\\\n} while (0)\n\n#define\tql_elm_new(a_elm, a_field) qr_new((a_elm), a_field)\n\n#define\tql_first(a_head) ((a_head)->qlh_first)\n\n#define\tql_last(a_head, a_field)\t\t\t\t\t\\\n\t((ql_first(a_head) != NULL)\t\t\t\t\t\\\n\t    ? qr_prev(ql_first(a_head), a_field) : NULL)\n\n#define\tql_next(a_head, a_elm, a_field)\t\t\t\t\t\\\n\t((ql_last(a_head, a_field) != (a_elm))\t\t\t\t\\\n\t    ? qr_next((a_elm), a_field)\t: NULL)\n\n#define\tql_prev(a_head, a_elm, a_field)\t\t\t\t\t\\\n\t((ql_first(a_head) != (a_elm)) ? qr_prev((a_elm), a_field)\t\\\n\t\t\t\t       : NULL)\n\n#define\tql_before_insert(a_head, a_qlelm, a_elm, a_field) do {\t\t\\\n\tqr_before_insert((a_qlelm), (a_elm), a_field);\t\t\t\\\n\tif (ql_first(a_head) == (a_qlelm)) {\t\t\t\t\\\n\t\tql_first(a_head) = (a_elm);\t\t\t\t\\\n\t}\t\t\t\t\t\t\t\t\\\n} while (0)\n\n#define\tql_after_insert(a_qlelm, a_elm, a_field)\t\t\t\\\n\tqr_after_insert((a_qlelm), (a_elm), a_field)\n\n#define\tql_head_insert(a_head, a_elm, a_field) do {\t\t\t\\\n\tif (ql_first(a_head) != NULL) {\t\t\t\t\t\\\n\t\tqr_before_insert(ql_first(a_head), (a_elm), a_field);\t\\\n\t}\t\t\t\t\t\t\t\t\\\n\tql_first(a_head) = (a_elm);\t\t\t\t\t\\\n} while (0)\n\n#define\tql_tail_insert(a_head, a_elm, a_field) do {\t\t\t\\\n\tif (ql_first(a_head) != NULL) {\t\t\t\t\t\\\n\t\tqr_before_insert(ql_first(a_head), (a_elm), a_field);\t\\\n\t}\t\t\t\t\t\t\t\t\\\n\tql_first(a_head) = qr_next((a_elm), a_field);\t\t\t\\\n} while (0)\n\n#define\tql_remove(a_head, a_elm, a_field) do {\t\t\t\t\\\n\tif (ql_first(a_head) == (a_elm)) {\t\t\t\t\\\n\t\tql_first(a_head) = qr_next(ql_first(a_head), a_field);\t\\\n\t}\t\t\t\t\t\t\t\t\\\n\tif (ql_first(a_head) != (a_elm)) {\t\t\t\t\\\n\t\tqr_remove((a_elm), a_field);\t\t\t\t\\\n\t} else {\t\t\t\t\t\t\t\\\n\t\tql_first(a_head) = NULL;\t\t\t\t\\\n\t}\t\t\t\t\t\t\t\t\\\n} while (0)\n\n#define\tql_head_remove(a_head, a_type, a_field) do {\t\t\t\\\n\ta_type *t = ql_first(a_head);\t\t\t\t\t\\\n\tql_remove((a_head), t, a_field);\t\t\t\t\\\n} while (0)\n\n#define\tql_tail_remove(a_head, a_type, a_field) do {\t\t\t\\\n\ta_type *t = ql_last(a_head, a_field);\t\t\t\t\\\n\tql_remove((a_head), t, a_field);\t\t\t\t\\\n} while (0)\n\n#define\tql_foreach(a_var, a_head, a_field)\t\t\t\t\\\n\tqr_foreach((a_var), ql_first(a_head), a_field)\n\n#define\tql_reverse_foreach(a_var, a_head, a_field)\t\t\t\\\n\tqr_reverse_foreach((a_var), ql_first(a_head), a_field)\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.8/deps/jemalloc/include/jemalloc/internal/qr.h",
    "content": "/* Ring definitions. */\n#define\tqr(a_type)\t\t\t\t\t\t\t\\\nstruct {\t\t\t\t\t\t\t\t\\\n\ta_type\t*qre_next;\t\t\t\t\t\t\\\n\ta_type\t*qre_prev;\t\t\t\t\t\t\\\n}\n\n/* Ring functions. */\n#define\tqr_new(a_qr, a_field) do {\t\t\t\t\t\\\n\t(a_qr)->a_field.qre_next = (a_qr);\t\t\t\t\\\n\t(a_qr)->a_field.qre_prev = (a_qr);\t\t\t\t\\\n} while (0)\n\n#define\tqr_next(a_qr, a_field) ((a_qr)->a_field.qre_next)\n\n#define\tqr_prev(a_qr, a_field) ((a_qr)->a_field.qre_prev)\n\n#define\tqr_before_insert(a_qrelm, a_qr, a_field) do {\t\t\t\\\n\t(a_qr)->a_field.qre_prev = (a_qrelm)->a_field.qre_prev;\t\t\\\n\t(a_qr)->a_field.qre_next = (a_qrelm);\t\t\t\t\\\n\t(a_qr)->a_field.qre_prev->a_field.qre_next = (a_qr);\t\t\\\n\t(a_qrelm)->a_field.qre_prev = (a_qr);\t\t\t\t\\\n} while (0)\n\n#define\tqr_after_insert(a_qrelm, a_qr, a_field)\t\t\t\t\\\n    do\t\t\t\t\t\t\t\t\t\\\n    {\t\t\t\t\t\t\t\t\t\\\n\t(a_qr)->a_field.qre_next = (a_qrelm)->a_field.qre_next;\t\t\\\n\t(a_qr)->a_field.qre_prev = (a_qrelm);\t\t\t\t\\\n\t(a_qr)->a_field.qre_next->a_field.qre_prev = (a_qr);\t\t\\\n\t(a_qrelm)->a_field.qre_next = (a_qr);\t\t\t\t\\\n    } while (0)\n\n#define\tqr_meld(a_qr_a, a_qr_b, a_field) do {\t\t\t\t\\\n\tvoid *t;\t\t\t\t\t\t\t\\\n\t(a_qr_a)->a_field.qre_prev->a_field.qre_next = (a_qr_b);\t\\\n\t(a_qr_b)->a_field.qre_prev->a_field.qre_next = (a_qr_a);\t\\\n\tt = (a_qr_a)->a_field.qre_prev;\t\t\t\t\t\\\n\t(a_qr_a)->a_field.qre_prev = (a_qr_b)->a_field.qre_prev;\t\\\n\t(a_qr_b)->a_field.qre_prev = t;\t\t\t\t\t\\\n} while (0)\n\n/*\n * qr_meld() and qr_split() are functionally equivalent, so there's no need to\n * have two copies of the code.\n */\n#define\tqr_split(a_qr_a, a_qr_b, a_field)\t\t\t\t\\\n\tqr_meld((a_qr_a), (a_qr_b), a_field)\n\n#define\tqr_remove(a_qr, a_field) do {\t\t\t\t\t\\\n\t(a_qr)->a_field.qre_prev->a_field.qre_next\t\t\t\\\n\t    = (a_qr)->a_field.qre_next;\t\t\t\t\t\\\n\t(a_qr)->a_field.qre_next->a_field.qre_prev\t\t\t\\\n\t    = (a_qr)->a_field.qre_prev;\t\t\t\t\t\\\n\t(a_qr)->a_field.qre_next = (a_qr);\t\t\t\t\\\n\t(a_qr)->a_field.qre_prev = (a_qr);\t\t\t\t\\\n} while (0)\n\n#define\tqr_foreach(var, a_qr, a_field)\t\t\t\t\t\\\n\tfor ((var) = (a_qr);\t\t\t\t\t\t\\\n\t    (var) != NULL;\t\t\t\t\t\t\\\n\t    (var) = (((var)->a_field.qre_next != (a_qr))\t\t\\\n\t    ? (var)->a_field.qre_next : NULL))\n\n#define\tqr_reverse_foreach(var, a_qr, a_field)\t\t\t\t\\\n\tfor ((var) = ((a_qr) != NULL) ? qr_prev(a_qr, a_field) : NULL;\t\\\n\t    (var) != NULL;\t\t\t\t\t\t\\\n\t    (var) = (((var) != (a_qr))\t\t\t\t\t\\\n\t    ? (var)->a_field.qre_prev : NULL))\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.8/deps/jemalloc/include/jemalloc/internal/quarantine.h",
    "content": "/******************************************************************************/\n#ifdef JEMALLOC_H_TYPES\n\ntypedef struct quarantine_obj_s quarantine_obj_t;\ntypedef struct quarantine_s quarantine_t;\n\n/* Default per thread quarantine size if valgrind is enabled. */\n#define\tJEMALLOC_VALGRIND_QUARANTINE_DEFAULT\t(ZU(1) << 24)\n\n#endif /* JEMALLOC_H_TYPES */\n/******************************************************************************/\n#ifdef JEMALLOC_H_STRUCTS\n\nstruct quarantine_obj_s {\n\tvoid\t*ptr;\n\tsize_t\tusize;\n};\n\nstruct quarantine_s {\n\tsize_t\t\t\tcurbytes;\n\tsize_t\t\t\tcurobjs;\n\tsize_t\t\t\tfirst;\n#define\tLG_MAXOBJS_INIT 10\n\tsize_t\t\t\tlg_maxobjs;\n\tquarantine_obj_t\tobjs[1]; /* Dynamically sized ring buffer. */\n};\n\n#endif /* JEMALLOC_H_STRUCTS */\n/******************************************************************************/\n#ifdef JEMALLOC_H_EXTERNS\n\nvoid\tquarantine_alloc_hook_work(tsd_t *tsd);\nvoid\tquarantine(tsd_t *tsd, void *ptr);\nvoid\tquarantine_cleanup(tsd_t *tsd);\n\n#endif /* JEMALLOC_H_EXTERNS */\n/******************************************************************************/\n#ifdef JEMALLOC_H_INLINES\n\n#ifndef JEMALLOC_ENABLE_INLINE\nvoid\tquarantine_alloc_hook(void);\n#endif\n\n#if (defined(JEMALLOC_ENABLE_INLINE) || defined(JEMALLOC_QUARANTINE_C_))\nJEMALLOC_ALWAYS_INLINE void\nquarantine_alloc_hook(void)\n{\n\ttsd_t *tsd;\n\n\tassert(config_fill && opt_quarantine);\n\n\ttsd = tsd_fetch();\n\tif (tsd_quarantine_get(tsd) == NULL)\n\t\tquarantine_alloc_hook_work(tsd);\n}\n#endif\n\n#endif /* JEMALLOC_H_INLINES */\n/******************************************************************************/\n\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.8/deps/jemalloc/include/jemalloc/internal/rb.h",
    "content": "/*-\n *******************************************************************************\n *\n * cpp macro implementation of left-leaning 2-3 red-black trees.  Parent\n * pointers are not used, and color bits are stored in the least significant\n * bit of right-child pointers (if RB_COMPACT is defined), thus making node\n * linkage as compact as is possible for red-black trees.\n *\n * Usage:\n *\n *   #include <stdint.h>\n *   #include <stdbool.h>\n *   #define NDEBUG // (Optional, see assert(3).)\n *   #include <assert.h>\n *   #define RB_COMPACT // (Optional, embed color bits in right-child pointers.)\n *   #include <rb.h>\n *   ...\n *\n *******************************************************************************\n */\n\n#ifndef RB_H_\n#define\tRB_H_\n\n#ifdef RB_COMPACT\n/* Node structure. */\n#define\trb_node(a_type)\t\t\t\t\t\t\t\\\nstruct {\t\t\t\t\t\t\t\t\\\n    a_type *rbn_left;\t\t\t\t\t\t\t\\\n    a_type *rbn_right_red;\t\t\t\t\t\t\\\n}\n#else\n#define\trb_node(a_type)\t\t\t\t\t\t\t\\\nstruct {\t\t\t\t\t\t\t\t\\\n    a_type *rbn_left;\t\t\t\t\t\t\t\\\n    a_type *rbn_right;\t\t\t\t\t\t\t\\\n    bool rbn_red;\t\t\t\t\t\t\t\\\n}\n#endif\n\n/* Root structure. */\n#define\trb_tree(a_type)\t\t\t\t\t\t\t\\\nstruct {\t\t\t\t\t\t\t\t\\\n    a_type *rbt_root;\t\t\t\t\t\t\t\\\n    a_type rbt_nil;\t\t\t\t\t\t\t\\\n}\n\n/* Left accessors. */\n#define\trbtn_left_get(a_type, a_field, a_node)\t\t\t\t\\\n    ((a_node)->a_field.rbn_left)\n#define\trbtn_left_set(a_type, a_field, a_node, a_left) do {\t\t\\\n    (a_node)->a_field.rbn_left = a_left;\t\t\t\t\\\n} while (0)\n\n#ifdef RB_COMPACT\n/* Right accessors. */\n#define\trbtn_right_get(a_type, a_field, a_node)\t\t\t\t\\\n    ((a_type *) (((intptr_t) (a_node)->a_field.rbn_right_red)\t\t\\\n      & ((ssize_t)-2)))\n#define\trbtn_right_set(a_type, a_field, a_node, a_right) do {\t\t\\\n    (a_node)->a_field.rbn_right_red = (a_type *) (((uintptr_t) a_right)\t\\\n      | (((uintptr_t) (a_node)->a_field.rbn_right_red) & ((size_t)1)));\t\\\n} while (0)\n\n/* Color accessors. */\n#define\trbtn_red_get(a_type, a_field, a_node)\t\t\t\t\\\n    ((bool) (((uintptr_t) (a_node)->a_field.rbn_right_red)\t\t\\\n      & ((size_t)1)))\n#define\trbtn_color_set(a_type, a_field, a_node, a_red) do {\t\t\\\n    (a_node)->a_field.rbn_right_red = (a_type *) ((((intptr_t)\t\t\\\n      (a_node)->a_field.rbn_right_red) & ((ssize_t)-2))\t\t\t\\\n      | ((ssize_t)a_red));\t\t\t\t\t\t\\\n} while (0)\n#define\trbtn_red_set(a_type, a_field, a_node) do {\t\t\t\\\n    (a_node)->a_field.rbn_right_red = (a_type *) (((uintptr_t)\t\t\\\n      (a_node)->a_field.rbn_right_red) | ((size_t)1));\t\t\t\\\n} while (0)\n#define\trbtn_black_set(a_type, a_field, a_node) do {\t\t\t\\\n    (a_node)->a_field.rbn_right_red = (a_type *) (((intptr_t)\t\t\\\n      (a_node)->a_field.rbn_right_red) & ((ssize_t)-2));\t\t\\\n} while (0)\n#else\n/* Right accessors. */\n#define\trbtn_right_get(a_type, a_field, a_node)\t\t\t\t\\\n    ((a_node)->a_field.rbn_right)\n#define\trbtn_right_set(a_type, a_field, a_node, a_right) do {\t\t\\\n    (a_node)->a_field.rbn_right = a_right;\t\t\t\t\\\n} while (0)\n\n/* Color accessors. */\n#define\trbtn_red_get(a_type, a_field, a_node)\t\t\t\t\\\n    ((a_node)->a_field.rbn_red)\n#define\trbtn_color_set(a_type, a_field, a_node, a_red) do {\t\t\\\n    (a_node)->a_field.rbn_red = (a_red);\t\t\t\t\\\n} while (0)\n#define\trbtn_red_set(a_type, a_field, a_node) do {\t\t\t\\\n    (a_node)->a_field.rbn_red = true;\t\t\t\t\t\\\n} while (0)\n#define\trbtn_black_set(a_type, a_field, a_node) do {\t\t\t\\\n    (a_node)->a_field.rbn_red = false;\t\t\t\t\t\\\n} while (0)\n#endif\n\n/* Node initializer. */\n#define\trbt_node_new(a_type, a_field, a_rbt, a_node) do {\t\t\\\n    rbtn_left_set(a_type, a_field, (a_node), &(a_rbt)->rbt_nil);\t\\\n    rbtn_right_set(a_type, a_field, (a_node), &(a_rbt)->rbt_nil);\t\\\n    rbtn_red_set(a_type, a_field, (a_node));\t\t\t\t\\\n} while (0)\n\n/* Tree initializer. */\n#define\trb_new(a_type, a_field, a_rbt) do {\t\t\t\t\\\n    (a_rbt)->rbt_root = &(a_rbt)->rbt_nil;\t\t\t\t\\\n    rbt_node_new(a_type, a_field, a_rbt, &(a_rbt)->rbt_nil);\t\t\\\n    rbtn_black_set(a_type, a_field, &(a_rbt)->rbt_nil);\t\t\t\\\n} while (0)\n\n/* Internal utility macros. */\n#define\trbtn_first(a_type, a_field, a_rbt, a_root, r_node) do {\t\t\\\n    (r_node) = (a_root);\t\t\t\t\t\t\\\n    if ((r_node) != &(a_rbt)->rbt_nil) {\t\t\t\t\\\n\tfor (;\t\t\t\t\t\t\t\t\\\n\t  rbtn_left_get(a_type, a_field, (r_node)) != &(a_rbt)->rbt_nil;\\\n\t  (r_node) = rbtn_left_get(a_type, a_field, (r_node))) {\t\\\n\t}\t\t\t\t\t\t\t\t\\\n    }\t\t\t\t\t\t\t\t\t\\\n} while (0)\n\n#define\trbtn_last(a_type, a_field, a_rbt, a_root, r_node) do {\t\t\\\n    (r_node) = (a_root);\t\t\t\t\t\t\\\n    if ((r_node) != &(a_rbt)->rbt_nil) {\t\t\t\t\\\n\tfor (; rbtn_right_get(a_type, a_field, (r_node)) !=\t\t\\\n\t  &(a_rbt)->rbt_nil; (r_node) = rbtn_right_get(a_type, a_field,\t\\\n\t  (r_node))) {\t\t\t\t\t\t\t\\\n\t}\t\t\t\t\t\t\t\t\\\n    }\t\t\t\t\t\t\t\t\t\\\n} while (0)\n\n#define\trbtn_rotate_left(a_type, a_field, a_node, r_node) do {\t\t\\\n    (r_node) = rbtn_right_get(a_type, a_field, (a_node));\t\t\\\n    rbtn_right_set(a_type, a_field, (a_node),\t\t\t\t\\\n      rbtn_left_get(a_type, a_field, (r_node)));\t\t\t\\\n    rbtn_left_set(a_type, a_field, (r_node), (a_node));\t\t\t\\\n} while (0)\n\n#define\trbtn_rotate_right(a_type, a_field, a_node, r_node) do {\t\t\\\n    (r_node) = rbtn_left_get(a_type, a_field, (a_node));\t\t\\\n    rbtn_left_set(a_type, a_field, (a_node),\t\t\t\t\\\n      rbtn_right_get(a_type, a_field, (r_node)));\t\t\t\\\n    rbtn_right_set(a_type, a_field, (r_node), (a_node));\t\t\\\n} while (0)\n\n/*\n * The rb_proto() macro generates function prototypes that correspond to the\n * functions generated by an equivalently parameterized call to rb_gen().\n */\n\n#define\trb_proto(a_attr, a_prefix, a_rbt_type, a_type)\t\t\t\\\na_attr void\t\t\t\t\t\t\t\t\\\na_prefix##new(a_rbt_type *rbtree);\t\t\t\t\t\\\na_attr bool\t\t\t\t\t\t\t\t\\\na_prefix##empty(a_rbt_type *rbtree);\t\t\t\t\t\\\na_attr a_type *\t\t\t\t\t\t\t\t\\\na_prefix##first(a_rbt_type *rbtree);\t\t\t\t\t\\\na_attr a_type *\t\t\t\t\t\t\t\t\\\na_prefix##last(a_rbt_type *rbtree);\t\t\t\t\t\\\na_attr a_type *\t\t\t\t\t\t\t\t\\\na_prefix##next(a_rbt_type *rbtree, a_type *node);\t\t\t\\\na_attr a_type *\t\t\t\t\t\t\t\t\\\na_prefix##prev(a_rbt_type *rbtree, a_type *node);\t\t\t\\\na_attr a_type *\t\t\t\t\t\t\t\t\\\na_prefix##search(a_rbt_type *rbtree, a_type *key);\t\t\t\\\na_attr a_type *\t\t\t\t\t\t\t\t\\\na_prefix##nsearch(a_rbt_type *rbtree, a_type *key);\t\t\t\\\na_attr a_type *\t\t\t\t\t\t\t\t\\\na_prefix##psearch(a_rbt_type *rbtree, a_type *key);\t\t\t\\\na_attr void\t\t\t\t\t\t\t\t\\\na_prefix##insert(a_rbt_type *rbtree, a_type *node);\t\t\t\\\na_attr void\t\t\t\t\t\t\t\t\\\na_prefix##remove(a_rbt_type *rbtree, a_type *node);\t\t\t\\\na_attr a_type *\t\t\t\t\t\t\t\t\\\na_prefix##iter(a_rbt_type *rbtree, a_type *start, a_type *(*cb)(\t\\\n  a_rbt_type *, a_type *, void *), void *arg);\t\t\t\t\\\na_attr a_type *\t\t\t\t\t\t\t\t\\\na_prefix##reverse_iter(a_rbt_type *rbtree, a_type *start,\t\t\\\n  a_type *(*cb)(a_rbt_type *, a_type *, void *), void *arg);\n\n/*\n * The rb_gen() macro generates a type-specific red-black tree implementation,\n * based on the above cpp macros.\n *\n * Arguments:\n *\n *   a_attr    : Function attribute for generated functions (ex: static).\n *   a_prefix  : Prefix for generated functions (ex: ex_).\n *   a_rb_type : Type for red-black tree data structure (ex: ex_t).\n *   a_type    : Type for red-black tree node data structure (ex: ex_node_t).\n *   a_field   : Name of red-black tree node linkage (ex: ex_link).\n *   a_cmp     : Node comparison function name, with the following prototype:\n *                 int (a_cmp *)(a_type *a_node, a_type *a_other);\n *                                       ^^^^^^\n *                                    or a_key\n *               Interpretation of comparison function return values:\n *                 -1 : a_node <  a_other\n *                  0 : a_node == a_other\n *                  1 : a_node >  a_other\n *               In all cases, the a_node or a_key macro argument is the first\n *               argument to the comparison function, which makes it possible\n *               to write comparison functions that treat the first argument\n *               specially.\n *\n * Assuming the following setup:\n *\n *   typedef struct ex_node_s ex_node_t;\n *   struct ex_node_s {\n *       rb_node(ex_node_t) ex_link;\n *   };\n *   typedef rb_tree(ex_node_t) ex_t;\n *   rb_gen(static, ex_, ex_t, ex_node_t, ex_link, ex_cmp)\n *\n * The following API is generated:\n *\n *   static void\n *   ex_new(ex_t *tree);\n *       Description: Initialize a red-black tree structure.\n *       Args:\n *         tree: Pointer to an uninitialized red-black tree object.\n *\n *   static bool\n *   ex_empty(ex_t *tree);\n *       Description: Determine whether tree is empty.\n *       Args:\n *         tree: Pointer to an initialized red-black tree object.\n *       Ret: True if tree is empty, false otherwise.\n *\n *   static ex_node_t *\n *   ex_first(ex_t *tree);\n *   static ex_node_t *\n *   ex_last(ex_t *tree);\n *       Description: Get the first/last node in tree.\n *       Args:\n *         tree: Pointer to an initialized red-black tree object.\n *       Ret: First/last node in tree, or NULL if tree is empty.\n *\n *   static ex_node_t *\n *   ex_next(ex_t *tree, ex_node_t *node);\n *   static ex_node_t *\n *   ex_prev(ex_t *tree, ex_node_t *node);\n *       Description: Get node's successor/predecessor.\n *       Args:\n *         tree: Pointer to an initialized red-black tree object.\n *         node: A node in tree.\n *       Ret: node's successor/predecessor in tree, or NULL if node is\n *            last/first.\n *\n *   static ex_node_t *\n *   ex_search(ex_t *tree, ex_node_t *key);\n *       Description: Search for node that matches key.\n *       Args:\n *         tree: Pointer to an initialized red-black tree object.\n *         key : Search key.\n *       Ret: Node in tree that matches key, or NULL if no match.\n *\n *   static ex_node_t *\n *   ex_nsearch(ex_t *tree, ex_node_t *key);\n *   static ex_node_t *\n *   ex_psearch(ex_t *tree, ex_node_t *key);\n *       Description: Search for node that matches key.  If no match is found,\n *                    return what would be key's successor/predecessor, were\n *                    key in tree.\n *       Args:\n *         tree: Pointer to an initialized red-black tree object.\n *         key : Search key.\n *       Ret: Node in tree that matches key, or if no match, hypothetical node's\n *            successor/predecessor (NULL if no successor/predecessor).\n *\n *   static void\n *   ex_insert(ex_t *tree, ex_node_t *node);\n *       Description: Insert node into tree.\n *       Args:\n *         tree: Pointer to an initialized red-black tree object.\n *         node: Node to be inserted into tree.\n *\n *   static void\n *   ex_remove(ex_t *tree, ex_node_t *node);\n *       Description: Remove node from tree.\n *       Args:\n *         tree: Pointer to an initialized red-black tree object.\n *         node: Node in tree to be removed.\n *\n *   static ex_node_t *\n *   ex_iter(ex_t *tree, ex_node_t *start, ex_node_t *(*cb)(ex_t *,\n *     ex_node_t *, void *), void *arg);\n *   static ex_node_t *\n *   ex_reverse_iter(ex_t *tree, ex_node_t *start, ex_node *(*cb)(ex_t *,\n *     ex_node_t *, void *), void *arg);\n *       Description: Iterate forward/backward over tree, starting at node.  If\n *                    tree is modified, iteration must be immediately\n *                    terminated by the callback function that causes the\n *                    modification.\n *       Args:\n *         tree : Pointer to an initialized red-black tree object.\n *         start: Node at which to start iteration, or NULL to start at\n *                first/last node.\n *         cb   : Callback function, which is called for each node during\n *                iteration.  Under normal circumstances the callback function\n *                should return NULL, which causes iteration to continue.  If a\n *                callback function returns non-NULL, iteration is immediately\n *                terminated and the non-NULL return value is returned by the\n *                iterator.  This is useful for re-starting iteration after\n *                modifying tree.\n *         arg  : Opaque pointer passed to cb().\n *       Ret: NULL if iteration completed, or the non-NULL callback return value\n *            that caused termination of the iteration.\n */\n#define\trb_gen(a_attr, a_prefix, a_rbt_type, a_type, a_field, a_cmp)\t\\\na_attr void\t\t\t\t\t\t\t\t\\\na_prefix##new(a_rbt_type *rbtree) {\t\t\t\t\t\\\n    rb_new(a_type, a_field, rbtree);\t\t\t\t\t\\\n}\t\t\t\t\t\t\t\t\t\\\na_attr bool\t\t\t\t\t\t\t\t\\\na_prefix##empty(a_rbt_type *rbtree) {\t\t\t\t\t\\\n    return (rbtree->rbt_root == &rbtree->rbt_nil);\t\t\t\\\n}\t\t\t\t\t\t\t\t\t\\\na_attr a_type *\t\t\t\t\t\t\t\t\\\na_prefix##first(a_rbt_type *rbtree) {\t\t\t\t\t\\\n    a_type *ret;\t\t\t\t\t\t\t\\\n    rbtn_first(a_type, a_field, rbtree, rbtree->rbt_root, ret);\t\t\\\n    if (ret == &rbtree->rbt_nil) {\t\t\t\t\t\\\n\tret = NULL;\t\t\t\t\t\t\t\\\n    }\t\t\t\t\t\t\t\t\t\\\n    return (ret);\t\t\t\t\t\t\t\\\n}\t\t\t\t\t\t\t\t\t\\\na_attr a_type *\t\t\t\t\t\t\t\t\\\na_prefix##last(a_rbt_type *rbtree) {\t\t\t\t\t\\\n    a_type *ret;\t\t\t\t\t\t\t\\\n    rbtn_last(a_type, a_field, rbtree, rbtree->rbt_root, ret);\t\t\\\n    if (ret == &rbtree->rbt_nil) {\t\t\t\t\t\\\n\tret = NULL;\t\t\t\t\t\t\t\\\n    }\t\t\t\t\t\t\t\t\t\\\n    return (ret);\t\t\t\t\t\t\t\\\n}\t\t\t\t\t\t\t\t\t\\\na_attr a_type *\t\t\t\t\t\t\t\t\\\na_prefix##next(a_rbt_type *rbtree, a_type *node) {\t\t\t\\\n    a_type *ret;\t\t\t\t\t\t\t\\\n    if (rbtn_right_get(a_type, a_field, node) != &rbtree->rbt_nil) {\t\\\n\trbtn_first(a_type, a_field, rbtree, rbtn_right_get(a_type,\t\\\n\t  a_field, node), ret);\t\t\t\t\t\t\\\n    } else {\t\t\t\t\t\t\t\t\\\n\ta_type *tnode = rbtree->rbt_root;\t\t\t\t\\\n\tassert(tnode != &rbtree->rbt_nil);\t\t\t\t\\\n\tret = &rbtree->rbt_nil;\t\t\t\t\t\t\\\n\twhile (true) {\t\t\t\t\t\t\t\\\n\t    int cmp = (a_cmp)(node, tnode);\t\t\t\t\\\n\t    if (cmp < 0) {\t\t\t\t\t\t\\\n\t\tret = tnode;\t\t\t\t\t\t\\\n\t\ttnode = rbtn_left_get(a_type, a_field, tnode);\t\t\\\n\t    } else if (cmp > 0) {\t\t\t\t\t\\\n\t\ttnode = rbtn_right_get(a_type, a_field, tnode);\t\t\\\n\t    } else {\t\t\t\t\t\t\t\\\n\t\tbreak;\t\t\t\t\t\t\t\\\n\t    }\t\t\t\t\t\t\t\t\\\n\t    assert(tnode != &rbtree->rbt_nil);\t\t\t\t\\\n\t}\t\t\t\t\t\t\t\t\\\n    }\t\t\t\t\t\t\t\t\t\\\n    if (ret == &rbtree->rbt_nil) {\t\t\t\t\t\\\n\tret = (NULL);\t\t\t\t\t\t\t\\\n    }\t\t\t\t\t\t\t\t\t\\\n    return (ret);\t\t\t\t\t\t\t\\\n}\t\t\t\t\t\t\t\t\t\\\na_attr a_type *\t\t\t\t\t\t\t\t\\\na_prefix##prev(a_rbt_type *rbtree, a_type *node) {\t\t\t\\\n    a_type *ret;\t\t\t\t\t\t\t\\\n    if (rbtn_left_get(a_type, a_field, node) != &rbtree->rbt_nil) {\t\\\n\trbtn_last(a_type, a_field, rbtree, rbtn_left_get(a_type,\t\\\n\t  a_field, node), ret);\t\t\t\t\t\t\\\n    } else {\t\t\t\t\t\t\t\t\\\n\ta_type *tnode = rbtree->rbt_root;\t\t\t\t\\\n\tassert(tnode != &rbtree->rbt_nil);\t\t\t\t\\\n\tret = &rbtree->rbt_nil;\t\t\t\t\t\t\\\n\twhile (true) {\t\t\t\t\t\t\t\\\n\t    int cmp = (a_cmp)(node, tnode);\t\t\t\t\\\n\t    if (cmp < 0) {\t\t\t\t\t\t\\\n\t\ttnode = rbtn_left_get(a_type, a_field, tnode);\t\t\\\n\t    } else if (cmp > 0) {\t\t\t\t\t\\\n\t\tret = tnode;\t\t\t\t\t\t\\\n\t\ttnode = rbtn_right_get(a_type, a_field, tnode);\t\t\\\n\t    } else {\t\t\t\t\t\t\t\\\n\t\tbreak;\t\t\t\t\t\t\t\\\n\t    }\t\t\t\t\t\t\t\t\\\n\t    assert(tnode != &rbtree->rbt_nil);\t\t\t\t\\\n\t}\t\t\t\t\t\t\t\t\\\n    }\t\t\t\t\t\t\t\t\t\\\n    if (ret == &rbtree->rbt_nil) {\t\t\t\t\t\\\n\tret = (NULL);\t\t\t\t\t\t\t\\\n    }\t\t\t\t\t\t\t\t\t\\\n    return (ret);\t\t\t\t\t\t\t\\\n}\t\t\t\t\t\t\t\t\t\\\na_attr a_type *\t\t\t\t\t\t\t\t\\\na_prefix##search(a_rbt_type *rbtree, a_type *key) {\t\t\t\\\n    a_type *ret;\t\t\t\t\t\t\t\\\n    int cmp;\t\t\t\t\t\t\t\t\\\n    ret = rbtree->rbt_root;\t\t\t\t\t\t\\\n    while (ret != &rbtree->rbt_nil\t\t\t\t\t\\\n      && (cmp = (a_cmp)(key, ret)) != 0) {\t\t\t\t\\\n\tif (cmp < 0) {\t\t\t\t\t\t\t\\\n\t    ret = rbtn_left_get(a_type, a_field, ret);\t\t\t\\\n\t} else {\t\t\t\t\t\t\t\\\n\t    ret = rbtn_right_get(a_type, a_field, ret);\t\t\t\\\n\t}\t\t\t\t\t\t\t\t\\\n    }\t\t\t\t\t\t\t\t\t\\\n    if (ret == &rbtree->rbt_nil) {\t\t\t\t\t\\\n\tret = (NULL);\t\t\t\t\t\t\t\\\n    }\t\t\t\t\t\t\t\t\t\\\n    return (ret);\t\t\t\t\t\t\t\\\n}\t\t\t\t\t\t\t\t\t\\\na_attr a_type *\t\t\t\t\t\t\t\t\\\na_prefix##nsearch(a_rbt_type *rbtree, a_type *key) {\t\t\t\\\n    a_type *ret;\t\t\t\t\t\t\t\\\n    a_type *tnode = rbtree->rbt_root;\t\t\t\t\t\\\n    ret = &rbtree->rbt_nil;\t\t\t\t\t\t\\\n    while (tnode != &rbtree->rbt_nil) {\t\t\t\t\t\\\n\tint cmp = (a_cmp)(key, tnode);\t\t\t\t\t\\\n\tif (cmp < 0) {\t\t\t\t\t\t\t\\\n\t    ret = tnode;\t\t\t\t\t\t\\\n\t    tnode = rbtn_left_get(a_type, a_field, tnode);\t\t\\\n\t} else if (cmp > 0) {\t\t\t\t\t\t\\\n\t    tnode = rbtn_right_get(a_type, a_field, tnode);\t\t\\\n\t} else {\t\t\t\t\t\t\t\\\n\t    ret = tnode;\t\t\t\t\t\t\\\n\t    break;\t\t\t\t\t\t\t\\\n\t}\t\t\t\t\t\t\t\t\\\n    }\t\t\t\t\t\t\t\t\t\\\n    if (ret == &rbtree->rbt_nil) {\t\t\t\t\t\\\n\tret = (NULL);\t\t\t\t\t\t\t\\\n    }\t\t\t\t\t\t\t\t\t\\\n    return (ret);\t\t\t\t\t\t\t\\\n}\t\t\t\t\t\t\t\t\t\\\na_attr a_type *\t\t\t\t\t\t\t\t\\\na_prefix##psearch(a_rbt_type *rbtree, a_type *key) {\t\t\t\\\n    a_type *ret;\t\t\t\t\t\t\t\\\n    a_type *tnode = rbtree->rbt_root;\t\t\t\t\t\\\n    ret = &rbtree->rbt_nil;\t\t\t\t\t\t\\\n    while (tnode != &rbtree->rbt_nil) {\t\t\t\t\t\\\n\tint cmp = (a_cmp)(key, tnode);\t\t\t\t\t\\\n\tif (cmp < 0) {\t\t\t\t\t\t\t\\\n\t    tnode = rbtn_left_get(a_type, a_field, tnode);\t\t\\\n\t} else if (cmp > 0) {\t\t\t\t\t\t\\\n\t    ret = tnode;\t\t\t\t\t\t\\\n\t    tnode = rbtn_right_get(a_type, a_field, tnode);\t\t\\\n\t} else {\t\t\t\t\t\t\t\\\n\t    ret = tnode;\t\t\t\t\t\t\\\n\t    break;\t\t\t\t\t\t\t\\\n\t}\t\t\t\t\t\t\t\t\\\n    }\t\t\t\t\t\t\t\t\t\\\n    if (ret == &rbtree->rbt_nil) {\t\t\t\t\t\\\n\tret = (NULL);\t\t\t\t\t\t\t\\\n    }\t\t\t\t\t\t\t\t\t\\\n    return (ret);\t\t\t\t\t\t\t\\\n}\t\t\t\t\t\t\t\t\t\\\na_attr void\t\t\t\t\t\t\t\t\\\na_prefix##insert(a_rbt_type *rbtree, a_type *node) {\t\t\t\\\n    struct {\t\t\t\t\t\t\t\t\\\n\ta_type *node;\t\t\t\t\t\t\t\\\n\tint cmp;\t\t\t\t\t\t\t\\\n    } path[sizeof(void *) << 4], *pathp;\t\t\t\t\\\n    rbt_node_new(a_type, a_field, rbtree, node);\t\t\t\\\n    /* Wind. */\t\t\t\t\t\t\t\t\\\n    path->node = rbtree->rbt_root;\t\t\t\t\t\\\n    for (pathp = path; pathp->node != &rbtree->rbt_nil; pathp++) {\t\\\n\tint cmp = pathp->cmp = a_cmp(node, pathp->node);\t\t\\\n\tassert(cmp != 0);\t\t\t\t\t\t\\\n\tif (cmp < 0) {\t\t\t\t\t\t\t\\\n\t    pathp[1].node = rbtn_left_get(a_type, a_field,\t\t\\\n\t      pathp->node);\t\t\t\t\t\t\\\n\t} else {\t\t\t\t\t\t\t\\\n\t    pathp[1].node = rbtn_right_get(a_type, a_field,\t\t\\\n\t      pathp->node);\t\t\t\t\t\t\\\n\t}\t\t\t\t\t\t\t\t\\\n    }\t\t\t\t\t\t\t\t\t\\\n    pathp->node = node;\t\t\t\t\t\t\t\\\n    /* Unwind. */\t\t\t\t\t\t\t\\\n    for (pathp--; (uintptr_t)pathp >= (uintptr_t)path; pathp--) {\t\\\n\ta_type *cnode = pathp->node;\t\t\t\t\t\\\n\tif (pathp->cmp < 0) {\t\t\t\t\t\t\\\n\t    a_type *left = pathp[1].node;\t\t\t\t\\\n\t    rbtn_left_set(a_type, a_field, cnode, left);\t\t\\\n\t    if (rbtn_red_get(a_type, a_field, left)) {\t\t\t\\\n\t\ta_type *leftleft = rbtn_left_get(a_type, a_field, left);\\\n\t\tif (rbtn_red_get(a_type, a_field, leftleft)) {\t\t\\\n\t\t    /* Fix up 4-node. */\t\t\t\t\\\n\t\t    a_type *tnode;\t\t\t\t\t\\\n\t\t    rbtn_black_set(a_type, a_field, leftleft);\t\t\\\n\t\t    rbtn_rotate_right(a_type, a_field, cnode, tnode);\t\\\n\t\t    cnode = tnode;\t\t\t\t\t\\\n\t\t}\t\t\t\t\t\t\t\\\n\t    } else {\t\t\t\t\t\t\t\\\n\t\treturn;\t\t\t\t\t\t\t\\\n\t    }\t\t\t\t\t\t\t\t\\\n\t} else {\t\t\t\t\t\t\t\\\n\t    a_type *right = pathp[1].node;\t\t\t\t\\\n\t    rbtn_right_set(a_type, a_field, cnode, right);\t\t\\\n\t    if (rbtn_red_get(a_type, a_field, right)) {\t\t\t\\\n\t\ta_type *left = rbtn_left_get(a_type, a_field, cnode);\t\\\n\t\tif (rbtn_red_get(a_type, a_field, left)) {\t\t\\\n\t\t    /* Split 4-node. */\t\t\t\t\t\\\n\t\t    rbtn_black_set(a_type, a_field, left);\t\t\\\n\t\t    rbtn_black_set(a_type, a_field, right);\t\t\\\n\t\t    rbtn_red_set(a_type, a_field, cnode);\t\t\\\n\t\t} else {\t\t\t\t\t\t\\\n\t\t    /* Lean left. */\t\t\t\t\t\\\n\t\t    a_type *tnode;\t\t\t\t\t\\\n\t\t    bool tred = rbtn_red_get(a_type, a_field, cnode);\t\\\n\t\t    rbtn_rotate_left(a_type, a_field, cnode, tnode);\t\\\n\t\t    rbtn_color_set(a_type, a_field, tnode, tred);\t\\\n\t\t    rbtn_red_set(a_type, a_field, cnode);\t\t\\\n\t\t    cnode = tnode;\t\t\t\t\t\\\n\t\t}\t\t\t\t\t\t\t\\\n\t    } else {\t\t\t\t\t\t\t\\\n\t\treturn;\t\t\t\t\t\t\t\\\n\t    }\t\t\t\t\t\t\t\t\\\n\t}\t\t\t\t\t\t\t\t\\\n\tpathp->node = cnode;\t\t\t\t\t\t\\\n    }\t\t\t\t\t\t\t\t\t\\\n    /* Set root, and make it black. */\t\t\t\t\t\\\n    rbtree->rbt_root = path->node;\t\t\t\t\t\\\n    rbtn_black_set(a_type, a_field, rbtree->rbt_root);\t\t\t\\\n}\t\t\t\t\t\t\t\t\t\\\na_attr void\t\t\t\t\t\t\t\t\\\na_prefix##remove(a_rbt_type *rbtree, a_type *node) {\t\t\t\\\n    struct {\t\t\t\t\t\t\t\t\\\n\ta_type *node;\t\t\t\t\t\t\t\\\n\tint cmp;\t\t\t\t\t\t\t\\\n    } *pathp, *nodep, path[sizeof(void *) << 4];\t\t\t\\\n    /* Wind. */\t\t\t\t\t\t\t\t\\\n    nodep = NULL; /* Silence compiler warning. */\t\t\t\\\n    path->node = rbtree->rbt_root;\t\t\t\t\t\\\n    for (pathp = path; pathp->node != &rbtree->rbt_nil; pathp++) {\t\\\n\tint cmp = pathp->cmp = a_cmp(node, pathp->node);\t\t\\\n\tif (cmp < 0) {\t\t\t\t\t\t\t\\\n\t    pathp[1].node = rbtn_left_get(a_type, a_field,\t\t\\\n\t      pathp->node);\t\t\t\t\t\t\\\n\t} else {\t\t\t\t\t\t\t\\\n\t    pathp[1].node = rbtn_right_get(a_type, a_field,\t\t\\\n\t      pathp->node);\t\t\t\t\t\t\\\n\t    if (cmp == 0) {\t\t\t\t\t\t\\\n\t        /* Find node's successor, in preparation for swap. */\t\\\n\t\tpathp->cmp = 1;\t\t\t\t\t\t\\\n\t\tnodep = pathp;\t\t\t\t\t\t\\\n\t\tfor (pathp++; pathp->node != &rbtree->rbt_nil;\t\t\\\n\t\t  pathp++) {\t\t\t\t\t\t\\\n\t\t    pathp->cmp = -1;\t\t\t\t\t\\\n\t\t    pathp[1].node = rbtn_left_get(a_type, a_field,\t\\\n\t\t      pathp->node);\t\t\t\t\t\\\n\t\t}\t\t\t\t\t\t\t\\\n\t\tbreak;\t\t\t\t\t\t\t\\\n\t    }\t\t\t\t\t\t\t\t\\\n\t}\t\t\t\t\t\t\t\t\\\n    }\t\t\t\t\t\t\t\t\t\\\n    assert(nodep->node == node);\t\t\t\t\t\\\n    pathp--;\t\t\t\t\t\t\t\t\\\n    if (pathp->node != node) {\t\t\t\t\t\t\\\n\t/* Swap node with its successor. */\t\t\t\t\\\n\tbool tred = rbtn_red_get(a_type, a_field, pathp->node);\t\t\\\n\trbtn_color_set(a_type, a_field, pathp->node,\t\t\t\\\n\t  rbtn_red_get(a_type, a_field, node));\t\t\t\t\\\n\trbtn_left_set(a_type, a_field, pathp->node,\t\t\t\\\n\t  rbtn_left_get(a_type, a_field, node));\t\t\t\\\n\t/* If node's successor is its right child, the following code */\\\n\t/* will do the wrong thing for the right child pointer.       */\\\n\t/* However, it doesn't matter, because the pointer will be    */\\\n\t/* properly set when the successor is pruned.                 */\\\n\trbtn_right_set(a_type, a_field, pathp->node,\t\t\t\\\n\t  rbtn_right_get(a_type, a_field, node));\t\t\t\\\n\trbtn_color_set(a_type, a_field, node, tred);\t\t\t\\\n\t/* The pruned leaf node's child pointers are never accessed   */\\\n\t/* again, so don't bother setting them to nil.                */\\\n\tnodep->node = pathp->node;\t\t\t\t\t\\\n\tpathp->node = node;\t\t\t\t\t\t\\\n\tif (nodep == path) {\t\t\t\t\t\t\\\n\t    rbtree->rbt_root = nodep->node;\t\t\t\t\\\n\t} else {\t\t\t\t\t\t\t\\\n\t    if (nodep[-1].cmp < 0) {\t\t\t\t\t\\\n\t\trbtn_left_set(a_type, a_field, nodep[-1].node,\t\t\\\n\t\t  nodep->node);\t\t\t\t\t\t\\\n\t    } else {\t\t\t\t\t\t\t\\\n\t\trbtn_right_set(a_type, a_field, nodep[-1].node,\t\t\\\n\t\t  nodep->node);\t\t\t\t\t\t\\\n\t    }\t\t\t\t\t\t\t\t\\\n\t}\t\t\t\t\t\t\t\t\\\n    } else {\t\t\t\t\t\t\t\t\\\n\ta_type *left = rbtn_left_get(a_type, a_field, node);\t\t\\\n\tif (left != &rbtree->rbt_nil) {\t\t\t\t\t\\\n\t    /* node has no successor, but it has a left child.        */\\\n\t    /* Splice node out, without losing the left child.        */\\\n\t    assert(!rbtn_red_get(a_type, a_field, node));\t\t\\\n\t    assert(rbtn_red_get(a_type, a_field, left));\t\t\\\n\t    rbtn_black_set(a_type, a_field, left);\t\t\t\\\n\t    if (pathp == path) {\t\t\t\t\t\\\n\t\trbtree->rbt_root = left;\t\t\t\t\\\n\t    } else {\t\t\t\t\t\t\t\\\n\t\tif (pathp[-1].cmp < 0) {\t\t\t\t\\\n\t\t    rbtn_left_set(a_type, a_field, pathp[-1].node,\t\\\n\t\t      left);\t\t\t\t\t\t\\\n\t\t} else {\t\t\t\t\t\t\\\n\t\t    rbtn_right_set(a_type, a_field, pathp[-1].node,\t\\\n\t\t      left);\t\t\t\t\t\t\\\n\t\t}\t\t\t\t\t\t\t\\\n\t    }\t\t\t\t\t\t\t\t\\\n\t    return;\t\t\t\t\t\t\t\\\n\t} else if (pathp == path) {\t\t\t\t\t\\\n\t    /* The tree only contained one node. */\t\t\t\\\n\t    rbtree->rbt_root = &rbtree->rbt_nil;\t\t\t\\\n\t    return;\t\t\t\t\t\t\t\\\n\t}\t\t\t\t\t\t\t\t\\\n    }\t\t\t\t\t\t\t\t\t\\\n    if (rbtn_red_get(a_type, a_field, pathp->node)) {\t\t\t\\\n\t/* Prune red node, which requires no fixup. */\t\t\t\\\n\tassert(pathp[-1].cmp < 0);\t\t\t\t\t\\\n\trbtn_left_set(a_type, a_field, pathp[-1].node,\t\t\t\\\n\t  &rbtree->rbt_nil);\t\t\t\t\t\t\\\n\treturn;\t\t\t\t\t\t\t\t\\\n    }\t\t\t\t\t\t\t\t\t\\\n    /* The node to be pruned is black, so unwind until balance is     */\\\n    /* restored.                                                      */\\\n    pathp->node = &rbtree->rbt_nil;\t\t\t\t\t\\\n    for (pathp--; (uintptr_t)pathp >= (uintptr_t)path; pathp--) {\t\\\n\tassert(pathp->cmp != 0);\t\t\t\t\t\\\n\tif (pathp->cmp < 0) {\t\t\t\t\t\t\\\n\t    rbtn_left_set(a_type, a_field, pathp->node,\t\t\t\\\n\t      pathp[1].node);\t\t\t\t\t\t\\\n\t    assert(!rbtn_red_get(a_type, a_field, pathp[1].node));\t\\\n\t    if (rbtn_red_get(a_type, a_field, pathp->node)) {\t\t\\\n\t\ta_type *right = rbtn_right_get(a_type, a_field,\t\t\\\n\t\t  pathp->node);\t\t\t\t\t\t\\\n\t\ta_type *rightleft = rbtn_left_get(a_type, a_field,\t\\\n\t\t  right);\t\t\t\t\t\t\\\n\t\ta_type *tnode;\t\t\t\t\t\t\\\n\t\tif (rbtn_red_get(a_type, a_field, rightleft)) {\t\t\\\n\t\t    /* In the following diagrams, ||, //, and \\\\      */\\\n\t\t    /* indicate the path to the removed node.         */\\\n\t\t    /*                                                */\\\n\t\t    /*      ||                                        */\\\n\t\t    /*    pathp(r)                                    */\\\n\t\t    /*  //        \\                                   */\\\n\t\t    /* (b)        (b)                                 */\\\n\t\t    /*           /                                    */\\\n\t\t    /*          (r)                                   */\\\n\t\t    /*                                                */\\\n\t\t    rbtn_black_set(a_type, a_field, pathp->node);\t\\\n\t\t    rbtn_rotate_right(a_type, a_field, right, tnode);\t\\\n\t\t    rbtn_right_set(a_type, a_field, pathp->node, tnode);\\\n\t\t    rbtn_rotate_left(a_type, a_field, pathp->node,\t\\\n\t\t      tnode);\t\t\t\t\t\t\\\n\t\t} else {\t\t\t\t\t\t\\\n\t\t    /*      ||                                        */\\\n\t\t    /*    pathp(r)                                    */\\\n\t\t    /*  //        \\                                   */\\\n\t\t    /* (b)        (b)                                 */\\\n\t\t    /*           /                                    */\\\n\t\t    /*          (b)                                   */\\\n\t\t    /*                                                */\\\n\t\t    rbtn_rotate_left(a_type, a_field, pathp->node,\t\\\n\t\t      tnode);\t\t\t\t\t\t\\\n\t\t}\t\t\t\t\t\t\t\\\n\t\t/* Balance restored, but rotation modified subtree    */\\\n\t\t/* root.                                              */\\\n\t\tassert((uintptr_t)pathp > (uintptr_t)path);\t\t\\\n\t\tif (pathp[-1].cmp < 0) {\t\t\t\t\\\n\t\t    rbtn_left_set(a_type, a_field, pathp[-1].node,\t\\\n\t\t      tnode);\t\t\t\t\t\t\\\n\t\t} else {\t\t\t\t\t\t\\\n\t\t    rbtn_right_set(a_type, a_field, pathp[-1].node,\t\\\n\t\t      tnode);\t\t\t\t\t\t\\\n\t\t}\t\t\t\t\t\t\t\\\n\t\treturn;\t\t\t\t\t\t\t\\\n\t    } else {\t\t\t\t\t\t\t\\\n\t\ta_type *right = rbtn_right_get(a_type, a_field,\t\t\\\n\t\t  pathp->node);\t\t\t\t\t\t\\\n\t\ta_type *rightleft = rbtn_left_get(a_type, a_field,\t\\\n\t\t  right);\t\t\t\t\t\t\\\n\t\tif (rbtn_red_get(a_type, a_field, rightleft)) {\t\t\\\n\t\t    /*      ||                                        */\\\n\t\t    /*    pathp(b)                                    */\\\n\t\t    /*  //        \\                                   */\\\n\t\t    /* (b)        (b)                                 */\\\n\t\t    /*           /                                    */\\\n\t\t    /*          (r)                                   */\\\n\t\t    a_type *tnode;\t\t\t\t\t\\\n\t\t    rbtn_black_set(a_type, a_field, rightleft);\t\t\\\n\t\t    rbtn_rotate_right(a_type, a_field, right, tnode);\t\\\n\t\t    rbtn_right_set(a_type, a_field, pathp->node, tnode);\\\n\t\t    rbtn_rotate_left(a_type, a_field, pathp->node,\t\\\n\t\t      tnode);\t\t\t\t\t\t\\\n\t\t    /* Balance restored, but rotation modified        */\\\n\t\t    /* subtree root, which may actually be the tree   */\\\n\t\t    /* root.                                          */\\\n\t\t    if (pathp == path) {\t\t\t\t\\\n\t\t\t/* Set root. */\t\t\t\t\t\\\n\t\t\trbtree->rbt_root = tnode;\t\t\t\\\n\t\t    } else {\t\t\t\t\t\t\\\n\t\t\tif (pathp[-1].cmp < 0) {\t\t\t\\\n\t\t\t    rbtn_left_set(a_type, a_field,\t\t\\\n\t\t\t      pathp[-1].node, tnode);\t\t\t\\\n\t\t\t} else {\t\t\t\t\t\\\n\t\t\t    rbtn_right_set(a_type, a_field,\t\t\\\n\t\t\t      pathp[-1].node, tnode);\t\t\t\\\n\t\t\t}\t\t\t\t\t\t\\\n\t\t    }\t\t\t\t\t\t\t\\\n\t\t    return;\t\t\t\t\t\t\\\n\t\t} else {\t\t\t\t\t\t\\\n\t\t    /*      ||                                        */\\\n\t\t    /*    pathp(b)                                    */\\\n\t\t    /*  //        \\                                   */\\\n\t\t    /* (b)        (b)                                 */\\\n\t\t    /*           /                                    */\\\n\t\t    /*          (b)                                   */\\\n\t\t    a_type *tnode;\t\t\t\t\t\\\n\t\t    rbtn_red_set(a_type, a_field, pathp->node);\t\t\\\n\t\t    rbtn_rotate_left(a_type, a_field, pathp->node,\t\\\n\t\t      tnode);\t\t\t\t\t\t\\\n\t\t    pathp->node = tnode;\t\t\t\t\\\n\t\t}\t\t\t\t\t\t\t\\\n\t    }\t\t\t\t\t\t\t\t\\\n\t} else {\t\t\t\t\t\t\t\\\n\t    a_type *left;\t\t\t\t\t\t\\\n\t    rbtn_right_set(a_type, a_field, pathp->node,\t\t\\\n\t      pathp[1].node);\t\t\t\t\t\t\\\n\t    left = rbtn_left_get(a_type, a_field, pathp->node);\t\t\\\n\t    if (rbtn_red_get(a_type, a_field, left)) {\t\t\t\\\n\t\ta_type *tnode;\t\t\t\t\t\t\\\n\t\ta_type *leftright = rbtn_right_get(a_type, a_field,\t\\\n\t\t  left);\t\t\t\t\t\t\\\n\t\ta_type *leftrightleft = rbtn_left_get(a_type, a_field,\t\\\n\t\t  leftright);\t\t\t\t\t\t\\\n\t\tif (rbtn_red_get(a_type, a_field, leftrightleft)) {\t\\\n\t\t    /*      ||                                        */\\\n\t\t    /*    pathp(b)                                    */\\\n\t\t    /*   /        \\\\                                  */\\\n\t\t    /* (r)        (b)                                 */\\\n\t\t    /*   \\                                            */\\\n\t\t    /*   (b)                                          */\\\n\t\t    /*   /                                            */\\\n\t\t    /* (r)                                            */\\\n\t\t    a_type *unode;\t\t\t\t\t\\\n\t\t    rbtn_black_set(a_type, a_field, leftrightleft);\t\\\n\t\t    rbtn_rotate_right(a_type, a_field, pathp->node,\t\\\n\t\t      unode);\t\t\t\t\t\t\\\n\t\t    rbtn_rotate_right(a_type, a_field, pathp->node,\t\\\n\t\t      tnode);\t\t\t\t\t\t\\\n\t\t    rbtn_right_set(a_type, a_field, unode, tnode);\t\\\n\t\t    rbtn_rotate_left(a_type, a_field, unode, tnode);\t\\\n\t\t} else {\t\t\t\t\t\t\\\n\t\t    /*      ||                                        */\\\n\t\t    /*    pathp(b)                                    */\\\n\t\t    /*   /        \\\\                                  */\\\n\t\t    /* (r)        (b)                                 */\\\n\t\t    /*   \\                                            */\\\n\t\t    /*   (b)                                          */\\\n\t\t    /*   /                                            */\\\n\t\t    /* (b)                                            */\\\n\t\t    assert(leftright != &rbtree->rbt_nil);\t\t\\\n\t\t    rbtn_red_set(a_type, a_field, leftright);\t\t\\\n\t\t    rbtn_rotate_right(a_type, a_field, pathp->node,\t\\\n\t\t      tnode);\t\t\t\t\t\t\\\n\t\t    rbtn_black_set(a_type, a_field, tnode);\t\t\\\n\t\t}\t\t\t\t\t\t\t\\\n\t\t/* Balance restored, but rotation modified subtree    */\\\n\t\t/* root, which may actually be the tree root.         */\\\n\t\tif (pathp == path) {\t\t\t\t\t\\\n\t\t    /* Set root. */\t\t\t\t\t\\\n\t\t    rbtree->rbt_root = tnode;\t\t\t\t\\\n\t\t} else {\t\t\t\t\t\t\\\n\t\t    if (pathp[-1].cmp < 0) {\t\t\t\t\\\n\t\t\trbtn_left_set(a_type, a_field, pathp[-1].node,\t\\\n\t\t\t  tnode);\t\t\t\t\t\\\n\t\t    } else {\t\t\t\t\t\t\\\n\t\t\trbtn_right_set(a_type, a_field, pathp[-1].node,\t\\\n\t\t\t  tnode);\t\t\t\t\t\\\n\t\t    }\t\t\t\t\t\t\t\\\n\t\t}\t\t\t\t\t\t\t\\\n\t\treturn;\t\t\t\t\t\t\t\\\n\t    } else if (rbtn_red_get(a_type, a_field, pathp->node)) {\t\\\n\t\ta_type *leftleft = rbtn_left_get(a_type, a_field, left);\\\n\t\tif (rbtn_red_get(a_type, a_field, leftleft)) {\t\t\\\n\t\t    /*        ||                                      */\\\n\t\t    /*      pathp(r)                                  */\\\n\t\t    /*     /        \\\\                                */\\\n\t\t    /*   (b)        (b)                               */\\\n\t\t    /*   /                                            */\\\n\t\t    /* (r)                                            */\\\n\t\t    a_type *tnode;\t\t\t\t\t\\\n\t\t    rbtn_black_set(a_type, a_field, pathp->node);\t\\\n\t\t    rbtn_red_set(a_type, a_field, left);\t\t\\\n\t\t    rbtn_black_set(a_type, a_field, leftleft);\t\t\\\n\t\t    rbtn_rotate_right(a_type, a_field, pathp->node,\t\\\n\t\t      tnode);\t\t\t\t\t\t\\\n\t\t    /* Balance restored, but rotation modified        */\\\n\t\t    /* subtree root.                                  */\\\n\t\t    assert((uintptr_t)pathp > (uintptr_t)path);\t\t\\\n\t\t    if (pathp[-1].cmp < 0) {\t\t\t\t\\\n\t\t\trbtn_left_set(a_type, a_field, pathp[-1].node,\t\\\n\t\t\t  tnode);\t\t\t\t\t\\\n\t\t    } else {\t\t\t\t\t\t\\\n\t\t\trbtn_right_set(a_type, a_field, pathp[-1].node,\t\\\n\t\t\t  tnode);\t\t\t\t\t\\\n\t\t    }\t\t\t\t\t\t\t\\\n\t\t    return;\t\t\t\t\t\t\\\n\t\t} else {\t\t\t\t\t\t\\\n\t\t    /*        ||                                      */\\\n\t\t    /*      pathp(r)                                  */\\\n\t\t    /*     /        \\\\                                */\\\n\t\t    /*   (b)        (b)                               */\\\n\t\t    /*   /                                            */\\\n\t\t    /* (b)                                            */\\\n\t\t    rbtn_red_set(a_type, a_field, left);\t\t\\\n\t\t    rbtn_black_set(a_type, a_field, pathp->node);\t\\\n\t\t    /* Balance restored. */\t\t\t\t\\\n\t\t    return;\t\t\t\t\t\t\\\n\t\t}\t\t\t\t\t\t\t\\\n\t    } else {\t\t\t\t\t\t\t\\\n\t\ta_type *leftleft = rbtn_left_get(a_type, a_field, left);\\\n\t\tif (rbtn_red_get(a_type, a_field, leftleft)) {\t\t\\\n\t\t    /*               ||                               */\\\n\t\t    /*             pathp(b)                           */\\\n\t\t    /*            /        \\\\                         */\\\n\t\t    /*          (b)        (b)                        */\\\n\t\t    /*          /                                     */\\\n\t\t    /*        (r)                                     */\\\n\t\t    a_type *tnode;\t\t\t\t\t\\\n\t\t    rbtn_black_set(a_type, a_field, leftleft);\t\t\\\n\t\t    rbtn_rotate_right(a_type, a_field, pathp->node,\t\\\n\t\t      tnode);\t\t\t\t\t\t\\\n\t\t    /* Balance restored, but rotation modified        */\\\n\t\t    /* subtree root, which may actually be the tree   */\\\n\t\t    /* root.                                          */\\\n\t\t    if (pathp == path) {\t\t\t\t\\\n\t\t\t/* Set root. */\t\t\t\t\t\\\n\t\t\trbtree->rbt_root = tnode;\t\t\t\\\n\t\t    } else {\t\t\t\t\t\t\\\n\t\t\tif (pathp[-1].cmp < 0) {\t\t\t\\\n\t\t\t    rbtn_left_set(a_type, a_field,\t\t\\\n\t\t\t      pathp[-1].node, tnode);\t\t\t\\\n\t\t\t} else {\t\t\t\t\t\\\n\t\t\t    rbtn_right_set(a_type, a_field,\t\t\\\n\t\t\t      pathp[-1].node, tnode);\t\t\t\\\n\t\t\t}\t\t\t\t\t\t\\\n\t\t    }\t\t\t\t\t\t\t\\\n\t\t    return;\t\t\t\t\t\t\\\n\t\t} else {\t\t\t\t\t\t\\\n\t\t    /*               ||                               */\\\n\t\t    /*             pathp(b)                           */\\\n\t\t    /*            /        \\\\                         */\\\n\t\t    /*          (b)        (b)                        */\\\n\t\t    /*          /                                     */\\\n\t\t    /*        (b)                                     */\\\n\t\t    rbtn_red_set(a_type, a_field, left);\t\t\\\n\t\t}\t\t\t\t\t\t\t\\\n\t    }\t\t\t\t\t\t\t\t\\\n\t}\t\t\t\t\t\t\t\t\\\n    }\t\t\t\t\t\t\t\t\t\\\n    /* Set root. */\t\t\t\t\t\t\t\\\n    rbtree->rbt_root = path->node;\t\t\t\t\t\\\n    assert(!rbtn_red_get(a_type, a_field, rbtree->rbt_root));\t\t\\\n}\t\t\t\t\t\t\t\t\t\\\na_attr a_type *\t\t\t\t\t\t\t\t\\\na_prefix##iter_recurse(a_rbt_type *rbtree, a_type *node,\t\t\\\n  a_type *(*cb)(a_rbt_type *, a_type *, void *), void *arg) {\t\t\\\n    if (node == &rbtree->rbt_nil) {\t\t\t\t\t\\\n\treturn (&rbtree->rbt_nil);\t\t\t\t\t\\\n    } else {\t\t\t\t\t\t\t\t\\\n\ta_type *ret;\t\t\t\t\t\t\t\\\n\tif ((ret = a_prefix##iter_recurse(rbtree, rbtn_left_get(a_type,\t\\\n\t  a_field, node), cb, arg)) != &rbtree->rbt_nil\t\t\t\\\n\t  || (ret = cb(rbtree, node, arg)) != NULL) {\t\t\t\\\n\t    return (ret);\t\t\t\t\t\t\\\n\t}\t\t\t\t\t\t\t\t\\\n\treturn (a_prefix##iter_recurse(rbtree, rbtn_right_get(a_type,\t\\\n\t  a_field, node), cb, arg));\t\t\t\t\t\\\n    }\t\t\t\t\t\t\t\t\t\\\n}\t\t\t\t\t\t\t\t\t\\\na_attr a_type *\t\t\t\t\t\t\t\t\\\na_prefix##iter_start(a_rbt_type *rbtree, a_type *start, a_type *node,\t\\\n  a_type *(*cb)(a_rbt_type *, a_type *, void *), void *arg) {\t\t\\\n    int cmp = a_cmp(start, node);\t\t\t\t\t\\\n    if (cmp < 0) {\t\t\t\t\t\t\t\\\n\ta_type *ret;\t\t\t\t\t\t\t\\\n\tif ((ret = a_prefix##iter_start(rbtree, start,\t\t\t\\\n\t  rbtn_left_get(a_type, a_field, node), cb, arg)) !=\t\t\\\n\t  &rbtree->rbt_nil || (ret = cb(rbtree, node, arg)) != NULL) {\t\\\n\t    return (ret);\t\t\t\t\t\t\\\n\t}\t\t\t\t\t\t\t\t\\\n\treturn (a_prefix##iter_recurse(rbtree, rbtn_right_get(a_type,\t\\\n\t  a_field, node), cb, arg));\t\t\t\t\t\\\n    } else if (cmp > 0) {\t\t\t\t\t\t\\\n\treturn (a_prefix##iter_start(rbtree, start,\t\t\t\\\n\t  rbtn_right_get(a_type, a_field, node), cb, arg));\t\t\\\n    } else {\t\t\t\t\t\t\t\t\\\n\ta_type *ret;\t\t\t\t\t\t\t\\\n\tif ((ret = cb(rbtree, node, arg)) != NULL) {\t\t\t\\\n\t    return (ret);\t\t\t\t\t\t\\\n\t}\t\t\t\t\t\t\t\t\\\n\treturn (a_prefix##iter_recurse(rbtree, rbtn_right_get(a_type,\t\\\n\t  a_field, node), cb, arg));\t\t\t\t\t\\\n    }\t\t\t\t\t\t\t\t\t\\\n}\t\t\t\t\t\t\t\t\t\\\na_attr a_type *\t\t\t\t\t\t\t\t\\\na_prefix##iter(a_rbt_type *rbtree, a_type *start, a_type *(*cb)(\t\\\n  a_rbt_type *, a_type *, void *), void *arg) {\t\t\t\t\\\n    a_type *ret;\t\t\t\t\t\t\t\\\n    if (start != NULL) {\t\t\t\t\t\t\\\n\tret = a_prefix##iter_start(rbtree, start, rbtree->rbt_root,\t\\\n\t  cb, arg);\t\t\t\t\t\t\t\\\n    } else {\t\t\t\t\t\t\t\t\\\n\tret = a_prefix##iter_recurse(rbtree, rbtree->rbt_root, cb, arg);\\\n    }\t\t\t\t\t\t\t\t\t\\\n    if (ret == &rbtree->rbt_nil) {\t\t\t\t\t\\\n\tret = NULL;\t\t\t\t\t\t\t\\\n    }\t\t\t\t\t\t\t\t\t\\\n    return (ret);\t\t\t\t\t\t\t\\\n}\t\t\t\t\t\t\t\t\t\\\na_attr a_type *\t\t\t\t\t\t\t\t\\\na_prefix##reverse_iter_recurse(a_rbt_type *rbtree, a_type *node,\t\\\n  a_type *(*cb)(a_rbt_type *, a_type *, void *), void *arg) {\t\t\\\n    if (node == &rbtree->rbt_nil) {\t\t\t\t\t\\\n\treturn (&rbtree->rbt_nil);\t\t\t\t\t\\\n    } else {\t\t\t\t\t\t\t\t\\\n\ta_type *ret;\t\t\t\t\t\t\t\\\n\tif ((ret = a_prefix##reverse_iter_recurse(rbtree,\t\t\\\n\t  rbtn_right_get(a_type, a_field, node), cb, arg)) !=\t\t\\\n\t  &rbtree->rbt_nil || (ret = cb(rbtree, node, arg)) != NULL) {\t\\\n\t    return (ret);\t\t\t\t\t\t\\\n\t}\t\t\t\t\t\t\t\t\\\n\treturn (a_prefix##reverse_iter_recurse(rbtree,\t\t\t\\\n\t  rbtn_left_get(a_type, a_field, node), cb, arg));\t\t\\\n    }\t\t\t\t\t\t\t\t\t\\\n}\t\t\t\t\t\t\t\t\t\\\na_attr a_type *\t\t\t\t\t\t\t\t\\\na_prefix##reverse_iter_start(a_rbt_type *rbtree, a_type *start,\t\t\\\n  a_type *node, a_type *(*cb)(a_rbt_type *, a_type *, void *),\t\t\\\n  void *arg) {\t\t\t\t\t\t\t\t\\\n    int cmp = a_cmp(start, node);\t\t\t\t\t\\\n    if (cmp > 0) {\t\t\t\t\t\t\t\\\n\ta_type *ret;\t\t\t\t\t\t\t\\\n\tif ((ret = a_prefix##reverse_iter_start(rbtree, start,\t\t\\\n\t  rbtn_right_get(a_type, a_field, node), cb, arg)) !=\t\t\\\n\t  &rbtree->rbt_nil || (ret = cb(rbtree, node, arg)) != NULL) {\t\\\n\t    return (ret);\t\t\t\t\t\t\\\n\t}\t\t\t\t\t\t\t\t\\\n\treturn (a_prefix##reverse_iter_recurse(rbtree,\t\t\t\\\n\t  rbtn_left_get(a_type, a_field, node), cb, arg));\t\t\\\n    } else if (cmp < 0) {\t\t\t\t\t\t\\\n\treturn (a_prefix##reverse_iter_start(rbtree, start,\t\t\\\n\t  rbtn_left_get(a_type, a_field, node), cb, arg));\t\t\\\n    } else {\t\t\t\t\t\t\t\t\\\n\ta_type *ret;\t\t\t\t\t\t\t\\\n\tif ((ret = cb(rbtree, node, arg)) != NULL) {\t\t\t\\\n\t    return (ret);\t\t\t\t\t\t\\\n\t}\t\t\t\t\t\t\t\t\\\n\treturn (a_prefix##reverse_iter_recurse(rbtree,\t\t\t\\\n\t  rbtn_left_get(a_type, a_field, node), cb, arg));\t\t\\\n    }\t\t\t\t\t\t\t\t\t\\\n}\t\t\t\t\t\t\t\t\t\\\na_attr a_type *\t\t\t\t\t\t\t\t\\\na_prefix##reverse_iter(a_rbt_type *rbtree, a_type *start,\t\t\\\n  a_type *(*cb)(a_rbt_type *, a_type *, void *), void *arg) {\t\t\\\n    a_type *ret;\t\t\t\t\t\t\t\\\n    if (start != NULL) {\t\t\t\t\t\t\\\n\tret = a_prefix##reverse_iter_start(rbtree, start,\t\t\\\n\t  rbtree->rbt_root, cb, arg);\t\t\t\t\t\\\n    } else {\t\t\t\t\t\t\t\t\\\n\tret = a_prefix##reverse_iter_recurse(rbtree, rbtree->rbt_root,\t\\\n\t  cb, arg);\t\t\t\t\t\t\t\\\n    }\t\t\t\t\t\t\t\t\t\\\n    if (ret == &rbtree->rbt_nil) {\t\t\t\t\t\\\n\tret = NULL;\t\t\t\t\t\t\t\\\n    }\t\t\t\t\t\t\t\t\t\\\n    return (ret);\t\t\t\t\t\t\t\\\n}\n\n#endif /* RB_H_ */\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.8/deps/jemalloc/include/jemalloc/internal/rtree.h",
    "content": "/*\n * This radix tree implementation is tailored to the singular purpose of\n * associating metadata with chunks that are currently owned by jemalloc.\n *\n *******************************************************************************\n */\n#ifdef JEMALLOC_H_TYPES\n\ntypedef struct rtree_node_elm_s rtree_node_elm_t;\ntypedef struct rtree_level_s rtree_level_t;\ntypedef struct rtree_s rtree_t;\n\n/*\n * RTREE_BITS_PER_LEVEL must be a power of two that is no larger than the\n * machine address width.\n */\n#define\tLG_RTREE_BITS_PER_LEVEL\t4\n#define\tRTREE_BITS_PER_LEVEL\t(ZU(1) << LG_RTREE_BITS_PER_LEVEL)\n#define\tRTREE_HEIGHT_MAX\t\t\t\t\t\t\\\n    ((ZU(1) << (LG_SIZEOF_PTR+3)) / RTREE_BITS_PER_LEVEL)\n\n/* Used for two-stage lock-free node initialization. */\n#define\tRTREE_NODE_INITIALIZING\t((rtree_node_elm_t *)0x1)\n\n/*\n * The node allocation callback function's argument is the number of contiguous\n * rtree_node_elm_t structures to allocate, and the resulting memory must be\n * zeroed.\n */\ntypedef rtree_node_elm_t *(rtree_node_alloc_t)(size_t);\ntypedef void (rtree_node_dalloc_t)(rtree_node_elm_t *);\n\n#endif /* JEMALLOC_H_TYPES */\n/******************************************************************************/\n#ifdef JEMALLOC_H_STRUCTS\n\nstruct rtree_node_elm_s {\n\tunion {\n\t\tvoid\t\t\t*pun;\n\t\trtree_node_elm_t\t*child;\n\t\textent_node_t\t\t*val;\n\t};\n};\n\nstruct rtree_level_s {\n\t/*\n\t * A non-NULL subtree points to a subtree rooted along the hypothetical\n\t * path to the leaf node corresponding to key 0.  Depending on what keys\n\t * have been used to store to the tree, an arbitrary combination of\n\t * subtree pointers may remain NULL.\n\t *\n\t * Suppose keys comprise 48 bits, and LG_RTREE_BITS_PER_LEVEL is 4.\n\t * This results in a 3-level tree, and the leftmost leaf can be directly\n\t * accessed via subtrees[2], the subtree prefixed by 0x0000 (excluding\n\t * 0x00000000) can be accessed via subtrees[1], and the remainder of the\n\t * tree can be accessed via subtrees[0].\n\t *\n\t *   levels[0] : [<unused> | 0x0001******** | 0x0002******** | ...]\n\t *\n\t *   levels[1] : [<unused> | 0x00000001**** | 0x00000002**** | ... ]\n\t *\n\t *   levels[2] : [val(0x000000000000) | val(0x000000000001) | ...]\n\t *\n\t * This has practical implications on x64, which currently uses only the\n\t * lower 47 bits of virtual address space in userland, thus leaving\n\t * subtrees[0] unused and avoiding a level of tree traversal.\n\t */\n\tunion {\n\t\tvoid\t\t\t*subtree_pun;\n\t\trtree_node_elm_t\t*subtree;\n\t};\n\t/* Number of key bits distinguished by this level. */\n\tunsigned\t\tbits;\n\t/*\n\t * Cumulative number of key bits distinguished by traversing to\n\t * corresponding tree level.\n\t */\n\tunsigned\t\tcumbits;\n};\n\nstruct rtree_s {\n\trtree_node_alloc_t\t*alloc;\n\trtree_node_dalloc_t\t*dalloc;\n\tunsigned\t\theight;\n\t/*\n\t * Precomputed table used to convert from the number of leading 0 key\n\t * bits to which subtree level to start at.\n\t */\n\tunsigned\t\tstart_level[RTREE_HEIGHT_MAX];\n\trtree_level_t\t\tlevels[RTREE_HEIGHT_MAX];\n};\n\n#endif /* JEMALLOC_H_STRUCTS */\n/******************************************************************************/\n#ifdef JEMALLOC_H_EXTERNS\n\nbool rtree_new(rtree_t *rtree, unsigned bits, rtree_node_alloc_t *alloc,\n    rtree_node_dalloc_t *dalloc);\nvoid\trtree_delete(rtree_t *rtree);\nrtree_node_elm_t\t*rtree_subtree_read_hard(rtree_t *rtree,\n    unsigned level);\nrtree_node_elm_t\t*rtree_child_read_hard(rtree_t *rtree,\n    rtree_node_elm_t *elm, unsigned level);\n\n#endif /* JEMALLOC_H_EXTERNS */\n/******************************************************************************/\n#ifdef JEMALLOC_H_INLINES\n\n#ifndef JEMALLOC_ENABLE_INLINE\nunsigned\trtree_start_level(rtree_t *rtree, uintptr_t key);\nuintptr_t\trtree_subkey(rtree_t *rtree, uintptr_t key, unsigned level);\n\nbool\trtree_node_valid(rtree_node_elm_t *node);\nrtree_node_elm_t\t*rtree_child_tryread(rtree_node_elm_t *elm);\nrtree_node_elm_t\t*rtree_child_read(rtree_t *rtree, rtree_node_elm_t *elm,\n    unsigned level);\nextent_node_t\t*rtree_val_read(rtree_t *rtree, rtree_node_elm_t *elm,\n    bool dependent);\nvoid\trtree_val_write(rtree_t *rtree, rtree_node_elm_t *elm,\n    const extent_node_t *val);\nrtree_node_elm_t\t*rtree_subtree_tryread(rtree_t *rtree, unsigned level);\nrtree_node_elm_t\t*rtree_subtree_read(rtree_t *rtree, unsigned level);\n\nextent_node_t\t*rtree_get(rtree_t *rtree, uintptr_t key, bool dependent);\nbool\trtree_set(rtree_t *rtree, uintptr_t key, const extent_node_t *val);\n#endif\n\n#if (defined(JEMALLOC_ENABLE_INLINE) || defined(JEMALLOC_RTREE_C_))\nJEMALLOC_INLINE unsigned\nrtree_start_level(rtree_t *rtree, uintptr_t key)\n{\n\tunsigned start_level;\n\n\tif (unlikely(key == 0))\n\t\treturn (rtree->height - 1);\n\n\tstart_level = rtree->start_level[lg_floor(key) >>\n\t    LG_RTREE_BITS_PER_LEVEL];\n\tassert(start_level < rtree->height);\n\treturn (start_level);\n}\n\nJEMALLOC_INLINE uintptr_t\nrtree_subkey(rtree_t *rtree, uintptr_t key, unsigned level)\n{\n\n\treturn ((key >> ((ZU(1) << (LG_SIZEOF_PTR+3)) -\n\t    rtree->levels[level].cumbits)) & ((ZU(1) <<\n\t    rtree->levels[level].bits) - 1));\n}\n\nJEMALLOC_INLINE bool\nrtree_node_valid(rtree_node_elm_t *node)\n{\n\n\treturn ((uintptr_t)node > (uintptr_t)RTREE_NODE_INITIALIZING);\n}\n\nJEMALLOC_INLINE rtree_node_elm_t *\nrtree_child_tryread(rtree_node_elm_t *elm)\n{\n\trtree_node_elm_t *child;\n\n\t/* Double-checked read (first read may be stale. */\n\tchild = elm->child;\n\tif (!rtree_node_valid(child))\n\t\tchild = atomic_read_p(&elm->pun);\n\treturn (child);\n}\n\nJEMALLOC_INLINE rtree_node_elm_t *\nrtree_child_read(rtree_t *rtree, rtree_node_elm_t *elm, unsigned level)\n{\n\trtree_node_elm_t *child;\n\n\tchild = rtree_child_tryread(elm);\n\tif (unlikely(!rtree_node_valid(child)))\n\t\tchild = rtree_child_read_hard(rtree, elm, level);\n\treturn (child);\n}\n\nJEMALLOC_INLINE extent_node_t *\nrtree_val_read(rtree_t *rtree, rtree_node_elm_t *elm, bool dependent)\n{\n\n\tif (dependent) {\n\t\t/*\n\t\t * Reading a val on behalf of a pointer to a valid allocation is\n\t\t * guaranteed to be a clean read even without synchronization,\n\t\t * because the rtree update became visible in memory before the\n\t\t * pointer came into existence.\n\t\t */\n\t\treturn (elm->val);\n\t} else {\n\t\t/*\n\t\t * An arbitrary read, e.g. on behalf of ivsalloc(), may not be\n\t\t * dependent on a previous rtree write, which means a stale read\n\t\t * could result if synchronization were omitted here.\n\t\t */\n\t\treturn (atomic_read_p(&elm->pun));\n\t}\n}\n\nJEMALLOC_INLINE void\nrtree_val_write(rtree_t *rtree, rtree_node_elm_t *elm, const extent_node_t *val)\n{\n\n\tatomic_write_p(&elm->pun, val);\n}\n\nJEMALLOC_INLINE rtree_node_elm_t *\nrtree_subtree_tryread(rtree_t *rtree, unsigned level)\n{\n\trtree_node_elm_t *subtree;\n\n\t/* Double-checked read (first read may be stale. */\n\tsubtree = rtree->levels[level].subtree;\n\tif (!rtree_node_valid(subtree))\n\t\tsubtree = atomic_read_p(&rtree->levels[level].subtree_pun);\n\treturn (subtree);\n}\n\nJEMALLOC_INLINE rtree_node_elm_t *\nrtree_subtree_read(rtree_t *rtree, unsigned level)\n{\n\trtree_node_elm_t *subtree;\n\n\tsubtree = rtree_subtree_tryread(rtree, level);\n\tif (unlikely(!rtree_node_valid(subtree)))\n\t\tsubtree = rtree_subtree_read_hard(rtree, level);\n\treturn (subtree);\n}\n\nJEMALLOC_INLINE extent_node_t *\nrtree_get(rtree_t *rtree, uintptr_t key, bool dependent)\n{\n\tuintptr_t subkey;\n\tunsigned i, start_level;\n\trtree_node_elm_t *node, *child;\n\n\tstart_level = rtree_start_level(rtree, key);\n\n\tfor (i = start_level, node = rtree_subtree_tryread(rtree, start_level);\n\t    /**/; i++, node = child) {\n\t\tif (!dependent && unlikely(!rtree_node_valid(node)))\n\t\t\treturn (NULL);\n\t\tsubkey = rtree_subkey(rtree, key, i);\n\t\tif (i == rtree->height - 1) {\n\t\t\t/*\n\t\t\t * node is a leaf, so it contains values rather than\n\t\t\t * child pointers.\n\t\t\t */\n\t\t\treturn (rtree_val_read(rtree, &node[subkey],\n\t\t\t    dependent));\n\t\t}\n\t\tassert(i < rtree->height - 1);\n\t\tchild = rtree_child_tryread(&node[subkey]);\n\t}\n\tnot_reached();\n}\n\nJEMALLOC_INLINE bool\nrtree_set(rtree_t *rtree, uintptr_t key, const extent_node_t *val)\n{\n\tuintptr_t subkey;\n\tunsigned i, start_level;\n\trtree_node_elm_t *node, *child;\n\n\tstart_level = rtree_start_level(rtree, key);\n\n\tnode = rtree_subtree_read(rtree, start_level);\n\tif (node == NULL)\n\t\treturn (true);\n\tfor (i = start_level; /**/; i++, node = child) {\n\t\tsubkey = rtree_subkey(rtree, key, i);\n\t\tif (i == rtree->height - 1) {\n\t\t\t/*\n\t\t\t * node is a leaf, so it contains values rather than\n\t\t\t * child pointers.\n\t\t\t */\n\t\t\trtree_val_write(rtree, &node[subkey], val);\n\t\t\treturn (false);\n\t\t}\n\t\tassert(i + 1 < rtree->height);\n\t\tchild = rtree_child_read(rtree, &node[subkey], i);\n\t\tif (child == NULL)\n\t\t\treturn (true);\n\t}\n\tnot_reached();\n}\n#endif\n\n#endif /* JEMALLOC_H_INLINES */\n/******************************************************************************/\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.8/deps/jemalloc/include/jemalloc/internal/size_classes.sh",
    "content": "#!/bin/sh\n#\n# Usage: size_classes.sh <lg_qarr> <lg_tmin> <lg_parr> <lg_g>\n\n# The following limits are chosen such that they cover all supported platforms.\n\n# Pointer sizes.\nlg_zarr=\"2 3\"\n\n# Quanta.\nlg_qarr=$1\n\n# The range of tiny size classes is [2^lg_tmin..2^(lg_q-1)].\nlg_tmin=$2\n\n# Maximum lookup size.\nlg_kmax=12\n\n# Page sizes.\nlg_parr=`echo $3 | tr ',' ' '`\n\n# Size class group size (number of size classes for each size doubling).\nlg_g=$4\n\npow2() {\n  e=$1\n  pow2_result=1\n  while [ ${e} -gt 0 ] ; do\n    pow2_result=$((${pow2_result} + ${pow2_result}))\n    e=$((${e} - 1))\n  done\n}\n\nlg() {\n  x=$1\n  lg_result=0\n  while [ ${x} -gt 1 ] ; do\n    lg_result=$((${lg_result} + 1))\n    x=$((${x} / 2))\n  done\n}\n\nsize_class() {\n  index=$1\n  lg_grp=$2\n  lg_delta=$3\n  ndelta=$4\n  lg_p=$5\n  lg_kmax=$6\n\n  lg ${ndelta}; lg_ndelta=${lg_result}; pow2 ${lg_ndelta}\n  if [ ${pow2_result} -lt ${ndelta} ] ; then\n    rem=\"yes\"\n  else\n    rem=\"no\"\n  fi\n\n  lg_size=${lg_grp}\n  if [ $((${lg_delta} + ${lg_ndelta})) -eq ${lg_grp} ] ; then\n    lg_size=$((${lg_grp} + 1))\n  else\n    lg_size=${lg_grp}\n    rem=\"yes\"\n  fi\n\n  if [ ${lg_size} -lt $((${lg_p} + ${lg_g})) ] ; then\n    bin=\"yes\"\n  else\n    bin=\"no\"\n  fi\n  if [ ${lg_size} -lt ${lg_kmax} \\\n      -o ${lg_size} -eq ${lg_kmax} -a ${rem} = \"no\" ] ; then\n    lg_delta_lookup=${lg_delta}\n  else\n    lg_delta_lookup=\"no\"\n  fi\n  printf '    SC(%3d, %6d, %8d, %6d, %3s, %2s) \\\\\\n' ${index} ${lg_grp} ${lg_delta} ${ndelta} ${bin} ${lg_delta_lookup}\n  # Defined upon return:\n  # - lg_delta_lookup (${lg_delta} or \"no\")\n  # - bin (\"yes\" or \"no\")\n}\n\nsep_line() {\n  echo \"                                               \\\\\"\n}\n\nsize_classes() {\n  lg_z=$1\n  lg_q=$2\n  lg_t=$3\n  lg_p=$4\n  lg_g=$5\n\n  pow2 $((${lg_z} + 3)); ptr_bits=${pow2_result}\n  pow2 ${lg_g}; g=${pow2_result}\n\n  echo \"#define\tSIZE_CLASSES \\\\\"\n  echo \"  /* index, lg_grp, lg_delta, ndelta, bin, lg_delta_lookup */ \\\\\"\n\n  ntbins=0\n  nlbins=0\n  lg_tiny_maxclass='\"NA\"'\n  nbins=0\n\n  # Tiny size classes.\n  ndelta=0\n  index=0\n  lg_grp=${lg_t}\n  lg_delta=${lg_grp}\n  while [ ${lg_grp} -lt ${lg_q} ] ; do\n    size_class ${index} ${lg_grp} ${lg_delta} ${ndelta} ${lg_p} ${lg_kmax}\n    if [ ${lg_delta_lookup} != \"no\" ] ; then\n      nlbins=$((${index} + 1))\n    fi\n    if [ ${bin} != \"no\" ] ; then\n      nbins=$((${index} + 1))\n    fi\n    ntbins=$((${ntbins} + 1))\n    lg_tiny_maxclass=${lg_grp} # Final written value is correct.\n    index=$((${index} + 1))\n    lg_delta=${lg_grp}\n    lg_grp=$((${lg_grp} + 1))\n  done\n\n  # First non-tiny group.\n  if [ ${ntbins} -gt 0 ] ; then\n    sep_line\n    # The first size class has an unusual encoding, because the size has to be\n    # split between grp and delta*ndelta.\n    lg_grp=$((${lg_grp} - 1))\n    ndelta=1\n    size_class ${index} ${lg_grp} ${lg_delta} ${ndelta} ${lg_p} ${lg_kmax}\n    index=$((${index} + 1))\n    lg_grp=$((${lg_grp} + 1))\n    lg_delta=$((${lg_delta} + 1))\n  fi\n  while [ ${ndelta} -lt ${g} ] ; do\n    size_class ${index} ${lg_grp} ${lg_delta} ${ndelta} ${lg_p} ${lg_kmax}\n    index=$((${index} + 1))\n    ndelta=$((${ndelta} + 1))\n  done\n\n  # All remaining groups.\n  lg_grp=$((${lg_grp} + ${lg_g}))\n  while [ ${lg_grp} -lt ${ptr_bits} ] ; do\n    sep_line\n    ndelta=1\n    if [ ${lg_grp} -eq $((${ptr_bits} - 1)) ] ; then\n      ndelta_limit=$((${g} - 1))\n    else\n      ndelta_limit=${g}\n    fi\n    while [ ${ndelta} -le ${ndelta_limit} ] ; do\n      size_class ${index} ${lg_grp} ${lg_delta} ${ndelta} ${lg_p} ${lg_kmax}\n      if [ ${lg_delta_lookup} != \"no\" ] ; then\n        nlbins=$((${index} + 1))\n        # Final written value is correct:\n        lookup_maxclass=\"((((size_t)1) << ${lg_grp}) + (((size_t)${ndelta}) << ${lg_delta}))\"\n      fi\n      if [ ${bin} != \"no\" ] ; then\n        nbins=$((${index} + 1))\n        # Final written value is correct:\n        small_maxclass=\"((((size_t)1) << ${lg_grp}) + (((size_t)${ndelta}) << ${lg_delta}))\"\n        if [ ${lg_g} -gt 0 ] ; then\n          lg_large_minclass=$((${lg_grp} + 1))\n        else\n          lg_large_minclass=$((${lg_grp} + 2))\n        fi\n      fi\n      # Final written value is correct:\n      huge_maxclass=\"((((size_t)1) << ${lg_grp}) + (((size_t)${ndelta}) << ${lg_delta}))\"\n      index=$((${index} + 1))\n      ndelta=$((${ndelta} + 1))\n    done\n    lg_grp=$((${lg_grp} + 1))\n    lg_delta=$((${lg_delta} + 1))\n  done\n  echo\n  nsizes=${index}\n\n  # Defined upon completion:\n  # - ntbins\n  # - nlbins\n  # - nbins\n  # - nsizes\n  # - lg_tiny_maxclass\n  # - lookup_maxclass\n  # - small_maxclass\n  # - lg_large_minclass\n  # - huge_maxclass\n}\n\ncat <<EOF\n/* This file was automatically generated by size_classes.sh. */\n/******************************************************************************/\n#ifdef JEMALLOC_H_TYPES\n\n/*\n * This header requires LG_SIZEOF_PTR, LG_TINY_MIN, LG_QUANTUM, and LG_PAGE to\n * be defined prior to inclusion, and it in turn defines:\n *\n *   LG_SIZE_CLASS_GROUP: Lg of size class count for each size doubling.\n *   SIZE_CLASSES: Complete table of\n *                 SC(index, lg_grp, lg_delta, ndelta, bin, lg_delta_lookup)\n *                 tuples.\n *     index: Size class index.\n *     lg_grp: Lg group base size (no deltas added).\n *     lg_delta: Lg delta to previous size class.\n *     ndelta: Delta multiplier.  size == 1<<lg_grp + ndelta<<lg_delta\n *     bin: 'yes' if a small bin size class, 'no' otherwise.\n *     lg_delta_lookup: Same as lg_delta if a lookup table size class, 'no'\n *                      otherwise.\n *   NTBINS: Number of tiny bins.\n *   NLBINS: Number of bins supported by the lookup table.\n *   NBINS: Number of small size class bins.\n *   NSIZES: Number of size classes.\n *   LG_TINY_MAXCLASS: Lg of maximum tiny size class.\n *   LOOKUP_MAXCLASS: Maximum size class included in lookup table.\n *   SMALL_MAXCLASS: Maximum small size class.\n *   LG_LARGE_MINCLASS: Lg of minimum large size class.\n *   HUGE_MAXCLASS: Maximum (huge) size class.\n */\n\n#define\tLG_SIZE_CLASS_GROUP\t${lg_g}\n\nEOF\n\nfor lg_z in ${lg_zarr} ; do\n  for lg_q in ${lg_qarr} ; do\n    lg_t=${lg_tmin}\n    while [ ${lg_t} -le ${lg_q} ] ; do\n      # Iterate through page sizes and compute how many bins there are.\n      for lg_p in ${lg_parr} ; do\n        echo \"#if (LG_SIZEOF_PTR == ${lg_z} && LG_TINY_MIN == ${lg_t} && LG_QUANTUM == ${lg_q} && LG_PAGE == ${lg_p})\"\n        size_classes ${lg_z} ${lg_q} ${lg_t} ${lg_p} ${lg_g}\n        echo \"#define\tSIZE_CLASSES_DEFINED\"\n        echo \"#define\tNTBINS\t\t\t${ntbins}\"\n        echo \"#define\tNLBINS\t\t\t${nlbins}\"\n        echo \"#define\tNBINS\t\t\t${nbins}\"\n        echo \"#define\tNSIZES\t\t\t${nsizes}\"\n        echo \"#define\tLG_TINY_MAXCLASS\t${lg_tiny_maxclass}\"\n        echo \"#define\tLOOKUP_MAXCLASS\t\t${lookup_maxclass}\"\n        echo \"#define\tSMALL_MAXCLASS\t\t${small_maxclass}\"\n        echo \"#define\tLG_LARGE_MINCLASS\t${lg_large_minclass}\"\n        echo \"#define\tHUGE_MAXCLASS\t\t${huge_maxclass}\"\n        echo \"#endif\"\n        echo\n      done\n      lg_t=$((${lg_t} + 1))\n    done\n  done\ndone\n\ncat <<EOF\n#ifndef SIZE_CLASSES_DEFINED\n#  error \"No size class definitions match configuration\"\n#endif\n#undef SIZE_CLASSES_DEFINED\n/*\n * The size2index_tab lookup table uses uint8_t to encode each bin index, so we\n * cannot support more than 256 small size classes.  Further constrain NBINS to\n * 255 since all small size classes, plus a \"not small\" size class must be\n * stored in 8 bits of arena_chunk_map_bits_t's bits field.\n */\n#if (NBINS > 255)\n#  error \"Too many small size classes\"\n#endif\n\n#endif /* JEMALLOC_H_TYPES */\n/******************************************************************************/\n#ifdef JEMALLOC_H_STRUCTS\n\n\n#endif /* JEMALLOC_H_STRUCTS */\n/******************************************************************************/\n#ifdef JEMALLOC_H_EXTERNS\n\n\n#endif /* JEMALLOC_H_EXTERNS */\n/******************************************************************************/\n#ifdef JEMALLOC_H_INLINES\n\n\n#endif /* JEMALLOC_H_INLINES */\n/******************************************************************************/\nEOF\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.8/deps/jemalloc/include/jemalloc/internal/stats.h",
    "content": "/******************************************************************************/\n#ifdef JEMALLOC_H_TYPES\n\ntypedef struct tcache_bin_stats_s tcache_bin_stats_t;\ntypedef struct malloc_bin_stats_s malloc_bin_stats_t;\ntypedef struct malloc_large_stats_s malloc_large_stats_t;\ntypedef struct malloc_huge_stats_s malloc_huge_stats_t;\ntypedef struct arena_stats_s arena_stats_t;\ntypedef struct chunk_stats_s chunk_stats_t;\n\n#endif /* JEMALLOC_H_TYPES */\n/******************************************************************************/\n#ifdef JEMALLOC_H_STRUCTS\n\nstruct tcache_bin_stats_s {\n\t/*\n\t * Number of allocation requests that corresponded to the size of this\n\t * bin.\n\t */\n\tuint64_t\tnrequests;\n};\n\nstruct malloc_bin_stats_s {\n\t/*\n\t * Total number of allocation/deallocation requests served directly by\n\t * the bin.  Note that tcache may allocate an object, then recycle it\n\t * many times, resulting many increments to nrequests, but only one\n\t * each to nmalloc and ndalloc.\n\t */\n\tuint64_t\tnmalloc;\n\tuint64_t\tndalloc;\n\n\t/*\n\t * Number of allocation requests that correspond to the size of this\n\t * bin.  This includes requests served by tcache, though tcache only\n\t * periodically merges into this counter.\n\t */\n\tuint64_t\tnrequests;\n\n\t/*\n\t * Current number of regions of this size class, including regions\n\t * currently cached by tcache.\n\t */\n\tsize_t\t\tcurregs;\n\n\t/* Number of tcache fills from this bin. */\n\tuint64_t\tnfills;\n\n\t/* Number of tcache flushes to this bin. */\n\tuint64_t\tnflushes;\n\n\t/* Total number of runs created for this bin's size class. */\n\tuint64_t\tnruns;\n\n\t/*\n\t * Total number of runs reused by extracting them from the runs tree for\n\t * this bin's size class.\n\t */\n\tuint64_t\treruns;\n\n\t/* Current number of runs in this bin. */\n\tsize_t\t\tcurruns;\n};\n\nstruct malloc_large_stats_s {\n\t/*\n\t * Total number of allocation/deallocation requests served directly by\n\t * the arena.  Note that tcache may allocate an object, then recycle it\n\t * many times, resulting many increments to nrequests, but only one\n\t * each to nmalloc and ndalloc.\n\t */\n\tuint64_t\tnmalloc;\n\tuint64_t\tndalloc;\n\n\t/*\n\t * Number of allocation requests that correspond to this size class.\n\t * This includes requests served by tcache, though tcache only\n\t * periodically merges into this counter.\n\t */\n\tuint64_t\tnrequests;\n\n\t/*\n\t * Current number of runs of this size class, including runs currently\n\t * cached by tcache.\n\t */\n\tsize_t\t\tcurruns;\n};\n\nstruct malloc_huge_stats_s {\n\t/*\n\t * Total number of allocation/deallocation requests served directly by\n\t * the arena.\n\t */\n\tuint64_t\tnmalloc;\n\tuint64_t\tndalloc;\n\n\t/* Current number of (multi-)chunk allocations of this size class. */\n\tsize_t\t\tcurhchunks;\n};\n\nstruct arena_stats_s {\n\t/* Number of bytes currently mapped. */\n\tsize_t\t\tmapped;\n\n\t/*\n\t * Total number of purge sweeps, total number of madvise calls made,\n\t * and total pages purged in order to keep dirty unused memory under\n\t * control.\n\t */\n\tuint64_t\tnpurge;\n\tuint64_t\tnmadvise;\n\tuint64_t\tpurged;\n\n\t/*\n\t * Number of bytes currently mapped purely for metadata purposes, and\n\t * number of bytes currently allocated for internal metadata.\n\t */\n\tsize_t\t\tmetadata_mapped;\n\tsize_t\t\tmetadata_allocated; /* Protected via atomic_*_z(). */\n\n\t/* Per-size-category statistics. */\n\tsize_t\t\tallocated_large;\n\tuint64_t\tnmalloc_large;\n\tuint64_t\tndalloc_large;\n\tuint64_t\tnrequests_large;\n\n\tsize_t\t\tallocated_huge;\n\tuint64_t\tnmalloc_huge;\n\tuint64_t\tndalloc_huge;\n\n\t/* One element for each large size class. */\n\tmalloc_large_stats_t\t*lstats;\n\n\t/* One element for each huge size class. */\n\tmalloc_huge_stats_t\t*hstats;\n};\n\n#endif /* JEMALLOC_H_STRUCTS */\n/******************************************************************************/\n#ifdef JEMALLOC_H_EXTERNS\n\nextern bool\topt_stats_print;\n\nextern size_t\tstats_cactive;\n\nvoid\tstats_print(void (*write)(void *, const char *), void *cbopaque,\n    const char *opts);\n\n#endif /* JEMALLOC_H_EXTERNS */\n/******************************************************************************/\n#ifdef JEMALLOC_H_INLINES\n\n#ifndef JEMALLOC_ENABLE_INLINE\nsize_t\tstats_cactive_get(void);\nvoid\tstats_cactive_add(size_t size);\nvoid\tstats_cactive_sub(size_t size);\n#endif\n\n#if (defined(JEMALLOC_ENABLE_INLINE) || defined(JEMALLOC_STATS_C_))\nJEMALLOC_INLINE size_t\nstats_cactive_get(void)\n{\n\n\treturn (atomic_read_z(&stats_cactive));\n}\n\nJEMALLOC_INLINE void\nstats_cactive_add(size_t size)\n{\n\n\tatomic_add_z(&stats_cactive, size);\n}\n\nJEMALLOC_INLINE void\nstats_cactive_sub(size_t size)\n{\n\n\tatomic_sub_z(&stats_cactive, size);\n}\n#endif\n\n#endif /* JEMALLOC_H_INLINES */\n/******************************************************************************/\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.8/deps/jemalloc/include/jemalloc/internal/tcache.h",
    "content": "/******************************************************************************/\n#ifdef JEMALLOC_H_TYPES\n\ntypedef struct tcache_bin_info_s tcache_bin_info_t;\ntypedef struct tcache_bin_s tcache_bin_t;\ntypedef struct tcache_s tcache_t;\ntypedef struct tcaches_s tcaches_t;\n\n/*\n * tcache pointers close to NULL are used to encode state information that is\n * used for two purposes: preventing thread caching on a per thread basis and\n * cleaning up during thread shutdown.\n */\n#define\tTCACHE_STATE_DISABLED\t\t((tcache_t *)(uintptr_t)1)\n#define\tTCACHE_STATE_REINCARNATED\t((tcache_t *)(uintptr_t)2)\n#define\tTCACHE_STATE_PURGATORY\t\t((tcache_t *)(uintptr_t)3)\n#define\tTCACHE_STATE_MAX\t\tTCACHE_STATE_PURGATORY\n\n/*\n * Absolute minimum number of cache slots for each small bin.\n */\n#define\tTCACHE_NSLOTS_SMALL_MIN\t\t20\n\n/*\n * Absolute maximum number of cache slots for each small bin in the thread\n * cache.  This is an additional constraint beyond that imposed as: twice the\n * number of regions per run for this size class.\n *\n * This constant must be an even number.\n */\n#define\tTCACHE_NSLOTS_SMALL_MAX\t\t200\n\n/* Number of cache slots for large size classes. */\n#define\tTCACHE_NSLOTS_LARGE\t\t20\n\n/* (1U << opt_lg_tcache_max) is used to compute tcache_maxclass. */\n#define\tLG_TCACHE_MAXCLASS_DEFAULT\t15\n\n/*\n * TCACHE_GC_SWEEP is the approximate number of allocation events between\n * full GC sweeps.  Integer rounding may cause the actual number to be\n * slightly higher, since GC is performed incrementally.\n */\n#define\tTCACHE_GC_SWEEP\t\t\t8192\n\n/* Number of tcache allocation/deallocation events between incremental GCs. */\n#define\tTCACHE_GC_INCR\t\t\t\t\t\t\t\\\n    ((TCACHE_GC_SWEEP / NBINS) + ((TCACHE_GC_SWEEP / NBINS == 0) ? 0 : 1))\n\n#endif /* JEMALLOC_H_TYPES */\n/******************************************************************************/\n#ifdef JEMALLOC_H_STRUCTS\n\ntypedef enum {\n\ttcache_enabled_false   = 0, /* Enable cast to/from bool. */\n\ttcache_enabled_true    = 1,\n\ttcache_enabled_default = 2\n} tcache_enabled_t;\n\n/*\n * Read-only information associated with each element of tcache_t's tbins array\n * is stored separately, mainly to reduce memory usage.\n */\nstruct tcache_bin_info_s {\n\tunsigned\tncached_max;\t/* Upper limit on ncached. */\n};\n\nstruct tcache_bin_s {\n\ttcache_bin_stats_t tstats;\n\tint\t\tlow_water;\t/* Min # cached since last GC. */\n\tunsigned\tlg_fill_div;\t/* Fill (ncached_max >> lg_fill_div). */\n\tunsigned\tncached;\t/* # of cached objects. */\n\tvoid\t\t**avail;\t/* Stack of available objects. */\n};\n\nstruct tcache_s {\n\tql_elm(tcache_t) link;\t\t/* Used for aggregating stats. */\n\tuint64_t\tprof_accumbytes;/* Cleared after arena_prof_accum(). */\n\tunsigned\tev_cnt;\t\t/* Event count since incremental GC. */\n\tszind_t\t\tnext_gc_bin;\t/* Next bin to GC. */\n\ttcache_bin_t\ttbins[1];\t/* Dynamically sized. */\n\t/*\n\t * The pointer stacks associated with tbins follow as a contiguous\n\t * array.  During tcache initialization, the avail pointer in each\n\t * element of tbins is initialized to point to the proper offset within\n\t * this array.\n\t */\n};\n\n/* Linkage for list of available (previously used) explicit tcache IDs. */\nstruct tcaches_s {\n\tunion {\n\t\ttcache_t\t*tcache;\n\t\ttcaches_t\t*next;\n\t};\n};\n\n#endif /* JEMALLOC_H_STRUCTS */\n/******************************************************************************/\n#ifdef JEMALLOC_H_EXTERNS\n\nextern bool\topt_tcache;\nextern ssize_t\topt_lg_tcache_max;\n\nextern tcache_bin_info_t\t*tcache_bin_info;\n\n/*\n * Number of tcache bins.  There are NBINS small-object bins, plus 0 or more\n * large-object bins.\n */\nextern size_t\tnhbins;\n\n/* Maximum cached size class. */\nextern size_t\ttcache_maxclass;\n\n/*\n * Explicit tcaches, managed via the tcache.{create,flush,destroy} mallctls and\n * usable via the MALLOCX_TCACHE() flag.  The automatic per thread tcaches are\n * completely disjoint from this data structure.  tcaches starts off as a sparse\n * array, so it has no physical memory footprint until individual pages are\n * touched.  This allows the entire array to be allocated the first time an\n * explicit tcache is created without a disproportionate impact on memory usage.\n */\nextern tcaches_t\t*tcaches;\n\nsize_t\ttcache_salloc(const void *ptr);\nvoid\ttcache_event_hard(tsd_t *tsd, tcache_t *tcache);\nvoid\t*tcache_alloc_small_hard(tsd_t *tsd, arena_t *arena, tcache_t *tcache,\n    tcache_bin_t *tbin, szind_t binind);\nvoid\ttcache_bin_flush_small(tsd_t *tsd, tcache_t *tcache, tcache_bin_t *tbin,\n    szind_t binind, unsigned rem);\nvoid\ttcache_bin_flush_large(tsd_t *tsd, tcache_bin_t *tbin, szind_t binind,\n    unsigned rem, tcache_t *tcache);\nvoid\ttcache_arena_associate(tcache_t *tcache, arena_t *arena);\nvoid\ttcache_arena_reassociate(tcache_t *tcache, arena_t *oldarena,\n    arena_t *newarena);\nvoid\ttcache_arena_dissociate(tcache_t *tcache, arena_t *arena);\ntcache_t *tcache_get_hard(tsd_t *tsd);\ntcache_t *tcache_create(tsd_t *tsd, arena_t *arena);\nvoid\ttcache_cleanup(tsd_t *tsd);\nvoid\ttcache_enabled_cleanup(tsd_t *tsd);\nvoid\ttcache_stats_merge(tcache_t *tcache, arena_t *arena);\nbool\ttcaches_create(tsd_t *tsd, unsigned *r_ind);\nvoid\ttcaches_flush(tsd_t *tsd, unsigned ind);\nvoid\ttcaches_destroy(tsd_t *tsd, unsigned ind);\nbool\ttcache_boot(void);\n\n#endif /* JEMALLOC_H_EXTERNS */\n/******************************************************************************/\n#ifdef JEMALLOC_H_INLINES\n\n#ifndef JEMALLOC_ENABLE_INLINE\nvoid\ttcache_event(tsd_t *tsd, tcache_t *tcache);\nvoid\ttcache_flush(void);\nbool\ttcache_enabled_get(void);\ntcache_t *tcache_get(tsd_t *tsd, bool create);\nvoid\ttcache_enabled_set(bool enabled);\nvoid\t*tcache_alloc_easy(tcache_bin_t *tbin);\nvoid\t*tcache_alloc_small(tsd_t *tsd, arena_t *arena, tcache_t *tcache,\n    size_t size, bool zero);\nvoid\t*tcache_alloc_large(tsd_t *tsd, arena_t *arena, tcache_t *tcache,\n    size_t size, bool zero);\nvoid\ttcache_dalloc_small(tsd_t *tsd, tcache_t *tcache, void *ptr,\n    szind_t binind);\nvoid\ttcache_dalloc_large(tsd_t *tsd, tcache_t *tcache, void *ptr,\n    size_t size);\ntcache_t\t*tcaches_get(tsd_t *tsd, unsigned ind);\n#endif\n\n#if (defined(JEMALLOC_ENABLE_INLINE) || defined(JEMALLOC_TCACHE_C_))\nJEMALLOC_INLINE void\ntcache_flush(void)\n{\n\ttsd_t *tsd;\n\n\tcassert(config_tcache);\n\n\ttsd = tsd_fetch();\n\ttcache_cleanup(tsd);\n}\n\nJEMALLOC_INLINE bool\ntcache_enabled_get(void)\n{\n\ttsd_t *tsd;\n\ttcache_enabled_t tcache_enabled;\n\n\tcassert(config_tcache);\n\n\ttsd = tsd_fetch();\n\ttcache_enabled = tsd_tcache_enabled_get(tsd);\n\tif (tcache_enabled == tcache_enabled_default) {\n\t\ttcache_enabled = (tcache_enabled_t)opt_tcache;\n\t\ttsd_tcache_enabled_set(tsd, tcache_enabled);\n\t}\n\n\treturn ((bool)tcache_enabled);\n}\n\nJEMALLOC_INLINE void\ntcache_enabled_set(bool enabled)\n{\n\ttsd_t *tsd;\n\ttcache_enabled_t tcache_enabled;\n\n\tcassert(config_tcache);\n\n\ttsd = tsd_fetch();\n\n\ttcache_enabled = (tcache_enabled_t)enabled;\n\ttsd_tcache_enabled_set(tsd, tcache_enabled);\n\n\tif (!enabled)\n\t\ttcache_cleanup(tsd);\n}\n\nJEMALLOC_ALWAYS_INLINE tcache_t *\ntcache_get(tsd_t *tsd, bool create)\n{\n\ttcache_t *tcache;\n\n\tif (!config_tcache)\n\t\treturn (NULL);\n\n\ttcache = tsd_tcache_get(tsd);\n\tif (!create)\n\t\treturn (tcache);\n\tif (unlikely(tcache == NULL) && tsd_nominal(tsd)) {\n\t\ttcache = tcache_get_hard(tsd);\n\t\ttsd_tcache_set(tsd, tcache);\n\t}\n\n\treturn (tcache);\n}\n\nJEMALLOC_ALWAYS_INLINE void\ntcache_event(tsd_t *tsd, tcache_t *tcache)\n{\n\n\tif (TCACHE_GC_INCR == 0)\n\t\treturn;\n\n\ttcache->ev_cnt++;\n\tassert(tcache->ev_cnt <= TCACHE_GC_INCR);\n\tif (unlikely(tcache->ev_cnt == TCACHE_GC_INCR))\n\t\ttcache_event_hard(tsd, tcache);\n}\n\nJEMALLOC_ALWAYS_INLINE void *\ntcache_alloc_easy(tcache_bin_t *tbin)\n{\n\tvoid *ret;\n\n\tif (unlikely(tbin->ncached == 0)) {\n\t\ttbin->low_water = -1;\n\t\treturn (NULL);\n\t}\n\ttbin->ncached--;\n\tif (unlikely((int)tbin->ncached < tbin->low_water))\n\t\ttbin->low_water = tbin->ncached;\n\tret = tbin->avail[tbin->ncached];\n\treturn (ret);\n}\n\nJEMALLOC_ALWAYS_INLINE void *\ntcache_alloc_small(tsd_t *tsd, arena_t *arena, tcache_t *tcache, size_t size,\n    bool zero)\n{\n\tvoid *ret;\n\tszind_t binind;\n\tsize_t usize;\n\ttcache_bin_t *tbin;\n\n\tbinind = size2index(size);\n\tassert(binind < NBINS);\n\ttbin = &tcache->tbins[binind];\n\tusize = index2size(binind);\n\tret = tcache_alloc_easy(tbin);\n\tif (unlikely(ret == NULL)) {\n\t\tret = tcache_alloc_small_hard(tsd, arena, tcache, tbin, binind);\n\t\tif (ret == NULL)\n\t\t\treturn (NULL);\n\t}\n\tassert(tcache_salloc(ret) == usize);\n\n\tif (likely(!zero)) {\n\t\tif (config_fill) {\n\t\t\tif (unlikely(opt_junk_alloc)) {\n\t\t\t\tarena_alloc_junk_small(ret,\n\t\t\t\t    &arena_bin_info[binind], false);\n\t\t\t} else if (unlikely(opt_zero))\n\t\t\t\tmemset(ret, 0, usize);\n\t\t}\n\t} else {\n\t\tif (config_fill && unlikely(opt_junk_alloc)) {\n\t\t\tarena_alloc_junk_small(ret, &arena_bin_info[binind],\n\t\t\t    true);\n\t\t}\n\t\tmemset(ret, 0, usize);\n\t}\n\n\tif (config_stats)\n\t\ttbin->tstats.nrequests++;\n\tif (config_prof)\n\t\ttcache->prof_accumbytes += usize;\n\ttcache_event(tsd, tcache);\n\treturn (ret);\n}\n\nJEMALLOC_ALWAYS_INLINE void *\ntcache_alloc_large(tsd_t *tsd, arena_t *arena, tcache_t *tcache, size_t size,\n    bool zero)\n{\n\tvoid *ret;\n\tszind_t binind;\n\tsize_t usize;\n\ttcache_bin_t *tbin;\n\n\tbinind = size2index(size);\n\tusize = index2size(binind);\n\tassert(usize <= tcache_maxclass);\n\tassert(binind < nhbins);\n\ttbin = &tcache->tbins[binind];\n\tret = tcache_alloc_easy(tbin);\n\tif (unlikely(ret == NULL)) {\n\t\t/*\n\t\t * Only allocate one large object at a time, because it's quite\n\t\t * expensive to create one and not use it.\n\t\t */\n\t\tret = arena_malloc_large(arena, usize, zero);\n\t\tif (ret == NULL)\n\t\t\treturn (NULL);\n\t} else {\n\t\tif (config_prof && usize == LARGE_MINCLASS) {\n\t\t\tarena_chunk_t *chunk =\n\t\t\t    (arena_chunk_t *)CHUNK_ADDR2BASE(ret);\n\t\t\tsize_t pageind = (((uintptr_t)ret - (uintptr_t)chunk) >>\n\t\t\t    LG_PAGE);\n\t\t\tarena_mapbits_large_binind_set(chunk, pageind,\n\t\t\t    BININD_INVALID);\n\t\t}\n\t\tif (likely(!zero)) {\n\t\t\tif (config_fill) {\n\t\t\t\tif (unlikely(opt_junk_alloc))\n\t\t\t\t\tmemset(ret, 0xa5, usize);\n\t\t\t\telse if (unlikely(opt_zero))\n\t\t\t\t\tmemset(ret, 0, usize);\n\t\t\t}\n\t\t} else\n\t\t\tmemset(ret, 0, usize);\n\n\t\tif (config_stats)\n\t\t\ttbin->tstats.nrequests++;\n\t\tif (config_prof)\n\t\t\ttcache->prof_accumbytes += usize;\n\t}\n\n\ttcache_event(tsd, tcache);\n\treturn (ret);\n}\n\nJEMALLOC_ALWAYS_INLINE void\ntcache_dalloc_small(tsd_t *tsd, tcache_t *tcache, void *ptr, szind_t binind)\n{\n\ttcache_bin_t *tbin;\n\ttcache_bin_info_t *tbin_info;\n\n\tassert(tcache_salloc(ptr) <= SMALL_MAXCLASS);\n\n\tif (config_fill && unlikely(opt_junk_free))\n\t\tarena_dalloc_junk_small(ptr, &arena_bin_info[binind]);\n\n\ttbin = &tcache->tbins[binind];\n\ttbin_info = &tcache_bin_info[binind];\n\tif (unlikely(tbin->ncached == tbin_info->ncached_max)) {\n\t\ttcache_bin_flush_small(tsd, tcache, tbin, binind,\n\t\t    (tbin_info->ncached_max >> 1));\n\t}\n\tassert(tbin->ncached < tbin_info->ncached_max);\n\ttbin->avail[tbin->ncached] = ptr;\n\ttbin->ncached++;\n\n\ttcache_event(tsd, tcache);\n}\n\nJEMALLOC_ALWAYS_INLINE void\ntcache_dalloc_large(tsd_t *tsd, tcache_t *tcache, void *ptr, size_t size)\n{\n\tszind_t binind;\n\ttcache_bin_t *tbin;\n\ttcache_bin_info_t *tbin_info;\n\n\tassert((size & PAGE_MASK) == 0);\n\tassert(tcache_salloc(ptr) > SMALL_MAXCLASS);\n\tassert(tcache_salloc(ptr) <= tcache_maxclass);\n\n\tbinind = size2index(size);\n\n\tif (config_fill && unlikely(opt_junk_free))\n\t\tarena_dalloc_junk_large(ptr, size);\n\n\ttbin = &tcache->tbins[binind];\n\ttbin_info = &tcache_bin_info[binind];\n\tif (unlikely(tbin->ncached == tbin_info->ncached_max)) {\n\t\ttcache_bin_flush_large(tsd, tbin, binind,\n\t\t    (tbin_info->ncached_max >> 1), tcache);\n\t}\n\tassert(tbin->ncached < tbin_info->ncached_max);\n\ttbin->avail[tbin->ncached] = ptr;\n\ttbin->ncached++;\n\n\ttcache_event(tsd, tcache);\n}\n\nJEMALLOC_ALWAYS_INLINE tcache_t *\ntcaches_get(tsd_t *tsd, unsigned ind)\n{\n\ttcaches_t *elm = &tcaches[ind];\n\tif (unlikely(elm->tcache == NULL))\n\t\telm->tcache = tcache_create(tsd, arena_choose(tsd, NULL));\n\treturn (elm->tcache);\n}\n#endif\n\n#endif /* JEMALLOC_H_INLINES */\n/******************************************************************************/\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.8/deps/jemalloc/include/jemalloc/internal/tsd.h",
    "content": "/******************************************************************************/\n#ifdef JEMALLOC_H_TYPES\n\n/* Maximum number of malloc_tsd users with cleanup functions. */\n#define\tMALLOC_TSD_CLEANUPS_MAX\t2\n\ntypedef bool (*malloc_tsd_cleanup_t)(void);\n\n#if (!defined(JEMALLOC_MALLOC_THREAD_CLEANUP) && !defined(JEMALLOC_TLS) && \\\n    !defined(_WIN32))\ntypedef struct tsd_init_block_s tsd_init_block_t;\ntypedef struct tsd_init_head_s tsd_init_head_t;\n#endif\n\ntypedef struct tsd_s tsd_t;\n\ntypedef enum {\n\ttsd_state_uninitialized,\n\ttsd_state_nominal,\n\ttsd_state_purgatory,\n\ttsd_state_reincarnated\n} tsd_state_t;\n\n/*\n * TLS/TSD-agnostic macro-based implementation of thread-specific data.  There\n * are five macros that support (at least) three use cases: file-private,\n * library-private, and library-private inlined.  Following is an example\n * library-private tsd variable:\n *\n * In example.h:\n *   typedef struct {\n *           int x;\n *           int y;\n *   } example_t;\n *   #define EX_INITIALIZER JEMALLOC_CONCAT({0, 0})\n *   malloc_tsd_types(example_, example_t)\n *   malloc_tsd_protos(, example_, example_t)\n *   malloc_tsd_externs(example_, example_t)\n * In example.c:\n *   malloc_tsd_data(, example_, example_t, EX_INITIALIZER)\n *   malloc_tsd_funcs(, example_, example_t, EX_INITIALIZER,\n *       example_tsd_cleanup)\n *\n * The result is a set of generated functions, e.g.:\n *\n *   bool example_tsd_boot(void) {...}\n *   example_t *example_tsd_get() {...}\n *   void example_tsd_set(example_t *val) {...}\n *\n * Note that all of the functions deal in terms of (a_type *) rather than\n * (a_type) so that it is possible to support non-pointer types (unlike\n * pthreads TSD).  example_tsd_cleanup() is passed an (a_type *) pointer that is\n * cast to (void *).  This means that the cleanup function needs to cast the\n * function argument to (a_type *), then dereference the resulting pointer to\n * access fields, e.g.\n *\n *   void\n *   example_tsd_cleanup(void *arg)\n *   {\n *           example_t *example = (example_t *)arg;\n *\n *           example->x = 42;\n *           [...]\n *           if ([want the cleanup function to be called again])\n *                   example_tsd_set(example);\n *   }\n *\n * If example_tsd_set() is called within example_tsd_cleanup(), it will be\n * called again.  This is similar to how pthreads TSD destruction works, except\n * that pthreads only calls the cleanup function again if the value was set to\n * non-NULL.\n */\n\n/* malloc_tsd_types(). */\n#ifdef JEMALLOC_MALLOC_THREAD_CLEANUP\n#define\tmalloc_tsd_types(a_name, a_type)\n#elif (defined(JEMALLOC_TLS))\n#define\tmalloc_tsd_types(a_name, a_type)\n#elif (defined(_WIN32))\n#define\tmalloc_tsd_types(a_name, a_type)\t\t\t\t\\\ntypedef struct {\t\t\t\t\t\t\t\\\n\tbool\tinitialized;\t\t\t\t\t\t\\\n\ta_type\tval;\t\t\t\t\t\t\t\\\n} a_name##tsd_wrapper_t;\n#else\n#define\tmalloc_tsd_types(a_name, a_type)\t\t\t\t\\\ntypedef struct {\t\t\t\t\t\t\t\\\n\tbool\tinitialized;\t\t\t\t\t\t\\\n\ta_type\tval;\t\t\t\t\t\t\t\\\n} a_name##tsd_wrapper_t;\n#endif\n\n/* malloc_tsd_protos(). */\n#define\tmalloc_tsd_protos(a_attr, a_name, a_type)\t\t\t\\\na_attr bool\t\t\t\t\t\t\t\t\\\na_name##tsd_boot0(void);\t\t\t\t\t\t\\\na_attr void\t\t\t\t\t\t\t\t\\\na_name##tsd_boot1(void);\t\t\t\t\t\t\\\na_attr bool\t\t\t\t\t\t\t\t\\\na_name##tsd_boot(void);\t\t\t\t\t\t\t\\\na_attr a_type *\t\t\t\t\t\t\t\t\\\na_name##tsd_get(void);\t\t\t\t\t\t\t\\\na_attr void\t\t\t\t\t\t\t\t\\\na_name##tsd_set(a_type *val);\n\n/* malloc_tsd_externs(). */\n#ifdef JEMALLOC_MALLOC_THREAD_CLEANUP\n#define\tmalloc_tsd_externs(a_name, a_type)\t\t\t\t\\\nextern __thread a_type\ta_name##tsd_tls;\t\t\t\t\\\nextern __thread bool\ta_name##tsd_initialized;\t\t\t\\\nextern bool\t\ta_name##tsd_booted;\n#elif (defined(JEMALLOC_TLS))\n#define\tmalloc_tsd_externs(a_name, a_type)\t\t\t\t\\\nextern __thread a_type\ta_name##tsd_tls;\t\t\t\t\\\nextern pthread_key_t\ta_name##tsd_tsd;\t\t\t\t\\\nextern bool\t\ta_name##tsd_booted;\n#elif (defined(_WIN32))\n#define\tmalloc_tsd_externs(a_name, a_type)\t\t\t\t\\\nextern DWORD\t\ta_name##tsd_tsd;\t\t\t\t\\\nextern a_name##tsd_wrapper_t\ta_name##tsd_boot_wrapper;\t\t\\\nextern bool\t\ta_name##tsd_booted;\n#else\n#define\tmalloc_tsd_externs(a_name, a_type)\t\t\t\t\\\nextern pthread_key_t\ta_name##tsd_tsd;\t\t\t\t\\\nextern tsd_init_head_t\ta_name##tsd_init_head;\t\t\t\t\\\nextern a_name##tsd_wrapper_t\ta_name##tsd_boot_wrapper;\t\t\\\nextern bool\t\ta_name##tsd_booted;\n#endif\n\n/* malloc_tsd_data(). */\n#ifdef JEMALLOC_MALLOC_THREAD_CLEANUP\n#define\tmalloc_tsd_data(a_attr, a_name, a_type, a_initializer)\t\t\\\na_attr __thread a_type JEMALLOC_TLS_MODEL\t\t\t\t\\\n    a_name##tsd_tls = a_initializer;\t\t\t\t\t\\\na_attr __thread bool JEMALLOC_TLS_MODEL\t\t\t\t\t\\\n    a_name##tsd_initialized = false;\t\t\t\t\t\\\na_attr bool\t\ta_name##tsd_booted = false;\n#elif (defined(JEMALLOC_TLS))\n#define\tmalloc_tsd_data(a_attr, a_name, a_type, a_initializer)\t\t\\\na_attr __thread a_type JEMALLOC_TLS_MODEL\t\t\t\t\\\n    a_name##tsd_tls = a_initializer;\t\t\t\t\t\\\na_attr pthread_key_t\ta_name##tsd_tsd;\t\t\t\t\\\na_attr bool\t\ta_name##tsd_booted = false;\n#elif (defined(_WIN32))\n#define\tmalloc_tsd_data(a_attr, a_name, a_type, a_initializer)\t\t\\\na_attr DWORD\t\ta_name##tsd_tsd;\t\t\t\t\\\na_attr a_name##tsd_wrapper_t a_name##tsd_boot_wrapper = {\t\t\\\n\tfalse,\t\t\t\t\t\t\t\t\\\n\ta_initializer\t\t\t\t\t\t\t\\\n};\t\t\t\t\t\t\t\t\t\\\na_attr bool\t\ta_name##tsd_booted = false;\n#else\n#define\tmalloc_tsd_data(a_attr, a_name, a_type, a_initializer)\t\t\\\na_attr pthread_key_t\ta_name##tsd_tsd;\t\t\t\t\\\na_attr tsd_init_head_t\ta_name##tsd_init_head = {\t\t\t\\\n\tql_head_initializer(blocks),\t\t\t\t\t\\\n\tMALLOC_MUTEX_INITIALIZER\t\t\t\t\t\\\n};\t\t\t\t\t\t\t\t\t\\\na_attr a_name##tsd_wrapper_t a_name##tsd_boot_wrapper = {\t\t\\\n\tfalse,\t\t\t\t\t\t\t\t\\\n\ta_initializer\t\t\t\t\t\t\t\\\n};\t\t\t\t\t\t\t\t\t\\\na_attr bool\t\ta_name##tsd_booted = false;\n#endif\n\n/* malloc_tsd_funcs(). */\n#ifdef JEMALLOC_MALLOC_THREAD_CLEANUP\n#define\tmalloc_tsd_funcs(a_attr, a_name, a_type, a_initializer,\t\t\\\n    a_cleanup)\t\t\t\t\t\t\t\t\\\n/* Initialization/cleanup. */\t\t\t\t\t\t\\\na_attr bool\t\t\t\t\t\t\t\t\\\na_name##tsd_cleanup_wrapper(void)\t\t\t\t\t\\\n{\t\t\t\t\t\t\t\t\t\\\n\t\t\t\t\t\t\t\t\t\\\n\tif (a_name##tsd_initialized) {\t\t\t\t\t\\\n\t\ta_name##tsd_initialized = false;\t\t\t\\\n\t\ta_cleanup(&a_name##tsd_tls);\t\t\t\t\\\n\t}\t\t\t\t\t\t\t\t\\\n\treturn (a_name##tsd_initialized);\t\t\t\t\\\n}\t\t\t\t\t\t\t\t\t\\\na_attr bool\t\t\t\t\t\t\t\t\\\na_name##tsd_boot0(void)\t\t\t\t\t\t\t\\\n{\t\t\t\t\t\t\t\t\t\\\n\t\t\t\t\t\t\t\t\t\\\n\tif (a_cleanup != malloc_tsd_no_cleanup) {\t\t\t\\\n\t\tmalloc_tsd_cleanup_register(\t\t\t\t\\\n\t\t    &a_name##tsd_cleanup_wrapper);\t\t\t\\\n\t}\t\t\t\t\t\t\t\t\\\n\ta_name##tsd_booted = true;\t\t\t\t\t\\\n\treturn (false);\t\t\t\t\t\t\t\\\n}\t\t\t\t\t\t\t\t\t\\\na_attr void\t\t\t\t\t\t\t\t\\\na_name##tsd_boot1(void)\t\t\t\t\t\t\t\\\n{\t\t\t\t\t\t\t\t\t\\\n\t\t\t\t\t\t\t\t\t\\\n\t/* Do nothing. */\t\t\t\t\t\t\\\n}\t\t\t\t\t\t\t\t\t\\\na_attr bool\t\t\t\t\t\t\t\t\\\na_name##tsd_boot(void)\t\t\t\t\t\t\t\\\n{\t\t\t\t\t\t\t\t\t\\\n\t\t\t\t\t\t\t\t\t\\\n\treturn (a_name##tsd_boot0());\t\t\t\t\t\\\n}\t\t\t\t\t\t\t\t\t\\\n/* Get/set. */\t\t\t\t\t\t\t\t\\\na_attr a_type *\t\t\t\t\t\t\t\t\\\na_name##tsd_get(void)\t\t\t\t\t\t\t\\\n{\t\t\t\t\t\t\t\t\t\\\n\t\t\t\t\t\t\t\t\t\\\n\tassert(a_name##tsd_booted);\t\t\t\t\t\\\n\treturn (&a_name##tsd_tls);\t\t\t\t\t\\\n}\t\t\t\t\t\t\t\t\t\\\na_attr void\t\t\t\t\t\t\t\t\\\na_name##tsd_set(a_type *val)\t\t\t\t\t\t\\\n{\t\t\t\t\t\t\t\t\t\\\n\t\t\t\t\t\t\t\t\t\\\n\tassert(a_name##tsd_booted);\t\t\t\t\t\\\n\ta_name##tsd_tls = (*val);\t\t\t\t\t\\\n\tif (a_cleanup != malloc_tsd_no_cleanup)\t\t\t\t\\\n\t\ta_name##tsd_initialized = true;\t\t\t\t\\\n}\n#elif (defined(JEMALLOC_TLS))\n#define\tmalloc_tsd_funcs(a_attr, a_name, a_type, a_initializer,\t\t\\\n    a_cleanup)\t\t\t\t\t\t\t\t\\\n/* Initialization/cleanup. */\t\t\t\t\t\t\\\na_attr bool\t\t\t\t\t\t\t\t\\\na_name##tsd_boot0(void)\t\t\t\t\t\t\t\\\n{\t\t\t\t\t\t\t\t\t\\\n\t\t\t\t\t\t\t\t\t\\\n\tif (a_cleanup != malloc_tsd_no_cleanup) {\t\t\t\\\n\t\tif (pthread_key_create(&a_name##tsd_tsd, a_cleanup) !=\t\\\n\t\t    0)\t\t\t\t\t\t\t\\\n\t\t\treturn (true);\t\t\t\t\t\\\n\t}\t\t\t\t\t\t\t\t\\\n\ta_name##tsd_booted = true;\t\t\t\t\t\\\n\treturn (false);\t\t\t\t\t\t\t\\\n}\t\t\t\t\t\t\t\t\t\\\na_attr void\t\t\t\t\t\t\t\t\\\na_name##tsd_boot1(void)\t\t\t\t\t\t\t\\\n{\t\t\t\t\t\t\t\t\t\\\n\t\t\t\t\t\t\t\t\t\\\n\t/* Do nothing. */\t\t\t\t\t\t\\\n}\t\t\t\t\t\t\t\t\t\\\na_attr bool\t\t\t\t\t\t\t\t\\\na_name##tsd_boot(void)\t\t\t\t\t\t\t\\\n{\t\t\t\t\t\t\t\t\t\\\n\t\t\t\t\t\t\t\t\t\\\n\treturn (a_name##tsd_boot0());\t\t\t\t\t\\\n}\t\t\t\t\t\t\t\t\t\\\n/* Get/set. */\t\t\t\t\t\t\t\t\\\na_attr a_type *\t\t\t\t\t\t\t\t\\\na_name##tsd_get(void)\t\t\t\t\t\t\t\\\n{\t\t\t\t\t\t\t\t\t\\\n\t\t\t\t\t\t\t\t\t\\\n\tassert(a_name##tsd_booted);\t\t\t\t\t\\\n\treturn (&a_name##tsd_tls);\t\t\t\t\t\\\n}\t\t\t\t\t\t\t\t\t\\\na_attr void\t\t\t\t\t\t\t\t\\\na_name##tsd_set(a_type *val)\t\t\t\t\t\t\\\n{\t\t\t\t\t\t\t\t\t\\\n\t\t\t\t\t\t\t\t\t\\\n\tassert(a_name##tsd_booted);\t\t\t\t\t\\\n\ta_name##tsd_tls = (*val);\t\t\t\t\t\\\n\tif (a_cleanup != malloc_tsd_no_cleanup) {\t\t\t\\\n\t\tif (pthread_setspecific(a_name##tsd_tsd,\t\t\\\n\t\t    (void *)(&a_name##tsd_tls))) {\t\t\t\\\n\t\t\tmalloc_write(\"<jemalloc>: Error\"\t\t\\\n\t\t\t    \" setting TSD for \"#a_name\"\\n\");\t\t\\\n\t\t\tif (opt_abort)\t\t\t\t\t\\\n\t\t\t\tabort();\t\t\t\t\\\n\t\t}\t\t\t\t\t\t\t\\\n\t}\t\t\t\t\t\t\t\t\\\n}\n#elif (defined(_WIN32))\n#define\tmalloc_tsd_funcs(a_attr, a_name, a_type, a_initializer,\t\t\\\n    a_cleanup)\t\t\t\t\t\t\t\t\\\n/* Initialization/cleanup. */\t\t\t\t\t\t\\\na_attr bool\t\t\t\t\t\t\t\t\\\na_name##tsd_cleanup_wrapper(void)\t\t\t\t\t\\\n{\t\t\t\t\t\t\t\t\t\\\n\tDWORD error = GetLastError();\t\t\t\t\t\\\n\ta_name##tsd_wrapper_t *wrapper = (a_name##tsd_wrapper_t *)\t\\\n\t    TlsGetValue(a_name##tsd_tsd);\t\t\t\t\\\n\tSetLastError(error);\t\t\t\t\t\t\\\n\t\t\t\t\t\t\t\t\t\\\n\tif (wrapper == NULL)\t\t\t\t\t\t\\\n\t\treturn (false);\t\t\t\t\t\t\\\n\tif (a_cleanup != malloc_tsd_no_cleanup &&\t\t\t\\\n\t    wrapper->initialized) {\t\t\t\t\t\\\n\t\twrapper->initialized = false;\t\t\t\t\\\n\t\ta_cleanup(&wrapper->val);\t\t\t\t\\\n\t\tif (wrapper->initialized) {\t\t\t\t\\\n\t\t\t/* Trigger another cleanup round. */\t\t\\\n\t\t\treturn (true);\t\t\t\t\t\\\n\t\t}\t\t\t\t\t\t\t\\\n\t}\t\t\t\t\t\t\t\t\\\n\tmalloc_tsd_dalloc(wrapper);\t\t\t\t\t\\\n\treturn (false);\t\t\t\t\t\t\t\\\n}\t\t\t\t\t\t\t\t\t\\\na_attr void\t\t\t\t\t\t\t\t\\\na_name##tsd_wrapper_set(a_name##tsd_wrapper_t *wrapper)\t\t\t\\\n{\t\t\t\t\t\t\t\t\t\\\n\t\t\t\t\t\t\t\t\t\\\n\tif (!TlsSetValue(a_name##tsd_tsd, (void *)wrapper)) {\t\t\\\n\t\tmalloc_write(\"<jemalloc>: Error setting\"\t\t\\\n\t\t    \" TSD for \"#a_name\"\\n\");\t\t\t\t\\\n\t\tabort();\t\t\t\t\t\t\\\n\t}\t\t\t\t\t\t\t\t\\\n}\t\t\t\t\t\t\t\t\t\\\na_attr a_name##tsd_wrapper_t *\t\t\t\t\t\t\\\na_name##tsd_wrapper_get(void)\t\t\t\t\t\t\\\n{\t\t\t\t\t\t\t\t\t\\\n\tDWORD error = GetLastError();\t\t\t\t\t\\\n\ta_name##tsd_wrapper_t *wrapper = (a_name##tsd_wrapper_t *)\t\\\n\t    TlsGetValue(a_name##tsd_tsd);\t\t\t\t\\\n\tSetLastError(error);\t\t\t\t\t\t\\\n\t\t\t\t\t\t\t\t\t\\\n\tif (unlikely(wrapper == NULL)) {\t\t\t\t\\\n\t\twrapper = (a_name##tsd_wrapper_t *)\t\t\t\\\n\t\t    malloc_tsd_malloc(sizeof(a_name##tsd_wrapper_t));\t\\\n\t\tif (wrapper == NULL) {\t\t\t\t\t\\\n\t\t\tmalloc_write(\"<jemalloc>: Error allocating\"\t\\\n\t\t\t    \" TSD for \"#a_name\"\\n\");\t\t\t\\\n\t\t\tabort();\t\t\t\t\t\\\n\t\t} else {\t\t\t\t\t\t\\\n\t\t\twrapper->initialized = false;\t\t\t\\\n\t\t\twrapper->val = a_initializer;\t\t\t\\\n\t\t}\t\t\t\t\t\t\t\\\n\t\ta_name##tsd_wrapper_set(wrapper);\t\t\t\\\n\t}\t\t\t\t\t\t\t\t\\\n\treturn (wrapper);\t\t\t\t\t\t\\\n}\t\t\t\t\t\t\t\t\t\\\na_attr bool\t\t\t\t\t\t\t\t\\\na_name##tsd_boot0(void)\t\t\t\t\t\t\t\\\n{\t\t\t\t\t\t\t\t\t\\\n\t\t\t\t\t\t\t\t\t\\\n\ta_name##tsd_tsd = TlsAlloc();\t\t\t\t\t\\\n\tif (a_name##tsd_tsd == TLS_OUT_OF_INDEXES)\t\t\t\\\n\t\treturn (true);\t\t\t\t\t\t\\\n\tif (a_cleanup != malloc_tsd_no_cleanup) {\t\t\t\\\n\t\tmalloc_tsd_cleanup_register(\t\t\t\t\\\n\t\t    &a_name##tsd_cleanup_wrapper);\t\t\t\\\n\t}\t\t\t\t\t\t\t\t\\\n\ta_name##tsd_wrapper_set(&a_name##tsd_boot_wrapper);\t\t\\\n\ta_name##tsd_booted = true;\t\t\t\t\t\\\n\treturn (false);\t\t\t\t\t\t\t\\\n}\t\t\t\t\t\t\t\t\t\\\na_attr void\t\t\t\t\t\t\t\t\\\na_name##tsd_boot1(void)\t\t\t\t\t\t\t\\\n{\t\t\t\t\t\t\t\t\t\\\n\ta_name##tsd_wrapper_t *wrapper;\t\t\t\t\t\\\n\twrapper = (a_name##tsd_wrapper_t *)\t\t\t\t\\\n\t    malloc_tsd_malloc(sizeof(a_name##tsd_wrapper_t));\t\t\\\n\tif (wrapper == NULL) {\t\t\t\t\t\t\\\n\t\tmalloc_write(\"<jemalloc>: Error allocating\"\t\t\\\n\t\t    \" TSD for \"#a_name\"\\n\");\t\t\t\t\\\n\t\tabort();\t\t\t\t\t\t\\\n\t}\t\t\t\t\t\t\t\t\\\n\tmemcpy(wrapper, &a_name##tsd_boot_wrapper,\t\t\t\\\n\t    sizeof(a_name##tsd_wrapper_t));\t\t\t\t\\\n\ta_name##tsd_wrapper_set(wrapper);\t\t\t\t\\\n}\t\t\t\t\t\t\t\t\t\\\na_attr bool\t\t\t\t\t\t\t\t\\\na_name##tsd_boot(void)\t\t\t\t\t\t\t\\\n{\t\t\t\t\t\t\t\t\t\\\n\t\t\t\t\t\t\t\t\t\\\n\tif (a_name##tsd_boot0())\t\t\t\t\t\\\n\t\treturn (true);\t\t\t\t\t\t\\\n\ta_name##tsd_boot1();\t\t\t\t\t\t\\\n\treturn (false);\t\t\t\t\t\t\t\\\n}\t\t\t\t\t\t\t\t\t\\\n/* Get/set. */\t\t\t\t\t\t\t\t\\\na_attr a_type *\t\t\t\t\t\t\t\t\\\na_name##tsd_get(void)\t\t\t\t\t\t\t\\\n{\t\t\t\t\t\t\t\t\t\\\n\ta_name##tsd_wrapper_t *wrapper;\t\t\t\t\t\\\n\t\t\t\t\t\t\t\t\t\\\n\tassert(a_name##tsd_booted);\t\t\t\t\t\\\n\twrapper = a_name##tsd_wrapper_get();\t\t\t\t\\\n\treturn (&wrapper->val);\t\t\t\t\t\t\\\n}\t\t\t\t\t\t\t\t\t\\\na_attr void\t\t\t\t\t\t\t\t\\\na_name##tsd_set(a_type *val)\t\t\t\t\t\t\\\n{\t\t\t\t\t\t\t\t\t\\\n\ta_name##tsd_wrapper_t *wrapper;\t\t\t\t\t\\\n\t\t\t\t\t\t\t\t\t\\\n\tassert(a_name##tsd_booted);\t\t\t\t\t\\\n\twrapper = a_name##tsd_wrapper_get();\t\t\t\t\\\n\twrapper->val = *(val);\t\t\t\t\t\t\\\n\tif (a_cleanup != malloc_tsd_no_cleanup)\t\t\t\t\\\n\t\twrapper->initialized = true;\t\t\t\t\\\n}\n#else\n#define\tmalloc_tsd_funcs(a_attr, a_name, a_type, a_initializer,\t\t\\\n    a_cleanup)\t\t\t\t\t\t\t\t\\\n/* Initialization/cleanup. */\t\t\t\t\t\t\\\na_attr void\t\t\t\t\t\t\t\t\\\na_name##tsd_cleanup_wrapper(void *arg)\t\t\t\t\t\\\n{\t\t\t\t\t\t\t\t\t\\\n\ta_name##tsd_wrapper_t *wrapper = (a_name##tsd_wrapper_t *)arg;\t\\\n\t\t\t\t\t\t\t\t\t\\\n\tif (a_cleanup != malloc_tsd_no_cleanup &&\t\t\t\\\n\t    wrapper->initialized) {\t\t\t\t\t\\\n\t\twrapper->initialized = false;\t\t\t\t\\\n\t\ta_cleanup(&wrapper->val);\t\t\t\t\\\n\t\tif (wrapper->initialized) {\t\t\t\t\\\n\t\t\t/* Trigger another cleanup round. */\t\t\\\n\t\t\tif (pthread_setspecific(a_name##tsd_tsd,\t\\\n\t\t\t    (void *)wrapper)) {\t\t\t\t\\\n\t\t\t\tmalloc_write(\"<jemalloc>: Error\"\t\\\n\t\t\t\t    \" setting TSD for \"#a_name\"\\n\");\t\\\n\t\t\t\tif (opt_abort)\t\t\t\t\\\n\t\t\t\t\tabort();\t\t\t\\\n\t\t\t}\t\t\t\t\t\t\\\n\t\t\treturn;\t\t\t\t\t\t\\\n\t\t}\t\t\t\t\t\t\t\\\n\t}\t\t\t\t\t\t\t\t\\\n\tmalloc_tsd_dalloc(wrapper);\t\t\t\t\t\\\n}\t\t\t\t\t\t\t\t\t\\\na_attr void\t\t\t\t\t\t\t\t\\\na_name##tsd_wrapper_set(a_name##tsd_wrapper_t *wrapper)\t\t\t\\\n{\t\t\t\t\t\t\t\t\t\\\n\t\t\t\t\t\t\t\t\t\\\n\tif (pthread_setspecific(a_name##tsd_tsd,\t\t\t\\\n\t    (void *)wrapper)) {\t\t\t\t\t\t\\\n\t\tmalloc_write(\"<jemalloc>: Error setting\"\t\t\\\n\t\t    \" TSD for \"#a_name\"\\n\");\t\t\t\t\\\n\t\tabort();\t\t\t\t\t\t\\\n\t}\t\t\t\t\t\t\t\t\\\n}\t\t\t\t\t\t\t\t\t\\\na_attr a_name##tsd_wrapper_t *\t\t\t\t\t\t\\\na_name##tsd_wrapper_get(void)\t\t\t\t\t\t\\\n{\t\t\t\t\t\t\t\t\t\\\n\ta_name##tsd_wrapper_t *wrapper = (a_name##tsd_wrapper_t *)\t\\\n\t    pthread_getspecific(a_name##tsd_tsd);\t\t\t\\\n\t\t\t\t\t\t\t\t\t\\\n\tif (unlikely(wrapper == NULL)) {\t\t\t\t\\\n\t\ttsd_init_block_t block;\t\t\t\t\t\\\n\t\twrapper = tsd_init_check_recursion(\t\t\t\\\n\t\t    &a_name##tsd_init_head, &block);\t\t\t\\\n\t\tif (wrapper)\t\t\t\t\t\t\\\n\t\t    return (wrapper);\t\t\t\t\t\\\n\t\twrapper = (a_name##tsd_wrapper_t *)\t\t\t\\\n\t\t    malloc_tsd_malloc(sizeof(a_name##tsd_wrapper_t));\t\\\n\t\tblock.data = wrapper;\t\t\t\t\t\\\n\t\tif (wrapper == NULL) {\t\t\t\t\t\\\n\t\t\tmalloc_write(\"<jemalloc>: Error allocating\"\t\\\n\t\t\t    \" TSD for \"#a_name\"\\n\");\t\t\t\\\n\t\t\tabort();\t\t\t\t\t\\\n\t\t} else {\t\t\t\t\t\t\\\n\t\t\twrapper->initialized = false;\t\t\t\\\n\t\t\twrapper->val = a_initializer;\t\t\t\\\n\t\t}\t\t\t\t\t\t\t\\\n\t\ta_name##tsd_wrapper_set(wrapper);\t\t\t\\\n\t\ttsd_init_finish(&a_name##tsd_init_head, &block);\t\\\n\t}\t\t\t\t\t\t\t\t\\\n\treturn (wrapper);\t\t\t\t\t\t\\\n}\t\t\t\t\t\t\t\t\t\\\na_attr bool\t\t\t\t\t\t\t\t\\\na_name##tsd_boot0(void)\t\t\t\t\t\t\t\\\n{\t\t\t\t\t\t\t\t\t\\\n\t\t\t\t\t\t\t\t\t\\\n\tif (pthread_key_create(&a_name##tsd_tsd,\t\t\t\\\n\t    a_name##tsd_cleanup_wrapper) != 0)\t\t\t\t\\\n\t\treturn (true);\t\t\t\t\t\t\\\n\ta_name##tsd_wrapper_set(&a_name##tsd_boot_wrapper);\t\t\\\n\ta_name##tsd_booted = true;\t\t\t\t\t\\\n\treturn (false);\t\t\t\t\t\t\t\\\n}\t\t\t\t\t\t\t\t\t\\\na_attr void\t\t\t\t\t\t\t\t\\\na_name##tsd_boot1(void)\t\t\t\t\t\t\t\\\n{\t\t\t\t\t\t\t\t\t\\\n\ta_name##tsd_wrapper_t *wrapper;\t\t\t\t\t\\\n\twrapper = (a_name##tsd_wrapper_t *)\t\t\t\t\\\n\t    malloc_tsd_malloc(sizeof(a_name##tsd_wrapper_t));\t\t\\\n\tif (wrapper == NULL) {\t\t\t\t\t\t\\\n\t\tmalloc_write(\"<jemalloc>: Error allocating\"\t\t\\\n\t\t    \" TSD for \"#a_name\"\\n\");\t\t\t\t\\\n\t\tabort();\t\t\t\t\t\t\\\n\t}\t\t\t\t\t\t\t\t\\\n\tmemcpy(wrapper, &a_name##tsd_boot_wrapper,\t\t\t\\\n\t    sizeof(a_name##tsd_wrapper_t));\t\t\t\t\\\n\ta_name##tsd_wrapper_set(wrapper);\t\t\t\t\\\n}\t\t\t\t\t\t\t\t\t\\\na_attr bool\t\t\t\t\t\t\t\t\\\na_name##tsd_boot(void)\t\t\t\t\t\t\t\\\n{\t\t\t\t\t\t\t\t\t\\\n\t\t\t\t\t\t\t\t\t\\\n\tif (a_name##tsd_boot0())\t\t\t\t\t\\\n\t\treturn (true);\t\t\t\t\t\t\\\n\ta_name##tsd_boot1();\t\t\t\t\t\t\\\n\treturn (false);\t\t\t\t\t\t\t\\\n}\t\t\t\t\t\t\t\t\t\\\n/* Get/set. */\t\t\t\t\t\t\t\t\\\na_attr a_type *\t\t\t\t\t\t\t\t\\\na_name##tsd_get(void)\t\t\t\t\t\t\t\\\n{\t\t\t\t\t\t\t\t\t\\\n\ta_name##tsd_wrapper_t *wrapper;\t\t\t\t\t\\\n\t\t\t\t\t\t\t\t\t\\\n\tassert(a_name##tsd_booted);\t\t\t\t\t\\\n\twrapper = a_name##tsd_wrapper_get();\t\t\t\t\\\n\treturn (&wrapper->val);\t\t\t\t\t\t\\\n}\t\t\t\t\t\t\t\t\t\\\na_attr void\t\t\t\t\t\t\t\t\\\na_name##tsd_set(a_type *val)\t\t\t\t\t\t\\\n{\t\t\t\t\t\t\t\t\t\\\n\ta_name##tsd_wrapper_t *wrapper;\t\t\t\t\t\\\n\t\t\t\t\t\t\t\t\t\\\n\tassert(a_name##tsd_booted);\t\t\t\t\t\\\n\twrapper = a_name##tsd_wrapper_get();\t\t\t\t\\\n\twrapper->val = *(val);\t\t\t\t\t\t\\\n\tif (a_cleanup != malloc_tsd_no_cleanup)\t\t\t\t\\\n\t\twrapper->initialized = true;\t\t\t\t\\\n}\n#endif\n\n#endif /* JEMALLOC_H_TYPES */\n/******************************************************************************/\n#ifdef JEMALLOC_H_STRUCTS\n\n#if (!defined(JEMALLOC_MALLOC_THREAD_CLEANUP) && !defined(JEMALLOC_TLS) && \\\n    !defined(_WIN32))\nstruct tsd_init_block_s {\n\tql_elm(tsd_init_block_t)\tlink;\n\tpthread_t\t\t\tthread;\n\tvoid\t\t\t\t*data;\n};\nstruct tsd_init_head_s {\n\tql_head(tsd_init_block_t)\tblocks;\n\tmalloc_mutex_t\t\t\tlock;\n};\n#endif\n\n#define\tMALLOC_TSD\t\t\t\t\t\t\t\\\n/*  O(name,\t\t\ttype) */\t\t\t\t\\\n    O(tcache,\t\t\ttcache_t *)\t\t\t\t\\\n    O(thread_allocated,\t\tuint64_t)\t\t\t\t\\\n    O(thread_deallocated,\tuint64_t)\t\t\t\t\\\n    O(prof_tdata,\t\tprof_tdata_t *)\t\t\t\t\\\n    O(arena,\t\t\tarena_t *)\t\t\t\t\\\n    O(arenas_cache,\t\tarena_t **)\t\t\t\t\\\n    O(narenas_cache,\t\tunsigned)\t\t\t\t\\\n    O(arenas_cache_bypass,\tbool)\t\t\t\t\t\\\n    O(tcache_enabled,\t\ttcache_enabled_t)\t\t\t\\\n    O(quarantine,\t\tquarantine_t *)\t\t\t\t\\\n\n#define\tTSD_INITIALIZER {\t\t\t\t\t\t\\\n    tsd_state_uninitialized,\t\t\t\t\t\t\\\n    NULL,\t\t\t\t\t\t\t\t\\\n    0,\t\t\t\t\t\t\t\t\t\\\n    0,\t\t\t\t\t\t\t\t\t\\\n    NULL,\t\t\t\t\t\t\t\t\\\n    NULL,\t\t\t\t\t\t\t\t\\\n    NULL,\t\t\t\t\t\t\t\t\\\n    0,\t\t\t\t\t\t\t\t\t\\\n    false,\t\t\t\t\t\t\t\t\\\n    tcache_enabled_default,\t\t\t\t\t\t\\\n    NULL\t\t\t\t\t\t\t\t\\\n}\n\nstruct tsd_s {\n\ttsd_state_t\tstate;\n#define\tO(n, t)\t\t\t\t\t\t\t\t\\\n\tt\t\tn;\nMALLOC_TSD\n#undef O\n};\n\nstatic const tsd_t tsd_initializer = TSD_INITIALIZER;\n\nmalloc_tsd_types(, tsd_t)\n\n#endif /* JEMALLOC_H_STRUCTS */\n/******************************************************************************/\n#ifdef JEMALLOC_H_EXTERNS\n\nvoid\t*malloc_tsd_malloc(size_t size);\nvoid\tmalloc_tsd_dalloc(void *wrapper);\nvoid\tmalloc_tsd_no_cleanup(void *arg);\nvoid\tmalloc_tsd_cleanup_register(bool (*f)(void));\nbool\tmalloc_tsd_boot0(void);\nvoid\tmalloc_tsd_boot1(void);\n#if (!defined(JEMALLOC_MALLOC_THREAD_CLEANUP) && !defined(JEMALLOC_TLS) && \\\n    !defined(_WIN32))\nvoid\t*tsd_init_check_recursion(tsd_init_head_t *head,\n    tsd_init_block_t *block);\nvoid\ttsd_init_finish(tsd_init_head_t *head, tsd_init_block_t *block);\n#endif\nvoid\ttsd_cleanup(void *arg);\n\n#endif /* JEMALLOC_H_EXTERNS */\n/******************************************************************************/\n#ifdef JEMALLOC_H_INLINES\n\n#ifndef JEMALLOC_ENABLE_INLINE\nmalloc_tsd_protos(JEMALLOC_ATTR(unused), , tsd_t)\n\ntsd_t\t*tsd_fetch(void);\nbool\ttsd_nominal(tsd_t *tsd);\n#define\tO(n, t)\t\t\t\t\t\t\t\t\\\nt\t*tsd_##n##p_get(tsd_t *tsd);\t\t\t\t\t\\\nt\ttsd_##n##_get(tsd_t *tsd);\t\t\t\t\t\\\nvoid\ttsd_##n##_set(tsd_t *tsd, t n);\nMALLOC_TSD\n#undef O\n#endif\n\n#if (defined(JEMALLOC_ENABLE_INLINE) || defined(JEMALLOC_TSD_C_))\nmalloc_tsd_externs(, tsd_t)\nmalloc_tsd_funcs(JEMALLOC_ALWAYS_INLINE, , tsd_t, tsd_initializer, tsd_cleanup)\n\nJEMALLOC_ALWAYS_INLINE tsd_t *\ntsd_fetch(void)\n{\n\ttsd_t *tsd = tsd_get();\n\n\tif (unlikely(tsd->state != tsd_state_nominal)) {\n\t\tif (tsd->state == tsd_state_uninitialized) {\n\t\t\ttsd->state = tsd_state_nominal;\n\t\t\t/* Trigger cleanup handler registration. */\n\t\t\ttsd_set(tsd);\n\t\t} else if (tsd->state == tsd_state_purgatory) {\n\t\t\ttsd->state = tsd_state_reincarnated;\n\t\t\ttsd_set(tsd);\n\t\t} else\n\t\t\tassert(tsd->state == tsd_state_reincarnated);\n\t}\n\n\treturn (tsd);\n}\n\nJEMALLOC_INLINE bool\ntsd_nominal(tsd_t *tsd)\n{\n\n\treturn (tsd->state == tsd_state_nominal);\n}\n\n#define\tO(n, t)\t\t\t\t\t\t\t\t\\\nJEMALLOC_ALWAYS_INLINE t *\t\t\t\t\t\t\\\ntsd_##n##p_get(tsd_t *tsd)\t\t\t\t\t\t\\\n{\t\t\t\t\t\t\t\t\t\\\n\t\t\t\t\t\t\t\t\t\\\n\treturn (&tsd->n);\t\t\t\t\t\t\\\n}\t\t\t\t\t\t\t\t\t\\\n\t\t\t\t\t\t\t\t\t\\\nJEMALLOC_ALWAYS_INLINE t\t\t\t\t\t\t\\\ntsd_##n##_get(tsd_t *tsd)\t\t\t\t\t\t\\\n{\t\t\t\t\t\t\t\t\t\\\n\t\t\t\t\t\t\t\t\t\\\n\treturn (*tsd_##n##p_get(tsd));\t\t\t\t\t\\\n}\t\t\t\t\t\t\t\t\t\\\n\t\t\t\t\t\t\t\t\t\\\nJEMALLOC_ALWAYS_INLINE void\t\t\t\t\t\t\\\ntsd_##n##_set(tsd_t *tsd, t n)\t\t\t\t\t\t\\\n{\t\t\t\t\t\t\t\t\t\\\n\t\t\t\t\t\t\t\t\t\\\n\tassert(tsd->state == tsd_state_nominal);\t\t\t\\\n\ttsd->n = n;\t\t\t\t\t\t\t\\\n}\nMALLOC_TSD\n#undef O\n#endif\n\n#endif /* JEMALLOC_H_INLINES */\n/******************************************************************************/\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.8/deps/jemalloc/include/jemalloc/internal/util.h",
    "content": "/******************************************************************************/\n#ifdef JEMALLOC_H_TYPES\n\n#ifdef _WIN32\n#  ifdef _WIN64\n#    define FMT64_PREFIX \"ll\"\n#    define FMTPTR_PREFIX \"ll\"\n#  else\n#    define FMT64_PREFIX \"ll\"\n#    define FMTPTR_PREFIX \"\"\n#  endif\n#  define FMTd32 \"d\"\n#  define FMTu32 \"u\"\n#  define FMTx32 \"x\"\n#  define FMTd64 FMT64_PREFIX \"d\"\n#  define FMTu64 FMT64_PREFIX \"u\"\n#  define FMTx64 FMT64_PREFIX \"x\"\n#  define FMTdPTR FMTPTR_PREFIX \"d\"\n#  define FMTuPTR FMTPTR_PREFIX \"u\"\n#  define FMTxPTR FMTPTR_PREFIX \"x\"\n#else\n#  include <inttypes.h>\n#  define FMTd32 PRId32\n#  define FMTu32 PRIu32\n#  define FMTx32 PRIx32\n#  define FMTd64 PRId64\n#  define FMTu64 PRIu64\n#  define FMTx64 PRIx64\n#  define FMTdPTR PRIdPTR\n#  define FMTuPTR PRIuPTR\n#  define FMTxPTR PRIxPTR\n#endif\n\n/* Size of stack-allocated buffer passed to buferror(). */\n#define\tBUFERROR_BUF\t\t64\n\n/*\n * Size of stack-allocated buffer used by malloc_{,v,vc}printf().  This must be\n * large enough for all possible uses within jemalloc.\n */\n#define\tMALLOC_PRINTF_BUFSIZE\t4096\n\n/*\n * Wrap a cpp argument that contains commas such that it isn't broken up into\n * multiple arguments.\n */\n#define\tJEMALLOC_ARG_CONCAT(...) __VA_ARGS__\n\n/*\n * Silence compiler warnings due to uninitialized values.  This is used\n * wherever the compiler fails to recognize that the variable is never used\n * uninitialized.\n */\n#ifdef JEMALLOC_CC_SILENCE\n#\tdefine JEMALLOC_CC_SILENCE_INIT(v) = v\n#else\n#\tdefine JEMALLOC_CC_SILENCE_INIT(v)\n#endif\n\n#define\tJEMALLOC_GNUC_PREREQ(major, minor)\t\t\t\t\\\n    (!defined(__clang__) &&\t\t\t\t\t\t\\\n    (__GNUC__ > (major) || (__GNUC__ == (major) && __GNUC_MINOR__ >= (minor))))\n#ifndef __has_builtin\n#  define __has_builtin(builtin) (0)\n#endif\n#define\tJEMALLOC_CLANG_HAS_BUILTIN(builtin)\t\t\t\t\\\n    (defined(__clang__) && __has_builtin(builtin))\n\n#ifdef __GNUC__\n#\tdefine likely(x)   __builtin_expect(!!(x), 1)\n#\tdefine unlikely(x) __builtin_expect(!!(x), 0)\n#  if JEMALLOC_GNUC_PREREQ(4, 6) ||\t\t\t\t\t\\\n      JEMALLOC_CLANG_HAS_BUILTIN(__builtin_unreachable)\n#\tdefine unreachable() __builtin_unreachable()\n#  else\n#\tdefine unreachable()\n#  endif\n#else\n#\tdefine likely(x)   !!(x)\n#\tdefine unlikely(x) !!(x)\n#\tdefine unreachable()\n#endif\n\n/*\n * Define a custom assert() in order to reduce the chances of deadlock during\n * assertion failure.\n */\n#ifndef assert\n#define\tassert(e) do {\t\t\t\t\t\t\t\\\n\tif (unlikely(config_debug && !(e))) {\t\t\t\t\\\n\t\tmalloc_printf(\t\t\t\t\t\t\\\n\t\t    \"<jemalloc>: %s:%d: Failed assertion: \\\"%s\\\"\\n\",\t\\\n\t\t    __FILE__, __LINE__, #e);\t\t\t\t\\\n\t\tabort();\t\t\t\t\t\t\\\n\t}\t\t\t\t\t\t\t\t\\\n} while (0)\n#endif\n\n#ifndef not_reached\n#define\tnot_reached() do {\t\t\t\t\t\t\\\n\tif (config_debug) {\t\t\t\t\t\t\\\n\t\tmalloc_printf(\t\t\t\t\t\t\\\n\t\t    \"<jemalloc>: %s:%d: Unreachable code reached\\n\",\t\\\n\t\t    __FILE__, __LINE__);\t\t\t\t\\\n\t\tabort();\t\t\t\t\t\t\\\n\t}\t\t\t\t\t\t\t\t\\\n\tunreachable();\t\t\t\t\t\t\t\\\n} while (0)\n#endif\n\n#ifndef not_implemented\n#define\tnot_implemented() do {\t\t\t\t\t\t\\\n\tif (config_debug) {\t\t\t\t\t\t\\\n\t\tmalloc_printf(\"<jemalloc>: %s:%d: Not implemented\\n\",\t\\\n\t\t    __FILE__, __LINE__);\t\t\t\t\\\n\t\tabort();\t\t\t\t\t\t\\\n\t}\t\t\t\t\t\t\t\t\\\n} while (0)\n#endif\n\n#ifndef assert_not_implemented\n#define\tassert_not_implemented(e) do {\t\t\t\t\t\\\n\tif (unlikely(config_debug && !(e)))\t\t\t\t\\\n\t\tnot_implemented();\t\t\t\t\t\\\n} while (0)\n#endif\n\n/* Use to assert a particular configuration, e.g., cassert(config_debug). */\n#define\tcassert(c) do {\t\t\t\t\t\t\t\\\n\tif (unlikely(!(c)))\t\t\t\t\t\t\\\n\t\tnot_reached();\t\t\t\t\t\t\\\n} while (0)\n\n#endif /* JEMALLOC_H_TYPES */\n/******************************************************************************/\n#ifdef JEMALLOC_H_STRUCTS\n\n#endif /* JEMALLOC_H_STRUCTS */\n/******************************************************************************/\n#ifdef JEMALLOC_H_EXTERNS\n\nint\tbuferror(int err, char *buf, size_t buflen);\nuintmax_t\tmalloc_strtoumax(const char *restrict nptr,\n    char **restrict endptr, int base);\nvoid\tmalloc_write(const char *s);\n\n/*\n * malloc_vsnprintf() supports a subset of snprintf(3) that avoids floating\n * point math.\n */\nint\tmalloc_vsnprintf(char *str, size_t size, const char *format,\n    va_list ap);\nint\tmalloc_snprintf(char *str, size_t size, const char *format, ...)\n    JEMALLOC_FORMAT_PRINTF(3, 4);\nvoid\tmalloc_vcprintf(void (*write_cb)(void *, const char *), void *cbopaque,\n    const char *format, va_list ap);\nvoid malloc_cprintf(void (*write)(void *, const char *), void *cbopaque,\n    const char *format, ...) JEMALLOC_FORMAT_PRINTF(3, 4);\nvoid\tmalloc_printf(const char *format, ...) JEMALLOC_FORMAT_PRINTF(1, 2);\n\n#endif /* JEMALLOC_H_EXTERNS */\n/******************************************************************************/\n#ifdef JEMALLOC_H_INLINES\n\n#ifndef JEMALLOC_ENABLE_INLINE\nint\tjemalloc_ffsl(long bitmap);\nint\tjemalloc_ffs(int bitmap);\nsize_t\tpow2_ceil(size_t x);\nsize_t\tlg_floor(size_t x);\nvoid\tset_errno(int errnum);\nint\tget_errno(void);\n#endif\n\n#if (defined(JEMALLOC_ENABLE_INLINE) || defined(JEMALLOC_UTIL_C_))\n\n/* Sanity check. */\n#if !defined(JEMALLOC_INTERNAL_FFSL) || !defined(JEMALLOC_INTERNAL_FFS)\n#  error Both JEMALLOC_INTERNAL_FFSL && JEMALLOC_INTERNAL_FFS should have been defined by configure\n#endif\n\nJEMALLOC_ALWAYS_INLINE int\njemalloc_ffsl(long bitmap)\n{\n\n\treturn (JEMALLOC_INTERNAL_FFSL(bitmap));\n}\n\nJEMALLOC_ALWAYS_INLINE int\njemalloc_ffs(int bitmap)\n{\n\n\treturn (JEMALLOC_INTERNAL_FFS(bitmap));\n}\n\n/* Compute the smallest power of 2 that is >= x. */\nJEMALLOC_INLINE size_t\npow2_ceil(size_t x)\n{\n\n\tx--;\n\tx |= x >> 1;\n\tx |= x >> 2;\n\tx |= x >> 4;\n\tx |= x >> 8;\n\tx |= x >> 16;\n#if (LG_SIZEOF_PTR == 3)\n\tx |= x >> 32;\n#endif\n\tx++;\n\treturn (x);\n}\n\n#if (defined(__i386__) || defined(__amd64__) || defined(__x86_64__))\nJEMALLOC_INLINE size_t\nlg_floor(size_t x)\n{\n\tsize_t ret;\n\n\tassert(x != 0);\n\n\tasm (\"bsr %1, %0\"\n\t    : \"=r\"(ret) // Outputs.\n\t    : \"r\"(x)    // Inputs.\n\t    );\n\treturn (ret);\n}\n#elif (defined(_MSC_VER))\nJEMALLOC_INLINE size_t\nlg_floor(size_t x)\n{\n\tunsigned long ret;\n\n\tassert(x != 0);\n\n#if (LG_SIZEOF_PTR == 3)\n\t_BitScanReverse64(&ret, x);\n#elif (LG_SIZEOF_PTR == 2)\n\t_BitScanReverse(&ret, x);\n#else\n#  error \"Unsupported type sizes for lg_floor()\"\n#endif\n\treturn (ret);\n}\n#elif (defined(JEMALLOC_HAVE_BUILTIN_CLZ))\nJEMALLOC_INLINE size_t\nlg_floor(size_t x)\n{\n\n\tassert(x != 0);\n\n#if (LG_SIZEOF_PTR == LG_SIZEOF_INT)\n\treturn (((8 << LG_SIZEOF_PTR) - 1) - __builtin_clz(x));\n#elif (LG_SIZEOF_PTR == LG_SIZEOF_LONG)\n\treturn (((8 << LG_SIZEOF_PTR) - 1) - __builtin_clzl(x));\n#else\n#  error \"Unsupported type sizes for lg_floor()\"\n#endif\n}\n#else\nJEMALLOC_INLINE size_t\nlg_floor(size_t x)\n{\n\n\tassert(x != 0);\n\n\tx |= (x >> 1);\n\tx |= (x >> 2);\n\tx |= (x >> 4);\n\tx |= (x >> 8);\n\tx |= (x >> 16);\n#if (LG_SIZEOF_PTR == 3 && LG_SIZEOF_PTR == LG_SIZEOF_LONG)\n\tx |= (x >> 32);\n\tif (x == KZU(0xffffffffffffffff))\n\t\treturn (63);\n\tx++;\n\treturn (jemalloc_ffsl(x) - 2);\n#elif (LG_SIZEOF_PTR == 2)\n\tif (x == KZU(0xffffffff))\n\t\treturn (31);\n\tx++;\n\treturn (jemalloc_ffs(x) - 2);\n#else\n#  error \"Unsupported type sizes for lg_floor()\"\n#endif\n}\n#endif\n\n/* Set error code. */\nJEMALLOC_INLINE void\nset_errno(int errnum)\n{\n\n#ifdef _WIN32\n\tSetLastError(errnum);\n#else\n\terrno = errnum;\n#endif\n}\n\n/* Get last error code. */\nJEMALLOC_INLINE int\nget_errno(void)\n{\n\n#ifdef _WIN32\n\treturn (GetLastError());\n#else\n\treturn (errno);\n#endif\n}\n#endif\n\n#endif /* JEMALLOC_H_INLINES */\n/******************************************************************************/\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.8/deps/jemalloc/include/jemalloc/internal/valgrind.h",
    "content": "/******************************************************************************/\n#ifdef JEMALLOC_H_TYPES\n\n#ifdef JEMALLOC_VALGRIND\n#include <valgrind/valgrind.h>\n\n/*\n * The size that is reported to Valgrind must be consistent through a chain of\n * malloc..realloc..realloc calls.  Request size isn't recorded anywhere in\n * jemalloc, so it is critical that all callers of these macros provide usize\n * rather than request size.  As a result, buffer overflow detection is\n * technically weakened for the standard API, though it is generally accepted\n * practice to consider any extra bytes reported by malloc_usable_size() as\n * usable space.\n */\n#define\tJEMALLOC_VALGRIND_MAKE_MEM_NOACCESS(ptr, usize) do {\t\t\\\n\tif (unlikely(in_valgrind))\t\t\t\t\t\\\n\t\tvalgrind_make_mem_noaccess(ptr, usize);\t\t\t\\\n} while (0)\n#define\tJEMALLOC_VALGRIND_MAKE_MEM_UNDEFINED(ptr, usize) do {\t\t\\\n\tif (unlikely(in_valgrind))\t\t\t\t\t\\\n\t\tvalgrind_make_mem_undefined(ptr, usize);\t\t\\\n} while (0)\n#define\tJEMALLOC_VALGRIND_MAKE_MEM_DEFINED(ptr, usize) do {\t\t\\\n\tif (unlikely(in_valgrind))\t\t\t\t\t\\\n\t\tvalgrind_make_mem_defined(ptr, usize);\t\t\t\\\n} while (0)\n/*\n * The VALGRIND_MALLOCLIKE_BLOCK() and VALGRIND_RESIZEINPLACE_BLOCK() macro\n * calls must be embedded in macros rather than in functions so that when\n * Valgrind reports errors, there are no extra stack frames in the backtraces.\n */\n#define\tJEMALLOC_VALGRIND_MALLOC(cond, ptr, usize, zero) do {\t\t\\\n\tif (unlikely(in_valgrind && cond))\t\t\t\t\\\n\t\tVALGRIND_MALLOCLIKE_BLOCK(ptr, usize, p2rz(ptr), zero);\t\\\n} while (0)\n#define\tJEMALLOC_VALGRIND_REALLOC(maybe_moved, ptr, usize,\t\t\\\n    ptr_maybe_null, old_ptr, old_usize, old_rzsize, old_ptr_maybe_null,\t\\\n    zero) do {\t\t\t\t\t\t\t\t\\\n\tif (unlikely(in_valgrind)) {\t\t\t\t\t\\\n\t\tsize_t rzsize = p2rz(ptr);\t\t\t\t\\\n\t\t\t\t\t\t\t\t\t\\\n\t\tif (!maybe_moved || ptr == old_ptr) {\t\t\t\\\n\t\t\tVALGRIND_RESIZEINPLACE_BLOCK(ptr, old_usize,\t\\\n\t\t\t    usize, rzsize);\t\t\t\t\\\n\t\t\tif (zero && old_usize < usize) {\t\t\\\n\t\t\t\tvalgrind_make_mem_defined(\t\t\\\n\t\t\t\t    (void *)((uintptr_t)ptr +\t\t\\\n\t\t\t\t    old_usize), usize - old_usize);\t\\\n\t\t\t}\t\t\t\t\t\t\\\n\t\t} else {\t\t\t\t\t\t\\\n\t\t\tif (!old_ptr_maybe_null || old_ptr != NULL) {\t\\\n\t\t\t\tvalgrind_freelike_block(old_ptr,\t\\\n\t\t\t\t    old_rzsize);\t\t\t\\\n\t\t\t}\t\t\t\t\t\t\\\n\t\t\tif (!ptr_maybe_null || ptr != NULL) {\t\t\\\n\t\t\t\tsize_t copy_size = (old_usize < usize)\t\\\n\t\t\t\t    ?  old_usize : usize;\t\t\\\n\t\t\t\tsize_t tail_size = usize - copy_size;\t\\\n\t\t\t\tVALGRIND_MALLOCLIKE_BLOCK(ptr, usize,\t\\\n\t\t\t\t    rzsize, false);\t\t\t\\\n\t\t\t\tif (copy_size > 0) {\t\t\t\\\n\t\t\t\t\tvalgrind_make_mem_defined(ptr,\t\\\n\t\t\t\t\tcopy_size);\t\t\t\\\n\t\t\t\t}\t\t\t\t\t\\\n\t\t\t\tif (zero && tail_size > 0) {\t\t\\\n\t\t\t\t\tvalgrind_make_mem_defined(\t\\\n\t\t\t\t\t    (void *)((uintptr_t)ptr +\t\\\n\t\t\t\t\t    copy_size), tail_size);\t\\\n\t\t\t\t}\t\t\t\t\t\\\n\t\t\t}\t\t\t\t\t\t\\\n\t\t}\t\t\t\t\t\t\t\\\n\t}\t\t\t\t\t\t\t\t\\\n} while (0)\n#define\tJEMALLOC_VALGRIND_FREE(ptr, rzsize) do {\t\t\t\\\n\tif (unlikely(in_valgrind))\t\t\t\t\t\\\n\t\tvalgrind_freelike_block(ptr, rzsize);\t\t\t\\\n} while (0)\n#else\n#define\tRUNNING_ON_VALGRIND\t((unsigned)0)\n#define\tJEMALLOC_VALGRIND_MAKE_MEM_NOACCESS(ptr, usize) do {} while (0)\n#define\tJEMALLOC_VALGRIND_MAKE_MEM_UNDEFINED(ptr, usize) do {} while (0)\n#define\tJEMALLOC_VALGRIND_MAKE_MEM_DEFINED(ptr, usize) do {} while (0)\n#define\tJEMALLOC_VALGRIND_MALLOC(cond, ptr, usize, zero) do {} while (0)\n#define\tJEMALLOC_VALGRIND_REALLOC(maybe_moved, ptr, usize,\t\t\\\n    ptr_maybe_null, old_ptr, old_usize, old_rzsize, old_ptr_maybe_null,\t\\\n    zero) do {} while (0)\n#define\tJEMALLOC_VALGRIND_FREE(ptr, rzsize) do {} while (0)\n#endif\n\n#endif /* JEMALLOC_H_TYPES */\n/******************************************************************************/\n#ifdef JEMALLOC_H_STRUCTS\n\n#endif /* JEMALLOC_H_STRUCTS */\n/******************************************************************************/\n#ifdef JEMALLOC_H_EXTERNS\n\n#ifdef JEMALLOC_VALGRIND\nvoid\tvalgrind_make_mem_noaccess(void *ptr, size_t usize);\nvoid\tvalgrind_make_mem_undefined(void *ptr, size_t usize);\nvoid\tvalgrind_make_mem_defined(void *ptr, size_t usize);\nvoid\tvalgrind_freelike_block(void *ptr, size_t usize);\n#endif\n\n#endif /* JEMALLOC_H_EXTERNS */\n/******************************************************************************/\n#ifdef JEMALLOC_H_INLINES\n\n#endif /* JEMALLOC_H_INLINES */\n/******************************************************************************/\n\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.8/deps/jemalloc/include/jemalloc/jemalloc.sh",
    "content": "#!/bin/sh\n\nobjroot=$1\n\ncat <<EOF\n#ifndef JEMALLOC_H_\n#define\tJEMALLOC_H_\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\nEOF\n\nfor hdr in jemalloc_defs.h jemalloc_rename.h jemalloc_macros.h \\\n           jemalloc_protos.h jemalloc_typedefs.h jemalloc_mangle.h ; do\n  cat \"${objroot}include/jemalloc/${hdr}\" \\\n      | grep -v 'Generated from .* by configure\\.' \\\n      | sed -e 's/^#define /#define\t/g' \\\n      | sed -e 's/ $//g'\n  echo\ndone\n\ncat <<EOF\n#ifdef __cplusplus\n}\n#endif\n#endif /* JEMALLOC_H_ */\nEOF\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.8/deps/jemalloc/include/jemalloc/jemalloc_defs.h.in",
    "content": "/* Defined if __attribute__((...)) syntax is supported. */\n#undef JEMALLOC_HAVE_ATTR\n\n/* Defined if alloc_size attribute is supported. */\n#undef JEMALLOC_HAVE_ATTR_ALLOC_SIZE\n\n/* Defined if format(gnu_printf, ...) attribute is supported. */\n#undef JEMALLOC_HAVE_ATTR_FORMAT_GNU_PRINTF\n\n/* Defined if format(printf, ...) attribute is supported. */\n#undef JEMALLOC_HAVE_ATTR_FORMAT_PRINTF\n\n/*\n * Define overrides for non-standard allocator-related functions if they are\n * present on the system.\n */\n#undef JEMALLOC_OVERRIDE_MEMALIGN\n#undef JEMALLOC_OVERRIDE_VALLOC\n\n/*\n * At least Linux omits the \"const\" in:\n *\n *   size_t malloc_usable_size(const void *ptr);\n *\n * Match the operating system's prototype.\n */\n#undef JEMALLOC_USABLE_SIZE_CONST\n\n/*\n * If defined, specify throw() for the public function prototypes when compiling\n * with C++.  The only justification for this is to match the prototypes that\n * glibc defines.\n */\n#undef JEMALLOC_USE_CXX_THROW\n\n/* sizeof(void *) == 2^LG_SIZEOF_PTR. */\n#undef LG_SIZEOF_PTR\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.8/deps/jemalloc/include/jemalloc/jemalloc_macros.h.in",
    "content": "#include <stdlib.h>\n#include <stdbool.h>\n#include <stdint.h>\n#include <limits.h>\n#include <strings.h>\n\n#define\tJEMALLOC_VERSION \"@jemalloc_version@\"\n#define\tJEMALLOC_VERSION_MAJOR @jemalloc_version_major@\n#define\tJEMALLOC_VERSION_MINOR @jemalloc_version_minor@\n#define\tJEMALLOC_VERSION_BUGFIX @jemalloc_version_bugfix@\n#define\tJEMALLOC_VERSION_NREV @jemalloc_version_nrev@\n#define\tJEMALLOC_VERSION_GID \"@jemalloc_version_gid@\"\n\n#  define MALLOCX_LG_ALIGN(la)\t(la)\n#  if LG_SIZEOF_PTR == 2\n#    define MALLOCX_ALIGN(a)\t(ffs(a)-1)\n#  else\n#    define MALLOCX_ALIGN(a)\t\t\t\t\t\t\\\n\t ((a < (size_t)INT_MAX) ? ffs(a)-1 : ffs(a>>32)+31)\n#  endif\n#  define MALLOCX_ZERO\t((int)0x40)\n/*\n * Bias tcache index bits so that 0 encodes \"automatic tcache management\", and 1\n * encodes MALLOCX_TCACHE_NONE.\n */\n#  define MALLOCX_TCACHE(tc)\t((int)(((tc)+2) << 8))\n#  define MALLOCX_TCACHE_NONE\tMALLOCX_TCACHE(-1)\n/*\n * Bias arena index bits so that 0 encodes \"use an automatically chosen arena\".\n */\n#  define MALLOCX_ARENA(a)\t((int)(((a)+1) << 20))\n\n#if defined(__cplusplus) && defined(JEMALLOC_USE_CXX_THROW)\n#  define JEMALLOC_CXX_THROW throw()\n#else\n#  define JEMALLOC_CXX_THROW\n#endif\n\n#ifdef JEMALLOC_HAVE_ATTR\n#  define JEMALLOC_ATTR(s) __attribute__((s))\n#  define JEMALLOC_ALIGNED(s) JEMALLOC_ATTR(aligned(s))\n#  ifdef JEMALLOC_HAVE_ATTR_ALLOC_SIZE\n#    define JEMALLOC_ALLOC_SIZE(s) JEMALLOC_ATTR(alloc_size(s))\n#    define JEMALLOC_ALLOC_SIZE2(s1, s2) JEMALLOC_ATTR(alloc_size(s1, s2))\n#  else\n#    define JEMALLOC_ALLOC_SIZE(s)\n#    define JEMALLOC_ALLOC_SIZE2(s1, s2)\n#  endif\n#  ifndef JEMALLOC_EXPORT\n#    define JEMALLOC_EXPORT JEMALLOC_ATTR(visibility(\"default\"))\n#  endif\n#  ifdef JEMALLOC_HAVE_ATTR_FORMAT_GNU_PRINTF\n#    define JEMALLOC_FORMAT_PRINTF(s, i) JEMALLOC_ATTR(format(gnu_printf, s, i))\n#  elif defined(JEMALLOC_HAVE_ATTR_FORMAT_PRINTF)\n#    define JEMALLOC_FORMAT_PRINTF(s, i) JEMALLOC_ATTR(format(printf, s, i))\n#  else\n#    define JEMALLOC_FORMAT_PRINTF(s, i)\n#  endif\n#  define JEMALLOC_NOINLINE JEMALLOC_ATTR(noinline)\n#  define JEMALLOC_NOTHROW JEMALLOC_ATTR(nothrow)\n#  define JEMALLOC_SECTION(s) JEMALLOC_ATTR(section(s))\n#  define JEMALLOC_RESTRICT_RETURN\n#  define JEMALLOC_ALLOCATOR\n#elif _MSC_VER\n#  define JEMALLOC_ATTR(s)\n#  define JEMALLOC_ALIGNED(s) __declspec(align(s))\n#  define JEMALLOC_ALLOC_SIZE(s)\n#  define JEMALLOC_ALLOC_SIZE2(s1, s2)\n#  ifndef JEMALLOC_EXPORT\n#    ifdef DLLEXPORT\n#      define JEMALLOC_EXPORT __declspec(dllexport)\n#    else\n#      define JEMALLOC_EXPORT __declspec(dllimport)\n#    endif\n#  endif\n#  define JEMALLOC_FORMAT_PRINTF(s, i)\n#  define JEMALLOC_NOINLINE __declspec(noinline)\n#  ifdef __cplusplus\n#    define JEMALLOC_NOTHROW __declspec(nothrow)\n#  else\n#    define JEMALLOC_NOTHROW\n#  endif\n#  define JEMALLOC_SECTION(s) __declspec(allocate(s))\n#  define JEMALLOC_RESTRICT_RETURN __declspec(restrict)\n#  if _MSC_VER >= 1900 && !defined(__EDG__)\n#    define JEMALLOC_ALLOCATOR __declspec(allocator)\n#  else\n#    define JEMALLOC_ALLOCATOR\n#  endif\n#else\n#  define JEMALLOC_ATTR(s)\n#  define JEMALLOC_ALIGNED(s)\n#  define JEMALLOC_ALLOC_SIZE(s)\n#  define JEMALLOC_ALLOC_SIZE2(s1, s2)\n#  define JEMALLOC_EXPORT\n#  define JEMALLOC_FORMAT_PRINTF(s, i)\n#  define JEMALLOC_NOINLINE\n#  define JEMALLOC_NOTHROW\n#  define JEMALLOC_SECTION(s)\n#  define JEMALLOC_RESTRICT_RETURN\n#  define JEMALLOC_ALLOCATOR\n#endif\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.8/deps/jemalloc/include/jemalloc/jemalloc_mangle.sh",
    "content": "#!/bin/sh\n\npublic_symbols_txt=$1\nsymbol_prefix=$2\n\ncat <<EOF\n/*\n * By default application code must explicitly refer to mangled symbol names,\n * so that it is possible to use jemalloc in conjunction with another allocator\n * in the same application.  Define JEMALLOC_MANGLE in order to cause automatic\n * name mangling that matches the API prefixing that happened as a result of\n * --with-mangling and/or --with-jemalloc-prefix configuration settings.\n */\n#ifdef JEMALLOC_MANGLE\n#  ifndef JEMALLOC_NO_DEMANGLE\n#    define JEMALLOC_NO_DEMANGLE\n#  endif\nEOF\n\nfor nm in `cat ${public_symbols_txt}` ; do\n  n=`echo ${nm} |tr ':' ' ' |awk '{print $1}'`\n  echo \"#  define ${n} ${symbol_prefix}${n}\"\ndone\n\ncat <<EOF\n#endif\n\n/*\n * The ${symbol_prefix}* macros can be used as stable alternative names for the\n * public jemalloc API if JEMALLOC_NO_DEMANGLE is defined.  This is primarily\n * meant for use in jemalloc itself, but it can be used by application code to\n * provide isolation from the name mangling specified via --with-mangling\n * and/or --with-jemalloc-prefix.\n */\n#ifndef JEMALLOC_NO_DEMANGLE\nEOF\n\nfor nm in `cat ${public_symbols_txt}` ; do\n  n=`echo ${nm} |tr ':' ' ' |awk '{print $1}'`\n  echo \"#  undef ${symbol_prefix}${n}\"\ndone\n\ncat <<EOF\n#endif\nEOF\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.8/deps/jemalloc/include/jemalloc/jemalloc_protos.h.in",
    "content": "/*\n * The @je_@ prefix on the following public symbol declarations is an artifact\n * of namespace management, and should be omitted in application code unless\n * JEMALLOC_NO_DEMANGLE is defined (see jemalloc_mangle@install_suffix@.h).\n */\nextern JEMALLOC_EXPORT const char\t*@je_@malloc_conf;\nextern JEMALLOC_EXPORT void\t\t(*@je_@malloc_message)(void *cbopaque,\n    const char *s);\n\nJEMALLOC_EXPORT JEMALLOC_ALLOCATOR JEMALLOC_RESTRICT_RETURN\n    void JEMALLOC_NOTHROW\t*@je_@malloc(size_t size)\n    JEMALLOC_CXX_THROW JEMALLOC_ATTR(malloc) JEMALLOC_ALLOC_SIZE(1);\nJEMALLOC_EXPORT JEMALLOC_ALLOCATOR JEMALLOC_RESTRICT_RETURN\n    void JEMALLOC_NOTHROW\t*@je_@calloc(size_t num, size_t size)\n    JEMALLOC_CXX_THROW JEMALLOC_ATTR(malloc) JEMALLOC_ALLOC_SIZE2(1, 2);\nJEMALLOC_EXPORT int JEMALLOC_NOTHROW\t@je_@posix_memalign(void **memptr,\n    size_t alignment, size_t size) JEMALLOC_CXX_THROW JEMALLOC_ATTR(nonnull(1));\nJEMALLOC_EXPORT JEMALLOC_ALLOCATOR JEMALLOC_RESTRICT_RETURN\n    void JEMALLOC_NOTHROW\t*@je_@aligned_alloc(size_t alignment,\n    size_t size) JEMALLOC_CXX_THROW JEMALLOC_ATTR(malloc)\n    JEMALLOC_ALLOC_SIZE(2);\nJEMALLOC_EXPORT JEMALLOC_ALLOCATOR JEMALLOC_RESTRICT_RETURN\n    void JEMALLOC_NOTHROW\t*@je_@realloc(void *ptr, size_t size)\n    JEMALLOC_CXX_THROW JEMALLOC_ALLOC_SIZE(2);\nJEMALLOC_EXPORT void JEMALLOC_NOTHROW\t@je_@free(void *ptr)\n    JEMALLOC_CXX_THROW;\n\nJEMALLOC_EXPORT JEMALLOC_ALLOCATOR JEMALLOC_RESTRICT_RETURN\n    void JEMALLOC_NOTHROW\t*@je_@mallocx(size_t size, int flags)\n    JEMALLOC_ATTR(malloc) JEMALLOC_ALLOC_SIZE(1);\nJEMALLOC_EXPORT JEMALLOC_ALLOCATOR JEMALLOC_RESTRICT_RETURN\n    void JEMALLOC_NOTHROW\t*@je_@rallocx(void *ptr, size_t size,\n    int flags) JEMALLOC_ALLOC_SIZE(2);\nJEMALLOC_EXPORT size_t JEMALLOC_NOTHROW\t@je_@xallocx(void *ptr, size_t size,\n    size_t extra, int flags);\nJEMALLOC_EXPORT size_t JEMALLOC_NOTHROW\t@je_@sallocx(const void *ptr,\n    int flags) JEMALLOC_ATTR(pure);\nJEMALLOC_EXPORT void JEMALLOC_NOTHROW\t@je_@dallocx(void *ptr, int flags);\nJEMALLOC_EXPORT void JEMALLOC_NOTHROW\t@je_@sdallocx(void *ptr, size_t size,\n    int flags);\nJEMALLOC_EXPORT size_t JEMALLOC_NOTHROW\t@je_@nallocx(size_t size, int flags)\n    JEMALLOC_ATTR(pure);\n\nJEMALLOC_EXPORT int JEMALLOC_NOTHROW\t@je_@mallctl(const char *name,\n    void *oldp, size_t *oldlenp, void *newp, size_t newlen);\nJEMALLOC_EXPORT int JEMALLOC_NOTHROW\t@je_@mallctlnametomib(const char *name,\n    size_t *mibp, size_t *miblenp);\nJEMALLOC_EXPORT int JEMALLOC_NOTHROW\t@je_@mallctlbymib(const size_t *mib,\n    size_t miblen, void *oldp, size_t *oldlenp, void *newp, size_t newlen);\nJEMALLOC_EXPORT void JEMALLOC_NOTHROW\t@je_@malloc_stats_print(\n    void (*write_cb)(void *, const char *), void *@je_@cbopaque,\n    const char *opts);\nJEMALLOC_EXPORT size_t JEMALLOC_NOTHROW\t@je_@malloc_usable_size(\n    JEMALLOC_USABLE_SIZE_CONST void *ptr) JEMALLOC_CXX_THROW;\n\n#ifdef JEMALLOC_OVERRIDE_MEMALIGN\nJEMALLOC_EXPORT JEMALLOC_ALLOCATOR JEMALLOC_RESTRICT_RETURN\n    void JEMALLOC_NOTHROW\t*@je_@memalign(size_t alignment, size_t size)\n    JEMALLOC_CXX_THROW JEMALLOC_ATTR(malloc);\n#endif\n\n#ifdef JEMALLOC_OVERRIDE_VALLOC\nJEMALLOC_EXPORT JEMALLOC_ALLOCATOR JEMALLOC_RESTRICT_RETURN\n    void JEMALLOC_NOTHROW\t*@je_@valloc(size_t size) JEMALLOC_CXX_THROW\n    JEMALLOC_ATTR(malloc);\n#endif\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.8/deps/jemalloc/include/jemalloc/jemalloc_rename.sh",
    "content": "#!/bin/sh\n\npublic_symbols_txt=$1\n\ncat <<EOF\n/*\n * Name mangling for public symbols is controlled by --with-mangling and\n * --with-jemalloc-prefix.  With default settings the je_ prefix is stripped by\n * these macro definitions.\n */\n#ifndef JEMALLOC_NO_RENAME\nEOF\n\nfor nm in `cat ${public_symbols_txt}` ; do\n  n=`echo ${nm} |tr ':' ' ' |awk '{print $1}'`\n  m=`echo ${nm} |tr ':' ' ' |awk '{print $2}'`\n  echo \"#  define je_${n} ${m}\"\ndone\n\ncat <<EOF\n#endif\nEOF\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.8/deps/jemalloc/include/jemalloc/jemalloc_typedefs.h.in",
    "content": "/*\n * void *\n * chunk_alloc(void *new_addr, size_t size, size_t alignment, bool *zero,\n *     bool *commit, unsigned arena_ind);\n */\ntypedef void *(chunk_alloc_t)(void *, size_t, size_t, bool *, bool *, unsigned);\n\n/*\n * bool\n * chunk_dalloc(void *chunk, size_t size, bool committed, unsigned arena_ind);\n */\ntypedef bool (chunk_dalloc_t)(void *, size_t, bool, unsigned);\n\n/*\n * bool\n * chunk_commit(void *chunk, size_t size, size_t offset, size_t length,\n *     unsigned arena_ind);\n */\ntypedef bool (chunk_commit_t)(void *, size_t, size_t, size_t, unsigned);\n\n/*\n * bool\n * chunk_decommit(void *chunk, size_t size, size_t offset, size_t length,\n *     unsigned arena_ind);\n */\ntypedef bool (chunk_decommit_t)(void *, size_t, size_t, size_t, unsigned);\n\n/*\n * bool\n * chunk_purge(void *chunk, size_t size, size_t offset, size_t length,\n *     unsigned arena_ind);\n */\ntypedef bool (chunk_purge_t)(void *, size_t, size_t, size_t, unsigned);\n\n/*\n * bool\n * chunk_split(void *chunk, size_t size, size_t size_a, size_t size_b,\n *     bool committed, unsigned arena_ind);\n */\ntypedef bool (chunk_split_t)(void *, size_t, size_t, size_t, bool, unsigned);\n\n/*\n * bool\n * chunk_merge(void *chunk_a, size_t size_a, void *chunk_b, size_t size_b,\n *     bool committed, unsigned arena_ind);\n */\ntypedef bool (chunk_merge_t)(void *, size_t, void *, size_t, bool, unsigned);\n\ntypedef struct {\n\tchunk_alloc_t\t\t*alloc;\n\tchunk_dalloc_t\t\t*dalloc;\n\tchunk_commit_t\t\t*commit;\n\tchunk_decommit_t\t*decommit;\n\tchunk_purge_t\t\t*purge;\n\tchunk_split_t\t\t*split;\n\tchunk_merge_t\t\t*merge;\n} chunk_hooks_t;\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.8/deps/jemalloc/include/msvc_compat/C99/stdbool.h",
    "content": "#ifndef stdbool_h\n#define stdbool_h\n\n#include <wtypes.h>\n\n/* MSVC doesn't define _Bool or bool in C, but does have BOOL */\n/* Note this doesn't pass autoconf's test because (bool) 0.5 != true */\n/* Clang-cl uses MSVC headers, so needs msvc_compat, but has _Bool as\n * a built-in type. */\n#ifndef __clang__\ntypedef BOOL _Bool;\n#endif\n\n#define bool _Bool\n#define true 1\n#define false 0\n\n#define __bool_true_false_are_defined 1\n\n#endif /* stdbool_h */\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.8/deps/jemalloc/include/msvc_compat/C99/stdint.h",
    "content": "// ISO C9x  compliant stdint.h for Microsoft Visual Studio\n// Based on ISO/IEC 9899:TC2 Committee draft (May 6, 2005) WG14/N1124 \n// \n//  Copyright (c) 2006-2008 Alexander Chemeris\n// \n// Redistribution and use in source and binary forms, with or without\n// modification, are permitted provided that the following conditions are met:\n// \n//   1. Redistributions of source code must retain the above copyright notice,\n//      this list of conditions and the following disclaimer.\n// \n//   2. Redistributions in binary form must reproduce the above copyright\n//      notice, this list of conditions and the following disclaimer in the\n//      documentation and/or other materials provided with the distribution.\n// \n//   3. The name of the author may be used to endorse or promote products\n//      derived from this software without specific prior written permission.\n// \n// THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED\n// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF\n// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO\n// EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,\n// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;\n// OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, \n// WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR\n// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF\n// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n// \n///////////////////////////////////////////////////////////////////////////////\n\n#ifndef _MSC_VER // [\n#error \"Use this header only with Microsoft Visual C++ compilers!\"\n#endif // _MSC_VER ]\n\n#ifndef _MSC_STDINT_H_ // [\n#define _MSC_STDINT_H_\n\n#if _MSC_VER > 1000\n#pragma once\n#endif\n\n#include <limits.h>\n\n// For Visual Studio 6 in C++ mode and for many Visual Studio versions when\n// compiling for ARM we should wrap <wchar.h> include with 'extern \"C++\" {}'\n// or compiler give many errors like this:\n//   error C2733: second C linkage of overloaded function 'wmemchr' not allowed\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n#  include <wchar.h>\n#ifdef __cplusplus\n}\n#endif\n\n// Define _W64 macros to mark types changing their size, like intptr_t.\n#ifndef _W64\n#  if !defined(__midl) && (defined(_X86_) || defined(_M_IX86)) && _MSC_VER >= 1300\n#     define _W64 __w64\n#  else\n#     define _W64\n#  endif\n#endif\n\n\n// 7.18.1 Integer types\n\n// 7.18.1.1 Exact-width integer types\n\n// Visual Studio 6 and Embedded Visual C++ 4 doesn't\n// realize that, e.g. char has the same size as __int8\n// so we give up on __intX for them.\n#if (_MSC_VER < 1300)\n   typedef signed char       int8_t;\n   typedef signed short      int16_t;\n   typedef signed int        int32_t;\n   typedef unsigned char     uint8_t;\n   typedef unsigned short    uint16_t;\n   typedef unsigned int      uint32_t;\n#else\n   typedef signed __int8     int8_t;\n   typedef signed __int16    int16_t;\n   typedef signed __int32    int32_t;\n   typedef unsigned __int8   uint8_t;\n   typedef unsigned __int16  uint16_t;\n   typedef unsigned __int32  uint32_t;\n#endif\ntypedef signed __int64       int64_t;\ntypedef unsigned __int64     uint64_t;\n\n\n// 7.18.1.2 Minimum-width integer types\ntypedef int8_t    int_least8_t;\ntypedef int16_t   int_least16_t;\ntypedef int32_t   int_least32_t;\ntypedef int64_t   int_least64_t;\ntypedef uint8_t   uint_least8_t;\ntypedef uint16_t  uint_least16_t;\ntypedef uint32_t  uint_least32_t;\ntypedef uint64_t  uint_least64_t;\n\n// 7.18.1.3 Fastest minimum-width integer types\ntypedef int8_t    int_fast8_t;\ntypedef int16_t   int_fast16_t;\ntypedef int32_t   int_fast32_t;\ntypedef int64_t   int_fast64_t;\ntypedef uint8_t   uint_fast8_t;\ntypedef uint16_t  uint_fast16_t;\ntypedef uint32_t  uint_fast32_t;\ntypedef uint64_t  uint_fast64_t;\n\n// 7.18.1.4 Integer types capable of holding object pointers\n#ifdef _WIN64 // [\n   typedef signed __int64    intptr_t;\n   typedef unsigned __int64  uintptr_t;\n#else // _WIN64 ][\n   typedef _W64 signed int   intptr_t;\n   typedef _W64 unsigned int uintptr_t;\n#endif // _WIN64 ]\n\n// 7.18.1.5 Greatest-width integer types\ntypedef int64_t   intmax_t;\ntypedef uint64_t  uintmax_t;\n\n\n// 7.18.2 Limits of specified-width integer types\n\n#if !defined(__cplusplus) || defined(__STDC_LIMIT_MACROS) // [   See footnote 220 at page 257 and footnote 221 at page 259\n\n// 7.18.2.1 Limits of exact-width integer types\n#define INT8_MIN     ((int8_t)_I8_MIN)\n#define INT8_MAX     _I8_MAX\n#define INT16_MIN    ((int16_t)_I16_MIN)\n#define INT16_MAX    _I16_MAX\n#define INT32_MIN    ((int32_t)_I32_MIN)\n#define INT32_MAX    _I32_MAX\n#define INT64_MIN    ((int64_t)_I64_MIN)\n#define INT64_MAX    _I64_MAX\n#define UINT8_MAX    _UI8_MAX\n#define UINT16_MAX   _UI16_MAX\n#define UINT32_MAX   _UI32_MAX\n#define UINT64_MAX   _UI64_MAX\n\n// 7.18.2.2 Limits of minimum-width integer types\n#define INT_LEAST8_MIN    INT8_MIN\n#define INT_LEAST8_MAX    INT8_MAX\n#define INT_LEAST16_MIN   INT16_MIN\n#define INT_LEAST16_MAX   INT16_MAX\n#define INT_LEAST32_MIN   INT32_MIN\n#define INT_LEAST32_MAX   INT32_MAX\n#define INT_LEAST64_MIN   INT64_MIN\n#define INT_LEAST64_MAX   INT64_MAX\n#define UINT_LEAST8_MAX   UINT8_MAX\n#define UINT_LEAST16_MAX  UINT16_MAX\n#define UINT_LEAST32_MAX  UINT32_MAX\n#define UINT_LEAST64_MAX  UINT64_MAX\n\n// 7.18.2.3 Limits of fastest minimum-width integer types\n#define INT_FAST8_MIN    INT8_MIN\n#define INT_FAST8_MAX    INT8_MAX\n#define INT_FAST16_MIN   INT16_MIN\n#define INT_FAST16_MAX   INT16_MAX\n#define INT_FAST32_MIN   INT32_MIN\n#define INT_FAST32_MAX   INT32_MAX\n#define INT_FAST64_MIN   INT64_MIN\n#define INT_FAST64_MAX   INT64_MAX\n#define UINT_FAST8_MAX   UINT8_MAX\n#define UINT_FAST16_MAX  UINT16_MAX\n#define UINT_FAST32_MAX  UINT32_MAX\n#define UINT_FAST64_MAX  UINT64_MAX\n\n// 7.18.2.4 Limits of integer types capable of holding object pointers\n#ifdef _WIN64 // [\n#  define INTPTR_MIN   INT64_MIN\n#  define INTPTR_MAX   INT64_MAX\n#  define UINTPTR_MAX  UINT64_MAX\n#else // _WIN64 ][\n#  define INTPTR_MIN   INT32_MIN\n#  define INTPTR_MAX   INT32_MAX\n#  define UINTPTR_MAX  UINT32_MAX\n#endif // _WIN64 ]\n\n// 7.18.2.5 Limits of greatest-width integer types\n#define INTMAX_MIN   INT64_MIN\n#define INTMAX_MAX   INT64_MAX\n#define UINTMAX_MAX  UINT64_MAX\n\n// 7.18.3 Limits of other integer types\n\n#ifdef _WIN64 // [\n#  define PTRDIFF_MIN  _I64_MIN\n#  define PTRDIFF_MAX  _I64_MAX\n#else  // _WIN64 ][\n#  define PTRDIFF_MIN  _I32_MIN\n#  define PTRDIFF_MAX  _I32_MAX\n#endif  // _WIN64 ]\n\n#define SIG_ATOMIC_MIN  INT_MIN\n#define SIG_ATOMIC_MAX  INT_MAX\n\n#ifndef SIZE_MAX // [\n#  ifdef _WIN64 // [\n#     define SIZE_MAX  _UI64_MAX\n#  else // _WIN64 ][\n#     define SIZE_MAX  _UI32_MAX\n#  endif // _WIN64 ]\n#endif // SIZE_MAX ]\n\n// WCHAR_MIN and WCHAR_MAX are also defined in <wchar.h>\n#ifndef WCHAR_MIN // [\n#  define WCHAR_MIN  0\n#endif  // WCHAR_MIN ]\n#ifndef WCHAR_MAX // [\n#  define WCHAR_MAX  _UI16_MAX\n#endif  // WCHAR_MAX ]\n\n#define WINT_MIN  0\n#define WINT_MAX  _UI16_MAX\n\n#endif // __STDC_LIMIT_MACROS ]\n\n\n// 7.18.4 Limits of other integer types\n\n#if !defined(__cplusplus) || defined(__STDC_CONSTANT_MACROS) // [   See footnote 224 at page 260\n\n// 7.18.4.1 Macros for minimum-width integer constants\n\n#define INT8_C(val)  val##i8\n#define INT16_C(val) val##i16\n#define INT32_C(val) val##i32\n#define INT64_C(val) val##i64\n\n#define UINT8_C(val)  val##ui8\n#define UINT16_C(val) val##ui16\n#define UINT32_C(val) val##ui32\n#define UINT64_C(val) val##ui64\n\n// 7.18.4.2 Macros for greatest-width integer constants\n#define INTMAX_C   INT64_C\n#define UINTMAX_C  UINT64_C\n\n#endif // __STDC_CONSTANT_MACROS ]\n\n\n#endif // _MSC_STDINT_H_ ]\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.8/deps/jemalloc/include/msvc_compat/strings.h",
    "content": "#ifndef strings_h\n#define strings_h\n\n/* MSVC doesn't define ffs/ffsl. This dummy strings.h header is provided\n * for both */\n#ifdef _MSC_VER\n#  include <intrin.h>\n#  pragma intrinsic(_BitScanForward)\nstatic __forceinline int ffsl(long x)\n{\n\tunsigned long i;\n\n\tif (_BitScanForward(&i, x))\n\t\treturn (i + 1);\n\treturn (0);\n}\n\nstatic __forceinline int ffs(int x)\n{\n\n\treturn (ffsl(x));\n}\n\n#else\n#  define ffsl(x) __builtin_ffsl(x)\n#  define ffs(x) __builtin_ffs(x)\n#endif\n\n#endif /* strings_h */\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.8/deps/jemalloc/include/msvc_compat/windows_extra.h",
    "content": "#ifndef MSVC_COMPAT_WINDOWS_EXTRA_H\n#define\tMSVC_COMPAT_WINDOWS_EXTRA_H\n\n#ifndef ENOENT\n#  define ENOENT ERROR_PATH_NOT_FOUND\n#endif\n#ifndef EINVAL\n#  define EINVAL ERROR_BAD_ARGUMENTS\n#endif\n#ifndef EAGAIN\n#  define EAGAIN ERROR_OUTOFMEMORY\n#endif\n#ifndef EPERM\n#  define EPERM  ERROR_WRITE_FAULT\n#endif\n#ifndef EFAULT\n#  define EFAULT ERROR_INVALID_ADDRESS\n#endif\n#ifndef ENOMEM\n#  define ENOMEM ERROR_NOT_ENOUGH_MEMORY\n#endif\n#ifndef ERANGE\n#  define ERANGE ERROR_INVALID_DATA\n#endif\n\n#endif /* MSVC_COMPAT_WINDOWS_EXTRA_H */\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.8/deps/jemalloc/install-sh",
    "content": "#! /bin/sh\n#\n# install - install a program, script, or datafile\n# This comes from X11R5 (mit/util/scripts/install.sh).\n#\n# Copyright 1991 by the Massachusetts Institute of Technology\n#\n# Permission to use, copy, modify, distribute, and sell this software and its\n# documentation for any purpose is hereby granted without fee, provided that\n# the above copyright notice appear in all copies and that both that\n# copyright notice and this permission notice appear in supporting\n# documentation, and that the name of M.I.T. not be used in advertising or\n# publicity pertaining to distribution of the software without specific,\n# written prior permission.  M.I.T. makes no representations about the\n# suitability of this software for any purpose.  It is provided \"as is\"\n# without express or implied warranty.\n#\n# Calling this script install-sh is preferred over install.sh, to prevent\n# `make' implicit rules from creating a file called install from it\n# when there is no Makefile.\n#\n# This script is compatible with the BSD install script, but was written\n# from scratch.  It can only install one file at a time, a restriction\n# shared with many OS's install programs.\n\n\n# set DOITPROG to echo to test this script\n\n# Don't use :- since 4.3BSD and earlier shells don't like it.\ndoit=\"${DOITPROG-}\"\n\n\n# put in absolute paths if you don't have them in your path; or use env. vars.\n\nmvprog=\"${MVPROG-mv}\"\ncpprog=\"${CPPROG-cp}\"\nchmodprog=\"${CHMODPROG-chmod}\"\nchownprog=\"${CHOWNPROG-chown}\"\nchgrpprog=\"${CHGRPPROG-chgrp}\"\nstripprog=\"${STRIPPROG-strip}\"\nrmprog=\"${RMPROG-rm}\"\nmkdirprog=\"${MKDIRPROG-mkdir}\"\n\ntransformbasename=\"\"\ntransform_arg=\"\"\ninstcmd=\"$mvprog\"\nchmodcmd=\"$chmodprog 0755\"\nchowncmd=\"\"\nchgrpcmd=\"\"\nstripcmd=\"\"\nrmcmd=\"$rmprog -f\"\nmvcmd=\"$mvprog\"\nsrc=\"\"\ndst=\"\"\ndir_arg=\"\"\n\nwhile [ x\"$1\" != x ]; do\n    case $1 in\n\t-c) instcmd=\"$cpprog\"\n\t    shift\n\t    continue;;\n\n\t-d) dir_arg=true\n\t    shift\n\t    continue;;\n\n\t-m) chmodcmd=\"$chmodprog $2\"\n\t    shift\n\t    shift\n\t    continue;;\n\n\t-o) chowncmd=\"$chownprog $2\"\n\t    shift\n\t    shift\n\t    continue;;\n\n\t-g) chgrpcmd=\"$chgrpprog $2\"\n\t    shift\n\t    shift\n\t    continue;;\n\n\t-s) stripcmd=\"$stripprog\"\n\t    shift\n\t    continue;;\n\n\t-t=*) transformarg=`echo $1 | sed 's/-t=//'`\n\t    shift\n\t    continue;;\n\n\t-b=*) transformbasename=`echo $1 | sed 's/-b=//'`\n\t    shift\n\t    continue;;\n\n\t*)  if [ x\"$src\" = x ]\n\t    then\n\t\tsrc=$1\n\t    else\n\t\t# this colon is to work around a 386BSD /bin/sh bug\n\t\t:\n\t\tdst=$1\n\t    fi\n\t    shift\n\t    continue;;\n    esac\ndone\n\nif [ x\"$src\" = x ]\nthen\n\techo \"install:\tno input file specified\"\n\texit 1\nelse\n\ttrue\nfi\n\nif [ x\"$dir_arg\" != x ]; then\n\tdst=$src\n\tsrc=\"\"\n\t\n\tif [ -d $dst ]; then\n\t\tinstcmd=:\n\telse\n\t\tinstcmd=mkdir\n\tfi\nelse\n\n# Waiting for this to be detected by the \"$instcmd $src $dsttmp\" command\n# might cause directories to be created, which would be especially bad \n# if $src (and thus $dsttmp) contains '*'.\n\n\tif [ -f $src -o -d $src ]\n\tthen\n\t\ttrue\n\telse\n\t\techo \"install:  $src does not exist\"\n\t\texit 1\n\tfi\n\t\n\tif [ x\"$dst\" = x ]\n\tthen\n\t\techo \"install:\tno destination specified\"\n\t\texit 1\n\telse\n\t\ttrue\n\tfi\n\n# If destination is a directory, append the input filename; if your system\n# does not like double slashes in filenames, you may need to add some logic\n\n\tif [ -d $dst ]\n\tthen\n\t\tdst=\"$dst\"/`basename $src`\n\telse\n\t\ttrue\n\tfi\nfi\n\n## this sed command emulates the dirname command\ndstdir=`echo $dst | sed -e 's,[^/]*$,,;s,/$,,;s,^$,.,'`\n\n# Make sure that the destination directory exists.\n#  this part is taken from Noah Friedman's mkinstalldirs script\n\n# Skip lots of stat calls in the usual case.\nif [ ! -d \"$dstdir\" ]; then\ndefaultIFS='\t\n'\nIFS=\"${IFS-${defaultIFS}}\"\n\noIFS=\"${IFS}\"\n# Some sh's can't handle IFS=/ for some reason.\nIFS='%'\nset - `echo ${dstdir} | sed -e 's@/@%@g' -e 's@^%@/@'`\nIFS=\"${oIFS}\"\n\npathcomp=''\n\nwhile [ $# -ne 0 ] ; do\n\tpathcomp=\"${pathcomp}${1}\"\n\tshift\n\n\tif [ ! -d \"${pathcomp}\" ] ;\n        then\n\t\t$mkdirprog \"${pathcomp}\"\n\telse\n\t\ttrue\n\tfi\n\n\tpathcomp=\"${pathcomp}/\"\ndone\nfi\n\nif [ x\"$dir_arg\" != x ]\nthen\n\t$doit $instcmd $dst &&\n\n\tif [ x\"$chowncmd\" != x ]; then $doit $chowncmd $dst; else true ; fi &&\n\tif [ x\"$chgrpcmd\" != x ]; then $doit $chgrpcmd $dst; else true ; fi &&\n\tif [ x\"$stripcmd\" != x ]; then $doit $stripcmd $dst; else true ; fi &&\n\tif [ x\"$chmodcmd\" != x ]; then $doit $chmodcmd $dst; else true ; fi\nelse\n\n# If we're going to rename the final executable, determine the name now.\n\n\tif [ x\"$transformarg\" = x ] \n\tthen\n\t\tdstfile=`basename $dst`\n\telse\n\t\tdstfile=`basename $dst $transformbasename | \n\t\t\tsed $transformarg`$transformbasename\n\tfi\n\n# don't allow the sed command to completely eliminate the filename\n\n\tif [ x\"$dstfile\" = x ] \n\tthen\n\t\tdstfile=`basename $dst`\n\telse\n\t\ttrue\n\tfi\n\n# Make a temp file name in the proper directory.\n\n\tdsttmp=$dstdir/#inst.$$#\n\n# Move or copy the file name to the temp name\n\n\t$doit $instcmd $src $dsttmp &&\n\n\ttrap \"rm -f ${dsttmp}\" 0 &&\n\n# and set any options; do chmod last to preserve setuid bits\n\n# If any of these fail, we abort the whole thing.  If we want to\n# ignore errors from any of these, just make sure not to ignore\n# errors from the above \"$doit $instcmd $src $dsttmp\" command.\n\n\tif [ x\"$chowncmd\" != x ]; then $doit $chowncmd $dsttmp; else true;fi &&\n\tif [ x\"$chgrpcmd\" != x ]; then $doit $chgrpcmd $dsttmp; else true;fi &&\n\tif [ x\"$stripcmd\" != x ]; then $doit $stripcmd $dsttmp; else true;fi &&\n\tif [ x\"$chmodcmd\" != x ]; then $doit $chmodcmd $dsttmp; else true;fi &&\n\n# Now rename the file to the real destination.\n\n\t$doit $rmcmd -f $dstdir/$dstfile &&\n\t$doit $mvcmd $dsttmp $dstdir/$dstfile \n\nfi &&\n\n\nexit 0\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.8/deps/jemalloc/jemalloc.pc.in",
    "content": "prefix=@prefix@\nexec_prefix=@exec_prefix@\nlibdir=@libdir@\nincludedir=@includedir@\ninstall_suffix=@install_suffix@\n\nName: jemalloc\nDescription: A general purpose malloc(3) implementation that emphasizes fragmentation avoidance and scalable concurrency support.\nURL: http://www.canonware.com/jemalloc\nVersion: @jemalloc_version@\nCflags: -I${includedir}\nLibs: -L${libdir} -ljemalloc${install_suffix}\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.8/deps/jemalloc/src/arena.c",
    "content": "#define\tJEMALLOC_ARENA_C_\n#include \"jemalloc/internal/jemalloc_internal.h\"\n\n/******************************************************************************/\n/* Data. */\n\nssize_t\t\topt_lg_dirty_mult = LG_DIRTY_MULT_DEFAULT;\nstatic ssize_t\tlg_dirty_mult_default;\narena_bin_info_t\tarena_bin_info[NBINS];\n\nsize_t\t\tmap_bias;\nsize_t\t\tmap_misc_offset;\nsize_t\t\tarena_maxrun; /* Max run size for arenas. */\nsize_t\t\tlarge_maxclass; /* Max large size class. */\nstatic size_t\tsmall_maxrun; /* Max run size used for small size classes. */\nstatic bool\t*small_run_tab; /* Valid small run page multiples. */\nunsigned\tnlclasses; /* Number of large size classes. */\nunsigned\tnhclasses; /* Number of huge size classes. */\n\n/******************************************************************************/\n/*\n * Function prototypes for static functions that are referenced prior to\n * definition.\n */\n\nstatic void\tarena_purge(arena_t *arena, bool all);\nstatic void\tarena_run_dalloc(arena_t *arena, arena_run_t *run, bool dirty,\n    bool cleaned, bool decommitted);\nstatic void\tarena_dalloc_bin_run(arena_t *arena, arena_chunk_t *chunk,\n    arena_run_t *run, arena_bin_t *bin);\nstatic void\tarena_bin_lower_run(arena_t *arena, arena_chunk_t *chunk,\n    arena_run_t *run, arena_bin_t *bin);\n\n/******************************************************************************/\n\n#define\tCHUNK_MAP_KEY\t\t((uintptr_t)0x1U)\n\nJEMALLOC_INLINE_C arena_chunk_map_misc_t *\narena_miscelm_key_create(size_t size)\n{\n\n\treturn ((arena_chunk_map_misc_t *)(arena_mapbits_size_encode(size) |\n\t    CHUNK_MAP_KEY));\n}\n\nJEMALLOC_INLINE_C bool\narena_miscelm_is_key(const arena_chunk_map_misc_t *miscelm)\n{\n\n\treturn (((uintptr_t)miscelm & CHUNK_MAP_KEY) != 0);\n}\n\n#undef CHUNK_MAP_KEY\n\nJEMALLOC_INLINE_C size_t\narena_miscelm_key_size_get(const arena_chunk_map_misc_t *miscelm)\n{\n\n\tassert(arena_miscelm_is_key(miscelm));\n\n\treturn (arena_mapbits_size_decode((uintptr_t)miscelm));\n}\n\nJEMALLOC_INLINE_C size_t\narena_miscelm_size_get(arena_chunk_map_misc_t *miscelm)\n{\n\tarena_chunk_t *chunk;\n\tsize_t pageind, mapbits;\n\n\tassert(!arena_miscelm_is_key(miscelm));\n\n\tchunk = (arena_chunk_t *)CHUNK_ADDR2BASE(miscelm);\n\tpageind = arena_miscelm_to_pageind(miscelm);\n\tmapbits = arena_mapbits_get(chunk, pageind);\n\treturn (arena_mapbits_size_decode(mapbits));\n}\n\nJEMALLOC_INLINE_C int\narena_run_comp(arena_chunk_map_misc_t *a, arena_chunk_map_misc_t *b)\n{\n\tuintptr_t a_miscelm = (uintptr_t)a;\n\tuintptr_t b_miscelm = (uintptr_t)b;\n\n\tassert(a != NULL);\n\tassert(b != NULL);\n\n\treturn ((a_miscelm > b_miscelm) - (a_miscelm < b_miscelm));\n}\n\n/* Generate red-black tree functions. */\nrb_gen(static UNUSED, arena_run_tree_, arena_run_tree_t, arena_chunk_map_misc_t,\n    rb_link, arena_run_comp)\n\nstatic size_t\nrun_quantize(size_t size)\n{\n\tsize_t qsize;\n\n\tassert(size != 0);\n\tassert(size == PAGE_CEILING(size));\n\n\t/* Don't change sizes that are valid small run sizes. */\n\tif (size <= small_maxrun && small_run_tab[size >> LG_PAGE])\n\t\treturn (size);\n\n\t/*\n\t * Round down to the nearest run size that can actually be requested\n\t * during normal large allocation.  Add large_pad so that cache index\n\t * randomization can offset the allocation from the page boundary.\n\t */\n\tqsize = index2size(size2index(size - large_pad + 1) - 1) + large_pad;\n\tif (qsize <= SMALL_MAXCLASS + large_pad)\n\t\treturn (run_quantize(size - large_pad));\n\tassert(qsize <= size);\n\treturn (qsize);\n}\n\nstatic size_t\nrun_quantize_next(size_t size)\n{\n\tsize_t large_run_size_next;\n\n\tassert(size != 0);\n\tassert(size == PAGE_CEILING(size));\n\n\t/*\n\t * Return the next quantized size greater than the input size.\n\t * Quantized sizes comprise the union of run sizes that back small\n\t * region runs, and run sizes that back large regions with no explicit\n\t * alignment constraints.\n\t */\n\n\tif (size > SMALL_MAXCLASS) {\n\t\tlarge_run_size_next = PAGE_CEILING(index2size(size2index(size -\n\t\t    large_pad) + 1) + large_pad);\n\t} else\n\t\tlarge_run_size_next = SIZE_T_MAX;\n\tif (size >= small_maxrun)\n\t\treturn (large_run_size_next);\n\n\twhile (true) {\n\t\tsize += PAGE;\n\t\tassert(size <= small_maxrun);\n\t\tif (small_run_tab[size >> LG_PAGE]) {\n\t\t\tif (large_run_size_next < size)\n\t\t\t\treturn (large_run_size_next);\n\t\t\treturn (size);\n\t\t}\n\t}\n}\n\nstatic size_t\nrun_quantize_first(size_t size)\n{\n\tsize_t qsize = run_quantize(size);\n\n\tif (qsize < size) {\n\t\t/*\n\t\t * Skip a quantization that may have an adequately large run,\n\t\t * because under-sized runs may be mixed in.  This only happens\n\t\t * when an unusual size is requested, i.e. for aligned\n\t\t * allocation, and is just one of several places where linear\n\t\t * search would potentially find sufficiently aligned available\n\t\t * memory somewhere lower.\n\t\t */\n\t\tqsize = run_quantize_next(size);\n\t}\n\treturn (qsize);\n}\n\nJEMALLOC_INLINE_C int\narena_avail_comp(arena_chunk_map_misc_t *a, arena_chunk_map_misc_t *b)\n{\n\tint ret;\n\tuintptr_t a_miscelm = (uintptr_t)a;\n\tsize_t a_qsize = run_quantize(arena_miscelm_is_key(a) ?\n\t    arena_miscelm_key_size_get(a) : arena_miscelm_size_get(a));\n\tsize_t b_qsize = run_quantize(arena_miscelm_size_get(b));\n\n\t/*\n\t * Compare based on quantized size rather than size, in order to sort\n\t * equally useful runs only by address.\n\t */\n\tret = (a_qsize > b_qsize) - (a_qsize < b_qsize);\n\tif (ret == 0) {\n\t\tif (!arena_miscelm_is_key(a)) {\n\t\t\tuintptr_t b_miscelm = (uintptr_t)b;\n\n\t\t\tret = (a_miscelm > b_miscelm) - (a_miscelm < b_miscelm);\n\t\t} else {\n\t\t\t/*\n\t\t\t * Treat keys as if they are lower than anything else.\n\t\t\t */\n\t\t\tret = -1;\n\t\t}\n\t}\n\n\treturn (ret);\n}\n\n/* Generate red-black tree functions. */\nrb_gen(static UNUSED, arena_avail_tree_, arena_avail_tree_t,\n    arena_chunk_map_misc_t, rb_link, arena_avail_comp)\n\nstatic void\narena_avail_insert(arena_t *arena, arena_chunk_t *chunk, size_t pageind,\n    size_t npages)\n{\n\n\tassert(npages == (arena_mapbits_unallocated_size_get(chunk, pageind) >>\n\t    LG_PAGE));\n\tarena_avail_tree_insert(&arena->runs_avail, arena_miscelm_get(chunk,\n\t    pageind));\n}\n\nstatic void\narena_avail_remove(arena_t *arena, arena_chunk_t *chunk, size_t pageind,\n    size_t npages)\n{\n\n\tassert(npages == (arena_mapbits_unallocated_size_get(chunk, pageind) >>\n\t    LG_PAGE));\n\tarena_avail_tree_remove(&arena->runs_avail, arena_miscelm_get(chunk,\n\t    pageind));\n}\n\nstatic void\narena_run_dirty_insert(arena_t *arena, arena_chunk_t *chunk, size_t pageind,\n    size_t npages)\n{\n\tarena_chunk_map_misc_t *miscelm = arena_miscelm_get(chunk, pageind);\n\n\tassert(npages == (arena_mapbits_unallocated_size_get(chunk, pageind) >>\n\t    LG_PAGE));\n\tassert(arena_mapbits_dirty_get(chunk, pageind) == CHUNK_MAP_DIRTY);\n\tassert(arena_mapbits_dirty_get(chunk, pageind+npages-1) ==\n\t    CHUNK_MAP_DIRTY);\n\n\tqr_new(&miscelm->rd, rd_link);\n\tqr_meld(&arena->runs_dirty, &miscelm->rd, rd_link);\n\tarena->ndirty += npages;\n}\n\nstatic void\narena_run_dirty_remove(arena_t *arena, arena_chunk_t *chunk, size_t pageind,\n    size_t npages)\n{\n\tarena_chunk_map_misc_t *miscelm = arena_miscelm_get(chunk, pageind);\n\n\tassert(npages == (arena_mapbits_unallocated_size_get(chunk, pageind) >>\n\t    LG_PAGE));\n\tassert(arena_mapbits_dirty_get(chunk, pageind) == CHUNK_MAP_DIRTY);\n\tassert(arena_mapbits_dirty_get(chunk, pageind+npages-1) ==\n\t    CHUNK_MAP_DIRTY);\n\n\tqr_remove(&miscelm->rd, rd_link);\n\tassert(arena->ndirty >= npages);\n\tarena->ndirty -= npages;\n}\n\nstatic size_t\narena_chunk_dirty_npages(const extent_node_t *node)\n{\n\n\treturn (extent_node_size_get(node) >> LG_PAGE);\n}\n\nvoid\narena_chunk_cache_maybe_insert(arena_t *arena, extent_node_t *node, bool cache)\n{\n\n\tif (cache) {\n\t\textent_node_dirty_linkage_init(node);\n\t\textent_node_dirty_insert(node, &arena->runs_dirty,\n\t\t    &arena->chunks_cache);\n\t\tarena->ndirty += arena_chunk_dirty_npages(node);\n\t}\n}\n\nvoid\narena_chunk_cache_maybe_remove(arena_t *arena, extent_node_t *node, bool dirty)\n{\n\n\tif (dirty) {\n\t\textent_node_dirty_remove(node);\n\t\tassert(arena->ndirty >= arena_chunk_dirty_npages(node));\n\t\tarena->ndirty -= arena_chunk_dirty_npages(node);\n\t}\n}\n\nJEMALLOC_INLINE_C void *\narena_run_reg_alloc(arena_run_t *run, arena_bin_info_t *bin_info)\n{\n\tvoid *ret;\n\tunsigned regind;\n\tarena_chunk_map_misc_t *miscelm;\n\tvoid *rpages;\n\n\tassert(run->nfree > 0);\n\tassert(!bitmap_full(run->bitmap, &bin_info->bitmap_info));\n\n\tregind = bitmap_sfu(run->bitmap, &bin_info->bitmap_info);\n\tmiscelm = arena_run_to_miscelm(run);\n\trpages = arena_miscelm_to_rpages(miscelm);\n\tret = (void *)((uintptr_t)rpages + (uintptr_t)bin_info->reg0_offset +\n\t    (uintptr_t)(bin_info->reg_interval * regind));\n\trun->nfree--;\n\treturn (ret);\n}\n\nJEMALLOC_INLINE_C void\narena_run_reg_dalloc(arena_run_t *run, void *ptr)\n{\n\tarena_chunk_t *chunk = (arena_chunk_t *)CHUNK_ADDR2BASE(run);\n\tsize_t pageind = ((uintptr_t)ptr - (uintptr_t)chunk) >> LG_PAGE;\n\tsize_t mapbits = arena_mapbits_get(chunk, pageind);\n\tszind_t binind = arena_ptr_small_binind_get(ptr, mapbits);\n\tarena_bin_info_t *bin_info = &arena_bin_info[binind];\n\tunsigned regind = arena_run_regind(run, bin_info, ptr);\n\n\tassert(run->nfree < bin_info->nregs);\n\t/* Freeing an interior pointer can cause assertion failure. */\n\tassert(((uintptr_t)ptr -\n\t    ((uintptr_t)arena_miscelm_to_rpages(arena_run_to_miscelm(run)) +\n\t    (uintptr_t)bin_info->reg0_offset)) %\n\t    (uintptr_t)bin_info->reg_interval == 0);\n\tassert((uintptr_t)ptr >=\n\t    (uintptr_t)arena_miscelm_to_rpages(arena_run_to_miscelm(run)) +\n\t    (uintptr_t)bin_info->reg0_offset);\n\t/* Freeing an unallocated pointer can cause assertion failure. */\n\tassert(bitmap_get(run->bitmap, &bin_info->bitmap_info, regind));\n\n\tbitmap_unset(run->bitmap, &bin_info->bitmap_info, regind);\n\trun->nfree++;\n}\n\nJEMALLOC_INLINE_C void\narena_run_zero(arena_chunk_t *chunk, size_t run_ind, size_t npages)\n{\n\n\tJEMALLOC_VALGRIND_MAKE_MEM_UNDEFINED((void *)((uintptr_t)chunk +\n\t    (run_ind << LG_PAGE)), (npages << LG_PAGE));\n\tmemset((void *)((uintptr_t)chunk + (run_ind << LG_PAGE)), 0,\n\t    (npages << LG_PAGE));\n}\n\nJEMALLOC_INLINE_C void\narena_run_page_mark_zeroed(arena_chunk_t *chunk, size_t run_ind)\n{\n\n\tJEMALLOC_VALGRIND_MAKE_MEM_DEFINED((void *)((uintptr_t)chunk + (run_ind\n\t    << LG_PAGE)), PAGE);\n}\n\nJEMALLOC_INLINE_C void\narena_run_page_validate_zeroed(arena_chunk_t *chunk, size_t run_ind)\n{\n\tsize_t i;\n\tUNUSED size_t *p = (size_t *)((uintptr_t)chunk + (run_ind << LG_PAGE));\n\n\tarena_run_page_mark_zeroed(chunk, run_ind);\n\tfor (i = 0; i < PAGE / sizeof(size_t); i++)\n\t\tassert(p[i] == 0);\n}\n\nstatic void\narena_cactive_update(arena_t *arena, size_t add_pages, size_t sub_pages)\n{\n\n\tif (config_stats) {\n\t\tssize_t cactive_diff = CHUNK_CEILING((arena->nactive + add_pages\n\t\t    - sub_pages) << LG_PAGE) - CHUNK_CEILING(arena->nactive <<\n\t\t    LG_PAGE);\n\t\tif (cactive_diff != 0)\n\t\t\tstats_cactive_add(cactive_diff);\n\t}\n}\n\nstatic void\narena_run_split_remove(arena_t *arena, arena_chunk_t *chunk, size_t run_ind,\n    size_t flag_dirty, size_t flag_decommitted, size_t need_pages)\n{\n\tsize_t total_pages, rem_pages;\n\n\tassert(flag_dirty == 0 || flag_decommitted == 0);\n\n\ttotal_pages = arena_mapbits_unallocated_size_get(chunk, run_ind) >>\n\t    LG_PAGE;\n\tassert(arena_mapbits_dirty_get(chunk, run_ind+total_pages-1) ==\n\t    flag_dirty);\n\tassert(need_pages <= total_pages);\n\trem_pages = total_pages - need_pages;\n\n\tarena_avail_remove(arena, chunk, run_ind, total_pages);\n\tif (flag_dirty != 0)\n\t\tarena_run_dirty_remove(arena, chunk, run_ind, total_pages);\n\tarena_cactive_update(arena, need_pages, 0);\n\tarena->nactive += need_pages;\n\n\t/* Keep track of trailing unused pages for later use. */\n\tif (rem_pages > 0) {\n\t\tsize_t flags = flag_dirty | flag_decommitted;\n\t\tsize_t flag_unzeroed_mask = (flags == 0) ?  CHUNK_MAP_UNZEROED :\n\t\t    0;\n\n\t\tarena_mapbits_unallocated_set(chunk, run_ind+need_pages,\n\t\t    (rem_pages << LG_PAGE), flags |\n\t\t    (arena_mapbits_unzeroed_get(chunk, run_ind+need_pages) &\n\t\t    flag_unzeroed_mask));\n\t\tarena_mapbits_unallocated_set(chunk, run_ind+total_pages-1,\n\t\t    (rem_pages << LG_PAGE), flags |\n\t\t    (arena_mapbits_unzeroed_get(chunk, run_ind+total_pages-1) &\n\t\t    flag_unzeroed_mask));\n\t\tif (flag_dirty != 0) {\n\t\t\tarena_run_dirty_insert(arena, chunk, run_ind+need_pages,\n\t\t\t    rem_pages);\n\t\t}\n\t\tarena_avail_insert(arena, chunk, run_ind+need_pages, rem_pages);\n\t}\n}\n\nstatic bool\narena_run_split_large_helper(arena_t *arena, arena_run_t *run, size_t size,\n    bool remove, bool zero)\n{\n\tarena_chunk_t *chunk;\n\tarena_chunk_map_misc_t *miscelm;\n\tsize_t flag_dirty, flag_decommitted, run_ind, need_pages;\n\tsize_t flag_unzeroed_mask;\n\n\tchunk = (arena_chunk_t *)CHUNK_ADDR2BASE(run);\n\tmiscelm = arena_run_to_miscelm(run);\n\trun_ind = arena_miscelm_to_pageind(miscelm);\n\tflag_dirty = arena_mapbits_dirty_get(chunk, run_ind);\n\tflag_decommitted = arena_mapbits_decommitted_get(chunk, run_ind);\n\tneed_pages = (size >> LG_PAGE);\n\tassert(need_pages > 0);\n\n\tif (flag_decommitted != 0 && arena->chunk_hooks.commit(chunk, chunksize,\n\t    run_ind << LG_PAGE, size, arena->ind))\n\t\treturn (true);\n\n\tif (remove) {\n\t\tarena_run_split_remove(arena, chunk, run_ind, flag_dirty,\n\t\t    flag_decommitted, need_pages);\n\t}\n\n\tif (zero) {\n\t\tif (flag_decommitted != 0) {\n\t\t\t/* The run is untouched, and therefore zeroed. */\n\t\t\tJEMALLOC_VALGRIND_MAKE_MEM_DEFINED((void\n\t\t\t    *)((uintptr_t)chunk + (run_ind << LG_PAGE)),\n\t\t\t    (need_pages << LG_PAGE));\n\t\t} else if (flag_dirty != 0) {\n\t\t\t/* The run is dirty, so all pages must be zeroed. */\n\t\t\tarena_run_zero(chunk, run_ind, need_pages);\n\t\t} else {\n\t\t\t/*\n\t\t\t * The run is clean, so some pages may be zeroed (i.e.\n\t\t\t * never before touched).\n\t\t\t */\n\t\t\tsize_t i;\n\t\t\tfor (i = 0; i < need_pages; i++) {\n\t\t\t\tif (arena_mapbits_unzeroed_get(chunk, run_ind+i)\n\t\t\t\t    != 0)\n\t\t\t\t\tarena_run_zero(chunk, run_ind+i, 1);\n\t\t\t\telse if (config_debug) {\n\t\t\t\t\tarena_run_page_validate_zeroed(chunk,\n\t\t\t\t\t    run_ind+i);\n\t\t\t\t} else {\n\t\t\t\t\tarena_run_page_mark_zeroed(chunk,\n\t\t\t\t\t    run_ind+i);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t} else {\n\t\tJEMALLOC_VALGRIND_MAKE_MEM_UNDEFINED((void *)((uintptr_t)chunk +\n\t\t    (run_ind << LG_PAGE)), (need_pages << LG_PAGE));\n\t}\n\n\t/*\n\t * Set the last element first, in case the run only contains one page\n\t * (i.e. both statements set the same element).\n\t */\n\tflag_unzeroed_mask = (flag_dirty | flag_decommitted) == 0 ?\n\t    CHUNK_MAP_UNZEROED : 0;\n\tarena_mapbits_large_set(chunk, run_ind+need_pages-1, 0, flag_dirty |\n\t    (flag_unzeroed_mask & arena_mapbits_unzeroed_get(chunk,\n\t    run_ind+need_pages-1)));\n\tarena_mapbits_large_set(chunk, run_ind, size, flag_dirty |\n\t    (flag_unzeroed_mask & arena_mapbits_unzeroed_get(chunk, run_ind)));\n\treturn (false);\n}\n\nstatic bool\narena_run_split_large(arena_t *arena, arena_run_t *run, size_t size, bool zero)\n{\n\n\treturn (arena_run_split_large_helper(arena, run, size, true, zero));\n}\n\nstatic bool\narena_run_init_large(arena_t *arena, arena_run_t *run, size_t size, bool zero)\n{\n\n\treturn (arena_run_split_large_helper(arena, run, size, false, zero));\n}\n\nstatic bool\narena_run_split_small(arena_t *arena, arena_run_t *run, size_t size,\n    szind_t binind)\n{\n\tarena_chunk_t *chunk;\n\tarena_chunk_map_misc_t *miscelm;\n\tsize_t flag_dirty, flag_decommitted, run_ind, need_pages, i;\n\n\tassert(binind != BININD_INVALID);\n\n\tchunk = (arena_chunk_t *)CHUNK_ADDR2BASE(run);\n\tmiscelm = arena_run_to_miscelm(run);\n\trun_ind = arena_miscelm_to_pageind(miscelm);\n\tflag_dirty = arena_mapbits_dirty_get(chunk, run_ind);\n\tflag_decommitted = arena_mapbits_decommitted_get(chunk, run_ind);\n\tneed_pages = (size >> LG_PAGE);\n\tassert(need_pages > 0);\n\n\tif (flag_decommitted != 0 && arena->chunk_hooks.commit(chunk, chunksize,\n\t    run_ind << LG_PAGE, size, arena->ind))\n\t\treturn (true);\n\n\tarena_run_split_remove(arena, chunk, run_ind, flag_dirty,\n\t    flag_decommitted, need_pages);\n\n\tfor (i = 0; i < need_pages; i++) {\n\t\tsize_t flag_unzeroed = arena_mapbits_unzeroed_get(chunk,\n\t\t    run_ind+i);\n\t\tarena_mapbits_small_set(chunk, run_ind+i, i, binind,\n\t\t    flag_unzeroed);\n\t\tif (config_debug && flag_dirty == 0 && flag_unzeroed == 0)\n\t\t\tarena_run_page_validate_zeroed(chunk, run_ind+i);\n\t}\n\tJEMALLOC_VALGRIND_MAKE_MEM_UNDEFINED((void *)((uintptr_t)chunk +\n\t    (run_ind << LG_PAGE)), (need_pages << LG_PAGE));\n\treturn (false);\n}\n\nstatic arena_chunk_t *\narena_chunk_init_spare(arena_t *arena)\n{\n\tarena_chunk_t *chunk;\n\n\tassert(arena->spare != NULL);\n\n\tchunk = arena->spare;\n\tarena->spare = NULL;\n\n\tassert(arena_mapbits_allocated_get(chunk, map_bias) == 0);\n\tassert(arena_mapbits_allocated_get(chunk, chunk_npages-1) == 0);\n\tassert(arena_mapbits_unallocated_size_get(chunk, map_bias) ==\n\t    arena_maxrun);\n\tassert(arena_mapbits_unallocated_size_get(chunk, chunk_npages-1) ==\n\t    arena_maxrun);\n\tassert(arena_mapbits_dirty_get(chunk, map_bias) ==\n\t    arena_mapbits_dirty_get(chunk, chunk_npages-1));\n\n\treturn (chunk);\n}\n\nstatic bool\narena_chunk_register(arena_t *arena, arena_chunk_t *chunk, bool zero)\n{\n\n\t/*\n\t * The extent node notion of \"committed\" doesn't directly apply to\n\t * arena chunks.  Arbitrarily mark them as committed.  The commit state\n\t * of runs is tracked individually, and upon chunk deallocation the\n\t * entire chunk is in a consistent commit state.\n\t */\n\textent_node_init(&chunk->node, arena, chunk, chunksize, zero, true);\n\textent_node_achunk_set(&chunk->node, true);\n\treturn (chunk_register(chunk, &chunk->node));\n}\n\nstatic arena_chunk_t *\narena_chunk_alloc_internal_hard(arena_t *arena, chunk_hooks_t *chunk_hooks,\n    bool *zero, bool *commit)\n{\n\tarena_chunk_t *chunk;\n\n\tmalloc_mutex_unlock(&arena->lock);\n\n\tchunk = (arena_chunk_t *)chunk_alloc_wrapper(arena, chunk_hooks, NULL,\n\t    chunksize, chunksize, zero, commit);\n\tif (chunk != NULL && !*commit) {\n\t\t/* Commit header. */\n\t\tif (chunk_hooks->commit(chunk, chunksize, 0, map_bias <<\n\t\t    LG_PAGE, arena->ind)) {\n\t\t\tchunk_dalloc_wrapper(arena, chunk_hooks,\n\t\t\t    (void *)chunk, chunksize, *commit);\n\t\t\tchunk = NULL;\n\t\t}\n\t}\n\tif (chunk != NULL && arena_chunk_register(arena, chunk, *zero)) {\n\t\tif (!*commit) {\n\t\t\t/* Undo commit of header. */\n\t\t\tchunk_hooks->decommit(chunk, chunksize, 0, map_bias <<\n\t\t\t    LG_PAGE, arena->ind);\n\t\t}\n\t\tchunk_dalloc_wrapper(arena, chunk_hooks, (void *)chunk,\n\t\t    chunksize, *commit);\n\t\tchunk = NULL;\n\t}\n\n\tmalloc_mutex_lock(&arena->lock);\n\treturn (chunk);\n}\n\nstatic arena_chunk_t *\narena_chunk_alloc_internal(arena_t *arena, bool *zero, bool *commit)\n{\n\tarena_chunk_t *chunk;\n\tchunk_hooks_t chunk_hooks = CHUNK_HOOKS_INITIALIZER;\n\n\tchunk = chunk_alloc_cache(arena, &chunk_hooks, NULL, chunksize,\n\t    chunksize, zero, true);\n\tif (chunk != NULL) {\n\t\tif (arena_chunk_register(arena, chunk, *zero)) {\n\t\t\tchunk_dalloc_cache(arena, &chunk_hooks, chunk,\n\t\t\t    chunksize, true);\n\t\t\treturn (NULL);\n\t\t}\n\t\t*commit = true;\n\t}\n\tif (chunk == NULL) {\n\t\tchunk = arena_chunk_alloc_internal_hard(arena, &chunk_hooks,\n\t\t    zero, commit);\n\t}\n\n\tif (config_stats && chunk != NULL) {\n\t\tarena->stats.mapped += chunksize;\n\t\tarena->stats.metadata_mapped += (map_bias << LG_PAGE);\n\t}\n\n\treturn (chunk);\n}\n\nstatic arena_chunk_t *\narena_chunk_init_hard(arena_t *arena)\n{\n\tarena_chunk_t *chunk;\n\tbool zero, commit;\n\tsize_t flag_unzeroed, flag_decommitted, i;\n\n\tassert(arena->spare == NULL);\n\n\tzero = false;\n\tcommit = false;\n\tchunk = arena_chunk_alloc_internal(arena, &zero, &commit);\n\tif (chunk == NULL)\n\t\treturn (NULL);\n\n\t/*\n\t * Initialize the map to contain one maximal free untouched run.  Mark\n\t * the pages as zeroed if chunk_alloc() returned a zeroed or decommitted\n\t * chunk.\n\t */\n\tflag_unzeroed = (zero || !commit) ? 0 : CHUNK_MAP_UNZEROED;\n\tflag_decommitted = commit ? 0 : CHUNK_MAP_DECOMMITTED;\n\tarena_mapbits_unallocated_set(chunk, map_bias, arena_maxrun,\n\t    flag_unzeroed | flag_decommitted);\n\t/*\n\t * There is no need to initialize the internal page map entries unless\n\t * the chunk is not zeroed.\n\t */\n\tif (!zero) {\n\t\tJEMALLOC_VALGRIND_MAKE_MEM_UNDEFINED(\n\t\t    (void *)arena_bitselm_get(chunk, map_bias+1),\n\t\t    (size_t)((uintptr_t) arena_bitselm_get(chunk,\n\t\t    chunk_npages-1) - (uintptr_t)arena_bitselm_get(chunk,\n\t\t    map_bias+1)));\n\t\tfor (i = map_bias+1; i < chunk_npages-1; i++)\n\t\t\tarena_mapbits_internal_set(chunk, i, flag_unzeroed);\n\t} else {\n\t\tJEMALLOC_VALGRIND_MAKE_MEM_DEFINED((void\n\t\t    *)arena_bitselm_get(chunk, map_bias+1), (size_t)((uintptr_t)\n\t\t    arena_bitselm_get(chunk, chunk_npages-1) -\n\t\t    (uintptr_t)arena_bitselm_get(chunk, map_bias+1)));\n\t\tif (config_debug) {\n\t\t\tfor (i = map_bias+1; i < chunk_npages-1; i++) {\n\t\t\t\tassert(arena_mapbits_unzeroed_get(chunk, i) ==\n\t\t\t\t    flag_unzeroed);\n\t\t\t}\n\t\t}\n\t}\n\tarena_mapbits_unallocated_set(chunk, chunk_npages-1, arena_maxrun,\n\t    flag_unzeroed);\n\n\treturn (chunk);\n}\n\nstatic arena_chunk_t *\narena_chunk_alloc(arena_t *arena)\n{\n\tarena_chunk_t *chunk;\n\n\tif (arena->spare != NULL)\n\t\tchunk = arena_chunk_init_spare(arena);\n\telse {\n\t\tchunk = arena_chunk_init_hard(arena);\n\t\tif (chunk == NULL)\n\t\t\treturn (NULL);\n\t}\n\n\t/* Insert the run into the runs_avail tree. */\n\tarena_avail_insert(arena, chunk, map_bias, chunk_npages-map_bias);\n\n\treturn (chunk);\n}\n\nstatic void\narena_chunk_dalloc(arena_t *arena, arena_chunk_t *chunk)\n{\n\n\tassert(arena_mapbits_allocated_get(chunk, map_bias) == 0);\n\tassert(arena_mapbits_allocated_get(chunk, chunk_npages-1) == 0);\n\tassert(arena_mapbits_unallocated_size_get(chunk, map_bias) ==\n\t    arena_maxrun);\n\tassert(arena_mapbits_unallocated_size_get(chunk, chunk_npages-1) ==\n\t    arena_maxrun);\n\tassert(arena_mapbits_dirty_get(chunk, map_bias) ==\n\t    arena_mapbits_dirty_get(chunk, chunk_npages-1));\n\tassert(arena_mapbits_decommitted_get(chunk, map_bias) ==\n\t    arena_mapbits_decommitted_get(chunk, chunk_npages-1));\n\n\t/*\n\t * Remove run from the runs_avail tree, so that the arena does not use\n\t * it.\n\t */\n\tarena_avail_remove(arena, chunk, map_bias, chunk_npages-map_bias);\n\n\tif (arena->spare != NULL) {\n\t\tarena_chunk_t *spare = arena->spare;\n\t\tchunk_hooks_t chunk_hooks = CHUNK_HOOKS_INITIALIZER;\n\t\tbool committed;\n\n\t\tarena->spare = chunk;\n\t\tif (arena_mapbits_dirty_get(spare, map_bias) != 0) {\n\t\t\tarena_run_dirty_remove(arena, spare, map_bias,\n\t\t\t    chunk_npages-map_bias);\n\t\t}\n\n\t\tchunk_deregister(spare, &spare->node);\n\n\t\tcommitted = (arena_mapbits_decommitted_get(spare, map_bias) ==\n\t\t    0);\n\t\tif (!committed) {\n\t\t\t/*\n\t\t\t * Decommit the header.  Mark the chunk as decommitted\n\t\t\t * even if header decommit fails, since treating a\n\t\t\t * partially committed chunk as committed has a high\n\t\t\t * potential for causing later access of decommitted\n\t\t\t * memory.\n\t\t\t */\n\t\t\tchunk_hooks = chunk_hooks_get(arena);\n\t\t\tchunk_hooks.decommit(spare, chunksize, 0, map_bias <<\n\t\t\t    LG_PAGE, arena->ind);\n\t\t}\n\n\t\tchunk_dalloc_cache(arena, &chunk_hooks, (void *)spare,\n\t\t    chunksize, committed);\n\n\t\tif (config_stats) {\n\t\t\tarena->stats.mapped -= chunksize;\n\t\t\tarena->stats.metadata_mapped -= (map_bias << LG_PAGE);\n\t\t}\n\t} else\n\t\tarena->spare = chunk;\n}\n\nstatic void\narena_huge_malloc_stats_update(arena_t *arena, size_t usize)\n{\n\tszind_t index = size2index(usize) - nlclasses - NBINS;\n\n\tcassert(config_stats);\n\n\tarena->stats.nmalloc_huge++;\n\tarena->stats.allocated_huge += usize;\n\tarena->stats.hstats[index].nmalloc++;\n\tarena->stats.hstats[index].curhchunks++;\n}\n\nstatic void\narena_huge_malloc_stats_update_undo(arena_t *arena, size_t usize)\n{\n\tszind_t index = size2index(usize) - nlclasses - NBINS;\n\n\tcassert(config_stats);\n\n\tarena->stats.nmalloc_huge--;\n\tarena->stats.allocated_huge -= usize;\n\tarena->stats.hstats[index].nmalloc--;\n\tarena->stats.hstats[index].curhchunks--;\n}\n\nstatic void\narena_huge_dalloc_stats_update(arena_t *arena, size_t usize)\n{\n\tszind_t index = size2index(usize) - nlclasses - NBINS;\n\n\tcassert(config_stats);\n\n\tarena->stats.ndalloc_huge++;\n\tarena->stats.allocated_huge -= usize;\n\tarena->stats.hstats[index].ndalloc++;\n\tarena->stats.hstats[index].curhchunks--;\n}\n\nstatic void\narena_huge_dalloc_stats_update_undo(arena_t *arena, size_t usize)\n{\n\tszind_t index = size2index(usize) - nlclasses - NBINS;\n\n\tcassert(config_stats);\n\n\tarena->stats.ndalloc_huge--;\n\tarena->stats.allocated_huge += usize;\n\tarena->stats.hstats[index].ndalloc--;\n\tarena->stats.hstats[index].curhchunks++;\n}\n\nstatic void\narena_huge_ralloc_stats_update(arena_t *arena, size_t oldsize, size_t usize)\n{\n\n\tarena_huge_dalloc_stats_update(arena, oldsize);\n\tarena_huge_malloc_stats_update(arena, usize);\n}\n\nstatic void\narena_huge_ralloc_stats_update_undo(arena_t *arena, size_t oldsize,\n    size_t usize)\n{\n\n\tarena_huge_dalloc_stats_update_undo(arena, oldsize);\n\tarena_huge_malloc_stats_update_undo(arena, usize);\n}\n\nextent_node_t *\narena_node_alloc(arena_t *arena)\n{\n\textent_node_t *node;\n\n\tmalloc_mutex_lock(&arena->node_cache_mtx);\n\tnode = ql_last(&arena->node_cache, ql_link);\n\tif (node == NULL) {\n\t\tmalloc_mutex_unlock(&arena->node_cache_mtx);\n\t\treturn (base_alloc(sizeof(extent_node_t)));\n\t}\n\tql_tail_remove(&arena->node_cache, extent_node_t, ql_link);\n\tmalloc_mutex_unlock(&arena->node_cache_mtx);\n\treturn (node);\n}\n\nvoid\narena_node_dalloc(arena_t *arena, extent_node_t *node)\n{\n\n\tmalloc_mutex_lock(&arena->node_cache_mtx);\n\tql_elm_new(node, ql_link);\n\tql_tail_insert(&arena->node_cache, node, ql_link);\n\tmalloc_mutex_unlock(&arena->node_cache_mtx);\n}\n\nstatic void *\narena_chunk_alloc_huge_hard(arena_t *arena, chunk_hooks_t *chunk_hooks,\n    size_t usize, size_t alignment, bool *zero, size_t csize)\n{\n\tvoid *ret;\n\tbool commit = true;\n\n\tret = chunk_alloc_wrapper(arena, chunk_hooks, NULL, csize, alignment,\n\t    zero, &commit);\n\tif (ret == NULL) {\n\t\t/* Revert optimistic stats updates. */\n\t\tmalloc_mutex_lock(&arena->lock);\n\t\tif (config_stats) {\n\t\t\tarena_huge_malloc_stats_update_undo(arena, usize);\n\t\t\tarena->stats.mapped -= usize;\n\t\t}\n\t\tarena->nactive -= (usize >> LG_PAGE);\n\t\tmalloc_mutex_unlock(&arena->lock);\n\t}\n\n\treturn (ret);\n}\n\nvoid *\narena_chunk_alloc_huge(arena_t *arena, size_t usize, size_t alignment,\n    bool *zero)\n{\n\tvoid *ret;\n\tchunk_hooks_t chunk_hooks = CHUNK_HOOKS_INITIALIZER;\n\tsize_t csize = CHUNK_CEILING(usize);\n\n\tmalloc_mutex_lock(&arena->lock);\n\n\t/* Optimistically update stats. */\n\tif (config_stats) {\n\t\tarena_huge_malloc_stats_update(arena, usize);\n\t\tarena->stats.mapped += usize;\n\t}\n\tarena->nactive += (usize >> LG_PAGE);\n\n\tret = chunk_alloc_cache(arena, &chunk_hooks, NULL, csize, alignment,\n\t    zero, true);\n\tmalloc_mutex_unlock(&arena->lock);\n\tif (ret == NULL) {\n\t\tret = arena_chunk_alloc_huge_hard(arena, &chunk_hooks, usize,\n\t\t    alignment, zero, csize);\n\t}\n\n\tif (config_stats && ret != NULL)\n\t\tstats_cactive_add(usize);\n\treturn (ret);\n}\n\nvoid\narena_chunk_dalloc_huge(arena_t *arena, void *chunk, size_t usize)\n{\n\tchunk_hooks_t chunk_hooks = CHUNK_HOOKS_INITIALIZER;\n\tsize_t csize;\n\n\tcsize = CHUNK_CEILING(usize);\n\tmalloc_mutex_lock(&arena->lock);\n\tif (config_stats) {\n\t\tarena_huge_dalloc_stats_update(arena, usize);\n\t\tarena->stats.mapped -= usize;\n\t\tstats_cactive_sub(usize);\n\t}\n\tarena->nactive -= (usize >> LG_PAGE);\n\n\tchunk_dalloc_cache(arena, &chunk_hooks, chunk, csize, true);\n\tmalloc_mutex_unlock(&arena->lock);\n}\n\nvoid\narena_chunk_ralloc_huge_similar(arena_t *arena, void *chunk, size_t oldsize,\n    size_t usize)\n{\n\n\tassert(CHUNK_CEILING(oldsize) == CHUNK_CEILING(usize));\n\tassert(oldsize != usize);\n\n\tmalloc_mutex_lock(&arena->lock);\n\tif (config_stats)\n\t\tarena_huge_ralloc_stats_update(arena, oldsize, usize);\n\tif (oldsize < usize) {\n\t\tsize_t udiff = usize - oldsize;\n\t\tarena->nactive += udiff >> LG_PAGE;\n\t\tif (config_stats)\n\t\t\tstats_cactive_add(udiff);\n\t} else {\n\t\tsize_t udiff = oldsize - usize;\n\t\tarena->nactive -= udiff >> LG_PAGE;\n\t\tif (config_stats)\n\t\t\tstats_cactive_sub(udiff);\n\t}\n\tmalloc_mutex_unlock(&arena->lock);\n}\n\nvoid\narena_chunk_ralloc_huge_shrink(arena_t *arena, void *chunk, size_t oldsize,\n    size_t usize)\n{\n\tsize_t udiff = oldsize - usize;\n\tsize_t cdiff = CHUNK_CEILING(oldsize) - CHUNK_CEILING(usize);\n\n\tmalloc_mutex_lock(&arena->lock);\n\tif (config_stats) {\n\t\tarena_huge_ralloc_stats_update(arena, oldsize, usize);\n\t\tif (cdiff != 0) {\n\t\t\tarena->stats.mapped -= cdiff;\n\t\t\tstats_cactive_sub(udiff);\n\t\t}\n\t}\n\tarena->nactive -= udiff >> LG_PAGE;\n\n\tif (cdiff != 0) {\n\t\tchunk_hooks_t chunk_hooks = CHUNK_HOOKS_INITIALIZER;\n\t\tvoid *nchunk = (void *)((uintptr_t)chunk +\n\t\t    CHUNK_CEILING(usize));\n\n\t\tchunk_dalloc_cache(arena, &chunk_hooks, nchunk, cdiff, true);\n\t}\n\tmalloc_mutex_unlock(&arena->lock);\n}\n\nstatic bool\narena_chunk_ralloc_huge_expand_hard(arena_t *arena, chunk_hooks_t *chunk_hooks,\n    void *chunk, size_t oldsize, size_t usize, bool *zero, void *nchunk,\n    size_t udiff, size_t cdiff)\n{\n\tbool err;\n\tbool commit = true;\n\n\terr = (chunk_alloc_wrapper(arena, chunk_hooks, nchunk, cdiff, chunksize,\n\t    zero, &commit) == NULL);\n\tif (err) {\n\t\t/* Revert optimistic stats updates. */\n\t\tmalloc_mutex_lock(&arena->lock);\n\t\tif (config_stats) {\n\t\t\tarena_huge_ralloc_stats_update_undo(arena, oldsize,\n\t\t\t    usize);\n\t\t\tarena->stats.mapped -= cdiff;\n\t\t}\n\t\tarena->nactive -= (udiff >> LG_PAGE);\n\t\tmalloc_mutex_unlock(&arena->lock);\n\t} else if (chunk_hooks->merge(chunk, CHUNK_CEILING(oldsize), nchunk,\n\t    cdiff, true, arena->ind)) {\n\t\tchunk_dalloc_arena(arena, chunk_hooks, nchunk, cdiff, *zero,\n\t\t    true);\n\t\terr = true;\n\t}\n\treturn (err);\n}\n\nbool\narena_chunk_ralloc_huge_expand(arena_t *arena, void *chunk, size_t oldsize,\n    size_t usize, bool *zero)\n{\n\tbool err;\n\tchunk_hooks_t chunk_hooks = chunk_hooks_get(arena);\n\tvoid *nchunk = (void *)((uintptr_t)chunk + CHUNK_CEILING(oldsize));\n\tsize_t udiff = usize - oldsize;\n\tsize_t cdiff = CHUNK_CEILING(usize) - CHUNK_CEILING(oldsize);\n\n\tmalloc_mutex_lock(&arena->lock);\n\n\t/* Optimistically update stats. */\n\tif (config_stats) {\n\t\tarena_huge_ralloc_stats_update(arena, oldsize, usize);\n\t\tarena->stats.mapped += cdiff;\n\t}\n\tarena->nactive += (udiff >> LG_PAGE);\n\n\terr = (chunk_alloc_cache(arena, &arena->chunk_hooks, nchunk, cdiff,\n\t    chunksize, zero, true) == NULL);\n\tmalloc_mutex_unlock(&arena->lock);\n\tif (err) {\n\t\terr = arena_chunk_ralloc_huge_expand_hard(arena, &chunk_hooks,\n\t\t    chunk, oldsize, usize, zero, nchunk, udiff,\n\t\t    cdiff);\n\t} else if (chunk_hooks.merge(chunk, CHUNK_CEILING(oldsize), nchunk,\n\t    cdiff, true, arena->ind)) {\n\t\tchunk_dalloc_arena(arena, &chunk_hooks, nchunk, cdiff, *zero,\n\t\t    true);\n\t\terr = true;\n\t}\n\n\tif (config_stats && !err)\n\t\tstats_cactive_add(udiff);\n\treturn (err);\n}\n\n/*\n * Do first-best-fit run selection, i.e. select the lowest run that best fits.\n * Run sizes are quantized, so not all candidate runs are necessarily exactly\n * the same size.\n */\nstatic arena_run_t *\narena_run_first_best_fit(arena_t *arena, size_t size)\n{\n\tsize_t search_size = run_quantize_first(size);\n\tarena_chunk_map_misc_t *key = arena_miscelm_key_create(search_size);\n\tarena_chunk_map_misc_t *miscelm =\n\t    arena_avail_tree_nsearch(&arena->runs_avail, key);\n\tif (miscelm == NULL)\n\t\treturn (NULL);\n\treturn (&miscelm->run);\n}\n\nstatic arena_run_t *\narena_run_alloc_large_helper(arena_t *arena, size_t size, bool zero)\n{\n\tarena_run_t *run = arena_run_first_best_fit(arena, s2u(size));\n\tif (run != NULL) {\n\t\tif (arena_run_split_large(arena, run, size, zero))\n\t\t\trun = NULL;\n\t}\n\treturn (run);\n}\n\nstatic arena_run_t *\narena_run_alloc_large(arena_t *arena, size_t size, bool zero)\n{\n\tarena_chunk_t *chunk;\n\tarena_run_t *run;\n\n\tassert(size <= arena_maxrun);\n\tassert(size == PAGE_CEILING(size));\n\n\t/* Search the arena's chunks for the lowest best fit. */\n\trun = arena_run_alloc_large_helper(arena, size, zero);\n\tif (run != NULL)\n\t\treturn (run);\n\n\t/*\n\t * No usable runs.  Create a new chunk from which to allocate the run.\n\t */\n\tchunk = arena_chunk_alloc(arena);\n\tif (chunk != NULL) {\n\t\trun = &arena_miscelm_get(chunk, map_bias)->run;\n\t\tif (arena_run_split_large(arena, run, size, zero))\n\t\t\trun = NULL;\n\t\treturn (run);\n\t}\n\n\t/*\n\t * arena_chunk_alloc() failed, but another thread may have made\n\t * sufficient memory available while this one dropped arena->lock in\n\t * arena_chunk_alloc(), so search one more time.\n\t */\n\treturn (arena_run_alloc_large_helper(arena, size, zero));\n}\n\nstatic arena_run_t *\narena_run_alloc_small_helper(arena_t *arena, size_t size, szind_t binind)\n{\n\tarena_run_t *run = arena_run_first_best_fit(arena, size);\n\tif (run != NULL) {\n\t\tif (arena_run_split_small(arena, run, size, binind))\n\t\t\trun = NULL;\n\t}\n\treturn (run);\n}\n\nstatic arena_run_t *\narena_run_alloc_small(arena_t *arena, size_t size, szind_t binind)\n{\n\tarena_chunk_t *chunk;\n\tarena_run_t *run;\n\n\tassert(size <= arena_maxrun);\n\tassert(size == PAGE_CEILING(size));\n\tassert(binind != BININD_INVALID);\n\n\t/* Search the arena's chunks for the lowest best fit. */\n\trun = arena_run_alloc_small_helper(arena, size, binind);\n\tif (run != NULL)\n\t\treturn (run);\n\n\t/*\n\t * No usable runs.  Create a new chunk from which to allocate the run.\n\t */\n\tchunk = arena_chunk_alloc(arena);\n\tif (chunk != NULL) {\n\t\trun = &arena_miscelm_get(chunk, map_bias)->run;\n\t\tif (arena_run_split_small(arena, run, size, binind))\n\t\t\trun = NULL;\n\t\treturn (run);\n\t}\n\n\t/*\n\t * arena_chunk_alloc() failed, but another thread may have made\n\t * sufficient memory available while this one dropped arena->lock in\n\t * arena_chunk_alloc(), so search one more time.\n\t */\n\treturn (arena_run_alloc_small_helper(arena, size, binind));\n}\n\nstatic bool\narena_lg_dirty_mult_valid(ssize_t lg_dirty_mult)\n{\n\n\treturn (lg_dirty_mult >= -1 && lg_dirty_mult < (ssize_t)(sizeof(size_t)\n\t    << 3));\n}\n\nssize_t\narena_lg_dirty_mult_get(arena_t *arena)\n{\n\tssize_t lg_dirty_mult;\n\n\tmalloc_mutex_lock(&arena->lock);\n\tlg_dirty_mult = arena->lg_dirty_mult;\n\tmalloc_mutex_unlock(&arena->lock);\n\n\treturn (lg_dirty_mult);\n}\n\nbool\narena_lg_dirty_mult_set(arena_t *arena, ssize_t lg_dirty_mult)\n{\n\n\tif (!arena_lg_dirty_mult_valid(lg_dirty_mult))\n\t\treturn (true);\n\n\tmalloc_mutex_lock(&arena->lock);\n\tarena->lg_dirty_mult = lg_dirty_mult;\n\tarena_maybe_purge(arena);\n\tmalloc_mutex_unlock(&arena->lock);\n\n\treturn (false);\n}\n\nvoid\narena_maybe_purge(arena_t *arena)\n{\n\n\t/* Don't purge if the option is disabled. */\n\tif (arena->lg_dirty_mult < 0)\n\t\treturn;\n\t/* Don't recursively purge. */\n\tif (arena->purging)\n\t\treturn;\n\t/*\n\t * Iterate, since preventing recursive purging could otherwise leave too\n\t * many dirty pages.\n\t */\n\twhile (true) {\n\t\tsize_t threshold = (arena->nactive >> arena->lg_dirty_mult);\n\t\tif (threshold < chunk_npages)\n\t\t\tthreshold = chunk_npages;\n\t\t/*\n\t\t * Don't purge unless the number of purgeable pages exceeds the\n\t\t * threshold.\n\t\t */\n\t\tif (arena->ndirty <= threshold)\n\t\t\treturn;\n\t\tarena_purge(arena, false);\n\t}\n}\n\nstatic size_t\narena_dirty_count(arena_t *arena)\n{\n\tsize_t ndirty = 0;\n\tarena_runs_dirty_link_t *rdelm;\n\textent_node_t *chunkselm;\n\n\tfor (rdelm = qr_next(&arena->runs_dirty, rd_link),\n\t    chunkselm = qr_next(&arena->chunks_cache, cc_link);\n\t    rdelm != &arena->runs_dirty; rdelm = qr_next(rdelm, rd_link)) {\n\t\tsize_t npages;\n\n\t\tif (rdelm == &chunkselm->rd) {\n\t\t\tnpages = extent_node_size_get(chunkselm) >> LG_PAGE;\n\t\t\tchunkselm = qr_next(chunkselm, cc_link);\n\t\t} else {\n\t\t\tarena_chunk_t *chunk = (arena_chunk_t *)CHUNK_ADDR2BASE(\n\t\t\t    rdelm);\n\t\t\tarena_chunk_map_misc_t *miscelm =\n\t\t\t    arena_rd_to_miscelm(rdelm);\n\t\t\tsize_t pageind = arena_miscelm_to_pageind(miscelm);\n\t\t\tassert(arena_mapbits_allocated_get(chunk, pageind) ==\n\t\t\t    0);\n\t\t\tassert(arena_mapbits_large_get(chunk, pageind) == 0);\n\t\t\tassert(arena_mapbits_dirty_get(chunk, pageind) != 0);\n\t\t\tnpages = arena_mapbits_unallocated_size_get(chunk,\n\t\t\t    pageind) >> LG_PAGE;\n\t\t}\n\t\tndirty += npages;\n\t}\n\n\treturn (ndirty);\n}\n\nstatic size_t\narena_compute_npurge(arena_t *arena, bool all)\n{\n\tsize_t npurge;\n\n\t/*\n\t * Compute the minimum number of pages that this thread should try to\n\t * purge.\n\t */\n\tif (!all) {\n\t\tsize_t threshold = (arena->nactive >> arena->lg_dirty_mult);\n\t\tthreshold = threshold < chunk_npages ? chunk_npages : threshold;\n\n\t\tnpurge = arena->ndirty - threshold;\n\t} else\n\t\tnpurge = arena->ndirty;\n\n\treturn (npurge);\n}\n\nstatic size_t\narena_stash_dirty(arena_t *arena, chunk_hooks_t *chunk_hooks, bool all,\n    size_t npurge, arena_runs_dirty_link_t *purge_runs_sentinel,\n    extent_node_t *purge_chunks_sentinel)\n{\n\tarena_runs_dirty_link_t *rdelm, *rdelm_next;\n\textent_node_t *chunkselm;\n\tsize_t nstashed = 0;\n\n\t/* Stash at least npurge pages. */\n\tfor (rdelm = qr_next(&arena->runs_dirty, rd_link),\n\t    chunkselm = qr_next(&arena->chunks_cache, cc_link);\n\t    rdelm != &arena->runs_dirty; rdelm = rdelm_next) {\n\t\tsize_t npages;\n\t\trdelm_next = qr_next(rdelm, rd_link);\n\n\t\tif (rdelm == &chunkselm->rd) {\n\t\t\textent_node_t *chunkselm_next;\n\t\t\tbool zero;\n\t\t\tUNUSED void *chunk;\n\n\t\t\tchunkselm_next = qr_next(chunkselm, cc_link);\n\t\t\t/*\n\t\t\t * Allocate.  chunkselm remains valid due to the\n\t\t\t * dalloc_node=false argument to chunk_alloc_cache().\n\t\t\t */\n\t\t\tzero = false;\n\t\t\tchunk = chunk_alloc_cache(arena, chunk_hooks,\n\t\t\t    extent_node_addr_get(chunkselm),\n\t\t\t    extent_node_size_get(chunkselm), chunksize, &zero,\n\t\t\t    false);\n\t\t\tassert(chunk == extent_node_addr_get(chunkselm));\n\t\t\tassert(zero == extent_node_zeroed_get(chunkselm));\n\t\t\textent_node_dirty_insert(chunkselm, purge_runs_sentinel,\n\t\t\t    purge_chunks_sentinel);\n\t\t\tnpages = extent_node_size_get(chunkselm) >> LG_PAGE;\n\t\t\tchunkselm = chunkselm_next;\n\t\t} else {\n\t\t\tarena_chunk_t *chunk =\n\t\t\t    (arena_chunk_t *)CHUNK_ADDR2BASE(rdelm);\n\t\t\tarena_chunk_map_misc_t *miscelm =\n\t\t\t    arena_rd_to_miscelm(rdelm);\n\t\t\tsize_t pageind = arena_miscelm_to_pageind(miscelm);\n\t\t\tarena_run_t *run = &miscelm->run;\n\t\t\tsize_t run_size =\n\t\t\t    arena_mapbits_unallocated_size_get(chunk, pageind);\n\n\t\t\tnpages = run_size >> LG_PAGE;\n\n\t\t\tassert(pageind + npages <= chunk_npages);\n\t\t\tassert(arena_mapbits_dirty_get(chunk, pageind) ==\n\t\t\t    arena_mapbits_dirty_get(chunk, pageind+npages-1));\n\n\t\t\t/*\n\t\t\t * If purging the spare chunk's run, make it available\n\t\t\t * prior to allocation.\n\t\t\t */\n\t\t\tif (chunk == arena->spare)\n\t\t\t\tarena_chunk_alloc(arena);\n\n\t\t\t/* Temporarily allocate the free dirty run. */\n\t\t\tarena_run_split_large(arena, run, run_size, false);\n\t\t\t/* Stash. */\n\t\t\tif (false)\n\t\t\t\tqr_new(rdelm, rd_link); /* Redundant. */\n\t\t\telse {\n\t\t\t\tassert(qr_next(rdelm, rd_link) == rdelm);\n\t\t\t\tassert(qr_prev(rdelm, rd_link) == rdelm);\n\t\t\t}\n\t\t\tqr_meld(purge_runs_sentinel, rdelm, rd_link);\n\t\t}\n\n\t\tnstashed += npages;\n\t\tif (!all && nstashed >= npurge)\n\t\t\tbreak;\n\t}\n\n\treturn (nstashed);\n}\n\nstatic size_t\narena_purge_stashed(arena_t *arena, chunk_hooks_t *chunk_hooks,\n    arena_runs_dirty_link_t *purge_runs_sentinel,\n    extent_node_t *purge_chunks_sentinel)\n{\n\tsize_t npurged, nmadvise;\n\tarena_runs_dirty_link_t *rdelm;\n\textent_node_t *chunkselm;\n\n\tif (config_stats)\n\t\tnmadvise = 0;\n\tnpurged = 0;\n\n\tmalloc_mutex_unlock(&arena->lock);\n\tfor (rdelm = qr_next(purge_runs_sentinel, rd_link),\n\t    chunkselm = qr_next(purge_chunks_sentinel, cc_link);\n\t    rdelm != purge_runs_sentinel; rdelm = qr_next(rdelm, rd_link)) {\n\t\tsize_t npages;\n\n\t\tif (rdelm == &chunkselm->rd) {\n\t\t\t/*\n\t\t\t * Don't actually purge the chunk here because 1)\n\t\t\t * chunkselm is embedded in the chunk and must remain\n\t\t\t * valid, and 2) we deallocate the chunk in\n\t\t\t * arena_unstash_purged(), where it is destroyed,\n\t\t\t * decommitted, or purged, depending on chunk\n\t\t\t * deallocation policy.\n\t\t\t */\n\t\t\tsize_t size = extent_node_size_get(chunkselm);\n\t\t\tnpages = size >> LG_PAGE;\n\t\t\tchunkselm = qr_next(chunkselm, cc_link);\n\t\t} else {\n\t\t\tsize_t pageind, run_size, flag_unzeroed, flags, i;\n\t\t\tbool decommitted;\n\t\t\tarena_chunk_t *chunk =\n\t\t\t    (arena_chunk_t *)CHUNK_ADDR2BASE(rdelm);\n\t\t\tarena_chunk_map_misc_t *miscelm =\n\t\t\t    arena_rd_to_miscelm(rdelm);\n\t\t\tpageind = arena_miscelm_to_pageind(miscelm);\n\t\t\trun_size = arena_mapbits_large_size_get(chunk, pageind);\n\t\t\tnpages = run_size >> LG_PAGE;\n\n\t\t\tassert(pageind + npages <= chunk_npages);\n\t\t\tassert(!arena_mapbits_decommitted_get(chunk, pageind));\n\t\t\tassert(!arena_mapbits_decommitted_get(chunk,\n\t\t\t    pageind+npages-1));\n\t\t\tdecommitted = !chunk_hooks->decommit(chunk, chunksize,\n\t\t\t    pageind << LG_PAGE, npages << LG_PAGE, arena->ind);\n\t\t\tif (decommitted) {\n\t\t\t\tflag_unzeroed = 0;\n\t\t\t\tflags = CHUNK_MAP_DECOMMITTED;\n\t\t\t} else {\n\t\t\t\tflag_unzeroed = chunk_purge_wrapper(arena,\n\t\t\t\t    chunk_hooks, chunk, chunksize, pageind <<\n\t\t\t\t    LG_PAGE, run_size) ? CHUNK_MAP_UNZEROED : 0;\n\t\t\t\tflags = flag_unzeroed;\n\t\t\t}\n\t\t\tarena_mapbits_large_set(chunk, pageind+npages-1, 0,\n\t\t\t    flags);\n\t\t\tarena_mapbits_large_set(chunk, pageind, run_size,\n\t\t\t    flags);\n\n\t\t\t/*\n\t\t\t * Set the unzeroed flag for internal pages, now that\n\t\t\t * chunk_purge_wrapper() has returned whether the pages\n\t\t\t * were zeroed as a side effect of purging.  This chunk\n\t\t\t * map modification is safe even though the arena mutex\n\t\t\t * isn't currently owned by this thread, because the run\n\t\t\t * is marked as allocated, thus protecting it from being\n\t\t\t * modified by any other thread.  As long as these\n\t\t\t * writes don't perturb the first and last elements'\n\t\t\t * CHUNK_MAP_ALLOCATED bits, behavior is well defined.\n\t\t\t */\n\t\t\tfor (i = 1; i < npages-1; i++) {\n\t\t\t\tarena_mapbits_internal_set(chunk, pageind+i,\n\t\t\t\t    flag_unzeroed);\n\t\t\t}\n\t\t}\n\n\t\tnpurged += npages;\n\t\tif (config_stats)\n\t\t\tnmadvise++;\n\t}\n\tmalloc_mutex_lock(&arena->lock);\n\n\tif (config_stats) {\n\t\tarena->stats.nmadvise += nmadvise;\n\t\tarena->stats.purged += npurged;\n\t}\n\n\treturn (npurged);\n}\n\nstatic void\narena_unstash_purged(arena_t *arena, chunk_hooks_t *chunk_hooks,\n    arena_runs_dirty_link_t *purge_runs_sentinel,\n    extent_node_t *purge_chunks_sentinel)\n{\n\tarena_runs_dirty_link_t *rdelm, *rdelm_next;\n\textent_node_t *chunkselm;\n\n\t/* Deallocate chunks/runs. */\n\tfor (rdelm = qr_next(purge_runs_sentinel, rd_link),\n\t    chunkselm = qr_next(purge_chunks_sentinel, cc_link);\n\t    rdelm != purge_runs_sentinel; rdelm = rdelm_next) {\n\t\trdelm_next = qr_next(rdelm, rd_link);\n\t\tif (rdelm == &chunkselm->rd) {\n\t\t\textent_node_t *chunkselm_next = qr_next(chunkselm,\n\t\t\t    cc_link);\n\t\t\tvoid *addr = extent_node_addr_get(chunkselm);\n\t\t\tsize_t size = extent_node_size_get(chunkselm);\n\t\t\tbool zeroed = extent_node_zeroed_get(chunkselm);\n\t\t\tbool committed = extent_node_committed_get(chunkselm);\n\t\t\textent_node_dirty_remove(chunkselm);\n\t\t\tarena_node_dalloc(arena, chunkselm);\n\t\t\tchunkselm = chunkselm_next;\n\t\t\tchunk_dalloc_arena(arena, chunk_hooks, addr, size,\n\t\t\t    zeroed, committed);\n\t\t} else {\n\t\t\tarena_chunk_t *chunk =\n\t\t\t    (arena_chunk_t *)CHUNK_ADDR2BASE(rdelm);\n\t\t\tarena_chunk_map_misc_t *miscelm =\n\t\t\t    arena_rd_to_miscelm(rdelm);\n\t\t\tsize_t pageind = arena_miscelm_to_pageind(miscelm);\n\t\t\tbool decommitted = (arena_mapbits_decommitted_get(chunk,\n\t\t\t    pageind) != 0);\n\t\t\tarena_run_t *run = &miscelm->run;\n\t\t\tqr_remove(rdelm, rd_link);\n\t\t\tarena_run_dalloc(arena, run, false, true, decommitted);\n\t\t}\n\t}\n}\n\nstatic void\narena_purge(arena_t *arena, bool all)\n{\n\tchunk_hooks_t chunk_hooks = chunk_hooks_get(arena);\n\tsize_t npurge, npurgeable, npurged;\n\tarena_runs_dirty_link_t purge_runs_sentinel;\n\textent_node_t purge_chunks_sentinel;\n\n\tarena->purging = true;\n\n\t/*\n\t * Calls to arena_dirty_count() are disabled even for debug builds\n\t * because overhead grows nonlinearly as memory usage increases.\n\t */\n\tif (false && config_debug) {\n\t\tsize_t ndirty = arena_dirty_count(arena);\n\t\tassert(ndirty == arena->ndirty);\n\t}\n\tassert((arena->nactive >> arena->lg_dirty_mult) < arena->ndirty || all);\n\n\tif (config_stats)\n\t\tarena->stats.npurge++;\n\n\tnpurge = arena_compute_npurge(arena, all);\n\tqr_new(&purge_runs_sentinel, rd_link);\n\textent_node_dirty_linkage_init(&purge_chunks_sentinel);\n\n\tnpurgeable = arena_stash_dirty(arena, &chunk_hooks, all, npurge,\n\t    &purge_runs_sentinel, &purge_chunks_sentinel);\n\tassert(npurgeable >= npurge);\n\tnpurged = arena_purge_stashed(arena, &chunk_hooks, &purge_runs_sentinel,\n\t    &purge_chunks_sentinel);\n\tassert(npurged == npurgeable);\n\tarena_unstash_purged(arena, &chunk_hooks, &purge_runs_sentinel,\n\t    &purge_chunks_sentinel);\n\n\tarena->purging = false;\n}\n\nvoid\narena_purge_all(arena_t *arena)\n{\n\n\tmalloc_mutex_lock(&arena->lock);\n\tarena_purge(arena, true);\n\tmalloc_mutex_unlock(&arena->lock);\n}\n\nstatic void\narena_run_coalesce(arena_t *arena, arena_chunk_t *chunk, size_t *p_size,\n    size_t *p_run_ind, size_t *p_run_pages, size_t flag_dirty,\n    size_t flag_decommitted)\n{\n\tsize_t size = *p_size;\n\tsize_t run_ind = *p_run_ind;\n\tsize_t run_pages = *p_run_pages;\n\n\t/* Try to coalesce forward. */\n\tif (run_ind + run_pages < chunk_npages &&\n\t    arena_mapbits_allocated_get(chunk, run_ind+run_pages) == 0 &&\n\t    arena_mapbits_dirty_get(chunk, run_ind+run_pages) == flag_dirty &&\n\t    arena_mapbits_decommitted_get(chunk, run_ind+run_pages) ==\n\t    flag_decommitted) {\n\t\tsize_t nrun_size = arena_mapbits_unallocated_size_get(chunk,\n\t\t    run_ind+run_pages);\n\t\tsize_t nrun_pages = nrun_size >> LG_PAGE;\n\n\t\t/*\n\t\t * Remove successor from runs_avail; the coalesced run is\n\t\t * inserted later.\n\t\t */\n\t\tassert(arena_mapbits_unallocated_size_get(chunk,\n\t\t    run_ind+run_pages+nrun_pages-1) == nrun_size);\n\t\tassert(arena_mapbits_dirty_get(chunk,\n\t\t    run_ind+run_pages+nrun_pages-1) == flag_dirty);\n\t\tassert(arena_mapbits_decommitted_get(chunk,\n\t\t    run_ind+run_pages+nrun_pages-1) == flag_decommitted);\n\t\tarena_avail_remove(arena, chunk, run_ind+run_pages, nrun_pages);\n\n\t\t/*\n\t\t * If the successor is dirty, remove it from the set of dirty\n\t\t * pages.\n\t\t */\n\t\tif (flag_dirty != 0) {\n\t\t\tarena_run_dirty_remove(arena, chunk, run_ind+run_pages,\n\t\t\t    nrun_pages);\n\t\t}\n\n\t\tsize += nrun_size;\n\t\trun_pages += nrun_pages;\n\n\t\tarena_mapbits_unallocated_size_set(chunk, run_ind, size);\n\t\tarena_mapbits_unallocated_size_set(chunk, run_ind+run_pages-1,\n\t\t    size);\n\t}\n\n\t/* Try to coalesce backward. */\n\tif (run_ind > map_bias && arena_mapbits_allocated_get(chunk,\n\t    run_ind-1) == 0 && arena_mapbits_dirty_get(chunk, run_ind-1) ==\n\t    flag_dirty && arena_mapbits_decommitted_get(chunk, run_ind-1) ==\n\t    flag_decommitted) {\n\t\tsize_t prun_size = arena_mapbits_unallocated_size_get(chunk,\n\t\t    run_ind-1);\n\t\tsize_t prun_pages = prun_size >> LG_PAGE;\n\n\t\trun_ind -= prun_pages;\n\n\t\t/*\n\t\t * Remove predecessor from runs_avail; the coalesced run is\n\t\t * inserted later.\n\t\t */\n\t\tassert(arena_mapbits_unallocated_size_get(chunk, run_ind) ==\n\t\t    prun_size);\n\t\tassert(arena_mapbits_dirty_get(chunk, run_ind) == flag_dirty);\n\t\tassert(arena_mapbits_decommitted_get(chunk, run_ind) ==\n\t\t    flag_decommitted);\n\t\tarena_avail_remove(arena, chunk, run_ind, prun_pages);\n\n\t\t/*\n\t\t * If the predecessor is dirty, remove it from the set of dirty\n\t\t * pages.\n\t\t */\n\t\tif (flag_dirty != 0) {\n\t\t\tarena_run_dirty_remove(arena, chunk, run_ind,\n\t\t\t    prun_pages);\n\t\t}\n\n\t\tsize += prun_size;\n\t\trun_pages += prun_pages;\n\n\t\tarena_mapbits_unallocated_size_set(chunk, run_ind, size);\n\t\tarena_mapbits_unallocated_size_set(chunk, run_ind+run_pages-1,\n\t\t    size);\n\t}\n\n\t*p_size = size;\n\t*p_run_ind = run_ind;\n\t*p_run_pages = run_pages;\n}\n\nstatic size_t\narena_run_size_get(arena_t *arena, arena_chunk_t *chunk, arena_run_t *run,\n    size_t run_ind)\n{\n\tsize_t size;\n\n\tassert(run_ind >= map_bias);\n\tassert(run_ind < chunk_npages);\n\n\tif (arena_mapbits_large_get(chunk, run_ind) != 0) {\n\t\tsize = arena_mapbits_large_size_get(chunk, run_ind);\n\t\tassert(size == PAGE || arena_mapbits_large_size_get(chunk,\n\t\t    run_ind+(size>>LG_PAGE)-1) == 0);\n\t} else {\n\t\tarena_bin_info_t *bin_info = &arena_bin_info[run->binind];\n\t\tsize = bin_info->run_size;\n\t}\n\n\treturn (size);\n}\n\nstatic bool\narena_run_decommit(arena_t *arena, arena_chunk_t *chunk, arena_run_t *run)\n{\n\tarena_chunk_map_misc_t *miscelm = arena_run_to_miscelm(run);\n\tsize_t run_ind = arena_miscelm_to_pageind(miscelm);\n\tsize_t offset = run_ind << LG_PAGE;\n\tsize_t length = arena_run_size_get(arena, chunk, run, run_ind);\n\n\treturn (arena->chunk_hooks.decommit(chunk, chunksize, offset, length,\n\t    arena->ind));\n}\n\nstatic void\narena_run_dalloc(arena_t *arena, arena_run_t *run, bool dirty, bool cleaned,\n    bool decommitted)\n{\n\tarena_chunk_t *chunk;\n\tarena_chunk_map_misc_t *miscelm;\n\tsize_t size, run_ind, run_pages, flag_dirty, flag_decommitted;\n\n\tchunk = (arena_chunk_t *)CHUNK_ADDR2BASE(run);\n\tmiscelm = arena_run_to_miscelm(run);\n\trun_ind = arena_miscelm_to_pageind(miscelm);\n\tassert(run_ind >= map_bias);\n\tassert(run_ind < chunk_npages);\n\tsize = arena_run_size_get(arena, chunk, run, run_ind);\n\trun_pages = (size >> LG_PAGE);\n\tarena_cactive_update(arena, 0, run_pages);\n\tarena->nactive -= run_pages;\n\n\t/*\n\t * The run is dirty if the caller claims to have dirtied it, as well as\n\t * if it was already dirty before being allocated and the caller\n\t * doesn't claim to have cleaned it.\n\t */\n\tassert(arena_mapbits_dirty_get(chunk, run_ind) ==\n\t    arena_mapbits_dirty_get(chunk, run_ind+run_pages-1));\n\tif (!cleaned && !decommitted && arena_mapbits_dirty_get(chunk, run_ind)\n\t    != 0)\n\t\tdirty = true;\n\tflag_dirty = dirty ? CHUNK_MAP_DIRTY : 0;\n\tflag_decommitted = decommitted ? CHUNK_MAP_DECOMMITTED : 0;\n\n\t/* Mark pages as unallocated in the chunk map. */\n\tif (dirty || decommitted) {\n\t\tsize_t flags = flag_dirty | flag_decommitted;\n\t\tarena_mapbits_unallocated_set(chunk, run_ind, size, flags);\n\t\tarena_mapbits_unallocated_set(chunk, run_ind+run_pages-1, size,\n\t\t    flags);\n\t} else {\n\t\tarena_mapbits_unallocated_set(chunk, run_ind, size,\n\t\t    arena_mapbits_unzeroed_get(chunk, run_ind));\n\t\tarena_mapbits_unallocated_set(chunk, run_ind+run_pages-1, size,\n\t\t    arena_mapbits_unzeroed_get(chunk, run_ind+run_pages-1));\n\t}\n\n\tarena_run_coalesce(arena, chunk, &size, &run_ind, &run_pages,\n\t    flag_dirty, flag_decommitted);\n\n\t/* Insert into runs_avail, now that coalescing is complete. */\n\tassert(arena_mapbits_unallocated_size_get(chunk, run_ind) ==\n\t    arena_mapbits_unallocated_size_get(chunk, run_ind+run_pages-1));\n\tassert(arena_mapbits_dirty_get(chunk, run_ind) ==\n\t    arena_mapbits_dirty_get(chunk, run_ind+run_pages-1));\n\tassert(arena_mapbits_decommitted_get(chunk, run_ind) ==\n\t    arena_mapbits_decommitted_get(chunk, run_ind+run_pages-1));\n\tarena_avail_insert(arena, chunk, run_ind, run_pages);\n\n\tif (dirty)\n\t\tarena_run_dirty_insert(arena, chunk, run_ind, run_pages);\n\n\t/* Deallocate chunk if it is now completely unused. */\n\tif (size == arena_maxrun) {\n\t\tassert(run_ind == map_bias);\n\t\tassert(run_pages == (arena_maxrun >> LG_PAGE));\n\t\tarena_chunk_dalloc(arena, chunk);\n\t}\n\n\t/*\n\t * It is okay to do dirty page processing here even if the chunk was\n\t * deallocated above, since in that case it is the spare.  Waiting\n\t * until after possible chunk deallocation to do dirty processing\n\t * allows for an old spare to be fully deallocated, thus decreasing the\n\t * chances of spuriously crossing the dirty page purging threshold.\n\t */\n\tif (dirty)\n\t\tarena_maybe_purge(arena);\n}\n\nstatic void\narena_run_dalloc_decommit(arena_t *arena, arena_chunk_t *chunk,\n    arena_run_t *run)\n{\n\tbool committed = arena_run_decommit(arena, chunk, run);\n\n\tarena_run_dalloc(arena, run, committed, false, !committed);\n}\n\nstatic void\narena_run_trim_head(arena_t *arena, arena_chunk_t *chunk, arena_run_t *run,\n    size_t oldsize, size_t newsize)\n{\n\tarena_chunk_map_misc_t *miscelm = arena_run_to_miscelm(run);\n\tsize_t pageind = arena_miscelm_to_pageind(miscelm);\n\tsize_t head_npages = (oldsize - newsize) >> LG_PAGE;\n\tsize_t flag_dirty = arena_mapbits_dirty_get(chunk, pageind);\n\tsize_t flag_decommitted = arena_mapbits_decommitted_get(chunk, pageind);\n\tsize_t flag_unzeroed_mask = (flag_dirty | flag_decommitted) == 0 ?\n\t    CHUNK_MAP_UNZEROED : 0;\n\n\tassert(oldsize > newsize);\n\n\t/*\n\t * Update the chunk map so that arena_run_dalloc() can treat the\n\t * leading run as separately allocated.  Set the last element of each\n\t * run first, in case of single-page runs.\n\t */\n\tassert(arena_mapbits_large_size_get(chunk, pageind) == oldsize);\n\tarena_mapbits_large_set(chunk, pageind+head_npages-1, 0, flag_dirty |\n\t    (flag_unzeroed_mask & arena_mapbits_unzeroed_get(chunk,\n\t    pageind+head_npages-1)));\n\tarena_mapbits_large_set(chunk, pageind, oldsize-newsize, flag_dirty |\n\t    (flag_unzeroed_mask & arena_mapbits_unzeroed_get(chunk, pageind)));\n\n\tif (config_debug) {\n\t\tUNUSED size_t tail_npages = newsize >> LG_PAGE;\n\t\tassert(arena_mapbits_large_size_get(chunk,\n\t\t    pageind+head_npages+tail_npages-1) == 0);\n\t\tassert(arena_mapbits_dirty_get(chunk,\n\t\t    pageind+head_npages+tail_npages-1) == flag_dirty);\n\t}\n\tarena_mapbits_large_set(chunk, pageind+head_npages, newsize,\n\t    flag_dirty | (flag_unzeroed_mask & arena_mapbits_unzeroed_get(chunk,\n\t    pageind+head_npages)));\n\n\tarena_run_dalloc(arena, run, false, false, (flag_decommitted != 0));\n}\n\nstatic void\narena_run_trim_tail(arena_t *arena, arena_chunk_t *chunk, arena_run_t *run,\n    size_t oldsize, size_t newsize, bool dirty)\n{\n\tarena_chunk_map_misc_t *miscelm = arena_run_to_miscelm(run);\n\tsize_t pageind = arena_miscelm_to_pageind(miscelm);\n\tsize_t head_npages = newsize >> LG_PAGE;\n\tsize_t flag_dirty = arena_mapbits_dirty_get(chunk, pageind);\n\tsize_t flag_decommitted = arena_mapbits_decommitted_get(chunk, pageind);\n\tsize_t flag_unzeroed_mask = (flag_dirty | flag_decommitted) == 0 ?\n\t    CHUNK_MAP_UNZEROED : 0;\n\tarena_chunk_map_misc_t *tail_miscelm;\n\tarena_run_t *tail_run;\n\n\tassert(oldsize > newsize);\n\n\t/*\n\t * Update the chunk map so that arena_run_dalloc() can treat the\n\t * trailing run as separately allocated.  Set the last element of each\n\t * run first, in case of single-page runs.\n\t */\n\tassert(arena_mapbits_large_size_get(chunk, pageind) == oldsize);\n\tarena_mapbits_large_set(chunk, pageind+head_npages-1, 0, flag_dirty |\n\t    (flag_unzeroed_mask & arena_mapbits_unzeroed_get(chunk,\n\t    pageind+head_npages-1)));\n\tarena_mapbits_large_set(chunk, pageind, newsize, flag_dirty |\n\t    (flag_unzeroed_mask & arena_mapbits_unzeroed_get(chunk, pageind)));\n\n\tif (config_debug) {\n\t\tUNUSED size_t tail_npages = (oldsize - newsize) >> LG_PAGE;\n\t\tassert(arena_mapbits_large_size_get(chunk,\n\t\t    pageind+head_npages+tail_npages-1) == 0);\n\t\tassert(arena_mapbits_dirty_get(chunk,\n\t\t    pageind+head_npages+tail_npages-1) == flag_dirty);\n\t}\n\tarena_mapbits_large_set(chunk, pageind+head_npages, oldsize-newsize,\n\t    flag_dirty | (flag_unzeroed_mask & arena_mapbits_unzeroed_get(chunk,\n\t    pageind+head_npages)));\n\n\ttail_miscelm = arena_miscelm_get(chunk, pageind + head_npages);\n\ttail_run = &tail_miscelm->run;\n\tarena_run_dalloc(arena, tail_run, dirty, false, (flag_decommitted !=\n\t    0));\n}\n\nstatic arena_run_t *\narena_bin_runs_first(arena_bin_t *bin)\n{\n\tarena_chunk_map_misc_t *miscelm = arena_run_tree_first(&bin->runs);\n\tif (miscelm != NULL)\n\t\treturn (&miscelm->run);\n\n\treturn (NULL);\n}\n\nstatic void\narena_bin_runs_insert(arena_bin_t *bin, arena_run_t *run)\n{\n\tarena_chunk_map_misc_t *miscelm = arena_run_to_miscelm(run);\n\n\tassert(arena_run_tree_search(&bin->runs, miscelm) == NULL);\n\n\tarena_run_tree_insert(&bin->runs, miscelm);\n}\n\nstatic void\narena_bin_runs_remove(arena_bin_t *bin, arena_run_t *run)\n{\n\tarena_chunk_map_misc_t *miscelm = arena_run_to_miscelm(run);\n\n\tassert(arena_run_tree_search(&bin->runs, miscelm) != NULL);\n\n\tarena_run_tree_remove(&bin->runs, miscelm);\n}\n\nstatic arena_run_t *\narena_bin_nonfull_run_tryget(arena_bin_t *bin)\n{\n\tarena_run_t *run = arena_bin_runs_first(bin);\n\tif (run != NULL) {\n\t\tarena_bin_runs_remove(bin, run);\n\t\tif (config_stats)\n\t\t\tbin->stats.reruns++;\n\t}\n\treturn (run);\n}\n\nstatic arena_run_t *\narena_bin_nonfull_run_get(arena_t *arena, arena_bin_t *bin)\n{\n\tarena_run_t *run;\n\tszind_t binind;\n\tarena_bin_info_t *bin_info;\n\n\t/* Look for a usable run. */\n\trun = arena_bin_nonfull_run_tryget(bin);\n\tif (run != NULL)\n\t\treturn (run);\n\t/* No existing runs have any space available. */\n\n\tbinind = arena_bin_index(arena, bin);\n\tbin_info = &arena_bin_info[binind];\n\n\t/* Allocate a new run. */\n\tmalloc_mutex_unlock(&bin->lock);\n\t/******************************/\n\tmalloc_mutex_lock(&arena->lock);\n\trun = arena_run_alloc_small(arena, bin_info->run_size, binind);\n\tif (run != NULL) {\n\t\t/* Initialize run internals. */\n\t\trun->binind = binind;\n\t\trun->nfree = bin_info->nregs;\n\t\tbitmap_init(run->bitmap, &bin_info->bitmap_info);\n\t}\n\tmalloc_mutex_unlock(&arena->lock);\n\t/********************************/\n\tmalloc_mutex_lock(&bin->lock);\n\tif (run != NULL) {\n\t\tif (config_stats) {\n\t\t\tbin->stats.nruns++;\n\t\t\tbin->stats.curruns++;\n\t\t}\n\t\treturn (run);\n\t}\n\n\t/*\n\t * arena_run_alloc_small() failed, but another thread may have made\n\t * sufficient memory available while this one dropped bin->lock above,\n\t * so search one more time.\n\t */\n\trun = arena_bin_nonfull_run_tryget(bin);\n\tif (run != NULL)\n\t\treturn (run);\n\n\treturn (NULL);\n}\n\n/* Re-fill bin->runcur, then call arena_run_reg_alloc(). */\nstatic void *\narena_bin_malloc_hard(arena_t *arena, arena_bin_t *bin)\n{\n\tszind_t binind;\n\tarena_bin_info_t *bin_info;\n\tarena_run_t *run;\n\n\tbinind = arena_bin_index(arena, bin);\n\tbin_info = &arena_bin_info[binind];\n\tbin->runcur = NULL;\n\trun = arena_bin_nonfull_run_get(arena, bin);\n\tif (bin->runcur != NULL && bin->runcur->nfree > 0) {\n\t\t/*\n\t\t * Another thread updated runcur while this one ran without the\n\t\t * bin lock in arena_bin_nonfull_run_get().\n\t\t */\n\t\tvoid *ret;\n\t\tassert(bin->runcur->nfree > 0);\n\t\tret = arena_run_reg_alloc(bin->runcur, bin_info);\n\t\tif (run != NULL) {\n\t\t\tarena_chunk_t *chunk;\n\n\t\t\t/*\n\t\t\t * arena_run_alloc_small() may have allocated run, or\n\t\t\t * it may have pulled run from the bin's run tree.\n\t\t\t * Therefore it is unsafe to make any assumptions about\n\t\t\t * how run has previously been used, and\n\t\t\t * arena_bin_lower_run() must be called, as if a region\n\t\t\t * were just deallocated from the run.\n\t\t\t */\n\t\t\tchunk = (arena_chunk_t *)CHUNK_ADDR2BASE(run);\n\t\t\tif (run->nfree == bin_info->nregs)\n\t\t\t\tarena_dalloc_bin_run(arena, chunk, run, bin);\n\t\t\telse\n\t\t\t\tarena_bin_lower_run(arena, chunk, run, bin);\n\t\t}\n\t\treturn (ret);\n\t}\n\n\tif (run == NULL)\n\t\treturn (NULL);\n\n\tbin->runcur = run;\n\n\tassert(bin->runcur->nfree > 0);\n\n\treturn (arena_run_reg_alloc(bin->runcur, bin_info));\n}\n\nvoid\narena_tcache_fill_small(arena_t *arena, tcache_bin_t *tbin, szind_t binind,\n    uint64_t prof_accumbytes)\n{\n\tunsigned i, nfill;\n\tarena_bin_t *bin;\n\n\tassert(tbin->ncached == 0);\n\n\tif (config_prof && arena_prof_accum(arena, prof_accumbytes))\n\t\tprof_idump();\n\tbin = &arena->bins[binind];\n\tmalloc_mutex_lock(&bin->lock);\n\tfor (i = 0, nfill = (tcache_bin_info[binind].ncached_max >>\n\t    tbin->lg_fill_div); i < nfill; i++) {\n\t\tarena_run_t *run;\n\t\tvoid *ptr;\n\t\tif ((run = bin->runcur) != NULL && run->nfree > 0)\n\t\t\tptr = arena_run_reg_alloc(run, &arena_bin_info[binind]);\n\t\telse\n\t\t\tptr = arena_bin_malloc_hard(arena, bin);\n\t\tif (ptr == NULL) {\n\t\t\t/*\n\t\t\t * OOM.  tbin->avail isn't yet filled down to its first\n\t\t\t * element, so the successful allocations (if any) must\n\t\t\t * be moved to the base of tbin->avail before bailing\n\t\t\t * out.\n\t\t\t */\n\t\t\tif (i > 0) {\n\t\t\t\tmemmove(tbin->avail, &tbin->avail[nfill - i],\n\t\t\t\t    i * sizeof(void *));\n\t\t\t}\n\t\t\tbreak;\n\t\t}\n\t\tif (config_fill && unlikely(opt_junk_alloc)) {\n\t\t\tarena_alloc_junk_small(ptr, &arena_bin_info[binind],\n\t\t\t    true);\n\t\t}\n\t\t/* Insert such that low regions get used first. */\n\t\ttbin->avail[nfill - 1 - i] = ptr;\n\t}\n\tif (config_stats) {\n\t\tbin->stats.nmalloc += i;\n\t\tbin->stats.nrequests += tbin->tstats.nrequests;\n\t\tbin->stats.curregs += i;\n\t\tbin->stats.nfills++;\n\t\ttbin->tstats.nrequests = 0;\n\t}\n\tmalloc_mutex_unlock(&bin->lock);\n\ttbin->ncached = i;\n}\n\nvoid\narena_alloc_junk_small(void *ptr, arena_bin_info_t *bin_info, bool zero)\n{\n\n\tif (zero) {\n\t\tsize_t redzone_size = bin_info->redzone_size;\n\t\tmemset((void *)((uintptr_t)ptr - redzone_size), 0xa5,\n\t\t    redzone_size);\n\t\tmemset((void *)((uintptr_t)ptr + bin_info->reg_size), 0xa5,\n\t\t    redzone_size);\n\t} else {\n\t\tmemset((void *)((uintptr_t)ptr - bin_info->redzone_size), 0xa5,\n\t\t    bin_info->reg_interval);\n\t}\n}\n\n#ifdef JEMALLOC_JET\n#undef arena_redzone_corruption\n#define\tarena_redzone_corruption JEMALLOC_N(arena_redzone_corruption_impl)\n#endif\nstatic void\narena_redzone_corruption(void *ptr, size_t usize, bool after,\n    size_t offset, uint8_t byte)\n{\n\n\tmalloc_printf(\"<jemalloc>: Corrupt redzone %zu byte%s %s %p \"\n\t    \"(size %zu), byte=%#x\\n\", offset, (offset == 1) ? \"\" : \"s\",\n\t    after ? \"after\" : \"before\", ptr, usize, byte);\n}\n#ifdef JEMALLOC_JET\n#undef arena_redzone_corruption\n#define\tarena_redzone_corruption JEMALLOC_N(arena_redzone_corruption)\narena_redzone_corruption_t *arena_redzone_corruption =\n    JEMALLOC_N(arena_redzone_corruption_impl);\n#endif\n\nstatic void\narena_redzones_validate(void *ptr, arena_bin_info_t *bin_info, bool reset)\n{\n\tbool error = false;\n\n\tif (opt_junk_alloc) {\n\t\tsize_t size = bin_info->reg_size;\n\t\tsize_t redzone_size = bin_info->redzone_size;\n\t\tsize_t i;\n\n\t\tfor (i = 1; i <= redzone_size; i++) {\n\t\t\tuint8_t *byte = (uint8_t *)((uintptr_t)ptr - i);\n\t\t\tif (*byte != 0xa5) {\n\t\t\t\terror = true;\n\t\t\t\tarena_redzone_corruption(ptr, size, false, i,\n\t\t\t\t    *byte);\n\t\t\t\tif (reset)\n\t\t\t\t\t*byte = 0xa5;\n\t\t\t}\n\t\t}\n\t\tfor (i = 0; i < redzone_size; i++) {\n\t\t\tuint8_t *byte = (uint8_t *)((uintptr_t)ptr + size + i);\n\t\t\tif (*byte != 0xa5) {\n\t\t\t\terror = true;\n\t\t\t\tarena_redzone_corruption(ptr, size, true, i,\n\t\t\t\t    *byte);\n\t\t\t\tif (reset)\n\t\t\t\t\t*byte = 0xa5;\n\t\t\t}\n\t\t}\n\t}\n\n\tif (opt_abort && error)\n\t\tabort();\n}\n\n#ifdef JEMALLOC_JET\n#undef arena_dalloc_junk_small\n#define\tarena_dalloc_junk_small JEMALLOC_N(arena_dalloc_junk_small_impl)\n#endif\nvoid\narena_dalloc_junk_small(void *ptr, arena_bin_info_t *bin_info)\n{\n\tsize_t redzone_size = bin_info->redzone_size;\n\n\tarena_redzones_validate(ptr, bin_info, false);\n\tmemset((void *)((uintptr_t)ptr - redzone_size), 0x5a,\n\t    bin_info->reg_interval);\n}\n#ifdef JEMALLOC_JET\n#undef arena_dalloc_junk_small\n#define\tarena_dalloc_junk_small JEMALLOC_N(arena_dalloc_junk_small)\narena_dalloc_junk_small_t *arena_dalloc_junk_small =\n    JEMALLOC_N(arena_dalloc_junk_small_impl);\n#endif\n\nvoid\narena_quarantine_junk_small(void *ptr, size_t usize)\n{\n\tszind_t binind;\n\tarena_bin_info_t *bin_info;\n\tcassert(config_fill);\n\tassert(opt_junk_free);\n\tassert(opt_quarantine);\n\tassert(usize <= SMALL_MAXCLASS);\n\n\tbinind = size2index(usize);\n\tbin_info = &arena_bin_info[binind];\n\tarena_redzones_validate(ptr, bin_info, true);\n}\n\nvoid *\narena_malloc_small(arena_t *arena, size_t size, bool zero)\n{\n\tvoid *ret;\n\tarena_bin_t *bin;\n\tarena_run_t *run;\n\tszind_t binind;\n\n\tbinind = size2index(size);\n\tassert(binind < NBINS);\n\tbin = &arena->bins[binind];\n\tsize = index2size(binind);\n\n\tmalloc_mutex_lock(&bin->lock);\n\tif ((run = bin->runcur) != NULL && run->nfree > 0)\n\t\tret = arena_run_reg_alloc(run, &arena_bin_info[binind]);\n\telse\n\t\tret = arena_bin_malloc_hard(arena, bin);\n\n\tif (ret == NULL) {\n\t\tmalloc_mutex_unlock(&bin->lock);\n\t\treturn (NULL);\n\t}\n\n\tif (config_stats) {\n\t\tbin->stats.nmalloc++;\n\t\tbin->stats.nrequests++;\n\t\tbin->stats.curregs++;\n\t}\n\tmalloc_mutex_unlock(&bin->lock);\n\tif (config_prof && !isthreaded && arena_prof_accum(arena, size))\n\t\tprof_idump();\n\n\tif (!zero) {\n\t\tif (config_fill) {\n\t\t\tif (unlikely(opt_junk_alloc)) {\n\t\t\t\tarena_alloc_junk_small(ret,\n\t\t\t\t    &arena_bin_info[binind], false);\n\t\t\t} else if (unlikely(opt_zero))\n\t\t\t\tmemset(ret, 0, size);\n\t\t}\n\t\tJEMALLOC_VALGRIND_MAKE_MEM_UNDEFINED(ret, size);\n\t} else {\n\t\tif (config_fill && unlikely(opt_junk_alloc)) {\n\t\t\tarena_alloc_junk_small(ret, &arena_bin_info[binind],\n\t\t\t    true);\n\t\t}\n\t\tJEMALLOC_VALGRIND_MAKE_MEM_UNDEFINED(ret, size);\n\t\tmemset(ret, 0, size);\n\t}\n\n\treturn (ret);\n}\n\nvoid *\narena_malloc_large(arena_t *arena, size_t size, bool zero)\n{\n\tvoid *ret;\n\tsize_t usize;\n\tuintptr_t random_offset;\n\tarena_run_t *run;\n\tarena_chunk_map_misc_t *miscelm;\n\tUNUSED bool idump;\n\n\t/* Large allocation. */\n\tusize = s2u(size);\n\tmalloc_mutex_lock(&arena->lock);\n\tif (config_cache_oblivious) {\n\t\tuint64_t r;\n\n\t\t/*\n\t\t * Compute a uniformly distributed offset within the first page\n\t\t * that is a multiple of the cacheline size, e.g. [0 .. 63) * 64\n\t\t * for 4 KiB pages and 64-byte cachelines.\n\t\t */\n\t\tprng64(r, LG_PAGE - LG_CACHELINE, arena->offset_state,\n\t\t    UINT64_C(6364136223846793009),\n\t\t    UINT64_C(1442695040888963409));\n\t\trandom_offset = ((uintptr_t)r) << LG_CACHELINE;\n\t} else\n\t\trandom_offset = 0;\n\trun = arena_run_alloc_large(arena, usize + large_pad, zero);\n\tif (run == NULL) {\n\t\tmalloc_mutex_unlock(&arena->lock);\n\t\treturn (NULL);\n\t}\n\tmiscelm = arena_run_to_miscelm(run);\n\tret = (void *)((uintptr_t)arena_miscelm_to_rpages(miscelm) +\n\t    random_offset);\n\tif (config_stats) {\n\t\tszind_t index = size2index(usize) - NBINS;\n\n\t\tarena->stats.nmalloc_large++;\n\t\tarena->stats.nrequests_large++;\n\t\tarena->stats.allocated_large += usize;\n\t\tarena->stats.lstats[index].nmalloc++;\n\t\tarena->stats.lstats[index].nrequests++;\n\t\tarena->stats.lstats[index].curruns++;\n\t}\n\tif (config_prof)\n\t\tidump = arena_prof_accum_locked(arena, usize);\n\tmalloc_mutex_unlock(&arena->lock);\n\tif (config_prof && idump)\n\t\tprof_idump();\n\n\tif (!zero) {\n\t\tif (config_fill) {\n\t\t\tif (unlikely(opt_junk_alloc))\n\t\t\t\tmemset(ret, 0xa5, usize);\n\t\t\telse if (unlikely(opt_zero))\n\t\t\t\tmemset(ret, 0, usize);\n\t\t}\n\t}\n\n\treturn (ret);\n}\n\n/* Only handles large allocations that require more than page alignment. */\nstatic void *\narena_palloc_large(tsd_t *tsd, arena_t *arena, size_t usize, size_t alignment,\n    bool zero)\n{\n\tvoid *ret;\n\tsize_t alloc_size, leadsize, trailsize;\n\tarena_run_t *run;\n\tarena_chunk_t *chunk;\n\tarena_chunk_map_misc_t *miscelm;\n\tvoid *rpages;\n\n\tassert(usize == PAGE_CEILING(usize));\n\n\tarena = arena_choose(tsd, arena);\n\tif (unlikely(arena == NULL))\n\t\treturn (NULL);\n\n\talignment = PAGE_CEILING(alignment);\n\talloc_size = usize + large_pad + alignment - PAGE;\n\n\tmalloc_mutex_lock(&arena->lock);\n\trun = arena_run_alloc_large(arena, alloc_size, false);\n\tif (run == NULL) {\n\t\tmalloc_mutex_unlock(&arena->lock);\n\t\treturn (NULL);\n\t}\n\tchunk = (arena_chunk_t *)CHUNK_ADDR2BASE(run);\n\tmiscelm = arena_run_to_miscelm(run);\n\trpages = arena_miscelm_to_rpages(miscelm);\n\n\tleadsize = ALIGNMENT_CEILING((uintptr_t)rpages, alignment) -\n\t    (uintptr_t)rpages;\n\tassert(alloc_size >= leadsize + usize);\n\ttrailsize = alloc_size - leadsize - usize - large_pad;\n\tif (leadsize != 0) {\n\t\tarena_chunk_map_misc_t *head_miscelm = miscelm;\n\t\tarena_run_t *head_run = run;\n\n\t\tmiscelm = arena_miscelm_get(chunk,\n\t\t    arena_miscelm_to_pageind(head_miscelm) + (leadsize >>\n\t\t    LG_PAGE));\n\t\trun = &miscelm->run;\n\n\t\tarena_run_trim_head(arena, chunk, head_run, alloc_size,\n\t\t    alloc_size - leadsize);\n\t}\n\tif (trailsize != 0) {\n\t\tarena_run_trim_tail(arena, chunk, run, usize + large_pad +\n\t\t    trailsize, usize + large_pad, false);\n\t}\n\tif (arena_run_init_large(arena, run, usize + large_pad, zero)) {\n\t\tsize_t run_ind =\n\t\t    arena_miscelm_to_pageind(arena_run_to_miscelm(run));\n\t\tbool dirty = (arena_mapbits_dirty_get(chunk, run_ind) != 0);\n\t\tbool decommitted = (arena_mapbits_decommitted_get(chunk,\n\t\t    run_ind) != 0);\n\n\t\tassert(decommitted); /* Cause of OOM. */\n\t\tarena_run_dalloc(arena, run, dirty, false, decommitted);\n\t\tmalloc_mutex_unlock(&arena->lock);\n\t\treturn (NULL);\n\t}\n\tret = arena_miscelm_to_rpages(miscelm);\n\n\tif (config_stats) {\n\t\tszind_t index = size2index(usize) - NBINS;\n\n\t\tarena->stats.nmalloc_large++;\n\t\tarena->stats.nrequests_large++;\n\t\tarena->stats.allocated_large += usize;\n\t\tarena->stats.lstats[index].nmalloc++;\n\t\tarena->stats.lstats[index].nrequests++;\n\t\tarena->stats.lstats[index].curruns++;\n\t}\n\tmalloc_mutex_unlock(&arena->lock);\n\n\tif (config_fill && !zero) {\n\t\tif (unlikely(opt_junk_alloc))\n\t\t\tmemset(ret, 0xa5, usize);\n\t\telse if (unlikely(opt_zero))\n\t\t\tmemset(ret, 0, usize);\n\t}\n\treturn (ret);\n}\n\nvoid *\narena_palloc(tsd_t *tsd, arena_t *arena, size_t usize, size_t alignment,\n    bool zero, tcache_t *tcache)\n{\n\tvoid *ret;\n\n\tif (usize <= SMALL_MAXCLASS && (alignment < PAGE || (alignment == PAGE\n\t    && (usize & PAGE_MASK) == 0))) {\n\t\t/* Small; alignment doesn't require special run placement. */\n\t\tret = arena_malloc(tsd, arena, usize, zero, tcache);\n\t} else if (usize <= large_maxclass && alignment <= PAGE) {\n\t\t/*\n\t\t * Large; alignment doesn't require special run placement.\n\t\t * However, the cached pointer may be at a random offset from\n\t\t * the base of the run, so do some bit manipulation to retrieve\n\t\t * the base.\n\t\t */\n\t\tret = arena_malloc(tsd, arena, usize, zero, tcache);\n\t\tif (config_cache_oblivious)\n\t\t\tret = (void *)((uintptr_t)ret & ~PAGE_MASK);\n\t} else {\n\t\tif (likely(usize <= large_maxclass)) {\n\t\t\tret = arena_palloc_large(tsd, arena, usize, alignment,\n\t\t\t    zero);\n\t\t} else if (likely(alignment <= chunksize))\n\t\t\tret = huge_malloc(tsd, arena, usize, zero, tcache);\n\t\telse {\n\t\t\tret = huge_palloc(tsd, arena, usize, alignment, zero,\n\t\t\t    tcache);\n\t\t}\n\t}\n\treturn (ret);\n}\n\nvoid\narena_prof_promoted(const void *ptr, size_t size)\n{\n\tarena_chunk_t *chunk;\n\tsize_t pageind;\n\tszind_t binind;\n\n\tcassert(config_prof);\n\tassert(ptr != NULL);\n\tassert(CHUNK_ADDR2BASE(ptr) != ptr);\n\tassert(isalloc(ptr, false) == LARGE_MINCLASS);\n\tassert(isalloc(ptr, true) == LARGE_MINCLASS);\n\tassert(size <= SMALL_MAXCLASS);\n\n\tchunk = (arena_chunk_t *)CHUNK_ADDR2BASE(ptr);\n\tpageind = ((uintptr_t)ptr - (uintptr_t)chunk) >> LG_PAGE;\n\tbinind = size2index(size);\n\tassert(binind < NBINS);\n\tarena_mapbits_large_binind_set(chunk, pageind, binind);\n\n\tassert(isalloc(ptr, false) == LARGE_MINCLASS);\n\tassert(isalloc(ptr, true) == size);\n}\n\nstatic void\narena_dissociate_bin_run(arena_chunk_t *chunk, arena_run_t *run,\n    arena_bin_t *bin)\n{\n\n\t/* Dissociate run from bin. */\n\tif (run == bin->runcur)\n\t\tbin->runcur = NULL;\n\telse {\n\t\tszind_t binind = arena_bin_index(extent_node_arena_get(\n\t\t    &chunk->node), bin);\n\t\tarena_bin_info_t *bin_info = &arena_bin_info[binind];\n\n\t\tif (bin_info->nregs != 1) {\n\t\t\t/*\n\t\t\t * This block's conditional is necessary because if the\n\t\t\t * run only contains one region, then it never gets\n\t\t\t * inserted into the non-full runs tree.\n\t\t\t */\n\t\t\tarena_bin_runs_remove(bin, run);\n\t\t}\n\t}\n}\n\nstatic void\narena_dalloc_bin_run(arena_t *arena, arena_chunk_t *chunk, arena_run_t *run,\n    arena_bin_t *bin)\n{\n\n\tassert(run != bin->runcur);\n\tassert(arena_run_tree_search(&bin->runs, arena_run_to_miscelm(run)) ==\n\t    NULL);\n\n\tmalloc_mutex_unlock(&bin->lock);\n\t/******************************/\n\tmalloc_mutex_lock(&arena->lock);\n\tarena_run_dalloc_decommit(arena, chunk, run);\n\tmalloc_mutex_unlock(&arena->lock);\n\t/****************************/\n\tmalloc_mutex_lock(&bin->lock);\n\tif (config_stats)\n\t\tbin->stats.curruns--;\n}\n\nstatic void\narena_bin_lower_run(arena_t *arena, arena_chunk_t *chunk, arena_run_t *run,\n    arena_bin_t *bin)\n{\n\n\t/*\n\t * Make sure that if bin->runcur is non-NULL, it refers to the lowest\n\t * non-full run.  It is okay to NULL runcur out rather than proactively\n\t * keeping it pointing at the lowest non-full run.\n\t */\n\tif ((uintptr_t)run < (uintptr_t)bin->runcur) {\n\t\t/* Switch runcur. */\n\t\tif (bin->runcur->nfree > 0)\n\t\t\tarena_bin_runs_insert(bin, bin->runcur);\n\t\tbin->runcur = run;\n\t\tif (config_stats)\n\t\t\tbin->stats.reruns++;\n\t} else\n\t\tarena_bin_runs_insert(bin, run);\n}\n\nstatic void\narena_dalloc_bin_locked_impl(arena_t *arena, arena_chunk_t *chunk, void *ptr,\n    arena_chunk_map_bits_t *bitselm, bool junked)\n{\n\tsize_t pageind, rpages_ind;\n\tarena_run_t *run;\n\tarena_bin_t *bin;\n\tarena_bin_info_t *bin_info;\n\tszind_t binind;\n\n\tpageind = ((uintptr_t)ptr - (uintptr_t)chunk) >> LG_PAGE;\n\trpages_ind = pageind - arena_mapbits_small_runind_get(chunk, pageind);\n\trun = &arena_miscelm_get(chunk, rpages_ind)->run;\n\tbinind = run->binind;\n\tbin = &arena->bins[binind];\n\tbin_info = &arena_bin_info[binind];\n\n\tif (!junked && config_fill && unlikely(opt_junk_free))\n\t\tarena_dalloc_junk_small(ptr, bin_info);\n\n\tarena_run_reg_dalloc(run, ptr);\n\tif (run->nfree == bin_info->nregs) {\n\t\tarena_dissociate_bin_run(chunk, run, bin);\n\t\tarena_dalloc_bin_run(arena, chunk, run, bin);\n\t} else if (run->nfree == 1 && run != bin->runcur)\n\t\tarena_bin_lower_run(arena, chunk, run, bin);\n\n\tif (config_stats) {\n\t\tbin->stats.ndalloc++;\n\t\tbin->stats.curregs--;\n\t}\n}\n\nvoid\narena_dalloc_bin_junked_locked(arena_t *arena, arena_chunk_t *chunk, void *ptr,\n    arena_chunk_map_bits_t *bitselm)\n{\n\n\tarena_dalloc_bin_locked_impl(arena, chunk, ptr, bitselm, true);\n}\n\nvoid\narena_dalloc_bin(arena_t *arena, arena_chunk_t *chunk, void *ptr,\n    size_t pageind, arena_chunk_map_bits_t *bitselm)\n{\n\tarena_run_t *run;\n\tarena_bin_t *bin;\n\tsize_t rpages_ind;\n\n\trpages_ind = pageind - arena_mapbits_small_runind_get(chunk, pageind);\n\trun = &arena_miscelm_get(chunk, rpages_ind)->run;\n\tbin = &arena->bins[run->binind];\n\tmalloc_mutex_lock(&bin->lock);\n\tarena_dalloc_bin_locked_impl(arena, chunk, ptr, bitselm, false);\n\tmalloc_mutex_unlock(&bin->lock);\n}\n\nvoid\narena_dalloc_small(arena_t *arena, arena_chunk_t *chunk, void *ptr,\n    size_t pageind)\n{\n\tarena_chunk_map_bits_t *bitselm;\n\n\tif (config_debug) {\n\t\t/* arena_ptr_small_binind_get() does extra sanity checking. */\n\t\tassert(arena_ptr_small_binind_get(ptr, arena_mapbits_get(chunk,\n\t\t    pageind)) != BININD_INVALID);\n\t}\n\tbitselm = arena_bitselm_get(chunk, pageind);\n\tarena_dalloc_bin(arena, chunk, ptr, pageind, bitselm);\n}\n\n#ifdef JEMALLOC_JET\n#undef arena_dalloc_junk_large\n#define\tarena_dalloc_junk_large JEMALLOC_N(arena_dalloc_junk_large_impl)\n#endif\nvoid\narena_dalloc_junk_large(void *ptr, size_t usize)\n{\n\n\tif (config_fill && unlikely(opt_junk_free))\n\t\tmemset(ptr, 0x5a, usize);\n}\n#ifdef JEMALLOC_JET\n#undef arena_dalloc_junk_large\n#define\tarena_dalloc_junk_large JEMALLOC_N(arena_dalloc_junk_large)\narena_dalloc_junk_large_t *arena_dalloc_junk_large =\n    JEMALLOC_N(arena_dalloc_junk_large_impl);\n#endif\n\nstatic void\narena_dalloc_large_locked_impl(arena_t *arena, arena_chunk_t *chunk,\n    void *ptr, bool junked)\n{\n\tsize_t pageind = ((uintptr_t)ptr - (uintptr_t)chunk) >> LG_PAGE;\n\tarena_chunk_map_misc_t *miscelm = arena_miscelm_get(chunk, pageind);\n\tarena_run_t *run = &miscelm->run;\n\n\tif (config_fill || config_stats) {\n\t\tsize_t usize = arena_mapbits_large_size_get(chunk, pageind) -\n\t\t    large_pad;\n\n\t\tif (!junked)\n\t\t\tarena_dalloc_junk_large(ptr, usize);\n\t\tif (config_stats) {\n\t\t\tszind_t index = size2index(usize) - NBINS;\n\n\t\t\tarena->stats.ndalloc_large++;\n\t\t\tarena->stats.allocated_large -= usize;\n\t\t\tarena->stats.lstats[index].ndalloc++;\n\t\t\tarena->stats.lstats[index].curruns--;\n\t\t}\n\t}\n\n\tarena_run_dalloc_decommit(arena, chunk, run);\n}\n\nvoid\narena_dalloc_large_junked_locked(arena_t *arena, arena_chunk_t *chunk,\n    void *ptr)\n{\n\n\tarena_dalloc_large_locked_impl(arena, chunk, ptr, true);\n}\n\nvoid\narena_dalloc_large(arena_t *arena, arena_chunk_t *chunk, void *ptr)\n{\n\n\tmalloc_mutex_lock(&arena->lock);\n\tarena_dalloc_large_locked_impl(arena, chunk, ptr, false);\n\tmalloc_mutex_unlock(&arena->lock);\n}\n\nstatic void\narena_ralloc_large_shrink(arena_t *arena, arena_chunk_t *chunk, void *ptr,\n    size_t oldsize, size_t size)\n{\n\tsize_t pageind = ((uintptr_t)ptr - (uintptr_t)chunk) >> LG_PAGE;\n\tarena_chunk_map_misc_t *miscelm = arena_miscelm_get(chunk, pageind);\n\tarena_run_t *run = &miscelm->run;\n\n\tassert(size < oldsize);\n\n\t/*\n\t * Shrink the run, and make trailing pages available for other\n\t * allocations.\n\t */\n\tmalloc_mutex_lock(&arena->lock);\n\tarena_run_trim_tail(arena, chunk, run, oldsize + large_pad, size +\n\t    large_pad, true);\n\tif (config_stats) {\n\t\tszind_t oldindex = size2index(oldsize) - NBINS;\n\t\tszind_t index = size2index(size) - NBINS;\n\n\t\tarena->stats.ndalloc_large++;\n\t\tarena->stats.allocated_large -= oldsize;\n\t\tarena->stats.lstats[oldindex].ndalloc++;\n\t\tarena->stats.lstats[oldindex].curruns--;\n\n\t\tarena->stats.nmalloc_large++;\n\t\tarena->stats.nrequests_large++;\n\t\tarena->stats.allocated_large += size;\n\t\tarena->stats.lstats[index].nmalloc++;\n\t\tarena->stats.lstats[index].nrequests++;\n\t\tarena->stats.lstats[index].curruns++;\n\t}\n\tmalloc_mutex_unlock(&arena->lock);\n}\n\nstatic bool\narena_ralloc_large_grow(arena_t *arena, arena_chunk_t *chunk, void *ptr,\n    size_t oldsize, size_t usize_min, size_t usize_max, bool zero)\n{\n\tsize_t pageind = ((uintptr_t)ptr - (uintptr_t)chunk) >> LG_PAGE;\n\tsize_t npages = (oldsize + large_pad) >> LG_PAGE;\n\tsize_t followsize;\n\n\tassert(oldsize == arena_mapbits_large_size_get(chunk, pageind) -\n\t    large_pad);\n\n\t/* Try to extend the run. */\n\tmalloc_mutex_lock(&arena->lock);\n\tif (pageind+npages >= chunk_npages || arena_mapbits_allocated_get(chunk,\n\t    pageind+npages) != 0)\n\t\tgoto label_fail;\n\tfollowsize = arena_mapbits_unallocated_size_get(chunk, pageind+npages);\n\tif (oldsize + followsize >= usize_min) {\n\t\t/*\n\t\t * The next run is available and sufficiently large.  Split the\n\t\t * following run, then merge the first part with the existing\n\t\t * allocation.\n\t\t */\n\t\tarena_run_t *run;\n\t\tsize_t usize, splitsize, size, flag_dirty, flag_unzeroed_mask;\n\n\t\tusize = usize_max;\n\t\twhile (oldsize + followsize < usize)\n\t\t\tusize = index2size(size2index(usize)-1);\n\t\tassert(usize >= usize_min);\n\t\tassert(usize >= oldsize);\n\t\tsplitsize = usize - oldsize;\n\t\tif (splitsize == 0)\n\t\t\tgoto label_fail;\n\n\t\trun = &arena_miscelm_get(chunk, pageind+npages)->run;\n\t\tif (arena_run_split_large(arena, run, splitsize, zero))\n\t\t\tgoto label_fail;\n\n\t\tif (config_cache_oblivious && zero) {\n\t\t\t/*\n\t\t\t * Zero the trailing bytes of the original allocation's\n\t\t\t * last page, since they are in an indeterminate state.\n\t\t\t */\n\t\t\tassert(PAGE_CEILING(oldsize) == oldsize);\n\t\t\tmemset((void *)((uintptr_t)ptr + oldsize), 0,\n\t\t\t    PAGE_CEILING((uintptr_t)ptr) - (uintptr_t)ptr);\n\t\t}\n\n\t\tsize = oldsize + splitsize;\n\t\tnpages = (size + large_pad) >> LG_PAGE;\n\n\t\t/*\n\t\t * Mark the extended run as dirty if either portion of the run\n\t\t * was dirty before allocation.  This is rather pedantic,\n\t\t * because there's not actually any sequence of events that\n\t\t * could cause the resulting run to be passed to\n\t\t * arena_run_dalloc() with the dirty argument set to false\n\t\t * (which is when dirty flag consistency would really matter).\n\t\t */\n\t\tflag_dirty = arena_mapbits_dirty_get(chunk, pageind) |\n\t\t    arena_mapbits_dirty_get(chunk, pageind+npages-1);\n\t\tflag_unzeroed_mask = flag_dirty == 0 ? CHUNK_MAP_UNZEROED : 0;\n\t\tarena_mapbits_large_set(chunk, pageind, size + large_pad,\n\t\t    flag_dirty | (flag_unzeroed_mask &\n\t\t    arena_mapbits_unzeroed_get(chunk, pageind)));\n\t\tarena_mapbits_large_set(chunk, pageind+npages-1, 0, flag_dirty |\n\t\t    (flag_unzeroed_mask & arena_mapbits_unzeroed_get(chunk,\n\t\t    pageind+npages-1)));\n\n\t\tif (config_stats) {\n\t\t\tszind_t oldindex = size2index(oldsize) - NBINS;\n\t\t\tszind_t index = size2index(size) - NBINS;\n\n\t\t\tarena->stats.ndalloc_large++;\n\t\t\tarena->stats.allocated_large -= oldsize;\n\t\t\tarena->stats.lstats[oldindex].ndalloc++;\n\t\t\tarena->stats.lstats[oldindex].curruns--;\n\n\t\t\tarena->stats.nmalloc_large++;\n\t\t\tarena->stats.nrequests_large++;\n\t\t\tarena->stats.allocated_large += size;\n\t\t\tarena->stats.lstats[index].nmalloc++;\n\t\t\tarena->stats.lstats[index].nrequests++;\n\t\t\tarena->stats.lstats[index].curruns++;\n\t\t}\n\t\tmalloc_mutex_unlock(&arena->lock);\n\t\treturn (false);\n\t}\nlabel_fail:\n\tmalloc_mutex_unlock(&arena->lock);\n\treturn (true);\n}\n\n#ifdef JEMALLOC_JET\n#undef arena_ralloc_junk_large\n#define\tarena_ralloc_junk_large JEMALLOC_N(arena_ralloc_junk_large_impl)\n#endif\nstatic void\narena_ralloc_junk_large(void *ptr, size_t old_usize, size_t usize)\n{\n\n\tif (config_fill && unlikely(opt_junk_free)) {\n\t\tmemset((void *)((uintptr_t)ptr + usize), 0x5a,\n\t\t    old_usize - usize);\n\t}\n}\n#ifdef JEMALLOC_JET\n#undef arena_ralloc_junk_large\n#define\tarena_ralloc_junk_large JEMALLOC_N(arena_ralloc_junk_large)\narena_ralloc_junk_large_t *arena_ralloc_junk_large =\n    JEMALLOC_N(arena_ralloc_junk_large_impl);\n#endif\n\n/*\n * Try to resize a large allocation, in order to avoid copying.  This will\n * always fail if growing an object, and the following run is already in use.\n */\nstatic bool\narena_ralloc_large(void *ptr, size_t oldsize, size_t usize_min,\n    size_t usize_max, bool zero)\n{\n\tarena_chunk_t *chunk;\n\tarena_t *arena;\n\n\tif (oldsize == usize_max) {\n\t\t/* Current size class is compatible and maximal. */\n\t\treturn (false);\n\t}\n\n\tchunk = (arena_chunk_t *)CHUNK_ADDR2BASE(ptr);\n\tarena = extent_node_arena_get(&chunk->node);\n\n\tif (oldsize < usize_max) {\n\t\tbool ret = arena_ralloc_large_grow(arena, chunk, ptr, oldsize,\n\t\t    usize_min, usize_max, zero);\n\t\tif (config_fill && !ret && !zero) {\n\t\t\tif (unlikely(opt_junk_alloc)) {\n\t\t\t\tmemset((void *)((uintptr_t)ptr + oldsize), 0xa5,\n\t\t\t\t    isalloc(ptr, config_prof) - oldsize);\n\t\t\t} else if (unlikely(opt_zero)) {\n\t\t\t\tmemset((void *)((uintptr_t)ptr + oldsize), 0,\n\t\t\t\t    isalloc(ptr, config_prof) - oldsize);\n\t\t\t}\n\t\t}\n\t\treturn (ret);\n\t}\n\n\tassert(oldsize > usize_max);\n\t/* Fill before shrinking in order avoid a race. */\n\tarena_ralloc_junk_large(ptr, oldsize, usize_max);\n\tarena_ralloc_large_shrink(arena, chunk, ptr, oldsize, usize_max);\n\treturn (false);\n}\n\nbool\narena_ralloc_no_move(void *ptr, size_t oldsize, size_t size, size_t extra,\n    bool zero)\n{\n\tsize_t usize_min, usize_max;\n\n\tusize_min = s2u(size);\n\tusize_max = s2u(size + extra);\n\tif (likely(oldsize <= large_maxclass && usize_min <= large_maxclass)) {\n\t\t/*\n\t\t * Avoid moving the allocation if the size class can be left the\n\t\t * same.\n\t\t */\n\t\tif (oldsize <= SMALL_MAXCLASS) {\n\t\t\tassert(arena_bin_info[size2index(oldsize)].reg_size ==\n\t\t\t    oldsize);\n\t\t\tif ((usize_max <= SMALL_MAXCLASS &&\n\t\t\t    size2index(usize_max) == size2index(oldsize)) ||\n\t\t\t    (size <= oldsize && usize_max >= oldsize))\n\t\t\t\treturn (false);\n\t\t} else {\n\t\t\tif (usize_max > SMALL_MAXCLASS) {\n\t\t\t\tif (!arena_ralloc_large(ptr, oldsize, usize_min,\n\t\t\t\t    usize_max, zero))\n\t\t\t\t\treturn (false);\n\t\t\t}\n\t\t}\n\n\t\t/* Reallocation would require a move. */\n\t\treturn (true);\n\t} else {\n\t\treturn (huge_ralloc_no_move(ptr, oldsize, usize_min, usize_max,\n\t\t    zero));\n\t}\n}\n\nstatic void *\narena_ralloc_move_helper(tsd_t *tsd, arena_t *arena, size_t usize,\n    size_t alignment, bool zero, tcache_t *tcache)\n{\n\n\tif (alignment == 0)\n\t\treturn (arena_malloc(tsd, arena, usize, zero, tcache));\n\tusize = sa2u(usize, alignment);\n\tif (usize == 0)\n\t\treturn (NULL);\n\treturn (ipalloct(tsd, usize, alignment, zero, tcache, arena));\n}\n\nvoid *\narena_ralloc(tsd_t *tsd, arena_t *arena, void *ptr, size_t oldsize, size_t size,\n    size_t alignment, bool zero, tcache_t *tcache)\n{\n\tvoid *ret;\n\tsize_t usize;\n\n\tusize = s2u(size);\n\tif (usize == 0)\n\t\treturn (NULL);\n\n\tif (likely(usize <= large_maxclass)) {\n\t\tsize_t copysize;\n\n\t\t/* Try to avoid moving the allocation. */\n\t\tif (!arena_ralloc_no_move(ptr, oldsize, usize, 0, zero))\n\t\t\treturn (ptr);\n\n\t\t/*\n\t\t * size and oldsize are different enough that we need to move\n\t\t * the object.  In that case, fall back to allocating new space\n\t\t * and copying.\n\t\t */\n\t\tret = arena_ralloc_move_helper(tsd, arena, usize, alignment,\n\t\t    zero, tcache);\n\t\tif (ret == NULL)\n\t\t\treturn (NULL);\n\n\t\t/*\n\t\t * Junk/zero-filling were already done by\n\t\t * ipalloc()/arena_malloc().\n\t\t */\n\n\t\tcopysize = (usize < oldsize) ? usize : oldsize;\n\t\tJEMALLOC_VALGRIND_MAKE_MEM_UNDEFINED(ret, copysize);\n\t\tmemcpy(ret, ptr, copysize);\n\t\tisqalloc(tsd, ptr, oldsize, tcache);\n\t} else {\n\t\tret = huge_ralloc(tsd, arena, ptr, oldsize, usize, alignment,\n\t\t    zero, tcache);\n\t}\n\treturn (ret);\n}\n\ndss_prec_t\narena_dss_prec_get(arena_t *arena)\n{\n\tdss_prec_t ret;\n\n\tmalloc_mutex_lock(&arena->lock);\n\tret = arena->dss_prec;\n\tmalloc_mutex_unlock(&arena->lock);\n\treturn (ret);\n}\n\nbool\narena_dss_prec_set(arena_t *arena, dss_prec_t dss_prec)\n{\n\n\tif (!have_dss)\n\t\treturn (dss_prec != dss_prec_disabled);\n\tmalloc_mutex_lock(&arena->lock);\n\tarena->dss_prec = dss_prec;\n\tmalloc_mutex_unlock(&arena->lock);\n\treturn (false);\n}\n\nssize_t\narena_lg_dirty_mult_default_get(void)\n{\n\n\treturn ((ssize_t)atomic_read_z((size_t *)&lg_dirty_mult_default));\n}\n\nbool\narena_lg_dirty_mult_default_set(ssize_t lg_dirty_mult)\n{\n\n\tif (!arena_lg_dirty_mult_valid(lg_dirty_mult))\n\t\treturn (true);\n\tatomic_write_z((size_t *)&lg_dirty_mult_default, (size_t)lg_dirty_mult);\n\treturn (false);\n}\n\nvoid\narena_stats_merge(arena_t *arena, const char **dss, ssize_t *lg_dirty_mult,\n    size_t *nactive, size_t *ndirty, arena_stats_t *astats,\n    malloc_bin_stats_t *bstats, malloc_large_stats_t *lstats,\n    malloc_huge_stats_t *hstats)\n{\n\tunsigned i;\n\n\tmalloc_mutex_lock(&arena->lock);\n\t*dss = dss_prec_names[arena->dss_prec];\n\t*lg_dirty_mult = arena->lg_dirty_mult;\n\t*nactive += arena->nactive;\n\t*ndirty += arena->ndirty;\n\n\tastats->mapped += arena->stats.mapped;\n\tastats->npurge += arena->stats.npurge;\n\tastats->nmadvise += arena->stats.nmadvise;\n\tastats->purged += arena->stats.purged;\n\tastats->metadata_mapped += arena->stats.metadata_mapped;\n\tastats->metadata_allocated += arena_metadata_allocated_get(arena);\n\tastats->allocated_large += arena->stats.allocated_large;\n\tastats->nmalloc_large += arena->stats.nmalloc_large;\n\tastats->ndalloc_large += arena->stats.ndalloc_large;\n\tastats->nrequests_large += arena->stats.nrequests_large;\n\tastats->allocated_huge += arena->stats.allocated_huge;\n\tastats->nmalloc_huge += arena->stats.nmalloc_huge;\n\tastats->ndalloc_huge += arena->stats.ndalloc_huge;\n\n\tfor (i = 0; i < nlclasses; i++) {\n\t\tlstats[i].nmalloc += arena->stats.lstats[i].nmalloc;\n\t\tlstats[i].ndalloc += arena->stats.lstats[i].ndalloc;\n\t\tlstats[i].nrequests += arena->stats.lstats[i].nrequests;\n\t\tlstats[i].curruns += arena->stats.lstats[i].curruns;\n\t}\n\n\tfor (i = 0; i < nhclasses; i++) {\n\t\thstats[i].nmalloc += arena->stats.hstats[i].nmalloc;\n\t\thstats[i].ndalloc += arena->stats.hstats[i].ndalloc;\n\t\thstats[i].curhchunks += arena->stats.hstats[i].curhchunks;\n\t}\n\tmalloc_mutex_unlock(&arena->lock);\n\n\tfor (i = 0; i < NBINS; i++) {\n\t\tarena_bin_t *bin = &arena->bins[i];\n\n\t\tmalloc_mutex_lock(&bin->lock);\n\t\tbstats[i].nmalloc += bin->stats.nmalloc;\n\t\tbstats[i].ndalloc += bin->stats.ndalloc;\n\t\tbstats[i].nrequests += bin->stats.nrequests;\n\t\tbstats[i].curregs += bin->stats.curregs;\n\t\tif (config_tcache) {\n\t\t\tbstats[i].nfills += bin->stats.nfills;\n\t\t\tbstats[i].nflushes += bin->stats.nflushes;\n\t\t}\n\t\tbstats[i].nruns += bin->stats.nruns;\n\t\tbstats[i].reruns += bin->stats.reruns;\n\t\tbstats[i].curruns += bin->stats.curruns;\n\t\tmalloc_mutex_unlock(&bin->lock);\n\t}\n}\n\narena_t *\narena_new(unsigned ind)\n{\n\tarena_t *arena;\n\tunsigned i;\n\tarena_bin_t *bin;\n\n\t/*\n\t * Allocate arena, arena->lstats, and arena->hstats contiguously, mainly\n\t * because there is no way to clean up if base_alloc() OOMs.\n\t */\n\tif (config_stats) {\n\t\tarena = (arena_t *)base_alloc(CACHELINE_CEILING(sizeof(arena_t))\n\t\t    + QUANTUM_CEILING(nlclasses * sizeof(malloc_large_stats_t) +\n\t\t    nhclasses) * sizeof(malloc_huge_stats_t));\n\t} else\n\t\tarena = (arena_t *)base_alloc(sizeof(arena_t));\n\tif (arena == NULL)\n\t\treturn (NULL);\n\n\tarena->ind = ind;\n\tarena->nthreads = 0;\n\tif (malloc_mutex_init(&arena->lock))\n\t\treturn (NULL);\n\n\tif (config_stats) {\n\t\tmemset(&arena->stats, 0, sizeof(arena_stats_t));\n\t\tarena->stats.lstats = (malloc_large_stats_t *)((uintptr_t)arena\n\t\t    + CACHELINE_CEILING(sizeof(arena_t)));\n\t\tmemset(arena->stats.lstats, 0, nlclasses *\n\t\t    sizeof(malloc_large_stats_t));\n\t\tarena->stats.hstats = (malloc_huge_stats_t *)((uintptr_t)arena\n\t\t    + CACHELINE_CEILING(sizeof(arena_t)) +\n\t\t    QUANTUM_CEILING(nlclasses * sizeof(malloc_large_stats_t)));\n\t\tmemset(arena->stats.hstats, 0, nhclasses *\n\t\t    sizeof(malloc_huge_stats_t));\n\t\tif (config_tcache)\n\t\t\tql_new(&arena->tcache_ql);\n\t}\n\n\tif (config_prof)\n\t\tarena->prof_accumbytes = 0;\n\n\tif (config_cache_oblivious) {\n\t\t/*\n\t\t * A nondeterministic seed based on the address of arena reduces\n\t\t * the likelihood of lockstep non-uniform cache index\n\t\t * utilization among identical concurrent processes, but at the\n\t\t * cost of test repeatability.  For debug builds, instead use a\n\t\t * deterministic seed.\n\t\t */\n\t\tarena->offset_state = config_debug ? ind :\n\t\t    (uint64_t)(uintptr_t)arena;\n\t}\n\n\tarena->dss_prec = chunk_dss_prec_get();\n\n\tarena->spare = NULL;\n\n\tarena->lg_dirty_mult = arena_lg_dirty_mult_default_get();\n\tarena->purging = false;\n\tarena->nactive = 0;\n\tarena->ndirty = 0;\n\n\tarena_avail_tree_new(&arena->runs_avail);\n\tqr_new(&arena->runs_dirty, rd_link);\n\tqr_new(&arena->chunks_cache, cc_link);\n\n\tql_new(&arena->huge);\n\tif (malloc_mutex_init(&arena->huge_mtx))\n\t\treturn (NULL);\n\n\textent_tree_szad_new(&arena->chunks_szad_cached);\n\textent_tree_ad_new(&arena->chunks_ad_cached);\n\textent_tree_szad_new(&arena->chunks_szad_retained);\n\textent_tree_ad_new(&arena->chunks_ad_retained);\n\tif (malloc_mutex_init(&arena->chunks_mtx))\n\t\treturn (NULL);\n\tql_new(&arena->node_cache);\n\tif (malloc_mutex_init(&arena->node_cache_mtx))\n\t\treturn (NULL);\n\n\tarena->chunk_hooks = chunk_hooks_default;\n\n\t/* Initialize bins. */\n\tfor (i = 0; i < NBINS; i++) {\n\t\tbin = &arena->bins[i];\n\t\tif (malloc_mutex_init(&bin->lock))\n\t\t\treturn (NULL);\n\t\tbin->runcur = NULL;\n\t\tarena_run_tree_new(&bin->runs);\n\t\tif (config_stats)\n\t\t\tmemset(&bin->stats, 0, sizeof(malloc_bin_stats_t));\n\t}\n\n\treturn (arena);\n}\n\n/*\n * Calculate bin_info->run_size such that it meets the following constraints:\n *\n *   *) bin_info->run_size <= arena_maxrun\n *   *) bin_info->nregs <= RUN_MAXREGS\n *\n * bin_info->nregs and bin_info->reg0_offset are also calculated here, since\n * these settings are all interdependent.\n */\nstatic void\nbin_info_run_size_calc(arena_bin_info_t *bin_info)\n{\n\tsize_t pad_size;\n\tsize_t try_run_size, perfect_run_size, actual_run_size;\n\tuint32_t try_nregs, perfect_nregs, actual_nregs;\n\n\t/*\n\t * Determine redzone size based on minimum alignment and minimum\n\t * redzone size.  Add padding to the end of the run if it is needed to\n\t * align the regions.  The padding allows each redzone to be half the\n\t * minimum alignment; without the padding, each redzone would have to\n\t * be twice as large in order to maintain alignment.\n\t */\n\tif (config_fill && unlikely(opt_redzone)) {\n\t\tsize_t align_min = ZU(1) << (jemalloc_ffs(bin_info->reg_size) -\n\t\t    1);\n\t\tif (align_min <= REDZONE_MINSIZE) {\n\t\t\tbin_info->redzone_size = REDZONE_MINSIZE;\n\t\t\tpad_size = 0;\n\t\t} else {\n\t\t\tbin_info->redzone_size = align_min >> 1;\n\t\t\tpad_size = bin_info->redzone_size;\n\t\t}\n\t} else {\n\t\tbin_info->redzone_size = 0;\n\t\tpad_size = 0;\n\t}\n\tbin_info->reg_interval = bin_info->reg_size +\n\t    (bin_info->redzone_size << 1);\n\n\t/*\n\t * Compute run size under ideal conditions (no redzones, no limit on run\n\t * size).\n\t */\n\ttry_run_size = PAGE;\n\ttry_nregs = try_run_size / bin_info->reg_size;\n\tdo {\n\t\tperfect_run_size = try_run_size;\n\t\tperfect_nregs = try_nregs;\n\n\t\ttry_run_size += PAGE;\n\t\ttry_nregs = try_run_size / bin_info->reg_size;\n\t} while (perfect_run_size != perfect_nregs * bin_info->reg_size);\n\tassert(perfect_nregs <= RUN_MAXREGS);\n\n\tactual_run_size = perfect_run_size;\n\tactual_nregs = (actual_run_size - pad_size) / bin_info->reg_interval;\n\n\t/*\n\t * Redzones can require enough padding that not even a single region can\n\t * fit within the number of pages that would normally be dedicated to a\n\t * run for this size class.  Increase the run size until at least one\n\t * region fits.\n\t */\n\twhile (actual_nregs == 0) {\n\t\tassert(config_fill && unlikely(opt_redzone));\n\n\t\tactual_run_size += PAGE;\n\t\tactual_nregs = (actual_run_size - pad_size) /\n\t\t    bin_info->reg_interval;\n\t}\n\n\t/*\n\t * Make sure that the run will fit within an arena chunk.\n\t */\n\twhile (actual_run_size > arena_maxrun) {\n\t\tactual_run_size -= PAGE;\n\t\tactual_nregs = (actual_run_size - pad_size) /\n\t\t    bin_info->reg_interval;\n\t}\n\tassert(actual_nregs > 0);\n\tassert(actual_run_size == s2u(actual_run_size));\n\n\t/* Copy final settings. */\n\tbin_info->run_size = actual_run_size;\n\tbin_info->nregs = actual_nregs;\n\tbin_info->reg0_offset = actual_run_size - (actual_nregs *\n\t    bin_info->reg_interval) - pad_size + bin_info->redzone_size;\n\n\tif (actual_run_size > small_maxrun)\n\t\tsmall_maxrun = actual_run_size;\n\n\tassert(bin_info->reg0_offset - bin_info->redzone_size + (bin_info->nregs\n\t    * bin_info->reg_interval) + pad_size == bin_info->run_size);\n}\n\nstatic void\nbin_info_init(void)\n{\n\tarena_bin_info_t *bin_info;\n\n#define\tBIN_INFO_INIT_bin_yes(index, size)\t\t\t\t\\\n\tbin_info = &arena_bin_info[index];\t\t\t\t\\\n\tbin_info->reg_size = size;\t\t\t\t\t\\\n\tbin_info_run_size_calc(bin_info);\t\t\t\t\\\n\tbitmap_info_init(&bin_info->bitmap_info, bin_info->nregs);\n#define\tBIN_INFO_INIT_bin_no(index, size)\n#define\tSC(index, lg_grp, lg_delta, ndelta, bin, lg_delta_lookup)\t\\\n\tBIN_INFO_INIT_bin_##bin(index, (ZU(1)<<lg_grp) + (ZU(ndelta)<<lg_delta))\n\tSIZE_CLASSES\n#undef BIN_INFO_INIT_bin_yes\n#undef BIN_INFO_INIT_bin_no\n#undef SC\n}\n\nstatic bool\nsmall_run_size_init(void)\n{\n\n\tassert(small_maxrun != 0);\n\n\tsmall_run_tab = (bool *)base_alloc(sizeof(bool) * (small_maxrun >>\n\t    LG_PAGE));\n\tif (small_run_tab == NULL)\n\t\treturn (true);\n\n#define\tTAB_INIT_bin_yes(index, size) {\t\t\t\t\t\\\n\t\tarena_bin_info_t *bin_info = &arena_bin_info[index];\t\\\n\t\tsmall_run_tab[bin_info->run_size >> LG_PAGE] = true;\t\\\n\t}\n#define\tTAB_INIT_bin_no(index, size)\n#define\tSC(index, lg_grp, lg_delta, ndelta, bin, lg_delta_lookup)\t\\\n\tTAB_INIT_bin_##bin(index, (ZU(1)<<lg_grp) + (ZU(ndelta)<<lg_delta))\n\tSIZE_CLASSES\n#undef TAB_INIT_bin_yes\n#undef TAB_INIT_bin_no\n#undef SC\n\n\treturn (false);\n}\n\nbool\narena_boot(void)\n{\n\tunsigned i;\n\n\tarena_lg_dirty_mult_default_set(opt_lg_dirty_mult);\n\n\t/*\n\t * Compute the header size such that it is large enough to contain the\n\t * page map.  The page map is biased to omit entries for the header\n\t * itself, so some iteration is necessary to compute the map bias.\n\t *\n\t * 1) Compute safe header_size and map_bias values that include enough\n\t *    space for an unbiased page map.\n\t * 2) Refine map_bias based on (1) to omit the header pages in the page\n\t *    map.  The resulting map_bias may be one too small.\n\t * 3) Refine map_bias based on (2).  The result will be >= the result\n\t *    from (2), and will always be correct.\n\t */\n\tmap_bias = 0;\n\tfor (i = 0; i < 3; i++) {\n\t\tsize_t header_size = offsetof(arena_chunk_t, map_bits) +\n\t\t    ((sizeof(arena_chunk_map_bits_t) +\n\t\t    sizeof(arena_chunk_map_misc_t)) * (chunk_npages-map_bias));\n\t\tmap_bias = (header_size + PAGE_MASK) >> LG_PAGE;\n\t}\n\tassert(map_bias > 0);\n\n\tmap_misc_offset = offsetof(arena_chunk_t, map_bits) +\n\t    sizeof(arena_chunk_map_bits_t) * (chunk_npages-map_bias);\n\n\tarena_maxrun = chunksize - (map_bias << LG_PAGE);\n\tassert(arena_maxrun > 0);\n\tlarge_maxclass = index2size(size2index(chunksize)-1);\n\tif (large_maxclass > arena_maxrun) {\n\t\t/*\n\t\t * For small chunk sizes it's possible for there to be fewer\n\t\t * non-header pages available than are necessary to serve the\n\t\t * size classes just below chunksize.\n\t\t */\n\t\tlarge_maxclass = arena_maxrun;\n\t}\n\tassert(large_maxclass > 0);\n\tnlclasses = size2index(large_maxclass) - size2index(SMALL_MAXCLASS);\n\tnhclasses = NSIZES - nlclasses - NBINS;\n\n\tbin_info_init();\n\treturn (small_run_size_init());\n}\n\nvoid\narena_prefork(arena_t *arena)\n{\n\tunsigned i;\n\n\tmalloc_mutex_prefork(&arena->lock);\n\tmalloc_mutex_prefork(&arena->huge_mtx);\n\tmalloc_mutex_prefork(&arena->chunks_mtx);\n\tmalloc_mutex_prefork(&arena->node_cache_mtx);\n\tfor (i = 0; i < NBINS; i++)\n\t\tmalloc_mutex_prefork(&arena->bins[i].lock);\n}\n\nvoid\narena_postfork_parent(arena_t *arena)\n{\n\tunsigned i;\n\n\tfor (i = 0; i < NBINS; i++)\n\t\tmalloc_mutex_postfork_parent(&arena->bins[i].lock);\n\tmalloc_mutex_postfork_parent(&arena->node_cache_mtx);\n\tmalloc_mutex_postfork_parent(&arena->chunks_mtx);\n\tmalloc_mutex_postfork_parent(&arena->huge_mtx);\n\tmalloc_mutex_postfork_parent(&arena->lock);\n}\n\nvoid\narena_postfork_child(arena_t *arena)\n{\n\tunsigned i;\n\n\tfor (i = 0; i < NBINS; i++)\n\t\tmalloc_mutex_postfork_child(&arena->bins[i].lock);\n\tmalloc_mutex_postfork_child(&arena->node_cache_mtx);\n\tmalloc_mutex_postfork_child(&arena->chunks_mtx);\n\tmalloc_mutex_postfork_child(&arena->huge_mtx);\n\tmalloc_mutex_postfork_child(&arena->lock);\n}\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.8/deps/jemalloc/src/atomic.c",
    "content": "#define\tJEMALLOC_ATOMIC_C_\n#include \"jemalloc/internal/jemalloc_internal.h\"\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.8/deps/jemalloc/src/base.c",
    "content": "#define\tJEMALLOC_BASE_C_\n#include \"jemalloc/internal/jemalloc_internal.h\"\n\n/******************************************************************************/\n/* Data. */\n\nstatic malloc_mutex_t\tbase_mtx;\nstatic extent_tree_t\tbase_avail_szad;\nstatic extent_node_t\t*base_nodes;\nstatic size_t\t\tbase_allocated;\nstatic size_t\t\tbase_resident;\nstatic size_t\t\tbase_mapped;\n\n/******************************************************************************/\n\n/* base_mtx must be held. */\nstatic extent_node_t *\nbase_node_try_alloc(void)\n{\n\textent_node_t *node;\n\n\tif (base_nodes == NULL)\n\t\treturn (NULL);\n\tnode = base_nodes;\n\tbase_nodes = *(extent_node_t **)node;\n\tJEMALLOC_VALGRIND_MAKE_MEM_UNDEFINED(node, sizeof(extent_node_t));\n\treturn (node);\n}\n\n/* base_mtx must be held. */\nstatic void\nbase_node_dalloc(extent_node_t *node)\n{\n\n\tJEMALLOC_VALGRIND_MAKE_MEM_UNDEFINED(node, sizeof(extent_node_t));\n\t*(extent_node_t **)node = base_nodes;\n\tbase_nodes = node;\n}\n\n/* base_mtx must be held. */\nstatic extent_node_t *\nbase_chunk_alloc(size_t minsize)\n{\n\textent_node_t *node;\n\tsize_t csize, nsize;\n\tvoid *addr;\n\n\tassert(minsize != 0);\n\tnode = base_node_try_alloc();\n\t/* Allocate enough space to also carve a node out if necessary. */\n\tnsize = (node == NULL) ? CACHELINE_CEILING(sizeof(extent_node_t)) : 0;\n\tcsize = CHUNK_CEILING(minsize + nsize);\n\taddr = chunk_alloc_base(csize);\n\tif (addr == NULL) {\n\t\tif (node != NULL)\n\t\t\tbase_node_dalloc(node);\n\t\treturn (NULL);\n\t}\n\tbase_mapped += csize;\n\tif (node == NULL) {\n\t\tnode = (extent_node_t *)addr;\n\t\taddr = (void *)((uintptr_t)addr + nsize);\n\t\tcsize -= nsize;\n\t\tif (config_stats) {\n\t\t\tbase_allocated += nsize;\n\t\t\tbase_resident += PAGE_CEILING(nsize);\n\t\t}\n\t}\n\textent_node_init(node, NULL, addr, csize, true, true);\n\treturn (node);\n}\n\n/*\n * base_alloc() guarantees demand-zeroed memory, in order to make multi-page\n * sparse data structures such as radix tree nodes efficient with respect to\n * physical memory usage.\n */\nvoid *\nbase_alloc(size_t size)\n{\n\tvoid *ret;\n\tsize_t csize, usize;\n\textent_node_t *node;\n\textent_node_t key;\n\n\t/*\n\t * Round size up to nearest multiple of the cacheline size, so that\n\t * there is no chance of false cache line sharing.\n\t */\n\tcsize = CACHELINE_CEILING(size);\n\n\tusize = s2u(csize);\n\textent_node_init(&key, NULL, NULL, usize, false, false);\n\tmalloc_mutex_lock(&base_mtx);\n\tnode = extent_tree_szad_nsearch(&base_avail_szad, &key);\n\tif (node != NULL) {\n\t\t/* Use existing space. */\n\t\textent_tree_szad_remove(&base_avail_szad, node);\n\t} else {\n\t\t/* Try to allocate more space. */\n\t\tnode = base_chunk_alloc(csize);\n\t}\n\tif (node == NULL) {\n\t\tret = NULL;\n\t\tgoto label_return;\n\t}\n\n\tret = extent_node_addr_get(node);\n\tif (extent_node_size_get(node) > csize) {\n\t\textent_node_addr_set(node, (void *)((uintptr_t)ret + csize));\n\t\textent_node_size_set(node, extent_node_size_get(node) - csize);\n\t\textent_tree_szad_insert(&base_avail_szad, node);\n\t} else\n\t\tbase_node_dalloc(node);\n\tif (config_stats) {\n\t\tbase_allocated += csize;\n\t\t/*\n\t\t * Add one PAGE to base_resident for every page boundary that is\n\t\t * crossed by the new allocation.\n\t\t */\n\t\tbase_resident += PAGE_CEILING((uintptr_t)ret + csize) -\n\t\t    PAGE_CEILING((uintptr_t)ret);\n\t}\n\tJEMALLOC_VALGRIND_MAKE_MEM_DEFINED(ret, csize);\nlabel_return:\n\tmalloc_mutex_unlock(&base_mtx);\n\treturn (ret);\n}\n\nvoid\nbase_stats_get(size_t *allocated, size_t *resident, size_t *mapped)\n{\n\n\tmalloc_mutex_lock(&base_mtx);\n\tassert(base_allocated <= base_resident);\n\tassert(base_resident <= base_mapped);\n\t*allocated = base_allocated;\n\t*resident = base_resident;\n\t*mapped = base_mapped;\n\tmalloc_mutex_unlock(&base_mtx);\n}\n\nbool\nbase_boot(void)\n{\n\n\tif (malloc_mutex_init(&base_mtx))\n\t\treturn (true);\n\textent_tree_szad_new(&base_avail_szad);\n\tbase_nodes = NULL;\n\n\treturn (false);\n}\n\nvoid\nbase_prefork(void)\n{\n\n\tmalloc_mutex_prefork(&base_mtx);\n}\n\nvoid\nbase_postfork_parent(void)\n{\n\n\tmalloc_mutex_postfork_parent(&base_mtx);\n}\n\nvoid\nbase_postfork_child(void)\n{\n\n\tmalloc_mutex_postfork_child(&base_mtx);\n}\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.8/deps/jemalloc/src/bitmap.c",
    "content": "#define\tJEMALLOC_BITMAP_C_\n#include \"jemalloc/internal/jemalloc_internal.h\"\n\n/******************************************************************************/\n\nvoid\nbitmap_info_init(bitmap_info_t *binfo, size_t nbits)\n{\n\tunsigned i;\n\tsize_t group_count;\n\n\tassert(nbits > 0);\n\tassert(nbits <= (ZU(1) << LG_BITMAP_MAXBITS));\n\n\t/*\n\t * Compute the number of groups necessary to store nbits bits, and\n\t * progressively work upward through the levels until reaching a level\n\t * that requires only one group.\n\t */\n\tbinfo->levels[0].group_offset = 0;\n\tgroup_count = BITMAP_BITS2GROUPS(nbits);\n\tfor (i = 1; group_count > 1; i++) {\n\t\tassert(i < BITMAP_MAX_LEVELS);\n\t\tbinfo->levels[i].group_offset = binfo->levels[i-1].group_offset\n\t\t    + group_count;\n\t\tgroup_count = BITMAP_BITS2GROUPS(group_count);\n\t}\n\tbinfo->levels[i].group_offset = binfo->levels[i-1].group_offset\n\t    + group_count;\n\tassert(binfo->levels[i].group_offset <= BITMAP_GROUPS_MAX);\n\tbinfo->nlevels = i;\n\tbinfo->nbits = nbits;\n}\n\nsize_t\nbitmap_info_ngroups(const bitmap_info_t *binfo)\n{\n\n\treturn (binfo->levels[binfo->nlevels].group_offset << LG_SIZEOF_BITMAP);\n}\n\nsize_t\nbitmap_size(size_t nbits)\n{\n\tbitmap_info_t binfo;\n\n\tbitmap_info_init(&binfo, nbits);\n\treturn (bitmap_info_ngroups(&binfo));\n}\n\nvoid\nbitmap_init(bitmap_t *bitmap, const bitmap_info_t *binfo)\n{\n\tsize_t extra;\n\tunsigned i;\n\n\t/*\n\t * Bits are actually inverted with regard to the external bitmap\n\t * interface, so the bitmap starts out with all 1 bits, except for\n\t * trailing unused bits (if any).  Note that each group uses bit 0 to\n\t * correspond to the first logical bit in the group, so extra bits\n\t * are the most significant bits of the last group.\n\t */\n\tmemset(bitmap, 0xffU, binfo->levels[binfo->nlevels].group_offset <<\n\t    LG_SIZEOF_BITMAP);\n\textra = (BITMAP_GROUP_NBITS - (binfo->nbits & BITMAP_GROUP_NBITS_MASK))\n\t    & BITMAP_GROUP_NBITS_MASK;\n\tif (extra != 0)\n\t\tbitmap[binfo->levels[1].group_offset - 1] >>= extra;\n\tfor (i = 1; i < binfo->nlevels; i++) {\n\t\tsize_t group_count = binfo->levels[i].group_offset -\n\t\t    binfo->levels[i-1].group_offset;\n\t\textra = (BITMAP_GROUP_NBITS - (group_count &\n\t\t    BITMAP_GROUP_NBITS_MASK)) & BITMAP_GROUP_NBITS_MASK;\n\t\tif (extra != 0)\n\t\t\tbitmap[binfo->levels[i+1].group_offset - 1] >>= extra;\n\t}\n}\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.8/deps/jemalloc/src/chunk.c",
    "content": "#define\tJEMALLOC_CHUNK_C_\n#include \"jemalloc/internal/jemalloc_internal.h\"\n\n/******************************************************************************/\n/* Data. */\n\nconst char\t*opt_dss = DSS_DEFAULT;\nsize_t\t\topt_lg_chunk = 0;\n\n/* Used exclusively for gdump triggering. */\nstatic size_t\tcurchunks;\nstatic size_t\thighchunks;\n\nrtree_t\t\tchunks_rtree;\n\n/* Various chunk-related settings. */\nsize_t\t\tchunksize;\nsize_t\t\tchunksize_mask; /* (chunksize - 1). */\nsize_t\t\tchunk_npages;\n\nstatic void\t*chunk_alloc_default(void *new_addr, size_t size,\n    size_t alignment, bool *zero, bool *commit, unsigned arena_ind);\nstatic bool\tchunk_dalloc_default(void *chunk, size_t size, bool committed,\n    unsigned arena_ind);\nstatic bool\tchunk_commit_default(void *chunk, size_t size, size_t offset,\n    size_t length, unsigned arena_ind);\nstatic bool\tchunk_decommit_default(void *chunk, size_t size, size_t offset,\n    size_t length, unsigned arena_ind);\nstatic bool\tchunk_purge_default(void *chunk, size_t size, size_t offset,\n    size_t length, unsigned arena_ind);\nstatic bool\tchunk_split_default(void *chunk, size_t size, size_t size_a,\n    size_t size_b, bool committed, unsigned arena_ind);\nstatic bool\tchunk_merge_default(void *chunk_a, size_t size_a, void *chunk_b,\n    size_t size_b, bool committed, unsigned arena_ind);\n\nconst chunk_hooks_t\tchunk_hooks_default = {\n\tchunk_alloc_default,\n\tchunk_dalloc_default,\n\tchunk_commit_default,\n\tchunk_decommit_default,\n\tchunk_purge_default,\n\tchunk_split_default,\n\tchunk_merge_default\n};\n\n/******************************************************************************/\n/*\n * Function prototypes for static functions that are referenced prior to\n * definition.\n */\n\nstatic void\tchunk_record(arena_t *arena, chunk_hooks_t *chunk_hooks,\n    extent_tree_t *chunks_szad, extent_tree_t *chunks_ad, bool cache,\n    void *chunk, size_t size, bool zeroed, bool committed);\n\n/******************************************************************************/\n\nstatic chunk_hooks_t\nchunk_hooks_get_locked(arena_t *arena)\n{\n\n\treturn (arena->chunk_hooks);\n}\n\nchunk_hooks_t\nchunk_hooks_get(arena_t *arena)\n{\n\tchunk_hooks_t chunk_hooks;\n\n\tmalloc_mutex_lock(&arena->chunks_mtx);\n\tchunk_hooks = chunk_hooks_get_locked(arena);\n\tmalloc_mutex_unlock(&arena->chunks_mtx);\n\n\treturn (chunk_hooks);\n}\n\nchunk_hooks_t\nchunk_hooks_set(arena_t *arena, const chunk_hooks_t *chunk_hooks)\n{\n\tchunk_hooks_t old_chunk_hooks;\n\n\tmalloc_mutex_lock(&arena->chunks_mtx);\n\told_chunk_hooks = arena->chunk_hooks;\n\t/*\n\t * Copy each field atomically so that it is impossible for readers to\n\t * see partially updated pointers.  There are places where readers only\n\t * need one hook function pointer (therefore no need to copy the\n\t * entirety of arena->chunk_hooks), and stale reads do not affect\n\t * correctness, so they perform unlocked reads.\n\t */\n#define\tATOMIC_COPY_HOOK(n) do {\t\t\t\t\t\\\n\tunion {\t\t\t\t\t\t\t\t\\\n\t\tchunk_##n##_t\t**n;\t\t\t\t\t\\\n\t\tvoid\t\t**v;\t\t\t\t\t\\\n\t} u;\t\t\t\t\t\t\t\t\\\n\tu.n = &arena->chunk_hooks.n;\t\t\t\t\t\\\n\tatomic_write_p(u.v, chunk_hooks->n);\t\t\t\t\\\n} while (0)\n\tATOMIC_COPY_HOOK(alloc);\n\tATOMIC_COPY_HOOK(dalloc);\n\tATOMIC_COPY_HOOK(commit);\n\tATOMIC_COPY_HOOK(decommit);\n\tATOMIC_COPY_HOOK(purge);\n\tATOMIC_COPY_HOOK(split);\n\tATOMIC_COPY_HOOK(merge);\n#undef ATOMIC_COPY_HOOK\n\tmalloc_mutex_unlock(&arena->chunks_mtx);\n\n\treturn (old_chunk_hooks);\n}\n\nstatic void\nchunk_hooks_assure_initialized_impl(arena_t *arena, chunk_hooks_t *chunk_hooks,\n    bool locked)\n{\n\tstatic const chunk_hooks_t uninitialized_hooks =\n\t    CHUNK_HOOKS_INITIALIZER;\n\n\tif (memcmp(chunk_hooks, &uninitialized_hooks, sizeof(chunk_hooks_t)) ==\n\t    0) {\n\t\t*chunk_hooks = locked ? chunk_hooks_get_locked(arena) :\n\t\t    chunk_hooks_get(arena);\n\t}\n}\n\nstatic void\nchunk_hooks_assure_initialized_locked(arena_t *arena,\n    chunk_hooks_t *chunk_hooks)\n{\n\n\tchunk_hooks_assure_initialized_impl(arena, chunk_hooks, true);\n}\n\nstatic void\nchunk_hooks_assure_initialized(arena_t *arena, chunk_hooks_t *chunk_hooks)\n{\n\n\tchunk_hooks_assure_initialized_impl(arena, chunk_hooks, false);\n}\n\nbool\nchunk_register(const void *chunk, const extent_node_t *node)\n{\n\n\tassert(extent_node_addr_get(node) == chunk);\n\n\tif (rtree_set(&chunks_rtree, (uintptr_t)chunk, node))\n\t\treturn (true);\n\tif (config_prof && opt_prof) {\n\t\tsize_t size = extent_node_size_get(node);\n\t\tsize_t nadd = (size == 0) ? 1 : size / chunksize;\n\t\tsize_t cur = atomic_add_z(&curchunks, nadd);\n\t\tsize_t high = atomic_read_z(&highchunks);\n\t\twhile (cur > high && atomic_cas_z(&highchunks, high, cur)) {\n\t\t\t/*\n\t\t\t * Don't refresh cur, because it may have decreased\n\t\t\t * since this thread lost the highchunks update race.\n\t\t\t */\n\t\t\thigh = atomic_read_z(&highchunks);\n\t\t}\n\t\tif (cur > high && prof_gdump_get_unlocked())\n\t\t\tprof_gdump();\n\t}\n\n\treturn (false);\n}\n\nvoid\nchunk_deregister(const void *chunk, const extent_node_t *node)\n{\n\tbool err;\n\n\terr = rtree_set(&chunks_rtree, (uintptr_t)chunk, NULL);\n\tassert(!err);\n\tif (config_prof && opt_prof) {\n\t\tsize_t size = extent_node_size_get(node);\n\t\tsize_t nsub = (size == 0) ? 1 : size / chunksize;\n\t\tassert(atomic_read_z(&curchunks) >= nsub);\n\t\tatomic_sub_z(&curchunks, nsub);\n\t}\n}\n\n/*\n * Do first-best-fit chunk selection, i.e. select the lowest chunk that best\n * fits.\n */\nstatic extent_node_t *\nchunk_first_best_fit(arena_t *arena, extent_tree_t *chunks_szad,\n    extent_tree_t *chunks_ad, size_t size)\n{\n\textent_node_t key;\n\n\tassert(size == CHUNK_CEILING(size));\n\n\textent_node_init(&key, arena, NULL, size, false, false);\n\treturn (extent_tree_szad_nsearch(chunks_szad, &key));\n}\n\nstatic void *\nchunk_recycle(arena_t *arena, chunk_hooks_t *chunk_hooks,\n    extent_tree_t *chunks_szad, extent_tree_t *chunks_ad, bool cache,\n    void *new_addr, size_t size, size_t alignment, bool *zero, bool *commit,\n    bool dalloc_node)\n{\n\tvoid *ret;\n\textent_node_t *node;\n\tsize_t alloc_size, leadsize, trailsize;\n\tbool zeroed, committed;\n\n\tassert(new_addr == NULL || alignment == chunksize);\n\t/*\n\t * Cached chunks use the node linkage embedded in their headers, in\n\t * which case dalloc_node is true, and new_addr is non-NULL because\n\t * we're operating on a specific chunk.\n\t */\n\tassert(dalloc_node || new_addr != NULL);\n\n\talloc_size = CHUNK_CEILING(s2u(size + alignment - chunksize));\n\t/* Beware size_t wrap-around. */\n\tif (alloc_size < size)\n\t\treturn (NULL);\n\tmalloc_mutex_lock(&arena->chunks_mtx);\n\tchunk_hooks_assure_initialized_locked(arena, chunk_hooks);\n\tif (new_addr != NULL) {\n\t\textent_node_t key;\n\t\textent_node_init(&key, arena, new_addr, alloc_size, false,\n\t\t    false);\n\t\tnode = extent_tree_ad_search(chunks_ad, &key);\n\t} else {\n\t\tnode = chunk_first_best_fit(arena, chunks_szad, chunks_ad,\n\t\t    alloc_size);\n\t}\n\tif (node == NULL || (new_addr != NULL && extent_node_size_get(node) <\n\t    size)) {\n\t\tmalloc_mutex_unlock(&arena->chunks_mtx);\n\t\treturn (NULL);\n\t}\n\tleadsize = ALIGNMENT_CEILING((uintptr_t)extent_node_addr_get(node),\n\t    alignment) - (uintptr_t)extent_node_addr_get(node);\n\tassert(new_addr == NULL || leadsize == 0);\n\tassert(extent_node_size_get(node) >= leadsize + size);\n\ttrailsize = extent_node_size_get(node) - leadsize - size;\n\tret = (void *)((uintptr_t)extent_node_addr_get(node) + leadsize);\n\tzeroed = extent_node_zeroed_get(node);\n\tif (zeroed)\n\t\t*zero = true;\n\tcommitted = extent_node_committed_get(node);\n\tif (committed)\n\t\t*commit = true;\n\t/* Split the lead. */\n\tif (leadsize != 0 &&\n\t    chunk_hooks->split(extent_node_addr_get(node),\n\t    extent_node_size_get(node), leadsize, size, false, arena->ind)) {\n\t\tmalloc_mutex_unlock(&arena->chunks_mtx);\n\t\treturn (NULL);\n\t}\n\t/* Remove node from the tree. */\n\textent_tree_szad_remove(chunks_szad, node);\n\textent_tree_ad_remove(chunks_ad, node);\n\tarena_chunk_cache_maybe_remove(arena, node, cache);\n\tif (leadsize != 0) {\n\t\t/* Insert the leading space as a smaller chunk. */\n\t\textent_node_size_set(node, leadsize);\n\t\textent_tree_szad_insert(chunks_szad, node);\n\t\textent_tree_ad_insert(chunks_ad, node);\n\t\tarena_chunk_cache_maybe_insert(arena, node, cache);\n\t\tnode = NULL;\n\t}\n\tif (trailsize != 0) {\n\t\t/* Split the trail. */\n\t\tif (chunk_hooks->split(ret, size + trailsize, size,\n\t\t    trailsize, false, arena->ind)) {\n\t\t\tif (dalloc_node && node != NULL)\n\t\t\t\tarena_node_dalloc(arena, node);\n\t\t\tmalloc_mutex_unlock(&arena->chunks_mtx);\n\t\t\tchunk_record(arena, chunk_hooks, chunks_szad, chunks_ad,\n\t\t\t    cache, ret, size + trailsize, zeroed, committed);\n\t\t\treturn (NULL);\n\t\t}\n\t\t/* Insert the trailing space as a smaller chunk. */\n\t\tif (node == NULL) {\n\t\t\tnode = arena_node_alloc(arena);\n\t\t\tif (node == NULL) {\n\t\t\t\tmalloc_mutex_unlock(&arena->chunks_mtx);\n\t\t\t\tchunk_record(arena, chunk_hooks, chunks_szad,\n\t\t\t\t    chunks_ad, cache, ret, size + trailsize,\n\t\t\t\t    zeroed, committed);\n\t\t\t\treturn (NULL);\n\t\t\t}\n\t\t}\n\t\textent_node_init(node, arena, (void *)((uintptr_t)(ret) + size),\n\t\t    trailsize, zeroed, committed);\n\t\textent_tree_szad_insert(chunks_szad, node);\n\t\textent_tree_ad_insert(chunks_ad, node);\n\t\tarena_chunk_cache_maybe_insert(arena, node, cache);\n\t\tnode = NULL;\n\t}\n\tif (!committed && chunk_hooks->commit(ret, size, 0, size, arena->ind)) {\n\t\tmalloc_mutex_unlock(&arena->chunks_mtx);\n\t\tchunk_record(arena, chunk_hooks, chunks_szad, chunks_ad, cache,\n\t\t    ret, size, zeroed, committed);\n\t\treturn (NULL);\n\t}\n\tmalloc_mutex_unlock(&arena->chunks_mtx);\n\n\tassert(dalloc_node || node != NULL);\n\tif (dalloc_node && node != NULL)\n\t\tarena_node_dalloc(arena, node);\n\tif (*zero) {\n\t\tif (!zeroed)\n\t\t\tmemset(ret, 0, size);\n\t\telse if (config_debug) {\n\t\t\tsize_t i;\n\t\t\tsize_t *p = (size_t *)(uintptr_t)ret;\n\n\t\t\tJEMALLOC_VALGRIND_MAKE_MEM_DEFINED(ret, size);\n\t\t\tfor (i = 0; i < size / sizeof(size_t); i++)\n\t\t\t\tassert(p[i] == 0);\n\t\t}\n\t}\n\treturn (ret);\n}\n\n/*\n * If the caller specifies (!*zero), it is still possible to receive zeroed\n * memory, in which case *zero is toggled to true.  arena_chunk_alloc() takes\n * advantage of this to avoid demanding zeroed chunks, but taking advantage of\n * them if they are returned.\n */\nstatic void *\nchunk_alloc_core(arena_t *arena, void *new_addr, size_t size, size_t alignment,\n    bool *zero, bool *commit, dss_prec_t dss_prec)\n{\n\tvoid *ret;\n\tchunk_hooks_t chunk_hooks = CHUNK_HOOKS_INITIALIZER;\n\n\tassert(size != 0);\n\tassert((size & chunksize_mask) == 0);\n\tassert(alignment != 0);\n\tassert((alignment & chunksize_mask) == 0);\n\n\t/* Retained. */\n\tif ((ret = chunk_recycle(arena, &chunk_hooks,\n\t    &arena->chunks_szad_retained, &arena->chunks_ad_retained, false,\n\t    new_addr, size, alignment, zero, commit, true)) != NULL)\n\t\treturn (ret);\n\n\t/* \"primary\" dss. */\n\tif (have_dss && dss_prec == dss_prec_primary && (ret =\n\t    chunk_alloc_dss(arena, new_addr, size, alignment, zero, commit)) !=\n\t    NULL)\n\t\treturn (ret);\n\t/*\n\t * mmap.  Requesting an address is not implemented for\n\t * chunk_alloc_mmap(), so only call it if (new_addr == NULL).\n\t */\n\tif (new_addr == NULL && (ret = chunk_alloc_mmap(size, alignment, zero,\n\t    commit)) != NULL)\n\t\treturn (ret);\n\t/* \"secondary\" dss. */\n\tif (have_dss && dss_prec == dss_prec_secondary && (ret =\n\t    chunk_alloc_dss(arena, new_addr, size, alignment, zero, commit)) !=\n\t    NULL)\n\t\treturn (ret);\n\n\t/* All strategies for allocation failed. */\n\treturn (NULL);\n}\n\nvoid *\nchunk_alloc_base(size_t size)\n{\n\tvoid *ret;\n\tbool zero, commit;\n\n\t/*\n\t * Directly call chunk_alloc_mmap() rather than chunk_alloc_core()\n\t * because it's critical that chunk_alloc_base() return untouched\n\t * demand-zeroed virtual memory.\n\t */\n\tzero = true;\n\tcommit = true;\n\tret = chunk_alloc_mmap(size, chunksize, &zero, &commit);\n\tif (ret == NULL)\n\t\treturn (NULL);\n\tif (config_valgrind)\n\t\tJEMALLOC_VALGRIND_MAKE_MEM_UNDEFINED(ret, size);\n\n\treturn (ret);\n}\n\nvoid *\nchunk_alloc_cache(arena_t *arena, chunk_hooks_t *chunk_hooks, void *new_addr,\n    size_t size, size_t alignment, bool *zero, bool dalloc_node)\n{\n\tvoid *ret;\n\tbool commit;\n\n\tassert(size != 0);\n\tassert((size & chunksize_mask) == 0);\n\tassert(alignment != 0);\n\tassert((alignment & chunksize_mask) == 0);\n\n\tcommit = true;\n\tret = chunk_recycle(arena, chunk_hooks, &arena->chunks_szad_cached,\n\t    &arena->chunks_ad_cached, true, new_addr, size, alignment, zero,\n\t    &commit, dalloc_node);\n\tif (ret == NULL)\n\t\treturn (NULL);\n\tassert(commit);\n\tif (config_valgrind)\n\t\tJEMALLOC_VALGRIND_MAKE_MEM_UNDEFINED(ret, size);\n\treturn (ret);\n}\n\nstatic arena_t *\nchunk_arena_get(unsigned arena_ind)\n{\n\tarena_t *arena;\n\n\t/* Dodge tsd for a0 in order to avoid bootstrapping issues. */\n\tarena = (arena_ind == 0) ? a0get() : arena_get(tsd_fetch(), arena_ind,\n\t     false, true);\n\t/*\n\t * The arena we're allocating on behalf of must have been initialized\n\t * already.\n\t */\n\tassert(arena != NULL);\n\treturn (arena);\n}\n\nstatic void *\nchunk_alloc_default(void *new_addr, size_t size, size_t alignment, bool *zero,\n    bool *commit, unsigned arena_ind)\n{\n\tvoid *ret;\n\tarena_t *arena;\n\n\tarena = chunk_arena_get(arena_ind);\n\tret = chunk_alloc_core(arena, new_addr, size, alignment, zero,\n\t    commit, arena->dss_prec);\n\tif (ret == NULL)\n\t\treturn (NULL);\n\tif (config_valgrind)\n\t\tJEMALLOC_VALGRIND_MAKE_MEM_UNDEFINED(ret, size);\n\n\treturn (ret);\n}\n\nvoid *\nchunk_alloc_wrapper(arena_t *arena, chunk_hooks_t *chunk_hooks, void *new_addr,\n    size_t size, size_t alignment, bool *zero, bool *commit)\n{\n\tvoid *ret;\n\n\tchunk_hooks_assure_initialized(arena, chunk_hooks);\n\tret = chunk_hooks->alloc(new_addr, size, alignment, zero, commit,\n\t    arena->ind);\n\tif (ret == NULL)\n\t\treturn (NULL);\n\tif (config_valgrind && chunk_hooks->alloc != chunk_alloc_default)\n\t\tJEMALLOC_VALGRIND_MAKE_MEM_UNDEFINED(ret, chunksize);\n\treturn (ret);\n}\n\nstatic void\nchunk_record(arena_t *arena, chunk_hooks_t *chunk_hooks,\n    extent_tree_t *chunks_szad, extent_tree_t *chunks_ad, bool cache,\n    void *chunk, size_t size, bool zeroed, bool committed)\n{\n\tbool unzeroed;\n\textent_node_t *node, *prev;\n\textent_node_t key;\n\n\tassert(!cache || !zeroed);\n\tunzeroed = cache || !zeroed;\n\tJEMALLOC_VALGRIND_MAKE_MEM_NOACCESS(chunk, size);\n\n\tmalloc_mutex_lock(&arena->chunks_mtx);\n\tchunk_hooks_assure_initialized_locked(arena, chunk_hooks);\n\textent_node_init(&key, arena, (void *)((uintptr_t)chunk + size), 0,\n\t    false, false);\n\tnode = extent_tree_ad_nsearch(chunks_ad, &key);\n\t/* Try to coalesce forward. */\n\tif (node != NULL && extent_node_addr_get(node) ==\n\t    extent_node_addr_get(&key) && extent_node_committed_get(node) ==\n\t    committed && !chunk_hooks->merge(chunk, size,\n\t    extent_node_addr_get(node), extent_node_size_get(node), false,\n\t    arena->ind)) {\n\t\t/*\n\t\t * Coalesce chunk with the following address range.  This does\n\t\t * not change the position within chunks_ad, so only\n\t\t * remove/insert from/into chunks_szad.\n\t\t */\n\t\textent_tree_szad_remove(chunks_szad, node);\n\t\tarena_chunk_cache_maybe_remove(arena, node, cache);\n\t\textent_node_addr_set(node, chunk);\n\t\textent_node_size_set(node, size + extent_node_size_get(node));\n\t\textent_node_zeroed_set(node, extent_node_zeroed_get(node) &&\n\t\t    !unzeroed);\n\t\textent_tree_szad_insert(chunks_szad, node);\n\t\tarena_chunk_cache_maybe_insert(arena, node, cache);\n\t} else {\n\t\t/* Coalescing forward failed, so insert a new node. */\n\t\tnode = arena_node_alloc(arena);\n\t\tif (node == NULL) {\n\t\t\t/*\n\t\t\t * Node allocation failed, which is an exceedingly\n\t\t\t * unlikely failure.  Leak chunk after making sure its\n\t\t\t * pages have already been purged, so that this is only\n\t\t\t * a virtual memory leak.\n\t\t\t */\n\t\t\tif (cache) {\n\t\t\t\tchunk_purge_wrapper(arena, chunk_hooks, chunk,\n\t\t\t\t    size, 0, size);\n\t\t\t}\n\t\t\tgoto label_return;\n\t\t}\n\t\textent_node_init(node, arena, chunk, size, !unzeroed,\n\t\t    committed);\n\t\textent_tree_ad_insert(chunks_ad, node);\n\t\textent_tree_szad_insert(chunks_szad, node);\n\t\tarena_chunk_cache_maybe_insert(arena, node, cache);\n\t}\n\n\t/* Try to coalesce backward. */\n\tprev = extent_tree_ad_prev(chunks_ad, node);\n\tif (prev != NULL && (void *)((uintptr_t)extent_node_addr_get(prev) +\n\t    extent_node_size_get(prev)) == chunk &&\n\t    extent_node_committed_get(prev) == committed &&\n\t    !chunk_hooks->merge(extent_node_addr_get(prev),\n\t    extent_node_size_get(prev), chunk, size, false, arena->ind)) {\n\t\t/*\n\t\t * Coalesce chunk with the previous address range.  This does\n\t\t * not change the position within chunks_ad, so only\n\t\t * remove/insert node from/into chunks_szad.\n\t\t */\n\t\textent_tree_szad_remove(chunks_szad, prev);\n\t\textent_tree_ad_remove(chunks_ad, prev);\n\t\tarena_chunk_cache_maybe_remove(arena, prev, cache);\n\t\textent_tree_szad_remove(chunks_szad, node);\n\t\tarena_chunk_cache_maybe_remove(arena, node, cache);\n\t\textent_node_addr_set(node, extent_node_addr_get(prev));\n\t\textent_node_size_set(node, extent_node_size_get(prev) +\n\t\t    extent_node_size_get(node));\n\t\textent_node_zeroed_set(node, extent_node_zeroed_get(prev) &&\n\t\t    extent_node_zeroed_get(node));\n\t\textent_tree_szad_insert(chunks_szad, node);\n\t\tarena_chunk_cache_maybe_insert(arena, node, cache);\n\n\t\tarena_node_dalloc(arena, prev);\n\t}\n\nlabel_return:\n\tmalloc_mutex_unlock(&arena->chunks_mtx);\n}\n\nvoid\nchunk_dalloc_cache(arena_t *arena, chunk_hooks_t *chunk_hooks, void *chunk,\n    size_t size, bool committed)\n{\n\n\tassert(chunk != NULL);\n\tassert(CHUNK_ADDR2BASE(chunk) == chunk);\n\tassert(size != 0);\n\tassert((size & chunksize_mask) == 0);\n\n\tchunk_record(arena, chunk_hooks, &arena->chunks_szad_cached,\n\t    &arena->chunks_ad_cached, true, chunk, size, false, committed);\n\tarena_maybe_purge(arena);\n}\n\nvoid\nchunk_dalloc_arena(arena_t *arena, chunk_hooks_t *chunk_hooks, void *chunk,\n    size_t size, bool zeroed, bool committed)\n{\n\n\tassert(chunk != NULL);\n\tassert(CHUNK_ADDR2BASE(chunk) == chunk);\n\tassert(size != 0);\n\tassert((size & chunksize_mask) == 0);\n\n\tchunk_hooks_assure_initialized(arena, chunk_hooks);\n\t/* Try to deallocate. */\n\tif (!chunk_hooks->dalloc(chunk, size, committed, arena->ind))\n\t\treturn;\n\t/* Try to decommit; purge if that fails. */\n\tif (committed) {\n\t\tcommitted = chunk_hooks->decommit(chunk, size, 0, size,\n\t\t    arena->ind);\n\t}\n\tzeroed = !committed || !chunk_hooks->purge(chunk, size, 0, size,\n\t    arena->ind);\n\tchunk_record(arena, chunk_hooks, &arena->chunks_szad_retained,\n\t    &arena->chunks_ad_retained, false, chunk, size, zeroed, committed);\n}\n\nstatic bool\nchunk_dalloc_default(void *chunk, size_t size, bool committed,\n    unsigned arena_ind)\n{\n\n\tif (!have_dss || !chunk_in_dss(chunk))\n\t\treturn (chunk_dalloc_mmap(chunk, size));\n\treturn (true);\n}\n\nvoid\nchunk_dalloc_wrapper(arena_t *arena, chunk_hooks_t *chunk_hooks, void *chunk,\n    size_t size, bool committed)\n{\n\n\tchunk_hooks_assure_initialized(arena, chunk_hooks);\n\tchunk_hooks->dalloc(chunk, size, committed, arena->ind);\n\tif (config_valgrind && chunk_hooks->dalloc != chunk_dalloc_default)\n\t\tJEMALLOC_VALGRIND_MAKE_MEM_NOACCESS(chunk, size);\n}\n\nstatic bool\nchunk_commit_default(void *chunk, size_t size, size_t offset, size_t length,\n    unsigned arena_ind)\n{\n\n\treturn (pages_commit((void *)((uintptr_t)chunk + (uintptr_t)offset),\n\t    length));\n}\n\nstatic bool\nchunk_decommit_default(void *chunk, size_t size, size_t offset, size_t length,\n    unsigned arena_ind)\n{\n\n\treturn (pages_decommit((void *)((uintptr_t)chunk + (uintptr_t)offset),\n\t    length));\n}\n\nbool\nchunk_purge_arena(arena_t *arena, void *chunk, size_t offset, size_t length)\n{\n\n\tassert(chunk != NULL);\n\tassert(CHUNK_ADDR2BASE(chunk) == chunk);\n\tassert((offset & PAGE_MASK) == 0);\n\tassert(length != 0);\n\tassert((length & PAGE_MASK) == 0);\n\n\treturn (pages_purge((void *)((uintptr_t)chunk + (uintptr_t)offset),\n\t    length));\n}\n\nstatic bool\nchunk_purge_default(void *chunk, size_t size, size_t offset, size_t length,\n    unsigned arena_ind)\n{\n\n\treturn (chunk_purge_arena(chunk_arena_get(arena_ind), chunk, offset,\n\t    length));\n}\n\nbool\nchunk_purge_wrapper(arena_t *arena, chunk_hooks_t *chunk_hooks, void *chunk,\n    size_t size, size_t offset, size_t length)\n{\n\n\tchunk_hooks_assure_initialized(arena, chunk_hooks);\n\treturn (chunk_hooks->purge(chunk, size, offset, length, arena->ind));\n}\n\nstatic bool\nchunk_split_default(void *chunk, size_t size, size_t size_a, size_t size_b,\n    bool committed, unsigned arena_ind)\n{\n\n\tif (!maps_coalesce)\n\t\treturn (true);\n\treturn (false);\n}\n\nstatic bool\nchunk_merge_default(void *chunk_a, size_t size_a, void *chunk_b, size_t size_b,\n    bool committed, unsigned arena_ind)\n{\n\n\tif (!maps_coalesce)\n\t\treturn (true);\n\tif (have_dss && chunk_in_dss(chunk_a) != chunk_in_dss(chunk_b))\n\t\treturn (true);\n\n\treturn (false);\n}\n\nstatic rtree_node_elm_t *\nchunks_rtree_node_alloc(size_t nelms)\n{\n\n\treturn ((rtree_node_elm_t *)base_alloc(nelms *\n\t    sizeof(rtree_node_elm_t)));\n}\n\nbool\nchunk_boot(void)\n{\n#ifdef _WIN32\n\tSYSTEM_INFO info;\n\tGetSystemInfo(&info);\n\n\t/*\n\t * Verify actual page size is equal to or an integral multiple of\n\t * configured page size.\n\t */\n\tif (info.dwPageSize & ((1U << LG_PAGE) - 1))\n\t\treturn (true);\n\n\t/*\n\t * Configure chunksize (if not set) to match granularity (usually 64K),\n\t * so pages_map will always take fast path.\n\t */\n\tif (!opt_lg_chunk) {\n\t\topt_lg_chunk = jemalloc_ffs((int)info.dwAllocationGranularity)\n\t\t    - 1;\n\t}\n#else\n\tif (!opt_lg_chunk)\n\t\topt_lg_chunk = LG_CHUNK_DEFAULT;\n#endif\n\n\t/* Set variables according to the value of opt_lg_chunk. */\n\tchunksize = (ZU(1) << opt_lg_chunk);\n\tassert(chunksize >= PAGE);\n\tchunksize_mask = chunksize - 1;\n\tchunk_npages = (chunksize >> LG_PAGE);\n\n\tif (have_dss && chunk_dss_boot())\n\t\treturn (true);\n\tif (rtree_new(&chunks_rtree, (ZU(1) << (LG_SIZEOF_PTR+3)) -\n\t    opt_lg_chunk, chunks_rtree_node_alloc, NULL))\n\t\treturn (true);\n\n\treturn (false);\n}\n\nvoid\nchunk_prefork(void)\n{\n\n\tchunk_dss_prefork();\n}\n\nvoid\nchunk_postfork_parent(void)\n{\n\n\tchunk_dss_postfork_parent();\n}\n\nvoid\nchunk_postfork_child(void)\n{\n\n\tchunk_dss_postfork_child();\n}\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.8/deps/jemalloc/src/chunk_dss.c",
    "content": "#define\tJEMALLOC_CHUNK_DSS_C_\n#include \"jemalloc/internal/jemalloc_internal.h\"\n/******************************************************************************/\n/* Data. */\n\nconst char\t*dss_prec_names[] = {\n\t\"disabled\",\n\t\"primary\",\n\t\"secondary\",\n\t\"N/A\"\n};\n\n/* Current dss precedence default, used when creating new arenas. */\nstatic dss_prec_t\tdss_prec_default = DSS_PREC_DEFAULT;\n\n/*\n * Protects sbrk() calls.  This avoids malloc races among threads, though it\n * does not protect against races with threads that call sbrk() directly.\n */\nstatic malloc_mutex_t\tdss_mtx;\n\n/* Base address of the DSS. */\nstatic void\t\t*dss_base;\n/* Current end of the DSS, or ((void *)-1) if the DSS is exhausted. */\nstatic void\t\t*dss_prev;\n/* Current upper limit on DSS addresses. */\nstatic void\t\t*dss_max;\n\n/******************************************************************************/\n\nstatic void *\nchunk_dss_sbrk(intptr_t increment)\n{\n\n#ifdef JEMALLOC_DSS\n\treturn (sbrk(increment));\n#else\n\tnot_implemented();\n\treturn (NULL);\n#endif\n}\n\ndss_prec_t\nchunk_dss_prec_get(void)\n{\n\tdss_prec_t ret;\n\n\tif (!have_dss)\n\t\treturn (dss_prec_disabled);\n\tmalloc_mutex_lock(&dss_mtx);\n\tret = dss_prec_default;\n\tmalloc_mutex_unlock(&dss_mtx);\n\treturn (ret);\n}\n\nbool\nchunk_dss_prec_set(dss_prec_t dss_prec)\n{\n\n\tif (!have_dss)\n\t\treturn (dss_prec != dss_prec_disabled);\n\tmalloc_mutex_lock(&dss_mtx);\n\tdss_prec_default = dss_prec;\n\tmalloc_mutex_unlock(&dss_mtx);\n\treturn (false);\n}\n\nvoid *\nchunk_alloc_dss(arena_t *arena, void *new_addr, size_t size, size_t alignment,\n    bool *zero, bool *commit)\n{\n\tcassert(have_dss);\n\tassert(size > 0 && (size & chunksize_mask) == 0);\n\tassert(alignment > 0 && (alignment & chunksize_mask) == 0);\n\n\t/*\n\t * sbrk() uses a signed increment argument, so take care not to\n\t * interpret a huge allocation request as a negative increment.\n\t */\n\tif ((intptr_t)size < 0)\n\t\treturn (NULL);\n\n\tmalloc_mutex_lock(&dss_mtx);\n\tif (dss_prev != (void *)-1) {\n\n\t\t/*\n\t\t * The loop is necessary to recover from races with other\n\t\t * threads that are using the DSS for something other than\n\t\t * malloc.\n\t\t */\n\t\tdo {\n\t\t\tvoid *ret, *cpad, *dss_next;\n\t\t\tsize_t gap_size, cpad_size;\n\t\t\tintptr_t incr;\n\t\t\t/* Avoid an unnecessary system call. */\n\t\t\tif (new_addr != NULL && dss_max != new_addr)\n\t\t\t\tbreak;\n\n\t\t\t/* Get the current end of the DSS. */\n\t\t\tdss_max = chunk_dss_sbrk(0);\n\n\t\t\t/* Make sure the earlier condition still holds. */\n\t\t\tif (new_addr != NULL && dss_max != new_addr)\n\t\t\t\tbreak;\n\n\t\t\t/*\n\t\t\t * Calculate how much padding is necessary to\n\t\t\t * chunk-align the end of the DSS.\n\t\t\t */\n\t\t\tgap_size = (chunksize - CHUNK_ADDR2OFFSET(dss_max)) &\n\t\t\t    chunksize_mask;\n\t\t\t/*\n\t\t\t * Compute how much chunk-aligned pad space (if any) is\n\t\t\t * necessary to satisfy alignment.  This space can be\n\t\t\t * recycled for later use.\n\t\t\t */\n\t\t\tcpad = (void *)((uintptr_t)dss_max + gap_size);\n\t\t\tret = (void *)ALIGNMENT_CEILING((uintptr_t)dss_max,\n\t\t\t    alignment);\n\t\t\tcpad_size = (uintptr_t)ret - (uintptr_t)cpad;\n\t\t\tdss_next = (void *)((uintptr_t)ret + size);\n\t\t\tif ((uintptr_t)ret < (uintptr_t)dss_max ||\n\t\t\t    (uintptr_t)dss_next < (uintptr_t)dss_max) {\n\t\t\t\t/* Wrap-around. */\n\t\t\t\tmalloc_mutex_unlock(&dss_mtx);\n\t\t\t\treturn (NULL);\n\t\t\t}\n\t\t\tincr = gap_size + cpad_size + size;\n\t\t\tdss_prev = chunk_dss_sbrk(incr);\n\t\t\tif (dss_prev == dss_max) {\n\t\t\t\t/* Success. */\n\t\t\t\tdss_max = dss_next;\n\t\t\t\tmalloc_mutex_unlock(&dss_mtx);\n\t\t\t\tif (cpad_size != 0) {\n\t\t\t\t\tchunk_hooks_t chunk_hooks =\n\t\t\t\t\t    CHUNK_HOOKS_INITIALIZER;\n\t\t\t\t\tchunk_dalloc_wrapper(arena,\n\t\t\t\t\t    &chunk_hooks, cpad, cpad_size,\n\t\t\t\t\t    true);\n\t\t\t\t}\n\t\t\t\tif (*zero) {\n\t\t\t\t\tJEMALLOC_VALGRIND_MAKE_MEM_UNDEFINED(\n\t\t\t\t\t    ret, size);\n\t\t\t\t\tmemset(ret, 0, size);\n\t\t\t\t}\n\t\t\t\tif (!*commit)\n\t\t\t\t\t*commit = pages_decommit(ret, size);\n\t\t\t\treturn (ret);\n\t\t\t}\n\t\t} while (dss_prev != (void *)-1);\n\t}\n\tmalloc_mutex_unlock(&dss_mtx);\n\n\treturn (NULL);\n}\n\nbool\nchunk_in_dss(void *chunk)\n{\n\tbool ret;\n\n\tcassert(have_dss);\n\n\tmalloc_mutex_lock(&dss_mtx);\n\tif ((uintptr_t)chunk >= (uintptr_t)dss_base\n\t    && (uintptr_t)chunk < (uintptr_t)dss_max)\n\t\tret = true;\n\telse\n\t\tret = false;\n\tmalloc_mutex_unlock(&dss_mtx);\n\n\treturn (ret);\n}\n\nbool\nchunk_dss_boot(void)\n{\n\n\tcassert(have_dss);\n\n\tif (malloc_mutex_init(&dss_mtx))\n\t\treturn (true);\n\tdss_base = chunk_dss_sbrk(0);\n\tdss_prev = dss_base;\n\tdss_max = dss_base;\n\n\treturn (false);\n}\n\nvoid\nchunk_dss_prefork(void)\n{\n\n\tif (have_dss)\n\t\tmalloc_mutex_prefork(&dss_mtx);\n}\n\nvoid\nchunk_dss_postfork_parent(void)\n{\n\n\tif (have_dss)\n\t\tmalloc_mutex_postfork_parent(&dss_mtx);\n}\n\nvoid\nchunk_dss_postfork_child(void)\n{\n\n\tif (have_dss)\n\t\tmalloc_mutex_postfork_child(&dss_mtx);\n}\n\n/******************************************************************************/\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.8/deps/jemalloc/src/chunk_mmap.c",
    "content": "#define\tJEMALLOC_CHUNK_MMAP_C_\n#include \"jemalloc/internal/jemalloc_internal.h\"\n\n/******************************************************************************/\n\nstatic void *\nchunk_alloc_mmap_slow(size_t size, size_t alignment, bool *zero, bool *commit)\n{\n\tvoid *ret;\n\tsize_t alloc_size;\n\n\talloc_size = size + alignment - PAGE;\n\t/* Beware size_t wrap-around. */\n\tif (alloc_size < size)\n\t\treturn (NULL);\n\tdo {\n\t\tvoid *pages;\n\t\tsize_t leadsize;\n\t\tpages = pages_map(NULL, alloc_size);\n\t\tif (pages == NULL)\n\t\t\treturn (NULL);\n\t\tleadsize = ALIGNMENT_CEILING((uintptr_t)pages, alignment) -\n\t\t    (uintptr_t)pages;\n\t\tret = pages_trim(pages, alloc_size, leadsize, size);\n\t} while (ret == NULL);\n\n\tassert(ret != NULL);\n\t*zero = true;\n\tif (!*commit)\n\t\t*commit = pages_decommit(ret, size);\n\treturn (ret);\n}\n\nvoid *\nchunk_alloc_mmap(size_t size, size_t alignment, bool *zero, bool *commit)\n{\n\tvoid *ret;\n\tsize_t offset;\n\n\t/*\n\t * Ideally, there would be a way to specify alignment to mmap() (like\n\t * NetBSD has), but in the absence of such a feature, we have to work\n\t * hard to efficiently create aligned mappings.  The reliable, but\n\t * slow method is to create a mapping that is over-sized, then trim the\n\t * excess.  However, that always results in one or two calls to\n\t * pages_unmap().\n\t *\n\t * Optimistically try mapping precisely the right amount before falling\n\t * back to the slow method, with the expectation that the optimistic\n\t * approach works most of the time.\n\t */\n\n\tassert(alignment != 0);\n\tassert((alignment & chunksize_mask) == 0);\n\n\tret = pages_map(NULL, size);\n\tif (ret == NULL)\n\t\treturn (NULL);\n\toffset = ALIGNMENT_ADDR2OFFSET(ret, alignment);\n\tif (offset != 0) {\n\t\tpages_unmap(ret, size);\n\t\treturn (chunk_alloc_mmap_slow(size, alignment, zero, commit));\n\t}\n\n\tassert(ret != NULL);\n\t*zero = true;\n\tif (!*commit)\n\t\t*commit = pages_decommit(ret, size);\n\treturn (ret);\n}\n\nbool\nchunk_dalloc_mmap(void *chunk, size_t size)\n{\n\n\tif (config_munmap)\n\t\tpages_unmap(chunk, size);\n\n\treturn (!config_munmap);\n}\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.8/deps/jemalloc/src/ckh.c",
    "content": "/*\n *******************************************************************************\n * Implementation of (2^1+,2) cuckoo hashing, where 2^1+ indicates that each\n * hash bucket contains 2^n cells, for n >= 1, and 2 indicates that two hash\n * functions are employed.  The original cuckoo hashing algorithm was described\n * in:\n *\n *   Pagh, R., F.F. Rodler (2004) Cuckoo Hashing.  Journal of Algorithms\n *     51(2):122-144.\n *\n * Generalization of cuckoo hashing was discussed in:\n *\n *   Erlingsson, U., M. Manasse, F. McSherry (2006) A cool and practical\n *     alternative to traditional hash tables.  In Proceedings of the 7th\n *     Workshop on Distributed Data and Structures (WDAS'06), Santa Clara, CA,\n *     January 2006.\n *\n * This implementation uses precisely two hash functions because that is the\n * fewest that can work, and supporting multiple hashes is an implementation\n * burden.  Here is a reproduction of Figure 1 from Erlingsson et al. (2006)\n * that shows approximate expected maximum load factors for various\n * configurations:\n *\n *           |         #cells/bucket         |\n *   #hashes |   1   |   2   |   4   |   8   |\n *   --------+-------+-------+-------+-------+\n *         1 | 0.006 | 0.006 | 0.03  | 0.12  |\n *         2 | 0.49  | 0.86  |>0.93< |>0.96< |\n *         3 | 0.91  | 0.97  | 0.98  | 0.999 |\n *         4 | 0.97  | 0.99  | 0.999 |       |\n *\n * The number of cells per bucket is chosen such that a bucket fits in one cache\n * line.  So, on 32- and 64-bit systems, we use (8,2) and (4,2) cuckoo hashing,\n * respectively.\n *\n ******************************************************************************/\n#define\tJEMALLOC_CKH_C_\n#include \"jemalloc/internal/jemalloc_internal.h\"\n\n/******************************************************************************/\n/* Function prototypes for non-inline static functions. */\n\nstatic bool\tckh_grow(tsd_t *tsd, ckh_t *ckh);\nstatic void\tckh_shrink(tsd_t *tsd, ckh_t *ckh);\n\n/******************************************************************************/\n\n/*\n * Search bucket for key and return the cell number if found; SIZE_T_MAX\n * otherwise.\n */\nJEMALLOC_INLINE_C size_t\nckh_bucket_search(ckh_t *ckh, size_t bucket, const void *key)\n{\n\tckhc_t *cell;\n\tunsigned i;\n\n\tfor (i = 0; i < (ZU(1) << LG_CKH_BUCKET_CELLS); i++) {\n\t\tcell = &ckh->tab[(bucket << LG_CKH_BUCKET_CELLS) + i];\n\t\tif (cell->key != NULL && ckh->keycomp(key, cell->key))\n\t\t\treturn ((bucket << LG_CKH_BUCKET_CELLS) + i);\n\t}\n\n\treturn (SIZE_T_MAX);\n}\n\n/*\n * Search table for key and return cell number if found; SIZE_T_MAX otherwise.\n */\nJEMALLOC_INLINE_C size_t\nckh_isearch(ckh_t *ckh, const void *key)\n{\n\tsize_t hashes[2], bucket, cell;\n\n\tassert(ckh != NULL);\n\n\tckh->hash(key, hashes);\n\n\t/* Search primary bucket. */\n\tbucket = hashes[0] & ((ZU(1) << ckh->lg_curbuckets) - 1);\n\tcell = ckh_bucket_search(ckh, bucket, key);\n\tif (cell != SIZE_T_MAX)\n\t\treturn (cell);\n\n\t/* Search secondary bucket. */\n\tbucket = hashes[1] & ((ZU(1) << ckh->lg_curbuckets) - 1);\n\tcell = ckh_bucket_search(ckh, bucket, key);\n\treturn (cell);\n}\n\nJEMALLOC_INLINE_C bool\nckh_try_bucket_insert(ckh_t *ckh, size_t bucket, const void *key,\n    const void *data)\n{\n\tckhc_t *cell;\n\tunsigned offset, i;\n\n\t/*\n\t * Cycle through the cells in the bucket, starting at a random position.\n\t * The randomness avoids worst-case search overhead as buckets fill up.\n\t */\n\tprng32(offset, LG_CKH_BUCKET_CELLS, ckh->prng_state, CKH_A, CKH_C);\n\tfor (i = 0; i < (ZU(1) << LG_CKH_BUCKET_CELLS); i++) {\n\t\tcell = &ckh->tab[(bucket << LG_CKH_BUCKET_CELLS) +\n\t\t    ((i + offset) & ((ZU(1) << LG_CKH_BUCKET_CELLS) - 1))];\n\t\tif (cell->key == NULL) {\n\t\t\tcell->key = key;\n\t\t\tcell->data = data;\n\t\t\tckh->count++;\n\t\t\treturn (false);\n\t\t}\n\t}\n\n\treturn (true);\n}\n\n/*\n * No space is available in bucket.  Randomly evict an item, then try to find an\n * alternate location for that item.  Iteratively repeat this\n * eviction/relocation procedure until either success or detection of an\n * eviction/relocation bucket cycle.\n */\nJEMALLOC_INLINE_C bool\nckh_evict_reloc_insert(ckh_t *ckh, size_t argbucket, void const **argkey,\n    void const **argdata)\n{\n\tconst void *key, *data, *tkey, *tdata;\n\tckhc_t *cell;\n\tsize_t hashes[2], bucket, tbucket;\n\tunsigned i;\n\n\tbucket = argbucket;\n\tkey = *argkey;\n\tdata = *argdata;\n\twhile (true) {\n\t\t/*\n\t\t * Choose a random item within the bucket to evict.  This is\n\t\t * critical to correct function, because without (eventually)\n\t\t * evicting all items within a bucket during iteration, it\n\t\t * would be possible to get stuck in an infinite loop if there\n\t\t * were an item for which both hashes indicated the same\n\t\t * bucket.\n\t\t */\n\t\tprng32(i, LG_CKH_BUCKET_CELLS, ckh->prng_state, CKH_A, CKH_C);\n\t\tcell = &ckh->tab[(bucket << LG_CKH_BUCKET_CELLS) + i];\n\t\tassert(cell->key != NULL);\n\n\t\t/* Swap cell->{key,data} and {key,data} (evict). */\n\t\ttkey = cell->key; tdata = cell->data;\n\t\tcell->key = key; cell->data = data;\n\t\tkey = tkey; data = tdata;\n\n#ifdef CKH_COUNT\n\t\tckh->nrelocs++;\n#endif\n\n\t\t/* Find the alternate bucket for the evicted item. */\n\t\tckh->hash(key, hashes);\n\t\ttbucket = hashes[1] & ((ZU(1) << ckh->lg_curbuckets) - 1);\n\t\tif (tbucket == bucket) {\n\t\t\ttbucket = hashes[0] & ((ZU(1) << ckh->lg_curbuckets)\n\t\t\t    - 1);\n\t\t\t/*\n\t\t\t * It may be that (tbucket == bucket) still, if the\n\t\t\t * item's hashes both indicate this bucket.  However,\n\t\t\t * we are guaranteed to eventually escape this bucket\n\t\t\t * during iteration, assuming pseudo-random item\n\t\t\t * selection (true randomness would make infinite\n\t\t\t * looping a remote possibility).  The reason we can\n\t\t\t * never get trapped forever is that there are two\n\t\t\t * cases:\n\t\t\t *\n\t\t\t * 1) This bucket == argbucket, so we will quickly\n\t\t\t *    detect an eviction cycle and terminate.\n\t\t\t * 2) An item was evicted to this bucket from another,\n\t\t\t *    which means that at least one item in this bucket\n\t\t\t *    has hashes that indicate distinct buckets.\n\t\t\t */\n\t\t}\n\t\t/* Check for a cycle. */\n\t\tif (tbucket == argbucket) {\n\t\t\t*argkey = key;\n\t\t\t*argdata = data;\n\t\t\treturn (true);\n\t\t}\n\n\t\tbucket = tbucket;\n\t\tif (!ckh_try_bucket_insert(ckh, bucket, key, data))\n\t\t\treturn (false);\n\t}\n}\n\nJEMALLOC_INLINE_C bool\nckh_try_insert(ckh_t *ckh, void const**argkey, void const**argdata)\n{\n\tsize_t hashes[2], bucket;\n\tconst void *key = *argkey;\n\tconst void *data = *argdata;\n\n\tckh->hash(key, hashes);\n\n\t/* Try to insert in primary bucket. */\n\tbucket = hashes[0] & ((ZU(1) << ckh->lg_curbuckets) - 1);\n\tif (!ckh_try_bucket_insert(ckh, bucket, key, data))\n\t\treturn (false);\n\n\t/* Try to insert in secondary bucket. */\n\tbucket = hashes[1] & ((ZU(1) << ckh->lg_curbuckets) - 1);\n\tif (!ckh_try_bucket_insert(ckh, bucket, key, data))\n\t\treturn (false);\n\n\t/*\n\t * Try to find a place for this item via iterative eviction/relocation.\n\t */\n\treturn (ckh_evict_reloc_insert(ckh, bucket, argkey, argdata));\n}\n\n/*\n * Try to rebuild the hash table from scratch by inserting all items from the\n * old table into the new.\n */\nJEMALLOC_INLINE_C bool\nckh_rebuild(ckh_t *ckh, ckhc_t *aTab)\n{\n\tsize_t count, i, nins;\n\tconst void *key, *data;\n\n\tcount = ckh->count;\n\tckh->count = 0;\n\tfor (i = nins = 0; nins < count; i++) {\n\t\tif (aTab[i].key != NULL) {\n\t\t\tkey = aTab[i].key;\n\t\t\tdata = aTab[i].data;\n\t\t\tif (ckh_try_insert(ckh, &key, &data)) {\n\t\t\t\tckh->count = count;\n\t\t\t\treturn (true);\n\t\t\t}\n\t\t\tnins++;\n\t\t}\n\t}\n\n\treturn (false);\n}\n\nstatic bool\nckh_grow(tsd_t *tsd, ckh_t *ckh)\n{\n\tbool ret;\n\tckhc_t *tab, *ttab;\n\tsize_t lg_curcells;\n\tunsigned lg_prevbuckets;\n\n#ifdef CKH_COUNT\n\tckh->ngrows++;\n#endif\n\n\t/*\n\t * It is possible (though unlikely, given well behaved hashes) that the\n\t * table will have to be doubled more than once in order to create a\n\t * usable table.\n\t */\n\tlg_prevbuckets = ckh->lg_curbuckets;\n\tlg_curcells = ckh->lg_curbuckets + LG_CKH_BUCKET_CELLS;\n\twhile (true) {\n\t\tsize_t usize;\n\n\t\tlg_curcells++;\n\t\tusize = sa2u(sizeof(ckhc_t) << lg_curcells, CACHELINE);\n\t\tif (usize == 0) {\n\t\t\tret = true;\n\t\t\tgoto label_return;\n\t\t}\n\t\ttab = (ckhc_t *)ipallocztm(tsd, usize, CACHELINE, true, NULL,\n\t\t    true, NULL);\n\t\tif (tab == NULL) {\n\t\t\tret = true;\n\t\t\tgoto label_return;\n\t\t}\n\t\t/* Swap in new table. */\n\t\tttab = ckh->tab;\n\t\tckh->tab = tab;\n\t\ttab = ttab;\n\t\tckh->lg_curbuckets = lg_curcells - LG_CKH_BUCKET_CELLS;\n\n\t\tif (!ckh_rebuild(ckh, tab)) {\n\t\t\tidalloctm(tsd, tab, tcache_get(tsd, false), true);\n\t\t\tbreak;\n\t\t}\n\n\t\t/* Rebuilding failed, so back out partially rebuilt table. */\n\t\tidalloctm(tsd, ckh->tab, tcache_get(tsd, false), true);\n\t\tckh->tab = tab;\n\t\tckh->lg_curbuckets = lg_prevbuckets;\n\t}\n\n\tret = false;\nlabel_return:\n\treturn (ret);\n}\n\nstatic void\nckh_shrink(tsd_t *tsd, ckh_t *ckh)\n{\n\tckhc_t *tab, *ttab;\n\tsize_t lg_curcells, usize;\n\tunsigned lg_prevbuckets;\n\n\t/*\n\t * It is possible (though unlikely, given well behaved hashes) that the\n\t * table rebuild will fail.\n\t */\n\tlg_prevbuckets = ckh->lg_curbuckets;\n\tlg_curcells = ckh->lg_curbuckets + LG_CKH_BUCKET_CELLS - 1;\n\tusize = sa2u(sizeof(ckhc_t) << lg_curcells, CACHELINE);\n\tif (usize == 0)\n\t\treturn;\n\ttab = (ckhc_t *)ipallocztm(tsd, usize, CACHELINE, true, NULL, true,\n\t    NULL);\n\tif (tab == NULL) {\n\t\t/*\n\t\t * An OOM error isn't worth propagating, since it doesn't\n\t\t * prevent this or future operations from proceeding.\n\t\t */\n\t\treturn;\n\t}\n\t/* Swap in new table. */\n\tttab = ckh->tab;\n\tckh->tab = tab;\n\ttab = ttab;\n\tckh->lg_curbuckets = lg_curcells - LG_CKH_BUCKET_CELLS;\n\n\tif (!ckh_rebuild(ckh, tab)) {\n\t\tidalloctm(tsd, tab, tcache_get(tsd, false), true);\n#ifdef CKH_COUNT\n\t\tckh->nshrinks++;\n#endif\n\t\treturn;\n\t}\n\n\t/* Rebuilding failed, so back out partially rebuilt table. */\n\tidalloctm(tsd, ckh->tab, tcache_get(tsd, false), true);\n\tckh->tab = tab;\n\tckh->lg_curbuckets = lg_prevbuckets;\n#ifdef CKH_COUNT\n\tckh->nshrinkfails++;\n#endif\n}\n\nbool\nckh_new(tsd_t *tsd, ckh_t *ckh, size_t minitems, ckh_hash_t *hash,\n    ckh_keycomp_t *keycomp)\n{\n\tbool ret;\n\tsize_t mincells, usize;\n\tunsigned lg_mincells;\n\n\tassert(minitems > 0);\n\tassert(hash != NULL);\n\tassert(keycomp != NULL);\n\n#ifdef CKH_COUNT\n\tckh->ngrows = 0;\n\tckh->nshrinks = 0;\n\tckh->nshrinkfails = 0;\n\tckh->ninserts = 0;\n\tckh->nrelocs = 0;\n#endif\n\tckh->prng_state = 42; /* Value doesn't really matter. */\n\tckh->count = 0;\n\n\t/*\n\t * Find the minimum power of 2 that is large enough to fit minitems\n\t * entries.  We are using (2+,2) cuckoo hashing, which has an expected\n\t * maximum load factor of at least ~0.86, so 0.75 is a conservative load\n\t * factor that will typically allow mincells items to fit without ever\n\t * growing the table.\n\t */\n\tassert(LG_CKH_BUCKET_CELLS > 0);\n\tmincells = ((minitems + (3 - (minitems % 3))) / 3) << 2;\n\tfor (lg_mincells = LG_CKH_BUCKET_CELLS;\n\t    (ZU(1) << lg_mincells) < mincells;\n\t    lg_mincells++)\n\t\t; /* Do nothing. */\n\tckh->lg_minbuckets = lg_mincells - LG_CKH_BUCKET_CELLS;\n\tckh->lg_curbuckets = lg_mincells - LG_CKH_BUCKET_CELLS;\n\tckh->hash = hash;\n\tckh->keycomp = keycomp;\n\n\tusize = sa2u(sizeof(ckhc_t) << lg_mincells, CACHELINE);\n\tif (usize == 0) {\n\t\tret = true;\n\t\tgoto label_return;\n\t}\n\tckh->tab = (ckhc_t *)ipallocztm(tsd, usize, CACHELINE, true, NULL, true,\n\t    NULL);\n\tif (ckh->tab == NULL) {\n\t\tret = true;\n\t\tgoto label_return;\n\t}\n\n\tret = false;\nlabel_return:\n\treturn (ret);\n}\n\nvoid\nckh_delete(tsd_t *tsd, ckh_t *ckh)\n{\n\n\tassert(ckh != NULL);\n\n#ifdef CKH_VERBOSE\n\tmalloc_printf(\n\t    \"%s(%p): ngrows: %\"FMTu64\", nshrinks: %\"FMTu64\",\"\n\t    \" nshrinkfails: %\"FMTu64\", ninserts: %\"FMTu64\",\"\n\t    \" nrelocs: %\"FMTu64\"\\n\", __func__, ckh,\n\t    (unsigned long long)ckh->ngrows,\n\t    (unsigned long long)ckh->nshrinks,\n\t    (unsigned long long)ckh->nshrinkfails,\n\t    (unsigned long long)ckh->ninserts,\n\t    (unsigned long long)ckh->nrelocs);\n#endif\n\n\tidalloctm(tsd, ckh->tab, tcache_get(tsd, false), true);\n\tif (config_debug)\n\t\tmemset(ckh, 0x5a, sizeof(ckh_t));\n}\n\nsize_t\nckh_count(ckh_t *ckh)\n{\n\n\tassert(ckh != NULL);\n\n\treturn (ckh->count);\n}\n\nbool\nckh_iter(ckh_t *ckh, size_t *tabind, void **key, void **data)\n{\n\tsize_t i, ncells;\n\n\tfor (i = *tabind, ncells = (ZU(1) << (ckh->lg_curbuckets +\n\t    LG_CKH_BUCKET_CELLS)); i < ncells; i++) {\n\t\tif (ckh->tab[i].key != NULL) {\n\t\t\tif (key != NULL)\n\t\t\t\t*key = (void *)ckh->tab[i].key;\n\t\t\tif (data != NULL)\n\t\t\t\t*data = (void *)ckh->tab[i].data;\n\t\t\t*tabind = i + 1;\n\t\t\treturn (false);\n\t\t}\n\t}\n\n\treturn (true);\n}\n\nbool\nckh_insert(tsd_t *tsd, ckh_t *ckh, const void *key, const void *data)\n{\n\tbool ret;\n\n\tassert(ckh != NULL);\n\tassert(ckh_search(ckh, key, NULL, NULL));\n\n#ifdef CKH_COUNT\n\tckh->ninserts++;\n#endif\n\n\twhile (ckh_try_insert(ckh, &key, &data)) {\n\t\tif (ckh_grow(tsd, ckh)) {\n\t\t\tret = true;\n\t\t\tgoto label_return;\n\t\t}\n\t}\n\n\tret = false;\nlabel_return:\n\treturn (ret);\n}\n\nbool\nckh_remove(tsd_t *tsd, ckh_t *ckh, const void *searchkey, void **key,\n    void **data)\n{\n\tsize_t cell;\n\n\tassert(ckh != NULL);\n\n\tcell = ckh_isearch(ckh, searchkey);\n\tif (cell != SIZE_T_MAX) {\n\t\tif (key != NULL)\n\t\t\t*key = (void *)ckh->tab[cell].key;\n\t\tif (data != NULL)\n\t\t\t*data = (void *)ckh->tab[cell].data;\n\t\tckh->tab[cell].key = NULL;\n\t\tckh->tab[cell].data = NULL; /* Not necessary. */\n\n\t\tckh->count--;\n\t\t/* Try to halve the table if it is less than 1/4 full. */\n\t\tif (ckh->count < (ZU(1) << (ckh->lg_curbuckets\n\t\t    + LG_CKH_BUCKET_CELLS - 2)) && ckh->lg_curbuckets\n\t\t    > ckh->lg_minbuckets) {\n\t\t\t/* Ignore error due to OOM. */\n\t\t\tckh_shrink(tsd, ckh);\n\t\t}\n\n\t\treturn (false);\n\t}\n\n\treturn (true);\n}\n\nbool\nckh_search(ckh_t *ckh, const void *searchkey, void **key, void **data)\n{\n\tsize_t cell;\n\n\tassert(ckh != NULL);\n\n\tcell = ckh_isearch(ckh, searchkey);\n\tif (cell != SIZE_T_MAX) {\n\t\tif (key != NULL)\n\t\t\t*key = (void *)ckh->tab[cell].key;\n\t\tif (data != NULL)\n\t\t\t*data = (void *)ckh->tab[cell].data;\n\t\treturn (false);\n\t}\n\n\treturn (true);\n}\n\nvoid\nckh_string_hash(const void *key, size_t r_hash[2])\n{\n\n\thash(key, strlen((const char *)key), 0x94122f33U, r_hash);\n}\n\nbool\nckh_string_keycomp(const void *k1, const void *k2)\n{\n\n    assert(k1 != NULL);\n    assert(k2 != NULL);\n\n    return (strcmp((char *)k1, (char *)k2) ? false : true);\n}\n\nvoid\nckh_pointer_hash(const void *key, size_t r_hash[2])\n{\n\tunion {\n\t\tconst void\t*v;\n\t\tsize_t\t\ti;\n\t} u;\n\n\tassert(sizeof(u.v) == sizeof(u.i));\n\tu.v = key;\n\thash(&u.i, sizeof(u.i), 0xd983396eU, r_hash);\n}\n\nbool\nckh_pointer_keycomp(const void *k1, const void *k2)\n{\n\n\treturn ((k1 == k2) ? true : false);\n}\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.8/deps/jemalloc/src/ctl.c",
    "content": "#define\tJEMALLOC_CTL_C_\n#include \"jemalloc/internal/jemalloc_internal.h\"\n\n/******************************************************************************/\n/* Data. */\n\n/*\n * ctl_mtx protects the following:\n * - ctl_stats.*\n */\nstatic malloc_mutex_t\tctl_mtx;\nstatic bool\t\tctl_initialized;\nstatic uint64_t\t\tctl_epoch;\nstatic ctl_stats_t\tctl_stats;\n\n/******************************************************************************/\n/* Helpers for named and indexed nodes. */\n\nJEMALLOC_INLINE_C const ctl_named_node_t *\nctl_named_node(const ctl_node_t *node)\n{\n\n\treturn ((node->named) ? (const ctl_named_node_t *)node : NULL);\n}\n\nJEMALLOC_INLINE_C const ctl_named_node_t *\nctl_named_children(const ctl_named_node_t *node, int index)\n{\n\tconst ctl_named_node_t *children = ctl_named_node(node->children);\n\n\treturn (children ? &children[index] : NULL);\n}\n\nJEMALLOC_INLINE_C const ctl_indexed_node_t *\nctl_indexed_node(const ctl_node_t *node)\n{\n\n\treturn (!node->named ? (const ctl_indexed_node_t *)node : NULL);\n}\n\n/******************************************************************************/\n/* Function prototypes for non-inline static functions. */\n\n#define\tCTL_PROTO(n)\t\t\t\t\t\t\t\\\nstatic int\tn##_ctl(const size_t *mib, size_t miblen, void *oldp,\t\\\n    size_t *oldlenp, void *newp, size_t newlen);\n\n#define\tINDEX_PROTO(n)\t\t\t\t\t\t\t\\\nstatic const ctl_named_node_t\t*n##_index(const size_t *mib,\t\t\\\n    size_t miblen, size_t i);\n\nstatic bool\tctl_arena_init(ctl_arena_stats_t *astats);\nstatic void\tctl_arena_clear(ctl_arena_stats_t *astats);\nstatic void\tctl_arena_stats_amerge(ctl_arena_stats_t *cstats,\n    arena_t *arena);\nstatic void\tctl_arena_stats_smerge(ctl_arena_stats_t *sstats,\n    ctl_arena_stats_t *astats);\nstatic void\tctl_arena_refresh(arena_t *arena, unsigned i);\nstatic bool\tctl_grow(void);\nstatic void\tctl_refresh(void);\nstatic bool\tctl_init(void);\nstatic int\tctl_lookup(const char *name, ctl_node_t const **nodesp,\n    size_t *mibp, size_t *depthp);\n\nCTL_PROTO(version)\nCTL_PROTO(epoch)\nCTL_PROTO(thread_tcache_enabled)\nCTL_PROTO(thread_tcache_flush)\nCTL_PROTO(thread_prof_name)\nCTL_PROTO(thread_prof_active)\nCTL_PROTO(thread_arena)\nCTL_PROTO(thread_allocated)\nCTL_PROTO(thread_allocatedp)\nCTL_PROTO(thread_deallocated)\nCTL_PROTO(thread_deallocatedp)\nCTL_PROTO(config_cache_oblivious)\nCTL_PROTO(config_debug)\nCTL_PROTO(config_fill)\nCTL_PROTO(config_lazy_lock)\nCTL_PROTO(config_munmap)\nCTL_PROTO(config_prof)\nCTL_PROTO(config_prof_libgcc)\nCTL_PROTO(config_prof_libunwind)\nCTL_PROTO(config_stats)\nCTL_PROTO(config_tcache)\nCTL_PROTO(config_tls)\nCTL_PROTO(config_utrace)\nCTL_PROTO(config_valgrind)\nCTL_PROTO(config_xmalloc)\nCTL_PROTO(opt_abort)\nCTL_PROTO(opt_dss)\nCTL_PROTO(opt_lg_chunk)\nCTL_PROTO(opt_narenas)\nCTL_PROTO(opt_lg_dirty_mult)\nCTL_PROTO(opt_stats_print)\nCTL_PROTO(opt_junk)\nCTL_PROTO(opt_zero)\nCTL_PROTO(opt_quarantine)\nCTL_PROTO(opt_redzone)\nCTL_PROTO(opt_utrace)\nCTL_PROTO(opt_xmalloc)\nCTL_PROTO(opt_tcache)\nCTL_PROTO(opt_lg_tcache_max)\nCTL_PROTO(opt_prof)\nCTL_PROTO(opt_prof_prefix)\nCTL_PROTO(opt_prof_active)\nCTL_PROTO(opt_prof_thread_active_init)\nCTL_PROTO(opt_lg_prof_sample)\nCTL_PROTO(opt_lg_prof_interval)\nCTL_PROTO(opt_prof_gdump)\nCTL_PROTO(opt_prof_final)\nCTL_PROTO(opt_prof_leak)\nCTL_PROTO(opt_prof_accum)\nCTL_PROTO(tcache_create)\nCTL_PROTO(tcache_flush)\nCTL_PROTO(tcache_destroy)\nCTL_PROTO(arena_i_purge)\nstatic void\tarena_purge(unsigned arena_ind);\nCTL_PROTO(arena_i_dss)\nCTL_PROTO(arena_i_lg_dirty_mult)\nCTL_PROTO(arena_i_chunk_hooks)\nINDEX_PROTO(arena_i)\nCTL_PROTO(arenas_bin_i_size)\nCTL_PROTO(arenas_bin_i_nregs)\nCTL_PROTO(arenas_bin_i_run_size)\nINDEX_PROTO(arenas_bin_i)\nCTL_PROTO(arenas_lrun_i_size)\nINDEX_PROTO(arenas_lrun_i)\nCTL_PROTO(arenas_hchunk_i_size)\nINDEX_PROTO(arenas_hchunk_i)\nCTL_PROTO(arenas_narenas)\nCTL_PROTO(arenas_initialized)\nCTL_PROTO(arenas_lg_dirty_mult)\nCTL_PROTO(arenas_quantum)\nCTL_PROTO(arenas_page)\nCTL_PROTO(arenas_tcache_max)\nCTL_PROTO(arenas_nbins)\nCTL_PROTO(arenas_nhbins)\nCTL_PROTO(arenas_nlruns)\nCTL_PROTO(arenas_nhchunks)\nCTL_PROTO(arenas_extend)\nCTL_PROTO(prof_thread_active_init)\nCTL_PROTO(prof_active)\nCTL_PROTO(prof_dump)\nCTL_PROTO(prof_gdump)\nCTL_PROTO(prof_reset)\nCTL_PROTO(prof_interval)\nCTL_PROTO(lg_prof_sample)\nCTL_PROTO(stats_arenas_i_small_allocated)\nCTL_PROTO(stats_arenas_i_small_nmalloc)\nCTL_PROTO(stats_arenas_i_small_ndalloc)\nCTL_PROTO(stats_arenas_i_small_nrequests)\nCTL_PROTO(stats_arenas_i_large_allocated)\nCTL_PROTO(stats_arenas_i_large_nmalloc)\nCTL_PROTO(stats_arenas_i_large_ndalloc)\nCTL_PROTO(stats_arenas_i_large_nrequests)\nCTL_PROTO(stats_arenas_i_huge_allocated)\nCTL_PROTO(stats_arenas_i_huge_nmalloc)\nCTL_PROTO(stats_arenas_i_huge_ndalloc)\nCTL_PROTO(stats_arenas_i_huge_nrequests)\nCTL_PROTO(stats_arenas_i_bins_j_nmalloc)\nCTL_PROTO(stats_arenas_i_bins_j_ndalloc)\nCTL_PROTO(stats_arenas_i_bins_j_nrequests)\nCTL_PROTO(stats_arenas_i_bins_j_curregs)\nCTL_PROTO(stats_arenas_i_bins_j_nfills)\nCTL_PROTO(stats_arenas_i_bins_j_nflushes)\nCTL_PROTO(stats_arenas_i_bins_j_nruns)\nCTL_PROTO(stats_arenas_i_bins_j_nreruns)\nCTL_PROTO(stats_arenas_i_bins_j_curruns)\nINDEX_PROTO(stats_arenas_i_bins_j)\nCTL_PROTO(stats_arenas_i_lruns_j_nmalloc)\nCTL_PROTO(stats_arenas_i_lruns_j_ndalloc)\nCTL_PROTO(stats_arenas_i_lruns_j_nrequests)\nCTL_PROTO(stats_arenas_i_lruns_j_curruns)\nINDEX_PROTO(stats_arenas_i_lruns_j)\nCTL_PROTO(stats_arenas_i_hchunks_j_nmalloc)\nCTL_PROTO(stats_arenas_i_hchunks_j_ndalloc)\nCTL_PROTO(stats_arenas_i_hchunks_j_nrequests)\nCTL_PROTO(stats_arenas_i_hchunks_j_curhchunks)\nINDEX_PROTO(stats_arenas_i_hchunks_j)\nCTL_PROTO(stats_arenas_i_nthreads)\nCTL_PROTO(stats_arenas_i_dss)\nCTL_PROTO(stats_arenas_i_lg_dirty_mult)\nCTL_PROTO(stats_arenas_i_pactive)\nCTL_PROTO(stats_arenas_i_pdirty)\nCTL_PROTO(stats_arenas_i_mapped)\nCTL_PROTO(stats_arenas_i_npurge)\nCTL_PROTO(stats_arenas_i_nmadvise)\nCTL_PROTO(stats_arenas_i_purged)\nCTL_PROTO(stats_arenas_i_metadata_mapped)\nCTL_PROTO(stats_arenas_i_metadata_allocated)\nINDEX_PROTO(stats_arenas_i)\nCTL_PROTO(stats_cactive)\nCTL_PROTO(stats_allocated)\nCTL_PROTO(stats_active)\nCTL_PROTO(stats_metadata)\nCTL_PROTO(stats_resident)\nCTL_PROTO(stats_mapped)\n\n/******************************************************************************/\n/* mallctl tree. */\n\n/* Maximum tree depth. */\n#define\tCTL_MAX_DEPTH\t6\n\n#define\tNAME(n)\t{true},\tn\n#define\tCHILD(t, c)\t\t\t\t\t\t\t\\\n\tsizeof(c##_node) / sizeof(ctl_##t##_node_t),\t\t\t\\\n\t(ctl_node_t *)c##_node,\t\t\t\t\t\t\\\n\tNULL\n#define\tCTL(c)\t0, NULL, c##_ctl\n\n/*\n * Only handles internal indexed nodes, since there are currently no external\n * ones.\n */\n#define\tINDEX(i)\t{false},\ti##_index\n\nstatic const ctl_named_node_t\tthread_tcache_node[] = {\n\t{NAME(\"enabled\"),\tCTL(thread_tcache_enabled)},\n\t{NAME(\"flush\"),\t\tCTL(thread_tcache_flush)}\n};\n\nstatic const ctl_named_node_t\tthread_prof_node[] = {\n\t{NAME(\"name\"),\t\tCTL(thread_prof_name)},\n\t{NAME(\"active\"),\tCTL(thread_prof_active)}\n};\n\nstatic const ctl_named_node_t\tthread_node[] = {\n\t{NAME(\"arena\"),\t\tCTL(thread_arena)},\n\t{NAME(\"allocated\"),\tCTL(thread_allocated)},\n\t{NAME(\"allocatedp\"),\tCTL(thread_allocatedp)},\n\t{NAME(\"deallocated\"),\tCTL(thread_deallocated)},\n\t{NAME(\"deallocatedp\"),\tCTL(thread_deallocatedp)},\n\t{NAME(\"tcache\"),\tCHILD(named, thread_tcache)},\n\t{NAME(\"prof\"),\t\tCHILD(named, thread_prof)}\n};\n\nstatic const ctl_named_node_t\tconfig_node[] = {\n\t{NAME(\"cache_oblivious\"), CTL(config_cache_oblivious)},\n\t{NAME(\"debug\"),\t\tCTL(config_debug)},\n\t{NAME(\"fill\"),\t\tCTL(config_fill)},\n\t{NAME(\"lazy_lock\"),\tCTL(config_lazy_lock)},\n\t{NAME(\"munmap\"),\tCTL(config_munmap)},\n\t{NAME(\"prof\"),\t\tCTL(config_prof)},\n\t{NAME(\"prof_libgcc\"),\tCTL(config_prof_libgcc)},\n\t{NAME(\"prof_libunwind\"), CTL(config_prof_libunwind)},\n\t{NAME(\"stats\"),\t\tCTL(config_stats)},\n\t{NAME(\"tcache\"),\tCTL(config_tcache)},\n\t{NAME(\"tls\"),\t\tCTL(config_tls)},\n\t{NAME(\"utrace\"),\tCTL(config_utrace)},\n\t{NAME(\"valgrind\"),\tCTL(config_valgrind)},\n\t{NAME(\"xmalloc\"),\tCTL(config_xmalloc)}\n};\n\nstatic const ctl_named_node_t opt_node[] = {\n\t{NAME(\"abort\"),\t\tCTL(opt_abort)},\n\t{NAME(\"dss\"),\t\tCTL(opt_dss)},\n\t{NAME(\"lg_chunk\"),\tCTL(opt_lg_chunk)},\n\t{NAME(\"narenas\"),\tCTL(opt_narenas)},\n\t{NAME(\"lg_dirty_mult\"),\tCTL(opt_lg_dirty_mult)},\n\t{NAME(\"stats_print\"),\tCTL(opt_stats_print)},\n\t{NAME(\"junk\"),\t\tCTL(opt_junk)},\n\t{NAME(\"zero\"),\t\tCTL(opt_zero)},\n\t{NAME(\"quarantine\"),\tCTL(opt_quarantine)},\n\t{NAME(\"redzone\"),\tCTL(opt_redzone)},\n\t{NAME(\"utrace\"),\tCTL(opt_utrace)},\n\t{NAME(\"xmalloc\"),\tCTL(opt_xmalloc)},\n\t{NAME(\"tcache\"),\tCTL(opt_tcache)},\n\t{NAME(\"lg_tcache_max\"),\tCTL(opt_lg_tcache_max)},\n\t{NAME(\"prof\"),\t\tCTL(opt_prof)},\n\t{NAME(\"prof_prefix\"),\tCTL(opt_prof_prefix)},\n\t{NAME(\"prof_active\"),\tCTL(opt_prof_active)},\n\t{NAME(\"prof_thread_active_init\"), CTL(opt_prof_thread_active_init)},\n\t{NAME(\"lg_prof_sample\"), CTL(opt_lg_prof_sample)},\n\t{NAME(\"lg_prof_interval\"), CTL(opt_lg_prof_interval)},\n\t{NAME(\"prof_gdump\"),\tCTL(opt_prof_gdump)},\n\t{NAME(\"prof_final\"),\tCTL(opt_prof_final)},\n\t{NAME(\"prof_leak\"),\tCTL(opt_prof_leak)},\n\t{NAME(\"prof_accum\"),\tCTL(opt_prof_accum)}\n};\n\nstatic const ctl_named_node_t\ttcache_node[] = {\n\t{NAME(\"create\"),\tCTL(tcache_create)},\n\t{NAME(\"flush\"),\t\tCTL(tcache_flush)},\n\t{NAME(\"destroy\"),\tCTL(tcache_destroy)}\n};\n\nstatic const ctl_named_node_t arena_i_node[] = {\n\t{NAME(\"purge\"),\t\tCTL(arena_i_purge)},\n\t{NAME(\"dss\"),\t\tCTL(arena_i_dss)},\n\t{NAME(\"lg_dirty_mult\"),\tCTL(arena_i_lg_dirty_mult)},\n\t{NAME(\"chunk_hooks\"),\tCTL(arena_i_chunk_hooks)}\n};\nstatic const ctl_named_node_t super_arena_i_node[] = {\n\t{NAME(\"\"),\t\tCHILD(named, arena_i)}\n};\n\nstatic const ctl_indexed_node_t arena_node[] = {\n\t{INDEX(arena_i)}\n};\n\nstatic const ctl_named_node_t arenas_bin_i_node[] = {\n\t{NAME(\"size\"),\t\tCTL(arenas_bin_i_size)},\n\t{NAME(\"nregs\"),\t\tCTL(arenas_bin_i_nregs)},\n\t{NAME(\"run_size\"),\tCTL(arenas_bin_i_run_size)}\n};\nstatic const ctl_named_node_t super_arenas_bin_i_node[] = {\n\t{NAME(\"\"),\t\tCHILD(named, arenas_bin_i)}\n};\n\nstatic const ctl_indexed_node_t arenas_bin_node[] = {\n\t{INDEX(arenas_bin_i)}\n};\n\nstatic const ctl_named_node_t arenas_lrun_i_node[] = {\n\t{NAME(\"size\"),\t\tCTL(arenas_lrun_i_size)}\n};\nstatic const ctl_named_node_t super_arenas_lrun_i_node[] = {\n\t{NAME(\"\"),\t\tCHILD(named, arenas_lrun_i)}\n};\n\nstatic const ctl_indexed_node_t arenas_lrun_node[] = {\n\t{INDEX(arenas_lrun_i)}\n};\n\nstatic const ctl_named_node_t arenas_hchunk_i_node[] = {\n\t{NAME(\"size\"),\t\tCTL(arenas_hchunk_i_size)}\n};\nstatic const ctl_named_node_t super_arenas_hchunk_i_node[] = {\n\t{NAME(\"\"),\t\tCHILD(named, arenas_hchunk_i)}\n};\n\nstatic const ctl_indexed_node_t arenas_hchunk_node[] = {\n\t{INDEX(arenas_hchunk_i)}\n};\n\nstatic const ctl_named_node_t arenas_node[] = {\n\t{NAME(\"narenas\"),\tCTL(arenas_narenas)},\n\t{NAME(\"initialized\"),\tCTL(arenas_initialized)},\n\t{NAME(\"lg_dirty_mult\"),\tCTL(arenas_lg_dirty_mult)},\n\t{NAME(\"quantum\"),\tCTL(arenas_quantum)},\n\t{NAME(\"page\"),\t\tCTL(arenas_page)},\n\t{NAME(\"tcache_max\"),\tCTL(arenas_tcache_max)},\n\t{NAME(\"nbins\"),\t\tCTL(arenas_nbins)},\n\t{NAME(\"nhbins\"),\tCTL(arenas_nhbins)},\n\t{NAME(\"bin\"),\t\tCHILD(indexed, arenas_bin)},\n\t{NAME(\"nlruns\"),\tCTL(arenas_nlruns)},\n\t{NAME(\"lrun\"),\t\tCHILD(indexed, arenas_lrun)},\n\t{NAME(\"nhchunks\"),\tCTL(arenas_nhchunks)},\n\t{NAME(\"hchunk\"),\tCHILD(indexed, arenas_hchunk)},\n\t{NAME(\"extend\"),\tCTL(arenas_extend)}\n};\n\nstatic const ctl_named_node_t\tprof_node[] = {\n\t{NAME(\"thread_active_init\"), CTL(prof_thread_active_init)},\n\t{NAME(\"active\"),\tCTL(prof_active)},\n\t{NAME(\"dump\"),\t\tCTL(prof_dump)},\n\t{NAME(\"gdump\"),\t\tCTL(prof_gdump)},\n\t{NAME(\"reset\"),\t\tCTL(prof_reset)},\n\t{NAME(\"interval\"),\tCTL(prof_interval)},\n\t{NAME(\"lg_sample\"),\tCTL(lg_prof_sample)}\n};\n\nstatic const ctl_named_node_t stats_arenas_i_metadata_node[] = {\n\t{NAME(\"mapped\"),\tCTL(stats_arenas_i_metadata_mapped)},\n\t{NAME(\"allocated\"),\tCTL(stats_arenas_i_metadata_allocated)}\n};\n\nstatic const ctl_named_node_t stats_arenas_i_small_node[] = {\n\t{NAME(\"allocated\"),\tCTL(stats_arenas_i_small_allocated)},\n\t{NAME(\"nmalloc\"),\tCTL(stats_arenas_i_small_nmalloc)},\n\t{NAME(\"ndalloc\"),\tCTL(stats_arenas_i_small_ndalloc)},\n\t{NAME(\"nrequests\"),\tCTL(stats_arenas_i_small_nrequests)}\n};\n\nstatic const ctl_named_node_t stats_arenas_i_large_node[] = {\n\t{NAME(\"allocated\"),\tCTL(stats_arenas_i_large_allocated)},\n\t{NAME(\"nmalloc\"),\tCTL(stats_arenas_i_large_nmalloc)},\n\t{NAME(\"ndalloc\"),\tCTL(stats_arenas_i_large_ndalloc)},\n\t{NAME(\"nrequests\"),\tCTL(stats_arenas_i_large_nrequests)}\n};\n\nstatic const ctl_named_node_t stats_arenas_i_huge_node[] = {\n\t{NAME(\"allocated\"),\tCTL(stats_arenas_i_huge_allocated)},\n\t{NAME(\"nmalloc\"),\tCTL(stats_arenas_i_huge_nmalloc)},\n\t{NAME(\"ndalloc\"),\tCTL(stats_arenas_i_huge_ndalloc)},\n\t{NAME(\"nrequests\"),\tCTL(stats_arenas_i_huge_nrequests)}\n};\n\nstatic const ctl_named_node_t stats_arenas_i_bins_j_node[] = {\n\t{NAME(\"nmalloc\"),\tCTL(stats_arenas_i_bins_j_nmalloc)},\n\t{NAME(\"ndalloc\"),\tCTL(stats_arenas_i_bins_j_ndalloc)},\n\t{NAME(\"nrequests\"),\tCTL(stats_arenas_i_bins_j_nrequests)},\n\t{NAME(\"curregs\"),\tCTL(stats_arenas_i_bins_j_curregs)},\n\t{NAME(\"nfills\"),\tCTL(stats_arenas_i_bins_j_nfills)},\n\t{NAME(\"nflushes\"),\tCTL(stats_arenas_i_bins_j_nflushes)},\n\t{NAME(\"nruns\"),\t\tCTL(stats_arenas_i_bins_j_nruns)},\n\t{NAME(\"nreruns\"),\tCTL(stats_arenas_i_bins_j_nreruns)},\n\t{NAME(\"curruns\"),\tCTL(stats_arenas_i_bins_j_curruns)}\n};\nstatic const ctl_named_node_t super_stats_arenas_i_bins_j_node[] = {\n\t{NAME(\"\"),\t\tCHILD(named, stats_arenas_i_bins_j)}\n};\n\nstatic const ctl_indexed_node_t stats_arenas_i_bins_node[] = {\n\t{INDEX(stats_arenas_i_bins_j)}\n};\n\nstatic const ctl_named_node_t stats_arenas_i_lruns_j_node[] = {\n\t{NAME(\"nmalloc\"),\tCTL(stats_arenas_i_lruns_j_nmalloc)},\n\t{NAME(\"ndalloc\"),\tCTL(stats_arenas_i_lruns_j_ndalloc)},\n\t{NAME(\"nrequests\"),\tCTL(stats_arenas_i_lruns_j_nrequests)},\n\t{NAME(\"curruns\"),\tCTL(stats_arenas_i_lruns_j_curruns)}\n};\nstatic const ctl_named_node_t super_stats_arenas_i_lruns_j_node[] = {\n\t{NAME(\"\"),\t\tCHILD(named, stats_arenas_i_lruns_j)}\n};\n\nstatic const ctl_indexed_node_t stats_arenas_i_lruns_node[] = {\n\t{INDEX(stats_arenas_i_lruns_j)}\n};\n\nstatic const ctl_named_node_t stats_arenas_i_hchunks_j_node[] = {\n\t{NAME(\"nmalloc\"),\tCTL(stats_arenas_i_hchunks_j_nmalloc)},\n\t{NAME(\"ndalloc\"),\tCTL(stats_arenas_i_hchunks_j_ndalloc)},\n\t{NAME(\"nrequests\"),\tCTL(stats_arenas_i_hchunks_j_nrequests)},\n\t{NAME(\"curhchunks\"),\tCTL(stats_arenas_i_hchunks_j_curhchunks)}\n};\nstatic const ctl_named_node_t super_stats_arenas_i_hchunks_j_node[] = {\n\t{NAME(\"\"),\t\tCHILD(named, stats_arenas_i_hchunks_j)}\n};\n\nstatic const ctl_indexed_node_t stats_arenas_i_hchunks_node[] = {\n\t{INDEX(stats_arenas_i_hchunks_j)}\n};\n\nstatic const ctl_named_node_t stats_arenas_i_node[] = {\n\t{NAME(\"nthreads\"),\tCTL(stats_arenas_i_nthreads)},\n\t{NAME(\"dss\"),\t\tCTL(stats_arenas_i_dss)},\n\t{NAME(\"lg_dirty_mult\"),\tCTL(stats_arenas_i_lg_dirty_mult)},\n\t{NAME(\"pactive\"),\tCTL(stats_arenas_i_pactive)},\n\t{NAME(\"pdirty\"),\tCTL(stats_arenas_i_pdirty)},\n\t{NAME(\"mapped\"),\tCTL(stats_arenas_i_mapped)},\n\t{NAME(\"npurge\"),\tCTL(stats_arenas_i_npurge)},\n\t{NAME(\"nmadvise\"),\tCTL(stats_arenas_i_nmadvise)},\n\t{NAME(\"purged\"),\tCTL(stats_arenas_i_purged)},\n\t{NAME(\"metadata\"),\tCHILD(named, stats_arenas_i_metadata)},\n\t{NAME(\"small\"),\t\tCHILD(named, stats_arenas_i_small)},\n\t{NAME(\"large\"),\t\tCHILD(named, stats_arenas_i_large)},\n\t{NAME(\"huge\"),\t\tCHILD(named, stats_arenas_i_huge)},\n\t{NAME(\"bins\"),\t\tCHILD(indexed, stats_arenas_i_bins)},\n\t{NAME(\"lruns\"),\t\tCHILD(indexed, stats_arenas_i_lruns)},\n\t{NAME(\"hchunks\"),\tCHILD(indexed, stats_arenas_i_hchunks)}\n};\nstatic const ctl_named_node_t super_stats_arenas_i_node[] = {\n\t{NAME(\"\"),\t\tCHILD(named, stats_arenas_i)}\n};\n\nstatic const ctl_indexed_node_t stats_arenas_node[] = {\n\t{INDEX(stats_arenas_i)}\n};\n\nstatic const ctl_named_node_t stats_node[] = {\n\t{NAME(\"cactive\"),\tCTL(stats_cactive)},\n\t{NAME(\"allocated\"),\tCTL(stats_allocated)},\n\t{NAME(\"active\"),\tCTL(stats_active)},\n\t{NAME(\"metadata\"),\tCTL(stats_metadata)},\n\t{NAME(\"resident\"),\tCTL(stats_resident)},\n\t{NAME(\"mapped\"),\tCTL(stats_mapped)},\n\t{NAME(\"arenas\"),\tCHILD(indexed, stats_arenas)}\n};\n\nstatic const ctl_named_node_t\troot_node[] = {\n\t{NAME(\"version\"),\tCTL(version)},\n\t{NAME(\"epoch\"),\t\tCTL(epoch)},\n\t{NAME(\"thread\"),\tCHILD(named, thread)},\n\t{NAME(\"config\"),\tCHILD(named, config)},\n\t{NAME(\"opt\"),\t\tCHILD(named, opt)},\n\t{NAME(\"tcache\"),\tCHILD(named, tcache)},\n\t{NAME(\"arena\"),\t\tCHILD(indexed, arena)},\n\t{NAME(\"arenas\"),\tCHILD(named, arenas)},\n\t{NAME(\"prof\"),\t\tCHILD(named, prof)},\n\t{NAME(\"stats\"),\t\tCHILD(named, stats)}\n};\nstatic const ctl_named_node_t super_root_node[] = {\n\t{NAME(\"\"),\t\tCHILD(named, root)}\n};\n\n#undef NAME\n#undef CHILD\n#undef CTL\n#undef INDEX\n\n/******************************************************************************/\n\nstatic bool\nctl_arena_init(ctl_arena_stats_t *astats)\n{\n\n\tif (astats->lstats == NULL) {\n\t\tastats->lstats = (malloc_large_stats_t *)a0malloc(nlclasses *\n\t\t    sizeof(malloc_large_stats_t));\n\t\tif (astats->lstats == NULL)\n\t\t\treturn (true);\n\t}\n\n\tif (astats->hstats == NULL) {\n\t\tastats->hstats = (malloc_huge_stats_t *)a0malloc(nhclasses *\n\t\t    sizeof(malloc_huge_stats_t));\n\t\tif (astats->hstats == NULL)\n\t\t\treturn (true);\n\t}\n\n\treturn (false);\n}\n\nstatic void\nctl_arena_clear(ctl_arena_stats_t *astats)\n{\n\n\tastats->dss = dss_prec_names[dss_prec_limit];\n\tastats->lg_dirty_mult = -1;\n\tastats->pactive = 0;\n\tastats->pdirty = 0;\n\tif (config_stats) {\n\t\tmemset(&astats->astats, 0, sizeof(arena_stats_t));\n\t\tastats->allocated_small = 0;\n\t\tastats->nmalloc_small = 0;\n\t\tastats->ndalloc_small = 0;\n\t\tastats->nrequests_small = 0;\n\t\tmemset(astats->bstats, 0, NBINS * sizeof(malloc_bin_stats_t));\n\t\tmemset(astats->lstats, 0, nlclasses *\n\t\t    sizeof(malloc_large_stats_t));\n\t\tmemset(astats->hstats, 0, nhclasses *\n\t\t    sizeof(malloc_huge_stats_t));\n\t}\n}\n\nstatic void\nctl_arena_stats_amerge(ctl_arena_stats_t *cstats, arena_t *arena)\n{\n\tunsigned i;\n\n\tarena_stats_merge(arena, &cstats->dss, &cstats->lg_dirty_mult,\n\t    &cstats->pactive, &cstats->pdirty, &cstats->astats, cstats->bstats,\n\t    cstats->lstats, cstats->hstats);\n\n\tfor (i = 0; i < NBINS; i++) {\n\t\tcstats->allocated_small += cstats->bstats[i].curregs *\n\t\t    index2size(i);\n\t\tcstats->nmalloc_small += cstats->bstats[i].nmalloc;\n\t\tcstats->ndalloc_small += cstats->bstats[i].ndalloc;\n\t\tcstats->nrequests_small += cstats->bstats[i].nrequests;\n\t}\n}\n\nstatic void\nctl_arena_stats_smerge(ctl_arena_stats_t *sstats, ctl_arena_stats_t *astats)\n{\n\tunsigned i;\n\n\tsstats->pactive += astats->pactive;\n\tsstats->pdirty += astats->pdirty;\n\n\tsstats->astats.mapped += astats->astats.mapped;\n\tsstats->astats.npurge += astats->astats.npurge;\n\tsstats->astats.nmadvise += astats->astats.nmadvise;\n\tsstats->astats.purged += astats->astats.purged;\n\n\tsstats->astats.metadata_mapped += astats->astats.metadata_mapped;\n\tsstats->astats.metadata_allocated += astats->astats.metadata_allocated;\n\n\tsstats->allocated_small += astats->allocated_small;\n\tsstats->nmalloc_small += astats->nmalloc_small;\n\tsstats->ndalloc_small += astats->ndalloc_small;\n\tsstats->nrequests_small += astats->nrequests_small;\n\n\tsstats->astats.allocated_large += astats->astats.allocated_large;\n\tsstats->astats.nmalloc_large += astats->astats.nmalloc_large;\n\tsstats->astats.ndalloc_large += astats->astats.ndalloc_large;\n\tsstats->astats.nrequests_large += astats->astats.nrequests_large;\n\n\tsstats->astats.allocated_huge += astats->astats.allocated_huge;\n\tsstats->astats.nmalloc_huge += astats->astats.nmalloc_huge;\n\tsstats->astats.ndalloc_huge += astats->astats.ndalloc_huge;\n\n\tfor (i = 0; i < NBINS; i++) {\n\t\tsstats->bstats[i].nmalloc += astats->bstats[i].nmalloc;\n\t\tsstats->bstats[i].ndalloc += astats->bstats[i].ndalloc;\n\t\tsstats->bstats[i].nrequests += astats->bstats[i].nrequests;\n\t\tsstats->bstats[i].curregs += astats->bstats[i].curregs;\n\t\tif (config_tcache) {\n\t\t\tsstats->bstats[i].nfills += astats->bstats[i].nfills;\n\t\t\tsstats->bstats[i].nflushes +=\n\t\t\t    astats->bstats[i].nflushes;\n\t\t}\n\t\tsstats->bstats[i].nruns += astats->bstats[i].nruns;\n\t\tsstats->bstats[i].reruns += astats->bstats[i].reruns;\n\t\tsstats->bstats[i].curruns += astats->bstats[i].curruns;\n\t}\n\n\tfor (i = 0; i < nlclasses; i++) {\n\t\tsstats->lstats[i].nmalloc += astats->lstats[i].nmalloc;\n\t\tsstats->lstats[i].ndalloc += astats->lstats[i].ndalloc;\n\t\tsstats->lstats[i].nrequests += astats->lstats[i].nrequests;\n\t\tsstats->lstats[i].curruns += astats->lstats[i].curruns;\n\t}\n\n\tfor (i = 0; i < nhclasses; i++) {\n\t\tsstats->hstats[i].nmalloc += astats->hstats[i].nmalloc;\n\t\tsstats->hstats[i].ndalloc += astats->hstats[i].ndalloc;\n\t\tsstats->hstats[i].curhchunks += astats->hstats[i].curhchunks;\n\t}\n}\n\nstatic void\nctl_arena_refresh(arena_t *arena, unsigned i)\n{\n\tctl_arena_stats_t *astats = &ctl_stats.arenas[i];\n\tctl_arena_stats_t *sstats = &ctl_stats.arenas[ctl_stats.narenas];\n\n\tctl_arena_clear(astats);\n\n\tsstats->nthreads += astats->nthreads;\n\tif (config_stats) {\n\t\tctl_arena_stats_amerge(astats, arena);\n\t\t/* Merge into sum stats as well. */\n\t\tctl_arena_stats_smerge(sstats, astats);\n\t} else {\n\t\tastats->pactive += arena->nactive;\n\t\tastats->pdirty += arena->ndirty;\n\t\t/* Merge into sum stats as well. */\n\t\tsstats->pactive += arena->nactive;\n\t\tsstats->pdirty += arena->ndirty;\n\t}\n}\n\nstatic bool\nctl_grow(void)\n{\n\tctl_arena_stats_t *astats;\n\n\t/* Initialize new arena. */\n\tif (arena_init(ctl_stats.narenas) == NULL)\n\t\treturn (true);\n\n\t/* Allocate extended arena stats. */\n\tastats = (ctl_arena_stats_t *)a0malloc((ctl_stats.narenas + 2) *\n\t    sizeof(ctl_arena_stats_t));\n\tif (astats == NULL)\n\t\treturn (true);\n\n\t/* Initialize the new astats element. */\n\tmemcpy(astats, ctl_stats.arenas, (ctl_stats.narenas + 1) *\n\t    sizeof(ctl_arena_stats_t));\n\tmemset(&astats[ctl_stats.narenas + 1], 0, sizeof(ctl_arena_stats_t));\n\tif (ctl_arena_init(&astats[ctl_stats.narenas + 1])) {\n\t\ta0dalloc(astats);\n\t\treturn (true);\n\t}\n\t/* Swap merged stats to their new location. */\n\t{\n\t\tctl_arena_stats_t tstats;\n\t\tmemcpy(&tstats, &astats[ctl_stats.narenas],\n\t\t    sizeof(ctl_arena_stats_t));\n\t\tmemcpy(&astats[ctl_stats.narenas],\n\t\t    &astats[ctl_stats.narenas + 1], sizeof(ctl_arena_stats_t));\n\t\tmemcpy(&astats[ctl_stats.narenas + 1], &tstats,\n\t\t    sizeof(ctl_arena_stats_t));\n\t}\n\ta0dalloc(ctl_stats.arenas);\n\tctl_stats.arenas = astats;\n\tctl_stats.narenas++;\n\n\treturn (false);\n}\n\nstatic void\nctl_refresh(void)\n{\n\ttsd_t *tsd;\n\tunsigned i;\n\tbool refreshed;\n\tVARIABLE_ARRAY(arena_t *, tarenas, ctl_stats.narenas);\n\n\t/*\n\t * Clear sum stats, since they will be merged into by\n\t * ctl_arena_refresh().\n\t */\n\tctl_stats.arenas[ctl_stats.narenas].nthreads = 0;\n\tctl_arena_clear(&ctl_stats.arenas[ctl_stats.narenas]);\n\n\ttsd = tsd_fetch();\n\tfor (i = 0, refreshed = false; i < ctl_stats.narenas; i++) {\n\t\ttarenas[i] = arena_get(tsd, i, false, false);\n\t\tif (tarenas[i] == NULL && !refreshed) {\n\t\t\ttarenas[i] = arena_get(tsd, i, false, true);\n\t\t\trefreshed = true;\n\t\t}\n\t}\n\n\tfor (i = 0; i < ctl_stats.narenas; i++) {\n\t\tif (tarenas[i] != NULL)\n\t\t\tctl_stats.arenas[i].nthreads = arena_nbound(i);\n\t\telse\n\t\t\tctl_stats.arenas[i].nthreads = 0;\n\t}\n\n\tfor (i = 0; i < ctl_stats.narenas; i++) {\n\t\tbool initialized = (tarenas[i] != NULL);\n\n\t\tctl_stats.arenas[i].initialized = initialized;\n\t\tif (initialized)\n\t\t\tctl_arena_refresh(tarenas[i], i);\n\t}\n\n\tif (config_stats) {\n\t\tsize_t base_allocated, base_resident, base_mapped;\n\t\tbase_stats_get(&base_allocated, &base_resident, &base_mapped);\n\t\tctl_stats.allocated =\n\t\t    ctl_stats.arenas[ctl_stats.narenas].allocated_small +\n\t\t    ctl_stats.arenas[ctl_stats.narenas].astats.allocated_large +\n\t\t    ctl_stats.arenas[ctl_stats.narenas].astats.allocated_huge;\n\t\tctl_stats.active =\n\t\t    (ctl_stats.arenas[ctl_stats.narenas].pactive << LG_PAGE);\n\t\tctl_stats.metadata = base_allocated +\n\t\t    ctl_stats.arenas[ctl_stats.narenas].astats.metadata_mapped +\n\t\t    ctl_stats.arenas[ctl_stats.narenas].astats\n\t\t    .metadata_allocated;\n\t\tctl_stats.resident = base_resident +\n\t\t    ctl_stats.arenas[ctl_stats.narenas].astats.metadata_mapped +\n\t\t    ((ctl_stats.arenas[ctl_stats.narenas].pactive +\n\t\t    ctl_stats.arenas[ctl_stats.narenas].pdirty) << LG_PAGE);\n\t\tctl_stats.mapped = base_mapped +\n\t\t    ctl_stats.arenas[ctl_stats.narenas].astats.mapped;\n\t}\n\n\tctl_epoch++;\n}\n\nstatic bool\nctl_init(void)\n{\n\tbool ret;\n\n\tmalloc_mutex_lock(&ctl_mtx);\n\tif (!ctl_initialized) {\n\t\t/*\n\t\t * Allocate space for one extra arena stats element, which\n\t\t * contains summed stats across all arenas.\n\t\t */\n\t\tctl_stats.narenas = narenas_total_get();\n\t\tctl_stats.arenas = (ctl_arena_stats_t *)a0malloc(\n\t\t    (ctl_stats.narenas + 1) * sizeof(ctl_arena_stats_t));\n\t\tif (ctl_stats.arenas == NULL) {\n\t\t\tret = true;\n\t\t\tgoto label_return;\n\t\t}\n\t\tmemset(ctl_stats.arenas, 0, (ctl_stats.narenas + 1) *\n\t\t    sizeof(ctl_arena_stats_t));\n\n\t\t/*\n\t\t * Initialize all stats structures, regardless of whether they\n\t\t * ever get used.  Lazy initialization would allow errors to\n\t\t * cause inconsistent state to be viewable by the application.\n\t\t */\n\t\tif (config_stats) {\n\t\t\tunsigned i;\n\t\t\tfor (i = 0; i <= ctl_stats.narenas; i++) {\n\t\t\t\tif (ctl_arena_init(&ctl_stats.arenas[i])) {\n\t\t\t\t\tunsigned j;\n\t\t\t\t\tfor (j = 0; j < i; j++) {\n\t\t\t\t\t\ta0dalloc(\n\t\t\t\t\t\t    ctl_stats.arenas[j].lstats);\n\t\t\t\t\t\ta0dalloc(\n\t\t\t\t\t\t    ctl_stats.arenas[j].hstats);\n\t\t\t\t\t}\n\t\t\t\t\ta0dalloc(ctl_stats.arenas);\n\t\t\t\t\tctl_stats.arenas = NULL;\n\t\t\t\t\tret = true;\n\t\t\t\t\tgoto label_return;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tctl_stats.arenas[ctl_stats.narenas].initialized = true;\n\n\t\tctl_epoch = 0;\n\t\tctl_refresh();\n\t\tctl_initialized = true;\n\t}\n\n\tret = false;\nlabel_return:\n\tmalloc_mutex_unlock(&ctl_mtx);\n\treturn (ret);\n}\n\nstatic int\nctl_lookup(const char *name, ctl_node_t const **nodesp, size_t *mibp,\n    size_t *depthp)\n{\n\tint ret;\n\tconst char *elm, *tdot, *dot;\n\tsize_t elen, i, j;\n\tconst ctl_named_node_t *node;\n\n\telm = name;\n\t/* Equivalent to strchrnul(). */\n\tdot = ((tdot = strchr(elm, '.')) != NULL) ? tdot : strchr(elm, '\\0');\n\telen = (size_t)((uintptr_t)dot - (uintptr_t)elm);\n\tif (elen == 0) {\n\t\tret = ENOENT;\n\t\tgoto label_return;\n\t}\n\tnode = super_root_node;\n\tfor (i = 0; i < *depthp; i++) {\n\t\tassert(node);\n\t\tassert(node->nchildren > 0);\n\t\tif (ctl_named_node(node->children) != NULL) {\n\t\t\tconst ctl_named_node_t *pnode = node;\n\n\t\t\t/* Children are named. */\n\t\t\tfor (j = 0; j < node->nchildren; j++) {\n\t\t\t\tconst ctl_named_node_t *child =\n\t\t\t\t    ctl_named_children(node, j);\n\t\t\t\tif (strlen(child->name) == elen &&\n\t\t\t\t    strncmp(elm, child->name, elen) == 0) {\n\t\t\t\t\tnode = child;\n\t\t\t\t\tif (nodesp != NULL)\n\t\t\t\t\t\tnodesp[i] =\n\t\t\t\t\t\t    (const ctl_node_t *)node;\n\t\t\t\t\tmibp[i] = j;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (node == pnode) {\n\t\t\t\tret = ENOENT;\n\t\t\t\tgoto label_return;\n\t\t\t}\n\t\t} else {\n\t\t\tuintmax_t index;\n\t\t\tconst ctl_indexed_node_t *inode;\n\n\t\t\t/* Children are indexed. */\n\t\t\tindex = malloc_strtoumax(elm, NULL, 10);\n\t\t\tif (index == UINTMAX_MAX || index > SIZE_T_MAX) {\n\t\t\t\tret = ENOENT;\n\t\t\t\tgoto label_return;\n\t\t\t}\n\n\t\t\tinode = ctl_indexed_node(node->children);\n\t\t\tnode = inode->index(mibp, *depthp, (size_t)index);\n\t\t\tif (node == NULL) {\n\t\t\t\tret = ENOENT;\n\t\t\t\tgoto label_return;\n\t\t\t}\n\n\t\t\tif (nodesp != NULL)\n\t\t\t\tnodesp[i] = (const ctl_node_t *)node;\n\t\t\tmibp[i] = (size_t)index;\n\t\t}\n\n\t\tif (node->ctl != NULL) {\n\t\t\t/* Terminal node. */\n\t\t\tif (*dot != '\\0') {\n\t\t\t\t/*\n\t\t\t\t * The name contains more elements than are\n\t\t\t\t * in this path through the tree.\n\t\t\t\t */\n\t\t\t\tret = ENOENT;\n\t\t\t\tgoto label_return;\n\t\t\t}\n\t\t\t/* Complete lookup successful. */\n\t\t\t*depthp = i + 1;\n\t\t\tbreak;\n\t\t}\n\n\t\t/* Update elm. */\n\t\tif (*dot == '\\0') {\n\t\t\t/* No more elements. */\n\t\t\tret = ENOENT;\n\t\t\tgoto label_return;\n\t\t}\n\t\telm = &dot[1];\n\t\tdot = ((tdot = strchr(elm, '.')) != NULL) ? tdot :\n\t\t    strchr(elm, '\\0');\n\t\telen = (size_t)((uintptr_t)dot - (uintptr_t)elm);\n\t}\n\n\tret = 0;\nlabel_return:\n\treturn (ret);\n}\n\nint\nctl_byname(const char *name, void *oldp, size_t *oldlenp, void *newp,\n    size_t newlen)\n{\n\tint ret;\n\tsize_t depth;\n\tctl_node_t const *nodes[CTL_MAX_DEPTH];\n\tsize_t mib[CTL_MAX_DEPTH];\n\tconst ctl_named_node_t *node;\n\n\tif (!ctl_initialized && ctl_init()) {\n\t\tret = EAGAIN;\n\t\tgoto label_return;\n\t}\n\n\tdepth = CTL_MAX_DEPTH;\n\tret = ctl_lookup(name, nodes, mib, &depth);\n\tif (ret != 0)\n\t\tgoto label_return;\n\n\tnode = ctl_named_node(nodes[depth-1]);\n\tif (node != NULL && node->ctl)\n\t\tret = node->ctl(mib, depth, oldp, oldlenp, newp, newlen);\n\telse {\n\t\t/* The name refers to a partial path through the ctl tree. */\n\t\tret = ENOENT;\n\t}\n\nlabel_return:\n\treturn(ret);\n}\n\nint\nctl_nametomib(const char *name, size_t *mibp, size_t *miblenp)\n{\n\tint ret;\n\n\tif (!ctl_initialized && ctl_init()) {\n\t\tret = EAGAIN;\n\t\tgoto label_return;\n\t}\n\n\tret = ctl_lookup(name, NULL, mibp, miblenp);\nlabel_return:\n\treturn(ret);\n}\n\nint\nctl_bymib(const size_t *mib, size_t miblen, void *oldp, size_t *oldlenp,\n    void *newp, size_t newlen)\n{\n\tint ret;\n\tconst ctl_named_node_t *node;\n\tsize_t i;\n\n\tif (!ctl_initialized && ctl_init()) {\n\t\tret = EAGAIN;\n\t\tgoto label_return;\n\t}\n\n\t/* Iterate down the tree. */\n\tnode = super_root_node;\n\tfor (i = 0; i < miblen; i++) {\n\t\tassert(node);\n\t\tassert(node->nchildren > 0);\n\t\tif (ctl_named_node(node->children) != NULL) {\n\t\t\t/* Children are named. */\n\t\t\tif (node->nchildren <= mib[i]) {\n\t\t\t\tret = ENOENT;\n\t\t\t\tgoto label_return;\n\t\t\t}\n\t\t\tnode = ctl_named_children(node, mib[i]);\n\t\t} else {\n\t\t\tconst ctl_indexed_node_t *inode;\n\n\t\t\t/* Indexed element. */\n\t\t\tinode = ctl_indexed_node(node->children);\n\t\t\tnode = inode->index(mib, miblen, mib[i]);\n\t\t\tif (node == NULL) {\n\t\t\t\tret = ENOENT;\n\t\t\t\tgoto label_return;\n\t\t\t}\n\t\t}\n\t}\n\n\t/* Call the ctl function. */\n\tif (node && node->ctl)\n\t\tret = node->ctl(mib, miblen, oldp, oldlenp, newp, newlen);\n\telse {\n\t\t/* Partial MIB. */\n\t\tret = ENOENT;\n\t}\n\nlabel_return:\n\treturn(ret);\n}\n\nbool\nctl_boot(void)\n{\n\n\tif (malloc_mutex_init(&ctl_mtx))\n\t\treturn (true);\n\n\tctl_initialized = false;\n\n\treturn (false);\n}\n\nvoid\nctl_prefork(void)\n{\n\n\tmalloc_mutex_prefork(&ctl_mtx);\n}\n\nvoid\nctl_postfork_parent(void)\n{\n\n\tmalloc_mutex_postfork_parent(&ctl_mtx);\n}\n\nvoid\nctl_postfork_child(void)\n{\n\n\tmalloc_mutex_postfork_child(&ctl_mtx);\n}\n\n/******************************************************************************/\n/* *_ctl() functions. */\n\n#define\tREADONLY()\tdo {\t\t\t\t\t\t\\\n\tif (newp != NULL || newlen != 0) {\t\t\t\t\\\n\t\tret = EPERM;\t\t\t\t\t\t\\\n\t\tgoto label_return;\t\t\t\t\t\\\n\t}\t\t\t\t\t\t\t\t\\\n} while (0)\n\n#define\tWRITEONLY()\tdo {\t\t\t\t\t\t\\\n\tif (oldp != NULL || oldlenp != NULL) {\t\t\t\t\\\n\t\tret = EPERM;\t\t\t\t\t\t\\\n\t\tgoto label_return;\t\t\t\t\t\\\n\t}\t\t\t\t\t\t\t\t\\\n} while (0)\n\n#define\tREAD_XOR_WRITE()\tdo {\t\t\t\t\t\\\n\tif ((oldp != NULL && oldlenp != NULL) && (newp != NULL ||\t\\\n\t    newlen != 0)) {\t\t\t\t\t\t\\\n\t\tret = EPERM;\t\t\t\t\t\t\\\n\t\tgoto label_return;\t\t\t\t\t\\\n\t}\t\t\t\t\t\t\t\t\\\n} while (0)\n\n#define\tREAD(v, t)\tdo {\t\t\t\t\t\t\\\n\tif (oldp != NULL && oldlenp != NULL) {\t\t\t\t\\\n\t\tif (*oldlenp != sizeof(t)) {\t\t\t\t\\\n\t\t\tsize_t\tcopylen = (sizeof(t) <= *oldlenp)\t\\\n\t\t\t    ? sizeof(t) : *oldlenp;\t\t\t\\\n\t\t\tmemcpy(oldp, (void *)&(v), copylen);\t\t\\\n\t\t\tret = EINVAL;\t\t\t\t\t\\\n\t\t\tgoto label_return;\t\t\t\t\\\n\t\t}\t\t\t\t\t\t\t\\\n\t\t*(t *)oldp = (v);\t\t\t\t\t\\\n\t}\t\t\t\t\t\t\t\t\\\n} while (0)\n\n#define\tWRITE(v, t)\tdo {\t\t\t\t\t\t\\\n\tif (newp != NULL) {\t\t\t\t\t\t\\\n\t\tif (newlen != sizeof(t)) {\t\t\t\t\\\n\t\t\tret = EINVAL;\t\t\t\t\t\\\n\t\t\tgoto label_return;\t\t\t\t\\\n\t\t}\t\t\t\t\t\t\t\\\n\t\t(v) = *(t *)newp;\t\t\t\t\t\\\n\t}\t\t\t\t\t\t\t\t\\\n} while (0)\n\n/*\n * There's a lot of code duplication in the following macros due to limitations\n * in how nested cpp macros are expanded.\n */\n#define\tCTL_RO_CLGEN(c, l, n, v, t)\t\t\t\t\t\\\nstatic int\t\t\t\t\t\t\t\t\\\nn##_ctl(const size_t *mib, size_t miblen, void *oldp, size_t *oldlenp,\t\\\n    void *newp, size_t newlen)\t\t\t\t\t\t\\\n{\t\t\t\t\t\t\t\t\t\\\n\tint ret;\t\t\t\t\t\t\t\\\n\tt oldval;\t\t\t\t\t\t\t\\\n\t\t\t\t\t\t\t\t\t\\\n\tif (!(c))\t\t\t\t\t\t\t\\\n\t\treturn (ENOENT);\t\t\t\t\t\\\n\tif (l)\t\t\t\t\t\t\t\t\\\n\t\tmalloc_mutex_lock(&ctl_mtx);\t\t\t\t\\\n\tREADONLY();\t\t\t\t\t\t\t\\\n\toldval = (v);\t\t\t\t\t\t\t\\\n\tREAD(oldval, t);\t\t\t\t\t\t\\\n\t\t\t\t\t\t\t\t\t\\\n\tret = 0;\t\t\t\t\t\t\t\\\nlabel_return:\t\t\t\t\t\t\t\t\\\n\tif (l)\t\t\t\t\t\t\t\t\\\n\t\tmalloc_mutex_unlock(&ctl_mtx);\t\t\t\t\\\n\treturn (ret);\t\t\t\t\t\t\t\\\n}\n\n#define\tCTL_RO_CGEN(c, n, v, t)\t\t\t\t\t\t\\\nstatic int\t\t\t\t\t\t\t\t\\\nn##_ctl(const size_t *mib, size_t miblen, void *oldp, size_t *oldlenp,\t\\\n    void *newp, size_t newlen)\t\t\t\t\t\t\\\n{\t\t\t\t\t\t\t\t\t\\\n\tint ret;\t\t\t\t\t\t\t\\\n\tt oldval;\t\t\t\t\t\t\t\\\n\t\t\t\t\t\t\t\t\t\\\n\tif (!(c))\t\t\t\t\t\t\t\\\n\t\treturn (ENOENT);\t\t\t\t\t\\\n\tmalloc_mutex_lock(&ctl_mtx);\t\t\t\t\t\\\n\tREADONLY();\t\t\t\t\t\t\t\\\n\toldval = (v);\t\t\t\t\t\t\t\\\n\tREAD(oldval, t);\t\t\t\t\t\t\\\n\t\t\t\t\t\t\t\t\t\\\n\tret = 0;\t\t\t\t\t\t\t\\\nlabel_return:\t\t\t\t\t\t\t\t\\\n\tmalloc_mutex_unlock(&ctl_mtx);\t\t\t\t\t\\\n\treturn (ret);\t\t\t\t\t\t\t\\\n}\n\n#define\tCTL_RO_GEN(n, v, t)\t\t\t\t\t\t\\\nstatic int\t\t\t\t\t\t\t\t\\\nn##_ctl(const size_t *mib, size_t miblen, void *oldp, size_t *oldlenp,\t\\\n    void *newp, size_t newlen)\t\t\t\t\t\t\\\n{\t\t\t\t\t\t\t\t\t\\\n\tint ret;\t\t\t\t\t\t\t\\\n\tt oldval;\t\t\t\t\t\t\t\\\n\t\t\t\t\t\t\t\t\t\\\n\tmalloc_mutex_lock(&ctl_mtx);\t\t\t\t\t\\\n\tREADONLY();\t\t\t\t\t\t\t\\\n\toldval = (v);\t\t\t\t\t\t\t\\\n\tREAD(oldval, t);\t\t\t\t\t\t\\\n\t\t\t\t\t\t\t\t\t\\\n\tret = 0;\t\t\t\t\t\t\t\\\nlabel_return:\t\t\t\t\t\t\t\t\\\n\tmalloc_mutex_unlock(&ctl_mtx);\t\t\t\t\t\\\n\treturn (ret);\t\t\t\t\t\t\t\\\n}\n\n/*\n * ctl_mtx is not acquired, under the assumption that no pertinent data will\n * mutate during the call.\n */\n#define\tCTL_RO_NL_CGEN(c, n, v, t)\t\t\t\t\t\\\nstatic int\t\t\t\t\t\t\t\t\\\nn##_ctl(const size_t *mib, size_t miblen, void *oldp, size_t *oldlenp,\t\\\n    void *newp, size_t newlen)\t\t\t\t\t\t\\\n{\t\t\t\t\t\t\t\t\t\\\n\tint ret;\t\t\t\t\t\t\t\\\n\tt oldval;\t\t\t\t\t\t\t\\\n\t\t\t\t\t\t\t\t\t\\\n\tif (!(c))\t\t\t\t\t\t\t\\\n\t\treturn (ENOENT);\t\t\t\t\t\\\n\tREADONLY();\t\t\t\t\t\t\t\\\n\toldval = (v);\t\t\t\t\t\t\t\\\n\tREAD(oldval, t);\t\t\t\t\t\t\\\n\t\t\t\t\t\t\t\t\t\\\n\tret = 0;\t\t\t\t\t\t\t\\\nlabel_return:\t\t\t\t\t\t\t\t\\\n\treturn (ret);\t\t\t\t\t\t\t\\\n}\n\n#define\tCTL_RO_NL_GEN(n, v, t)\t\t\t\t\t\t\\\nstatic int\t\t\t\t\t\t\t\t\\\nn##_ctl(const size_t *mib, size_t miblen, void *oldp, size_t *oldlenp,\t\\\n    void *newp, size_t newlen)\t\t\t\t\t\t\\\n{\t\t\t\t\t\t\t\t\t\\\n\tint ret;\t\t\t\t\t\t\t\\\n\tt oldval;\t\t\t\t\t\t\t\\\n\t\t\t\t\t\t\t\t\t\\\n\tREADONLY();\t\t\t\t\t\t\t\\\n\toldval = (v);\t\t\t\t\t\t\t\\\n\tREAD(oldval, t);\t\t\t\t\t\t\\\n\t\t\t\t\t\t\t\t\t\\\n\tret = 0;\t\t\t\t\t\t\t\\\nlabel_return:\t\t\t\t\t\t\t\t\\\n\treturn (ret);\t\t\t\t\t\t\t\\\n}\n\n#define\tCTL_TSD_RO_NL_CGEN(c, n, m, t)\t\t\t\t\t\\\nstatic int\t\t\t\t\t\t\t\t\\\nn##_ctl(const size_t *mib, size_t miblen, void *oldp, size_t *oldlenp,\t\\\n    void *newp, size_t newlen)\t\t\t\t\t\t\\\n{\t\t\t\t\t\t\t\t\t\\\n\tint ret;\t\t\t\t\t\t\t\\\n\tt oldval;\t\t\t\t\t\t\t\\\n\ttsd_t *tsd;\t\t\t\t\t\t\t\\\n\t\t\t\t\t\t\t\t\t\\\n\tif (!(c))\t\t\t\t\t\t\t\\\n\t\treturn (ENOENT);\t\t\t\t\t\\\n\tREADONLY();\t\t\t\t\t\t\t\\\n\ttsd = tsd_fetch();\t\t\t\t\t\t\\\n\toldval = (m(tsd));\t\t\t\t\t\t\\\n\tREAD(oldval, t);\t\t\t\t\t\t\\\n\t\t\t\t\t\t\t\t\t\\\n\tret = 0;\t\t\t\t\t\t\t\\\nlabel_return:\t\t\t\t\t\t\t\t\\\n\treturn (ret);\t\t\t\t\t\t\t\\\n}\n\n#define\tCTL_RO_BOOL_CONFIG_GEN(n)\t\t\t\t\t\\\nstatic int\t\t\t\t\t\t\t\t\\\nn##_ctl(const size_t *mib, size_t miblen, void *oldp, size_t *oldlenp,\t\\\n    void *newp, size_t newlen)\t\t\t\t\t\t\\\n{\t\t\t\t\t\t\t\t\t\\\n\tint ret;\t\t\t\t\t\t\t\\\n\tbool oldval;\t\t\t\t\t\t\t\\\n\t\t\t\t\t\t\t\t\t\\\n\tREADONLY();\t\t\t\t\t\t\t\\\n\toldval = n;\t\t\t\t\t\t\t\\\n\tREAD(oldval, bool);\t\t\t\t\t\t\\\n\t\t\t\t\t\t\t\t\t\\\n\tret = 0;\t\t\t\t\t\t\t\\\nlabel_return:\t\t\t\t\t\t\t\t\\\n\treturn (ret);\t\t\t\t\t\t\t\\\n}\n\n/******************************************************************************/\n\nCTL_RO_NL_GEN(version, JEMALLOC_VERSION, const char *)\n\nstatic int\nepoch_ctl(const size_t *mib, size_t miblen, void *oldp, size_t *oldlenp,\n    void *newp, size_t newlen)\n{\n\tint ret;\n\tUNUSED uint64_t newval;\n\n\tmalloc_mutex_lock(&ctl_mtx);\n\tWRITE(newval, uint64_t);\n\tif (newp != NULL)\n\t\tctl_refresh();\n\tREAD(ctl_epoch, uint64_t);\n\n\tret = 0;\nlabel_return:\n\tmalloc_mutex_unlock(&ctl_mtx);\n\treturn (ret);\n}\n\n/******************************************************************************/\n\nCTL_RO_BOOL_CONFIG_GEN(config_cache_oblivious)\nCTL_RO_BOOL_CONFIG_GEN(config_debug)\nCTL_RO_BOOL_CONFIG_GEN(config_fill)\nCTL_RO_BOOL_CONFIG_GEN(config_lazy_lock)\nCTL_RO_BOOL_CONFIG_GEN(config_munmap)\nCTL_RO_BOOL_CONFIG_GEN(config_prof)\nCTL_RO_BOOL_CONFIG_GEN(config_prof_libgcc)\nCTL_RO_BOOL_CONFIG_GEN(config_prof_libunwind)\nCTL_RO_BOOL_CONFIG_GEN(config_stats)\nCTL_RO_BOOL_CONFIG_GEN(config_tcache)\nCTL_RO_BOOL_CONFIG_GEN(config_tls)\nCTL_RO_BOOL_CONFIG_GEN(config_utrace)\nCTL_RO_BOOL_CONFIG_GEN(config_valgrind)\nCTL_RO_BOOL_CONFIG_GEN(config_xmalloc)\n\n/******************************************************************************/\n\nCTL_RO_NL_GEN(opt_abort, opt_abort, bool)\nCTL_RO_NL_GEN(opt_dss, opt_dss, const char *)\nCTL_RO_NL_GEN(opt_lg_chunk, opt_lg_chunk, size_t)\nCTL_RO_NL_GEN(opt_narenas, opt_narenas, size_t)\nCTL_RO_NL_GEN(opt_lg_dirty_mult, opt_lg_dirty_mult, ssize_t)\nCTL_RO_NL_GEN(opt_stats_print, opt_stats_print, bool)\nCTL_RO_NL_CGEN(config_fill, opt_junk, opt_junk, const char *)\nCTL_RO_NL_CGEN(config_fill, opt_quarantine, opt_quarantine, size_t)\nCTL_RO_NL_CGEN(config_fill, opt_redzone, opt_redzone, bool)\nCTL_RO_NL_CGEN(config_fill, opt_zero, opt_zero, bool)\nCTL_RO_NL_CGEN(config_utrace, opt_utrace, opt_utrace, bool)\nCTL_RO_NL_CGEN(config_xmalloc, opt_xmalloc, opt_xmalloc, bool)\nCTL_RO_NL_CGEN(config_tcache, opt_tcache, opt_tcache, bool)\nCTL_RO_NL_CGEN(config_tcache, opt_lg_tcache_max, opt_lg_tcache_max, ssize_t)\nCTL_RO_NL_CGEN(config_prof, opt_prof, opt_prof, bool)\nCTL_RO_NL_CGEN(config_prof, opt_prof_prefix, opt_prof_prefix, const char *)\nCTL_RO_NL_CGEN(config_prof, opt_prof_active, opt_prof_active, bool)\nCTL_RO_NL_CGEN(config_prof, opt_prof_thread_active_init,\n    opt_prof_thread_active_init, bool)\nCTL_RO_NL_CGEN(config_prof, opt_lg_prof_sample, opt_lg_prof_sample, size_t)\nCTL_RO_NL_CGEN(config_prof, opt_prof_accum, opt_prof_accum, bool)\nCTL_RO_NL_CGEN(config_prof, opt_lg_prof_interval, opt_lg_prof_interval, ssize_t)\nCTL_RO_NL_CGEN(config_prof, opt_prof_gdump, opt_prof_gdump, bool)\nCTL_RO_NL_CGEN(config_prof, opt_prof_final, opt_prof_final, bool)\nCTL_RO_NL_CGEN(config_prof, opt_prof_leak, opt_prof_leak, bool)\n\n/******************************************************************************/\n\nstatic int\nthread_arena_ctl(const size_t *mib, size_t miblen, void *oldp, size_t *oldlenp,\n    void *newp, size_t newlen)\n{\n\tint ret;\n\ttsd_t *tsd;\n\tarena_t *oldarena;\n\tunsigned newind, oldind;\n\n\ttsd = tsd_fetch();\n\toldarena = arena_choose(tsd, NULL);\n\tif (oldarena == NULL)\n\t\treturn (EAGAIN);\n\n\tmalloc_mutex_lock(&ctl_mtx);\n\tnewind = oldind = oldarena->ind;\n\tWRITE(newind, unsigned);\n\tREAD(oldind, unsigned);\n\tif (newind != oldind) {\n\t\tarena_t *newarena;\n\n\t\tif (newind >= ctl_stats.narenas) {\n\t\t\t/* New arena index is out of range. */\n\t\t\tret = EFAULT;\n\t\t\tgoto label_return;\n\t\t}\n\n\t\t/* Initialize arena if necessary. */\n\t\tnewarena = arena_get(tsd, newind, true, true);\n\t\tif (newarena == NULL) {\n\t\t\tret = EAGAIN;\n\t\t\tgoto label_return;\n\t\t}\n\t\t/* Set new arena/tcache associations. */\n\t\tarena_migrate(tsd, oldind, newind);\n\t\tif (config_tcache) {\n\t\t\ttcache_t *tcache = tsd_tcache_get(tsd);\n\t\t\tif (tcache != NULL) {\n\t\t\t\ttcache_arena_reassociate(tcache, oldarena,\n\t\t\t\t    newarena);\n\t\t\t}\n\t\t}\n\t}\n\n\tret = 0;\nlabel_return:\n\tmalloc_mutex_unlock(&ctl_mtx);\n\treturn (ret);\n}\n\nCTL_TSD_RO_NL_CGEN(config_stats, thread_allocated, tsd_thread_allocated_get,\n    uint64_t)\nCTL_TSD_RO_NL_CGEN(config_stats, thread_allocatedp, tsd_thread_allocatedp_get,\n    uint64_t *)\nCTL_TSD_RO_NL_CGEN(config_stats, thread_deallocated, tsd_thread_deallocated_get,\n    uint64_t)\nCTL_TSD_RO_NL_CGEN(config_stats, thread_deallocatedp,\n    tsd_thread_deallocatedp_get, uint64_t *)\n\nstatic int\nthread_tcache_enabled_ctl(const size_t *mib, size_t miblen, void *oldp,\n    size_t *oldlenp, void *newp, size_t newlen)\n{\n\tint ret;\n\tbool oldval;\n\n\tif (!config_tcache)\n\t\treturn (ENOENT);\n\n\toldval = tcache_enabled_get();\n\tif (newp != NULL) {\n\t\tif (newlen != sizeof(bool)) {\n\t\t\tret = EINVAL;\n\t\t\tgoto label_return;\n\t\t}\n\t\ttcache_enabled_set(*(bool *)newp);\n\t}\n\tREAD(oldval, bool);\n\n\tret = 0;\nlabel_return:\n\treturn (ret);\n}\n\nstatic int\nthread_tcache_flush_ctl(const size_t *mib, size_t miblen, void *oldp,\n    size_t *oldlenp, void *newp, size_t newlen)\n{\n\tint ret;\n\n\tif (!config_tcache)\n\t\treturn (ENOENT);\n\n\tREADONLY();\n\tWRITEONLY();\n\n\ttcache_flush();\n\n\tret = 0;\nlabel_return:\n\treturn (ret);\n}\n\nstatic int\nthread_prof_name_ctl(const size_t *mib, size_t miblen, void *oldp,\n    size_t *oldlenp, void *newp, size_t newlen)\n{\n\tint ret;\n\n\tif (!config_prof)\n\t\treturn (ENOENT);\n\n\tREAD_XOR_WRITE();\n\n\tif (newp != NULL) {\n\t\ttsd_t *tsd;\n\n\t\tif (newlen != sizeof(const char *)) {\n\t\t\tret = EINVAL;\n\t\t\tgoto label_return;\n\t\t}\n\n\t\ttsd = tsd_fetch();\n\n\t\tif ((ret = prof_thread_name_set(tsd, *(const char **)newp)) !=\n\t\t    0)\n\t\t\tgoto label_return;\n\t} else {\n\t\tconst char *oldname = prof_thread_name_get();\n\t\tREAD(oldname, const char *);\n\t}\n\n\tret = 0;\nlabel_return:\n\treturn (ret);\n}\n\nstatic int\nthread_prof_active_ctl(const size_t *mib, size_t miblen, void *oldp,\n    size_t *oldlenp, void *newp, size_t newlen)\n{\n\tint ret;\n\tbool oldval;\n\n\tif (!config_prof)\n\t\treturn (ENOENT);\n\n\toldval = prof_thread_active_get();\n\tif (newp != NULL) {\n\t\tif (newlen != sizeof(bool)) {\n\t\t\tret = EINVAL;\n\t\t\tgoto label_return;\n\t\t}\n\t\tif (prof_thread_active_set(*(bool *)newp)) {\n\t\t\tret = EAGAIN;\n\t\t\tgoto label_return;\n\t\t}\n\t}\n\tREAD(oldval, bool);\n\n\tret = 0;\nlabel_return:\n\treturn (ret);\n}\n\n/******************************************************************************/\n\nstatic int\ntcache_create_ctl(const size_t *mib, size_t miblen, void *oldp, size_t *oldlenp,\n    void *newp, size_t newlen)\n{\n\tint ret;\n\ttsd_t *tsd;\n\tunsigned tcache_ind;\n\n\tif (!config_tcache)\n\t\treturn (ENOENT);\n\n\ttsd = tsd_fetch();\n\n\tmalloc_mutex_lock(&ctl_mtx);\n\tREADONLY();\n\tif (tcaches_create(tsd, &tcache_ind)) {\n\t\tret = EFAULT;\n\t\tgoto label_return;\n\t}\n\tREAD(tcache_ind, unsigned);\n\n\tret = 0;\nlabel_return:\n\tmalloc_mutex_unlock(&ctl_mtx);\n\treturn (ret);\n}\n\nstatic int\ntcache_flush_ctl(const size_t *mib, size_t miblen, void *oldp, size_t *oldlenp,\n    void *newp, size_t newlen)\n{\n\tint ret;\n\ttsd_t *tsd;\n\tunsigned tcache_ind;\n\n\tif (!config_tcache)\n\t\treturn (ENOENT);\n\n\ttsd = tsd_fetch();\n\n\tWRITEONLY();\n\ttcache_ind = UINT_MAX;\n\tWRITE(tcache_ind, unsigned);\n\tif (tcache_ind == UINT_MAX) {\n\t\tret = EFAULT;\n\t\tgoto label_return;\n\t}\n\ttcaches_flush(tsd, tcache_ind);\n\n\tret = 0;\nlabel_return:\n\treturn (ret);\n}\n\nstatic int\ntcache_destroy_ctl(const size_t *mib, size_t miblen, void *oldp,\n    size_t *oldlenp, void *newp, size_t newlen)\n{\n\tint ret;\n\ttsd_t *tsd;\n\tunsigned tcache_ind;\n\n\tif (!config_tcache)\n\t\treturn (ENOENT);\n\n\ttsd = tsd_fetch();\n\n\tWRITEONLY();\n\ttcache_ind = UINT_MAX;\n\tWRITE(tcache_ind, unsigned);\n\tif (tcache_ind == UINT_MAX) {\n\t\tret = EFAULT;\n\t\tgoto label_return;\n\t}\n\ttcaches_destroy(tsd, tcache_ind);\n\n\tret = 0;\nlabel_return:\n\treturn (ret);\n}\n\n/******************************************************************************/\n\n/* ctl_mutex must be held during execution of this function. */\nstatic void\narena_purge(unsigned arena_ind)\n{\n\ttsd_t *tsd;\n\tunsigned i;\n\tbool refreshed;\n\tVARIABLE_ARRAY(arena_t *, tarenas, ctl_stats.narenas);\n\n\ttsd = tsd_fetch();\n\tfor (i = 0, refreshed = false; i < ctl_stats.narenas; i++) {\n\t\ttarenas[i] = arena_get(tsd, i, false, false);\n\t\tif (tarenas[i] == NULL && !refreshed) {\n\t\t\ttarenas[i] = arena_get(tsd, i, false, true);\n\t\t\trefreshed = true;\n\t\t}\n\t}\n\n\tif (arena_ind == ctl_stats.narenas) {\n\t\tunsigned i;\n\t\tfor (i = 0; i < ctl_stats.narenas; i++) {\n\t\t\tif (tarenas[i] != NULL)\n\t\t\t\tarena_purge_all(tarenas[i]);\n\t\t}\n\t} else {\n\t\tassert(arena_ind < ctl_stats.narenas);\n\t\tif (tarenas[arena_ind] != NULL)\n\t\t\tarena_purge_all(tarenas[arena_ind]);\n\t}\n}\n\nstatic int\narena_i_purge_ctl(const size_t *mib, size_t miblen, void *oldp, size_t *oldlenp,\n    void *newp, size_t newlen)\n{\n\tint ret;\n\n\tREADONLY();\n\tWRITEONLY();\n\tmalloc_mutex_lock(&ctl_mtx);\n\tarena_purge(mib[1]);\n\tmalloc_mutex_unlock(&ctl_mtx);\n\n\tret = 0;\nlabel_return:\n\treturn (ret);\n}\n\nstatic int\narena_i_dss_ctl(const size_t *mib, size_t miblen, void *oldp, size_t *oldlenp,\n    void *newp, size_t newlen)\n{\n\tint ret;\n\tconst char *dss = NULL;\n\tunsigned arena_ind = mib[1];\n\tdss_prec_t dss_prec_old = dss_prec_limit;\n\tdss_prec_t dss_prec = dss_prec_limit;\n\n\tmalloc_mutex_lock(&ctl_mtx);\n\tWRITE(dss, const char *);\n\tif (dss != NULL) {\n\t\tint i;\n\t\tbool match = false;\n\n\t\tfor (i = 0; i < dss_prec_limit; i++) {\n\t\t\tif (strcmp(dss_prec_names[i], dss) == 0) {\n\t\t\t\tdss_prec = i;\n\t\t\t\tmatch = true;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\n\t\tif (!match) {\n\t\t\tret = EINVAL;\n\t\t\tgoto label_return;\n\t\t}\n\t}\n\n\tif (arena_ind < ctl_stats.narenas) {\n\t\tarena_t *arena = arena_get(tsd_fetch(), arena_ind, false, true);\n\t\tif (arena == NULL || (dss_prec != dss_prec_limit &&\n\t\t    arena_dss_prec_set(arena, dss_prec))) {\n\t\t\tret = EFAULT;\n\t\t\tgoto label_return;\n\t\t}\n\t\tdss_prec_old = arena_dss_prec_get(arena);\n\t} else {\n\t\tif (dss_prec != dss_prec_limit &&\n\t\t    chunk_dss_prec_set(dss_prec)) {\n\t\t\tret = EFAULT;\n\t\t\tgoto label_return;\n\t\t}\n\t\tdss_prec_old = chunk_dss_prec_get();\n\t}\n\n\tdss = dss_prec_names[dss_prec_old];\n\tREAD(dss, const char *);\n\n\tret = 0;\nlabel_return:\n\tmalloc_mutex_unlock(&ctl_mtx);\n\treturn (ret);\n}\n\nstatic int\narena_i_lg_dirty_mult_ctl(const size_t *mib, size_t miblen, void *oldp,\n    size_t *oldlenp, void *newp, size_t newlen)\n{\n\tint ret;\n\tunsigned arena_ind = mib[1];\n\tarena_t *arena;\n\n\tarena = arena_get(tsd_fetch(), arena_ind, false, true);\n\tif (arena == NULL) {\n\t\tret = EFAULT;\n\t\tgoto label_return;\n\t}\n\n\tif (oldp != NULL && oldlenp != NULL) {\n\t\tsize_t oldval = arena_lg_dirty_mult_get(arena);\n\t\tREAD(oldval, ssize_t);\n\t}\n\tif (newp != NULL) {\n\t\tif (newlen != sizeof(ssize_t)) {\n\t\t\tret = EINVAL;\n\t\t\tgoto label_return;\n\t\t}\n\t\tif (arena_lg_dirty_mult_set(arena, *(ssize_t *)newp)) {\n\t\t\tret = EFAULT;\n\t\t\tgoto label_return;\n\t\t}\n\t}\n\n\tret = 0;\nlabel_return:\n\treturn (ret);\n}\n\nstatic int\narena_i_chunk_hooks_ctl(const size_t *mib, size_t miblen, void *oldp,\n    size_t *oldlenp, void *newp, size_t newlen)\n{\n\tint ret;\n\tunsigned arena_ind = mib[1];\n\tarena_t *arena;\n\n\tmalloc_mutex_lock(&ctl_mtx);\n\tif (arena_ind < narenas_total_get() && (arena =\n\t    arena_get(tsd_fetch(), arena_ind, false, true)) != NULL) {\n\t\tif (newp != NULL) {\n\t\t\tchunk_hooks_t old_chunk_hooks, new_chunk_hooks;\n\t\t\tWRITE(new_chunk_hooks, chunk_hooks_t);\n\t\t\told_chunk_hooks = chunk_hooks_set(arena,\n\t\t\t    &new_chunk_hooks);\n\t\t\tREAD(old_chunk_hooks, chunk_hooks_t);\n\t\t} else {\n\t\t\tchunk_hooks_t old_chunk_hooks = chunk_hooks_get(arena);\n\t\t\tREAD(old_chunk_hooks, chunk_hooks_t);\n\t\t}\n\t} else {\n\t\tret = EFAULT;\n\t\tgoto label_return;\n\t}\n\tret = 0;\nlabel_return:\n\tmalloc_mutex_unlock(&ctl_mtx);\n\treturn (ret);\n}\n\nstatic const ctl_named_node_t *\narena_i_index(const size_t *mib, size_t miblen, size_t i)\n{\n\tconst ctl_named_node_t * ret;\n\n\tmalloc_mutex_lock(&ctl_mtx);\n\tif (i > ctl_stats.narenas) {\n\t\tret = NULL;\n\t\tgoto label_return;\n\t}\n\n\tret = super_arena_i_node;\nlabel_return:\n\tmalloc_mutex_unlock(&ctl_mtx);\n\treturn (ret);\n}\n\n/******************************************************************************/\n\nstatic int\narenas_narenas_ctl(const size_t *mib, size_t miblen, void *oldp,\n    size_t *oldlenp, void *newp, size_t newlen)\n{\n\tint ret;\n\tunsigned narenas;\n\n\tmalloc_mutex_lock(&ctl_mtx);\n\tREADONLY();\n\tif (*oldlenp != sizeof(unsigned)) {\n\t\tret = EINVAL;\n\t\tgoto label_return;\n\t}\n\tnarenas = ctl_stats.narenas;\n\tREAD(narenas, unsigned);\n\n\tret = 0;\nlabel_return:\n\tmalloc_mutex_unlock(&ctl_mtx);\n\treturn (ret);\n}\n\nstatic int\narenas_initialized_ctl(const size_t *mib, size_t miblen, void *oldp,\n    size_t *oldlenp, void *newp, size_t newlen)\n{\n\tint ret;\n\tunsigned nread, i;\n\n\tmalloc_mutex_lock(&ctl_mtx);\n\tREADONLY();\n\tif (*oldlenp != ctl_stats.narenas * sizeof(bool)) {\n\t\tret = EINVAL;\n\t\tnread = (*oldlenp < ctl_stats.narenas * sizeof(bool))\n\t\t    ? (*oldlenp / sizeof(bool)) : ctl_stats.narenas;\n\t} else {\n\t\tret = 0;\n\t\tnread = ctl_stats.narenas;\n\t}\n\n\tfor (i = 0; i < nread; i++)\n\t\t((bool *)oldp)[i] = ctl_stats.arenas[i].initialized;\n\nlabel_return:\n\tmalloc_mutex_unlock(&ctl_mtx);\n\treturn (ret);\n}\n\nstatic int\narenas_lg_dirty_mult_ctl(const size_t *mib, size_t miblen, void *oldp,\n    size_t *oldlenp, void *newp, size_t newlen)\n{\n\tint ret;\n\n\tif (oldp != NULL && oldlenp != NULL) {\n\t\tsize_t oldval = arena_lg_dirty_mult_default_get();\n\t\tREAD(oldval, ssize_t);\n\t}\n\tif (newp != NULL) {\n\t\tif (newlen != sizeof(ssize_t)) {\n\t\t\tret = EINVAL;\n\t\t\tgoto label_return;\n\t\t}\n\t\tif (arena_lg_dirty_mult_default_set(*(ssize_t *)newp)) {\n\t\t\tret = EFAULT;\n\t\t\tgoto label_return;\n\t\t}\n\t}\n\n\tret = 0;\nlabel_return:\n\treturn (ret);\n}\n\nCTL_RO_NL_GEN(arenas_quantum, QUANTUM, size_t)\nCTL_RO_NL_GEN(arenas_page, PAGE, size_t)\nCTL_RO_NL_CGEN(config_tcache, arenas_tcache_max, tcache_maxclass, size_t)\nCTL_RO_NL_GEN(arenas_nbins, NBINS, unsigned)\nCTL_RO_NL_CGEN(config_tcache, arenas_nhbins, nhbins, unsigned)\nCTL_RO_NL_GEN(arenas_bin_i_size, arena_bin_info[mib[2]].reg_size, size_t)\nCTL_RO_NL_GEN(arenas_bin_i_nregs, arena_bin_info[mib[2]].nregs, uint32_t)\nCTL_RO_NL_GEN(arenas_bin_i_run_size, arena_bin_info[mib[2]].run_size, size_t)\nstatic const ctl_named_node_t *\narenas_bin_i_index(const size_t *mib, size_t miblen, size_t i)\n{\n\n\tif (i > NBINS)\n\t\treturn (NULL);\n\treturn (super_arenas_bin_i_node);\n}\n\nCTL_RO_NL_GEN(arenas_nlruns, nlclasses, unsigned)\nCTL_RO_NL_GEN(arenas_lrun_i_size, index2size(NBINS+mib[2]), size_t)\nstatic const ctl_named_node_t *\narenas_lrun_i_index(const size_t *mib, size_t miblen, size_t i)\n{\n\n\tif (i > nlclasses)\n\t\treturn (NULL);\n\treturn (super_arenas_lrun_i_node);\n}\n\nCTL_RO_NL_GEN(arenas_nhchunks, nhclasses, unsigned)\nCTL_RO_NL_GEN(arenas_hchunk_i_size, index2size(NBINS+nlclasses+mib[2]), size_t)\nstatic const ctl_named_node_t *\narenas_hchunk_i_index(const size_t *mib, size_t miblen, size_t i)\n{\n\n\tif (i > nhclasses)\n\t\treturn (NULL);\n\treturn (super_arenas_hchunk_i_node);\n}\n\nstatic int\narenas_extend_ctl(const size_t *mib, size_t miblen, void *oldp, size_t *oldlenp,\n    void *newp, size_t newlen)\n{\n\tint ret;\n\tunsigned narenas;\n\n\tmalloc_mutex_lock(&ctl_mtx);\n\tREADONLY();\n\tif (ctl_grow()) {\n\t\tret = EAGAIN;\n\t\tgoto label_return;\n\t}\n\tnarenas = ctl_stats.narenas - 1;\n\tREAD(narenas, unsigned);\n\n\tret = 0;\nlabel_return:\n\tmalloc_mutex_unlock(&ctl_mtx);\n\treturn (ret);\n}\n\n/******************************************************************************/\n\nstatic int\nprof_thread_active_init_ctl(const size_t *mib, size_t miblen, void *oldp,\n    size_t *oldlenp, void *newp, size_t newlen)\n{\n\tint ret;\n\tbool oldval;\n\n\tif (!config_prof)\n\t\treturn (ENOENT);\n\n\tif (newp != NULL) {\n\t\tif (newlen != sizeof(bool)) {\n\t\t\tret = EINVAL;\n\t\t\tgoto label_return;\n\t\t}\n\t\toldval = prof_thread_active_init_set(*(bool *)newp);\n\t} else\n\t\toldval = prof_thread_active_init_get();\n\tREAD(oldval, bool);\n\n\tret = 0;\nlabel_return:\n\treturn (ret);\n}\n\nstatic int\nprof_active_ctl(const size_t *mib, size_t miblen, void *oldp, size_t *oldlenp,\n    void *newp, size_t newlen)\n{\n\tint ret;\n\tbool oldval;\n\n\tif (!config_prof)\n\t\treturn (ENOENT);\n\n\tif (newp != NULL) {\n\t\tif (newlen != sizeof(bool)) {\n\t\t\tret = EINVAL;\n\t\t\tgoto label_return;\n\t\t}\n\t\toldval = prof_active_set(*(bool *)newp);\n\t} else\n\t\toldval = prof_active_get();\n\tREAD(oldval, bool);\n\n\tret = 0;\nlabel_return:\n\treturn (ret);\n}\n\nstatic int\nprof_dump_ctl(const size_t *mib, size_t miblen, void *oldp, size_t *oldlenp,\n    void *newp, size_t newlen)\n{\n\tint ret;\n\tconst char *filename = NULL;\n\n\tif (!config_prof)\n\t\treturn (ENOENT);\n\n\tWRITEONLY();\n\tWRITE(filename, const char *);\n\n\tif (prof_mdump(filename)) {\n\t\tret = EFAULT;\n\t\tgoto label_return;\n\t}\n\n\tret = 0;\nlabel_return:\n\treturn (ret);\n}\n\nstatic int\nprof_gdump_ctl(const size_t *mib, size_t miblen, void *oldp, size_t *oldlenp,\n    void *newp, size_t newlen)\n{\n\tint ret;\n\tbool oldval;\n\n\tif (!config_prof)\n\t\treturn (ENOENT);\n\n\tif (newp != NULL) {\n\t\tif (newlen != sizeof(bool)) {\n\t\t\tret = EINVAL;\n\t\t\tgoto label_return;\n\t\t}\n\t\toldval = prof_gdump_set(*(bool *)newp);\n\t} else\n\t\toldval = prof_gdump_get();\n\tREAD(oldval, bool);\n\n\tret = 0;\nlabel_return:\n\treturn (ret);\n}\n\nstatic int\nprof_reset_ctl(const size_t *mib, size_t miblen, void *oldp, size_t *oldlenp,\n    void *newp, size_t newlen)\n{\n\tint ret;\n\tsize_t lg_sample = lg_prof_sample;\n\ttsd_t *tsd;\n\n\tif (!config_prof)\n\t\treturn (ENOENT);\n\n\tWRITEONLY();\n\tWRITE(lg_sample, size_t);\n\tif (lg_sample >= (sizeof(uint64_t) << 3))\n\t\tlg_sample = (sizeof(uint64_t) << 3) - 1;\n\n\ttsd = tsd_fetch();\n\n\tprof_reset(tsd, lg_sample);\n\n\tret = 0;\nlabel_return:\n\treturn (ret);\n}\n\nCTL_RO_NL_CGEN(config_prof, prof_interval, prof_interval, uint64_t)\nCTL_RO_NL_CGEN(config_prof, lg_prof_sample, lg_prof_sample, size_t)\n\n/******************************************************************************/\n\nCTL_RO_CGEN(config_stats, stats_cactive, &stats_cactive, size_t *)\nCTL_RO_CGEN(config_stats, stats_allocated, ctl_stats.allocated, size_t)\nCTL_RO_CGEN(config_stats, stats_active, ctl_stats.active, size_t)\nCTL_RO_CGEN(config_stats, stats_metadata, ctl_stats.metadata, size_t)\nCTL_RO_CGEN(config_stats, stats_resident, ctl_stats.resident, size_t)\nCTL_RO_CGEN(config_stats, stats_mapped, ctl_stats.mapped, size_t)\n\nCTL_RO_GEN(stats_arenas_i_dss, ctl_stats.arenas[mib[2]].dss, const char *)\nCTL_RO_GEN(stats_arenas_i_lg_dirty_mult, ctl_stats.arenas[mib[2]].lg_dirty_mult,\n    ssize_t)\nCTL_RO_GEN(stats_arenas_i_nthreads, ctl_stats.arenas[mib[2]].nthreads, unsigned)\nCTL_RO_GEN(stats_arenas_i_pactive, ctl_stats.arenas[mib[2]].pactive, size_t)\nCTL_RO_GEN(stats_arenas_i_pdirty, ctl_stats.arenas[mib[2]].pdirty, size_t)\nCTL_RO_CGEN(config_stats, stats_arenas_i_mapped,\n    ctl_stats.arenas[mib[2]].astats.mapped, size_t)\nCTL_RO_CGEN(config_stats, stats_arenas_i_npurge,\n    ctl_stats.arenas[mib[2]].astats.npurge, uint64_t)\nCTL_RO_CGEN(config_stats, stats_arenas_i_nmadvise,\n    ctl_stats.arenas[mib[2]].astats.nmadvise, uint64_t)\nCTL_RO_CGEN(config_stats, stats_arenas_i_purged,\n    ctl_stats.arenas[mib[2]].astats.purged, uint64_t)\nCTL_RO_CGEN(config_stats, stats_arenas_i_metadata_mapped,\n    ctl_stats.arenas[mib[2]].astats.metadata_mapped, size_t)\nCTL_RO_CGEN(config_stats, stats_arenas_i_metadata_allocated,\n    ctl_stats.arenas[mib[2]].astats.metadata_allocated, size_t)\n\nCTL_RO_CGEN(config_stats, stats_arenas_i_small_allocated,\n    ctl_stats.arenas[mib[2]].allocated_small, size_t)\nCTL_RO_CGEN(config_stats, stats_arenas_i_small_nmalloc,\n    ctl_stats.arenas[mib[2]].nmalloc_small, uint64_t)\nCTL_RO_CGEN(config_stats, stats_arenas_i_small_ndalloc,\n    ctl_stats.arenas[mib[2]].ndalloc_small, uint64_t)\nCTL_RO_CGEN(config_stats, stats_arenas_i_small_nrequests,\n    ctl_stats.arenas[mib[2]].nrequests_small, uint64_t)\nCTL_RO_CGEN(config_stats, stats_arenas_i_large_allocated,\n    ctl_stats.arenas[mib[2]].astats.allocated_large, size_t)\nCTL_RO_CGEN(config_stats, stats_arenas_i_large_nmalloc,\n    ctl_stats.arenas[mib[2]].astats.nmalloc_large, uint64_t)\nCTL_RO_CGEN(config_stats, stats_arenas_i_large_ndalloc,\n    ctl_stats.arenas[mib[2]].astats.ndalloc_large, uint64_t)\nCTL_RO_CGEN(config_stats, stats_arenas_i_large_nrequests,\n    ctl_stats.arenas[mib[2]].astats.nrequests_large, uint64_t)\nCTL_RO_CGEN(config_stats, stats_arenas_i_huge_allocated,\n    ctl_stats.arenas[mib[2]].astats.allocated_huge, size_t)\nCTL_RO_CGEN(config_stats, stats_arenas_i_huge_nmalloc,\n    ctl_stats.arenas[mib[2]].astats.nmalloc_huge, uint64_t)\nCTL_RO_CGEN(config_stats, stats_arenas_i_huge_ndalloc,\n    ctl_stats.arenas[mib[2]].astats.ndalloc_huge, uint64_t)\nCTL_RO_CGEN(config_stats, stats_arenas_i_huge_nrequests,\n    ctl_stats.arenas[mib[2]].astats.nmalloc_huge, uint64_t) /* Intentional. */\n\nCTL_RO_CGEN(config_stats, stats_arenas_i_bins_j_nmalloc,\n    ctl_stats.arenas[mib[2]].bstats[mib[4]].nmalloc, uint64_t)\nCTL_RO_CGEN(config_stats, stats_arenas_i_bins_j_ndalloc,\n    ctl_stats.arenas[mib[2]].bstats[mib[4]].ndalloc, uint64_t)\nCTL_RO_CGEN(config_stats, stats_arenas_i_bins_j_nrequests,\n    ctl_stats.arenas[mib[2]].bstats[mib[4]].nrequests, uint64_t)\nCTL_RO_CGEN(config_stats, stats_arenas_i_bins_j_curregs,\n    ctl_stats.arenas[mib[2]].bstats[mib[4]].curregs, size_t)\nCTL_RO_CGEN(config_stats && config_tcache, stats_arenas_i_bins_j_nfills,\n    ctl_stats.arenas[mib[2]].bstats[mib[4]].nfills, uint64_t)\nCTL_RO_CGEN(config_stats && config_tcache, stats_arenas_i_bins_j_nflushes,\n    ctl_stats.arenas[mib[2]].bstats[mib[4]].nflushes, uint64_t)\nCTL_RO_CGEN(config_stats, stats_arenas_i_bins_j_nruns,\n    ctl_stats.arenas[mib[2]].bstats[mib[4]].nruns, uint64_t)\nCTL_RO_CGEN(config_stats, stats_arenas_i_bins_j_nreruns,\n    ctl_stats.arenas[mib[2]].bstats[mib[4]].reruns, uint64_t)\nCTL_RO_CGEN(config_stats, stats_arenas_i_bins_j_curruns,\n    ctl_stats.arenas[mib[2]].bstats[mib[4]].curruns, size_t)\n\nstatic const ctl_named_node_t *\nstats_arenas_i_bins_j_index(const size_t *mib, size_t miblen, size_t j)\n{\n\n\tif (j > NBINS)\n\t\treturn (NULL);\n\treturn (super_stats_arenas_i_bins_j_node);\n}\n\nCTL_RO_CGEN(config_stats, stats_arenas_i_lruns_j_nmalloc,\n    ctl_stats.arenas[mib[2]].lstats[mib[4]].nmalloc, uint64_t)\nCTL_RO_CGEN(config_stats, stats_arenas_i_lruns_j_ndalloc,\n    ctl_stats.arenas[mib[2]].lstats[mib[4]].ndalloc, uint64_t)\nCTL_RO_CGEN(config_stats, stats_arenas_i_lruns_j_nrequests,\n    ctl_stats.arenas[mib[2]].lstats[mib[4]].nrequests, uint64_t)\nCTL_RO_CGEN(config_stats, stats_arenas_i_lruns_j_curruns,\n    ctl_stats.arenas[mib[2]].lstats[mib[4]].curruns, size_t)\n\nstatic const ctl_named_node_t *\nstats_arenas_i_lruns_j_index(const size_t *mib, size_t miblen, size_t j)\n{\n\n\tif (j > nlclasses)\n\t\treturn (NULL);\n\treturn (super_stats_arenas_i_lruns_j_node);\n}\n\nCTL_RO_CGEN(config_stats, stats_arenas_i_hchunks_j_nmalloc,\n    ctl_stats.arenas[mib[2]].hstats[mib[4]].nmalloc, uint64_t)\nCTL_RO_CGEN(config_stats, stats_arenas_i_hchunks_j_ndalloc,\n    ctl_stats.arenas[mib[2]].hstats[mib[4]].ndalloc, uint64_t)\nCTL_RO_CGEN(config_stats, stats_arenas_i_hchunks_j_nrequests,\n    ctl_stats.arenas[mib[2]].hstats[mib[4]].nmalloc, /* Intentional. */\n    uint64_t)\nCTL_RO_CGEN(config_stats, stats_arenas_i_hchunks_j_curhchunks,\n    ctl_stats.arenas[mib[2]].hstats[mib[4]].curhchunks, size_t)\n\nstatic const ctl_named_node_t *\nstats_arenas_i_hchunks_j_index(const size_t *mib, size_t miblen, size_t j)\n{\n\n\tif (j > nhclasses)\n\t\treturn (NULL);\n\treturn (super_stats_arenas_i_hchunks_j_node);\n}\n\nstatic const ctl_named_node_t *\nstats_arenas_i_index(const size_t *mib, size_t miblen, size_t i)\n{\n\tconst ctl_named_node_t * ret;\n\n\tmalloc_mutex_lock(&ctl_mtx);\n\tif (i > ctl_stats.narenas || !ctl_stats.arenas[i].initialized) {\n\t\tret = NULL;\n\t\tgoto label_return;\n\t}\n\n\tret = super_stats_arenas_i_node;\nlabel_return:\n\tmalloc_mutex_unlock(&ctl_mtx);\n\treturn (ret);\n}\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.8/deps/jemalloc/src/extent.c",
    "content": "#define\tJEMALLOC_EXTENT_C_\n#include \"jemalloc/internal/jemalloc_internal.h\"\n\n/******************************************************************************/\n\nJEMALLOC_INLINE_C size_t\nextent_quantize(size_t size)\n{\n\n\t/*\n\t * Round down to the nearest chunk size that can actually be requested\n\t * during normal huge allocation.\n\t */\n\treturn (index2size(size2index(size + 1) - 1));\n}\n\nJEMALLOC_INLINE_C int\nextent_szad_comp(extent_node_t *a, extent_node_t *b)\n{\n\tint ret;\n\tsize_t a_qsize = extent_quantize(extent_node_size_get(a));\n\tsize_t b_qsize = extent_quantize(extent_node_size_get(b));\n\n\t/*\n\t * Compare based on quantized size rather than size, in order to sort\n\t * equally useful extents only by address.\n\t */\n\tret = (a_qsize > b_qsize) - (a_qsize < b_qsize);\n\tif (ret == 0) {\n\t\tuintptr_t a_addr = (uintptr_t)extent_node_addr_get(a);\n\t\tuintptr_t b_addr = (uintptr_t)extent_node_addr_get(b);\n\n\t\tret = (a_addr > b_addr) - (a_addr < b_addr);\n\t}\n\n\treturn (ret);\n}\n\n/* Generate red-black tree functions. */\nrb_gen(, extent_tree_szad_, extent_tree_t, extent_node_t, szad_link,\n    extent_szad_comp)\n\nJEMALLOC_INLINE_C int\nextent_ad_comp(extent_node_t *a, extent_node_t *b)\n{\n\tuintptr_t a_addr = (uintptr_t)extent_node_addr_get(a);\n\tuintptr_t b_addr = (uintptr_t)extent_node_addr_get(b);\n\n\treturn ((a_addr > b_addr) - (a_addr < b_addr));\n}\n\n/* Generate red-black tree functions. */\nrb_gen(, extent_tree_ad_, extent_tree_t, extent_node_t, ad_link, extent_ad_comp)\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.8/deps/jemalloc/src/hash.c",
    "content": "#define\tJEMALLOC_HASH_C_\n#include \"jemalloc/internal/jemalloc_internal.h\"\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.8/deps/jemalloc/src/huge.c",
    "content": "#define\tJEMALLOC_HUGE_C_\n#include \"jemalloc/internal/jemalloc_internal.h\"\n\n/******************************************************************************/\n\nstatic extent_node_t *\nhuge_node_get(const void *ptr)\n{\n\textent_node_t *node;\n\n\tnode = chunk_lookup(ptr, true);\n\tassert(!extent_node_achunk_get(node));\n\n\treturn (node);\n}\n\nstatic bool\nhuge_node_set(const void *ptr, extent_node_t *node)\n{\n\n\tassert(extent_node_addr_get(node) == ptr);\n\tassert(!extent_node_achunk_get(node));\n\treturn (chunk_register(ptr, node));\n}\n\nstatic void\nhuge_node_unset(const void *ptr, const extent_node_t *node)\n{\n\n\tchunk_deregister(ptr, node);\n}\n\nvoid *\nhuge_malloc(tsd_t *tsd, arena_t *arena, size_t size, bool zero,\n    tcache_t *tcache)\n{\n\tsize_t usize;\n\n\tusize = s2u(size);\n\tif (usize == 0) {\n\t\t/* size_t overflow. */\n\t\treturn (NULL);\n\t}\n\n\treturn (huge_palloc(tsd, arena, usize, chunksize, zero, tcache));\n}\n\nvoid *\nhuge_palloc(tsd_t *tsd, arena_t *arena, size_t size, size_t alignment,\n    bool zero, tcache_t *tcache)\n{\n\tvoid *ret;\n\tsize_t usize;\n\textent_node_t *node;\n\tbool is_zeroed;\n\n\t/* Allocate one or more contiguous chunks for this request. */\n\n\tusize = sa2u(size, alignment);\n\tif (unlikely(usize == 0))\n\t\treturn (NULL);\n\tassert(usize >= chunksize);\n\n\t/* Allocate an extent node with which to track the chunk. */\n\tnode = ipallocztm(tsd, CACHELINE_CEILING(sizeof(extent_node_t)),\n\t    CACHELINE, false, tcache, true, arena);\n\tif (node == NULL)\n\t\treturn (NULL);\n\n\t/*\n\t * Copy zero into is_zeroed and pass the copy to chunk_alloc(), so that\n\t * it is possible to make correct junk/zero fill decisions below.\n\t */\n\tis_zeroed = zero;\n\tarena = arena_choose(tsd, arena);\n\tif (unlikely(arena == NULL) || (ret = arena_chunk_alloc_huge(arena,\n\t    size, alignment, &is_zeroed)) == NULL) {\n\t\tidalloctm(tsd, node, tcache, true);\n\t\treturn (NULL);\n\t}\n\n\textent_node_init(node, arena, ret, size, is_zeroed, true);\n\n\tif (huge_node_set(ret, node)) {\n\t\tarena_chunk_dalloc_huge(arena, ret, size);\n\t\tidalloctm(tsd, node, tcache, true);\n\t\treturn (NULL);\n\t}\n\n\t/* Insert node into huge. */\n\tmalloc_mutex_lock(&arena->huge_mtx);\n\tql_elm_new(node, ql_link);\n\tql_tail_insert(&arena->huge, node, ql_link);\n\tmalloc_mutex_unlock(&arena->huge_mtx);\n\n\tif (zero || (config_fill && unlikely(opt_zero))) {\n\t\tif (!is_zeroed)\n\t\t\tmemset(ret, 0, size);\n\t} else if (config_fill && unlikely(opt_junk_alloc))\n\t\tmemset(ret, 0xa5, size);\n\n\treturn (ret);\n}\n\n#ifdef JEMALLOC_JET\n#undef huge_dalloc_junk\n#define\thuge_dalloc_junk JEMALLOC_N(huge_dalloc_junk_impl)\n#endif\nstatic void\nhuge_dalloc_junk(void *ptr, size_t usize)\n{\n\n\tif (config_fill && have_dss && unlikely(opt_junk_free)) {\n\t\t/*\n\t\t * Only bother junk filling if the chunk isn't about to be\n\t\t * unmapped.\n\t\t */\n\t\tif (!config_munmap || (have_dss && chunk_in_dss(ptr)))\n\t\t\tmemset(ptr, 0x5a, usize);\n\t}\n}\n#ifdef JEMALLOC_JET\n#undef huge_dalloc_junk\n#define\thuge_dalloc_junk JEMALLOC_N(huge_dalloc_junk)\nhuge_dalloc_junk_t *huge_dalloc_junk = JEMALLOC_N(huge_dalloc_junk_impl);\n#endif\n\nstatic void\nhuge_ralloc_no_move_similar(void *ptr, size_t oldsize, size_t usize_min,\n    size_t usize_max, bool zero)\n{\n\tsize_t usize, usize_next;\n\textent_node_t *node;\n\tarena_t *arena;\n\tchunk_hooks_t chunk_hooks = CHUNK_HOOKS_INITIALIZER;\n\tbool pre_zeroed, post_zeroed;\n\n\t/* Increase usize to incorporate extra. */\n\tfor (usize = usize_min; usize < usize_max && (usize_next = s2u(usize+1))\n\t    <= oldsize; usize = usize_next)\n\t\t; /* Do nothing. */\n\n\tif (oldsize == usize)\n\t\treturn;\n\n\tnode = huge_node_get(ptr);\n\tarena = extent_node_arena_get(node);\n\tpre_zeroed = extent_node_zeroed_get(node);\n\n\t/* Fill if necessary (shrinking). */\n\tif (oldsize > usize) {\n\t\tsize_t sdiff = oldsize - usize;\n\t\tif (config_fill && unlikely(opt_junk_free)) {\n\t\t\tmemset((void *)((uintptr_t)ptr + usize), 0x5a, sdiff);\n\t\t\tpost_zeroed = false;\n\t\t} else {\n\t\t\tpost_zeroed = !chunk_purge_wrapper(arena, &chunk_hooks,\n\t\t\t    ptr, CHUNK_CEILING(oldsize), usize, sdiff);\n\t\t}\n\t} else\n\t\tpost_zeroed = pre_zeroed;\n\n\tmalloc_mutex_lock(&arena->huge_mtx);\n\t/* Update the size of the huge allocation. */\n\tassert(extent_node_size_get(node) != usize);\n\textent_node_size_set(node, usize);\n\t/* Update zeroed. */\n\textent_node_zeroed_set(node, post_zeroed);\n\tmalloc_mutex_unlock(&arena->huge_mtx);\n\n\tarena_chunk_ralloc_huge_similar(arena, ptr, oldsize, usize);\n\n\t/* Fill if necessary (growing). */\n\tif (oldsize < usize) {\n\t\tif (zero || (config_fill && unlikely(opt_zero))) {\n\t\t\tif (!pre_zeroed) {\n\t\t\t\tmemset((void *)((uintptr_t)ptr + oldsize), 0,\n\t\t\t\t    usize - oldsize);\n\t\t\t}\n\t\t} else if (config_fill && unlikely(opt_junk_alloc)) {\n\t\t\tmemset((void *)((uintptr_t)ptr + oldsize), 0xa5, usize -\n\t\t\t    oldsize);\n\t\t}\n\t}\n}\n\nstatic bool\nhuge_ralloc_no_move_shrink(void *ptr, size_t oldsize, size_t usize)\n{\n\textent_node_t *node;\n\tarena_t *arena;\n\tchunk_hooks_t chunk_hooks;\n\tsize_t cdiff;\n\tbool pre_zeroed, post_zeroed;\n\n\tnode = huge_node_get(ptr);\n\tarena = extent_node_arena_get(node);\n\tpre_zeroed = extent_node_zeroed_get(node);\n\tchunk_hooks = chunk_hooks_get(arena);\n\n\tassert(oldsize > usize);\n\n\t/* Split excess chunks. */\n\tcdiff = CHUNK_CEILING(oldsize) - CHUNK_CEILING(usize);\n\tif (cdiff != 0 && chunk_hooks.split(ptr, CHUNK_CEILING(oldsize),\n\t    CHUNK_CEILING(usize), cdiff, true, arena->ind))\n\t\treturn (true);\n\n\tif (oldsize > usize) {\n\t\tsize_t sdiff = oldsize - usize;\n\t\tif (config_fill && unlikely(opt_junk_free)) {\n\t\t\thuge_dalloc_junk((void *)((uintptr_t)ptr + usize),\n\t\t\t    sdiff);\n\t\t\tpost_zeroed = false;\n\t\t} else {\n\t\t\tpost_zeroed = !chunk_purge_wrapper(arena, &chunk_hooks,\n\t\t\t    CHUNK_ADDR2BASE((uintptr_t)ptr + usize),\n\t\t\t    CHUNK_CEILING(oldsize),\n\t\t\t    CHUNK_ADDR2OFFSET((uintptr_t)ptr + usize), sdiff);\n\t\t}\n\t} else\n\t\tpost_zeroed = pre_zeroed;\n\n\tmalloc_mutex_lock(&arena->huge_mtx);\n\t/* Update the size of the huge allocation. */\n\textent_node_size_set(node, usize);\n\t/* Update zeroed. */\n\textent_node_zeroed_set(node, post_zeroed);\n\tmalloc_mutex_unlock(&arena->huge_mtx);\n\n\t/* Zap the excess chunks. */\n\tarena_chunk_ralloc_huge_shrink(arena, ptr, oldsize, usize);\n\n\treturn (false);\n}\n\nstatic bool\nhuge_ralloc_no_move_expand(void *ptr, size_t oldsize, size_t usize, bool zero) {\n\textent_node_t *node;\n\tarena_t *arena;\n\tbool is_zeroed_subchunk, is_zeroed_chunk;\n\n\tnode = huge_node_get(ptr);\n\tarena = extent_node_arena_get(node);\n\tmalloc_mutex_lock(&arena->huge_mtx);\n\tis_zeroed_subchunk = extent_node_zeroed_get(node);\n\tmalloc_mutex_unlock(&arena->huge_mtx);\n\n\t/*\n\t * Copy zero into is_zeroed_chunk and pass the copy to chunk_alloc(), so\n\t * that it is possible to make correct junk/zero fill decisions below.\n\t */\n\tis_zeroed_chunk = zero;\n\n\tif (arena_chunk_ralloc_huge_expand(arena, ptr, oldsize, usize,\n\t     &is_zeroed_chunk))\n\t\treturn (true);\n\n\tmalloc_mutex_lock(&arena->huge_mtx);\n\t/* Update the size of the huge allocation. */\n\textent_node_size_set(node, usize);\n\tmalloc_mutex_unlock(&arena->huge_mtx);\n\n\tif (zero || (config_fill && unlikely(opt_zero))) {\n\t\tif (!is_zeroed_subchunk) {\n\t\t\tmemset((void *)((uintptr_t)ptr + oldsize), 0,\n\t\t\t    CHUNK_CEILING(oldsize) - oldsize);\n\t\t}\n\t\tif (!is_zeroed_chunk) {\n\t\t\tmemset((void *)((uintptr_t)ptr +\n\t\t\t    CHUNK_CEILING(oldsize)), 0, usize -\n\t\t\t    CHUNK_CEILING(oldsize));\n\t\t}\n\t} else if (config_fill && unlikely(opt_junk_alloc)) {\n\t\tmemset((void *)((uintptr_t)ptr + oldsize), 0xa5, usize -\n\t\t    oldsize);\n\t}\n\n\treturn (false);\n}\n\nbool\nhuge_ralloc_no_move(void *ptr, size_t oldsize, size_t usize_min,\n    size_t usize_max, bool zero)\n{\n\n\tassert(s2u(oldsize) == oldsize);\n\n\t/* Both allocations must be huge to avoid a move. */\n\tif (oldsize < chunksize || usize_max < chunksize)\n\t\treturn (true);\n\n\tif (CHUNK_CEILING(usize_max) > CHUNK_CEILING(oldsize)) {\n\t\t/* Attempt to expand the allocation in-place. */\n\t\tif (!huge_ralloc_no_move_expand(ptr, oldsize, usize_max, zero))\n\t\t\treturn (false);\n\t\t/* Try again, this time with usize_min. */\n\t\tif (usize_min < usize_max && CHUNK_CEILING(usize_min) >\n\t\t    CHUNK_CEILING(oldsize) && huge_ralloc_no_move_expand(ptr,\n\t\t    oldsize, usize_min, zero))\n\t\t\treturn (false);\n\t}\n\n\t/*\n\t * Avoid moving the allocation if the existing chunk size accommodates\n\t * the new size.\n\t */\n\tif (CHUNK_CEILING(oldsize) >= CHUNK_CEILING(usize_min)\n\t    && CHUNK_CEILING(oldsize) <= CHUNK_CEILING(usize_max)) {\n\t\thuge_ralloc_no_move_similar(ptr, oldsize, usize_min, usize_max,\n\t\t    zero);\n\t\treturn (false);\n\t}\n\n\t/* Attempt to shrink the allocation in-place. */\n\tif (CHUNK_CEILING(oldsize) > CHUNK_CEILING(usize_max))\n\t\treturn (huge_ralloc_no_move_shrink(ptr, oldsize, usize_max));\n\treturn (true);\n}\n\nstatic void *\nhuge_ralloc_move_helper(tsd_t *tsd, arena_t *arena, size_t usize,\n    size_t alignment, bool zero, tcache_t *tcache)\n{\n\n\tif (alignment <= chunksize)\n\t\treturn (huge_malloc(tsd, arena, usize, zero, tcache));\n\treturn (huge_palloc(tsd, arena, usize, alignment, zero, tcache));\n}\n\nvoid *\nhuge_ralloc(tsd_t *tsd, arena_t *arena, void *ptr, size_t oldsize, size_t usize,\n    size_t alignment, bool zero, tcache_t *tcache)\n{\n\tvoid *ret;\n\tsize_t copysize;\n\n\t/* Try to avoid moving the allocation. */\n\tif (!huge_ralloc_no_move(ptr, oldsize, usize, usize, zero))\n\t\treturn (ptr);\n\n\t/*\n\t * usize and oldsize are different enough that we need to use a\n\t * different size class.  In that case, fall back to allocating new\n\t * space and copying.\n\t */\n\tret = huge_ralloc_move_helper(tsd, arena, usize, alignment, zero,\n\t    tcache);\n\tif (ret == NULL)\n\t\treturn (NULL);\n\n\tcopysize = (usize < oldsize) ? usize : oldsize;\n\tmemcpy(ret, ptr, copysize);\n\tisqalloc(tsd, ptr, oldsize, tcache);\n\treturn (ret);\n}\n\nvoid\nhuge_dalloc(tsd_t *tsd, void *ptr, tcache_t *tcache)\n{\n\textent_node_t *node;\n\tarena_t *arena;\n\n\tnode = huge_node_get(ptr);\n\tarena = extent_node_arena_get(node);\n\thuge_node_unset(ptr, node);\n\tmalloc_mutex_lock(&arena->huge_mtx);\n\tql_remove(&arena->huge, node, ql_link);\n\tmalloc_mutex_unlock(&arena->huge_mtx);\n\n\thuge_dalloc_junk(extent_node_addr_get(node),\n\t    extent_node_size_get(node));\n\tarena_chunk_dalloc_huge(extent_node_arena_get(node),\n\t    extent_node_addr_get(node), extent_node_size_get(node));\n\tidalloctm(tsd, node, tcache, true);\n}\n\narena_t *\nhuge_aalloc(const void *ptr)\n{\n\n\treturn (extent_node_arena_get(huge_node_get(ptr)));\n}\n\nsize_t\nhuge_salloc(const void *ptr)\n{\n\tsize_t size;\n\textent_node_t *node;\n\tarena_t *arena;\n\n\tnode = huge_node_get(ptr);\n\tarena = extent_node_arena_get(node);\n\tmalloc_mutex_lock(&arena->huge_mtx);\n\tsize = extent_node_size_get(node);\n\tmalloc_mutex_unlock(&arena->huge_mtx);\n\n\treturn (size);\n}\n\nprof_tctx_t *\nhuge_prof_tctx_get(const void *ptr)\n{\n\tprof_tctx_t *tctx;\n\textent_node_t *node;\n\tarena_t *arena;\n\n\tnode = huge_node_get(ptr);\n\tarena = extent_node_arena_get(node);\n\tmalloc_mutex_lock(&arena->huge_mtx);\n\ttctx = extent_node_prof_tctx_get(node);\n\tmalloc_mutex_unlock(&arena->huge_mtx);\n\n\treturn (tctx);\n}\n\nvoid\nhuge_prof_tctx_set(const void *ptr, prof_tctx_t *tctx)\n{\n\textent_node_t *node;\n\tarena_t *arena;\n\n\tnode = huge_node_get(ptr);\n\tarena = extent_node_arena_get(node);\n\tmalloc_mutex_lock(&arena->huge_mtx);\n\textent_node_prof_tctx_set(node, tctx);\n\tmalloc_mutex_unlock(&arena->huge_mtx);\n}\n\nvoid\nhuge_prof_tctx_reset(const void *ptr)\n{\n\n\thuge_prof_tctx_set(ptr, (prof_tctx_t *)(uintptr_t)1U);\n}\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.8/deps/jemalloc/src/jemalloc.c",
    "content": "#define\tJEMALLOC_C_\n#include \"jemalloc/internal/jemalloc_internal.h\"\n\n/******************************************************************************/\n/* Data. */\n\n/* Runtime configuration options. */\nconst char\t*je_malloc_conf JEMALLOC_ATTR(weak);\nbool\topt_abort =\n#ifdef JEMALLOC_DEBUG\n    true\n#else\n    false\n#endif\n    ;\nconst char\t*opt_junk =\n#if (defined(JEMALLOC_DEBUG) && defined(JEMALLOC_FILL))\n    \"true\"\n#else\n    \"false\"\n#endif\n    ;\nbool\topt_junk_alloc =\n#if (defined(JEMALLOC_DEBUG) && defined(JEMALLOC_FILL))\n    true\n#else\n    false\n#endif\n    ;\nbool\topt_junk_free =\n#if (defined(JEMALLOC_DEBUG) && defined(JEMALLOC_FILL))\n    true\n#else\n    false\n#endif\n    ;\n\nsize_t\topt_quarantine = ZU(0);\nbool\topt_redzone = false;\nbool\topt_utrace = false;\nbool\topt_xmalloc = false;\nbool\topt_zero = false;\nsize_t\topt_narenas = 0;\n\n/* Initialized to true if the process is running inside Valgrind. */\nbool\tin_valgrind;\n\nunsigned\tncpus;\n\n/* Protects arenas initialization (arenas, narenas_total). */\nstatic malloc_mutex_t\tarenas_lock;\n/*\n * Arenas that are used to service external requests.  Not all elements of the\n * arenas array are necessarily used; arenas are created lazily as needed.\n *\n * arenas[0..narenas_auto) are used for automatic multiplexing of threads and\n * arenas.  arenas[narenas_auto..narenas_total) are only used if the application\n * takes some action to create them and allocate from them.\n */\nstatic arena_t\t\t**arenas;\nstatic unsigned\t\tnarenas_total;\nstatic arena_t\t\t*a0; /* arenas[0]; read-only after initialization. */\nstatic unsigned\t\tnarenas_auto; /* Read-only after initialization. */\n\ntypedef enum {\n\tmalloc_init_uninitialized\t= 3,\n\tmalloc_init_a0_initialized\t= 2,\n\tmalloc_init_recursible\t\t= 1,\n\tmalloc_init_initialized\t\t= 0 /* Common case --> jnz. */\n} malloc_init_t;\nstatic malloc_init_t\tmalloc_init_state = malloc_init_uninitialized;\n\nJEMALLOC_ALIGNED(CACHELINE)\nconst size_t\tindex2size_tab[NSIZES] = {\n#define\tSC(index, lg_grp, lg_delta, ndelta, bin, lg_delta_lookup) \\\n\t((ZU(1)<<lg_grp) + (ZU(ndelta)<<lg_delta)),\n\tSIZE_CLASSES\n#undef SC\n};\n\nJEMALLOC_ALIGNED(CACHELINE)\nconst uint8_t\tsize2index_tab[] = {\n#if LG_TINY_MIN == 0\n#warning \"Dangerous LG_TINY_MIN\"\n#define\tS2B_0(i)\ti,\n#elif LG_TINY_MIN == 1\n#warning \"Dangerous LG_TINY_MIN\"\n#define\tS2B_1(i)\ti,\n#elif LG_TINY_MIN == 2\n#warning \"Dangerous LG_TINY_MIN\"\n#define\tS2B_2(i)\ti,\n#elif LG_TINY_MIN == 3\n#define\tS2B_3(i)\ti,\n#elif LG_TINY_MIN == 4\n#define\tS2B_4(i)\ti,\n#elif LG_TINY_MIN == 5\n#define\tS2B_5(i)\ti,\n#elif LG_TINY_MIN == 6\n#define\tS2B_6(i)\ti,\n#elif LG_TINY_MIN == 7\n#define\tS2B_7(i)\ti,\n#elif LG_TINY_MIN == 8\n#define\tS2B_8(i)\ti,\n#elif LG_TINY_MIN == 9\n#define\tS2B_9(i)\ti,\n#elif LG_TINY_MIN == 10\n#define\tS2B_10(i)\ti,\n#elif LG_TINY_MIN == 11\n#define\tS2B_11(i)\ti,\n#else\n#error \"Unsupported LG_TINY_MIN\"\n#endif\n#if LG_TINY_MIN < 1\n#define\tS2B_1(i)\tS2B_0(i) S2B_0(i)\n#endif\n#if LG_TINY_MIN < 2\n#define\tS2B_2(i)\tS2B_1(i) S2B_1(i)\n#endif\n#if LG_TINY_MIN < 3\n#define\tS2B_3(i)\tS2B_2(i) S2B_2(i)\n#endif\n#if LG_TINY_MIN < 4\n#define\tS2B_4(i)\tS2B_3(i) S2B_3(i)\n#endif\n#if LG_TINY_MIN < 5\n#define\tS2B_5(i)\tS2B_4(i) S2B_4(i)\n#endif\n#if LG_TINY_MIN < 6\n#define\tS2B_6(i)\tS2B_5(i) S2B_5(i)\n#endif\n#if LG_TINY_MIN < 7\n#define\tS2B_7(i)\tS2B_6(i) S2B_6(i)\n#endif\n#if LG_TINY_MIN < 8\n#define\tS2B_8(i)\tS2B_7(i) S2B_7(i)\n#endif\n#if LG_TINY_MIN < 9\n#define\tS2B_9(i)\tS2B_8(i) S2B_8(i)\n#endif\n#if LG_TINY_MIN < 10\n#define\tS2B_10(i)\tS2B_9(i) S2B_9(i)\n#endif\n#if LG_TINY_MIN < 11\n#define\tS2B_11(i)\tS2B_10(i) S2B_10(i)\n#endif\n#define\tS2B_no(i)\n#define\tSC(index, lg_grp, lg_delta, ndelta, bin, lg_delta_lookup) \\\n\tS2B_##lg_delta_lookup(index)\n\tSIZE_CLASSES\n#undef S2B_3\n#undef S2B_4\n#undef S2B_5\n#undef S2B_6\n#undef S2B_7\n#undef S2B_8\n#undef S2B_9\n#undef S2B_10\n#undef S2B_11\n#undef S2B_no\n#undef SC\n};\n\n#ifdef JEMALLOC_THREADED_INIT\n/* Used to let the initializing thread recursively allocate. */\n#  define NO_INITIALIZER\t((unsigned long)0)\n#  define INITIALIZER\t\tpthread_self()\n#  define IS_INITIALIZER\t(malloc_initializer == pthread_self())\nstatic pthread_t\t\tmalloc_initializer = NO_INITIALIZER;\n#else\n#  define NO_INITIALIZER\tfalse\n#  define INITIALIZER\t\ttrue\n#  define IS_INITIALIZER\tmalloc_initializer\nstatic bool\t\t\tmalloc_initializer = NO_INITIALIZER;\n#endif\n\n/* Used to avoid initialization races. */\n#ifdef _WIN32\n#if _WIN32_WINNT >= 0x0600\nstatic malloc_mutex_t\tinit_lock = SRWLOCK_INIT;\n#else\nstatic malloc_mutex_t\tinit_lock;\nstatic bool init_lock_initialized = false;\n\nJEMALLOC_ATTR(constructor)\nstatic void WINAPI\n_init_init_lock(void)\n{\n\n\t/* If another constructor in the same binary is using mallctl to\n\t * e.g. setup chunk hooks, it may end up running before this one,\n\t * and malloc_init_hard will crash trying to lock the uninitialized\n\t * lock. So we force an initialization of the lock in\n\t * malloc_init_hard as well. We don't try to care about atomicity\n\t * of the accessed to the init_lock_initialized boolean, since it\n\t * really only matters early in the process creation, before any\n\t * separate thread normally starts doing anything. */\n\tif (!init_lock_initialized)\n\t\tmalloc_mutex_init(&init_lock);\n\tinit_lock_initialized = true;\n}\n\n#ifdef _MSC_VER\n#  pragma section(\".CRT$XCU\", read)\nJEMALLOC_SECTION(\".CRT$XCU\") JEMALLOC_ATTR(used)\nstatic const void (WINAPI *init_init_lock)(void) = _init_init_lock;\n#endif\n#endif\n#else\nstatic malloc_mutex_t\tinit_lock = MALLOC_MUTEX_INITIALIZER;\n#endif\n\ntypedef struct {\n\tvoid\t*p;\t/* Input pointer (as in realloc(p, s)). */\n\tsize_t\ts;\t/* Request size. */\n\tvoid\t*r;\t/* Result pointer. */\n} malloc_utrace_t;\n\n#ifdef JEMALLOC_UTRACE\n#  define UTRACE(a, b, c) do {\t\t\t\t\t\t\\\n\tif (unlikely(opt_utrace)) {\t\t\t\t\t\\\n\t\tint utrace_serrno = errno;\t\t\t\t\\\n\t\tmalloc_utrace_t ut;\t\t\t\t\t\\\n\t\tut.p = (a);\t\t\t\t\t\t\\\n\t\tut.s = (b);\t\t\t\t\t\t\\\n\t\tut.r = (c);\t\t\t\t\t\t\\\n\t\tutrace(&ut, sizeof(ut));\t\t\t\t\\\n\t\terrno = utrace_serrno;\t\t\t\t\t\\\n\t}\t\t\t\t\t\t\t\t\\\n} while (0)\n#else\n#  define UTRACE(a, b, c)\n#endif\n\n/******************************************************************************/\n/*\n * Function prototypes for static functions that are referenced prior to\n * definition.\n */\n\nstatic bool\tmalloc_init_hard_a0(void);\nstatic bool\tmalloc_init_hard(void);\n\n/******************************************************************************/\n/*\n * Begin miscellaneous support functions.\n */\n\nJEMALLOC_ALWAYS_INLINE_C bool\nmalloc_initialized(void)\n{\n\n\treturn (malloc_init_state == malloc_init_initialized);\n}\n\nJEMALLOC_ALWAYS_INLINE_C void\nmalloc_thread_init(void)\n{\n\n\t/*\n\t * TSD initialization can't be safely done as a side effect of\n\t * deallocation, because it is possible for a thread to do nothing but\n\t * deallocate its TLS data via free(), in which case writing to TLS\n\t * would cause write-after-free memory corruption.  The quarantine\n\t * facility *only* gets used as a side effect of deallocation, so make\n\t * a best effort attempt at initializing its TSD by hooking all\n\t * allocation events.\n\t */\n\tif (config_fill && unlikely(opt_quarantine))\n\t\tquarantine_alloc_hook();\n}\n\nJEMALLOC_ALWAYS_INLINE_C bool\nmalloc_init_a0(void)\n{\n\n\tif (unlikely(malloc_init_state == malloc_init_uninitialized))\n\t\treturn (malloc_init_hard_a0());\n\treturn (false);\n}\n\nJEMALLOC_ALWAYS_INLINE_C bool\nmalloc_init(void)\n{\n\n\tif (unlikely(!malloc_initialized()) && malloc_init_hard())\n\t\treturn (true);\n\tmalloc_thread_init();\n\n\treturn (false);\n}\n\n/*\n * The a0*() functions are used instead of i[mcd]alloc() in situations that\n * cannot tolerate TLS variable access.\n */\n\narena_t *\na0get(void)\n{\n\n\tassert(a0 != NULL);\n\treturn (a0);\n}\n\nstatic void *\na0ialloc(size_t size, bool zero, bool is_metadata)\n{\n\n\tif (unlikely(malloc_init_a0()))\n\t\treturn (NULL);\n\n\treturn (iallocztm(NULL, size, zero, false, is_metadata, a0get()));\n}\n\nstatic void\na0idalloc(void *ptr, bool is_metadata)\n{\n\n\tidalloctm(NULL, ptr, false, is_metadata);\n}\n\nvoid *\na0malloc(size_t size)\n{\n\n\treturn (a0ialloc(size, false, true));\n}\n\nvoid\na0dalloc(void *ptr)\n{\n\n\ta0idalloc(ptr, true);\n}\n\n/*\n * FreeBSD's libc uses the bootstrap_*() functions in bootstrap-senstive\n * situations that cannot tolerate TLS variable access (TLS allocation and very\n * early internal data structure initialization).\n */\n\nvoid *\nbootstrap_malloc(size_t size)\n{\n\n\tif (unlikely(size == 0))\n\t\tsize = 1;\n\n\treturn (a0ialloc(size, false, false));\n}\n\nvoid *\nbootstrap_calloc(size_t num, size_t size)\n{\n\tsize_t num_size;\n\n\tnum_size = num * size;\n\tif (unlikely(num_size == 0)) {\n\t\tassert(num == 0 || size == 0);\n\t\tnum_size = 1;\n\t}\n\n\treturn (a0ialloc(num_size, true, false));\n}\n\nvoid\nbootstrap_free(void *ptr)\n{\n\n\tif (unlikely(ptr == NULL))\n\t\treturn;\n\n\ta0idalloc(ptr, false);\n}\n\n/* Create a new arena and insert it into the arenas array at index ind. */\nstatic arena_t *\narena_init_locked(unsigned ind)\n{\n\tarena_t *arena;\n\n\t/* Expand arenas if necessary. */\n\tassert(ind <= narenas_total);\n\tif (ind > MALLOCX_ARENA_MAX)\n\t\treturn (NULL);\n\tif (ind == narenas_total) {\n\t\tunsigned narenas_new = narenas_total + 1;\n\t\tarena_t **arenas_new =\n\t\t    (arena_t **)a0malloc(CACHELINE_CEILING(narenas_new *\n\t\t    sizeof(arena_t *)));\n\t\tif (arenas_new == NULL)\n\t\t\treturn (NULL);\n\t\tmemcpy(arenas_new, arenas, narenas_total * sizeof(arena_t *));\n\t\tarenas_new[ind] = NULL;\n\t\t/*\n\t\t * Deallocate only if arenas came from a0malloc() (not\n\t\t * base_alloc()).\n\t\t */\n\t\tif (narenas_total != narenas_auto)\n\t\t\ta0dalloc(arenas);\n\t\tarenas = arenas_new;\n\t\tnarenas_total = narenas_new;\n\t}\n\n\t/*\n\t * Another thread may have already initialized arenas[ind] if it's an\n\t * auto arena.\n\t */\n\tarena = arenas[ind];\n\tif (arena != NULL) {\n\t\tassert(ind < narenas_auto);\n\t\treturn (arena);\n\t}\n\n\t/* Actually initialize the arena. */\n\tarena = arenas[ind] = arena_new(ind);\n\treturn (arena);\n}\n\narena_t *\narena_init(unsigned ind)\n{\n\tarena_t *arena;\n\n\tmalloc_mutex_lock(&arenas_lock);\n\tarena = arena_init_locked(ind);\n\tmalloc_mutex_unlock(&arenas_lock);\n\treturn (arena);\n}\n\nunsigned\nnarenas_total_get(void)\n{\n\tunsigned narenas;\n\n\tmalloc_mutex_lock(&arenas_lock);\n\tnarenas = narenas_total;\n\tmalloc_mutex_unlock(&arenas_lock);\n\n\treturn (narenas);\n}\n\nstatic void\narena_bind_locked(tsd_t *tsd, unsigned ind)\n{\n\tarena_t *arena;\n\n\tarena = arenas[ind];\n\tarena->nthreads++;\n\n\tif (tsd_nominal(tsd))\n\t\ttsd_arena_set(tsd, arena);\n}\n\nstatic void\narena_bind(tsd_t *tsd, unsigned ind)\n{\n\n\tmalloc_mutex_lock(&arenas_lock);\n\tarena_bind_locked(tsd, ind);\n\tmalloc_mutex_unlock(&arenas_lock);\n}\n\nvoid\narena_migrate(tsd_t *tsd, unsigned oldind, unsigned newind)\n{\n\tarena_t *oldarena, *newarena;\n\n\tmalloc_mutex_lock(&arenas_lock);\n\toldarena = arenas[oldind];\n\tnewarena = arenas[newind];\n\toldarena->nthreads--;\n\tnewarena->nthreads++;\n\tmalloc_mutex_unlock(&arenas_lock);\n\ttsd_arena_set(tsd, newarena);\n}\n\nunsigned\narena_nbound(unsigned ind)\n{\n\tunsigned nthreads;\n\n\tmalloc_mutex_lock(&arenas_lock);\n\tnthreads = arenas[ind]->nthreads;\n\tmalloc_mutex_unlock(&arenas_lock);\n\treturn (nthreads);\n}\n\nstatic void\narena_unbind(tsd_t *tsd, unsigned ind)\n{\n\tarena_t *arena;\n\n\tmalloc_mutex_lock(&arenas_lock);\n\tarena = arenas[ind];\n\tarena->nthreads--;\n\tmalloc_mutex_unlock(&arenas_lock);\n\ttsd_arena_set(tsd, NULL);\n}\n\narena_t *\narena_get_hard(tsd_t *tsd, unsigned ind, bool init_if_missing)\n{\n\tarena_t *arena;\n\tarena_t **arenas_cache = tsd_arenas_cache_get(tsd);\n\tunsigned narenas_cache = tsd_narenas_cache_get(tsd);\n\tunsigned narenas_actual = narenas_total_get();\n\n\t/* Deallocate old cache if it's too small. */\n\tif (arenas_cache != NULL && narenas_cache < narenas_actual) {\n\t\ta0dalloc(arenas_cache);\n\t\tarenas_cache = NULL;\n\t\tnarenas_cache = 0;\n\t\ttsd_arenas_cache_set(tsd, arenas_cache);\n\t\ttsd_narenas_cache_set(tsd, narenas_cache);\n\t}\n\n\t/* Allocate cache if it's missing. */\n\tif (arenas_cache == NULL) {\n\t\tbool *arenas_cache_bypassp = tsd_arenas_cache_bypassp_get(tsd);\n\t\tassert(ind < narenas_actual || !init_if_missing);\n\t\tnarenas_cache = (ind < narenas_actual) ? narenas_actual : ind+1;\n\n\t\tif (tsd_nominal(tsd) && !*arenas_cache_bypassp) {\n\t\t\t*arenas_cache_bypassp = true;\n\t\t\tarenas_cache = (arena_t **)a0malloc(sizeof(arena_t *) *\n\t\t\t    narenas_cache);\n\t\t\t*arenas_cache_bypassp = false;\n\t\t}\n\t\tif (arenas_cache == NULL) {\n\t\t\t/*\n\t\t\t * This function must always tell the truth, even if\n\t\t\t * it's slow, so don't let OOM, thread cleanup (note\n\t\t\t * tsd_nominal check), nor recursive allocation\n\t\t\t * avoidance (note arenas_cache_bypass check) get in the\n\t\t\t * way.\n\t\t\t */\n\t\t\tif (ind >= narenas_actual)\n\t\t\t\treturn (NULL);\n\t\t\tmalloc_mutex_lock(&arenas_lock);\n\t\t\tarena = arenas[ind];\n\t\t\tmalloc_mutex_unlock(&arenas_lock);\n\t\t\treturn (arena);\n\t\t}\n\t\tassert(tsd_nominal(tsd) && !*arenas_cache_bypassp);\n\t\ttsd_arenas_cache_set(tsd, arenas_cache);\n\t\ttsd_narenas_cache_set(tsd, narenas_cache);\n\t}\n\n\t/*\n\t * Copy to cache.  It's possible that the actual number of arenas has\n\t * increased since narenas_total_get() was called above, but that causes\n\t * no correctness issues unless two threads concurrently execute the\n\t * arenas.extend mallctl, which we trust mallctl synchronization to\n\t * prevent.\n\t */\n\tmalloc_mutex_lock(&arenas_lock);\n\tmemcpy(arenas_cache, arenas, sizeof(arena_t *) * narenas_actual);\n\tmalloc_mutex_unlock(&arenas_lock);\n\tif (narenas_cache > narenas_actual) {\n\t\tmemset(&arenas_cache[narenas_actual], 0, sizeof(arena_t *) *\n\t\t    (narenas_cache - narenas_actual));\n\t}\n\n\t/* Read the refreshed cache, and init the arena if necessary. */\n\tarena = arenas_cache[ind];\n\tif (init_if_missing && arena == NULL)\n\t\tarena = arenas_cache[ind] = arena_init(ind);\n\treturn (arena);\n}\n\n/* Slow path, called only by arena_choose(). */\narena_t *\narena_choose_hard(tsd_t *tsd)\n{\n\tarena_t *ret;\n\n\tif (narenas_auto > 1) {\n\t\tunsigned i, choose, first_null;\n\n\t\tchoose = 0;\n\t\tfirst_null = narenas_auto;\n\t\tmalloc_mutex_lock(&arenas_lock);\n\t\tassert(a0get() != NULL);\n\t\tfor (i = 1; i < narenas_auto; i++) {\n\t\t\tif (arenas[i] != NULL) {\n\t\t\t\t/*\n\t\t\t\t * Choose the first arena that has the lowest\n\t\t\t\t * number of threads assigned to it.\n\t\t\t\t */\n\t\t\t\tif (arenas[i]->nthreads <\n\t\t\t\t    arenas[choose]->nthreads)\n\t\t\t\t\tchoose = i;\n\t\t\t} else if (first_null == narenas_auto) {\n\t\t\t\t/*\n\t\t\t\t * Record the index of the first uninitialized\n\t\t\t\t * arena, in case all extant arenas are in use.\n\t\t\t\t *\n\t\t\t\t * NB: It is possible for there to be\n\t\t\t\t * discontinuities in terms of initialized\n\t\t\t\t * versus uninitialized arenas, due to the\n\t\t\t\t * \"thread.arena\" mallctl.\n\t\t\t\t */\n\t\t\t\tfirst_null = i;\n\t\t\t}\n\t\t}\n\n\t\tif (arenas[choose]->nthreads == 0\n\t\t    || first_null == narenas_auto) {\n\t\t\t/*\n\t\t\t * Use an unloaded arena, or the least loaded arena if\n\t\t\t * all arenas are already initialized.\n\t\t\t */\n\t\t\tret = arenas[choose];\n\t\t} else {\n\t\t\t/* Initialize a new arena. */\n\t\t\tchoose = first_null;\n\t\t\tret = arena_init_locked(choose);\n\t\t\tif (ret == NULL) {\n\t\t\t\tmalloc_mutex_unlock(&arenas_lock);\n\t\t\t\treturn (NULL);\n\t\t\t}\n\t\t}\n\t\tarena_bind_locked(tsd, choose);\n\t\tmalloc_mutex_unlock(&arenas_lock);\n\t} else {\n\t\tret = a0get();\n\t\tarena_bind(tsd, 0);\n\t}\n\n\treturn (ret);\n}\n\nvoid\nthread_allocated_cleanup(tsd_t *tsd)\n{\n\n\t/* Do nothing. */\n}\n\nvoid\nthread_deallocated_cleanup(tsd_t *tsd)\n{\n\n\t/* Do nothing. */\n}\n\nvoid\narena_cleanup(tsd_t *tsd)\n{\n\tarena_t *arena;\n\n\tarena = tsd_arena_get(tsd);\n\tif (arena != NULL)\n\t\tarena_unbind(tsd, arena->ind);\n}\n\nvoid\narenas_cache_cleanup(tsd_t *tsd)\n{\n\tarena_t **arenas_cache;\n\n\tarenas_cache = tsd_arenas_cache_get(tsd);\n\tif (arenas_cache != NULL) {\n\t\ttsd_arenas_cache_set(tsd, NULL);\n\t\ta0dalloc(arenas_cache);\n\t}\n}\n\nvoid\nnarenas_cache_cleanup(tsd_t *tsd)\n{\n\n\t/* Do nothing. */\n}\n\nvoid\narenas_cache_bypass_cleanup(tsd_t *tsd)\n{\n\n\t/* Do nothing. */\n}\n\nstatic void\nstats_print_atexit(void)\n{\n\n\tif (config_tcache && config_stats) {\n\t\tunsigned narenas, i;\n\n\t\t/*\n\t\t * Merge stats from extant threads.  This is racy, since\n\t\t * individual threads do not lock when recording tcache stats\n\t\t * events.  As a consequence, the final stats may be slightly\n\t\t * out of date by the time they are reported, if other threads\n\t\t * continue to allocate.\n\t\t */\n\t\tfor (i = 0, narenas = narenas_total_get(); i < narenas; i++) {\n\t\t\tarena_t *arena = arenas[i];\n\t\t\tif (arena != NULL) {\n\t\t\t\ttcache_t *tcache;\n\n\t\t\t\t/*\n\t\t\t\t * tcache_stats_merge() locks bins, so if any\n\t\t\t\t * code is introduced that acquires both arena\n\t\t\t\t * and bin locks in the opposite order,\n\t\t\t\t * deadlocks may result.\n\t\t\t\t */\n\t\t\t\tmalloc_mutex_lock(&arena->lock);\n\t\t\t\tql_foreach(tcache, &arena->tcache_ql, link) {\n\t\t\t\t\ttcache_stats_merge(tcache, arena);\n\t\t\t\t}\n\t\t\t\tmalloc_mutex_unlock(&arena->lock);\n\t\t\t}\n\t\t}\n\t}\n\tje_malloc_stats_print(NULL, NULL, NULL);\n}\n\n/*\n * End miscellaneous support functions.\n */\n/******************************************************************************/\n/*\n * Begin initialization functions.\n */\n\n#ifndef JEMALLOC_HAVE_SECURE_GETENV\nstatic char *\nsecure_getenv(const char *name)\n{\n\n#  ifdef JEMALLOC_HAVE_ISSETUGID\n\tif (issetugid() != 0)\n\t\treturn (NULL);\n#  endif\n\treturn (getenv(name));\n}\n#endif\n\nstatic unsigned\nmalloc_ncpus(void)\n{\n\tlong result;\n\n#ifdef _WIN32\n\tSYSTEM_INFO si;\n\tGetSystemInfo(&si);\n\tresult = si.dwNumberOfProcessors;\n#else\n\tresult = sysconf(_SC_NPROCESSORS_ONLN);\n#endif\n\treturn ((result == -1) ? 1 : (unsigned)result);\n}\n\nstatic bool\nmalloc_conf_next(char const **opts_p, char const **k_p, size_t *klen_p,\n    char const **v_p, size_t *vlen_p)\n{\n\tbool accept;\n\tconst char *opts = *opts_p;\n\n\t*k_p = opts;\n\n\tfor (accept = false; !accept;) {\n\t\tswitch (*opts) {\n\t\tcase 'A': case 'B': case 'C': case 'D': case 'E': case 'F':\n\t\tcase 'G': case 'H': case 'I': case 'J': case 'K': case 'L':\n\t\tcase 'M': case 'N': case 'O': case 'P': case 'Q': case 'R':\n\t\tcase 'S': case 'T': case 'U': case 'V': case 'W': case 'X':\n\t\tcase 'Y': case 'Z':\n\t\tcase 'a': case 'b': case 'c': case 'd': case 'e': case 'f':\n\t\tcase 'g': case 'h': case 'i': case 'j': case 'k': case 'l':\n\t\tcase 'm': case 'n': case 'o': case 'p': case 'q': case 'r':\n\t\tcase 's': case 't': case 'u': case 'v': case 'w': case 'x':\n\t\tcase 'y': case 'z':\n\t\tcase '0': case '1': case '2': case '3': case '4': case '5':\n\t\tcase '6': case '7': case '8': case '9':\n\t\tcase '_':\n\t\t\topts++;\n\t\t\tbreak;\n\t\tcase ':':\n\t\t\topts++;\n\t\t\t*klen_p = (uintptr_t)opts - 1 - (uintptr_t)*k_p;\n\t\t\t*v_p = opts;\n\t\t\taccept = true;\n\t\t\tbreak;\n\t\tcase '\\0':\n\t\t\tif (opts != *opts_p) {\n\t\t\t\tmalloc_write(\"<jemalloc>: Conf string ends \"\n\t\t\t\t    \"with key\\n\");\n\t\t\t}\n\t\t\treturn (true);\n\t\tdefault:\n\t\t\tmalloc_write(\"<jemalloc>: Malformed conf string\\n\");\n\t\t\treturn (true);\n\t\t}\n\t}\n\n\tfor (accept = false; !accept;) {\n\t\tswitch (*opts) {\n\t\tcase ',':\n\t\t\topts++;\n\t\t\t/*\n\t\t\t * Look ahead one character here, because the next time\n\t\t\t * this function is called, it will assume that end of\n\t\t\t * input has been cleanly reached if no input remains,\n\t\t\t * but we have optimistically already consumed the\n\t\t\t * comma if one exists.\n\t\t\t */\n\t\t\tif (*opts == '\\0') {\n\t\t\t\tmalloc_write(\"<jemalloc>: Conf string ends \"\n\t\t\t\t    \"with comma\\n\");\n\t\t\t}\n\t\t\t*vlen_p = (uintptr_t)opts - 1 - (uintptr_t)*v_p;\n\t\t\taccept = true;\n\t\t\tbreak;\n\t\tcase '\\0':\n\t\t\t*vlen_p = (uintptr_t)opts - (uintptr_t)*v_p;\n\t\t\taccept = true;\n\t\t\tbreak;\n\t\tdefault:\n\t\t\topts++;\n\t\t\tbreak;\n\t\t}\n\t}\n\n\t*opts_p = opts;\n\treturn (false);\n}\n\nstatic void\nmalloc_conf_error(const char *msg, const char *k, size_t klen, const char *v,\n    size_t vlen)\n{\n\n\tmalloc_printf(\"<jemalloc>: %s: %.*s:%.*s\\n\", msg, (int)klen, k,\n\t    (int)vlen, v);\n}\n\nstatic void\nmalloc_conf_init(void)\n{\n\tunsigned i;\n\tchar buf[PATH_MAX + 1];\n\tconst char *opts, *k, *v;\n\tsize_t klen, vlen;\n\n\t/*\n\t * Automatically configure valgrind before processing options.  The\n\t * valgrind option remains in jemalloc 3.x for compatibility reasons.\n\t */\n\tif (config_valgrind) {\n\t\tin_valgrind = (RUNNING_ON_VALGRIND != 0) ? true : false;\n\t\tif (config_fill && unlikely(in_valgrind)) {\n\t\t\topt_junk = \"false\";\n\t\t\topt_junk_alloc = false;\n\t\t\topt_junk_free = false;\n\t\t\tassert(!opt_zero);\n\t\t\topt_quarantine = JEMALLOC_VALGRIND_QUARANTINE_DEFAULT;\n\t\t\topt_redzone = true;\n\t\t}\n\t\tif (config_tcache && unlikely(in_valgrind))\n\t\t\topt_tcache = false;\n\t}\n\n\tfor (i = 0; i < 3; i++) {\n\t\t/* Get runtime configuration. */\n\t\tswitch (i) {\n\t\tcase 0:\n\t\t\tif (je_malloc_conf != NULL) {\n\t\t\t\t/*\n\t\t\t\t * Use options that were compiled into the\n\t\t\t\t * program.\n\t\t\t\t */\n\t\t\t\topts = je_malloc_conf;\n\t\t\t} else {\n\t\t\t\t/* No configuration specified. */\n\t\t\t\tbuf[0] = '\\0';\n\t\t\t\topts = buf;\n\t\t\t}\n\t\t\tbreak;\n\t\tcase 1: {\n\t\t\tint linklen = 0;\n#ifndef _WIN32\n\t\t\tint saved_errno = errno;\n\t\t\tconst char *linkname =\n#  ifdef JEMALLOC_PREFIX\n\t\t\t    \"/etc/\"JEMALLOC_PREFIX\"malloc.conf\"\n#  else\n\t\t\t    \"/etc/malloc.conf\"\n#  endif\n\t\t\t    ;\n\n\t\t\t/*\n\t\t\t * Try to use the contents of the \"/etc/malloc.conf\"\n\t\t\t * symbolic link's name.\n\t\t\t */\n\t\t\tlinklen = readlink(linkname, buf, sizeof(buf) - 1);\n\t\t\tif (linklen == -1) {\n\t\t\t\t/* No configuration specified. */\n\t\t\t\tlinklen = 0;\n\t\t\t\t/* Restore errno. */\n\t\t\t\tset_errno(saved_errno);\n\t\t\t}\n#endif\n\t\t\tbuf[linklen] = '\\0';\n\t\t\topts = buf;\n\t\t\tbreak;\n\t\t} case 2: {\n\t\t\tconst char *envname =\n#ifdef JEMALLOC_PREFIX\n\t\t\t    JEMALLOC_CPREFIX\"MALLOC_CONF\"\n#else\n\t\t\t    \"MALLOC_CONF\"\n#endif\n\t\t\t    ;\n\n\t\t\tif ((opts = secure_getenv(envname)) != NULL) {\n\t\t\t\t/*\n\t\t\t\t * Do nothing; opts is already initialized to\n\t\t\t\t * the value of the MALLOC_CONF environment\n\t\t\t\t * variable.\n\t\t\t\t */\n\t\t\t} else {\n\t\t\t\t/* No configuration specified. */\n\t\t\t\tbuf[0] = '\\0';\n\t\t\t\topts = buf;\n\t\t\t}\n\t\t\tbreak;\n\t\t} default:\n\t\t\tnot_reached();\n\t\t\tbuf[0] = '\\0';\n\t\t\topts = buf;\n\t\t}\n\n\t\twhile (*opts != '\\0' && !malloc_conf_next(&opts, &k, &klen, &v,\n\t\t    &vlen)) {\n#define\tCONF_MATCH(n)\t\t\t\t\t\t\t\\\n\t(sizeof(n)-1 == klen && strncmp(n, k, klen) == 0)\n#define\tCONF_MATCH_VALUE(n)\t\t\t\t\t\t\\\n\t(sizeof(n)-1 == vlen && strncmp(n, v, vlen) == 0)\n#define\tCONF_HANDLE_BOOL(o, n, cont)\t\t\t\t\t\\\n\t\t\tif (CONF_MATCH(n)) {\t\t\t\t\\\n\t\t\t\tif (CONF_MATCH_VALUE(\"true\"))\t\t\\\n\t\t\t\t\to = true;\t\t\t\\\n\t\t\t\telse if (CONF_MATCH_VALUE(\"false\"))\t\\\n\t\t\t\t\to = false;\t\t\t\\\n\t\t\t\telse {\t\t\t\t\t\\\n\t\t\t\t\tmalloc_conf_error(\t\t\\\n\t\t\t\t\t    \"Invalid conf value\",\t\\\n\t\t\t\t\t    k, klen, v, vlen);\t\t\\\n\t\t\t\t}\t\t\t\t\t\\\n\t\t\t\tif (cont)\t\t\t\t\\\n\t\t\t\t\tcontinue;\t\t\t\\\n\t\t\t}\n#define\tCONF_HANDLE_SIZE_T(o, n, min, max, clip)\t\t\t\\\n\t\t\tif (CONF_MATCH(n)) {\t\t\t\t\\\n\t\t\t\tuintmax_t um;\t\t\t\t\\\n\t\t\t\tchar *end;\t\t\t\t\\\n\t\t\t\t\t\t\t\t\t\\\n\t\t\t\tset_errno(0);\t\t\t\t\\\n\t\t\t\tum = malloc_strtoumax(v, &end, 0);\t\\\n\t\t\t\tif (get_errno() != 0 || (uintptr_t)end -\\\n\t\t\t\t    (uintptr_t)v != vlen) {\t\t\\\n\t\t\t\t\tmalloc_conf_error(\t\t\\\n\t\t\t\t\t    \"Invalid conf value\",\t\\\n\t\t\t\t\t    k, klen, v, vlen);\t\t\\\n\t\t\t\t} else if (clip) {\t\t\t\\\n\t\t\t\t\tif ((min) != 0 && um < (min))\t\\\n\t\t\t\t\t\to = (min);\t\t\\\n\t\t\t\t\telse if (um > (max))\t\t\\\n\t\t\t\t\t\to = (max);\t\t\\\n\t\t\t\t\telse\t\t\t\t\\\n\t\t\t\t\t\to = um;\t\t\t\\\n\t\t\t\t} else {\t\t\t\t\\\n\t\t\t\t\tif (((min) != 0 && um < (min))\t\\\n\t\t\t\t\t    || um > (max)) {\t\t\\\n\t\t\t\t\t\tmalloc_conf_error(\t\\\n\t\t\t\t\t\t    \"Out-of-range \"\t\\\n\t\t\t\t\t\t    \"conf value\",\t\\\n\t\t\t\t\t\t    k, klen, v, vlen);\t\\\n\t\t\t\t\t} else\t\t\t\t\\\n\t\t\t\t\t\to = um;\t\t\t\\\n\t\t\t\t}\t\t\t\t\t\\\n\t\t\t\tcontinue;\t\t\t\t\\\n\t\t\t}\n#define\tCONF_HANDLE_SSIZE_T(o, n, min, max)\t\t\t\t\\\n\t\t\tif (CONF_MATCH(n)) {\t\t\t\t\\\n\t\t\t\tlong l;\t\t\t\t\t\\\n\t\t\t\tchar *end;\t\t\t\t\\\n\t\t\t\t\t\t\t\t\t\\\n\t\t\t\tset_errno(0);\t\t\t\t\\\n\t\t\t\tl = strtol(v, &end, 0);\t\t\t\\\n\t\t\t\tif (get_errno() != 0 || (uintptr_t)end -\\\n\t\t\t\t    (uintptr_t)v != vlen) {\t\t\\\n\t\t\t\t\tmalloc_conf_error(\t\t\\\n\t\t\t\t\t    \"Invalid conf value\",\t\\\n\t\t\t\t\t    k, klen, v, vlen);\t\t\\\n\t\t\t\t} else if (l < (ssize_t)(min) || l >\t\\\n\t\t\t\t    (ssize_t)(max)) {\t\t\t\\\n\t\t\t\t\tmalloc_conf_error(\t\t\\\n\t\t\t\t\t    \"Out-of-range conf value\",\t\\\n\t\t\t\t\t    k, klen, v, vlen);\t\t\\\n\t\t\t\t} else\t\t\t\t\t\\\n\t\t\t\t\to = l;\t\t\t\t\\\n\t\t\t\tcontinue;\t\t\t\t\\\n\t\t\t}\n#define\tCONF_HANDLE_CHAR_P(o, n, d)\t\t\t\t\t\\\n\t\t\tif (CONF_MATCH(n)) {\t\t\t\t\\\n\t\t\t\tsize_t cpylen = (vlen <=\t\t\\\n\t\t\t\t    sizeof(o)-1) ? vlen :\t\t\\\n\t\t\t\t    sizeof(o)-1;\t\t\t\\\n\t\t\t\tstrncpy(o, v, cpylen);\t\t\t\\\n\t\t\t\to[cpylen] = '\\0';\t\t\t\\\n\t\t\t\tcontinue;\t\t\t\t\\\n\t\t\t}\n\n\t\t\tCONF_HANDLE_BOOL(opt_abort, \"abort\", true)\n\t\t\t/*\n\t\t\t * Chunks always require at least one header page,\n\t\t\t * as many as 2^(LG_SIZE_CLASS_GROUP+1) data pages, and\n\t\t\t * possibly an additional page in the presence of\n\t\t\t * redzones.  In order to simplify options processing,\n\t\t\t * use a conservative bound that accommodates all these\n\t\t\t * constraints.\n\t\t\t */\n\t\t\tCONF_HANDLE_SIZE_T(opt_lg_chunk, \"lg_chunk\", LG_PAGE +\n\t\t\t    LG_SIZE_CLASS_GROUP + (config_fill ? 2 : 1),\n\t\t\t    (sizeof(size_t) << 3) - 1, true)\n\t\t\tif (strncmp(\"dss\", k, klen) == 0) {\n\t\t\t\tint i;\n\t\t\t\tbool match = false;\n\t\t\t\tfor (i = 0; i < dss_prec_limit; i++) {\n\t\t\t\t\tif (strncmp(dss_prec_names[i], v, vlen)\n\t\t\t\t\t    == 0) {\n\t\t\t\t\t\tif (chunk_dss_prec_set(i)) {\n\t\t\t\t\t\t\tmalloc_conf_error(\n\t\t\t\t\t\t\t    \"Error setting dss\",\n\t\t\t\t\t\t\t    k, klen, v, vlen);\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\topt_dss =\n\t\t\t\t\t\t\t    dss_prec_names[i];\n\t\t\t\t\t\t\tmatch = true;\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tif (!match) {\n\t\t\t\t\tmalloc_conf_error(\"Invalid conf value\",\n\t\t\t\t\t    k, klen, v, vlen);\n\t\t\t\t}\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tCONF_HANDLE_SIZE_T(opt_narenas, \"narenas\", 1,\n\t\t\t    SIZE_T_MAX, false)\n\t\t\tCONF_HANDLE_SSIZE_T(opt_lg_dirty_mult, \"lg_dirty_mult\",\n\t\t\t    -1, (sizeof(size_t) << 3) - 1)\n\t\t\tCONF_HANDLE_BOOL(opt_stats_print, \"stats_print\", true)\n\t\t\tif (config_fill) {\n\t\t\t\tif (CONF_MATCH(\"junk\")) {\n\t\t\t\t\tif (CONF_MATCH_VALUE(\"true\")) {\n\t\t\t\t\t\topt_junk = \"true\";\n\t\t\t\t\t\topt_junk_alloc = opt_junk_free =\n\t\t\t\t\t\t    true;\n\t\t\t\t\t} else if (CONF_MATCH_VALUE(\"false\")) {\n\t\t\t\t\t\topt_junk = \"false\";\n\t\t\t\t\t\topt_junk_alloc = opt_junk_free =\n\t\t\t\t\t\t    false;\n\t\t\t\t\t} else if (CONF_MATCH_VALUE(\"alloc\")) {\n\t\t\t\t\t\topt_junk = \"alloc\";\n\t\t\t\t\t\topt_junk_alloc = true;\n\t\t\t\t\t\topt_junk_free = false;\n\t\t\t\t\t} else if (CONF_MATCH_VALUE(\"free\")) {\n\t\t\t\t\t\topt_junk = \"free\";\n\t\t\t\t\t\topt_junk_alloc = false;\n\t\t\t\t\t\topt_junk_free = true;\n\t\t\t\t\t} else {\n\t\t\t\t\t\tmalloc_conf_error(\n\t\t\t\t\t\t    \"Invalid conf value\", k,\n\t\t\t\t\t\t    klen, v, vlen);\n\t\t\t\t\t}\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t\tCONF_HANDLE_SIZE_T(opt_quarantine, \"quarantine\",\n\t\t\t\t    0, SIZE_T_MAX, false)\n\t\t\t\tCONF_HANDLE_BOOL(opt_redzone, \"redzone\", true)\n\t\t\t\tCONF_HANDLE_BOOL(opt_zero, \"zero\", true)\n\t\t\t}\n\t\t\tif (config_utrace) {\n\t\t\t\tCONF_HANDLE_BOOL(opt_utrace, \"utrace\", true)\n\t\t\t}\n\t\t\tif (config_xmalloc) {\n\t\t\t\tCONF_HANDLE_BOOL(opt_xmalloc, \"xmalloc\", true)\n\t\t\t}\n\t\t\tif (config_tcache) {\n\t\t\t\tCONF_HANDLE_BOOL(opt_tcache, \"tcache\",\n\t\t\t\t    !config_valgrind || !in_valgrind)\n\t\t\t\tif (CONF_MATCH(\"tcache\")) {\n\t\t\t\t\tassert(config_valgrind && in_valgrind);\n\t\t\t\t\tif (opt_tcache) {\n\t\t\t\t\t\topt_tcache = false;\n\t\t\t\t\t\tmalloc_conf_error(\n\t\t\t\t\t\t\"tcache cannot be enabled \"\n\t\t\t\t\t\t\"while running inside Valgrind\",\n\t\t\t\t\t\tk, klen, v, vlen);\n\t\t\t\t\t}\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t\tCONF_HANDLE_SSIZE_T(opt_lg_tcache_max,\n\t\t\t\t    \"lg_tcache_max\", -1,\n\t\t\t\t    (sizeof(size_t) << 3) - 1)\n\t\t\t}\n\t\t\tif (config_prof) {\n\t\t\t\tCONF_HANDLE_BOOL(opt_prof, \"prof\", true)\n\t\t\t\tCONF_HANDLE_CHAR_P(opt_prof_prefix,\n\t\t\t\t    \"prof_prefix\", \"jeprof\")\n\t\t\t\tCONF_HANDLE_BOOL(opt_prof_active, \"prof_active\",\n\t\t\t\t    true)\n\t\t\t\tCONF_HANDLE_BOOL(opt_prof_thread_active_init,\n\t\t\t\t    \"prof_thread_active_init\", true)\n\t\t\t\tCONF_HANDLE_SIZE_T(opt_lg_prof_sample,\n\t\t\t\t    \"lg_prof_sample\", 0,\n\t\t\t\t    (sizeof(uint64_t) << 3) - 1, true)\n\t\t\t\tCONF_HANDLE_BOOL(opt_prof_accum, \"prof_accum\",\n\t\t\t\t    true)\n\t\t\t\tCONF_HANDLE_SSIZE_T(opt_lg_prof_interval,\n\t\t\t\t    \"lg_prof_interval\", -1,\n\t\t\t\t    (sizeof(uint64_t) << 3) - 1)\n\t\t\t\tCONF_HANDLE_BOOL(opt_prof_gdump, \"prof_gdump\",\n\t\t\t\t    true)\n\t\t\t\tCONF_HANDLE_BOOL(opt_prof_final, \"prof_final\",\n\t\t\t\t    true)\n\t\t\t\tCONF_HANDLE_BOOL(opt_prof_leak, \"prof_leak\",\n\t\t\t\t    true)\n\t\t\t}\n\t\t\tmalloc_conf_error(\"Invalid conf pair\", k, klen, v,\n\t\t\t    vlen);\n#undef CONF_MATCH\n#undef CONF_HANDLE_BOOL\n#undef CONF_HANDLE_SIZE_T\n#undef CONF_HANDLE_SSIZE_T\n#undef CONF_HANDLE_CHAR_P\n\t\t}\n\t}\n}\n\n/* init_lock must be held. */\nstatic bool\nmalloc_init_hard_needed(void)\n{\n\n\tif (malloc_initialized() || (IS_INITIALIZER && malloc_init_state ==\n\t    malloc_init_recursible)) {\n\t\t/*\n\t\t * Another thread initialized the allocator before this one\n\t\t * acquired init_lock, or this thread is the initializing\n\t\t * thread, and it is recursively allocating.\n\t\t */\n\t\treturn (false);\n\t}\n#ifdef JEMALLOC_THREADED_INIT\n\tif (malloc_initializer != NO_INITIALIZER && !IS_INITIALIZER) {\n\t\t/* Busy-wait until the initializing thread completes. */\n\t\tdo {\n\t\t\tmalloc_mutex_unlock(&init_lock);\n\t\t\tCPU_SPINWAIT;\n\t\t\tmalloc_mutex_lock(&init_lock);\n\t\t} while (!malloc_initialized());\n\t\treturn (false);\n\t}\n#endif\n\treturn (true);\n}\n\n/* init_lock must be held. */\nstatic bool\nmalloc_init_hard_a0_locked(void)\n{\n\n\tmalloc_initializer = INITIALIZER;\n\n\tif (config_prof)\n\t\tprof_boot0();\n\tmalloc_conf_init();\n\tif (opt_stats_print) {\n\t\t/* Print statistics at exit. */\n\t\tif (atexit(stats_print_atexit) != 0) {\n\t\t\tmalloc_write(\"<jemalloc>: Error in atexit()\\n\");\n\t\t\tif (opt_abort)\n\t\t\t\tabort();\n\t\t}\n\t}\n\tif (base_boot())\n\t\treturn (true);\n\tif (chunk_boot())\n\t\treturn (true);\n\tif (ctl_boot())\n\t\treturn (true);\n\tif (config_prof)\n\t\tprof_boot1();\n\tif (arena_boot())\n\t\treturn (true);\n\tif (config_tcache && tcache_boot())\n\t\treturn (true);\n\tif (malloc_mutex_init(&arenas_lock))\n\t\treturn (true);\n\t/*\n\t * Create enough scaffolding to allow recursive allocation in\n\t * malloc_ncpus().\n\t */\n\tnarenas_total = narenas_auto = 1;\n\tarenas = &a0;\n\tmemset(arenas, 0, sizeof(arena_t *) * narenas_auto);\n\t/*\n\t * Initialize one arena here.  The rest are lazily created in\n\t * arena_choose_hard().\n\t */\n\tif (arena_init(0) == NULL)\n\t\treturn (true);\n\tmalloc_init_state = malloc_init_a0_initialized;\n\treturn (false);\n}\n\nstatic bool\nmalloc_init_hard_a0(void)\n{\n\tbool ret;\n\n\tmalloc_mutex_lock(&init_lock);\n\tret = malloc_init_hard_a0_locked();\n\tmalloc_mutex_unlock(&init_lock);\n\treturn (ret);\n}\n\n/*\n * Initialize data structures which may trigger recursive allocation.\n *\n * init_lock must be held.\n */\nstatic void\nmalloc_init_hard_recursible(void)\n{\n\n\tmalloc_init_state = malloc_init_recursible;\n\tmalloc_mutex_unlock(&init_lock);\n\n\tncpus = malloc_ncpus();\n\n#if (!defined(JEMALLOC_MUTEX_INIT_CB) && !defined(JEMALLOC_ZONE) \\\n    && !defined(_WIN32) && !defined(__native_client__))\n\t/* LinuxThreads's pthread_atfork() allocates. */\n\tif (pthread_atfork(jemalloc_prefork, jemalloc_postfork_parent,\n\t    jemalloc_postfork_child) != 0) {\n\t\tmalloc_write(\"<jemalloc>: Error in pthread_atfork()\\n\");\n\t\tif (opt_abort)\n\t\t\tabort();\n\t}\n#endif\n\tmalloc_mutex_lock(&init_lock);\n}\n\n/* init_lock must be held. */\nstatic bool\nmalloc_init_hard_finish(void)\n{\n\n\tif (mutex_boot())\n\t\treturn (true);\n\n\tif (opt_narenas == 0) {\n\t\t/*\n\t\t * For SMP systems, create more than one arena per CPU by\n\t\t * default.\n\t\t */\n\t\tif (ncpus > 1)\n\t\t\topt_narenas = ncpus << 2;\n\t\telse\n\t\t\topt_narenas = 1;\n\t}\n\tnarenas_auto = opt_narenas;\n\t/*\n\t * Make sure that the arenas array can be allocated.  In practice, this\n\t * limit is enough to allow the allocator to function, but the ctl\n\t * machinery will fail to allocate memory at far lower limits.\n\t */\n\tif (narenas_auto > chunksize / sizeof(arena_t *)) {\n\t\tnarenas_auto = chunksize / sizeof(arena_t *);\n\t\tmalloc_printf(\"<jemalloc>: Reducing narenas to limit (%d)\\n\",\n\t\t    narenas_auto);\n\t}\n\tnarenas_total = narenas_auto;\n\n\t/* Allocate and initialize arenas. */\n\tarenas = (arena_t **)base_alloc(sizeof(arena_t *) * narenas_total);\n\tif (arenas == NULL)\n\t\treturn (true);\n\t/*\n\t * Zero the array.  In practice, this should always be pre-zeroed,\n\t * since it was just mmap()ed, but let's be sure.\n\t */\n\tmemset(arenas, 0, sizeof(arena_t *) * narenas_total);\n\t/* Copy the pointer to the one arena that was already initialized. */\n\tarenas[0] = a0;\n\n\tmalloc_init_state = malloc_init_initialized;\n\treturn (false);\n}\n\nstatic bool\nmalloc_init_hard(void)\n{\n\n#if defined(_WIN32) && _WIN32_WINNT < 0x0600\n\t_init_init_lock();\n#endif\n\tmalloc_mutex_lock(&init_lock);\n\tif (!malloc_init_hard_needed()) {\n\t\tmalloc_mutex_unlock(&init_lock);\n\t\treturn (false);\n\t}\n\n\tif (malloc_init_state != malloc_init_a0_initialized &&\n\t    malloc_init_hard_a0_locked()) {\n\t\tmalloc_mutex_unlock(&init_lock);\n\t\treturn (true);\n\t}\n\tif (malloc_tsd_boot0()) {\n\t\tmalloc_mutex_unlock(&init_lock);\n\t\treturn (true);\n\t}\n\tif (config_prof && prof_boot2()) {\n\t\tmalloc_mutex_unlock(&init_lock);\n\t\treturn (true);\n\t}\n\n\tmalloc_init_hard_recursible();\n\n\tif (malloc_init_hard_finish()) {\n\t\tmalloc_mutex_unlock(&init_lock);\n\t\treturn (true);\n\t}\n\n\tmalloc_mutex_unlock(&init_lock);\n\tmalloc_tsd_boot1();\n\treturn (false);\n}\n\n/*\n * End initialization functions.\n */\n/******************************************************************************/\n/*\n * Begin malloc(3)-compatible functions.\n */\n\nstatic void *\nimalloc_prof_sample(tsd_t *tsd, size_t usize, prof_tctx_t *tctx)\n{\n\tvoid *p;\n\n\tif (tctx == NULL)\n\t\treturn (NULL);\n\tif (usize <= SMALL_MAXCLASS) {\n\t\tp = imalloc(tsd, LARGE_MINCLASS);\n\t\tif (p == NULL)\n\t\t\treturn (NULL);\n\t\tarena_prof_promoted(p, usize);\n\t} else\n\t\tp = imalloc(tsd, usize);\n\n\treturn (p);\n}\n\nJEMALLOC_ALWAYS_INLINE_C void *\nimalloc_prof(tsd_t *tsd, size_t usize)\n{\n\tvoid *p;\n\tprof_tctx_t *tctx;\n\n\ttctx = prof_alloc_prep(tsd, usize, prof_active_get_unlocked(), true);\n\tif (unlikely((uintptr_t)tctx != (uintptr_t)1U))\n\t\tp = imalloc_prof_sample(tsd, usize, tctx);\n\telse\n\t\tp = imalloc(tsd, usize);\n\tif (unlikely(p == NULL)) {\n\t\tprof_alloc_rollback(tsd, tctx, true);\n\t\treturn (NULL);\n\t}\n\tprof_malloc(p, usize, tctx);\n\n\treturn (p);\n}\n\nJEMALLOC_ALWAYS_INLINE_C void *\nimalloc_body(size_t size, tsd_t **tsd, size_t *usize)\n{\n\n\tif (unlikely(malloc_init()))\n\t\treturn (NULL);\n\t*tsd = tsd_fetch();\n\n\tif (config_prof && opt_prof) {\n\t\t*usize = s2u(size);\n\t\tif (unlikely(*usize == 0))\n\t\t\treturn (NULL);\n\t\treturn (imalloc_prof(*tsd, *usize));\n\t}\n\n\tif (config_stats || (config_valgrind && unlikely(in_valgrind)))\n\t\t*usize = s2u(size);\n\treturn (imalloc(*tsd, size));\n}\n\nJEMALLOC_EXPORT JEMALLOC_ALLOCATOR JEMALLOC_RESTRICT_RETURN\nvoid JEMALLOC_NOTHROW *\nJEMALLOC_ATTR(malloc) JEMALLOC_ALLOC_SIZE(1)\nje_malloc(size_t size)\n{\n\tvoid *ret;\n\ttsd_t *tsd;\n\tsize_t usize JEMALLOC_CC_SILENCE_INIT(0);\n\n\tif (size == 0)\n\t\tsize = 1;\n\n\tret = imalloc_body(size, &tsd, &usize);\n\tif (unlikely(ret == NULL)) {\n\t\tif (config_xmalloc && unlikely(opt_xmalloc)) {\n\t\t\tmalloc_write(\"<jemalloc>: Error in malloc(): \"\n\t\t\t    \"out of memory\\n\");\n\t\t\tabort();\n\t\t}\n\t\tset_errno(ENOMEM);\n\t}\n\tif (config_stats && likely(ret != NULL)) {\n\t\tassert(usize == isalloc(ret, config_prof));\n\t\t*tsd_thread_allocatedp_get(tsd) += usize;\n\t}\n\tUTRACE(0, size, ret);\n\tJEMALLOC_VALGRIND_MALLOC(ret != NULL, ret, usize, false);\n\treturn (ret);\n}\n\nstatic void *\nimemalign_prof_sample(tsd_t *tsd, size_t alignment, size_t usize,\n    prof_tctx_t *tctx)\n{\n\tvoid *p;\n\n\tif (tctx == NULL)\n\t\treturn (NULL);\n\tif (usize <= SMALL_MAXCLASS) {\n\t\tassert(sa2u(LARGE_MINCLASS, alignment) == LARGE_MINCLASS);\n\t\tp = ipalloc(tsd, LARGE_MINCLASS, alignment, false);\n\t\tif (p == NULL)\n\t\t\treturn (NULL);\n\t\tarena_prof_promoted(p, usize);\n\t} else\n\t\tp = ipalloc(tsd, usize, alignment, false);\n\n\treturn (p);\n}\n\nJEMALLOC_ALWAYS_INLINE_C void *\nimemalign_prof(tsd_t *tsd, size_t alignment, size_t usize)\n{\n\tvoid *p;\n\tprof_tctx_t *tctx;\n\n\ttctx = prof_alloc_prep(tsd, usize, prof_active_get_unlocked(), true);\n\tif (unlikely((uintptr_t)tctx != (uintptr_t)1U))\n\t\tp = imemalign_prof_sample(tsd, alignment, usize, tctx);\n\telse\n\t\tp = ipalloc(tsd, usize, alignment, false);\n\tif (unlikely(p == NULL)) {\n\t\tprof_alloc_rollback(tsd, tctx, true);\n\t\treturn (NULL);\n\t}\n\tprof_malloc(p, usize, tctx);\n\n\treturn (p);\n}\n\nJEMALLOC_ATTR(nonnull(1))\nstatic int\nimemalign(void **memptr, size_t alignment, size_t size, size_t min_alignment)\n{\n\tint ret;\n\ttsd_t *tsd;\n\tsize_t usize;\n\tvoid *result;\n\n\tassert(min_alignment != 0);\n\n\tif (unlikely(malloc_init())) {\n\t\tresult = NULL;\n\t\tgoto label_oom;\n\t}\n\ttsd = tsd_fetch();\n\tif (size == 0)\n\t\tsize = 1;\n\n\t/* Make sure that alignment is a large enough power of 2. */\n\tif (unlikely(((alignment - 1) & alignment) != 0\n\t    || (alignment < min_alignment))) {\n\t\tif (config_xmalloc && unlikely(opt_xmalloc)) {\n\t\t\tmalloc_write(\"<jemalloc>: Error allocating \"\n\t\t\t    \"aligned memory: invalid alignment\\n\");\n\t\t\tabort();\n\t\t}\n\t\tresult = NULL;\n\t\tret = EINVAL;\n\t\tgoto label_return;\n\t}\n\n\tusize = sa2u(size, alignment);\n\tif (unlikely(usize == 0)) {\n\t\tresult = NULL;\n\t\tgoto label_oom;\n\t}\n\n\tif (config_prof && opt_prof)\n\t\tresult = imemalign_prof(tsd, alignment, usize);\n\telse\n\t\tresult = ipalloc(tsd, usize, alignment, false);\n\tif (unlikely(result == NULL))\n\t\tgoto label_oom;\n\tassert(((uintptr_t)result & (alignment - 1)) == ZU(0));\n\n\t*memptr = result;\n\tret = 0;\nlabel_return:\n\tif (config_stats && likely(result != NULL)) {\n\t\tassert(usize == isalloc(result, config_prof));\n\t\t*tsd_thread_allocatedp_get(tsd) += usize;\n\t}\n\tUTRACE(0, size, result);\n\treturn (ret);\nlabel_oom:\n\tassert(result == NULL);\n\tif (config_xmalloc && unlikely(opt_xmalloc)) {\n\t\tmalloc_write(\"<jemalloc>: Error allocating aligned memory: \"\n\t\t    \"out of memory\\n\");\n\t\tabort();\n\t}\n\tret = ENOMEM;\n\tgoto label_return;\n}\n\nJEMALLOC_EXPORT int JEMALLOC_NOTHROW\nJEMALLOC_ATTR(nonnull(1))\nje_posix_memalign(void **memptr, size_t alignment, size_t size)\n{\n\tint ret = imemalign(memptr, alignment, size, sizeof(void *));\n\tJEMALLOC_VALGRIND_MALLOC(ret == 0, *memptr, isalloc(*memptr,\n\t    config_prof), false);\n\treturn (ret);\n}\n\nJEMALLOC_EXPORT JEMALLOC_ALLOCATOR JEMALLOC_RESTRICT_RETURN\nvoid JEMALLOC_NOTHROW *\nJEMALLOC_ATTR(malloc) JEMALLOC_ALLOC_SIZE(2)\nje_aligned_alloc(size_t alignment, size_t size)\n{\n\tvoid *ret;\n\tint err;\n\n\tif (unlikely((err = imemalign(&ret, alignment, size, 1)) != 0)) {\n\t\tret = NULL;\n\t\tset_errno(err);\n\t}\n\tJEMALLOC_VALGRIND_MALLOC(err == 0, ret, isalloc(ret, config_prof),\n\t    false);\n\treturn (ret);\n}\n\nstatic void *\nicalloc_prof_sample(tsd_t *tsd, size_t usize, prof_tctx_t *tctx)\n{\n\tvoid *p;\n\n\tif (tctx == NULL)\n\t\treturn (NULL);\n\tif (usize <= SMALL_MAXCLASS) {\n\t\tp = icalloc(tsd, LARGE_MINCLASS);\n\t\tif (p == NULL)\n\t\t\treturn (NULL);\n\t\tarena_prof_promoted(p, usize);\n\t} else\n\t\tp = icalloc(tsd, usize);\n\n\treturn (p);\n}\n\nJEMALLOC_ALWAYS_INLINE_C void *\nicalloc_prof(tsd_t *tsd, size_t usize)\n{\n\tvoid *p;\n\tprof_tctx_t *tctx;\n\n\ttctx = prof_alloc_prep(tsd, usize, prof_active_get_unlocked(), true);\n\tif (unlikely((uintptr_t)tctx != (uintptr_t)1U))\n\t\tp = icalloc_prof_sample(tsd, usize, tctx);\n\telse\n\t\tp = icalloc(tsd, usize);\n\tif (unlikely(p == NULL)) {\n\t\tprof_alloc_rollback(tsd, tctx, true);\n\t\treturn (NULL);\n\t}\n\tprof_malloc(p, usize, tctx);\n\n\treturn (p);\n}\n\nJEMALLOC_EXPORT JEMALLOC_ALLOCATOR JEMALLOC_RESTRICT_RETURN\nvoid JEMALLOC_NOTHROW *\nJEMALLOC_ATTR(malloc) JEMALLOC_ALLOC_SIZE2(1, 2)\nje_calloc(size_t num, size_t size)\n{\n\tvoid *ret;\n\ttsd_t *tsd;\n\tsize_t num_size;\n\tsize_t usize JEMALLOC_CC_SILENCE_INIT(0);\n\n\tif (unlikely(malloc_init())) {\n\t\tnum_size = 0;\n\t\tret = NULL;\n\t\tgoto label_return;\n\t}\n\ttsd = tsd_fetch();\n\n\tnum_size = num * size;\n\tif (unlikely(num_size == 0)) {\n\t\tif (num == 0 || size == 0)\n\t\t\tnum_size = 1;\n\t\telse {\n\t\t\tret = NULL;\n\t\t\tgoto label_return;\n\t\t}\n\t/*\n\t * Try to avoid division here.  We know that it isn't possible to\n\t * overflow during multiplication if neither operand uses any of the\n\t * most significant half of the bits in a size_t.\n\t */\n\t} else if (unlikely(((num | size) & (SIZE_T_MAX << (sizeof(size_t) <<\n\t    2))) && (num_size / size != num))) {\n\t\t/* size_t overflow. */\n\t\tret = NULL;\n\t\tgoto label_return;\n\t}\n\n\tif (config_prof && opt_prof) {\n\t\tusize = s2u(num_size);\n\t\tif (unlikely(usize == 0)) {\n\t\t\tret = NULL;\n\t\t\tgoto label_return;\n\t\t}\n\t\tret = icalloc_prof(tsd, usize);\n\t} else {\n\t\tif (config_stats || (config_valgrind && unlikely(in_valgrind)))\n\t\t\tusize = s2u(num_size);\n\t\tret = icalloc(tsd, num_size);\n\t}\n\nlabel_return:\n\tif (unlikely(ret == NULL)) {\n\t\tif (config_xmalloc && unlikely(opt_xmalloc)) {\n\t\t\tmalloc_write(\"<jemalloc>: Error in calloc(): out of \"\n\t\t\t    \"memory\\n\");\n\t\t\tabort();\n\t\t}\n\t\tset_errno(ENOMEM);\n\t}\n\tif (config_stats && likely(ret != NULL)) {\n\t\tassert(usize == isalloc(ret, config_prof));\n\t\t*tsd_thread_allocatedp_get(tsd) += usize;\n\t}\n\tUTRACE(0, num_size, ret);\n\tJEMALLOC_VALGRIND_MALLOC(ret != NULL, ret, usize, true);\n\treturn (ret);\n}\n\nstatic void *\nirealloc_prof_sample(tsd_t *tsd, void *old_ptr, size_t old_usize, size_t usize,\n    prof_tctx_t *tctx)\n{\n\tvoid *p;\n\n\tif (tctx == NULL)\n\t\treturn (NULL);\n\tif (usize <= SMALL_MAXCLASS) {\n\t\tp = iralloc(tsd, old_ptr, old_usize, LARGE_MINCLASS, 0, false);\n\t\tif (p == NULL)\n\t\t\treturn (NULL);\n\t\tarena_prof_promoted(p, usize);\n\t} else\n\t\tp = iralloc(tsd, old_ptr, old_usize, usize, 0, false);\n\n\treturn (p);\n}\n\nJEMALLOC_ALWAYS_INLINE_C void *\nirealloc_prof(tsd_t *tsd, void *old_ptr, size_t old_usize, size_t usize)\n{\n\tvoid *p;\n\tbool prof_active;\n\tprof_tctx_t *old_tctx, *tctx;\n\n\tprof_active = prof_active_get_unlocked();\n\told_tctx = prof_tctx_get(old_ptr);\n\ttctx = prof_alloc_prep(tsd, usize, prof_active, true);\n\tif (unlikely((uintptr_t)tctx != (uintptr_t)1U))\n\t\tp = irealloc_prof_sample(tsd, old_ptr, old_usize, usize, tctx);\n\telse\n\t\tp = iralloc(tsd, old_ptr, old_usize, usize, 0, false);\n\tif (unlikely(p == NULL)) {\n\t\tprof_alloc_rollback(tsd, tctx, true);\n\t\treturn (NULL);\n\t}\n\tprof_realloc(tsd, p, usize, tctx, prof_active, true, old_ptr, old_usize,\n\t    old_tctx);\n\n\treturn (p);\n}\n\nJEMALLOC_INLINE_C void\nifree(tsd_t *tsd, void *ptr, tcache_t *tcache)\n{\n\tsize_t usize;\n\tUNUSED size_t rzsize JEMALLOC_CC_SILENCE_INIT(0);\n\n\tassert(ptr != NULL);\n\tassert(malloc_initialized() || IS_INITIALIZER);\n\n\tif (config_prof && opt_prof) {\n\t\tusize = isalloc(ptr, config_prof);\n\t\tprof_free(tsd, ptr, usize);\n\t} else if (config_stats || config_valgrind)\n\t\tusize = isalloc(ptr, config_prof);\n\tif (config_stats)\n\t\t*tsd_thread_deallocatedp_get(tsd) += usize;\n\tif (config_valgrind && unlikely(in_valgrind))\n\t\trzsize = p2rz(ptr);\n\tiqalloc(tsd, ptr, tcache);\n\tJEMALLOC_VALGRIND_FREE(ptr, rzsize);\n}\n\nJEMALLOC_INLINE_C void\nisfree(tsd_t *tsd, void *ptr, size_t usize, tcache_t *tcache)\n{\n\tUNUSED size_t rzsize JEMALLOC_CC_SILENCE_INIT(0);\n\n\tassert(ptr != NULL);\n\tassert(malloc_initialized() || IS_INITIALIZER);\n\n\tif (config_prof && opt_prof)\n\t\tprof_free(tsd, ptr, usize);\n\tif (config_stats)\n\t\t*tsd_thread_deallocatedp_get(tsd) += usize;\n\tif (config_valgrind && unlikely(in_valgrind))\n\t\trzsize = p2rz(ptr);\n\tisqalloc(tsd, ptr, usize, tcache);\n\tJEMALLOC_VALGRIND_FREE(ptr, rzsize);\n}\n\nJEMALLOC_EXPORT JEMALLOC_ALLOCATOR JEMALLOC_RESTRICT_RETURN\nvoid JEMALLOC_NOTHROW *\nJEMALLOC_ALLOC_SIZE(2)\nje_realloc(void *ptr, size_t size)\n{\n\tvoid *ret;\n\ttsd_t *tsd JEMALLOC_CC_SILENCE_INIT(NULL);\n\tsize_t usize JEMALLOC_CC_SILENCE_INIT(0);\n\tsize_t old_usize = 0;\n\tUNUSED size_t old_rzsize JEMALLOC_CC_SILENCE_INIT(0);\n\n\tif (unlikely(size == 0)) {\n\t\tif (ptr != NULL) {\n\t\t\t/* realloc(ptr, 0) is equivalent to free(ptr). */\n\t\t\tUTRACE(ptr, 0, 0);\n\t\t\ttsd = tsd_fetch();\n\t\t\tifree(tsd, ptr, tcache_get(tsd, false));\n\t\t\treturn (NULL);\n\t\t}\n\t\tsize = 1;\n\t}\n\n\tif (likely(ptr != NULL)) {\n\t\tassert(malloc_initialized() || IS_INITIALIZER);\n\t\tmalloc_thread_init();\n\t\ttsd = tsd_fetch();\n\n\t\told_usize = isalloc(ptr, config_prof);\n\t\tif (config_valgrind && unlikely(in_valgrind))\n\t\t\told_rzsize = config_prof ? p2rz(ptr) : u2rz(old_usize);\n\n\t\tif (config_prof && opt_prof) {\n\t\t\tusize = s2u(size);\n\t\t\tret = unlikely(usize == 0) ? NULL : irealloc_prof(tsd,\n\t\t\t    ptr, old_usize, usize);\n\t\t} else {\n\t\t\tif (config_stats || (config_valgrind &&\n\t\t\t    unlikely(in_valgrind)))\n\t\t\t\tusize = s2u(size);\n\t\t\tret = iralloc(tsd, ptr, old_usize, size, 0, false);\n\t\t}\n\t} else {\n\t\t/* realloc(NULL, size) is equivalent to malloc(size). */\n\t\tret = imalloc_body(size, &tsd, &usize);\n\t}\n\n\tif (unlikely(ret == NULL)) {\n\t\tif (config_xmalloc && unlikely(opt_xmalloc)) {\n\t\t\tmalloc_write(\"<jemalloc>: Error in realloc(): \"\n\t\t\t    \"out of memory\\n\");\n\t\t\tabort();\n\t\t}\n\t\tset_errno(ENOMEM);\n\t}\n\tif (config_stats && likely(ret != NULL)) {\n\t\tassert(usize == isalloc(ret, config_prof));\n\t\t*tsd_thread_allocatedp_get(tsd) += usize;\n\t\t*tsd_thread_deallocatedp_get(tsd) += old_usize;\n\t}\n\tUTRACE(ptr, size, ret);\n\tJEMALLOC_VALGRIND_REALLOC(true, ret, usize, true, ptr, old_usize,\n\t    old_rzsize, true, false);\n\treturn (ret);\n}\n\nJEMALLOC_EXPORT void JEMALLOC_NOTHROW\nje_free(void *ptr)\n{\n\n\tUTRACE(ptr, 0, 0);\n\tif (likely(ptr != NULL)) {\n\t\ttsd_t *tsd = tsd_fetch();\n\t\tifree(tsd, ptr, tcache_get(tsd, false));\n\t}\n}\n\n/*\n * End malloc(3)-compatible functions.\n */\n/******************************************************************************/\n/*\n * Begin non-standard override functions.\n */\n\n#ifdef JEMALLOC_OVERRIDE_MEMALIGN\nJEMALLOC_EXPORT JEMALLOC_ALLOCATOR JEMALLOC_RESTRICT_RETURN\nvoid JEMALLOC_NOTHROW *\nJEMALLOC_ATTR(malloc)\nje_memalign(size_t alignment, size_t size)\n{\n\tvoid *ret JEMALLOC_CC_SILENCE_INIT(NULL);\n\tif (unlikely(imemalign(&ret, alignment, size, 1) != 0))\n\t\tret = NULL;\n\tJEMALLOC_VALGRIND_MALLOC(ret != NULL, ret, size, false);\n\treturn (ret);\n}\n#endif\n\n#ifdef JEMALLOC_OVERRIDE_VALLOC\nJEMALLOC_EXPORT JEMALLOC_ALLOCATOR JEMALLOC_RESTRICT_RETURN\nvoid JEMALLOC_NOTHROW *\nJEMALLOC_ATTR(malloc)\nje_valloc(size_t size)\n{\n\tvoid *ret JEMALLOC_CC_SILENCE_INIT(NULL);\n\tif (unlikely(imemalign(&ret, PAGE, size, 1) != 0))\n\t\tret = NULL;\n\tJEMALLOC_VALGRIND_MALLOC(ret != NULL, ret, size, false);\n\treturn (ret);\n}\n#endif\n\n/*\n * is_malloc(je_malloc) is some macro magic to detect if jemalloc_defs.h has\n * #define je_malloc malloc\n */\n#define\tmalloc_is_malloc 1\n#define\tis_malloc_(a) malloc_is_ ## a\n#define\tis_malloc(a) is_malloc_(a)\n\n#if ((is_malloc(je_malloc) == 1) && defined(JEMALLOC_GLIBC_MALLOC_HOOK))\n/*\n * glibc provides the RTLD_DEEPBIND flag for dlopen which can make it possible\n * to inconsistently reference libc's malloc(3)-compatible functions\n * (https://bugzilla.mozilla.org/show_bug.cgi?id=493541).\n *\n * These definitions interpose hooks in glibc.  The functions are actually\n * passed an extra argument for the caller return address, which will be\n * ignored.\n */\nJEMALLOC_EXPORT void (*__free_hook)(void *ptr) = je_free;\nJEMALLOC_EXPORT void *(*__malloc_hook)(size_t size) = je_malloc;\nJEMALLOC_EXPORT void *(*__realloc_hook)(void *ptr, size_t size) = je_realloc;\n# ifdef JEMALLOC_GLIBC_MEMALIGN_HOOK\nJEMALLOC_EXPORT void *(*__memalign_hook)(size_t alignment, size_t size) =\n    je_memalign;\n# endif\n#endif\n\n/*\n * End non-standard override functions.\n */\n/******************************************************************************/\n/*\n * Begin non-standard functions.\n */\n\nJEMALLOC_ALWAYS_INLINE_C bool\nimallocx_flags_decode_hard(tsd_t *tsd, size_t size, int flags, size_t *usize,\n    size_t *alignment, bool *zero, tcache_t **tcache, arena_t **arena)\n{\n\n\tif ((flags & MALLOCX_LG_ALIGN_MASK) == 0) {\n\t\t*alignment = 0;\n\t\t*usize = s2u(size);\n\t} else {\n\t\t*alignment = MALLOCX_ALIGN_GET_SPECIFIED(flags);\n\t\t*usize = sa2u(size, *alignment);\n\t}\n\tassert(*usize != 0);\n\t*zero = MALLOCX_ZERO_GET(flags);\n\tif ((flags & MALLOCX_TCACHE_MASK) != 0) {\n\t\tif ((flags & MALLOCX_TCACHE_MASK) == MALLOCX_TCACHE_NONE)\n\t\t\t*tcache = NULL;\n\t\telse\n\t\t\t*tcache = tcaches_get(tsd, MALLOCX_TCACHE_GET(flags));\n\t} else\n\t\t*tcache = tcache_get(tsd, true);\n\tif ((flags & MALLOCX_ARENA_MASK) != 0) {\n\t\tunsigned arena_ind = MALLOCX_ARENA_GET(flags);\n\t\t*arena = arena_get(tsd, arena_ind, true, true);\n\t\tif (unlikely(*arena == NULL))\n\t\t\treturn (true);\n\t} else\n\t\t*arena = NULL;\n\treturn (false);\n}\n\nJEMALLOC_ALWAYS_INLINE_C bool\nimallocx_flags_decode(tsd_t *tsd, size_t size, int flags, size_t *usize,\n    size_t *alignment, bool *zero, tcache_t **tcache, arena_t **arena)\n{\n\n\tif (likely(flags == 0)) {\n\t\t*usize = s2u(size);\n\t\tassert(*usize != 0);\n\t\t*alignment = 0;\n\t\t*zero = false;\n\t\t*tcache = tcache_get(tsd, true);\n\t\t*arena = NULL;\n\t\treturn (false);\n\t} else {\n\t\treturn (imallocx_flags_decode_hard(tsd, size, flags, usize,\n\t\t    alignment, zero, tcache, arena));\n\t}\n}\n\nJEMALLOC_ALWAYS_INLINE_C void *\nimallocx_flags(tsd_t *tsd, size_t usize, size_t alignment, bool zero,\n    tcache_t *tcache, arena_t *arena)\n{\n\n\tif (unlikely(alignment != 0))\n\t\treturn (ipalloct(tsd, usize, alignment, zero, tcache, arena));\n\tif (unlikely(zero))\n\t\treturn (icalloct(tsd, usize, tcache, arena));\n\treturn (imalloct(tsd, usize, tcache, arena));\n}\n\nstatic void *\nimallocx_prof_sample(tsd_t *tsd, size_t usize, size_t alignment, bool zero,\n    tcache_t *tcache, arena_t *arena)\n{\n\tvoid *p;\n\n\tif (usize <= SMALL_MAXCLASS) {\n\t\tassert(((alignment == 0) ? s2u(LARGE_MINCLASS) :\n\t\t    sa2u(LARGE_MINCLASS, alignment)) == LARGE_MINCLASS);\n\t\tp = imallocx_flags(tsd, LARGE_MINCLASS, alignment, zero, tcache,\n\t\t    arena);\n\t\tif (p == NULL)\n\t\t\treturn (NULL);\n\t\tarena_prof_promoted(p, usize);\n\t} else\n\t\tp = imallocx_flags(tsd, usize, alignment, zero, tcache, arena);\n\n\treturn (p);\n}\n\nJEMALLOC_ALWAYS_INLINE_C void *\nimallocx_prof(tsd_t *tsd, size_t size, int flags, size_t *usize)\n{\n\tvoid *p;\n\tsize_t alignment;\n\tbool zero;\n\ttcache_t *tcache;\n\tarena_t *arena;\n\tprof_tctx_t *tctx;\n\n\tif (unlikely(imallocx_flags_decode(tsd, size, flags, usize, &alignment,\n\t    &zero, &tcache, &arena)))\n\t\treturn (NULL);\n\ttctx = prof_alloc_prep(tsd, *usize, prof_active_get_unlocked(), true);\n\tif (likely((uintptr_t)tctx == (uintptr_t)1U))\n\t\tp = imallocx_flags(tsd, *usize, alignment, zero, tcache, arena);\n\telse if ((uintptr_t)tctx > (uintptr_t)1U) {\n\t\tp = imallocx_prof_sample(tsd, *usize, alignment, zero, tcache,\n\t\t    arena);\n\t} else\n\t\tp = NULL;\n\tif (unlikely(p == NULL)) {\n\t\tprof_alloc_rollback(tsd, tctx, true);\n\t\treturn (NULL);\n\t}\n\tprof_malloc(p, *usize, tctx);\n\n\tassert(alignment == 0 || ((uintptr_t)p & (alignment - 1)) == ZU(0));\n\treturn (p);\n}\n\nJEMALLOC_ALWAYS_INLINE_C void *\nimallocx_no_prof(tsd_t *tsd, size_t size, int flags, size_t *usize)\n{\n\tvoid *p;\n\tsize_t alignment;\n\tbool zero;\n\ttcache_t *tcache;\n\tarena_t *arena;\n\n\tif (likely(flags == 0)) {\n\t\tif (config_stats || (config_valgrind && unlikely(in_valgrind)))\n\t\t\t*usize = s2u(size);\n\t\treturn (imalloc(tsd, size));\n\t}\n\n\tif (unlikely(imallocx_flags_decode_hard(tsd, size, flags, usize,\n\t    &alignment, &zero, &tcache, &arena)))\n\t\treturn (NULL);\n\tp = imallocx_flags(tsd, *usize, alignment, zero, tcache, arena);\n\tassert(alignment == 0 || ((uintptr_t)p & (alignment - 1)) == ZU(0));\n\treturn (p);\n}\n\nJEMALLOC_EXPORT JEMALLOC_ALLOCATOR JEMALLOC_RESTRICT_RETURN\nvoid JEMALLOC_NOTHROW *\nJEMALLOC_ATTR(malloc) JEMALLOC_ALLOC_SIZE(1)\nje_mallocx(size_t size, int flags)\n{\n\ttsd_t *tsd;\n\tvoid *p;\n\tsize_t usize;\n\n\tassert(size != 0);\n\n\tif (unlikely(malloc_init()))\n\t\tgoto label_oom;\n\ttsd = tsd_fetch();\n\n\tif (config_prof && opt_prof)\n\t\tp = imallocx_prof(tsd, size, flags, &usize);\n\telse\n\t\tp = imallocx_no_prof(tsd, size, flags, &usize);\n\tif (unlikely(p == NULL))\n\t\tgoto label_oom;\n\n\tif (config_stats) {\n\t\tassert(usize == isalloc(p, config_prof));\n\t\t*tsd_thread_allocatedp_get(tsd) += usize;\n\t}\n\tUTRACE(0, size, p);\n\tJEMALLOC_VALGRIND_MALLOC(true, p, usize, MALLOCX_ZERO_GET(flags));\n\treturn (p);\nlabel_oom:\n\tif (config_xmalloc && unlikely(opt_xmalloc)) {\n\t\tmalloc_write(\"<jemalloc>: Error in mallocx(): out of memory\\n\");\n\t\tabort();\n\t}\n\tUTRACE(0, size, 0);\n\treturn (NULL);\n}\n\nstatic void *\nirallocx_prof_sample(tsd_t *tsd, void *old_ptr, size_t old_usize,\n    size_t usize, size_t alignment, bool zero, tcache_t *tcache, arena_t *arena,\n    prof_tctx_t *tctx)\n{\n\tvoid *p;\n\n\tif (tctx == NULL)\n\t\treturn (NULL);\n\tif (usize <= SMALL_MAXCLASS) {\n\t\tp = iralloct(tsd, old_ptr, old_usize, LARGE_MINCLASS, alignment,\n\t\t    zero, tcache, arena);\n\t\tif (p == NULL)\n\t\t\treturn (NULL);\n\t\tarena_prof_promoted(p, usize);\n\t} else {\n\t\tp = iralloct(tsd, old_ptr, old_usize, usize, alignment, zero,\n\t\t    tcache, arena);\n\t}\n\n\treturn (p);\n}\n\nJEMALLOC_ALWAYS_INLINE_C void *\nirallocx_prof(tsd_t *tsd, void *old_ptr, size_t old_usize, size_t size,\n    size_t alignment, size_t *usize, bool zero, tcache_t *tcache,\n    arena_t *arena)\n{\n\tvoid *p;\n\tbool prof_active;\n\tprof_tctx_t *old_tctx, *tctx;\n\n\tprof_active = prof_active_get_unlocked();\n\told_tctx = prof_tctx_get(old_ptr);\n\ttctx = prof_alloc_prep(tsd, *usize, prof_active, true);\n\tif (unlikely((uintptr_t)tctx != (uintptr_t)1U)) {\n\t\tp = irallocx_prof_sample(tsd, old_ptr, old_usize, *usize,\n\t\t    alignment, zero, tcache, arena, tctx);\n\t} else {\n\t\tp = iralloct(tsd, old_ptr, old_usize, size, alignment, zero,\n\t\t    tcache, arena);\n\t}\n\tif (unlikely(p == NULL)) {\n\t\tprof_alloc_rollback(tsd, tctx, true);\n\t\treturn (NULL);\n\t}\n\n\tif (p == old_ptr && alignment != 0) {\n\t\t/*\n\t\t * The allocation did not move, so it is possible that the size\n\t\t * class is smaller than would guarantee the requested\n\t\t * alignment, and that the alignment constraint was\n\t\t * serendipitously satisfied.  Additionally, old_usize may not\n\t\t * be the same as the current usize because of in-place large\n\t\t * reallocation.  Therefore, query the actual value of usize.\n\t\t */\n\t\t*usize = isalloc(p, config_prof);\n\t}\n\tprof_realloc(tsd, p, *usize, tctx, prof_active, true, old_ptr,\n\t    old_usize, old_tctx);\n\n\treturn (p);\n}\n\nJEMALLOC_EXPORT JEMALLOC_ALLOCATOR JEMALLOC_RESTRICT_RETURN\nvoid JEMALLOC_NOTHROW *\nJEMALLOC_ALLOC_SIZE(2)\nje_rallocx(void *ptr, size_t size, int flags)\n{\n\tvoid *p;\n\ttsd_t *tsd;\n\tsize_t usize;\n\tsize_t old_usize;\n\tUNUSED size_t old_rzsize JEMALLOC_CC_SILENCE_INIT(0);\n\tsize_t alignment = MALLOCX_ALIGN_GET(flags);\n\tbool zero = flags & MALLOCX_ZERO;\n\tarena_t *arena;\n\ttcache_t *tcache;\n\n\tassert(ptr != NULL);\n\tassert(size != 0);\n\tassert(malloc_initialized() || IS_INITIALIZER);\n\tmalloc_thread_init();\n\ttsd = tsd_fetch();\n\n\tif (unlikely((flags & MALLOCX_ARENA_MASK) != 0)) {\n\t\tunsigned arena_ind = MALLOCX_ARENA_GET(flags);\n\t\tarena = arena_get(tsd, arena_ind, true, true);\n\t\tif (unlikely(arena == NULL))\n\t\t\tgoto label_oom;\n\t} else\n\t\tarena = NULL;\n\n\tif (unlikely((flags & MALLOCX_TCACHE_MASK) != 0)) {\n\t\tif ((flags & MALLOCX_TCACHE_MASK) == MALLOCX_TCACHE_NONE)\n\t\t\ttcache = NULL;\n\t\telse\n\t\t\ttcache = tcaches_get(tsd, MALLOCX_TCACHE_GET(flags));\n\t} else\n\t\ttcache = tcache_get(tsd, true);\n\n\told_usize = isalloc(ptr, config_prof);\n\tif (config_valgrind && unlikely(in_valgrind))\n\t\told_rzsize = u2rz(old_usize);\n\n\tif (config_prof && opt_prof) {\n\t\tusize = (alignment == 0) ? s2u(size) : sa2u(size, alignment);\n\t\tassert(usize != 0);\n\t\tp = irallocx_prof(tsd, ptr, old_usize, size, alignment, &usize,\n\t\t    zero, tcache, arena);\n\t\tif (unlikely(p == NULL))\n\t\t\tgoto label_oom;\n\t} else {\n\t\tp = iralloct(tsd, ptr, old_usize, size, alignment, zero,\n\t\t     tcache, arena);\n\t\tif (unlikely(p == NULL))\n\t\t\tgoto label_oom;\n\t\tif (config_stats || (config_valgrind && unlikely(in_valgrind)))\n\t\t\tusize = isalloc(p, config_prof);\n\t}\n\tassert(alignment == 0 || ((uintptr_t)p & (alignment - 1)) == ZU(0));\n\n\tif (config_stats) {\n\t\t*tsd_thread_allocatedp_get(tsd) += usize;\n\t\t*tsd_thread_deallocatedp_get(tsd) += old_usize;\n\t}\n\tUTRACE(ptr, size, p);\n\tJEMALLOC_VALGRIND_REALLOC(true, p, usize, false, ptr, old_usize,\n\t    old_rzsize, false, zero);\n\treturn (p);\nlabel_oom:\n\tif (config_xmalloc && unlikely(opt_xmalloc)) {\n\t\tmalloc_write(\"<jemalloc>: Error in rallocx(): out of memory\\n\");\n\t\tabort();\n\t}\n\tUTRACE(ptr, size, 0);\n\treturn (NULL);\n}\n\nJEMALLOC_ALWAYS_INLINE_C size_t\nixallocx_helper(void *ptr, size_t old_usize, size_t size, size_t extra,\n    size_t alignment, bool zero)\n{\n\tsize_t usize;\n\n\tif (ixalloc(ptr, old_usize, size, extra, alignment, zero))\n\t\treturn (old_usize);\n\tusize = isalloc(ptr, config_prof);\n\n\treturn (usize);\n}\n\nstatic size_t\nixallocx_prof_sample(void *ptr, size_t old_usize, size_t size, size_t extra,\n    size_t alignment, bool zero, prof_tctx_t *tctx)\n{\n\tsize_t usize;\n\n\tif (tctx == NULL)\n\t\treturn (old_usize);\n\tusize = ixallocx_helper(ptr, old_usize, size, extra, alignment, zero);\n\n\treturn (usize);\n}\n\nJEMALLOC_ALWAYS_INLINE_C size_t\nixallocx_prof(tsd_t *tsd, void *ptr, size_t old_usize, size_t size,\n    size_t extra, size_t alignment, bool zero)\n{\n\tsize_t usize_max, usize;\n\tbool prof_active;\n\tprof_tctx_t *old_tctx, *tctx;\n\n\tprof_active = prof_active_get_unlocked();\n\told_tctx = prof_tctx_get(ptr);\n\t/*\n\t * usize isn't knowable before ixalloc() returns when extra is non-zero.\n\t * Therefore, compute its maximum possible value and use that in\n\t * prof_alloc_prep() to decide whether to capture a backtrace.\n\t * prof_realloc() will use the actual usize to decide whether to sample.\n\t */\n\tusize_max = (alignment == 0) ? s2u(size+extra) : sa2u(size+extra,\n\t    alignment);\n\tassert(usize_max != 0);\n\ttctx = prof_alloc_prep(tsd, usize_max, prof_active, false);\n\tif (unlikely((uintptr_t)tctx != (uintptr_t)1U)) {\n\t\tusize = ixallocx_prof_sample(ptr, old_usize, size, extra,\n\t\t    alignment, zero, tctx);\n\t} else {\n\t\tusize = ixallocx_helper(ptr, old_usize, size, extra, alignment,\n\t\t    zero);\n\t}\n\tif (usize == old_usize) {\n\t\tprof_alloc_rollback(tsd, tctx, false);\n\t\treturn (usize);\n\t}\n\tprof_realloc(tsd, ptr, usize, tctx, prof_active, false, ptr, old_usize,\n\t    old_tctx);\n\n\treturn (usize);\n}\n\nJEMALLOC_EXPORT size_t JEMALLOC_NOTHROW\nje_xallocx(void *ptr, size_t size, size_t extra, int flags)\n{\n\ttsd_t *tsd;\n\tsize_t usize, old_usize;\n\tUNUSED size_t old_rzsize JEMALLOC_CC_SILENCE_INIT(0);\n\tsize_t alignment = MALLOCX_ALIGN_GET(flags);\n\tbool zero = flags & MALLOCX_ZERO;\n\n\tassert(ptr != NULL);\n\tassert(size != 0);\n\tassert(SIZE_T_MAX - size >= extra);\n\tassert(malloc_initialized() || IS_INITIALIZER);\n\tmalloc_thread_init();\n\ttsd = tsd_fetch();\n\n\told_usize = isalloc(ptr, config_prof);\n\n\t/* Clamp extra if necessary to avoid (size + extra) overflow. */\n\tif (unlikely(size + extra > HUGE_MAXCLASS)) {\n\t\t/* Check for size overflow. */\n\t\tif (unlikely(size > HUGE_MAXCLASS)) {\n\t\t\tusize = old_usize;\n\t\t\tgoto label_not_resized;\n\t\t}\n\t\textra = HUGE_MAXCLASS - size;\n\t}\n\n\tif (config_valgrind && unlikely(in_valgrind))\n\t\told_rzsize = u2rz(old_usize);\n\n\tif (config_prof && opt_prof) {\n\t\tusize = ixallocx_prof(tsd, ptr, old_usize, size, extra,\n\t\t    alignment, zero);\n\t} else {\n\t\tusize = ixallocx_helper(ptr, old_usize, size, extra, alignment,\n\t\t    zero);\n\t}\n\tif (unlikely(usize == old_usize))\n\t\tgoto label_not_resized;\n\n\tif (config_stats) {\n\t\t*tsd_thread_allocatedp_get(tsd) += usize;\n\t\t*tsd_thread_deallocatedp_get(tsd) += old_usize;\n\t}\n\tJEMALLOC_VALGRIND_REALLOC(false, ptr, usize, false, ptr, old_usize,\n\t    old_rzsize, false, zero);\nlabel_not_resized:\n\tUTRACE(ptr, size, ptr);\n\treturn (usize);\n}\n\nJEMALLOC_EXPORT size_t JEMALLOC_NOTHROW\nJEMALLOC_ATTR(pure)\nje_sallocx(const void *ptr, int flags)\n{\n\tsize_t usize;\n\n\tassert(malloc_initialized() || IS_INITIALIZER);\n\tmalloc_thread_init();\n\n\tif (config_ivsalloc)\n\t\tusize = ivsalloc(ptr, config_prof);\n\telse\n\t\tusize = isalloc(ptr, config_prof);\n\n\treturn (usize);\n}\n\nJEMALLOC_EXPORT void JEMALLOC_NOTHROW\nje_dallocx(void *ptr, int flags)\n{\n\ttsd_t *tsd;\n\ttcache_t *tcache;\n\n\tassert(ptr != NULL);\n\tassert(malloc_initialized() || IS_INITIALIZER);\n\n\ttsd = tsd_fetch();\n\tif (unlikely((flags & MALLOCX_TCACHE_MASK) != 0)) {\n\t\tif ((flags & MALLOCX_TCACHE_MASK) == MALLOCX_TCACHE_NONE)\n\t\t\ttcache = NULL;\n\t\telse\n\t\t\ttcache = tcaches_get(tsd, MALLOCX_TCACHE_GET(flags));\n\t} else\n\t\ttcache = tcache_get(tsd, false);\n\n\tUTRACE(ptr, 0, 0);\n\tifree(tsd_fetch(), ptr, tcache);\n}\n\nJEMALLOC_ALWAYS_INLINE_C size_t\ninallocx(size_t size, int flags)\n{\n\tsize_t usize;\n\n\tif (likely((flags & MALLOCX_LG_ALIGN_MASK) == 0))\n\t\tusize = s2u(size);\n\telse\n\t\tusize = sa2u(size, MALLOCX_ALIGN_GET_SPECIFIED(flags));\n\tassert(usize != 0);\n\treturn (usize);\n}\n\nJEMALLOC_EXPORT void JEMALLOC_NOTHROW\nje_sdallocx(void *ptr, size_t size, int flags)\n{\n\ttsd_t *tsd;\n\ttcache_t *tcache;\n\tsize_t usize;\n\n\tassert(ptr != NULL);\n\tassert(malloc_initialized() || IS_INITIALIZER);\n\tusize = inallocx(size, flags);\n\tassert(usize == isalloc(ptr, config_prof));\n\n\ttsd = tsd_fetch();\n\tif (unlikely((flags & MALLOCX_TCACHE_MASK) != 0)) {\n\t\tif ((flags & MALLOCX_TCACHE_MASK) == MALLOCX_TCACHE_NONE)\n\t\t\ttcache = NULL;\n\t\telse\n\t\t\ttcache = tcaches_get(tsd, MALLOCX_TCACHE_GET(flags));\n\t} else\n\t\ttcache = tcache_get(tsd, false);\n\n\tUTRACE(ptr, 0, 0);\n\tisfree(tsd, ptr, usize, tcache);\n}\n\nJEMALLOC_EXPORT size_t JEMALLOC_NOTHROW\nJEMALLOC_ATTR(pure)\nje_nallocx(size_t size, int flags)\n{\n\n\tassert(size != 0);\n\n\tif (unlikely(malloc_init()))\n\t\treturn (0);\n\n\treturn (inallocx(size, flags));\n}\n\nJEMALLOC_EXPORT int JEMALLOC_NOTHROW\nje_mallctl(const char *name, void *oldp, size_t *oldlenp, void *newp,\n    size_t newlen)\n{\n\n\tif (unlikely(malloc_init()))\n\t\treturn (EAGAIN);\n\n\treturn (ctl_byname(name, oldp, oldlenp, newp, newlen));\n}\n\nJEMALLOC_EXPORT int JEMALLOC_NOTHROW\nje_mallctlnametomib(const char *name, size_t *mibp, size_t *miblenp)\n{\n\n\tif (unlikely(malloc_init()))\n\t\treturn (EAGAIN);\n\n\treturn (ctl_nametomib(name, mibp, miblenp));\n}\n\nJEMALLOC_EXPORT int JEMALLOC_NOTHROW\nje_mallctlbymib(const size_t *mib, size_t miblen, void *oldp, size_t *oldlenp,\n  void *newp, size_t newlen)\n{\n\n\tif (unlikely(malloc_init()))\n\t\treturn (EAGAIN);\n\n\treturn (ctl_bymib(mib, miblen, oldp, oldlenp, newp, newlen));\n}\n\nJEMALLOC_EXPORT void JEMALLOC_NOTHROW\nje_malloc_stats_print(void (*write_cb)(void *, const char *), void *cbopaque,\n    const char *opts)\n{\n\n\tstats_print(write_cb, cbopaque, opts);\n}\n\nJEMALLOC_EXPORT size_t JEMALLOC_NOTHROW\nje_malloc_usable_size(JEMALLOC_USABLE_SIZE_CONST void *ptr)\n{\n\tsize_t ret;\n\n\tassert(malloc_initialized() || IS_INITIALIZER);\n\tmalloc_thread_init();\n\n\tif (config_ivsalloc)\n\t\tret = ivsalloc(ptr, config_prof);\n\telse\n\t\tret = (ptr == NULL) ? 0 : isalloc(ptr, config_prof);\n\n\treturn (ret);\n}\n\n/*\n * End non-standard functions.\n */\n/******************************************************************************/\n/*\n * The following functions are used by threading libraries for protection of\n * malloc during fork().\n */\n\n/*\n * If an application creates a thread before doing any allocation in the main\n * thread, then calls fork(2) in the main thread followed by memory allocation\n * in the child process, a race can occur that results in deadlock within the\n * child: the main thread may have forked while the created thread had\n * partially initialized the allocator.  Ordinarily jemalloc prevents\n * fork/malloc races via the following functions it registers during\n * initialization using pthread_atfork(), but of course that does no good if\n * the allocator isn't fully initialized at fork time.  The following library\n * constructor is a partial solution to this problem.  It may still be possible\n * to trigger the deadlock described above, but doing so would involve forking\n * via a library constructor that runs before jemalloc's runs.\n */\nJEMALLOC_ATTR(constructor)\nstatic void\njemalloc_constructor(void)\n{\n\n\tmalloc_init();\n}\n\n#ifndef JEMALLOC_MUTEX_INIT_CB\nvoid\njemalloc_prefork(void)\n#else\nJEMALLOC_EXPORT void\n_malloc_prefork(void)\n#endif\n{\n\tunsigned i;\n\n#ifdef JEMALLOC_MUTEX_INIT_CB\n\tif (!malloc_initialized())\n\t\treturn;\n#endif\n\tassert(malloc_initialized());\n\n\t/* Acquire all mutexes in a safe order. */\n\tctl_prefork();\n\tprof_prefork();\n\tmalloc_mutex_prefork(&arenas_lock);\n\tfor (i = 0; i < narenas_total; i++) {\n\t\tif (arenas[i] != NULL)\n\t\t\tarena_prefork(arenas[i]);\n\t}\n\tchunk_prefork();\n\tbase_prefork();\n}\n\n#ifndef JEMALLOC_MUTEX_INIT_CB\nvoid\njemalloc_postfork_parent(void)\n#else\nJEMALLOC_EXPORT void\n_malloc_postfork(void)\n#endif\n{\n\tunsigned i;\n\n#ifdef JEMALLOC_MUTEX_INIT_CB\n\tif (!malloc_initialized())\n\t\treturn;\n#endif\n\tassert(malloc_initialized());\n\n\t/* Release all mutexes, now that fork() has completed. */\n\tbase_postfork_parent();\n\tchunk_postfork_parent();\n\tfor (i = 0; i < narenas_total; i++) {\n\t\tif (arenas[i] != NULL)\n\t\t\tarena_postfork_parent(arenas[i]);\n\t}\n\tmalloc_mutex_postfork_parent(&arenas_lock);\n\tprof_postfork_parent();\n\tctl_postfork_parent();\n}\n\nvoid\njemalloc_postfork_child(void)\n{\n\tunsigned i;\n\n\tassert(malloc_initialized());\n\n\t/* Release all mutexes, now that fork() has completed. */\n\tbase_postfork_child();\n\tchunk_postfork_child();\n\tfor (i = 0; i < narenas_total; i++) {\n\t\tif (arenas[i] != NULL)\n\t\t\tarena_postfork_child(arenas[i]);\n\t}\n\tmalloc_mutex_postfork_child(&arenas_lock);\n\tprof_postfork_child();\n\tctl_postfork_child();\n}\n\n/******************************************************************************/\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.8/deps/jemalloc/src/mb.c",
    "content": "#define\tJEMALLOC_MB_C_\n#include \"jemalloc/internal/jemalloc_internal.h\"\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.8/deps/jemalloc/src/mutex.c",
    "content": "#define\tJEMALLOC_MUTEX_C_\n#include \"jemalloc/internal/jemalloc_internal.h\"\n\n#if defined(JEMALLOC_LAZY_LOCK) && !defined(_WIN32)\n#include <dlfcn.h>\n#endif\n\n#ifndef _CRT_SPINCOUNT\n#define\t_CRT_SPINCOUNT 4000\n#endif\n\n/******************************************************************************/\n/* Data. */\n\n#ifdef JEMALLOC_LAZY_LOCK\nbool isthreaded = false;\n#endif\n#ifdef JEMALLOC_MUTEX_INIT_CB\nstatic bool\t\tpostpone_init = true;\nstatic malloc_mutex_t\t*postponed_mutexes = NULL;\n#endif\n\n#if defined(JEMALLOC_LAZY_LOCK) && !defined(_WIN32)\nstatic void\tpthread_create_once(void);\n#endif\n\n/******************************************************************************/\n/*\n * We intercept pthread_create() calls in order to toggle isthreaded if the\n * process goes multi-threaded.\n */\n\n#if defined(JEMALLOC_LAZY_LOCK) && !defined(_WIN32)\nstatic int (*pthread_create_fptr)(pthread_t *__restrict, const pthread_attr_t *,\n    void *(*)(void *), void *__restrict);\n\nstatic void\npthread_create_once(void)\n{\n\n\tpthread_create_fptr = dlsym(RTLD_NEXT, \"pthread_create\");\n\tif (pthread_create_fptr == NULL) {\n\t\tmalloc_write(\"<jemalloc>: Error in dlsym(RTLD_NEXT, \"\n\t\t    \"\\\"pthread_create\\\")\\n\");\n\t\tabort();\n\t}\n\n\tisthreaded = true;\n}\n\nJEMALLOC_EXPORT int\npthread_create(pthread_t *__restrict thread,\n    const pthread_attr_t *__restrict attr, void *(*start_routine)(void *),\n    void *__restrict arg)\n{\n\tstatic pthread_once_t once_control = PTHREAD_ONCE_INIT;\n\n\tpthread_once(&once_control, pthread_create_once);\n\n\treturn (pthread_create_fptr(thread, attr, start_routine, arg));\n}\n#endif\n\n/******************************************************************************/\n\n#ifdef JEMALLOC_MUTEX_INIT_CB\nJEMALLOC_EXPORT int\t_pthread_mutex_init_calloc_cb(pthread_mutex_t *mutex,\n    void *(calloc_cb)(size_t, size_t));\n#endif\n\nbool\nmalloc_mutex_init(malloc_mutex_t *mutex)\n{\n\n#ifdef _WIN32\n#  if _WIN32_WINNT >= 0x0600\n\tInitializeSRWLock(&mutex->lock);\n#  else\n\tif (!InitializeCriticalSectionAndSpinCount(&mutex->lock,\n\t    _CRT_SPINCOUNT))\n\t\treturn (true);\n#  endif\n#elif (defined(JEMALLOC_OSSPIN))\n\tmutex->lock = 0;\n#elif (defined(JEMALLOC_MUTEX_INIT_CB))\n\tif (postpone_init) {\n\t\tmutex->postponed_next = postponed_mutexes;\n\t\tpostponed_mutexes = mutex;\n\t} else {\n\t\tif (_pthread_mutex_init_calloc_cb(&mutex->lock,\n\t\t    bootstrap_calloc) != 0)\n\t\t\treturn (true);\n\t}\n#else\n\tpthread_mutexattr_t attr;\n\n\tif (pthread_mutexattr_init(&attr) != 0)\n\t\treturn (true);\n\tpthread_mutexattr_settype(&attr, MALLOC_MUTEX_TYPE);\n\tif (pthread_mutex_init(&mutex->lock, &attr) != 0) {\n\t\tpthread_mutexattr_destroy(&attr);\n\t\treturn (true);\n\t}\n\tpthread_mutexattr_destroy(&attr);\n#endif\n\treturn (false);\n}\n\nvoid\nmalloc_mutex_prefork(malloc_mutex_t *mutex)\n{\n\n\tmalloc_mutex_lock(mutex);\n}\n\nvoid\nmalloc_mutex_postfork_parent(malloc_mutex_t *mutex)\n{\n\n\tmalloc_mutex_unlock(mutex);\n}\n\nvoid\nmalloc_mutex_postfork_child(malloc_mutex_t *mutex)\n{\n\n#ifdef JEMALLOC_MUTEX_INIT_CB\n\tmalloc_mutex_unlock(mutex);\n#else\n\tif (malloc_mutex_init(mutex)) {\n\t\tmalloc_printf(\"<jemalloc>: Error re-initializing mutex in \"\n\t\t    \"child\\n\");\n\t\tif (opt_abort)\n\t\t\tabort();\n\t}\n#endif\n}\n\nbool\nmutex_boot(void)\n{\n\n#ifdef JEMALLOC_MUTEX_INIT_CB\n\tpostpone_init = false;\n\twhile (postponed_mutexes != NULL) {\n\t\tif (_pthread_mutex_init_calloc_cb(&postponed_mutexes->lock,\n\t\t    bootstrap_calloc) != 0)\n\t\t\treturn (true);\n\t\tpostponed_mutexes = postponed_mutexes->postponed_next;\n\t}\n#endif\n\treturn (false);\n}\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.8/deps/jemalloc/src/pages.c",
    "content": "#define\tJEMALLOC_PAGES_C_\n#include \"jemalloc/internal/jemalloc_internal.h\"\n\n/******************************************************************************/\n\nvoid *\npages_map(void *addr, size_t size)\n{\n\tvoid *ret;\n\n\tassert(size != 0);\n\n#ifdef _WIN32\n\t/*\n\t * If VirtualAlloc can't allocate at the given address when one is\n\t * given, it fails and returns NULL.\n\t */\n\tret = VirtualAlloc(addr, size, MEM_COMMIT | MEM_RESERVE,\n\t    PAGE_READWRITE);\n#else\n\t/*\n\t * We don't use MAP_FIXED here, because it can cause the *replacement*\n\t * of existing mappings, and we only want to create new mappings.\n\t */\n\tret = mmap(addr, size, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANON,\n\t    -1, 0);\n\tassert(ret != NULL);\n\n\tif (ret == MAP_FAILED)\n\t\tret = NULL;\n\telse if (addr != NULL && ret != addr) {\n\t\t/*\n\t\t * We succeeded in mapping memory, but not in the right place.\n\t\t */\n\t\tpages_unmap(ret, size);\n\t\tret = NULL;\n\t}\n#endif\n\tassert(ret == NULL || (addr == NULL && ret != addr)\n\t    || (addr != NULL && ret == addr));\n\treturn (ret);\n}\n\nvoid\npages_unmap(void *addr, size_t size)\n{\n\n#ifdef _WIN32\n\tif (VirtualFree(addr, 0, MEM_RELEASE) == 0)\n#else\n\tif (munmap(addr, size) == -1)\n#endif\n\t{\n\t\tchar buf[BUFERROR_BUF];\n\n\t\tbuferror(get_errno(), buf, sizeof(buf));\n\t\tmalloc_printf(\"<jemalloc>: Error in \"\n#ifdef _WIN32\n\t\t              \"VirtualFree\"\n#else\n\t\t              \"munmap\"\n#endif\n\t\t              \"(): %s\\n\", buf);\n\t\tif (opt_abort)\n\t\t\tabort();\n\t}\n}\n\nvoid *\npages_trim(void *addr, size_t alloc_size, size_t leadsize, size_t size)\n{\n\tvoid *ret = (void *)((uintptr_t)addr + leadsize);\n\n\tassert(alloc_size >= leadsize + size);\n#ifdef _WIN32\n\t{\n\t\tvoid *new_addr;\n\n\t\tpages_unmap(addr, alloc_size);\n\t\tnew_addr = pages_map(ret, size);\n\t\tif (new_addr == ret)\n\t\t\treturn (ret);\n\t\tif (new_addr)\n\t\t\tpages_unmap(new_addr, size);\n\t\treturn (NULL);\n\t}\n#else\n\t{\n\t\tsize_t trailsize = alloc_size - leadsize - size;\n\n\t\tif (leadsize != 0)\n\t\t\tpages_unmap(addr, leadsize);\n\t\tif (trailsize != 0)\n\t\t\tpages_unmap((void *)((uintptr_t)ret + size), trailsize);\n\t\treturn (ret);\n\t}\n#endif\n}\n\nstatic bool\npages_commit_impl(void *addr, size_t size, bool commit)\n{\n\n#ifndef _WIN32\n\t/*\n\t * The following decommit/commit implementation is functional, but\n\t * always disabled because it doesn't add value beyong improved\n\t * debugging (at the cost of extra system calls) on systems that\n\t * overcommit.\n\t */\n\tif (false) {\n\t\tint prot = commit ? (PROT_READ | PROT_WRITE) : PROT_NONE;\n\t\tvoid *result = mmap(addr, size, prot, MAP_PRIVATE | MAP_ANON |\n\t\t    MAP_FIXED, -1, 0);\n\t\tif (result == MAP_FAILED)\n\t\t\treturn (true);\n\t\tif (result != addr) {\n\t\t\t/*\n\t\t\t * We succeeded in mapping memory, but not in the right\n\t\t\t * place.\n\t\t\t */\n\t\t\tpages_unmap(result, size);\n\t\t\treturn (true);\n\t\t}\n\t\treturn (false);\n\t}\n#endif\n\treturn (true);\n}\n\nbool\npages_commit(void *addr, size_t size)\n{\n\n\treturn (pages_commit_impl(addr, size, true));\n}\n\nbool\npages_decommit(void *addr, size_t size)\n{\n\n\treturn (pages_commit_impl(addr, size, false));\n}\n\nbool\npages_purge(void *addr, size_t size)\n{\n\tbool unzeroed;\n\n#ifdef _WIN32\n\tVirtualAlloc(addr, size, MEM_RESET, PAGE_READWRITE);\n\tunzeroed = true;\n#elif defined(JEMALLOC_HAVE_MADVISE)\n#  ifdef JEMALLOC_PURGE_MADVISE_DONTNEED\n#    define JEMALLOC_MADV_PURGE MADV_DONTNEED\n#    define JEMALLOC_MADV_ZEROS true\n#  elif defined(JEMALLOC_PURGE_MADVISE_FREE)\n#    define JEMALLOC_MADV_PURGE MADV_FREE\n#    define JEMALLOC_MADV_ZEROS false\n#  else\n#    error \"No madvise(2) flag defined for purging unused dirty pages.\"\n#  endif\n\tint err = madvise(addr, size, JEMALLOC_MADV_PURGE);\n\tunzeroed = (!JEMALLOC_MADV_ZEROS || err != 0);\n#  undef JEMALLOC_MADV_PURGE\n#  undef JEMALLOC_MADV_ZEROS\n#else\n\t/* Last resort no-op. */\n\tunzeroed = true;\n#endif\n\treturn (unzeroed);\n}\n\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.8/deps/jemalloc/src/prof.c",
    "content": "#define\tJEMALLOC_PROF_C_\n#include \"jemalloc/internal/jemalloc_internal.h\"\n/******************************************************************************/\n\n#ifdef JEMALLOC_PROF_LIBUNWIND\n#define\tUNW_LOCAL_ONLY\n#include <libunwind.h>\n#endif\n\n#ifdef JEMALLOC_PROF_LIBGCC\n#include <unwind.h>\n#endif\n\n/******************************************************************************/\n/* Data. */\n\nbool\t\topt_prof = false;\nbool\t\topt_prof_active = true;\nbool\t\topt_prof_thread_active_init = true;\nsize_t\t\topt_lg_prof_sample = LG_PROF_SAMPLE_DEFAULT;\nssize_t\t\topt_lg_prof_interval = LG_PROF_INTERVAL_DEFAULT;\nbool\t\topt_prof_gdump = false;\nbool\t\topt_prof_final = false;\nbool\t\topt_prof_leak = false;\nbool\t\topt_prof_accum = false;\nchar\t\topt_prof_prefix[\n    /* Minimize memory bloat for non-prof builds. */\n#ifdef JEMALLOC_PROF\n    PATH_MAX +\n#endif\n    1];\n\n/*\n * Initialized as opt_prof_active, and accessed via\n * prof_active_[gs]et{_unlocked,}().\n */\nbool\t\t\tprof_active;\nstatic malloc_mutex_t\tprof_active_mtx;\n\n/*\n * Initialized as opt_prof_thread_active_init, and accessed via\n * prof_thread_active_init_[gs]et().\n */\nstatic bool\t\tprof_thread_active_init;\nstatic malloc_mutex_t\tprof_thread_active_init_mtx;\n\n/*\n * Initialized as opt_prof_gdump, and accessed via\n * prof_gdump_[gs]et{_unlocked,}().\n */\nbool\t\t\tprof_gdump_val;\nstatic malloc_mutex_t\tprof_gdump_mtx;\n\nuint64_t\tprof_interval = 0;\n\nsize_t\t\tlg_prof_sample;\n\n/*\n * Table of mutexes that are shared among gctx's.  These are leaf locks, so\n * there is no problem with using them for more than one gctx at the same time.\n * The primary motivation for this sharing though is that gctx's are ephemeral,\n * and destroying mutexes causes complications for systems that allocate when\n * creating/destroying mutexes.\n */\nstatic malloc_mutex_t\t*gctx_locks;\nstatic unsigned\t\tcum_gctxs; /* Atomic counter. */\n\n/*\n * Table of mutexes that are shared among tdata's.  No operations require\n * holding multiple tdata locks, so there is no problem with using them for more\n * than one tdata at the same time, even though a gctx lock may be acquired\n * while holding a tdata lock.\n */\nstatic malloc_mutex_t\t*tdata_locks;\n\n/*\n * Global hash of (prof_bt_t *)-->(prof_gctx_t *).  This is the master data\n * structure that knows about all backtraces currently captured.\n */\nstatic ckh_t\t\tbt2gctx;\nstatic malloc_mutex_t\tbt2gctx_mtx;\n\n/*\n * Tree of all extant prof_tdata_t structures, regardless of state,\n * {attached,detached,expired}.\n */\nstatic prof_tdata_tree_t\ttdatas;\nstatic malloc_mutex_t\ttdatas_mtx;\n\nstatic uint64_t\t\tnext_thr_uid;\nstatic malloc_mutex_t\tnext_thr_uid_mtx;\n\nstatic malloc_mutex_t\tprof_dump_seq_mtx;\nstatic uint64_t\t\tprof_dump_seq;\nstatic uint64_t\t\tprof_dump_iseq;\nstatic uint64_t\t\tprof_dump_mseq;\nstatic uint64_t\t\tprof_dump_useq;\n\n/*\n * This buffer is rather large for stack allocation, so use a single buffer for\n * all profile dumps.\n */\nstatic malloc_mutex_t\tprof_dump_mtx;\nstatic char\t\tprof_dump_buf[\n    /* Minimize memory bloat for non-prof builds. */\n#ifdef JEMALLOC_PROF\n    PROF_DUMP_BUFSIZE\n#else\n    1\n#endif\n];\nstatic unsigned\t\tprof_dump_buf_end;\nstatic int\t\tprof_dump_fd;\n\n/* Do not dump any profiles until bootstrapping is complete. */\nstatic bool\t\tprof_booted = false;\n\n/******************************************************************************/\n/*\n * Function prototypes for static functions that are referenced prior to\n * definition.\n */\n\nstatic bool\tprof_tctx_should_destroy(prof_tctx_t *tctx);\nstatic void\tprof_tctx_destroy(tsd_t *tsd, prof_tctx_t *tctx);\nstatic bool\tprof_tdata_should_destroy(prof_tdata_t *tdata,\n    bool even_if_attached);\nstatic void\tprof_tdata_destroy(tsd_t *tsd, prof_tdata_t *tdata,\n    bool even_if_attached);\nstatic char\t*prof_thread_name_alloc(tsd_t *tsd, const char *thread_name);\n\n/******************************************************************************/\n/* Red-black trees. */\n\nJEMALLOC_INLINE_C int\nprof_tctx_comp(const prof_tctx_t *a, const prof_tctx_t *b)\n{\n\tuint64_t a_thr_uid = a->thr_uid;\n\tuint64_t b_thr_uid = b->thr_uid;\n\tint ret = (a_thr_uid > b_thr_uid) - (a_thr_uid < b_thr_uid);\n\tif (ret == 0) {\n\t\tuint64_t a_thr_discrim = a->thr_discrim;\n\t\tuint64_t b_thr_discrim = b->thr_discrim;\n\t\tret = (a_thr_discrim > b_thr_discrim) - (a_thr_discrim <\n\t\t    b_thr_discrim);\n\t\tif (ret == 0) {\n\t\t\tuint64_t a_tctx_uid = a->tctx_uid;\n\t\t\tuint64_t b_tctx_uid = b->tctx_uid;\n\t\t\tret = (a_tctx_uid > b_tctx_uid) - (a_tctx_uid <\n\t\t\t    b_tctx_uid);\n\t\t}\n\t}\n\treturn (ret);\n}\n\nrb_gen(static UNUSED, tctx_tree_, prof_tctx_tree_t, prof_tctx_t,\n    tctx_link, prof_tctx_comp)\n\nJEMALLOC_INLINE_C int\nprof_gctx_comp(const prof_gctx_t *a, const prof_gctx_t *b)\n{\n\tunsigned a_len = a->bt.len;\n\tunsigned b_len = b->bt.len;\n\tunsigned comp_len = (a_len < b_len) ? a_len : b_len;\n\tint ret = memcmp(a->bt.vec, b->bt.vec, comp_len * sizeof(void *));\n\tif (ret == 0)\n\t\tret = (a_len > b_len) - (a_len < b_len);\n\treturn (ret);\n}\n\nrb_gen(static UNUSED, gctx_tree_, prof_gctx_tree_t, prof_gctx_t, dump_link,\n    prof_gctx_comp)\n\nJEMALLOC_INLINE_C int\nprof_tdata_comp(const prof_tdata_t *a, const prof_tdata_t *b)\n{\n\tint ret;\n\tuint64_t a_uid = a->thr_uid;\n\tuint64_t b_uid = b->thr_uid;\n\n\tret = ((a_uid > b_uid) - (a_uid < b_uid));\n\tif (ret == 0) {\n\t\tuint64_t a_discrim = a->thr_discrim;\n\t\tuint64_t b_discrim = b->thr_discrim;\n\n\t\tret = ((a_discrim > b_discrim) - (a_discrim < b_discrim));\n\t}\n\treturn (ret);\n}\n\nrb_gen(static UNUSED, tdata_tree_, prof_tdata_tree_t, prof_tdata_t, tdata_link,\n    prof_tdata_comp)\n\n/******************************************************************************/\n\nvoid\nprof_alloc_rollback(tsd_t *tsd, prof_tctx_t *tctx, bool updated)\n{\n\tprof_tdata_t *tdata;\n\n\tcassert(config_prof);\n\n\tif (updated) {\n\t\t/*\n\t\t * Compute a new sample threshold.  This isn't very important in\n\t\t * practice, because this function is rarely executed, so the\n\t\t * potential for sample bias is minimal except in contrived\n\t\t * programs.\n\t\t */\n\t\ttdata = prof_tdata_get(tsd, true);\n\t\tif (tdata != NULL)\n\t\t\tprof_sample_threshold_update(tdata);\n\t}\n\n\tif ((uintptr_t)tctx > (uintptr_t)1U) {\n\t\tmalloc_mutex_lock(tctx->tdata->lock);\n\t\ttctx->prepared = false;\n\t\tif (prof_tctx_should_destroy(tctx))\n\t\t\tprof_tctx_destroy(tsd, tctx);\n\t\telse\n\t\t\tmalloc_mutex_unlock(tctx->tdata->lock);\n\t}\n}\n\nvoid\nprof_malloc_sample_object(const void *ptr, size_t usize, prof_tctx_t *tctx)\n{\n\n\tprof_tctx_set(ptr, usize, tctx);\n\n\tmalloc_mutex_lock(tctx->tdata->lock);\n\ttctx->cnts.curobjs++;\n\ttctx->cnts.curbytes += usize;\n\tif (opt_prof_accum) {\n\t\ttctx->cnts.accumobjs++;\n\t\ttctx->cnts.accumbytes += usize;\n\t}\n\ttctx->prepared = false;\n\tmalloc_mutex_unlock(tctx->tdata->lock);\n}\n\nvoid\nprof_free_sampled_object(tsd_t *tsd, size_t usize, prof_tctx_t *tctx)\n{\n\n\tmalloc_mutex_lock(tctx->tdata->lock);\n\tassert(tctx->cnts.curobjs > 0);\n\tassert(tctx->cnts.curbytes >= usize);\n\ttctx->cnts.curobjs--;\n\ttctx->cnts.curbytes -= usize;\n\n\tif (prof_tctx_should_destroy(tctx))\n\t\tprof_tctx_destroy(tsd, tctx);\n\telse\n\t\tmalloc_mutex_unlock(tctx->tdata->lock);\n}\n\nvoid\nbt_init(prof_bt_t *bt, void **vec)\n{\n\n\tcassert(config_prof);\n\n\tbt->vec = vec;\n\tbt->len = 0;\n}\n\nJEMALLOC_INLINE_C void\nprof_enter(tsd_t *tsd, prof_tdata_t *tdata)\n{\n\n\tcassert(config_prof);\n\tassert(tdata == prof_tdata_get(tsd, false));\n\n\tif (tdata != NULL) {\n\t\tassert(!tdata->enq);\n\t\ttdata->enq = true;\n\t}\n\n\tmalloc_mutex_lock(&bt2gctx_mtx);\n}\n\nJEMALLOC_INLINE_C void\nprof_leave(tsd_t *tsd, prof_tdata_t *tdata)\n{\n\n\tcassert(config_prof);\n\tassert(tdata == prof_tdata_get(tsd, false));\n\n\tmalloc_mutex_unlock(&bt2gctx_mtx);\n\n\tif (tdata != NULL) {\n\t\tbool idump, gdump;\n\n\t\tassert(tdata->enq);\n\t\ttdata->enq = false;\n\t\tidump = tdata->enq_idump;\n\t\ttdata->enq_idump = false;\n\t\tgdump = tdata->enq_gdump;\n\t\ttdata->enq_gdump = false;\n\n\t\tif (idump)\n\t\t\tprof_idump();\n\t\tif (gdump)\n\t\t\tprof_gdump();\n\t}\n}\n\n#ifdef JEMALLOC_PROF_LIBUNWIND\nvoid\nprof_backtrace(prof_bt_t *bt)\n{\n\tint nframes;\n\n\tcassert(config_prof);\n\tassert(bt->len == 0);\n\tassert(bt->vec != NULL);\n\n\tnframes = unw_backtrace(bt->vec, PROF_BT_MAX);\n\tif (nframes <= 0)\n\t\treturn;\n\tbt->len = nframes;\n}\n#elif (defined(JEMALLOC_PROF_LIBGCC))\nstatic _Unwind_Reason_Code\nprof_unwind_init_callback(struct _Unwind_Context *context, void *arg)\n{\n\n\tcassert(config_prof);\n\n\treturn (_URC_NO_REASON);\n}\n\nstatic _Unwind_Reason_Code\nprof_unwind_callback(struct _Unwind_Context *context, void *arg)\n{\n\tprof_unwind_data_t *data = (prof_unwind_data_t *)arg;\n\tvoid *ip;\n\n\tcassert(config_prof);\n\n\tip = (void *)_Unwind_GetIP(context);\n\tif (ip == NULL)\n\t\treturn (_URC_END_OF_STACK);\n\tdata->bt->vec[data->bt->len] = ip;\n\tdata->bt->len++;\n\tif (data->bt->len == data->max)\n\t\treturn (_URC_END_OF_STACK);\n\n\treturn (_URC_NO_REASON);\n}\n\nvoid\nprof_backtrace(prof_bt_t *bt)\n{\n\tprof_unwind_data_t data = {bt, PROF_BT_MAX};\n\n\tcassert(config_prof);\n\n\t_Unwind_Backtrace(prof_unwind_callback, &data);\n}\n#elif (defined(JEMALLOC_PROF_GCC))\nvoid\nprof_backtrace(prof_bt_t *bt)\n{\n#define\tBT_FRAME(i)\t\t\t\t\t\t\t\\\n\tif ((i) < PROF_BT_MAX) {\t\t\t\t\t\\\n\t\tvoid *p;\t\t\t\t\t\t\\\n\t\tif (__builtin_frame_address(i) == 0)\t\t\t\\\n\t\t\treturn;\t\t\t\t\t\t\\\n\t\tp = __builtin_return_address(i);\t\t\t\\\n\t\tif (p == NULL)\t\t\t\t\t\t\\\n\t\t\treturn;\t\t\t\t\t\t\\\n\t\tbt->vec[(i)] = p;\t\t\t\t\t\\\n\t\tbt->len = (i) + 1;\t\t\t\t\t\\\n\t} else\t\t\t\t\t\t\t\t\\\n\t\treturn;\n\n\tcassert(config_prof);\n\n\tBT_FRAME(0)\n\tBT_FRAME(1)\n\tBT_FRAME(2)\n\tBT_FRAME(3)\n\tBT_FRAME(4)\n\tBT_FRAME(5)\n\tBT_FRAME(6)\n\tBT_FRAME(7)\n\tBT_FRAME(8)\n\tBT_FRAME(9)\n\n\tBT_FRAME(10)\n\tBT_FRAME(11)\n\tBT_FRAME(12)\n\tBT_FRAME(13)\n\tBT_FRAME(14)\n\tBT_FRAME(15)\n\tBT_FRAME(16)\n\tBT_FRAME(17)\n\tBT_FRAME(18)\n\tBT_FRAME(19)\n\n\tBT_FRAME(20)\n\tBT_FRAME(21)\n\tBT_FRAME(22)\n\tBT_FRAME(23)\n\tBT_FRAME(24)\n\tBT_FRAME(25)\n\tBT_FRAME(26)\n\tBT_FRAME(27)\n\tBT_FRAME(28)\n\tBT_FRAME(29)\n\n\tBT_FRAME(30)\n\tBT_FRAME(31)\n\tBT_FRAME(32)\n\tBT_FRAME(33)\n\tBT_FRAME(34)\n\tBT_FRAME(35)\n\tBT_FRAME(36)\n\tBT_FRAME(37)\n\tBT_FRAME(38)\n\tBT_FRAME(39)\n\n\tBT_FRAME(40)\n\tBT_FRAME(41)\n\tBT_FRAME(42)\n\tBT_FRAME(43)\n\tBT_FRAME(44)\n\tBT_FRAME(45)\n\tBT_FRAME(46)\n\tBT_FRAME(47)\n\tBT_FRAME(48)\n\tBT_FRAME(49)\n\n\tBT_FRAME(50)\n\tBT_FRAME(51)\n\tBT_FRAME(52)\n\tBT_FRAME(53)\n\tBT_FRAME(54)\n\tBT_FRAME(55)\n\tBT_FRAME(56)\n\tBT_FRAME(57)\n\tBT_FRAME(58)\n\tBT_FRAME(59)\n\n\tBT_FRAME(60)\n\tBT_FRAME(61)\n\tBT_FRAME(62)\n\tBT_FRAME(63)\n\tBT_FRAME(64)\n\tBT_FRAME(65)\n\tBT_FRAME(66)\n\tBT_FRAME(67)\n\tBT_FRAME(68)\n\tBT_FRAME(69)\n\n\tBT_FRAME(70)\n\tBT_FRAME(71)\n\tBT_FRAME(72)\n\tBT_FRAME(73)\n\tBT_FRAME(74)\n\tBT_FRAME(75)\n\tBT_FRAME(76)\n\tBT_FRAME(77)\n\tBT_FRAME(78)\n\tBT_FRAME(79)\n\n\tBT_FRAME(80)\n\tBT_FRAME(81)\n\tBT_FRAME(82)\n\tBT_FRAME(83)\n\tBT_FRAME(84)\n\tBT_FRAME(85)\n\tBT_FRAME(86)\n\tBT_FRAME(87)\n\tBT_FRAME(88)\n\tBT_FRAME(89)\n\n\tBT_FRAME(90)\n\tBT_FRAME(91)\n\tBT_FRAME(92)\n\tBT_FRAME(93)\n\tBT_FRAME(94)\n\tBT_FRAME(95)\n\tBT_FRAME(96)\n\tBT_FRAME(97)\n\tBT_FRAME(98)\n\tBT_FRAME(99)\n\n\tBT_FRAME(100)\n\tBT_FRAME(101)\n\tBT_FRAME(102)\n\tBT_FRAME(103)\n\tBT_FRAME(104)\n\tBT_FRAME(105)\n\tBT_FRAME(106)\n\tBT_FRAME(107)\n\tBT_FRAME(108)\n\tBT_FRAME(109)\n\n\tBT_FRAME(110)\n\tBT_FRAME(111)\n\tBT_FRAME(112)\n\tBT_FRAME(113)\n\tBT_FRAME(114)\n\tBT_FRAME(115)\n\tBT_FRAME(116)\n\tBT_FRAME(117)\n\tBT_FRAME(118)\n\tBT_FRAME(119)\n\n\tBT_FRAME(120)\n\tBT_FRAME(121)\n\tBT_FRAME(122)\n\tBT_FRAME(123)\n\tBT_FRAME(124)\n\tBT_FRAME(125)\n\tBT_FRAME(126)\n\tBT_FRAME(127)\n#undef BT_FRAME\n}\n#else\nvoid\nprof_backtrace(prof_bt_t *bt)\n{\n\n\tcassert(config_prof);\n\tnot_reached();\n}\n#endif\n\nstatic malloc_mutex_t *\nprof_gctx_mutex_choose(void)\n{\n\tunsigned ngctxs = atomic_add_u(&cum_gctxs, 1);\n\n\treturn (&gctx_locks[(ngctxs - 1) % PROF_NCTX_LOCKS]);\n}\n\nstatic malloc_mutex_t *\nprof_tdata_mutex_choose(uint64_t thr_uid)\n{\n\n\treturn (&tdata_locks[thr_uid % PROF_NTDATA_LOCKS]);\n}\n\nstatic prof_gctx_t *\nprof_gctx_create(tsd_t *tsd, prof_bt_t *bt)\n{\n\t/*\n\t * Create a single allocation that has space for vec of length bt->len.\n\t */\n\tprof_gctx_t *gctx = (prof_gctx_t *)iallocztm(tsd, offsetof(prof_gctx_t,\n\t    vec) + (bt->len * sizeof(void *)), false, tcache_get(tsd, true),\n\t    true, NULL);\n\tif (gctx == NULL)\n\t\treturn (NULL);\n\tgctx->lock = prof_gctx_mutex_choose();\n\t/*\n\t * Set nlimbo to 1, in order to avoid a race condition with\n\t * prof_tctx_destroy()/prof_gctx_try_destroy().\n\t */\n\tgctx->nlimbo = 1;\n\ttctx_tree_new(&gctx->tctxs);\n\t/* Duplicate bt. */\n\tmemcpy(gctx->vec, bt->vec, bt->len * sizeof(void *));\n\tgctx->bt.vec = gctx->vec;\n\tgctx->bt.len = bt->len;\n\treturn (gctx);\n}\n\nstatic void\nprof_gctx_try_destroy(tsd_t *tsd, prof_tdata_t *tdata_self, prof_gctx_t *gctx,\n    prof_tdata_t *tdata)\n{\n\n\tcassert(config_prof);\n\n\t/*\n\t * Check that gctx is still unused by any thread cache before destroying\n\t * it.  prof_lookup() increments gctx->nlimbo in order to avoid a race\n\t * condition with this function, as does prof_tctx_destroy() in order to\n\t * avoid a race between the main body of prof_tctx_destroy() and entry\n\t * into this function.\n\t */\n\tprof_enter(tsd, tdata_self);\n\tmalloc_mutex_lock(gctx->lock);\n\tassert(gctx->nlimbo != 0);\n\tif (tctx_tree_empty(&gctx->tctxs) && gctx->nlimbo == 1) {\n\t\t/* Remove gctx from bt2gctx. */\n\t\tif (ckh_remove(tsd, &bt2gctx, &gctx->bt, NULL, NULL))\n\t\t\tnot_reached();\n\t\tprof_leave(tsd, tdata_self);\n\t\t/* Destroy gctx. */\n\t\tmalloc_mutex_unlock(gctx->lock);\n\t\tidalloctm(tsd, gctx, tcache_get(tsd, false), true);\n\t} else {\n\t\t/*\n\t\t * Compensate for increment in prof_tctx_destroy() or\n\t\t * prof_lookup().\n\t\t */\n\t\tgctx->nlimbo--;\n\t\tmalloc_mutex_unlock(gctx->lock);\n\t\tprof_leave(tsd, tdata_self);\n\t}\n}\n\n/* tctx->tdata->lock must be held. */\nstatic bool\nprof_tctx_should_destroy(prof_tctx_t *tctx)\n{\n\n\tif (opt_prof_accum)\n\t\treturn (false);\n\tif (tctx->cnts.curobjs != 0)\n\t\treturn (false);\n\tif (tctx->prepared)\n\t\treturn (false);\n\treturn (true);\n}\n\nstatic bool\nprof_gctx_should_destroy(prof_gctx_t *gctx)\n{\n\n\tif (opt_prof_accum)\n\t\treturn (false);\n\tif (!tctx_tree_empty(&gctx->tctxs))\n\t\treturn (false);\n\tif (gctx->nlimbo != 0)\n\t\treturn (false);\n\treturn (true);\n}\n\n/* tctx->tdata->lock is held upon entry, and released before return. */\nstatic void\nprof_tctx_destroy(tsd_t *tsd, prof_tctx_t *tctx)\n{\n\tprof_tdata_t *tdata = tctx->tdata;\n\tprof_gctx_t *gctx = tctx->gctx;\n\tbool destroy_tdata, destroy_tctx, destroy_gctx;\n\n\tassert(tctx->cnts.curobjs == 0);\n\tassert(tctx->cnts.curbytes == 0);\n\tassert(!opt_prof_accum);\n\tassert(tctx->cnts.accumobjs == 0);\n\tassert(tctx->cnts.accumbytes == 0);\n\n\tckh_remove(tsd, &tdata->bt2tctx, &gctx->bt, NULL, NULL);\n\tdestroy_tdata = prof_tdata_should_destroy(tdata, false);\n\tmalloc_mutex_unlock(tdata->lock);\n\n\tmalloc_mutex_lock(gctx->lock);\n\tswitch (tctx->state) {\n\tcase prof_tctx_state_nominal:\n\t\ttctx_tree_remove(&gctx->tctxs, tctx);\n\t\tdestroy_tctx = true;\n\t\tif (prof_gctx_should_destroy(gctx)) {\n\t\t\t/*\n\t\t\t * Increment gctx->nlimbo in order to keep another\n\t\t\t * thread from winning the race to destroy gctx while\n\t\t\t * this one has gctx->lock dropped.  Without this, it\n\t\t\t * would be possible for another thread to:\n\t\t\t *\n\t\t\t * 1) Sample an allocation associated with gctx.\n\t\t\t * 2) Deallocate the sampled object.\n\t\t\t * 3) Successfully prof_gctx_try_destroy(gctx).\n\t\t\t *\n\t\t\t * The result would be that gctx no longer exists by the\n\t\t\t * time this thread accesses it in\n\t\t\t * prof_gctx_try_destroy().\n\t\t\t */\n\t\t\tgctx->nlimbo++;\n\t\t\tdestroy_gctx = true;\n\t\t} else\n\t\t\tdestroy_gctx = false;\n\t\tbreak;\n\tcase prof_tctx_state_dumping:\n\t\t/*\n\t\t * A dumping thread needs tctx to remain valid until dumping\n\t\t * has finished.  Change state such that the dumping thread will\n\t\t * complete destruction during a late dump iteration phase.\n\t\t */\n\t\ttctx->state = prof_tctx_state_purgatory;\n\t\tdestroy_tctx = false;\n\t\tdestroy_gctx = false;\n\t\tbreak;\n\tdefault:\n\t\tnot_reached();\n\t\tdestroy_tctx = false;\n\t\tdestroy_gctx = false;\n\t}\n\tmalloc_mutex_unlock(gctx->lock);\n\tif (destroy_gctx) {\n\t\tprof_gctx_try_destroy(tsd, prof_tdata_get(tsd, false), gctx,\n\t\t    tdata);\n\t}\n\n\tif (destroy_tdata)\n\t\tprof_tdata_destroy(tsd, tdata, false);\n\n\tif (destroy_tctx)\n\t\tidalloctm(tsd, tctx, tcache_get(tsd, false), true);\n}\n\nstatic bool\nprof_lookup_global(tsd_t *tsd, prof_bt_t *bt, prof_tdata_t *tdata,\n    void **p_btkey, prof_gctx_t **p_gctx, bool *p_new_gctx)\n{\n\tunion {\n\t\tprof_gctx_t\t*p;\n\t\tvoid\t\t*v;\n\t} gctx;\n\tunion {\n\t\tprof_bt_t\t*p;\n\t\tvoid\t\t*v;\n\t} btkey;\n\tbool new_gctx;\n\n\tprof_enter(tsd, tdata);\n\tif (ckh_search(&bt2gctx, bt, &btkey.v, &gctx.v)) {\n\t\t/* bt has never been seen before.  Insert it. */\n\t\tgctx.p = prof_gctx_create(tsd, bt);\n\t\tif (gctx.v == NULL) {\n\t\t\tprof_leave(tsd, tdata);\n\t\t\treturn (true);\n\t\t}\n\t\tbtkey.p = &gctx.p->bt;\n\t\tif (ckh_insert(tsd, &bt2gctx, btkey.v, gctx.v)) {\n\t\t\t/* OOM. */\n\t\t\tprof_leave(tsd, tdata);\n\t\t\tidalloctm(tsd, gctx.v, tcache_get(tsd, false), true);\n\t\t\treturn (true);\n\t\t}\n\t\tnew_gctx = true;\n\t} else {\n\t\t/*\n\t\t * Increment nlimbo, in order to avoid a race condition with\n\t\t * prof_tctx_destroy()/prof_gctx_try_destroy().\n\t\t */\n\t\tmalloc_mutex_lock(gctx.p->lock);\n\t\tgctx.p->nlimbo++;\n\t\tmalloc_mutex_unlock(gctx.p->lock);\n\t\tnew_gctx = false;\n\t}\n\tprof_leave(tsd, tdata);\n\n\t*p_btkey = btkey.v;\n\t*p_gctx = gctx.p;\n\t*p_new_gctx = new_gctx;\n\treturn (false);\n}\n\nprof_tctx_t *\nprof_lookup(tsd_t *tsd, prof_bt_t *bt)\n{\n\tunion {\n\t\tprof_tctx_t\t*p;\n\t\tvoid\t\t*v;\n\t} ret;\n\tprof_tdata_t *tdata;\n\tbool not_found;\n\n\tcassert(config_prof);\n\n\ttdata = prof_tdata_get(tsd, false);\n\tif (tdata == NULL)\n\t\treturn (NULL);\n\n\tmalloc_mutex_lock(tdata->lock);\n\tnot_found = ckh_search(&tdata->bt2tctx, bt, NULL, &ret.v);\n\tif (!not_found) /* Note double negative! */\n\t\tret.p->prepared = true;\n\tmalloc_mutex_unlock(tdata->lock);\n\tif (not_found) {\n\t\ttcache_t *tcache;\n\t\tvoid *btkey;\n\t\tprof_gctx_t *gctx;\n\t\tbool new_gctx, error;\n\n\t\t/*\n\t\t * This thread's cache lacks bt.  Look for it in the global\n\t\t * cache.\n\t\t */\n\t\tif (prof_lookup_global(tsd, bt, tdata, &btkey, &gctx,\n\t\t    &new_gctx))\n\t\t\treturn (NULL);\n\n\t\t/* Link a prof_tctx_t into gctx for this thread. */\n\t\ttcache = tcache_get(tsd, true);\n\t\tret.v = iallocztm(tsd, sizeof(prof_tctx_t), false, tcache, true,\n\t\t    NULL);\n\t\tif (ret.p == NULL) {\n\t\t\tif (new_gctx)\n\t\t\t\tprof_gctx_try_destroy(tsd, tdata, gctx, tdata);\n\t\t\treturn (NULL);\n\t\t}\n\t\tret.p->tdata = tdata;\n\t\tret.p->thr_uid = tdata->thr_uid;\n\t\tret.p->thr_discrim = tdata->thr_discrim;\n\t\tmemset(&ret.p->cnts, 0, sizeof(prof_cnt_t));\n\t\tret.p->gctx = gctx;\n\t\tret.p->tctx_uid = tdata->tctx_uid_next++;\n\t\tret.p->prepared = true;\n\t\tret.p->state = prof_tctx_state_initializing;\n\t\tmalloc_mutex_lock(tdata->lock);\n\t\terror = ckh_insert(tsd, &tdata->bt2tctx, btkey, ret.v);\n\t\tmalloc_mutex_unlock(tdata->lock);\n\t\tif (error) {\n\t\t\tif (new_gctx)\n\t\t\t\tprof_gctx_try_destroy(tsd, tdata, gctx, tdata);\n\t\t\tidalloctm(tsd, ret.v, tcache, true);\n\t\t\treturn (NULL);\n\t\t}\n\t\tmalloc_mutex_lock(gctx->lock);\n\t\tret.p->state = prof_tctx_state_nominal;\n\t\ttctx_tree_insert(&gctx->tctxs, ret.p);\n\t\tgctx->nlimbo--;\n\t\tmalloc_mutex_unlock(gctx->lock);\n\t}\n\n\treturn (ret.p);\n}\n\nvoid\nprof_sample_threshold_update(prof_tdata_t *tdata)\n{\n\t/*\n\t * The body of this function is compiled out unless heap profiling is\n\t * enabled, so that it is possible to compile jemalloc with floating\n\t * point support completely disabled.  Avoiding floating point code is\n\t * important on memory-constrained systems, but it also enables a\n\t * workaround for versions of glibc that don't properly save/restore\n\t * floating point registers during dynamic lazy symbol loading (which\n\t * internally calls into whatever malloc implementation happens to be\n\t * integrated into the application).  Note that some compilers (e.g.\n\t * gcc 4.8) may use floating point registers for fast memory moves, so\n\t * jemalloc must be compiled with such optimizations disabled (e.g.\n\t * -mno-sse) in order for the workaround to be complete.\n\t */\n#ifdef JEMALLOC_PROF\n\tuint64_t r;\n\tdouble u;\n\n\tif (!config_prof)\n\t\treturn;\n\n\tif (lg_prof_sample == 0) {\n\t\ttdata->bytes_until_sample = 0;\n\t\treturn;\n\t}\n\n\t/*\n\t * Compute sample interval as a geometrically distributed random\n\t * variable with mean (2^lg_prof_sample).\n\t *\n\t *                             __        __\n\t *                             |  log(u)  |                     1\n\t * tdata->bytes_until_sample = | -------- |, where p = ---------------\n\t *                             | log(1-p) |             lg_prof_sample\n\t *                                                     2\n\t *\n\t * For more information on the math, see:\n\t *\n\t *   Non-Uniform Random Variate Generation\n\t *   Luc Devroye\n\t *   Springer-Verlag, New York, 1986\n\t *   pp 500\n\t *   (http://luc.devroye.org/rnbookindex.html)\n\t */\n\tprng64(r, 53, tdata->prng_state, UINT64_C(6364136223846793005),\n\t    UINT64_C(1442695040888963407));\n\tu = (double)r * (1.0/9007199254740992.0L);\n\ttdata->bytes_until_sample = (uint64_t)(log(u) /\n\t    log(1.0 - (1.0 / (double)((uint64_t)1U << lg_prof_sample))))\n\t    + (uint64_t)1U;\n#endif\n}\n\n#ifdef JEMALLOC_JET\nstatic prof_tdata_t *\nprof_tdata_count_iter(prof_tdata_tree_t *tdatas, prof_tdata_t *tdata, void *arg)\n{\n\tsize_t *tdata_count = (size_t *)arg;\n\n\t(*tdata_count)++;\n\n\treturn (NULL);\n}\n\nsize_t\nprof_tdata_count(void)\n{\n\tsize_t tdata_count = 0;\n\n\tmalloc_mutex_lock(&tdatas_mtx);\n\ttdata_tree_iter(&tdatas, NULL, prof_tdata_count_iter,\n\t    (void *)&tdata_count);\n\tmalloc_mutex_unlock(&tdatas_mtx);\n\n\treturn (tdata_count);\n}\n#endif\n\n#ifdef JEMALLOC_JET\nsize_t\nprof_bt_count(void)\n{\n\tsize_t bt_count;\n\ttsd_t *tsd;\n\tprof_tdata_t *tdata;\n\n\ttsd = tsd_fetch();\n\ttdata = prof_tdata_get(tsd, false);\n\tif (tdata == NULL)\n\t\treturn (0);\n\n\tmalloc_mutex_lock(&bt2gctx_mtx);\n\tbt_count = ckh_count(&bt2gctx);\n\tmalloc_mutex_unlock(&bt2gctx_mtx);\n\n\treturn (bt_count);\n}\n#endif\n\n#ifdef JEMALLOC_JET\n#undef prof_dump_open\n#define\tprof_dump_open JEMALLOC_N(prof_dump_open_impl)\n#endif\nstatic int\nprof_dump_open(bool propagate_err, const char *filename)\n{\n\tint fd;\n\n\tfd = creat(filename, 0644);\n\tif (fd == -1 && !propagate_err) {\n\t\tmalloc_printf(\"<jemalloc>: creat(\\\"%s\\\"), 0644) failed\\n\",\n\t\t    filename);\n\t\tif (opt_abort)\n\t\t\tabort();\n\t}\n\n\treturn (fd);\n}\n#ifdef JEMALLOC_JET\n#undef prof_dump_open\n#define\tprof_dump_open JEMALLOC_N(prof_dump_open)\nprof_dump_open_t *prof_dump_open = JEMALLOC_N(prof_dump_open_impl);\n#endif\n\nstatic bool\nprof_dump_flush(bool propagate_err)\n{\n\tbool ret = false;\n\tssize_t err;\n\n\tcassert(config_prof);\n\n\terr = write(prof_dump_fd, prof_dump_buf, prof_dump_buf_end);\n\tif (err == -1) {\n\t\tif (!propagate_err) {\n\t\t\tmalloc_write(\"<jemalloc>: write() failed during heap \"\n\t\t\t    \"profile flush\\n\");\n\t\t\tif (opt_abort)\n\t\t\t\tabort();\n\t\t}\n\t\tret = true;\n\t}\n\tprof_dump_buf_end = 0;\n\n\treturn (ret);\n}\n\nstatic bool\nprof_dump_close(bool propagate_err)\n{\n\tbool ret;\n\n\tassert(prof_dump_fd != -1);\n\tret = prof_dump_flush(propagate_err);\n\tclose(prof_dump_fd);\n\tprof_dump_fd = -1;\n\n\treturn (ret);\n}\n\nstatic bool\nprof_dump_write(bool propagate_err, const char *s)\n{\n\tunsigned i, slen, n;\n\n\tcassert(config_prof);\n\n\ti = 0;\n\tslen = strlen(s);\n\twhile (i < slen) {\n\t\t/* Flush the buffer if it is full. */\n\t\tif (prof_dump_buf_end == PROF_DUMP_BUFSIZE)\n\t\t\tif (prof_dump_flush(propagate_err) && propagate_err)\n\t\t\t\treturn (true);\n\n\t\tif (prof_dump_buf_end + slen <= PROF_DUMP_BUFSIZE) {\n\t\t\t/* Finish writing. */\n\t\t\tn = slen - i;\n\t\t} else {\n\t\t\t/* Write as much of s as will fit. */\n\t\t\tn = PROF_DUMP_BUFSIZE - prof_dump_buf_end;\n\t\t}\n\t\tmemcpy(&prof_dump_buf[prof_dump_buf_end], &s[i], n);\n\t\tprof_dump_buf_end += n;\n\t\ti += n;\n\t}\n\n\treturn (false);\n}\n\nJEMALLOC_FORMAT_PRINTF(2, 3)\nstatic bool\nprof_dump_printf(bool propagate_err, const char *format, ...)\n{\n\tbool ret;\n\tva_list ap;\n\tchar buf[PROF_PRINTF_BUFSIZE];\n\n\tva_start(ap, format);\n\tmalloc_vsnprintf(buf, sizeof(buf), format, ap);\n\tva_end(ap);\n\tret = prof_dump_write(propagate_err, buf);\n\n\treturn (ret);\n}\n\n/* tctx->tdata->lock is held. */\nstatic void\nprof_tctx_merge_tdata(prof_tctx_t *tctx, prof_tdata_t *tdata)\n{\n\n\tmalloc_mutex_lock(tctx->gctx->lock);\n\n\tswitch (tctx->state) {\n\tcase prof_tctx_state_initializing:\n\t\tmalloc_mutex_unlock(tctx->gctx->lock);\n\t\treturn;\n\tcase prof_tctx_state_nominal:\n\t\ttctx->state = prof_tctx_state_dumping;\n\t\tmalloc_mutex_unlock(tctx->gctx->lock);\n\n\t\tmemcpy(&tctx->dump_cnts, &tctx->cnts, sizeof(prof_cnt_t));\n\n\t\ttdata->cnt_summed.curobjs += tctx->dump_cnts.curobjs;\n\t\ttdata->cnt_summed.curbytes += tctx->dump_cnts.curbytes;\n\t\tif (opt_prof_accum) {\n\t\t\ttdata->cnt_summed.accumobjs +=\n\t\t\t    tctx->dump_cnts.accumobjs;\n\t\t\ttdata->cnt_summed.accumbytes +=\n\t\t\t    tctx->dump_cnts.accumbytes;\n\t\t}\n\t\tbreak;\n\tcase prof_tctx_state_dumping:\n\tcase prof_tctx_state_purgatory:\n\t\tnot_reached();\n\t}\n}\n\n/* gctx->lock is held. */\nstatic void\nprof_tctx_merge_gctx(prof_tctx_t *tctx, prof_gctx_t *gctx)\n{\n\n\tgctx->cnt_summed.curobjs += tctx->dump_cnts.curobjs;\n\tgctx->cnt_summed.curbytes += tctx->dump_cnts.curbytes;\n\tif (opt_prof_accum) {\n\t\tgctx->cnt_summed.accumobjs += tctx->dump_cnts.accumobjs;\n\t\tgctx->cnt_summed.accumbytes += tctx->dump_cnts.accumbytes;\n\t}\n}\n\n/* tctx->gctx is held. */\nstatic prof_tctx_t *\nprof_tctx_merge_iter(prof_tctx_tree_t *tctxs, prof_tctx_t *tctx, void *arg)\n{\n\n\tswitch (tctx->state) {\n\tcase prof_tctx_state_nominal:\n\t\t/* New since dumping started; ignore. */\n\t\tbreak;\n\tcase prof_tctx_state_dumping:\n\tcase prof_tctx_state_purgatory:\n\t\tprof_tctx_merge_gctx(tctx, tctx->gctx);\n\t\tbreak;\n\tdefault:\n\t\tnot_reached();\n\t}\n\n\treturn (NULL);\n}\n\n/* gctx->lock is held. */\nstatic prof_tctx_t *\nprof_tctx_dump_iter(prof_tctx_tree_t *tctxs, prof_tctx_t *tctx, void *arg)\n{\n\tbool propagate_err = *(bool *)arg;\n\n\tswitch (tctx->state) {\n\tcase prof_tctx_state_initializing:\n\tcase prof_tctx_state_nominal:\n\t\t/* Not captured by this dump. */\n\t\tbreak;\n\tcase prof_tctx_state_dumping:\n\tcase prof_tctx_state_purgatory:\n\t\tif (prof_dump_printf(propagate_err,\n\t\t    \"  t%\"FMTu64\": %\"FMTu64\": %\"FMTu64\" [%\"FMTu64\": \"\n\t\t    \"%\"FMTu64\"]\\n\", tctx->thr_uid, tctx->dump_cnts.curobjs,\n\t\t    tctx->dump_cnts.curbytes, tctx->dump_cnts.accumobjs,\n\t\t    tctx->dump_cnts.accumbytes))\n\t\t\treturn (tctx);\n\t\tbreak;\n\tdefault:\n\t\tnot_reached();\n\t}\n\treturn (NULL);\n}\n\n/* tctx->gctx is held. */\nstatic prof_tctx_t *\nprof_tctx_finish_iter(prof_tctx_tree_t *tctxs, prof_tctx_t *tctx, void *arg)\n{\n\tprof_tctx_t *ret;\n\n\tswitch (tctx->state) {\n\tcase prof_tctx_state_nominal:\n\t\t/* New since dumping started; ignore. */\n\t\tbreak;\n\tcase prof_tctx_state_dumping:\n\t\ttctx->state = prof_tctx_state_nominal;\n\t\tbreak;\n\tcase prof_tctx_state_purgatory:\n\t\tret = tctx;\n\t\tgoto label_return;\n\tdefault:\n\t\tnot_reached();\n\t}\n\n\tret = NULL;\nlabel_return:\n\treturn (ret);\n}\n\nstatic void\nprof_dump_gctx_prep(prof_gctx_t *gctx, prof_gctx_tree_t *gctxs)\n{\n\n\tcassert(config_prof);\n\n\tmalloc_mutex_lock(gctx->lock);\n\n\t/*\n\t * Increment nlimbo so that gctx won't go away before dump.\n\t * Additionally, link gctx into the dump list so that it is included in\n\t * prof_dump()'s second pass.\n\t */\n\tgctx->nlimbo++;\n\tgctx_tree_insert(gctxs, gctx);\n\n\tmemset(&gctx->cnt_summed, 0, sizeof(prof_cnt_t));\n\n\tmalloc_mutex_unlock(gctx->lock);\n}\n\nstatic prof_gctx_t *\nprof_gctx_merge_iter(prof_gctx_tree_t *gctxs, prof_gctx_t *gctx, void *arg)\n{\n\tsize_t *leak_ngctx = (size_t *)arg;\n\n\tmalloc_mutex_lock(gctx->lock);\n\ttctx_tree_iter(&gctx->tctxs, NULL, prof_tctx_merge_iter, NULL);\n\tif (gctx->cnt_summed.curobjs != 0)\n\t\t(*leak_ngctx)++;\n\tmalloc_mutex_unlock(gctx->lock);\n\n\treturn (NULL);\n}\n\nstatic void\nprof_gctx_finish(tsd_t *tsd, prof_gctx_tree_t *gctxs)\n{\n\tprof_tdata_t *tdata = prof_tdata_get(tsd, false);\n\tprof_gctx_t *gctx;\n\n\t/*\n\t * Standard tree iteration won't work here, because as soon as we\n\t * decrement gctx->nlimbo and unlock gctx, another thread can\n\t * concurrently destroy it, which will corrupt the tree.  Therefore,\n\t * tear down the tree one node at a time during iteration.\n\t */\n\twhile ((gctx = gctx_tree_first(gctxs)) != NULL) {\n\t\tgctx_tree_remove(gctxs, gctx);\n\t\tmalloc_mutex_lock(gctx->lock);\n\t\t{\n\t\t\tprof_tctx_t *next;\n\n\t\t\tnext = NULL;\n\t\t\tdo {\n\t\t\t\tprof_tctx_t *to_destroy =\n\t\t\t\t    tctx_tree_iter(&gctx->tctxs, next,\n\t\t\t\t    prof_tctx_finish_iter, NULL);\n\t\t\t\tif (to_destroy != NULL) {\n\t\t\t\t\tnext = tctx_tree_next(&gctx->tctxs,\n\t\t\t\t\t    to_destroy);\n\t\t\t\t\ttctx_tree_remove(&gctx->tctxs,\n\t\t\t\t\t    to_destroy);\n\t\t\t\t\tidalloctm(tsd, to_destroy,\n\t\t\t\t\t    tcache_get(tsd, false), true);\n\t\t\t\t} else\n\t\t\t\t\tnext = NULL;\n\t\t\t} while (next != NULL);\n\t\t}\n\t\tgctx->nlimbo--;\n\t\tif (prof_gctx_should_destroy(gctx)) {\n\t\t\tgctx->nlimbo++;\n\t\t\tmalloc_mutex_unlock(gctx->lock);\n\t\t\tprof_gctx_try_destroy(tsd, tdata, gctx, tdata);\n\t\t} else\n\t\t\tmalloc_mutex_unlock(gctx->lock);\n\t}\n}\n\nstatic prof_tdata_t *\nprof_tdata_merge_iter(prof_tdata_tree_t *tdatas, prof_tdata_t *tdata, void *arg)\n{\n\tprof_cnt_t *cnt_all = (prof_cnt_t *)arg;\n\n\tmalloc_mutex_lock(tdata->lock);\n\tif (!tdata->expired) {\n\t\tsize_t tabind;\n\t\tunion {\n\t\t\tprof_tctx_t\t*p;\n\t\t\tvoid\t\t*v;\n\t\t} tctx;\n\n\t\ttdata->dumping = true;\n\t\tmemset(&tdata->cnt_summed, 0, sizeof(prof_cnt_t));\n\t\tfor (tabind = 0; !ckh_iter(&tdata->bt2tctx, &tabind, NULL,\n\t\t    &tctx.v);)\n\t\t\tprof_tctx_merge_tdata(tctx.p, tdata);\n\n\t\tcnt_all->curobjs += tdata->cnt_summed.curobjs;\n\t\tcnt_all->curbytes += tdata->cnt_summed.curbytes;\n\t\tif (opt_prof_accum) {\n\t\t\tcnt_all->accumobjs += tdata->cnt_summed.accumobjs;\n\t\t\tcnt_all->accumbytes += tdata->cnt_summed.accumbytes;\n\t\t}\n\t} else\n\t\ttdata->dumping = false;\n\tmalloc_mutex_unlock(tdata->lock);\n\n\treturn (NULL);\n}\n\nstatic prof_tdata_t *\nprof_tdata_dump_iter(prof_tdata_tree_t *tdatas, prof_tdata_t *tdata, void *arg)\n{\n\tbool propagate_err = *(bool *)arg;\n\n\tif (!tdata->dumping)\n\t\treturn (NULL);\n\n\tif (prof_dump_printf(propagate_err,\n\t    \"  t%\"FMTu64\": %\"FMTu64\": %\"FMTu64\" [%\"FMTu64\": %\"FMTu64\"]%s%s\\n\",\n\t    tdata->thr_uid, tdata->cnt_summed.curobjs,\n\t    tdata->cnt_summed.curbytes, tdata->cnt_summed.accumobjs,\n\t    tdata->cnt_summed.accumbytes,\n\t    (tdata->thread_name != NULL) ? \" \" : \"\",\n\t    (tdata->thread_name != NULL) ? tdata->thread_name : \"\"))\n\t\treturn (tdata);\n\treturn (NULL);\n}\n\n#ifdef JEMALLOC_JET\n#undef prof_dump_header\n#define\tprof_dump_header JEMALLOC_N(prof_dump_header_impl)\n#endif\nstatic bool\nprof_dump_header(bool propagate_err, const prof_cnt_t *cnt_all)\n{\n\tbool ret;\n\n\tif (prof_dump_printf(propagate_err,\n\t    \"heap_v2/%\"FMTu64\"\\n\"\n\t    \"  t*: %\"FMTu64\": %\"FMTu64\" [%\"FMTu64\": %\"FMTu64\"]\\n\",\n\t    ((uint64_t)1U << lg_prof_sample), cnt_all->curobjs,\n\t    cnt_all->curbytes, cnt_all->accumobjs, cnt_all->accumbytes))\n\t\treturn (true);\n\n\tmalloc_mutex_lock(&tdatas_mtx);\n\tret = (tdata_tree_iter(&tdatas, NULL, prof_tdata_dump_iter,\n\t    (void *)&propagate_err) != NULL);\n\tmalloc_mutex_unlock(&tdatas_mtx);\n\treturn (ret);\n}\n#ifdef JEMALLOC_JET\n#undef prof_dump_header\n#define\tprof_dump_header JEMALLOC_N(prof_dump_header)\nprof_dump_header_t *prof_dump_header = JEMALLOC_N(prof_dump_header_impl);\n#endif\n\n/* gctx->lock is held. */\nstatic bool\nprof_dump_gctx(bool propagate_err, prof_gctx_t *gctx, const prof_bt_t *bt,\n    prof_gctx_tree_t *gctxs)\n{\n\tbool ret;\n\tunsigned i;\n\n\tcassert(config_prof);\n\n\t/* Avoid dumping such gctx's that have no useful data. */\n\tif ((!opt_prof_accum && gctx->cnt_summed.curobjs == 0) ||\n\t    (opt_prof_accum && gctx->cnt_summed.accumobjs == 0)) {\n\t\tassert(gctx->cnt_summed.curobjs == 0);\n\t\tassert(gctx->cnt_summed.curbytes == 0);\n\t\tassert(gctx->cnt_summed.accumobjs == 0);\n\t\tassert(gctx->cnt_summed.accumbytes == 0);\n\t\tret = false;\n\t\tgoto label_return;\n\t}\n\n\tif (prof_dump_printf(propagate_err, \"@\")) {\n\t\tret = true;\n\t\tgoto label_return;\n\t}\n\tfor (i = 0; i < bt->len; i++) {\n\t\tif (prof_dump_printf(propagate_err, \" %#\"FMTxPTR,\n\t\t    (uintptr_t)bt->vec[i])) {\n\t\t\tret = true;\n\t\t\tgoto label_return;\n\t\t}\n\t}\n\n\tif (prof_dump_printf(propagate_err,\n\t    \"\\n\"\n\t    \"  t*: %\"FMTu64\": %\"FMTu64\" [%\"FMTu64\": %\"FMTu64\"]\\n\",\n\t    gctx->cnt_summed.curobjs, gctx->cnt_summed.curbytes,\n\t    gctx->cnt_summed.accumobjs, gctx->cnt_summed.accumbytes)) {\n\t\tret = true;\n\t\tgoto label_return;\n\t}\n\n\tif (tctx_tree_iter(&gctx->tctxs, NULL, prof_tctx_dump_iter,\n\t    (void *)&propagate_err) != NULL) {\n\t\tret = true;\n\t\tgoto label_return;\n\t}\n\n\tret = false;\nlabel_return:\n\treturn (ret);\n}\n\nJEMALLOC_FORMAT_PRINTF(1, 2)\nstatic int\nprof_open_maps(const char *format, ...)\n{\n\tint mfd;\n\tva_list ap;\n\tchar filename[PATH_MAX + 1];\n\n\tva_start(ap, format);\n\tmalloc_vsnprintf(filename, sizeof(filename), format, ap);\n\tva_end(ap);\n\tmfd = open(filename, O_RDONLY);\n\n\treturn (mfd);\n}\n\nstatic bool\nprof_dump_maps(bool propagate_err)\n{\n\tbool ret;\n\tint mfd;\n\n\tcassert(config_prof);\n#ifdef __FreeBSD__\n\tmfd = prof_open_maps(\"/proc/curproc/map\");\n#else\n\t{\n\t\tint pid = getpid();\n\n\t\tmfd = prof_open_maps(\"/proc/%d/task/%d/maps\", pid, pid);\n\t\tif (mfd == -1)\n\t\t\tmfd = prof_open_maps(\"/proc/%d/maps\", pid);\n\t}\n#endif\n\tif (mfd != -1) {\n\t\tssize_t nread;\n\n\t\tif (prof_dump_write(propagate_err, \"\\nMAPPED_LIBRARIES:\\n\") &&\n\t\t    propagate_err) {\n\t\t\tret = true;\n\t\t\tgoto label_return;\n\t\t}\n\t\tnread = 0;\n\t\tdo {\n\t\t\tprof_dump_buf_end += nread;\n\t\t\tif (prof_dump_buf_end == PROF_DUMP_BUFSIZE) {\n\t\t\t\t/* Make space in prof_dump_buf before read(). */\n\t\t\t\tif (prof_dump_flush(propagate_err) &&\n\t\t\t\t    propagate_err) {\n\t\t\t\t\tret = true;\n\t\t\t\t\tgoto label_return;\n\t\t\t\t}\n\t\t\t}\n\t\t\tnread = read(mfd, &prof_dump_buf[prof_dump_buf_end],\n\t\t\t    PROF_DUMP_BUFSIZE - prof_dump_buf_end);\n\t\t} while (nread > 0);\n\t} else {\n\t\tret = true;\n\t\tgoto label_return;\n\t}\n\n\tret = false;\nlabel_return:\n\tif (mfd != -1)\n\t\tclose(mfd);\n\treturn (ret);\n}\n\nstatic void\nprof_leakcheck(const prof_cnt_t *cnt_all, size_t leak_ngctx,\n    const char *filename)\n{\n\n\tif (cnt_all->curbytes != 0) {\n\t\tmalloc_printf(\"<jemalloc>: Leak summary: %\"FMTu64\" byte%s, %\"\n\t\t    FMTu64\" object%s, %zu context%s\\n\",\n\t\t    cnt_all->curbytes, (cnt_all->curbytes != 1) ? \"s\" : \"\",\n\t\t    cnt_all->curobjs, (cnt_all->curobjs != 1) ? \"s\" : \"\",\n\t\t    leak_ngctx, (leak_ngctx != 1) ? \"s\" : \"\");\n\t\tmalloc_printf(\n\t\t    \"<jemalloc>: Run jeprof on \\\"%s\\\" for leak detail\\n\",\n\t\t    filename);\n\t}\n}\n\nstatic prof_gctx_t *\nprof_gctx_dump_iter(prof_gctx_tree_t *gctxs, prof_gctx_t *gctx, void *arg)\n{\n\tprof_gctx_t *ret;\n\tbool propagate_err = *(bool *)arg;\n\n\tmalloc_mutex_lock(gctx->lock);\n\n\tif (prof_dump_gctx(propagate_err, gctx, &gctx->bt, gctxs)) {\n\t\tret = gctx;\n\t\tgoto label_return;\n\t}\n\n\tret = NULL;\nlabel_return:\n\tmalloc_mutex_unlock(gctx->lock);\n\treturn (ret);\n}\n\nstatic bool\nprof_dump(tsd_t *tsd, bool propagate_err, const char *filename, bool leakcheck)\n{\n\tprof_tdata_t *tdata;\n\tprof_cnt_t cnt_all;\n\tsize_t tabind;\n\tunion {\n\t\tprof_gctx_t\t*p;\n\t\tvoid\t\t*v;\n\t} gctx;\n\tsize_t leak_ngctx;\n\tprof_gctx_tree_t gctxs;\n\n\tcassert(config_prof);\n\n\ttdata = prof_tdata_get(tsd, true);\n\tif (tdata == NULL)\n\t\treturn (true);\n\n\tmalloc_mutex_lock(&prof_dump_mtx);\n\tprof_enter(tsd, tdata);\n\n\t/*\n\t * Put gctx's in limbo and clear their counters in preparation for\n\t * summing.\n\t */\n\tgctx_tree_new(&gctxs);\n\tfor (tabind = 0; !ckh_iter(&bt2gctx, &tabind, NULL, &gctx.v);)\n\t\tprof_dump_gctx_prep(gctx.p, &gctxs);\n\n\t/*\n\t * Iterate over tdatas, and for the non-expired ones snapshot their tctx\n\t * stats and merge them into the associated gctx's.\n\t */\n\tmemset(&cnt_all, 0, sizeof(prof_cnt_t));\n\tmalloc_mutex_lock(&tdatas_mtx);\n\ttdata_tree_iter(&tdatas, NULL, prof_tdata_merge_iter, (void *)&cnt_all);\n\tmalloc_mutex_unlock(&tdatas_mtx);\n\n\t/* Merge tctx stats into gctx's. */\n\tleak_ngctx = 0;\n\tgctx_tree_iter(&gctxs, NULL, prof_gctx_merge_iter, (void *)&leak_ngctx);\n\n\tprof_leave(tsd, tdata);\n\n\t/* Create dump file. */\n\tif ((prof_dump_fd = prof_dump_open(propagate_err, filename)) == -1)\n\t\tgoto label_open_close_error;\n\n\t/* Dump profile header. */\n\tif (prof_dump_header(propagate_err, &cnt_all))\n\t\tgoto label_write_error;\n\n\t/* Dump per gctx profile stats. */\n\tif (gctx_tree_iter(&gctxs, NULL, prof_gctx_dump_iter,\n\t    (void *)&propagate_err) != NULL)\n\t\tgoto label_write_error;\n\n\t/* Dump /proc/<pid>/maps if possible. */\n\tif (prof_dump_maps(propagate_err))\n\t\tgoto label_write_error;\n\n\tif (prof_dump_close(propagate_err))\n\t\tgoto label_open_close_error;\n\n\tprof_gctx_finish(tsd, &gctxs);\n\tmalloc_mutex_unlock(&prof_dump_mtx);\n\n\tif (leakcheck)\n\t\tprof_leakcheck(&cnt_all, leak_ngctx, filename);\n\n\treturn (false);\nlabel_write_error:\n\tprof_dump_close(propagate_err);\nlabel_open_close_error:\n\tprof_gctx_finish(tsd, &gctxs);\n\tmalloc_mutex_unlock(&prof_dump_mtx);\n\treturn (true);\n}\n\n#define\tDUMP_FILENAME_BUFSIZE\t(PATH_MAX + 1)\n#define\tVSEQ_INVALID\t\tUINT64_C(0xffffffffffffffff)\nstatic void\nprof_dump_filename(char *filename, char v, uint64_t vseq)\n{\n\n\tcassert(config_prof);\n\n\tif (vseq != VSEQ_INVALID) {\n\t        /* \"<prefix>.<pid>.<seq>.v<vseq>.heap\" */\n\t\tmalloc_snprintf(filename, DUMP_FILENAME_BUFSIZE,\n\t\t    \"%s.%d.%\"FMTu64\".%c%\"FMTu64\".heap\",\n\t\t    opt_prof_prefix, (int)getpid(), prof_dump_seq, v, vseq);\n\t} else {\n\t        /* \"<prefix>.<pid>.<seq>.<v>.heap\" */\n\t\tmalloc_snprintf(filename, DUMP_FILENAME_BUFSIZE,\n\t\t    \"%s.%d.%\"FMTu64\".%c.heap\",\n\t\t    opt_prof_prefix, (int)getpid(), prof_dump_seq, v);\n\t}\n\tprof_dump_seq++;\n}\n\nstatic void\nprof_fdump(void)\n{\n\ttsd_t *tsd;\n\tchar filename[DUMP_FILENAME_BUFSIZE];\n\n\tcassert(config_prof);\n\tassert(opt_prof_final);\n\tassert(opt_prof_prefix[0] != '\\0');\n\n\tif (!prof_booted)\n\t\treturn;\n\ttsd = tsd_fetch();\n\n\tmalloc_mutex_lock(&prof_dump_seq_mtx);\n\tprof_dump_filename(filename, 'f', VSEQ_INVALID);\n\tmalloc_mutex_unlock(&prof_dump_seq_mtx);\n\tprof_dump(tsd, false, filename, opt_prof_leak);\n}\n\nvoid\nprof_idump(void)\n{\n\ttsd_t *tsd;\n\tprof_tdata_t *tdata;\n\n\tcassert(config_prof);\n\n\tif (!prof_booted)\n\t\treturn;\n\ttsd = tsd_fetch();\n\ttdata = prof_tdata_get(tsd, false);\n\tif (tdata == NULL)\n\t\treturn;\n\tif (tdata->enq) {\n\t\ttdata->enq_idump = true;\n\t\treturn;\n\t}\n\n\tif (opt_prof_prefix[0] != '\\0') {\n\t\tchar filename[PATH_MAX + 1];\n\t\tmalloc_mutex_lock(&prof_dump_seq_mtx);\n\t\tprof_dump_filename(filename, 'i', prof_dump_iseq);\n\t\tprof_dump_iseq++;\n\t\tmalloc_mutex_unlock(&prof_dump_seq_mtx);\n\t\tprof_dump(tsd, false, filename, false);\n\t}\n}\n\nbool\nprof_mdump(const char *filename)\n{\n\ttsd_t *tsd;\n\tchar filename_buf[DUMP_FILENAME_BUFSIZE];\n\n\tcassert(config_prof);\n\n\tif (!opt_prof || !prof_booted)\n\t\treturn (true);\n\ttsd = tsd_fetch();\n\n\tif (filename == NULL) {\n\t\t/* No filename specified, so automatically generate one. */\n\t\tif (opt_prof_prefix[0] == '\\0')\n\t\t\treturn (true);\n\t\tmalloc_mutex_lock(&prof_dump_seq_mtx);\n\t\tprof_dump_filename(filename_buf, 'm', prof_dump_mseq);\n\t\tprof_dump_mseq++;\n\t\tmalloc_mutex_unlock(&prof_dump_seq_mtx);\n\t\tfilename = filename_buf;\n\t}\n\treturn (prof_dump(tsd, true, filename, false));\n}\n\nvoid\nprof_gdump(void)\n{\n\ttsd_t *tsd;\n\tprof_tdata_t *tdata;\n\n\tcassert(config_prof);\n\n\tif (!prof_booted)\n\t\treturn;\n\ttsd = tsd_fetch();\n\ttdata = prof_tdata_get(tsd, false);\n\tif (tdata == NULL)\n\t\treturn;\n\tif (tdata->enq) {\n\t\ttdata->enq_gdump = true;\n\t\treturn;\n\t}\n\n\tif (opt_prof_prefix[0] != '\\0') {\n\t\tchar filename[DUMP_FILENAME_BUFSIZE];\n\t\tmalloc_mutex_lock(&prof_dump_seq_mtx);\n\t\tprof_dump_filename(filename, 'u', prof_dump_useq);\n\t\tprof_dump_useq++;\n\t\tmalloc_mutex_unlock(&prof_dump_seq_mtx);\n\t\tprof_dump(tsd, false, filename, false);\n\t}\n}\n\nstatic void\nprof_bt_hash(const void *key, size_t r_hash[2])\n{\n\tprof_bt_t *bt = (prof_bt_t *)key;\n\n\tcassert(config_prof);\n\n\thash(bt->vec, bt->len * sizeof(void *), 0x94122f33U, r_hash);\n}\n\nstatic bool\nprof_bt_keycomp(const void *k1, const void *k2)\n{\n\tconst prof_bt_t *bt1 = (prof_bt_t *)k1;\n\tconst prof_bt_t *bt2 = (prof_bt_t *)k2;\n\n\tcassert(config_prof);\n\n\tif (bt1->len != bt2->len)\n\t\treturn (false);\n\treturn (memcmp(bt1->vec, bt2->vec, bt1->len * sizeof(void *)) == 0);\n}\n\nJEMALLOC_INLINE_C uint64_t\nprof_thr_uid_alloc(void)\n{\n\tuint64_t thr_uid;\n\n\tmalloc_mutex_lock(&next_thr_uid_mtx);\n\tthr_uid = next_thr_uid;\n\tnext_thr_uid++;\n\tmalloc_mutex_unlock(&next_thr_uid_mtx);\n\n\treturn (thr_uid);\n}\n\nstatic prof_tdata_t *\nprof_tdata_init_impl(tsd_t *tsd, uint64_t thr_uid, uint64_t thr_discrim,\n    char *thread_name, bool active)\n{\n\tprof_tdata_t *tdata;\n\ttcache_t *tcache;\n\n\tcassert(config_prof);\n\n\t/* Initialize an empty cache for this thread. */\n\ttcache = tcache_get(tsd, true);\n\ttdata = (prof_tdata_t *)iallocztm(tsd, sizeof(prof_tdata_t), false,\n\t    tcache, true, NULL);\n\tif (tdata == NULL)\n\t\treturn (NULL);\n\n\ttdata->lock = prof_tdata_mutex_choose(thr_uid);\n\ttdata->thr_uid = thr_uid;\n\ttdata->thr_discrim = thr_discrim;\n\ttdata->thread_name = thread_name;\n\ttdata->attached = true;\n\ttdata->expired = false;\n\ttdata->tctx_uid_next = 0;\n\n\tif (ckh_new(tsd, &tdata->bt2tctx, PROF_CKH_MINITEMS,\n\t    prof_bt_hash, prof_bt_keycomp)) {\n\t\tidalloctm(tsd, tdata, tcache, true);\n\t\treturn (NULL);\n\t}\n\n\ttdata->prng_state = (uint64_t)(uintptr_t)tdata;\n\tprof_sample_threshold_update(tdata);\n\n\ttdata->enq = false;\n\ttdata->enq_idump = false;\n\ttdata->enq_gdump = false;\n\n\ttdata->dumping = false;\n\ttdata->active = active;\n\n\tmalloc_mutex_lock(&tdatas_mtx);\n\ttdata_tree_insert(&tdatas, tdata);\n\tmalloc_mutex_unlock(&tdatas_mtx);\n\n\treturn (tdata);\n}\n\nprof_tdata_t *\nprof_tdata_init(tsd_t *tsd)\n{\n\n\treturn (prof_tdata_init_impl(tsd, prof_thr_uid_alloc(), 0, NULL,\n\t    prof_thread_active_init_get()));\n}\n\n/* tdata->lock must be held. */\nstatic bool\nprof_tdata_should_destroy(prof_tdata_t *tdata, bool even_if_attached)\n{\n\n\tif (tdata->attached && !even_if_attached)\n\t\treturn (false);\n\tif (ckh_count(&tdata->bt2tctx) != 0)\n\t\treturn (false);\n\treturn (true);\n}\n\n/* tdatas_mtx must be held. */\nstatic void\nprof_tdata_destroy_locked(tsd_t *tsd, prof_tdata_t *tdata,\n    bool even_if_attached)\n{\n\ttcache_t *tcache;\n\n\tassert(prof_tdata_should_destroy(tdata, even_if_attached));\n\tassert(tsd_prof_tdata_get(tsd) != tdata);\n\n\ttdata_tree_remove(&tdatas, tdata);\n\n\ttcache = tcache_get(tsd, false);\n\tif (tdata->thread_name != NULL)\n\t\tidalloctm(tsd, tdata->thread_name, tcache, true);\n\tckh_delete(tsd, &tdata->bt2tctx);\n\tidalloctm(tsd, tdata, tcache, true);\n}\n\nstatic void\nprof_tdata_destroy(tsd_t *tsd, prof_tdata_t *tdata, bool even_if_attached)\n{\n\n\tmalloc_mutex_lock(&tdatas_mtx);\n\tprof_tdata_destroy_locked(tsd, tdata, even_if_attached);\n\tmalloc_mutex_unlock(&tdatas_mtx);\n}\n\nstatic void\nprof_tdata_detach(tsd_t *tsd, prof_tdata_t *tdata)\n{\n\tbool destroy_tdata;\n\n\tmalloc_mutex_lock(tdata->lock);\n\tif (tdata->attached) {\n\t\tdestroy_tdata = prof_tdata_should_destroy(tdata, true);\n\t\t/*\n\t\t * Only detach if !destroy_tdata, because detaching would allow\n\t\t * another thread to win the race to destroy tdata.\n\t\t */\n\t\tif (!destroy_tdata)\n\t\t\ttdata->attached = false;\n\t\ttsd_prof_tdata_set(tsd, NULL);\n\t} else\n\t\tdestroy_tdata = false;\n\tmalloc_mutex_unlock(tdata->lock);\n\tif (destroy_tdata)\n\t\tprof_tdata_destroy(tsd, tdata, true);\n}\n\nprof_tdata_t *\nprof_tdata_reinit(tsd_t *tsd, prof_tdata_t *tdata)\n{\n\tuint64_t thr_uid = tdata->thr_uid;\n\tuint64_t thr_discrim = tdata->thr_discrim + 1;\n\tchar *thread_name = (tdata->thread_name != NULL) ?\n\t    prof_thread_name_alloc(tsd, tdata->thread_name) : NULL;\n\tbool active = tdata->active;\n\n\tprof_tdata_detach(tsd, tdata);\n\treturn (prof_tdata_init_impl(tsd, thr_uid, thr_discrim, thread_name,\n\t    active));\n}\n\nstatic bool\nprof_tdata_expire(prof_tdata_t *tdata)\n{\n\tbool destroy_tdata;\n\n\tmalloc_mutex_lock(tdata->lock);\n\tif (!tdata->expired) {\n\t\ttdata->expired = true;\n\t\tdestroy_tdata = tdata->attached ? false :\n\t\t    prof_tdata_should_destroy(tdata, false);\n\t} else\n\t\tdestroy_tdata = false;\n\tmalloc_mutex_unlock(tdata->lock);\n\n\treturn (destroy_tdata);\n}\n\nstatic prof_tdata_t *\nprof_tdata_reset_iter(prof_tdata_tree_t *tdatas, prof_tdata_t *tdata, void *arg)\n{\n\n\treturn (prof_tdata_expire(tdata) ? tdata : NULL);\n}\n\nvoid\nprof_reset(tsd_t *tsd, size_t lg_sample)\n{\n\tprof_tdata_t *next;\n\n\tassert(lg_sample < (sizeof(uint64_t) << 3));\n\n\tmalloc_mutex_lock(&prof_dump_mtx);\n\tmalloc_mutex_lock(&tdatas_mtx);\n\n\tlg_prof_sample = lg_sample;\n\n\tnext = NULL;\n\tdo {\n\t\tprof_tdata_t *to_destroy = tdata_tree_iter(&tdatas, next,\n\t\t    prof_tdata_reset_iter, NULL);\n\t\tif (to_destroy != NULL) {\n\t\t\tnext = tdata_tree_next(&tdatas, to_destroy);\n\t\t\tprof_tdata_destroy_locked(tsd, to_destroy, false);\n\t\t} else\n\t\t\tnext = NULL;\n\t} while (next != NULL);\n\n\tmalloc_mutex_unlock(&tdatas_mtx);\n\tmalloc_mutex_unlock(&prof_dump_mtx);\n}\n\nvoid\nprof_tdata_cleanup(tsd_t *tsd)\n{\n\tprof_tdata_t *tdata;\n\n\tif (!config_prof)\n\t\treturn;\n\n\ttdata = tsd_prof_tdata_get(tsd);\n\tif (tdata != NULL)\n\t\tprof_tdata_detach(tsd, tdata);\n}\n\nbool\nprof_active_get(void)\n{\n\tbool prof_active_current;\n\n\tmalloc_mutex_lock(&prof_active_mtx);\n\tprof_active_current = prof_active;\n\tmalloc_mutex_unlock(&prof_active_mtx);\n\treturn (prof_active_current);\n}\n\nbool\nprof_active_set(bool active)\n{\n\tbool prof_active_old;\n\n\tmalloc_mutex_lock(&prof_active_mtx);\n\tprof_active_old = prof_active;\n\tprof_active = active;\n\tmalloc_mutex_unlock(&prof_active_mtx);\n\treturn (prof_active_old);\n}\n\nconst char *\nprof_thread_name_get(void)\n{\n\ttsd_t *tsd;\n\tprof_tdata_t *tdata;\n\n\ttsd = tsd_fetch();\n\ttdata = prof_tdata_get(tsd, true);\n\tif (tdata == NULL)\n\t\treturn (\"\");\n\treturn (tdata->thread_name != NULL ? tdata->thread_name : \"\");\n}\n\nstatic char *\nprof_thread_name_alloc(tsd_t *tsd, const char *thread_name)\n{\n\tchar *ret;\n\tsize_t size;\n\n\tif (thread_name == NULL)\n\t\treturn (NULL);\n\n\tsize = strlen(thread_name) + 1;\n\tif (size == 1)\n\t\treturn (\"\");\n\n\tret = iallocztm(tsd, size, false, tcache_get(tsd, true), true, NULL);\n\tif (ret == NULL)\n\t\treturn (NULL);\n\tmemcpy(ret, thread_name, size);\n\treturn (ret);\n}\n\nint\nprof_thread_name_set(tsd_t *tsd, const char *thread_name)\n{\n\tprof_tdata_t *tdata;\n\tunsigned i;\n\tchar *s;\n\n\ttdata = prof_tdata_get(tsd, true);\n\tif (tdata == NULL)\n\t\treturn (EAGAIN);\n\n\t/* Validate input. */\n\tif (thread_name == NULL)\n\t\treturn (EFAULT);\n\tfor (i = 0; thread_name[i] != '\\0'; i++) {\n\t\tchar c = thread_name[i];\n\t\tif (!isgraph(c) && !isblank(c))\n\t\t\treturn (EFAULT);\n\t}\n\n\ts = prof_thread_name_alloc(tsd, thread_name);\n\tif (s == NULL)\n\t\treturn (EAGAIN);\n\n\tif (tdata->thread_name != NULL) {\n\t\tidalloctm(tsd, tdata->thread_name, tcache_get(tsd, false),\n\t\t    true);\n\t\ttdata->thread_name = NULL;\n\t}\n\tif (strlen(s) > 0)\n\t\ttdata->thread_name = s;\n\treturn (0);\n}\n\nbool\nprof_thread_active_get(void)\n{\n\ttsd_t *tsd;\n\tprof_tdata_t *tdata;\n\n\ttsd = tsd_fetch();\n\ttdata = prof_tdata_get(tsd, true);\n\tif (tdata == NULL)\n\t\treturn (false);\n\treturn (tdata->active);\n}\n\nbool\nprof_thread_active_set(bool active)\n{\n\ttsd_t *tsd;\n\tprof_tdata_t *tdata;\n\n\ttsd = tsd_fetch();\n\ttdata = prof_tdata_get(tsd, true);\n\tif (tdata == NULL)\n\t\treturn (true);\n\ttdata->active = active;\n\treturn (false);\n}\n\nbool\nprof_thread_active_init_get(void)\n{\n\tbool active_init;\n\n\tmalloc_mutex_lock(&prof_thread_active_init_mtx);\n\tactive_init = prof_thread_active_init;\n\tmalloc_mutex_unlock(&prof_thread_active_init_mtx);\n\treturn (active_init);\n}\n\nbool\nprof_thread_active_init_set(bool active_init)\n{\n\tbool active_init_old;\n\n\tmalloc_mutex_lock(&prof_thread_active_init_mtx);\n\tactive_init_old = prof_thread_active_init;\n\tprof_thread_active_init = active_init;\n\tmalloc_mutex_unlock(&prof_thread_active_init_mtx);\n\treturn (active_init_old);\n}\n\nbool\nprof_gdump_get(void)\n{\n\tbool prof_gdump_current;\n\n\tmalloc_mutex_lock(&prof_gdump_mtx);\n\tprof_gdump_current = prof_gdump_val;\n\tmalloc_mutex_unlock(&prof_gdump_mtx);\n\treturn (prof_gdump_current);\n}\n\nbool\nprof_gdump_set(bool gdump)\n{\n\tbool prof_gdump_old;\n\n\tmalloc_mutex_lock(&prof_gdump_mtx);\n\tprof_gdump_old = prof_gdump_val;\n\tprof_gdump_val = gdump;\n\tmalloc_mutex_unlock(&prof_gdump_mtx);\n\treturn (prof_gdump_old);\n}\n\nvoid\nprof_boot0(void)\n{\n\n\tcassert(config_prof);\n\n\tmemcpy(opt_prof_prefix, PROF_PREFIX_DEFAULT,\n\t    sizeof(PROF_PREFIX_DEFAULT));\n}\n\nvoid\nprof_boot1(void)\n{\n\n\tcassert(config_prof);\n\n\t/*\n\t * opt_prof must be in its final state before any arenas are\n\t * initialized, so this function must be executed early.\n\t */\n\n\tif (opt_prof_leak && !opt_prof) {\n\t\t/*\n\t\t * Enable opt_prof, but in such a way that profiles are never\n\t\t * automatically dumped.\n\t\t */\n\t\topt_prof = true;\n\t\topt_prof_gdump = false;\n\t} else if (opt_prof) {\n\t\tif (opt_lg_prof_interval >= 0) {\n\t\t\tprof_interval = (((uint64_t)1U) <<\n\t\t\t    opt_lg_prof_interval);\n\t\t}\n\t}\n}\n\nbool\nprof_boot2(void)\n{\n\n\tcassert(config_prof);\n\n\tif (opt_prof) {\n\t\ttsd_t *tsd;\n\t\tunsigned i;\n\n\t\tlg_prof_sample = opt_lg_prof_sample;\n\n\t\tprof_active = opt_prof_active;\n\t\tif (malloc_mutex_init(&prof_active_mtx))\n\t\t\treturn (true);\n\n\t\tprof_gdump_val = opt_prof_gdump;\n\t\tif (malloc_mutex_init(&prof_gdump_mtx))\n\t\t\treturn (true);\n\n\t\tprof_thread_active_init = opt_prof_thread_active_init;\n\t\tif (malloc_mutex_init(&prof_thread_active_init_mtx))\n\t\t\treturn (true);\n\n\t\ttsd = tsd_fetch();\n\t\tif (ckh_new(tsd, &bt2gctx, PROF_CKH_MINITEMS, prof_bt_hash,\n\t\t    prof_bt_keycomp))\n\t\t\treturn (true);\n\t\tif (malloc_mutex_init(&bt2gctx_mtx))\n\t\t\treturn (true);\n\n\t\ttdata_tree_new(&tdatas);\n\t\tif (malloc_mutex_init(&tdatas_mtx))\n\t\t\treturn (true);\n\n\t\tnext_thr_uid = 0;\n\t\tif (malloc_mutex_init(&next_thr_uid_mtx))\n\t\t\treturn (true);\n\n\t\tif (malloc_mutex_init(&prof_dump_seq_mtx))\n\t\t\treturn (true);\n\t\tif (malloc_mutex_init(&prof_dump_mtx))\n\t\t\treturn (true);\n\n\t\tif (opt_prof_final && opt_prof_prefix[0] != '\\0' &&\n\t\t    atexit(prof_fdump) != 0) {\n\t\t\tmalloc_write(\"<jemalloc>: Error in atexit()\\n\");\n\t\t\tif (opt_abort)\n\t\t\t\tabort();\n\t\t}\n\n\t\tgctx_locks = (malloc_mutex_t *)base_alloc(PROF_NCTX_LOCKS *\n\t\t    sizeof(malloc_mutex_t));\n\t\tif (gctx_locks == NULL)\n\t\t\treturn (true);\n\t\tfor (i = 0; i < PROF_NCTX_LOCKS; i++) {\n\t\t\tif (malloc_mutex_init(&gctx_locks[i]))\n\t\t\t\treturn (true);\n\t\t}\n\n\t\ttdata_locks = (malloc_mutex_t *)base_alloc(PROF_NTDATA_LOCKS *\n\t\t    sizeof(malloc_mutex_t));\n\t\tif (tdata_locks == NULL)\n\t\t\treturn (true);\n\t\tfor (i = 0; i < PROF_NTDATA_LOCKS; i++) {\n\t\t\tif (malloc_mutex_init(&tdata_locks[i]))\n\t\t\t\treturn (true);\n\t\t}\n\t}\n\n#ifdef JEMALLOC_PROF_LIBGCC\n\t/*\n\t * Cause the backtracing machinery to allocate its internal state\n\t * before enabling profiling.\n\t */\n\t_Unwind_Backtrace(prof_unwind_init_callback, NULL);\n#endif\n\n\tprof_booted = true;\n\n\treturn (false);\n}\n\nvoid\nprof_prefork(void)\n{\n\n\tif (opt_prof) {\n\t\tunsigned i;\n\n\t\tmalloc_mutex_prefork(&tdatas_mtx);\n\t\tmalloc_mutex_prefork(&bt2gctx_mtx);\n\t\tmalloc_mutex_prefork(&next_thr_uid_mtx);\n\t\tmalloc_mutex_prefork(&prof_dump_seq_mtx);\n\t\tfor (i = 0; i < PROF_NCTX_LOCKS; i++)\n\t\t\tmalloc_mutex_prefork(&gctx_locks[i]);\n\t\tfor (i = 0; i < PROF_NTDATA_LOCKS; i++)\n\t\t\tmalloc_mutex_prefork(&tdata_locks[i]);\n\t}\n}\n\nvoid\nprof_postfork_parent(void)\n{\n\n\tif (opt_prof) {\n\t\tunsigned i;\n\n\t\tfor (i = 0; i < PROF_NTDATA_LOCKS; i++)\n\t\t\tmalloc_mutex_postfork_parent(&tdata_locks[i]);\n\t\tfor (i = 0; i < PROF_NCTX_LOCKS; i++)\n\t\t\tmalloc_mutex_postfork_parent(&gctx_locks[i]);\n\t\tmalloc_mutex_postfork_parent(&prof_dump_seq_mtx);\n\t\tmalloc_mutex_postfork_parent(&next_thr_uid_mtx);\n\t\tmalloc_mutex_postfork_parent(&bt2gctx_mtx);\n\t\tmalloc_mutex_postfork_parent(&tdatas_mtx);\n\t}\n}\n\nvoid\nprof_postfork_child(void)\n{\n\n\tif (opt_prof) {\n\t\tunsigned i;\n\n\t\tfor (i = 0; i < PROF_NTDATA_LOCKS; i++)\n\t\t\tmalloc_mutex_postfork_child(&tdata_locks[i]);\n\t\tfor (i = 0; i < PROF_NCTX_LOCKS; i++)\n\t\t\tmalloc_mutex_postfork_child(&gctx_locks[i]);\n\t\tmalloc_mutex_postfork_child(&prof_dump_seq_mtx);\n\t\tmalloc_mutex_postfork_child(&next_thr_uid_mtx);\n\t\tmalloc_mutex_postfork_child(&bt2gctx_mtx);\n\t\tmalloc_mutex_postfork_child(&tdatas_mtx);\n\t}\n}\n\n/******************************************************************************/\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.8/deps/jemalloc/src/quarantine.c",
    "content": "#define\tJEMALLOC_QUARANTINE_C_\n#include \"jemalloc/internal/jemalloc_internal.h\"\n\n/*\n * Quarantine pointers close to NULL are used to encode state information that\n * is used for cleaning up during thread shutdown.\n */\n#define\tQUARANTINE_STATE_REINCARNATED\t((quarantine_t *)(uintptr_t)1)\n#define\tQUARANTINE_STATE_PURGATORY\t((quarantine_t *)(uintptr_t)2)\n#define\tQUARANTINE_STATE_MAX\t\tQUARANTINE_STATE_PURGATORY\n\n/******************************************************************************/\n/* Function prototypes for non-inline static functions. */\n\nstatic quarantine_t\t*quarantine_grow(tsd_t *tsd, quarantine_t *quarantine);\nstatic void\tquarantine_drain_one(tsd_t *tsd, quarantine_t *quarantine);\nstatic void\tquarantine_drain(tsd_t *tsd, quarantine_t *quarantine,\n    size_t upper_bound);\n\n/******************************************************************************/\n\nstatic quarantine_t *\nquarantine_init(tsd_t *tsd, size_t lg_maxobjs)\n{\n\tquarantine_t *quarantine;\n\n\tassert(tsd_nominal(tsd));\n\n\tquarantine = (quarantine_t *)iallocztm(tsd, offsetof(quarantine_t, objs)\n\t    + ((ZU(1) << lg_maxobjs) * sizeof(quarantine_obj_t)), false,\n\t    tcache_get(tsd, true), true, NULL);\n\tif (quarantine == NULL)\n\t\treturn (NULL);\n\tquarantine->curbytes = 0;\n\tquarantine->curobjs = 0;\n\tquarantine->first = 0;\n\tquarantine->lg_maxobjs = lg_maxobjs;\n\n\treturn (quarantine);\n}\n\nvoid\nquarantine_alloc_hook_work(tsd_t *tsd)\n{\n\tquarantine_t *quarantine;\n\n\tif (!tsd_nominal(tsd))\n\t\treturn;\n\n\tquarantine = quarantine_init(tsd, LG_MAXOBJS_INIT);\n\t/*\n\t * Check again whether quarantine has been initialized, because\n\t * quarantine_init() may have triggered recursive initialization.\n\t */\n\tif (tsd_quarantine_get(tsd) == NULL)\n\t\ttsd_quarantine_set(tsd, quarantine);\n\telse\n\t\tidalloctm(tsd, quarantine, tcache_get(tsd, false), true);\n}\n\nstatic quarantine_t *\nquarantine_grow(tsd_t *tsd, quarantine_t *quarantine)\n{\n\tquarantine_t *ret;\n\n\tret = quarantine_init(tsd, quarantine->lg_maxobjs + 1);\n\tif (ret == NULL) {\n\t\tquarantine_drain_one(tsd, quarantine);\n\t\treturn (quarantine);\n\t}\n\n\tret->curbytes = quarantine->curbytes;\n\tret->curobjs = quarantine->curobjs;\n\tif (quarantine->first + quarantine->curobjs <= (ZU(1) <<\n\t    quarantine->lg_maxobjs)) {\n\t\t/* objs ring buffer data are contiguous. */\n\t\tmemcpy(ret->objs, &quarantine->objs[quarantine->first],\n\t\t    quarantine->curobjs * sizeof(quarantine_obj_t));\n\t} else {\n\t\t/* objs ring buffer data wrap around. */\n\t\tsize_t ncopy_a = (ZU(1) << quarantine->lg_maxobjs) -\n\t\t    quarantine->first;\n\t\tsize_t ncopy_b = quarantine->curobjs - ncopy_a;\n\n\t\tmemcpy(ret->objs, &quarantine->objs[quarantine->first], ncopy_a\n\t\t    * sizeof(quarantine_obj_t));\n\t\tmemcpy(&ret->objs[ncopy_a], quarantine->objs, ncopy_b *\n\t\t    sizeof(quarantine_obj_t));\n\t}\n\tidalloctm(tsd, quarantine, tcache_get(tsd, false), true);\n\n\ttsd_quarantine_set(tsd, ret);\n\treturn (ret);\n}\n\nstatic void\nquarantine_drain_one(tsd_t *tsd, quarantine_t *quarantine)\n{\n\tquarantine_obj_t *obj = &quarantine->objs[quarantine->first];\n\tassert(obj->usize == isalloc(obj->ptr, config_prof));\n\tidalloctm(tsd, obj->ptr, NULL, false);\n\tquarantine->curbytes -= obj->usize;\n\tquarantine->curobjs--;\n\tquarantine->first = (quarantine->first + 1) & ((ZU(1) <<\n\t    quarantine->lg_maxobjs) - 1);\n}\n\nstatic void\nquarantine_drain(tsd_t *tsd, quarantine_t *quarantine, size_t upper_bound)\n{\n\n\twhile (quarantine->curbytes > upper_bound && quarantine->curobjs > 0)\n\t\tquarantine_drain_one(tsd, quarantine);\n}\n\nvoid\nquarantine(tsd_t *tsd, void *ptr)\n{\n\tquarantine_t *quarantine;\n\tsize_t usize = isalloc(ptr, config_prof);\n\n\tcassert(config_fill);\n\tassert(opt_quarantine);\n\n\tif ((quarantine = tsd_quarantine_get(tsd)) == NULL) {\n\t\tidalloctm(tsd, ptr, NULL, false);\n\t\treturn;\n\t}\n\t/*\n\t * Drain one or more objects if the quarantine size limit would be\n\t * exceeded by appending ptr.\n\t */\n\tif (quarantine->curbytes + usize > opt_quarantine) {\n\t\tsize_t upper_bound = (opt_quarantine >= usize) ? opt_quarantine\n\t\t    - usize : 0;\n\t\tquarantine_drain(tsd, quarantine, upper_bound);\n\t}\n\t/* Grow the quarantine ring buffer if it's full. */\n\tif (quarantine->curobjs == (ZU(1) << quarantine->lg_maxobjs))\n\t\tquarantine = quarantine_grow(tsd, quarantine);\n\t/* quarantine_grow() must free a slot if it fails to grow. */\n\tassert(quarantine->curobjs < (ZU(1) << quarantine->lg_maxobjs));\n\t/* Append ptr if its size doesn't exceed the quarantine size. */\n\tif (quarantine->curbytes + usize <= opt_quarantine) {\n\t\tsize_t offset = (quarantine->first + quarantine->curobjs) &\n\t\t    ((ZU(1) << quarantine->lg_maxobjs) - 1);\n\t\tquarantine_obj_t *obj = &quarantine->objs[offset];\n\t\tobj->ptr = ptr;\n\t\tobj->usize = usize;\n\t\tquarantine->curbytes += usize;\n\t\tquarantine->curobjs++;\n\t\tif (config_fill && unlikely(opt_junk_free)) {\n\t\t\t/*\n\t\t\t * Only do redzone validation if Valgrind isn't in\n\t\t\t * operation.\n\t\t\t */\n\t\t\tif ((!config_valgrind || likely(!in_valgrind))\n\t\t\t    && usize <= SMALL_MAXCLASS)\n\t\t\t\tarena_quarantine_junk_small(ptr, usize);\n\t\t\telse\n\t\t\t\tmemset(ptr, 0x5a, usize);\n\t\t}\n\t} else {\n\t\tassert(quarantine->curbytes == 0);\n\t\tidalloctm(tsd, ptr, NULL, false);\n\t}\n}\n\nvoid\nquarantine_cleanup(tsd_t *tsd)\n{\n\tquarantine_t *quarantine;\n\n\tif (!config_fill)\n\t\treturn;\n\n\tquarantine = tsd_quarantine_get(tsd);\n\tif (quarantine != NULL) {\n\t\tquarantine_drain(tsd, quarantine, 0);\n\t\tidalloctm(tsd, quarantine, tcache_get(tsd, false), true);\n\t\ttsd_quarantine_set(tsd, NULL);\n\t}\n}\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.8/deps/jemalloc/src/rtree.c",
    "content": "#define\tJEMALLOC_RTREE_C_\n#include \"jemalloc/internal/jemalloc_internal.h\"\n\nstatic unsigned\nhmin(unsigned ha, unsigned hb)\n{\n\n\treturn (ha < hb ? ha : hb);\n}\n\n/* Only the most significant bits of keys passed to rtree_[gs]et() are used. */\nbool\nrtree_new(rtree_t *rtree, unsigned bits, rtree_node_alloc_t *alloc,\n    rtree_node_dalloc_t *dalloc)\n{\n\tunsigned bits_in_leaf, height, i;\n\n\tassert(bits > 0 && bits <= (sizeof(uintptr_t) << 3));\n\n\tbits_in_leaf = (bits % RTREE_BITS_PER_LEVEL) == 0 ? RTREE_BITS_PER_LEVEL\n\t    : (bits % RTREE_BITS_PER_LEVEL);\n\tif (bits > bits_in_leaf) {\n\t\theight = 1 + (bits - bits_in_leaf) / RTREE_BITS_PER_LEVEL;\n\t\tif ((height-1) * RTREE_BITS_PER_LEVEL + bits_in_leaf != bits)\n\t\t\theight++;\n\t} else\n\t\theight = 1;\n\tassert((height-1) * RTREE_BITS_PER_LEVEL + bits_in_leaf == bits);\n\n\trtree->alloc = alloc;\n\trtree->dalloc = dalloc;\n\trtree->height = height;\n\n\t/* Root level. */\n\trtree->levels[0].subtree = NULL;\n\trtree->levels[0].bits = (height > 1) ? RTREE_BITS_PER_LEVEL :\n\t    bits_in_leaf;\n\trtree->levels[0].cumbits = rtree->levels[0].bits;\n\t/* Interior levels. */\n\tfor (i = 1; i < height-1; i++) {\n\t\trtree->levels[i].subtree = NULL;\n\t\trtree->levels[i].bits = RTREE_BITS_PER_LEVEL;\n\t\trtree->levels[i].cumbits = rtree->levels[i-1].cumbits +\n\t\t    RTREE_BITS_PER_LEVEL;\n\t}\n\t/* Leaf level. */\n\tif (height > 1) {\n\t\trtree->levels[height-1].subtree = NULL;\n\t\trtree->levels[height-1].bits = bits_in_leaf;\n\t\trtree->levels[height-1].cumbits = bits;\n\t}\n\n\t/* Compute lookup table to be used by rtree_start_level(). */\n\tfor (i = 0; i < RTREE_HEIGHT_MAX; i++) {\n\t\trtree->start_level[i] = hmin(RTREE_HEIGHT_MAX - 1 - i, height -\n\t\t    1);\n\t}\n\n\treturn (false);\n}\n\nstatic void\nrtree_delete_subtree(rtree_t *rtree, rtree_node_elm_t *node, unsigned level)\n{\n\n\tif (level + 1 < rtree->height) {\n\t\tsize_t nchildren, i;\n\n\t\tnchildren = ZU(1) << rtree->levels[level].bits;\n\t\tfor (i = 0; i < nchildren; i++) {\n\t\t\trtree_node_elm_t *child = node[i].child;\n\t\t\tif (child != NULL)\n\t\t\t\trtree_delete_subtree(rtree, child, level + 1);\n\t\t}\n\t}\n\trtree->dalloc(node);\n}\n\nvoid\nrtree_delete(rtree_t *rtree)\n{\n\tunsigned i;\n\n\tfor (i = 0; i < rtree->height; i++) {\n\t\trtree_node_elm_t *subtree = rtree->levels[i].subtree;\n\t\tif (subtree != NULL)\n\t\t\trtree_delete_subtree(rtree, subtree, i);\n\t}\n}\n\nstatic rtree_node_elm_t *\nrtree_node_init(rtree_t *rtree, unsigned level, rtree_node_elm_t **elmp)\n{\n\trtree_node_elm_t *node;\n\n\tif (atomic_cas_p((void **)elmp, NULL, RTREE_NODE_INITIALIZING)) {\n\t\t/*\n\t\t * Another thread is already in the process of initializing.\n\t\t * Spin-wait until initialization is complete.\n\t\t */\n\t\tdo {\n\t\t\tCPU_SPINWAIT;\n\t\t\tnode = atomic_read_p((void **)elmp);\n\t\t} while (node == RTREE_NODE_INITIALIZING);\n\t} else {\n\t\tnode = rtree->alloc(ZU(1) << rtree->levels[level].bits);\n\t\tif (node == NULL)\n\t\t\treturn (NULL);\n\t\tatomic_write_p((void **)elmp, node);\n\t}\n\n\treturn (node);\n}\n\nrtree_node_elm_t *\nrtree_subtree_read_hard(rtree_t *rtree, unsigned level)\n{\n\n\treturn (rtree_node_init(rtree, level, &rtree->levels[level].subtree));\n}\n\nrtree_node_elm_t *\nrtree_child_read_hard(rtree_t *rtree, rtree_node_elm_t *elm, unsigned level)\n{\n\n\treturn (rtree_node_init(rtree, level, &elm->child));\n}\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.8/deps/jemalloc/src/stats.c",
    "content": "#define\tJEMALLOC_STATS_C_\n#include \"jemalloc/internal/jemalloc_internal.h\"\n\n#define\tCTL_GET(n, v, t) do {\t\t\t\t\t\t\\\n\tsize_t sz = sizeof(t);\t\t\t\t\t\t\\\n\txmallctl(n, v, &sz, NULL, 0);\t\t\t\t\t\\\n} while (0)\n\n#define\tCTL_M2_GET(n, i, v, t) do {\t\t\t\t\t\\\n\tsize_t mib[6];\t\t\t\t\t\t\t\\\n\tsize_t miblen = sizeof(mib) / sizeof(size_t);\t\t\t\\\n\tsize_t sz = sizeof(t);\t\t\t\t\t\t\\\n\txmallctlnametomib(n, mib, &miblen);\t\t\t\t\\\n\tmib[2] = (i);\t\t\t\t\t\t\t\\\n\txmallctlbymib(mib, miblen, v, &sz, NULL, 0);\t\t\t\\\n} while (0)\n\n#define\tCTL_M2_M4_GET(n, i, j, v, t) do {\t\t\t\t\\\n\tsize_t mib[6];\t\t\t\t\t\t\t\\\n\tsize_t miblen = sizeof(mib) / sizeof(size_t);\t\t\t\\\n\tsize_t sz = sizeof(t);\t\t\t\t\t\t\\\n\txmallctlnametomib(n, mib, &miblen);\t\t\t\t\\\n\tmib[2] = (i);\t\t\t\t\t\t\t\\\n\tmib[4] = (j);\t\t\t\t\t\t\t\\\n\txmallctlbymib(mib, miblen, v, &sz, NULL, 0);\t\t\t\\\n} while (0)\n\n/******************************************************************************/\n/* Data. */\n\nbool\topt_stats_print = false;\n\nsize_t\tstats_cactive = 0;\n\n/******************************************************************************/\n/* Function prototypes for non-inline static functions. */\n\nstatic void\tstats_arena_bins_print(void (*write_cb)(void *, const char *),\n    void *cbopaque, unsigned i);\nstatic void\tstats_arena_lruns_print(void (*write_cb)(void *, const char *),\n    void *cbopaque, unsigned i);\nstatic void\tstats_arena_hchunks_print(\n    void (*write_cb)(void *, const char *), void *cbopaque, unsigned i);\nstatic void\tstats_arena_print(void (*write_cb)(void *, const char *),\n    void *cbopaque, unsigned i, bool bins, bool large, bool huge);\n\n/******************************************************************************/\n\nstatic void\nstats_arena_bins_print(void (*write_cb)(void *, const char *), void *cbopaque,\n    unsigned i)\n{\n\tsize_t page;\n\tbool config_tcache, in_gap;\n\tunsigned nbins, j;\n\n\tCTL_GET(\"arenas.page\", &page, size_t);\n\n\tCTL_GET(\"config.tcache\", &config_tcache, bool);\n\tif (config_tcache) {\n\t\tmalloc_cprintf(write_cb, cbopaque,\n\t\t    \"bins:           size ind    allocated      nmalloc\"\n\t\t    \"      ndalloc    nrequests      curregs      curruns regs\"\n\t\t    \" pgs  util       nfills     nflushes      newruns\"\n\t\t    \"       reruns\\n\");\n\t} else {\n\t\tmalloc_cprintf(write_cb, cbopaque,\n\t\t    \"bins:           size ind    allocated      nmalloc\"\n\t\t    \"      ndalloc    nrequests      curregs      curruns regs\"\n\t\t    \" pgs  util      newruns       reruns\\n\");\n\t}\n\tCTL_GET(\"arenas.nbins\", &nbins, unsigned);\n\tfor (j = 0, in_gap = false; j < nbins; j++) {\n\t\tuint64_t nruns;\n\n\t\tCTL_M2_M4_GET(\"stats.arenas.0.bins.0.nruns\", i, j, &nruns,\n\t\t    uint64_t);\n\t\tif (nruns == 0)\n\t\t\tin_gap = true;\n\t\telse {\n\t\t\tsize_t reg_size, run_size, curregs, availregs, milli;\n\t\t\tsize_t curruns;\n\t\t\tuint32_t nregs;\n\t\t\tuint64_t nmalloc, ndalloc, nrequests, nfills, nflushes;\n\t\t\tuint64_t reruns;\n\t\t\tchar util[6]; /* \"x.yyy\". */\n\n\t\t\tif (in_gap) {\n\t\t\t\tmalloc_cprintf(write_cb, cbopaque,\n\t\t\t\t    \"                     ---\\n\");\n\t\t\t\tin_gap = false;\n\t\t\t}\n\t\t\tCTL_M2_GET(\"arenas.bin.0.size\", j, &reg_size, size_t);\n\t\t\tCTL_M2_GET(\"arenas.bin.0.nregs\", j, &nregs, uint32_t);\n\t\t\tCTL_M2_GET(\"arenas.bin.0.run_size\", j, &run_size,\n\t\t\t    size_t);\n\t\t\tCTL_M2_M4_GET(\"stats.arenas.0.bins.0.nmalloc\", i, j,\n\t\t\t    &nmalloc, uint64_t);\n\t\t\tCTL_M2_M4_GET(\"stats.arenas.0.bins.0.ndalloc\", i, j,\n\t\t\t    &ndalloc, uint64_t);\n\t\t\tCTL_M2_M4_GET(\"stats.arenas.0.bins.0.curregs\", i, j,\n\t\t\t    &curregs, size_t);\n\t\t\tCTL_M2_M4_GET(\"stats.arenas.0.bins.0.nrequests\", i, j,\n\t\t\t    &nrequests, uint64_t);\n\t\t\tif (config_tcache) {\n\t\t\t\tCTL_M2_M4_GET(\"stats.arenas.0.bins.0.nfills\", i,\n\t\t\t\t    j, &nfills, uint64_t);\n\t\t\t\tCTL_M2_M4_GET(\"stats.arenas.0.bins.0.nflushes\",\n\t\t\t\t    i, j, &nflushes, uint64_t);\n\t\t\t}\n\t\t\tCTL_M2_M4_GET(\"stats.arenas.0.bins.0.nreruns\", i, j,\n\t\t\t    &reruns, uint64_t);\n\t\t\tCTL_M2_M4_GET(\"stats.arenas.0.bins.0.curruns\", i, j,\n\t\t\t    &curruns, size_t);\n\n\t\t\tavailregs = nregs * curruns;\n\t\t\tmilli = (availregs != 0) ? (1000 * curregs) / availregs\n\t\t\t    : 1000;\n\t\t\tassert(milli <= 1000);\n\t\t\tif (milli < 10) {\n\t\t\t\tmalloc_snprintf(util, sizeof(util),\n\t\t\t\t    \"0.00%zu\", milli);\n\t\t\t} else if (milli < 100) {\n\t\t\t\tmalloc_snprintf(util, sizeof(util), \"0.0%zu\",\n\t\t\t\t    milli);\n\t\t\t} else if (milli < 1000) {\n\t\t\t\tmalloc_snprintf(util, sizeof(util), \"0.%zu\",\n\t\t\t\t    milli);\n\t\t\t} else\n\t\t\t\tmalloc_snprintf(util, sizeof(util), \"1\");\n\n\t\t\tif (config_tcache) {\n\t\t\t\tmalloc_cprintf(write_cb, cbopaque,\n\t\t\t\t    \"%20zu %3u %12zu %12\"FMTu64\n\t\t\t\t    \" %12\"FMTu64\" %12\"FMTu64\" %12zu\"\n\t\t\t\t    \" %12zu %4u %3zu %-5s %12\"FMTu64\n\t\t\t\t    \" %12\"FMTu64\" %12\"FMTu64\" %12\"FMTu64\"\\n\",\n\t\t\t\t    reg_size, j, curregs * reg_size, nmalloc,\n\t\t\t\t    ndalloc, nrequests, curregs, curruns, nregs,\n\t\t\t\t    run_size / page, util, nfills, nflushes,\n\t\t\t\t    nruns, reruns);\n\t\t\t} else {\n\t\t\t\tmalloc_cprintf(write_cb, cbopaque,\n\t\t\t\t    \"%20zu %3u %12zu %12\"FMTu64\n\t\t\t\t    \" %12\"FMTu64\" %12\"FMTu64\" %12zu\"\n\t\t\t\t    \" %12zu %4u %3zu %-5s %12\"FMTu64\n\t\t\t\t    \" %12\"FMTu64\"\\n\",\n\t\t\t\t    reg_size, j, curregs * reg_size, nmalloc,\n\t\t\t\t    ndalloc, nrequests, curregs, curruns, nregs,\n\t\t\t\t    run_size / page, util, nruns, reruns);\n\t\t\t}\n\t\t}\n\t}\n\tif (in_gap) {\n\t\tmalloc_cprintf(write_cb, cbopaque,\n\t\t    \"                     ---\\n\");\n\t}\n}\n\nstatic void\nstats_arena_lruns_print(void (*write_cb)(void *, const char *), void *cbopaque,\n    unsigned i)\n{\n\tunsigned nbins, nlruns, j;\n\tbool in_gap;\n\n\tmalloc_cprintf(write_cb, cbopaque,\n\t    \"large:          size ind    allocated      nmalloc      ndalloc\"\n\t    \"    nrequests      curruns\\n\");\n\tCTL_GET(\"arenas.nbins\", &nbins, unsigned);\n\tCTL_GET(\"arenas.nlruns\", &nlruns, unsigned);\n\tfor (j = 0, in_gap = false; j < nlruns; j++) {\n\t\tuint64_t nmalloc, ndalloc, nrequests;\n\t\tsize_t run_size, curruns;\n\n\t\tCTL_M2_M4_GET(\"stats.arenas.0.lruns.0.nmalloc\", i, j, &nmalloc,\n\t\t    uint64_t);\n\t\tCTL_M2_M4_GET(\"stats.arenas.0.lruns.0.ndalloc\", i, j, &ndalloc,\n\t\t    uint64_t);\n\t\tCTL_M2_M4_GET(\"stats.arenas.0.lruns.0.nrequests\", i, j,\n\t\t    &nrequests, uint64_t);\n\t\tif (nrequests == 0)\n\t\t\tin_gap = true;\n\t\telse {\n\t\t\tCTL_M2_GET(\"arenas.lrun.0.size\", j, &run_size, size_t);\n\t\t\tCTL_M2_M4_GET(\"stats.arenas.0.lruns.0.curruns\", i, j,\n\t\t\t    &curruns, size_t);\n\t\t\tif (in_gap) {\n\t\t\t\tmalloc_cprintf(write_cb, cbopaque,\n\t\t\t\t    \"                     ---\\n\");\n\t\t\t\tin_gap = false;\n\t\t\t}\n\t\t\tmalloc_cprintf(write_cb, cbopaque,\n\t\t\t    \"%20zu %3u %12zu %12\"FMTu64\" %12\"FMTu64\n\t\t\t    \" %12\"FMTu64\" %12zu\\n\",\n\t\t\t    run_size, nbins + j, curruns * run_size, nmalloc,\n\t\t\t    ndalloc, nrequests, curruns);\n\t\t}\n\t}\n\tif (in_gap) {\n\t\tmalloc_cprintf(write_cb, cbopaque,\n\t\t    \"                     ---\\n\");\n\t}\n}\n\nstatic void\nstats_arena_hchunks_print(void (*write_cb)(void *, const char *),\n    void *cbopaque, unsigned i)\n{\n\tunsigned nbins, nlruns, nhchunks, j;\n\tbool in_gap;\n\n\tmalloc_cprintf(write_cb, cbopaque,\n\t    \"huge:           size ind    allocated      nmalloc      ndalloc\"\n\t    \"    nrequests   curhchunks\\n\");\n\tCTL_GET(\"arenas.nbins\", &nbins, unsigned);\n\tCTL_GET(\"arenas.nlruns\", &nlruns, unsigned);\n\tCTL_GET(\"arenas.nhchunks\", &nhchunks, unsigned);\n\tfor (j = 0, in_gap = false; j < nhchunks; j++) {\n\t\tuint64_t nmalloc, ndalloc, nrequests;\n\t\tsize_t hchunk_size, curhchunks;\n\n\t\tCTL_M2_M4_GET(\"stats.arenas.0.hchunks.0.nmalloc\", i, j,\n\t\t    &nmalloc, uint64_t);\n\t\tCTL_M2_M4_GET(\"stats.arenas.0.hchunks.0.ndalloc\", i, j,\n\t\t    &ndalloc, uint64_t);\n\t\tCTL_M2_M4_GET(\"stats.arenas.0.hchunks.0.nrequests\", i, j,\n\t\t    &nrequests, uint64_t);\n\t\tif (nrequests == 0)\n\t\t\tin_gap = true;\n\t\telse {\n\t\t\tCTL_M2_GET(\"arenas.hchunk.0.size\", j, &hchunk_size,\n\t\t\t    size_t);\n\t\t\tCTL_M2_M4_GET(\"stats.arenas.0.hchunks.0.curhchunks\", i,\n\t\t\t    j, &curhchunks, size_t);\n\t\t\tif (in_gap) {\n\t\t\t\tmalloc_cprintf(write_cb, cbopaque,\n\t\t\t\t    \"                     ---\\n\");\n\t\t\t\tin_gap = false;\n\t\t\t}\n\t\t\tmalloc_cprintf(write_cb, cbopaque,\n\t\t\t    \"%20zu %3u %12zu %12\"FMTu64\" %12\"FMTu64\n\t\t\t    \" %12\"FMTu64\" %12zu\\n\",\n\t\t\t    hchunk_size, nbins + nlruns + j,\n\t\t\t    curhchunks * hchunk_size, nmalloc, ndalloc,\n\t\t\t    nrequests, curhchunks);\n\t\t}\n\t}\n\tif (in_gap) {\n\t\tmalloc_cprintf(write_cb, cbopaque,\n\t\t    \"                     ---\\n\");\n\t}\n}\n\nstatic void\nstats_arena_print(void (*write_cb)(void *, const char *), void *cbopaque,\n    unsigned i, bool bins, bool large, bool huge)\n{\n\tunsigned nthreads;\n\tconst char *dss;\n\tssize_t lg_dirty_mult;\n\tsize_t page, pactive, pdirty, mapped;\n\tsize_t metadata_mapped, metadata_allocated;\n\tuint64_t npurge, nmadvise, purged;\n\tsize_t small_allocated;\n\tuint64_t small_nmalloc, small_ndalloc, small_nrequests;\n\tsize_t large_allocated;\n\tuint64_t large_nmalloc, large_ndalloc, large_nrequests;\n\tsize_t huge_allocated;\n\tuint64_t huge_nmalloc, huge_ndalloc, huge_nrequests;\n\n\tCTL_GET(\"arenas.page\", &page, size_t);\n\n\tCTL_M2_GET(\"stats.arenas.0.nthreads\", i, &nthreads, unsigned);\n\tmalloc_cprintf(write_cb, cbopaque,\n\t    \"assigned threads: %u\\n\", nthreads);\n\tCTL_M2_GET(\"stats.arenas.0.dss\", i, &dss, const char *);\n\tmalloc_cprintf(write_cb, cbopaque, \"dss allocation precedence: %s\\n\",\n\t    dss);\n\tCTL_M2_GET(\"stats.arenas.0.lg_dirty_mult\", i, &lg_dirty_mult, ssize_t);\n\tif (lg_dirty_mult >= 0) {\n\t\tmalloc_cprintf(write_cb, cbopaque,\n\t\t    \"min active:dirty page ratio: %u:1\\n\",\n\t\t    (1U << lg_dirty_mult));\n\t} else {\n\t\tmalloc_cprintf(write_cb, cbopaque,\n\t\t    \"min active:dirty page ratio: N/A\\n\");\n\t}\n\tCTL_M2_GET(\"stats.arenas.0.pactive\", i, &pactive, size_t);\n\tCTL_M2_GET(\"stats.arenas.0.pdirty\", i, &pdirty, size_t);\n\tCTL_M2_GET(\"stats.arenas.0.npurge\", i, &npurge, uint64_t);\n\tCTL_M2_GET(\"stats.arenas.0.nmadvise\", i, &nmadvise, uint64_t);\n\tCTL_M2_GET(\"stats.arenas.0.purged\", i, &purged, uint64_t);\n\tmalloc_cprintf(write_cb, cbopaque,\n\t    \"dirty pages: %zu:%zu active:dirty, %\"FMTu64\" sweep%s, %\"FMTu64\n\t    \" madvise%s, %\"FMTu64\" purged\\n\", pactive, pdirty, npurge, npurge ==\n\t    1 ? \"\" : \"s\", nmadvise, nmadvise == 1 ? \"\" : \"s\", purged);\n\n\tmalloc_cprintf(write_cb, cbopaque,\n\t    \"                            allocated      nmalloc      ndalloc\"\n\t    \"    nrequests\\n\");\n\tCTL_M2_GET(\"stats.arenas.0.small.allocated\", i, &small_allocated,\n\t    size_t);\n\tCTL_M2_GET(\"stats.arenas.0.small.nmalloc\", i, &small_nmalloc, uint64_t);\n\tCTL_M2_GET(\"stats.arenas.0.small.ndalloc\", i, &small_ndalloc, uint64_t);\n\tCTL_M2_GET(\"stats.arenas.0.small.nrequests\", i, &small_nrequests,\n\t    uint64_t);\n\tmalloc_cprintf(write_cb, cbopaque,\n\t    \"small:                   %12zu %12\"FMTu64\" %12\"FMTu64\n\t    \" %12\"FMTu64\"\\n\",\n\t    small_allocated, small_nmalloc, small_ndalloc, small_nrequests);\n\tCTL_M2_GET(\"stats.arenas.0.large.allocated\", i, &large_allocated,\n\t    size_t);\n\tCTL_M2_GET(\"stats.arenas.0.large.nmalloc\", i, &large_nmalloc, uint64_t);\n\tCTL_M2_GET(\"stats.arenas.0.large.ndalloc\", i, &large_ndalloc, uint64_t);\n\tCTL_M2_GET(\"stats.arenas.0.large.nrequests\", i, &large_nrequests,\n\t    uint64_t);\n\tmalloc_cprintf(write_cb, cbopaque,\n\t    \"large:                   %12zu %12\"FMTu64\" %12\"FMTu64\n\t    \" %12\"FMTu64\"\\n\",\n\t    large_allocated, large_nmalloc, large_ndalloc, large_nrequests);\n\tCTL_M2_GET(\"stats.arenas.0.huge.allocated\", i, &huge_allocated, size_t);\n\tCTL_M2_GET(\"stats.arenas.0.huge.nmalloc\", i, &huge_nmalloc, uint64_t);\n\tCTL_M2_GET(\"stats.arenas.0.huge.ndalloc\", i, &huge_ndalloc, uint64_t);\n\tCTL_M2_GET(\"stats.arenas.0.huge.nrequests\", i, &huge_nrequests,\n\t    uint64_t);\n\tmalloc_cprintf(write_cb, cbopaque,\n\t    \"huge:                    %12zu %12\"FMTu64\" %12\"FMTu64\n\t    \" %12\"FMTu64\"\\n\",\n\t    huge_allocated, huge_nmalloc, huge_ndalloc, huge_nrequests);\n\tmalloc_cprintf(write_cb, cbopaque,\n\t    \"total:                   %12zu %12\"FMTu64\" %12\"FMTu64\n\t    \" %12\"FMTu64\"\\n\",\n\t    small_allocated + large_allocated + huge_allocated,\n\t    small_nmalloc + large_nmalloc + huge_nmalloc,\n\t    small_ndalloc + large_ndalloc + huge_ndalloc,\n\t    small_nrequests + large_nrequests + huge_nrequests);\n\tmalloc_cprintf(write_cb, cbopaque,\n\t    \"active:                  %12zu\\n\", pactive * page);\n\tCTL_M2_GET(\"stats.arenas.0.mapped\", i, &mapped, size_t);\n\tmalloc_cprintf(write_cb, cbopaque,\n\t    \"mapped:                  %12zu\\n\", mapped);\n\tCTL_M2_GET(\"stats.arenas.0.metadata.mapped\", i, &metadata_mapped,\n\t    size_t);\n\tCTL_M2_GET(\"stats.arenas.0.metadata.allocated\", i, &metadata_allocated,\n\t    size_t);\n\tmalloc_cprintf(write_cb, cbopaque,\n\t    \"metadata: mapped: %zu, allocated: %zu\\n\",\n\t    metadata_mapped, metadata_allocated);\n\n\tif (bins)\n\t\tstats_arena_bins_print(write_cb, cbopaque, i);\n\tif (large)\n\t\tstats_arena_lruns_print(write_cb, cbopaque, i);\n\tif (huge)\n\t\tstats_arena_hchunks_print(write_cb, cbopaque, i);\n}\n\nvoid\nstats_print(void (*write_cb)(void *, const char *), void *cbopaque,\n    const char *opts)\n{\n\tint err;\n\tuint64_t epoch;\n\tsize_t u64sz;\n\tbool general = true;\n\tbool merged = true;\n\tbool unmerged = true;\n\tbool bins = true;\n\tbool large = true;\n\tbool huge = true;\n\n\t/*\n\t * Refresh stats, in case mallctl() was called by the application.\n\t *\n\t * Check for OOM here, since refreshing the ctl cache can trigger\n\t * allocation.  In practice, none of the subsequent mallctl()-related\n\t * calls in this function will cause OOM if this one succeeds.\n\t * */\n\tepoch = 1;\n\tu64sz = sizeof(uint64_t);\n\terr = je_mallctl(\"epoch\", &epoch, &u64sz, &epoch, sizeof(uint64_t));\n\tif (err != 0) {\n\t\tif (err == EAGAIN) {\n\t\t\tmalloc_write(\"<jemalloc>: Memory allocation failure in \"\n\t\t\t    \"mallctl(\\\"epoch\\\", ...)\\n\");\n\t\t\treturn;\n\t\t}\n\t\tmalloc_write(\"<jemalloc>: Failure in mallctl(\\\"epoch\\\", \"\n\t\t    \"...)\\n\");\n\t\tabort();\n\t}\n\n\tif (opts != NULL) {\n\t\tunsigned i;\n\n\t\tfor (i = 0; opts[i] != '\\0'; i++) {\n\t\t\tswitch (opts[i]) {\n\t\t\tcase 'g':\n\t\t\t\tgeneral = false;\n\t\t\t\tbreak;\n\t\t\tcase 'm':\n\t\t\t\tmerged = false;\n\t\t\t\tbreak;\n\t\t\tcase 'a':\n\t\t\t\tunmerged = false;\n\t\t\t\tbreak;\n\t\t\tcase 'b':\n\t\t\t\tbins = false;\n\t\t\t\tbreak;\n\t\t\tcase 'l':\n\t\t\t\tlarge = false;\n\t\t\t\tbreak;\n\t\t\tcase 'h':\n\t\t\t\thuge = false;\n\t\t\t\tbreak;\n\t\t\tdefault:;\n\t\t\t}\n\t\t}\n\t}\n\n\tmalloc_cprintf(write_cb, cbopaque,\n\t    \"___ Begin jemalloc statistics ___\\n\");\n\tif (general) {\n\t\tconst char *cpv;\n\t\tbool bv;\n\t\tunsigned uv;\n\t\tssize_t ssv;\n\t\tsize_t sv, bsz, ssz, sssz, cpsz;\n\n\t\tbsz = sizeof(bool);\n\t\tssz = sizeof(size_t);\n\t\tsssz = sizeof(ssize_t);\n\t\tcpsz = sizeof(const char *);\n\n\t\tCTL_GET(\"version\", &cpv, const char *);\n\t\tmalloc_cprintf(write_cb, cbopaque, \"Version: %s\\n\", cpv);\n\t\tCTL_GET(\"config.debug\", &bv, bool);\n\t\tmalloc_cprintf(write_cb, cbopaque, \"Assertions %s\\n\",\n\t\t    bv ? \"enabled\" : \"disabled\");\n\n#define\tOPT_WRITE_BOOL(n)\t\t\t\t\t\t\\\n\t\tif (je_mallctl(\"opt.\"#n, &bv, &bsz, NULL, 0) == 0) {\t\\\n\t\t\tmalloc_cprintf(write_cb, cbopaque,\t\t\\\n\t\t\t    \"  opt.\"#n\": %s\\n\", bv ? \"true\" : \"false\");\t\\\n\t\t}\n#define\tOPT_WRITE_BOOL_MUTABLE(n, m) {\t\t\t\t\t\\\n\t\tbool bv2;\t\t\t\t\t\t\\\n\t\tif (je_mallctl(\"opt.\"#n, &bv, &bsz, NULL, 0) == 0 &&\t\\\n\t\t    je_mallctl(#m, &bv2, &bsz, NULL, 0) == 0) {\t\t\\\n\t\t\tmalloc_cprintf(write_cb, cbopaque,\t\t\\\n\t\t\t    \"  opt.\"#n\": %s (\"#m\": %s)\\n\", bv ? \"true\"\t\\\n\t\t\t    : \"false\", bv2 ? \"true\" : \"false\");\t\t\\\n\t\t}\t\t\t\t\t\t\t\\\n}\n#define\tOPT_WRITE_SIZE_T(n)\t\t\t\t\t\t\\\n\t\tif (je_mallctl(\"opt.\"#n, &sv, &ssz, NULL, 0) == 0) {\t\\\n\t\t\tmalloc_cprintf(write_cb, cbopaque,\t\t\\\n\t\t\t\"  opt.\"#n\": %zu\\n\", sv);\t\t\t\\\n\t\t}\n#define\tOPT_WRITE_SSIZE_T(n)\t\t\t\t\t\t\\\n\t\tif (je_mallctl(\"opt.\"#n, &ssv, &sssz, NULL, 0) == 0) {\t\\\n\t\t\tmalloc_cprintf(write_cb, cbopaque,\t\t\\\n\t\t\t    \"  opt.\"#n\": %zd\\n\", ssv);\t\t\t\\\n\t\t}\n#define\tOPT_WRITE_SSIZE_T_MUTABLE(n, m) {\t\t\t\t\\\n\t\tssize_t ssv2;\t\t\t\t\t\t\\\n\t\tif (je_mallctl(\"opt.\"#n, &ssv, &sssz, NULL, 0) == 0 &&\t\\\n\t\t    je_mallctl(#m, &ssv2, &sssz, NULL, 0) == 0) {\t\\\n\t\t\tmalloc_cprintf(write_cb, cbopaque,\t\t\\\n\t\t\t    \"  opt.\"#n\": %zd (\"#m\": %zd)\\n\",\t\t\\\n\t\t\t    ssv, ssv2);\t\t\t\t\t\\\n\t\t}\t\t\t\t\t\t\t\\\n}\n#define\tOPT_WRITE_CHAR_P(n)\t\t\t\t\t\t\\\n\t\tif (je_mallctl(\"opt.\"#n, &cpv, &cpsz, NULL, 0) == 0) {\t\\\n\t\t\tmalloc_cprintf(write_cb, cbopaque,\t\t\\\n\t\t\t    \"  opt.\"#n\": \\\"%s\\\"\\n\", cpv);\t\t\\\n\t\t}\n\n\t\tmalloc_cprintf(write_cb, cbopaque,\n\t\t    \"Run-time option settings:\\n\");\n\t\tOPT_WRITE_BOOL(abort)\n\t\tOPT_WRITE_SIZE_T(lg_chunk)\n\t\tOPT_WRITE_CHAR_P(dss)\n\t\tOPT_WRITE_SIZE_T(narenas)\n\t\tOPT_WRITE_SSIZE_T_MUTABLE(lg_dirty_mult, arenas.lg_dirty_mult)\n\t\tOPT_WRITE_BOOL(stats_print)\n\t\tOPT_WRITE_CHAR_P(junk)\n\t\tOPT_WRITE_SIZE_T(quarantine)\n\t\tOPT_WRITE_BOOL(redzone)\n\t\tOPT_WRITE_BOOL(zero)\n\t\tOPT_WRITE_BOOL(utrace)\n\t\tOPT_WRITE_BOOL(valgrind)\n\t\tOPT_WRITE_BOOL(xmalloc)\n\t\tOPT_WRITE_BOOL(tcache)\n\t\tOPT_WRITE_SSIZE_T(lg_tcache_max)\n\t\tOPT_WRITE_BOOL(prof)\n\t\tOPT_WRITE_CHAR_P(prof_prefix)\n\t\tOPT_WRITE_BOOL_MUTABLE(prof_active, prof.active)\n\t\tOPT_WRITE_BOOL_MUTABLE(prof_thread_active_init,\n\t\t    prof.thread_active_init)\n\t\tOPT_WRITE_SSIZE_T(lg_prof_sample)\n\t\tOPT_WRITE_BOOL(prof_accum)\n\t\tOPT_WRITE_SSIZE_T(lg_prof_interval)\n\t\tOPT_WRITE_BOOL(prof_gdump)\n\t\tOPT_WRITE_BOOL(prof_final)\n\t\tOPT_WRITE_BOOL(prof_leak)\n\n#undef OPT_WRITE_BOOL\n#undef OPT_WRITE_BOOL_MUTABLE\n#undef OPT_WRITE_SIZE_T\n#undef OPT_WRITE_SSIZE_T\n#undef OPT_WRITE_CHAR_P\n\n\t\tmalloc_cprintf(write_cb, cbopaque, \"CPUs: %u\\n\", ncpus);\n\n\t\tCTL_GET(\"arenas.narenas\", &uv, unsigned);\n\t\tmalloc_cprintf(write_cb, cbopaque, \"Arenas: %u\\n\", uv);\n\n\t\tmalloc_cprintf(write_cb, cbopaque, \"Pointer size: %zu\\n\",\n\t\t    sizeof(void *));\n\n\t\tCTL_GET(\"arenas.quantum\", &sv, size_t);\n\t\tmalloc_cprintf(write_cb, cbopaque, \"Quantum size: %zu\\n\",\n\t\t    sv);\n\n\t\tCTL_GET(\"arenas.page\", &sv, size_t);\n\t\tmalloc_cprintf(write_cb, cbopaque, \"Page size: %zu\\n\", sv);\n\n\t\tCTL_GET(\"arenas.lg_dirty_mult\", &ssv, ssize_t);\n\t\tif (ssv >= 0) {\n\t\t\tmalloc_cprintf(write_cb, cbopaque,\n\t\t\t    \"Min active:dirty page ratio per arena: %u:1\\n\",\n\t\t\t    (1U << ssv));\n\t\t} else {\n\t\t\tmalloc_cprintf(write_cb, cbopaque,\n\t\t\t    \"Min active:dirty page ratio per arena: N/A\\n\");\n\t\t}\n\t\tif (je_mallctl(\"arenas.tcache_max\", &sv, &ssz, NULL, 0) == 0) {\n\t\t\tmalloc_cprintf(write_cb, cbopaque,\n\t\t\t    \"Maximum thread-cached size class: %zu\\n\", sv);\n\t\t}\n\t\tif (je_mallctl(\"opt.prof\", &bv, &bsz, NULL, 0) == 0 && bv) {\n\t\t\tCTL_GET(\"prof.lg_sample\", &sv, size_t);\n\t\t\tmalloc_cprintf(write_cb, cbopaque,\n\t\t\t    \"Average profile sample interval: %\"FMTu64\n\t\t\t    \" (2^%zu)\\n\", (((uint64_t)1U) << sv), sv);\n\n\t\t\tCTL_GET(\"opt.lg_prof_interval\", &ssv, ssize_t);\n\t\t\tif (ssv >= 0) {\n\t\t\t\tmalloc_cprintf(write_cb, cbopaque,\n\t\t\t\t    \"Average profile dump interval: %\"FMTu64\n\t\t\t\t    \" (2^%zd)\\n\",\n\t\t\t\t    (((uint64_t)1U) << ssv), ssv);\n\t\t\t} else {\n\t\t\t\tmalloc_cprintf(write_cb, cbopaque,\n\t\t\t\t    \"Average profile dump interval: N/A\\n\");\n\t\t\t}\n\t\t}\n\t\tCTL_GET(\"opt.lg_chunk\", &sv, size_t);\n\t\tmalloc_cprintf(write_cb, cbopaque,\n\t\t    \"Chunk size: %zu (2^%zu)\\n\", (ZU(1) << sv), sv);\n\t}\n\n\tif (config_stats) {\n\t\tsize_t *cactive;\n\t\tsize_t allocated, active, metadata, resident, mapped;\n\n\t\tCTL_GET(\"stats.cactive\", &cactive, size_t *);\n\t\tCTL_GET(\"stats.allocated\", &allocated, size_t);\n\t\tCTL_GET(\"stats.active\", &active, size_t);\n\t\tCTL_GET(\"stats.metadata\", &metadata, size_t);\n\t\tCTL_GET(\"stats.resident\", &resident, size_t);\n\t\tCTL_GET(\"stats.mapped\", &mapped, size_t);\n\t\tmalloc_cprintf(write_cb, cbopaque,\n\t\t    \"Allocated: %zu, active: %zu, metadata: %zu,\"\n\t\t    \" resident: %zu, mapped: %zu\\n\",\n\t\t    allocated, active, metadata, resident, mapped);\n\t\tmalloc_cprintf(write_cb, cbopaque,\n\t\t    \"Current active ceiling: %zu\\n\",\n\t\t    atomic_read_z(cactive));\n\n\t\tif (merged) {\n\t\t\tunsigned narenas;\n\n\t\t\tCTL_GET(\"arenas.narenas\", &narenas, unsigned);\n\t\t\t{\n\t\t\t\tVARIABLE_ARRAY(bool, initialized, narenas);\n\t\t\t\tsize_t isz;\n\t\t\t\tunsigned i, ninitialized;\n\n\t\t\t\tisz = sizeof(bool) * narenas;\n\t\t\t\txmallctl(\"arenas.initialized\", initialized,\n\t\t\t\t    &isz, NULL, 0);\n\t\t\t\tfor (i = ninitialized = 0; i < narenas; i++) {\n\t\t\t\t\tif (initialized[i])\n\t\t\t\t\t\tninitialized++;\n\t\t\t\t}\n\n\t\t\t\tif (ninitialized > 1 || !unmerged) {\n\t\t\t\t\t/* Print merged arena stats. */\n\t\t\t\t\tmalloc_cprintf(write_cb, cbopaque,\n\t\t\t\t\t    \"\\nMerged arenas stats:\\n\");\n\t\t\t\t\tstats_arena_print(write_cb, cbopaque,\n\t\t\t\t\t    narenas, bins, large, huge);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tif (unmerged) {\n\t\t\tunsigned narenas;\n\n\t\t\t/* Print stats for each arena. */\n\n\t\t\tCTL_GET(\"arenas.narenas\", &narenas, unsigned);\n\t\t\t{\n\t\t\t\tVARIABLE_ARRAY(bool, initialized, narenas);\n\t\t\t\tsize_t isz;\n\t\t\t\tunsigned i;\n\n\t\t\t\tisz = sizeof(bool) * narenas;\n\t\t\t\txmallctl(\"arenas.initialized\", initialized,\n\t\t\t\t    &isz, NULL, 0);\n\n\t\t\t\tfor (i = 0; i < narenas; i++) {\n\t\t\t\t\tif (initialized[i]) {\n\t\t\t\t\t\tmalloc_cprintf(write_cb,\n\t\t\t\t\t\t    cbopaque,\n\t\t\t\t\t\t    \"\\narenas[%u]:\\n\", i);\n\t\t\t\t\t\tstats_arena_print(write_cb,\n\t\t\t\t\t\t    cbopaque, i, bins, large,\n\t\t\t\t\t\t    huge);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\tmalloc_cprintf(write_cb, cbopaque, \"--- End jemalloc statistics ---\\n\");\n}\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.8/deps/jemalloc/src/tcache.c",
    "content": "#define\tJEMALLOC_TCACHE_C_\n#include \"jemalloc/internal/jemalloc_internal.h\"\n\n/******************************************************************************/\n/* Data. */\n\nbool\topt_tcache = true;\nssize_t\topt_lg_tcache_max = LG_TCACHE_MAXCLASS_DEFAULT;\n\ntcache_bin_info_t\t*tcache_bin_info;\nstatic unsigned\t\tstack_nelms; /* Total stack elms per tcache. */\n\nsize_t\t\t\tnhbins;\nsize_t\t\t\ttcache_maxclass;\n\ntcaches_t\t\t*tcaches;\n\n/* Index of first element within tcaches that has never been used. */\nstatic unsigned\t\ttcaches_past;\n\n/* Head of singly linked list tracking available tcaches elements. */\nstatic tcaches_t\t*tcaches_avail;\n\n/******************************************************************************/\n\nsize_t\ttcache_salloc(const void *ptr)\n{\n\n\treturn (arena_salloc(ptr, false));\n}\n\nvoid\ntcache_event_hard(tsd_t *tsd, tcache_t *tcache)\n{\n\tszind_t binind = tcache->next_gc_bin;\n\ttcache_bin_t *tbin = &tcache->tbins[binind];\n\ttcache_bin_info_t *tbin_info = &tcache_bin_info[binind];\n\n\tif (tbin->low_water > 0) {\n\t\t/*\n\t\t * Flush (ceiling) 3/4 of the objects below the low water mark.\n\t\t */\n\t\tif (binind < NBINS) {\n\t\t\ttcache_bin_flush_small(tsd, tcache, tbin, binind,\n\t\t\t    tbin->ncached - tbin->low_water + (tbin->low_water\n\t\t\t    >> 2));\n\t\t} else {\n\t\t\ttcache_bin_flush_large(tsd, tbin, binind, tbin->ncached\n\t\t\t    - tbin->low_water + (tbin->low_water >> 2), tcache);\n\t\t}\n\t\t/*\n\t\t * Reduce fill count by 2X.  Limit lg_fill_div such that the\n\t\t * fill count is always at least 1.\n\t\t */\n\t\tif ((tbin_info->ncached_max >> (tbin->lg_fill_div+1)) >= 1)\n\t\t\ttbin->lg_fill_div++;\n\t} else if (tbin->low_water < 0) {\n\t\t/*\n\t\t * Increase fill count by 2X.  Make sure lg_fill_div stays\n\t\t * greater than 0.\n\t\t */\n\t\tif (tbin->lg_fill_div > 1)\n\t\t\ttbin->lg_fill_div--;\n\t}\n\ttbin->low_water = tbin->ncached;\n\n\ttcache->next_gc_bin++;\n\tif (tcache->next_gc_bin == nhbins)\n\t\ttcache->next_gc_bin = 0;\n\ttcache->ev_cnt = 0;\n}\n\nvoid *\ntcache_alloc_small_hard(tsd_t *tsd, arena_t *arena, tcache_t *tcache,\n    tcache_bin_t *tbin, szind_t binind)\n{\n\tvoid *ret;\n\n\tarena_tcache_fill_small(arena, tbin, binind, config_prof ?\n\t    tcache->prof_accumbytes : 0);\n\tif (config_prof)\n\t\ttcache->prof_accumbytes = 0;\n\tret = tcache_alloc_easy(tbin);\n\n\treturn (ret);\n}\n\nvoid\ntcache_bin_flush_small(tsd_t *tsd, tcache_t *tcache, tcache_bin_t *tbin,\n    szind_t binind, unsigned rem)\n{\n\tarena_t *arena;\n\tvoid *ptr;\n\tunsigned i, nflush, ndeferred;\n\tbool merged_stats = false;\n\n\tassert(binind < NBINS);\n\tassert(rem <= tbin->ncached);\n\n\tarena = arena_choose(tsd, NULL);\n\tassert(arena != NULL);\n\tfor (nflush = tbin->ncached - rem; nflush > 0; nflush = ndeferred) {\n\t\t/* Lock the arena bin associated with the first object. */\n\t\tarena_chunk_t *chunk = (arena_chunk_t *)CHUNK_ADDR2BASE(\n\t\t    tbin->avail[0]);\n\t\tarena_t *bin_arena = extent_node_arena_get(&chunk->node);\n\t\tarena_bin_t *bin = &bin_arena->bins[binind];\n\n\t\tif (config_prof && bin_arena == arena) {\n\t\t\tif (arena_prof_accum(arena, tcache->prof_accumbytes))\n\t\t\t\tprof_idump();\n\t\t\ttcache->prof_accumbytes = 0;\n\t\t}\n\n\t\tmalloc_mutex_lock(&bin->lock);\n\t\tif (config_stats && bin_arena == arena) {\n\t\t\tassert(!merged_stats);\n\t\t\tmerged_stats = true;\n\t\t\tbin->stats.nflushes++;\n\t\t\tbin->stats.nrequests += tbin->tstats.nrequests;\n\t\t\ttbin->tstats.nrequests = 0;\n\t\t}\n\t\tndeferred = 0;\n\t\tfor (i = 0; i < nflush; i++) {\n\t\t\tptr = tbin->avail[i];\n\t\t\tassert(ptr != NULL);\n\t\t\tchunk = (arena_chunk_t *)CHUNK_ADDR2BASE(ptr);\n\t\t\tif (extent_node_arena_get(&chunk->node) == bin_arena) {\n\t\t\t\tsize_t pageind = ((uintptr_t)ptr -\n\t\t\t\t    (uintptr_t)chunk) >> LG_PAGE;\n\t\t\t\tarena_chunk_map_bits_t *bitselm =\n\t\t\t\t    arena_bitselm_get(chunk, pageind);\n\t\t\t\tarena_dalloc_bin_junked_locked(bin_arena, chunk,\n\t\t\t\t    ptr, bitselm);\n\t\t\t} else {\n\t\t\t\t/*\n\t\t\t\t * This object was allocated via a different\n\t\t\t\t * arena bin than the one that is currently\n\t\t\t\t * locked.  Stash the object, so that it can be\n\t\t\t\t * handled in a future pass.\n\t\t\t\t */\n\t\t\t\ttbin->avail[ndeferred] = ptr;\n\t\t\t\tndeferred++;\n\t\t\t}\n\t\t}\n\t\tmalloc_mutex_unlock(&bin->lock);\n\t}\n\tif (config_stats && !merged_stats) {\n\t\t/*\n\t\t * The flush loop didn't happen to flush to this thread's\n\t\t * arena, so the stats didn't get merged.  Manually do so now.\n\t\t */\n\t\tarena_bin_t *bin = &arena->bins[binind];\n\t\tmalloc_mutex_lock(&bin->lock);\n\t\tbin->stats.nflushes++;\n\t\tbin->stats.nrequests += tbin->tstats.nrequests;\n\t\ttbin->tstats.nrequests = 0;\n\t\tmalloc_mutex_unlock(&bin->lock);\n\t}\n\n\tmemmove(tbin->avail, &tbin->avail[tbin->ncached - rem],\n\t    rem * sizeof(void *));\n\ttbin->ncached = rem;\n\tif ((int)tbin->ncached < tbin->low_water)\n\t\ttbin->low_water = tbin->ncached;\n}\n\nvoid\ntcache_bin_flush_large(tsd_t *tsd, tcache_bin_t *tbin, szind_t binind,\n    unsigned rem, tcache_t *tcache)\n{\n\tarena_t *arena;\n\tvoid *ptr;\n\tunsigned i, nflush, ndeferred;\n\tbool merged_stats = false;\n\n\tassert(binind < nhbins);\n\tassert(rem <= tbin->ncached);\n\n\tarena = arena_choose(tsd, NULL);\n\tassert(arena != NULL);\n\tfor (nflush = tbin->ncached - rem; nflush > 0; nflush = ndeferred) {\n\t\t/* Lock the arena associated with the first object. */\n\t\tarena_chunk_t *chunk = (arena_chunk_t *)CHUNK_ADDR2BASE(\n\t\t    tbin->avail[0]);\n\t\tarena_t *locked_arena = extent_node_arena_get(&chunk->node);\n\t\tUNUSED bool idump;\n\n\t\tif (config_prof)\n\t\t\tidump = false;\n\t\tmalloc_mutex_lock(&locked_arena->lock);\n\t\tif ((config_prof || config_stats) && locked_arena == arena) {\n\t\t\tif (config_prof) {\n\t\t\t\tidump = arena_prof_accum_locked(arena,\n\t\t\t\t    tcache->prof_accumbytes);\n\t\t\t\ttcache->prof_accumbytes = 0;\n\t\t\t}\n\t\t\tif (config_stats) {\n\t\t\t\tmerged_stats = true;\n\t\t\t\tarena->stats.nrequests_large +=\n\t\t\t\t    tbin->tstats.nrequests;\n\t\t\t\tarena->stats.lstats[binind - NBINS].nrequests +=\n\t\t\t\t    tbin->tstats.nrequests;\n\t\t\t\ttbin->tstats.nrequests = 0;\n\t\t\t}\n\t\t}\n\t\tndeferred = 0;\n\t\tfor (i = 0; i < nflush; i++) {\n\t\t\tptr = tbin->avail[i];\n\t\t\tassert(ptr != NULL);\n\t\t\tchunk = (arena_chunk_t *)CHUNK_ADDR2BASE(ptr);\n\t\t\tif (extent_node_arena_get(&chunk->node) ==\n\t\t\t    locked_arena) {\n\t\t\t\tarena_dalloc_large_junked_locked(locked_arena,\n\t\t\t\t    chunk, ptr);\n\t\t\t} else {\n\t\t\t\t/*\n\t\t\t\t * This object was allocated via a different\n\t\t\t\t * arena than the one that is currently locked.\n\t\t\t\t * Stash the object, so that it can be handled\n\t\t\t\t * in a future pass.\n\t\t\t\t */\n\t\t\t\ttbin->avail[ndeferred] = ptr;\n\t\t\t\tndeferred++;\n\t\t\t}\n\t\t}\n\t\tmalloc_mutex_unlock(&locked_arena->lock);\n\t\tif (config_prof && idump)\n\t\t\tprof_idump();\n\t}\n\tif (config_stats && !merged_stats) {\n\t\t/*\n\t\t * The flush loop didn't happen to flush to this thread's\n\t\t * arena, so the stats didn't get merged.  Manually do so now.\n\t\t */\n\t\tmalloc_mutex_lock(&arena->lock);\n\t\tarena->stats.nrequests_large += tbin->tstats.nrequests;\n\t\tarena->stats.lstats[binind - NBINS].nrequests +=\n\t\t    tbin->tstats.nrequests;\n\t\ttbin->tstats.nrequests = 0;\n\t\tmalloc_mutex_unlock(&arena->lock);\n\t}\n\n\tmemmove(tbin->avail, &tbin->avail[tbin->ncached - rem],\n\t    rem * sizeof(void *));\n\ttbin->ncached = rem;\n\tif ((int)tbin->ncached < tbin->low_water)\n\t\ttbin->low_water = tbin->ncached;\n}\n\nvoid\ntcache_arena_associate(tcache_t *tcache, arena_t *arena)\n{\n\n\tif (config_stats) {\n\t\t/* Link into list of extant tcaches. */\n\t\tmalloc_mutex_lock(&arena->lock);\n\t\tql_elm_new(tcache, link);\n\t\tql_tail_insert(&arena->tcache_ql, tcache, link);\n\t\tmalloc_mutex_unlock(&arena->lock);\n\t}\n}\n\nvoid\ntcache_arena_reassociate(tcache_t *tcache, arena_t *oldarena, arena_t *newarena)\n{\n\n\ttcache_arena_dissociate(tcache, oldarena);\n\ttcache_arena_associate(tcache, newarena);\n}\n\nvoid\ntcache_arena_dissociate(tcache_t *tcache, arena_t *arena)\n{\n\n\tif (config_stats) {\n\t\t/* Unlink from list of extant tcaches. */\n\t\tmalloc_mutex_lock(&arena->lock);\n\t\tif (config_debug) {\n\t\t\tbool in_ql = false;\n\t\t\ttcache_t *iter;\n\t\t\tql_foreach(iter, &arena->tcache_ql, link) {\n\t\t\t\tif (iter == tcache) {\n\t\t\t\t\tin_ql = true;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t\tassert(in_ql);\n\t\t}\n\t\tql_remove(&arena->tcache_ql, tcache, link);\n\t\ttcache_stats_merge(tcache, arena);\n\t\tmalloc_mutex_unlock(&arena->lock);\n\t}\n}\n\ntcache_t *\ntcache_get_hard(tsd_t *tsd)\n{\n\tarena_t *arena;\n\n\tif (!tcache_enabled_get()) {\n\t\tif (tsd_nominal(tsd))\n\t\t\ttcache_enabled_set(false); /* Memoize. */\n\t\treturn (NULL);\n\t}\n\tarena = arena_choose(tsd, NULL);\n\tif (unlikely(arena == NULL))\n\t\treturn (NULL);\n\treturn (tcache_create(tsd, arena));\n}\n\ntcache_t *\ntcache_create(tsd_t *tsd, arena_t *arena)\n{\n\ttcache_t *tcache;\n\tsize_t size, stack_offset;\n\tunsigned i;\n\n\tsize = offsetof(tcache_t, tbins) + (sizeof(tcache_bin_t) * nhbins);\n\t/* Naturally align the pointer stacks. */\n\tsize = PTR_CEILING(size);\n\tstack_offset = size;\n\tsize += stack_nelms * sizeof(void *);\n\t/* Avoid false cacheline sharing. */\n\tsize = sa2u(size, CACHELINE);\n\n\ttcache = ipallocztm(tsd, size, CACHELINE, true, false, true, a0get());\n\tif (tcache == NULL)\n\t\treturn (NULL);\n\n\ttcache_arena_associate(tcache, arena);\n\n\tassert((TCACHE_NSLOTS_SMALL_MAX & 1U) == 0);\n\tfor (i = 0; i < nhbins; i++) {\n\t\ttcache->tbins[i].lg_fill_div = 1;\n\t\ttcache->tbins[i].avail = (void **)((uintptr_t)tcache +\n\t\t    (uintptr_t)stack_offset);\n\t\tstack_offset += tcache_bin_info[i].ncached_max * sizeof(void *);\n\t}\n\n\treturn (tcache);\n}\n\nstatic void\ntcache_destroy(tsd_t *tsd, tcache_t *tcache)\n{\n\tarena_t *arena;\n\tunsigned i;\n\n\tarena = arena_choose(tsd, NULL);\n\ttcache_arena_dissociate(tcache, arena);\n\n\tfor (i = 0; i < NBINS; i++) {\n\t\ttcache_bin_t *tbin = &tcache->tbins[i];\n\t\ttcache_bin_flush_small(tsd, tcache, tbin, i, 0);\n\n\t\tif (config_stats && tbin->tstats.nrequests != 0) {\n\t\t\tarena_bin_t *bin = &arena->bins[i];\n\t\t\tmalloc_mutex_lock(&bin->lock);\n\t\t\tbin->stats.nrequests += tbin->tstats.nrequests;\n\t\t\tmalloc_mutex_unlock(&bin->lock);\n\t\t}\n\t}\n\n\tfor (; i < nhbins; i++) {\n\t\ttcache_bin_t *tbin = &tcache->tbins[i];\n\t\ttcache_bin_flush_large(tsd, tbin, i, 0, tcache);\n\n\t\tif (config_stats && tbin->tstats.nrequests != 0) {\n\t\t\tmalloc_mutex_lock(&arena->lock);\n\t\t\tarena->stats.nrequests_large += tbin->tstats.nrequests;\n\t\t\tarena->stats.lstats[i - NBINS].nrequests +=\n\t\t\t    tbin->tstats.nrequests;\n\t\t\tmalloc_mutex_unlock(&arena->lock);\n\t\t}\n\t}\n\n\tif (config_prof && tcache->prof_accumbytes > 0 &&\n\t    arena_prof_accum(arena, tcache->prof_accumbytes))\n\t\tprof_idump();\n\n\tidalloctm(tsd, tcache, false, true);\n}\n\nvoid\ntcache_cleanup(tsd_t *tsd)\n{\n\ttcache_t *tcache;\n\n\tif (!config_tcache)\n\t\treturn;\n\n\tif ((tcache = tsd_tcache_get(tsd)) != NULL) {\n\t\ttcache_destroy(tsd, tcache);\n\t\ttsd_tcache_set(tsd, NULL);\n\t}\n}\n\nvoid\ntcache_enabled_cleanup(tsd_t *tsd)\n{\n\n\t/* Do nothing. */\n}\n\n/* Caller must own arena->lock. */\nvoid\ntcache_stats_merge(tcache_t *tcache, arena_t *arena)\n{\n\tunsigned i;\n\n\tcassert(config_stats);\n\n\t/* Merge and reset tcache stats. */\n\tfor (i = 0; i < NBINS; i++) {\n\t\tarena_bin_t *bin = &arena->bins[i];\n\t\ttcache_bin_t *tbin = &tcache->tbins[i];\n\t\tmalloc_mutex_lock(&bin->lock);\n\t\tbin->stats.nrequests += tbin->tstats.nrequests;\n\t\tmalloc_mutex_unlock(&bin->lock);\n\t\ttbin->tstats.nrequests = 0;\n\t}\n\n\tfor (; i < nhbins; i++) {\n\t\tmalloc_large_stats_t *lstats = &arena->stats.lstats[i - NBINS];\n\t\ttcache_bin_t *tbin = &tcache->tbins[i];\n\t\tarena->stats.nrequests_large += tbin->tstats.nrequests;\n\t\tlstats->nrequests += tbin->tstats.nrequests;\n\t\ttbin->tstats.nrequests = 0;\n\t}\n}\n\nbool\ntcaches_create(tsd_t *tsd, unsigned *r_ind)\n{\n\ttcache_t *tcache;\n\ttcaches_t *elm;\n\n\tif (tcaches == NULL) {\n\t\ttcaches = base_alloc(sizeof(tcache_t *) *\n\t\t    (MALLOCX_TCACHE_MAX+1));\n\t\tif (tcaches == NULL)\n\t\t\treturn (true);\n\t}\n\n\tif (tcaches_avail == NULL && tcaches_past > MALLOCX_TCACHE_MAX)\n\t\treturn (true);\n\ttcache = tcache_create(tsd, a0get());\n\tif (tcache == NULL)\n\t\treturn (true);\n\n\tif (tcaches_avail != NULL) {\n\t\telm = tcaches_avail;\n\t\ttcaches_avail = tcaches_avail->next;\n\t\telm->tcache = tcache;\n\t\t*r_ind = elm - tcaches;\n\t} else {\n\t\telm = &tcaches[tcaches_past];\n\t\telm->tcache = tcache;\n\t\t*r_ind = tcaches_past;\n\t\ttcaches_past++;\n\t}\n\n\treturn (false);\n}\n\nstatic void\ntcaches_elm_flush(tsd_t *tsd, tcaches_t *elm)\n{\n\n\tif (elm->tcache == NULL)\n\t\treturn;\n\ttcache_destroy(tsd, elm->tcache);\n\telm->tcache = NULL;\n}\n\nvoid\ntcaches_flush(tsd_t *tsd, unsigned ind)\n{\n\n\ttcaches_elm_flush(tsd, &tcaches[ind]);\n}\n\nvoid\ntcaches_destroy(tsd_t *tsd, unsigned ind)\n{\n\ttcaches_t *elm = &tcaches[ind];\n\ttcaches_elm_flush(tsd, elm);\n\telm->next = tcaches_avail;\n\ttcaches_avail = elm;\n}\n\nbool\ntcache_boot(void)\n{\n\tunsigned i;\n\n\t/*\n\t * If necessary, clamp opt_lg_tcache_max, now that large_maxclass is\n\t * known.\n\t */\n\tif (opt_lg_tcache_max < 0 || (1U << opt_lg_tcache_max) < SMALL_MAXCLASS)\n\t\ttcache_maxclass = SMALL_MAXCLASS;\n\telse if ((1U << opt_lg_tcache_max) > large_maxclass)\n\t\ttcache_maxclass = large_maxclass;\n\telse\n\t\ttcache_maxclass = (1U << opt_lg_tcache_max);\n\n\tnhbins = size2index(tcache_maxclass) + 1;\n\n\t/* Initialize tcache_bin_info. */\n\ttcache_bin_info = (tcache_bin_info_t *)base_alloc(nhbins *\n\t    sizeof(tcache_bin_info_t));\n\tif (tcache_bin_info == NULL)\n\t\treturn (true);\n\tstack_nelms = 0;\n\tfor (i = 0; i < NBINS; i++) {\n\t\tif ((arena_bin_info[i].nregs << 1) <= TCACHE_NSLOTS_SMALL_MIN) {\n\t\t\ttcache_bin_info[i].ncached_max =\n\t\t\t    TCACHE_NSLOTS_SMALL_MIN;\n\t\t} else if ((arena_bin_info[i].nregs << 1) <=\n\t\t    TCACHE_NSLOTS_SMALL_MAX) {\n\t\t\ttcache_bin_info[i].ncached_max =\n\t\t\t    (arena_bin_info[i].nregs << 1);\n\t\t} else {\n\t\t\ttcache_bin_info[i].ncached_max =\n\t\t\t    TCACHE_NSLOTS_SMALL_MAX;\n\t\t}\n\t\tstack_nelms += tcache_bin_info[i].ncached_max;\n\t}\n\tfor (; i < nhbins; i++) {\n\t\ttcache_bin_info[i].ncached_max = TCACHE_NSLOTS_LARGE;\n\t\tstack_nelms += tcache_bin_info[i].ncached_max;\n\t}\n\n\treturn (false);\n}\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.8/deps/jemalloc/src/tsd.c",
    "content": "#define\tJEMALLOC_TSD_C_\n#include \"jemalloc/internal/jemalloc_internal.h\"\n\n/******************************************************************************/\n/* Data. */\n\nstatic unsigned ncleanups;\nstatic malloc_tsd_cleanup_t cleanups[MALLOC_TSD_CLEANUPS_MAX];\n\nmalloc_tsd_data(, , tsd_t, TSD_INITIALIZER)\n\n/******************************************************************************/\n\nvoid *\nmalloc_tsd_malloc(size_t size)\n{\n\n\treturn (a0malloc(CACHELINE_CEILING(size)));\n}\n\nvoid\nmalloc_tsd_dalloc(void *wrapper)\n{\n\n\ta0dalloc(wrapper);\n}\n\nvoid\nmalloc_tsd_no_cleanup(void *arg)\n{\n\n\tnot_reached();\n}\n\n#if defined(JEMALLOC_MALLOC_THREAD_CLEANUP) || defined(_WIN32)\n#ifndef _WIN32\nJEMALLOC_EXPORT\n#endif\nvoid\n_malloc_thread_cleanup(void)\n{\n\tbool pending[MALLOC_TSD_CLEANUPS_MAX], again;\n\tunsigned i;\n\n\tfor (i = 0; i < ncleanups; i++)\n\t\tpending[i] = true;\n\n\tdo {\n\t\tagain = false;\n\t\tfor (i = 0; i < ncleanups; i++) {\n\t\t\tif (pending[i]) {\n\t\t\t\tpending[i] = cleanups[i]();\n\t\t\t\tif (pending[i])\n\t\t\t\t\tagain = true;\n\t\t\t}\n\t\t}\n\t} while (again);\n}\n#endif\n\nvoid\nmalloc_tsd_cleanup_register(bool (*f)(void))\n{\n\n\tassert(ncleanups < MALLOC_TSD_CLEANUPS_MAX);\n\tcleanups[ncleanups] = f;\n\tncleanups++;\n}\n\nvoid\ntsd_cleanup(void *arg)\n{\n\ttsd_t *tsd = (tsd_t *)arg;\n\n\tswitch (tsd->state) {\n\tcase tsd_state_uninitialized:\n\t\t/* Do nothing. */\n\t\tbreak;\n\tcase tsd_state_nominal:\n#define O(n, t)\t\t\t\t\t\t\t\t\\\n\t\tn##_cleanup(tsd);\nMALLOC_TSD\n#undef O\n\t\ttsd->state = tsd_state_purgatory;\n\t\ttsd_set(tsd);\n\t\tbreak;\n\tcase tsd_state_purgatory:\n\t\t/*\n\t\t * The previous time this destructor was called, we set the\n\t\t * state to tsd_state_purgatory so that other destructors\n\t\t * wouldn't cause re-creation of the tsd.  This time, do\n\t\t * nothing, and do not request another callback.\n\t\t */\n\t\tbreak;\n\tcase tsd_state_reincarnated:\n\t\t/*\n\t\t * Another destructor deallocated memory after this destructor\n\t\t * was called.  Reset state to tsd_state_purgatory and request\n\t\t * another callback.\n\t\t */\n\t\ttsd->state = tsd_state_purgatory;\n\t\ttsd_set(tsd);\n\t\tbreak;\n\tdefault:\n\t\tnot_reached();\n\t}\n}\n\nbool\nmalloc_tsd_boot0(void)\n{\n\n\tncleanups = 0;\n\tif (tsd_boot0())\n\t\treturn (true);\n\t*tsd_arenas_cache_bypassp_get(tsd_fetch()) = true;\n\treturn (false);\n}\n\nvoid\nmalloc_tsd_boot1(void)\n{\n\n\ttsd_boot1();\n\t*tsd_arenas_cache_bypassp_get(tsd_fetch()) = false;\n}\n\n#ifdef _WIN32\nstatic BOOL WINAPI\n_tls_callback(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)\n{\n\n\tswitch (fdwReason) {\n#ifdef JEMALLOC_LAZY_LOCK\n\tcase DLL_THREAD_ATTACH:\n\t\tisthreaded = true;\n\t\tbreak;\n#endif\n\tcase DLL_THREAD_DETACH:\n\t\t_malloc_thread_cleanup();\n\t\tbreak;\n\tdefault:\n\t\tbreak;\n\t}\n\treturn (true);\n}\n\n#ifdef _MSC_VER\n#  ifdef _M_IX86\n#    pragma comment(linker, \"/INCLUDE:__tls_used\")\n#  else\n#    pragma comment(linker, \"/INCLUDE:_tls_used\")\n#  endif\n#  pragma section(\".CRT$XLY\",long,read)\n#endif\nJEMALLOC_SECTION(\".CRT$XLY\") JEMALLOC_ATTR(used)\nstatic BOOL\t(WINAPI *const tls_callback)(HINSTANCE hinstDLL,\n    DWORD fdwReason, LPVOID lpvReserved) = _tls_callback;\n#endif\n\n#if (!defined(JEMALLOC_MALLOC_THREAD_CLEANUP) && !defined(JEMALLOC_TLS) && \\\n    !defined(_WIN32))\nvoid *\ntsd_init_check_recursion(tsd_init_head_t *head, tsd_init_block_t *block)\n{\n\tpthread_t self = pthread_self();\n\ttsd_init_block_t *iter;\n\n\t/* Check whether this thread has already inserted into the list. */\n\tmalloc_mutex_lock(&head->lock);\n\tql_foreach(iter, &head->blocks, link) {\n\t\tif (iter->thread == self) {\n\t\t\tmalloc_mutex_unlock(&head->lock);\n\t\t\treturn (iter->data);\n\t\t}\n\t}\n\t/* Insert block into list. */\n\tql_elm_new(block, link);\n\tblock->thread = self;\n\tql_tail_insert(&head->blocks, block, link);\n\tmalloc_mutex_unlock(&head->lock);\n\treturn (NULL);\n}\n\nvoid\ntsd_init_finish(tsd_init_head_t *head, tsd_init_block_t *block)\n{\n\n\tmalloc_mutex_lock(&head->lock);\n\tql_remove(&head->blocks, block, link);\n\tmalloc_mutex_unlock(&head->lock);\n}\n#endif\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.8/deps/jemalloc/src/util.c",
    "content": "#define\tassert(e) do {\t\t\t\t\t\t\t\\\n\tif (config_debug && !(e)) {\t\t\t\t\t\\\n\t\tmalloc_write(\"<jemalloc>: Failed assertion\\n\");\t\t\\\n\t\tabort();\t\t\t\t\t\t\\\n\t}\t\t\t\t\t\t\t\t\\\n} while (0)\n\n#define\tnot_reached() do {\t\t\t\t\t\t\\\n\tif (config_debug) {\t\t\t\t\t\t\\\n\t\tmalloc_write(\"<jemalloc>: Unreachable code reached\\n\");\t\\\n\t\tabort();\t\t\t\t\t\t\\\n\t}\t\t\t\t\t\t\t\t\\\n} while (0)\n\n#define\tnot_implemented() do {\t\t\t\t\t\t\\\n\tif (config_debug) {\t\t\t\t\t\t\\\n\t\tmalloc_write(\"<jemalloc>: Not implemented\\n\");\t\t\\\n\t\tabort();\t\t\t\t\t\t\\\n\t}\t\t\t\t\t\t\t\t\\\n} while (0)\n\n#define\tJEMALLOC_UTIL_C_\n#include \"jemalloc/internal/jemalloc_internal.h\"\n\n/******************************************************************************/\n/* Function prototypes for non-inline static functions. */\n\nstatic void\twrtmessage(void *cbopaque, const char *s);\n#define\tU2S_BUFSIZE\t((1U << (LG_SIZEOF_INTMAX_T + 3)) + 1)\nstatic char\t*u2s(uintmax_t x, unsigned base, bool uppercase, char *s,\n    size_t *slen_p);\n#define\tD2S_BUFSIZE\t(1 + U2S_BUFSIZE)\nstatic char\t*d2s(intmax_t x, char sign, char *s, size_t *slen_p);\n#define\tO2S_BUFSIZE\t(1 + U2S_BUFSIZE)\nstatic char\t*o2s(uintmax_t x, bool alt_form, char *s, size_t *slen_p);\n#define\tX2S_BUFSIZE\t(2 + U2S_BUFSIZE)\nstatic char\t*x2s(uintmax_t x, bool alt_form, bool uppercase, char *s,\n    size_t *slen_p);\n\n/******************************************************************************/\n\n/* malloc_message() setup. */\nstatic void\nwrtmessage(void *cbopaque, const char *s)\n{\n\n#ifdef SYS_write\n\t/*\n\t * Use syscall(2) rather than write(2) when possible in order to avoid\n\t * the possibility of memory allocation within libc.  This is necessary\n\t * on FreeBSD; most operating systems do not have this problem though.\n\t */\n\tUNUSED int result = syscall(SYS_write, STDERR_FILENO, s, strlen(s));\n#else\n\tUNUSED int result = write(STDERR_FILENO, s, strlen(s));\n#endif\n}\n\nJEMALLOC_EXPORT void\t(*je_malloc_message)(void *, const char *s);\n\n/*\n * Wrapper around malloc_message() that avoids the need for\n * je_malloc_message(...) throughout the code.\n */\nvoid\nmalloc_write(const char *s)\n{\n\n\tif (je_malloc_message != NULL)\n\t\tje_malloc_message(NULL, s);\n\telse\n\t\twrtmessage(NULL, s);\n}\n\n/*\n * glibc provides a non-standard strerror_r() when _GNU_SOURCE is defined, so\n * provide a wrapper.\n */\nint\nbuferror(int err, char *buf, size_t buflen)\n{\n\n#ifdef _WIN32\n\tFormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM, NULL, err, 0,\n\t    (LPSTR)buf, buflen, NULL);\n\treturn (0);\n#elif defined(__GLIBC__) && defined(_GNU_SOURCE)\n\tchar *b = strerror_r(err, buf, buflen);\n\tif (b != buf) {\n\t\tstrncpy(buf, b, buflen);\n\t\tbuf[buflen-1] = '\\0';\n\t}\n\treturn (0);\n#else\n\treturn (strerror_r(err, buf, buflen));\n#endif\n}\n\nuintmax_t\nmalloc_strtoumax(const char *restrict nptr, char **restrict endptr, int base)\n{\n\tuintmax_t ret, digit;\n\tunsigned b;\n\tbool neg;\n\tconst char *p, *ns;\n\n\tp = nptr;\n\tif (base < 0 || base == 1 || base > 36) {\n\t\tns = p;\n\t\tset_errno(EINVAL);\n\t\tret = UINTMAX_MAX;\n\t\tgoto label_return;\n\t}\n\tb = base;\n\n\t/* Swallow leading whitespace and get sign, if any. */\n\tneg = false;\n\twhile (true) {\n\t\tswitch (*p) {\n\t\tcase '\\t': case '\\n': case '\\v': case '\\f': case '\\r': case ' ':\n\t\t\tp++;\n\t\t\tbreak;\n\t\tcase '-':\n\t\t\tneg = true;\n\t\t\t/* Fall through. */\n\t\tcase '+':\n\t\t\tp++;\n\t\t\t/* Fall through. */\n\t\tdefault:\n\t\t\tgoto label_prefix;\n\t\t}\n\t}\n\n\t/* Get prefix, if any. */\n\tlabel_prefix:\n\t/*\n\t * Note where the first non-whitespace/sign character is so that it is\n\t * possible to tell whether any digits are consumed (e.g., \"  0\" vs.\n\t * \"  -x\").\n\t */\n\tns = p;\n\tif (*p == '0') {\n\t\tswitch (p[1]) {\n\t\tcase '0': case '1': case '2': case '3': case '4': case '5':\n\t\tcase '6': case '7':\n\t\t\tif (b == 0)\n\t\t\t\tb = 8;\n\t\t\tif (b == 8)\n\t\t\t\tp++;\n\t\t\tbreak;\n\t\tcase 'X': case 'x':\n\t\t\tswitch (p[2]) {\n\t\t\tcase '0': case '1': case '2': case '3': case '4':\n\t\t\tcase '5': case '6': case '7': case '8': case '9':\n\t\t\tcase 'A': case 'B': case 'C': case 'D': case 'E':\n\t\t\tcase 'F':\n\t\t\tcase 'a': case 'b': case 'c': case 'd': case 'e':\n\t\t\tcase 'f':\n\t\t\t\tif (b == 0)\n\t\t\t\t\tb = 16;\n\t\t\t\tif (b == 16)\n\t\t\t\t\tp += 2;\n\t\t\t\tbreak;\n\t\t\tdefault:\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tbreak;\n\t\tdefault:\n\t\t\tp++;\n\t\t\tret = 0;\n\t\t\tgoto label_return;\n\t\t}\n\t}\n\tif (b == 0)\n\t\tb = 10;\n\n\t/* Convert. */\n\tret = 0;\n\twhile ((*p >= '0' && *p <= '9' && (digit = *p - '0') < b)\n\t    || (*p >= 'A' && *p <= 'Z' && (digit = 10 + *p - 'A') < b)\n\t    || (*p >= 'a' && *p <= 'z' && (digit = 10 + *p - 'a') < b)) {\n\t\tuintmax_t pret = ret;\n\t\tret *= b;\n\t\tret += digit;\n\t\tif (ret < pret) {\n\t\t\t/* Overflow. */\n\t\t\tset_errno(ERANGE);\n\t\t\tret = UINTMAX_MAX;\n\t\t\tgoto label_return;\n\t\t}\n\t\tp++;\n\t}\n\tif (neg)\n\t\tret = -ret;\n\n\tif (p == ns) {\n\t\t/* No conversion performed. */\n\t\tset_errno(EINVAL);\n\t\tret = UINTMAX_MAX;\n\t\tgoto label_return;\n\t}\n\nlabel_return:\n\tif (endptr != NULL) {\n\t\tif (p == ns) {\n\t\t\t/* No characters were converted. */\n\t\t\t*endptr = (char *)nptr;\n\t\t} else\n\t\t\t*endptr = (char *)p;\n\t}\n\treturn (ret);\n}\n\nstatic char *\nu2s(uintmax_t x, unsigned base, bool uppercase, char *s, size_t *slen_p)\n{\n\tunsigned i;\n\n\ti = U2S_BUFSIZE - 1;\n\ts[i] = '\\0';\n\tswitch (base) {\n\tcase 10:\n\t\tdo {\n\t\t\ti--;\n\t\t\ts[i] = \"0123456789\"[x % (uint64_t)10];\n\t\t\tx /= (uint64_t)10;\n\t\t} while (x > 0);\n\t\tbreak;\n\tcase 16: {\n\t\tconst char *digits = (uppercase)\n\t\t    ? \"0123456789ABCDEF\"\n\t\t    : \"0123456789abcdef\";\n\n\t\tdo {\n\t\t\ti--;\n\t\t\ts[i] = digits[x & 0xf];\n\t\t\tx >>= 4;\n\t\t} while (x > 0);\n\t\tbreak;\n\t} default: {\n\t\tconst char *digits = (uppercase)\n\t\t    ? \"0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ\"\n\t\t    : \"0123456789abcdefghijklmnopqrstuvwxyz\";\n\n\t\tassert(base >= 2 && base <= 36);\n\t\tdo {\n\t\t\ti--;\n\t\t\ts[i] = digits[x % (uint64_t)base];\n\t\t\tx /= (uint64_t)base;\n\t\t} while (x > 0);\n\t}}\n\n\t*slen_p = U2S_BUFSIZE - 1 - i;\n\treturn (&s[i]);\n}\n\nstatic char *\nd2s(intmax_t x, char sign, char *s, size_t *slen_p)\n{\n\tbool neg;\n\n\tif ((neg = (x < 0)))\n\t\tx = -x;\n\ts = u2s(x, 10, false, s, slen_p);\n\tif (neg)\n\t\tsign = '-';\n\tswitch (sign) {\n\tcase '-':\n\t\tif (!neg)\n\t\t\tbreak;\n\t\t/* Fall through. */\n\tcase ' ':\n\tcase '+':\n\t\ts--;\n\t\t(*slen_p)++;\n\t\t*s = sign;\n\t\tbreak;\n\tdefault: not_reached();\n\t}\n\treturn (s);\n}\n\nstatic char *\no2s(uintmax_t x, bool alt_form, char *s, size_t *slen_p)\n{\n\n\ts = u2s(x, 8, false, s, slen_p);\n\tif (alt_form && *s != '0') {\n\t\ts--;\n\t\t(*slen_p)++;\n\t\t*s = '0';\n\t}\n\treturn (s);\n}\n\nstatic char *\nx2s(uintmax_t x, bool alt_form, bool uppercase, char *s, size_t *slen_p)\n{\n\n\ts = u2s(x, 16, uppercase, s, slen_p);\n\tif (alt_form) {\n\t\ts -= 2;\n\t\t(*slen_p) += 2;\n\t\tmemcpy(s, uppercase ? \"0X\" : \"0x\", 2);\n\t}\n\treturn (s);\n}\n\nint\nmalloc_vsnprintf(char *str, size_t size, const char *format, va_list ap)\n{\n\tint ret;\n\tsize_t i;\n\tconst char *f;\n\n#define\tAPPEND_C(c) do {\t\t\t\t\t\t\\\n\tif (i < size)\t\t\t\t\t\t\t\\\n\t\tstr[i] = (c);\t\t\t\t\t\t\\\n\ti++;\t\t\t\t\t\t\t\t\\\n} while (0)\n#define\tAPPEND_S(s, slen) do {\t\t\t\t\t\t\\\n\tif (i < size) {\t\t\t\t\t\t\t\\\n\t\tsize_t cpylen = (slen <= size - i) ? slen : size - i;\t\\\n\t\tmemcpy(&str[i], s, cpylen);\t\t\t\t\\\n\t}\t\t\t\t\t\t\t\t\\\n\ti += slen;\t\t\t\t\t\t\t\\\n} while (0)\n#define\tAPPEND_PADDED_S(s, slen, width, left_justify) do {\t\t\\\n\t/* Left padding. */\t\t\t\t\t\t\\\n\tsize_t pad_len = (width == -1) ? 0 : ((slen < (size_t)width) ?\t\\\n\t    (size_t)width - slen : 0);\t\t\t\t\t\\\n\tif (!left_justify && pad_len != 0) {\t\t\t\t\\\n\t\tsize_t j;\t\t\t\t\t\t\\\n\t\tfor (j = 0; j < pad_len; j++)\t\t\t\t\\\n\t\t\tAPPEND_C(' ');\t\t\t\t\t\\\n\t}\t\t\t\t\t\t\t\t\\\n\t/* Value. */\t\t\t\t\t\t\t\\\n\tAPPEND_S(s, slen);\t\t\t\t\t\t\\\n\t/* Right padding. */\t\t\t\t\t\t\\\n\tif (left_justify && pad_len != 0) {\t\t\t\t\\\n\t\tsize_t j;\t\t\t\t\t\t\\\n\t\tfor (j = 0; j < pad_len; j++)\t\t\t\t\\\n\t\t\tAPPEND_C(' ');\t\t\t\t\t\\\n\t}\t\t\t\t\t\t\t\t\\\n} while (0)\n#define\tGET_ARG_NUMERIC(val, len) do {\t\t\t\t\t\\\n\tswitch (len) {\t\t\t\t\t\t\t\\\n\tcase '?':\t\t\t\t\t\t\t\\\n\t\tval = va_arg(ap, int);\t\t\t\t\t\\\n\t\tbreak;\t\t\t\t\t\t\t\\\n\tcase '?' | 0x80:\t\t\t\t\t\t\\\n\t\tval = va_arg(ap, unsigned int);\t\t\t\t\\\n\t\tbreak;\t\t\t\t\t\t\t\\\n\tcase 'l':\t\t\t\t\t\t\t\\\n\t\tval = va_arg(ap, long);\t\t\t\t\t\\\n\t\tbreak;\t\t\t\t\t\t\t\\\n\tcase 'l' | 0x80:\t\t\t\t\t\t\\\n\t\tval = va_arg(ap, unsigned long);\t\t\t\\\n\t\tbreak;\t\t\t\t\t\t\t\\\n\tcase 'q':\t\t\t\t\t\t\t\\\n\t\tval = va_arg(ap, long long);\t\t\t\t\\\n\t\tbreak;\t\t\t\t\t\t\t\\\n\tcase 'q' | 0x80:\t\t\t\t\t\t\\\n\t\tval = va_arg(ap, unsigned long long);\t\t\t\\\n\t\tbreak;\t\t\t\t\t\t\t\\\n\tcase 'j':\t\t\t\t\t\t\t\\\n\t\tval = va_arg(ap, intmax_t);\t\t\t\t\\\n\t\tbreak;\t\t\t\t\t\t\t\\\n\tcase 'j' | 0x80:\t\t\t\t\t\t\\\n\t\tval = va_arg(ap, uintmax_t);\t\t\t\t\\\n\t\tbreak;\t\t\t\t\t\t\t\\\n\tcase 't':\t\t\t\t\t\t\t\\\n\t\tval = va_arg(ap, ptrdiff_t);\t\t\t\t\\\n\t\tbreak;\t\t\t\t\t\t\t\\\n\tcase 'z':\t\t\t\t\t\t\t\\\n\t\tval = va_arg(ap, ssize_t);\t\t\t\t\\\n\t\tbreak;\t\t\t\t\t\t\t\\\n\tcase 'z' | 0x80:\t\t\t\t\t\t\\\n\t\tval = va_arg(ap, size_t);\t\t\t\t\\\n\t\tbreak;\t\t\t\t\t\t\t\\\n\tcase 'p': /* Synthetic; used for %p. */\t\t\t\t\\\n\t\tval = va_arg(ap, uintptr_t);\t\t\t\t\\\n\t\tbreak;\t\t\t\t\t\t\t\\\n\tdefault:\t\t\t\t\t\t\t\\\n\t\tnot_reached();\t\t\t\t\t\t\\\n\t\tval = 0;\t\t\t\t\t\t\\\n\t}\t\t\t\t\t\t\t\t\\\n} while (0)\n\n\ti = 0;\n\tf = format;\n\twhile (true) {\n\t\tswitch (*f) {\n\t\tcase '\\0': goto label_out;\n\t\tcase '%': {\n\t\t\tbool alt_form = false;\n\t\t\tbool left_justify = false;\n\t\t\tbool plus_space = false;\n\t\t\tbool plus_plus = false;\n\t\t\tint prec = -1;\n\t\t\tint width = -1;\n\t\t\tunsigned char len = '?';\n\n\t\t\tf++;\n\t\t\t/* Flags. */\n\t\t\twhile (true) {\n\t\t\t\tswitch (*f) {\n\t\t\t\tcase '#':\n\t\t\t\t\tassert(!alt_form);\n\t\t\t\t\talt_form = true;\n\t\t\t\t\tbreak;\n\t\t\t\tcase '-':\n\t\t\t\t\tassert(!left_justify);\n\t\t\t\t\tleft_justify = true;\n\t\t\t\t\tbreak;\n\t\t\t\tcase ' ':\n\t\t\t\t\tassert(!plus_space);\n\t\t\t\t\tplus_space = true;\n\t\t\t\t\tbreak;\n\t\t\t\tcase '+':\n\t\t\t\t\tassert(!plus_plus);\n\t\t\t\t\tplus_plus = true;\n\t\t\t\t\tbreak;\n\t\t\t\tdefault: goto label_width;\n\t\t\t\t}\n\t\t\t\tf++;\n\t\t\t}\n\t\t\t/* Width. */\n\t\t\tlabel_width:\n\t\t\tswitch (*f) {\n\t\t\tcase '*':\n\t\t\t\twidth = va_arg(ap, int);\n\t\t\t\tf++;\n\t\t\t\tif (width < 0) {\n\t\t\t\t\tleft_justify = true;\n\t\t\t\t\twidth = -width;\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\tcase '0': case '1': case '2': case '3': case '4':\n\t\t\tcase '5': case '6': case '7': case '8': case '9': {\n\t\t\t\tuintmax_t uwidth;\n\t\t\t\tset_errno(0);\n\t\t\t\tuwidth = malloc_strtoumax(f, (char **)&f, 10);\n\t\t\t\tassert(uwidth != UINTMAX_MAX || get_errno() !=\n\t\t\t\t    ERANGE);\n\t\t\t\twidth = (int)uwidth;\n\t\t\t\tbreak;\n\t\t\t} default:\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\t/* Width/precision separator. */\n\t\t\tif (*f == '.')\n\t\t\t\tf++;\n\t\t\telse\n\t\t\t\tgoto label_length;\n\t\t\t/* Precision. */\n\t\t\tswitch (*f) {\n\t\t\tcase '*':\n\t\t\t\tprec = va_arg(ap, int);\n\t\t\t\tf++;\n\t\t\t\tbreak;\n\t\t\tcase '0': case '1': case '2': case '3': case '4':\n\t\t\tcase '5': case '6': case '7': case '8': case '9': {\n\t\t\t\tuintmax_t uprec;\n\t\t\t\tset_errno(0);\n\t\t\t\tuprec = malloc_strtoumax(f, (char **)&f, 10);\n\t\t\t\tassert(uprec != UINTMAX_MAX || get_errno() !=\n\t\t\t\t    ERANGE);\n\t\t\t\tprec = (int)uprec;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tdefault: break;\n\t\t\t}\n\t\t\t/* Length. */\n\t\t\tlabel_length:\n\t\t\tswitch (*f) {\n\t\t\tcase 'l':\n\t\t\t\tf++;\n\t\t\t\tif (*f == 'l') {\n\t\t\t\t\tlen = 'q';\n\t\t\t\t\tf++;\n\t\t\t\t} else\n\t\t\t\t\tlen = 'l';\n\t\t\t\tbreak;\n\t\t\tcase 'q': case 'j': case 't': case 'z':\n\t\t\t\tlen = *f;\n\t\t\t\tf++;\n\t\t\t\tbreak;\n\t\t\tdefault: break;\n\t\t\t}\n\t\t\t/* Conversion specifier. */\n\t\t\tswitch (*f) {\n\t\t\t\tchar *s;\n\t\t\t\tsize_t slen;\n\t\t\tcase '%':\n\t\t\t\t/* %% */\n\t\t\t\tAPPEND_C(*f);\n\t\t\t\tf++;\n\t\t\t\tbreak;\n\t\t\tcase 'd': case 'i': {\n\t\t\t\tintmax_t val JEMALLOC_CC_SILENCE_INIT(0);\n\t\t\t\tchar buf[D2S_BUFSIZE];\n\n\t\t\t\tGET_ARG_NUMERIC(val, len);\n\t\t\t\ts = d2s(val, (plus_plus ? '+' : (plus_space ?\n\t\t\t\t    ' ' : '-')), buf, &slen);\n\t\t\t\tAPPEND_PADDED_S(s, slen, width, left_justify);\n\t\t\t\tf++;\n\t\t\t\tbreak;\n\t\t\t} case 'o': {\n\t\t\t\tuintmax_t val JEMALLOC_CC_SILENCE_INIT(0);\n\t\t\t\tchar buf[O2S_BUFSIZE];\n\n\t\t\t\tGET_ARG_NUMERIC(val, len | 0x80);\n\t\t\t\ts = o2s(val, alt_form, buf, &slen);\n\t\t\t\tAPPEND_PADDED_S(s, slen, width, left_justify);\n\t\t\t\tf++;\n\t\t\t\tbreak;\n\t\t\t} case 'u': {\n\t\t\t\tuintmax_t val JEMALLOC_CC_SILENCE_INIT(0);\n\t\t\t\tchar buf[U2S_BUFSIZE];\n\n\t\t\t\tGET_ARG_NUMERIC(val, len | 0x80);\n\t\t\t\ts = u2s(val, 10, false, buf, &slen);\n\t\t\t\tAPPEND_PADDED_S(s, slen, width, left_justify);\n\t\t\t\tf++;\n\t\t\t\tbreak;\n\t\t\t} case 'x': case 'X': {\n\t\t\t\tuintmax_t val JEMALLOC_CC_SILENCE_INIT(0);\n\t\t\t\tchar buf[X2S_BUFSIZE];\n\n\t\t\t\tGET_ARG_NUMERIC(val, len | 0x80);\n\t\t\t\ts = x2s(val, alt_form, *f == 'X', buf, &slen);\n\t\t\t\tAPPEND_PADDED_S(s, slen, width, left_justify);\n\t\t\t\tf++;\n\t\t\t\tbreak;\n\t\t\t} case 'c': {\n\t\t\t\tunsigned char val;\n\t\t\t\tchar buf[2];\n\n\t\t\t\tassert(len == '?' || len == 'l');\n\t\t\t\tassert_not_implemented(len != 'l');\n\t\t\t\tval = va_arg(ap, int);\n\t\t\t\tbuf[0] = val;\n\t\t\t\tbuf[1] = '\\0';\n\t\t\t\tAPPEND_PADDED_S(buf, 1, width, left_justify);\n\t\t\t\tf++;\n\t\t\t\tbreak;\n\t\t\t} case 's':\n\t\t\t\tassert(len == '?' || len == 'l');\n\t\t\t\tassert_not_implemented(len != 'l');\n\t\t\t\ts = va_arg(ap, char *);\n\t\t\t\tslen = (prec < 0) ? strlen(s) : (size_t)prec;\n\t\t\t\tAPPEND_PADDED_S(s, slen, width, left_justify);\n\t\t\t\tf++;\n\t\t\t\tbreak;\n\t\t\tcase 'p': {\n\t\t\t\tuintmax_t val;\n\t\t\t\tchar buf[X2S_BUFSIZE];\n\n\t\t\t\tGET_ARG_NUMERIC(val, 'p');\n\t\t\t\ts = x2s(val, true, false, buf, &slen);\n\t\t\t\tAPPEND_PADDED_S(s, slen, width, left_justify);\n\t\t\t\tf++;\n\t\t\t\tbreak;\n\t\t\t} default: not_reached();\n\t\t\t}\n\t\t\tbreak;\n\t\t} default: {\n\t\t\tAPPEND_C(*f);\n\t\t\tf++;\n\t\t\tbreak;\n\t\t}}\n\t}\n\tlabel_out:\n\tif (i < size)\n\t\tstr[i] = '\\0';\n\telse\n\t\tstr[size - 1] = '\\0';\n\tret = i;\n\n#undef APPEND_C\n#undef APPEND_S\n#undef APPEND_PADDED_S\n#undef GET_ARG_NUMERIC\n\treturn (ret);\n}\n\nJEMALLOC_FORMAT_PRINTF(3, 4)\nint\nmalloc_snprintf(char *str, size_t size, const char *format, ...)\n{\n\tint ret;\n\tva_list ap;\n\n\tva_start(ap, format);\n\tret = malloc_vsnprintf(str, size, format, ap);\n\tva_end(ap);\n\n\treturn (ret);\n}\n\nvoid\nmalloc_vcprintf(void (*write_cb)(void *, const char *), void *cbopaque,\n    const char *format, va_list ap)\n{\n\tchar buf[MALLOC_PRINTF_BUFSIZE];\n\n\tif (write_cb == NULL) {\n\t\t/*\n\t\t * The caller did not provide an alternate write_cb callback\n\t\t * function, so use the default one.  malloc_write() is an\n\t\t * inline function, so use malloc_message() directly here.\n\t\t */\n\t\twrite_cb = (je_malloc_message != NULL) ? je_malloc_message :\n\t\t    wrtmessage;\n\t\tcbopaque = NULL;\n\t}\n\n\tmalloc_vsnprintf(buf, sizeof(buf), format, ap);\n\twrite_cb(cbopaque, buf);\n}\n\n/*\n * Print to a callback function in such a way as to (hopefully) avoid memory\n * allocation.\n */\nJEMALLOC_FORMAT_PRINTF(3, 4)\nvoid\nmalloc_cprintf(void (*write_cb)(void *, const char *), void *cbopaque,\n    const char *format, ...)\n{\n\tva_list ap;\n\n\tva_start(ap, format);\n\tmalloc_vcprintf(write_cb, cbopaque, format, ap);\n\tva_end(ap);\n}\n\n/* Print to stderr in such a way as to avoid memory allocation. */\nJEMALLOC_FORMAT_PRINTF(1, 2)\nvoid\nmalloc_printf(const char *format, ...)\n{\n\tva_list ap;\n\n\tva_start(ap, format);\n\tmalloc_vcprintf(NULL, NULL, format, ap);\n\tva_end(ap);\n}\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.8/deps/jemalloc/src/valgrind.c",
    "content": "#include \"jemalloc/internal/jemalloc_internal.h\"\n#ifndef JEMALLOC_VALGRIND\n#  error \"This source file is for Valgrind integration.\"\n#endif\n\n#include <valgrind/memcheck.h>\n\nvoid\nvalgrind_make_mem_noaccess(void *ptr, size_t usize)\n{\n\n\tVALGRIND_MAKE_MEM_NOACCESS(ptr, usize);\n}\n\nvoid\nvalgrind_make_mem_undefined(void *ptr, size_t usize)\n{\n\n\tVALGRIND_MAKE_MEM_UNDEFINED(ptr, usize);\n}\n\nvoid\nvalgrind_make_mem_defined(void *ptr, size_t usize)\n{\n\n\tVALGRIND_MAKE_MEM_DEFINED(ptr, usize);\n}\n\nvoid\nvalgrind_freelike_block(void *ptr, size_t usize)\n{\n\n\tVALGRIND_FREELIKE_BLOCK(ptr, usize);\n}\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.8/deps/jemalloc/src/zone.c",
    "content": "#include \"jemalloc/internal/jemalloc_internal.h\"\n#ifndef JEMALLOC_ZONE\n#  error \"This source file is for zones on Darwin (OS X).\"\n#endif\n\n/*\n * The malloc_default_purgeable_zone function is only available on >= 10.6.\n * We need to check whether it is present at runtime, thus the weak_import.\n */\nextern malloc_zone_t *malloc_default_purgeable_zone(void)\nJEMALLOC_ATTR(weak_import);\n\n/******************************************************************************/\n/* Data. */\n\nstatic malloc_zone_t zone;\nstatic struct malloc_introspection_t zone_introspect;\n\n/******************************************************************************/\n/* Function prototypes for non-inline static functions. */\n\nstatic size_t\tzone_size(malloc_zone_t *zone, void *ptr);\nstatic void\t*zone_malloc(malloc_zone_t *zone, size_t size);\nstatic void\t*zone_calloc(malloc_zone_t *zone, size_t num, size_t size);\nstatic void\t*zone_valloc(malloc_zone_t *zone, size_t size);\nstatic void\tzone_free(malloc_zone_t *zone, void *ptr);\nstatic void\t*zone_realloc(malloc_zone_t *zone, void *ptr, size_t size);\n#if (JEMALLOC_ZONE_VERSION >= 5)\nstatic void\t*zone_memalign(malloc_zone_t *zone, size_t alignment,\n#endif\n#if (JEMALLOC_ZONE_VERSION >= 6)\n    size_t size);\nstatic void\tzone_free_definite_size(malloc_zone_t *zone, void *ptr,\n    size_t size);\n#endif\nstatic void\t*zone_destroy(malloc_zone_t *zone);\nstatic size_t\tzone_good_size(malloc_zone_t *zone, size_t size);\nstatic void\tzone_force_lock(malloc_zone_t *zone);\nstatic void\tzone_force_unlock(malloc_zone_t *zone);\n\n/******************************************************************************/\n/*\n * Functions.\n */\n\nstatic size_t\nzone_size(malloc_zone_t *zone, void *ptr)\n{\n\n\t/*\n\t * There appear to be places within Darwin (such as setenv(3)) that\n\t * cause calls to this function with pointers that *no* zone owns.  If\n\t * we knew that all pointers were owned by *some* zone, we could split\n\t * our zone into two parts, and use one as the default allocator and\n\t * the other as the default deallocator/reallocator.  Since that will\n\t * not work in practice, we must check all pointers to assure that they\n\t * reside within a mapped chunk before determining size.\n\t */\n\treturn (ivsalloc(ptr, config_prof));\n}\n\nstatic void *\nzone_malloc(malloc_zone_t *zone, size_t size)\n{\n\n\treturn (je_malloc(size));\n}\n\nstatic void *\nzone_calloc(malloc_zone_t *zone, size_t num, size_t size)\n{\n\n\treturn (je_calloc(num, size));\n}\n\nstatic void *\nzone_valloc(malloc_zone_t *zone, size_t size)\n{\n\tvoid *ret = NULL; /* Assignment avoids useless compiler warning. */\n\n\tje_posix_memalign(&ret, PAGE, size);\n\n\treturn (ret);\n}\n\nstatic void\nzone_free(malloc_zone_t *zone, void *ptr)\n{\n\n\tif (ivsalloc(ptr, config_prof) != 0) {\n\t\tje_free(ptr);\n\t\treturn;\n\t}\n\n\tfree(ptr);\n}\n\nstatic void *\nzone_realloc(malloc_zone_t *zone, void *ptr, size_t size)\n{\n\n\tif (ivsalloc(ptr, config_prof) != 0)\n\t\treturn (je_realloc(ptr, size));\n\n\treturn (realloc(ptr, size));\n}\n\n#if (JEMALLOC_ZONE_VERSION >= 5)\nstatic void *\nzone_memalign(malloc_zone_t *zone, size_t alignment, size_t size)\n{\n\tvoid *ret = NULL; /* Assignment avoids useless compiler warning. */\n\n\tje_posix_memalign(&ret, alignment, size);\n\n\treturn (ret);\n}\n#endif\n\n#if (JEMALLOC_ZONE_VERSION >= 6)\nstatic void\nzone_free_definite_size(malloc_zone_t *zone, void *ptr, size_t size)\n{\n\n\tif (ivsalloc(ptr, config_prof) != 0) {\n\t\tassert(ivsalloc(ptr, config_prof) == size);\n\t\tje_free(ptr);\n\t\treturn;\n\t}\n\n\tfree(ptr);\n}\n#endif\n\nstatic void *\nzone_destroy(malloc_zone_t *zone)\n{\n\n\t/* This function should never be called. */\n\tnot_reached();\n\treturn (NULL);\n}\n\nstatic size_t\nzone_good_size(malloc_zone_t *zone, size_t size)\n{\n\n\tif (size == 0)\n\t\tsize = 1;\n\treturn (s2u(size));\n}\n\nstatic void\nzone_force_lock(malloc_zone_t *zone)\n{\n\n\tif (isthreaded)\n\t\tjemalloc_prefork();\n}\n\nstatic void\nzone_force_unlock(malloc_zone_t *zone)\n{\n\n\tif (isthreaded)\n\t\tjemalloc_postfork_parent();\n}\n\nJEMALLOC_ATTR(constructor)\nvoid\nregister_zone(void)\n{\n\n\t/*\n\t * If something else replaced the system default zone allocator, don't\n\t * register jemalloc's.\n\t */\n\tmalloc_zone_t *default_zone = malloc_default_zone();\n\tmalloc_zone_t *purgeable_zone = NULL;\n\tif (!default_zone->zone_name ||\n\t    strcmp(default_zone->zone_name, \"DefaultMallocZone\") != 0) {\n\t\treturn;\n\t}\n\n\tzone.size = (void *)zone_size;\n\tzone.malloc = (void *)zone_malloc;\n\tzone.calloc = (void *)zone_calloc;\n\tzone.valloc = (void *)zone_valloc;\n\tzone.free = (void *)zone_free;\n\tzone.realloc = (void *)zone_realloc;\n\tzone.destroy = (void *)zone_destroy;\n\tzone.zone_name = \"jemalloc_zone\";\n\tzone.batch_malloc = NULL;\n\tzone.batch_free = NULL;\n\tzone.introspect = &zone_introspect;\n\tzone.version = JEMALLOC_ZONE_VERSION;\n#if (JEMALLOC_ZONE_VERSION >= 5)\n\tzone.memalign = zone_memalign;\n#endif\n#if (JEMALLOC_ZONE_VERSION >= 6)\n\tzone.free_definite_size = zone_free_definite_size;\n#endif\n#if (JEMALLOC_ZONE_VERSION >= 8)\n\tzone.pressure_relief = NULL;\n#endif\n\n\tzone_introspect.enumerator = NULL;\n\tzone_introspect.good_size = (void *)zone_good_size;\n\tzone_introspect.check = NULL;\n\tzone_introspect.print = NULL;\n\tzone_introspect.log = NULL;\n\tzone_introspect.force_lock = (void *)zone_force_lock;\n\tzone_introspect.force_unlock = (void *)zone_force_unlock;\n\tzone_introspect.statistics = NULL;\n#if (JEMALLOC_ZONE_VERSION >= 6)\n\tzone_introspect.zone_locked = NULL;\n#endif\n#if (JEMALLOC_ZONE_VERSION >= 7)\n\tzone_introspect.enable_discharge_checking = NULL;\n\tzone_introspect.disable_discharge_checking = NULL;\n\tzone_introspect.discharge = NULL;\n#ifdef __BLOCKS__\n\tzone_introspect.enumerate_discharged_pointers = NULL;\n#else\n\tzone_introspect.enumerate_unavailable_without_blocks = NULL;\n#endif\n#endif\n\n\t/*\n\t * The default purgeable zone is created lazily by OSX's libc.  It uses\n\t * the default zone when it is created for \"small\" allocations\n\t * (< 15 KiB), but assumes the default zone is a scalable_zone.  This\n\t * obviously fails when the default zone is the jemalloc zone, so\n\t * malloc_default_purgeable_zone is called beforehand so that the\n\t * default purgeable zone is created when the default zone is still\n\t * a scalable_zone.  As purgeable zones only exist on >= 10.6, we need\n\t * to check for the existence of malloc_default_purgeable_zone() at\n\t * run time.\n\t */\n\tif (malloc_default_purgeable_zone != NULL)\n\t\tpurgeable_zone = malloc_default_purgeable_zone();\n\n\t/* Register the custom zone.  At this point it won't be the default. */\n\tmalloc_zone_register(&zone);\n\n\tdo {\n\t\tdefault_zone = malloc_default_zone();\n\t\t/*\n\t\t * Unregister and reregister the default zone.  On OSX >= 10.6,\n\t\t * unregistering takes the last registered zone and places it\n\t\t * at the location of the specified zone.  Unregistering the\n\t\t * default zone thus makes the last registered one the default.\n\t\t * On OSX < 10.6, unregistering shifts all registered zones.\n\t\t * The first registered zone then becomes the default.\n\t\t */\n\t\tmalloc_zone_unregister(default_zone);\n\t\tmalloc_zone_register(default_zone);\n\t\t/*\n\t\t * On OSX 10.6, having the default purgeable zone appear before\n\t\t * the default zone makes some things crash because it thinks it\n\t\t * owns the default zone allocated pointers.  We thus\n\t\t * unregister/re-register it in order to ensure it's always\n\t\t * after the default zone.  On OSX < 10.6, there is no purgeable\n\t\t * zone, so this does nothing.  On OSX >= 10.6, unregistering\n\t\t * replaces the purgeable zone with the last registered zone\n\t\t * above, i.e. the default zone.  Registering it again then puts\n\t\t * it at the end, obviously after the default zone.\n\t\t */\n\t\tif (purgeable_zone) {\n\t\t\tmalloc_zone_unregister(purgeable_zone);\n\t\t\tmalloc_zone_register(purgeable_zone);\n\t\t}\n\t} while (malloc_default_zone() != &zone);\n}\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.8/deps/jemalloc/test/include/test/SFMT-alti.h",
    "content": "/*\n * This file derives from SFMT 1.3.3\n * (http://www.math.sci.hiroshima-u.ac.jp/~m-mat/MT/SFMT/index.html), which was\n * released under the terms of the following license:\n *\n *   Copyright (c) 2006,2007 Mutsuo Saito, Makoto Matsumoto and Hiroshima\n *   University. All rights reserved.\n *\n *   Redistribution and use in source and binary forms, with or without\n *   modification, are permitted provided that the following conditions are\n *   met:\n *\n *       * Redistributions of source code must retain the above copyright\n *         notice, this list of conditions and the following disclaimer.\n *       * Redistributions in binary form must reproduce the above\n *         copyright notice, this list of conditions and the following\n *         disclaimer in the documentation and/or other materials provided\n *         with the distribution.\n *       * Neither the name of the Hiroshima University nor the names of\n *         its contributors may be used to endorse or promote products\n *         derived from this software without specific prior written\n *         permission.\n *\n *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n *   \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\n *   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\n *   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\n *   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n *   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\n *   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n *   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n *   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n *   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n *   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n/** \n * @file SFMT-alti.h \n *\n * @brief SIMD oriented Fast Mersenne Twister(SFMT)\n * pseudorandom number generator\n *\n * @author Mutsuo Saito (Hiroshima University)\n * @author Makoto Matsumoto (Hiroshima University)\n *\n * Copyright (C) 2007 Mutsuo Saito, Makoto Matsumoto and Hiroshima\n * University. All rights reserved.\n *\n * The new BSD License is applied to this software.\n * see LICENSE.txt\n */\n\n#ifndef SFMT_ALTI_H\n#define SFMT_ALTI_H\n\n/**\n * This function represents the recursion formula in AltiVec and BIG ENDIAN.\n * @param a a 128-bit part of the interal state array\n * @param b a 128-bit part of the interal state array\n * @param c a 128-bit part of the interal state array\n * @param d a 128-bit part of the interal state array\n * @return output\n */\nJEMALLOC_ALWAYS_INLINE\nvector unsigned int vec_recursion(vector unsigned int a,\n\t\t\t\t\t\tvector unsigned int b,\n\t\t\t\t\t\tvector unsigned int c,\n\t\t\t\t\t\tvector unsigned int d) {\n\n    const vector unsigned int sl1 = ALTI_SL1;\n    const vector unsigned int sr1 = ALTI_SR1;\n#ifdef ONLY64\n    const vector unsigned int mask = ALTI_MSK64;\n    const vector unsigned char perm_sl = ALTI_SL2_PERM64;\n    const vector unsigned char perm_sr = ALTI_SR2_PERM64;\n#else\n    const vector unsigned int mask = ALTI_MSK;\n    const vector unsigned char perm_sl = ALTI_SL2_PERM;\n    const vector unsigned char perm_sr = ALTI_SR2_PERM;\n#endif\n    vector unsigned int v, w, x, y, z;\n    x = vec_perm(a, (vector unsigned int)perm_sl, perm_sl);\n    v = a;\n    y = vec_sr(b, sr1);\n    z = vec_perm(c, (vector unsigned int)perm_sr, perm_sr);\n    w = vec_sl(d, sl1);\n    z = vec_xor(z, w);\n    y = vec_and(y, mask);\n    v = vec_xor(v, x);\n    z = vec_xor(z, y);\n    z = vec_xor(z, v);\n    return z;\n}\n\n/**\n * This function fills the internal state array with pseudorandom\n * integers.\n */\nJEMALLOC_INLINE void gen_rand_all(sfmt_t *ctx) {\n    int i;\n    vector unsigned int r, r1, r2;\n\n    r1 = ctx->sfmt[N - 2].s;\n    r2 = ctx->sfmt[N - 1].s;\n    for (i = 0; i < N - POS1; i++) {\n\tr = vec_recursion(ctx->sfmt[i].s, ctx->sfmt[i + POS1].s, r1, r2);\n\tctx->sfmt[i].s = r;\n\tr1 = r2;\n\tr2 = r;\n    }\n    for (; i < N; i++) {\n\tr = vec_recursion(ctx->sfmt[i].s, ctx->sfmt[i + POS1 - N].s, r1, r2);\n\tctx->sfmt[i].s = r;\n\tr1 = r2;\n\tr2 = r;\n    }\n}\n\n/**\n * This function fills the user-specified array with pseudorandom\n * integers.\n *\n * @param array an 128-bit array to be filled by pseudorandom numbers.  \n * @param size number of 128-bit pesudorandom numbers to be generated.\n */\nJEMALLOC_INLINE void gen_rand_array(sfmt_t *ctx, w128_t *array, int size) {\n    int i, j;\n    vector unsigned int r, r1, r2;\n\n    r1 = ctx->sfmt[N - 2].s;\n    r2 = ctx->sfmt[N - 1].s;\n    for (i = 0; i < N - POS1; i++) {\n\tr = vec_recursion(ctx->sfmt[i].s, ctx->sfmt[i + POS1].s, r1, r2);\n\tarray[i].s = r;\n\tr1 = r2;\n\tr2 = r;\n    }\n    for (; i < N; i++) {\n\tr = vec_recursion(ctx->sfmt[i].s, array[i + POS1 - N].s, r1, r2);\n\tarray[i].s = r;\n\tr1 = r2;\n\tr2 = r;\n    }\n    /* main loop */\n    for (; i < size - N; i++) {\n\tr = vec_recursion(array[i - N].s, array[i + POS1 - N].s, r1, r2);\n\tarray[i].s = r;\n\tr1 = r2;\n\tr2 = r;\n    }\n    for (j = 0; j < 2 * N - size; j++) {\n\tctx->sfmt[j].s = array[j + size - N].s;\n    }\n    for (; i < size; i++) {\n\tr = vec_recursion(array[i - N].s, array[i + POS1 - N].s, r1, r2);\n\tarray[i].s = r;\n\tctx->sfmt[j++].s = r;\n\tr1 = r2;\n\tr2 = r;\n    }\n}\n\n#ifndef ONLY64\n#if defined(__APPLE__)\n#define ALTI_SWAP (vector unsigned char) \\\n\t(4, 5, 6, 7, 0, 1, 2, 3, 12, 13, 14, 15, 8, 9, 10, 11)\n#else\n#define ALTI_SWAP {4, 5, 6, 7, 0, 1, 2, 3, 12, 13, 14, 15, 8, 9, 10, 11}\n#endif\n/**\n * This function swaps high and low 32-bit of 64-bit integers in user\n * specified array.\n *\n * @param array an 128-bit array to be swaped.\n * @param size size of 128-bit array.\n */\nJEMALLOC_INLINE void swap(w128_t *array, int size) {\n    int i;\n    const vector unsigned char perm = ALTI_SWAP;\n\n    for (i = 0; i < size; i++) {\n\tarray[i].s = vec_perm(array[i].s, (vector unsigned int)perm, perm);\n    }\n}\n#endif\n\n#endif\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.8/deps/jemalloc/test/include/test/SFMT-params.h",
    "content": "/*\n * This file derives from SFMT 1.3.3\n * (http://www.math.sci.hiroshima-u.ac.jp/~m-mat/MT/SFMT/index.html), which was\n * released under the terms of the following license:\n *\n *   Copyright (c) 2006,2007 Mutsuo Saito, Makoto Matsumoto and Hiroshima\n *   University. All rights reserved.\n *\n *   Redistribution and use in source and binary forms, with or without\n *   modification, are permitted provided that the following conditions are\n *   met:\n *\n *       * Redistributions of source code must retain the above copyright\n *         notice, this list of conditions and the following disclaimer.\n *       * Redistributions in binary form must reproduce the above\n *         copyright notice, this list of conditions and the following\n *         disclaimer in the documentation and/or other materials provided\n *         with the distribution.\n *       * Neither the name of the Hiroshima University nor the names of\n *         its contributors may be used to endorse or promote products\n *         derived from this software without specific prior written\n *         permission.\n *\n *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n *   \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\n *   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\n *   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\n *   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n *   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\n *   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n *   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n *   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n *   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n *   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n#ifndef SFMT_PARAMS_H\n#define SFMT_PARAMS_H\n\n#if !defined(MEXP)\n#ifdef __GNUC__\n  #warning \"MEXP is not defined. I assume MEXP is 19937.\"\n#endif\n  #define MEXP 19937\n#endif\n/*-----------------\n  BASIC DEFINITIONS\n  -----------------*/\n/** Mersenne Exponent. The period of the sequence \n *  is a multiple of 2^MEXP-1.\n * #define MEXP 19937 */\n/** SFMT generator has an internal state array of 128-bit integers,\n * and N is its size. */\n#define N (MEXP / 128 + 1)\n/** N32 is the size of internal state array when regarded as an array\n * of 32-bit integers.*/\n#define N32 (N * 4)\n/** N64 is the size of internal state array when regarded as an array\n * of 64-bit integers.*/\n#define N64 (N * 2)\n\n/*----------------------\n  the parameters of SFMT\n  following definitions are in paramsXXXX.h file.\n  ----------------------*/\n/** the pick up position of the array.\n#define POS1 122 \n*/\n\n/** the parameter of shift left as four 32-bit registers.\n#define SL1 18\n */\n\n/** the parameter of shift left as one 128-bit register. \n * The 128-bit integer is shifted by (SL2 * 8) bits. \n#define SL2 1 \n*/\n\n/** the parameter of shift right as four 32-bit registers.\n#define SR1 11\n*/\n\n/** the parameter of shift right as one 128-bit register. \n * The 128-bit integer is shifted by (SL2 * 8) bits. \n#define SR2 1 \n*/\n\n/** A bitmask, used in the recursion.  These parameters are introduced\n * to break symmetry of SIMD.\n#define MSK1 0xdfffffefU\n#define MSK2 0xddfecb7fU\n#define MSK3 0xbffaffffU\n#define MSK4 0xbffffff6U \n*/\n\n/** These definitions are part of a 128-bit period certification vector.\n#define PARITY1\t0x00000001U\n#define PARITY2\t0x00000000U\n#define PARITY3\t0x00000000U\n#define PARITY4\t0xc98e126aU\n*/\n\n#if MEXP == 607\n  #include \"test/SFMT-params607.h\"\n#elif MEXP == 1279\n  #include \"test/SFMT-params1279.h\"\n#elif MEXP == 2281\n  #include \"test/SFMT-params2281.h\"\n#elif MEXP == 4253\n  #include \"test/SFMT-params4253.h\"\n#elif MEXP == 11213\n  #include \"test/SFMT-params11213.h\"\n#elif MEXP == 19937\n  #include \"test/SFMT-params19937.h\"\n#elif MEXP == 44497\n  #include \"test/SFMT-params44497.h\"\n#elif MEXP == 86243\n  #include \"test/SFMT-params86243.h\"\n#elif MEXP == 132049\n  #include \"test/SFMT-params132049.h\"\n#elif MEXP == 216091\n  #include \"test/SFMT-params216091.h\"\n#else\n#ifdef __GNUC__\n  #error \"MEXP is not valid.\"\n  #undef MEXP\n#else\n  #undef MEXP\n#endif\n\n#endif\n\n#endif /* SFMT_PARAMS_H */\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.8/deps/jemalloc/test/include/test/SFMT-params11213.h",
    "content": "/*\n * This file derives from SFMT 1.3.3\n * (http://www.math.sci.hiroshima-u.ac.jp/~m-mat/MT/SFMT/index.html), which was\n * released under the terms of the following license:\n *\n *   Copyright (c) 2006,2007 Mutsuo Saito, Makoto Matsumoto and Hiroshima\n *   University. All rights reserved.\n *\n *   Redistribution and use in source and binary forms, with or without\n *   modification, are permitted provided that the following conditions are\n *   met:\n *\n *       * Redistributions of source code must retain the above copyright\n *         notice, this list of conditions and the following disclaimer.\n *       * Redistributions in binary form must reproduce the above\n *         copyright notice, this list of conditions and the following\n *         disclaimer in the documentation and/or other materials provided\n *         with the distribution.\n *       * Neither the name of the Hiroshima University nor the names of\n *         its contributors may be used to endorse or promote products\n *         derived from this software without specific prior written\n *         permission.\n *\n *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n *   \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\n *   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\n *   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\n *   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n *   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\n *   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n *   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n *   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n *   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n *   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n#ifndef SFMT_PARAMS11213_H\n#define SFMT_PARAMS11213_H\n\n#define POS1\t68\n#define SL1\t14\n#define SL2\t3\n#define SR1\t7\n#define SR2\t3\n#define MSK1\t0xeffff7fbU\n#define MSK2\t0xffffffefU\n#define MSK3\t0xdfdfbfffU\n#define MSK4\t0x7fffdbfdU\n#define PARITY1\t0x00000001U\n#define PARITY2\t0x00000000U\n#define PARITY3\t0xe8148000U\n#define PARITY4\t0xd0c7afa3U\n\n\n/* PARAMETERS FOR ALTIVEC */\n#if defined(__APPLE__)\t/* For OSX */\n    #define ALTI_SL1\t(vector unsigned int)(SL1, SL1, SL1, SL1)\n    #define ALTI_SR1\t(vector unsigned int)(SR1, SR1, SR1, SR1)\n    #define ALTI_MSK\t(vector unsigned int)(MSK1, MSK2, MSK3, MSK4)\n    #define ALTI_MSK64 \\\n\t(vector unsigned int)(MSK2, MSK1, MSK4, MSK3)\n    #define ALTI_SL2_PERM \\\n\t(vector unsigned char)(3,21,21,21,7,0,1,2,11,4,5,6,15,8,9,10)\n    #define ALTI_SL2_PERM64 \\\n\t(vector unsigned char)(3,4,5,6,7,29,29,29,11,12,13,14,15,0,1,2)\n    #define ALTI_SR2_PERM \\\n\t(vector unsigned char)(5,6,7,0,9,10,11,4,13,14,15,8,19,19,19,12)\n    #define ALTI_SR2_PERM64 \\\n\t(vector unsigned char)(13,14,15,0,1,2,3,4,19,19,19,8,9,10,11,12)\n#else\t/* For OTHER OSs(Linux?) */\n    #define ALTI_SL1\t{SL1, SL1, SL1, SL1}\n    #define ALTI_SR1\t{SR1, SR1, SR1, SR1}\n    #define ALTI_MSK\t{MSK1, MSK2, MSK3, MSK4}\n    #define ALTI_MSK64\t{MSK2, MSK1, MSK4, MSK3}\n    #define ALTI_SL2_PERM\t{3,21,21,21,7,0,1,2,11,4,5,6,15,8,9,10}\n    #define ALTI_SL2_PERM64\t{3,4,5,6,7,29,29,29,11,12,13,14,15,0,1,2}\n    #define ALTI_SR2_PERM\t{5,6,7,0,9,10,11,4,13,14,15,8,19,19,19,12}\n    #define ALTI_SR2_PERM64\t{13,14,15,0,1,2,3,4,19,19,19,8,9,10,11,12}\n#endif\t/* For OSX */\n#define IDSTR\t\"SFMT-11213:68-14-3-7-3:effff7fb-ffffffef-dfdfbfff-7fffdbfd\"\n\n#endif /* SFMT_PARAMS11213_H */\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.8/deps/jemalloc/test/include/test/SFMT-params1279.h",
    "content": "/*\n * This file derives from SFMT 1.3.3\n * (http://www.math.sci.hiroshima-u.ac.jp/~m-mat/MT/SFMT/index.html), which was\n * released under the terms of the following license:\n *\n *   Copyright (c) 2006,2007 Mutsuo Saito, Makoto Matsumoto and Hiroshima\n *   University. All rights reserved.\n *\n *   Redistribution and use in source and binary forms, with or without\n *   modification, are permitted provided that the following conditions are\n *   met:\n *\n *       * Redistributions of source code must retain the above copyright\n *         notice, this list of conditions and the following disclaimer.\n *       * Redistributions in binary form must reproduce the above\n *         copyright notice, this list of conditions and the following\n *         disclaimer in the documentation and/or other materials provided\n *         with the distribution.\n *       * Neither the name of the Hiroshima University nor the names of\n *         its contributors may be used to endorse or promote products\n *         derived from this software without specific prior written\n *         permission.\n *\n *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n *   \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\n *   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\n *   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\n *   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n *   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\n *   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n *   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n *   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n *   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n *   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n#ifndef SFMT_PARAMS1279_H\n#define SFMT_PARAMS1279_H\n\n#define POS1\t7\n#define SL1\t14\n#define SL2\t3\n#define SR1\t5\n#define SR2\t1\n#define MSK1\t0xf7fefffdU\n#define MSK2\t0x7fefcfffU\n#define MSK3\t0xaff3ef3fU\n#define MSK4\t0xb5ffff7fU\n#define PARITY1\t0x00000001U\n#define PARITY2\t0x00000000U\n#define PARITY3\t0x00000000U\n#define PARITY4\t0x20000000U\n\n\n/* PARAMETERS FOR ALTIVEC */\n#if defined(__APPLE__)\t/* For OSX */\n    #define ALTI_SL1\t(vector unsigned int)(SL1, SL1, SL1, SL1)\n    #define ALTI_SR1\t(vector unsigned int)(SR1, SR1, SR1, SR1)\n    #define ALTI_MSK\t(vector unsigned int)(MSK1, MSK2, MSK3, MSK4)\n    #define ALTI_MSK64 \\\n\t(vector unsigned int)(MSK2, MSK1, MSK4, MSK3)\n    #define ALTI_SL2_PERM \\\n\t(vector unsigned char)(3,21,21,21,7,0,1,2,11,4,5,6,15,8,9,10)\n    #define ALTI_SL2_PERM64 \\\n\t(vector unsigned char)(3,4,5,6,7,29,29,29,11,12,13,14,15,0,1,2)\n    #define ALTI_SR2_PERM \\\n\t(vector unsigned char)(7,0,1,2,11,4,5,6,15,8,9,10,17,12,13,14)\n    #define ALTI_SR2_PERM64 \\\n\t(vector unsigned char)(15,0,1,2,3,4,5,6,17,8,9,10,11,12,13,14)\n#else\t/* For OTHER OSs(Linux?) */\n    #define ALTI_SL1\t{SL1, SL1, SL1, SL1}\n    #define ALTI_SR1\t{SR1, SR1, SR1, SR1}\n    #define ALTI_MSK\t{MSK1, MSK2, MSK3, MSK4}\n    #define ALTI_MSK64\t{MSK2, MSK1, MSK4, MSK3}\n    #define ALTI_SL2_PERM\t{3,21,21,21,7,0,1,2,11,4,5,6,15,8,9,10}\n    #define ALTI_SL2_PERM64\t{3,4,5,6,7,29,29,29,11,12,13,14,15,0,1,2}\n    #define ALTI_SR2_PERM\t{7,0,1,2,11,4,5,6,15,8,9,10,17,12,13,14}\n    #define ALTI_SR2_PERM64\t{15,0,1,2,3,4,5,6,17,8,9,10,11,12,13,14}\n#endif\t/* For OSX */\n#define IDSTR\t\"SFMT-1279:7-14-3-5-1:f7fefffd-7fefcfff-aff3ef3f-b5ffff7f\"\n\n#endif /* SFMT_PARAMS1279_H */\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.8/deps/jemalloc/test/include/test/SFMT-params132049.h",
    "content": "/*\n * This file derives from SFMT 1.3.3\n * (http://www.math.sci.hiroshima-u.ac.jp/~m-mat/MT/SFMT/index.html), which was\n * released under the terms of the following license:\n *\n *   Copyright (c) 2006,2007 Mutsuo Saito, Makoto Matsumoto and Hiroshima\n *   University. All rights reserved.\n *\n *   Redistribution and use in source and binary forms, with or without\n *   modification, are permitted provided that the following conditions are\n *   met:\n *\n *       * Redistributions of source code must retain the above copyright\n *         notice, this list of conditions and the following disclaimer.\n *       * Redistributions in binary form must reproduce the above\n *         copyright notice, this list of conditions and the following\n *         disclaimer in the documentation and/or other materials provided\n *         with the distribution.\n *       * Neither the name of the Hiroshima University nor the names of\n *         its contributors may be used to endorse or promote products\n *         derived from this software without specific prior written\n *         permission.\n *\n *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n *   \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\n *   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\n *   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\n *   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n *   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\n *   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n *   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n *   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n *   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n *   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n#ifndef SFMT_PARAMS132049_H\n#define SFMT_PARAMS132049_H\n\n#define POS1\t110\n#define SL1\t19\n#define SL2\t1\n#define SR1\t21\n#define SR2\t1\n#define MSK1\t0xffffbb5fU\n#define MSK2\t0xfb6ebf95U\n#define MSK3\t0xfffefffaU\n#define MSK4\t0xcff77fffU\n#define PARITY1\t0x00000001U\n#define PARITY2\t0x00000000U\n#define PARITY3\t0xcb520000U\n#define PARITY4\t0xc7e91c7dU\n\n\n/* PARAMETERS FOR ALTIVEC */\n#if defined(__APPLE__)\t/* For OSX */\n    #define ALTI_SL1\t(vector unsigned int)(SL1, SL1, SL1, SL1)\n    #define ALTI_SR1\t(vector unsigned int)(SR1, SR1, SR1, SR1)\n    #define ALTI_MSK\t(vector unsigned int)(MSK1, MSK2, MSK3, MSK4)\n    #define ALTI_MSK64 \\\n\t(vector unsigned int)(MSK2, MSK1, MSK4, MSK3)\n    #define ALTI_SL2_PERM \\\n\t(vector unsigned char)(1,2,3,23,5,6,7,0,9,10,11,4,13,14,15,8)\n    #define ALTI_SL2_PERM64 \\\n\t(vector unsigned char)(1,2,3,4,5,6,7,31,9,10,11,12,13,14,15,0)\n    #define ALTI_SR2_PERM \\\n\t(vector unsigned char)(7,0,1,2,11,4,5,6,15,8,9,10,17,12,13,14)\n    #define ALTI_SR2_PERM64 \\\n\t(vector unsigned char)(15,0,1,2,3,4,5,6,17,8,9,10,11,12,13,14)\n#else\t/* For OTHER OSs(Linux?) */\n    #define ALTI_SL1\t{SL1, SL1, SL1, SL1}\n    #define ALTI_SR1\t{SR1, SR1, SR1, SR1}\n    #define ALTI_MSK\t{MSK1, MSK2, MSK3, MSK4}\n    #define ALTI_MSK64\t{MSK2, MSK1, MSK4, MSK3}\n    #define ALTI_SL2_PERM\t{1,2,3,23,5,6,7,0,9,10,11,4,13,14,15,8}\n    #define ALTI_SL2_PERM64\t{1,2,3,4,5,6,7,31,9,10,11,12,13,14,15,0}\n    #define ALTI_SR2_PERM\t{7,0,1,2,11,4,5,6,15,8,9,10,17,12,13,14}\n    #define ALTI_SR2_PERM64\t{15,0,1,2,3,4,5,6,17,8,9,10,11,12,13,14}\n#endif\t/* For OSX */\n#define IDSTR\t\"SFMT-132049:110-19-1-21-1:ffffbb5f-fb6ebf95-fffefffa-cff77fff\"\n\n#endif /* SFMT_PARAMS132049_H */\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.8/deps/jemalloc/test/include/test/SFMT-params19937.h",
    "content": "/*\n * This file derives from SFMT 1.3.3\n * (http://www.math.sci.hiroshima-u.ac.jp/~m-mat/MT/SFMT/index.html), which was\n * released under the terms of the following license:\n *\n *   Copyright (c) 2006,2007 Mutsuo Saito, Makoto Matsumoto and Hiroshima\n *   University. All rights reserved.\n *\n *   Redistribution and use in source and binary forms, with or without\n *   modification, are permitted provided that the following conditions are\n *   met:\n *\n *       * Redistributions of source code must retain the above copyright\n *         notice, this list of conditions and the following disclaimer.\n *       * Redistributions in binary form must reproduce the above\n *         copyright notice, this list of conditions and the following\n *         disclaimer in the documentation and/or other materials provided\n *         with the distribution.\n *       * Neither the name of the Hiroshima University nor the names of\n *         its contributors may be used to endorse or promote products\n *         derived from this software without specific prior written\n *         permission.\n *\n *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n *   \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\n *   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\n *   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\n *   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n *   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\n *   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n *   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n *   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n *   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n *   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n#ifndef SFMT_PARAMS19937_H\n#define SFMT_PARAMS19937_H\n\n#define POS1\t122\n#define SL1\t18\n#define SL2\t1\n#define SR1\t11\n#define SR2\t1\n#define MSK1\t0xdfffffefU\n#define MSK2\t0xddfecb7fU\n#define MSK3\t0xbffaffffU\n#define MSK4\t0xbffffff6U\n#define PARITY1\t0x00000001U\n#define PARITY2\t0x00000000U\n#define PARITY3\t0x00000000U\n#define PARITY4\t0x13c9e684U\n\n\n/* PARAMETERS FOR ALTIVEC */\n#if defined(__APPLE__)\t/* For OSX */\n    #define ALTI_SL1\t(vector unsigned int)(SL1, SL1, SL1, SL1)\n    #define ALTI_SR1\t(vector unsigned int)(SR1, SR1, SR1, SR1)\n    #define ALTI_MSK\t(vector unsigned int)(MSK1, MSK2, MSK3, MSK4)\n    #define ALTI_MSK64 \\\n\t(vector unsigned int)(MSK2, MSK1, MSK4, MSK3)\n    #define ALTI_SL2_PERM \\\n\t(vector unsigned char)(1,2,3,23,5,6,7,0,9,10,11,4,13,14,15,8)\n    #define ALTI_SL2_PERM64 \\\n\t(vector unsigned char)(1,2,3,4,5,6,7,31,9,10,11,12,13,14,15,0)\n    #define ALTI_SR2_PERM \\\n\t(vector unsigned char)(7,0,1,2,11,4,5,6,15,8,9,10,17,12,13,14)\n    #define ALTI_SR2_PERM64 \\\n\t(vector unsigned char)(15,0,1,2,3,4,5,6,17,8,9,10,11,12,13,14)\n#else\t/* For OTHER OSs(Linux?) */\n    #define ALTI_SL1\t{SL1, SL1, SL1, SL1}\n    #define ALTI_SR1\t{SR1, SR1, SR1, SR1}\n    #define ALTI_MSK\t{MSK1, MSK2, MSK3, MSK4}\n    #define ALTI_MSK64\t{MSK2, MSK1, MSK4, MSK3}\n    #define ALTI_SL2_PERM\t{1,2,3,23,5,6,7,0,9,10,11,4,13,14,15,8}\n    #define ALTI_SL2_PERM64\t{1,2,3,4,5,6,7,31,9,10,11,12,13,14,15,0}\n    #define ALTI_SR2_PERM\t{7,0,1,2,11,4,5,6,15,8,9,10,17,12,13,14}\n    #define ALTI_SR2_PERM64\t{15,0,1,2,3,4,5,6,17,8,9,10,11,12,13,14}\n#endif\t/* For OSX */\n#define IDSTR\t\"SFMT-19937:122-18-1-11-1:dfffffef-ddfecb7f-bffaffff-bffffff6\"\n\n#endif /* SFMT_PARAMS19937_H */\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.8/deps/jemalloc/test/include/test/SFMT-params216091.h",
    "content": "/*\n * This file derives from SFMT 1.3.3\n * (http://www.math.sci.hiroshima-u.ac.jp/~m-mat/MT/SFMT/index.html), which was\n * released under the terms of the following license:\n *\n *   Copyright (c) 2006,2007 Mutsuo Saito, Makoto Matsumoto and Hiroshima\n *   University. All rights reserved.\n *\n *   Redistribution and use in source and binary forms, with or without\n *   modification, are permitted provided that the following conditions are\n *   met:\n *\n *       * Redistributions of source code must retain the above copyright\n *         notice, this list of conditions and the following disclaimer.\n *       * Redistributions in binary form must reproduce the above\n *         copyright notice, this list of conditions and the following\n *         disclaimer in the documentation and/or other materials provided\n *         with the distribution.\n *       * Neither the name of the Hiroshima University nor the names of\n *         its contributors may be used to endorse or promote products\n *         derived from this software without specific prior written\n *         permission.\n *\n *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n *   \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\n *   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\n *   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\n *   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n *   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\n *   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n *   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n *   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n *   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n *   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n#ifndef SFMT_PARAMS216091_H\n#define SFMT_PARAMS216091_H\n\n#define POS1\t627\n#define SL1\t11\n#define SL2\t3\n#define SR1\t10\n#define SR2\t1\n#define MSK1\t0xbff7bff7U\n#define MSK2\t0xbfffffffU\n#define MSK3\t0xbffffa7fU\n#define MSK4\t0xffddfbfbU\n#define PARITY1\t0xf8000001U\n#define PARITY2\t0x89e80709U\n#define PARITY3\t0x3bd2b64bU\n#define PARITY4\t0x0c64b1e4U\n\n\n/* PARAMETERS FOR ALTIVEC */\n#if defined(__APPLE__)\t/* For OSX */\n    #define ALTI_SL1\t(vector unsigned int)(SL1, SL1, SL1, SL1)\n    #define ALTI_SR1\t(vector unsigned int)(SR1, SR1, SR1, SR1)\n    #define ALTI_MSK\t(vector unsigned int)(MSK1, MSK2, MSK3, MSK4)\n    #define ALTI_MSK64 \\\n\t(vector unsigned int)(MSK2, MSK1, MSK4, MSK3)\n    #define ALTI_SL2_PERM \\\n\t(vector unsigned char)(3,21,21,21,7,0,1,2,11,4,5,6,15,8,9,10)\n    #define ALTI_SL2_PERM64 \\\n\t(vector unsigned char)(3,4,5,6,7,29,29,29,11,12,13,14,15,0,1,2)\n    #define ALTI_SR2_PERM \\\n\t(vector unsigned char)(7,0,1,2,11,4,5,6,15,8,9,10,17,12,13,14)\n    #define ALTI_SR2_PERM64 \\\n\t(vector unsigned char)(15,0,1,2,3,4,5,6,17,8,9,10,11,12,13,14)\n#else\t/* For OTHER OSs(Linux?) */\n    #define ALTI_SL1\t{SL1, SL1, SL1, SL1}\n    #define ALTI_SR1\t{SR1, SR1, SR1, SR1}\n    #define ALTI_MSK\t{MSK1, MSK2, MSK3, MSK4}\n    #define ALTI_MSK64\t{MSK2, MSK1, MSK4, MSK3}\n    #define ALTI_SL2_PERM\t{3,21,21,21,7,0,1,2,11,4,5,6,15,8,9,10}\n    #define ALTI_SL2_PERM64\t{3,4,5,6,7,29,29,29,11,12,13,14,15,0,1,2}\n    #define ALTI_SR2_PERM\t{7,0,1,2,11,4,5,6,15,8,9,10,17,12,13,14}\n    #define ALTI_SR2_PERM64\t{15,0,1,2,3,4,5,6,17,8,9,10,11,12,13,14}\n#endif\t/* For OSX */\n#define IDSTR\t\"SFMT-216091:627-11-3-10-1:bff7bff7-bfffffff-bffffa7f-ffddfbfb\"\n\n#endif /* SFMT_PARAMS216091_H */\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.8/deps/jemalloc/test/include/test/SFMT-params2281.h",
    "content": "/*\n * This file derives from SFMT 1.3.3\n * (http://www.math.sci.hiroshima-u.ac.jp/~m-mat/MT/SFMT/index.html), which was\n * released under the terms of the following license:\n *\n *   Copyright (c) 2006,2007 Mutsuo Saito, Makoto Matsumoto and Hiroshima\n *   University. All rights reserved.\n *\n *   Redistribution and use in source and binary forms, with or without\n *   modification, are permitted provided that the following conditions are\n *   met:\n *\n *       * Redistributions of source code must retain the above copyright\n *         notice, this list of conditions and the following disclaimer.\n *       * Redistributions in binary form must reproduce the above\n *         copyright notice, this list of conditions and the following\n *         disclaimer in the documentation and/or other materials provided\n *         with the distribution.\n *       * Neither the name of the Hiroshima University nor the names of\n *         its contributors may be used to endorse or promote products\n *         derived from this software without specific prior written\n *         permission.\n *\n *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n *   \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\n *   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\n *   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\n *   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n *   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\n *   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n *   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n *   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n *   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n *   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n#ifndef SFMT_PARAMS2281_H\n#define SFMT_PARAMS2281_H\n\n#define POS1\t12\n#define SL1\t19\n#define SL2\t1\n#define SR1\t5\n#define SR2\t1\n#define MSK1\t0xbff7ffbfU\n#define MSK2\t0xfdfffffeU\n#define MSK3\t0xf7ffef7fU\n#define MSK4\t0xf2f7cbbfU\n#define PARITY1\t0x00000001U\n#define PARITY2\t0x00000000U\n#define PARITY3\t0x00000000U\n#define PARITY4\t0x41dfa600U\n\n\n/* PARAMETERS FOR ALTIVEC */\n#if defined(__APPLE__)\t/* For OSX */\n    #define ALTI_SL1\t(vector unsigned int)(SL1, SL1, SL1, SL1)\n    #define ALTI_SR1\t(vector unsigned int)(SR1, SR1, SR1, SR1)\n    #define ALTI_MSK\t(vector unsigned int)(MSK1, MSK2, MSK3, MSK4)\n    #define ALTI_MSK64 \\\n\t(vector unsigned int)(MSK2, MSK1, MSK4, MSK3)\n    #define ALTI_SL2_PERM \\\n\t(vector unsigned char)(1,2,3,23,5,6,7,0,9,10,11,4,13,14,15,8)\n    #define ALTI_SL2_PERM64 \\\n\t(vector unsigned char)(1,2,3,4,5,6,7,31,9,10,11,12,13,14,15,0)\n    #define ALTI_SR2_PERM \\\n\t(vector unsigned char)(7,0,1,2,11,4,5,6,15,8,9,10,17,12,13,14)\n    #define ALTI_SR2_PERM64 \\\n\t(vector unsigned char)(15,0,1,2,3,4,5,6,17,8,9,10,11,12,13,14)\n#else\t/* For OTHER OSs(Linux?) */\n    #define ALTI_SL1\t{SL1, SL1, SL1, SL1}\n    #define ALTI_SR1\t{SR1, SR1, SR1, SR1}\n    #define ALTI_MSK\t{MSK1, MSK2, MSK3, MSK4}\n    #define ALTI_MSK64\t{MSK2, MSK1, MSK4, MSK3}\n    #define ALTI_SL2_PERM\t{1,2,3,23,5,6,7,0,9,10,11,4,13,14,15,8}\n    #define ALTI_SL2_PERM64\t{1,2,3,4,5,6,7,31,9,10,11,12,13,14,15,0}\n    #define ALTI_SR2_PERM\t{7,0,1,2,11,4,5,6,15,8,9,10,17,12,13,14}\n    #define ALTI_SR2_PERM64\t{15,0,1,2,3,4,5,6,17,8,9,10,11,12,13,14}\n#endif\t/* For OSX */\n#define IDSTR\t\"SFMT-2281:12-19-1-5-1:bff7ffbf-fdfffffe-f7ffef7f-f2f7cbbf\"\n\n#endif /* SFMT_PARAMS2281_H */\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.8/deps/jemalloc/test/include/test/SFMT-params4253.h",
    "content": "/*\n * This file derives from SFMT 1.3.3\n * (http://www.math.sci.hiroshima-u.ac.jp/~m-mat/MT/SFMT/index.html), which was\n * released under the terms of the following license:\n *\n *   Copyright (c) 2006,2007 Mutsuo Saito, Makoto Matsumoto and Hiroshima\n *   University. All rights reserved.\n *\n *   Redistribution and use in source and binary forms, with or without\n *   modification, are permitted provided that the following conditions are\n *   met:\n *\n *       * Redistributions of source code must retain the above copyright\n *         notice, this list of conditions and the following disclaimer.\n *       * Redistributions in binary form must reproduce the above\n *         copyright notice, this list of conditions and the following\n *         disclaimer in the documentation and/or other materials provided\n *         with the distribution.\n *       * Neither the name of the Hiroshima University nor the names of\n *         its contributors may be used to endorse or promote products\n *         derived from this software without specific prior written\n *         permission.\n *\n *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n *   \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\n *   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\n *   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\n *   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n *   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\n *   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n *   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n *   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n *   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n *   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n#ifndef SFMT_PARAMS4253_H\n#define SFMT_PARAMS4253_H\n\n#define POS1\t17\n#define SL1\t20\n#define SL2\t1\n#define SR1\t7\n#define SR2\t1\n#define MSK1\t0x9f7bffffU\n#define MSK2\t0x9fffff5fU\n#define MSK3\t0x3efffffbU\n#define MSK4\t0xfffff7bbU\n#define PARITY1\t0xa8000001U\n#define PARITY2\t0xaf5390a3U\n#define PARITY3\t0xb740b3f8U\n#define PARITY4\t0x6c11486dU\n\n\n/* PARAMETERS FOR ALTIVEC */\n#if defined(__APPLE__)\t/* For OSX */\n    #define ALTI_SL1\t(vector unsigned int)(SL1, SL1, SL1, SL1)\n    #define ALTI_SR1\t(vector unsigned int)(SR1, SR1, SR1, SR1)\n    #define ALTI_MSK\t(vector unsigned int)(MSK1, MSK2, MSK3, MSK4)\n    #define ALTI_MSK64 \\\n\t(vector unsigned int)(MSK2, MSK1, MSK4, MSK3)\n    #define ALTI_SL2_PERM \\\n\t(vector unsigned char)(1,2,3,23,5,6,7,0,9,10,11,4,13,14,15,8)\n    #define ALTI_SL2_PERM64 \\\n\t(vector unsigned char)(1,2,3,4,5,6,7,31,9,10,11,12,13,14,15,0)\n    #define ALTI_SR2_PERM \\\n\t(vector unsigned char)(7,0,1,2,11,4,5,6,15,8,9,10,17,12,13,14)\n    #define ALTI_SR2_PERM64 \\\n\t(vector unsigned char)(15,0,1,2,3,4,5,6,17,8,9,10,11,12,13,14)\n#else\t/* For OTHER OSs(Linux?) */\n    #define ALTI_SL1\t{SL1, SL1, SL1, SL1}\n    #define ALTI_SR1\t{SR1, SR1, SR1, SR1}\n    #define ALTI_MSK\t{MSK1, MSK2, MSK3, MSK4}\n    #define ALTI_MSK64\t{MSK2, MSK1, MSK4, MSK3}\n    #define ALTI_SL2_PERM\t{1,2,3,23,5,6,7,0,9,10,11,4,13,14,15,8}\n    #define ALTI_SL2_PERM64\t{1,2,3,4,5,6,7,31,9,10,11,12,13,14,15,0}\n    #define ALTI_SR2_PERM\t{7,0,1,2,11,4,5,6,15,8,9,10,17,12,13,14}\n    #define ALTI_SR2_PERM64\t{15,0,1,2,3,4,5,6,17,8,9,10,11,12,13,14}\n#endif\t/* For OSX */\n#define IDSTR\t\"SFMT-4253:17-20-1-7-1:9f7bffff-9fffff5f-3efffffb-fffff7bb\"\n\n#endif /* SFMT_PARAMS4253_H */\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.8/deps/jemalloc/test/include/test/SFMT-params44497.h",
    "content": "/*\n * This file derives from SFMT 1.3.3\n * (http://www.math.sci.hiroshima-u.ac.jp/~m-mat/MT/SFMT/index.html), which was\n * released under the terms of the following license:\n *\n *   Copyright (c) 2006,2007 Mutsuo Saito, Makoto Matsumoto and Hiroshima\n *   University. All rights reserved.\n *\n *   Redistribution and use in source and binary forms, with or without\n *   modification, are permitted provided that the following conditions are\n *   met:\n *\n *       * Redistributions of source code must retain the above copyright\n *         notice, this list of conditions and the following disclaimer.\n *       * Redistributions in binary form must reproduce the above\n *         copyright notice, this list of conditions and the following\n *         disclaimer in the documentation and/or other materials provided\n *         with the distribution.\n *       * Neither the name of the Hiroshima University nor the names of\n *         its contributors may be used to endorse or promote products\n *         derived from this software without specific prior written\n *         permission.\n *\n *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n *   \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\n *   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\n *   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\n *   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n *   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\n *   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n *   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n *   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n *   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n *   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n#ifndef SFMT_PARAMS44497_H\n#define SFMT_PARAMS44497_H\n\n#define POS1\t330\n#define SL1\t5\n#define SL2\t3\n#define SR1\t9\n#define SR2\t3\n#define MSK1\t0xeffffffbU\n#define MSK2\t0xdfbebfffU\n#define MSK3\t0xbfbf7befU\n#define MSK4\t0x9ffd7bffU\n#define PARITY1\t0x00000001U\n#define PARITY2\t0x00000000U\n#define PARITY3\t0xa3ac4000U\n#define PARITY4\t0xecc1327aU\n\n\n/* PARAMETERS FOR ALTIVEC */\n#if defined(__APPLE__)\t/* For OSX */\n    #define ALTI_SL1\t(vector unsigned int)(SL1, SL1, SL1, SL1)\n    #define ALTI_SR1\t(vector unsigned int)(SR1, SR1, SR1, SR1)\n    #define ALTI_MSK\t(vector unsigned int)(MSK1, MSK2, MSK3, MSK4)\n    #define ALTI_MSK64 \\\n\t(vector unsigned int)(MSK2, MSK1, MSK4, MSK3)\n    #define ALTI_SL2_PERM \\\n\t(vector unsigned char)(3,21,21,21,7,0,1,2,11,4,5,6,15,8,9,10)\n    #define ALTI_SL2_PERM64 \\\n\t(vector unsigned char)(3,4,5,6,7,29,29,29,11,12,13,14,15,0,1,2)\n    #define ALTI_SR2_PERM \\\n\t(vector unsigned char)(5,6,7,0,9,10,11,4,13,14,15,8,19,19,19,12)\n    #define ALTI_SR2_PERM64 \\\n\t(vector unsigned char)(13,14,15,0,1,2,3,4,19,19,19,8,9,10,11,12)\n#else\t/* For OTHER OSs(Linux?) */\n    #define ALTI_SL1\t{SL1, SL1, SL1, SL1}\n    #define ALTI_SR1\t{SR1, SR1, SR1, SR1}\n    #define ALTI_MSK\t{MSK1, MSK2, MSK3, MSK4}\n    #define ALTI_MSK64\t{MSK2, MSK1, MSK4, MSK3}\n    #define ALTI_SL2_PERM\t{3,21,21,21,7,0,1,2,11,4,5,6,15,8,9,10}\n    #define ALTI_SL2_PERM64\t{3,4,5,6,7,29,29,29,11,12,13,14,15,0,1,2}\n    #define ALTI_SR2_PERM\t{5,6,7,0,9,10,11,4,13,14,15,8,19,19,19,12}\n    #define ALTI_SR2_PERM64\t{13,14,15,0,1,2,3,4,19,19,19,8,9,10,11,12}\n#endif\t/* For OSX */\n#define IDSTR\t\"SFMT-44497:330-5-3-9-3:effffffb-dfbebfff-bfbf7bef-9ffd7bff\"\n\n#endif /* SFMT_PARAMS44497_H */\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.8/deps/jemalloc/test/include/test/SFMT-params607.h",
    "content": "/*\n * This file derives from SFMT 1.3.3\n * (http://www.math.sci.hiroshima-u.ac.jp/~m-mat/MT/SFMT/index.html), which was\n * released under the terms of the following license:\n *\n *   Copyright (c) 2006,2007 Mutsuo Saito, Makoto Matsumoto and Hiroshima\n *   University. All rights reserved.\n *\n *   Redistribution and use in source and binary forms, with or without\n *   modification, are permitted provided that the following conditions are\n *   met:\n *\n *       * Redistributions of source code must retain the above copyright\n *         notice, this list of conditions and the following disclaimer.\n *       * Redistributions in binary form must reproduce the above\n *         copyright notice, this list of conditions and the following\n *         disclaimer in the documentation and/or other materials provided\n *         with the distribution.\n *       * Neither the name of the Hiroshima University nor the names of\n *         its contributors may be used to endorse or promote products\n *         derived from this software without specific prior written\n *         permission.\n *\n *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n *   \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\n *   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\n *   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\n *   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n *   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\n *   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n *   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n *   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n *   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n *   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n#ifndef SFMT_PARAMS607_H\n#define SFMT_PARAMS607_H\n\n#define POS1\t2\n#define SL1\t15\n#define SL2\t3\n#define SR1\t13\n#define SR2\t3\n#define MSK1\t0xfdff37ffU\n#define MSK2\t0xef7f3f7dU\n#define MSK3\t0xff777b7dU\n#define MSK4\t0x7ff7fb2fU\n#define PARITY1\t0x00000001U\n#define PARITY2\t0x00000000U\n#define PARITY3\t0x00000000U\n#define PARITY4\t0x5986f054U\n\n\n/* PARAMETERS FOR ALTIVEC */\n#if defined(__APPLE__)\t/* For OSX */\n    #define ALTI_SL1\t(vector unsigned int)(SL1, SL1, SL1, SL1)\n    #define ALTI_SR1\t(vector unsigned int)(SR1, SR1, SR1, SR1)\n    #define ALTI_MSK\t(vector unsigned int)(MSK1, MSK2, MSK3, MSK4)\n    #define ALTI_MSK64 \\\n\t(vector unsigned int)(MSK2, MSK1, MSK4, MSK3)\n    #define ALTI_SL2_PERM \\\n\t(vector unsigned char)(3,21,21,21,7,0,1,2,11,4,5,6,15,8,9,10)\n    #define ALTI_SL2_PERM64 \\\n\t(vector unsigned char)(3,4,5,6,7,29,29,29,11,12,13,14,15,0,1,2)\n    #define ALTI_SR2_PERM \\\n\t(vector unsigned char)(5,6,7,0,9,10,11,4,13,14,15,8,19,19,19,12)\n    #define ALTI_SR2_PERM64 \\\n\t(vector unsigned char)(13,14,15,0,1,2,3,4,19,19,19,8,9,10,11,12)\n#else\t/* For OTHER OSs(Linux?) */\n    #define ALTI_SL1\t{SL1, SL1, SL1, SL1}\n    #define ALTI_SR1\t{SR1, SR1, SR1, SR1}\n    #define ALTI_MSK\t{MSK1, MSK2, MSK3, MSK4}\n    #define ALTI_MSK64\t{MSK2, MSK1, MSK4, MSK3}\n    #define ALTI_SL2_PERM\t{3,21,21,21,7,0,1,2,11,4,5,6,15,8,9,10}\n    #define ALTI_SL2_PERM64\t{3,4,5,6,7,29,29,29,11,12,13,14,15,0,1,2}\n    #define ALTI_SR2_PERM\t{5,6,7,0,9,10,11,4,13,14,15,8,19,19,19,12}\n    #define ALTI_SR2_PERM64\t{13,14,15,0,1,2,3,4,19,19,19,8,9,10,11,12}\n#endif\t/* For OSX */\n#define IDSTR\t\"SFMT-607:2-15-3-13-3:fdff37ff-ef7f3f7d-ff777b7d-7ff7fb2f\"\n\n#endif /* SFMT_PARAMS607_H */\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.8/deps/jemalloc/test/include/test/SFMT-params86243.h",
    "content": "/*\n * This file derives from SFMT 1.3.3\n * (http://www.math.sci.hiroshima-u.ac.jp/~m-mat/MT/SFMT/index.html), which was\n * released under the terms of the following license:\n *\n *   Copyright (c) 2006,2007 Mutsuo Saito, Makoto Matsumoto and Hiroshima\n *   University. All rights reserved.\n *\n *   Redistribution and use in source and binary forms, with or without\n *   modification, are permitted provided that the following conditions are\n *   met:\n *\n *       * Redistributions of source code must retain the above copyright\n *         notice, this list of conditions and the following disclaimer.\n *       * Redistributions in binary form must reproduce the above\n *         copyright notice, this list of conditions and the following\n *         disclaimer in the documentation and/or other materials provided\n *         with the distribution.\n *       * Neither the name of the Hiroshima University nor the names of\n *         its contributors may be used to endorse or promote products\n *         derived from this software without specific prior written\n *         permission.\n *\n *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n *   \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\n *   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\n *   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\n *   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n *   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\n *   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n *   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n *   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n *   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n *   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n#ifndef SFMT_PARAMS86243_H\n#define SFMT_PARAMS86243_H\n\n#define POS1\t366\n#define SL1\t6\n#define SL2\t7\n#define SR1\t19\n#define SR2\t1\n#define MSK1\t0xfdbffbffU\n#define MSK2\t0xbff7ff3fU\n#define MSK3\t0xfd77efffU\n#define MSK4\t0xbf9ff3ffU\n#define PARITY1\t0x00000001U\n#define PARITY2\t0x00000000U\n#define PARITY3\t0x00000000U\n#define PARITY4\t0xe9528d85U\n\n\n/* PARAMETERS FOR ALTIVEC */\n#if defined(__APPLE__)\t/* For OSX */\n    #define ALTI_SL1\t(vector unsigned int)(SL1, SL1, SL1, SL1)\n    #define ALTI_SR1\t(vector unsigned int)(SR1, SR1, SR1, SR1)\n    #define ALTI_MSK\t(vector unsigned int)(MSK1, MSK2, MSK3, MSK4)\n    #define ALTI_MSK64 \\\n\t(vector unsigned int)(MSK2, MSK1, MSK4, MSK3)\n    #define ALTI_SL2_PERM \\\n\t(vector unsigned char)(25,25,25,25,3,25,25,25,7,0,1,2,11,4,5,6)\n    #define ALTI_SL2_PERM64 \\\n\t(vector unsigned char)(7,25,25,25,25,25,25,25,15,0,1,2,3,4,5,6)\n    #define ALTI_SR2_PERM \\\n\t(vector unsigned char)(7,0,1,2,11,4,5,6,15,8,9,10,17,12,13,14)\n    #define ALTI_SR2_PERM64 \\\n\t(vector unsigned char)(15,0,1,2,3,4,5,6,17,8,9,10,11,12,13,14)\n#else\t/* For OTHER OSs(Linux?) */\n    #define ALTI_SL1\t{SL1, SL1, SL1, SL1}\n    #define ALTI_SR1\t{SR1, SR1, SR1, SR1}\n    #define ALTI_MSK\t{MSK1, MSK2, MSK3, MSK4}\n    #define ALTI_MSK64\t{MSK2, MSK1, MSK4, MSK3}\n    #define ALTI_SL2_PERM\t{25,25,25,25,3,25,25,25,7,0,1,2,11,4,5,6}\n    #define ALTI_SL2_PERM64\t{7,25,25,25,25,25,25,25,15,0,1,2,3,4,5,6}\n    #define ALTI_SR2_PERM\t{7,0,1,2,11,4,5,6,15,8,9,10,17,12,13,14}\n    #define ALTI_SR2_PERM64\t{15,0,1,2,3,4,5,6,17,8,9,10,11,12,13,14}\n#endif\t/* For OSX */\n#define IDSTR\t\"SFMT-86243:366-6-7-19-1:fdbffbff-bff7ff3f-fd77efff-bf9ff3ff\"\n\n#endif /* SFMT_PARAMS86243_H */\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.8/deps/jemalloc/test/include/test/SFMT-sse2.h",
    "content": "/*\n * This file derives from SFMT 1.3.3\n * (http://www.math.sci.hiroshima-u.ac.jp/~m-mat/MT/SFMT/index.html), which was\n * released under the terms of the following license:\n *\n *   Copyright (c) 2006,2007 Mutsuo Saito, Makoto Matsumoto and Hiroshima\n *   University. All rights reserved.\n *\n *   Redistribution and use in source and binary forms, with or without\n *   modification, are permitted provided that the following conditions are\n *   met:\n *\n *       * Redistributions of source code must retain the above copyright\n *         notice, this list of conditions and the following disclaimer.\n *       * Redistributions in binary form must reproduce the above\n *         copyright notice, this list of conditions and the following\n *         disclaimer in the documentation and/or other materials provided\n *         with the distribution.\n *       * Neither the name of the Hiroshima University nor the names of\n *         its contributors may be used to endorse or promote products\n *         derived from this software without specific prior written\n *         permission.\n *\n *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n *   \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\n *   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\n *   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\n *   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n *   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\n *   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n *   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n *   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n *   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n *   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n/** \n * @file  SFMT-sse2.h\n * @brief SIMD oriented Fast Mersenne Twister(SFMT) for Intel SSE2\n *\n * @author Mutsuo Saito (Hiroshima University)\n * @author Makoto Matsumoto (Hiroshima University)\n *\n * @note We assume LITTLE ENDIAN in this file\n *\n * Copyright (C) 2006, 2007 Mutsuo Saito, Makoto Matsumoto and Hiroshima\n * University. All rights reserved.\n *\n * The new BSD License is applied to this software, see LICENSE.txt\n */\n\n#ifndef SFMT_SSE2_H\n#define SFMT_SSE2_H\n\n/**\n * This function represents the recursion formula.\n * @param a a 128-bit part of the interal state array\n * @param b a 128-bit part of the interal state array\n * @param c a 128-bit part of the interal state array\n * @param d a 128-bit part of the interal state array\n * @param mask 128-bit mask\n * @return output\n */\nJEMALLOC_ALWAYS_INLINE __m128i mm_recursion(__m128i *a, __m128i *b, \n\t\t\t\t   __m128i c, __m128i d, __m128i mask) {\n    __m128i v, x, y, z;\n    \n    x = _mm_load_si128(a);\n    y = _mm_srli_epi32(*b, SR1);\n    z = _mm_srli_si128(c, SR2);\n    v = _mm_slli_epi32(d, SL1);\n    z = _mm_xor_si128(z, x);\n    z = _mm_xor_si128(z, v);\n    x = _mm_slli_si128(x, SL2);\n    y = _mm_and_si128(y, mask);\n    z = _mm_xor_si128(z, x);\n    z = _mm_xor_si128(z, y);\n    return z;\n}\n\n/**\n * This function fills the internal state array with pseudorandom\n * integers.\n */\nJEMALLOC_INLINE void gen_rand_all(sfmt_t *ctx) {\n    int i;\n    __m128i r, r1, r2, mask;\n    mask = _mm_set_epi32(MSK4, MSK3, MSK2, MSK1);\n\n    r1 = _mm_load_si128(&ctx->sfmt[N - 2].si);\n    r2 = _mm_load_si128(&ctx->sfmt[N - 1].si);\n    for (i = 0; i < N - POS1; i++) {\n\tr = mm_recursion(&ctx->sfmt[i].si, &ctx->sfmt[i + POS1].si, r1, r2,\n\t  mask);\n\t_mm_store_si128(&ctx->sfmt[i].si, r);\n\tr1 = r2;\n\tr2 = r;\n    }\n    for (; i < N; i++) {\n\tr = mm_recursion(&ctx->sfmt[i].si, &ctx->sfmt[i + POS1 - N].si, r1, r2,\n\t  mask);\n\t_mm_store_si128(&ctx->sfmt[i].si, r);\n\tr1 = r2;\n\tr2 = r;\n    }\n}\n\n/**\n * This function fills the user-specified array with pseudorandom\n * integers.\n *\n * @param array an 128-bit array to be filled by pseudorandom numbers.  \n * @param size number of 128-bit pesudorandom numbers to be generated.\n */\nJEMALLOC_INLINE void gen_rand_array(sfmt_t *ctx, w128_t *array, int size) {\n    int i, j;\n    __m128i r, r1, r2, mask;\n    mask = _mm_set_epi32(MSK4, MSK3, MSK2, MSK1);\n\n    r1 = _mm_load_si128(&ctx->sfmt[N - 2].si);\n    r2 = _mm_load_si128(&ctx->sfmt[N - 1].si);\n    for (i = 0; i < N - POS1; i++) {\n\tr = mm_recursion(&ctx->sfmt[i].si, &ctx->sfmt[i + POS1].si, r1, r2,\n\t  mask);\n\t_mm_store_si128(&array[i].si, r);\n\tr1 = r2;\n\tr2 = r;\n    }\n    for (; i < N; i++) {\n\tr = mm_recursion(&ctx->sfmt[i].si, &array[i + POS1 - N].si, r1, r2,\n\t  mask);\n\t_mm_store_si128(&array[i].si, r);\n\tr1 = r2;\n\tr2 = r;\n    }\n    /* main loop */\n    for (; i < size - N; i++) {\n\tr = mm_recursion(&array[i - N].si, &array[i + POS1 - N].si, r1, r2,\n\t\t\t mask);\n\t_mm_store_si128(&array[i].si, r);\n\tr1 = r2;\n\tr2 = r;\n    }\n    for (j = 0; j < 2 * N - size; j++) {\n\tr = _mm_load_si128(&array[j + size - N].si);\n\t_mm_store_si128(&ctx->sfmt[j].si, r);\n    }\n    for (; i < size; i++) {\n\tr = mm_recursion(&array[i - N].si, &array[i + POS1 - N].si, r1, r2,\n\t\t\t mask);\n\t_mm_store_si128(&array[i].si, r);\n\t_mm_store_si128(&ctx->sfmt[j++].si, r);\n\tr1 = r2;\n\tr2 = r;\n    }\n}\n\n#endif\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.8/deps/jemalloc/test/include/test/SFMT.h",
    "content": "/*\n * This file derives from SFMT 1.3.3\n * (http://www.math.sci.hiroshima-u.ac.jp/~m-mat/MT/SFMT/index.html), which was\n * released under the terms of the following license:\n *\n *   Copyright (c) 2006,2007 Mutsuo Saito, Makoto Matsumoto and Hiroshima\n *   University. All rights reserved.\n *\n *   Redistribution and use in source and binary forms, with or without\n *   modification, are permitted provided that the following conditions are\n *   met:\n *\n *       * Redistributions of source code must retain the above copyright\n *         notice, this list of conditions and the following disclaimer.\n *       * Redistributions in binary form must reproduce the above\n *         copyright notice, this list of conditions and the following\n *         disclaimer in the documentation and/or other materials provided\n *         with the distribution.\n *       * Neither the name of the Hiroshima University nor the names of\n *         its contributors may be used to endorse or promote products\n *         derived from this software without specific prior written\n *         permission.\n *\n *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n *   \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\n *   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\n *   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\n *   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n *   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\n *   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n *   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n *   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n *   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n *   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n/** \n * @file SFMT.h \n *\n * @brief SIMD oriented Fast Mersenne Twister(SFMT) pseudorandom\n * number generator\n *\n * @author Mutsuo Saito (Hiroshima University)\n * @author Makoto Matsumoto (Hiroshima University)\n *\n * Copyright (C) 2006, 2007 Mutsuo Saito, Makoto Matsumoto and Hiroshima\n * University. All rights reserved.\n *\n * The new BSD License is applied to this software.\n * see LICENSE.txt\n *\n * @note We assume that your system has inttypes.h.  If your system\n * doesn't have inttypes.h, you have to typedef uint32_t and uint64_t,\n * and you have to define PRIu64 and PRIx64 in this file as follows:\n * @verbatim\n typedef unsigned int uint32_t\n typedef unsigned long long uint64_t  \n #define PRIu64 \"llu\"\n #define PRIx64 \"llx\"\n@endverbatim\n * uint32_t must be exactly 32-bit unsigned integer type (no more, no\n * less), and uint64_t must be exactly 64-bit unsigned integer type.\n * PRIu64 and PRIx64 are used for printf function to print 64-bit\n * unsigned int and 64-bit unsigned int in hexadecimal format.\n */\n\n#ifndef SFMT_H\n#define SFMT_H\n\ntypedef struct sfmt_s sfmt_t;\n\nuint32_t gen_rand32(sfmt_t *ctx);\nuint32_t gen_rand32_range(sfmt_t *ctx, uint32_t limit);\nuint64_t gen_rand64(sfmt_t *ctx);\nuint64_t gen_rand64_range(sfmt_t *ctx, uint64_t limit);\nvoid fill_array32(sfmt_t *ctx, uint32_t *array, int size);\nvoid fill_array64(sfmt_t *ctx, uint64_t *array, int size);\nsfmt_t *init_gen_rand(uint32_t seed);\nsfmt_t *init_by_array(uint32_t *init_key, int key_length);\nvoid fini_gen_rand(sfmt_t *ctx);\nconst char *get_idstring(void);\nint get_min_array_size32(void);\nint get_min_array_size64(void);\n\n#ifndef JEMALLOC_ENABLE_INLINE\ndouble to_real1(uint32_t v);\ndouble genrand_real1(sfmt_t *ctx);\ndouble to_real2(uint32_t v);\ndouble genrand_real2(sfmt_t *ctx);\ndouble to_real3(uint32_t v);\ndouble genrand_real3(sfmt_t *ctx);\ndouble to_res53(uint64_t v);\ndouble to_res53_mix(uint32_t x, uint32_t y);\ndouble genrand_res53(sfmt_t *ctx);\ndouble genrand_res53_mix(sfmt_t *ctx);\n#endif\n\n#if (defined(JEMALLOC_ENABLE_INLINE) || defined(SFMT_C_))\n/* These real versions are due to Isaku Wada */\n/** generates a random number on [0,1]-real-interval */\nJEMALLOC_INLINE double to_real1(uint32_t v)\n{\n    return v * (1.0/4294967295.0); \n    /* divided by 2^32-1 */ \n}\n\n/** generates a random number on [0,1]-real-interval */\nJEMALLOC_INLINE double genrand_real1(sfmt_t *ctx)\n{\n    return to_real1(gen_rand32(ctx));\n}\n\n/** generates a random number on [0,1)-real-interval */\nJEMALLOC_INLINE double to_real2(uint32_t v)\n{\n    return v * (1.0/4294967296.0); \n    /* divided by 2^32 */\n}\n\n/** generates a random number on [0,1)-real-interval */\nJEMALLOC_INLINE double genrand_real2(sfmt_t *ctx)\n{\n    return to_real2(gen_rand32(ctx));\n}\n\n/** generates a random number on (0,1)-real-interval */\nJEMALLOC_INLINE double to_real3(uint32_t v)\n{\n    return (((double)v) + 0.5)*(1.0/4294967296.0); \n    /* divided by 2^32 */\n}\n\n/** generates a random number on (0,1)-real-interval */\nJEMALLOC_INLINE double genrand_real3(sfmt_t *ctx)\n{\n    return to_real3(gen_rand32(ctx));\n}\n/** These real versions are due to Isaku Wada */\n\n/** generates a random number on [0,1) with 53-bit resolution*/\nJEMALLOC_INLINE double to_res53(uint64_t v) \n{ \n    return v * (1.0/18446744073709551616.0L);\n}\n\n/** generates a random number on [0,1) with 53-bit resolution from two\n * 32 bit integers */\nJEMALLOC_INLINE double to_res53_mix(uint32_t x, uint32_t y) \n{ \n    return to_res53(x | ((uint64_t)y << 32));\n}\n\n/** generates a random number on [0,1) with 53-bit resolution\n */\nJEMALLOC_INLINE double genrand_res53(sfmt_t *ctx) \n{ \n    return to_res53(gen_rand64(ctx));\n} \n\n/** generates a random number on [0,1) with 53-bit resolution\n    using 32bit integer.\n */\nJEMALLOC_INLINE double genrand_res53_mix(sfmt_t *ctx) \n{ \n    uint32_t x, y;\n\n    x = gen_rand32(ctx);\n    y = gen_rand32(ctx);\n    return to_res53_mix(x, y);\n} \n#endif\n#endif\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.8/deps/jemalloc/test/include/test/btalloc.h",
    "content": "/* btalloc() provides a mechanism for allocating via permuted backtraces. */\nvoid\t*btalloc(size_t size, unsigned bits);\n\n#define\tbtalloc_n_proto(n)\t\t\t\t\t\t\\\nvoid\t*btalloc_##n(size_t size, unsigned bits);\nbtalloc_n_proto(0)\nbtalloc_n_proto(1)\n\n#define\tbtalloc_n_gen(n)\t\t\t\t\t\t\\\nvoid *\t\t\t\t\t\t\t\t\t\\\nbtalloc_##n(size_t size, unsigned bits)\t\t\t\t\t\\\n{\t\t\t\t\t\t\t\t\t\\\n\tvoid *p;\t\t\t\t\t\t\t\\\n\t\t\t\t\t\t\t\t\t\\\n\tif (bits == 0)\t\t\t\t\t\t\t\\\n\t\tp = mallocx(size, 0);\t\t\t\t\t\\\n\telse {\t\t\t\t\t\t\t\t\\\n\t\tswitch (bits & 0x1U) {\t\t\t\t\t\\\n\t\tcase 0:\t\t\t\t\t\t\t\\\n\t\t\tp = (btalloc_0(size, bits >> 1));\t\t\\\n\t\t\tbreak;\t\t\t\t\t\t\\\n\t\tcase 1:\t\t\t\t\t\t\t\\\n\t\t\tp = (btalloc_1(size, bits >> 1));\t\t\\\n\t\t\tbreak;\t\t\t\t\t\t\\\n\t\tdefault: not_reached();\t\t\t\t\t\\\n\t\t}\t\t\t\t\t\t\t\\\n\t}\t\t\t\t\t\t\t\t\\\n\t/* Intentionally sabotage tail call optimization. */\t\t\\\n\tassert_ptr_not_null(p, \"Unexpected mallocx() failure\");\t\t\\\n\treturn (p);\t\t\t\t\t\t\t\\\n}\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.8/deps/jemalloc/test/include/test/jemalloc_test.h.in",
    "content": "#include <limits.h>\n#ifndef SIZE_T_MAX\n#  define SIZE_T_MAX\tSIZE_MAX\n#endif\n#include <stdlib.h>\n#include <stdarg.h>\n#include <stdbool.h>\n#include <errno.h>\n#include <math.h>\n#include <string.h>\n#ifdef _WIN32\n#  include \"msvc_compat/strings.h\"\n#endif\n#include <sys/time.h>\n\n#ifdef _WIN32\n#  include <windows.h>\n#  include \"msvc_compat/windows_extra.h\"\n#else\n#  include <pthread.h>\n#endif\n\n/******************************************************************************/\n/*\n * Define always-enabled assertion macros, so that test assertions execute even\n * if assertions are disabled in the library code.  These definitions must\n * exist prior to including \"jemalloc/internal/util.h\".\n */\n#define\tassert(e) do {\t\t\t\t\t\t\t\\\n\tif (!(e)) {\t\t\t\t\t\t\t\\\n\t\tmalloc_printf(\t\t\t\t\t\t\\\n\t\t    \"<jemalloc>: %s:%d: Failed assertion: \\\"%s\\\"\\n\",\t\\\n\t\t    __FILE__, __LINE__, #e);\t\t\t\t\\\n\t\tabort();\t\t\t\t\t\t\\\n\t}\t\t\t\t\t\t\t\t\\\n} while (0)\n\n#define\tnot_reached() do {\t\t\t\t\t\t\\\n\tmalloc_printf(\t\t\t\t\t\t\t\\\n\t    \"<jemalloc>: %s:%d: Unreachable code reached\\n\",\t\t\\\n\t    __FILE__, __LINE__);\t\t\t\t\t\\\n\tabort();\t\t\t\t\t\t\t\\\n} while (0)\n\n#define\tnot_implemented() do {\t\t\t\t\t\t\\\n\tmalloc_printf(\"<jemalloc>: %s:%d: Not implemented\\n\",\t\t\\\n\t    __FILE__, __LINE__);\t\t\t\t\t\\\n\tabort();\t\t\t\t\t\t\t\\\n} while (0)\n\n#define\tassert_not_implemented(e) do {\t\t\t\t\t\\\n\tif (!(e))\t\t\t\t\t\t\t\\\n\t\tnot_implemented();\t\t\t\t\t\\\n} while (0)\n\n#include \"test/jemalloc_test_defs.h\"\n\n#ifdef JEMALLOC_OSSPIN\n#  include <libkern/OSAtomic.h>\n#endif\n\n#if defined(HAVE_ALTIVEC) && !defined(__APPLE__)\n#  include <altivec.h>\n#endif\n#ifdef HAVE_SSE2\n#  include <emmintrin.h>\n#endif\n\n/******************************************************************************/\n/*\n * For unit tests, expose all public and private interfaces.\n */\n#ifdef JEMALLOC_UNIT_TEST\n#  define JEMALLOC_JET\n#  define JEMALLOC_MANGLE\n#  include \"jemalloc/internal/jemalloc_internal.h\"\n\n/******************************************************************************/\n/*\n * For integration tests, expose the public jemalloc interfaces, but only\n * expose the minimum necessary internal utility code (to avoid re-implementing\n * essentially identical code within the test infrastructure).\n */\n#elif defined(JEMALLOC_INTEGRATION_TEST)\n#  define JEMALLOC_MANGLE\n#  include \"jemalloc/jemalloc@install_suffix@.h\"\n#  include \"jemalloc/internal/jemalloc_internal_defs.h\"\n#  include \"jemalloc/internal/jemalloc_internal_macros.h\"\n\n#  define JEMALLOC_N(n) @private_namespace@##n\n#  include \"jemalloc/internal/private_namespace.h\"\n\n#  define JEMALLOC_H_TYPES\n#  define JEMALLOC_H_STRUCTS\n#  define JEMALLOC_H_EXTERNS\n#  define JEMALLOC_H_INLINES\n#  include \"jemalloc/internal/util.h\"\n#  include \"jemalloc/internal/qr.h\"\n#  include \"jemalloc/internal/ql.h\"\n#  undef JEMALLOC_H_TYPES\n#  undef JEMALLOC_H_STRUCTS\n#  undef JEMALLOC_H_EXTERNS\n#  undef JEMALLOC_H_INLINES\n\n/******************************************************************************/\n/*\n * For stress tests, expose the public jemalloc interfaces with name mangling\n * so that they can be tested as e.g. malloc() and free().  Also expose the\n * public jemalloc interfaces with jet_ prefixes, so that stress tests can use\n * a separate allocator for their internal data structures.\n */\n#elif defined(JEMALLOC_STRESS_TEST)\n#  include \"jemalloc/jemalloc@install_suffix@.h\"\n\n#  include \"jemalloc/jemalloc_protos_jet.h\"\n\n#  define JEMALLOC_JET\n#  include \"jemalloc/internal/jemalloc_internal.h\"\n#  include \"jemalloc/internal/public_unnamespace.h\"\n#  undef JEMALLOC_JET\n\n#  include \"jemalloc/jemalloc_rename.h\"\n#  define JEMALLOC_MANGLE\n#  ifdef JEMALLOC_STRESS_TESTLIB\n#    include \"jemalloc/jemalloc_mangle_jet.h\"\n#  else\n#    include \"jemalloc/jemalloc_mangle.h\"\n#  endif\n\n/******************************************************************************/\n/*\n * This header does dangerous things, the effects of which only test code\n * should be subject to.\n */\n#else\n#  error \"This header cannot be included outside a testing context\"\n#endif\n\n/******************************************************************************/\n/*\n * Common test utilities.\n */\n#include \"test/btalloc.h\"\n#include \"test/math.h\"\n#include \"test/mtx.h\"\n#include \"test/mq.h\"\n#include \"test/test.h\"\n#include \"test/timer.h\"\n#include \"test/thd.h\"\n#define\tMEXP 19937\n#include \"test/SFMT.h\"\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.8/deps/jemalloc/test/include/test/jemalloc_test_defs.h.in",
    "content": "#include \"jemalloc/internal/jemalloc_internal_defs.h\"\n#include \"jemalloc/internal/jemalloc_internal_decls.h\"\n\n/*\n * For use by SFMT.  configure.ac doesn't actually define HAVE_SSE2 because its\n * dependencies are notoriously unportable in practice.\n */\n#undef HAVE_SSE2\n#undef HAVE_ALTIVEC\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.8/deps/jemalloc/test/include/test/math.h",
    "content": "#ifndef JEMALLOC_ENABLE_INLINE\ndouble\tln_gamma(double x);\ndouble\ti_gamma(double x, double p, double ln_gamma_p);\ndouble\tpt_norm(double p);\ndouble\tpt_chi2(double p, double df, double ln_gamma_df_2);\ndouble\tpt_gamma(double p, double shape, double scale, double ln_gamma_shape);\n#endif\n\n#if (defined(JEMALLOC_ENABLE_INLINE) || defined(MATH_C_))\n/*\n * Compute the natural log of Gamma(x), accurate to 10 decimal places.\n *\n * This implementation is based on:\n *\n *   Pike, M.C., I.D. Hill (1966) Algorithm 291: Logarithm of Gamma function\n *   [S14].  Communications of the ACM 9(9):684.\n */\nJEMALLOC_INLINE double\nln_gamma(double x)\n{\n\tdouble f, z;\n\n\tassert(x > 0.0);\n\n\tif (x < 7.0) {\n\t\tf = 1.0;\n\t\tz = x;\n\t\twhile (z < 7.0) {\n\t\t\tf *= z;\n\t\t\tz += 1.0;\n\t\t}\n\t\tx = z;\n\t\tf = -log(f);\n\t} else\n\t\tf = 0.0;\n\n\tz = 1.0 / (x * x);\n\n\treturn (f + (x-0.5) * log(x) - x + 0.918938533204673 +\n\t    (((-0.000595238095238 * z + 0.000793650793651) * z -\n\t    0.002777777777778) * z + 0.083333333333333) / x);\n}\n\n/*\n * Compute the incomplete Gamma ratio for [0..x], where p is the shape\n * parameter, and ln_gamma_p is ln_gamma(p).\n *\n * This implementation is based on:\n *\n *   Bhattacharjee, G.P. (1970) Algorithm AS 32: The incomplete Gamma integral.\n *   Applied Statistics 19:285-287.\n */\nJEMALLOC_INLINE double\ni_gamma(double x, double p, double ln_gamma_p)\n{\n\tdouble acu, factor, oflo, gin, term, rn, a, b, an, dif;\n\tdouble pn[6];\n\tunsigned i;\n\n\tassert(p > 0.0);\n\tassert(x >= 0.0);\n\n\tif (x == 0.0)\n\t\treturn (0.0);\n\n\tacu = 1.0e-10;\n\toflo = 1.0e30;\n\tgin = 0.0;\n\tfactor = exp(p * log(x) - x - ln_gamma_p);\n\n\tif (x <= 1.0 || x < p) {\n\t\t/* Calculation by series expansion. */\n\t\tgin = 1.0;\n\t\tterm = 1.0;\n\t\trn = p;\n\n\t\twhile (true) {\n\t\t\trn += 1.0;\n\t\t\tterm *= x / rn;\n\t\t\tgin += term;\n\t\t\tif (term <= acu) {\n\t\t\t\tgin *= factor / p;\n\t\t\t\treturn (gin);\n\t\t\t}\n\t\t}\n\t} else {\n\t\t/* Calculation by continued fraction. */\n\t\ta = 1.0 - p;\n\t\tb = a + x + 1.0;\n\t\tterm = 0.0;\n\t\tpn[0] = 1.0;\n\t\tpn[1] = x;\n\t\tpn[2] = x + 1.0;\n\t\tpn[3] = x * b;\n\t\tgin = pn[2] / pn[3];\n\n\t\twhile (true) {\n\t\t\ta += 1.0;\n\t\t\tb += 2.0;\n\t\t\tterm += 1.0;\n\t\t\tan = a * term;\n\t\t\tfor (i = 0; i < 2; i++)\n\t\t\t\tpn[i+4] = b * pn[i+2] - an * pn[i];\n\t\t\tif (pn[5] != 0.0) {\n\t\t\t\trn = pn[4] / pn[5];\n\t\t\t\tdif = fabs(gin - rn);\n\t\t\t\tif (dif <= acu && dif <= acu * rn) {\n\t\t\t\t\tgin = 1.0 - factor * gin;\n\t\t\t\t\treturn (gin);\n\t\t\t\t}\n\t\t\t\tgin = rn;\n\t\t\t}\n\t\t\tfor (i = 0; i < 4; i++)\n\t\t\t\tpn[i] = pn[i+2];\n\n\t\t\tif (fabs(pn[4]) >= oflo) {\n\t\t\t\tfor (i = 0; i < 4; i++)\n\t\t\t\t\tpn[i] /= oflo;\n\t\t\t}\n\t\t}\n\t}\n}\n\n/*\n * Given a value p in [0..1] of the lower tail area of the normal distribution,\n * compute the limit on the definite integral from [-inf..z] that satisfies p,\n * accurate to 16 decimal places.\n *\n * This implementation is based on:\n *\n *   Wichura, M.J. (1988) Algorithm AS 241: The percentage points of the normal\n *   distribution.  Applied Statistics 37(3):477-484.\n */\nJEMALLOC_INLINE double\npt_norm(double p)\n{\n\tdouble q, r, ret;\n\n\tassert(p > 0.0 && p < 1.0);\n\n\tq = p - 0.5;\n\tif (fabs(q) <= 0.425) {\n\t\t/* p close to 1/2. */\n\t\tr = 0.180625 - q * q;\n\t\treturn (q * (((((((2.5090809287301226727e3 * r +\n\t\t    3.3430575583588128105e4) * r + 6.7265770927008700853e4) * r\n\t\t    + 4.5921953931549871457e4) * r + 1.3731693765509461125e4) *\n\t\t    r + 1.9715909503065514427e3) * r + 1.3314166789178437745e2)\n\t\t    * r + 3.3871328727963666080e0) /\n\t\t    (((((((5.2264952788528545610e3 * r +\n\t\t    2.8729085735721942674e4) * r + 3.9307895800092710610e4) * r\n\t\t    + 2.1213794301586595867e4) * r + 5.3941960214247511077e3) *\n\t\t    r + 6.8718700749205790830e2) * r + 4.2313330701600911252e1)\n\t\t    * r + 1.0));\n\t} else {\n\t\tif (q < 0.0)\n\t\t\tr = p;\n\t\telse\n\t\t\tr = 1.0 - p;\n\t\tassert(r > 0.0);\n\n\t\tr = sqrt(-log(r));\n\t\tif (r <= 5.0) {\n\t\t\t/* p neither close to 1/2 nor 0 or 1. */\n\t\t\tr -= 1.6;\n\t\t\tret = ((((((((7.74545014278341407640e-4 * r +\n\t\t\t    2.27238449892691845833e-2) * r +\n\t\t\t    2.41780725177450611770e-1) * r +\n\t\t\t    1.27045825245236838258e0) * r +\n\t\t\t    3.64784832476320460504e0) * r +\n\t\t\t    5.76949722146069140550e0) * r +\n\t\t\t    4.63033784615654529590e0) * r +\n\t\t\t    1.42343711074968357734e0) /\n\t\t\t    (((((((1.05075007164441684324e-9 * r +\n\t\t\t    5.47593808499534494600e-4) * r +\n\t\t\t    1.51986665636164571966e-2)\n\t\t\t    * r + 1.48103976427480074590e-1) * r +\n\t\t\t    6.89767334985100004550e-1) * r +\n\t\t\t    1.67638483018380384940e0) * r +\n\t\t\t    2.05319162663775882187e0) * r + 1.0));\n\t\t} else {\n\t\t\t/* p near 0 or 1. */\n\t\t\tr -= 5.0;\n\t\t\tret = ((((((((2.01033439929228813265e-7 * r +\n\t\t\t    2.71155556874348757815e-5) * r +\n\t\t\t    1.24266094738807843860e-3) * r +\n\t\t\t    2.65321895265761230930e-2) * r +\n\t\t\t    2.96560571828504891230e-1) * r +\n\t\t\t    1.78482653991729133580e0) * r +\n\t\t\t    5.46378491116411436990e0) * r +\n\t\t\t    6.65790464350110377720e0) /\n\t\t\t    (((((((2.04426310338993978564e-15 * r +\n\t\t\t    1.42151175831644588870e-7) * r +\n\t\t\t    1.84631831751005468180e-5) * r +\n\t\t\t    7.86869131145613259100e-4) * r +\n\t\t\t    1.48753612908506148525e-2) * r +\n\t\t\t    1.36929880922735805310e-1) * r +\n\t\t\t    5.99832206555887937690e-1)\n\t\t\t    * r + 1.0));\n\t\t}\n\t\tif (q < 0.0)\n\t\t\tret = -ret;\n\t\treturn (ret);\n\t}\n}\n\n/*\n * Given a value p in [0..1] of the lower tail area of the Chi^2 distribution\n * with df degrees of freedom, where ln_gamma_df_2 is ln_gamma(df/2.0), compute\n * the upper limit on the definite integral from [0..z] that satisfies p,\n * accurate to 12 decimal places.\n *\n * This implementation is based on:\n *\n *   Best, D.J., D.E. Roberts (1975) Algorithm AS 91: The percentage points of\n *   the Chi^2 distribution.  Applied Statistics 24(3):385-388.\n *\n *   Shea, B.L. (1991) Algorithm AS R85: A remark on AS 91: The percentage\n *   points of the Chi^2 distribution.  Applied Statistics 40(1):233-235.\n */\nJEMALLOC_INLINE double\npt_chi2(double p, double df, double ln_gamma_df_2)\n{\n\tdouble e, aa, xx, c, ch, a, q, p1, p2, t, x, b, s1, s2, s3, s4, s5, s6;\n\tunsigned i;\n\n\tassert(p >= 0.0 && p < 1.0);\n\tassert(df > 0.0);\n\n\te = 5.0e-7;\n\taa = 0.6931471805;\n\n\txx = 0.5 * df;\n\tc = xx - 1.0;\n\n\tif (df < -1.24 * log(p)) {\n\t\t/* Starting approximation for small Chi^2. */\n\t\tch = pow(p * xx * exp(ln_gamma_df_2 + xx * aa), 1.0 / xx);\n\t\tif (ch - e < 0.0)\n\t\t\treturn (ch);\n\t} else {\n\t\tif (df > 0.32) {\n\t\t\tx = pt_norm(p);\n\t\t\t/*\n\t\t\t * Starting approximation using Wilson and Hilferty\n\t\t\t * estimate.\n\t\t\t */\n\t\t\tp1 = 0.222222 / df;\n\t\t\tch = df * pow(x * sqrt(p1) + 1.0 - p1, 3.0);\n\t\t\t/* Starting approximation for p tending to 1. */\n\t\t\tif (ch > 2.2 * df + 6.0) {\n\t\t\t\tch = -2.0 * (log(1.0 - p) - c * log(0.5 * ch) +\n\t\t\t\t    ln_gamma_df_2);\n\t\t\t}\n\t\t} else {\n\t\t\tch = 0.4;\n\t\t\ta = log(1.0 - p);\n\t\t\twhile (true) {\n\t\t\t\tq = ch;\n\t\t\t\tp1 = 1.0 + ch * (4.67 + ch);\n\t\t\t\tp2 = ch * (6.73 + ch * (6.66 + ch));\n\t\t\t\tt = -0.5 + (4.67 + 2.0 * ch) / p1 - (6.73 + ch\n\t\t\t\t    * (13.32 + 3.0 * ch)) / p2;\n\t\t\t\tch -= (1.0 - exp(a + ln_gamma_df_2 + 0.5 * ch +\n\t\t\t\t    c * aa) * p2 / p1) / t;\n\t\t\t\tif (fabs(q / ch - 1.0) - 0.01 <= 0.0)\n\t\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t}\n\n\tfor (i = 0; i < 20; i++) {\n\t\t/* Calculation of seven-term Taylor series. */\n\t\tq = ch;\n\t\tp1 = 0.5 * ch;\n\t\tif (p1 < 0.0)\n\t\t\treturn (-1.0);\n\t\tp2 = p - i_gamma(p1, xx, ln_gamma_df_2);\n\t\tt = p2 * exp(xx * aa + ln_gamma_df_2 + p1 - c * log(ch));\n\t\tb = t / ch;\n\t\ta = 0.5 * t - b * c;\n\t\ts1 = (210.0 + a * (140.0 + a * (105.0 + a * (84.0 + a * (70.0 +\n\t\t    60.0 * a))))) / 420.0;\n\t\ts2 = (420.0 + a * (735.0 + a * (966.0 + a * (1141.0 + 1278.0 *\n\t\t    a)))) / 2520.0;\n\t\ts3 = (210.0 + a * (462.0 + a * (707.0 + 932.0 * a))) / 2520.0;\n\t\ts4 = (252.0 + a * (672.0 + 1182.0 * a) + c * (294.0 + a *\n\t\t    (889.0 + 1740.0 * a))) / 5040.0;\n\t\ts5 = (84.0 + 264.0 * a + c * (175.0 + 606.0 * a)) / 2520.0;\n\t\ts6 = (120.0 + c * (346.0 + 127.0 * c)) / 5040.0;\n\t\tch += t * (1.0 + 0.5 * t * s1 - b * c * (s1 - b * (s2 - b * (s3\n\t\t    - b * (s4 - b * (s5 - b * s6))))));\n\t\tif (fabs(q / ch - 1.0) <= e)\n\t\t\tbreak;\n\t}\n\n\treturn (ch);\n}\n\n/*\n * Given a value p in [0..1] and Gamma distribution shape and scale parameters,\n * compute the upper limit on the definite integral from [0..z] that satisfies\n * p.\n */\nJEMALLOC_INLINE double\npt_gamma(double p, double shape, double scale, double ln_gamma_shape)\n{\n\n\treturn (pt_chi2(p, shape * 2.0, ln_gamma_shape) * 0.5 * scale);\n}\n#endif\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.8/deps/jemalloc/test/include/test/mq.h",
    "content": "void\tmq_nanosleep(unsigned ns);\n\n/*\n * Simple templated message queue implementation that relies on only mutexes for\n * synchronization (which reduces portability issues).  Given the following\n * setup:\n *\n *   typedef struct mq_msg_s mq_msg_t;\n *   struct mq_msg_s {\n *           mq_msg(mq_msg_t) link;\n *           [message data]\n *   };\n *   mq_gen(, mq_, mq_t, mq_msg_t, link)\n *\n * The API is as follows:\n *\n *   bool mq_init(mq_t *mq);\n *   void mq_fini(mq_t *mq);\n *   unsigned mq_count(mq_t *mq);\n *   mq_msg_t *mq_tryget(mq_t *mq);\n *   mq_msg_t *mq_get(mq_t *mq);\n *   void mq_put(mq_t *mq, mq_msg_t *msg);\n *\n * The message queue linkage embedded in each message is to be treated as\n * externally opaque (no need to initialize or clean up externally).  mq_fini()\n * does not perform any cleanup of messages, since it knows nothing of their\n * payloads.\n */\n#define\tmq_msg(a_mq_msg_type)\tql_elm(a_mq_msg_type)\n\n#define\tmq_gen(a_attr, a_prefix, a_mq_type, a_mq_msg_type, a_field)\t\\\ntypedef struct {\t\t\t\t\t\t\t\\\n\tmtx_t\t\t\tlock;\t\t\t\t\t\\\n\tql_head(a_mq_msg_type)\tmsgs;\t\t\t\t\t\\\n\tunsigned\t\tcount;\t\t\t\t\t\\\n} a_mq_type;\t\t\t\t\t\t\t\t\\\na_attr bool\t\t\t\t\t\t\t\t\\\na_prefix##init(a_mq_type *mq) {\t\t\t\t\t\t\\\n\t\t\t\t\t\t\t\t\t\\\n\tif (mtx_init(&mq->lock))\t\t\t\t\t\\\n\t\treturn (true);\t\t\t\t\t\t\\\n\tql_new(&mq->msgs);\t\t\t\t\t\t\\\n\tmq->count = 0;\t\t\t\t\t\t\t\\\n\treturn (false);\t\t\t\t\t\t\t\\\n}\t\t\t\t\t\t\t\t\t\\\na_attr void\t\t\t\t\t\t\t\t\\\na_prefix##fini(a_mq_type *mq)\t\t\t\t\t\t\\\n{\t\t\t\t\t\t\t\t\t\\\n\t\t\t\t\t\t\t\t\t\\\n\tmtx_fini(&mq->lock);\t\t\t\t\t\t\\\n}\t\t\t\t\t\t\t\t\t\\\na_attr unsigned\t\t\t\t\t\t\t\t\\\na_prefix##count(a_mq_type *mq)\t\t\t\t\t\t\\\n{\t\t\t\t\t\t\t\t\t\\\n\tunsigned count;\t\t\t\t\t\t\t\\\n\t\t\t\t\t\t\t\t\t\\\n\tmtx_lock(&mq->lock);\t\t\t\t\t\t\\\n\tcount = mq->count;\t\t\t\t\t\t\\\n\tmtx_unlock(&mq->lock);\t\t\t\t\t\t\\\n\treturn (count);\t\t\t\t\t\t\t\\\n}\t\t\t\t\t\t\t\t\t\\\na_attr a_mq_msg_type *\t\t\t\t\t\t\t\\\na_prefix##tryget(a_mq_type *mq)\t\t\t\t\t\t\\\n{\t\t\t\t\t\t\t\t\t\\\n\ta_mq_msg_type *msg;\t\t\t\t\t\t\\\n\t\t\t\t\t\t\t\t\t\\\n\tmtx_lock(&mq->lock);\t\t\t\t\t\t\\\n\tmsg = ql_first(&mq->msgs);\t\t\t\t\t\\\n\tif (msg != NULL) {\t\t\t\t\t\t\\\n\t\tql_head_remove(&mq->msgs, a_mq_msg_type, a_field);\t\\\n\t\tmq->count--;\t\t\t\t\t\t\\\n\t}\t\t\t\t\t\t\t\t\\\n\tmtx_unlock(&mq->lock);\t\t\t\t\t\t\\\n\treturn (msg);\t\t\t\t\t\t\t\\\n}\t\t\t\t\t\t\t\t\t\\\na_attr a_mq_msg_type *\t\t\t\t\t\t\t\\\na_prefix##get(a_mq_type *mq)\t\t\t\t\t\t\\\n{\t\t\t\t\t\t\t\t\t\\\n\ta_mq_msg_type *msg;\t\t\t\t\t\t\\\n\tunsigned ns;\t\t\t\t\t\t\t\\\n\t\t\t\t\t\t\t\t\t\\\n\tmsg = a_prefix##tryget(mq);\t\t\t\t\t\\\n\tif (msg != NULL)\t\t\t\t\t\t\\\n\t\treturn (msg);\t\t\t\t\t\t\\\n\t\t\t\t\t\t\t\t\t\\\n\tns = 1;\t\t\t\t\t\t\t\t\\\n\twhile (true) {\t\t\t\t\t\t\t\\\n\t\tmq_nanosleep(ns);\t\t\t\t\t\\\n\t\tmsg = a_prefix##tryget(mq);\t\t\t\t\\\n\t\tif (msg != NULL)\t\t\t\t\t\\\n\t\t\treturn (msg);\t\t\t\t\t\\\n\t\tif (ns < 1000*1000*1000) {\t\t\t\t\\\n\t\t\t/* Double sleep time, up to max 1 second. */\t\\\n\t\t\tns <<= 1;\t\t\t\t\t\\\n\t\t\tif (ns > 1000*1000*1000)\t\t\t\\\n\t\t\t\tns = 1000*1000*1000;\t\t\t\\\n\t\t}\t\t\t\t\t\t\t\\\n\t}\t\t\t\t\t\t\t\t\\\n}\t\t\t\t\t\t\t\t\t\\\na_attr void\t\t\t\t\t\t\t\t\\\na_prefix##put(a_mq_type *mq, a_mq_msg_type *msg)\t\t\t\\\n{\t\t\t\t\t\t\t\t\t\\\n\t\t\t\t\t\t\t\t\t\\\n\tmtx_lock(&mq->lock);\t\t\t\t\t\t\\\n\tql_elm_new(msg, a_field);\t\t\t\t\t\\\n\tql_tail_insert(&mq->msgs, msg, a_field);\t\t\t\\\n\tmq->count++;\t\t\t\t\t\t\t\\\n\tmtx_unlock(&mq->lock);\t\t\t\t\t\t\\\n}\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.8/deps/jemalloc/test/include/test/mtx.h",
    "content": "/*\n * mtx is a slightly simplified version of malloc_mutex.  This code duplication\n * is unfortunate, but there are allocator bootstrapping considerations that\n * would leak into the test infrastructure if malloc_mutex were used directly\n * in tests.\n */\n\ntypedef struct {\n#ifdef _WIN32\n\tCRITICAL_SECTION\tlock;\n#elif (defined(JEMALLOC_OSSPIN))\n\tOSSpinLock\t\tlock;\n#else\n\tpthread_mutex_t\t\tlock;\n#endif\n} mtx_t;\n\nbool\tmtx_init(mtx_t *mtx);\nvoid\tmtx_fini(mtx_t *mtx);\nvoid\tmtx_lock(mtx_t *mtx);\nvoid\tmtx_unlock(mtx_t *mtx);\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.8/deps/jemalloc/test/include/test/test.h",
    "content": "#define\tASSERT_BUFSIZE\t256\n\n#define\tassert_cmp(t, a, b, cmp, neg_cmp, pri, ...) do {\t\t\\\n\tt a_ = (a);\t\t\t\t\t\t\t\\\n\tt b_ = (b);\t\t\t\t\t\t\t\\\n\tif (!(a_ cmp b_)) {\t\t\t\t\t\t\\\n\t\tchar prefix[ASSERT_BUFSIZE];\t\t\t\t\\\n\t\tchar message[ASSERT_BUFSIZE];\t\t\t\t\\\n\t\tmalloc_snprintf(prefix, sizeof(prefix),\t\t\t\\\n\t\t    \"%s:%s:%d: Failed assertion: \"\t\t\t\\\n\t\t    \"(%s) \"#cmp\" (%s) --> \"\t\t\t\t\\\n\t\t    \"%\"pri\" \"#neg_cmp\" %\"pri\": \",\t\t\t\\\n\t\t    __func__, __FILE__, __LINE__,\t\t\t\\\n\t\t    #a, #b, a_, b_);\t\t\t\t\t\\\n\t\tmalloc_snprintf(message, sizeof(message), __VA_ARGS__);\t\\\n\t\tp_test_fail(prefix, message);\t\t\t\t\\\n\t}\t\t\t\t\t\t\t\t\\\n} while (0)\n\n#define\tassert_ptr_eq(a, b, ...)\tassert_cmp(void *, a, b, ==,\t\\\n    !=, \"p\", __VA_ARGS__)\n#define\tassert_ptr_ne(a, b, ...)\tassert_cmp(void *, a, b, !=,\t\\\n    ==, \"p\", __VA_ARGS__)\n#define\tassert_ptr_null(a, ...)\t\tassert_cmp(void *, a, NULL, ==,\t\\\n    !=, \"p\", __VA_ARGS__)\n#define\tassert_ptr_not_null(a, ...)\tassert_cmp(void *, a, NULL, !=,\t\\\n    ==, \"p\", __VA_ARGS__)\n\n#define\tassert_c_eq(a, b, ...)\tassert_cmp(char, a, b, ==, !=, \"c\", __VA_ARGS__)\n#define\tassert_c_ne(a, b, ...)\tassert_cmp(char, a, b, !=, ==, \"c\", __VA_ARGS__)\n#define\tassert_c_lt(a, b, ...)\tassert_cmp(char, a, b, <, >=, \"c\", __VA_ARGS__)\n#define\tassert_c_le(a, b, ...)\tassert_cmp(char, a, b, <=, >, \"c\", __VA_ARGS__)\n#define\tassert_c_ge(a, b, ...)\tassert_cmp(char, a, b, >=, <, \"c\", __VA_ARGS__)\n#define\tassert_c_gt(a, b, ...)\tassert_cmp(char, a, b, >, <=, \"c\", __VA_ARGS__)\n\n#define\tassert_x_eq(a, b, ...)\tassert_cmp(int, a, b, ==, !=, \"#x\", __VA_ARGS__)\n#define\tassert_x_ne(a, b, ...)\tassert_cmp(int, a, b, !=, ==, \"#x\", __VA_ARGS__)\n#define\tassert_x_lt(a, b, ...)\tassert_cmp(int, a, b, <, >=, \"#x\", __VA_ARGS__)\n#define\tassert_x_le(a, b, ...)\tassert_cmp(int, a, b, <=, >, \"#x\", __VA_ARGS__)\n#define\tassert_x_ge(a, b, ...)\tassert_cmp(int, a, b, >=, <, \"#x\", __VA_ARGS__)\n#define\tassert_x_gt(a, b, ...)\tassert_cmp(int, a, b, >, <=, \"#x\", __VA_ARGS__)\n\n#define\tassert_d_eq(a, b, ...)\tassert_cmp(int, a, b, ==, !=, \"d\", __VA_ARGS__)\n#define\tassert_d_ne(a, b, ...)\tassert_cmp(int, a, b, !=, ==, \"d\", __VA_ARGS__)\n#define\tassert_d_lt(a, b, ...)\tassert_cmp(int, a, b, <, >=, \"d\", __VA_ARGS__)\n#define\tassert_d_le(a, b, ...)\tassert_cmp(int, a, b, <=, >, \"d\", __VA_ARGS__)\n#define\tassert_d_ge(a, b, ...)\tassert_cmp(int, a, b, >=, <, \"d\", __VA_ARGS__)\n#define\tassert_d_gt(a, b, ...)\tassert_cmp(int, a, b, >, <=, \"d\", __VA_ARGS__)\n\n#define\tassert_u_eq(a, b, ...)\tassert_cmp(int, a, b, ==, !=, \"u\", __VA_ARGS__)\n#define\tassert_u_ne(a, b, ...)\tassert_cmp(int, a, b, !=, ==, \"u\", __VA_ARGS__)\n#define\tassert_u_lt(a, b, ...)\tassert_cmp(int, a, b, <, >=, \"u\", __VA_ARGS__)\n#define\tassert_u_le(a, b, ...)\tassert_cmp(int, a, b, <=, >, \"u\", __VA_ARGS__)\n#define\tassert_u_ge(a, b, ...)\tassert_cmp(int, a, b, >=, <, \"u\", __VA_ARGS__)\n#define\tassert_u_gt(a, b, ...)\tassert_cmp(int, a, b, >, <=, \"u\", __VA_ARGS__)\n\n#define\tassert_ld_eq(a, b, ...)\tassert_cmp(long, a, b, ==,\t\\\n    !=, \"ld\", __VA_ARGS__)\n#define\tassert_ld_ne(a, b, ...)\tassert_cmp(long, a, b, !=,\t\\\n    ==, \"ld\", __VA_ARGS__)\n#define\tassert_ld_lt(a, b, ...)\tassert_cmp(long, a, b, <,\t\\\n    >=, \"ld\", __VA_ARGS__)\n#define\tassert_ld_le(a, b, ...)\tassert_cmp(long, a, b, <=,\t\\\n    >, \"ld\", __VA_ARGS__)\n#define\tassert_ld_ge(a, b, ...)\tassert_cmp(long, a, b, >=,\t\\\n    <, \"ld\", __VA_ARGS__)\n#define\tassert_ld_gt(a, b, ...)\tassert_cmp(long, a, b, >,\t\\\n    <=, \"ld\", __VA_ARGS__)\n\n#define\tassert_lu_eq(a, b, ...)\tassert_cmp(unsigned long,\t\\\n    a, b, ==, !=, \"lu\", __VA_ARGS__)\n#define\tassert_lu_ne(a, b, ...)\tassert_cmp(unsigned long,\t\\\n    a, b, !=, ==, \"lu\", __VA_ARGS__)\n#define\tassert_lu_lt(a, b, ...)\tassert_cmp(unsigned long,\t\\\n    a, b, <, >=, \"lu\", __VA_ARGS__)\n#define\tassert_lu_le(a, b, ...)\tassert_cmp(unsigned long,\t\\\n    a, b, <=, >, \"lu\", __VA_ARGS__)\n#define\tassert_lu_ge(a, b, ...)\tassert_cmp(unsigned long,\t\\\n    a, b, >=, <, \"lu\", __VA_ARGS__)\n#define\tassert_lu_gt(a, b, ...)\tassert_cmp(unsigned long,\t\\\n    a, b, >, <=, \"lu\", __VA_ARGS__)\n\n#define\tassert_qd_eq(a, b, ...)\tassert_cmp(long long, a, b, ==,\t\\\n    !=, \"qd\", __VA_ARGS__)\n#define\tassert_qd_ne(a, b, ...)\tassert_cmp(long long, a, b, !=,\t\\\n    ==, \"qd\", __VA_ARGS__)\n#define\tassert_qd_lt(a, b, ...)\tassert_cmp(long long, a, b, <,\t\\\n    >=, \"qd\", __VA_ARGS__)\n#define\tassert_qd_le(a, b, ...)\tassert_cmp(long long, a, b, <=,\t\\\n    >, \"qd\", __VA_ARGS__)\n#define\tassert_qd_ge(a, b, ...)\tassert_cmp(long long, a, b, >=,\t\\\n    <, \"qd\", __VA_ARGS__)\n#define\tassert_qd_gt(a, b, ...)\tassert_cmp(long long, a, b, >,\t\\\n    <=, \"qd\", __VA_ARGS__)\n\n#define\tassert_qu_eq(a, b, ...)\tassert_cmp(unsigned long long,\t\\\n    a, b, ==, !=, \"qu\", __VA_ARGS__)\n#define\tassert_qu_ne(a, b, ...)\tassert_cmp(unsigned long long,\t\\\n    a, b, !=, ==, \"qu\", __VA_ARGS__)\n#define\tassert_qu_lt(a, b, ...)\tassert_cmp(unsigned long long,\t\\\n    a, b, <, >=, \"qu\", __VA_ARGS__)\n#define\tassert_qu_le(a, b, ...)\tassert_cmp(unsigned long long,\t\\\n    a, b, <=, >, \"qu\", __VA_ARGS__)\n#define\tassert_qu_ge(a, b, ...)\tassert_cmp(unsigned long long,\t\\\n    a, b, >=, <, \"qu\", __VA_ARGS__)\n#define\tassert_qu_gt(a, b, ...)\tassert_cmp(unsigned long long,\t\\\n    a, b, >, <=, \"qu\", __VA_ARGS__)\n\n#define\tassert_jd_eq(a, b, ...)\tassert_cmp(intmax_t, a, b, ==,\t\\\n    !=, \"jd\", __VA_ARGS__)\n#define\tassert_jd_ne(a, b, ...)\tassert_cmp(intmax_t, a, b, !=,\t\\\n    ==, \"jd\", __VA_ARGS__)\n#define\tassert_jd_lt(a, b, ...)\tassert_cmp(intmax_t, a, b, <,\t\\\n    >=, \"jd\", __VA_ARGS__)\n#define\tassert_jd_le(a, b, ...)\tassert_cmp(intmax_t, a, b, <=,\t\\\n    >, \"jd\", __VA_ARGS__)\n#define\tassert_jd_ge(a, b, ...)\tassert_cmp(intmax_t, a, b, >=,\t\\\n    <, \"jd\", __VA_ARGS__)\n#define\tassert_jd_gt(a, b, ...)\tassert_cmp(intmax_t, a, b, >,\t\\\n    <=, \"jd\", __VA_ARGS__)\n\n#define\tassert_ju_eq(a, b, ...)\tassert_cmp(uintmax_t, a, b, ==,\t\\\n    !=, \"ju\", __VA_ARGS__)\n#define\tassert_ju_ne(a, b, ...)\tassert_cmp(uintmax_t, a, b, !=,\t\\\n    ==, \"ju\", __VA_ARGS__)\n#define\tassert_ju_lt(a, b, ...)\tassert_cmp(uintmax_t, a, b, <,\t\\\n    >=, \"ju\", __VA_ARGS__)\n#define\tassert_ju_le(a, b, ...)\tassert_cmp(uintmax_t, a, b, <=,\t\\\n    >, \"ju\", __VA_ARGS__)\n#define\tassert_ju_ge(a, b, ...)\tassert_cmp(uintmax_t, a, b, >=,\t\\\n    <, \"ju\", __VA_ARGS__)\n#define\tassert_ju_gt(a, b, ...)\tassert_cmp(uintmax_t, a, b, >,\t\\\n    <=, \"ju\", __VA_ARGS__)\n\n#define\tassert_zd_eq(a, b, ...)\tassert_cmp(ssize_t, a, b, ==,\t\\\n    !=, \"zd\", __VA_ARGS__)\n#define\tassert_zd_ne(a, b, ...)\tassert_cmp(ssize_t, a, b, !=,\t\\\n    ==, \"zd\", __VA_ARGS__)\n#define\tassert_zd_lt(a, b, ...)\tassert_cmp(ssize_t, a, b, <,\t\\\n    >=, \"zd\", __VA_ARGS__)\n#define\tassert_zd_le(a, b, ...)\tassert_cmp(ssize_t, a, b, <=,\t\\\n    >, \"zd\", __VA_ARGS__)\n#define\tassert_zd_ge(a, b, ...)\tassert_cmp(ssize_t, a, b, >=,\t\\\n    <, \"zd\", __VA_ARGS__)\n#define\tassert_zd_gt(a, b, ...)\tassert_cmp(ssize_t, a, b, >,\t\\\n    <=, \"zd\", __VA_ARGS__)\n\n#define\tassert_zu_eq(a, b, ...)\tassert_cmp(size_t, a, b, ==,\t\\\n    !=, \"zu\", __VA_ARGS__)\n#define\tassert_zu_ne(a, b, ...)\tassert_cmp(size_t, a, b, !=,\t\\\n    ==, \"zu\", __VA_ARGS__)\n#define\tassert_zu_lt(a, b, ...)\tassert_cmp(size_t, a, b, <,\t\\\n    >=, \"zu\", __VA_ARGS__)\n#define\tassert_zu_le(a, b, ...)\tassert_cmp(size_t, a, b, <=,\t\\\n    >, \"zu\", __VA_ARGS__)\n#define\tassert_zu_ge(a, b, ...)\tassert_cmp(size_t, a, b, >=,\t\\\n    <, \"zu\", __VA_ARGS__)\n#define\tassert_zu_gt(a, b, ...)\tassert_cmp(size_t, a, b, >,\t\\\n    <=, \"zu\", __VA_ARGS__)\n\n#define\tassert_d32_eq(a, b, ...)\tassert_cmp(int32_t, a, b, ==,\t\\\n    !=, FMTd32, __VA_ARGS__)\n#define\tassert_d32_ne(a, b, ...)\tassert_cmp(int32_t, a, b, !=,\t\\\n    ==, FMTd32, __VA_ARGS__)\n#define\tassert_d32_lt(a, b, ...)\tassert_cmp(int32_t, a, b, <,\t\\\n    >=, FMTd32, __VA_ARGS__)\n#define\tassert_d32_le(a, b, ...)\tassert_cmp(int32_t, a, b, <=,\t\\\n    >, FMTd32, __VA_ARGS__)\n#define\tassert_d32_ge(a, b, ...)\tassert_cmp(int32_t, a, b, >=,\t\\\n    <, FMTd32, __VA_ARGS__)\n#define\tassert_d32_gt(a, b, ...)\tassert_cmp(int32_t, a, b, >,\t\\\n    <=, FMTd32, __VA_ARGS__)\n\n#define\tassert_u32_eq(a, b, ...)\tassert_cmp(uint32_t, a, b, ==,\t\\\n    !=, FMTu32, __VA_ARGS__)\n#define\tassert_u32_ne(a, b, ...)\tassert_cmp(uint32_t, a, b, !=,\t\\\n    ==, FMTu32, __VA_ARGS__)\n#define\tassert_u32_lt(a, b, ...)\tassert_cmp(uint32_t, a, b, <,\t\\\n    >=, FMTu32, __VA_ARGS__)\n#define\tassert_u32_le(a, b, ...)\tassert_cmp(uint32_t, a, b, <=,\t\\\n    >, FMTu32, __VA_ARGS__)\n#define\tassert_u32_ge(a, b, ...)\tassert_cmp(uint32_t, a, b, >=,\t\\\n    <, FMTu32, __VA_ARGS__)\n#define\tassert_u32_gt(a, b, ...)\tassert_cmp(uint32_t, a, b, >,\t\\\n    <=, FMTu32, __VA_ARGS__)\n\n#define\tassert_d64_eq(a, b, ...)\tassert_cmp(int64_t, a, b, ==,\t\\\n    !=, FMTd64, __VA_ARGS__)\n#define\tassert_d64_ne(a, b, ...)\tassert_cmp(int64_t, a, b, !=,\t\\\n    ==, FMTd64, __VA_ARGS__)\n#define\tassert_d64_lt(a, b, ...)\tassert_cmp(int64_t, a, b, <,\t\\\n    >=, FMTd64, __VA_ARGS__)\n#define\tassert_d64_le(a, b, ...)\tassert_cmp(int64_t, a, b, <=,\t\\\n    >, FMTd64, __VA_ARGS__)\n#define\tassert_d64_ge(a, b, ...)\tassert_cmp(int64_t, a, b, >=,\t\\\n    <, FMTd64, __VA_ARGS__)\n#define\tassert_d64_gt(a, b, ...)\tassert_cmp(int64_t, a, b, >,\t\\\n    <=, FMTd64, __VA_ARGS__)\n\n#define\tassert_u64_eq(a, b, ...)\tassert_cmp(uint64_t, a, b, ==,\t\\\n    !=, FMTu64, __VA_ARGS__)\n#define\tassert_u64_ne(a, b, ...)\tassert_cmp(uint64_t, a, b, !=,\t\\\n    ==, FMTu64, __VA_ARGS__)\n#define\tassert_u64_lt(a, b, ...)\tassert_cmp(uint64_t, a, b, <,\t\\\n    >=, FMTu64, __VA_ARGS__)\n#define\tassert_u64_le(a, b, ...)\tassert_cmp(uint64_t, a, b, <=,\t\\\n    >, FMTu64, __VA_ARGS__)\n#define\tassert_u64_ge(a, b, ...)\tassert_cmp(uint64_t, a, b, >=,\t\\\n    <, FMTu64, __VA_ARGS__)\n#define\tassert_u64_gt(a, b, ...)\tassert_cmp(uint64_t, a, b, >,\t\\\n    <=, FMTu64, __VA_ARGS__)\n\n#define\tassert_b_eq(a, b, ...) do {\t\t\t\t\t\\\n\tbool a_ = (a);\t\t\t\t\t\t\t\\\n\tbool b_ = (b);\t\t\t\t\t\t\t\\\n\tif (!(a_ == b_)) {\t\t\t\t\t\t\\\n\t\tchar prefix[ASSERT_BUFSIZE];\t\t\t\t\\\n\t\tchar message[ASSERT_BUFSIZE];\t\t\t\t\\\n\t\tmalloc_snprintf(prefix, sizeof(prefix),\t\t\t\\\n\t\t    \"%s:%s:%d: Failed assertion: \"\t\t\t\\\n\t\t    \"(%s) == (%s) --> %s != %s: \",\t\t\t\\\n\t\t    __func__, __FILE__, __LINE__,\t\t\t\\\n\t\t    #a, #b, a_ ? \"true\" : \"false\",\t\t\t\\\n\t\t    b_ ? \"true\" : \"false\");\t\t\t\t\\\n\t\tmalloc_snprintf(message, sizeof(message), __VA_ARGS__);\t\\\n\t\tp_test_fail(prefix, message);\t\t\t\t\\\n\t}\t\t\t\t\t\t\t\t\\\n} while (0)\n#define\tassert_b_ne(a, b, ...) do {\t\t\t\t\t\\\n\tbool a_ = (a);\t\t\t\t\t\t\t\\\n\tbool b_ = (b);\t\t\t\t\t\t\t\\\n\tif (!(a_ != b_)) {\t\t\t\t\t\t\\\n\t\tchar prefix[ASSERT_BUFSIZE];\t\t\t\t\\\n\t\tchar message[ASSERT_BUFSIZE];\t\t\t\t\\\n\t\tmalloc_snprintf(prefix, sizeof(prefix),\t\t\t\\\n\t\t    \"%s:%s:%d: Failed assertion: \"\t\t\t\\\n\t\t    \"(%s) != (%s) --> %s == %s: \",\t\t\t\\\n\t\t    __func__, __FILE__, __LINE__,\t\t\t\\\n\t\t    #a, #b, a_ ? \"true\" : \"false\",\t\t\t\\\n\t\t    b_ ? \"true\" : \"false\");\t\t\t\t\\\n\t\tmalloc_snprintf(message, sizeof(message), __VA_ARGS__);\t\\\n\t\tp_test_fail(prefix, message);\t\t\t\t\\\n\t}\t\t\t\t\t\t\t\t\\\n} while (0)\n#define\tassert_true(a, ...)\tassert_b_eq(a, true, __VA_ARGS__)\n#define\tassert_false(a, ...)\tassert_b_eq(a, false, __VA_ARGS__)\n\n#define\tassert_str_eq(a, b, ...) do {\t\t\t\t\\\n\tif (strcmp((a), (b))) {\t\t\t\t\t\t\\\n\t\tchar prefix[ASSERT_BUFSIZE];\t\t\t\t\\\n\t\tchar message[ASSERT_BUFSIZE];\t\t\t\t\\\n\t\tmalloc_snprintf(prefix, sizeof(prefix),\t\t\t\\\n\t\t    \"%s:%s:%d: Failed assertion: \"\t\t\t\\\n\t\t    \"(%s) same as (%s) --> \"\t\t\t\t\\\n\t\t    \"\\\"%s\\\" differs from \\\"%s\\\": \",\t\t\t\\\n\t\t    __func__, __FILE__, __LINE__, #a, #b, a, b);\t\\\n\t\tmalloc_snprintf(message, sizeof(message), __VA_ARGS__);\t\\\n\t\tp_test_fail(prefix, message);\t\t\t\t\\\n\t}\t\t\t\t\t\t\t\t\\\n} while (0)\n#define\tassert_str_ne(a, b, ...) do {\t\t\t\t\\\n\tif (!strcmp((a), (b))) {\t\t\t\t\t\\\n\t\tchar prefix[ASSERT_BUFSIZE];\t\t\t\t\\\n\t\tchar message[ASSERT_BUFSIZE];\t\t\t\t\\\n\t\tmalloc_snprintf(prefix, sizeof(prefix),\t\t\t\\\n\t\t    \"%s:%s:%d: Failed assertion: \"\t\t\t\\\n\t\t    \"(%s) differs from (%s) --> \"\t\t\t\\\n\t\t    \"\\\"%s\\\" same as \\\"%s\\\": \",\t\t\t\t\\\n\t\t    __func__, __FILE__, __LINE__, #a, #b, a, b);\t\\\n\t\tmalloc_snprintf(message, sizeof(message), __VA_ARGS__);\t\\\n\t\tp_test_fail(prefix, message);\t\t\t\t\\\n\t}\t\t\t\t\t\t\t\t\\\n} while (0)\n\n#define\tassert_not_reached(...) do {\t\t\t\t\t\\\n\tchar prefix[ASSERT_BUFSIZE];\t\t\t\t\t\\\n\tchar message[ASSERT_BUFSIZE];\t\t\t\t\t\\\n\tmalloc_snprintf(prefix, sizeof(prefix),\t\t\t\t\\\n\t    \"%s:%s:%d: Unreachable code reached: \",\t\t\t\\\n\t    __func__, __FILE__, __LINE__);\t\t\t\t\\\n\tmalloc_snprintf(message, sizeof(message), __VA_ARGS__);\t\t\\\n\tp_test_fail(prefix, message);\t\t\t\t\t\\\n} while (0)\n\n/*\n * If this enum changes, corresponding changes in test/test.sh.in are also\n * necessary.\n */\ntypedef enum {\n\ttest_status_pass = 0,\n\ttest_status_skip = 1,\n\ttest_status_fail = 2,\n\n\ttest_status_count = 3\n} test_status_t;\n\ntypedef void (test_t)(void);\n\n#define\tTEST_BEGIN(f)\t\t\t\t\t\t\t\\\nstatic void\t\t\t\t\t\t\t\t\\\nf(void)\t\t\t\t\t\t\t\t\t\\\n{\t\t\t\t\t\t\t\t\t\\\n\tp_test_init(#f);\n\n#define\tTEST_END\t\t\t\t\t\t\t\\\n\tgoto label_test_end;\t\t\t\t\t\t\\\nlabel_test_end:\t\t\t\t\t\t\t\t\\\n\tp_test_fini();\t\t\t\t\t\t\t\\\n}\n\n#define\ttest(...)\t\t\t\t\t\t\t\\\n\tp_test(__VA_ARGS__, NULL)\n\n#define\ttest_skip_if(e) do {\t\t\t\t\t\t\\\n\tif (e) {\t\t\t\t\t\t\t\\\n\t\ttest_skip(\"%s:%s:%d: Test skipped: (%s)\",\t\t\\\n\t\t    __func__, __FILE__, __LINE__, #e);\t\t\t\\\n\t\tgoto label_test_end;\t\t\t\t\t\\\n\t}\t\t\t\t\t\t\t\t\\\n} while (0)\n\nvoid\ttest_skip(const char *format, ...) JEMALLOC_FORMAT_PRINTF(1, 2);\nvoid\ttest_fail(const char *format, ...) JEMALLOC_FORMAT_PRINTF(1, 2);\n\n/* For private use by macros. */\ntest_status_t\tp_test(test_t *t, ...);\nvoid\tp_test_init(const char *name);\nvoid\tp_test_fini(void);\nvoid\tp_test_fail(const char *prefix, const char *message);\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.8/deps/jemalloc/test/include/test/thd.h",
    "content": "/* Abstraction layer for threading in tests. */\n#ifdef _WIN32\ntypedef HANDLE thd_t;\n#else\ntypedef pthread_t thd_t;\n#endif\n\nvoid\tthd_create(thd_t *thd, void *(*proc)(void *), void *arg);\nvoid\tthd_join(thd_t thd, void **ret);\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.8/deps/jemalloc/test/include/test/timer.h",
    "content": "/* Simple timer, for use in benchmark reporting. */\n\n#include <unistd.h>\n#include <sys/time.h>\n\n#define JEMALLOC_CLOCK_GETTIME defined(_POSIX_MONOTONIC_CLOCK) \\\n    && _POSIX_MONOTONIC_CLOCK >= 0\n\ntypedef struct {\n#ifdef _WIN32\n\tFILETIME ft0;\n\tFILETIME ft1;\n#elif JEMALLOC_CLOCK_GETTIME\n\tstruct timespec ts0;\n\tstruct timespec ts1;\n\tint clock_id;\n#else\n\tstruct timeval tv0;\n\tstruct timeval tv1;\n#endif\n} timedelta_t;\n\nvoid\ttimer_start(timedelta_t *timer);\nvoid\ttimer_stop(timedelta_t *timer);\nuint64_t\ttimer_usec(const timedelta_t *timer);\nvoid\ttimer_ratio(timedelta_t *a, timedelta_t *b, char *buf, size_t buflen);\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.8/deps/jemalloc/test/integration/MALLOCX_ARENA.c",
    "content": "#include \"test/jemalloc_test.h\"\n\n#define\tNTHREADS 10\n\nstatic bool have_dss =\n#ifdef JEMALLOC_DSS\n    true\n#else\n    false\n#endif\n    ;\n\nvoid *\nthd_start(void *arg)\n{\n\tunsigned thread_ind = (unsigned)(uintptr_t)arg;\n\tunsigned arena_ind;\n\tvoid *p;\n\tsize_t sz;\n\n\tsz = sizeof(arena_ind);\n\tassert_d_eq(mallctl(\"arenas.extend\", &arena_ind, &sz, NULL, 0), 0,\n\t    \"Error in arenas.extend\");\n\n\tif (thread_ind % 4 != 3) {\n\t\tsize_t mib[3];\n\t\tsize_t miblen = sizeof(mib) / sizeof(size_t);\n\t\tconst char *dss_precs[] = {\"disabled\", \"primary\", \"secondary\"};\n\t\tunsigned prec_ind = thread_ind %\n\t\t    (sizeof(dss_precs)/sizeof(char*));\n\t\tconst char *dss = dss_precs[prec_ind];\n\t\tint expected_err = (have_dss || prec_ind == 0) ? 0 : EFAULT;\n\t\tassert_d_eq(mallctlnametomib(\"arena.0.dss\", mib, &miblen), 0,\n\t\t    \"Error in mallctlnametomib()\");\n\t\tmib[1] = arena_ind;\n\t\tassert_d_eq(mallctlbymib(mib, miblen, NULL, NULL, (void *)&dss,\n\t\t    sizeof(const char *)), expected_err,\n\t\t    \"Error in mallctlbymib()\");\n\t}\n\n\tp = mallocx(1, MALLOCX_ARENA(arena_ind));\n\tassert_ptr_not_null(p, \"Unexpected mallocx() error\");\n\tdallocx(p, 0);\n\n\treturn (NULL);\n}\n\nTEST_BEGIN(test_MALLOCX_ARENA)\n{\n\tthd_t thds[NTHREADS];\n\tunsigned i;\n\n\tfor (i = 0; i < NTHREADS; i++) {\n\t\tthd_create(&thds[i], thd_start,\n\t\t    (void *)(uintptr_t)i);\n\t}\n\n\tfor (i = 0; i < NTHREADS; i++)\n\t\tthd_join(thds[i], NULL);\n}\nTEST_END\n\nint\nmain(void)\n{\n\n\treturn (test(\n\t    test_MALLOCX_ARENA));\n}\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.8/deps/jemalloc/test/integration/aligned_alloc.c",
    "content": "#include \"test/jemalloc_test.h\"\n\n#define\tCHUNK 0x400000\n/* #define MAXALIGN ((size_t)UINT64_C(0x80000000000)) */\n#define\tMAXALIGN ((size_t)0x2000000LU)\n#define\tNITER 4\n\nTEST_BEGIN(test_alignment_errors)\n{\n\tsize_t alignment;\n\tvoid *p;\n\n\talignment = 0;\n\tset_errno(0);\n\tp = aligned_alloc(alignment, 1);\n\tassert_false(p != NULL || get_errno() != EINVAL,\n\t    \"Expected error for invalid alignment %zu\", alignment);\n\n\tfor (alignment = sizeof(size_t); alignment < MAXALIGN;\n\t    alignment <<= 1) {\n\t\tset_errno(0);\n\t\tp = aligned_alloc(alignment + 1, 1);\n\t\tassert_false(p != NULL || get_errno() != EINVAL,\n\t\t    \"Expected error for invalid alignment %zu\",\n\t\t    alignment + 1);\n\t}\n}\nTEST_END\n\nTEST_BEGIN(test_oom_errors)\n{\n\tsize_t alignment, size;\n\tvoid *p;\n\n#if LG_SIZEOF_PTR == 3\n\talignment = UINT64_C(0x8000000000000000);\n\tsize      = UINT64_C(0x8000000000000000);\n#else\n\talignment = 0x80000000LU;\n\tsize      = 0x80000000LU;\n#endif\n\tset_errno(0);\n\tp = aligned_alloc(alignment, size);\n\tassert_false(p != NULL || get_errno() != ENOMEM,\n\t    \"Expected error for aligned_alloc(%zu, %zu)\",\n\t    alignment, size);\n\n#if LG_SIZEOF_PTR == 3\n\talignment = UINT64_C(0x4000000000000000);\n\tsize      = UINT64_C(0xc000000000000001);\n#else\n\talignment = 0x40000000LU;\n\tsize      = 0xc0000001LU;\n#endif\n\tset_errno(0);\n\tp = aligned_alloc(alignment, size);\n\tassert_false(p != NULL || get_errno() != ENOMEM,\n\t    \"Expected error for aligned_alloc(%zu, %zu)\",\n\t    alignment, size);\n\n\talignment = 0x10LU;\n#if LG_SIZEOF_PTR == 3\n\tsize = UINT64_C(0xfffffffffffffff0);\n#else\n\tsize = 0xfffffff0LU;\n#endif\n\tset_errno(0);\n\tp = aligned_alloc(alignment, size);\n\tassert_false(p != NULL || get_errno() != ENOMEM,\n\t    \"Expected error for aligned_alloc(&p, %zu, %zu)\",\n\t    alignment, size);\n}\nTEST_END\n\nTEST_BEGIN(test_alignment_and_size)\n{\n\tsize_t alignment, size, total;\n\tunsigned i;\n\tvoid *ps[NITER];\n\n\tfor (i = 0; i < NITER; i++)\n\t\tps[i] = NULL;\n\n\tfor (alignment = 8;\n\t    alignment <= MAXALIGN;\n\t    alignment <<= 1) {\n\t\ttotal = 0;\n\t\tfor (size = 1;\n\t\t    size < 3 * alignment && size < (1U << 31);\n\t\t    size += (alignment >> (LG_SIZEOF_PTR-1)) - 1) {\n\t\t\tfor (i = 0; i < NITER; i++) {\n\t\t\t\tps[i] = aligned_alloc(alignment, size);\n\t\t\t\tif (ps[i] == NULL) {\n\t\t\t\t\tchar buf[BUFERROR_BUF];\n\n\t\t\t\t\tbuferror(get_errno(), buf, sizeof(buf));\n\t\t\t\t\ttest_fail(\n\t\t\t\t\t    \"Error for alignment=%zu, \"\n\t\t\t\t\t    \"size=%zu (%#zx): %s\",\n\t\t\t\t\t    alignment, size, size, buf);\n\t\t\t\t}\n\t\t\t\ttotal += malloc_usable_size(ps[i]);\n\t\t\t\tif (total >= (MAXALIGN << 1))\n\t\t\t\t\tbreak;\n\t\t\t}\n\t\t\tfor (i = 0; i < NITER; i++) {\n\t\t\t\tif (ps[i] != NULL) {\n\t\t\t\t\tfree(ps[i]);\n\t\t\t\t\tps[i] = NULL;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}\nTEST_END\n\nint\nmain(void)\n{\n\n\treturn (test(\n\t    test_alignment_errors,\n\t    test_oom_errors,\n\t    test_alignment_and_size));\n}\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.8/deps/jemalloc/test/integration/allocated.c",
    "content": "#include \"test/jemalloc_test.h\"\n\nstatic const bool config_stats =\n#ifdef JEMALLOC_STATS\n    true\n#else\n    false\n#endif\n    ;\n\nvoid *\nthd_start(void *arg)\n{\n\tint err;\n\tvoid *p;\n\tuint64_t a0, a1, d0, d1;\n\tuint64_t *ap0, *ap1, *dp0, *dp1;\n\tsize_t sz, usize;\n\n\tsz = sizeof(a0);\n\tif ((err = mallctl(\"thread.allocated\", &a0, &sz, NULL, 0))) {\n\t\tif (err == ENOENT)\n\t\t\tgoto label_ENOENT;\n\t\ttest_fail(\"%s(): Error in mallctl(): %s\", __func__,\n\t\t    strerror(err));\n\t}\n\tsz = sizeof(ap0);\n\tif ((err = mallctl(\"thread.allocatedp\", &ap0, &sz, NULL, 0))) {\n\t\tif (err == ENOENT)\n\t\t\tgoto label_ENOENT;\n\t\ttest_fail(\"%s(): Error in mallctl(): %s\", __func__,\n\t\t    strerror(err));\n\t}\n\tassert_u64_eq(*ap0, a0,\n\t    \"\\\"thread.allocatedp\\\" should provide a pointer to internal \"\n\t    \"storage\");\n\n\tsz = sizeof(d0);\n\tif ((err = mallctl(\"thread.deallocated\", &d0, &sz, NULL, 0))) {\n\t\tif (err == ENOENT)\n\t\t\tgoto label_ENOENT;\n\t\ttest_fail(\"%s(): Error in mallctl(): %s\", __func__,\n\t\t    strerror(err));\n\t}\n\tsz = sizeof(dp0);\n\tif ((err = mallctl(\"thread.deallocatedp\", &dp0, &sz, NULL, 0))) {\n\t\tif (err == ENOENT)\n\t\t\tgoto label_ENOENT;\n\t\ttest_fail(\"%s(): Error in mallctl(): %s\", __func__,\n\t\t    strerror(err));\n\t}\n\tassert_u64_eq(*dp0, d0,\n\t    \"\\\"thread.deallocatedp\\\" should provide a pointer to internal \"\n\t    \"storage\");\n\n\tp = malloc(1);\n\tassert_ptr_not_null(p, \"Unexpected malloc() error\");\n\n\tsz = sizeof(a1);\n\tmallctl(\"thread.allocated\", &a1, &sz, NULL, 0);\n\tsz = sizeof(ap1);\n\tmallctl(\"thread.allocatedp\", &ap1, &sz, NULL, 0);\n\tassert_u64_eq(*ap1, a1,\n\t    \"Dereferenced \\\"thread.allocatedp\\\" value should equal \"\n\t    \"\\\"thread.allocated\\\" value\");\n\tassert_ptr_eq(ap0, ap1,\n\t    \"Pointer returned by \\\"thread.allocatedp\\\" should not change\");\n\n\tusize = malloc_usable_size(p);\n\tassert_u64_le(a0 + usize, a1,\n\t    \"Allocated memory counter should increase by at least the amount \"\n\t    \"explicitly allocated\");\n\n\tfree(p);\n\n\tsz = sizeof(d1);\n\tmallctl(\"thread.deallocated\", &d1, &sz, NULL, 0);\n\tsz = sizeof(dp1);\n\tmallctl(\"thread.deallocatedp\", &dp1, &sz, NULL, 0);\n\tassert_u64_eq(*dp1, d1,\n\t    \"Dereferenced \\\"thread.deallocatedp\\\" value should equal \"\n\t    \"\\\"thread.deallocated\\\" value\");\n\tassert_ptr_eq(dp0, dp1,\n\t    \"Pointer returned by \\\"thread.deallocatedp\\\" should not change\");\n\n\tassert_u64_le(d0 + usize, d1,\n\t    \"Deallocated memory counter should increase by at least the amount \"\n\t    \"explicitly deallocated\");\n\n\treturn (NULL);\nlabel_ENOENT:\n\tassert_false(config_stats,\n\t    \"ENOENT should only be returned if stats are disabled\");\n\ttest_skip(\"\\\"thread.allocated\\\" mallctl not available\");\n\treturn (NULL);\n}\n\nTEST_BEGIN(test_main_thread)\n{\n\n\tthd_start(NULL);\n}\nTEST_END\n\nTEST_BEGIN(test_subthread)\n{\n\tthd_t thd;\n\n\tthd_create(&thd, thd_start, NULL);\n\tthd_join(thd, NULL);\n}\nTEST_END\n\nint\nmain(void)\n{\n\n\t/* Run tests multiple times to check for bad interactions. */\n\treturn (test(\n\t    test_main_thread,\n\t    test_subthread,\n\t    test_main_thread,\n\t    test_subthread,\n\t    test_main_thread));\n}\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.8/deps/jemalloc/test/integration/chunk.c",
    "content": "#include \"test/jemalloc_test.h\"\n\n#ifdef JEMALLOC_FILL\nconst char *malloc_conf = \"junk:false\";\n#endif\n\nstatic chunk_hooks_t orig_hooks;\nstatic chunk_hooks_t old_hooks;\n\nstatic bool do_dalloc = true;\nstatic bool do_decommit;\n\nstatic bool did_alloc;\nstatic bool did_dalloc;\nstatic bool did_commit;\nstatic bool did_decommit;\nstatic bool did_purge;\nstatic bool did_split;\nstatic bool did_merge;\n\n#if 0\n#  define TRACE_HOOK(fmt, ...) malloc_printf(fmt, __VA_ARGS__)\n#else\n#  define TRACE_HOOK(fmt, ...)\n#endif\n\nvoid *\nchunk_alloc(void *new_addr, size_t size, size_t alignment, bool *zero,\n    bool *commit, unsigned arena_ind)\n{\n\n\tTRACE_HOOK(\"%s(new_addr=%p, size=%zu, alignment=%zu, *zero=%s, \"\n\t    \"*commit=%s, arena_ind=%u)\\n\", __func__, new_addr, size, alignment,\n\t    *zero ?  \"true\" : \"false\", *commit ? \"true\" : \"false\", arena_ind);\n\tdid_alloc = true;\n\treturn (old_hooks.alloc(new_addr, size, alignment, zero, commit,\n\t    arena_ind));\n}\n\nbool\nchunk_dalloc(void *chunk, size_t size, bool committed, unsigned arena_ind)\n{\n\n\tTRACE_HOOK(\"%s(chunk=%p, size=%zu, committed=%s, arena_ind=%u)\\n\",\n\t    __func__, chunk, size, committed ? \"true\" : \"false\", arena_ind);\n\tdid_dalloc = true;\n\tif (!do_dalloc)\n\t\treturn (true);\n\treturn (old_hooks.dalloc(chunk, size, committed, arena_ind));\n}\n\nbool\nchunk_commit(void *chunk, size_t size, size_t offset, size_t length,\n    unsigned arena_ind)\n{\n\tbool err;\n\n\tTRACE_HOOK(\"%s(chunk=%p, size=%zu, offset=%zu, length=%zu, \"\n\t    \"arena_ind=%u)\\n\", __func__, chunk, size, offset, length,\n\t    arena_ind);\n\terr = old_hooks.commit(chunk, size, offset, length, arena_ind);\n\tdid_commit = !err;\n\treturn (err);\n}\n\nbool\nchunk_decommit(void *chunk, size_t size, size_t offset, size_t length,\n    unsigned arena_ind)\n{\n\tbool err;\n\n\tTRACE_HOOK(\"%s(chunk=%p, size=%zu, offset=%zu, length=%zu, \"\n\t    \"arena_ind=%u)\\n\", __func__, chunk, size, offset, length,\n\t    arena_ind);\n\tif (!do_decommit)\n\t\treturn (true);\n\terr = old_hooks.decommit(chunk, size, offset, length, arena_ind);\n\tdid_decommit = !err;\n\treturn (err);\n}\n\nbool\nchunk_purge(void *chunk, size_t size, size_t offset, size_t length,\n    unsigned arena_ind)\n{\n\n\tTRACE_HOOK(\"%s(chunk=%p, size=%zu, offset=%zu, length=%zu \"\n\t    \"arena_ind=%u)\\n\", __func__, chunk, size, offset, length,\n\t    arena_ind);\n\tdid_purge = true;\n\treturn (old_hooks.purge(chunk, size, offset, length, arena_ind));\n}\n\nbool\nchunk_split(void *chunk, size_t size, size_t size_a, size_t size_b,\n    bool committed, unsigned arena_ind)\n{\n\n\tTRACE_HOOK(\"%s(chunk=%p, size=%zu, size_a=%zu, size_b=%zu, \"\n\t    \"committed=%s, arena_ind=%u)\\n\", __func__, chunk, size, size_a,\n\t    size_b, committed ? \"true\" : \"false\", arena_ind);\n\tdid_split = true;\n\treturn (old_hooks.split(chunk, size, size_a, size_b, committed,\n\t    arena_ind));\n}\n\nbool\nchunk_merge(void *chunk_a, size_t size_a, void *chunk_b, size_t size_b,\n    bool committed, unsigned arena_ind)\n{\n\n\tTRACE_HOOK(\"%s(chunk_a=%p, size_a=%zu, chunk_b=%p size_b=%zu, \"\n\t    \"committed=%s, arena_ind=%u)\\n\", __func__, chunk_a, size_a, chunk_b,\n\t    size_b, committed ? \"true\" : \"false\", arena_ind);\n\tdid_merge = true;\n\treturn (old_hooks.merge(chunk_a, size_a, chunk_b, size_b,\n\t    committed, arena_ind));\n}\n\nTEST_BEGIN(test_chunk)\n{\n\tvoid *p;\n\tsize_t old_size, new_size, large0, large1, huge0, huge1, huge2, sz;\n\tchunk_hooks_t new_hooks = {\n\t\tchunk_alloc,\n\t\tchunk_dalloc,\n\t\tchunk_commit,\n\t\tchunk_decommit,\n\t\tchunk_purge,\n\t\tchunk_split,\n\t\tchunk_merge\n\t};\n\tbool xallocx_success_a, xallocx_success_b, xallocx_success_c;\n\n\t/* Install custom chunk hooks. */\n\told_size = sizeof(chunk_hooks_t);\n\tnew_size = sizeof(chunk_hooks_t);\n\tassert_d_eq(mallctl(\"arena.0.chunk_hooks\", &old_hooks, &old_size,\n\t    &new_hooks, new_size), 0, \"Unexpected chunk_hooks error\");\n\torig_hooks = old_hooks;\n\tassert_ptr_ne(old_hooks.alloc, chunk_alloc, \"Unexpected alloc error\");\n\tassert_ptr_ne(old_hooks.dalloc, chunk_dalloc,\n\t    \"Unexpected dalloc error\");\n\tassert_ptr_ne(old_hooks.commit, chunk_commit,\n\t    \"Unexpected commit error\");\n\tassert_ptr_ne(old_hooks.decommit, chunk_decommit,\n\t    \"Unexpected decommit error\");\n\tassert_ptr_ne(old_hooks.purge, chunk_purge, \"Unexpected purge error\");\n\tassert_ptr_ne(old_hooks.split, chunk_split, \"Unexpected split error\");\n\tassert_ptr_ne(old_hooks.merge, chunk_merge, \"Unexpected merge error\");\n\n\t/* Get large size classes. */\n\tsz = sizeof(size_t);\n\tassert_d_eq(mallctl(\"arenas.lrun.0.size\", &large0, &sz, NULL, 0), 0,\n\t    \"Unexpected arenas.lrun.0.size failure\");\n\tassert_d_eq(mallctl(\"arenas.lrun.1.size\", &large1, &sz, NULL, 0), 0,\n\t    \"Unexpected arenas.lrun.1.size failure\");\n\n\t/* Get huge size classes. */\n\tassert_d_eq(mallctl(\"arenas.hchunk.0.size\", &huge0, &sz, NULL, 0), 0,\n\t    \"Unexpected arenas.hchunk.0.size failure\");\n\tassert_d_eq(mallctl(\"arenas.hchunk.1.size\", &huge1, &sz, NULL, 0), 0,\n\t    \"Unexpected arenas.hchunk.1.size failure\");\n\tassert_d_eq(mallctl(\"arenas.hchunk.2.size\", &huge2, &sz, NULL, 0), 0,\n\t    \"Unexpected arenas.hchunk.2.size failure\");\n\n\t/* Test dalloc/decommit/purge cascade. */\n\tdo_dalloc = false;\n\tdo_decommit = false;\n\tp = mallocx(huge0 * 2, 0);\n\tassert_ptr_not_null(p, \"Unexpected mallocx() error\");\n\tdid_dalloc = false;\n\tdid_decommit = false;\n\tdid_purge = false;\n\tdid_split = false;\n\txallocx_success_a = (xallocx(p, huge0, 0, 0) == huge0);\n\tassert_d_eq(mallctl(\"arena.0.purge\", NULL, NULL, NULL, 0), 0,\n\t    \"Unexpected arena.0.purge error\");\n\tif (xallocx_success_a) {\n\t\tassert_true(did_dalloc, \"Expected dalloc\");\n\t\tassert_false(did_decommit, \"Unexpected decommit\");\n\t\tassert_true(did_purge, \"Expected purge\");\n\t}\n\tassert_true(did_split, \"Expected split\");\n\tdallocx(p, 0);\n\tdo_dalloc = true;\n\n\t/* Test decommit/commit and observe split/merge. */\n\tdo_dalloc = false;\n\tdo_decommit = true;\n\tp = mallocx(huge0 * 2, 0);\n\tassert_ptr_not_null(p, \"Unexpected mallocx() error\");\n\tdid_decommit = false;\n\tdid_commit = false;\n\tdid_split = false;\n\tdid_merge = false;\n\txallocx_success_b = (xallocx(p, huge0, 0, 0) == huge0);\n\tassert_d_eq(mallctl(\"arena.0.purge\", NULL, NULL, NULL, 0), 0,\n\t    \"Unexpected arena.0.purge error\");\n\tif (xallocx_success_b)\n\t\tassert_true(did_split, \"Expected split\");\n\txallocx_success_c = (xallocx(p, huge0 * 2, 0, 0) == huge0 * 2);\n\tassert_b_eq(did_decommit, did_commit, \"Expected decommit/commit match\");\n\tif (xallocx_success_b && xallocx_success_c)\n\t\tassert_true(did_merge, \"Expected merge\");\n\tdallocx(p, 0);\n\tdo_dalloc = true;\n\tdo_decommit = false;\n\n\t/* Test purge for partial-chunk huge allocations. */\n\tif (huge0 * 2 > huge2) {\n\t\t/*\n\t\t * There are at least four size classes per doubling, so a\n\t\t * successful xallocx() from size=huge2 to size=huge1 is\n\t\t * guaranteed to leave trailing purgeable memory.\n\t\t */\n\t\tp = mallocx(huge2, 0);\n\t\tassert_ptr_not_null(p, \"Unexpected mallocx() error\");\n\t\tdid_purge = false;\n\t\tassert_zu_eq(xallocx(p, huge1, 0, 0), huge1,\n\t\t    \"Unexpected xallocx() failure\");\n\t\tassert_true(did_purge, \"Expected purge\");\n\t\tdallocx(p, 0);\n\t}\n\n\t/* Test decommit for large allocations. */\n\tdo_decommit = true;\n\tp = mallocx(large1, 0);\n\tassert_ptr_not_null(p, \"Unexpected mallocx() error\");\n\tassert_d_eq(mallctl(\"arena.0.purge\", NULL, NULL, NULL, 0), 0,\n\t    \"Unexpected arena.0.purge error\");\n\tdid_decommit = false;\n\tassert_zu_eq(xallocx(p, large0, 0, 0), large0,\n\t    \"Unexpected xallocx() failure\");\n\tassert_d_eq(mallctl(\"arena.0.purge\", NULL, NULL, NULL, 0), 0,\n\t    \"Unexpected arena.0.purge error\");\n\tdid_commit = false;\n\tassert_zu_eq(xallocx(p, large1, 0, 0), large1,\n\t    \"Unexpected xallocx() failure\");\n\tassert_b_eq(did_decommit, did_commit, \"Expected decommit/commit match\");\n\tdallocx(p, 0);\n\tdo_decommit = false;\n\n\t/* Make sure non-huge allocation succeeds. */\n\tp = mallocx(42, 0);\n\tassert_ptr_not_null(p, \"Unexpected mallocx() error\");\n\tdallocx(p, 0);\n\n\t/* Restore chunk hooks. */\n\tassert_d_eq(mallctl(\"arena.0.chunk_hooks\", NULL, NULL, &old_hooks,\n\t    new_size), 0, \"Unexpected chunk_hooks error\");\n\tassert_d_eq(mallctl(\"arena.0.chunk_hooks\", &old_hooks, &old_size,\n\t    NULL, 0), 0, \"Unexpected chunk_hooks error\");\n\tassert_ptr_eq(old_hooks.alloc, orig_hooks.alloc,\n\t    \"Unexpected alloc error\");\n\tassert_ptr_eq(old_hooks.dalloc, orig_hooks.dalloc,\n\t    \"Unexpected dalloc error\");\n\tassert_ptr_eq(old_hooks.commit, orig_hooks.commit,\n\t    \"Unexpected commit error\");\n\tassert_ptr_eq(old_hooks.decommit, orig_hooks.decommit,\n\t    \"Unexpected decommit error\");\n\tassert_ptr_eq(old_hooks.purge, orig_hooks.purge,\n\t    \"Unexpected purge error\");\n\tassert_ptr_eq(old_hooks.split, orig_hooks.split,\n\t    \"Unexpected split error\");\n\tassert_ptr_eq(old_hooks.merge, orig_hooks.merge,\n\t    \"Unexpected merge error\");\n}\nTEST_END\n\nint\nmain(void)\n{\n\n\treturn (test(test_chunk));\n}\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.8/deps/jemalloc/test/integration/mallocx.c",
    "content": "#include \"test/jemalloc_test.h\"\n\nstatic unsigned\nget_nsizes_impl(const char *cmd)\n{\n\tunsigned ret;\n\tsize_t z;\n\n\tz = sizeof(unsigned);\n\tassert_d_eq(mallctl(cmd, &ret, &z, NULL, 0), 0,\n\t    \"Unexpected mallctl(\\\"%s\\\", ...) failure\", cmd);\n\n\treturn (ret);\n}\n\nstatic unsigned\nget_nhuge(void)\n{\n\n\treturn (get_nsizes_impl(\"arenas.nhchunks\"));\n}\n\nstatic size_t\nget_size_impl(const char *cmd, size_t ind)\n{\n\tsize_t ret;\n\tsize_t z;\n\tsize_t mib[4];\n\tsize_t miblen = 4;\n\n\tz = sizeof(size_t);\n\tassert_d_eq(mallctlnametomib(cmd, mib, &miblen),\n\t    0, \"Unexpected mallctlnametomib(\\\"%s\\\", ...) failure\", cmd);\n\tmib[2] = ind;\n\tz = sizeof(size_t);\n\tassert_d_eq(mallctlbymib(mib, miblen, &ret, &z, NULL, 0),\n\t    0, \"Unexpected mallctlbymib([\\\"%s\\\", %zu], ...) failure\", cmd, ind);\n\n\treturn (ret);\n}\n\nstatic size_t\nget_huge_size(size_t ind)\n{\n\n\treturn (get_size_impl(\"arenas.hchunk.0.size\", ind));\n}\n\nTEST_BEGIN(test_oom)\n{\n\tsize_t hugemax, size, alignment;\n\n\thugemax = get_huge_size(get_nhuge()-1);\n\n\t/*\n\t * It should be impossible to allocate two objects that each consume\n\t * more than half the virtual address space.\n\t */\n\t{\n\t\tvoid *p;\n\n\t\tp = mallocx(hugemax, 0);\n\t\tif (p != NULL) {\n\t\t\tassert_ptr_null(mallocx(hugemax, 0),\n\t\t\t    \"Expected OOM for mallocx(size=%#zx, 0)\", hugemax);\n\t\t\tdallocx(p, 0);\n\t\t}\n\t}\n\n#if LG_SIZEOF_PTR == 3\n\tsize      = ZU(0x8000000000000000);\n\talignment = ZU(0x8000000000000000);\n#else\n\tsize      = ZU(0x80000000);\n\talignment = ZU(0x80000000);\n#endif\n\tassert_ptr_null(mallocx(size, MALLOCX_ALIGN(alignment)),\n\t    \"Expected OOM for mallocx(size=%#zx, MALLOCX_ALIGN(%#zx)\", size,\n\t    alignment);\n}\nTEST_END\n\nTEST_BEGIN(test_basic)\n{\n#define\tMAXSZ (((size_t)1) << 26)\n\tsize_t sz;\n\n\tfor (sz = 1; sz < MAXSZ; sz = nallocx(sz, 0) + 1) {\n\t\tsize_t nsz, rsz;\n\t\tvoid *p;\n\t\tnsz = nallocx(sz, 0);\n\t\tassert_zu_ne(nsz, 0, \"Unexpected nallocx() error\");\n\t\tp = mallocx(sz, 0);\n\t\tassert_ptr_not_null(p, \"Unexpected mallocx() error\");\n\t\trsz = sallocx(p, 0);\n\t\tassert_zu_ge(rsz, sz, \"Real size smaller than expected\");\n\t\tassert_zu_eq(nsz, rsz, \"nallocx()/sallocx() size mismatch\");\n\t\tdallocx(p, 0);\n\n\t\tp = mallocx(sz, 0);\n\t\tassert_ptr_not_null(p, \"Unexpected mallocx() error\");\n\t\tdallocx(p, 0);\n\n\t\tnsz = nallocx(sz, MALLOCX_ZERO);\n\t\tassert_zu_ne(nsz, 0, \"Unexpected nallocx() error\");\n\t\tp = mallocx(sz, MALLOCX_ZERO);\n\t\tassert_ptr_not_null(p, \"Unexpected mallocx() error\");\n\t\trsz = sallocx(p, 0);\n\t\tassert_zu_eq(nsz, rsz, \"nallocx()/sallocx() rsize mismatch\");\n\t\tdallocx(p, 0);\n\t}\n#undef MAXSZ\n}\nTEST_END\n\nTEST_BEGIN(test_alignment_and_size)\n{\n#define\tMAXALIGN (((size_t)1) << 25)\n#define\tNITER 4\n\tsize_t nsz, rsz, sz, alignment, total;\n\tunsigned i;\n\tvoid *ps[NITER];\n\n\tfor (i = 0; i < NITER; i++)\n\t\tps[i] = NULL;\n\n\tfor (alignment = 8;\n\t    alignment <= MAXALIGN;\n\t    alignment <<= 1) {\n\t\ttotal = 0;\n\t\tfor (sz = 1;\n\t\t    sz < 3 * alignment && sz < (1U << 31);\n\t\t    sz += (alignment >> (LG_SIZEOF_PTR-1)) - 1) {\n\t\t\tfor (i = 0; i < NITER; i++) {\n\t\t\t\tnsz = nallocx(sz, MALLOCX_ALIGN(alignment) |\n\t\t\t\t    MALLOCX_ZERO);\n\t\t\t\tassert_zu_ne(nsz, 0,\n\t\t\t\t    \"nallocx() error for alignment=%zu, \"\n\t\t\t\t    \"size=%zu (%#zx)\", alignment, sz, sz);\n\t\t\t\tps[i] = mallocx(sz, MALLOCX_ALIGN(alignment) |\n\t\t\t\t    MALLOCX_ZERO);\n\t\t\t\tassert_ptr_not_null(ps[i],\n\t\t\t\t    \"mallocx() error for alignment=%zu, \"\n\t\t\t\t    \"size=%zu (%#zx)\", alignment, sz, sz);\n\t\t\t\trsz = sallocx(ps[i], 0);\n\t\t\t\tassert_zu_ge(rsz, sz,\n\t\t\t\t    \"Real size smaller than expected for \"\n\t\t\t\t    \"alignment=%zu, size=%zu\", alignment, sz);\n\t\t\t\tassert_zu_eq(nsz, rsz,\n\t\t\t\t    \"nallocx()/sallocx() size mismatch for \"\n\t\t\t\t    \"alignment=%zu, size=%zu\", alignment, sz);\n\t\t\t\tassert_ptr_null(\n\t\t\t\t    (void *)((uintptr_t)ps[i] & (alignment-1)),\n\t\t\t\t    \"%p inadequately aligned for\"\n\t\t\t\t    \" alignment=%zu, size=%zu\", ps[i],\n\t\t\t\t    alignment, sz);\n\t\t\t\ttotal += rsz;\n\t\t\t\tif (total >= (MAXALIGN << 1))\n\t\t\t\t\tbreak;\n\t\t\t}\n\t\t\tfor (i = 0; i < NITER; i++) {\n\t\t\t\tif (ps[i] != NULL) {\n\t\t\t\t\tdallocx(ps[i], 0);\n\t\t\t\t\tps[i] = NULL;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n#undef MAXALIGN\n#undef NITER\n}\nTEST_END\n\nint\nmain(void)\n{\n\n\treturn (test(\n\t    test_oom,\n\t    test_basic,\n\t    test_alignment_and_size));\n}\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.8/deps/jemalloc/test/integration/overflow.c",
    "content": "#include \"test/jemalloc_test.h\"\n\nTEST_BEGIN(test_overflow)\n{\n\tunsigned nhchunks;\n\tsize_t mib[4];\n\tsize_t sz, miblen, max_size_class;\n\tvoid *p;\n\n\tsz = sizeof(unsigned);\n\tassert_d_eq(mallctl(\"arenas.nhchunks\", &nhchunks, &sz, NULL, 0), 0,\n\t    \"Unexpected mallctl() error\");\n\n\tmiblen = sizeof(mib) / sizeof(size_t);\n\tassert_d_eq(mallctlnametomib(\"arenas.hchunk.0.size\", mib, &miblen), 0,\n\t    \"Unexpected mallctlnametomib() error\");\n\tmib[2] = nhchunks - 1;\n\n\tsz = sizeof(size_t);\n\tassert_d_eq(mallctlbymib(mib, miblen, &max_size_class, &sz, NULL, 0), 0,\n\t    \"Unexpected mallctlbymib() error\");\n\n\tassert_ptr_null(malloc(max_size_class + 1),\n\t    \"Expected OOM due to over-sized allocation request\");\n\tassert_ptr_null(malloc(SIZE_T_MAX),\n\t    \"Expected OOM due to over-sized allocation request\");\n\n\tassert_ptr_null(calloc(1, max_size_class + 1),\n\t    \"Expected OOM due to over-sized allocation request\");\n\tassert_ptr_null(calloc(1, SIZE_T_MAX),\n\t    \"Expected OOM due to over-sized allocation request\");\n\n\tp = malloc(1);\n\tassert_ptr_not_null(p, \"Unexpected malloc() OOM\");\n\tassert_ptr_null(realloc(p, max_size_class + 1),\n\t    \"Expected OOM due to over-sized allocation request\");\n\tassert_ptr_null(realloc(p, SIZE_T_MAX),\n\t    \"Expected OOM due to over-sized allocation request\");\n\tfree(p);\n}\nTEST_END\n\nint\nmain(void)\n{\n\n\treturn (test(\n\t    test_overflow));\n}\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.8/deps/jemalloc/test/integration/posix_memalign.c",
    "content": "#include \"test/jemalloc_test.h\"\n\n#define\tCHUNK 0x400000\n/* #define MAXALIGN ((size_t)UINT64_C(0x80000000000)) */\n#define\tMAXALIGN ((size_t)0x2000000LU)\n#define\tNITER 4\n\nTEST_BEGIN(test_alignment_errors)\n{\n\tsize_t alignment;\n\tvoid *p;\n\n\tfor (alignment = 0; alignment < sizeof(void *); alignment++) {\n\t\tassert_d_eq(posix_memalign(&p, alignment, 1), EINVAL,\n\t\t    \"Expected error for invalid alignment %zu\",\n\t\t    alignment);\n\t}\n\n\tfor (alignment = sizeof(size_t); alignment < MAXALIGN;\n\t    alignment <<= 1) {\n\t\tassert_d_ne(posix_memalign(&p, alignment + 1, 1), 0,\n\t\t    \"Expected error for invalid alignment %zu\",\n\t\t    alignment + 1);\n\t}\n}\nTEST_END\n\nTEST_BEGIN(test_oom_errors)\n{\n\tsize_t alignment, size;\n\tvoid *p;\n\n#if LG_SIZEOF_PTR == 3\n\talignment = UINT64_C(0x8000000000000000);\n\tsize      = UINT64_C(0x8000000000000000);\n#else\n\talignment = 0x80000000LU;\n\tsize      = 0x80000000LU;\n#endif\n\tassert_d_ne(posix_memalign(&p, alignment, size), 0,\n\t    \"Expected error for posix_memalign(&p, %zu, %zu)\",\n\t    alignment, size);\n\n#if LG_SIZEOF_PTR == 3\n\talignment = UINT64_C(0x4000000000000000);\n\tsize      = UINT64_C(0xc000000000000001);\n#else\n\talignment = 0x40000000LU;\n\tsize      = 0xc0000001LU;\n#endif\n\tassert_d_ne(posix_memalign(&p, alignment, size), 0,\n\t    \"Expected error for posix_memalign(&p, %zu, %zu)\",\n\t    alignment, size);\n\n\talignment = 0x10LU;\n#if LG_SIZEOF_PTR == 3\n\tsize = UINT64_C(0xfffffffffffffff0);\n#else\n\tsize = 0xfffffff0LU;\n#endif\n\tassert_d_ne(posix_memalign(&p, alignment, size), 0,\n\t    \"Expected error for posix_memalign(&p, %zu, %zu)\",\n\t    alignment, size);\n}\nTEST_END\n\nTEST_BEGIN(test_alignment_and_size)\n{\n\tsize_t alignment, size, total;\n\tunsigned i;\n\tint err;\n\tvoid *ps[NITER];\n\n\tfor (i = 0; i < NITER; i++)\n\t\tps[i] = NULL;\n\n\tfor (alignment = 8;\n\t    alignment <= MAXALIGN;\n\t    alignment <<= 1) {\n\t\ttotal = 0;\n\t\tfor (size = 1;\n\t\t    size < 3 * alignment && size < (1U << 31);\n\t\t    size += (alignment >> (LG_SIZEOF_PTR-1)) - 1) {\n\t\t\tfor (i = 0; i < NITER; i++) {\n\t\t\t\terr = posix_memalign(&ps[i],\n\t\t\t\t    alignment, size);\n\t\t\t\tif (err) {\n\t\t\t\t\tchar buf[BUFERROR_BUF];\n\n\t\t\t\t\tbuferror(get_errno(), buf, sizeof(buf));\n\t\t\t\t\ttest_fail(\n\t\t\t\t\t    \"Error for alignment=%zu, \"\n\t\t\t\t\t    \"size=%zu (%#zx): %s\",\n\t\t\t\t\t    alignment, size, size, buf);\n\t\t\t\t}\n\t\t\t\ttotal += malloc_usable_size(ps[i]);\n\t\t\t\tif (total >= (MAXALIGN << 1))\n\t\t\t\t\tbreak;\n\t\t\t}\n\t\t\tfor (i = 0; i < NITER; i++) {\n\t\t\t\tif (ps[i] != NULL) {\n\t\t\t\t\tfree(ps[i]);\n\t\t\t\t\tps[i] = NULL;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}\nTEST_END\n\nint\nmain(void)\n{\n\n\treturn (test(\n\t    test_alignment_errors,\n\t    test_oom_errors,\n\t    test_alignment_and_size));\n}\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.8/deps/jemalloc/test/integration/rallocx.c",
    "content": "#include \"test/jemalloc_test.h\"\n\nTEST_BEGIN(test_grow_and_shrink)\n{\n\tvoid *p, *q;\n\tsize_t tsz;\n#define\tNCYCLES 3\n\tunsigned i, j;\n#define\tNSZS 2500\n\tsize_t szs[NSZS];\n#define\tMAXSZ ZU(12 * 1024 * 1024)\n\n\tp = mallocx(1, 0);\n\tassert_ptr_not_null(p, \"Unexpected mallocx() error\");\n\tszs[0] = sallocx(p, 0);\n\n\tfor (i = 0; i < NCYCLES; i++) {\n\t\tfor (j = 1; j < NSZS && szs[j-1] < MAXSZ; j++) {\n\t\t\tq = rallocx(p, szs[j-1]+1, 0);\n\t\t\tassert_ptr_not_null(q,\n\t\t\t    \"Unexpected rallocx() error for size=%zu-->%zu\",\n\t\t\t    szs[j-1], szs[j-1]+1);\n\t\t\tszs[j] = sallocx(q, 0);\n\t\t\tassert_zu_ne(szs[j], szs[j-1]+1,\n\t\t\t    \"Expected size to be at least: %zu\", szs[j-1]+1);\n\t\t\tp = q;\n\t\t}\n\n\t\tfor (j--; j > 0; j--) {\n\t\t\tq = rallocx(p, szs[j-1], 0);\n\t\t\tassert_ptr_not_null(q,\n\t\t\t    \"Unexpected rallocx() error for size=%zu-->%zu\",\n\t\t\t    szs[j], szs[j-1]);\n\t\t\ttsz = sallocx(q, 0);\n\t\t\tassert_zu_eq(tsz, szs[j-1],\n\t\t\t    \"Expected size=%zu, got size=%zu\", szs[j-1], tsz);\n\t\t\tp = q;\n\t\t}\n\t}\n\n\tdallocx(p, 0);\n#undef MAXSZ\n#undef NSZS\n#undef NCYCLES\n}\nTEST_END\n\nstatic bool\nvalidate_fill(const void *p, uint8_t c, size_t offset, size_t len)\n{\n\tbool ret = false;\n\tconst uint8_t *buf = (const uint8_t *)p;\n\tsize_t i;\n\n\tfor (i = 0; i < len; i++) {\n\t\tuint8_t b = buf[offset+i];\n\t\tif (b != c) {\n\t\t\ttest_fail(\"Allocation at %p (len=%zu) contains %#x \"\n\t\t\t    \"rather than %#x at offset %zu\", p, len, b, c,\n\t\t\t    offset+i);\n\t\t\tret = true;\n\t\t}\n\t}\n\n\treturn (ret);\n}\n\nTEST_BEGIN(test_zero)\n{\n\tvoid *p, *q;\n\tsize_t psz, qsz, i, j;\n\tsize_t start_sizes[] = {1, 3*1024, 63*1024, 4095*1024};\n#define\tFILL_BYTE 0xaaU\n#define\tRANGE 2048\n\n\tfor (i = 0; i < sizeof(start_sizes)/sizeof(size_t); i++) {\n\t\tsize_t start_size = start_sizes[i];\n\t\tp = mallocx(start_size, MALLOCX_ZERO);\n\t\tassert_ptr_not_null(p, \"Unexpected mallocx() error\");\n\t\tpsz = sallocx(p, 0);\n\n\t\tassert_false(validate_fill(p, 0, 0, psz),\n\t\t    \"Expected zeroed memory\");\n\t\tmemset(p, FILL_BYTE, psz);\n\t\tassert_false(validate_fill(p, FILL_BYTE, 0, psz),\n\t\t    \"Expected filled memory\");\n\n\t\tfor (j = 1; j < RANGE; j++) {\n\t\t\tq = rallocx(p, start_size+j, MALLOCX_ZERO);\n\t\t\tassert_ptr_not_null(q, \"Unexpected rallocx() error\");\n\t\t\tqsz = sallocx(q, 0);\n\t\t\tif (q != p || qsz != psz) {\n\t\t\t\tassert_false(validate_fill(q, FILL_BYTE, 0,\n\t\t\t\t    psz), \"Expected filled memory\");\n\t\t\t\tassert_false(validate_fill(q, 0, psz, qsz-psz),\n\t\t\t\t    \"Expected zeroed memory\");\n\t\t\t}\n\t\t\tif (psz != qsz) {\n\t\t\t\tmemset((void *)((uintptr_t)q+psz), FILL_BYTE,\n\t\t\t\t    qsz-psz);\n\t\t\t\tpsz = qsz;\n\t\t\t}\n\t\t\tp = q;\n\t\t}\n\t\tassert_false(validate_fill(p, FILL_BYTE, 0, psz),\n\t\t    \"Expected filled memory\");\n\t\tdallocx(p, 0);\n\t}\n#undef FILL_BYTE\n}\nTEST_END\n\nTEST_BEGIN(test_align)\n{\n\tvoid *p, *q;\n\tsize_t align;\n#define\tMAX_ALIGN (ZU(1) << 25)\n\n\talign = ZU(1);\n\tp = mallocx(1, MALLOCX_ALIGN(align));\n\tassert_ptr_not_null(p, \"Unexpected mallocx() error\");\n\n\tfor (align <<= 1; align <= MAX_ALIGN; align <<= 1) {\n\t\tq = rallocx(p, 1, MALLOCX_ALIGN(align));\n\t\tassert_ptr_not_null(q,\n\t\t    \"Unexpected rallocx() error for align=%zu\", align);\n\t\tassert_ptr_null(\n\t\t    (void *)((uintptr_t)q & (align-1)),\n\t\t    \"%p inadequately aligned for align=%zu\",\n\t\t    q, align);\n\t\tp = q;\n\t}\n\tdallocx(p, 0);\n#undef MAX_ALIGN\n}\nTEST_END\n\nTEST_BEGIN(test_lg_align_and_zero)\n{\n\tvoid *p, *q;\n\tsize_t lg_align, sz;\n#define\tMAX_LG_ALIGN 25\n#define\tMAX_VALIDATE (ZU(1) << 22)\n\n\tlg_align = ZU(0);\n\tp = mallocx(1, MALLOCX_LG_ALIGN(lg_align)|MALLOCX_ZERO);\n\tassert_ptr_not_null(p, \"Unexpected mallocx() error\");\n\n\tfor (lg_align++; lg_align <= MAX_LG_ALIGN; lg_align++) {\n\t\tq = rallocx(p, 1, MALLOCX_LG_ALIGN(lg_align)|MALLOCX_ZERO);\n\t\tassert_ptr_not_null(q,\n\t\t    \"Unexpected rallocx() error for lg_align=%zu\", lg_align);\n\t\tassert_ptr_null(\n\t\t    (void *)((uintptr_t)q & ((ZU(1) << lg_align)-1)),\n\t\t    \"%p inadequately aligned for lg_align=%zu\",\n\t\t    q, lg_align);\n\t\tsz = sallocx(q, 0);\n\t\tif ((sz << 1) <= MAX_VALIDATE) {\n\t\t\tassert_false(validate_fill(q, 0, 0, sz),\n\t\t\t    \"Expected zeroed memory\");\n\t\t} else {\n\t\t\tassert_false(validate_fill(q, 0, 0, MAX_VALIDATE),\n\t\t\t    \"Expected zeroed memory\");\n\t\t\tassert_false(validate_fill(\n\t\t\t    (void *)((uintptr_t)q+sz-MAX_VALIDATE),\n\t\t\t    0, 0, MAX_VALIDATE), \"Expected zeroed memory\");\n\t\t}\n\t\tp = q;\n\t}\n\tdallocx(p, 0);\n#undef MAX_VALIDATE\n#undef MAX_LG_ALIGN\n}\nTEST_END\n\nint\nmain(void)\n{\n\n\treturn (test(\n\t    test_grow_and_shrink,\n\t    test_zero,\n\t    test_align,\n\t    test_lg_align_and_zero));\n}\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.8/deps/jemalloc/test/integration/sdallocx.c",
    "content": "#include \"test/jemalloc_test.h\"\n\n#define\tMAXALIGN (((size_t)1) << 25)\n#define\tNITER 4\n\nTEST_BEGIN(test_basic)\n{\n\tvoid *ptr = mallocx(64, 0);\n\tsdallocx(ptr, 64, 0);\n}\nTEST_END\n\nTEST_BEGIN(test_alignment_and_size)\n{\n\tsize_t nsz, sz, alignment, total;\n\tunsigned i;\n\tvoid *ps[NITER];\n\n\tfor (i = 0; i < NITER; i++)\n\t\tps[i] = NULL;\n\n\tfor (alignment = 8;\n\t    alignment <= MAXALIGN;\n\t    alignment <<= 1) {\n\t\ttotal = 0;\n\t\tfor (sz = 1;\n\t\t    sz < 3 * alignment && sz < (1U << 31);\n\t\t    sz += (alignment >> (LG_SIZEOF_PTR-1)) - 1) {\n\t\t\tfor (i = 0; i < NITER; i++) {\n\t\t\t\tnsz = nallocx(sz, MALLOCX_ALIGN(alignment) |\n\t\t\t\t    MALLOCX_ZERO);\n\t\t\t\tps[i] = mallocx(sz, MALLOCX_ALIGN(alignment) |\n\t\t\t\t    MALLOCX_ZERO);\n\t\t\t\ttotal += nsz;\n\t\t\t\tif (total >= (MAXALIGN << 1))\n\t\t\t\t\tbreak;\n\t\t\t}\n\t\t\tfor (i = 0; i < NITER; i++) {\n\t\t\t\tif (ps[i] != NULL) {\n\t\t\t\t\tsdallocx(ps[i], sz,\n\t\t\t\t\t    MALLOCX_ALIGN(alignment));\n\t\t\t\t\tps[i] = NULL;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}\nTEST_END\n\nint\nmain(void)\n{\n\n\treturn (test(\n\t    test_basic,\n\t    test_alignment_and_size));\n}\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.8/deps/jemalloc/test/integration/thread_arena.c",
    "content": "#include \"test/jemalloc_test.h\"\n\n#define\tNTHREADS 10\n\nvoid *\nthd_start(void *arg)\n{\n\tunsigned main_arena_ind = *(unsigned *)arg;\n\tvoid *p;\n\tunsigned arena_ind;\n\tsize_t size;\n\tint err;\n\n\tp = malloc(1);\n\tassert_ptr_not_null(p, \"Error in malloc()\");\n\tfree(p);\n\n\tsize = sizeof(arena_ind);\n\tif ((err = mallctl(\"thread.arena\", &arena_ind, &size, &main_arena_ind,\n\t    sizeof(main_arena_ind)))) {\n\t\tchar buf[BUFERROR_BUF];\n\n\t\tbuferror(err, buf, sizeof(buf));\n\t\ttest_fail(\"Error in mallctl(): %s\", buf);\n\t}\n\n\tsize = sizeof(arena_ind);\n\tif ((err = mallctl(\"thread.arena\", &arena_ind, &size, NULL, 0))) {\n\t\tchar buf[BUFERROR_BUF];\n\n\t\tbuferror(err, buf, sizeof(buf));\n\t\ttest_fail(\"Error in mallctl(): %s\", buf);\n\t}\n\tassert_u_eq(arena_ind, main_arena_ind,\n\t    \"Arena index should be same as for main thread\");\n\n\treturn (NULL);\n}\n\nTEST_BEGIN(test_thread_arena)\n{\n\tvoid *p;\n\tunsigned arena_ind;\n\tsize_t size;\n\tint err;\n\tthd_t thds[NTHREADS];\n\tunsigned i;\n\n\tp = malloc(1);\n\tassert_ptr_not_null(p, \"Error in malloc()\");\n\n\tsize = sizeof(arena_ind);\n\tif ((err = mallctl(\"thread.arena\", &arena_ind, &size, NULL, 0))) {\n\t\tchar buf[BUFERROR_BUF];\n\n\t\tbuferror(err, buf, sizeof(buf));\n\t\ttest_fail(\"Error in mallctl(): %s\", buf);\n\t}\n\n\tfor (i = 0; i < NTHREADS; i++) {\n\t\tthd_create(&thds[i], thd_start,\n\t\t    (void *)&arena_ind);\n\t}\n\n\tfor (i = 0; i < NTHREADS; i++) {\n\t\tintptr_t join_ret;\n\t\tthd_join(thds[i], (void *)&join_ret);\n\t\tassert_zd_eq(join_ret, 0, \"Unexpected thread join error\");\n\t}\n}\nTEST_END\n\nint\nmain(void)\n{\n\n\treturn (test(\n\t    test_thread_arena));\n}\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.8/deps/jemalloc/test/integration/thread_tcache_enabled.c",
    "content": "#include \"test/jemalloc_test.h\"\n\nstatic const bool config_tcache =\n#ifdef JEMALLOC_TCACHE\n    true\n#else\n    false\n#endif\n    ;\n\nvoid *\nthd_start(void *arg)\n{\n\tint err;\n\tsize_t sz;\n\tbool e0, e1;\n\n\tsz = sizeof(bool);\n\tif ((err = mallctl(\"thread.tcache.enabled\", &e0, &sz, NULL, 0))) {\n\t\tif (err == ENOENT) {\n\t\t\tassert_false(config_tcache,\n\t\t\t    \"ENOENT should only be returned if tcache is \"\n\t\t\t    \"disabled\");\n\t\t}\n\t\tgoto label_ENOENT;\n\t}\n\n\tif (e0) {\n\t\te1 = false;\n\t\tassert_d_eq(mallctl(\"thread.tcache.enabled\", &e0, &sz, &e1, sz),\n\t\t    0, \"Unexpected mallctl() error\");\n\t\tassert_true(e0, \"tcache should be enabled\");\n\t}\n\n\te1 = true;\n\tassert_d_eq(mallctl(\"thread.tcache.enabled\", &e0, &sz, &e1, sz), 0,\n\t    \"Unexpected mallctl() error\");\n\tassert_false(e0, \"tcache should be disabled\");\n\n\te1 = true;\n\tassert_d_eq(mallctl(\"thread.tcache.enabled\", &e0, &sz, &e1, sz), 0,\n\t    \"Unexpected mallctl() error\");\n\tassert_true(e0, \"tcache should be enabled\");\n\n\te1 = false;\n\tassert_d_eq(mallctl(\"thread.tcache.enabled\", &e0, &sz, &e1, sz), 0,\n\t    \"Unexpected mallctl() error\");\n\tassert_true(e0, \"tcache should be enabled\");\n\n\te1 = false;\n\tassert_d_eq(mallctl(\"thread.tcache.enabled\", &e0, &sz, &e1, sz), 0,\n\t    \"Unexpected mallctl() error\");\n\tassert_false(e0, \"tcache should be disabled\");\n\n\tfree(malloc(1));\n\te1 = true;\n\tassert_d_eq(mallctl(\"thread.tcache.enabled\", &e0, &sz, &e1, sz), 0,\n\t    \"Unexpected mallctl() error\");\n\tassert_false(e0, \"tcache should be disabled\");\n\n\tfree(malloc(1));\n\te1 = true;\n\tassert_d_eq(mallctl(\"thread.tcache.enabled\", &e0, &sz, &e1, sz), 0,\n\t    \"Unexpected mallctl() error\");\n\tassert_true(e0, \"tcache should be enabled\");\n\n\tfree(malloc(1));\n\te1 = false;\n\tassert_d_eq(mallctl(\"thread.tcache.enabled\", &e0, &sz, &e1, sz), 0,\n\t    \"Unexpected mallctl() error\");\n\tassert_true(e0, \"tcache should be enabled\");\n\n\tfree(malloc(1));\n\te1 = false;\n\tassert_d_eq(mallctl(\"thread.tcache.enabled\", &e0, &sz, &e1, sz), 0,\n\t    \"Unexpected mallctl() error\");\n\tassert_false(e0, \"tcache should be disabled\");\n\n\tfree(malloc(1));\n\treturn (NULL);\nlabel_ENOENT:\n\ttest_skip(\"\\\"thread.tcache.enabled\\\" mallctl not available\");\n\treturn (NULL);\n}\n\nTEST_BEGIN(test_main_thread)\n{\n\n\tthd_start(NULL);\n}\nTEST_END\n\nTEST_BEGIN(test_subthread)\n{\n\tthd_t thd;\n\n\tthd_create(&thd, thd_start, NULL);\n\tthd_join(thd, NULL);\n}\nTEST_END\n\nint\nmain(void)\n{\n\n\t/* Run tests multiple times to check for bad interactions. */\n\treturn (test(\n\t    test_main_thread,\n\t    test_subthread,\n\t    test_main_thread,\n\t    test_subthread,\n\t    test_main_thread));\n}\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.8/deps/jemalloc/test/integration/xallocx.c",
    "content": "#include \"test/jemalloc_test.h\"\n\nTEST_BEGIN(test_same_size)\n{\n\tvoid *p;\n\tsize_t sz, tsz;\n\n\tp = mallocx(42, 0);\n\tassert_ptr_not_null(p, \"Unexpected mallocx() error\");\n\tsz = sallocx(p, 0);\n\n\ttsz = xallocx(p, sz, 0, 0);\n\tassert_zu_eq(tsz, sz, \"Unexpected size change: %zu --> %zu\", sz, tsz);\n\n\tdallocx(p, 0);\n}\nTEST_END\n\nTEST_BEGIN(test_extra_no_move)\n{\n\tvoid *p;\n\tsize_t sz, tsz;\n\n\tp = mallocx(42, 0);\n\tassert_ptr_not_null(p, \"Unexpected mallocx() error\");\n\tsz = sallocx(p, 0);\n\n\ttsz = xallocx(p, sz, sz-42, 0);\n\tassert_zu_eq(tsz, sz, \"Unexpected size change: %zu --> %zu\", sz, tsz);\n\n\tdallocx(p, 0);\n}\nTEST_END\n\nTEST_BEGIN(test_no_move_fail)\n{\n\tvoid *p;\n\tsize_t sz, tsz;\n\n\tp = mallocx(42, 0);\n\tassert_ptr_not_null(p, \"Unexpected mallocx() error\");\n\tsz = sallocx(p, 0);\n\n\ttsz = xallocx(p, sz + 5, 0, 0);\n\tassert_zu_eq(tsz, sz, \"Unexpected size change: %zu --> %zu\", sz, tsz);\n\n\tdallocx(p, 0);\n}\nTEST_END\n\nstatic unsigned\nget_nsizes_impl(const char *cmd)\n{\n\tunsigned ret;\n\tsize_t z;\n\n\tz = sizeof(unsigned);\n\tassert_d_eq(mallctl(cmd, &ret, &z, NULL, 0), 0,\n\t    \"Unexpected mallctl(\\\"%s\\\", ...) failure\", cmd);\n\n\treturn (ret);\n}\n\nstatic unsigned\nget_nsmall(void)\n{\n\n\treturn (get_nsizes_impl(\"arenas.nbins\"));\n}\n\nstatic unsigned\nget_nlarge(void)\n{\n\n\treturn (get_nsizes_impl(\"arenas.nlruns\"));\n}\n\nstatic unsigned\nget_nhuge(void)\n{\n\n\treturn (get_nsizes_impl(\"arenas.nhchunks\"));\n}\n\nstatic size_t\nget_size_impl(const char *cmd, size_t ind)\n{\n\tsize_t ret;\n\tsize_t z;\n\tsize_t mib[4];\n\tsize_t miblen = 4;\n\n\tz = sizeof(size_t);\n\tassert_d_eq(mallctlnametomib(cmd, mib, &miblen),\n\t    0, \"Unexpected mallctlnametomib(\\\"%s\\\", ...) failure\", cmd);\n\tmib[2] = ind;\n\tz = sizeof(size_t);\n\tassert_d_eq(mallctlbymib(mib, miblen, &ret, &z, NULL, 0),\n\t    0, \"Unexpected mallctlbymib([\\\"%s\\\", %zu], ...) failure\", cmd, ind);\n\n\treturn (ret);\n}\n\nstatic size_t\nget_small_size(size_t ind)\n{\n\n\treturn (get_size_impl(\"arenas.bin.0.size\", ind));\n}\n\nstatic size_t\nget_large_size(size_t ind)\n{\n\n\treturn (get_size_impl(\"arenas.lrun.0.size\", ind));\n}\n\nstatic size_t\nget_huge_size(size_t ind)\n{\n\n\treturn (get_size_impl(\"arenas.hchunk.0.size\", ind));\n}\n\nTEST_BEGIN(test_size)\n{\n\tsize_t small0, hugemax;\n\tvoid *p;\n\n\t/* Get size classes. */\n\tsmall0 = get_small_size(0);\n\thugemax = get_huge_size(get_nhuge()-1);\n\n\tp = mallocx(small0, 0);\n\tassert_ptr_not_null(p, \"Unexpected mallocx() error\");\n\n\t/* Test smallest supported size. */\n\tassert_zu_eq(xallocx(p, 1, 0, 0), small0,\n\t    \"Unexpected xallocx() behavior\");\n\n\t/* Test largest supported size. */\n\tassert_zu_le(xallocx(p, hugemax, 0, 0), hugemax,\n\t    \"Unexpected xallocx() behavior\");\n\n\t/* Test size overflow. */\n\tassert_zu_le(xallocx(p, hugemax+1, 0, 0), hugemax,\n\t    \"Unexpected xallocx() behavior\");\n\tassert_zu_le(xallocx(p, SIZE_T_MAX, 0, 0), hugemax,\n\t    \"Unexpected xallocx() behavior\");\n\n\tdallocx(p, 0);\n}\nTEST_END\n\nTEST_BEGIN(test_size_extra_overflow)\n{\n\tsize_t small0, hugemax;\n\tvoid *p;\n\n\t/* Get size classes. */\n\tsmall0 = get_small_size(0);\n\thugemax = get_huge_size(get_nhuge()-1);\n\n\tp = mallocx(small0, 0);\n\tassert_ptr_not_null(p, \"Unexpected mallocx() error\");\n\n\t/* Test overflows that can be resolved by clamping extra. */\n\tassert_zu_le(xallocx(p, hugemax-1, 2, 0), hugemax,\n\t    \"Unexpected xallocx() behavior\");\n\tassert_zu_le(xallocx(p, hugemax, 1, 0), hugemax,\n\t    \"Unexpected xallocx() behavior\");\n\n\t/* Test overflow such that hugemax-size underflows. */\n\tassert_zu_le(xallocx(p, hugemax+1, 2, 0), hugemax,\n\t    \"Unexpected xallocx() behavior\");\n\tassert_zu_le(xallocx(p, hugemax+2, 3, 0), hugemax,\n\t    \"Unexpected xallocx() behavior\");\n\tassert_zu_le(xallocx(p, SIZE_T_MAX-2, 2, 0), hugemax,\n\t    \"Unexpected xallocx() behavior\");\n\tassert_zu_le(xallocx(p, SIZE_T_MAX-1, 1, 0), hugemax,\n\t    \"Unexpected xallocx() behavior\");\n\n\tdallocx(p, 0);\n}\nTEST_END\n\nTEST_BEGIN(test_extra_small)\n{\n\tsize_t small0, small1, hugemax;\n\tvoid *p;\n\n\t/* Get size classes. */\n\tsmall0 = get_small_size(0);\n\tsmall1 = get_small_size(1);\n\thugemax = get_huge_size(get_nhuge()-1);\n\n\tp = mallocx(small0, 0);\n\tassert_ptr_not_null(p, \"Unexpected mallocx() error\");\n\n\tassert_zu_eq(xallocx(p, small1, 0, 0), small0,\n\t    \"Unexpected xallocx() behavior\");\n\n\tassert_zu_eq(xallocx(p, small1, 0, 0), small0,\n\t    \"Unexpected xallocx() behavior\");\n\n\tassert_zu_eq(xallocx(p, small0, small1 - small0, 0), small0,\n\t    \"Unexpected xallocx() behavior\");\n\n\t/* Test size+extra overflow. */\n\tassert_zu_eq(xallocx(p, small0, hugemax - small0 + 1, 0), small0,\n\t    \"Unexpected xallocx() behavior\");\n\tassert_zu_eq(xallocx(p, small0, SIZE_T_MAX - small0, 0), small0,\n\t    \"Unexpected xallocx() behavior\");\n\n\tdallocx(p, 0);\n}\nTEST_END\n\nTEST_BEGIN(test_extra_large)\n{\n\tsize_t smallmax, large0, large1, large2, huge0, hugemax;\n\tvoid *p;\n\n\t/* Get size classes. */\n\tsmallmax = get_small_size(get_nsmall()-1);\n\tlarge0 = get_large_size(0);\n\tlarge1 = get_large_size(1);\n\tlarge2 = get_large_size(2);\n\thuge0 = get_huge_size(0);\n\thugemax = get_huge_size(get_nhuge()-1);\n\n\tp = mallocx(large2, 0);\n\tassert_ptr_not_null(p, \"Unexpected mallocx() error\");\n\n\tassert_zu_eq(xallocx(p, large2, 0, 0), large2,\n\t    \"Unexpected xallocx() behavior\");\n\t/* Test size decrease with zero extra. */\n\tassert_zu_eq(xallocx(p, large0, 0, 0), large0,\n\t    \"Unexpected xallocx() behavior\");\n\tassert_zu_eq(xallocx(p, smallmax, 0, 0), large0,\n\t    \"Unexpected xallocx() behavior\");\n\n\tassert_zu_eq(xallocx(p, large2, 0, 0), large2,\n\t    \"Unexpected xallocx() behavior\");\n\t/* Test size decrease with non-zero extra. */\n\tassert_zu_eq(xallocx(p, large0, large2 - large0, 0), large2,\n\t    \"Unexpected xallocx() behavior\");\n\tassert_zu_eq(xallocx(p, large1, large2 - large1, 0), large2,\n\t    \"Unexpected xallocx() behavior\");\n\tassert_zu_eq(xallocx(p, large0, large1 - large0, 0), large1,\n\t    \"Unexpected xallocx() behavior\");\n\tassert_zu_eq(xallocx(p, smallmax, large0 - smallmax, 0), large0,\n\t    \"Unexpected xallocx() behavior\");\n\n\tassert_zu_eq(xallocx(p, large0, 0, 0), large0,\n\t    \"Unexpected xallocx() behavior\");\n\t/* Test size increase with zero extra. */\n\tassert_zu_eq(xallocx(p, large2, 0, 0), large2,\n\t    \"Unexpected xallocx() behavior\");\n\tassert_zu_eq(xallocx(p, huge0, 0, 0), large2,\n\t    \"Unexpected xallocx() behavior\");\n\n\tassert_zu_eq(xallocx(p, large0, 0, 0), large0,\n\t    \"Unexpected xallocx() behavior\");\n\t/* Test size increase with non-zero extra. */\n\tassert_zu_lt(xallocx(p, large0, huge0 - large0, 0), huge0,\n\t    \"Unexpected xallocx() behavior\");\n\n\tassert_zu_eq(xallocx(p, large0, 0, 0), large0,\n\t    \"Unexpected xallocx() behavior\");\n\t/* Test size increase with non-zero extra. */\n\tassert_zu_eq(xallocx(p, large0, large2 - large0, 0), large2,\n\t    \"Unexpected xallocx() behavior\");\n\n\tassert_zu_eq(xallocx(p, large2, 0, 0), large2,\n\t    \"Unexpected xallocx() behavior\");\n\t/* Test size+extra overflow. */\n\tassert_zu_lt(xallocx(p, large2, hugemax - large2 + 1, 0), huge0,\n\t    \"Unexpected xallocx() behavior\");\n\n\tdallocx(p, 0);\n}\nTEST_END\n\nTEST_BEGIN(test_extra_huge)\n{\n\tsize_t largemax, huge0, huge1, huge2, hugemax;\n\tvoid *p;\n\n\t/* Get size classes. */\n\tlargemax = get_large_size(get_nlarge()-1);\n\thuge0 = get_huge_size(0);\n\thuge1 = get_huge_size(1);\n\thuge2 = get_huge_size(2);\n\thugemax = get_huge_size(get_nhuge()-1);\n\n\tp = mallocx(huge2, 0);\n\tassert_ptr_not_null(p, \"Unexpected mallocx() error\");\n\n\tassert_zu_eq(xallocx(p, huge2, 0, 0), huge2,\n\t    \"Unexpected xallocx() behavior\");\n\t/* Test size decrease with zero extra. */\n\tassert_zu_ge(xallocx(p, huge0, 0, 0), huge0,\n\t    \"Unexpected xallocx() behavior\");\n\tassert_zu_ge(xallocx(p, largemax, 0, 0), huge0,\n\t    \"Unexpected xallocx() behavior\");\n\n\tassert_zu_eq(xallocx(p, huge2, 0, 0), huge2,\n\t    \"Unexpected xallocx() behavior\");\n\t/* Test size decrease with non-zero extra. */\n\tassert_zu_eq(xallocx(p, huge0, huge2 - huge0, 0), huge2,\n\t    \"Unexpected xallocx() behavior\");\n\tassert_zu_eq(xallocx(p, huge1, huge2 - huge1, 0), huge2,\n\t    \"Unexpected xallocx() behavior\");\n\tassert_zu_eq(xallocx(p, huge0, huge1 - huge0, 0), huge1,\n\t    \"Unexpected xallocx() behavior\");\n\tassert_zu_ge(xallocx(p, largemax, huge0 - largemax, 0), huge0,\n\t    \"Unexpected xallocx() behavior\");\n\n\tassert_zu_ge(xallocx(p, huge0, 0, 0), huge0,\n\t    \"Unexpected xallocx() behavior\");\n\t/* Test size increase with zero extra. */\n\tassert_zu_le(xallocx(p, huge2, 0, 0), huge2,\n\t    \"Unexpected xallocx() behavior\");\n\tassert_zu_le(xallocx(p, hugemax+1, 0, 0), huge2,\n\t    \"Unexpected xallocx() behavior\");\n\n\tassert_zu_ge(xallocx(p, huge0, 0, 0), huge0,\n\t    \"Unexpected xallocx() behavior\");\n\t/* Test size increase with non-zero extra. */\n\tassert_zu_le(xallocx(p, huge0, SIZE_T_MAX - huge0, 0), hugemax,\n\t    \"Unexpected xallocx() behavior\");\n\n\tassert_zu_ge(xallocx(p, huge0, 0, 0), huge0,\n\t    \"Unexpected xallocx() behavior\");\n\t/* Test size increase with non-zero extra. */\n\tassert_zu_le(xallocx(p, huge0, huge2 - huge0, 0), huge2,\n\t    \"Unexpected xallocx() behavior\");\n\n\tassert_zu_eq(xallocx(p, huge2, 0, 0), huge2,\n\t    \"Unexpected xallocx() behavior\");\n\t/* Test size+extra overflow. */\n\tassert_zu_le(xallocx(p, huge2, hugemax - huge2 + 1, 0), hugemax,\n\t    \"Unexpected xallocx() behavior\");\n\n\tdallocx(p, 0);\n}\nTEST_END\n\nstatic void\nprint_filled_extents(const void *p, uint8_t c, size_t len)\n{\n\tconst uint8_t *pc = (const uint8_t *)p;\n\tsize_t i, range0;\n\tuint8_t c0;\n\n\tmalloc_printf(\"  p=%p, c=%#x, len=%zu:\", p, c, len);\n\trange0 = 0;\n\tc0 = pc[0];\n\tfor (i = 0; i < len; i++) {\n\t\tif (pc[i] != c0) {\n\t\t\tmalloc_printf(\" %#x[%zu..%zu)\", c0, range0, i);\n\t\t\trange0 = i;\n\t\t\tc0 = pc[i];\n\t\t}\n\t}\n\tmalloc_printf(\" %#x[%zu..%zu)\\n\", c0, range0, i);\n}\n\nstatic bool\nvalidate_fill(const void *p, uint8_t c, size_t offset, size_t len)\n{\n\tconst uint8_t *pc = (const uint8_t *)p;\n\tbool err;\n\tsize_t i;\n\n\tfor (i = offset, err = false; i < offset+len; i++) {\n\t\tif (pc[i] != c)\n\t\t\terr = true;\n\t}\n\n\tif (err)\n\t\tprint_filled_extents(p, c, offset + len);\n\n\treturn (err);\n}\n\nstatic void\ntest_zero(size_t szmin, size_t szmax)\n{\n\tsize_t sz, nsz;\n\tvoid *p;\n#define\tFILL_BYTE 0x7aU\n\n\tsz = szmax;\n\tp = mallocx(sz, MALLOCX_ZERO);\n\tassert_ptr_not_null(p, \"Unexpected mallocx() error\");\n\tassert_false(validate_fill(p, 0x00, 0, sz), \"Memory not filled: sz=%zu\",\n\t    sz);\n\n\t/*\n\t * Fill with non-zero so that non-debug builds are more likely to detect\n\t * errors.\n\t */\n\tmemset(p, FILL_BYTE, sz);\n\tassert_false(validate_fill(p, FILL_BYTE, 0, sz),\n\t    \"Memory not filled: sz=%zu\", sz);\n\n\t/* Shrink in place so that we can expect growing in place to succeed. */\n\tsz = szmin;\n\tassert_zu_eq(xallocx(p, sz, 0, MALLOCX_ZERO), sz,\n\t    \"Unexpected xallocx() error\");\n\tassert_false(validate_fill(p, FILL_BYTE, 0, sz),\n\t    \"Memory not filled: sz=%zu\", sz);\n\n\tfor (sz = szmin; sz < szmax; sz = nsz) {\n\t\tnsz = nallocx(sz+1, MALLOCX_ZERO);\n\t\tassert_zu_eq(xallocx(p, sz+1, 0, MALLOCX_ZERO), nsz,\n\t\t    \"Unexpected xallocx() failure\");\n\t\tassert_false(validate_fill(p, FILL_BYTE, 0, sz),\n\t\t    \"Memory not filled: sz=%zu\", sz);\n\t\tassert_false(validate_fill(p, 0x00, sz, nsz-sz),\n\t\t    \"Memory not filled: sz=%zu, nsz-sz=%zu\", sz, nsz-sz);\n\t\tmemset((void *)((uintptr_t)p + sz), FILL_BYTE, nsz-sz);\n\t\tassert_false(validate_fill(p, FILL_BYTE, 0, nsz),\n\t\t    \"Memory not filled: nsz=%zu\", nsz);\n\t}\n\n\tdallocx(p, 0);\n}\n\nTEST_BEGIN(test_zero_large)\n{\n\tsize_t large0, largemax;\n\n\t/* Get size classes. */\n\tlarge0 = get_large_size(0);\n\tlargemax = get_large_size(get_nlarge()-1);\n\n\ttest_zero(large0, largemax);\n}\nTEST_END\n\nTEST_BEGIN(test_zero_huge)\n{\n\tsize_t huge0, huge1;\n\n\t/* Get size classes. */\n\thuge0 = get_huge_size(0);\n\thuge1 = get_huge_size(1);\n\n\ttest_zero(huge1, huge0 * 2);\n}\nTEST_END\n\nint\nmain(void)\n{\n\n\treturn (test(\n\t    test_same_size,\n\t    test_extra_no_move,\n\t    test_no_move_fail,\n\t    test_size,\n\t    test_size_extra_overflow,\n\t    test_extra_small,\n\t    test_extra_large,\n\t    test_extra_huge,\n\t    test_zero_large,\n\t    test_zero_huge));\n}\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.8/deps/jemalloc/test/src/SFMT.c",
    "content": "/*\n * This file derives from SFMT 1.3.3\n * (http://www.math.sci.hiroshima-u.ac.jp/~m-mat/MT/SFMT/index.html), which was\n * released under the terms of the following license:\n *\n *   Copyright (c) 2006,2007 Mutsuo Saito, Makoto Matsumoto and Hiroshima\n *   University. All rights reserved.\n *\n *   Redistribution and use in source and binary forms, with or without\n *   modification, are permitted provided that the following conditions are\n *   met:\n *\n *       * Redistributions of source code must retain the above copyright\n *         notice, this list of conditions and the following disclaimer.\n *       * Redistributions in binary form must reproduce the above\n *         copyright notice, this list of conditions and the following\n *         disclaimer in the documentation and/or other materials provided\n *         with the distribution.\n *       * Neither the name of the Hiroshima University nor the names of\n *         its contributors may be used to endorse or promote products\n *         derived from this software without specific prior written\n *         permission.\n *\n *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n *   \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\n *   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\n *   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\n *   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n *   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\n *   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n *   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n *   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n *   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n *   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n/** \n * @file  SFMT.c\n * @brief SIMD oriented Fast Mersenne Twister(SFMT)\n *\n * @author Mutsuo Saito (Hiroshima University)\n * @author Makoto Matsumoto (Hiroshima University)\n *\n * Copyright (C) 2006,2007 Mutsuo Saito, Makoto Matsumoto and Hiroshima\n * University. All rights reserved.\n *\n * The new BSD License is applied to this software, see LICENSE.txt\n */\n#define\tSFMT_C_\n#include \"test/jemalloc_test.h\"\n#include \"test/SFMT-params.h\"\n\n#if defined(JEMALLOC_BIG_ENDIAN) && !defined(BIG_ENDIAN64)\n#define BIG_ENDIAN64 1\n#endif\n#if defined(__BIG_ENDIAN__) && !defined(__amd64) && !defined(BIG_ENDIAN64)\n#define BIG_ENDIAN64 1\n#endif\n#if defined(HAVE_ALTIVEC) && !defined(BIG_ENDIAN64)\n#define BIG_ENDIAN64 1\n#endif\n#if defined(ONLY64) && !defined(BIG_ENDIAN64)\n  #if defined(__GNUC__)\n    #error \"-DONLY64 must be specified with -DBIG_ENDIAN64\"\n  #endif\n#undef ONLY64\n#endif\n/*------------------------------------------------------\n  128-bit SIMD data type for Altivec, SSE2 or standard C\n  ------------------------------------------------------*/\n#if defined(HAVE_ALTIVEC)\n/** 128-bit data structure */\nunion W128_T {\n    vector unsigned int s;\n    uint32_t u[4];\n};\n/** 128-bit data type */\ntypedef union W128_T w128_t;\n\n#elif defined(HAVE_SSE2)\n/** 128-bit data structure */\nunion W128_T {\n    __m128i si;\n    uint32_t u[4];\n};\n/** 128-bit data type */\ntypedef union W128_T w128_t;\n\n#else\n\n/** 128-bit data structure */\nstruct W128_T {\n    uint32_t u[4];\n};\n/** 128-bit data type */\ntypedef struct W128_T w128_t;\n\n#endif\n\nstruct sfmt_s {\n    /** the 128-bit internal state array */\n    w128_t sfmt[N];\n    /** index counter to the 32-bit internal state array */\n    int idx;\n    /** a flag: it is 0 if and only if the internal state is not yet\n     * initialized. */\n    int initialized;\n};\n\n/*--------------------------------------\n  FILE GLOBAL VARIABLES\n  internal state, index counter and flag \n  --------------------------------------*/\n\n/** a parity check vector which certificate the period of 2^{MEXP} */\nstatic uint32_t parity[4] = {PARITY1, PARITY2, PARITY3, PARITY4};\n\n/*----------------\n  STATIC FUNCTIONS\n  ----------------*/\nJEMALLOC_INLINE_C int idxof(int i);\n#if (!defined(HAVE_ALTIVEC)) && (!defined(HAVE_SSE2))\nJEMALLOC_INLINE_C void rshift128(w128_t *out,  w128_t const *in, int shift);\nJEMALLOC_INLINE_C void lshift128(w128_t *out,  w128_t const *in, int shift);\n#endif\nJEMALLOC_INLINE_C void gen_rand_all(sfmt_t *ctx);\nJEMALLOC_INLINE_C void gen_rand_array(sfmt_t *ctx, w128_t *array, int size);\nJEMALLOC_INLINE_C uint32_t func1(uint32_t x);\nJEMALLOC_INLINE_C uint32_t func2(uint32_t x);\nstatic void period_certification(sfmt_t *ctx);\n#if defined(BIG_ENDIAN64) && !defined(ONLY64)\nJEMALLOC_INLINE_C void swap(w128_t *array, int size);\n#endif\n\n#if defined(HAVE_ALTIVEC)\n  #include \"test/SFMT-alti.h\"\n#elif defined(HAVE_SSE2)\n  #include \"test/SFMT-sse2.h\"\n#endif\n\n/**\n * This function simulate a 64-bit index of LITTLE ENDIAN \n * in BIG ENDIAN machine.\n */\n#ifdef ONLY64\nJEMALLOC_INLINE_C int idxof(int i) {\n    return i ^ 1;\n}\n#else\nJEMALLOC_INLINE_C int idxof(int i) {\n    return i;\n}\n#endif\n/**\n * This function simulates SIMD 128-bit right shift by the standard C.\n * The 128-bit integer given in in is shifted by (shift * 8) bits.\n * This function simulates the LITTLE ENDIAN SIMD.\n * @param out the output of this function\n * @param in the 128-bit data to be shifted\n * @param shift the shift value\n */\n#if (!defined(HAVE_ALTIVEC)) && (!defined(HAVE_SSE2))\n#ifdef ONLY64\nJEMALLOC_INLINE_C void rshift128(w128_t *out, w128_t const *in, int shift) {\n    uint64_t th, tl, oh, ol;\n\n    th = ((uint64_t)in->u[2] << 32) | ((uint64_t)in->u[3]);\n    tl = ((uint64_t)in->u[0] << 32) | ((uint64_t)in->u[1]);\n\n    oh = th >> (shift * 8);\n    ol = tl >> (shift * 8);\n    ol |= th << (64 - shift * 8);\n    out->u[0] = (uint32_t)(ol >> 32);\n    out->u[1] = (uint32_t)ol;\n    out->u[2] = (uint32_t)(oh >> 32);\n    out->u[3] = (uint32_t)oh;\n}\n#else\nJEMALLOC_INLINE_C void rshift128(w128_t *out, w128_t const *in, int shift) {\n    uint64_t th, tl, oh, ol;\n\n    th = ((uint64_t)in->u[3] << 32) | ((uint64_t)in->u[2]);\n    tl = ((uint64_t)in->u[1] << 32) | ((uint64_t)in->u[0]);\n\n    oh = th >> (shift * 8);\n    ol = tl >> (shift * 8);\n    ol |= th << (64 - shift * 8);\n    out->u[1] = (uint32_t)(ol >> 32);\n    out->u[0] = (uint32_t)ol;\n    out->u[3] = (uint32_t)(oh >> 32);\n    out->u[2] = (uint32_t)oh;\n}\n#endif\n/**\n * This function simulates SIMD 128-bit left shift by the standard C.\n * The 128-bit integer given in in is shifted by (shift * 8) bits.\n * This function simulates the LITTLE ENDIAN SIMD.\n * @param out the output of this function\n * @param in the 128-bit data to be shifted\n * @param shift the shift value\n */\n#ifdef ONLY64\nJEMALLOC_INLINE_C void lshift128(w128_t *out, w128_t const *in, int shift) {\n    uint64_t th, tl, oh, ol;\n\n    th = ((uint64_t)in->u[2] << 32) | ((uint64_t)in->u[3]);\n    tl = ((uint64_t)in->u[0] << 32) | ((uint64_t)in->u[1]);\n\n    oh = th << (shift * 8);\n    ol = tl << (shift * 8);\n    oh |= tl >> (64 - shift * 8);\n    out->u[0] = (uint32_t)(ol >> 32);\n    out->u[1] = (uint32_t)ol;\n    out->u[2] = (uint32_t)(oh >> 32);\n    out->u[3] = (uint32_t)oh;\n}\n#else\nJEMALLOC_INLINE_C void lshift128(w128_t *out, w128_t const *in, int shift) {\n    uint64_t th, tl, oh, ol;\n\n    th = ((uint64_t)in->u[3] << 32) | ((uint64_t)in->u[2]);\n    tl = ((uint64_t)in->u[1] << 32) | ((uint64_t)in->u[0]);\n\n    oh = th << (shift * 8);\n    ol = tl << (shift * 8);\n    oh |= tl >> (64 - shift * 8);\n    out->u[1] = (uint32_t)(ol >> 32);\n    out->u[0] = (uint32_t)ol;\n    out->u[3] = (uint32_t)(oh >> 32);\n    out->u[2] = (uint32_t)oh;\n}\n#endif\n#endif\n\n/**\n * This function represents the recursion formula.\n * @param r output\n * @param a a 128-bit part of the internal state array\n * @param b a 128-bit part of the internal state array\n * @param c a 128-bit part of the internal state array\n * @param d a 128-bit part of the internal state array\n */\n#if (!defined(HAVE_ALTIVEC)) && (!defined(HAVE_SSE2))\n#ifdef ONLY64\nJEMALLOC_INLINE_C void do_recursion(w128_t *r, w128_t *a, w128_t *b, w128_t *c,\n\t\t\t\tw128_t *d) {\n    w128_t x;\n    w128_t y;\n\n    lshift128(&x, a, SL2);\n    rshift128(&y, c, SR2);\n    r->u[0] = a->u[0] ^ x.u[0] ^ ((b->u[0] >> SR1) & MSK2) ^ y.u[0] \n\t^ (d->u[0] << SL1);\n    r->u[1] = a->u[1] ^ x.u[1] ^ ((b->u[1] >> SR1) & MSK1) ^ y.u[1] \n\t^ (d->u[1] << SL1);\n    r->u[2] = a->u[2] ^ x.u[2] ^ ((b->u[2] >> SR1) & MSK4) ^ y.u[2] \n\t^ (d->u[2] << SL1);\n    r->u[3] = a->u[3] ^ x.u[3] ^ ((b->u[3] >> SR1) & MSK3) ^ y.u[3] \n\t^ (d->u[3] << SL1);\n}\n#else\nJEMALLOC_INLINE_C void do_recursion(w128_t *r, w128_t *a, w128_t *b, w128_t *c,\n\t\t\t\tw128_t *d) {\n    w128_t x;\n    w128_t y;\n\n    lshift128(&x, a, SL2);\n    rshift128(&y, c, SR2);\n    r->u[0] = a->u[0] ^ x.u[0] ^ ((b->u[0] >> SR1) & MSK1) ^ y.u[0] \n\t^ (d->u[0] << SL1);\n    r->u[1] = a->u[1] ^ x.u[1] ^ ((b->u[1] >> SR1) & MSK2) ^ y.u[1] \n\t^ (d->u[1] << SL1);\n    r->u[2] = a->u[2] ^ x.u[2] ^ ((b->u[2] >> SR1) & MSK3) ^ y.u[2] \n\t^ (d->u[2] << SL1);\n    r->u[3] = a->u[3] ^ x.u[3] ^ ((b->u[3] >> SR1) & MSK4) ^ y.u[3] \n\t^ (d->u[3] << SL1);\n}\n#endif\n#endif\n\n#if (!defined(HAVE_ALTIVEC)) && (!defined(HAVE_SSE2))\n/**\n * This function fills the internal state array with pseudorandom\n * integers.\n */\nJEMALLOC_INLINE_C void gen_rand_all(sfmt_t *ctx) {\n    int i;\n    w128_t *r1, *r2;\n\n    r1 = &ctx->sfmt[N - 2];\n    r2 = &ctx->sfmt[N - 1];\n    for (i = 0; i < N - POS1; i++) {\n\tdo_recursion(&ctx->sfmt[i], &ctx->sfmt[i], &ctx->sfmt[i + POS1], r1,\n\t  r2);\n\tr1 = r2;\n\tr2 = &ctx->sfmt[i];\n    }\n    for (; i < N; i++) {\n\tdo_recursion(&ctx->sfmt[i], &ctx->sfmt[i], &ctx->sfmt[i + POS1 - N], r1,\n\t  r2);\n\tr1 = r2;\n\tr2 = &ctx->sfmt[i];\n    }\n}\n\n/**\n * This function fills the user-specified array with pseudorandom\n * integers.\n *\n * @param array an 128-bit array to be filled by pseudorandom numbers.  \n * @param size number of 128-bit pseudorandom numbers to be generated.\n */\nJEMALLOC_INLINE_C void gen_rand_array(sfmt_t *ctx, w128_t *array, int size) {\n    int i, j;\n    w128_t *r1, *r2;\n\n    r1 = &ctx->sfmt[N - 2];\n    r2 = &ctx->sfmt[N - 1];\n    for (i = 0; i < N - POS1; i++) {\n\tdo_recursion(&array[i], &ctx->sfmt[i], &ctx->sfmt[i + POS1], r1, r2);\n\tr1 = r2;\n\tr2 = &array[i];\n    }\n    for (; i < N; i++) {\n\tdo_recursion(&array[i], &ctx->sfmt[i], &array[i + POS1 - N], r1, r2);\n\tr1 = r2;\n\tr2 = &array[i];\n    }\n    for (; i < size - N; i++) {\n\tdo_recursion(&array[i], &array[i - N], &array[i + POS1 - N], r1, r2);\n\tr1 = r2;\n\tr2 = &array[i];\n    }\n    for (j = 0; j < 2 * N - size; j++) {\n\tctx->sfmt[j] = array[j + size - N];\n    }\n    for (; i < size; i++, j++) {\n\tdo_recursion(&array[i], &array[i - N], &array[i + POS1 - N], r1, r2);\n\tr1 = r2;\n\tr2 = &array[i];\n\tctx->sfmt[j] = array[i];\n    }\n}\n#endif\n\n#if defined(BIG_ENDIAN64) && !defined(ONLY64) && !defined(HAVE_ALTIVEC)\nJEMALLOC_INLINE_C void swap(w128_t *array, int size) {\n    int i;\n    uint32_t x, y;\n\n    for (i = 0; i < size; i++) {\n\tx = array[i].u[0];\n\ty = array[i].u[2];\n\tarray[i].u[0] = array[i].u[1];\n\tarray[i].u[2] = array[i].u[3];\n\tarray[i].u[1] = x;\n\tarray[i].u[3] = y;\n    }\n}\n#endif\n/**\n * This function represents a function used in the initialization\n * by init_by_array\n * @param x 32-bit integer\n * @return 32-bit integer\n */\nstatic uint32_t func1(uint32_t x) {\n    return (x ^ (x >> 27)) * (uint32_t)1664525UL;\n}\n\n/**\n * This function represents a function used in the initialization\n * by init_by_array\n * @param x 32-bit integer\n * @return 32-bit integer\n */\nstatic uint32_t func2(uint32_t x) {\n    return (x ^ (x >> 27)) * (uint32_t)1566083941UL;\n}\n\n/**\n * This function certificate the period of 2^{MEXP}\n */\nstatic void period_certification(sfmt_t *ctx) {\n    int inner = 0;\n    int i, j;\n    uint32_t work;\n    uint32_t *psfmt32 = &ctx->sfmt[0].u[0];\n\n    for (i = 0; i < 4; i++)\n\tinner ^= psfmt32[idxof(i)] & parity[i];\n    for (i = 16; i > 0; i >>= 1)\n\tinner ^= inner >> i;\n    inner &= 1;\n    /* check OK */\n    if (inner == 1) {\n\treturn;\n    }\n    /* check NG, and modification */\n    for (i = 0; i < 4; i++) {\n\twork = 1;\n\tfor (j = 0; j < 32; j++) {\n\t    if ((work & parity[i]) != 0) {\n\t\tpsfmt32[idxof(i)] ^= work;\n\t\treturn;\n\t    }\n\t    work = work << 1;\n\t}\n    }\n}\n\n/*----------------\n  PUBLIC FUNCTIONS\n  ----------------*/\n/**\n * This function returns the identification string.\n * The string shows the word size, the Mersenne exponent,\n * and all parameters of this generator.\n */\nconst char *get_idstring(void) {\n    return IDSTR;\n}\n\n/**\n * This function returns the minimum size of array used for \\b\n * fill_array32() function.\n * @return minimum size of array used for fill_array32() function.\n */\nint get_min_array_size32(void) {\n    return N32;\n}\n\n/**\n * This function returns the minimum size of array used for \\b\n * fill_array64() function.\n * @return minimum size of array used for fill_array64() function.\n */\nint get_min_array_size64(void) {\n    return N64;\n}\n\n#ifndef ONLY64\n/**\n * This function generates and returns 32-bit pseudorandom number.\n * init_gen_rand or init_by_array must be called before this function.\n * @return 32-bit pseudorandom number\n */\nuint32_t gen_rand32(sfmt_t *ctx) {\n    uint32_t r;\n    uint32_t *psfmt32 = &ctx->sfmt[0].u[0];\n\n    assert(ctx->initialized);\n    if (ctx->idx >= N32) {\n\tgen_rand_all(ctx);\n\tctx->idx = 0;\n    }\n    r = psfmt32[ctx->idx++];\n    return r;\n}\n\n/* Generate a random integer in [0..limit). */\nuint32_t gen_rand32_range(sfmt_t *ctx, uint32_t limit) {\n    uint32_t ret, above;\n\n    above = 0xffffffffU - (0xffffffffU % limit);\n    while (1) {\n\tret = gen_rand32(ctx);\n\tif (ret < above) {\n\t    ret %= limit;\n\t    break;\n\t}\n    }\n    return ret;\n}\n#endif\n/**\n * This function generates and returns 64-bit pseudorandom number.\n * init_gen_rand or init_by_array must be called before this function.\n * The function gen_rand64 should not be called after gen_rand32,\n * unless an initialization is again executed. \n * @return 64-bit pseudorandom number\n */\nuint64_t gen_rand64(sfmt_t *ctx) {\n#if defined(BIG_ENDIAN64) && !defined(ONLY64)\n    uint32_t r1, r2;\n    uint32_t *psfmt32 = &ctx->sfmt[0].u[0];\n#else\n    uint64_t r;\n    uint64_t *psfmt64 = (uint64_t *)&ctx->sfmt[0].u[0];\n#endif\n\n    assert(ctx->initialized);\n    assert(ctx->idx % 2 == 0);\n\n    if (ctx->idx >= N32) {\n\tgen_rand_all(ctx);\n\tctx->idx = 0;\n    }\n#if defined(BIG_ENDIAN64) && !defined(ONLY64)\n    r1 = psfmt32[ctx->idx];\n    r2 = psfmt32[ctx->idx + 1];\n    ctx->idx += 2;\n    return ((uint64_t)r2 << 32) | r1;\n#else\n    r = psfmt64[ctx->idx / 2];\n    ctx->idx += 2;\n    return r;\n#endif\n}\n\n/* Generate a random integer in [0..limit). */\nuint64_t gen_rand64_range(sfmt_t *ctx, uint64_t limit) {\n    uint64_t ret, above;\n\n    above = KQU(0xffffffffffffffff) - (KQU(0xffffffffffffffff) % limit);\n    while (1) {\n\tret = gen_rand64(ctx);\n\tif (ret < above) {\n\t    ret %= limit;\n\t    break;\n\t}\n    }\n    return ret;\n}\n\n#ifndef ONLY64\n/**\n * This function generates pseudorandom 32-bit integers in the\n * specified array[] by one call. The number of pseudorandom integers\n * is specified by the argument size, which must be at least 624 and a\n * multiple of four.  The generation by this function is much faster\n * than the following gen_rand function.\n *\n * For initialization, init_gen_rand or init_by_array must be called\n * before the first call of this function. This function can not be\n * used after calling gen_rand function, without initialization.\n *\n * @param array an array where pseudorandom 32-bit integers are filled\n * by this function.  The pointer to the array must be \\b \"aligned\"\n * (namely, must be a multiple of 16) in the SIMD version, since it\n * refers to the address of a 128-bit integer.  In the standard C\n * version, the pointer is arbitrary.\n *\n * @param size the number of 32-bit pseudorandom integers to be\n * generated.  size must be a multiple of 4, and greater than or equal\n * to (MEXP / 128 + 1) * 4.\n *\n * @note \\b memalign or \\b posix_memalign is available to get aligned\n * memory. Mac OSX doesn't have these functions, but \\b malloc of OSX\n * returns the pointer to the aligned memory block.\n */\nvoid fill_array32(sfmt_t *ctx, uint32_t *array, int size) {\n    assert(ctx->initialized);\n    assert(ctx->idx == N32);\n    assert(size % 4 == 0);\n    assert(size >= N32);\n\n    gen_rand_array(ctx, (w128_t *)array, size / 4);\n    ctx->idx = N32;\n}\n#endif\n\n/**\n * This function generates pseudorandom 64-bit integers in the\n * specified array[] by one call. The number of pseudorandom integers\n * is specified by the argument size, which must be at least 312 and a\n * multiple of two.  The generation by this function is much faster\n * than the following gen_rand function.\n *\n * For initialization, init_gen_rand or init_by_array must be called\n * before the first call of this function. This function can not be\n * used after calling gen_rand function, without initialization.\n *\n * @param array an array where pseudorandom 64-bit integers are filled\n * by this function.  The pointer to the array must be \"aligned\"\n * (namely, must be a multiple of 16) in the SIMD version, since it\n * refers to the address of a 128-bit integer.  In the standard C\n * version, the pointer is arbitrary.\n *\n * @param size the number of 64-bit pseudorandom integers to be\n * generated.  size must be a multiple of 2, and greater than or equal\n * to (MEXP / 128 + 1) * 2\n *\n * @note \\b memalign or \\b posix_memalign is available to get aligned\n * memory. Mac OSX doesn't have these functions, but \\b malloc of OSX\n * returns the pointer to the aligned memory block.\n */\nvoid fill_array64(sfmt_t *ctx, uint64_t *array, int size) {\n    assert(ctx->initialized);\n    assert(ctx->idx == N32);\n    assert(size % 2 == 0);\n    assert(size >= N64);\n\n    gen_rand_array(ctx, (w128_t *)array, size / 2);\n    ctx->idx = N32;\n\n#if defined(BIG_ENDIAN64) && !defined(ONLY64)\n    swap((w128_t *)array, size /2);\n#endif\n}\n\n/**\n * This function initializes the internal state array with a 32-bit\n * integer seed.\n *\n * @param seed a 32-bit integer used as the seed.\n */\nsfmt_t *init_gen_rand(uint32_t seed) {\n    void *p;\n    sfmt_t *ctx;\n    int i;\n    uint32_t *psfmt32;\n\n    if (posix_memalign(&p, sizeof(w128_t), sizeof(sfmt_t)) != 0) {\n\treturn NULL;\n    }\n    ctx = (sfmt_t *)p;\n    psfmt32 = &ctx->sfmt[0].u[0];\n\n    psfmt32[idxof(0)] = seed;\n    for (i = 1; i < N32; i++) {\n\tpsfmt32[idxof(i)] = 1812433253UL * (psfmt32[idxof(i - 1)] \n\t\t\t\t\t    ^ (psfmt32[idxof(i - 1)] >> 30))\n\t    + i;\n    }\n    ctx->idx = N32;\n    period_certification(ctx);\n    ctx->initialized = 1;\n\n    return ctx;\n}\n\n/**\n * This function initializes the internal state array,\n * with an array of 32-bit integers used as the seeds\n * @param init_key the array of 32-bit integers, used as a seed.\n * @param key_length the length of init_key.\n */\nsfmt_t *init_by_array(uint32_t *init_key, int key_length) {\n    void *p;\n    sfmt_t *ctx;\n    int i, j, count;\n    uint32_t r;\n    int lag;\n    int mid;\n    int size = N * 4;\n    uint32_t *psfmt32;\n\n    if (posix_memalign(&p, sizeof(w128_t), sizeof(sfmt_t)) != 0) {\n\treturn NULL;\n    }\n    ctx = (sfmt_t *)p;\n    psfmt32 = &ctx->sfmt[0].u[0];\n\n    if (size >= 623) {\n\tlag = 11;\n    } else if (size >= 68) {\n\tlag = 7;\n    } else if (size >= 39) {\n\tlag = 5;\n    } else {\n\tlag = 3;\n    }\n    mid = (size - lag) / 2;\n\n    memset(ctx->sfmt, 0x8b, sizeof(ctx->sfmt));\n    if (key_length + 1 > N32) {\n\tcount = key_length + 1;\n    } else {\n\tcount = N32;\n    }\n    r = func1(psfmt32[idxof(0)] ^ psfmt32[idxof(mid)] \n\t      ^ psfmt32[idxof(N32 - 1)]);\n    psfmt32[idxof(mid)] += r;\n    r += key_length;\n    psfmt32[idxof(mid + lag)] += r;\n    psfmt32[idxof(0)] = r;\n\n    count--;\n    for (i = 1, j = 0; (j < count) && (j < key_length); j++) {\n\tr = func1(psfmt32[idxof(i)] ^ psfmt32[idxof((i + mid) % N32)] \n\t\t  ^ psfmt32[idxof((i + N32 - 1) % N32)]);\n\tpsfmt32[idxof((i + mid) % N32)] += r;\n\tr += init_key[j] + i;\n\tpsfmt32[idxof((i + mid + lag) % N32)] += r;\n\tpsfmt32[idxof(i)] = r;\n\ti = (i + 1) % N32;\n    }\n    for (; j < count; j++) {\n\tr = func1(psfmt32[idxof(i)] ^ psfmt32[idxof((i + mid) % N32)] \n\t\t  ^ psfmt32[idxof((i + N32 - 1) % N32)]);\n\tpsfmt32[idxof((i + mid) % N32)] += r;\n\tr += i;\n\tpsfmt32[idxof((i + mid + lag) % N32)] += r;\n\tpsfmt32[idxof(i)] = r;\n\ti = (i + 1) % N32;\n    }\n    for (j = 0; j < N32; j++) {\n\tr = func2(psfmt32[idxof(i)] + psfmt32[idxof((i + mid) % N32)] \n\t\t  + psfmt32[idxof((i + N32 - 1) % N32)]);\n\tpsfmt32[idxof((i + mid) % N32)] ^= r;\n\tr -= i;\n\tpsfmt32[idxof((i + mid + lag) % N32)] ^= r;\n\tpsfmt32[idxof(i)] = r;\n\ti = (i + 1) % N32;\n    }\n\n    ctx->idx = N32;\n    period_certification(ctx);\n    ctx->initialized = 1;\n\n    return ctx;\n}\n\nvoid fini_gen_rand(sfmt_t *ctx) {\n    assert(ctx != NULL);\n\n    ctx->initialized = 0;\n    free(ctx);\n}\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.8/deps/jemalloc/test/src/btalloc.c",
    "content": "#include \"test/jemalloc_test.h\"\n\nvoid *\nbtalloc(size_t size, unsigned bits)\n{\n\n\treturn (btalloc_0(size, bits));\n}\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.8/deps/jemalloc/test/src/btalloc_0.c",
    "content": "#include \"test/jemalloc_test.h\"\n\nbtalloc_n_gen(0)\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.8/deps/jemalloc/test/src/btalloc_1.c",
    "content": "#include \"test/jemalloc_test.h\"\n\nbtalloc_n_gen(1)\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.8/deps/jemalloc/test/src/math.c",
    "content": "#define\tMATH_C_\n#include \"test/jemalloc_test.h\"\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.8/deps/jemalloc/test/src/mq.c",
    "content": "#include \"test/jemalloc_test.h\"\n\n/*\n * Sleep for approximately ns nanoseconds.  No lower *nor* upper bound on sleep\n * time is guaranteed.\n */\nvoid\nmq_nanosleep(unsigned ns)\n{\n\n\tassert(ns <= 1000*1000*1000);\n\n#ifdef _WIN32\n\tSleep(ns / 1000);\n#else\n\t{\n\t\tstruct timespec timeout;\n\n\t\tif (ns < 1000*1000*1000) {\n\t\t\ttimeout.tv_sec = 0;\n\t\t\ttimeout.tv_nsec = ns;\n\t\t} else {\n\t\t\ttimeout.tv_sec = 1;\n\t\t\ttimeout.tv_nsec = 0;\n\t\t}\n\t\tnanosleep(&timeout, NULL);\n\t}\n#endif\n}\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.8/deps/jemalloc/test/src/mtx.c",
    "content": "#include \"test/jemalloc_test.h\"\n\n#ifndef _CRT_SPINCOUNT\n#define\t_CRT_SPINCOUNT 4000\n#endif\n\nbool\nmtx_init(mtx_t *mtx)\n{\n\n#ifdef _WIN32\n\tif (!InitializeCriticalSectionAndSpinCount(&mtx->lock, _CRT_SPINCOUNT))\n\t\treturn (true);\n#elif (defined(JEMALLOC_OSSPIN))\n\tmtx->lock = 0;\n#else\n\tpthread_mutexattr_t attr;\n\n\tif (pthread_mutexattr_init(&attr) != 0)\n\t\treturn (true);\n\tpthread_mutexattr_settype(&attr, PTHREAD_MUTEX_DEFAULT);\n\tif (pthread_mutex_init(&mtx->lock, &attr) != 0) {\n\t\tpthread_mutexattr_destroy(&attr);\n\t\treturn (true);\n\t}\n\tpthread_mutexattr_destroy(&attr);\n#endif\n\treturn (false);\n}\n\nvoid\nmtx_fini(mtx_t *mtx)\n{\n\n#ifdef _WIN32\n#elif (defined(JEMALLOC_OSSPIN))\n#else\n\tpthread_mutex_destroy(&mtx->lock);\n#endif\n}\n\nvoid\nmtx_lock(mtx_t *mtx)\n{\n\n#ifdef _WIN32\n\tEnterCriticalSection(&mtx->lock);\n#elif (defined(JEMALLOC_OSSPIN))\n\tOSSpinLockLock(&mtx->lock);\n#else\n\tpthread_mutex_lock(&mtx->lock);\n#endif\n}\n\nvoid\nmtx_unlock(mtx_t *mtx)\n{\n\n#ifdef _WIN32\n\tLeaveCriticalSection(&mtx->lock);\n#elif (defined(JEMALLOC_OSSPIN))\n\tOSSpinLockUnlock(&mtx->lock);\n#else\n\tpthread_mutex_unlock(&mtx->lock);\n#endif\n}\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.8/deps/jemalloc/test/src/test.c",
    "content": "#include \"test/jemalloc_test.h\"\n\nstatic unsigned\t\ttest_count = 0;\nstatic test_status_t\ttest_counts[test_status_count] = {0, 0, 0};\nstatic test_status_t\ttest_status = test_status_pass;\nstatic const char *\ttest_name = \"\";\n\nJEMALLOC_FORMAT_PRINTF(1, 2)\nvoid\ntest_skip(const char *format, ...)\n{\n\tva_list ap;\n\n\tva_start(ap, format);\n\tmalloc_vcprintf(NULL, NULL, format, ap);\n\tva_end(ap);\n\tmalloc_printf(\"\\n\");\n\ttest_status = test_status_skip;\n}\n\nJEMALLOC_FORMAT_PRINTF(1, 2)\nvoid\ntest_fail(const char *format, ...)\n{\n\tva_list ap;\n\n\tva_start(ap, format);\n\tmalloc_vcprintf(NULL, NULL, format, ap);\n\tva_end(ap);\n\tmalloc_printf(\"\\n\");\n\ttest_status = test_status_fail;\n}\n\nstatic const char *\ntest_status_string(test_status_t test_status)\n{\n\n\tswitch (test_status) {\n\tcase test_status_pass: return \"pass\";\n\tcase test_status_skip: return \"skip\";\n\tcase test_status_fail: return \"fail\";\n\tdefault: not_reached();\n\t}\n}\n\nvoid\np_test_init(const char *name)\n{\n\n\ttest_count++;\n\ttest_status = test_status_pass;\n\ttest_name = name;\n}\n\nvoid\np_test_fini(void)\n{\n\n\ttest_counts[test_status]++;\n\tmalloc_printf(\"%s: %s\\n\", test_name, test_status_string(test_status));\n}\n\ntest_status_t\np_test(test_t *t, ...)\n{\n\ttest_status_t ret;\n\tva_list ap;\n\n\t/*\n\t * Make sure initialization occurs prior to running tests.  Tests are\n\t * special because they may use internal facilities prior to triggering\n\t * initialization as a side effect of calling into the public API.  This\n\t * is a final safety that works even if jemalloc_constructor() doesn't\n\t * run, as for MSVC builds.\n\t */\n\tif (nallocx(1, 0) == 0) {\n\t\tmalloc_printf(\"Initialization error\");\n\t\treturn (test_status_fail);\n\t}\n\n\tret = test_status_pass;\n\tva_start(ap, t);\n\tfor (; t != NULL; t = va_arg(ap, test_t *)) {\n\t\tt();\n\t\tif (test_status > ret)\n\t\t\tret = test_status;\n\t}\n\tva_end(ap);\n\n\tmalloc_printf(\"--- %s: %u/%u, %s: %u/%u, %s: %u/%u ---\\n\",\n\t    test_status_string(test_status_pass),\n\t    test_counts[test_status_pass], test_count,\n\t    test_status_string(test_status_skip),\n\t    test_counts[test_status_skip], test_count,\n\t    test_status_string(test_status_fail),\n\t    test_counts[test_status_fail], test_count);\n\n\treturn (ret);\n}\n\nvoid\np_test_fail(const char *prefix, const char *message)\n{\n\n\tmalloc_cprintf(NULL, NULL, \"%s%s\\n\", prefix, message);\n\ttest_status = test_status_fail;\n}\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.8/deps/jemalloc/test/src/thd.c",
    "content": "#include \"test/jemalloc_test.h\"\n\n#ifdef _WIN32\nvoid\nthd_create(thd_t *thd, void *(*proc)(void *), void *arg)\n{\n\tLPTHREAD_START_ROUTINE routine = (LPTHREAD_START_ROUTINE)proc;\n\t*thd = CreateThread(NULL, 0, routine, arg, 0, NULL);\n\tif (*thd == NULL)\n\t\ttest_fail(\"Error in CreateThread()\\n\");\n}\n\nvoid\nthd_join(thd_t thd, void **ret)\n{\n\n\tif (WaitForSingleObject(thd, INFINITE) == WAIT_OBJECT_0 && ret) {\n\t\tDWORD exit_code;\n\t\tGetExitCodeThread(thd, (LPDWORD) &exit_code);\n\t\t*ret = (void *)(uintptr_t)exit_code;\n\t}\n}\n\n#else\nvoid\nthd_create(thd_t *thd, void *(*proc)(void *), void *arg)\n{\n\n\tif (pthread_create(thd, NULL, proc, arg) != 0)\n\t\ttest_fail(\"Error in pthread_create()\\n\");\n}\n\nvoid\nthd_join(thd_t thd, void **ret)\n{\n\n\tpthread_join(thd, ret);\n}\n#endif\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.8/deps/jemalloc/test/src/timer.c",
    "content": "#include \"test/jemalloc_test.h\"\n\nvoid\ntimer_start(timedelta_t *timer)\n{\n\n#ifdef _WIN32\n\tGetSystemTimeAsFileTime(&timer->ft0);\n#elif JEMALLOC_CLOCK_GETTIME\n\tif (sysconf(_SC_MONOTONIC_CLOCK) <= 0)\n\t\ttimer->clock_id = CLOCK_REALTIME;\n\telse\n\t\ttimer->clock_id = CLOCK_MONOTONIC;\n\tclock_gettime(timer->clock_id, &timer->ts0);\n#else\n\tgettimeofday(&timer->tv0, NULL);\n#endif\n}\n\nvoid\ntimer_stop(timedelta_t *timer)\n{\n\n#ifdef _WIN32\n\tGetSystemTimeAsFileTime(&timer->ft0);\n#elif JEMALLOC_CLOCK_GETTIME\n\tclock_gettime(timer->clock_id, &timer->ts1);\n#else\n\tgettimeofday(&timer->tv1, NULL);\n#endif\n}\n\nuint64_t\ntimer_usec(const timedelta_t *timer)\n{\n\n#ifdef _WIN32\n\tuint64_t t0, t1;\n\tt0 = (((uint64_t)timer->ft0.dwHighDateTime) << 32) |\n\t    timer->ft0.dwLowDateTime;\n\tt1 = (((uint64_t)timer->ft1.dwHighDateTime) << 32) |\n\t    timer->ft1.dwLowDateTime;\n\treturn ((t1 - t0) / 10);\n#elif JEMALLOC_CLOCK_GETTIME\n\treturn (((timer->ts1.tv_sec - timer->ts0.tv_sec) * 1000000) +\n\t    (timer->ts1.tv_nsec - timer->ts0.tv_nsec) / 1000);\n#else\n\treturn (((timer->tv1.tv_sec - timer->tv0.tv_sec) * 1000000) +\n\t    timer->tv1.tv_usec - timer->tv0.tv_usec);\n#endif\n}\n\nvoid\ntimer_ratio(timedelta_t *a, timedelta_t *b, char *buf, size_t buflen)\n{\n\tuint64_t t0 = timer_usec(a);\n\tuint64_t t1 = timer_usec(b);\n\tuint64_t mult;\n\tunsigned i = 0;\n\tunsigned j;\n\tint n;\n\n\t/* Whole. */\n\tn = malloc_snprintf(&buf[i], buflen-i, \"%\"FMTu64, t0 / t1);\n\ti += n;\n\tif (i >= buflen)\n\t\treturn;\n\tmult = 1;\n\tfor (j = 0; j < n; j++)\n\t\tmult *= 10;\n\n\t/* Decimal. */\n\tn = malloc_snprintf(&buf[i], buflen-i, \".\");\n\ti += n;\n\n\t/* Fraction. */\n\twhile (i < buflen-1) {\n\t\tuint64_t round = (i+1 == buflen-1 && ((t0 * mult * 10 / t1) % 10\n\t\t    >= 5)) ? 1 : 0;\n\t\tn = malloc_snprintf(&buf[i], buflen-i,\n\t\t    \"%\"FMTu64, (t0 * mult / t1) % 10 + round);\n\t\ti += n;\n\t\tmult *= 10;\n\t}\n}\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.8/deps/jemalloc/test/stress/microbench.c",
    "content": "#include \"test/jemalloc_test.h\"\n\nJEMALLOC_INLINE_C void\ntime_func(timedelta_t *timer, uint64_t nwarmup, uint64_t niter, void (*func)(void))\n{\n\tuint64_t i;\n\n\tfor (i = 0; i < nwarmup; i++)\n\t\tfunc();\n\ttimer_start(timer);\n\tfor (i = 0; i < niter; i++)\n\t\tfunc();\n\ttimer_stop(timer);\n}\n\nvoid\ncompare_funcs(uint64_t nwarmup, uint64_t niter, const char *name_a,\n    void (*func_a), const char *name_b, void (*func_b))\n{\n\ttimedelta_t timer_a, timer_b;\n\tchar ratio_buf[6];\n\tvoid *p;\n\n\tp = mallocx(1, 0);\n\tif (p == NULL) {\n\t\ttest_fail(\"Unexpected mallocx() failure\");\n\t\treturn;\n\t}\n\n\ttime_func(&timer_a, nwarmup, niter, func_a);\n\ttime_func(&timer_b, nwarmup, niter, func_b);\n\n\ttimer_ratio(&timer_a, &timer_b, ratio_buf, sizeof(ratio_buf));\n\tmalloc_printf(\"%\"FMTu64\" iterations, %s=%\"FMTu64\"us, \"\n\t    \"%s=%\"FMTu64\"us, ratio=1:%s\\n\",\n\t    niter, name_a, timer_usec(&timer_a), name_b, timer_usec(&timer_b),\n\t    ratio_buf);\n\n\tdallocx(p, 0);\n}\n\nstatic void\nmalloc_free(void)\n{\n\t/* The compiler can optimize away free(malloc(1))! */\n\tvoid *p = malloc(1);\n\tif (p == NULL) {\n\t\ttest_fail(\"Unexpected malloc() failure\");\n\t\treturn;\n\t}\n\tfree(p);\n}\n\nstatic void\nmallocx_free(void)\n{\n\tvoid *p = mallocx(1, 0);\n\tif (p == NULL) {\n\t\ttest_fail(\"Unexpected mallocx() failure\");\n\t\treturn;\n\t}\n\tfree(p);\n}\n\nTEST_BEGIN(test_malloc_vs_mallocx)\n{\n\n\tcompare_funcs(10*1000*1000, 100*1000*1000, \"malloc\",\n\t    malloc_free, \"mallocx\", mallocx_free);\n}\nTEST_END\n\nstatic void\nmalloc_dallocx(void)\n{\n\tvoid *p = malloc(1);\n\tif (p == NULL) {\n\t\ttest_fail(\"Unexpected malloc() failure\");\n\t\treturn;\n\t}\n\tdallocx(p, 0);\n}\n\nstatic void\nmalloc_sdallocx(void)\n{\n\tvoid *p = malloc(1);\n\tif (p == NULL) {\n\t\ttest_fail(\"Unexpected malloc() failure\");\n\t\treturn;\n\t}\n\tsdallocx(p, 1, 0);\n}\n\nTEST_BEGIN(test_free_vs_dallocx)\n{\n\n\tcompare_funcs(10*1000*1000, 100*1000*1000, \"free\", malloc_free,\n\t    \"dallocx\", malloc_dallocx);\n}\nTEST_END\n\nTEST_BEGIN(test_dallocx_vs_sdallocx)\n{\n\n\tcompare_funcs(10*1000*1000, 100*1000*1000, \"dallocx\", malloc_dallocx,\n\t    \"sdallocx\", malloc_sdallocx);\n}\nTEST_END\n\nstatic void\nmalloc_mus_free(void)\n{\n\tvoid *p;\n\n\tp = malloc(1);\n\tif (p == NULL) {\n\t\ttest_fail(\"Unexpected malloc() failure\");\n\t\treturn;\n\t}\n\tmalloc_usable_size(p);\n\tfree(p);\n}\n\nstatic void\nmalloc_sallocx_free(void)\n{\n\tvoid *p;\n\n\tp = malloc(1);\n\tif (p == NULL) {\n\t\ttest_fail(\"Unexpected malloc() failure\");\n\t\treturn;\n\t}\n\tif (sallocx(p, 0) < 1)\n\t\ttest_fail(\"Unexpected sallocx() failure\");\n\tfree(p);\n}\n\nTEST_BEGIN(test_mus_vs_sallocx)\n{\n\n\tcompare_funcs(10*1000*1000, 100*1000*1000, \"malloc_usable_size\",\n\t    malloc_mus_free, \"sallocx\", malloc_sallocx_free);\n}\nTEST_END\n\nstatic void\nmalloc_nallocx_free(void)\n{\n\tvoid *p;\n\n\tp = malloc(1);\n\tif (p == NULL) {\n\t\ttest_fail(\"Unexpected malloc() failure\");\n\t\treturn;\n\t}\n\tif (nallocx(1, 0) < 1)\n\t\ttest_fail(\"Unexpected nallocx() failure\");\n\tfree(p);\n}\n\nTEST_BEGIN(test_sallocx_vs_nallocx)\n{\n\n\tcompare_funcs(10*1000*1000, 100*1000*1000, \"sallocx\",\n\t    malloc_sallocx_free, \"nallocx\", malloc_nallocx_free);\n}\nTEST_END\n\nint\nmain(void)\n{\n\n\treturn (test(\n\t    test_malloc_vs_mallocx,\n\t    test_free_vs_dallocx,\n\t    test_dallocx_vs_sdallocx,\n\t    test_mus_vs_sallocx,\n\t    test_sallocx_vs_nallocx));\n}\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.8/deps/jemalloc/test/test.sh.in",
    "content": "#!/bin/sh\n\ncase @abi@ in\n  macho)\n    export DYLD_FALLBACK_LIBRARY_PATH=\"@objroot@lib\"\n    ;;\n  pecoff)\n    export PATH=\"${PATH}:@objroot@lib\"\n    ;;\n  *)\n    ;;\nesac\n\n# Corresponds to test_status_t.\npass_code=0\nskip_code=1\nfail_code=2\n\npass_count=0\nskip_count=0\nfail_count=0\nfor t in $@; do\n  if [ $pass_count -ne 0 -o $skip_count -ne 0 -o $fail_count != 0 ] ; then\n    echo\n  fi\n  echo \"=== ${t} ===\"\n  ${t}@exe@ @abs_srcroot@ @abs_objroot@\n  result_code=$?\n  case ${result_code} in\n    ${pass_code})\n      pass_count=$((pass_count+1))\n      ;;\n    ${skip_code})\n      skip_count=$((skip_count+1))\n      ;;\n    ${fail_code})\n      fail_count=$((fail_count+1))\n      ;;\n    *)\n      echo \"Test harness error\" 1>&2\n      exit 1\n  esac\ndone\n\ntotal_count=`expr ${pass_count} + ${skip_count} + ${fail_count}`\necho\necho \"Test suite summary: pass: ${pass_count}/${total_count}, skip: ${skip_count}/${total_count}, fail: ${fail_count}/${total_count}\"\n\nif [ ${fail_count} -eq 0 ] ; then\n  exit 0\nelse\n  exit 1\nfi\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.8/deps/jemalloc/test/unit/SFMT.c",
    "content": "/*\n * This file derives from SFMT 1.3.3\n * (http://www.math.sci.hiroshima-u.ac.jp/~m-mat/MT/SFMT/index.html), which was\n * released under the terms of the following license:\n *\n *   Copyright (c) 2006,2007 Mutsuo Saito, Makoto Matsumoto and Hiroshima\n *   University. All rights reserved.\n *\n *   Redistribution and use in source and binary forms, with or without\n *   modification, are permitted provided that the following conditions are\n *   met:\n *\n *       * Redistributions of source code must retain the above copyright\n *         notice, this list of conditions and the following disclaimer.\n *       * Redistributions in binary form must reproduce the above\n *         copyright notice, this list of conditions and the following\n *         disclaimer in the documentation and/or other materials provided\n *         with the distribution.\n *       * Neither the name of the Hiroshima University nor the names of\n *         its contributors may be used to endorse or promote products\n *         derived from this software without specific prior written\n *         permission.\n *\n *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n *   \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\n *   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\n *   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\n *   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n *   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\n *   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n *   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n *   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n *   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n *   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n#include \"test/jemalloc_test.h\"\n\n#define\tBLOCK_SIZE 10000\n#define\tBLOCK_SIZE64 (BLOCK_SIZE / 2)\n#define\tCOUNT_1 1000\n#define\tCOUNT_2 700\n\nstatic const uint32_t init_gen_rand_32_expected[] = {\n\t3440181298U, 1564997079U, 1510669302U, 2930277156U, 1452439940U,\n\t3796268453U,  423124208U, 2143818589U, 3827219408U, 2987036003U,\n\t2674978610U, 1536842514U, 2027035537U, 2534897563U, 1686527725U,\n\t 545368292U, 1489013321U, 1370534252U, 4231012796U, 3994803019U,\n\t1764869045U,  824597505U,  862581900U, 2469764249U,  812862514U,\n\t 359318673U,  116957936U, 3367389672U, 2327178354U, 1898245200U,\n\t3206507879U, 2378925033U, 1040214787U, 2524778605U, 3088428700U,\n\t1417665896U,  964324147U, 2282797708U, 2456269299U,  313400376U,\n\t2245093271U, 1015729427U, 2694465011U, 3246975184U, 1992793635U,\n\t 463679346U, 3721104591U, 3475064196U,  856141236U, 1499559719U,\n\t3522818941U, 3721533109U, 1954826617U, 1282044024U, 1543279136U,\n\t1301863085U, 2669145051U, 4221477354U, 3896016841U, 3392740262U,\n\t 462466863U, 1037679449U, 1228140306U,  922298197U, 1205109853U,\n\t1872938061U, 3102547608U, 2742766808U, 1888626088U, 4028039414U,\n\t 157593879U, 1136901695U, 4038377686U, 3572517236U, 4231706728U,\n\t2997311961U, 1189931652U, 3981543765U, 2826166703U,   87159245U,\n\t1721379072U, 3897926942U, 1790395498U, 2569178939U, 1047368729U,\n\t2340259131U, 3144212906U, 2301169789U, 2442885464U, 3034046771U,\n\t3667880593U, 3935928400U, 2372805237U, 1666397115U, 2460584504U,\n\t 513866770U, 3810869743U, 2147400037U, 2792078025U, 2941761810U,\n\t3212265810U,  984692259U,  346590253U, 1804179199U, 3298543443U,\n\t 750108141U, 2880257022U,  243310542U, 1869036465U, 1588062513U,\n\t2983949551U, 1931450364U, 4034505847U, 2735030199U, 1628461061U,\n\t2539522841U,  127965585U, 3992448871U,  913388237U,  559130076U,\n\t1202933193U, 4087643167U, 2590021067U, 2256240196U, 1746697293U,\n\t1013913783U, 1155864921U, 2715773730U,  915061862U, 1948766573U,\n\t2322882854U, 3761119102U, 1343405684U, 3078711943U, 3067431651U,\n\t3245156316U, 3588354584U, 3484623306U, 3899621563U, 4156689741U,\n\t3237090058U, 3880063844U,  862416318U, 4039923869U, 2303788317U,\n\t3073590536U,  701653667U, 2131530884U, 3169309950U, 2028486980U,\n\t 747196777U, 3620218225U,  432016035U, 1449580595U, 2772266392U,\n\t 444224948U, 1662832057U, 3184055582U, 3028331792U, 1861686254U,\n\t1104864179U,  342430307U, 1350510923U, 3024656237U, 1028417492U,\n\t2870772950U,  290847558U, 3675663500U,  508431529U, 4264340390U,\n\t2263569913U, 1669302976U,  519511383U, 2706411211U, 3764615828U,\n\t3883162495U, 4051445305U, 2412729798U, 3299405164U, 3991911166U,\n\t2348767304U, 2664054906U, 3763609282U,  593943581U, 3757090046U,\n\t2075338894U, 2020550814U, 4287452920U, 4290140003U, 1422957317U,\n\t2512716667U, 2003485045U, 2307520103U, 2288472169U, 3940751663U,\n\t4204638664U, 2892583423U, 1710068300U, 3904755993U, 2363243951U,\n\t3038334120U,  547099465U,  771105860U, 3199983734U, 4282046461U,\n\t2298388363U,  934810218U, 2837827901U, 3952500708U, 2095130248U,\n\t3083335297U,   26885281U, 3932155283U, 1531751116U, 1425227133U,\n\t 495654159U, 3279634176U, 3855562207U, 3957195338U, 4159985527U,\n\t 893375062U, 1875515536U, 1327247422U, 3754140693U, 1028923197U,\n\t1729880440U,  805571298U,  448971099U, 2726757106U, 2749436461U,\n\t2485987104U,  175337042U, 3235477922U, 3882114302U, 2020970972U,\n\t 943926109U, 2762587195U, 1904195558U, 3452650564U,  108432281U,\n\t3893463573U, 3977583081U, 2636504348U, 1110673525U, 3548479841U,\n\t4258854744U,  980047703U, 4057175418U, 3890008292U,  145653646U,\n\t3141868989U, 3293216228U, 1194331837U, 1254570642U, 3049934521U,\n\t2868313360U, 2886032750U, 1110873820U,  279553524U, 3007258565U,\n\t1104807822U, 3186961098U,  315764646U, 2163680838U, 3574508994U,\n\t3099755655U,  191957684U, 3642656737U, 3317946149U, 3522087636U,\n\t 444526410U,  779157624U, 1088229627U, 1092460223U, 1856013765U,\n\t3659877367U,  368270451U,  503570716U, 3000984671U, 2742789647U,\n\t 928097709U, 2914109539U,  308843566U, 2816161253U, 3667192079U,\n\t2762679057U, 3395240989U, 2928925038U, 1491465914U, 3458702834U,\n\t3787782576U, 2894104823U, 1296880455U, 1253636503U,  989959407U,\n\t2291560361U, 2776790436U, 1913178042U, 1584677829U,  689637520U,\n\t1898406878U,  688391508U, 3385234998U,  845493284U, 1943591856U,\n\t2720472050U,  222695101U, 1653320868U, 2904632120U, 4084936008U,\n\t1080720688U, 3938032556U,  387896427U, 2650839632U,   99042991U,\n\t1720913794U, 1047186003U, 1877048040U, 2090457659U,  517087501U,\n\t4172014665U, 2129713163U, 2413533132U, 2760285054U, 4129272496U,\n\t1317737175U, 2309566414U, 2228873332U, 3889671280U, 1110864630U,\n\t3576797776U, 2074552772U,  832002644U, 3097122623U, 2464859298U,\n\t2679603822U, 1667489885U, 3237652716U, 1478413938U, 1719340335U,\n\t2306631119U,  639727358U, 3369698270U,  226902796U, 2099920751U,\n\t1892289957U, 2201594097U, 3508197013U, 3495811856U, 3900381493U,\n\t 841660320U, 3974501451U, 3360949056U, 1676829340U,  728899254U,\n\t2047809627U, 2390948962U,  670165943U, 3412951831U, 4189320049U,\n\t1911595255U, 2055363086U,  507170575U,  418219594U, 4141495280U,\n\t2692088692U, 4203630654U, 3540093932U,  791986533U, 2237921051U,\n\t2526864324U, 2956616642U, 1394958700U, 1983768223U, 1893373266U,\n\t 591653646U,  228432437U, 1611046598U, 3007736357U, 1040040725U,\n\t2726180733U, 2789804360U, 4263568405U,  829098158U, 3847722805U,\n\t1123578029U, 1804276347U,  997971319U, 4203797076U, 4185199713U,\n\t2811733626U, 2343642194U, 2985262313U, 1417930827U, 3759587724U,\n\t1967077982U, 1585223204U, 1097475516U, 1903944948U,  740382444U,\n\t1114142065U, 1541796065U, 1718384172U, 1544076191U, 1134682254U,\n\t3519754455U, 2866243923U,  341865437U,  645498576U, 2690735853U,\n\t1046963033U, 2493178460U, 1187604696U, 1619577821U,  488503634U,\n\t3255768161U, 2306666149U, 1630514044U, 2377698367U, 2751503746U,\n\t3794467088U, 1796415981U, 3657173746U,  409136296U, 1387122342U,\n\t1297726519U,  219544855U, 4270285558U,  437578827U, 1444698679U,\n\t2258519491U,  963109892U, 3982244073U, 3351535275U,  385328496U,\n\t1804784013U,  698059346U, 3920535147U,  708331212U,  784338163U,\n\t 785678147U, 1238376158U, 1557298846U, 2037809321U,  271576218U,\n\t4145155269U, 1913481602U, 2763691931U,  588981080U, 1201098051U,\n\t3717640232U, 1509206239U,  662536967U, 3180523616U, 1133105435U,\n\t2963500837U, 2253971215U, 3153642623U, 1066925709U, 2582781958U,\n\t3034720222U, 1090798544U, 2942170004U, 4036187520U,  686972531U,\n\t2610990302U, 2641437026U, 1837562420U,  722096247U, 1315333033U,\n\t2102231203U, 3402389208U, 3403698140U, 1312402831U, 2898426558U,\n\t 814384596U,  385649582U, 1916643285U, 1924625106U, 2512905582U,\n\t2501170304U, 4275223366U, 2841225246U, 1467663688U, 3563567847U,\n\t2969208552U,  884750901U,  102992576U,  227844301U, 3681442994U,\n\t3502881894U, 4034693299U, 1166727018U, 1697460687U, 1737778332U,\n\t1787161139U, 1053003655U, 1215024478U, 2791616766U, 2525841204U,\n\t1629323443U,    3233815U, 2003823032U, 3083834263U, 2379264872U,\n\t3752392312U, 1287475550U, 3770904171U, 3004244617U, 1502117784U,\n\t 918698423U, 2419857538U, 3864502062U, 1751322107U, 2188775056U,\n\t4018728324U,  983712955U,  440071928U, 3710838677U, 2001027698U,\n\t3994702151U,   22493119U, 3584400918U, 3446253670U, 4254789085U,\n\t1405447860U, 1240245579U, 1800644159U, 1661363424U, 3278326132U,\n\t3403623451U,   67092802U, 2609352193U, 3914150340U, 1814842761U,\n\t3610830847U,  591531412U, 3880232807U, 1673505890U, 2585326991U,\n\t1678544474U, 3148435887U, 3457217359U, 1193226330U, 2816576908U,\n\t 154025329U,  121678860U, 1164915738U,  973873761U,  269116100U,\n\t  52087970U,  744015362U,  498556057U,   94298882U, 1563271621U,\n\t2383059628U, 4197367290U, 3958472990U, 2592083636U, 2906408439U,\n\t1097742433U, 3924840517U,  264557272U, 2292287003U, 3203307984U,\n\t4047038857U, 3820609705U, 2333416067U, 1839206046U, 3600944252U,\n\t3412254904U,  583538222U, 2390557166U, 4140459427U, 2810357445U,\n\t 226777499U, 2496151295U, 2207301712U, 3283683112U,  611630281U,\n\t1933218215U, 3315610954U, 3889441987U, 3719454256U, 3957190521U,\n\t1313998161U, 2365383016U, 3146941060U, 1801206260U,  796124080U,\n\t2076248581U, 1747472464U, 3254365145U,  595543130U, 3573909503U,\n\t3758250204U, 2020768540U, 2439254210U,   93368951U, 3155792250U,\n\t2600232980U, 3709198295U, 3894900440U, 2971850836U, 1578909644U,\n\t1443493395U, 2581621665U, 3086506297U, 2443465861U,  558107211U,\n\t1519367835U,  249149686U,  908102264U, 2588765675U, 1232743965U,\n\t1001330373U, 3561331654U, 2259301289U, 1564977624U, 3835077093U,\n\t 727244906U, 4255738067U, 1214133513U, 2570786021U, 3899704621U,\n\t1633861986U, 1636979509U, 1438500431U,   58463278U, 2823485629U,\n\t2297430187U, 2926781924U, 3371352948U, 1864009023U, 2722267973U,\n\t1444292075U,  437703973U, 1060414512U,  189705863U,  910018135U,\n\t4077357964U,  884213423U, 2644986052U, 3973488374U, 1187906116U,\n\t2331207875U,  780463700U, 3713351662U, 3854611290U,  412805574U,\n\t2978462572U, 2176222820U,  829424696U, 2790788332U, 2750819108U,\n\t1594611657U, 3899878394U, 3032870364U, 1702887682U, 1948167778U,\n\t  14130042U,  192292500U,  947227076U,   90719497U, 3854230320U,\n\t 784028434U, 2142399787U, 1563449646U, 2844400217U,  819143172U,\n\t2883302356U, 2328055304U, 1328532246U, 2603885363U, 3375188924U,\n\t 933941291U, 3627039714U, 2129697284U, 2167253953U, 2506905438U,\n\t1412424497U, 2981395985U, 1418359660U, 2925902456U,   52752784U,\n\t3713667988U, 3924669405U,  648975707U, 1145520213U, 4018650664U,\n\t3805915440U, 2380542088U, 2013260958U, 3262572197U, 2465078101U,\n\t1114540067U, 3728768081U, 2396958768U,  590672271U,  904818725U,\n\t4263660715U,  700754408U, 1042601829U, 4094111823U, 4274838909U,\n\t2512692617U, 2774300207U, 2057306915U, 3470942453U,   99333088U,\n\t1142661026U, 2889931380U,   14316674U, 2201179167U,  415289459U,\n\t 448265759U, 3515142743U, 3254903683U,  246633281U, 1184307224U,\n\t2418347830U, 2092967314U, 2682072314U, 2558750234U, 2000352263U,\n\t1544150531U,  399010405U, 1513946097U,  499682937U,  461167460U,\n\t3045570638U, 1633669705U,  851492362U, 4052801922U, 2055266765U,\n\t 635556996U,  368266356U, 2385737383U, 3218202352U, 2603772408U,\n\t 349178792U,  226482567U, 3102426060U, 3575998268U, 2103001871U,\n\t3243137071U,  225500688U, 1634718593U, 4283311431U, 4292122923U,\n\t3842802787U,  811735523U,  105712518U,  663434053U, 1855889273U,\n\t2847972595U, 1196355421U, 2552150115U, 4254510614U, 3752181265U,\n\t3430721819U, 3828705396U, 3436287905U, 3441964937U, 4123670631U,\n\t 353001539U,  459496439U, 3799690868U, 1293777660U, 2761079737U,\n\t 498096339U, 3398433374U, 4080378380U, 2304691596U, 2995729055U,\n\t4134660419U, 3903444024U, 3576494993U,  203682175U, 3321164857U,\n\t2747963611U,   79749085U, 2992890370U, 1240278549U, 1772175713U,\n\t2111331972U, 2655023449U, 1683896345U, 2836027212U, 3482868021U,\n\t2489884874U,  756853961U, 2298874501U, 4013448667U, 4143996022U,\n\t2948306858U, 4132920035U, 1283299272U,  995592228U, 3450508595U,\n\t1027845759U, 1766942720U, 3861411826U, 1446861231U,   95974993U,\n\t3502263554U, 1487532194U,  601502472U, 4129619129U,  250131773U,\n\t2050079547U, 3198903947U, 3105589778U, 4066481316U, 3026383978U,\n\t2276901713U,  365637751U, 2260718426U, 1394775634U, 1791172338U,\n\t2690503163U, 2952737846U, 1568710462U,  732623190U, 2980358000U,\n\t1053631832U, 1432426951U, 3229149635U, 1854113985U, 3719733532U,\n\t3204031934U,  735775531U,  107468620U, 3734611984U,  631009402U,\n\t3083622457U, 4109580626U,  159373458U, 1301970201U, 4132389302U,\n\t1293255004U,  847182752U, 4170022737U,   96712900U, 2641406755U,\n\t1381727755U,  405608287U, 4287919625U, 1703554290U, 3589580244U,\n\t2911403488U,    2166565U, 2647306451U, 2330535117U, 1200815358U,\n\t1165916754U,  245060911U, 4040679071U, 3684908771U, 2452834126U,\n\t2486872773U, 2318678365U, 2940627908U, 1837837240U, 3447897409U,\n\t4270484676U, 1495388728U, 3754288477U, 4204167884U, 1386977705U,\n\t2692224733U, 3076249689U, 4109568048U, 4170955115U, 4167531356U,\n\t4020189950U, 4261855038U, 3036907575U, 3410399885U, 3076395737U,\n\t1046178638U,  144496770U,  230725846U, 3349637149U,   17065717U,\n\t2809932048U, 2054581785U, 3608424964U, 3259628808U,  134897388U,\n\t3743067463U,  257685904U, 3795656590U, 1562468719U, 3589103904U,\n\t3120404710U,  254684547U, 2653661580U, 3663904795U, 2631942758U,\n\t1063234347U, 2609732900U, 2332080715U, 3521125233U, 1180599599U,\n\t1935868586U, 4110970440U,  296706371U, 2128666368U, 1319875791U,\n\t1570900197U, 3096025483U, 1799882517U, 1928302007U, 1163707758U,\n\t1244491489U, 3533770203U,  567496053U, 2757924305U, 2781639343U,\n\t2818420107U,  560404889U, 2619609724U, 4176035430U, 2511289753U,\n\t2521842019U, 3910553502U, 2926149387U, 3302078172U, 4237118867U,\n\t 330725126U,  367400677U,  888239854U,  545570454U, 4259590525U,\n\t 134343617U, 1102169784U, 1647463719U, 3260979784U, 1518840883U,\n\t3631537963U, 3342671457U, 1301549147U, 2083739356U,  146593792U,\n\t3217959080U,  652755743U, 2032187193U, 3898758414U, 1021358093U,\n\t4037409230U, 2176407931U, 3427391950U, 2883553603U,  985613827U,\n\t3105265092U, 3423168427U, 3387507672U,  467170288U, 2141266163U,\n\t3723870208U,  916410914U, 1293987799U, 2652584950U,  769160137U,\n\t3205292896U, 1561287359U, 1684510084U, 3136055621U, 3765171391U,\n\t 639683232U, 2639569327U, 1218546948U, 4263586685U, 3058215773U,\n\t2352279820U,  401870217U, 2625822463U, 1529125296U, 2981801895U,\n\t1191285226U, 4027725437U, 3432700217U, 4098835661U,  971182783U,\n\t2443861173U, 3881457123U, 3874386651U,  457276199U, 2638294160U,\n\t4002809368U,  421169044U, 1112642589U, 3076213779U, 3387033971U,\n\t2499610950U, 3057240914U, 1662679783U,  461224431U, 1168395933U\n};\nstatic const uint32_t init_by_array_32_expected[] = {\n\t2920711183U, 3885745737U, 3501893680U,  856470934U, 1421864068U,\n\t 277361036U, 1518638004U, 2328404353U, 3355513634U,   64329189U,\n\t1624587673U, 3508467182U, 2481792141U, 3706480799U, 1925859037U,\n\t2913275699U,  882658412U,  384641219U,  422202002U, 1873384891U,\n\t2006084383U, 3924929912U, 1636718106U, 3108838742U, 1245465724U,\n\t4195470535U,  779207191U, 1577721373U, 1390469554U, 2928648150U,\n\t 121399709U, 3170839019U, 4044347501U,  953953814U, 3821710850U,\n\t3085591323U, 3666535579U, 3577837737U, 2012008410U, 3565417471U,\n\t4044408017U,  433600965U, 1637785608U, 1798509764U,  860770589U,\n\t3081466273U, 3982393409U, 2451928325U, 3437124742U, 4093828739U,\n\t3357389386U, 2154596123U,  496568176U, 2650035164U, 2472361850U,\n\t   3438299U, 2150366101U, 1577256676U, 3802546413U, 1787774626U,\n\t4078331588U, 3706103141U,  170391138U, 3806085154U, 1680970100U,\n\t1961637521U, 3316029766U,  890610272U, 1453751581U, 1430283664U,\n\t3051057411U, 3597003186U,  542563954U, 3796490244U, 1690016688U,\n\t3448752238U,  440702173U,  347290497U, 1121336647U, 2540588620U,\n\t 280881896U, 2495136428U,  213707396U,   15104824U, 2946180358U,\n\t 659000016U,  566379385U, 2614030979U, 2855760170U,  334526548U,\n\t2315569495U, 2729518615U,  564745877U, 1263517638U, 3157185798U,\n\t1604852056U, 1011639885U, 2950579535U, 2524219188U,  312951012U,\n\t1528896652U, 1327861054U, 2846910138U, 3966855905U, 2536721582U,\n\t 855353911U, 1685434729U, 3303978929U, 1624872055U, 4020329649U,\n\t3164802143U, 1642802700U, 1957727869U, 1792352426U, 3334618929U,\n\t2631577923U, 3027156164U,  842334259U, 3353446843U, 1226432104U,\n\t1742801369U, 3552852535U, 3471698828U, 1653910186U, 3380330939U,\n\t2313782701U, 3351007196U, 2129839995U, 1800682418U, 4085884420U,\n\t1625156629U, 3669701987U,  615211810U, 3294791649U, 4131143784U,\n\t2590843588U, 3207422808U, 3275066464U,  561592872U, 3957205738U,\n\t3396578098U,   48410678U, 3505556445U, 1005764855U, 3920606528U,\n\t2936980473U, 2378918600U, 2404449845U, 1649515163U,  701203563U,\n\t3705256349U,   83714199U, 3586854132U,  922978446U, 2863406304U,\n\t3523398907U, 2606864832U, 2385399361U, 3171757816U, 4262841009U,\n\t3645837721U, 1169579486U, 3666433897U, 3174689479U, 1457866976U,\n\t3803895110U, 3346639145U, 1907224409U, 1978473712U, 1036712794U,\n\t 980754888U, 1302782359U, 1765252468U,  459245755U, 3728923860U,\n\t1512894209U, 2046491914U,  207860527U,  514188684U, 2288713615U,\n\t1597354672U, 3349636117U, 2357291114U, 3995796221U,  945364213U,\n\t1893326518U, 3770814016U, 1691552714U, 2397527410U,  967486361U,\n\t 776416472U, 4197661421U,  951150819U, 1852770983U, 4044624181U,\n\t1399439738U, 4194455275U, 2284037669U, 1550734958U, 3321078108U,\n\t1865235926U, 2912129961U, 2664980877U, 1357572033U, 2600196436U,\n\t2486728200U, 2372668724U, 1567316966U, 2374111491U, 1839843570U,\n\t  20815612U, 3727008608U, 3871996229U,  824061249U, 1932503978U,\n\t3404541726U,  758428924U, 2609331364U, 1223966026U, 1299179808U,\n\t 648499352U, 2180134401U,  880821170U, 3781130950U,  113491270U,\n\t1032413764U, 4185884695U, 2490396037U, 1201932817U, 4060951446U,\n\t4165586898U, 1629813212U, 2887821158U,  415045333U,  628926856U,\n\t2193466079U, 3391843445U, 2227540681U, 1907099846U, 2848448395U,\n\t1717828221U, 1372704537U, 1707549841U, 2294058813U, 2101214437U,\n\t2052479531U, 1695809164U, 3176587306U, 2632770465U,   81634404U,\n\t1603220563U,  644238487U,  302857763U,  897352968U, 2613146653U,\n\t1391730149U, 4245717312U, 4191828749U, 1948492526U, 2618174230U,\n\t3992984522U, 2178852787U, 3596044509U, 3445573503U, 2026614616U,\n\t 915763564U, 3415689334U, 2532153403U, 3879661562U, 2215027417U,\n\t3111154986U, 2929478371U,  668346391U, 1152241381U, 2632029711U,\n\t3004150659U, 2135025926U,  948690501U, 2799119116U, 4228829406U,\n\t1981197489U, 4209064138U,  684318751U, 3459397845U,  201790843U,\n\t4022541136U, 3043635877U,  492509624U, 3263466772U, 1509148086U,\n\t 921459029U, 3198857146U,  705479721U, 3835966910U, 3603356465U,\n\t 576159741U, 1742849431U,  594214882U, 2055294343U, 3634861861U,\n\t 449571793U, 3246390646U, 3868232151U, 1479156585U, 2900125656U,\n\t2464815318U, 3960178104U, 1784261920U,   18311476U, 3627135050U,\n\t 644609697U,  424968996U,  919890700U, 2986824110U,  816423214U,\n\t4003562844U, 1392714305U, 1757384428U, 2569030598U,  995949559U,\n\t3875659880U, 2933807823U, 2752536860U, 2993858466U, 4030558899U,\n\t2770783427U, 2775406005U, 2777781742U, 1931292655U,  472147933U,\n\t3865853827U, 2726470545U, 2668412860U, 2887008249U,  408979190U,\n\t3578063323U, 3242082049U, 1778193530U,   27981909U, 2362826515U,\n\t 389875677U, 1043878156U,  581653903U, 3830568952U,  389535942U,\n\t3713523185U, 2768373359U, 2526101582U, 1998618197U, 1160859704U,\n\t3951172488U, 1098005003U,  906275699U, 3446228002U, 2220677963U,\n\t2059306445U,  132199571U,  476838790U, 1868039399U, 3097344807U,\n\t 857300945U,  396345050U, 2835919916U, 1782168828U, 1419519470U,\n\t4288137521U,  819087232U,  596301494U,  872823172U, 1526888217U,\n\t 805161465U, 1116186205U, 2829002754U, 2352620120U,  620121516U,\n\t 354159268U, 3601949785U,  209568138U, 1352371732U, 2145977349U,\n\t4236871834U, 1539414078U, 3558126206U, 3224857093U, 4164166682U,\n\t3817553440U, 3301780278U, 2682696837U, 3734994768U, 1370950260U,\n\t1477421202U, 2521315749U, 1330148125U, 1261554731U, 2769143688U,\n\t3554756293U, 4235882678U, 3254686059U, 3530579953U, 1215452615U,\n\t3574970923U, 4057131421U,  589224178U, 1000098193U,  171190718U,\n\t2521852045U, 2351447494U, 2284441580U, 2646685513U, 3486933563U,\n\t3789864960U, 1190528160U, 1702536782U, 1534105589U, 4262946827U,\n\t2726686826U, 3584544841U, 2348270128U, 2145092281U, 2502718509U,\n\t1027832411U, 3571171153U, 1287361161U, 4011474411U, 3241215351U,\n\t2419700818U,  971242709U, 1361975763U, 1096842482U, 3271045537U,\n\t  81165449U,  612438025U, 3912966678U, 1356929810U,  733545735U,\n\t 537003843U, 1282953084U,  884458241U,  588930090U, 3930269801U,\n\t2961472450U, 1219535534U, 3632251943U,  268183903U, 1441240533U,\n\t3653903360U, 3854473319U, 2259087390U, 2548293048U, 2022641195U,\n\t2105543911U, 1764085217U, 3246183186U,  482438805U,  888317895U,\n\t2628314765U, 2466219854U,  717546004U, 2322237039U,  416725234U,\n\t1544049923U, 1797944973U, 3398652364U, 3111909456U,  485742908U,\n\t2277491072U, 1056355088U, 3181001278U,  129695079U, 2693624550U,\n\t1764438564U, 3797785470U,  195503713U, 3266519725U, 2053389444U,\n\t1961527818U, 3400226523U, 3777903038U, 2597274307U, 4235851091U,\n\t4094406648U, 2171410785U, 1781151386U, 1378577117U,  654643266U,\n\t3424024173U, 3385813322U,  679385799U,  479380913U,  681715441U,\n\t3096225905U,  276813409U, 3854398070U, 2721105350U,  831263315U,\n\t3276280337U, 2628301522U, 3984868494U, 1466099834U, 2104922114U,\n\t1412672743U,  820330404U, 3491501010U,  942735832U,  710652807U,\n\t3972652090U,  679881088U,   40577009U, 3705286397U, 2815423480U,\n\t3566262429U,  663396513U, 3777887429U, 4016670678U,  404539370U,\n\t1142712925U, 1140173408U, 2913248352U, 2872321286U,  263751841U,\n\t3175196073U, 3162557581U, 2878996619U,   75498548U, 3836833140U,\n\t3284664959U, 1157523805U,  112847376U,  207855609U, 1337979698U,\n\t1222578451U,  157107174U,  901174378U, 3883717063U, 1618632639U,\n\t1767889440U, 4264698824U, 1582999313U,  884471997U, 2508825098U,\n\t3756370771U, 2457213553U, 3565776881U, 3709583214U,  915609601U,\n\t 460833524U, 1091049576U,   85522880U,    2553251U,  132102809U,\n\t2429882442U, 2562084610U, 1386507633U, 4112471229U,   21965213U,\n\t1981516006U, 2418435617U, 3054872091U, 4251511224U, 2025783543U,\n\t1916911512U, 2454491136U, 3938440891U, 3825869115U, 1121698605U,\n\t3463052265U,  802340101U, 1912886800U, 4031997367U, 3550640406U,\n\t1596096923U,  610150600U,  431464457U, 2541325046U,  486478003U,\n\t 739704936U, 2862696430U, 3037903166U, 1129749694U, 2611481261U,\n\t1228993498U,  510075548U, 3424962587U, 2458689681U,  818934833U,\n\t4233309125U, 1608196251U, 3419476016U, 1858543939U, 2682166524U,\n\t3317854285U,  631986188U, 3008214764U,  613826412U, 3567358221U,\n\t3512343882U, 1552467474U, 3316162670U, 1275841024U, 4142173454U,\n\t 565267881U,  768644821U,  198310105U, 2396688616U, 1837659011U,\n\t 203429334U,  854539004U, 4235811518U, 3338304926U, 3730418692U,\n\t3852254981U, 3032046452U, 2329811860U, 2303590566U, 2696092212U,\n\t3894665932U,  145835667U,  249563655U, 1932210840U, 2431696407U,\n\t3312636759U,  214962629U, 2092026914U, 3020145527U, 4073039873U,\n\t2739105705U, 1308336752U,  855104522U, 2391715321U,   67448785U,\n\t 547989482U,  854411802U, 3608633740U,  431731530U,  537375589U,\n\t3888005760U,  696099141U,  397343236U, 1864511780U,   44029739U,\n\t1729526891U, 1993398655U, 2010173426U, 2591546756U,  275223291U,\n\t1503900299U, 4217765081U, 2185635252U, 1122436015U, 3550155364U,\n\t 681707194U, 3260479338U,  933579397U, 2983029282U, 2505504587U,\n\t2667410393U, 2962684490U, 4139721708U, 2658172284U, 2452602383U,\n\t2607631612U, 1344296217U, 3075398709U, 2949785295U, 1049956168U,\n\t3917185129U, 2155660174U, 3280524475U, 1503827867U,  674380765U,\n\t1918468193U, 3843983676U,  634358221U, 2538335643U, 1873351298U,\n\t3368723763U, 2129144130U, 3203528633U, 3087174986U, 2691698871U,\n\t2516284287U,   24437745U, 1118381474U, 2816314867U, 2448576035U,\n\t4281989654U,  217287825U,  165872888U, 2628995722U, 3533525116U,\n\t2721669106U,  872340568U, 3429930655U, 3309047304U, 3916704967U,\n\t3270160355U, 1348884255U, 1634797670U,  881214967U, 4259633554U,\n\t 174613027U, 1103974314U, 1625224232U, 2678368291U, 1133866707U,\n\t3853082619U, 4073196549U, 1189620777U,  637238656U,  930241537U,\n\t4042750792U, 3842136042U, 2417007212U, 2524907510U, 1243036827U,\n\t1282059441U, 3764588774U, 1394459615U, 2323620015U, 1166152231U,\n\t3307479609U, 3849322257U, 3507445699U, 4247696636U,  758393720U,\n\t 967665141U, 1095244571U, 1319812152U,  407678762U, 2640605208U,\n\t2170766134U, 3663594275U, 4039329364U, 2512175520U,  725523154U,\n\t2249807004U, 3312617979U, 2414634172U, 1278482215U,  349206484U,\n\t1573063308U, 1196429124U, 3873264116U, 2400067801U,  268795167U,\n\t 226175489U, 2961367263U, 1968719665U,   42656370U, 1010790699U,\n\t 561600615U, 2422453992U, 3082197735U, 1636700484U, 3977715296U,\n\t3125350482U, 3478021514U, 2227819446U, 1540868045U, 3061908980U,\n\t1087362407U, 3625200291U,  361937537U,  580441897U, 1520043666U,\n\t2270875402U, 1009161260U, 2502355842U, 4278769785U,  473902412U,\n\t1057239083U, 1905829039U, 1483781177U, 2080011417U, 1207494246U,\n\t1806991954U, 2194674403U, 3455972205U,  807207678U, 3655655687U,\n\t 674112918U,  195425752U, 3917890095U, 1874364234U, 1837892715U,\n\t3663478166U, 1548892014U, 2570748714U, 2049929836U, 2167029704U,\n\t 697543767U, 3499545023U, 3342496315U, 1725251190U, 3561387469U,\n\t2905606616U, 1580182447U, 3934525927U, 4103172792U, 1365672522U,\n\t1534795737U, 3308667416U, 2841911405U, 3943182730U, 4072020313U,\n\t3494770452U, 3332626671U,   55327267U,  478030603U,  411080625U,\n\t3419529010U, 1604767823U, 3513468014U,  570668510U,  913790824U,\n\t2283967995U,  695159462U, 3825542932U, 4150698144U, 1829758699U,\n\t 202895590U, 1609122645U, 1267651008U, 2910315509U, 2511475445U,\n\t2477423819U, 3932081579U,  900879979U, 2145588390U, 2670007504U,\n\t 580819444U, 1864996828U, 2526325979U, 1019124258U,  815508628U,\n\t2765933989U, 1277301341U, 3006021786U,  855540956U,  288025710U,\n\t1919594237U, 2331223864U,  177452412U, 2475870369U, 2689291749U,\n\t 865194284U,  253432152U, 2628531804U, 2861208555U, 2361597573U,\n\t1653952120U, 1039661024U, 2159959078U, 3709040440U, 3564718533U,\n\t2596878672U, 2041442161U,   31164696U, 2662962485U, 3665637339U,\n\t1678115244U, 2699839832U, 3651968520U, 3521595541U,  458433303U,\n\t2423096824U,   21831741U,  380011703U, 2498168716U,  861806087U,\n\t1673574843U, 4188794405U, 2520563651U, 2632279153U, 2170465525U,\n\t4171949898U, 3886039621U, 1661344005U, 3424285243U,  992588372U,\n\t2500984144U, 2993248497U, 3590193895U, 1535327365U,  515645636U,\n\t 131633450U, 3729760261U, 1613045101U, 3254194278U,   15889678U,\n\t1493590689U,  244148718U, 2991472662U, 1401629333U,  777349878U,\n\t2501401703U, 4285518317U, 3794656178U,  955526526U, 3442142820U,\n\t3970298374U,  736025417U, 2737370764U, 1271509744U,  440570731U,\n\t 136141826U, 1596189518U,  923399175U,  257541519U, 3505774281U,\n\t2194358432U, 2518162991U, 1379893637U, 2667767062U, 3748146247U,\n\t1821712620U, 3923161384U, 1947811444U, 2392527197U, 4127419685U,\n\t1423694998U, 4156576871U, 1382885582U, 3420127279U, 3617499534U,\n\t2994377493U, 4038063986U, 1918458672U, 2983166794U, 4200449033U,\n\t 353294540U, 1609232588U,  243926648U, 2332803291U,  507996832U,\n\t2392838793U, 4075145196U, 2060984340U, 4287475136U,   88232602U,\n\t2491531140U, 4159725633U, 2272075455U,  759298618U,  201384554U,\n\t 838356250U, 1416268324U,  674476934U,   90795364U,  141672229U,\n\t3660399588U, 4196417251U, 3249270244U, 3774530247U,   59587265U,\n\t3683164208U,   19392575U, 1463123697U, 1882205379U,  293780489U,\n\t2553160622U, 2933904694U,  675638239U, 2851336944U, 1435238743U,\n\t2448730183U,  804436302U, 2119845972U,  322560608U, 4097732704U,\n\t2987802540U,  641492617U, 2575442710U, 4217822703U, 3271835300U,\n\t2836418300U, 3739921620U, 2138378768U, 2879771855U, 4294903423U,\n\t3121097946U, 2603440486U, 2560820391U, 1012930944U, 2313499967U,\n\t 584489368U, 3431165766U,  897384869U, 2062537737U, 2847889234U,\n\t3742362450U, 2951174585U, 4204621084U, 1109373893U, 3668075775U,\n\t2750138839U, 3518055702U,  733072558U, 4169325400U,  788493625U\n};\nstatic const uint64_t init_gen_rand_64_expected[] = {\n\tKQU(16924766246869039260), KQU( 8201438687333352714),\n\tKQU( 2265290287015001750), KQU(18397264611805473832),\n\tKQU( 3375255223302384358), KQU( 6345559975416828796),\n\tKQU(18229739242790328073), KQU( 7596792742098800905),\n\tKQU(  255338647169685981), KQU( 2052747240048610300),\n\tKQU(18328151576097299343), KQU(12472905421133796567),\n\tKQU(11315245349717600863), KQU(16594110197775871209),\n\tKQU(15708751964632456450), KQU(10452031272054632535),\n\tKQU(11097646720811454386), KQU( 4556090668445745441),\n\tKQU(17116187693090663106), KQU(14931526836144510645),\n\tKQU( 9190752218020552591), KQU( 9625800285771901401),\n\tKQU(13995141077659972832), KQU( 5194209094927829625),\n\tKQU( 4156788379151063303), KQU( 8523452593770139494),\n\tKQU(14082382103049296727), KQU( 2462601863986088483),\n\tKQU( 3030583461592840678), KQU( 5221622077872827681),\n\tKQU( 3084210671228981236), KQU(13956758381389953823),\n\tKQU(13503889856213423831), KQU(15696904024189836170),\n\tKQU( 4612584152877036206), KQU( 6231135538447867881),\n\tKQU(10172457294158869468), KQU( 6452258628466708150),\n\tKQU(14044432824917330221), KQU(  370168364480044279),\n\tKQU(10102144686427193359), KQU(  667870489994776076),\n\tKQU( 2732271956925885858), KQU(18027788905977284151),\n\tKQU(15009842788582923859), KQU( 7136357960180199542),\n\tKQU(15901736243475578127), KQU(16951293785352615701),\n\tKQU(10551492125243691632), KQU(17668869969146434804),\n\tKQU(13646002971174390445), KQU( 9804471050759613248),\n\tKQU( 5511670439655935493), KQU(18103342091070400926),\n\tKQU(17224512747665137533), KQU(15534627482992618168),\n\tKQU( 1423813266186582647), KQU(15821176807932930024),\n\tKQU(   30323369733607156), KQU(11599382494723479403),\n\tKQU(  653856076586810062), KQU( 3176437395144899659),\n\tKQU(14028076268147963917), KQU(16156398271809666195),\n\tKQU( 3166955484848201676), KQU( 5746805620136919390),\n\tKQU(17297845208891256593), KQU(11691653183226428483),\n\tKQU(17900026146506981577), KQU(15387382115755971042),\n\tKQU(16923567681040845943), KQU( 8039057517199388606),\n\tKQU(11748409241468629263), KQU(  794358245539076095),\n\tKQU(13438501964693401242), KQU(14036803236515618962),\n\tKQU( 5252311215205424721), KQU(17806589612915509081),\n\tKQU( 6802767092397596006), KQU(14212120431184557140),\n\tKQU( 1072951366761385712), KQU(13098491780722836296),\n\tKQU( 9466676828710797353), KQU(12673056849042830081),\n\tKQU(12763726623645357580), KQU(16468961652999309493),\n\tKQU(15305979875636438926), KQU(17444713151223449734),\n\tKQU( 5692214267627883674), KQU(13049589139196151505),\n\tKQU(  880115207831670745), KQU( 1776529075789695498),\n\tKQU(16695225897801466485), KQU(10666901778795346845),\n\tKQU( 6164389346722833869), KQU( 2863817793264300475),\n\tKQU( 9464049921886304754), KQU( 3993566636740015468),\n\tKQU( 9983749692528514136), KQU(16375286075057755211),\n\tKQU(16042643417005440820), KQU(11445419662923489877),\n\tKQU( 7999038846885158836), KQU( 6721913661721511535),\n\tKQU( 5363052654139357320), KQU( 1817788761173584205),\n\tKQU(13290974386445856444), KQU( 4650350818937984680),\n\tKQU( 8219183528102484836), KQU( 1569862923500819899),\n\tKQU( 4189359732136641860), KQU(14202822961683148583),\n\tKQU( 4457498315309429058), KQU(13089067387019074834),\n\tKQU(11075517153328927293), KQU(10277016248336668389),\n\tKQU( 7070509725324401122), KQU(17808892017780289380),\n\tKQU(13143367339909287349), KQU( 1377743745360085151),\n\tKQU( 5749341807421286485), KQU(14832814616770931325),\n\tKQU( 7688820635324359492), KQU(10960474011539770045),\n\tKQU(   81970066653179790), KQU(12619476072607878022),\n\tKQU( 4419566616271201744), KQU(15147917311750568503),\n\tKQU( 5549739182852706345), KQU( 7308198397975204770),\n\tKQU(13580425496671289278), KQU(17070764785210130301),\n\tKQU( 8202832846285604405), KQU( 6873046287640887249),\n\tKQU( 6927424434308206114), KQU( 6139014645937224874),\n\tKQU(10290373645978487639), KQU(15904261291701523804),\n\tKQU( 9628743442057826883), KQU(18383429096255546714),\n\tKQU( 4977413265753686967), KQU( 7714317492425012869),\n\tKQU( 9025232586309926193), KQU(14627338359776709107),\n\tKQU(14759849896467790763), KQU(10931129435864423252),\n\tKQU( 4588456988775014359), KQU(10699388531797056724),\n\tKQU(  468652268869238792), KQU( 5755943035328078086),\n\tKQU( 2102437379988580216), KQU( 9986312786506674028),\n\tKQU( 2654207180040945604), KQU( 8726634790559960062),\n\tKQU(  100497234871808137), KQU( 2800137176951425819),\n\tKQU( 6076627612918553487), KQU( 5780186919186152796),\n\tKQU( 8179183595769929098), KQU( 6009426283716221169),\n\tKQU( 2796662551397449358), KQU( 1756961367041986764),\n\tKQU( 6972897917355606205), KQU(14524774345368968243),\n\tKQU( 2773529684745706940), KQU( 4853632376213075959),\n\tKQU( 4198177923731358102), KQU( 8271224913084139776),\n\tKQU( 2741753121611092226), KQU(16782366145996731181),\n\tKQU(15426125238972640790), KQU(13595497100671260342),\n\tKQU( 3173531022836259898), KQU( 6573264560319511662),\n\tKQU(18041111951511157441), KQU( 2351433581833135952),\n\tKQU( 3113255578908173487), KQU( 1739371330877858784),\n\tKQU(16046126562789165480), KQU( 8072101652214192925),\n\tKQU(15267091584090664910), KQU( 9309579200403648940),\n\tKQU( 5218892439752408722), KQU(14492477246004337115),\n\tKQU(17431037586679770619), KQU( 7385248135963250480),\n\tKQU( 9580144956565560660), KQU( 4919546228040008720),\n\tKQU(15261542469145035584), KQU(18233297270822253102),\n\tKQU( 5453248417992302857), KQU( 9309519155931460285),\n\tKQU(10342813012345291756), KQU(15676085186784762381),\n\tKQU(15912092950691300645), KQU( 9371053121499003195),\n\tKQU( 9897186478226866746), KQU(14061858287188196327),\n\tKQU(  122575971620788119), KQU(12146750969116317754),\n\tKQU( 4438317272813245201), KQU( 8332576791009527119),\n\tKQU(13907785691786542057), KQU(10374194887283287467),\n\tKQU( 2098798755649059566), KQU( 3416235197748288894),\n\tKQU( 8688269957320773484), KQU( 7503964602397371571),\n\tKQU(16724977015147478236), KQU( 9461512855439858184),\n\tKQU(13259049744534534727), KQU( 3583094952542899294),\n\tKQU( 8764245731305528292), KQU(13240823595462088985),\n\tKQU(13716141617617910448), KQU(18114969519935960955),\n\tKQU( 2297553615798302206), KQU( 4585521442944663362),\n\tKQU(17776858680630198686), KQU( 4685873229192163363),\n\tKQU(  152558080671135627), KQU(15424900540842670088),\n\tKQU(13229630297130024108), KQU(17530268788245718717),\n\tKQU(16675633913065714144), KQU( 3158912717897568068),\n\tKQU(15399132185380087288), KQU( 7401418744515677872),\n\tKQU(13135412922344398535), KQU( 6385314346100509511),\n\tKQU(13962867001134161139), KQU(10272780155442671999),\n\tKQU(12894856086597769142), KQU(13340877795287554994),\n\tKQU(12913630602094607396), KQU(12543167911119793857),\n\tKQU(17343570372251873096), KQU(10959487764494150545),\n\tKQU( 6966737953093821128), KQU(13780699135496988601),\n\tKQU( 4405070719380142046), KQU(14923788365607284982),\n\tKQU( 2869487678905148380), KQU( 6416272754197188403),\n\tKQU(15017380475943612591), KQU( 1995636220918429487),\n\tKQU( 3402016804620122716), KQU(15800188663407057080),\n\tKQU(11362369990390932882), KQU(15262183501637986147),\n\tKQU(10239175385387371494), KQU( 9352042420365748334),\n\tKQU( 1682457034285119875), KQU( 1724710651376289644),\n\tKQU( 2038157098893817966), KQU( 9897825558324608773),\n\tKQU( 1477666236519164736), KQU(16835397314511233640),\n\tKQU(10370866327005346508), KQU(10157504370660621982),\n\tKQU(12113904045335882069), KQU(13326444439742783008),\n\tKQU(11302769043000765804), KQU(13594979923955228484),\n\tKQU(11779351762613475968), KQU( 3786101619539298383),\n\tKQU( 8021122969180846063), KQU(15745904401162500495),\n\tKQU(10762168465993897267), KQU(13552058957896319026),\n\tKQU(11200228655252462013), KQU( 5035370357337441226),\n\tKQU( 7593918984545500013), KQU( 5418554918361528700),\n\tKQU( 4858270799405446371), KQU( 9974659566876282544),\n\tKQU(18227595922273957859), KQU( 2772778443635656220),\n\tKQU(14285143053182085385), KQU( 9939700992429600469),\n\tKQU(12756185904545598068), KQU( 2020783375367345262),\n\tKQU(   57026775058331227), KQU(  950827867930065454),\n\tKQU( 6602279670145371217), KQU( 2291171535443566929),\n\tKQU( 5832380724425010313), KQU( 1220343904715982285),\n\tKQU(17045542598598037633), KQU(15460481779702820971),\n\tKQU(13948388779949365130), KQU(13975040175430829518),\n\tKQU(17477538238425541763), KQU(11104663041851745725),\n\tKQU(15860992957141157587), KQU(14529434633012950138),\n\tKQU( 2504838019075394203), KQU( 7512113882611121886),\n\tKQU( 4859973559980886617), KQU( 1258601555703250219),\n\tKQU(15594548157514316394), KQU( 4516730171963773048),\n\tKQU(11380103193905031983), KQU( 6809282239982353344),\n\tKQU(18045256930420065002), KQU( 2453702683108791859),\n\tKQU(  977214582986981460), KQU( 2006410402232713466),\n\tKQU( 6192236267216378358), KQU( 3429468402195675253),\n\tKQU(18146933153017348921), KQU(17369978576367231139),\n\tKQU( 1246940717230386603), KQU(11335758870083327110),\n\tKQU(14166488801730353682), KQU( 9008573127269635732),\n\tKQU(10776025389820643815), KQU(15087605441903942962),\n\tKQU( 1359542462712147922), KQU(13898874411226454206),\n\tKQU(17911176066536804411), KQU( 9435590428600085274),\n\tKQU(  294488509967864007), KQU( 8890111397567922046),\n\tKQU( 7987823476034328778), KQU(13263827582440967651),\n\tKQU( 7503774813106751573), KQU(14974747296185646837),\n\tKQU( 8504765037032103375), KQU(17340303357444536213),\n\tKQU( 7704610912964485743), KQU( 8107533670327205061),\n\tKQU( 9062969835083315985), KQU(16968963142126734184),\n\tKQU(12958041214190810180), KQU( 2720170147759570200),\n\tKQU( 2986358963942189566), KQU(14884226322219356580),\n\tKQU(  286224325144368520), KQU(11313800433154279797),\n\tKQU(18366849528439673248), KQU(17899725929482368789),\n\tKQU( 3730004284609106799), KQU( 1654474302052767205),\n\tKQU( 5006698007047077032), KQU( 8196893913601182838),\n\tKQU(15214541774425211640), KQU(17391346045606626073),\n\tKQU( 8369003584076969089), KQU( 3939046733368550293),\n\tKQU(10178639720308707785), KQU( 2180248669304388697),\n\tKQU(   62894391300126322), KQU( 9205708961736223191),\n\tKQU( 6837431058165360438), KQU( 3150743890848308214),\n\tKQU(17849330658111464583), KQU(12214815643135450865),\n\tKQU(13410713840519603402), KQU( 3200778126692046802),\n\tKQU(13354780043041779313), KQU(  800850022756886036),\n\tKQU(15660052933953067433), KQU( 6572823544154375676),\n\tKQU(11030281857015819266), KQU(12682241941471433835),\n\tKQU(11654136407300274693), KQU( 4517795492388641109),\n\tKQU( 9757017371504524244), KQU(17833043400781889277),\n\tKQU(12685085201747792227), KQU(10408057728835019573),\n\tKQU(   98370418513455221), KQU( 6732663555696848598),\n\tKQU(13248530959948529780), KQU( 3530441401230622826),\n\tKQU(18188251992895660615), KQU( 1847918354186383756),\n\tKQU( 1127392190402660921), KQU(11293734643143819463),\n\tKQU( 3015506344578682982), KQU(13852645444071153329),\n\tKQU( 2121359659091349142), KQU( 1294604376116677694),\n\tKQU( 5616576231286352318), KQU( 7112502442954235625),\n\tKQU(11676228199551561689), KQU(12925182803007305359),\n\tKQU( 7852375518160493082), KQU( 1136513130539296154),\n\tKQU( 5636923900916593195), KQU( 3221077517612607747),\n\tKQU(17784790465798152513), KQU( 3554210049056995938),\n\tKQU(17476839685878225874), KQU( 3206836372585575732),\n\tKQU( 2765333945644823430), KQU(10080070903718799528),\n\tKQU( 5412370818878286353), KQU( 9689685887726257728),\n\tKQU( 8236117509123533998), KQU( 1951139137165040214),\n\tKQU( 4492205209227980349), KQU(16541291230861602967),\n\tKQU( 1424371548301437940), KQU( 9117562079669206794),\n\tKQU(14374681563251691625), KQU(13873164030199921303),\n\tKQU( 6680317946770936731), KQU(15586334026918276214),\n\tKQU(10896213950976109802), KQU( 9506261949596413689),\n\tKQU( 9903949574308040616), KQU( 6038397344557204470),\n\tKQU(  174601465422373648), KQU(15946141191338238030),\n\tKQU(17142225620992044937), KQU( 7552030283784477064),\n\tKQU( 2947372384532947997), KQU(  510797021688197711),\n\tKQU( 4962499439249363461), KQU(   23770320158385357),\n\tKQU(  959774499105138124), KQU( 1468396011518788276),\n\tKQU( 2015698006852312308), KQU( 4149400718489980136),\n\tKQU( 5992916099522371188), KQU(10819182935265531076),\n\tKQU(16189787999192351131), KQU(  342833961790261950),\n\tKQU(12470830319550495336), KQU(18128495041912812501),\n\tKQU( 1193600899723524337), KQU( 9056793666590079770),\n\tKQU( 2154021227041669041), KQU( 4963570213951235735),\n\tKQU( 4865075960209211409), KQU( 2097724599039942963),\n\tKQU( 2024080278583179845), KQU(11527054549196576736),\n\tKQU(10650256084182390252), KQU( 4808408648695766755),\n\tKQU( 1642839215013788844), KQU(10607187948250398390),\n\tKQU( 7076868166085913508), KQU(  730522571106887032),\n\tKQU(12500579240208524895), KQU( 4484390097311355324),\n\tKQU(15145801330700623870), KQU( 8055827661392944028),\n\tKQU( 5865092976832712268), KQU(15159212508053625143),\n\tKQU( 3560964582876483341), KQU( 4070052741344438280),\n\tKQU( 6032585709886855634), KQU(15643262320904604873),\n\tKQU( 2565119772293371111), KQU(  318314293065348260),\n\tKQU(15047458749141511872), KQU( 7772788389811528730),\n\tKQU( 7081187494343801976), KQU( 6465136009467253947),\n\tKQU(10425940692543362069), KQU(  554608190318339115),\n\tKQU(14796699860302125214), KQU( 1638153134431111443),\n\tKQU(10336967447052276248), KQU( 8412308070396592958),\n\tKQU( 4004557277152051226), KQU( 8143598997278774834),\n\tKQU(16413323996508783221), KQU(13139418758033994949),\n\tKQU( 9772709138335006667), KQU( 2818167159287157659),\n\tKQU(17091740573832523669), KQU(14629199013130751608),\n\tKQU(18268322711500338185), KQU( 8290963415675493063),\n\tKQU( 8830864907452542588), KQU( 1614839084637494849),\n\tKQU(14855358500870422231), KQU( 3472996748392519937),\n\tKQU(15317151166268877716), KQU( 5825895018698400362),\n\tKQU(16730208429367544129), KQU(10481156578141202800),\n\tKQU( 4746166512382823750), KQU(12720876014472464998),\n\tKQU( 8825177124486735972), KQU(13733447296837467838),\n\tKQU( 6412293741681359625), KQU( 8313213138756135033),\n\tKQU(11421481194803712517), KQU( 7997007691544174032),\n\tKQU( 6812963847917605930), KQU( 9683091901227558641),\n\tKQU(14703594165860324713), KQU( 1775476144519618309),\n\tKQU( 2724283288516469519), KQU(  717642555185856868),\n\tKQU( 8736402192215092346), KQU(11878800336431381021),\n\tKQU( 4348816066017061293), KQU( 6115112756583631307),\n\tKQU( 9176597239667142976), KQU(12615622714894259204),\n\tKQU(10283406711301385987), KQU( 5111762509485379420),\n\tKQU( 3118290051198688449), KQU( 7345123071632232145),\n\tKQU( 9176423451688682359), KQU( 4843865456157868971),\n\tKQU(12008036363752566088), KQU(12058837181919397720),\n\tKQU( 2145073958457347366), KQU( 1526504881672818067),\n\tKQU( 3488830105567134848), KQU(13208362960674805143),\n\tKQU( 4077549672899572192), KQU( 7770995684693818365),\n\tKQU( 1398532341546313593), KQU(12711859908703927840),\n\tKQU( 1417561172594446813), KQU(17045191024194170604),\n\tKQU( 4101933177604931713), KQU(14708428834203480320),\n\tKQU(17447509264469407724), KQU(14314821973983434255),\n\tKQU(17990472271061617265), KQU( 5087756685841673942),\n\tKQU(12797820586893859939), KQU( 1778128952671092879),\n\tKQU( 3535918530508665898), KQU( 9035729701042481301),\n\tKQU(14808661568277079962), KQU(14587345077537747914),\n\tKQU(11920080002323122708), KQU( 6426515805197278753),\n\tKQU( 3295612216725984831), KQU(11040722532100876120),\n\tKQU(12305952936387598754), KQU(16097391899742004253),\n\tKQU( 4908537335606182208), KQU(12446674552196795504),\n\tKQU(16010497855816895177), KQU( 9194378874788615551),\n\tKQU( 3382957529567613384), KQU( 5154647600754974077),\n\tKQU( 9801822865328396141), KQU( 9023662173919288143),\n\tKQU(17623115353825147868), KQU( 8238115767443015816),\n\tKQU(15811444159859002560), KQU( 9085612528904059661),\n\tKQU( 6888601089398614254), KQU(  258252992894160189),\n\tKQU( 6704363880792428622), KQU( 6114966032147235763),\n\tKQU(11075393882690261875), KQU( 8797664238933620407),\n\tKQU( 5901892006476726920), KQU( 5309780159285518958),\n\tKQU(14940808387240817367), KQU(14642032021449656698),\n\tKQU( 9808256672068504139), KQU( 3670135111380607658),\n\tKQU(11211211097845960152), KQU( 1474304506716695808),\n\tKQU(15843166204506876239), KQU( 7661051252471780561),\n\tKQU(10170905502249418476), KQU( 7801416045582028589),\n\tKQU( 2763981484737053050), KQU( 9491377905499253054),\n\tKQU(16201395896336915095), KQU( 9256513756442782198),\n\tKQU( 5411283157972456034), KQU( 5059433122288321676),\n\tKQU( 4327408006721123357), KQU( 9278544078834433377),\n\tKQU( 7601527110882281612), KQU(11848295896975505251),\n\tKQU(12096998801094735560), KQU(14773480339823506413),\n\tKQU(15586227433895802149), KQU(12786541257830242872),\n\tKQU( 6904692985140503067), KQU( 5309011515263103959),\n\tKQU(12105257191179371066), KQU(14654380212442225037),\n\tKQU( 2556774974190695009), KQU( 4461297399927600261),\n\tKQU(14888225660915118646), KQU(14915459341148291824),\n\tKQU( 2738802166252327631), KQU( 6047155789239131512),\n\tKQU(12920545353217010338), KQU(10697617257007840205),\n\tKQU( 2751585253158203504), KQU(13252729159780047496),\n\tKQU(14700326134672815469), KQU(14082527904374600529),\n\tKQU(16852962273496542070), KQU(17446675504235853907),\n\tKQU(15019600398527572311), KQU(12312781346344081551),\n\tKQU(14524667935039810450), KQU( 5634005663377195738),\n\tKQU(11375574739525000569), KQU( 2423665396433260040),\n\tKQU( 5222836914796015410), KQU( 4397666386492647387),\n\tKQU( 4619294441691707638), KQU(  665088602354770716),\n\tKQU(13246495665281593610), KQU( 6564144270549729409),\n\tKQU(10223216188145661688), KQU( 3961556907299230585),\n\tKQU(11543262515492439914), KQU(16118031437285993790),\n\tKQU( 7143417964520166465), KQU(13295053515909486772),\n\tKQU(   40434666004899675), KQU(17127804194038347164),\n\tKQU( 8599165966560586269), KQU( 8214016749011284903),\n\tKQU(13725130352140465239), KQU( 5467254474431726291),\n\tKQU( 7748584297438219877), KQU(16933551114829772472),\n\tKQU( 2169618439506799400), KQU( 2169787627665113463),\n\tKQU(17314493571267943764), KQU(18053575102911354912),\n\tKQU(11928303275378476973), KQU(11593850925061715550),\n\tKQU(17782269923473589362), KQU( 3280235307704747039),\n\tKQU( 6145343578598685149), KQU(17080117031114086090),\n\tKQU(18066839902983594755), KQU( 6517508430331020706),\n\tKQU( 8092908893950411541), KQU(12558378233386153732),\n\tKQU( 4476532167973132976), KQU(16081642430367025016),\n\tKQU( 4233154094369139361), KQU( 8693630486693161027),\n\tKQU(11244959343027742285), KQU(12273503967768513508),\n\tKQU(14108978636385284876), KQU( 7242414665378826984),\n\tKQU( 6561316938846562432), KQU( 8601038474994665795),\n\tKQU(17532942353612365904), KQU(17940076637020912186),\n\tKQU( 7340260368823171304), KQU( 7061807613916067905),\n\tKQU(10561734935039519326), KQU(17990796503724650862),\n\tKQU( 6208732943911827159), KQU(  359077562804090617),\n\tKQU(14177751537784403113), KQU(10659599444915362902),\n\tKQU(15081727220615085833), KQU(13417573895659757486),\n\tKQU(15513842342017811524), KQU(11814141516204288231),\n\tKQU( 1827312513875101814), KQU( 2804611699894603103),\n\tKQU(17116500469975602763), KQU(12270191815211952087),\n\tKQU(12256358467786024988), KQU(18435021722453971267),\n\tKQU(  671330264390865618), KQU(  476504300460286050),\n\tKQU(16465470901027093441), KQU( 4047724406247136402),\n\tKQU( 1322305451411883346), KQU( 1388308688834322280),\n\tKQU( 7303989085269758176), KQU( 9323792664765233642),\n\tKQU( 4542762575316368936), KQU(17342696132794337618),\n\tKQU( 4588025054768498379), KQU(13415475057390330804),\n\tKQU(17880279491733405570), KQU(10610553400618620353),\n\tKQU( 3180842072658960139), KQU(13002966655454270120),\n\tKQU( 1665301181064982826), KQU( 7083673946791258979),\n\tKQU(  190522247122496820), KQU(17388280237250677740),\n\tKQU( 8430770379923642945), KQU(12987180971921668584),\n\tKQU( 2311086108365390642), KQU( 2870984383579822345),\n\tKQU(14014682609164653318), KQU(14467187293062251484),\n\tKQU(  192186361147413298), KQU(15171951713531796524),\n\tKQU( 9900305495015948728), KQU(17958004775615466344),\n\tKQU(14346380954498606514), KQU(18040047357617407096),\n\tKQU( 5035237584833424532), KQU(15089555460613972287),\n\tKQU( 4131411873749729831), KQU( 1329013581168250330),\n\tKQU(10095353333051193949), KQU(10749518561022462716),\n\tKQU( 9050611429810755847), KQU(15022028840236655649),\n\tKQU( 8775554279239748298), KQU(13105754025489230502),\n\tKQU(15471300118574167585), KQU(   89864764002355628),\n\tKQU( 8776416323420466637), KQU( 5280258630612040891),\n\tKQU( 2719174488591862912), KQU( 7599309137399661994),\n\tKQU(15012887256778039979), KQU(14062981725630928925),\n\tKQU(12038536286991689603), KQU( 7089756544681775245),\n\tKQU(10376661532744718039), KQU( 1265198725901533130),\n\tKQU(13807996727081142408), KQU( 2935019626765036403),\n\tKQU( 7651672460680700141), KQU( 3644093016200370795),\n\tKQU( 2840982578090080674), KQU(17956262740157449201),\n\tKQU(18267979450492880548), KQU(11799503659796848070),\n\tKQU( 9942537025669672388), KQU(11886606816406990297),\n\tKQU( 5488594946437447576), KQU( 7226714353282744302),\n\tKQU( 3784851653123877043), KQU(  878018453244803041),\n\tKQU(12110022586268616085), KQU(  734072179404675123),\n\tKQU(11869573627998248542), KQU(  469150421297783998),\n\tKQU(  260151124912803804), KQU(11639179410120968649),\n\tKQU( 9318165193840846253), KQU(12795671722734758075),\n\tKQU(15318410297267253933), KQU(  691524703570062620),\n\tKQU( 5837129010576994601), KQU(15045963859726941052),\n\tKQU( 5850056944932238169), KQU(12017434144750943807),\n\tKQU( 7447139064928956574), KQU( 3101711812658245019),\n\tKQU(16052940704474982954), KQU(18195745945986994042),\n\tKQU( 8932252132785575659), KQU(13390817488106794834),\n\tKQU(11582771836502517453), KQU( 4964411326683611686),\n\tKQU( 2195093981702694011), KQU(14145229538389675669),\n\tKQU(16459605532062271798), KQU(  866316924816482864),\n\tKQU( 4593041209937286377), KQU( 8415491391910972138),\n\tKQU( 4171236715600528969), KQU(16637569303336782889),\n\tKQU( 2002011073439212680), KQU(17695124661097601411),\n\tKQU( 4627687053598611702), KQU( 7895831936020190403),\n\tKQU( 8455951300917267802), KQU( 2923861649108534854),\n\tKQU( 8344557563927786255), KQU( 6408671940373352556),\n\tKQU(12210227354536675772), KQU(14294804157294222295),\n\tKQU(10103022425071085127), KQU(10092959489504123771),\n\tKQU( 6554774405376736268), KQU(12629917718410641774),\n\tKQU( 6260933257596067126), KQU( 2460827021439369673),\n\tKQU( 2541962996717103668), KQU(  597377203127351475),\n\tKQU( 5316984203117315309), KQU( 4811211393563241961),\n\tKQU(13119698597255811641), KQU( 8048691512862388981),\n\tKQU(10216818971194073842), KQU( 4612229970165291764),\n\tKQU(10000980798419974770), KQU( 6877640812402540687),\n\tKQU( 1488727563290436992), KQU( 2227774069895697318),\n\tKQU(11237754507523316593), KQU(13478948605382290972),\n\tKQU( 1963583846976858124), KQU( 5512309205269276457),\n\tKQU( 3972770164717652347), KQU( 3841751276198975037),\n\tKQU(10283343042181903117), KQU( 8564001259792872199),\n\tKQU(16472187244722489221), KQU( 8953493499268945921),\n\tKQU( 3518747340357279580), KQU( 4003157546223963073),\n\tKQU( 3270305958289814590), KQU( 3966704458129482496),\n\tKQU( 8122141865926661939), KQU(14627734748099506653),\n\tKQU(13064426990862560568), KQU( 2414079187889870829),\n\tKQU( 5378461209354225306), KQU(10841985740128255566),\n\tKQU(  538582442885401738), KQU( 7535089183482905946),\n\tKQU(16117559957598879095), KQU( 8477890721414539741),\n\tKQU( 1459127491209533386), KQU(17035126360733620462),\n\tKQU( 8517668552872379126), KQU(10292151468337355014),\n\tKQU(17081267732745344157), KQU(13751455337946087178),\n\tKQU(14026945459523832966), KQU( 6653278775061723516),\n\tKQU(10619085543856390441), KQU( 2196343631481122885),\n\tKQU(10045966074702826136), KQU(10082317330452718282),\n\tKQU( 5920859259504831242), KQU( 9951879073426540617),\n\tKQU( 7074696649151414158), KQU(15808193543879464318),\n\tKQU( 7385247772746953374), KQU( 3192003544283864292),\n\tKQU(18153684490917593847), KQU(12423498260668568905),\n\tKQU(10957758099756378169), KQU(11488762179911016040),\n\tKQU( 2099931186465333782), KQU(11180979581250294432),\n\tKQU( 8098916250668367933), KQU( 3529200436790763465),\n\tKQU(12988418908674681745), KQU( 6147567275954808580),\n\tKQU( 3207503344604030989), KQU(10761592604898615360),\n\tKQU(  229854861031893504), KQU( 8809853962667144291),\n\tKQU(13957364469005693860), KQU( 7634287665224495886),\n\tKQU(12353487366976556874), KQU( 1134423796317152034),\n\tKQU( 2088992471334107068), KQU( 7393372127190799698),\n\tKQU( 1845367839871058391), KQU(  207922563987322884),\n\tKQU(11960870813159944976), KQU(12182120053317317363),\n\tKQU(17307358132571709283), KQU(13871081155552824936),\n\tKQU(18304446751741566262), KQU( 7178705220184302849),\n\tKQU(10929605677758824425), KQU(16446976977835806844),\n\tKQU(13723874412159769044), KQU( 6942854352100915216),\n\tKQU( 1726308474365729390), KQU( 2150078766445323155),\n\tKQU(15345558947919656626), KQU(12145453828874527201),\n\tKQU( 2054448620739726849), KQU( 2740102003352628137),\n\tKQU(11294462163577610655), KQU(  756164283387413743),\n\tKQU(17841144758438810880), KQU(10802406021185415861),\n\tKQU( 8716455530476737846), KQU( 6321788834517649606),\n\tKQU(14681322910577468426), KQU(17330043563884336387),\n\tKQU(12701802180050071614), KQU(14695105111079727151),\n\tKQU( 5112098511654172830), KQU( 4957505496794139973),\n\tKQU( 8270979451952045982), KQU(12307685939199120969),\n\tKQU(12425799408953443032), KQU( 8376410143634796588),\n\tKQU(16621778679680060464), KQU( 3580497854566660073),\n\tKQU( 1122515747803382416), KQU(  857664980960597599),\n\tKQU( 6343640119895925918), KQU(12878473260854462891),\n\tKQU(10036813920765722626), KQU(14451335468363173812),\n\tKQU( 5476809692401102807), KQU(16442255173514366342),\n\tKQU(13060203194757167104), KQU(14354124071243177715),\n\tKQU(15961249405696125227), KQU(13703893649690872584),\n\tKQU(  363907326340340064), KQU( 6247455540491754842),\n\tKQU(12242249332757832361), KQU(  156065475679796717),\n\tKQU( 9351116235749732355), KQU( 4590350628677701405),\n\tKQU( 1671195940982350389), KQU(13501398458898451905),\n\tKQU( 6526341991225002255), KQU( 1689782913778157592),\n\tKQU( 7439222350869010334), KQU(13975150263226478308),\n\tKQU(11411961169932682710), KQU(17204271834833847277),\n\tKQU(  541534742544435367), KQU( 6591191931218949684),\n\tKQU( 2645454775478232486), KQU( 4322857481256485321),\n\tKQU( 8477416487553065110), KQU(12902505428548435048),\n\tKQU(  971445777981341415), KQU(14995104682744976712),\n\tKQU( 4243341648807158063), KQU( 8695061252721927661),\n\tKQU( 5028202003270177222), KQU( 2289257340915567840),\n\tKQU(13870416345121866007), KQU(13994481698072092233),\n\tKQU( 6912785400753196481), KQU( 2278309315841980139),\n\tKQU( 4329765449648304839), KQU( 5963108095785485298),\n\tKQU( 4880024847478722478), KQU(16015608779890240947),\n\tKQU( 1866679034261393544), KQU(  914821179919731519),\n\tKQU( 9643404035648760131), KQU( 2418114953615593915),\n\tKQU(  944756836073702374), KQU(15186388048737296834),\n\tKQU( 7723355336128442206), KQU( 7500747479679599691),\n\tKQU(18013961306453293634), KQU( 2315274808095756456),\n\tKQU(13655308255424029566), KQU(17203800273561677098),\n\tKQU( 1382158694422087756), KQU( 5090390250309588976),\n\tKQU(  517170818384213989), KQU( 1612709252627729621),\n\tKQU( 1330118955572449606), KQU(  300922478056709885),\n\tKQU(18115693291289091987), KQU(13491407109725238321),\n\tKQU(15293714633593827320), KQU( 5151539373053314504),\n\tKQU( 5951523243743139207), KQU(14459112015249527975),\n\tKQU( 5456113959000700739), KQU( 3877918438464873016),\n\tKQU(12534071654260163555), KQU(15871678376893555041),\n\tKQU(11005484805712025549), KQU(16353066973143374252),\n\tKQU( 4358331472063256685), KQU( 8268349332210859288),\n\tKQU(12485161590939658075), KQU(13955993592854471343),\n\tKQU( 5911446886848367039), KQU(14925834086813706974),\n\tKQU( 6590362597857994805), KQU( 1280544923533661875),\n\tKQU( 1637756018947988164), KQU( 4734090064512686329),\n\tKQU(16693705263131485912), KQU( 6834882340494360958),\n\tKQU( 8120732176159658505), KQU( 2244371958905329346),\n\tKQU(10447499707729734021), KQU( 7318742361446942194),\n\tKQU( 8032857516355555296), KQU(14023605983059313116),\n\tKQU( 1032336061815461376), KQU( 9840995337876562612),\n\tKQU( 9869256223029203587), KQU(12227975697177267636),\n\tKQU(12728115115844186033), KQU( 7752058479783205470),\n\tKQU(  729733219713393087), KQU(12954017801239007622)\n};\nstatic const uint64_t init_by_array_64_expected[] = {\n\tKQU( 2100341266307895239), KQU( 8344256300489757943),\n\tKQU(15687933285484243894), KQU( 8268620370277076319),\n\tKQU(12371852309826545459), KQU( 8800491541730110238),\n\tKQU(18113268950100835773), KQU( 2886823658884438119),\n\tKQU( 3293667307248180724), KQU( 9307928143300172731),\n\tKQU( 7688082017574293629), KQU(  900986224735166665),\n\tKQU( 9977972710722265039), KQU( 6008205004994830552),\n\tKQU(  546909104521689292), KQU( 7428471521869107594),\n\tKQU(14777563419314721179), KQU(16116143076567350053),\n\tKQU( 5322685342003142329), KQU( 4200427048445863473),\n\tKQU( 4693092150132559146), KQU(13671425863759338582),\n\tKQU( 6747117460737639916), KQU( 4732666080236551150),\n\tKQU( 5912839950611941263), KQU( 3903717554504704909),\n\tKQU( 2615667650256786818), KQU(10844129913887006352),\n\tKQU(13786467861810997820), KQU(14267853002994021570),\n\tKQU(13767807302847237439), KQU(16407963253707224617),\n\tKQU( 4802498363698583497), KQU( 2523802839317209764),\n\tKQU( 3822579397797475589), KQU( 8950320572212130610),\n\tKQU( 3745623504978342534), KQU(16092609066068482806),\n\tKQU( 9817016950274642398), KQU(10591660660323829098),\n\tKQU(11751606650792815920), KQU( 5122873818577122211),\n\tKQU(17209553764913936624), KQU( 6249057709284380343),\n\tKQU(15088791264695071830), KQU(15344673071709851930),\n\tKQU( 4345751415293646084), KQU( 2542865750703067928),\n\tKQU(13520525127852368784), KQU(18294188662880997241),\n\tKQU( 3871781938044881523), KQU( 2873487268122812184),\n\tKQU(15099676759482679005), KQU(15442599127239350490),\n\tKQU( 6311893274367710888), KQU( 3286118760484672933),\n\tKQU( 4146067961333542189), KQU(13303942567897208770),\n\tKQU( 8196013722255630418), KQU( 4437815439340979989),\n\tKQU(15433791533450605135), KQU( 4254828956815687049),\n\tKQU( 1310903207708286015), KQU(10529182764462398549),\n\tKQU(14900231311660638810), KQU( 9727017277104609793),\n\tKQU( 1821308310948199033), KQU(11628861435066772084),\n\tKQU( 9469019138491546924), KQU( 3145812670532604988),\n\tKQU( 9938468915045491919), KQU( 1562447430672662142),\n\tKQU(13963995266697989134), KQU( 3356884357625028695),\n\tKQU( 4499850304584309747), KQU( 8456825817023658122),\n\tKQU(10859039922814285279), KQU( 8099512337972526555),\n\tKQU(  348006375109672149), KQU(11919893998241688603),\n\tKQU( 1104199577402948826), KQU(16689191854356060289),\n\tKQU(10992552041730168078), KQU( 7243733172705465836),\n\tKQU( 5668075606180319560), KQU(18182847037333286970),\n\tKQU( 4290215357664631322), KQU( 4061414220791828613),\n\tKQU(13006291061652989604), KQU( 7140491178917128798),\n\tKQU(12703446217663283481), KQU( 5500220597564558267),\n\tKQU(10330551509971296358), KQU(15958554768648714492),\n\tKQU( 5174555954515360045), KQU( 1731318837687577735),\n\tKQU( 3557700801048354857), KQU(13764012341928616198),\n\tKQU(13115166194379119043), KQU( 7989321021560255519),\n\tKQU( 2103584280905877040), KQU( 9230788662155228488),\n\tKQU(16396629323325547654), KQU(  657926409811318051),\n\tKQU(15046700264391400727), KQU( 5120132858771880830),\n\tKQU( 7934160097989028561), KQU( 6963121488531976245),\n\tKQU(17412329602621742089), KQU(15144843053931774092),\n\tKQU(17204176651763054532), KQU(13166595387554065870),\n\tKQU( 8590377810513960213), KQU( 5834365135373991938),\n\tKQU( 7640913007182226243), KQU( 3479394703859418425),\n\tKQU(16402784452644521040), KQU( 4993979809687083980),\n\tKQU(13254522168097688865), KQU(15643659095244365219),\n\tKQU( 5881437660538424982), KQU(11174892200618987379),\n\tKQU(  254409966159711077), KQU(17158413043140549909),\n\tKQU( 3638048789290376272), KQU( 1376816930299489190),\n\tKQU( 4622462095217761923), KQU(15086407973010263515),\n\tKQU(13253971772784692238), KQU( 5270549043541649236),\n\tKQU(11182714186805411604), KQU(12283846437495577140),\n\tKQU( 5297647149908953219), KQU(10047451738316836654),\n\tKQU( 4938228100367874746), KQU(12328523025304077923),\n\tKQU( 3601049438595312361), KQU( 9313624118352733770),\n\tKQU(13322966086117661798), KQU(16660005705644029394),\n\tKQU(11337677526988872373), KQU(13869299102574417795),\n\tKQU(15642043183045645437), KQU( 3021755569085880019),\n\tKQU( 4979741767761188161), KQU(13679979092079279587),\n\tKQU( 3344685842861071743), KQU(13947960059899588104),\n\tKQU(  305806934293368007), KQU( 5749173929201650029),\n\tKQU(11123724852118844098), KQU(15128987688788879802),\n\tKQU(15251651211024665009), KQU( 7689925933816577776),\n\tKQU(16732804392695859449), KQU(17087345401014078468),\n\tKQU(14315108589159048871), KQU( 4820700266619778917),\n\tKQU(16709637539357958441), KQU( 4936227875177351374),\n\tKQU( 2137907697912987247), KQU(11628565601408395420),\n\tKQU( 2333250549241556786), KQU( 5711200379577778637),\n\tKQU( 5170680131529031729), KQU(12620392043061335164),\n\tKQU(   95363390101096078), KQU( 5487981914081709462),\n\tKQU( 1763109823981838620), KQU( 3395861271473224396),\n\tKQU( 1300496844282213595), KQU( 6894316212820232902),\n\tKQU(10673859651135576674), KQU( 5911839658857903252),\n\tKQU(17407110743387299102), KQU( 8257427154623140385),\n\tKQU(11389003026741800267), KQU( 4070043211095013717),\n\tKQU(11663806997145259025), KQU(15265598950648798210),\n\tKQU(  630585789434030934), KQU( 3524446529213587334),\n\tKQU( 7186424168495184211), KQU(10806585451386379021),\n\tKQU(11120017753500499273), KQU( 1586837651387701301),\n\tKQU(17530454400954415544), KQU( 9991670045077880430),\n\tKQU( 7550997268990730180), KQU( 8640249196597379304),\n\tKQU( 3522203892786893823), KQU(10401116549878854788),\n\tKQU(13690285544733124852), KQU( 8295785675455774586),\n\tKQU(15535716172155117603), KQU( 3112108583723722511),\n\tKQU(17633179955339271113), KQU(18154208056063759375),\n\tKQU( 1866409236285815666), KQU(13326075895396412882),\n\tKQU( 8756261842948020025), KQU( 6281852999868439131),\n\tKQU(15087653361275292858), KQU(10333923911152949397),\n\tKQU( 5265567645757408500), KQU(12728041843210352184),\n\tKQU( 6347959327507828759), KQU(  154112802625564758),\n\tKQU(18235228308679780218), KQU( 3253805274673352418),\n\tKQU( 4849171610689031197), KQU(17948529398340432518),\n\tKQU(13803510475637409167), KQU(13506570190409883095),\n\tKQU(15870801273282960805), KQU( 8451286481299170773),\n\tKQU( 9562190620034457541), KQU( 8518905387449138364),\n\tKQU(12681306401363385655), KQU( 3788073690559762558),\n\tKQU( 5256820289573487769), KQU( 2752021372314875467),\n\tKQU( 6354035166862520716), KQU( 4328956378309739069),\n\tKQU(  449087441228269600), KQU( 5533508742653090868),\n\tKQU( 1260389420404746988), KQU(18175394473289055097),\n\tKQU( 1535467109660399420), KQU( 8818894282874061442),\n\tKQU(12140873243824811213), KQU(15031386653823014946),\n\tKQU( 1286028221456149232), KQU( 6329608889367858784),\n\tKQU( 9419654354945132725), KQU( 6094576547061672379),\n\tKQU(17706217251847450255), KQU( 1733495073065878126),\n\tKQU(16918923754607552663), KQU( 8881949849954945044),\n\tKQU(12938977706896313891), KQU(14043628638299793407),\n\tKQU(18393874581723718233), KQU( 6886318534846892044),\n\tKQU(14577870878038334081), KQU(13541558383439414119),\n\tKQU(13570472158807588273), KQU(18300760537910283361),\n\tKQU(  818368572800609205), KQU( 1417000585112573219),\n\tKQU(12337533143867683655), KQU(12433180994702314480),\n\tKQU(  778190005829189083), KQU(13667356216206524711),\n\tKQU( 9866149895295225230), KQU(11043240490417111999),\n\tKQU( 1123933826541378598), KQU( 6469631933605123610),\n\tKQU(14508554074431980040), KQU(13918931242962026714),\n\tKQU( 2870785929342348285), KQU(14786362626740736974),\n\tKQU(13176680060902695786), KQU( 9591778613541679456),\n\tKQU( 9097662885117436706), KQU(  749262234240924947),\n\tKQU( 1944844067793307093), KQU( 4339214904577487742),\n\tKQU( 8009584152961946551), KQU(16073159501225501777),\n\tKQU( 3335870590499306217), KQU(17088312653151202847),\n\tKQU( 3108893142681931848), KQU(16636841767202792021),\n\tKQU(10423316431118400637), KQU( 8008357368674443506),\n\tKQU(11340015231914677875), KQU(17687896501594936090),\n\tKQU(15173627921763199958), KQU(  542569482243721959),\n\tKQU(15071714982769812975), KQU( 4466624872151386956),\n\tKQU( 1901780715602332461), KQU( 9822227742154351098),\n\tKQU( 1479332892928648780), KQU( 6981611948382474400),\n\tKQU( 7620824924456077376), KQU(14095973329429406782),\n\tKQU( 7902744005696185404), KQU(15830577219375036920),\n\tKQU(10287076667317764416), KQU(12334872764071724025),\n\tKQU( 4419302088133544331), KQU(14455842851266090520),\n\tKQU(12488077416504654222), KQU( 7953892017701886766),\n\tKQU( 6331484925529519007), KQU( 4902145853785030022),\n\tKQU(17010159216096443073), KQU(11945354668653886087),\n\tKQU(15112022728645230829), KQU(17363484484522986742),\n\tKQU( 4423497825896692887), KQU( 8155489510809067471),\n\tKQU(  258966605622576285), KQU( 5462958075742020534),\n\tKQU( 6763710214913276228), KQU( 2368935183451109054),\n\tKQU(14209506165246453811), KQU( 2646257040978514881),\n\tKQU( 3776001911922207672), KQU( 1419304601390147631),\n\tKQU(14987366598022458284), KQU( 3977770701065815721),\n\tKQU(  730820417451838898), KQU( 3982991703612885327),\n\tKQU( 2803544519671388477), KQU(17067667221114424649),\n\tKQU( 2922555119737867166), KQU( 1989477584121460932),\n\tKQU(15020387605892337354), KQU( 9293277796427533547),\n\tKQU(10722181424063557247), KQU(16704542332047511651),\n\tKQU( 5008286236142089514), KQU(16174732308747382540),\n\tKQU(17597019485798338402), KQU(13081745199110622093),\n\tKQU( 8850305883842258115), KQU(12723629125624589005),\n\tKQU( 8140566453402805978), KQU(15356684607680935061),\n\tKQU(14222190387342648650), KQU(11134610460665975178),\n\tKQU( 1259799058620984266), KQU(13281656268025610041),\n\tKQU(  298262561068153992), KQU(12277871700239212922),\n\tKQU(13911297774719779438), KQU(16556727962761474934),\n\tKQU(17903010316654728010), KQU( 9682617699648434744),\n\tKQU(14757681836838592850), KQU( 1327242446558524473),\n\tKQU(11126645098780572792), KQU( 1883602329313221774),\n\tKQU( 2543897783922776873), KQU(15029168513767772842),\n\tKQU(12710270651039129878), KQU(16118202956069604504),\n\tKQU(15010759372168680524), KQU( 2296827082251923948),\n\tKQU(10793729742623518101), KQU(13829764151845413046),\n\tKQU(17769301223184451213), KQU( 3118268169210783372),\n\tKQU(17626204544105123127), KQU( 7416718488974352644),\n\tKQU(10450751996212925994), KQU( 9352529519128770586),\n\tKQU(  259347569641110140), KQU( 8048588892269692697),\n\tKQU( 1774414152306494058), KQU(10669548347214355622),\n\tKQU(13061992253816795081), KQU(18432677803063861659),\n\tKQU( 8879191055593984333), KQU(12433753195199268041),\n\tKQU(14919392415439730602), KQU( 6612848378595332963),\n\tKQU( 6320986812036143628), KQU(10465592420226092859),\n\tKQU( 4196009278962570808), KQU( 3747816564473572224),\n\tKQU(17941203486133732898), KQU( 2350310037040505198),\n\tKQU( 5811779859134370113), KQU(10492109599506195126),\n\tKQU( 7699650690179541274), KQU( 1954338494306022961),\n\tKQU(14095816969027231152), KQU( 5841346919964852061),\n\tKQU(14945969510148214735), KQU( 3680200305887550992),\n\tKQU( 6218047466131695792), KQU( 8242165745175775096),\n\tKQU(11021371934053307357), KQU( 1265099502753169797),\n\tKQU( 4644347436111321718), KQU( 3609296916782832859),\n\tKQU( 8109807992218521571), KQU(18387884215648662020),\n\tKQU(14656324896296392902), KQU(17386819091238216751),\n\tKQU(17788300878582317152), KQU( 7919446259742399591),\n\tKQU( 4466613134576358004), KQU(12928181023667938509),\n\tKQU(13147446154454932030), KQU(16552129038252734620),\n\tKQU( 8395299403738822450), KQU(11313817655275361164),\n\tKQU(  434258809499511718), KQU( 2074882104954788676),\n\tKQU( 7929892178759395518), KQU( 9006461629105745388),\n\tKQU( 5176475650000323086), KQU(11128357033468341069),\n\tKQU(12026158851559118955), KQU(14699716249471156500),\n\tKQU(  448982497120206757), KQU( 4156475356685519900),\n\tKQU( 6063816103417215727), KQU(10073289387954971479),\n\tKQU( 8174466846138590962), KQU( 2675777452363449006),\n\tKQU( 9090685420572474281), KQU( 6659652652765562060),\n\tKQU(12923120304018106621), KQU(11117480560334526775),\n\tKQU(  937910473424587511), KQU( 1838692113502346645),\n\tKQU(11133914074648726180), KQU( 7922600945143884053),\n\tKQU(13435287702700959550), KQU( 5287964921251123332),\n\tKQU(11354875374575318947), KQU(17955724760748238133),\n\tKQU(13728617396297106512), KQU( 4107449660118101255),\n\tKQU( 1210269794886589623), KQU(11408687205733456282),\n\tKQU( 4538354710392677887), KQU(13566803319341319267),\n\tKQU(17870798107734050771), KQU( 3354318982568089135),\n\tKQU( 9034450839405133651), KQU(13087431795753424314),\n\tKQU(  950333102820688239), KQU( 1968360654535604116),\n\tKQU(16840551645563314995), KQU( 8867501803892924995),\n\tKQU(11395388644490626845), KQU( 1529815836300732204),\n\tKQU(13330848522996608842), KQU( 1813432878817504265),\n\tKQU( 2336867432693429560), KQU(15192805445973385902),\n\tKQU( 2528593071076407877), KQU(  128459777936689248),\n\tKQU( 9976345382867214866), KQU( 6208885766767996043),\n\tKQU(14982349522273141706), KQU( 3099654362410737822),\n\tKQU(13776700761947297661), KQU( 8806185470684925550),\n\tKQU( 8151717890410585321), KQU(  640860591588072925),\n\tKQU(14592096303937307465), KQU( 9056472419613564846),\n\tKQU(14861544647742266352), KQU(12703771500398470216),\n\tKQU( 3142372800384138465), KQU( 6201105606917248196),\n\tKQU(18337516409359270184), KQU(15042268695665115339),\n\tKQU(15188246541383283846), KQU(12800028693090114519),\n\tKQU( 5992859621101493472), KQU(18278043971816803521),\n\tKQU( 9002773075219424560), KQU( 7325707116943598353),\n\tKQU( 7930571931248040822), KQU( 5645275869617023448),\n\tKQU( 7266107455295958487), KQU( 4363664528273524411),\n\tKQU(14313875763787479809), KQU(17059695613553486802),\n\tKQU( 9247761425889940932), KQU(13704726459237593128),\n\tKQU( 2701312427328909832), KQU(17235532008287243115),\n\tKQU(14093147761491729538), KQU( 6247352273768386516),\n\tKQU( 8268710048153268415), KQU( 7985295214477182083),\n\tKQU(15624495190888896807), KQU( 3772753430045262788),\n\tKQU( 9133991620474991698), KQU( 5665791943316256028),\n\tKQU( 7551996832462193473), KQU(13163729206798953877),\n\tKQU( 9263532074153846374), KQU( 1015460703698618353),\n\tKQU(17929874696989519390), KQU(18257884721466153847),\n\tKQU(16271867543011222991), KQU( 3905971519021791941),\n\tKQU(16814488397137052085), KQU( 1321197685504621613),\n\tKQU( 2870359191894002181), KQU(14317282970323395450),\n\tKQU(13663920845511074366), KQU( 2052463995796539594),\n\tKQU(14126345686431444337), KQU( 1727572121947022534),\n\tKQU(17793552254485594241), KQU( 6738857418849205750),\n\tKQU( 1282987123157442952), KQU(16655480021581159251),\n\tKQU( 6784587032080183866), KQU(14726758805359965162),\n\tKQU( 7577995933961987349), KQU(12539609320311114036),\n\tKQU(10789773033385439494), KQU( 8517001497411158227),\n\tKQU(10075543932136339710), KQU(14838152340938811081),\n\tKQU( 9560840631794044194), KQU(17445736541454117475),\n\tKQU(10633026464336393186), KQU(15705729708242246293),\n\tKQU( 1117517596891411098), KQU( 4305657943415886942),\n\tKQU( 4948856840533979263), KQU(16071681989041789593),\n\tKQU(13723031429272486527), KQU( 7639567622306509462),\n\tKQU(12670424537483090390), KQU( 9715223453097197134),\n\tKQU( 5457173389992686394), KQU(  289857129276135145),\n\tKQU(17048610270521972512), KQU(  692768013309835485),\n\tKQU(14823232360546632057), KQU(18218002361317895936),\n\tKQU( 3281724260212650204), KQU(16453957266549513795),\n\tKQU( 8592711109774511881), KQU(  929825123473369579),\n\tKQU(15966784769764367791), KQU( 9627344291450607588),\n\tKQU(10849555504977813287), KQU( 9234566913936339275),\n\tKQU( 6413807690366911210), KQU(10862389016184219267),\n\tKQU(13842504799335374048), KQU( 1531994113376881174),\n\tKQU( 2081314867544364459), KQU(16430628791616959932),\n\tKQU( 8314714038654394368), KQU( 9155473892098431813),\n\tKQU(12577843786670475704), KQU( 4399161106452401017),\n\tKQU( 1668083091682623186), KQU( 1741383777203714216),\n\tKQU( 2162597285417794374), KQU(15841980159165218736),\n\tKQU( 1971354603551467079), KQU( 1206714764913205968),\n\tKQU( 4790860439591272330), KQU(14699375615594055799),\n\tKQU( 8374423871657449988), KQU(10950685736472937738),\n\tKQU(  697344331343267176), KQU(10084998763118059810),\n\tKQU(12897369539795983124), KQU(12351260292144383605),\n\tKQU( 1268810970176811234), KQU( 7406287800414582768),\n\tKQU(  516169557043807831), KQU( 5077568278710520380),\n\tKQU( 3828791738309039304), KQU( 7721974069946943610),\n\tKQU( 3534670260981096460), KQU( 4865792189600584891),\n\tKQU(16892578493734337298), KQU( 9161499464278042590),\n\tKQU(11976149624067055931), KQU(13219479887277343990),\n\tKQU(14161556738111500680), KQU(14670715255011223056),\n\tKQU( 4671205678403576558), KQU(12633022931454259781),\n\tKQU(14821376219869187646), KQU(  751181776484317028),\n\tKQU( 2192211308839047070), KQU(11787306362361245189),\n\tKQU(10672375120744095707), KQU( 4601972328345244467),\n\tKQU(15457217788831125879), KQU( 8464345256775460809),\n\tKQU(10191938789487159478), KQU( 6184348739615197613),\n\tKQU(11425436778806882100), KQU( 2739227089124319793),\n\tKQU(  461464518456000551), KQU( 4689850170029177442),\n\tKQU( 6120307814374078625), KQU(11153579230681708671),\n\tKQU( 7891721473905347926), KQU(10281646937824872400),\n\tKQU( 3026099648191332248), KQU( 8666750296953273818),\n\tKQU(14978499698844363232), KQU(13303395102890132065),\n\tKQU( 8182358205292864080), KQU(10560547713972971291),\n\tKQU(11981635489418959093), KQU( 3134621354935288409),\n\tKQU(11580681977404383968), KQU(14205530317404088650),\n\tKQU( 5997789011854923157), KQU(13659151593432238041),\n\tKQU(11664332114338865086), KQU( 7490351383220929386),\n\tKQU( 7189290499881530378), KQU(15039262734271020220),\n\tKQU( 2057217285976980055), KQU(  555570804905355739),\n\tKQU(11235311968348555110), KQU(13824557146269603217),\n\tKQU(16906788840653099693), KQU( 7222878245455661677),\n\tKQU( 5245139444332423756), KQU( 4723748462805674292),\n\tKQU(12216509815698568612), KQU(17402362976648951187),\n\tKQU(17389614836810366768), KQU( 4880936484146667711),\n\tKQU( 9085007839292639880), KQU(13837353458498535449),\n\tKQU(11914419854360366677), KQU(16595890135313864103),\n\tKQU( 6313969847197627222), KQU(18296909792163910431),\n\tKQU(10041780113382084042), KQU( 2499478551172884794),\n\tKQU(11057894246241189489), KQU( 9742243032389068555),\n\tKQU(12838934582673196228), KQU(13437023235248490367),\n\tKQU(13372420669446163240), KQU( 6752564244716909224),\n\tKQU( 7157333073400313737), KQU(12230281516370654308),\n\tKQU( 1182884552219419117), KQU( 2955125381312499218),\n\tKQU(10308827097079443249), KQU( 1337648572986534958),\n\tKQU(16378788590020343939), KQU(  108619126514420935),\n\tKQU( 3990981009621629188), KQU( 5460953070230946410),\n\tKQU( 9703328329366531883), KQU(13166631489188077236),\n\tKQU( 1104768831213675170), KQU( 3447930458553877908),\n\tKQU( 8067172487769945676), KQU( 5445802098190775347),\n\tKQU( 3244840981648973873), KQU(17314668322981950060),\n\tKQU( 5006812527827763807), KQU(18158695070225526260),\n\tKQU( 2824536478852417853), KQU(13974775809127519886),\n\tKQU( 9814362769074067392), KQU(17276205156374862128),\n\tKQU(11361680725379306967), KQU( 3422581970382012542),\n\tKQU(11003189603753241266), KQU(11194292945277862261),\n\tKQU( 6839623313908521348), KQU(11935326462707324634),\n\tKQU( 1611456788685878444), KQU(13112620989475558907),\n\tKQU(  517659108904450427), KQU(13558114318574407624),\n\tKQU(15699089742731633077), KQU( 4988979278862685458),\n\tKQU( 8111373583056521297), KQU( 3891258746615399627),\n\tKQU( 8137298251469718086), KQU(12748663295624701649),\n\tKQU( 4389835683495292062), KQU( 5775217872128831729),\n\tKQU( 9462091896405534927), KQU( 8498124108820263989),\n\tKQU( 8059131278842839525), KQU(10503167994254090892),\n\tKQU(11613153541070396656), KQU(18069248738504647790),\n\tKQU(  570657419109768508), KQU( 3950574167771159665),\n\tKQU( 5514655599604313077), KQU( 2908460854428484165),\n\tKQU(10777722615935663114), KQU(12007363304839279486),\n\tKQU( 9800646187569484767), KQU( 8795423564889864287),\n\tKQU(14257396680131028419), KQU( 6405465117315096498),\n\tKQU( 7939411072208774878), KQU(17577572378528990006),\n\tKQU(14785873806715994850), KQU(16770572680854747390),\n\tKQU(18127549474419396481), KQU(11637013449455757750),\n\tKQU(14371851933996761086), KQU( 3601181063650110280),\n\tKQU( 4126442845019316144), KQU(10198287239244320669),\n\tKQU(18000169628555379659), KQU(18392482400739978269),\n\tKQU( 6219919037686919957), KQU( 3610085377719446052),\n\tKQU( 2513925039981776336), KQU(16679413537926716955),\n\tKQU(12903302131714909434), KQU( 5581145789762985009),\n\tKQU(12325955044293303233), KQU(17216111180742141204),\n\tKQU( 6321919595276545740), KQU( 3507521147216174501),\n\tKQU( 9659194593319481840), KQU(11473976005975358326),\n\tKQU(14742730101435987026), KQU(  492845897709954780),\n\tKQU(16976371186162599676), KQU(17712703422837648655),\n\tKQU( 9881254778587061697), KQU( 8413223156302299551),\n\tKQU( 1563841828254089168), KQU( 9996032758786671975),\n\tKQU(  138877700583772667), KQU(13003043368574995989),\n\tKQU( 4390573668650456587), KQU( 8610287390568126755),\n\tKQU(15126904974266642199), KQU( 6703637238986057662),\n\tKQU( 2873075592956810157), KQU( 6035080933946049418),\n\tKQU(13382846581202353014), KQU( 7303971031814642463),\n\tKQU(18418024405307444267), KQU( 5847096731675404647),\n\tKQU( 4035880699639842500), KQU(11525348625112218478),\n\tKQU( 3041162365459574102), KQU( 2604734487727986558),\n\tKQU(15526341771636983145), KQU(14556052310697370254),\n\tKQU(12997787077930808155), KQU( 9601806501755554499),\n\tKQU(11349677952521423389), KQU(14956777807644899350),\n\tKQU(16559736957742852721), KQU(12360828274778140726),\n\tKQU( 6685373272009662513), KQU(16932258748055324130),\n\tKQU(15918051131954158508), KQU( 1692312913140790144),\n\tKQU(  546653826801637367), KQU( 5341587076045986652),\n\tKQU(14975057236342585662), KQU(12374976357340622412),\n\tKQU(10328833995181940552), KQU(12831807101710443149),\n\tKQU(10548514914382545716), KQU( 2217806727199715993),\n\tKQU(12627067369242845138), KQU( 4598965364035438158),\n\tKQU(  150923352751318171), KQU(14274109544442257283),\n\tKQU( 4696661475093863031), KQU( 1505764114384654516),\n\tKQU(10699185831891495147), KQU( 2392353847713620519),\n\tKQU( 3652870166711788383), KQU( 8640653276221911108),\n\tKQU( 3894077592275889704), KQU( 4918592872135964845),\n\tKQU(16379121273281400789), KQU(12058465483591683656),\n\tKQU(11250106829302924945), KQU( 1147537556296983005),\n\tKQU( 6376342756004613268), KQU(14967128191709280506),\n\tKQU(18007449949790627628), KQU( 9497178279316537841),\n\tKQU( 7920174844809394893), KQU(10037752595255719907),\n\tKQU(15875342784985217697), KQU(15311615921712850696),\n\tKQU( 9552902652110992950), KQU(14054979450099721140),\n\tKQU( 5998709773566417349), KQU(18027910339276320187),\n\tKQU( 8223099053868585554), KQU( 7842270354824999767),\n\tKQU( 4896315688770080292), KQU(12969320296569787895),\n\tKQU( 2674321489185759961), KQU( 4053615936864718439),\n\tKQU(11349775270588617578), KQU( 4743019256284553975),\n\tKQU( 5602100217469723769), KQU(14398995691411527813),\n\tKQU( 7412170493796825470), KQU(  836262406131744846),\n\tKQU( 8231086633845153022), KQU( 5161377920438552287),\n\tKQU( 8828731196169924949), KQU(16211142246465502680),\n\tKQU( 3307990879253687818), KQU( 5193405406899782022),\n\tKQU( 8510842117467566693), KQU( 6070955181022405365),\n\tKQU(14482950231361409799), KQU(12585159371331138077),\n\tKQU( 3511537678933588148), KQU( 2041849474531116417),\n\tKQU(10944936685095345792), KQU(18303116923079107729),\n\tKQU( 2720566371239725320), KQU( 4958672473562397622),\n\tKQU( 3032326668253243412), KQU(13689418691726908338),\n\tKQU( 1895205511728843996), KQU( 8146303515271990527),\n\tKQU(16507343500056113480), KQU(  473996939105902919),\n\tKQU( 9897686885246881481), KQU(14606433762712790575),\n\tKQU( 6732796251605566368), KQU( 1399778120855368916),\n\tKQU(  935023885182833777), KQU(16066282816186753477),\n\tKQU( 7291270991820612055), KQU(17530230393129853844),\n\tKQU(10223493623477451366), KQU(15841725630495676683),\n\tKQU(17379567246435515824), KQU( 8588251429375561971),\n\tKQU(18339511210887206423), KQU(17349587430725976100),\n\tKQU(12244876521394838088), KQU( 6382187714147161259),\n\tKQU(12335807181848950831), KQU(16948885622305460665),\n\tKQU(13755097796371520506), KQU(14806740373324947801),\n\tKQU( 4828699633859287703), KQU( 8209879281452301604),\n\tKQU(12435716669553736437), KQU(13970976859588452131),\n\tKQU( 6233960842566773148), KQU(12507096267900505759),\n\tKQU( 1198713114381279421), KQU(14989862731124149015),\n\tKQU(15932189508707978949), KQU( 2526406641432708722),\n\tKQU(   29187427817271982), KQU( 1499802773054556353),\n\tKQU(10816638187021897173), KQU( 5436139270839738132),\n\tKQU( 6659882287036010082), KQU( 2154048955317173697),\n\tKQU(10887317019333757642), KQU(16281091802634424955),\n\tKQU(10754549879915384901), KQU(10760611745769249815),\n\tKQU( 2161505946972504002), KQU( 5243132808986265107),\n\tKQU(10129852179873415416), KQU(  710339480008649081),\n\tKQU( 7802129453068808528), KQU(17967213567178907213),\n\tKQU(15730859124668605599), KQU(13058356168962376502),\n\tKQU( 3701224985413645909), KQU(14464065869149109264),\n\tKQU( 9959272418844311646), KQU(10157426099515958752),\n\tKQU(14013736814538268528), KQU(17797456992065653951),\n\tKQU(17418878140257344806), KQU(15457429073540561521),\n\tKQU( 2184426881360949378), KQU( 2062193041154712416),\n\tKQU( 8553463347406931661), KQU( 4913057625202871854),\n\tKQU( 2668943682126618425), KQU(17064444737891172288),\n\tKQU( 4997115903913298637), KQU(12019402608892327416),\n\tKQU(17603584559765897352), KQU(11367529582073647975),\n\tKQU( 8211476043518436050), KQU( 8676849804070323674),\n\tKQU(18431829230394475730), KQU(10490177861361247904),\n\tKQU( 9508720602025651349), KQU( 7409627448555722700),\n\tKQU( 5804047018862729008), KQU(11943858176893142594),\n\tKQU(11908095418933847092), KQU( 5415449345715887652),\n\tKQU( 1554022699166156407), KQU( 9073322106406017161),\n\tKQU( 7080630967969047082), KQU(18049736940860732943),\n\tKQU(12748714242594196794), KQU( 1226992415735156741),\n\tKQU(17900981019609531193), KQU(11720739744008710999),\n\tKQU( 3006400683394775434), KQU(11347974011751996028),\n\tKQU( 3316999628257954608), KQU( 8384484563557639101),\n\tKQU(18117794685961729767), KQU( 1900145025596618194),\n\tKQU(17459527840632892676), KQU( 5634784101865710994),\n\tKQU( 7918619300292897158), KQU( 3146577625026301350),\n\tKQU( 9955212856499068767), KQU( 1873995843681746975),\n\tKQU( 1561487759967972194), KQU( 8322718804375878474),\n\tKQU(11300284215327028366), KQU( 4667391032508998982),\n\tKQU( 9820104494306625580), KQU(17922397968599970610),\n\tKQU( 1784690461886786712), KQU(14940365084341346821),\n\tKQU( 5348719575594186181), KQU(10720419084507855261),\n\tKQU(14210394354145143274), KQU( 2426468692164000131),\n\tKQU(16271062114607059202), KQU(14851904092357070247),\n\tKQU( 6524493015693121897), KQU( 9825473835127138531),\n\tKQU(14222500616268569578), KQU(15521484052007487468),\n\tKQU(14462579404124614699), KQU(11012375590820665520),\n\tKQU(11625327350536084927), KQU(14452017765243785417),\n\tKQU( 9989342263518766305), KQU( 3640105471101803790),\n\tKQU( 4749866455897513242), KQU(13963064946736312044),\n\tKQU(10007416591973223791), KQU(18314132234717431115),\n\tKQU( 3286596588617483450), KQU( 7726163455370818765),\n\tKQU( 7575454721115379328), KQU( 5308331576437663422),\n\tKQU(18288821894903530934), KQU( 8028405805410554106),\n\tKQU(15744019832103296628), KQU(  149765559630932100),\n\tKQU( 6137705557200071977), KQU(14513416315434803615),\n\tKQU(11665702820128984473), KQU(  218926670505601386),\n\tKQU( 6868675028717769519), KQU(15282016569441512302),\n\tKQU( 5707000497782960236), KQU( 6671120586555079567),\n\tKQU( 2194098052618985448), KQU(16849577895477330978),\n\tKQU(12957148471017466283), KQU( 1997805535404859393),\n\tKQU( 1180721060263860490), KQU(13206391310193756958),\n\tKQU(12980208674461861797), KQU( 3825967775058875366),\n\tKQU(17543433670782042631), KQU( 1518339070120322730),\n\tKQU(16344584340890991669), KQU( 2611327165318529819),\n\tKQU(11265022723283422529), KQU( 4001552800373196817),\n\tKQU(14509595890079346161), KQU( 3528717165416234562),\n\tKQU(18153222571501914072), KQU( 9387182977209744425),\n\tKQU(10064342315985580021), KQU(11373678413215253977),\n\tKQU( 2308457853228798099), KQU( 9729042942839545302),\n\tKQU( 7833785471140127746), KQU( 6351049900319844436),\n\tKQU(14454610627133496067), KQU(12533175683634819111),\n\tKQU(15570163926716513029), KQU(13356980519185762498)\n};\n\nTEST_BEGIN(test_gen_rand_32)\n{\n\tuint32_t array32[BLOCK_SIZE] JEMALLOC_ATTR(aligned(16));\n\tuint32_t array32_2[BLOCK_SIZE] JEMALLOC_ATTR(aligned(16));\n\tint i;\n\tuint32_t r32;\n\tsfmt_t *ctx;\n\n\tassert_d_le(get_min_array_size32(), BLOCK_SIZE,\n\t    \"Array size too small\");\n\tctx = init_gen_rand(1234);\n\tfill_array32(ctx, array32, BLOCK_SIZE);\n\tfill_array32(ctx, array32_2, BLOCK_SIZE);\n\tfini_gen_rand(ctx);\n\n\tctx = init_gen_rand(1234);\n\tfor (i = 0; i < BLOCK_SIZE; i++) {\n\t\tif (i < COUNT_1) {\n\t\t\tassert_u32_eq(array32[i], init_gen_rand_32_expected[i],\n\t\t\t    \"Output mismatch for i=%d\", i);\n\t\t}\n\t\tr32 = gen_rand32(ctx);\n\t\tassert_u32_eq(r32, array32[i],\n\t\t    \"Mismatch at array32[%d]=%x, gen=%x\", i, array32[i], r32);\n\t}\n\tfor (i = 0; i < COUNT_2; i++) {\n\t\tr32 = gen_rand32(ctx);\n\t\tassert_u32_eq(r32, array32_2[i],\n\t\t    \"Mismatch at array32_2[%d]=%x, gen=%x\", i, array32_2[i],\n\t\t    r32);\n\t}\n\tfini_gen_rand(ctx);\n}\nTEST_END\n\nTEST_BEGIN(test_by_array_32)\n{\n\tuint32_t array32[BLOCK_SIZE] JEMALLOC_ATTR(aligned(16));\n\tuint32_t array32_2[BLOCK_SIZE] JEMALLOC_ATTR(aligned(16));\n\tint i;\n\tuint32_t ini[4] = {0x1234, 0x5678, 0x9abc, 0xdef0};\n\tuint32_t r32;\n\tsfmt_t *ctx;\n\n\tassert_d_le(get_min_array_size32(), BLOCK_SIZE,\n\t    \"Array size too small\");\n\tctx = init_by_array(ini, 4);\n\tfill_array32(ctx, array32, BLOCK_SIZE);\n\tfill_array32(ctx, array32_2, BLOCK_SIZE);\n\tfini_gen_rand(ctx);\n\n\tctx = init_by_array(ini, 4);\n\tfor (i = 0; i < BLOCK_SIZE; i++) {\n\t\tif (i < COUNT_1) {\n\t\t\tassert_u32_eq(array32[i], init_by_array_32_expected[i],\n\t\t\t    \"Output mismatch for i=%d\", i);\n\t\t}\n\t\tr32 = gen_rand32(ctx);\n\t\tassert_u32_eq(r32, array32[i],\n\t\t    \"Mismatch at array32[%d]=%x, gen=%x\", i, array32[i], r32);\n\t}\n\tfor (i = 0; i < COUNT_2; i++) {\n\t\tr32 = gen_rand32(ctx);\n\t\tassert_u32_eq(r32, array32_2[i],\n\t\t    \"Mismatch at array32_2[%d]=%x, gen=%x\", i, array32_2[i],\n\t\t    r32);\n\t}\n\tfini_gen_rand(ctx);\n}\nTEST_END\n\nTEST_BEGIN(test_gen_rand_64)\n{\n\tuint64_t array64[BLOCK_SIZE64] JEMALLOC_ATTR(aligned(16));\n\tuint64_t array64_2[BLOCK_SIZE64] JEMALLOC_ATTR(aligned(16));\n\tint i;\n\tuint64_t r;\n\tsfmt_t *ctx;\n\n\tassert_d_le(get_min_array_size64(), BLOCK_SIZE64,\n\t    \"Array size too small\");\n\tctx = init_gen_rand(4321);\n\tfill_array64(ctx, array64, BLOCK_SIZE64);\n\tfill_array64(ctx, array64_2, BLOCK_SIZE64);\n\tfini_gen_rand(ctx);\n\n\tctx = init_gen_rand(4321);\n\tfor (i = 0; i < BLOCK_SIZE64; i++) {\n\t\tif (i < COUNT_1) {\n\t\t\tassert_u64_eq(array64[i], init_gen_rand_64_expected[i],\n\t\t\t    \"Output mismatch for i=%d\", i);\n\t\t}\n\t\tr = gen_rand64(ctx);\n\t\tassert_u64_eq(r, array64[i],\n\t\t    \"Mismatch at array64[%d]=%\"FMTx64\", gen=%\"FMTx64, i,\n\t\t    array64[i], r);\n\t}\n\tfor (i = 0; i < COUNT_2; i++) {\n\t\tr = gen_rand64(ctx);\n\t\tassert_u64_eq(r, array64_2[i],\n\t\t    \"Mismatch at array64_2[%d]=%\"FMTx64\" gen=%\"FMTx64\"\", i,\n\t\t    array64_2[i], r);\n\t}\n\tfini_gen_rand(ctx);\n}\nTEST_END\n\nTEST_BEGIN(test_by_array_64)\n{\n\tuint64_t array64[BLOCK_SIZE64] JEMALLOC_ATTR(aligned(16));\n\tuint64_t array64_2[BLOCK_SIZE64] JEMALLOC_ATTR(aligned(16));\n\tint i;\n\tuint64_t r;\n\tuint32_t ini[] = {5, 4, 3, 2, 1};\n\tsfmt_t *ctx;\n\n\tassert_d_le(get_min_array_size64(), BLOCK_SIZE64,\n\t    \"Array size too small\");\n\tctx = init_by_array(ini, 5);\n\tfill_array64(ctx, array64, BLOCK_SIZE64);\n\tfill_array64(ctx, array64_2, BLOCK_SIZE64);\n\tfini_gen_rand(ctx);\n\n\tctx = init_by_array(ini, 5);\n\tfor (i = 0; i < BLOCK_SIZE64; i++) {\n\t\tif (i < COUNT_1) {\n\t\t\tassert_u64_eq(array64[i], init_by_array_64_expected[i],\n\t\t\t    \"Output mismatch for i=%d\", i);\n\t\t}\n\t\tr = gen_rand64(ctx);\n\t\tassert_u64_eq(r, array64[i],\n\t\t    \"Mismatch at array64[%d]=%\"FMTx64\" gen=%\"FMTx64, i,\n\t\t    array64[i], r);\n\t}\n\tfor (i = 0; i < COUNT_2; i++) {\n\t\tr = gen_rand64(ctx);\n\t\tassert_u64_eq(r, array64_2[i],\n\t\t    \"Mismatch at array64_2[%d]=%\"FMTx64\" gen=%\"FMTx64, i,\n\t\t    array64_2[i], r);\n\t}\n\tfini_gen_rand(ctx);\n}\nTEST_END\n\nint\nmain(void)\n{\n\n\treturn (test(\n\t    test_gen_rand_32,\n\t    test_by_array_32,\n\t    test_gen_rand_64,\n\t    test_by_array_64));\n}\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.8/deps/jemalloc/test/unit/atomic.c",
    "content": "#include \"test/jemalloc_test.h\"\n\n#define\tTEST_STRUCT(p, t)\t\t\t\t\t\t\\\nstruct p##_test_s {\t\t\t\t\t\t\t\\\n\tt\taccum0;\t\t\t\t\t\t\t\\\n\tt\tx;\t\t\t\t\t\t\t\\\n\tt\ts;\t\t\t\t\t\t\t\\\n};\t\t\t\t\t\t\t\t\t\\\ntypedef struct p##_test_s p##_test_t;\n\n#define\tTEST_BODY(p, t, tc, ta, FMT) do {\t\t\t\t\\\n\tconst p##_test_t tests[] = {\t\t\t\t\t\\\n\t\t{(t)-1, (t)-1, (t)-2},\t\t\t\t\t\\\n\t\t{(t)-1, (t) 0, (t)-2},\t\t\t\t\t\\\n\t\t{(t)-1, (t) 1, (t)-2},\t\t\t\t\t\\\n\t\t\t\t\t\t\t\t\t\\\n\t\t{(t) 0, (t)-1, (t)-2},\t\t\t\t\t\\\n\t\t{(t) 0, (t) 0, (t)-2},\t\t\t\t\t\\\n\t\t{(t) 0, (t) 1, (t)-2},\t\t\t\t\t\\\n\t\t\t\t\t\t\t\t\t\\\n\t\t{(t) 1, (t)-1, (t)-2},\t\t\t\t\t\\\n\t\t{(t) 1, (t) 0, (t)-2},\t\t\t\t\t\\\n\t\t{(t) 1, (t) 1, (t)-2},\t\t\t\t\t\\\n\t\t\t\t\t\t\t\t\t\\\n\t\t{(t)0, (t)-(1 << 22), (t)-2},\t\t\t\t\\\n\t\t{(t)0, (t)(1 << 22), (t)-2},\t\t\t\t\\\n\t\t{(t)(1 << 22), (t)-(1 << 22), (t)-2},\t\t\t\\\n\t\t{(t)(1 << 22), (t)(1 << 22), (t)-2}\t\t\t\\\n\t};\t\t\t\t\t\t\t\t\\\n\tunsigned i;\t\t\t\t\t\t\t\\\n\t\t\t\t\t\t\t\t\t\\\n\tfor (i = 0; i < sizeof(tests)/sizeof(p##_test_t); i++) {\t\\\n\t\tbool err;\t\t\t\t\t\t\\\n\t\tt accum = tests[i].accum0;\t\t\t\t\\\n\t\tassert_##ta##_eq(atomic_read_##p(&accum),\t\t\\\n\t\t    tests[i].accum0,\t\t\t\t\t\\\n\t\t    \"Erroneous read, i=%u\", i);\t\t\t\t\\\n\t\t\t\t\t\t\t\t\t\\\n\t\tassert_##ta##_eq(atomic_add_##p(&accum, tests[i].x),\t\\\n\t\t    (t)((tc)tests[i].accum0 + (tc)tests[i].x),\t\t\\\n\t\t    \"i=%u, accum=%\"FMT\", x=%\"FMT,\t\t\t\\\n\t\t    i, tests[i].accum0, tests[i].x);\t\t\t\\\n\t\tassert_##ta##_eq(atomic_read_##p(&accum), accum,\t\\\n\t\t    \"Erroneous add, i=%u\", i);\t\t\t\t\\\n\t\t\t\t\t\t\t\t\t\\\n\t\taccum = tests[i].accum0;\t\t\t\t\\\n\t\tassert_##ta##_eq(atomic_sub_##p(&accum, tests[i].x),\t\\\n\t\t    (t)((tc)tests[i].accum0 - (tc)tests[i].x),\t\t\\\n\t\t    \"i=%u, accum=%\"FMT\", x=%\"FMT,\t\t\t\\\n\t\t    i, tests[i].accum0, tests[i].x);\t\t\t\\\n\t\tassert_##ta##_eq(atomic_read_##p(&accum), accum,\t\\\n\t\t    \"Erroneous sub, i=%u\", i);\t\t\t\t\\\n\t\t\t\t\t\t\t\t\t\\\n\t\taccum = tests[i].accum0;\t\t\t\t\\\n\t\terr = atomic_cas_##p(&accum, tests[i].x, tests[i].s);\t\\\n\t\tassert_b_eq(err, tests[i].accum0 != tests[i].x,\t\t\\\n\t\t    \"Erroneous cas success/failure result\");\t\t\\\n\t\tassert_##ta##_eq(accum, err ? tests[i].accum0 :\t\t\\\n\t\t    tests[i].s, \"Erroneous cas effect, i=%u\", i);\t\\\n\t\t\t\t\t\t\t\t\t\\\n\t\taccum = tests[i].accum0;\t\t\t\t\\\n\t\tatomic_write_##p(&accum, tests[i].s);\t\t\t\\\n\t\tassert_##ta##_eq(accum, tests[i].s,\t\t\t\\\n\t\t    \"Erroneous write, i=%u\", i);\t\t\t\\\n\t}\t\t\t\t\t\t\t\t\\\n} while (0)\n\nTEST_STRUCT(uint64, uint64_t)\nTEST_BEGIN(test_atomic_uint64)\n{\n\n#if !(LG_SIZEOF_PTR == 3 || LG_SIZEOF_INT == 3)\n\ttest_skip(\"64-bit atomic operations not supported\");\n#else\n\tTEST_BODY(uint64, uint64_t, uint64_t, u64, FMTx64);\n#endif\n}\nTEST_END\n\nTEST_STRUCT(uint32, uint32_t)\nTEST_BEGIN(test_atomic_uint32)\n{\n\n\tTEST_BODY(uint32, uint32_t, uint32_t, u32, \"#\"FMTx32);\n}\nTEST_END\n\nTEST_STRUCT(p, void *)\nTEST_BEGIN(test_atomic_p)\n{\n\n\tTEST_BODY(p, void *, uintptr_t, ptr, \"p\");\n}\nTEST_END\n\nTEST_STRUCT(z, size_t)\nTEST_BEGIN(test_atomic_z)\n{\n\n\tTEST_BODY(z, size_t, size_t, zu, \"#zx\");\n}\nTEST_END\n\nTEST_STRUCT(u, unsigned)\nTEST_BEGIN(test_atomic_u)\n{\n\n\tTEST_BODY(u, unsigned, unsigned, u, \"#x\");\n}\nTEST_END\n\nint\nmain(void)\n{\n\n\treturn (test(\n\t    test_atomic_uint64,\n\t    test_atomic_uint32,\n\t    test_atomic_p,\n\t    test_atomic_z,\n\t    test_atomic_u));\n}\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.8/deps/jemalloc/test/unit/bitmap.c",
    "content": "#include \"test/jemalloc_test.h\"\n\nTEST_BEGIN(test_bitmap_size)\n{\n\tsize_t i, prev_size;\n\n\tprev_size = 0;\n\tfor (i = 1; i <= BITMAP_MAXBITS; i++) {\n\t\tsize_t size = bitmap_size(i);\n\t\tassert_true(size >= prev_size,\n\t\t    \"Bitmap size is smaller than expected\");\n\t\tprev_size = size;\n\t}\n}\nTEST_END\n\nTEST_BEGIN(test_bitmap_init)\n{\n\tsize_t i;\n\n\tfor (i = 1; i <= BITMAP_MAXBITS; i++) {\n\t\tbitmap_info_t binfo;\n\t\tbitmap_info_init(&binfo, i);\n\t\t{\n\t\t\tsize_t j;\n\t\t\tbitmap_t *bitmap = (bitmap_t *)malloc(sizeof(bitmap_t) *\n\t\t\t\tbitmap_info_ngroups(&binfo));\n\t\t\tbitmap_init(bitmap, &binfo);\n\n\t\t\tfor (j = 0; j < i; j++) {\n\t\t\t\tassert_false(bitmap_get(bitmap, &binfo, j),\n\t\t\t\t    \"Bit should be unset\");\n\t\t\t}\n\t\t\tfree(bitmap);\n\t\t}\n\t}\n}\nTEST_END\n\nTEST_BEGIN(test_bitmap_set)\n{\n\tsize_t i;\n\n\tfor (i = 1; i <= BITMAP_MAXBITS; i++) {\n\t\tbitmap_info_t binfo;\n\t\tbitmap_info_init(&binfo, i);\n\t\t{\n\t\t\tsize_t j;\n\t\t\tbitmap_t *bitmap = (bitmap_t *)malloc(sizeof(bitmap_t) *\n\t\t\t\tbitmap_info_ngroups(&binfo));\n\t\t\tbitmap_init(bitmap, &binfo);\n\n\t\t\tfor (j = 0; j < i; j++)\n\t\t\t\tbitmap_set(bitmap, &binfo, j);\n\t\t\tassert_true(bitmap_full(bitmap, &binfo),\n\t\t\t    \"All bits should be set\");\n\t\t\tfree(bitmap);\n\t\t}\n\t}\n}\nTEST_END\n\nTEST_BEGIN(test_bitmap_unset)\n{\n\tsize_t i;\n\n\tfor (i = 1; i <= BITMAP_MAXBITS; i++) {\n\t\tbitmap_info_t binfo;\n\t\tbitmap_info_init(&binfo, i);\n\t\t{\n\t\t\tsize_t j;\n\t\t\tbitmap_t *bitmap = (bitmap_t *)malloc(sizeof(bitmap_t) *\n\t\t\t\tbitmap_info_ngroups(&binfo));\n\t\t\tbitmap_init(bitmap, &binfo);\n\n\t\t\tfor (j = 0; j < i; j++)\n\t\t\t\tbitmap_set(bitmap, &binfo, j);\n\t\t\tassert_true(bitmap_full(bitmap, &binfo),\n\t\t\t    \"All bits should be set\");\n\t\t\tfor (j = 0; j < i; j++)\n\t\t\t\tbitmap_unset(bitmap, &binfo, j);\n\t\t\tfor (j = 0; j < i; j++)\n\t\t\t\tbitmap_set(bitmap, &binfo, j);\n\t\t\tassert_true(bitmap_full(bitmap, &binfo),\n\t\t\t    \"All bits should be set\");\n\t\t\tfree(bitmap);\n\t\t}\n\t}\n}\nTEST_END\n\nTEST_BEGIN(test_bitmap_sfu)\n{\n\tsize_t i;\n\n\tfor (i = 1; i <= BITMAP_MAXBITS; i++) {\n\t\tbitmap_info_t binfo;\n\t\tbitmap_info_init(&binfo, i);\n\t\t{\n\t\t\tssize_t j;\n\t\t\tbitmap_t *bitmap = (bitmap_t *)malloc(sizeof(bitmap_t) *\n\t\t\t\tbitmap_info_ngroups(&binfo));\n\t\t\tbitmap_init(bitmap, &binfo);\n\n\t\t\t/* Iteratively set bits starting at the beginning. */\n\t\t\tfor (j = 0; j < i; j++) {\n\t\t\t\tassert_zd_eq(bitmap_sfu(bitmap, &binfo), j,\n\t\t\t\t    \"First unset bit should be just after \"\n\t\t\t\t    \"previous first unset bit\");\n\t\t\t}\n\t\t\tassert_true(bitmap_full(bitmap, &binfo),\n\t\t\t    \"All bits should be set\");\n\n\t\t\t/*\n\t\t\t * Iteratively unset bits starting at the end, and\n\t\t\t * verify that bitmap_sfu() reaches the unset bits.\n\t\t\t */\n\t\t\tfor (j = i - 1; j >= 0; j--) {\n\t\t\t\tbitmap_unset(bitmap, &binfo, j);\n\t\t\t\tassert_zd_eq(bitmap_sfu(bitmap, &binfo), j,\n\t\t\t\t    \"First unset bit should the bit previously \"\n\t\t\t\t    \"unset\");\n\t\t\t\tbitmap_unset(bitmap, &binfo, j);\n\t\t\t}\n\t\t\tassert_false(bitmap_get(bitmap, &binfo, 0),\n\t\t\t    \"Bit should be unset\");\n\n\t\t\t/*\n\t\t\t * Iteratively set bits starting at the beginning, and\n\t\t\t * verify that bitmap_sfu() looks past them.\n\t\t\t */\n\t\t\tfor (j = 1; j < i; j++) {\n\t\t\t\tbitmap_set(bitmap, &binfo, j - 1);\n\t\t\t\tassert_zd_eq(bitmap_sfu(bitmap, &binfo), j,\n\t\t\t\t    \"First unset bit should be just after the \"\n\t\t\t\t    \"bit previously set\");\n\t\t\t\tbitmap_unset(bitmap, &binfo, j);\n\t\t\t}\n\t\t\tassert_zd_eq(bitmap_sfu(bitmap, &binfo), i - 1,\n\t\t\t    \"First unset bit should be the last bit\");\n\t\t\tassert_true(bitmap_full(bitmap, &binfo),\n\t\t\t    \"All bits should be set\");\n\t\t\tfree(bitmap);\n\t\t}\n\t}\n}\nTEST_END\n\nint\nmain(void)\n{\n\n\treturn (test(\n\t    test_bitmap_size,\n\t    test_bitmap_init,\n\t    test_bitmap_set,\n\t    test_bitmap_unset,\n\t    test_bitmap_sfu));\n}\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.8/deps/jemalloc/test/unit/ckh.c",
    "content": "#include \"test/jemalloc_test.h\"\n\nTEST_BEGIN(test_new_delete)\n{\n\ttsd_t *tsd;\n\tckh_t ckh;\n\n\ttsd = tsd_fetch();\n\n\tassert_false(ckh_new(tsd, &ckh, 2, ckh_string_hash, ckh_string_keycomp),\n\t    \"Unexpected ckh_new() error\");\n\tckh_delete(tsd, &ckh);\n\n\tassert_false(ckh_new(tsd, &ckh, 3, ckh_pointer_hash,\n\t    ckh_pointer_keycomp), \"Unexpected ckh_new() error\");\n\tckh_delete(tsd, &ckh);\n}\nTEST_END\n\nTEST_BEGIN(test_count_insert_search_remove)\n{\n\ttsd_t *tsd;\n\tckh_t ckh;\n\tconst char *strs[] = {\n\t    \"a string\",\n\t    \"A string\",\n\t    \"a string.\",\n\t    \"A string.\"\n\t};\n\tconst char *missing = \"A string not in the hash table.\";\n\tsize_t i;\n\n\ttsd = tsd_fetch();\n\n\tassert_false(ckh_new(tsd, &ckh, 2, ckh_string_hash, ckh_string_keycomp),\n\t    \"Unexpected ckh_new() error\");\n\tassert_zu_eq(ckh_count(&ckh), 0,\n\t    \"ckh_count() should return %zu, but it returned %zu\", ZU(0),\n\t    ckh_count(&ckh));\n\n\t/* Insert. */\n\tfor (i = 0; i < sizeof(strs)/sizeof(const char *); i++) {\n\t\tckh_insert(tsd, &ckh, strs[i], strs[i]);\n\t\tassert_zu_eq(ckh_count(&ckh), i+1,\n\t\t    \"ckh_count() should return %zu, but it returned %zu\", i+1,\n\t\t    ckh_count(&ckh));\n\t}\n\n\t/* Search. */\n\tfor (i = 0; i < sizeof(strs)/sizeof(const char *); i++) {\n\t\tunion {\n\t\t\tvoid *p;\n\t\t\tconst char *s;\n\t\t} k, v;\n\t\tvoid **kp, **vp;\n\t\tconst char *ks, *vs;\n\n\t\tkp = (i & 1) ? &k.p : NULL;\n\t\tvp = (i & 2) ? &v.p : NULL;\n\t\tk.p = NULL;\n\t\tv.p = NULL;\n\t\tassert_false(ckh_search(&ckh, strs[i], kp, vp),\n\t\t    \"Unexpected ckh_search() error\");\n\n\t\tks = (i & 1) ? strs[i] : (const char *)NULL;\n\t\tvs = (i & 2) ? strs[i] : (const char *)NULL;\n\t\tassert_ptr_eq((void *)ks, (void *)k.s, \"Key mismatch, i=%zu\",\n\t\t    i);\n\t\tassert_ptr_eq((void *)vs, (void *)v.s, \"Value mismatch, i=%zu\",\n\t\t    i);\n\t}\n\tassert_true(ckh_search(&ckh, missing, NULL, NULL),\n\t    \"Unexpected ckh_search() success\");\n\n\t/* Remove. */\n\tfor (i = 0; i < sizeof(strs)/sizeof(const char *); i++) {\n\t\tunion {\n\t\t\tvoid *p;\n\t\t\tconst char *s;\n\t\t} k, v;\n\t\tvoid **kp, **vp;\n\t\tconst char *ks, *vs;\n\n\t\tkp = (i & 1) ? &k.p : NULL;\n\t\tvp = (i & 2) ? &v.p : NULL;\n\t\tk.p = NULL;\n\t\tv.p = NULL;\n\t\tassert_false(ckh_remove(tsd, &ckh, strs[i], kp, vp),\n\t\t    \"Unexpected ckh_remove() error\");\n\n\t\tks = (i & 1) ? strs[i] : (const char *)NULL;\n\t\tvs = (i & 2) ? strs[i] : (const char *)NULL;\n\t\tassert_ptr_eq((void *)ks, (void *)k.s, \"Key mismatch, i=%zu\",\n\t\t    i);\n\t\tassert_ptr_eq((void *)vs, (void *)v.s, \"Value mismatch, i=%zu\",\n\t\t    i);\n\t\tassert_zu_eq(ckh_count(&ckh),\n\t\t    sizeof(strs)/sizeof(const char *) - i - 1,\n\t\t    \"ckh_count() should return %zu, but it returned %zu\",\n\t\t        sizeof(strs)/sizeof(const char *) - i - 1,\n\t\t    ckh_count(&ckh));\n\t}\n\n\tckh_delete(tsd, &ckh);\n}\nTEST_END\n\nTEST_BEGIN(test_insert_iter_remove)\n{\n#define\tNITEMS ZU(1000)\n\ttsd_t *tsd;\n\tckh_t ckh;\n\tvoid **p[NITEMS];\n\tvoid *q, *r;\n\tsize_t i;\n\n\ttsd = tsd_fetch();\n\n\tassert_false(ckh_new(tsd, &ckh, 2, ckh_pointer_hash,\n\t    ckh_pointer_keycomp), \"Unexpected ckh_new() error\");\n\n\tfor (i = 0; i < NITEMS; i++) {\n\t\tp[i] = mallocx(i+1, 0);\n\t\tassert_ptr_not_null(p[i], \"Unexpected mallocx() failure\");\n\t}\n\n\tfor (i = 0; i < NITEMS; i++) {\n\t\tsize_t j;\n\n\t\tfor (j = i; j < NITEMS; j++) {\n\t\t\tassert_false(ckh_insert(tsd, &ckh, p[j], p[j]),\n\t\t\t    \"Unexpected ckh_insert() failure\");\n\t\t\tassert_false(ckh_search(&ckh, p[j], &q, &r),\n\t\t\t    \"Unexpected ckh_search() failure\");\n\t\t\tassert_ptr_eq(p[j], q, \"Key pointer mismatch\");\n\t\t\tassert_ptr_eq(p[j], r, \"Value pointer mismatch\");\n\t\t}\n\n\t\tassert_zu_eq(ckh_count(&ckh), NITEMS,\n\t\t    \"ckh_count() should return %zu, but it returned %zu\",\n\t\t    NITEMS, ckh_count(&ckh));\n\n\t\tfor (j = i + 1; j < NITEMS; j++) {\n\t\t\tassert_false(ckh_search(&ckh, p[j], NULL, NULL),\n\t\t\t    \"Unexpected ckh_search() failure\");\n\t\t\tassert_false(ckh_remove(tsd, &ckh, p[j], &q, &r),\n\t\t\t    \"Unexpected ckh_remove() failure\");\n\t\t\tassert_ptr_eq(p[j], q, \"Key pointer mismatch\");\n\t\t\tassert_ptr_eq(p[j], r, \"Value pointer mismatch\");\n\t\t\tassert_true(ckh_search(&ckh, p[j], NULL, NULL),\n\t\t\t    \"Unexpected ckh_search() success\");\n\t\t\tassert_true(ckh_remove(tsd, &ckh, p[j], &q, &r),\n\t\t\t    \"Unexpected ckh_remove() success\");\n\t\t}\n\n\t\t{\n\t\t\tbool seen[NITEMS];\n\t\t\tsize_t tabind;\n\n\t\t\tmemset(seen, 0, sizeof(seen));\n\n\t\t\tfor (tabind = 0; !ckh_iter(&ckh, &tabind, &q, &r);) {\n\t\t\t\tsize_t k;\n\n\t\t\t\tassert_ptr_eq(q, r, \"Key and val not equal\");\n\n\t\t\t\tfor (k = 0; k < NITEMS; k++) {\n\t\t\t\t\tif (p[k] == q) {\n\t\t\t\t\t\tassert_false(seen[k],\n\t\t\t\t\t\t    \"Item %zu already seen\", k);\n\t\t\t\t\t\tseen[k] = true;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tfor (j = 0; j < i + 1; j++)\n\t\t\t\tassert_true(seen[j], \"Item %zu not seen\", j);\n\t\t\tfor (; j < NITEMS; j++)\n\t\t\t\tassert_false(seen[j], \"Item %zu seen\", j);\n\t\t}\n\t}\n\n\tfor (i = 0; i < NITEMS; i++) {\n\t\tassert_false(ckh_search(&ckh, p[i], NULL, NULL),\n\t\t    \"Unexpected ckh_search() failure\");\n\t\tassert_false(ckh_remove(tsd, &ckh, p[i], &q, &r),\n\t\t    \"Unexpected ckh_remove() failure\");\n\t\tassert_ptr_eq(p[i], q, \"Key pointer mismatch\");\n\t\tassert_ptr_eq(p[i], r, \"Value pointer mismatch\");\n\t\tassert_true(ckh_search(&ckh, p[i], NULL, NULL),\n\t\t    \"Unexpected ckh_search() success\");\n\t\tassert_true(ckh_remove(tsd, &ckh, p[i], &q, &r),\n\t\t    \"Unexpected ckh_remove() success\");\n\t\tdallocx(p[i], 0);\n\t}\n\n\tassert_zu_eq(ckh_count(&ckh), 0,\n\t    \"ckh_count() should return %zu, but it returned %zu\",\n\t    ZU(0), ckh_count(&ckh));\n\tckh_delete(tsd, &ckh);\n#undef NITEMS\n}\nTEST_END\n\nint\nmain(void)\n{\n\n\treturn (test(\n\t    test_new_delete,\n\t    test_count_insert_search_remove,\n\t    test_insert_iter_remove));\n}\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.8/deps/jemalloc/test/unit/hash.c",
    "content": "/*\n * This file is based on code that is part of SMHasher\n * (https://code.google.com/p/smhasher/), and is subject to the MIT license\n * (http://www.opensource.org/licenses/mit-license.php).  Both email addresses\n * associated with the source code's revision history belong to Austin Appleby,\n * and the revision history ranges from 2010 to 2012.  Therefore the copyright\n * and license are here taken to be:\n *\n * Copyright (c) 2010-2012 Austin Appleby\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n\n#include \"test/jemalloc_test.h\"\n\ntypedef enum {\n\thash_variant_x86_32,\n\thash_variant_x86_128,\n\thash_variant_x64_128\n} hash_variant_t;\n\nstatic size_t\nhash_variant_bits(hash_variant_t variant)\n{\n\n\tswitch (variant) {\n\tcase hash_variant_x86_32: return (32);\n\tcase hash_variant_x86_128: return (128);\n\tcase hash_variant_x64_128: return (128);\n\tdefault: not_reached();\n\t}\n}\n\nstatic const char *\nhash_variant_string(hash_variant_t variant)\n{\n\n\tswitch (variant) {\n\tcase hash_variant_x86_32: return (\"hash_x86_32\");\n\tcase hash_variant_x86_128: return (\"hash_x86_128\");\n\tcase hash_variant_x64_128: return (\"hash_x64_128\");\n\tdefault: not_reached();\n\t}\n}\n\nstatic void\nhash_variant_verify(hash_variant_t variant)\n{\n\tconst size_t hashbytes = hash_variant_bits(variant) / 8;\n\tuint8_t key[256];\n\tVARIABLE_ARRAY(uint8_t, hashes, hashbytes * 256);\n\tVARIABLE_ARRAY(uint8_t, final, hashbytes);\n\tunsigned i;\n\tuint32_t computed, expected;\n\n\tmemset(key, 0, sizeof(key));\n\tmemset(hashes, 0, sizeof(hashes));\n\tmemset(final, 0, sizeof(final));\n\n\t/*\n\t * Hash keys of the form {0}, {0,1}, {0,1,2}, ..., {0,1,...,255} as the\n\t * seed.\n\t */\n\tfor (i = 0; i < 256; i++) {\n\t\tkey[i] = (uint8_t)i;\n\t\tswitch (variant) {\n\t\tcase hash_variant_x86_32: {\n\t\t\tuint32_t out;\n\t\t\tout = hash_x86_32(key, i, 256-i);\n\t\t\tmemcpy(&hashes[i*hashbytes], &out, hashbytes);\n\t\t\tbreak;\n\t\t} case hash_variant_x86_128: {\n\t\t\tuint64_t out[2];\n\t\t\thash_x86_128(key, i, 256-i, out);\n\t\t\tmemcpy(&hashes[i*hashbytes], out, hashbytes);\n\t\t\tbreak;\n\t\t} case hash_variant_x64_128: {\n\t\t\tuint64_t out[2];\n\t\t\thash_x64_128(key, i, 256-i, out);\n\t\t\tmemcpy(&hashes[i*hashbytes], out, hashbytes);\n\t\t\tbreak;\n\t\t} default: not_reached();\n\t\t}\n\t}\n\n\t/* Hash the result array. */\n\tswitch (variant) {\n\tcase hash_variant_x86_32: {\n\t\tuint32_t out = hash_x86_32(hashes, hashbytes*256, 0);\n\t\tmemcpy(final, &out, sizeof(out));\n\t\tbreak;\n\t} case hash_variant_x86_128: {\n\t\tuint64_t out[2];\n\t\thash_x86_128(hashes, hashbytes*256, 0, out);\n\t\tmemcpy(final, out, sizeof(out));\n\t\tbreak;\n\t} case hash_variant_x64_128: {\n\t\tuint64_t out[2];\n\t\thash_x64_128(hashes, hashbytes*256, 0, out);\n\t\tmemcpy(final, out, sizeof(out));\n\t\tbreak;\n\t} default: not_reached();\n\t}\n\n\tcomputed = (final[0] << 0) | (final[1] << 8) | (final[2] << 16) |\n\t    (final[3] << 24);\n\n\tswitch (variant) {\n#ifdef JEMALLOC_BIG_ENDIAN\n\tcase hash_variant_x86_32: expected = 0x6213303eU; break;\n\tcase hash_variant_x86_128: expected = 0x266820caU; break;\n\tcase hash_variant_x64_128: expected = 0xcc622b6fU; break;\n#else\n\tcase hash_variant_x86_32: expected = 0xb0f57ee3U; break;\n\tcase hash_variant_x86_128: expected = 0xb3ece62aU; break;\n\tcase hash_variant_x64_128: expected = 0x6384ba69U; break;\n#endif\n\tdefault: not_reached();\n\t}\n\n\tassert_u32_eq(computed, expected,\n\t    \"Hash mismatch for %s(): expected %#x but got %#x\",\n\t    hash_variant_string(variant), expected, computed);\n}\n\nTEST_BEGIN(test_hash_x86_32)\n{\n\n\thash_variant_verify(hash_variant_x86_32);\n}\nTEST_END\n\nTEST_BEGIN(test_hash_x86_128)\n{\n\n\thash_variant_verify(hash_variant_x86_128);\n}\nTEST_END\n\nTEST_BEGIN(test_hash_x64_128)\n{\n\n\thash_variant_verify(hash_variant_x64_128);\n}\nTEST_END\n\nint\nmain(void)\n{\n\n\treturn (test(\n\t    test_hash_x86_32,\n\t    test_hash_x86_128,\n\t    test_hash_x64_128));\n}\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.8/deps/jemalloc/test/unit/junk.c",
    "content": "#include \"test/jemalloc_test.h\"\n\n#ifdef JEMALLOC_FILL\n#  ifndef JEMALLOC_TEST_JUNK_OPT\n#    define JEMALLOC_TEST_JUNK_OPT \"junk:true\"\n#  endif\nconst char *malloc_conf =\n    \"abort:false,zero:false,redzone:true,quarantine:0,\" JEMALLOC_TEST_JUNK_OPT;\n#endif\n\nstatic arena_dalloc_junk_small_t *arena_dalloc_junk_small_orig;\nstatic arena_dalloc_junk_large_t *arena_dalloc_junk_large_orig;\nstatic huge_dalloc_junk_t *huge_dalloc_junk_orig;\nstatic void *watch_for_junking;\nstatic bool saw_junking;\n\nstatic void\nwatch_junking(void *p)\n{\n\n\twatch_for_junking = p;\n\tsaw_junking = false;\n}\n\nstatic void\narena_dalloc_junk_small_intercept(void *ptr, arena_bin_info_t *bin_info)\n{\n\tsize_t i;\n\n\tarena_dalloc_junk_small_orig(ptr, bin_info);\n\tfor (i = 0; i < bin_info->reg_size; i++) {\n\t\tassert_c_eq(((char *)ptr)[i], 0x5a,\n\t\t    \"Missing junk fill for byte %zu/%zu of deallocated region\",\n\t\t    i, bin_info->reg_size);\n\t}\n\tif (ptr == watch_for_junking)\n\t\tsaw_junking = true;\n}\n\nstatic void\narena_dalloc_junk_large_intercept(void *ptr, size_t usize)\n{\n\tsize_t i;\n\n\tarena_dalloc_junk_large_orig(ptr, usize);\n\tfor (i = 0; i < usize; i++) {\n\t\tassert_c_eq(((char *)ptr)[i], 0x5a,\n\t\t    \"Missing junk fill for byte %zu/%zu of deallocated region\",\n\t\t    i, usize);\n\t}\n\tif (ptr == watch_for_junking)\n\t\tsaw_junking = true;\n}\n\nstatic void\nhuge_dalloc_junk_intercept(void *ptr, size_t usize)\n{\n\n\thuge_dalloc_junk_orig(ptr, usize);\n\t/*\n\t * The conditions under which junk filling actually occurs are nuanced\n\t * enough that it doesn't make sense to duplicate the decision logic in\n\t * test code, so don't actually check that the region is junk-filled.\n\t */\n\tif (ptr == watch_for_junking)\n\t\tsaw_junking = true;\n}\n\nstatic void\ntest_junk(size_t sz_min, size_t sz_max)\n{\n\tchar *s;\n\tsize_t sz_prev, sz, i;\n\n\tif (opt_junk_free) {\n\t\tarena_dalloc_junk_small_orig = arena_dalloc_junk_small;\n\t\tarena_dalloc_junk_small = arena_dalloc_junk_small_intercept;\n\t\tarena_dalloc_junk_large_orig = arena_dalloc_junk_large;\n\t\tarena_dalloc_junk_large = arena_dalloc_junk_large_intercept;\n\t\thuge_dalloc_junk_orig = huge_dalloc_junk;\n\t\thuge_dalloc_junk = huge_dalloc_junk_intercept;\n\t}\n\n\tsz_prev = 0;\n\ts = (char *)mallocx(sz_min, 0);\n\tassert_ptr_not_null((void *)s, \"Unexpected mallocx() failure\");\n\n\tfor (sz = sallocx(s, 0); sz <= sz_max;\n\t    sz_prev = sz, sz = sallocx(s, 0)) {\n\t\tif (sz_prev > 0) {\n\t\t\tassert_c_eq(s[0], 'a',\n\t\t\t    \"Previously allocated byte %zu/%zu is corrupted\",\n\t\t\t    ZU(0), sz_prev);\n\t\t\tassert_c_eq(s[sz_prev-1], 'a',\n\t\t\t    \"Previously allocated byte %zu/%zu is corrupted\",\n\t\t\t    sz_prev-1, sz_prev);\n\t\t}\n\n\t\tfor (i = sz_prev; i < sz; i++) {\n\t\t\tif (opt_junk_alloc) {\n\t\t\t\tassert_c_eq(s[i], 0xa5,\n\t\t\t\t    \"Newly allocated byte %zu/%zu isn't \"\n\t\t\t\t    \"junk-filled\", i, sz);\n\t\t\t}\n\t\t\ts[i] = 'a';\n\t\t}\n\n\t\tif (xallocx(s, sz+1, 0, 0) == sz) {\n\t\t\twatch_junking(s);\n\t\t\ts = (char *)rallocx(s, sz+1, 0);\n\t\t\tassert_ptr_not_null((void *)s,\n\t\t\t    \"Unexpected rallocx() failure\");\n\t\t\tassert_true(!opt_junk_free || saw_junking,\n\t\t\t    \"Expected region of size %zu to be junk-filled\",\n\t\t\t    sz);\n\t\t}\n\t}\n\n\twatch_junking(s);\n\tdallocx(s, 0);\n\tassert_true(!opt_junk_free || saw_junking,\n\t    \"Expected region of size %zu to be junk-filled\", sz);\n\n\tif (opt_junk_free) {\n\t\tarena_dalloc_junk_small = arena_dalloc_junk_small_orig;\n\t\tarena_dalloc_junk_large = arena_dalloc_junk_large_orig;\n\t\thuge_dalloc_junk = huge_dalloc_junk_orig;\n\t}\n}\n\nTEST_BEGIN(test_junk_small)\n{\n\n\ttest_skip_if(!config_fill);\n\ttest_junk(1, SMALL_MAXCLASS-1);\n}\nTEST_END\n\nTEST_BEGIN(test_junk_large)\n{\n\n\ttest_skip_if(!config_fill);\n\ttest_junk(SMALL_MAXCLASS+1, large_maxclass);\n}\nTEST_END\n\nTEST_BEGIN(test_junk_huge)\n{\n\n\ttest_skip_if(!config_fill);\n\ttest_junk(large_maxclass+1, chunksize*2);\n}\nTEST_END\n\narena_ralloc_junk_large_t *arena_ralloc_junk_large_orig;\nstatic void *most_recently_trimmed;\n\nstatic size_t\nshrink_size(size_t size)\n{\n\tsize_t shrink_size;\n\n\tfor (shrink_size = size - 1; nallocx(shrink_size, 0) == size;\n\t    shrink_size--)\n\t\t; /* Do nothing. */\n\n\treturn (shrink_size);\n}\n\nstatic void\narena_ralloc_junk_large_intercept(void *ptr, size_t old_usize, size_t usize)\n{\n\n\tarena_ralloc_junk_large_orig(ptr, old_usize, usize);\n\tassert_zu_eq(old_usize, large_maxclass, \"Unexpected old_usize\");\n\tassert_zu_eq(usize, shrink_size(large_maxclass), \"Unexpected usize\");\n\tmost_recently_trimmed = ptr;\n}\n\nTEST_BEGIN(test_junk_large_ralloc_shrink)\n{\n\tvoid *p1, *p2;\n\n\tp1 = mallocx(large_maxclass, 0);\n\tassert_ptr_not_null(p1, \"Unexpected mallocx() failure\");\n\n\tarena_ralloc_junk_large_orig = arena_ralloc_junk_large;\n\tarena_ralloc_junk_large = arena_ralloc_junk_large_intercept;\n\n\tp2 = rallocx(p1, shrink_size(large_maxclass), 0);\n\tassert_ptr_eq(p1, p2, \"Unexpected move during shrink\");\n\n\tarena_ralloc_junk_large = arena_ralloc_junk_large_orig;\n\n\tassert_ptr_eq(most_recently_trimmed, p1,\n\t    \"Expected trimmed portion of region to be junk-filled\");\n}\nTEST_END\n\nstatic bool detected_redzone_corruption;\n\nstatic void\narena_redzone_corruption_replacement(void *ptr, size_t usize, bool after,\n    size_t offset, uint8_t byte)\n{\n\n\tdetected_redzone_corruption = true;\n}\n\nTEST_BEGIN(test_junk_redzone)\n{\n\tchar *s;\n\tarena_redzone_corruption_t *arena_redzone_corruption_orig;\n\n\ttest_skip_if(!config_fill);\n\ttest_skip_if(!opt_junk_alloc || !opt_junk_free);\n\n\tarena_redzone_corruption_orig = arena_redzone_corruption;\n\tarena_redzone_corruption = arena_redzone_corruption_replacement;\n\n\t/* Test underflow. */\n\tdetected_redzone_corruption = false;\n\ts = (char *)mallocx(1, 0);\n\tassert_ptr_not_null((void *)s, \"Unexpected mallocx() failure\");\n\ts[-1] = 0xbb;\n\tdallocx(s, 0);\n\tassert_true(detected_redzone_corruption,\n\t    \"Did not detect redzone corruption\");\n\n\t/* Test overflow. */\n\tdetected_redzone_corruption = false;\n\ts = (char *)mallocx(1, 0);\n\tassert_ptr_not_null((void *)s, \"Unexpected mallocx() failure\");\n\ts[sallocx(s, 0)] = 0xbb;\n\tdallocx(s, 0);\n\tassert_true(detected_redzone_corruption,\n\t    \"Did not detect redzone corruption\");\n\n\tarena_redzone_corruption = arena_redzone_corruption_orig;\n}\nTEST_END\n\nint\nmain(void)\n{\n\n\tassert(!config_fill || opt_junk_alloc || opt_junk_free);\n\treturn (test(\n\t    test_junk_small,\n\t    test_junk_large,\n\t    test_junk_huge,\n\t    test_junk_large_ralloc_shrink,\n\t    test_junk_redzone));\n}\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.8/deps/jemalloc/test/unit/junk_alloc.c",
    "content": "#define JEMALLOC_TEST_JUNK_OPT \"junk:alloc\"\n#include \"junk.c\"\n#undef JEMALLOC_TEST_JUNK_OPT\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.8/deps/jemalloc/test/unit/junk_free.c",
    "content": "#define JEMALLOC_TEST_JUNK_OPT \"junk:free\"\n#include \"junk.c\"\n#undef JEMALLOC_TEST_JUNK_OPT\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.8/deps/jemalloc/test/unit/lg_chunk.c",
    "content": "#include \"test/jemalloc_test.h\"\n\n/*\n * Make sure that opt.lg_chunk clamping is sufficient.  In practice, this test\n * program will fail a debug assertion during initialization and abort (rather\n * than the test soft-failing) if clamping is insufficient.\n */\nconst char *malloc_conf = \"lg_chunk:0\";\n\nTEST_BEGIN(test_lg_chunk_clamp)\n{\n\tvoid *p;\n\n\tp = mallocx(1, 0);\n\tassert_ptr_not_null(p, \"Unexpected mallocx() failure\");\n\tdallocx(p, 0);\n}\nTEST_END\n\nint\nmain(void)\n{\n\n\treturn (test(\n\t    test_lg_chunk_clamp));\n}\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.8/deps/jemalloc/test/unit/mallctl.c",
    "content": "#include \"test/jemalloc_test.h\"\n\nTEST_BEGIN(test_mallctl_errors)\n{\n\tuint64_t epoch;\n\tsize_t sz;\n\n\tassert_d_eq(mallctl(\"no_such_name\", NULL, NULL, NULL, 0), ENOENT,\n\t    \"mallctl() should return ENOENT for non-existent names\");\n\n\tassert_d_eq(mallctl(\"version\", NULL, NULL, \"0.0.0\", strlen(\"0.0.0\")),\n\t    EPERM, \"mallctl() should return EPERM on attempt to write \"\n\t    \"read-only value\");\n\n\tassert_d_eq(mallctl(\"epoch\", NULL, NULL, &epoch, sizeof(epoch)-1),\n\t    EINVAL, \"mallctl() should return EINVAL for input size mismatch\");\n\tassert_d_eq(mallctl(\"epoch\", NULL, NULL, &epoch, sizeof(epoch)+1),\n\t    EINVAL, \"mallctl() should return EINVAL for input size mismatch\");\n\n\tsz = sizeof(epoch)-1;\n\tassert_d_eq(mallctl(\"epoch\", &epoch, &sz, NULL, 0), EINVAL,\n\t    \"mallctl() should return EINVAL for output size mismatch\");\n\tsz = sizeof(epoch)+1;\n\tassert_d_eq(mallctl(\"epoch\", &epoch, &sz, NULL, 0), EINVAL,\n\t    \"mallctl() should return EINVAL for output size mismatch\");\n}\nTEST_END\n\nTEST_BEGIN(test_mallctlnametomib_errors)\n{\n\tsize_t mib[1];\n\tsize_t miblen;\n\n\tmiblen = sizeof(mib)/sizeof(size_t);\n\tassert_d_eq(mallctlnametomib(\"no_such_name\", mib, &miblen), ENOENT,\n\t    \"mallctlnametomib() should return ENOENT for non-existent names\");\n}\nTEST_END\n\nTEST_BEGIN(test_mallctlbymib_errors)\n{\n\tuint64_t epoch;\n\tsize_t sz;\n\tsize_t mib[1];\n\tsize_t miblen;\n\n\tmiblen = sizeof(mib)/sizeof(size_t);\n\tassert_d_eq(mallctlnametomib(\"version\", mib, &miblen), 0,\n\t    \"Unexpected mallctlnametomib() failure\");\n\n\tassert_d_eq(mallctlbymib(mib, miblen, NULL, NULL, \"0.0.0\",\n\t    strlen(\"0.0.0\")), EPERM, \"mallctl() should return EPERM on \"\n\t    \"attempt to write read-only value\");\n\n\tmiblen = sizeof(mib)/sizeof(size_t);\n\tassert_d_eq(mallctlnametomib(\"epoch\", mib, &miblen), 0,\n\t    \"Unexpected mallctlnametomib() failure\");\n\n\tassert_d_eq(mallctlbymib(mib, miblen, NULL, NULL, &epoch,\n\t    sizeof(epoch)-1), EINVAL,\n\t    \"mallctlbymib() should return EINVAL for input size mismatch\");\n\tassert_d_eq(mallctlbymib(mib, miblen, NULL, NULL, &epoch,\n\t    sizeof(epoch)+1), EINVAL,\n\t    \"mallctlbymib() should return EINVAL for input size mismatch\");\n\n\tsz = sizeof(epoch)-1;\n\tassert_d_eq(mallctlbymib(mib, miblen, &epoch, &sz, NULL, 0), EINVAL,\n\t    \"mallctlbymib() should return EINVAL for output size mismatch\");\n\tsz = sizeof(epoch)+1;\n\tassert_d_eq(mallctlbymib(mib, miblen, &epoch, &sz, NULL, 0), EINVAL,\n\t    \"mallctlbymib() should return EINVAL for output size mismatch\");\n}\nTEST_END\n\nTEST_BEGIN(test_mallctl_read_write)\n{\n\tuint64_t old_epoch, new_epoch;\n\tsize_t sz = sizeof(old_epoch);\n\n\t/* Blind. */\n\tassert_d_eq(mallctl(\"epoch\", NULL, NULL, NULL, 0), 0,\n\t    \"Unexpected mallctl() failure\");\n\tassert_zu_eq(sz, sizeof(old_epoch), \"Unexpected output size\");\n\n\t/* Read. */\n\tassert_d_eq(mallctl(\"epoch\", &old_epoch, &sz, NULL, 0), 0,\n\t    \"Unexpected mallctl() failure\");\n\tassert_zu_eq(sz, sizeof(old_epoch), \"Unexpected output size\");\n\n\t/* Write. */\n\tassert_d_eq(mallctl(\"epoch\", NULL, NULL, &new_epoch, sizeof(new_epoch)),\n\t    0, \"Unexpected mallctl() failure\");\n\tassert_zu_eq(sz, sizeof(old_epoch), \"Unexpected output size\");\n\n\t/* Read+write. */\n\tassert_d_eq(mallctl(\"epoch\", &old_epoch, &sz, &new_epoch,\n\t    sizeof(new_epoch)), 0, \"Unexpected mallctl() failure\");\n\tassert_zu_eq(sz, sizeof(old_epoch), \"Unexpected output size\");\n}\nTEST_END\n\nTEST_BEGIN(test_mallctlnametomib_short_mib)\n{\n\tsize_t mib[4];\n\tsize_t miblen;\n\n\tmiblen = 3;\n\tmib[3] = 42;\n\tassert_d_eq(mallctlnametomib(\"arenas.bin.0.nregs\", mib, &miblen), 0,\n\t    \"Unexpected mallctlnametomib() failure\");\n\tassert_zu_eq(miblen, 3, \"Unexpected mib output length\");\n\tassert_zu_eq(mib[3], 42,\n\t    \"mallctlnametomib() wrote past the end of the input mib\");\n}\nTEST_END\n\nTEST_BEGIN(test_mallctl_config)\n{\n\n#define\tTEST_MALLCTL_CONFIG(config) do {\t\t\t\t\\\n\tbool oldval;\t\t\t\t\t\t\t\\\n\tsize_t sz = sizeof(oldval);\t\t\t\t\t\\\n\tassert_d_eq(mallctl(\"config.\"#config, &oldval, &sz, NULL, 0),\t\\\n\t    0, \"Unexpected mallctl() failure\");\t\t\t\t\\\n\tassert_b_eq(oldval, config_##config, \"Incorrect config value\");\t\\\n\tassert_zu_eq(sz, sizeof(oldval), \"Unexpected output size\");\t\\\n} while (0)\n\n\tTEST_MALLCTL_CONFIG(cache_oblivious);\n\tTEST_MALLCTL_CONFIG(debug);\n\tTEST_MALLCTL_CONFIG(fill);\n\tTEST_MALLCTL_CONFIG(lazy_lock);\n\tTEST_MALLCTL_CONFIG(munmap);\n\tTEST_MALLCTL_CONFIG(prof);\n\tTEST_MALLCTL_CONFIG(prof_libgcc);\n\tTEST_MALLCTL_CONFIG(prof_libunwind);\n\tTEST_MALLCTL_CONFIG(stats);\n\tTEST_MALLCTL_CONFIG(tcache);\n\tTEST_MALLCTL_CONFIG(tls);\n\tTEST_MALLCTL_CONFIG(utrace);\n\tTEST_MALLCTL_CONFIG(valgrind);\n\tTEST_MALLCTL_CONFIG(xmalloc);\n\n#undef TEST_MALLCTL_CONFIG\n}\nTEST_END\n\nTEST_BEGIN(test_mallctl_opt)\n{\n\tbool config_always = true;\n\n#define\tTEST_MALLCTL_OPT(t, opt, config) do {\t\t\t\t\\\n\tt oldval;\t\t\t\t\t\t\t\\\n\tsize_t sz = sizeof(oldval);\t\t\t\t\t\\\n\tint expected = config_##config ? 0 : ENOENT;\t\t\t\\\n\tint result = mallctl(\"opt.\"#opt, &oldval, &sz, NULL, 0);\t\\\n\tassert_d_eq(result, expected,\t\t\t\t\t\\\n\t    \"Unexpected mallctl() result for opt.\"#opt);\t\t\\\n\tassert_zu_eq(sz, sizeof(oldval), \"Unexpected output size\");\t\\\n} while (0)\n\n\tTEST_MALLCTL_OPT(bool, abort, always);\n\tTEST_MALLCTL_OPT(size_t, lg_chunk, always);\n\tTEST_MALLCTL_OPT(const char *, dss, always);\n\tTEST_MALLCTL_OPT(size_t, narenas, always);\n\tTEST_MALLCTL_OPT(ssize_t, lg_dirty_mult, always);\n\tTEST_MALLCTL_OPT(bool, stats_print, always);\n\tTEST_MALLCTL_OPT(const char *, junk, fill);\n\tTEST_MALLCTL_OPT(size_t, quarantine, fill);\n\tTEST_MALLCTL_OPT(bool, redzone, fill);\n\tTEST_MALLCTL_OPT(bool, zero, fill);\n\tTEST_MALLCTL_OPT(bool, utrace, utrace);\n\tTEST_MALLCTL_OPT(bool, xmalloc, xmalloc);\n\tTEST_MALLCTL_OPT(bool, tcache, tcache);\n\tTEST_MALLCTL_OPT(size_t, lg_tcache_max, tcache);\n\tTEST_MALLCTL_OPT(bool, prof, prof);\n\tTEST_MALLCTL_OPT(const char *, prof_prefix, prof);\n\tTEST_MALLCTL_OPT(bool, prof_active, prof);\n\tTEST_MALLCTL_OPT(ssize_t, lg_prof_sample, prof);\n\tTEST_MALLCTL_OPT(bool, prof_accum, prof);\n\tTEST_MALLCTL_OPT(ssize_t, lg_prof_interval, prof);\n\tTEST_MALLCTL_OPT(bool, prof_gdump, prof);\n\tTEST_MALLCTL_OPT(bool, prof_final, prof);\n\tTEST_MALLCTL_OPT(bool, prof_leak, prof);\n\n#undef TEST_MALLCTL_OPT\n}\nTEST_END\n\nTEST_BEGIN(test_manpage_example)\n{\n\tunsigned nbins, i;\n\tsize_t mib[4];\n\tsize_t len, miblen;\n\n\tlen = sizeof(nbins);\n\tassert_d_eq(mallctl(\"arenas.nbins\", &nbins, &len, NULL, 0), 0,\n\t    \"Unexpected mallctl() failure\");\n\n\tmiblen = 4;\n\tassert_d_eq(mallctlnametomib(\"arenas.bin.0.size\", mib, &miblen), 0,\n\t    \"Unexpected mallctlnametomib() failure\");\n\tfor (i = 0; i < nbins; i++) {\n\t\tsize_t bin_size;\n\n\t\tmib[2] = i;\n\t\tlen = sizeof(bin_size);\n\t\tassert_d_eq(mallctlbymib(mib, miblen, &bin_size, &len, NULL, 0),\n\t\t    0, \"Unexpected mallctlbymib() failure\");\n\t\t/* Do something with bin_size... */\n\t}\n}\nTEST_END\n\nTEST_BEGIN(test_tcache_none)\n{\n\tvoid *p0, *q, *p1;\n\n\ttest_skip_if(!config_tcache);\n\n\t/* Allocate p and q. */\n\tp0 = mallocx(42, 0);\n\tassert_ptr_not_null(p0, \"Unexpected mallocx() failure\");\n\tq = mallocx(42, 0);\n\tassert_ptr_not_null(q, \"Unexpected mallocx() failure\");\n\n\t/* Deallocate p and q, but bypass the tcache for q. */\n\tdallocx(p0, 0);\n\tdallocx(q, MALLOCX_TCACHE_NONE);\n\n\t/* Make sure that tcache-based allocation returns p, not q. */\n\tp1 = mallocx(42, 0);\n\tassert_ptr_not_null(p1, \"Unexpected mallocx() failure\");\n\tassert_ptr_eq(p0, p1, \"Expected tcache to allocate cached region\");\n\n\t/* Clean up. */\n\tdallocx(p1, MALLOCX_TCACHE_NONE);\n}\nTEST_END\n\nTEST_BEGIN(test_tcache)\n{\n#define\tNTCACHES\t10\n\tunsigned tis[NTCACHES];\n\tvoid *ps[NTCACHES];\n\tvoid *qs[NTCACHES];\n\tunsigned i;\n\tsize_t sz, psz, qsz;\n\n\ttest_skip_if(!config_tcache);\n\n\tpsz = 42;\n\tqsz = nallocx(psz, 0) + 1;\n\n\t/* Create tcaches. */\n\tfor (i = 0; i < NTCACHES; i++) {\n\t\tsz = sizeof(unsigned);\n\t\tassert_d_eq(mallctl(\"tcache.create\", &tis[i], &sz, NULL, 0), 0,\n\t\t    \"Unexpected mallctl() failure, i=%u\", i);\n\t}\n\n\t/* Exercise tcache ID recycling. */\n\tfor (i = 0; i < NTCACHES; i++) {\n\t\tassert_d_eq(mallctl(\"tcache.destroy\", NULL, NULL, &tis[i],\n\t\t    sizeof(unsigned)), 0, \"Unexpected mallctl() failure, i=%u\",\n\t\t    i);\n\t}\n\tfor (i = 0; i < NTCACHES; i++) {\n\t\tsz = sizeof(unsigned);\n\t\tassert_d_eq(mallctl(\"tcache.create\", &tis[i], &sz, NULL, 0), 0,\n\t\t    \"Unexpected mallctl() failure, i=%u\", i);\n\t}\n\n\t/* Flush empty tcaches. */\n\tfor (i = 0; i < NTCACHES; i++) {\n\t\tassert_d_eq(mallctl(\"tcache.flush\", NULL, NULL, &tis[i],\n\t\t    sizeof(unsigned)), 0, \"Unexpected mallctl() failure, i=%u\",\n\t\t    i);\n\t}\n\n\t/* Cache some allocations. */\n\tfor (i = 0; i < NTCACHES; i++) {\n\t\tps[i] = mallocx(psz, MALLOCX_TCACHE(tis[i]));\n\t\tassert_ptr_not_null(ps[i], \"Unexpected mallocx() failure, i=%u\",\n\t\t    i);\n\t\tdallocx(ps[i], MALLOCX_TCACHE(tis[i]));\n\n\t\tqs[i] = mallocx(qsz, MALLOCX_TCACHE(tis[i]));\n\t\tassert_ptr_not_null(qs[i], \"Unexpected mallocx() failure, i=%u\",\n\t\t    i);\n\t\tdallocx(qs[i], MALLOCX_TCACHE(tis[i]));\n\t}\n\n\t/* Verify that tcaches allocate cached regions. */\n\tfor (i = 0; i < NTCACHES; i++) {\n\t\tvoid *p0 = ps[i];\n\t\tps[i] = mallocx(psz, MALLOCX_TCACHE(tis[i]));\n\t\tassert_ptr_not_null(ps[i], \"Unexpected mallocx() failure, i=%u\",\n\t\t    i);\n\t\tassert_ptr_eq(ps[i], p0,\n\t\t    \"Expected mallocx() to allocate cached region, i=%u\", i);\n\t}\n\n\t/* Verify that reallocation uses cached regions. */\n\tfor (i = 0; i < NTCACHES; i++) {\n\t\tvoid *q0 = qs[i];\n\t\tqs[i] = rallocx(ps[i], qsz, MALLOCX_TCACHE(tis[i]));\n\t\tassert_ptr_not_null(qs[i], \"Unexpected rallocx() failure, i=%u\",\n\t\t    i);\n\t\tassert_ptr_eq(qs[i], q0,\n\t\t    \"Expected rallocx() to allocate cached region, i=%u\", i);\n\t\t/* Avoid undefined behavior in case of test failure. */\n\t\tif (qs[i] == NULL)\n\t\t\tqs[i] = ps[i];\n\t}\n\tfor (i = 0; i < NTCACHES; i++)\n\t\tdallocx(qs[i], MALLOCX_TCACHE(tis[i]));\n\n\t/* Flush some non-empty tcaches. */\n\tfor (i = 0; i < NTCACHES/2; i++) {\n\t\tassert_d_eq(mallctl(\"tcache.flush\", NULL, NULL, &tis[i],\n\t\t    sizeof(unsigned)), 0, \"Unexpected mallctl() failure, i=%u\",\n\t\t    i);\n\t}\n\n\t/* Destroy tcaches. */\n\tfor (i = 0; i < NTCACHES; i++) {\n\t\tassert_d_eq(mallctl(\"tcache.destroy\", NULL, NULL, &tis[i],\n\t\t    sizeof(unsigned)), 0, \"Unexpected mallctl() failure, i=%u\",\n\t\t    i);\n\t}\n}\nTEST_END\n\nTEST_BEGIN(test_thread_arena)\n{\n\tunsigned arena_old, arena_new, narenas;\n\tsize_t sz = sizeof(unsigned);\n\n\tassert_d_eq(mallctl(\"arenas.narenas\", &narenas, &sz, NULL, 0), 0,\n\t    \"Unexpected mallctl() failure\");\n\tassert_u_eq(narenas, opt_narenas, \"Number of arenas incorrect\");\n\tarena_new = narenas - 1;\n\tassert_d_eq(mallctl(\"thread.arena\", &arena_old, &sz, &arena_new,\n\t    sizeof(unsigned)), 0, \"Unexpected mallctl() failure\");\n\tarena_new = 0;\n\tassert_d_eq(mallctl(\"thread.arena\", &arena_old, &sz, &arena_new,\n\t    sizeof(unsigned)), 0, \"Unexpected mallctl() failure\");\n}\nTEST_END\n\nTEST_BEGIN(test_arena_i_lg_dirty_mult)\n{\n\tssize_t lg_dirty_mult, orig_lg_dirty_mult, prev_lg_dirty_mult;\n\tsize_t sz = sizeof(ssize_t);\n\n\tassert_d_eq(mallctl(\"arena.0.lg_dirty_mult\", &orig_lg_dirty_mult, &sz,\n\t    NULL, 0), 0, \"Unexpected mallctl() failure\");\n\n\tlg_dirty_mult = -2;\n\tassert_d_eq(mallctl(\"arena.0.lg_dirty_mult\", NULL, NULL,\n\t    &lg_dirty_mult, sizeof(ssize_t)), EFAULT,\n\t    \"Unexpected mallctl() success\");\n\n\tlg_dirty_mult = (sizeof(size_t) << 3);\n\tassert_d_eq(mallctl(\"arena.0.lg_dirty_mult\", NULL, NULL,\n\t    &lg_dirty_mult, sizeof(ssize_t)), EFAULT,\n\t    \"Unexpected mallctl() success\");\n\n\tfor (prev_lg_dirty_mult = orig_lg_dirty_mult, lg_dirty_mult = -1;\n\t    lg_dirty_mult < (ssize_t)(sizeof(size_t) << 3); prev_lg_dirty_mult\n\t    = lg_dirty_mult, lg_dirty_mult++) {\n\t\tssize_t old_lg_dirty_mult;\n\n\t\tassert_d_eq(mallctl(\"arena.0.lg_dirty_mult\", &old_lg_dirty_mult,\n\t\t    &sz, &lg_dirty_mult, sizeof(ssize_t)), 0,\n\t\t    \"Unexpected mallctl() failure\");\n\t\tassert_zd_eq(old_lg_dirty_mult, prev_lg_dirty_mult,\n\t\t    \"Unexpected old arena.0.lg_dirty_mult\");\n\t}\n}\nTEST_END\n\nTEST_BEGIN(test_arena_i_purge)\n{\n\tunsigned narenas;\n\tsize_t sz = sizeof(unsigned);\n\tsize_t mib[3];\n\tsize_t miblen = 3;\n\n\tassert_d_eq(mallctl(\"arena.0.purge\", NULL, NULL, NULL, 0), 0,\n\t    \"Unexpected mallctl() failure\");\n\n\tassert_d_eq(mallctl(\"arenas.narenas\", &narenas, &sz, NULL, 0), 0,\n\t    \"Unexpected mallctl() failure\");\n\tassert_d_eq(mallctlnametomib(\"arena.0.purge\", mib, &miblen), 0,\n\t    \"Unexpected mallctlnametomib() failure\");\n\tmib[1] = narenas;\n\tassert_d_eq(mallctlbymib(mib, miblen, NULL, NULL, NULL, 0), 0,\n\t    \"Unexpected mallctlbymib() failure\");\n}\nTEST_END\n\nTEST_BEGIN(test_arena_i_dss)\n{\n\tconst char *dss_prec_old, *dss_prec_new;\n\tsize_t sz = sizeof(dss_prec_old);\n\tsize_t mib[3];\n\tsize_t miblen;\n\n\tmiblen = sizeof(mib)/sizeof(size_t);\n\tassert_d_eq(mallctlnametomib(\"arena.0.dss\", mib, &miblen), 0,\n\t    \"Unexpected mallctlnametomib() error\");\n\n\tdss_prec_new = \"disabled\";\n\tassert_d_eq(mallctlbymib(mib, miblen, &dss_prec_old, &sz, &dss_prec_new,\n\t    sizeof(dss_prec_new)), 0, \"Unexpected mallctl() failure\");\n\tassert_str_ne(dss_prec_old, \"primary\",\n\t    \"Unexpected default for dss precedence\");\n\n\tassert_d_eq(mallctlbymib(mib, miblen, &dss_prec_new, &sz, &dss_prec_old,\n\t    sizeof(dss_prec_old)), 0, \"Unexpected mallctl() failure\");\n\n\tassert_d_eq(mallctlbymib(mib, miblen, &dss_prec_old, &sz, NULL, 0), 0,\n\t    \"Unexpected mallctl() failure\");\n\tassert_str_ne(dss_prec_old, \"primary\",\n\t    \"Unexpected value for dss precedence\");\n\n\tmib[1] = narenas_total_get();\n\tdss_prec_new = \"disabled\";\n\tassert_d_eq(mallctlbymib(mib, miblen, &dss_prec_old, &sz, &dss_prec_new,\n\t    sizeof(dss_prec_new)), 0, \"Unexpected mallctl() failure\");\n\tassert_str_ne(dss_prec_old, \"primary\",\n\t    \"Unexpected default for dss precedence\");\n\n\tassert_d_eq(mallctlbymib(mib, miblen, &dss_prec_new, &sz, &dss_prec_old,\n\t    sizeof(dss_prec_new)), 0, \"Unexpected mallctl() failure\");\n\n\tassert_d_eq(mallctlbymib(mib, miblen, &dss_prec_old, &sz, NULL, 0), 0,\n\t    \"Unexpected mallctl() failure\");\n\tassert_str_ne(dss_prec_old, \"primary\",\n\t    \"Unexpected value for dss precedence\");\n}\nTEST_END\n\nTEST_BEGIN(test_arenas_initialized)\n{\n\tunsigned narenas;\n\tsize_t sz = sizeof(narenas);\n\n\tassert_d_eq(mallctl(\"arenas.narenas\", &narenas, &sz, NULL, 0), 0,\n\t    \"Unexpected mallctl() failure\");\n\t{\n\t\tVARIABLE_ARRAY(bool, initialized, narenas);\n\n\t\tsz = narenas * sizeof(bool);\n\t\tassert_d_eq(mallctl(\"arenas.initialized\", initialized, &sz,\n\t\t    NULL, 0), 0, \"Unexpected mallctl() failure\");\n\t}\n}\nTEST_END\n\nTEST_BEGIN(test_arenas_lg_dirty_mult)\n{\n\tssize_t lg_dirty_mult, orig_lg_dirty_mult, prev_lg_dirty_mult;\n\tsize_t sz = sizeof(ssize_t);\n\n\tassert_d_eq(mallctl(\"arenas.lg_dirty_mult\", &orig_lg_dirty_mult, &sz,\n\t    NULL, 0), 0, \"Unexpected mallctl() failure\");\n\n\tlg_dirty_mult = -2;\n\tassert_d_eq(mallctl(\"arenas.lg_dirty_mult\", NULL, NULL,\n\t    &lg_dirty_mult, sizeof(ssize_t)), EFAULT,\n\t    \"Unexpected mallctl() success\");\n\n\tlg_dirty_mult = (sizeof(size_t) << 3);\n\tassert_d_eq(mallctl(\"arenas.lg_dirty_mult\", NULL, NULL,\n\t    &lg_dirty_mult, sizeof(ssize_t)), EFAULT,\n\t    \"Unexpected mallctl() success\");\n\n\tfor (prev_lg_dirty_mult = orig_lg_dirty_mult, lg_dirty_mult = -1;\n\t    lg_dirty_mult < (ssize_t)(sizeof(size_t) << 3); prev_lg_dirty_mult =\n\t    lg_dirty_mult, lg_dirty_mult++) {\n\t\tssize_t old_lg_dirty_mult;\n\n\t\tassert_d_eq(mallctl(\"arenas.lg_dirty_mult\", &old_lg_dirty_mult,\n\t\t    &sz, &lg_dirty_mult, sizeof(ssize_t)), 0,\n\t\t    \"Unexpected mallctl() failure\");\n\t\tassert_zd_eq(old_lg_dirty_mult, prev_lg_dirty_mult,\n\t\t    \"Unexpected old arenas.lg_dirty_mult\");\n\t}\n}\nTEST_END\n\nTEST_BEGIN(test_arenas_constants)\n{\n\n#define\tTEST_ARENAS_CONSTANT(t, name, expected) do {\t\t\t\\\n\tt name;\t\t\t\t\t\t\t\t\\\n\tsize_t sz = sizeof(t);\t\t\t\t\t\t\\\n\tassert_d_eq(mallctl(\"arenas.\"#name, &name, &sz, NULL, 0), 0,\t\\\n\t    \"Unexpected mallctl() failure\");\t\t\t\t\\\n\tassert_zu_eq(name, expected, \"Incorrect \"#name\" size\");\t\t\\\n} while (0)\n\n\tTEST_ARENAS_CONSTANT(size_t, quantum, QUANTUM);\n\tTEST_ARENAS_CONSTANT(size_t, page, PAGE);\n\tTEST_ARENAS_CONSTANT(unsigned, nbins, NBINS);\n\tTEST_ARENAS_CONSTANT(unsigned, nlruns, nlclasses);\n\tTEST_ARENAS_CONSTANT(unsigned, nhchunks, nhclasses);\n\n#undef TEST_ARENAS_CONSTANT\n}\nTEST_END\n\nTEST_BEGIN(test_arenas_bin_constants)\n{\n\n#define\tTEST_ARENAS_BIN_CONSTANT(t, name, expected) do {\t\t\\\n\tt name;\t\t\t\t\t\t\t\t\\\n\tsize_t sz = sizeof(t);\t\t\t\t\t\t\\\n\tassert_d_eq(mallctl(\"arenas.bin.0.\"#name, &name, &sz, NULL, 0),\t\\\n\t    0, \"Unexpected mallctl() failure\");\t\t\t\t\\\n\tassert_zu_eq(name, expected, \"Incorrect \"#name\" size\");\t\t\\\n} while (0)\n\n\tTEST_ARENAS_BIN_CONSTANT(size_t, size, arena_bin_info[0].reg_size);\n\tTEST_ARENAS_BIN_CONSTANT(uint32_t, nregs, arena_bin_info[0].nregs);\n\tTEST_ARENAS_BIN_CONSTANT(size_t, run_size, arena_bin_info[0].run_size);\n\n#undef TEST_ARENAS_BIN_CONSTANT\n}\nTEST_END\n\nTEST_BEGIN(test_arenas_lrun_constants)\n{\n\n#define\tTEST_ARENAS_LRUN_CONSTANT(t, name, expected) do {\t\t\\\n\tt name;\t\t\t\t\t\t\t\t\\\n\tsize_t sz = sizeof(t);\t\t\t\t\t\t\\\n\tassert_d_eq(mallctl(\"arenas.lrun.0.\"#name, &name, &sz, NULL,\t\\\n\t    0), 0, \"Unexpected mallctl() failure\");\t\t\t\\\n\tassert_zu_eq(name, expected, \"Incorrect \"#name\" size\");\t\t\\\n} while (0)\n\n\tTEST_ARENAS_LRUN_CONSTANT(size_t, size, LARGE_MINCLASS);\n\n#undef TEST_ARENAS_LRUN_CONSTANT\n}\nTEST_END\n\nTEST_BEGIN(test_arenas_hchunk_constants)\n{\n\n#define\tTEST_ARENAS_HCHUNK_CONSTANT(t, name, expected) do {\t\t\\\n\tt name;\t\t\t\t\t\t\t\t\\\n\tsize_t sz = sizeof(t);\t\t\t\t\t\t\\\n\tassert_d_eq(mallctl(\"arenas.hchunk.0.\"#name, &name, &sz, NULL,\t\\\n\t    0), 0, \"Unexpected mallctl() failure\");\t\t\t\\\n\tassert_zu_eq(name, expected, \"Incorrect \"#name\" size\");\t\t\\\n} while (0)\n\n\tTEST_ARENAS_HCHUNK_CONSTANT(size_t, size, chunksize);\n\n#undef TEST_ARENAS_HCHUNK_CONSTANT\n}\nTEST_END\n\nTEST_BEGIN(test_arenas_extend)\n{\n\tunsigned narenas_before, arena, narenas_after;\n\tsize_t sz = sizeof(unsigned);\n\n\tassert_d_eq(mallctl(\"arenas.narenas\", &narenas_before, &sz, NULL, 0), 0,\n\t    \"Unexpected mallctl() failure\");\n\tassert_d_eq(mallctl(\"arenas.extend\", &arena, &sz, NULL, 0), 0,\n\t    \"Unexpected mallctl() failure\");\n\tassert_d_eq(mallctl(\"arenas.narenas\", &narenas_after, &sz, NULL, 0), 0,\n\t    \"Unexpected mallctl() failure\");\n\n\tassert_u_eq(narenas_before+1, narenas_after,\n\t    \"Unexpected number of arenas before versus after extension\");\n\tassert_u_eq(arena, narenas_after-1, \"Unexpected arena index\");\n}\nTEST_END\n\nTEST_BEGIN(test_stats_arenas)\n{\n\n#define\tTEST_STATS_ARENAS(t, name) do {\t\t\t\t\t\\\n\tt name;\t\t\t\t\t\t\t\t\\\n\tsize_t sz = sizeof(t);\t\t\t\t\t\t\\\n\tassert_d_eq(mallctl(\"stats.arenas.0.\"#name, &name, &sz, NULL,\t\\\n\t    0), 0, \"Unexpected mallctl() failure\");\t\t\t\\\n} while (0)\n\n\tTEST_STATS_ARENAS(const char *, dss);\n\tTEST_STATS_ARENAS(unsigned, nthreads);\n\tTEST_STATS_ARENAS(size_t, pactive);\n\tTEST_STATS_ARENAS(size_t, pdirty);\n\n#undef TEST_STATS_ARENAS\n}\nTEST_END\n\nint\nmain(void)\n{\n\n\treturn (test(\n\t    test_mallctl_errors,\n\t    test_mallctlnametomib_errors,\n\t    test_mallctlbymib_errors,\n\t    test_mallctl_read_write,\n\t    test_mallctlnametomib_short_mib,\n\t    test_mallctl_config,\n\t    test_mallctl_opt,\n\t    test_manpage_example,\n\t    test_tcache_none,\n\t    test_tcache,\n\t    test_thread_arena,\n\t    test_arena_i_lg_dirty_mult,\n\t    test_arena_i_purge,\n\t    test_arena_i_dss,\n\t    test_arenas_initialized,\n\t    test_arenas_lg_dirty_mult,\n\t    test_arenas_constants,\n\t    test_arenas_bin_constants,\n\t    test_arenas_lrun_constants,\n\t    test_arenas_hchunk_constants,\n\t    test_arenas_extend,\n\t    test_stats_arenas));\n}\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.8/deps/jemalloc/test/unit/math.c",
    "content": "#include \"test/jemalloc_test.h\"\n\n#define\tMAX_REL_ERR 1.0e-9\n#define\tMAX_ABS_ERR 1.0e-9\n\n#include <float.h>\n\n#ifndef INFINITY\n#define\tINFINITY (DBL_MAX + DBL_MAX)\n#endif\n\nstatic bool\ndouble_eq_rel(double a, double b, double max_rel_err, double max_abs_err)\n{\n\tdouble rel_err;\n\n\tif (fabs(a - b) < max_abs_err)\n\t\treturn (true);\n\trel_err = (fabs(b) > fabs(a)) ? fabs((a-b)/b) : fabs((a-b)/a);\n\treturn (rel_err < max_rel_err);\n}\n\nstatic uint64_t\nfactorial(unsigned x)\n{\n\tuint64_t ret = 1;\n\tunsigned i;\n\n\tfor (i = 2; i <= x; i++)\n\t\tret *= (uint64_t)i;\n\n\treturn (ret);\n}\n\nTEST_BEGIN(test_ln_gamma_factorial)\n{\n\tunsigned x;\n\n\t/* exp(ln_gamma(x)) == (x-1)! for integer x. */\n\tfor (x = 1; x <= 21; x++) {\n\t\tassert_true(double_eq_rel(exp(ln_gamma(x)),\n\t\t    (double)factorial(x-1), MAX_REL_ERR, MAX_ABS_ERR),\n\t\t    \"Incorrect factorial result for x=%u\", x);\n\t}\n}\nTEST_END\n\n/* Expected ln_gamma([0.0..100.0] increment=0.25). */\nstatic const double ln_gamma_misc_expected[] = {\n\tINFINITY,\n\t1.28802252469807743, 0.57236494292470008, 0.20328095143129538,\n\t0.00000000000000000, -0.09827183642181320, -0.12078223763524518,\n\t-0.08440112102048555, 0.00000000000000000, 0.12487171489239651,\n\t0.28468287047291918, 0.47521466691493719, 0.69314718055994529,\n\t0.93580193110872523, 1.20097360234707429, 1.48681557859341718,\n\t1.79175946922805496, 2.11445692745037128, 2.45373657084244234,\n\t2.80857141857573644, 3.17805383034794575, 3.56137591038669710,\n\t3.95781396761871651, 4.36671603662228680, 4.78749174278204581,\n\t5.21960398699022932, 5.66256205985714178, 6.11591589143154568,\n\t6.57925121201010121, 7.05218545073853953, 7.53436423675873268,\n\t8.02545839631598312, 8.52516136106541467, 9.03318691960512332,\n\t9.54926725730099690, 10.07315123968123949, 10.60460290274525086,\n\t11.14340011995171231, 11.68933342079726856, 12.24220494005076176,\n\t12.80182748008146909, 13.36802367147604720, 13.94062521940376342,\n\t14.51947222506051816, 15.10441257307551943, 15.69530137706046524,\n\t16.29200047656724237, 16.89437797963419285, 17.50230784587389010,\n\t18.11566950571089407, 18.73434751193644843, 19.35823122022435427,\n\t19.98721449566188468, 20.62119544270163018, 21.26007615624470048,\n\t21.90376249182879320, 22.55216385312342098, 23.20519299513386002,\n\t23.86276584168908954, 24.52480131594137802, 25.19122118273868338,\n\t25.86194990184851861, 26.53691449111561340, 27.21604439872720604,\n\t27.89927138384089389, 28.58652940490193828, 29.27775451504081516,\n\t29.97288476399884871, 30.67186010608067548, 31.37462231367769050,\n\t32.08111489594735843, 32.79128302226991565, 33.50507345013689076,\n\t34.22243445715505317, 34.94331577687681545, 35.66766853819134298,\n\t36.39544520803305261, 37.12659953718355865, 37.86108650896109395,\n\t38.59886229060776230, 39.33988418719949465, 40.08411059791735198,\n\t40.83150097453079752, 41.58201578195490100, 42.33561646075348506,\n\t43.09226539146988699, 43.85192586067515208, 44.61456202863158893,\n\t45.38013889847690052, 46.14862228684032885, 46.91997879580877395,\n\t47.69417578616628361, 48.47118135183522014, 49.25096429545256882,\n\t50.03349410501914463, 50.81874093156324790, 51.60667556776436982,\n\t52.39726942748592364, 53.19049452616926743, 53.98632346204390586,\n\t54.78472939811231157, 55.58568604486942633, 56.38916764371992940,\n\t57.19514895105859864, 58.00360522298051080, 58.81451220059079787,\n\t59.62784609588432261, 60.44358357816834371, 61.26170176100199427,\n\t62.08217818962842927, 62.90499082887649962, 63.73011805151035958,\n\t64.55753862700632340, 65.38723171073768015, 66.21917683354901385,\n\t67.05335389170279825, 67.88974313718154008, 68.72832516833013017,\n\t69.56908092082363737, 70.41199165894616385, 71.25703896716800045,\n\t72.10420474200799390, 72.95347118416940191, 73.80482079093779646,\n\t74.65823634883015814, 75.51370092648485866, 76.37119786778275454,\n\t77.23071078519033961, 78.09222355331530707, 78.95572030266725960,\n\t79.82118541361435859, 80.68860351052903468, 81.55795945611502873,\n\t82.42923834590904164, 83.30242550295004378, 84.17750647261028973,\n\t85.05446701758152983, 85.93329311301090456, 86.81397094178107920,\n\t87.69648688992882057, 88.58082754219766741, 89.46697967771913795,\n\t90.35493026581838194, 91.24466646193963015, 92.13617560368709292,\n\t93.02944520697742803, 93.92446296229978486, 94.82121673107967297,\n\t95.71969454214321615, 96.61988458827809723, 97.52177522288820910,\n\t98.42535495673848800, 99.33061245478741341, 100.23753653310367895,\n\t101.14611615586458981, 102.05634043243354370, 102.96819861451382394,\n\t103.88168009337621811, 104.79677439715833032, 105.71347118823287303,\n\t106.63176026064346047, 107.55163153760463501, 108.47307506906540198,\n\t109.39608102933323153, 110.32063971475740516, 111.24674154146920557,\n\t112.17437704317786995, 113.10353686902013237, 114.03421178146170689,\n\t114.96639265424990128, 115.90007047041454769, 116.83523632031698014,\n\t117.77188139974506953, 118.70999700805310795, 119.64957454634490830,\n\t120.59060551569974962, 121.53308151543865279, 122.47699424143097247,\n\t123.42233548443955726, 124.36909712850338394, 125.31727114935689826,\n\t126.26684961288492559, 127.21782467361175861, 128.17018857322420899,\n\t129.12393363912724453, 130.07905228303084755, 131.03553699956862033,\n\t131.99338036494577864, 132.95257503561629164, 133.91311374698926784,\n\t134.87498931216194364, 135.83819462068046846, 136.80272263732638294,\n\t137.76856640092901785, 138.73571902320256299, 139.70417368760718091,\n\t140.67392364823425055, 141.64496222871400732, 142.61728282114600574,\n\t143.59087888505104047, 144.56574394634486680, 145.54187159633210058,\n\t146.51925549072063859, 147.49788934865566148, 148.47776695177302031,\n\t149.45888214327129617, 150.44122882700193600, 151.42480096657754984,\n\t152.40959258449737490, 153.39559776128982094, 154.38281063467164245,\n\t155.37122539872302696, 156.36083630307879844, 157.35163765213474107,\n\t158.34362380426921391, 159.33678917107920370, 160.33112821663092973,\n\t161.32663545672428995, 162.32330545817117695, 163.32113283808695314,\n\t164.32011226319519892, 165.32023844914485267, 166.32150615984036790,\n\t167.32391020678358018, 168.32744544842768164, 169.33210678954270634,\n\t170.33788918059275375, 171.34478761712384198, 172.35279713916281707,\n\t173.36191283062726143, 174.37212981874515094, 175.38344327348534080,\n\t176.39584840699734514, 177.40934047306160437, 178.42391476654847793,\n\t179.43956662288721304, 180.45629141754378111, 181.47408456550741107,\n\t182.49294152078630304, 183.51285777591152737, 184.53382886144947861,\n\t185.55585034552262869, 186.57891783333786861, 187.60302696672312095,\n\t188.62817342367162610, 189.65435291789341932, 190.68156119837468054,\n\t191.70979404894376330, 192.73904728784492590, 193.76931676731820176,\n\t194.80059837318714244, 195.83288802445184729, 196.86618167288995096,\n\t197.90047530266301123, 198.93576492992946214, 199.97204660246373464,\n\t201.00931639928148797, 202.04757043027063901, 203.08680483582807597,\n\t204.12701578650228385, 205.16819948264117102, 206.21035215404597807,\n\t207.25347005962987623, 208.29754948708190909, 209.34258675253678916,\n\t210.38857820024875878, 211.43552020227099320, 212.48340915813977858,\n\t213.53224149456323744, 214.58201366511514152, 215.63272214993284592,\n\t216.68436345542014010, 217.73693411395422004, 218.79043068359703739,\n\t219.84484974781133815, 220.90018791517996988, 221.95644181913033322,\n\t223.01360811766215875, 224.07168349307951871, 225.13066465172661879,\n\t226.19054832372759734, 227.25133126272962159, 228.31301024565024704,\n\t229.37558207242807384, 230.43904356577689896, 231.50339157094342113,\n\t232.56862295546847008, 233.63473460895144740, 234.70172344281823484,\n\t235.76958639009222907, 236.83832040516844586, 237.90792246359117712,\n\t238.97838956183431947, 240.04971871708477238, 241.12190696702904802,\n\t242.19495136964280846, 243.26884900298270509, 244.34359696498191283,\n\t245.41919237324782443, 246.49563236486270057, 247.57291409618682110,\n\t248.65103474266476269, 249.72999149863338175, 250.80978157713354904,\n\t251.89040220972316320, 252.97185064629374551, 254.05412415488834199,\n\t255.13722002152300661, 256.22113555000953511, 257.30586806178126835,\n\t258.39141489572085675, 259.47777340799029844, 260.56494097186322279,\n\t261.65291497755913497, 262.74169283208021852, 263.83127195904967266,\n\t264.92164979855277807, 266.01282380697938379, 267.10479145686849733,\n\t268.19755023675537586, 269.29109765101975427, 270.38543121973674488,\n\t271.48054847852881721, 272.57644697842033565, 273.67312428569374561,\n\t274.77057798174683967, 275.86880566295326389, 276.96780494052313770,\n\t278.06757344036617496, 279.16810880295668085, 280.26940868320008349,\n\t281.37147075030043197, 282.47429268763045229, 283.57787219260217171,\n\t284.68220697654078322, 285.78729476455760050, 286.89313329542699194,\n\t287.99972032146268930, 289.10705360839756395, 290.21513093526289140,\n\t291.32395009427028754, 292.43350889069523646, 293.54380514276073200,\n\t294.65483668152336350, 295.76660135076059532, 296.87909700685889902,\n\t297.99232151870342022, 299.10627276756946458, 300.22094864701409733,\n\t301.33634706277030091, 302.45246593264130297, 303.56930318639643929,\n\t304.68685676566872189, 305.80512462385280514, 306.92410472600477078,\n\t308.04379504874236773, 309.16419358014690033, 310.28529831966631036,\n\t311.40710727801865687, 312.52961847709792664, 313.65282994987899201,\n\t314.77673974032603610, 315.90134590329950015, 317.02664650446632777,\n\t318.15263962020929966, 319.27932333753892635, 320.40669575400545455,\n\t321.53475497761127144, 322.66349912672620803, 323.79292633000159185,\n\t324.92303472628691452, 326.05382246454587403, 327.18528770377525916,\n\t328.31742861292224234, 329.45024337080525356, 330.58373016603343331,\n\t331.71788719692847280, 332.85271267144611329, 333.98820480709991898,\n\t335.12436183088397001, 336.26118197919845443, 337.39866349777429377,\n\t338.53680464159958774, 339.67560367484657036, 340.81505887079896411,\n\t341.95516851178109619, 343.09593088908627578, 344.23734430290727460,\n\t345.37940706226686416, 346.52211748494903532, 347.66547389743118401,\n\t348.80947463481720661, 349.95411804077025408, 351.09940246744753267,\n\t352.24532627543504759, 353.39188783368263103, 354.53908551944078908,\n\t355.68691771819692349, 356.83538282361303118, 357.98447923746385868,\n\t359.13420536957539753\n};\n\nTEST_BEGIN(test_ln_gamma_misc)\n{\n\tunsigned i;\n\n\tfor (i = 1; i < sizeof(ln_gamma_misc_expected)/sizeof(double); i++) {\n\t\tdouble x = (double)i * 0.25;\n\t\tassert_true(double_eq_rel(ln_gamma(x),\n\t\t    ln_gamma_misc_expected[i], MAX_REL_ERR, MAX_ABS_ERR),\n\t\t    \"Incorrect ln_gamma result for i=%u\", i);\n\t}\n}\nTEST_END\n\n/* Expected pt_norm([0.01..0.99] increment=0.01). */\nstatic const double pt_norm_expected[] = {\n\t-INFINITY,\n\t-2.32634787404084076, -2.05374891063182252, -1.88079360815125085,\n\t-1.75068607125216946, -1.64485362695147264, -1.55477359459685305,\n\t-1.47579102817917063, -1.40507156030963221, -1.34075503369021654,\n\t-1.28155156554460081, -1.22652812003661049, -1.17498679206608991,\n\t-1.12639112903880045, -1.08031934081495606, -1.03643338949378938,\n\t-0.99445788320975281, -0.95416525314619416, -0.91536508784281390,\n\t-0.87789629505122846, -0.84162123357291418, -0.80642124701824025,\n\t-0.77219321418868492, -0.73884684918521371, -0.70630256284008752,\n\t-0.67448975019608171, -0.64334540539291685, -0.61281299101662701,\n\t-0.58284150727121620, -0.55338471955567281, -0.52440051270804067,\n\t-0.49585034734745320, -0.46769879911450812, -0.43991316567323380,\n\t-0.41246312944140462, -0.38532046640756751, -0.35845879325119373,\n\t-0.33185334643681652, -0.30548078809939738, -0.27931903444745404,\n\t-0.25334710313579978, -0.22754497664114931, -0.20189347914185077,\n\t-0.17637416478086135, -0.15096921549677725, -0.12566134685507399,\n\t-0.10043372051146975, -0.07526986209982976, -0.05015358346473352,\n\t-0.02506890825871106, 0.00000000000000000, 0.02506890825871106,\n\t0.05015358346473366, 0.07526986209982990, 0.10043372051146990,\n\t0.12566134685507413, 0.15096921549677739, 0.17637416478086146,\n\t0.20189347914185105, 0.22754497664114931, 0.25334710313579978,\n\t0.27931903444745404, 0.30548078809939738, 0.33185334643681652,\n\t0.35845879325119373, 0.38532046640756762, 0.41246312944140484,\n\t0.43991316567323391, 0.46769879911450835, 0.49585034734745348,\n\t0.52440051270804111, 0.55338471955567303, 0.58284150727121620,\n\t0.61281299101662701, 0.64334540539291685, 0.67448975019608171,\n\t0.70630256284008752, 0.73884684918521371, 0.77219321418868492,\n\t0.80642124701824036, 0.84162123357291441, 0.87789629505122879,\n\t0.91536508784281423, 0.95416525314619460, 0.99445788320975348,\n\t1.03643338949378938, 1.08031934081495606, 1.12639112903880045,\n\t1.17498679206608991, 1.22652812003661049, 1.28155156554460081,\n\t1.34075503369021654, 1.40507156030963265, 1.47579102817917085,\n\t1.55477359459685394, 1.64485362695147308, 1.75068607125217102,\n\t1.88079360815125041, 2.05374891063182208, 2.32634787404084076\n};\n\nTEST_BEGIN(test_pt_norm)\n{\n\tunsigned i;\n\n\tfor (i = 1; i < sizeof(pt_norm_expected)/sizeof(double); i++) {\n\t\tdouble p = (double)i * 0.01;\n\t\tassert_true(double_eq_rel(pt_norm(p), pt_norm_expected[i],\n\t\t    MAX_REL_ERR, MAX_ABS_ERR),\n\t\t    \"Incorrect pt_norm result for i=%u\", i);\n\t}\n}\nTEST_END\n\n/*\n * Expected pt_chi2(p=[0.01..0.99] increment=0.07,\n *                  df={0.1, 1.1, 10.1, 100.1, 1000.1}).\n */\nstatic const double pt_chi2_df[] = {0.1, 1.1, 10.1, 100.1, 1000.1};\nstatic const double pt_chi2_expected[] = {\n\t1.168926411457320e-40, 1.347680397072034e-22, 3.886980416666260e-17,\n\t8.245951724356564e-14, 2.068936347497604e-11, 1.562561743309233e-09,\n\t5.459543043426564e-08, 1.114775688149252e-06, 1.532101202364371e-05,\n\t1.553884683726585e-04, 1.239396954915939e-03, 8.153872320255721e-03,\n\t4.631183739647523e-02, 2.473187311701327e-01, 2.175254800183617e+00,\n\n\t0.0003729887888876379, 0.0164409238228929513, 0.0521523015190650113,\n\t0.1064701372271216612, 0.1800913735793082115, 0.2748704281195626931,\n\t0.3939246282787986497, 0.5420727552260817816, 0.7267265822221973259,\n\t0.9596554296000253670, 1.2607440376386165326, 1.6671185084541604304,\n\t2.2604828984738705167, 3.2868613342148607082, 6.9298574921692139839,\n\n\t2.606673548632508, 4.602913725294877, 5.646152813924212,\n\t6.488971315540869, 7.249823275816285, 7.977314231410841,\n\t8.700354939944047, 9.441728024225892, 10.224338321374127,\n\t11.076435368801061, 12.039320937038386, 13.183878752697167,\n\t14.657791935084575, 16.885728216339373, 23.361991680031817,\n\n\t70.14844087392152, 80.92379498849355, 85.53325420085891,\n\t88.94433120715347, 91.83732712857017, 94.46719943606301,\n\t96.96896479994635, 99.43412843510363, 101.94074719829733,\n\t104.57228644307247, 107.43900093448734, 110.71844673417287,\n\t114.76616819871325, 120.57422505959563, 135.92318818757556,\n\n\t899.0072447849649, 937.9271278858220, 953.8117189560207,\n\t965.3079371501154, 974.8974061207954, 983.4936235182347,\n\t991.5691170518946, 999.4334123954690, 1007.3391826856553,\n\t1015.5445154999951, 1024.3777075619569, 1034.3538789836223,\n\t1046.4872561869577, 1063.5717461999654, 1107.0741966053859\n};\n\nTEST_BEGIN(test_pt_chi2)\n{\n\tunsigned i, j;\n\tunsigned e = 0;\n\n\tfor (i = 0; i < sizeof(pt_chi2_df)/sizeof(double); i++) {\n\t\tdouble df = pt_chi2_df[i];\n\t\tdouble ln_gamma_df = ln_gamma(df * 0.5);\n\t\tfor (j = 1; j < 100; j += 7) {\n\t\t\tdouble p = (double)j * 0.01;\n\t\t\tassert_true(double_eq_rel(pt_chi2(p, df, ln_gamma_df),\n\t\t\t    pt_chi2_expected[e], MAX_REL_ERR, MAX_ABS_ERR),\n\t\t\t    \"Incorrect pt_chi2 result for i=%u, j=%u\", i, j);\n\t\t\te++;\n\t\t}\n\t}\n}\nTEST_END\n\n/*\n * Expected pt_gamma(p=[0.1..0.99] increment=0.07,\n *                   shape=[0.5..3.0] increment=0.5).\n */\nstatic const double pt_gamma_shape[] = {0.5, 1.0, 1.5, 2.0, 2.5, 3.0};\nstatic const double pt_gamma_expected[] = {\n\t7.854392895485103e-05, 5.043466107888016e-03, 1.788288957794883e-02,\n\t3.900956150232906e-02, 6.913847560638034e-02, 1.093710833465766e-01,\n\t1.613412523825817e-01, 2.274682115597864e-01, 3.114117323127083e-01,\n\t4.189466220207417e-01, 5.598106789059246e-01, 7.521856146202706e-01,\n\t1.036125427911119e+00, 1.532450860038180e+00, 3.317448300510606e+00,\n\n\t0.01005033585350144, 0.08338160893905107, 0.16251892949777497,\n\t0.24846135929849966, 0.34249030894677596, 0.44628710262841947,\n\t0.56211891815354142, 0.69314718055994529, 0.84397007029452920,\n\t1.02165124753198167, 1.23787435600161766, 1.51412773262977574,\n\t1.89711998488588196, 2.52572864430825783, 4.60517018598809091,\n\n\t0.05741590094955853, 0.24747378084860744, 0.39888572212236084,\n\t0.54394139997444901, 0.69048812513915159, 0.84311389861296104,\n\t1.00580622221479898, 1.18298694218766931, 1.38038096305861213,\n\t1.60627736383027453, 1.87396970522337947, 2.20749220408081070,\n\t2.65852391865854942, 3.37934630984842244, 5.67243336507218476,\n\n\t0.1485547402532659, 0.4657458011640391, 0.6832386130709406,\n\t0.8794297834672100, 1.0700752852474524, 1.2629614217350744,\n\t1.4638400448580779, 1.6783469900166610, 1.9132338090606940,\n\t2.1778589228618777, 2.4868823970010991, 2.8664695666264195,\n\t3.3724415436062114, 4.1682658512758071, 6.6383520679938108,\n\n\t0.2771490383641385, 0.7195001279643727, 0.9969081732265243,\n\t1.2383497880608061, 1.4675206597269927, 1.6953064251816552,\n\t1.9291243435606809, 2.1757300955477641, 2.4428032131216391,\n\t2.7406534569230616, 3.0851445039665513, 3.5043101122033367,\n\t4.0575997065264637, 4.9182956424675286, 7.5431362346944937,\n\n\t0.4360451650782932, 0.9983600902486267, 1.3306365880734528,\n\t1.6129750834753802, 1.8767241606994294, 2.1357032436097660,\n\t2.3988853336865565, 2.6740603137235603, 2.9697561737517959,\n\t3.2971457713883265, 3.6731795898504660, 4.1275751617770631,\n\t4.7230515633946677, 5.6417477865306020, 8.4059469148854635\n};\n\nTEST_BEGIN(test_pt_gamma_shape)\n{\n\tunsigned i, j;\n\tunsigned e = 0;\n\n\tfor (i = 0; i < sizeof(pt_gamma_shape)/sizeof(double); i++) {\n\t\tdouble shape = pt_gamma_shape[i];\n\t\tdouble ln_gamma_shape = ln_gamma(shape);\n\t\tfor (j = 1; j < 100; j += 7) {\n\t\t\tdouble p = (double)j * 0.01;\n\t\t\tassert_true(double_eq_rel(pt_gamma(p, shape, 1.0,\n\t\t\t    ln_gamma_shape), pt_gamma_expected[e], MAX_REL_ERR,\n\t\t\t    MAX_ABS_ERR),\n\t\t\t    \"Incorrect pt_gamma result for i=%u, j=%u\", i, j);\n\t\t\te++;\n\t\t}\n\t}\n}\nTEST_END\n\nTEST_BEGIN(test_pt_gamma_scale)\n{\n\tdouble shape = 1.0;\n\tdouble ln_gamma_shape = ln_gamma(shape);\n\n\tassert_true(double_eq_rel(\n\t    pt_gamma(0.5, shape, 1.0, ln_gamma_shape) * 10.0,\n\t    pt_gamma(0.5, shape, 10.0, ln_gamma_shape), MAX_REL_ERR,\n\t    MAX_ABS_ERR),\n\t    \"Scale should be trivially equivalent to external multiplication\");\n}\nTEST_END\n\nint\nmain(void)\n{\n\n\treturn (test(\n\t    test_ln_gamma_factorial,\n\t    test_ln_gamma_misc,\n\t    test_pt_norm,\n\t    test_pt_chi2,\n\t    test_pt_gamma_shape,\n\t    test_pt_gamma_scale));\n}\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.8/deps/jemalloc/test/unit/mq.c",
    "content": "#include \"test/jemalloc_test.h\"\n\n#define\tNSENDERS\t3\n#define\tNMSGS\t\t100000\n\ntypedef struct mq_msg_s mq_msg_t;\nstruct mq_msg_s {\n\tmq_msg(mq_msg_t)\tlink;\n};\nmq_gen(static, mq_, mq_t, mq_msg_t, link)\n\nTEST_BEGIN(test_mq_basic)\n{\n\tmq_t mq;\n\tmq_msg_t msg;\n\n\tassert_false(mq_init(&mq), \"Unexpected mq_init() failure\");\n\tassert_u_eq(mq_count(&mq), 0, \"mq should be empty\");\n\tassert_ptr_null(mq_tryget(&mq),\n\t    \"mq_tryget() should fail when the queue is empty\");\n\n\tmq_put(&mq, &msg);\n\tassert_u_eq(mq_count(&mq), 1, \"mq should contain one message\");\n\tassert_ptr_eq(mq_tryget(&mq), &msg, \"mq_tryget() should return msg\");\n\n\tmq_put(&mq, &msg);\n\tassert_ptr_eq(mq_get(&mq), &msg, \"mq_get() should return msg\");\n\n\tmq_fini(&mq);\n}\nTEST_END\n\nstatic void *\nthd_receiver_start(void *arg)\n{\n\tmq_t *mq = (mq_t *)arg;\n\tunsigned i;\n\n\tfor (i = 0; i < (NSENDERS * NMSGS); i++) {\n\t\tmq_msg_t *msg = mq_get(mq);\n\t\tassert_ptr_not_null(msg, \"mq_get() should never return NULL\");\n\t\tdallocx(msg, 0);\n\t}\n\treturn (NULL);\n}\n\nstatic void *\nthd_sender_start(void *arg)\n{\n\tmq_t *mq = (mq_t *)arg;\n\tunsigned i;\n\n\tfor (i = 0; i < NMSGS; i++) {\n\t\tmq_msg_t *msg;\n\t\tvoid *p;\n\t\tp = mallocx(sizeof(mq_msg_t), 0);\n\t\tassert_ptr_not_null(p, \"Unexpected mallocx() failure\");\n\t\tmsg = (mq_msg_t *)p;\n\t\tmq_put(mq, msg);\n\t}\n\treturn (NULL);\n}\n\nTEST_BEGIN(test_mq_threaded)\n{\n\tmq_t mq;\n\tthd_t receiver;\n\tthd_t senders[NSENDERS];\n\tunsigned i;\n\n\tassert_false(mq_init(&mq), \"Unexpected mq_init() failure\");\n\n\tthd_create(&receiver, thd_receiver_start, (void *)&mq);\n\tfor (i = 0; i < NSENDERS; i++)\n\t\tthd_create(&senders[i], thd_sender_start, (void *)&mq);\n\n\tthd_join(receiver, NULL);\n\tfor (i = 0; i < NSENDERS; i++)\n\t\tthd_join(senders[i], NULL);\n\n\tmq_fini(&mq);\n}\nTEST_END\n\nint\nmain(void)\n{\n\n\treturn (test(\n\t    test_mq_basic,\n\t    test_mq_threaded));\n}\n\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.8/deps/jemalloc/test/unit/mtx.c",
    "content": "#include \"test/jemalloc_test.h\"\n\n#define\tNTHREADS\t2\n#define\tNINCRS\t\t2000000\n\nTEST_BEGIN(test_mtx_basic)\n{\n\tmtx_t mtx;\n\n\tassert_false(mtx_init(&mtx), \"Unexpected mtx_init() failure\");\n\tmtx_lock(&mtx);\n\tmtx_unlock(&mtx);\n\tmtx_fini(&mtx);\n}\nTEST_END\n\ntypedef struct {\n\tmtx_t\t\tmtx;\n\tunsigned\tx;\n} thd_start_arg_t;\n\nstatic void *\nthd_start(void *varg)\n{\n\tthd_start_arg_t *arg = (thd_start_arg_t *)varg;\n\tunsigned i;\n\n\tfor (i = 0; i < NINCRS; i++) {\n\t\tmtx_lock(&arg->mtx);\n\t\targ->x++;\n\t\tmtx_unlock(&arg->mtx);\n\t}\n\treturn (NULL);\n}\n\nTEST_BEGIN(test_mtx_race)\n{\n\tthd_start_arg_t arg;\n\tthd_t thds[NTHREADS];\n\tunsigned i;\n\n\tassert_false(mtx_init(&arg.mtx), \"Unexpected mtx_init() failure\");\n\targ.x = 0;\n\tfor (i = 0; i < NTHREADS; i++)\n\t\tthd_create(&thds[i], thd_start, (void *)&arg);\n\tfor (i = 0; i < NTHREADS; i++)\n\t\tthd_join(thds[i], NULL);\n\tassert_u_eq(arg.x, NTHREADS * NINCRS,\n\t    \"Race-related counter corruption\");\n}\nTEST_END\n\nint\nmain(void)\n{\n\n\treturn (test(\n\t    test_mtx_basic,\n\t    test_mtx_race));\n}\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.8/deps/jemalloc/test/unit/prof_accum.c",
    "content": "#include \"test/jemalloc_test.h\"\n\n#define\tNTHREADS\t\t4\n#define\tNALLOCS_PER_THREAD\t50\n#define\tDUMP_INTERVAL\t\t1\n#define\tBT_COUNT_CHECK_INTERVAL\t5\n\n#ifdef JEMALLOC_PROF\nconst char *malloc_conf =\n    \"prof:true,prof_accum:true,prof_active:false,lg_prof_sample:0\";\n#endif\n\nstatic int\nprof_dump_open_intercept(bool propagate_err, const char *filename)\n{\n\tint fd;\n\n\tfd = open(\"/dev/null\", O_WRONLY);\n\tassert_d_ne(fd, -1, \"Unexpected open() failure\");\n\n\treturn (fd);\n}\n\nstatic void *\nalloc_from_permuted_backtrace(unsigned thd_ind, unsigned iteration)\n{\n\n\treturn (btalloc(1, thd_ind*NALLOCS_PER_THREAD + iteration));\n}\n\nstatic void *\nthd_start(void *varg)\n{\n\tunsigned thd_ind = *(unsigned *)varg;\n\tsize_t bt_count_prev, bt_count;\n\tunsigned i_prev, i;\n\n\ti_prev = 0;\n\tbt_count_prev = 0;\n\tfor (i = 0; i < NALLOCS_PER_THREAD; i++) {\n\t\tvoid *p = alloc_from_permuted_backtrace(thd_ind, i);\n\t\tdallocx(p, 0);\n\t\tif (i % DUMP_INTERVAL == 0) {\n\t\t\tassert_d_eq(mallctl(\"prof.dump\", NULL, NULL, NULL, 0),\n\t\t\t    0, \"Unexpected error while dumping heap profile\");\n\t\t}\n\n\t\tif (i % BT_COUNT_CHECK_INTERVAL == 0 ||\n\t\t    i+1 == NALLOCS_PER_THREAD) {\n\t\t\tbt_count = prof_bt_count();\n\t\t\tassert_zu_le(bt_count_prev+(i-i_prev), bt_count,\n\t\t\t    \"Expected larger backtrace count increase\");\n\t\t\ti_prev = i;\n\t\t\tbt_count_prev = bt_count;\n\t\t}\n\t}\n\n\treturn (NULL);\n}\n\nTEST_BEGIN(test_idump)\n{\n\tbool active;\n\tthd_t thds[NTHREADS];\n\tunsigned thd_args[NTHREADS];\n\tunsigned i;\n\n\ttest_skip_if(!config_prof);\n\n\tactive = true;\n\tassert_d_eq(mallctl(\"prof.active\", NULL, NULL, &active, sizeof(active)),\n\t    0, \"Unexpected mallctl failure while activating profiling\");\n\n\tprof_dump_open = prof_dump_open_intercept;\n\n\tfor (i = 0; i < NTHREADS; i++) {\n\t\tthd_args[i] = i;\n\t\tthd_create(&thds[i], thd_start, (void *)&thd_args[i]);\n\t}\n\tfor (i = 0; i < NTHREADS; i++)\n\t\tthd_join(thds[i], NULL);\n}\nTEST_END\n\nint\nmain(void)\n{\n\n\treturn (test(\n\t    test_idump));\n}\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.8/deps/jemalloc/test/unit/prof_active.c",
    "content": "#include \"test/jemalloc_test.h\"\n\n#ifdef JEMALLOC_PROF\nconst char *malloc_conf =\n    \"prof:true,prof_thread_active_init:false,lg_prof_sample:0\";\n#endif\n\nstatic void\nmallctl_bool_get(const char *name, bool expected, const char *func, int line)\n{\n\tbool old;\n\tsize_t sz;\n\n\tsz = sizeof(old);\n\tassert_d_eq(mallctl(name, &old, &sz, NULL, 0), 0,\n\t    \"%s():%d: Unexpected mallctl failure reading %s\", func, line, name);\n\tassert_b_eq(old, expected, \"%s():%d: Unexpected %s value\", func, line,\n\t    name);\n}\n\nstatic void\nmallctl_bool_set(const char *name, bool old_expected, bool val_new,\n    const char *func, int line)\n{\n\tbool old;\n\tsize_t sz;\n\n\tsz = sizeof(old);\n\tassert_d_eq(mallctl(name, &old, &sz, &val_new, sizeof(val_new)), 0,\n\t    \"%s():%d: Unexpected mallctl failure reading/writing %s\", func,\n\t    line, name);\n\tassert_b_eq(old, old_expected, \"%s():%d: Unexpected %s value\", func,\n\t    line, name);\n}\n\nstatic void\nmallctl_prof_active_get_impl(bool prof_active_old_expected, const char *func,\n    int line)\n{\n\n\tmallctl_bool_get(\"prof.active\", prof_active_old_expected, func, line);\n}\n#define\tmallctl_prof_active_get(a)\t\t\t\t\t\\\n\tmallctl_prof_active_get_impl(a, __func__, __LINE__)\n\nstatic void\nmallctl_prof_active_set_impl(bool prof_active_old_expected,\n    bool prof_active_new, const char *func, int line)\n{\n\n\tmallctl_bool_set(\"prof.active\", prof_active_old_expected,\n\t    prof_active_new, func, line);\n}\n#define\tmallctl_prof_active_set(a, b)\t\t\t\t\t\\\n\tmallctl_prof_active_set_impl(a, b, __func__, __LINE__)\n\nstatic void\nmallctl_thread_prof_active_get_impl(bool thread_prof_active_old_expected,\n    const char *func, int line)\n{\n\n\tmallctl_bool_get(\"thread.prof.active\", thread_prof_active_old_expected,\n\t    func, line);\n}\n#define\tmallctl_thread_prof_active_get(a)\t\t\t\t\\\n\tmallctl_thread_prof_active_get_impl(a, __func__, __LINE__)\n\nstatic void\nmallctl_thread_prof_active_set_impl(bool thread_prof_active_old_expected,\n    bool thread_prof_active_new, const char *func, int line)\n{\n\n\tmallctl_bool_set(\"thread.prof.active\", thread_prof_active_old_expected,\n\t    thread_prof_active_new, func, line);\n}\n#define\tmallctl_thread_prof_active_set(a, b)\t\t\t\t\\\n\tmallctl_thread_prof_active_set_impl(a, b, __func__, __LINE__)\n\nstatic void\nprof_sampling_probe_impl(bool expect_sample, const char *func, int line)\n{\n\tvoid *p;\n\tsize_t expected_backtraces = expect_sample ? 1 : 0;\n\n\tassert_zu_eq(prof_bt_count(), 0, \"%s():%d: Expected 0 backtraces\", func,\n\t    line);\n\tp = mallocx(1, 0);\n\tassert_ptr_not_null(p, \"Unexpected mallocx() failure\");\n\tassert_zu_eq(prof_bt_count(), expected_backtraces,\n\t    \"%s():%d: Unexpected backtrace count\", func, line);\n\tdallocx(p, 0);\n}\n#define\tprof_sampling_probe(a)\t\t\t\t\t\t\\\n\tprof_sampling_probe_impl(a, __func__, __LINE__)\n\nTEST_BEGIN(test_prof_active)\n{\n\n\ttest_skip_if(!config_prof);\n\n\tmallctl_prof_active_get(true);\n\tmallctl_thread_prof_active_get(false);\n\n\tmallctl_prof_active_set(true, true);\n\tmallctl_thread_prof_active_set(false, false);\n\t/* prof.active, !thread.prof.active. */\n\tprof_sampling_probe(false);\n\n\tmallctl_prof_active_set(true, false);\n\tmallctl_thread_prof_active_set(false, false);\n\t/* !prof.active, !thread.prof.active. */\n\tprof_sampling_probe(false);\n\n\tmallctl_prof_active_set(false, false);\n\tmallctl_thread_prof_active_set(false, true);\n\t/* !prof.active, thread.prof.active. */\n\tprof_sampling_probe(false);\n\n\tmallctl_prof_active_set(false, true);\n\tmallctl_thread_prof_active_set(true, true);\n\t/* prof.active, thread.prof.active. */\n\tprof_sampling_probe(true);\n\n\t/* Restore settings. */\n\tmallctl_prof_active_set(true, true);\n\tmallctl_thread_prof_active_set(true, false);\n}\nTEST_END\n\nint\nmain(void)\n{\n\n\treturn (test(\n\t    test_prof_active));\n}\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.8/deps/jemalloc/test/unit/prof_gdump.c",
    "content": "#include \"test/jemalloc_test.h\"\n\n#ifdef JEMALLOC_PROF\nconst char *malloc_conf = \"prof:true,prof_active:false,prof_gdump:true\";\n#endif\n\nstatic bool did_prof_dump_open;\n\nstatic int\nprof_dump_open_intercept(bool propagate_err, const char *filename)\n{\n\tint fd;\n\n\tdid_prof_dump_open = true;\n\n\tfd = open(\"/dev/null\", O_WRONLY);\n\tassert_d_ne(fd, -1, \"Unexpected open() failure\");\n\n\treturn (fd);\n}\n\nTEST_BEGIN(test_gdump)\n{\n\tbool active, gdump, gdump_old;\n\tvoid *p, *q, *r, *s;\n\tsize_t sz;\n\n\ttest_skip_if(!config_prof);\n\n\tactive = true;\n\tassert_d_eq(mallctl(\"prof.active\", NULL, NULL, &active, sizeof(active)),\n\t    0, \"Unexpected mallctl failure while activating profiling\");\n\n\tprof_dump_open = prof_dump_open_intercept;\n\n\tdid_prof_dump_open = false;\n\tp = mallocx(chunksize, 0);\n\tassert_ptr_not_null(p, \"Unexpected mallocx() failure\");\n\tassert_true(did_prof_dump_open, \"Expected a profile dump\");\n\n\tdid_prof_dump_open = false;\n\tq = mallocx(chunksize, 0);\n\tassert_ptr_not_null(q, \"Unexpected mallocx() failure\");\n\tassert_true(did_prof_dump_open, \"Expected a profile dump\");\n\n\tgdump = false;\n\tsz = sizeof(gdump_old);\n\tassert_d_eq(mallctl(\"prof.gdump\", &gdump_old, &sz, &gdump,\n\t    sizeof(gdump)), 0,\n\t    \"Unexpected mallctl failure while disabling prof.gdump\");\n\tassert(gdump_old);\n\tdid_prof_dump_open = false;\n\tr = mallocx(chunksize, 0);\n\tassert_ptr_not_null(q, \"Unexpected mallocx() failure\");\n\tassert_false(did_prof_dump_open, \"Unexpected profile dump\");\n\n\tgdump = true;\n\tsz = sizeof(gdump_old);\n\tassert_d_eq(mallctl(\"prof.gdump\", &gdump_old, &sz, &gdump,\n\t    sizeof(gdump)), 0,\n\t    \"Unexpected mallctl failure while enabling prof.gdump\");\n\tassert(!gdump_old);\n\tdid_prof_dump_open = false;\n\ts = mallocx(chunksize, 0);\n\tassert_ptr_not_null(q, \"Unexpected mallocx() failure\");\n\tassert_true(did_prof_dump_open, \"Expected a profile dump\");\n\n\tdallocx(p, 0);\n\tdallocx(q, 0);\n\tdallocx(r, 0);\n\tdallocx(s, 0);\n}\nTEST_END\n\nint\nmain(void)\n{\n\n\treturn (test(\n\t    test_gdump));\n}\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.8/deps/jemalloc/test/unit/prof_idump.c",
    "content": "#include \"test/jemalloc_test.h\"\n\n#ifdef JEMALLOC_PROF\nconst char *malloc_conf =\n    \"prof:true,prof_accum:true,prof_active:false,lg_prof_sample:0,\"\n    \"lg_prof_interval:0\";\n#endif\n\nstatic bool did_prof_dump_open;\n\nstatic int\nprof_dump_open_intercept(bool propagate_err, const char *filename)\n{\n\tint fd;\n\n\tdid_prof_dump_open = true;\n\n\tfd = open(\"/dev/null\", O_WRONLY);\n\tassert_d_ne(fd, -1, \"Unexpected open() failure\");\n\n\treturn (fd);\n}\n\nTEST_BEGIN(test_idump)\n{\n\tbool active;\n\tvoid *p;\n\n\ttest_skip_if(!config_prof);\n\n\tactive = true;\n\tassert_d_eq(mallctl(\"prof.active\", NULL, NULL, &active, sizeof(active)),\n\t    0, \"Unexpected mallctl failure while activating profiling\");\n\n\tprof_dump_open = prof_dump_open_intercept;\n\n\tdid_prof_dump_open = false;\n\tp = mallocx(1, 0);\n\tassert_ptr_not_null(p, \"Unexpected mallocx() failure\");\n\tdallocx(p, 0);\n\tassert_true(did_prof_dump_open, \"Expected a profile dump\");\n}\nTEST_END\n\nint\nmain(void)\n{\n\n\treturn (test(\n\t    test_idump));\n}\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.8/deps/jemalloc/test/unit/prof_reset.c",
    "content": "#include \"test/jemalloc_test.h\"\n\n#ifdef JEMALLOC_PROF\nconst char *malloc_conf =\n    \"prof:true,prof_active:false,lg_prof_sample:0\";\n#endif\n\nstatic int\nprof_dump_open_intercept(bool propagate_err, const char *filename)\n{\n\tint fd;\n\n\tfd = open(\"/dev/null\", O_WRONLY);\n\tassert_d_ne(fd, -1, \"Unexpected open() failure\");\n\n\treturn (fd);\n}\n\nstatic void\nset_prof_active(bool active)\n{\n\n\tassert_d_eq(mallctl(\"prof.active\", NULL, NULL, &active, sizeof(active)),\n\t    0, \"Unexpected mallctl failure\");\n}\n\nstatic size_t\nget_lg_prof_sample(void)\n{\n\tsize_t lg_prof_sample;\n\tsize_t sz = sizeof(size_t);\n\n\tassert_d_eq(mallctl(\"prof.lg_sample\", &lg_prof_sample, &sz, NULL, 0), 0,\n\t    \"Unexpected mallctl failure while reading profiling sample rate\");\n\treturn (lg_prof_sample);\n}\n\nstatic void\ndo_prof_reset(size_t lg_prof_sample)\n{\n\tassert_d_eq(mallctl(\"prof.reset\", NULL, NULL,\n\t    &lg_prof_sample, sizeof(size_t)), 0,\n\t    \"Unexpected mallctl failure while resetting profile data\");\n\tassert_zu_eq(lg_prof_sample, get_lg_prof_sample(),\n\t    \"Expected profile sample rate change\");\n}\n\nTEST_BEGIN(test_prof_reset_basic)\n{\n\tsize_t lg_prof_sample_orig, lg_prof_sample, lg_prof_sample_next;\n\tsize_t sz;\n\tunsigned i;\n\n\ttest_skip_if(!config_prof);\n\n\tsz = sizeof(size_t);\n\tassert_d_eq(mallctl(\"opt.lg_prof_sample\", &lg_prof_sample_orig, &sz,\n\t    NULL, 0), 0,\n\t    \"Unexpected mallctl failure while reading profiling sample rate\");\n\tassert_zu_eq(lg_prof_sample_orig, 0,\n\t    \"Unexpected profiling sample rate\");\n\tlg_prof_sample = get_lg_prof_sample();\n\tassert_zu_eq(lg_prof_sample_orig, lg_prof_sample,\n\t    \"Unexpected disagreement between \\\"opt.lg_prof_sample\\\" and \"\n\t    \"\\\"prof.lg_sample\\\"\");\n\n\t/* Test simple resets. */\n\tfor (i = 0; i < 2; i++) {\n\t\tassert_d_eq(mallctl(\"prof.reset\", NULL, NULL, NULL, 0), 0,\n\t\t    \"Unexpected mallctl failure while resetting profile data\");\n\t\tlg_prof_sample = get_lg_prof_sample();\n\t\tassert_zu_eq(lg_prof_sample_orig, lg_prof_sample,\n\t\t    \"Unexpected profile sample rate change\");\n\t}\n\n\t/* Test resets with prof.lg_sample changes. */\n\tlg_prof_sample_next = 1;\n\tfor (i = 0; i < 2; i++) {\n\t\tdo_prof_reset(lg_prof_sample_next);\n\t\tlg_prof_sample = get_lg_prof_sample();\n\t\tassert_zu_eq(lg_prof_sample, lg_prof_sample_next,\n\t\t    \"Expected profile sample rate change\");\n\t\tlg_prof_sample_next = lg_prof_sample_orig;\n\t}\n\n\t/* Make sure the test code restored prof.lg_sample. */\n\tlg_prof_sample = get_lg_prof_sample();\n\tassert_zu_eq(lg_prof_sample_orig, lg_prof_sample,\n\t    \"Unexpected disagreement between \\\"opt.lg_prof_sample\\\" and \"\n\t    \"\\\"prof.lg_sample\\\"\");\n}\nTEST_END\n\nbool prof_dump_header_intercepted = false;\nprof_cnt_t cnt_all_copy = {0, 0, 0, 0};\nstatic bool\nprof_dump_header_intercept(bool propagate_err, const prof_cnt_t *cnt_all)\n{\n\n\tprof_dump_header_intercepted = true;\n\tmemcpy(&cnt_all_copy, cnt_all, sizeof(prof_cnt_t));\n\n\treturn (false);\n}\n\nTEST_BEGIN(test_prof_reset_cleanup)\n{\n\tvoid *p;\n\tprof_dump_header_t *prof_dump_header_orig;\n\n\ttest_skip_if(!config_prof);\n\n\tset_prof_active(true);\n\n\tassert_zu_eq(prof_bt_count(), 0, \"Expected 0 backtraces\");\n\tp = mallocx(1, 0);\n\tassert_ptr_not_null(p, \"Unexpected mallocx() failure\");\n\tassert_zu_eq(prof_bt_count(), 1, \"Expected 1 backtrace\");\n\n\tprof_dump_header_orig = prof_dump_header;\n\tprof_dump_header = prof_dump_header_intercept;\n\tassert_false(prof_dump_header_intercepted, \"Unexpected intercept\");\n\n\tassert_d_eq(mallctl(\"prof.dump\", NULL, NULL, NULL, 0),\n\t    0, \"Unexpected error while dumping heap profile\");\n\tassert_true(prof_dump_header_intercepted, \"Expected intercept\");\n\tassert_u64_eq(cnt_all_copy.curobjs, 1, \"Expected 1 allocation\");\n\n\tassert_d_eq(mallctl(\"prof.reset\", NULL, NULL, NULL, 0), 0,\n\t    \"Unexpected error while resetting heap profile data\");\n\tassert_d_eq(mallctl(\"prof.dump\", NULL, NULL, NULL, 0),\n\t    0, \"Unexpected error while dumping heap profile\");\n\tassert_u64_eq(cnt_all_copy.curobjs, 0, \"Expected 0 allocations\");\n\tassert_zu_eq(prof_bt_count(), 1, \"Expected 1 backtrace\");\n\n\tprof_dump_header = prof_dump_header_orig;\n\n\tdallocx(p, 0);\n\tassert_zu_eq(prof_bt_count(), 0, \"Expected 0 backtraces\");\n\n\tset_prof_active(false);\n}\nTEST_END\n\n#define\tNTHREADS\t\t4\n#define\tNALLOCS_PER_THREAD\t(1U << 13)\n#define\tOBJ_RING_BUF_COUNT\t1531\n#define\tRESET_INTERVAL\t\t(1U << 10)\n#define\tDUMP_INTERVAL\t\t3677\nstatic void *\nthd_start(void *varg)\n{\n\tunsigned thd_ind = *(unsigned *)varg;\n\tunsigned i;\n\tvoid *objs[OBJ_RING_BUF_COUNT];\n\n\tmemset(objs, 0, sizeof(objs));\n\n\tfor (i = 0; i < NALLOCS_PER_THREAD; i++) {\n\t\tif (i % RESET_INTERVAL == 0) {\n\t\t\tassert_d_eq(mallctl(\"prof.reset\", NULL, NULL, NULL, 0),\n\t\t\t    0, \"Unexpected error while resetting heap profile \"\n\t\t\t    \"data\");\n\t\t}\n\n\t\tif (i % DUMP_INTERVAL == 0) {\n\t\t\tassert_d_eq(mallctl(\"prof.dump\", NULL, NULL, NULL, 0),\n\t\t\t    0, \"Unexpected error while dumping heap profile\");\n\t\t}\n\n\t\t{\n\t\t\tvoid **pp = &objs[i % OBJ_RING_BUF_COUNT];\n\t\t\tif (*pp != NULL) {\n\t\t\t\tdallocx(*pp, 0);\n\t\t\t\t*pp = NULL;\n\t\t\t}\n\t\t\t*pp = btalloc(1, thd_ind*NALLOCS_PER_THREAD + i);\n\t\t\tassert_ptr_not_null(*pp,\n\t\t\t    \"Unexpected btalloc() failure\");\n\t\t}\n\t}\n\n\t/* Clean up any remaining objects. */\n\tfor (i = 0; i < OBJ_RING_BUF_COUNT; i++) {\n\t\tvoid **pp = &objs[i % OBJ_RING_BUF_COUNT];\n\t\tif (*pp != NULL) {\n\t\t\tdallocx(*pp, 0);\n\t\t\t*pp = NULL;\n\t\t}\n\t}\n\n\treturn (NULL);\n}\n\nTEST_BEGIN(test_prof_reset)\n{\n\tsize_t lg_prof_sample_orig;\n\tthd_t thds[NTHREADS];\n\tunsigned thd_args[NTHREADS];\n\tunsigned i;\n\tsize_t bt_count, tdata_count;\n\n\ttest_skip_if(!config_prof);\n\n\tbt_count = prof_bt_count();\n\tassert_zu_eq(bt_count, 0,\n\t    \"Unexpected pre-existing tdata structures\");\n\ttdata_count = prof_tdata_count();\n\n\tlg_prof_sample_orig = get_lg_prof_sample();\n\tdo_prof_reset(5);\n\n\tset_prof_active(true);\n\n\tfor (i = 0; i < NTHREADS; i++) {\n\t\tthd_args[i] = i;\n\t\tthd_create(&thds[i], thd_start, (void *)&thd_args[i]);\n\t}\n\tfor (i = 0; i < NTHREADS; i++)\n\t\tthd_join(thds[i], NULL);\n\n\tassert_zu_eq(prof_bt_count(), bt_count,\n\t    \"Unexpected bactrace count change\");\n\tassert_zu_eq(prof_tdata_count(), tdata_count,\n\t    \"Unexpected remaining tdata structures\");\n\n\tset_prof_active(false);\n\n\tdo_prof_reset(lg_prof_sample_orig);\n}\nTEST_END\n#undef NTHREADS\n#undef NALLOCS_PER_THREAD\n#undef OBJ_RING_BUF_COUNT\n#undef RESET_INTERVAL\n#undef DUMP_INTERVAL\n\n/* Test sampling at the same allocation site across resets. */\n#define\tNITER 10\nTEST_BEGIN(test_xallocx)\n{\n\tsize_t lg_prof_sample_orig;\n\tunsigned i;\n\tvoid *ptrs[NITER];\n\n\ttest_skip_if(!config_prof);\n\n\tlg_prof_sample_orig = get_lg_prof_sample();\n\tset_prof_active(true);\n\n\t/* Reset profiling. */\n\tdo_prof_reset(0);\n\n\tfor (i = 0; i < NITER; i++) {\n\t\tvoid *p;\n\t\tsize_t sz, nsz;\n\n\t\t/* Reset profiling. */\n\t\tdo_prof_reset(0);\n\n\t\t/* Allocate small object (which will be promoted). */\n\t\tp = ptrs[i] = mallocx(1, 0);\n\t\tassert_ptr_not_null(p, \"Unexpected mallocx() failure\");\n\n\t\t/* Reset profiling. */\n\t\tdo_prof_reset(0);\n\n\t\t/* Perform successful xallocx(). */\n\t\tsz = sallocx(p, 0);\n\t\tassert_zu_eq(xallocx(p, sz, 0, 0), sz,\n\t\t    \"Unexpected xallocx() failure\");\n\n\t\t/* Perform unsuccessful xallocx(). */\n\t\tnsz = nallocx(sz+1, 0);\n\t\tassert_zu_eq(xallocx(p, nsz, 0, 0), sz,\n\t\t    \"Unexpected xallocx() success\");\n\t}\n\n\tfor (i = 0; i < NITER; i++) {\n\t\t/* dallocx. */\n\t\tdallocx(ptrs[i], 0);\n\t}\n\n\tset_prof_active(false);\n\tdo_prof_reset(lg_prof_sample_orig);\n}\nTEST_END\n#undef NITER\n\nint\nmain(void)\n{\n\n\t/* Intercept dumping prior to running any tests. */\n\tprof_dump_open = prof_dump_open_intercept;\n\n\treturn (test(\n\t    test_prof_reset_basic,\n\t    test_prof_reset_cleanup,\n\t    test_prof_reset,\n\t    test_xallocx));\n}\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.8/deps/jemalloc/test/unit/prof_thread_name.c",
    "content": "#include \"test/jemalloc_test.h\"\n\n#ifdef JEMALLOC_PROF\nconst char *malloc_conf = \"prof:true,prof_active:false\";\n#endif\n\nstatic void\nmallctl_thread_name_get_impl(const char *thread_name_expected, const char *func,\n    int line)\n{\n\tconst char *thread_name_old;\n\tsize_t sz;\n\n\tsz = sizeof(thread_name_old);\n\tassert_d_eq(mallctl(\"thread.prof.name\", &thread_name_old, &sz, NULL, 0),\n\t    0, \"%s():%d: Unexpected mallctl failure reading thread.prof.name\",\n\t    func, line);\n\tassert_str_eq(thread_name_old, thread_name_expected,\n\t    \"%s():%d: Unexpected thread.prof.name value\", func, line);\n}\n#define\tmallctl_thread_name_get(a)\t\t\t\t\t\\\n\tmallctl_thread_name_get_impl(a, __func__, __LINE__)\n\nstatic void\nmallctl_thread_name_set_impl(const char *thread_name, const char *func,\n    int line)\n{\n\n\tassert_d_eq(mallctl(\"thread.prof.name\", NULL, NULL, &thread_name,\n\t    sizeof(thread_name)), 0,\n\t    \"%s():%d: Unexpected mallctl failure reading thread.prof.name\",\n\t    func, line);\n\tmallctl_thread_name_get_impl(thread_name, func, line);\n}\n#define\tmallctl_thread_name_set(a)\t\t\t\t\t\\\n\tmallctl_thread_name_set_impl(a, __func__, __LINE__)\n\nTEST_BEGIN(test_prof_thread_name_validation)\n{\n\tconst char *thread_name;\n\n\ttest_skip_if(!config_prof);\n\n\tmallctl_thread_name_get(\"\");\n\tmallctl_thread_name_set(\"hi there\");\n\n\t/* NULL input shouldn't be allowed. */\n\tthread_name = NULL;\n\tassert_d_eq(mallctl(\"thread.prof.name\", NULL, NULL, &thread_name,\n\t    sizeof(thread_name)), EFAULT,\n\t    \"Unexpected mallctl result writing \\\"%s\\\" to thread.prof.name\",\n\t    thread_name);\n\n\t/* '\\n' shouldn't be allowed. */\n\tthread_name = \"hi\\nthere\";\n\tassert_d_eq(mallctl(\"thread.prof.name\", NULL, NULL, &thread_name,\n\t    sizeof(thread_name)), EFAULT,\n\t    \"Unexpected mallctl result writing \\\"%s\\\" to thread.prof.name\",\n\t    thread_name);\n\n\t/* Simultaneous read/write shouldn't be allowed. */\n\t{\n\t\tconst char *thread_name_old;\n\t\tsize_t sz;\n\n\t\tsz = sizeof(thread_name_old);\n\t\tassert_d_eq(mallctl(\"thread.prof.name\", &thread_name_old, &sz,\n\t\t    &thread_name, sizeof(thread_name)), EPERM,\n\t\t    \"Unexpected mallctl result writing \\\"%s\\\" to \"\n\t\t    \"thread.prof.name\", thread_name);\n\t}\n\n\tmallctl_thread_name_set(\"\");\n}\nTEST_END\n\n#define\tNTHREADS\t4\n#define\tNRESET\t\t25\nstatic void *\nthd_start(void *varg)\n{\n\tunsigned thd_ind = *(unsigned *)varg;\n\tchar thread_name[16] = \"\";\n\tunsigned i;\n\n\tmalloc_snprintf(thread_name, sizeof(thread_name), \"thread %u\", thd_ind);\n\n\tmallctl_thread_name_get(\"\");\n\tmallctl_thread_name_set(thread_name);\n\n\tfor (i = 0; i < NRESET; i++) {\n\t\tassert_d_eq(mallctl(\"prof.reset\", NULL, NULL, NULL, 0), 0,\n\t\t    \"Unexpected error while resetting heap profile data\");\n\t\tmallctl_thread_name_get(thread_name);\n\t}\n\n\tmallctl_thread_name_set(thread_name);\n\tmallctl_thread_name_set(\"\");\n\n\treturn (NULL);\n}\n\nTEST_BEGIN(test_prof_thread_name_threaded)\n{\n\tthd_t thds[NTHREADS];\n\tunsigned thd_args[NTHREADS];\n\tunsigned i;\n\n\ttest_skip_if(!config_prof);\n\n\tfor (i = 0; i < NTHREADS; i++) {\n\t\tthd_args[i] = i;\n\t\tthd_create(&thds[i], thd_start, (void *)&thd_args[i]);\n\t}\n\tfor (i = 0; i < NTHREADS; i++)\n\t\tthd_join(thds[i], NULL);\n}\nTEST_END\n#undef NTHREADS\n#undef NRESET\n\nint\nmain(void)\n{\n\n\treturn (test(\n\t    test_prof_thread_name_validation,\n\t    test_prof_thread_name_threaded));\n}\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.8/deps/jemalloc/test/unit/ql.c",
    "content": "#include \"test/jemalloc_test.h\"\n\n/* Number of ring entries, in [2..26]. */\n#define\tNENTRIES 9\n\ntypedef struct list_s list_t;\ntypedef ql_head(list_t) list_head_t;\n\nstruct list_s {\n\tql_elm(list_t) link;\n\tchar id;\n};\n\nstatic void\ntest_empty_list(list_head_t *head)\n{\n\tlist_t *t;\n\tunsigned i;\n\n\tassert_ptr_null(ql_first(head), \"Unexpected element for empty list\");\n\tassert_ptr_null(ql_last(head, link),\n\t    \"Unexpected element for empty list\");\n\n\ti = 0;\n\tql_foreach(t, head, link) {\n\t\ti++;\n\t}\n\tassert_u_eq(i, 0, \"Unexpected element for empty list\");\n\n\ti = 0;\n\tql_reverse_foreach(t, head, link) {\n\t\ti++;\n\t}\n\tassert_u_eq(i, 0, \"Unexpected element for empty list\");\n}\n\nTEST_BEGIN(test_ql_empty)\n{\n\tlist_head_t head;\n\n\tql_new(&head);\n\ttest_empty_list(&head);\n}\nTEST_END\n\nstatic void\ninit_entries(list_t *entries, unsigned nentries)\n{\n\tunsigned i;\n\n\tfor (i = 0; i < nentries; i++) {\n\t\tentries[i].id = 'a' + i;\n\t\tql_elm_new(&entries[i], link);\n\t}\n}\n\nstatic void\ntest_entries_list(list_head_t *head, list_t *entries, unsigned nentries)\n{\n\tlist_t *t;\n\tunsigned i;\n\n\tassert_c_eq(ql_first(head)->id, entries[0].id, \"Element id mismatch\");\n\tassert_c_eq(ql_last(head, link)->id, entries[nentries-1].id,\n\t    \"Element id mismatch\");\n\n\ti = 0;\n\tql_foreach(t, head, link) {\n\t\tassert_c_eq(t->id, entries[i].id, \"Element id mismatch\");\n\t\ti++;\n\t}\n\n\ti = 0;\n\tql_reverse_foreach(t, head, link) {\n\t\tassert_c_eq(t->id, entries[nentries-i-1].id,\n\t\t    \"Element id mismatch\");\n\t\ti++;\n\t}\n\n\tfor (i = 0; i < nentries-1; i++) {\n\t\tt = ql_next(head, &entries[i], link);\n\t\tassert_c_eq(t->id, entries[i+1].id, \"Element id mismatch\");\n\t}\n\tassert_ptr_null(ql_next(head, &entries[nentries-1], link),\n\t    \"Unexpected element\");\n\n\tassert_ptr_null(ql_prev(head, &entries[0], link), \"Unexpected element\");\n\tfor (i = 1; i < nentries; i++) {\n\t\tt = ql_prev(head, &entries[i], link);\n\t\tassert_c_eq(t->id, entries[i-1].id, \"Element id mismatch\");\n\t}\n}\n\nTEST_BEGIN(test_ql_tail_insert)\n{\n\tlist_head_t head;\n\tlist_t entries[NENTRIES];\n\tunsigned i;\n\n\tql_new(&head);\n\tinit_entries(entries, sizeof(entries)/sizeof(list_t));\n\tfor (i = 0; i < NENTRIES; i++)\n\t\tql_tail_insert(&head, &entries[i], link);\n\n\ttest_entries_list(&head, entries, NENTRIES);\n}\nTEST_END\n\nTEST_BEGIN(test_ql_tail_remove)\n{\n\tlist_head_t head;\n\tlist_t entries[NENTRIES];\n\tunsigned i;\n\n\tql_new(&head);\n\tinit_entries(entries, sizeof(entries)/sizeof(list_t));\n\tfor (i = 0; i < NENTRIES; i++)\n\t\tql_tail_insert(&head, &entries[i], link);\n\n\tfor (i = 0; i < NENTRIES; i++) {\n\t\ttest_entries_list(&head, entries, NENTRIES-i);\n\t\tql_tail_remove(&head, list_t, link);\n\t}\n\ttest_empty_list(&head);\n}\nTEST_END\n\nTEST_BEGIN(test_ql_head_insert)\n{\n\tlist_head_t head;\n\tlist_t entries[NENTRIES];\n\tunsigned i;\n\n\tql_new(&head);\n\tinit_entries(entries, sizeof(entries)/sizeof(list_t));\n\tfor (i = 0; i < NENTRIES; i++)\n\t\tql_head_insert(&head, &entries[NENTRIES-i-1], link);\n\n\ttest_entries_list(&head, entries, NENTRIES);\n}\nTEST_END\n\nTEST_BEGIN(test_ql_head_remove)\n{\n\tlist_head_t head;\n\tlist_t entries[NENTRIES];\n\tunsigned i;\n\n\tql_new(&head);\n\tinit_entries(entries, sizeof(entries)/sizeof(list_t));\n\tfor (i = 0; i < NENTRIES; i++)\n\t\tql_head_insert(&head, &entries[NENTRIES-i-1], link);\n\n\tfor (i = 0; i < NENTRIES; i++) {\n\t\ttest_entries_list(&head, &entries[i], NENTRIES-i);\n\t\tql_head_remove(&head, list_t, link);\n\t}\n\ttest_empty_list(&head);\n}\nTEST_END\n\nTEST_BEGIN(test_ql_insert)\n{\n\tlist_head_t head;\n\tlist_t entries[8];\n\tlist_t *a, *b, *c, *d, *e, *f, *g, *h;\n\n\tql_new(&head);\n\tinit_entries(entries, sizeof(entries)/sizeof(list_t));\n\ta = &entries[0];\n\tb = &entries[1];\n\tc = &entries[2];\n\td = &entries[3];\n\te = &entries[4];\n\tf = &entries[5];\n\tg = &entries[6];\n\th = &entries[7];\n\n\t/*\n\t * ql_remove(), ql_before_insert(), and ql_after_insert() are used\n\t * internally by other macros that are already tested, so there's no\n\t * need to test them completely.  However, insertion/deletion from the\n\t * middle of lists is not otherwise tested; do so here.\n\t */\n\tql_tail_insert(&head, f, link);\n\tql_before_insert(&head, f, b, link);\n\tql_before_insert(&head, f, c, link);\n\tql_after_insert(f, h, link);\n\tql_after_insert(f, g, link);\n\tql_before_insert(&head, b, a, link);\n\tql_after_insert(c, d, link);\n\tql_before_insert(&head, f, e, link);\n\n\ttest_entries_list(&head, entries, sizeof(entries)/sizeof(list_t));\n}\nTEST_END\n\nint\nmain(void)\n{\n\n\treturn (test(\n\t    test_ql_empty,\n\t    test_ql_tail_insert,\n\t    test_ql_tail_remove,\n\t    test_ql_head_insert,\n\t    test_ql_head_remove,\n\t    test_ql_insert));\n}\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.8/deps/jemalloc/test/unit/qr.c",
    "content": "#include \"test/jemalloc_test.h\"\n\n/* Number of ring entries, in [2..26]. */\n#define\tNENTRIES 9\n/* Split index, in [1..NENTRIES). */\n#define\tSPLIT_INDEX 5\n\ntypedef struct ring_s ring_t;\n\nstruct ring_s {\n\tqr(ring_t) link;\n\tchar id;\n};\n\nstatic void\ninit_entries(ring_t *entries)\n{\n\tunsigned i;\n\n\tfor (i = 0; i < NENTRIES; i++) {\n\t\tqr_new(&entries[i], link);\n\t\tentries[i].id = 'a' + i;\n\t}\n}\n\nstatic void\ntest_independent_entries(ring_t *entries)\n{\n\tring_t *t;\n\tunsigned i, j;\n\n\tfor (i = 0; i < NENTRIES; i++) {\n\t\tj = 0;\n\t\tqr_foreach(t, &entries[i], link) {\n\t\t\tj++;\n\t\t}\n\t\tassert_u_eq(j, 1,\n\t\t    \"Iteration over single-element ring should visit precisely \"\n\t\t    \"one element\");\n\t}\n\tfor (i = 0; i < NENTRIES; i++) {\n\t\tj = 0;\n\t\tqr_reverse_foreach(t, &entries[i], link) {\n\t\t\tj++;\n\t\t}\n\t\tassert_u_eq(j, 1,\n\t\t    \"Iteration over single-element ring should visit precisely \"\n\t\t    \"one element\");\n\t}\n\tfor (i = 0; i < NENTRIES; i++) {\n\t\tt = qr_next(&entries[i], link);\n\t\tassert_ptr_eq(t, &entries[i],\n\t\t    \"Next element in single-element ring should be same as \"\n\t\t    \"current element\");\n\t}\n\tfor (i = 0; i < NENTRIES; i++) {\n\t\tt = qr_prev(&entries[i], link);\n\t\tassert_ptr_eq(t, &entries[i],\n\t\t    \"Previous element in single-element ring should be same as \"\n\t\t    \"current element\");\n\t}\n}\n\nTEST_BEGIN(test_qr_one)\n{\n\tring_t entries[NENTRIES];\n\n\tinit_entries(entries);\n\ttest_independent_entries(entries);\n}\nTEST_END\n\nstatic void\ntest_entries_ring(ring_t *entries)\n{\n\tring_t *t;\n\tunsigned i, j;\n\n\tfor (i = 0; i < NENTRIES; i++) {\n\t\tj = 0;\n\t\tqr_foreach(t, &entries[i], link) {\n\t\t\tassert_c_eq(t->id, entries[(i+j) % NENTRIES].id,\n\t\t\t    \"Element id mismatch\");\n\t\t\tj++;\n\t\t}\n\t}\n\tfor (i = 0; i < NENTRIES; i++) {\n\t\tj = 0;\n\t\tqr_reverse_foreach(t, &entries[i], link) {\n\t\t\tassert_c_eq(t->id, entries[(NENTRIES+i-j-1) %\n\t\t\t    NENTRIES].id, \"Element id mismatch\");\n\t\t\tj++;\n\t\t}\n\t}\n\tfor (i = 0; i < NENTRIES; i++) {\n\t\tt = qr_next(&entries[i], link);\n\t\tassert_c_eq(t->id, entries[(i+1) % NENTRIES].id,\n\t\t    \"Element id mismatch\");\n\t}\n\tfor (i = 0; i < NENTRIES; i++) {\n\t\tt = qr_prev(&entries[i], link);\n\t\tassert_c_eq(t->id, entries[(NENTRIES+i-1) % NENTRIES].id,\n\t\t    \"Element id mismatch\");\n\t}\n}\n\nTEST_BEGIN(test_qr_after_insert)\n{\n\tring_t entries[NENTRIES];\n\tunsigned i;\n\n\tinit_entries(entries);\n\tfor (i = 1; i < NENTRIES; i++)\n\t\tqr_after_insert(&entries[i - 1], &entries[i], link);\n\ttest_entries_ring(entries);\n}\nTEST_END\n\nTEST_BEGIN(test_qr_remove)\n{\n\tring_t entries[NENTRIES];\n\tring_t *t;\n\tunsigned i, j;\n\n\tinit_entries(entries);\n\tfor (i = 1; i < NENTRIES; i++)\n\t\tqr_after_insert(&entries[i - 1], &entries[i], link);\n\n\tfor (i = 0; i < NENTRIES; i++) {\n\t\tj = 0;\n\t\tqr_foreach(t, &entries[i], link) {\n\t\t\tassert_c_eq(t->id, entries[i+j].id,\n\t\t\t    \"Element id mismatch\");\n\t\t\tj++;\n\t\t}\n\t\tj = 0;\n\t\tqr_reverse_foreach(t, &entries[i], link) {\n\t\t\tassert_c_eq(t->id, entries[NENTRIES - 1 - j].id,\n\t\t\t\"Element id mismatch\");\n\t\t\tj++;\n\t\t}\n\t\tqr_remove(&entries[i], link);\n\t}\n\ttest_independent_entries(entries);\n}\nTEST_END\n\nTEST_BEGIN(test_qr_before_insert)\n{\n\tring_t entries[NENTRIES];\n\tring_t *t;\n\tunsigned i, j;\n\n\tinit_entries(entries);\n\tfor (i = 1; i < NENTRIES; i++)\n\t\tqr_before_insert(&entries[i - 1], &entries[i], link);\n\tfor (i = 0; i < NENTRIES; i++) {\n\t\tj = 0;\n\t\tqr_foreach(t, &entries[i], link) {\n\t\t\tassert_c_eq(t->id, entries[(NENTRIES+i-j) %\n\t\t\t    NENTRIES].id, \"Element id mismatch\");\n\t\t\tj++;\n\t\t}\n\t}\n\tfor (i = 0; i < NENTRIES; i++) {\n\t\tj = 0;\n\t\tqr_reverse_foreach(t, &entries[i], link) {\n\t\t\tassert_c_eq(t->id, entries[(i+j+1) % NENTRIES].id,\n\t\t\t    \"Element id mismatch\");\n\t\t\tj++;\n\t\t}\n\t}\n\tfor (i = 0; i < NENTRIES; i++) {\n\t\tt = qr_next(&entries[i], link);\n\t\tassert_c_eq(t->id, entries[(NENTRIES+i-1) % NENTRIES].id,\n\t\t    \"Element id mismatch\");\n\t}\n\tfor (i = 0; i < NENTRIES; i++) {\n\t\tt = qr_prev(&entries[i], link);\n\t\tassert_c_eq(t->id, entries[(i+1) % NENTRIES].id,\n\t\t    \"Element id mismatch\");\n\t}\n}\nTEST_END\n\nstatic void\ntest_split_entries(ring_t *entries)\n{\n\tring_t *t;\n\tunsigned i, j;\n\n\tfor (i = 0; i < NENTRIES; i++) {\n\t\tj = 0;\n\t\tqr_foreach(t, &entries[i], link) {\n\t\t\tif (i < SPLIT_INDEX) {\n\t\t\t\tassert_c_eq(t->id,\n\t\t\t\t    entries[(i+j) % SPLIT_INDEX].id,\n\t\t\t\t    \"Element id mismatch\");\n\t\t\t} else {\n\t\t\t\tassert_c_eq(t->id, entries[(i+j-SPLIT_INDEX) %\n\t\t\t\t    (NENTRIES-SPLIT_INDEX) + SPLIT_INDEX].id,\n\t\t\t\t    \"Element id mismatch\");\n\t\t\t}\n\t\t\tj++;\n\t\t}\n\t}\n}\n\nTEST_BEGIN(test_qr_meld_split)\n{\n\tring_t entries[NENTRIES];\n\tunsigned i;\n\n\tinit_entries(entries);\n\tfor (i = 1; i < NENTRIES; i++)\n\t\tqr_after_insert(&entries[i - 1], &entries[i], link);\n\n\tqr_split(&entries[0], &entries[SPLIT_INDEX], link);\n\ttest_split_entries(entries);\n\n\tqr_meld(&entries[0], &entries[SPLIT_INDEX], link);\n\ttest_entries_ring(entries);\n\n\tqr_meld(&entries[0], &entries[SPLIT_INDEX], link);\n\ttest_split_entries(entries);\n\n\tqr_split(&entries[0], &entries[SPLIT_INDEX], link);\n\ttest_entries_ring(entries);\n\n\tqr_split(&entries[0], &entries[0], link);\n\ttest_entries_ring(entries);\n\n\tqr_meld(&entries[0], &entries[0], link);\n\ttest_entries_ring(entries);\n}\nTEST_END\n\nint\nmain(void)\n{\n\n\treturn (test(\n\t    test_qr_one,\n\t    test_qr_after_insert,\n\t    test_qr_remove,\n\t    test_qr_before_insert,\n\t    test_qr_meld_split));\n}\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.8/deps/jemalloc/test/unit/quarantine.c",
    "content": "#include \"test/jemalloc_test.h\"\n\n#define\tQUARANTINE_SIZE\t\t8192\n#define\tSTRINGIFY_HELPER(x)\t#x\n#define\tSTRINGIFY(x)\t\tSTRINGIFY_HELPER(x)\n\n#ifdef JEMALLOC_FILL\nconst char *malloc_conf = \"abort:false,junk:true,redzone:true,quarantine:\"\n    STRINGIFY(QUARANTINE_SIZE);\n#endif\n\nvoid\nquarantine_clear(void)\n{\n\tvoid *p;\n\n\tp = mallocx(QUARANTINE_SIZE*2, 0);\n\tassert_ptr_not_null(p, \"Unexpected mallocx() failure\");\n\tdallocx(p, 0);\n}\n\nTEST_BEGIN(test_quarantine)\n{\n#define\tSZ\t\tZU(256)\n#define\tNQUARANTINED\t(QUARANTINE_SIZE/SZ)\n\tvoid *quarantined[NQUARANTINED+1];\n\tsize_t i, j;\n\n\ttest_skip_if(!config_fill);\n\n\tassert_zu_eq(nallocx(SZ, 0), SZ,\n\t    \"SZ=%zu does not precisely equal a size class\", SZ);\n\n\tquarantine_clear();\n\n\t/*\n\t * Allocate enough regions to completely fill the quarantine, plus one\n\t * more.  The last iteration occurs with a completely full quarantine,\n\t * but no regions should be drained from the quarantine until the last\n\t * deallocation occurs.  Therefore no region recycling should occur\n\t * until after this loop completes.\n\t */\n\tfor (i = 0; i < NQUARANTINED+1; i++) {\n\t\tvoid *p = mallocx(SZ, 0);\n\t\tassert_ptr_not_null(p, \"Unexpected mallocx() failure\");\n\t\tquarantined[i] = p;\n\t\tdallocx(p, 0);\n\t\tfor (j = 0; j < i; j++) {\n\t\t\tassert_ptr_ne(p, quarantined[j],\n\t\t\t    \"Quarantined region recycled too early; \"\n\t\t\t    \"i=%zu, j=%zu\", i, j);\n\t\t}\n\t}\n#undef NQUARANTINED\n#undef SZ\n}\nTEST_END\n\nstatic bool detected_redzone_corruption;\n\nstatic void\narena_redzone_corruption_replacement(void *ptr, size_t usize, bool after,\n    size_t offset, uint8_t byte)\n{\n\n\tdetected_redzone_corruption = true;\n}\n\nTEST_BEGIN(test_quarantine_redzone)\n{\n\tchar *s;\n\tarena_redzone_corruption_t *arena_redzone_corruption_orig;\n\n\ttest_skip_if(!config_fill);\n\n\tarena_redzone_corruption_orig = arena_redzone_corruption;\n\tarena_redzone_corruption = arena_redzone_corruption_replacement;\n\n\t/* Test underflow. */\n\tdetected_redzone_corruption = false;\n\ts = (char *)mallocx(1, 0);\n\tassert_ptr_not_null((void *)s, \"Unexpected mallocx() failure\");\n\ts[-1] = 0xbb;\n\tdallocx(s, 0);\n\tassert_true(detected_redzone_corruption,\n\t    \"Did not detect redzone corruption\");\n\n\t/* Test overflow. */\n\tdetected_redzone_corruption = false;\n\ts = (char *)mallocx(1, 0);\n\tassert_ptr_not_null((void *)s, \"Unexpected mallocx() failure\");\n\ts[sallocx(s, 0)] = 0xbb;\n\tdallocx(s, 0);\n\tassert_true(detected_redzone_corruption,\n\t    \"Did not detect redzone corruption\");\n\n\tarena_redzone_corruption = arena_redzone_corruption_orig;\n}\nTEST_END\n\nint\nmain(void)\n{\n\n\treturn (test(\n\t    test_quarantine,\n\t    test_quarantine_redzone));\n}\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.8/deps/jemalloc/test/unit/rb.c",
    "content": "#include \"test/jemalloc_test.h\"\n\n#define\trbtn_black_height(a_type, a_field, a_rbt, r_height) do {\t\\\n    a_type *rbp_bh_t;\t\t\t\t\t\t\t\\\n    for (rbp_bh_t = (a_rbt)->rbt_root, (r_height) = 0;\t\t\t\\\n      rbp_bh_t != &(a_rbt)->rbt_nil;\t\t\t\t\t\\\n      rbp_bh_t = rbtn_left_get(a_type, a_field, rbp_bh_t)) {\t\t\\\n\tif (!rbtn_red_get(a_type, a_field, rbp_bh_t)) {\t\t\t\\\n\t    (r_height)++;\t\t\t\t\t\t\\\n\t}\t\t\t\t\t\t\t\t\\\n    }\t\t\t\t\t\t\t\t\t\\\n} while (0)\n\ntypedef struct node_s node_t;\n\nstruct node_s {\n#define\tNODE_MAGIC 0x9823af7e\n\tuint32_t magic;\n\trb_node(node_t) link;\n\tuint64_t key;\n};\n\nstatic int\nnode_cmp(node_t *a, node_t *b) {\n\tint ret;\n\n\tassert_u32_eq(a->magic, NODE_MAGIC, \"Bad magic\");\n\tassert_u32_eq(b->magic, NODE_MAGIC, \"Bad magic\");\n\n\tret = (a->key > b->key) - (a->key < b->key);\n\tif (ret == 0) {\n\t\t/*\n\t\t * Duplicates are not allowed in the tree, so force an\n\t\t * arbitrary ordering for non-identical items with equal keys.\n\t\t */\n\t\tret = (((uintptr_t)a) > ((uintptr_t)b))\n\t\t    - (((uintptr_t)a) < ((uintptr_t)b));\n\t}\n\treturn (ret);\n}\n\ntypedef rb_tree(node_t) tree_t;\nrb_gen(static, tree_, tree_t, node_t, link, node_cmp);\n\nTEST_BEGIN(test_rb_empty)\n{\n\ttree_t tree;\n\tnode_t key;\n\n\ttree_new(&tree);\n\n\tassert_true(tree_empty(&tree), \"Tree should be empty\");\n\tassert_ptr_null(tree_first(&tree), \"Unexpected node\");\n\tassert_ptr_null(tree_last(&tree), \"Unexpected node\");\n\n\tkey.key = 0;\n\tkey.magic = NODE_MAGIC;\n\tassert_ptr_null(tree_search(&tree, &key), \"Unexpected node\");\n\n\tkey.key = 0;\n\tkey.magic = NODE_MAGIC;\n\tassert_ptr_null(tree_nsearch(&tree, &key), \"Unexpected node\");\n\n\tkey.key = 0;\n\tkey.magic = NODE_MAGIC;\n\tassert_ptr_null(tree_psearch(&tree, &key), \"Unexpected node\");\n}\nTEST_END\n\nstatic unsigned\ntree_recurse(node_t *node, unsigned black_height, unsigned black_depth,\n    node_t *nil)\n{\n\tunsigned ret = 0;\n\tnode_t *left_node = rbtn_left_get(node_t, link, node);\n\tnode_t *right_node = rbtn_right_get(node_t, link, node);\n\n\tif (!rbtn_red_get(node_t, link, node))\n\t\tblack_depth++;\n\n\t/* Red nodes must be interleaved with black nodes. */\n\tif (rbtn_red_get(node_t, link, node)) {\n\t\tassert_false(rbtn_red_get(node_t, link, left_node),\n\t\t    \"Node should be black\");\n\t\tassert_false(rbtn_red_get(node_t, link, right_node),\n\t\t    \"Node should be black\");\n\t}\n\n\tif (node == nil)\n\t\treturn (ret);\n\t/* Self. */\n\tassert_u32_eq(node->magic, NODE_MAGIC, \"Bad magic\");\n\n\t/* Left subtree. */\n\tif (left_node != nil)\n\t\tret += tree_recurse(left_node, black_height, black_depth, nil);\n\telse\n\t\tret += (black_depth != black_height);\n\n\t/* Right subtree. */\n\tif (right_node != nil)\n\t\tret += tree_recurse(right_node, black_height, black_depth, nil);\n\telse\n\t\tret += (black_depth != black_height);\n\n\treturn (ret);\n}\n\nstatic node_t *\ntree_iterate_cb(tree_t *tree, node_t *node, void *data)\n{\n\tunsigned *i = (unsigned *)data;\n\tnode_t *search_node;\n\n\tassert_u32_eq(node->magic, NODE_MAGIC, \"Bad magic\");\n\n\t/* Test rb_search(). */\n\tsearch_node = tree_search(tree, node);\n\tassert_ptr_eq(search_node, node,\n\t    \"tree_search() returned unexpected node\");\n\n\t/* Test rb_nsearch(). */\n\tsearch_node = tree_nsearch(tree, node);\n\tassert_ptr_eq(search_node, node,\n\t    \"tree_nsearch() returned unexpected node\");\n\n\t/* Test rb_psearch(). */\n\tsearch_node = tree_psearch(tree, node);\n\tassert_ptr_eq(search_node, node,\n\t    \"tree_psearch() returned unexpected node\");\n\n\t(*i)++;\n\n\treturn (NULL);\n}\n\nstatic unsigned\ntree_iterate(tree_t *tree)\n{\n\tunsigned i;\n\n\ti = 0;\n\ttree_iter(tree, NULL, tree_iterate_cb, (void *)&i);\n\n\treturn (i);\n}\n\nstatic unsigned\ntree_iterate_reverse(tree_t *tree)\n{\n\tunsigned i;\n\n\ti = 0;\n\ttree_reverse_iter(tree, NULL, tree_iterate_cb, (void *)&i);\n\n\treturn (i);\n}\n\nstatic void\nnode_remove(tree_t *tree, node_t *node, unsigned nnodes)\n{\n\tnode_t *search_node;\n\tunsigned black_height, imbalances;\n\n\ttree_remove(tree, node);\n\n\t/* Test rb_nsearch(). */\n\tsearch_node = tree_nsearch(tree, node);\n\tif (search_node != NULL) {\n\t\tassert_u64_ge(search_node->key, node->key,\n\t\t    \"Key ordering error\");\n\t}\n\n\t/* Test rb_psearch(). */\n\tsearch_node = tree_psearch(tree, node);\n\tif (search_node != NULL) {\n\t\tassert_u64_le(search_node->key, node->key,\n\t\t    \"Key ordering error\");\n\t}\n\n\tnode->magic = 0;\n\n\trbtn_black_height(node_t, link, tree, black_height);\n\timbalances = tree_recurse(tree->rbt_root, black_height, 0,\n\t    &(tree->rbt_nil));\n\tassert_u_eq(imbalances, 0, \"Tree is unbalanced\");\n\tassert_u_eq(tree_iterate(tree), nnodes-1,\n\t    \"Unexpected node iteration count\");\n\tassert_u_eq(tree_iterate_reverse(tree), nnodes-1,\n\t    \"Unexpected node iteration count\");\n}\n\nstatic node_t *\nremove_iterate_cb(tree_t *tree, node_t *node, void *data)\n{\n\tunsigned *nnodes = (unsigned *)data;\n\tnode_t *ret = tree_next(tree, node);\n\n\tnode_remove(tree, node, *nnodes);\n\n\treturn (ret);\n}\n\nstatic node_t *\nremove_reverse_iterate_cb(tree_t *tree, node_t *node, void *data)\n{\n\tunsigned *nnodes = (unsigned *)data;\n\tnode_t *ret = tree_prev(tree, node);\n\n\tnode_remove(tree, node, *nnodes);\n\n\treturn (ret);\n}\n\nTEST_BEGIN(test_rb_random)\n{\n#define\tNNODES 25\n#define\tNBAGS 250\n#define\tSEED 42\n\tsfmt_t *sfmt;\n\tuint64_t bag[NNODES];\n\ttree_t tree;\n\tnode_t nodes[NNODES];\n\tunsigned i, j, k, black_height, imbalances;\n\n\tsfmt = init_gen_rand(SEED);\n\tfor (i = 0; i < NBAGS; i++) {\n\t\tswitch (i) {\n\t\tcase 0:\n\t\t\t/* Insert in order. */\n\t\t\tfor (j = 0; j < NNODES; j++)\n\t\t\t\tbag[j] = j;\n\t\t\tbreak;\n\t\tcase 1:\n\t\t\t/* Insert in reverse order. */\n\t\t\tfor (j = 0; j < NNODES; j++)\n\t\t\t\tbag[j] = NNODES - j - 1;\n\t\t\tbreak;\n\t\tdefault:\n\t\t\tfor (j = 0; j < NNODES; j++)\n\t\t\t\tbag[j] = gen_rand64_range(sfmt, NNODES);\n\t\t}\n\n\t\tfor (j = 1; j <= NNODES; j++) {\n\t\t\t/* Initialize tree and nodes. */\n\t\t\ttree_new(&tree);\n\t\t\ttree.rbt_nil.magic = 0;\n\t\t\tfor (k = 0; k < j; k++) {\n\t\t\t\tnodes[k].magic = NODE_MAGIC;\n\t\t\t\tnodes[k].key = bag[k];\n\t\t\t}\n\n\t\t\t/* Insert nodes. */\n\t\t\tfor (k = 0; k < j; k++) {\n\t\t\t\ttree_insert(&tree, &nodes[k]);\n\n\t\t\t\trbtn_black_height(node_t, link, &tree,\n\t\t\t\t    black_height);\n\t\t\t\timbalances = tree_recurse(tree.rbt_root,\n\t\t\t\t    black_height, 0, &(tree.rbt_nil));\n\t\t\t\tassert_u_eq(imbalances, 0,\n\t\t\t\t    \"Tree is unbalanced\");\n\n\t\t\t\tassert_u_eq(tree_iterate(&tree), k+1,\n\t\t\t\t    \"Unexpected node iteration count\");\n\t\t\t\tassert_u_eq(tree_iterate_reverse(&tree), k+1,\n\t\t\t\t    \"Unexpected node iteration count\");\n\n\t\t\t\tassert_false(tree_empty(&tree),\n\t\t\t\t    \"Tree should not be empty\");\n\t\t\t\tassert_ptr_not_null(tree_first(&tree),\n\t\t\t\t    \"Tree should not be empty\");\n\t\t\t\tassert_ptr_not_null(tree_last(&tree),\n\t\t\t\t    \"Tree should not be empty\");\n\n\t\t\t\ttree_next(&tree, &nodes[k]);\n\t\t\t\ttree_prev(&tree, &nodes[k]);\n\t\t\t}\n\n\t\t\t/* Remove nodes. */\n\t\t\tswitch (i % 4) {\n\t\t\tcase 0:\n\t\t\t\tfor (k = 0; k < j; k++)\n\t\t\t\t\tnode_remove(&tree, &nodes[k], j - k);\n\t\t\t\tbreak;\n\t\t\tcase 1:\n\t\t\t\tfor (k = j; k > 0; k--)\n\t\t\t\t\tnode_remove(&tree, &nodes[k-1], k);\n\t\t\t\tbreak;\n\t\t\tcase 2: {\n\t\t\t\tnode_t *start;\n\t\t\t\tunsigned nnodes = j;\n\n\t\t\t\tstart = NULL;\n\t\t\t\tdo {\n\t\t\t\t\tstart = tree_iter(&tree, start,\n\t\t\t\t\t    remove_iterate_cb, (void *)&nnodes);\n\t\t\t\t\tnnodes--;\n\t\t\t\t} while (start != NULL);\n\t\t\t\tassert_u_eq(nnodes, 0,\n\t\t\t\t    \"Removal terminated early\");\n\t\t\t\tbreak;\n\t\t\t} case 3: {\n\t\t\t\tnode_t *start;\n\t\t\t\tunsigned nnodes = j;\n\n\t\t\t\tstart = NULL;\n\t\t\t\tdo {\n\t\t\t\t\tstart = tree_reverse_iter(&tree, start,\n\t\t\t\t\t    remove_reverse_iterate_cb,\n\t\t\t\t\t    (void *)&nnodes);\n\t\t\t\t\tnnodes--;\n\t\t\t\t} while (start != NULL);\n\t\t\t\tassert_u_eq(nnodes, 0,\n\t\t\t\t    \"Removal terminated early\");\n\t\t\t\tbreak;\n\t\t\t} default:\n\t\t\t\tnot_reached();\n\t\t\t}\n\t\t}\n\t}\n\tfini_gen_rand(sfmt);\n#undef NNODES\n#undef NBAGS\n#undef SEED\n}\nTEST_END\n\nint\nmain(void)\n{\n\n\treturn (test(\n\t    test_rb_empty,\n\t    test_rb_random));\n}\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.8/deps/jemalloc/test/unit/rtree.c",
    "content": "#include \"test/jemalloc_test.h\"\n\nstatic rtree_node_elm_t *\nnode_alloc(size_t nelms)\n{\n\n\treturn ((rtree_node_elm_t *)calloc(nelms, sizeof(rtree_node_elm_t)));\n}\n\nstatic void\nnode_dalloc(rtree_node_elm_t *node)\n{\n\n\tfree(node);\n}\n\nTEST_BEGIN(test_rtree_get_empty)\n{\n\tunsigned i;\n\n\tfor (i = 1; i <= (sizeof(uintptr_t) << 3); i++) {\n\t\trtree_t rtree;\n\t\tassert_false(rtree_new(&rtree, i, node_alloc, node_dalloc),\n\t\t    \"Unexpected rtree_new() failure\");\n\t\tassert_ptr_null(rtree_get(&rtree, 0, false),\n\t\t    \"rtree_get() should return NULL for empty tree\");\n\t\trtree_delete(&rtree);\n\t}\n}\nTEST_END\n\nTEST_BEGIN(test_rtree_extrema)\n{\n\tunsigned i;\n\textent_node_t node_a, node_b;\n\n\tfor (i = 1; i <= (sizeof(uintptr_t) << 3); i++) {\n\t\trtree_t rtree;\n\t\tassert_false(rtree_new(&rtree, i, node_alloc, node_dalloc),\n\t\t    \"Unexpected rtree_new() failure\");\n\n\t\tassert_false(rtree_set(&rtree, 0, &node_a),\n\t\t    \"Unexpected rtree_set() failure\");\n\t\tassert_ptr_eq(rtree_get(&rtree, 0, true), &node_a,\n\t\t    \"rtree_get() should return previously set value\");\n\n\t\tassert_false(rtree_set(&rtree, ~((uintptr_t)0), &node_b),\n\t\t    \"Unexpected rtree_set() failure\");\n\t\tassert_ptr_eq(rtree_get(&rtree, ~((uintptr_t)0), true), &node_b,\n\t\t    \"rtree_get() should return previously set value\");\n\n\t\trtree_delete(&rtree);\n\t}\n}\nTEST_END\n\nTEST_BEGIN(test_rtree_bits)\n{\n\tunsigned i, j, k;\n\n\tfor (i = 1; i < (sizeof(uintptr_t) << 3); i++) {\n\t\tuintptr_t keys[] = {0, 1,\n\t\t    (((uintptr_t)1) << (sizeof(uintptr_t)*8-i)) - 1};\n\t\textent_node_t node;\n\t\trtree_t rtree;\n\n\t\tassert_false(rtree_new(&rtree, i, node_alloc, node_dalloc),\n\t\t    \"Unexpected rtree_new() failure\");\n\n\t\tfor (j = 0; j < sizeof(keys)/sizeof(uintptr_t); j++) {\n\t\t\tassert_false(rtree_set(&rtree, keys[j], &node),\n\t\t\t    \"Unexpected rtree_set() failure\");\n\t\t\tfor (k = 0; k < sizeof(keys)/sizeof(uintptr_t); k++) {\n\t\t\t\tassert_ptr_eq(rtree_get(&rtree, keys[k], true),\n\t\t\t\t    &node, \"rtree_get() should return \"\n\t\t\t\t    \"previously set value and ignore \"\n\t\t\t\t    \"insignificant key bits; i=%u, j=%u, k=%u, \"\n\t\t\t\t    \"set key=%#\"FMTxPTR\", get key=%#\"FMTxPTR, i,\n\t\t\t\t    j, k, keys[j], keys[k]);\n\t\t\t}\n\t\t\tassert_ptr_null(rtree_get(&rtree,\n\t\t\t    (((uintptr_t)1) << (sizeof(uintptr_t)*8-i)), false),\n\t\t\t    \"Only leftmost rtree leaf should be set; \"\n\t\t\t    \"i=%u, j=%u\", i, j);\n\t\t\tassert_false(rtree_set(&rtree, keys[j], NULL),\n\t\t\t    \"Unexpected rtree_set() failure\");\n\t\t}\n\n\t\trtree_delete(&rtree);\n\t}\n}\nTEST_END\n\nTEST_BEGIN(test_rtree_random)\n{\n\tunsigned i;\n\tsfmt_t *sfmt;\n#define\tNSET 16\n#define\tSEED 42\n\n\tsfmt = init_gen_rand(SEED);\n\tfor (i = 1; i <= (sizeof(uintptr_t) << 3); i++) {\n\t\tuintptr_t keys[NSET];\n\t\textent_node_t node;\n\t\tunsigned j;\n\t\trtree_t rtree;\n\n\t\tassert_false(rtree_new(&rtree, i, node_alloc, node_dalloc),\n\t\t    \"Unexpected rtree_new() failure\");\n\n\t\tfor (j = 0; j < NSET; j++) {\n\t\t\tkeys[j] = (uintptr_t)gen_rand64(sfmt);\n\t\t\tassert_false(rtree_set(&rtree, keys[j], &node),\n\t\t\t    \"Unexpected rtree_set() failure\");\n\t\t\tassert_ptr_eq(rtree_get(&rtree, keys[j], true), &node,\n\t\t\t    \"rtree_get() should return previously set value\");\n\t\t}\n\t\tfor (j = 0; j < NSET; j++) {\n\t\t\tassert_ptr_eq(rtree_get(&rtree, keys[j], true), &node,\n\t\t\t    \"rtree_get() should return previously set value\");\n\t\t}\n\n\t\tfor (j = 0; j < NSET; j++) {\n\t\t\tassert_false(rtree_set(&rtree, keys[j], NULL),\n\t\t\t    \"Unexpected rtree_set() failure\");\n\t\t\tassert_ptr_null(rtree_get(&rtree, keys[j], true),\n\t\t\t    \"rtree_get() should return previously set value\");\n\t\t}\n\t\tfor (j = 0; j < NSET; j++) {\n\t\t\tassert_ptr_null(rtree_get(&rtree, keys[j], true),\n\t\t\t    \"rtree_get() should return previously set value\");\n\t\t}\n\n\t\trtree_delete(&rtree);\n\t}\n\tfini_gen_rand(sfmt);\n#undef NSET\n#undef SEED\n}\nTEST_END\n\nint\nmain(void)\n{\n\n\treturn (test(\n\t    test_rtree_get_empty,\n\t    test_rtree_extrema,\n\t    test_rtree_bits,\n\t    test_rtree_random));\n}\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.8/deps/jemalloc/test/unit/size_classes.c",
    "content": "#include \"test/jemalloc_test.h\"\n\nstatic size_t\nget_max_size_class(void)\n{\n\tunsigned nhchunks;\n\tsize_t mib[4];\n\tsize_t sz, miblen, max_size_class;\n\n\tsz = sizeof(unsigned);\n\tassert_d_eq(mallctl(\"arenas.nhchunks\", &nhchunks, &sz, NULL, 0), 0,\n\t    \"Unexpected mallctl() error\");\n\n\tmiblen = sizeof(mib) / sizeof(size_t);\n\tassert_d_eq(mallctlnametomib(\"arenas.hchunk.0.size\", mib, &miblen), 0,\n\t    \"Unexpected mallctlnametomib() error\");\n\tmib[2] = nhchunks - 1;\n\n\tsz = sizeof(size_t);\n\tassert_d_eq(mallctlbymib(mib, miblen, &max_size_class, &sz, NULL, 0), 0,\n\t    \"Unexpected mallctlbymib() error\");\n\n\treturn (max_size_class);\n}\n\nTEST_BEGIN(test_size_classes)\n{\n\tsize_t size_class, max_size_class;\n\tszind_t index, max_index;\n\n\tmax_size_class = get_max_size_class();\n\tmax_index = size2index(max_size_class);\n\n\tfor (index = 0, size_class = index2size(index); index < max_index ||\n\t    size_class < max_size_class; index++, size_class =\n\t    index2size(index)) {\n\t\tassert_true(index < max_index,\n\t\t    \"Loop conditionals should be equivalent; index=%u, \"\n\t\t    \"size_class=%zu (%#zx)\", index, size_class, size_class);\n\t\tassert_true(size_class < max_size_class,\n\t\t    \"Loop conditionals should be equivalent; index=%u, \"\n\t\t    \"size_class=%zu (%#zx)\", index, size_class, size_class);\n\n\t\tassert_u_eq(index, size2index(size_class),\n\t\t    \"size2index() does not reverse index2size(): index=%u -->\"\n\t\t    \" size_class=%zu --> index=%u --> size_class=%zu\", index,\n\t\t    size_class, size2index(size_class),\n\t\t    index2size(size2index(size_class)));\n\t\tassert_zu_eq(size_class, index2size(size2index(size_class)),\n\t\t    \"index2size() does not reverse size2index(): index=%u -->\"\n\t\t    \" size_class=%zu --> index=%u --> size_class=%zu\", index,\n\t\t    size_class, size2index(size_class),\n\t\t    index2size(size2index(size_class)));\n\n\t\tassert_u_eq(index+1, size2index(size_class+1),\n\t\t    \"Next size_class does not round up properly\");\n\n\t\tassert_zu_eq(size_class, (index > 0) ?\n\t\t    s2u(index2size(index-1)+1) : s2u(1),\n\t\t    \"s2u() does not round up to size class\");\n\t\tassert_zu_eq(size_class, s2u(size_class-1),\n\t\t    \"s2u() does not round up to size class\");\n\t\tassert_zu_eq(size_class, s2u(size_class),\n\t\t    \"s2u() does not compute same size class\");\n\t\tassert_zu_eq(s2u(size_class+1), index2size(index+1),\n\t\t    \"s2u() does not round up to next size class\");\n\t}\n\n\tassert_u_eq(index, size2index(index2size(index)),\n\t    \"size2index() does not reverse index2size()\");\n\tassert_zu_eq(max_size_class, index2size(size2index(max_size_class)),\n\t    \"index2size() does not reverse size2index()\");\n\n\tassert_zu_eq(size_class, s2u(index2size(index-1)+1),\n\t    \"s2u() does not round up to size class\");\n\tassert_zu_eq(size_class, s2u(size_class-1),\n\t    \"s2u() does not round up to size class\");\n\tassert_zu_eq(size_class, s2u(size_class),\n\t    \"s2u() does not compute same size class\");\n}\nTEST_END\n\nint\nmain(void)\n{\n\n\treturn (test(\n\t    test_size_classes));\n}\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.8/deps/jemalloc/test/unit/stats.c",
    "content": "#include \"test/jemalloc_test.h\"\n\nTEST_BEGIN(test_stats_summary)\n{\n\tsize_t *cactive;\n\tsize_t sz, allocated, active, resident, mapped;\n\tint expected = config_stats ? 0 : ENOENT;\n\n\tsz = sizeof(cactive);\n\tassert_d_eq(mallctl(\"stats.cactive\", &cactive, &sz, NULL, 0), expected,\n\t    \"Unexpected mallctl() result\");\n\n\tsz = sizeof(size_t);\n\tassert_d_eq(mallctl(\"stats.allocated\", &allocated, &sz, NULL, 0),\n\t    expected, \"Unexpected mallctl() result\");\n\tassert_d_eq(mallctl(\"stats.active\", &active, &sz, NULL, 0), expected,\n\t    \"Unexpected mallctl() result\");\n\tassert_d_eq(mallctl(\"stats.resident\", &resident, &sz, NULL, 0),\n\t    expected, \"Unexpected mallctl() result\");\n\tassert_d_eq(mallctl(\"stats.mapped\", &mapped, &sz, NULL, 0), expected,\n\t    \"Unexpected mallctl() result\");\n\n\tif (config_stats) {\n\t\tassert_zu_le(active, *cactive,\n\t\t    \"active should be no larger than cactive\");\n\t\tassert_zu_le(allocated, active,\n\t\t    \"allocated should be no larger than active\");\n\t\tassert_zu_lt(active, resident,\n\t\t    \"active should be less than resident\");\n\t\tassert_zu_lt(active, mapped,\n\t\t    \"active should be less than mapped\");\n\t}\n}\nTEST_END\n\nTEST_BEGIN(test_stats_huge)\n{\n\tvoid *p;\n\tuint64_t epoch;\n\tsize_t allocated;\n\tuint64_t nmalloc, ndalloc, nrequests;\n\tsize_t sz;\n\tint expected = config_stats ? 0 : ENOENT;\n\n\tp = mallocx(large_maxclass+1, 0);\n\tassert_ptr_not_null(p, \"Unexpected mallocx() failure\");\n\n\tassert_d_eq(mallctl(\"epoch\", NULL, NULL, &epoch, sizeof(epoch)), 0,\n\t    \"Unexpected mallctl() failure\");\n\n\tsz = sizeof(size_t);\n\tassert_d_eq(mallctl(\"stats.arenas.0.huge.allocated\", &allocated, &sz,\n\t    NULL, 0), expected, \"Unexpected mallctl() result\");\n\tsz = sizeof(uint64_t);\n\tassert_d_eq(mallctl(\"stats.arenas.0.huge.nmalloc\", &nmalloc, &sz, NULL,\n\t    0), expected, \"Unexpected mallctl() result\");\n\tassert_d_eq(mallctl(\"stats.arenas.0.huge.ndalloc\", &ndalloc, &sz, NULL,\n\t    0), expected, \"Unexpected mallctl() result\");\n\tassert_d_eq(mallctl(\"stats.arenas.0.huge.nrequests\", &nrequests, &sz,\n\t    NULL, 0), expected, \"Unexpected mallctl() result\");\n\n\tif (config_stats) {\n\t\tassert_zu_gt(allocated, 0,\n\t\t    \"allocated should be greater than zero\");\n\t\tassert_u64_ge(nmalloc, ndalloc,\n\t\t    \"nmalloc should be at least as large as ndalloc\");\n\t\tassert_u64_le(nmalloc, nrequests,\n\t\t    \"nmalloc should no larger than nrequests\");\n\t}\n\n\tdallocx(p, 0);\n}\nTEST_END\n\nTEST_BEGIN(test_stats_arenas_summary)\n{\n\tunsigned arena;\n\tvoid *little, *large, *huge;\n\tuint64_t epoch;\n\tsize_t sz;\n\tint expected = config_stats ? 0 : ENOENT;\n\tsize_t mapped;\n\tuint64_t npurge, nmadvise, purged;\n\n\tarena = 0;\n\tassert_d_eq(mallctl(\"thread.arena\", NULL, NULL, &arena, sizeof(arena)),\n\t    0, \"Unexpected mallctl() failure\");\n\n\tlittle = mallocx(SMALL_MAXCLASS, 0);\n\tassert_ptr_not_null(little, \"Unexpected mallocx() failure\");\n\tlarge = mallocx(large_maxclass, 0);\n\tassert_ptr_not_null(large, \"Unexpected mallocx() failure\");\n\thuge = mallocx(chunksize, 0);\n\tassert_ptr_not_null(huge, \"Unexpected mallocx() failure\");\n\n\tassert_d_eq(mallctl(\"arena.0.purge\", NULL, NULL, NULL, 0), 0,\n\t    \"Unexpected mallctl() failure\");\n\n\tassert_d_eq(mallctl(\"epoch\", NULL, NULL, &epoch, sizeof(epoch)), 0,\n\t    \"Unexpected mallctl() failure\");\n\n\tsz = sizeof(size_t);\n\tassert_d_eq(mallctl(\"stats.arenas.0.mapped\", &mapped, &sz, NULL, 0),\n\t    expected, \"Unexepected mallctl() result\");\n\tsz = sizeof(uint64_t);\n\tassert_d_eq(mallctl(\"stats.arenas.0.npurge\", &npurge, &sz, NULL, 0),\n\t    expected, \"Unexepected mallctl() result\");\n\tassert_d_eq(mallctl(\"stats.arenas.0.nmadvise\", &nmadvise, &sz, NULL, 0),\n\t    expected, \"Unexepected mallctl() result\");\n\tassert_d_eq(mallctl(\"stats.arenas.0.purged\", &purged, &sz, NULL, 0),\n\t    expected, \"Unexepected mallctl() result\");\n\n\tif (config_stats) {\n\t\tassert_u64_gt(npurge, 0,\n\t\t    \"At least one purge should have occurred\");\n\t\tassert_u64_le(nmadvise, purged,\n\t\t    \"nmadvise should be no greater than purged\");\n\t}\n\n\tdallocx(little, 0);\n\tdallocx(large, 0);\n\tdallocx(huge, 0);\n}\nTEST_END\n\nvoid *\nthd_start(void *arg)\n{\n\n\treturn (NULL);\n}\n\nstatic void\nno_lazy_lock(void)\n{\n\tthd_t thd;\n\n\tthd_create(&thd, thd_start, NULL);\n\tthd_join(thd, NULL);\n}\n\nTEST_BEGIN(test_stats_arenas_small)\n{\n\tunsigned arena;\n\tvoid *p;\n\tsize_t sz, allocated;\n\tuint64_t epoch, nmalloc, ndalloc, nrequests;\n\tint expected = config_stats ? 0 : ENOENT;\n\n\tno_lazy_lock(); /* Lazy locking would dodge tcache testing. */\n\n\tarena = 0;\n\tassert_d_eq(mallctl(\"thread.arena\", NULL, NULL, &arena, sizeof(arena)),\n\t    0, \"Unexpected mallctl() failure\");\n\n\tp = mallocx(SMALL_MAXCLASS, 0);\n\tassert_ptr_not_null(p, \"Unexpected mallocx() failure\");\n\n\tassert_d_eq(mallctl(\"thread.tcache.flush\", NULL, NULL, NULL, 0),\n\t    config_tcache ? 0 : ENOENT, \"Unexpected mallctl() result\");\n\n\tassert_d_eq(mallctl(\"epoch\", NULL, NULL, &epoch, sizeof(epoch)), 0,\n\t    \"Unexpected mallctl() failure\");\n\n\tsz = sizeof(size_t);\n\tassert_d_eq(mallctl(\"stats.arenas.0.small.allocated\", &allocated, &sz,\n\t    NULL, 0), expected, \"Unexpected mallctl() result\");\n\tsz = sizeof(uint64_t);\n\tassert_d_eq(mallctl(\"stats.arenas.0.small.nmalloc\", &nmalloc, &sz,\n\t    NULL, 0), expected, \"Unexpected mallctl() result\");\n\tassert_d_eq(mallctl(\"stats.arenas.0.small.ndalloc\", &ndalloc, &sz,\n\t    NULL, 0), expected, \"Unexpected mallctl() result\");\n\tassert_d_eq(mallctl(\"stats.arenas.0.small.nrequests\", &nrequests, &sz,\n\t    NULL, 0), expected, \"Unexpected mallctl() result\");\n\n\tif (config_stats) {\n\t\tassert_zu_gt(allocated, 0,\n\t\t    \"allocated should be greater than zero\");\n\t\tassert_u64_gt(nmalloc, 0,\n\t\t    \"nmalloc should be no greater than zero\");\n\t\tassert_u64_ge(nmalloc, ndalloc,\n\t\t    \"nmalloc should be at least as large as ndalloc\");\n\t\tassert_u64_gt(nrequests, 0,\n\t\t    \"nrequests should be greater than zero\");\n\t}\n\n\tdallocx(p, 0);\n}\nTEST_END\n\nTEST_BEGIN(test_stats_arenas_large)\n{\n\tunsigned arena;\n\tvoid *p;\n\tsize_t sz, allocated;\n\tuint64_t epoch, nmalloc, ndalloc, nrequests;\n\tint expected = config_stats ? 0 : ENOENT;\n\n\tarena = 0;\n\tassert_d_eq(mallctl(\"thread.arena\", NULL, NULL, &arena, sizeof(arena)),\n\t    0, \"Unexpected mallctl() failure\");\n\n\tp = mallocx(large_maxclass, 0);\n\tassert_ptr_not_null(p, \"Unexpected mallocx() failure\");\n\n\tassert_d_eq(mallctl(\"epoch\", NULL, NULL, &epoch, sizeof(epoch)), 0,\n\t    \"Unexpected mallctl() failure\");\n\n\tsz = sizeof(size_t);\n\tassert_d_eq(mallctl(\"stats.arenas.0.large.allocated\", &allocated, &sz,\n\t    NULL, 0), expected, \"Unexpected mallctl() result\");\n\tsz = sizeof(uint64_t);\n\tassert_d_eq(mallctl(\"stats.arenas.0.large.nmalloc\", &nmalloc, &sz,\n\t    NULL, 0), expected, \"Unexpected mallctl() result\");\n\tassert_d_eq(mallctl(\"stats.arenas.0.large.ndalloc\", &ndalloc, &sz,\n\t    NULL, 0), expected, \"Unexpected mallctl() result\");\n\tassert_d_eq(mallctl(\"stats.arenas.0.large.nrequests\", &nrequests, &sz,\n\t    NULL, 0), expected, \"Unexpected mallctl() result\");\n\n\tif (config_stats) {\n\t\tassert_zu_gt(allocated, 0,\n\t\t    \"allocated should be greater than zero\");\n\t\tassert_zu_gt(nmalloc, 0,\n\t\t    \"nmalloc should be greater than zero\");\n\t\tassert_zu_ge(nmalloc, ndalloc,\n\t\t    \"nmalloc should be at least as large as ndalloc\");\n\t\tassert_zu_gt(nrequests, 0,\n\t\t    \"nrequests should be greater than zero\");\n\t}\n\n\tdallocx(p, 0);\n}\nTEST_END\n\nTEST_BEGIN(test_stats_arenas_huge)\n{\n\tunsigned arena;\n\tvoid *p;\n\tsize_t sz, allocated;\n\tuint64_t epoch, nmalloc, ndalloc;\n\tint expected = config_stats ? 0 : ENOENT;\n\n\tarena = 0;\n\tassert_d_eq(mallctl(\"thread.arena\", NULL, NULL, &arena, sizeof(arena)),\n\t    0, \"Unexpected mallctl() failure\");\n\n\tp = mallocx(chunksize, 0);\n\tassert_ptr_not_null(p, \"Unexpected mallocx() failure\");\n\n\tassert_d_eq(mallctl(\"epoch\", NULL, NULL, &epoch, sizeof(epoch)), 0,\n\t    \"Unexpected mallctl() failure\");\n\n\tsz = sizeof(size_t);\n\tassert_d_eq(mallctl(\"stats.arenas.0.huge.allocated\", &allocated, &sz,\n\t    NULL, 0), expected, \"Unexpected mallctl() result\");\n\tsz = sizeof(uint64_t);\n\tassert_d_eq(mallctl(\"stats.arenas.0.huge.nmalloc\", &nmalloc, &sz,\n\t    NULL, 0), expected, \"Unexpected mallctl() result\");\n\tassert_d_eq(mallctl(\"stats.arenas.0.huge.ndalloc\", &ndalloc, &sz,\n\t    NULL, 0), expected, \"Unexpected mallctl() result\");\n\n\tif (config_stats) {\n\t\tassert_zu_gt(allocated, 0,\n\t\t    \"allocated should be greater than zero\");\n\t\tassert_zu_gt(nmalloc, 0,\n\t\t    \"nmalloc should be greater than zero\");\n\t\tassert_zu_ge(nmalloc, ndalloc,\n\t\t    \"nmalloc should be at least as large as ndalloc\");\n\t}\n\n\tdallocx(p, 0);\n}\nTEST_END\n\nTEST_BEGIN(test_stats_arenas_bins)\n{\n\tunsigned arena;\n\tvoid *p;\n\tsize_t sz, curruns, curregs;\n\tuint64_t epoch, nmalloc, ndalloc, nrequests, nfills, nflushes;\n\tuint64_t nruns, nreruns;\n\tint expected = config_stats ? 0 : ENOENT;\n\n\tarena = 0;\n\tassert_d_eq(mallctl(\"thread.arena\", NULL, NULL, &arena, sizeof(arena)),\n\t    0, \"Unexpected mallctl() failure\");\n\n\tp = mallocx(arena_bin_info[0].reg_size, 0);\n\tassert_ptr_not_null(p, \"Unexpected mallocx() failure\");\n\n\tassert_d_eq(mallctl(\"thread.tcache.flush\", NULL, NULL, NULL, 0),\n\t    config_tcache ? 0 : ENOENT, \"Unexpected mallctl() result\");\n\n\tassert_d_eq(mallctl(\"epoch\", NULL, NULL, &epoch, sizeof(epoch)), 0,\n\t    \"Unexpected mallctl() failure\");\n\n\tsz = sizeof(uint64_t);\n\tassert_d_eq(mallctl(\"stats.arenas.0.bins.0.nmalloc\", &nmalloc, &sz,\n\t    NULL, 0), expected, \"Unexpected mallctl() result\");\n\tassert_d_eq(mallctl(\"stats.arenas.0.bins.0.ndalloc\", &ndalloc, &sz,\n\t    NULL, 0), expected, \"Unexpected mallctl() result\");\n\tassert_d_eq(mallctl(\"stats.arenas.0.bins.0.nrequests\", &nrequests, &sz,\n\t    NULL, 0), expected, \"Unexpected mallctl() result\");\n\tsz = sizeof(size_t);\n\tassert_d_eq(mallctl(\"stats.arenas.0.bins.0.curregs\", &curregs, &sz,\n\t    NULL, 0), expected, \"Unexpected mallctl() result\");\n\n\tsz = sizeof(uint64_t);\n\tassert_d_eq(mallctl(\"stats.arenas.0.bins.0.nfills\", &nfills, &sz,\n\t    NULL, 0), config_tcache ? expected : ENOENT,\n\t    \"Unexpected mallctl() result\");\n\tassert_d_eq(mallctl(\"stats.arenas.0.bins.0.nflushes\", &nflushes, &sz,\n\t    NULL, 0), config_tcache ? expected : ENOENT,\n\t    \"Unexpected mallctl() result\");\n\n\tassert_d_eq(mallctl(\"stats.arenas.0.bins.0.nruns\", &nruns, &sz,\n\t    NULL, 0), expected, \"Unexpected mallctl() result\");\n\tassert_d_eq(mallctl(\"stats.arenas.0.bins.0.nreruns\", &nreruns, &sz,\n\t    NULL, 0), expected, \"Unexpected mallctl() result\");\n\tsz = sizeof(size_t);\n\tassert_d_eq(mallctl(\"stats.arenas.0.bins.0.curruns\", &curruns, &sz,\n\t    NULL, 0), expected, \"Unexpected mallctl() result\");\n\n\tif (config_stats) {\n\t\tassert_u64_gt(nmalloc, 0,\n\t\t    \"nmalloc should be greater than zero\");\n\t\tassert_u64_ge(nmalloc, ndalloc,\n\t\t    \"nmalloc should be at least as large as ndalloc\");\n\t\tassert_u64_gt(nrequests, 0,\n\t\t    \"nrequests should be greater than zero\");\n\t\tassert_zu_gt(curregs, 0,\n\t\t    \"allocated should be greater than zero\");\n\t\tif (config_tcache) {\n\t\t\tassert_u64_gt(nfills, 0,\n\t\t\t    \"At least one fill should have occurred\");\n\t\t\tassert_u64_gt(nflushes, 0,\n\t\t\t    \"At least one flush should have occurred\");\n\t\t}\n\t\tassert_u64_gt(nruns, 0,\n\t\t    \"At least one run should have been allocated\");\n\t\tassert_zu_gt(curruns, 0,\n\t\t    \"At least one run should be currently allocated\");\n\t}\n\n\tdallocx(p, 0);\n}\nTEST_END\n\nTEST_BEGIN(test_stats_arenas_lruns)\n{\n\tunsigned arena;\n\tvoid *p;\n\tuint64_t epoch, nmalloc, ndalloc, nrequests;\n\tsize_t curruns, sz;\n\tint expected = config_stats ? 0 : ENOENT;\n\n\tarena = 0;\n\tassert_d_eq(mallctl(\"thread.arena\", NULL, NULL, &arena, sizeof(arena)),\n\t    0, \"Unexpected mallctl() failure\");\n\n\tp = mallocx(LARGE_MINCLASS, 0);\n\tassert_ptr_not_null(p, \"Unexpected mallocx() failure\");\n\n\tassert_d_eq(mallctl(\"epoch\", NULL, NULL, &epoch, sizeof(epoch)), 0,\n\t    \"Unexpected mallctl() failure\");\n\n\tsz = sizeof(uint64_t);\n\tassert_d_eq(mallctl(\"stats.arenas.0.lruns.0.nmalloc\", &nmalloc, &sz,\n\t    NULL, 0), expected, \"Unexpected mallctl() result\");\n\tassert_d_eq(mallctl(\"stats.arenas.0.lruns.0.ndalloc\", &ndalloc, &sz,\n\t    NULL, 0), expected, \"Unexpected mallctl() result\");\n\tassert_d_eq(mallctl(\"stats.arenas.0.lruns.0.nrequests\", &nrequests, &sz,\n\t    NULL, 0), expected, \"Unexpected mallctl() result\");\n\tsz = sizeof(size_t);\n\tassert_d_eq(mallctl(\"stats.arenas.0.lruns.0.curruns\", &curruns, &sz,\n\t    NULL, 0), expected, \"Unexpected mallctl() result\");\n\n\tif (config_stats) {\n\t\tassert_u64_gt(nmalloc, 0,\n\t\t    \"nmalloc should be greater than zero\");\n\t\tassert_u64_ge(nmalloc, ndalloc,\n\t\t    \"nmalloc should be at least as large as ndalloc\");\n\t\tassert_u64_gt(nrequests, 0,\n\t\t    \"nrequests should be greater than zero\");\n\t\tassert_u64_gt(curruns, 0,\n\t\t    \"At least one run should be currently allocated\");\n\t}\n\n\tdallocx(p, 0);\n}\nTEST_END\n\nTEST_BEGIN(test_stats_arenas_hchunks)\n{\n\tunsigned arena;\n\tvoid *p;\n\tuint64_t epoch, nmalloc, ndalloc;\n\tsize_t curhchunks, sz;\n\tint expected = config_stats ? 0 : ENOENT;\n\n\tarena = 0;\n\tassert_d_eq(mallctl(\"thread.arena\", NULL, NULL, &arena, sizeof(arena)),\n\t    0, \"Unexpected mallctl() failure\");\n\n\tp = mallocx(chunksize, 0);\n\tassert_ptr_not_null(p, \"Unexpected mallocx() failure\");\n\n\tassert_d_eq(mallctl(\"epoch\", NULL, NULL, &epoch, sizeof(epoch)), 0,\n\t    \"Unexpected mallctl() failure\");\n\n\tsz = sizeof(uint64_t);\n\tassert_d_eq(mallctl(\"stats.arenas.0.hchunks.0.nmalloc\", &nmalloc, &sz,\n\t    NULL, 0), expected, \"Unexpected mallctl() result\");\n\tassert_d_eq(mallctl(\"stats.arenas.0.hchunks.0.ndalloc\", &ndalloc, &sz,\n\t    NULL, 0), expected, \"Unexpected mallctl() result\");\n\tsz = sizeof(size_t);\n\tassert_d_eq(mallctl(\"stats.arenas.0.hchunks.0.curhchunks\", &curhchunks,\n\t    &sz, NULL, 0), expected, \"Unexpected mallctl() result\");\n\n\tif (config_stats) {\n\t\tassert_u64_gt(nmalloc, 0,\n\t\t    \"nmalloc should be greater than zero\");\n\t\tassert_u64_ge(nmalloc, ndalloc,\n\t\t    \"nmalloc should be at least as large as ndalloc\");\n\t\tassert_u64_gt(curhchunks, 0,\n\t\t    \"At least one chunk should be currently allocated\");\n\t}\n\n\tdallocx(p, 0);\n}\nTEST_END\n\nint\nmain(void)\n{\n\n\treturn (test(\n\t    test_stats_summary,\n\t    test_stats_huge,\n\t    test_stats_arenas_summary,\n\t    test_stats_arenas_small,\n\t    test_stats_arenas_large,\n\t    test_stats_arenas_huge,\n\t    test_stats_arenas_bins,\n\t    test_stats_arenas_lruns,\n\t    test_stats_arenas_hchunks));\n}\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.8/deps/jemalloc/test/unit/tsd.c",
    "content": "#include \"test/jemalloc_test.h\"\n\n#define\tTHREAD_DATA 0x72b65c10\n\ntypedef unsigned int data_t;\n\nstatic bool data_cleanup_executed;\n\nmalloc_tsd_types(data_, data_t)\nmalloc_tsd_protos(, data_, data_t)\n\nvoid\ndata_cleanup(void *arg)\n{\n\tdata_t *data = (data_t *)arg;\n\n\tif (!data_cleanup_executed) {\n\t\tassert_x_eq(*data, THREAD_DATA,\n\t\t    \"Argument passed into cleanup function should match tsd \"\n\t\t    \"value\");\n\t}\n\tdata_cleanup_executed = true;\n\n\t/*\n\t * Allocate during cleanup for two rounds, in order to assure that\n\t * jemalloc's internal tsd reinitialization happens.\n\t */\n\tswitch (*data) {\n\tcase THREAD_DATA:\n\t\t*data = 1;\n\t\tdata_tsd_set(data);\n\t\tbreak;\n\tcase 1:\n\t\t*data = 2;\n\t\tdata_tsd_set(data);\n\t\tbreak;\n\tcase 2:\n\t\treturn;\n\tdefault:\n\t\tnot_reached();\n\t}\n\n\t{\n\t\tvoid *p = mallocx(1, 0);\n\t\tassert_ptr_not_null(p, \"Unexpeced mallocx() failure\");\n\t\tdallocx(p, 0);\n\t}\n}\n\nmalloc_tsd_externs(data_, data_t)\n#define\tDATA_INIT 0x12345678\nmalloc_tsd_data(, data_, data_t, DATA_INIT)\nmalloc_tsd_funcs(, data_, data_t, DATA_INIT, data_cleanup)\n\nstatic void *\nthd_start(void *arg)\n{\n\tdata_t d = (data_t)(uintptr_t)arg;\n\tvoid *p;\n\n\tassert_x_eq(*data_tsd_get(), DATA_INIT,\n\t    \"Initial tsd get should return initialization value\");\n\n\tp = malloc(1);\n\tassert_ptr_not_null(p, \"Unexpected malloc() failure\");\n\n\tdata_tsd_set(&d);\n\tassert_x_eq(*data_tsd_get(), d,\n\t    \"After tsd set, tsd get should return value that was set\");\n\n\td = 0;\n\tassert_x_eq(*data_tsd_get(), (data_t)(uintptr_t)arg,\n\t    \"Resetting local data should have no effect on tsd\");\n\n\tfree(p);\n\treturn (NULL);\n}\n\nTEST_BEGIN(test_tsd_main_thread)\n{\n\n\tthd_start((void *) 0xa5f3e329);\n}\nTEST_END\n\nTEST_BEGIN(test_tsd_sub_thread)\n{\n\tthd_t thd;\n\n\tdata_cleanup_executed = false;\n\tthd_create(&thd, thd_start, (void *)THREAD_DATA);\n\tthd_join(thd, NULL);\n\tassert_true(data_cleanup_executed,\n\t    \"Cleanup function should have executed\");\n}\nTEST_END\n\nint\nmain(void)\n{\n\n\tdata_tsd_boot();\n\n\treturn (test(\n\t    test_tsd_main_thread,\n\t    test_tsd_sub_thread));\n}\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.8/deps/jemalloc/test/unit/util.c",
    "content": "#include \"test/jemalloc_test.h\"\n\nTEST_BEGIN(test_pow2_ceil)\n{\n\tunsigned i, pow2;\n\tsize_t x;\n\n\tassert_zu_eq(pow2_ceil(0), 0, \"Unexpected result\");\n\n\tfor (i = 0; i < sizeof(size_t) * 8; i++) {\n\t\tassert_zu_eq(pow2_ceil(ZU(1) << i), ZU(1) << i,\n\t\t    \"Unexpected result\");\n\t}\n\n\tfor (i = 2; i < sizeof(size_t) * 8; i++) {\n\t\tassert_zu_eq(pow2_ceil((ZU(1) << i) - 1), ZU(1) << i,\n\t\t    \"Unexpected result\");\n\t}\n\n\tfor (i = 0; i < sizeof(size_t) * 8 - 1; i++) {\n\t\tassert_zu_eq(pow2_ceil((ZU(1) << i) + 1), ZU(1) << (i+1),\n\t\t    \"Unexpected result\");\n\t}\n\n\tfor (pow2 = 1; pow2 < 25; pow2++) {\n\t\tfor (x = (ZU(1) << (pow2-1)) + 1; x <= ZU(1) << pow2; x++) {\n\t\t\tassert_zu_eq(pow2_ceil(x), ZU(1) << pow2,\n\t\t\t    \"Unexpected result, x=%zu\", x);\n\t\t}\n\t}\n}\nTEST_END\n\nTEST_BEGIN(test_malloc_strtoumax_no_endptr)\n{\n\tint err;\n\n\tset_errno(0);\n\tassert_ju_eq(malloc_strtoumax(\"0\", NULL, 0), 0, \"Unexpected result\");\n\terr = get_errno();\n\tassert_d_eq(err, 0, \"Unexpected failure\");\n}\nTEST_END\n\nTEST_BEGIN(test_malloc_strtoumax)\n{\n\tstruct test_s {\n\t\tconst char *input;\n\t\tconst char *expected_remainder;\n\t\tint base;\n\t\tint expected_errno;\n\t\tconst char *expected_errno_name;\n\t\tuintmax_t expected_x;\n\t};\n#define\tERR(e)\t\te, #e\n#define\tKUMAX(x)\t((uintmax_t)x##ULL)\n\tstruct test_s tests[] = {\n\t\t{\"0\",\t\t\"0\",\t-1,\tERR(EINVAL),\tUINTMAX_MAX},\n\t\t{\"0\",\t\t\"0\",\t1,\tERR(EINVAL),\tUINTMAX_MAX},\n\t\t{\"0\",\t\t\"0\",\t37,\tERR(EINVAL),\tUINTMAX_MAX},\n\n\t\t{\"\",\t\t\"\",\t0,\tERR(EINVAL),\tUINTMAX_MAX},\n\t\t{\"+\",\t\t\"+\",\t0,\tERR(EINVAL),\tUINTMAX_MAX},\n\t\t{\"++3\",\t\t\"++3\",\t0,\tERR(EINVAL),\tUINTMAX_MAX},\n\t\t{\"-\",\t\t\"-\",\t0,\tERR(EINVAL),\tUINTMAX_MAX},\n\n\t\t{\"42\",\t\t\"\",\t0,\tERR(0),\t\tKUMAX(42)},\n\t\t{\"+42\",\t\t\"\",\t0,\tERR(0),\t\tKUMAX(42)},\n\t\t{\"-42\",\t\t\"\",\t0,\tERR(0),\t\tKUMAX(-42)},\n\t\t{\"042\",\t\t\"\",\t0,\tERR(0),\t\tKUMAX(042)},\n\t\t{\"+042\",\t\"\",\t0,\tERR(0),\t\tKUMAX(042)},\n\t\t{\"-042\",\t\"\",\t0,\tERR(0),\t\tKUMAX(-042)},\n\t\t{\"0x42\",\t\"\",\t0,\tERR(0),\t\tKUMAX(0x42)},\n\t\t{\"+0x42\",\t\"\",\t0,\tERR(0),\t\tKUMAX(0x42)},\n\t\t{\"-0x42\",\t\"\",\t0,\tERR(0),\t\tKUMAX(-0x42)},\n\n\t\t{\"0\",\t\t\"\",\t0,\tERR(0),\t\tKUMAX(0)},\n\t\t{\"1\",\t\t\"\",\t0,\tERR(0),\t\tKUMAX(1)},\n\n\t\t{\"42\",\t\t\"\",\t0,\tERR(0),\t\tKUMAX(42)},\n\t\t{\" 42\",\t\t\"\",\t0,\tERR(0),\t\tKUMAX(42)},\n\t\t{\"42 \",\t\t\" \",\t0,\tERR(0),\t\tKUMAX(42)},\n\t\t{\"0x\",\t\t\"x\",\t0,\tERR(0),\t\tKUMAX(0)},\n\t\t{\"42x\",\t\t\"x\",\t0,\tERR(0),\t\tKUMAX(42)},\n\n\t\t{\"07\",\t\t\"\",\t0,\tERR(0),\t\tKUMAX(7)},\n\t\t{\"010\",\t\t\"\",\t0,\tERR(0),\t\tKUMAX(8)},\n\t\t{\"08\",\t\t\"8\",\t0,\tERR(0),\t\tKUMAX(0)},\n\t\t{\"0_\",\t\t\"_\",\t0,\tERR(0),\t\tKUMAX(0)},\n\n\t\t{\"0x\",\t\t\"x\",\t0,\tERR(0),\t\tKUMAX(0)},\n\t\t{\"0X\",\t\t\"X\",\t0,\tERR(0),\t\tKUMAX(0)},\n\t\t{\"0xg\",\t\t\"xg\",\t0,\tERR(0),\t\tKUMAX(0)},\n\t\t{\"0XA\",\t\t\"\",\t0,\tERR(0),\t\tKUMAX(10)},\n\n\t\t{\"010\",\t\t\"\",\t10,\tERR(0),\t\tKUMAX(10)},\n\t\t{\"0x3\",\t\t\"x3\",\t10,\tERR(0),\t\tKUMAX(0)},\n\n\t\t{\"12\",\t\t\"2\",\t2,\tERR(0),\t\tKUMAX(1)},\n\t\t{\"78\",\t\t\"8\",\t8,\tERR(0),\t\tKUMAX(7)},\n\t\t{\"9a\",\t\t\"a\",\t10,\tERR(0),\t\tKUMAX(9)},\n\t\t{\"9A\",\t\t\"A\",\t10,\tERR(0),\t\tKUMAX(9)},\n\t\t{\"fg\",\t\t\"g\",\t16,\tERR(0),\t\tKUMAX(15)},\n\t\t{\"FG\",\t\t\"G\",\t16,\tERR(0),\t\tKUMAX(15)},\n\t\t{\"0xfg\",\t\"g\",\t16,\tERR(0),\t\tKUMAX(15)},\n\t\t{\"0XFG\",\t\"G\",\t16,\tERR(0),\t\tKUMAX(15)},\n\t\t{\"z_\",\t\t\"_\",\t36,\tERR(0),\t\tKUMAX(35)},\n\t\t{\"Z_\",\t\t\"_\",\t36,\tERR(0),\t\tKUMAX(35)}\n\t};\n#undef ERR\n#undef KUMAX\n\tunsigned i;\n\n\tfor (i = 0; i < sizeof(tests)/sizeof(struct test_s); i++) {\n\t\tstruct test_s *test = &tests[i];\n\t\tint err;\n\t\tuintmax_t result;\n\t\tchar *remainder;\n\n\t\tset_errno(0);\n\t\tresult = malloc_strtoumax(test->input, &remainder, test->base);\n\t\terr = get_errno();\n\t\tassert_d_eq(err, test->expected_errno,\n\t\t    \"Expected errno %s for \\\"%s\\\", base %d\",\n\t\t    test->expected_errno_name, test->input, test->base);\n\t\tassert_str_eq(remainder, test->expected_remainder,\n\t\t    \"Unexpected remainder for \\\"%s\\\", base %d\",\n\t\t    test->input, test->base);\n\t\tif (err == 0) {\n\t\t\tassert_ju_eq(result, test->expected_x,\n\t\t\t    \"Unexpected result for \\\"%s\\\", base %d\",\n\t\t\t    test->input, test->base);\n\t\t}\n\t}\n}\nTEST_END\n\nTEST_BEGIN(test_malloc_snprintf_truncated)\n{\n#define\tBUFLEN\t15\n\tchar buf[BUFLEN];\n\tint result;\n\tsize_t len;\n#define TEST(expected_str_untruncated, ...) do {\t\t\t\\\n\tresult = malloc_snprintf(buf, len, __VA_ARGS__);\t\t\\\n\tassert_d_eq(strncmp(buf, expected_str_untruncated, len-1), 0,\t\\\n\t    \"Unexpected string inequality (\\\"%s\\\" vs \\\"%s\\\")\",\t\t\\\n\t    buf, expected_str_untruncated);\t\t\\\n\tassert_d_eq(result, strlen(expected_str_untruncated),\t\t\\\n\t    \"Unexpected result\");\t\t\t\t\t\\\n} while (0)\n\n\tfor (len = 1; len < BUFLEN; len++) {\n\t\tTEST(\"012346789\",\t\"012346789\");\n\t\tTEST(\"a0123b\",\t\t\"a%sb\", \"0123\");\n\t\tTEST(\"a01234567\",\t\"a%s%s\", \"0123\", \"4567\");\n\t\tTEST(\"a0123  \",\t\t\"a%-6s\", \"0123\");\n\t\tTEST(\"a  0123\",\t\t\"a%6s\", \"0123\");\n\t\tTEST(\"a   012\",\t\t\"a%6.3s\", \"0123\");\n\t\tTEST(\"a   012\",\t\t\"a%*.*s\", 6, 3, \"0123\");\n\t\tTEST(\"a 123b\",\t\t\"a% db\", 123);\n\t\tTEST(\"a123b\",\t\t\"a%-db\", 123);\n\t\tTEST(\"a-123b\",\t\t\"a%-db\", -123);\n\t\tTEST(\"a+123b\",\t\t\"a%+db\", 123);\n\t}\n#undef BUFLEN\n#undef TEST\n}\nTEST_END\n\nTEST_BEGIN(test_malloc_snprintf)\n{\n#define\tBUFLEN\t128\n\tchar buf[BUFLEN];\n\tint result;\n#define\tTEST(expected_str, ...) do {\t\t\t\t\t\\\n\tresult = malloc_snprintf(buf, sizeof(buf), __VA_ARGS__);\t\\\n\tassert_str_eq(buf, expected_str, \"Unexpected output\");\t\t\\\n\tassert_d_eq(result, strlen(expected_str), \"Unexpected result\");\t\\\n} while (0)\n\n\tTEST(\"hello\", \"hello\");\n\n\tTEST(\"50%, 100%\", \"50%%, %d%%\", 100);\n\n\tTEST(\"a0123b\", \"a%sb\", \"0123\");\n\n\tTEST(\"a 0123b\", \"a%5sb\", \"0123\");\n\tTEST(\"a 0123b\", \"a%*sb\", 5, \"0123\");\n\n\tTEST(\"a0123 b\", \"a%-5sb\", \"0123\");\n\tTEST(\"a0123b\", \"a%*sb\", -1, \"0123\");\n\tTEST(\"a0123 b\", \"a%*sb\", -5, \"0123\");\n\tTEST(\"a0123 b\", \"a%-*sb\", -5, \"0123\");\n\n\tTEST(\"a012b\", \"a%.3sb\", \"0123\");\n\tTEST(\"a012b\", \"a%.*sb\", 3, \"0123\");\n\tTEST(\"a0123b\", \"a%.*sb\", -3, \"0123\");\n\n\tTEST(\"a  012b\", \"a%5.3sb\", \"0123\");\n\tTEST(\"a  012b\", \"a%5.*sb\", 3, \"0123\");\n\tTEST(\"a  012b\", \"a%*.3sb\", 5, \"0123\");\n\tTEST(\"a  012b\", \"a%*.*sb\", 5, 3, \"0123\");\n\tTEST(\"a 0123b\", \"a%*.*sb\", 5, -3, \"0123\");\n\n\tTEST(\"_abcd_\", \"_%x_\", 0xabcd);\n\tTEST(\"_0xabcd_\", \"_%#x_\", 0xabcd);\n\tTEST(\"_1234_\", \"_%o_\", 01234);\n\tTEST(\"_01234_\", \"_%#o_\", 01234);\n\tTEST(\"_1234_\", \"_%u_\", 1234);\n\n\tTEST(\"_1234_\", \"_%d_\", 1234);\n\tTEST(\"_ 1234_\", \"_% d_\", 1234);\n\tTEST(\"_+1234_\", \"_%+d_\", 1234);\n\tTEST(\"_-1234_\", \"_%d_\", -1234);\n\tTEST(\"_-1234_\", \"_% d_\", -1234);\n\tTEST(\"_-1234_\", \"_%+d_\", -1234);\n\n\tTEST(\"_-1234_\", \"_%d_\", -1234);\n\tTEST(\"_1234_\", \"_%d_\", 1234);\n\tTEST(\"_-1234_\", \"_%i_\", -1234);\n\tTEST(\"_1234_\", \"_%i_\", 1234);\n\tTEST(\"_01234_\", \"_%#o_\", 01234);\n\tTEST(\"_1234_\", \"_%u_\", 1234);\n\tTEST(\"_0x1234abc_\", \"_%#x_\", 0x1234abc);\n\tTEST(\"_0X1234ABC_\", \"_%#X_\", 0x1234abc);\n\tTEST(\"_c_\", \"_%c_\", 'c');\n\tTEST(\"_string_\", \"_%s_\", \"string\");\n\tTEST(\"_0x42_\", \"_%p_\", ((void *)0x42));\n\n\tTEST(\"_-1234_\", \"_%ld_\", ((long)-1234));\n\tTEST(\"_1234_\", \"_%ld_\", ((long)1234));\n\tTEST(\"_-1234_\", \"_%li_\", ((long)-1234));\n\tTEST(\"_1234_\", \"_%li_\", ((long)1234));\n\tTEST(\"_01234_\", \"_%#lo_\", ((long)01234));\n\tTEST(\"_1234_\", \"_%lu_\", ((long)1234));\n\tTEST(\"_0x1234abc_\", \"_%#lx_\", ((long)0x1234abc));\n\tTEST(\"_0X1234ABC_\", \"_%#lX_\", ((long)0x1234ABC));\n\n\tTEST(\"_-1234_\", \"_%lld_\", ((long long)-1234));\n\tTEST(\"_1234_\", \"_%lld_\", ((long long)1234));\n\tTEST(\"_-1234_\", \"_%lli_\", ((long long)-1234));\n\tTEST(\"_1234_\", \"_%lli_\", ((long long)1234));\n\tTEST(\"_01234_\", \"_%#llo_\", ((long long)01234));\n\tTEST(\"_1234_\", \"_%llu_\", ((long long)1234));\n\tTEST(\"_0x1234abc_\", \"_%#llx_\", ((long long)0x1234abc));\n\tTEST(\"_0X1234ABC_\", \"_%#llX_\", ((long long)0x1234ABC));\n\n\tTEST(\"_-1234_\", \"_%qd_\", ((long long)-1234));\n\tTEST(\"_1234_\", \"_%qd_\", ((long long)1234));\n\tTEST(\"_-1234_\", \"_%qi_\", ((long long)-1234));\n\tTEST(\"_1234_\", \"_%qi_\", ((long long)1234));\n\tTEST(\"_01234_\", \"_%#qo_\", ((long long)01234));\n\tTEST(\"_1234_\", \"_%qu_\", ((long long)1234));\n\tTEST(\"_0x1234abc_\", \"_%#qx_\", ((long long)0x1234abc));\n\tTEST(\"_0X1234ABC_\", \"_%#qX_\", ((long long)0x1234ABC));\n\n\tTEST(\"_-1234_\", \"_%jd_\", ((intmax_t)-1234));\n\tTEST(\"_1234_\", \"_%jd_\", ((intmax_t)1234));\n\tTEST(\"_-1234_\", \"_%ji_\", ((intmax_t)-1234));\n\tTEST(\"_1234_\", \"_%ji_\", ((intmax_t)1234));\n\tTEST(\"_01234_\", \"_%#jo_\", ((intmax_t)01234));\n\tTEST(\"_1234_\", \"_%ju_\", ((intmax_t)1234));\n\tTEST(\"_0x1234abc_\", \"_%#jx_\", ((intmax_t)0x1234abc));\n\tTEST(\"_0X1234ABC_\", \"_%#jX_\", ((intmax_t)0x1234ABC));\n\n\tTEST(\"_1234_\", \"_%td_\", ((ptrdiff_t)1234));\n\tTEST(\"_-1234_\", \"_%td_\", ((ptrdiff_t)-1234));\n\tTEST(\"_1234_\", \"_%ti_\", ((ptrdiff_t)1234));\n\tTEST(\"_-1234_\", \"_%ti_\", ((ptrdiff_t)-1234));\n\n\tTEST(\"_-1234_\", \"_%zd_\", ((ssize_t)-1234));\n\tTEST(\"_1234_\", \"_%zd_\", ((ssize_t)1234));\n\tTEST(\"_-1234_\", \"_%zi_\", ((ssize_t)-1234));\n\tTEST(\"_1234_\", \"_%zi_\", ((ssize_t)1234));\n\tTEST(\"_01234_\", \"_%#zo_\", ((ssize_t)01234));\n\tTEST(\"_1234_\", \"_%zu_\", ((ssize_t)1234));\n\tTEST(\"_0x1234abc_\", \"_%#zx_\", ((ssize_t)0x1234abc));\n\tTEST(\"_0X1234ABC_\", \"_%#zX_\", ((ssize_t)0x1234ABC));\n#undef BUFLEN\n}\nTEST_END\n\nint\nmain(void)\n{\n\n\treturn (test(\n\t    test_pow2_ceil,\n\t    test_malloc_strtoumax_no_endptr,\n\t    test_malloc_strtoumax,\n\t    test_malloc_snprintf_truncated,\n\t    test_malloc_snprintf));\n}\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.8/deps/jemalloc/test/unit/zero.c",
    "content": "#include \"test/jemalloc_test.h\"\n\n#ifdef JEMALLOC_FILL\nconst char *malloc_conf =\n    \"abort:false,junk:false,zero:true,redzone:false,quarantine:0\";\n#endif\n\nstatic void\ntest_zero(size_t sz_min, size_t sz_max)\n{\n\tchar *s;\n\tsize_t sz_prev, sz, i;\n\n\tsz_prev = 0;\n\ts = (char *)mallocx(sz_min, 0);\n\tassert_ptr_not_null((void *)s, \"Unexpected mallocx() failure\");\n\n\tfor (sz = sallocx(s, 0); sz <= sz_max;\n\t    sz_prev = sz, sz = sallocx(s, 0)) {\n\t\tif (sz_prev > 0) {\n\t\t\tassert_c_eq(s[0], 'a',\n\t\t\t    \"Previously allocated byte %zu/%zu is corrupted\",\n\t\t\t    ZU(0), sz_prev);\n\t\t\tassert_c_eq(s[sz_prev-1], 'a',\n\t\t\t    \"Previously allocated byte %zu/%zu is corrupted\",\n\t\t\t    sz_prev-1, sz_prev);\n\t\t}\n\n\t\tfor (i = sz_prev; i < sz; i++) {\n\t\t\tassert_c_eq(s[i], 0x0,\n\t\t\t    \"Newly allocated byte %zu/%zu isn't zero-filled\",\n\t\t\t    i, sz);\n\t\t\ts[i] = 'a';\n\t\t}\n\n\t\tif (xallocx(s, sz+1, 0, 0) == sz) {\n\t\t\ts = (char *)rallocx(s, sz+1, 0);\n\t\t\tassert_ptr_not_null((void *)s,\n\t\t\t    \"Unexpected rallocx() failure\");\n\t\t}\n\t}\n\n\tdallocx(s, 0);\n}\n\nTEST_BEGIN(test_zero_small)\n{\n\n\ttest_skip_if(!config_fill);\n\ttest_zero(1, SMALL_MAXCLASS-1);\n}\nTEST_END\n\nTEST_BEGIN(test_zero_large)\n{\n\n\ttest_skip_if(!config_fill);\n\ttest_zero(SMALL_MAXCLASS+1, large_maxclass);\n}\nTEST_END\n\nTEST_BEGIN(test_zero_huge)\n{\n\n\ttest_skip_if(!config_fill);\n\ttest_zero(large_maxclass+1, chunksize*2);\n}\nTEST_END\n\nint\nmain(void)\n{\n\n\treturn (test(\n\t    test_zero_small,\n\t    test_zero_large,\n\t    test_zero_huge));\n}\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.8/deps/linenoise/.gitignore",
    "content": "linenoise_example\n*.dSYM\nhistory.txt\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.8/deps/linenoise/Makefile",
    "content": "STD=\nWARN= -Wall\nOPT= -Os\n\nR_CFLAGS= $(STD) $(WARN) $(OPT) $(DEBUG) $(CFLAGS)\nR_LDFLAGS= $(LDFLAGS)\nDEBUG= -g\n\nR_CC=$(CC) $(R_CFLAGS)\nR_LD=$(CC) $(R_LDFLAGS)\n\nlinenoise.o: linenoise.h linenoise.c\n\nlinenoise_example: linenoise.o example.o\n\t$(R_LD) -o $@ $^\n\n.c.o:\n\t$(R_CC) -c $<\n\nclean:\n\trm -f linenoise_example *.o\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.8/deps/linenoise/README.markdown",
    "content": "# Linenoise\n\nA minimal, zero-config, BSD licensed, readline replacement used in Redis,\nMongoDB, and Android.\n\n* Single and multi line editing mode with the usual key bindings implemented.\n* History handling.\n* Completion.\n* Hints (suggestions at the right of the prompt as you type).\n* About 1,100 lines of BSD license source code.\n* Only uses a subset of VT100 escapes (ANSI.SYS compatible).\n\n## Can a line editing library be 20k lines of code?\n\nLine editing with some support for history is a really important feature for command line utilities. Instead of retyping almost the same stuff again and again it's just much better to hit the up arrow and edit on syntax errors, or in order to try a slightly different command. But apparently code dealing with terminals is some sort of Black Magic: readline is 30k lines of code, libedit 20k. Is it reasonable to link small utilities to huge libraries just to get a minimal support for line editing?\n\nSo what usually happens is either:\n\n * Large programs with configure scripts disabling line editing if readline is not present in the system, or not supporting it at all since readline is GPL licensed and libedit (the BSD clone) is not as known and available as readline is (Real world example of this problem: Tclsh).\n * Smaller programs not using a configure script not supporting line editing at all (A problem we had with Redis-cli for instance).\n \nThe result is a pollution of binaries without line editing support.\n\nSo I spent more or less two hours doing a reality check resulting in this little library: is it *really* needed for a line editing library to be 20k lines of code? Apparently not, it is possibe to get a very small, zero configuration, trivial to embed library, that solves the problem. Smaller programs will just include this, supporing line editing out of the box. Larger programs may use this little library or just checking with configure if readline/libedit is available and resorting to Linenoise if not.\n\n## Terminals, in 2010.\n\nApparently almost every terminal you can happen to use today has some kind of support for basic VT100 escape sequences. So I tried to write a lib using just very basic VT100 features. The resulting library appears to work everywhere I tried to use it, and now can work even on ANSI.SYS compatible terminals, since no\nVT220 specific sequences are used anymore.\n\nThe library is currently about 1100 lines of code. In order to use it in your project just look at the *example.c* file in the source distribution, it is trivial. Linenoise is BSD code, so you can use both in free software and commercial software.\n\n## Tested with...\n\n * Linux text only console ($TERM = linux)\n * Linux KDE terminal application ($TERM = xterm)\n * Linux xterm ($TERM = xterm)\n * Linux Buildroot ($TERM = vt100)\n * Mac OS X iTerm ($TERM = xterm)\n * Mac OS X default Terminal.app ($TERM = xterm)\n * OpenBSD 4.5 through an OSX Terminal.app ($TERM = screen)\n * IBM AIX 6.1\n * FreeBSD xterm ($TERM = xterm)\n * ANSI.SYS\n * Emacs comint mode ($TERM = dumb)\n\nPlease test it everywhere you can and report back!\n\n## Let's push this forward!\n\nPatches should be provided in the respect of Linenoise sensibility for small\neasy to understand code.\n\nSend feedbacks to antirez at gmail\n\n# The API\n\nLinenoise is very easy to use, and reading the example shipped with the\nlibrary should get you up to speed ASAP. Here is a list of API calls\nand how to use them.\n\n    char *linenoise(const char *prompt);\n\nThis is the main Linenoise call: it shows the user a prompt with line editing\nand history capabilities. The prompt you specify is used as a prompt, that is,\nit will be printed to the left of the cursor. The library returns a buffer\nwith the line composed by the user, or NULL on end of file or when there\nis an out of memory condition.\n\nWhen a tty is detected (the user is actually typing into a terminal session)\nthe maximum editable line length is `LINENOISE_MAX_LINE`. When instead the\nstandard input is not a tty, which happens every time you redirect a file\nto a program, or use it in an Unix pipeline, there are no limits to the\nlength of the line that can be returned.\n\nThe returned line should be freed with the `free()` standard system call.\nHowever sometimes it could happen that your program uses a different dynamic\nallocation library, so you may also used `linenoiseFree` to make sure the\nline is freed with the same allocator it was created.\n\nThe canonical loop used by a program using Linenoise will be something like\nthis:\n\n    while((line = linenoise(\"hello> \")) != NULL) {\n        printf(\"You wrote: %s\\n\", line);\n        linenoiseFree(line); /* Or just free(line) if you use libc malloc. */\n    }\n\n## Single line VS multi line editing\n\nBy default, Linenoise uses single line editing, that is, a single row on the\nscreen will be used, and as the user types more, the text will scroll towards\nleft to make room. This works if your program is one where the user is\nunlikely to write a lot of text, otherwise multi line editing, where multiple\nscreens rows are used, can be a lot more comfortable.\n\nIn order to enable multi line editing use the following API call:\n\n    linenoiseSetMultiLine(1);\n\nYou can disable it using `0` as argument.\n\n## History\n\nLinenoise supporst history, so that the user does not have to retype\nagain and again the same things, but can use the down and up arrows in order\nto search and re-edit already inserted lines of text.\n\nThe followings are the history API calls:\n\n    int linenoiseHistoryAdd(const char *line);\n    int linenoiseHistorySetMaxLen(int len);\n    int linenoiseHistorySave(const char *filename);\n    int linenoiseHistoryLoad(const char *filename);\n\nUse `linenoiseHistoryAdd` every time you want to add a new element\nto the top of the history (it will be the first the user will see when\nusing the up arrow).\n\nNote that for history to work, you have to set a length for the history\n(which is zero by default, so history will be disabled if you don't set\na proper one). This is accomplished using the `linenoiseHistorySetMaxLen`\nfunction.\n\nLinenoise has direct support for persisting the history into an history\nfile. The functions `linenoiseHistorySave` and `linenoiseHistoryLoad` do\njust that. Both functions return -1 on error and 0 on success.\n\n## Completion\n\nLinenoise supports completion, which is the ability to complete the user\ninput when she or he presses the `<TAB>` key.\n\nIn order to use completion, you need to register a completion callback, which\nis called every time the user presses `<TAB>`. Your callback will return a\nlist of items that are completions for the current string.\n\nThe following is an example of registering a completion callback:\n\n    linenoiseSetCompletionCallback(completion);\n\nThe completion must be a function returning `void` and getting as input\na `const char` pointer, which is the line the user has typed so far, and\na `linenoiseCompletions` object pointer, which is used as argument of\n`linenoiseAddCompletion` in order to add completions inside the callback.\nAn example will make it more clear:\n\n    void completion(const char *buf, linenoiseCompletions *lc) {\n        if (buf[0] == 'h') {\n            linenoiseAddCompletion(lc,\"hello\");\n            linenoiseAddCompletion(lc,\"hello there\");\n        }\n    }\n\nBasically in your completion callback, you inspect the input, and return\na list of items that are good completions by using `linenoiseAddCompletion`.\n\nIf you want to test the completion feature, compile the example program\nwith `make`, run it, type `h` and press `<TAB>`.\n\n## Hints\n\nLinenoise has a feature called *hints* which is very useful when you\nuse Linenoise in order to implement a REPL (Read Eval Print Loop) for\na program that accepts commands and arguments, but may also be useful in\nother conditions.\n\nThe feature shows, on the right of the cursor, as the user types, hints that\nmay be useful. The hints can be displayed using a different color compared\nto the color the user is typing, and can also be bold.\n\nFor example as the user starts to type `\"git remote add\"`, with hints it's\npossible to show on the right of the prompt a string `<name> <url>`.\n\nThe feature works similarly to the history feature, using a callback.\nTo register the callback we use:\n\n    linenoiseSetHintsCallback(hints);\n\nThe callback itself is implemented like this:\n\n    char *hints(const char *buf, int *color, int *bold) {\n        if (!strcasecmp(buf,\"git remote add\")) {\n            *color = 35;\n            *bold = 0;\n            return \" <name> <url>\";\n        }\n        return NULL;\n    }\n\nThe callback function returns the string that should be displayed or NULL\nif no hint is available for the text the user currently typed. The returned\nstring will be trimmed as needed depending on the number of columns available\non the screen.\n\nIt is possible to return a string allocated in dynamic way, by also registering\na function to deallocate the hint string once used:\n\n    void linenoiseSetFreeHintsCallback(linenoiseFreeHintsCallback *);\n\nThe free hint callback will just receive the pointer and free the string\nas needed (depending on how the hits callback allocated it).\n\nAs you can see in the example above, a `color` (in xterm color terminal codes)\ncan be provided together with a `bold` attribute. If no color is set, the\ncurrent terminal foreground color is used. If no bold attribute is set,\nnon-bold text is printed.\n\nColor codes are:\n\n    red = 31\n    green = 32\n    yellow = 33\n    blue = 34\n    magenta = 35\n    cyan = 36\n    white = 37;\n\n## Screen handling\n\nSometimes you may want to clear the screen as a result of something the\nuser typed. You can do this by calling the following function:\n\n    void linenoiseClearScreen(void);\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.8/deps/linenoise/example.c",
    "content": "#include <stdio.h>\n#include <stdlib.h>\n#include <string.h>\n#include \"linenoise.h\"\n\n\nvoid completion(const char *buf, linenoiseCompletions *lc) {\n    if (buf[0] == 'h') {\n        linenoiseAddCompletion(lc,\"hello\");\n        linenoiseAddCompletion(lc,\"hello there\");\n    }\n}\n\nchar *hints(const char *buf, int *color, int *bold) {\n    if (!strcasecmp(buf,\"hello\")) {\n        *color = 35;\n        *bold = 0;\n        return \" World\";\n    }\n    return NULL;\n}\n\nint main(int argc, char **argv) {\n    char *line;\n    char *prgname = argv[0];\n\n    /* Parse options, with --multiline we enable multi line editing. */\n    while(argc > 1) {\n        argc--;\n        argv++;\n        if (!strcmp(*argv,\"--multiline\")) {\n            linenoiseSetMultiLine(1);\n            printf(\"Multi-line mode enabled.\\n\");\n        } else if (!strcmp(*argv,\"--keycodes\")) {\n            linenoisePrintKeyCodes();\n            exit(0);\n        } else {\n            fprintf(stderr, \"Usage: %s [--multiline] [--keycodes]\\n\", prgname);\n            exit(1);\n        }\n    }\n\n    /* Set the completion callback. This will be called every time the\n     * user uses the <tab> key. */\n    linenoiseSetCompletionCallback(completion);\n    linenoiseSetHintsCallback(hints);\n\n    /* Load history from file. The history file is just a plain text file\n     * where entries are separated by newlines. */\n    linenoiseHistoryLoad(\"history.txt\"); /* Load the history at startup */\n\n    /* Now this is the main loop of the typical linenoise-based application.\n     * The call to linenoise() will block as long as the user types something\n     * and presses enter.\n     *\n     * The typed string is returned as a malloc() allocated string by\n     * linenoise, so the user needs to free() it. */\n    while((line = linenoise(\"hello> \")) != NULL) {\n        /* Do something with the string. */\n        if (line[0] != '\\0' && line[0] != '/') {\n            printf(\"echo: '%s'\\n\", line);\n            linenoiseHistoryAdd(line); /* Add to the history. */\n            linenoiseHistorySave(\"history.txt\"); /* Save the history on disk. */\n        } else if (!strncmp(line,\"/historylen\",11)) {\n            /* The \"/historylen\" command will change the history len. */\n            int len = atoi(line+11);\n            linenoiseHistorySetMaxLen(len);\n        } else if (line[0] == '/') {\n            printf(\"Unreconized command: %s\\n\", line);\n        }\n        free(line);\n    }\n    return 0;\n}\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.8/deps/linenoise/linenoise.c",
    "content": "/* linenoise.c -- guerrilla line editing library against the idea that a\n * line editing lib needs to be 20,000 lines of C code.\n *\n * You can find the latest source code at:\n *\n *   http://github.com/antirez/linenoise\n *\n * Does a number of crazy assumptions that happen to be true in 99.9999% of\n * the 2010 UNIX computers around.\n *\n * ------------------------------------------------------------------------\n *\n * Copyright (c) 2010-2016, Salvatore Sanfilippo <antirez at gmail dot com>\n * Copyright (c) 2010-2013, Pieter Noordhuis <pcnoordhuis at gmail dot com>\n *\n * All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions are\n * met:\n *\n *  *  Redistributions of source code must retain the above copyright\n *     notice, this list of conditions and the following disclaimer.\n *\n *  *  Redistributions in binary form must reproduce the above copyright\n *     notice, this list of conditions and the following disclaimer in the\n *     documentation and/or other materials provided with the distribution.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n * \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\n * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\n * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\n * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\n * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n *\n * ------------------------------------------------------------------------\n *\n * References:\n * - http://invisible-island.net/xterm/ctlseqs/ctlseqs.html\n * - http://www.3waylabs.com/nw/WWW/products/wizcon/vt220.html\n *\n * Todo list:\n * - Filter bogus Ctrl+<char> combinations.\n * - Win32 support\n *\n * Bloat:\n * - History search like Ctrl+r in readline?\n *\n * List of escape sequences used by this program, we do everything just\n * with three sequences. In order to be so cheap we may have some\n * flickering effect with some slow terminal, but the lesser sequences\n * the more compatible.\n *\n * EL (Erase Line)\n *    Sequence: ESC [ n K\n *    Effect: if n is 0 or missing, clear from cursor to end of line\n *    Effect: if n is 1, clear from beginning of line to cursor\n *    Effect: if n is 2, clear entire line\n *\n * CUF (CUrsor Forward)\n *    Sequence: ESC [ n C\n *    Effect: moves cursor forward n chars\n *\n * CUB (CUrsor Backward)\n *    Sequence: ESC [ n D\n *    Effect: moves cursor backward n chars\n *\n * The following is used to get the terminal width if getting\n * the width with the TIOCGWINSZ ioctl fails\n *\n * DSR (Device Status Report)\n *    Sequence: ESC [ 6 n\n *    Effect: reports the current cusor position as ESC [ n ; m R\n *            where n is the row and m is the column\n *\n * When multi line mode is enabled, we also use an additional escape\n * sequence. However multi line editing is disabled by default.\n *\n * CUU (Cursor Up)\n *    Sequence: ESC [ n A\n *    Effect: moves cursor up of n chars.\n *\n * CUD (Cursor Down)\n *    Sequence: ESC [ n B\n *    Effect: moves cursor down of n chars.\n *\n * When linenoiseClearScreen() is called, two additional escape sequences\n * are used in order to clear the screen and position the cursor at home\n * position.\n *\n * CUP (Cursor position)\n *    Sequence: ESC [ H\n *    Effect: moves the cursor to upper left corner\n *\n * ED (Erase display)\n *    Sequence: ESC [ 2 J\n *    Effect: clear the whole screen\n *\n */\n\n#include <termios.h>\n#include <unistd.h>\n#include <stdlib.h>\n#include <stdio.h>\n#include <errno.h>\n#include <string.h>\n#include <stdlib.h>\n#include <ctype.h>\n#include <sys/stat.h>\n#include <sys/types.h>\n#include <sys/ioctl.h>\n#include <unistd.h>\n#include \"linenoise.h\"\n\n#define LINENOISE_DEFAULT_HISTORY_MAX_LEN 100\n#define LINENOISE_MAX_LINE 4096\nstatic char *unsupported_term[] = {\"dumb\",\"cons25\",\"emacs\",NULL};\nstatic linenoiseCompletionCallback *completionCallback = NULL;\nstatic linenoiseHintsCallback *hintsCallback = NULL;\nstatic linenoiseFreeHintsCallback *freeHintsCallback = NULL;\n\nstatic struct termios orig_termios; /* In order to restore at exit.*/\nstatic int rawmode = 0; /* For atexit() function to check if restore is needed*/\nstatic int mlmode = 0;  /* Multi line mode. Default is single line. */\nstatic int atexit_registered = 0; /* Register atexit just 1 time. */\nstatic int history_max_len = LINENOISE_DEFAULT_HISTORY_MAX_LEN;\nstatic int history_len = 0;\nstatic char **history = NULL;\n\n/* The linenoiseState structure represents the state during line editing.\n * We pass this state to functions implementing specific editing\n * functionalities. */\nstruct linenoiseState {\n    int ifd;            /* Terminal stdin file descriptor. */\n    int ofd;            /* Terminal stdout file descriptor. */\n    char *buf;          /* Edited line buffer. */\n    size_t buflen;      /* Edited line buffer size. */\n    const char *prompt; /* Prompt to display. */\n    size_t plen;        /* Prompt length. */\n    size_t pos;         /* Current cursor position. */\n    size_t oldpos;      /* Previous refresh cursor position. */\n    size_t len;         /* Current edited line length. */\n    size_t cols;        /* Number of columns in terminal. */\n    size_t maxrows;     /* Maximum num of rows used so far (multiline mode) */\n    int history_index;  /* The history index we are currently editing. */\n};\n\nenum KEY_ACTION{\n\tKEY_NULL = 0,\t    /* NULL */\n\tCTRL_A = 1,         /* Ctrl+a */\n\tCTRL_B = 2,         /* Ctrl-b */\n\tCTRL_C = 3,         /* Ctrl-c */\n\tCTRL_D = 4,         /* Ctrl-d */\n\tCTRL_E = 5,         /* Ctrl-e */\n\tCTRL_F = 6,         /* Ctrl-f */\n\tCTRL_H = 8,         /* Ctrl-h */\n\tTAB = 9,            /* Tab */\n\tCTRL_K = 11,        /* Ctrl+k */\n\tCTRL_L = 12,        /* Ctrl+l */\n\tENTER = 13,         /* Enter */\n\tCTRL_N = 14,        /* Ctrl-n */\n\tCTRL_P = 16,        /* Ctrl-p */\n\tCTRL_T = 20,        /* Ctrl-t */\n\tCTRL_U = 21,        /* Ctrl+u */\n\tCTRL_W = 23,        /* Ctrl+w */\n\tESC = 27,           /* Escape */\n\tBACKSPACE =  127    /* Backspace */\n};\n\nstatic void linenoiseAtExit(void);\nint linenoiseHistoryAdd(const char *line);\nstatic void refreshLine(struct linenoiseState *l);\n\n/* Debugging macro. */\n#if 0\nFILE *lndebug_fp = NULL;\n#define lndebug(...) \\\n    do { \\\n        if (lndebug_fp == NULL) { \\\n            lndebug_fp = fopen(\"/tmp/lndebug.txt\",\"a\"); \\\n            fprintf(lndebug_fp, \\\n            \"[%d %d %d] p: %d, rows: %d, rpos: %d, max: %d, oldmax: %d\\n\", \\\n            (int)l->len,(int)l->pos,(int)l->oldpos,plen,rows,rpos, \\\n            (int)l->maxrows,old_rows); \\\n        } \\\n        fprintf(lndebug_fp, \", \" __VA_ARGS__); \\\n        fflush(lndebug_fp); \\\n    } while (0)\n#else\n#define lndebug(fmt, ...)\n#endif\n\n/* ======================= Low level terminal handling ====================== */\n\n/* Set if to use or not the multi line mode. */\nvoid linenoiseSetMultiLine(int ml) {\n    mlmode = ml;\n}\n\n/* Return true if the terminal name is in the list of terminals we know are\n * not able to understand basic escape sequences. */\nstatic int isUnsupportedTerm(void) {\n    char *term = getenv(\"TERM\");\n    int j;\n\n    if (term == NULL) return 0;\n    for (j = 0; unsupported_term[j]; j++)\n        if (!strcasecmp(term,unsupported_term[j])) return 1;\n    return 0;\n}\n\n/* Raw mode: 1960 magic shit. */\nstatic int enableRawMode(int fd) {\n    struct termios raw;\n\n    if (!isatty(STDIN_FILENO)) goto fatal;\n    if (!atexit_registered) {\n        atexit(linenoiseAtExit);\n        atexit_registered = 1;\n    }\n    if (tcgetattr(fd,&orig_termios) == -1) goto fatal;\n\n    raw = orig_termios;  /* modify the original mode */\n    /* input modes: no break, no CR to NL, no parity check, no strip char,\n     * no start/stop output control. */\n    raw.c_iflag &= ~(BRKINT | ICRNL | INPCK | ISTRIP | IXON);\n    /* output modes - disable post processing */\n    raw.c_oflag &= ~(OPOST);\n    /* control modes - set 8 bit chars */\n    raw.c_cflag |= (CS8);\n    /* local modes - choing off, canonical off, no extended functions,\n     * no signal chars (^Z,^C) */\n    raw.c_lflag &= ~(ECHO | ICANON | IEXTEN | ISIG);\n    /* control chars - set return condition: min number of bytes and timer.\n     * We want read to return every single byte, without timeout. */\n    raw.c_cc[VMIN] = 1; raw.c_cc[VTIME] = 0; /* 1 byte, no timer */\n\n    /* put terminal in raw mode after flushing */\n    if (tcsetattr(fd,TCSAFLUSH,&raw) < 0) goto fatal;\n    rawmode = 1;\n    return 0;\n\nfatal:\n    errno = ENOTTY;\n    return -1;\n}\n\nstatic void disableRawMode(int fd) {\n    /* Don't even check the return value as it's too late. */\n    if (rawmode && tcsetattr(fd,TCSAFLUSH,&orig_termios) != -1)\n        rawmode = 0;\n}\n\n/* Use the ESC [6n escape sequence to query the horizontal cursor position\n * and return it. On error -1 is returned, on success the position of the\n * cursor. */\nstatic int getCursorPosition(int ifd, int ofd) {\n    char buf[32];\n    int cols, rows;\n    unsigned int i = 0;\n\n    /* Report cursor location */\n    if (write(ofd, \"\\x1b[6n\", 4) != 4) return -1;\n\n    /* Read the response: ESC [ rows ; cols R */\n    while (i < sizeof(buf)-1) {\n        if (read(ifd,buf+i,1) != 1) break;\n        if (buf[i] == 'R') break;\n        i++;\n    }\n    buf[i] = '\\0';\n\n    /* Parse it. */\n    if (buf[0] != ESC || buf[1] != '[') return -1;\n    if (sscanf(buf+2,\"%d;%d\",&rows,&cols) != 2) return -1;\n    return cols;\n}\n\n/* Try to get the number of columns in the current terminal, or assume 80\n * if it fails. */\nstatic int getColumns(int ifd, int ofd) {\n    struct winsize ws;\n\n    if (ioctl(1, TIOCGWINSZ, &ws) == -1 || ws.ws_col == 0) {\n        /* ioctl() failed. Try to query the terminal itself. */\n        int start, cols;\n\n        /* Get the initial position so we can restore it later. */\n        start = getCursorPosition(ifd,ofd);\n        if (start == -1) goto failed;\n\n        /* Go to right margin and get position. */\n        if (write(ofd,\"\\x1b[999C\",6) != 6) goto failed;\n        cols = getCursorPosition(ifd,ofd);\n        if (cols == -1) goto failed;\n\n        /* Restore position. */\n        if (cols > start) {\n            char seq[32];\n            snprintf(seq,32,\"\\x1b[%dD\",cols-start);\n            if (write(ofd,seq,strlen(seq)) == -1) {\n                /* Can't recover... */\n            }\n        }\n        return cols;\n    } else {\n        return ws.ws_col;\n    }\n\nfailed:\n    return 80;\n}\n\n/* Clear the screen. Used to handle ctrl+l */\nvoid linenoiseClearScreen(void) {\n    if (write(STDOUT_FILENO,\"\\x1b[H\\x1b[2J\",7) <= 0) {\n        /* nothing to do, just to avoid warning. */\n    }\n}\n\n/* Beep, used for completion when there is nothing to complete or when all\n * the choices were already shown. */\nstatic void linenoiseBeep(void) {\n    fprintf(stderr, \"\\x7\");\n    fflush(stderr);\n}\n\n/* ============================== Completion ================================ */\n\n/* Free a list of completion option populated by linenoiseAddCompletion(). */\nstatic void freeCompletions(linenoiseCompletions *lc) {\n    size_t i;\n    for (i = 0; i < lc->len; i++)\n        free(lc->cvec[i]);\n    if (lc->cvec != NULL)\n        free(lc->cvec);\n}\n\n/* This is an helper function for linenoiseEdit() and is called when the\n * user types the <tab> key in order to complete the string currently in the\n * input.\n *\n * The state of the editing is encapsulated into the pointed linenoiseState\n * structure as described in the structure definition. */\nstatic int completeLine(struct linenoiseState *ls) {\n    linenoiseCompletions lc = { 0, NULL };\n    int nread, nwritten;\n    char c = 0;\n\n    completionCallback(ls->buf,&lc);\n    if (lc.len == 0) {\n        linenoiseBeep();\n    } else {\n        size_t stop = 0, i = 0;\n\n        while(!stop) {\n            /* Show completion or original buffer */\n            if (i < lc.len) {\n                struct linenoiseState saved = *ls;\n\n                ls->len = ls->pos = strlen(lc.cvec[i]);\n                ls->buf = lc.cvec[i];\n                refreshLine(ls);\n                ls->len = saved.len;\n                ls->pos = saved.pos;\n                ls->buf = saved.buf;\n            } else {\n                refreshLine(ls);\n            }\n\n            nread = read(ls->ifd,&c,1);\n            if (nread <= 0) {\n                freeCompletions(&lc);\n                return -1;\n            }\n\n            switch(c) {\n                case 9: /* tab */\n                    i = (i+1) % (lc.len+1);\n                    if (i == lc.len) linenoiseBeep();\n                    break;\n                case 27: /* escape */\n                    /* Re-show original buffer */\n                    if (i < lc.len) refreshLine(ls);\n                    stop = 1;\n                    break;\n                default:\n                    /* Update buffer and return */\n                    if (i < lc.len) {\n                        nwritten = snprintf(ls->buf,ls->buflen,\"%s\",lc.cvec[i]);\n                        ls->len = ls->pos = nwritten;\n                    }\n                    stop = 1;\n                    break;\n            }\n        }\n    }\n\n    freeCompletions(&lc);\n    return c; /* Return last read character */\n}\n\n/* Register a callback function to be called for tab-completion. */\nvoid linenoiseSetCompletionCallback(linenoiseCompletionCallback *fn) {\n    completionCallback = fn;\n}\n\n/* Register a hits function to be called to show hits to the user at the\n * right of the prompt. */\nvoid linenoiseSetHintsCallback(linenoiseHintsCallback *fn) {\n    hintsCallback = fn;\n}\n\n/* Register a function to free the hints returned by the hints callback\n * registered with linenoiseSetHintsCallback(). */\nvoid linenoiseSetFreeHintsCallback(linenoiseFreeHintsCallback *fn) {\n    freeHintsCallback = fn;\n}\n\n/* This function is used by the callback function registered by the user\n * in order to add completion options given the input string when the\n * user typed <tab>. See the example.c source code for a very easy to\n * understand example. */\nvoid linenoiseAddCompletion(linenoiseCompletions *lc, const char *str) {\n    size_t len = strlen(str);\n    char *copy, **cvec;\n\n    copy = malloc(len+1);\n    if (copy == NULL) return;\n    memcpy(copy,str,len+1);\n    cvec = realloc(lc->cvec,sizeof(char*)*(lc->len+1));\n    if (cvec == NULL) {\n        free(copy);\n        return;\n    }\n    lc->cvec = cvec;\n    lc->cvec[lc->len++] = copy;\n}\n\n/* =========================== Line editing ================================= */\n\n/* We define a very simple \"append buffer\" structure, that is an heap\n * allocated string where we can append to. This is useful in order to\n * write all the escape sequences in a buffer and flush them to the standard\n * output in a single call, to avoid flickering effects. */\nstruct abuf {\n    char *b;\n    int len;\n};\n\nstatic void abInit(struct abuf *ab) {\n    ab->b = NULL;\n    ab->len = 0;\n}\n\nstatic void abAppend(struct abuf *ab, const char *s, int len) {\n    char *new = realloc(ab->b,ab->len+len);\n\n    if (new == NULL) return;\n    memcpy(new+ab->len,s,len);\n    ab->b = new;\n    ab->len += len;\n}\n\nstatic void abFree(struct abuf *ab) {\n    free(ab->b);\n}\n\n/* Helper of refreshSingleLine() and refreshMultiLine() to show hints\n * to the right of the prompt. */\nvoid refreshShowHints(struct abuf *ab, struct linenoiseState *l, int plen) {\n    char seq[64];\n    if (hintsCallback && plen+l->len < l->cols) {\n        int color = -1, bold = 0;\n        char *hint = hintsCallback(l->buf,&color,&bold);\n        if (hint) {\n            int hintlen = strlen(hint);\n            int hintmaxlen = l->cols-(plen+l->len);\n            if (hintlen > hintmaxlen) hintlen = hintmaxlen;\n            if (bold == 1 && color == -1) color = 37;\n            if (color != -1 || bold != 0)\n                snprintf(seq,64,\"\\033[%d;%d;49m\",bold,color);\n            abAppend(ab,seq,strlen(seq));\n            abAppend(ab,hint,hintlen);\n            if (color != -1 || bold != 0)\n                abAppend(ab,\"\\033[0m\",4);\n            /* Call the function to free the hint returned. */\n            if (freeHintsCallback) freeHintsCallback(hint);\n        }\n    }\n}\n\n/* Single line low level line refresh.\n *\n * Rewrite the currently edited line accordingly to the buffer content,\n * cursor position, and number of columns of the terminal. */\nstatic void refreshSingleLine(struct linenoiseState *l) {\n    char seq[64];\n    size_t plen = strlen(l->prompt);\n    int fd = l->ofd;\n    char *buf = l->buf;\n    size_t len = l->len;\n    size_t pos = l->pos;\n    struct abuf ab;\n\n    while((plen+pos) >= l->cols) {\n        buf++;\n        len--;\n        pos--;\n    }\n    while (plen+len > l->cols) {\n        len--;\n    }\n\n    abInit(&ab);\n    /* Cursor to left edge */\n    snprintf(seq,64,\"\\r\");\n    abAppend(&ab,seq,strlen(seq));\n    /* Write the prompt and the current buffer content */\n    abAppend(&ab,l->prompt,strlen(l->prompt));\n    abAppend(&ab,buf,len);\n    /* Show hits if any. */\n    refreshShowHints(&ab,l,plen);\n    /* Erase to right */\n    snprintf(seq,64,\"\\x1b[0K\");\n    abAppend(&ab,seq,strlen(seq));\n    /* Move cursor to original position. */\n    snprintf(seq,64,\"\\r\\x1b[%dC\", (int)(pos+plen));\n    abAppend(&ab,seq,strlen(seq));\n    if (write(fd,ab.b,ab.len) == -1) {} /* Can't recover from write error. */\n    abFree(&ab);\n}\n\n/* Multi line low level line refresh.\n *\n * Rewrite the currently edited line accordingly to the buffer content,\n * cursor position, and number of columns of the terminal. */\nstatic void refreshMultiLine(struct linenoiseState *l) {\n    char seq[64];\n    int plen = strlen(l->prompt);\n    int rows = (plen+l->len+l->cols-1)/l->cols; /* rows used by current buf. */\n    int rpos = (plen+l->oldpos+l->cols)/l->cols; /* cursor relative row. */\n    int rpos2; /* rpos after refresh. */\n    int col; /* colum position, zero-based. */\n    int old_rows = l->maxrows;\n    int fd = l->ofd, j;\n    struct abuf ab;\n\n    /* Update maxrows if needed. */\n    if (rows > (int)l->maxrows) l->maxrows = rows;\n\n    /* First step: clear all the lines used before. To do so start by\n     * going to the last row. */\n    abInit(&ab);\n    if (old_rows-rpos > 0) {\n        lndebug(\"go down %d\", old_rows-rpos);\n        snprintf(seq,64,\"\\x1b[%dB\", old_rows-rpos);\n        abAppend(&ab,seq,strlen(seq));\n    }\n\n    /* Now for every row clear it, go up. */\n    for (j = 0; j < old_rows-1; j++) {\n        lndebug(\"clear+up\");\n        snprintf(seq,64,\"\\r\\x1b[0K\\x1b[1A\");\n        abAppend(&ab,seq,strlen(seq));\n    }\n\n    /* Clean the top line. */\n    lndebug(\"clear\");\n    snprintf(seq,64,\"\\r\\x1b[0K\");\n    abAppend(&ab,seq,strlen(seq));\n\n    /* Write the prompt and the current buffer content */\n    abAppend(&ab,l->prompt,strlen(l->prompt));\n    abAppend(&ab,l->buf,l->len);\n\n    /* Show hits if any. */\n    refreshShowHints(&ab,l,plen);\n\n    /* If we are at the very end of the screen with our prompt, we need to\n     * emit a newline and move the prompt to the first column. */\n    if (l->pos &&\n        l->pos == l->len &&\n        (l->pos+plen) % l->cols == 0)\n    {\n        lndebug(\"<newline>\");\n        abAppend(&ab,\"\\n\",1);\n        snprintf(seq,64,\"\\r\");\n        abAppend(&ab,seq,strlen(seq));\n        rows++;\n        if (rows > (int)l->maxrows) l->maxrows = rows;\n    }\n\n    /* Move cursor to right position. */\n    rpos2 = (plen+l->pos+l->cols)/l->cols; /* current cursor relative row. */\n    lndebug(\"rpos2 %d\", rpos2);\n\n    /* Go up till we reach the expected positon. */\n    if (rows-rpos2 > 0) {\n        lndebug(\"go-up %d\", rows-rpos2);\n        snprintf(seq,64,\"\\x1b[%dA\", rows-rpos2);\n        abAppend(&ab,seq,strlen(seq));\n    }\n\n    /* Set column. */\n    col = (plen+(int)l->pos) % (int)l->cols;\n    lndebug(\"set col %d\", 1+col);\n    if (col)\n        snprintf(seq,64,\"\\r\\x1b[%dC\", col);\n    else\n        snprintf(seq,64,\"\\r\");\n    abAppend(&ab,seq,strlen(seq));\n\n    lndebug(\"\\n\");\n    l->oldpos = l->pos;\n\n    if (write(fd,ab.b,ab.len) == -1) {} /* Can't recover from write error. */\n    abFree(&ab);\n}\n\n/* Calls the two low level functions refreshSingleLine() or\n * refreshMultiLine() according to the selected mode. */\nstatic void refreshLine(struct linenoiseState *l) {\n    if (mlmode)\n        refreshMultiLine(l);\n    else\n        refreshSingleLine(l);\n}\n\n/* Insert the character 'c' at cursor current position.\n *\n * On error writing to the terminal -1 is returned, otherwise 0. */\nint linenoiseEditInsert(struct linenoiseState *l, char c) {\n    if (l->len < l->buflen) {\n        if (l->len == l->pos) {\n            l->buf[l->pos] = c;\n            l->pos++;\n            l->len++;\n            l->buf[l->len] = '\\0';\n            if ((!mlmode && l->plen+l->len < l->cols && !hintsCallback)) {\n                /* Avoid a full update of the line in the\n                 * trivial case. */\n                if (write(l->ofd,&c,1) == -1) return -1;\n            } else {\n                refreshLine(l);\n            }\n        } else {\n            memmove(l->buf+l->pos+1,l->buf+l->pos,l->len-l->pos);\n            l->buf[l->pos] = c;\n            l->len++;\n            l->pos++;\n            l->buf[l->len] = '\\0';\n            refreshLine(l);\n        }\n    }\n    return 0;\n}\n\n/* Move cursor on the left. */\nvoid linenoiseEditMoveLeft(struct linenoiseState *l) {\n    if (l->pos > 0) {\n        l->pos--;\n        refreshLine(l);\n    }\n}\n\n/* Move cursor on the right. */\nvoid linenoiseEditMoveRight(struct linenoiseState *l) {\n    if (l->pos != l->len) {\n        l->pos++;\n        refreshLine(l);\n    }\n}\n\n/* Move cursor to the start of the line. */\nvoid linenoiseEditMoveHome(struct linenoiseState *l) {\n    if (l->pos != 0) {\n        l->pos = 0;\n        refreshLine(l);\n    }\n}\n\n/* Move cursor to the end of the line. */\nvoid linenoiseEditMoveEnd(struct linenoiseState *l) {\n    if (l->pos != l->len) {\n        l->pos = l->len;\n        refreshLine(l);\n    }\n}\n\n/* Substitute the currently edited line with the next or previous history\n * entry as specified by 'dir'. */\n#define LINENOISE_HISTORY_NEXT 0\n#define LINENOISE_HISTORY_PREV 1\nvoid linenoiseEditHistoryNext(struct linenoiseState *l, int dir) {\n    if (history_len > 1) {\n        /* Update the current history entry before to\n         * overwrite it with the next one. */\n        free(history[history_len - 1 - l->history_index]);\n        history[history_len - 1 - l->history_index] = strdup(l->buf);\n        /* Show the new entry */\n        l->history_index += (dir == LINENOISE_HISTORY_PREV) ? 1 : -1;\n        if (l->history_index < 0) {\n            l->history_index = 0;\n            return;\n        } else if (l->history_index >= history_len) {\n            l->history_index = history_len-1;\n            return;\n        }\n        strncpy(l->buf,history[history_len - 1 - l->history_index],l->buflen);\n        l->buf[l->buflen-1] = '\\0';\n        l->len = l->pos = strlen(l->buf);\n        refreshLine(l);\n    }\n}\n\n/* Delete the character at the right of the cursor without altering the cursor\n * position. Basically this is what happens with the \"Delete\" keyboard key. */\nvoid linenoiseEditDelete(struct linenoiseState *l) {\n    if (l->len > 0 && l->pos < l->len) {\n        memmove(l->buf+l->pos,l->buf+l->pos+1,l->len-l->pos-1);\n        l->len--;\n        l->buf[l->len] = '\\0';\n        refreshLine(l);\n    }\n}\n\n/* Backspace implementation. */\nvoid linenoiseEditBackspace(struct linenoiseState *l) {\n    if (l->pos > 0 && l->len > 0) {\n        memmove(l->buf+l->pos-1,l->buf+l->pos,l->len-l->pos);\n        l->pos--;\n        l->len--;\n        l->buf[l->len] = '\\0';\n        refreshLine(l);\n    }\n}\n\n/* Delete the previosu word, maintaining the cursor at the start of the\n * current word. */\nvoid linenoiseEditDeletePrevWord(struct linenoiseState *l) {\n    size_t old_pos = l->pos;\n    size_t diff;\n\n    while (l->pos > 0 && l->buf[l->pos-1] == ' ')\n        l->pos--;\n    while (l->pos > 0 && l->buf[l->pos-1] != ' ')\n        l->pos--;\n    diff = old_pos - l->pos;\n    memmove(l->buf+l->pos,l->buf+old_pos,l->len-old_pos+1);\n    l->len -= diff;\n    refreshLine(l);\n}\n\n/* This function is the core of the line editing capability of linenoise.\n * It expects 'fd' to be already in \"raw mode\" so that every key pressed\n * will be returned ASAP to read().\n *\n * The resulting string is put into 'buf' when the user type enter, or\n * when ctrl+d is typed.\n *\n * The function returns the length of the current buffer. */\nstatic int linenoiseEdit(int stdin_fd, int stdout_fd, char *buf, size_t buflen, const char *prompt)\n{\n    struct linenoiseState l;\n\n    /* Populate the linenoise state that we pass to functions implementing\n     * specific editing functionalities. */\n    l.ifd = stdin_fd;\n    l.ofd = stdout_fd;\n    l.buf = buf;\n    l.buflen = buflen;\n    l.prompt = prompt;\n    l.plen = strlen(prompt);\n    l.oldpos = l.pos = 0;\n    l.len = 0;\n    l.cols = getColumns(stdin_fd, stdout_fd);\n    l.maxrows = 0;\n    l.history_index = 0;\n\n    /* Buffer starts empty. */\n    l.buf[0] = '\\0';\n    l.buflen--; /* Make sure there is always space for the nulterm */\n\n    /* The latest history entry is always our current buffer, that\n     * initially is just an empty string. */\n    linenoiseHistoryAdd(\"\");\n\n    if (write(l.ofd,prompt,l.plen) == -1) return -1;\n    while(1) {\n        char c;\n        int nread;\n        char seq[3];\n\n        nread = read(l.ifd,&c,1);\n        if (nread <= 0) return l.len;\n\n        /* Only autocomplete when the callback is set. It returns < 0 when\n         * there was an error reading from fd. Otherwise it will return the\n         * character that should be handled next. */\n        if (c == 9 && completionCallback != NULL) {\n            c = completeLine(&l);\n            /* Return on errors */\n            if (c < 0) return l.len;\n            /* Read next character when 0 */\n            if (c == 0) continue;\n        }\n\n        switch(c) {\n        case ENTER:    /* enter */\n            history_len--;\n            free(history[history_len]);\n            if (mlmode) linenoiseEditMoveEnd(&l);\n            if (hintsCallback) {\n                /* Force a refresh without hints to leave the previous\n                 * line as the user typed it after a newline. */\n                linenoiseHintsCallback *hc = hintsCallback;\n                hintsCallback = NULL;\n                refreshLine(&l);\n                hintsCallback = hc;\n            }\n            return (int)l.len;\n        case CTRL_C:     /* ctrl-c */\n            errno = EAGAIN;\n            return -1;\n        case BACKSPACE:   /* backspace */\n        case 8:     /* ctrl-h */\n            linenoiseEditBackspace(&l);\n            break;\n        case CTRL_D:     /* ctrl-d, remove char at right of cursor, or if the\n                            line is empty, act as end-of-file. */\n            if (l.len > 0) {\n                linenoiseEditDelete(&l);\n            } else {\n                history_len--;\n                free(history[history_len]);\n                return -1;\n            }\n            break;\n        case CTRL_T:    /* ctrl-t, swaps current character with previous. */\n            if (l.pos > 0 && l.pos < l.len) {\n                int aux = buf[l.pos-1];\n                buf[l.pos-1] = buf[l.pos];\n                buf[l.pos] = aux;\n                if (l.pos != l.len-1) l.pos++;\n                refreshLine(&l);\n            }\n            break;\n        case CTRL_B:     /* ctrl-b */\n            linenoiseEditMoveLeft(&l);\n            break;\n        case CTRL_F:     /* ctrl-f */\n            linenoiseEditMoveRight(&l);\n            break;\n        case CTRL_P:    /* ctrl-p */\n            linenoiseEditHistoryNext(&l, LINENOISE_HISTORY_PREV);\n            break;\n        case CTRL_N:    /* ctrl-n */\n            linenoiseEditHistoryNext(&l, LINENOISE_HISTORY_NEXT);\n            break;\n        case ESC:    /* escape sequence */\n            /* Read the next two bytes representing the escape sequence.\n             * Use two calls to handle slow terminals returning the two\n             * chars at different times. */\n            if (read(l.ifd,seq,1) == -1) break;\n            if (read(l.ifd,seq+1,1) == -1) break;\n\n            /* ESC [ sequences. */\n            if (seq[0] == '[') {\n                if (seq[1] >= '0' && seq[1] <= '9') {\n                    /* Extended escape, read additional byte. */\n                    if (read(l.ifd,seq+2,1) == -1) break;\n                    if (seq[2] == '~') {\n                        switch(seq[1]) {\n                        case '3': /* Delete key. */\n                            linenoiseEditDelete(&l);\n                            break;\n                        }\n                    }\n                } else {\n                    switch(seq[1]) {\n                    case 'A': /* Up */\n                        linenoiseEditHistoryNext(&l, LINENOISE_HISTORY_PREV);\n                        break;\n                    case 'B': /* Down */\n                        linenoiseEditHistoryNext(&l, LINENOISE_HISTORY_NEXT);\n                        break;\n                    case 'C': /* Right */\n                        linenoiseEditMoveRight(&l);\n                        break;\n                    case 'D': /* Left */\n                        linenoiseEditMoveLeft(&l);\n                        break;\n                    case 'H': /* Home */\n                        linenoiseEditMoveHome(&l);\n                        break;\n                    case 'F': /* End*/\n                        linenoiseEditMoveEnd(&l);\n                        break;\n                    }\n                }\n            }\n\n            /* ESC O sequences. */\n            else if (seq[0] == 'O') {\n                switch(seq[1]) {\n                case 'H': /* Home */\n                    linenoiseEditMoveHome(&l);\n                    break;\n                case 'F': /* End*/\n                    linenoiseEditMoveEnd(&l);\n                    break;\n                }\n            }\n            break;\n        default:\n            if (linenoiseEditInsert(&l,c)) return -1;\n            break;\n        case CTRL_U: /* Ctrl+u, delete the whole line. */\n            buf[0] = '\\0';\n            l.pos = l.len = 0;\n            refreshLine(&l);\n            break;\n        case CTRL_K: /* Ctrl+k, delete from current to end of line. */\n            buf[l.pos] = '\\0';\n            l.len = l.pos;\n            refreshLine(&l);\n            break;\n        case CTRL_A: /* Ctrl+a, go to the start of the line */\n            linenoiseEditMoveHome(&l);\n            break;\n        case CTRL_E: /* ctrl+e, go to the end of the line */\n            linenoiseEditMoveEnd(&l);\n            break;\n        case CTRL_L: /* ctrl+l, clear screen */\n            linenoiseClearScreen();\n            refreshLine(&l);\n            break;\n        case CTRL_W: /* ctrl+w, delete previous word */\n            linenoiseEditDeletePrevWord(&l);\n            break;\n        }\n    }\n    return l.len;\n}\n\n/* This special mode is used by linenoise in order to print scan codes\n * on screen for debugging / development purposes. It is implemented\n * by the linenoise_example program using the --keycodes option. */\nvoid linenoisePrintKeyCodes(void) {\n    char quit[4];\n\n    printf(\"Linenoise key codes debugging mode.\\n\"\n            \"Press keys to see scan codes. Type 'quit' at any time to exit.\\n\");\n    if (enableRawMode(STDIN_FILENO) == -1) return;\n    memset(quit,' ',4);\n    while(1) {\n        char c;\n        int nread;\n\n        nread = read(STDIN_FILENO,&c,1);\n        if (nread <= 0) continue;\n        memmove(quit,quit+1,sizeof(quit)-1); /* shift string to left. */\n        quit[sizeof(quit)-1] = c; /* Insert current char on the right. */\n        if (memcmp(quit,\"quit\",sizeof(quit)) == 0) break;\n\n        printf(\"'%c' %02x (%d) (type quit to exit)\\n\",\n            isprint(c) ? c : '?', (int)c, (int)c);\n        printf(\"\\r\"); /* Go left edge manually, we are in raw mode. */\n        fflush(stdout);\n    }\n    disableRawMode(STDIN_FILENO);\n}\n\n/* This function calls the line editing function linenoiseEdit() using\n * the STDIN file descriptor set in raw mode. */\nstatic int linenoiseRaw(char *buf, size_t buflen, const char *prompt) {\n    int count;\n\n    if (buflen == 0) {\n        errno = EINVAL;\n        return -1;\n    }\n\n    if (enableRawMode(STDIN_FILENO) == -1) return -1;\n    count = linenoiseEdit(STDIN_FILENO, STDOUT_FILENO, buf, buflen, prompt);\n    disableRawMode(STDIN_FILENO);\n    printf(\"\\n\");\n    return count;\n}\n\n/* This function is called when linenoise() is called with the standard\n * input file descriptor not attached to a TTY. So for example when the\n * program using linenoise is called in pipe or with a file redirected\n * to its standard input. In this case, we want to be able to return the\n * line regardless of its length (by default we are limited to 4k). */\nstatic char *linenoiseNoTTY(void) {\n    char *line = NULL;\n    size_t len = 0, maxlen = 0;\n\n    while(1) {\n        if (len == maxlen) {\n            if (maxlen == 0) maxlen = 16;\n            maxlen *= 2;\n            char *oldval = line;\n            line = realloc(line,maxlen);\n            if (line == NULL) {\n                if (oldval) free(oldval);\n                return NULL;\n            }\n        }\n        int c = fgetc(stdin);\n        if (c == EOF || c == '\\n') {\n            if (c == EOF && len == 0) {\n                free(line);\n                return NULL;\n            } else {\n                line[len] = '\\0';\n                return line;\n            }\n        } else {\n            line[len] = c;\n            len++;\n        }\n    }\n}\n\n/* The high level function that is the main API of the linenoise library.\n * This function checks if the terminal has basic capabilities, just checking\n * for a blacklist of stupid terminals, and later either calls the line\n * editing function or uses dummy fgets() so that you will be able to type\n * something even in the most desperate of the conditions. */\nchar *linenoise(const char *prompt) {\n    char buf[LINENOISE_MAX_LINE];\n    int count;\n\n    if (!isatty(STDIN_FILENO)) {\n        /* Not a tty: read from file / pipe. In this mode we don't want any\n         * limit to the line size, so we call a function to handle that. */\n        return linenoiseNoTTY();\n    } else if (isUnsupportedTerm()) {\n        size_t len;\n\n        printf(\"%s\",prompt);\n        fflush(stdout);\n        if (fgets(buf,LINENOISE_MAX_LINE,stdin) == NULL) return NULL;\n        len = strlen(buf);\n        while(len && (buf[len-1] == '\\n' || buf[len-1] == '\\r')) {\n            len--;\n            buf[len] = '\\0';\n        }\n        return strdup(buf);\n    } else {\n        count = linenoiseRaw(buf,LINENOISE_MAX_LINE,prompt);\n        if (count == -1) return NULL;\n        return strdup(buf);\n    }\n}\n\n/* This is just a wrapper the user may want to call in order to make sure\n * the linenoise returned buffer is freed with the same allocator it was\n * created with. Useful when the main program is using an alternative\n * allocator. */\nvoid linenoiseFree(void *ptr) {\n    free(ptr);\n}\n\n/* ================================ History ================================= */\n\n/* Free the history, but does not reset it. Only used when we have to\n * exit() to avoid memory leaks are reported by valgrind & co. */\nstatic void freeHistory(void) {\n    if (history) {\n        int j;\n\n        for (j = 0; j < history_len; j++)\n            free(history[j]);\n        free(history);\n    }\n}\n\n/* At exit we'll try to fix the terminal to the initial conditions. */\nstatic void linenoiseAtExit(void) {\n    disableRawMode(STDIN_FILENO);\n    freeHistory();\n}\n\n/* This is the API call to add a new entry in the linenoise history.\n * It uses a fixed array of char pointers that are shifted (memmoved)\n * when the history max length is reached in order to remove the older\n * entry and make room for the new one, so it is not exactly suitable for huge\n * histories, but will work well for a few hundred of entries.\n *\n * Using a circular buffer is smarter, but a bit more complex to handle. */\nint linenoiseHistoryAdd(const char *line) {\n    char *linecopy;\n\n    if (history_max_len == 0) return 0;\n\n    /* Initialization on first call. */\n    if (history == NULL) {\n        history = malloc(sizeof(char*)*history_max_len);\n        if (history == NULL) return 0;\n        memset(history,0,(sizeof(char*)*history_max_len));\n    }\n\n    /* Don't add duplicated lines. */\n    if (history_len && !strcmp(history[history_len-1], line)) return 0;\n\n    /* Add an heap allocated copy of the line in the history.\n     * If we reached the max length, remove the older line. */\n    linecopy = strdup(line);\n    if (!linecopy) return 0;\n    if (history_len == history_max_len) {\n        free(history[0]);\n        memmove(history,history+1,sizeof(char*)*(history_max_len-1));\n        history_len--;\n    }\n    history[history_len] = linecopy;\n    history_len++;\n    return 1;\n}\n\n/* Set the maximum length for the history. This function can be called even\n * if there is already some history, the function will make sure to retain\n * just the latest 'len' elements if the new history length value is smaller\n * than the amount of items already inside the history. */\nint linenoiseHistorySetMaxLen(int len) {\n    char **new;\n\n    if (len < 1) return 0;\n    if (history) {\n        int tocopy = history_len;\n\n        new = malloc(sizeof(char*)*len);\n        if (new == NULL) return 0;\n\n        /* If we can't copy everything, free the elements we'll not use. */\n        if (len < tocopy) {\n            int j;\n\n            for (j = 0; j < tocopy-len; j++) free(history[j]);\n            tocopy = len;\n        }\n        memset(new,0,sizeof(char*)*len);\n        memcpy(new,history+(history_len-tocopy), sizeof(char*)*tocopy);\n        free(history);\n        history = new;\n    }\n    history_max_len = len;\n    if (history_len > history_max_len)\n        history_len = history_max_len;\n    return 1;\n}\n\n/* Save the history in the specified file. On success 0 is returned\n * otherwise -1 is returned. */\nint linenoiseHistorySave(const char *filename) {\n    mode_t old_umask = umask(S_IXUSR|S_IRWXG|S_IRWXO);\n    FILE *fp;\n    int j;\n\n    fp = fopen(filename,\"w\");\n    umask(old_umask);\n    if (fp == NULL) return -1;\n    chmod(filename,S_IRUSR|S_IWUSR);\n    for (j = 0; j < history_len; j++)\n        fprintf(fp,\"%s\\n\",history[j]);\n    fclose(fp);\n    return 0;\n}\n\n/* Load the history from the specified file. If the file does not exist\n * zero is returned and no operation is performed.\n *\n * If the file exists and the operation succeeded 0 is returned, otherwise\n * on error -1 is returned. */\nint linenoiseHistoryLoad(const char *filename) {\n    FILE *fp = fopen(filename,\"r\");\n    char buf[LINENOISE_MAX_LINE];\n\n    if (fp == NULL) return -1;\n\n    while (fgets(buf,LINENOISE_MAX_LINE,fp) != NULL) {\n        char *p;\n\n        p = strchr(buf,'\\r');\n        if (!p) p = strchr(buf,'\\n');\n        if (p) *p = '\\0';\n        linenoiseHistoryAdd(buf);\n    }\n    fclose(fp);\n    return 0;\n}\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.8/deps/linenoise/linenoise.h",
    "content": "/* linenoise.h -- VERSION 1.0\n *\n * Guerrilla line editing library against the idea that a line editing lib\n * needs to be 20,000 lines of C code.\n *\n * See linenoise.c for more information.\n *\n * ------------------------------------------------------------------------\n *\n * Copyright (c) 2010-2014, Salvatore Sanfilippo <antirez at gmail dot com>\n * Copyright (c) 2010-2013, Pieter Noordhuis <pcnoordhuis at gmail dot com>\n *\n * All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions are\n * met:\n *\n *  *  Redistributions of source code must retain the above copyright\n *     notice, this list of conditions and the following disclaimer.\n *\n *  *  Redistributions in binary form must reproduce the above copyright\n *     notice, this list of conditions and the following disclaimer in the\n *     documentation and/or other materials provided with the distribution.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n * \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\n * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\n * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\n * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\n * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n\n#ifndef __LINENOISE_H\n#define __LINENOISE_H\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\ntypedef struct linenoiseCompletions {\n  size_t len;\n  char **cvec;\n} linenoiseCompletions;\n\ntypedef void(linenoiseCompletionCallback)(const char *, linenoiseCompletions *);\ntypedef char*(linenoiseHintsCallback)(const char *, int *color, int *bold);\ntypedef void(linenoiseFreeHintsCallback)(void *);\nvoid linenoiseSetCompletionCallback(linenoiseCompletionCallback *);\nvoid linenoiseSetHintsCallback(linenoiseHintsCallback *);\nvoid linenoiseSetFreeHintsCallback(linenoiseFreeHintsCallback *);\nvoid linenoiseAddCompletion(linenoiseCompletions *, const char *);\n\nchar *linenoise(const char *prompt);\nvoid linenoiseFree(void *ptr);\nint linenoiseHistoryAdd(const char *line);\nint linenoiseHistorySetMaxLen(int len);\nint linenoiseHistorySave(const char *filename);\nint linenoiseHistoryLoad(const char *filename);\nvoid linenoiseClearScreen(void);\nvoid linenoiseSetMultiLine(int ml);\nvoid linenoisePrintKeyCodes(void);\n\n#ifdef __cplusplus\n}\n#endif\n\n#endif /* __LINENOISE_H */\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.8/deps/lua/COPYRIGHT",
    "content": "Lua License\n-----------\n\nLua is licensed under the terms of the MIT license reproduced below.\nThis means that Lua is free software and can be used for both academic\nand commercial purposes at absolutely no cost.\n\nFor details and rationale, see http://www.lua.org/license.html .\n\n===============================================================================\n\nCopyright (C) 1994-2012 Lua.org, PUC-Rio.\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in\nall copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\nTHE SOFTWARE.\n\n===============================================================================\n\n(end of COPYRIGHT)\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.8/deps/lua/HISTORY",
    "content": "HISTORY for Lua 5.1\n\n* Changes from version 5.0 to 5.1\n  -------------------------------\n  Language:\n  + new module system.\n  + new semantics for control variables of fors.\n  + new semantics for setn/getn.\n  + new syntax/semantics for varargs.\n  + new long strings and comments.\n  + new `mod' operator (`%')\n  + new length operator #t\n  + metatables for all types\n  API:\n  + new functions: lua_createtable, lua_get(set)field, lua_push(to)integer.\n  + user supplies memory allocator (lua_open becomes lua_newstate).\n  + luaopen_* functions must be called through Lua.\n  Implementation:\n  + new configuration scheme via luaconf.h.\n  + incremental garbage collection.\n  + better handling of end-of-line in the lexer.\n  + fully reentrant parser (new Lua function `load')\n  + better support for 64-bit machines.\n  + native loadlib support for Mac OS X.\n  + standard distribution in only one library (lualib.a merged into lua.a)\n\n* Changes from version 4.0 to 5.0\n  -------------------------------\n  Language:\n  + lexical scoping.\n  + Lua coroutines.\n  + standard libraries now packaged in tables.\n  + tags replaced by metatables and tag methods replaced by metamethods,\n    stored in metatables.\n  + proper tail calls.\n  + each function can have its own global table, which can be shared.\n  + new __newindex metamethod, called when we insert a new key into a table.\n  + new block comments: --[[ ... ]].\n  + new generic for.\n  + new weak tables.\n  + new boolean type.\n  + new syntax \"local function\".\n  + (f()) returns the first value returned by f.\n  + {f()} fills a table with all values returned by f.\n  + \\n ignored in [[\\n .\n  + fixed and-or priorities.\n  + more general syntax for function definition (e.g. function a.x.y:f()...end).\n  + more general syntax for function calls (e.g. (print or write)(9)).\n  + new functions (time/date, tmpfile, unpack, require, load*, etc.).\n  API:\n  + chunks are loaded by using lua_load; new luaL_loadfile and luaL_loadbuffer.\n  + introduced lightweight userdata, a simple \"void*\" without a metatable.\n  + new error handling protocol: the core no longer prints error messages;\n    all errors are reported to the caller on the stack.\n  + new lua_atpanic for host cleanup.\n  + new, signal-safe, hook scheme.\n  Implementation:\n  + new license: MIT.\n  + new, faster, register-based virtual machine.\n  + support for external multithreading and coroutines.\n  + new and consistent error message format.\n  + the core no longer needs \"stdio.h\" for anything (except for a single\n    use of sprintf to convert numbers to strings).\n  + lua.c now runs the environment variable LUA_INIT, if present. It can\n    be \"@filename\", to run a file, or the chunk itself.\n  + support for user extensions in lua.c.\n    sample implementation given for command line editing.\n  + new dynamic loading library, active by default on several platforms.\n  + safe garbage-collector metamethods.\n  + precompiled bytecodes checked for integrity (secure binary dostring).\n  + strings are fully aligned.\n  + position capture in string.find.\n  + read('*l') can read lines with embedded zeros.\n\n* Changes from version 3.2 to 4.0\n  -------------------------------\n  Language:\n  + new \"break\" and \"for\" statements (both numerical and for tables).\n  + uniform treatment of globals: globals are now stored in a Lua table.\n  + improved error messages.\n  + no more '$debug': full speed *and* full debug information.\n  + new read form: read(N) for next N bytes.\n  + general read patterns now deprecated.\n    (still available with -DCOMPAT_READPATTERNS.)\n  + all return values are passed as arguments for the last function\n    (old semantics still available with -DLUA_COMPAT_ARGRET)\n  + garbage collection tag methods for tables now deprecated.\n  + there is now only one tag method for order.\n  API:\n  + New API: fully re-entrant, simpler, and more efficient.\n  + New debug API.\n  Implementation:\n  + faster than ever: cleaner virtual machine and new hashing algorithm.\n  + non-recursive garbage-collector algorithm.\n  + reduced memory usage for programs with many strings.\n  + improved treatment for memory allocation errors.\n  + improved support for 16-bit machines (we hope).\n  + code now compiles unmodified as both ANSI C and C++.\n  + numbers in bases other than 10 are converted using strtoul.\n  + new -f option in Lua to support #! scripts.\n  + luac can now combine text and binaries.\n\n* Changes from version 3.1 to 3.2\n  -------------------------------\n  + redirected all output in Lua's core to _ERRORMESSAGE and _ALERT.\n  + increased limit on the number of constants and globals per function\n    (from 2^16 to 2^24).\n  + debugging info (lua_debug and hooks) moved into lua_state and new API\n    functions provided to get and set this info.\n  + new debug lib gives full debugging access within Lua.\n  + new table functions \"foreachi\", \"sort\", \"tinsert\", \"tremove\", \"getn\".\n  + new io functions \"flush\", \"seek\".\n\n* Changes from version 3.0 to 3.1\n  -------------------------------\n  + NEW FEATURE: anonymous functions with closures (via \"upvalues\").\n  + new syntax:\n    - local variables in chunks.\n    - better scope control with DO block END.\n    - constructors can now be also written: { record-part; list-part }.\n    - more general syntax for function calls and lvalues, e.g.:\n      f(x).y=1\n      o:f(x,y):g(z)\n      f\"string\" is sugar for f(\"string\")\n  + strings may now contain arbitrary binary data (e.g., embedded zeros).\n  + major code re-organization and clean-up; reduced module interdependecies.\n  + no arbitrary limits on the total number of constants and globals.\n  + support for multiple global contexts.\n  + better syntax error messages.\n  + new traversal functions \"foreach\" and \"foreachvar\".\n  + the default for numbers is now double.\n    changing it to use floats or longs is easy.\n  + complete debug information stored in pre-compiled chunks.\n  + sample interpreter now prompts user when run interactively, and also\n    handles control-C interruptions gracefully.\n\n* Changes from version 2.5 to 3.0\n  -------------------------------\n  + NEW CONCEPT: \"tag methods\".\n    Tag methods replace fallbacks as the meta-mechanism for extending the\n    semantics of Lua. Whereas fallbacks had a global nature, tag methods\n    work on objects having the same tag (e.g., groups of tables).\n    Existing code that uses fallbacks should work without change.\n  + new, general syntax for constructors {[exp] = exp, ... }.\n  + support for handling variable number of arguments in functions (varargs).\n  + support for conditional compilation ($if ... $else ... $end).\n  + cleaner semantics in API simplifies host code.\n  + better support for writing libraries (auxlib.h).\n  + better type checking and error messages in the standard library.\n  + luac can now also undump.\n\n* Changes from version 2.4 to 2.5\n  -------------------------------\n  + io and string libraries are now based on pattern matching;\n    the old libraries are still available for compatibility\n  + dofile and dostring can now return values (via return statement)\n  + better support for 16- and 64-bit machines\n  + expanded documentation, with more examples\n\n* Changes from version 2.2 to 2.4\n  -------------------------------\n  + external compiler creates portable binary files that can be loaded faster\n  + interface for debugging and profiling\n  + new \"getglobal\" fallback\n  + new functions for handling references to Lua objects\n  + new functions in standard lib\n  + only one copy of each string is stored\n  + expanded documentation, with more examples\n\n* Changes from version 2.1 to 2.2\n  -------------------------------\n  + functions now may be declared with any \"lvalue\" as a name\n  + garbage collection of functions\n  + support for pipes\n\n* Changes from version 1.1 to 2.1\n  -------------------------------\n  + object-oriented support\n  + fallbacks\n  + simplified syntax for tables\n  + many internal improvements\n\n(end of HISTORY)\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.8/deps/lua/INSTALL",
    "content": "INSTALL for Lua 5.1\n\n* Building Lua\n  ------------\n  Lua is built in the src directory, but the build process can be\n  controlled from the top-level Makefile.\n\n  Building Lua on Unix systems should be very easy. First do \"make\" and\n  see if your platform is listed. If so, just do \"make xxx\", where xxx\n  is your platform name. The platforms currently supported are:\n    aix ansi bsd freebsd generic linux macosx mingw posix solaris\n\n  If your platform is not listed, try the closest one or posix, generic,\n  ansi, in this order.\n\n  See below for customization instructions and for instructions on how\n  to build with other Windows compilers.\n\n  If you want to check that Lua has been built correctly, do \"make test\"\n  after building Lua. Also, have a look at the example programs in test.\n\n* Installing Lua\n  --------------\n  Once you have built Lua, you may want to install it in an official\n  place in your system. In this case, do \"make install\". The official\n  place and the way to install files are defined in Makefile. You must\n  have the right permissions to install files.\n\n  If you want to build and install Lua in one step, do \"make xxx install\",\n  where xxx is your platform name.\n\n  If you want to install Lua locally, then do \"make local\". This will\n  create directories bin, include, lib, man, and install Lua there as\n  follows:\n\n    bin:\tlua luac\n    include:\tlua.h luaconf.h lualib.h lauxlib.h lua.hpp\n    lib:\tliblua.a\n    man/man1:\tlua.1 luac.1\n\n  These are the only directories you need for development.\n\n  There are man pages for lua and luac, in both nroff and html, and a\n  reference manual in html in doc, some sample code in test, and some\n  useful stuff in etc. You don't need these directories for development.\n\n  If you want to install Lua locally, but in some other directory, do\n  \"make install INSTALL_TOP=xxx\", where xxx is your chosen directory.\n\n  See below for instructions for Windows and other systems.\n\n* Customization\n  -------------\n  Three things can be customized by editing a file:\n    - Where and how to install Lua -- edit Makefile.\n    - How to build Lua -- edit src/Makefile.\n    - Lua features -- edit src/luaconf.h.\n\n  You don't actually need to edit the Makefiles because you may set the\n  relevant variables when invoking make.\n\n  On the other hand, if you need to select some Lua features, you'll need\n  to edit src/luaconf.h. The edited file will be the one installed, and\n  it will be used by any Lua clients that you build, to ensure consistency.\n\n  We strongly recommend that you enable dynamic loading. This is done\n  automatically for all platforms listed above that have this feature\n  (and also Windows). See src/luaconf.h and also src/Makefile.\n\n* Building Lua on Windows and other systems\n  -----------------------------------------\n  If you're not using the usual Unix tools, then the instructions for\n  building Lua depend on the compiler you use. You'll need to create\n  projects (or whatever your compiler uses) for building the library,\n  the interpreter, and the compiler, as follows:\n\n  library:\tlapi.c lcode.c ldebug.c ldo.c ldump.c lfunc.c lgc.c llex.c\n\t\tlmem.c lobject.c lopcodes.c lparser.c lstate.c lstring.c\n\t\tltable.c ltm.c lundump.c lvm.c lzio.c\n\t\tlauxlib.c lbaselib.c ldblib.c liolib.c lmathlib.c loslib.c\n\t\tltablib.c lstrlib.c loadlib.c linit.c\n\n  interpreter:\tlibrary, lua.c\n\n  compiler:\tlibrary, luac.c print.c\n\n  If you use Visual Studio .NET, you can use etc/luavs.bat in its\n  \"Command Prompt\".\n\n  If all you want is to build the Lua interpreter, you may put all .c files\n  in a single project, except for luac.c and print.c. Or just use etc/all.c.\n\n  To use Lua as a library in your own programs, you'll need to know how to\n  create and use libraries with your compiler.\n\n  As mentioned above, you may edit luaconf.h to select some features before\n  building Lua.\n\n(end of INSTALL)\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.8/deps/lua/Makefile",
    "content": "# makefile for installing Lua\n# see INSTALL for installation instructions\n# see src/Makefile and src/luaconf.h for further customization\n\n# == CHANGE THE SETTINGS BELOW TO SUIT YOUR ENVIRONMENT =======================\n\n# Your platform. See PLATS for possible values.\nPLAT= none\n\n# Where to install. The installation starts in the src and doc directories,\n# so take care if INSTALL_TOP is not an absolute path.\nINSTALL_TOP= /usr/local\nINSTALL_BIN= $(INSTALL_TOP)/bin\nINSTALL_INC= $(INSTALL_TOP)/include\nINSTALL_LIB= $(INSTALL_TOP)/lib\nINSTALL_MAN= $(INSTALL_TOP)/man/man1\n#\n# You probably want to make INSTALL_LMOD and INSTALL_CMOD consistent with\n# LUA_ROOT, LUA_LDIR, and LUA_CDIR in luaconf.h (and also with etc/lua.pc).\nINSTALL_LMOD= $(INSTALL_TOP)/share/lua/$V\nINSTALL_CMOD= $(INSTALL_TOP)/lib/lua/$V\n\n# How to install. If your install program does not support \"-p\", then you\n# may have to run ranlib on the installed liblua.a (do \"make ranlib\").\nINSTALL= install -p\nINSTALL_EXEC= $(INSTALL) -m 0755\nINSTALL_DATA= $(INSTALL) -m 0644\n#\n# If you don't have install you can use cp instead.\n# INSTALL= cp -p\n# INSTALL_EXEC= $(INSTALL)\n# INSTALL_DATA= $(INSTALL)\n\n# Utilities.\nMKDIR= mkdir -p\nRANLIB= ranlib\n\n# == END OF USER SETTINGS. NO NEED TO CHANGE ANYTHING BELOW THIS LINE =========\n\n# Convenience platforms targets.\nPLATS= aix ansi bsd freebsd generic linux macosx mingw posix solaris\n\n# What to install.\nTO_BIN= lua luac\nTO_INC= lua.h luaconf.h lualib.h lauxlib.h ../etc/lua.hpp\nTO_LIB= liblua.a\nTO_MAN= lua.1 luac.1\n\n# Lua version and release.\nV= 5.1\nR= 5.1.5\n\nall:\t$(PLAT)\n\n$(PLATS) clean:\n\tcd src && $(MAKE) $@\n\ntest:\tdummy\n\tsrc/lua test/hello.lua\n\ninstall: dummy\n\tcd src && $(MKDIR) $(INSTALL_BIN) $(INSTALL_INC) $(INSTALL_LIB) $(INSTALL_MAN) $(INSTALL_LMOD) $(INSTALL_CMOD)\n\tcd src && $(INSTALL_EXEC) $(TO_BIN) $(INSTALL_BIN)\n\tcd src && $(INSTALL_DATA) $(TO_INC) $(INSTALL_INC)\n\tcd src && $(INSTALL_DATA) $(TO_LIB) $(INSTALL_LIB)\n\tcd doc && $(INSTALL_DATA) $(TO_MAN) $(INSTALL_MAN)\n\nranlib:\n\tcd src && cd $(INSTALL_LIB) && $(RANLIB) $(TO_LIB)\n\nlocal:\n\t$(MAKE) install INSTALL_TOP=..\n\nnone:\n\t@echo \"Please do\"\n\t@echo \"   make PLATFORM\"\n\t@echo \"where PLATFORM is one of these:\"\n\t@echo \"   $(PLATS)\"\n\t@echo \"See INSTALL for complete instructions.\"\n\n# make may get confused with test/ and INSTALL in a case-insensitive OS\ndummy:\n\n# echo config parameters\necho:\n\t@echo \"\"\n\t@echo \"These are the parameters currently set in src/Makefile to build Lua $R:\"\n\t@echo \"\"\n\t@cd src && $(MAKE) -s echo\n\t@echo \"\"\n\t@echo \"These are the parameters currently set in Makefile to install Lua $R:\"\n\t@echo \"\"\n\t@echo \"PLAT = $(PLAT)\"\n\t@echo \"INSTALL_TOP = $(INSTALL_TOP)\"\n\t@echo \"INSTALL_BIN = $(INSTALL_BIN)\"\n\t@echo \"INSTALL_INC = $(INSTALL_INC)\"\n\t@echo \"INSTALL_LIB = $(INSTALL_LIB)\"\n\t@echo \"INSTALL_MAN = $(INSTALL_MAN)\"\n\t@echo \"INSTALL_LMOD = $(INSTALL_LMOD)\"\n\t@echo \"INSTALL_CMOD = $(INSTALL_CMOD)\"\n\t@echo \"INSTALL_EXEC = $(INSTALL_EXEC)\"\n\t@echo \"INSTALL_DATA = $(INSTALL_DATA)\"\n\t@echo \"\"\n\t@echo \"See also src/luaconf.h .\"\n\t@echo \"\"\n\n# echo private config parameters\npecho:\n\t@echo \"V = $(V)\"\n\t@echo \"R = $(R)\"\n\t@echo \"TO_BIN = $(TO_BIN)\"\n\t@echo \"TO_INC = $(TO_INC)\"\n\t@echo \"TO_LIB = $(TO_LIB)\"\n\t@echo \"TO_MAN = $(TO_MAN)\"\n\n# echo config parameters as Lua code\n# uncomment the last sed expression if you want nil instead of empty strings\nlecho:\n\t@echo \"-- installation parameters for Lua $R\"\n\t@echo \"VERSION = '$V'\"\n\t@echo \"RELEASE = '$R'\"\n\t@$(MAKE) echo | grep = | sed -e 's/= /= \"/' -e 's/$$/\"/' #-e 's/\"\"/nil/'\n\t@echo \"-- EOF\"\n\n# list targets that do not create files (but not all makes understand .PHONY)\n.PHONY: all $(PLATS) clean test install local none dummy echo pecho lecho\n\n# (end of Makefile)\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.8/deps/lua/README",
    "content": "README for Lua 5.1\n\nSee INSTALL for installation instructions.\nSee HISTORY for a summary of changes since the last released version.\n\n* What is Lua?\n  ------------\n  Lua is a powerful, light-weight programming language designed for extending\n  applications. Lua is also frequently used as a general-purpose, stand-alone\n  language. Lua is free software.\n\n  For complete information, visit Lua's web site at http://www.lua.org/ .\n  For an executive summary, see http://www.lua.org/about.html .\n\n  Lua has been used in many different projects around the world.\n  For a short list, see http://www.lua.org/uses.html .\n\n* Availability\n  ------------\n  Lua is freely available for both academic and commercial purposes.\n  See COPYRIGHT and http://www.lua.org/license.html for details.\n  Lua can be downloaded at http://www.lua.org/download.html .\n\n* Installation\n  ------------\n  Lua is implemented in pure ANSI C, and compiles unmodified in all known\n  platforms that have an ANSI C compiler. In most Unix-like platforms, simply\n  do \"make\" with a suitable target. See INSTALL for detailed instructions.\n\n* Origin\n  ------\n  Lua is developed at Lua.org, a laboratory of the Department of Computer\n  Science of PUC-Rio (the Pontifical Catholic University of Rio de Janeiro\n  in Brazil).\n  For more information about the authors, see http://www.lua.org/authors.html .\n\n(end of README)\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.8/deps/lua/doc/contents.html",
    "content": "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\">\n<HTML>\n<HEAD>\n<TITLE>Lua 5.1 Reference Manual - contents</TITLE>\n<LINK REL=\"stylesheet\" TYPE=\"text/css\" HREF=\"lua.css\">\n<META HTTP-EQUIV=\"content-type\" CONTENT=\"text/html; charset=utf-8\">\n<STYLE TYPE=\"text/css\">\nul {\n\tlist-style-type: none ;\n}\n</STYLE>\n</HEAD>\n\n<BODY>\n\n<HR>\n<H1>\n<A HREF=\"http://www.lua.org/\"><IMG SRC=\"logo.gif\" ALT=\"\" BORDER=0></A>\nLua 5.1 Reference Manual\n</H1>\n\n<P>\nThe reference manual is the official definition of the Lua language.\nFor a complete introduction to Lua programming, see the book\n<A HREF=\"http://www.lua.org/docs.html#pil\">Programming in Lua</A>.\n\n<P>\nThis manual is also available as a book:\n<BLOCKQUOTE>\n<A HREF=\"http://www.amazon.com/exec/obidos/ASIN/8590379833/lua-indexmanual-20\">\n<IMG SRC=\"cover.png\" ALT=\"\" TITLE=\"buy from Amazon\" BORDER=1 ALIGN=\"left\" HSPACE=12>\n</A>\n<B>Lua 5.1 Reference Manual</B>\n<BR>by R. Ierusalimschy, L. H. de Figueiredo, W. Celes\n<BR>Lua.org, August 2006\n<BR>ISBN 85-903798-3-3\n<BR CLEAR=\"all\">\n</BLOCKQUOTE>\n\n<P>\n<A HREF=\"http://www.amazon.com/exec/obidos/ASIN/8590379833/lua-indexmanual-20\">Buy a copy</A>\nof this book and\n<A HREF=\"http://www.lua.org/donations.html\">help to support</A>\nthe Lua project.\n\n<P>\n<A HREF=\"manual.html\">start</A>\n&middot;\n<A HREF=\"#contents\">contents</A>\n&middot;\n<A HREF=\"#index\">index</A>\n&middot;\n<A HREF=\"http://www.lua.org/manual/\">other versions</A>\n<HR>\n<SMALL>\nCopyright &copy; 2006&ndash;2012 Lua.org, PUC-Rio.\nFreely available under the terms of the\n<A HREF=\"http://www.lua.org/license.html\">Lua license</A>.\n</SMALL>\n\n<H2><A NAME=\"contents\">Contents</A></H2>\n<UL style=\"padding: 0\">\n<LI><A HREF=\"manual.html\">1 &ndash; Introduction</A>\n<P>\n<LI><A HREF=\"manual.html#2\">2 &ndash; The Language</A>\n<UL>\n<LI><A HREF=\"manual.html#2.1\">2.1 &ndash; Lexical Conventions</A>\n<LI><A HREF=\"manual.html#2.2\">2.2 &ndash; Values and Types</A>\n<UL>\n<LI><A HREF=\"manual.html#2.2.1\">2.2.1 &ndash; Coercion</A>\n</UL>\n<LI><A HREF=\"manual.html#2.3\">2.3 &ndash; Variables</A>\n<LI><A HREF=\"manual.html#2.4\">2.4 &ndash; Statements</A>\n<UL>\n<LI><A HREF=\"manual.html#2.4.1\">2.4.1 &ndash; Chunks</A>\n<LI><A HREF=\"manual.html#2.4.2\">2.4.2 &ndash; Blocks</A>\n<LI><A HREF=\"manual.html#2.4.3\">2.4.3 &ndash; Assignment</A>\n<LI><A HREF=\"manual.html#2.4.4\">2.4.4 &ndash; Control Structures</A>\n<LI><A HREF=\"manual.html#2.4.5\">2.4.5 &ndash; For Statement</A>\n<LI><A HREF=\"manual.html#2.4.6\">2.4.6 &ndash; Function Calls as Statements</A>\n<LI><A HREF=\"manual.html#2.4.7\">2.4.7 &ndash; Local Declarations</A>\n</UL>\n<LI><A HREF=\"manual.html#2.5\">2.5 &ndash; Expressions</A>\n<UL>\n<LI><A HREF=\"manual.html#2.5.1\">2.5.1 &ndash; Arithmetic Operators</A>\n<LI><A HREF=\"manual.html#2.5.2\">2.5.2 &ndash; Relational Operators</A>\n<LI><A HREF=\"manual.html#2.5.3\">2.5.3 &ndash; Logical Operators</A>\n<LI><A HREF=\"manual.html#2.5.4\">2.5.4 &ndash; Concatenation</A>\n<LI><A HREF=\"manual.html#2.5.5\">2.5.5 &ndash; The Length Operator</A>\n<LI><A HREF=\"manual.html#2.5.6\">2.5.6 &ndash; Precedence</A>\n<LI><A HREF=\"manual.html#2.5.7\">2.5.7 &ndash; Table Constructors</A>\n<LI><A HREF=\"manual.html#2.5.8\">2.5.8 &ndash; Function Calls</A>\n<LI><A HREF=\"manual.html#2.5.9\">2.5.9 &ndash; Function Definitions</A>\n</UL>\n<LI><A HREF=\"manual.html#2.6\">2.6 &ndash; Visibility Rules</A>\n<LI><A HREF=\"manual.html#2.7\">2.7 &ndash; Error Handling</A>\n<LI><A HREF=\"manual.html#2.8\">2.8 &ndash; Metatables</A>\n<LI><A HREF=\"manual.html#2.9\">2.9 &ndash; Environments</A>\n<LI><A HREF=\"manual.html#2.10\">2.10 &ndash; Garbage Collection</A>\n<UL>\n<LI><A HREF=\"manual.html#2.10.1\">2.10.1 &ndash; Garbage-Collection Metamethods</A>\n<LI><A HREF=\"manual.html#2.10.2\">2.10.2 &ndash; Weak Tables</A>\n</UL>\n<LI><A HREF=\"manual.html#2.11\">2.11 &ndash; Coroutines</A>\n</UL>\n<P>\n<LI><A HREF=\"manual.html#3\">3 &ndash; The Application Program Interface</A>\n<UL>\n<LI><A HREF=\"manual.html#3.1\">3.1 &ndash; The Stack</A>\n<LI><A HREF=\"manual.html#3.2\">3.2 &ndash; Stack Size</A>\n<LI><A HREF=\"manual.html#3.3\">3.3 &ndash; Pseudo-Indices</A>\n<LI><A HREF=\"manual.html#3.4\">3.4 &ndash; C Closures</A>\n<LI><A HREF=\"manual.html#3.5\">3.5 &ndash; Registry</A>\n<LI><A HREF=\"manual.html#3.6\">3.6 &ndash; Error Handling in C</A>\n<LI><A HREF=\"manual.html#3.7\">3.7 &ndash; Functions and Types</A>\n<LI><A HREF=\"manual.html#3.8\">3.8 &ndash; The Debug Interface</A>\n</UL>\n<P>\n<LI><A HREF=\"manual.html#4\">4 &ndash; The Auxiliary Library</A>\n<UL>\n<LI><A HREF=\"manual.html#4.1\">4.1 &ndash; Functions and Types</A>\n</UL>\n<P>\n<LI><A HREF=\"manual.html#5\">5 &ndash; Standard Libraries</A>\n<UL>\n<LI><A HREF=\"manual.html#5.1\">5.1 &ndash; Basic Functions</A>\n<LI><A HREF=\"manual.html#5.2\">5.2 &ndash; Coroutine Manipulation</A>\n<LI><A HREF=\"manual.html#5.3\">5.3 &ndash; Modules</A>\n<LI><A HREF=\"manual.html#5.4\">5.4 &ndash; String Manipulation</A>\n<UL>\n<LI><A HREF=\"manual.html#5.4.1\">5.4.1 &ndash; Patterns</A>\n</UL>\n<LI><A HREF=\"manual.html#5.5\">5.5 &ndash; Table Manipulation</A>\n<LI><A HREF=\"manual.html#5.6\">5.6 &ndash; Mathematical Functions</A>\n<LI><A HREF=\"manual.html#5.7\">5.7 &ndash; Input and Output Facilities</A>\n<LI><A HREF=\"manual.html#5.8\">5.8 &ndash; Operating System Facilities</A>\n<LI><A HREF=\"manual.html#5.9\">5.9 &ndash; The Debug Library</A>\n</UL>\n<P>\n<LI><A HREF=\"manual.html#6\">6 &ndash; Lua Stand-alone</A>\n<P>\n<LI><A HREF=\"manual.html#7\">7 &ndash; Incompatibilities with the Previous Version</A>\n<UL>\n<LI><A HREF=\"manual.html#7.1\">7.1 &ndash; Changes in the Language</A>\n<LI><A HREF=\"manual.html#7.2\">7.2 &ndash; Changes in the Libraries</A>\n<LI><A HREF=\"manual.html#7.3\">7.3 &ndash; Changes in the API</A>\n</UL>\n<P>\n<LI><A HREF=\"manual.html#8\">8 &ndash; The Complete Syntax of Lua</A>\n</UL>\n\n<H2><A NAME=\"index\">Index</A></H2>\n<TABLE WIDTH=\"100%\">\n<TR VALIGN=\"top\">\n<TD>\n<H3><A NAME=\"functions\">Lua functions</A></H3>\n<A HREF=\"manual.html#pdf-_G\">_G</A><BR>\n<A HREF=\"manual.html#pdf-_VERSION\">_VERSION</A><BR>\n<P>\n\n<A HREF=\"manual.html#pdf-assert\">assert</A><BR>\n<A HREF=\"manual.html#pdf-collectgarbage\">collectgarbage</A><BR>\n<A HREF=\"manual.html#pdf-dofile\">dofile</A><BR>\n<A HREF=\"manual.html#pdf-error\">error</A><BR>\n<A HREF=\"manual.html#pdf-getfenv\">getfenv</A><BR>\n<A HREF=\"manual.html#pdf-getmetatable\">getmetatable</A><BR>\n<A HREF=\"manual.html#pdf-ipairs\">ipairs</A><BR>\n<A HREF=\"manual.html#pdf-load\">load</A><BR>\n<A HREF=\"manual.html#pdf-loadfile\">loadfile</A><BR>\n<A HREF=\"manual.html#pdf-loadstring\">loadstring</A><BR>\n<A HREF=\"manual.html#pdf-module\">module</A><BR>\n<A HREF=\"manual.html#pdf-next\">next</A><BR>\n<A HREF=\"manual.html#pdf-pairs\">pairs</A><BR>\n<A HREF=\"manual.html#pdf-pcall\">pcall</A><BR>\n<A HREF=\"manual.html#pdf-print\">print</A><BR>\n<A HREF=\"manual.html#pdf-rawequal\">rawequal</A><BR>\n<A HREF=\"manual.html#pdf-rawget\">rawget</A><BR>\n<A HREF=\"manual.html#pdf-rawset\">rawset</A><BR>\n<A HREF=\"manual.html#pdf-require\">require</A><BR>\n<A HREF=\"manual.html#pdf-select\">select</A><BR>\n<A HREF=\"manual.html#pdf-setfenv\">setfenv</A><BR>\n<A HREF=\"manual.html#pdf-setmetatable\">setmetatable</A><BR>\n<A HREF=\"manual.html#pdf-tonumber\">tonumber</A><BR>\n<A HREF=\"manual.html#pdf-tostring\">tostring</A><BR>\n<A HREF=\"manual.html#pdf-type\">type</A><BR>\n<A HREF=\"manual.html#pdf-unpack\">unpack</A><BR>\n<A HREF=\"manual.html#pdf-xpcall\">xpcall</A><BR>\n<P>\n\n<A HREF=\"manual.html#pdf-coroutine.create\">coroutine.create</A><BR>\n<A HREF=\"manual.html#pdf-coroutine.resume\">coroutine.resume</A><BR>\n<A HREF=\"manual.html#pdf-coroutine.running\">coroutine.running</A><BR>\n<A HREF=\"manual.html#pdf-coroutine.status\">coroutine.status</A><BR>\n<A HREF=\"manual.html#pdf-coroutine.wrap\">coroutine.wrap</A><BR>\n<A HREF=\"manual.html#pdf-coroutine.yield\">coroutine.yield</A><BR>\n<P>\n\n<A HREF=\"manual.html#pdf-debug.debug\">debug.debug</A><BR>\n<A HREF=\"manual.html#pdf-debug.getfenv\">debug.getfenv</A><BR>\n<A HREF=\"manual.html#pdf-debug.gethook\">debug.gethook</A><BR>\n<A HREF=\"manual.html#pdf-debug.getinfo\">debug.getinfo</A><BR>\n<A HREF=\"manual.html#pdf-debug.getlocal\">debug.getlocal</A><BR>\n<A HREF=\"manual.html#pdf-debug.getmetatable\">debug.getmetatable</A><BR>\n<A HREF=\"manual.html#pdf-debug.getregistry\">debug.getregistry</A><BR>\n<A HREF=\"manual.html#pdf-debug.getupvalue\">debug.getupvalue</A><BR>\n<A HREF=\"manual.html#pdf-debug.setfenv\">debug.setfenv</A><BR>\n<A HREF=\"manual.html#pdf-debug.sethook\">debug.sethook</A><BR>\n<A HREF=\"manual.html#pdf-debug.setlocal\">debug.setlocal</A><BR>\n<A HREF=\"manual.html#pdf-debug.setmetatable\">debug.setmetatable</A><BR>\n<A HREF=\"manual.html#pdf-debug.setupvalue\">debug.setupvalue</A><BR>\n<A HREF=\"manual.html#pdf-debug.traceback\">debug.traceback</A><BR>\n\n</TD>\n<TD>\n<H3>&nbsp;</H3>\n<A HREF=\"manual.html#pdf-file:close\">file:close</A><BR>\n<A HREF=\"manual.html#pdf-file:flush\">file:flush</A><BR>\n<A HREF=\"manual.html#pdf-file:lines\">file:lines</A><BR>\n<A HREF=\"manual.html#pdf-file:read\">file:read</A><BR>\n<A HREF=\"manual.html#pdf-file:seek\">file:seek</A><BR>\n<A HREF=\"manual.html#pdf-file:setvbuf\">file:setvbuf</A><BR>\n<A HREF=\"manual.html#pdf-file:write\">file:write</A><BR>\n<P>\n\n<A HREF=\"manual.html#pdf-io.close\">io.close</A><BR>\n<A HREF=\"manual.html#pdf-io.flush\">io.flush</A><BR>\n<A HREF=\"manual.html#pdf-io.input\">io.input</A><BR>\n<A HREF=\"manual.html#pdf-io.lines\">io.lines</A><BR>\n<A HREF=\"manual.html#pdf-io.open\">io.open</A><BR>\n<A HREF=\"manual.html#pdf-io.output\">io.output</A><BR>\n<A HREF=\"manual.html#pdf-io.popen\">io.popen</A><BR>\n<A HREF=\"manual.html#pdf-io.read\">io.read</A><BR>\n<A HREF=\"manual.html#pdf-io.stderr\">io.stderr</A><BR>\n<A HREF=\"manual.html#pdf-io.stdin\">io.stdin</A><BR>\n<A HREF=\"manual.html#pdf-io.stdout\">io.stdout</A><BR>\n<A HREF=\"manual.html#pdf-io.tmpfile\">io.tmpfile</A><BR>\n<A HREF=\"manual.html#pdf-io.type\">io.type</A><BR>\n<A HREF=\"manual.html#pdf-io.write\">io.write</A><BR>\n<P>\n\n<A HREF=\"manual.html#pdf-math.abs\">math.abs</A><BR>\n<A HREF=\"manual.html#pdf-math.acos\">math.acos</A><BR>\n<A HREF=\"manual.html#pdf-math.asin\">math.asin</A><BR>\n<A HREF=\"manual.html#pdf-math.atan\">math.atan</A><BR>\n<A HREF=\"manual.html#pdf-math.atan2\">math.atan2</A><BR>\n<A HREF=\"manual.html#pdf-math.ceil\">math.ceil</A><BR>\n<A HREF=\"manual.html#pdf-math.cos\">math.cos</A><BR>\n<A HREF=\"manual.html#pdf-math.cosh\">math.cosh</A><BR>\n<A HREF=\"manual.html#pdf-math.deg\">math.deg</A><BR>\n<A HREF=\"manual.html#pdf-math.exp\">math.exp</A><BR>\n<A HREF=\"manual.html#pdf-math.floor\">math.floor</A><BR>\n<A HREF=\"manual.html#pdf-math.fmod\">math.fmod</A><BR>\n<A HREF=\"manual.html#pdf-math.frexp\">math.frexp</A><BR>\n<A HREF=\"manual.html#pdf-math.huge\">math.huge</A><BR>\n<A HREF=\"manual.html#pdf-math.ldexp\">math.ldexp</A><BR>\n<A HREF=\"manual.html#pdf-math.log\">math.log</A><BR>\n<A HREF=\"manual.html#pdf-math.log10\">math.log10</A><BR>\n<A HREF=\"manual.html#pdf-math.max\">math.max</A><BR>\n<A HREF=\"manual.html#pdf-math.min\">math.min</A><BR>\n<A HREF=\"manual.html#pdf-math.modf\">math.modf</A><BR>\n<A HREF=\"manual.html#pdf-math.pi\">math.pi</A><BR>\n<A HREF=\"manual.html#pdf-math.pow\">math.pow</A><BR>\n<A HREF=\"manual.html#pdf-math.rad\">math.rad</A><BR>\n<A HREF=\"manual.html#pdf-math.random\">math.random</A><BR>\n<A HREF=\"manual.html#pdf-math.randomseed\">math.randomseed</A><BR>\n<A HREF=\"manual.html#pdf-math.sin\">math.sin</A><BR>\n<A HREF=\"manual.html#pdf-math.sinh\">math.sinh</A><BR>\n<A HREF=\"manual.html#pdf-math.sqrt\">math.sqrt</A><BR>\n<A HREF=\"manual.html#pdf-math.tan\">math.tan</A><BR>\n<A HREF=\"manual.html#pdf-math.tanh\">math.tanh</A><BR>\n<P>\n\n<A HREF=\"manual.html#pdf-os.clock\">os.clock</A><BR>\n<A HREF=\"manual.html#pdf-os.date\">os.date</A><BR>\n<A HREF=\"manual.html#pdf-os.difftime\">os.difftime</A><BR>\n<A HREF=\"manual.html#pdf-os.execute\">os.execute</A><BR>\n<A HREF=\"manual.html#pdf-os.exit\">os.exit</A><BR>\n<A HREF=\"manual.html#pdf-os.getenv\">os.getenv</A><BR>\n<A HREF=\"manual.html#pdf-os.remove\">os.remove</A><BR>\n<A HREF=\"manual.html#pdf-os.rename\">os.rename</A><BR>\n<A HREF=\"manual.html#pdf-os.setlocale\">os.setlocale</A><BR>\n<A HREF=\"manual.html#pdf-os.time\">os.time</A><BR>\n<A HREF=\"manual.html#pdf-os.tmpname\">os.tmpname</A><BR>\n<P>\n\n<A HREF=\"manual.html#pdf-package.cpath\">package.cpath</A><BR>\n<A HREF=\"manual.html#pdf-package.loaded\">package.loaded</A><BR>\n<A HREF=\"manual.html#pdf-package.loaders\">package.loaders</A><BR>\n<A HREF=\"manual.html#pdf-package.loadlib\">package.loadlib</A><BR>\n<A HREF=\"manual.html#pdf-package.path\">package.path</A><BR>\n<A HREF=\"manual.html#pdf-package.preload\">package.preload</A><BR>\n<A HREF=\"manual.html#pdf-package.seeall\">package.seeall</A><BR>\n<P>\n\n<A HREF=\"manual.html#pdf-string.byte\">string.byte</A><BR>\n<A HREF=\"manual.html#pdf-string.char\">string.char</A><BR>\n<A HREF=\"manual.html#pdf-string.dump\">string.dump</A><BR>\n<A HREF=\"manual.html#pdf-string.find\">string.find</A><BR>\n<A HREF=\"manual.html#pdf-string.format\">string.format</A><BR>\n<A HREF=\"manual.html#pdf-string.gmatch\">string.gmatch</A><BR>\n<A HREF=\"manual.html#pdf-string.gsub\">string.gsub</A><BR>\n<A HREF=\"manual.html#pdf-string.len\">string.len</A><BR>\n<A HREF=\"manual.html#pdf-string.lower\">string.lower</A><BR>\n<A HREF=\"manual.html#pdf-string.match\">string.match</A><BR>\n<A HREF=\"manual.html#pdf-string.rep\">string.rep</A><BR>\n<A HREF=\"manual.html#pdf-string.reverse\">string.reverse</A><BR>\n<A HREF=\"manual.html#pdf-string.sub\">string.sub</A><BR>\n<A HREF=\"manual.html#pdf-string.upper\">string.upper</A><BR>\n<P>\n\n<A HREF=\"manual.html#pdf-table.concat\">table.concat</A><BR>\n<A HREF=\"manual.html#pdf-table.insert\">table.insert</A><BR>\n<A HREF=\"manual.html#pdf-table.maxn\">table.maxn</A><BR>\n<A HREF=\"manual.html#pdf-table.remove\">table.remove</A><BR>\n<A HREF=\"manual.html#pdf-table.sort\">table.sort</A><BR>\n\n</TD>\n<TD>\n<H3>C API</H3>\n<A HREF=\"manual.html#lua_Alloc\">lua_Alloc</A><BR>\n<A HREF=\"manual.html#lua_CFunction\">lua_CFunction</A><BR>\n<A HREF=\"manual.html#lua_Debug\">lua_Debug</A><BR>\n<A HREF=\"manual.html#lua_Hook\">lua_Hook</A><BR>\n<A HREF=\"manual.html#lua_Integer\">lua_Integer</A><BR>\n<A HREF=\"manual.html#lua_Number\">lua_Number</A><BR>\n<A HREF=\"manual.html#lua_Reader\">lua_Reader</A><BR>\n<A HREF=\"manual.html#lua_State\">lua_State</A><BR>\n<A HREF=\"manual.html#lua_Writer\">lua_Writer</A><BR>\n<P>\n\n<A HREF=\"manual.html#lua_atpanic\">lua_atpanic</A><BR>\n<A HREF=\"manual.html#lua_call\">lua_call</A><BR>\n<A HREF=\"manual.html#lua_checkstack\">lua_checkstack</A><BR>\n<A HREF=\"manual.html#lua_close\">lua_close</A><BR>\n<A HREF=\"manual.html#lua_concat\">lua_concat</A><BR>\n<A HREF=\"manual.html#lua_cpcall\">lua_cpcall</A><BR>\n<A HREF=\"manual.html#lua_createtable\">lua_createtable</A><BR>\n<A HREF=\"manual.html#lua_dump\">lua_dump</A><BR>\n<A HREF=\"manual.html#lua_equal\">lua_equal</A><BR>\n<A HREF=\"manual.html#lua_error\">lua_error</A><BR>\n<A HREF=\"manual.html#lua_gc\">lua_gc</A><BR>\n<A HREF=\"manual.html#lua_getallocf\">lua_getallocf</A><BR>\n<A HREF=\"manual.html#lua_getfenv\">lua_getfenv</A><BR>\n<A HREF=\"manual.html#lua_getfield\">lua_getfield</A><BR>\n<A HREF=\"manual.html#lua_getglobal\">lua_getglobal</A><BR>\n<A HREF=\"manual.html#lua_gethook\">lua_gethook</A><BR>\n<A HREF=\"manual.html#lua_gethookcount\">lua_gethookcount</A><BR>\n<A HREF=\"manual.html#lua_gethookmask\">lua_gethookmask</A><BR>\n<A HREF=\"manual.html#lua_getinfo\">lua_getinfo</A><BR>\n<A HREF=\"manual.html#lua_getlocal\">lua_getlocal</A><BR>\n<A HREF=\"manual.html#lua_getmetatable\">lua_getmetatable</A><BR>\n<A HREF=\"manual.html#lua_getstack\">lua_getstack</A><BR>\n<A HREF=\"manual.html#lua_gettable\">lua_gettable</A><BR>\n<A HREF=\"manual.html#lua_gettop\">lua_gettop</A><BR>\n<A HREF=\"manual.html#lua_getupvalue\">lua_getupvalue</A><BR>\n<A HREF=\"manual.html#lua_insert\">lua_insert</A><BR>\n<A HREF=\"manual.html#lua_isboolean\">lua_isboolean</A><BR>\n<A HREF=\"manual.html#lua_iscfunction\">lua_iscfunction</A><BR>\n<A HREF=\"manual.html#lua_isfunction\">lua_isfunction</A><BR>\n<A HREF=\"manual.html#lua_islightuserdata\">lua_islightuserdata</A><BR>\n<A HREF=\"manual.html#lua_isnil\">lua_isnil</A><BR>\n<A HREF=\"manual.html#lua_isnone\">lua_isnone</A><BR>\n<A HREF=\"manual.html#lua_isnoneornil\">lua_isnoneornil</A><BR>\n<A HREF=\"manual.html#lua_isnumber\">lua_isnumber</A><BR>\n<A HREF=\"manual.html#lua_isstring\">lua_isstring</A><BR>\n<A HREF=\"manual.html#lua_istable\">lua_istable</A><BR>\n<A HREF=\"manual.html#lua_isthread\">lua_isthread</A><BR>\n<A HREF=\"manual.html#lua_isuserdata\">lua_isuserdata</A><BR>\n<A HREF=\"manual.html#lua_lessthan\">lua_lessthan</A><BR>\n<A HREF=\"manual.html#lua_load\">lua_load</A><BR>\n<A HREF=\"manual.html#lua_newstate\">lua_newstate</A><BR>\n<A HREF=\"manual.html#lua_newtable\">lua_newtable</A><BR>\n<A HREF=\"manual.html#lua_newthread\">lua_newthread</A><BR>\n<A HREF=\"manual.html#lua_newuserdata\">lua_newuserdata</A><BR>\n<A HREF=\"manual.html#lua_next\">lua_next</A><BR>\n<A HREF=\"manual.html#lua_objlen\">lua_objlen</A><BR>\n<A HREF=\"manual.html#lua_pcall\">lua_pcall</A><BR>\n<A HREF=\"manual.html#lua_pop\">lua_pop</A><BR>\n<A HREF=\"manual.html#lua_pushboolean\">lua_pushboolean</A><BR>\n<A HREF=\"manual.html#lua_pushcclosure\">lua_pushcclosure</A><BR>\n<A HREF=\"manual.html#lua_pushcfunction\">lua_pushcfunction</A><BR>\n<A HREF=\"manual.html#lua_pushfstring\">lua_pushfstring</A><BR>\n<A HREF=\"manual.html#lua_pushinteger\">lua_pushinteger</A><BR>\n<A HREF=\"manual.html#lua_pushlightuserdata\">lua_pushlightuserdata</A><BR>\n<A HREF=\"manual.html#lua_pushliteral\">lua_pushliteral</A><BR>\n<A HREF=\"manual.html#lua_pushlstring\">lua_pushlstring</A><BR>\n<A HREF=\"manual.html#lua_pushnil\">lua_pushnil</A><BR>\n<A HREF=\"manual.html#lua_pushnumber\">lua_pushnumber</A><BR>\n<A HREF=\"manual.html#lua_pushstring\">lua_pushstring</A><BR>\n<A HREF=\"manual.html#lua_pushthread\">lua_pushthread</A><BR>\n<A HREF=\"manual.html#lua_pushvalue\">lua_pushvalue</A><BR>\n<A HREF=\"manual.html#lua_pushvfstring\">lua_pushvfstring</A><BR>\n<A HREF=\"manual.html#lua_rawequal\">lua_rawequal</A><BR>\n<A HREF=\"manual.html#lua_rawget\">lua_rawget</A><BR>\n<A HREF=\"manual.html#lua_rawgeti\">lua_rawgeti</A><BR>\n<A HREF=\"manual.html#lua_rawset\">lua_rawset</A><BR>\n<A HREF=\"manual.html#lua_rawseti\">lua_rawseti</A><BR>\n<A HREF=\"manual.html#lua_register\">lua_register</A><BR>\n<A HREF=\"manual.html#lua_remove\">lua_remove</A><BR>\n<A HREF=\"manual.html#lua_replace\">lua_replace</A><BR>\n<A HREF=\"manual.html#lua_resume\">lua_resume</A><BR>\n<A HREF=\"manual.html#lua_setallocf\">lua_setallocf</A><BR>\n<A HREF=\"manual.html#lua_setfenv\">lua_setfenv</A><BR>\n<A HREF=\"manual.html#lua_setfield\">lua_setfield</A><BR>\n<A HREF=\"manual.html#lua_setglobal\">lua_setglobal</A><BR>\n<A HREF=\"manual.html#lua_sethook\">lua_sethook</A><BR>\n<A HREF=\"manual.html#lua_setlocal\">lua_setlocal</A><BR>\n<A HREF=\"manual.html#lua_setmetatable\">lua_setmetatable</A><BR>\n<A HREF=\"manual.html#lua_settable\">lua_settable</A><BR>\n<A HREF=\"manual.html#lua_settop\">lua_settop</A><BR>\n<A HREF=\"manual.html#lua_setupvalue\">lua_setupvalue</A><BR>\n<A HREF=\"manual.html#lua_status\">lua_status</A><BR>\n<A HREF=\"manual.html#lua_toboolean\">lua_toboolean</A><BR>\n<A HREF=\"manual.html#lua_tocfunction\">lua_tocfunction</A><BR>\n<A HREF=\"manual.html#lua_tointeger\">lua_tointeger</A><BR>\n<A HREF=\"manual.html#lua_tolstring\">lua_tolstring</A><BR>\n<A HREF=\"manual.html#lua_tonumber\">lua_tonumber</A><BR>\n<A HREF=\"manual.html#lua_topointer\">lua_topointer</A><BR>\n<A HREF=\"manual.html#lua_tostring\">lua_tostring</A><BR>\n<A HREF=\"manual.html#lua_tothread\">lua_tothread</A><BR>\n<A HREF=\"manual.html#lua_touserdata\">lua_touserdata</A><BR>\n<A HREF=\"manual.html#lua_type\">lua_type</A><BR>\n<A HREF=\"manual.html#lua_typename\">lua_typename</A><BR>\n<A HREF=\"manual.html#lua_upvalueindex\">lua_upvalueindex</A><BR>\n<A HREF=\"manual.html#lua_xmove\">lua_xmove</A><BR>\n<A HREF=\"manual.html#lua_yield\">lua_yield</A><BR>\n\n</TD>\n<TD>\n<H3>auxiliary library</H3>\n<A HREF=\"manual.html#luaL_Buffer\">luaL_Buffer</A><BR>\n<A HREF=\"manual.html#luaL_Reg\">luaL_Reg</A><BR>\n<P>\n\n<A HREF=\"manual.html#luaL_addchar\">luaL_addchar</A><BR>\n<A HREF=\"manual.html#luaL_addlstring\">luaL_addlstring</A><BR>\n<A HREF=\"manual.html#luaL_addsize\">luaL_addsize</A><BR>\n<A HREF=\"manual.html#luaL_addstring\">luaL_addstring</A><BR>\n<A HREF=\"manual.html#luaL_addvalue\">luaL_addvalue</A><BR>\n<A HREF=\"manual.html#luaL_argcheck\">luaL_argcheck</A><BR>\n<A HREF=\"manual.html#luaL_argerror\">luaL_argerror</A><BR>\n<A HREF=\"manual.html#luaL_buffinit\">luaL_buffinit</A><BR>\n<A HREF=\"manual.html#luaL_callmeta\">luaL_callmeta</A><BR>\n<A HREF=\"manual.html#luaL_checkany\">luaL_checkany</A><BR>\n<A HREF=\"manual.html#luaL_checkint\">luaL_checkint</A><BR>\n<A HREF=\"manual.html#luaL_checkinteger\">luaL_checkinteger</A><BR>\n<A HREF=\"manual.html#luaL_checklong\">luaL_checklong</A><BR>\n<A HREF=\"manual.html#luaL_checklstring\">luaL_checklstring</A><BR>\n<A HREF=\"manual.html#luaL_checknumber\">luaL_checknumber</A><BR>\n<A HREF=\"manual.html#luaL_checkoption\">luaL_checkoption</A><BR>\n<A HREF=\"manual.html#luaL_checkstack\">luaL_checkstack</A><BR>\n<A HREF=\"manual.html#luaL_checkstring\">luaL_checkstring</A><BR>\n<A HREF=\"manual.html#luaL_checktype\">luaL_checktype</A><BR>\n<A HREF=\"manual.html#luaL_checkudata\">luaL_checkudata</A><BR>\n<A HREF=\"manual.html#luaL_dofile\">luaL_dofile</A><BR>\n<A HREF=\"manual.html#luaL_dostring\">luaL_dostring</A><BR>\n<A HREF=\"manual.html#luaL_error\">luaL_error</A><BR>\n<A HREF=\"manual.html#luaL_getmetafield\">luaL_getmetafield</A><BR>\n<A HREF=\"manual.html#luaL_getmetatable\">luaL_getmetatable</A><BR>\n<A HREF=\"manual.html#luaL_gsub\">luaL_gsub</A><BR>\n<A HREF=\"manual.html#luaL_loadbuffer\">luaL_loadbuffer</A><BR>\n<A HREF=\"manual.html#luaL_loadfile\">luaL_loadfile</A><BR>\n<A HREF=\"manual.html#luaL_loadstring\">luaL_loadstring</A><BR>\n<A HREF=\"manual.html#luaL_newmetatable\">luaL_newmetatable</A><BR>\n<A HREF=\"manual.html#luaL_newstate\">luaL_newstate</A><BR>\n<A HREF=\"manual.html#luaL_openlibs\">luaL_openlibs</A><BR>\n<A HREF=\"manual.html#luaL_optint\">luaL_optint</A><BR>\n<A HREF=\"manual.html#luaL_optinteger\">luaL_optinteger</A><BR>\n<A HREF=\"manual.html#luaL_optlong\">luaL_optlong</A><BR>\n<A HREF=\"manual.html#luaL_optlstring\">luaL_optlstring</A><BR>\n<A HREF=\"manual.html#luaL_optnumber\">luaL_optnumber</A><BR>\n<A HREF=\"manual.html#luaL_optstring\">luaL_optstring</A><BR>\n<A HREF=\"manual.html#luaL_prepbuffer\">luaL_prepbuffer</A><BR>\n<A HREF=\"manual.html#luaL_pushresult\">luaL_pushresult</A><BR>\n<A HREF=\"manual.html#luaL_ref\">luaL_ref</A><BR>\n<A HREF=\"manual.html#luaL_register\">luaL_register</A><BR>\n<A HREF=\"manual.html#luaL_typename\">luaL_typename</A><BR>\n<A HREF=\"manual.html#luaL_typerror\">luaL_typerror</A><BR>\n<A HREF=\"manual.html#luaL_unref\">luaL_unref</A><BR>\n<A HREF=\"manual.html#luaL_where\">luaL_where</A><BR>\n\n</TD>\n</TR>\n</TABLE>\n<P>\n\n<HR>\n<SMALL CLASS=\"footer\">\nLast update:\nMon Feb 13 18:53:32 BRST 2012\n</SMALL>\n<!--\nLast change: revised for Lua 5.1.5\n-->\n\n</BODY>\n</HTML>\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.8/deps/lua/doc/lua.1",
    "content": ".\\\" $Id: lua.man,v 1.11 2006/01/06 16:03:34 lhf Exp $\n.TH LUA 1 \"$Date: 2006/01/06 16:03:34 $\"\n.SH NAME\nlua \\- Lua interpreter\n.SH SYNOPSIS\n.B lua\n[\n.I options\n]\n[\n.I script\n[\n.I args\n]\n]\n.SH DESCRIPTION\n.B lua\nis the stand-alone Lua interpreter.\nIt loads and executes Lua programs,\neither in textual source form or\nin precompiled binary form.\n(Precompiled binaries are output by\n.BR luac ,\nthe Lua compiler.)\n.B lua\ncan be used as a batch interpreter and also interactively.\n.LP\nThe given\n.I options\n(see below)\nare executed and then\nthe Lua program in file\n.I script\nis loaded and executed.\nThe given\n.I args\nare available to\n.I script\nas strings in a global table named\n.BR arg .\nIf these arguments contain spaces or other characters special to the shell,\nthen they should be quoted\n(but note that the quotes will be removed by the shell).\nThe arguments in\n.B arg\nstart at 0,\nwhich contains the string\n.RI ' script '.\nThe index of the last argument is stored in\n.BR arg.n .\nThe arguments given in the command line before\n.IR script ,\nincluding the name of the interpreter,\nare available in negative indices in\n.BR arg .\n.LP\nAt the very start,\nbefore even handling the command line,\n.B lua\nexecutes the contents of the environment variable\n.BR LUA_INIT ,\nif it is defined.\nIf the value of\n.B LUA_INIT\nis of the form\n.RI '@ filename ',\nthen\n.I filename\nis executed.\nOtherwise, the string is assumed to be a Lua statement and is executed.\n.LP\nOptions start with\n.B '\\-'\nand are described below.\nYou can use\n.B \"'\\--'\"\nto signal the end of options.\n.LP\nIf no arguments are given,\nthen\n.B \"\\-v \\-i\"\nis assumed when the standard input is a terminal;\notherwise,\n.B \"\\-\"\nis assumed.\n.LP\nIn interactive mode,\n.B lua\nprompts the user,\nreads lines from the standard input,\nand executes them as they are read.\nIf a line does not contain a complete statement,\nthen a secondary prompt is displayed and\nlines are read until a complete statement is formed or\na syntax error is found.\nSo, one way to interrupt the reading of an incomplete statement is\nto force a syntax error:\nadding a\n.B ';' \nin the middle of a statement is a sure way of forcing a syntax error\n(except inside multiline strings and comments; these must be closed explicitly).\nIf a line starts with\n.BR '=' ,\nthen\n.B lua\ndisplays the values of all the expressions in the remainder of the\nline. The expressions must be separated by commas.\nThe primary prompt is the value of the global variable\n.BR _PROMPT ,\nif this value is a string;\notherwise, the default prompt is used.\nSimilarly, the secondary prompt is the value of the global variable\n.BR _PROMPT2 .\nSo,\nto change the prompts,\nset the corresponding variable to a string of your choice.\nYou can do that after calling the interpreter\nor on the command line\n(but in this case you have to be careful with quotes\nif the prompt string contains a space; otherwise you may confuse the shell.)\nThe default prompts are \"> \" and \">> \".\n.SH OPTIONS\n.TP\n.B \\-\nload and execute the standard input as a file,\nthat is,\nnot interactively,\neven when the standard input is a terminal.\n.TP\n.BI \\-e \" stat\"\nexecute statement\n.IR stat .\nYou need to quote\n.I stat \nif it contains spaces, quotes,\nor other characters special to the shell.\n.TP\n.B \\-i\nenter interactive mode after\n.I script\nis executed.\n.TP\n.BI \\-l \" name\"\ncall\n.BI require(' name ')\nbefore executing\n.IR script .\nTypically used to load libraries.\n.TP\n.B \\-v\nshow version information.\n.SH \"SEE ALSO\"\n.BR luac (1)\n.br\nhttp://www.lua.org/\n.SH DIAGNOSTICS\nError messages should be self explanatory.\n.SH AUTHORS\nR. Ierusalimschy,\nL. H. de Figueiredo,\nand\nW. Celes\n.\\\" EOF\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.8/deps/lua/doc/lua.css",
    "content": "body {\n\tcolor: #000000 ;\n\tbackground-color: #FFFFFF ;\n\tfont-family: Helvetica, Arial, sans-serif ;\n\ttext-align: justify ;\n\tmargin-right: 30px ;\n\tmargin-left: 30px ;\n}\n\nh1, h2, h3, h4 {\n\tfont-family: Verdana, Geneva, sans-serif ;\n\tfont-weight: normal ;\n\tfont-style: italic ;\n}\n\nh2 {\n\tpadding-top: 0.4em ;\n\tpadding-bottom: 0.4em ;\n\tpadding-left: 30px ;\n\tpadding-right: 30px ;\n\tmargin-left: -30px ;\n\tbackground-color: #E0E0FF ;\n}\n\nh3 {\n\tpadding-left: 0.5em ;\n\tborder-left: solid #E0E0FF 1em ;\n}\n\ntable h3 {\n\tpadding-left: 0px ;\n\tborder-left: none ;\n}\n\na:link {\n\tcolor: #000080 ;\n\tbackground-color: inherit ;\n\ttext-decoration: none ;\n}\n\na:visited {\n\tbackground-color: inherit ;\n\ttext-decoration: none ;\n}\n\na:link:hover, a:visited:hover {\n\tcolor: #000080 ;\n\tbackground-color: #E0E0FF ;\n}\n\na:link:active, a:visited:active {\n\tcolor: #FF0000 ;\n}\n\nhr {\n\tborder: 0 ;\n\theight: 1px ;\n\tcolor: #a0a0a0 ;\n\tbackground-color: #a0a0a0 ;\n}\n\n:target {\n\tbackground-color: #F8F8F8 ;\n\tpadding: 8px ;\n\tborder: solid #a0a0a0 2px ;\n}\n\n.footer {\n\tcolor: gray ;\n\tfont-size: small ;\n}\n\ninput[type=text] {\n\tborder: solid #a0a0a0 2px ;\n\tborder-radius: 2em ;\n\t-moz-border-radius: 2em ;\n\tbackground-image: url('images/search.png') ;\n\tbackground-repeat: no-repeat;\n\tbackground-position: 4px center ;\n\tpadding-left: 20px ;\n\theight: 2em ;\n}\n\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.8/deps/lua/doc/lua.html",
    "content": "<!-- $Id: lua.man,v 1.11 2006/01/06 16:03:34 lhf Exp $ -->\n<HTML>\n<HEAD>\n<TITLE>LUA man page</TITLE>\n<LINK REL=\"stylesheet\" TYPE=\"text/css\" HREF=\"lua.css\">\n</HEAD>\n\n<BODY BGCOLOR=\"#FFFFFF\">\n\n<H2>NAME</H2>\nlua - Lua interpreter\n<H2>SYNOPSIS</H2>\n<B>lua</B>\n[\n<I>options</I>\n]\n[\n<I>script</I>\n[\n<I>args</I>\n]\n]\n<H2>DESCRIPTION</H2>\n<B>lua</B>\nis the stand-alone Lua interpreter.\nIt loads and executes Lua programs,\neither in textual source form or\nin precompiled binary form.\n(Precompiled binaries are output by\n<B>luac</B>,\nthe Lua compiler.)\n<B>lua</B>\ncan be used as a batch interpreter and also interactively.\n<P>\nThe given\n<I>options</I>\n(see below)\nare executed and then\nthe Lua program in file\n<I>script</I>\nis loaded and executed.\nThe given\n<I>args</I>\nare available to\n<I>script</I>\nas strings in a global table named\n<B>arg</B>.\nIf these arguments contain spaces or other characters special to the shell,\nthen they should be quoted\n(but note that the quotes will be removed by the shell).\nThe arguments in\n<B>arg</B>\nstart at 0,\nwhich contains the string\n'<I>script</I>'.\nThe index of the last argument is stored in\n<B>arg.n</B>.\nThe arguments given in the command line before\n<I>script</I>,\nincluding the name of the interpreter,\nare available in negative indices in\n<B>arg</B>.\n<P>\nAt the very start,\nbefore even handling the command line,\n<B>lua</B>\nexecutes the contents of the environment variable\n<B>LUA_INIT</B>,\nif it is defined.\nIf the value of\n<B>LUA_INIT</B>\nis of the form\n'@<I>filename</I>',\nthen\n<I>filename</I>\nis executed.\nOtherwise, the string is assumed to be a Lua statement and is executed.\n<P>\nOptions start with\n<B>'-'</B>\nand are described below.\nYou can use\n<B>'--'</B>\nto signal the end of options.\n<P>\nIf no arguments are given,\nthen\n<B>\"-v -i\"</B>\nis assumed when the standard input is a terminal;\notherwise,\n<B>\"-\"</B>\nis assumed.\n<P>\nIn interactive mode,\n<B>lua</B>\nprompts the user,\nreads lines from the standard input,\nand executes them as they are read.\nIf a line does not contain a complete statement,\nthen a secondary prompt is displayed and\nlines are read until a complete statement is formed or\na syntax error is found.\nSo, one way to interrupt the reading of an incomplete statement is\nto force a syntax error:\nadding a\n<B>';'</B>\nin the middle of a statement is a sure way of forcing a syntax error\n(except inside multiline strings and comments; these must be closed explicitly).\nIf a line starts with\n<B>'='</B>,\nthen\n<B>lua</B>\ndisplays the values of all the expressions in the remainder of the\nline. The expressions must be separated by commas.\nThe primary prompt is the value of the global variable\n<B>_PROMPT</B>,\nif this value is a string;\notherwise, the default prompt is used.\nSimilarly, the secondary prompt is the value of the global variable\n<B>_PROMPT2</B>.\nSo,\nto change the prompts,\nset the corresponding variable to a string of your choice.\nYou can do that after calling the interpreter\nor on the command line\n(but in this case you have to be careful with quotes\nif the prompt string contains a space; otherwise you may confuse the shell.)\nThe default prompts are \"&gt; \" and \"&gt;&gt; \".\n<H2>OPTIONS</H2>\n<P>\n<B>-</B>\nload and execute the standard input as a file,\nthat is,\nnot interactively,\neven when the standard input is a terminal.\n<P>\n<B>-e </B><I>stat</I>\nexecute statement\n<I>stat</I>.\nYou need to quote\n<I>stat </I>\nif it contains spaces, quotes,\nor other characters special to the shell.\n<P>\n<B>-i</B>\nenter interactive mode after\n<I>script</I>\nis executed.\n<P>\n<B>-l </B><I>name</I>\ncall\n<B>require</B>('<I>name</I>')\nbefore executing\n<I>script</I>.\nTypically used to load libraries.\n<P>\n<B>-v</B>\nshow version information.\n<H2>SEE ALSO</H2>\n<B>luac</B>(1)\n<BR>\n<A HREF=\"http://www.lua.org/\">http://www.lua.org/</A>\n<H2>DIAGNOSTICS</H2>\nError messages should be self explanatory.\n<H2>AUTHORS</H2>\nR. Ierusalimschy,\nL. H. de Figueiredo,\nand\nW. Celes\n<!-- EOF -->\n</BODY>\n</HTML>\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.8/deps/lua/doc/luac.1",
    "content": ".\\\" $Id: luac.man,v 1.28 2006/01/06 16:03:34 lhf Exp $\n.TH LUAC 1 \"$Date: 2006/01/06 16:03:34 $\"\n.SH NAME\nluac \\- Lua compiler\n.SH SYNOPSIS\n.B luac\n[\n.I options\n] [\n.I filenames\n]\n.SH DESCRIPTION\n.B luac\nis the Lua compiler.\nIt translates programs written in the Lua programming language\ninto binary files that can be later loaded and executed.\n.LP\nThe main advantages of precompiling chunks are:\nfaster loading,\nprotecting source code from accidental user changes,\nand\noff-line syntax checking.\n.LP\nPre-compiling does not imply faster execution\nbecause in Lua chunks are always compiled into bytecodes before being executed.\n.B luac\nsimply allows those bytecodes to be saved in a file for later execution.\n.LP\nPre-compiled chunks are not necessarily smaller than the corresponding source.\nThe main goal in pre-compiling is faster loading.\n.LP\nThe binary files created by\n.B luac\nare portable only among architectures with the same word size and byte order.\n.LP\n.B luac\nproduces a single output file containing the bytecodes\nfor all source files given.\nBy default,\nthe output file is named\n.BR luac.out ,\nbut you can change this with the\n.B \\-o\noption.\n.LP\nIn the command line,\nyou can mix\ntext files containing Lua source and\nbinary files containing precompiled chunks.\nThis is useful to combine several precompiled chunks,\neven from different (but compatible) platforms,\ninto a single precompiled chunk.\n.LP\nYou can use\n.B \"'\\-'\"\nto indicate the standard input as a source file\nand\n.B \"'\\--'\"\nto signal the end of options\n(that is,\nall remaining arguments will be treated as files even if they start with\n.BR \"'\\-'\" ).\n.LP\nThe internal format of the binary files produced by\n.B luac\nis likely to change when a new version of Lua is released.\nSo,\nsave the source files of all Lua programs that you precompile.\n.LP\n.SH OPTIONS\nOptions must be separate.\n.TP\n.B \\-l\nproduce a listing of the compiled bytecode for Lua's virtual machine.\nListing bytecodes is useful to learn about Lua's virtual machine.\nIf no files are given, then\n.B luac\nloads\n.B luac.out\nand lists its contents.\n.TP\n.BI \\-o \" file\"\noutput to\n.IR file ,\ninstead of the default\n.BR luac.out .\n(You can use\n.B \"'\\-'\"\nfor standard output,\nbut not on platforms that open standard output in text mode.)\nThe output file may be a source file because\nall files are loaded before the output file is written.\nBe careful not to overwrite precious files.\n.TP\n.B \\-p\nload files but do not generate any output file.\nUsed mainly for syntax checking and for testing precompiled chunks:\ncorrupted files will probably generate errors when loaded.\nLua always performs a thorough integrity test on precompiled chunks.\nBytecode that passes this test is completely safe,\nin the sense that it will not break the interpreter.\nHowever,\nthere is no guarantee that such code does anything sensible.\n(None can be given, because the halting problem is unsolvable.)\nIf no files are given, then\n.B luac\nloads\n.B luac.out\nand tests its contents.\nNo messages are displayed if the file passes the integrity test.\n.TP\n.B \\-s\nstrip debug information before writing the output file.\nThis saves some space in very large chunks,\nbut if errors occur when running a stripped chunk,\nthen the error messages may not contain the full information they usually do.\nFor instance,\nline numbers and names of local variables are lost.\n.TP\n.B \\-v\nshow version information.\n.SH FILES\n.TP 15\n.B luac.out\ndefault output file\n.SH \"SEE ALSO\"\n.BR lua (1)\n.br\nhttp://www.lua.org/\n.SH DIAGNOSTICS\nError messages should be self explanatory.\n.SH AUTHORS\nL. H. de Figueiredo,\nR. Ierusalimschy and\nW. Celes\n.\\\" EOF\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.8/deps/lua/doc/luac.html",
    "content": "<!-- $Id: luac.man,v 1.28 2006/01/06 16:03:34 lhf Exp $ -->\n<HTML>\n<HEAD>\n<TITLE>LUAC man page</TITLE>\n<LINK REL=\"stylesheet\" TYPE=\"text/css\" HREF=\"lua.css\">\n</HEAD>\n\n<BODY BGCOLOR=\"#FFFFFF\">\n\n<H2>NAME</H2>\nluac - Lua compiler\n<H2>SYNOPSIS</H2>\n<B>luac</B>\n[\n<I>options</I>\n] [\n<I>filenames</I>\n]\n<H2>DESCRIPTION</H2>\n<B>luac</B>\nis the Lua compiler.\nIt translates programs written in the Lua programming language\ninto binary files that can be later loaded and executed.\n<P>\nThe main advantages of precompiling chunks are:\nfaster loading,\nprotecting source code from accidental user changes,\nand\noff-line syntax checking.\n<P>\nPrecompiling does not imply faster execution\nbecause in Lua chunks are always compiled into bytecodes before being executed.\n<B>luac</B>\nsimply allows those bytecodes to be saved in a file for later execution.\n<P>\nPrecompiled chunks are not necessarily smaller than the corresponding source.\nThe main goal in precompiling is faster loading.\n<P>\nThe binary files created by\n<B>luac</B>\nare portable only among architectures with the same word size and byte order.\n<P>\n<B>luac</B>\nproduces a single output file containing the bytecodes\nfor all source files given.\nBy default,\nthe output file is named\n<B>luac.out</B>,\nbut you can change this with the\n<B>-o</B>\noption.\n<P>\nIn the command line,\nyou can mix\ntext files containing Lua source and\nbinary files containing precompiled chunks.\nThis is useful because several precompiled chunks,\neven from different (but compatible) platforms,\ncan be combined into a single precompiled chunk.\n<P>\nYou can use\n<B>'-'</B>\nto indicate the standard input as a source file\nand\n<B>'--'</B>\nto signal the end of options\n(that is,\nall remaining arguments will be treated as files even if they start with\n<B>'-'</B>).\n<P>\nThe internal format of the binary files produced by\n<B>luac</B>\nis likely to change when a new version of Lua is released.\nSo,\nsave the source files of all Lua programs that you precompile.\n<P>\n<H2>OPTIONS</H2>\nOptions must be separate.\n<P>\n<B>-l</B>\nproduce a listing of the compiled bytecode for Lua's virtual machine.\nListing bytecodes is useful to learn about Lua's virtual machine.\nIf no files are given, then\n<B>luac</B>\nloads\n<B>luac.out</B>\nand lists its contents.\n<P>\n<B>-o </B><I>file</I>\noutput to\n<I>file</I>,\ninstead of the default\n<B>luac.out</B>.\n(You can use\n<B>'-'</B>\nfor standard output,\nbut not on platforms that open standard output in text mode.)\nThe output file may be a source file because\nall files are loaded before the output file is written.\nBe careful not to overwrite precious files.\n<P>\n<B>-p</B>\nload files but do not generate any output file.\nUsed mainly for syntax checking and for testing precompiled chunks:\ncorrupted files will probably generate errors when loaded.\nLua always performs a thorough integrity test on precompiled chunks.\nBytecode that passes this test is completely safe,\nin the sense that it will not break the interpreter.\nHowever,\nthere is no guarantee that such code does anything sensible.\n(None can be given, because the halting problem is unsolvable.)\nIf no files are given, then\n<B>luac</B>\nloads\n<B>luac.out</B>\nand tests its contents.\nNo messages are displayed if the file passes the integrity test.\n<P>\n<B>-s</B>\nstrip debug information before writing the output file.\nThis saves some space in very large chunks,\nbut if errors occur when running a stripped chunk,\nthen the error messages may not contain the full information they usually do.\nFor instance,\nline numbers and names of local variables are lost.\n<P>\n<B>-v</B>\nshow version information.\n<H2>FILES</H2>\n<P>\n<B>luac.out</B>\ndefault output file\n<H2>SEE ALSO</H2>\n<B>lua</B>(1)\n<BR>\n<A HREF=\"http://www.lua.org/\">http://www.lua.org/</A>\n<H2>DIAGNOSTICS</H2>\nError messages should be self explanatory.\n<H2>AUTHORS</H2>\nL. H. de Figueiredo,\nR. Ierusalimschy and\nW. Celes\n<!-- EOF -->\n</BODY>\n</HTML>\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.8/deps/lua/doc/manual.css",
    "content": "h3 code {\n\tfont-family: inherit ;\n\tfont-size: inherit ;\n}\n\npre, code {\n\tfont-size: 12pt ;\n}\n\nspan.apii {\n\tfloat: right ;\n\tfont-family: inherit ;\n\tfont-style: normal ;\n\tfont-size: small ;\n\tcolor: gray ;\n}\n\np+h1, ul+h1 {\n\tpadding-top: 0.4em ;\n\tpadding-bottom: 0.4em ;\n\tpadding-left: 30px ;\n\tmargin-left: -30px ;\n\tbackground-color: #E0E0FF ;\n}\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.8/deps/lua/doc/manual.html",
    "content": "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\">\n<html>\n\n<head>\n<title>Lua 5.1 Reference Manual</title>\n<link rel=\"stylesheet\" type=\"text/css\" href=\"lua.css\">\n<link rel=\"stylesheet\" type=\"text/css\" href=\"manual.css\">\n<META HTTP-EQUIV=\"content-type\" CONTENT=\"text/html; charset=iso-8859-1\">\n</head>\n\n<body>\n\n<hr>\n<h1>\n<a href=\"http://www.lua.org/\"><img src=\"logo.gif\" alt=\"\" border=\"0\"></a>\nLua 5.1 Reference Manual\n</h1>\n\nby Roberto Ierusalimschy, Luiz Henrique de Figueiredo, Waldemar Celes\n<p>\n<small>\nCopyright &copy; 2006&ndash;2012 Lua.org, PUC-Rio.\nFreely available under the terms of the\n<a href=\"http://www.lua.org/license.html\">Lua license</a>.\n</small>\n<hr>\n<p>\n\n<a href=\"contents.html#contents\">contents</A>\n&middot;\n<a href=\"contents.html#index\">index</A>\n&middot;\n<A HREF=\"http://www.lua.org/manual/\">other versions</A>\n\n<!-- ====================================================================== -->\n<p>\n\n<!-- $Id: manual.of,v 1.49.1.2 2012/01/13 20:23:26 roberto Exp $ -->\n\n\n\n\n<h1>1 - <a name=\"1\">Introduction</a></h1>\n\n<p>\nLua is an extension programming language designed to support\ngeneral procedural programming with data description\nfacilities.\nIt also offers good support for object-oriented programming,\nfunctional programming, and data-driven programming.\nLua is intended to be used as a powerful, light-weight\nscripting language for any program that needs one.\nLua is implemented as a library, written in <em>clean</em> C\n(that is, in the common subset of ANSI&nbsp;C and C++).\n\n\n<p>\nBeing an extension language, Lua has no notion of a \"main\" program:\nit only works <em>embedded</em> in a host client,\ncalled the <em>embedding program</em> or simply the <em>host</em>.\nThis host program can invoke functions to execute a piece of Lua code,\ncan write and read Lua variables,\nand can register C&nbsp;functions to be called by Lua code.\nThrough the use of C&nbsp;functions, Lua can be augmented to cope with\na wide range of different domains,\nthus creating customized programming languages sharing a syntactical framework.\nThe Lua distribution includes a sample host program called <code>lua</code>,\nwhich uses the Lua library to offer a complete, stand-alone Lua interpreter.\n\n\n<p>\nLua is free software,\nand is provided as usual with no guarantees,\nas stated in its license.\nThe implementation described in this manual is available\nat Lua's official web site, <code>www.lua.org</code>.\n\n\n<p>\nLike any other reference manual,\nthis document is dry in places.\nFor a discussion of the decisions behind the design of Lua,\nsee the technical papers available at Lua's web site.\nFor a detailed introduction to programming in Lua,\nsee Roberto's book, <em>Programming in Lua (Second Edition)</em>.\n\n\n\n<h1>2 - <a name=\"2\">The Language</a></h1>\n\n<p>\nThis section describes the lexis, the syntax, and the semantics of Lua.\nIn other words,\nthis section describes\nwhich tokens are valid,\nhow they can be combined,\nand what their combinations mean.\n\n\n<p>\nThe language constructs will be explained using the usual extended BNF notation,\nin which\n{<em>a</em>}&nbsp;means&nbsp;0 or more <em>a</em>'s, and\n[<em>a</em>]&nbsp;means an optional <em>a</em>.\nNon-terminals are shown like non-terminal,\nkeywords are shown like <b>kword</b>,\nand other terminal symbols are shown like `<b>=</b>&acute;.\nThe complete syntax of Lua can be found in <a href=\"#8\">&sect;8</a>\nat the end of this manual.\n\n\n\n<h2>2.1 - <a name=\"2.1\">Lexical Conventions</a></h2>\n\n<p>\n<em>Names</em>\n(also called <em>identifiers</em>)\nin Lua can be any string of letters,\ndigits, and underscores,\nnot beginning with a digit.\nThis coincides with the definition of names in most languages.\n(The definition of letter depends on the current locale:\nany character considered alphabetic by the current locale\ncan be used in an identifier.)\nIdentifiers are used to name variables and table fields.\n\n\n<p>\nThe following <em>keywords</em> are reserved\nand cannot be used as names:\n\n\n<pre>\n     and       break     do        else      elseif\n     end       false     for       function  if\n     in        local     nil       not       or\n     repeat    return    then      true      until     while\n</pre>\n\n<p>\nLua is a case-sensitive language:\n<code>and</code> is a reserved word, but <code>And</code> and <code>AND</code>\nare two different, valid names.\nAs a convention, names starting with an underscore followed by\nuppercase letters (such as <a href=\"#pdf-_VERSION\"><code>_VERSION</code></a>)\nare reserved for internal global variables used by Lua.\n\n\n<p>\nThe following strings denote other tokens:\n\n<pre>\n     +     -     *     /     %     ^     #\n     ==    ~=    &lt;=    &gt;=    &lt;     &gt;     =\n     (     )     {     }     [     ]\n     ;     :     ,     .     ..    ...\n</pre>\n\n<p>\n<em>Literal strings</em>\ncan be delimited by matching single or double quotes,\nand can contain the following C-like escape sequences:\n'<code>\\a</code>' (bell),\n'<code>\\b</code>' (backspace),\n'<code>\\f</code>' (form feed),\n'<code>\\n</code>' (newline),\n'<code>\\r</code>' (carriage return),\n'<code>\\t</code>' (horizontal tab),\n'<code>\\v</code>' (vertical tab),\n'<code>\\\\</code>' (backslash),\n'<code>\\\"</code>' (quotation mark [double quote]),\nand '<code>\\'</code>' (apostrophe [single quote]).\nMoreover, a backslash followed by a real newline\nresults in a newline in the string.\nA character in a string can also be specified by its numerical value\nusing the escape sequence <code>\\<em>ddd</em></code>,\nwhere <em>ddd</em> is a sequence of up to three decimal digits.\n(Note that if a numerical escape is to be followed by a digit,\nit must be expressed using exactly three digits.)\nStrings in Lua can contain any 8-bit value, including embedded zeros,\nwhich can be specified as '<code>\\0</code>'.\n\n\n<p>\nLiteral strings can also be defined using a long format\nenclosed by <em>long brackets</em>.\nWe define an <em>opening long bracket of level <em>n</em></em> as an opening\nsquare bracket followed by <em>n</em> equal signs followed by another\nopening square bracket.\nSo, an opening long bracket of level&nbsp;0 is written as <code>[[</code>,\nan opening long bracket of level&nbsp;1 is written as <code>[=[</code>,\nand so on.\nA <em>closing long bracket</em> is defined similarly;\nfor instance, a closing long bracket of level&nbsp;4 is written as <code>]====]</code>.\nA long string starts with an opening long bracket of any level and\nends at the first closing long bracket of the same level.\nLiterals in this bracketed form can run for several lines,\ndo not interpret any escape sequences,\nand ignore long brackets of any other level.\nThey can contain anything except a closing bracket of the proper level.\n\n\n<p>\nFor convenience,\nwhen the opening long bracket is immediately followed by a newline,\nthe newline is not included in the string.\nAs an example, in a system using ASCII\n(in which '<code>a</code>' is coded as&nbsp;97,\nnewline is coded as&nbsp;10, and '<code>1</code>' is coded as&nbsp;49),\nthe five literal strings below denote the same string:\n\n<pre>\n     a = 'alo\\n123\"'\n     a = \"alo\\n123\\\"\"\n     a = '\\97lo\\10\\04923\"'\n     a = [[alo\n     123\"]]\n     a = [==[\n     alo\n     123\"]==]\n</pre>\n\n<p>\nA <em>numerical constant</em> can be written with an optional decimal part\nand an optional decimal exponent.\nLua also accepts integer hexadecimal constants,\nby prefixing them with <code>0x</code>.\nExamples of valid numerical constants are\n\n<pre>\n     3   3.0   3.1416   314.16e-2   0.31416E1   0xff   0x56\n</pre>\n\n<p>\nA <em>comment</em> starts with a double hyphen (<code>--</code>)\nanywhere outside a string.\nIf the text immediately after <code>--</code> is not an opening long bracket,\nthe comment is a <em>short comment</em>,\nwhich runs until the end of the line.\nOtherwise, it is a <em>long comment</em>,\nwhich runs until the corresponding closing long bracket.\nLong comments are frequently used to disable code temporarily.\n\n\n\n\n\n<h2>2.2 - <a name=\"2.2\">Values and Types</a></h2>\n\n<p>\nLua is a <em>dynamically typed language</em>.\nThis means that\nvariables do not have types; only values do.\nThere are no type definitions in the language.\nAll values carry their own type.\n\n\n<p>\nAll values in Lua are <em>first-class values</em>.\nThis means that all values can be stored in variables,\npassed as arguments to other functions, and returned as results.\n\n\n<p>\nThere are eight basic types in Lua:\n<em>nil</em>, <em>boolean</em>, <em>number</em>,\n<em>string</em>, <em>function</em>, <em>userdata</em>,\n<em>thread</em>, and <em>table</em>.\n<em>Nil</em> is the type of the value <b>nil</b>,\nwhose main property is to be different from any other value;\nit usually represents the absence of a useful value.\n<em>Boolean</em> is the type of the values <b>false</b> and <b>true</b>.\nBoth <b>nil</b> and <b>false</b> make a condition false;\nany other value makes it true.\n<em>Number</em> represents real (double-precision floating-point) numbers.\n(It is easy to build Lua interpreters that use other\ninternal representations for numbers,\nsuch as single-precision float or long integers;\nsee file <code>luaconf.h</code>.)\n<em>String</em> represents arrays of characters.\n\nLua is 8-bit clean:\nstrings can contain any 8-bit character,\nincluding embedded zeros ('<code>\\0</code>') (see <a href=\"#2.1\">&sect;2.1</a>).\n\n\n<p>\nLua can call (and manipulate) functions written in Lua and\nfunctions written in C\n(see <a href=\"#2.5.8\">&sect;2.5.8</a>).\n\n\n<p>\nThe type <em>userdata</em> is provided to allow arbitrary C&nbsp;data to\nbe stored in Lua variables.\nThis type corresponds to a block of raw memory\nand has no pre-defined operations in Lua,\nexcept assignment and identity test.\nHowever, by using <em>metatables</em>,\nthe programmer can define operations for userdata values\n(see <a href=\"#2.8\">&sect;2.8</a>).\nUserdata values cannot be created or modified in Lua,\nonly through the C&nbsp;API.\nThis guarantees the integrity of data owned by the host program.\n\n\n<p>\nThe type <em>thread</em> represents independent threads of execution\nand it is used to implement coroutines (see <a href=\"#2.11\">&sect;2.11</a>).\nDo not confuse Lua threads with operating-system threads.\nLua supports coroutines on all systems,\neven those that do not support threads.\n\n\n<p>\nThe type <em>table</em> implements associative arrays,\nthat is, arrays that can be indexed not only with numbers,\nbut with any value (except <b>nil</b>).\nTables can be <em>heterogeneous</em>;\nthat is, they can contain values of all types (except <b>nil</b>).\nTables are the sole data structuring mechanism in Lua;\nthey can be used to represent ordinary arrays,\nsymbol tables, sets, records, graphs, trees, etc.\nTo represent records, Lua uses the field name as an index.\nThe language supports this representation by\nproviding <code>a.name</code> as syntactic sugar for <code>a[\"name\"]</code>.\nThere are several convenient ways to create tables in Lua\n(see <a href=\"#2.5.7\">&sect;2.5.7</a>).\n\n\n<p>\nLike indices,\nthe value of a table field can be of any type (except <b>nil</b>).\nIn particular,\nbecause functions are first-class values,\ntable fields can contain functions.\nThus tables can also carry <em>methods</em> (see <a href=\"#2.5.9\">&sect;2.5.9</a>).\n\n\n<p>\nTables, functions, threads, and (full) userdata values are <em>objects</em>:\nvariables do not actually <em>contain</em> these values,\nonly <em>references</em> to them.\nAssignment, parameter passing, and function returns\nalways manipulate references to such values;\nthese operations do not imply any kind of copy.\n\n\n<p>\nThe library function <a href=\"#pdf-type\"><code>type</code></a> returns a string describing the type\nof a given value.\n\n\n\n<h3>2.2.1 - <a name=\"2.2.1\">Coercion</a></h3>\n\n<p>\nLua provides automatic conversion between\nstring and number values at run time.\nAny arithmetic operation applied to a string tries to convert\nthis string to a number, following the usual conversion rules.\nConversely, whenever a number is used where a string is expected,\nthe number is converted to a string, in a reasonable format.\nFor complete control over how numbers are converted to strings,\nuse the <code>format</code> function from the string library\n(see <a href=\"#pdf-string.format\"><code>string.format</code></a>).\n\n\n\n\n\n\n\n<h2>2.3 - <a name=\"2.3\">Variables</a></h2>\n\n<p>\nVariables are places that store values.\n\nThere are three kinds of variables in Lua:\nglobal variables, local variables, and table fields.\n\n\n<p>\nA single name can denote a global variable or a local variable\n(or a function's formal parameter,\nwhich is a particular kind of local variable):\n\n<pre>\n\tvar ::= Name\n</pre><p>\nName denotes identifiers, as defined in <a href=\"#2.1\">&sect;2.1</a>.\n\n\n<p>\nAny variable is assumed to be global unless explicitly declared\nas a local (see <a href=\"#2.4.7\">&sect;2.4.7</a>).\nLocal variables are <em>lexically scoped</em>:\nlocal variables can be freely accessed by functions\ndefined inside their scope (see <a href=\"#2.6\">&sect;2.6</a>).\n\n\n<p>\nBefore the first assignment to a variable, its value is <b>nil</b>.\n\n\n<p>\nSquare brackets are used to index a table:\n\n<pre>\n\tvar ::= prefixexp `<b>[</b>&acute; exp `<b>]</b>&acute;\n</pre><p>\nThe meaning of accesses to global variables \nand table fields can be changed via metatables.\nAn access to an indexed variable <code>t[i]</code> is equivalent to\na call <code>gettable_event(t,i)</code>.\n(See <a href=\"#2.8\">&sect;2.8</a> for a complete description of the\n<code>gettable_event</code> function.\nThis function is not defined or callable in Lua.\nWe use it here only for explanatory purposes.)\n\n\n<p>\nThe syntax <code>var.Name</code> is just syntactic sugar for\n<code>var[\"Name\"]</code>:\n\n<pre>\n\tvar ::= prefixexp `<b>.</b>&acute; Name\n</pre>\n\n<p>\nAll global variables live as fields in ordinary Lua tables,\ncalled <em>environment tables</em> or simply\n<em>environments</em> (see <a href=\"#2.9\">&sect;2.9</a>).\nEach function has its own reference to an environment,\nso that all global variables in this function\nwill refer to this environment table.\nWhen a function is created,\nit inherits the environment from the function that created it.\nTo get the environment table of a Lua function,\nyou call <a href=\"#pdf-getfenv\"><code>getfenv</code></a>.\nTo replace it,\nyou call <a href=\"#pdf-setfenv\"><code>setfenv</code></a>.\n(You can only manipulate the environment of C&nbsp;functions\nthrough the debug library; (see <a href=\"#5.9\">&sect;5.9</a>).)\n\n\n<p>\nAn access to a global variable <code>x</code>\nis equivalent to <code>_env.x</code>,\nwhich in turn is equivalent to\n\n<pre>\n     gettable_event(_env, \"x\")\n</pre><p>\nwhere <code>_env</code> is the environment of the running function.\n(See <a href=\"#2.8\">&sect;2.8</a> for a complete description of the\n<code>gettable_event</code> function.\nThis function is not defined or callable in Lua.\nSimilarly, the <code>_env</code> variable is not defined in Lua.\nWe use them here only for explanatory purposes.)\n\n\n\n\n\n<h2>2.4 - <a name=\"2.4\">Statements</a></h2>\n\n<p>\nLua supports an almost conventional set of statements,\nsimilar to those in Pascal or C.\nThis set includes\nassignments, control structures, function calls,\nand variable declarations.\n\n\n\n<h3>2.4.1 - <a name=\"2.4.1\">Chunks</a></h3>\n\n<p>\nThe unit of execution of Lua is called a <em>chunk</em>.\nA chunk is simply a sequence of statements,\nwhich are executed sequentially.\nEach statement can be optionally followed by a semicolon:\n\n<pre>\n\tchunk ::= {stat [`<b>;</b>&acute;]}\n</pre><p>\nThere are no empty statements and thus '<code>;;</code>' is not legal.\n\n\n<p>\nLua handles a chunk as the body of an anonymous function \nwith a variable number of arguments\n(see <a href=\"#2.5.9\">&sect;2.5.9</a>).\nAs such, chunks can define local variables,\nreceive arguments, and return values.\n\n\n<p>\nA chunk can be stored in a file or in a string inside the host program.\nTo execute a chunk,\nLua first pre-compiles the chunk into instructions for a virtual machine,\nand then it executes the compiled code\nwith an interpreter for the virtual machine.\n\n\n<p>\nChunks can also be pre-compiled into binary form;\nsee program <code>luac</code> for details.\nPrograms in source and compiled forms are interchangeable;\nLua automatically detects the file type and acts accordingly.\n\n\n\n\n\n\n<h3>2.4.2 - <a name=\"2.4.2\">Blocks</a></h3><p>\nA block is a list of statements;\nsyntactically, a block is the same as a chunk:\n\n<pre>\n\tblock ::= chunk\n</pre>\n\n<p>\nA block can be explicitly delimited to produce a single statement:\n\n<pre>\n\tstat ::= <b>do</b> block <b>end</b>\n</pre><p>\nExplicit blocks are useful\nto control the scope of variable declarations.\nExplicit blocks are also sometimes used to\nadd a <b>return</b> or <b>break</b> statement in the middle\nof another block (see <a href=\"#2.4.4\">&sect;2.4.4</a>).\n\n\n\n\n\n<h3>2.4.3 - <a name=\"2.4.3\">Assignment</a></h3>\n\n<p>\nLua allows multiple assignments.\nTherefore, the syntax for assignment\ndefines a list of variables on the left side\nand a list of expressions on the right side.\nThe elements in both lists are separated by commas:\n\n<pre>\n\tstat ::= varlist `<b>=</b>&acute; explist\n\tvarlist ::= var {`<b>,</b>&acute; var}\n\texplist ::= exp {`<b>,</b>&acute; exp}\n</pre><p>\nExpressions are discussed in <a href=\"#2.5\">&sect;2.5</a>.\n\n\n<p>\nBefore the assignment,\nthe list of values is <em>adjusted</em> to the length of\nthe list of variables.\nIf there are more values than needed,\nthe excess values are thrown away.\nIf there are fewer values than needed,\nthe list is extended with as many  <b>nil</b>'s as needed.\nIf the list of expressions ends with a function call,\nthen all values returned by that call enter the list of values,\nbefore the adjustment\n(except when the call is enclosed in parentheses; see <a href=\"#2.5\">&sect;2.5</a>).\n\n\n<p>\nThe assignment statement first evaluates all its expressions\nand only then are the assignments performed.\nThus the code\n\n<pre>\n     i = 3\n     i, a[i] = i+1, 20\n</pre><p>\nsets <code>a[3]</code> to 20, without affecting <code>a[4]</code>\nbecause the <code>i</code> in <code>a[i]</code> is evaluated (to 3)\nbefore it is assigned&nbsp;4.\nSimilarly, the line\n\n<pre>\n     x, y = y, x\n</pre><p>\nexchanges the values of <code>x</code> and <code>y</code>,\nand\n\n<pre>\n     x, y, z = y, z, x\n</pre><p>\ncyclically permutes the values of <code>x</code>, <code>y</code>, and <code>z</code>.\n\n\n<p>\nThe meaning of assignments to global variables\nand table fields can be changed via metatables.\nAn assignment to an indexed variable <code>t[i] = val</code> is equivalent to\n<code>settable_event(t,i,val)</code>.\n(See <a href=\"#2.8\">&sect;2.8</a> for a complete description of the\n<code>settable_event</code> function.\nThis function is not defined or callable in Lua.\nWe use it here only for explanatory purposes.)\n\n\n<p>\nAn assignment to a global variable <code>x = val</code>\nis equivalent to the assignment\n<code>_env.x = val</code>,\nwhich in turn is equivalent to\n\n<pre>\n     settable_event(_env, \"x\", val)\n</pre><p>\nwhere <code>_env</code> is the environment of the running function.\n(The <code>_env</code> variable is not defined in Lua.\nWe use it here only for explanatory purposes.)\n\n\n\n\n\n<h3>2.4.4 - <a name=\"2.4.4\">Control Structures</a></h3><p>\nThe control structures\n<b>if</b>, <b>while</b>, and <b>repeat</b> have the usual meaning and\nfamiliar syntax:\n\n\n\n\n<pre>\n\tstat ::= <b>while</b> exp <b>do</b> block <b>end</b>\n\tstat ::= <b>repeat</b> block <b>until</b> exp\n\tstat ::= <b>if</b> exp <b>then</b> block {<b>elseif</b> exp <b>then</b> block} [<b>else</b> block] <b>end</b>\n</pre><p>\nLua also has a <b>for</b> statement, in two flavors (see <a href=\"#2.4.5\">&sect;2.4.5</a>).\n\n\n<p>\nThe condition expression of a\ncontrol structure can return any value.\nBoth <b>false</b> and <b>nil</b> are considered false.\nAll values different from <b>nil</b> and <b>false</b> are considered true\n(in particular, the number 0 and the empty string are also true).\n\n\n<p>\nIn the <b>repeat</b>&ndash;<b>until</b> loop,\nthe inner block does not end at the <b>until</b> keyword,\nbut only after the condition.\nSo, the condition can refer to local variables\ndeclared inside the loop block.\n\n\n<p>\nThe <b>return</b> statement is used to return values\nfrom a function or a chunk (which is just a function).\n\nFunctions and chunks can return more than one value,\nand so the syntax for the <b>return</b> statement is\n\n<pre>\n\tstat ::= <b>return</b> [explist]\n</pre>\n\n<p>\nThe <b>break</b> statement is used to terminate the execution of a\n<b>while</b>, <b>repeat</b>, or <b>for</b> loop,\nskipping to the next statement after the loop:\n\n\n<pre>\n\tstat ::= <b>break</b>\n</pre><p>\nA <b>break</b> ends the innermost enclosing loop.\n\n\n<p>\nThe <b>return</b> and <b>break</b>\nstatements can only be written as the <em>last</em> statement of a block.\nIf it is really necessary to <b>return</b> or <b>break</b> in the\nmiddle of a block,\nthen an explicit inner block can be used,\nas in the idioms\n<code>do return end</code> and <code>do break end</code>,\nbecause now <b>return</b> and <b>break</b> are the last statements in\ntheir (inner) blocks.\n\n\n\n\n\n<h3>2.4.5 - <a name=\"2.4.5\">For Statement</a></h3>\n\n<p>\n\nThe <b>for</b> statement has two forms:\none numeric and one generic.\n\n\n<p>\nThe numeric <b>for</b> loop repeats a block of code while a\ncontrol variable runs through an arithmetic progression.\nIt has the following syntax:\n\n<pre>\n\tstat ::= <b>for</b> Name `<b>=</b>&acute; exp `<b>,</b>&acute; exp [`<b>,</b>&acute; exp] <b>do</b> block <b>end</b>\n</pre><p>\nThe <em>block</em> is repeated for <em>name</em> starting at the value of\nthe first <em>exp</em>, until it passes the second <em>exp</em> by steps of the\nthird <em>exp</em>.\nMore precisely, a <b>for</b> statement like\n\n<pre>\n     for v = <em>e1</em>, <em>e2</em>, <em>e3</em> do <em>block</em> end\n</pre><p>\nis equivalent to the code:\n\n<pre>\n     do\n       local <em>var</em>, <em>limit</em>, <em>step</em> = tonumber(<em>e1</em>), tonumber(<em>e2</em>), tonumber(<em>e3</em>)\n       if not (<em>var</em> and <em>limit</em> and <em>step</em>) then error() end\n       while (<em>step</em> &gt; 0 and <em>var</em> &lt;= <em>limit</em>) or (<em>step</em> &lt;= 0 and <em>var</em> &gt;= <em>limit</em>) do\n         local v = <em>var</em>\n         <em>block</em>\n         <em>var</em> = <em>var</em> + <em>step</em>\n       end\n     end\n</pre><p>\nNote the following:\n\n<ul>\n\n<li>\nAll three control expressions are evaluated only once,\nbefore the loop starts.\nThey must all result in numbers.\n</li>\n\n<li>\n<code><em>var</em></code>, <code><em>limit</em></code>, and <code><em>step</em></code> are invisible variables.\nThe names shown here are for explanatory purposes only.\n</li>\n\n<li>\nIf the third expression (the step) is absent,\nthen a step of&nbsp;1 is used.\n</li>\n\n<li>\nYou can use <b>break</b> to exit a <b>for</b> loop.\n</li>\n\n<li>\nThe loop variable <code>v</code> is local to the loop;\nyou cannot use its value after the <b>for</b> ends or is broken.\nIf you need this value,\nassign it to another variable before breaking or exiting the loop.\n</li>\n\n</ul>\n\n<p>\nThe generic <b>for</b> statement works over functions,\ncalled <em>iterators</em>.\nOn each iteration, the iterator function is called to produce a new value,\nstopping when this new value is <b>nil</b>.\nThe generic <b>for</b> loop has the following syntax:\n\n<pre>\n\tstat ::= <b>for</b> namelist <b>in</b> explist <b>do</b> block <b>end</b>\n\tnamelist ::= Name {`<b>,</b>&acute; Name}\n</pre><p>\nA <b>for</b> statement like\n\n<pre>\n     for <em>var_1</em>, &middot;&middot;&middot;, <em>var_n</em> in <em>explist</em> do <em>block</em> end\n</pre><p>\nis equivalent to the code:\n\n<pre>\n     do\n       local <em>f</em>, <em>s</em>, <em>var</em> = <em>explist</em>\n       while true do\n         local <em>var_1</em>, &middot;&middot;&middot;, <em>var_n</em> = <em>f</em>(<em>s</em>, <em>var</em>)\n         <em>var</em> = <em>var_1</em>\n         if <em>var</em> == nil then break end\n         <em>block</em>\n       end\n     end\n</pre><p>\nNote the following:\n\n<ul>\n\n<li>\n<code><em>explist</em></code> is evaluated only once.\nIts results are an <em>iterator</em> function,\na <em>state</em>,\nand an initial value for the first <em>iterator variable</em>.\n</li>\n\n<li>\n<code><em>f</em></code>, <code><em>s</em></code>, and <code><em>var</em></code> are invisible variables.\nThe names are here for explanatory purposes only.\n</li>\n\n<li>\nYou can use <b>break</b> to exit a <b>for</b> loop.\n</li>\n\n<li>\nThe loop variables <code><em>var_i</em></code> are local to the loop;\nyou cannot use their values after the <b>for</b> ends.\nIf you need these values,\nthen assign them to other variables before breaking or exiting the loop.\n</li>\n\n</ul>\n\n\n\n\n<h3>2.4.6 - <a name=\"2.4.6\">Function Calls as Statements</a></h3><p>\nTo allow possible side-effects,\nfunction calls can be executed as statements:\n\n<pre>\n\tstat ::= functioncall\n</pre><p>\nIn this case, all returned values are thrown away.\nFunction calls are explained in <a href=\"#2.5.8\">&sect;2.5.8</a>.\n\n\n\n\n\n<h3>2.4.7 - <a name=\"2.4.7\">Local Declarations</a></h3><p>\nLocal variables can be declared anywhere inside a block.\nThe declaration can include an initial assignment:\n\n<pre>\n\tstat ::= <b>local</b> namelist [`<b>=</b>&acute; explist]\n</pre><p>\nIf present, an initial assignment has the same semantics\nof a multiple assignment (see <a href=\"#2.4.3\">&sect;2.4.3</a>).\nOtherwise, all variables are initialized with <b>nil</b>.\n\n\n<p>\nA chunk is also a block (see <a href=\"#2.4.1\">&sect;2.4.1</a>),\nand so local variables can be declared in a chunk outside any explicit block.\nThe scope of such local variables extends until the end of the chunk.\n\n\n<p>\nThe visibility rules for local variables are explained in <a href=\"#2.6\">&sect;2.6</a>.\n\n\n\n\n\n\n\n<h2>2.5 - <a name=\"2.5\">Expressions</a></h2>\n\n<p>\nThe basic expressions in Lua are the following:\n\n<pre>\n\texp ::= prefixexp\n\texp ::= <b>nil</b> | <b>false</b> | <b>true</b>\n\texp ::= Number\n\texp ::= String\n\texp ::= function\n\texp ::= tableconstructor\n\texp ::= `<b>...</b>&acute;\n\texp ::= exp binop exp\n\texp ::= unop exp\n\tprefixexp ::= var | functioncall | `<b>(</b>&acute; exp `<b>)</b>&acute;\n</pre>\n\n<p>\nNumbers and literal strings are explained in <a href=\"#2.1\">&sect;2.1</a>;\nvariables are explained in <a href=\"#2.3\">&sect;2.3</a>;\nfunction definitions are explained in <a href=\"#2.5.9\">&sect;2.5.9</a>;\nfunction calls are explained in <a href=\"#2.5.8\">&sect;2.5.8</a>;\ntable constructors are explained in <a href=\"#2.5.7\">&sect;2.5.7</a>.\nVararg expressions,\ndenoted by three dots ('<code>...</code>'), can only be used when\ndirectly inside a vararg function;\nthey are explained in <a href=\"#2.5.9\">&sect;2.5.9</a>.\n\n\n<p>\nBinary operators comprise arithmetic operators (see <a href=\"#2.5.1\">&sect;2.5.1</a>),\nrelational operators (see <a href=\"#2.5.2\">&sect;2.5.2</a>), logical operators (see <a href=\"#2.5.3\">&sect;2.5.3</a>),\nand the concatenation operator (see <a href=\"#2.5.4\">&sect;2.5.4</a>).\nUnary operators comprise the unary minus (see <a href=\"#2.5.1\">&sect;2.5.1</a>),\nthe unary <b>not</b> (see <a href=\"#2.5.3\">&sect;2.5.3</a>),\nand the unary <em>length operator</em> (see <a href=\"#2.5.5\">&sect;2.5.5</a>).\n\n\n<p>\nBoth function calls and vararg expressions can result in multiple values.\nIf an expression is used as a statement\n(only possible for function calls (see <a href=\"#2.4.6\">&sect;2.4.6</a>)),\nthen its return list is adjusted to zero elements,\nthus discarding all returned values.\nIf an expression is used as the last (or the only) element\nof a list of expressions,\nthen no adjustment is made\n(unless the call is enclosed in parentheses).\nIn all other contexts,\nLua adjusts the result list to one element,\ndiscarding all values except the first one.\n\n\n<p>\nHere are some examples:\n\n<pre>\n     f()                -- adjusted to 0 results\n     g(f(), x)          -- f() is adjusted to 1 result\n     g(x, f())          -- g gets x plus all results from f()\n     a,b,c = f(), x     -- f() is adjusted to 1 result (c gets nil)\n     a,b = ...          -- a gets the first vararg parameter, b gets\n                        -- the second (both a and b can get nil if there\n                        -- is no corresponding vararg parameter)\n     \n     a,b,c = x, f()     -- f() is adjusted to 2 results\n     a,b,c = f()        -- f() is adjusted to 3 results\n     return f()         -- returns all results from f()\n     return ...         -- returns all received vararg parameters\n     return x,y,f()     -- returns x, y, and all results from f()\n     {f()}              -- creates a list with all results from f()\n     {...}              -- creates a list with all vararg parameters\n     {f(), nil}         -- f() is adjusted to 1 result\n</pre>\n\n<p>\nAny expression enclosed in parentheses always results in only one value.\nThus,\n<code>(f(x,y,z))</code> is always a single value,\neven if <code>f</code> returns several values.\n(The value of <code>(f(x,y,z))</code> is the first value returned by <code>f</code>\nor <b>nil</b> if <code>f</code> does not return any values.)\n\n\n\n<h3>2.5.1 - <a name=\"2.5.1\">Arithmetic Operators</a></h3><p>\nLua supports the usual arithmetic operators:\nthe binary <code>+</code> (addition),\n<code>-</code> (subtraction), <code>*</code> (multiplication),\n<code>/</code> (division), <code>%</code> (modulo), and <code>^</code> (exponentiation);\nand unary <code>-</code> (negation).\nIf the operands are numbers, or strings that can be converted to\nnumbers (see <a href=\"#2.2.1\">&sect;2.2.1</a>),\nthen all operations have the usual meaning.\nExponentiation works for any exponent.\nFor instance, <code>x^(-0.5)</code> computes the inverse of the square root of <code>x</code>.\nModulo is defined as\n\n<pre>\n     a % b == a - math.floor(a/b)*b\n</pre><p>\nThat is, it is the remainder of a division that rounds\nthe quotient towards minus infinity.\n\n\n\n\n\n<h3>2.5.2 - <a name=\"2.5.2\">Relational Operators</a></h3><p>\nThe relational operators in Lua are\n\n<pre>\n     ==    ~=    &lt;     &gt;     &lt;=    &gt;=\n</pre><p>\nThese operators always result in <b>false</b> or <b>true</b>.\n\n\n<p>\nEquality (<code>==</code>) first compares the type of its operands.\nIf the types are different, then the result is <b>false</b>.\nOtherwise, the values of the operands are compared.\nNumbers and strings are compared in the usual way.\nObjects (tables, userdata, threads, and functions)\nare compared by <em>reference</em>:\ntwo objects are considered equal only if they are the <em>same</em> object.\nEvery time you create a new object\n(a table, userdata, thread, or function),\nthis new object is different from any previously existing object.\n\n\n<p>\nYou can change the way that Lua compares tables and userdata \nby using the \"eq\" metamethod (see <a href=\"#2.8\">&sect;2.8</a>).\n\n\n<p>\nThe conversion rules of <a href=\"#2.2.1\">&sect;2.2.1</a>\n<em>do not</em> apply to equality comparisons.\nThus, <code>\"0\"==0</code> evaluates to <b>false</b>,\nand <code>t[0]</code> and <code>t[\"0\"]</code> denote different\nentries in a table.\n\n\n<p>\nThe operator <code>~=</code> is exactly the negation of equality (<code>==</code>).\n\n\n<p>\nThe order operators work as follows.\nIf both arguments are numbers, then they are compared as such.\nOtherwise, if both arguments are strings,\nthen their values are compared according to the current locale.\nOtherwise, Lua tries to call the \"lt\" or the \"le\"\nmetamethod (see <a href=\"#2.8\">&sect;2.8</a>).\nA comparison <code>a &gt; b</code> is translated to <code>b &lt; a</code>\nand <code>a &gt;= b</code> is translated to <code>b &lt;= a</code>.\n\n\n\n\n\n<h3>2.5.3 - <a name=\"2.5.3\">Logical Operators</a></h3><p>\nThe logical operators in Lua are\n<b>and</b>, <b>or</b>, and <b>not</b>.\nLike the control structures (see <a href=\"#2.4.4\">&sect;2.4.4</a>),\nall logical operators consider both <b>false</b> and <b>nil</b> as false\nand anything else as true.\n\n\n<p>\nThe negation operator <b>not</b> always returns <b>false</b> or <b>true</b>.\nThe conjunction operator <b>and</b> returns its first argument\nif this value is <b>false</b> or <b>nil</b>;\notherwise, <b>and</b> returns its second argument.\nThe disjunction operator <b>or</b> returns its first argument\nif this value is different from <b>nil</b> and <b>false</b>;\notherwise, <b>or</b> returns its second argument.\nBoth <b>and</b> and <b>or</b> use short-cut evaluation;\nthat is,\nthe second operand is evaluated only if necessary.\nHere are some examples:\n\n<pre>\n     10 or 20            --&gt; 10\n     10 or error()       --&gt; 10\n     nil or \"a\"          --&gt; \"a\"\n     nil and 10          --&gt; nil\n     false and error()   --&gt; false\n     false and nil       --&gt; false\n     false or nil        --&gt; nil\n     10 and 20           --&gt; 20\n</pre><p>\n(In this manual,\n<code>--&gt;</code> indicates the result of the preceding expression.)\n\n\n\n\n\n<h3>2.5.4 - <a name=\"2.5.4\">Concatenation</a></h3><p>\nThe string concatenation operator in Lua is\ndenoted by two dots ('<code>..</code>').\nIf both operands are strings or numbers, then they are converted to\nstrings according to the rules mentioned in <a href=\"#2.2.1\">&sect;2.2.1</a>.\nOtherwise, the \"concat\" metamethod is called (see <a href=\"#2.8\">&sect;2.8</a>).\n\n\n\n\n\n<h3>2.5.5 - <a name=\"2.5.5\">The Length Operator</a></h3>\n\n<p>\nThe length operator is denoted by the unary operator <code>#</code>.\nThe length of a string is its number of bytes\n(that is, the usual meaning of string length when each\ncharacter is one byte).\n\n\n<p>\nThe length of a table <code>t</code> is defined to be any\ninteger index <code>n</code>\nsuch that <code>t[n]</code> is not <b>nil</b> and <code>t[n+1]</code> is <b>nil</b>;\nmoreover, if <code>t[1]</code> is <b>nil</b>, <code>n</code> can be zero.\nFor a regular array, with non-nil values from 1 to a given <code>n</code>,\nits length is exactly that <code>n</code>,\nthe index of its last value.\nIf the array has \"holes\"\n(that is, <b>nil</b> values between other non-nil values),\nthen <code>#t</code> can be any of the indices that\ndirectly precedes a <b>nil</b> value\n(that is, it may consider any such <b>nil</b> value as the end of\nthe array). \n\n\n\n\n\n<h3>2.5.6 - <a name=\"2.5.6\">Precedence</a></h3><p>\nOperator precedence in Lua follows the table below,\nfrom lower to higher priority:\n\n<pre>\n     or\n     and\n     &lt;     &gt;     &lt;=    &gt;=    ~=    ==\n     ..\n     +     -\n     *     /     %\n     not   #     - (unary)\n     ^\n</pre><p>\nAs usual,\nyou can use parentheses to change the precedences of an expression.\nThe concatenation ('<code>..</code>') and exponentiation ('<code>^</code>')\noperators are right associative.\nAll other binary operators are left associative.\n\n\n\n\n\n<h3>2.5.7 - <a name=\"2.5.7\">Table Constructors</a></h3><p>\nTable constructors are expressions that create tables.\nEvery time a constructor is evaluated, a new table is created.\nA constructor can be used to create an empty table\nor to create a table and initialize some of its fields.\nThe general syntax for constructors is\n\n<pre>\n\ttableconstructor ::= `<b>{</b>&acute; [fieldlist] `<b>}</b>&acute;\n\tfieldlist ::= field {fieldsep field} [fieldsep]\n\tfield ::= `<b>[</b>&acute; exp `<b>]</b>&acute; `<b>=</b>&acute; exp | Name `<b>=</b>&acute; exp | exp\n\tfieldsep ::= `<b>,</b>&acute; | `<b>;</b>&acute;\n</pre>\n\n<p>\nEach field of the form <code>[exp1] = exp2</code> adds to the new table an entry\nwith key <code>exp1</code> and value <code>exp2</code>.\nA field of the form <code>name = exp</code> is equivalent to\n<code>[\"name\"] = exp</code>.\nFinally, fields of the form <code>exp</code> are equivalent to\n<code>[i] = exp</code>, where <code>i</code> are consecutive numerical integers,\nstarting with 1.\nFields in the other formats do not affect this counting.\nFor example,\n\n<pre>\n     a = { [f(1)] = g; \"x\", \"y\"; x = 1, f(x), [30] = 23; 45 }\n</pre><p>\nis equivalent to\n\n<pre>\n     do\n       local t = {}\n       t[f(1)] = g\n       t[1] = \"x\"         -- 1st exp\n       t[2] = \"y\"         -- 2nd exp\n       t.x = 1            -- t[\"x\"] = 1\n       t[3] = f(x)        -- 3rd exp\n       t[30] = 23\n       t[4] = 45          -- 4th exp\n       a = t\n     end\n</pre>\n\n<p>\nIf the last field in the list has the form <code>exp</code>\nand the expression is a function call or a vararg expression,\nthen all values returned by this expression enter the list consecutively\n(see <a href=\"#2.5.8\">&sect;2.5.8</a>).\nTo avoid this,\nenclose the function call or the vararg expression\nin parentheses (see <a href=\"#2.5\">&sect;2.5</a>).\n\n\n<p>\nThe field list can have an optional trailing separator,\nas a convenience for machine-generated code.\n\n\n\n\n\n<h3>2.5.8 - <a name=\"2.5.8\">Function Calls</a></h3><p>\nA function call in Lua has the following syntax:\n\n<pre>\n\tfunctioncall ::= prefixexp args\n</pre><p>\nIn a function call,\nfirst prefixexp and args are evaluated.\nIf the value of prefixexp has type <em>function</em>,\nthen this function is called\nwith the given arguments.\nOtherwise, the prefixexp \"call\" metamethod is called,\nhaving as first parameter the value of prefixexp,\nfollowed by the original call arguments\n(see <a href=\"#2.8\">&sect;2.8</a>).\n\n\n<p>\nThe form\n\n<pre>\n\tfunctioncall ::= prefixexp `<b>:</b>&acute; Name args\n</pre><p>\ncan be used to call \"methods\".\nA call <code>v:name(<em>args</em>)</code>\nis syntactic sugar for <code>v.name(v,<em>args</em>)</code>,\nexcept that <code>v</code> is evaluated only once.\n\n\n<p>\nArguments have the following syntax:\n\n<pre>\n\targs ::= `<b>(</b>&acute; [explist] `<b>)</b>&acute;\n\targs ::= tableconstructor\n\targs ::= String\n</pre><p>\nAll argument expressions are evaluated before the call.\nA call of the form <code>f{<em>fields</em>}</code> is\nsyntactic sugar for <code>f({<em>fields</em>})</code>;\nthat is, the argument list is a single new table.\nA call of the form <code>f'<em>string</em>'</code>\n(or <code>f\"<em>string</em>\"</code> or <code>f[[<em>string</em>]]</code>)\nis syntactic sugar for <code>f('<em>string</em>')</code>;\nthat is, the argument list is a single literal string.\n\n\n<p>\nAs an exception to the free-format syntax of Lua,\nyou cannot put a line break before the '<code>(</code>' in a function call.\nThis restriction avoids some ambiguities in the language.\nIf you write\n\n<pre>\n     a = f\n     (g).x(a)\n</pre><p>\nLua would see that as a single statement, <code>a = f(g).x(a)</code>.\nSo, if you want two statements, you must add a semi-colon between them.\nIf you actually want to call <code>f</code>,\nyou must remove the line break before <code>(g)</code>.\n\n\n<p>\nA call of the form <code>return</code> <em>functioncall</em> is called\na <em>tail call</em>.\nLua implements <em>proper tail calls</em>\n(or <em>proper tail recursion</em>):\nin a tail call,\nthe called function reuses the stack entry of the calling function.\nTherefore, there is no limit on the number of nested tail calls that\na program can execute.\nHowever, a tail call erases any debug information about the\ncalling function.\nNote that a tail call only happens with a particular syntax,\nwhere the <b>return</b> has one single function call as argument;\nthis syntax makes the calling function return exactly\nthe returns of the called function.\nSo, none of the following examples are tail calls:\n\n<pre>\n     return (f(x))        -- results adjusted to 1\n     return 2 * f(x)\n     return x, f(x)       -- additional results\n     f(x); return         -- results discarded\n     return x or f(x)     -- results adjusted to 1\n</pre>\n\n\n\n\n<h3>2.5.9 - <a name=\"2.5.9\">Function Definitions</a></h3>\n\n<p>\nThe syntax for function definition is\n\n<pre>\n\tfunction ::= <b>function</b> funcbody\n\tfuncbody ::= `<b>(</b>&acute; [parlist] `<b>)</b>&acute; block <b>end</b>\n</pre>\n\n<p>\nThe following syntactic sugar simplifies function definitions:\n\n<pre>\n\tstat ::= <b>function</b> funcname funcbody\n\tstat ::= <b>local</b> <b>function</b> Name funcbody\n\tfuncname ::= Name {`<b>.</b>&acute; Name} [`<b>:</b>&acute; Name]\n</pre><p>\nThe statement\n\n<pre>\n     function f () <em>body</em> end\n</pre><p>\ntranslates to\n\n<pre>\n     f = function () <em>body</em> end\n</pre><p>\nThe statement\n\n<pre>\n     function t.a.b.c.f () <em>body</em> end\n</pre><p>\ntranslates to\n\n<pre>\n     t.a.b.c.f = function () <em>body</em> end\n</pre><p>\nThe statement\n\n<pre>\n     local function f () <em>body</em> end\n</pre><p>\ntranslates to\n\n<pre>\n     local f; f = function () <em>body</em> end\n</pre><p>\n<em>not</em> to\n\n<pre>\n     local f = function () <em>body</em> end\n</pre><p>\n(This only makes a difference when the body of the function\ncontains references to <code>f</code>.)\n\n\n<p>\nA function definition is an executable expression,\nwhose value has type <em>function</em>.\nWhen Lua pre-compiles a chunk,\nall its function bodies are pre-compiled too.\nThen, whenever Lua executes the function definition,\nthe function is <em>instantiated</em> (or <em>closed</em>).\nThis function instance (or <em>closure</em>)\nis the final value of the expression.\nDifferent instances of the same function\ncan refer to different  external local variables\nand can have different environment tables.\n\n\n<p>\nParameters act as local variables that are\ninitialized with the argument values:\n\n<pre>\n\tparlist ::= namelist [`<b>,</b>&acute; `<b>...</b>&acute;] | `<b>...</b>&acute;\n</pre><p>\nWhen a function is called,\nthe list of arguments is adjusted to\nthe length of the list of parameters,\nunless the function is a variadic or <em>vararg function</em>,\nwhich is\nindicated by three dots ('<code>...</code>') at the end of its parameter list.\nA vararg function does not adjust its argument list;\ninstead, it collects all extra arguments and supplies them\nto the function through a <em>vararg expression</em>,\nwhich is also written as three dots.\nThe value of this expression is a list of all actual extra arguments,\nsimilar to a function with multiple results.\nIf a vararg expression is used inside another expression\nor in the middle of a list of expressions,\nthen its return list is adjusted to one element.\nIf the expression is used as the last element of a list of expressions,\nthen no adjustment is made\n(unless that last expression is enclosed in parentheses).\n\n\n<p>\nAs an example, consider the following definitions:\n\n<pre>\n     function f(a, b) end\n     function g(a, b, ...) end\n     function r() return 1,2,3 end\n</pre><p>\nThen, we have the following mapping from arguments to parameters and\nto the vararg expression:\n\n<pre>\n     CALL            PARAMETERS\n     \n     f(3)             a=3, b=nil\n     f(3, 4)          a=3, b=4\n     f(3, 4, 5)       a=3, b=4\n     f(r(), 10)       a=1, b=10\n     f(r())           a=1, b=2\n     \n     g(3)             a=3, b=nil, ... --&gt;  (nothing)\n     g(3, 4)          a=3, b=4,   ... --&gt;  (nothing)\n     g(3, 4, 5, 8)    a=3, b=4,   ... --&gt;  5  8\n     g(5, r())        a=5, b=1,   ... --&gt;  2  3\n</pre>\n\n<p>\nResults are returned using the <b>return</b> statement (see <a href=\"#2.4.4\">&sect;2.4.4</a>).\nIf control reaches the end of a function\nwithout encountering a <b>return</b> statement,\nthen the function returns with no results.\n\n\n<p>\nThe <em>colon</em> syntax\nis used for defining <em>methods</em>,\nthat is, functions that have an implicit extra parameter <code>self</code>.\nThus, the statement\n\n<pre>\n     function t.a.b.c:f (<em>params</em>) <em>body</em> end\n</pre><p>\nis syntactic sugar for\n\n<pre>\n     t.a.b.c.f = function (self, <em>params</em>) <em>body</em> end\n</pre>\n\n\n\n\n\n\n<h2>2.6 - <a name=\"2.6\">Visibility Rules</a></h2>\n\n<p>\n\nLua is a lexically scoped language.\nThe scope of variables begins at the first statement <em>after</em>\ntheir declaration and lasts until the end of the innermost block that\nincludes the declaration.\nConsider the following example:\n\n<pre>\n     x = 10                -- global variable\n     do                    -- new block\n       local x = x         -- new 'x', with value 10\n       print(x)            --&gt; 10\n       x = x+1\n       do                  -- another block\n         local x = x+1     -- another 'x'\n         print(x)          --&gt; 12\n       end\n       print(x)            --&gt; 11\n     end\n     print(x)              --&gt; 10  (the global one)\n</pre>\n\n<p>\nNotice that, in a declaration like <code>local x = x</code>,\nthe new <code>x</code> being declared is not in scope yet,\nand so the second <code>x</code> refers to the outside variable.\n\n\n<p>\nBecause of the lexical scoping rules,\nlocal variables can be freely accessed by functions\ndefined inside their scope.\nA local variable used by an inner function is called\nan <em>upvalue</em>, or <em>external local variable</em>,\ninside the inner function.\n\n\n<p>\nNotice that each execution of a <b>local</b> statement\ndefines new local variables.\nConsider the following example:\n\n<pre>\n     a = {}\n     local x = 20\n     for i=1,10 do\n       local y = 0\n       a[i] = function () y=y+1; return x+y end\n     end\n</pre><p>\nThe loop creates ten closures\n(that is, ten instances of the anonymous function).\nEach of these closures uses a different <code>y</code> variable,\nwhile all of them share the same <code>x</code>.\n\n\n\n\n\n<h2>2.7 - <a name=\"2.7\">Error Handling</a></h2>\n\n<p>\nBecause Lua is an embedded extension language,\nall Lua actions start from C&nbsp;code in the host program\ncalling a function from the Lua library (see <a href=\"#lua_pcall\"><code>lua_pcall</code></a>).\nWhenever an error occurs during Lua compilation or execution,\ncontrol returns to C,\nwhich can take appropriate measures\n(such as printing an error message).\n\n\n<p>\nLua code can explicitly generate an error by calling the\n<a href=\"#pdf-error\"><code>error</code></a> function.\nIf you need to catch errors in Lua,\nyou can use the <a href=\"#pdf-pcall\"><code>pcall</code></a> function.\n\n\n\n\n\n<h2>2.8 - <a name=\"2.8\">Metatables</a></h2>\n\n<p>\nEvery value in Lua can have a <em>metatable</em>.\nThis <em>metatable</em> is an ordinary Lua table\nthat defines the behavior of the original value\nunder certain special operations.\nYou can change several aspects of the behavior\nof operations over a value by setting specific fields in its metatable.\nFor instance, when a non-numeric value is the operand of an addition,\nLua checks for a function in the field <code>\"__add\"</code> in its metatable.\nIf it finds one,\nLua calls this function to perform the addition.\n\n\n<p>\nWe call the keys in a metatable <em>events</em>\nand the values <em>metamethods</em>.\nIn the previous example, the event is <code>\"add\"</code> \nand the metamethod is the function that performs the addition.\n\n\n<p>\nYou can query the metatable of any value\nthrough the <a href=\"#pdf-getmetatable\"><code>getmetatable</code></a> function.\n\n\n<p>\nYou can replace the metatable of tables\nthrough the <a href=\"#pdf-setmetatable\"><code>setmetatable</code></a>\nfunction.\nYou cannot change the metatable of other types from Lua\n(except by using the debug library);\nyou must use the C&nbsp;API for that.\n\n\n<p>\nTables and full userdata have individual metatables\n(although multiple tables and userdata can share their metatables).\nValues of all other types share one single metatable per type;\nthat is, there is one single metatable for all numbers,\none for all strings, etc.\n\n\n<p>\nA metatable controls how an object behaves in arithmetic operations,\norder comparisons, concatenation, length operation, and indexing.\nA metatable also can define a function to be called when a userdata\nis garbage collected.\nFor each of these operations Lua associates a specific key\ncalled an <em>event</em>.\nWhen Lua performs one of these operations over a value,\nit checks whether this value has a metatable with the corresponding event.\nIf so, the value associated with that key (the metamethod)\ncontrols how Lua will perform the operation.\n\n\n<p>\nMetatables control the operations listed next.\nEach operation is identified by its corresponding name.\nThe key for each operation is a string with its name prefixed by\ntwo underscores, '<code>__</code>';\nfor instance, the key for operation \"add\" is the\nstring <code>\"__add\"</code>.\nThe semantics of these operations is better explained by a Lua function\ndescribing how the interpreter executes the operation.\n\n\n<p>\nThe code shown here in Lua is only illustrative;\nthe real behavior is hard coded in the interpreter\nand it is much more efficient than this simulation.\nAll functions used in these descriptions\n(<a href=\"#pdf-rawget\"><code>rawget</code></a>, <a href=\"#pdf-tonumber\"><code>tonumber</code></a>, etc.)\nare described in <a href=\"#5.1\">&sect;5.1</a>.\nIn particular, to retrieve the metamethod of a given object,\nwe use the expression\n\n<pre>\n     metatable(obj)[event]\n</pre><p>\nThis should be read as\n\n<pre>\n     rawget(getmetatable(obj) or {}, event)\n</pre><p>\n\nThat is, the access to a metamethod does not invoke other metamethods,\nand the access to objects with no metatables does not fail\n(it simply results in <b>nil</b>).\n\n\n\n<ul>\n\n<li><b>\"add\":</b>\nthe <code>+</code> operation.\n\n\n\n<p>\nThe function <code>getbinhandler</code> below defines how Lua chooses a handler\nfor a binary operation.\nFirst, Lua tries the first operand.\nIf its type does not define a handler for the operation,\nthen Lua tries the second operand.\n\n<pre>\n     function getbinhandler (op1, op2, event)\n       return metatable(op1)[event] or metatable(op2)[event]\n     end\n</pre><p>\nBy using this function,\nthe behavior of the <code>op1 + op2</code> is\n\n<pre>\n     function add_event (op1, op2)\n       local o1, o2 = tonumber(op1), tonumber(op2)\n       if o1 and o2 then  -- both operands are numeric?\n         return o1 + o2   -- '+' here is the primitive 'add'\n       else  -- at least one of the operands is not numeric\n         local h = getbinhandler(op1, op2, \"__add\")\n         if h then\n           -- call the handler with both operands\n           return (h(op1, op2))\n         else  -- no handler available: default behavior\n           error(&middot;&middot;&middot;)\n         end\n       end\n     end\n</pre><p>\n</li>\n\n<li><b>\"sub\":</b>\nthe <code>-</code> operation.\n\nBehavior similar to the \"add\" operation.\n</li>\n\n<li><b>\"mul\":</b>\nthe <code>*</code> operation.\n\nBehavior similar to the \"add\" operation.\n</li>\n\n<li><b>\"div\":</b>\nthe <code>/</code> operation.\n\nBehavior similar to the \"add\" operation.\n</li>\n\n<li><b>\"mod\":</b>\nthe <code>%</code> operation.\n\nBehavior similar to the \"add\" operation,\nwith the operation\n<code>o1 - floor(o1/o2)*o2</code> as the primitive operation.\n</li>\n\n<li><b>\"pow\":</b>\nthe <code>^</code> (exponentiation) operation.\n\nBehavior similar to the \"add\" operation,\nwith the function <code>pow</code> (from the C&nbsp;math library)\nas the primitive operation.\n</li>\n\n<li><b>\"unm\":</b>\nthe unary <code>-</code> operation.\n\n\n<pre>\n     function unm_event (op)\n       local o = tonumber(op)\n       if o then  -- operand is numeric?\n         return -o  -- '-' here is the primitive 'unm'\n       else  -- the operand is not numeric.\n         -- Try to get a handler from the operand\n         local h = metatable(op).__unm\n         if h then\n           -- call the handler with the operand\n           return (h(op))\n         else  -- no handler available: default behavior\n           error(&middot;&middot;&middot;)\n         end\n       end\n     end\n</pre><p>\n</li>\n\n<li><b>\"concat\":</b>\nthe <code>..</code> (concatenation) operation.\n\n\n<pre>\n     function concat_event (op1, op2)\n       if (type(op1) == \"string\" or type(op1) == \"number\") and\n          (type(op2) == \"string\" or type(op2) == \"number\") then\n         return op1 .. op2  -- primitive string concatenation\n       else\n         local h = getbinhandler(op1, op2, \"__concat\")\n         if h then\n           return (h(op1, op2))\n         else\n           error(&middot;&middot;&middot;)\n         end\n       end\n     end\n</pre><p>\n</li>\n\n<li><b>\"len\":</b>\nthe <code>#</code> operation.\n\n\n<pre>\n     function len_event (op)\n       if type(op) == \"string\" then\n         return strlen(op)         -- primitive string length\n       elseif type(op) == \"table\" then\n         return #op                -- primitive table length\n       else\n         local h = metatable(op).__len\n         if h then\n           -- call the handler with the operand\n           return (h(op))\n         else  -- no handler available: default behavior\n           error(&middot;&middot;&middot;)\n         end\n       end\n     end\n</pre><p>\nSee <a href=\"#2.5.5\">&sect;2.5.5</a> for a description of the length of a table.\n</li>\n\n<li><b>\"eq\":</b>\nthe <code>==</code> operation.\n\nThe function <code>getcomphandler</code> defines how Lua chooses a metamethod\nfor comparison operators.\nA metamethod only is selected when both objects\nbeing compared have the same type\nand the same metamethod for the selected operation.\n\n<pre>\n     function getcomphandler (op1, op2, event)\n       if type(op1) ~= type(op2) then return nil end\n       local mm1 = metatable(op1)[event]\n       local mm2 = metatable(op2)[event]\n       if mm1 == mm2 then return mm1 else return nil end\n     end\n</pre><p>\nThe \"eq\" event is defined as follows:\n\n<pre>\n     function eq_event (op1, op2)\n       if type(op1) ~= type(op2) then  -- different types?\n         return false   -- different objects\n       end\n       if op1 == op2 then   -- primitive equal?\n         return true   -- objects are equal\n       end\n       -- try metamethod\n       local h = getcomphandler(op1, op2, \"__eq\")\n       if h then\n         return (h(op1, op2))\n       else\n         return false\n       end\n     end\n</pre><p>\n<code>a ~= b</code> is equivalent to <code>not (a == b)</code>.\n</li>\n\n<li><b>\"lt\":</b>\nthe <code>&lt;</code> operation.\n\n\n<pre>\n     function lt_event (op1, op2)\n       if type(op1) == \"number\" and type(op2) == \"number\" then\n         return op1 &lt; op2   -- numeric comparison\n       elseif type(op1) == \"string\" and type(op2) == \"string\" then\n         return op1 &lt; op2   -- lexicographic comparison\n       else\n         local h = getcomphandler(op1, op2, \"__lt\")\n         if h then\n           return (h(op1, op2))\n         else\n           error(&middot;&middot;&middot;)\n         end\n       end\n     end\n</pre><p>\n<code>a &gt; b</code> is equivalent to <code>b &lt; a</code>.\n</li>\n\n<li><b>\"le\":</b>\nthe <code>&lt;=</code> operation.\n\n\n<pre>\n     function le_event (op1, op2)\n       if type(op1) == \"number\" and type(op2) == \"number\" then\n         return op1 &lt;= op2   -- numeric comparison\n       elseif type(op1) == \"string\" and type(op2) == \"string\" then\n         return op1 &lt;= op2   -- lexicographic comparison\n       else\n         local h = getcomphandler(op1, op2, \"__le\")\n         if h then\n           return (h(op1, op2))\n         else\n           h = getcomphandler(op1, op2, \"__lt\")\n           if h then\n             return not h(op2, op1)\n           else\n             error(&middot;&middot;&middot;)\n           end\n         end\n       end\n     end\n</pre><p>\n<code>a &gt;= b</code> is equivalent to <code>b &lt;= a</code>.\nNote that, in the absence of a \"le\" metamethod,\nLua tries the \"lt\", assuming that <code>a &lt;= b</code> is\nequivalent to <code>not (b &lt; a)</code>.\n</li>\n\n<li><b>\"index\":</b>\nThe indexing access <code>table[key]</code>.\n\n\n<pre>\n     function gettable_event (table, key)\n       local h\n       if type(table) == \"table\" then\n         local v = rawget(table, key)\n         if v ~= nil then return v end\n         h = metatable(table).__index\n         if h == nil then return nil end\n       else\n         h = metatable(table).__index\n         if h == nil then\n           error(&middot;&middot;&middot;)\n         end\n       end\n       if type(h) == \"function\" then\n         return (h(table, key))     -- call the handler\n       else return h[key]           -- or repeat operation on it\n       end\n     end\n</pre><p>\n</li>\n\n<li><b>\"newindex\":</b>\nThe indexing assignment <code>table[key] = value</code>.\n\n\n<pre>\n     function settable_event (table, key, value)\n       local h\n       if type(table) == \"table\" then\n         local v = rawget(table, key)\n         if v ~= nil then rawset(table, key, value); return end\n         h = metatable(table).__newindex\n         if h == nil then rawset(table, key, value); return end\n       else\n         h = metatable(table).__newindex\n         if h == nil then\n           error(&middot;&middot;&middot;)\n         end\n       end\n       if type(h) == \"function\" then\n         h(table, key,value)           -- call the handler\n       else h[key] = value             -- or repeat operation on it\n       end\n     end\n</pre><p>\n</li>\n\n<li><b>\"call\":</b>\ncalled when Lua calls a value.\n\n\n<pre>\n     function function_event (func, ...)\n       if type(func) == \"function\" then\n         return func(...)   -- primitive call\n       else\n         local h = metatable(func).__call\n         if h then\n           return h(func, ...)\n         else\n           error(&middot;&middot;&middot;)\n         end\n       end\n     end\n</pre><p>\n</li>\n\n</ul>\n\n\n\n\n<h2>2.9 - <a name=\"2.9\">Environments</a></h2>\n\n<p>\nBesides metatables,\nobjects of types thread, function, and userdata\nhave another table associated with them,\ncalled their <em>environment</em>.\nLike metatables, environments are regular tables and\nmultiple objects can share the same environment.\n\n\n<p>\nThreads are created sharing the environment of the creating thread.\nUserdata and C&nbsp;functions are created sharing the environment\nof the creating C&nbsp;function.\nNon-nested Lua functions\n(created by <a href=\"#pdf-loadfile\"><code>loadfile</code></a>, <a href=\"#pdf-loadstring\"><code>loadstring</code></a> or <a href=\"#pdf-load\"><code>load</code></a>)\nare created sharing the environment of the creating thread.\nNested Lua functions are created sharing the environment of\nthe creating Lua function.\n\n\n<p>\nEnvironments associated with userdata have no meaning for Lua.\nIt is only a convenience feature for programmers to associate a table to\na userdata.\n\n\n<p>\nEnvironments associated with threads are called\n<em>global environments</em>.\nThey are used as the default environment for threads and\nnon-nested Lua functions created by the thread\nand can be directly accessed by C&nbsp;code (see <a href=\"#3.3\">&sect;3.3</a>).\n\n\n<p>\nThe environment associated with a C&nbsp;function can be directly\naccessed by C&nbsp;code (see <a href=\"#3.3\">&sect;3.3</a>).\nIt is used as the default environment for other C&nbsp;functions\nand userdata created by the function.\n\n\n<p>\nEnvironments associated with Lua functions are used to resolve\nall accesses to global variables within the function (see <a href=\"#2.3\">&sect;2.3</a>).\nThey are used as the default environment for nested Lua functions\ncreated by the function.\n\n\n<p>\nYou can change the environment of a Lua function or the\nrunning thread by calling <a href=\"#pdf-setfenv\"><code>setfenv</code></a>.\nYou can get the environment of a Lua function or the running thread\nby calling <a href=\"#pdf-getfenv\"><code>getfenv</code></a>.\nTo manipulate the environment of other objects\n(userdata, C&nbsp;functions, other threads) you must\nuse the C&nbsp;API.\n\n\n\n\n\n<h2>2.10 - <a name=\"2.10\">Garbage Collection</a></h2>\n\n<p>\nLua performs automatic memory management.\nThis means that\nyou have to worry neither about allocating memory for new objects\nnor about freeing it when the objects are no longer needed.\nLua manages memory automatically by running\na <em>garbage collector</em> from time to time\nto collect all <em>dead objects</em>\n(that is, objects that are no longer accessible from Lua).\nAll memory used by Lua is subject to automatic management:\ntables, userdata, functions, threads, strings, etc.\n\n\n<p>\nLua implements an incremental mark-and-sweep collector.\nIt uses two numbers to control its garbage-collection cycles:\nthe <em>garbage-collector pause</em> and\nthe <em>garbage-collector step multiplier</em>.\nBoth use percentage points as units\n(so that a value of 100 means an internal value of 1).\n\n\n<p>\nThe garbage-collector pause\ncontrols how long the collector waits before starting a new cycle.\nLarger values make the collector less aggressive.\nValues smaller than 100 mean the collector will not wait to\nstart a new cycle.\nA value of 200 means that the collector waits for the total memory in use\nto double before starting a new cycle.\n\n\n<p>\nThe step multiplier\ncontrols the relative speed of the collector relative to\nmemory allocation.\nLarger values make the collector more aggressive but also increase\nthe size of each incremental step.\nValues smaller than 100 make the collector too slow and\ncan result in the collector never finishing a cycle.\nThe default, 200, means that the collector runs at \"twice\"\nthe speed of memory allocation.\n\n\n<p>\nYou can change these numbers by calling <a href=\"#lua_gc\"><code>lua_gc</code></a> in C\nor <a href=\"#pdf-collectgarbage\"><code>collectgarbage</code></a> in Lua.\nWith these functions you can also control \nthe collector directly (e.g., stop and restart it).\n\n\n\n<h3>2.10.1 - <a name=\"2.10.1\">Garbage-Collection Metamethods</a></h3>\n\n<p>\nUsing the C&nbsp;API,\nyou can set garbage-collector metamethods for userdata (see <a href=\"#2.8\">&sect;2.8</a>).\nThese metamethods are also called <em>finalizers</em>.\nFinalizers allow you to coordinate Lua's garbage collection\nwith external resource management\n(such as closing files, network or database connections,\nor freeing your own memory).\n\n\n<p>\nGarbage userdata with a field <code>__gc</code> in their metatables are not\ncollected immediately by the garbage collector.\nInstead, Lua puts them in a list.\nAfter the collection,\nLua does the equivalent of the following function\nfor each userdata in that list:\n\n<pre>\n     function gc_event (udata)\n       local h = metatable(udata).__gc\n       if h then\n         h(udata)\n       end\n     end\n</pre>\n\n<p>\nAt the end of each garbage-collection cycle,\nthe finalizers for userdata are called in <em>reverse</em>\norder of their creation,\namong those collected in that cycle.\nThat is, the first finalizer to be called is the one associated\nwith the userdata created last in the program.\nThe userdata itself is freed only in the next garbage-collection cycle.\n\n\n\n\n\n<h3>2.10.2 - <a name=\"2.10.2\">Weak Tables</a></h3>\n\n<p>\nA <em>weak table</em> is a table whose elements are\n<em>weak references</em>.\nA weak reference is ignored by the garbage collector.\nIn other words,\nif the only references to an object are weak references,\nthen the garbage collector will collect this object.\n\n\n<p>\nA weak table can have weak keys, weak values, or both.\nA table with weak keys allows the collection of its keys,\nbut prevents the collection of its values.\nA table with both weak keys and weak values allows the collection of\nboth keys and values.\nIn any case, if either the key or the value is collected,\nthe whole pair is removed from the table.\nThe weakness of a table is controlled by the\n<code>__mode</code> field of its metatable.\nIf the <code>__mode</code> field is a string containing the character&nbsp;'<code>k</code>',\nthe keys in the table are weak.\nIf <code>__mode</code> contains '<code>v</code>',\nthe values in the table are weak.\n\n\n<p>\nAfter you use a table as a metatable,\nyou should not change the value of its <code>__mode</code> field.\nOtherwise, the weak behavior of the tables controlled by this\nmetatable is undefined.\n\n\n\n\n\n\n\n<h2>2.11 - <a name=\"2.11\">Coroutines</a></h2>\n\n<p>\nLua supports coroutines,\nalso called <em>collaborative multithreading</em>.\nA coroutine in Lua represents an independent thread of execution.\nUnlike threads in multithread systems, however,\na coroutine only suspends its execution by explicitly calling\na yield function.\n\n\n<p>\nYou create a coroutine with a call to <a href=\"#pdf-coroutine.create\"><code>coroutine.create</code></a>.\nIts sole argument is a function\nthat is the main function of the coroutine.\nThe <code>create</code> function only creates a new coroutine and\nreturns a handle to it (an object of type <em>thread</em>);\nit does not start the coroutine execution.\n\n\n<p>\nWhen you first call <a href=\"#pdf-coroutine.resume\"><code>coroutine.resume</code></a>,\npassing as its first argument\na thread returned by <a href=\"#pdf-coroutine.create\"><code>coroutine.create</code></a>,\nthe coroutine starts its execution,\nat the first line of its main function.\nExtra arguments passed to <a href=\"#pdf-coroutine.resume\"><code>coroutine.resume</code></a> are passed on\nto the coroutine main function.\nAfter the coroutine starts running,\nit runs until it terminates or <em>yields</em>.\n\n\n<p>\nA coroutine can terminate its execution in two ways:\nnormally, when its main function returns\n(explicitly or implicitly, after the last instruction);\nand abnormally, if there is an unprotected error.\nIn the first case, <a href=\"#pdf-coroutine.resume\"><code>coroutine.resume</code></a> returns <b>true</b>,\nplus any values returned by the coroutine main function.\nIn case of errors, <a href=\"#pdf-coroutine.resume\"><code>coroutine.resume</code></a> returns <b>false</b>\nplus an error message.\n\n\n<p>\nA coroutine yields by calling <a href=\"#pdf-coroutine.yield\"><code>coroutine.yield</code></a>.\nWhen a coroutine yields,\nthe corresponding <a href=\"#pdf-coroutine.resume\"><code>coroutine.resume</code></a> returns immediately,\neven if the yield happens inside nested function calls\n(that is, not in the main function,\nbut in a function directly or indirectly called by the main function).\nIn the case of a yield, <a href=\"#pdf-coroutine.resume\"><code>coroutine.resume</code></a> also returns <b>true</b>,\nplus any values passed to <a href=\"#pdf-coroutine.yield\"><code>coroutine.yield</code></a>.\nThe next time you resume the same coroutine,\nit continues its execution from the point where it yielded,\nwith the call to <a href=\"#pdf-coroutine.yield\"><code>coroutine.yield</code></a> returning any extra\narguments passed to <a href=\"#pdf-coroutine.resume\"><code>coroutine.resume</code></a>.\n\n\n<p>\nLike <a href=\"#pdf-coroutine.create\"><code>coroutine.create</code></a>,\nthe <a href=\"#pdf-coroutine.wrap\"><code>coroutine.wrap</code></a> function also creates a coroutine,\nbut instead of returning the coroutine itself,\nit returns a function that, when called, resumes the coroutine.\nAny arguments passed to this function\ngo as extra arguments to <a href=\"#pdf-coroutine.resume\"><code>coroutine.resume</code></a>.\n<a href=\"#pdf-coroutine.wrap\"><code>coroutine.wrap</code></a> returns all the values returned by <a href=\"#pdf-coroutine.resume\"><code>coroutine.resume</code></a>,\nexcept the first one (the boolean error code).\nUnlike <a href=\"#pdf-coroutine.resume\"><code>coroutine.resume</code></a>,\n<a href=\"#pdf-coroutine.wrap\"><code>coroutine.wrap</code></a> does not catch errors;\nany error is propagated to the caller.\n\n\n<p>\nAs an example,\nconsider the following code:\n\n<pre>\n     function foo (a)\n       print(\"foo\", a)\n       return coroutine.yield(2*a)\n     end\n     \n     co = coroutine.create(function (a,b)\n           print(\"co-body\", a, b)\n           local r = foo(a+1)\n           print(\"co-body\", r)\n           local r, s = coroutine.yield(a+b, a-b)\n           print(\"co-body\", r, s)\n           return b, \"end\"\n     end)\n            \n     print(\"main\", coroutine.resume(co, 1, 10))\n     print(\"main\", coroutine.resume(co, \"r\"))\n     print(\"main\", coroutine.resume(co, \"x\", \"y\"))\n     print(\"main\", coroutine.resume(co, \"x\", \"y\"))\n</pre><p>\nWhen you run it, it produces the following output:\n\n<pre>\n     co-body 1       10\n     foo     2\n     \n     main    true    4\n     co-body r\n     main    true    11      -9\n     co-body x       y\n     main    true    10      end\n     main    false   cannot resume dead coroutine\n</pre>\n\n\n\n\n<h1>3 - <a name=\"3\">The Application Program Interface</a></h1>\n\n<p>\n\nThis section describes the C&nbsp;API for Lua, that is,\nthe set of C&nbsp;functions available to the host program to communicate\nwith Lua.\nAll API functions and related types and constants\nare declared in the header file <a name=\"pdf-lua.h\"><code>lua.h</code></a>.\n\n\n<p>\nEven when we use the term \"function\",\nany facility in the API may be provided as a macro instead.\nAll such macros use each of their arguments exactly once\n(except for the first argument, which is always a Lua state),\nand so do not generate any hidden side-effects.\n\n\n<p>\nAs in most C&nbsp;libraries,\nthe Lua API functions do not check their arguments for validity or consistency.\nHowever, you can change this behavior by compiling Lua\nwith a proper definition for the macro <a name=\"pdf-luai_apicheck\"><code>luai_apicheck</code></a>,\nin file <code>luaconf.h</code>.\n\n\n\n<h2>3.1 - <a name=\"3.1\">The Stack</a></h2>\n\n<p>\nLua uses a <em>virtual stack</em> to pass values to and from C.\nEach element in this stack represents a Lua value\n(<b>nil</b>, number, string, etc.).\n\n\n<p>\nWhenever Lua calls C, the called function gets a new stack,\nwhich is independent of previous stacks and of stacks of\nC&nbsp;functions that are still active.\nThis stack initially contains any arguments to the C&nbsp;function\nand it is where the C&nbsp;function pushes its results\nto be returned to the caller (see <a href=\"#lua_CFunction\"><code>lua_CFunction</code></a>).\n\n\n<p>\nFor convenience,\nmost query operations in the API do not follow a strict stack discipline.\nInstead, they can refer to any element in the stack\nby using an <em>index</em>:\nA positive index represents an <em>absolute</em> stack position\n(starting at&nbsp;1);\na negative index represents an <em>offset</em> relative to the top of the stack.\nMore specifically, if the stack has <em>n</em> elements,\nthen index&nbsp;1 represents the first element\n(that is, the element that was pushed onto the stack first)\nand\nindex&nbsp;<em>n</em> represents the last element;\nindex&nbsp;-1 also represents the last element\n(that is, the element at the&nbsp;top)\nand index <em>-n</em> represents the first element.\nWe say that an index is <em>valid</em>\nif it lies between&nbsp;1 and the stack top\n(that is, if <code>1 &le; abs(index) &le; top</code>).\n \n\n\n\n\n\n<h2>3.2 - <a name=\"3.2\">Stack Size</a></h2>\n\n<p>\nWhen you interact with Lua API,\nyou are responsible for ensuring consistency.\nIn particular,\n<em>you are responsible for controlling stack overflow</em>.\nYou can use the function <a href=\"#lua_checkstack\"><code>lua_checkstack</code></a>\nto grow the stack size.\n\n\n<p>\nWhenever Lua calls C,\nit ensures that at least <a name=\"pdf-LUA_MINSTACK\"><code>LUA_MINSTACK</code></a> stack positions are available.\n<code>LUA_MINSTACK</code> is defined as 20,\nso that usually you do not have to worry about stack space\nunless your code has loops pushing elements onto the stack.\n\n\n<p>\nMost query functions accept as indices any value inside the\navailable stack space, that is, indices up to the maximum stack size\nyou have set through <a href=\"#lua_checkstack\"><code>lua_checkstack</code></a>.\nSuch indices are called <em>acceptable indices</em>.\nMore formally, we define an <em>acceptable index</em>\nas follows:\n\n<pre>\n     (index &lt; 0 &amp;&amp; abs(index) &lt;= top) ||\n     (index &gt; 0 &amp;&amp; index &lt;= stackspace)\n</pre><p>\nNote that 0 is never an acceptable index.\n\n\n\n\n\n<h2>3.3 - <a name=\"3.3\">Pseudo-Indices</a></h2>\n\n<p>\nUnless otherwise noted,\nany function that accepts valid indices can also be called with\n<em>pseudo-indices</em>,\nwhich represent some Lua values that are accessible to C&nbsp;code\nbut which are not in the stack.\nPseudo-indices are used to access the thread environment,\nthe function environment,\nthe registry,\nand the upvalues of a C&nbsp;function (see <a href=\"#3.4\">&sect;3.4</a>).\n\n\n<p>\nThe thread environment (where global variables live) is\nalways at pseudo-index <a name=\"pdf-LUA_GLOBALSINDEX\"><code>LUA_GLOBALSINDEX</code></a>.\nThe environment of the running C&nbsp;function is always\nat pseudo-index <a name=\"pdf-LUA_ENVIRONINDEX\"><code>LUA_ENVIRONINDEX</code></a>.\n\n\n<p>\nTo access and change the value of global variables,\nyou can use regular table operations over an environment table.\nFor instance, to access the value of a global variable, do\n\n<pre>\n     lua_getfield(L, LUA_GLOBALSINDEX, varname);\n</pre>\n\n\n\n\n<h2>3.4 - <a name=\"3.4\">C Closures</a></h2>\n\n<p>\nWhen a C&nbsp;function is created,\nit is possible to associate some values with it,\nthus creating a <em>C&nbsp;closure</em>;\nthese values are called <em>upvalues</em> and are\naccessible to the function whenever it is called\n(see <a href=\"#lua_pushcclosure\"><code>lua_pushcclosure</code></a>).\n\n\n<p>\nWhenever a C&nbsp;function is called,\nits upvalues are located at specific pseudo-indices.\nThese pseudo-indices are produced by the macro\n<a name=\"lua_upvalueindex\"><code>lua_upvalueindex</code></a>.\nThe first value associated with a function is at position\n<code>lua_upvalueindex(1)</code>, and so on.\nAny access to <code>lua_upvalueindex(<em>n</em>)</code>,\nwhere <em>n</em> is greater than the number of upvalues of the\ncurrent function (but not greater than 256),\nproduces an acceptable (but invalid) index.\n\n\n\n\n\n<h2>3.5 - <a name=\"3.5\">Registry</a></h2>\n\n<p>\nLua provides a <em>registry</em>,\na pre-defined table that can be used by any C&nbsp;code to\nstore whatever Lua value it needs to store.\nThis table is always located at pseudo-index\n<a name=\"pdf-LUA_REGISTRYINDEX\"><code>LUA_REGISTRYINDEX</code></a>.\nAny C&nbsp;library can store data into this table,\nbut it should take care to choose keys different from those used\nby other libraries, to avoid collisions.\nTypically, you should use as key a string containing your library name\nor a light userdata with the address of a C&nbsp;object in your code.\n\n\n<p>\nThe integer keys in the registry are used by the reference mechanism,\nimplemented by the auxiliary library,\nand therefore should not be used for other purposes.\n\n\n\n\n\n<h2>3.6 - <a name=\"3.6\">Error Handling in C</a></h2>\n\n<p>\nInternally, Lua uses the C <code>longjmp</code> facility to handle errors.\n(You can also choose to use exceptions if you use C++;\nsee file <code>luaconf.h</code>.)\nWhen Lua faces any error\n(such as memory allocation errors, type errors, syntax errors,\nand runtime errors)\nit <em>raises</em> an error;\nthat is, it does a long jump.\nA <em>protected environment</em> uses <code>setjmp</code>\nto set a recover point;\nany error jumps to the most recent active recover point.\n\n\n<p>\nMost functions in the API can throw an error,\nfor instance due to a memory allocation error.\nThe documentation for each function indicates whether\nit can throw errors.\n\n\n<p>\nInside a C&nbsp;function you can throw an error by calling <a href=\"#lua_error\"><code>lua_error</code></a>.\n\n\n\n\n\n<h2>3.7 - <a name=\"3.7\">Functions and Types</a></h2>\n\n<p>\nHere we list all functions and types from the C&nbsp;API in\nalphabetical order.\nEach function has an indicator like this:\n<span class=\"apii\">[-o, +p, <em>x</em>]</span>\n\n\n<p>\nThe first field, <code>o</code>,\nis how many elements the function pops from the stack.\nThe second field, <code>p</code>,\nis how many elements the function pushes onto the stack.\n(Any function always pushes its results after popping its arguments.)\nA field in the form <code>x|y</code> means the function can push (or pop)\n<code>x</code> or <code>y</code> elements,\ndepending on the situation;\nan interrogation mark '<code>?</code>' means that\nwe cannot know how many elements the function pops/pushes\nby looking only at its arguments\n(e.g., they may depend on what is on the stack).\nThe third field, <code>x</code>,\ntells whether the function may throw errors:\n'<code>-</code>' means the function never throws any error;\n'<code>m</code>' means the function may throw an error\nonly due to not enough memory;\n'<code>e</code>' means the function may throw other kinds of errors;\n'<code>v</code>' means the function may throw an error on purpose.\n\n\n\n<hr><h3><a name=\"lua_Alloc\"><code>lua_Alloc</code></a></h3>\n<pre>typedef void * (*lua_Alloc) (void *ud,\n                             void *ptr,\n                             size_t osize,\n                             size_t nsize);</pre>\n\n<p>\nThe type of the memory-allocation function used by Lua states.\nThe allocator function must provide a\nfunctionality similar to <code>realloc</code>,\nbut not exactly the same.\nIts arguments are\n<code>ud</code>, an opaque pointer passed to <a href=\"#lua_newstate\"><code>lua_newstate</code></a>;\n<code>ptr</code>, a pointer to the block being allocated/reallocated/freed;\n<code>osize</code>, the original size of the block;\n<code>nsize</code>, the new size of the block.\n<code>ptr</code> is <code>NULL</code> if and only if <code>osize</code> is zero.\nWhen <code>nsize</code> is zero, the allocator must return <code>NULL</code>;\nif <code>osize</code> is not zero,\nit should free the block pointed to by <code>ptr</code>.\nWhen <code>nsize</code> is not zero, the allocator returns <code>NULL</code>\nif and only if it cannot fill the request.\nWhen <code>nsize</code> is not zero and <code>osize</code> is zero,\nthe allocator should behave like <code>malloc</code>.\nWhen <code>nsize</code> and <code>osize</code> are not zero,\nthe allocator behaves like <code>realloc</code>.\nLua assumes that the allocator never fails when\n<code>osize &gt;= nsize</code>.\n\n\n<p>\nHere is a simple implementation for the allocator function.\nIt is used in the auxiliary library by <a href=\"#luaL_newstate\"><code>luaL_newstate</code></a>.\n\n<pre>\n     static void *l_alloc (void *ud, void *ptr, size_t osize,\n                                                size_t nsize) {\n       (void)ud;  (void)osize;  /* not used */\n       if (nsize == 0) {\n         free(ptr);\n         return NULL;\n       }\n       else\n         return realloc(ptr, nsize);\n     }\n</pre><p>\nThis code assumes\nthat <code>free(NULL)</code> has no effect and that\n<code>realloc(NULL, size)</code> is equivalent to <code>malloc(size)</code>.\nANSI&nbsp;C ensures both behaviors.\n\n\n\n\n\n<hr><h3><a name=\"lua_atpanic\"><code>lua_atpanic</code></a></h3><p>\n<span class=\"apii\">[-0, +0, <em>-</em>]</span>\n<pre>lua_CFunction lua_atpanic (lua_State *L, lua_CFunction panicf);</pre>\n\n<p>\nSets a new panic function and returns the old one.\n\n\n<p>\nIf an error happens outside any protected environment,\nLua calls a <em>panic function</em>\nand then calls <code>exit(EXIT_FAILURE)</code>,\nthus exiting the host application.\nYour panic function can avoid this exit by\nnever returning (e.g., doing a long jump).\n\n\n<p>\nThe panic function can access the error message at the top of the stack.\n\n\n\n\n\n<hr><h3><a name=\"lua_call\"><code>lua_call</code></a></h3><p>\n<span class=\"apii\">[-(nargs + 1), +nresults, <em>e</em>]</span>\n<pre>void lua_call (lua_State *L, int nargs, int nresults);</pre>\n\n<p>\nCalls a function.\n\n\n<p>\nTo call a function you must use the following protocol:\nfirst, the function to be called is pushed onto the stack;\nthen, the arguments to the function are pushed\nin direct order;\nthat is, the first argument is pushed first.\nFinally you call <a href=\"#lua_call\"><code>lua_call</code></a>;\n<code>nargs</code> is the number of arguments that you pushed onto the stack.\nAll arguments and the function value are popped from the stack\nwhen the function is called.\nThe function results are pushed onto the stack when the function returns.\nThe number of results is adjusted to <code>nresults</code>,\nunless <code>nresults</code> is <a name=\"pdf-LUA_MULTRET\"><code>LUA_MULTRET</code></a>.\nIn this case, <em>all</em> results from the function are pushed.\nLua takes care that the returned values fit into the stack space.\nThe function results are pushed onto the stack in direct order\n(the first result is pushed first),\nso that after the call the last result is on the top of the stack.\n\n\n<p>\nAny error inside the called function is propagated upwards\n(with a <code>longjmp</code>).\n\n\n<p>\nThe following example shows how the host program can do the\nequivalent to this Lua code:\n\n<pre>\n     a = f(\"how\", t.x, 14)\n</pre><p>\nHere it is in&nbsp;C:\n\n<pre>\n     lua_getfield(L, LUA_GLOBALSINDEX, \"f\"); /* function to be called */\n     lua_pushstring(L, \"how\");                        /* 1st argument */\n     lua_getfield(L, LUA_GLOBALSINDEX, \"t\");   /* table to be indexed */\n     lua_getfield(L, -1, \"x\");        /* push result of t.x (2nd arg) */\n     lua_remove(L, -2);                  /* remove 't' from the stack */\n     lua_pushinteger(L, 14);                          /* 3rd argument */\n     lua_call(L, 3, 1);     /* call 'f' with 3 arguments and 1 result */\n     lua_setfield(L, LUA_GLOBALSINDEX, \"a\");        /* set global 'a' */\n</pre><p>\nNote that the code above is \"balanced\":\nat its end, the stack is back to its original configuration.\nThis is considered good programming practice.\n\n\n\n\n\n<hr><h3><a name=\"lua_CFunction\"><code>lua_CFunction</code></a></h3>\n<pre>typedef int (*lua_CFunction) (lua_State *L);</pre>\n\n<p>\nType for C&nbsp;functions.\n\n\n<p>\nIn order to communicate properly with Lua,\na C&nbsp;function must use the following protocol,\nwhich defines the way parameters and results are passed:\na C&nbsp;function receives its arguments from Lua in its stack\nin direct order (the first argument is pushed first).\nSo, when the function starts,\n<code>lua_gettop(L)</code> returns the number of arguments received by the function.\nThe first argument (if any) is at index 1\nand its last argument is at index <code>lua_gettop(L)</code>.\nTo return values to Lua, a C&nbsp;function just pushes them onto the stack,\nin direct order (the first result is pushed first),\nand returns the number of results.\nAny other value in the stack below the results will be properly\ndiscarded by Lua.\nLike a Lua function, a C&nbsp;function called by Lua can also return\nmany results.\n\n\n<p>\nAs an example, the following function receives a variable number\nof numerical arguments and returns their average and sum:\n\n<pre>\n     static int foo (lua_State *L) {\n       int n = lua_gettop(L);    /* number of arguments */\n       lua_Number sum = 0;\n       int i;\n       for (i = 1; i &lt;= n; i++) {\n         if (!lua_isnumber(L, i)) {\n           lua_pushstring(L, \"incorrect argument\");\n           lua_error(L);\n         }\n         sum += lua_tonumber(L, i);\n       }\n       lua_pushnumber(L, sum/n);        /* first result */\n       lua_pushnumber(L, sum);         /* second result */\n       return 2;                   /* number of results */\n     }\n</pre>\n\n\n\n\n<hr><h3><a name=\"lua_checkstack\"><code>lua_checkstack</code></a></h3><p>\n<span class=\"apii\">[-0, +0, <em>m</em>]</span>\n<pre>int lua_checkstack (lua_State *L, int extra);</pre>\n\n<p>\nEnsures that there are at least <code>extra</code> free stack slots in the stack.\nIt returns false if it cannot grow the stack to that size.\nThis function never shrinks the stack;\nif the stack is already larger than the new size,\nit is left unchanged.\n\n\n\n\n\n<hr><h3><a name=\"lua_close\"><code>lua_close</code></a></h3><p>\n<span class=\"apii\">[-0, +0, <em>-</em>]</span>\n<pre>void lua_close (lua_State *L);</pre>\n\n<p>\nDestroys all objects in the given Lua state\n(calling the corresponding garbage-collection metamethods, if any)\nand frees all dynamic memory used by this state.\nOn several platforms, you may not need to call this function,\nbecause all resources are naturally released when the host program ends.\nOn the other hand, long-running programs,\nsuch as a daemon or a web server,\nmight need to release states as soon as they are not needed,\nto avoid growing too large.\n\n\n\n\n\n<hr><h3><a name=\"lua_concat\"><code>lua_concat</code></a></h3><p>\n<span class=\"apii\">[-n, +1, <em>e</em>]</span>\n<pre>void lua_concat (lua_State *L, int n);</pre>\n\n<p>\nConcatenates the <code>n</code> values at the top of the stack,\npops them, and leaves the result at the top.\nIf <code>n</code>&nbsp;is&nbsp;1, the result is the single value on the stack\n(that is, the function does nothing);\nif <code>n</code> is 0, the result is the empty string.\nConcatenation is performed following the usual semantics of Lua\n(see <a href=\"#2.5.4\">&sect;2.5.4</a>).\n\n\n\n\n\n<hr><h3><a name=\"lua_cpcall\"><code>lua_cpcall</code></a></h3><p>\n<span class=\"apii\">[-0, +(0|1), <em>-</em>]</span>\n<pre>int lua_cpcall (lua_State *L, lua_CFunction func, void *ud);</pre>\n\n<p>\nCalls the C&nbsp;function <code>func</code> in protected mode.\n<code>func</code> starts with only one element in its stack,\na light userdata containing <code>ud</code>.\nIn case of errors,\n<a href=\"#lua_cpcall\"><code>lua_cpcall</code></a> returns the same error codes as <a href=\"#lua_pcall\"><code>lua_pcall</code></a>,\nplus the error object on the top of the stack;\notherwise, it returns zero, and does not change the stack.\nAll values returned by <code>func</code> are discarded.\n\n\n\n\n\n<hr><h3><a name=\"lua_createtable\"><code>lua_createtable</code></a></h3><p>\n<span class=\"apii\">[-0, +1, <em>m</em>]</span>\n<pre>void lua_createtable (lua_State *L, int narr, int nrec);</pre>\n\n<p>\nCreates a new empty table and pushes it onto the stack.\nThe new table has space pre-allocated\nfor <code>narr</code> array elements and <code>nrec</code> non-array elements.\nThis pre-allocation is useful when you know exactly how many elements\nthe table will have.\nOtherwise you can use the function <a href=\"#lua_newtable\"><code>lua_newtable</code></a>.\n\n\n\n\n\n<hr><h3><a name=\"lua_dump\"><code>lua_dump</code></a></h3><p>\n<span class=\"apii\">[-0, +0, <em>m</em>]</span>\n<pre>int lua_dump (lua_State *L, lua_Writer writer, void *data);</pre>\n\n<p>\nDumps a function as a binary chunk.\nReceives a Lua function on the top of the stack\nand produces a binary chunk that,\nif loaded again,\nresults in a function equivalent to the one dumped.\nAs it produces parts of the chunk,\n<a href=\"#lua_dump\"><code>lua_dump</code></a> calls function <code>writer</code> (see <a href=\"#lua_Writer\"><code>lua_Writer</code></a>)\nwith the given <code>data</code>\nto write them.\n\n\n<p>\nThe value returned is the error code returned by the last\ncall to the writer;\n0&nbsp;means no errors.\n\n\n<p>\nThis function does not pop the Lua function from the stack.\n\n\n\n\n\n<hr><h3><a name=\"lua_equal\"><code>lua_equal</code></a></h3><p>\n<span class=\"apii\">[-0, +0, <em>e</em>]</span>\n<pre>int lua_equal (lua_State *L, int index1, int index2);</pre>\n\n<p>\nReturns 1 if the two values in acceptable indices <code>index1</code> and\n<code>index2</code> are equal,\nfollowing the semantics of the Lua <code>==</code> operator\n(that is, may call metamethods).\nOtherwise returns&nbsp;0.\nAlso returns&nbsp;0 if any of the indices is non valid.\n\n\n\n\n\n<hr><h3><a name=\"lua_error\"><code>lua_error</code></a></h3><p>\n<span class=\"apii\">[-1, +0, <em>v</em>]</span>\n<pre>int lua_error (lua_State *L);</pre>\n\n<p>\nGenerates a Lua error.\nThe error message (which can actually be a Lua value of any type)\nmust be on the stack top.\nThis function does a long jump,\nand therefore never returns.\n(see <a href=\"#luaL_error\"><code>luaL_error</code></a>).\n\n\n\n\n\n<hr><h3><a name=\"lua_gc\"><code>lua_gc</code></a></h3><p>\n<span class=\"apii\">[-0, +0, <em>e</em>]</span>\n<pre>int lua_gc (lua_State *L, int what, int data);</pre>\n\n<p>\nControls the garbage collector.\n\n\n<p>\nThis function performs several tasks,\naccording to the value of the parameter <code>what</code>:\n\n<ul>\n\n<li><b><code>LUA_GCSTOP</code>:</b>\nstops the garbage collector.\n</li>\n\n<li><b><code>LUA_GCRESTART</code>:</b>\nrestarts the garbage collector.\n</li>\n\n<li><b><code>LUA_GCCOLLECT</code>:</b>\nperforms a full garbage-collection cycle.\n</li>\n\n<li><b><code>LUA_GCCOUNT</code>:</b>\nreturns the current amount of memory (in Kbytes) in use by Lua.\n</li>\n\n<li><b><code>LUA_GCCOUNTB</code>:</b>\nreturns the remainder of dividing the current amount of bytes of\nmemory in use by Lua by 1024.\n</li>\n\n<li><b><code>LUA_GCSTEP</code>:</b>\nperforms an incremental step of garbage collection.\nThe step \"size\" is controlled by <code>data</code>\n(larger values mean more steps) in a non-specified way.\nIf you want to control the step size\nyou must experimentally tune the value of <code>data</code>.\nThe function returns 1 if the step finished a\ngarbage-collection cycle.\n</li>\n\n<li><b><code>LUA_GCSETPAUSE</code>:</b>\nsets <code>data</code> as the new value\nfor the <em>pause</em> of the collector (see <a href=\"#2.10\">&sect;2.10</a>).\nThe function returns the previous value of the pause.\n</li>\n\n<li><b><code>LUA_GCSETSTEPMUL</code>:</b>\nsets <code>data</code> as the new value for the <em>step multiplier</em> of\nthe collector (see <a href=\"#2.10\">&sect;2.10</a>).\nThe function returns the previous value of the step multiplier.\n</li>\n\n</ul>\n\n\n\n\n<hr><h3><a name=\"lua_getallocf\"><code>lua_getallocf</code></a></h3><p>\n<span class=\"apii\">[-0, +0, <em>-</em>]</span>\n<pre>lua_Alloc lua_getallocf (lua_State *L, void **ud);</pre>\n\n<p>\nReturns the memory-allocation function of a given state.\nIf <code>ud</code> is not <code>NULL</code>, Lua stores in <code>*ud</code> the\nopaque pointer passed to <a href=\"#lua_newstate\"><code>lua_newstate</code></a>.\n\n\n\n\n\n<hr><h3><a name=\"lua_getfenv\"><code>lua_getfenv</code></a></h3><p>\n<span class=\"apii\">[-0, +1, <em>-</em>]</span>\n<pre>void lua_getfenv (lua_State *L, int index);</pre>\n\n<p>\nPushes onto the stack the environment table of\nthe value at the given index.\n\n\n\n\n\n<hr><h3><a name=\"lua_getfield\"><code>lua_getfield</code></a></h3><p>\n<span class=\"apii\">[-0, +1, <em>e</em>]</span>\n<pre>void lua_getfield (lua_State *L, int index, const char *k);</pre>\n\n<p>\nPushes onto the stack the value <code>t[k]</code>,\nwhere <code>t</code> is the value at the given valid index.\nAs in Lua, this function may trigger a metamethod\nfor the \"index\" event (see <a href=\"#2.8\">&sect;2.8</a>).\n\n\n\n\n\n<hr><h3><a name=\"lua_getglobal\"><code>lua_getglobal</code></a></h3><p>\n<span class=\"apii\">[-0, +1, <em>e</em>]</span>\n<pre>void lua_getglobal (lua_State *L, const char *name);</pre>\n\n<p>\nPushes onto the stack the value of the global <code>name</code>.\nIt is defined as a macro:\n\n<pre>\n     #define lua_getglobal(L,s)  lua_getfield(L, LUA_GLOBALSINDEX, s)\n</pre>\n\n\n\n\n<hr><h3><a name=\"lua_getmetatable\"><code>lua_getmetatable</code></a></h3><p>\n<span class=\"apii\">[-0, +(0|1), <em>-</em>]</span>\n<pre>int lua_getmetatable (lua_State *L, int index);</pre>\n\n<p>\nPushes onto the stack the metatable of the value at the given\nacceptable index.\nIf the index is not valid,\nor if the value does not have a metatable,\nthe function returns&nbsp;0 and pushes nothing on the stack.\n\n\n\n\n\n<hr><h3><a name=\"lua_gettable\"><code>lua_gettable</code></a></h3><p>\n<span class=\"apii\">[-1, +1, <em>e</em>]</span>\n<pre>void lua_gettable (lua_State *L, int index);</pre>\n\n<p>\nPushes onto the stack the value <code>t[k]</code>,\nwhere <code>t</code> is the value at the given valid index\nand <code>k</code> is the value at the top of the stack.\n\n\n<p>\nThis function pops the key from the stack\n(putting the resulting value in its place).\nAs in Lua, this function may trigger a metamethod\nfor the \"index\" event (see <a href=\"#2.8\">&sect;2.8</a>).\n\n\n\n\n\n<hr><h3><a name=\"lua_gettop\"><code>lua_gettop</code></a></h3><p>\n<span class=\"apii\">[-0, +0, <em>-</em>]</span>\n<pre>int lua_gettop (lua_State *L);</pre>\n\n<p>\nReturns the index of the top element in the stack.\nBecause indices start at&nbsp;1,\nthis result is equal to the number of elements in the stack\n(and so 0&nbsp;means an empty stack).\n\n\n\n\n\n<hr><h3><a name=\"lua_insert\"><code>lua_insert</code></a></h3><p>\n<span class=\"apii\">[-1, +1, <em>-</em>]</span>\n<pre>void lua_insert (lua_State *L, int index);</pre>\n\n<p>\nMoves the top element into the given valid index,\nshifting up the elements above this index to open space.\nCannot be called with a pseudo-index,\nbecause a pseudo-index is not an actual stack position.\n\n\n\n\n\n<hr><h3><a name=\"lua_Integer\"><code>lua_Integer</code></a></h3>\n<pre>typedef ptrdiff_t lua_Integer;</pre>\n\n<p>\nThe type used by the Lua API to represent integral values.\n\n\n<p>\nBy default it is a <code>ptrdiff_t</code>,\nwhich is usually the largest signed integral type the machine handles\n\"comfortably\".\n\n\n\n\n\n<hr><h3><a name=\"lua_isboolean\"><code>lua_isboolean</code></a></h3><p>\n<span class=\"apii\">[-0, +0, <em>-</em>]</span>\n<pre>int lua_isboolean (lua_State *L, int index);</pre>\n\n<p>\nReturns 1 if the value at the given acceptable index has type boolean,\nand 0&nbsp;otherwise.\n\n\n\n\n\n<hr><h3><a name=\"lua_iscfunction\"><code>lua_iscfunction</code></a></h3><p>\n<span class=\"apii\">[-0, +0, <em>-</em>]</span>\n<pre>int lua_iscfunction (lua_State *L, int index);</pre>\n\n<p>\nReturns 1 if the value at the given acceptable index is a C&nbsp;function,\nand 0&nbsp;otherwise.\n\n\n\n\n\n<hr><h3><a name=\"lua_isfunction\"><code>lua_isfunction</code></a></h3><p>\n<span class=\"apii\">[-0, +0, <em>-</em>]</span>\n<pre>int lua_isfunction (lua_State *L, int index);</pre>\n\n<p>\nReturns 1 if the value at the given acceptable index is a function\n(either C or Lua), and 0&nbsp;otherwise.\n\n\n\n\n\n<hr><h3><a name=\"lua_islightuserdata\"><code>lua_islightuserdata</code></a></h3><p>\n<span class=\"apii\">[-0, +0, <em>-</em>]</span>\n<pre>int lua_islightuserdata (lua_State *L, int index);</pre>\n\n<p>\nReturns 1 if the value at the given acceptable index is a light userdata,\nand 0&nbsp;otherwise.\n\n\n\n\n\n<hr><h3><a name=\"lua_isnil\"><code>lua_isnil</code></a></h3><p>\n<span class=\"apii\">[-0, +0, <em>-</em>]</span>\n<pre>int lua_isnil (lua_State *L, int index);</pre>\n\n<p>\nReturns 1 if the value at the given acceptable index is <b>nil</b>,\nand 0&nbsp;otherwise.\n\n\n\n\n\n<hr><h3><a name=\"lua_isnone\"><code>lua_isnone</code></a></h3><p>\n<span class=\"apii\">[-0, +0, <em>-</em>]</span>\n<pre>int lua_isnone (lua_State *L, int index);</pre>\n\n<p>\nReturns 1 if the given acceptable index is not valid\n(that is, it refers to an element outside the current stack),\nand 0&nbsp;otherwise.\n\n\n\n\n\n<hr><h3><a name=\"lua_isnoneornil\"><code>lua_isnoneornil</code></a></h3><p>\n<span class=\"apii\">[-0, +0, <em>-</em>]</span>\n<pre>int lua_isnoneornil (lua_State *L, int index);</pre>\n\n<p>\nReturns 1 if the given acceptable index is not valid\n(that is, it refers to an element outside the current stack)\nor if the value at this index is <b>nil</b>,\nand 0&nbsp;otherwise.\n\n\n\n\n\n<hr><h3><a name=\"lua_isnumber\"><code>lua_isnumber</code></a></h3><p>\n<span class=\"apii\">[-0, +0, <em>-</em>]</span>\n<pre>int lua_isnumber (lua_State *L, int index);</pre>\n\n<p>\nReturns 1 if the value at the given acceptable index is a number\nor a string convertible to a number,\nand 0&nbsp;otherwise.\n\n\n\n\n\n<hr><h3><a name=\"lua_isstring\"><code>lua_isstring</code></a></h3><p>\n<span class=\"apii\">[-0, +0, <em>-</em>]</span>\n<pre>int lua_isstring (lua_State *L, int index);</pre>\n\n<p>\nReturns 1 if the value at the given acceptable index is a string\nor a number (which is always convertible to a string),\nand 0&nbsp;otherwise.\n\n\n\n\n\n<hr><h3><a name=\"lua_istable\"><code>lua_istable</code></a></h3><p>\n<span class=\"apii\">[-0, +0, <em>-</em>]</span>\n<pre>int lua_istable (lua_State *L, int index);</pre>\n\n<p>\nReturns 1 if the value at the given acceptable index is a table,\nand 0&nbsp;otherwise.\n\n\n\n\n\n<hr><h3><a name=\"lua_isthread\"><code>lua_isthread</code></a></h3><p>\n<span class=\"apii\">[-0, +0, <em>-</em>]</span>\n<pre>int lua_isthread (lua_State *L, int index);</pre>\n\n<p>\nReturns 1 if the value at the given acceptable index is a thread,\nand 0&nbsp;otherwise.\n\n\n\n\n\n<hr><h3><a name=\"lua_isuserdata\"><code>lua_isuserdata</code></a></h3><p>\n<span class=\"apii\">[-0, +0, <em>-</em>]</span>\n<pre>int lua_isuserdata (lua_State *L, int index);</pre>\n\n<p>\nReturns 1 if the value at the given acceptable index is a userdata\n(either full or light), and 0&nbsp;otherwise.\n\n\n\n\n\n<hr><h3><a name=\"lua_lessthan\"><code>lua_lessthan</code></a></h3><p>\n<span class=\"apii\">[-0, +0, <em>e</em>]</span>\n<pre>int lua_lessthan (lua_State *L, int index1, int index2);</pre>\n\n<p>\nReturns 1 if the value at acceptable index <code>index1</code> is smaller\nthan the value at acceptable index <code>index2</code>,\nfollowing the semantics of the Lua <code>&lt;</code> operator\n(that is, may call metamethods).\nOtherwise returns&nbsp;0.\nAlso returns&nbsp;0 if any of the indices is non valid.\n\n\n\n\n\n<hr><h3><a name=\"lua_load\"><code>lua_load</code></a></h3><p>\n<span class=\"apii\">[-0, +1, <em>-</em>]</span>\n<pre>int lua_load (lua_State *L,\n              lua_Reader reader,\n              void *data,\n              const char *chunkname);</pre>\n\n<p>\nLoads a Lua chunk.\nIf there are no errors,\n<a href=\"#lua_load\"><code>lua_load</code></a> pushes the compiled chunk as a Lua\nfunction on top of the stack.\nOtherwise, it pushes an error message.\nThe return values of <a href=\"#lua_load\"><code>lua_load</code></a> are:\n\n<ul>\n\n<li><b>0:</b> no errors;</li>\n\n<li><b><a name=\"pdf-LUA_ERRSYNTAX\"><code>LUA_ERRSYNTAX</code></a>:</b>\nsyntax error during pre-compilation;</li>\n\n<li><b><a href=\"#pdf-LUA_ERRMEM\"><code>LUA_ERRMEM</code></a>:</b>\nmemory allocation error.</li>\n\n</ul>\n\n<p>\nThis function only loads a chunk;\nit does not run it.\n\n\n<p>\n<a href=\"#lua_load\"><code>lua_load</code></a> automatically detects whether the chunk is text or binary,\nand loads it accordingly (see program <code>luac</code>).\n\n\n<p>\nThe <a href=\"#lua_load\"><code>lua_load</code></a> function uses a user-supplied <code>reader</code> function\nto read the chunk (see <a href=\"#lua_Reader\"><code>lua_Reader</code></a>).\nThe <code>data</code> argument is an opaque value passed to the reader function.\n\n\n<p>\nThe <code>chunkname</code> argument gives a name to the chunk,\nwhich is used for error messages and in debug information (see <a href=\"#3.8\">&sect;3.8</a>).\n\n\n\n\n\n<hr><h3><a name=\"lua_newstate\"><code>lua_newstate</code></a></h3><p>\n<span class=\"apii\">[-0, +0, <em>-</em>]</span>\n<pre>lua_State *lua_newstate (lua_Alloc f, void *ud);</pre>\n\n<p>\nCreates a new, independent state.\nReturns <code>NULL</code> if cannot create the state\n(due to lack of memory).\nThe argument <code>f</code> is the allocator function;\nLua does all memory allocation for this state through this function.\nThe second argument, <code>ud</code>, is an opaque pointer that Lua\nsimply passes to the allocator in every call.\n\n\n\n\n\n<hr><h3><a name=\"lua_newtable\"><code>lua_newtable</code></a></h3><p>\n<span class=\"apii\">[-0, +1, <em>m</em>]</span>\n<pre>void lua_newtable (lua_State *L);</pre>\n\n<p>\nCreates a new empty table and pushes it onto the stack.\nIt is equivalent to <code>lua_createtable(L, 0, 0)</code>.\n\n\n\n\n\n<hr><h3><a name=\"lua_newthread\"><code>lua_newthread</code></a></h3><p>\n<span class=\"apii\">[-0, +1, <em>m</em>]</span>\n<pre>lua_State *lua_newthread (lua_State *L);</pre>\n\n<p>\nCreates a new thread, pushes it on the stack,\nand returns a pointer to a <a href=\"#lua_State\"><code>lua_State</code></a> that represents this new thread.\nThe new state returned by this function shares with the original state\nall global objects (such as tables),\nbut has an independent execution stack.\n\n\n<p>\nThere is no explicit function to close or to destroy a thread.\nThreads are subject to garbage collection,\nlike any Lua object.\n\n\n\n\n\n<hr><h3><a name=\"lua_newuserdata\"><code>lua_newuserdata</code></a></h3><p>\n<span class=\"apii\">[-0, +1, <em>m</em>]</span>\n<pre>void *lua_newuserdata (lua_State *L, size_t size);</pre>\n\n<p>\nThis function allocates a new block of memory with the given size,\npushes onto the stack a new full userdata with the block address,\nand returns this address.\n\n\n<p>\nUserdata represent C&nbsp;values in Lua.\nA <em>full userdata</em> represents a block of memory.\nIt is an object (like a table):\nyou must create it, it can have its own metatable,\nand you can detect when it is being collected.\nA full userdata is only equal to itself (under raw equality).\n\n\n<p>\nWhen Lua collects a full userdata with a <code>gc</code> metamethod,\nLua calls the metamethod and marks the userdata as finalized.\nWhen this userdata is collected again then\nLua frees its corresponding memory.\n\n\n\n\n\n<hr><h3><a name=\"lua_next\"><code>lua_next</code></a></h3><p>\n<span class=\"apii\">[-1, +(2|0), <em>e</em>]</span>\n<pre>int lua_next (lua_State *L, int index);</pre>\n\n<p>\nPops a key from the stack,\nand pushes a key-value pair from the table at the given index\n(the \"next\" pair after the given key).\nIf there are no more elements in the table,\nthen <a href=\"#lua_next\"><code>lua_next</code></a> returns 0 (and pushes nothing).\n\n\n<p>\nA typical traversal looks like this:\n\n<pre>\n     /* table is in the stack at index 't' */\n     lua_pushnil(L);  /* first key */\n     while (lua_next(L, t) != 0) {\n       /* uses 'key' (at index -2) and 'value' (at index -1) */\n       printf(\"%s - %s\\n\",\n              lua_typename(L, lua_type(L, -2)),\n              lua_typename(L, lua_type(L, -1)));\n       /* removes 'value'; keeps 'key' for next iteration */\n       lua_pop(L, 1);\n     }\n</pre>\n\n<p>\nWhile traversing a table,\ndo not call <a href=\"#lua_tolstring\"><code>lua_tolstring</code></a> directly on a key,\nunless you know that the key is actually a string.\nRecall that <a href=\"#lua_tolstring\"><code>lua_tolstring</code></a> <em>changes</em>\nthe value at the given index;\nthis confuses the next call to <a href=\"#lua_next\"><code>lua_next</code></a>.\n\n\n\n\n\n<hr><h3><a name=\"lua_Number\"><code>lua_Number</code></a></h3>\n<pre>typedef double lua_Number;</pre>\n\n<p>\nThe type of numbers in Lua.\nBy default, it is double, but that can be changed in <code>luaconf.h</code>.\n\n\n<p>\nThrough the configuration file you can change\nLua to operate with another type for numbers (e.g., float or long).\n\n\n\n\n\n<hr><h3><a name=\"lua_objlen\"><code>lua_objlen</code></a></h3><p>\n<span class=\"apii\">[-0, +0, <em>-</em>]</span>\n<pre>size_t lua_objlen (lua_State *L, int index);</pre>\n\n<p>\nReturns the \"length\" of the value at the given acceptable index:\nfor strings, this is the string length;\nfor tables, this is the result of the length operator ('<code>#</code>');\nfor userdata, this is the size of the block of memory allocated\nfor the userdata;\nfor other values, it is&nbsp;0.\n\n\n\n\n\n<hr><h3><a name=\"lua_pcall\"><code>lua_pcall</code></a></h3><p>\n<span class=\"apii\">[-(nargs + 1), +(nresults|1), <em>-</em>]</span>\n<pre>int lua_pcall (lua_State *L, int nargs, int nresults, int errfunc);</pre>\n\n<p>\nCalls a function in protected mode.\n\n\n<p>\nBoth <code>nargs</code> and <code>nresults</code> have the same meaning as\nin <a href=\"#lua_call\"><code>lua_call</code></a>.\nIf there are no errors during the call,\n<a href=\"#lua_pcall\"><code>lua_pcall</code></a> behaves exactly like <a href=\"#lua_call\"><code>lua_call</code></a>.\nHowever, if there is any error,\n<a href=\"#lua_pcall\"><code>lua_pcall</code></a> catches it,\npushes a single value on the stack (the error message),\nand returns an error code.\nLike <a href=\"#lua_call\"><code>lua_call</code></a>,\n<a href=\"#lua_pcall\"><code>lua_pcall</code></a> always removes the function\nand its arguments from the stack.\n\n\n<p>\nIf <code>errfunc</code> is 0,\nthen the error message returned on the stack\nis exactly the original error message.\nOtherwise, <code>errfunc</code> is the stack index of an\n<em>error handler function</em>.\n(In the current implementation, this index cannot be a pseudo-index.)\nIn case of runtime errors,\nthis function will be called with the error message\nand its return value will be the message returned on the stack by <a href=\"#lua_pcall\"><code>lua_pcall</code></a>.\n\n\n<p>\nTypically, the error handler function is used to add more debug\ninformation to the error message, such as a stack traceback.\nSuch information cannot be gathered after the return of <a href=\"#lua_pcall\"><code>lua_pcall</code></a>,\nsince by then the stack has unwound.\n\n\n<p>\nThe <a href=\"#lua_pcall\"><code>lua_pcall</code></a> function returns 0 in case of success\nor one of the following error codes\n(defined in <code>lua.h</code>):\n\n<ul>\n\n<li><b><a name=\"pdf-LUA_ERRRUN\"><code>LUA_ERRRUN</code></a>:</b>\na runtime error.\n</li>\n\n<li><b><a name=\"pdf-LUA_ERRMEM\"><code>LUA_ERRMEM</code></a>:</b>\nmemory allocation error.\nFor such errors, Lua does not call the error handler function.\n</li>\n\n<li><b><a name=\"pdf-LUA_ERRERR\"><code>LUA_ERRERR</code></a>:</b>\nerror while running the error handler function.\n</li>\n\n</ul>\n\n\n\n\n<hr><h3><a name=\"lua_pop\"><code>lua_pop</code></a></h3><p>\n<span class=\"apii\">[-n, +0, <em>-</em>]</span>\n<pre>void lua_pop (lua_State *L, int n);</pre>\n\n<p>\nPops <code>n</code> elements from the stack.\n\n\n\n\n\n<hr><h3><a name=\"lua_pushboolean\"><code>lua_pushboolean</code></a></h3><p>\n<span class=\"apii\">[-0, +1, <em>-</em>]</span>\n<pre>void lua_pushboolean (lua_State *L, int b);</pre>\n\n<p>\nPushes a boolean value with value <code>b</code> onto the stack.\n\n\n\n\n\n<hr><h3><a name=\"lua_pushcclosure\"><code>lua_pushcclosure</code></a></h3><p>\n<span class=\"apii\">[-n, +1, <em>m</em>]</span>\n<pre>void lua_pushcclosure (lua_State *L, lua_CFunction fn, int n);</pre>\n\n<p>\nPushes a new C&nbsp;closure onto the stack.\n\n\n<p>\nWhen a C&nbsp;function is created,\nit is possible to associate some values with it,\nthus creating a C&nbsp;closure (see <a href=\"#3.4\">&sect;3.4</a>);\nthese values are then accessible to the function whenever it is called.\nTo associate values with a C&nbsp;function,\nfirst these values should be pushed onto the stack\n(when there are multiple values, the first value is pushed first).\nThen <a href=\"#lua_pushcclosure\"><code>lua_pushcclosure</code></a>\nis called to create and push the C&nbsp;function onto the stack,\nwith the argument <code>n</code> telling how many values should be\nassociated with the function.\n<a href=\"#lua_pushcclosure\"><code>lua_pushcclosure</code></a> also pops these values from the stack.\n\n\n<p>\nThe maximum value for <code>n</code> is 255.\n\n\n\n\n\n<hr><h3><a name=\"lua_pushcfunction\"><code>lua_pushcfunction</code></a></h3><p>\n<span class=\"apii\">[-0, +1, <em>m</em>]</span>\n<pre>void lua_pushcfunction (lua_State *L, lua_CFunction f);</pre>\n\n<p>\nPushes a C&nbsp;function onto the stack.\nThis function receives a pointer to a C function\nand pushes onto the stack a Lua value of type <code>function</code> that,\nwhen called, invokes the corresponding C&nbsp;function.\n\n\n<p>\nAny function to be registered in Lua must\nfollow the correct protocol to receive its parameters\nand return its results (see <a href=\"#lua_CFunction\"><code>lua_CFunction</code></a>).\n\n\n<p>\n<code>lua_pushcfunction</code> is defined as a macro:\n\n<pre>\n     #define lua_pushcfunction(L,f)  lua_pushcclosure(L,f,0)\n</pre>\n\n\n\n\n<hr><h3><a name=\"lua_pushfstring\"><code>lua_pushfstring</code></a></h3><p>\n<span class=\"apii\">[-0, +1, <em>m</em>]</span>\n<pre>const char *lua_pushfstring (lua_State *L, const char *fmt, ...);</pre>\n\n<p>\nPushes onto the stack a formatted string\nand returns a pointer to this string.\nIt is similar to the C&nbsp;function <code>sprintf</code>,\nbut has some important differences:\n\n<ul>\n\n<li>\nYou do not have to allocate space for the result:\nthe result is a Lua string and Lua takes care of memory allocation\n(and deallocation, through garbage collection).\n</li>\n\n<li>\nThe conversion specifiers are quite restricted.\nThere are no flags, widths, or precisions.\nThe conversion specifiers can only be\n'<code>%%</code>' (inserts a '<code>%</code>' in the string),\n'<code>%s</code>' (inserts a zero-terminated string, with no size restrictions),\n'<code>%f</code>' (inserts a <a href=\"#lua_Number\"><code>lua_Number</code></a>),\n'<code>%p</code>' (inserts a pointer as a hexadecimal numeral),\n'<code>%d</code>' (inserts an <code>int</code>), and\n'<code>%c</code>' (inserts an <code>int</code> as a character).\n</li>\n\n</ul>\n\n\n\n\n<hr><h3><a name=\"lua_pushinteger\"><code>lua_pushinteger</code></a></h3><p>\n<span class=\"apii\">[-0, +1, <em>-</em>]</span>\n<pre>void lua_pushinteger (lua_State *L, lua_Integer n);</pre>\n\n<p>\nPushes a number with value <code>n</code> onto the stack.\n\n\n\n\n\n<hr><h3><a name=\"lua_pushlightuserdata\"><code>lua_pushlightuserdata</code></a></h3><p>\n<span class=\"apii\">[-0, +1, <em>-</em>]</span>\n<pre>void lua_pushlightuserdata (lua_State *L, void *p);</pre>\n\n<p>\nPushes a light userdata onto the stack.\n\n\n<p>\nUserdata represent C&nbsp;values in Lua.\nA <em>light userdata</em> represents a pointer.\nIt is a value (like a number):\nyou do not create it, it has no individual metatable,\nand it is not collected (as it was never created).\nA light userdata is equal to \"any\"\nlight userdata with the same C&nbsp;address.\n\n\n\n\n\n<hr><h3><a name=\"lua_pushliteral\"><code>lua_pushliteral</code></a></h3><p>\n<span class=\"apii\">[-0, +1, <em>m</em>]</span>\n<pre>void lua_pushliteral (lua_State *L, const char *s);</pre>\n\n<p>\nThis macro is equivalent to <a href=\"#lua_pushlstring\"><code>lua_pushlstring</code></a>,\nbut can be used only when <code>s</code> is a literal string.\nIn these cases, it automatically provides the string length.\n\n\n\n\n\n<hr><h3><a name=\"lua_pushlstring\"><code>lua_pushlstring</code></a></h3><p>\n<span class=\"apii\">[-0, +1, <em>m</em>]</span>\n<pre>void lua_pushlstring (lua_State *L, const char *s, size_t len);</pre>\n\n<p>\nPushes the string pointed to by <code>s</code> with size <code>len</code>\nonto the stack.\nLua makes (or reuses) an internal copy of the given string,\nso the memory at <code>s</code> can be freed or reused immediately after\nthe function returns.\nThe string can contain embedded zeros.\n\n\n\n\n\n<hr><h3><a name=\"lua_pushnil\"><code>lua_pushnil</code></a></h3><p>\n<span class=\"apii\">[-0, +1, <em>-</em>]</span>\n<pre>void lua_pushnil (lua_State *L);</pre>\n\n<p>\nPushes a nil value onto the stack.\n\n\n\n\n\n<hr><h3><a name=\"lua_pushnumber\"><code>lua_pushnumber</code></a></h3><p>\n<span class=\"apii\">[-0, +1, <em>-</em>]</span>\n<pre>void lua_pushnumber (lua_State *L, lua_Number n);</pre>\n\n<p>\nPushes a number with value <code>n</code> onto the stack.\n\n\n\n\n\n<hr><h3><a name=\"lua_pushstring\"><code>lua_pushstring</code></a></h3><p>\n<span class=\"apii\">[-0, +1, <em>m</em>]</span>\n<pre>void lua_pushstring (lua_State *L, const char *s);</pre>\n\n<p>\nPushes the zero-terminated string pointed to by <code>s</code>\nonto the stack.\nLua makes (or reuses) an internal copy of the given string,\nso the memory at <code>s</code> can be freed or reused immediately after\nthe function returns.\nThe string cannot contain embedded zeros;\nit is assumed to end at the first zero.\n\n\n\n\n\n<hr><h3><a name=\"lua_pushthread\"><code>lua_pushthread</code></a></h3><p>\n<span class=\"apii\">[-0, +1, <em>-</em>]</span>\n<pre>int lua_pushthread (lua_State *L);</pre>\n\n<p>\nPushes the thread represented by <code>L</code> onto the stack.\nReturns 1 if this thread is the main thread of its state.\n\n\n\n\n\n<hr><h3><a name=\"lua_pushvalue\"><code>lua_pushvalue</code></a></h3><p>\n<span class=\"apii\">[-0, +1, <em>-</em>]</span>\n<pre>void lua_pushvalue (lua_State *L, int index);</pre>\n\n<p>\nPushes a copy of the element at the given valid index\nonto the stack.\n\n\n\n\n\n<hr><h3><a name=\"lua_pushvfstring\"><code>lua_pushvfstring</code></a></h3><p>\n<span class=\"apii\">[-0, +1, <em>m</em>]</span>\n<pre>const char *lua_pushvfstring (lua_State *L,\n                              const char *fmt,\n                              va_list argp);</pre>\n\n<p>\nEquivalent to <a href=\"#lua_pushfstring\"><code>lua_pushfstring</code></a>, except that it receives a <code>va_list</code>\ninstead of a variable number of arguments.\n\n\n\n\n\n<hr><h3><a name=\"lua_rawequal\"><code>lua_rawequal</code></a></h3><p>\n<span class=\"apii\">[-0, +0, <em>-</em>]</span>\n<pre>int lua_rawequal (lua_State *L, int index1, int index2);</pre>\n\n<p>\nReturns 1 if the two values in acceptable indices <code>index1</code> and\n<code>index2</code> are primitively equal\n(that is, without calling metamethods).\nOtherwise returns&nbsp;0.\nAlso returns&nbsp;0 if any of the indices are non valid.\n\n\n\n\n\n<hr><h3><a name=\"lua_rawget\"><code>lua_rawget</code></a></h3><p>\n<span class=\"apii\">[-1, +1, <em>-</em>]</span>\n<pre>void lua_rawget (lua_State *L, int index);</pre>\n\n<p>\nSimilar to <a href=\"#lua_gettable\"><code>lua_gettable</code></a>, but does a raw access\n(i.e., without metamethods).\n\n\n\n\n\n<hr><h3><a name=\"lua_rawgeti\"><code>lua_rawgeti</code></a></h3><p>\n<span class=\"apii\">[-0, +1, <em>-</em>]</span>\n<pre>void lua_rawgeti (lua_State *L, int index, int n);</pre>\n\n<p>\nPushes onto the stack the value <code>t[n]</code>,\nwhere <code>t</code> is the value at the given valid index.\nThe access is raw;\nthat is, it does not invoke metamethods.\n\n\n\n\n\n<hr><h3><a name=\"lua_rawset\"><code>lua_rawset</code></a></h3><p>\n<span class=\"apii\">[-2, +0, <em>m</em>]</span>\n<pre>void lua_rawset (lua_State *L, int index);</pre>\n\n<p>\nSimilar to <a href=\"#lua_settable\"><code>lua_settable</code></a>, but does a raw assignment\n(i.e., without metamethods).\n\n\n\n\n\n<hr><h3><a name=\"lua_rawseti\"><code>lua_rawseti</code></a></h3><p>\n<span class=\"apii\">[-1, +0, <em>m</em>]</span>\n<pre>void lua_rawseti (lua_State *L, int index, int n);</pre>\n\n<p>\nDoes the equivalent of <code>t[n] = v</code>,\nwhere <code>t</code> is the value at the given valid index\nand <code>v</code> is the value at the top of the stack.\n\n\n<p>\nThis function pops the value from the stack.\nThe assignment is raw;\nthat is, it does not invoke metamethods.\n\n\n\n\n\n<hr><h3><a name=\"lua_Reader\"><code>lua_Reader</code></a></h3>\n<pre>typedef const char * (*lua_Reader) (lua_State *L,\n                                    void *data,\n                                    size_t *size);</pre>\n\n<p>\nThe reader function used by <a href=\"#lua_load\"><code>lua_load</code></a>.\nEvery time it needs another piece of the chunk,\n<a href=\"#lua_load\"><code>lua_load</code></a> calls the reader,\npassing along its <code>data</code> parameter.\nThe reader must return a pointer to a block of memory\nwith a new piece of the chunk\nand set <code>size</code> to the block size.\nThe block must exist until the reader function is called again.\nTo signal the end of the chunk,\nthe reader must return <code>NULL</code> or set <code>size</code> to zero.\nThe reader function may return pieces of any size greater than zero.\n\n\n\n\n\n<hr><h3><a name=\"lua_register\"><code>lua_register</code></a></h3><p>\n<span class=\"apii\">[-0, +0, <em>e</em>]</span>\n<pre>void lua_register (lua_State *L,\n                   const char *name,\n                   lua_CFunction f);</pre>\n\n<p>\nSets the C function <code>f</code> as the new value of global <code>name</code>.\nIt is defined as a macro:\n\n<pre>\n     #define lua_register(L,n,f) \\\n            (lua_pushcfunction(L, f), lua_setglobal(L, n))\n</pre>\n\n\n\n\n<hr><h3><a name=\"lua_remove\"><code>lua_remove</code></a></h3><p>\n<span class=\"apii\">[-1, +0, <em>-</em>]</span>\n<pre>void lua_remove (lua_State *L, int index);</pre>\n\n<p>\nRemoves the element at the given valid index,\nshifting down the elements above this index to fill the gap.\nCannot be called with a pseudo-index,\nbecause a pseudo-index is not an actual stack position.\n\n\n\n\n\n<hr><h3><a name=\"lua_replace\"><code>lua_replace</code></a></h3><p>\n<span class=\"apii\">[-1, +0, <em>-</em>]</span>\n<pre>void lua_replace (lua_State *L, int index);</pre>\n\n<p>\nMoves the top element into the given position (and pops it),\nwithout shifting any element\n(therefore replacing the value at the given position).\n\n\n\n\n\n<hr><h3><a name=\"lua_resume\"><code>lua_resume</code></a></h3><p>\n<span class=\"apii\">[-?, +?, <em>-</em>]</span>\n<pre>int lua_resume (lua_State *L, int narg);</pre>\n\n<p>\nStarts and resumes a coroutine in a given thread.\n\n\n<p>\nTo start a coroutine, you first create a new thread\n(see <a href=\"#lua_newthread\"><code>lua_newthread</code></a>);\nthen you push onto its stack the main function plus any arguments;\nthen you call <a href=\"#lua_resume\"><code>lua_resume</code></a>,\nwith <code>narg</code> being the number of arguments.\nThis call returns when the coroutine suspends or finishes its execution.\nWhen it returns, the stack contains all values passed to <a href=\"#lua_yield\"><code>lua_yield</code></a>,\nor all values returned by the body function.\n<a href=\"#lua_resume\"><code>lua_resume</code></a> returns\n<a href=\"#pdf-LUA_YIELD\"><code>LUA_YIELD</code></a> if the coroutine yields,\n0 if the coroutine finishes its execution\nwithout errors,\nor an error code in case of errors (see <a href=\"#lua_pcall\"><code>lua_pcall</code></a>).\nIn case of errors,\nthe stack is not unwound,\nso you can use the debug API over it.\nThe error message is on the top of the stack.\nTo restart a coroutine, you put on its stack only the values to\nbe passed as results from <code>yield</code>,\nand then call <a href=\"#lua_resume\"><code>lua_resume</code></a>.\n\n\n\n\n\n<hr><h3><a name=\"lua_setallocf\"><code>lua_setallocf</code></a></h3><p>\n<span class=\"apii\">[-0, +0, <em>-</em>]</span>\n<pre>void lua_setallocf (lua_State *L, lua_Alloc f, void *ud);</pre>\n\n<p>\nChanges the allocator function of a given state to <code>f</code>\nwith user data <code>ud</code>.\n\n\n\n\n\n<hr><h3><a name=\"lua_setfenv\"><code>lua_setfenv</code></a></h3><p>\n<span class=\"apii\">[-1, +0, <em>-</em>]</span>\n<pre>int lua_setfenv (lua_State *L, int index);</pre>\n\n<p>\nPops a table from the stack and sets it as\nthe new environment for the value at the given index.\nIf the value at the given index is\nneither a function nor a thread nor a userdata,\n<a href=\"#lua_setfenv\"><code>lua_setfenv</code></a> returns 0.\nOtherwise it returns 1.\n\n\n\n\n\n<hr><h3><a name=\"lua_setfield\"><code>lua_setfield</code></a></h3><p>\n<span class=\"apii\">[-1, +0, <em>e</em>]</span>\n<pre>void lua_setfield (lua_State *L, int index, const char *k);</pre>\n\n<p>\nDoes the equivalent to <code>t[k] = v</code>,\nwhere <code>t</code> is the value at the given valid index\nand <code>v</code> is the value at the top of the stack.\n\n\n<p>\nThis function pops the value from the stack.\nAs in Lua, this function may trigger a metamethod\nfor the \"newindex\" event (see <a href=\"#2.8\">&sect;2.8</a>).\n\n\n\n\n\n<hr><h3><a name=\"lua_setglobal\"><code>lua_setglobal</code></a></h3><p>\n<span class=\"apii\">[-1, +0, <em>e</em>]</span>\n<pre>void lua_setglobal (lua_State *L, const char *name);</pre>\n\n<p>\nPops a value from the stack and\nsets it as the new value of global <code>name</code>.\nIt is defined as a macro:\n\n<pre>\n     #define lua_setglobal(L,s)   lua_setfield(L, LUA_GLOBALSINDEX, s)\n</pre>\n\n\n\n\n<hr><h3><a name=\"lua_setmetatable\"><code>lua_setmetatable</code></a></h3><p>\n<span class=\"apii\">[-1, +0, <em>-</em>]</span>\n<pre>int lua_setmetatable (lua_State *L, int index);</pre>\n\n<p>\nPops a table from the stack and\nsets it as the new metatable for the value at the given\nacceptable index.\n\n\n\n\n\n<hr><h3><a name=\"lua_settable\"><code>lua_settable</code></a></h3><p>\n<span class=\"apii\">[-2, +0, <em>e</em>]</span>\n<pre>void lua_settable (lua_State *L, int index);</pre>\n\n<p>\nDoes the equivalent to <code>t[k] = v</code>,\nwhere <code>t</code> is the value at the given valid index,\n<code>v</code> is the value at the top of the stack,\nand <code>k</code> is the value just below the top.\n\n\n<p>\nThis function pops both the key and the value from the stack.\nAs in Lua, this function may trigger a metamethod\nfor the \"newindex\" event (see <a href=\"#2.8\">&sect;2.8</a>).\n\n\n\n\n\n<hr><h3><a name=\"lua_settop\"><code>lua_settop</code></a></h3><p>\n<span class=\"apii\">[-?, +?, <em>-</em>]</span>\n<pre>void lua_settop (lua_State *L, int index);</pre>\n\n<p>\nAccepts any acceptable index, or&nbsp;0,\nand sets the stack top to this index.\nIf the new top is larger than the old one,\nthen the new elements are filled with <b>nil</b>.\nIf <code>index</code> is&nbsp;0, then all stack elements are removed.\n\n\n\n\n\n<hr><h3><a name=\"lua_State\"><code>lua_State</code></a></h3>\n<pre>typedef struct lua_State lua_State;</pre>\n\n<p>\nOpaque structure that keeps the whole state of a Lua interpreter.\nThe Lua library is fully reentrant:\nit has no global variables.\nAll information about a state is kept in this structure.\n\n\n<p>\nA pointer to this state must be passed as the first argument to\nevery function in the library, except to <a href=\"#lua_newstate\"><code>lua_newstate</code></a>,\nwhich creates a Lua state from scratch.\n\n\n\n\n\n<hr><h3><a name=\"lua_status\"><code>lua_status</code></a></h3><p>\n<span class=\"apii\">[-0, +0, <em>-</em>]</span>\n<pre>int lua_status (lua_State *L);</pre>\n\n<p>\nReturns the status of the thread <code>L</code>.\n\n\n<p>\nThe status can be 0 for a normal thread,\nan error code if the thread finished its execution with an error,\nor <a name=\"pdf-LUA_YIELD\"><code>LUA_YIELD</code></a> if the thread is suspended.\n\n\n\n\n\n<hr><h3><a name=\"lua_toboolean\"><code>lua_toboolean</code></a></h3><p>\n<span class=\"apii\">[-0, +0, <em>-</em>]</span>\n<pre>int lua_toboolean (lua_State *L, int index);</pre>\n\n<p>\nConverts the Lua value at the given acceptable index to a C&nbsp;boolean\nvalue (0&nbsp;or&nbsp;1).\nLike all tests in Lua,\n<a href=\"#lua_toboolean\"><code>lua_toboolean</code></a> returns 1 for any Lua value\ndifferent from <b>false</b> and <b>nil</b>;\notherwise it returns 0.\nIt also returns 0 when called with a non-valid index.\n(If you want to accept only actual boolean values,\nuse <a href=\"#lua_isboolean\"><code>lua_isboolean</code></a> to test the value's type.)\n\n\n\n\n\n<hr><h3><a name=\"lua_tocfunction\"><code>lua_tocfunction</code></a></h3><p>\n<span class=\"apii\">[-0, +0, <em>-</em>]</span>\n<pre>lua_CFunction lua_tocfunction (lua_State *L, int index);</pre>\n\n<p>\nConverts a value at the given acceptable index to a C&nbsp;function.\nThat value must be a C&nbsp;function;\notherwise, returns <code>NULL</code>.\n\n\n\n\n\n<hr><h3><a name=\"lua_tointeger\"><code>lua_tointeger</code></a></h3><p>\n<span class=\"apii\">[-0, +0, <em>-</em>]</span>\n<pre>lua_Integer lua_tointeger (lua_State *L, int index);</pre>\n\n<p>\nConverts the Lua value at the given acceptable index\nto the signed integral type <a href=\"#lua_Integer\"><code>lua_Integer</code></a>.\nThe Lua value must be a number or a string convertible to a number\n(see <a href=\"#2.2.1\">&sect;2.2.1</a>);\notherwise, <a href=\"#lua_tointeger\"><code>lua_tointeger</code></a> returns&nbsp;0.\n\n\n<p>\nIf the number is not an integer,\nit is truncated in some non-specified way.\n\n\n\n\n\n<hr><h3><a name=\"lua_tolstring\"><code>lua_tolstring</code></a></h3><p>\n<span class=\"apii\">[-0, +0, <em>m</em>]</span>\n<pre>const char *lua_tolstring (lua_State *L, int index, size_t *len);</pre>\n\n<p>\nConverts the Lua value at the given acceptable index to a C&nbsp;string.\nIf <code>len</code> is not <code>NULL</code>,\nit also sets <code>*len</code> with the string length.\nThe Lua value must be a string or a number;\notherwise, the function returns <code>NULL</code>.\nIf the value is a number,\nthen <a href=\"#lua_tolstring\"><code>lua_tolstring</code></a> also\n<em>changes the actual value in the stack to a string</em>.\n(This change confuses <a href=\"#lua_next\"><code>lua_next</code></a>\nwhen <a href=\"#lua_tolstring\"><code>lua_tolstring</code></a> is applied to keys during a table traversal.)\n\n\n<p>\n<a href=\"#lua_tolstring\"><code>lua_tolstring</code></a> returns a fully aligned pointer\nto a string inside the Lua state.\nThis string always has a zero ('<code>\\0</code>')\nafter its last character (as in&nbsp;C),\nbut can contain other zeros in its body.\nBecause Lua has garbage collection,\nthere is no guarantee that the pointer returned by <a href=\"#lua_tolstring\"><code>lua_tolstring</code></a>\nwill be valid after the corresponding value is removed from the stack.\n\n\n\n\n\n<hr><h3><a name=\"lua_tonumber\"><code>lua_tonumber</code></a></h3><p>\n<span class=\"apii\">[-0, +0, <em>-</em>]</span>\n<pre>lua_Number lua_tonumber (lua_State *L, int index);</pre>\n\n<p>\nConverts the Lua value at the given acceptable index\nto the C&nbsp;type <a href=\"#lua_Number\"><code>lua_Number</code></a> (see <a href=\"#lua_Number\"><code>lua_Number</code></a>).\nThe Lua value must be a number or a string convertible to a number\n(see <a href=\"#2.2.1\">&sect;2.2.1</a>);\notherwise, <a href=\"#lua_tonumber\"><code>lua_tonumber</code></a> returns&nbsp;0.\n\n\n\n\n\n<hr><h3><a name=\"lua_topointer\"><code>lua_topointer</code></a></h3><p>\n<span class=\"apii\">[-0, +0, <em>-</em>]</span>\n<pre>const void *lua_topointer (lua_State *L, int index);</pre>\n\n<p>\nConverts the value at the given acceptable index to a generic\nC&nbsp;pointer (<code>void*</code>).\nThe value can be a userdata, a table, a thread, or a function;\notherwise, <a href=\"#lua_topointer\"><code>lua_topointer</code></a> returns <code>NULL</code>.\nDifferent objects will give different pointers.\nThere is no way to convert the pointer back to its original value.\n\n\n<p>\nTypically this function is used only for debug information.\n\n\n\n\n\n<hr><h3><a name=\"lua_tostring\"><code>lua_tostring</code></a></h3><p>\n<span class=\"apii\">[-0, +0, <em>m</em>]</span>\n<pre>const char *lua_tostring (lua_State *L, int index);</pre>\n\n<p>\nEquivalent to <a href=\"#lua_tolstring\"><code>lua_tolstring</code></a> with <code>len</code> equal to <code>NULL</code>.\n\n\n\n\n\n<hr><h3><a name=\"lua_tothread\"><code>lua_tothread</code></a></h3><p>\n<span class=\"apii\">[-0, +0, <em>-</em>]</span>\n<pre>lua_State *lua_tothread (lua_State *L, int index);</pre>\n\n<p>\nConverts the value at the given acceptable index to a Lua thread\n(represented as <code>lua_State*</code>).\nThis value must be a thread;\notherwise, the function returns <code>NULL</code>.\n\n\n\n\n\n<hr><h3><a name=\"lua_touserdata\"><code>lua_touserdata</code></a></h3><p>\n<span class=\"apii\">[-0, +0, <em>-</em>]</span>\n<pre>void *lua_touserdata (lua_State *L, int index);</pre>\n\n<p>\nIf the value at the given acceptable index is a full userdata,\nreturns its block address.\nIf the value is a light userdata,\nreturns its pointer.\nOtherwise, returns <code>NULL</code>.\n\n\n\n\n\n<hr><h3><a name=\"lua_type\"><code>lua_type</code></a></h3><p>\n<span class=\"apii\">[-0, +0, <em>-</em>]</span>\n<pre>int lua_type (lua_State *L, int index);</pre>\n\n<p>\nReturns the type of the value in the given acceptable index,\nor <code>LUA_TNONE</code> for a non-valid index\n(that is, an index to an \"empty\" stack position).\nThe types returned by <a href=\"#lua_type\"><code>lua_type</code></a> are coded by the following constants\ndefined in <code>lua.h</code>:\n<code>LUA_TNIL</code>,\n<code>LUA_TNUMBER</code>,\n<code>LUA_TBOOLEAN</code>,\n<code>LUA_TSTRING</code>,\n<code>LUA_TTABLE</code>,\n<code>LUA_TFUNCTION</code>,\n<code>LUA_TUSERDATA</code>,\n<code>LUA_TTHREAD</code>,\nand\n<code>LUA_TLIGHTUSERDATA</code>.\n\n\n\n\n\n<hr><h3><a name=\"lua_typename\"><code>lua_typename</code></a></h3><p>\n<span class=\"apii\">[-0, +0, <em>-</em>]</span>\n<pre>const char *lua_typename  (lua_State *L, int tp);</pre>\n\n<p>\nReturns the name of the type encoded by the value <code>tp</code>,\nwhich must be one the values returned by <a href=\"#lua_type\"><code>lua_type</code></a>.\n\n\n\n\n\n<hr><h3><a name=\"lua_Writer\"><code>lua_Writer</code></a></h3>\n<pre>typedef int (*lua_Writer) (lua_State *L,\n                           const void* p,\n                           size_t sz,\n                           void* ud);</pre>\n\n<p>\nThe type of the writer function used by <a href=\"#lua_dump\"><code>lua_dump</code></a>.\nEvery time it produces another piece of chunk,\n<a href=\"#lua_dump\"><code>lua_dump</code></a> calls the writer,\npassing along the buffer to be written (<code>p</code>),\nits size (<code>sz</code>),\nand the <code>data</code> parameter supplied to <a href=\"#lua_dump\"><code>lua_dump</code></a>.\n\n\n<p>\nThe writer returns an error code:\n0&nbsp;means no errors;\nany other value means an error and stops <a href=\"#lua_dump\"><code>lua_dump</code></a> from\ncalling the writer again.\n\n\n\n\n\n<hr><h3><a name=\"lua_xmove\"><code>lua_xmove</code></a></h3><p>\n<span class=\"apii\">[-?, +?, <em>-</em>]</span>\n<pre>void lua_xmove (lua_State *from, lua_State *to, int n);</pre>\n\n<p>\nExchange values between different threads of the <em>same</em> global state.\n\n\n<p>\nThis function pops <code>n</code> values from the stack <code>from</code>,\nand pushes them onto the stack <code>to</code>.\n\n\n\n\n\n<hr><h3><a name=\"lua_yield\"><code>lua_yield</code></a></h3><p>\n<span class=\"apii\">[-?, +?, <em>-</em>]</span>\n<pre>int lua_yield  (lua_State *L, int nresults);</pre>\n\n<p>\nYields a coroutine.\n\n\n<p>\nThis function should only be called as the\nreturn expression of a C&nbsp;function, as follows:\n\n<pre>\n     return lua_yield (L, nresults);\n</pre><p>\nWhen a C&nbsp;function calls <a href=\"#lua_yield\"><code>lua_yield</code></a> in that way,\nthe running coroutine suspends its execution,\nand the call to <a href=\"#lua_resume\"><code>lua_resume</code></a> that started this coroutine returns.\nThe parameter <code>nresults</code> is the number of values from the stack\nthat are passed as results to <a href=\"#lua_resume\"><code>lua_resume</code></a>.\n\n\n\n\n\n\n\n<h2>3.8 - <a name=\"3.8\">The Debug Interface</a></h2>\n\n<p>\nLua has no built-in debugging facilities.\nInstead, it offers a special interface\nby means of functions and <em>hooks</em>.\nThis interface allows the construction of different\nkinds of debuggers, profilers, and other tools\nthat need \"inside information\" from the interpreter.\n\n\n\n<hr><h3><a name=\"lua_Debug\"><code>lua_Debug</code></a></h3>\n<pre>typedef struct lua_Debug {\n  int event;\n  const char *name;           /* (n) */\n  const char *namewhat;       /* (n) */\n  const char *what;           /* (S) */\n  const char *source;         /* (S) */\n  int currentline;            /* (l) */\n  int nups;                   /* (u) number of upvalues */\n  int linedefined;            /* (S) */\n  int lastlinedefined;        /* (S) */\n  char short_src[LUA_IDSIZE]; /* (S) */\n  /* private part */\n  <em>other fields</em>\n} lua_Debug;</pre>\n\n<p>\nA structure used to carry different pieces of\ninformation about an active function.\n<a href=\"#lua_getstack\"><code>lua_getstack</code></a> fills only the private part\nof this structure, for later use.\nTo fill the other fields of <a href=\"#lua_Debug\"><code>lua_Debug</code></a> with useful information,\ncall <a href=\"#lua_getinfo\"><code>lua_getinfo</code></a>.\n\n\n<p>\nThe fields of <a href=\"#lua_Debug\"><code>lua_Debug</code></a> have the following meaning:\n\n<ul>\n\n<li><b><code>source</code>:</b>\nIf the function was defined in a string,\nthen <code>source</code> is that string.\nIf the function was defined in a file,\nthen <code>source</code> starts with a '<code>@</code>' followed by the file name.\n</li>\n\n<li><b><code>short_src</code>:</b>\na \"printable\" version of <code>source</code>, to be used in error messages.\n</li>\n\n<li><b><code>linedefined</code>:</b>\nthe line number where the definition of the function starts.\n</li>\n\n<li><b><code>lastlinedefined</code>:</b>\nthe line number where the definition of the function ends.\n</li>\n\n<li><b><code>what</code>:</b>\nthe string <code>\"Lua\"</code> if the function is a Lua function,\n<code>\"C\"</code> if it is a C&nbsp;function,\n<code>\"main\"</code> if it is the main part of a chunk,\nand <code>\"tail\"</code> if it was a function that did a tail call.\nIn the latter case,\nLua has no other information about the function.\n</li>\n\n<li><b><code>currentline</code>:</b>\nthe current line where the given function is executing.\nWhen no line information is available,\n<code>currentline</code> is set to -1.\n</li>\n\n<li><b><code>name</code>:</b>\na reasonable name for the given function.\nBecause functions in Lua are first-class values,\nthey do not have a fixed name:\nsome functions can be the value of multiple global variables,\nwhile others can be stored only in a table field.\nThe <code>lua_getinfo</code> function checks how the function was\ncalled to find a suitable name.\nIf it cannot find a name,\nthen <code>name</code> is set to <code>NULL</code>.\n</li>\n\n<li><b><code>namewhat</code>:</b>\nexplains the <code>name</code> field.\nThe value of <code>namewhat</code> can be\n<code>\"global\"</code>, <code>\"local\"</code>, <code>\"method\"</code>,\n<code>\"field\"</code>, <code>\"upvalue\"</code>, or <code>\"\"</code> (the empty string),\naccording to how the function was called.\n(Lua uses the empty string when no other option seems to apply.)\n</li>\n\n<li><b><code>nups</code>:</b>\nthe number of upvalues of the function.\n</li>\n\n</ul>\n\n\n\n\n<hr><h3><a name=\"lua_gethook\"><code>lua_gethook</code></a></h3><p>\n<span class=\"apii\">[-0, +0, <em>-</em>]</span>\n<pre>lua_Hook lua_gethook (lua_State *L);</pre>\n\n<p>\nReturns the current hook function.\n\n\n\n\n\n<hr><h3><a name=\"lua_gethookcount\"><code>lua_gethookcount</code></a></h3><p>\n<span class=\"apii\">[-0, +0, <em>-</em>]</span>\n<pre>int lua_gethookcount (lua_State *L);</pre>\n\n<p>\nReturns the current hook count.\n\n\n\n\n\n<hr><h3><a name=\"lua_gethookmask\"><code>lua_gethookmask</code></a></h3><p>\n<span class=\"apii\">[-0, +0, <em>-</em>]</span>\n<pre>int lua_gethookmask (lua_State *L);</pre>\n\n<p>\nReturns the current hook mask.\n\n\n\n\n\n<hr><h3><a name=\"lua_getinfo\"><code>lua_getinfo</code></a></h3><p>\n<span class=\"apii\">[-(0|1), +(0|1|2), <em>m</em>]</span>\n<pre>int lua_getinfo (lua_State *L, const char *what, lua_Debug *ar);</pre>\n\n<p>\nReturns information about a specific function or function invocation.\n\n\n<p>\nTo get information about a function invocation,\nthe parameter <code>ar</code> must be a valid activation record that was\nfilled by a previous call to <a href=\"#lua_getstack\"><code>lua_getstack</code></a> or\ngiven as argument to a hook (see <a href=\"#lua_Hook\"><code>lua_Hook</code></a>).\n\n\n<p>\nTo get information about a function you push it onto the stack\nand start the <code>what</code> string with the character '<code>&gt;</code>'.\n(In that case,\n<code>lua_getinfo</code> pops the function in the top of the stack.)\nFor instance, to know in which line a function <code>f</code> was defined,\nyou can write the following code:\n\n<pre>\n     lua_Debug ar;\n     lua_getfield(L, LUA_GLOBALSINDEX, \"f\");  /* get global 'f' */\n     lua_getinfo(L, \"&gt;S\", &amp;ar);\n     printf(\"%d\\n\", ar.linedefined);\n</pre>\n\n<p>\nEach character in the string <code>what</code>\nselects some fields of the structure <code>ar</code> to be filled or\na value to be pushed on the stack:\n\n<ul>\n\n<li><b>'<code>n</code>':</b> fills in the field <code>name</code> and <code>namewhat</code>;\n</li>\n\n<li><b>'<code>S</code>':</b>\nfills in the fields <code>source</code>, <code>short_src</code>,\n<code>linedefined</code>, <code>lastlinedefined</code>, and <code>what</code>;\n</li>\n\n<li><b>'<code>l</code>':</b> fills in the field <code>currentline</code>;\n</li>\n\n<li><b>'<code>u</code>':</b> fills in the field <code>nups</code>;\n</li>\n\n<li><b>'<code>f</code>':</b>\npushes onto the stack the function that is\nrunning at the given level;\n</li>\n\n<li><b>'<code>L</code>':</b>\npushes onto the stack a table whose indices are the\nnumbers of the lines that are valid on the function.\n(A <em>valid line</em> is a line with some associated code,\nthat is, a line where you can put a break point.\nNon-valid lines include empty lines and comments.)\n</li>\n\n</ul>\n\n<p>\nThis function returns 0 on error\n(for instance, an invalid option in <code>what</code>).\n\n\n\n\n\n<hr><h3><a name=\"lua_getlocal\"><code>lua_getlocal</code></a></h3><p>\n<span class=\"apii\">[-0, +(0|1), <em>-</em>]</span>\n<pre>const char *lua_getlocal (lua_State *L, lua_Debug *ar, int n);</pre>\n\n<p>\nGets information about a local variable of a given activation record.\nThe parameter <code>ar</code> must be a valid activation record that was\nfilled by a previous call to <a href=\"#lua_getstack\"><code>lua_getstack</code></a> or\ngiven as argument to a hook (see <a href=\"#lua_Hook\"><code>lua_Hook</code></a>).\nThe index <code>n</code> selects which local variable to inspect\n(1 is the first parameter or active local variable, and so on,\nuntil the last active local variable).\n<a href=\"#lua_getlocal\"><code>lua_getlocal</code></a> pushes the variable's value onto the stack\nand returns its name.\n\n\n<p>\nVariable names starting with '<code>(</code>' (open parentheses)\nrepresent internal variables\n(loop control variables, temporaries, and C&nbsp;function locals).\n\n\n<p>\nReturns <code>NULL</code> (and pushes nothing)\nwhen the index is greater than\nthe number of active local variables.\n\n\n\n\n\n<hr><h3><a name=\"lua_getstack\"><code>lua_getstack</code></a></h3><p>\n<span class=\"apii\">[-0, +0, <em>-</em>]</span>\n<pre>int lua_getstack (lua_State *L, int level, lua_Debug *ar);</pre>\n\n<p>\nGet information about the interpreter runtime stack.\n\n\n<p>\nThis function fills parts of a <a href=\"#lua_Debug\"><code>lua_Debug</code></a> structure with\nan identification of the <em>activation record</em>\nof the function executing at a given level.\nLevel&nbsp;0 is the current running function,\nwhereas level <em>n+1</em> is the function that has called level <em>n</em>.\nWhen there are no errors, <a href=\"#lua_getstack\"><code>lua_getstack</code></a> returns 1;\nwhen called with a level greater than the stack depth,\nit returns 0.\n\n\n\n\n\n<hr><h3><a name=\"lua_getupvalue\"><code>lua_getupvalue</code></a></h3><p>\n<span class=\"apii\">[-0, +(0|1), <em>-</em>]</span>\n<pre>const char *lua_getupvalue (lua_State *L, int funcindex, int n);</pre>\n\n<p>\nGets information about a closure's upvalue.\n(For Lua functions,\nupvalues are the external local variables that the function uses,\nand that are consequently included in its closure.)\n<a href=\"#lua_getupvalue\"><code>lua_getupvalue</code></a> gets the index <code>n</code> of an upvalue,\npushes the upvalue's value onto the stack,\nand returns its name.\n<code>funcindex</code> points to the closure in the stack.\n(Upvalues have no particular order,\nas they are active through the whole function.\nSo, they are numbered in an arbitrary order.)\n\n\n<p>\nReturns <code>NULL</code> (and pushes nothing)\nwhen the index is greater than the number of upvalues.\nFor C&nbsp;functions, this function uses the empty string <code>\"\"</code>\nas a name for all upvalues.\n\n\n\n\n\n<hr><h3><a name=\"lua_Hook\"><code>lua_Hook</code></a></h3>\n<pre>typedef void (*lua_Hook) (lua_State *L, lua_Debug *ar);</pre>\n\n<p>\nType for debugging hook functions.\n\n\n<p>\nWhenever a hook is called, its <code>ar</code> argument has its field\n<code>event</code> set to the specific event that triggered the hook.\nLua identifies these events with the following constants:\n<a name=\"pdf-LUA_HOOKCALL\"><code>LUA_HOOKCALL</code></a>, <a name=\"pdf-LUA_HOOKRET\"><code>LUA_HOOKRET</code></a>,\n<a name=\"pdf-LUA_HOOKTAILRET\"><code>LUA_HOOKTAILRET</code></a>, <a name=\"pdf-LUA_HOOKLINE\"><code>LUA_HOOKLINE</code></a>,\nand <a name=\"pdf-LUA_HOOKCOUNT\"><code>LUA_HOOKCOUNT</code></a>.\nMoreover, for line events, the field <code>currentline</code> is also set.\nTo get the value of any other field in <code>ar</code>,\nthe hook must call <a href=\"#lua_getinfo\"><code>lua_getinfo</code></a>.\nFor return events, <code>event</code> can be <code>LUA_HOOKRET</code>,\nthe normal value, or <code>LUA_HOOKTAILRET</code>.\nIn the latter case, Lua is simulating a return from\na function that did a tail call;\nin this case, it is useless to call <a href=\"#lua_getinfo\"><code>lua_getinfo</code></a>.\n\n\n<p>\nWhile Lua is running a hook, it disables other calls to hooks.\nTherefore, if a hook calls back Lua to execute a function or a chunk,\nthis execution occurs without any calls to hooks.\n\n\n\n\n\n<hr><h3><a name=\"lua_sethook\"><code>lua_sethook</code></a></h3><p>\n<span class=\"apii\">[-0, +0, <em>-</em>]</span>\n<pre>int lua_sethook (lua_State *L, lua_Hook f, int mask, int count);</pre>\n\n<p>\nSets the debugging hook function.\n\n\n<p>\nArgument <code>f</code> is the hook function.\n<code>mask</code> specifies on which events the hook will be called:\nit is formed by a bitwise or of the constants\n<a name=\"pdf-LUA_MASKCALL\"><code>LUA_MASKCALL</code></a>,\n<a name=\"pdf-LUA_MASKRET\"><code>LUA_MASKRET</code></a>,\n<a name=\"pdf-LUA_MASKLINE\"><code>LUA_MASKLINE</code></a>,\nand <a name=\"pdf-LUA_MASKCOUNT\"><code>LUA_MASKCOUNT</code></a>.\nThe <code>count</code> argument is only meaningful when the mask\nincludes <code>LUA_MASKCOUNT</code>.\nFor each event, the hook is called as explained below:\n\n<ul>\n\n<li><b>The call hook:</b> is called when the interpreter calls a function.\nThe hook is called just after Lua enters the new function,\nbefore the function gets its arguments.\n</li>\n\n<li><b>The return hook:</b> is called when the interpreter returns from a function.\nThe hook is called just before Lua leaves the function.\nYou have no access to the values to be returned by the function.\n</li>\n\n<li><b>The line hook:</b> is called when the interpreter is about to\nstart the execution of a new line of code,\nor when it jumps back in the code (even to the same line).\n(This event only happens while Lua is executing a Lua function.)\n</li>\n\n<li><b>The count hook:</b> is called after the interpreter executes every\n<code>count</code> instructions.\n(This event only happens while Lua is executing a Lua function.)\n</li>\n\n</ul>\n\n<p>\nA hook is disabled by setting <code>mask</code> to zero.\n\n\n\n\n\n<hr><h3><a name=\"lua_setlocal\"><code>lua_setlocal</code></a></h3><p>\n<span class=\"apii\">[-(0|1), +0, <em>-</em>]</span>\n<pre>const char *lua_setlocal (lua_State *L, lua_Debug *ar, int n);</pre>\n\n<p>\nSets the value of a local variable of a given activation record.\nParameters <code>ar</code> and <code>n</code> are as in <a href=\"#lua_getlocal\"><code>lua_getlocal</code></a>\n(see <a href=\"#lua_getlocal\"><code>lua_getlocal</code></a>).\n<a href=\"#lua_setlocal\"><code>lua_setlocal</code></a> assigns the value at the top of the stack\nto the variable and returns its name.\nIt also pops the value from the stack.\n\n\n<p>\nReturns <code>NULL</code> (and pops nothing)\nwhen the index is greater than\nthe number of active local variables.\n\n\n\n\n\n<hr><h3><a name=\"lua_setupvalue\"><code>lua_setupvalue</code></a></h3><p>\n<span class=\"apii\">[-(0|1), +0, <em>-</em>]</span>\n<pre>const char *lua_setupvalue (lua_State *L, int funcindex, int n);</pre>\n\n<p>\nSets the value of a closure's upvalue.\nIt assigns the value at the top of the stack\nto the upvalue and returns its name.\nIt also pops the value from the stack.\nParameters <code>funcindex</code> and <code>n</code> are as in the <a href=\"#lua_getupvalue\"><code>lua_getupvalue</code></a>\n(see <a href=\"#lua_getupvalue\"><code>lua_getupvalue</code></a>).\n\n\n<p>\nReturns <code>NULL</code> (and pops nothing)\nwhen the index is greater than the number of upvalues.\n\n\n\n\n\n\n\n<h1>4 - <a name=\"4\">The Auxiliary Library</a></h1>\n\n<p>\n\nThe <em>auxiliary library</em> provides several convenient functions\nto interface C with Lua.\nWhile the basic API provides the primitive functions for all \ninteractions between C and Lua,\nthe auxiliary library provides higher-level functions for some\ncommon tasks.\n\n\n<p>\nAll functions from the auxiliary library\nare defined in header file <code>lauxlib.h</code> and\nhave a prefix <code>luaL_</code>.\n\n\n<p>\nAll functions in the auxiliary library are built on\ntop of the basic API,\nand so they provide nothing that cannot be done with this API.\n\n\n<p>\nSeveral functions in the auxiliary library are used to\ncheck C&nbsp;function arguments.\nTheir names are always <code>luaL_check*</code> or <code>luaL_opt*</code>.\nAll of these functions throw an error if the check is not satisfied.\nBecause the error message is formatted for arguments\n(e.g., \"<code>bad argument #1</code>\"),\nyou should not use these functions for other stack values.\n\n\n\n<h2>4.1 - <a name=\"4.1\">Functions and Types</a></h2>\n\n<p>\nHere we list all functions and types from the auxiliary library\nin alphabetical order.\n\n\n\n<hr><h3><a name=\"luaL_addchar\"><code>luaL_addchar</code></a></h3><p>\n<span class=\"apii\">[-0, +0, <em>m</em>]</span>\n<pre>void luaL_addchar (luaL_Buffer *B, char c);</pre>\n\n<p>\nAdds the character <code>c</code> to the buffer <code>B</code>\n(see <a href=\"#luaL_Buffer\"><code>luaL_Buffer</code></a>).\n\n\n\n\n\n<hr><h3><a name=\"luaL_addlstring\"><code>luaL_addlstring</code></a></h3><p>\n<span class=\"apii\">[-0, +0, <em>m</em>]</span>\n<pre>void luaL_addlstring (luaL_Buffer *B, const char *s, size_t l);</pre>\n\n<p>\nAdds the string pointed to by <code>s</code> with length <code>l</code> to\nthe buffer <code>B</code>\n(see <a href=\"#luaL_Buffer\"><code>luaL_Buffer</code></a>).\nThe string may contain embedded zeros.\n\n\n\n\n\n<hr><h3><a name=\"luaL_addsize\"><code>luaL_addsize</code></a></h3><p>\n<span class=\"apii\">[-0, +0, <em>m</em>]</span>\n<pre>void luaL_addsize (luaL_Buffer *B, size_t n);</pre>\n\n<p>\nAdds to the buffer <code>B</code> (see <a href=\"#luaL_Buffer\"><code>luaL_Buffer</code></a>)\na string of length <code>n</code> previously copied to the\nbuffer area (see <a href=\"#luaL_prepbuffer\"><code>luaL_prepbuffer</code></a>).\n\n\n\n\n\n<hr><h3><a name=\"luaL_addstring\"><code>luaL_addstring</code></a></h3><p>\n<span class=\"apii\">[-0, +0, <em>m</em>]</span>\n<pre>void luaL_addstring (luaL_Buffer *B, const char *s);</pre>\n\n<p>\nAdds the zero-terminated string pointed to by <code>s</code>\nto the buffer <code>B</code>\n(see <a href=\"#luaL_Buffer\"><code>luaL_Buffer</code></a>).\nThe string may not contain embedded zeros.\n\n\n\n\n\n<hr><h3><a name=\"luaL_addvalue\"><code>luaL_addvalue</code></a></h3><p>\n<span class=\"apii\">[-1, +0, <em>m</em>]</span>\n<pre>void luaL_addvalue (luaL_Buffer *B);</pre>\n\n<p>\nAdds the value at the top of the stack\nto the buffer <code>B</code>\n(see <a href=\"#luaL_Buffer\"><code>luaL_Buffer</code></a>).\nPops the value.\n\n\n<p>\nThis is the only function on string buffers that can (and must)\nbe called with an extra element on the stack,\nwhich is the value to be added to the buffer.\n\n\n\n\n\n<hr><h3><a name=\"luaL_argcheck\"><code>luaL_argcheck</code></a></h3><p>\n<span class=\"apii\">[-0, +0, <em>v</em>]</span>\n<pre>void luaL_argcheck (lua_State *L,\n                    int cond,\n                    int narg,\n                    const char *extramsg);</pre>\n\n<p>\nChecks whether <code>cond</code> is true.\nIf not, raises an error with the following message,\nwhere <code>func</code> is retrieved from the call stack:\n\n<pre>\n     bad argument #&lt;narg&gt; to &lt;func&gt; (&lt;extramsg&gt;)\n</pre>\n\n\n\n\n<hr><h3><a name=\"luaL_argerror\"><code>luaL_argerror</code></a></h3><p>\n<span class=\"apii\">[-0, +0, <em>v</em>]</span>\n<pre>int luaL_argerror (lua_State *L, int narg, const char *extramsg);</pre>\n\n<p>\nRaises an error with the following message,\nwhere <code>func</code> is retrieved from the call stack:\n\n<pre>\n     bad argument #&lt;narg&gt; to &lt;func&gt; (&lt;extramsg&gt;)\n</pre>\n\n<p>\nThis function never returns,\nbut it is an idiom to use it in C&nbsp;functions\nas <code>return luaL_argerror(<em>args</em>)</code>.\n\n\n\n\n\n<hr><h3><a name=\"luaL_Buffer\"><code>luaL_Buffer</code></a></h3>\n<pre>typedef struct luaL_Buffer luaL_Buffer;</pre>\n\n<p>\nType for a <em>string buffer</em>.\n\n\n<p>\nA string buffer allows C&nbsp;code to build Lua strings piecemeal.\nIts pattern of use is as follows:\n\n<ul>\n\n<li>First you declare a variable <code>b</code> of type <a href=\"#luaL_Buffer\"><code>luaL_Buffer</code></a>.</li>\n\n<li>Then you initialize it with a call <code>luaL_buffinit(L, &amp;b)</code>.</li>\n\n<li>\nThen you add string pieces to the buffer calling any of\nthe <code>luaL_add*</code> functions.\n</li>\n\n<li>\nYou finish by calling <code>luaL_pushresult(&amp;b)</code>.\nThis call leaves the final string on the top of the stack.\n</li>\n\n</ul>\n\n<p>\nDuring its normal operation,\na string buffer uses a variable number of stack slots.\nSo, while using a buffer, you cannot assume that you know where\nthe top of the stack is.\nYou can use the stack between successive calls to buffer operations\nas long as that use is balanced;\nthat is,\nwhen you call a buffer operation,\nthe stack is at the same level\nit was immediately after the previous buffer operation.\n(The only exception to this rule is <a href=\"#luaL_addvalue\"><code>luaL_addvalue</code></a>.)\nAfter calling <a href=\"#luaL_pushresult\"><code>luaL_pushresult</code></a> the stack is back to its\nlevel when the buffer was initialized,\nplus the final string on its top.\n\n\n\n\n\n<hr><h3><a name=\"luaL_buffinit\"><code>luaL_buffinit</code></a></h3><p>\n<span class=\"apii\">[-0, +0, <em>-</em>]</span>\n<pre>void luaL_buffinit (lua_State *L, luaL_Buffer *B);</pre>\n\n<p>\nInitializes a buffer <code>B</code>.\nThis function does not allocate any space;\nthe buffer must be declared as a variable\n(see <a href=\"#luaL_Buffer\"><code>luaL_Buffer</code></a>).\n\n\n\n\n\n<hr><h3><a name=\"luaL_callmeta\"><code>luaL_callmeta</code></a></h3><p>\n<span class=\"apii\">[-0, +(0|1), <em>e</em>]</span>\n<pre>int luaL_callmeta (lua_State *L, int obj, const char *e);</pre>\n\n<p>\nCalls a metamethod.\n\n\n<p>\nIf the object at index <code>obj</code> has a metatable and this\nmetatable has a field <code>e</code>,\nthis function calls this field and passes the object as its only argument.\nIn this case this function returns 1 and pushes onto the\nstack the value returned by the call.\nIf there is no metatable or no metamethod,\nthis function returns 0 (without pushing any value on the stack).\n\n\n\n\n\n<hr><h3><a name=\"luaL_checkany\"><code>luaL_checkany</code></a></h3><p>\n<span class=\"apii\">[-0, +0, <em>v</em>]</span>\n<pre>void luaL_checkany (lua_State *L, int narg);</pre>\n\n<p>\nChecks whether the function has an argument\nof any type (including <b>nil</b>) at position <code>narg</code>.\n\n\n\n\n\n<hr><h3><a name=\"luaL_checkint\"><code>luaL_checkint</code></a></h3><p>\n<span class=\"apii\">[-0, +0, <em>v</em>]</span>\n<pre>int luaL_checkint (lua_State *L, int narg);</pre>\n\n<p>\nChecks whether the function argument <code>narg</code> is a number\nand returns this number cast to an <code>int</code>.\n\n\n\n\n\n<hr><h3><a name=\"luaL_checkinteger\"><code>luaL_checkinteger</code></a></h3><p>\n<span class=\"apii\">[-0, +0, <em>v</em>]</span>\n<pre>lua_Integer luaL_checkinteger (lua_State *L, int narg);</pre>\n\n<p>\nChecks whether the function argument <code>narg</code> is a number\nand returns this number cast to a <a href=\"#lua_Integer\"><code>lua_Integer</code></a>.\n\n\n\n\n\n<hr><h3><a name=\"luaL_checklong\"><code>luaL_checklong</code></a></h3><p>\n<span class=\"apii\">[-0, +0, <em>v</em>]</span>\n<pre>long luaL_checklong (lua_State *L, int narg);</pre>\n\n<p>\nChecks whether the function argument <code>narg</code> is a number\nand returns this number cast to a <code>long</code>.\n\n\n\n\n\n<hr><h3><a name=\"luaL_checklstring\"><code>luaL_checklstring</code></a></h3><p>\n<span class=\"apii\">[-0, +0, <em>v</em>]</span>\n<pre>const char *luaL_checklstring (lua_State *L, int narg, size_t *l);</pre>\n\n<p>\nChecks whether the function argument <code>narg</code> is a string\nand returns this string;\nif <code>l</code> is not <code>NULL</code> fills <code>*l</code>\nwith the string's length.\n\n\n<p>\nThis function uses <a href=\"#lua_tolstring\"><code>lua_tolstring</code></a> to get its result,\nso all conversions and caveats of that function apply here.\n\n\n\n\n\n<hr><h3><a name=\"luaL_checknumber\"><code>luaL_checknumber</code></a></h3><p>\n<span class=\"apii\">[-0, +0, <em>v</em>]</span>\n<pre>lua_Number luaL_checknumber (lua_State *L, int narg);</pre>\n\n<p>\nChecks whether the function argument <code>narg</code> is a number\nand returns this number.\n\n\n\n\n\n<hr><h3><a name=\"luaL_checkoption\"><code>luaL_checkoption</code></a></h3><p>\n<span class=\"apii\">[-0, +0, <em>v</em>]</span>\n<pre>int luaL_checkoption (lua_State *L,\n                      int narg,\n                      const char *def,\n                      const char *const lst[]);</pre>\n\n<p>\nChecks whether the function argument <code>narg</code> is a string and\nsearches for this string in the array <code>lst</code>\n(which must be NULL-terminated).\nReturns the index in the array where the string was found.\nRaises an error if the argument is not a string or\nif the string cannot be found.\n\n\n<p>\nIf <code>def</code> is not <code>NULL</code>,\nthe function uses <code>def</code> as a default value when\nthere is no argument <code>narg</code> or if this argument is <b>nil</b>.\n\n\n<p>\nThis is a useful function for mapping strings to C&nbsp;enums.\n(The usual convention in Lua libraries is\nto use strings instead of numbers to select options.)\n\n\n\n\n\n<hr><h3><a name=\"luaL_checkstack\"><code>luaL_checkstack</code></a></h3><p>\n<span class=\"apii\">[-0, +0, <em>v</em>]</span>\n<pre>void luaL_checkstack (lua_State *L, int sz, const char *msg);</pre>\n\n<p>\nGrows the stack size to <code>top + sz</code> elements,\nraising an error if the stack cannot grow to that size.\n<code>msg</code> is an additional text to go into the error message.\n\n\n\n\n\n<hr><h3><a name=\"luaL_checkstring\"><code>luaL_checkstring</code></a></h3><p>\n<span class=\"apii\">[-0, +0, <em>v</em>]</span>\n<pre>const char *luaL_checkstring (lua_State *L, int narg);</pre>\n\n<p>\nChecks whether the function argument <code>narg</code> is a string\nand returns this string.\n\n\n<p>\nThis function uses <a href=\"#lua_tolstring\"><code>lua_tolstring</code></a> to get its result,\nso all conversions and caveats of that function apply here.\n\n\n\n\n\n<hr><h3><a name=\"luaL_checktype\"><code>luaL_checktype</code></a></h3><p>\n<span class=\"apii\">[-0, +0, <em>v</em>]</span>\n<pre>void luaL_checktype (lua_State *L, int narg, int t);</pre>\n\n<p>\nChecks whether the function argument <code>narg</code> has type <code>t</code>.\nSee <a href=\"#lua_type\"><code>lua_type</code></a> for the encoding of types for <code>t</code>.\n\n\n\n\n\n<hr><h3><a name=\"luaL_checkudata\"><code>luaL_checkudata</code></a></h3><p>\n<span class=\"apii\">[-0, +0, <em>v</em>]</span>\n<pre>void *luaL_checkudata (lua_State *L, int narg, const char *tname);</pre>\n\n<p>\nChecks whether the function argument <code>narg</code> is a userdata\nof the type <code>tname</code> (see <a href=\"#luaL_newmetatable\"><code>luaL_newmetatable</code></a>).\n\n\n\n\n\n<hr><h3><a name=\"luaL_dofile\"><code>luaL_dofile</code></a></h3><p>\n<span class=\"apii\">[-0, +?, <em>m</em>]</span>\n<pre>int luaL_dofile (lua_State *L, const char *filename);</pre>\n\n<p>\nLoads and runs the given file.\nIt is defined as the following macro:\n\n<pre>\n     (luaL_loadfile(L, filename) || lua_pcall(L, 0, LUA_MULTRET, 0))\n</pre><p>\nIt returns 0 if there are no errors\nor 1 in case of errors.\n\n\n\n\n\n<hr><h3><a name=\"luaL_dostring\"><code>luaL_dostring</code></a></h3><p>\n<span class=\"apii\">[-0, +?, <em>m</em>]</span>\n<pre>int luaL_dostring (lua_State *L, const char *str);</pre>\n\n<p>\nLoads and runs the given string.\nIt is defined as the following macro:\n\n<pre>\n     (luaL_loadstring(L, str) || lua_pcall(L, 0, LUA_MULTRET, 0))\n</pre><p>\nIt returns 0 if there are no errors\nor 1 in case of errors.\n\n\n\n\n\n<hr><h3><a name=\"luaL_error\"><code>luaL_error</code></a></h3><p>\n<span class=\"apii\">[-0, +0, <em>v</em>]</span>\n<pre>int luaL_error (lua_State *L, const char *fmt, ...);</pre>\n\n<p>\nRaises an error.\nThe error message format is given by <code>fmt</code>\nplus any extra arguments,\nfollowing the same rules of <a href=\"#lua_pushfstring\"><code>lua_pushfstring</code></a>.\nIt also adds at the beginning of the message the file name and\nthe line number where the error occurred,\nif this information is available.\n\n\n<p>\nThis function never returns,\nbut it is an idiom to use it in C&nbsp;functions\nas <code>return luaL_error(<em>args</em>)</code>.\n\n\n\n\n\n<hr><h3><a name=\"luaL_getmetafield\"><code>luaL_getmetafield</code></a></h3><p>\n<span class=\"apii\">[-0, +(0|1), <em>m</em>]</span>\n<pre>int luaL_getmetafield (lua_State *L, int obj, const char *e);</pre>\n\n<p>\nPushes onto the stack the field <code>e</code> from the metatable\nof the object at index <code>obj</code>.\nIf the object does not have a metatable,\nor if the metatable does not have this field,\nreturns 0 and pushes nothing.\n\n\n\n\n\n<hr><h3><a name=\"luaL_getmetatable\"><code>luaL_getmetatable</code></a></h3><p>\n<span class=\"apii\">[-0, +1, <em>-</em>]</span>\n<pre>void luaL_getmetatable (lua_State *L, const char *tname);</pre>\n\n<p>\nPushes onto the stack the metatable associated with name <code>tname</code>\nin the registry (see <a href=\"#luaL_newmetatable\"><code>luaL_newmetatable</code></a>).\n\n\n\n\n\n<hr><h3><a name=\"luaL_gsub\"><code>luaL_gsub</code></a></h3><p>\n<span class=\"apii\">[-0, +1, <em>m</em>]</span>\n<pre>const char *luaL_gsub (lua_State *L,\n                       const char *s,\n                       const char *p,\n                       const char *r);</pre>\n\n<p>\nCreates a copy of string <code>s</code> by replacing\nany occurrence of the string <code>p</code>\nwith the string <code>r</code>.\nPushes the resulting string on the stack and returns it.\n\n\n\n\n\n<hr><h3><a name=\"luaL_loadbuffer\"><code>luaL_loadbuffer</code></a></h3><p>\n<span class=\"apii\">[-0, +1, <em>m</em>]</span>\n<pre>int luaL_loadbuffer (lua_State *L,\n                     const char *buff,\n                     size_t sz,\n                     const char *name);</pre>\n\n<p>\nLoads a buffer as a Lua chunk.\nThis function uses <a href=\"#lua_load\"><code>lua_load</code></a> to load the chunk in the\nbuffer pointed to by <code>buff</code> with size <code>sz</code>.\n\n\n<p>\nThis function returns the same results as <a href=\"#lua_load\"><code>lua_load</code></a>.\n<code>name</code> is the chunk name,\nused for debug information and error messages.\n\n\n\n\n\n<hr><h3><a name=\"luaL_loadfile\"><code>luaL_loadfile</code></a></h3><p>\n<span class=\"apii\">[-0, +1, <em>m</em>]</span>\n<pre>int luaL_loadfile (lua_State *L, const char *filename);</pre>\n\n<p>\nLoads a file as a Lua chunk.\nThis function uses <a href=\"#lua_load\"><code>lua_load</code></a> to load the chunk in the file\nnamed <code>filename</code>.\nIf <code>filename</code> is <code>NULL</code>,\nthen it loads from the standard input.\nThe first line in the file is ignored if it starts with a <code>#</code>.\n\n\n<p>\nThis function returns the same results as <a href=\"#lua_load\"><code>lua_load</code></a>,\nbut it has an extra error code <a name=\"pdf-LUA_ERRFILE\"><code>LUA_ERRFILE</code></a>\nif it cannot open/read the file.\n\n\n<p>\nAs <a href=\"#lua_load\"><code>lua_load</code></a>, this function only loads the chunk;\nit does not run it.\n\n\n\n\n\n<hr><h3><a name=\"luaL_loadstring\"><code>luaL_loadstring</code></a></h3><p>\n<span class=\"apii\">[-0, +1, <em>m</em>]</span>\n<pre>int luaL_loadstring (lua_State *L, const char *s);</pre>\n\n<p>\nLoads a string as a Lua chunk.\nThis function uses <a href=\"#lua_load\"><code>lua_load</code></a> to load the chunk in\nthe zero-terminated string <code>s</code>.\n\n\n<p>\nThis function returns the same results as <a href=\"#lua_load\"><code>lua_load</code></a>.\n\n\n<p>\nAlso as <a href=\"#lua_load\"><code>lua_load</code></a>, this function only loads the chunk;\nit does not run it.\n\n\n\n\n\n<hr><h3><a name=\"luaL_newmetatable\"><code>luaL_newmetatable</code></a></h3><p>\n<span class=\"apii\">[-0, +1, <em>m</em>]</span>\n<pre>int luaL_newmetatable (lua_State *L, const char *tname);</pre>\n\n<p>\nIf the registry already has the key <code>tname</code>,\nreturns 0.\nOtherwise,\ncreates a new table to be used as a metatable for userdata,\nadds it to the registry with key <code>tname</code>,\nand returns 1.\n\n\n<p>\nIn both cases pushes onto the stack the final value associated\nwith <code>tname</code> in the registry.\n\n\n\n\n\n<hr><h3><a name=\"luaL_newstate\"><code>luaL_newstate</code></a></h3><p>\n<span class=\"apii\">[-0, +0, <em>-</em>]</span>\n<pre>lua_State *luaL_newstate (void);</pre>\n\n<p>\nCreates a new Lua state.\nIt calls <a href=\"#lua_newstate\"><code>lua_newstate</code></a> with an\nallocator based on the standard&nbsp;C <code>realloc</code> function\nand then sets a panic function (see <a href=\"#lua_atpanic\"><code>lua_atpanic</code></a>) that prints\nan error message to the standard error output in case of fatal\nerrors.\n\n\n<p>\nReturns the new state,\nor <code>NULL</code> if there is a memory allocation error.\n\n\n\n\n\n<hr><h3><a name=\"luaL_openlibs\"><code>luaL_openlibs</code></a></h3><p>\n<span class=\"apii\">[-0, +0, <em>m</em>]</span>\n<pre>void luaL_openlibs (lua_State *L);</pre>\n\n<p>\nOpens all standard Lua libraries into the given state.\n\n\n\n\n\n<hr><h3><a name=\"luaL_optint\"><code>luaL_optint</code></a></h3><p>\n<span class=\"apii\">[-0, +0, <em>v</em>]</span>\n<pre>int luaL_optint (lua_State *L, int narg, int d);</pre>\n\n<p>\nIf the function argument <code>narg</code> is a number,\nreturns this number cast to an <code>int</code>.\nIf this argument is absent or is <b>nil</b>,\nreturns <code>d</code>.\nOtherwise, raises an error.\n\n\n\n\n\n<hr><h3><a name=\"luaL_optinteger\"><code>luaL_optinteger</code></a></h3><p>\n<span class=\"apii\">[-0, +0, <em>v</em>]</span>\n<pre>lua_Integer luaL_optinteger (lua_State *L,\n                             int narg,\n                             lua_Integer d);</pre>\n\n<p>\nIf the function argument <code>narg</code> is a number,\nreturns this number cast to a <a href=\"#lua_Integer\"><code>lua_Integer</code></a>.\nIf this argument is absent or is <b>nil</b>,\nreturns <code>d</code>.\nOtherwise, raises an error.\n\n\n\n\n\n<hr><h3><a name=\"luaL_optlong\"><code>luaL_optlong</code></a></h3><p>\n<span class=\"apii\">[-0, +0, <em>v</em>]</span>\n<pre>long luaL_optlong (lua_State *L, int narg, long d);</pre>\n\n<p>\nIf the function argument <code>narg</code> is a number,\nreturns this number cast to a <code>long</code>.\nIf this argument is absent or is <b>nil</b>,\nreturns <code>d</code>.\nOtherwise, raises an error.\n\n\n\n\n\n<hr><h3><a name=\"luaL_optlstring\"><code>luaL_optlstring</code></a></h3><p>\n<span class=\"apii\">[-0, +0, <em>v</em>]</span>\n<pre>const char *luaL_optlstring (lua_State *L,\n                             int narg,\n                             const char *d,\n                             size_t *l);</pre>\n\n<p>\nIf the function argument <code>narg</code> is a string,\nreturns this string.\nIf this argument is absent or is <b>nil</b>,\nreturns <code>d</code>.\nOtherwise, raises an error.\n\n\n<p>\nIf <code>l</code> is not <code>NULL</code>,\nfills the position <code>*l</code> with the results's length.\n\n\n\n\n\n<hr><h3><a name=\"luaL_optnumber\"><code>luaL_optnumber</code></a></h3><p>\n<span class=\"apii\">[-0, +0, <em>v</em>]</span>\n<pre>lua_Number luaL_optnumber (lua_State *L, int narg, lua_Number d);</pre>\n\n<p>\nIf the function argument <code>narg</code> is a number,\nreturns this number.\nIf this argument is absent or is <b>nil</b>,\nreturns <code>d</code>.\nOtherwise, raises an error.\n\n\n\n\n\n<hr><h3><a name=\"luaL_optstring\"><code>luaL_optstring</code></a></h3><p>\n<span class=\"apii\">[-0, +0, <em>v</em>]</span>\n<pre>const char *luaL_optstring (lua_State *L,\n                            int narg,\n                            const char *d);</pre>\n\n<p>\nIf the function argument <code>narg</code> is a string,\nreturns this string.\nIf this argument is absent or is <b>nil</b>,\nreturns <code>d</code>.\nOtherwise, raises an error.\n\n\n\n\n\n<hr><h3><a name=\"luaL_prepbuffer\"><code>luaL_prepbuffer</code></a></h3><p>\n<span class=\"apii\">[-0, +0, <em>-</em>]</span>\n<pre>char *luaL_prepbuffer (luaL_Buffer *B);</pre>\n\n<p>\nReturns an address to a space of size <a name=\"pdf-LUAL_BUFFERSIZE\"><code>LUAL_BUFFERSIZE</code></a>\nwhere you can copy a string to be added to buffer <code>B</code>\n(see <a href=\"#luaL_Buffer\"><code>luaL_Buffer</code></a>).\nAfter copying the string into this space you must call\n<a href=\"#luaL_addsize\"><code>luaL_addsize</code></a> with the size of the string to actually add \nit to the buffer.\n\n\n\n\n\n<hr><h3><a name=\"luaL_pushresult\"><code>luaL_pushresult</code></a></h3><p>\n<span class=\"apii\">[-?, +1, <em>m</em>]</span>\n<pre>void luaL_pushresult (luaL_Buffer *B);</pre>\n\n<p>\nFinishes the use of buffer <code>B</code> leaving the final string on\nthe top of the stack.\n\n\n\n\n\n<hr><h3><a name=\"luaL_ref\"><code>luaL_ref</code></a></h3><p>\n<span class=\"apii\">[-1, +0, <em>m</em>]</span>\n<pre>int luaL_ref (lua_State *L, int t);</pre>\n\n<p>\nCreates and returns a <em>reference</em>,\nin the table at index <code>t</code>,\nfor the object at the top of the stack (and pops the object).\n\n\n<p>\nA reference is a unique integer key.\nAs long as you do not manually add integer keys into table <code>t</code>,\n<a href=\"#luaL_ref\"><code>luaL_ref</code></a> ensures the uniqueness of the key it returns.\nYou can retrieve an object referred by reference <code>r</code>\nby calling <code>lua_rawgeti(L, t, r)</code>.\nFunction <a href=\"#luaL_unref\"><code>luaL_unref</code></a> frees a reference and its associated object.\n\n\n<p>\nIf the object at the top of the stack is <b>nil</b>,\n<a href=\"#luaL_ref\"><code>luaL_ref</code></a> returns the constant <a name=\"pdf-LUA_REFNIL\"><code>LUA_REFNIL</code></a>.\nThe constant <a name=\"pdf-LUA_NOREF\"><code>LUA_NOREF</code></a> is guaranteed to be different\nfrom any reference returned by <a href=\"#luaL_ref\"><code>luaL_ref</code></a>.\n\n\n\n\n\n<hr><h3><a name=\"luaL_Reg\"><code>luaL_Reg</code></a></h3>\n<pre>typedef struct luaL_Reg {\n  const char *name;\n  lua_CFunction func;\n} luaL_Reg;</pre>\n\n<p>\nType for arrays of functions to be registered by\n<a href=\"#luaL_register\"><code>luaL_register</code></a>.\n<code>name</code> is the function name and <code>func</code> is a pointer to\nthe function.\nAny array of <a href=\"#luaL_Reg\"><code>luaL_Reg</code></a> must end with an sentinel entry\nin which both <code>name</code> and <code>func</code> are <code>NULL</code>.\n\n\n\n\n\n<hr><h3><a name=\"luaL_register\"><code>luaL_register</code></a></h3><p>\n<span class=\"apii\">[-(0|1), +1, <em>m</em>]</span>\n<pre>void luaL_register (lua_State *L,\n                    const char *libname,\n                    const luaL_Reg *l);</pre>\n\n<p>\nOpens a library.\n\n\n<p>\nWhen called with <code>libname</code> equal to <code>NULL</code>,\nit simply registers all functions in the list <code>l</code>\n(see <a href=\"#luaL_Reg\"><code>luaL_Reg</code></a>) into the table on the top of the stack.\n\n\n<p>\nWhen called with a non-null <code>libname</code>,\n<code>luaL_register</code> creates a new table <code>t</code>,\nsets it as the value of the global variable <code>libname</code>,\nsets it as the value of <code>package.loaded[libname]</code>,\nand registers on it all functions in the list <code>l</code>.\nIf there is a table in <code>package.loaded[libname]</code> or in\nvariable <code>libname</code>,\nreuses this table instead of creating a new one.\n\n\n<p>\nIn any case the function leaves the table\non the top of the stack.\n\n\n\n\n\n<hr><h3><a name=\"luaL_typename\"><code>luaL_typename</code></a></h3><p>\n<span class=\"apii\">[-0, +0, <em>-</em>]</span>\n<pre>const char *luaL_typename (lua_State *L, int index);</pre>\n\n<p>\nReturns the name of the type of the value at the given index.\n\n\n\n\n\n<hr><h3><a name=\"luaL_typerror\"><code>luaL_typerror</code></a></h3><p>\n<span class=\"apii\">[-0, +0, <em>v</em>]</span>\n<pre>int luaL_typerror (lua_State *L, int narg, const char *tname);</pre>\n\n<p>\nGenerates an error with a message like the following:\n\n<pre>\n     <em>location</em>: bad argument <em>narg</em> to '<em>func</em>' (<em>tname</em> expected, got <em>rt</em>)\n</pre><p>\nwhere <code><em>location</em></code> is produced by <a href=\"#luaL_where\"><code>luaL_where</code></a>,\n<code><em>func</em></code> is the name of the current function,\nand <code><em>rt</em></code> is the type name of the actual argument.\n\n\n\n\n\n<hr><h3><a name=\"luaL_unref\"><code>luaL_unref</code></a></h3><p>\n<span class=\"apii\">[-0, +0, <em>-</em>]</span>\n<pre>void luaL_unref (lua_State *L, int t, int ref);</pre>\n\n<p>\nReleases reference <code>ref</code> from the table at index <code>t</code>\n(see <a href=\"#luaL_ref\"><code>luaL_ref</code></a>).\nThe entry is removed from the table,\nso that the referred object can be collected.\nThe reference <code>ref</code> is also freed to be used again.\n\n\n<p>\nIf <code>ref</code> is <a href=\"#pdf-LUA_NOREF\"><code>LUA_NOREF</code></a> or <a href=\"#pdf-LUA_REFNIL\"><code>LUA_REFNIL</code></a>,\n<a href=\"#luaL_unref\"><code>luaL_unref</code></a> does nothing.\n\n\n\n\n\n<hr><h3><a name=\"luaL_where\"><code>luaL_where</code></a></h3><p>\n<span class=\"apii\">[-0, +1, <em>m</em>]</span>\n<pre>void luaL_where (lua_State *L, int lvl);</pre>\n\n<p>\nPushes onto the stack a string identifying the current position\nof the control at level <code>lvl</code> in the call stack.\nTypically this string has the following format:\n\n<pre>\n     <em>chunkname</em>:<em>currentline</em>:\n</pre><p>\nLevel&nbsp;0 is the running function,\nlevel&nbsp;1 is the function that called the running function,\netc.\n\n\n<p>\nThis function is used to build a prefix for error messages.\n\n\n\n\n\n\n\n<h1>5 - <a name=\"5\">Standard Libraries</a></h1>\n\n<p>\nThe standard Lua libraries provide useful functions\nthat are implemented directly through the C&nbsp;API.\nSome of these functions provide essential services to the language\n(e.g., <a href=\"#pdf-type\"><code>type</code></a> and <a href=\"#pdf-getmetatable\"><code>getmetatable</code></a>);\nothers provide access to \"outside\" services (e.g., I/O);\nand others could be implemented in Lua itself,\nbut are quite useful or have critical performance requirements that\ndeserve an implementation in C (e.g., <a href=\"#pdf-table.sort\"><code>table.sort</code></a>).\n\n\n<p>\nAll libraries are implemented through the official C&nbsp;API\nand are provided as separate C&nbsp;modules.\nCurrently, Lua has the following standard libraries:\n\n<ul>\n\n<li>basic library, which includes the coroutine sub-library;</li>\n\n<li>package library;</li>\n\n<li>string manipulation;</li>\n\n<li>table manipulation;</li>\n\n<li>mathematical functions (sin, log, etc.);</li>\n\n<li>input and output;</li>\n\n<li>operating system facilities;</li>\n\n<li>debug facilities.</li>\n\n</ul><p>\nExcept for the basic and package libraries,\neach library provides all its functions as fields of a global table\nor as methods of its objects.\n\n\n<p>\nTo have access to these libraries,\nthe C&nbsp;host program should call the <a href=\"#luaL_openlibs\"><code>luaL_openlibs</code></a> function,\nwhich opens all standard libraries.\nAlternatively,\nit can open them individually by calling\n<a name=\"pdf-luaopen_base\"><code>luaopen_base</code></a> (for the basic library),\n<a name=\"pdf-luaopen_package\"><code>luaopen_package</code></a> (for the package library),\n<a name=\"pdf-luaopen_string\"><code>luaopen_string</code></a> (for the string library),\n<a name=\"pdf-luaopen_table\"><code>luaopen_table</code></a> (for the table library),\n<a name=\"pdf-luaopen_math\"><code>luaopen_math</code></a> (for the mathematical library),\n<a name=\"pdf-luaopen_io\"><code>luaopen_io</code></a> (for the I/O library),\n<a name=\"pdf-luaopen_os\"><code>luaopen_os</code></a> (for the Operating System library),\nand <a name=\"pdf-luaopen_debug\"><code>luaopen_debug</code></a> (for the debug library).\nThese functions are declared in <a name=\"pdf-lualib.h\"><code>lualib.h</code></a>\nand should not be called directly:\nyou must call them like any other Lua C&nbsp;function,\ne.g., by using <a href=\"#lua_call\"><code>lua_call</code></a>.\n\n\n\n<h2>5.1 - <a name=\"5.1\">Basic Functions</a></h2>\n\n<p>\nThe basic library provides some core functions to Lua.\nIf you do not include this library in your application,\nyou should check carefully whether you need to provide \nimplementations for some of its facilities.\n\n\n<p>\n<hr><h3><a name=\"pdf-assert\"><code>assert (v [, message])</code></a></h3>\nIssues an  error when\nthe value of its argument <code>v</code> is false (i.e., <b>nil</b> or <b>false</b>);\notherwise, returns all its arguments.\n<code>message</code> is an error message;\nwhen absent, it defaults to \"assertion failed!\"\n\n\n\n\n<p>\n<hr><h3><a name=\"pdf-collectgarbage\"><code>collectgarbage ([opt [, arg]])</code></a></h3>\n\n\n<p>\nThis function is a generic interface to the garbage collector.\nIt performs different functions according to its first argument, <code>opt</code>:\n\n<ul>\n\n<li><b>\"collect\":</b>\nperforms a full garbage-collection cycle.\nThis is the default option.\n</li>\n\n<li><b>\"stop\":</b>\nstops the garbage collector.\n</li>\n\n<li><b>\"restart\":</b>\nrestarts the garbage collector.\n</li>\n\n<li><b>\"count\":</b>\nreturns the total memory in use by Lua (in Kbytes).\n</li>\n\n<li><b>\"step\":</b>\nperforms a garbage-collection step.\nThe step \"size\" is controlled by <code>arg</code>\n(larger values mean more steps) in a non-specified way.\nIf you want to control the step size\nyou must experimentally tune the value of <code>arg</code>.\nReturns <b>true</b> if the step finished a collection cycle.\n</li>\n\n<li><b>\"setpause\":</b>\nsets <code>arg</code> as the new value for the <em>pause</em> of\nthe collector (see <a href=\"#2.10\">&sect;2.10</a>).\nReturns the previous value for <em>pause</em>.\n</li>\n\n<li><b>\"setstepmul\":</b>\nsets <code>arg</code> as the new value for the <em>step multiplier</em> of\nthe collector (see <a href=\"#2.10\">&sect;2.10</a>).\nReturns the previous value for <em>step</em>.\n</li>\n\n</ul>\n\n\n\n<p>\n<hr><h3><a name=\"pdf-dofile\"><code>dofile ([filename])</code></a></h3>\nOpens the named file and executes its contents as a Lua chunk.\nWhen called without arguments,\n<code>dofile</code> executes the contents of the standard input (<code>stdin</code>).\nReturns all values returned by the chunk.\nIn case of errors, <code>dofile</code> propagates the error\nto its caller (that is, <code>dofile</code> does not run in protected mode).\n\n\n\n\n<p>\n<hr><h3><a name=\"pdf-error\"><code>error (message [, level])</code></a></h3>\nTerminates the last protected function called\nand returns <code>message</code> as the error message.\nFunction <code>error</code> never returns.\n\n\n<p>\nUsually, <code>error</code> adds some information about the error position\nat the beginning of the message.\nThe <code>level</code> argument specifies how to get the error position.\nWith level&nbsp;1 (the default), the error position is where the\n<code>error</code> function was called.\nLevel&nbsp;2 points the error to where the function\nthat called <code>error</code> was called; and so on.\nPassing a level&nbsp;0 avoids the addition of error position information\nto the message.\n\n\n\n\n<p>\n<hr><h3><a name=\"pdf-_G\"><code>_G</code></a></h3>\nA global variable (not a function) that\nholds the global environment (that is, <code>_G._G = _G</code>).\nLua itself does not use this variable;\nchanging its value does not affect any environment,\nnor vice-versa.\n(Use <a href=\"#pdf-setfenv\"><code>setfenv</code></a> to change environments.)\n\n\n\n\n<p>\n<hr><h3><a name=\"pdf-getfenv\"><code>getfenv ([f])</code></a></h3>\nReturns the current environment in use by the function.\n<code>f</code> can be a Lua function or a number\nthat specifies the function at that stack level:\nLevel&nbsp;1 is the function calling <code>getfenv</code>.\nIf the given function is not a Lua function,\nor if <code>f</code> is 0,\n<code>getfenv</code> returns the global environment.\nThe default for <code>f</code> is 1.\n\n\n\n\n<p>\n<hr><h3><a name=\"pdf-getmetatable\"><code>getmetatable (object)</code></a></h3>\n\n\n<p>\nIf <code>object</code> does not have a metatable, returns <b>nil</b>.\nOtherwise,\nif the object's metatable has a <code>\"__metatable\"</code> field,\nreturns the associated value.\nOtherwise, returns the metatable of the given object.\n\n\n\n\n<p>\n<hr><h3><a name=\"pdf-ipairs\"><code>ipairs (t)</code></a></h3>\n\n\n<p>\nReturns three values: an iterator function, the table <code>t</code>, and 0,\nso that the construction\n\n<pre>\n     for i,v in ipairs(t) do <em>body</em> end\n</pre><p>\nwill iterate over the pairs (<code>1,t[1]</code>), (<code>2,t[2]</code>), &middot;&middot;&middot;,\nup to the first integer key absent from the table.\n\n\n\n\n<p>\n<hr><h3><a name=\"pdf-load\"><code>load (func [, chunkname])</code></a></h3>\n\n\n<p>\nLoads a chunk using function <code>func</code> to get its pieces.\nEach call to <code>func</code> must return a string that concatenates\nwith previous results.\nA return of an empty string, <b>nil</b>, or no value signals the end of the chunk.\n\n\n<p>\nIf there are no errors, \nreturns the compiled chunk as a function;\notherwise, returns <b>nil</b> plus the error message.\nThe environment of the returned function is the global environment.\n\n\n<p>\n<code>chunkname</code> is used as the chunk name for error messages\nand debug information.\nWhen absent,\nit defaults to \"<code>=(load)</code>\".\n\n\n\n\n<p>\n<hr><h3><a name=\"pdf-loadfile\"><code>loadfile ([filename])</code></a></h3>\n\n\n<p>\nSimilar to <a href=\"#pdf-load\"><code>load</code></a>,\nbut gets the chunk from file <code>filename</code>\nor from the standard input,\nif no file name is given.\n\n\n\n\n<p>\n<hr><h3><a name=\"pdf-loadstring\"><code>loadstring (string [, chunkname])</code></a></h3>\n\n\n<p>\nSimilar to <a href=\"#pdf-load\"><code>load</code></a>,\nbut gets the chunk from the given string.\n\n\n<p>\nTo load and run a given string, use the idiom\n\n<pre>\n     assert(loadstring(s))()\n</pre>\n\n<p>\nWhen absent,\n<code>chunkname</code> defaults to the given string.\n\n\n\n\n<p>\n<hr><h3><a name=\"pdf-next\"><code>next (table [, index])</code></a></h3>\n\n\n<p>\nAllows a program to traverse all fields of a table.\nIts first argument is a table and its second argument\nis an index in this table.\n<code>next</code> returns the next index of the table\nand its associated value.\nWhen called with <b>nil</b> as its second argument,\n<code>next</code> returns an initial index\nand its associated value.\nWhen called with the last index,\nor with <b>nil</b> in an empty table,\n<code>next</code> returns <b>nil</b>.\nIf the second argument is absent, then it is interpreted as <b>nil</b>.\nIn particular,\nyou can use <code>next(t)</code> to check whether a table is empty.\n\n\n<p>\nThe order in which the indices are enumerated is not specified,\n<em>even for numeric indices</em>.\n(To traverse a table in numeric order,\nuse a numerical <b>for</b> or the <a href=\"#pdf-ipairs\"><code>ipairs</code></a> function.)\n\n\n<p>\nThe behavior of <code>next</code> is <em>undefined</em> if,\nduring the traversal,\nyou assign any value to a non-existent field in the table.\nYou may however modify existing fields.\nIn particular, you may clear existing fields.\n\n\n\n\n<p>\n<hr><h3><a name=\"pdf-pairs\"><code>pairs (t)</code></a></h3>\n\n\n<p>\nReturns three values: the <a href=\"#pdf-next\"><code>next</code></a> function, the table <code>t</code>, and <b>nil</b>,\nso that the construction\n\n<pre>\n     for k,v in pairs(t) do <em>body</em> end\n</pre><p>\nwill iterate over all key&ndash;value pairs of table <code>t</code>.\n\n\n<p>\nSee function <a href=\"#pdf-next\"><code>next</code></a> for the caveats of modifying\nthe table during its traversal.\n\n\n\n\n<p>\n<hr><h3><a name=\"pdf-pcall\"><code>pcall (f, arg1, &middot;&middot;&middot;)</code></a></h3>\n\n\n<p>\nCalls function <code>f</code> with\nthe given arguments in <em>protected mode</em>.\nThis means that any error inside&nbsp;<code>f</code> is not propagated;\ninstead, <code>pcall</code> catches the error\nand returns a status code.\nIts first result is the status code (a boolean),\nwhich is true if the call succeeds without errors.\nIn such case, <code>pcall</code> also returns all results from the call,\nafter this first result.\nIn case of any error, <code>pcall</code> returns <b>false</b> plus the error message.\n\n\n\n\n<p>\n<hr><h3><a name=\"pdf-print\"><code>print (&middot;&middot;&middot;)</code></a></h3>\nReceives any number of arguments,\nand prints their values to <code>stdout</code>,\nusing the <a href=\"#pdf-tostring\"><code>tostring</code></a> function to convert them to strings.\n<code>print</code> is not intended for formatted output,\nbut only as a quick way to show a value,\ntypically for debugging.\nFor formatted output, use <a href=\"#pdf-string.format\"><code>string.format</code></a>.\n\n\n\n\n<p>\n<hr><h3><a name=\"pdf-rawequal\"><code>rawequal (v1, v2)</code></a></h3>\nChecks whether <code>v1</code> is equal to <code>v2</code>,\nwithout invoking any metamethod.\nReturns a boolean.\n\n\n\n\n<p>\n<hr><h3><a name=\"pdf-rawget\"><code>rawget (table, index)</code></a></h3>\nGets the real value of <code>table[index]</code>,\nwithout invoking any metamethod.\n<code>table</code> must be a table;\n<code>index</code> may be any value.\n\n\n\n\n<p>\n<hr><h3><a name=\"pdf-rawset\"><code>rawset (table, index, value)</code></a></h3>\nSets the real value of <code>table[index]</code> to <code>value</code>,\nwithout invoking any metamethod.\n<code>table</code> must be a table,\n<code>index</code> any value different from <b>nil</b>,\nand <code>value</code> any Lua value.\n\n\n<p>\nThis function returns <code>table</code>.\n\n\n\n\n<p>\n<hr><h3><a name=\"pdf-select\"><code>select (index, &middot;&middot;&middot;)</code></a></h3>\n\n\n<p>\nIf <code>index</code> is a number,\nreturns all arguments after argument number <code>index</code>.\nOtherwise, <code>index</code> must be the string <code>\"#\"</code>,\nand <code>select</code> returns the total number of extra arguments it received.\n\n\n\n\n<p>\n<hr><h3><a name=\"pdf-setfenv\"><code>setfenv (f, table)</code></a></h3>\n\n\n<p>\nSets the environment to be used by the given function.\n<code>f</code> can be a Lua function or a number\nthat specifies the function at that stack level:\nLevel&nbsp;1 is the function calling <code>setfenv</code>.\n<code>setfenv</code> returns the given function.\n\n\n<p>\nAs a special case, when <code>f</code> is 0 <code>setfenv</code> changes\nthe environment of the running thread.\nIn this case, <code>setfenv</code> returns no values.\n\n\n\n\n<p>\n<hr><h3><a name=\"pdf-setmetatable\"><code>setmetatable (table, metatable)</code></a></h3>\n\n\n<p>\nSets the metatable for the given table.\n(You cannot change the metatable of other types from Lua, only from&nbsp;C.)\nIf <code>metatable</code> is <b>nil</b>,\nremoves the metatable of the given table.\nIf the original metatable has a <code>\"__metatable\"</code> field,\nraises an error.\n\n\n<p>\nThis function returns <code>table</code>.\n\n\n\n\n<p>\n<hr><h3><a name=\"pdf-tonumber\"><code>tonumber (e [, base])</code></a></h3>\nTries to convert its argument to a number.\nIf the argument is already a number or a string convertible\nto a number, then <code>tonumber</code> returns this number;\notherwise, it returns <b>nil</b>.\n\n\n<p>\nAn optional argument specifies the base to interpret the numeral.\nThe base may be any integer between 2 and 36, inclusive.\nIn bases above&nbsp;10, the letter '<code>A</code>' (in either upper or lower case)\nrepresents&nbsp;10, '<code>B</code>' represents&nbsp;11, and so forth,\nwith '<code>Z</code>' representing 35.\nIn base 10 (the default), the number can have a decimal part,\nas well as an optional exponent part (see <a href=\"#2.1\">&sect;2.1</a>).\nIn other bases, only unsigned integers are accepted.\n\n\n\n\n<p>\n<hr><h3><a name=\"pdf-tostring\"><code>tostring (e)</code></a></h3>\nReceives an argument of any type and\nconverts it to a string in a reasonable format.\nFor complete control of how numbers are converted,\nuse <a href=\"#pdf-string.format\"><code>string.format</code></a>.\n\n\n<p>\nIf the metatable of <code>e</code> has a <code>\"__tostring\"</code> field,\nthen <code>tostring</code> calls the corresponding value\nwith <code>e</code> as argument,\nand uses the result of the call as its result.\n\n\n\n\n<p>\n<hr><h3><a name=\"pdf-type\"><code>type (v)</code></a></h3>\nReturns the type of its only argument, coded as a string.\nThe possible results of this function are\n\"<code>nil</code>\" (a string, not the value <b>nil</b>),\n\"<code>number</code>\",\n\"<code>string</code>\",\n\"<code>boolean</code>\",\n\"<code>table</code>\",\n\"<code>function</code>\",\n\"<code>thread</code>\",\nand \"<code>userdata</code>\".\n\n\n\n\n<p>\n<hr><h3><a name=\"pdf-unpack\"><code>unpack (list [, i [, j]])</code></a></h3>\nReturns the elements from the given table.\nThis function is equivalent to\n\n<pre>\n     return list[i], list[i+1], &middot;&middot;&middot;, list[j]\n</pre><p>\nexcept that the above code can be written only for a fixed number\nof elements.\nBy default, <code>i</code> is&nbsp;1 and <code>j</code> is the length of the list,\nas defined by the length operator (see <a href=\"#2.5.5\">&sect;2.5.5</a>).\n\n\n\n\n<p>\n<hr><h3><a name=\"pdf-_VERSION\"><code>_VERSION</code></a></h3>\nA global variable (not a function) that\nholds a string containing the current interpreter version.\nThe current contents of this variable is \"<code>Lua 5.1</code>\".\n\n\n\n\n<p>\n<hr><h3><a name=\"pdf-xpcall\"><code>xpcall (f, err)</code></a></h3>\n\n\n<p>\nThis function is similar to <a href=\"#pdf-pcall\"><code>pcall</code></a>,\nexcept that you can set a new error handler.\n\n\n<p>\n<code>xpcall</code> calls function <code>f</code> in protected mode,\nusing <code>err</code> as the error handler.\nAny error inside <code>f</code> is not propagated;\ninstead, <code>xpcall</code> catches the error,\ncalls the <code>err</code> function with the original error object,\nand returns a status code.\nIts first result is the status code (a boolean),\nwhich is true if the call succeeds without errors.\nIn this case, <code>xpcall</code> also returns all results from the call,\nafter this first result.\nIn case of any error,\n<code>xpcall</code> returns <b>false</b> plus the result from <code>err</code>.\n\n\n\n\n\n\n\n<h2>5.2 - <a name=\"5.2\">Coroutine Manipulation</a></h2>\n\n<p>\nThe operations related to coroutines comprise a sub-library of\nthe basic library and come inside the table <a name=\"pdf-coroutine\"><code>coroutine</code></a>.\nSee <a href=\"#2.11\">&sect;2.11</a> for a general description of coroutines.\n\n\n<p>\n<hr><h3><a name=\"pdf-coroutine.create\"><code>coroutine.create (f)</code></a></h3>\n\n\n<p>\nCreates a new coroutine, with body <code>f</code>.\n<code>f</code> must be a Lua function.\nReturns this new coroutine,\nan object with type <code>\"thread\"</code>.\n\n\n\n\n<p>\n<hr><h3><a name=\"pdf-coroutine.resume\"><code>coroutine.resume (co [, val1, &middot;&middot;&middot;])</code></a></h3>\n\n\n<p>\nStarts or continues the execution of coroutine <code>co</code>.\nThe first time you resume a coroutine,\nit starts running its body.\nThe values <code>val1</code>, &middot;&middot;&middot; are passed\nas the arguments to the body function.\nIf the coroutine has yielded,\n<code>resume</code> restarts it;\nthe values <code>val1</code>, &middot;&middot;&middot; are passed\nas the results from the yield.\n\n\n<p>\nIf the coroutine runs without any errors,\n<code>resume</code> returns <b>true</b> plus any values passed to <code>yield</code>\n(if the coroutine yields) or any values returned by the body function\n(if the coroutine terminates).\nIf there is any error,\n<code>resume</code> returns <b>false</b> plus the error message.\n\n\n\n\n<p>\n<hr><h3><a name=\"pdf-coroutine.running\"><code>coroutine.running ()</code></a></h3>\n\n\n<p>\nReturns the running coroutine,\nor <b>nil</b> when called by the main thread.\n\n\n\n\n<p>\n<hr><h3><a name=\"pdf-coroutine.status\"><code>coroutine.status (co)</code></a></h3>\n\n\n<p>\nReturns the status of coroutine <code>co</code>, as a string:\n<code>\"running\"</code>,\nif the coroutine is running (that is, it called <code>status</code>);\n<code>\"suspended\"</code>, if the coroutine is suspended in a call to <code>yield</code>,\nor if it has not started running yet;\n<code>\"normal\"</code> if the coroutine is active but not running\n(that is, it has resumed another coroutine);\nand <code>\"dead\"</code> if the coroutine has finished its body function,\nor if it has stopped with an error.\n\n\n\n\n<p>\n<hr><h3><a name=\"pdf-coroutine.wrap\"><code>coroutine.wrap (f)</code></a></h3>\n\n\n<p>\nCreates a new coroutine, with body <code>f</code>.\n<code>f</code> must be a Lua function.\nReturns a function that resumes the coroutine each time it is called.\nAny arguments passed to the function behave as the\nextra arguments to <code>resume</code>.\nReturns the same values returned by <code>resume</code>,\nexcept the first boolean.\nIn case of error, propagates the error.\n\n\n\n\n<p>\n<hr><h3><a name=\"pdf-coroutine.yield\"><code>coroutine.yield (&middot;&middot;&middot;)</code></a></h3>\n\n\n<p>\nSuspends the execution of the calling coroutine.\nThe coroutine cannot be running a C&nbsp;function,\na metamethod, or an iterator.\nAny arguments to <code>yield</code> are passed as extra results to <code>resume</code>.\n\n\n\n\n\n\n\n<h2>5.3 - <a name=\"5.3\">Modules</a></h2>\n\n<p>\nThe package library provides basic\nfacilities for loading and building modules in Lua.\nIt exports two of its functions directly in the global environment:\n<a href=\"#pdf-require\"><code>require</code></a> and <a href=\"#pdf-module\"><code>module</code></a>.\nEverything else is exported in a table <a name=\"pdf-package\"><code>package</code></a>.\n\n\n<p>\n<hr><h3><a name=\"pdf-module\"><code>module (name [, &middot;&middot;&middot;])</code></a></h3>\n\n\n<p>\nCreates a module.\nIf there is a table in <code>package.loaded[name]</code>,\nthis table is the module.\nOtherwise, if there is a global table <code>t</code> with the given name,\nthis table is the module.\nOtherwise creates a new table <code>t</code> and\nsets it as the value of the global <code>name</code> and\nthe value of <code>package.loaded[name]</code>.\nThis function also initializes <code>t._NAME</code> with the given name,\n<code>t._M</code> with the module (<code>t</code> itself),\nand <code>t._PACKAGE</code> with the package name\n(the full module name minus last component; see below).\nFinally, <code>module</code> sets <code>t</code> as the new environment\nof the current function and the new value of <code>package.loaded[name]</code>,\nso that <a href=\"#pdf-require\"><code>require</code></a> returns <code>t</code>.\n\n\n<p>\nIf <code>name</code> is a compound name\n(that is, one with components separated by dots),\n<code>module</code> creates (or reuses, if they already exist)\ntables for each component.\nFor instance, if <code>name</code> is <code>a.b.c</code>,\nthen <code>module</code> stores the module table in field <code>c</code> of\nfield <code>b</code> of global <code>a</code>.\n\n\n<p>\nThis function can receive optional <em>options</em> after\nthe module name,\nwhere each option is a function to be applied over the module.\n\n\n\n\n<p>\n<hr><h3><a name=\"pdf-require\"><code>require (modname)</code></a></h3>\n\n\n<p>\nLoads the given module.\nThe function starts by looking into the <a href=\"#pdf-package.loaded\"><code>package.loaded</code></a> table\nto determine whether <code>modname</code> is already loaded.\nIf it is, then <code>require</code> returns the value stored\nat <code>package.loaded[modname]</code>.\nOtherwise, it tries to find a <em>loader</em> for the module.\n\n\n<p>\nTo find a loader,\n<code>require</code> is guided by the <a href=\"#pdf-package.loaders\"><code>package.loaders</code></a> array.\nBy changing this array,\nwe can change how <code>require</code> looks for a module.\nThe following explanation is based on the default configuration\nfor <a href=\"#pdf-package.loaders\"><code>package.loaders</code></a>.\n\n\n<p>\nFirst <code>require</code> queries <code>package.preload[modname]</code>.\nIf it has a value,\nthis value (which should be a function) is the loader.\nOtherwise <code>require</code> searches for a Lua loader using the\npath stored in <a href=\"#pdf-package.path\"><code>package.path</code></a>.\nIf that also fails, it searches for a C&nbsp;loader using the\npath stored in <a href=\"#pdf-package.cpath\"><code>package.cpath</code></a>.\nIf that also fails,\nit tries an <em>all-in-one</em> loader (see <a href=\"#pdf-package.loaders\"><code>package.loaders</code></a>).\n\n\n<p>\nOnce a loader is found,\n<code>require</code> calls the loader with a single argument, <code>modname</code>.\nIf the loader returns any value,\n<code>require</code> assigns the returned value to <code>package.loaded[modname]</code>.\nIf the loader returns no value and\nhas not assigned any value to <code>package.loaded[modname]</code>,\nthen <code>require</code> assigns <b>true</b> to this entry.\nIn any case, <code>require</code> returns the\nfinal value of <code>package.loaded[modname]</code>.\n\n\n<p>\nIf there is any error loading or running the module,\nor if it cannot find any loader for the module,\nthen <code>require</code> signals an error. \n\n\n\n\n<p>\n<hr><h3><a name=\"pdf-package.cpath\"><code>package.cpath</code></a></h3>\n\n\n<p>\nThe path used by <a href=\"#pdf-require\"><code>require</code></a> to search for a C&nbsp;loader.\n\n\n<p>\nLua initializes the C&nbsp;path <a href=\"#pdf-package.cpath\"><code>package.cpath</code></a> in the same way\nit initializes the Lua path <a href=\"#pdf-package.path\"><code>package.path</code></a>,\nusing the environment variable <a name=\"pdf-LUA_CPATH\"><code>LUA_CPATH</code></a>\nor a default path defined in <code>luaconf.h</code>.\n\n\n\n\n<p>\n\n<hr><h3><a name=\"pdf-package.loaded\"><code>package.loaded</code></a></h3>\n\n\n<p>\nA table used by <a href=\"#pdf-require\"><code>require</code></a> to control which\nmodules are already loaded.\nWhen you require a module <code>modname</code> and\n<code>package.loaded[modname]</code> is not false,\n<a href=\"#pdf-require\"><code>require</code></a> simply returns the value stored there.\n\n\n\n\n<p>\n<hr><h3><a name=\"pdf-package.loaders\"><code>package.loaders</code></a></h3>\n\n\n<p>\nA table used by <a href=\"#pdf-require\"><code>require</code></a> to control how to load modules.\n\n\n<p>\nEach entry in this table is a <em>searcher function</em>.\nWhen looking for a module,\n<a href=\"#pdf-require\"><code>require</code></a> calls each of these searchers in ascending order,\nwith the module name (the argument given to <a href=\"#pdf-require\"><code>require</code></a>) as its\nsole parameter.\nThe function can return another function (the module <em>loader</em>)\nor a string explaining why it did not find that module\n(or <b>nil</b> if it has nothing to say).\nLua initializes this table with four functions.\n\n\n<p>\nThe first searcher simply looks for a loader in the\n<a href=\"#pdf-package.preload\"><code>package.preload</code></a> table.\n\n\n<p>\nThe second searcher looks for a loader as a Lua library,\nusing the path stored at <a href=\"#pdf-package.path\"><code>package.path</code></a>.\nA path is a sequence of <em>templates</em> separated by semicolons.\nFor each template,\nthe searcher will change each interrogation\nmark in the template by <code>filename</code>,\nwhich is the module name with each dot replaced by a\n\"directory separator\" (such as \"<code>/</code>\" in Unix);\nthen it will try to open the resulting file name.\nSo, for instance, if the Lua path is the string\n\n<pre>\n     \"./?.lua;./?.lc;/usr/local/?/init.lua\"\n</pre><p>\nthe search for a Lua file for module <code>foo</code>\nwill try to open the files\n<code>./foo.lua</code>, <code>./foo.lc</code>, and\n<code>/usr/local/foo/init.lua</code>, in that order.\n\n\n<p>\nThe third searcher looks for a loader as a C&nbsp;library,\nusing the path given by the variable <a href=\"#pdf-package.cpath\"><code>package.cpath</code></a>.\nFor instance,\nif the C&nbsp;path is the string\n\n<pre>\n     \"./?.so;./?.dll;/usr/local/?/init.so\"\n</pre><p>\nthe searcher for module <code>foo</code>\nwill try to open the files <code>./foo.so</code>, <code>./foo.dll</code>,\nand <code>/usr/local/foo/init.so</code>, in that order.\nOnce it finds a C&nbsp;library,\nthis searcher first uses a dynamic link facility to link the\napplication with the library.\nThen it tries to find a C&nbsp;function inside the library to\nbe used as the loader.\nThe name of this C&nbsp;function is the string \"<code>luaopen_</code>\"\nconcatenated with a copy of the module name where each dot\nis replaced by an underscore.\nMoreover, if the module name has a hyphen,\nits prefix up to (and including) the first hyphen is removed.\nFor instance, if the module name is <code>a.v1-b.c</code>,\nthe function name will be <code>luaopen_b_c</code>.\n\n\n<p>\nThe fourth searcher tries an <em>all-in-one loader</em>.\nIt searches the C&nbsp;path for a library for\nthe root name of the given module.\nFor instance, when requiring <code>a.b.c</code>,\nit will search for a C&nbsp;library for <code>a</code>.\nIf found, it looks into it for an open function for\nthe submodule;\nin our example, that would be <code>luaopen_a_b_c</code>.\nWith this facility, a package can pack several C&nbsp;submodules\ninto one single library,\nwith each submodule keeping its original open function.\n\n\n\n\n<p>\n<hr><h3><a name=\"pdf-package.loadlib\"><code>package.loadlib (libname, funcname)</code></a></h3>\n\n\n<p>\nDynamically links the host program with the C&nbsp;library <code>libname</code>.\nInside this library, looks for a function <code>funcname</code>\nand returns this function as a C&nbsp;function.\n(So, <code>funcname</code> must follow the protocol (see <a href=\"#lua_CFunction\"><code>lua_CFunction</code></a>)).\n\n\n<p>\nThis is a low-level function.\nIt completely bypasses the package and module system.\nUnlike <a href=\"#pdf-require\"><code>require</code></a>,\nit does not perform any path searching and\ndoes not automatically adds extensions.\n<code>libname</code> must be the complete file name of the C&nbsp;library,\nincluding if necessary a path and extension.\n<code>funcname</code> must be the exact name exported by the C&nbsp;library\n(which may depend on the C&nbsp;compiler and linker used).\n\n\n<p>\nThis function is not supported by ANSI C.\nAs such, it is only available on some platforms\n(Windows, Linux, Mac OS X, Solaris, BSD,\nplus other Unix systems that support the <code>dlfcn</code> standard).\n\n\n\n\n<p>\n<hr><h3><a name=\"pdf-package.path\"><code>package.path</code></a></h3>\n\n\n<p>\nThe path used by <a href=\"#pdf-require\"><code>require</code></a> to search for a Lua loader.\n\n\n<p>\nAt start-up, Lua initializes this variable with\nthe value of the environment variable <a name=\"pdf-LUA_PATH\"><code>LUA_PATH</code></a> or\nwith a default path defined in <code>luaconf.h</code>,\nif the environment variable is not defined.\nAny \"<code>;;</code>\" in the value of the environment variable\nis replaced by the default path.\n\n\n\n\n<p>\n<hr><h3><a name=\"pdf-package.preload\"><code>package.preload</code></a></h3>\n\n\n<p>\nA table to store loaders for specific modules\n(see <a href=\"#pdf-require\"><code>require</code></a>).\n\n\n\n\n<p>\n<hr><h3><a name=\"pdf-package.seeall\"><code>package.seeall (module)</code></a></h3>\n\n\n<p>\nSets a metatable for <code>module</code> with\nits <code>__index</code> field referring to the global environment,\nso that this module inherits values\nfrom the global environment.\nTo be used as an option to function <a href=\"#pdf-module\"><code>module</code></a>.\n\n\n\n\n\n\n\n<h2>5.4 - <a name=\"5.4\">String Manipulation</a></h2>\n\n<p>\nThis library provides generic functions for string manipulation,\nsuch as finding and extracting substrings, and pattern matching.\nWhen indexing a string in Lua, the first character is at position&nbsp;1\n(not at&nbsp;0, as in C).\nIndices are allowed to be negative and are interpreted as indexing backwards,\nfrom the end of the string.\nThus, the last character is at position -1, and so on.\n\n\n<p>\nThe string library provides all its functions inside the table\n<a name=\"pdf-string\"><code>string</code></a>.\nIt also sets a metatable for strings\nwhere the <code>__index</code> field points to the <code>string</code> table.\nTherefore, you can use the string functions in object-oriented style.\nFor instance, <code>string.byte(s, i)</code>\ncan be written as <code>s:byte(i)</code>.\n\n\n<p>\nThe string library assumes one-byte character encodings.\n\n\n<p>\n<hr><h3><a name=\"pdf-string.byte\"><code>string.byte (s [, i [, j]])</code></a></h3>\nReturns the internal numerical codes of the characters <code>s[i]</code>,\n<code>s[i+1]</code>, &middot;&middot;&middot;, <code>s[j]</code>.\nThe default value for <code>i</code> is&nbsp;1;\nthe default value for <code>j</code> is&nbsp;<code>i</code>.\n\n\n<p>\nNote that numerical codes are not necessarily portable across platforms.\n\n\n\n\n<p>\n<hr><h3><a name=\"pdf-string.char\"><code>string.char (&middot;&middot;&middot;)</code></a></h3>\nReceives zero or more integers.\nReturns a string with length equal to the number of arguments,\nin which each character has the internal numerical code equal\nto its corresponding argument.\n\n\n<p>\nNote that numerical codes are not necessarily portable across platforms.\n\n\n\n\n<p>\n<hr><h3><a name=\"pdf-string.dump\"><code>string.dump (function)</code></a></h3>\n\n\n<p>\nReturns a string containing a binary representation of the given function,\nso that a later <a href=\"#pdf-loadstring\"><code>loadstring</code></a> on this string returns\na copy of the function.\n<code>function</code> must be a Lua function without upvalues.\n\n\n\n\n<p>\n<hr><h3><a name=\"pdf-string.find\"><code>string.find (s, pattern [, init [, plain]])</code></a></h3>\nLooks for the first match of\n<code>pattern</code> in the string <code>s</code>.\nIf it finds a match, then <code>find</code> returns the indices of&nbsp;<code>s</code>\nwhere this occurrence starts and ends;\notherwise, it returns <b>nil</b>.\nA third, optional numerical argument <code>init</code> specifies\nwhere to start the search;\nits default value is&nbsp;1 and can be negative.\nA value of <b>true</b> as a fourth, optional argument <code>plain</code>\nturns off the pattern matching facilities,\nso the function does a plain \"find substring\" operation,\nwith no characters in <code>pattern</code> being considered \"magic\".\nNote that if <code>plain</code> is given, then <code>init</code> must be given as well.\n\n\n<p>\nIf the pattern has captures,\nthen in a successful match\nthe captured values are also returned,\nafter the two indices.\n\n\n\n\n<p>\n<hr><h3><a name=\"pdf-string.format\"><code>string.format (formatstring, &middot;&middot;&middot;)</code></a></h3>\nReturns a formatted version of its variable number of arguments\nfollowing the description given in its first argument (which must be a string).\nThe format string follows the same rules as the <code>printf</code> family of\nstandard C&nbsp;functions.\nThe only differences are that the options/modifiers\n<code>*</code>, <code>l</code>, <code>L</code>, <code>n</code>, <code>p</code>,\nand <code>h</code> are not supported\nand that there is an extra option, <code>q</code>.\nThe <code>q</code> option formats a string in a form suitable to be safely read\nback by the Lua interpreter:\nthe string is written between double quotes,\nand all double quotes, newlines, embedded zeros,\nand backslashes in the string\nare correctly escaped when written.\nFor instance, the call\n\n<pre>\n     string.format('%q', 'a string with \"quotes\" and \\n new line')\n</pre><p>\nwill produce the string:\n\n<pre>\n     \"a string with \\\"quotes\\\" and \\\n      new line\"\n</pre>\n\n<p>\nThe options <code>c</code>, <code>d</code>, <code>E</code>, <code>e</code>, <code>f</code>,\n<code>g</code>, <code>G</code>, <code>i</code>, <code>o</code>, <code>u</code>, <code>X</code>, and <code>x</code> all\nexpect a number as argument,\nwhereas <code>q</code> and <code>s</code> expect a string.\n\n\n<p>\nThis function does not accept string values\ncontaining embedded zeros,\nexcept as arguments to the <code>q</code> option.\n\n\n\n\n<p>\n<hr><h3><a name=\"pdf-string.gmatch\"><code>string.gmatch (s, pattern)</code></a></h3>\nReturns an iterator function that,\neach time it is called,\nreturns the next captures from <code>pattern</code> over string <code>s</code>.\nIf <code>pattern</code> specifies no captures,\nthen the whole match is produced in each call.\n\n\n<p>\nAs an example, the following loop\n\n<pre>\n     s = \"hello world from Lua\"\n     for w in string.gmatch(s, \"%a+\") do\n       print(w)\n     end\n</pre><p>\nwill iterate over all the words from string <code>s</code>,\nprinting one per line.\nThe next example collects all pairs <code>key=value</code> from the\ngiven string into a table:\n\n<pre>\n     t = {}\n     s = \"from=world, to=Lua\"\n     for k, v in string.gmatch(s, \"(%w+)=(%w+)\") do\n       t[k] = v\n     end\n</pre>\n\n<p>\nFor this function, a '<code>^</code>' at the start of a pattern does not\nwork as an anchor, as this would prevent the iteration.\n\n\n\n\n<p>\n<hr><h3><a name=\"pdf-string.gsub\"><code>string.gsub (s, pattern, repl [, n])</code></a></h3>\nReturns a copy of <code>s</code>\nin which all (or the first <code>n</code>, if given)\noccurrences of the <code>pattern</code> have been\nreplaced by a replacement string specified by <code>repl</code>,\nwhich can be a string, a table, or a function.\n<code>gsub</code> also returns, as its second value,\nthe total number of matches that occurred.\n\n\n<p>\nIf <code>repl</code> is a string, then its value is used for replacement.\nThe character&nbsp;<code>%</code> works as an escape character:\nany sequence in <code>repl</code> of the form <code>%<em>n</em></code>,\nwith <em>n</em> between 1 and 9,\nstands for the value of the <em>n</em>-th captured substring (see below).\nThe sequence <code>%0</code> stands for the whole match.\nThe sequence <code>%%</code> stands for a single&nbsp;<code>%</code>.\n\n\n<p>\nIf <code>repl</code> is a table, then the table is queried for every match,\nusing the first capture as the key;\nif the pattern specifies no captures,\nthen the whole match is used as the key.\n\n\n<p>\nIf <code>repl</code> is a function, then this function is called every time a\nmatch occurs, with all captured substrings passed as arguments,\nin order;\nif the pattern specifies no captures,\nthen the whole match is passed as a sole argument.\n\n\n<p>\nIf the value returned by the table query or by the function call\nis a string or a number,\nthen it is used as the replacement string;\notherwise, if it is <b>false</b> or <b>nil</b>,\nthen there is no replacement\n(that is, the original match is kept in the string).\n\n\n<p>\nHere are some examples:\n\n<pre>\n     x = string.gsub(\"hello world\", \"(%w+)\", \"%1 %1\")\n     --&gt; x=\"hello hello world world\"\n     \n     x = string.gsub(\"hello world\", \"%w+\", \"%0 %0\", 1)\n     --&gt; x=\"hello hello world\"\n     \n     x = string.gsub(\"hello world from Lua\", \"(%w+)%s*(%w+)\", \"%2 %1\")\n     --&gt; x=\"world hello Lua from\"\n     \n     x = string.gsub(\"home = $HOME, user = $USER\", \"%$(%w+)\", os.getenv)\n     --&gt; x=\"home = /home/roberto, user = roberto\"\n     \n     x = string.gsub(\"4+5 = $return 4+5$\", \"%$(.-)%$\", function (s)\n           return loadstring(s)()\n         end)\n     --&gt; x=\"4+5 = 9\"\n     \n     local t = {name=\"lua\", version=\"5.1\"}\n     x = string.gsub(\"$name-$version.tar.gz\", \"%$(%w+)\", t)\n     --&gt; x=\"lua-5.1.tar.gz\"\n</pre>\n\n\n\n<p>\n<hr><h3><a name=\"pdf-string.len\"><code>string.len (s)</code></a></h3>\nReceives a string and returns its length.\nThe empty string <code>\"\"</code> has length 0.\nEmbedded zeros are counted,\nso <code>\"a\\000bc\\000\"</code> has length 5.\n\n\n\n\n<p>\n<hr><h3><a name=\"pdf-string.lower\"><code>string.lower (s)</code></a></h3>\nReceives a string and returns a copy of this string with all\nuppercase letters changed to lowercase.\nAll other characters are left unchanged.\nThe definition of what an uppercase letter is depends on the current locale.\n\n\n\n\n<p>\n<hr><h3><a name=\"pdf-string.match\"><code>string.match (s, pattern [, init])</code></a></h3>\nLooks for the first <em>match</em> of\n<code>pattern</code> in the string <code>s</code>.\nIf it finds one, then <code>match</code> returns\nthe captures from the pattern;\notherwise it returns <b>nil</b>.\nIf <code>pattern</code> specifies no captures,\nthen the whole match is returned.\nA third, optional numerical argument <code>init</code> specifies\nwhere to start the search;\nits default value is&nbsp;1 and can be negative.\n\n\n\n\n<p>\n<hr><h3><a name=\"pdf-string.rep\"><code>string.rep (s, n)</code></a></h3>\nReturns a string that is the concatenation of <code>n</code> copies of\nthe string <code>s</code>.\n\n\n\n\n<p>\n<hr><h3><a name=\"pdf-string.reverse\"><code>string.reverse (s)</code></a></h3>\nReturns a string that is the string <code>s</code> reversed.\n\n\n\n\n<p>\n<hr><h3><a name=\"pdf-string.sub\"><code>string.sub (s, i [, j])</code></a></h3>\nReturns the substring of <code>s</code> that\nstarts at <code>i</code>  and continues until <code>j</code>;\n<code>i</code> and <code>j</code> can be negative.\nIf <code>j</code> is absent, then it is assumed to be equal to -1\n(which is the same as the string length).\nIn particular,\nthe call <code>string.sub(s,1,j)</code> returns a prefix of <code>s</code>\nwith length <code>j</code>,\nand <code>string.sub(s, -i)</code> returns a suffix of <code>s</code>\nwith length <code>i</code>.\n\n\n\n\n<p>\n<hr><h3><a name=\"pdf-string.upper\"><code>string.upper (s)</code></a></h3>\nReceives a string and returns a copy of this string with all\nlowercase letters changed to uppercase.\nAll other characters are left unchanged.\nThe definition of what a lowercase letter is depends on the current locale.\n\n\n\n<h3>5.4.1 - <a name=\"5.4.1\">Patterns</a></h3>\n\n\n<h4>Character Class:</h4><p>\nA <em>character class</em> is used to represent a set of characters.\nThe following combinations are allowed in describing a character class:\n\n<ul>\n\n<li><b><em>x</em>:</b>\n(where <em>x</em> is not one of the <em>magic characters</em>\n<code>^$()%.[]*+-?</code>)\nrepresents the character <em>x</em> itself.\n</li>\n\n<li><b><code>.</code>:</b> (a dot) represents all characters.</li>\n\n<li><b><code>%a</code>:</b> represents all letters.</li>\n\n<li><b><code>%c</code>:</b> represents all control characters.</li>\n\n<li><b><code>%d</code>:</b> represents all digits.</li>\n\n<li><b><code>%l</code>:</b> represents all lowercase letters.</li>\n\n<li><b><code>%p</code>:</b> represents all punctuation characters.</li>\n\n<li><b><code>%s</code>:</b> represents all space characters.</li>\n\n<li><b><code>%u</code>:</b> represents all uppercase letters.</li>\n\n<li><b><code>%w</code>:</b> represents all alphanumeric characters.</li>\n\n<li><b><code>%x</code>:</b> represents all hexadecimal digits.</li>\n\n<li><b><code>%z</code>:</b> represents the character with representation 0.</li>\n\n<li><b><code>%<em>x</em></code>:</b> (where <em>x</em> is any non-alphanumeric character)\nrepresents the character <em>x</em>.\nThis is the standard way to escape the magic characters.\nAny punctuation character (even the non magic)\ncan be preceded by a '<code>%</code>'\nwhen used to represent itself in a pattern.\n</li>\n\n<li><b><code>[<em>set</em>]</code>:</b>\nrepresents the class which is the union of all\ncharacters in <em>set</em>.\nA range of characters can be specified by\nseparating the end characters of the range with a '<code>-</code>'.\nAll classes <code>%</code><em>x</em> described above can also be used as\ncomponents in <em>set</em>.\nAll other characters in <em>set</em> represent themselves.\nFor example, <code>[%w_]</code> (or <code>[_%w]</code>)\nrepresents all alphanumeric characters plus the underscore,\n<code>[0-7]</code> represents the octal digits,\nand <code>[0-7%l%-]</code> represents the octal digits plus\nthe lowercase letters plus the '<code>-</code>' character.\n\n\n<p>\nThe interaction between ranges and classes is not defined.\nTherefore, patterns like <code>[%a-z]</code> or <code>[a-%%]</code>\nhave no meaning.\n</li>\n\n<li><b><code>[^<em>set</em>]</code>:</b>\nrepresents the complement of <em>set</em>,\nwhere <em>set</em> is interpreted as above.\n</li>\n\n</ul><p>\nFor all classes represented by single letters (<code>%a</code>, <code>%c</code>, etc.),\nthe corresponding uppercase letter represents the complement of the class.\nFor instance, <code>%S</code> represents all non-space characters.\n\n\n<p>\nThe definitions of letter, space, and other character groups\ndepend on the current locale.\nIn particular, the class <code>[a-z]</code> may not be equivalent to <code>%l</code>.\n\n\n\n\n\n<h4>Pattern Item:</h4><p>\nA <em>pattern item</em> can be\n\n<ul>\n\n<li>\na single character class,\nwhich matches any single character in the class;\n</li>\n\n<li>\na single character class followed by '<code>*</code>',\nwhich matches 0 or more repetitions of characters in the class.\nThese repetition items will always match the longest possible sequence;\n</li>\n\n<li>\na single character class followed by '<code>+</code>',\nwhich matches 1 or more repetitions of characters in the class.\nThese repetition items will always match the longest possible sequence;\n</li>\n\n<li>\na single character class followed by '<code>-</code>',\nwhich also matches 0 or more repetitions of characters in the class.\nUnlike '<code>*</code>',\nthese repetition items will always match the <em>shortest</em> possible sequence;\n</li>\n\n<li>\na single character class followed by '<code>?</code>',\nwhich matches 0 or 1 occurrence of a character in the class;\n</li>\n\n<li>\n<code>%<em>n</em></code>, for <em>n</em> between 1 and 9;\nsuch item matches a substring equal to the <em>n</em>-th captured string\n(see below);\n</li>\n\n<li>\n<code>%b<em>xy</em></code>, where <em>x</em> and <em>y</em> are two distinct characters;\nsuch item matches strings that start with&nbsp;<em>x</em>, end with&nbsp;<em>y</em>,\nand where the <em>x</em> and <em>y</em> are <em>balanced</em>.\nThis means that, if one reads the string from left to right,\ncounting <em>+1</em> for an <em>x</em> and <em>-1</em> for a <em>y</em>,\nthe ending <em>y</em> is the first <em>y</em> where the count reaches 0.\nFor instance, the item <code>%b()</code> matches expressions with\nbalanced parentheses.\n</li>\n\n</ul>\n\n\n\n\n<h4>Pattern:</h4><p>\nA <em>pattern</em> is a sequence of pattern items.\nA '<code>^</code>' at the beginning of a pattern anchors the match at the\nbeginning of the subject string.\nA '<code>$</code>' at the end of a pattern anchors the match at the\nend of the subject string.\nAt other positions,\n'<code>^</code>' and '<code>$</code>' have no special meaning and represent themselves.\n\n\n\n\n\n<h4>Captures:</h4><p>\nA pattern can contain sub-patterns enclosed in parentheses;\nthey describe <em>captures</em>.\nWhen a match succeeds, the substrings of the subject string\nthat match captures are stored (<em>captured</em>) for future use.\nCaptures are numbered according to their left parentheses.\nFor instance, in the pattern <code>\"(a*(.)%w(%s*))\"</code>,\nthe part of the string matching <code>\"a*(.)%w(%s*)\"</code> is\nstored as the first capture (and therefore has number&nbsp;1);\nthe character matching \"<code>.</code>\" is captured with number&nbsp;2,\nand the part matching \"<code>%s*</code>\" has number&nbsp;3.\n\n\n<p>\nAs a special case, the empty capture <code>()</code> captures\nthe current string position (a number).\nFor instance, if we apply the pattern <code>\"()aa()\"</code> on the\nstring <code>\"flaaap\"</code>, there will be two captures: 3&nbsp;and&nbsp;5.\n\n\n<p>\nA pattern cannot contain embedded zeros.  Use <code>%z</code> instead.\n\n\n\n\n\n\n\n\n\n\n\n<h2>5.5 - <a name=\"5.5\">Table Manipulation</a></h2><p>\nThis library provides generic functions for table manipulation.\nIt provides all its functions inside the table <a name=\"pdf-table\"><code>table</code></a>.\n\n\n<p>\nMost functions in the table library assume that the table\nrepresents an array or a list.\nFor these functions, when we talk about the \"length\" of a table\nwe mean the result of the length operator.\n\n\n<p>\n<hr><h3><a name=\"pdf-table.concat\"><code>table.concat (table [, sep [, i [, j]]])</code></a></h3>\nGiven an array where all elements are strings or numbers,\nreturns <code>table[i]..sep..table[i+1] &middot;&middot;&middot; sep..table[j]</code>.\nThe default value for <code>sep</code> is the empty string,\nthe default for <code>i</code> is 1,\nand the default for <code>j</code> is the length of the table.\nIf <code>i</code> is greater than <code>j</code>, returns the empty string.\n\n\n\n\n<p>\n<hr><h3><a name=\"pdf-table.insert\"><code>table.insert (table, [pos,] value)</code></a></h3>\n\n\n<p>\nInserts element <code>value</code> at position <code>pos</code> in <code>table</code>,\nshifting up other elements to open space, if necessary.\nThe default value for <code>pos</code> is <code>n+1</code>,\nwhere <code>n</code> is the length of the table (see <a href=\"#2.5.5\">&sect;2.5.5</a>),\nso that a call <code>table.insert(t,x)</code> inserts <code>x</code> at the end\nof table <code>t</code>.\n\n\n\n\n<p>\n<hr><h3><a name=\"pdf-table.maxn\"><code>table.maxn (table)</code></a></h3>\n\n\n<p>\nReturns the largest positive numerical index of the given table,\nor zero if the table has no positive numerical indices.\n(To do its job this function does a linear traversal of\nthe whole table.) \n\n\n\n\n<p>\n<hr><h3><a name=\"pdf-table.remove\"><code>table.remove (table [, pos])</code></a></h3>\n\n\n<p>\nRemoves from <code>table</code> the element at position <code>pos</code>,\nshifting down other elements to close the space, if necessary.\nReturns the value of the removed element.\nThe default value for <code>pos</code> is <code>n</code>,\nwhere <code>n</code> is the length of the table,\nso that a call <code>table.remove(t)</code> removes the last element\nof table <code>t</code>.\n\n\n\n\n<p>\n<hr><h3><a name=\"pdf-table.sort\"><code>table.sort (table [, comp])</code></a></h3>\nSorts table elements in a given order, <em>in-place</em>,\nfrom <code>table[1]</code> to <code>table[n]</code>,\nwhere <code>n</code> is the length of the table.\nIf <code>comp</code> is given,\nthen it must be a function that receives two table elements,\nand returns true\nwhen the first is less than the second\n(so that <code>not comp(a[i+1],a[i])</code> will be true after the sort).\nIf <code>comp</code> is not given,\nthen the standard Lua operator <code>&lt;</code> is used instead.\n\n\n<p>\nThe sort algorithm is not stable;\nthat is, elements considered equal by the given order\nmay have their relative positions changed by the sort.\n\n\n\n\n\n\n\n<h2>5.6 - <a name=\"5.6\">Mathematical Functions</a></h2>\n\n<p>\nThis library is an interface to the standard C&nbsp;math library.\nIt provides all its functions inside the table <a name=\"pdf-math\"><code>math</code></a>.\n\n\n<p>\n<hr><h3><a name=\"pdf-math.abs\"><code>math.abs (x)</code></a></h3>\n\n\n<p>\nReturns the absolute value of <code>x</code>.\n\n\n\n\n<p>\n<hr><h3><a name=\"pdf-math.acos\"><code>math.acos (x)</code></a></h3>\n\n\n<p>\nReturns the arc cosine of <code>x</code> (in radians).\n\n\n\n\n<p>\n<hr><h3><a name=\"pdf-math.asin\"><code>math.asin (x)</code></a></h3>\n\n\n<p>\nReturns the arc sine of <code>x</code> (in radians).\n\n\n\n\n<p>\n<hr><h3><a name=\"pdf-math.atan\"><code>math.atan (x)</code></a></h3>\n\n\n<p>\nReturns the arc tangent of <code>x</code> (in radians).\n\n\n\n\n<p>\n<hr><h3><a name=\"pdf-math.atan2\"><code>math.atan2 (y, x)</code></a></h3>\n\n\n<p>\nReturns the arc tangent of <code>y/x</code> (in radians),\nbut uses the signs of both parameters to find the\nquadrant of the result.\n(It also handles correctly the case of <code>x</code> being zero.)\n\n\n\n\n<p>\n<hr><h3><a name=\"pdf-math.ceil\"><code>math.ceil (x)</code></a></h3>\n\n\n<p>\nReturns the smallest integer larger than or equal to <code>x</code>.\n\n\n\n\n<p>\n<hr><h3><a name=\"pdf-math.cos\"><code>math.cos (x)</code></a></h3>\n\n\n<p>\nReturns the cosine of <code>x</code> (assumed to be in radians).\n\n\n\n\n<p>\n<hr><h3><a name=\"pdf-math.cosh\"><code>math.cosh (x)</code></a></h3>\n\n\n<p>\nReturns the hyperbolic cosine of <code>x</code>.\n\n\n\n\n<p>\n<hr><h3><a name=\"pdf-math.deg\"><code>math.deg (x)</code></a></h3>\n\n\n<p>\nReturns the angle <code>x</code> (given in radians) in degrees.\n\n\n\n\n<p>\n<hr><h3><a name=\"pdf-math.exp\"><code>math.exp (x)</code></a></h3>\n\n\n<p>\nReturns the value <em>e<sup>x</sup></em>.\n\n\n\n\n<p>\n<hr><h3><a name=\"pdf-math.floor\"><code>math.floor (x)</code></a></h3>\n\n\n<p>\nReturns the largest integer smaller than or equal to <code>x</code>.\n\n\n\n\n<p>\n<hr><h3><a name=\"pdf-math.fmod\"><code>math.fmod (x, y)</code></a></h3>\n\n\n<p>\nReturns the remainder of the division of <code>x</code> by <code>y</code>\nthat rounds the quotient towards zero.\n\n\n\n\n<p>\n<hr><h3><a name=\"pdf-math.frexp\"><code>math.frexp (x)</code></a></h3>\n\n\n<p>\nReturns <code>m</code> and <code>e</code> such that <em>x = m2<sup>e</sup></em>,\n<code>e</code> is an integer and the absolute value of <code>m</code> is\nin the range <em>[0.5, 1)</em>\n(or zero when <code>x</code> is zero).\n\n\n\n\n<p>\n<hr><h3><a name=\"pdf-math.huge\"><code>math.huge</code></a></h3>\n\n\n<p>\nThe value <code>HUGE_VAL</code>,\na value larger than or equal to any other numerical value.\n\n\n\n\n<p>\n<hr><h3><a name=\"pdf-math.ldexp\"><code>math.ldexp (m, e)</code></a></h3>\n\n\n<p>\nReturns <em>m2<sup>e</sup></em> (<code>e</code> should be an integer).\n\n\n\n\n<p>\n<hr><h3><a name=\"pdf-math.log\"><code>math.log (x)</code></a></h3>\n\n\n<p>\nReturns the natural logarithm of <code>x</code>.\n\n\n\n\n<p>\n<hr><h3><a name=\"pdf-math.log10\"><code>math.log10 (x)</code></a></h3>\n\n\n<p>\nReturns the base-10 logarithm of <code>x</code>.\n\n\n\n\n<p>\n<hr><h3><a name=\"pdf-math.max\"><code>math.max (x, &middot;&middot;&middot;)</code></a></h3>\n\n\n<p>\nReturns the maximum value among its arguments.\n\n\n\n\n<p>\n<hr><h3><a name=\"pdf-math.min\"><code>math.min (x, &middot;&middot;&middot;)</code></a></h3>\n\n\n<p>\nReturns the minimum value among its arguments.\n\n\n\n\n<p>\n<hr><h3><a name=\"pdf-math.modf\"><code>math.modf (x)</code></a></h3>\n\n\n<p>\nReturns two numbers,\nthe integral part of <code>x</code> and the fractional part of <code>x</code>.\n\n\n\n\n<p>\n<hr><h3><a name=\"pdf-math.pi\"><code>math.pi</code></a></h3>\n\n\n<p>\nThe value of <em>pi</em>.\n\n\n\n\n<p>\n<hr><h3><a name=\"pdf-math.pow\"><code>math.pow (x, y)</code></a></h3>\n\n\n<p>\nReturns <em>x<sup>y</sup></em>.\n(You can also use the expression <code>x^y</code> to compute this value.)\n\n\n\n\n<p>\n<hr><h3><a name=\"pdf-math.rad\"><code>math.rad (x)</code></a></h3>\n\n\n<p>\nReturns the angle <code>x</code> (given in degrees) in radians.\n\n\n\n\n<p>\n<hr><h3><a name=\"pdf-math.random\"><code>math.random ([m [, n]])</code></a></h3>\n\n\n<p>\nThis function is an interface to the simple\npseudo-random generator function <code>rand</code> provided by ANSI&nbsp;C.\n(No guarantees can be given for its statistical properties.)\n\n\n<p>\nWhen called without arguments,\nreturns a uniform pseudo-random real number\nin the range <em>[0,1)</em>.  \nWhen called with an integer number <code>m</code>,\n<code>math.random</code> returns\na uniform pseudo-random integer in the range <em>[1, m]</em>.\nWhen called with two integer numbers <code>m</code> and <code>n</code>,\n<code>math.random</code> returns a uniform pseudo-random\ninteger in the range <em>[m, n]</em>.\n\n\n\n\n<p>\n<hr><h3><a name=\"pdf-math.randomseed\"><code>math.randomseed (x)</code></a></h3>\n\n\n<p>\nSets <code>x</code> as the \"seed\"\nfor the pseudo-random generator:\nequal seeds produce equal sequences of numbers.\n\n\n\n\n<p>\n<hr><h3><a name=\"pdf-math.sin\"><code>math.sin (x)</code></a></h3>\n\n\n<p>\nReturns the sine of <code>x</code> (assumed to be in radians).\n\n\n\n\n<p>\n<hr><h3><a name=\"pdf-math.sinh\"><code>math.sinh (x)</code></a></h3>\n\n\n<p>\nReturns the hyperbolic sine of <code>x</code>.\n\n\n\n\n<p>\n<hr><h3><a name=\"pdf-math.sqrt\"><code>math.sqrt (x)</code></a></h3>\n\n\n<p>\nReturns the square root of <code>x</code>.\n(You can also use the expression <code>x^0.5</code> to compute this value.)\n\n\n\n\n<p>\n<hr><h3><a name=\"pdf-math.tan\"><code>math.tan (x)</code></a></h3>\n\n\n<p>\nReturns the tangent of <code>x</code> (assumed to be in radians).\n\n\n\n\n<p>\n<hr><h3><a name=\"pdf-math.tanh\"><code>math.tanh (x)</code></a></h3>\n\n\n<p>\nReturns the hyperbolic tangent of <code>x</code>.\n\n\n\n\n\n\n\n<h2>5.7 - <a name=\"5.7\">Input and Output Facilities</a></h2>\n\n<p>\nThe I/O library provides two different styles for file manipulation.\nThe first one uses implicit file descriptors;\nthat is, there are operations to set a default input file and a\ndefault output file,\nand all input/output operations are over these default files.\nThe second style uses explicit file descriptors.\n\n\n<p>\nWhen using implicit file descriptors,\nall operations are supplied by table <a name=\"pdf-io\"><code>io</code></a>.\nWhen using explicit file descriptors,\nthe operation <a href=\"#pdf-io.open\"><code>io.open</code></a> returns a file descriptor\nand then all operations are supplied as methods of the file descriptor.\n\n\n<p>\nThe table <code>io</code> also provides\nthree predefined file descriptors with their usual meanings from C:\n<a name=\"pdf-io.stdin\"><code>io.stdin</code></a>, <a name=\"pdf-io.stdout\"><code>io.stdout</code></a>, and <a name=\"pdf-io.stderr\"><code>io.stderr</code></a>.\nThe I/O library never closes these files.\n\n\n<p>\nUnless otherwise stated,\nall I/O functions return <b>nil</b> on failure\n(plus an error message as a second result and\na system-dependent error code as a third result)\nand some value different from <b>nil</b> on success.\n\n\n<p>\n<hr><h3><a name=\"pdf-io.close\"><code>io.close ([file])</code></a></h3>\n\n\n<p>\nEquivalent to <code>file:close()</code>.\nWithout a <code>file</code>, closes the default output file.\n\n\n\n\n<p>\n<hr><h3><a name=\"pdf-io.flush\"><code>io.flush ()</code></a></h3>\n\n\n<p>\nEquivalent to <code>file:flush</code> over the default output file.\n\n\n\n\n<p>\n<hr><h3><a name=\"pdf-io.input\"><code>io.input ([file])</code></a></h3>\n\n\n<p>\nWhen called with a file name, it opens the named file (in text mode),\nand sets its handle as the default input file.\nWhen called with a file handle,\nit simply sets this file handle as the default input file.\nWhen called without parameters,\nit returns the current default input file.\n\n\n<p>\nIn case of errors this function raises the error,\ninstead of returning an error code.\n\n\n\n\n<p>\n<hr><h3><a name=\"pdf-io.lines\"><code>io.lines ([filename])</code></a></h3>\n\n\n<p>\nOpens the given file name in read mode\nand returns an iterator function that,\neach time it is called,\nreturns a new line from the file.\nTherefore, the construction\n\n<pre>\n     for line in io.lines(filename) do <em>body</em> end\n</pre><p>\nwill iterate over all lines of the file.\nWhen the iterator function detects the end of file,\nit returns <b>nil</b> (to finish the loop) and automatically closes the file.\n\n\n<p>\nThe call <code>io.lines()</code> (with no file name) is equivalent\nto <code>io.input():lines()</code>;\nthat is, it iterates over the lines of the default input file.\nIn this case it does not close the file when the loop ends.\n\n\n\n\n<p>\n<hr><h3><a name=\"pdf-io.open\"><code>io.open (filename [, mode])</code></a></h3>\n\n\n<p>\nThis function opens a file,\nin the mode specified in the string <code>mode</code>.\nIt returns a new file handle,\nor, in case of errors, <b>nil</b> plus an error message.\n\n\n<p>\nThe <code>mode</code> string can be any of the following:\n\n<ul>\n<li><b>\"r\":</b> read mode (the default);</li>\n<li><b>\"w\":</b> write mode;</li>\n<li><b>\"a\":</b> append mode;</li>\n<li><b>\"r+\":</b> update mode, all previous data is preserved;</li>\n<li><b>\"w+\":</b> update mode, all previous data is erased;</li>\n<li><b>\"a+\":</b> append update mode, previous data is preserved,\n  writing is only allowed at the end of file.</li>\n</ul><p>\nThe <code>mode</code> string can also have a '<code>b</code>' at the end,\nwhich is needed in some systems to open the file in binary mode.\nThis string is exactly what is used in the\nstandard&nbsp;C function <code>fopen</code>.\n\n\n\n\n<p>\n<hr><h3><a name=\"pdf-io.output\"><code>io.output ([file])</code></a></h3>\n\n\n<p>\nSimilar to <a href=\"#pdf-io.input\"><code>io.input</code></a>, but operates over the default output file.\n\n\n\n\n<p>\n<hr><h3><a name=\"pdf-io.popen\"><code>io.popen (prog [, mode])</code></a></h3>\n\n\n<p>\nStarts program <code>prog</code> in a separated process and returns\na file handle that you can use to read data from this program\n(if <code>mode</code> is <code>\"r\"</code>, the default)\nor to write data to this program\n(if <code>mode</code> is <code>\"w\"</code>).\n\n\n<p>\nThis function is system dependent and is not available\non all platforms.\n\n\n\n\n<p>\n<hr><h3><a name=\"pdf-io.read\"><code>io.read (&middot;&middot;&middot;)</code></a></h3>\n\n\n<p>\nEquivalent to <code>io.input():read</code>.\n\n\n\n\n<p>\n<hr><h3><a name=\"pdf-io.tmpfile\"><code>io.tmpfile ()</code></a></h3>\n\n\n<p>\nReturns a handle for a temporary file.\nThis file is opened in update mode\nand it is automatically removed when the program ends.\n\n\n\n\n<p>\n<hr><h3><a name=\"pdf-io.type\"><code>io.type (obj)</code></a></h3>\n\n\n<p>\nChecks whether <code>obj</code> is a valid file handle.\nReturns the string <code>\"file\"</code> if <code>obj</code> is an open file handle,\n<code>\"closed file\"</code> if <code>obj</code> is a closed file handle,\nor <b>nil</b> if <code>obj</code> is not a file handle.\n\n\n\n\n<p>\n<hr><h3><a name=\"pdf-io.write\"><code>io.write (&middot;&middot;&middot;)</code></a></h3>\n\n\n<p>\nEquivalent to <code>io.output():write</code>.\n\n\n\n\n<p>\n<hr><h3><a name=\"pdf-file:close\"><code>file:close ()</code></a></h3>\n\n\n<p>\nCloses <code>file</code>.\nNote that files are automatically closed when\ntheir handles are garbage collected,\nbut that takes an unpredictable amount of time to happen.\n\n\n\n\n<p>\n<hr><h3><a name=\"pdf-file:flush\"><code>file:flush ()</code></a></h3>\n\n\n<p>\nSaves any written data to <code>file</code>.\n\n\n\n\n<p>\n<hr><h3><a name=\"pdf-file:lines\"><code>file:lines ()</code></a></h3>\n\n\n<p>\nReturns an iterator function that,\neach time it is called,\nreturns a new line from the file.\nTherefore, the construction\n\n<pre>\n     for line in file:lines() do <em>body</em> end\n</pre><p>\nwill iterate over all lines of the file.\n(Unlike <a href=\"#pdf-io.lines\"><code>io.lines</code></a>, this function does not close the file\nwhen the loop ends.)\n\n\n\n\n<p>\n<hr><h3><a name=\"pdf-file:read\"><code>file:read (&middot;&middot;&middot;)</code></a></h3>\n\n\n<p>\nReads the file <code>file</code>,\naccording to the given formats, which specify what to read.\nFor each format,\nthe function returns a string (or a number) with the characters read,\nor <b>nil</b> if it cannot read data with the specified format.\nWhen called without formats,\nit uses a default format that reads the entire next line\n(see below).\n\n\n<p>\nThe available formats are\n\n<ul>\n\n<li><b>\"*n\":</b>\nreads a number;\nthis is the only format that returns a number instead of a string.\n</li>\n\n<li><b>\"*a\":</b>\nreads the whole file, starting at the current position.\nOn end of file, it returns the empty string.\n</li>\n\n<li><b>\"*l\":</b>\nreads the next line (skipping the end of line),\nreturning <b>nil</b> on end of file.\nThis is the default format.\n</li>\n\n<li><b><em>number</em>:</b>\nreads a string with up to this number of characters,\nreturning <b>nil</b> on end of file.\nIf number is zero,\nit reads nothing and returns an empty string,\nor <b>nil</b> on end of file.\n</li>\n\n</ul>\n\n\n\n<p>\n<hr><h3><a name=\"pdf-file:seek\"><code>file:seek ([whence] [, offset])</code></a></h3>\n\n\n<p>\nSets and gets the file position,\nmeasured from the beginning of the file,\nto the position given by <code>offset</code> plus a base\nspecified by the string <code>whence</code>, as follows:\n\n<ul>\n<li><b>\"set\":</b> base is position 0 (beginning of the file);</li>\n<li><b>\"cur\":</b> base is current position;</li>\n<li><b>\"end\":</b> base is end of file;</li>\n</ul><p>\nIn case of success, function <code>seek</code> returns the final file position,\nmeasured in bytes from the beginning of the file.\nIf this function fails, it returns <b>nil</b>,\nplus a string describing the error.\n\n\n<p>\nThe default value for <code>whence</code> is <code>\"cur\"</code>,\nand for <code>offset</code> is 0.\nTherefore, the call <code>file:seek()</code> returns the current\nfile position, without changing it;\nthe call <code>file:seek(\"set\")</code> sets the position to the\nbeginning of the file (and returns 0);\nand the call <code>file:seek(\"end\")</code> sets the position to the\nend of the file, and returns its size.\n\n\n\n\n<p>\n<hr><h3><a name=\"pdf-file:setvbuf\"><code>file:setvbuf (mode [, size])</code></a></h3>\n\n\n<p>\nSets the buffering mode for an output file.\nThere are three available modes:\n\n<ul>\n\n<li><b>\"no\":</b>\nno buffering; the result of any output operation appears immediately.\n</li>\n\n<li><b>\"full\":</b>\nfull buffering; output operation is performed only\nwhen the buffer is full (or when you explicitly <code>flush</code> the file\n(see <a href=\"#pdf-io.flush\"><code>io.flush</code></a>)).\n</li>\n\n<li><b>\"line\":</b>\nline buffering; output is buffered until a newline is output\nor there is any input from some special files\n(such as a terminal device).\n</li>\n\n</ul><p>\nFor the last two cases, <code>size</code>\nspecifies the size of the buffer, in bytes.\nThe default is an appropriate size.\n\n\n\n\n<p>\n<hr><h3><a name=\"pdf-file:write\"><code>file:write (&middot;&middot;&middot;)</code></a></h3>\n\n\n<p>\nWrites the value of each of its arguments to\nthe <code>file</code>.\nThe arguments must be strings or numbers.\nTo write other values,\nuse <a href=\"#pdf-tostring\"><code>tostring</code></a> or <a href=\"#pdf-string.format\"><code>string.format</code></a> before <code>write</code>.\n\n\n\n\n\n\n\n<h2>5.8 - <a name=\"5.8\">Operating System Facilities</a></h2>\n\n<p>\nThis library is implemented through table <a name=\"pdf-os\"><code>os</code></a>.\n\n\n<p>\n<hr><h3><a name=\"pdf-os.clock\"><code>os.clock ()</code></a></h3>\n\n\n<p>\nReturns an approximation of the amount in seconds of CPU time\nused by the program.\n\n\n\n\n<p>\n<hr><h3><a name=\"pdf-os.date\"><code>os.date ([format [, time]])</code></a></h3>\n\n\n<p>\nReturns a string or a table containing date and time,\nformatted according to the given string <code>format</code>.\n\n\n<p>\nIf the <code>time</code> argument is present,\nthis is the time to be formatted\n(see the <a href=\"#pdf-os.time\"><code>os.time</code></a> function for a description of this value).\nOtherwise, <code>date</code> formats the current time.\n\n\n<p>\nIf <code>format</code> starts with '<code>!</code>',\nthen the date is formatted in Coordinated Universal Time.\nAfter this optional character,\nif <code>format</code> is the string \"<code>*t</code>\",\nthen <code>date</code> returns a table with the following fields:\n<code>year</code> (four digits), <code>month</code> (1--12), <code>day</code> (1--31),\n<code>hour</code> (0--23), <code>min</code> (0--59), <code>sec</code> (0--61),\n<code>wday</code> (weekday, Sunday is&nbsp;1),\n<code>yday</code> (day of the year),\nand <code>isdst</code> (daylight saving flag, a boolean).\n\n\n<p>\nIf <code>format</code> is not \"<code>*t</code>\",\nthen <code>date</code> returns the date as a string,\nformatted according to the same rules as the C&nbsp;function <code>strftime</code>.\n\n\n<p>\nWhen called without arguments,\n<code>date</code> returns a reasonable date and time representation that depends on\nthe host system and on the current locale\n(that is, <code>os.date()</code> is equivalent to <code>os.date(\"%c\")</code>).\n\n\n\n\n<p>\n<hr><h3><a name=\"pdf-os.difftime\"><code>os.difftime (t2, t1)</code></a></h3>\n\n\n<p>\nReturns the number of seconds from time <code>t1</code> to time <code>t2</code>.\nIn POSIX, Windows, and some other systems,\nthis value is exactly <code>t2</code><em>-</em><code>t1</code>.\n\n\n\n\n<p>\n<hr><h3><a name=\"pdf-os.execute\"><code>os.execute ([command])</code></a></h3>\n\n\n<p>\nThis function is equivalent to the C&nbsp;function <code>system</code>.\nIt passes <code>command</code> to be executed by an operating system shell.\nIt returns a status code, which is system-dependent.\nIf <code>command</code> is absent, then it returns nonzero if a shell is available\nand zero otherwise.\n\n\n\n\n<p>\n<hr><h3><a name=\"pdf-os.exit\"><code>os.exit ([code])</code></a></h3>\n\n\n<p>\nCalls the C&nbsp;function <code>exit</code>,\nwith an optional <code>code</code>,\nto terminate the host program.\nThe default value for <code>code</code> is the success code.\n\n\n\n\n<p>\n<hr><h3><a name=\"pdf-os.getenv\"><code>os.getenv (varname)</code></a></h3>\n\n\n<p>\nReturns the value of the process environment variable <code>varname</code>,\nor <b>nil</b> if the variable is not defined.\n\n\n\n\n<p>\n<hr><h3><a name=\"pdf-os.remove\"><code>os.remove (filename)</code></a></h3>\n\n\n<p>\nDeletes the file or directory with the given name.\nDirectories must be empty to be removed.\nIf this function fails, it returns <b>nil</b>,\nplus a string describing the error.\n\n\n\n\n<p>\n<hr><h3><a name=\"pdf-os.rename\"><code>os.rename (oldname, newname)</code></a></h3>\n\n\n<p>\nRenames file or directory named <code>oldname</code> to <code>newname</code>.\nIf this function fails, it returns <b>nil</b>,\nplus a string describing the error.\n\n\n\n\n<p>\n<hr><h3><a name=\"pdf-os.setlocale\"><code>os.setlocale (locale [, category])</code></a></h3>\n\n\n<p>\nSets the current locale of the program.\n<code>locale</code> is a string specifying a locale;\n<code>category</code> is an optional string describing which category to change:\n<code>\"all\"</code>, <code>\"collate\"</code>, <code>\"ctype\"</code>,\n<code>\"monetary\"</code>, <code>\"numeric\"</code>, or <code>\"time\"</code>;\nthe default category is <code>\"all\"</code>.\nThe function returns the name of the new locale,\nor <b>nil</b> if the request cannot be honored.\n\n\n<p>\nIf <code>locale</code> is the empty string,\nthe current locale is set to an implementation-defined native locale.\nIf <code>locale</code> is the string \"<code>C</code>\",\nthe current locale is set to the standard C locale.\n\n\n<p>\nWhen called with <b>nil</b> as the first argument,\nthis function only returns the name of the current locale\nfor the given category.\n\n\n\n\n<p>\n<hr><h3><a name=\"pdf-os.time\"><code>os.time ([table])</code></a></h3>\n\n\n<p>\nReturns the current time when called without arguments,\nor a time representing the date and time specified by the given table.\nThis table must have fields <code>year</code>, <code>month</code>, and <code>day</code>,\nand may have fields <code>hour</code>, <code>min</code>, <code>sec</code>, and <code>isdst</code>\n(for a description of these fields, see the <a href=\"#pdf-os.date\"><code>os.date</code></a> function).\n\n\n<p>\nThe returned value is a number, whose meaning depends on your system.\nIn POSIX, Windows, and some other systems, this number counts the number\nof seconds since some given start time (the \"epoch\").\nIn other systems, the meaning is not specified,\nand the number returned by <code>time</code> can be used only as an argument to\n<code>date</code> and <code>difftime</code>.\n\n\n\n\n<p>\n<hr><h3><a name=\"pdf-os.tmpname\"><code>os.tmpname ()</code></a></h3>\n\n\n<p>\nReturns a string with a file name that can\nbe used for a temporary file.\nThe file must be explicitly opened before its use\nand explicitly removed when no longer needed.\n\n\n<p>\nOn some systems (POSIX),\nthis function also creates a file with that name,\nto avoid security risks.\n(Someone else might create the file with wrong permissions\nin the time between getting the name and creating the file.)\nYou still have to open the file to use it\nand to remove it (even if you do not use it).\n\n\n<p>\nWhen possible,\nyou may prefer to use <a href=\"#pdf-io.tmpfile\"><code>io.tmpfile</code></a>,\nwhich automatically removes the file when the program ends.\n\n\n\n\n\n\n\n<h2>5.9 - <a name=\"5.9\">The Debug Library</a></h2>\n\n<p>\nThis library provides\nthe functionality of the debug interface to Lua programs.\nYou should exert care when using this library.\nThe functions provided here should be used exclusively for debugging\nand similar tasks, such as profiling.\nPlease resist the temptation to use them as a\nusual programming tool:\nthey can be very slow.\nMoreover, several of these functions\nviolate some assumptions about Lua code\n(e.g., that variables local to a function\ncannot be accessed from outside or\nthat userdata metatables cannot be changed by Lua code)\nand therefore can compromise otherwise secure code.\n\n\n<p>\nAll functions in this library are provided\ninside the <a name=\"pdf-debug\"><code>debug</code></a> table.\nAll functions that operate over a thread\nhave an optional first argument which is the\nthread to operate over.\nThe default is always the current thread.\n\n\n<p>\n<hr><h3><a name=\"pdf-debug.debug\"><code>debug.debug ()</code></a></h3>\n\n\n<p>\nEnters an interactive mode with the user,\nrunning each string that the user enters.\nUsing simple commands and other debug facilities,\nthe user can inspect global and local variables,\nchange their values, evaluate expressions, and so on.\nA line containing only the word <code>cont</code> finishes this function,\nso that the caller continues its execution.\n\n\n<p>\nNote that commands for <code>debug.debug</code> are not lexically nested\nwithin any function, and so have no direct access to local variables.\n\n\n\n\n<p>\n<hr><h3><a name=\"pdf-debug.getfenv\"><code>debug.getfenv (o)</code></a></h3>\nReturns the environment of object <code>o</code>.\n\n\n\n\n<p>\n<hr><h3><a name=\"pdf-debug.gethook\"><code>debug.gethook ([thread])</code></a></h3>\n\n\n<p>\nReturns the current hook settings of the thread, as three values:\nthe current hook function, the current hook mask,\nand the current hook count\n(as set by the <a href=\"#pdf-debug.sethook\"><code>debug.sethook</code></a> function).\n\n\n\n\n<p>\n<hr><h3><a name=\"pdf-debug.getinfo\"><code>debug.getinfo ([thread,] function [, what])</code></a></h3>\n\n\n<p>\nReturns a table with information about a function.\nYou can give the function directly,\nor you can give a number as the value of <code>function</code>,\nwhich means the function running at level <code>function</code> of the call stack\nof the given thread:\nlevel&nbsp;0 is the current function (<code>getinfo</code> itself);\nlevel&nbsp;1 is the function that called <code>getinfo</code>;\nand so on.\nIf <code>function</code> is a number larger than the number of active functions,\nthen <code>getinfo</code> returns <b>nil</b>.\n\n\n<p>\nThe returned table can contain all the fields returned by <a href=\"#lua_getinfo\"><code>lua_getinfo</code></a>,\nwith the string <code>what</code> describing which fields to fill in.\nThe default for <code>what</code> is to get all information available,\nexcept the table of valid lines.\nIf present,\nthe option '<code>f</code>'\nadds a field named <code>func</code> with the function itself.\nIf present,\nthe option '<code>L</code>'\nadds a field named <code>activelines</code> with the table of\nvalid lines.\n\n\n<p>\nFor instance, the expression <code>debug.getinfo(1,\"n\").name</code> returns\na table with a name for the current function,\nif a reasonable name can be found,\nand the expression <code>debug.getinfo(print)</code>\nreturns a table with all available information\nabout the <a href=\"#pdf-print\"><code>print</code></a> function.\n\n\n\n\n<p>\n<hr><h3><a name=\"pdf-debug.getlocal\"><code>debug.getlocal ([thread,] level, local)</code></a></h3>\n\n\n<p>\nThis function returns the name and the value of the local variable\nwith index <code>local</code> of the function at level <code>level</code> of the stack.\n(The first parameter or local variable has index&nbsp;1, and so on,\nuntil the last active local variable.)\nThe function returns <b>nil</b> if there is no local\nvariable with the given index,\nand raises an error when called with a <code>level</code> out of range.\n(You can call <a href=\"#pdf-debug.getinfo\"><code>debug.getinfo</code></a> to check whether the level is valid.)\n\n\n<p>\nVariable names starting with '<code>(</code>' (open parentheses)\nrepresent internal variables\n(loop control variables, temporaries, and C&nbsp;function locals).\n\n\n\n\n<p>\n<hr><h3><a name=\"pdf-debug.getmetatable\"><code>debug.getmetatable (object)</code></a></h3>\n\n\n<p>\nReturns the metatable of the given <code>object</code>\nor <b>nil</b> if it does not have a metatable.\n\n\n\n\n<p>\n<hr><h3><a name=\"pdf-debug.getregistry\"><code>debug.getregistry ()</code></a></h3>\n\n\n<p>\nReturns the registry table (see <a href=\"#3.5\">&sect;3.5</a>).\n\n\n\n\n<p>\n<hr><h3><a name=\"pdf-debug.getupvalue\"><code>debug.getupvalue (func, up)</code></a></h3>\n\n\n<p>\nThis function returns the name and the value of the upvalue\nwith index <code>up</code> of the function <code>func</code>.\nThe function returns <b>nil</b> if there is no upvalue with the given index.\n\n\n\n\n<p>\n<hr><h3><a name=\"pdf-debug.setfenv\"><code>debug.setfenv (object, table)</code></a></h3>\n\n\n<p>\nSets the environment of the given <code>object</code> to the given <code>table</code>.\nReturns <code>object</code>.\n\n\n\n\n<p>\n<hr><h3><a name=\"pdf-debug.sethook\"><code>debug.sethook ([thread,] hook, mask [, count])</code></a></h3>\n\n\n<p>\nSets the given function as a hook.\nThe string <code>mask</code> and the number <code>count</code> describe\nwhen the hook will be called.\nThe string mask may have the following characters,\nwith the given meaning:\n\n<ul>\n<li><b><code>\"c\"</code>:</b> the hook is called every time Lua calls a function;</li>\n<li><b><code>\"r\"</code>:</b> the hook is called every time Lua returns from a function;</li>\n<li><b><code>\"l\"</code>:</b> the hook is called every time Lua enters a new line of code.</li>\n</ul><p>\nWith a <code>count</code> different from zero,\nthe hook is called after every <code>count</code> instructions.\n\n\n<p>\nWhen called without arguments,\n<a href=\"#pdf-debug.sethook\"><code>debug.sethook</code></a> turns off the hook.\n\n\n<p>\nWhen the hook is called, its first parameter is a string\ndescribing the event that has triggered its call:\n<code>\"call\"</code>, <code>\"return\"</code> (or <code>\"tail return\"</code>,\nwhen simulating a return from a tail call),\n<code>\"line\"</code>, and <code>\"count\"</code>.\nFor line events,\nthe hook also gets the new line number as its second parameter.\nInside a hook,\nyou can call <code>getinfo</code> with level&nbsp;2 to get more information about\nthe running function\n(level&nbsp;0 is the <code>getinfo</code> function,\nand level&nbsp;1 is the hook function),\nunless the event is <code>\"tail return\"</code>.\nIn this case, Lua is only simulating the return,\nand a call to <code>getinfo</code> will return invalid data.\n\n\n\n\n<p>\n<hr><h3><a name=\"pdf-debug.setlocal\"><code>debug.setlocal ([thread,] level, local, value)</code></a></h3>\n\n\n<p>\nThis function assigns the value <code>value</code> to the local variable\nwith index <code>local</code> of the function at level <code>level</code> of the stack.\nThe function returns <b>nil</b> if there is no local\nvariable with the given index,\nand raises an error when called with a <code>level</code> out of range.\n(You can call <code>getinfo</code> to check whether the level is valid.)\nOtherwise, it returns the name of the local variable.\n\n\n\n\n<p>\n<hr><h3><a name=\"pdf-debug.setmetatable\"><code>debug.setmetatable (object, table)</code></a></h3>\n\n\n<p>\nSets the metatable for the given <code>object</code> to the given <code>table</code>\n(which can be <b>nil</b>).\n\n\n\n\n<p>\n<hr><h3><a name=\"pdf-debug.setupvalue\"><code>debug.setupvalue (func, up, value)</code></a></h3>\n\n\n<p>\nThis function assigns the value <code>value</code> to the upvalue\nwith index <code>up</code> of the function <code>func</code>.\nThe function returns <b>nil</b> if there is no upvalue\nwith the given index.\nOtherwise, it returns the name of the upvalue.\n\n\n\n\n<p>\n<hr><h3><a name=\"pdf-debug.traceback\"><code>debug.traceback ([thread,] [message [, level]])</code></a></h3>\n\n\n<p>\nReturns a string with a traceback of the call stack.\nAn optional <code>message</code> string is appended\nat the beginning of the traceback.\nAn optional <code>level</code> number tells at which level\nto start the traceback\n(default is 1, the function calling <code>traceback</code>).\n\n\n\n\n\n\n\n<h1>6 - <a name=\"6\">Lua Stand-alone</a></h1>\n\n<p>\nAlthough Lua has been designed as an extension language,\nto be embedded in a host C&nbsp;program,\nit is also frequently used as a stand-alone language.\nAn interpreter for Lua as a stand-alone language,\ncalled simply <code>lua</code>,\nis provided with the standard distribution.\nThe stand-alone interpreter includes\nall standard libraries, including the debug library.\nIts usage is:\n\n<pre>\n     lua [options] [script [args]]\n</pre><p>\nThe options are:\n\n<ul>\n<li><b><code>-e <em>stat</em></code>:</b> executes string <em>stat</em>;</li>\n<li><b><code>-l <em>mod</em></code>:</b> \"requires\" <em>mod</em>;</li>\n<li><b><code>-i</code>:</b> enters interactive mode after running <em>script</em>;</li>\n<li><b><code>-v</code>:</b> prints version information;</li>\n<li><b><code>--</code>:</b> stops handling options;</li>\n<li><b><code>-</code>:</b> executes <code>stdin</code> as a file and stops handling options.</li>\n</ul><p>\nAfter handling its options, <code>lua</code> runs the given <em>script</em>,\npassing to it the given <em>args</em> as string arguments.\nWhen called without arguments,\n<code>lua</code> behaves as <code>lua -v -i</code>\nwhen the standard input (<code>stdin</code>) is a terminal,\nand as <code>lua -</code> otherwise.\n\n\n<p>\nBefore running any argument,\nthe interpreter checks for an environment variable <a name=\"pdf-LUA_INIT\"><code>LUA_INIT</code></a>.\nIf its format is <code>@<em>filename</em></code>,\nthen <code>lua</code> executes the file.\nOtherwise, <code>lua</code> executes the string itself.\n\n\n<p>\nAll options are handled in order, except <code>-i</code>.\nFor instance, an invocation like\n\n<pre>\n     $ lua -e'a=1' -e 'print(a)' script.lua\n</pre><p>\nwill first set <code>a</code> to 1, then print the value of <code>a</code> (which is '<code>1</code>'),\nand finally run the file <code>script.lua</code> with no arguments.\n(Here <code>$</code> is the shell prompt. Your prompt may be different.)\n\n\n<p>\nBefore starting to run the script,\n<code>lua</code> collects all arguments in the command line\nin a global table called <code>arg</code>.\nThe script name is stored at index 0,\nthe first argument after the script name goes to index 1,\nand so on.\nAny arguments before the script name\n(that is, the interpreter name plus the options)\ngo to negative indices.\nFor instance, in the call\n\n<pre>\n     $ lua -la b.lua t1 t2\n</pre><p>\nthe interpreter first runs the file <code>a.lua</code>,\nthen creates a table\n\n<pre>\n     arg = { [-2] = \"lua\", [-1] = \"-la\",\n             [0] = \"b.lua\",\n             [1] = \"t1\", [2] = \"t2\" }\n</pre><p>\nand finally runs the file <code>b.lua</code>.\nThe script is called with <code>arg[1]</code>, <code>arg[2]</code>, &middot;&middot;&middot;\nas arguments;\nit can also access these arguments with the vararg expression '<code>...</code>'.\n\n\n<p>\nIn interactive mode,\nif you write an incomplete statement,\nthe interpreter waits for its completion\nby issuing a different prompt.\n\n\n<p>\nIf the global variable <a name=\"pdf-_PROMPT\"><code>_PROMPT</code></a> contains a string,\nthen its value is used as the prompt.\nSimilarly, if the global variable <a name=\"pdf-_PROMPT2\"><code>_PROMPT2</code></a> contains a string,\nits value is used as the secondary prompt\n(issued during incomplete statements).\nTherefore, both prompts can be changed directly on the command line\nor in any Lua programs by assigning to <code>_PROMPT</code>.\nSee the next example:\n\n<pre>\n     $ lua -e\"_PROMPT='myprompt&gt; '\" -i\n</pre><p>\n(The outer pair of quotes is for the shell,\nthe inner pair is for Lua.)\nNote the use of <code>-i</code> to enter interactive mode;\notherwise,\nthe program would just end silently\nright after the assignment to <code>_PROMPT</code>.\n\n\n<p>\nTo allow the use of Lua as a\nscript interpreter in Unix systems,\nthe stand-alone interpreter skips\nthe first line of a chunk if it starts with <code>#</code>.\nTherefore, Lua scripts can be made into executable programs\nby using <code>chmod +x</code> and the&nbsp;<code>#!</code> form,\nas in\n\n<pre>\n     #!/usr/local/bin/lua\n</pre><p>\n(Of course,\nthe location of the Lua interpreter may be different in your machine.\nIf <code>lua</code> is in your <code>PATH</code>,\nthen \n\n<pre>\n     #!/usr/bin/env lua\n</pre><p>\nis a more portable solution.) \n\n\n\n<h1>7 - <a name=\"7\">Incompatibilities with the Previous Version</a></h1>\n\n<p>\nHere we list the incompatibilities that you may find when moving a program\nfrom Lua&nbsp;5.0 to Lua&nbsp;5.1.\nYou can avoid most of the incompatibilities compiling Lua with\nappropriate options (see file <code>luaconf.h</code>).\nHowever,\nall these compatibility options will be removed in the next version of Lua.\n\n\n\n<h2>7.1 - <a name=\"7.1\">Changes in the Language</a></h2>\n<ul>\n\n<li>\nThe vararg system changed from the pseudo-argument <code>arg</code> with a\ntable with the extra arguments to the vararg expression.\n(See compile-time option <code>LUA_COMPAT_VARARG</code> in <code>luaconf.h</code>.)\n</li>\n\n<li>\nThere was a subtle change in the scope of the implicit\nvariables of the <b>for</b> statement and for the <b>repeat</b> statement.\n</li>\n\n<li>\nThe long string/long comment syntax (<code>[[<em>string</em>]]</code>)\ndoes not allow nesting.\nYou can use the new syntax (<code>[=[<em>string</em>]=]</code>) in these cases.\n(See compile-time option <code>LUA_COMPAT_LSTR</code> in <code>luaconf.h</code>.)\n</li>\n\n</ul>\n\n\n\n\n<h2>7.2 - <a name=\"7.2\">Changes in the Libraries</a></h2>\n<ul>\n\n<li>\nFunction <code>string.gfind</code> was renamed <a href=\"#pdf-string.gmatch\"><code>string.gmatch</code></a>.\n(See compile-time option <code>LUA_COMPAT_GFIND</code> in <code>luaconf.h</code>.)\n</li>\n\n<li>\nWhen <a href=\"#pdf-string.gsub\"><code>string.gsub</code></a> is called with a function as its\nthird argument,\nwhenever this function returns <b>nil</b> or <b>false</b> the\nreplacement string is the whole match,\ninstead of the empty string.\n</li>\n\n<li>\nFunction <code>table.setn</code> was deprecated.\nFunction <code>table.getn</code> corresponds\nto the new length operator (<code>#</code>);\nuse the operator instead of the function.\n(See compile-time option <code>LUA_COMPAT_GETN</code> in <code>luaconf.h</code>.)\n</li>\n\n<li>\nFunction <code>loadlib</code> was renamed <a href=\"#pdf-package.loadlib\"><code>package.loadlib</code></a>.\n(See compile-time option <code>LUA_COMPAT_LOADLIB</code> in <code>luaconf.h</code>.)\n</li>\n\n<li>\nFunction <code>math.mod</code> was renamed <a href=\"#pdf-math.fmod\"><code>math.fmod</code></a>.\n(See compile-time option <code>LUA_COMPAT_MOD</code> in <code>luaconf.h</code>.)\n</li>\n\n<li>\nFunctions <code>table.foreach</code> and <code>table.foreachi</code> are deprecated.\nYou can use a for loop with <code>pairs</code> or <code>ipairs</code> instead.\n</li>\n\n<li>\nThere were substantial changes in function <a href=\"#pdf-require\"><code>require</code></a> due to\nthe new module system.\nHowever, the new behavior is mostly compatible with the old,\nbut <code>require</code> gets the path from <a href=\"#pdf-package.path\"><code>package.path</code></a> instead\nof from <code>LUA_PATH</code>.\n</li>\n\n<li>\nFunction <a href=\"#pdf-collectgarbage\"><code>collectgarbage</code></a> has different arguments.\nFunction <code>gcinfo</code> is deprecated;\nuse <code>collectgarbage(\"count\")</code> instead.\n</li>\n\n</ul>\n\n\n\n\n<h2>7.3 - <a name=\"7.3\">Changes in the API</a></h2>\n<ul>\n\n<li>\nThe <code>luaopen_*</code> functions (to open libraries)\ncannot be called directly,\nlike a regular C function.\nThey must be called through Lua,\nlike a Lua function.\n</li>\n\n<li>\nFunction <code>lua_open</code> was replaced by <a href=\"#lua_newstate\"><code>lua_newstate</code></a> to\nallow the user to set a memory-allocation function.\nYou can use <a href=\"#luaL_newstate\"><code>luaL_newstate</code></a> from the standard library to\ncreate a state with a standard allocation function\n(based on <code>realloc</code>).\n</li>\n\n<li>\nFunctions <code>luaL_getn</code> and <code>luaL_setn</code>\n(from the auxiliary library) are deprecated.\nUse <a href=\"#lua_objlen\"><code>lua_objlen</code></a> instead of <code>luaL_getn</code>\nand nothing instead of <code>luaL_setn</code>.\n</li>\n\n<li>\nFunction <code>luaL_openlib</code> was replaced by <a href=\"#luaL_register\"><code>luaL_register</code></a>.\n</li>\n\n<li>\nFunction <code>luaL_checkudata</code> now throws an error when the given value\nis not a userdata of the expected type.\n(In Lua&nbsp;5.0 it returned <code>NULL</code>.)\n</li>\n\n</ul>\n\n\n\n\n<h1>8 - <a name=\"8\">The Complete Syntax of Lua</a></h1>\n\n<p>\nHere is the complete syntax of Lua in extended BNF.\n(It does not describe operator precedences.)\n\n\n\n\n<pre>\n\n\tchunk ::= {stat [`<b>;</b>&acute;]} [laststat [`<b>;</b>&acute;]]\n\n\tblock ::= chunk\n\n\tstat ::=  varlist `<b>=</b>&acute; explist | \n\t\t functioncall | \n\t\t <b>do</b> block <b>end</b> | \n\t\t <b>while</b> exp <b>do</b> block <b>end</b> | \n\t\t <b>repeat</b> block <b>until</b> exp | \n\t\t <b>if</b> exp <b>then</b> block {<b>elseif</b> exp <b>then</b> block} [<b>else</b> block] <b>end</b> | \n\t\t <b>for</b> Name `<b>=</b>&acute; exp `<b>,</b>&acute; exp [`<b>,</b>&acute; exp] <b>do</b> block <b>end</b> | \n\t\t <b>for</b> namelist <b>in</b> explist <b>do</b> block <b>end</b> | \n\t\t <b>function</b> funcname funcbody | \n\t\t <b>local</b> <b>function</b> Name funcbody | \n\t\t <b>local</b> namelist [`<b>=</b>&acute; explist] \n\n\tlaststat ::= <b>return</b> [explist] | <b>break</b>\n\n\tfuncname ::= Name {`<b>.</b>&acute; Name} [`<b>:</b>&acute; Name]\n\n\tvarlist ::= var {`<b>,</b>&acute; var}\n\n\tvar ::=  Name | prefixexp `<b>[</b>&acute; exp `<b>]</b>&acute; | prefixexp `<b>.</b>&acute; Name \n\n\tnamelist ::= Name {`<b>,</b>&acute; Name}\n\n\texplist ::= {exp `<b>,</b>&acute;} exp\n\n\texp ::=  <b>nil</b> | <b>false</b> | <b>true</b> | Number | String | `<b>...</b>&acute; | function | \n\t\t prefixexp | tableconstructor | exp binop exp | unop exp \n\n\tprefixexp ::= var | functioncall | `<b>(</b>&acute; exp `<b>)</b>&acute;\n\n\tfunctioncall ::=  prefixexp args | prefixexp `<b>:</b>&acute; Name args \n\n\targs ::=  `<b>(</b>&acute; [explist] `<b>)</b>&acute; | tableconstructor | String \n\n\tfunction ::= <b>function</b> funcbody\n\n\tfuncbody ::= `<b>(</b>&acute; [parlist] `<b>)</b>&acute; block <b>end</b>\n\n\tparlist ::= namelist [`<b>,</b>&acute; `<b>...</b>&acute;] | `<b>...</b>&acute;\n\n\ttableconstructor ::= `<b>{</b>&acute; [fieldlist] `<b>}</b>&acute;\n\n\tfieldlist ::= field {fieldsep field} [fieldsep]\n\n\tfield ::= `<b>[</b>&acute; exp `<b>]</b>&acute; `<b>=</b>&acute; exp | Name `<b>=</b>&acute; exp | exp\n\n\tfieldsep ::= `<b>,</b>&acute; | `<b>;</b>&acute;\n\n\tbinop ::= `<b>+</b>&acute; | `<b>-</b>&acute; | `<b>*</b>&acute; | `<b>/</b>&acute; | `<b>^</b>&acute; | `<b>%</b>&acute; | `<b>..</b>&acute; | \n\t\t `<b>&lt;</b>&acute; | `<b>&lt;=</b>&acute; | `<b>&gt;</b>&acute; | `<b>&gt;=</b>&acute; | `<b>==</b>&acute; | `<b>~=</b>&acute; | \n\t\t <b>and</b> | <b>or</b>\n\n\tunop ::= `<b>-</b>&acute; | <b>not</b> | `<b>#</b>&acute;\n\n</pre>\n\n<p>\n\n\n\n\n\n\n\n<HR>\n<SMALL CLASS=\"footer\">\nLast update:\nMon Feb 13 18:54:19 BRST 2012\n</SMALL>\n<!--\nLast change: revised for Lua 5.1.5\n-->\n\n</body></html>\n\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.8/deps/lua/doc/readme.html",
    "content": "<HTML>\n<HEAD>\n<TITLE>Lua documentation</TITLE>\n<LINK REL=\"stylesheet\" TYPE=\"text/css\" HREF=\"lua.css\">\n</HEAD>\n\n<BODY>\n\n<HR>\n<H1>\n<A HREF=\"http://www.lua.org/\"><IMG SRC=\"logo.gif\" ALT=\"Lua\" BORDER=0></A>\nDocumentation\n</H1>\n\nThis is the documentation included in the source distribution of Lua 5.1.5.\n\n<UL>\n<LI><A HREF=\"contents.html\">Reference manual</A>\n<LI><A HREF=\"lua.html\">lua man page</A>\n<LI><A HREF=\"luac.html\">luac man page</A>\n<LI><A HREF=\"../README\">lua/README</A>\n<LI><A HREF=\"../etc/README\">lua/etc/README</A>\n<LI><A HREF=\"../test/README\">lua/test/README</A>\n</UL>\n\nLua's\n<A HREF=\"http://www.lua.org/\">official web site</A>\ncontains updated documentation,\nespecially the\n<A HREF=\"http://www.lua.org/manual/5.1/\">reference manual</A>.\n<P>\n\n<HR>\n<SMALL>\nLast update:\nFri Feb  3 09:44:42 BRST 2012\n</SMALL>\n\n</BODY>\n</HTML>\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.8/deps/lua/etc/Makefile",
    "content": "# makefile for Lua etc\n\nTOP= ..\nLIB= $(TOP)/src\nINC= $(TOP)/src\nBIN= $(TOP)/src\nSRC= $(TOP)/src\nTST= $(TOP)/test\n\nCC= gcc\nCFLAGS= -O2 -Wall -I$(INC) $(MYCFLAGS)\nMYCFLAGS= \nMYLDFLAGS= -Wl,-E\nMYLIBS= -lm\n#MYLIBS= -lm -Wl,-E -ldl -lreadline -lhistory -lncurses\nRM= rm -f\n\ndefault:\n\t@echo 'Please choose a target: min noparser one strict clean'\n\nmin:\tmin.c\n\t$(CC) $(CFLAGS) $@.c -L$(LIB) -llua $(MYLIBS)\n\techo 'print\"Hello there!\"' | ./a.out\n\nnoparser: noparser.o\n\t$(CC) noparser.o $(SRC)/lua.o -L$(LIB) -llua $(MYLIBS)\n\t$(BIN)/luac $(TST)/hello.lua\n\t-./a.out luac.out\n\t-./a.out -e'a=1'\n\none:\n\t$(CC) $(CFLAGS) all.c $(MYLIBS)\n\t./a.out $(TST)/hello.lua\n\nstrict:\n\t-$(BIN)/lua -e 'print(a);b=2'\n\t-$(BIN)/lua -lstrict -e 'print(a)'\n\t-$(BIN)/lua -e 'function f() b=2 end f()'\n\t-$(BIN)/lua -lstrict -e 'function f() b=2 end f()'\n\nclean:\n\t$(RM) a.out core core.* *.o luac.out\n\n.PHONY:\tdefault min noparser one strict clean\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.8/deps/lua/etc/README",
    "content": "This directory contains some useful files and code.\nUnlike the code in ../src, everything here is in the public domain.\n\nIf any of the makes fail, you're probably not using the same libraries\nused to build Lua. Set MYLIBS in Makefile accordingly.\n\nall.c\n\tFull Lua interpreter in a single file.\n\tDo \"make one\" for a demo.\n\nlua.hpp\n\tLua header files for C++ using 'extern \"C\"'.\n\nlua.ico\n\tA Lua icon for Windows (and web sites: save as favicon.ico).\n\tDrawn by hand by Markus Gritsch <gritsch@iue.tuwien.ac.at>.\n\nlua.pc\n\tpkg-config data for Lua\n\nluavs.bat\n\tScript to build Lua under \"Visual Studio .NET Command Prompt\".\n\tRun it from the toplevel as etc\\luavs.bat.\n\nmin.c\n\tA minimal Lua interpreter.\n\tGood for learning and for starting your own.\n\tDo \"make min\" for a demo.\n\nnoparser.c\n\tLinking with noparser.o avoids loading the parsing modules in lualib.a.\n\tDo \"make noparser\" for a demo.\n\nstrict.lua\n\tTraps uses of undeclared global variables.\n\tDo \"make strict\" for a demo.\n\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.8/deps/lua/etc/all.c",
    "content": "/*\n* all.c -- Lua core, libraries and interpreter in a single file\n*/\n\n#define luaall_c\n\n#include \"lapi.c\"\n#include \"lcode.c\"\n#include \"ldebug.c\"\n#include \"ldo.c\"\n#include \"ldump.c\"\n#include \"lfunc.c\"\n#include \"lgc.c\"\n#include \"llex.c\"\n#include \"lmem.c\"\n#include \"lobject.c\"\n#include \"lopcodes.c\"\n#include \"lparser.c\"\n#include \"lstate.c\"\n#include \"lstring.c\"\n#include \"ltable.c\"\n#include \"ltm.c\"\n#include \"lundump.c\"\n#include \"lvm.c\"\n#include \"lzio.c\"\n\n#include \"lauxlib.c\"\n#include \"lbaselib.c\"\n#include \"ldblib.c\"\n#include \"liolib.c\"\n#include \"linit.c\"\n#include \"lmathlib.c\"\n#include \"loadlib.c\"\n#include \"loslib.c\"\n#include \"lstrlib.c\"\n#include \"ltablib.c\"\n\n#include \"lua.c\"\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.8/deps/lua/etc/lua.hpp",
    "content": "// lua.hpp\n// Lua header files for C++\n// <<extern \"C\">> not supplied automatically because Lua also compiles as C++\n\nextern \"C\" {\n#include \"lua.h\"\n#include \"lualib.h\"\n#include \"lauxlib.h\"\n}\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.8/deps/lua/etc/lua.pc",
    "content": "# lua.pc -- pkg-config data for Lua\n\n# vars from install Makefile\n\n# grep '^V=' ../Makefile\nV= 5.1\n# grep '^R=' ../Makefile\nR= 5.1.5\n\n# grep '^INSTALL_.*=' ../Makefile | sed 's/INSTALL_TOP/prefix/'\nprefix= /usr/local\nINSTALL_BIN= ${prefix}/bin\nINSTALL_INC= ${prefix}/include\nINSTALL_LIB= ${prefix}/lib\nINSTALL_MAN= ${prefix}/man/man1\nINSTALL_LMOD= ${prefix}/share/lua/${V}\nINSTALL_CMOD= ${prefix}/lib/lua/${V}\n\n# canonical vars\nexec_prefix=${prefix}\nlibdir=${exec_prefix}/lib\nincludedir=${prefix}/include\n\nName: Lua\nDescription: An Extensible Extension Language\nVersion: ${R}\nRequires: \nLibs: -L${libdir} -llua -lm\nCflags: -I${includedir}\n\n# (end of lua.pc)\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.8/deps/lua/etc/luavs.bat",
    "content": "@rem Script to build Lua under \"Visual Studio .NET Command Prompt\".\r\n@rem Do not run from this directory; run it from the toplevel: etc\\luavs.bat .\r\n@rem It creates lua51.dll, lua51.lib, lua.exe, and luac.exe in src.\r\n@rem (contributed by David Manura and Mike Pall)\r\n\r\n@setlocal\r\n@set MYCOMPILE=cl /nologo /MD /O2 /W3 /c /D_CRT_SECURE_NO_DEPRECATE\r\n@set MYLINK=link /nologo\r\n@set MYMT=mt /nologo\r\n\r\ncd src\r\n%MYCOMPILE% /DLUA_BUILD_AS_DLL l*.c\r\ndel lua.obj luac.obj\r\n%MYLINK% /DLL /out:lua51.dll l*.obj\r\nif exist lua51.dll.manifest^\r\n  %MYMT% -manifest lua51.dll.manifest -outputresource:lua51.dll;2\r\n%MYCOMPILE% /DLUA_BUILD_AS_DLL lua.c\r\n%MYLINK% /out:lua.exe lua.obj lua51.lib\r\nif exist lua.exe.manifest^\r\n  %MYMT% -manifest lua.exe.manifest -outputresource:lua.exe\r\n%MYCOMPILE% l*.c print.c\r\ndel lua.obj linit.obj lbaselib.obj ldblib.obj liolib.obj lmathlib.obj^\r\n    loslib.obj ltablib.obj lstrlib.obj loadlib.obj\r\n%MYLINK% /out:luac.exe *.obj\r\nif exist luac.exe.manifest^\r\n  %MYMT% -manifest luac.exe.manifest -outputresource:luac.exe\r\ndel *.obj *.manifest\r\ncd ..\r\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.8/deps/lua/etc/min.c",
    "content": "/*\n* min.c -- a minimal Lua interpreter\n* loads stdin only with minimal error handling.\n* no interaction, and no standard library, only a \"print\" function.\n*/\n\n#include <stdio.h>\n\n#include \"lua.h\"\n#include \"lauxlib.h\"\n\nstatic int print(lua_State *L)\n{\n int n=lua_gettop(L);\n int i;\n for (i=1; i<=n; i++)\n {\n  if (i>1) printf(\"\\t\");\n  if (lua_isstring(L,i))\n   printf(\"%s\",lua_tostring(L,i));\n  else if (lua_isnil(L,i))\n   printf(\"%s\",\"nil\");\n  else if (lua_isboolean(L,i))\n   printf(\"%s\",lua_toboolean(L,i) ? \"true\" : \"false\");\n  else\n   printf(\"%s:%p\",luaL_typename(L,i),lua_topointer(L,i));\n }\n printf(\"\\n\");\n return 0;\n}\n\nint main(void)\n{\n lua_State *L=lua_open();\n lua_register(L,\"print\",print);\n if (luaL_dofile(L,NULL)!=0) fprintf(stderr,\"%s\\n\",lua_tostring(L,-1));\n lua_close(L);\n return 0;\n}\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.8/deps/lua/etc/noparser.c",
    "content": "/*\n* The code below can be used to make a Lua core that does not contain the\n* parsing modules (lcode, llex, lparser), which represent 35% of the total core.\n* You'll only be able to load binary files and strings, precompiled with luac.\n* (Of course, you'll have to build luac with the original parsing modules!)\n*\n* To use this module, simply compile it (\"make noparser\" does that) and list\n* its object file before the Lua libraries. The linker should then not load\n* the parsing modules. To try it, do \"make luab\".\n*\n* If you also want to avoid the dump module (ldump.o), define NODUMP.\n* #define NODUMP\n*/\n\n#define LUA_CORE\n\n#include \"llex.h\"\n#include \"lparser.h\"\n#include \"lzio.h\"\n\nLUAI_FUNC void luaX_init (lua_State *L) {\n  UNUSED(L);\n}\n\nLUAI_FUNC Proto *luaY_parser (lua_State *L, ZIO *z, Mbuffer *buff, const char *name) {\n  UNUSED(z);\n  UNUSED(buff);\n  UNUSED(name);\n  lua_pushliteral(L,\"parser not loaded\");\n  lua_error(L);\n  return NULL;\n}\n\n#ifdef NODUMP\n#include \"lundump.h\"\n\nLUAI_FUNC int luaU_dump (lua_State* L, const Proto* f, lua_Writer w, void* data, int strip) {\n  UNUSED(f);\n  UNUSED(w);\n  UNUSED(data);\n  UNUSED(strip);\n#if 1\n  UNUSED(L);\n  return 0;\n#else\n  lua_pushliteral(L,\"dumper not loaded\");\n  lua_error(L);\n#endif\n}\n#endif\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.8/deps/lua/etc/strict.lua",
    "content": "--\n-- strict.lua\n-- checks uses of undeclared global variables\n-- All global variables must be 'declared' through a regular assignment\n-- (even assigning nil will do) in a main chunk before being used\n-- anywhere or assigned to inside a function.\n--\n\nlocal getinfo, error, rawset, rawget = debug.getinfo, error, rawset, rawget\n\nlocal mt = getmetatable(_G)\nif mt == nil then\n  mt = {}\n  setmetatable(_G, mt)\nend\n\nmt.__declared = {}\n\nlocal function what ()\n  local d = getinfo(3, \"S\")\n  return d and d.what or \"C\"\nend\n\nmt.__newindex = function (t, n, v)\n  if not mt.__declared[n] then\n    local w = what()\n    if w ~= \"main\" and w ~= \"C\" then\n      error(\"assign to undeclared variable '\"..n..\"'\", 2)\n    end\n    mt.__declared[n] = true\n  end\n  rawset(t, n, v)\nend\n  \nmt.__index = function (t, n)\n  if not mt.__declared[n] and what() ~= \"C\" then\n    error(\"variable '\"..n..\"' is not declared\", 2)\n  end\n  return rawget(t, n)\nend\n\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.8/deps/lua/src/Makefile",
    "content": "# makefile for building Lua\n# see ../INSTALL for installation instructions\n# see ../Makefile and luaconf.h for further customization\n\n# == CHANGE THE SETTINGS BELOW TO SUIT YOUR ENVIRONMENT =======================\n\n# Your platform. See PLATS for possible values.\nPLAT= none\n\nCC?= gcc\nCFLAGS= -O2 -Wall $(MYCFLAGS)\nAR= ar rcu\nRANLIB= ranlib\nRM= rm -f\nLIBS= -lm $(MYLIBS)\n\nMYCFLAGS=\nMYLDFLAGS=\nMYLIBS=\n\n# == END OF USER SETTINGS. NO NEED TO CHANGE ANYTHING BELOW THIS LINE =========\n\nPLATS= aix ansi bsd freebsd generic linux macosx mingw posix solaris\n\nLUA_A=\tliblua.a\nCORE_O=\tlapi.o lcode.o ldebug.o ldo.o ldump.o lfunc.o lgc.o llex.o lmem.o \\\n\tlobject.o lopcodes.o lparser.o lstate.o lstring.o ltable.o ltm.o  \\\n\tlundump.o lvm.o lzio.o strbuf.o fpconv.o\nLIB_O=\tlauxlib.o lbaselib.o ldblib.o liolib.o lmathlib.o loslib.o ltablib.o \\\n\tlstrlib.o loadlib.o linit.o lua_cjson.o lua_struct.o lua_cmsgpack.o \\\n\tlua_bit.o\n\nLUA_T=\tlua\nLUA_O=\tlua.o\n\nLUAC_T=\tluac\nLUAC_O=\tluac.o print.o\n\nALL_O= $(CORE_O) $(LIB_O) $(LUA_O) $(LUAC_O)\nALL_T= $(LUA_A) $(LUA_T) $(LUAC_T)\nALL_A= $(LUA_A)\n\ndefault: $(PLAT)\n\nall:\t$(ALL_T)\n\no:\t$(ALL_O)\n\na:\t$(ALL_A)\n\n$(LUA_A): $(CORE_O) $(LIB_O)\n\t$(AR) $@ $(CORE_O) $(LIB_O)\t# DLL needs all object files\n\t$(RANLIB) $@\n\n$(LUA_T): $(LUA_O) $(LUA_A)\n\t$(CC) -o $@ $(MYLDFLAGS) $(LUA_O) $(LUA_A) $(LIBS)\n\n$(LUAC_T): $(LUAC_O) $(LUA_A)\n\t$(CC) -o $@ $(MYLDFLAGS) $(LUAC_O) $(LUA_A) $(LIBS)\n\nclean:\n\t$(RM) $(ALL_T) $(ALL_O)\n\ndepend:\n\t@$(CC) $(CFLAGS) -MM l*.c print.c\n\necho:\n\t@echo \"PLAT = $(PLAT)\"\n\t@echo \"CC = $(CC)\"\n\t@echo \"CFLAGS = $(CFLAGS)\"\n\t@echo \"AR = $(AR)\"\n\t@echo \"RANLIB = $(RANLIB)\"\n\t@echo \"RM = $(RM)\"\n\t@echo \"MYCFLAGS = $(MYCFLAGS)\"\n\t@echo \"MYLDFLAGS = $(MYLDFLAGS)\"\n\t@echo \"MYLIBS = $(MYLIBS)\"\n\n# convenience targets for popular platforms\n\nnone:\n\t@echo \"Please choose a platform:\"\n\t@echo \"   $(PLATS)\"\n\naix:\n\t$(MAKE) all CC=\"xlc\" CFLAGS=\"-O2 -DLUA_USE_POSIX -DLUA_USE_DLOPEN\" MYLIBS=\"-ldl\" MYLDFLAGS=\"-brtl -bexpall\"\n\nansi:\n\t$(MAKE) all MYCFLAGS=-DLUA_ANSI\n\nbsd:\n\t$(MAKE) all MYCFLAGS=\"-DLUA_USE_POSIX -DLUA_USE_DLOPEN\" MYLIBS=\"-Wl,-E\"\n\nfreebsd:\n\t$(MAKE) all MYCFLAGS=\"-DLUA_USE_LINUX\" MYLIBS=\"-Wl,-E -lreadline\"\n\ngeneric:\n\t$(MAKE) all MYCFLAGS=\n\nlinux:\n\t$(MAKE) all MYCFLAGS=-DLUA_USE_LINUX MYLIBS=\"-Wl,-E -ldl -lreadline -lhistory -lncurses\"\n\nmacosx:\n\t$(MAKE) all MYCFLAGS=-DLUA_USE_LINUX MYLIBS=\"-lreadline\"\n# use this on Mac OS X 10.3-\n#\t$(MAKE) all MYCFLAGS=-DLUA_USE_MACOSX\n\nmingw:\n\t$(MAKE) \"LUA_A=lua51.dll\" \"LUA_T=lua.exe\" \\\n\t\"AR=$(CC) -shared -o\" \"RANLIB=strip --strip-unneeded\" \\\n\t\"MYCFLAGS=-DLUA_BUILD_AS_DLL\" \"MYLIBS=\" \"MYLDFLAGS=-s\" lua.exe\n\t$(MAKE) \"LUAC_T=luac.exe\" luac.exe\n\nposix:\n\t$(MAKE) all MYCFLAGS=-DLUA_USE_POSIX\n\nsolaris:\n\t$(MAKE) all MYCFLAGS=\"-DLUA_USE_POSIX -DLUA_USE_DLOPEN\" MYLIBS=\"-ldl\"\n\n# list targets that do not create files (but not all makes understand .PHONY)\n.PHONY: all $(PLATS) default o a clean depend echo none\n\n# DO NOT DELETE\n\nlapi.o: lapi.c lua.h luaconf.h lapi.h lobject.h llimits.h ldebug.h \\\n  lstate.h ltm.h lzio.h lmem.h ldo.h lfunc.h lgc.h lstring.h ltable.h \\\n  lundump.h lvm.h\nlauxlib.o: lauxlib.c lua.h luaconf.h lauxlib.h\nlbaselib.o: lbaselib.c lua.h luaconf.h lauxlib.h lualib.h\nlcode.o: lcode.c lua.h luaconf.h lcode.h llex.h lobject.h llimits.h \\\n  lzio.h lmem.h lopcodes.h lparser.h ldebug.h lstate.h ltm.h ldo.h lgc.h \\\n  ltable.h\nldblib.o: ldblib.c lua.h luaconf.h lauxlib.h lualib.h\nldebug.o: ldebug.c lua.h luaconf.h lapi.h lobject.h llimits.h lcode.h \\\n  llex.h lzio.h lmem.h lopcodes.h lparser.h ldebug.h lstate.h ltm.h ldo.h \\\n  lfunc.h lstring.h lgc.h ltable.h lvm.h\nldo.o: ldo.c lua.h luaconf.h ldebug.h lstate.h lobject.h llimits.h ltm.h \\\n  lzio.h lmem.h ldo.h lfunc.h lgc.h lopcodes.h lparser.h lstring.h \\\n  ltable.h lundump.h lvm.h\nldump.o: ldump.c lua.h luaconf.h lobject.h llimits.h lstate.h ltm.h \\\n  lzio.h lmem.h lundump.h\nlfunc.o: lfunc.c lua.h luaconf.h lfunc.h lobject.h llimits.h lgc.h lmem.h \\\n  lstate.h ltm.h lzio.h\nlgc.o: lgc.c lua.h luaconf.h ldebug.h lstate.h lobject.h llimits.h ltm.h \\\n  lzio.h lmem.h ldo.h lfunc.h lgc.h lstring.h ltable.h\nlinit.o: linit.c lua.h luaconf.h lualib.h lauxlib.h\nliolib.o: liolib.c lua.h luaconf.h lauxlib.h lualib.h\nllex.o: llex.c lua.h luaconf.h ldo.h lobject.h llimits.h lstate.h ltm.h \\\n  lzio.h lmem.h llex.h lparser.h lstring.h lgc.h ltable.h\nlmathlib.o: lmathlib.c lua.h luaconf.h lauxlib.h lualib.h\nlmem.o: lmem.c lua.h luaconf.h ldebug.h lstate.h lobject.h llimits.h \\\n  ltm.h lzio.h lmem.h ldo.h\nloadlib.o: loadlib.c lua.h luaconf.h lauxlib.h lualib.h\nlobject.o: lobject.c lua.h luaconf.h ldo.h lobject.h llimits.h lstate.h \\\n  ltm.h lzio.h lmem.h lstring.h lgc.h lvm.h\nlopcodes.o: lopcodes.c lopcodes.h llimits.h lua.h luaconf.h\nloslib.o: loslib.c lua.h luaconf.h lauxlib.h lualib.h\nlparser.o: lparser.c lua.h luaconf.h lcode.h llex.h lobject.h llimits.h \\\n  lzio.h lmem.h lopcodes.h lparser.h ldebug.h lstate.h ltm.h ldo.h \\\n  lfunc.h lstring.h lgc.h ltable.h\nlstate.o: lstate.c lua.h luaconf.h ldebug.h lstate.h lobject.h llimits.h \\\n  ltm.h lzio.h lmem.h ldo.h lfunc.h lgc.h llex.h lstring.h ltable.h\nlstring.o: lstring.c lua.h luaconf.h lmem.h llimits.h lobject.h lstate.h \\\n  ltm.h lzio.h lstring.h lgc.h\nlstrlib.o: lstrlib.c lua.h luaconf.h lauxlib.h lualib.h\nltable.o: ltable.c lua.h luaconf.h ldebug.h lstate.h lobject.h llimits.h \\\n  ltm.h lzio.h lmem.h ldo.h lgc.h ltable.h\nltablib.o: ltablib.c lua.h luaconf.h lauxlib.h lualib.h\nltm.o: ltm.c lua.h luaconf.h lobject.h llimits.h lstate.h ltm.h lzio.h \\\n  lmem.h lstring.h lgc.h ltable.h\nlua.o: lua.c lua.h luaconf.h lauxlib.h lualib.h\nluac.o: luac.c lua.h luaconf.h lauxlib.h ldo.h lobject.h llimits.h \\\n  lstate.h ltm.h lzio.h lmem.h lfunc.h lopcodes.h lstring.h lgc.h \\\n  lundump.h\nlundump.o: lundump.c lua.h luaconf.h ldebug.h lstate.h lobject.h \\\n  llimits.h ltm.h lzio.h lmem.h ldo.h lfunc.h lstring.h lgc.h lundump.h\nlvm.o: lvm.c lua.h luaconf.h ldebug.h lstate.h lobject.h llimits.h ltm.h \\\n  lzio.h lmem.h ldo.h lfunc.h lgc.h lopcodes.h lstring.h ltable.h lvm.h\nlzio.o: lzio.c lua.h luaconf.h llimits.h lmem.h lstate.h lobject.h ltm.h \\\n  lzio.h\nprint.o: print.c ldebug.h lstate.h lua.h luaconf.h lobject.h llimits.h \\\n  ltm.h lzio.h lmem.h lopcodes.h lundump.h\n\n# (end of Makefile)\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.8/deps/lua/src/fpconv.c",
    "content": "/* fpconv - Floating point conversion routines\n *\n * Copyright (c) 2011-2012  Mark Pulford <mark@kyne.com.au>\n *\n * Permission is hereby granted, free of charge, to any person obtaining\n * a copy of this software and associated documentation files (the\n * \"Software\"), to deal in the Software without restriction, including\n * without limitation the rights to use, copy, modify, merge, publish,\n * distribute, sublicense, and/or sell copies of the Software, and to\n * permit persons to whom the Software is furnished to do so, subject to\n * the following conditions:\n *\n * The above copyright notice and this permission notice shall be\n * included in all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND,\n * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\n * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.\n * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY\n * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,\n * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE\n * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n */\n\n/* JSON uses a '.' decimal separator. strtod() / sprintf() under C libraries\n * with locale support will break when the decimal separator is a comma.\n *\n * fpconv_* will around these issues with a translation buffer if required.\n */\n\n#include <stdio.h>\n#include <stdlib.h>\n#include <assert.h>\n#include <string.h>\n\n#include \"fpconv.h\"\n\n/* Lua CJSON assumes the locale is the same for all threads within a\n * process and doesn't change after initialisation.\n *\n * This avoids the need for per thread storage or expensive checks\n * for call. */\nstatic char locale_decimal_point = '.';\n\n/* In theory multibyte decimal_points are possible, but\n * Lua CJSON only supports UTF-8 and known locales only have\n * single byte decimal points ([.,]).\n *\n * localconv() may not be thread safe (=>crash), and nl_langinfo() is\n * not supported on some platforms. Use sprintf() instead - if the\n * locale does change, at least Lua CJSON won't crash. */\nstatic void fpconv_update_locale()\n{\n    char buf[8];\n\n    snprintf(buf, sizeof(buf), \"%g\", 0.5);\n\n    /* Failing this test might imply the platform has a buggy dtoa\n     * implementation or wide characters */\n    if (buf[0] != '0' || buf[2] != '5' || buf[3] != 0) {\n        fprintf(stderr, \"Error: wide characters found or printf() bug.\");\n        abort();\n    }\n\n    locale_decimal_point = buf[1];\n}\n\n/* Check for a valid number character: [-+0-9a-yA-Y.]\n * Eg: -0.6e+5, infinity, 0xF0.F0pF0\n *\n * Used to find the probable end of a number. It doesn't matter if\n * invalid characters are counted - strtod() will find the valid\n * number if it exists.  The risk is that slightly more memory might\n * be allocated before a parse error occurs. */\nstatic inline int valid_number_character(char ch)\n{\n    char lower_ch;\n\n    if ('0' <= ch && ch <= '9')\n        return 1;\n    if (ch == '-' || ch == '+' || ch == '.')\n        return 1;\n\n    /* Hex digits, exponent (e), base (p), \"infinity\",.. */\n    lower_ch = ch | 0x20;\n    if ('a' <= lower_ch && lower_ch <= 'y')\n        return 1;\n\n    return 0;\n}\n\n/* Calculate the size of the buffer required for a strtod locale\n * conversion. */\nstatic int strtod_buffer_size(const char *s)\n{\n    const char *p = s;\n\n    while (valid_number_character(*p))\n        p++;\n\n    return p - s;\n}\n\n/* Similar to strtod(), but must be passed the current locale's decimal point\n * character. Guaranteed to be called at the start of any valid number in a string */\ndouble fpconv_strtod(const char *nptr, char **endptr)\n{\n    char localbuf[FPCONV_G_FMT_BUFSIZE];\n    char *buf, *endbuf, *dp;\n    int buflen;\n    double value;\n\n    /* System strtod() is fine when decimal point is '.' */\n    if (locale_decimal_point == '.')\n        return strtod(nptr, endptr);\n\n    buflen = strtod_buffer_size(nptr);\n    if (!buflen) {\n        /* No valid characters found, standard strtod() return */\n        *endptr = (char *)nptr;\n        return 0;\n    }\n\n    /* Duplicate number into buffer */\n    if (buflen >= FPCONV_G_FMT_BUFSIZE) {\n        /* Handle unusually large numbers */\n        buf = malloc(buflen + 1);\n        if (!buf) {\n            fprintf(stderr, \"Out of memory\");\n            abort();\n        }\n    } else {\n        /* This is the common case.. */\n        buf = localbuf;\n    }\n    memcpy(buf, nptr, buflen);\n    buf[buflen] = 0;\n\n    /* Update decimal point character if found */\n    dp = strchr(buf, '.');\n    if (dp)\n        *dp = locale_decimal_point;\n\n    value = strtod(buf, &endbuf);\n    *endptr = (char *)&nptr[endbuf - buf];\n    if (buflen >= FPCONV_G_FMT_BUFSIZE)\n        free(buf);\n\n    return value;\n}\n\n/* \"fmt\" must point to a buffer of at least 6 characters */\nstatic void set_number_format(char *fmt, int precision)\n{\n    int d1, d2, i;\n\n    assert(1 <= precision && precision <= 14);\n\n    /* Create printf format (%.14g) from precision */\n    d1 = precision / 10;\n    d2 = precision % 10;\n    fmt[0] = '%';\n    fmt[1] = '.';\n    i = 2;\n    if (d1) {\n        fmt[i++] = '0' + d1;\n    }\n    fmt[i++] = '0' + d2;\n    fmt[i++] = 'g';\n    fmt[i] = 0;\n}\n\n/* Assumes there is always at least 32 characters available in the target buffer */\nint fpconv_g_fmt(char *str, double num, int precision)\n{\n    char buf[FPCONV_G_FMT_BUFSIZE];\n    char fmt[6];\n    int len;\n    char *b;\n\n    set_number_format(fmt, precision);\n\n    /* Pass through when decimal point character is dot. */\n    if (locale_decimal_point == '.')\n        return snprintf(str, FPCONV_G_FMT_BUFSIZE, fmt, num);\n\n    /* snprintf() to a buffer then translate for other decimal point characters */\n    len = snprintf(buf, FPCONV_G_FMT_BUFSIZE, fmt, num);\n\n    /* Copy into target location. Translate decimal point if required */\n    b = buf;\n    do {\n        *str++ = (*b == locale_decimal_point ? '.' : *b);\n    } while(*b++);\n\n    return len;\n}\n\nvoid fpconv_init()\n{\n    fpconv_update_locale();\n}\n\n/* vi:ai et sw=4 ts=4:\n */\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.8/deps/lua/src/fpconv.h",
    "content": "/* Lua CJSON floating point conversion routines */\n\n/* Buffer required to store the largest string representation of a double.\n *\n * Longest double printed with %.14g is 21 characters long:\n * -1.7976931348623e+308 */\n# define FPCONV_G_FMT_BUFSIZE   32\n\n#ifdef USE_INTERNAL_FPCONV\nstatic inline void fpconv_init()\n{\n    /* Do nothing - not required */\n}\n#else\nextern void fpconv_init();\n#endif\n\nextern int fpconv_g_fmt(char*, double, int);\nextern double fpconv_strtod(const char*, char**);\n\n/* vi:ai et sw=4 ts=4:\n */\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.8/deps/lua/src/lapi.c",
    "content": "/*\n** $Id: lapi.c,v 2.55.1.5 2008/07/04 18:41:18 roberto Exp $\n** Lua API\n** See Copyright Notice in lua.h\n*/\n\n\n#include <assert.h>\n#include <math.h>\n#include <stdarg.h>\n#include <string.h>\n\n#define lapi_c\n#define LUA_CORE\n\n#include \"lua.h\"\n\n#include \"lapi.h\"\n#include \"ldebug.h\"\n#include \"ldo.h\"\n#include \"lfunc.h\"\n#include \"lgc.h\"\n#include \"lmem.h\"\n#include \"lobject.h\"\n#include \"lstate.h\"\n#include \"lstring.h\"\n#include \"ltable.h\"\n#include \"ltm.h\"\n#include \"lundump.h\"\n#include \"lvm.h\"\n\n\n\nconst char lua_ident[] =\n  \"$Lua: \" LUA_RELEASE \" \" LUA_COPYRIGHT \" $\\n\"\n  \"$Authors: \" LUA_AUTHORS \" $\\n\"\n  \"$URL: www.lua.org $\\n\";\n\n\n\n#define api_checknelems(L, n)\tapi_check(L, (n) <= (L->top - L->base))\n\n#define api_checkvalidindex(L, i)\tapi_check(L, (i) != luaO_nilobject)\n\n#define api_incr_top(L)   {api_check(L, L->top < L->ci->top); L->top++;}\n\n\n\nstatic TValue *index2adr (lua_State *L, int idx) {\n  if (idx > 0) {\n    TValue *o = L->base + (idx - 1);\n    api_check(L, idx <= L->ci->top - L->base);\n    if (o >= L->top) return cast(TValue *, luaO_nilobject);\n    else return o;\n  }\n  else if (idx > LUA_REGISTRYINDEX) {\n    api_check(L, idx != 0 && -idx <= L->top - L->base);\n    return L->top + idx;\n  }\n  else switch (idx) {  /* pseudo-indices */\n    case LUA_REGISTRYINDEX: return registry(L);\n    case LUA_ENVIRONINDEX: {\n      Closure *func = curr_func(L);\n      sethvalue(L, &L->env, func->c.env);\n      return &L->env;\n    }\n    case LUA_GLOBALSINDEX: return gt(L);\n    default: {\n      Closure *func = curr_func(L);\n      idx = LUA_GLOBALSINDEX - idx;\n      return (idx <= func->c.nupvalues)\n                ? &func->c.upvalue[idx-1]\n                : cast(TValue *, luaO_nilobject);\n    }\n  }\n}\n\n\nstatic Table *getcurrenv (lua_State *L) {\n  if (L->ci == L->base_ci)  /* no enclosing function? */\n    return hvalue(gt(L));  /* use global table as environment */\n  else {\n    Closure *func = curr_func(L);\n    return func->c.env;\n  }\n}\n\n\nvoid luaA_pushobject (lua_State *L, const TValue *o) {\n  setobj2s(L, L->top, o);\n  api_incr_top(L);\n}\n\n\nLUA_API int lua_checkstack (lua_State *L, int size) {\n  int res = 1;\n  lua_lock(L);\n  if (size > LUAI_MAXCSTACK || (L->top - L->base + size) > LUAI_MAXCSTACK)\n    res = 0;  /* stack overflow */\n  else if (size > 0) {\n    luaD_checkstack(L, size);\n    if (L->ci->top < L->top + size)\n      L->ci->top = L->top + size;\n  }\n  lua_unlock(L);\n  return res;\n}\n\n\nLUA_API void lua_xmove (lua_State *from, lua_State *to, int n) {\n  int i;\n  if (from == to) return;\n  lua_lock(to);\n  api_checknelems(from, n);\n  api_check(from, G(from) == G(to));\n  api_check(from, to->ci->top - to->top >= n);\n  from->top -= n;\n  for (i = 0; i < n; i++) {\n    setobj2s(to, to->top++, from->top + i);\n  }\n  lua_unlock(to);\n}\n\n\nLUA_API void lua_setlevel (lua_State *from, lua_State *to) {\n  to->nCcalls = from->nCcalls;\n}\n\n\nLUA_API lua_CFunction lua_atpanic (lua_State *L, lua_CFunction panicf) {\n  lua_CFunction old;\n  lua_lock(L);\n  old = G(L)->panic;\n  G(L)->panic = panicf;\n  lua_unlock(L);\n  return old;\n}\n\n\nLUA_API lua_State *lua_newthread (lua_State *L) {\n  lua_State *L1;\n  lua_lock(L);\n  luaC_checkGC(L);\n  L1 = luaE_newthread(L);\n  setthvalue(L, L->top, L1);\n  api_incr_top(L);\n  lua_unlock(L);\n  luai_userstatethread(L, L1);\n  return L1;\n}\n\n\n\n/*\n** basic stack manipulation\n*/\n\n\nLUA_API int lua_gettop (lua_State *L) {\n  return cast_int(L->top - L->base);\n}\n\n\nLUA_API void lua_settop (lua_State *L, int idx) {\n  lua_lock(L);\n  if (idx >= 0) {\n    api_check(L, idx <= L->stack_last - L->base);\n    while (L->top < L->base + idx)\n      setnilvalue(L->top++);\n    L->top = L->base + idx;\n  }\n  else {\n    api_check(L, -(idx+1) <= (L->top - L->base));\n    L->top += idx+1;  /* `subtract' index (index is negative) */\n  }\n  lua_unlock(L);\n}\n\n\nLUA_API void lua_remove (lua_State *L, int idx) {\n  StkId p;\n  lua_lock(L);\n  p = index2adr(L, idx);\n  api_checkvalidindex(L, p);\n  while (++p < L->top) setobjs2s(L, p-1, p);\n  L->top--;\n  lua_unlock(L);\n}\n\n\nLUA_API void lua_insert (lua_State *L, int idx) {\n  StkId p;\n  StkId q;\n  lua_lock(L);\n  p = index2adr(L, idx);\n  api_checkvalidindex(L, p);\n  for (q = L->top; q>p; q--) setobjs2s(L, q, q-1);\n  setobjs2s(L, p, L->top);\n  lua_unlock(L);\n}\n\n\nLUA_API void lua_replace (lua_State *L, int idx) {\n  StkId o;\n  lua_lock(L);\n  /* explicit test for incompatible code */\n  if (idx == LUA_ENVIRONINDEX && L->ci == L->base_ci)\n    luaG_runerror(L, \"no calling environment\");\n  api_checknelems(L, 1);\n  o = index2adr(L, idx);\n  api_checkvalidindex(L, o);\n  if (idx == LUA_ENVIRONINDEX) {\n    Closure *func = curr_func(L);\n    api_check(L, ttistable(L->top - 1)); \n    func->c.env = hvalue(L->top - 1);\n    luaC_barrier(L, func, L->top - 1);\n  }\n  else {\n    setobj(L, o, L->top - 1);\n    if (idx < LUA_GLOBALSINDEX)  /* function upvalue? */\n      luaC_barrier(L, curr_func(L), L->top - 1);\n  }\n  L->top--;\n  lua_unlock(L);\n}\n\n\nLUA_API void lua_pushvalue (lua_State *L, int idx) {\n  lua_lock(L);\n  setobj2s(L, L->top, index2adr(L, idx));\n  api_incr_top(L);\n  lua_unlock(L);\n}\n\n\n\n/*\n** access functions (stack -> C)\n*/\n\n\nLUA_API int lua_type (lua_State *L, int idx) {\n  StkId o = index2adr(L, idx);\n  return (o == luaO_nilobject) ? LUA_TNONE : ttype(o);\n}\n\n\nLUA_API const char *lua_typename (lua_State *L, int t) {\n  UNUSED(L);\n  return (t == LUA_TNONE) ? \"no value\" : luaT_typenames[t];\n}\n\n\nLUA_API int lua_iscfunction (lua_State *L, int idx) {\n  StkId o = index2adr(L, idx);\n  return iscfunction(o);\n}\n\n\nLUA_API int lua_isnumber (lua_State *L, int idx) {\n  TValue n;\n  const TValue *o = index2adr(L, idx);\n  return tonumber(o, &n);\n}\n\n\nLUA_API int lua_isstring (lua_State *L, int idx) {\n  int t = lua_type(L, idx);\n  return (t == LUA_TSTRING || t == LUA_TNUMBER);\n}\n\n\nLUA_API int lua_isuserdata (lua_State *L, int idx) {\n  const TValue *o = index2adr(L, idx);\n  return (ttisuserdata(o) || ttislightuserdata(o));\n}\n\n\nLUA_API int lua_rawequal (lua_State *L, int index1, int index2) {\n  StkId o1 = index2adr(L, index1);\n  StkId o2 = index2adr(L, index2);\n  return (o1 == luaO_nilobject || o2 == luaO_nilobject) ? 0\n         : luaO_rawequalObj(o1, o2);\n}\n\n\nLUA_API int lua_equal (lua_State *L, int index1, int index2) {\n  StkId o1, o2;\n  int i;\n  lua_lock(L);  /* may call tag method */\n  o1 = index2adr(L, index1);\n  o2 = index2adr(L, index2);\n  i = (o1 == luaO_nilobject || o2 == luaO_nilobject) ? 0 : equalobj(L, o1, o2);\n  lua_unlock(L);\n  return i;\n}\n\n\nLUA_API int lua_lessthan (lua_State *L, int index1, int index2) {\n  StkId o1, o2;\n  int i;\n  lua_lock(L);  /* may call tag method */\n  o1 = index2adr(L, index1);\n  o2 = index2adr(L, index2);\n  i = (o1 == luaO_nilobject || o2 == luaO_nilobject) ? 0\n       : luaV_lessthan(L, o1, o2);\n  lua_unlock(L);\n  return i;\n}\n\n\n\nLUA_API lua_Number lua_tonumber (lua_State *L, int idx) {\n  TValue n;\n  const TValue *o = index2adr(L, idx);\n  if (tonumber(o, &n))\n    return nvalue(o);\n  else\n    return 0;\n}\n\n\nLUA_API lua_Integer lua_tointeger (lua_State *L, int idx) {\n  TValue n;\n  const TValue *o = index2adr(L, idx);\n  if (tonumber(o, &n)) {\n    lua_Integer res;\n    lua_Number num = nvalue(o);\n    lua_number2integer(res, num);\n    return res;\n  }\n  else\n    return 0;\n}\n\n\nLUA_API int lua_toboolean (lua_State *L, int idx) {\n  const TValue *o = index2adr(L, idx);\n  return !l_isfalse(o);\n}\n\n\nLUA_API const char *lua_tolstring (lua_State *L, int idx, size_t *len) {\n  StkId o = index2adr(L, idx);\n  if (!ttisstring(o)) {\n    lua_lock(L);  /* `luaV_tostring' may create a new string */\n    if (!luaV_tostring(L, o)) {  /* conversion failed? */\n      if (len != NULL) *len = 0;\n      lua_unlock(L);\n      return NULL;\n    }\n    luaC_checkGC(L);\n    o = index2adr(L, idx);  /* previous call may reallocate the stack */\n    lua_unlock(L);\n  }\n  if (len != NULL) *len = tsvalue(o)->len;\n  return svalue(o);\n}\n\n\nLUA_API size_t lua_objlen (lua_State *L, int idx) {\n  StkId o = index2adr(L, idx);\n  switch (ttype(o)) {\n    case LUA_TSTRING: return tsvalue(o)->len;\n    case LUA_TUSERDATA: return uvalue(o)->len;\n    case LUA_TTABLE: return luaH_getn(hvalue(o));\n    case LUA_TNUMBER: {\n      size_t l;\n      lua_lock(L);  /* `luaV_tostring' may create a new string */\n      l = (luaV_tostring(L, o) ? tsvalue(o)->len : 0);\n      lua_unlock(L);\n      return l;\n    }\n    default: return 0;\n  }\n}\n\n\nLUA_API lua_CFunction lua_tocfunction (lua_State *L, int idx) {\n  StkId o = index2adr(L, idx);\n  return (!iscfunction(o)) ? NULL : clvalue(o)->c.f;\n}\n\n\nLUA_API void *lua_touserdata (lua_State *L, int idx) {\n  StkId o = index2adr(L, idx);\n  switch (ttype(o)) {\n    case LUA_TUSERDATA: return (rawuvalue(o) + 1);\n    case LUA_TLIGHTUSERDATA: return pvalue(o);\n    default: return NULL;\n  }\n}\n\n\nLUA_API lua_State *lua_tothread (lua_State *L, int idx) {\n  StkId o = index2adr(L, idx);\n  return (!ttisthread(o)) ? NULL : thvalue(o);\n}\n\n\nLUA_API const void *lua_topointer (lua_State *L, int idx) {\n  StkId o = index2adr(L, idx);\n  switch (ttype(o)) {\n    case LUA_TTABLE: return hvalue(o);\n    case LUA_TFUNCTION: return clvalue(o);\n    case LUA_TTHREAD: return thvalue(o);\n    case LUA_TUSERDATA:\n    case LUA_TLIGHTUSERDATA:\n      return lua_touserdata(L, idx);\n    default: return NULL;\n  }\n}\n\n\n\n/*\n** push functions (C -> stack)\n*/\n\n\nLUA_API void lua_pushnil (lua_State *L) {\n  lua_lock(L);\n  setnilvalue(L->top);\n  api_incr_top(L);\n  lua_unlock(L);\n}\n\n\nLUA_API void lua_pushnumber (lua_State *L, lua_Number n) {\n  lua_lock(L);\n  setnvalue(L->top, n);\n  api_incr_top(L);\n  lua_unlock(L);\n}\n\n\nLUA_API void lua_pushinteger (lua_State *L, lua_Integer n) {\n  lua_lock(L);\n  setnvalue(L->top, cast_num(n));\n  api_incr_top(L);\n  lua_unlock(L);\n}\n\n\nLUA_API void lua_pushlstring (lua_State *L, const char *s, size_t len) {\n  lua_lock(L);\n  luaC_checkGC(L);\n  setsvalue2s(L, L->top, luaS_newlstr(L, s, len));\n  api_incr_top(L);\n  lua_unlock(L);\n}\n\n\nLUA_API void lua_pushstring (lua_State *L, const char *s) {\n  if (s == NULL)\n    lua_pushnil(L);\n  else\n    lua_pushlstring(L, s, strlen(s));\n}\n\n\nLUA_API const char *lua_pushvfstring (lua_State *L, const char *fmt,\n                                      va_list argp) {\n  const char *ret;\n  lua_lock(L);\n  luaC_checkGC(L);\n  ret = luaO_pushvfstring(L, fmt, argp);\n  lua_unlock(L);\n  return ret;\n}\n\n\nLUA_API const char *lua_pushfstring (lua_State *L, const char *fmt, ...) {\n  const char *ret;\n  va_list argp;\n  lua_lock(L);\n  luaC_checkGC(L);\n  va_start(argp, fmt);\n  ret = luaO_pushvfstring(L, fmt, argp);\n  va_end(argp);\n  lua_unlock(L);\n  return ret;\n}\n\n\nLUA_API void lua_pushcclosure (lua_State *L, lua_CFunction fn, int n) {\n  Closure *cl;\n  lua_lock(L);\n  luaC_checkGC(L);\n  api_checknelems(L, n);\n  cl = luaF_newCclosure(L, n, getcurrenv(L));\n  cl->c.f = fn;\n  L->top -= n;\n  while (n--)\n    setobj2n(L, &cl->c.upvalue[n], L->top+n);\n  setclvalue(L, L->top, cl);\n  lua_assert(iswhite(obj2gco(cl)));\n  api_incr_top(L);\n  lua_unlock(L);\n}\n\n\nLUA_API void lua_pushboolean (lua_State *L, int b) {\n  lua_lock(L);\n  setbvalue(L->top, (b != 0));  /* ensure that true is 1 */\n  api_incr_top(L);\n  lua_unlock(L);\n}\n\n\nLUA_API void lua_pushlightuserdata (lua_State *L, void *p) {\n  lua_lock(L);\n  setpvalue(L->top, p);\n  api_incr_top(L);\n  lua_unlock(L);\n}\n\n\nLUA_API int lua_pushthread (lua_State *L) {\n  lua_lock(L);\n  setthvalue(L, L->top, L);\n  api_incr_top(L);\n  lua_unlock(L);\n  return (G(L)->mainthread == L);\n}\n\n\n\n/*\n** get functions (Lua -> stack)\n*/\n\n\nLUA_API void lua_gettable (lua_State *L, int idx) {\n  StkId t;\n  lua_lock(L);\n  t = index2adr(L, idx);\n  api_checkvalidindex(L, t);\n  luaV_gettable(L, t, L->top - 1, L->top - 1);\n  lua_unlock(L);\n}\n\n\nLUA_API void lua_getfield (lua_State *L, int idx, const char *k) {\n  StkId t;\n  TValue key;\n  lua_lock(L);\n  t = index2adr(L, idx);\n  api_checkvalidindex(L, t);\n  setsvalue(L, &key, luaS_new(L, k));\n  luaV_gettable(L, t, &key, L->top);\n  api_incr_top(L);\n  lua_unlock(L);\n}\n\n\nLUA_API void lua_rawget (lua_State *L, int idx) {\n  StkId t;\n  lua_lock(L);\n  t = index2adr(L, idx);\n  api_check(L, ttistable(t));\n  setobj2s(L, L->top - 1, luaH_get(hvalue(t), L->top - 1));\n  lua_unlock(L);\n}\n\n\nLUA_API void lua_rawgeti (lua_State *L, int idx, int n) {\n  StkId o;\n  lua_lock(L);\n  o = index2adr(L, idx);\n  api_check(L, ttistable(o));\n  setobj2s(L, L->top, luaH_getnum(hvalue(o), n));\n  api_incr_top(L);\n  lua_unlock(L);\n}\n\n\nLUA_API void lua_createtable (lua_State *L, int narray, int nrec) {\n  lua_lock(L);\n  luaC_checkGC(L);\n  sethvalue(L, L->top, luaH_new(L, narray, nrec));\n  api_incr_top(L);\n  lua_unlock(L);\n}\n\n\nLUA_API int lua_getmetatable (lua_State *L, int objindex) {\n  const TValue *obj;\n  Table *mt = NULL;\n  int res;\n  lua_lock(L);\n  obj = index2adr(L, objindex);\n  switch (ttype(obj)) {\n    case LUA_TTABLE:\n      mt = hvalue(obj)->metatable;\n      break;\n    case LUA_TUSERDATA:\n      mt = uvalue(obj)->metatable;\n      break;\n    default:\n      mt = G(L)->mt[ttype(obj)];\n      break;\n  }\n  if (mt == NULL)\n    res = 0;\n  else {\n    sethvalue(L, L->top, mt);\n    api_incr_top(L);\n    res = 1;\n  }\n  lua_unlock(L);\n  return res;\n}\n\n\nLUA_API void lua_getfenv (lua_State *L, int idx) {\n  StkId o;\n  lua_lock(L);\n  o = index2adr(L, idx);\n  api_checkvalidindex(L, o);\n  switch (ttype(o)) {\n    case LUA_TFUNCTION:\n      sethvalue(L, L->top, clvalue(o)->c.env);\n      break;\n    case LUA_TUSERDATA:\n      sethvalue(L, L->top, uvalue(o)->env);\n      break;\n    case LUA_TTHREAD:\n      setobj2s(L, L->top,  gt(thvalue(o)));\n      break;\n    default:\n      setnilvalue(L->top);\n      break;\n  }\n  api_incr_top(L);\n  lua_unlock(L);\n}\n\n\n/*\n** set functions (stack -> Lua)\n*/\n\n\nLUA_API void lua_settable (lua_State *L, int idx) {\n  StkId t;\n  lua_lock(L);\n  api_checknelems(L, 2);\n  t = index2adr(L, idx);\n  api_checkvalidindex(L, t);\n  luaV_settable(L, t, L->top - 2, L->top - 1);\n  L->top -= 2;  /* pop index and value */\n  lua_unlock(L);\n}\n\n\nLUA_API void lua_setfield (lua_State *L, int idx, const char *k) {\n  StkId t;\n  TValue key;\n  lua_lock(L);\n  api_checknelems(L, 1);\n  t = index2adr(L, idx);\n  api_checkvalidindex(L, t);\n  setsvalue(L, &key, luaS_new(L, k));\n  luaV_settable(L, t, &key, L->top - 1);\n  L->top--;  /* pop value */\n  lua_unlock(L);\n}\n\n\nLUA_API void lua_rawset (lua_State *L, int idx) {\n  StkId t;\n  lua_lock(L);\n  api_checknelems(L, 2);\n  t = index2adr(L, idx);\n  api_check(L, ttistable(t));\n  setobj2t(L, luaH_set(L, hvalue(t), L->top-2), L->top-1);\n  luaC_barriert(L, hvalue(t), L->top-1);\n  L->top -= 2;\n  lua_unlock(L);\n}\n\n\nLUA_API void lua_rawseti (lua_State *L, int idx, int n) {\n  StkId o;\n  lua_lock(L);\n  api_checknelems(L, 1);\n  o = index2adr(L, idx);\n  api_check(L, ttistable(o));\n  setobj2t(L, luaH_setnum(L, hvalue(o), n), L->top-1);\n  luaC_barriert(L, hvalue(o), L->top-1);\n  L->top--;\n  lua_unlock(L);\n}\n\n\nLUA_API int lua_setmetatable (lua_State *L, int objindex) {\n  TValue *obj;\n  Table *mt;\n  lua_lock(L);\n  api_checknelems(L, 1);\n  obj = index2adr(L, objindex);\n  api_checkvalidindex(L, obj);\n  if (ttisnil(L->top - 1))\n    mt = NULL;\n  else {\n    api_check(L, ttistable(L->top - 1));\n    mt = hvalue(L->top - 1);\n  }\n  switch (ttype(obj)) {\n    case LUA_TTABLE: {\n      hvalue(obj)->metatable = mt;\n      if (mt)\n        luaC_objbarriert(L, hvalue(obj), mt);\n      break;\n    }\n    case LUA_TUSERDATA: {\n      uvalue(obj)->metatable = mt;\n      if (mt)\n        luaC_objbarrier(L, rawuvalue(obj), mt);\n      break;\n    }\n    default: {\n      G(L)->mt[ttype(obj)] = mt;\n      break;\n    }\n  }\n  L->top--;\n  lua_unlock(L);\n  return 1;\n}\n\n\nLUA_API int lua_setfenv (lua_State *L, int idx) {\n  StkId o;\n  int res = 1;\n  lua_lock(L);\n  api_checknelems(L, 1);\n  o = index2adr(L, idx);\n  api_checkvalidindex(L, o);\n  api_check(L, ttistable(L->top - 1));\n  switch (ttype(o)) {\n    case LUA_TFUNCTION:\n      clvalue(o)->c.env = hvalue(L->top - 1);\n      break;\n    case LUA_TUSERDATA:\n      uvalue(o)->env = hvalue(L->top - 1);\n      break;\n    case LUA_TTHREAD:\n      sethvalue(L, gt(thvalue(o)), hvalue(L->top - 1));\n      break;\n    default:\n      res = 0;\n      break;\n  }\n  if (res) luaC_objbarrier(L, gcvalue(o), hvalue(L->top - 1));\n  L->top--;\n  lua_unlock(L);\n  return res;\n}\n\n\n/*\n** `load' and `call' functions (run Lua code)\n*/\n\n\n#define adjustresults(L,nres) \\\n    { if (nres == LUA_MULTRET && L->top >= L->ci->top) L->ci->top = L->top; }\n\n\n#define checkresults(L,na,nr) \\\n     api_check(L, (nr) == LUA_MULTRET || (L->ci->top - L->top >= (nr) - (na)))\n\t\n\nLUA_API void lua_call (lua_State *L, int nargs, int nresults) {\n  StkId func;\n  lua_lock(L);\n  api_checknelems(L, nargs+1);\n  checkresults(L, nargs, nresults);\n  func = L->top - (nargs+1);\n  luaD_call(L, func, nresults);\n  adjustresults(L, nresults);\n  lua_unlock(L);\n}\n\n\n\n/*\n** Execute a protected call.\n*/\nstruct CallS {  /* data to `f_call' */\n  StkId func;\n  int nresults;\n};\n\n\nstatic void f_call (lua_State *L, void *ud) {\n  struct CallS *c = cast(struct CallS *, ud);\n  luaD_call(L, c->func, c->nresults);\n}\n\n\n\nLUA_API int lua_pcall (lua_State *L, int nargs, int nresults, int errfunc) {\n  struct CallS c;\n  int status;\n  ptrdiff_t func;\n  lua_lock(L);\n  api_checknelems(L, nargs+1);\n  checkresults(L, nargs, nresults);\n  if (errfunc == 0)\n    func = 0;\n  else {\n    StkId o = index2adr(L, errfunc);\n    api_checkvalidindex(L, o);\n    func = savestack(L, o);\n  }\n  c.func = L->top - (nargs+1);  /* function to be called */\n  c.nresults = nresults;\n  status = luaD_pcall(L, f_call, &c, savestack(L, c.func), func);\n  adjustresults(L, nresults);\n  lua_unlock(L);\n  return status;\n}\n\n\n/*\n** Execute a protected C call.\n*/\nstruct CCallS {  /* data to `f_Ccall' */\n  lua_CFunction func;\n  void *ud;\n};\n\n\nstatic void f_Ccall (lua_State *L, void *ud) {\n  struct CCallS *c = cast(struct CCallS *, ud);\n  Closure *cl;\n  cl = luaF_newCclosure(L, 0, getcurrenv(L));\n  cl->c.f = c->func;\n  setclvalue(L, L->top, cl);  /* push function */\n  api_incr_top(L);\n  setpvalue(L->top, c->ud);  /* push only argument */\n  api_incr_top(L);\n  luaD_call(L, L->top - 2, 0);\n}\n\n\nLUA_API int lua_cpcall (lua_State *L, lua_CFunction func, void *ud) {\n  struct CCallS c;\n  int status;\n  lua_lock(L);\n  c.func = func;\n  c.ud = ud;\n  status = luaD_pcall(L, f_Ccall, &c, savestack(L, L->top), 0);\n  lua_unlock(L);\n  return status;\n}\n\n\nLUA_API int lua_load (lua_State *L, lua_Reader reader, void *data,\n                      const char *chunkname) {\n  ZIO z;\n  int status;\n  lua_lock(L);\n  if (!chunkname) chunkname = \"?\";\n  luaZ_init(L, &z, reader, data);\n  status = luaD_protectedparser(L, &z, chunkname);\n  lua_unlock(L);\n  return status;\n}\n\n\nLUA_API int lua_dump (lua_State *L, lua_Writer writer, void *data) {\n  int status;\n  TValue *o;\n  lua_lock(L);\n  api_checknelems(L, 1);\n  o = L->top - 1;\n  if (isLfunction(o))\n    status = luaU_dump(L, clvalue(o)->l.p, writer, data, 0);\n  else\n    status = 1;\n  lua_unlock(L);\n  return status;\n}\n\n\nLUA_API int  lua_status (lua_State *L) {\n  return L->status;\n}\n\n\n/*\n** Garbage-collection function\n*/\n\nLUA_API int lua_gc (lua_State *L, int what, int data) {\n  int res = 0;\n  global_State *g;\n  lua_lock(L);\n  g = G(L);\n  switch (what) {\n    case LUA_GCSTOP: {\n      g->GCthreshold = MAX_LUMEM;\n      break;\n    }\n    case LUA_GCRESTART: {\n      g->GCthreshold = g->totalbytes;\n      break;\n    }\n    case LUA_GCCOLLECT: {\n      luaC_fullgc(L);\n      break;\n    }\n    case LUA_GCCOUNT: {\n      /* GC values are expressed in Kbytes: #bytes/2^10 */\n      res = cast_int(g->totalbytes >> 10);\n      break;\n    }\n    case LUA_GCCOUNTB: {\n      res = cast_int(g->totalbytes & 0x3ff);\n      break;\n    }\n    case LUA_GCSTEP: {\n      lu_mem a = (cast(lu_mem, data) << 10);\n      if (a <= g->totalbytes)\n        g->GCthreshold = g->totalbytes - a;\n      else\n        g->GCthreshold = 0;\n      while (g->GCthreshold <= g->totalbytes) {\n        luaC_step(L);\n        if (g->gcstate == GCSpause) {  /* end of cycle? */\n          res = 1;  /* signal it */\n          break;\n        }\n      }\n      break;\n    }\n    case LUA_GCSETPAUSE: {\n      res = g->gcpause;\n      g->gcpause = data;\n      break;\n    }\n    case LUA_GCSETSTEPMUL: {\n      res = g->gcstepmul;\n      g->gcstepmul = data;\n      break;\n    }\n    default: res = -1;  /* invalid option */\n  }\n  lua_unlock(L);\n  return res;\n}\n\n\n\n/*\n** miscellaneous functions\n*/\n\n\nLUA_API int lua_error (lua_State *L) {\n  lua_lock(L);\n  api_checknelems(L, 1);\n  luaG_errormsg(L);\n  lua_unlock(L);\n  return 0;  /* to avoid warnings */\n}\n\n\nLUA_API int lua_next (lua_State *L, int idx) {\n  StkId t;\n  int more;\n  lua_lock(L);\n  t = index2adr(L, idx);\n  api_check(L, ttistable(t));\n  more = luaH_next(L, hvalue(t), L->top - 1);\n  if (more) {\n    api_incr_top(L);\n  }\n  else  /* no more elements */\n    L->top -= 1;  /* remove key */\n  lua_unlock(L);\n  return more;\n}\n\n\nLUA_API void lua_concat (lua_State *L, int n) {\n  lua_lock(L);\n  api_checknelems(L, n);\n  if (n >= 2) {\n    luaC_checkGC(L);\n    luaV_concat(L, n, cast_int(L->top - L->base) - 1);\n    L->top -= (n-1);\n  }\n  else if (n == 0) {  /* push empty string */\n    setsvalue2s(L, L->top, luaS_newlstr(L, \"\", 0));\n    api_incr_top(L);\n  }\n  /* else n == 1; nothing to do */\n  lua_unlock(L);\n}\n\n\nLUA_API lua_Alloc lua_getallocf (lua_State *L, void **ud) {\n  lua_Alloc f;\n  lua_lock(L);\n  if (ud) *ud = G(L)->ud;\n  f = G(L)->frealloc;\n  lua_unlock(L);\n  return f;\n}\n\n\nLUA_API void lua_setallocf (lua_State *L, lua_Alloc f, void *ud) {\n  lua_lock(L);\n  G(L)->ud = ud;\n  G(L)->frealloc = f;\n  lua_unlock(L);\n}\n\n\nLUA_API void *lua_newuserdata (lua_State *L, size_t size) {\n  Udata *u;\n  lua_lock(L);\n  luaC_checkGC(L);\n  u = luaS_newudata(L, size, getcurrenv(L));\n  setuvalue(L, L->top, u);\n  api_incr_top(L);\n  lua_unlock(L);\n  return u + 1;\n}\n\n\n\n\nstatic const char *aux_upvalue (StkId fi, int n, TValue **val) {\n  Closure *f;\n  if (!ttisfunction(fi)) return NULL;\n  f = clvalue(fi);\n  if (f->c.isC) {\n    if (!(1 <= n && n <= f->c.nupvalues)) return NULL;\n    *val = &f->c.upvalue[n-1];\n    return \"\";\n  }\n  else {\n    Proto *p = f->l.p;\n    if (!(1 <= n && n <= p->sizeupvalues)) return NULL;\n    *val = f->l.upvals[n-1]->v;\n    return getstr(p->upvalues[n-1]);\n  }\n}\n\n\nLUA_API const char *lua_getupvalue (lua_State *L, int funcindex, int n) {\n  const char *name;\n  TValue *val;\n  lua_lock(L);\n  name = aux_upvalue(index2adr(L, funcindex), n, &val);\n  if (name) {\n    setobj2s(L, L->top, val);\n    api_incr_top(L);\n  }\n  lua_unlock(L);\n  return name;\n}\n\n\nLUA_API const char *lua_setupvalue (lua_State *L, int funcindex, int n) {\n  const char *name;\n  TValue *val;\n  StkId fi;\n  lua_lock(L);\n  fi = index2adr(L, funcindex);\n  api_checknelems(L, 1);\n  name = aux_upvalue(fi, n, &val);\n  if (name) {\n    L->top--;\n    setobj(L, val, L->top);\n    luaC_barrier(L, clvalue(fi), L->top);\n  }\n  lua_unlock(L);\n  return name;\n}\n\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.8/deps/lua/src/lapi.h",
    "content": "/*\n** $Id: lapi.h,v 2.2.1.1 2007/12/27 13:02:25 roberto Exp $\n** Auxiliary functions from Lua API\n** See Copyright Notice in lua.h\n*/\n\n#ifndef lapi_h\n#define lapi_h\n\n\n#include \"lobject.h\"\n\n\nLUAI_FUNC void luaA_pushobject (lua_State *L, const TValue *o);\n\n#endif\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.8/deps/lua/src/lauxlib.c",
    "content": "/*\n** $Id: lauxlib.c,v 1.159.1.3 2008/01/21 13:20:51 roberto Exp $\n** Auxiliary functions for building Lua libraries\n** See Copyright Notice in lua.h\n*/\n\n\n#include <ctype.h>\n#include <errno.h>\n#include <stdarg.h>\n#include <stdio.h>\n#include <stdlib.h>\n#include <string.h>\n\n\n/* This file uses only the official API of Lua.\n** Any function declared here could be written as an application function.\n*/\n\n#define lauxlib_c\n#define LUA_LIB\n\n#include \"lua.h\"\n\n#include \"lauxlib.h\"\n\n\n#define FREELIST_REF\t0\t/* free list of references */\n\n\n/* convert a stack index to positive */\n#define abs_index(L, i)\t\t((i) > 0 || (i) <= LUA_REGISTRYINDEX ? (i) : \\\n\t\t\t\t\tlua_gettop(L) + (i) + 1)\n\n\n/*\n** {======================================================\n** Error-report functions\n** =======================================================\n*/\n\n\nLUALIB_API int luaL_argerror (lua_State *L, int narg, const char *extramsg) {\n  lua_Debug ar;\n  if (!lua_getstack(L, 0, &ar))  /* no stack frame? */\n    return luaL_error(L, \"bad argument #%d (%s)\", narg, extramsg);\n  lua_getinfo(L, \"n\", &ar);\n  if (strcmp(ar.namewhat, \"method\") == 0) {\n    narg--;  /* do not count `self' */\n    if (narg == 0)  /* error is in the self argument itself? */\n      return luaL_error(L, \"calling \" LUA_QS \" on bad self (%s)\",\n                           ar.name, extramsg);\n  }\n  if (ar.name == NULL)\n    ar.name = \"?\";\n  return luaL_error(L, \"bad argument #%d to \" LUA_QS \" (%s)\",\n                        narg, ar.name, extramsg);\n}\n\n\nLUALIB_API int luaL_typerror (lua_State *L, int narg, const char *tname) {\n  const char *msg = lua_pushfstring(L, \"%s expected, got %s\",\n                                    tname, luaL_typename(L, narg));\n  return luaL_argerror(L, narg, msg);\n}\n\n\nstatic void tag_error (lua_State *L, int narg, int tag) {\n  luaL_typerror(L, narg, lua_typename(L, tag));\n}\n\n\nLUALIB_API void luaL_where (lua_State *L, int level) {\n  lua_Debug ar;\n  if (lua_getstack(L, level, &ar)) {  /* check function at level */\n    lua_getinfo(L, \"Sl\", &ar);  /* get info about it */\n    if (ar.currentline > 0) {  /* is there info? */\n      lua_pushfstring(L, \"%s:%d: \", ar.short_src, ar.currentline);\n      return;\n    }\n  }\n  lua_pushliteral(L, \"\");  /* else, no information available... */\n}\n\n\nLUALIB_API int luaL_error (lua_State *L, const char *fmt, ...) {\n  va_list argp;\n  va_start(argp, fmt);\n  luaL_where(L, 1);\n  lua_pushvfstring(L, fmt, argp);\n  va_end(argp);\n  lua_concat(L, 2);\n  return lua_error(L);\n}\n\n/* }====================================================== */\n\n\nLUALIB_API int luaL_checkoption (lua_State *L, int narg, const char *def,\n                                 const char *const lst[]) {\n  const char *name = (def) ? luaL_optstring(L, narg, def) :\n                             luaL_checkstring(L, narg);\n  int i;\n  for (i=0; lst[i]; i++)\n    if (strcmp(lst[i], name) == 0)\n      return i;\n  return luaL_argerror(L, narg,\n                       lua_pushfstring(L, \"invalid option \" LUA_QS, name));\n}\n\n\nLUALIB_API int luaL_newmetatable (lua_State *L, const char *tname) {\n  lua_getfield(L, LUA_REGISTRYINDEX, tname);  /* get registry.name */\n  if (!lua_isnil(L, -1))  /* name already in use? */\n    return 0;  /* leave previous value on top, but return 0 */\n  lua_pop(L, 1);\n  lua_newtable(L);  /* create metatable */\n  lua_pushvalue(L, -1);\n  lua_setfield(L, LUA_REGISTRYINDEX, tname);  /* registry.name = metatable */\n  return 1;\n}\n\n\nLUALIB_API void *luaL_checkudata (lua_State *L, int ud, const char *tname) {\n  void *p = lua_touserdata(L, ud);\n  if (p != NULL) {  /* value is a userdata? */\n    if (lua_getmetatable(L, ud)) {  /* does it have a metatable? */\n      lua_getfield(L, LUA_REGISTRYINDEX, tname);  /* get correct metatable */\n      if (lua_rawequal(L, -1, -2)) {  /* does it have the correct mt? */\n        lua_pop(L, 2);  /* remove both metatables */\n        return p;\n      }\n    }\n  }\n  luaL_typerror(L, ud, tname);  /* else error */\n  return NULL;  /* to avoid warnings */\n}\n\n\nLUALIB_API void luaL_checkstack (lua_State *L, int space, const char *mes) {\n  if (!lua_checkstack(L, space))\n    luaL_error(L, \"stack overflow (%s)\", mes);\n}\n\n\nLUALIB_API void luaL_checktype (lua_State *L, int narg, int t) {\n  if (lua_type(L, narg) != t)\n    tag_error(L, narg, t);\n}\n\n\nLUALIB_API void luaL_checkany (lua_State *L, int narg) {\n  if (lua_type(L, narg) == LUA_TNONE)\n    luaL_argerror(L, narg, \"value expected\");\n}\n\n\nLUALIB_API const char *luaL_checklstring (lua_State *L, int narg, size_t *len) {\n  const char *s = lua_tolstring(L, narg, len);\n  if (!s) tag_error(L, narg, LUA_TSTRING);\n  return s;\n}\n\n\nLUALIB_API const char *luaL_optlstring (lua_State *L, int narg,\n                                        const char *def, size_t *len) {\n  if (lua_isnoneornil(L, narg)) {\n    if (len)\n      *len = (def ? strlen(def) : 0);\n    return def;\n  }\n  else return luaL_checklstring(L, narg, len);\n}\n\n\nLUALIB_API lua_Number luaL_checknumber (lua_State *L, int narg) {\n  lua_Number d = lua_tonumber(L, narg);\n  if (d == 0 && !lua_isnumber(L, narg))  /* avoid extra test when d is not 0 */\n    tag_error(L, narg, LUA_TNUMBER);\n  return d;\n}\n\n\nLUALIB_API lua_Number luaL_optnumber (lua_State *L, int narg, lua_Number def) {\n  return luaL_opt(L, luaL_checknumber, narg, def);\n}\n\n\nLUALIB_API lua_Integer luaL_checkinteger (lua_State *L, int narg) {\n  lua_Integer d = lua_tointeger(L, narg);\n  if (d == 0 && !lua_isnumber(L, narg))  /* avoid extra test when d is not 0 */\n    tag_error(L, narg, LUA_TNUMBER);\n  return d;\n}\n\n\nLUALIB_API lua_Integer luaL_optinteger (lua_State *L, int narg,\n                                                      lua_Integer def) {\n  return luaL_opt(L, luaL_checkinteger, narg, def);\n}\n\n\nLUALIB_API int luaL_getmetafield (lua_State *L, int obj, const char *event) {\n  if (!lua_getmetatable(L, obj))  /* no metatable? */\n    return 0;\n  lua_pushstring(L, event);\n  lua_rawget(L, -2);\n  if (lua_isnil(L, -1)) {\n    lua_pop(L, 2);  /* remove metatable and metafield */\n    return 0;\n  }\n  else {\n    lua_remove(L, -2);  /* remove only metatable */\n    return 1;\n  }\n}\n\n\nLUALIB_API int luaL_callmeta (lua_State *L, int obj, const char *event) {\n  obj = abs_index(L, obj);\n  if (!luaL_getmetafield(L, obj, event))  /* no metafield? */\n    return 0;\n  lua_pushvalue(L, obj);\n  lua_call(L, 1, 1);\n  return 1;\n}\n\n\nLUALIB_API void (luaL_register) (lua_State *L, const char *libname,\n                                const luaL_Reg *l) {\n  luaI_openlib(L, libname, l, 0);\n}\n\n\nstatic int libsize (const luaL_Reg *l) {\n  int size = 0;\n  for (; l->name; l++) size++;\n  return size;\n}\n\n\nLUALIB_API void luaI_openlib (lua_State *L, const char *libname,\n                              const luaL_Reg *l, int nup) {\n  if (libname) {\n    int size = libsize(l);\n    /* check whether lib already exists */\n    luaL_findtable(L, LUA_REGISTRYINDEX, \"_LOADED\", 1);\n    lua_getfield(L, -1, libname);  /* get _LOADED[libname] */\n    if (!lua_istable(L, -1)) {  /* not found? */\n      lua_pop(L, 1);  /* remove previous result */\n      /* try global variable (and create one if it does not exist) */\n      if (luaL_findtable(L, LUA_GLOBALSINDEX, libname, size) != NULL)\n        luaL_error(L, \"name conflict for module \" LUA_QS, libname);\n      lua_pushvalue(L, -1);\n      lua_setfield(L, -3, libname);  /* _LOADED[libname] = new table */\n    }\n    lua_remove(L, -2);  /* remove _LOADED table */\n    lua_insert(L, -(nup+1));  /* move library table to below upvalues */\n  }\n  for (; l->name; l++) {\n    int i;\n    for (i=0; i<nup; i++)  /* copy upvalues to the top */\n      lua_pushvalue(L, -nup);\n    lua_pushcclosure(L, l->func, nup);\n    lua_setfield(L, -(nup+2), l->name);\n  }\n  lua_pop(L, nup);  /* remove upvalues */\n}\n\n\n\n/*\n** {======================================================\n** getn-setn: size for arrays\n** =======================================================\n*/\n\n#if defined(LUA_COMPAT_GETN)\n\nstatic int checkint (lua_State *L, int topop) {\n  int n = (lua_type(L, -1) == LUA_TNUMBER) ? lua_tointeger(L, -1) : -1;\n  lua_pop(L, topop);\n  return n;\n}\n\n\nstatic void getsizes (lua_State *L) {\n  lua_getfield(L, LUA_REGISTRYINDEX, \"LUA_SIZES\");\n  if (lua_isnil(L, -1)) {  /* no `size' table? */\n    lua_pop(L, 1);  /* remove nil */\n    lua_newtable(L);  /* create it */\n    lua_pushvalue(L, -1);  /* `size' will be its own metatable */\n    lua_setmetatable(L, -2);\n    lua_pushliteral(L, \"kv\");\n    lua_setfield(L, -2, \"__mode\");  /* metatable(N).__mode = \"kv\" */\n    lua_pushvalue(L, -1);\n    lua_setfield(L, LUA_REGISTRYINDEX, \"LUA_SIZES\");  /* store in register */\n  }\n}\n\n\nLUALIB_API void luaL_setn (lua_State *L, int t, int n) {\n  t = abs_index(L, t);\n  lua_pushliteral(L, \"n\");\n  lua_rawget(L, t);\n  if (checkint(L, 1) >= 0) {  /* is there a numeric field `n'? */\n    lua_pushliteral(L, \"n\");  /* use it */\n    lua_pushinteger(L, n);\n    lua_rawset(L, t);\n  }\n  else {  /* use `sizes' */\n    getsizes(L);\n    lua_pushvalue(L, t);\n    lua_pushinteger(L, n);\n    lua_rawset(L, -3);  /* sizes[t] = n */\n    lua_pop(L, 1);  /* remove `sizes' */\n  }\n}\n\n\nLUALIB_API int luaL_getn (lua_State *L, int t) {\n  int n;\n  t = abs_index(L, t);\n  lua_pushliteral(L, \"n\");  /* try t.n */\n  lua_rawget(L, t);\n  if ((n = checkint(L, 1)) >= 0) return n;\n  getsizes(L);  /* else try sizes[t] */\n  lua_pushvalue(L, t);\n  lua_rawget(L, -2);\n  if ((n = checkint(L, 2)) >= 0) return n;\n  return (int)lua_objlen(L, t);\n}\n\n#endif\n\n/* }====================================================== */\n\n\n\nLUALIB_API const char *luaL_gsub (lua_State *L, const char *s, const char *p,\n                                                               const char *r) {\n  const char *wild;\n  size_t l = strlen(p);\n  luaL_Buffer b;\n  luaL_buffinit(L, &b);\n  while ((wild = strstr(s, p)) != NULL) {\n    luaL_addlstring(&b, s, wild - s);  /* push prefix */\n    luaL_addstring(&b, r);  /* push replacement in place of pattern */\n    s = wild + l;  /* continue after `p' */\n  }\n  luaL_addstring(&b, s);  /* push last suffix */\n  luaL_pushresult(&b);\n  return lua_tostring(L, -1);\n}\n\n\nLUALIB_API const char *luaL_findtable (lua_State *L, int idx,\n                                       const char *fname, int szhint) {\n  const char *e;\n  lua_pushvalue(L, idx);\n  do {\n    e = strchr(fname, '.');\n    if (e == NULL) e = fname + strlen(fname);\n    lua_pushlstring(L, fname, e - fname);\n    lua_rawget(L, -2);\n    if (lua_isnil(L, -1)) {  /* no such field? */\n      lua_pop(L, 1);  /* remove this nil */\n      lua_createtable(L, 0, (*e == '.' ? 1 : szhint)); /* new table for field */\n      lua_pushlstring(L, fname, e - fname);\n      lua_pushvalue(L, -2);\n      lua_settable(L, -4);  /* set new table into field */\n    }\n    else if (!lua_istable(L, -1)) {  /* field has a non-table value? */\n      lua_pop(L, 2);  /* remove table and value */\n      return fname;  /* return problematic part of the name */\n    }\n    lua_remove(L, -2);  /* remove previous table */\n    fname = e + 1;\n  } while (*e == '.');\n  return NULL;\n}\n\n\n\n/*\n** {======================================================\n** Generic Buffer manipulation\n** =======================================================\n*/\n\n\n#define bufflen(B)\t((B)->p - (B)->buffer)\n#define bufffree(B)\t((size_t)(LUAL_BUFFERSIZE - bufflen(B)))\n\n#define LIMIT\t(LUA_MINSTACK/2)\n\n\nstatic int emptybuffer (luaL_Buffer *B) {\n  size_t l = bufflen(B);\n  if (l == 0) return 0;  /* put nothing on stack */\n  else {\n    lua_pushlstring(B->L, B->buffer, l);\n    B->p = B->buffer;\n    B->lvl++;\n    return 1;\n  }\n}\n\n\nstatic void adjuststack (luaL_Buffer *B) {\n  if (B->lvl > 1) {\n    lua_State *L = B->L;\n    int toget = 1;  /* number of levels to concat */\n    size_t toplen = lua_strlen(L, -1);\n    do {\n      size_t l = lua_strlen(L, -(toget+1));\n      if (B->lvl - toget + 1 >= LIMIT || toplen > l) {\n        toplen += l;\n        toget++;\n      }\n      else break;\n    } while (toget < B->lvl);\n    lua_concat(L, toget);\n    B->lvl = B->lvl - toget + 1;\n  }\n}\n\n\nLUALIB_API char *luaL_prepbuffer (luaL_Buffer *B) {\n  if (emptybuffer(B))\n    adjuststack(B);\n  return B->buffer;\n}\n\n\nLUALIB_API void luaL_addlstring (luaL_Buffer *B, const char *s, size_t l) {\n  while (l--)\n    luaL_addchar(B, *s++);\n}\n\n\nLUALIB_API void luaL_addstring (luaL_Buffer *B, const char *s) {\n  luaL_addlstring(B, s, strlen(s));\n}\n\n\nLUALIB_API void luaL_pushresult (luaL_Buffer *B) {\n  emptybuffer(B);\n  lua_concat(B->L, B->lvl);\n  B->lvl = 1;\n}\n\n\nLUALIB_API void luaL_addvalue (luaL_Buffer *B) {\n  lua_State *L = B->L;\n  size_t vl;\n  const char *s = lua_tolstring(L, -1, &vl);\n  if (vl <= bufffree(B)) {  /* fit into buffer? */\n    memcpy(B->p, s, vl);  /* put it there */\n    B->p += vl;\n    lua_pop(L, 1);  /* remove from stack */\n  }\n  else {\n    if (emptybuffer(B))\n      lua_insert(L, -2);  /* put buffer before new value */\n    B->lvl++;  /* add new value into B stack */\n    adjuststack(B);\n  }\n}\n\n\nLUALIB_API void luaL_buffinit (lua_State *L, luaL_Buffer *B) {\n  B->L = L;\n  B->p = B->buffer;\n  B->lvl = 0;\n}\n\n/* }====================================================== */\n\n\nLUALIB_API int luaL_ref (lua_State *L, int t) {\n  int ref;\n  t = abs_index(L, t);\n  if (lua_isnil(L, -1)) {\n    lua_pop(L, 1);  /* remove from stack */\n    return LUA_REFNIL;  /* `nil' has a unique fixed reference */\n  }\n  lua_rawgeti(L, t, FREELIST_REF);  /* get first free element */\n  ref = (int)lua_tointeger(L, -1);  /* ref = t[FREELIST_REF] */\n  lua_pop(L, 1);  /* remove it from stack */\n  if (ref != 0) {  /* any free element? */\n    lua_rawgeti(L, t, ref);  /* remove it from list */\n    lua_rawseti(L, t, FREELIST_REF);  /* (t[FREELIST_REF] = t[ref]) */\n  }\n  else {  /* no free elements */\n    ref = (int)lua_objlen(L, t);\n    ref++;  /* create new reference */\n  }\n  lua_rawseti(L, t, ref);\n  return ref;\n}\n\n\nLUALIB_API void luaL_unref (lua_State *L, int t, int ref) {\n  if (ref >= 0) {\n    t = abs_index(L, t);\n    lua_rawgeti(L, t, FREELIST_REF);\n    lua_rawseti(L, t, ref);  /* t[ref] = t[FREELIST_REF] */\n    lua_pushinteger(L, ref);\n    lua_rawseti(L, t, FREELIST_REF);  /* t[FREELIST_REF] = ref */\n  }\n}\n\n\n\n/*\n** {======================================================\n** Load functions\n** =======================================================\n*/\n\ntypedef struct LoadF {\n  int extraline;\n  FILE *f;\n  char buff[LUAL_BUFFERSIZE];\n} LoadF;\n\n\nstatic const char *getF (lua_State *L, void *ud, size_t *size) {\n  LoadF *lf = (LoadF *)ud;\n  (void)L;\n  if (lf->extraline) {\n    lf->extraline = 0;\n    *size = 1;\n    return \"\\n\";\n  }\n  if (feof(lf->f)) return NULL;\n  *size = fread(lf->buff, 1, sizeof(lf->buff), lf->f);\n  return (*size > 0) ? lf->buff : NULL;\n}\n\n\nstatic int errfile (lua_State *L, const char *what, int fnameindex) {\n  const char *serr = strerror(errno);\n  const char *filename = lua_tostring(L, fnameindex) + 1;\n  lua_pushfstring(L, \"cannot %s %s: %s\", what, filename, serr);\n  lua_remove(L, fnameindex);\n  return LUA_ERRFILE;\n}\n\n\nLUALIB_API int luaL_loadfile (lua_State *L, const char *filename) {\n  LoadF lf;\n  int status, readstatus;\n  int c;\n  int fnameindex = lua_gettop(L) + 1;  /* index of filename on the stack */\n  lf.extraline = 0;\n  if (filename == NULL) {\n    lua_pushliteral(L, \"=stdin\");\n    lf.f = stdin;\n  }\n  else {\n    lua_pushfstring(L, \"@%s\", filename);\n    lf.f = fopen(filename, \"r\");\n    if (lf.f == NULL) return errfile(L, \"open\", fnameindex);\n  }\n  c = getc(lf.f);\n  if (c == '#') {  /* Unix exec. file? */\n    lf.extraline = 1;\n    while ((c = getc(lf.f)) != EOF && c != '\\n') ;  /* skip first line */\n    if (c == '\\n') c = getc(lf.f);\n  }\n  if (c == LUA_SIGNATURE[0] && filename) {  /* binary file? */\n    lf.f = freopen(filename, \"rb\", lf.f);  /* reopen in binary mode */\n    if (lf.f == NULL) return errfile(L, \"reopen\", fnameindex);\n    /* skip eventual `#!...' */\n   while ((c = getc(lf.f)) != EOF && c != LUA_SIGNATURE[0]) ;\n    lf.extraline = 0;\n  }\n  ungetc(c, lf.f);\n  status = lua_load(L, getF, &lf, lua_tostring(L, -1));\n  readstatus = ferror(lf.f);\n  if (filename) fclose(lf.f);  /* close file (even in case of errors) */\n  if (readstatus) {\n    lua_settop(L, fnameindex);  /* ignore results from `lua_load' */\n    return errfile(L, \"read\", fnameindex);\n  }\n  lua_remove(L, fnameindex);\n  return status;\n}\n\n\ntypedef struct LoadS {\n  const char *s;\n  size_t size;\n} LoadS;\n\n\nstatic const char *getS (lua_State *L, void *ud, size_t *size) {\n  LoadS *ls = (LoadS *)ud;\n  (void)L;\n  if (ls->size == 0) return NULL;\n  *size = ls->size;\n  ls->size = 0;\n  return ls->s;\n}\n\n\nLUALIB_API int luaL_loadbuffer (lua_State *L, const char *buff, size_t size,\n                                const char *name) {\n  LoadS ls;\n  ls.s = buff;\n  ls.size = size;\n  return lua_load(L, getS, &ls, name);\n}\n\n\nLUALIB_API int (luaL_loadstring) (lua_State *L, const char *s) {\n  return luaL_loadbuffer(L, s, strlen(s), s);\n}\n\n\n\n/* }====================================================== */\n\n\nstatic void *l_alloc (void *ud, void *ptr, size_t osize, size_t nsize) {\n  (void)ud;\n  (void)osize;\n  if (nsize == 0) {\n    free(ptr);\n    return NULL;\n  }\n  else\n    return realloc(ptr, nsize);\n}\n\n\nstatic int panic (lua_State *L) {\n  (void)L;  /* to avoid warnings */\n  fprintf(stderr, \"PANIC: unprotected error in call to Lua API (%s)\\n\",\n                   lua_tostring(L, -1));\n  return 0;\n}\n\n\nLUALIB_API lua_State *luaL_newstate (void) {\n  lua_State *L = lua_newstate(l_alloc, NULL);\n  if (L) lua_atpanic(L, &panic);\n  return L;\n}\n\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.8/deps/lua/src/lauxlib.h",
    "content": "/*\n** $Id: lauxlib.h,v 1.88.1.1 2007/12/27 13:02:25 roberto Exp $\n** Auxiliary functions for building Lua libraries\n** See Copyright Notice in lua.h\n*/\n\n\n#ifndef lauxlib_h\n#define lauxlib_h\n\n\n#include <stddef.h>\n#include <stdio.h>\n\n#include \"lua.h\"\n\n\n#if defined(LUA_COMPAT_GETN)\nLUALIB_API int (luaL_getn) (lua_State *L, int t);\nLUALIB_API void (luaL_setn) (lua_State *L, int t, int n);\n#else\n#define luaL_getn(L,i)          ((int)lua_objlen(L, i))\n#define luaL_setn(L,i,j)        ((void)0)  /* no op! */\n#endif\n\n#if defined(LUA_COMPAT_OPENLIB)\n#define luaI_openlib\tluaL_openlib\n#endif\n\n\n/* extra error code for `luaL_load' */\n#define LUA_ERRFILE     (LUA_ERRERR+1)\n\n\ntypedef struct luaL_Reg {\n  const char *name;\n  lua_CFunction func;\n} luaL_Reg;\n\n\n\nLUALIB_API void (luaI_openlib) (lua_State *L, const char *libname,\n                                const luaL_Reg *l, int nup);\nLUALIB_API void (luaL_register) (lua_State *L, const char *libname,\n                                const luaL_Reg *l);\nLUALIB_API int (luaL_getmetafield) (lua_State *L, int obj, const char *e);\nLUALIB_API int (luaL_callmeta) (lua_State *L, int obj, const char *e);\nLUALIB_API int (luaL_typerror) (lua_State *L, int narg, const char *tname);\nLUALIB_API int (luaL_argerror) (lua_State *L, int numarg, const char *extramsg);\nLUALIB_API const char *(luaL_checklstring) (lua_State *L, int numArg,\n                                                          size_t *l);\nLUALIB_API const char *(luaL_optlstring) (lua_State *L, int numArg,\n                                          const char *def, size_t *l);\nLUALIB_API lua_Number (luaL_checknumber) (lua_State *L, int numArg);\nLUALIB_API lua_Number (luaL_optnumber) (lua_State *L, int nArg, lua_Number def);\n\nLUALIB_API lua_Integer (luaL_checkinteger) (lua_State *L, int numArg);\nLUALIB_API lua_Integer (luaL_optinteger) (lua_State *L, int nArg,\n                                          lua_Integer def);\n\nLUALIB_API void (luaL_checkstack) (lua_State *L, int sz, const char *msg);\nLUALIB_API void (luaL_checktype) (lua_State *L, int narg, int t);\nLUALIB_API void (luaL_checkany) (lua_State *L, int narg);\n\nLUALIB_API int   (luaL_newmetatable) (lua_State *L, const char *tname);\nLUALIB_API void *(luaL_checkudata) (lua_State *L, int ud, const char *tname);\n\nLUALIB_API void (luaL_where) (lua_State *L, int lvl);\nLUALIB_API int (luaL_error) (lua_State *L, const char *fmt, ...);\n\nLUALIB_API int (luaL_checkoption) (lua_State *L, int narg, const char *def,\n                                   const char *const lst[]);\n\nLUALIB_API int (luaL_ref) (lua_State *L, int t);\nLUALIB_API void (luaL_unref) (lua_State *L, int t, int ref);\n\nLUALIB_API int (luaL_loadfile) (lua_State *L, const char *filename);\nLUALIB_API int (luaL_loadbuffer) (lua_State *L, const char *buff, size_t sz,\n                                  const char *name);\nLUALIB_API int (luaL_loadstring) (lua_State *L, const char *s);\n\nLUALIB_API lua_State *(luaL_newstate) (void);\n\n\nLUALIB_API const char *(luaL_gsub) (lua_State *L, const char *s, const char *p,\n                                                  const char *r);\n\nLUALIB_API const char *(luaL_findtable) (lua_State *L, int idx,\n                                         const char *fname, int szhint);\n\n\n\n\n/*\n** ===============================================================\n** some useful macros\n** ===============================================================\n*/\n\n#define luaL_argcheck(L, cond,numarg,extramsg)\t\\\n\t\t((void)((cond) || luaL_argerror(L, (numarg), (extramsg))))\n#define luaL_checkstring(L,n)\t(luaL_checklstring(L, (n), NULL))\n#define luaL_optstring(L,n,d)\t(luaL_optlstring(L, (n), (d), NULL))\n#define luaL_checkint(L,n)\t((int)luaL_checkinteger(L, (n)))\n#define luaL_optint(L,n,d)\t((int)luaL_optinteger(L, (n), (d)))\n#define luaL_checklong(L,n)\t((long)luaL_checkinteger(L, (n)))\n#define luaL_optlong(L,n,d)\t((long)luaL_optinteger(L, (n), (d)))\n\n#define luaL_typename(L,i)\tlua_typename(L, lua_type(L,(i)))\n\n#define luaL_dofile(L, fn) \\\n\t(luaL_loadfile(L, fn) || lua_pcall(L, 0, LUA_MULTRET, 0))\n\n#define luaL_dostring(L, s) \\\n\t(luaL_loadstring(L, s) || lua_pcall(L, 0, LUA_MULTRET, 0))\n\n#define luaL_getmetatable(L,n)\t(lua_getfield(L, LUA_REGISTRYINDEX, (n)))\n\n#define luaL_opt(L,f,n,d)\t(lua_isnoneornil(L,(n)) ? (d) : f(L,(n)))\n\n/*\n** {======================================================\n** Generic Buffer manipulation\n** =======================================================\n*/\n\n\n\ntypedef struct luaL_Buffer {\n  char *p;\t\t\t/* current position in buffer */\n  int lvl;  /* number of strings in the stack (level) */\n  lua_State *L;\n  char buffer[LUAL_BUFFERSIZE];\n} luaL_Buffer;\n\n#define luaL_addchar(B,c) \\\n  ((void)((B)->p < ((B)->buffer+LUAL_BUFFERSIZE) || luaL_prepbuffer(B)), \\\n   (*(B)->p++ = (char)(c)))\n\n/* compatibility only */\n#define luaL_putchar(B,c)\tluaL_addchar(B,c)\n\n#define luaL_addsize(B,n)\t((B)->p += (n))\n\nLUALIB_API void (luaL_buffinit) (lua_State *L, luaL_Buffer *B);\nLUALIB_API char *(luaL_prepbuffer) (luaL_Buffer *B);\nLUALIB_API void (luaL_addlstring) (luaL_Buffer *B, const char *s, size_t l);\nLUALIB_API void (luaL_addstring) (luaL_Buffer *B, const char *s);\nLUALIB_API void (luaL_addvalue) (luaL_Buffer *B);\nLUALIB_API void (luaL_pushresult) (luaL_Buffer *B);\n\n\n/* }====================================================== */\n\n\n/* compatibility with ref system */\n\n/* pre-defined references */\n#define LUA_NOREF       (-2)\n#define LUA_REFNIL      (-1)\n\n#define lua_ref(L,lock) ((lock) ? luaL_ref(L, LUA_REGISTRYINDEX) : \\\n      (lua_pushstring(L, \"unlocked references are obsolete\"), lua_error(L), 0))\n\n#define lua_unref(L,ref)        luaL_unref(L, LUA_REGISTRYINDEX, (ref))\n\n#define lua_getref(L,ref)       lua_rawgeti(L, LUA_REGISTRYINDEX, (ref))\n\n\n#define luaL_reg\tluaL_Reg\n\n#endif\n\n\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.8/deps/lua/src/lbaselib.c",
    "content": "/*\n** $Id: lbaselib.c,v 1.191.1.6 2008/02/14 16:46:22 roberto Exp $\n** Basic library\n** See Copyright Notice in lua.h\n*/\n\n\n\n#include <ctype.h>\n#include <stdio.h>\n#include <stdlib.h>\n#include <string.h>\n\n#define lbaselib_c\n#define LUA_LIB\n\n#include \"lua.h\"\n\n#include \"lauxlib.h\"\n#include \"lualib.h\"\n\n\n\n\n/*\n** If your system does not support `stdout', you can just remove this function.\n** If you need, you can define your own `print' function, following this\n** model but changing `fputs' to put the strings at a proper place\n** (a console window or a log file, for instance).\n*/\nstatic int luaB_print (lua_State *L) {\n  int n = lua_gettop(L);  /* number of arguments */\n  int i;\n  lua_getglobal(L, \"tostring\");\n  for (i=1; i<=n; i++) {\n    const char *s;\n    lua_pushvalue(L, -1);  /* function to be called */\n    lua_pushvalue(L, i);   /* value to print */\n    lua_call(L, 1, 1);\n    s = lua_tostring(L, -1);  /* get result */\n    if (s == NULL)\n      return luaL_error(L, LUA_QL(\"tostring\") \" must return a string to \"\n                           LUA_QL(\"print\"));\n    if (i>1) fputs(\"\\t\", stdout);\n    fputs(s, stdout);\n    lua_pop(L, 1);  /* pop result */\n  }\n  fputs(\"\\n\", stdout);\n  return 0;\n}\n\n\nstatic int luaB_tonumber (lua_State *L) {\n  int base = luaL_optint(L, 2, 10);\n  if (base == 10) {  /* standard conversion */\n    luaL_checkany(L, 1);\n    if (lua_isnumber(L, 1)) {\n      lua_pushnumber(L, lua_tonumber(L, 1));\n      return 1;\n    }\n  }\n  else {\n    const char *s1 = luaL_checkstring(L, 1);\n    char *s2;\n    unsigned long n;\n    luaL_argcheck(L, 2 <= base && base <= 36, 2, \"base out of range\");\n    n = strtoul(s1, &s2, base);\n    if (s1 != s2) {  /* at least one valid digit? */\n      while (isspace((unsigned char)(*s2))) s2++;  /* skip trailing spaces */\n      if (*s2 == '\\0') {  /* no invalid trailing characters? */\n        lua_pushnumber(L, (lua_Number)n);\n        return 1;\n      }\n    }\n  }\n  lua_pushnil(L);  /* else not a number */\n  return 1;\n}\n\n\nstatic int luaB_error (lua_State *L) {\n  int level = luaL_optint(L, 2, 1);\n  lua_settop(L, 1);\n  if (lua_isstring(L, 1) && level > 0) {  /* add extra information? */\n    luaL_where(L, level);\n    lua_pushvalue(L, 1);\n    lua_concat(L, 2);\n  }\n  return lua_error(L);\n}\n\n\nstatic int luaB_getmetatable (lua_State *L) {\n  luaL_checkany(L, 1);\n  if (!lua_getmetatable(L, 1)) {\n    lua_pushnil(L);\n    return 1;  /* no metatable */\n  }\n  luaL_getmetafield(L, 1, \"__metatable\");\n  return 1;  /* returns either __metatable field (if present) or metatable */\n}\n\n\nstatic int luaB_setmetatable (lua_State *L) {\n  int t = lua_type(L, 2);\n  luaL_checktype(L, 1, LUA_TTABLE);\n  luaL_argcheck(L, t == LUA_TNIL || t == LUA_TTABLE, 2,\n                    \"nil or table expected\");\n  if (luaL_getmetafield(L, 1, \"__metatable\"))\n    luaL_error(L, \"cannot change a protected metatable\");\n  lua_settop(L, 2);\n  lua_setmetatable(L, 1);\n  return 1;\n}\n\n\nstatic void getfunc (lua_State *L, int opt) {\n  if (lua_isfunction(L, 1)) lua_pushvalue(L, 1);\n  else {\n    lua_Debug ar;\n    int level = opt ? luaL_optint(L, 1, 1) : luaL_checkint(L, 1);\n    luaL_argcheck(L, level >= 0, 1, \"level must be non-negative\");\n    if (lua_getstack(L, level, &ar) == 0)\n      luaL_argerror(L, 1, \"invalid level\");\n    lua_getinfo(L, \"f\", &ar);\n    if (lua_isnil(L, -1))\n      luaL_error(L, \"no function environment for tail call at level %d\",\n                    level);\n  }\n}\n\n\nstatic int luaB_getfenv (lua_State *L) {\n  getfunc(L, 1);\n  if (lua_iscfunction(L, -1))  /* is a C function? */\n    lua_pushvalue(L, LUA_GLOBALSINDEX);  /* return the thread's global env. */\n  else\n    lua_getfenv(L, -1);\n  return 1;\n}\n\n\nstatic int luaB_setfenv (lua_State *L) {\n  luaL_checktype(L, 2, LUA_TTABLE);\n  getfunc(L, 0);\n  lua_pushvalue(L, 2);\n  if (lua_isnumber(L, 1) && lua_tonumber(L, 1) == 0) {\n    /* change environment of current thread */\n    lua_pushthread(L);\n    lua_insert(L, -2);\n    lua_setfenv(L, -2);\n    return 0;\n  }\n  else if (lua_iscfunction(L, -2) || lua_setfenv(L, -2) == 0)\n    luaL_error(L,\n          LUA_QL(\"setfenv\") \" cannot change environment of given object\");\n  return 1;\n}\n\n\nstatic int luaB_rawequal (lua_State *L) {\n  luaL_checkany(L, 1);\n  luaL_checkany(L, 2);\n  lua_pushboolean(L, lua_rawequal(L, 1, 2));\n  return 1;\n}\n\n\nstatic int luaB_rawget (lua_State *L) {\n  luaL_checktype(L, 1, LUA_TTABLE);\n  luaL_checkany(L, 2);\n  lua_settop(L, 2);\n  lua_rawget(L, 1);\n  return 1;\n}\n\nstatic int luaB_rawset (lua_State *L) {\n  luaL_checktype(L, 1, LUA_TTABLE);\n  luaL_checkany(L, 2);\n  luaL_checkany(L, 3);\n  lua_settop(L, 3);\n  lua_rawset(L, 1);\n  return 1;\n}\n\n\nstatic int luaB_gcinfo (lua_State *L) {\n  lua_pushinteger(L, lua_getgccount(L));\n  return 1;\n}\n\n\nstatic int luaB_collectgarbage (lua_State *L) {\n  static const char *const opts[] = {\"stop\", \"restart\", \"collect\",\n    \"count\", \"step\", \"setpause\", \"setstepmul\", NULL};\n  static const int optsnum[] = {LUA_GCSTOP, LUA_GCRESTART, LUA_GCCOLLECT,\n    LUA_GCCOUNT, LUA_GCSTEP, LUA_GCSETPAUSE, LUA_GCSETSTEPMUL};\n  int o = luaL_checkoption(L, 1, \"collect\", opts);\n  int ex = luaL_optint(L, 2, 0);\n  int res = lua_gc(L, optsnum[o], ex);\n  switch (optsnum[o]) {\n    case LUA_GCCOUNT: {\n      int b = lua_gc(L, LUA_GCCOUNTB, 0);\n      lua_pushnumber(L, res + ((lua_Number)b/1024));\n      return 1;\n    }\n    case LUA_GCSTEP: {\n      lua_pushboolean(L, res);\n      return 1;\n    }\n    default: {\n      lua_pushnumber(L, res);\n      return 1;\n    }\n  }\n}\n\n\nstatic int luaB_type (lua_State *L) {\n  luaL_checkany(L, 1);\n  lua_pushstring(L, luaL_typename(L, 1));\n  return 1;\n}\n\n\nstatic int luaB_next (lua_State *L) {\n  luaL_checktype(L, 1, LUA_TTABLE);\n  lua_settop(L, 2);  /* create a 2nd argument if there isn't one */\n  if (lua_next(L, 1))\n    return 2;\n  else {\n    lua_pushnil(L);\n    return 1;\n  }\n}\n\n\nstatic int luaB_pairs (lua_State *L) {\n  luaL_checktype(L, 1, LUA_TTABLE);\n  lua_pushvalue(L, lua_upvalueindex(1));  /* return generator, */\n  lua_pushvalue(L, 1);  /* state, */\n  lua_pushnil(L);  /* and initial value */\n  return 3;\n}\n\n\nstatic int ipairsaux (lua_State *L) {\n  int i = luaL_checkint(L, 2);\n  luaL_checktype(L, 1, LUA_TTABLE);\n  i++;  /* next value */\n  lua_pushinteger(L, i);\n  lua_rawgeti(L, 1, i);\n  return (lua_isnil(L, -1)) ? 0 : 2;\n}\n\n\nstatic int luaB_ipairs (lua_State *L) {\n  luaL_checktype(L, 1, LUA_TTABLE);\n  lua_pushvalue(L, lua_upvalueindex(1));  /* return generator, */\n  lua_pushvalue(L, 1);  /* state, */\n  lua_pushinteger(L, 0);  /* and initial value */\n  return 3;\n}\n\n\nstatic int load_aux (lua_State *L, int status) {\n  if (status == 0)  /* OK? */\n    return 1;\n  else {\n    lua_pushnil(L);\n    lua_insert(L, -2);  /* put before error message */\n    return 2;  /* return nil plus error message */\n  }\n}\n\n\nstatic int luaB_loadstring (lua_State *L) {\n  size_t l;\n  const char *s = luaL_checklstring(L, 1, &l);\n  const char *chunkname = luaL_optstring(L, 2, s);\n  return load_aux(L, luaL_loadbuffer(L, s, l, chunkname));\n}\n\n\nstatic int luaB_loadfile (lua_State *L) {\n  const char *fname = luaL_optstring(L, 1, NULL);\n  return load_aux(L, luaL_loadfile(L, fname));\n}\n\n\n/*\n** Reader for generic `load' function: `lua_load' uses the\n** stack for internal stuff, so the reader cannot change the\n** stack top. Instead, it keeps its resulting string in a\n** reserved slot inside the stack.\n*/\nstatic const char *generic_reader (lua_State *L, void *ud, size_t *size) {\n  (void)ud;  /* to avoid warnings */\n  luaL_checkstack(L, 2, \"too many nested functions\");\n  lua_pushvalue(L, 1);  /* get function */\n  lua_call(L, 0, 1);  /* call it */\n  if (lua_isnil(L, -1)) {\n    *size = 0;\n    return NULL;\n  }\n  else if (lua_isstring(L, -1)) {\n    lua_replace(L, 3);  /* save string in a reserved stack slot */\n    return lua_tolstring(L, 3, size);\n  }\n  else luaL_error(L, \"reader function must return a string\");\n  return NULL;  /* to avoid warnings */\n}\n\n\nstatic int luaB_load (lua_State *L) {\n  int status;\n  const char *cname = luaL_optstring(L, 2, \"=(load)\");\n  luaL_checktype(L, 1, LUA_TFUNCTION);\n  lua_settop(L, 3);  /* function, eventual name, plus one reserved slot */\n  status = lua_load(L, generic_reader, NULL, cname);\n  return load_aux(L, status);\n}\n\n\nstatic int luaB_dofile (lua_State *L) {\n  const char *fname = luaL_optstring(L, 1, NULL);\n  int n = lua_gettop(L);\n  if (luaL_loadfile(L, fname) != 0) lua_error(L);\n  lua_call(L, 0, LUA_MULTRET);\n  return lua_gettop(L) - n;\n}\n\n\nstatic int luaB_assert (lua_State *L) {\n  luaL_checkany(L, 1);\n  if (!lua_toboolean(L, 1))\n    return luaL_error(L, \"%s\", luaL_optstring(L, 2, \"assertion failed!\"));\n  return lua_gettop(L);\n}\n\n\nstatic int luaB_unpack (lua_State *L) {\n  int i, e, n;\n  luaL_checktype(L, 1, LUA_TTABLE);\n  i = luaL_optint(L, 2, 1);\n  e = luaL_opt(L, luaL_checkint, 3, luaL_getn(L, 1));\n  if (i > e) return 0;  /* empty range */\n  n = e - i + 1;  /* number of elements */\n  if (n <= 0 || !lua_checkstack(L, n))  /* n <= 0 means arith. overflow */\n    return luaL_error(L, \"too many results to unpack\");\n  lua_rawgeti(L, 1, i);  /* push arg[i] (avoiding overflow problems) */\n  while (i++ < e)  /* push arg[i + 1...e] */\n    lua_rawgeti(L, 1, i);\n  return n;\n}\n\n\nstatic int luaB_select (lua_State *L) {\n  int n = lua_gettop(L);\n  if (lua_type(L, 1) == LUA_TSTRING && *lua_tostring(L, 1) == '#') {\n    lua_pushinteger(L, n-1);\n    return 1;\n  }\n  else {\n    int i = luaL_checkint(L, 1);\n    if (i < 0) i = n + i;\n    else if (i > n) i = n;\n    luaL_argcheck(L, 1 <= i, 1, \"index out of range\");\n    return n - i;\n  }\n}\n\n\nstatic int luaB_pcall (lua_State *L) {\n  int status;\n  luaL_checkany(L, 1);\n  status = lua_pcall(L, lua_gettop(L) - 1, LUA_MULTRET, 0);\n  lua_pushboolean(L, (status == 0));\n  lua_insert(L, 1);\n  return lua_gettop(L);  /* return status + all results */\n}\n\n\nstatic int luaB_xpcall (lua_State *L) {\n  int status;\n  luaL_checkany(L, 2);\n  lua_settop(L, 2);\n  lua_insert(L, 1);  /* put error function under function to be called */\n  status = lua_pcall(L, 0, LUA_MULTRET, 1);\n  lua_pushboolean(L, (status == 0));\n  lua_replace(L, 1);\n  return lua_gettop(L);  /* return status + all results */\n}\n\n\nstatic int luaB_tostring (lua_State *L) {\n  luaL_checkany(L, 1);\n  if (luaL_callmeta(L, 1, \"__tostring\"))  /* is there a metafield? */\n    return 1;  /* use its value */\n  switch (lua_type(L, 1)) {\n    case LUA_TNUMBER:\n      lua_pushstring(L, lua_tostring(L, 1));\n      break;\n    case LUA_TSTRING:\n      lua_pushvalue(L, 1);\n      break;\n    case LUA_TBOOLEAN:\n      lua_pushstring(L, (lua_toboolean(L, 1) ? \"true\" : \"false\"));\n      break;\n    case LUA_TNIL:\n      lua_pushliteral(L, \"nil\");\n      break;\n    default:\n      lua_pushfstring(L, \"%s: %p\", luaL_typename(L, 1), lua_topointer(L, 1));\n      break;\n  }\n  return 1;\n}\n\n\nstatic int luaB_newproxy (lua_State *L) {\n  lua_settop(L, 1);\n  lua_newuserdata(L, 0);  /* create proxy */\n  if (lua_toboolean(L, 1) == 0)\n    return 1;  /* no metatable */\n  else if (lua_isboolean(L, 1)) {\n    lua_newtable(L);  /* create a new metatable `m' ... */\n    lua_pushvalue(L, -1);  /* ... and mark `m' as a valid metatable */\n    lua_pushboolean(L, 1);\n    lua_rawset(L, lua_upvalueindex(1));  /* weaktable[m] = true */\n  }\n  else {\n    int validproxy = 0;  /* to check if weaktable[metatable(u)] == true */\n    if (lua_getmetatable(L, 1)) {\n      lua_rawget(L, lua_upvalueindex(1));\n      validproxy = lua_toboolean(L, -1);\n      lua_pop(L, 1);  /* remove value */\n    }\n    luaL_argcheck(L, validproxy, 1, \"boolean or proxy expected\");\n    lua_getmetatable(L, 1);  /* metatable is valid; get it */\n  }\n  lua_setmetatable(L, 2);\n  return 1;\n}\n\n\nstatic const luaL_Reg base_funcs[] = {\n  {\"assert\", luaB_assert},\n  {\"collectgarbage\", luaB_collectgarbage},\n  {\"dofile\", luaB_dofile},\n  {\"error\", luaB_error},\n  {\"gcinfo\", luaB_gcinfo},\n  {\"getfenv\", luaB_getfenv},\n  {\"getmetatable\", luaB_getmetatable},\n  {\"loadfile\", luaB_loadfile},\n  {\"load\", luaB_load},\n  {\"loadstring\", luaB_loadstring},\n  {\"next\", luaB_next},\n  {\"pcall\", luaB_pcall},\n  {\"print\", luaB_print},\n  {\"rawequal\", luaB_rawequal},\n  {\"rawget\", luaB_rawget},\n  {\"rawset\", luaB_rawset},\n  {\"select\", luaB_select},\n  {\"setfenv\", luaB_setfenv},\n  {\"setmetatable\", luaB_setmetatable},\n  {\"tonumber\", luaB_tonumber},\n  {\"tostring\", luaB_tostring},\n  {\"type\", luaB_type},\n  {\"unpack\", luaB_unpack},\n  {\"xpcall\", luaB_xpcall},\n  {NULL, NULL}\n};\n\n\n/*\n** {======================================================\n** Coroutine library\n** =======================================================\n*/\n\n#define CO_RUN\t0\t/* running */\n#define CO_SUS\t1\t/* suspended */\n#define CO_NOR\t2\t/* 'normal' (it resumed another coroutine) */\n#define CO_DEAD\t3\n\nstatic const char *const statnames[] =\n    {\"running\", \"suspended\", \"normal\", \"dead\"};\n\nstatic int costatus (lua_State *L, lua_State *co) {\n  if (L == co) return CO_RUN;\n  switch (lua_status(co)) {\n    case LUA_YIELD:\n      return CO_SUS;\n    case 0: {\n      lua_Debug ar;\n      if (lua_getstack(co, 0, &ar) > 0)  /* does it have frames? */\n        return CO_NOR;  /* it is running */\n      else if (lua_gettop(co) == 0)\n          return CO_DEAD;\n      else\n        return CO_SUS;  /* initial state */\n    }\n    default:  /* some error occured */\n      return CO_DEAD;\n  }\n}\n\n\nstatic int luaB_costatus (lua_State *L) {\n  lua_State *co = lua_tothread(L, 1);\n  luaL_argcheck(L, co, 1, \"coroutine expected\");\n  lua_pushstring(L, statnames[costatus(L, co)]);\n  return 1;\n}\n\n\nstatic int auxresume (lua_State *L, lua_State *co, int narg) {\n  int status = costatus(L, co);\n  if (!lua_checkstack(co, narg))\n    luaL_error(L, \"too many arguments to resume\");\n  if (status != CO_SUS) {\n    lua_pushfstring(L, \"cannot resume %s coroutine\", statnames[status]);\n    return -1;  /* error flag */\n  }\n  lua_xmove(L, co, narg);\n  lua_setlevel(L, co);\n  status = lua_resume(co, narg);\n  if (status == 0 || status == LUA_YIELD) {\n    int nres = lua_gettop(co);\n    if (!lua_checkstack(L, nres + 1))\n      luaL_error(L, \"too many results to resume\");\n    lua_xmove(co, L, nres);  /* move yielded values */\n    return nres;\n  }\n  else {\n    lua_xmove(co, L, 1);  /* move error message */\n    return -1;  /* error flag */\n  }\n}\n\n\nstatic int luaB_coresume (lua_State *L) {\n  lua_State *co = lua_tothread(L, 1);\n  int r;\n  luaL_argcheck(L, co, 1, \"coroutine expected\");\n  r = auxresume(L, co, lua_gettop(L) - 1);\n  if (r < 0) {\n    lua_pushboolean(L, 0);\n    lua_insert(L, -2);\n    return 2;  /* return false + error message */\n  }\n  else {\n    lua_pushboolean(L, 1);\n    lua_insert(L, -(r + 1));\n    return r + 1;  /* return true + `resume' returns */\n  }\n}\n\n\nstatic int luaB_auxwrap (lua_State *L) {\n  lua_State *co = lua_tothread(L, lua_upvalueindex(1));\n  int r = auxresume(L, co, lua_gettop(L));\n  if (r < 0) {\n    if (lua_isstring(L, -1)) {  /* error object is a string? */\n      luaL_where(L, 1);  /* add extra info */\n      lua_insert(L, -2);\n      lua_concat(L, 2);\n    }\n    lua_error(L);  /* propagate error */\n  }\n  return r;\n}\n\n\nstatic int luaB_cocreate (lua_State *L) {\n  lua_State *NL = lua_newthread(L);\n  luaL_argcheck(L, lua_isfunction(L, 1) && !lua_iscfunction(L, 1), 1,\n    \"Lua function expected\");\n  lua_pushvalue(L, 1);  /* move function to top */\n  lua_xmove(L, NL, 1);  /* move function from L to NL */\n  return 1;\n}\n\n\nstatic int luaB_cowrap (lua_State *L) {\n  luaB_cocreate(L);\n  lua_pushcclosure(L, luaB_auxwrap, 1);\n  return 1;\n}\n\n\nstatic int luaB_yield (lua_State *L) {\n  return lua_yield(L, lua_gettop(L));\n}\n\n\nstatic int luaB_corunning (lua_State *L) {\n  if (lua_pushthread(L))\n    lua_pushnil(L);  /* main thread is not a coroutine */\n  return 1;\n}\n\n\nstatic const luaL_Reg co_funcs[] = {\n  {\"create\", luaB_cocreate},\n  {\"resume\", luaB_coresume},\n  {\"running\", luaB_corunning},\n  {\"status\", luaB_costatus},\n  {\"wrap\", luaB_cowrap},\n  {\"yield\", luaB_yield},\n  {NULL, NULL}\n};\n\n/* }====================================================== */\n\n\nstatic void auxopen (lua_State *L, const char *name,\n                     lua_CFunction f, lua_CFunction u) {\n  lua_pushcfunction(L, u);\n  lua_pushcclosure(L, f, 1);\n  lua_setfield(L, -2, name);\n}\n\n\nstatic void base_open (lua_State *L) {\n  /* set global _G */\n  lua_pushvalue(L, LUA_GLOBALSINDEX);\n  lua_setglobal(L, \"_G\");\n  /* open lib into global table */\n  luaL_register(L, \"_G\", base_funcs);\n  lua_pushliteral(L, LUA_VERSION);\n  lua_setglobal(L, \"_VERSION\");  /* set global _VERSION */\n  /* `ipairs' and `pairs' need auxiliary functions as upvalues */\n  auxopen(L, \"ipairs\", luaB_ipairs, ipairsaux);\n  auxopen(L, \"pairs\", luaB_pairs, luaB_next);\n  /* `newproxy' needs a weaktable as upvalue */\n  lua_createtable(L, 0, 1);  /* new table `w' */\n  lua_pushvalue(L, -1);  /* `w' will be its own metatable */\n  lua_setmetatable(L, -2);\n  lua_pushliteral(L, \"kv\");\n  lua_setfield(L, -2, \"__mode\");  /* metatable(w).__mode = \"kv\" */\n  lua_pushcclosure(L, luaB_newproxy, 1);\n  lua_setglobal(L, \"newproxy\");  /* set global `newproxy' */\n}\n\n\nLUALIB_API int luaopen_base (lua_State *L) {\n  base_open(L);\n  luaL_register(L, LUA_COLIBNAME, co_funcs);\n  return 2;\n}\n\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.8/deps/lua/src/lcode.c",
    "content": "/*\n** $Id: lcode.c,v 2.25.1.5 2011/01/31 14:53:16 roberto Exp $\n** Code generator for Lua\n** See Copyright Notice in lua.h\n*/\n\n\n#include <stdlib.h>\n\n#define lcode_c\n#define LUA_CORE\n\n#include \"lua.h\"\n\n#include \"lcode.h\"\n#include \"ldebug.h\"\n#include \"ldo.h\"\n#include \"lgc.h\"\n#include \"llex.h\"\n#include \"lmem.h\"\n#include \"lobject.h\"\n#include \"lopcodes.h\"\n#include \"lparser.h\"\n#include \"ltable.h\"\n\n\n#define hasjumps(e)\t((e)->t != (e)->f)\n\n\nstatic int isnumeral(expdesc *e) {\n  return (e->k == VKNUM && e->t == NO_JUMP && e->f == NO_JUMP);\n}\n\n\nvoid luaK_nil (FuncState *fs, int from, int n) {\n  Instruction *previous;\n  if (fs->pc > fs->lasttarget) {  /* no jumps to current position? */\n    if (fs->pc == 0) {  /* function start? */\n      if (from >= fs->nactvar)\n        return;  /* positions are already clean */\n    }\n    else {\n      previous = &fs->f->code[fs->pc-1];\n      if (GET_OPCODE(*previous) == OP_LOADNIL) {\n        int pfrom = GETARG_A(*previous);\n        int pto = GETARG_B(*previous);\n        if (pfrom <= from && from <= pto+1) {  /* can connect both? */\n          if (from+n-1 > pto)\n            SETARG_B(*previous, from+n-1);\n          return;\n        }\n      }\n    }\n  }\n  luaK_codeABC(fs, OP_LOADNIL, from, from+n-1, 0);  /* else no optimization */\n}\n\n\nint luaK_jump (FuncState *fs) {\n  int jpc = fs->jpc;  /* save list of jumps to here */\n  int j;\n  fs->jpc = NO_JUMP;\n  j = luaK_codeAsBx(fs, OP_JMP, 0, NO_JUMP);\n  luaK_concat(fs, &j, jpc);  /* keep them on hold */\n  return j;\n}\n\n\nvoid luaK_ret (FuncState *fs, int first, int nret) {\n  luaK_codeABC(fs, OP_RETURN, first, nret+1, 0);\n}\n\n\nstatic int condjump (FuncState *fs, OpCode op, int A, int B, int C) {\n  luaK_codeABC(fs, op, A, B, C);\n  return luaK_jump(fs);\n}\n\n\nstatic void fixjump (FuncState *fs, int pc, int dest) {\n  Instruction *jmp = &fs->f->code[pc];\n  int offset = dest-(pc+1);\n  lua_assert(dest != NO_JUMP);\n  if (abs(offset) > MAXARG_sBx)\n    luaX_syntaxerror(fs->ls, \"control structure too long\");\n  SETARG_sBx(*jmp, offset);\n}\n\n\n/*\n** returns current `pc' and marks it as a jump target (to avoid wrong\n** optimizations with consecutive instructions not in the same basic block).\n*/\nint luaK_getlabel (FuncState *fs) {\n  fs->lasttarget = fs->pc;\n  return fs->pc;\n}\n\n\nstatic int getjump (FuncState *fs, int pc) {\n  int offset = GETARG_sBx(fs->f->code[pc]);\n  if (offset == NO_JUMP)  /* point to itself represents end of list */\n    return NO_JUMP;  /* end of list */\n  else\n    return (pc+1)+offset;  /* turn offset into absolute position */\n}\n\n\nstatic Instruction *getjumpcontrol (FuncState *fs, int pc) {\n  Instruction *pi = &fs->f->code[pc];\n  if (pc >= 1 && testTMode(GET_OPCODE(*(pi-1))))\n    return pi-1;\n  else\n    return pi;\n}\n\n\n/*\n** check whether list has any jump that do not produce a value\n** (or produce an inverted value)\n*/\nstatic int need_value (FuncState *fs, int list) {\n  for (; list != NO_JUMP; list = getjump(fs, list)) {\n    Instruction i = *getjumpcontrol(fs, list);\n    if (GET_OPCODE(i) != OP_TESTSET) return 1;\n  }\n  return 0;  /* not found */\n}\n\n\nstatic int patchtestreg (FuncState *fs, int node, int reg) {\n  Instruction *i = getjumpcontrol(fs, node);\n  if (GET_OPCODE(*i) != OP_TESTSET)\n    return 0;  /* cannot patch other instructions */\n  if (reg != NO_REG && reg != GETARG_B(*i))\n    SETARG_A(*i, reg);\n  else  /* no register to put value or register already has the value */\n    *i = CREATE_ABC(OP_TEST, GETARG_B(*i), 0, GETARG_C(*i));\n\n  return 1;\n}\n\n\nstatic void removevalues (FuncState *fs, int list) {\n  for (; list != NO_JUMP; list = getjump(fs, list))\n      patchtestreg(fs, list, NO_REG);\n}\n\n\nstatic void patchlistaux (FuncState *fs, int list, int vtarget, int reg,\n                          int dtarget) {\n  while (list != NO_JUMP) {\n    int next = getjump(fs, list);\n    if (patchtestreg(fs, list, reg))\n      fixjump(fs, list, vtarget);\n    else\n      fixjump(fs, list, dtarget);  /* jump to default target */\n    list = next;\n  }\n}\n\n\nstatic void dischargejpc (FuncState *fs) {\n  patchlistaux(fs, fs->jpc, fs->pc, NO_REG, fs->pc);\n  fs->jpc = NO_JUMP;\n}\n\n\nvoid luaK_patchlist (FuncState *fs, int list, int target) {\n  if (target == fs->pc)\n    luaK_patchtohere(fs, list);\n  else {\n    lua_assert(target < fs->pc);\n    patchlistaux(fs, list, target, NO_REG, target);\n  }\n}\n\n\nvoid luaK_patchtohere (FuncState *fs, int list) {\n  luaK_getlabel(fs);\n  luaK_concat(fs, &fs->jpc, list);\n}\n\n\nvoid luaK_concat (FuncState *fs, int *l1, int l2) {\n  if (l2 == NO_JUMP) return;\n  else if (*l1 == NO_JUMP)\n    *l1 = l2;\n  else {\n    int list = *l1;\n    int next;\n    while ((next = getjump(fs, list)) != NO_JUMP)  /* find last element */\n      list = next;\n    fixjump(fs, list, l2);\n  }\n}\n\n\nvoid luaK_checkstack (FuncState *fs, int n) {\n  int newstack = fs->freereg + n;\n  if (newstack > fs->f->maxstacksize) {\n    if (newstack >= MAXSTACK)\n      luaX_syntaxerror(fs->ls, \"function or expression too complex\");\n    fs->f->maxstacksize = cast_byte(newstack);\n  }\n}\n\n\nvoid luaK_reserveregs (FuncState *fs, int n) {\n  luaK_checkstack(fs, n);\n  fs->freereg += n;\n}\n\n\nstatic void freereg (FuncState *fs, int reg) {\n  if (!ISK(reg) && reg >= fs->nactvar) {\n    fs->freereg--;\n    lua_assert(reg == fs->freereg);\n  }\n}\n\n\nstatic void freeexp (FuncState *fs, expdesc *e) {\n  if (e->k == VNONRELOC)\n    freereg(fs, e->u.s.info);\n}\n\n\nstatic int addk (FuncState *fs, TValue *k, TValue *v) {\n  lua_State *L = fs->L;\n  TValue *idx = luaH_set(L, fs->h, k);\n  Proto *f = fs->f;\n  int oldsize = f->sizek;\n  if (ttisnumber(idx)) {\n    lua_assert(luaO_rawequalObj(&fs->f->k[cast_int(nvalue(idx))], v));\n    return cast_int(nvalue(idx));\n  }\n  else {  /* constant not found; create a new entry */\n    setnvalue(idx, cast_num(fs->nk));\n    luaM_growvector(L, f->k, fs->nk, f->sizek, TValue,\n                    MAXARG_Bx, \"constant table overflow\");\n    while (oldsize < f->sizek) setnilvalue(&f->k[oldsize++]);\n    setobj(L, &f->k[fs->nk], v);\n    luaC_barrier(L, f, v);\n    return fs->nk++;\n  }\n}\n\n\nint luaK_stringK (FuncState *fs, TString *s) {\n  TValue o;\n  setsvalue(fs->L, &o, s);\n  return addk(fs, &o, &o);\n}\n\n\nint luaK_numberK (FuncState *fs, lua_Number r) {\n  TValue o;\n  setnvalue(&o, r);\n  return addk(fs, &o, &o);\n}\n\n\nstatic int boolK (FuncState *fs, int b) {\n  TValue o;\n  setbvalue(&o, b);\n  return addk(fs, &o, &o);\n}\n\n\nstatic int nilK (FuncState *fs) {\n  TValue k, v;\n  setnilvalue(&v);\n  /* cannot use nil as key; instead use table itself to represent nil */\n  sethvalue(fs->L, &k, fs->h);\n  return addk(fs, &k, &v);\n}\n\n\nvoid luaK_setreturns (FuncState *fs, expdesc *e, int nresults) {\n  if (e->k == VCALL) {  /* expression is an open function call? */\n    SETARG_C(getcode(fs, e), nresults+1);\n  }\n  else if (e->k == VVARARG) {\n    SETARG_B(getcode(fs, e), nresults+1);\n    SETARG_A(getcode(fs, e), fs->freereg);\n    luaK_reserveregs(fs, 1);\n  }\n}\n\n\nvoid luaK_setoneret (FuncState *fs, expdesc *e) {\n  if (e->k == VCALL) {  /* expression is an open function call? */\n    e->k = VNONRELOC;\n    e->u.s.info = GETARG_A(getcode(fs, e));\n  }\n  else if (e->k == VVARARG) {\n    SETARG_B(getcode(fs, e), 2);\n    e->k = VRELOCABLE;  /* can relocate its simple result */\n  }\n}\n\n\nvoid luaK_dischargevars (FuncState *fs, expdesc *e) {\n  switch (e->k) {\n    case VLOCAL: {\n      e->k = VNONRELOC;\n      break;\n    }\n    case VUPVAL: {\n      e->u.s.info = luaK_codeABC(fs, OP_GETUPVAL, 0, e->u.s.info, 0);\n      e->k = VRELOCABLE;\n      break;\n    }\n    case VGLOBAL: {\n      e->u.s.info = luaK_codeABx(fs, OP_GETGLOBAL, 0, e->u.s.info);\n      e->k = VRELOCABLE;\n      break;\n    }\n    case VINDEXED: {\n      freereg(fs, e->u.s.aux);\n      freereg(fs, e->u.s.info);\n      e->u.s.info = luaK_codeABC(fs, OP_GETTABLE, 0, e->u.s.info, e->u.s.aux);\n      e->k = VRELOCABLE;\n      break;\n    }\n    case VVARARG:\n    case VCALL: {\n      luaK_setoneret(fs, e);\n      break;\n    }\n    default: break;  /* there is one value available (somewhere) */\n  }\n}\n\n\nstatic int code_label (FuncState *fs, int A, int b, int jump) {\n  luaK_getlabel(fs);  /* those instructions may be jump targets */\n  return luaK_codeABC(fs, OP_LOADBOOL, A, b, jump);\n}\n\n\nstatic void discharge2reg (FuncState *fs, expdesc *e, int reg) {\n  luaK_dischargevars(fs, e);\n  switch (e->k) {\n    case VNIL: {\n      luaK_nil(fs, reg, 1);\n      break;\n    }\n    case VFALSE:  case VTRUE: {\n      luaK_codeABC(fs, OP_LOADBOOL, reg, e->k == VTRUE, 0);\n      break;\n    }\n    case VK: {\n      luaK_codeABx(fs, OP_LOADK, reg, e->u.s.info);\n      break;\n    }\n    case VKNUM: {\n      luaK_codeABx(fs, OP_LOADK, reg, luaK_numberK(fs, e->u.nval));\n      break;\n    }\n    case VRELOCABLE: {\n      Instruction *pc = &getcode(fs, e);\n      SETARG_A(*pc, reg);\n      break;\n    }\n    case VNONRELOC: {\n      if (reg != e->u.s.info)\n        luaK_codeABC(fs, OP_MOVE, reg, e->u.s.info, 0);\n      break;\n    }\n    default: {\n      lua_assert(e->k == VVOID || e->k == VJMP);\n      return;  /* nothing to do... */\n    }\n  }\n  e->u.s.info = reg;\n  e->k = VNONRELOC;\n}\n\n\nstatic void discharge2anyreg (FuncState *fs, expdesc *e) {\n  if (e->k != VNONRELOC) {\n    luaK_reserveregs(fs, 1);\n    discharge2reg(fs, e, fs->freereg-1);\n  }\n}\n\n\nstatic void exp2reg (FuncState *fs, expdesc *e, int reg) {\n  discharge2reg(fs, e, reg);\n  if (e->k == VJMP)\n    luaK_concat(fs, &e->t, e->u.s.info);  /* put this jump in `t' list */\n  if (hasjumps(e)) {\n    int final;  /* position after whole expression */\n    int p_f = NO_JUMP;  /* position of an eventual LOAD false */\n    int p_t = NO_JUMP;  /* position of an eventual LOAD true */\n    if (need_value(fs, e->t) || need_value(fs, e->f)) {\n      int fj = (e->k == VJMP) ? NO_JUMP : luaK_jump(fs);\n      p_f = code_label(fs, reg, 0, 1);\n      p_t = code_label(fs, reg, 1, 0);\n      luaK_patchtohere(fs, fj);\n    }\n    final = luaK_getlabel(fs);\n    patchlistaux(fs, e->f, final, reg, p_f);\n    patchlistaux(fs, e->t, final, reg, p_t);\n  }\n  e->f = e->t = NO_JUMP;\n  e->u.s.info = reg;\n  e->k = VNONRELOC;\n}\n\n\nvoid luaK_exp2nextreg (FuncState *fs, expdesc *e) {\n  luaK_dischargevars(fs, e);\n  freeexp(fs, e);\n  luaK_reserveregs(fs, 1);\n  exp2reg(fs, e, fs->freereg - 1);\n}\n\n\nint luaK_exp2anyreg (FuncState *fs, expdesc *e) {\n  luaK_dischargevars(fs, e);\n  if (e->k == VNONRELOC) {\n    if (!hasjumps(e)) return e->u.s.info;  /* exp is already in a register */\n    if (e->u.s.info >= fs->nactvar) {  /* reg. is not a local? */\n      exp2reg(fs, e, e->u.s.info);  /* put value on it */\n      return e->u.s.info;\n    }\n  }\n  luaK_exp2nextreg(fs, e);  /* default */\n  return e->u.s.info;\n}\n\n\nvoid luaK_exp2val (FuncState *fs, expdesc *e) {\n  if (hasjumps(e))\n    luaK_exp2anyreg(fs, e);\n  else\n    luaK_dischargevars(fs, e);\n}\n\n\nint luaK_exp2RK (FuncState *fs, expdesc *e) {\n  luaK_exp2val(fs, e);\n  switch (e->k) {\n    case VKNUM:\n    case VTRUE:\n    case VFALSE:\n    case VNIL: {\n      if (fs->nk <= MAXINDEXRK) {  /* constant fit in RK operand? */\n        e->u.s.info = (e->k == VNIL)  ? nilK(fs) :\n                      (e->k == VKNUM) ? luaK_numberK(fs, e->u.nval) :\n                                        boolK(fs, (e->k == VTRUE));\n        e->k = VK;\n        return RKASK(e->u.s.info);\n      }\n      else break;\n    }\n    case VK: {\n      if (e->u.s.info <= MAXINDEXRK)  /* constant fit in argC? */\n        return RKASK(e->u.s.info);\n      else break;\n    }\n    default: break;\n  }\n  /* not a constant in the right range: put it in a register */\n  return luaK_exp2anyreg(fs, e);\n}\n\n\nvoid luaK_storevar (FuncState *fs, expdesc *var, expdesc *ex) {\n  switch (var->k) {\n    case VLOCAL: {\n      freeexp(fs, ex);\n      exp2reg(fs, ex, var->u.s.info);\n      return;\n    }\n    case VUPVAL: {\n      int e = luaK_exp2anyreg(fs, ex);\n      luaK_codeABC(fs, OP_SETUPVAL, e, var->u.s.info, 0);\n      break;\n    }\n    case VGLOBAL: {\n      int e = luaK_exp2anyreg(fs, ex);\n      luaK_codeABx(fs, OP_SETGLOBAL, e, var->u.s.info);\n      break;\n    }\n    case VINDEXED: {\n      int e = luaK_exp2RK(fs, ex);\n      luaK_codeABC(fs, OP_SETTABLE, var->u.s.info, var->u.s.aux, e);\n      break;\n    }\n    default: {\n      lua_assert(0);  /* invalid var kind to store */\n      break;\n    }\n  }\n  freeexp(fs, ex);\n}\n\n\nvoid luaK_self (FuncState *fs, expdesc *e, expdesc *key) {\n  int func;\n  luaK_exp2anyreg(fs, e);\n  freeexp(fs, e);\n  func = fs->freereg;\n  luaK_reserveregs(fs, 2);\n  luaK_codeABC(fs, OP_SELF, func, e->u.s.info, luaK_exp2RK(fs, key));\n  freeexp(fs, key);\n  e->u.s.info = func;\n  e->k = VNONRELOC;\n}\n\n\nstatic void invertjump (FuncState *fs, expdesc *e) {\n  Instruction *pc = getjumpcontrol(fs, e->u.s.info);\n  lua_assert(testTMode(GET_OPCODE(*pc)) && GET_OPCODE(*pc) != OP_TESTSET &&\n                                           GET_OPCODE(*pc) != OP_TEST);\n  SETARG_A(*pc, !(GETARG_A(*pc)));\n}\n\n\nstatic int jumponcond (FuncState *fs, expdesc *e, int cond) {\n  if (e->k == VRELOCABLE) {\n    Instruction ie = getcode(fs, e);\n    if (GET_OPCODE(ie) == OP_NOT) {\n      fs->pc--;  /* remove previous OP_NOT */\n      return condjump(fs, OP_TEST, GETARG_B(ie), 0, !cond);\n    }\n    /* else go through */\n  }\n  discharge2anyreg(fs, e);\n  freeexp(fs, e);\n  return condjump(fs, OP_TESTSET, NO_REG, e->u.s.info, cond);\n}\n\n\nvoid luaK_goiftrue (FuncState *fs, expdesc *e) {\n  int pc;  /* pc of last jump */\n  luaK_dischargevars(fs, e);\n  switch (e->k) {\n    case VK: case VKNUM: case VTRUE: {\n      pc = NO_JUMP;  /* always true; do nothing */\n      break;\n    }\n    case VJMP: {\n      invertjump(fs, e);\n      pc = e->u.s.info;\n      break;\n    }\n    default: {\n      pc = jumponcond(fs, e, 0);\n      break;\n    }\n  }\n  luaK_concat(fs, &e->f, pc);  /* insert last jump in `f' list */\n  luaK_patchtohere(fs, e->t);\n  e->t = NO_JUMP;\n}\n\n\nstatic void luaK_goiffalse (FuncState *fs, expdesc *e) {\n  int pc;  /* pc of last jump */\n  luaK_dischargevars(fs, e);\n  switch (e->k) {\n    case VNIL: case VFALSE: {\n      pc = NO_JUMP;  /* always false; do nothing */\n      break;\n    }\n    case VJMP: {\n      pc = e->u.s.info;\n      break;\n    }\n    default: {\n      pc = jumponcond(fs, e, 1);\n      break;\n    }\n  }\n  luaK_concat(fs, &e->t, pc);  /* insert last jump in `t' list */\n  luaK_patchtohere(fs, e->f);\n  e->f = NO_JUMP;\n}\n\n\nstatic void codenot (FuncState *fs, expdesc *e) {\n  luaK_dischargevars(fs, e);\n  switch (e->k) {\n    case VNIL: case VFALSE: {\n      e->k = VTRUE;\n      break;\n    }\n    case VK: case VKNUM: case VTRUE: {\n      e->k = VFALSE;\n      break;\n    }\n    case VJMP: {\n      invertjump(fs, e);\n      break;\n    }\n    case VRELOCABLE:\n    case VNONRELOC: {\n      discharge2anyreg(fs, e);\n      freeexp(fs, e);\n      e->u.s.info = luaK_codeABC(fs, OP_NOT, 0, e->u.s.info, 0);\n      e->k = VRELOCABLE;\n      break;\n    }\n    default: {\n      lua_assert(0);  /* cannot happen */\n      break;\n    }\n  }\n  /* interchange true and false lists */\n  { int temp = e->f; e->f = e->t; e->t = temp; }\n  removevalues(fs, e->f);\n  removevalues(fs, e->t);\n}\n\n\nvoid luaK_indexed (FuncState *fs, expdesc *t, expdesc *k) {\n  t->u.s.aux = luaK_exp2RK(fs, k);\n  t->k = VINDEXED;\n}\n\n\nstatic int constfolding (OpCode op, expdesc *e1, expdesc *e2) {\n  lua_Number v1, v2, r;\n  if (!isnumeral(e1) || !isnumeral(e2)) return 0;\n  v1 = e1->u.nval;\n  v2 = e2->u.nval;\n  switch (op) {\n    case OP_ADD: r = luai_numadd(v1, v2); break;\n    case OP_SUB: r = luai_numsub(v1, v2); break;\n    case OP_MUL: r = luai_nummul(v1, v2); break;\n    case OP_DIV:\n      if (v2 == 0) return 0;  /* do not attempt to divide by 0 */\n      r = luai_numdiv(v1, v2); break;\n    case OP_MOD:\n      if (v2 == 0) return 0;  /* do not attempt to divide by 0 */\n      r = luai_nummod(v1, v2); break;\n    case OP_POW: r = luai_numpow(v1, v2); break;\n    case OP_UNM: r = luai_numunm(v1); break;\n    case OP_LEN: return 0;  /* no constant folding for 'len' */\n    default: lua_assert(0); r = 0; break;\n  }\n  if (luai_numisnan(r)) return 0;  /* do not attempt to produce NaN */\n  e1->u.nval = r;\n  return 1;\n}\n\n\nstatic void codearith (FuncState *fs, OpCode op, expdesc *e1, expdesc *e2) {\n  if (constfolding(op, e1, e2))\n    return;\n  else {\n    int o2 = (op != OP_UNM && op != OP_LEN) ? luaK_exp2RK(fs, e2) : 0;\n    int o1 = luaK_exp2RK(fs, e1);\n    if (o1 > o2) {\n      freeexp(fs, e1);\n      freeexp(fs, e2);\n    }\n    else {\n      freeexp(fs, e2);\n      freeexp(fs, e1);\n    }\n    e1->u.s.info = luaK_codeABC(fs, op, 0, o1, o2);\n    e1->k = VRELOCABLE;\n  }\n}\n\n\nstatic void codecomp (FuncState *fs, OpCode op, int cond, expdesc *e1,\n                                                          expdesc *e2) {\n  int o1 = luaK_exp2RK(fs, e1);\n  int o2 = luaK_exp2RK(fs, e2);\n  freeexp(fs, e2);\n  freeexp(fs, e1);\n  if (cond == 0 && op != OP_EQ) {\n    int temp;  /* exchange args to replace by `<' or `<=' */\n    temp = o1; o1 = o2; o2 = temp;  /* o1 <==> o2 */\n    cond = 1;\n  }\n  e1->u.s.info = condjump(fs, op, cond, o1, o2);\n  e1->k = VJMP;\n}\n\n\nvoid luaK_prefix (FuncState *fs, UnOpr op, expdesc *e) {\n  expdesc e2;\n  e2.t = e2.f = NO_JUMP; e2.k = VKNUM; e2.u.nval = 0;\n  switch (op) {\n    case OPR_MINUS: {\n      if (!isnumeral(e))\n        luaK_exp2anyreg(fs, e);  /* cannot operate on non-numeric constants */\n      codearith(fs, OP_UNM, e, &e2);\n      break;\n    }\n    case OPR_NOT: codenot(fs, e); break;\n    case OPR_LEN: {\n      luaK_exp2anyreg(fs, e);  /* cannot operate on constants */\n      codearith(fs, OP_LEN, e, &e2);\n      break;\n    }\n    default: lua_assert(0);\n  }\n}\n\n\nvoid luaK_infix (FuncState *fs, BinOpr op, expdesc *v) {\n  switch (op) {\n    case OPR_AND: {\n      luaK_goiftrue(fs, v);\n      break;\n    }\n    case OPR_OR: {\n      luaK_goiffalse(fs, v);\n      break;\n    }\n    case OPR_CONCAT: {\n      luaK_exp2nextreg(fs, v);  /* operand must be on the `stack' */\n      break;\n    }\n    case OPR_ADD: case OPR_SUB: case OPR_MUL: case OPR_DIV:\n    case OPR_MOD: case OPR_POW: {\n      if (!isnumeral(v)) luaK_exp2RK(fs, v);\n      break;\n    }\n    default: {\n      luaK_exp2RK(fs, v);\n      break;\n    }\n  }\n}\n\n\nvoid luaK_posfix (FuncState *fs, BinOpr op, expdesc *e1, expdesc *e2) {\n  switch (op) {\n    case OPR_AND: {\n      lua_assert(e1->t == NO_JUMP);  /* list must be closed */\n      luaK_dischargevars(fs, e2);\n      luaK_concat(fs, &e2->f, e1->f);\n      *e1 = *e2;\n      break;\n    }\n    case OPR_OR: {\n      lua_assert(e1->f == NO_JUMP);  /* list must be closed */\n      luaK_dischargevars(fs, e2);\n      luaK_concat(fs, &e2->t, e1->t);\n      *e1 = *e2;\n      break;\n    }\n    case OPR_CONCAT: {\n      luaK_exp2val(fs, e2);\n      if (e2->k == VRELOCABLE && GET_OPCODE(getcode(fs, e2)) == OP_CONCAT) {\n        lua_assert(e1->u.s.info == GETARG_B(getcode(fs, e2))-1);\n        freeexp(fs, e1);\n        SETARG_B(getcode(fs, e2), e1->u.s.info);\n        e1->k = VRELOCABLE; e1->u.s.info = e2->u.s.info;\n      }\n      else {\n        luaK_exp2nextreg(fs, e2);  /* operand must be on the 'stack' */\n        codearith(fs, OP_CONCAT, e1, e2);\n      }\n      break;\n    }\n    case OPR_ADD: codearith(fs, OP_ADD, e1, e2); break;\n    case OPR_SUB: codearith(fs, OP_SUB, e1, e2); break;\n    case OPR_MUL: codearith(fs, OP_MUL, e1, e2); break;\n    case OPR_DIV: codearith(fs, OP_DIV, e1, e2); break;\n    case OPR_MOD: codearith(fs, OP_MOD, e1, e2); break;\n    case OPR_POW: codearith(fs, OP_POW, e1, e2); break;\n    case OPR_EQ: codecomp(fs, OP_EQ, 1, e1, e2); break;\n    case OPR_NE: codecomp(fs, OP_EQ, 0, e1, e2); break;\n    case OPR_LT: codecomp(fs, OP_LT, 1, e1, e2); break;\n    case OPR_LE: codecomp(fs, OP_LE, 1, e1, e2); break;\n    case OPR_GT: codecomp(fs, OP_LT, 0, e1, e2); break;\n    case OPR_GE: codecomp(fs, OP_LE, 0, e1, e2); break;\n    default: lua_assert(0);\n  }\n}\n\n\nvoid luaK_fixline (FuncState *fs, int line) {\n  fs->f->lineinfo[fs->pc - 1] = line;\n}\n\n\nstatic int luaK_code (FuncState *fs, Instruction i, int line) {\n  Proto *f = fs->f;\n  dischargejpc(fs);  /* `pc' will change */\n  /* put new instruction in code array */\n  luaM_growvector(fs->L, f->code, fs->pc, f->sizecode, Instruction,\n                  MAX_INT, \"code size overflow\");\n  f->code[fs->pc] = i;\n  /* save corresponding line information */\n  luaM_growvector(fs->L, f->lineinfo, fs->pc, f->sizelineinfo, int,\n                  MAX_INT, \"code size overflow\");\n  f->lineinfo[fs->pc] = line;\n  return fs->pc++;\n}\n\n\nint luaK_codeABC (FuncState *fs, OpCode o, int a, int b, int c) {\n  lua_assert(getOpMode(o) == iABC);\n  lua_assert(getBMode(o) != OpArgN || b == 0);\n  lua_assert(getCMode(o) != OpArgN || c == 0);\n  return luaK_code(fs, CREATE_ABC(o, a, b, c), fs->ls->lastline);\n}\n\n\nint luaK_codeABx (FuncState *fs, OpCode o, int a, unsigned int bc) {\n  lua_assert(getOpMode(o) == iABx || getOpMode(o) == iAsBx);\n  lua_assert(getCMode(o) == OpArgN);\n  return luaK_code(fs, CREATE_ABx(o, a, bc), fs->ls->lastline);\n}\n\n\nvoid luaK_setlist (FuncState *fs, int base, int nelems, int tostore) {\n  int c =  (nelems - 1)/LFIELDS_PER_FLUSH + 1;\n  int b = (tostore == LUA_MULTRET) ? 0 : tostore;\n  lua_assert(tostore != 0);\n  if (c <= MAXARG_C)\n    luaK_codeABC(fs, OP_SETLIST, base, b, c);\n  else {\n    luaK_codeABC(fs, OP_SETLIST, base, b, 0);\n    luaK_code(fs, cast(Instruction, c), fs->ls->lastline);\n  }\n  fs->freereg = base + 1;  /* free registers with list values */\n}\n\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.8/deps/lua/src/lcode.h",
    "content": "/*\n** $Id: lcode.h,v 1.48.1.1 2007/12/27 13:02:25 roberto Exp $\n** Code generator for Lua\n** See Copyright Notice in lua.h\n*/\n\n#ifndef lcode_h\n#define lcode_h\n\n#include \"llex.h\"\n#include \"lobject.h\"\n#include \"lopcodes.h\"\n#include \"lparser.h\"\n\n\n/*\n** Marks the end of a patch list. It is an invalid value both as an absolute\n** address, and as a list link (would link an element to itself).\n*/\n#define NO_JUMP (-1)\n\n\n/*\n** grep \"ORDER OPR\" if you change these enums\n*/\ntypedef enum BinOpr {\n  OPR_ADD, OPR_SUB, OPR_MUL, OPR_DIV, OPR_MOD, OPR_POW,\n  OPR_CONCAT,\n  OPR_NE, OPR_EQ,\n  OPR_LT, OPR_LE, OPR_GT, OPR_GE,\n  OPR_AND, OPR_OR,\n  OPR_NOBINOPR\n} BinOpr;\n\n\ntypedef enum UnOpr { OPR_MINUS, OPR_NOT, OPR_LEN, OPR_NOUNOPR } UnOpr;\n\n\n#define getcode(fs,e)\t((fs)->f->code[(e)->u.s.info])\n\n#define luaK_codeAsBx(fs,o,A,sBx)\tluaK_codeABx(fs,o,A,(sBx)+MAXARG_sBx)\n\n#define luaK_setmultret(fs,e)\tluaK_setreturns(fs, e, LUA_MULTRET)\n\nLUAI_FUNC int luaK_codeABx (FuncState *fs, OpCode o, int A, unsigned int Bx);\nLUAI_FUNC int luaK_codeABC (FuncState *fs, OpCode o, int A, int B, int C);\nLUAI_FUNC void luaK_fixline (FuncState *fs, int line);\nLUAI_FUNC void luaK_nil (FuncState *fs, int from, int n);\nLUAI_FUNC void luaK_reserveregs (FuncState *fs, int n);\nLUAI_FUNC void luaK_checkstack (FuncState *fs, int n);\nLUAI_FUNC int luaK_stringK (FuncState *fs, TString *s);\nLUAI_FUNC int luaK_numberK (FuncState *fs, lua_Number r);\nLUAI_FUNC void luaK_dischargevars (FuncState *fs, expdesc *e);\nLUAI_FUNC int luaK_exp2anyreg (FuncState *fs, expdesc *e);\nLUAI_FUNC void luaK_exp2nextreg (FuncState *fs, expdesc *e);\nLUAI_FUNC void luaK_exp2val (FuncState *fs, expdesc *e);\nLUAI_FUNC int luaK_exp2RK (FuncState *fs, expdesc *e);\nLUAI_FUNC void luaK_self (FuncState *fs, expdesc *e, expdesc *key);\nLUAI_FUNC void luaK_indexed (FuncState *fs, expdesc *t, expdesc *k);\nLUAI_FUNC void luaK_goiftrue (FuncState *fs, expdesc *e);\nLUAI_FUNC void luaK_storevar (FuncState *fs, expdesc *var, expdesc *e);\nLUAI_FUNC void luaK_setreturns (FuncState *fs, expdesc *e, int nresults);\nLUAI_FUNC void luaK_setoneret (FuncState *fs, expdesc *e);\nLUAI_FUNC int luaK_jump (FuncState *fs);\nLUAI_FUNC void luaK_ret (FuncState *fs, int first, int nret);\nLUAI_FUNC void luaK_patchlist (FuncState *fs, int list, int target);\nLUAI_FUNC void luaK_patchtohere (FuncState *fs, int list);\nLUAI_FUNC void luaK_concat (FuncState *fs, int *l1, int l2);\nLUAI_FUNC int luaK_getlabel (FuncState *fs);\nLUAI_FUNC void luaK_prefix (FuncState *fs, UnOpr op, expdesc *v);\nLUAI_FUNC void luaK_infix (FuncState *fs, BinOpr op, expdesc *v);\nLUAI_FUNC void luaK_posfix (FuncState *fs, BinOpr op, expdesc *v1, expdesc *v2);\nLUAI_FUNC void luaK_setlist (FuncState *fs, int base, int nelems, int tostore);\n\n\n#endif\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.8/deps/lua/src/ldblib.c",
    "content": "/*\n** $Id: ldblib.c,v 1.104.1.4 2009/08/04 18:50:18 roberto Exp $\n** Interface from Lua to its debug API\n** See Copyright Notice in lua.h\n*/\n\n\n#include <stdio.h>\n#include <stdlib.h>\n#include <string.h>\n\n#define ldblib_c\n#define LUA_LIB\n\n#include \"lua.h\"\n\n#include \"lauxlib.h\"\n#include \"lualib.h\"\n\n\n\nstatic int db_getregistry (lua_State *L) {\n  lua_pushvalue(L, LUA_REGISTRYINDEX);\n  return 1;\n}\n\n\nstatic int db_getmetatable (lua_State *L) {\n  luaL_checkany(L, 1);\n  if (!lua_getmetatable(L, 1)) {\n    lua_pushnil(L);  /* no metatable */\n  }\n  return 1;\n}\n\n\nstatic int db_setmetatable (lua_State *L) {\n  int t = lua_type(L, 2);\n  luaL_argcheck(L, t == LUA_TNIL || t == LUA_TTABLE, 2,\n                    \"nil or table expected\");\n  lua_settop(L, 2);\n  lua_pushboolean(L, lua_setmetatable(L, 1));\n  return 1;\n}\n\n\nstatic int db_getfenv (lua_State *L) {\n  luaL_checkany(L, 1);\n  lua_getfenv(L, 1);\n  return 1;\n}\n\n\nstatic int db_setfenv (lua_State *L) {\n  luaL_checktype(L, 2, LUA_TTABLE);\n  lua_settop(L, 2);\n  if (lua_setfenv(L, 1) == 0)\n    luaL_error(L, LUA_QL(\"setfenv\")\n                  \" cannot change environment of given object\");\n  return 1;\n}\n\n\nstatic void settabss (lua_State *L, const char *i, const char *v) {\n  lua_pushstring(L, v);\n  lua_setfield(L, -2, i);\n}\n\n\nstatic void settabsi (lua_State *L, const char *i, int v) {\n  lua_pushinteger(L, v);\n  lua_setfield(L, -2, i);\n}\n\n\nstatic lua_State *getthread (lua_State *L, int *arg) {\n  if (lua_isthread(L, 1)) {\n    *arg = 1;\n    return lua_tothread(L, 1);\n  }\n  else {\n    *arg = 0;\n    return L;\n  }\n}\n\n\nstatic void treatstackoption (lua_State *L, lua_State *L1, const char *fname) {\n  if (L == L1) {\n    lua_pushvalue(L, -2);\n    lua_remove(L, -3);\n  }\n  else\n    lua_xmove(L1, L, 1);\n  lua_setfield(L, -2, fname);\n}\n\n\nstatic int db_getinfo (lua_State *L) {\n  lua_Debug ar;\n  int arg;\n  lua_State *L1 = getthread(L, &arg);\n  const char *options = luaL_optstring(L, arg+2, \"flnSu\");\n  if (lua_isnumber(L, arg+1)) {\n    if (!lua_getstack(L1, (int)lua_tointeger(L, arg+1), &ar)) {\n      lua_pushnil(L);  /* level out of range */\n      return 1;\n    }\n  }\n  else if (lua_isfunction(L, arg+1)) {\n    lua_pushfstring(L, \">%s\", options);\n    options = lua_tostring(L, -1);\n    lua_pushvalue(L, arg+1);\n    lua_xmove(L, L1, 1);\n  }\n  else\n    return luaL_argerror(L, arg+1, \"function or level expected\");\n  if (!lua_getinfo(L1, options, &ar))\n    return luaL_argerror(L, arg+2, \"invalid option\");\n  lua_createtable(L, 0, 2);\n  if (strchr(options, 'S')) {\n    settabss(L, \"source\", ar.source);\n    settabss(L, \"short_src\", ar.short_src);\n    settabsi(L, \"linedefined\", ar.linedefined);\n    settabsi(L, \"lastlinedefined\", ar.lastlinedefined);\n    settabss(L, \"what\", ar.what);\n  }\n  if (strchr(options, 'l'))\n    settabsi(L, \"currentline\", ar.currentline);\n  if (strchr(options, 'u'))\n    settabsi(L, \"nups\", ar.nups);\n  if (strchr(options, 'n')) {\n    settabss(L, \"name\", ar.name);\n    settabss(L, \"namewhat\", ar.namewhat);\n  }\n  if (strchr(options, 'L'))\n    treatstackoption(L, L1, \"activelines\");\n  if (strchr(options, 'f'))\n    treatstackoption(L, L1, \"func\");\n  return 1;  /* return table */\n}\n    \n\nstatic int db_getlocal (lua_State *L) {\n  int arg;\n  lua_State *L1 = getthread(L, &arg);\n  lua_Debug ar;\n  const char *name;\n  if (!lua_getstack(L1, luaL_checkint(L, arg+1), &ar))  /* out of range? */\n    return luaL_argerror(L, arg+1, \"level out of range\");\n  name = lua_getlocal(L1, &ar, luaL_checkint(L, arg+2));\n  if (name) {\n    lua_xmove(L1, L, 1);\n    lua_pushstring(L, name);\n    lua_pushvalue(L, -2);\n    return 2;\n  }\n  else {\n    lua_pushnil(L);\n    return 1;\n  }\n}\n\n\nstatic int db_setlocal (lua_State *L) {\n  int arg;\n  lua_State *L1 = getthread(L, &arg);\n  lua_Debug ar;\n  if (!lua_getstack(L1, luaL_checkint(L, arg+1), &ar))  /* out of range? */\n    return luaL_argerror(L, arg+1, \"level out of range\");\n  luaL_checkany(L, arg+3);\n  lua_settop(L, arg+3);\n  lua_xmove(L, L1, 1);\n  lua_pushstring(L, lua_setlocal(L1, &ar, luaL_checkint(L, arg+2)));\n  return 1;\n}\n\n\nstatic int auxupvalue (lua_State *L, int get) {\n  const char *name;\n  int n = luaL_checkint(L, 2);\n  luaL_checktype(L, 1, LUA_TFUNCTION);\n  if (lua_iscfunction(L, 1)) return 0;  /* cannot touch C upvalues from Lua */\n  name = get ? lua_getupvalue(L, 1, n) : lua_setupvalue(L, 1, n);\n  if (name == NULL) return 0;\n  lua_pushstring(L, name);\n  lua_insert(L, -(get+1));\n  return get + 1;\n}\n\n\nstatic int db_getupvalue (lua_State *L) {\n  return auxupvalue(L, 1);\n}\n\n\nstatic int db_setupvalue (lua_State *L) {\n  luaL_checkany(L, 3);\n  return auxupvalue(L, 0);\n}\n\n\n\nstatic const char KEY_HOOK = 'h';\n\n\nstatic void hookf (lua_State *L, lua_Debug *ar) {\n  static const char *const hooknames[] =\n    {\"call\", \"return\", \"line\", \"count\", \"tail return\"};\n  lua_pushlightuserdata(L, (void *)&KEY_HOOK);\n  lua_rawget(L, LUA_REGISTRYINDEX);\n  lua_pushlightuserdata(L, L);\n  lua_rawget(L, -2);\n  if (lua_isfunction(L, -1)) {\n    lua_pushstring(L, hooknames[(int)ar->event]);\n    if (ar->currentline >= 0)\n      lua_pushinteger(L, ar->currentline);\n    else lua_pushnil(L);\n    lua_assert(lua_getinfo(L, \"lS\", ar));\n    lua_call(L, 2, 0);\n  }\n}\n\n\nstatic int makemask (const char *smask, int count) {\n  int mask = 0;\n  if (strchr(smask, 'c')) mask |= LUA_MASKCALL;\n  if (strchr(smask, 'r')) mask |= LUA_MASKRET;\n  if (strchr(smask, 'l')) mask |= LUA_MASKLINE;\n  if (count > 0) mask |= LUA_MASKCOUNT;\n  return mask;\n}\n\n\nstatic char *unmakemask (int mask, char *smask) {\n  int i = 0;\n  if (mask & LUA_MASKCALL) smask[i++] = 'c';\n  if (mask & LUA_MASKRET) smask[i++] = 'r';\n  if (mask & LUA_MASKLINE) smask[i++] = 'l';\n  smask[i] = '\\0';\n  return smask;\n}\n\n\nstatic void gethooktable (lua_State *L) {\n  lua_pushlightuserdata(L, (void *)&KEY_HOOK);\n  lua_rawget(L, LUA_REGISTRYINDEX);\n  if (!lua_istable(L, -1)) {\n    lua_pop(L, 1);\n    lua_createtable(L, 0, 1);\n    lua_pushlightuserdata(L, (void *)&KEY_HOOK);\n    lua_pushvalue(L, -2);\n    lua_rawset(L, LUA_REGISTRYINDEX);\n  }\n}\n\n\nstatic int db_sethook (lua_State *L) {\n  int arg, mask, count;\n  lua_Hook func;\n  lua_State *L1 = getthread(L, &arg);\n  if (lua_isnoneornil(L, arg+1)) {\n    lua_settop(L, arg+1);\n    func = NULL; mask = 0; count = 0;  /* turn off hooks */\n  }\n  else {\n    const char *smask = luaL_checkstring(L, arg+2);\n    luaL_checktype(L, arg+1, LUA_TFUNCTION);\n    count = luaL_optint(L, arg+3, 0);\n    func = hookf; mask = makemask(smask, count);\n  }\n  gethooktable(L);\n  lua_pushlightuserdata(L, L1);\n  lua_pushvalue(L, arg+1);\n  lua_rawset(L, -3);  /* set new hook */\n  lua_pop(L, 1);  /* remove hook table */\n  lua_sethook(L1, func, mask, count);  /* set hooks */\n  return 0;\n}\n\n\nstatic int db_gethook (lua_State *L) {\n  int arg;\n  lua_State *L1 = getthread(L, &arg);\n  char buff[5];\n  int mask = lua_gethookmask(L1);\n  lua_Hook hook = lua_gethook(L1);\n  if (hook != NULL && hook != hookf)  /* external hook? */\n    lua_pushliteral(L, \"external hook\");\n  else {\n    gethooktable(L);\n    lua_pushlightuserdata(L, L1);\n    lua_rawget(L, -2);   /* get hook */\n    lua_remove(L, -2);  /* remove hook table */\n  }\n  lua_pushstring(L, unmakemask(mask, buff));\n  lua_pushinteger(L, lua_gethookcount(L1));\n  return 3;\n}\n\n\nstatic int db_debug (lua_State *L) {\n  for (;;) {\n    char buffer[250];\n    fputs(\"lua_debug> \", stderr);\n    if (fgets(buffer, sizeof(buffer), stdin) == 0 ||\n        strcmp(buffer, \"cont\\n\") == 0)\n      return 0;\n    if (luaL_loadbuffer(L, buffer, strlen(buffer), \"=(debug command)\") ||\n        lua_pcall(L, 0, 0, 0)) {\n      fputs(lua_tostring(L, -1), stderr);\n      fputs(\"\\n\", stderr);\n    }\n    lua_settop(L, 0);  /* remove eventual returns */\n  }\n}\n\n\n#define LEVELS1\t12\t/* size of the first part of the stack */\n#define LEVELS2\t10\t/* size of the second part of the stack */\n\nstatic int db_errorfb (lua_State *L) {\n  int level;\n  int firstpart = 1;  /* still before eventual `...' */\n  int arg;\n  lua_State *L1 = getthread(L, &arg);\n  lua_Debug ar;\n  if (lua_isnumber(L, arg+2)) {\n    level = (int)lua_tointeger(L, arg+2);\n    lua_pop(L, 1);\n  }\n  else\n    level = (L == L1) ? 1 : 0;  /* level 0 may be this own function */\n  if (lua_gettop(L) == arg)\n    lua_pushliteral(L, \"\");\n  else if (!lua_isstring(L, arg+1)) return 1;  /* message is not a string */\n  else lua_pushliteral(L, \"\\n\");\n  lua_pushliteral(L, \"stack traceback:\");\n  while (lua_getstack(L1, level++, &ar)) {\n    if (level > LEVELS1 && firstpart) {\n      /* no more than `LEVELS2' more levels? */\n      if (!lua_getstack(L1, level+LEVELS2, &ar))\n        level--;  /* keep going */\n      else {\n        lua_pushliteral(L, \"\\n\\t...\");  /* too many levels */\n        while (lua_getstack(L1, level+LEVELS2, &ar))  /* find last levels */\n          level++;\n      }\n      firstpart = 0;\n      continue;\n    }\n    lua_pushliteral(L, \"\\n\\t\");\n    lua_getinfo(L1, \"Snl\", &ar);\n    lua_pushfstring(L, \"%s:\", ar.short_src);\n    if (ar.currentline > 0)\n      lua_pushfstring(L, \"%d:\", ar.currentline);\n    if (*ar.namewhat != '\\0')  /* is there a name? */\n        lua_pushfstring(L, \" in function \" LUA_QS, ar.name);\n    else {\n      if (*ar.what == 'm')  /* main? */\n        lua_pushfstring(L, \" in main chunk\");\n      else if (*ar.what == 'C' || *ar.what == 't')\n        lua_pushliteral(L, \" ?\");  /* C function or tail call */\n      else\n        lua_pushfstring(L, \" in function <%s:%d>\",\n                           ar.short_src, ar.linedefined);\n    }\n    lua_concat(L, lua_gettop(L) - arg);\n  }\n  lua_concat(L, lua_gettop(L) - arg);\n  return 1;\n}\n\n\nstatic const luaL_Reg dblib[] = {\n  {\"debug\", db_debug},\n  {\"getfenv\", db_getfenv},\n  {\"gethook\", db_gethook},\n  {\"getinfo\", db_getinfo},\n  {\"getlocal\", db_getlocal},\n  {\"getregistry\", db_getregistry},\n  {\"getmetatable\", db_getmetatable},\n  {\"getupvalue\", db_getupvalue},\n  {\"setfenv\", db_setfenv},\n  {\"sethook\", db_sethook},\n  {\"setlocal\", db_setlocal},\n  {\"setmetatable\", db_setmetatable},\n  {\"setupvalue\", db_setupvalue},\n  {\"traceback\", db_errorfb},\n  {NULL, NULL}\n};\n\n\nLUALIB_API int luaopen_debug (lua_State *L) {\n  luaL_register(L, LUA_DBLIBNAME, dblib);\n  return 1;\n}\n\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.8/deps/lua/src/ldebug.c",
    "content": "/*\n** $Id: ldebug.c,v 2.29.1.6 2008/05/08 16:56:26 roberto Exp $\n** Debug Interface\n** See Copyright Notice in lua.h\n*/\n\n\n#include <stdarg.h>\n#include <stddef.h>\n#include <string.h>\n\n\n#define ldebug_c\n#define LUA_CORE\n\n#include \"lua.h\"\n\n#include \"lapi.h\"\n#include \"lcode.h\"\n#include \"ldebug.h\"\n#include \"ldo.h\"\n#include \"lfunc.h\"\n#include \"lobject.h\"\n#include \"lopcodes.h\"\n#include \"lstate.h\"\n#include \"lstring.h\"\n#include \"ltable.h\"\n#include \"ltm.h\"\n#include \"lvm.h\"\n\n\n\nstatic const char *getfuncname (lua_State *L, CallInfo *ci, const char **name);\n\n\nstatic int currentpc (lua_State *L, CallInfo *ci) {\n  if (!isLua(ci)) return -1;  /* function is not a Lua function? */\n  if (ci == L->ci)\n    ci->savedpc = L->savedpc;\n  return pcRel(ci->savedpc, ci_func(ci)->l.p);\n}\n\n\nstatic int currentline (lua_State *L, CallInfo *ci) {\n  int pc = currentpc(L, ci);\n  if (pc < 0)\n    return -1;  /* only active lua functions have current-line information */\n  else\n    return getline(ci_func(ci)->l.p, pc);\n}\n\n\n/*\n** this function can be called asynchronous (e.g. during a signal)\n*/\nLUA_API int lua_sethook (lua_State *L, lua_Hook func, int mask, int count) {\n  if (func == NULL || mask == 0) {  /* turn off hooks? */\n    mask = 0;\n    func = NULL;\n  }\n  L->hook = func;\n  L->basehookcount = count;\n  resethookcount(L);\n  L->hookmask = cast_byte(mask);\n  return 1;\n}\n\n\nLUA_API lua_Hook lua_gethook (lua_State *L) {\n  return L->hook;\n}\n\n\nLUA_API int lua_gethookmask (lua_State *L) {\n  return L->hookmask;\n}\n\n\nLUA_API int lua_gethookcount (lua_State *L) {\n  return L->basehookcount;\n}\n\n\nLUA_API int lua_getstack (lua_State *L, int level, lua_Debug *ar) {\n  int status;\n  CallInfo *ci;\n  lua_lock(L);\n  for (ci = L->ci; level > 0 && ci > L->base_ci; ci--) {\n    level--;\n    if (f_isLua(ci))  /* Lua function? */\n      level -= ci->tailcalls;  /* skip lost tail calls */\n  }\n  if (level == 0 && ci > L->base_ci) {  /* level found? */\n    status = 1;\n    ar->i_ci = cast_int(ci - L->base_ci);\n  }\n  else if (level < 0) {  /* level is of a lost tail call? */\n    status = 1;\n    ar->i_ci = 0;\n  }\n  else status = 0;  /* no such level */\n  lua_unlock(L);\n  return status;\n}\n\n\nstatic Proto *getluaproto (CallInfo *ci) {\n  return (isLua(ci) ? ci_func(ci)->l.p : NULL);\n}\n\n\nstatic const char *findlocal (lua_State *L, CallInfo *ci, int n) {\n  const char *name;\n  Proto *fp = getluaproto(ci);\n  if (fp && (name = luaF_getlocalname(fp, n, currentpc(L, ci))) != NULL)\n    return name;  /* is a local variable in a Lua function */\n  else {\n    StkId limit = (ci == L->ci) ? L->top : (ci+1)->func;\n    if (limit - ci->base >= n && n > 0)  /* is 'n' inside 'ci' stack? */\n      return \"(*temporary)\";\n    else\n      return NULL;\n  }\n}\n\n\nLUA_API const char *lua_getlocal (lua_State *L, const lua_Debug *ar, int n) {\n  CallInfo *ci = L->base_ci + ar->i_ci;\n  const char *name = findlocal(L, ci, n);\n  lua_lock(L);\n  if (name)\n      luaA_pushobject(L, ci->base + (n - 1));\n  lua_unlock(L);\n  return name;\n}\n\n\nLUA_API const char *lua_setlocal (lua_State *L, const lua_Debug *ar, int n) {\n  CallInfo *ci = L->base_ci + ar->i_ci;\n  const char *name = findlocal(L, ci, n);\n  lua_lock(L);\n  if (name)\n      setobjs2s(L, ci->base + (n - 1), L->top - 1);\n  L->top--;  /* pop value */\n  lua_unlock(L);\n  return name;\n}\n\n\nstatic void funcinfo (lua_Debug *ar, Closure *cl) {\n  if (cl->c.isC) {\n    ar->source = \"=[C]\";\n    ar->linedefined = -1;\n    ar->lastlinedefined = -1;\n    ar->what = \"C\";\n  }\n  else {\n    ar->source = getstr(cl->l.p->source);\n    ar->linedefined = cl->l.p->linedefined;\n    ar->lastlinedefined = cl->l.p->lastlinedefined;\n    ar->what = (ar->linedefined == 0) ? \"main\" : \"Lua\";\n  }\n  luaO_chunkid(ar->short_src, ar->source, LUA_IDSIZE);\n}\n\n\nstatic void info_tailcall (lua_Debug *ar) {\n  ar->name = ar->namewhat = \"\";\n  ar->what = \"tail\";\n  ar->lastlinedefined = ar->linedefined = ar->currentline = -1;\n  ar->source = \"=(tail call)\";\n  luaO_chunkid(ar->short_src, ar->source, LUA_IDSIZE);\n  ar->nups = 0;\n}\n\n\nstatic void collectvalidlines (lua_State *L, Closure *f) {\n  if (f == NULL || f->c.isC) {\n    setnilvalue(L->top);\n  }\n  else {\n    Table *t = luaH_new(L, 0, 0);\n    int *lineinfo = f->l.p->lineinfo;\n    int i;\n    for (i=0; i<f->l.p->sizelineinfo; i++)\n      setbvalue(luaH_setnum(L, t, lineinfo[i]), 1);\n    sethvalue(L, L->top, t); \n  }\n  incr_top(L);\n}\n\n\nstatic int auxgetinfo (lua_State *L, const char *what, lua_Debug *ar,\n                    Closure *f, CallInfo *ci) {\n  int status = 1;\n  if (f == NULL) {\n    info_tailcall(ar);\n    return status;\n  }\n  for (; *what; what++) {\n    switch (*what) {\n      case 'S': {\n        funcinfo(ar, f);\n        break;\n      }\n      case 'l': {\n        ar->currentline = (ci) ? currentline(L, ci) : -1;\n        break;\n      }\n      case 'u': {\n        ar->nups = f->c.nupvalues;\n        break;\n      }\n      case 'n': {\n        ar->namewhat = (ci) ? getfuncname(L, ci, &ar->name) : NULL;\n        if (ar->namewhat == NULL) {\n          ar->namewhat = \"\";  /* not found */\n          ar->name = NULL;\n        }\n        break;\n      }\n      case 'L':\n      case 'f':  /* handled by lua_getinfo */\n        break;\n      default: status = 0;  /* invalid option */\n    }\n  }\n  return status;\n}\n\n\nLUA_API int lua_getinfo (lua_State *L, const char *what, lua_Debug *ar) {\n  int status;\n  Closure *f = NULL;\n  CallInfo *ci = NULL;\n  lua_lock(L);\n  if (*what == '>') {\n    StkId func = L->top - 1;\n    luai_apicheck(L, ttisfunction(func));\n    what++;  /* skip the '>' */\n    f = clvalue(func);\n    L->top--;  /* pop function */\n  }\n  else if (ar->i_ci != 0) {  /* no tail call? */\n    ci = L->base_ci + ar->i_ci;\n    lua_assert(ttisfunction(ci->func));\n    f = clvalue(ci->func);\n  }\n  status = auxgetinfo(L, what, ar, f, ci);\n  if (strchr(what, 'f')) {\n    if (f == NULL) setnilvalue(L->top);\n    else setclvalue(L, L->top, f);\n    incr_top(L);\n  }\n  if (strchr(what, 'L'))\n    collectvalidlines(L, f);\n  lua_unlock(L);\n  return status;\n}\n\n\n/*\n** {======================================================\n** Symbolic Execution and code checker\n** =======================================================\n*/\n\n#define check(x)\t\tif (!(x)) return 0;\n\n#define checkjump(pt,pc)\tcheck(0 <= pc && pc < pt->sizecode)\n\n#define checkreg(pt,reg)\tcheck((reg) < (pt)->maxstacksize)\n\n\n\nstatic int precheck (const Proto *pt) {\n  check(pt->maxstacksize <= MAXSTACK);\n  check(pt->numparams+(pt->is_vararg & VARARG_HASARG) <= pt->maxstacksize);\n  check(!(pt->is_vararg & VARARG_NEEDSARG) ||\n              (pt->is_vararg & VARARG_HASARG));\n  check(pt->sizeupvalues <= pt->nups);\n  check(pt->sizelineinfo == pt->sizecode || pt->sizelineinfo == 0);\n  check(pt->sizecode > 0 && GET_OPCODE(pt->code[pt->sizecode-1]) == OP_RETURN);\n  return 1;\n}\n\n\n#define checkopenop(pt,pc)\tluaG_checkopenop((pt)->code[(pc)+1])\n\nint luaG_checkopenop (Instruction i) {\n  switch (GET_OPCODE(i)) {\n    case OP_CALL:\n    case OP_TAILCALL:\n    case OP_RETURN:\n    case OP_SETLIST: {\n      check(GETARG_B(i) == 0);\n      return 1;\n    }\n    default: return 0;  /* invalid instruction after an open call */\n  }\n}\n\n\nstatic int checkArgMode (const Proto *pt, int r, enum OpArgMask mode) {\n  switch (mode) {\n    case OpArgN: check(r == 0); break;\n    case OpArgU: break;\n    case OpArgR: checkreg(pt, r); break;\n    case OpArgK:\n      check(ISK(r) ? INDEXK(r) < pt->sizek : r < pt->maxstacksize);\n      break;\n  }\n  return 1;\n}\n\n\nstatic Instruction symbexec (const Proto *pt, int lastpc, int reg) {\n  int pc;\n  int last;  /* stores position of last instruction that changed `reg' */\n  last = pt->sizecode-1;  /* points to final return (a `neutral' instruction) */\n  check(precheck(pt));\n  for (pc = 0; pc < lastpc; pc++) {\n    Instruction i = pt->code[pc];\n    OpCode op = GET_OPCODE(i);\n    int a = GETARG_A(i);\n    int b = 0;\n    int c = 0;\n    check(op < NUM_OPCODES);\n    checkreg(pt, a);\n    switch (getOpMode(op)) {\n      case iABC: {\n        b = GETARG_B(i);\n        c = GETARG_C(i);\n        check(checkArgMode(pt, b, getBMode(op)));\n        check(checkArgMode(pt, c, getCMode(op)));\n        break;\n      }\n      case iABx: {\n        b = GETARG_Bx(i);\n        if (getBMode(op) == OpArgK) check(b < pt->sizek);\n        break;\n      }\n      case iAsBx: {\n        b = GETARG_sBx(i);\n        if (getBMode(op) == OpArgR) {\n          int dest = pc+1+b;\n          check(0 <= dest && dest < pt->sizecode);\n          if (dest > 0) {\n            int j;\n            /* check that it does not jump to a setlist count; this\n               is tricky, because the count from a previous setlist may\n               have the same value of an invalid setlist; so, we must\n               go all the way back to the first of them (if any) */\n            for (j = 0; j < dest; j++) {\n              Instruction d = pt->code[dest-1-j];\n              if (!(GET_OPCODE(d) == OP_SETLIST && GETARG_C(d) == 0)) break;\n            }\n            /* if 'j' is even, previous value is not a setlist (even if\n               it looks like one) */\n            check((j&1) == 0);\n          }\n        }\n        break;\n      }\n    }\n    if (testAMode(op)) {\n      if (a == reg) last = pc;  /* change register `a' */\n    }\n    if (testTMode(op)) {\n      check(pc+2 < pt->sizecode);  /* check skip */\n      check(GET_OPCODE(pt->code[pc+1]) == OP_JMP);\n    }\n    switch (op) {\n      case OP_LOADBOOL: {\n        if (c == 1) {  /* does it jump? */\n          check(pc+2 < pt->sizecode);  /* check its jump */\n          check(GET_OPCODE(pt->code[pc+1]) != OP_SETLIST ||\n                GETARG_C(pt->code[pc+1]) != 0);\n        }\n        break;\n      }\n      case OP_LOADNIL: {\n        if (a <= reg && reg <= b)\n          last = pc;  /* set registers from `a' to `b' */\n        break;\n      }\n      case OP_GETUPVAL:\n      case OP_SETUPVAL: {\n        check(b < pt->nups);\n        break;\n      }\n      case OP_GETGLOBAL:\n      case OP_SETGLOBAL: {\n        check(ttisstring(&pt->k[b]));\n        break;\n      }\n      case OP_SELF: {\n        checkreg(pt, a+1);\n        if (reg == a+1) last = pc;\n        break;\n      }\n      case OP_CONCAT: {\n        check(b < c);  /* at least two operands */\n        break;\n      }\n      case OP_TFORLOOP: {\n        check(c >= 1);  /* at least one result (control variable) */\n        checkreg(pt, a+2+c);  /* space for results */\n        if (reg >= a+2) last = pc;  /* affect all regs above its base */\n        break;\n      }\n      case OP_FORLOOP:\n      case OP_FORPREP:\n        checkreg(pt, a+3);\n        /* go through */\n      case OP_JMP: {\n        int dest = pc+1+b;\n        /* not full check and jump is forward and do not skip `lastpc'? */\n        if (reg != NO_REG && pc < dest && dest <= lastpc)\n          pc += b;  /* do the jump */\n        break;\n      }\n      case OP_CALL:\n      case OP_TAILCALL: {\n        if (b != 0) {\n          checkreg(pt, a+b-1);\n        }\n        c--;  /* c = num. returns */\n        if (c == LUA_MULTRET) {\n          check(checkopenop(pt, pc));\n        }\n        else if (c != 0)\n          checkreg(pt, a+c-1);\n        if (reg >= a) last = pc;  /* affect all registers above base */\n        break;\n      }\n      case OP_RETURN: {\n        b--;  /* b = num. returns */\n        if (b > 0) checkreg(pt, a+b-1);\n        break;\n      }\n      case OP_SETLIST: {\n        if (b > 0) checkreg(pt, a + b);\n        if (c == 0) {\n          pc++;\n          check(pc < pt->sizecode - 1);\n        }\n        break;\n      }\n      case OP_CLOSURE: {\n        int nup, j;\n        check(b < pt->sizep);\n        nup = pt->p[b]->nups;\n        check(pc + nup < pt->sizecode);\n        for (j = 1; j <= nup; j++) {\n          OpCode op1 = GET_OPCODE(pt->code[pc + j]);\n          check(op1 == OP_GETUPVAL || op1 == OP_MOVE);\n        }\n        if (reg != NO_REG)  /* tracing? */\n          pc += nup;  /* do not 'execute' these pseudo-instructions */\n        break;\n      }\n      case OP_VARARG: {\n        check((pt->is_vararg & VARARG_ISVARARG) &&\n             !(pt->is_vararg & VARARG_NEEDSARG));\n        b--;\n        if (b == LUA_MULTRET) check(checkopenop(pt, pc));\n        checkreg(pt, a+b-1);\n        break;\n      }\n      default: break;\n    }\n  }\n  return pt->code[last];\n}\n\n#undef check\n#undef checkjump\n#undef checkreg\n\n/* }====================================================== */\n\n\nint luaG_checkcode (const Proto *pt) {\n  return (symbexec(pt, pt->sizecode, NO_REG) != 0);\n}\n\n\nstatic const char *kname (Proto *p, int c) {\n  if (ISK(c) && ttisstring(&p->k[INDEXK(c)]))\n    return svalue(&p->k[INDEXK(c)]);\n  else\n    return \"?\";\n}\n\n\nstatic const char *getobjname (lua_State *L, CallInfo *ci, int stackpos,\n                               const char **name) {\n  if (isLua(ci)) {  /* a Lua function? */\n    Proto *p = ci_func(ci)->l.p;\n    int pc = currentpc(L, ci);\n    Instruction i;\n    *name = luaF_getlocalname(p, stackpos+1, pc);\n    if (*name)  /* is a local? */\n      return \"local\";\n    i = symbexec(p, pc, stackpos);  /* try symbolic execution */\n    lua_assert(pc != -1);\n    switch (GET_OPCODE(i)) {\n      case OP_GETGLOBAL: {\n        int g = GETARG_Bx(i);  /* global index */\n        lua_assert(ttisstring(&p->k[g]));\n        *name = svalue(&p->k[g]);\n        return \"global\";\n      }\n      case OP_MOVE: {\n        int a = GETARG_A(i);\n        int b = GETARG_B(i);  /* move from `b' to `a' */\n        if (b < a)\n          return getobjname(L, ci, b, name);  /* get name for `b' */\n        break;\n      }\n      case OP_GETTABLE: {\n        int k = GETARG_C(i);  /* key index */\n        *name = kname(p, k);\n        return \"field\";\n      }\n      case OP_GETUPVAL: {\n        int u = GETARG_B(i);  /* upvalue index */\n        *name = p->upvalues ? getstr(p->upvalues[u]) : \"?\";\n        return \"upvalue\";\n      }\n      case OP_SELF: {\n        int k = GETARG_C(i);  /* key index */\n        *name = kname(p, k);\n        return \"method\";\n      }\n      default: break;\n    }\n  }\n  return NULL;  /* no useful name found */\n}\n\n\nstatic const char *getfuncname (lua_State *L, CallInfo *ci, const char **name) {\n  Instruction i;\n  if ((isLua(ci) && ci->tailcalls > 0) || !isLua(ci - 1))\n    return NULL;  /* calling function is not Lua (or is unknown) */\n  ci--;  /* calling function */\n  i = ci_func(ci)->l.p->code[currentpc(L, ci)];\n  if (GET_OPCODE(i) == OP_CALL || GET_OPCODE(i) == OP_TAILCALL ||\n      GET_OPCODE(i) == OP_TFORLOOP)\n    return getobjname(L, ci, GETARG_A(i), name);\n  else\n    return NULL;  /* no useful name can be found */\n}\n\n\n/* only ANSI way to check whether a pointer points to an array */\nstatic int isinstack (CallInfo *ci, const TValue *o) {\n  StkId p;\n  for (p = ci->base; p < ci->top; p++)\n    if (o == p) return 1;\n  return 0;\n}\n\n\nvoid luaG_typeerror (lua_State *L, const TValue *o, const char *op) {\n  const char *name = NULL;\n  const char *t = luaT_typenames[ttype(o)];\n  const char *kind = (isinstack(L->ci, o)) ?\n                         getobjname(L, L->ci, cast_int(o - L->base), &name) :\n                         NULL;\n  if (kind)\n    luaG_runerror(L, \"attempt to %s %s \" LUA_QS \" (a %s value)\",\n                op, kind, name, t);\n  else\n    luaG_runerror(L, \"attempt to %s a %s value\", op, t);\n}\n\n\nvoid luaG_concaterror (lua_State *L, StkId p1, StkId p2) {\n  if (ttisstring(p1) || ttisnumber(p1)) p1 = p2;\n  lua_assert(!ttisstring(p1) && !ttisnumber(p1));\n  luaG_typeerror(L, p1, \"concatenate\");\n}\n\n\nvoid luaG_aritherror (lua_State *L, const TValue *p1, const TValue *p2) {\n  TValue temp;\n  if (luaV_tonumber(p1, &temp) == NULL)\n    p2 = p1;  /* first operand is wrong */\n  luaG_typeerror(L, p2, \"perform arithmetic on\");\n}\n\n\nint luaG_ordererror (lua_State *L, const TValue *p1, const TValue *p2) {\n  const char *t1 = luaT_typenames[ttype(p1)];\n  const char *t2 = luaT_typenames[ttype(p2)];\n  if (t1[2] == t2[2])\n    luaG_runerror(L, \"attempt to compare two %s values\", t1);\n  else\n    luaG_runerror(L, \"attempt to compare %s with %s\", t1, t2);\n  return 0;\n}\n\n\nstatic void addinfo (lua_State *L, const char *msg) {\n  CallInfo *ci = L->ci;\n  if (isLua(ci)) {  /* is Lua code? */\n    char buff[LUA_IDSIZE];  /* add file:line information */\n    int line = currentline(L, ci);\n    luaO_chunkid(buff, getstr(getluaproto(ci)->source), LUA_IDSIZE);\n    luaO_pushfstring(L, \"%s:%d: %s\", buff, line, msg);\n  }\n}\n\n\nvoid luaG_errormsg (lua_State *L) {\n  if (L->errfunc != 0) {  /* is there an error handling function? */\n    StkId errfunc = restorestack(L, L->errfunc);\n    if (!ttisfunction(errfunc)) luaD_throw(L, LUA_ERRERR);\n    setobjs2s(L, L->top, L->top - 1);  /* move argument */\n    setobjs2s(L, L->top - 1, errfunc);  /* push function */\n    incr_top(L);\n    luaD_call(L, L->top - 2, 1);  /* call it */\n  }\n  luaD_throw(L, LUA_ERRRUN);\n}\n\n\nvoid luaG_runerror (lua_State *L, const char *fmt, ...) {\n  va_list argp;\n  va_start(argp, fmt);\n  addinfo(L, luaO_pushvfstring(L, fmt, argp));\n  va_end(argp);\n  luaG_errormsg(L);\n}\n\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.8/deps/lua/src/ldebug.h",
    "content": "/*\n** $Id: ldebug.h,v 2.3.1.1 2007/12/27 13:02:25 roberto Exp $\n** Auxiliary functions from Debug Interface module\n** See Copyright Notice in lua.h\n*/\n\n#ifndef ldebug_h\n#define ldebug_h\n\n\n#include \"lstate.h\"\n\n\n#define pcRel(pc, p)\t(cast(int, (pc) - (p)->code) - 1)\n\n#define getline(f,pc)\t(((f)->lineinfo) ? (f)->lineinfo[pc] : 0)\n\n#define resethookcount(L)\t(L->hookcount = L->basehookcount)\n\n\nLUAI_FUNC void luaG_typeerror (lua_State *L, const TValue *o,\n                                             const char *opname);\nLUAI_FUNC void luaG_concaterror (lua_State *L, StkId p1, StkId p2);\nLUAI_FUNC void luaG_aritherror (lua_State *L, const TValue *p1,\n                                              const TValue *p2);\nLUAI_FUNC int luaG_ordererror (lua_State *L, const TValue *p1,\n                                             const TValue *p2);\nLUAI_FUNC void luaG_runerror (lua_State *L, const char *fmt, ...);\nLUAI_FUNC void luaG_errormsg (lua_State *L);\nLUAI_FUNC int luaG_checkcode (const Proto *pt);\nLUAI_FUNC int luaG_checkopenop (Instruction i);\n\n#endif\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.8/deps/lua/src/ldo.c",
    "content": "/*\n** $Id: ldo.c,v 2.38.1.4 2012/01/18 02:27:10 roberto Exp $\n** Stack and Call structure of Lua\n** See Copyright Notice in lua.h\n*/\n\n\n#include <setjmp.h>\n#include <stdlib.h>\n#include <string.h>\n\n#define ldo_c\n#define LUA_CORE\n\n#include \"lua.h\"\n\n#include \"ldebug.h\"\n#include \"ldo.h\"\n#include \"lfunc.h\"\n#include \"lgc.h\"\n#include \"lmem.h\"\n#include \"lobject.h\"\n#include \"lopcodes.h\"\n#include \"lparser.h\"\n#include \"lstate.h\"\n#include \"lstring.h\"\n#include \"ltable.h\"\n#include \"ltm.h\"\n#include \"lundump.h\"\n#include \"lvm.h\"\n#include \"lzio.h\"\n\n\n\n\n/*\n** {======================================================\n** Error-recovery functions\n** =======================================================\n*/\n\n\n/* chain list of long jump buffers */\nstruct lua_longjmp {\n  struct lua_longjmp *previous;\n  luai_jmpbuf b;\n  volatile int status;  /* error code */\n};\n\n\nvoid luaD_seterrorobj (lua_State *L, int errcode, StkId oldtop) {\n  switch (errcode) {\n    case LUA_ERRMEM: {\n      setsvalue2s(L, oldtop, luaS_newliteral(L, MEMERRMSG));\n      break;\n    }\n    case LUA_ERRERR: {\n      setsvalue2s(L, oldtop, luaS_newliteral(L, \"error in error handling\"));\n      break;\n    }\n    case LUA_ERRSYNTAX:\n    case LUA_ERRRUN: {\n      setobjs2s(L, oldtop, L->top - 1);  /* error message on current top */\n      break;\n    }\n  }\n  L->top = oldtop + 1;\n}\n\n\nstatic void restore_stack_limit (lua_State *L) {\n  lua_assert(L->stack_last - L->stack == L->stacksize - EXTRA_STACK - 1);\n  if (L->size_ci > LUAI_MAXCALLS) {  /* there was an overflow? */\n    int inuse = cast_int(L->ci - L->base_ci);\n    if (inuse + 1 < LUAI_MAXCALLS)  /* can `undo' overflow? */\n      luaD_reallocCI(L, LUAI_MAXCALLS);\n  }\n}\n\n\nstatic void resetstack (lua_State *L, int status) {\n  L->ci = L->base_ci;\n  L->base = L->ci->base;\n  luaF_close(L, L->base);  /* close eventual pending closures */\n  luaD_seterrorobj(L, status, L->base);\n  L->nCcalls = L->baseCcalls;\n  L->allowhook = 1;\n  restore_stack_limit(L);\n  L->errfunc = 0;\n  L->errorJmp = NULL;\n}\n\n\nvoid luaD_throw (lua_State *L, int errcode) {\n  if (L->errorJmp) {\n    L->errorJmp->status = errcode;\n    LUAI_THROW(L, L->errorJmp);\n  }\n  else {\n    L->status = cast_byte(errcode);\n    if (G(L)->panic) {\n      resetstack(L, errcode);\n      lua_unlock(L);\n      G(L)->panic(L);\n    }\n    exit(EXIT_FAILURE);\n  }\n}\n\n\nint luaD_rawrunprotected (lua_State *L, Pfunc f, void *ud) {\n  struct lua_longjmp lj;\n  lj.status = 0;\n  lj.previous = L->errorJmp;  /* chain new error handler */\n  L->errorJmp = &lj;\n  LUAI_TRY(L, &lj,\n    (*f)(L, ud);\n  );\n  L->errorJmp = lj.previous;  /* restore old error handler */\n  return lj.status;\n}\n\n/* }====================================================== */\n\n\nstatic void correctstack (lua_State *L, TValue *oldstack) {\n  CallInfo *ci;\n  GCObject *up;\n  L->top = (L->top - oldstack) + L->stack;\n  for (up = L->openupval; up != NULL; up = up->gch.next)\n    gco2uv(up)->v = (gco2uv(up)->v - oldstack) + L->stack;\n  for (ci = L->base_ci; ci <= L->ci; ci++) {\n    ci->top = (ci->top - oldstack) + L->stack;\n    ci->base = (ci->base - oldstack) + L->stack;\n    ci->func = (ci->func - oldstack) + L->stack;\n  }\n  L->base = (L->base - oldstack) + L->stack;\n}\n\n\nvoid luaD_reallocstack (lua_State *L, int newsize) {\n  TValue *oldstack = L->stack;\n  int realsize = newsize + 1 + EXTRA_STACK;\n  lua_assert(L->stack_last - L->stack == L->stacksize - EXTRA_STACK - 1);\n  luaM_reallocvector(L, L->stack, L->stacksize, realsize, TValue);\n  L->stacksize = realsize;\n  L->stack_last = L->stack+newsize;\n  correctstack(L, oldstack);\n}\n\n\nvoid luaD_reallocCI (lua_State *L, int newsize) {\n  CallInfo *oldci = L->base_ci;\n  luaM_reallocvector(L, L->base_ci, L->size_ci, newsize, CallInfo);\n  L->size_ci = newsize;\n  L->ci = (L->ci - oldci) + L->base_ci;\n  L->end_ci = L->base_ci + L->size_ci - 1;\n}\n\n\nvoid luaD_growstack (lua_State *L, int n) {\n  if (n <= L->stacksize)  /* double size is enough? */\n    luaD_reallocstack(L, 2*L->stacksize);\n  else\n    luaD_reallocstack(L, L->stacksize + n);\n}\n\n\nstatic CallInfo *growCI (lua_State *L) {\n  if (L->size_ci > LUAI_MAXCALLS)  /* overflow while handling overflow? */\n    luaD_throw(L, LUA_ERRERR);\n  else {\n    luaD_reallocCI(L, 2*L->size_ci);\n    if (L->size_ci > LUAI_MAXCALLS)\n      luaG_runerror(L, \"stack overflow\");\n  }\n  return ++L->ci;\n}\n\n\nvoid luaD_callhook (lua_State *L, int event, int line) {\n  lua_Hook hook = L->hook;\n  if (hook && L->allowhook) {\n    ptrdiff_t top = savestack(L, L->top);\n    ptrdiff_t ci_top = savestack(L, L->ci->top);\n    lua_Debug ar;\n    ar.event = event;\n    ar.currentline = line;\n    if (event == LUA_HOOKTAILRET)\n      ar.i_ci = 0;  /* tail call; no debug information about it */\n    else\n      ar.i_ci = cast_int(L->ci - L->base_ci);\n    luaD_checkstack(L, LUA_MINSTACK);  /* ensure minimum stack size */\n    L->ci->top = L->top + LUA_MINSTACK;\n    lua_assert(L->ci->top <= L->stack_last);\n    L->allowhook = 0;  /* cannot call hooks inside a hook */\n    lua_unlock(L);\n    (*hook)(L, &ar);\n    lua_lock(L);\n    lua_assert(!L->allowhook);\n    L->allowhook = 1;\n    L->ci->top = restorestack(L, ci_top);\n    L->top = restorestack(L, top);\n  }\n}\n\n\nstatic StkId adjust_varargs (lua_State *L, Proto *p, int actual) {\n  int i;\n  int nfixargs = p->numparams;\n  Table *htab = NULL;\n  StkId base, fixed;\n  for (; actual < nfixargs; ++actual)\n    setnilvalue(L->top++);\n#if defined(LUA_COMPAT_VARARG)\n  if (p->is_vararg & VARARG_NEEDSARG) { /* compat. with old-style vararg? */\n    int nvar = actual - nfixargs;  /* number of extra arguments */\n    lua_assert(p->is_vararg & VARARG_HASARG);\n    luaC_checkGC(L);\n    luaD_checkstack(L, p->maxstacksize);\n    htab = luaH_new(L, nvar, 1);  /* create `arg' table */\n    for (i=0; i<nvar; i++)  /* put extra arguments into `arg' table */\n      setobj2n(L, luaH_setnum(L, htab, i+1), L->top - nvar + i);\n    /* store counter in field `n' */\n    setnvalue(luaH_setstr(L, htab, luaS_newliteral(L, \"n\")), cast_num(nvar));\n  }\n#endif\n  /* move fixed parameters to final position */\n  fixed = L->top - actual;  /* first fixed argument */\n  base = L->top;  /* final position of first argument */\n  for (i=0; i<nfixargs; i++) {\n    setobjs2s(L, L->top++, fixed+i);\n    setnilvalue(fixed+i);\n  }\n  /* add `arg' parameter */\n  if (htab) {\n    sethvalue(L, L->top++, htab);\n    lua_assert(iswhite(obj2gco(htab)));\n  }\n  return base;\n}\n\n\nstatic StkId tryfuncTM (lua_State *L, StkId func) {\n  const TValue *tm = luaT_gettmbyobj(L, func, TM_CALL);\n  StkId p;\n  ptrdiff_t funcr = savestack(L, func);\n  if (!ttisfunction(tm))\n    luaG_typeerror(L, func, \"call\");\n  /* Open a hole inside the stack at `func' */\n  for (p = L->top; p > func; p--) setobjs2s(L, p, p-1);\n  incr_top(L);\n  func = restorestack(L, funcr);  /* previous call may change stack */\n  setobj2s(L, func, tm);  /* tag method is the new function to be called */\n  return func;\n}\n\n\n\n#define inc_ci(L) \\\n  ((L->ci == L->end_ci) ? growCI(L) : \\\n   (condhardstacktests(luaD_reallocCI(L, L->size_ci)), ++L->ci))\n\n\nint luaD_precall (lua_State *L, StkId func, int nresults) {\n  LClosure *cl;\n  ptrdiff_t funcr;\n  if (!ttisfunction(func)) /* `func' is not a function? */\n    func = tryfuncTM(L, func);  /* check the `function' tag method */\n  funcr = savestack(L, func);\n  cl = &clvalue(func)->l;\n  L->ci->savedpc = L->savedpc;\n  if (!cl->isC) {  /* Lua function? prepare its call */\n    CallInfo *ci;\n    StkId st, base;\n    Proto *p = cl->p;\n    luaD_checkstack(L, p->maxstacksize);\n    func = restorestack(L, funcr);\n    if (!p->is_vararg) {  /* no varargs? */\n      base = func + 1;\n      if (L->top > base + p->numparams)\n        L->top = base + p->numparams;\n    }\n    else {  /* vararg function */\n      int nargs = cast_int(L->top - func) - 1;\n      base = adjust_varargs(L, p, nargs);\n      func = restorestack(L, funcr);  /* previous call may change the stack */\n    }\n    ci = inc_ci(L);  /* now `enter' new function */\n    ci->func = func;\n    L->base = ci->base = base;\n    ci->top = L->base + p->maxstacksize;\n    lua_assert(ci->top <= L->stack_last);\n    L->savedpc = p->code;  /* starting point */\n    ci->tailcalls = 0;\n    ci->nresults = nresults;\n    for (st = L->top; st < ci->top; st++)\n      setnilvalue(st);\n    L->top = ci->top;\n    if (L->hookmask & LUA_MASKCALL) {\n      L->savedpc++;  /* hooks assume 'pc' is already incremented */\n      luaD_callhook(L, LUA_HOOKCALL, -1);\n      L->savedpc--;  /* correct 'pc' */\n    }\n    return PCRLUA;\n  }\n  else {  /* if is a C function, call it */\n    CallInfo *ci;\n    int n;\n    luaD_checkstack(L, LUA_MINSTACK);  /* ensure minimum stack size */\n    ci = inc_ci(L);  /* now `enter' new function */\n    ci->func = restorestack(L, funcr);\n    L->base = ci->base = ci->func + 1;\n    ci->top = L->top + LUA_MINSTACK;\n    lua_assert(ci->top <= L->stack_last);\n    ci->nresults = nresults;\n    if (L->hookmask & LUA_MASKCALL)\n      luaD_callhook(L, LUA_HOOKCALL, -1);\n    lua_unlock(L);\n    n = (*curr_func(L)->c.f)(L);  /* do the actual call */\n    lua_lock(L);\n    if (n < 0)  /* yielding? */\n      return PCRYIELD;\n    else {\n      luaD_poscall(L, L->top - n);\n      return PCRC;\n    }\n  }\n}\n\n\nstatic StkId callrethooks (lua_State *L, StkId firstResult) {\n  ptrdiff_t fr = savestack(L, firstResult);  /* next call may change stack */\n  luaD_callhook(L, LUA_HOOKRET, -1);\n  if (f_isLua(L->ci)) {  /* Lua function? */\n    while ((L->hookmask & LUA_MASKRET) && L->ci->tailcalls--) /* tail calls */\n      luaD_callhook(L, LUA_HOOKTAILRET, -1);\n  }\n  return restorestack(L, fr);\n}\n\n\nint luaD_poscall (lua_State *L, StkId firstResult) {\n  StkId res;\n  int wanted, i;\n  CallInfo *ci;\n  if (L->hookmask & LUA_MASKRET)\n    firstResult = callrethooks(L, firstResult);\n  ci = L->ci--;\n  res = ci->func;  /* res == final position of 1st result */\n  wanted = ci->nresults;\n  L->base = (ci - 1)->base;  /* restore base */\n  L->savedpc = (ci - 1)->savedpc;  /* restore savedpc */\n  /* move results to correct place */\n  for (i = wanted; i != 0 && firstResult < L->top; i--)\n    setobjs2s(L, res++, firstResult++);\n  while (i-- > 0)\n    setnilvalue(res++);\n  L->top = res;\n  return (wanted - LUA_MULTRET);  /* 0 iff wanted == LUA_MULTRET */\n}\n\n\n/*\n** Call a function (C or Lua). The function to be called is at *func.\n** The arguments are on the stack, right after the function.\n** When returns, all the results are on the stack, starting at the original\n** function position.\n*/ \nvoid luaD_call (lua_State *L, StkId func, int nResults) {\n  if (++L->nCcalls >= LUAI_MAXCCALLS) {\n    if (L->nCcalls == LUAI_MAXCCALLS)\n      luaG_runerror(L, \"C stack overflow\");\n    else if (L->nCcalls >= (LUAI_MAXCCALLS + (LUAI_MAXCCALLS>>3)))\n      luaD_throw(L, LUA_ERRERR);  /* error while handing stack error */\n  }\n  if (luaD_precall(L, func, nResults) == PCRLUA)  /* is a Lua function? */\n    luaV_execute(L, 1);  /* call it */\n  L->nCcalls--;\n  luaC_checkGC(L);\n}\n\n\nstatic void resume (lua_State *L, void *ud) {\n  StkId firstArg = cast(StkId, ud);\n  CallInfo *ci = L->ci;\n  if (L->status == 0) {  /* start coroutine? */\n    lua_assert(ci == L->base_ci && firstArg > L->base);\n    if (luaD_precall(L, firstArg - 1, LUA_MULTRET) != PCRLUA)\n      return;\n  }\n  else {  /* resuming from previous yield */\n    lua_assert(L->status == LUA_YIELD);\n    L->status = 0;\n    if (!f_isLua(ci)) {  /* `common' yield? */\n      /* finish interrupted execution of `OP_CALL' */\n      lua_assert(GET_OPCODE(*((ci-1)->savedpc - 1)) == OP_CALL ||\n                 GET_OPCODE(*((ci-1)->savedpc - 1)) == OP_TAILCALL);\n      if (luaD_poscall(L, firstArg))  /* complete it... */\n        L->top = L->ci->top;  /* and correct top if not multiple results */\n    }\n    else  /* yielded inside a hook: just continue its execution */\n      L->base = L->ci->base;\n  }\n  luaV_execute(L, cast_int(L->ci - L->base_ci));\n}\n\n\nstatic int resume_error (lua_State *L, const char *msg) {\n  L->top = L->ci->base;\n  setsvalue2s(L, L->top, luaS_new(L, msg));\n  incr_top(L);\n  lua_unlock(L);\n  return LUA_ERRRUN;\n}\n\n\nLUA_API int lua_resume (lua_State *L, int nargs) {\n  int status;\n  lua_lock(L);\n  if (L->status != LUA_YIELD && (L->status != 0 || L->ci != L->base_ci))\n      return resume_error(L, \"cannot resume non-suspended coroutine\");\n  if (L->nCcalls >= LUAI_MAXCCALLS)\n    return resume_error(L, \"C stack overflow\");\n  luai_userstateresume(L, nargs);\n  lua_assert(L->errfunc == 0);\n  L->baseCcalls = ++L->nCcalls;\n  status = luaD_rawrunprotected(L, resume, L->top - nargs);\n  if (status != 0) {  /* error? */\n    L->status = cast_byte(status);  /* mark thread as `dead' */\n    luaD_seterrorobj(L, status, L->top);\n    L->ci->top = L->top;\n  }\n  else {\n    lua_assert(L->nCcalls == L->baseCcalls);\n    status = L->status;\n  }\n  --L->nCcalls;\n  lua_unlock(L);\n  return status;\n}\n\n\nLUA_API int lua_yield (lua_State *L, int nresults) {\n  luai_userstateyield(L, nresults);\n  lua_lock(L);\n  if (L->nCcalls > L->baseCcalls)\n    luaG_runerror(L, \"attempt to yield across metamethod/C-call boundary\");\n  L->base = L->top - nresults;  /* protect stack slots below */\n  L->status = LUA_YIELD;\n  lua_unlock(L);\n  return -1;\n}\n\n\nint luaD_pcall (lua_State *L, Pfunc func, void *u,\n                ptrdiff_t old_top, ptrdiff_t ef) {\n  int status;\n  unsigned short oldnCcalls = L->nCcalls;\n  ptrdiff_t old_ci = saveci(L, L->ci);\n  lu_byte old_allowhooks = L->allowhook;\n  ptrdiff_t old_errfunc = L->errfunc;\n  L->errfunc = ef;\n  status = luaD_rawrunprotected(L, func, u);\n  if (status != 0) {  /* an error occurred? */\n    StkId oldtop = restorestack(L, old_top);\n    luaF_close(L, oldtop);  /* close eventual pending closures */\n    luaD_seterrorobj(L, status, oldtop);\n    L->nCcalls = oldnCcalls;\n    L->ci = restoreci(L, old_ci);\n    L->base = L->ci->base;\n    L->savedpc = L->ci->savedpc;\n    L->allowhook = old_allowhooks;\n    restore_stack_limit(L);\n  }\n  L->errfunc = old_errfunc;\n  return status;\n}\n\n\n\n/*\n** Execute a protected parser.\n*/\nstruct SParser {  /* data to `f_parser' */\n  ZIO *z;\n  Mbuffer buff;  /* buffer to be used by the scanner */\n  const char *name;\n};\n\nstatic void f_parser (lua_State *L, void *ud) {\n  int i;\n  Proto *tf;\n  Closure *cl;\n  struct SParser *p = cast(struct SParser *, ud);\n  int c = luaZ_lookahead(p->z);\n  luaC_checkGC(L);\n  tf = (luaY_parser)(L, p->z,\n                                                             &p->buff, p->name);\n  cl = luaF_newLclosure(L, tf->nups, hvalue(gt(L)));\n  cl->l.p = tf;\n  for (i = 0; i < tf->nups; i++)  /* initialize eventual upvalues */\n    cl->l.upvals[i] = luaF_newupval(L);\n  setclvalue(L, L->top, cl);\n  incr_top(L);\n}\n\n\nint luaD_protectedparser (lua_State *L, ZIO *z, const char *name) {\n  struct SParser p;\n  int status;\n  p.z = z; p.name = name;\n  luaZ_initbuffer(L, &p.buff);\n  status = luaD_pcall(L, f_parser, &p, savestack(L, L->top), L->errfunc);\n  luaZ_freebuffer(L, &p.buff);\n  return status;\n}\n\n\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.8/deps/lua/src/ldo.h",
    "content": "/*\n** $Id: ldo.h,v 2.7.1.1 2007/12/27 13:02:25 roberto Exp $\n** Stack and Call structure of Lua\n** See Copyright Notice in lua.h\n*/\n\n#ifndef ldo_h\n#define ldo_h\n\n\n#include \"lobject.h\"\n#include \"lstate.h\"\n#include \"lzio.h\"\n\n\n#define luaD_checkstack(L,n)\t\\\n  if ((char *)L->stack_last - (char *)L->top <= (n)*(int)sizeof(TValue)) \\\n    luaD_growstack(L, n); \\\n  else condhardstacktests(luaD_reallocstack(L, L->stacksize - EXTRA_STACK - 1));\n\n\n#define incr_top(L) {luaD_checkstack(L,1); L->top++;}\n\n#define savestack(L,p)\t\t((char *)(p) - (char *)L->stack)\n#define restorestack(L,n)\t((TValue *)((char *)L->stack + (n)))\n\n#define saveci(L,p)\t\t((char *)(p) - (char *)L->base_ci)\n#define restoreci(L,n)\t\t((CallInfo *)((char *)L->base_ci + (n)))\n\n\n/* results from luaD_precall */\n#define PCRLUA\t\t0\t/* initiated a call to a Lua function */\n#define PCRC\t\t1\t/* did a call to a C function */\n#define PCRYIELD\t2\t/* C funtion yielded */\n\n\n/* type of protected functions, to be ran by `runprotected' */\ntypedef void (*Pfunc) (lua_State *L, void *ud);\n\nLUAI_FUNC int luaD_protectedparser (lua_State *L, ZIO *z, const char *name);\nLUAI_FUNC void luaD_callhook (lua_State *L, int event, int line);\nLUAI_FUNC int luaD_precall (lua_State *L, StkId func, int nresults);\nLUAI_FUNC void luaD_call (lua_State *L, StkId func, int nResults);\nLUAI_FUNC int luaD_pcall (lua_State *L, Pfunc func, void *u,\n                                        ptrdiff_t oldtop, ptrdiff_t ef);\nLUAI_FUNC int luaD_poscall (lua_State *L, StkId firstResult);\nLUAI_FUNC void luaD_reallocCI (lua_State *L, int newsize);\nLUAI_FUNC void luaD_reallocstack (lua_State *L, int newsize);\nLUAI_FUNC void luaD_growstack (lua_State *L, int n);\n\nLUAI_FUNC void luaD_throw (lua_State *L, int errcode);\nLUAI_FUNC int luaD_rawrunprotected (lua_State *L, Pfunc f, void *ud);\n\nLUAI_FUNC void luaD_seterrorobj (lua_State *L, int errcode, StkId oldtop);\n\n#endif\n\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.8/deps/lua/src/ldump.c",
    "content": "/*\n** $Id: ldump.c,v 2.8.1.1 2007/12/27 13:02:25 roberto Exp $\n** save precompiled Lua chunks\n** See Copyright Notice in lua.h\n*/\n\n#include <stddef.h>\n\n#define ldump_c\n#define LUA_CORE\n\n#include \"lua.h\"\n\n#include \"lobject.h\"\n#include \"lstate.h\"\n#include \"lundump.h\"\n\ntypedef struct {\n lua_State* L;\n lua_Writer writer;\n void* data;\n int strip;\n int status;\n} DumpState;\n\n#define DumpMem(b,n,size,D)\tDumpBlock(b,(n)*(size),D)\n#define DumpVar(x,D)\t \tDumpMem(&x,1,sizeof(x),D)\n\nstatic void DumpBlock(const void* b, size_t size, DumpState* D)\n{\n if (D->status==0)\n {\n  lua_unlock(D->L);\n  D->status=(*D->writer)(D->L,b,size,D->data);\n  lua_lock(D->L);\n }\n}\n\nstatic void DumpChar(int y, DumpState* D)\n{\n char x=(char)y;\n DumpVar(x,D);\n}\n\nstatic void DumpInt(int x, DumpState* D)\n{\n DumpVar(x,D);\n}\n\nstatic void DumpNumber(lua_Number x, DumpState* D)\n{\n DumpVar(x,D);\n}\n\nstatic void DumpVector(const void* b, int n, size_t size, DumpState* D)\n{\n DumpInt(n,D);\n DumpMem(b,n,size,D);\n}\n\nstatic void DumpString(const TString* s, DumpState* D)\n{\n if (s==NULL || getstr(s)==NULL)\n {\n  size_t size=0;\n  DumpVar(size,D);\n }\n else\n {\n  size_t size=s->tsv.len+1;\t\t/* include trailing '\\0' */\n  DumpVar(size,D);\n  DumpBlock(getstr(s),size,D);\n }\n}\n\n#define DumpCode(f,D)\t DumpVector(f->code,f->sizecode,sizeof(Instruction),D)\n\nstatic void DumpFunction(const Proto* f, const TString* p, DumpState* D);\n\nstatic void DumpConstants(const Proto* f, DumpState* D)\n{\n int i,n=f->sizek;\n DumpInt(n,D);\n for (i=0; i<n; i++)\n {\n  const TValue* o=&f->k[i];\n  DumpChar(ttype(o),D);\n  switch (ttype(o))\n  {\n   case LUA_TNIL:\n\tbreak;\n   case LUA_TBOOLEAN:\n\tDumpChar(bvalue(o),D);\n\tbreak;\n   case LUA_TNUMBER:\n\tDumpNumber(nvalue(o),D);\n\tbreak;\n   case LUA_TSTRING:\n\tDumpString(rawtsvalue(o),D);\n\tbreak;\n   default:\n\tlua_assert(0);\t\t\t/* cannot happen */\n\tbreak;\n  }\n }\n n=f->sizep;\n DumpInt(n,D);\n for (i=0; i<n; i++) DumpFunction(f->p[i],f->source,D);\n}\n\nstatic void DumpDebug(const Proto* f, DumpState* D)\n{\n int i,n;\n n= (D->strip) ? 0 : f->sizelineinfo;\n DumpVector(f->lineinfo,n,sizeof(int),D);\n n= (D->strip) ? 0 : f->sizelocvars;\n DumpInt(n,D);\n for (i=0; i<n; i++)\n {\n  DumpString(f->locvars[i].varname,D);\n  DumpInt(f->locvars[i].startpc,D);\n  DumpInt(f->locvars[i].endpc,D);\n }\n n= (D->strip) ? 0 : f->sizeupvalues;\n DumpInt(n,D);\n for (i=0; i<n; i++) DumpString(f->upvalues[i],D);\n}\n\nstatic void DumpFunction(const Proto* f, const TString* p, DumpState* D)\n{\n DumpString((f->source==p || D->strip) ? NULL : f->source,D);\n DumpInt(f->linedefined,D);\n DumpInt(f->lastlinedefined,D);\n DumpChar(f->nups,D);\n DumpChar(f->numparams,D);\n DumpChar(f->is_vararg,D);\n DumpChar(f->maxstacksize,D);\n DumpCode(f,D);\n DumpConstants(f,D);\n DumpDebug(f,D);\n}\n\nstatic void DumpHeader(DumpState* D)\n{\n char h[LUAC_HEADERSIZE];\n luaU_header(h);\n DumpBlock(h,LUAC_HEADERSIZE,D);\n}\n\n/*\n** dump Lua function as precompiled chunk\n*/\nint luaU_dump (lua_State* L, const Proto* f, lua_Writer w, void* data, int strip)\n{\n DumpState D;\n D.L=L;\n D.writer=w;\n D.data=data;\n D.strip=strip;\n D.status=0;\n DumpHeader(&D);\n DumpFunction(f,NULL,&D);\n return D.status;\n}\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.8/deps/lua/src/lfunc.c",
    "content": "/*\n** $Id: lfunc.c,v 2.12.1.2 2007/12/28 14:58:43 roberto Exp $\n** Auxiliary functions to manipulate prototypes and closures\n** See Copyright Notice in lua.h\n*/\n\n\n#include <stddef.h>\n\n#define lfunc_c\n#define LUA_CORE\n\n#include \"lua.h\"\n\n#include \"lfunc.h\"\n#include \"lgc.h\"\n#include \"lmem.h\"\n#include \"lobject.h\"\n#include \"lstate.h\"\n\n\n\nClosure *luaF_newCclosure (lua_State *L, int nelems, Table *e) {\n  Closure *c = cast(Closure *, luaM_malloc(L, sizeCclosure(nelems)));\n  luaC_link(L, obj2gco(c), LUA_TFUNCTION);\n  c->c.isC = 1;\n  c->c.env = e;\n  c->c.nupvalues = cast_byte(nelems);\n  return c;\n}\n\n\nClosure *luaF_newLclosure (lua_State *L, int nelems, Table *e) {\n  Closure *c = cast(Closure *, luaM_malloc(L, sizeLclosure(nelems)));\n  luaC_link(L, obj2gco(c), LUA_TFUNCTION);\n  c->l.isC = 0;\n  c->l.env = e;\n  c->l.nupvalues = cast_byte(nelems);\n  while (nelems--) c->l.upvals[nelems] = NULL;\n  return c;\n}\n\n\nUpVal *luaF_newupval (lua_State *L) {\n  UpVal *uv = luaM_new(L, UpVal);\n  luaC_link(L, obj2gco(uv), LUA_TUPVAL);\n  uv->v = &uv->u.value;\n  setnilvalue(uv->v);\n  return uv;\n}\n\n\nUpVal *luaF_findupval (lua_State *L, StkId level) {\n  global_State *g = G(L);\n  GCObject **pp = &L->openupval;\n  UpVal *p;\n  UpVal *uv;\n  while (*pp != NULL && (p = ngcotouv(*pp))->v >= level) {\n    lua_assert(p->v != &p->u.value);\n    if (p->v == level) {  /* found a corresponding upvalue? */\n      if (isdead(g, obj2gco(p)))  /* is it dead? */\n        changewhite(obj2gco(p));  /* ressurect it */\n      return p;\n    }\n    pp = &p->next;\n  }\n  uv = luaM_new(L, UpVal);  /* not found: create a new one */\n  uv->tt = LUA_TUPVAL;\n  uv->marked = luaC_white(g);\n  uv->v = level;  /* current value lives in the stack */\n  uv->next = *pp;  /* chain it in the proper position */\n  *pp = obj2gco(uv);\n  uv->u.l.prev = &g->uvhead;  /* double link it in `uvhead' list */\n  uv->u.l.next = g->uvhead.u.l.next;\n  uv->u.l.next->u.l.prev = uv;\n  g->uvhead.u.l.next = uv;\n  lua_assert(uv->u.l.next->u.l.prev == uv && uv->u.l.prev->u.l.next == uv);\n  return uv;\n}\n\n\nstatic void unlinkupval (UpVal *uv) {\n  lua_assert(uv->u.l.next->u.l.prev == uv && uv->u.l.prev->u.l.next == uv);\n  uv->u.l.next->u.l.prev = uv->u.l.prev;  /* remove from `uvhead' list */\n  uv->u.l.prev->u.l.next = uv->u.l.next;\n}\n\n\nvoid luaF_freeupval (lua_State *L, UpVal *uv) {\n  if (uv->v != &uv->u.value)  /* is it open? */\n    unlinkupval(uv);  /* remove from open list */\n  luaM_free(L, uv);  /* free upvalue */\n}\n\n\nvoid luaF_close (lua_State *L, StkId level) {\n  UpVal *uv;\n  global_State *g = G(L);\n  while (L->openupval != NULL && (uv = ngcotouv(L->openupval))->v >= level) {\n    GCObject *o = obj2gco(uv);\n    lua_assert(!isblack(o) && uv->v != &uv->u.value);\n    L->openupval = uv->next;  /* remove from `open' list */\n    if (isdead(g, o))\n      luaF_freeupval(L, uv);  /* free upvalue */\n    else {\n      unlinkupval(uv);\n      setobj(L, &uv->u.value, uv->v);\n      uv->v = &uv->u.value;  /* now current value lives here */\n      luaC_linkupval(L, uv);  /* link upvalue into `gcroot' list */\n    }\n  }\n}\n\n\nProto *luaF_newproto (lua_State *L) {\n  Proto *f = luaM_new(L, Proto);\n  luaC_link(L, obj2gco(f), LUA_TPROTO);\n  f->k = NULL;\n  f->sizek = 0;\n  f->p = NULL;\n  f->sizep = 0;\n  f->code = NULL;\n  f->sizecode = 0;\n  f->sizelineinfo = 0;\n  f->sizeupvalues = 0;\n  f->nups = 0;\n  f->upvalues = NULL;\n  f->numparams = 0;\n  f->is_vararg = 0;\n  f->maxstacksize = 0;\n  f->lineinfo = NULL;\n  f->sizelocvars = 0;\n  f->locvars = NULL;\n  f->linedefined = 0;\n  f->lastlinedefined = 0;\n  f->source = NULL;\n  return f;\n}\n\n\nvoid luaF_freeproto (lua_State *L, Proto *f) {\n  luaM_freearray(L, f->code, f->sizecode, Instruction);\n  luaM_freearray(L, f->p, f->sizep, Proto *);\n  luaM_freearray(L, f->k, f->sizek, TValue);\n  luaM_freearray(L, f->lineinfo, f->sizelineinfo, int);\n  luaM_freearray(L, f->locvars, f->sizelocvars, struct LocVar);\n  luaM_freearray(L, f->upvalues, f->sizeupvalues, TString *);\n  luaM_free(L, f);\n}\n\n\nvoid luaF_freeclosure (lua_State *L, Closure *c) {\n  int size = (c->c.isC) ? sizeCclosure(c->c.nupvalues) :\n                          sizeLclosure(c->l.nupvalues);\n  luaM_freemem(L, c, size);\n}\n\n\n/*\n** Look for n-th local variable at line `line' in function `func'.\n** Returns NULL if not found.\n*/\nconst char *luaF_getlocalname (const Proto *f, int local_number, int pc) {\n  int i;\n  for (i = 0; i<f->sizelocvars && f->locvars[i].startpc <= pc; i++) {\n    if (pc < f->locvars[i].endpc) {  /* is variable active? */\n      local_number--;\n      if (local_number == 0)\n        return getstr(f->locvars[i].varname);\n    }\n  }\n  return NULL;  /* not found */\n}\n\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.8/deps/lua/src/lfunc.h",
    "content": "/*\n** $Id: lfunc.h,v 2.4.1.1 2007/12/27 13:02:25 roberto Exp $\n** Auxiliary functions to manipulate prototypes and closures\n** See Copyright Notice in lua.h\n*/\n\n#ifndef lfunc_h\n#define lfunc_h\n\n\n#include \"lobject.h\"\n\n\n#define sizeCclosure(n)\t(cast(int, sizeof(CClosure)) + \\\n                         cast(int, sizeof(TValue)*((n)-1)))\n\n#define sizeLclosure(n)\t(cast(int, sizeof(LClosure)) + \\\n                         cast(int, sizeof(TValue *)*((n)-1)))\n\n\nLUAI_FUNC Proto *luaF_newproto (lua_State *L);\nLUAI_FUNC Closure *luaF_newCclosure (lua_State *L, int nelems, Table *e);\nLUAI_FUNC Closure *luaF_newLclosure (lua_State *L, int nelems, Table *e);\nLUAI_FUNC UpVal *luaF_newupval (lua_State *L);\nLUAI_FUNC UpVal *luaF_findupval (lua_State *L, StkId level);\nLUAI_FUNC void luaF_close (lua_State *L, StkId level);\nLUAI_FUNC void luaF_freeproto (lua_State *L, Proto *f);\nLUAI_FUNC void luaF_freeclosure (lua_State *L, Closure *c);\nLUAI_FUNC void luaF_freeupval (lua_State *L, UpVal *uv);\nLUAI_FUNC const char *luaF_getlocalname (const Proto *func, int local_number,\n                                         int pc);\n\n\n#endif\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.8/deps/lua/src/lgc.c",
    "content": "/*\n** $Id: lgc.c,v 2.38.1.2 2011/03/18 18:05:38 roberto Exp $\n** Garbage Collector\n** See Copyright Notice in lua.h\n*/\n\n#include <string.h>\n\n#define lgc_c\n#define LUA_CORE\n\n#include \"lua.h\"\n\n#include \"ldebug.h\"\n#include \"ldo.h\"\n#include \"lfunc.h\"\n#include \"lgc.h\"\n#include \"lmem.h\"\n#include \"lobject.h\"\n#include \"lstate.h\"\n#include \"lstring.h\"\n#include \"ltable.h\"\n#include \"ltm.h\"\n\n\n#define GCSTEPSIZE\t1024u\n#define GCSWEEPMAX\t40\n#define GCSWEEPCOST\t10\n#define GCFINALIZECOST\t100\n\n\n#define maskmarks\tcast_byte(~(bitmask(BLACKBIT)|WHITEBITS))\n\n#define makewhite(g,x)\t\\\n   ((x)->gch.marked = cast_byte(((x)->gch.marked & maskmarks) | luaC_white(g)))\n\n#define white2gray(x)\treset2bits((x)->gch.marked, WHITE0BIT, WHITE1BIT)\n#define black2gray(x)\tresetbit((x)->gch.marked, BLACKBIT)\n\n#define stringmark(s)\treset2bits((s)->tsv.marked, WHITE0BIT, WHITE1BIT)\n\n\n#define isfinalized(u)\t\ttestbit((u)->marked, FINALIZEDBIT)\n#define markfinalized(u)\tl_setbit((u)->marked, FINALIZEDBIT)\n\n\n#define KEYWEAK         bitmask(KEYWEAKBIT)\n#define VALUEWEAK       bitmask(VALUEWEAKBIT)\n\n\n\n#define markvalue(g,o) { checkconsistency(o); \\\n  if (iscollectable(o) && iswhite(gcvalue(o))) reallymarkobject(g,gcvalue(o)); }\n\n#define markobject(g,t) { if (iswhite(obj2gco(t))) \\\n\t\treallymarkobject(g, obj2gco(t)); }\n\n\n#define setthreshold(g)  (g->GCthreshold = (g->estimate/100) * g->gcpause)\n\n\nstatic void removeentry (Node *n) {\n  lua_assert(ttisnil(gval(n)));\n  if (iscollectable(gkey(n)))\n    setttype(gkey(n), LUA_TDEADKEY);  /* dead key; remove it */\n}\n\n\nstatic void reallymarkobject (global_State *g, GCObject *o) {\n  lua_assert(iswhite(o) && !isdead(g, o));\n  white2gray(o);\n  switch (o->gch.tt) {\n    case LUA_TSTRING: {\n      return;\n    }\n    case LUA_TUSERDATA: {\n      Table *mt = gco2u(o)->metatable;\n      gray2black(o);  /* udata are never gray */\n      if (mt) markobject(g, mt);\n      markobject(g, gco2u(o)->env);\n      return;\n    }\n    case LUA_TUPVAL: {\n      UpVal *uv = gco2uv(o);\n      markvalue(g, uv->v);\n      if (uv->v == &uv->u.value)  /* closed? */\n        gray2black(o);  /* open upvalues are never black */\n      return;\n    }\n    case LUA_TFUNCTION: {\n      gco2cl(o)->c.gclist = g->gray;\n      g->gray = o;\n      break;\n    }\n    case LUA_TTABLE: {\n      gco2h(o)->gclist = g->gray;\n      g->gray = o;\n      break;\n    }\n    case LUA_TTHREAD: {\n      gco2th(o)->gclist = g->gray;\n      g->gray = o;\n      break;\n    }\n    case LUA_TPROTO: {\n      gco2p(o)->gclist = g->gray;\n      g->gray = o;\n      break;\n    }\n    default: lua_assert(0);\n  }\n}\n\n\nstatic void marktmu (global_State *g) {\n  GCObject *u = g->tmudata;\n  if (u) {\n    do {\n      u = u->gch.next;\n      makewhite(g, u);  /* may be marked, if left from previous GC */\n      reallymarkobject(g, u);\n    } while (u != g->tmudata);\n  }\n}\n\n\n/* move `dead' udata that need finalization to list `tmudata' */\nsize_t luaC_separateudata (lua_State *L, int all) {\n  global_State *g = G(L);\n  size_t deadmem = 0;\n  GCObject **p = &g->mainthread->next;\n  GCObject *curr;\n  while ((curr = *p) != NULL) {\n    if (!(iswhite(curr) || all) || isfinalized(gco2u(curr)))\n      p = &curr->gch.next;  /* don't bother with them */\n    else if (fasttm(L, gco2u(curr)->metatable, TM_GC) == NULL) {\n      markfinalized(gco2u(curr));  /* don't need finalization */\n      p = &curr->gch.next;\n    }\n    else {  /* must call its gc method */\n      deadmem += sizeudata(gco2u(curr));\n      markfinalized(gco2u(curr));\n      *p = curr->gch.next;\n      /* link `curr' at the end of `tmudata' list */\n      if (g->tmudata == NULL)  /* list is empty? */\n        g->tmudata = curr->gch.next = curr;  /* creates a circular list */\n      else {\n        curr->gch.next = g->tmudata->gch.next;\n        g->tmudata->gch.next = curr;\n        g->tmudata = curr;\n      }\n    }\n  }\n  return deadmem;\n}\n\n\nstatic int traversetable (global_State *g, Table *h) {\n  int i;\n  int weakkey = 0;\n  int weakvalue = 0;\n  const TValue *mode;\n  if (h->metatable)\n    markobject(g, h->metatable);\n  mode = gfasttm(g, h->metatable, TM_MODE);\n  if (mode && ttisstring(mode)) {  /* is there a weak mode? */\n    weakkey = (strchr(svalue(mode), 'k') != NULL);\n    weakvalue = (strchr(svalue(mode), 'v') != NULL);\n    if (weakkey || weakvalue) {  /* is really weak? */\n      h->marked &= ~(KEYWEAK | VALUEWEAK);  /* clear bits */\n      h->marked |= cast_byte((weakkey << KEYWEAKBIT) |\n                             (weakvalue << VALUEWEAKBIT));\n      h->gclist = g->weak;  /* must be cleared after GC, ... */\n      g->weak = obj2gco(h);  /* ... so put in the appropriate list */\n    }\n  }\n  if (weakkey && weakvalue) return 1;\n  if (!weakvalue) {\n    i = h->sizearray;\n    while (i--)\n      markvalue(g, &h->array[i]);\n  }\n  i = sizenode(h);\n  while (i--) {\n    Node *n = gnode(h, i);\n    lua_assert(ttype(gkey(n)) != LUA_TDEADKEY || ttisnil(gval(n)));\n    if (ttisnil(gval(n)))\n      removeentry(n);  /* remove empty entries */\n    else {\n      lua_assert(!ttisnil(gkey(n)));\n      if (!weakkey) markvalue(g, gkey(n));\n      if (!weakvalue) markvalue(g, gval(n));\n    }\n  }\n  return weakkey || weakvalue;\n}\n\n\n/*\n** All marks are conditional because a GC may happen while the\n** prototype is still being created\n*/\nstatic void traverseproto (global_State *g, Proto *f) {\n  int i;\n  if (f->source) stringmark(f->source);\n  for (i=0; i<f->sizek; i++)  /* mark literals */\n    markvalue(g, &f->k[i]);\n  for (i=0; i<f->sizeupvalues; i++) {  /* mark upvalue names */\n    if (f->upvalues[i])\n      stringmark(f->upvalues[i]);\n  }\n  for (i=0; i<f->sizep; i++) {  /* mark nested protos */\n    if (f->p[i])\n      markobject(g, f->p[i]);\n  }\n  for (i=0; i<f->sizelocvars; i++) {  /* mark local-variable names */\n    if (f->locvars[i].varname)\n      stringmark(f->locvars[i].varname);\n  }\n}\n\n\n\nstatic void traverseclosure (global_State *g, Closure *cl) {\n  markobject(g, cl->c.env);\n  if (cl->c.isC) {\n    int i;\n    for (i=0; i<cl->c.nupvalues; i++)  /* mark its upvalues */\n      markvalue(g, &cl->c.upvalue[i]);\n  }\n  else {\n    int i;\n    lua_assert(cl->l.nupvalues == cl->l.p->nups);\n    markobject(g, cl->l.p);\n    for (i=0; i<cl->l.nupvalues; i++)  /* mark its upvalues */\n      markobject(g, cl->l.upvals[i]);\n  }\n}\n\n\nstatic void checkstacksizes (lua_State *L, StkId max) {\n  int ci_used = cast_int(L->ci - L->base_ci);  /* number of `ci' in use */\n  int s_used = cast_int(max - L->stack);  /* part of stack in use */\n  if (L->size_ci > LUAI_MAXCALLS)  /* handling overflow? */\n    return;  /* do not touch the stacks */\n  if (4*ci_used < L->size_ci && 2*BASIC_CI_SIZE < L->size_ci)\n    luaD_reallocCI(L, L->size_ci/2);  /* still big enough... */\n  condhardstacktests(luaD_reallocCI(L, ci_used + 1));\n  if (4*s_used < L->stacksize &&\n      2*(BASIC_STACK_SIZE+EXTRA_STACK) < L->stacksize)\n    luaD_reallocstack(L, L->stacksize/2);  /* still big enough... */\n  condhardstacktests(luaD_reallocstack(L, s_used));\n}\n\n\nstatic void traversestack (global_State *g, lua_State *l) {\n  StkId o, lim;\n  CallInfo *ci;\n  markvalue(g, gt(l));\n  lim = l->top;\n  for (ci = l->base_ci; ci <= l->ci; ci++) {\n    lua_assert(ci->top <= l->stack_last);\n    if (lim < ci->top) lim = ci->top;\n  }\n  for (o = l->stack; o < l->top; o++)\n    markvalue(g, o);\n  for (; o <= lim; o++)\n    setnilvalue(o);\n  checkstacksizes(l, lim);\n}\n\n\n/*\n** traverse one gray object, turning it to black.\n** Returns `quantity' traversed.\n*/\nstatic l_mem propagatemark (global_State *g) {\n  GCObject *o = g->gray;\n  lua_assert(isgray(o));\n  gray2black(o);\n  switch (o->gch.tt) {\n    case LUA_TTABLE: {\n      Table *h = gco2h(o);\n      g->gray = h->gclist;\n      if (traversetable(g, h))  /* table is weak? */\n        black2gray(o);  /* keep it gray */\n      return sizeof(Table) + sizeof(TValue) * h->sizearray +\n                             sizeof(Node) * sizenode(h);\n    }\n    case LUA_TFUNCTION: {\n      Closure *cl = gco2cl(o);\n      g->gray = cl->c.gclist;\n      traverseclosure(g, cl);\n      return (cl->c.isC) ? sizeCclosure(cl->c.nupvalues) :\n                           sizeLclosure(cl->l.nupvalues);\n    }\n    case LUA_TTHREAD: {\n      lua_State *th = gco2th(o);\n      g->gray = th->gclist;\n      th->gclist = g->grayagain;\n      g->grayagain = o;\n      black2gray(o);\n      traversestack(g, th);\n      return sizeof(lua_State) + sizeof(TValue) * th->stacksize +\n                                 sizeof(CallInfo) * th->size_ci;\n    }\n    case LUA_TPROTO: {\n      Proto *p = gco2p(o);\n      g->gray = p->gclist;\n      traverseproto(g, p);\n      return sizeof(Proto) + sizeof(Instruction) * p->sizecode +\n                             sizeof(Proto *) * p->sizep +\n                             sizeof(TValue) * p->sizek + \n                             sizeof(int) * p->sizelineinfo +\n                             sizeof(LocVar) * p->sizelocvars +\n                             sizeof(TString *) * p->sizeupvalues;\n    }\n    default: lua_assert(0); return 0;\n  }\n}\n\n\nstatic size_t propagateall (global_State *g) {\n  size_t m = 0;\n  while (g->gray) m += propagatemark(g);\n  return m;\n}\n\n\n/*\n** The next function tells whether a key or value can be cleared from\n** a weak table. Non-collectable objects are never removed from weak\n** tables. Strings behave as `values', so are never removed too. for\n** other objects: if really collected, cannot keep them; for userdata\n** being finalized, keep them in keys, but not in values\n*/\nstatic int iscleared (const TValue *o, int iskey) {\n  if (!iscollectable(o)) return 0;\n  if (ttisstring(o)) {\n    stringmark(rawtsvalue(o));  /* strings are `values', so are never weak */\n    return 0;\n  }\n  return iswhite(gcvalue(o)) ||\n    (ttisuserdata(o) && (!iskey && isfinalized(uvalue(o))));\n}\n\n\n/*\n** clear collected entries from weaktables\n*/\nstatic void cleartable (GCObject *l) {\n  while (l) {\n    Table *h = gco2h(l);\n    int i = h->sizearray;\n    lua_assert(testbit(h->marked, VALUEWEAKBIT) ||\n               testbit(h->marked, KEYWEAKBIT));\n    if (testbit(h->marked, VALUEWEAKBIT)) {\n      while (i--) {\n        TValue *o = &h->array[i];\n        if (iscleared(o, 0))  /* value was collected? */\n          setnilvalue(o);  /* remove value */\n      }\n    }\n    i = sizenode(h);\n    while (i--) {\n      Node *n = gnode(h, i);\n      if (!ttisnil(gval(n)) &&  /* non-empty entry? */\n          (iscleared(key2tval(n), 1) || iscleared(gval(n), 0))) {\n        setnilvalue(gval(n));  /* remove value ... */\n        removeentry(n);  /* remove entry from table */\n      }\n    }\n    l = h->gclist;\n  }\n}\n\n\nstatic void freeobj (lua_State *L, GCObject *o) {\n  switch (o->gch.tt) {\n    case LUA_TPROTO: luaF_freeproto(L, gco2p(o)); break;\n    case LUA_TFUNCTION: luaF_freeclosure(L, gco2cl(o)); break;\n    case LUA_TUPVAL: luaF_freeupval(L, gco2uv(o)); break;\n    case LUA_TTABLE: luaH_free(L, gco2h(o)); break;\n    case LUA_TTHREAD: {\n      lua_assert(gco2th(o) != L && gco2th(o) != G(L)->mainthread);\n      luaE_freethread(L, gco2th(o));\n      break;\n    }\n    case LUA_TSTRING: {\n      G(L)->strt.nuse--;\n      luaM_freemem(L, o, sizestring(gco2ts(o)));\n      break;\n    }\n    case LUA_TUSERDATA: {\n      luaM_freemem(L, o, sizeudata(gco2u(o)));\n      break;\n    }\n    default: lua_assert(0);\n  }\n}\n\n\n\n#define sweepwholelist(L,p)\tsweeplist(L,p,MAX_LUMEM)\n\n\nstatic GCObject **sweeplist (lua_State *L, GCObject **p, lu_mem count) {\n  GCObject *curr;\n  global_State *g = G(L);\n  int deadmask = otherwhite(g);\n  while ((curr = *p) != NULL && count-- > 0) {\n    if (curr->gch.tt == LUA_TTHREAD)  /* sweep open upvalues of each thread */\n      sweepwholelist(L, &gco2th(curr)->openupval);\n    if ((curr->gch.marked ^ WHITEBITS) & deadmask) {  /* not dead? */\n      lua_assert(!isdead(g, curr) || testbit(curr->gch.marked, FIXEDBIT));\n      makewhite(g, curr);  /* make it white (for next cycle) */\n      p = &curr->gch.next;\n    }\n    else {  /* must erase `curr' */\n      lua_assert(isdead(g, curr) || deadmask == bitmask(SFIXEDBIT));\n      *p = curr->gch.next;\n      if (curr == g->rootgc)  /* is the first element of the list? */\n        g->rootgc = curr->gch.next;  /* adjust first */\n      freeobj(L, curr);\n    }\n  }\n  return p;\n}\n\n\nstatic void checkSizes (lua_State *L) {\n  global_State *g = G(L);\n  /* check size of string hash */\n  if (g->strt.nuse < cast(lu_int32, g->strt.size/4) &&\n      g->strt.size > MINSTRTABSIZE*2)\n    luaS_resize(L, g->strt.size/2);  /* table is too big */\n  /* check size of buffer */\n  if (luaZ_sizebuffer(&g->buff) > LUA_MINBUFFER*2) {  /* buffer too big? */\n    size_t newsize = luaZ_sizebuffer(&g->buff) / 2;\n    luaZ_resizebuffer(L, &g->buff, newsize);\n  }\n}\n\n\nstatic void GCTM (lua_State *L) {\n  global_State *g = G(L);\n  GCObject *o = g->tmudata->gch.next;  /* get first element */\n  Udata *udata = rawgco2u(o);\n  const TValue *tm;\n  /* remove udata from `tmudata' */\n  if (o == g->tmudata)  /* last element? */\n    g->tmudata = NULL;\n  else\n    g->tmudata->gch.next = udata->uv.next;\n  udata->uv.next = g->mainthread->next;  /* return it to `root' list */\n  g->mainthread->next = o;\n  makewhite(g, o);\n  tm = fasttm(L, udata->uv.metatable, TM_GC);\n  if (tm != NULL) {\n    lu_byte oldah = L->allowhook;\n    lu_mem oldt = g->GCthreshold;\n    L->allowhook = 0;  /* stop debug hooks during GC tag method */\n    g->GCthreshold = 2*g->totalbytes;  /* avoid GC steps */\n    setobj2s(L, L->top, tm);\n    setuvalue(L, L->top+1, udata);\n    L->top += 2;\n    luaD_call(L, L->top - 2, 0);\n    L->allowhook = oldah;  /* restore hooks */\n    g->GCthreshold = oldt;  /* restore threshold */\n  }\n}\n\n\n/*\n** Call all GC tag methods\n*/\nvoid luaC_callGCTM (lua_State *L) {\n  while (G(L)->tmudata)\n    GCTM(L);\n}\n\n\nvoid luaC_freeall (lua_State *L) {\n  global_State *g = G(L);\n  int i;\n  g->currentwhite = WHITEBITS | bitmask(SFIXEDBIT);  /* mask to collect all elements */\n  sweepwholelist(L, &g->rootgc);\n  for (i = 0; i < g->strt.size; i++)  /* free all string lists */\n    sweepwholelist(L, &g->strt.hash[i]);\n}\n\n\nstatic void markmt (global_State *g) {\n  int i;\n  for (i=0; i<NUM_TAGS; i++)\n    if (g->mt[i]) markobject(g, g->mt[i]);\n}\n\n\n/* mark root set */\nstatic void markroot (lua_State *L) {\n  global_State *g = G(L);\n  g->gray = NULL;\n  g->grayagain = NULL;\n  g->weak = NULL;\n  markobject(g, g->mainthread);\n  /* make global table be traversed before main stack */\n  markvalue(g, gt(g->mainthread));\n  markvalue(g, registry(L));\n  markmt(g);\n  g->gcstate = GCSpropagate;\n}\n\n\nstatic void remarkupvals (global_State *g) {\n  UpVal *uv;\n  for (uv = g->uvhead.u.l.next; uv != &g->uvhead; uv = uv->u.l.next) {\n    lua_assert(uv->u.l.next->u.l.prev == uv && uv->u.l.prev->u.l.next == uv);\n    if (isgray(obj2gco(uv)))\n      markvalue(g, uv->v);\n  }\n}\n\n\nstatic void atomic (lua_State *L) {\n  global_State *g = G(L);\n  size_t udsize;  /* total size of userdata to be finalized */\n  /* remark occasional upvalues of (maybe) dead threads */\n  remarkupvals(g);\n  /* traverse objects cautch by write barrier and by 'remarkupvals' */\n  propagateall(g);\n  /* remark weak tables */\n  g->gray = g->weak;\n  g->weak = NULL;\n  lua_assert(!iswhite(obj2gco(g->mainthread)));\n  markobject(g, L);  /* mark running thread */\n  markmt(g);  /* mark basic metatables (again) */\n  propagateall(g);\n  /* remark gray again */\n  g->gray = g->grayagain;\n  g->grayagain = NULL;\n  propagateall(g);\n  udsize = luaC_separateudata(L, 0);  /* separate userdata to be finalized */\n  marktmu(g);  /* mark `preserved' userdata */\n  udsize += propagateall(g);  /* remark, to propagate `preserveness' */\n  cleartable(g->weak);  /* remove collected objects from weak tables */\n  /* flip current white */\n  g->currentwhite = cast_byte(otherwhite(g));\n  g->sweepstrgc = 0;\n  g->sweepgc = &g->rootgc;\n  g->gcstate = GCSsweepstring;\n  g->estimate = g->totalbytes - udsize;  /* first estimate */\n}\n\n\nstatic l_mem singlestep (lua_State *L) {\n  global_State *g = G(L);\n  /*lua_checkmemory(L);*/\n  switch (g->gcstate) {\n    case GCSpause: {\n      markroot(L);  /* start a new collection */\n      return 0;\n    }\n    case GCSpropagate: {\n      if (g->gray)\n        return propagatemark(g);\n      else {  /* no more `gray' objects */\n        atomic(L);  /* finish mark phase */\n        return 0;\n      }\n    }\n    case GCSsweepstring: {\n      lu_mem old = g->totalbytes;\n      sweepwholelist(L, &g->strt.hash[g->sweepstrgc++]);\n      if (g->sweepstrgc >= g->strt.size)  /* nothing more to sweep? */\n        g->gcstate = GCSsweep;  /* end sweep-string phase */\n      lua_assert(old >= g->totalbytes);\n      g->estimate -= old - g->totalbytes;\n      return GCSWEEPCOST;\n    }\n    case GCSsweep: {\n      lu_mem old = g->totalbytes;\n      g->sweepgc = sweeplist(L, g->sweepgc, GCSWEEPMAX);\n      if (*g->sweepgc == NULL) {  /* nothing more to sweep? */\n        checkSizes(L);\n        g->gcstate = GCSfinalize;  /* end sweep phase */\n      }\n      lua_assert(old >= g->totalbytes);\n      g->estimate -= old - g->totalbytes;\n      return GCSWEEPMAX*GCSWEEPCOST;\n    }\n    case GCSfinalize: {\n      if (g->tmudata) {\n        GCTM(L);\n        if (g->estimate > GCFINALIZECOST)\n          g->estimate -= GCFINALIZECOST;\n        return GCFINALIZECOST;\n      }\n      else {\n        g->gcstate = GCSpause;  /* end collection */\n        g->gcdept = 0;\n        return 0;\n      }\n    }\n    default: lua_assert(0); return 0;\n  }\n}\n\n\nvoid luaC_step (lua_State *L) {\n  global_State *g = G(L);\n  l_mem lim = (GCSTEPSIZE/100) * g->gcstepmul;\n  if (lim == 0)\n    lim = (MAX_LUMEM-1)/2;  /* no limit */\n  g->gcdept += g->totalbytes - g->GCthreshold;\n  do {\n    lim -= singlestep(L);\n    if (g->gcstate == GCSpause)\n      break;\n  } while (lim > 0);\n  if (g->gcstate != GCSpause) {\n    if (g->gcdept < GCSTEPSIZE)\n      g->GCthreshold = g->totalbytes + GCSTEPSIZE;  /* - lim/g->gcstepmul;*/\n    else {\n      g->gcdept -= GCSTEPSIZE;\n      g->GCthreshold = g->totalbytes;\n    }\n  }\n  else {\n    setthreshold(g);\n  }\n}\n\n\nvoid luaC_fullgc (lua_State *L) {\n  global_State *g = G(L);\n  if (g->gcstate <= GCSpropagate) {\n    /* reset sweep marks to sweep all elements (returning them to white) */\n    g->sweepstrgc = 0;\n    g->sweepgc = &g->rootgc;\n    /* reset other collector lists */\n    g->gray = NULL;\n    g->grayagain = NULL;\n    g->weak = NULL;\n    g->gcstate = GCSsweepstring;\n  }\n  lua_assert(g->gcstate != GCSpause && g->gcstate != GCSpropagate);\n  /* finish any pending sweep phase */\n  while (g->gcstate != GCSfinalize) {\n    lua_assert(g->gcstate == GCSsweepstring || g->gcstate == GCSsweep);\n    singlestep(L);\n  }\n  markroot(L);\n  while (g->gcstate != GCSpause) {\n    singlestep(L);\n  }\n  setthreshold(g);\n}\n\n\nvoid luaC_barrierf (lua_State *L, GCObject *o, GCObject *v) {\n  global_State *g = G(L);\n  lua_assert(isblack(o) && iswhite(v) && !isdead(g, v) && !isdead(g, o));\n  lua_assert(g->gcstate != GCSfinalize && g->gcstate != GCSpause);\n  lua_assert(ttype(&o->gch) != LUA_TTABLE);\n  /* must keep invariant? */\n  if (g->gcstate == GCSpropagate)\n    reallymarkobject(g, v);  /* restore invariant */\n  else  /* don't mind */\n    makewhite(g, o);  /* mark as white just to avoid other barriers */\n}\n\n\nvoid luaC_barrierback (lua_State *L, Table *t) {\n  global_State *g = G(L);\n  GCObject *o = obj2gco(t);\n  lua_assert(isblack(o) && !isdead(g, o));\n  lua_assert(g->gcstate != GCSfinalize && g->gcstate != GCSpause);\n  black2gray(o);  /* make table gray (again) */\n  t->gclist = g->grayagain;\n  g->grayagain = o;\n}\n\n\nvoid luaC_link (lua_State *L, GCObject *o, lu_byte tt) {\n  global_State *g = G(L);\n  o->gch.next = g->rootgc;\n  g->rootgc = o;\n  o->gch.marked = luaC_white(g);\n  o->gch.tt = tt;\n}\n\n\nvoid luaC_linkupval (lua_State *L, UpVal *uv) {\n  global_State *g = G(L);\n  GCObject *o = obj2gco(uv);\n  o->gch.next = g->rootgc;  /* link upvalue into `rootgc' list */\n  g->rootgc = o;\n  if (isgray(o)) { \n    if (g->gcstate == GCSpropagate) {\n      gray2black(o);  /* closed upvalues need barrier */\n      luaC_barrier(L, uv, uv->v);\n    }\n    else {  /* sweep phase: sweep it (turning it into white) */\n      makewhite(g, o);\n      lua_assert(g->gcstate != GCSfinalize && g->gcstate != GCSpause);\n    }\n  }\n}\n\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.8/deps/lua/src/lgc.h",
    "content": "/*\n** $Id: lgc.h,v 2.15.1.1 2007/12/27 13:02:25 roberto Exp $\n** Garbage Collector\n** See Copyright Notice in lua.h\n*/\n\n#ifndef lgc_h\n#define lgc_h\n\n\n#include \"lobject.h\"\n\n\n/*\n** Possible states of the Garbage Collector\n*/\n#define GCSpause\t0\n#define GCSpropagate\t1\n#define GCSsweepstring\t2\n#define GCSsweep\t3\n#define GCSfinalize\t4\n\n\n/*\n** some userful bit tricks\n*/\n#define resetbits(x,m)\t((x) &= cast(lu_byte, ~(m)))\n#define setbits(x,m)\t((x) |= (m))\n#define testbits(x,m)\t((x) & (m))\n#define bitmask(b)\t(1<<(b))\n#define bit2mask(b1,b2)\t(bitmask(b1) | bitmask(b2))\n#define l_setbit(x,b)\tsetbits(x, bitmask(b))\n#define resetbit(x,b)\tresetbits(x, bitmask(b))\n#define testbit(x,b)\ttestbits(x, bitmask(b))\n#define set2bits(x,b1,b2)\tsetbits(x, (bit2mask(b1, b2)))\n#define reset2bits(x,b1,b2)\tresetbits(x, (bit2mask(b1, b2)))\n#define test2bits(x,b1,b2)\ttestbits(x, (bit2mask(b1, b2)))\n\n\n\n/*\n** Layout for bit use in `marked' field:\n** bit 0 - object is white (type 0)\n** bit 1 - object is white (type 1)\n** bit 2 - object is black\n** bit 3 - for userdata: has been finalized\n** bit 3 - for tables: has weak keys\n** bit 4 - for tables: has weak values\n** bit 5 - object is fixed (should not be collected)\n** bit 6 - object is \"super\" fixed (only the main thread)\n*/\n\n\n#define WHITE0BIT\t0\n#define WHITE1BIT\t1\n#define BLACKBIT\t2\n#define FINALIZEDBIT\t3\n#define KEYWEAKBIT\t3\n#define VALUEWEAKBIT\t4\n#define FIXEDBIT\t5\n#define SFIXEDBIT\t6\n#define WHITEBITS\tbit2mask(WHITE0BIT, WHITE1BIT)\n\n\n#define iswhite(x)      test2bits((x)->gch.marked, WHITE0BIT, WHITE1BIT)\n#define isblack(x)      testbit((x)->gch.marked, BLACKBIT)\n#define isgray(x)\t(!isblack(x) && !iswhite(x))\n\n#define otherwhite(g)\t(g->currentwhite ^ WHITEBITS)\n#define isdead(g,v)\t((v)->gch.marked & otherwhite(g) & WHITEBITS)\n\n#define changewhite(x)\t((x)->gch.marked ^= WHITEBITS)\n#define gray2black(x)\tl_setbit((x)->gch.marked, BLACKBIT)\n\n#define valiswhite(x)\t(iscollectable(x) && iswhite(gcvalue(x)))\n\n#define luaC_white(g)\tcast(lu_byte, (g)->currentwhite & WHITEBITS)\n\n\n#define luaC_checkGC(L) { \\\n  condhardstacktests(luaD_reallocstack(L, L->stacksize - EXTRA_STACK - 1)); \\\n  if (G(L)->totalbytes >= G(L)->GCthreshold) \\\n\tluaC_step(L); }\n\n\n#define luaC_barrier(L,p,v) { if (valiswhite(v) && isblack(obj2gco(p)))  \\\n\tluaC_barrierf(L,obj2gco(p),gcvalue(v)); }\n\n#define luaC_barriert(L,t,v) { if (valiswhite(v) && isblack(obj2gco(t)))  \\\n\tluaC_barrierback(L,t); }\n\n#define luaC_objbarrier(L,p,o)  \\\n\t{ if (iswhite(obj2gco(o)) && isblack(obj2gco(p))) \\\n\t\tluaC_barrierf(L,obj2gco(p),obj2gco(o)); }\n\n#define luaC_objbarriert(L,t,o)  \\\n   { if (iswhite(obj2gco(o)) && isblack(obj2gco(t))) luaC_barrierback(L,t); }\n\nLUAI_FUNC size_t luaC_separateudata (lua_State *L, int all);\nLUAI_FUNC void luaC_callGCTM (lua_State *L);\nLUAI_FUNC void luaC_freeall (lua_State *L);\nLUAI_FUNC void luaC_step (lua_State *L);\nLUAI_FUNC void luaC_fullgc (lua_State *L);\nLUAI_FUNC void luaC_link (lua_State *L, GCObject *o, lu_byte tt);\nLUAI_FUNC void luaC_linkupval (lua_State *L, UpVal *uv);\nLUAI_FUNC void luaC_barrierf (lua_State *L, GCObject *o, GCObject *v);\nLUAI_FUNC void luaC_barrierback (lua_State *L, Table *t);\n\n\n#endif\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.8/deps/lua/src/linit.c",
    "content": "/*\n** $Id: linit.c,v 1.14.1.1 2007/12/27 13:02:25 roberto Exp $\n** Initialization of libraries for lua.c\n** See Copyright Notice in lua.h\n*/\n\n\n#define linit_c\n#define LUA_LIB\n\n#include \"lua.h\"\n\n#include \"lualib.h\"\n#include \"lauxlib.h\"\n\n\nstatic const luaL_Reg lualibs[] = {\n  {\"\", luaopen_base},\n  {LUA_LOADLIBNAME, luaopen_package},\n  {LUA_TABLIBNAME, luaopen_table},\n  {LUA_IOLIBNAME, luaopen_io},\n  {LUA_OSLIBNAME, luaopen_os},\n  {LUA_STRLIBNAME, luaopen_string},\n  {LUA_MATHLIBNAME, luaopen_math},\n  {LUA_DBLIBNAME, luaopen_debug},\n  {NULL, NULL}\n};\n\n\nLUALIB_API void luaL_openlibs (lua_State *L) {\n  const luaL_Reg *lib = lualibs;\n  for (; lib->func; lib++) {\n    lua_pushcfunction(L, lib->func);\n    lua_pushstring(L, lib->name);\n    lua_call(L, 1, 0);\n  }\n}\n\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.8/deps/lua/src/liolib.c",
    "content": "/*\n** $Id: liolib.c,v 2.73.1.4 2010/05/14 15:33:51 roberto Exp $\n** Standard I/O (and system) library\n** See Copyright Notice in lua.h\n*/\n\n\n#include <errno.h>\n#include <stdio.h>\n#include <stdlib.h>\n#include <string.h>\n\n#define liolib_c\n#define LUA_LIB\n\n#include \"lua.h\"\n\n#include \"lauxlib.h\"\n#include \"lualib.h\"\n\n\n\n#define IO_INPUT\t1\n#define IO_OUTPUT\t2\n\n\nstatic const char *const fnames[] = {\"input\", \"output\"};\n\n\nstatic int pushresult (lua_State *L, int i, const char *filename) {\n  int en = errno;  /* calls to Lua API may change this value */\n  if (i) {\n    lua_pushboolean(L, 1);\n    return 1;\n  }\n  else {\n    lua_pushnil(L);\n    if (filename)\n      lua_pushfstring(L, \"%s: %s\", filename, strerror(en));\n    else\n      lua_pushfstring(L, \"%s\", strerror(en));\n    lua_pushinteger(L, en);\n    return 3;\n  }\n}\n\n\nstatic void fileerror (lua_State *L, int arg, const char *filename) {\n  lua_pushfstring(L, \"%s: %s\", filename, strerror(errno));\n  luaL_argerror(L, arg, lua_tostring(L, -1));\n}\n\n\n#define tofilep(L)\t((FILE **)luaL_checkudata(L, 1, LUA_FILEHANDLE))\n\n\nstatic int io_type (lua_State *L) {\n  void *ud;\n  luaL_checkany(L, 1);\n  ud = lua_touserdata(L, 1);\n  lua_getfield(L, LUA_REGISTRYINDEX, LUA_FILEHANDLE);\n  if (ud == NULL || !lua_getmetatable(L, 1) || !lua_rawequal(L, -2, -1))\n    lua_pushnil(L);  /* not a file */\n  else if (*((FILE **)ud) == NULL)\n    lua_pushliteral(L, \"closed file\");\n  else\n    lua_pushliteral(L, \"file\");\n  return 1;\n}\n\n\nstatic FILE *tofile (lua_State *L) {\n  FILE **f = tofilep(L);\n  if (*f == NULL)\n    luaL_error(L, \"attempt to use a closed file\");\n  return *f;\n}\n\n\n\n/*\n** When creating file handles, always creates a `closed' file handle\n** before opening the actual file; so, if there is a memory error, the\n** file is not left opened.\n*/\nstatic FILE **newfile (lua_State *L) {\n  FILE **pf = (FILE **)lua_newuserdata(L, sizeof(FILE *));\n  *pf = NULL;  /* file handle is currently `closed' */\n  luaL_getmetatable(L, LUA_FILEHANDLE);\n  lua_setmetatable(L, -2);\n  return pf;\n}\n\n\n/*\n** function to (not) close the standard files stdin, stdout, and stderr\n*/\nstatic int io_noclose (lua_State *L) {\n  lua_pushnil(L);\n  lua_pushliteral(L, \"cannot close standard file\");\n  return 2;\n}\n\n\n/*\n** function to close 'popen' files\n*/\nstatic int io_pclose (lua_State *L) {\n  FILE **p = tofilep(L);\n  int ok = lua_pclose(L, *p);\n  *p = NULL;\n  return pushresult(L, ok, NULL);\n}\n\n\n/*\n** function to close regular files\n*/\nstatic int io_fclose (lua_State *L) {\n  FILE **p = tofilep(L);\n  int ok = (fclose(*p) == 0);\n  *p = NULL;\n  return pushresult(L, ok, NULL);\n}\n\n\nstatic int aux_close (lua_State *L) {\n  lua_getfenv(L, 1);\n  lua_getfield(L, -1, \"__close\");\n  return (lua_tocfunction(L, -1))(L);\n}\n\n\nstatic int io_close (lua_State *L) {\n  if (lua_isnone(L, 1))\n    lua_rawgeti(L, LUA_ENVIRONINDEX, IO_OUTPUT);\n  tofile(L);  /* make sure argument is a file */\n  return aux_close(L);\n}\n\n\nstatic int io_gc (lua_State *L) {\n  FILE *f = *tofilep(L);\n  /* ignore closed files */\n  if (f != NULL)\n    aux_close(L);\n  return 0;\n}\n\n\nstatic int io_tostring (lua_State *L) {\n  FILE *f = *tofilep(L);\n  if (f == NULL)\n    lua_pushliteral(L, \"file (closed)\");\n  else\n    lua_pushfstring(L, \"file (%p)\", f);\n  return 1;\n}\n\n\nstatic int io_open (lua_State *L) {\n  const char *filename = luaL_checkstring(L, 1);\n  const char *mode = luaL_optstring(L, 2, \"r\");\n  FILE **pf = newfile(L);\n  *pf = fopen(filename, mode);\n  return (*pf == NULL) ? pushresult(L, 0, filename) : 1;\n}\n\n\n/*\n** this function has a separated environment, which defines the\n** correct __close for 'popen' files\n*/\nstatic int io_popen (lua_State *L) {\n  const char *filename = luaL_checkstring(L, 1);\n  const char *mode = luaL_optstring(L, 2, \"r\");\n  FILE **pf = newfile(L);\n  *pf = lua_popen(L, filename, mode);\n  return (*pf == NULL) ? pushresult(L, 0, filename) : 1;\n}\n\n\nstatic int io_tmpfile (lua_State *L) {\n  FILE **pf = newfile(L);\n  *pf = tmpfile();\n  return (*pf == NULL) ? pushresult(L, 0, NULL) : 1;\n}\n\n\nstatic FILE *getiofile (lua_State *L, int findex) {\n  FILE *f;\n  lua_rawgeti(L, LUA_ENVIRONINDEX, findex);\n  f = *(FILE **)lua_touserdata(L, -1);\n  if (f == NULL)\n    luaL_error(L, \"standard %s file is closed\", fnames[findex - 1]);\n  return f;\n}\n\n\nstatic int g_iofile (lua_State *L, int f, const char *mode) {\n  if (!lua_isnoneornil(L, 1)) {\n    const char *filename = lua_tostring(L, 1);\n    if (filename) {\n      FILE **pf = newfile(L);\n      *pf = fopen(filename, mode);\n      if (*pf == NULL)\n        fileerror(L, 1, filename);\n    }\n    else {\n      tofile(L);  /* check that it's a valid file handle */\n      lua_pushvalue(L, 1);\n    }\n    lua_rawseti(L, LUA_ENVIRONINDEX, f);\n  }\n  /* return current value */\n  lua_rawgeti(L, LUA_ENVIRONINDEX, f);\n  return 1;\n}\n\n\nstatic int io_input (lua_State *L) {\n  return g_iofile(L, IO_INPUT, \"r\");\n}\n\n\nstatic int io_output (lua_State *L) {\n  return g_iofile(L, IO_OUTPUT, \"w\");\n}\n\n\nstatic int io_readline (lua_State *L);\n\n\nstatic void aux_lines (lua_State *L, int idx, int toclose) {\n  lua_pushvalue(L, idx);\n  lua_pushboolean(L, toclose);  /* close/not close file when finished */\n  lua_pushcclosure(L, io_readline, 2);\n}\n\n\nstatic int f_lines (lua_State *L) {\n  tofile(L);  /* check that it's a valid file handle */\n  aux_lines(L, 1, 0);\n  return 1;\n}\n\n\nstatic int io_lines (lua_State *L) {\n  if (lua_isnoneornil(L, 1)) {  /* no arguments? */\n    /* will iterate over default input */\n    lua_rawgeti(L, LUA_ENVIRONINDEX, IO_INPUT);\n    return f_lines(L);\n  }\n  else {\n    const char *filename = luaL_checkstring(L, 1);\n    FILE **pf = newfile(L);\n    *pf = fopen(filename, \"r\");\n    if (*pf == NULL)\n      fileerror(L, 1, filename);\n    aux_lines(L, lua_gettop(L), 1);\n    return 1;\n  }\n}\n\n\n/*\n** {======================================================\n** READ\n** =======================================================\n*/\n\n\nstatic int read_number (lua_State *L, FILE *f) {\n  lua_Number d;\n  if (fscanf(f, LUA_NUMBER_SCAN, &d) == 1) {\n    lua_pushnumber(L, d);\n    return 1;\n  }\n  else {\n    lua_pushnil(L);  /* \"result\" to be removed */\n    return 0;  /* read fails */\n  }\n}\n\n\nstatic int test_eof (lua_State *L, FILE *f) {\n  int c = getc(f);\n  ungetc(c, f);\n  lua_pushlstring(L, NULL, 0);\n  return (c != EOF);\n}\n\n\nstatic int read_line (lua_State *L, FILE *f) {\n  luaL_Buffer b;\n  luaL_buffinit(L, &b);\n  for (;;) {\n    size_t l;\n    char *p = luaL_prepbuffer(&b);\n    if (fgets(p, LUAL_BUFFERSIZE, f) == NULL) {  /* eof? */\n      luaL_pushresult(&b);  /* close buffer */\n      return (lua_objlen(L, -1) > 0);  /* check whether read something */\n    }\n    l = strlen(p);\n    if (l == 0 || p[l-1] != '\\n')\n      luaL_addsize(&b, l);\n    else {\n      luaL_addsize(&b, l - 1);  /* do not include `eol' */\n      luaL_pushresult(&b);  /* close buffer */\n      return 1;  /* read at least an `eol' */\n    }\n  }\n}\n\n\nstatic int read_chars (lua_State *L, FILE *f, size_t n) {\n  size_t rlen;  /* how much to read */\n  size_t nr;  /* number of chars actually read */\n  luaL_Buffer b;\n  luaL_buffinit(L, &b);\n  rlen = LUAL_BUFFERSIZE;  /* try to read that much each time */\n  do {\n    char *p = luaL_prepbuffer(&b);\n    if (rlen > n) rlen = n;  /* cannot read more than asked */\n    nr = fread(p, sizeof(char), rlen, f);\n    luaL_addsize(&b, nr);\n    n -= nr;  /* still have to read `n' chars */\n  } while (n > 0 && nr == rlen);  /* until end of count or eof */\n  luaL_pushresult(&b);  /* close buffer */\n  return (n == 0 || lua_objlen(L, -1) > 0);\n}\n\n\nstatic int g_read (lua_State *L, FILE *f, int first) {\n  int nargs = lua_gettop(L) - 1;\n  int success;\n  int n;\n  clearerr(f);\n  if (nargs == 0) {  /* no arguments? */\n    success = read_line(L, f);\n    n = first+1;  /* to return 1 result */\n  }\n  else {  /* ensure stack space for all results and for auxlib's buffer */\n    luaL_checkstack(L, nargs+LUA_MINSTACK, \"too many arguments\");\n    success = 1;\n    for (n = first; nargs-- && success; n++) {\n      if (lua_type(L, n) == LUA_TNUMBER) {\n        size_t l = (size_t)lua_tointeger(L, n);\n        success = (l == 0) ? test_eof(L, f) : read_chars(L, f, l);\n      }\n      else {\n        const char *p = lua_tostring(L, n);\n        luaL_argcheck(L, p && p[0] == '*', n, \"invalid option\");\n        switch (p[1]) {\n          case 'n':  /* number */\n            success = read_number(L, f);\n            break;\n          case 'l':  /* line */\n            success = read_line(L, f);\n            break;\n          case 'a':  /* file */\n            read_chars(L, f, ~((size_t)0));  /* read MAX_SIZE_T chars */\n            success = 1; /* always success */\n            break;\n          default:\n            return luaL_argerror(L, n, \"invalid format\");\n        }\n      }\n    }\n  }\n  if (ferror(f))\n    return pushresult(L, 0, NULL);\n  if (!success) {\n    lua_pop(L, 1);  /* remove last result */\n    lua_pushnil(L);  /* push nil instead */\n  }\n  return n - first;\n}\n\n\nstatic int io_read (lua_State *L) {\n  return g_read(L, getiofile(L, IO_INPUT), 1);\n}\n\n\nstatic int f_read (lua_State *L) {\n  return g_read(L, tofile(L), 2);\n}\n\n\nstatic int io_readline (lua_State *L) {\n  FILE *f = *(FILE **)lua_touserdata(L, lua_upvalueindex(1));\n  int sucess;\n  if (f == NULL)  /* file is already closed? */\n    luaL_error(L, \"file is already closed\");\n  sucess = read_line(L, f);\n  if (ferror(f))\n    return luaL_error(L, \"%s\", strerror(errno));\n  if (sucess) return 1;\n  else {  /* EOF */\n    if (lua_toboolean(L, lua_upvalueindex(2))) {  /* generator created file? */\n      lua_settop(L, 0);\n      lua_pushvalue(L, lua_upvalueindex(1));\n      aux_close(L);  /* close it */\n    }\n    return 0;\n  }\n}\n\n/* }====================================================== */\n\n\nstatic int g_write (lua_State *L, FILE *f, int arg) {\n  int nargs = lua_gettop(L) - 1;\n  int status = 1;\n  for (; nargs--; arg++) {\n    if (lua_type(L, arg) == LUA_TNUMBER) {\n      /* optimization: could be done exactly as for strings */\n      status = status &&\n          fprintf(f, LUA_NUMBER_FMT, lua_tonumber(L, arg)) > 0;\n    }\n    else {\n      size_t l;\n      const char *s = luaL_checklstring(L, arg, &l);\n      status = status && (fwrite(s, sizeof(char), l, f) == l);\n    }\n  }\n  return pushresult(L, status, NULL);\n}\n\n\nstatic int io_write (lua_State *L) {\n  return g_write(L, getiofile(L, IO_OUTPUT), 1);\n}\n\n\nstatic int f_write (lua_State *L) {\n  return g_write(L, tofile(L), 2);\n}\n\n\nstatic int f_seek (lua_State *L) {\n  static const int mode[] = {SEEK_SET, SEEK_CUR, SEEK_END};\n  static const char *const modenames[] = {\"set\", \"cur\", \"end\", NULL};\n  FILE *f = tofile(L);\n  int op = luaL_checkoption(L, 2, \"cur\", modenames);\n  long offset = luaL_optlong(L, 3, 0);\n  op = fseek(f, offset, mode[op]);\n  if (op)\n    return pushresult(L, 0, NULL);  /* error */\n  else {\n    lua_pushinteger(L, ftell(f));\n    return 1;\n  }\n}\n\n\nstatic int f_setvbuf (lua_State *L) {\n  static const int mode[] = {_IONBF, _IOFBF, _IOLBF};\n  static const char *const modenames[] = {\"no\", \"full\", \"line\", NULL};\n  FILE *f = tofile(L);\n  int op = luaL_checkoption(L, 2, NULL, modenames);\n  lua_Integer sz = luaL_optinteger(L, 3, LUAL_BUFFERSIZE);\n  int res = setvbuf(f, NULL, mode[op], sz);\n  return pushresult(L, res == 0, NULL);\n}\n\n\n\nstatic int io_flush (lua_State *L) {\n  return pushresult(L, fflush(getiofile(L, IO_OUTPUT)) == 0, NULL);\n}\n\n\nstatic int f_flush (lua_State *L) {\n  return pushresult(L, fflush(tofile(L)) == 0, NULL);\n}\n\n\nstatic const luaL_Reg iolib[] = {\n  {\"close\", io_close},\n  {\"flush\", io_flush},\n  {\"input\", io_input},\n  {\"lines\", io_lines},\n  {\"open\", io_open},\n  {\"output\", io_output},\n  {\"popen\", io_popen},\n  {\"read\", io_read},\n  {\"tmpfile\", io_tmpfile},\n  {\"type\", io_type},\n  {\"write\", io_write},\n  {NULL, NULL}\n};\n\n\nstatic const luaL_Reg flib[] = {\n  {\"close\", io_close},\n  {\"flush\", f_flush},\n  {\"lines\", f_lines},\n  {\"read\", f_read},\n  {\"seek\", f_seek},\n  {\"setvbuf\", f_setvbuf},\n  {\"write\", f_write},\n  {\"__gc\", io_gc},\n  {\"__tostring\", io_tostring},\n  {NULL, NULL}\n};\n\n\nstatic void createmeta (lua_State *L) {\n  luaL_newmetatable(L, LUA_FILEHANDLE);  /* create metatable for file handles */\n  lua_pushvalue(L, -1);  /* push metatable */\n  lua_setfield(L, -2, \"__index\");  /* metatable.__index = metatable */\n  luaL_register(L, NULL, flib);  /* file methods */\n}\n\n\nstatic void createstdfile (lua_State *L, FILE *f, int k, const char *fname) {\n  *newfile(L) = f;\n  if (k > 0) {\n    lua_pushvalue(L, -1);\n    lua_rawseti(L, LUA_ENVIRONINDEX, k);\n  }\n  lua_pushvalue(L, -2);  /* copy environment */\n  lua_setfenv(L, -2);  /* set it */\n  lua_setfield(L, -3, fname);\n}\n\n\nstatic void newfenv (lua_State *L, lua_CFunction cls) {\n  lua_createtable(L, 0, 1);\n  lua_pushcfunction(L, cls);\n  lua_setfield(L, -2, \"__close\");\n}\n\n\nLUALIB_API int luaopen_io (lua_State *L) {\n  createmeta(L);\n  /* create (private) environment (with fields IO_INPUT, IO_OUTPUT, __close) */\n  newfenv(L, io_fclose);\n  lua_replace(L, LUA_ENVIRONINDEX);\n  /* open library */\n  luaL_register(L, LUA_IOLIBNAME, iolib);\n  /* create (and set) default files */\n  newfenv(L, io_noclose);  /* close function for default files */\n  createstdfile(L, stdin, IO_INPUT, \"stdin\");\n  createstdfile(L, stdout, IO_OUTPUT, \"stdout\");\n  createstdfile(L, stderr, 0, \"stderr\");\n  lua_pop(L, 1);  /* pop environment for default files */\n  lua_getfield(L, -1, \"popen\");\n  newfenv(L, io_pclose);  /* create environment for 'popen' */\n  lua_setfenv(L, -2);  /* set fenv for 'popen' */\n  lua_pop(L, 1);  /* pop 'popen' */\n  return 1;\n}\n\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.8/deps/lua/src/llex.c",
    "content": "/*\n** $Id: llex.c,v 2.20.1.2 2009/11/23 14:58:22 roberto Exp $\n** Lexical Analyzer\n** See Copyright Notice in lua.h\n*/\n\n\n#include <ctype.h>\n#include <locale.h>\n#include <string.h>\n\n#define llex_c\n#define LUA_CORE\n\n#include \"lua.h\"\n\n#include \"ldo.h\"\n#include \"llex.h\"\n#include \"lobject.h\"\n#include \"lparser.h\"\n#include \"lstate.h\"\n#include \"lstring.h\"\n#include \"ltable.h\"\n#include \"lzio.h\"\n\n\n\n#define next(ls) (ls->current = zgetc(ls->z))\n\n\n\n\n#define currIsNewline(ls)\t(ls->current == '\\n' || ls->current == '\\r')\n\n\n/* ORDER RESERVED */\nconst char *const luaX_tokens [] = {\n    \"and\", \"break\", \"do\", \"else\", \"elseif\",\n    \"end\", \"false\", \"for\", \"function\", \"if\",\n    \"in\", \"local\", \"nil\", \"not\", \"or\", \"repeat\",\n    \"return\", \"then\", \"true\", \"until\", \"while\",\n    \"..\", \"...\", \"==\", \">=\", \"<=\", \"~=\",\n    \"<number>\", \"<name>\", \"<string>\", \"<eof>\",\n    NULL\n};\n\n\n#define save_and_next(ls) (save(ls, ls->current), next(ls))\n\n\nstatic void save (LexState *ls, int c) {\n  Mbuffer *b = ls->buff;\n  if (b->n + 1 > b->buffsize) {\n    size_t newsize;\n    if (b->buffsize >= MAX_SIZET/2)\n      luaX_lexerror(ls, \"lexical element too long\", 0);\n    newsize = b->buffsize * 2;\n    luaZ_resizebuffer(ls->L, b, newsize);\n  }\n  b->buffer[b->n++] = cast(char, c);\n}\n\n\nvoid luaX_init (lua_State *L) {\n  int i;\n  for (i=0; i<NUM_RESERVED; i++) {\n    TString *ts = luaS_new(L, luaX_tokens[i]);\n    luaS_fix(ts);  /* reserved words are never collected */\n    lua_assert(strlen(luaX_tokens[i])+1 <= TOKEN_LEN);\n    ts->tsv.reserved = cast_byte(i+1);  /* reserved word */\n  }\n}\n\n\n#define MAXSRC          80\n\n\nconst char *luaX_token2str (LexState *ls, int token) {\n  if (token < FIRST_RESERVED) {\n    lua_assert(token == cast(unsigned char, token));\n    return (iscntrl(token)) ? luaO_pushfstring(ls->L, \"char(%d)\", token) :\n                              luaO_pushfstring(ls->L, \"%c\", token);\n  }\n  else\n    return luaX_tokens[token-FIRST_RESERVED];\n}\n\n\nstatic const char *txtToken (LexState *ls, int token) {\n  switch (token) {\n    case TK_NAME:\n    case TK_STRING:\n    case TK_NUMBER:\n      save(ls, '\\0');\n      return luaZ_buffer(ls->buff);\n    default:\n      return luaX_token2str(ls, token);\n  }\n}\n\n\nvoid luaX_lexerror (LexState *ls, const char *msg, int token) {\n  char buff[MAXSRC];\n  luaO_chunkid(buff, getstr(ls->source), MAXSRC);\n  msg = luaO_pushfstring(ls->L, \"%s:%d: %s\", buff, ls->linenumber, msg);\n  if (token)\n    luaO_pushfstring(ls->L, \"%s near \" LUA_QS, msg, txtToken(ls, token));\n  luaD_throw(ls->L, LUA_ERRSYNTAX);\n}\n\n\nvoid luaX_syntaxerror (LexState *ls, const char *msg) {\n  luaX_lexerror(ls, msg, ls->t.token);\n}\n\n\nTString *luaX_newstring (LexState *ls, const char *str, size_t l) {\n  lua_State *L = ls->L;\n  TString *ts = luaS_newlstr(L, str, l);\n  TValue *o = luaH_setstr(L, ls->fs->h, ts);  /* entry for `str' */\n  if (ttisnil(o)) {\n    setbvalue(o, 1);  /* make sure `str' will not be collected */\n    luaC_checkGC(L);\n  }\n  return ts;\n}\n\n\nstatic void inclinenumber (LexState *ls) {\n  int old = ls->current;\n  lua_assert(currIsNewline(ls));\n  next(ls);  /* skip `\\n' or `\\r' */\n  if (currIsNewline(ls) && ls->current != old)\n    next(ls);  /* skip `\\n\\r' or `\\r\\n' */\n  if (++ls->linenumber >= MAX_INT)\n    luaX_syntaxerror(ls, \"chunk has too many lines\");\n}\n\n\nvoid luaX_setinput (lua_State *L, LexState *ls, ZIO *z, TString *source) {\n  ls->decpoint = '.';\n  ls->L = L;\n  ls->lookahead.token = TK_EOS;  /* no look-ahead token */\n  ls->z = z;\n  ls->fs = NULL;\n  ls->linenumber = 1;\n  ls->lastline = 1;\n  ls->source = source;\n  luaZ_resizebuffer(ls->L, ls->buff, LUA_MINBUFFER);  /* initialize buffer */\n  next(ls);  /* read first char */\n}\n\n\n\n/*\n** =======================================================\n** LEXICAL ANALYZER\n** =======================================================\n*/\n\n\n\nstatic int check_next (LexState *ls, const char *set) {\n  if (!strchr(set, ls->current))\n    return 0;\n  save_and_next(ls);\n  return 1;\n}\n\n\nstatic void buffreplace (LexState *ls, char from, char to) {\n  size_t n = luaZ_bufflen(ls->buff);\n  char *p = luaZ_buffer(ls->buff);\n  while (n--)\n    if (p[n] == from) p[n] = to;\n}\n\n\nstatic void trydecpoint (LexState *ls, SemInfo *seminfo) {\n  /* format error: try to update decimal point separator */\n  struct lconv *cv = localeconv();\n  char old = ls->decpoint;\n  ls->decpoint = (cv ? cv->decimal_point[0] : '.');\n  buffreplace(ls, old, ls->decpoint);  /* try updated decimal separator */\n  if (!luaO_str2d(luaZ_buffer(ls->buff), &seminfo->r)) {\n    /* format error with correct decimal point: no more options */\n    buffreplace(ls, ls->decpoint, '.');  /* undo change (for error message) */\n    luaX_lexerror(ls, \"malformed number\", TK_NUMBER);\n  }\n}\n\n\n/* LUA_NUMBER */\nstatic void read_numeral (LexState *ls, SemInfo *seminfo) {\n  lua_assert(isdigit(ls->current));\n  do {\n    save_and_next(ls);\n  } while (isdigit(ls->current) || ls->current == '.');\n  if (check_next(ls, \"Ee\"))  /* `E'? */\n    check_next(ls, \"+-\");  /* optional exponent sign */\n  while (isalnum(ls->current) || ls->current == '_')\n    save_and_next(ls);\n  save(ls, '\\0');\n  buffreplace(ls, '.', ls->decpoint);  /* follow locale for decimal point */\n  if (!luaO_str2d(luaZ_buffer(ls->buff), &seminfo->r))  /* format error? */\n    trydecpoint(ls, seminfo); /* try to update decimal point separator */\n}\n\n\nstatic int skip_sep (LexState *ls) {\n  int count = 0;\n  int s = ls->current;\n  lua_assert(s == '[' || s == ']');\n  save_and_next(ls);\n  while (ls->current == '=') {\n    save_and_next(ls);\n    count++;\n  }\n  return (ls->current == s) ? count : (-count) - 1;\n}\n\n\nstatic void read_long_string (LexState *ls, SemInfo *seminfo, int sep) {\n  int cont = 0;\n  (void)(cont);  /* avoid warnings when `cont' is not used */\n  save_and_next(ls);  /* skip 2nd `[' */\n  if (currIsNewline(ls))  /* string starts with a newline? */\n    inclinenumber(ls);  /* skip it */\n  for (;;) {\n    switch (ls->current) {\n      case EOZ:\n        luaX_lexerror(ls, (seminfo) ? \"unfinished long string\" :\n                                   \"unfinished long comment\", TK_EOS);\n        break;  /* to avoid warnings */\n#if defined(LUA_COMPAT_LSTR)\n      case '[': {\n        if (skip_sep(ls) == sep) {\n          save_and_next(ls);  /* skip 2nd `[' */\n          cont++;\n#if LUA_COMPAT_LSTR == 1\n          if (sep == 0)\n            luaX_lexerror(ls, \"nesting of [[...]] is deprecated\", '[');\n#endif\n        }\n        break;\n      }\n#endif\n      case ']': {\n        if (skip_sep(ls) == sep) {\n          save_and_next(ls);  /* skip 2nd `]' */\n#if defined(LUA_COMPAT_LSTR) && LUA_COMPAT_LSTR == 2\n          cont--;\n          if (sep == 0 && cont >= 0) break;\n#endif\n          goto endloop;\n        }\n        break;\n      }\n      case '\\n':\n      case '\\r': {\n        save(ls, '\\n');\n        inclinenumber(ls);\n        if (!seminfo) luaZ_resetbuffer(ls->buff);  /* avoid wasting space */\n        break;\n      }\n      default: {\n        if (seminfo) save_and_next(ls);\n        else next(ls);\n      }\n    }\n  } endloop:\n  if (seminfo)\n    seminfo->ts = luaX_newstring(ls, luaZ_buffer(ls->buff) + (2 + sep),\n                                     luaZ_bufflen(ls->buff) - 2*(2 + sep));\n}\n\n\nstatic void read_string (LexState *ls, int del, SemInfo *seminfo) {\n  save_and_next(ls);\n  while (ls->current != del) {\n    switch (ls->current) {\n      case EOZ:\n        luaX_lexerror(ls, \"unfinished string\", TK_EOS);\n        continue;  /* to avoid warnings */\n      case '\\n':\n      case '\\r':\n        luaX_lexerror(ls, \"unfinished string\", TK_STRING);\n        continue;  /* to avoid warnings */\n      case '\\\\': {\n        int c;\n        next(ls);  /* do not save the `\\' */\n        switch (ls->current) {\n          case 'a': c = '\\a'; break;\n          case 'b': c = '\\b'; break;\n          case 'f': c = '\\f'; break;\n          case 'n': c = '\\n'; break;\n          case 'r': c = '\\r'; break;\n          case 't': c = '\\t'; break;\n          case 'v': c = '\\v'; break;\n          case '\\n':  /* go through */\n          case '\\r': save(ls, '\\n'); inclinenumber(ls); continue;\n          case EOZ: continue;  /* will raise an error next loop */\n          default: {\n            if (!isdigit(ls->current))\n              save_and_next(ls);  /* handles \\\\, \\\", \\', and \\? */\n            else {  /* \\xxx */\n              int i = 0;\n              c = 0;\n              do {\n                c = 10*c + (ls->current-'0');\n                next(ls);\n              } while (++i<3 && isdigit(ls->current));\n              if (c > UCHAR_MAX)\n                luaX_lexerror(ls, \"escape sequence too large\", TK_STRING);\n              save(ls, c);\n            }\n            continue;\n          }\n        }\n        save(ls, c);\n        next(ls);\n        continue;\n      }\n      default:\n        save_and_next(ls);\n    }\n  }\n  save_and_next(ls);  /* skip delimiter */\n  seminfo->ts = luaX_newstring(ls, luaZ_buffer(ls->buff) + 1,\n                                   luaZ_bufflen(ls->buff) - 2);\n}\n\n\nstatic int llex (LexState *ls, SemInfo *seminfo) {\n  luaZ_resetbuffer(ls->buff);\n  for (;;) {\n    switch (ls->current) {\n      case '\\n':\n      case '\\r': {\n        inclinenumber(ls);\n        continue;\n      }\n      case '-': {\n        next(ls);\n        if (ls->current != '-') return '-';\n        /* else is a comment */\n        next(ls);\n        if (ls->current == '[') {\n          int sep = skip_sep(ls);\n          luaZ_resetbuffer(ls->buff);  /* `skip_sep' may dirty the buffer */\n          if (sep >= 0) {\n            read_long_string(ls, NULL, sep);  /* long comment */\n            luaZ_resetbuffer(ls->buff);\n            continue;\n          }\n        }\n        /* else short comment */\n        while (!currIsNewline(ls) && ls->current != EOZ)\n          next(ls);\n        continue;\n      }\n      case '[': {\n        int sep = skip_sep(ls);\n        if (sep >= 0) {\n          read_long_string(ls, seminfo, sep);\n          return TK_STRING;\n        }\n        else if (sep == -1) return '[';\n        else luaX_lexerror(ls, \"invalid long string delimiter\", TK_STRING);\n      }\n      case '=': {\n        next(ls);\n        if (ls->current != '=') return '=';\n        else { next(ls); return TK_EQ; }\n      }\n      case '<': {\n        next(ls);\n        if (ls->current != '=') return '<';\n        else { next(ls); return TK_LE; }\n      }\n      case '>': {\n        next(ls);\n        if (ls->current != '=') return '>';\n        else { next(ls); return TK_GE; }\n      }\n      case '~': {\n        next(ls);\n        if (ls->current != '=') return '~';\n        else { next(ls); return TK_NE; }\n      }\n      case '\"':\n      case '\\'': {\n        read_string(ls, ls->current, seminfo);\n        return TK_STRING;\n      }\n      case '.': {\n        save_and_next(ls);\n        if (check_next(ls, \".\")) {\n          if (check_next(ls, \".\"))\n            return TK_DOTS;   /* ... */\n          else return TK_CONCAT;   /* .. */\n        }\n        else if (!isdigit(ls->current)) return '.';\n        else {\n          read_numeral(ls, seminfo);\n          return TK_NUMBER;\n        }\n      }\n      case EOZ: {\n        return TK_EOS;\n      }\n      default: {\n        if (isspace(ls->current)) {\n          lua_assert(!currIsNewline(ls));\n          next(ls);\n          continue;\n        }\n        else if (isdigit(ls->current)) {\n          read_numeral(ls, seminfo);\n          return TK_NUMBER;\n        }\n        else if (isalpha(ls->current) || ls->current == '_') {\n          /* identifier or reserved word */\n          TString *ts;\n          do {\n            save_and_next(ls);\n          } while (isalnum(ls->current) || ls->current == '_');\n          ts = luaX_newstring(ls, luaZ_buffer(ls->buff),\n                                  luaZ_bufflen(ls->buff));\n          if (ts->tsv.reserved > 0)  /* reserved word? */\n            return ts->tsv.reserved - 1 + FIRST_RESERVED;\n          else {\n            seminfo->ts = ts;\n            return TK_NAME;\n          }\n        }\n        else {\n          int c = ls->current;\n          next(ls);\n          return c;  /* single-char tokens (+ - / ...) */\n        }\n      }\n    }\n  }\n}\n\n\nvoid luaX_next (LexState *ls) {\n  ls->lastline = ls->linenumber;\n  if (ls->lookahead.token != TK_EOS) {  /* is there a look-ahead token? */\n    ls->t = ls->lookahead;  /* use this one */\n    ls->lookahead.token = TK_EOS;  /* and discharge it */\n  }\n  else\n    ls->t.token = llex(ls, &ls->t.seminfo);  /* read next token */\n}\n\n\nvoid luaX_lookahead (LexState *ls) {\n  lua_assert(ls->lookahead.token == TK_EOS);\n  ls->lookahead.token = llex(ls, &ls->lookahead.seminfo);\n}\n\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.8/deps/lua/src/llex.h",
    "content": "/*\n** $Id: llex.h,v 1.58.1.1 2007/12/27 13:02:25 roberto Exp $\n** Lexical Analyzer\n** See Copyright Notice in lua.h\n*/\n\n#ifndef llex_h\n#define llex_h\n\n#include \"lobject.h\"\n#include \"lzio.h\"\n\n\n#define FIRST_RESERVED\t257\n\n/* maximum length of a reserved word */\n#define TOKEN_LEN\t(sizeof(\"function\")/sizeof(char))\n\n\n/*\n* WARNING: if you change the order of this enumeration,\n* grep \"ORDER RESERVED\"\n*/\nenum RESERVED {\n  /* terminal symbols denoted by reserved words */\n  TK_AND = FIRST_RESERVED, TK_BREAK,\n  TK_DO, TK_ELSE, TK_ELSEIF, TK_END, TK_FALSE, TK_FOR, TK_FUNCTION,\n  TK_IF, TK_IN, TK_LOCAL, TK_NIL, TK_NOT, TK_OR, TK_REPEAT,\n  TK_RETURN, TK_THEN, TK_TRUE, TK_UNTIL, TK_WHILE,\n  /* other terminal symbols */\n  TK_CONCAT, TK_DOTS, TK_EQ, TK_GE, TK_LE, TK_NE, TK_NUMBER,\n  TK_NAME, TK_STRING, TK_EOS\n};\n\n/* number of reserved words */\n#define NUM_RESERVED\t(cast(int, TK_WHILE-FIRST_RESERVED+1))\n\n\n/* array with token `names' */\nLUAI_DATA const char *const luaX_tokens [];\n\n\ntypedef union {\n  lua_Number r;\n  TString *ts;\n} SemInfo;  /* semantics information */\n\n\ntypedef struct Token {\n  int token;\n  SemInfo seminfo;\n} Token;\n\n\ntypedef struct LexState {\n  int current;  /* current character (charint) */\n  int linenumber;  /* input line counter */\n  int lastline;  /* line of last token `consumed' */\n  Token t;  /* current token */\n  Token lookahead;  /* look ahead token */\n  struct FuncState *fs;  /* `FuncState' is private to the parser */\n  struct lua_State *L;\n  ZIO *z;  /* input stream */\n  Mbuffer *buff;  /* buffer for tokens */\n  TString *source;  /* current source name */\n  char decpoint;  /* locale decimal point */\n} LexState;\n\n\nLUAI_FUNC void luaX_init (lua_State *L);\nLUAI_FUNC void luaX_setinput (lua_State *L, LexState *ls, ZIO *z,\n                              TString *source);\nLUAI_FUNC TString *luaX_newstring (LexState *ls, const char *str, size_t l);\nLUAI_FUNC void luaX_next (LexState *ls);\nLUAI_FUNC void luaX_lookahead (LexState *ls);\nLUAI_FUNC void luaX_lexerror (LexState *ls, const char *msg, int token);\nLUAI_FUNC void luaX_syntaxerror (LexState *ls, const char *s);\nLUAI_FUNC const char *luaX_token2str (LexState *ls, int token);\n\n\n#endif\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.8/deps/lua/src/llimits.h",
    "content": "/*\n** $Id: llimits.h,v 1.69.1.1 2007/12/27 13:02:25 roberto Exp $\n** Limits, basic types, and some other `installation-dependent' definitions\n** See Copyright Notice in lua.h\n*/\n\n#ifndef llimits_h\n#define llimits_h\n\n\n#include <limits.h>\n#include <stddef.h>\n\n\n#include \"lua.h\"\n\n\ntypedef LUAI_UINT32 lu_int32;\n\ntypedef LUAI_UMEM lu_mem;\n\ntypedef LUAI_MEM l_mem;\n\n\n\n/* chars used as small naturals (so that `char' is reserved for characters) */\ntypedef unsigned char lu_byte;\n\n\n#define MAX_SIZET\t((size_t)(~(size_t)0)-2)\n\n#define MAX_LUMEM\t((lu_mem)(~(lu_mem)0)-2)\n\n\n#define MAX_INT (INT_MAX-2)  /* maximum value of an int (-2 for safety) */\n\n/*\n** conversion of pointer to integer\n** this is for hashing only; there is no problem if the integer\n** cannot hold the whole pointer value\n*/\n#define IntPoint(p)  ((unsigned int)(lu_mem)(p))\n\n\n\n/* type to ensure maximum alignment */\ntypedef LUAI_USER_ALIGNMENT_T L_Umaxalign;\n\n\n/* result of a `usual argument conversion' over lua_Number */\ntypedef LUAI_UACNUMBER l_uacNumber;\n\n\n/* internal assertions for in-house debugging */\n#ifdef lua_assert\n\n#define check_exp(c,e)\t\t(lua_assert(c), (e))\n#define api_check(l,e)\t\tlua_assert(e)\n\n#else\n\n#define lua_assert(c)\t\t((void)0)\n#define check_exp(c,e)\t\t(e)\n#define api_check\t\tluai_apicheck\n\n#endif\n\n\n#ifndef UNUSED\n#define UNUSED(x)\t((void)(x))\t/* to avoid warnings */\n#endif\n\n\n#ifndef cast\n#define cast(t, exp)\t((t)(exp))\n#endif\n\n#define cast_byte(i)\tcast(lu_byte, (i))\n#define cast_num(i)\tcast(lua_Number, (i))\n#define cast_int(i)\tcast(int, (i))\n\n\n\n/*\n** type for virtual-machine instructions\n** must be an unsigned with (at least) 4 bytes (see details in lopcodes.h)\n*/\ntypedef lu_int32 Instruction;\n\n\n\n/* maximum stack for a Lua function */\n#define MAXSTACK\t250\n\n\n\n/* minimum size for the string table (must be power of 2) */\n#ifndef MINSTRTABSIZE\n#define MINSTRTABSIZE\t32\n#endif\n\n\n/* minimum size for string buffer */\n#ifndef LUA_MINBUFFER\n#define LUA_MINBUFFER\t32\n#endif\n\n\n#ifndef lua_lock\n#define lua_lock(L)     ((void) 0) \n#define lua_unlock(L)   ((void) 0)\n#endif\n\n#ifndef luai_threadyield\n#define luai_threadyield(L)     {lua_unlock(L); lua_lock(L);}\n#endif\n\n\n/*\n** macro to control inclusion of some hard tests on stack reallocation\n*/ \n#ifndef HARDSTACKTESTS\n#define condhardstacktests(x)\t((void)0)\n#else\n#define condhardstacktests(x)\tx\n#endif\n\n#endif\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.8/deps/lua/src/lmathlib.c",
    "content": "/*\n** $Id: lmathlib.c,v 1.67.1.1 2007/12/27 13:02:25 roberto Exp $\n** Standard mathematical library\n** See Copyright Notice in lua.h\n*/\n\n\n#include <stdlib.h>\n#include <math.h>\n\n#define lmathlib_c\n#define LUA_LIB\n\n#include \"lua.h\"\n\n#include \"lauxlib.h\"\n#include \"lualib.h\"\n\n\n#undef PI\n#define PI (3.14159265358979323846)\n#define RADIANS_PER_DEGREE (PI/180.0)\n\n\n\nstatic int math_abs (lua_State *L) {\n  lua_pushnumber(L, fabs(luaL_checknumber(L, 1)));\n  return 1;\n}\n\nstatic int math_sin (lua_State *L) {\n  lua_pushnumber(L, sin(luaL_checknumber(L, 1)));\n  return 1;\n}\n\nstatic int math_sinh (lua_State *L) {\n  lua_pushnumber(L, sinh(luaL_checknumber(L, 1)));\n  return 1;\n}\n\nstatic int math_cos (lua_State *L) {\n  lua_pushnumber(L, cos(luaL_checknumber(L, 1)));\n  return 1;\n}\n\nstatic int math_cosh (lua_State *L) {\n  lua_pushnumber(L, cosh(luaL_checknumber(L, 1)));\n  return 1;\n}\n\nstatic int math_tan (lua_State *L) {\n  lua_pushnumber(L, tan(luaL_checknumber(L, 1)));\n  return 1;\n}\n\nstatic int math_tanh (lua_State *L) {\n  lua_pushnumber(L, tanh(luaL_checknumber(L, 1)));\n  return 1;\n}\n\nstatic int math_asin (lua_State *L) {\n  lua_pushnumber(L, asin(luaL_checknumber(L, 1)));\n  return 1;\n}\n\nstatic int math_acos (lua_State *L) {\n  lua_pushnumber(L, acos(luaL_checknumber(L, 1)));\n  return 1;\n}\n\nstatic int math_atan (lua_State *L) {\n  lua_pushnumber(L, atan(luaL_checknumber(L, 1)));\n  return 1;\n}\n\nstatic int math_atan2 (lua_State *L) {\n  lua_pushnumber(L, atan2(luaL_checknumber(L, 1), luaL_checknumber(L, 2)));\n  return 1;\n}\n\nstatic int math_ceil (lua_State *L) {\n  lua_pushnumber(L, ceil(luaL_checknumber(L, 1)));\n  return 1;\n}\n\nstatic int math_floor (lua_State *L) {\n  lua_pushnumber(L, floor(luaL_checknumber(L, 1)));\n  return 1;\n}\n\nstatic int math_fmod (lua_State *L) {\n  lua_pushnumber(L, fmod(luaL_checknumber(L, 1), luaL_checknumber(L, 2)));\n  return 1;\n}\n\nstatic int math_modf (lua_State *L) {\n  double ip;\n  double fp = modf(luaL_checknumber(L, 1), &ip);\n  lua_pushnumber(L, ip);\n  lua_pushnumber(L, fp);\n  return 2;\n}\n\nstatic int math_sqrt (lua_State *L) {\n  lua_pushnumber(L, sqrt(luaL_checknumber(L, 1)));\n  return 1;\n}\n\nstatic int math_pow (lua_State *L) {\n  lua_pushnumber(L, pow(luaL_checknumber(L, 1), luaL_checknumber(L, 2)));\n  return 1;\n}\n\nstatic int math_log (lua_State *L) {\n  lua_pushnumber(L, log(luaL_checknumber(L, 1)));\n  return 1;\n}\n\nstatic int math_log10 (lua_State *L) {\n  lua_pushnumber(L, log10(luaL_checknumber(L, 1)));\n  return 1;\n}\n\nstatic int math_exp (lua_State *L) {\n  lua_pushnumber(L, exp(luaL_checknumber(L, 1)));\n  return 1;\n}\n\nstatic int math_deg (lua_State *L) {\n  lua_pushnumber(L, luaL_checknumber(L, 1)/RADIANS_PER_DEGREE);\n  return 1;\n}\n\nstatic int math_rad (lua_State *L) {\n  lua_pushnumber(L, luaL_checknumber(L, 1)*RADIANS_PER_DEGREE);\n  return 1;\n}\n\nstatic int math_frexp (lua_State *L) {\n  int e;\n  lua_pushnumber(L, frexp(luaL_checknumber(L, 1), &e));\n  lua_pushinteger(L, e);\n  return 2;\n}\n\nstatic int math_ldexp (lua_State *L) {\n  lua_pushnumber(L, ldexp(luaL_checknumber(L, 1), luaL_checkint(L, 2)));\n  return 1;\n}\n\n\n\nstatic int math_min (lua_State *L) {\n  int n = lua_gettop(L);  /* number of arguments */\n  lua_Number dmin = luaL_checknumber(L, 1);\n  int i;\n  for (i=2; i<=n; i++) {\n    lua_Number d = luaL_checknumber(L, i);\n    if (d < dmin)\n      dmin = d;\n  }\n  lua_pushnumber(L, dmin);\n  return 1;\n}\n\n\nstatic int math_max (lua_State *L) {\n  int n = lua_gettop(L);  /* number of arguments */\n  lua_Number dmax = luaL_checknumber(L, 1);\n  int i;\n  for (i=2; i<=n; i++) {\n    lua_Number d = luaL_checknumber(L, i);\n    if (d > dmax)\n      dmax = d;\n  }\n  lua_pushnumber(L, dmax);\n  return 1;\n}\n\n\nstatic int math_random (lua_State *L) {\n  /* the `%' avoids the (rare) case of r==1, and is needed also because on\n     some systems (SunOS!) `rand()' may return a value larger than RAND_MAX */\n  lua_Number r = (lua_Number)(rand()%RAND_MAX) / (lua_Number)RAND_MAX;\n  switch (lua_gettop(L)) {  /* check number of arguments */\n    case 0: {  /* no arguments */\n      lua_pushnumber(L, r);  /* Number between 0 and 1 */\n      break;\n    }\n    case 1: {  /* only upper limit */\n      int u = luaL_checkint(L, 1);\n      luaL_argcheck(L, 1<=u, 1, \"interval is empty\");\n      lua_pushnumber(L, floor(r*u)+1);  /* int between 1 and `u' */\n      break;\n    }\n    case 2: {  /* lower and upper limits */\n      int l = luaL_checkint(L, 1);\n      int u = luaL_checkint(L, 2);\n      luaL_argcheck(L, l<=u, 2, \"interval is empty\");\n      lua_pushnumber(L, floor(r*(u-l+1))+l);  /* int between `l' and `u' */\n      break;\n    }\n    default: return luaL_error(L, \"wrong number of arguments\");\n  }\n  return 1;\n}\n\n\nstatic int math_randomseed (lua_State *L) {\n  srand(luaL_checkint(L, 1));\n  return 0;\n}\n\n\nstatic const luaL_Reg mathlib[] = {\n  {\"abs\",   math_abs},\n  {\"acos\",  math_acos},\n  {\"asin\",  math_asin},\n  {\"atan2\", math_atan2},\n  {\"atan\",  math_atan},\n  {\"ceil\",  math_ceil},\n  {\"cosh\",   math_cosh},\n  {\"cos\",   math_cos},\n  {\"deg\",   math_deg},\n  {\"exp\",   math_exp},\n  {\"floor\", math_floor},\n  {\"fmod\",   math_fmod},\n  {\"frexp\", math_frexp},\n  {\"ldexp\", math_ldexp},\n  {\"log10\", math_log10},\n  {\"log\",   math_log},\n  {\"max\",   math_max},\n  {\"min\",   math_min},\n  {\"modf\",   math_modf},\n  {\"pow\",   math_pow},\n  {\"rad\",   math_rad},\n  {\"random\",     math_random},\n  {\"randomseed\", math_randomseed},\n  {\"sinh\",   math_sinh},\n  {\"sin\",   math_sin},\n  {\"sqrt\",  math_sqrt},\n  {\"tanh\",   math_tanh},\n  {\"tan\",   math_tan},\n  {NULL, NULL}\n};\n\n\n/*\n** Open math library\n*/\nLUALIB_API int luaopen_math (lua_State *L) {\n  luaL_register(L, LUA_MATHLIBNAME, mathlib);\n  lua_pushnumber(L, PI);\n  lua_setfield(L, -2, \"pi\");\n  lua_pushnumber(L, HUGE_VAL);\n  lua_setfield(L, -2, \"huge\");\n#if defined(LUA_COMPAT_MOD)\n  lua_getfield(L, -1, \"fmod\");\n  lua_setfield(L, -2, \"mod\");\n#endif\n  return 1;\n}\n\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.8/deps/lua/src/lmem.c",
    "content": "/*\n** $Id: lmem.c,v 1.70.1.1 2007/12/27 13:02:25 roberto Exp $\n** Interface to Memory Manager\n** See Copyright Notice in lua.h\n*/\n\n\n#include <stddef.h>\n\n#define lmem_c\n#define LUA_CORE\n\n#include \"lua.h\"\n\n#include \"ldebug.h\"\n#include \"ldo.h\"\n#include \"lmem.h\"\n#include \"lobject.h\"\n#include \"lstate.h\"\n\n\n\n/*\n** About the realloc function:\n** void * frealloc (void *ud, void *ptr, size_t osize, size_t nsize);\n** (`osize' is the old size, `nsize' is the new size)\n**\n** Lua ensures that (ptr == NULL) iff (osize == 0).\n**\n** * frealloc(ud, NULL, 0, x) creates a new block of size `x'\n**\n** * frealloc(ud, p, x, 0) frees the block `p'\n** (in this specific case, frealloc must return NULL).\n** particularly, frealloc(ud, NULL, 0, 0) does nothing\n** (which is equivalent to free(NULL) in ANSI C)\n**\n** frealloc returns NULL if it cannot create or reallocate the area\n** (any reallocation to an equal or smaller size cannot fail!)\n*/\n\n\n\n#define MINSIZEARRAY\t4\n\n\nvoid *luaM_growaux_ (lua_State *L, void *block, int *size, size_t size_elems,\n                     int limit, const char *errormsg) {\n  void *newblock;\n  int newsize;\n  if (*size >= limit/2) {  /* cannot double it? */\n    if (*size >= limit)  /* cannot grow even a little? */\n      luaG_runerror(L, errormsg);\n    newsize = limit;  /* still have at least one free place */\n  }\n  else {\n    newsize = (*size)*2;\n    if (newsize < MINSIZEARRAY)\n      newsize = MINSIZEARRAY;  /* minimum size */\n  }\n  newblock = luaM_reallocv(L, block, *size, newsize, size_elems);\n  *size = newsize;  /* update only when everything else is OK */\n  return newblock;\n}\n\n\nvoid *luaM_toobig (lua_State *L) {\n  luaG_runerror(L, \"memory allocation error: block too big\");\n  return NULL;  /* to avoid warnings */\n}\n\n\n\n/*\n** generic allocation routine.\n*/\nvoid *luaM_realloc_ (lua_State *L, void *block, size_t osize, size_t nsize) {\n  global_State *g = G(L);\n  lua_assert((osize == 0) == (block == NULL));\n  block = (*g->frealloc)(g->ud, block, osize, nsize);\n  if (block == NULL && nsize > 0)\n    luaD_throw(L, LUA_ERRMEM);\n  lua_assert((nsize == 0) == (block == NULL));\n  g->totalbytes = (g->totalbytes - osize) + nsize;\n  return block;\n}\n\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.8/deps/lua/src/lmem.h",
    "content": "/*\n** $Id: lmem.h,v 1.31.1.1 2007/12/27 13:02:25 roberto Exp $\n** Interface to Memory Manager\n** See Copyright Notice in lua.h\n*/\n\n#ifndef lmem_h\n#define lmem_h\n\n\n#include <stddef.h>\n\n#include \"llimits.h\"\n#include \"lua.h\"\n\n#define MEMERRMSG\t\"not enough memory\"\n\n\n#define luaM_reallocv(L,b,on,n,e) \\\n\t((cast(size_t, (n)+1) <= MAX_SIZET/(e)) ?  /* +1 to avoid warnings */ \\\n\t\tluaM_realloc_(L, (b), (on)*(e), (n)*(e)) : \\\n\t\tluaM_toobig(L))\n\n#define luaM_freemem(L, b, s)\tluaM_realloc_(L, (b), (s), 0)\n#define luaM_free(L, b)\t\tluaM_realloc_(L, (b), sizeof(*(b)), 0)\n#define luaM_freearray(L, b, n, t)   luaM_reallocv(L, (b), n, 0, sizeof(t))\n\n#define luaM_malloc(L,t)\tluaM_realloc_(L, NULL, 0, (t))\n#define luaM_new(L,t)\t\tcast(t *, luaM_malloc(L, sizeof(t)))\n#define luaM_newvector(L,n,t) \\\n\t\tcast(t *, luaM_reallocv(L, NULL, 0, n, sizeof(t)))\n\n#define luaM_growvector(L,v,nelems,size,t,limit,e) \\\n          if ((nelems)+1 > (size)) \\\n            ((v)=cast(t *, luaM_growaux_(L,v,&(size),sizeof(t),limit,e)))\n\n#define luaM_reallocvector(L, v,oldn,n,t) \\\n   ((v)=cast(t *, luaM_reallocv(L, v, oldn, n, sizeof(t))))\n\n\nLUAI_FUNC void *luaM_realloc_ (lua_State *L, void *block, size_t oldsize,\n                                                          size_t size);\nLUAI_FUNC void *luaM_toobig (lua_State *L);\nLUAI_FUNC void *luaM_growaux_ (lua_State *L, void *block, int *size,\n                               size_t size_elem, int limit,\n                               const char *errormsg);\n\n#endif\n\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.8/deps/lua/src/loadlib.c",
    "content": "/*\n** $Id: loadlib.c,v 1.52.1.4 2009/09/09 13:17:16 roberto Exp $\n** Dynamic library loader for Lua\n** See Copyright Notice in lua.h\n**\n** This module contains an implementation of loadlib for Unix systems\n** that have dlfcn, an implementation for Darwin (Mac OS X), an\n** implementation for Windows, and a stub for other systems.\n*/\n\n\n#include <stdlib.h>\n#include <string.h>\n\n\n#define loadlib_c\n#define LUA_LIB\n\n#include \"lua.h\"\n\n#include \"lauxlib.h\"\n#include \"lualib.h\"\n\n\n/* prefix for open functions in C libraries */\n#define LUA_POF\t\t\"luaopen_\"\n\n/* separator for open functions in C libraries */\n#define LUA_OFSEP\t\"_\"\n\n\n#define LIBPREFIX\t\"LOADLIB: \"\n\n#define POF\t\tLUA_POF\n#define LIB_FAIL\t\"open\"\n\n\n/* error codes for ll_loadfunc */\n#define ERRLIB\t\t1\n#define ERRFUNC\t\t2\n\n#define setprogdir(L)\t\t((void)0)\n\n\nstatic void ll_unloadlib (void *lib);\nstatic void *ll_load (lua_State *L, const char *path);\nstatic lua_CFunction ll_sym (lua_State *L, void *lib, const char *sym);\n\n\n\n#if defined(LUA_DL_DLOPEN)\n/*\n** {========================================================================\n** This is an implementation of loadlib based on the dlfcn interface.\n** The dlfcn interface is available in Linux, SunOS, Solaris, IRIX, FreeBSD,\n** NetBSD, AIX 4.2, HPUX 11, and  probably most other Unix flavors, at least\n** as an emulation layer on top of native functions.\n** =========================================================================\n*/\n\n#include <dlfcn.h>\n\nstatic void ll_unloadlib (void *lib) {\n  dlclose(lib);\n}\n\n\nstatic void *ll_load (lua_State *L, const char *path) {\n  void *lib = dlopen(path, RTLD_NOW);\n  if (lib == NULL) lua_pushstring(L, dlerror());\n  return lib;\n}\n\n\nstatic lua_CFunction ll_sym (lua_State *L, void *lib, const char *sym) {\n  lua_CFunction f = (lua_CFunction)dlsym(lib, sym);\n  if (f == NULL) lua_pushstring(L, dlerror());\n  return f;\n}\n\n/* }====================================================== */\n\n\n\n#elif defined(LUA_DL_DLL)\n/*\n** {======================================================================\n** This is an implementation of loadlib for Windows using native functions.\n** =======================================================================\n*/\n\n#include <windows.h>\n\n\n#undef setprogdir\n\nstatic void setprogdir (lua_State *L) {\n  char buff[MAX_PATH + 1];\n  char *lb;\n  DWORD nsize = sizeof(buff)/sizeof(char);\n  DWORD n = GetModuleFileNameA(NULL, buff, nsize);\n  if (n == 0 || n == nsize || (lb = strrchr(buff, '\\\\')) == NULL)\n    luaL_error(L, \"unable to get ModuleFileName\");\n  else {\n    *lb = '\\0';\n    luaL_gsub(L, lua_tostring(L, -1), LUA_EXECDIR, buff);\n    lua_remove(L, -2);  /* remove original string */\n  }\n}\n\n\nstatic void pusherror (lua_State *L) {\n  int error = GetLastError();\n  char buffer[128];\n  if (FormatMessageA(FORMAT_MESSAGE_IGNORE_INSERTS | FORMAT_MESSAGE_FROM_SYSTEM,\n      NULL, error, 0, buffer, sizeof(buffer), NULL))\n    lua_pushstring(L, buffer);\n  else\n    lua_pushfstring(L, \"system error %d\\n\", error);\n}\n\nstatic void ll_unloadlib (void *lib) {\n  FreeLibrary((HINSTANCE)lib);\n}\n\n\nstatic void *ll_load (lua_State *L, const char *path) {\n  HINSTANCE lib = LoadLibraryA(path);\n  if (lib == NULL) pusherror(L);\n  return lib;\n}\n\n\nstatic lua_CFunction ll_sym (lua_State *L, void *lib, const char *sym) {\n  lua_CFunction f = (lua_CFunction)GetProcAddress((HINSTANCE)lib, sym);\n  if (f == NULL) pusherror(L);\n  return f;\n}\n\n/* }====================================================== */\n\n\n\n#elif defined(LUA_DL_DYLD)\n/*\n** {======================================================================\n** Native Mac OS X / Darwin Implementation\n** =======================================================================\n*/\n\n#include <mach-o/dyld.h>\n\n\n/* Mac appends a `_' before C function names */\n#undef POF\n#define POF\t\"_\" LUA_POF\n\n\nstatic void pusherror (lua_State *L) {\n  const char *err_str;\n  const char *err_file;\n  NSLinkEditErrors err;\n  int err_num;\n  NSLinkEditError(&err, &err_num, &err_file, &err_str);\n  lua_pushstring(L, err_str);\n}\n\n\nstatic const char *errorfromcode (NSObjectFileImageReturnCode ret) {\n  switch (ret) {\n    case NSObjectFileImageInappropriateFile:\n      return \"file is not a bundle\";\n    case NSObjectFileImageArch:\n      return \"library is for wrong CPU type\";\n    case NSObjectFileImageFormat:\n      return \"bad format\";\n    case NSObjectFileImageAccess:\n      return \"cannot access file\";\n    case NSObjectFileImageFailure:\n    default:\n      return \"unable to load library\";\n  }\n}\n\n\nstatic void ll_unloadlib (void *lib) {\n  NSUnLinkModule((NSModule)lib, NSUNLINKMODULE_OPTION_RESET_LAZY_REFERENCES);\n}\n\n\nstatic void *ll_load (lua_State *L, const char *path) {\n  NSObjectFileImage img;\n  NSObjectFileImageReturnCode ret;\n  /* this would be a rare case, but prevents crashing if it happens */\n  if(!_dyld_present()) {\n    lua_pushliteral(L, \"dyld not present\");\n    return NULL;\n  }\n  ret = NSCreateObjectFileImageFromFile(path, &img);\n  if (ret == NSObjectFileImageSuccess) {\n    NSModule mod = NSLinkModule(img, path, NSLINKMODULE_OPTION_PRIVATE |\n                       NSLINKMODULE_OPTION_RETURN_ON_ERROR);\n    NSDestroyObjectFileImage(img);\n    if (mod == NULL) pusherror(L);\n    return mod;\n  }\n  lua_pushstring(L, errorfromcode(ret));\n  return NULL;\n}\n\n\nstatic lua_CFunction ll_sym (lua_State *L, void *lib, const char *sym) {\n  NSSymbol nss = NSLookupSymbolInModule((NSModule)lib, sym);\n  if (nss == NULL) {\n    lua_pushfstring(L, \"symbol \" LUA_QS \" not found\", sym);\n    return NULL;\n  }\n  return (lua_CFunction)NSAddressOfSymbol(nss);\n}\n\n/* }====================================================== */\n\n\n\n#else\n/*\n** {======================================================\n** Fallback for other systems\n** =======================================================\n*/\n\n#undef LIB_FAIL\n#define LIB_FAIL\t\"absent\"\n\n\n#define DLMSG\t\"dynamic libraries not enabled; check your Lua installation\"\n\n\nstatic void ll_unloadlib (void *lib) {\n  (void)lib;  /* to avoid warnings */\n}\n\n\nstatic void *ll_load (lua_State *L, const char *path) {\n  (void)path;  /* to avoid warnings */\n  lua_pushliteral(L, DLMSG);\n  return NULL;\n}\n\n\nstatic lua_CFunction ll_sym (lua_State *L, void *lib, const char *sym) {\n  (void)lib; (void)sym;  /* to avoid warnings */\n  lua_pushliteral(L, DLMSG);\n  return NULL;\n}\n\n/* }====================================================== */\n#endif\n\n\n\nstatic void **ll_register (lua_State *L, const char *path) {\n  void **plib;\n  lua_pushfstring(L, \"%s%s\", LIBPREFIX, path);\n  lua_gettable(L, LUA_REGISTRYINDEX);  /* check library in registry? */\n  if (!lua_isnil(L, -1))  /* is there an entry? */\n    plib = (void **)lua_touserdata(L, -1);\n  else {  /* no entry yet; create one */\n    lua_pop(L, 1);\n    plib = (void **)lua_newuserdata(L, sizeof(const void *));\n    *plib = NULL;\n    luaL_getmetatable(L, \"_LOADLIB\");\n    lua_setmetatable(L, -2);\n    lua_pushfstring(L, \"%s%s\", LIBPREFIX, path);\n    lua_pushvalue(L, -2);\n    lua_settable(L, LUA_REGISTRYINDEX);\n  }\n  return plib;\n}\n\n\n/*\n** __gc tag method: calls library's `ll_unloadlib' function with the lib\n** handle\n*/\nstatic int gctm (lua_State *L) {\n  void **lib = (void **)luaL_checkudata(L, 1, \"_LOADLIB\");\n  if (*lib) ll_unloadlib(*lib);\n  *lib = NULL;  /* mark library as closed */\n  return 0;\n}\n\n\nstatic int ll_loadfunc (lua_State *L, const char *path, const char *sym) {\n  void **reg = ll_register(L, path);\n  if (*reg == NULL) *reg = ll_load(L, path);\n  if (*reg == NULL)\n    return ERRLIB;  /* unable to load library */\n  else {\n    lua_CFunction f = ll_sym(L, *reg, sym);\n    if (f == NULL)\n      return ERRFUNC;  /* unable to find function */\n    lua_pushcfunction(L, f);\n    return 0;  /* return function */\n  }\n}\n\n\nstatic int ll_loadlib (lua_State *L) {\n  const char *path = luaL_checkstring(L, 1);\n  const char *init = luaL_checkstring(L, 2);\n  int stat = ll_loadfunc(L, path, init);\n  if (stat == 0)  /* no errors? */\n    return 1;  /* return the loaded function */\n  else {  /* error; error message is on stack top */\n    lua_pushnil(L);\n    lua_insert(L, -2);\n    lua_pushstring(L, (stat == ERRLIB) ?  LIB_FAIL : \"init\");\n    return 3;  /* return nil, error message, and where */\n  }\n}\n\n\n\n/*\n** {======================================================\n** 'require' function\n** =======================================================\n*/\n\n\nstatic int readable (const char *filename) {\n  FILE *f = fopen(filename, \"r\");  /* try to open file */\n  if (f == NULL) return 0;  /* open failed */\n  fclose(f);\n  return 1;\n}\n\n\nstatic const char *pushnexttemplate (lua_State *L, const char *path) {\n  const char *l;\n  while (*path == *LUA_PATHSEP) path++;  /* skip separators */\n  if (*path == '\\0') return NULL;  /* no more templates */\n  l = strchr(path, *LUA_PATHSEP);  /* find next separator */\n  if (l == NULL) l = path + strlen(path);\n  lua_pushlstring(L, path, l - path);  /* template */\n  return l;\n}\n\n\nstatic const char *findfile (lua_State *L, const char *name,\n                                           const char *pname) {\n  const char *path;\n  name = luaL_gsub(L, name, \".\", LUA_DIRSEP);\n  lua_getfield(L, LUA_ENVIRONINDEX, pname);\n  path = lua_tostring(L, -1);\n  if (path == NULL)\n    luaL_error(L, LUA_QL(\"package.%s\") \" must be a string\", pname);\n  lua_pushliteral(L, \"\");  /* error accumulator */\n  while ((path = pushnexttemplate(L, path)) != NULL) {\n    const char *filename;\n    filename = luaL_gsub(L, lua_tostring(L, -1), LUA_PATH_MARK, name);\n    lua_remove(L, -2);  /* remove path template */\n    if (readable(filename))  /* does file exist and is readable? */\n      return filename;  /* return that file name */\n    lua_pushfstring(L, \"\\n\\tno file \" LUA_QS, filename);\n    lua_remove(L, -2);  /* remove file name */\n    lua_concat(L, 2);  /* add entry to possible error message */\n  }\n  return NULL;  /* not found */\n}\n\n\nstatic void loaderror (lua_State *L, const char *filename) {\n  luaL_error(L, \"error loading module \" LUA_QS \" from file \" LUA_QS \":\\n\\t%s\",\n                lua_tostring(L, 1), filename, lua_tostring(L, -1));\n}\n\n\nstatic int loader_Lua (lua_State *L) {\n  const char *filename;\n  const char *name = luaL_checkstring(L, 1);\n  filename = findfile(L, name, \"path\");\n  if (filename == NULL) return 1;  /* library not found in this path */\n  if (luaL_loadfile(L, filename) != 0)\n    loaderror(L, filename);\n  return 1;  /* library loaded successfully */\n}\n\n\nstatic const char *mkfuncname (lua_State *L, const char *modname) {\n  const char *funcname;\n  const char *mark = strchr(modname, *LUA_IGMARK);\n  if (mark) modname = mark + 1;\n  funcname = luaL_gsub(L, modname, \".\", LUA_OFSEP);\n  funcname = lua_pushfstring(L, POF\"%s\", funcname);\n  lua_remove(L, -2);  /* remove 'gsub' result */\n  return funcname;\n}\n\n\nstatic int loader_C (lua_State *L) {\n  const char *funcname;\n  const char *name = luaL_checkstring(L, 1);\n  const char *filename = findfile(L, name, \"cpath\");\n  if (filename == NULL) return 1;  /* library not found in this path */\n  funcname = mkfuncname(L, name);\n  if (ll_loadfunc(L, filename, funcname) != 0)\n    loaderror(L, filename);\n  return 1;  /* library loaded successfully */\n}\n\n\nstatic int loader_Croot (lua_State *L) {\n  const char *funcname;\n  const char *filename;\n  const char *name = luaL_checkstring(L, 1);\n  const char *p = strchr(name, '.');\n  int stat;\n  if (p == NULL) return 0;  /* is root */\n  lua_pushlstring(L, name, p - name);\n  filename = findfile(L, lua_tostring(L, -1), \"cpath\");\n  if (filename == NULL) return 1;  /* root not found */\n  funcname = mkfuncname(L, name);\n  if ((stat = ll_loadfunc(L, filename, funcname)) != 0) {\n    if (stat != ERRFUNC) loaderror(L, filename);  /* real error */\n    lua_pushfstring(L, \"\\n\\tno module \" LUA_QS \" in file \" LUA_QS,\n                       name, filename);\n    return 1;  /* function not found */\n  }\n  return 1;\n}\n\n\nstatic int loader_preload (lua_State *L) {\n  const char *name = luaL_checkstring(L, 1);\n  lua_getfield(L, LUA_ENVIRONINDEX, \"preload\");\n  if (!lua_istable(L, -1))\n    luaL_error(L, LUA_QL(\"package.preload\") \" must be a table\");\n  lua_getfield(L, -1, name);\n  if (lua_isnil(L, -1))  /* not found? */\n    lua_pushfstring(L, \"\\n\\tno field package.preload['%s']\", name);\n  return 1;\n}\n\n\nstatic const int sentinel_ = 0;\n#define sentinel\t((void *)&sentinel_)\n\n\nstatic int ll_require (lua_State *L) {\n  const char *name = luaL_checkstring(L, 1);\n  int i;\n  lua_settop(L, 1);  /* _LOADED table will be at index 2 */\n  lua_getfield(L, LUA_REGISTRYINDEX, \"_LOADED\");\n  lua_getfield(L, 2, name);\n  if (lua_toboolean(L, -1)) {  /* is it there? */\n    if (lua_touserdata(L, -1) == sentinel)  /* check loops */\n      luaL_error(L, \"loop or previous error loading module \" LUA_QS, name);\n    return 1;  /* package is already loaded */\n  }\n  /* else must load it; iterate over available loaders */\n  lua_getfield(L, LUA_ENVIRONINDEX, \"loaders\");\n  if (!lua_istable(L, -1))\n    luaL_error(L, LUA_QL(\"package.loaders\") \" must be a table\");\n  lua_pushliteral(L, \"\");  /* error message accumulator */\n  for (i=1; ; i++) {\n    lua_rawgeti(L, -2, i);  /* get a loader */\n    if (lua_isnil(L, -1))\n      luaL_error(L, \"module \" LUA_QS \" not found:%s\",\n                    name, lua_tostring(L, -2));\n    lua_pushstring(L, name);\n    lua_call(L, 1, 1);  /* call it */\n    if (lua_isfunction(L, -1))  /* did it find module? */\n      break;  /* module loaded successfully */\n    else if (lua_isstring(L, -1))  /* loader returned error message? */\n      lua_concat(L, 2);  /* accumulate it */\n    else\n      lua_pop(L, 1);\n  }\n  lua_pushlightuserdata(L, sentinel);\n  lua_setfield(L, 2, name);  /* _LOADED[name] = sentinel */\n  lua_pushstring(L, name);  /* pass name as argument to module */\n  lua_call(L, 1, 1);  /* run loaded module */\n  if (!lua_isnil(L, -1))  /* non-nil return? */\n    lua_setfield(L, 2, name);  /* _LOADED[name] = returned value */\n  lua_getfield(L, 2, name);\n  if (lua_touserdata(L, -1) == sentinel) {   /* module did not set a value? */\n    lua_pushboolean(L, 1);  /* use true as result */\n    lua_pushvalue(L, -1);  /* extra copy to be returned */\n    lua_setfield(L, 2, name);  /* _LOADED[name] = true */\n  }\n  return 1;\n}\n\n/* }====================================================== */\n\n\n\n/*\n** {======================================================\n** 'module' function\n** =======================================================\n*/\n  \n\nstatic void setfenv (lua_State *L) {\n  lua_Debug ar;\n  if (lua_getstack(L, 1, &ar) == 0 ||\n      lua_getinfo(L, \"f\", &ar) == 0 ||  /* get calling function */\n      lua_iscfunction(L, -1))\n    luaL_error(L, LUA_QL(\"module\") \" not called from a Lua function\");\n  lua_pushvalue(L, -2);\n  lua_setfenv(L, -2);\n  lua_pop(L, 1);\n}\n\n\nstatic void dooptions (lua_State *L, int n) {\n  int i;\n  for (i = 2; i <= n; i++) {\n    lua_pushvalue(L, i);  /* get option (a function) */\n    lua_pushvalue(L, -2);  /* module */\n    lua_call(L, 1, 0);\n  }\n}\n\n\nstatic void modinit (lua_State *L, const char *modname) {\n  const char *dot;\n  lua_pushvalue(L, -1);\n  lua_setfield(L, -2, \"_M\");  /* module._M = module */\n  lua_pushstring(L, modname);\n  lua_setfield(L, -2, \"_NAME\");\n  dot = strrchr(modname, '.');  /* look for last dot in module name */\n  if (dot == NULL) dot = modname;\n  else dot++;\n  /* set _PACKAGE as package name (full module name minus last part) */\n  lua_pushlstring(L, modname, dot - modname);\n  lua_setfield(L, -2, \"_PACKAGE\");\n}\n\n\nstatic int ll_module (lua_State *L) {\n  const char *modname = luaL_checkstring(L, 1);\n  int loaded = lua_gettop(L) + 1;  /* index of _LOADED table */\n  lua_getfield(L, LUA_REGISTRYINDEX, \"_LOADED\");\n  lua_getfield(L, loaded, modname);  /* get _LOADED[modname] */\n  if (!lua_istable(L, -1)) {  /* not found? */\n    lua_pop(L, 1);  /* remove previous result */\n    /* try global variable (and create one if it does not exist) */\n    if (luaL_findtable(L, LUA_GLOBALSINDEX, modname, 1) != NULL)\n      return luaL_error(L, \"name conflict for module \" LUA_QS, modname);\n    lua_pushvalue(L, -1);\n    lua_setfield(L, loaded, modname);  /* _LOADED[modname] = new table */\n  }\n  /* check whether table already has a _NAME field */\n  lua_getfield(L, -1, \"_NAME\");\n  if (!lua_isnil(L, -1))  /* is table an initialized module? */\n    lua_pop(L, 1);\n  else {  /* no; initialize it */\n    lua_pop(L, 1);\n    modinit(L, modname);\n  }\n  lua_pushvalue(L, -1);\n  setfenv(L);\n  dooptions(L, loaded - 1);\n  return 0;\n}\n\n\nstatic int ll_seeall (lua_State *L) {\n  luaL_checktype(L, 1, LUA_TTABLE);\n  if (!lua_getmetatable(L, 1)) {\n    lua_createtable(L, 0, 1); /* create new metatable */\n    lua_pushvalue(L, -1);\n    lua_setmetatable(L, 1);\n  }\n  lua_pushvalue(L, LUA_GLOBALSINDEX);\n  lua_setfield(L, -2, \"__index\");  /* mt.__index = _G */\n  return 0;\n}\n\n\n/* }====================================================== */\n\n\n\n/* auxiliary mark (for internal use) */\n#define AUXMARK\t\t\"\\1\"\n\nstatic void setpath (lua_State *L, const char *fieldname, const char *envname,\n                                   const char *def) {\n  const char *path = getenv(envname);\n  if (path == NULL)  /* no environment variable? */\n    lua_pushstring(L, def);  /* use default */\n  else {\n    /* replace \";;\" by \";AUXMARK;\" and then AUXMARK by default path */\n    path = luaL_gsub(L, path, LUA_PATHSEP LUA_PATHSEP,\n                              LUA_PATHSEP AUXMARK LUA_PATHSEP);\n    luaL_gsub(L, path, AUXMARK, def);\n    lua_remove(L, -2);\n  }\n  setprogdir(L);\n  lua_setfield(L, -2, fieldname);\n}\n\n\nstatic const luaL_Reg pk_funcs[] = {\n  {\"loadlib\", ll_loadlib},\n  {\"seeall\", ll_seeall},\n  {NULL, NULL}\n};\n\n\nstatic const luaL_Reg ll_funcs[] = {\n  {\"module\", ll_module},\n  {\"require\", ll_require},\n  {NULL, NULL}\n};\n\n\nstatic const lua_CFunction loaders[] =\n  {loader_preload, loader_Lua, loader_C, loader_Croot, NULL};\n\n\nLUALIB_API int luaopen_package (lua_State *L) {\n  int i;\n  /* create new type _LOADLIB */\n  luaL_newmetatable(L, \"_LOADLIB\");\n  lua_pushcfunction(L, gctm);\n  lua_setfield(L, -2, \"__gc\");\n  /* create `package' table */\n  luaL_register(L, LUA_LOADLIBNAME, pk_funcs);\n#if defined(LUA_COMPAT_LOADLIB) \n  lua_getfield(L, -1, \"loadlib\");\n  lua_setfield(L, LUA_GLOBALSINDEX, \"loadlib\");\n#endif\n  lua_pushvalue(L, -1);\n  lua_replace(L, LUA_ENVIRONINDEX);\n  /* create `loaders' table */\n  lua_createtable(L, sizeof(loaders)/sizeof(loaders[0]) - 1, 0);\n  /* fill it with pre-defined loaders */\n  for (i=0; loaders[i] != NULL; i++) {\n    lua_pushcfunction(L, loaders[i]);\n    lua_rawseti(L, -2, i+1);\n  }\n  lua_setfield(L, -2, \"loaders\");  /* put it in field `loaders' */\n  setpath(L, \"path\", LUA_PATH, LUA_PATH_DEFAULT);  /* set field `path' */\n  setpath(L, \"cpath\", LUA_CPATH, LUA_CPATH_DEFAULT); /* set field `cpath' */\n  /* store config information */\n  lua_pushliteral(L, LUA_DIRSEP \"\\n\" LUA_PATHSEP \"\\n\" LUA_PATH_MARK \"\\n\"\n                     LUA_EXECDIR \"\\n\" LUA_IGMARK);\n  lua_setfield(L, -2, \"config\");\n  /* set field `loaded' */\n  luaL_findtable(L, LUA_REGISTRYINDEX, \"_LOADED\", 2);\n  lua_setfield(L, -2, \"loaded\");\n  /* set field `preload' */\n  lua_newtable(L);\n  lua_setfield(L, -2, \"preload\");\n  lua_pushvalue(L, LUA_GLOBALSINDEX);\n  luaL_register(L, NULL, ll_funcs);  /* open lib into global table */\n  lua_pop(L, 1);\n  return 1;  /* return 'package' table */\n}\n\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.8/deps/lua/src/lobject.c",
    "content": "/*\n** $Id: lobject.c,v 2.22.1.1 2007/12/27 13:02:25 roberto Exp $\n** Some generic functions over Lua objects\n** See Copyright Notice in lua.h\n*/\n\n#include <ctype.h>\n#include <stdarg.h>\n#include <stdio.h>\n#include <stdlib.h>\n#include <string.h>\n\n#define lobject_c\n#define LUA_CORE\n\n#include \"lua.h\"\n\n#include \"ldo.h\"\n#include \"lmem.h\"\n#include \"lobject.h\"\n#include \"lstate.h\"\n#include \"lstring.h\"\n#include \"lvm.h\"\n\n\n\nconst TValue luaO_nilobject_ = {{NULL}, LUA_TNIL};\n\n\n/*\n** converts an integer to a \"floating point byte\", represented as\n** (eeeeexxx), where the real value is (1xxx) * 2^(eeeee - 1) if\n** eeeee != 0 and (xxx) otherwise.\n*/\nint luaO_int2fb (unsigned int x) {\n  int e = 0;  /* expoent */\n  while (x >= 16) {\n    x = (x+1) >> 1;\n    e++;\n  }\n  if (x < 8) return x;\n  else return ((e+1) << 3) | (cast_int(x) - 8);\n}\n\n\n/* converts back */\nint luaO_fb2int (int x) {\n  int e = (x >> 3) & 31;\n  if (e == 0) return x;\n  else return ((x & 7)+8) << (e - 1);\n}\n\n\nint luaO_log2 (unsigned int x) {\n  static const lu_byte log_2[256] = {\n    0,1,2,2,3,3,3,3,4,4,4,4,4,4,4,4,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,\n    6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,\n    7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,\n    7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,\n    8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,\n    8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,\n    8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,\n    8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8\n  };\n  int l = -1;\n  while (x >= 256) { l += 8; x >>= 8; }\n  return l + log_2[x];\n\n}\n\n\nint luaO_rawequalObj (const TValue *t1, const TValue *t2) {\n  if (ttype(t1) != ttype(t2)) return 0;\n  else switch (ttype(t1)) {\n    case LUA_TNIL:\n      return 1;\n    case LUA_TNUMBER:\n      return luai_numeq(nvalue(t1), nvalue(t2));\n    case LUA_TBOOLEAN:\n      return bvalue(t1) == bvalue(t2);  /* boolean true must be 1 !! */\n    case LUA_TLIGHTUSERDATA:\n      return pvalue(t1) == pvalue(t2);\n    default:\n      lua_assert(iscollectable(t1));\n      return gcvalue(t1) == gcvalue(t2);\n  }\n}\n\n\nint luaO_str2d (const char *s, lua_Number *result) {\n  char *endptr;\n  *result = lua_str2number(s, &endptr);\n  if (endptr == s) return 0;  /* conversion failed */\n  if (*endptr == 'x' || *endptr == 'X')  /* maybe an hexadecimal constant? */\n    *result = cast_num(strtoul(s, &endptr, 16));\n  if (*endptr == '\\0') return 1;  /* most common case */\n  while (isspace(cast(unsigned char, *endptr))) endptr++;\n  if (*endptr != '\\0') return 0;  /* invalid trailing characters? */\n  return 1;\n}\n\n\n\nstatic void pushstr (lua_State *L, const char *str) {\n  setsvalue2s(L, L->top, luaS_new(L, str));\n  incr_top(L);\n}\n\n\n/* this function handles only `%d', `%c', %f, %p, and `%s' formats */\nconst char *luaO_pushvfstring (lua_State *L, const char *fmt, va_list argp) {\n  int n = 1;\n  pushstr(L, \"\");\n  for (;;) {\n    const char *e = strchr(fmt, '%');\n    if (e == NULL) break;\n    setsvalue2s(L, L->top, luaS_newlstr(L, fmt, e-fmt));\n    incr_top(L);\n    switch (*(e+1)) {\n      case 's': {\n        const char *s = va_arg(argp, char *);\n        if (s == NULL) s = \"(null)\";\n        pushstr(L, s);\n        break;\n      }\n      case 'c': {\n        char buff[2];\n        buff[0] = cast(char, va_arg(argp, int));\n        buff[1] = '\\0';\n        pushstr(L, buff);\n        break;\n      }\n      case 'd': {\n        setnvalue(L->top, cast_num(va_arg(argp, int)));\n        incr_top(L);\n        break;\n      }\n      case 'f': {\n        setnvalue(L->top, cast_num(va_arg(argp, l_uacNumber)));\n        incr_top(L);\n        break;\n      }\n      case 'p': {\n        char buff[4*sizeof(void *) + 8]; /* should be enough space for a `%p' */\n        sprintf(buff, \"%p\", va_arg(argp, void *));\n        pushstr(L, buff);\n        break;\n      }\n      case '%': {\n        pushstr(L, \"%\");\n        break;\n      }\n      default: {\n        char buff[3];\n        buff[0] = '%';\n        buff[1] = *(e+1);\n        buff[2] = '\\0';\n        pushstr(L, buff);\n        break;\n      }\n    }\n    n += 2;\n    fmt = e+2;\n  }\n  pushstr(L, fmt);\n  luaV_concat(L, n+1, cast_int(L->top - L->base) - 1);\n  L->top -= n;\n  return svalue(L->top - 1);\n}\n\n\nconst char *luaO_pushfstring (lua_State *L, const char *fmt, ...) {\n  const char *msg;\n  va_list argp;\n  va_start(argp, fmt);\n  msg = luaO_pushvfstring(L, fmt, argp);\n  va_end(argp);\n  return msg;\n}\n\n\nvoid luaO_chunkid (char *out, const char *source, size_t bufflen) {\n  if (*source == '=') {\n    strncpy(out, source+1, bufflen);  /* remove first char */\n    out[bufflen-1] = '\\0';  /* ensures null termination */\n  }\n  else {  /* out = \"source\", or \"...source\" */\n    if (*source == '@') {\n      size_t l;\n      source++;  /* skip the `@' */\n      bufflen -= sizeof(\" '...' \");\n      l = strlen(source);\n      strcpy(out, \"\");\n      if (l > bufflen) {\n        source += (l-bufflen);  /* get last part of file name */\n        strcat(out, \"...\");\n      }\n      strcat(out, source);\n    }\n    else {  /* out = [string \"string\"] */\n      size_t len = strcspn(source, \"\\n\\r\");  /* stop at first newline */\n      bufflen -= sizeof(\" [string \\\"...\\\"] \");\n      if (len > bufflen) len = bufflen;\n      strcpy(out, \"[string \\\"\");\n      if (source[len] != '\\0') {  /* must truncate? */\n        strncat(out, source, len);\n        strcat(out, \"...\");\n      }\n      else\n        strcat(out, source);\n      strcat(out, \"\\\"]\");\n    }\n  }\n}\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.8/deps/lua/src/lobject.h",
    "content": "/*\n** $Id: lobject.h,v 2.20.1.2 2008/08/06 13:29:48 roberto Exp $\n** Type definitions for Lua objects\n** See Copyright Notice in lua.h\n*/\n\n\n#ifndef lobject_h\n#define lobject_h\n\n\n#include <stdarg.h>\n\n\n#include \"llimits.h\"\n#include \"lua.h\"\n\n\n/* tags for values visible from Lua */\n#define LAST_TAG\tLUA_TTHREAD\n\n#define NUM_TAGS\t(LAST_TAG+1)\n\n\n/*\n** Extra tags for non-values\n*/\n#define LUA_TPROTO\t(LAST_TAG+1)\n#define LUA_TUPVAL\t(LAST_TAG+2)\n#define LUA_TDEADKEY\t(LAST_TAG+3)\n\n\n/*\n** Union of all collectable objects\n*/\ntypedef union GCObject GCObject;\n\n\n/*\n** Common Header for all collectable objects (in macro form, to be\n** included in other objects)\n*/\n#define CommonHeader\tGCObject *next; lu_byte tt; lu_byte marked\n\n\n/*\n** Common header in struct form\n*/\ntypedef struct GCheader {\n  CommonHeader;\n} GCheader;\n\n\n\n\n/*\n** Union of all Lua values\n*/\ntypedef union {\n  GCObject *gc;\n  void *p;\n  lua_Number n;\n  int b;\n} Value;\n\n\n/*\n** Tagged Values\n*/\n\n#define TValuefields\tValue value; int tt\n\ntypedef struct lua_TValue {\n  TValuefields;\n} TValue;\n\n\n/* Macros to test type */\n#define ttisnil(o)\t(ttype(o) == LUA_TNIL)\n#define ttisnumber(o)\t(ttype(o) == LUA_TNUMBER)\n#define ttisstring(o)\t(ttype(o) == LUA_TSTRING)\n#define ttistable(o)\t(ttype(o) == LUA_TTABLE)\n#define ttisfunction(o)\t(ttype(o) == LUA_TFUNCTION)\n#define ttisboolean(o)\t(ttype(o) == LUA_TBOOLEAN)\n#define ttisuserdata(o)\t(ttype(o) == LUA_TUSERDATA)\n#define ttisthread(o)\t(ttype(o) == LUA_TTHREAD)\n#define ttislightuserdata(o)\t(ttype(o) == LUA_TLIGHTUSERDATA)\n\n/* Macros to access values */\n#define ttype(o)\t((o)->tt)\n#define gcvalue(o)\tcheck_exp(iscollectable(o), (o)->value.gc)\n#define pvalue(o)\tcheck_exp(ttislightuserdata(o), (o)->value.p)\n#define nvalue(o)\tcheck_exp(ttisnumber(o), (o)->value.n)\n#define rawtsvalue(o)\tcheck_exp(ttisstring(o), &(o)->value.gc->ts)\n#define tsvalue(o)\t(&rawtsvalue(o)->tsv)\n#define rawuvalue(o)\tcheck_exp(ttisuserdata(o), &(o)->value.gc->u)\n#define uvalue(o)\t(&rawuvalue(o)->uv)\n#define clvalue(o)\tcheck_exp(ttisfunction(o), &(o)->value.gc->cl)\n#define hvalue(o)\tcheck_exp(ttistable(o), &(o)->value.gc->h)\n#define bvalue(o)\tcheck_exp(ttisboolean(o), (o)->value.b)\n#define thvalue(o)\tcheck_exp(ttisthread(o), &(o)->value.gc->th)\n\n#define l_isfalse(o)\t(ttisnil(o) || (ttisboolean(o) && bvalue(o) == 0))\n\n/*\n** for internal debug only\n*/\n#define checkconsistency(obj) \\\n  lua_assert(!iscollectable(obj) || (ttype(obj) == (obj)->value.gc->gch.tt))\n\n#define checkliveness(g,obj) \\\n  lua_assert(!iscollectable(obj) || \\\n  ((ttype(obj) == (obj)->value.gc->gch.tt) && !isdead(g, (obj)->value.gc)))\n\n\n/* Macros to set values */\n#define setnilvalue(obj) ((obj)->tt=LUA_TNIL)\n\n#define setnvalue(obj,x) \\\n  { TValue *i_o=(obj); i_o->value.n=(x); i_o->tt=LUA_TNUMBER; }\n\n#define setpvalue(obj,x) \\\n  { TValue *i_o=(obj); i_o->value.p=(x); i_o->tt=LUA_TLIGHTUSERDATA; }\n\n#define setbvalue(obj,x) \\\n  { TValue *i_o=(obj); i_o->value.b=(x); i_o->tt=LUA_TBOOLEAN; }\n\n#define setsvalue(L,obj,x) \\\n  { TValue *i_o=(obj); \\\n    i_o->value.gc=cast(GCObject *, (x)); i_o->tt=LUA_TSTRING; \\\n    checkliveness(G(L),i_o); }\n\n#define setuvalue(L,obj,x) \\\n  { TValue *i_o=(obj); \\\n    i_o->value.gc=cast(GCObject *, (x)); i_o->tt=LUA_TUSERDATA; \\\n    checkliveness(G(L),i_o); }\n\n#define setthvalue(L,obj,x) \\\n  { TValue *i_o=(obj); \\\n    i_o->value.gc=cast(GCObject *, (x)); i_o->tt=LUA_TTHREAD; \\\n    checkliveness(G(L),i_o); }\n\n#define setclvalue(L,obj,x) \\\n  { TValue *i_o=(obj); \\\n    i_o->value.gc=cast(GCObject *, (x)); i_o->tt=LUA_TFUNCTION; \\\n    checkliveness(G(L),i_o); }\n\n#define sethvalue(L,obj,x) \\\n  { TValue *i_o=(obj); \\\n    i_o->value.gc=cast(GCObject *, (x)); i_o->tt=LUA_TTABLE; \\\n    checkliveness(G(L),i_o); }\n\n#define setptvalue(L,obj,x) \\\n  { TValue *i_o=(obj); \\\n    i_o->value.gc=cast(GCObject *, (x)); i_o->tt=LUA_TPROTO; \\\n    checkliveness(G(L),i_o); }\n\n\n\n\n#define setobj(L,obj1,obj2) \\\n  { const TValue *o2=(obj2); TValue *o1=(obj1); \\\n    o1->value = o2->value; o1->tt=o2->tt; \\\n    checkliveness(G(L),o1); }\n\n\n/*\n** different types of sets, according to destination\n*/\n\n/* from stack to (same) stack */\n#define setobjs2s\tsetobj\n/* to stack (not from same stack) */\n#define setobj2s\tsetobj\n#define setsvalue2s\tsetsvalue\n#define sethvalue2s\tsethvalue\n#define setptvalue2s\tsetptvalue\n/* from table to same table */\n#define setobjt2t\tsetobj\n/* to table */\n#define setobj2t\tsetobj\n/* to new object */\n#define setobj2n\tsetobj\n#define setsvalue2n\tsetsvalue\n\n#define setttype(obj, tt) (ttype(obj) = (tt))\n\n\n#define iscollectable(o)\t(ttype(o) >= LUA_TSTRING)\n\n\n\ntypedef TValue *StkId;  /* index to stack elements */\n\n\n/*\n** String headers for string table\n*/\ntypedef union TString {\n  L_Umaxalign dummy;  /* ensures maximum alignment for strings */\n  struct {\n    CommonHeader;\n    lu_byte reserved;\n    unsigned int hash;\n    size_t len;\n  } tsv;\n} TString;\n\n\n#define getstr(ts)\tcast(const char *, (ts) + 1)\n#define svalue(o)       getstr(rawtsvalue(o))\n\n\n\ntypedef union Udata {\n  L_Umaxalign dummy;  /* ensures maximum alignment for `local' udata */\n  struct {\n    CommonHeader;\n    struct Table *metatable;\n    struct Table *env;\n    size_t len;\n  } uv;\n} Udata;\n\n\n\n\n/*\n** Function Prototypes\n*/\ntypedef struct Proto {\n  CommonHeader;\n  TValue *k;  /* constants used by the function */\n  Instruction *code;\n  struct Proto **p;  /* functions defined inside the function */\n  int *lineinfo;  /* map from opcodes to source lines */\n  struct LocVar *locvars;  /* information about local variables */\n  TString **upvalues;  /* upvalue names */\n  TString  *source;\n  int sizeupvalues;\n  int sizek;  /* size of `k' */\n  int sizecode;\n  int sizelineinfo;\n  int sizep;  /* size of `p' */\n  int sizelocvars;\n  int linedefined;\n  int lastlinedefined;\n  GCObject *gclist;\n  lu_byte nups;  /* number of upvalues */\n  lu_byte numparams;\n  lu_byte is_vararg;\n  lu_byte maxstacksize;\n} Proto;\n\n\n/* masks for new-style vararg */\n#define VARARG_HASARG\t\t1\n#define VARARG_ISVARARG\t\t2\n#define VARARG_NEEDSARG\t\t4\n\n\ntypedef struct LocVar {\n  TString *varname;\n  int startpc;  /* first point where variable is active */\n  int endpc;    /* first point where variable is dead */\n} LocVar;\n\n\n\n/*\n** Upvalues\n*/\n\ntypedef struct UpVal {\n  CommonHeader;\n  TValue *v;  /* points to stack or to its own value */\n  union {\n    TValue value;  /* the value (when closed) */\n    struct {  /* double linked list (when open) */\n      struct UpVal *prev;\n      struct UpVal *next;\n    } l;\n  } u;\n} UpVal;\n\n\n/*\n** Closures\n*/\n\n#define ClosureHeader \\\n\tCommonHeader; lu_byte isC; lu_byte nupvalues; GCObject *gclist; \\\n\tstruct Table *env\n\ntypedef struct CClosure {\n  ClosureHeader;\n  lua_CFunction f;\n  TValue upvalue[1];\n} CClosure;\n\n\ntypedef struct LClosure {\n  ClosureHeader;\n  struct Proto *p;\n  UpVal *upvals[1];\n} LClosure;\n\n\ntypedef union Closure {\n  CClosure c;\n  LClosure l;\n} Closure;\n\n\n#define iscfunction(o)\t(ttype(o) == LUA_TFUNCTION && clvalue(o)->c.isC)\n#define isLfunction(o)\t(ttype(o) == LUA_TFUNCTION && !clvalue(o)->c.isC)\n\n\n/*\n** Tables\n*/\n\ntypedef union TKey {\n  struct {\n    TValuefields;\n    struct Node *next;  /* for chaining */\n  } nk;\n  TValue tvk;\n} TKey;\n\n\ntypedef struct Node {\n  TValue i_val;\n  TKey i_key;\n} Node;\n\n\ntypedef struct Table {\n  CommonHeader;\n  lu_byte flags;  /* 1<<p means tagmethod(p) is not present */ \n  lu_byte lsizenode;  /* log2 of size of `node' array */\n  struct Table *metatable;\n  TValue *array;  /* array part */\n  Node *node;\n  Node *lastfree;  /* any free position is before this position */\n  GCObject *gclist;\n  int sizearray;  /* size of `array' array */\n} Table;\n\n\n\n/*\n** `module' operation for hashing (size is always a power of 2)\n*/\n#define lmod(s,size) \\\n\t(check_exp((size&(size-1))==0, (cast(int, (s) & ((size)-1)))))\n\n\n#define twoto(x)\t(1<<(x))\n#define sizenode(t)\t(twoto((t)->lsizenode))\n\n\n#define luaO_nilobject\t\t(&luaO_nilobject_)\n\nLUAI_DATA const TValue luaO_nilobject_;\n\n#define ceillog2(x)\t(luaO_log2((x)-1) + 1)\n\nLUAI_FUNC int luaO_log2 (unsigned int x);\nLUAI_FUNC int luaO_int2fb (unsigned int x);\nLUAI_FUNC int luaO_fb2int (int x);\nLUAI_FUNC int luaO_rawequalObj (const TValue *t1, const TValue *t2);\nLUAI_FUNC int luaO_str2d (const char *s, lua_Number *result);\nLUAI_FUNC const char *luaO_pushvfstring (lua_State *L, const char *fmt,\n                                                       va_list argp);\nLUAI_FUNC const char *luaO_pushfstring (lua_State *L, const char *fmt, ...);\nLUAI_FUNC void luaO_chunkid (char *out, const char *source, size_t len);\n\n\n#endif\n\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.8/deps/lua/src/lopcodes.c",
    "content": "/*\n** $Id: lopcodes.c,v 1.37.1.1 2007/12/27 13:02:25 roberto Exp $\n** See Copyright Notice in lua.h\n*/\n\n\n#define lopcodes_c\n#define LUA_CORE\n\n\n#include \"lopcodes.h\"\n\n\n/* ORDER OP */\n\nconst char *const luaP_opnames[NUM_OPCODES+1] = {\n  \"MOVE\",\n  \"LOADK\",\n  \"LOADBOOL\",\n  \"LOADNIL\",\n  \"GETUPVAL\",\n  \"GETGLOBAL\",\n  \"GETTABLE\",\n  \"SETGLOBAL\",\n  \"SETUPVAL\",\n  \"SETTABLE\",\n  \"NEWTABLE\",\n  \"SELF\",\n  \"ADD\",\n  \"SUB\",\n  \"MUL\",\n  \"DIV\",\n  \"MOD\",\n  \"POW\",\n  \"UNM\",\n  \"NOT\",\n  \"LEN\",\n  \"CONCAT\",\n  \"JMP\",\n  \"EQ\",\n  \"LT\",\n  \"LE\",\n  \"TEST\",\n  \"TESTSET\",\n  \"CALL\",\n  \"TAILCALL\",\n  \"RETURN\",\n  \"FORLOOP\",\n  \"FORPREP\",\n  \"TFORLOOP\",\n  \"SETLIST\",\n  \"CLOSE\",\n  \"CLOSURE\",\n  \"VARARG\",\n  NULL\n};\n\n\n#define opmode(t,a,b,c,m) (((t)<<7) | ((a)<<6) | ((b)<<4) | ((c)<<2) | (m))\n\nconst lu_byte luaP_opmodes[NUM_OPCODES] = {\n/*       T  A    B       C     mode\t\t   opcode\t*/\n  opmode(0, 1, OpArgR, OpArgN, iABC) \t\t/* OP_MOVE */\n ,opmode(0, 1, OpArgK, OpArgN, iABx)\t\t/* OP_LOADK */\n ,opmode(0, 1, OpArgU, OpArgU, iABC)\t\t/* OP_LOADBOOL */\n ,opmode(0, 1, OpArgR, OpArgN, iABC)\t\t/* OP_LOADNIL */\n ,opmode(0, 1, OpArgU, OpArgN, iABC)\t\t/* OP_GETUPVAL */\n ,opmode(0, 1, OpArgK, OpArgN, iABx)\t\t/* OP_GETGLOBAL */\n ,opmode(0, 1, OpArgR, OpArgK, iABC)\t\t/* OP_GETTABLE */\n ,opmode(0, 0, OpArgK, OpArgN, iABx)\t\t/* OP_SETGLOBAL */\n ,opmode(0, 0, OpArgU, OpArgN, iABC)\t\t/* OP_SETUPVAL */\n ,opmode(0, 0, OpArgK, OpArgK, iABC)\t\t/* OP_SETTABLE */\n ,opmode(0, 1, OpArgU, OpArgU, iABC)\t\t/* OP_NEWTABLE */\n ,opmode(0, 1, OpArgR, OpArgK, iABC)\t\t/* OP_SELF */\n ,opmode(0, 1, OpArgK, OpArgK, iABC)\t\t/* OP_ADD */\n ,opmode(0, 1, OpArgK, OpArgK, iABC)\t\t/* OP_SUB */\n ,opmode(0, 1, OpArgK, OpArgK, iABC)\t\t/* OP_MUL */\n ,opmode(0, 1, OpArgK, OpArgK, iABC)\t\t/* OP_DIV */\n ,opmode(0, 1, OpArgK, OpArgK, iABC)\t\t/* OP_MOD */\n ,opmode(0, 1, OpArgK, OpArgK, iABC)\t\t/* OP_POW */\n ,opmode(0, 1, OpArgR, OpArgN, iABC)\t\t/* OP_UNM */\n ,opmode(0, 1, OpArgR, OpArgN, iABC)\t\t/* OP_NOT */\n ,opmode(0, 1, OpArgR, OpArgN, iABC)\t\t/* OP_LEN */\n ,opmode(0, 1, OpArgR, OpArgR, iABC)\t\t/* OP_CONCAT */\n ,opmode(0, 0, OpArgR, OpArgN, iAsBx)\t\t/* OP_JMP */\n ,opmode(1, 0, OpArgK, OpArgK, iABC)\t\t/* OP_EQ */\n ,opmode(1, 0, OpArgK, OpArgK, iABC)\t\t/* OP_LT */\n ,opmode(1, 0, OpArgK, OpArgK, iABC)\t\t/* OP_LE */\n ,opmode(1, 1, OpArgR, OpArgU, iABC)\t\t/* OP_TEST */\n ,opmode(1, 1, OpArgR, OpArgU, iABC)\t\t/* OP_TESTSET */\n ,opmode(0, 1, OpArgU, OpArgU, iABC)\t\t/* OP_CALL */\n ,opmode(0, 1, OpArgU, OpArgU, iABC)\t\t/* OP_TAILCALL */\n ,opmode(0, 0, OpArgU, OpArgN, iABC)\t\t/* OP_RETURN */\n ,opmode(0, 1, OpArgR, OpArgN, iAsBx)\t\t/* OP_FORLOOP */\n ,opmode(0, 1, OpArgR, OpArgN, iAsBx)\t\t/* OP_FORPREP */\n ,opmode(1, 0, OpArgN, OpArgU, iABC)\t\t/* OP_TFORLOOP */\n ,opmode(0, 0, OpArgU, OpArgU, iABC)\t\t/* OP_SETLIST */\n ,opmode(0, 0, OpArgN, OpArgN, iABC)\t\t/* OP_CLOSE */\n ,opmode(0, 1, OpArgU, OpArgN, iABx)\t\t/* OP_CLOSURE */\n ,opmode(0, 1, OpArgU, OpArgN, iABC)\t\t/* OP_VARARG */\n};\n\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.8/deps/lua/src/lopcodes.h",
    "content": "/*\n** $Id: lopcodes.h,v 1.125.1.1 2007/12/27 13:02:25 roberto Exp $\n** Opcodes for Lua virtual machine\n** See Copyright Notice in lua.h\n*/\n\n#ifndef lopcodes_h\n#define lopcodes_h\n\n#include \"llimits.h\"\n\n\n/*===========================================================================\n  We assume that instructions are unsigned numbers.\n  All instructions have an opcode in the first 6 bits.\n  Instructions can have the following fields:\n\t`A' : 8 bits\n\t`B' : 9 bits\n\t`C' : 9 bits\n\t`Bx' : 18 bits (`B' and `C' together)\n\t`sBx' : signed Bx\n\n  A signed argument is represented in excess K; that is, the number\n  value is the unsigned value minus K. K is exactly the maximum value\n  for that argument (so that -max is represented by 0, and +max is\n  represented by 2*max), which is half the maximum for the corresponding\n  unsigned argument.\n===========================================================================*/\n\n\nenum OpMode {iABC, iABx, iAsBx};  /* basic instruction format */\n\n\n/*\n** size and position of opcode arguments.\n*/\n#define SIZE_C\t\t9\n#define SIZE_B\t\t9\n#define SIZE_Bx\t\t(SIZE_C + SIZE_B)\n#define SIZE_A\t\t8\n\n#define SIZE_OP\t\t6\n\n#define POS_OP\t\t0\n#define POS_A\t\t(POS_OP + SIZE_OP)\n#define POS_C\t\t(POS_A + SIZE_A)\n#define POS_B\t\t(POS_C + SIZE_C)\n#define POS_Bx\t\tPOS_C\n\n\n/*\n** limits for opcode arguments.\n** we use (signed) int to manipulate most arguments,\n** so they must fit in LUAI_BITSINT-1 bits (-1 for sign)\n*/\n#if SIZE_Bx < LUAI_BITSINT-1\n#define MAXARG_Bx        ((1<<SIZE_Bx)-1)\n#define MAXARG_sBx        (MAXARG_Bx>>1)         /* `sBx' is signed */\n#else\n#define MAXARG_Bx        MAX_INT\n#define MAXARG_sBx        MAX_INT\n#endif\n\n\n#define MAXARG_A        ((1<<SIZE_A)-1)\n#define MAXARG_B        ((1<<SIZE_B)-1)\n#define MAXARG_C        ((1<<SIZE_C)-1)\n\n\n/* creates a mask with `n' 1 bits at position `p' */\n#define MASK1(n,p)\t((~((~(Instruction)0)<<n))<<p)\n\n/* creates a mask with `n' 0 bits at position `p' */\n#define MASK0(n,p)\t(~MASK1(n,p))\n\n/*\n** the following macros help to manipulate instructions\n*/\n\n#define GET_OPCODE(i)\t(cast(OpCode, ((i)>>POS_OP) & MASK1(SIZE_OP,0)))\n#define SET_OPCODE(i,o)\t((i) = (((i)&MASK0(SIZE_OP,POS_OP)) | \\\n\t\t((cast(Instruction, o)<<POS_OP)&MASK1(SIZE_OP,POS_OP))))\n\n#define GETARG_A(i)\t(cast(int, ((i)>>POS_A) & MASK1(SIZE_A,0)))\n#define SETARG_A(i,u)\t((i) = (((i)&MASK0(SIZE_A,POS_A)) | \\\n\t\t((cast(Instruction, u)<<POS_A)&MASK1(SIZE_A,POS_A))))\n\n#define GETARG_B(i)\t(cast(int, ((i)>>POS_B) & MASK1(SIZE_B,0)))\n#define SETARG_B(i,b)\t((i) = (((i)&MASK0(SIZE_B,POS_B)) | \\\n\t\t((cast(Instruction, b)<<POS_B)&MASK1(SIZE_B,POS_B))))\n\n#define GETARG_C(i)\t(cast(int, ((i)>>POS_C) & MASK1(SIZE_C,0)))\n#define SETARG_C(i,b)\t((i) = (((i)&MASK0(SIZE_C,POS_C)) | \\\n\t\t((cast(Instruction, b)<<POS_C)&MASK1(SIZE_C,POS_C))))\n\n#define GETARG_Bx(i)\t(cast(int, ((i)>>POS_Bx) & MASK1(SIZE_Bx,0)))\n#define SETARG_Bx(i,b)\t((i) = (((i)&MASK0(SIZE_Bx,POS_Bx)) | \\\n\t\t((cast(Instruction, b)<<POS_Bx)&MASK1(SIZE_Bx,POS_Bx))))\n\n#define GETARG_sBx(i)\t(GETARG_Bx(i)-MAXARG_sBx)\n#define SETARG_sBx(i,b)\tSETARG_Bx((i),cast(unsigned int, (b)+MAXARG_sBx))\n\n\n#define CREATE_ABC(o,a,b,c)\t((cast(Instruction, o)<<POS_OP) \\\n\t\t\t| (cast(Instruction, a)<<POS_A) \\\n\t\t\t| (cast(Instruction, b)<<POS_B) \\\n\t\t\t| (cast(Instruction, c)<<POS_C))\n\n#define CREATE_ABx(o,a,bc)\t((cast(Instruction, o)<<POS_OP) \\\n\t\t\t| (cast(Instruction, a)<<POS_A) \\\n\t\t\t| (cast(Instruction, bc)<<POS_Bx))\n\n\n/*\n** Macros to operate RK indices\n*/\n\n/* this bit 1 means constant (0 means register) */\n#define BITRK\t\t(1 << (SIZE_B - 1))\n\n/* test whether value is a constant */\n#define ISK(x)\t\t((x) & BITRK)\n\n/* gets the index of the constant */\n#define INDEXK(r)\t((int)(r) & ~BITRK)\n\n#define MAXINDEXRK\t(BITRK - 1)\n\n/* code a constant index as a RK value */\n#define RKASK(x)\t((x) | BITRK)\n\n\n/*\n** invalid register that fits in 8 bits\n*/\n#define NO_REG\t\tMAXARG_A\n\n\n/*\n** R(x) - register\n** Kst(x) - constant (in constant table)\n** RK(x) == if ISK(x) then Kst(INDEXK(x)) else R(x)\n*/\n\n\n/*\n** grep \"ORDER OP\" if you change these enums\n*/\n\ntypedef enum {\n/*----------------------------------------------------------------------\nname\t\targs\tdescription\n------------------------------------------------------------------------*/\nOP_MOVE,/*\tA B\tR(A) := R(B)\t\t\t\t\t*/\nOP_LOADK,/*\tA Bx\tR(A) := Kst(Bx)\t\t\t\t\t*/\nOP_LOADBOOL,/*\tA B C\tR(A) := (Bool)B; if (C) pc++\t\t\t*/\nOP_LOADNIL,/*\tA B\tR(A) := ... := R(B) := nil\t\t\t*/\nOP_GETUPVAL,/*\tA B\tR(A) := UpValue[B]\t\t\t\t*/\n\nOP_GETGLOBAL,/*\tA Bx\tR(A) := Gbl[Kst(Bx)]\t\t\t\t*/\nOP_GETTABLE,/*\tA B C\tR(A) := R(B)[RK(C)]\t\t\t\t*/\n\nOP_SETGLOBAL,/*\tA Bx\tGbl[Kst(Bx)] := R(A)\t\t\t\t*/\nOP_SETUPVAL,/*\tA B\tUpValue[B] := R(A)\t\t\t\t*/\nOP_SETTABLE,/*\tA B C\tR(A)[RK(B)] := RK(C)\t\t\t\t*/\n\nOP_NEWTABLE,/*\tA B C\tR(A) := {} (size = B,C)\t\t\t\t*/\n\nOP_SELF,/*\tA B C\tR(A+1) := R(B); R(A) := R(B)[RK(C)]\t\t*/\n\nOP_ADD,/*\tA B C\tR(A) := RK(B) + RK(C)\t\t\t\t*/\nOP_SUB,/*\tA B C\tR(A) := RK(B) - RK(C)\t\t\t\t*/\nOP_MUL,/*\tA B C\tR(A) := RK(B) * RK(C)\t\t\t\t*/\nOP_DIV,/*\tA B C\tR(A) := RK(B) / RK(C)\t\t\t\t*/\nOP_MOD,/*\tA B C\tR(A) := RK(B) % RK(C)\t\t\t\t*/\nOP_POW,/*\tA B C\tR(A) := RK(B) ^ RK(C)\t\t\t\t*/\nOP_UNM,/*\tA B\tR(A) := -R(B)\t\t\t\t\t*/\nOP_NOT,/*\tA B\tR(A) := not R(B)\t\t\t\t*/\nOP_LEN,/*\tA B\tR(A) := length of R(B)\t\t\t\t*/\n\nOP_CONCAT,/*\tA B C\tR(A) := R(B).. ... ..R(C)\t\t\t*/\n\nOP_JMP,/*\tsBx\tpc+=sBx\t\t\t\t\t*/\n\nOP_EQ,/*\tA B C\tif ((RK(B) == RK(C)) ~= A) then pc++\t\t*/\nOP_LT,/*\tA B C\tif ((RK(B) <  RK(C)) ~= A) then pc++  \t\t*/\nOP_LE,/*\tA B C\tif ((RK(B) <= RK(C)) ~= A) then pc++  \t\t*/\n\nOP_TEST,/*\tA C\tif not (R(A) <=> C) then pc++\t\t\t*/ \nOP_TESTSET,/*\tA B C\tif (R(B) <=> C) then R(A) := R(B) else pc++\t*/ \n\nOP_CALL,/*\tA B C\tR(A), ... ,R(A+C-2) := R(A)(R(A+1), ... ,R(A+B-1)) */\nOP_TAILCALL,/*\tA B C\treturn R(A)(R(A+1), ... ,R(A+B-1))\t\t*/\nOP_RETURN,/*\tA B\treturn R(A), ... ,R(A+B-2)\t(see note)\t*/\n\nOP_FORLOOP,/*\tA sBx\tR(A)+=R(A+2);\n\t\t\tif R(A) <?= R(A+1) then { pc+=sBx; R(A+3)=R(A) }*/\nOP_FORPREP,/*\tA sBx\tR(A)-=R(A+2); pc+=sBx\t\t\t\t*/\n\nOP_TFORLOOP,/*\tA C\tR(A+3), ... ,R(A+2+C) := R(A)(R(A+1), R(A+2)); \n                        if R(A+3) ~= nil then R(A+2)=R(A+3) else pc++\t*/ \nOP_SETLIST,/*\tA B C\tR(A)[(C-1)*FPF+i] := R(A+i), 1 <= i <= B\t*/\n\nOP_CLOSE,/*\tA \tclose all variables in the stack up to (>=) R(A)*/\nOP_CLOSURE,/*\tA Bx\tR(A) := closure(KPROTO[Bx], R(A), ... ,R(A+n))\t*/\n\nOP_VARARG/*\tA B\tR(A), R(A+1), ..., R(A+B-1) = vararg\t\t*/\n} OpCode;\n\n\n#define NUM_OPCODES\t(cast(int, OP_VARARG) + 1)\n\n\n\n/*===========================================================================\n  Notes:\n  (*) In OP_CALL, if (B == 0) then B = top. C is the number of returns - 1,\n      and can be 0: OP_CALL then sets `top' to last_result+1, so\n      next open instruction (OP_CALL, OP_RETURN, OP_SETLIST) may use `top'.\n\n  (*) In OP_VARARG, if (B == 0) then use actual number of varargs and\n      set top (like in OP_CALL with C == 0).\n\n  (*) In OP_RETURN, if (B == 0) then return up to `top'\n\n  (*) In OP_SETLIST, if (B == 0) then B = `top';\n      if (C == 0) then next `instruction' is real C\n\n  (*) For comparisons, A specifies what condition the test should accept\n      (true or false).\n\n  (*) All `skips' (pc++) assume that next instruction is a jump\n===========================================================================*/\n\n\n/*\n** masks for instruction properties. The format is:\n** bits 0-1: op mode\n** bits 2-3: C arg mode\n** bits 4-5: B arg mode\n** bit 6: instruction set register A\n** bit 7: operator is a test\n*/  \n\nenum OpArgMask {\n  OpArgN,  /* argument is not used */\n  OpArgU,  /* argument is used */\n  OpArgR,  /* argument is a register or a jump offset */\n  OpArgK   /* argument is a constant or register/constant */\n};\n\nLUAI_DATA const lu_byte luaP_opmodes[NUM_OPCODES];\n\n#define getOpMode(m)\t(cast(enum OpMode, luaP_opmodes[m] & 3))\n#define getBMode(m)\t(cast(enum OpArgMask, (luaP_opmodes[m] >> 4) & 3))\n#define getCMode(m)\t(cast(enum OpArgMask, (luaP_opmodes[m] >> 2) & 3))\n#define testAMode(m)\t(luaP_opmodes[m] & (1 << 6))\n#define testTMode(m)\t(luaP_opmodes[m] & (1 << 7))\n\n\nLUAI_DATA const char *const luaP_opnames[NUM_OPCODES+1];  /* opcode names */\n\n\n/* number of list items to accumulate before a SETLIST instruction */\n#define LFIELDS_PER_FLUSH\t50\n\n\n#endif\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.8/deps/lua/src/loslib.c",
    "content": "/*\n** $Id: loslib.c,v 1.19.1.3 2008/01/18 16:38:18 roberto Exp $\n** Standard Operating System library\n** See Copyright Notice in lua.h\n*/\n\n\n#include <errno.h>\n#include <locale.h>\n#include <stdlib.h>\n#include <string.h>\n#include <time.h>\n\n#define loslib_c\n#define LUA_LIB\n\n#include \"lua.h\"\n\n#include \"lauxlib.h\"\n#include \"lualib.h\"\n\n\nstatic int os_pushresult (lua_State *L, int i, const char *filename) {\n  int en = errno;  /* calls to Lua API may change this value */\n  if (i) {\n    lua_pushboolean(L, 1);\n    return 1;\n  }\n  else {\n    lua_pushnil(L);\n    lua_pushfstring(L, \"%s: %s\", filename, strerror(en));\n    lua_pushinteger(L, en);\n    return 3;\n  }\n}\n\n\nstatic int os_execute (lua_State *L) {\n  lua_pushinteger(L, system(luaL_optstring(L, 1, NULL)));\n  return 1;\n}\n\n\nstatic int os_remove (lua_State *L) {\n  const char *filename = luaL_checkstring(L, 1);\n  return os_pushresult(L, remove(filename) == 0, filename);\n}\n\n\nstatic int os_rename (lua_State *L) {\n  const char *fromname = luaL_checkstring(L, 1);\n  const char *toname = luaL_checkstring(L, 2);\n  return os_pushresult(L, rename(fromname, toname) == 0, fromname);\n}\n\n\nstatic int os_tmpname (lua_State *L) {\n  char buff[LUA_TMPNAMBUFSIZE];\n  int err;\n  lua_tmpnam(buff, err);\n  if (err)\n    return luaL_error(L, \"unable to generate a unique filename\");\n  lua_pushstring(L, buff);\n  return 1;\n}\n\n\nstatic int os_getenv (lua_State *L) {\n  lua_pushstring(L, getenv(luaL_checkstring(L, 1)));  /* if NULL push nil */\n  return 1;\n}\n\n\nstatic int os_clock (lua_State *L) {\n  lua_pushnumber(L, ((lua_Number)clock())/(lua_Number)CLOCKS_PER_SEC);\n  return 1;\n}\n\n\n/*\n** {======================================================\n** Time/Date operations\n** { year=%Y, month=%m, day=%d, hour=%H, min=%M, sec=%S,\n**   wday=%w+1, yday=%j, isdst=? }\n** =======================================================\n*/\n\nstatic void setfield (lua_State *L, const char *key, int value) {\n  lua_pushinteger(L, value);\n  lua_setfield(L, -2, key);\n}\n\nstatic void setboolfield (lua_State *L, const char *key, int value) {\n  if (value < 0)  /* undefined? */\n    return;  /* does not set field */\n  lua_pushboolean(L, value);\n  lua_setfield(L, -2, key);\n}\n\nstatic int getboolfield (lua_State *L, const char *key) {\n  int res;\n  lua_getfield(L, -1, key);\n  res = lua_isnil(L, -1) ? -1 : lua_toboolean(L, -1);\n  lua_pop(L, 1);\n  return res;\n}\n\n\nstatic int getfield (lua_State *L, const char *key, int d) {\n  int res;\n  lua_getfield(L, -1, key);\n  if (lua_isnumber(L, -1))\n    res = (int)lua_tointeger(L, -1);\n  else {\n    if (d < 0)\n      return luaL_error(L, \"field \" LUA_QS \" missing in date table\", key);\n    res = d;\n  }\n  lua_pop(L, 1);\n  return res;\n}\n\n\nstatic int os_date (lua_State *L) {\n  const char *s = luaL_optstring(L, 1, \"%c\");\n  time_t t = luaL_opt(L, (time_t)luaL_checknumber, 2, time(NULL));\n  struct tm *stm;\n  if (*s == '!') {  /* UTC? */\n    stm = gmtime(&t);\n    s++;  /* skip `!' */\n  }\n  else\n    stm = localtime(&t);\n  if (stm == NULL)  /* invalid date? */\n    lua_pushnil(L);\n  else if (strcmp(s, \"*t\") == 0) {\n    lua_createtable(L, 0, 9);  /* 9 = number of fields */\n    setfield(L, \"sec\", stm->tm_sec);\n    setfield(L, \"min\", stm->tm_min);\n    setfield(L, \"hour\", stm->tm_hour);\n    setfield(L, \"day\", stm->tm_mday);\n    setfield(L, \"month\", stm->tm_mon+1);\n    setfield(L, \"year\", stm->tm_year+1900);\n    setfield(L, \"wday\", stm->tm_wday+1);\n    setfield(L, \"yday\", stm->tm_yday+1);\n    setboolfield(L, \"isdst\", stm->tm_isdst);\n  }\n  else {\n    char cc[3];\n    luaL_Buffer b;\n    cc[0] = '%'; cc[2] = '\\0';\n    luaL_buffinit(L, &b);\n    for (; *s; s++) {\n      if (*s != '%' || *(s + 1) == '\\0')  /* no conversion specifier? */\n        luaL_addchar(&b, *s);\n      else {\n        size_t reslen;\n        char buff[200];  /* should be big enough for any conversion result */\n        cc[1] = *(++s);\n        reslen = strftime(buff, sizeof(buff), cc, stm);\n        luaL_addlstring(&b, buff, reslen);\n      }\n    }\n    luaL_pushresult(&b);\n  }\n  return 1;\n}\n\n\nstatic int os_time (lua_State *L) {\n  time_t t;\n  if (lua_isnoneornil(L, 1))  /* called without args? */\n    t = time(NULL);  /* get current time */\n  else {\n    struct tm ts;\n    luaL_checktype(L, 1, LUA_TTABLE);\n    lua_settop(L, 1);  /* make sure table is at the top */\n    ts.tm_sec = getfield(L, \"sec\", 0);\n    ts.tm_min = getfield(L, \"min\", 0);\n    ts.tm_hour = getfield(L, \"hour\", 12);\n    ts.tm_mday = getfield(L, \"day\", -1);\n    ts.tm_mon = getfield(L, \"month\", -1) - 1;\n    ts.tm_year = getfield(L, \"year\", -1) - 1900;\n    ts.tm_isdst = getboolfield(L, \"isdst\");\n    t = mktime(&ts);\n  }\n  if (t == (time_t)(-1))\n    lua_pushnil(L);\n  else\n    lua_pushnumber(L, (lua_Number)t);\n  return 1;\n}\n\n\nstatic int os_difftime (lua_State *L) {\n  lua_pushnumber(L, difftime((time_t)(luaL_checknumber(L, 1)),\n                             (time_t)(luaL_optnumber(L, 2, 0))));\n  return 1;\n}\n\n/* }====================================================== */\n\n\nstatic int os_setlocale (lua_State *L) {\n  static const int cat[] = {LC_ALL, LC_COLLATE, LC_CTYPE, LC_MONETARY,\n                      LC_NUMERIC, LC_TIME};\n  static const char *const catnames[] = {\"all\", \"collate\", \"ctype\", \"monetary\",\n     \"numeric\", \"time\", NULL};\n  const char *l = luaL_optstring(L, 1, NULL);\n  int op = luaL_checkoption(L, 2, \"all\", catnames);\n  lua_pushstring(L, setlocale(cat[op], l));\n  return 1;\n}\n\n\nstatic int os_exit (lua_State *L) {\n  exit(luaL_optint(L, 1, EXIT_SUCCESS));\n}\n\nstatic const luaL_Reg syslib[] = {\n  {\"clock\",     os_clock},\n  {\"date\",      os_date},\n  {\"difftime\",  os_difftime},\n  {\"execute\",   os_execute},\n  {\"exit\",      os_exit},\n  {\"getenv\",    os_getenv},\n  {\"remove\",    os_remove},\n  {\"rename\",    os_rename},\n  {\"setlocale\", os_setlocale},\n  {\"time\",      os_time},\n  {\"tmpname\",   os_tmpname},\n  {NULL, NULL}\n};\n\n/* }====================================================== */\n\n\n\nLUALIB_API int luaopen_os (lua_State *L) {\n  luaL_register(L, LUA_OSLIBNAME, syslib);\n  return 1;\n}\n\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.8/deps/lua/src/lparser.c",
    "content": "/*\n** $Id: lparser.c,v 2.42.1.4 2011/10/21 19:31:42 roberto Exp $\n** Lua Parser\n** See Copyright Notice in lua.h\n*/\n\n\n#include <string.h>\n\n#define lparser_c\n#define LUA_CORE\n\n#include \"lua.h\"\n\n#include \"lcode.h\"\n#include \"ldebug.h\"\n#include \"ldo.h\"\n#include \"lfunc.h\"\n#include \"llex.h\"\n#include \"lmem.h\"\n#include \"lobject.h\"\n#include \"lopcodes.h\"\n#include \"lparser.h\"\n#include \"lstate.h\"\n#include \"lstring.h\"\n#include \"ltable.h\"\n\n\n\n#define hasmultret(k)\t\t((k) == VCALL || (k) == VVARARG)\n\n#define getlocvar(fs, i)\t((fs)->f->locvars[(fs)->actvar[i]])\n\n#define luaY_checklimit(fs,v,l,m)\tif ((v)>(l)) errorlimit(fs,l,m)\n\n\n/*\n** nodes for block list (list of active blocks)\n*/\ntypedef struct BlockCnt {\n  struct BlockCnt *previous;  /* chain */\n  int breaklist;  /* list of jumps out of this loop */\n  lu_byte nactvar;  /* # active locals outside the breakable structure */\n  lu_byte upval;  /* true if some variable in the block is an upvalue */\n  lu_byte isbreakable;  /* true if `block' is a loop */\n} BlockCnt;\n\n\n\n/*\n** prototypes for recursive non-terminal functions\n*/\nstatic void chunk (LexState *ls);\nstatic void expr (LexState *ls, expdesc *v);\n\n\nstatic void anchor_token (LexState *ls) {\n  if (ls->t.token == TK_NAME || ls->t.token == TK_STRING) {\n    TString *ts = ls->t.seminfo.ts;\n    luaX_newstring(ls, getstr(ts), ts->tsv.len);\n  }\n}\n\n\nstatic void error_expected (LexState *ls, int token) {\n  luaX_syntaxerror(ls,\n      luaO_pushfstring(ls->L, LUA_QS \" expected\", luaX_token2str(ls, token)));\n}\n\n\nstatic void errorlimit (FuncState *fs, int limit, const char *what) {\n  const char *msg = (fs->f->linedefined == 0) ?\n    luaO_pushfstring(fs->L, \"main function has more than %d %s\", limit, what) :\n    luaO_pushfstring(fs->L, \"function at line %d has more than %d %s\",\n                            fs->f->linedefined, limit, what);\n  luaX_lexerror(fs->ls, msg, 0);\n}\n\n\nstatic int testnext (LexState *ls, int c) {\n  if (ls->t.token == c) {\n    luaX_next(ls);\n    return 1;\n  }\n  else return 0;\n}\n\n\nstatic void check (LexState *ls, int c) {\n  if (ls->t.token != c)\n    error_expected(ls, c);\n}\n\nstatic void checknext (LexState *ls, int c) {\n  check(ls, c);\n  luaX_next(ls);\n}\n\n\n#define check_condition(ls,c,msg)\t{ if (!(c)) luaX_syntaxerror(ls, msg); }\n\n\n\nstatic void check_match (LexState *ls, int what, int who, int where) {\n  if (!testnext(ls, what)) {\n    if (where == ls->linenumber)\n      error_expected(ls, what);\n    else {\n      luaX_syntaxerror(ls, luaO_pushfstring(ls->L,\n             LUA_QS \" expected (to close \" LUA_QS \" at line %d)\",\n              luaX_token2str(ls, what), luaX_token2str(ls, who), where));\n    }\n  }\n}\n\n\nstatic TString *str_checkname (LexState *ls) {\n  TString *ts;\n  check(ls, TK_NAME);\n  ts = ls->t.seminfo.ts;\n  luaX_next(ls);\n  return ts;\n}\n\n\nstatic void init_exp (expdesc *e, expkind k, int i) {\n  e->f = e->t = NO_JUMP;\n  e->k = k;\n  e->u.s.info = i;\n}\n\n\nstatic void codestring (LexState *ls, expdesc *e, TString *s) {\n  init_exp(e, VK, luaK_stringK(ls->fs, s));\n}\n\n\nstatic void checkname(LexState *ls, expdesc *e) {\n  codestring(ls, e, str_checkname(ls));\n}\n\n\nstatic int registerlocalvar (LexState *ls, TString *varname) {\n  FuncState *fs = ls->fs;\n  Proto *f = fs->f;\n  int oldsize = f->sizelocvars;\n  luaM_growvector(ls->L, f->locvars, fs->nlocvars, f->sizelocvars,\n                  LocVar, SHRT_MAX, \"too many local variables\");\n  while (oldsize < f->sizelocvars) f->locvars[oldsize++].varname = NULL;\n  f->locvars[fs->nlocvars].varname = varname;\n  luaC_objbarrier(ls->L, f, varname);\n  return fs->nlocvars++;\n}\n\n\n#define new_localvarliteral(ls,v,n) \\\n  new_localvar(ls, luaX_newstring(ls, \"\" v, (sizeof(v)/sizeof(char))-1), n)\n\n\nstatic void new_localvar (LexState *ls, TString *name, int n) {\n  FuncState *fs = ls->fs;\n  luaY_checklimit(fs, fs->nactvar+n+1, LUAI_MAXVARS, \"local variables\");\n  fs->actvar[fs->nactvar+n] = cast(unsigned short, registerlocalvar(ls, name));\n}\n\n\nstatic void adjustlocalvars (LexState *ls, int nvars) {\n  FuncState *fs = ls->fs;\n  fs->nactvar = cast_byte(fs->nactvar + nvars);\n  for (; nvars; nvars--) {\n    getlocvar(fs, fs->nactvar - nvars).startpc = fs->pc;\n  }\n}\n\n\nstatic void removevars (LexState *ls, int tolevel) {\n  FuncState *fs = ls->fs;\n  while (fs->nactvar > tolevel)\n    getlocvar(fs, --fs->nactvar).endpc = fs->pc;\n}\n\n\nstatic int indexupvalue (FuncState *fs, TString *name, expdesc *v) {\n  int i;\n  Proto *f = fs->f;\n  int oldsize = f->sizeupvalues;\n  for (i=0; i<f->nups; i++) {\n    if (fs->upvalues[i].k == v->k && fs->upvalues[i].info == v->u.s.info) {\n      lua_assert(f->upvalues[i] == name);\n      return i;\n    }\n  }\n  /* new one */\n  luaY_checklimit(fs, f->nups + 1, LUAI_MAXUPVALUES, \"upvalues\");\n  luaM_growvector(fs->L, f->upvalues, f->nups, f->sizeupvalues,\n                  TString *, MAX_INT, \"\");\n  while (oldsize < f->sizeupvalues) f->upvalues[oldsize++] = NULL;\n  f->upvalues[f->nups] = name;\n  luaC_objbarrier(fs->L, f, name);\n  lua_assert(v->k == VLOCAL || v->k == VUPVAL);\n  fs->upvalues[f->nups].k = cast_byte(v->k);\n  fs->upvalues[f->nups].info = cast_byte(v->u.s.info);\n  return f->nups++;\n}\n\n\nstatic int searchvar (FuncState *fs, TString *n) {\n  int i;\n  for (i=fs->nactvar-1; i >= 0; i--) {\n    if (n == getlocvar(fs, i).varname)\n      return i;\n  }\n  return -1;  /* not found */\n}\n\n\nstatic void markupval (FuncState *fs, int level) {\n  BlockCnt *bl = fs->bl;\n  while (bl && bl->nactvar > level) bl = bl->previous;\n  if (bl) bl->upval = 1;\n}\n\n\nstatic int singlevaraux (FuncState *fs, TString *n, expdesc *var, int base) {\n  if (fs == NULL) {  /* no more levels? */\n    init_exp(var, VGLOBAL, NO_REG);  /* default is global variable */\n    return VGLOBAL;\n  }\n  else {\n    int v = searchvar(fs, n);  /* look up at current level */\n    if (v >= 0) {\n      init_exp(var, VLOCAL, v);\n      if (!base)\n        markupval(fs, v);  /* local will be used as an upval */\n      return VLOCAL;\n    }\n    else {  /* not found at current level; try upper one */\n      if (singlevaraux(fs->prev, n, var, 0) == VGLOBAL)\n        return VGLOBAL;\n      var->u.s.info = indexupvalue(fs, n, var);  /* else was LOCAL or UPVAL */\n      var->k = VUPVAL;  /* upvalue in this level */\n      return VUPVAL;\n    }\n  }\n}\n\n\nstatic void singlevar (LexState *ls, expdesc *var) {\n  TString *varname = str_checkname(ls);\n  FuncState *fs = ls->fs;\n  if (singlevaraux(fs, varname, var, 1) == VGLOBAL)\n    var->u.s.info = luaK_stringK(fs, varname);  /* info points to global name */\n}\n\n\nstatic void adjust_assign (LexState *ls, int nvars, int nexps, expdesc *e) {\n  FuncState *fs = ls->fs;\n  int extra = nvars - nexps;\n  if (hasmultret(e->k)) {\n    extra++;  /* includes call itself */\n    if (extra < 0) extra = 0;\n    luaK_setreturns(fs, e, extra);  /* last exp. provides the difference */\n    if (extra > 1) luaK_reserveregs(fs, extra-1);\n  }\n  else {\n    if (e->k != VVOID) luaK_exp2nextreg(fs, e);  /* close last expression */\n    if (extra > 0) {\n      int reg = fs->freereg;\n      luaK_reserveregs(fs, extra);\n      luaK_nil(fs, reg, extra);\n    }\n  }\n}\n\n\nstatic void enterlevel (LexState *ls) {\n  if (++ls->L->nCcalls > LUAI_MAXCCALLS)\n\tluaX_lexerror(ls, \"chunk has too many syntax levels\", 0);\n}\n\n\n#define leavelevel(ls)\t((ls)->L->nCcalls--)\n\n\nstatic void enterblock (FuncState *fs, BlockCnt *bl, lu_byte isbreakable) {\n  bl->breaklist = NO_JUMP;\n  bl->isbreakable = isbreakable;\n  bl->nactvar = fs->nactvar;\n  bl->upval = 0;\n  bl->previous = fs->bl;\n  fs->bl = bl;\n  lua_assert(fs->freereg == fs->nactvar);\n}\n\n\nstatic void leaveblock (FuncState *fs) {\n  BlockCnt *bl = fs->bl;\n  fs->bl = bl->previous;\n  removevars(fs->ls, bl->nactvar);\n  if (bl->upval)\n    luaK_codeABC(fs, OP_CLOSE, bl->nactvar, 0, 0);\n  /* a block either controls scope or breaks (never both) */\n  lua_assert(!bl->isbreakable || !bl->upval);\n  lua_assert(bl->nactvar == fs->nactvar);\n  fs->freereg = fs->nactvar;  /* free registers */\n  luaK_patchtohere(fs, bl->breaklist);\n}\n\n\nstatic void pushclosure (LexState *ls, FuncState *func, expdesc *v) {\n  FuncState *fs = ls->fs;\n  Proto *f = fs->f;\n  int oldsize = f->sizep;\n  int i;\n  luaM_growvector(ls->L, f->p, fs->np, f->sizep, Proto *,\n                  MAXARG_Bx, \"constant table overflow\");\n  while (oldsize < f->sizep) f->p[oldsize++] = NULL;\n  f->p[fs->np++] = func->f;\n  luaC_objbarrier(ls->L, f, func->f);\n  init_exp(v, VRELOCABLE, luaK_codeABx(fs, OP_CLOSURE, 0, fs->np-1));\n  for (i=0; i<func->f->nups; i++) {\n    OpCode o = (func->upvalues[i].k == VLOCAL) ? OP_MOVE : OP_GETUPVAL;\n    luaK_codeABC(fs, o, 0, func->upvalues[i].info, 0);\n  }\n}\n\n\nstatic void open_func (LexState *ls, FuncState *fs) {\n  lua_State *L = ls->L;\n  Proto *f = luaF_newproto(L);\n  fs->f = f;\n  fs->prev = ls->fs;  /* linked list of funcstates */\n  fs->ls = ls;\n  fs->L = L;\n  ls->fs = fs;\n  fs->pc = 0;\n  fs->lasttarget = -1;\n  fs->jpc = NO_JUMP;\n  fs->freereg = 0;\n  fs->nk = 0;\n  fs->np = 0;\n  fs->nlocvars = 0;\n  fs->nactvar = 0;\n  fs->bl = NULL;\n  f->source = ls->source;\n  f->maxstacksize = 2;  /* registers 0/1 are always valid */\n  fs->h = luaH_new(L, 0, 0);\n  /* anchor table of constants and prototype (to avoid being collected) */\n  sethvalue2s(L, L->top, fs->h);\n  incr_top(L);\n  setptvalue2s(L, L->top, f);\n  incr_top(L);\n}\n\n\nstatic void close_func (LexState *ls) {\n  lua_State *L = ls->L;\n  FuncState *fs = ls->fs;\n  Proto *f = fs->f;\n  removevars(ls, 0);\n  luaK_ret(fs, 0, 0);  /* final return */\n  luaM_reallocvector(L, f->code, f->sizecode, fs->pc, Instruction);\n  f->sizecode = fs->pc;\n  luaM_reallocvector(L, f->lineinfo, f->sizelineinfo, fs->pc, int);\n  f->sizelineinfo = fs->pc;\n  luaM_reallocvector(L, f->k, f->sizek, fs->nk, TValue);\n  f->sizek = fs->nk;\n  luaM_reallocvector(L, f->p, f->sizep, fs->np, Proto *);\n  f->sizep = fs->np;\n  luaM_reallocvector(L, f->locvars, f->sizelocvars, fs->nlocvars, LocVar);\n  f->sizelocvars = fs->nlocvars;\n  luaM_reallocvector(L, f->upvalues, f->sizeupvalues, f->nups, TString *);\n  f->sizeupvalues = f->nups;\n  lua_assert(luaG_checkcode(f));\n  lua_assert(fs->bl == NULL);\n  ls->fs = fs->prev;\n  /* last token read was anchored in defunct function; must reanchor it */\n  if (fs) anchor_token(ls);\n  L->top -= 2;  /* remove table and prototype from the stack */\n}\n\n\nProto *luaY_parser (lua_State *L, ZIO *z, Mbuffer *buff, const char *name) {\n  struct LexState lexstate;\n  struct FuncState funcstate;\n  lexstate.buff = buff;\n  luaX_setinput(L, &lexstate, z, luaS_new(L, name));\n  open_func(&lexstate, &funcstate);\n  funcstate.f->is_vararg = VARARG_ISVARARG;  /* main func. is always vararg */\n  luaX_next(&lexstate);  /* read first token */\n  chunk(&lexstate);\n  check(&lexstate, TK_EOS);\n  close_func(&lexstate);\n  lua_assert(funcstate.prev == NULL);\n  lua_assert(funcstate.f->nups == 0);\n  lua_assert(lexstate.fs == NULL);\n  return funcstate.f;\n}\n\n\n\n/*============================================================*/\n/* GRAMMAR RULES */\n/*============================================================*/\n\n\nstatic void field (LexState *ls, expdesc *v) {\n  /* field -> ['.' | ':'] NAME */\n  FuncState *fs = ls->fs;\n  expdesc key;\n  luaK_exp2anyreg(fs, v);\n  luaX_next(ls);  /* skip the dot or colon */\n  checkname(ls, &key);\n  luaK_indexed(fs, v, &key);\n}\n\n\nstatic void yindex (LexState *ls, expdesc *v) {\n  /* index -> '[' expr ']' */\n  luaX_next(ls);  /* skip the '[' */\n  expr(ls, v);\n  luaK_exp2val(ls->fs, v);\n  checknext(ls, ']');\n}\n\n\n/*\n** {======================================================================\n** Rules for Constructors\n** =======================================================================\n*/\n\n\nstruct ConsControl {\n  expdesc v;  /* last list item read */\n  expdesc *t;  /* table descriptor */\n  int nh;  /* total number of `record' elements */\n  int na;  /* total number of array elements */\n  int tostore;  /* number of array elements pending to be stored */\n};\n\n\nstatic void recfield (LexState *ls, struct ConsControl *cc) {\n  /* recfield -> (NAME | `['exp1`]') = exp1 */\n  FuncState *fs = ls->fs;\n  int reg = ls->fs->freereg;\n  expdesc key, val;\n  int rkkey;\n  if (ls->t.token == TK_NAME) {\n    luaY_checklimit(fs, cc->nh, MAX_INT, \"items in a constructor\");\n    checkname(ls, &key);\n  }\n  else  /* ls->t.token == '[' */\n    yindex(ls, &key);\n  cc->nh++;\n  checknext(ls, '=');\n  rkkey = luaK_exp2RK(fs, &key);\n  expr(ls, &val);\n  luaK_codeABC(fs, OP_SETTABLE, cc->t->u.s.info, rkkey, luaK_exp2RK(fs, &val));\n  fs->freereg = reg;  /* free registers */\n}\n\n\nstatic void closelistfield (FuncState *fs, struct ConsControl *cc) {\n  if (cc->v.k == VVOID) return;  /* there is no list item */\n  luaK_exp2nextreg(fs, &cc->v);\n  cc->v.k = VVOID;\n  if (cc->tostore == LFIELDS_PER_FLUSH) {\n    luaK_setlist(fs, cc->t->u.s.info, cc->na, cc->tostore);  /* flush */\n    cc->tostore = 0;  /* no more items pending */\n  }\n}\n\n\nstatic void lastlistfield (FuncState *fs, struct ConsControl *cc) {\n  if (cc->tostore == 0) return;\n  if (hasmultret(cc->v.k)) {\n    luaK_setmultret(fs, &cc->v);\n    luaK_setlist(fs, cc->t->u.s.info, cc->na, LUA_MULTRET);\n    cc->na--;  /* do not count last expression (unknown number of elements) */\n  }\n  else {\n    if (cc->v.k != VVOID)\n      luaK_exp2nextreg(fs, &cc->v);\n    luaK_setlist(fs, cc->t->u.s.info, cc->na, cc->tostore);\n  }\n}\n\n\nstatic void listfield (LexState *ls, struct ConsControl *cc) {\n  expr(ls, &cc->v);\n  luaY_checklimit(ls->fs, cc->na, MAX_INT, \"items in a constructor\");\n  cc->na++;\n  cc->tostore++;\n}\n\n\nstatic void constructor (LexState *ls, expdesc *t) {\n  /* constructor -> ?? */\n  FuncState *fs = ls->fs;\n  int line = ls->linenumber;\n  int pc = luaK_codeABC(fs, OP_NEWTABLE, 0, 0, 0);\n  struct ConsControl cc;\n  cc.na = cc.nh = cc.tostore = 0;\n  cc.t = t;\n  init_exp(t, VRELOCABLE, pc);\n  init_exp(&cc.v, VVOID, 0);  /* no value (yet) */\n  luaK_exp2nextreg(ls->fs, t);  /* fix it at stack top (for gc) */\n  checknext(ls, '{');\n  do {\n    lua_assert(cc.v.k == VVOID || cc.tostore > 0);\n    if (ls->t.token == '}') break;\n    closelistfield(fs, &cc);\n    switch(ls->t.token) {\n      case TK_NAME: {  /* may be listfields or recfields */\n        luaX_lookahead(ls);\n        if (ls->lookahead.token != '=')  /* expression? */\n          listfield(ls, &cc);\n        else\n          recfield(ls, &cc);\n        break;\n      }\n      case '[': {  /* constructor_item -> recfield */\n        recfield(ls, &cc);\n        break;\n      }\n      default: {  /* constructor_part -> listfield */\n        listfield(ls, &cc);\n        break;\n      }\n    }\n  } while (testnext(ls, ',') || testnext(ls, ';'));\n  check_match(ls, '}', '{', line);\n  lastlistfield(fs, &cc);\n  SETARG_B(fs->f->code[pc], luaO_int2fb(cc.na)); /* set initial array size */\n  SETARG_C(fs->f->code[pc], luaO_int2fb(cc.nh));  /* set initial table size */\n}\n\n/* }====================================================================== */\n\n\n\nstatic void parlist (LexState *ls) {\n  /* parlist -> [ param { `,' param } ] */\n  FuncState *fs = ls->fs;\n  Proto *f = fs->f;\n  int nparams = 0;\n  f->is_vararg = 0;\n  if (ls->t.token != ')') {  /* is `parlist' not empty? */\n    do {\n      switch (ls->t.token) {\n        case TK_NAME: {  /* param -> NAME */\n          new_localvar(ls, str_checkname(ls), nparams++);\n          break;\n        }\n        case TK_DOTS: {  /* param -> `...' */\n          luaX_next(ls);\n#if defined(LUA_COMPAT_VARARG)\n          /* use `arg' as default name */\n          new_localvarliteral(ls, \"arg\", nparams++);\n          f->is_vararg = VARARG_HASARG | VARARG_NEEDSARG;\n#endif\n          f->is_vararg |= VARARG_ISVARARG;\n          break;\n        }\n        default: luaX_syntaxerror(ls, \"<name> or \" LUA_QL(\"...\") \" expected\");\n      }\n    } while (!f->is_vararg && testnext(ls, ','));\n  }\n  adjustlocalvars(ls, nparams);\n  f->numparams = cast_byte(fs->nactvar - (f->is_vararg & VARARG_HASARG));\n  luaK_reserveregs(fs, fs->nactvar);  /* reserve register for parameters */\n}\n\n\nstatic void body (LexState *ls, expdesc *e, int needself, int line) {\n  /* body ->  `(' parlist `)' chunk END */\n  FuncState new_fs;\n  open_func(ls, &new_fs);\n  new_fs.f->linedefined = line;\n  checknext(ls, '(');\n  if (needself) {\n    new_localvarliteral(ls, \"self\", 0);\n    adjustlocalvars(ls, 1);\n  }\n  parlist(ls);\n  checknext(ls, ')');\n  chunk(ls);\n  new_fs.f->lastlinedefined = ls->linenumber;\n  check_match(ls, TK_END, TK_FUNCTION, line);\n  close_func(ls);\n  pushclosure(ls, &new_fs, e);\n}\n\n\nstatic int explist1 (LexState *ls, expdesc *v) {\n  /* explist1 -> expr { `,' expr } */\n  int n = 1;  /* at least one expression */\n  expr(ls, v);\n  while (testnext(ls, ',')) {\n    luaK_exp2nextreg(ls->fs, v);\n    expr(ls, v);\n    n++;\n  }\n  return n;\n}\n\n\nstatic void funcargs (LexState *ls, expdesc *f) {\n  FuncState *fs = ls->fs;\n  expdesc args;\n  int base, nparams;\n  int line = ls->linenumber;\n  switch (ls->t.token) {\n    case '(': {  /* funcargs -> `(' [ explist1 ] `)' */\n      if (line != ls->lastline)\n        luaX_syntaxerror(ls,\"ambiguous syntax (function call x new statement)\");\n      luaX_next(ls);\n      if (ls->t.token == ')')  /* arg list is empty? */\n        args.k = VVOID;\n      else {\n        explist1(ls, &args);\n        luaK_setmultret(fs, &args);\n      }\n      check_match(ls, ')', '(', line);\n      break;\n    }\n    case '{': {  /* funcargs -> constructor */\n      constructor(ls, &args);\n      break;\n    }\n    case TK_STRING: {  /* funcargs -> STRING */\n      codestring(ls, &args, ls->t.seminfo.ts);\n      luaX_next(ls);  /* must use `seminfo' before `next' */\n      break;\n    }\n    default: {\n      luaX_syntaxerror(ls, \"function arguments expected\");\n      return;\n    }\n  }\n  lua_assert(f->k == VNONRELOC);\n  base = f->u.s.info;  /* base register for call */\n  if (hasmultret(args.k))\n    nparams = LUA_MULTRET;  /* open call */\n  else {\n    if (args.k != VVOID)\n      luaK_exp2nextreg(fs, &args);  /* close last argument */\n    nparams = fs->freereg - (base+1);\n  }\n  init_exp(f, VCALL, luaK_codeABC(fs, OP_CALL, base, nparams+1, 2));\n  luaK_fixline(fs, line);\n  fs->freereg = base+1;  /* call remove function and arguments and leaves\n                            (unless changed) one result */\n}\n\n\n\n\n/*\n** {======================================================================\n** Expression parsing\n** =======================================================================\n*/\n\n\nstatic void prefixexp (LexState *ls, expdesc *v) {\n  /* prefixexp -> NAME | '(' expr ')' */\n  switch (ls->t.token) {\n    case '(': {\n      int line = ls->linenumber;\n      luaX_next(ls);\n      expr(ls, v);\n      check_match(ls, ')', '(', line);\n      luaK_dischargevars(ls->fs, v);\n      return;\n    }\n    case TK_NAME: {\n      singlevar(ls, v);\n      return;\n    }\n    default: {\n      luaX_syntaxerror(ls, \"unexpected symbol\");\n      return;\n    }\n  }\n}\n\n\nstatic void primaryexp (LexState *ls, expdesc *v) {\n  /* primaryexp ->\n        prefixexp { `.' NAME | `[' exp `]' | `:' NAME funcargs | funcargs } */\n  FuncState *fs = ls->fs;\n  prefixexp(ls, v);\n  for (;;) {\n    switch (ls->t.token) {\n      case '.': {  /* field */\n        field(ls, v);\n        break;\n      }\n      case '[': {  /* `[' exp1 `]' */\n        expdesc key;\n        luaK_exp2anyreg(fs, v);\n        yindex(ls, &key);\n        luaK_indexed(fs, v, &key);\n        break;\n      }\n      case ':': {  /* `:' NAME funcargs */\n        expdesc key;\n        luaX_next(ls);\n        checkname(ls, &key);\n        luaK_self(fs, v, &key);\n        funcargs(ls, v);\n        break;\n      }\n      case '(': case TK_STRING: case '{': {  /* funcargs */\n        luaK_exp2nextreg(fs, v);\n        funcargs(ls, v);\n        break;\n      }\n      default: return;\n    }\n  }\n}\n\n\nstatic void simpleexp (LexState *ls, expdesc *v) {\n  /* simpleexp -> NUMBER | STRING | NIL | true | false | ... |\n                  constructor | FUNCTION body | primaryexp */\n  switch (ls->t.token) {\n    case TK_NUMBER: {\n      init_exp(v, VKNUM, 0);\n      v->u.nval = ls->t.seminfo.r;\n      break;\n    }\n    case TK_STRING: {\n      codestring(ls, v, ls->t.seminfo.ts);\n      break;\n    }\n    case TK_NIL: {\n      init_exp(v, VNIL, 0);\n      break;\n    }\n    case TK_TRUE: {\n      init_exp(v, VTRUE, 0);\n      break;\n    }\n    case TK_FALSE: {\n      init_exp(v, VFALSE, 0);\n      break;\n    }\n    case TK_DOTS: {  /* vararg */\n      FuncState *fs = ls->fs;\n      check_condition(ls, fs->f->is_vararg,\n                      \"cannot use \" LUA_QL(\"...\") \" outside a vararg function\");\n      fs->f->is_vararg &= ~VARARG_NEEDSARG;  /* don't need 'arg' */\n      init_exp(v, VVARARG, luaK_codeABC(fs, OP_VARARG, 0, 1, 0));\n      break;\n    }\n    case '{': {  /* constructor */\n      constructor(ls, v);\n      return;\n    }\n    case TK_FUNCTION: {\n      luaX_next(ls);\n      body(ls, v, 0, ls->linenumber);\n      return;\n    }\n    default: {\n      primaryexp(ls, v);\n      return;\n    }\n  }\n  luaX_next(ls);\n}\n\n\nstatic UnOpr getunopr (int op) {\n  switch (op) {\n    case TK_NOT: return OPR_NOT;\n    case '-': return OPR_MINUS;\n    case '#': return OPR_LEN;\n    default: return OPR_NOUNOPR;\n  }\n}\n\n\nstatic BinOpr getbinopr (int op) {\n  switch (op) {\n    case '+': return OPR_ADD;\n    case '-': return OPR_SUB;\n    case '*': return OPR_MUL;\n    case '/': return OPR_DIV;\n    case '%': return OPR_MOD;\n    case '^': return OPR_POW;\n    case TK_CONCAT: return OPR_CONCAT;\n    case TK_NE: return OPR_NE;\n    case TK_EQ: return OPR_EQ;\n    case '<': return OPR_LT;\n    case TK_LE: return OPR_LE;\n    case '>': return OPR_GT;\n    case TK_GE: return OPR_GE;\n    case TK_AND: return OPR_AND;\n    case TK_OR: return OPR_OR;\n    default: return OPR_NOBINOPR;\n  }\n}\n\n\nstatic const struct {\n  lu_byte left;  /* left priority for each binary operator */\n  lu_byte right; /* right priority */\n} priority[] = {  /* ORDER OPR */\n   {6, 6}, {6, 6}, {7, 7}, {7, 7}, {7, 7},  /* `+' `-' `/' `%' */\n   {10, 9}, {5, 4},                 /* power and concat (right associative) */\n   {3, 3}, {3, 3},                  /* equality and inequality */\n   {3, 3}, {3, 3}, {3, 3}, {3, 3},  /* order */\n   {2, 2}, {1, 1}                   /* logical (and/or) */\n};\n\n#define UNARY_PRIORITY\t8  /* priority for unary operators */\n\n\n/*\n** subexpr -> (simpleexp | unop subexpr) { binop subexpr }\n** where `binop' is any binary operator with a priority higher than `limit'\n*/\nstatic BinOpr subexpr (LexState *ls, expdesc *v, unsigned int limit) {\n  BinOpr op;\n  UnOpr uop;\n  enterlevel(ls);\n  uop = getunopr(ls->t.token);\n  if (uop != OPR_NOUNOPR) {\n    luaX_next(ls);\n    subexpr(ls, v, UNARY_PRIORITY);\n    luaK_prefix(ls->fs, uop, v);\n  }\n  else simpleexp(ls, v);\n  /* expand while operators have priorities higher than `limit' */\n  op = getbinopr(ls->t.token);\n  while (op != OPR_NOBINOPR && priority[op].left > limit) {\n    expdesc v2;\n    BinOpr nextop;\n    luaX_next(ls);\n    luaK_infix(ls->fs, op, v);\n    /* read sub-expression with higher priority */\n    nextop = subexpr(ls, &v2, priority[op].right);\n    luaK_posfix(ls->fs, op, v, &v2);\n    op = nextop;\n  }\n  leavelevel(ls);\n  return op;  /* return first untreated operator */\n}\n\n\nstatic void expr (LexState *ls, expdesc *v) {\n  subexpr(ls, v, 0);\n}\n\n/* }==================================================================== */\n\n\n\n/*\n** {======================================================================\n** Rules for Statements\n** =======================================================================\n*/\n\n\nstatic int block_follow (int token) {\n  switch (token) {\n    case TK_ELSE: case TK_ELSEIF: case TK_END:\n    case TK_UNTIL: case TK_EOS:\n      return 1;\n    default: return 0;\n  }\n}\n\n\nstatic void block (LexState *ls) {\n  /* block -> chunk */\n  FuncState *fs = ls->fs;\n  BlockCnt bl;\n  enterblock(fs, &bl, 0);\n  chunk(ls);\n  lua_assert(bl.breaklist == NO_JUMP);\n  leaveblock(fs);\n}\n\n\n/*\n** structure to chain all variables in the left-hand side of an\n** assignment\n*/\nstruct LHS_assign {\n  struct LHS_assign *prev;\n  expdesc v;  /* variable (global, local, upvalue, or indexed) */\n};\n\n\n/*\n** check whether, in an assignment to a local variable, the local variable\n** is needed in a previous assignment (to a table). If so, save original\n** local value in a safe place and use this safe copy in the previous\n** assignment.\n*/\nstatic void check_conflict (LexState *ls, struct LHS_assign *lh, expdesc *v) {\n  FuncState *fs = ls->fs;\n  int extra = fs->freereg;  /* eventual position to save local variable */\n  int conflict = 0;\n  for (; lh; lh = lh->prev) {\n    if (lh->v.k == VINDEXED) {\n      if (lh->v.u.s.info == v->u.s.info) {  /* conflict? */\n        conflict = 1;\n        lh->v.u.s.info = extra;  /* previous assignment will use safe copy */\n      }\n      if (lh->v.u.s.aux == v->u.s.info) {  /* conflict? */\n        conflict = 1;\n        lh->v.u.s.aux = extra;  /* previous assignment will use safe copy */\n      }\n    }\n  }\n  if (conflict) {\n    luaK_codeABC(fs, OP_MOVE, fs->freereg, v->u.s.info, 0);  /* make copy */\n    luaK_reserveregs(fs, 1);\n  }\n}\n\n\nstatic void assignment (LexState *ls, struct LHS_assign *lh, int nvars) {\n  expdesc e;\n  check_condition(ls, VLOCAL <= lh->v.k && lh->v.k <= VINDEXED,\n                      \"syntax error\");\n  if (testnext(ls, ',')) {  /* assignment -> `,' primaryexp assignment */\n    struct LHS_assign nv;\n    nv.prev = lh;\n    primaryexp(ls, &nv.v);\n    if (nv.v.k == VLOCAL)\n      check_conflict(ls, lh, &nv.v);\n    luaY_checklimit(ls->fs, nvars, LUAI_MAXCCALLS - ls->L->nCcalls,\n                    \"variables in assignment\");\n    assignment(ls, &nv, nvars+1);\n  }\n  else {  /* assignment -> `=' explist1 */\n    int nexps;\n    checknext(ls, '=');\n    nexps = explist1(ls, &e);\n    if (nexps != nvars) {\n      adjust_assign(ls, nvars, nexps, &e);\n      if (nexps > nvars)\n        ls->fs->freereg -= nexps - nvars;  /* remove extra values */\n    }\n    else {\n      luaK_setoneret(ls->fs, &e);  /* close last expression */\n      luaK_storevar(ls->fs, &lh->v, &e);\n      return;  /* avoid default */\n    }\n  }\n  init_exp(&e, VNONRELOC, ls->fs->freereg-1);  /* default assignment */\n  luaK_storevar(ls->fs, &lh->v, &e);\n}\n\n\nstatic int cond (LexState *ls) {\n  /* cond -> exp */\n  expdesc v;\n  expr(ls, &v);  /* read condition */\n  if (v.k == VNIL) v.k = VFALSE;  /* `falses' are all equal here */\n  luaK_goiftrue(ls->fs, &v);\n  return v.f;\n}\n\n\nstatic void breakstat (LexState *ls) {\n  FuncState *fs = ls->fs;\n  BlockCnt *bl = fs->bl;\n  int upval = 0;\n  while (bl && !bl->isbreakable) {\n    upval |= bl->upval;\n    bl = bl->previous;\n  }\n  if (!bl)\n    luaX_syntaxerror(ls, \"no loop to break\");\n  if (upval)\n    luaK_codeABC(fs, OP_CLOSE, bl->nactvar, 0, 0);\n  luaK_concat(fs, &bl->breaklist, luaK_jump(fs));\n}\n\n\nstatic void whilestat (LexState *ls, int line) {\n  /* whilestat -> WHILE cond DO block END */\n  FuncState *fs = ls->fs;\n  int whileinit;\n  int condexit;\n  BlockCnt bl;\n  luaX_next(ls);  /* skip WHILE */\n  whileinit = luaK_getlabel(fs);\n  condexit = cond(ls);\n  enterblock(fs, &bl, 1);\n  checknext(ls, TK_DO);\n  block(ls);\n  luaK_patchlist(fs, luaK_jump(fs), whileinit);\n  check_match(ls, TK_END, TK_WHILE, line);\n  leaveblock(fs);\n  luaK_patchtohere(fs, condexit);  /* false conditions finish the loop */\n}\n\n\nstatic void repeatstat (LexState *ls, int line) {\n  /* repeatstat -> REPEAT block UNTIL cond */\n  int condexit;\n  FuncState *fs = ls->fs;\n  int repeat_init = luaK_getlabel(fs);\n  BlockCnt bl1, bl2;\n  enterblock(fs, &bl1, 1);  /* loop block */\n  enterblock(fs, &bl2, 0);  /* scope block */\n  luaX_next(ls);  /* skip REPEAT */\n  chunk(ls);\n  check_match(ls, TK_UNTIL, TK_REPEAT, line);\n  condexit = cond(ls);  /* read condition (inside scope block) */\n  if (!bl2.upval) {  /* no upvalues? */\n    leaveblock(fs);  /* finish scope */\n    luaK_patchlist(ls->fs, condexit, repeat_init);  /* close the loop */\n  }\n  else {  /* complete semantics when there are upvalues */\n    breakstat(ls);  /* if condition then break */\n    luaK_patchtohere(ls->fs, condexit);  /* else... */\n    leaveblock(fs);  /* finish scope... */\n    luaK_patchlist(ls->fs, luaK_jump(fs), repeat_init);  /* and repeat */\n  }\n  leaveblock(fs);  /* finish loop */\n}\n\n\nstatic int exp1 (LexState *ls) {\n  expdesc e;\n  int k;\n  expr(ls, &e);\n  k = e.k;\n  luaK_exp2nextreg(ls->fs, &e);\n  return k;\n}\n\n\nstatic void forbody (LexState *ls, int base, int line, int nvars, int isnum) {\n  /* forbody -> DO block */\n  BlockCnt bl;\n  FuncState *fs = ls->fs;\n  int prep, endfor;\n  adjustlocalvars(ls, 3);  /* control variables */\n  checknext(ls, TK_DO);\n  prep = isnum ? luaK_codeAsBx(fs, OP_FORPREP, base, NO_JUMP) : luaK_jump(fs);\n  enterblock(fs, &bl, 0);  /* scope for declared variables */\n  adjustlocalvars(ls, nvars);\n  luaK_reserveregs(fs, nvars);\n  block(ls);\n  leaveblock(fs);  /* end of scope for declared variables */\n  luaK_patchtohere(fs, prep);\n  endfor = (isnum) ? luaK_codeAsBx(fs, OP_FORLOOP, base, NO_JUMP) :\n                     luaK_codeABC(fs, OP_TFORLOOP, base, 0, nvars);\n  luaK_fixline(fs, line);  /* pretend that `OP_FOR' starts the loop */\n  luaK_patchlist(fs, (isnum ? endfor : luaK_jump(fs)), prep + 1);\n}\n\n\nstatic void fornum (LexState *ls, TString *varname, int line) {\n  /* fornum -> NAME = exp1,exp1[,exp1] forbody */\n  FuncState *fs = ls->fs;\n  int base = fs->freereg;\n  new_localvarliteral(ls, \"(for index)\", 0);\n  new_localvarliteral(ls, \"(for limit)\", 1);\n  new_localvarliteral(ls, \"(for step)\", 2);\n  new_localvar(ls, varname, 3);\n  checknext(ls, '=');\n  exp1(ls);  /* initial value */\n  checknext(ls, ',');\n  exp1(ls);  /* limit */\n  if (testnext(ls, ','))\n    exp1(ls);  /* optional step */\n  else {  /* default step = 1 */\n    luaK_codeABx(fs, OP_LOADK, fs->freereg, luaK_numberK(fs, 1));\n    luaK_reserveregs(fs, 1);\n  }\n  forbody(ls, base, line, 1, 1);\n}\n\n\nstatic void forlist (LexState *ls, TString *indexname) {\n  /* forlist -> NAME {,NAME} IN explist1 forbody */\n  FuncState *fs = ls->fs;\n  expdesc e;\n  int nvars = 0;\n  int line;\n  int base = fs->freereg;\n  /* create control variables */\n  new_localvarliteral(ls, \"(for generator)\", nvars++);\n  new_localvarliteral(ls, \"(for state)\", nvars++);\n  new_localvarliteral(ls, \"(for control)\", nvars++);\n  /* create declared variables */\n  new_localvar(ls, indexname, nvars++);\n  while (testnext(ls, ','))\n    new_localvar(ls, str_checkname(ls), nvars++);\n  checknext(ls, TK_IN);\n  line = ls->linenumber;\n  adjust_assign(ls, 3, explist1(ls, &e), &e);\n  luaK_checkstack(fs, 3);  /* extra space to call generator */\n  forbody(ls, base, line, nvars - 3, 0);\n}\n\n\nstatic void forstat (LexState *ls, int line) {\n  /* forstat -> FOR (fornum | forlist) END */\n  FuncState *fs = ls->fs;\n  TString *varname;\n  BlockCnt bl;\n  enterblock(fs, &bl, 1);  /* scope for loop and control variables */\n  luaX_next(ls);  /* skip `for' */\n  varname = str_checkname(ls);  /* first variable name */\n  switch (ls->t.token) {\n    case '=': fornum(ls, varname, line); break;\n    case ',': case TK_IN: forlist(ls, varname); break;\n    default: luaX_syntaxerror(ls, LUA_QL(\"=\") \" or \" LUA_QL(\"in\") \" expected\");\n  }\n  check_match(ls, TK_END, TK_FOR, line);\n  leaveblock(fs);  /* loop scope (`break' jumps to this point) */\n}\n\n\nstatic int test_then_block (LexState *ls) {\n  /* test_then_block -> [IF | ELSEIF] cond THEN block */\n  int condexit;\n  luaX_next(ls);  /* skip IF or ELSEIF */\n  condexit = cond(ls);\n  checknext(ls, TK_THEN);\n  block(ls);  /* `then' part */\n  return condexit;\n}\n\n\nstatic void ifstat (LexState *ls, int line) {\n  /* ifstat -> IF cond THEN block {ELSEIF cond THEN block} [ELSE block] END */\n  FuncState *fs = ls->fs;\n  int flist;\n  int escapelist = NO_JUMP;\n  flist = test_then_block(ls);  /* IF cond THEN block */\n  while (ls->t.token == TK_ELSEIF) {\n    luaK_concat(fs, &escapelist, luaK_jump(fs));\n    luaK_patchtohere(fs, flist);\n    flist = test_then_block(ls);  /* ELSEIF cond THEN block */\n  }\n  if (ls->t.token == TK_ELSE) {\n    luaK_concat(fs, &escapelist, luaK_jump(fs));\n    luaK_patchtohere(fs, flist);\n    luaX_next(ls);  /* skip ELSE (after patch, for correct line info) */\n    block(ls);  /* `else' part */\n  }\n  else\n    luaK_concat(fs, &escapelist, flist);\n  luaK_patchtohere(fs, escapelist);\n  check_match(ls, TK_END, TK_IF, line);\n}\n\n\nstatic void localfunc (LexState *ls) {\n  expdesc v, b;\n  FuncState *fs = ls->fs;\n  new_localvar(ls, str_checkname(ls), 0);\n  init_exp(&v, VLOCAL, fs->freereg);\n  luaK_reserveregs(fs, 1);\n  adjustlocalvars(ls, 1);\n  body(ls, &b, 0, ls->linenumber);\n  luaK_storevar(fs, &v, &b);\n  /* debug information will only see the variable after this point! */\n  getlocvar(fs, fs->nactvar - 1).startpc = fs->pc;\n}\n\n\nstatic void localstat (LexState *ls) {\n  /* stat -> LOCAL NAME {`,' NAME} [`=' explist1] */\n  int nvars = 0;\n  int nexps;\n  expdesc e;\n  do {\n    new_localvar(ls, str_checkname(ls), nvars++);\n  } while (testnext(ls, ','));\n  if (testnext(ls, '='))\n    nexps = explist1(ls, &e);\n  else {\n    e.k = VVOID;\n    nexps = 0;\n  }\n  adjust_assign(ls, nvars, nexps, &e);\n  adjustlocalvars(ls, nvars);\n}\n\n\nstatic int funcname (LexState *ls, expdesc *v) {\n  /* funcname -> NAME {field} [`:' NAME] */\n  int needself = 0;\n  singlevar(ls, v);\n  while (ls->t.token == '.')\n    field(ls, v);\n  if (ls->t.token == ':') {\n    needself = 1;\n    field(ls, v);\n  }\n  return needself;\n}\n\n\nstatic void funcstat (LexState *ls, int line) {\n  /* funcstat -> FUNCTION funcname body */\n  int needself;\n  expdesc v, b;\n  luaX_next(ls);  /* skip FUNCTION */\n  needself = funcname(ls, &v);\n  body(ls, &b, needself, line);\n  luaK_storevar(ls->fs, &v, &b);\n  luaK_fixline(ls->fs, line);  /* definition `happens' in the first line */\n}\n\n\nstatic void exprstat (LexState *ls) {\n  /* stat -> func | assignment */\n  FuncState *fs = ls->fs;\n  struct LHS_assign v;\n  primaryexp(ls, &v.v);\n  if (v.v.k == VCALL)  /* stat -> func */\n    SETARG_C(getcode(fs, &v.v), 1);  /* call statement uses no results */\n  else {  /* stat -> assignment */\n    v.prev = NULL;\n    assignment(ls, &v, 1);\n  }\n}\n\n\nstatic void retstat (LexState *ls) {\n  /* stat -> RETURN explist */\n  FuncState *fs = ls->fs;\n  expdesc e;\n  int first, nret;  /* registers with returned values */\n  luaX_next(ls);  /* skip RETURN */\n  if (block_follow(ls->t.token) || ls->t.token == ';')\n    first = nret = 0;  /* return no values */\n  else {\n    nret = explist1(ls, &e);  /* optional return values */\n    if (hasmultret(e.k)) {\n      luaK_setmultret(fs, &e);\n      if (e.k == VCALL && nret == 1) {  /* tail call? */\n        SET_OPCODE(getcode(fs,&e), OP_TAILCALL);\n        lua_assert(GETARG_A(getcode(fs,&e)) == fs->nactvar);\n      }\n      first = fs->nactvar;\n      nret = LUA_MULTRET;  /* return all values */\n    }\n    else {\n      if (nret == 1)  /* only one single value? */\n        first = luaK_exp2anyreg(fs, &e);\n      else {\n        luaK_exp2nextreg(fs, &e);  /* values must go to the `stack' */\n        first = fs->nactvar;  /* return all `active' values */\n        lua_assert(nret == fs->freereg - first);\n      }\n    }\n  }\n  luaK_ret(fs, first, nret);\n}\n\n\nstatic int statement (LexState *ls) {\n  int line = ls->linenumber;  /* may be needed for error messages */\n  switch (ls->t.token) {\n    case TK_IF: {  /* stat -> ifstat */\n      ifstat(ls, line);\n      return 0;\n    }\n    case TK_WHILE: {  /* stat -> whilestat */\n      whilestat(ls, line);\n      return 0;\n    }\n    case TK_DO: {  /* stat -> DO block END */\n      luaX_next(ls);  /* skip DO */\n      block(ls);\n      check_match(ls, TK_END, TK_DO, line);\n      return 0;\n    }\n    case TK_FOR: {  /* stat -> forstat */\n      forstat(ls, line);\n      return 0;\n    }\n    case TK_REPEAT: {  /* stat -> repeatstat */\n      repeatstat(ls, line);\n      return 0;\n    }\n    case TK_FUNCTION: {\n      funcstat(ls, line);  /* stat -> funcstat */\n      return 0;\n    }\n    case TK_LOCAL: {  /* stat -> localstat */\n      luaX_next(ls);  /* skip LOCAL */\n      if (testnext(ls, TK_FUNCTION))  /* local function? */\n        localfunc(ls);\n      else\n        localstat(ls);\n      return 0;\n    }\n    case TK_RETURN: {  /* stat -> retstat */\n      retstat(ls);\n      return 1;  /* must be last statement */\n    }\n    case TK_BREAK: {  /* stat -> breakstat */\n      luaX_next(ls);  /* skip BREAK */\n      breakstat(ls);\n      return 1;  /* must be last statement */\n    }\n    default: {\n      exprstat(ls);\n      return 0;  /* to avoid warnings */\n    }\n  }\n}\n\n\nstatic void chunk (LexState *ls) {\n  /* chunk -> { stat [`;'] } */\n  int islast = 0;\n  enterlevel(ls);\n  while (!islast && !block_follow(ls->t.token)) {\n    islast = statement(ls);\n    testnext(ls, ';');\n    lua_assert(ls->fs->f->maxstacksize >= ls->fs->freereg &&\n               ls->fs->freereg >= ls->fs->nactvar);\n    ls->fs->freereg = ls->fs->nactvar;  /* free registers */\n  }\n  leavelevel(ls);\n}\n\n/* }====================================================================== */\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.8/deps/lua/src/lparser.h",
    "content": "/*\n** $Id: lparser.h,v 1.57.1.1 2007/12/27 13:02:25 roberto Exp $\n** Lua Parser\n** See Copyright Notice in lua.h\n*/\n\n#ifndef lparser_h\n#define lparser_h\n\n#include \"llimits.h\"\n#include \"lobject.h\"\n#include \"lzio.h\"\n\n\n/*\n** Expression descriptor\n*/\n\ntypedef enum {\n  VVOID,\t/* no value */\n  VNIL,\n  VTRUE,\n  VFALSE,\n  VK,\t\t/* info = index of constant in `k' */\n  VKNUM,\t/* nval = numerical value */\n  VLOCAL,\t/* info = local register */\n  VUPVAL,       /* info = index of upvalue in `upvalues' */\n  VGLOBAL,\t/* info = index of table; aux = index of global name in `k' */\n  VINDEXED,\t/* info = table register; aux = index register (or `k') */\n  VJMP,\t\t/* info = instruction pc */\n  VRELOCABLE,\t/* info = instruction pc */\n  VNONRELOC,\t/* info = result register */\n  VCALL,\t/* info = instruction pc */\n  VVARARG\t/* info = instruction pc */\n} expkind;\n\ntypedef struct expdesc {\n  expkind k;\n  union {\n    struct { int info, aux; } s;\n    lua_Number nval;\n  } u;\n  int t;  /* patch list of `exit when true' */\n  int f;  /* patch list of `exit when false' */\n} expdesc;\n\n\ntypedef struct upvaldesc {\n  lu_byte k;\n  lu_byte info;\n} upvaldesc;\n\n\nstruct BlockCnt;  /* defined in lparser.c */\n\n\n/* state needed to generate code for a given function */\ntypedef struct FuncState {\n  Proto *f;  /* current function header */\n  Table *h;  /* table to find (and reuse) elements in `k' */\n  struct FuncState *prev;  /* enclosing function */\n  struct LexState *ls;  /* lexical state */\n  struct lua_State *L;  /* copy of the Lua state */\n  struct BlockCnt *bl;  /* chain of current blocks */\n  int pc;  /* next position to code (equivalent to `ncode') */\n  int lasttarget;   /* `pc' of last `jump target' */\n  int jpc;  /* list of pending jumps to `pc' */\n  int freereg;  /* first free register */\n  int nk;  /* number of elements in `k' */\n  int np;  /* number of elements in `p' */\n  short nlocvars;  /* number of elements in `locvars' */\n  lu_byte nactvar;  /* number of active local variables */\n  upvaldesc upvalues[LUAI_MAXUPVALUES];  /* upvalues */\n  unsigned short actvar[LUAI_MAXVARS];  /* declared-variable stack */\n} FuncState;\n\n\nLUAI_FUNC Proto *luaY_parser (lua_State *L, ZIO *z, Mbuffer *buff,\n                                            const char *name);\n\n\n#endif\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.8/deps/lua/src/lstate.c",
    "content": "/*\n** $Id: lstate.c,v 2.36.1.2 2008/01/03 15:20:39 roberto Exp $\n** Global State\n** See Copyright Notice in lua.h\n*/\n\n\n#include <stddef.h>\n\n#define lstate_c\n#define LUA_CORE\n\n#include \"lua.h\"\n\n#include \"ldebug.h\"\n#include \"ldo.h\"\n#include \"lfunc.h\"\n#include \"lgc.h\"\n#include \"llex.h\"\n#include \"lmem.h\"\n#include \"lstate.h\"\n#include \"lstring.h\"\n#include \"ltable.h\"\n#include \"ltm.h\"\n\n\n#define state_size(x)\t(sizeof(x) + LUAI_EXTRASPACE)\n#define fromstate(l)\t(cast(lu_byte *, (l)) - LUAI_EXTRASPACE)\n#define tostate(l)   (cast(lua_State *, cast(lu_byte *, l) + LUAI_EXTRASPACE))\n\n\n/*\n** Main thread combines a thread state and the global state\n*/\ntypedef struct LG {\n  lua_State l;\n  global_State g;\n} LG;\n  \n\n\nstatic void stack_init (lua_State *L1, lua_State *L) {\n  /* initialize CallInfo array */\n  L1->base_ci = luaM_newvector(L, BASIC_CI_SIZE, CallInfo);\n  L1->ci = L1->base_ci;\n  L1->size_ci = BASIC_CI_SIZE;\n  L1->end_ci = L1->base_ci + L1->size_ci - 1;\n  /* initialize stack array */\n  L1->stack = luaM_newvector(L, BASIC_STACK_SIZE + EXTRA_STACK, TValue);\n  L1->stacksize = BASIC_STACK_SIZE + EXTRA_STACK;\n  L1->top = L1->stack;\n  L1->stack_last = L1->stack+(L1->stacksize - EXTRA_STACK)-1;\n  /* initialize first ci */\n  L1->ci->func = L1->top;\n  setnilvalue(L1->top++);  /* `function' entry for this `ci' */\n  L1->base = L1->ci->base = L1->top;\n  L1->ci->top = L1->top + LUA_MINSTACK;\n}\n\n\nstatic void freestack (lua_State *L, lua_State *L1) {\n  luaM_freearray(L, L1->base_ci, L1->size_ci, CallInfo);\n  luaM_freearray(L, L1->stack, L1->stacksize, TValue);\n}\n\n\n/*\n** open parts that may cause memory-allocation errors\n*/\nstatic void f_luaopen (lua_State *L, void *ud) {\n  global_State *g = G(L);\n  UNUSED(ud);\n  stack_init(L, L);  /* init stack */\n  sethvalue(L, gt(L), luaH_new(L, 0, 2));  /* table of globals */\n  sethvalue(L, registry(L), luaH_new(L, 0, 2));  /* registry */\n  luaS_resize(L, MINSTRTABSIZE);  /* initial size of string table */\n  luaT_init(L);\n  luaX_init(L);\n  luaS_fix(luaS_newliteral(L, MEMERRMSG));\n  g->GCthreshold = 4*g->totalbytes;\n}\n\n\nstatic void preinit_state (lua_State *L, global_State *g) {\n  G(L) = g;\n  L->stack = NULL;\n  L->stacksize = 0;\n  L->errorJmp = NULL;\n  L->hook = NULL;\n  L->hookmask = 0;\n  L->basehookcount = 0;\n  L->allowhook = 1;\n  resethookcount(L);\n  L->openupval = NULL;\n  L->size_ci = 0;\n  L->nCcalls = L->baseCcalls = 0;\n  L->status = 0;\n  L->base_ci = L->ci = NULL;\n  L->savedpc = NULL;\n  L->errfunc = 0;\n  setnilvalue(gt(L));\n}\n\n\nstatic void close_state (lua_State *L) {\n  global_State *g = G(L);\n  luaF_close(L, L->stack);  /* close all upvalues for this thread */\n  luaC_freeall(L);  /* collect all objects */\n  lua_assert(g->rootgc == obj2gco(L));\n  lua_assert(g->strt.nuse == 0);\n  luaM_freearray(L, G(L)->strt.hash, G(L)->strt.size, TString *);\n  luaZ_freebuffer(L, &g->buff);\n  freestack(L, L);\n  lua_assert(g->totalbytes == sizeof(LG));\n  (*g->frealloc)(g->ud, fromstate(L), state_size(LG), 0);\n}\n\n\nlua_State *luaE_newthread (lua_State *L) {\n  lua_State *L1 = tostate(luaM_malloc(L, state_size(lua_State)));\n  luaC_link(L, obj2gco(L1), LUA_TTHREAD);\n  preinit_state(L1, G(L));\n  stack_init(L1, L);  /* init stack */\n  setobj2n(L, gt(L1), gt(L));  /* share table of globals */\n  L1->hookmask = L->hookmask;\n  L1->basehookcount = L->basehookcount;\n  L1->hook = L->hook;\n  resethookcount(L1);\n  lua_assert(iswhite(obj2gco(L1)));\n  return L1;\n}\n\n\nvoid luaE_freethread (lua_State *L, lua_State *L1) {\n  luaF_close(L1, L1->stack);  /* close all upvalues for this thread */\n  lua_assert(L1->openupval == NULL);\n  luai_userstatefree(L1);\n  freestack(L, L1);\n  luaM_freemem(L, fromstate(L1), state_size(lua_State));\n}\n\n\nLUA_API lua_State *lua_newstate (lua_Alloc f, void *ud) {\n  int i;\n  lua_State *L;\n  global_State *g;\n  void *l = (*f)(ud, NULL, 0, state_size(LG));\n  if (l == NULL) return NULL;\n  L = tostate(l);\n  g = &((LG *)L)->g;\n  L->next = NULL;\n  L->tt = LUA_TTHREAD;\n  g->currentwhite = bit2mask(WHITE0BIT, FIXEDBIT);\n  L->marked = luaC_white(g);\n  set2bits(L->marked, FIXEDBIT, SFIXEDBIT);\n  preinit_state(L, g);\n  g->frealloc = f;\n  g->ud = ud;\n  g->mainthread = L;\n  g->uvhead.u.l.prev = &g->uvhead;\n  g->uvhead.u.l.next = &g->uvhead;\n  g->GCthreshold = 0;  /* mark it as unfinished state */\n  g->strt.size = 0;\n  g->strt.nuse = 0;\n  g->strt.hash = NULL;\n  setnilvalue(registry(L));\n  luaZ_initbuffer(L, &g->buff);\n  g->panic = NULL;\n  g->gcstate = GCSpause;\n  g->rootgc = obj2gco(L);\n  g->sweepstrgc = 0;\n  g->sweepgc = &g->rootgc;\n  g->gray = NULL;\n  g->grayagain = NULL;\n  g->weak = NULL;\n  g->tmudata = NULL;\n  g->totalbytes = sizeof(LG);\n  g->gcpause = LUAI_GCPAUSE;\n  g->gcstepmul = LUAI_GCMUL;\n  g->gcdept = 0;\n  for (i=0; i<NUM_TAGS; i++) g->mt[i] = NULL;\n  if (luaD_rawrunprotected(L, f_luaopen, NULL) != 0) {\n    /* memory allocation error: free partial state */\n    close_state(L);\n    L = NULL;\n  }\n  else\n    luai_userstateopen(L);\n  return L;\n}\n\n\nstatic void callallgcTM (lua_State *L, void *ud) {\n  UNUSED(ud);\n  luaC_callGCTM(L);  /* call GC metamethods for all udata */\n}\n\n\nLUA_API void lua_close (lua_State *L) {\n  L = G(L)->mainthread;  /* only the main thread can be closed */\n  lua_lock(L);\n  luaF_close(L, L->stack);  /* close all upvalues for this thread */\n  luaC_separateudata(L, 1);  /* separate udata that have GC metamethods */\n  L->errfunc = 0;  /* no error function during GC metamethods */\n  do {  /* repeat until no more errors */\n    L->ci = L->base_ci;\n    L->base = L->top = L->ci->base;\n    L->nCcalls = L->baseCcalls = 0;\n  } while (luaD_rawrunprotected(L, callallgcTM, NULL) != 0);\n  lua_assert(G(L)->tmudata == NULL);\n  luai_userstateclose(L);\n  close_state(L);\n}\n\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.8/deps/lua/src/lstate.h",
    "content": "/*\n** $Id: lstate.h,v 2.24.1.2 2008/01/03 15:20:39 roberto Exp $\n** Global State\n** See Copyright Notice in lua.h\n*/\n\n#ifndef lstate_h\n#define lstate_h\n\n#include \"lua.h\"\n\n#include \"lobject.h\"\n#include \"ltm.h\"\n#include \"lzio.h\"\n\n\n\nstruct lua_longjmp;  /* defined in ldo.c */\n\n\n/* table of globals */\n#define gt(L)\t(&L->l_gt)\n\n/* registry */\n#define registry(L)\t(&G(L)->l_registry)\n\n\n/* extra stack space to handle TM calls and some other extras */\n#define EXTRA_STACK   5\n\n\n#define BASIC_CI_SIZE           8\n\n#define BASIC_STACK_SIZE        (2*LUA_MINSTACK)\n\n\n\ntypedef struct stringtable {\n  GCObject **hash;\n  lu_int32 nuse;  /* number of elements */\n  int size;\n} stringtable;\n\n\n/*\n** informations about a call\n*/\ntypedef struct CallInfo {\n  StkId base;  /* base for this function */\n  StkId func;  /* function index in the stack */\n  StkId\ttop;  /* top for this function */\n  const Instruction *savedpc;\n  int nresults;  /* expected number of results from this function */\n  int tailcalls;  /* number of tail calls lost under this entry */\n} CallInfo;\n\n\n\n#define curr_func(L)\t(clvalue(L->ci->func))\n#define ci_func(ci)\t(clvalue((ci)->func))\n#define f_isLua(ci)\t(!ci_func(ci)->c.isC)\n#define isLua(ci)\t(ttisfunction((ci)->func) && f_isLua(ci))\n\n\n/*\n** `global state', shared by all threads of this state\n*/\ntypedef struct global_State {\n  stringtable strt;  /* hash table for strings */\n  lua_Alloc frealloc;  /* function to reallocate memory */\n  void *ud;         /* auxiliary data to `frealloc' */\n  lu_byte currentwhite;\n  lu_byte gcstate;  /* state of garbage collector */\n  int sweepstrgc;  /* position of sweep in `strt' */\n  GCObject *rootgc;  /* list of all collectable objects */\n  GCObject **sweepgc;  /* position of sweep in `rootgc' */\n  GCObject *gray;  /* list of gray objects */\n  GCObject *grayagain;  /* list of objects to be traversed atomically */\n  GCObject *weak;  /* list of weak tables (to be cleared) */\n  GCObject *tmudata;  /* last element of list of userdata to be GC */\n  Mbuffer buff;  /* temporary buffer for string concatentation */\n  lu_mem GCthreshold;\n  lu_mem totalbytes;  /* number of bytes currently allocated */\n  lu_mem estimate;  /* an estimate of number of bytes actually in use */\n  lu_mem gcdept;  /* how much GC is `behind schedule' */\n  int gcpause;  /* size of pause between successive GCs */\n  int gcstepmul;  /* GC `granularity' */\n  lua_CFunction panic;  /* to be called in unprotected errors */\n  TValue l_registry;\n  struct lua_State *mainthread;\n  UpVal uvhead;  /* head of double-linked list of all open upvalues */\n  struct Table *mt[NUM_TAGS];  /* metatables for basic types */\n  TString *tmname[TM_N];  /* array with tag-method names */\n} global_State;\n\n\n/*\n** `per thread' state\n*/\nstruct lua_State {\n  CommonHeader;\n  lu_byte status;\n  StkId top;  /* first free slot in the stack */\n  StkId base;  /* base of current function */\n  global_State *l_G;\n  CallInfo *ci;  /* call info for current function */\n  const Instruction *savedpc;  /* `savedpc' of current function */\n  StkId stack_last;  /* last free slot in the stack */\n  StkId stack;  /* stack base */\n  CallInfo *end_ci;  /* points after end of ci array*/\n  CallInfo *base_ci;  /* array of CallInfo's */\n  int stacksize;\n  int size_ci;  /* size of array `base_ci' */\n  unsigned short nCcalls;  /* number of nested C calls */\n  unsigned short baseCcalls;  /* nested C calls when resuming coroutine */\n  lu_byte hookmask;\n  lu_byte allowhook;\n  int basehookcount;\n  int hookcount;\n  lua_Hook hook;\n  TValue l_gt;  /* table of globals */\n  TValue env;  /* temporary place for environments */\n  GCObject *openupval;  /* list of open upvalues in this stack */\n  GCObject *gclist;\n  struct lua_longjmp *errorJmp;  /* current error recover point */\n  ptrdiff_t errfunc;  /* current error handling function (stack index) */\n};\n\n\n#define G(L)\t(L->l_G)\n\n\n/*\n** Union of all collectable objects\n*/\nunion GCObject {\n  GCheader gch;\n  union TString ts;\n  union Udata u;\n  union Closure cl;\n  struct Table h;\n  struct Proto p;\n  struct UpVal uv;\n  struct lua_State th;  /* thread */\n};\n\n\n/* macros to convert a GCObject into a specific value */\n#define rawgco2ts(o)\tcheck_exp((o)->gch.tt == LUA_TSTRING, &((o)->ts))\n#define gco2ts(o)\t(&rawgco2ts(o)->tsv)\n#define rawgco2u(o)\tcheck_exp((o)->gch.tt == LUA_TUSERDATA, &((o)->u))\n#define gco2u(o)\t(&rawgco2u(o)->uv)\n#define gco2cl(o)\tcheck_exp((o)->gch.tt == LUA_TFUNCTION, &((o)->cl))\n#define gco2h(o)\tcheck_exp((o)->gch.tt == LUA_TTABLE, &((o)->h))\n#define gco2p(o)\tcheck_exp((o)->gch.tt == LUA_TPROTO, &((o)->p))\n#define gco2uv(o)\tcheck_exp((o)->gch.tt == LUA_TUPVAL, &((o)->uv))\n#define ngcotouv(o) \\\n\tcheck_exp((o) == NULL || (o)->gch.tt == LUA_TUPVAL, &((o)->uv))\n#define gco2th(o)\tcheck_exp((o)->gch.tt == LUA_TTHREAD, &((o)->th))\n\n/* macro to convert any Lua object into a GCObject */\n#define obj2gco(v)\t(cast(GCObject *, (v)))\n\n\nLUAI_FUNC lua_State *luaE_newthread (lua_State *L);\nLUAI_FUNC void luaE_freethread (lua_State *L, lua_State *L1);\n\n#endif\n\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.8/deps/lua/src/lstring.c",
    "content": "/*\n** $Id: lstring.c,v 2.8.1.1 2007/12/27 13:02:25 roberto Exp $\n** String table (keeps all strings handled by Lua)\n** See Copyright Notice in lua.h\n*/\n\n\n#include <string.h>\n\n#define lstring_c\n#define LUA_CORE\n\n#include \"lua.h\"\n\n#include \"lmem.h\"\n#include \"lobject.h\"\n#include \"lstate.h\"\n#include \"lstring.h\"\n\n\n\nvoid luaS_resize (lua_State *L, int newsize) {\n  GCObject **newhash;\n  stringtable *tb;\n  int i;\n  if (G(L)->gcstate == GCSsweepstring)\n    return;  /* cannot resize during GC traverse */\n  newhash = luaM_newvector(L, newsize, GCObject *);\n  tb = &G(L)->strt;\n  for (i=0; i<newsize; i++) newhash[i] = NULL;\n  /* rehash */\n  for (i=0; i<tb->size; i++) {\n    GCObject *p = tb->hash[i];\n    while (p) {  /* for each node in the list */\n      GCObject *next = p->gch.next;  /* save next */\n      unsigned int h = gco2ts(p)->hash;\n      int h1 = lmod(h, newsize);  /* new position */\n      lua_assert(cast_int(h%newsize) == lmod(h, newsize));\n      p->gch.next = newhash[h1];  /* chain it */\n      newhash[h1] = p;\n      p = next;\n    }\n  }\n  luaM_freearray(L, tb->hash, tb->size, TString *);\n  tb->size = newsize;\n  tb->hash = newhash;\n}\n\n\nstatic TString *newlstr (lua_State *L, const char *str, size_t l,\n                                       unsigned int h) {\n  TString *ts;\n  stringtable *tb;\n  if (l+1 > (MAX_SIZET - sizeof(TString))/sizeof(char))\n    luaM_toobig(L);\n  ts = cast(TString *, luaM_malloc(L, (l+1)*sizeof(char)+sizeof(TString)));\n  ts->tsv.len = l;\n  ts->tsv.hash = h;\n  ts->tsv.marked = luaC_white(G(L));\n  ts->tsv.tt = LUA_TSTRING;\n  ts->tsv.reserved = 0;\n  memcpy(ts+1, str, l*sizeof(char));\n  ((char *)(ts+1))[l] = '\\0';  /* ending 0 */\n  tb = &G(L)->strt;\n  h = lmod(h, tb->size);\n  ts->tsv.next = tb->hash[h];  /* chain new entry */\n  tb->hash[h] = obj2gco(ts);\n  tb->nuse++;\n  if (tb->nuse > cast(lu_int32, tb->size) && tb->size <= MAX_INT/2)\n    luaS_resize(L, tb->size*2);  /* too crowded */\n  return ts;\n}\n\n\nTString *luaS_newlstr (lua_State *L, const char *str, size_t l) {\n  GCObject *o;\n  unsigned int h = cast(unsigned int, l);  /* seed */\n  size_t step = (l>>5)+1;  /* if string is too long, don't hash all its chars */\n  size_t l1;\n  for (l1=l; l1>=step; l1-=step)  /* compute hash */\n    h = h ^ ((h<<5)+(h>>2)+cast(unsigned char, str[l1-1]));\n  for (o = G(L)->strt.hash[lmod(h, G(L)->strt.size)];\n       o != NULL;\n       o = o->gch.next) {\n    TString *ts = rawgco2ts(o);\n    if (ts->tsv.len == l && (memcmp(str, getstr(ts), l) == 0)) {\n      /* string may be dead */\n      if (isdead(G(L), o)) changewhite(o);\n      return ts;\n    }\n  }\n  return newlstr(L, str, l, h);  /* not found */\n}\n\n\nUdata *luaS_newudata (lua_State *L, size_t s, Table *e) {\n  Udata *u;\n  if (s > MAX_SIZET - sizeof(Udata))\n    luaM_toobig(L);\n  u = cast(Udata *, luaM_malloc(L, s + sizeof(Udata)));\n  u->uv.marked = luaC_white(G(L));  /* is not finalized */\n  u->uv.tt = LUA_TUSERDATA;\n  u->uv.len = s;\n  u->uv.metatable = NULL;\n  u->uv.env = e;\n  /* chain it on udata list (after main thread) */\n  u->uv.next = G(L)->mainthread->next;\n  G(L)->mainthread->next = obj2gco(u);\n  return u;\n}\n\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.8/deps/lua/src/lstring.h",
    "content": "/*\n** $Id: lstring.h,v 1.43.1.1 2007/12/27 13:02:25 roberto Exp $\n** String table (keep all strings handled by Lua)\n** See Copyright Notice in lua.h\n*/\n\n#ifndef lstring_h\n#define lstring_h\n\n\n#include \"lgc.h\"\n#include \"lobject.h\"\n#include \"lstate.h\"\n\n\n#define sizestring(s)\t(sizeof(union TString)+((s)->len+1)*sizeof(char))\n\n#define sizeudata(u)\t(sizeof(union Udata)+(u)->len)\n\n#define luaS_new(L, s)\t(luaS_newlstr(L, s, strlen(s)))\n#define luaS_newliteral(L, s)\t(luaS_newlstr(L, \"\" s, \\\n                                 (sizeof(s)/sizeof(char))-1))\n\n#define luaS_fix(s)\tl_setbit((s)->tsv.marked, FIXEDBIT)\n\nLUAI_FUNC void luaS_resize (lua_State *L, int newsize);\nLUAI_FUNC Udata *luaS_newudata (lua_State *L, size_t s, Table *e);\nLUAI_FUNC TString *luaS_newlstr (lua_State *L, const char *str, size_t l);\n\n\n#endif\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.8/deps/lua/src/lstrlib.c",
    "content": "/*\n** $Id: lstrlib.c,v 1.132.1.5 2010/05/14 15:34:19 roberto Exp $\n** Standard library for string operations and pattern-matching\n** See Copyright Notice in lua.h\n*/\n\n\n#include <ctype.h>\n#include <stddef.h>\n#include <stdio.h>\n#include <stdlib.h>\n#include <string.h>\n\n#define lstrlib_c\n#define LUA_LIB\n\n#include \"lua.h\"\n\n#include \"lauxlib.h\"\n#include \"lualib.h\"\n\n\n/* macro to `unsign' a character */\n#define uchar(c)        ((unsigned char)(c))\n\n\n\nstatic int str_len (lua_State *L) {\n  size_t l;\n  luaL_checklstring(L, 1, &l);\n  lua_pushinteger(L, l);\n  return 1;\n}\n\n\nstatic ptrdiff_t posrelat (ptrdiff_t pos, size_t len) {\n  /* relative string position: negative means back from end */\n  if (pos < 0) pos += (ptrdiff_t)len + 1;\n  return (pos >= 0) ? pos : 0;\n}\n\n\nstatic int str_sub (lua_State *L) {\n  size_t l;\n  const char *s = luaL_checklstring(L, 1, &l);\n  ptrdiff_t start = posrelat(luaL_checkinteger(L, 2), l);\n  ptrdiff_t end = posrelat(luaL_optinteger(L, 3, -1), l);\n  if (start < 1) start = 1;\n  if (end > (ptrdiff_t)l) end = (ptrdiff_t)l;\n  if (start <= end)\n    lua_pushlstring(L, s+start-1, end-start+1);\n  else lua_pushliteral(L, \"\");\n  return 1;\n}\n\n\nstatic int str_reverse (lua_State *L) {\n  size_t l;\n  luaL_Buffer b;\n  const char *s = luaL_checklstring(L, 1, &l);\n  luaL_buffinit(L, &b);\n  while (l--) luaL_addchar(&b, s[l]);\n  luaL_pushresult(&b);\n  return 1;\n}\n\n\nstatic int str_lower (lua_State *L) {\n  size_t l;\n  size_t i;\n  luaL_Buffer b;\n  const char *s = luaL_checklstring(L, 1, &l);\n  luaL_buffinit(L, &b);\n  for (i=0; i<l; i++)\n    luaL_addchar(&b, tolower(uchar(s[i])));\n  luaL_pushresult(&b);\n  return 1;\n}\n\n\nstatic int str_upper (lua_State *L) {\n  size_t l;\n  size_t i;\n  luaL_Buffer b;\n  const char *s = luaL_checklstring(L, 1, &l);\n  luaL_buffinit(L, &b);\n  for (i=0; i<l; i++)\n    luaL_addchar(&b, toupper(uchar(s[i])));\n  luaL_pushresult(&b);\n  return 1;\n}\n\nstatic int str_rep (lua_State *L) {\n  size_t l;\n  luaL_Buffer b;\n  const char *s = luaL_checklstring(L, 1, &l);\n  int n = luaL_checkint(L, 2);\n  luaL_buffinit(L, &b);\n  while (n-- > 0)\n    luaL_addlstring(&b, s, l);\n  luaL_pushresult(&b);\n  return 1;\n}\n\n\nstatic int str_byte (lua_State *L) {\n  size_t l;\n  const char *s = luaL_checklstring(L, 1, &l);\n  ptrdiff_t posi = posrelat(luaL_optinteger(L, 2, 1), l);\n  ptrdiff_t pose = posrelat(luaL_optinteger(L, 3, posi), l);\n  int n, i;\n  if (posi <= 0) posi = 1;\n  if ((size_t)pose > l) pose = l;\n  if (posi > pose) return 0;  /* empty interval; return no values */\n  n = (int)(pose -  posi + 1);\n  if (posi + n <= pose)  /* overflow? */\n    luaL_error(L, \"string slice too long\");\n  luaL_checkstack(L, n, \"string slice too long\");\n  for (i=0; i<n; i++)\n    lua_pushinteger(L, uchar(s[posi+i-1]));\n  return n;\n}\n\n\nstatic int str_char (lua_State *L) {\n  int n = lua_gettop(L);  /* number of arguments */\n  int i;\n  luaL_Buffer b;\n  luaL_buffinit(L, &b);\n  for (i=1; i<=n; i++) {\n    int c = luaL_checkint(L, i);\n    luaL_argcheck(L, uchar(c) == c, i, \"invalid value\");\n    luaL_addchar(&b, uchar(c));\n  }\n  luaL_pushresult(&b);\n  return 1;\n}\n\n\nstatic int writer (lua_State *L, const void* b, size_t size, void* B) {\n  (void)L;\n  luaL_addlstring((luaL_Buffer*) B, (const char *)b, size);\n  return 0;\n}\n\n\nstatic int str_dump (lua_State *L) {\n  luaL_Buffer b;\n  luaL_checktype(L, 1, LUA_TFUNCTION);\n  lua_settop(L, 1);\n  luaL_buffinit(L,&b);\n  if (lua_dump(L, writer, &b) != 0)\n    luaL_error(L, \"unable to dump given function\");\n  luaL_pushresult(&b);\n  return 1;\n}\n\n\n\n/*\n** {======================================================\n** PATTERN MATCHING\n** =======================================================\n*/\n\n\n#define CAP_UNFINISHED\t(-1)\n#define CAP_POSITION\t(-2)\n\ntypedef struct MatchState {\n  const char *src_init;  /* init of source string */\n  const char *src_end;  /* end (`\\0') of source string */\n  lua_State *L;\n  int level;  /* total number of captures (finished or unfinished) */\n  struct {\n    const char *init;\n    ptrdiff_t len;\n  } capture[LUA_MAXCAPTURES];\n} MatchState;\n\n\n#define L_ESC\t\t'%'\n#define SPECIALS\t\"^$*+?.([%-\"\n\n\nstatic int check_capture (MatchState *ms, int l) {\n  l -= '1';\n  if (l < 0 || l >= ms->level || ms->capture[l].len == CAP_UNFINISHED)\n    return luaL_error(ms->L, \"invalid capture index\");\n  return l;\n}\n\n\nstatic int capture_to_close (MatchState *ms) {\n  int level = ms->level;\n  for (level--; level>=0; level--)\n    if (ms->capture[level].len == CAP_UNFINISHED) return level;\n  return luaL_error(ms->L, \"invalid pattern capture\");\n}\n\n\nstatic const char *classend (MatchState *ms, const char *p) {\n  switch (*p++) {\n    case L_ESC: {\n      if (*p == '\\0')\n        luaL_error(ms->L, \"malformed pattern (ends with \" LUA_QL(\"%%\") \")\");\n      return p+1;\n    }\n    case '[': {\n      if (*p == '^') p++;\n      do {  /* look for a `]' */\n        if (*p == '\\0')\n          luaL_error(ms->L, \"malformed pattern (missing \" LUA_QL(\"]\") \")\");\n        if (*(p++) == L_ESC && *p != '\\0')\n          p++;  /* skip escapes (e.g. `%]') */\n      } while (*p != ']');\n      return p+1;\n    }\n    default: {\n      return p;\n    }\n  }\n}\n\n\nstatic int match_class (int c, int cl) {\n  int res;\n  switch (tolower(cl)) {\n    case 'a' : res = isalpha(c); break;\n    case 'c' : res = iscntrl(c); break;\n    case 'd' : res = isdigit(c); break;\n    case 'l' : res = islower(c); break;\n    case 'p' : res = ispunct(c); break;\n    case 's' : res = isspace(c); break;\n    case 'u' : res = isupper(c); break;\n    case 'w' : res = isalnum(c); break;\n    case 'x' : res = isxdigit(c); break;\n    case 'z' : res = (c == 0); break;\n    default: return (cl == c);\n  }\n  return (islower(cl) ? res : !res);\n}\n\n\nstatic int matchbracketclass (int c, const char *p, const char *ec) {\n  int sig = 1;\n  if (*(p+1) == '^') {\n    sig = 0;\n    p++;  /* skip the `^' */\n  }\n  while (++p < ec) {\n    if (*p == L_ESC) {\n      p++;\n      if (match_class(c, uchar(*p)))\n        return sig;\n    }\n    else if ((*(p+1) == '-') && (p+2 < ec)) {\n      p+=2;\n      if (uchar(*(p-2)) <= c && c <= uchar(*p))\n        return sig;\n    }\n    else if (uchar(*p) == c) return sig;\n  }\n  return !sig;\n}\n\n\nstatic int singlematch (int c, const char *p, const char *ep) {\n  switch (*p) {\n    case '.': return 1;  /* matches any char */\n    case L_ESC: return match_class(c, uchar(*(p+1)));\n    case '[': return matchbracketclass(c, p, ep-1);\n    default:  return (uchar(*p) == c);\n  }\n}\n\n\nstatic const char *match (MatchState *ms, const char *s, const char *p);\n\n\nstatic const char *matchbalance (MatchState *ms, const char *s,\n                                   const char *p) {\n  if (*p == 0 || *(p+1) == 0)\n    luaL_error(ms->L, \"unbalanced pattern\");\n  if (*s != *p) return NULL;\n  else {\n    int b = *p;\n    int e = *(p+1);\n    int cont = 1;\n    while (++s < ms->src_end) {\n      if (*s == e) {\n        if (--cont == 0) return s+1;\n      }\n      else if (*s == b) cont++;\n    }\n  }\n  return NULL;  /* string ends out of balance */\n}\n\n\nstatic const char *max_expand (MatchState *ms, const char *s,\n                                 const char *p, const char *ep) {\n  ptrdiff_t i = 0;  /* counts maximum expand for item */\n  while ((s+i)<ms->src_end && singlematch(uchar(*(s+i)), p, ep))\n    i++;\n  /* keeps trying to match with the maximum repetitions */\n  while (i>=0) {\n    const char *res = match(ms, (s+i), ep+1);\n    if (res) return res;\n    i--;  /* else didn't match; reduce 1 repetition to try again */\n  }\n  return NULL;\n}\n\n\nstatic const char *min_expand (MatchState *ms, const char *s,\n                                 const char *p, const char *ep) {\n  for (;;) {\n    const char *res = match(ms, s, ep+1);\n    if (res != NULL)\n      return res;\n    else if (s<ms->src_end && singlematch(uchar(*s), p, ep))\n      s++;  /* try with one more repetition */\n    else return NULL;\n  }\n}\n\n\nstatic const char *start_capture (MatchState *ms, const char *s,\n                                    const char *p, int what) {\n  const char *res;\n  int level = ms->level;\n  if (level >= LUA_MAXCAPTURES) luaL_error(ms->L, \"too many captures\");\n  ms->capture[level].init = s;\n  ms->capture[level].len = what;\n  ms->level = level+1;\n  if ((res=match(ms, s, p)) == NULL)  /* match failed? */\n    ms->level--;  /* undo capture */\n  return res;\n}\n\n\nstatic const char *end_capture (MatchState *ms, const char *s,\n                                  const char *p) {\n  int l = capture_to_close(ms);\n  const char *res;\n  ms->capture[l].len = s - ms->capture[l].init;  /* close capture */\n  if ((res = match(ms, s, p)) == NULL)  /* match failed? */\n    ms->capture[l].len = CAP_UNFINISHED;  /* undo capture */\n  return res;\n}\n\n\nstatic const char *match_capture (MatchState *ms, const char *s, int l) {\n  size_t len;\n  l = check_capture(ms, l);\n  len = ms->capture[l].len;\n  if ((size_t)(ms->src_end-s) >= len &&\n      memcmp(ms->capture[l].init, s, len) == 0)\n    return s+len;\n  else return NULL;\n}\n\n\nstatic const char *match (MatchState *ms, const char *s, const char *p) {\n  init: /* using goto's to optimize tail recursion */\n  switch (*p) {\n    case '(': {  /* start capture */\n      if (*(p+1) == ')')  /* position capture? */\n        return start_capture(ms, s, p+2, CAP_POSITION);\n      else\n        return start_capture(ms, s, p+1, CAP_UNFINISHED);\n    }\n    case ')': {  /* end capture */\n      return end_capture(ms, s, p+1);\n    }\n    case L_ESC: {\n      switch (*(p+1)) {\n        case 'b': {  /* balanced string? */\n          s = matchbalance(ms, s, p+2);\n          if (s == NULL) return NULL;\n          p+=4; goto init;  /* else return match(ms, s, p+4); */\n        }\n        case 'f': {  /* frontier? */\n          const char *ep; char previous;\n          p += 2;\n          if (*p != '[')\n            luaL_error(ms->L, \"missing \" LUA_QL(\"[\") \" after \"\n                               LUA_QL(\"%%f\") \" in pattern\");\n          ep = classend(ms, p);  /* points to what is next */\n          previous = (s == ms->src_init) ? '\\0' : *(s-1);\n          if (matchbracketclass(uchar(previous), p, ep-1) ||\n             !matchbracketclass(uchar(*s), p, ep-1)) return NULL;\n          p=ep; goto init;  /* else return match(ms, s, ep); */\n        }\n        default: {\n          if (isdigit(uchar(*(p+1)))) {  /* capture results (%0-%9)? */\n            s = match_capture(ms, s, uchar(*(p+1)));\n            if (s == NULL) return NULL;\n            p+=2; goto init;  /* else return match(ms, s, p+2) */\n          }\n          goto dflt;  /* case default */\n        }\n      }\n    }\n    case '\\0': {  /* end of pattern */\n      return s;  /* match succeeded */\n    }\n    case '$': {\n      if (*(p+1) == '\\0')  /* is the `$' the last char in pattern? */\n        return (s == ms->src_end) ? s : NULL;  /* check end of string */\n      else goto dflt;\n    }\n    default: dflt: {  /* it is a pattern item */\n      const char *ep = classend(ms, p);  /* points to what is next */\n      int m = s<ms->src_end && singlematch(uchar(*s), p, ep);\n      switch (*ep) {\n        case '?': {  /* optional */\n          const char *res;\n          if (m && ((res=match(ms, s+1, ep+1)) != NULL))\n            return res;\n          p=ep+1; goto init;  /* else return match(ms, s, ep+1); */\n        }\n        case '*': {  /* 0 or more repetitions */\n          return max_expand(ms, s, p, ep);\n        }\n        case '+': {  /* 1 or more repetitions */\n          return (m ? max_expand(ms, s+1, p, ep) : NULL);\n        }\n        case '-': {  /* 0 or more repetitions (minimum) */\n          return min_expand(ms, s, p, ep);\n        }\n        default: {\n          if (!m) return NULL;\n          s++; p=ep; goto init;  /* else return match(ms, s+1, ep); */\n        }\n      }\n    }\n  }\n}\n\n\n\nstatic const char *lmemfind (const char *s1, size_t l1,\n                               const char *s2, size_t l2) {\n  if (l2 == 0) return s1;  /* empty strings are everywhere */\n  else if (l2 > l1) return NULL;  /* avoids a negative `l1' */\n  else {\n    const char *init;  /* to search for a `*s2' inside `s1' */\n    l2--;  /* 1st char will be checked by `memchr' */\n    l1 = l1-l2;  /* `s2' cannot be found after that */\n    while (l1 > 0 && (init = (const char *)memchr(s1, *s2, l1)) != NULL) {\n      init++;   /* 1st char is already checked */\n      if (memcmp(init, s2+1, l2) == 0)\n        return init-1;\n      else {  /* correct `l1' and `s1' to try again */\n        l1 -= init-s1;\n        s1 = init;\n      }\n    }\n    return NULL;  /* not found */\n  }\n}\n\n\nstatic void push_onecapture (MatchState *ms, int i, const char *s,\n                                                    const char *e) {\n  if (i >= ms->level) {\n    if (i == 0)  /* ms->level == 0, too */\n      lua_pushlstring(ms->L, s, e - s);  /* add whole match */\n    else\n      luaL_error(ms->L, \"invalid capture index\");\n  }\n  else {\n    ptrdiff_t l = ms->capture[i].len;\n    if (l == CAP_UNFINISHED) luaL_error(ms->L, \"unfinished capture\");\n    if (l == CAP_POSITION)\n      lua_pushinteger(ms->L, ms->capture[i].init - ms->src_init + 1);\n    else\n      lua_pushlstring(ms->L, ms->capture[i].init, l);\n  }\n}\n\n\nstatic int push_captures (MatchState *ms, const char *s, const char *e) {\n  int i;\n  int nlevels = (ms->level == 0 && s) ? 1 : ms->level;\n  luaL_checkstack(ms->L, nlevels, \"too many captures\");\n  for (i = 0; i < nlevels; i++)\n    push_onecapture(ms, i, s, e);\n  return nlevels;  /* number of strings pushed */\n}\n\n\nstatic int str_find_aux (lua_State *L, int find) {\n  size_t l1, l2;\n  const char *s = luaL_checklstring(L, 1, &l1);\n  const char *p = luaL_checklstring(L, 2, &l2);\n  ptrdiff_t init = posrelat(luaL_optinteger(L, 3, 1), l1) - 1;\n  if (init < 0) init = 0;\n  else if ((size_t)(init) > l1) init = (ptrdiff_t)l1;\n  if (find && (lua_toboolean(L, 4) ||  /* explicit request? */\n      strpbrk(p, SPECIALS) == NULL)) {  /* or no special characters? */\n    /* do a plain search */\n    const char *s2 = lmemfind(s+init, l1-init, p, l2);\n    if (s2) {\n      lua_pushinteger(L, s2-s+1);\n      lua_pushinteger(L, s2-s+l2);\n      return 2;\n    }\n  }\n  else {\n    MatchState ms;\n    int anchor = (*p == '^') ? (p++, 1) : 0;\n    const char *s1=s+init;\n    ms.L = L;\n    ms.src_init = s;\n    ms.src_end = s+l1;\n    do {\n      const char *res;\n      ms.level = 0;\n      if ((res=match(&ms, s1, p)) != NULL) {\n        if (find) {\n          lua_pushinteger(L, s1-s+1);  /* start */\n          lua_pushinteger(L, res-s);   /* end */\n          return push_captures(&ms, NULL, 0) + 2;\n        }\n        else\n          return push_captures(&ms, s1, res);\n      }\n    } while (s1++ < ms.src_end && !anchor);\n  }\n  lua_pushnil(L);  /* not found */\n  return 1;\n}\n\n\nstatic int str_find (lua_State *L) {\n  return str_find_aux(L, 1);\n}\n\n\nstatic int str_match (lua_State *L) {\n  return str_find_aux(L, 0);\n}\n\n\nstatic int gmatch_aux (lua_State *L) {\n  MatchState ms;\n  size_t ls;\n  const char *s = lua_tolstring(L, lua_upvalueindex(1), &ls);\n  const char *p = lua_tostring(L, lua_upvalueindex(2));\n  const char *src;\n  ms.L = L;\n  ms.src_init = s;\n  ms.src_end = s+ls;\n  for (src = s + (size_t)lua_tointeger(L, lua_upvalueindex(3));\n       src <= ms.src_end;\n       src++) {\n    const char *e;\n    ms.level = 0;\n    if ((e = match(&ms, src, p)) != NULL) {\n      lua_Integer newstart = e-s;\n      if (e == src) newstart++;  /* empty match? go at least one position */\n      lua_pushinteger(L, newstart);\n      lua_replace(L, lua_upvalueindex(3));\n      return push_captures(&ms, src, e);\n    }\n  }\n  return 0;  /* not found */\n}\n\n\nstatic int gmatch (lua_State *L) {\n  luaL_checkstring(L, 1);\n  luaL_checkstring(L, 2);\n  lua_settop(L, 2);\n  lua_pushinteger(L, 0);\n  lua_pushcclosure(L, gmatch_aux, 3);\n  return 1;\n}\n\n\nstatic int gfind_nodef (lua_State *L) {\n  return luaL_error(L, LUA_QL(\"string.gfind\") \" was renamed to \"\n                       LUA_QL(\"string.gmatch\"));\n}\n\n\nstatic void add_s (MatchState *ms, luaL_Buffer *b, const char *s,\n                                                   const char *e) {\n  size_t l, i;\n  const char *news = lua_tolstring(ms->L, 3, &l);\n  for (i = 0; i < l; i++) {\n    if (news[i] != L_ESC)\n      luaL_addchar(b, news[i]);\n    else {\n      i++;  /* skip ESC */\n      if (!isdigit(uchar(news[i])))\n        luaL_addchar(b, news[i]);\n      else if (news[i] == '0')\n          luaL_addlstring(b, s, e - s);\n      else {\n        push_onecapture(ms, news[i] - '1', s, e);\n        luaL_addvalue(b);  /* add capture to accumulated result */\n      }\n    }\n  }\n}\n\n\nstatic void add_value (MatchState *ms, luaL_Buffer *b, const char *s,\n                                                       const char *e) {\n  lua_State *L = ms->L;\n  switch (lua_type(L, 3)) {\n    case LUA_TNUMBER:\n    case LUA_TSTRING: {\n      add_s(ms, b, s, e);\n      return;\n    }\n    case LUA_TFUNCTION: {\n      int n;\n      lua_pushvalue(L, 3);\n      n = push_captures(ms, s, e);\n      lua_call(L, n, 1);\n      break;\n    }\n    case LUA_TTABLE: {\n      push_onecapture(ms, 0, s, e);\n      lua_gettable(L, 3);\n      break;\n    }\n  }\n  if (!lua_toboolean(L, -1)) {  /* nil or false? */\n    lua_pop(L, 1);\n    lua_pushlstring(L, s, e - s);  /* keep original text */\n  }\n  else if (!lua_isstring(L, -1))\n    luaL_error(L, \"invalid replacement value (a %s)\", luaL_typename(L, -1)); \n  luaL_addvalue(b);  /* add result to accumulator */\n}\n\n\nstatic int str_gsub (lua_State *L) {\n  size_t srcl;\n  const char *src = luaL_checklstring(L, 1, &srcl);\n  const char *p = luaL_checkstring(L, 2);\n  int  tr = lua_type(L, 3);\n  int max_s = luaL_optint(L, 4, srcl+1);\n  int anchor = (*p == '^') ? (p++, 1) : 0;\n  int n = 0;\n  MatchState ms;\n  luaL_Buffer b;\n  luaL_argcheck(L, tr == LUA_TNUMBER || tr == LUA_TSTRING ||\n                   tr == LUA_TFUNCTION || tr == LUA_TTABLE, 3,\n                      \"string/function/table expected\");\n  luaL_buffinit(L, &b);\n  ms.L = L;\n  ms.src_init = src;\n  ms.src_end = src+srcl;\n  while (n < max_s) {\n    const char *e;\n    ms.level = 0;\n    e = match(&ms, src, p);\n    if (e) {\n      n++;\n      add_value(&ms, &b, src, e);\n    }\n    if (e && e>src) /* non empty match? */\n      src = e;  /* skip it */\n    else if (src < ms.src_end)\n      luaL_addchar(&b, *src++);\n    else break;\n    if (anchor) break;\n  }\n  luaL_addlstring(&b, src, ms.src_end-src);\n  luaL_pushresult(&b);\n  lua_pushinteger(L, n);  /* number of substitutions */\n  return 2;\n}\n\n/* }====================================================== */\n\n\n/* maximum size of each formatted item (> len(format('%99.99f', -1e308))) */\n#define MAX_ITEM\t512\n/* valid flags in a format specification */\n#define FLAGS\t\"-+ #0\"\n/*\n** maximum size of each format specification (such as '%-099.99d')\n** (+10 accounts for %99.99x plus margin of error)\n*/\n#define MAX_FORMAT\t(sizeof(FLAGS) + sizeof(LUA_INTFRMLEN) + 10)\n\n\nstatic void addquoted (lua_State *L, luaL_Buffer *b, int arg) {\n  size_t l;\n  const char *s = luaL_checklstring(L, arg, &l);\n  luaL_addchar(b, '\"');\n  while (l--) {\n    switch (*s) {\n      case '\"': case '\\\\': case '\\n': {\n        luaL_addchar(b, '\\\\');\n        luaL_addchar(b, *s);\n        break;\n      }\n      case '\\r': {\n        luaL_addlstring(b, \"\\\\r\", 2);\n        break;\n      }\n      case '\\0': {\n        luaL_addlstring(b, \"\\\\000\", 4);\n        break;\n      }\n      default: {\n        luaL_addchar(b, *s);\n        break;\n      }\n    }\n    s++;\n  }\n  luaL_addchar(b, '\"');\n}\n\nstatic const char *scanformat (lua_State *L, const char *strfrmt, char *form) {\n  const char *p = strfrmt;\n  while (*p != '\\0' && strchr(FLAGS, *p) != NULL) p++;  /* skip flags */\n  if ((size_t)(p - strfrmt) >= sizeof(FLAGS))\n    luaL_error(L, \"invalid format (repeated flags)\");\n  if (isdigit(uchar(*p))) p++;  /* skip width */\n  if (isdigit(uchar(*p))) p++;  /* (2 digits at most) */\n  if (*p == '.') {\n    p++;\n    if (isdigit(uchar(*p))) p++;  /* skip precision */\n    if (isdigit(uchar(*p))) p++;  /* (2 digits at most) */\n  }\n  if (isdigit(uchar(*p)))\n    luaL_error(L, \"invalid format (width or precision too long)\");\n  *(form++) = '%';\n  strncpy(form, strfrmt, p - strfrmt + 1);\n  form += p - strfrmt + 1;\n  *form = '\\0';\n  return p;\n}\n\n\nstatic void addintlen (char *form) {\n  size_t l = strlen(form);\n  char spec = form[l - 1];\n  strcpy(form + l - 1, LUA_INTFRMLEN);\n  form[l + sizeof(LUA_INTFRMLEN) - 2] = spec;\n  form[l + sizeof(LUA_INTFRMLEN) - 1] = '\\0';\n}\n\n\nstatic int str_format (lua_State *L) {\n  int top = lua_gettop(L);\n  int arg = 1;\n  size_t sfl;\n  const char *strfrmt = luaL_checklstring(L, arg, &sfl);\n  const char *strfrmt_end = strfrmt+sfl;\n  luaL_Buffer b;\n  luaL_buffinit(L, &b);\n  while (strfrmt < strfrmt_end) {\n    if (*strfrmt != L_ESC)\n      luaL_addchar(&b, *strfrmt++);\n    else if (*++strfrmt == L_ESC)\n      luaL_addchar(&b, *strfrmt++);  /* %% */\n    else { /* format item */\n      char form[MAX_FORMAT];  /* to store the format (`%...') */\n      char buff[MAX_ITEM];  /* to store the formatted item */\n      if (++arg > top)\n        luaL_argerror(L, arg, \"no value\");\n      strfrmt = scanformat(L, strfrmt, form);\n      switch (*strfrmt++) {\n        case 'c': {\n          sprintf(buff, form, (int)luaL_checknumber(L, arg));\n          break;\n        }\n        case 'd':  case 'i': {\n          addintlen(form);\n          sprintf(buff, form, (LUA_INTFRM_T)luaL_checknumber(L, arg));\n          break;\n        }\n        case 'o':  case 'u':  case 'x':  case 'X': {\n          addintlen(form);\n          sprintf(buff, form, (unsigned LUA_INTFRM_T)luaL_checknumber(L, arg));\n          break;\n        }\n        case 'e':  case 'E': case 'f':\n        case 'g': case 'G': {\n          sprintf(buff, form, (double)luaL_checknumber(L, arg));\n          break;\n        }\n        case 'q': {\n          addquoted(L, &b, arg);\n          continue;  /* skip the 'addsize' at the end */\n        }\n        case 's': {\n          size_t l;\n          const char *s = luaL_checklstring(L, arg, &l);\n          if (!strchr(form, '.') && l >= 100) {\n            /* no precision and string is too long to be formatted;\n               keep original string */\n            lua_pushvalue(L, arg);\n            luaL_addvalue(&b);\n            continue;  /* skip the `addsize' at the end */\n          }\n          else {\n            sprintf(buff, form, s);\n            break;\n          }\n        }\n        default: {  /* also treat cases `pnLlh' */\n          return luaL_error(L, \"invalid option \" LUA_QL(\"%%%c\") \" to \"\n                               LUA_QL(\"format\"), *(strfrmt - 1));\n        }\n      }\n      luaL_addlstring(&b, buff, strlen(buff));\n    }\n  }\n  luaL_pushresult(&b);\n  return 1;\n}\n\n\nstatic const luaL_Reg strlib[] = {\n  {\"byte\", str_byte},\n  {\"char\", str_char},\n  {\"dump\", str_dump},\n  {\"find\", str_find},\n  {\"format\", str_format},\n  {\"gfind\", gfind_nodef},\n  {\"gmatch\", gmatch},\n  {\"gsub\", str_gsub},\n  {\"len\", str_len},\n  {\"lower\", str_lower},\n  {\"match\", str_match},\n  {\"rep\", str_rep},\n  {\"reverse\", str_reverse},\n  {\"sub\", str_sub},\n  {\"upper\", str_upper},\n  {NULL, NULL}\n};\n\n\nstatic void createmetatable (lua_State *L) {\n  lua_createtable(L, 0, 1);  /* create metatable for strings */\n  lua_pushliteral(L, \"\");  /* dummy string */\n  lua_pushvalue(L, -2);\n  lua_setmetatable(L, -2);  /* set string metatable */\n  lua_pop(L, 1);  /* pop dummy string */\n  lua_pushvalue(L, -2);  /* string library... */\n  lua_setfield(L, -2, \"__index\");  /* ...is the __index metamethod */\n  lua_pop(L, 1);  /* pop metatable */\n}\n\n\n/*\n** Open string library\n*/\nLUALIB_API int luaopen_string (lua_State *L) {\n  luaL_register(L, LUA_STRLIBNAME, strlib);\n#if defined(LUA_COMPAT_GFIND)\n  lua_getfield(L, -1, \"gmatch\");\n  lua_setfield(L, -2, \"gfind\");\n#endif\n  createmetatable(L);\n  return 1;\n}\n\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.8/deps/lua/src/ltable.c",
    "content": "/*\n** $Id: ltable.c,v 2.32.1.2 2007/12/28 15:32:23 roberto Exp $\n** Lua tables (hash)\n** See Copyright Notice in lua.h\n*/\n\n\n/*\n** Implementation of tables (aka arrays, objects, or hash tables).\n** Tables keep its elements in two parts: an array part and a hash part.\n** Non-negative integer keys are all candidates to be kept in the array\n** part. The actual size of the array is the largest `n' such that at\n** least half the slots between 0 and n are in use.\n** Hash uses a mix of chained scatter table with Brent's variation.\n** A main invariant of these tables is that, if an element is not\n** in its main position (i.e. the `original' position that its hash gives\n** to it), then the colliding element is in its own main position.\n** Hence even when the load factor reaches 100%, performance remains good.\n*/\n\n#include <math.h>\n#include <string.h>\n\n#define ltable_c\n#define LUA_CORE\n\n#include \"lua.h\"\n\n#include \"ldebug.h\"\n#include \"ldo.h\"\n#include \"lgc.h\"\n#include \"lmem.h\"\n#include \"lobject.h\"\n#include \"lstate.h\"\n#include \"ltable.h\"\n\n\n/*\n** max size of array part is 2^MAXBITS\n*/\n#if LUAI_BITSINT > 26\n#define MAXBITS\t\t26\n#else\n#define MAXBITS\t\t(LUAI_BITSINT-2)\n#endif\n\n#define MAXASIZE\t(1 << MAXBITS)\n\n\n#define hashpow2(t,n)      (gnode(t, lmod((n), sizenode(t))))\n  \n#define hashstr(t,str)  hashpow2(t, (str)->tsv.hash)\n#define hashboolean(t,p)        hashpow2(t, p)\n\n\n/*\n** for some types, it is better to avoid modulus by power of 2, as\n** they tend to have many 2 factors.\n*/\n#define hashmod(t,n)\t(gnode(t, ((n) % ((sizenode(t)-1)|1))))\n\n\n#define hashpointer(t,p)\thashmod(t, IntPoint(p))\n\n\n/*\n** number of ints inside a lua_Number\n*/\n#define numints\t\tcast_int(sizeof(lua_Number)/sizeof(int))\n\n\n\n#define dummynode\t\t(&dummynode_)\n\nstatic const Node dummynode_ = {\n  {{NULL}, LUA_TNIL},  /* value */\n  {{{NULL}, LUA_TNIL, NULL}}  /* key */\n};\n\n\n/*\n** hash for lua_Numbers\n*/\nstatic Node *hashnum (const Table *t, lua_Number n) {\n  unsigned int a[numints];\n  int i;\n  if (luai_numeq(n, 0))  /* avoid problems with -0 */\n    return gnode(t, 0);\n  memcpy(a, &n, sizeof(a));\n  for (i = 1; i < numints; i++) a[0] += a[i];\n  return hashmod(t, a[0]);\n}\n\n\n\n/*\n** returns the `main' position of an element in a table (that is, the index\n** of its hash value)\n*/\nstatic Node *mainposition (const Table *t, const TValue *key) {\n  switch (ttype(key)) {\n    case LUA_TNUMBER:\n      return hashnum(t, nvalue(key));\n    case LUA_TSTRING:\n      return hashstr(t, rawtsvalue(key));\n    case LUA_TBOOLEAN:\n      return hashboolean(t, bvalue(key));\n    case LUA_TLIGHTUSERDATA:\n      return hashpointer(t, pvalue(key));\n    default:\n      return hashpointer(t, gcvalue(key));\n  }\n}\n\n\n/*\n** returns the index for `key' if `key' is an appropriate key to live in\n** the array part of the table, -1 otherwise.\n*/\nstatic int arrayindex (const TValue *key) {\n  if (ttisnumber(key)) {\n    lua_Number n = nvalue(key);\n    int k;\n    lua_number2int(k, n);\n    if (luai_numeq(cast_num(k), n))\n      return k;\n  }\n  return -1;  /* `key' did not match some condition */\n}\n\n\n/*\n** returns the index of a `key' for table traversals. First goes all\n** elements in the array part, then elements in the hash part. The\n** beginning of a traversal is signalled by -1.\n*/\nstatic int findindex (lua_State *L, Table *t, StkId key) {\n  int i;\n  if (ttisnil(key)) return -1;  /* first iteration */\n  i = arrayindex(key);\n  if (0 < i && i <= t->sizearray)  /* is `key' inside array part? */\n    return i-1;  /* yes; that's the index (corrected to C) */\n  else {\n    Node *n = mainposition(t, key);\n    do {  /* check whether `key' is somewhere in the chain */\n      /* key may be dead already, but it is ok to use it in `next' */\n      if (luaO_rawequalObj(key2tval(n), key) ||\n            (ttype(gkey(n)) == LUA_TDEADKEY && iscollectable(key) &&\n             gcvalue(gkey(n)) == gcvalue(key))) {\n        i = cast_int(n - gnode(t, 0));  /* key index in hash table */\n        /* hash elements are numbered after array ones */\n        return i + t->sizearray;\n      }\n      else n = gnext(n);\n    } while (n);\n    luaG_runerror(L, \"invalid key to \" LUA_QL(\"next\"));  /* key not found */\n    return 0;  /* to avoid warnings */\n  }\n}\n\n\nint luaH_next (lua_State *L, Table *t, StkId key) {\n  int i = findindex(L, t, key);  /* find original element */\n  for (i++; i < t->sizearray; i++) {  /* try first array part */\n    if (!ttisnil(&t->array[i])) {  /* a non-nil value? */\n      setnvalue(key, cast_num(i+1));\n      setobj2s(L, key+1, &t->array[i]);\n      return 1;\n    }\n  }\n  for (i -= t->sizearray; i < sizenode(t); i++) {  /* then hash part */\n    if (!ttisnil(gval(gnode(t, i)))) {  /* a non-nil value? */\n      setobj2s(L, key, key2tval(gnode(t, i)));\n      setobj2s(L, key+1, gval(gnode(t, i)));\n      return 1;\n    }\n  }\n  return 0;  /* no more elements */\n}\n\n\n/*\n** {=============================================================\n** Rehash\n** ==============================================================\n*/\n\n\nstatic int computesizes (int nums[], int *narray) {\n  int i;\n  int twotoi;  /* 2^i */\n  int a = 0;  /* number of elements smaller than 2^i */\n  int na = 0;  /* number of elements to go to array part */\n  int n = 0;  /* optimal size for array part */\n  for (i = 0, twotoi = 1; twotoi/2 < *narray; i++, twotoi *= 2) {\n    if (nums[i] > 0) {\n      a += nums[i];\n      if (a > twotoi/2) {  /* more than half elements present? */\n        n = twotoi;  /* optimal size (till now) */\n        na = a;  /* all elements smaller than n will go to array part */\n      }\n    }\n    if (a == *narray) break;  /* all elements already counted */\n  }\n  *narray = n;\n  lua_assert(*narray/2 <= na && na <= *narray);\n  return na;\n}\n\n\nstatic int countint (const TValue *key, int *nums) {\n  int k = arrayindex(key);\n  if (0 < k && k <= MAXASIZE) {  /* is `key' an appropriate array index? */\n    nums[ceillog2(k)]++;  /* count as such */\n    return 1;\n  }\n  else\n    return 0;\n}\n\n\nstatic int numusearray (const Table *t, int *nums) {\n  int lg;\n  int ttlg;  /* 2^lg */\n  int ause = 0;  /* summation of `nums' */\n  int i = 1;  /* count to traverse all array keys */\n  for (lg=0, ttlg=1; lg<=MAXBITS; lg++, ttlg*=2) {  /* for each slice */\n    int lc = 0;  /* counter */\n    int lim = ttlg;\n    if (lim > t->sizearray) {\n      lim = t->sizearray;  /* adjust upper limit */\n      if (i > lim)\n        break;  /* no more elements to count */\n    }\n    /* count elements in range (2^(lg-1), 2^lg] */\n    for (; i <= lim; i++) {\n      if (!ttisnil(&t->array[i-1]))\n        lc++;\n    }\n    nums[lg] += lc;\n    ause += lc;\n  }\n  return ause;\n}\n\n\nstatic int numusehash (const Table *t, int *nums, int *pnasize) {\n  int totaluse = 0;  /* total number of elements */\n  int ause = 0;  /* summation of `nums' */\n  int i = sizenode(t);\n  while (i--) {\n    Node *n = &t->node[i];\n    if (!ttisnil(gval(n))) {\n      ause += countint(key2tval(n), nums);\n      totaluse++;\n    }\n  }\n  *pnasize += ause;\n  return totaluse;\n}\n\n\nstatic void setarrayvector (lua_State *L, Table *t, int size) {\n  int i;\n  luaM_reallocvector(L, t->array, t->sizearray, size, TValue);\n  for (i=t->sizearray; i<size; i++)\n     setnilvalue(&t->array[i]);\n  t->sizearray = size;\n}\n\n\nstatic void setnodevector (lua_State *L, Table *t, int size) {\n  int lsize;\n  if (size == 0) {  /* no elements to hash part? */\n    t->node = cast(Node *, dummynode);  /* use common `dummynode' */\n    lsize = 0;\n  }\n  else {\n    int i;\n    lsize = ceillog2(size);\n    if (lsize > MAXBITS)\n      luaG_runerror(L, \"table overflow\");\n    size = twoto(lsize);\n    t->node = luaM_newvector(L, size, Node);\n    for (i=0; i<size; i++) {\n      Node *n = gnode(t, i);\n      gnext(n) = NULL;\n      setnilvalue(gkey(n));\n      setnilvalue(gval(n));\n    }\n  }\n  t->lsizenode = cast_byte(lsize);\n  t->lastfree = gnode(t, size);  /* all positions are free */\n}\n\n\nstatic void resize (lua_State *L, Table *t, int nasize, int nhsize) {\n  int i;\n  int oldasize = t->sizearray;\n  int oldhsize = t->lsizenode;\n  Node *nold = t->node;  /* save old hash ... */\n  if (nasize > oldasize)  /* array part must grow? */\n    setarrayvector(L, t, nasize);\n  /* create new hash part with appropriate size */\n  setnodevector(L, t, nhsize);  \n  if (nasize < oldasize) {  /* array part must shrink? */\n    t->sizearray = nasize;\n    /* re-insert elements from vanishing slice */\n    for (i=nasize; i<oldasize; i++) {\n      if (!ttisnil(&t->array[i]))\n        setobjt2t(L, luaH_setnum(L, t, i+1), &t->array[i]);\n    }\n    /* shrink array */\n    luaM_reallocvector(L, t->array, oldasize, nasize, TValue);\n  }\n  /* re-insert elements from hash part */\n  for (i = twoto(oldhsize) - 1; i >= 0; i--) {\n    Node *old = nold+i;\n    if (!ttisnil(gval(old)))\n      setobjt2t(L, luaH_set(L, t, key2tval(old)), gval(old));\n  }\n  if (nold != dummynode)\n    luaM_freearray(L, nold, twoto(oldhsize), Node);  /* free old array */\n}\n\n\nvoid luaH_resizearray (lua_State *L, Table *t, int nasize) {\n  int nsize = (t->node == dummynode) ? 0 : sizenode(t);\n  resize(L, t, nasize, nsize);\n}\n\n\nstatic void rehash (lua_State *L, Table *t, const TValue *ek) {\n  int nasize, na;\n  int nums[MAXBITS+1];  /* nums[i] = number of keys between 2^(i-1) and 2^i */\n  int i;\n  int totaluse;\n  for (i=0; i<=MAXBITS; i++) nums[i] = 0;  /* reset counts */\n  nasize = numusearray(t, nums);  /* count keys in array part */\n  totaluse = nasize;  /* all those keys are integer keys */\n  totaluse += numusehash(t, nums, &nasize);  /* count keys in hash part */\n  /* count extra key */\n  nasize += countint(ek, nums);\n  totaluse++;\n  /* compute new size for array part */\n  na = computesizes(nums, &nasize);\n  /* resize the table to new computed sizes */\n  resize(L, t, nasize, totaluse - na);\n}\n\n\n\n/*\n** }=============================================================\n*/\n\n\nTable *luaH_new (lua_State *L, int narray, int nhash) {\n  Table *t = luaM_new(L, Table);\n  luaC_link(L, obj2gco(t), LUA_TTABLE);\n  t->metatable = NULL;\n  t->flags = cast_byte(~0);\n  /* temporary values (kept only if some malloc fails) */\n  t->array = NULL;\n  t->sizearray = 0;\n  t->lsizenode = 0;\n  t->node = cast(Node *, dummynode);\n  setarrayvector(L, t, narray);\n  setnodevector(L, t, nhash);\n  return t;\n}\n\n\nvoid luaH_free (lua_State *L, Table *t) {\n  if (t->node != dummynode)\n    luaM_freearray(L, t->node, sizenode(t), Node);\n  luaM_freearray(L, t->array, t->sizearray, TValue);\n  luaM_free(L, t);\n}\n\n\nstatic Node *getfreepos (Table *t) {\n  while (t->lastfree-- > t->node) {\n    if (ttisnil(gkey(t->lastfree)))\n      return t->lastfree;\n  }\n  return NULL;  /* could not find a free place */\n}\n\n\n\n/*\n** inserts a new key into a hash table; first, check whether key's main \n** position is free. If not, check whether colliding node is in its main \n** position or not: if it is not, move colliding node to an empty place and \n** put new key in its main position; otherwise (colliding node is in its main \n** position), new key goes to an empty position. \n*/\nstatic TValue *newkey (lua_State *L, Table *t, const TValue *key) {\n  Node *mp = mainposition(t, key);\n  if (!ttisnil(gval(mp)) || mp == dummynode) {\n    Node *othern;\n    Node *n = getfreepos(t);  /* get a free place */\n    if (n == NULL) {  /* cannot find a free place? */\n      rehash(L, t, key);  /* grow table */\n      return luaH_set(L, t, key);  /* re-insert key into grown table */\n    }\n    lua_assert(n != dummynode);\n    othern = mainposition(t, key2tval(mp));\n    if (othern != mp) {  /* is colliding node out of its main position? */\n      /* yes; move colliding node into free position */\n      while (gnext(othern) != mp) othern = gnext(othern);  /* find previous */\n      gnext(othern) = n;  /* redo the chain with `n' in place of `mp' */\n      *n = *mp;  /* copy colliding node into free pos. (mp->next also goes) */\n      gnext(mp) = NULL;  /* now `mp' is free */\n      setnilvalue(gval(mp));\n    }\n    else {  /* colliding node is in its own main position */\n      /* new node will go into free position */\n      gnext(n) = gnext(mp);  /* chain new position */\n      gnext(mp) = n;\n      mp = n;\n    }\n  }\n  gkey(mp)->value = key->value; gkey(mp)->tt = key->tt;\n  luaC_barriert(L, t, key);\n  lua_assert(ttisnil(gval(mp)));\n  return gval(mp);\n}\n\n\n/*\n** search function for integers\n*/\nconst TValue *luaH_getnum (Table *t, int key) {\n  /* (1 <= key && key <= t->sizearray) */\n  if (cast(unsigned int, key-1) < cast(unsigned int, t->sizearray))\n    return &t->array[key-1];\n  else {\n    lua_Number nk = cast_num(key);\n    Node *n = hashnum(t, nk);\n    do {  /* check whether `key' is somewhere in the chain */\n      if (ttisnumber(gkey(n)) && luai_numeq(nvalue(gkey(n)), nk))\n        return gval(n);  /* that's it */\n      else n = gnext(n);\n    } while (n);\n    return luaO_nilobject;\n  }\n}\n\n\n/*\n** search function for strings\n*/\nconst TValue *luaH_getstr (Table *t, TString *key) {\n  Node *n = hashstr(t, key);\n  do {  /* check whether `key' is somewhere in the chain */\n    if (ttisstring(gkey(n)) && rawtsvalue(gkey(n)) == key)\n      return gval(n);  /* that's it */\n    else n = gnext(n);\n  } while (n);\n  return luaO_nilobject;\n}\n\n\n/*\n** main search function\n*/\nconst TValue *luaH_get (Table *t, const TValue *key) {\n  switch (ttype(key)) {\n    case LUA_TNIL: return luaO_nilobject;\n    case LUA_TSTRING: return luaH_getstr(t, rawtsvalue(key));\n    case LUA_TNUMBER: {\n      int k;\n      lua_Number n = nvalue(key);\n      lua_number2int(k, n);\n      if (luai_numeq(cast_num(k), nvalue(key))) /* index is int? */\n        return luaH_getnum(t, k);  /* use specialized version */\n      /* else go through */\n    }\n    default: {\n      Node *n = mainposition(t, key);\n      do {  /* check whether `key' is somewhere in the chain */\n        if (luaO_rawequalObj(key2tval(n), key))\n          return gval(n);  /* that's it */\n        else n = gnext(n);\n      } while (n);\n      return luaO_nilobject;\n    }\n  }\n}\n\n\nTValue *luaH_set (lua_State *L, Table *t, const TValue *key) {\n  const TValue *p = luaH_get(t, key);\n  t->flags = 0;\n  if (p != luaO_nilobject)\n    return cast(TValue *, p);\n  else {\n    if (ttisnil(key)) luaG_runerror(L, \"table index is nil\");\n    else if (ttisnumber(key) && luai_numisnan(nvalue(key)))\n      luaG_runerror(L, \"table index is NaN\");\n    return newkey(L, t, key);\n  }\n}\n\n\nTValue *luaH_setnum (lua_State *L, Table *t, int key) {\n  const TValue *p = luaH_getnum(t, key);\n  if (p != luaO_nilobject)\n    return cast(TValue *, p);\n  else {\n    TValue k;\n    setnvalue(&k, cast_num(key));\n    return newkey(L, t, &k);\n  }\n}\n\n\nTValue *luaH_setstr (lua_State *L, Table *t, TString *key) {\n  const TValue *p = luaH_getstr(t, key);\n  if (p != luaO_nilobject)\n    return cast(TValue *, p);\n  else {\n    TValue k;\n    setsvalue(L, &k, key);\n    return newkey(L, t, &k);\n  }\n}\n\n\nstatic int unbound_search (Table *t, unsigned int j) {\n  unsigned int i = j;  /* i is zero or a present index */\n  j++;\n  /* find `i' and `j' such that i is present and j is not */\n  while (!ttisnil(luaH_getnum(t, j))) {\n    i = j;\n    j *= 2;\n    if (j > cast(unsigned int, MAX_INT)) {  /* overflow? */\n      /* table was built with bad purposes: resort to linear search */\n      i = 1;\n      while (!ttisnil(luaH_getnum(t, i))) i++;\n      return i - 1;\n    }\n  }\n  /* now do a binary search between them */\n  while (j - i > 1) {\n    unsigned int m = (i+j)/2;\n    if (ttisnil(luaH_getnum(t, m))) j = m;\n    else i = m;\n  }\n  return i;\n}\n\n\n/*\n** Try to find a boundary in table `t'. A `boundary' is an integer index\n** such that t[i] is non-nil and t[i+1] is nil (and 0 if t[1] is nil).\n*/\nint luaH_getn (Table *t) {\n  unsigned int j = t->sizearray;\n  if (j > 0 && ttisnil(&t->array[j - 1])) {\n    /* there is a boundary in the array part: (binary) search for it */\n    unsigned int i = 0;\n    while (j - i > 1) {\n      unsigned int m = (i+j)/2;\n      if (ttisnil(&t->array[m - 1])) j = m;\n      else i = m;\n    }\n    return i;\n  }\n  /* else must find a boundary in hash part */\n  else if (t->node == dummynode)  /* hash part is empty? */\n    return j;  /* that is easy... */\n  else return unbound_search(t, j);\n}\n\n\n\n#if defined(LUA_DEBUG)\n\nNode *luaH_mainposition (const Table *t, const TValue *key) {\n  return mainposition(t, key);\n}\n\nint luaH_isdummy (Node *n) { return n == dummynode; }\n\n#endif\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.8/deps/lua/src/ltable.h",
    "content": "/*\n** $Id: ltable.h,v 2.10.1.1 2007/12/27 13:02:25 roberto Exp $\n** Lua tables (hash)\n** See Copyright Notice in lua.h\n*/\n\n#ifndef ltable_h\n#define ltable_h\n\n#include \"lobject.h\"\n\n\n#define gnode(t,i)\t(&(t)->node[i])\n#define gkey(n)\t\t(&(n)->i_key.nk)\n#define gval(n)\t\t(&(n)->i_val)\n#define gnext(n)\t((n)->i_key.nk.next)\n\n#define key2tval(n)\t(&(n)->i_key.tvk)\n\n\nLUAI_FUNC const TValue *luaH_getnum (Table *t, int key);\nLUAI_FUNC TValue *luaH_setnum (lua_State *L, Table *t, int key);\nLUAI_FUNC const TValue *luaH_getstr (Table *t, TString *key);\nLUAI_FUNC TValue *luaH_setstr (lua_State *L, Table *t, TString *key);\nLUAI_FUNC const TValue *luaH_get (Table *t, const TValue *key);\nLUAI_FUNC TValue *luaH_set (lua_State *L, Table *t, const TValue *key);\nLUAI_FUNC Table *luaH_new (lua_State *L, int narray, int lnhash);\nLUAI_FUNC void luaH_resizearray (lua_State *L, Table *t, int nasize);\nLUAI_FUNC void luaH_free (lua_State *L, Table *t);\nLUAI_FUNC int luaH_next (lua_State *L, Table *t, StkId key);\nLUAI_FUNC int luaH_getn (Table *t);\n\n\n#if defined(LUA_DEBUG)\nLUAI_FUNC Node *luaH_mainposition (const Table *t, const TValue *key);\nLUAI_FUNC int luaH_isdummy (Node *n);\n#endif\n\n\n#endif\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.8/deps/lua/src/ltablib.c",
    "content": "/*\n** $Id: ltablib.c,v 1.38.1.3 2008/02/14 16:46:58 roberto Exp $\n** Library for Table Manipulation\n** See Copyright Notice in lua.h\n*/\n\n\n#include <stddef.h>\n\n#define ltablib_c\n#define LUA_LIB\n\n#include \"lua.h\"\n\n#include \"lauxlib.h\"\n#include \"lualib.h\"\n\n\n#define aux_getn(L,n)\t(luaL_checktype(L, n, LUA_TTABLE), luaL_getn(L, n))\n\n\nstatic int foreachi (lua_State *L) {\n  int i;\n  int n = aux_getn(L, 1);\n  luaL_checktype(L, 2, LUA_TFUNCTION);\n  for (i=1; i <= n; i++) {\n    lua_pushvalue(L, 2);  /* function */\n    lua_pushinteger(L, i);  /* 1st argument */\n    lua_rawgeti(L, 1, i);  /* 2nd argument */\n    lua_call(L, 2, 1);\n    if (!lua_isnil(L, -1))\n      return 1;\n    lua_pop(L, 1);  /* remove nil result */\n  }\n  return 0;\n}\n\n\nstatic int foreach (lua_State *L) {\n  luaL_checktype(L, 1, LUA_TTABLE);\n  luaL_checktype(L, 2, LUA_TFUNCTION);\n  lua_pushnil(L);  /* first key */\n  while (lua_next(L, 1)) {\n    lua_pushvalue(L, 2);  /* function */\n    lua_pushvalue(L, -3);  /* key */\n    lua_pushvalue(L, -3);  /* value */\n    lua_call(L, 2, 1);\n    if (!lua_isnil(L, -1))\n      return 1;\n    lua_pop(L, 2);  /* remove value and result */\n  }\n  return 0;\n}\n\n\nstatic int maxn (lua_State *L) {\n  lua_Number max = 0;\n  luaL_checktype(L, 1, LUA_TTABLE);\n  lua_pushnil(L);  /* first key */\n  while (lua_next(L, 1)) {\n    lua_pop(L, 1);  /* remove value */\n    if (lua_type(L, -1) == LUA_TNUMBER) {\n      lua_Number v = lua_tonumber(L, -1);\n      if (v > max) max = v;\n    }\n  }\n  lua_pushnumber(L, max);\n  return 1;\n}\n\n\nstatic int getn (lua_State *L) {\n  lua_pushinteger(L, aux_getn(L, 1));\n  return 1;\n}\n\n\nstatic int setn (lua_State *L) {\n  luaL_checktype(L, 1, LUA_TTABLE);\n#ifndef luaL_setn\n  luaL_setn(L, 1, luaL_checkint(L, 2));\n#else\n  luaL_error(L, LUA_QL(\"setn\") \" is obsolete\");\n#endif\n  lua_pushvalue(L, 1);\n  return 1;\n}\n\n\nstatic int tinsert (lua_State *L) {\n  int e = aux_getn(L, 1) + 1;  /* first empty element */\n  int pos;  /* where to insert new element */\n  switch (lua_gettop(L)) {\n    case 2: {  /* called with only 2 arguments */\n      pos = e;  /* insert new element at the end */\n      break;\n    }\n    case 3: {\n      int i;\n      pos = luaL_checkint(L, 2);  /* 2nd argument is the position */\n      if (pos > e) e = pos;  /* `grow' array if necessary */\n      for (i = e; i > pos; i--) {  /* move up elements */\n        lua_rawgeti(L, 1, i-1);\n        lua_rawseti(L, 1, i);  /* t[i] = t[i-1] */\n      }\n      break;\n    }\n    default: {\n      return luaL_error(L, \"wrong number of arguments to \" LUA_QL(\"insert\"));\n    }\n  }\n  luaL_setn(L, 1, e);  /* new size */\n  lua_rawseti(L, 1, pos);  /* t[pos] = v */\n  return 0;\n}\n\n\nstatic int tremove (lua_State *L) {\n  int e = aux_getn(L, 1);\n  int pos = luaL_optint(L, 2, e);\n  if (!(1 <= pos && pos <= e))  /* position is outside bounds? */\n   return 0;  /* nothing to remove */\n  luaL_setn(L, 1, e - 1);  /* t.n = n-1 */\n  lua_rawgeti(L, 1, pos);  /* result = t[pos] */\n  for ( ;pos<e; pos++) {\n    lua_rawgeti(L, 1, pos+1);\n    lua_rawseti(L, 1, pos);  /* t[pos] = t[pos+1] */\n  }\n  lua_pushnil(L);\n  lua_rawseti(L, 1, e);  /* t[e] = nil */\n  return 1;\n}\n\n\nstatic void addfield (lua_State *L, luaL_Buffer *b, int i) {\n  lua_rawgeti(L, 1, i);\n  if (!lua_isstring(L, -1))\n    luaL_error(L, \"invalid value (%s) at index %d in table for \"\n                  LUA_QL(\"concat\"), luaL_typename(L, -1), i);\n    luaL_addvalue(b);\n}\n\n\nstatic int tconcat (lua_State *L) {\n  luaL_Buffer b;\n  size_t lsep;\n  int i, last;\n  const char *sep = luaL_optlstring(L, 2, \"\", &lsep);\n  luaL_checktype(L, 1, LUA_TTABLE);\n  i = luaL_optint(L, 3, 1);\n  last = luaL_opt(L, luaL_checkint, 4, luaL_getn(L, 1));\n  luaL_buffinit(L, &b);\n  for (; i < last; i++) {\n    addfield(L, &b, i);\n    luaL_addlstring(&b, sep, lsep);\n  }\n  if (i == last)  /* add last value (if interval was not empty) */\n    addfield(L, &b, i);\n  luaL_pushresult(&b);\n  return 1;\n}\n\n\n\n/*\n** {======================================================\n** Quicksort\n** (based on `Algorithms in MODULA-3', Robert Sedgewick;\n**  Addison-Wesley, 1993.)\n*/\n\n\nstatic void set2 (lua_State *L, int i, int j) {\n  lua_rawseti(L, 1, i);\n  lua_rawseti(L, 1, j);\n}\n\nstatic int sort_comp (lua_State *L, int a, int b) {\n  if (!lua_isnil(L, 2)) {  /* function? */\n    int res;\n    lua_pushvalue(L, 2);\n    lua_pushvalue(L, a-1);  /* -1 to compensate function */\n    lua_pushvalue(L, b-2);  /* -2 to compensate function and `a' */\n    lua_call(L, 2, 1);\n    res = lua_toboolean(L, -1);\n    lua_pop(L, 1);\n    return res;\n  }\n  else  /* a < b? */\n    return lua_lessthan(L, a, b);\n}\n\nstatic void auxsort (lua_State *L, int l, int u) {\n  while (l < u) {  /* for tail recursion */\n    int i, j;\n    /* sort elements a[l], a[(l+u)/2] and a[u] */\n    lua_rawgeti(L, 1, l);\n    lua_rawgeti(L, 1, u);\n    if (sort_comp(L, -1, -2))  /* a[u] < a[l]? */\n      set2(L, l, u);  /* swap a[l] - a[u] */\n    else\n      lua_pop(L, 2);\n    if (u-l == 1) break;  /* only 2 elements */\n    i = (l+u)/2;\n    lua_rawgeti(L, 1, i);\n    lua_rawgeti(L, 1, l);\n    if (sort_comp(L, -2, -1))  /* a[i]<a[l]? */\n      set2(L, i, l);\n    else {\n      lua_pop(L, 1);  /* remove a[l] */\n      lua_rawgeti(L, 1, u);\n      if (sort_comp(L, -1, -2))  /* a[u]<a[i]? */\n        set2(L, i, u);\n      else\n        lua_pop(L, 2);\n    }\n    if (u-l == 2) break;  /* only 3 elements */\n    lua_rawgeti(L, 1, i);  /* Pivot */\n    lua_pushvalue(L, -1);\n    lua_rawgeti(L, 1, u-1);\n    set2(L, i, u-1);\n    /* a[l] <= P == a[u-1] <= a[u], only need to sort from l+1 to u-2 */\n    i = l; j = u-1;\n    for (;;) {  /* invariant: a[l..i] <= P <= a[j..u] */\n      /* repeat ++i until a[i] >= P */\n      while (lua_rawgeti(L, 1, ++i), sort_comp(L, -1, -2)) {\n        if (i>u) luaL_error(L, \"invalid order function for sorting\");\n        lua_pop(L, 1);  /* remove a[i] */\n      }\n      /* repeat --j until a[j] <= P */\n      while (lua_rawgeti(L, 1, --j), sort_comp(L, -3, -1)) {\n        if (j<l) luaL_error(L, \"invalid order function for sorting\");\n        lua_pop(L, 1);  /* remove a[j] */\n      }\n      if (j<i) {\n        lua_pop(L, 3);  /* pop pivot, a[i], a[j] */\n        break;\n      }\n      set2(L, i, j);\n    }\n    lua_rawgeti(L, 1, u-1);\n    lua_rawgeti(L, 1, i);\n    set2(L, u-1, i);  /* swap pivot (a[u-1]) with a[i] */\n    /* a[l..i-1] <= a[i] == P <= a[i+1..u] */\n    /* adjust so that smaller half is in [j..i] and larger one in [l..u] */\n    if (i-l < u-i) {\n      j=l; i=i-1; l=i+2;\n    }\n    else {\n      j=i+1; i=u; u=j-2;\n    }\n    auxsort(L, j, i);  /* call recursively the smaller one */\n  }  /* repeat the routine for the larger one */\n}\n\nstatic int sort (lua_State *L) {\n  int n = aux_getn(L, 1);\n  luaL_checkstack(L, 40, \"\");  /* assume array is smaller than 2^40 */\n  if (!lua_isnoneornil(L, 2))  /* is there a 2nd argument? */\n    luaL_checktype(L, 2, LUA_TFUNCTION);\n  lua_settop(L, 2);  /* make sure there is two arguments */\n  auxsort(L, 1, n);\n  return 0;\n}\n\n/* }====================================================== */\n\n\nstatic const luaL_Reg tab_funcs[] = {\n  {\"concat\", tconcat},\n  {\"foreach\", foreach},\n  {\"foreachi\", foreachi},\n  {\"getn\", getn},\n  {\"maxn\", maxn},\n  {\"insert\", tinsert},\n  {\"remove\", tremove},\n  {\"setn\", setn},\n  {\"sort\", sort},\n  {NULL, NULL}\n};\n\n\nLUALIB_API int luaopen_table (lua_State *L) {\n  luaL_register(L, LUA_TABLIBNAME, tab_funcs);\n  return 1;\n}\n\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.8/deps/lua/src/ltm.c",
    "content": "/*\n** $Id: ltm.c,v 2.8.1.1 2007/12/27 13:02:25 roberto Exp $\n** Tag methods\n** See Copyright Notice in lua.h\n*/\n\n\n#include <string.h>\n\n#define ltm_c\n#define LUA_CORE\n\n#include \"lua.h\"\n\n#include \"lobject.h\"\n#include \"lstate.h\"\n#include \"lstring.h\"\n#include \"ltable.h\"\n#include \"ltm.h\"\n\n\n\nconst char *const luaT_typenames[] = {\n  \"nil\", \"boolean\", \"userdata\", \"number\",\n  \"string\", \"table\", \"function\", \"userdata\", \"thread\",\n  \"proto\", \"upval\"\n};\n\n\nvoid luaT_init (lua_State *L) {\n  static const char *const luaT_eventname[] = {  /* ORDER TM */\n    \"__index\", \"__newindex\",\n    \"__gc\", \"__mode\", \"__eq\",\n    \"__add\", \"__sub\", \"__mul\", \"__div\", \"__mod\",\n    \"__pow\", \"__unm\", \"__len\", \"__lt\", \"__le\",\n    \"__concat\", \"__call\"\n  };\n  int i;\n  for (i=0; i<TM_N; i++) {\n    G(L)->tmname[i] = luaS_new(L, luaT_eventname[i]);\n    luaS_fix(G(L)->tmname[i]);  /* never collect these names */\n  }\n}\n\n\n/*\n** function to be used with macro \"fasttm\": optimized for absence of\n** tag methods\n*/\nconst TValue *luaT_gettm (Table *events, TMS event, TString *ename) {\n  const TValue *tm = luaH_getstr(events, ename);\n  lua_assert(event <= TM_EQ);\n  if (ttisnil(tm)) {  /* no tag method? */\n    events->flags |= cast_byte(1u<<event);  /* cache this fact */\n    return NULL;\n  }\n  else return tm;\n}\n\n\nconst TValue *luaT_gettmbyobj (lua_State *L, const TValue *o, TMS event) {\n  Table *mt;\n  switch (ttype(o)) {\n    case LUA_TTABLE:\n      mt = hvalue(o)->metatable;\n      break;\n    case LUA_TUSERDATA:\n      mt = uvalue(o)->metatable;\n      break;\n    default:\n      mt = G(L)->mt[ttype(o)];\n  }\n  return (mt ? luaH_getstr(mt, G(L)->tmname[event]) : luaO_nilobject);\n}\n\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.8/deps/lua/src/ltm.h",
    "content": "/*\n** $Id: ltm.h,v 2.6.1.1 2007/12/27 13:02:25 roberto Exp $\n** Tag methods\n** See Copyright Notice in lua.h\n*/\n\n#ifndef ltm_h\n#define ltm_h\n\n\n#include \"lobject.h\"\n\n\n/*\n* WARNING: if you change the order of this enumeration,\n* grep \"ORDER TM\"\n*/\ntypedef enum {\n  TM_INDEX,\n  TM_NEWINDEX,\n  TM_GC,\n  TM_MODE,\n  TM_EQ,  /* last tag method with `fast' access */\n  TM_ADD,\n  TM_SUB,\n  TM_MUL,\n  TM_DIV,\n  TM_MOD,\n  TM_POW,\n  TM_UNM,\n  TM_LEN,\n  TM_LT,\n  TM_LE,\n  TM_CONCAT,\n  TM_CALL,\n  TM_N\t\t/* number of elements in the enum */\n} TMS;\n\n\n\n#define gfasttm(g,et,e) ((et) == NULL ? NULL : \\\n  ((et)->flags & (1u<<(e))) ? NULL : luaT_gettm(et, e, (g)->tmname[e]))\n\n#define fasttm(l,et,e)\tgfasttm(G(l), et, e)\n\nLUAI_DATA const char *const luaT_typenames[];\n\n\nLUAI_FUNC const TValue *luaT_gettm (Table *events, TMS event, TString *ename);\nLUAI_FUNC const TValue *luaT_gettmbyobj (lua_State *L, const TValue *o,\n                                                       TMS event);\nLUAI_FUNC void luaT_init (lua_State *L);\n\n#endif\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.8/deps/lua/src/lua.c",
    "content": "/*\n** $Id: lua.c,v 1.160.1.2 2007/12/28 15:32:23 roberto Exp $\n** Lua stand-alone interpreter\n** See Copyright Notice in lua.h\n*/\n\n\n#include <signal.h>\n#include <stdio.h>\n#include <stdlib.h>\n#include <string.h>\n\n#define lua_c\n\n#include \"lua.h\"\n\n#include \"lauxlib.h\"\n#include \"lualib.h\"\n\n\n\nstatic lua_State *globalL = NULL;\n\nstatic const char *progname = LUA_PROGNAME;\n\n\n\nstatic void lstop (lua_State *L, lua_Debug *ar) {\n  (void)ar;  /* unused arg. */\n  lua_sethook(L, NULL, 0, 0);\n  luaL_error(L, \"interrupted!\");\n}\n\n\nstatic void laction (int i) {\n  signal(i, SIG_DFL); /* if another SIGINT happens before lstop,\n                              terminate process (default action) */\n  lua_sethook(globalL, lstop, LUA_MASKCALL | LUA_MASKRET | LUA_MASKCOUNT, 1);\n}\n\n\nstatic void print_usage (void) {\n  fprintf(stderr,\n  \"usage: %s [options] [script [args]].\\n\"\n  \"Available options are:\\n\"\n  \"  -e stat  execute string \" LUA_QL(\"stat\") \"\\n\"\n  \"  -l name  require library \" LUA_QL(\"name\") \"\\n\"\n  \"  -i       enter interactive mode after executing \" LUA_QL(\"script\") \"\\n\"\n  \"  -v       show version information\\n\"\n  \"  --       stop handling options\\n\"\n  \"  -        execute stdin and stop handling options\\n\"\n  ,\n  progname);\n  fflush(stderr);\n}\n\n\nstatic void l_message (const char *pname, const char *msg) {\n  if (pname) fprintf(stderr, \"%s: \", pname);\n  fprintf(stderr, \"%s\\n\", msg);\n  fflush(stderr);\n}\n\n\nstatic int report (lua_State *L, int status) {\n  if (status && !lua_isnil(L, -1)) {\n    const char *msg = lua_tostring(L, -1);\n    if (msg == NULL) msg = \"(error object is not a string)\";\n    l_message(progname, msg);\n    lua_pop(L, 1);\n  }\n  return status;\n}\n\n\nstatic int traceback (lua_State *L) {\n  if (!lua_isstring(L, 1))  /* 'message' not a string? */\n    return 1;  /* keep it intact */\n  lua_getfield(L, LUA_GLOBALSINDEX, \"debug\");\n  if (!lua_istable(L, -1)) {\n    lua_pop(L, 1);\n    return 1;\n  }\n  lua_getfield(L, -1, \"traceback\");\n  if (!lua_isfunction(L, -1)) {\n    lua_pop(L, 2);\n    return 1;\n  }\n  lua_pushvalue(L, 1);  /* pass error message */\n  lua_pushinteger(L, 2);  /* skip this function and traceback */\n  lua_call(L, 2, 1);  /* call debug.traceback */\n  return 1;\n}\n\n\nstatic int docall (lua_State *L, int narg, int clear) {\n  int status;\n  int base = lua_gettop(L) - narg;  /* function index */\n  lua_pushcfunction(L, traceback);  /* push traceback function */\n  lua_insert(L, base);  /* put it under chunk and args */\n  signal(SIGINT, laction);\n  status = lua_pcall(L, narg, (clear ? 0 : LUA_MULTRET), base);\n  signal(SIGINT, SIG_DFL);\n  lua_remove(L, base);  /* remove traceback function */\n  /* force a complete garbage collection in case of errors */\n  if (status != 0) lua_gc(L, LUA_GCCOLLECT, 0);\n  return status;\n}\n\n\nstatic void print_version (void) {\n  l_message(NULL, LUA_RELEASE \"  \" LUA_COPYRIGHT);\n}\n\n\nstatic int getargs (lua_State *L, char **argv, int n) {\n  int narg;\n  int i;\n  int argc = 0;\n  while (argv[argc]) argc++;  /* count total number of arguments */\n  narg = argc - (n + 1);  /* number of arguments to the script */\n  luaL_checkstack(L, narg + 3, \"too many arguments to script\");\n  for (i=n+1; i < argc; i++)\n    lua_pushstring(L, argv[i]);\n  lua_createtable(L, narg, n + 1);\n  for (i=0; i < argc; i++) {\n    lua_pushstring(L, argv[i]);\n    lua_rawseti(L, -2, i - n);\n  }\n  return narg;\n}\n\n\nstatic int dofile (lua_State *L, const char *name) {\n  int status = luaL_loadfile(L, name) || docall(L, 0, 1);\n  return report(L, status);\n}\n\n\nstatic int dostring (lua_State *L, const char *s, const char *name) {\n  int status = luaL_loadbuffer(L, s, strlen(s), name) || docall(L, 0, 1);\n  return report(L, status);\n}\n\n\nstatic int dolibrary (lua_State *L, const char *name) {\n  lua_getglobal(L, \"require\");\n  lua_pushstring(L, name);\n  return report(L, docall(L, 1, 1));\n}\n\n\nstatic const char *get_prompt (lua_State *L, int firstline) {\n  const char *p;\n  lua_getfield(L, LUA_GLOBALSINDEX, firstline ? \"_PROMPT\" : \"_PROMPT2\");\n  p = lua_tostring(L, -1);\n  if (p == NULL) p = (firstline ? LUA_PROMPT : LUA_PROMPT2);\n  lua_pop(L, 1);  /* remove global */\n  return p;\n}\n\n\nstatic int incomplete (lua_State *L, int status) {\n  if (status == LUA_ERRSYNTAX) {\n    size_t lmsg;\n    const char *msg = lua_tolstring(L, -1, &lmsg);\n    const char *tp = msg + lmsg - (sizeof(LUA_QL(\"<eof>\")) - 1);\n    if (strstr(msg, LUA_QL(\"<eof>\")) == tp) {\n      lua_pop(L, 1);\n      return 1;\n    }\n  }\n  return 0;  /* else... */\n}\n\n\nstatic int pushline (lua_State *L, int firstline) {\n  char buffer[LUA_MAXINPUT];\n  char *b = buffer;\n  size_t l;\n  const char *prmt = get_prompt(L, firstline);\n  if (lua_readline(L, b, prmt) == 0)\n    return 0;  /* no input */\n  l = strlen(b);\n  if (l > 0 && b[l-1] == '\\n')  /* line ends with newline? */\n    b[l-1] = '\\0';  /* remove it */\n  if (firstline && b[0] == '=')  /* first line starts with `=' ? */\n    lua_pushfstring(L, \"return %s\", b+1);  /* change it to `return' */\n  else\n    lua_pushstring(L, b);\n  lua_freeline(L, b);\n  return 1;\n}\n\n\nstatic int loadline (lua_State *L) {\n  int status;\n  lua_settop(L, 0);\n  if (!pushline(L, 1))\n    return -1;  /* no input */\n  for (;;) {  /* repeat until gets a complete line */\n    status = luaL_loadbuffer(L, lua_tostring(L, 1), lua_strlen(L, 1), \"=stdin\");\n    if (!incomplete(L, status)) break;  /* cannot try to add lines? */\n    if (!pushline(L, 0))  /* no more input? */\n      return -1;\n    lua_pushliteral(L, \"\\n\");  /* add a new line... */\n    lua_insert(L, -2);  /* ...between the two lines */\n    lua_concat(L, 3);  /* join them */\n  }\n  lua_saveline(L, 1);\n  lua_remove(L, 1);  /* remove line */\n  return status;\n}\n\n\nstatic void dotty (lua_State *L) {\n  int status;\n  const char *oldprogname = progname;\n  progname = NULL;\n  while ((status = loadline(L)) != -1) {\n    if (status == 0) status = docall(L, 0, 0);\n    report(L, status);\n    if (status == 0 && lua_gettop(L) > 0) {  /* any result to print? */\n      lua_getglobal(L, \"print\");\n      lua_insert(L, 1);\n      if (lua_pcall(L, lua_gettop(L)-1, 0, 0) != 0)\n        l_message(progname, lua_pushfstring(L,\n                               \"error calling \" LUA_QL(\"print\") \" (%s)\",\n                               lua_tostring(L, -1)));\n    }\n  }\n  lua_settop(L, 0);  /* clear stack */\n  fputs(\"\\n\", stdout);\n  fflush(stdout);\n  progname = oldprogname;\n}\n\n\nstatic int handle_script (lua_State *L, char **argv, int n) {\n  int status;\n  const char *fname;\n  int narg = getargs(L, argv, n);  /* collect arguments */\n  lua_setglobal(L, \"arg\");\n  fname = argv[n];\n  if (strcmp(fname, \"-\") == 0 && strcmp(argv[n-1], \"--\") != 0) \n    fname = NULL;  /* stdin */\n  status = luaL_loadfile(L, fname);\n  lua_insert(L, -(narg+1));\n  if (status == 0)\n    status = docall(L, narg, 0);\n  else\n    lua_pop(L, narg);      \n  return report(L, status);\n}\n\n\n/* check that argument has no extra characters at the end */\n#define notail(x)\t{if ((x)[2] != '\\0') return -1;}\n\n\nstatic int collectargs (char **argv, int *pi, int *pv, int *pe) {\n  int i;\n  for (i = 1; argv[i] != NULL; i++) {\n    if (argv[i][0] != '-')  /* not an option? */\n        return i;\n    switch (argv[i][1]) {  /* option */\n      case '-':\n        notail(argv[i]);\n        return (argv[i+1] != NULL ? i+1 : 0);\n      case '\\0':\n        return i;\n      case 'i':\n        notail(argv[i]);\n        *pi = 1;  /* go through */\n      case 'v':\n        notail(argv[i]);\n        *pv = 1;\n        break;\n      case 'e':\n        *pe = 1;  /* go through */\n      case 'l':\n        if (argv[i][2] == '\\0') {\n          i++;\n          if (argv[i] == NULL) return -1;\n        }\n        break;\n      default: return -1;  /* invalid option */\n    }\n  }\n  return 0;\n}\n\n\nstatic int runargs (lua_State *L, char **argv, int n) {\n  int i;\n  for (i = 1; i < n; i++) {\n    if (argv[i] == NULL) continue;\n    lua_assert(argv[i][0] == '-');\n    switch (argv[i][1]) {  /* option */\n      case 'e': {\n        const char *chunk = argv[i] + 2;\n        if (*chunk == '\\0') chunk = argv[++i];\n        lua_assert(chunk != NULL);\n        if (dostring(L, chunk, \"=(command line)\") != 0)\n          return 1;\n        break;\n      }\n      case 'l': {\n        const char *filename = argv[i] + 2;\n        if (*filename == '\\0') filename = argv[++i];\n        lua_assert(filename != NULL);\n        if (dolibrary(L, filename))\n          return 1;  /* stop if file fails */\n        break;\n      }\n      default: break;\n    }\n  }\n  return 0;\n}\n\n\nstatic int handle_luainit (lua_State *L) {\n  const char *init = getenv(LUA_INIT);\n  if (init == NULL) return 0;  /* status OK */\n  else if (init[0] == '@')\n    return dofile(L, init+1);\n  else\n    return dostring(L, init, \"=\" LUA_INIT);\n}\n\n\nstruct Smain {\n  int argc;\n  char **argv;\n  int status;\n};\n\n\nstatic int pmain (lua_State *L) {\n  struct Smain *s = (struct Smain *)lua_touserdata(L, 1);\n  char **argv = s->argv;\n  int script;\n  int has_i = 0, has_v = 0, has_e = 0;\n  globalL = L;\n  if (argv[0] && argv[0][0]) progname = argv[0];\n  lua_gc(L, LUA_GCSTOP, 0);  /* stop collector during initialization */\n  luaL_openlibs(L);  /* open libraries */\n  lua_gc(L, LUA_GCRESTART, 0);\n  s->status = handle_luainit(L);\n  if (s->status != 0) return 0;\n  script = collectargs(argv, &has_i, &has_v, &has_e);\n  if (script < 0) {  /* invalid args? */\n    print_usage();\n    s->status = 1;\n    return 0;\n  }\n  if (has_v) print_version();\n  s->status = runargs(L, argv, (script > 0) ? script : s->argc);\n  if (s->status != 0) return 0;\n  if (script)\n    s->status = handle_script(L, argv, script);\n  if (s->status != 0) return 0;\n  if (has_i)\n    dotty(L);\n  else if (script == 0 && !has_e && !has_v) {\n    if (lua_stdin_is_tty()) {\n      print_version();\n      dotty(L);\n    }\n    else dofile(L, NULL);  /* executes stdin as a file */\n  }\n  return 0;\n}\n\n\nint main (int argc, char **argv) {\n  int status;\n  struct Smain s;\n  lua_State *L = lua_open();  /* create state */\n  if (L == NULL) {\n    l_message(argv[0], \"cannot create state: not enough memory\");\n    return EXIT_FAILURE;\n  }\n  s.argc = argc;\n  s.argv = argv;\n  status = lua_cpcall(L, &pmain, &s);\n  report(L, status);\n  lua_close(L);\n  return (status || s.status) ? EXIT_FAILURE : EXIT_SUCCESS;\n}\n\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.8/deps/lua/src/lua.h",
    "content": "/*\n** $Id: lua.h,v 1.218.1.7 2012/01/13 20:36:20 roberto Exp $\n** Lua - An Extensible Extension Language\n** Lua.org, PUC-Rio, Brazil (http://www.lua.org)\n** See Copyright Notice at the end of this file\n*/\n\n\n#ifndef lua_h\n#define lua_h\n\n#include <stdarg.h>\n#include <stddef.h>\n\n\n#include \"luaconf.h\"\n\n\n#define LUA_VERSION\t\"Lua 5.1\"\n#define LUA_RELEASE\t\"Lua 5.1.5\"\n#define LUA_VERSION_NUM\t501\n#define LUA_COPYRIGHT\t\"Copyright (C) 1994-2012 Lua.org, PUC-Rio\"\n#define LUA_AUTHORS \t\"R. Ierusalimschy, L. H. de Figueiredo & W. Celes\"\n\n\n/* mark for precompiled code (`<esc>Lua') */\n#define\tLUA_SIGNATURE\t\"\\033Lua\"\n\n/* option for multiple returns in `lua_pcall' and `lua_call' */\n#define LUA_MULTRET\t(-1)\n\n\n/*\n** pseudo-indices\n*/\n#define LUA_REGISTRYINDEX\t(-10000)\n#define LUA_ENVIRONINDEX\t(-10001)\n#define LUA_GLOBALSINDEX\t(-10002)\n#define lua_upvalueindex(i)\t(LUA_GLOBALSINDEX-(i))\n\n\n/* thread status; 0 is OK */\n#define LUA_YIELD\t1\n#define LUA_ERRRUN\t2\n#define LUA_ERRSYNTAX\t3\n#define LUA_ERRMEM\t4\n#define LUA_ERRERR\t5\n\n\ntypedef struct lua_State lua_State;\n\ntypedef int (*lua_CFunction) (lua_State *L);\n\n\n/*\n** functions that read/write blocks when loading/dumping Lua chunks\n*/\ntypedef const char * (*lua_Reader) (lua_State *L, void *ud, size_t *sz);\n\ntypedef int (*lua_Writer) (lua_State *L, const void* p, size_t sz, void* ud);\n\n\n/*\n** prototype for memory-allocation functions\n*/\ntypedef void * (*lua_Alloc) (void *ud, void *ptr, size_t osize, size_t nsize);\n\n\n/*\n** basic types\n*/\n#define LUA_TNONE\t\t(-1)\n\n#define LUA_TNIL\t\t0\n#define LUA_TBOOLEAN\t\t1\n#define LUA_TLIGHTUSERDATA\t2\n#define LUA_TNUMBER\t\t3\n#define LUA_TSTRING\t\t4\n#define LUA_TTABLE\t\t5\n#define LUA_TFUNCTION\t\t6\n#define LUA_TUSERDATA\t\t7\n#define LUA_TTHREAD\t\t8\n\n\n\n/* minimum Lua stack available to a C function */\n#define LUA_MINSTACK\t20\n\n\n/*\n** generic extra include file\n*/\n#if defined(LUA_USER_H)\n#include LUA_USER_H\n#endif\n\n\n/* type of numbers in Lua */\ntypedef LUA_NUMBER lua_Number;\n\n\n/* type for integer functions */\ntypedef LUA_INTEGER lua_Integer;\n\n\n\n/*\n** state manipulation\n*/\nLUA_API lua_State *(lua_newstate) (lua_Alloc f, void *ud);\nLUA_API void       (lua_close) (lua_State *L);\nLUA_API lua_State *(lua_newthread) (lua_State *L);\n\nLUA_API lua_CFunction (lua_atpanic) (lua_State *L, lua_CFunction panicf);\n\n\n/*\n** basic stack manipulation\n*/\nLUA_API int   (lua_gettop) (lua_State *L);\nLUA_API void  (lua_settop) (lua_State *L, int idx);\nLUA_API void  (lua_pushvalue) (lua_State *L, int idx);\nLUA_API void  (lua_remove) (lua_State *L, int idx);\nLUA_API void  (lua_insert) (lua_State *L, int idx);\nLUA_API void  (lua_replace) (lua_State *L, int idx);\nLUA_API int   (lua_checkstack) (lua_State *L, int sz);\n\nLUA_API void  (lua_xmove) (lua_State *from, lua_State *to, int n);\n\n\n/*\n** access functions (stack -> C)\n*/\n\nLUA_API int             (lua_isnumber) (lua_State *L, int idx);\nLUA_API int             (lua_isstring) (lua_State *L, int idx);\nLUA_API int             (lua_iscfunction) (lua_State *L, int idx);\nLUA_API int             (lua_isuserdata) (lua_State *L, int idx);\nLUA_API int             (lua_type) (lua_State *L, int idx);\nLUA_API const char     *(lua_typename) (lua_State *L, int tp);\n\nLUA_API int            (lua_equal) (lua_State *L, int idx1, int idx2);\nLUA_API int            (lua_rawequal) (lua_State *L, int idx1, int idx2);\nLUA_API int            (lua_lessthan) (lua_State *L, int idx1, int idx2);\n\nLUA_API lua_Number      (lua_tonumber) (lua_State *L, int idx);\nLUA_API lua_Integer     (lua_tointeger) (lua_State *L, int idx);\nLUA_API int             (lua_toboolean) (lua_State *L, int idx);\nLUA_API const char     *(lua_tolstring) (lua_State *L, int idx, size_t *len);\nLUA_API size_t          (lua_objlen) (lua_State *L, int idx);\nLUA_API lua_CFunction   (lua_tocfunction) (lua_State *L, int idx);\nLUA_API void\t       *(lua_touserdata) (lua_State *L, int idx);\nLUA_API lua_State      *(lua_tothread) (lua_State *L, int idx);\nLUA_API const void     *(lua_topointer) (lua_State *L, int idx);\n\n\n/*\n** push functions (C -> stack)\n*/\nLUA_API void  (lua_pushnil) (lua_State *L);\nLUA_API void  (lua_pushnumber) (lua_State *L, lua_Number n);\nLUA_API void  (lua_pushinteger) (lua_State *L, lua_Integer n);\nLUA_API void  (lua_pushlstring) (lua_State *L, const char *s, size_t l);\nLUA_API void  (lua_pushstring) (lua_State *L, const char *s);\nLUA_API const char *(lua_pushvfstring) (lua_State *L, const char *fmt,\n                                                      va_list argp);\nLUA_API const char *(lua_pushfstring) (lua_State *L, const char *fmt, ...);\nLUA_API void  (lua_pushcclosure) (lua_State *L, lua_CFunction fn, int n);\nLUA_API void  (lua_pushboolean) (lua_State *L, int b);\nLUA_API void  (lua_pushlightuserdata) (lua_State *L, void *p);\nLUA_API int   (lua_pushthread) (lua_State *L);\n\n\n/*\n** get functions (Lua -> stack)\n*/\nLUA_API void  (lua_gettable) (lua_State *L, int idx);\nLUA_API void  (lua_getfield) (lua_State *L, int idx, const char *k);\nLUA_API void  (lua_rawget) (lua_State *L, int idx);\nLUA_API void  (lua_rawgeti) (lua_State *L, int idx, int n);\nLUA_API void  (lua_createtable) (lua_State *L, int narr, int nrec);\nLUA_API void *(lua_newuserdata) (lua_State *L, size_t sz);\nLUA_API int   (lua_getmetatable) (lua_State *L, int objindex);\nLUA_API void  (lua_getfenv) (lua_State *L, int idx);\n\n\n/*\n** set functions (stack -> Lua)\n*/\nLUA_API void  (lua_settable) (lua_State *L, int idx);\nLUA_API void  (lua_setfield) (lua_State *L, int idx, const char *k);\nLUA_API void  (lua_rawset) (lua_State *L, int idx);\nLUA_API void  (lua_rawseti) (lua_State *L, int idx, int n);\nLUA_API int   (lua_setmetatable) (lua_State *L, int objindex);\nLUA_API int   (lua_setfenv) (lua_State *L, int idx);\n\n\n/*\n** `load' and `call' functions (load and run Lua code)\n*/\nLUA_API void  (lua_call) (lua_State *L, int nargs, int nresults);\nLUA_API int   (lua_pcall) (lua_State *L, int nargs, int nresults, int errfunc);\nLUA_API int   (lua_cpcall) (lua_State *L, lua_CFunction func, void *ud);\nLUA_API int   (lua_load) (lua_State *L, lua_Reader reader, void *dt,\n                                        const char *chunkname);\n\nLUA_API int (lua_dump) (lua_State *L, lua_Writer writer, void *data);\n\n\n/*\n** coroutine functions\n*/\nLUA_API int  (lua_yield) (lua_State *L, int nresults);\nLUA_API int  (lua_resume) (lua_State *L, int narg);\nLUA_API int  (lua_status) (lua_State *L);\n\n/*\n** garbage-collection function and options\n*/\n\n#define LUA_GCSTOP\t\t0\n#define LUA_GCRESTART\t\t1\n#define LUA_GCCOLLECT\t\t2\n#define LUA_GCCOUNT\t\t3\n#define LUA_GCCOUNTB\t\t4\n#define LUA_GCSTEP\t\t5\n#define LUA_GCSETPAUSE\t\t6\n#define LUA_GCSETSTEPMUL\t7\n\nLUA_API int (lua_gc) (lua_State *L, int what, int data);\n\n\n/*\n** miscellaneous functions\n*/\n\nLUA_API int   (lua_error) (lua_State *L);\n\nLUA_API int   (lua_next) (lua_State *L, int idx);\n\nLUA_API void  (lua_concat) (lua_State *L, int n);\n\nLUA_API lua_Alloc (lua_getallocf) (lua_State *L, void **ud);\nLUA_API void lua_setallocf (lua_State *L, lua_Alloc f, void *ud);\n\n\n\n/* \n** ===============================================================\n** some useful macros\n** ===============================================================\n*/\n\n#define lua_pop(L,n)\t\tlua_settop(L, -(n)-1)\n\n#define lua_newtable(L)\t\tlua_createtable(L, 0, 0)\n\n#define lua_register(L,n,f) (lua_pushcfunction(L, (f)), lua_setglobal(L, (n)))\n\n#define lua_pushcfunction(L,f)\tlua_pushcclosure(L, (f), 0)\n\n#define lua_strlen(L,i)\t\tlua_objlen(L, (i))\n\n#define lua_isfunction(L,n)\t(lua_type(L, (n)) == LUA_TFUNCTION)\n#define lua_istable(L,n)\t(lua_type(L, (n)) == LUA_TTABLE)\n#define lua_islightuserdata(L,n)\t(lua_type(L, (n)) == LUA_TLIGHTUSERDATA)\n#define lua_isnil(L,n)\t\t(lua_type(L, (n)) == LUA_TNIL)\n#define lua_isboolean(L,n)\t(lua_type(L, (n)) == LUA_TBOOLEAN)\n#define lua_isthread(L,n)\t(lua_type(L, (n)) == LUA_TTHREAD)\n#define lua_isnone(L,n)\t\t(lua_type(L, (n)) == LUA_TNONE)\n#define lua_isnoneornil(L, n)\t(lua_type(L, (n)) <= 0)\n\n#define lua_pushliteral(L, s)\t\\\n\tlua_pushlstring(L, \"\" s, (sizeof(s)/sizeof(char))-1)\n\n#define lua_setglobal(L,s)\tlua_setfield(L, LUA_GLOBALSINDEX, (s))\n#define lua_getglobal(L,s)\tlua_getfield(L, LUA_GLOBALSINDEX, (s))\n\n#define lua_tostring(L,i)\tlua_tolstring(L, (i), NULL)\n\n\n\n/*\n** compatibility macros and functions\n*/\n\n#define lua_open()\tluaL_newstate()\n\n#define lua_getregistry(L)\tlua_pushvalue(L, LUA_REGISTRYINDEX)\n\n#define lua_getgccount(L)\tlua_gc(L, LUA_GCCOUNT, 0)\n\n#define lua_Chunkreader\t\tlua_Reader\n#define lua_Chunkwriter\t\tlua_Writer\n\n\n/* hack */\nLUA_API void lua_setlevel\t(lua_State *from, lua_State *to);\n\n\n/*\n** {======================================================================\n** Debug API\n** =======================================================================\n*/\n\n\n/*\n** Event codes\n*/\n#define LUA_HOOKCALL\t0\n#define LUA_HOOKRET\t1\n#define LUA_HOOKLINE\t2\n#define LUA_HOOKCOUNT\t3\n#define LUA_HOOKTAILRET 4\n\n\n/*\n** Event masks\n*/\n#define LUA_MASKCALL\t(1 << LUA_HOOKCALL)\n#define LUA_MASKRET\t(1 << LUA_HOOKRET)\n#define LUA_MASKLINE\t(1 << LUA_HOOKLINE)\n#define LUA_MASKCOUNT\t(1 << LUA_HOOKCOUNT)\n\ntypedef struct lua_Debug lua_Debug;  /* activation record */\n\n\n/* Functions to be called by the debuger in specific events */\ntypedef void (*lua_Hook) (lua_State *L, lua_Debug *ar);\n\n\nLUA_API int lua_getstack (lua_State *L, int level, lua_Debug *ar);\nLUA_API int lua_getinfo (lua_State *L, const char *what, lua_Debug *ar);\nLUA_API const char *lua_getlocal (lua_State *L, const lua_Debug *ar, int n);\nLUA_API const char *lua_setlocal (lua_State *L, const lua_Debug *ar, int n);\nLUA_API const char *lua_getupvalue (lua_State *L, int funcindex, int n);\nLUA_API const char *lua_setupvalue (lua_State *L, int funcindex, int n);\n\nLUA_API int lua_sethook (lua_State *L, lua_Hook func, int mask, int count);\nLUA_API lua_Hook lua_gethook (lua_State *L);\nLUA_API int lua_gethookmask (lua_State *L);\nLUA_API int lua_gethookcount (lua_State *L);\n\n\nstruct lua_Debug {\n  int event;\n  const char *name;\t/* (n) */\n  const char *namewhat;\t/* (n) `global', `local', `field', `method' */\n  const char *what;\t/* (S) `Lua', `C', `main', `tail' */\n  const char *source;\t/* (S) */\n  int currentline;\t/* (l) */\n  int nups;\t\t/* (u) number of upvalues */\n  int linedefined;\t/* (S) */\n  int lastlinedefined;\t/* (S) */\n  char short_src[LUA_IDSIZE]; /* (S) */\n  /* private part */\n  int i_ci;  /* active function */\n};\n\n/* }====================================================================== */\n\n\n/******************************************************************************\n* Copyright (C) 1994-2012 Lua.org, PUC-Rio.  All rights reserved.\n*\n* Permission is hereby granted, free of charge, to any person obtaining\n* a copy of this software and associated documentation files (the\n* \"Software\"), to deal in the Software without restriction, including\n* without limitation the rights to use, copy, modify, merge, publish,\n* distribute, sublicense, and/or sell copies of the Software, and to\n* permit persons to whom the Software is furnished to do so, subject to\n* the following conditions:\n*\n* The above copyright notice and this permission notice shall be\n* included in all copies or substantial portions of the Software.\n*\n* THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND,\n* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\n* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.\n* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY\n* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,\n* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE\n* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n******************************************************************************/\n\n\n#endif\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.8/deps/lua/src/lua_bit.c",
    "content": "/*\n** Lua BitOp -- a bit operations library for Lua 5.1/5.2.\n** http://bitop.luajit.org/\n**\n** Copyright (C) 2008-2012 Mike Pall. All rights reserved.\n**\n** Permission is hereby granted, free of charge, to any person obtaining\n** a copy of this software and associated documentation files (the\n** \"Software\"), to deal in the Software without restriction, including\n** without limitation the rights to use, copy, modify, merge, publish,\n** distribute, sublicense, and/or sell copies of the Software, and to\n** permit persons to whom the Software is furnished to do so, subject to\n** the following conditions:\n**\n** The above copyright notice and this permission notice shall be\n** included in all copies or substantial portions of the Software.\n**\n** THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND,\n** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\n** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.\n** IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY\n** CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,\n** TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE\n** SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n**\n** [ MIT license: http://www.opensource.org/licenses/mit-license.php ]\n*/\n\n#define LUA_BITOP_VERSION\t\"1.0.2\"\n\n#define LUA_LIB\n#include \"lua.h\"\n#include \"lauxlib.h\"\n\n#ifdef _MSC_VER\n/* MSVC is stuck in the last century and doesn't have C99's stdint.h. */\ntypedef __int32 int32_t;\ntypedef unsigned __int32 uint32_t;\ntypedef unsigned __int64 uint64_t;\n#else\n#include <stdint.h>\n#endif\n\ntypedef int32_t SBits;\ntypedef uint32_t UBits;\n\ntypedef union {\n  lua_Number n;\n#ifdef LUA_NUMBER_DOUBLE\n  uint64_t b;\n#else\n  UBits b;\n#endif\n} BitNum;\n\n/* Convert argument to bit type. */\nstatic UBits barg(lua_State *L, int idx)\n{\n  BitNum bn;\n  UBits b;\n#if LUA_VERSION_NUM < 502\n  bn.n = lua_tonumber(L, idx);\n#else\n  bn.n = luaL_checknumber(L, idx);\n#endif\n#if defined(LUA_NUMBER_DOUBLE)\n  bn.n += 6755399441055744.0;  /* 2^52+2^51 */\n#ifdef SWAPPED_DOUBLE\n  b = (UBits)(bn.b >> 32);\n#else\n  b = (UBits)bn.b;\n#endif\n#elif defined(LUA_NUMBER_INT) || defined(LUA_NUMBER_LONG) || \\\n      defined(LUA_NUMBER_LONGLONG) || defined(LUA_NUMBER_LONG_LONG) || \\\n      defined(LUA_NUMBER_LLONG)\n  if (sizeof(UBits) == sizeof(lua_Number))\n    b = bn.b;\n  else\n    b = (UBits)(SBits)bn.n;\n#elif defined(LUA_NUMBER_FLOAT)\n#error \"A 'float' lua_Number type is incompatible with this library\"\n#else\n#error \"Unknown number type, check LUA_NUMBER_* in luaconf.h\"\n#endif\n#if LUA_VERSION_NUM < 502\n  if (b == 0 && !lua_isnumber(L, idx)) {\n    luaL_typerror(L, idx, \"number\");\n  }\n#endif\n  return b;\n}\n\n/* Return bit type. */\n#define BRET(b)  lua_pushnumber(L, (lua_Number)(SBits)(b)); return 1;\n\nstatic int bit_tobit(lua_State *L) { BRET(barg(L, 1)) }\nstatic int bit_bnot(lua_State *L) { BRET(~barg(L, 1)) }\n\n#define BIT_OP(func, opr) \\\n  static int func(lua_State *L) { int i; UBits b = barg(L, 1); \\\n    for (i = lua_gettop(L); i > 1; i--) b opr barg(L, i); BRET(b) }\nBIT_OP(bit_band, &=)\nBIT_OP(bit_bor, |=)\nBIT_OP(bit_bxor, ^=)\n\n#define bshl(b, n)  (b << n)\n#define bshr(b, n)  (b >> n)\n#define bsar(b, n)  ((SBits)b >> n)\n#define brol(b, n)  ((b << n) | (b >> (32-n)))\n#define bror(b, n)  ((b << (32-n)) | (b >> n))\n#define BIT_SH(func, fn) \\\n  static int func(lua_State *L) { \\\n    UBits b = barg(L, 1); UBits n = barg(L, 2) & 31; BRET(fn(b, n)) }\nBIT_SH(bit_lshift, bshl)\nBIT_SH(bit_rshift, bshr)\nBIT_SH(bit_arshift, bsar)\nBIT_SH(bit_rol, brol)\nBIT_SH(bit_ror, bror)\n\nstatic int bit_bswap(lua_State *L)\n{\n  UBits b = barg(L, 1);\n  b = (b >> 24) | ((b >> 8) & 0xff00) | ((b & 0xff00) << 8) | (b << 24);\n  BRET(b)\n}\n\nstatic int bit_tohex(lua_State *L)\n{\n  UBits b = barg(L, 1);\n  SBits n = lua_isnone(L, 2) ? 8 : (SBits)barg(L, 2);\n  const char *hexdigits = \"0123456789abcdef\";\n  char buf[8];\n  int i;\n  if (n < 0) { n = -n; hexdigits = \"0123456789ABCDEF\"; }\n  if (n > 8) n = 8;\n  for (i = (int)n; --i >= 0; ) { buf[i] = hexdigits[b & 15]; b >>= 4; }\n  lua_pushlstring(L, buf, (size_t)n);\n  return 1;\n}\n\nstatic const struct luaL_Reg bit_funcs[] = {\n  { \"tobit\",\tbit_tobit },\n  { \"bnot\",\tbit_bnot },\n  { \"band\",\tbit_band },\n  { \"bor\",\tbit_bor },\n  { \"bxor\",\tbit_bxor },\n  { \"lshift\",\tbit_lshift },\n  { \"rshift\",\tbit_rshift },\n  { \"arshift\",\tbit_arshift },\n  { \"rol\",\tbit_rol },\n  { \"ror\",\tbit_ror },\n  { \"bswap\",\tbit_bswap },\n  { \"tohex\",\tbit_tohex },\n  { NULL, NULL }\n};\n\n/* Signed right-shifts are implementation-defined per C89/C99.\n** But the de facto standard are arithmetic right-shifts on two's\n** complement CPUs. This behaviour is required here, so test for it.\n*/\n#define BAD_SAR\t\t(bsar(-8, 2) != (SBits)-2)\n\nLUALIB_API int luaopen_bit(lua_State *L)\n{\n  UBits b;\n  lua_pushnumber(L, (lua_Number)1437217655L);\n  b = barg(L, -1);\n  if (b != (UBits)1437217655L || BAD_SAR) {  /* Perform a simple self-test. */\n    const char *msg = \"compiled with incompatible luaconf.h\";\n#ifdef LUA_NUMBER_DOUBLE\n#ifdef _WIN32\n    if (b == (UBits)1610612736L)\n      msg = \"use D3DCREATE_FPU_PRESERVE with DirectX\";\n#endif\n    if (b == (UBits)1127743488L)\n      msg = \"not compiled with SWAPPED_DOUBLE\";\n#endif\n    if (BAD_SAR)\n      msg = \"arithmetic right-shift broken\";\n    luaL_error(L, \"bit library self-test failed (%s)\", msg);\n  }\n#if LUA_VERSION_NUM < 502\n  luaL_register(L, \"bit\", bit_funcs);\n#else\n  luaL_newlib(L, bit_funcs);\n#endif\n  return 1;\n}\n\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.8/deps/lua/src/lua_cjson.c",
    "content": "/* Lua CJSON - JSON support for Lua\n *\n * Copyright (c) 2010-2012  Mark Pulford <mark@kyne.com.au>\n *\n * Permission is hereby granted, free of charge, to any person obtaining\n * a copy of this software and associated documentation files (the\n * \"Software\"), to deal in the Software without restriction, including\n * without limitation the rights to use, copy, modify, merge, publish,\n * distribute, sublicense, and/or sell copies of the Software, and to\n * permit persons to whom the Software is furnished to do so, subject to\n * the following conditions:\n *\n * The above copyright notice and this permission notice shall be\n * included in all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND,\n * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\n * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.\n * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY\n * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,\n * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE\n * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n */\n\n/* Caveats:\n * - JSON \"null\" values are represented as lightuserdata since Lua\n *   tables cannot contain \"nil\". Compare with cjson.null.\n * - Invalid UTF-8 characters are not detected and will be passed\n *   untouched. If required, UTF-8 error checking should be done\n *   outside this library.\n * - Javascript comments are not part of the JSON spec, and are not\n *   currently supported.\n *\n * Note: Decoding is slower than encoding. Lua spends significant\n *       time (30%) managing tables when parsing JSON since it is\n *       difficult to know object/array sizes ahead of time.\n */\n\n#include <assert.h>\n#include <string.h>\n#include <math.h>\n#include <limits.h>\n#include \"lua.h\"\n#include \"lauxlib.h\"\n\n#include \"strbuf.h\"\n#include \"fpconv.h\"\n\n#include \"../../../src/solarisfixes.h\"\n\n#ifndef CJSON_MODNAME\n#define CJSON_MODNAME   \"cjson\"\n#endif\n\n#ifndef CJSON_VERSION\n#define CJSON_VERSION   \"2.1.0\"\n#endif\n\n/* Workaround for Solaris platforms missing isinf() */\n#if !defined(isinf) && (defined(USE_INTERNAL_ISINF) || defined(MISSING_ISINF))\n#define isinf(x) (!isnan(x) && isnan((x) - (x)))\n#endif\n\n#define DEFAULT_SPARSE_CONVERT 0\n#define DEFAULT_SPARSE_RATIO 2\n#define DEFAULT_SPARSE_SAFE 10\n#define DEFAULT_ENCODE_MAX_DEPTH 1000\n#define DEFAULT_DECODE_MAX_DEPTH 1000\n#define DEFAULT_ENCODE_INVALID_NUMBERS 0\n#define DEFAULT_DECODE_INVALID_NUMBERS 1\n#define DEFAULT_ENCODE_KEEP_BUFFER 1\n#define DEFAULT_ENCODE_NUMBER_PRECISION 14\n\n#ifdef DISABLE_INVALID_NUMBERS\n#undef DEFAULT_DECODE_INVALID_NUMBERS\n#define DEFAULT_DECODE_INVALID_NUMBERS 0\n#endif\n\ntypedef enum {\n    T_OBJ_BEGIN,\n    T_OBJ_END,\n    T_ARR_BEGIN,\n    T_ARR_END,\n    T_STRING,\n    T_NUMBER,\n    T_BOOLEAN,\n    T_NULL,\n    T_COLON,\n    T_COMMA,\n    T_END,\n    T_WHITESPACE,\n    T_ERROR,\n    T_UNKNOWN\n} json_token_type_t;\n\nstatic const char *json_token_type_name[] = {\n    \"T_OBJ_BEGIN\",\n    \"T_OBJ_END\",\n    \"T_ARR_BEGIN\",\n    \"T_ARR_END\",\n    \"T_STRING\",\n    \"T_NUMBER\",\n    \"T_BOOLEAN\",\n    \"T_NULL\",\n    \"T_COLON\",\n    \"T_COMMA\",\n    \"T_END\",\n    \"T_WHITESPACE\",\n    \"T_ERROR\",\n    \"T_UNKNOWN\",\n    NULL\n};\n\ntypedef struct {\n    json_token_type_t ch2token[256];\n    char escape2char[256];  /* Decoding */\n\n    /* encode_buf is only allocated and used when\n     * encode_keep_buffer is set */\n    strbuf_t encode_buf;\n\n    int encode_sparse_convert;\n    int encode_sparse_ratio;\n    int encode_sparse_safe;\n    int encode_max_depth;\n    int encode_invalid_numbers;     /* 2 => Encode as \"null\" */\n    int encode_number_precision;\n    int encode_keep_buffer;\n\n    int decode_invalid_numbers;\n    int decode_max_depth;\n} json_config_t;\n\ntypedef struct {\n    const char *data;\n    const char *ptr;\n    strbuf_t *tmp;    /* Temporary storage for strings */\n    json_config_t *cfg;\n    int current_depth;\n} json_parse_t;\n\ntypedef struct {\n    json_token_type_t type;\n    int index;\n    union {\n        const char *string;\n        double number;\n        int boolean;\n    } value;\n    int string_len;\n} json_token_t;\n\nstatic const char *char2escape[256] = {\n    \"\\\\u0000\", \"\\\\u0001\", \"\\\\u0002\", \"\\\\u0003\",\n    \"\\\\u0004\", \"\\\\u0005\", \"\\\\u0006\", \"\\\\u0007\",\n    \"\\\\b\", \"\\\\t\", \"\\\\n\", \"\\\\u000b\",\n    \"\\\\f\", \"\\\\r\", \"\\\\u000e\", \"\\\\u000f\",\n    \"\\\\u0010\", \"\\\\u0011\", \"\\\\u0012\", \"\\\\u0013\",\n    \"\\\\u0014\", \"\\\\u0015\", \"\\\\u0016\", \"\\\\u0017\",\n    \"\\\\u0018\", \"\\\\u0019\", \"\\\\u001a\", \"\\\\u001b\",\n    \"\\\\u001c\", \"\\\\u001d\", \"\\\\u001e\", \"\\\\u001f\",\n    NULL, NULL, \"\\\\\\\"\", NULL, NULL, NULL, NULL, NULL,\n    NULL, NULL, NULL, NULL, NULL, NULL, NULL, \"\\\\/\",\n    NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,\n    NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,\n    NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,\n    NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,\n    NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,\n    NULL, NULL, NULL, NULL, \"\\\\\\\\\", NULL, NULL, NULL,\n    NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,\n    NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,\n    NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,\n    NULL, NULL, NULL, NULL, NULL, NULL, NULL, \"\\\\u007f\",\n    NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,\n    NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,\n    NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,\n    NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,\n    NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,\n    NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,\n    NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,\n    NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,\n    NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,\n    NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,\n    NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,\n    NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,\n    NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,\n    NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,\n    NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,\n    NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,\n};\n\n/* ===== CONFIGURATION ===== */\n\nstatic json_config_t *json_fetch_config(lua_State *l)\n{\n    json_config_t *cfg;\n\n    cfg = lua_touserdata(l, lua_upvalueindex(1));\n    if (!cfg)\n        luaL_error(l, \"BUG: Unable to fetch CJSON configuration\");\n\n    return cfg;\n}\n\n/* Ensure the correct number of arguments have been provided.\n * Pad with nil to allow other functions to simply check arg[i]\n * to find whether an argument was provided */\nstatic json_config_t *json_arg_init(lua_State *l, int args)\n{\n    luaL_argcheck(l, lua_gettop(l) <= args, args + 1,\n                  \"found too many arguments\");\n\n    while (lua_gettop(l) < args)\n        lua_pushnil(l);\n\n    return json_fetch_config(l);\n}\n\n/* Process integer options for configuration functions */\nstatic int json_integer_option(lua_State *l, int optindex, int *setting,\n                               int min, int max)\n{\n    char errmsg[64];\n    int value;\n\n    if (!lua_isnil(l, optindex)) {\n        value = luaL_checkinteger(l, optindex);\n        snprintf(errmsg, sizeof(errmsg), \"expected integer between %d and %d\", min, max);\n        luaL_argcheck(l, min <= value && value <= max, 1, errmsg);\n        *setting = value;\n    }\n\n    lua_pushinteger(l, *setting);\n\n    return 1;\n}\n\n/* Process enumerated arguments for a configuration function */\nstatic int json_enum_option(lua_State *l, int optindex, int *setting,\n                            const char **options, int bool_true)\n{\n    static const char *bool_options[] = { \"off\", \"on\", NULL };\n\n    if (!options) {\n        options = bool_options;\n        bool_true = 1;\n    }\n\n    if (!lua_isnil(l, optindex)) {\n        if (bool_true && lua_isboolean(l, optindex))\n            *setting = lua_toboolean(l, optindex) * bool_true;\n        else\n            *setting = luaL_checkoption(l, optindex, NULL, options);\n    }\n\n    if (bool_true && (*setting == 0 || *setting == bool_true))\n        lua_pushboolean(l, *setting);\n    else\n        lua_pushstring(l, options[*setting]);\n\n    return 1;\n}\n\n/* Configures handling of extremely sparse arrays:\n * convert: Convert extremely sparse arrays into objects? Otherwise error.\n * ratio: 0: always allow sparse; 1: never allow sparse; >1: use ratio\n * safe: Always use an array when the max index <= safe */\nstatic int json_cfg_encode_sparse_array(lua_State *l)\n{\n    json_config_t *cfg = json_arg_init(l, 3);\n\n    json_enum_option(l, 1, &cfg->encode_sparse_convert, NULL, 1);\n    json_integer_option(l, 2, &cfg->encode_sparse_ratio, 0, INT_MAX);\n    json_integer_option(l, 3, &cfg->encode_sparse_safe, 0, INT_MAX);\n\n    return 3;\n}\n\n/* Configures the maximum number of nested arrays/objects allowed when\n * encoding */\nstatic int json_cfg_encode_max_depth(lua_State *l)\n{\n    json_config_t *cfg = json_arg_init(l, 1);\n\n    return json_integer_option(l, 1, &cfg->encode_max_depth, 1, INT_MAX);\n}\n\n/* Configures the maximum number of nested arrays/objects allowed when\n * encoding */\nstatic int json_cfg_decode_max_depth(lua_State *l)\n{\n    json_config_t *cfg = json_arg_init(l, 1);\n\n    return json_integer_option(l, 1, &cfg->decode_max_depth, 1, INT_MAX);\n}\n\n/* Configures number precision when converting doubles to text */\nstatic int json_cfg_encode_number_precision(lua_State *l)\n{\n    json_config_t *cfg = json_arg_init(l, 1);\n\n    return json_integer_option(l, 1, &cfg->encode_number_precision, 1, 14);\n}\n\n/* Configures JSON encoding buffer persistence */\nstatic int json_cfg_encode_keep_buffer(lua_State *l)\n{\n    json_config_t *cfg = json_arg_init(l, 1);\n    int old_value;\n\n    old_value = cfg->encode_keep_buffer;\n\n    json_enum_option(l, 1, &cfg->encode_keep_buffer, NULL, 1);\n\n    /* Init / free the buffer if the setting has changed */\n    if (old_value ^ cfg->encode_keep_buffer) {\n        if (cfg->encode_keep_buffer)\n            strbuf_init(&cfg->encode_buf, 0);\n        else\n            strbuf_free(&cfg->encode_buf);\n    }\n\n    return 1;\n}\n\n#if defined(DISABLE_INVALID_NUMBERS) && !defined(USE_INTERNAL_FPCONV)\nvoid json_verify_invalid_number_setting(lua_State *l, int *setting)\n{\n    if (*setting == 1) {\n        *setting = 0;\n        luaL_error(l, \"Infinity, NaN, and/or hexadecimal numbers are not supported.\");\n    }\n}\n#else\n#define json_verify_invalid_number_setting(l, s)    do { } while(0)\n#endif\n\nstatic int json_cfg_encode_invalid_numbers(lua_State *l)\n{\n    static const char *options[] = { \"off\", \"on\", \"null\", NULL };\n    json_config_t *cfg = json_arg_init(l, 1);\n\n    json_enum_option(l, 1, &cfg->encode_invalid_numbers, options, 1);\n\n    json_verify_invalid_number_setting(l, &cfg->encode_invalid_numbers);\n\n    return 1;\n}\n\nstatic int json_cfg_decode_invalid_numbers(lua_State *l)\n{\n    json_config_t *cfg = json_arg_init(l, 1);\n\n    json_enum_option(l, 1, &cfg->decode_invalid_numbers, NULL, 1);\n\n    json_verify_invalid_number_setting(l, &cfg->encode_invalid_numbers);\n\n    return 1;\n}\n\nstatic int json_destroy_config(lua_State *l)\n{\n    json_config_t *cfg;\n\n    cfg = lua_touserdata(l, 1);\n    if (cfg)\n        strbuf_free(&cfg->encode_buf);\n    cfg = NULL;\n\n    return 0;\n}\n\nstatic void json_create_config(lua_State *l)\n{\n    json_config_t *cfg;\n    int i;\n\n    cfg = lua_newuserdata(l, sizeof(*cfg));\n\n    /* Create GC method to clean up strbuf */\n    lua_newtable(l);\n    lua_pushcfunction(l, json_destroy_config);\n    lua_setfield(l, -2, \"__gc\");\n    lua_setmetatable(l, -2);\n\n    cfg->encode_sparse_convert = DEFAULT_SPARSE_CONVERT;\n    cfg->encode_sparse_ratio = DEFAULT_SPARSE_RATIO;\n    cfg->encode_sparse_safe = DEFAULT_SPARSE_SAFE;\n    cfg->encode_max_depth = DEFAULT_ENCODE_MAX_DEPTH;\n    cfg->decode_max_depth = DEFAULT_DECODE_MAX_DEPTH;\n    cfg->encode_invalid_numbers = DEFAULT_ENCODE_INVALID_NUMBERS;\n    cfg->decode_invalid_numbers = DEFAULT_DECODE_INVALID_NUMBERS;\n    cfg->encode_keep_buffer = DEFAULT_ENCODE_KEEP_BUFFER;\n    cfg->encode_number_precision = DEFAULT_ENCODE_NUMBER_PRECISION;\n\n#if DEFAULT_ENCODE_KEEP_BUFFER > 0\n    strbuf_init(&cfg->encode_buf, 0);\n#endif\n\n    /* Decoding init */\n\n    /* Tag all characters as an error */\n    for (i = 0; i < 256; i++)\n        cfg->ch2token[i] = T_ERROR;\n\n    /* Set tokens that require no further processing */\n    cfg->ch2token['{'] = T_OBJ_BEGIN;\n    cfg->ch2token['}'] = T_OBJ_END;\n    cfg->ch2token['['] = T_ARR_BEGIN;\n    cfg->ch2token[']'] = T_ARR_END;\n    cfg->ch2token[','] = T_COMMA;\n    cfg->ch2token[':'] = T_COLON;\n    cfg->ch2token['\\0'] = T_END;\n    cfg->ch2token[' '] = T_WHITESPACE;\n    cfg->ch2token['\\t'] = T_WHITESPACE;\n    cfg->ch2token['\\n'] = T_WHITESPACE;\n    cfg->ch2token['\\r'] = T_WHITESPACE;\n\n    /* Update characters that require further processing */\n    cfg->ch2token['f'] = T_UNKNOWN;     /* false? */\n    cfg->ch2token['i'] = T_UNKNOWN;     /* inf, ininity? */\n    cfg->ch2token['I'] = T_UNKNOWN;\n    cfg->ch2token['n'] = T_UNKNOWN;     /* null, nan? */\n    cfg->ch2token['N'] = T_UNKNOWN;\n    cfg->ch2token['t'] = T_UNKNOWN;     /* true? */\n    cfg->ch2token['\"'] = T_UNKNOWN;     /* string? */\n    cfg->ch2token['+'] = T_UNKNOWN;     /* number? */\n    cfg->ch2token['-'] = T_UNKNOWN;\n    for (i = 0; i < 10; i++)\n        cfg->ch2token['0' + i] = T_UNKNOWN;\n\n    /* Lookup table for parsing escape characters */\n    for (i = 0; i < 256; i++)\n        cfg->escape2char[i] = 0;          /* String error */\n    cfg->escape2char['\"'] = '\"';\n    cfg->escape2char['\\\\'] = '\\\\';\n    cfg->escape2char['/'] = '/';\n    cfg->escape2char['b'] = '\\b';\n    cfg->escape2char['t'] = '\\t';\n    cfg->escape2char['n'] = '\\n';\n    cfg->escape2char['f'] = '\\f';\n    cfg->escape2char['r'] = '\\r';\n    cfg->escape2char['u'] = 'u';          /* Unicode parsing required */\n}\n\n/* ===== ENCODING ===== */\n\nstatic void json_encode_exception(lua_State *l, json_config_t *cfg, strbuf_t *json, int lindex,\n                                  const char *reason)\n{\n    if (!cfg->encode_keep_buffer)\n        strbuf_free(json);\n    luaL_error(l, \"Cannot serialise %s: %s\",\n                  lua_typename(l, lua_type(l, lindex)), reason);\n}\n\n/* json_append_string args:\n * - lua_State\n * - JSON strbuf\n * - String (Lua stack index)\n *\n * Returns nothing. Doesn't remove string from Lua stack */\nstatic void json_append_string(lua_State *l, strbuf_t *json, int lindex)\n{\n    const char *escstr;\n    int i;\n    const char *str;\n    size_t len;\n\n    str = lua_tolstring(l, lindex, &len);\n\n    /* Worst case is len * 6 (all unicode escapes).\n     * This buffer is reused constantly for small strings\n     * If there are any excess pages, they won't be hit anyway.\n     * This gains ~5% speedup. */\n    strbuf_ensure_empty_length(json, len * 6 + 2);\n\n    strbuf_append_char_unsafe(json, '\\\"');\n    for (i = 0; i < len; i++) {\n        escstr = char2escape[(unsigned char)str[i]];\n        if (escstr)\n            strbuf_append_string(json, escstr);\n        else\n            strbuf_append_char_unsafe(json, str[i]);\n    }\n    strbuf_append_char_unsafe(json, '\\\"');\n}\n\n/* Find the size of the array on the top of the Lua stack\n * -1   object (not a pure array)\n * >=0  elements in array\n */\nstatic int lua_array_length(lua_State *l, json_config_t *cfg, strbuf_t *json)\n{\n    double k;\n    int max;\n    int items;\n\n    max = 0;\n    items = 0;\n\n    lua_pushnil(l);\n    /* table, startkey */\n    while (lua_next(l, -2) != 0) {\n        /* table, key, value */\n        if (lua_type(l, -2) == LUA_TNUMBER &&\n            (k = lua_tonumber(l, -2))) {\n            /* Integer >= 1 ? */\n            if (floor(k) == k && k >= 1) {\n                if (k > max)\n                    max = k;\n                items++;\n                lua_pop(l, 1);\n                continue;\n            }\n        }\n\n        /* Must not be an array (non integer key) */\n        lua_pop(l, 2);\n        return -1;\n    }\n\n    /* Encode excessively sparse arrays as objects (if enabled) */\n    if (cfg->encode_sparse_ratio > 0 &&\n        max > items * cfg->encode_sparse_ratio &&\n        max > cfg->encode_sparse_safe) {\n        if (!cfg->encode_sparse_convert)\n            json_encode_exception(l, cfg, json, -1, \"excessively sparse array\");\n\n        return -1;\n    }\n\n    return max;\n}\n\nstatic void json_check_encode_depth(lua_State *l, json_config_t *cfg,\n                                    int current_depth, strbuf_t *json)\n{\n    /* Ensure there are enough slots free to traverse a table (key,\n     * value) and push a string for a potential error message.\n     *\n     * Unlike \"decode\", the key and value are still on the stack when\n     * lua_checkstack() is called.  Hence an extra slot for luaL_error()\n     * below is required just in case the next check to lua_checkstack()\n     * fails.\n     *\n     * While this won't cause a crash due to the EXTRA_STACK reserve\n     * slots, it would still be an improper use of the API. */\n    if (current_depth <= cfg->encode_max_depth && lua_checkstack(l, 3))\n        return;\n\n    if (!cfg->encode_keep_buffer)\n        strbuf_free(json);\n\n    luaL_error(l, \"Cannot serialise, excessive nesting (%d)\",\n               current_depth);\n}\n\nstatic void json_append_data(lua_State *l, json_config_t *cfg,\n                             int current_depth, strbuf_t *json);\n\n/* json_append_array args:\n * - lua_State\n * - JSON strbuf\n * - Size of passwd Lua array (top of stack) */\nstatic void json_append_array(lua_State *l, json_config_t *cfg, int current_depth,\n                              strbuf_t *json, int array_length)\n{\n    int comma, i;\n\n    strbuf_append_char(json, '[');\n\n    comma = 0;\n    for (i = 1; i <= array_length; i++) {\n        if (comma)\n            strbuf_append_char(json, ',');\n        else\n            comma = 1;\n\n        lua_rawgeti(l, -1, i);\n        json_append_data(l, cfg, current_depth, json);\n        lua_pop(l, 1);\n    }\n\n    strbuf_append_char(json, ']');\n}\n\nstatic void json_append_number(lua_State *l, json_config_t *cfg,\n                               strbuf_t *json, int lindex)\n{\n    double num = lua_tonumber(l, lindex);\n    int len;\n\n    if (cfg->encode_invalid_numbers == 0) {\n        /* Prevent encoding invalid numbers */\n        if (isinf(num) || isnan(num))\n            json_encode_exception(l, cfg, json, lindex, \"must not be NaN or Inf\");\n    } else if (cfg->encode_invalid_numbers == 1) {\n        /* Encode invalid numbers, but handle \"nan\" separately\n         * since some platforms may encode as \"-nan\". */\n        if (isnan(num)) {\n            strbuf_append_mem(json, \"nan\", 3);\n            return;\n        }\n    } else {\n        /* Encode invalid numbers as \"null\" */\n        if (isinf(num) || isnan(num)) {\n            strbuf_append_mem(json, \"null\", 4);\n            return;\n        }\n    }\n\n    strbuf_ensure_empty_length(json, FPCONV_G_FMT_BUFSIZE);\n    len = fpconv_g_fmt(strbuf_empty_ptr(json), num, cfg->encode_number_precision);\n    strbuf_extend_length(json, len);\n}\n\nstatic void json_append_object(lua_State *l, json_config_t *cfg,\n                               int current_depth, strbuf_t *json)\n{\n    int comma, keytype;\n\n    /* Object */\n    strbuf_append_char(json, '{');\n\n    lua_pushnil(l);\n    /* table, startkey */\n    comma = 0;\n    while (lua_next(l, -2) != 0) {\n        if (comma)\n            strbuf_append_char(json, ',');\n        else\n            comma = 1;\n\n        /* table, key, value */\n        keytype = lua_type(l, -2);\n        if (keytype == LUA_TNUMBER) {\n            strbuf_append_char(json, '\"');\n            json_append_number(l, cfg, json, -2);\n            strbuf_append_mem(json, \"\\\":\", 2);\n        } else if (keytype == LUA_TSTRING) {\n            json_append_string(l, json, -2);\n            strbuf_append_char(json, ':');\n        } else {\n            json_encode_exception(l, cfg, json, -2,\n                                  \"table key must be a number or string\");\n            /* never returns */\n        }\n\n        /* table, key, value */\n        json_append_data(l, cfg, current_depth, json);\n        lua_pop(l, 1);\n        /* table, key */\n    }\n\n    strbuf_append_char(json, '}');\n}\n\n/* Serialise Lua data into JSON string. */\nstatic void json_append_data(lua_State *l, json_config_t *cfg,\n                             int current_depth, strbuf_t *json)\n{\n    int len;\n\n    switch (lua_type(l, -1)) {\n    case LUA_TSTRING:\n        json_append_string(l, json, -1);\n        break;\n    case LUA_TNUMBER:\n        json_append_number(l, cfg, json, -1);\n        break;\n    case LUA_TBOOLEAN:\n        if (lua_toboolean(l, -1))\n            strbuf_append_mem(json, \"true\", 4);\n        else\n            strbuf_append_mem(json, \"false\", 5);\n        break;\n    case LUA_TTABLE:\n        current_depth++;\n        json_check_encode_depth(l, cfg, current_depth, json);\n        len = lua_array_length(l, cfg, json);\n        if (len > 0)\n            json_append_array(l, cfg, current_depth, json, len);\n        else\n            json_append_object(l, cfg, current_depth, json);\n        break;\n    case LUA_TNIL:\n        strbuf_append_mem(json, \"null\", 4);\n        break;\n    case LUA_TLIGHTUSERDATA:\n        if (lua_touserdata(l, -1) == NULL) {\n            strbuf_append_mem(json, \"null\", 4);\n            break;\n        }\n    default:\n        /* Remaining types (LUA_TFUNCTION, LUA_TUSERDATA, LUA_TTHREAD,\n         * and LUA_TLIGHTUSERDATA) cannot be serialised */\n        json_encode_exception(l, cfg, json, -1, \"type not supported\");\n        /* never returns */\n    }\n}\n\nstatic int json_encode(lua_State *l)\n{\n    json_config_t *cfg = json_fetch_config(l);\n    strbuf_t local_encode_buf;\n    strbuf_t *encode_buf;\n    char *json;\n    int len;\n\n    luaL_argcheck(l, lua_gettop(l) == 1, 1, \"expected 1 argument\");\n\n    if (!cfg->encode_keep_buffer) {\n        /* Use private buffer */\n        encode_buf = &local_encode_buf;\n        strbuf_init(encode_buf, 0);\n    } else {\n        /* Reuse existing buffer */\n        encode_buf = &cfg->encode_buf;\n        strbuf_reset(encode_buf);\n    }\n\n    json_append_data(l, cfg, 0, encode_buf);\n    json = strbuf_string(encode_buf, &len);\n\n    lua_pushlstring(l, json, len);\n\n    if (!cfg->encode_keep_buffer)\n        strbuf_free(encode_buf);\n\n    return 1;\n}\n\n/* ===== DECODING ===== */\n\nstatic void json_process_value(lua_State *l, json_parse_t *json,\n                               json_token_t *token);\n\nstatic int hexdigit2int(char hex)\n{\n    if ('0' <= hex  && hex <= '9')\n        return hex - '0';\n\n    /* Force lowercase */\n    hex |= 0x20;\n    if ('a' <= hex && hex <= 'f')\n        return 10 + hex - 'a';\n\n    return -1;\n}\n\nstatic int decode_hex4(const char *hex)\n{\n    int digit[4];\n    int i;\n\n    /* Convert ASCII hex digit to numeric digit\n     * Note: this returns an error for invalid hex digits, including\n     *       NULL */\n    for (i = 0; i < 4; i++) {\n        digit[i] = hexdigit2int(hex[i]);\n        if (digit[i] < 0) {\n            return -1;\n        }\n    }\n\n    return (digit[0] << 12) +\n           (digit[1] << 8) +\n           (digit[2] << 4) +\n            digit[3];\n}\n\n/* Converts a Unicode codepoint to UTF-8.\n * Returns UTF-8 string length, and up to 4 bytes in *utf8 */\nstatic int codepoint_to_utf8(char *utf8, int codepoint)\n{\n    /* 0xxxxxxx */\n    if (codepoint <= 0x7F) {\n        utf8[0] = codepoint;\n        return 1;\n    }\n\n    /* 110xxxxx 10xxxxxx */\n    if (codepoint <= 0x7FF) {\n        utf8[0] = (codepoint >> 6) | 0xC0;\n        utf8[1] = (codepoint & 0x3F) | 0x80;\n        return 2;\n    }\n\n    /* 1110xxxx 10xxxxxx 10xxxxxx */\n    if (codepoint <= 0xFFFF) {\n        utf8[0] = (codepoint >> 12) | 0xE0;\n        utf8[1] = ((codepoint >> 6) & 0x3F) | 0x80;\n        utf8[2] = (codepoint & 0x3F) | 0x80;\n        return 3;\n    }\n\n    /* 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx */\n    if (codepoint <= 0x1FFFFF) {\n        utf8[0] = (codepoint >> 18) | 0xF0;\n        utf8[1] = ((codepoint >> 12) & 0x3F) | 0x80;\n        utf8[2] = ((codepoint >> 6) & 0x3F) | 0x80;\n        utf8[3] = (codepoint & 0x3F) | 0x80;\n        return 4;\n    }\n\n    return 0;\n}\n\n\n/* Called when index pointing to beginning of UTF-16 code escape: \\uXXXX\n * \\u is guaranteed to exist, but the remaining hex characters may be\n * missing.\n * Translate to UTF-8 and append to temporary token string.\n * Must advance index to the next character to be processed.\n * Returns: 0   success\n *          -1  error\n */\nstatic int json_append_unicode_escape(json_parse_t *json)\n{\n    char utf8[4];       /* Surrogate pairs require 4 UTF-8 bytes */\n    int codepoint;\n    int surrogate_low;\n    int len;\n    int escape_len = 6;\n\n    /* Fetch UTF-16 code unit */\n    codepoint = decode_hex4(json->ptr + 2);\n    if (codepoint < 0)\n        return -1;\n\n    /* UTF-16 surrogate pairs take the following 2 byte form:\n     *      11011 x yyyyyyyyyy\n     * When x = 0: y is the high 10 bits of the codepoint\n     *      x = 1: y is the low 10 bits of the codepoint\n     *\n     * Check for a surrogate pair (high or low) */\n    if ((codepoint & 0xF800) == 0xD800) {\n        /* Error if the 1st surrogate is not high */\n        if (codepoint & 0x400)\n            return -1;\n\n        /* Ensure the next code is a unicode escape */\n        if (*(json->ptr + escape_len) != '\\\\' ||\n            *(json->ptr + escape_len + 1) != 'u') {\n            return -1;\n        }\n\n        /* Fetch the next codepoint */\n        surrogate_low = decode_hex4(json->ptr + 2 + escape_len);\n        if (surrogate_low < 0)\n            return -1;\n\n        /* Error if the 2nd code is not a low surrogate */\n        if ((surrogate_low & 0xFC00) != 0xDC00)\n            return -1;\n\n        /* Calculate Unicode codepoint */\n        codepoint = (codepoint & 0x3FF) << 10;\n        surrogate_low &= 0x3FF;\n        codepoint = (codepoint | surrogate_low) + 0x10000;\n        escape_len = 12;\n    }\n\n    /* Convert codepoint to UTF-8 */\n    len = codepoint_to_utf8(utf8, codepoint);\n    if (!len)\n        return -1;\n\n    /* Append bytes and advance parse index */\n    strbuf_append_mem_unsafe(json->tmp, utf8, len);\n    json->ptr += escape_len;\n\n    return 0;\n}\n\nstatic void json_set_token_error(json_token_t *token, json_parse_t *json,\n                                 const char *errtype)\n{\n    token->type = T_ERROR;\n    token->index = json->ptr - json->data;\n    token->value.string = errtype;\n}\n\nstatic void json_next_string_token(json_parse_t *json, json_token_t *token)\n{\n    char *escape2char = json->cfg->escape2char;\n    char ch;\n\n    /* Caller must ensure a string is next */\n    assert(*json->ptr == '\"');\n\n    /* Skip \" */\n    json->ptr++;\n\n    /* json->tmp is the temporary strbuf used to accumulate the\n     * decoded string value.\n     * json->tmp is sized to handle JSON containing only a string value.\n     */\n    strbuf_reset(json->tmp);\n\n    while ((ch = *json->ptr) != '\"') {\n        if (!ch) {\n            /* Premature end of the string */\n            json_set_token_error(token, json, \"unexpected end of string\");\n            return;\n        }\n\n        /* Handle escapes */\n        if (ch == '\\\\') {\n            /* Fetch escape character */\n            ch = *(json->ptr + 1);\n\n            /* Translate escape code and append to tmp string */\n            ch = escape2char[(unsigned char)ch];\n            if (ch == 'u') {\n                if (json_append_unicode_escape(json) == 0)\n                    continue;\n\n                json_set_token_error(token, json,\n                                     \"invalid unicode escape code\");\n                return;\n            }\n            if (!ch) {\n                json_set_token_error(token, json, \"invalid escape code\");\n                return;\n            }\n\n            /* Skip '\\' */\n            json->ptr++;\n        }\n        /* Append normal character or translated single character\n         * Unicode escapes are handled above */\n        strbuf_append_char_unsafe(json->tmp, ch);\n        json->ptr++;\n    }\n    json->ptr++;    /* Eat final quote (\") */\n\n    strbuf_ensure_null(json->tmp);\n\n    token->type = T_STRING;\n    token->value.string = strbuf_string(json->tmp, &token->string_len);\n}\n\n/* JSON numbers should take the following form:\n *      -?(0|[1-9]|[1-9][0-9]+)(.[0-9]+)?([eE][-+]?[0-9]+)?\n *\n * json_next_number_token() uses strtod() which allows other forms:\n * - numbers starting with '+'\n * - NaN, -NaN, infinity, -infinity\n * - hexadecimal numbers\n * - numbers with leading zeros\n *\n * json_is_invalid_number() detects \"numbers\" which may pass strtod()'s\n * error checking, but should not be allowed with strict JSON.\n *\n * json_is_invalid_number() may pass numbers which cause strtod()\n * to generate an error.\n */\nstatic int json_is_invalid_number(json_parse_t *json)\n{\n    const char *p = json->ptr;\n\n    /* Reject numbers starting with + */\n    if (*p == '+')\n        return 1;\n\n    /* Skip minus sign if it exists */\n    if (*p == '-')\n        p++;\n\n    /* Reject numbers starting with 0x, or leading zeros */\n    if (*p == '0') {\n        int ch2 = *(p + 1);\n\n        if ((ch2 | 0x20) == 'x' ||          /* Hex */\n            ('0' <= ch2 && ch2 <= '9'))     /* Leading zero */\n            return 1;\n\n        return 0;\n    } else if (*p <= '9') {\n        return 0;                           /* Ordinary number */\n    }\n\n    /* Reject inf/nan */\n    if (!strncasecmp(p, \"inf\", 3))\n        return 1;\n    if (!strncasecmp(p, \"nan\", 3))\n        return 1;\n\n    /* Pass all other numbers which may still be invalid, but\n     * strtod() will catch them. */\n    return 0;\n}\n\nstatic void json_next_number_token(json_parse_t *json, json_token_t *token)\n{\n    char *endptr;\n\n    token->type = T_NUMBER;\n    token->value.number = fpconv_strtod(json->ptr, &endptr);\n    if (json->ptr == endptr)\n        json_set_token_error(token, json, \"invalid number\");\n    else\n        json->ptr = endptr;     /* Skip the processed number */\n\n    return;\n}\n\n/* Fills in the token struct.\n * T_STRING will return a pointer to the json_parse_t temporary string\n * T_ERROR will leave the json->ptr pointer at the error.\n */\nstatic void json_next_token(json_parse_t *json, json_token_t *token)\n{\n    const json_token_type_t *ch2token = json->cfg->ch2token;\n    int ch;\n\n    /* Eat whitespace. */\n    while (1) {\n        ch = (unsigned char)*(json->ptr);\n        token->type = ch2token[ch];\n        if (token->type != T_WHITESPACE)\n            break;\n        json->ptr++;\n    }\n\n    /* Store location of new token. Required when throwing errors\n     * for unexpected tokens (syntax errors). */\n    token->index = json->ptr - json->data;\n\n    /* Don't advance the pointer for an error or the end */\n    if (token->type == T_ERROR) {\n        json_set_token_error(token, json, \"invalid token\");\n        return;\n    }\n\n    if (token->type == T_END) {\n        return;\n    }\n\n    /* Found a known single character token, advance index and return */\n    if (token->type != T_UNKNOWN) {\n        json->ptr++;\n        return;\n    }\n\n    /* Process characters which triggered T_UNKNOWN\n     *\n     * Must use strncmp() to match the front of the JSON string.\n     * JSON identifier must be lowercase.\n     * When strict_numbers if disabled, either case is allowed for\n     * Infinity/NaN (since we are no longer following the spec..) */\n    if (ch == '\"') {\n        json_next_string_token(json, token);\n        return;\n    } else if (ch == '-' || ('0' <= ch && ch <= '9')) {\n        if (!json->cfg->decode_invalid_numbers && json_is_invalid_number(json)) {\n            json_set_token_error(token, json, \"invalid number\");\n            return;\n        }\n        json_next_number_token(json, token);\n        return;\n    } else if (!strncmp(json->ptr, \"true\", 4)) {\n        token->type = T_BOOLEAN;\n        token->value.boolean = 1;\n        json->ptr += 4;\n        return;\n    } else if (!strncmp(json->ptr, \"false\", 5)) {\n        token->type = T_BOOLEAN;\n        token->value.boolean = 0;\n        json->ptr += 5;\n        return;\n    } else if (!strncmp(json->ptr, \"null\", 4)) {\n        token->type = T_NULL;\n        json->ptr += 4;\n        return;\n    } else if (json->cfg->decode_invalid_numbers &&\n               json_is_invalid_number(json)) {\n        /* When decode_invalid_numbers is enabled, only attempt to process\n         * numbers we know are invalid JSON (Inf, NaN, hex)\n         * This is required to generate an appropriate token error,\n         * otherwise all bad tokens will register as \"invalid number\"\n         */\n        json_next_number_token(json, token);\n        return;\n    }\n\n    /* Token starts with t/f/n but isn't recognised above. */\n    json_set_token_error(token, json, \"invalid token\");\n}\n\n/* This function does not return.\n * DO NOT CALL WITH DYNAMIC MEMORY ALLOCATED.\n * The only supported exception is the temporary parser string\n * json->tmp struct.\n * json and token should exist on the stack somewhere.\n * luaL_error() will long_jmp and release the stack */\nstatic void json_throw_parse_error(lua_State *l, json_parse_t *json,\n                                   const char *exp, json_token_t *token)\n{\n    const char *found;\n\n    strbuf_free(json->tmp);\n\n    if (token->type == T_ERROR)\n        found = token->value.string;\n    else\n        found = json_token_type_name[token->type];\n\n    /* Note: token->index is 0 based, display starting from 1 */\n    luaL_error(l, \"Expected %s but found %s at character %d\",\n               exp, found, token->index + 1);\n}\n\nstatic inline void json_decode_ascend(json_parse_t *json)\n{\n    json->current_depth--;\n}\n\nstatic void json_decode_descend(lua_State *l, json_parse_t *json, int slots)\n{\n    json->current_depth++;\n\n    if (json->current_depth <= json->cfg->decode_max_depth &&\n        lua_checkstack(l, slots)) {\n        return;\n    }\n\n    strbuf_free(json->tmp);\n    luaL_error(l, \"Found too many nested data structures (%d) at character %d\",\n        json->current_depth, json->ptr - json->data);\n}\n\nstatic void json_parse_object_context(lua_State *l, json_parse_t *json)\n{\n    json_token_t token;\n\n    /* 3 slots required:\n     * .., table, key, value */\n    json_decode_descend(l, json, 3);\n\n    lua_newtable(l);\n\n    json_next_token(json, &token);\n\n    /* Handle empty objects */\n    if (token.type == T_OBJ_END) {\n        json_decode_ascend(json);\n        return;\n    }\n\n    while (1) {\n        if (token.type != T_STRING)\n            json_throw_parse_error(l, json, \"object key string\", &token);\n\n        /* Push key */\n        lua_pushlstring(l, token.value.string, token.string_len);\n\n        json_next_token(json, &token);\n        if (token.type != T_COLON)\n            json_throw_parse_error(l, json, \"colon\", &token);\n\n        /* Fetch value */\n        json_next_token(json, &token);\n        json_process_value(l, json, &token);\n\n        /* Set key = value */\n        lua_rawset(l, -3);\n\n        json_next_token(json, &token);\n\n        if (token.type == T_OBJ_END) {\n            json_decode_ascend(json);\n            return;\n        }\n\n        if (token.type != T_COMMA)\n            json_throw_parse_error(l, json, \"comma or object end\", &token);\n\n        json_next_token(json, &token);\n    }\n}\n\n/* Handle the array context */\nstatic void json_parse_array_context(lua_State *l, json_parse_t *json)\n{\n    json_token_t token;\n    int i;\n\n    /* 2 slots required:\n     * .., table, value */\n    json_decode_descend(l, json, 2);\n\n    lua_newtable(l);\n\n    json_next_token(json, &token);\n\n    /* Handle empty arrays */\n    if (token.type == T_ARR_END) {\n        json_decode_ascend(json);\n        return;\n    }\n\n    for (i = 1; ; i++) {\n        json_process_value(l, json, &token);\n        lua_rawseti(l, -2, i);            /* arr[i] = value */\n\n        json_next_token(json, &token);\n\n        if (token.type == T_ARR_END) {\n            json_decode_ascend(json);\n            return;\n        }\n\n        if (token.type != T_COMMA)\n            json_throw_parse_error(l, json, \"comma or array end\", &token);\n\n        json_next_token(json, &token);\n    }\n}\n\n/* Handle the \"value\" context */\nstatic void json_process_value(lua_State *l, json_parse_t *json,\n                               json_token_t *token)\n{\n    switch (token->type) {\n    case T_STRING:\n        lua_pushlstring(l, token->value.string, token->string_len);\n        break;;\n    case T_NUMBER:\n        lua_pushnumber(l, token->value.number);\n        break;;\n    case T_BOOLEAN:\n        lua_pushboolean(l, token->value.boolean);\n        break;;\n    case T_OBJ_BEGIN:\n        json_parse_object_context(l, json);\n        break;;\n    case T_ARR_BEGIN:\n        json_parse_array_context(l, json);\n        break;;\n    case T_NULL:\n        /* In Lua, setting \"t[k] = nil\" will delete k from the table.\n         * Hence a NULL pointer lightuserdata object is used instead */\n        lua_pushlightuserdata(l, NULL);\n        break;;\n    default:\n        json_throw_parse_error(l, json, \"value\", token);\n    }\n}\n\nstatic int json_decode(lua_State *l)\n{\n    json_parse_t json;\n    json_token_t token;\n    size_t json_len;\n\n    luaL_argcheck(l, lua_gettop(l) == 1, 1, \"expected 1 argument\");\n\n    json.cfg = json_fetch_config(l);\n    json.data = luaL_checklstring(l, 1, &json_len);\n    json.current_depth = 0;\n    json.ptr = json.data;\n\n    /* Detect Unicode other than UTF-8 (see RFC 4627, Sec 3)\n     *\n     * CJSON can support any simple data type, hence only the first\n     * character is guaranteed to be ASCII (at worst: '\"'). This is\n     * still enough to detect whether the wrong encoding is in use. */\n    if (json_len >= 2 && (!json.data[0] || !json.data[1]))\n        luaL_error(l, \"JSON parser does not support UTF-16 or UTF-32\");\n\n    /* Ensure the temporary buffer can hold the entire string.\n     * This means we no longer need to do length checks since the decoded\n     * string must be smaller than the entire json string */\n    json.tmp = strbuf_new(json_len);\n\n    json_next_token(&json, &token);\n    json_process_value(l, &json, &token);\n\n    /* Ensure there is no more input left */\n    json_next_token(&json, &token);\n\n    if (token.type != T_END)\n        json_throw_parse_error(l, &json, \"the end\", &token);\n\n    strbuf_free(json.tmp);\n\n    return 1;\n}\n\n/* ===== INITIALISATION ===== */\n\n#if !defined(LUA_VERSION_NUM) || LUA_VERSION_NUM < 502\n/* Compatibility for Lua 5.1.\n *\n * luaL_setfuncs() is used to create a module table where the functions have\n * json_config_t as their first upvalue. Code borrowed from Lua 5.2 source. */\nstatic void luaL_setfuncs (lua_State *l, const luaL_Reg *reg, int nup)\n{\n    int i;\n\n    luaL_checkstack(l, nup, \"too many upvalues\");\n    for (; reg->name != NULL; reg++) {  /* fill the table with given functions */\n        for (i = 0; i < nup; i++)  /* copy upvalues to the top */\n            lua_pushvalue(l, -nup);\n        lua_pushcclosure(l, reg->func, nup);  /* closure with those upvalues */\n        lua_setfield(l, -(nup + 2), reg->name);\n    }\n    lua_pop(l, nup);  /* remove upvalues */\n}\n#endif\n\n/* Call target function in protected mode with all supplied args.\n * Assumes target function only returns a single non-nil value.\n * Convert and return thrown errors as: nil, \"error message\" */\nstatic int json_protect_conversion(lua_State *l)\n{\n    int err;\n\n    /* Deliberately throw an error for invalid arguments */\n    luaL_argcheck(l, lua_gettop(l) == 1, 1, \"expected 1 argument\");\n\n    /* pcall() the function stored as upvalue(1) */\n    lua_pushvalue(l, lua_upvalueindex(1));\n    lua_insert(l, 1);\n    err = lua_pcall(l, 1, 1, 0);\n    if (!err)\n        return 1;\n\n    if (err == LUA_ERRRUN) {\n        lua_pushnil(l);\n        lua_insert(l, -2);\n        return 2;\n    }\n\n    /* Since we are not using a custom error handler, the only remaining\n     * errors are memory related */\n    return luaL_error(l, \"Memory allocation error in CJSON protected call\");\n}\n\n/* Return cjson module table */\nstatic int lua_cjson_new(lua_State *l)\n{\n    luaL_Reg reg[] = {\n        { \"encode\", json_encode },\n        { \"decode\", json_decode },\n        { \"encode_sparse_array\", json_cfg_encode_sparse_array },\n        { \"encode_max_depth\", json_cfg_encode_max_depth },\n        { \"decode_max_depth\", json_cfg_decode_max_depth },\n        { \"encode_number_precision\", json_cfg_encode_number_precision },\n        { \"encode_keep_buffer\", json_cfg_encode_keep_buffer },\n        { \"encode_invalid_numbers\", json_cfg_encode_invalid_numbers },\n        { \"decode_invalid_numbers\", json_cfg_decode_invalid_numbers },\n        { \"new\", lua_cjson_new },\n        { NULL, NULL }\n    };\n\n    /* Initialise number conversions */\n    fpconv_init();\n\n    /* cjson module table */\n    lua_newtable(l);\n\n    /* Register functions with config data as upvalue */\n    json_create_config(l);\n    luaL_setfuncs(l, reg, 1);\n\n    /* Set cjson.null */\n    lua_pushlightuserdata(l, NULL);\n    lua_setfield(l, -2, \"null\");\n\n    /* Set module name / version fields */\n    lua_pushliteral(l, CJSON_MODNAME);\n    lua_setfield(l, -2, \"_NAME\");\n    lua_pushliteral(l, CJSON_VERSION);\n    lua_setfield(l, -2, \"_VERSION\");\n\n    return 1;\n}\n\n/* Return cjson.safe module table */\nstatic int lua_cjson_safe_new(lua_State *l)\n{\n    const char *func[] = { \"decode\", \"encode\", NULL };\n    int i;\n\n    lua_cjson_new(l);\n\n    /* Fix new() method */\n    lua_pushcfunction(l, lua_cjson_safe_new);\n    lua_setfield(l, -2, \"new\");\n\n    for (i = 0; func[i]; i++) {\n        lua_getfield(l, -1, func[i]);\n        lua_pushcclosure(l, json_protect_conversion, 1);\n        lua_setfield(l, -2, func[i]);\n    }\n\n    return 1;\n}\n\nint luaopen_cjson(lua_State *l)\n{\n    lua_cjson_new(l);\n\n#ifdef ENABLE_CJSON_GLOBAL\n    /* Register a global \"cjson\" table. */\n    lua_pushvalue(l, -1);\n    lua_setglobal(l, CJSON_MODNAME);\n#endif\n\n    /* Return cjson table */\n    return 1;\n}\n\nint luaopen_cjson_safe(lua_State *l)\n{\n    lua_cjson_safe_new(l);\n\n    /* Return cjson.safe table */\n    return 1;\n}\n\n/* vi:ai et sw=4 ts=4:\n */\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.8/deps/lua/src/lua_cmsgpack.c",
    "content": "#include <math.h>\n#include <stdlib.h>\n#include <stdint.h>\n#include <string.h>\n#include <assert.h>\n\n#include \"lua.h\"\n#include \"lauxlib.h\"\n\n#define LUACMSGPACK_NAME        \"cmsgpack\"\n#define LUACMSGPACK_SAFE_NAME   \"cmsgpack_safe\"\n#define LUACMSGPACK_VERSION     \"lua-cmsgpack 0.4.0\"\n#define LUACMSGPACK_COPYRIGHT   \"Copyright (C) 2012, Salvatore Sanfilippo\"\n#define LUACMSGPACK_DESCRIPTION \"MessagePack C implementation for Lua\"\n\n/* Allows a preprocessor directive to override MAX_NESTING */\n#ifndef LUACMSGPACK_MAX_NESTING\n    #define LUACMSGPACK_MAX_NESTING  16 /* Max tables nesting. */\n#endif\n\n/* Check if float or double can be an integer without loss of precision */\n#define IS_INT_TYPE_EQUIVALENT(x, T) (!isinf(x) && (T)(x) == (x))\n\n#define IS_INT64_EQUIVALENT(x) IS_INT_TYPE_EQUIVALENT(x, int64_t)\n#define IS_INT_EQUIVALENT(x) IS_INT_TYPE_EQUIVALENT(x, int)\n\n/* If size of pointer is equal to a 4 byte integer, we're on 32 bits. */\n#if UINTPTR_MAX == UINT_MAX\n    #define BITS_32 1\n#else\n    #define BITS_32 0\n#endif\n\n#if BITS_32\n    #define lua_pushunsigned(L, n) lua_pushnumber(L, n)\n#else\n    #define lua_pushunsigned(L, n) lua_pushinteger(L, n)\n#endif\n\n/* =============================================================================\n * MessagePack implementation and bindings for Lua 5.1/5.2.\n * Copyright(C) 2012 Salvatore Sanfilippo <antirez@gmail.com>\n *\n * http://github.com/antirez/lua-cmsgpack\n *\n * For MessagePack specification check the following web site:\n * http://wiki.msgpack.org/display/MSGPACK/Format+specification\n *\n * See Copyright Notice at the end of this file.\n *\n * CHANGELOG:\n * 19-Feb-2012 (ver 0.1.0): Initial release.\n * 20-Feb-2012 (ver 0.2.0): Tables encoding improved.\n * 20-Feb-2012 (ver 0.2.1): Minor bug fixing.\n * 20-Feb-2012 (ver 0.3.0): Module renamed lua-cmsgpack (was lua-msgpack).\n * 04-Apr-2014 (ver 0.3.1): Lua 5.2 support and minor bug fix.\n * 07-Apr-2014 (ver 0.4.0): Multiple pack/unpack, lua allocator, efficiency.\n * ========================================================================== */\n\n/* -------------------------- Endian conversion --------------------------------\n * We use it only for floats and doubles, all the other conversions performed\n * in an endian independent fashion. So the only thing we need is a function\n * that swaps a binary string if arch is little endian (and left it untouched\n * otherwise). */\n\n/* Reverse memory bytes if arch is little endian. Given the conceptual\n * simplicity of the Lua build system we prefer check for endianess at runtime.\n * The performance difference should be acceptable. */\nvoid memrevifle(void *ptr, size_t len) {\n    unsigned char   *p = (unsigned char *)ptr,\n                    *e = (unsigned char *)p+len-1,\n                    aux;\n    int test = 1;\n    unsigned char *testp = (unsigned char*) &test;\n\n    if (testp[0] == 0) return; /* Big endian, nothing to do. */\n    len /= 2;\n    while(len--) {\n        aux = *p;\n        *p = *e;\n        *e = aux;\n        p++;\n        e--;\n    }\n}\n\n/* ---------------------------- String buffer ----------------------------------\n * This is a simple implementation of string buffers. The only operation\n * supported is creating empty buffers and appending bytes to it.\n * The string buffer uses 2x preallocation on every realloc for O(N) append\n * behavior.  */\n\ntypedef struct mp_buf {\n    unsigned char *b;\n    size_t len, free;\n} mp_buf;\n\nvoid *mp_realloc(lua_State *L, void *target, size_t osize,size_t nsize) {\n    void *(*local_realloc) (void *, void *, size_t osize, size_t nsize) = NULL;\n    void *ud;\n\n    local_realloc = lua_getallocf(L, &ud);\n\n    return local_realloc(ud, target, osize, nsize);\n}\n\nmp_buf *mp_buf_new(lua_State *L) {\n    mp_buf *buf = NULL;\n\n    /* Old size = 0; new size = sizeof(*buf) */\n    buf = (mp_buf*)mp_realloc(L, NULL, 0, sizeof(*buf));\n\n    buf->b = NULL;\n    buf->len = buf->free = 0;\n    return buf;\n}\n\nvoid mp_buf_append(lua_State *L, mp_buf *buf, const unsigned char *s, size_t len) {\n    if (buf->free < len) {\n        size_t newsize = (buf->len+len)*2;\n\n        buf->b = (unsigned char*)mp_realloc(L, buf->b, buf->len + buf->free, newsize);\n        buf->free = newsize - buf->len;\n    }\n    memcpy(buf->b+buf->len,s,len);\n    buf->len += len;\n    buf->free -= len;\n}\n\nvoid mp_buf_free(lua_State *L, mp_buf *buf) {\n    mp_realloc(L, buf->b, buf->len + buf->free, 0); /* realloc to 0 = free */\n    mp_realloc(L, buf, sizeof(*buf), 0);\n}\n\n/* ---------------------------- String cursor ----------------------------------\n * This simple data structure is used for parsing. Basically you create a cursor\n * using a string pointer and a length, then it is possible to access the\n * current string position with cursor->p, check the remaining length\n * in cursor->left, and finally consume more string using\n * mp_cur_consume(cursor,len), to advance 'p' and subtract 'left'.\n * An additional field cursor->error is set to zero on initialization and can\n * be used to report errors. */\n\n#define MP_CUR_ERROR_NONE   0\n#define MP_CUR_ERROR_EOF    1   /* Not enough data to complete operation. */\n#define MP_CUR_ERROR_BADFMT 2   /* Bad data format */\n\ntypedef struct mp_cur {\n    const unsigned char *p;\n    size_t left;\n    int err;\n} mp_cur;\n\nvoid mp_cur_init(mp_cur *cursor, const unsigned char *s, size_t len) {\n    cursor->p = s;\n    cursor->left = len;\n    cursor->err = MP_CUR_ERROR_NONE;\n}\n\n#define mp_cur_consume(_c,_len) do { _c->p += _len; _c->left -= _len; } while(0)\n\n/* When there is not enough room we set an error in the cursor and return. This\n * is very common across the code so we have a macro to make the code look\n * a bit simpler. */\n#define mp_cur_need(_c,_len) do { \\\n    if (_c->left < _len) { \\\n        _c->err = MP_CUR_ERROR_EOF; \\\n        return; \\\n    } \\\n} while(0)\n\n/* ------------------------- Low level MP encoding -------------------------- */\n\nvoid mp_encode_bytes(lua_State *L, mp_buf *buf, const unsigned char *s, size_t len) {\n    unsigned char hdr[5];\n    int hdrlen;\n\n    if (len < 32) {\n        hdr[0] = 0xa0 | (len&0xff); /* fix raw */\n        hdrlen = 1;\n    } else if (len <= 0xff) {\n        hdr[0] = 0xd9;\n        hdr[1] = len;\n        hdrlen = 2;\n    } else if (len <= 0xffff) {\n        hdr[0] = 0xda;\n        hdr[1] = (len&0xff00)>>8;\n        hdr[2] = len&0xff;\n        hdrlen = 3;\n    } else {\n        hdr[0] = 0xdb;\n        hdr[1] = (len&0xff000000)>>24;\n        hdr[2] = (len&0xff0000)>>16;\n        hdr[3] = (len&0xff00)>>8;\n        hdr[4] = len&0xff;\n        hdrlen = 5;\n    }\n    mp_buf_append(L,buf,hdr,hdrlen);\n    mp_buf_append(L,buf,s,len);\n}\n\n/* we assume IEEE 754 internal format for single and double precision floats. */\nvoid mp_encode_double(lua_State *L, mp_buf *buf, double d) {\n    unsigned char b[9];\n    float f = d;\n\n    assert(sizeof(f) == 4 && sizeof(d) == 8);\n    if (d == (double)f) {\n        b[0] = 0xca;    /* float IEEE 754 */\n        memcpy(b+1,&f,4);\n        memrevifle(b+1,4);\n        mp_buf_append(L,buf,b,5);\n    } else if (sizeof(d) == 8) {\n        b[0] = 0xcb;    /* double IEEE 754 */\n        memcpy(b+1,&d,8);\n        memrevifle(b+1,8);\n        mp_buf_append(L,buf,b,9);\n    }\n}\n\nvoid mp_encode_int(lua_State *L, mp_buf *buf, int64_t n) {\n    unsigned char b[9];\n    int enclen;\n\n    if (n >= 0) {\n        if (n <= 127) {\n            b[0] = n & 0x7f;    /* positive fixnum */\n            enclen = 1;\n        } else if (n <= 0xff) {\n            b[0] = 0xcc;        /* uint 8 */\n            b[1] = n & 0xff;\n            enclen = 2;\n        } else if (n <= 0xffff) {\n            b[0] = 0xcd;        /* uint 16 */\n            b[1] = (n & 0xff00) >> 8;\n            b[2] = n & 0xff;\n            enclen = 3;\n        } else if (n <= 0xffffffffLL) {\n            b[0] = 0xce;        /* uint 32 */\n            b[1] = (n & 0xff000000) >> 24;\n            b[2] = (n & 0xff0000) >> 16;\n            b[3] = (n & 0xff00) >> 8;\n            b[4] = n & 0xff;\n            enclen = 5;\n        } else {\n            b[0] = 0xcf;        /* uint 64 */\n            b[1] = (n & 0xff00000000000000LL) >> 56;\n            b[2] = (n & 0xff000000000000LL) >> 48;\n            b[3] = (n & 0xff0000000000LL) >> 40;\n            b[4] = (n & 0xff00000000LL) >> 32;\n            b[5] = (n & 0xff000000) >> 24;\n            b[6] = (n & 0xff0000) >> 16;\n            b[7] = (n & 0xff00) >> 8;\n            b[8] = n & 0xff;\n            enclen = 9;\n        }\n    } else {\n        if (n >= -32) {\n            b[0] = ((signed char)n);   /* negative fixnum */\n            enclen = 1;\n        } else if (n >= -128) {\n            b[0] = 0xd0;        /* int 8 */\n            b[1] = n & 0xff;\n            enclen = 2;\n        } else if (n >= -32768) {\n            b[0] = 0xd1;        /* int 16 */\n            b[1] = (n & 0xff00) >> 8;\n            b[2] = n & 0xff;\n            enclen = 3;\n        } else if (n >= -2147483648LL) {\n            b[0] = 0xd2;        /* int 32 */\n            b[1] = (n & 0xff000000) >> 24;\n            b[2] = (n & 0xff0000) >> 16;\n            b[3] = (n & 0xff00) >> 8;\n            b[4] = n & 0xff;\n            enclen = 5;\n        } else {\n            b[0] = 0xd3;        /* int 64 */\n            b[1] = (n & 0xff00000000000000LL) >> 56;\n            b[2] = (n & 0xff000000000000LL) >> 48;\n            b[3] = (n & 0xff0000000000LL) >> 40;\n            b[4] = (n & 0xff00000000LL) >> 32;\n            b[5] = (n & 0xff000000) >> 24;\n            b[6] = (n & 0xff0000) >> 16;\n            b[7] = (n & 0xff00) >> 8;\n            b[8] = n & 0xff;\n            enclen = 9;\n        }\n    }\n    mp_buf_append(L,buf,b,enclen);\n}\n\nvoid mp_encode_array(lua_State *L, mp_buf *buf, int64_t n) {\n    unsigned char b[5];\n    int enclen;\n\n    if (n <= 15) {\n        b[0] = 0x90 | (n & 0xf);    /* fix array */\n        enclen = 1;\n    } else if (n <= 65535) {\n        b[0] = 0xdc;                /* array 16 */\n        b[1] = (n & 0xff00) >> 8;\n        b[2] = n & 0xff;\n        enclen = 3;\n    } else {\n        b[0] = 0xdd;                /* array 32 */\n        b[1] = (n & 0xff000000) >> 24;\n        b[2] = (n & 0xff0000) >> 16;\n        b[3] = (n & 0xff00) >> 8;\n        b[4] = n & 0xff;\n        enclen = 5;\n    }\n    mp_buf_append(L,buf,b,enclen);\n}\n\nvoid mp_encode_map(lua_State *L, mp_buf *buf, int64_t n) {\n    unsigned char b[5];\n    int enclen;\n\n    if (n <= 15) {\n        b[0] = 0x80 | (n & 0xf);    /* fix map */\n        enclen = 1;\n    } else if (n <= 65535) {\n        b[0] = 0xde;                /* map 16 */\n        b[1] = (n & 0xff00) >> 8;\n        b[2] = n & 0xff;\n        enclen = 3;\n    } else {\n        b[0] = 0xdf;                /* map 32 */\n        b[1] = (n & 0xff000000) >> 24;\n        b[2] = (n & 0xff0000) >> 16;\n        b[3] = (n & 0xff00) >> 8;\n        b[4] = n & 0xff;\n        enclen = 5;\n    }\n    mp_buf_append(L,buf,b,enclen);\n}\n\n/* --------------------------- Lua types encoding --------------------------- */\n\nvoid mp_encode_lua_string(lua_State *L, mp_buf *buf) {\n    size_t len;\n    const char *s;\n\n    s = lua_tolstring(L,-1,&len);\n    mp_encode_bytes(L,buf,(const unsigned char*)s,len);\n}\n\nvoid mp_encode_lua_bool(lua_State *L, mp_buf *buf) {\n    unsigned char b = lua_toboolean(L,-1) ? 0xc3 : 0xc2;\n    mp_buf_append(L,buf,&b,1);\n}\n\n/* Lua 5.3 has a built in 64-bit integer type */\nvoid mp_encode_lua_integer(lua_State *L, mp_buf *buf) {\n#if (LUA_VERSION_NUM < 503) && BITS_32\n    lua_Number i = lua_tonumber(L,-1);\n#else\n    lua_Integer i = lua_tointeger(L,-1);\n#endif\n    mp_encode_int(L, buf, (int64_t)i);\n}\n\n/* Lua 5.2 and lower only has 64-bit doubles, so we need to\n * detect if the double may be representable as an int\n * for Lua < 5.3 */\nvoid mp_encode_lua_number(lua_State *L, mp_buf *buf) {\n    lua_Number n = lua_tonumber(L,-1);\n\n    if (IS_INT64_EQUIVALENT(n)) {\n        mp_encode_lua_integer(L, buf);\n    } else {\n        mp_encode_double(L,buf,(double)n);\n    }\n}\n\nvoid mp_encode_lua_type(lua_State *L, mp_buf *buf, int level);\n\n/* Convert a lua table into a message pack list. */\nvoid mp_encode_lua_table_as_array(lua_State *L, mp_buf *buf, int level) {\n#if LUA_VERSION_NUM < 502\n    size_t len = lua_objlen(L,-1), j;\n#else\n    size_t len = lua_rawlen(L,-1), j;\n#endif\n\n    mp_encode_array(L,buf,len);\n    for (j = 1; j <= len; j++) {\n        lua_pushnumber(L,j);\n        lua_gettable(L,-2);\n        mp_encode_lua_type(L,buf,level+1);\n    }\n}\n\n/* Convert a lua table into a message pack key-value map. */\nvoid mp_encode_lua_table_as_map(lua_State *L, mp_buf *buf, int level) {\n    size_t len = 0;\n\n    /* First step: count keys into table. No other way to do it with the\n     * Lua API, we need to iterate a first time. Note that an alternative\n     * would be to do a single run, and then hack the buffer to insert the\n     * map opcodes for message pack. Too hackish for this lib. */\n    lua_pushnil(L);\n    while(lua_next(L,-2)) {\n        lua_pop(L,1); /* remove value, keep key for next iteration. */\n        len++;\n    }\n\n    /* Step two: actually encoding of the map. */\n    mp_encode_map(L,buf,len);\n    lua_pushnil(L);\n    while(lua_next(L,-2)) {\n        /* Stack: ... key value */\n        lua_pushvalue(L,-2); /* Stack: ... key value key */\n        mp_encode_lua_type(L,buf,level+1); /* encode key */\n        mp_encode_lua_type(L,buf,level+1); /* encode val */\n    }\n}\n\n/* Returns true if the Lua table on top of the stack is exclusively composed\n * of keys from numerical keys from 1 up to N, with N being the total number\n * of elements, without any hole in the middle. */\nint table_is_an_array(lua_State *L) {\n    int count = 0, max = 0;\n#if LUA_VERSION_NUM < 503\n    lua_Number n;\n#else\n    lua_Integer n;\n#endif\n\n    /* Stack top on function entry */\n    int stacktop;\n\n    stacktop = lua_gettop(L);\n\n    lua_pushnil(L);\n    while(lua_next(L,-2)) {\n        /* Stack: ... key value */\n        lua_pop(L,1); /* Stack: ... key */\n        /* The <= 0 check is valid here because we're comparing indexes. */\n#if LUA_VERSION_NUM < 503\n        if ((LUA_TNUMBER != lua_type(L,-1)) || (n = lua_tonumber(L, -1)) <= 0 ||\n            !IS_INT_EQUIVALENT(n))\n#else\n        if (!lua_isinteger(L,-1) || (n = lua_tointeger(L, -1)) <= 0)\n#endif\n        {\n            lua_settop(L, stacktop);\n            return 0;\n        }\n        max = (n > max ? n : max);\n        count++;\n    }\n    /* We have the total number of elements in \"count\". Also we have\n     * the max index encountered in \"max\". We can't reach this code\n     * if there are indexes <= 0. If you also note that there can not be\n     * repeated keys into a table, you have that if max==count you are sure\n     * that there are all the keys form 1 to count (both included). */\n    lua_settop(L, stacktop);\n    return max == count;\n}\n\n/* If the length operator returns non-zero, that is, there is at least\n * an object at key '1', we serialize to message pack list. Otherwise\n * we use a map. */\nvoid mp_encode_lua_table(lua_State *L, mp_buf *buf, int level) {\n    if (table_is_an_array(L))\n        mp_encode_lua_table_as_array(L,buf,level);\n    else\n        mp_encode_lua_table_as_map(L,buf,level);\n}\n\nvoid mp_encode_lua_null(lua_State *L, mp_buf *buf) {\n    unsigned char b[1];\n\n    b[0] = 0xc0;\n    mp_buf_append(L,buf,b,1);\n}\n\nvoid mp_encode_lua_type(lua_State *L, mp_buf *buf, int level) {\n    int t = lua_type(L,-1);\n\n    /* Limit the encoding of nested tables to a specified maximum depth, so that\n     * we survive when called against circular references in tables. */\n    if (t == LUA_TTABLE && level == LUACMSGPACK_MAX_NESTING) t = LUA_TNIL;\n    switch(t) {\n    case LUA_TSTRING: mp_encode_lua_string(L,buf); break;\n    case LUA_TBOOLEAN: mp_encode_lua_bool(L,buf); break;\n    case LUA_TNUMBER:\n    #if LUA_VERSION_NUM < 503\n        mp_encode_lua_number(L,buf); break;\n    #else\n        if (lua_isinteger(L, -1)) {\n            mp_encode_lua_integer(L, buf);\n        } else {\n            mp_encode_lua_number(L, buf);\n        }\n        break;\n    #endif\n    case LUA_TTABLE: mp_encode_lua_table(L,buf,level); break;\n    default: mp_encode_lua_null(L,buf); break;\n    }\n    lua_pop(L,1);\n}\n\n/*\n * Packs all arguments as a stream for multiple upacking later.\n * Returns error if no arguments provided.\n */\nint mp_pack(lua_State *L) {\n    int nargs = lua_gettop(L);\n    int i;\n    mp_buf *buf;\n\n    if (nargs == 0)\n        return luaL_argerror(L, 0, \"MessagePack pack needs input.\");\n\n    buf = mp_buf_new(L);\n    for(i = 1; i <= nargs; i++) {\n        /* Copy argument i to top of stack for _encode processing;\n         * the encode function pops it from the stack when complete. */\n        lua_pushvalue(L, i);\n\n        mp_encode_lua_type(L,buf,0);\n\n        lua_pushlstring(L,(char*)buf->b,buf->len);\n\n        /* Reuse the buffer for the next operation by\n         * setting its free count to the total buffer size\n         * and the current position to zero. */\n        buf->free += buf->len;\n        buf->len = 0;\n    }\n    mp_buf_free(L, buf);\n\n    /* Concatenate all nargs buffers together */\n    lua_concat(L, nargs);\n    return 1;\n}\n\n/* ------------------------------- Decoding --------------------------------- */\n\nvoid mp_decode_to_lua_type(lua_State *L, mp_cur *c);\n\nvoid mp_decode_to_lua_array(lua_State *L, mp_cur *c, size_t len) {\n    assert(len <= UINT_MAX);\n    int index = 1;\n\n    lua_newtable(L);\n    while(len--) {\n        lua_pushnumber(L,index++);\n        mp_decode_to_lua_type(L,c);\n        if (c->err) return;\n        lua_settable(L,-3);\n    }\n}\n\nvoid mp_decode_to_lua_hash(lua_State *L, mp_cur *c, size_t len) {\n    assert(len <= UINT_MAX);\n    lua_newtable(L);\n    while(len--) {\n        mp_decode_to_lua_type(L,c); /* key */\n        if (c->err) return;\n        mp_decode_to_lua_type(L,c); /* value */\n        if (c->err) return;\n        lua_settable(L,-3);\n    }\n}\n\n/* Decode a Message Pack raw object pointed by the string cursor 'c' to\n * a Lua type, that is left as the only result on the stack. */\nvoid mp_decode_to_lua_type(lua_State *L, mp_cur *c) {\n    mp_cur_need(c,1);\n\n    /* If we return more than 18 elements, we must resize the stack to\n     * fit all our return values.  But, there is no way to\n     * determine how many objects a msgpack will unpack to up front, so\n     * we request a +1 larger stack on each iteration (noop if stack is\n     * big enough, and when stack does require resize it doubles in size) */\n    luaL_checkstack(L, 1,\n        \"too many return values at once; \"\n        \"use unpack_one or unpack_limit instead.\");\n\n    switch(c->p[0]) {\n    case 0xcc:  /* uint 8 */\n        mp_cur_need(c,2);\n        lua_pushunsigned(L,c->p[1]);\n        mp_cur_consume(c,2);\n        break;\n    case 0xd0:  /* int 8 */\n        mp_cur_need(c,2);\n        lua_pushinteger(L,(signed char)c->p[1]);\n        mp_cur_consume(c,2);\n        break;\n    case 0xcd:  /* uint 16 */\n        mp_cur_need(c,3);\n        lua_pushunsigned(L,\n            (c->p[1] << 8) |\n             c->p[2]);\n        mp_cur_consume(c,3);\n        break;\n    case 0xd1:  /* int 16 */\n        mp_cur_need(c,3);\n        lua_pushinteger(L,(int16_t)\n            (c->p[1] << 8) |\n             c->p[2]);\n        mp_cur_consume(c,3);\n        break;\n    case 0xce:  /* uint 32 */\n        mp_cur_need(c,5);\n        lua_pushunsigned(L,\n            ((uint32_t)c->p[1] << 24) |\n            ((uint32_t)c->p[2] << 16) |\n            ((uint32_t)c->p[3] << 8) |\n             (uint32_t)c->p[4]);\n        mp_cur_consume(c,5);\n        break;\n    case 0xd2:  /* int 32 */\n        mp_cur_need(c,5);\n        lua_pushinteger(L,\n            ((int32_t)c->p[1] << 24) |\n            ((int32_t)c->p[2] << 16) |\n            ((int32_t)c->p[3] << 8) |\n             (int32_t)c->p[4]);\n        mp_cur_consume(c,5);\n        break;\n    case 0xcf:  /* uint 64 */\n        mp_cur_need(c,9);\n        lua_pushunsigned(L,\n            ((uint64_t)c->p[1] << 56) |\n            ((uint64_t)c->p[2] << 48) |\n            ((uint64_t)c->p[3] << 40) |\n            ((uint64_t)c->p[4] << 32) |\n            ((uint64_t)c->p[5] << 24) |\n            ((uint64_t)c->p[6] << 16) |\n            ((uint64_t)c->p[7] << 8) |\n             (uint64_t)c->p[8]);\n        mp_cur_consume(c,9);\n        break;\n    case 0xd3:  /* int 64 */\n        mp_cur_need(c,9);\n#if LUA_VERSION_NUM < 503\n        lua_pushnumber(L,\n#else\n        lua_pushinteger(L,\n#endif\n            ((int64_t)c->p[1] << 56) |\n            ((int64_t)c->p[2] << 48) |\n            ((int64_t)c->p[3] << 40) |\n            ((int64_t)c->p[4] << 32) |\n            ((int64_t)c->p[5] << 24) |\n            ((int64_t)c->p[6] << 16) |\n            ((int64_t)c->p[7] << 8) |\n             (int64_t)c->p[8]);\n        mp_cur_consume(c,9);\n        break;\n    case 0xc0:  /* nil */\n        lua_pushnil(L);\n        mp_cur_consume(c,1);\n        break;\n    case 0xc3:  /* true */\n        lua_pushboolean(L,1);\n        mp_cur_consume(c,1);\n        break;\n    case 0xc2:  /* false */\n        lua_pushboolean(L,0);\n        mp_cur_consume(c,1);\n        break;\n    case 0xca:  /* float */\n        mp_cur_need(c,5);\n        assert(sizeof(float) == 4);\n        {\n            float f;\n            memcpy(&f,c->p+1,4);\n            memrevifle(&f,4);\n            lua_pushnumber(L,f);\n            mp_cur_consume(c,5);\n        }\n        break;\n    case 0xcb:  /* double */\n        mp_cur_need(c,9);\n        assert(sizeof(double) == 8);\n        {\n            double d;\n            memcpy(&d,c->p+1,8);\n            memrevifle(&d,8);\n            lua_pushnumber(L,d);\n            mp_cur_consume(c,9);\n        }\n        break;\n    case 0xd9:  /* raw 8 */\n        mp_cur_need(c,2);\n        {\n            size_t l = c->p[1];\n            mp_cur_need(c,2+l);\n            lua_pushlstring(L,(char*)c->p+2,l);\n            mp_cur_consume(c,2+l);\n        }\n        break;\n    case 0xda:  /* raw 16 */\n        mp_cur_need(c,3);\n        {\n            size_t l = (c->p[1] << 8) | c->p[2];\n            mp_cur_need(c,3+l);\n            lua_pushlstring(L,(char*)c->p+3,l);\n            mp_cur_consume(c,3+l);\n        }\n        break;\n    case 0xdb:  /* raw 32 */\n        mp_cur_need(c,5);\n        {\n            size_t l = ((size_t)c->p[1] << 24) |\n                       ((size_t)c->p[2] << 16) |\n                       ((size_t)c->p[3] << 8) |\n                       (size_t)c->p[4];\n            mp_cur_consume(c,5);\n            mp_cur_need(c,l);\n            lua_pushlstring(L,(char*)c->p,l);\n            mp_cur_consume(c,l);\n        }\n        break;\n    case 0xdc:  /* array 16 */\n        mp_cur_need(c,3);\n        {\n            size_t l = (c->p[1] << 8) | c->p[2];\n            mp_cur_consume(c,3);\n            mp_decode_to_lua_array(L,c,l);\n        }\n        break;\n    case 0xdd:  /* array 32 */\n        mp_cur_need(c,5);\n        {\n            size_t l = ((size_t)c->p[1] << 24) |\n                       ((size_t)c->p[2] << 16) |\n                       ((size_t)c->p[3] << 8) |\n                       (size_t)c->p[4];\n            mp_cur_consume(c,5);\n            mp_decode_to_lua_array(L,c,l);\n        }\n        break;\n    case 0xde:  /* map 16 */\n        mp_cur_need(c,3);\n        {\n            size_t l = (c->p[1] << 8) | c->p[2];\n            mp_cur_consume(c,3);\n            mp_decode_to_lua_hash(L,c,l);\n        }\n        break;\n    case 0xdf:  /* map 32 */\n        mp_cur_need(c,5);\n        {\n            size_t l = ((size_t)c->p[1] << 24) |\n                       ((size_t)c->p[2] << 16) |\n                       ((size_t)c->p[3] << 8) |\n                       (size_t)c->p[4];\n            mp_cur_consume(c,5);\n            mp_decode_to_lua_hash(L,c,l);\n        }\n        break;\n    default:    /* types that can't be idenitified by first byte value. */\n        if ((c->p[0] & 0x80) == 0) {   /* positive fixnum */\n            lua_pushunsigned(L,c->p[0]);\n            mp_cur_consume(c,1);\n        } else if ((c->p[0] & 0xe0) == 0xe0) {  /* negative fixnum */\n            lua_pushinteger(L,(signed char)c->p[0]);\n            mp_cur_consume(c,1);\n        } else if ((c->p[0] & 0xe0) == 0xa0) {  /* fix raw */\n            size_t l = c->p[0] & 0x1f;\n            mp_cur_need(c,1+l);\n            lua_pushlstring(L,(char*)c->p+1,l);\n            mp_cur_consume(c,1+l);\n        } else if ((c->p[0] & 0xf0) == 0x90) {  /* fix map */\n            size_t l = c->p[0] & 0xf;\n            mp_cur_consume(c,1);\n            mp_decode_to_lua_array(L,c,l);\n        } else if ((c->p[0] & 0xf0) == 0x80) {  /* fix map */\n            size_t l = c->p[0] & 0xf;\n            mp_cur_consume(c,1);\n            mp_decode_to_lua_hash(L,c,l);\n        } else {\n            c->err = MP_CUR_ERROR_BADFMT;\n        }\n    }\n}\n\nint mp_unpack_full(lua_State *L, int limit, int offset) {\n    size_t len;\n    const char *s;\n    mp_cur c;\n    int cnt; /* Number of objects unpacked */\n    int decode_all = (!limit && !offset);\n\n    s = luaL_checklstring(L,1,&len); /* if no match, exits */\n\n    if (offset < 0 || limit < 0) /* requesting negative off or lim is invalid */\n        return luaL_error(L,\n            \"Invalid request to unpack with offset of %d and limit of %d.\",\n            offset, len);\n    else if (offset > len)\n        return luaL_error(L,\n            \"Start offset %d greater than input length %d.\", offset, len);\n\n    if (decode_all) limit = INT_MAX;\n\n    mp_cur_init(&c,(const unsigned char *)s+offset,len-offset);\n\n    /* We loop over the decode because this could be a stream\n     * of multiple top-level values serialized together */\n    for(cnt = 0; c.left > 0 && cnt < limit; cnt++) {\n        mp_decode_to_lua_type(L,&c);\n\n        if (c.err == MP_CUR_ERROR_EOF) {\n            return luaL_error(L,\"Missing bytes in input.\");\n        } else if (c.err == MP_CUR_ERROR_BADFMT) {\n            return luaL_error(L,\"Bad data format in input.\");\n        }\n    }\n\n    if (!decode_all) {\n        /* c->left is the remaining size of the input buffer.\n         * subtract the entire buffer size from the unprocessed size\n         * to get our next start offset */\n        int offset = len - c.left;\n        /* Return offset -1 when we have have processed the entire buffer. */\n        lua_pushinteger(L, c.left == 0 ? -1 : offset);\n        /* Results are returned with the arg elements still\n         * in place. Lua takes care of only returning\n         * elements above the args for us.\n         * In this case, we have one arg on the stack\n         * for this function, so we insert our first return\n         * value at position 2. */\n        lua_insert(L, 2);\n        cnt += 1; /* increase return count by one to make room for offset */\n    }\n\n    return cnt;\n}\n\nint mp_unpack(lua_State *L) {\n    return mp_unpack_full(L, 0, 0);\n}\n\nint mp_unpack_one(lua_State *L) {\n    int offset = luaL_optinteger(L, 2, 0);\n    /* Variable pop because offset may not exist */\n    lua_pop(L, lua_gettop(L)-1);\n    return mp_unpack_full(L, 1, offset);\n}\n\nint mp_unpack_limit(lua_State *L) {\n    int limit = luaL_checkinteger(L, 2);\n    int offset = luaL_optinteger(L, 3, 0);\n    /* Variable pop because offset may not exist */\n    lua_pop(L, lua_gettop(L)-1);\n\n    return mp_unpack_full(L, limit, offset);\n}\n\nint mp_safe(lua_State *L) {\n    int argc, err, total_results;\n\n    argc = lua_gettop(L);\n\n    /* This adds our function to the bottom of the stack\n     * (the \"call this function\" position) */\n    lua_pushvalue(L, lua_upvalueindex(1));\n    lua_insert(L, 1);\n\n    err = lua_pcall(L, argc, LUA_MULTRET, 0);\n    total_results = lua_gettop(L);\n\n    if (!err) {\n        return total_results;\n    } else {\n        lua_pushnil(L);\n        lua_insert(L,-2);\n        return 2;\n    }\n}\n\n/* -------------------------------------------------------------------------- */\nconst struct luaL_Reg cmds[] = {\n    {\"pack\", mp_pack},\n    {\"unpack\", mp_unpack},\n    {\"unpack_one\", mp_unpack_one},\n    {\"unpack_limit\", mp_unpack_limit},\n    {0}\n};\n\nint luaopen_create(lua_State *L) {\n    int i;\n    /* Manually construct our module table instead of\n     * relying on _register or _newlib */\n    lua_newtable(L);\n\n    for (i = 0; i < (sizeof(cmds)/sizeof(*cmds) - 1); i++) {\n        lua_pushcfunction(L, cmds[i].func);\n        lua_setfield(L, -2, cmds[i].name);\n    }\n\n    /* Add metadata */\n    lua_pushliteral(L, LUACMSGPACK_NAME);\n    lua_setfield(L, -2, \"_NAME\");\n    lua_pushliteral(L, LUACMSGPACK_VERSION);\n    lua_setfield(L, -2, \"_VERSION\");\n    lua_pushliteral(L, LUACMSGPACK_COPYRIGHT);\n    lua_setfield(L, -2, \"_COPYRIGHT\");\n    lua_pushliteral(L, LUACMSGPACK_DESCRIPTION);\n    lua_setfield(L, -2, \"_DESCRIPTION\");\n    return 1;\n}\n\nLUALIB_API int luaopen_cmsgpack(lua_State *L) {\n    luaopen_create(L);\n\n#if LUA_VERSION_NUM < 502\n    /* Register name globally for 5.1 */\n    lua_pushvalue(L, -1);\n    lua_setglobal(L, LUACMSGPACK_NAME);\n#endif\n\n    return 1;\n}\n\nLUALIB_API int luaopen_cmsgpack_safe(lua_State *L) {\n    int i;\n\n    luaopen_cmsgpack(L);\n\n    /* Wrap all functions in the safe handler */\n    for (i = 0; i < (sizeof(cmds)/sizeof(*cmds) - 1); i++) {\n        lua_getfield(L, -1, cmds[i].name);\n        lua_pushcclosure(L, mp_safe, 1);\n        lua_setfield(L, -2, cmds[i].name);\n    }\n\n#if LUA_VERSION_NUM < 502\n    /* Register name globally for 5.1 */\n    lua_pushvalue(L, -1);\n    lua_setglobal(L, LUACMSGPACK_SAFE_NAME);\n#endif\n\n    return 1;\n}\n\n/******************************************************************************\n* Copyright (C) 2012 Salvatore Sanfilippo.  All rights reserved.\n*\n* Permission is hereby granted, free of charge, to any person obtaining\n* a copy of this software and associated documentation files (the\n* \"Software\"), to deal in the Software without restriction, including\n* without limitation the rights to use, copy, modify, merge, publish,\n* distribute, sublicense, and/or sell copies of the Software, and to\n* permit persons to whom the Software is furnished to do so, subject to\n* the following conditions:\n*\n* The above copyright notice and this permission notice shall be\n* included in all copies or substantial portions of the Software.\n*\n* THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND,\n* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\n* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.\n* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY\n* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,\n* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE\n* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n******************************************************************************/\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.8/deps/lua/src/lua_struct.c",
    "content": "/*\n** {======================================================\n** Library for packing/unpacking structures.\n** $Id: struct.c,v 1.4 2012/07/04 18:54:29 roberto Exp $\n** See Copyright Notice at the end of this file\n** =======================================================\n*/\n/*\n** Valid formats:\n** > - big endian\n** < - little endian\n** ![num] - alignment\n** x - pading\n** b/B - signed/unsigned byte\n** h/H - signed/unsigned short\n** l/L - signed/unsigned long\n** T   - size_t\n** i/In - signed/unsigned integer with size `n' (default is size of int)\n** cn - sequence of `n' chars (from/to a string); when packing, n==0 means\n        the whole string; when unpacking, n==0 means use the previous\n        read number as the string length\n** s - zero-terminated string\n** f - float\n** d - double\n** ' ' - ignored\n*/\n\n\n#include <assert.h>\n#include <ctype.h>\n#include <limits.h>\n#include <stddef.h>\n#include <string.h>\n\n\n#include \"lua.h\"\n#include \"lauxlib.h\"\n\n\n#if (LUA_VERSION_NUM >= 502)\n\n#define luaL_register(L,n,f)\tluaL_newlib(L,f)\n\n#endif\n\n\n/* basic integer type */\n#if !defined(STRUCT_INT)\n#define STRUCT_INT\tlong\n#endif\n\ntypedef STRUCT_INT Inttype;\n\n/* corresponding unsigned version */\ntypedef unsigned STRUCT_INT Uinttype;\n\n\n/* maximum size (in bytes) for integral types */\n#define MAXINTSIZE\t32\n\n/* is 'x' a power of 2? */\n#define isp2(x)\t\t((x) > 0 && ((x) & ((x) - 1)) == 0)\n\n/* dummy structure to get alignment requirements */\nstruct cD {\n  char c;\n  double d;\n};\n\n\n#define PADDING\t\t(sizeof(struct cD) - sizeof(double))\n#define MAXALIGN  \t(PADDING > sizeof(int) ? PADDING : sizeof(int))\n\n\n/* endian options */\n#define BIG\t0\n#define LITTLE\t1\n\n\nstatic union {\n  int dummy;\n  char endian;\n} const native = {1};\n\n\ntypedef struct Header {\n  int endian;\n  int align;\n} Header;\n\n\nstatic int getnum (lua_State *L, const char **fmt, int df) {\n  if (!isdigit(**fmt))  /* no number? */\n    return df;  /* return default value */\n  else {\n    int a = 0;\n    do {\n      if (a > (INT_MAX / 10) || a * 10 > (INT_MAX - (**fmt - '0')))\n        luaL_error(L, \"integral size overflow\");\n      a = a*10 + *((*fmt)++) - '0';\n    } while (isdigit(**fmt));\n    return a;\n  }\n}\n\n\n#define defaultoptions(h)\t((h)->endian = native.endian, (h)->align = 1)\n\n\n\nstatic size_t optsize (lua_State *L, char opt, const char **fmt) {\n  switch (opt) {\n    case 'B': case 'b': return sizeof(char);\n    case 'H': case 'h': return sizeof(short);\n    case 'L': case 'l': return sizeof(long);\n    case 'T': return sizeof(size_t);\n    case 'f':  return sizeof(float);\n    case 'd':  return sizeof(double);\n    case 'x': return 1;\n    case 'c': return getnum(L, fmt, 1);\n    case 'i': case 'I': {\n      int sz = getnum(L, fmt, sizeof(int));\n      if (sz > MAXINTSIZE)\n        luaL_error(L, \"integral size %d is larger than limit of %d\",\n                       sz, MAXINTSIZE);\n      return sz;\n    }\n    default: return 0;  /* other cases do not need alignment */\n  }\n}\n\n\n/*\n** return number of bytes needed to align an element of size 'size'\n** at current position 'len'\n*/\nstatic int gettoalign (size_t len, Header *h, int opt, size_t size) {\n  if (size == 0 || opt == 'c') return 0;\n  if (size > (size_t)h->align)\n    size = h->align;  /* respect max. alignment */\n  return (size - (len & (size - 1))) & (size - 1);\n}\n\n\n/*\n** options to control endianess and alignment\n*/\nstatic void controloptions (lua_State *L, int opt, const char **fmt,\n                            Header *h) {\n  switch (opt) {\n    case  ' ': return;  /* ignore white spaces */\n    case '>': h->endian = BIG; return;\n    case '<': h->endian = LITTLE; return;\n    case '!': {\n      int a = getnum(L, fmt, MAXALIGN);\n      if (!isp2(a))\n        luaL_error(L, \"alignment %d is not a power of 2\", a);\n      h->align = a;\n      return;\n    }\n    default: {\n      const char *msg = lua_pushfstring(L, \"invalid format option '%c'\", opt);\n      luaL_argerror(L, 1, msg);\n    }\n  }\n}\n\n\nstatic void putinteger (lua_State *L, luaL_Buffer *b, int arg, int endian,\n                        int size) {\n  lua_Number n = luaL_checknumber(L, arg);\n  Uinttype value;\n  char buff[MAXINTSIZE];\n  if (n < 0)\n    value = (Uinttype)(Inttype)n;\n  else\n    value = (Uinttype)n;\n  if (endian == LITTLE) {\n    int i;\n    for (i = 0; i < size; i++) {\n      buff[i] = (value & 0xff);\n      value >>= 8;\n    }\n  }\n  else {\n    int i;\n    for (i = size - 1; i >= 0; i--) {\n      buff[i] = (value & 0xff);\n      value >>= 8;\n    }\n  }\n  luaL_addlstring(b, buff, size);\n}\n\n\nstatic void correctbytes (char *b, int size, int endian) {\n  if (endian != native.endian) {\n    int i = 0;\n    while (i < --size) {\n      char temp = b[i];\n      b[i++] = b[size];\n      b[size] = temp;\n    }\n  }\n}\n\n\nstatic int b_pack (lua_State *L) {\n  luaL_Buffer b;\n  const char *fmt = luaL_checkstring(L, 1);\n  Header h;\n  int arg = 2;\n  size_t totalsize = 0;\n  defaultoptions(&h);\n  lua_pushnil(L);  /* mark to separate arguments from string buffer */\n  luaL_buffinit(L, &b);\n  while (*fmt != '\\0') {\n    int opt = *fmt++;\n    size_t size = optsize(L, opt, &fmt);\n    int toalign = gettoalign(totalsize, &h, opt, size);\n    totalsize += toalign;\n    while (toalign-- > 0) luaL_addchar(&b, '\\0');\n    switch (opt) {\n      case 'b': case 'B': case 'h': case 'H':\n      case 'l': case 'L': case 'T': case 'i': case 'I': {  /* integer types */\n        putinteger(L, &b, arg++, h.endian, size);\n        break;\n      }\n      case 'x': {\n        luaL_addchar(&b, '\\0');\n        break;\n      }\n      case 'f': {\n        float f = (float)luaL_checknumber(L, arg++);\n        correctbytes((char *)&f, size, h.endian);\n        luaL_addlstring(&b, (char *)&f, size);\n        break;\n      }\n      case 'd': {\n        double d = luaL_checknumber(L, arg++);\n        correctbytes((char *)&d, size, h.endian);\n        luaL_addlstring(&b, (char *)&d, size);\n        break;\n      }\n      case 'c': case 's': {\n        size_t l;\n        const char *s = luaL_checklstring(L, arg++, &l);\n        if (size == 0) size = l;\n        luaL_argcheck(L, l >= (size_t)size, arg, \"string too short\");\n        luaL_addlstring(&b, s, size);\n        if (opt == 's') {\n          luaL_addchar(&b, '\\0');  /* add zero at the end */\n          size++;\n        }\n        break;\n      }\n      default: controloptions(L, opt, &fmt, &h);\n    }\n    totalsize += size;\n  }\n  luaL_pushresult(&b);\n  return 1;\n}\n\n\nstatic lua_Number getinteger (const char *buff, int endian,\n                        int issigned, int size) {\n  Uinttype l = 0;\n  int i;\n  if (endian == BIG) {\n    for (i = 0; i < size; i++) {\n      l <<= 8;\n      l |= (Uinttype)(unsigned char)buff[i];\n    }\n  }\n  else {\n    for (i = size - 1; i >= 0; i--) {\n      l <<= 8;\n      l |= (Uinttype)(unsigned char)buff[i];\n    }\n  }\n  if (!issigned)\n    return (lua_Number)l;\n  else {  /* signed format */\n    Uinttype mask = (Uinttype)(~((Uinttype)0)) << (size*8 - 1);\n    if (l & mask)  /* negative value? */\n      l |= mask;  /* signal extension */\n    return (lua_Number)(Inttype)l;\n  }\n}\n\n\nstatic int b_unpack (lua_State *L) {\n  Header h;\n  const char *fmt = luaL_checkstring(L, 1);\n  size_t ld;\n  const char *data = luaL_checklstring(L, 2, &ld);\n  size_t pos = luaL_optinteger(L, 3, 1) - 1;\n  defaultoptions(&h);\n  lua_settop(L, 2);\n  while (*fmt) {\n    int opt = *fmt++;\n    size_t size = optsize(L, opt, &fmt);\n    pos += gettoalign(pos, &h, opt, size);\n    luaL_argcheck(L, pos+size <= ld, 2, \"data string too short\");\n    luaL_checkstack(L, 1, \"too many results\");\n    switch (opt) {\n      case 'b': case 'B': case 'h': case 'H':\n      case 'l': case 'L': case 'T': case 'i':  case 'I': {  /* integer types */\n        int issigned = islower(opt);\n        lua_Number res = getinteger(data+pos, h.endian, issigned, size);\n        lua_pushnumber(L, res);\n        break;\n      }\n      case 'x': {\n        break;\n      }\n      case 'f': {\n        float f;\n        memcpy(&f, data+pos, size);\n        correctbytes((char *)&f, sizeof(f), h.endian);\n        lua_pushnumber(L, f);\n        break;\n      }\n      case 'd': {\n        double d;\n        memcpy(&d, data+pos, size);\n        correctbytes((char *)&d, sizeof(d), h.endian);\n        lua_pushnumber(L, d);\n        break;\n      }\n      case 'c': {\n        if (size == 0) {\n          if (!lua_isnumber(L, -1))\n            luaL_error(L, \"format `c0' needs a previous size\");\n          size = lua_tonumber(L, -1);\n          lua_pop(L, 1);\n          luaL_argcheck(L, pos+size <= ld, 2, \"data string too short\");\n        }\n        lua_pushlstring(L, data+pos, size);\n        break;\n      }\n      case 's': {\n        const char *e = (const char *)memchr(data+pos, '\\0', ld - pos);\n        if (e == NULL)\n          luaL_error(L, \"unfinished string in data\");\n        size = (e - (data+pos)) + 1;\n        lua_pushlstring(L, data+pos, size - 1);\n        break;\n      }\n      default: controloptions(L, opt, &fmt, &h);\n    }\n    pos += size;\n  }\n  lua_pushinteger(L, pos + 1);\n  return lua_gettop(L) - 2;\n}\n\n\nstatic int b_size (lua_State *L) {\n  Header h;\n  const char *fmt = luaL_checkstring(L, 1);\n  size_t pos = 0;\n  defaultoptions(&h);\n  while (*fmt) {\n    int opt = *fmt++;\n    size_t size = optsize(L, opt, &fmt);\n    pos += gettoalign(pos, &h, opt, size);\n    if (opt == 's')\n      luaL_argerror(L, 1, \"option 's' has no fixed size\");\n    else if (opt == 'c' && size == 0)\n      luaL_argerror(L, 1, \"option 'c0' has no fixed size\");\n    if (!isalnum(opt))\n      controloptions(L, opt, &fmt, &h);\n    pos += size;\n  }\n  lua_pushinteger(L, pos);\n  return 1;\n}\n\n/* }====================================================== */\n\n\n\nstatic const struct luaL_Reg thislib[] = {\n  {\"pack\", b_pack},\n  {\"unpack\", b_unpack},\n  {\"size\", b_size},\n  {NULL, NULL}\n};\n\n\nLUALIB_API int luaopen_struct (lua_State *L);\n\nLUALIB_API int luaopen_struct (lua_State *L) {\n  luaL_register(L, \"struct\", thislib);\n  return 1;\n}\n\n\n/******************************************************************************\n* Copyright (C) 2010-2012 Lua.org, PUC-Rio.  All rights reserved.\n*\n* Permission is hereby granted, free of charge, to any person obtaining\n* a copy of this software and associated documentation files (the\n* \"Software\"), to deal in the Software without restriction, including\n* without limitation the rights to use, copy, modify, merge, publish,\n* distribute, sublicense, and/or sell copies of the Software, and to\n* permit persons to whom the Software is furnished to do so, subject to\n* the following conditions:\n*\n* The above copyright notice and this permission notice shall be\n* included in all copies or substantial portions of the Software.\n*\n* THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND,\n* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\n* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.\n* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY\n* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,\n* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE\n* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n******************************************************************************/\n\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.8/deps/lua/src/luac.c",
    "content": "/*\n** $Id: luac.c,v 1.54 2006/06/02 17:37:11 lhf Exp $\n** Lua compiler (saves bytecodes to files; also list bytecodes)\n** See Copyright Notice in lua.h\n*/\n\n#include <errno.h>\n#include <stdio.h>\n#include <stdlib.h>\n#include <string.h>\n\n#define luac_c\n#define LUA_CORE\n\n#include \"lua.h\"\n#include \"lauxlib.h\"\n\n#include \"ldo.h\"\n#include \"lfunc.h\"\n#include \"lmem.h\"\n#include \"lobject.h\"\n#include \"lopcodes.h\"\n#include \"lstring.h\"\n#include \"lundump.h\"\n\n#define PROGNAME\t\"luac\"\t\t/* default program name */\n#define\tOUTPUT\t\tPROGNAME \".out\"\t/* default output file */\n\nstatic int listing=0;\t\t\t/* list bytecodes? */\nstatic int dumping=1;\t\t\t/* dump bytecodes? */\nstatic int stripping=0;\t\t\t/* strip debug information? */\nstatic char Output[]={ OUTPUT };\t/* default output file name */\nstatic const char* output=Output;\t/* actual output file name */\nstatic const char* progname=PROGNAME;\t/* actual program name */\n\nstatic void fatal(const char* message)\n{\n fprintf(stderr,\"%s: %s\\n\",progname,message);\n exit(EXIT_FAILURE);\n}\n\nstatic void cannot(const char* what)\n{\n fprintf(stderr,\"%s: cannot %s %s: %s\\n\",progname,what,output,strerror(errno));\n exit(EXIT_FAILURE);\n}\n\nstatic void usage(const char* message)\n{\n if (*message=='-')\n  fprintf(stderr,\"%s: unrecognized option \" LUA_QS \"\\n\",progname,message);\n else\n  fprintf(stderr,\"%s: %s\\n\",progname,message);\n fprintf(stderr,\n \"usage: %s [options] [filenames].\\n\"\n \"Available options are:\\n\"\n \"  -        process stdin\\n\"\n \"  -l       list\\n\"\n \"  -o name  output to file \" LUA_QL(\"name\") \" (default is \\\"%s\\\")\\n\"\n \"  -p       parse only\\n\"\n \"  -s       strip debug information\\n\"\n \"  -v       show version information\\n\"\n \"  --       stop handling options\\n\",\n progname,Output);\n exit(EXIT_FAILURE);\n}\n\n#define\tIS(s)\t(strcmp(argv[i],s)==0)\n\nstatic int doargs(int argc, char* argv[])\n{\n int i;\n int version=0;\n if (argv[0]!=NULL && *argv[0]!=0) progname=argv[0];\n for (i=1; i<argc; i++)\n {\n  if (*argv[i]!='-')\t\t\t/* end of options; keep it */\n   break;\n  else if (IS(\"--\"))\t\t\t/* end of options; skip it */\n  {\n   ++i;\n   if (version) ++version;\n   break;\n  }\n  else if (IS(\"-\"))\t\t\t/* end of options; use stdin */\n   break;\n  else if (IS(\"-l\"))\t\t\t/* list */\n   ++listing;\n  else if (IS(\"-o\"))\t\t\t/* output file */\n  {\n   output=argv[++i];\n   if (output==NULL || *output==0) usage(LUA_QL(\"-o\") \" needs argument\");\n   if (IS(\"-\")) output=NULL;\n  }\n  else if (IS(\"-p\"))\t\t\t/* parse only */\n   dumping=0;\n  else if (IS(\"-s\"))\t\t\t/* strip debug information */\n   stripping=1;\n  else if (IS(\"-v\"))\t\t\t/* show version */\n   ++version;\n  else\t\t\t\t\t/* unknown option */\n   usage(argv[i]);\n }\n if (i==argc && (listing || !dumping))\n {\n  dumping=0;\n  argv[--i]=Output;\n }\n if (version)\n {\n  printf(\"%s  %s\\n\",LUA_RELEASE,LUA_COPYRIGHT);\n  if (version==argc-1) exit(EXIT_SUCCESS);\n }\n return i;\n}\n\n#define toproto(L,i) (clvalue(L->top+(i))->l.p)\n\nstatic const Proto* combine(lua_State* L, int n)\n{\n if (n==1)\n  return toproto(L,-1);\n else\n {\n  int i,pc;\n  Proto* f=luaF_newproto(L);\n  setptvalue2s(L,L->top,f); incr_top(L);\n  f->source=luaS_newliteral(L,\"=(\" PROGNAME \")\");\n  f->maxstacksize=1;\n  pc=2*n+1;\n  f->code=luaM_newvector(L,pc,Instruction);\n  f->sizecode=pc;\n  f->p=luaM_newvector(L,n,Proto*);\n  f->sizep=n;\n  pc=0;\n  for (i=0; i<n; i++)\n  {\n   f->p[i]=toproto(L,i-n-1);\n   f->code[pc++]=CREATE_ABx(OP_CLOSURE,0,i);\n   f->code[pc++]=CREATE_ABC(OP_CALL,0,1,1);\n  }\n  f->code[pc++]=CREATE_ABC(OP_RETURN,0,1,0);\n  return f;\n }\n}\n\nstatic int writer(lua_State* L, const void* p, size_t size, void* u)\n{\n UNUSED(L);\n return (fwrite(p,size,1,(FILE*)u)!=1) && (size!=0);\n}\n\nstruct Smain {\n int argc;\n char** argv;\n};\n\nstatic int pmain(lua_State* L)\n{\n struct Smain* s = (struct Smain*)lua_touserdata(L, 1);\n int argc=s->argc;\n char** argv=s->argv;\n const Proto* f;\n int i;\n if (!lua_checkstack(L,argc)) fatal(\"too many input files\");\n for (i=0; i<argc; i++)\n {\n  const char* filename=IS(\"-\") ? NULL : argv[i];\n  if (luaL_loadfile(L,filename)!=0) fatal(lua_tostring(L,-1));\n }\n f=combine(L,argc);\n if (listing) luaU_print(f,listing>1);\n if (dumping)\n {\n  FILE* D= (output==NULL) ? stdout : fopen(output,\"wb\");\n  if (D==NULL) cannot(\"open\");\n  lua_lock(L);\n  luaU_dump(L,f,writer,D,stripping);\n  lua_unlock(L);\n  if (ferror(D)) cannot(\"write\");\n  if (fclose(D)) cannot(\"close\");\n }\n return 0;\n}\n\nint main(int argc, char* argv[])\n{\n lua_State* L;\n struct Smain s;\n int i=doargs(argc,argv);\n argc-=i; argv+=i;\n if (argc<=0) usage(\"no input files given\");\n L=lua_open();\n if (L==NULL) fatal(\"not enough memory for state\");\n s.argc=argc;\n s.argv=argv;\n if (lua_cpcall(L,pmain,&s)!=0) fatal(lua_tostring(L,-1));\n lua_close(L);\n return EXIT_SUCCESS;\n}\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.8/deps/lua/src/luaconf.h",
    "content": "/*\n** $Id: luaconf.h,v 1.82.1.7 2008/02/11 16:25:08 roberto Exp $\n** Configuration file for Lua\n** See Copyright Notice in lua.h\n*/\n\n\n#ifndef lconfig_h\n#define lconfig_h\n\n#include <limits.h>\n#include <stddef.h>\n\n\n/*\n** ==================================================================\n** Search for \"@@\" to find all configurable definitions.\n** ===================================================================\n*/\n\n\n/*\n@@ LUA_ANSI controls the use of non-ansi features.\n** CHANGE it (define it) if you want Lua to avoid the use of any\n** non-ansi feature or library.\n*/\n#if defined(__STRICT_ANSI__)\n#define LUA_ANSI\n#endif\n\n\n#if !defined(LUA_ANSI) && defined(_WIN32)\n#define LUA_WIN\n#endif\n\n#if defined(LUA_USE_LINUX)\n#define LUA_USE_POSIX\n#define LUA_USE_DLOPEN\t\t/* needs an extra library: -ldl */\n#define LUA_USE_READLINE\t/* needs some extra libraries */\n#endif\n\n#if defined(LUA_USE_MACOSX)\n#define LUA_USE_POSIX\n#define LUA_DL_DYLD\t\t/* does not need extra library */\n#endif\n\n\n\n/*\n@@ LUA_USE_POSIX includes all functionallity listed as X/Open System\n@* Interfaces Extension (XSI).\n** CHANGE it (define it) if your system is XSI compatible.\n*/\n#if defined(LUA_USE_POSIX)\n#define LUA_USE_MKSTEMP\n#define LUA_USE_ISATTY\n#define LUA_USE_POPEN\n#define LUA_USE_ULONGJMP\n#endif\n\n\n/*\n@@ LUA_PATH and LUA_CPATH are the names of the environment variables that\n@* Lua check to set its paths.\n@@ LUA_INIT is the name of the environment variable that Lua\n@* checks for initialization code.\n** CHANGE them if you want different names.\n*/\n#define LUA_PATH        \"LUA_PATH\"\n#define LUA_CPATH       \"LUA_CPATH\"\n#define LUA_INIT\t\"LUA_INIT\"\n\n\n/*\n@@ LUA_PATH_DEFAULT is the default path that Lua uses to look for\n@* Lua libraries.\n@@ LUA_CPATH_DEFAULT is the default path that Lua uses to look for\n@* C libraries.\n** CHANGE them if your machine has a non-conventional directory\n** hierarchy or if you want to install your libraries in\n** non-conventional directories.\n*/\n#if defined(_WIN32)\n/*\n** In Windows, any exclamation mark ('!') in the path is replaced by the\n** path of the directory of the executable file of the current process.\n*/\n#define LUA_LDIR\t\"!\\\\lua\\\\\"\n#define LUA_CDIR\t\"!\\\\\"\n#define LUA_PATH_DEFAULT  \\\n\t\t\".\\\\?.lua;\"  LUA_LDIR\"?.lua;\"  LUA_LDIR\"?\\\\init.lua;\" \\\n\t\t             LUA_CDIR\"?.lua;\"  LUA_CDIR\"?\\\\init.lua\"\n#define LUA_CPATH_DEFAULT \\\n\t\".\\\\?.dll;\"  LUA_CDIR\"?.dll;\" LUA_CDIR\"loadall.dll\"\n\n#else\n#define LUA_ROOT\t\"/usr/local/\"\n#define LUA_LDIR\tLUA_ROOT \"share/lua/5.1/\"\n#define LUA_CDIR\tLUA_ROOT \"lib/lua/5.1/\"\n#define LUA_PATH_DEFAULT  \\\n\t\t\"./?.lua;\"  LUA_LDIR\"?.lua;\"  LUA_LDIR\"?/init.lua;\" \\\n\t\t            LUA_CDIR\"?.lua;\"  LUA_CDIR\"?/init.lua\"\n#define LUA_CPATH_DEFAULT \\\n\t\"./?.so;\"  LUA_CDIR\"?.so;\" LUA_CDIR\"loadall.so\"\n#endif\n\n\n/*\n@@ LUA_DIRSEP is the directory separator (for submodules).\n** CHANGE it if your machine does not use \"/\" as the directory separator\n** and is not Windows. (On Windows Lua automatically uses \"\\\".)\n*/\n#if defined(_WIN32)\n#define LUA_DIRSEP\t\"\\\\\"\n#else\n#define LUA_DIRSEP\t\"/\"\n#endif\n\n\n/*\n@@ LUA_PATHSEP is the character that separates templates in a path.\n@@ LUA_PATH_MARK is the string that marks the substitution points in a\n@* template.\n@@ LUA_EXECDIR in a Windows path is replaced by the executable's\n@* directory.\n@@ LUA_IGMARK is a mark to ignore all before it when bulding the\n@* luaopen_ function name.\n** CHANGE them if for some reason your system cannot use those\n** characters. (E.g., if one of those characters is a common character\n** in file/directory names.) Probably you do not need to change them.\n*/\n#define LUA_PATHSEP\t\";\"\n#define LUA_PATH_MARK\t\"?\"\n#define LUA_EXECDIR\t\"!\"\n#define LUA_IGMARK\t\"-\"\n\n\n/*\n@@ LUA_INTEGER is the integral type used by lua_pushinteger/lua_tointeger.\n** CHANGE that if ptrdiff_t is not adequate on your machine. (On most\n** machines, ptrdiff_t gives a good choice between int or long.)\n*/\n#define LUA_INTEGER\tptrdiff_t\n\n\n/*\n@@ LUA_API is a mark for all core API functions.\n@@ LUALIB_API is a mark for all standard library functions.\n** CHANGE them if you need to define those functions in some special way.\n** For instance, if you want to create one Windows DLL with the core and\n** the libraries, you may want to use the following definition (define\n** LUA_BUILD_AS_DLL to get it).\n*/\n#if defined(LUA_BUILD_AS_DLL)\n\n#if defined(LUA_CORE) || defined(LUA_LIB)\n#define LUA_API __declspec(dllexport)\n#else\n#define LUA_API __declspec(dllimport)\n#endif\n\n#else\n\n#define LUA_API\t\textern\n\n#endif\n\n/* more often than not the libs go together with the core */\n#define LUALIB_API\tLUA_API\n\n\n/*\n@@ LUAI_FUNC is a mark for all extern functions that are not to be\n@* exported to outside modules.\n@@ LUAI_DATA is a mark for all extern (const) variables that are not to\n@* be exported to outside modules.\n** CHANGE them if you need to mark them in some special way. Elf/gcc\n** (versions 3.2 and later) mark them as \"hidden\" to optimize access\n** when Lua is compiled as a shared library.\n*/\n#if defined(luaall_c)\n#define LUAI_FUNC\tstatic\n#define LUAI_DATA\t/* empty */\n\n#elif defined(__GNUC__) && ((__GNUC__*100 + __GNUC_MINOR__) >= 302) && \\\n      defined(__ELF__)\n#define LUAI_FUNC\t__attribute__((visibility(\"hidden\"))) extern\n#define LUAI_DATA\tLUAI_FUNC\n\n#else\n#define LUAI_FUNC\textern\n#define LUAI_DATA\textern\n#endif\n\n\n\n/*\n@@ LUA_QL describes how error messages quote program elements.\n** CHANGE it if you want a different appearance.\n*/\n#define LUA_QL(x)\t\"'\" x \"'\"\n#define LUA_QS\t\tLUA_QL(\"%s\")\n\n\n/*\n@@ LUA_IDSIZE gives the maximum size for the description of the source\n@* of a function in debug information.\n** CHANGE it if you want a different size.\n*/\n#define LUA_IDSIZE\t60\n\n\n/*\n** {==================================================================\n** Stand-alone configuration\n** ===================================================================\n*/\n\n#if defined(lua_c) || defined(luaall_c)\n\n/*\n@@ lua_stdin_is_tty detects whether the standard input is a 'tty' (that\n@* is, whether we're running lua interactively).\n** CHANGE it if you have a better definition for non-POSIX/non-Windows\n** systems.\n*/\n#if defined(LUA_USE_ISATTY)\n#include <unistd.h>\n#define lua_stdin_is_tty()\tisatty(0)\n#elif defined(LUA_WIN)\n#include <io.h>\n#include <stdio.h>\n#define lua_stdin_is_tty()\t_isatty(_fileno(stdin))\n#else\n#define lua_stdin_is_tty()\t1  /* assume stdin is a tty */\n#endif\n\n\n/*\n@@ LUA_PROMPT is the default prompt used by stand-alone Lua.\n@@ LUA_PROMPT2 is the default continuation prompt used by stand-alone Lua.\n** CHANGE them if you want different prompts. (You can also change the\n** prompts dynamically, assigning to globals _PROMPT/_PROMPT2.)\n*/\n#define LUA_PROMPT\t\t\"> \"\n#define LUA_PROMPT2\t\t\">> \"\n\n\n/*\n@@ LUA_PROGNAME is the default name for the stand-alone Lua program.\n** CHANGE it if your stand-alone interpreter has a different name and\n** your system is not able to detect that name automatically.\n*/\n#define LUA_PROGNAME\t\t\"lua\"\n\n\n/*\n@@ LUA_MAXINPUT is the maximum length for an input line in the\n@* stand-alone interpreter.\n** CHANGE it if you need longer lines.\n*/\n#define LUA_MAXINPUT\t512\n\n\n/*\n@@ lua_readline defines how to show a prompt and then read a line from\n@* the standard input.\n@@ lua_saveline defines how to \"save\" a read line in a \"history\".\n@@ lua_freeline defines how to free a line read by lua_readline.\n** CHANGE them if you want to improve this functionality (e.g., by using\n** GNU readline and history facilities).\n*/\n#if defined(LUA_USE_READLINE)\n#include <stdio.h>\n#include <readline/readline.h>\n#include <readline/history.h>\n#define lua_readline(L,b,p)\t((void)L, ((b)=readline(p)) != NULL)\n#define lua_saveline(L,idx) \\\n\tif (lua_strlen(L,idx) > 0)  /* non-empty line? */ \\\n\t  add_history(lua_tostring(L, idx));  /* add it to history */\n#define lua_freeline(L,b)\t((void)L, free(b))\n#else\n#define lua_readline(L,b,p)\t\\\n\t((void)L, fputs(p, stdout), fflush(stdout),  /* show prompt */ \\\n\tfgets(b, LUA_MAXINPUT, stdin) != NULL)  /* get line */\n#define lua_saveline(L,idx)\t{ (void)L; (void)idx; }\n#define lua_freeline(L,b)\t{ (void)L; (void)b; }\n#endif\n\n#endif\n\n/* }================================================================== */\n\n\n/*\n@@ LUAI_GCPAUSE defines the default pause between garbage-collector cycles\n@* as a percentage.\n** CHANGE it if you want the GC to run faster or slower (higher values\n** mean larger pauses which mean slower collection.) You can also change\n** this value dynamically.\n*/\n#define LUAI_GCPAUSE\t200  /* 200% (wait memory to double before next GC) */\n\n\n/*\n@@ LUAI_GCMUL defines the default speed of garbage collection relative to\n@* memory allocation as a percentage.\n** CHANGE it if you want to change the granularity of the garbage\n** collection. (Higher values mean coarser collections. 0 represents\n** infinity, where each step performs a full collection.) You can also\n** change this value dynamically.\n*/\n#define LUAI_GCMUL\t200 /* GC runs 'twice the speed' of memory allocation */\n\n\n\n/*\n@@ LUA_COMPAT_GETN controls compatibility with old getn behavior.\n** CHANGE it (define it) if you want exact compatibility with the\n** behavior of setn/getn in Lua 5.0.\n*/\n#undef LUA_COMPAT_GETN\n\n/*\n@@ LUA_COMPAT_LOADLIB controls compatibility about global loadlib.\n** CHANGE it to undefined as soon as you do not need a global 'loadlib'\n** function (the function is still available as 'package.loadlib').\n*/\n#undef LUA_COMPAT_LOADLIB\n\n/*\n@@ LUA_COMPAT_VARARG controls compatibility with old vararg feature.\n** CHANGE it to undefined as soon as your programs use only '...' to\n** access vararg parameters (instead of the old 'arg' table).\n*/\n#define LUA_COMPAT_VARARG\n\n/*\n@@ LUA_COMPAT_MOD controls compatibility with old math.mod function.\n** CHANGE it to undefined as soon as your programs use 'math.fmod' or\n** the new '%' operator instead of 'math.mod'.\n*/\n#define LUA_COMPAT_MOD\n\n/*\n@@ LUA_COMPAT_LSTR controls compatibility with old long string nesting\n@* facility.\n** CHANGE it to 2 if you want the old behaviour, or undefine it to turn\n** off the advisory error when nesting [[...]].\n*/\n#define LUA_COMPAT_LSTR\t\t1\n\n/*\n@@ LUA_COMPAT_GFIND controls compatibility with old 'string.gfind' name.\n** CHANGE it to undefined as soon as you rename 'string.gfind' to\n** 'string.gmatch'.\n*/\n#define LUA_COMPAT_GFIND\n\n/*\n@@ LUA_COMPAT_OPENLIB controls compatibility with old 'luaL_openlib'\n@* behavior.\n** CHANGE it to undefined as soon as you replace to 'luaL_register'\n** your uses of 'luaL_openlib'\n*/\n#define LUA_COMPAT_OPENLIB\n\n\n\n/*\n@@ luai_apicheck is the assert macro used by the Lua-C API.\n** CHANGE luai_apicheck if you want Lua to perform some checks in the\n** parameters it gets from API calls. This may slow down the interpreter\n** a bit, but may be quite useful when debugging C code that interfaces\n** with Lua. A useful redefinition is to use assert.h.\n*/\n#if defined(LUA_USE_APICHECK)\n#include <assert.h>\n#define luai_apicheck(L,o)\t{ (void)L; assert(o); }\n#else\n#define luai_apicheck(L,o)\t{ (void)L; }\n#endif\n\n\n/*\n@@ LUAI_BITSINT defines the number of bits in an int.\n** CHANGE here if Lua cannot automatically detect the number of bits of\n** your machine. Probably you do not need to change this.\n*/\n/* avoid overflows in comparison */\n#if INT_MAX-20 < 32760\n#define LUAI_BITSINT\t16\n#elif INT_MAX > 2147483640L\n/* int has at least 32 bits */\n#define LUAI_BITSINT\t32\n#else\n#error \"you must define LUA_BITSINT with number of bits in an integer\"\n#endif\n\n\n/*\n@@ LUAI_UINT32 is an unsigned integer with at least 32 bits.\n@@ LUAI_INT32 is an signed integer with at least 32 bits.\n@@ LUAI_UMEM is an unsigned integer big enough to count the total\n@* memory used by Lua.\n@@ LUAI_MEM is a signed integer big enough to count the total memory\n@* used by Lua.\n** CHANGE here if for some weird reason the default definitions are not\n** good enough for your machine. (The definitions in the 'else'\n** part always works, but may waste space on machines with 64-bit\n** longs.) Probably you do not need to change this.\n*/\n#if LUAI_BITSINT >= 32\n#define LUAI_UINT32\tunsigned int\n#define LUAI_INT32\tint\n#define LUAI_MAXINT32\tINT_MAX\n#define LUAI_UMEM\tsize_t\n#define LUAI_MEM\tptrdiff_t\n#else\n/* 16-bit ints */\n#define LUAI_UINT32\tunsigned long\n#define LUAI_INT32\tlong\n#define LUAI_MAXINT32\tLONG_MAX\n#define LUAI_UMEM\tunsigned long\n#define LUAI_MEM\tlong\n#endif\n\n\n/*\n@@ LUAI_MAXCALLS limits the number of nested calls.\n** CHANGE it if you need really deep recursive calls. This limit is\n** arbitrary; its only purpose is to stop infinite recursion before\n** exhausting memory.\n*/\n#define LUAI_MAXCALLS\t20000\n\n\n/*\n@@ LUAI_MAXCSTACK limits the number of Lua stack slots that a C function\n@* can use.\n** CHANGE it if you need lots of (Lua) stack space for your C\n** functions. This limit is arbitrary; its only purpose is to stop C\n** functions to consume unlimited stack space. (must be smaller than\n** -LUA_REGISTRYINDEX)\n*/\n#define LUAI_MAXCSTACK\t8000\n\n\n\n/*\n** {==================================================================\n** CHANGE (to smaller values) the following definitions if your system\n** has a small C stack. (Or you may want to change them to larger\n** values if your system has a large C stack and these limits are\n** too rigid for you.) Some of these constants control the size of\n** stack-allocated arrays used by the compiler or the interpreter, while\n** others limit the maximum number of recursive calls that the compiler\n** or the interpreter can perform. Values too large may cause a C stack\n** overflow for some forms of deep constructs.\n** ===================================================================\n*/\n\n\n/*\n@@ LUAI_MAXCCALLS is the maximum depth for nested C calls (short) and\n@* syntactical nested non-terminals in a program.\n*/\n#define LUAI_MAXCCALLS\t\t200\n\n\n/*\n@@ LUAI_MAXVARS is the maximum number of local variables per function\n@* (must be smaller than 250).\n*/\n#define LUAI_MAXVARS\t\t200\n\n\n/*\n@@ LUAI_MAXUPVALUES is the maximum number of upvalues per function\n@* (must be smaller than 250).\n*/\n#define LUAI_MAXUPVALUES\t60\n\n\n/*\n@@ LUAL_BUFFERSIZE is the buffer size used by the lauxlib buffer system.\n*/\n#define LUAL_BUFFERSIZE\t\tBUFSIZ\n\n/* }================================================================== */\n\n\n\n\n/*\n** {==================================================================\n@@ LUA_NUMBER is the type of numbers in Lua.\n** CHANGE the following definitions only if you want to build Lua\n** with a number type different from double. You may also need to\n** change lua_number2int & lua_number2integer.\n** ===================================================================\n*/\n\n#define LUA_NUMBER_DOUBLE\n#define LUA_NUMBER\tdouble\n\n/*\n@@ LUAI_UACNUMBER is the result of an 'usual argument conversion'\n@* over a number.\n*/\n#define LUAI_UACNUMBER\tdouble\n\n\n/*\n@@ LUA_NUMBER_SCAN is the format for reading numbers.\n@@ LUA_NUMBER_FMT is the format for writing numbers.\n@@ lua_number2str converts a number to a string.\n@@ LUAI_MAXNUMBER2STR is maximum size of previous conversion.\n@@ lua_str2number converts a string to a number.\n*/\n#define LUA_NUMBER_SCAN\t\t\"%lf\"\n#define LUA_NUMBER_FMT\t\t\"%.14g\"\n#define lua_number2str(s,n)\tsprintf((s), LUA_NUMBER_FMT, (n))\n#define LUAI_MAXNUMBER2STR\t32 /* 16 digits, sign, point, and \\0 */\n#define lua_str2number(s,p)\tstrtod((s), (p))\n\n\n/*\n@@ The luai_num* macros define the primitive operations over numbers.\n*/\n#if defined(LUA_CORE)\n#include <math.h>\n#define luai_numadd(a,b)\t((a)+(b))\n#define luai_numsub(a,b)\t((a)-(b))\n#define luai_nummul(a,b)\t((a)*(b))\n#define luai_numdiv(a,b)\t((a)/(b))\n#define luai_nummod(a,b)\t((a) - floor((a)/(b))*(b))\n#define luai_numpow(a,b)\t(pow(a,b))\n#define luai_numunm(a)\t\t(-(a))\n#define luai_numeq(a,b)\t\t((a)==(b))\n#define luai_numlt(a,b)\t\t((a)<(b))\n#define luai_numle(a,b)\t\t((a)<=(b))\n#define luai_numisnan(a)\t(!luai_numeq((a), (a)))\n#endif\n\n\n/*\n@@ lua_number2int is a macro to convert lua_Number to int.\n@@ lua_number2integer is a macro to convert lua_Number to lua_Integer.\n** CHANGE them if you know a faster way to convert a lua_Number to\n** int (with any rounding method and without throwing errors) in your\n** system. In Pentium machines, a naive typecast from double to int\n** in C is extremely slow, so any alternative is worth trying.\n*/\n\n/* On a Pentium, resort to a trick */\n#if defined(LUA_NUMBER_DOUBLE) && !defined(LUA_ANSI) && !defined(__SSE2__) && \\\n    (defined(__i386) || defined (_M_IX86) || defined(__i386__))\n\n/* On a Microsoft compiler, use assembler */\n#if defined(_MSC_VER)\n\n#define lua_number2int(i,d)   __asm fld d   __asm fistp i\n#define lua_number2integer(i,n)\t\tlua_number2int(i, n)\n\n/* the next trick should work on any Pentium, but sometimes clashes\n   with a DirectX idiosyncrasy */\n#else\n\nunion luai_Cast { double l_d; long l_l; };\n#define lua_number2int(i,d) \\\n  { volatile union luai_Cast u; u.l_d = (d) + 6755399441055744.0; (i) = u.l_l; }\n#define lua_number2integer(i,n)\t\tlua_number2int(i, n)\n\n#endif\n\n\n/* this option always works, but may be slow */\n#else\n#define lua_number2int(i,d)\t((i)=(int)(d))\n#define lua_number2integer(i,d)\t((i)=(lua_Integer)(d))\n\n#endif\n\n/* }================================================================== */\n\n\n/*\n@@ LUAI_USER_ALIGNMENT_T is a type that requires maximum alignment.\n** CHANGE it if your system requires alignments larger than double. (For\n** instance, if your system supports long doubles and they must be\n** aligned in 16-byte boundaries, then you should add long double in the\n** union.) Probably you do not need to change this.\n*/\n#define LUAI_USER_ALIGNMENT_T\tunion { double u; void *s; long l; }\n\n\n/*\n@@ LUAI_THROW/LUAI_TRY define how Lua does exception handling.\n** CHANGE them if you prefer to use longjmp/setjmp even with C++\n** or if want/don't to use _longjmp/_setjmp instead of regular\n** longjmp/setjmp. By default, Lua handles errors with exceptions when\n** compiling as C++ code, with _longjmp/_setjmp when asked to use them,\n** and with longjmp/setjmp otherwise.\n*/\n#if defined(__cplusplus)\n/* C++ exceptions */\n#define LUAI_THROW(L,c)\tthrow(c)\n#define LUAI_TRY(L,c,a)\ttry { a } catch(...) \\\n\t{ if ((c)->status == 0) (c)->status = -1; }\n#define luai_jmpbuf\tint  /* dummy variable */\n\n#elif defined(LUA_USE_ULONGJMP)\n/* in Unix, try _longjmp/_setjmp (more efficient) */\n#define LUAI_THROW(L,c)\t_longjmp((c)->b, 1)\n#define LUAI_TRY(L,c,a)\tif (_setjmp((c)->b) == 0) { a }\n#define luai_jmpbuf\tjmp_buf\n\n#else\n/* default handling with long jumps */\n#define LUAI_THROW(L,c)\tlongjmp((c)->b, 1)\n#define LUAI_TRY(L,c,a)\tif (setjmp((c)->b) == 0) { a }\n#define luai_jmpbuf\tjmp_buf\n\n#endif\n\n\n/*\n@@ LUA_MAXCAPTURES is the maximum number of captures that a pattern\n@* can do during pattern-matching.\n** CHANGE it if you need more captures. This limit is arbitrary.\n*/\n#define LUA_MAXCAPTURES\t\t32\n\n\n/*\n@@ lua_tmpnam is the function that the OS library uses to create a\n@* temporary name.\n@@ LUA_TMPNAMBUFSIZE is the maximum size of a name created by lua_tmpnam.\n** CHANGE them if you have an alternative to tmpnam (which is considered\n** insecure) or if you want the original tmpnam anyway.  By default, Lua\n** uses tmpnam except when POSIX is available, where it uses mkstemp.\n*/\n#if defined(loslib_c) || defined(luaall_c)\n\n#if defined(LUA_USE_MKSTEMP)\n#include <unistd.h>\n#define LUA_TMPNAMBUFSIZE\t32\n#define lua_tmpnam(b,e)\t{ \\\n\tstrcpy(b, \"/tmp/lua_XXXXXX\"); \\\n\te = mkstemp(b); \\\n\tif (e != -1) close(e); \\\n\te = (e == -1); }\n\n#else\n#define LUA_TMPNAMBUFSIZE\tL_tmpnam\n#define lua_tmpnam(b,e)\t\t{ e = (tmpnam(b) == NULL); }\n#endif\n\n#endif\n\n\n/*\n@@ lua_popen spawns a new process connected to the current one through\n@* the file streams.\n** CHANGE it if you have a way to implement it in your system.\n*/\n#if defined(LUA_USE_POPEN)\n\n#define lua_popen(L,c,m)\t((void)L, fflush(NULL), popen(c,m))\n#define lua_pclose(L,file)\t((void)L, (pclose(file) != -1))\n\n#elif defined(LUA_WIN)\n\n#define lua_popen(L,c,m)\t((void)L, _popen(c,m))\n#define lua_pclose(L,file)\t((void)L, (_pclose(file) != -1))\n\n#else\n\n#define lua_popen(L,c,m)\t((void)((void)c, m),  \\\n\t\tluaL_error(L, LUA_QL(\"popen\") \" not supported\"), (FILE*)0)\n#define lua_pclose(L,file)\t\t((void)((void)L, file), 0)\n\n#endif\n\n/*\n@@ LUA_DL_* define which dynamic-library system Lua should use.\n** CHANGE here if Lua has problems choosing the appropriate\n** dynamic-library system for your platform (either Windows' DLL, Mac's\n** dyld, or Unix's dlopen). If your system is some kind of Unix, there\n** is a good chance that it has dlopen, so LUA_DL_DLOPEN will work for\n** it.  To use dlopen you also need to adapt the src/Makefile (probably\n** adding -ldl to the linker options), so Lua does not select it\n** automatically.  (When you change the makefile to add -ldl, you must\n** also add -DLUA_USE_DLOPEN.)\n** If you do not want any kind of dynamic library, undefine all these\n** options.\n** By default, _WIN32 gets LUA_DL_DLL and MAC OS X gets LUA_DL_DYLD.\n*/\n#if defined(LUA_USE_DLOPEN)\n#define LUA_DL_DLOPEN\n#endif\n\n#if defined(LUA_WIN)\n#define LUA_DL_DLL\n#endif\n\n\n/*\n@@ LUAI_EXTRASPACE allows you to add user-specific data in a lua_State\n@* (the data goes just *before* the lua_State pointer).\n** CHANGE (define) this if you really need that. This value must be\n** a multiple of the maximum alignment required for your machine.\n*/\n#define LUAI_EXTRASPACE\t\t0\n\n\n/*\n@@ luai_userstate* allow user-specific actions on threads.\n** CHANGE them if you defined LUAI_EXTRASPACE and need to do something\n** extra when a thread is created/deleted/resumed/yielded.\n*/\n#define luai_userstateopen(L)\t\t((void)L)\n#define luai_userstateclose(L)\t\t((void)L)\n#define luai_userstatethread(L,L1)\t((void)L)\n#define luai_userstatefree(L)\t\t((void)L)\n#define luai_userstateresume(L,n)\t((void)L)\n#define luai_userstateyield(L,n)\t((void)L)\n\n\n/*\n@@ LUA_INTFRMLEN is the length modifier for integer conversions\n@* in 'string.format'.\n@@ LUA_INTFRM_T is the integer type correspoding to the previous length\n@* modifier.\n** CHANGE them if your system supports long long or does not support long.\n*/\n\n#if defined(LUA_USELONGLONG)\n\n#define LUA_INTFRMLEN\t\t\"ll\"\n#define LUA_INTFRM_T\t\tlong long\n\n#else\n\n#define LUA_INTFRMLEN\t\t\"l\"\n#define LUA_INTFRM_T\t\tlong\n\n#endif\n\n\n\n/* =================================================================== */\n\n/*\n** Local configuration. You can use this space to add your redefinitions\n** without modifying the main part of the file.\n*/\n\n\n\n#endif\n\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.8/deps/lua/src/lualib.h",
    "content": "/*\n** $Id: lualib.h,v 1.36.1.1 2007/12/27 13:02:25 roberto Exp $\n** Lua standard libraries\n** See Copyright Notice in lua.h\n*/\n\n\n#ifndef lualib_h\n#define lualib_h\n\n#include \"lua.h\"\n\n\n/* Key to file-handle type */\n#define LUA_FILEHANDLE\t\t\"FILE*\"\n\n\n#define LUA_COLIBNAME\t\"coroutine\"\nLUALIB_API int (luaopen_base) (lua_State *L);\n\n#define LUA_TABLIBNAME\t\"table\"\nLUALIB_API int (luaopen_table) (lua_State *L);\n\n#define LUA_IOLIBNAME\t\"io\"\nLUALIB_API int (luaopen_io) (lua_State *L);\n\n#define LUA_OSLIBNAME\t\"os\"\nLUALIB_API int (luaopen_os) (lua_State *L);\n\n#define LUA_STRLIBNAME\t\"string\"\nLUALIB_API int (luaopen_string) (lua_State *L);\n\n#define LUA_MATHLIBNAME\t\"math\"\nLUALIB_API int (luaopen_math) (lua_State *L);\n\n#define LUA_DBLIBNAME\t\"debug\"\nLUALIB_API int (luaopen_debug) (lua_State *L);\n\n#define LUA_LOADLIBNAME\t\"package\"\nLUALIB_API int (luaopen_package) (lua_State *L);\n\n\n/* open all previous libraries */\nLUALIB_API void (luaL_openlibs) (lua_State *L); \n\n\n\n#ifndef lua_assert\n#define lua_assert(x)\t((void)0)\n#endif\n\n\n#endif\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.8/deps/lua/src/lundump.c",
    "content": "/*\n** $Id: lundump.c,v 2.7.1.4 2008/04/04 19:51:41 roberto Exp $\n** load precompiled Lua chunks\n** See Copyright Notice in lua.h\n*/\n\n#include <string.h>\n\n#define lundump_c\n#define LUA_CORE\n\n#include \"lua.h\"\n\n#include \"ldebug.h\"\n#include \"ldo.h\"\n#include \"lfunc.h\"\n#include \"lmem.h\"\n#include \"lobject.h\"\n#include \"lstring.h\"\n#include \"lundump.h\"\n#include \"lzio.h\"\n\ntypedef struct {\n lua_State* L;\n ZIO* Z;\n Mbuffer* b;\n const char* name;\n} LoadState;\n\n#ifdef LUAC_TRUST_BINARIES\n#define IF(c,s)\n#define error(S,s)\n#else\n#define IF(c,s)\t\tif (c) error(S,s)\n\nstatic void error(LoadState* S, const char* why)\n{\n luaO_pushfstring(S->L,\"%s: %s in precompiled chunk\",S->name,why);\n luaD_throw(S->L,LUA_ERRSYNTAX);\n}\n#endif\n\n#define LoadMem(S,b,n,size)\tLoadBlock(S,b,(n)*(size))\n#define\tLoadByte(S)\t\t(lu_byte)LoadChar(S)\n#define LoadVar(S,x)\t\tLoadMem(S,&x,1,sizeof(x))\n#define LoadVector(S,b,n,size)\tLoadMem(S,b,n,size)\n\nstatic void LoadBlock(LoadState* S, void* b, size_t size)\n{\n size_t r=luaZ_read(S->Z,b,size);\n IF (r!=0, \"unexpected end\");\n}\n\nstatic int LoadChar(LoadState* S)\n{\n char x;\n LoadVar(S,x);\n return x;\n}\n\nstatic int LoadInt(LoadState* S)\n{\n int x;\n LoadVar(S,x);\n IF (x<0, \"bad integer\");\n return x;\n}\n\nstatic lua_Number LoadNumber(LoadState* S)\n{\n lua_Number x;\n LoadVar(S,x);\n return x;\n}\n\nstatic TString* LoadString(LoadState* S)\n{\n size_t size;\n LoadVar(S,size);\n if (size==0)\n  return NULL;\n else\n {\n  char* s=luaZ_openspace(S->L,S->b,size);\n  LoadBlock(S,s,size);\n  return luaS_newlstr(S->L,s,size-1);\t\t/* remove trailing '\\0' */\n }\n}\n\nstatic void LoadCode(LoadState* S, Proto* f)\n{\n int n=LoadInt(S);\n f->code=luaM_newvector(S->L,n,Instruction);\n f->sizecode=n;\n LoadVector(S,f->code,n,sizeof(Instruction));\n}\n\nstatic Proto* LoadFunction(LoadState* S, TString* p);\n\nstatic void LoadConstants(LoadState* S, Proto* f)\n{\n int i,n;\n n=LoadInt(S);\n f->k=luaM_newvector(S->L,n,TValue);\n f->sizek=n;\n for (i=0; i<n; i++) setnilvalue(&f->k[i]);\n for (i=0; i<n; i++)\n {\n  TValue* o=&f->k[i];\n  int t=LoadChar(S);\n  switch (t)\n  {\n   case LUA_TNIL:\n   \tsetnilvalue(o);\n\tbreak;\n   case LUA_TBOOLEAN:\n   \tsetbvalue(o,LoadChar(S)!=0);\n\tbreak;\n   case LUA_TNUMBER:\n\tsetnvalue(o,LoadNumber(S));\n\tbreak;\n   case LUA_TSTRING:\n\tsetsvalue2n(S->L,o,LoadString(S));\n\tbreak;\n   default:\n\terror(S,\"bad constant\");\n\tbreak;\n  }\n }\n n=LoadInt(S);\n f->p=luaM_newvector(S->L,n,Proto*);\n f->sizep=n;\n for (i=0; i<n; i++) f->p[i]=NULL;\n for (i=0; i<n; i++) f->p[i]=LoadFunction(S,f->source);\n}\n\nstatic void LoadDebug(LoadState* S, Proto* f)\n{\n int i,n;\n n=LoadInt(S);\n f->lineinfo=luaM_newvector(S->L,n,int);\n f->sizelineinfo=n;\n LoadVector(S,f->lineinfo,n,sizeof(int));\n n=LoadInt(S);\n f->locvars=luaM_newvector(S->L,n,LocVar);\n f->sizelocvars=n;\n for (i=0; i<n; i++) f->locvars[i].varname=NULL;\n for (i=0; i<n; i++)\n {\n  f->locvars[i].varname=LoadString(S);\n  f->locvars[i].startpc=LoadInt(S);\n  f->locvars[i].endpc=LoadInt(S);\n }\n n=LoadInt(S);\n f->upvalues=luaM_newvector(S->L,n,TString*);\n f->sizeupvalues=n;\n for (i=0; i<n; i++) f->upvalues[i]=NULL;\n for (i=0; i<n; i++) f->upvalues[i]=LoadString(S);\n}\n\nstatic Proto* LoadFunction(LoadState* S, TString* p)\n{\n Proto* f;\n if (++S->L->nCcalls > LUAI_MAXCCALLS) error(S,\"code too deep\");\n f=luaF_newproto(S->L);\n setptvalue2s(S->L,S->L->top,f); incr_top(S->L);\n f->source=LoadString(S); if (f->source==NULL) f->source=p;\n f->linedefined=LoadInt(S);\n f->lastlinedefined=LoadInt(S);\n f->nups=LoadByte(S);\n f->numparams=LoadByte(S);\n f->is_vararg=LoadByte(S);\n f->maxstacksize=LoadByte(S);\n LoadCode(S,f);\n LoadConstants(S,f);\n LoadDebug(S,f);\n IF (!luaG_checkcode(f), \"bad code\");\n S->L->top--;\n S->L->nCcalls--;\n return f;\n}\n\nstatic void LoadHeader(LoadState* S)\n{\n char h[LUAC_HEADERSIZE];\n char s[LUAC_HEADERSIZE];\n luaU_header(h);\n LoadBlock(S,s,LUAC_HEADERSIZE);\n IF (memcmp(h,s,LUAC_HEADERSIZE)!=0, \"bad header\");\n}\n\n/*\n** load precompiled chunk\n*/\nProto* luaU_undump (lua_State* L, ZIO* Z, Mbuffer* buff, const char* name)\n{\n LoadState S;\n if (*name=='@' || *name=='=')\n  S.name=name+1;\n else if (*name==LUA_SIGNATURE[0])\n  S.name=\"binary string\";\n else\n  S.name=name;\n S.L=L;\n S.Z=Z;\n S.b=buff;\n LoadHeader(&S);\n return LoadFunction(&S,luaS_newliteral(L,\"=?\"));\n}\n\n/*\n* make header\n*/\nvoid luaU_header (char* h)\n{\n int x=1;\n memcpy(h,LUA_SIGNATURE,sizeof(LUA_SIGNATURE)-1);\n h+=sizeof(LUA_SIGNATURE)-1;\n *h++=(char)LUAC_VERSION;\n *h++=(char)LUAC_FORMAT;\n *h++=(char)*(char*)&x;\t\t\t\t/* endianness */\n *h++=(char)sizeof(int);\n *h++=(char)sizeof(size_t);\n *h++=(char)sizeof(Instruction);\n *h++=(char)sizeof(lua_Number);\n *h++=(char)(((lua_Number)0.5)==0);\t\t/* is lua_Number integral? */\n}\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.8/deps/lua/src/lundump.h",
    "content": "/*\n** $Id: lundump.h,v 1.37.1.1 2007/12/27 13:02:25 roberto Exp $\n** load precompiled Lua chunks\n** See Copyright Notice in lua.h\n*/\n\n#ifndef lundump_h\n#define lundump_h\n\n#include \"lobject.h\"\n#include \"lzio.h\"\n\n/* load one chunk; from lundump.c */\nLUAI_FUNC Proto* luaU_undump (lua_State* L, ZIO* Z, Mbuffer* buff, const char* name);\n\n/* make header; from lundump.c */\nLUAI_FUNC void luaU_header (char* h);\n\n/* dump one chunk; from ldump.c */\nLUAI_FUNC int luaU_dump (lua_State* L, const Proto* f, lua_Writer w, void* data, int strip);\n\n#ifdef luac_c\n/* print one chunk; from print.c */\nLUAI_FUNC void luaU_print (const Proto* f, int full);\n#endif\n\n/* for header of binary files -- this is Lua 5.1 */\n#define LUAC_VERSION\t\t0x51\n\n/* for header of binary files -- this is the official format */\n#define LUAC_FORMAT\t\t0\n\n/* size of header of binary files */\n#define LUAC_HEADERSIZE\t\t12\n\n#endif\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.8/deps/lua/src/lvm.c",
    "content": "/*\n** $Id: lvm.c,v 2.63.1.5 2011/08/17 20:43:11 roberto Exp $\n** Lua virtual machine\n** See Copyright Notice in lua.h\n*/\n\n\n#include <stdio.h>\n#include <stdlib.h>\n#include <string.h>\n\n#define lvm_c\n#define LUA_CORE\n\n#include \"lua.h\"\n\n#include \"ldebug.h\"\n#include \"ldo.h\"\n#include \"lfunc.h\"\n#include \"lgc.h\"\n#include \"lobject.h\"\n#include \"lopcodes.h\"\n#include \"lstate.h\"\n#include \"lstring.h\"\n#include \"ltable.h\"\n#include \"ltm.h\"\n#include \"lvm.h\"\n\n\n\n/* limit for table tag-method chains (to avoid loops) */\n#define MAXTAGLOOP\t100\n\n\nconst TValue *luaV_tonumber (const TValue *obj, TValue *n) {\n  lua_Number num;\n  if (ttisnumber(obj)) return obj;\n  if (ttisstring(obj) && luaO_str2d(svalue(obj), &num)) {\n    setnvalue(n, num);\n    return n;\n  }\n  else\n    return NULL;\n}\n\n\nint luaV_tostring (lua_State *L, StkId obj) {\n  if (!ttisnumber(obj))\n    return 0;\n  else {\n    char s[LUAI_MAXNUMBER2STR];\n    lua_Number n = nvalue(obj);\n    lua_number2str(s, n);\n    setsvalue2s(L, obj, luaS_new(L, s));\n    return 1;\n  }\n}\n\n\nstatic void traceexec (lua_State *L, const Instruction *pc) {\n  lu_byte mask = L->hookmask;\n  const Instruction *oldpc = L->savedpc;\n  L->savedpc = pc;\n  if ((mask & LUA_MASKCOUNT) && L->hookcount == 0) {\n    resethookcount(L);\n    luaD_callhook(L, LUA_HOOKCOUNT, -1);\n  }\n  if (mask & LUA_MASKLINE) {\n    Proto *p = ci_func(L->ci)->l.p;\n    int npc = pcRel(pc, p);\n    int newline = getline(p, npc);\n    /* call linehook when enter a new function, when jump back (loop),\n       or when enter a new line */\n    if (npc == 0 || pc <= oldpc || newline != getline(p, pcRel(oldpc, p)))\n      luaD_callhook(L, LUA_HOOKLINE, newline);\n  }\n}\n\n\nstatic void callTMres (lua_State *L, StkId res, const TValue *f,\n                        const TValue *p1, const TValue *p2) {\n  ptrdiff_t result = savestack(L, res);\n  setobj2s(L, L->top, f);  /* push function */\n  setobj2s(L, L->top+1, p1);  /* 1st argument */\n  setobj2s(L, L->top+2, p2);  /* 2nd argument */\n  luaD_checkstack(L, 3);\n  L->top += 3;\n  luaD_call(L, L->top - 3, 1);\n  res = restorestack(L, result);\n  L->top--;\n  setobjs2s(L, res, L->top);\n}\n\n\n\nstatic void callTM (lua_State *L, const TValue *f, const TValue *p1,\n                    const TValue *p2, const TValue *p3) {\n  setobj2s(L, L->top, f);  /* push function */\n  setobj2s(L, L->top+1, p1);  /* 1st argument */\n  setobj2s(L, L->top+2, p2);  /* 2nd argument */\n  setobj2s(L, L->top+3, p3);  /* 3th argument */\n  luaD_checkstack(L, 4);\n  L->top += 4;\n  luaD_call(L, L->top - 4, 0);\n}\n\n\nvoid luaV_gettable (lua_State *L, const TValue *t, TValue *key, StkId val) {\n  int loop;\n  for (loop = 0; loop < MAXTAGLOOP; loop++) {\n    const TValue *tm;\n    if (ttistable(t)) {  /* `t' is a table? */\n      Table *h = hvalue(t);\n      const TValue *res = luaH_get(h, key); /* do a primitive get */\n      if (!ttisnil(res) ||  /* result is no nil? */\n          (tm = fasttm(L, h->metatable, TM_INDEX)) == NULL) { /* or no TM? */\n        setobj2s(L, val, res);\n        return;\n      }\n      /* else will try the tag method */\n    }\n    else if (ttisnil(tm = luaT_gettmbyobj(L, t, TM_INDEX)))\n      luaG_typeerror(L, t, \"index\");\n    if (ttisfunction(tm)) {\n      callTMres(L, val, tm, t, key);\n      return;\n    }\n    t = tm;  /* else repeat with `tm' */ \n  }\n  luaG_runerror(L, \"loop in gettable\");\n}\n\n\nvoid luaV_settable (lua_State *L, const TValue *t, TValue *key, StkId val) {\n  int loop;\n  TValue temp;\n  for (loop = 0; loop < MAXTAGLOOP; loop++) {\n    const TValue *tm;\n    if (ttistable(t)) {  /* `t' is a table? */\n      Table *h = hvalue(t);\n      TValue *oldval = luaH_set(L, h, key); /* do a primitive set */\n      if (!ttisnil(oldval) ||  /* result is no nil? */\n          (tm = fasttm(L, h->metatable, TM_NEWINDEX)) == NULL) { /* or no TM? */\n        setobj2t(L, oldval, val);\n        h->flags = 0;\n        luaC_barriert(L, h, val);\n        return;\n      }\n      /* else will try the tag method */\n    }\n    else if (ttisnil(tm = luaT_gettmbyobj(L, t, TM_NEWINDEX)))\n      luaG_typeerror(L, t, \"index\");\n    if (ttisfunction(tm)) {\n      callTM(L, tm, t, key, val);\n      return;\n    }\n    /* else repeat with `tm' */\n    setobj(L, &temp, tm);  /* avoid pointing inside table (may rehash) */\n    t = &temp;\n  }\n  luaG_runerror(L, \"loop in settable\");\n}\n\n\nstatic int call_binTM (lua_State *L, const TValue *p1, const TValue *p2,\n                       StkId res, TMS event) {\n  const TValue *tm = luaT_gettmbyobj(L, p1, event);  /* try first operand */\n  if (ttisnil(tm))\n    tm = luaT_gettmbyobj(L, p2, event);  /* try second operand */\n  if (ttisnil(tm)) return 0;\n  callTMres(L, res, tm, p1, p2);\n  return 1;\n}\n\n\nstatic const TValue *get_compTM (lua_State *L, Table *mt1, Table *mt2,\n                                  TMS event) {\n  const TValue *tm1 = fasttm(L, mt1, event);\n  const TValue *tm2;\n  if (tm1 == NULL) return NULL;  /* no metamethod */\n  if (mt1 == mt2) return tm1;  /* same metatables => same metamethods */\n  tm2 = fasttm(L, mt2, event);\n  if (tm2 == NULL) return NULL;  /* no metamethod */\n  if (luaO_rawequalObj(tm1, tm2))  /* same metamethods? */\n    return tm1;\n  return NULL;\n}\n\n\nstatic int call_orderTM (lua_State *L, const TValue *p1, const TValue *p2,\n                         TMS event) {\n  const TValue *tm1 = luaT_gettmbyobj(L, p1, event);\n  const TValue *tm2;\n  if (ttisnil(tm1)) return -1;  /* no metamethod? */\n  tm2 = luaT_gettmbyobj(L, p2, event);\n  if (!luaO_rawequalObj(tm1, tm2))  /* different metamethods? */\n    return -1;\n  callTMres(L, L->top, tm1, p1, p2);\n  return !l_isfalse(L->top);\n}\n\n\nstatic int l_strcmp (const TString *ls, const TString *rs) {\n  const char *l = getstr(ls);\n  size_t ll = ls->tsv.len;\n  const char *r = getstr(rs);\n  size_t lr = rs->tsv.len;\n  for (;;) {\n    int temp = strcoll(l, r);\n    if (temp != 0) return temp;\n    else {  /* strings are equal up to a `\\0' */\n      size_t len = strlen(l);  /* index of first `\\0' in both strings */\n      if (len == lr)  /* r is finished? */\n        return (len == ll) ? 0 : 1;\n      else if (len == ll)  /* l is finished? */\n        return -1;  /* l is smaller than r (because r is not finished) */\n      /* both strings longer than `len'; go on comparing (after the `\\0') */\n      len++;\n      l += len; ll -= len; r += len; lr -= len;\n    }\n  }\n}\n\n\nint luaV_lessthan (lua_State *L, const TValue *l, const TValue *r) {\n  int res;\n  if (ttype(l) != ttype(r))\n    return luaG_ordererror(L, l, r);\n  else if (ttisnumber(l))\n    return luai_numlt(nvalue(l), nvalue(r));\n  else if (ttisstring(l))\n    return l_strcmp(rawtsvalue(l), rawtsvalue(r)) < 0;\n  else if ((res = call_orderTM(L, l, r, TM_LT)) != -1)\n    return res;\n  return luaG_ordererror(L, l, r);\n}\n\n\nstatic int lessequal (lua_State *L, const TValue *l, const TValue *r) {\n  int res;\n  if (ttype(l) != ttype(r))\n    return luaG_ordererror(L, l, r);\n  else if (ttisnumber(l))\n    return luai_numle(nvalue(l), nvalue(r));\n  else if (ttisstring(l))\n    return l_strcmp(rawtsvalue(l), rawtsvalue(r)) <= 0;\n  else if ((res = call_orderTM(L, l, r, TM_LE)) != -1)  /* first try `le' */\n    return res;\n  else if ((res = call_orderTM(L, r, l, TM_LT)) != -1)  /* else try `lt' */\n    return !res;\n  return luaG_ordererror(L, l, r);\n}\n\n\nint luaV_equalval (lua_State *L, const TValue *t1, const TValue *t2) {\n  const TValue *tm;\n  lua_assert(ttype(t1) == ttype(t2));\n  switch (ttype(t1)) {\n    case LUA_TNIL: return 1;\n    case LUA_TNUMBER: return luai_numeq(nvalue(t1), nvalue(t2));\n    case LUA_TBOOLEAN: return bvalue(t1) == bvalue(t2);  /* true must be 1 !! */\n    case LUA_TLIGHTUSERDATA: return pvalue(t1) == pvalue(t2);\n    case LUA_TUSERDATA: {\n      if (uvalue(t1) == uvalue(t2)) return 1;\n      tm = get_compTM(L, uvalue(t1)->metatable, uvalue(t2)->metatable,\n                         TM_EQ);\n      break;  /* will try TM */\n    }\n    case LUA_TTABLE: {\n      if (hvalue(t1) == hvalue(t2)) return 1;\n      tm = get_compTM(L, hvalue(t1)->metatable, hvalue(t2)->metatable, TM_EQ);\n      break;  /* will try TM */\n    }\n    default: return gcvalue(t1) == gcvalue(t2);\n  }\n  if (tm == NULL) return 0;  /* no TM? */\n  callTMres(L, L->top, tm, t1, t2);  /* call TM */\n  return !l_isfalse(L->top);\n}\n\n\nvoid luaV_concat (lua_State *L, int total, int last) {\n  do {\n    StkId top = L->base + last + 1;\n    int n = 2;  /* number of elements handled in this pass (at least 2) */\n    if (!(ttisstring(top-2) || ttisnumber(top-2)) || !tostring(L, top-1)) {\n      if (!call_binTM(L, top-2, top-1, top-2, TM_CONCAT))\n        luaG_concaterror(L, top-2, top-1);\n    } else if (tsvalue(top-1)->len == 0)  /* second op is empty? */\n      (void)tostring(L, top - 2);  /* result is first op (as string) */\n    else {\n      /* at least two string values; get as many as possible */\n      size_t tl = tsvalue(top-1)->len;\n      char *buffer;\n      int i;\n      /* collect total length */\n      for (n = 1; n < total && tostring(L, top-n-1); n++) {\n        size_t l = tsvalue(top-n-1)->len;\n        if (l >= MAX_SIZET - tl) luaG_runerror(L, \"string length overflow\");\n        tl += l;\n      }\n      buffer = luaZ_openspace(L, &G(L)->buff, tl);\n      tl = 0;\n      for (i=n; i>0; i--) {  /* concat all strings */\n        size_t l = tsvalue(top-i)->len;\n        memcpy(buffer+tl, svalue(top-i), l);\n        tl += l;\n      }\n      setsvalue2s(L, top-n, luaS_newlstr(L, buffer, tl));\n    }\n    total -= n-1;  /* got `n' strings to create 1 new */\n    last -= n-1;\n  } while (total > 1);  /* repeat until only 1 result left */\n}\n\n\nstatic void Arith (lua_State *L, StkId ra, const TValue *rb,\n                   const TValue *rc, TMS op) {\n  TValue tempb, tempc;\n  const TValue *b, *c;\n  if ((b = luaV_tonumber(rb, &tempb)) != NULL &&\n      (c = luaV_tonumber(rc, &tempc)) != NULL) {\n    lua_Number nb = nvalue(b), nc = nvalue(c);\n    switch (op) {\n      case TM_ADD: setnvalue(ra, luai_numadd(nb, nc)); break;\n      case TM_SUB: setnvalue(ra, luai_numsub(nb, nc)); break;\n      case TM_MUL: setnvalue(ra, luai_nummul(nb, nc)); break;\n      case TM_DIV: setnvalue(ra, luai_numdiv(nb, nc)); break;\n      case TM_MOD: setnvalue(ra, luai_nummod(nb, nc)); break;\n      case TM_POW: setnvalue(ra, luai_numpow(nb, nc)); break;\n      case TM_UNM: setnvalue(ra, luai_numunm(nb)); break;\n      default: lua_assert(0); break;\n    }\n  }\n  else if (!call_binTM(L, rb, rc, ra, op))\n    luaG_aritherror(L, rb, rc);\n}\n\n\n\n/*\n** some macros for common tasks in `luaV_execute'\n*/\n\n#define runtime_check(L, c)\t{ if (!(c)) break; }\n\n#define RA(i)\t(base+GETARG_A(i))\n/* to be used after possible stack reallocation */\n#define RB(i)\tcheck_exp(getBMode(GET_OPCODE(i)) == OpArgR, base+GETARG_B(i))\n#define RC(i)\tcheck_exp(getCMode(GET_OPCODE(i)) == OpArgR, base+GETARG_C(i))\n#define RKB(i)\tcheck_exp(getBMode(GET_OPCODE(i)) == OpArgK, \\\n\tISK(GETARG_B(i)) ? k+INDEXK(GETARG_B(i)) : base+GETARG_B(i))\n#define RKC(i)\tcheck_exp(getCMode(GET_OPCODE(i)) == OpArgK, \\\n\tISK(GETARG_C(i)) ? k+INDEXK(GETARG_C(i)) : base+GETARG_C(i))\n#define KBx(i)\tcheck_exp(getBMode(GET_OPCODE(i)) == OpArgK, k+GETARG_Bx(i))\n\n\n#define dojump(L,pc,i)\t{(pc) += (i); luai_threadyield(L);}\n\n\n#define Protect(x)\t{ L->savedpc = pc; {x;}; base = L->base; }\n\n\n#define arith_op(op,tm) { \\\n        TValue *rb = RKB(i); \\\n        TValue *rc = RKC(i); \\\n        if (ttisnumber(rb) && ttisnumber(rc)) { \\\n          lua_Number nb = nvalue(rb), nc = nvalue(rc); \\\n          setnvalue(ra, op(nb, nc)); \\\n        } \\\n        else \\\n          Protect(Arith(L, ra, rb, rc, tm)); \\\n      }\n\n\n\nvoid luaV_execute (lua_State *L, int nexeccalls) {\n  LClosure *cl;\n  StkId base;\n  TValue *k;\n  const Instruction *pc;\n reentry:  /* entry point */\n  lua_assert(isLua(L->ci));\n  pc = L->savedpc;\n  cl = &clvalue(L->ci->func)->l;\n  base = L->base;\n  k = cl->p->k;\n  /* main loop of interpreter */\n  for (;;) {\n    const Instruction i = *pc++;\n    StkId ra;\n    if ((L->hookmask & (LUA_MASKLINE | LUA_MASKCOUNT)) &&\n        (--L->hookcount == 0 || L->hookmask & LUA_MASKLINE)) {\n      traceexec(L, pc);\n      if (L->status == LUA_YIELD) {  /* did hook yield? */\n        L->savedpc = pc - 1;\n        return;\n      }\n      base = L->base;\n    }\n    /* warning!! several calls may realloc the stack and invalidate `ra' */\n    ra = RA(i);\n    lua_assert(base == L->base && L->base == L->ci->base);\n    lua_assert(base <= L->top && L->top <= L->stack + L->stacksize);\n    lua_assert(L->top == L->ci->top || luaG_checkopenop(i));\n    switch (GET_OPCODE(i)) {\n      case OP_MOVE: {\n        setobjs2s(L, ra, RB(i));\n        continue;\n      }\n      case OP_LOADK: {\n        setobj2s(L, ra, KBx(i));\n        continue;\n      }\n      case OP_LOADBOOL: {\n        setbvalue(ra, GETARG_B(i));\n        if (GETARG_C(i)) pc++;  /* skip next instruction (if C) */\n        continue;\n      }\n      case OP_LOADNIL: {\n        TValue *rb = RB(i);\n        do {\n          setnilvalue(rb--);\n        } while (rb >= ra);\n        continue;\n      }\n      case OP_GETUPVAL: {\n        int b = GETARG_B(i);\n        setobj2s(L, ra, cl->upvals[b]->v);\n        continue;\n      }\n      case OP_GETGLOBAL: {\n        TValue g;\n        TValue *rb = KBx(i);\n        sethvalue(L, &g, cl->env);\n        lua_assert(ttisstring(rb));\n        Protect(luaV_gettable(L, &g, rb, ra));\n        continue;\n      }\n      case OP_GETTABLE: {\n        Protect(luaV_gettable(L, RB(i), RKC(i), ra));\n        continue;\n      }\n      case OP_SETGLOBAL: {\n        TValue g;\n        sethvalue(L, &g, cl->env);\n        lua_assert(ttisstring(KBx(i)));\n        Protect(luaV_settable(L, &g, KBx(i), ra));\n        continue;\n      }\n      case OP_SETUPVAL: {\n        UpVal *uv = cl->upvals[GETARG_B(i)];\n        setobj(L, uv->v, ra);\n        luaC_barrier(L, uv, ra);\n        continue;\n      }\n      case OP_SETTABLE: {\n        Protect(luaV_settable(L, ra, RKB(i), RKC(i)));\n        continue;\n      }\n      case OP_NEWTABLE: {\n        int b = GETARG_B(i);\n        int c = GETARG_C(i);\n        sethvalue(L, ra, luaH_new(L, luaO_fb2int(b), luaO_fb2int(c)));\n        Protect(luaC_checkGC(L));\n        continue;\n      }\n      case OP_SELF: {\n        StkId rb = RB(i);\n        setobjs2s(L, ra+1, rb);\n        Protect(luaV_gettable(L, rb, RKC(i), ra));\n        continue;\n      }\n      case OP_ADD: {\n        arith_op(luai_numadd, TM_ADD);\n        continue;\n      }\n      case OP_SUB: {\n        arith_op(luai_numsub, TM_SUB);\n        continue;\n      }\n      case OP_MUL: {\n        arith_op(luai_nummul, TM_MUL);\n        continue;\n      }\n      case OP_DIV: {\n        arith_op(luai_numdiv, TM_DIV);\n        continue;\n      }\n      case OP_MOD: {\n        arith_op(luai_nummod, TM_MOD);\n        continue;\n      }\n      case OP_POW: {\n        arith_op(luai_numpow, TM_POW);\n        continue;\n      }\n      case OP_UNM: {\n        TValue *rb = RB(i);\n        if (ttisnumber(rb)) {\n          lua_Number nb = nvalue(rb);\n          setnvalue(ra, luai_numunm(nb));\n        }\n        else {\n          Protect(Arith(L, ra, rb, rb, TM_UNM));\n        }\n        continue;\n      }\n      case OP_NOT: {\n        int res = l_isfalse(RB(i));  /* next assignment may change this value */\n        setbvalue(ra, res);\n        continue;\n      }\n      case OP_LEN: {\n        const TValue *rb = RB(i);\n        switch (ttype(rb)) {\n          case LUA_TTABLE: {\n            setnvalue(ra, cast_num(luaH_getn(hvalue(rb))));\n            break;\n          }\n          case LUA_TSTRING: {\n            setnvalue(ra, cast_num(tsvalue(rb)->len));\n            break;\n          }\n          default: {  /* try metamethod */\n            Protect(\n              if (!call_binTM(L, rb, luaO_nilobject, ra, TM_LEN))\n                luaG_typeerror(L, rb, \"get length of\");\n            )\n          }\n        }\n        continue;\n      }\n      case OP_CONCAT: {\n        int b = GETARG_B(i);\n        int c = GETARG_C(i);\n        Protect(luaV_concat(L, c-b+1, c); luaC_checkGC(L));\n        setobjs2s(L, RA(i), base+b);\n        continue;\n      }\n      case OP_JMP: {\n        dojump(L, pc, GETARG_sBx(i));\n        continue;\n      }\n      case OP_EQ: {\n        TValue *rb = RKB(i);\n        TValue *rc = RKC(i);\n        Protect(\n          if (equalobj(L, rb, rc) == GETARG_A(i))\n            dojump(L, pc, GETARG_sBx(*pc));\n        )\n        pc++;\n        continue;\n      }\n      case OP_LT: {\n        Protect(\n          if (luaV_lessthan(L, RKB(i), RKC(i)) == GETARG_A(i))\n            dojump(L, pc, GETARG_sBx(*pc));\n        )\n        pc++;\n        continue;\n      }\n      case OP_LE: {\n        Protect(\n          if (lessequal(L, RKB(i), RKC(i)) == GETARG_A(i))\n            dojump(L, pc, GETARG_sBx(*pc));\n        )\n        pc++;\n        continue;\n      }\n      case OP_TEST: {\n        if (l_isfalse(ra) != GETARG_C(i))\n          dojump(L, pc, GETARG_sBx(*pc));\n        pc++;\n        continue;\n      }\n      case OP_TESTSET: {\n        TValue *rb = RB(i);\n        if (l_isfalse(rb) != GETARG_C(i)) {\n          setobjs2s(L, ra, rb);\n          dojump(L, pc, GETARG_sBx(*pc));\n        }\n        pc++;\n        continue;\n      }\n      case OP_CALL: {\n        int b = GETARG_B(i);\n        int nresults = GETARG_C(i) - 1;\n        if (b != 0) L->top = ra+b;  /* else previous instruction set top */\n        L->savedpc = pc;\n        switch (luaD_precall(L, ra, nresults)) {\n          case PCRLUA: {\n            nexeccalls++;\n            goto reentry;  /* restart luaV_execute over new Lua function */\n          }\n          case PCRC: {\n            /* it was a C function (`precall' called it); adjust results */\n            if (nresults >= 0) L->top = L->ci->top;\n            base = L->base;\n            continue;\n          }\n          default: {\n            return;  /* yield */\n          }\n        }\n      }\n      case OP_TAILCALL: {\n        int b = GETARG_B(i);\n        if (b != 0) L->top = ra+b;  /* else previous instruction set top */\n        L->savedpc = pc;\n        lua_assert(GETARG_C(i) - 1 == LUA_MULTRET);\n        switch (luaD_precall(L, ra, LUA_MULTRET)) {\n          case PCRLUA: {\n            /* tail call: put new frame in place of previous one */\n            CallInfo *ci = L->ci - 1;  /* previous frame */\n            int aux;\n            StkId func = ci->func;\n            StkId pfunc = (ci+1)->func;  /* previous function index */\n            if (L->openupval) luaF_close(L, ci->base);\n            L->base = ci->base = ci->func + ((ci+1)->base - pfunc);\n            for (aux = 0; pfunc+aux < L->top; aux++)  /* move frame down */\n              setobjs2s(L, func+aux, pfunc+aux);\n            ci->top = L->top = func+aux;  /* correct top */\n            lua_assert(L->top == L->base + clvalue(func)->l.p->maxstacksize);\n            ci->savedpc = L->savedpc;\n            ci->tailcalls++;  /* one more call lost */\n            L->ci--;  /* remove new frame */\n            goto reentry;\n          }\n          case PCRC: {  /* it was a C function (`precall' called it) */\n            base = L->base;\n            continue;\n          }\n          default: {\n            return;  /* yield */\n          }\n        }\n      }\n      case OP_RETURN: {\n        int b = GETARG_B(i);\n        if (b != 0) L->top = ra+b-1;\n        if (L->openupval) luaF_close(L, base);\n        L->savedpc = pc;\n        b = luaD_poscall(L, ra);\n        if (--nexeccalls == 0)  /* was previous function running `here'? */\n          return;  /* no: return */\n        else {  /* yes: continue its execution */\n          if (b) L->top = L->ci->top;\n          lua_assert(isLua(L->ci));\n          lua_assert(GET_OPCODE(*((L->ci)->savedpc - 1)) == OP_CALL);\n          goto reentry;\n        }\n      }\n      case OP_FORLOOP: {\n        lua_Number step = nvalue(ra+2);\n        lua_Number idx = luai_numadd(nvalue(ra), step); /* increment index */\n        lua_Number limit = nvalue(ra+1);\n        if (luai_numlt(0, step) ? luai_numle(idx, limit)\n                                : luai_numle(limit, idx)) {\n          dojump(L, pc, GETARG_sBx(i));  /* jump back */\n          setnvalue(ra, idx);  /* update internal index... */\n          setnvalue(ra+3, idx);  /* ...and external index */\n        }\n        continue;\n      }\n      case OP_FORPREP: {\n        const TValue *init = ra;\n        const TValue *plimit = ra+1;\n        const TValue *pstep = ra+2;\n        L->savedpc = pc;  /* next steps may throw errors */\n        if (!tonumber(init, ra))\n          luaG_runerror(L, LUA_QL(\"for\") \" initial value must be a number\");\n        else if (!tonumber(plimit, ra+1))\n          luaG_runerror(L, LUA_QL(\"for\") \" limit must be a number\");\n        else if (!tonumber(pstep, ra+2))\n          luaG_runerror(L, LUA_QL(\"for\") \" step must be a number\");\n        setnvalue(ra, luai_numsub(nvalue(ra), nvalue(pstep)));\n        dojump(L, pc, GETARG_sBx(i));\n        continue;\n      }\n      case OP_TFORLOOP: {\n        StkId cb = ra + 3;  /* call base */\n        setobjs2s(L, cb+2, ra+2);\n        setobjs2s(L, cb+1, ra+1);\n        setobjs2s(L, cb, ra);\n        L->top = cb+3;  /* func. + 2 args (state and index) */\n        Protect(luaD_call(L, cb, GETARG_C(i)));\n        L->top = L->ci->top;\n        cb = RA(i) + 3;  /* previous call may change the stack */\n        if (!ttisnil(cb)) {  /* continue loop? */\n          setobjs2s(L, cb-1, cb);  /* save control variable */\n          dojump(L, pc, GETARG_sBx(*pc));  /* jump back */\n        }\n        pc++;\n        continue;\n      }\n      case OP_SETLIST: {\n        int n = GETARG_B(i);\n        int c = GETARG_C(i);\n        int last;\n        Table *h;\n        if (n == 0) {\n          n = cast_int(L->top - ra) - 1;\n          L->top = L->ci->top;\n        }\n        if (c == 0) c = cast_int(*pc++);\n        runtime_check(L, ttistable(ra));\n        h = hvalue(ra);\n        last = ((c-1)*LFIELDS_PER_FLUSH) + n;\n        if (last > h->sizearray)  /* needs more space? */\n          luaH_resizearray(L, h, last);  /* pre-alloc it at once */\n        for (; n > 0; n--) {\n          TValue *val = ra+n;\n          setobj2t(L, luaH_setnum(L, h, last--), val);\n          luaC_barriert(L, h, val);\n        }\n        continue;\n      }\n      case OP_CLOSE: {\n        luaF_close(L, ra);\n        continue;\n      }\n      case OP_CLOSURE: {\n        Proto *p;\n        Closure *ncl;\n        int nup, j;\n        p = cl->p->p[GETARG_Bx(i)];\n        nup = p->nups;\n        ncl = luaF_newLclosure(L, nup, cl->env);\n        ncl->l.p = p;\n        for (j=0; j<nup; j++, pc++) {\n          if (GET_OPCODE(*pc) == OP_GETUPVAL)\n            ncl->l.upvals[j] = cl->upvals[GETARG_B(*pc)];\n          else {\n            lua_assert(GET_OPCODE(*pc) == OP_MOVE);\n            ncl->l.upvals[j] = luaF_findupval(L, base + GETARG_B(*pc));\n          }\n        }\n        setclvalue(L, ra, ncl);\n        Protect(luaC_checkGC(L));\n        continue;\n      }\n      case OP_VARARG: {\n        int b = GETARG_B(i) - 1;\n        int j;\n        CallInfo *ci = L->ci;\n        int n = cast_int(ci->base - ci->func) - cl->p->numparams - 1;\n        if (b == LUA_MULTRET) {\n          Protect(luaD_checkstack(L, n));\n          ra = RA(i);  /* previous call may change the stack */\n          b = n;\n          L->top = ra + n;\n        }\n        for (j = 0; j < b; j++) {\n          if (j < n) {\n            setobjs2s(L, ra + j, ci->base - n + j);\n          }\n          else {\n            setnilvalue(ra + j);\n          }\n        }\n        continue;\n      }\n    }\n  }\n}\n\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.8/deps/lua/src/lvm.h",
    "content": "/*\n** $Id: lvm.h,v 2.5.1.1 2007/12/27 13:02:25 roberto Exp $\n** Lua virtual machine\n** See Copyright Notice in lua.h\n*/\n\n#ifndef lvm_h\n#define lvm_h\n\n\n#include \"ldo.h\"\n#include \"lobject.h\"\n#include \"ltm.h\"\n\n\n#define tostring(L,o) ((ttype(o) == LUA_TSTRING) || (luaV_tostring(L, o)))\n\n#define tonumber(o,n)\t(ttype(o) == LUA_TNUMBER || \\\n                         (((o) = luaV_tonumber(o,n)) != NULL))\n\n#define equalobj(L,o1,o2) \\\n\t(ttype(o1) == ttype(o2) && luaV_equalval(L, o1, o2))\n\n\nLUAI_FUNC int luaV_lessthan (lua_State *L, const TValue *l, const TValue *r);\nLUAI_FUNC int luaV_equalval (lua_State *L, const TValue *t1, const TValue *t2);\nLUAI_FUNC const TValue *luaV_tonumber (const TValue *obj, TValue *n);\nLUAI_FUNC int luaV_tostring (lua_State *L, StkId obj);\nLUAI_FUNC void luaV_gettable (lua_State *L, const TValue *t, TValue *key,\n                                            StkId val);\nLUAI_FUNC void luaV_settable (lua_State *L, const TValue *t, TValue *key,\n                                            StkId val);\nLUAI_FUNC void luaV_execute (lua_State *L, int nexeccalls);\nLUAI_FUNC void luaV_concat (lua_State *L, int total, int last);\n\n#endif\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.8/deps/lua/src/lzio.c",
    "content": "/*\n** $Id: lzio.c,v 1.31.1.1 2007/12/27 13:02:25 roberto Exp $\n** a generic input stream interface\n** See Copyright Notice in lua.h\n*/\n\n\n#include <string.h>\n\n#define lzio_c\n#define LUA_CORE\n\n#include \"lua.h\"\n\n#include \"llimits.h\"\n#include \"lmem.h\"\n#include \"lstate.h\"\n#include \"lzio.h\"\n\n\nint luaZ_fill (ZIO *z) {\n  size_t size;\n  lua_State *L = z->L;\n  const char *buff;\n  lua_unlock(L);\n  buff = z->reader(L, z->data, &size);\n  lua_lock(L);\n  if (buff == NULL || size == 0) return EOZ;\n  z->n = size - 1;\n  z->p = buff;\n  return char2int(*(z->p++));\n}\n\n\nint luaZ_lookahead (ZIO *z) {\n  if (z->n == 0) {\n    if (luaZ_fill(z) == EOZ)\n      return EOZ;\n    else {\n      z->n++;  /* luaZ_fill removed first byte; put back it */\n      z->p--;\n    }\n  }\n  return char2int(*z->p);\n}\n\n\nvoid luaZ_init (lua_State *L, ZIO *z, lua_Reader reader, void *data) {\n  z->L = L;\n  z->reader = reader;\n  z->data = data;\n  z->n = 0;\n  z->p = NULL;\n}\n\n\n/* --------------------------------------------------------------- read --- */\nsize_t luaZ_read (ZIO *z, void *b, size_t n) {\n  while (n) {\n    size_t m;\n    if (luaZ_lookahead(z) == EOZ)\n      return n;  /* return number of missing bytes */\n    m = (n <= z->n) ? n : z->n;  /* min. between n and z->n */\n    memcpy(b, z->p, m);\n    z->n -= m;\n    z->p += m;\n    b = (char *)b + m;\n    n -= m;\n  }\n  return 0;\n}\n\n/* ------------------------------------------------------------------------ */\nchar *luaZ_openspace (lua_State *L, Mbuffer *buff, size_t n) {\n  if (n > buff->buffsize) {\n    if (n < LUA_MINBUFFER) n = LUA_MINBUFFER;\n    luaZ_resizebuffer(L, buff, n);\n  }\n  return buff->buffer;\n}\n\n\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.8/deps/lua/src/lzio.h",
    "content": "/*\n** $Id: lzio.h,v 1.21.1.1 2007/12/27 13:02:25 roberto Exp $\n** Buffered streams\n** See Copyright Notice in lua.h\n*/\n\n\n#ifndef lzio_h\n#define lzio_h\n\n#include \"lua.h\"\n\n#include \"lmem.h\"\n\n\n#define EOZ\t(-1)\t\t\t/* end of stream */\n\ntypedef struct Zio ZIO;\n\n#define char2int(c)\tcast(int, cast(unsigned char, (c)))\n\n#define zgetc(z)  (((z)->n--)>0 ?  char2int(*(z)->p++) : luaZ_fill(z))\n\ntypedef struct Mbuffer {\n  char *buffer;\n  size_t n;\n  size_t buffsize;\n} Mbuffer;\n\n#define luaZ_initbuffer(L, buff) ((buff)->buffer = NULL, (buff)->buffsize = 0)\n\n#define luaZ_buffer(buff)\t((buff)->buffer)\n#define luaZ_sizebuffer(buff)\t((buff)->buffsize)\n#define luaZ_bufflen(buff)\t((buff)->n)\n\n#define luaZ_resetbuffer(buff) ((buff)->n = 0)\n\n\n#define luaZ_resizebuffer(L, buff, size) \\\n\t(luaM_reallocvector(L, (buff)->buffer, (buff)->buffsize, size, char), \\\n\t(buff)->buffsize = size)\n\n#define luaZ_freebuffer(L, buff)\tluaZ_resizebuffer(L, buff, 0)\n\n\nLUAI_FUNC char *luaZ_openspace (lua_State *L, Mbuffer *buff, size_t n);\nLUAI_FUNC void luaZ_init (lua_State *L, ZIO *z, lua_Reader reader,\n                                        void *data);\nLUAI_FUNC size_t luaZ_read (ZIO* z, void* b, size_t n);\t/* read next n bytes */\nLUAI_FUNC int luaZ_lookahead (ZIO *z);\n\n\n\n/* --------- Private Part ------------------ */\n\nstruct Zio {\n  size_t n;\t\t\t/* bytes still unread */\n  const char *p;\t\t/* current position in buffer */\n  lua_Reader reader;\n  void* data;\t\t\t/* additional data */\n  lua_State *L;\t\t\t/* Lua state (for reader) */\n};\n\n\nLUAI_FUNC int luaZ_fill (ZIO *z);\n\n#endif\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.8/deps/lua/src/print.c",
    "content": "/*\n** $Id: print.c,v 1.55a 2006/05/31 13:30:05 lhf Exp $\n** print bytecodes\n** See Copyright Notice in lua.h\n*/\n\n#include <ctype.h>\n#include <stdio.h>\n\n#define luac_c\n#define LUA_CORE\n\n#include \"ldebug.h\"\n#include \"lobject.h\"\n#include \"lopcodes.h\"\n#include \"lundump.h\"\n\n#define PrintFunction\tluaU_print\n\n#define Sizeof(x)\t((int)sizeof(x))\n#define VOID(p)\t\t((const void*)(p))\n\nstatic void PrintString(const TString* ts)\n{\n const char* s=getstr(ts);\n size_t i,n=ts->tsv.len;\n putchar('\"');\n for (i=0; i<n; i++)\n {\n  int c=s[i];\n  switch (c)\n  {\n   case '\"': printf(\"\\\\\\\"\"); break;\n   case '\\\\': printf(\"\\\\\\\\\"); break;\n   case '\\a': printf(\"\\\\a\"); break;\n   case '\\b': printf(\"\\\\b\"); break;\n   case '\\f': printf(\"\\\\f\"); break;\n   case '\\n': printf(\"\\\\n\"); break;\n   case '\\r': printf(\"\\\\r\"); break;\n   case '\\t': printf(\"\\\\t\"); break;\n   case '\\v': printf(\"\\\\v\"); break;\n   default:\tif (isprint((unsigned char)c))\n   \t\t\tputchar(c);\n\t\telse\n\t\t\tprintf(\"\\\\%03u\",(unsigned char)c);\n  }\n }\n putchar('\"');\n}\n\nstatic void PrintConstant(const Proto* f, int i)\n{\n const TValue* o=&f->k[i];\n switch (ttype(o))\n {\n  case LUA_TNIL:\n\tprintf(\"nil\");\n\tbreak;\n  case LUA_TBOOLEAN:\n\tprintf(bvalue(o) ? \"true\" : \"false\");\n\tbreak;\n  case LUA_TNUMBER:\n\tprintf(LUA_NUMBER_FMT,nvalue(o));\n\tbreak;\n  case LUA_TSTRING:\n\tPrintString(rawtsvalue(o));\n\tbreak;\n  default:\t\t\t\t/* cannot happen */\n\tprintf(\"? type=%d\",ttype(o));\n\tbreak;\n }\n}\n\nstatic void PrintCode(const Proto* f)\n{\n const Instruction* code=f->code;\n int pc,n=f->sizecode;\n for (pc=0; pc<n; pc++)\n {\n  Instruction i=code[pc];\n  OpCode o=GET_OPCODE(i);\n  int a=GETARG_A(i);\n  int b=GETARG_B(i);\n  int c=GETARG_C(i);\n  int bx=GETARG_Bx(i);\n  int sbx=GETARG_sBx(i);\n  int line=getline(f,pc);\n  printf(\"\\t%d\\t\",pc+1);\n  if (line>0) printf(\"[%d]\\t\",line); else printf(\"[-]\\t\");\n  printf(\"%-9s\\t\",luaP_opnames[o]);\n  switch (getOpMode(o))\n  {\n   case iABC:\n    printf(\"%d\",a);\n    if (getBMode(o)!=OpArgN) printf(\" %d\",ISK(b) ? (-1-INDEXK(b)) : b);\n    if (getCMode(o)!=OpArgN) printf(\" %d\",ISK(c) ? (-1-INDEXK(c)) : c);\n    break;\n   case iABx:\n    if (getBMode(o)==OpArgK) printf(\"%d %d\",a,-1-bx); else printf(\"%d %d\",a,bx);\n    break;\n   case iAsBx:\n    if (o==OP_JMP) printf(\"%d\",sbx); else printf(\"%d %d\",a,sbx);\n    break;\n  }\n  switch (o)\n  {\n   case OP_LOADK:\n    printf(\"\\t; \"); PrintConstant(f,bx);\n    break;\n   case OP_GETUPVAL:\n   case OP_SETUPVAL:\n    printf(\"\\t; %s\", (f->sizeupvalues>0) ? getstr(f->upvalues[b]) : \"-\");\n    break;\n   case OP_GETGLOBAL:\n   case OP_SETGLOBAL:\n    printf(\"\\t; %s\",svalue(&f->k[bx]));\n    break;\n   case OP_GETTABLE:\n   case OP_SELF:\n    if (ISK(c)) { printf(\"\\t; \"); PrintConstant(f,INDEXK(c)); }\n    break;\n   case OP_SETTABLE:\n   case OP_ADD:\n   case OP_SUB:\n   case OP_MUL:\n   case OP_DIV:\n   case OP_POW:\n   case OP_EQ:\n   case OP_LT:\n   case OP_LE:\n    if (ISK(b) || ISK(c))\n    {\n     printf(\"\\t; \");\n     if (ISK(b)) PrintConstant(f,INDEXK(b)); else printf(\"-\");\n     printf(\" \");\n     if (ISK(c)) PrintConstant(f,INDEXK(c)); else printf(\"-\");\n    }\n    break;\n   case OP_JMP:\n   case OP_FORLOOP:\n   case OP_FORPREP:\n    printf(\"\\t; to %d\",sbx+pc+2);\n    break;\n   case OP_CLOSURE:\n    printf(\"\\t; %p\",VOID(f->p[bx]));\n    break;\n   case OP_SETLIST:\n    if (c==0) printf(\"\\t; %d\",(int)code[++pc]);\n    else printf(\"\\t; %d\",c);\n    break;\n   default:\n    break;\n  }\n  printf(\"\\n\");\n }\n}\n\n#define SS(x)\t(x==1)?\"\":\"s\"\n#define S(x)\tx,SS(x)\n\nstatic void PrintHeader(const Proto* f)\n{\n const char* s=getstr(f->source);\n if (*s=='@' || *s=='=')\n  s++;\n else if (*s==LUA_SIGNATURE[0])\n  s=\"(bstring)\";\n else\n  s=\"(string)\";\n printf(\"\\n%s <%s:%d,%d> (%d instruction%s, %d bytes at %p)\\n\",\n \t(f->linedefined==0)?\"main\":\"function\",s,\n\tf->linedefined,f->lastlinedefined,\n\tS(f->sizecode),f->sizecode*Sizeof(Instruction),VOID(f));\n printf(\"%d%s param%s, %d slot%s, %d upvalue%s, \",\n\tf->numparams,f->is_vararg?\"+\":\"\",SS(f->numparams),\n\tS(f->maxstacksize),S(f->nups));\n printf(\"%d local%s, %d constant%s, %d function%s\\n\",\n\tS(f->sizelocvars),S(f->sizek),S(f->sizep));\n}\n\nstatic void PrintConstants(const Proto* f)\n{\n int i,n=f->sizek;\n printf(\"constants (%d) for %p:\\n\",n,VOID(f));\n for (i=0; i<n; i++)\n {\n  printf(\"\\t%d\\t\",i+1);\n  PrintConstant(f,i);\n  printf(\"\\n\");\n }\n}\n\nstatic void PrintLocals(const Proto* f)\n{\n int i,n=f->sizelocvars;\n printf(\"locals (%d) for %p:\\n\",n,VOID(f));\n for (i=0; i<n; i++)\n {\n  printf(\"\\t%d\\t%s\\t%d\\t%d\\n\",\n  i,getstr(f->locvars[i].varname),f->locvars[i].startpc+1,f->locvars[i].endpc+1);\n }\n}\n\nstatic void PrintUpvalues(const Proto* f)\n{\n int i,n=f->sizeupvalues;\n printf(\"upvalues (%d) for %p:\\n\",n,VOID(f));\n if (f->upvalues==NULL) return;\n for (i=0; i<n; i++)\n {\n  printf(\"\\t%d\\t%s\\n\",i,getstr(f->upvalues[i]));\n }\n}\n\nvoid PrintFunction(const Proto* f, int full)\n{\n int i,n=f->sizep;\n PrintHeader(f);\n PrintCode(f);\n if (full)\n {\n  PrintConstants(f);\n  PrintLocals(f);\n  PrintUpvalues(f);\n }\n for (i=0; i<n; i++) PrintFunction(f->p[i],full);\n}\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.8/deps/lua/src/strbuf.c",
    "content": "/* strbuf - String buffer routines\n *\n * Copyright (c) 2010-2012  Mark Pulford <mark@kyne.com.au>\n *\n * Permission is hereby granted, free of charge, to any person obtaining\n * a copy of this software and associated documentation files (the\n * \"Software\"), to deal in the Software without restriction, including\n * without limitation the rights to use, copy, modify, merge, publish,\n * distribute, sublicense, and/or sell copies of the Software, and to\n * permit persons to whom the Software is furnished to do so, subject to\n * the following conditions:\n *\n * The above copyright notice and this permission notice shall be\n * included in all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND,\n * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\n * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.\n * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY\n * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,\n * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE\n * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n */\n\n#include <stdio.h>\n#include <stdlib.h>\n#include <stdarg.h>\n#include <string.h>\n\n#include \"strbuf.h\"\n\nstatic void die(const char *fmt, ...)\n{\n    va_list arg;\n\n    va_start(arg, fmt);\n    vfprintf(stderr, fmt, arg);\n    va_end(arg);\n    fprintf(stderr, \"\\n\");\n\n    exit(-1);\n}\n\nvoid strbuf_init(strbuf_t *s, int len)\n{\n    int size;\n\n    if (len <= 0)\n        size = STRBUF_DEFAULT_SIZE;\n    else\n        size = len + 1;         /* \\0 terminator */\n\n    s->buf = NULL;\n    s->size = size;\n    s->length = 0;\n    s->increment = STRBUF_DEFAULT_INCREMENT;\n    s->dynamic = 0;\n    s->reallocs = 0;\n    s->debug = 0;\n\n    s->buf = malloc(size);\n    if (!s->buf)\n        die(\"Out of memory\");\n\n    strbuf_ensure_null(s);\n}\n\nstrbuf_t *strbuf_new(int len)\n{\n    strbuf_t *s;\n\n    s = malloc(sizeof(strbuf_t));\n    if (!s)\n        die(\"Out of memory\");\n\n    strbuf_init(s, len);\n\n    /* Dynamic strbuf allocation / deallocation */\n    s->dynamic = 1;\n\n    return s;\n}\n\nvoid strbuf_set_increment(strbuf_t *s, int increment)\n{\n    /* Increment > 0:  Linear buffer growth rate\n     * Increment < -1: Exponential buffer growth rate */\n    if (increment == 0 || increment == -1)\n        die(\"BUG: Invalid string increment\");\n\n    s->increment = increment;\n}\n\nstatic inline void debug_stats(strbuf_t *s)\n{\n    if (s->debug) {\n        fprintf(stderr, \"strbuf(%lx) reallocs: %d, length: %d, size: %d\\n\",\n                (long)s, s->reallocs, s->length, s->size);\n    }\n}\n\n/* If strbuf_t has not been dynamically allocated, strbuf_free() can\n * be called any number of times strbuf_init() */\nvoid strbuf_free(strbuf_t *s)\n{\n    debug_stats(s);\n\n    if (s->buf) {\n        free(s->buf);\n        s->buf = NULL;\n    }\n    if (s->dynamic)\n        free(s);\n}\n\nchar *strbuf_free_to_string(strbuf_t *s, int *len)\n{\n    char *buf;\n\n    debug_stats(s);\n\n    strbuf_ensure_null(s);\n\n    buf = s->buf;\n    if (len)\n        *len = s->length;\n\n    if (s->dynamic)\n        free(s);\n\n    return buf;\n}\n\nstatic int calculate_new_size(strbuf_t *s, int len)\n{\n    int reqsize, newsize;\n\n    if (len <= 0)\n        die(\"BUG: Invalid strbuf length requested\");\n\n    /* Ensure there is room for optional NULL termination */\n    reqsize = len + 1;\n\n    /* If the user has requested to shrink the buffer, do it exactly */\n    if (s->size > reqsize)\n        return reqsize;\n\n    newsize = s->size;\n    if (s->increment < 0) {\n        /* Exponential sizing */\n        while (newsize < reqsize)\n            newsize *= -s->increment;\n    } else {\n        /* Linear sizing */\n        newsize = ((newsize + s->increment - 1) / s->increment) * s->increment;\n    }\n\n    return newsize;\n}\n\n\n/* Ensure strbuf can handle a string length bytes long (ignoring NULL\n * optional termination). */\nvoid strbuf_resize(strbuf_t *s, int len)\n{\n    int newsize;\n\n    newsize = calculate_new_size(s, len);\n\n    if (s->debug > 1) {\n        fprintf(stderr, \"strbuf(%lx) resize: %d => %d\\n\",\n                (long)s, s->size, newsize);\n    }\n\n    s->size = newsize;\n    s->buf = realloc(s->buf, s->size);\n    if (!s->buf)\n        die(\"Out of memory\");\n    s->reallocs++;\n}\n\nvoid strbuf_append_string(strbuf_t *s, const char *str)\n{\n    int space, i;\n\n    space = strbuf_empty_length(s);\n\n    for (i = 0; str[i]; i++) {\n        if (space < 1) {\n            strbuf_resize(s, s->length + 1);\n            space = strbuf_empty_length(s);\n        }\n\n        s->buf[s->length] = str[i];\n        s->length++;\n        space--;\n    }\n}\n\n/* strbuf_append_fmt() should only be used when an upper bound\n * is known for the output string. */\nvoid strbuf_append_fmt(strbuf_t *s, int len, const char *fmt, ...)\n{\n    va_list arg;\n    int fmt_len;\n\n    strbuf_ensure_empty_length(s, len);\n\n    va_start(arg, fmt);\n    fmt_len = vsnprintf(s->buf + s->length, len, fmt, arg);\n    va_end(arg);\n\n    if (fmt_len < 0)\n        die(\"BUG: Unable to convert number\");  /* This should never happen.. */\n\n    s->length += fmt_len;\n}\n\n/* strbuf_append_fmt_retry() can be used when the there is no known\n * upper bound for the output string. */\nvoid strbuf_append_fmt_retry(strbuf_t *s, const char *fmt, ...)\n{\n    va_list arg;\n    int fmt_len, try;\n    int empty_len;\n\n    /* If the first attempt to append fails, resize the buffer appropriately\n     * and try again */\n    for (try = 0; ; try++) {\n        va_start(arg, fmt);\n        /* Append the new formatted string */\n        /* fmt_len is the length of the string required, excluding the\n         * trailing NULL */\n        empty_len = strbuf_empty_length(s);\n        /* Add 1 since there is also space to store the terminating NULL. */\n        fmt_len = vsnprintf(s->buf + s->length, empty_len + 1, fmt, arg);\n        va_end(arg);\n\n        if (fmt_len <= empty_len)\n            break;  /* SUCCESS */\n        if (try > 0)\n            die(\"BUG: length of formatted string changed\");\n\n        strbuf_resize(s, s->length + fmt_len);\n    }\n\n    s->length += fmt_len;\n}\n\n/* vi:ai et sw=4 ts=4:\n */\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.8/deps/lua/src/strbuf.h",
    "content": "/* strbuf - String buffer routines\n *\n * Copyright (c) 2010-2012  Mark Pulford <mark@kyne.com.au>\n *\n * Permission is hereby granted, free of charge, to any person obtaining\n * a copy of this software and associated documentation files (the\n * \"Software\"), to deal in the Software without restriction, including\n * without limitation the rights to use, copy, modify, merge, publish,\n * distribute, sublicense, and/or sell copies of the Software, and to\n * permit persons to whom the Software is furnished to do so, subject to\n * the following conditions:\n *\n * The above copyright notice and this permission notice shall be\n * included in all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND,\n * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\n * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.\n * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY\n * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,\n * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE\n * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n */\n\n#include <stdlib.h>\n#include <stdarg.h>\n\n/* Size: Total bytes allocated to *buf\n * Length: String length, excluding optional NULL terminator.\n * Increment: Allocation increments when resizing the string buffer.\n * Dynamic: True if created via strbuf_new()\n */\n\ntypedef struct {\n    char *buf;\n    int size;\n    int length;\n    int increment;\n    int dynamic;\n    int reallocs;\n    int debug;\n} strbuf_t;\n\n#ifndef STRBUF_DEFAULT_SIZE\n#define STRBUF_DEFAULT_SIZE 1023\n#endif\n#ifndef STRBUF_DEFAULT_INCREMENT\n#define STRBUF_DEFAULT_INCREMENT -2\n#endif\n\n/* Initialise */\nextern strbuf_t *strbuf_new(int len);\nextern void strbuf_init(strbuf_t *s, int len);\nextern void strbuf_set_increment(strbuf_t *s, int increment);\n\n/* Release */\nextern void strbuf_free(strbuf_t *s);\nextern char *strbuf_free_to_string(strbuf_t *s, int *len);\n\n/* Management */\nextern void strbuf_resize(strbuf_t *s, int len);\nstatic int strbuf_empty_length(strbuf_t *s);\nstatic int strbuf_length(strbuf_t *s);\nstatic char *strbuf_string(strbuf_t *s, int *len);\nstatic void strbuf_ensure_empty_length(strbuf_t *s, int len);\nstatic char *strbuf_empty_ptr(strbuf_t *s);\nstatic void strbuf_extend_length(strbuf_t *s, int len);\n\n/* Update */\nextern void strbuf_append_fmt(strbuf_t *s, int len, const char *fmt, ...);\nextern void strbuf_append_fmt_retry(strbuf_t *s, const char *format, ...);\nstatic void strbuf_append_mem(strbuf_t *s, const char *c, int len);\nextern void strbuf_append_string(strbuf_t *s, const char *str);\nstatic void strbuf_append_char(strbuf_t *s, const char c);\nstatic void strbuf_ensure_null(strbuf_t *s);\n\n/* Reset string for before use */\nstatic inline void strbuf_reset(strbuf_t *s)\n{\n    s->length = 0;\n}\n\nstatic inline int strbuf_allocated(strbuf_t *s)\n{\n    return s->buf != NULL;\n}\n\n/* Return bytes remaining in the string buffer\n * Ensure there is space for a NULL terminator. */\nstatic inline int strbuf_empty_length(strbuf_t *s)\n{\n    return s->size - s->length - 1;\n}\n\nstatic inline void strbuf_ensure_empty_length(strbuf_t *s, int len)\n{\n    if (len > strbuf_empty_length(s))\n        strbuf_resize(s, s->length + len);\n}\n\nstatic inline char *strbuf_empty_ptr(strbuf_t *s)\n{\n    return s->buf + s->length;\n}\n\nstatic inline void strbuf_extend_length(strbuf_t *s, int len)\n{\n    s->length += len;\n}\n\nstatic inline int strbuf_length(strbuf_t *s)\n{\n    return s->length;\n}\n\nstatic inline void strbuf_append_char(strbuf_t *s, const char c)\n{\n    strbuf_ensure_empty_length(s, 1);\n    s->buf[s->length++] = c;\n}\n\nstatic inline void strbuf_append_char_unsafe(strbuf_t *s, const char c)\n{\n    s->buf[s->length++] = c;\n}\n\nstatic inline void strbuf_append_mem(strbuf_t *s, const char *c, int len)\n{\n    strbuf_ensure_empty_length(s, len);\n    memcpy(s->buf + s->length, c, len);\n    s->length += len;\n}\n\nstatic inline void strbuf_append_mem_unsafe(strbuf_t *s, const char *c, int len)\n{\n    memcpy(s->buf + s->length, c, len);\n    s->length += len;\n}\n\nstatic inline void strbuf_ensure_null(strbuf_t *s)\n{\n    s->buf[s->length] = 0;\n}\n\nstatic inline char *strbuf_string(strbuf_t *s, int *len)\n{\n    if (len)\n        *len = s->length;\n\n    return s->buf;\n}\n\n/* vi:ai et sw=4 ts=4:\n */\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.8/deps/lua/test/README",
    "content": "These are simple tests for Lua.  Some of them contain useful code.\nThey are meant to be run to make sure Lua is built correctly and also\nto be read, to see how Lua programs look.\n\nHere is a one-line summary of each program:\n\n   bisect.lua\t\tbisection method for solving non-linear equations\n   cf.lua\t\ttemperature conversion table (celsius to farenheit)\n   echo.lua             echo command line arguments\n   env.lua              environment variables as automatic global variables\n   factorial.lua\tfactorial without recursion\n   fib.lua\t\tfibonacci function with cache\n   fibfor.lua\t\tfibonacci numbers with coroutines and generators\n   globals.lua\t\treport global variable usage\n   hello.lua\t\tthe first program in every language\n   life.lua\t\tConway's Game of Life\n   luac.lua\t \tbare-bones luac\n   printf.lua\t\tan implementation of printf\n   readonly.lua\t\tmake global variables readonly\n   sieve.lua\t\tthe sieve of of Eratosthenes programmed with coroutines\n   sort.lua\t\ttwo implementations of a sort function\n   table.lua\t\tmake table, grouping all data for the same item\n   trace-calls.lua\ttrace calls\n   trace-globals.lua\ttrace assigments to global variables\n   xd.lua\t\thex dump\n\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.8/deps/lua/test/bisect.lua",
    "content": "-- bisection method for solving non-linear equations\n\ndelta=1e-6\t-- tolerance\n\nfunction bisect(f,a,b,fa,fb)\n local c=(a+b)/2\n io.write(n,\" c=\",c,\" a=\",a,\" b=\",b,\"\\n\")\n if c==a or c==b or math.abs(a-b)<delta then return c,b-a end\n n=n+1\n local fc=f(c)\n if fa*fc<0 then return bisect(f,a,c,fa,fc) else return bisect(f,c,b,fc,fb) end\nend\n\n-- find root of f in the inverval [a,b]. needs f(a)*f(b)<0\nfunction solve(f,a,b)\n n=0\n local z,e=bisect(f,a,b,f(a),f(b))\n io.write(string.format(\"after %d steps, root is %.17g with error %.1e, f=%.1e\\n\",n,z,e,f(z)))\nend\n\n-- our function\nfunction f(x)\n return x*x*x-x-1\nend\n\n-- find zero in [1,2]\nsolve(f,1,2)\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.8/deps/lua/test/cf.lua",
    "content": "-- temperature conversion table (celsius to farenheit)\n\nfor c0=-20,50-1,10 do\n\tio.write(\"C \")\n\tfor c=c0,c0+10-1 do\n\t\tio.write(string.format(\"%3.0f \",c))\n\tend\n\tio.write(\"\\n\")\n\t\n\tio.write(\"F \")\n\tfor c=c0,c0+10-1 do\n\t\tf=(9/5)*c+32\n\t\tio.write(string.format(\"%3.0f \",f))\n\tend\n\tio.write(\"\\n\\n\")\nend\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.8/deps/lua/test/echo.lua",
    "content": "-- echo command line arguments\n\nfor i=0,table.getn(arg) do\n print(i,arg[i])\nend\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.8/deps/lua/test/env.lua",
    "content": "-- read environment variables as if they were global variables\n\nlocal f=function (t,i) return os.getenv(i) end\nsetmetatable(getfenv(),{__index=f})\n\n-- an example\nprint(a,USER,PATH)\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.8/deps/lua/test/factorial.lua",
    "content": "-- function closures are powerful\n\n-- traditional fixed-point operator from functional programming\nY = function (g)\n      local a = function (f) return f(f) end\n      return a(function (f)\n                 return g(function (x)\n                             local c=f(f)\n                             return c(x)\n                           end)\n               end)\nend\n\n\n-- factorial without recursion\nF = function (f)\n      return function (n)\n               if n == 0 then return 1\n               else return n*f(n-1) end\n             end\n    end\n\nfactorial = Y(F)   -- factorial is the fixed point of F\n\n-- now test it\nfunction test(x)\n\tio.write(x,\"! = \",factorial(x),\"\\n\")\nend\n\nfor n=0,16 do\n\ttest(n)\nend\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.8/deps/lua/test/fib.lua",
    "content": "-- fibonacci function with cache\n\n-- very inefficient fibonacci function\nfunction fib(n)\n\tN=N+1\n\tif n<2 then\n\t\treturn n\n\telse\n\t\treturn fib(n-1)+fib(n-2)\n\tend\nend\n\n-- a general-purpose value cache\nfunction cache(f)\n\tlocal c={}\n\treturn function (x)\n\t\tlocal y=c[x]\n\t\tif not y then\n\t\t\ty=f(x)\n\t\t\tc[x]=y\n\t\tend\n\t\treturn y\n\tend\nend\n\n-- run and time it\nfunction test(s,f)\n\tN=0\n\tlocal c=os.clock()\n\tlocal v=f(n)\n\tlocal t=os.clock()-c\n\tprint(s,n,v,t,N)\nend\n\nn=arg[1] or 24\t\t-- for other values, do lua fib.lua XX\nn=tonumber(n)\nprint(\"\",\"n\",\"value\",\"time\",\"evals\")\ntest(\"plain\",fib)\nfib=cache(fib)\ntest(\"cached\",fib)\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.8/deps/lua/test/fibfor.lua",
    "content": "-- example of for with generator functions\n\nfunction generatefib (n)\n  return coroutine.wrap(function ()\n    local a,b = 1, 1\n    while a <= n do\n      coroutine.yield(a)\n      a, b = b, a+b\n    end\n  end)\nend\n\nfor i in generatefib(1000) do print(i) end\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.8/deps/lua/test/globals.lua",
    "content": "-- reads luac listings and reports global variable usage\n-- lines where a global is written to are marked with \"*\"\n-- typical usage: luac -p -l file.lua | lua globals.lua | sort | lua table.lua\n\nwhile 1 do\n local s=io.read()\n if s==nil then break end\n local ok,_,l,op,g=string.find(s,\"%[%-?(%d*)%]%s*([GS])ETGLOBAL.-;%s+(.*)$\")\n if ok then\n  if op==\"S\" then op=\"*\" else op=\"\" end\n  io.write(g,\"\\t\",l,op,\"\\n\")\n end\nend\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.8/deps/lua/test/hello.lua",
    "content": "-- the first program in every language\n\nio.write(\"Hello world, from \",_VERSION,\"!\\n\")\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.8/deps/lua/test/life.lua",
    "content": "-- life.lua\n-- original by Dave Bollinger <DBollinger@compuserve.com> posted to lua-l\n-- modified to use ANSI terminal escape sequences\n-- modified to use for instead of while\n\nlocal write=io.write\n\nALIVE=\"\"\tDEAD=\"\"\nALIVE=\"O\"\tDEAD=\"-\"\n\nfunction delay() -- NOTE: SYSTEM-DEPENDENT, adjust as necessary\n  for i=1,10000 do end\n  -- local i=os.clock()+1 while(os.clock()<i) do end\nend\n\nfunction ARRAY2D(w,h)\n  local t = {w=w,h=h}\n  for y=1,h do\n    t[y] = {}\n    for x=1,w do\n      t[y][x]=0\n    end\n  end\n  return t\nend\n\n_CELLS = {}\n\n-- give birth to a \"shape\" within the cell array\nfunction _CELLS:spawn(shape,left,top)\n  for y=0,shape.h-1 do\n    for x=0,shape.w-1 do\n      self[top+y][left+x] = shape[y*shape.w+x+1]\n    end\n  end\nend\n\n-- run the CA and produce the next generation\nfunction _CELLS:evolve(next)\n  local ym1,y,yp1,yi=self.h-1,self.h,1,self.h\n  while yi > 0 do\n    local xm1,x,xp1,xi=self.w-1,self.w,1,self.w\n    while xi > 0 do\n      local sum = self[ym1][xm1] + self[ym1][x] + self[ym1][xp1] +\n                  self[y][xm1] + self[y][xp1] +\n                  self[yp1][xm1] + self[yp1][x] + self[yp1][xp1]\n      next[y][x] = ((sum==2) and self[y][x]) or ((sum==3) and 1) or 0\n      xm1,x,xp1,xi = x,xp1,xp1+1,xi-1\n    end\n    ym1,y,yp1,yi = y,yp1,yp1+1,yi-1\n  end\nend\n\n-- output the array to screen\nfunction _CELLS:draw()\n  local out=\"\" -- accumulate to reduce flicker\n  for y=1,self.h do\n   for x=1,self.w do\n      out=out..(((self[y][x]>0) and ALIVE) or DEAD)\n    end\n    out=out..\"\\n\"\n  end\n  write(out)\nend\n\n-- constructor\nfunction CELLS(w,h)\n  local c = ARRAY2D(w,h)\n  c.spawn = _CELLS.spawn\n  c.evolve = _CELLS.evolve\n  c.draw = _CELLS.draw\n  return c\nend\n\n--\n-- shapes suitable for use with spawn() above\n--\nHEART = { 1,0,1,1,0,1,1,1,1; w=3,h=3 }\nGLIDER = { 0,0,1,1,0,1,0,1,1; w=3,h=3 }\nEXPLODE = { 0,1,0,1,1,1,1,0,1,0,1,0; w=3,h=4 }\nFISH = { 0,1,1,1,1,1,0,0,0,1,0,0,0,0,1,1,0,0,1,0; w=5,h=4 }\nBUTTERFLY = { 1,0,0,0,1,0,1,1,1,0,1,0,0,0,1,1,0,1,0,1,1,0,0,0,1; w=5,h=5 }\n\n-- the main routine\nfunction LIFE(w,h)\n  -- create two arrays\n  local thisgen = CELLS(w,h)\n  local nextgen = CELLS(w,h)\n\n  -- create some life\n  -- about 1000 generations of fun, then a glider steady-state\n  thisgen:spawn(GLIDER,5,4)\n  thisgen:spawn(EXPLODE,25,10)\n  thisgen:spawn(FISH,4,12)\n\n  -- run until break\n  local gen=1\n  write(\"\\027[2J\")\t-- ANSI clear screen\n  while 1 do\n    thisgen:evolve(nextgen)\n    thisgen,nextgen = nextgen,thisgen\n    write(\"\\027[H\")\t-- ANSI home cursor\n    thisgen:draw()\n    write(\"Life - generation \",gen,\"\\n\")\n    gen=gen+1\n    if gen>2000 then break end\n    --delay()\t\t-- no delay\n  end\nend\n\nLIFE(40,20)\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.8/deps/lua/test/luac.lua",
    "content": "-- bare-bones luac in Lua\n-- usage: lua luac.lua file.lua\n\nassert(arg[1]~=nil and arg[2]==nil,\"usage: lua luac.lua file.lua\")\nf=assert(io.open(\"luac.out\",\"wb\"))\nassert(f:write(string.dump(assert(loadfile(arg[1])))))\nassert(f:close())\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.8/deps/lua/test/printf.lua",
    "content": "-- an implementation of printf\n\nfunction printf(...)\n io.write(string.format(...))\nend\n\nprintf(\"Hello %s from %s on %s\\n\",os.getenv\"USER\" or \"there\",_VERSION,os.date())\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.8/deps/lua/test/readonly.lua",
    "content": "-- make global variables readonly\n\nlocal f=function (t,i) error(\"cannot redefine global variable `\"..i..\"'\",2) end\nlocal g={}\nlocal G=getfenv()\nsetmetatable(g,{__index=G,__newindex=f})\nsetfenv(1,g)\n\n-- an example\nrawset(g,\"x\",3)\nx=2\ny=1\t-- cannot redefine `y'\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.8/deps/lua/test/sieve.lua",
    "content": "-- the sieve of of Eratosthenes programmed with coroutines\n-- typical usage: lua -e N=1000 sieve.lua | column\n\n-- generate all the numbers from 2 to n\nfunction gen (n)\n  return coroutine.wrap(function ()\n    for i=2,n do coroutine.yield(i) end\n  end)\nend\n\n-- filter the numbers generated by `g', removing multiples of `p'\nfunction filter (p, g)\n  return coroutine.wrap(function ()\n    while 1 do\n      local n = g()\n      if n == nil then return end\n      if math.mod(n, p) ~= 0 then coroutine.yield(n) end\n    end\n  end)\nend\n\nN=N or 1000\t\t-- from command line\nx = gen(N)\t\t-- generate primes up to N\nwhile 1 do\n  local n = x()\t\t-- pick a number until done\n  if n == nil then break end\n  print(n)\t\t-- must be a prime number\n  x = filter(n, x)\t-- now remove its multiples\nend\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.8/deps/lua/test/sort.lua",
    "content": "-- two implementations of a sort function\n-- this is an example only. Lua has now a built-in function \"sort\"\n\n-- extracted from Programming Pearls, page 110\nfunction qsort(x,l,u,f)\n if l<u then\n  local m=math.random(u-(l-1))+l-1\t-- choose a random pivot in range l..u\n  x[l],x[m]=x[m],x[l]\t\t\t-- swap pivot to first position\n  local t=x[l]\t\t\t\t-- pivot value\n  m=l\n  local i=l+1\n  while i<=u do\n    -- invariant: x[l+1..m] < t <= x[m+1..i-1]\n    if f(x[i],t) then\n      m=m+1\n      x[m],x[i]=x[i],x[m]\t\t-- swap x[i] and x[m]\n    end\n    i=i+1\n  end\n  x[l],x[m]=x[m],x[l]\t\t\t-- swap pivot to a valid place\n  -- x[l+1..m-1] < x[m] <= x[m+1..u]\n  qsort(x,l,m-1,f)\n  qsort(x,m+1,u,f)\n end\nend\n\nfunction selectionsort(x,n,f)\n local i=1\n while i<=n do\n  local m,j=i,i+1\n  while j<=n do\n   if f(x[j],x[m]) then m=j end\n   j=j+1\n  end\n x[i],x[m]=x[m],x[i]\t\t\t-- swap x[i] and x[m]\n i=i+1\n end\nend\n\nfunction show(m,x)\n io.write(m,\"\\n\\t\")\n local i=1\n while x[i] do\n  io.write(x[i])\n  i=i+1\n  if x[i] then io.write(\",\") end\n end\n io.write(\"\\n\")\nend\n\nfunction testsorts(x)\n local n=1\n while x[n] do n=n+1 end; n=n-1\t\t-- count elements\n show(\"original\",x)\n qsort(x,1,n,function (x,y) return x<y end)\n show(\"after quicksort\",x)\n selectionsort(x,n,function (x,y) return x>y end)\n show(\"after reverse selection sort\",x)\n qsort(x,1,n,function (x,y) return x<y end)\n show(\"after quicksort again\",x)\nend\n\n-- array to be sorted\nx={\"Jan\",\"Feb\",\"Mar\",\"Apr\",\"May\",\"Jun\",\"Jul\",\"Aug\",\"Sep\",\"Oct\",\"Nov\",\"Dec\"}\n\ntestsorts(x)\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.8/deps/lua/test/table.lua",
    "content": "-- make table, grouping all data for the same item\n-- input is 2 columns (item, data)\n\nlocal A\nwhile 1 do\n local l=io.read()\n if l==nil then break end\n local _,_,a,b=string.find(l,'\"?([_%w]+)\"?%s*(.*)$')\n if a~=A then A=a io.write(\"\\n\",a,\":\") end\n io.write(\" \",b)\nend\nio.write(\"\\n\")\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.8/deps/lua/test/trace-calls.lua",
    "content": "-- trace calls\n-- example: lua -ltrace-calls bisect.lua\n\nlocal level=0\n\nlocal function hook(event)\n local t=debug.getinfo(3)\n io.write(level,\" >>> \",string.rep(\" \",level))\n if t~=nil and t.currentline>=0 then io.write(t.short_src,\":\",t.currentline,\" \") end\n t=debug.getinfo(2)\n if event==\"call\" then\n  level=level+1\n else\n  level=level-1 if level<0 then level=0 end\n end\n if t.what==\"main\" then\n  if event==\"call\" then\n   io.write(\"begin \",t.short_src)\n  else\n   io.write(\"end \",t.short_src)\n  end\n elseif t.what==\"Lua\" then\n-- table.foreach(t,print)\n  io.write(event,\" \",t.name or \"(Lua)\",\" <\",t.linedefined,\":\",t.short_src,\">\")\n else\n io.write(event,\" \",t.name or \"(C)\",\" [\",t.what,\"] \")\n end\n io.write(\"\\n\")\nend\n\ndebug.sethook(hook,\"cr\")\nlevel=0\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.8/deps/lua/test/trace-globals.lua",
    "content": "-- trace assigments to global variables\n\ndo\n -- a tostring that quotes strings. note the use of the original tostring.\n local _tostring=tostring\n local tostring=function(a)\n  if type(a)==\"string\" then\n   return string.format(\"%q\",a)\n  else\n   return _tostring(a)\n  end\n end\n\n local log=function (name,old,new)\n  local t=debug.getinfo(3,\"Sl\")\n  local line=t.currentline\n  io.write(t.short_src)\n  if line>=0 then io.write(\":\",line) end\n  io.write(\": \",name,\" is now \",tostring(new),\" (was \",tostring(old),\")\",\"\\n\")\n end\n\n local g={}\n local set=function (t,name,value)\n  log(name,g[name],value)\n  g[name]=value\n end\n setmetatable(getfenv(),{__index=g,__newindex=set})\nend\n\n-- an example\n\na=1\nb=2\na=10\nb=20\nb=nil\nb=200\nprint(a,b,c)\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.8/deps/lua/test/xd.lua",
    "content": "-- hex dump\n-- usage: lua xd.lua < file\n\nlocal offset=0\nwhile true do\n local s=io.read(16)\n if s==nil then return end\n io.write(string.format(\"%08X  \",offset))\n string.gsub(s,\"(.)\",\n\tfunction (c) io.write(string.format(\"%02X \",string.byte(c))) end)\n io.write(string.rep(\" \",3*(16-string.len(s))))\n io.write(\" \",string.gsub(s,\"%c\",\".\"),\"\\n\") \n offset=offset+16\nend\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.8/deps/update-jemalloc.sh",
    "content": "#!/bin/bash\nVER=$1\nURL=\"http://www.canonware.com/download/jemalloc/jemalloc-${VER}.tar.bz2\"\necho \"Downloading $URL\"\ncurl $URL > /tmp/jemalloc.tar.bz2\ntar xvjf /tmp/jemalloc.tar.bz2\nrm -rf jemalloc\nmv jemalloc-${VER} jemalloc\necho \"Use git status, add all files and commit changes.\"\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.8/patch/Makefile",
    "content": "all:\n\npatch revert:\n\t@bash run.sh $@\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.8/patch/codis/0000-redis.patch",
    "content": "diff --git a/extern/redis-3.2.7/src/Makefile b/extern/redis-3.2.7/src/Makefile\nindex fdbe36a..68af785 100644\n--- a/extern/redis-3.2.7/src/Makefile\n+++ b/extern/redis-3.2.7/src/Makefile\n@@ -127,7 +127,7 @@ endif\n \n REDIS_SERVER_NAME=redis-server\n REDIS_SENTINEL_NAME=redis-sentinel\n-REDIS_SERVER_OBJ=adlist.o quicklist.o ae.o anet.o dict.o server.o sds.o zmalloc.o lzf_c.o lzf_d.o pqsort.o zipmap.o sha1.o ziplist.o release.o networking.o util.o object.o db.o replication.o rdb.o t_string.o t_list.o t_set.o t_zset.o t_hash.o config.o aof.o pubsub.o multi.o debug.o sort.o intset.o syncio.o cluster.o crc16.o endianconv.o slowlog.o scripting.o bio.o rio.o rand.o memtest.o crc64.o bitops.o sentinel.o notify.o setproctitle.o blocked.o hyperloglog.o latency.o sparkline.o redis-check-rdb.o geo.o\n+REDIS_SERVER_OBJ=adlist.o quicklist.o ae.o anet.o dict.o server.o sds.o zmalloc.o lzf_c.o lzf_d.o pqsort.o zipmap.o sha1.o ziplist.o release.o networking.o util.o object.o db.o replication.o rdb.o t_string.o t_list.o t_set.o t_zset.o t_hash.o config.o aof.o pubsub.o multi.o debug.o sort.o intset.o syncio.o cluster.o crc16.o endianconv.o slowlog.o scripting.o bio.o rio.o rand.o memtest.o crc64.o bitops.o sentinel.o notify.o setproctitle.o blocked.o hyperloglog.o latency.o sparkline.o redis-check-rdb.o geo.o slots.o crc32.o\n REDIS_GEOHASH_OBJ=../deps/geohash-int/geohash.o ../deps/geohash-int/geohash_helper.o\n REDIS_CLI_NAME=redis-cli\n REDIS_CLI_OBJ=anet.o adlist.o redis-cli.o zmalloc.o release.o anet.o ae.o crc64.o\ndiff --git a/extern/redis-3.2.7/src/Makefile.dep b/extern/redis-3.2.7/src/Makefile.dep\nindex 9af8331..ddedf6a 100644\n--- a/extern/redis-3.2.7/src/Makefile.dep\n+++ b/extern/redis-3.2.7/src/Makefile.dep\n@@ -67,6 +67,8 @@ latency.o: latency.c server.h fmacros.h config.h solarisfixes.h \\\n lzf_c.o: lzf_c.c lzfP.h\n lzf_d.o: lzf_d.c lzfP.h\n memtest.o: memtest.c config.h\n+crc32.o: crc32.c\n+slots.o: slots.c server.h\n multi.o: multi.c server.h fmacros.h config.h solarisfixes.h \\\n  ../deps/lua/src/lua.h ../deps/lua/src/luaconf.h ae.h sds.h dict.h \\\n  adlist.h zmalloc.h anet.h ziplist.h intset.h version.h util.h latency.h \\\ndiff --git a/extern/redis-3.2.7/src/crc32.c b/extern/redis-3.2.7/src/crc32.c\nnew file mode 100644\nindex 0000000..cc7ae86\n--- /dev/null\n+++ b/extern/redis-3.2.7/src/crc32.c\n@@ -0,0 +1,41 @@\n+#include <stdint.h>\n+\n+static const uint32_t IEEE_POLY = 0xedb88320;\n+\n+static uint32_t crc32tab[256];\n+\n+static void\n+crc32_tabinit(uint32_t poly) {\n+    int i, j;\n+    for (i = 0; i < 256; i ++) {\n+        uint32_t crc = i;\n+        for (j = 0; j < 8; j ++) {\n+            if (crc & 1) {\n+                crc = (crc >> 1) ^ poly;\n+            } else {\n+                crc = (crc >> 1);\n+            }\n+        }\n+        crc32tab[i] = crc;\n+    }\n+}\n+\n+void\n+crc32_init() {\n+    crc32_tabinit(IEEE_POLY);\n+}\n+\n+static uint32_t\n+crc32_update(uint32_t crc, const char *buf, int len) {\n+    int i;\n+    crc = ~crc;\n+    for (i = 0; i < len; i ++) {\n+        crc = crc32tab[(uint8_t)((char)crc ^ buf[i])] ^ (crc >> 8);\n+    }\n+    return ~crc;\n+}\n+\n+uint32_t\n+crc32_checksum(const char *buf, int len) {\n+    return crc32_update(0, buf, len);\n+}\ndiff --git a/extern/redis-3.2.7/src/db.c b/extern/redis-3.2.7/src/db.c\nindex fba731c..fa79e54 100644\n--- a/extern/redis-3.2.7/src/db.c\n+++ b/extern/redis-3.2.7/src/db.c\n@@ -158,6 +158,17 @@ void dbAdd(redisDb *db, robj *key, robj *val) {\n     sds copy = sdsdup(key->ptr);\n     int retval = dictAdd(db->dict, copy, val);\n \n+    do {\n+        uint32_t crc;\n+        int hastag;\n+        int slot = slots_num(key->ptr, &crc, &hastag);\n+        dictAdd(db->hash_slots[slot], copy, (void *)(long)crc);\n+        if (hastag) {\n+            incrRefCount(key);\n+            zslInsert(db->tagged_keys, (double)crc, key);\n+        }\n+    } while (0);\n+\n     serverAssertWithInfo(NULL,key,retval == DICT_OK);\n     if (val->type == OBJ_LIST) signalListAsReady(db, key);\n     if (server.cluster_enabled) slotToKeyAdd(key);\n@@ -227,6 +238,18 @@ int dbDelete(redisDb *db, robj *key) {\n     /* Deleting an entry from the expires dict will not free the sds of\n      * the key, because it is shared with the main dictionary. */\n     if (dictSize(db->expires) > 0) dictDelete(db->expires,key->ptr);\n+\n+    do {\n+        uint32_t crc;\n+        int hastag;\n+        int slot = slots_num(key->ptr, &crc, &hastag);\n+        if (dictDelete(db->hash_slots[slot], key->ptr) == DICT_OK) {\n+            if (hastag) {\n+                zslDelete(db->tagged_keys, (double)crc, key);\n+            }\n+        }\n+    } while (0);\n+\n     if (dictDelete(db->dict,key->ptr) == DICT_OK) {\n         if (server.cluster_enabled) slotToKeyDel(key);\n         return 1;\n@@ -274,11 +297,18 @@ robj *dbUnshareStringValue(redisDb *db, robj *key, robj *o) {\n }\n \n long long emptyDb(void(callback)(void*)) {\n-    int j;\n+    int i, j;\n     long long removed = 0;\n \n     for (j = 0; j < server.dbnum; j++) {\n         removed += dictSize(server.db[j].dict);\n+        for (i = 0; i < HASH_SLOTS_SIZE; i ++) {\n+            dictEmpty(server.db[j].hash_slots[i], NULL);\n+        }\n+        if (server.db[j].tagged_keys->length != 0) {\n+            zslFree(server.db[j].tagged_keys);\n+            server.db[j].tagged_keys = zslCreate();\n+        }\n         dictEmpty(server.db[j].dict,callback);\n         dictEmpty(server.db[j].expires,callback);\n     }\n@@ -315,8 +345,16 @@ void signalFlushedDb(int dbid) {\n  *----------------------------------------------------------------------------*/\n \n void flushdbCommand(client *c) {\n+    int i;\n     server.dirty += dictSize(c->db->dict);\n     signalFlushedDb(c->db->id);\n+    for (i = 0; i < HASH_SLOTS_SIZE; i ++) {\n+        dictEmpty(c->db->hash_slots[i], NULL);\n+    }\n+    if (c->db->tagged_keys->length != 0) {\n+        zslFree(c->db->tagged_keys);\n+        c->db->tagged_keys = zslCreate();\n+    }\n     dictEmpty(c->db->dict,NULL);\n     dictEmpty(c->db->expires,NULL);\n     if (server.cluster_enabled) slotToKeyFlush();\n@@ -724,7 +762,15 @@ void shutdownCommand(client *c) {\n      * Also when in Sentinel mode clear the SAVE flag and force NOSAVE. */\n     if (server.loading || server.sentinel_mode)\n         flags = (flags & ~SHUTDOWN_SAVE) | SHUTDOWN_NOSAVE;\n-    if (prepareForShutdown(flags) == C_OK) exit(0);\n+    if (prepareForShutdown(flags) == C_OK) {\n+        for (int j = 0; j < server.dbnum; j ++) {\n+            for (int i = 0; i < HASH_SLOTS_SIZE; i ++) {\n+                dictRelease(server.db[j].hash_slots[i]);\n+            }\n+            zslFree(server.db[j].tagged_keys);\n+        }\n+        exit(0);\n+    }\n     addReplyError(c,\"Errors trying to SHUTDOWN. Check logs.\");\n }\n \ndiff --git a/extern/redis-3.2.7/src/server.c b/extern/redis-3.2.7/src/server.c\nindex 71bcda7..983d1b1 100644\n--- a/extern/redis-3.2.7/src/server.c\n+++ b/extern/redis-3.2.7/src/server.c\n@@ -296,7 +296,16 @@ struct redisCommand redisCommandTable[] = {\n     {\"pfdebug\",pfdebugCommand,-3,\"w\",0,NULL,0,0,0,0,0},\n     {\"post\",securityWarningCommand,-1,\"lt\",0,NULL,0,0,0,0,0},\n     {\"host:\",securityWarningCommand,-1,\"lt\",0,NULL,0,0,0,0,0},\n-    {\"latency\",latencyCommand,-2,\"aslt\",0,NULL,0,0,0,0,0}\n+    {\"latency\",latencyCommand,-2,\"aslt\",0,NULL,0,0,0,0,0},\n+    {\"slotsinfo\",slotsinfoCommand,-1,\"rF\",0,NULL,0,0,0,0,0},\n+    {\"slotsdel\",slotsdelCommand,-2,\"w\",0,NULL,1,-1,1,0,0},\n+    {\"slotsmgrtslot\",slotsmgrtslotCommand,5,\"aw\",0,NULL,0,0,0,0,0},\n+    {\"slotsmgrtone\",slotsmgrtoneCommand,5,\"aw\",0,NULL,0,0,0,0,0},\n+    {\"slotsmgrttagslot\",slotsmgrttagslotCommand,5,\"aw\",0,NULL,0,0,0,0,0},\n+    {\"slotsmgrttagone\",slotsmgrttagoneCommand,5,\"aw\",0,NULL,0,0,0,0,0},\n+    {\"slotshashkey\",slotshashkeyCommand,-1,\"rF\",0,NULL,0,0,0,0,0},\n+    {\"slotscheck\",slotscheckCommand,0,\"r\",0,NULL,0,0,0,0,0},\n+    {\"slotsrestore\",slotsrestoreCommand,-4,\"awm\",0,NULL,1,1,1,0,0},\n };\n \n struct evictionPoolEntry *evictionPoolAlloc(void);\n@@ -564,6 +573,15 @@ dictType dbDictType = {\n     dictObjectDestructor   /* val destructor */\n };\n \n+dictType hashSlotType = {\n+    dictSdsHash,                /* hash function */\n+    NULL,                       /* key dup */\n+    NULL,                       /* val dup */\n+    dictSdsKeyCompare,          /* key compare */\n+    NULL,                       /* key destructor */\n+    NULL                        /* val destructor */\n+};\n+\n /* server.lua_scripts sha (as sds string) -> scripts (as robj) cache. */\n dictType shaScriptObjectDictType = {\n     dictSdsCaseHash,            /* hash function */\n@@ -673,8 +691,15 @@ int htNeedsResize(dict *dict) {\n /* If the percentage of used slots in the HT reaches HASHTABLE_MIN_FILL\n  * we resize the hash table to save memory */\n void tryResizeHashTables(int dbid) {\n-    if (htNeedsResize(server.db[dbid].dict))\n+    if (htNeedsResize(server.db[dbid].dict)) {\n         dictResize(server.db[dbid].dict);\n+        for (int i = 0; i < HASH_SLOTS_SIZE; i ++) {\n+            dict *d = server.db[dbid].hash_slots[i];\n+            if (htNeedsResize(d)) {\n+                dictResize(d);\n+            }\n+        }\n+    }\n     if (htNeedsResize(server.db[dbid].expires))\n         dictResize(server.db[dbid].expires);\n }\n@@ -690,6 +715,12 @@ int incrementallyRehash(int dbid) {\n     /* Keys dictionary */\n     if (dictIsRehashing(server.db[dbid].dict)) {\n         dictRehashMilliseconds(server.db[dbid].dict,1);\n+        for (int i = 0; i < HASH_SLOTS_SIZE; i ++) {\n+            dict *d = server.db[dbid].hash_slots[i];\n+            if (dictIsRehashing(d)) {\n+                dictRehashMilliseconds(d, 1);\n+            }\n+        }\n         return 1; /* already used our millisecond for this loop... */\n     }\n     /* Expires */\n@@ -1283,6 +1314,10 @@ int serverCron(struct aeEventLoop *eventLoop, long long id, void *clientData) {\n         if (server.sentinel_mode) sentinelTimer();\n     }\n \n+    run_with_period(1000) {\n+        slotsmgrt_cleanup();\n+    }\n+\n     /* Cleanup expired MIGRATE cached sockets. */\n     run_with_period(1000) {\n         migrateCloseTimedoutSockets();\n@@ -1534,6 +1569,8 @@ void initServerConfig(void) {\n     server.next_client_id = 1; /* Client IDs, start from 1 .*/\n     server.loading_process_events_interval_bytes = (1024*1024*2);\n \n+    server.slotsmgrt_cached_sockfds = dictCreate(&migrateCacheDictType, NULL);\n+\n     server.lruclock = getLRUClock();\n     resetServerSaveParams();\n \n@@ -1860,12 +1897,14 @@ void resetServerStats(void) {\n }\n \n void initServer(void) {\n-    int j;\n+    int i, j;\n \n     signal(SIGHUP, SIG_IGN);\n     signal(SIGPIPE, SIG_IGN);\n     setupSignalHandlers();\n \n+    crc32_init();\n+\n     if (server.syslog_enabled) {\n         openlog(server.syslog_ident, LOG_PID | LOG_NDELAY | LOG_NOWAIT,\n             server.syslog_facility);\n@@ -1924,6 +1963,10 @@ void initServer(void) {\n         server.db[j].eviction_pool = evictionPoolAlloc();\n         server.db[j].id = j;\n         server.db[j].avg_ttl = 0;\n+        for (i = 0; i < HASH_SLOTS_SIZE; i ++) {\n+            server.db[j].hash_slots[i] = dictCreate(&hashSlotType, NULL);\n+        }\n+        server.db[j].tagged_keys = zslCreate();\n     }\n     server.pubsub_channels = dictCreate(&keylistDictType,NULL);\n     server.pubsub_patterns = listCreate();\ndiff --git a/extern/redis-3.2.7/src/server.h b/extern/redis-3.2.7/src/server.h\nindex 3fa7c3a..e7681c5 100644\n--- a/extern/redis-3.2.7/src/server.h\n+++ b/extern/redis-3.2.7/src/server.h\n@@ -498,6 +498,14 @@ struct evictionPoolEntry {\n     sds key;                    /* Key name. */\n };\n \n+void crc32_init();\n+uint32_t crc32_checksum(const char *buf, int len);\n+\n+#define HASH_SLOTS_MASK 0x000003ff\n+#define HASH_SLOTS_SIZE (HASH_SLOTS_MASK + 1)\n+\n+struct zskiplist;\n+\n /* Redis database representation. There are multiple databases identified\n  * by integers from 0 (the default database) up to the max configured\n  * database. The database number is the 'id' field in the structure. */\n@@ -507,6 +515,8 @@ typedef struct redisDb {\n     dict *blocking_keys;        /* Keys with clients waiting for data (BLPOP) */\n     dict *ready_keys;           /* Blocked keys that received a PUSH */\n     dict *watched_keys;         /* WATCHED keys for MULTI/EXEC CAS */\n+    dict *hash_slots[HASH_SLOTS_SIZE];\n+    struct zskiplist *tagged_keys;\n     struct evictionPoolEntry *eviction_pool;    /* Eviction pool of keys */\n     int id;                     /* Database ID */\n     long long avg_ttl;          /* Average TTL, just for stats */\n@@ -741,6 +751,7 @@ struct redisServer {\n     int clients_paused;         /* True if clients are currently paused */\n     mstime_t clients_pause_end_time; /* Time when we undo clients_paused */\n     char neterr[ANET_ERR_LEN];   /* Error buffer for anet.c */\n+    dict *slotsmgrt_cached_sockfds;\n     dict *migrate_cached_sockets;/* MIGRATE cached sockets */\n     uint64_t next_client_id;    /* Next client unique ID. Incremental. */\n     int protected_mode;         /* Don't accept external connections. */\n@@ -1647,6 +1658,19 @@ void pfdebugCommand(client *c);\n void latencyCommand(client *c);\n void securityWarningCommand(client *c);\n \n+void slotsinfoCommand(client *c);\n+void slotsdelCommand(client *c);\n+void slotsmgrtslotCommand(client *c);\n+void slotsmgrtoneCommand(client *c);\n+void slotsmgrttagslotCommand(client *c);\n+void slotsmgrttagoneCommand(client *c);\n+void slotshashkeyCommand(client *c);\n+void slotscheckCommand(client *c);\n+void slotsrestoreCommand(client *c);\n+\n+void slotsmgrt_cleanup();\n+int slots_num(const sds s, uint32_t *pcrc, int *phastag);\n+\n #if defined(__GNUC__)\n void *calloc(size_t count, size_t size) __attribute__ ((deprecated));\n void free(void *ptr) __attribute__ ((deprecated));\ndiff --git a/extern/redis-3.2.7/src/slots.c b/extern/redis-3.2.7/src/slots.c\nnew file mode 100644\nindex 0000000..ff23492\n--- /dev/null\n+++ b/extern/redis-3.2.7/src/slots.c\n@@ -0,0 +1,817 @@\n+#include \"server.h\"\n+\n+extern void createDumpPayload(rio *payload, robj *o);\n+extern int verifyDumpPayload(unsigned char *p, size_t len);\n+\n+static void *\n+slots_tag(const sds s, int *plen) {\n+    int i, j, n = sdslen(s);\n+    for (i = 0; i < n && s[i] != '{'; i ++) {}\n+    if (i == n) {\n+        return NULL;\n+    }\n+    i ++;\n+    for (j = i; j < n && s[j] != '}'; j ++) {}\n+    if (j == n) {\n+        return NULL;\n+    }\n+    if (plen != NULL) {\n+        *plen = j - i;\n+    }\n+    return s + i;\n+}\n+\n+int\n+slots_num(const sds s, uint32_t *pcrc, int *phastag) {\n+    int taglen;\n+    int hastag = 0;\n+    void *tag = slots_tag(s, &taglen);\n+    if (tag == NULL) {\n+        tag = s, taglen = sdslen(s);\n+    } else {\n+        hastag = 1;\n+    }\n+    uint32_t crc = crc32_checksum(tag, taglen);\n+    if (pcrc != NULL) {\n+        *pcrc = crc;\n+    }\n+    if (phastag != NULL) {\n+        *phastag = hastag;\n+    }\n+    return crc & HASH_SLOTS_MASK;\n+}\n+\n+static int\n+parse_int(client *c, robj *obj, int *p) {\n+    long v;\n+    if (getLongFromObjectOrReply(c, obj, &v, NULL) != C_OK) {\n+        return -1;\n+    }\n+    *p = v;\n+    return 0;\n+}\n+\n+static int\n+parse_timeout(client *c, robj *obj, int *p) {\n+    int v;\n+    if (parse_int(c, obj, &v) != 0) {\n+        return -1;\n+    }\n+    if (v < 0) {\n+        addReplyErrorFormat(c, \"invalid timeout = %d\", v);\n+        return -1;\n+    }\n+    *p = (v == 0) ? 100 : v;\n+    return 0;\n+}\n+\n+static int\n+parse_slot(client *c, robj *obj, int *p) {\n+    int v;\n+    if (parse_int(c, obj, &v) != 0) {\n+        return -1;\n+    }\n+    if (v < 0 || v >= HASH_SLOTS_SIZE) {\n+        addReplyErrorFormat(c, \"invalid slot number = %d\", v);\n+        return -1;\n+    }\n+    *p = v;\n+    return 0;\n+}\n+\n+/* *\n+ * slotshashkey [key1 key2...]\n+ * */\n+void\n+slotshashkeyCommand(client *c) {\n+    int i;\n+    addReplyMultiBulkLen(c, c->argc - 1);\n+    for (i = 1; i < c->argc; i ++) {\n+        robj *key = c->argv[i];\n+        addReplyLongLong(c, slots_num(key->ptr, NULL, NULL));\n+    }\n+}\n+\n+/* *\n+ * slotsinfo [start] [count]\n+ * */\n+void\n+slotsinfoCommand(client *c) {\n+    int slots_slot[HASH_SLOTS_SIZE];\n+    int slots_size[HASH_SLOTS_SIZE];\n+    int n = 0, beg = 0, end = HASH_SLOTS_SIZE;\n+    if (c->argc >= 2) {\n+        if (parse_slot(c, c->argv[1], &beg) != 0) {\n+            return;\n+        }\n+    }\n+    if (c->argc >= 3) {\n+        int v;\n+        if (parse_int(c, c->argv[2], &v) != 0) {\n+            return;\n+        }\n+        if (v < 0) {\n+            addReplyErrorFormat(c, \"invalid slot count = %d\", v);\n+            return;\n+        }\n+        if (beg + v < end) {\n+            end = beg + v;\n+        }\n+    }\n+    if (c->argc >= 4) {\n+        addReplyErrorFormat(c, \"wrong number of arguments for 'slotsinfo' command\");\n+        return;\n+    }\n+    int i;\n+    for (i = beg; i < end; i ++) {\n+        int s = dictSize(c->db->hash_slots[i]);\n+        if (s == 0) {\n+            continue;\n+        }\n+        slots_slot[n] = i;\n+        slots_size[n] = s;\n+        n ++;\n+    }\n+    addReplyMultiBulkLen(c, n);\n+    for (i = 0; i < n; i ++) {\n+        addReplyMultiBulkLen(c, 2);\n+        addReplyLongLong(c, slots_slot[i]);\n+        addReplyLongLong(c, slots_size[i]);\n+    }\n+}\n+\n+typedef struct {\n+    int fd;\n+    int db;\n+    int authorized;\n+    time_t lasttime;\n+} slotsmgrt_sockfd;\n+\n+static slotsmgrt_sockfd *\n+slotsmgrt_get_sockfd(client *c, sds host, sds port, int timeout) {\n+    sds name = sdsempty();\n+    name = sdscatlen(name, host, sdslen(host));\n+    name = sdscatlen(name, \":\", 1);\n+    name = sdscatlen(name, port, sdslen(port));\n+\n+    slotsmgrt_sockfd *pfd = dictFetchValue(server.slotsmgrt_cached_sockfds, name);\n+    if (pfd != NULL) {\n+        sdsfree(name);\n+        pfd->lasttime = server.unixtime;\n+        return pfd;\n+    }\n+\n+    int fd = anetTcpNonBlockConnect(server.neterr, host, atoi(port));\n+    if (fd == -1) {\n+        serverLog(LL_WARNING, \"slotsmgrt: connect to target %s:%s, error = '%s'\",\n+                host, port, server.neterr);\n+        sdsfree(name);\n+        addReplyErrorFormat(c,\"Can't connect to target node: %s\", server.neterr);\n+        return NULL;\n+    }\n+    anetEnableTcpNoDelay(server.neterr, fd);\n+    if ((aeWait(fd, AE_WRITABLE, timeout) & AE_WRITABLE) == 0) {\n+        serverLog(LL_WARNING, \"slotsmgrt: connect to target %s:%s, aewait error = '%s'\",\n+                host, port, server.neterr);\n+        sdsfree(name);\n+        close(fd);\n+        addReplySds(c, sdsnew(\"-IOERR error or timeout connecting to the client\\r\\n\"));\n+        return NULL;\n+    }\n+    serverLog(LL_WARNING, \"slotsmgrt: connect to target %s:%s\", host, port);\n+\n+    pfd = zmalloc(sizeof(*pfd));\n+    pfd->fd = fd;\n+    pfd->db = -1;\n+    pfd->authorized = (server.requirepass == NULL) ? 1 : 0;\n+    pfd->lasttime = server.unixtime;\n+    dictAdd(server.slotsmgrt_cached_sockfds, name, pfd);\n+    return pfd;\n+}\n+\n+static void\n+slotsmgrt_close_socket(sds host, sds port) {\n+    sds name = sdsempty();\n+    name = sdscatlen(name, host, sdslen(host));\n+    name = sdscatlen(name, \":\", 1);\n+    name = sdscatlen(name, port, sdslen(port));\n+\n+    slotsmgrt_sockfd *pfd = dictFetchValue(server.slotsmgrt_cached_sockfds, name);\n+    if (pfd == NULL) {\n+        serverLog(LL_WARNING, \"slotsmgrt: close target %s:%s again\", host, port);\n+        sdsfree(name);\n+        return;\n+    } else {\n+        serverLog(LL_WARNING, \"slotsmgrt: close target %s:%s\", host, port);\n+    }\n+    dictDelete(server.slotsmgrt_cached_sockfds, name);\n+    close(pfd->fd);\n+    zfree(pfd);\n+    sdsfree(name);\n+}\n+\n+void\n+slotsmgrt_cleanup() {\n+    dictIterator *di = dictGetSafeIterator(server.slotsmgrt_cached_sockfds);\n+    dictEntry *de;\n+    while((de = dictNext(di)) != NULL) {\n+        slotsmgrt_sockfd *pfd = dictGetVal(de);\n+        if ((server.unixtime - pfd->lasttime) > 15) {\n+            serverLog(LL_WARNING, \"slotsmgrt: timeout target %s, lasttime = %ld, now = %ld\",\n+                   (char *)dictGetKey(de), pfd->lasttime, server.unixtime);\n+            dictDelete(server.slotsmgrt_cached_sockfds, dictGetKey(de));\n+            close(pfd->fd);\n+            zfree(pfd);\n+        }\n+    }\n+    dictReleaseIterator(di);\n+}\n+\n+static int\n+slotsmgrt(client *c, sds host, sds port, slotsmgrt_sockfd *pfd, int db, int timeout, robj *keys[], robj *vals[], int n) {\n+    rio cmd;\n+    rioInitWithBuffer(&cmd, sdsempty());\n+\n+    int needauth = 0;\n+    if (pfd->authorized == 0 && server.requirepass != NULL) {\n+        needauth = 1;\n+        serverAssertWithInfo(c, NULL, rioWriteBulkCount(&cmd, '*', 2));\n+        serverAssertWithInfo(c, NULL, rioWriteBulkString(&cmd, \"AUTH\", 4));\n+        serverAssertWithInfo(c, NULL, rioWriteBulkString(&cmd, server.requirepass, strlen(server.requirepass)));\n+    }\n+\n+    int selectdb = 0;\n+    if (pfd->db != db) {\n+        selectdb = 1;\n+        serverAssertWithInfo(c, NULL, rioWriteBulkCount(&cmd, '*', 2));\n+        serverAssertWithInfo(c, NULL, rioWriteBulkString(&cmd, \"SELECT\", 6));\n+        serverAssertWithInfo(c, NULL, rioWriteBulkLongLong(&cmd, db));\n+    }\n+\n+    serverAssertWithInfo(c, NULL, rioWriteBulkCount(&cmd, '*', 1 + 3 * n));\n+    serverAssertWithInfo(c, NULL, rioWriteBulkString(&cmd, \"SLOTSRESTORE\", 12));\n+\n+    sds onekey = NULL;\n+    for (int i = 0; i < n; i ++) {\n+        robj *key = keys[i], *val = vals[i];\n+        long long ttl = 0, expireat = getExpire(c->db, key);\n+        if (expireat != -1) {\n+            ttl = expireat - mstime();\n+            if (ttl < 1) {\n+                ttl = 1;\n+            }\n+        }\n+        sds skey = key->ptr;\n+        serverAssertWithInfo(c, NULL, rioWriteBulkString(&cmd, skey, sdslen(skey)));\n+        serverAssertWithInfo(c, NULL, rioWriteBulkLongLong(&cmd, ttl));\n+        do {\n+            rio pld;\n+            createDumpPayload(&pld, val);\n+            sds buf = pld.io.buffer.ptr;\n+            serverAssertWithInfo(c, NULL, rioWriteBulkString(&cmd, buf, sdslen(buf)));\n+            sdsfree(buf);\n+        } while (0);\n+        if (onekey == NULL) {\n+            onekey = skey;\n+        }\n+    }\n+\n+    do {\n+        sds buf = cmd.io.buffer.ptr;\n+        size_t pos = 0, towrite;\n+        int nwritten = 0;\n+        while ((towrite = sdslen(buf) - pos) > 0) {\n+            towrite = (towrite > (64 * 1024) ? (64 * 1024) : towrite);\n+            nwritten = syncWrite(pfd->fd, buf + pos, towrite, timeout);\n+            if (nwritten != (signed)towrite) {\n+                serverLog(LL_WARNING, \"slotsmgrt: writing to target %s:%s, error '%s', \"\n+                        \"nkeys = %d, onekey = '%s', cmd.len = %ld, pos = %ld, towrite = %ld\",\n+                        host, port, server.neterr, n, onekey, sdslen(buf), pos, towrite);\n+                addReplySds(c, sdsnew(\"-IOERR error or timeout writing to target\\r\\n\"));\n+                sdsfree(buf);\n+                return -1;\n+            }\n+            pos += nwritten;\n+        }\n+        sdsfree(buf);\n+    } while (0);\n+\n+    do {\n+        char buf[1024];\n+        if (needauth) {\n+            if (syncReadLine(pfd->fd, buf, sizeof(buf), timeout) <= 0) {\n+                serverLog(LL_WARNING, \"slotsmgrt: auth failed, reading from target %s:%s: nkeys = %d, onekey = '%s', error = '%s'\",\n+                        host, port, n, onekey, server.neterr);\n+                addReplySds(c, sdsnew(\"-IOERR error or timeout reading from target\\r\\n\"));\n+                return -1;\n+            }\n+            if (buf[0] != '+') {\n+                serverLog(LL_WARNING, \"slotsmgrt: auth failed, reading from target %s:%s: nkeys = %d, onekey = '%s', response = '%s'\",\n+                        host, port, n, onekey, buf);\n+                addReplyError(c, \"error on slotsrestore, auth failed\");\n+                return -1;\n+            }\n+            pfd->authorized = 1;\n+        }\n+\n+        if (selectdb) {\n+            if (syncReadLine(pfd->fd, buf, sizeof(buf), timeout) <= 0) {\n+                serverLog(LL_WARNING, \"slotsmgrt: select failed, reading from target %s:%s: nkeys = %d, onekey = '%s', error = '%s'\",\n+                        host, port, n, onekey, server.neterr);\n+                addReplySds(c, sdsnew(\"-IOERR error or timeout reading from target\\r\\n\"));\n+                return -1;\n+            }\n+            if (buf[0] != '+') {\n+                serverLog(LL_WARNING, \"slotsmgrt: select failed, reading from target %s:%s: nkeys = %d, onekey = '%s', response = '%s'\",\n+                        host, port, n, onekey, buf);\n+                addReplyError(c, \"error on slotsrestore, select failed\");\n+                return -1;\n+            }\n+            pfd->db = db;\n+        }\n+\n+        if (syncReadLine(pfd->fd, buf, sizeof(buf), timeout) <= 0) {\n+            serverLog(LL_WARNING, \"slotsmgrt: migration failed, reading from target %s:%s: nkeys = %d, onekey = '%s', error = '%s'\",\n+                    host, port, n, onekey, server.neterr);\n+            addReplySds(c, sdsnew(\"-IOERR error or timeout reading from target\\r\\n\"));\n+            return -1;\n+        }\n+        if (buf[0] == '-') {\n+            serverLog(LL_WARNING, \"slotsmgrt: migration failed, reading from target %s:%s: nkeys = %d, onekey = '%s', response = '%s'\",\n+                    host, port, n, onekey, buf);\n+            addReplyError(c, \"error on slotsrestore, migration failed\");\n+            return -1;\n+        }\n+    } while (0);\n+\n+    pfd->lasttime = server.unixtime;\n+\n+    serverLog(LL_VERBOSE, \"slotsmgrt: migrate to %s:%s, nkeys = %d, onekey = '%s'\", host, port, n, onekey);\n+    return 0;\n+}\n+\n+static void\n+slotsremove(client *c, robj **keys, int n, int rewrite) {\n+    for (int i = 0; i < n; i ++) {\n+        dbDelete(c->db, keys[i]);\n+        signalModifiedKey(c->db, keys[i]);\n+        server.dirty ++;\n+    }\n+    if (!rewrite) {\n+        return;\n+    }\n+    for (int i = 0; i < n; i ++) {\n+        incrRefCount(keys[i]);\n+    }\n+    for (int i = 0; i < c->argc; i ++) {\n+        decrRefCount(c->argv[i]);\n+    }\n+    zfree(c->argv);\n+    c->argc = n + 1;\n+    c->argv = zmalloc(sizeof(robj *) * c->argc);\n+    c->argv[0] = createStringObject(\"DEL\", 3);\n+    for (int i = 0; i < n; i ++) {\n+        c->argv[i + 1] = keys[i];\n+    }\n+    c->cmd = lookupCommandOrOriginal(c->argv[0]->ptr);\n+    serverAssertWithInfo(c, NULL, c->cmd != NULL);\n+}\n+\n+/* *\n+ * do migrate a key-value for slotsmgrt/slotsmgrtone commands\n+ * return value:\n+ *    -1 - error happens\n+ *   >=0 - # of success migration (0 or 1)\n+ * */\n+static int\n+slotsmgrtone_command(client *c, sds host, sds port, int timeout, robj *key) {\n+    slotsmgrt_sockfd *pfd = slotsmgrt_get_sockfd(c, host, port, timeout);\n+    if (pfd == NULL) {\n+        return -1;\n+    }\n+\n+    robj *val = lookupKeyWrite(c->db, key);\n+    if (val == NULL) {\n+        return 0;\n+    }\n+    robj *keys[] = {key};\n+    robj *vals[] = {val};\n+    if (slotsmgrt(c, host, port, pfd, c->db->id, timeout, keys, vals, 1) != 0) {\n+        slotsmgrt_close_socket(host, port);\n+        return -1;\n+    }\n+    slotsremove(c, keys, 1, 1);\n+    return 1;\n+}\n+\n+/* *\n+ * slotsmgrtslot host port timeout slot\n+ * */\n+void\n+slotsmgrtslotCommand(client *c) {\n+    sds host = c->argv[1]->ptr;\n+    sds port = c->argv[2]->ptr;\n+    int timeout, slot;\n+    if (parse_timeout(c, c->argv[3], &timeout) != 0) {\n+        return;\n+    }\n+    if (parse_slot(c, c->argv[4], &slot) != 0) {\n+        return;\n+    }\n+\n+    dict *d = c->db->hash_slots[slot];\n+    int succ = 0;\n+    do {\n+        const dictEntry *de = dictGetRandomKey(d);\n+        if (de == NULL) {\n+            break;\n+        }\n+        sds skey = dictGetKey(de);\n+        robj *key = createStringObject(skey, sdslen(skey));\n+        succ = slotsmgrtone_command(c, host, port, timeout, key);\n+        decrRefCount(key);\n+        if (succ < 0) {\n+            return;\n+        }\n+    } while (0);\n+    addReplyMultiBulkLen(c, 2);\n+    addReplyLongLong(c, succ);\n+    addReplyLongLong(c, dictSize(d));\n+}\n+\n+/* *\n+ * slotsmgrtone host port timeout key\n+ * */\n+void\n+slotsmgrtoneCommand(client *c) {\n+    sds host = c->argv[1]->ptr;\n+    sds port = c->argv[2]->ptr;\n+    int timeout;\n+    if (parse_timeout(c, c->argv[3], &timeout) != 0) {\n+        return;\n+    }\n+\n+    robj *key = c->argv[4];\n+    int succ = slotsmgrtone_command(c, host, port, timeout, key);\n+    if (succ < 0) {\n+        return;\n+    }\n+    addReplyLongLong(c, succ);\n+}\n+\n+static void\n+slotsScanSdsKeyCallback(void *l, const dictEntry *de) {\n+    sds skey = dictGetKey(de);\n+    robj *key = createStringObject(skey, sdslen(skey));\n+    listAddNodeTail((list *)l, key);\n+}\n+\n+/* *\n+ * slotsdel slot1 [slot2 ...]\n+ * */\n+void\n+slotsdelCommand(client *c) {\n+    int slots_slot[HASH_SLOTS_SIZE];\n+    int n = 0;\n+    if (c->argc <= 1) {\n+        addReplyErrorFormat(c, \"wrong number of arguments for 'slotsdel' command\");\n+        return;\n+    }\n+    int i;\n+    for (i = 1; i < c->argc; i ++) {\n+        int slot;\n+        if (parse_slot(c, c->argv[i], &slot) != 0) {\n+            return;\n+        }\n+        slots_slot[n] = slot;\n+        n ++;\n+    }\n+    for (i = 0; i < n; i ++) {\n+        dict *d = c->db->hash_slots[slots_slot[i]];\n+        int s = dictSize(d);\n+        if (s == 0) {\n+            continue;\n+        }\n+        list *l = listCreate();\n+        listSetFreeMethod(l, decrRefCountVoid);\n+        unsigned long cursor = 0;\n+        do {\n+            cursor = dictScan(d, cursor, slotsScanSdsKeyCallback, l);\n+        } while (cursor != 0);\n+        while (1) {\n+            listNode *head = listFirst(l);\n+            if (head == NULL) {\n+                break;\n+            }\n+            robj *key = listNodeValue(head);\n+            robj *keys[] = {key};\n+            slotsremove(c, keys, 1, 0);\n+            listDelNode(l, head);\n+        }\n+        listRelease(l);\n+    }\n+    addReplyMultiBulkLen(c, n);\n+    for (i = 0; i < n; i ++) {\n+        int n = slots_slot[i];\n+        int s = dictSize(c->db->hash_slots[n]);\n+        addReplyMultiBulkLen(c, 2);\n+        addReplyLongLong(c, n);\n+        addReplyLongLong(c, s);\n+    }\n+}\n+\n+/* *\n+ * slotscheck\n+ * */\n+void\n+slotscheckCommand(client *c) {\n+    sds bug = NULL;\n+    int i;\n+    for (i = 0; i < HASH_SLOTS_SIZE && bug == NULL; i ++) {\n+        dict *d = c->db->hash_slots[i];\n+        if (dictSize(d) == 0) {\n+            continue;\n+        }\n+        list *l = listCreate();\n+        listSetFreeMethod(l, decrRefCountVoid);\n+        unsigned long cursor = 0;\n+        do {\n+            cursor = dictScan(d, cursor, slotsScanSdsKeyCallback, l);\n+            while (1) {\n+                listNode *head = listFirst(l);\n+                if (head == NULL) {\n+                    break;\n+                }\n+                robj *key = listNodeValue(head);\n+                if (lookupKeyRead(c->db, key) == NULL) {\n+                    if (bug == NULL) {\n+                        bug = sdsdup(key->ptr);\n+                    }\n+                }\n+                listDelNode(l, head);\n+            }\n+        } while (cursor != 0 && bug == NULL);\n+        listRelease(l);\n+    }\n+    if (bug != NULL) {\n+        addReplyErrorFormat(c, \"step 1, miss = '%s'\", bug);\n+        sdsfree(bug);\n+        return;\n+    }\n+    do {\n+        dict *d = c->db->dict;\n+        if (dictSize(d) == 0) {\n+            break;\n+        }\n+        list *l = listCreate();\n+        listSetFreeMethod(l, decrRefCountVoid);\n+        unsigned long cursor = 0;\n+        do {\n+            cursor = dictScan(d, cursor, slotsScanSdsKeyCallback, l);\n+            while (1) {\n+                listNode *head = listFirst(l);\n+                if (head == NULL) {\n+                    break;\n+                }\n+                robj *key = listNodeValue(head);\n+                int slot = slots_num(key->ptr, NULL, NULL);\n+                if (dictFind(c->db->hash_slots[slot], key->ptr) == NULL) {\n+                    if (bug == NULL) {\n+                        bug = sdsdup(key->ptr);\n+                    }\n+                }\n+                listDelNode(l, head);\n+            }\n+        } while (cursor != 0 && bug == NULL);\n+        listRelease(l);\n+    } while (0);\n+    if (bug != NULL) {\n+        addReplyErrorFormat(c, \"step 2, miss = '%s'\", bug);\n+        sdsfree(bug);\n+        return;\n+    }\n+    zskiplistNode *node = c->db->tagged_keys->header->level[0].forward;\n+    while (node != NULL && bug == NULL) {\n+        if (lookupKeyRead(c->db, node->obj) == NULL) {\n+            bug = sdsdup(node->obj->ptr);\n+        }\n+        node = node->level[0].forward;\n+    }\n+    if (bug != NULL) {\n+        addReplyErrorFormat(c, \"step 3, miss = '%s'\", bug);\n+        sdsfree(bug);\n+        return;\n+    }\n+    addReply(c, shared.ok);\n+}\n+\n+/* *\n+ * slotsrestore key ttl val [key ttl val ...]\n+ * */\n+void\n+slotsrestoreCommand(client *c) {\n+    if (c->argc < 4 || (c->argc - 1) % 3 != 0) {\n+        addReplyErrorFormat(c, \"wrong number of arguments for 'slotsrestore' command\");\n+        return;\n+    }\n+    int n = (c->argc - 1) / 3;\n+\n+    long long *ttls = zmalloc(sizeof(long long) * n);\n+    robj **vals = zmalloc(sizeof(robj *) * n);\n+    for (int i = 0; i < n; i ++) {\n+        vals[i] = NULL;\n+    }\n+\n+    for (int i = 0; i < n; i ++) {\n+        robj *key = c->argv[i * 3 + 1];\n+        robj *ttl = c->argv[i * 3 + 2];\n+        robj *val = c->argv[i * 3 + 3];\n+        if (lookupKeyWrite(c->db, key) != NULL) {\n+            serverLog(LL_WARNING, \"slotsrestore: slot = %d, key = '%s' already exists\",\n+                    slots_num(key->ptr, NULL, NULL), (char *)key->ptr);\n+        }\n+        if (getLongLongFromObjectOrReply(c, ttl, &ttls[i], NULL) != C_OK) {\n+            goto cleanup;\n+        } else if (ttls[i] < 0) {\n+            addReplyError(c, \"invalid ttl value, must be >= 0\");\n+            goto cleanup;\n+        }\n+        rio payload;\n+        int type;\n+        if (verifyDumpPayload(val->ptr, sdslen(val->ptr)) != C_OK) {\n+            addReplyError(c, \"dump payload version or checksum are wrong\");\n+            goto cleanup;\n+        }\n+        rioInitWithBuffer(&payload, val->ptr);\n+        if (((type = rdbLoadObjectType(&payload)) == -1) ||\n+                ((vals[i] = rdbLoadObject(type, &payload)) == NULL)) {\n+            addReplyError(c, \"bad data format\");\n+            goto cleanup;\n+        }\n+    }\n+\n+    for (int i = 0; i < n; i ++) {\n+        robj *key = c->argv[i * 3 + 1];\n+        long long ttl = ttls[i];\n+        robj *val = vals[i];\n+        dbDelete(c->db, key);\n+        dbAdd(c->db, key, val);\n+        incrRefCount(val);\n+        if (ttl) {\n+            setExpire(c->db, key, mstime() + ttl);\n+        }\n+        signalModifiedKey(c->db, key);\n+        server.dirty ++;\n+    }\n+    addReply(c, shared.ok);\n+\n+cleanup:\n+    for (int i = 0; i < n; i ++) {\n+        if (vals[i] != NULL) {\n+            decrRefCount(vals[i]);\n+        }\n+    }\n+    zfree(vals);\n+    zfree(ttls);\n+}\n+\n+/* *\n+ * do migrate mutli key-value(s) for {slotsmgrt/slotsmgrtone}with tag commands\n+ * return value:\n+ *    -1 - error happens\n+ *   >=0 - # of success migration\n+ * */\n+static int\n+slotsmgrttag_command(client *c, sds host, sds port, int timeout, robj *key) {\n+    uint32_t crc;\n+    int hastag;\n+    int slot = slots_num(key->ptr, &crc, &hastag);\n+    if (!hastag) {\n+        return slotsmgrtone_command(c, host, port, timeout, key);\n+    }\n+\n+    slotsmgrt_sockfd *pfd = slotsmgrt_get_sockfd(c, host, port, timeout);\n+    if (pfd == NULL) {\n+        return -1;\n+    }\n+\n+    dict *d = c->db->hash_slots[slot];\n+    if (dictSize(d) == 0) {\n+        return 0;\n+    }\n+\n+    zrangespec range;\n+    range.min = (double)crc;\n+    range.minex = 0;\n+    range.max = (double)crc;\n+    range.maxex = 0;\n+\n+    list *l = listCreate();\n+    listSetFreeMethod(l, decrRefCountVoid);\n+\n+    zskiplistNode *node = zslFirstInRange(c->db->tagged_keys, &range);\n+    while (node != NULL && node->score == (double)crc) {\n+        listAddNodeTail(l, node->obj);\n+        incrRefCount(node->obj);\n+        node = node->level[0].forward;\n+    }\n+\n+    int max = listLength(l);\n+    if (max == 0) {\n+        listRelease(l);\n+        return 0;\n+    }\n+\n+    robj **keys = zmalloc(sizeof(robj *) * max);\n+    robj **vals = zmalloc(sizeof(robj *) * max);\n+\n+    int n = 0;\n+    for (int i = 0; i < max; i ++) {\n+        listNode *head = listFirst(l);\n+        robj *key = listNodeValue(head);\n+        robj *val = lookupKeyWrite(c->db, key);\n+        if (val != NULL) {\n+            keys[n] = key;\n+            vals[n] = val;\n+            n ++;\n+            incrRefCount(key);\n+            incrRefCount(val);\n+        }\n+        listDelNode(l, head);\n+    }\n+\n+    int ret = 0;\n+    if (n != 0) {\n+        if (slotsmgrt(c, host, port, pfd, c->db->id, timeout, keys, vals, n) != 0) {\n+            slotsmgrt_close_socket(host, port);\n+            ret = -1;\n+        } else {\n+            slotsremove(c, keys, n, 1);\n+            ret = n;\n+        }\n+    }\n+\n+    listRelease(l);\n+    for (int i = 0; i < n; i ++) {\n+        decrRefCount(keys[i]);\n+        decrRefCount(vals[i]);\n+    }\n+    zfree(keys);\n+    zfree(vals);\n+    return ret;\n+}\n+\n+/* *\n+ * slotsmgrttagslot host port timeout slot\n+ * */\n+void\n+slotsmgrttagslotCommand(client *c) {\n+    sds host = c->argv[1]->ptr;\n+    sds port = c->argv[2]->ptr;\n+    int timeout, slot;\n+    if (parse_timeout(c, c->argv[3], &timeout) != 0) {\n+        return;\n+    }\n+    if (parse_slot(c, c->argv[4], &slot) != 0) {\n+        return;\n+    }\n+\n+    dict *d = c->db->hash_slots[slot];\n+    int succ = 0;\n+    do {\n+        const dictEntry *de = dictGetRandomKey(d);\n+        if (de == NULL) {\n+            break;\n+        }\n+        sds skey = dictGetKey(de);\n+        robj *key = createStringObject(skey, sdslen(skey));\n+        succ = slotsmgrttag_command(c, host, port, timeout, key);\n+        decrRefCount(key);\n+        if (succ < 0) {\n+            return;\n+        }\n+    } while (0);\n+    addReplyMultiBulkLen(c, 2);\n+    addReplyLongLong(c, succ);\n+    addReplyLongLong(c, dictSize(d));\n+}\n+\n+/* *\n+ * slotsmgrttagone host port timeout key\n+ * */\n+void\n+slotsmgrttagoneCommand(client *c) {\n+    sds host = c->argv[1]->ptr;\n+    sds port = c->argv[2]->ptr;\n+    int timeout;\n+    if (parse_timeout(c, c->argv[3], &timeout) != 0) {\n+        return;\n+    }\n+\n+    robj *key = c->argv[4];\n+    int succ = slotsmgrttag_command(c, host, port, timeout, key);\n+    if (succ < 0) {\n+        return;\n+    }\n+    addReplyLongLong(c, succ);\n+}\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.8/patch/codis/0001-slotsscan.patch",
    "content": "diff --git a/extern/redis-3.2.7/src/server.c b/extern/redis-3.2.7/src/server.c\nindex 983d1b1..029f9e0 100644\n--- a/extern/redis-3.2.7/src/server.c\n+++ b/extern/redis-3.2.7/src/server.c\n@@ -298,6 +298,7 @@ struct redisCommand redisCommandTable[] = {\n     {\"host:\",securityWarningCommand,-1,\"lt\",0,NULL,0,0,0,0,0},\n     {\"latency\",latencyCommand,-2,\"aslt\",0,NULL,0,0,0,0,0},\n     {\"slotsinfo\",slotsinfoCommand,-1,\"rF\",0,NULL,0,0,0,0,0},\n+    {\"slotsscan\",slotsscanCommand,-3,\"rR\",0,NULL,0,0,0,0,0},\n     {\"slotsdel\",slotsdelCommand,-2,\"w\",0,NULL,1,-1,1,0,0},\n     {\"slotsmgrtslot\",slotsmgrtslotCommand,5,\"aw\",0,NULL,0,0,0,0,0},\n     {\"slotsmgrtone\",slotsmgrtoneCommand,5,\"aw\",0,NULL,0,0,0,0,0},\ndiff --git a/extern/redis-3.2.7/src/server.h b/extern/redis-3.2.7/src/server.h\nindex e7681c5..3961c29 100644\n--- a/extern/redis-3.2.7/src/server.h\n+++ b/extern/redis-3.2.7/src/server.h\n@@ -1659,6 +1659,7 @@ void latencyCommand(client *c);\n void securityWarningCommand(client *c);\n \n void slotsinfoCommand(client *c);\n+void slotsscanCommand(client *c);\n void slotsdelCommand(client *c);\n void slotsmgrtslotCommand(client *c);\n void slotsmgrtoneCommand(client *c);\ndiff --git a/extern/redis-3.2.7/src/slots.c b/extern/redis-3.2.7/src/slots.c\nindex ff23492..90ff60a 100644\n--- a/extern/redis-3.2.7/src/slots.c\n+++ b/extern/redis-3.2.7/src/slots.c\n@@ -47,8 +47,13 @@ parse_int(client *c, robj *obj, int *p) {\n     if (getLongFromObjectOrReply(c, obj, &v, NULL) != C_OK) {\n         return -1;\n     }\n-    *p = v;\n-    return 0;\n+    if (v < INT_MIN || v > INT_MAX) {\n+        addReplyError(c, \"value is out of range\");\n+        return -1;\n+    } else {\n+        *p = v;\n+        return 0;\n+    }\n }\n \n static int\n@@ -815,3 +820,63 @@ slotsmgrttagoneCommand(client *c) {\n     }\n     addReplyLongLong(c, succ);\n }\n+\n+/* *\n+ * slotsscan slotnum cursor [COUNT count]\n+ * */\n+void\n+slotsscanCommand(client *c) {\n+    int slot;\n+    if (parse_slot(c, c->argv[1], &slot) != 0) {\n+        return;\n+    }\n+    unsigned long cursor;\n+    if (parseScanCursorOrReply(c, c->argv[2], &cursor) == C_ERR) {\n+        return;\n+    }\n+    unsigned long count = 10;\n+    if (c->argc != 3 && c->argc != 5) {\n+        addReplyErrorFormat(c, \"wrong number of arguments for 'slotsscan' command\");\n+        return;\n+    }\n+    if (c->argc == 5) {\n+        if (strcasecmp(c->argv[3]->ptr, \"count\") != 0) {\n+            addReply(c, shared.syntaxerr);\n+            return;\n+        }\n+        int v;\n+        if (parse_int(c, c->argv[4], &v) != 0) {\n+            return;\n+        }\n+        if (v < 1) {\n+            addReply(c, shared.syntaxerr);\n+            return;\n+        }\n+        count = v;\n+    }\n+    dict *d = c->db->hash_slots[slot];\n+    list *l = listCreate();\n+    listSetFreeMethod(l, decrRefCountVoid);\n+\n+    long loops = count * 10;\n+    do {\n+        cursor = dictScan(d, cursor, slotsScanSdsKeyCallback, l);\n+        loops --;\n+    } while (cursor != 0 && loops > 0 && listLength(l) < count);\n+\n+    addReplyMultiBulkLen(c, 2);\n+    addReplyBulkLongLong(c, cursor);\n+\n+    addReplyMultiBulkLen(c, listLength(l));\n+    while (1) {\n+        listNode *head = listFirst(l);\n+        if (head == NULL) {\n+            break;\n+        }\n+        robj *key = listNodeValue(head);\n+        addReplyBulk(c, key);\n+        listDelNode(l, head);\n+    }\n+\n+    listRelease(l);\n+}\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.8/patch/codis/0002-rehash.patch",
    "content": "diff --git a/extern/redis-3.2.7/src/server.c b/extern/redis-3.2.7/src/server.c\nindex 029f9e0..f05763e 100644\n--- a/extern/redis-3.2.7/src/server.c\n+++ b/extern/redis-3.2.7/src/server.c\n@@ -716,10 +716,16 @@ int incrementallyRehash(int dbid) {\n     /* Keys dictionary */\n     if (dictIsRehashing(server.db[dbid].dict)) {\n         dictRehashMilliseconds(server.db[dbid].dict,1);\n+\n+        long long start = timeInMilliseconds();\n         for (int i = 0; i < HASH_SLOTS_SIZE; i ++) {\n-            dict *d = server.db[dbid].hash_slots[i];\n+            int idx = ((i + start) & HASH_SLOTS_MASK);\n+            dict *d = server.db[dbid].hash_slots[idx];\n             if (dictIsRehashing(d)) {\n                 dictRehashMilliseconds(d, 1);\n+                if (timeInMilliseconds() != start) {\n+                    break;\n+                }\n             }\n         }\n         return 1; /* already used our millisecond for this loop... */\ndiff --git a/extern/redis-3.2.7/src/server.h b/extern/redis-3.2.7/src/server.h\nindex 3961c29..ebe34d7 100644\n--- a/extern/redis-3.2.7/src/server.h\n+++ b/extern/redis-3.2.7/src/server.h\n@@ -501,6 +501,8 @@ struct evictionPoolEntry {\n void crc32_init();\n uint32_t crc32_checksum(const char *buf, int len);\n \n+long long timeInMilliseconds(void);\n+\n #define HASH_SLOTS_MASK 0x000003ff\n #define HASH_SLOTS_SIZE (HASH_SLOTS_MASK + 1)\n \n"
  },
  {
    "path": "extern/deprecated/redis-3.2.8/patch/codis/0003-slots_async1.patch",
    "content": "diff --git a/extern/redis-3.2.8/src/Makefile b/extern/redis-3.2.8/src/Makefile\nindex 68af785..27427e4 100644\n--- a/extern/redis-3.2.8/src/Makefile\n+++ b/extern/redis-3.2.8/src/Makefile\n@@ -105,7 +105,7 @@ endif\n ifeq ($(MALLOC),jemalloc)\n \tDEPENDENCY_TARGETS+= jemalloc\n \tFINAL_CFLAGS+= -DUSE_JEMALLOC -I../deps/jemalloc/include\n-\tFINAL_LIBS+= ../deps/jemalloc/lib/libjemalloc.a\n+\tFINAL_LIBS+= ../deps/jemalloc/lib/libjemalloc.a -lrt\n endif\n \n REDIS_CC=$(QUIET_CC)$(CC) $(FINAL_CFLAGS)\n@@ -127,7 +127,7 @@ endif\n \n REDIS_SERVER_NAME=redis-server\n REDIS_SENTINEL_NAME=redis-sentinel\n-REDIS_SERVER_OBJ=adlist.o quicklist.o ae.o anet.o dict.o server.o sds.o zmalloc.o lzf_c.o lzf_d.o pqsort.o zipmap.o sha1.o ziplist.o release.o networking.o util.o object.o db.o replication.o rdb.o t_string.o t_list.o t_set.o t_zset.o t_hash.o config.o aof.o pubsub.o multi.o debug.o sort.o intset.o syncio.o cluster.o crc16.o endianconv.o slowlog.o scripting.o bio.o rio.o rand.o memtest.o crc64.o bitops.o sentinel.o notify.o setproctitle.o blocked.o hyperloglog.o latency.o sparkline.o redis-check-rdb.o geo.o slots.o crc32.o\n+REDIS_SERVER_OBJ=adlist.o quicklist.o ae.o anet.o dict.o server.o sds.o zmalloc.o lzf_c.o lzf_d.o pqsort.o zipmap.o sha1.o ziplist.o release.o networking.o util.o object.o db.o replication.o rdb.o t_string.o t_list.o t_set.o t_zset.o t_hash.o config.o aof.o pubsub.o multi.o debug.o sort.o intset.o syncio.o cluster.o crc16.o endianconv.o slowlog.o scripting.o bio.o rio.o rand.o memtest.o crc64.o bitops.o sentinel.o notify.o setproctitle.o blocked.o hyperloglog.o latency.o sparkline.o redis-check-rdb.o geo.o slots.o slots_async.o crc32.o\n REDIS_GEOHASH_OBJ=../deps/geohash-int/geohash.o ../deps/geohash-int/geohash_helper.o\n REDIS_CLI_NAME=redis-cli\n REDIS_CLI_OBJ=anet.o adlist.o redis-cli.o zmalloc.o release.o anet.o ae.o crc64.o\ndiff --git a/extern/redis-3.2.8/src/help.h b/extern/redis-3.2.8/src/help.h\nindex 5f927c3..3d57430 100644\n--- a/extern/redis-3.2.8/src/help.h\n+++ b/extern/redis-3.2.8/src/help.h\n@@ -17,7 +17,8 @@ static char *commandGroups[] = {\n     \"scripting\",\n     \"hyperloglog\",\n     \"cluster\",\n-    \"geo\"\n+    \"geo\",\n+    \"codis\",\n };\n \n struct commandHelp {\n@@ -1011,7 +1012,123 @@ struct commandHelp {\n     \"destination numkeys key [key ...] [WEIGHTS weight] [AGGREGATE SUM|MIN|MAX]\",\n     \"Add multiple sorted sets and store the resulting sorted set in a new key\",\n     4,\n-    \"2.0.0\" }\n+    \"2.0.0\" },\n+    {\"SLOTSINFO\",\n+        \"-\",\n+        \"\", 14, \"codis1.9\"\n+    },\n+    {\"SLOTSSCAN\",\n+        \"slotnum cursor [COUNT count]\",\n+        \"\", 14, \"codis3.1\"\n+    },\n+    {\"SLOTSDEL\",\n+        \"slot [slot ...]\",\n+        \"\", 14, \"codis1.9\"\n+    },\n+    {\"SLOTSMGRTSLOT\",\n+        \"host port timeout slot\",\n+        \"\", 14, \"codis1.9\"\n+    },\n+    {\"SLOTSMGRTTAGSLOT\",\n+        \"host port timeout slot\",\n+        \"\", 14, \"codis1.9\"\n+    },\n+    {\"SLOTSMGRTONE\",\n+        \"host port timeout key\",\n+        \"\", 14, \"codis1.9\"\n+    },\n+    {\"SLOTSMGRTTAGONE\",\n+        \"host port timeout key\",\n+        \"\", 14, \"codis1.9\"\n+    },\n+    {\"SLOTSHASHKEY\",\n+        \"key [key...]\",\n+        \"\", 14, \"codis1.9\"\n+    },\n+    {\"SLOTSCHECK\",\n+        \"-\",\n+        \"\", 14, \"codis1.9\"\n+    },\n+    {\"SLOTSRESTORE\",\n+        \"key ttl val [key ttl val ...]\",\n+        \"\", 14, \"codis1.9\"\n+    },\n+    {\"SLOTSMGRTSLOT-ASYNC\",\n+        \"host port timeout maxbulks maxbytes slot numkeys\",\n+        \"\", 14, \"codis3.2\"\n+    },\n+    {\"SLOTSMGRTTAGSLOT-ASYNC\",\n+        \"host port timeout maxbulks maxbytes slot numkeys\",\n+        \"\", 14, \"codis3.2\"\n+    },\n+    {\"SLOTSMGRTONE-ASYNC\",\n+        \"host port timeout maxbulks maxbytes key [key...]\",\n+        \"\", 14, \"codis3.2\"\n+    },\n+    {\"SLOTSMGRTTAGONE-ASYNC\",\n+        \"host port timeout maxbulks maxbytes key [key...]\",\n+        \"\", 14, \"codis3.2\"\n+    },\n+    {\"SLOTSMGRTONE-ASYNC-DUMP\",\n+        \"timeout maxbulks key [key...]\",\n+        \"\", 14, \"codis3.2\"\n+    },\n+    {\"SLOTSMGRTTAGONE-ASYNC-DUMP\",\n+        \"timeout maxbulks key [key...]\",\n+        \"\", 14, \"codis3.2\"\n+    },\n+    {\"SLOTSMGRT-ASYNC-FENCE\",\n+        \"-\",\n+        \"\", 14, \"codis3.2\"\n+    },\n+    {\"SLOTSMGRT-ASYNC-CANCEL\",\n+        \"-\",\n+        \"\", 14, \"codis3.2\"\n+    },\n+    {\"SLOTSMGRT-EXEC-WRAPPER\",\n+        \"hashkey command [arg ...]\",\n+        \"\", 14, \"codis3.2\"\n+    },\n+    {\"SLOTSMGRT-LAZY-RELEASE\",\n+        \"[microseconds]\",\n+        \"\", 14, \"codis3.2\"\n+    },\n+    {\"SLOTSRESTORE-ASYNC SELECT\",\n+        \"db\",\n+        \"\", 14, \"codis3.2\"\n+    },\n+    {\"SLOTSRESTORE-ASYNC DEL\",\n+        \"key\",\n+        \"\", 14, \"codis3.2\"\n+    },\n+    {\"SLOTSRESTORE-ASYNC EXPIRE\",\n+        \"key ttl\",\n+        \"\", 14, \"codis3.2\"\n+    },\n+    {\"SLOTSRESTORE-ASYNC OBJECT\",\n+        \"key ttl payload\",\n+        \"\", 14, \"codis3.2\"\n+    },\n+    {\"SLOTSRESTORE-ASYNC LIST\",\n+        \"key ttl hint [elem ...]\",\n+        \"\", 14, \"codis3.2\"\n+    },\n+    {\"SLOTSRESTORE-ASYNC HASH\",\n+        \"key ttl hint [field value ...]\",\n+        \"\", 14, \"codis3.2\"\n+    },\n+    {\"SLOTSRESTORE-ASYNC DICT\",\n+        \"key ttl hint [elem ...]\",\n+        \"\", 14, \"codis3.2\"\n+    },\n+    {\"SLOTSRESTORE-ASYNC ZSET\",\n+        \"key ttl hint [field score ...]\",\n+        \"\", 14, \"codis3.2\"\n+    },\n+    {\"SLOTSRESTORE-ASYNC-AUTH\",\n+        \"passwd\",\n+        \"\", 14, \"codis3.2\"\n+    },\n };\n \n #endif\ndiff --git a/extern/redis-3.2.8/src/networking.c b/extern/redis-3.2.8/src/networking.c\nindex fb5341e..dff5225 100644\n--- a/extern/redis-3.2.8/src/networking.c\n+++ b/extern/redis-3.2.8/src/networking.c\n@@ -123,6 +123,8 @@ client *createClient(int fd) {\n     c->pubsub_channels = dictCreate(&setDictType,NULL);\n     c->pubsub_patterns = listCreate();\n     c->peerid = NULL;\n+    c->slotsmgrt_flags = 0;\n+    c->slotsmgrt_fenceq = NULL;\n     listSetFreeMethod(c->pubsub_patterns,decrRefCountVoid);\n     listSetMatchMethod(c->pubsub_patterns,listMatchObjects);\n     if (fd != -1) listAddNodeTail(server.clients,c);\n@@ -809,6 +811,8 @@ void freeClient(client *c) {\n             replicationGetSlaveName(c));\n     }\n \n+    slotsmgrtAsyncUnlinkClient(c);\n+\n     /* Free the query buffer */\n     sdsfree(c->querybuf);\n     c->querybuf = NULL;\n@@ -1794,6 +1798,10 @@ int checkClientOutputBufferLimits(client *c) {\n     int soft = 0, hard = 0, class;\n     unsigned long used_mem = getClientOutputBufferMemoryUsage(c);\n \n+    if (c->slotsmgrt_flags & CLIENT_SLOTSMGRT_ASYNC_CACHED_CLIENT) {\n+        return 0;\n+    }\n+\n     class = getClientType(c);\n     /* For the purpose of output buffer limiting, masters are handled\n      * like normal clients. */\ndiff --git a/extern/redis-3.2.8/src/server.c b/extern/redis-3.2.8/src/server.c\nindex f05763e..8946e65 100644\n--- a/extern/redis-3.2.8/src/server.c\n+++ b/extern/redis-3.2.8/src/server.c\n@@ -300,13 +300,26 @@ struct redisCommand redisCommandTable[] = {\n     {\"slotsinfo\",slotsinfoCommand,-1,\"rF\",0,NULL,0,0,0,0,0},\n     {\"slotsscan\",slotsscanCommand,-3,\"rR\",0,NULL,0,0,0,0,0},\n     {\"slotsdel\",slotsdelCommand,-2,\"w\",0,NULL,1,-1,1,0,0},\n-    {\"slotsmgrtslot\",slotsmgrtslotCommand,5,\"aw\",0,NULL,0,0,0,0,0},\n-    {\"slotsmgrtone\",slotsmgrtoneCommand,5,\"aw\",0,NULL,0,0,0,0,0},\n-    {\"slotsmgrttagslot\",slotsmgrttagslotCommand,5,\"aw\",0,NULL,0,0,0,0,0},\n-    {\"slotsmgrttagone\",slotsmgrttagoneCommand,5,\"aw\",0,NULL,0,0,0,0,0},\n+    {\"slotsmgrtslot\",slotsmgrtslotCommand,5,\"w\",0,NULL,0,0,0,0,0},\n+    {\"slotsmgrttagslot\",slotsmgrttagslotCommand,5,\"w\",0,NULL,0,0,0,0,0},\n+    {\"slotsmgrtone\",slotsmgrtoneCommand,5,\"w\",0,NULL,0,0,0,0,0},\n+    {\"slotsmgrttagone\",slotsmgrttagoneCommand,5,\"w\",0,NULL,0,0,0,0,0},\n     {\"slotshashkey\",slotshashkeyCommand,-1,\"rF\",0,NULL,0,0,0,0,0},\n     {\"slotscheck\",slotscheckCommand,0,\"r\",0,NULL,0,0,0,0,0},\n-    {\"slotsrestore\",slotsrestoreCommand,-4,\"awm\",0,NULL,1,1,1,0,0},\n+    {\"slotsrestore\",slotsrestoreCommand,-4,\"wm\",0,NULL,0,0,0,0,0},\n+    {\"slotsmgrtslot-async\",slotsmgrtSlotAsyncCommand,8,\"w\",0,NULL,0,0,0,0,0},\n+    {\"slotsmgrttagslot-async\",slotsmgrtTagSlotAsyncCommand,8,\"w\",0,NULL,0,0,0,0,0},\n+    {\"slotsmgrtone-async\",slotsmgrtOneAsyncCommand,-7,\"w\",0,NULL,0,0,0,0,0},\n+    {\"slotsmgrttagone-async\",slotsmgrtTagOneAsyncCommand,-7,\"w\",0,NULL,0,0,0,0,0},\n+    {\"slotsmgrtone-async-dump\",slotsmgrtOneAsyncDumpCommand,-4,\"rm\",0,NULL,0,0,0,0,0},\n+    {\"slotsmgrttagone-async-dump\",slotsmgrtTagOneAsyncDumpCommand,-4,\"rm\",0,NULL,0,0,0,0,0},\n+    {\"slotsmgrt-async-fence\",slotsmgrtAsyncFenceCommand,0,\"r\",0,NULL,0,0,0,0,0},\n+    {\"slotsmgrt-async-cancel\",slotsmgrtAsyncCancelCommand,0,\"F\",0,NULL,0,0,0,0,0},\n+    {\"slotsmgrt-exec-wrapper\",slotsmgrtExecWrapperCommand,-3,\"wm\",0,NULL,0,0,0,0,0},\n+    {\"slotsmgrt-lazy-release\",slotsmgrtLazyReleaseCommand,-1,\"r\",0,NULL,0,0,0,0,0},\n+    {\"slotsrestore-async\",slotsrestoreAsyncCommand,-2,\"w\",0,NULL,0,0,0,0,0},\n+    {\"slotsrestore-async-auth\",slotsrestoreAsyncAuthCommand,2,\"F\",0,NULL,0,0,0,0,0},\n+    {\"slotsrestore-async-ack\",slotsrestoreAsyncAckCommand,3,\"w\",0,NULL,0,0,0,0,0},\n };\n \n struct evictionPoolEntry *evictionPoolAlloc(void);\n@@ -716,7 +729,10 @@ int incrementallyRehash(int dbid) {\n     /* Keys dictionary */\n     if (dictIsRehashing(server.db[dbid].dict)) {\n         dictRehashMilliseconds(server.db[dbid].dict,1);\n-\n+        server.db[dbid].hash_slots_rehashing = 1;\n+        return 1; /* already used our millisecond for this loop... */\n+    }\n+    if (server.db[dbid].hash_slots_rehashing) {\n         long long start = timeInMilliseconds();\n         for (int i = 0; i < HASH_SLOTS_SIZE; i ++) {\n             int idx = ((i + start) & HASH_SLOTS_MASK);\n@@ -724,10 +740,11 @@ int incrementallyRehash(int dbid) {\n             if (dictIsRehashing(d)) {\n                 dictRehashMilliseconds(d, 1);\n                 if (timeInMilliseconds() != start) {\n-                    break;\n+                    return 1; /* already used our millisecond for this loop... */\n                 }\n             }\n         }\n+        server.db[dbid].hash_slots_rehashing = 0;\n         return 1; /* already used our millisecond for this loop... */\n     }\n     /* Expires */\n@@ -1323,6 +1340,11 @@ int serverCron(struct aeEventLoop *eventLoop, long long id, void *clientData) {\n \n     run_with_period(1000) {\n         slotsmgrt_cleanup();\n+        slotsmgrtAsyncCleanup();\n+    }\n+\n+    run_with_period(100) {\n+        slotsmgrtLazyReleaseCleanup();\n     }\n \n     /* Cleanup expired MIGRATE cached sockets. */\n@@ -1576,8 +1598,6 @@ void initServerConfig(void) {\n     server.next_client_id = 1; /* Client IDs, start from 1 .*/\n     server.loading_process_events_interval_bytes = (1024*1024*2);\n \n-    server.slotsmgrt_cached_sockfds = dictCreate(&migrateCacheDictType, NULL);\n-\n     server.lruclock = getLRUClock();\n     resetServerSaveParams();\n \n@@ -1937,6 +1957,14 @@ void initServer(void) {\n     server.el = aeCreateEventLoop(server.maxclients+CONFIG_FDSET_INCR);\n     server.db = zmalloc(sizeof(redisDb)*server.dbnum);\n \n+    server.slotsmgrt_cached_sockfds = dictCreate(&migrateCacheDictType, NULL);\n+    server.slotsmgrt_cached_clients = zmalloc(sizeof(slotsmgrtAsyncClient) * server.dbnum);\n+    for (j = 0; j < server.dbnum; j ++) {\n+        slotsmgrtAsyncClient *ac = &server.slotsmgrt_cached_clients[j];\n+        memset(ac, 0, sizeof(*ac));\n+    }\n+    server.slotsmgrt_lazy_release = listCreate();\n+\n     /* Open the TCP listening socket for the user commands. */\n     if (server.port != 0 &&\n         listenToPort(server.port,server.ipfd,&server.ipfd_count) == C_ERR)\n@@ -1973,6 +2001,7 @@ void initServer(void) {\n         for (i = 0; i < HASH_SLOTS_SIZE; i ++) {\n             server.db[j].hash_slots[i] = dictCreate(&hashSlotType, NULL);\n         }\n+        server.db[j].hash_slots_rehashing = 0;\n         server.db[j].tagged_keys = zslCreate();\n     }\n     server.pubsub_channels = dictCreate(&keylistDictType,NULL);\n@@ -2428,7 +2457,9 @@ int processCommand(client *c) {\n     }\n \n     /* Check if the user is authenticated */\n-    if (server.requirepass && !c->authenticated && c->cmd->proc != authCommand)\n+    if (server.requirepass && !c->authenticated\n+            && c->cmd->proc != authCommand\n+            && c->cmd->proc != slotsrestoreAsyncAuthCommand)\n     {\n         flagTransaction(c);\n         addReply(c,shared.noautherr);\n@@ -2570,6 +2601,10 @@ int processCommand(client *c) {\n         return C_OK;\n     }\n \n+    if (c->cmd->proc != slotsrestoreAsyncAckCommand) {\n+        slotsmgrtLazyReleaseIncrementally();\n+    }\n+\n     /* Exec the command */\n     if (c->flags & CLIENT_MULTI &&\n         c->cmd->proc != execCommand && c->cmd->proc != discardCommand &&\ndiff --git a/extern/redis-3.2.8/src/server.h b/extern/redis-3.2.8/src/server.h\nindex ebe34d7..d34ee4f 100644\n--- a/extern/redis-3.2.8/src/server.h\n+++ b/extern/redis-3.2.8/src/server.h\n@@ -273,6 +273,9 @@ typedef long long mstime_t; /* millisecond time type. */\n #define CLIENT_LUA_DEBUG (1<<25)  /* Run EVAL in debug mode. */\n #define CLIENT_LUA_DEBUG_SYNC (1<<26)  /* EVAL debugging without fork() */\n \n+#define CLIENT_SLOTSMGRT_ASYNC_CACHED_CLIENT (1 << 0)\n+#define CLIENT_SLOTSMGRT_ASYNC_NORMAL_CLIENT (1 << 1)\n+\n /* Client block type (btype field in client structure)\n  * if CLIENT_BLOCKED flag is set. */\n #define BLOCKED_NONE 0    /* Not blocked, no CLIENT_BLOCKED flag set. */\n@@ -518,6 +521,7 @@ typedef struct redisDb {\n     dict *ready_keys;           /* Blocked keys that received a PUSH */\n     dict *watched_keys;         /* WATCHED keys for MULTI/EXEC CAS */\n     dict *hash_slots[HASH_SLOTS_SIZE];\n+    int hash_slots_rehashing;\n     struct zskiplist *tagged_keys;\n     struct evictionPoolEntry *eviction_pool;    /* Eviction pool of keys */\n     int id;                     /* Database ID */\n@@ -622,6 +626,9 @@ typedef struct client {\n     list *pubsub_patterns;  /* patterns a client is interested in (SUBSCRIBE) */\n     sds peerid;             /* Cached peer ID. */\n \n+    long slotsmgrt_flags;\n+    list *slotsmgrt_fenceq;\n+\n     /* Response buffer */\n     int bufpos;\n     char buf[PROTO_REPLY_CHUNK_BYTES];\n@@ -713,6 +720,18 @@ struct clusterState;\n #undef hz\n #endif\n \n+typedef struct {\n+    client *c;\n+    int used;\n+    sds host;\n+    int port;\n+    long long timeout;\n+    long long lastuse;\n+    long sending_msgs;\n+    void *batched_iter;\n+    list *blocked_list;\n+} slotsmgrtAsyncClient;\n+\n struct redisServer {\n     /* General */\n     pid_t pid;                  /* Main process pid. */\n@@ -754,6 +773,8 @@ struct redisServer {\n     mstime_t clients_pause_end_time; /* Time when we undo clients_paused */\n     char neterr[ANET_ERR_LEN];   /* Error buffer for anet.c */\n     dict *slotsmgrt_cached_sockfds;\n+    list *slotsmgrt_lazy_release;\n+    slotsmgrtAsyncClient *slotsmgrt_cached_clients;\n     dict *migrate_cached_sockets;/* MIGRATE cached sockets */\n     uint64_t next_client_id;    /* Next client unique ID. Incremental. */\n     int protected_mode;         /* Don't accept external connections. */\n@@ -1671,6 +1692,25 @@ void slotshashkeyCommand(client *c);\n void slotscheckCommand(client *c);\n void slotsrestoreCommand(client *c);\n \n+void slotsmgrtSlotAsyncCommand(client *c);\n+void slotsmgrtTagSlotAsyncCommand(client *c);\n+void slotsmgrtOneAsyncCommand(client *c);\n+void slotsmgrtOneAsyncDumpCommand(client *c);\n+void slotsmgrtTagOneAsyncCommand(client *c);\n+void slotsmgrtTagOneAsyncDumpCommand(client *c);\n+void slotsmgrtAsyncFenceCommand(client *c);\n+void slotsmgrtAsyncCancelCommand(client *c);\n+void slotsmgrtExecWrapperCommand(client *c);\n+void slotsmgrtLazyReleaseCommand(client *c);\n+void slotsrestoreAsyncCommand(client *c);\n+void slotsrestoreAsyncAuthCommand(client *c);\n+void slotsrestoreAsyncAckCommand(client *c);\n+\n+void slotsmgrtAsyncCleanup();\n+void slotsmgrtAsyncUnlinkClient(client *c);\n+void slotsmgrtLazyReleaseCleanup();\n+void slotsmgrtLazyReleaseIncrementally();\n+\n void slotsmgrt_cleanup();\n int slots_num(const sds s, uint32_t *pcrc, int *phastag);\n \ndiff --git a/extern/redis-3.2.8/src/slots.c b/extern/redis-3.2.8/src/slots.c\nindex 90ff60a..afd2082 100644\n--- a/extern/redis-3.2.8/src/slots.c\n+++ b/extern/redis-3.2.8/src/slots.c\n@@ -502,17 +502,17 @@ slotsdelCommand(client *c) {\n         unsigned long cursor = 0;\n         do {\n             cursor = dictScan(d, cursor, slotsScanSdsKeyCallback, l);\n-        } while (cursor != 0);\n-        while (1) {\n-            listNode *head = listFirst(l);\n-            if (head == NULL) {\n-                break;\n+            while (1) {\n+                listNode *head = listFirst(l);\n+                if (head == NULL) {\n+                    break;\n+                }\n+                robj *key = listNodeValue(head);\n+                robj *keys[] = {key};\n+                slotsremove(c, keys, 1, 0);\n+                listDelNode(l, head);\n             }\n-            robj *key = listNodeValue(head);\n-            robj *keys[] = {key};\n-            slotsremove(c, keys, 1, 0);\n-            listDelNode(l, head);\n-        }\n+        } while (cursor != 0);\n         listRelease(l);\n     }\n     addReplyMultiBulkLen(c, n);\ndiff --git a/extern/redis-3.2.8/src/slots_async.c b/extern/redis-3.2.8/src/slots_async.c\nnew file mode 100644\nindex 0000000..73b3205\n--- /dev/null\n+++ b/extern/redis-3.2.8/src/slots_async.c\n@@ -0,0 +1,1801 @@\n+#include \"server.h\"\n+\n+/* ============================ Iterator for Lazy Release ================================== */\n+\n+typedef struct {\n+    robj *val;\n+    unsigned long cursor;\n+} lazyReleaseIterator;\n+\n+static lazyReleaseIterator *\n+createLazyReleaseIterator(robj *val) {\n+    lazyReleaseIterator *it = zmalloc(sizeof(lazyReleaseIterator));\n+    it->val = val;\n+    incrRefCount(it->val);\n+    it->cursor = 0;\n+    return it;\n+}\n+\n+static void\n+freeLazyReleaseIterator(lazyReleaseIterator *it) {\n+    if (it->val != NULL) {\n+        decrRefCount(it->val);\n+    }\n+    zfree(it);\n+}\n+\n+static int\n+lazyReleaseIteratorHasNext(lazyReleaseIterator *it) {\n+    return it->val != NULL;\n+}\n+\n+static void\n+lazyReleaseIteratorScanCallback(void *data, const dictEntry *de) {\n+    void **pd = (void **)data;\n+    list *l = pd[0];\n+\n+    robj *field = dictGetKey(de);\n+    incrRefCount(field);\n+    listAddNodeTail(l, field);\n+}\n+\n+static void\n+lazyReleaseIteratorNext(lazyReleaseIterator *it, int step) {\n+    robj *val = it->val;\n+    serverAssert(val != NULL);\n+\n+    unsigned int limit = step * 2;\n+    if (limit < 100) {\n+        limit = 100;\n+    }\n+\n+    if (val->type == OBJ_LIST) {\n+        if (listTypeLength(val) <= limit) {\n+            decrRefCount(val);\n+            it->val = NULL;\n+        } else {\n+            for (int i = 0; i < step; i ++) {\n+                robj *value = listTypePop(val, LIST_HEAD);\n+                decrRefCount(value);\n+            }\n+        }\n+        return;\n+    }\n+\n+    if (val->type == OBJ_HASH || val->type == OBJ_SET) {\n+        dict *ht = val->ptr;\n+        if (dictSize(ht) <= limit) {\n+            decrRefCount(val);\n+            it->val = NULL;\n+        } else {\n+            list *ll = listCreate();\n+            listSetFreeMethod(ll, decrRefCountVoid);\n+            int loop = step;\n+            void *pd[] = {ll};\n+            do {\n+                it->cursor = dictScan(ht, it->cursor, lazyReleaseIteratorScanCallback, pd);\n+            } while (it->cursor != 0 && listLength(ll) < (unsigned long)step && (-- loop) >= 0);\n+\n+            while (listLength(ll) != 0) {\n+                listNode *head = listFirst(ll);\n+                robj *field = listNodeValue(head);\n+                dictDelete(ht, field);\n+                listDelNode(ll, head);\n+            }\n+            listRelease(ll);\n+        }\n+        return;\n+    }\n+\n+    if (val->type == OBJ_ZSET) {\n+        zset *zs = val->ptr;\n+        dict *ht = zs->dict;\n+        if (dictSize(ht) <= limit) {\n+            decrRefCount(val);\n+            it->val = NULL;\n+        } else {\n+            zskiplist *zsl = zs->zsl;\n+            for (int i = 0; i < step; i ++) {\n+                zskiplistNode *node = zsl->header->level[0].forward;\n+                robj *field = node->obj;\n+                incrRefCount(field);\n+                zslDelete(zsl, node->score, field);\n+                dictDelete(ht, field);\n+                decrRefCount(field);\n+            }\n+        }\n+        return;\n+    }\n+\n+    serverPanic(\"unknown object type\");\n+}\n+\n+static int\n+lazyReleaseIteratorRemains(lazyReleaseIterator *it) {\n+    robj *val = it->val;\n+    if (val == NULL) {\n+        return 0;\n+    }\n+    if (val->type == OBJ_LIST) {\n+        return listTypeLength(val);\n+    }\n+    if (val->type == OBJ_HASH) {\n+        return hashTypeLength(val);\n+    }\n+    if (val->type == OBJ_SET) {\n+        return setTypeSize(val);\n+    }\n+    if (val->type == OBJ_ZSET) {\n+        return zsetLength(val);\n+    }\n+    return -1;\n+}\n+\n+static int\n+slotsmgrtLazyReleaseStep(int step) {\n+    list *ll = server.slotsmgrt_lazy_release;\n+    if (listLength(ll) != 0) {\n+        listNode *head = listFirst(ll);\n+        lazyReleaseIterator *it = listNodeValue(head);\n+        if (lazyReleaseIteratorHasNext(it)) {\n+            lazyReleaseIteratorNext(it, step);\n+        } else {\n+            freeLazyReleaseIterator(it);\n+            listDelNode(ll, head);\n+        }\n+        return 1;\n+    }\n+    return 0;\n+}\n+\n+static void\n+slotsmgrtLazyReleaseMicroseconds(long long usecs) {\n+    long long deadline = ustime() + usecs;\n+    while (slotsmgrtLazyReleaseStep(50)) {\n+        if (ustime() >= deadline) {\n+            return;\n+        }\n+    }\n+}\n+\n+static struct {\n+    long long last_numcommands;\n+    int step;\n+} lazy_release_options = {\n+    .last_numcommands = 0,\n+    .step = 1,\n+};\n+\n+void\n+slotsmgrtLazyReleaseCleanup() {\n+    long long ops = server.stat_numcommands - lazy_release_options.last_numcommands;\n+    if (ops < 0) {\n+        ops = 0;\n+    }\n+    if (ops > 30) {\n+        lazy_release_options.step = 1 + (1000 / ops) * 3;\n+    } else {\n+        lazy_release_options.step = 100;\n+    }\n+    lazy_release_options.last_numcommands = server.stat_numcommands;\n+\n+    long long usecs = lazy_release_options.step / 10 * 100;\n+    if (usecs != 0) {\n+        slotsmgrtLazyReleaseMicroseconds(usecs);\n+    }\n+}\n+\n+void\n+slotsmgrtLazyReleaseIncrementally() {\n+    slotsmgrtLazyReleaseStep(lazy_release_options.step);\n+}\n+\n+/* *\n+ * SLOTSMGRT-LAZY-RELEASE $microseconds\n+ * */\n+void\n+slotsmgrtLazyReleaseCommand(client *c) {\n+    if (c->argc != 1 && c->argc != 2) {\n+        addReplyError(c, \"wrong number of arguments for SLOTSMGRT-LAZY-RELEASE\");\n+        return;\n+    }\n+    long long usecs = 1;\n+    if (c->argc != 1) {\n+        if (getLongLongFromObject(c->argv[1], &usecs) != C_OK ||\n+                !(usecs >= 0 && usecs <= INT_MAX)) {\n+            addReplyErrorFormat(c, \"invalid value of usecs (%s)\",\n+                    (char *)c->argv[1]->ptr);\n+            return;\n+        }\n+    }\n+    if (usecs != 0) {\n+        slotsmgrtLazyReleaseMicroseconds(usecs);\n+    }\n+\n+    list *ll = server.slotsmgrt_lazy_release;\n+\n+    addReplyMultiBulkLen(c, 2);\n+    addReplyLongLong(c, listLength(ll));\n+\n+    if (listLength(ll) != 0) {\n+        lazyReleaseIterator *it = listNodeValue(listFirst(ll));\n+        addReplyLongLong(c, lazyReleaseIteratorRemains(it));\n+    } else {\n+        addReplyLongLong(c, 0);\n+    }\n+}\n+\n+/* ============================ Iterator for Data Migration ================================ */\n+\n+#define STAGE_PREPARE 0\n+#define STAGE_PAYLOAD 1\n+#define STAGE_CHUNKED 2\n+#define STAGE_FILLTTL 3\n+#define STAGE_DONE    4\n+\n+typedef struct {\n+    int stage;\n+    robj *key;\n+    robj *val;\n+    long long expire;\n+    unsigned long cursor;\n+    unsigned long lindex;\n+    unsigned long zindex;\n+    int chunked;\n+} singleObjectIterator;\n+\n+static singleObjectIterator *\n+createSingleObjectIterator(robj *key) {\n+    singleObjectIterator *it = zmalloc(sizeof(singleObjectIterator));\n+    it->stage = STAGE_PREPARE;\n+    it->key = key;\n+    incrRefCount(it->key);\n+    it->val = NULL;\n+    it->expire = 0;\n+    it->cursor = 0;\n+    it->lindex = 0;\n+    it->zindex = 0;\n+    it->chunked = 0;\n+    return it;\n+}\n+\n+static void\n+freeSingleObjectIterator(singleObjectIterator *it) {\n+    if (it->val != NULL) {\n+        decrRefCount(it->val);\n+    }\n+    decrRefCount(it->key);\n+    zfree(it);\n+}\n+\n+static void\n+freeSingleObjectIteratorVoid(void *it) {\n+    freeSingleObjectIterator(it);\n+}\n+\n+static int\n+singleObjectIteratorHasNext(singleObjectIterator *it) {\n+    return it->stage != STAGE_DONE;\n+}\n+\n+static size_t\n+sdslenOrElse(robj *o, size_t len) {\n+    return sdsEncodedObject(o) ? sdslen(o->ptr) : len;\n+}\n+\n+static void\n+singleObjectIteratorScanCallback(void *data, const dictEntry *de) {\n+    void **pd = (void **)data;\n+    list *l = pd[0];\n+    robj *o = pd[1];\n+    long long *n = pd[2];\n+\n+    robj *objs[2] = {NULL, NULL};\n+    switch (o->type) {\n+    case OBJ_HASH:\n+        objs[0] = dictGetKey(de);\n+        objs[1] = dictGetVal(de);\n+        break;\n+    case OBJ_SET:\n+        objs[0] = dictGetKey(de);\n+        break;\n+    }\n+    for (int i = 0; i < 2; i ++) {\n+        if (objs[i] != NULL) {\n+            incrRefCount(objs[i]);\n+            *n += sdslenOrElse(objs[i], 8);\n+            listAddNodeTail(l, objs[i]);\n+        }\n+    }\n+}\n+\n+static uint64_t\n+convertDoubleToRawBits(double value) {\n+    union {\n+        double d;\n+        uint64_t u;\n+    } fp;\n+    fp.d = value;\n+    return fp.u;\n+}\n+\n+static double\n+convertRawBitsToDouble(uint64_t value) {\n+    union {\n+        double d;\n+        uint64_t u;\n+    } fp;\n+    fp.u = value;\n+    return fp.d;\n+}\n+\n+static robj *\n+createRawStringObjectFromUint64(uint64_t v) {\n+    uint64_t p = intrev64ifbe(v);\n+    return createRawStringObject((char *)&p, sizeof(p));\n+}\n+\n+static int\n+getUint64FromRawStringObject(robj *o, uint64_t *p) {\n+    if (sdsEncodedObject(o) && sdslen(o->ptr) == sizeof(uint64_t)) {\n+        *p = intrev64ifbe(*(uint64_t *)(o->ptr));\n+        return C_OK;\n+    }\n+    return C_ERR;\n+}\n+\n+static long\n+numberOfRestoreCommandsFromObject(robj *val, long long maxbulks) {\n+    long long numbulks = 0;\n+    switch (val->type) {\n+    case OBJ_LIST:\n+        if (val->encoding == OBJ_ENCODING_QUICKLIST) {\n+            numbulks = listTypeLength(val);\n+        }\n+        break;\n+    case OBJ_HASH:\n+        if (val->encoding == OBJ_ENCODING_HT) {\n+            numbulks = hashTypeLength(val) * 2;\n+        }\n+        break;\n+    case OBJ_SET:\n+        if (val->encoding == OBJ_ENCODING_HT) {\n+            numbulks = setTypeSize(val);\n+        }\n+        break;\n+    case OBJ_ZSET:\n+        if (val->encoding == OBJ_ENCODING_SKIPLIST) {\n+            numbulks = zsetLength(val) * 2;\n+        }\n+        break;\n+    }\n+    if (numbulks <= maxbulks) {\n+        return 1;\n+    }\n+    return (numbulks + maxbulks - 1) / maxbulks;\n+}\n+\n+static long\n+estimateNumberOfRestoreCommands(redisDb *db, robj *key, long long maxbulks) {\n+    robj *val = lookupKeyWrite(db, key);\n+    if (val != NULL) {\n+        return numberOfRestoreCommandsFromObject(val, maxbulks);\n+    }\n+    return 0;\n+}\n+\n+extern void createDumpPayload(rio *payload, robj *o);\n+extern zskiplistNode* zslGetElementByRank(zskiplist *zsl, unsigned long rank);\n+\n+static slotsmgrtAsyncClient *getSlotsmgrtAsyncClient(int db);\n+\n+static int\n+singleObjectIteratorNext(client *c, singleObjectIterator *it,\n+        long long timeout, unsigned int maxbulks, unsigned int maxbytes) {\n+    /* *\n+     * STAGE_PREPARE ---> STAGE_PAYLOAD ---> STAGE_DONE\n+     *     |                                      A\n+     *     V                                      |\n+     *     +------------> STAGE_CHUNKED ---> STAGE_FILLTTL\n+     *                      A       |\n+     *                      |       V\n+     *                      +-------+\n+     * */\n+\n+    robj *key = it->key;\n+\n+    if (it->stage == STAGE_PREPARE) {\n+        robj *val = lookupKeyWrite(c->db, key);\n+        if (val == NULL) {\n+            it->stage = STAGE_DONE;\n+            return 0;\n+        }\n+        it->val = val;\n+        incrRefCount(it->val);\n+        it->expire = getExpire(c->db, key);\n+\n+        int extra_msgs = 0;\n+\n+        slotsmgrtAsyncClient *client = getSlotsmgrtAsyncClient(c->db->id);\n+        if (client->c == c) {\n+            if (client->used == 0) {\n+                client->used = 1;\n+                if (server.requirepass != NULL) {\n+                    /* SLOTSRESTORE-ASYNC-AUTH $password */\n+                    addReplyMultiBulkLen(c, 2);\n+                    addReplyBulkCString(c, \"SLOTSRESTORE-ASYNC-AUTH\");\n+                    addReplyBulkCString(c, server.requirepass);\n+                    extra_msgs += 1;\n+                }\n+                do {\n+                    /* SLOTSRESTORE-ASYNC select $db */\n+                    addReplyMultiBulkLen(c, 3);\n+                    addReplyBulkCString(c, \"SLOTSRESTORE-ASYNC\");\n+                    addReplyBulkCString(c, \"select\");\n+                    addReplyBulkLongLong(c, c->db->id);\n+                    extra_msgs += 1;\n+                } while (0);\n+            }\n+        }\n+\n+        /* SLOTSRESTORE-ASYNC del $key */\n+        addReplyMultiBulkLen(c, 3);\n+        addReplyBulkCString(c, \"SLOTSRESTORE-ASYNC\");\n+        addReplyBulkCString(c, \"del\");\n+        addReplyBulk(c, key);\n+\n+        if (numberOfRestoreCommandsFromObject(val, maxbulks) != 1) {\n+            it->stage = STAGE_CHUNKED;\n+            it->chunked = 1;\n+        } else {\n+            it->stage = STAGE_PAYLOAD;\n+        }\n+        return 1 + extra_msgs;\n+    }\n+\n+    robj *val = it->val;\n+    long long ttl = 0;\n+    if (it->stage == STAGE_CHUNKED) {\n+        ttl = timeout * 3;\n+    } else if (it->expire != -1) {\n+        ttl = it->expire - mstime();\n+        if (ttl < 1) {\n+            ttl = 1;\n+        }\n+    }\n+\n+    if (it->stage == STAGE_FILLTTL) {\n+        /* SLOTSRESTORE-ASYNC expire $key $ttl */\n+        addReplyMultiBulkLen(c, 4);\n+        addReplyBulkCString(c, \"SLOTSRESTORE-ASYNC\");\n+        addReplyBulkCString(c, \"expire\");\n+        addReplyBulk(c, key);\n+        addReplyBulkLongLong(c, ttl);\n+\n+        it->stage = STAGE_DONE;\n+        return 1;\n+    }\n+\n+    if (it->stage == STAGE_PAYLOAD && val->type != OBJ_STRING) {\n+        rio payload;\n+        createDumpPayload(&payload, val);\n+\n+        /* SLOTSRESTORE-ASYNC object $key $ttl $payload */\n+        addReplyMultiBulkLen(c, 5);\n+        addReplyBulkCString(c, \"SLOTSRESTORE-ASYNC\");\n+        addReplyBulkCString(c, \"object\");\n+        addReplyBulk(c, key);\n+        addReplyBulkLongLong(c, ttl);\n+        addReplyBulkSds(c, payload.io.buffer.ptr);\n+\n+        it->stage = STAGE_DONE;\n+        return 1;\n+    }\n+\n+    if (it->stage == STAGE_PAYLOAD && val->type == OBJ_STRING) {\n+        /* SLOTSRESTORE-ASYNC string $key $ttl $payload */\n+        addReplyMultiBulkLen(c, 5);\n+        addReplyBulkCString(c, \"SLOTSRESTORE-ASYNC\");\n+        addReplyBulkCString(c, \"string\");\n+        addReplyBulk(c, key);\n+        addReplyBulkLongLong(c, ttl);\n+        addReplyBulk(c, val);\n+\n+        it->stage = STAGE_DONE;\n+        return 1;\n+    }\n+\n+    if (it->stage == STAGE_CHUNKED) {\n+        const char *cmd = NULL;\n+        switch (val->type) {\n+        case OBJ_LIST:\n+            cmd = \"list\";\n+            break;\n+        case OBJ_HASH:\n+            cmd = \"hash\";\n+            break;\n+        case OBJ_SET:\n+            cmd = \"dict\";\n+            break;\n+        case OBJ_ZSET:\n+            cmd = \"zset\";\n+            break;\n+        default:\n+            serverPanic(\"unknown object type\");\n+        }\n+\n+        int more = 1;\n+\n+        list *ll = listCreate();\n+        listSetFreeMethod(ll, decrRefCountVoid);\n+        long long hint = 0, len = 0;\n+\n+        if (val->type == OBJ_LIST) {\n+            listTypeIterator *li = listTypeInitIterator(val, it->lindex, LIST_TAIL);\n+            do {\n+                listTypeEntry entry;\n+                if (listTypeNext(li, &entry)) {\n+                    quicklistEntry *e = &(entry.entry);\n+                    robj *obj;\n+                    if (e->value) {\n+                        obj = createStringObject((const char *)e->value, e->sz);\n+                    } else {\n+                        obj = createStringObjectFromLongLong(e->longval);\n+                    }\n+                    len += sdslenOrElse(obj, 8);\n+                    listAddNodeTail(ll, obj);\n+                    it->lindex ++;\n+                } else {\n+                    more = 0;\n+                }\n+            } while (more && listLength(ll) < maxbulks && len < maxbytes);\n+            listTypeReleaseIterator(li);\n+            hint = listTypeLength(val);\n+        }\n+\n+        if (val->type == OBJ_HASH || val->type == OBJ_SET) {\n+            int loop = maxbulks * 10;\n+            if (loop < 100) {\n+                loop = 100;\n+            }\n+            dict *ht = val->ptr;\n+            void *pd[] = {ll, val, &len};\n+            do {\n+                it->cursor = dictScan(ht, it->cursor, singleObjectIteratorScanCallback, pd);\n+                if (it->cursor == 0) {\n+                    more = 0;\n+                }\n+            } while (more && listLength(ll) < maxbulks && len < maxbytes && (-- loop) >= 0);\n+            hint = dictSize(ht);\n+        }\n+\n+        if (val->type == OBJ_ZSET) {\n+            zset *zs = val->ptr;\n+            dict *ht = zs->dict;\n+            long long rank = (long long)zsetLength(val) - it->zindex;\n+            zskiplistNode *node = (rank >= 1) ? zslGetElementByRank(zs->zsl, rank) : NULL;\n+            do {\n+                if (node != NULL) {\n+                    robj *field = node->obj;\n+                    incrRefCount(field);\n+                    len += sdslenOrElse(field, 8);\n+                    listAddNodeTail(ll, field);\n+                    uint64_t bits = convertDoubleToRawBits(node->score);\n+                    robj *score = createRawStringObjectFromUint64(bits);\n+                    len += sdslenOrElse(score, 8);\n+                    listAddNodeTail(ll, score);\n+                    node = node->backward;\n+                    it->zindex ++;\n+                } else {\n+                    more = 0;\n+                }\n+            } while (more && listLength(ll) < maxbulks && len < maxbytes);\n+            hint = dictSize(ht);\n+        }\n+\n+        /* SLOTSRESTORE-ASYNC list/hash/zset/dict $key $ttl $hint [$arg1 ...] */\n+        addReplyMultiBulkLen(c, 5 + listLength(ll));\n+        addReplyBulkCString(c, \"SLOTSRESTORE-ASYNC\");\n+        addReplyBulkCString(c, cmd);\n+        addReplyBulk(c, key);\n+        addReplyBulkLongLong(c, ttl);\n+        addReplyBulkLongLong(c, hint);\n+\n+        while (listLength(ll) != 0) {\n+            listNode *head = listFirst(ll);\n+            robj *obj = listNodeValue(head);\n+            addReplyBulk(c, obj);\n+            listDelNode(ll, head);\n+        }\n+        listRelease(ll);\n+\n+        if (!more) {\n+            it->stage = STAGE_FILLTTL;\n+        }\n+        return 1;\n+    }\n+\n+    if (it->stage != STAGE_DONE) {\n+        serverPanic(\"invalid iterator stage\");\n+    }\n+\n+    serverPanic(\"use of empty iterator\");\n+}\n+\n+/* ============================ Iterator for Data Migration (batched) ====================== */\n+\n+typedef struct {\n+    struct zskiplist *tags;\n+    dict *keys;\n+    list *list;\n+    dict *hash_slot;\n+    struct zskiplist *hash_tags;\n+    long long timeout;\n+    unsigned int maxbulks;\n+    unsigned int maxbytes;\n+    list *removed_keys;\n+    list *chunked_vals;\n+    long estimate_msgs;\n+} batchedObjectIterator;\n+\n+static batchedObjectIterator *\n+createBatchedObjectIterator(dict *hash_slot, struct zskiplist *hash_tags,\n+        long long timeout, unsigned int maxbulks, unsigned int maxbytes) {\n+    batchedObjectIterator *it = zmalloc(sizeof(batchedObjectIterator));\n+    it->tags = zslCreate();\n+    it->keys = dictCreate(&setDictType, NULL);\n+    it->list = listCreate();\n+    listSetFreeMethod(it->list, freeSingleObjectIteratorVoid);\n+    it->hash_slot = hash_slot;\n+    it->hash_tags = hash_tags;\n+    it->timeout = timeout;\n+    it->maxbulks = maxbulks;\n+    it->maxbytes = maxbytes;\n+    it->removed_keys = listCreate();\n+    listSetFreeMethod(it->removed_keys, decrRefCountVoid);\n+    it->chunked_vals = listCreate();\n+    listSetFreeMethod(it->chunked_vals, decrRefCountVoid);\n+    it->estimate_msgs = 0;\n+    return it;\n+}\n+\n+static void\n+freeBatchedObjectIterator(batchedObjectIterator *it) {\n+    zslFree(it->tags);\n+    dictRelease(it->keys);\n+    listRelease(it->list);\n+    listRelease(it->removed_keys);\n+    listRelease(it->chunked_vals);\n+    zfree(it);\n+}\n+\n+static int\n+batchedObjectIteratorHasNext(batchedObjectIterator *it) {\n+    while (listLength(it->list) != 0) {\n+        listNode *head = listFirst(it->list);\n+        singleObjectIterator *sp = listNodeValue(head);\n+        if (singleObjectIteratorHasNext(sp)) {\n+            return 1;\n+        }\n+        if (sp->val != NULL) {\n+            incrRefCount(sp->key);\n+            listAddNodeTail(it->removed_keys, sp->key);\n+            if (sp->chunked) {\n+                incrRefCount(sp->val);\n+                listAddNodeTail(it->chunked_vals, sp->val);\n+            }\n+        }\n+        listDelNode(it->list, head);\n+    }\n+    return 0;\n+}\n+\n+static int\n+batchedObjectIteratorNext(client *c, batchedObjectIterator *it) {\n+    if (listLength(it->list) != 0) {\n+        listNode *head = listFirst(it->list);\n+        singleObjectIterator *sp = listNodeValue(head);\n+        long long maxbytes = (long long)it->maxbytes - getClientOutputBufferMemoryUsage(c);\n+        return singleObjectIteratorNext(c, sp, it->timeout, it->maxbulks, maxbytes > 0 ? maxbytes : 0);\n+    }\n+    serverPanic(\"use of empty iterator\");\n+}\n+\n+static int\n+batchedObjectIteratorContains(batchedObjectIterator *it, robj *key, int usetag) {\n+    if (dictFind(it->keys, key) != NULL) {\n+        return 1;\n+    }\n+    if (!usetag) {\n+        return 0;\n+    }\n+    uint32_t crc;\n+    int hastag;\n+    slots_num(key->ptr, &crc, &hastag);\n+    if (!hastag) {\n+        return 0;\n+    }\n+    zrangespec range;\n+    range.min = (double)crc;\n+    range.minex = 0;\n+    range.max = (double)crc;\n+    range.maxex = 0;\n+    return zslFirstInRange(it->tags, &range) != NULL;\n+}\n+\n+static int\n+batchedObjectIteratorAddKey(redisDb *db, batchedObjectIterator *it, robj *key) {\n+    if (dictAdd(it->keys, key, NULL) != C_OK) {\n+        return 0;\n+    }\n+    incrRefCount(key);\n+    listAddNodeTail(it->list, createSingleObjectIterator(key));\n+    it->estimate_msgs += estimateNumberOfRestoreCommands(db, key, it->maxbulks);\n+\n+    int size = dictSize(it->keys);\n+\n+    uint32_t crc;\n+    int hastag;\n+    slots_num(key->ptr, &crc, &hastag);\n+    if (!hastag) {\n+        goto out;\n+    }\n+    zrangespec range;\n+    range.min = (double)crc;\n+    range.minex = 0;\n+    range.max = (double)crc;\n+    range.maxex = 0;\n+    if (zslFirstInRange(it->tags, &range) != NULL) {\n+        goto out;\n+    }\n+    incrRefCount(key);\n+    zslInsert(it->tags, (double)crc, key);\n+\n+    if (it->hash_tags == NULL) {\n+        goto out;\n+    }\n+    zskiplistNode *node = zslFirstInRange(it->hash_tags, &range);\n+    while (node != NULL && node->score == (double)crc) {\n+        robj *key = node->obj;\n+        node = node->level[0].forward;\n+        if (dictAdd(it->keys, key, NULL) != C_OK) {\n+            continue;\n+        }\n+        incrRefCount(key);\n+        listAddNodeTail(it->list, createSingleObjectIterator(key));\n+        it->estimate_msgs += estimateNumberOfRestoreCommands(db, key, it->maxbulks);\n+    }\n+\n+out:\n+    return 1 + dictSize(it->keys) - size;\n+}\n+\n+static void\n+batchedObjectIteratorAddKeyCallback(void *data, const dictEntry *de) {\n+    void **pd = (void **)data;\n+    batchedObjectIterator *it = pd[0];\n+    redisDb *db = pd[1];\n+    long long numkeys = *(long long *)pd[2];\n+\n+    if (it->estimate_msgs >= numkeys) {\n+        return;\n+    }\n+    sds skey = dictGetKey(de);\n+    robj *key = createStringObject(skey, sdslen(skey));\n+    long msgs = estimateNumberOfRestoreCommands(db, key, it->maxbulks);\n+    if (it->estimate_msgs == 0 || it->estimate_msgs + msgs <= numkeys * 2) {\n+        batchedObjectIteratorAddKey(db, it, key);\n+    }\n+    decrRefCount(key);\n+}\n+\n+/* ============================ Clients ==================================================== */\n+\n+static slotsmgrtAsyncClient *\n+getSlotsmgrtAsyncClient(int db) {\n+    return &server.slotsmgrt_cached_clients[db];\n+}\n+\n+static void\n+notifySlotsmgrtAsyncClient(slotsmgrtAsyncClient *ac, const char *errmsg) {\n+    batchedObjectIterator *it = ac->batched_iter;\n+    list *ll = ac->blocked_list;\n+    while (listLength(ll) != 0) {\n+        listNode *head = listFirst(ll);\n+        client *c = listNodeValue(head);\n+        if (errmsg != NULL) {\n+            addReplyError(c, errmsg);\n+        } else if (it == NULL) {\n+            addReplyError(c, \"invalid iterator (NULL)\");\n+        } else if (it->hash_slot == NULL) {\n+            addReplyLongLong(c, listLength(it->removed_keys));\n+        } else {\n+            addReplyMultiBulkLen(c, 2);\n+            addReplyLongLong(c, listLength(it->removed_keys));\n+            addReplyLongLong(c, dictSize(it->hash_slot));\n+        }\n+        c->slotsmgrt_flags &= ~CLIENT_SLOTSMGRT_ASYNC_NORMAL_CLIENT;\n+        c->slotsmgrt_fenceq = NULL;\n+        listDelNode(ll, head);\n+    }\n+}\n+\n+static void\n+unlinkSlotsmgrtAsyncCachedClient(client *c, const char *errmsg) {\n+    slotsmgrtAsyncClient *ac = getSlotsmgrtAsyncClient(c->db->id);\n+    serverAssert(c->slotsmgrt_flags & CLIENT_SLOTSMGRT_ASYNC_CACHED_CLIENT);\n+    serverAssert(ac->c == c);\n+\n+    notifySlotsmgrtAsyncClient(ac, errmsg);\n+\n+    batchedObjectIterator *it = ac->batched_iter;\n+\n+    long long elapsed = mstime() - ac->lastuse;\n+    serverLog(LL_WARNING, \"slotsmgrt_async: unlink client %s:%d (DB=%d): \"\n+            \"sending_msgs = %ld, batched_iter = %ld, blocked_list = %ld, \"\n+            \"timeout = %lld(ms), elapsed = %lld(ms) (%s)\",\n+            ac->host, ac->port, c->db->id, ac->sending_msgs,\n+            it != NULL ? (long)listLength(it->list) : -1, (long)listLength(ac->blocked_list),\n+            ac->timeout, elapsed, errmsg);\n+\n+    sdsfree(ac->host);\n+    if (it != NULL) {\n+        freeBatchedObjectIterator(it);\n+    }\n+    listRelease(ac->blocked_list);\n+\n+    c->slotsmgrt_flags &= ~CLIENT_SLOTSMGRT_ASYNC_CACHED_CLIENT;\n+\n+    memset(ac, 0, sizeof(*ac));\n+}\n+\n+static int\n+releaseSlotsmgrtAsyncClient(int db, const char *errmsg) {\n+    slotsmgrtAsyncClient *ac = getSlotsmgrtAsyncClient(db);\n+    if (ac->c == NULL) {\n+        return 0;\n+    }\n+    client *c = ac->c;\n+    unlinkSlotsmgrtAsyncCachedClient(c, errmsg);\n+    freeClient(c);\n+    return 1;\n+}\n+\n+static int\n+createSlotsmgrtAsyncClient(int db, char *host, int port, long timeout) {\n+    int fd = anetTcpNonBlockConnect(server.neterr, host, port);\n+    if (fd == -1) {\n+        serverLog(LL_WARNING, \"slotsmgrt_async: create socket %s:%d (DB=%d) failed, %s\",\n+                host, port, db, server.neterr);\n+        return C_ERR;\n+    }\n+    anetEnableTcpNoDelay(server.neterr, fd);\n+\n+    int wait = 100;\n+    if (wait > timeout) {\n+        wait = timeout;\n+    }\n+    if ((aeWait(fd, AE_WRITABLE, wait) & AE_WRITABLE) == 0) {\n+        serverLog(LL_WARNING, \"slotsmgrt_async: create socket %s:%d (DB=%d) failed, io error or timeout (%d)\",\n+                host, port, db, wait);\n+        close(fd);\n+        return C_ERR;\n+    }\n+\n+    client *c = createClient(fd);\n+    if (c == NULL) {\n+        serverLog(LL_WARNING, \"slotsmgrt_async: create client %s:%d (DB=%d) failed, %s\",\n+                host, port, db, server.neterr);\n+        return C_ERR;\n+    }\n+    if (selectDb(c, db) != C_OK) {\n+        serverLog(LL_WARNING, \"slotsmgrt_async: invalid DB index (DB=%d)\", db);\n+        freeClient(c);\n+        return C_ERR;\n+    }\n+    c->slotsmgrt_flags |= CLIENT_SLOTSMGRT_ASYNC_CACHED_CLIENT;\n+    c->authenticated = 1;\n+\n+    releaseSlotsmgrtAsyncClient(db, \"interrupted: build new connection\");\n+\n+    serverLog(LL_WARNING, \"slotsmgrt_async: create client %s:%d (DB=%d) OK\", host, port, db);\n+\n+    slotsmgrtAsyncClient *ac = getSlotsmgrtAsyncClient(db);\n+    ac->c = c;\n+    ac->used = 0;\n+    ac->host = sdsnew(host);\n+    ac->port = port;\n+    ac->timeout = timeout;\n+    ac->lastuse = mstime();\n+    ac->sending_msgs = 0;\n+    ac->batched_iter = NULL;\n+    ac->blocked_list = listCreate();\n+    return C_OK;\n+}\n+\n+static slotsmgrtAsyncClient *\n+getOrCreateSlotsmgrtAsyncClient(int db, char *host, int port, long timeout) {\n+    slotsmgrtAsyncClient *ac = getSlotsmgrtAsyncClient(db);\n+    if (ac->c != NULL) {\n+        if (ac->port == port && !strcmp(ac->host, host)) {\n+            return ac;\n+        }\n+    }\n+    return createSlotsmgrtAsyncClient(db, host, port, timeout) != C_OK ? NULL : ac;\n+}\n+\n+static void\n+unlinkSlotsmgrtAsyncNormalClient(client *c) {\n+    serverAssert(c->slotsmgrt_flags & CLIENT_SLOTSMGRT_ASYNC_NORMAL_CLIENT);\n+    serverAssert(c->slotsmgrt_fenceq != NULL);\n+\n+    list *ll = c->slotsmgrt_fenceq;\n+    listNode *node = listSearchKey(ll, c);\n+    serverAssert(node != NULL);\n+\n+    c->slotsmgrt_flags &= ~CLIENT_SLOTSMGRT_ASYNC_NORMAL_CLIENT;\n+    c->slotsmgrt_fenceq = NULL;\n+    listDelNode(ll, node);\n+}\n+\n+void\n+slotsmgrtAsyncUnlinkClient(client *c) {\n+    if (c->slotsmgrt_flags & CLIENT_SLOTSMGRT_ASYNC_CACHED_CLIENT) {\n+        unlinkSlotsmgrtAsyncCachedClient(c, \"interrupted: connection closed\");\n+    }\n+    if (c->slotsmgrt_flags & CLIENT_SLOTSMGRT_ASYNC_NORMAL_CLIENT) {\n+        unlinkSlotsmgrtAsyncNormalClient(c);\n+    }\n+}\n+\n+void\n+slotsmgrtAsyncCleanup() {\n+    for (int i = 0; i < server.dbnum; i ++) {\n+        slotsmgrtAsyncClient *ac = getSlotsmgrtAsyncClient(i);\n+        if (ac->c == NULL) {\n+            continue;\n+        }\n+        long long elapsed = mstime() - ac->lastuse;\n+        long long timeout = ac->batched_iter != NULL ? ac->timeout : 1000LL * 60;\n+        if (elapsed <= timeout) {\n+            continue;\n+        }\n+        releaseSlotsmgrtAsyncClient(i, ac->batched_iter != NULL ?\n+                \"interrupted: migration timeout\" : \"interrupted: idle timeout\");\n+    }\n+}\n+\n+static int\n+getSlotsmgrtAsyncClientMigrationStatusOrBlock(client *c, robj *key, int block) {\n+    slotsmgrtAsyncClient *ac = getSlotsmgrtAsyncClient(c->db->id);\n+    if (ac->c == NULL || ac->batched_iter == NULL) {\n+        return 0;\n+    }\n+    batchedObjectIterator *it = ac->batched_iter;\n+    if (key != NULL && !batchedObjectIteratorContains(it, key, 1)) {\n+        return 0;\n+    }\n+    if (!block) {\n+        return 1;\n+    }\n+    if (c->slotsmgrt_flags & CLIENT_SLOTSMGRT_ASYNC_NORMAL_CLIENT) {\n+        return -1;\n+    }\n+    list *ll = ac->blocked_list;\n+    c->slotsmgrt_flags |= CLIENT_SLOTSMGRT_ASYNC_NORMAL_CLIENT;\n+    c->slotsmgrt_fenceq = ll;\n+    listAddNodeTail(ll, c);\n+    return 1;\n+}\n+\n+/* ============================ Slotsmgrt{One,TagOne}AsyncDumpCommand ====================== */\n+\n+/* SLOTSMGRTONE-ASYNC-DUMP    $timeout $maxbulks $key1 [$key2 ...] */\n+/* SLOTSMGRTTAGONE-ASYNC-DUMP $timeout $maxbulks $key1 [$key2 ...] */\n+static void\n+slotsmgrtAsyncDumpGenericCommand(client *c, int usetag) {\n+    long long timeout;\n+    if (getLongLongFromObject(c->argv[1], &timeout) != C_OK ||\n+            !(timeout >= 0 && timeout <= INT_MAX)) {\n+        addReplyErrorFormat(c, \"invalid value of timeout (%s)\",\n+                (char *)c->argv[1]->ptr);\n+        return;\n+    }\n+    if (timeout == 0) {\n+        timeout = 1000 * 30;\n+    }\n+    long long maxbulks;\n+    if (getLongLongFromObject(c->argv[2], &maxbulks) != C_OK ||\n+            !(maxbulks >= 0 && maxbulks <= INT_MAX)) {\n+        addReplyErrorFormat(c, \"invalid value of maxbulks (%s)\",\n+                (char *)c->argv[2]->ptr);\n+        return;\n+    }\n+    if (maxbulks == 0) {\n+        maxbulks = 1000;\n+    }\n+\n+    batchedObjectIterator *it = createBatchedObjectIterator(NULL,\n+            usetag ? c->db->tagged_keys : NULL, timeout, maxbulks, INT_MAX);\n+    for (int i = 3; i < c->argc; i ++) {\n+        batchedObjectIteratorAddKey(c->db, it, c->argv[i]);\n+    }\n+\n+    void *ptr = addDeferredMultiBulkLength(c);\n+    int total = 0;\n+    while (batchedObjectIteratorHasNext(it)) {\n+        total += batchedObjectIteratorNext(c, it);\n+    }\n+    setDeferredMultiBulkLength(c, ptr, total);\n+    freeBatchedObjectIterator(it);\n+}\n+\n+/* *\n+ * SLOTSMGRTONE-ASYNC-DUMP    $timeout $maxbulks $key1 [$key2 ...]\n+ * */\n+void slotsmgrtOneAsyncDumpCommand(client *c) {\n+    if (c->argc <= 3) {\n+        addReplyError(c, \"wrong number of arguments for SLOTSMGRTONE-ASYNC-DUMP\");\n+        return;\n+    }\n+    slotsmgrtAsyncDumpGenericCommand(c, 0);\n+}\n+\n+/* *\n+ * SLOTSMGRTTAGONE-ASYNC-DUMP $timeout $maxbulks $key1 [$key2 ...]\n+ * */\n+void\n+slotsmgrtTagOneAsyncDumpCommand(client *c) {\n+    if (c->argc <= 3) {\n+        addReplyError(c, \"wrong number of arguments for SLOTSMGRTTAGONE-ASYNC-DUMP\");\n+        return;\n+    }\n+    slotsmgrtAsyncDumpGenericCommand(c, 1);\n+}\n+\n+/* ============================ Slotsmgrt{One,TagOne,Slot,TagSlot}AsyncCommand ============= */\n+\n+static unsigned int\n+slotsmgrtAsyncMaxBufferLimit(unsigned int maxbytes) {\n+    clientBufferLimitsConfig *config = &server.client_obuf_limits[CLIENT_TYPE_NORMAL];\n+    if (config->soft_limit_bytes != 0 && config->soft_limit_bytes < maxbytes) {\n+        maxbytes = config->soft_limit_bytes;\n+    }\n+    if (config->hard_limit_bytes != 0 && config->hard_limit_bytes < maxbytes) {\n+        maxbytes = config->hard_limit_bytes;\n+    }\n+    return maxbytes;\n+}\n+\n+static long\n+slotsmgrtAsyncNextMessagesMicroseconds(slotsmgrtAsyncClient *ac, long atleast, long long usecs) {\n+    batchedObjectIterator *it = ac->batched_iter;\n+    long long deadline = ustime() + usecs;\n+    long msgs = 0;\n+    while (batchedObjectIteratorHasNext(it) && getClientOutputBufferMemoryUsage(ac->c) < it->maxbytes) {\n+        if ((msgs += batchedObjectIteratorNext(ac->c, it)) < atleast) {\n+            continue;\n+        }\n+        if (ustime() >= deadline) {\n+            return msgs;\n+        }\n+    }\n+    return msgs;\n+}\n+\n+/* SLOTSMGRTONE-ASYNC     $host $port $timeout $maxbulks $maxbytes $key1 [$key2 ...] */\n+/* SLOTSMGRTTAGONE-ASYNC  $host $port $timeout $maxbulks $maxbytes $key1 [$key2 ...] */\n+/* SLOTSMGRTSLOT-ASYNC    $host $port $timeout $maxbulks $maxbytes $slot $numkeys    */\n+/* SLOTSMGRTTAGSLOT-ASYNC $host $port $timeout $maxbulks $maxbytes $slot $numkeys    */\n+static void\n+slotsmgrtAsyncGenericCommand(client *c, int usetag, int usekey) {\n+    char *host = c->argv[1]->ptr;\n+    long long port;\n+    if (getLongLongFromObject(c->argv[2], &port) != C_OK ||\n+            !(port >= 1 && port < 65536)) {\n+        addReplyErrorFormat(c, \"invalid value of port (%s)\",\n+                (char *)c->argv[2]->ptr);\n+        return;\n+    }\n+    long long timeout;\n+    if (getLongLongFromObject(c->argv[3], &timeout) != C_OK ||\n+            !(timeout >= 0 && timeout <= INT_MAX)) {\n+        addReplyErrorFormat(c, \"invalid value of timeout (%s)\",\n+                (char *)c->argv[3]->ptr);\n+        return;\n+    }\n+    if (timeout == 0) {\n+        timeout = 1000 * 30;\n+    }\n+    long long maxbulks;\n+    if (getLongLongFromObject(c->argv[4], &maxbulks) != C_OK ||\n+            !(maxbulks >= 0 && maxbulks <= INT_MAX)) {\n+        addReplyErrorFormat(c, \"invalid value of maxbulks (%s)\",\n+                (char *)c->argv[4]->ptr);\n+        return;\n+    }\n+    if (maxbulks == 0) {\n+        maxbulks = 200;\n+    }\n+    if (maxbulks > 512 * 1024) {\n+        maxbulks = 512 * 1024;\n+    }\n+    long long maxbytes;\n+    if (getLongLongFromObject(c->argv[5], &maxbytes) != C_OK ||\n+            !(maxbytes >= 0 && maxbytes <= INT_MAX)) {\n+        addReplyErrorFormat(c, \"invalid value of maxbytes (%s)\",\n+                (char *)c->argv[5]->ptr);\n+        return;\n+    }\n+    if (maxbytes == 0) {\n+        maxbytes = 512 * 1024;\n+    }\n+    if (maxbytes > INT_MAX / 2) {\n+        maxbytes = INT_MAX / 2;\n+    }\n+    maxbytes = slotsmgrtAsyncMaxBufferLimit(maxbytes);\n+\n+    dict *hash_slot = NULL;\n+    long long numkeys = 0;\n+    if (!usekey) {\n+        long long slotnum;\n+        if (getLongLongFromObject(c->argv[6], &slotnum) != C_OK ||\n+                !(slotnum >= 0 && slotnum < HASH_SLOTS_SIZE)) {\n+            addReplyErrorFormat(c, \"invalid value of slot (%s)\",\n+                    (char *)c->argv[6]->ptr);\n+            return;\n+        }\n+        hash_slot = c->db->hash_slots[slotnum];\n+        if (getLongLongFromObject(c->argv[7], &numkeys) != C_OK ||\n+                !(numkeys >= 0 && numkeys <= INT_MAX)) {\n+            addReplyErrorFormat(c, \"invalid value of numkeys (%s)\",\n+                    (char *)c->argv[7]->ptr);\n+            return;\n+        }\n+        if (numkeys == 0) {\n+            numkeys = 100;\n+        }\n+    }\n+\n+    if (getSlotsmgrtAsyncClientMigrationStatusOrBlock(c, NULL, 0) != 0) {\n+        addReplyError(c, \"the specified DB is being migrated\");\n+        return;\n+    }\n+    if (c->slotsmgrt_flags & CLIENT_SLOTSMGRT_ASYNC_NORMAL_CLIENT) {\n+        addReplyError(c, \"previous operation has not finished\");\n+        return;\n+    }\n+\n+    slotsmgrtAsyncClient *ac = getOrCreateSlotsmgrtAsyncClient(c->db->id, host, port, timeout);\n+    if (ac == NULL) {\n+        addReplyErrorFormat(c, \"create client to %s:%d failed\", host, (int)port);\n+        return;\n+    }\n+\n+    batchedObjectIterator *it = createBatchedObjectIterator(hash_slot,\n+            usetag ? c->db->tagged_keys : NULL, timeout, maxbulks, maxbytes);\n+    if (!usekey) {\n+        void *pd[] = {it, c->db, &numkeys};\n+        for (int i = 2; i >= 0 && it->estimate_msgs < numkeys; i --) {\n+            unsigned long cursor = 0;\n+            if (i != 0) {\n+                cursor = random();\n+            } else {\n+                if (htNeedsResize(hash_slot)) {\n+                    dictResize(hash_slot);\n+                }\n+            }\n+            if (dictIsRehashing(hash_slot)) {\n+                dictRehash(hash_slot, 50);\n+            }\n+            int loop = numkeys * 10;\n+            if (loop < 100) {\n+                loop = 100;\n+            }\n+            do {\n+                cursor = dictScan(hash_slot, cursor, batchedObjectIteratorAddKeyCallback, pd);\n+            } while (cursor != 0 && it->estimate_msgs < numkeys &&\n+                    dictSize(it->keys) < (unsigned long)numkeys && (-- loop) >= 0);\n+        }\n+    } else {\n+        for (int i = 6; i < c->argc; i ++) {\n+            batchedObjectIteratorAddKey(c->db, it, c->argv[i]);\n+        }\n+    }\n+    serverAssert(ac->sending_msgs == 0);\n+    serverAssert(ac->batched_iter == NULL && listLength(ac->blocked_list) == 0);\n+\n+    ac->timeout = timeout;\n+    ac->lastuse = mstime();\n+    ac->batched_iter = it;\n+    ac->sending_msgs = slotsmgrtAsyncNextMessagesMicroseconds(ac, 3, 500);\n+\n+    getSlotsmgrtAsyncClientMigrationStatusOrBlock(c, NULL, 1);\n+\n+    if (ac->sending_msgs != 0) {\n+        return;\n+    }\n+    notifySlotsmgrtAsyncClient(ac, NULL);\n+\n+    ac->batched_iter = NULL;\n+    freeBatchedObjectIterator(it);\n+}\n+\n+/* *\n+ * SLOTSMGRTONE-ASYNC     $host $port $timeout $maxbulks $maxbytes $key1 [$key2 ...]\n+ * */\n+void slotsmgrtOneAsyncCommand(client *c) {\n+    if (c->argc <= 6) {\n+        addReplyError(c, \"wrong number of arguments for SLOTSMGRTONE-ASYNC\");\n+        return;\n+    }\n+    slotsmgrtAsyncGenericCommand(c, 0, 1);\n+}\n+\n+/* *\n+ * SLOTSMGRTTAGONE-ASYNC  $host $port $timeout $maxbulks $maxbytes $key1 [$key2 ...]\n+ * */\n+void slotsmgrtTagOneAsyncCommand(client *c) {\n+    if (c->argc <= 6) {\n+        addReplyError(c, \"wrong number of arguments for SLOTSMGRTTAGONE-ASYNC\");\n+        return;\n+    }\n+    slotsmgrtAsyncGenericCommand(c, 1, 1);\n+}\n+\n+/* *\n+ * SLOTSMGRTSLOT-ASYNC    $host $port $timeout $maxbulks $maxbytes $slot $numkeys\n+ * */\n+void slotsmgrtSlotAsyncCommand(client *c) {\n+    if (c->argc != 8) {\n+        addReplyError(c, \"wrong number of arguments for SLOTSMGRTSLOT-ASYNC\");\n+        return;\n+    }\n+    slotsmgrtAsyncGenericCommand(c, 0, 0);\n+}\n+\n+/* *\n+ * SLOTSMGRTTAGSLOT-ASYNC $host $port $timeout $maxbulks $maxbytes $slot $numkeys\n+ * */\n+void slotsmgrtTagSlotAsyncCommand(client *c) {\n+    if (c->argc != 8) {\n+        addReplyError(c, \"wrong number of arguments for SLOTSMGRTSLOT-ASYNC\");\n+        return;\n+    }\n+    slotsmgrtAsyncGenericCommand(c, 1, 0);\n+}\n+\n+/* *\n+ * SLOTSMGRT-ASYNC-FENCE\n+ * */\n+void\n+slotsmgrtAsyncFenceCommand(client *c) {\n+    int ret = getSlotsmgrtAsyncClientMigrationStatusOrBlock(c, NULL, 1);\n+    if (ret == 0) {\n+        addReply(c, shared.ok);\n+    } else if (ret != 1) {\n+        addReplyError(c, \"previous operation has not finished (call fence again)\");\n+    }\n+}\n+\n+/* *\n+ * SLOTSMGRT-ASYNC-CANCEL\n+ * */\n+void\n+slotsmgrtAsyncCancelCommand(client *c) {\n+    addReplyLongLong(c, releaseSlotsmgrtAsyncClient(c->db->id, \"interrupted: canceled\"));\n+}\n+\n+/* ============================ SlotsmgrtExecWrapper ======================================= */\n+\n+/* *\n+ * SLOTSMGRT-EXEC-WRAPPER $hashkey $command [$arg1 ...]\n+ * */\n+void\n+slotsmgrtExecWrapperCommand(client *c) {\n+    addReplyMultiBulkLen(c, 2);\n+    if (c->argc < 3) {\n+        addReplyLongLong(c, -1);\n+        addReplyError(c, \"wrong number of arguments for SLOTSMGRT-EXEC-WRAPPER\");\n+        return;\n+    }\n+    struct redisCommand *cmd = lookupCommand(c->argv[2]->ptr);\n+    if (cmd == NULL) {\n+        addReplyLongLong(c, -1);\n+        addReplyErrorFormat(c,\"invalid command specified (%s)\",\n+                (char *)c->argv[2]->ptr);\n+        return;\n+    }\n+    if ((cmd->arity > 0 && cmd->arity != c->argc - 2) || (c->argc - 2 < -cmd->arity)) {\n+        addReplyLongLong(c, -1);\n+        addReplyErrorFormat(c, \"wrong number of arguments for command (%s)\",\n+                (char *)c->argv[2]->ptr);\n+        return;\n+    }\n+    if (lookupKeyWrite(c->db, c->argv[1]) == NULL) {\n+        addReplyLongLong(c, 0);\n+        addReplyError(c, \"the specified key doesn't exist\");\n+        return;\n+    }\n+    if (!(cmd->flags & CMD_READONLY) && getSlotsmgrtAsyncClientMigrationStatusOrBlock(c, c->argv[1], 0) != 0) {\n+        addReplyLongLong(c, 1);\n+        addReplyError(c, \"the specified key is being migrated\");\n+        return;\n+    } else {\n+        addReplyLongLong(c, 2);\n+        robj **argv = zmalloc(sizeof(robj *) * (c->argc - 2));\n+        for (int i = 2; i < c->argc; i ++) {\n+            argv[i - 2] = c->argv[i];\n+            incrRefCount(c->argv[i]);\n+        }\n+        for (int i = 0; i < c->argc; i ++) {\n+            decrRefCount(c->argv[i]);\n+        }\n+        zfree(c->argv);\n+        c->argc = c->argc - 2;\n+        c->argv = argv;\n+        c->cmd = cmd;\n+        call(c, CMD_CALL_FULL & ~CMD_CALL_PROPAGATE);\n+    }\n+}\n+\n+/* ============================ SlotsrestoreAsync Commands ================================= */\n+\n+static void\n+slotsrestoreReplyAck(client *c, int errcode, const char *fmt, ...) {\n+    va_list ap;\n+    va_start(ap, fmt);\n+    sds s = sdscatvprintf(sdsempty(), fmt, ap);\n+    va_end(ap);\n+\n+    addReplyMultiBulkLen(c, 3);\n+    addReplyBulkCString(c, \"SLOTSRESTORE-ASYNC-ACK\");\n+    addReplyBulkLongLong(c, errcode);\n+    addReplyBulkSds(c, s);\n+}\n+\n+extern int verifyDumpPayload(unsigned char *p, size_t len);\n+\n+static int\n+slotsrestoreAsyncHandle(client *c) {\n+    if (getSlotsmgrtAsyncClientMigrationStatusOrBlock(c, NULL, 0) != 0) {\n+        slotsrestoreReplyAck(c, -1, \"the specified DB is being migrated\");\n+        return C_ERR;\n+    }\n+\n+    const char *cmd = \"\";\n+    if (c->argc < 2) {\n+        goto bad_arguments_number;\n+    }\n+    cmd = c->argv[1]->ptr;\n+\n+    /* SLOTSRESTORE-ASYNC select $db */\n+    if (!strcasecmp(cmd, \"select\")) {\n+        long long db;\n+        if (c->argc != 3) {\n+            goto bad_arguments_number;\n+        }\n+        if (getLongLongFromObject(c->argv[2], &db) != C_OK ||\n+                !(db >= 0 && db <= INT_MAX) || selectDb(c, db) != C_OK) {\n+            slotsrestoreReplyAck(c, -1, \"invalid DB index (DB=%s)\", c->argv[2]->ptr);\n+            return C_ERR;\n+        }\n+        slotsrestoreReplyAck(c, 0, \"%d\", c->db->id);\n+        return C_OK;\n+    }\n+\n+    /* ==================================================== */\n+    /* SLOTSRESTORE-ASYNC $cmd $key [$ttl $arg1, $arg2 ...] */\n+    /* ==================================================== */\n+\n+    if (c->argc < 3) {\n+        goto bad_arguments_number;\n+    }\n+\n+    robj *key = c->argv[2];\n+\n+    /* SLOTSRESTORE-ASYNC del $key */\n+    if (!strcasecmp(cmd, \"del\")) {\n+        if (c->argc != 3) {\n+            goto bad_arguments_number;\n+        }\n+        int deleted = dbDelete(c->db, key);\n+        if (deleted) {\n+            signalModifiedKey(c->db, key);\n+            server.dirty ++;\n+        }\n+        slotsrestoreReplyAck(c, 0, deleted ? \"1\" : \"0\");\n+        return C_OK;\n+    }\n+\n+    /* ==================================================== */\n+    /* SLOTSRESTORE-ASYNC $cmd $key $ttl [$arg1, $arg2 ...] */\n+    /* ==================================================== */\n+\n+    if (c->argc < 4) {\n+        goto bad_arguments_number;\n+    }\n+\n+    long long ttl;\n+    if (getLongLongFromObject(c->argv[3], &ttl) != C_OK || ttl < 0) {\n+        slotsrestoreReplyAck(c, -1, \"invalid TTL value (TTL=%s)\", c->argv[3]->ptr);\n+        return C_ERR;\n+    }\n+\n+    /* SLOTSRESTORE-ASYNC expire $key $ttl */\n+    if (!strcasecmp(cmd, \"expire\")) {\n+        if (c->argc != 4) {\n+            goto bad_arguments_number;\n+        }\n+        if (lookupKeyWrite(c->db, key) == NULL) {\n+            slotsrestoreReplyAck(c, -1, \"the specified key doesn't exist (%s)\", key->ptr);\n+            return C_ERR;\n+        }\n+        slotsrestoreReplyAck(c, 0, \"1\");\n+        goto success_common;\n+    }\n+\n+    /* SLOTSRESTORE-ASYNC string $key $ttl $payload */\n+    if (!strcasecmp(cmd, \"string\")) {\n+        if (c->argc != 5) {\n+            goto bad_arguments_number;\n+        }\n+        if (lookupKeyWrite(c->db, key) != NULL) {\n+            slotsrestoreReplyAck(c, -1, \"the specified key already exists (%s)\", key->ptr);\n+            return C_ERR;\n+        }\n+        robj *val = c->argv[4] = tryObjectEncoding(c->argv[4]);\n+        dbAdd(c->db, key, val);\n+        incrRefCount(val);\n+        slotsrestoreReplyAck(c, 0, \"1\");\n+        goto success_common;\n+    }\n+\n+    /* SLOTSRESTORE-ASYNC object $key $ttl $payload */\n+    if (!strcasecmp(cmd, \"object\")) {\n+        if (c->argc != 5) {\n+            goto bad_arguments_number;\n+        }\n+        if (lookupKeyWrite(c->db, key) != NULL) {\n+            slotsrestoreReplyAck(c, -1, \"the specified key already exists (%s)\", key->ptr);\n+            return C_ERR;\n+        }\n+        void *bytes = c->argv[4]->ptr;\n+        rio payload;\n+        if (verifyDumpPayload(bytes, sdslen(bytes)) != C_OK) {\n+            slotsrestoreReplyAck(c, -1, \"invalid payload checksum\");\n+            return C_ERR;\n+        }\n+        rioInitWithBuffer(&payload, bytes);\n+        int type = rdbLoadObjectType(&payload);\n+        if (type == -1) {\n+            slotsrestoreReplyAck(c, -1, \"invalid payload type\");\n+            return C_ERR;\n+        }\n+        robj *val = rdbLoadObject(type, &payload);\n+        if (val == NULL) {\n+            slotsrestoreReplyAck(c, -1, \"invalid payload body\");\n+            return C_ERR;\n+        }\n+        dbAdd(c->db, key, val);\n+        slotsrestoreReplyAck(c, 0, \"1\");\n+        goto success_common;\n+    }\n+\n+    /* ========================================================== */\n+    /* SLOTSRESTORE-ASYNC $cmd $key $ttl $hint [$arg1, $arg2 ...] */\n+    /* ========================================================== */\n+\n+    if (c->argc < 5) {\n+        goto bad_arguments_number;\n+    }\n+\n+    long long hint;\n+    if (getLongLongFromObject(c->argv[4], &hint) != C_OK || hint < 0) {\n+        slotsrestoreReplyAck(c, -1, \"invalid Hint value (Hint=%s)\", c->argv[4]->ptr);\n+        return C_ERR;\n+    }\n+\n+    int xargc = c->argc - 5;\n+    robj **xargv = &c->argv[5];\n+\n+    /* SLOTSRESTORE-ASYNC list $key $ttl $hint [$elem1 ...] */\n+    if (!strcasecmp(cmd, \"list\")) {\n+        robj *val = lookupKeyWrite(c->db, key);\n+        if (val != NULL) {\n+            if (val->type != OBJ_LIST || val->encoding != OBJ_ENCODING_QUICKLIST) {\n+                slotsrestoreReplyAck(c, -1, \"wrong type (expect=%d/%d,got=%d/%d)\",\n+                        OBJ_LIST, OBJ_ENCODING_QUICKLIST, val->type, val->encoding);\n+                return C_ERR;\n+            }\n+        } else {\n+            if (xargc == 0) {\n+                slotsrestoreReplyAck(c, -1, \"the specified key doesn't exist (%s)\", key->ptr);\n+                return C_ERR;\n+            }\n+            val = createQuicklistObject();\n+            quicklistSetOptions(val->ptr, server.list_max_ziplist_size,\n+                    server.list_compress_depth);\n+            dbAdd(c->db, key, val);\n+        }\n+        for (int i = 0; i < xargc; i ++) {\n+            xargv[i] = tryObjectEncoding(xargv[i]);\n+            listTypePush(val, xargv[i], LIST_TAIL);\n+        }\n+        slotsrestoreReplyAck(c, 0, \"%d\", listTypeLength(val));\n+        goto success_common;\n+    }\n+\n+    /* SLOTSRESTORE-ASYNC hash $key $ttl $hint [$hkey1 $hval1 ...] */\n+    if (!strcasecmp(cmd, \"hash\")) {\n+        if (xargc % 2 != 0) {\n+            goto bad_arguments_number;\n+        }\n+        robj *val = lookupKeyWrite(c->db, key);\n+        if (val != NULL) {\n+            if (val->type != OBJ_HASH || val->encoding != OBJ_ENCODING_HT) {\n+                slotsrestoreReplyAck(c, -1, \"wrong type (expect=%d/%d,got=%d/%d)\",\n+                        OBJ_HASH, OBJ_ENCODING_HT, val->type, val->encoding);\n+                return C_ERR;\n+            }\n+        } else {\n+            if (xargc == 0) {\n+                slotsrestoreReplyAck(c, -1, \"the specified key doesn't exist (%s)\", key->ptr);\n+                return C_ERR;\n+            }\n+            val = createHashObject();\n+            if (val->encoding !=  OBJ_ENCODING_HT) {\n+                hashTypeConvert(val, OBJ_ENCODING_HT);\n+            }\n+            dbAdd(c->db, key, val);\n+        }\n+        if (hint != 0) {\n+            dict *ht = val->ptr;\n+            dictExpand(ht, hint);\n+        }\n+        for (int i = 0; i < xargc; i += 2) {\n+            hashTypeTryObjectEncoding(val, &xargv[i], &xargv[i + 1]);\n+            hashTypeSet(val, xargv[i], xargv[i + 1]);\n+        }\n+        slotsrestoreReplyAck(c, 0, \"%d\", hashTypeLength(val));\n+        goto success_common;\n+    }\n+\n+    /* SLOTSRESTORE-ASYNC dict $key $ttl $hint [$elem1 ...] */\n+    if (!strcasecmp(cmd, \"dict\")) {\n+        robj *val = lookupKeyWrite(c->db, key);\n+        if (val != NULL) {\n+            if (val->type != OBJ_SET || val->encoding != OBJ_ENCODING_HT) {\n+                slotsrestoreReplyAck(c, -1, \"wrong type (expect=%d/%d,got=%d/%d)\",\n+                        OBJ_SET, OBJ_ENCODING_HT, val->type, val->encoding);\n+                return C_ERR;\n+            }\n+        } else {\n+            if (xargc == 0) {\n+                slotsrestoreReplyAck(c, -1, \"the specified key doesn't exist (%s)\", key->ptr);\n+                return C_ERR;\n+            }\n+            val = createSetObject();\n+            if (val->encoding != OBJ_ENCODING_HT) {\n+                setTypeConvert(val, OBJ_ENCODING_HT);\n+            }\n+            dbAdd(c->db, key, val);\n+        }\n+        if (hint != 0) {\n+            dict *ht = val->ptr;\n+            dictExpand(ht, hint);\n+        }\n+        for (int i = 0; i < xargc; i ++) {\n+            xargv[i] = tryObjectEncoding(xargv[i]);\n+            setTypeAdd(val, xargv[i]);\n+        }\n+        slotsrestoreReplyAck(c, 0, \"%d\", setTypeSize(val));\n+        goto success_common;\n+    }\n+\n+    /* SLOTSRESTORE-ASYNC zset $key $ttl $hint [$elem1 $score1 ...] */\n+    if (!strcasecmp(cmd, \"zset\")) {\n+        if (xargc % 2 != 0) {\n+            goto bad_arguments_number;\n+        }\n+        double *scores = zmalloc(sizeof(double) * xargc / 2);\n+        for (int i = 1, j = 0; i < xargc; i += 2, j ++) {\n+            uint64_t bits;\n+            if (getUint64FromRawStringObject(xargv[i], &bits) != C_OK) {\n+                zfree(scores);\n+                slotsrestoreReplyAck(c, -1, \"invalid zset score ([%d]), bad raw bits\", j);\n+                return C_ERR;\n+            }\n+            scores[j] = convertRawBitsToDouble(bits);\n+        }\n+        robj *val = lookupKeyWrite(c->db, key);\n+        if (val != NULL) {\n+            if (val->type != OBJ_ZSET || val->encoding != OBJ_ENCODING_SKIPLIST) {\n+                zfree(scores);\n+                slotsrestoreReplyAck(c, -1, \"wrong type (expect=%d/%d,got=%d/%d)\",\n+                        OBJ_ZSET, OBJ_ENCODING_SKIPLIST, val->type, val->encoding);\n+                return C_ERR;\n+            }\n+        } else {\n+            if (xargc == 0) {\n+                zfree(scores);\n+                slotsrestoreReplyAck(c, -1, \"the specified key doesn't exist (%s)\", key->ptr);\n+                return C_ERR;\n+            }\n+            val = createZsetObject();\n+            if (val->encoding != OBJ_ENCODING_SKIPLIST) {\n+                zsetConvert(val, OBJ_ENCODING_SKIPLIST);\n+            }\n+            dbAdd(c->db, key, val);\n+        }\n+        zset *zset = val->ptr;\n+        if (hint != 0) {\n+            dict *ht = zset->dict;\n+            dictExpand(ht, hint);\n+        }\n+        for (int i = 0, j = 0; i < xargc; i += 2, j ++) {\n+            robj *elem = xargv[i] = tryObjectEncoding(xargv[i]);\n+            dictEntry *de = dictFind(zset->dict, elem);\n+            if (de != NULL) {\n+                double score = *(double *)dictGetVal(de);\n+                zslDelete(zset->zsl, score, elem);\n+                dictDelete(zset->dict, elem);\n+            }\n+            zskiplistNode *znode = zslInsert(zset->zsl, scores[j], elem);\n+            incrRefCount(elem);\n+            dictAdd(zset->dict, elem, &(znode->score));\n+            incrRefCount(elem);\n+        }\n+        zfree(scores);\n+        slotsrestoreReplyAck(c, 0, \"%d\", zsetLength(val));\n+        goto success_common;\n+    }\n+\n+    slotsrestoreReplyAck(c, -1, \"unknown command (argc=%d,cmd=%s)\", c->argc, cmd);\n+    return C_ERR;\n+\n+bad_arguments_number:\n+    slotsrestoreReplyAck(c, -1, \"wrong number of arguments (argc=%d,cmd=%s)\", c->argc, cmd);\n+    return C_ERR;\n+\n+success_common:\n+    if (ttl != 0) {\n+        setExpire(c->db, key, mstime() + ttl);\n+    } else {\n+        removeExpire(c->db, key);\n+    }\n+    signalModifiedKey(c->db, key);\n+    server.dirty ++;\n+    return C_OK;\n+}\n+\n+\n+/* *\n+ * SLOTSRESTORE-ASYNC select $db\n+ *                    del    $key\n+ *                    expire $key $ttl\n+ *                    object $key $ttl $payload\n+ *                    string $key $ttl $payload\n+ *                    list   $key $ttl $hint [$elem1 ...]\n+ *                    hash   $key $ttl $hint [$hkey1 $hval1 ...]\n+ *                    dict   $key $ttl $hint [$elem1 ...]\n+ *                    zset   $key $ttl $hint [$elem1 $score1 ...]\n+ * */\n+void\n+slotsrestoreAsyncCommand(client *c) {\n+    if (slotsrestoreAsyncHandle(c) != C_OK) {\n+        c->flags |= CLIENT_CLOSE_AFTER_REPLY;\n+    }\n+}\n+\n+static int\n+slotsrestoreAsyncAckHandle(client *c) {\n+    slotsmgrtAsyncClient *ac = getSlotsmgrtAsyncClient(c->db->id);\n+    if (ac->c != c) {\n+        addReplyErrorFormat(c, \"invalid client, permission denied\");\n+        return C_ERR;\n+    }\n+    if (c->argc != 3) {\n+        addReplyError(c, \"wrong number of arguments for SLOTSRESTORE-ASYNC-ACK\");\n+        return C_ERR;\n+    }\n+    long long errcode;\n+    if (getLongLongFromObject(c->argv[1], &errcode) != C_OK) {\n+        addReplyErrorFormat(c, \"invalid errcode (%s)\",\n+                (char *)c->argv[1]->ptr);\n+        return C_ERR;\n+    }\n+    const char *errmsg = c->argv[2]->ptr;\n+    if (errcode != 0) {\n+        serverLog(LL_WARNING, \"slotsmgrt_async: ack[%d] %s\",\n+                (int)errcode, errmsg != NULL ? errmsg : \"(null)\");\n+        return C_ERR;\n+    }\n+    if (ac->batched_iter == NULL) {\n+        serverLog(LL_WARNING, \"slotsmgrt_async: null batched iterator\");\n+        addReplyError(c, \"invalid iterator (NULL)\");\n+        return C_ERR;\n+    }\n+    if (ac->sending_msgs == 0) {\n+        serverLog(LL_WARNING, \"slotsmgrt_async: invalid message counter\");\n+        addReplyError(c, \"invalid pending messages\");\n+        return C_ERR;\n+    }\n+\n+    ac->lastuse = mstime();\n+    ac->sending_msgs -= 1;\n+    ac->sending_msgs += slotsmgrtAsyncNextMessagesMicroseconds(ac, 2, 10);\n+\n+    if (ac->sending_msgs != 0) {\n+        return C_OK;\n+    }\n+    notifySlotsmgrtAsyncClient(ac, NULL);\n+\n+    batchedObjectIterator *it = ac->batched_iter;\n+    if (listLength(it->removed_keys) != 0) {\n+        list *ll = it->removed_keys;\n+        for (int i = 0; i < c->argc; i ++) {\n+            decrRefCount(c->argv[i]);\n+        }\n+        zfree(c->argv);\n+        c->argc = 1 + listLength(ll);\n+        c->argv = zmalloc(sizeof(robj *) * c->argc);\n+        for (int i = 1; i < c->argc; i ++) {\n+            listNode *head = listFirst(ll);\n+            robj *key = listNodeValue(head);\n+            if (dbDelete(c->db, key)) {\n+                signalModifiedKey(c->db, key);\n+                server.dirty ++;\n+            }\n+            c->argv[i] = key;\n+            incrRefCount(key);\n+            listDelNode(ll, head);\n+        }\n+        c->argv[0] = createStringObject(\"DEL\", 3);\n+    }\n+\n+    if (listLength(it->chunked_vals) != 0) {\n+        list *ll = it->chunked_vals;\n+        while (listLength(ll) != 0) {\n+            listNode *head = listFirst(ll);\n+            robj *val = listNodeValue(head);\n+            listAddNodeTail(server.slotsmgrt_lazy_release, createLazyReleaseIterator(val));\n+            listDelNode(ll, head);\n+        }\n+    }\n+\n+    ac->batched_iter = NULL;\n+    freeBatchedObjectIterator(it);\n+    return C_OK;\n+}\n+\n+/* *\n+ * SLOTSRESTORE-ASYNC-ACK $errno $message\n+ * */\n+void\n+slotsrestoreAsyncAckCommand(client *c) {\n+    if (slotsrestoreAsyncAckHandle(c) != C_OK) {\n+        c->flags |= CLIENT_CLOSE_AFTER_REPLY;\n+    }\n+}\n+\n+extern int time_independent_strcmp(const char *a, const char *b);\n+\n+/* *\n+ * SLOTSRESTORE-ASYNC-AUTH $passwd\n+ * */\n+void\n+slotsrestoreAsyncAuthCommand(client *c) {\n+    if (!server.requirepass) {\n+        slotsrestoreReplyAck(c, -1, \"Client sent AUTH, but no password is set\");\n+        return;\n+    }\n+    if (!time_independent_strcmp(c->argv[1]->ptr, server.requirepass)) {\n+        c->authenticated = 1;\n+        slotsrestoreReplyAck(c, 0, \"OK\");\n+    } else {\n+        c->authenticated = 0;\n+        slotsrestoreReplyAck(c, -1, \"invalid password\");\n+    }\n+}\n+\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.8/patch/codis/0004-slots_async2.patch",
    "content": "diff --git a/extern/redis-3.2.8/src/help.h b/extern/redis-3.2.8/src/help.h\nindex 3d57430..bf27662 100644\n--- a/extern/redis-3.2.8/src/help.h\n+++ b/extern/redis-3.2.8/src/help.h\n@@ -1085,6 +1085,10 @@ struct commandHelp {\n         \"-\",\n         \"\", 14, \"codis3.2\"\n     },\n+    {\"SLOTSMGRT-ASYNC-STATUS\",\n+        \"-\",\n+        \"\", 14, \"codis3.2\"\n+    },\n     {\"SLOTSMGRT-EXEC-WRAPPER\",\n         \"hashkey command [arg ...]\",\n         \"\", 14, \"codis3.2\"\ndiff --git a/extern/redis-3.2.8/src/server.c b/extern/redis-3.2.8/src/server.c\nindex 8946e65..7a24804 100644\n--- a/extern/redis-3.2.8/src/server.c\n+++ b/extern/redis-3.2.8/src/server.c\n@@ -315,6 +315,7 @@ struct redisCommand redisCommandTable[] = {\n     {\"slotsmgrttagone-async-dump\",slotsmgrtTagOneAsyncDumpCommand,-4,\"rm\",0,NULL,0,0,0,0,0},\n     {\"slotsmgrt-async-fence\",slotsmgrtAsyncFenceCommand,0,\"r\",0,NULL,0,0,0,0,0},\n     {\"slotsmgrt-async-cancel\",slotsmgrtAsyncCancelCommand,0,\"F\",0,NULL,0,0,0,0,0},\n+    {\"slotsmgrt-async-status\",slotsmgrtAsyncStatusCommand,0,\"F\",0,NULL,0,0,0,0,0},\n     {\"slotsmgrt-exec-wrapper\",slotsmgrtExecWrapperCommand,-3,\"wm\",0,NULL,0,0,0,0,0},\n     {\"slotsmgrt-lazy-release\",slotsmgrtLazyReleaseCommand,-1,\"r\",0,NULL,0,0,0,0,0},\n     {\"slotsrestore-async\",slotsrestoreAsyncCommand,-2,\"w\",0,NULL,0,0,0,0,0},\ndiff --git a/extern/redis-3.2.8/src/server.h b/extern/redis-3.2.8/src/server.h\nindex d34ee4f..234f569 100644\n--- a/extern/redis-3.2.8/src/server.h\n+++ b/extern/redis-3.2.8/src/server.h\n@@ -1700,6 +1700,7 @@ void slotsmgrtTagOneAsyncCommand(client *c);\n void slotsmgrtTagOneAsyncDumpCommand(client *c);\n void slotsmgrtAsyncFenceCommand(client *c);\n void slotsmgrtAsyncCancelCommand(client *c);\n+void slotsmgrtAsyncStatusCommand(client *c);\n void slotsmgrtExecWrapperCommand(client *c);\n void slotsmgrtLazyReleaseCommand(client *c);\n void slotsrestoreAsyncCommand(client *c);\ndiff --git a/extern/redis-3.2.8/src/slots_async.c b/extern/redis-3.2.8/src/slots_async.c\nindex 73b3205..852d96b 100644\n--- a/extern/redis-3.2.8/src/slots_async.c\n+++ b/extern/redis-3.2.8/src/slots_async.c\n@@ -241,7 +241,7 @@ typedef struct {\n     unsigned long cursor;\n     unsigned long lindex;\n     unsigned long zindex;\n-    int chunked;\n+    unsigned long chunked_msgs;\n } singleObjectIterator;\n \n static singleObjectIterator *\n@@ -255,7 +255,7 @@ createSingleObjectIterator(robj *key) {\n     it->cursor = 0;\n     it->lindex = 0;\n     it->zindex = 0;\n-    it->chunked = 0;\n+    it->chunked_msgs = 0;\n     return it;\n }\n \n@@ -414,18 +414,18 @@ singleObjectIteratorNext(client *c, singleObjectIterator *it,\n         incrRefCount(it->val);\n         it->expire = getExpire(c->db, key);\n \n-        int extra_msgs = 0;\n+        int leading_msgs = 0;\n \n-        slotsmgrtAsyncClient *client = getSlotsmgrtAsyncClient(c->db->id);\n-        if (client->c == c) {\n-            if (client->used == 0) {\n-                client->used = 1;\n+        slotsmgrtAsyncClient *ac = getSlotsmgrtAsyncClient(c->db->id);\n+        if (ac->c == c) {\n+            if (ac->used == 0) {\n+                ac->used = 1;\n                 if (server.requirepass != NULL) {\n                     /* SLOTSRESTORE-ASYNC-AUTH $password */\n                     addReplyMultiBulkLen(c, 2);\n                     addReplyBulkCString(c, \"SLOTSRESTORE-ASYNC-AUTH\");\n                     addReplyBulkCString(c, server.requirepass);\n-                    extra_msgs += 1;\n+                    leading_msgs += 1;\n                 }\n                 do {\n                     /* SLOTSRESTORE-ASYNC select $db */\n@@ -433,7 +433,7 @@ singleObjectIteratorNext(client *c, singleObjectIterator *it,\n                     addReplyBulkCString(c, \"SLOTSRESTORE-ASYNC\");\n                     addReplyBulkCString(c, \"select\");\n                     addReplyBulkLongLong(c, c->db->id);\n-                    extra_msgs += 1;\n+                    leading_msgs += 1;\n                 } while (0);\n             }\n         }\n@@ -444,13 +444,15 @@ singleObjectIteratorNext(client *c, singleObjectIterator *it,\n         addReplyBulkCString(c, \"del\");\n         addReplyBulk(c, key);\n \n-        if (numberOfRestoreCommandsFromObject(val, maxbulks) != 1) {\n+        long n = numberOfRestoreCommandsFromObject(val, maxbulks);\n+        if (n >= 2) {\n             it->stage = STAGE_CHUNKED;\n-            it->chunked = 1;\n+            it->chunked_msgs = n;\n         } else {\n             it->stage = STAGE_PAYLOAD;\n+            it->chunked_msgs = 0;\n         }\n-        return 1 + extra_msgs;\n+        return 1 + leading_msgs;\n     }\n \n     robj *val = it->val;\n@@ -680,7 +682,7 @@ batchedObjectIteratorHasNext(batchedObjectIterator *it) {\n         if (sp->val != NULL) {\n             incrRefCount(sp->key);\n             listAddNodeTail(it->removed_keys, sp->key);\n-            if (sp->chunked) {\n+            if (sp->chunked_msgs != 0) {\n                 incrRefCount(sp->val);\n                 listAddNodeTail(it->chunked_vals, sp->val);\n             }\n@@ -1286,6 +1288,137 @@ slotsmgrtAsyncCancelCommand(client *c) {\n     addReplyLongLong(c, releaseSlotsmgrtAsyncClient(c->db->id, \"interrupted: canceled\"));\n }\n \n+/* ============================ SlotsmgrtAsyncStatus ======================================= */\n+\n+static void\n+singleObjectIteratorStatus(client *c, singleObjectIterator *it) {\n+    if (it == NULL) {\n+        addReply(c, shared.nullmultibulk);\n+        return;\n+    }\n+    void *ptr = addDeferredMultiBulkLength(c);\n+    int fields = 0;\n+\n+    fields ++; addReplyBulkCString(c, \"key\");\n+    addReplyBulk(c, it->key);\n+\n+    fields ++; addReplyBulkCString(c, \"val.type\");\n+    addReplyBulkLongLong(c, it->val == NULL ? -1 : it->val->type);\n+\n+    fields ++; addReplyBulkCString(c, \"stage\");\n+    addReplyBulkLongLong(c, it->stage);\n+\n+    fields ++; addReplyBulkCString(c, \"expire\");\n+    addReplyBulkLongLong(c, it->expire);\n+\n+    fields ++; addReplyBulkCString(c, \"cursor\");\n+    addReplyBulkLongLong(c, it->cursor);\n+\n+    fields ++; addReplyBulkCString(c, \"lindex\");\n+    addReplyBulkLongLong(c, it->lindex);\n+\n+    fields ++; addReplyBulkCString(c, \"zindex\");\n+    addReplyBulkLongLong(c, it->zindex);\n+\n+    fields ++; addReplyBulkCString(c, \"chunked_msgs\");\n+    addReplyBulkLongLong(c, it->chunked_msgs);\n+\n+    setDeferredMultiBulkLength(c, ptr, fields * 2);\n+}\n+\n+static void\n+batchedObjectIteratorStatus(client *c, batchedObjectIterator *it) {\n+    if (it == NULL) {\n+        addReply(c, shared.nullmultibulk);\n+        return;\n+    }\n+    void *ptr = addDeferredMultiBulkLength(c);\n+    int fields = 0;\n+\n+    fields ++; addReplyBulkCString(c, \"keys\");\n+    addReplyMultiBulkLen(c, 2);\n+    addReplyBulkLongLong(c, dictSize(it->keys));\n+    addReplyMultiBulkLen(c, dictSize(it->keys));\n+    dictIterator *di = dictGetIterator(it->keys);\n+    dictEntry *de;\n+    while((de = dictNext(di)) != NULL) {\n+        addReplyBulk(c, dictGetKey(de));\n+    }\n+    dictReleaseIterator(di);\n+\n+    fields ++; addReplyBulkCString(c, \"timeout\");\n+    addReplyBulkLongLong(c, it->timeout);\n+\n+    fields ++; addReplyBulkCString(c, \"maxbulks\");\n+    addReplyBulkLongLong(c, it->maxbulks);\n+\n+    fields ++; addReplyBulkCString(c, \"maxbytes\");\n+    addReplyBulkLongLong(c, it->maxbytes);\n+\n+    fields ++; addReplyBulkCString(c, \"estimate_msgs\");\n+    addReplyBulkLongLong(c, it->estimate_msgs);\n+\n+    fields ++; addReplyBulkCString(c, \"removed_keys\");\n+    addReplyBulkLongLong(c, listLength(it->removed_keys));\n+\n+    fields ++; addReplyBulkCString(c, \"chunked_vals\");\n+    addReplyBulkLongLong(c, listLength(it->chunked_vals));\n+\n+    fields ++; addReplyBulkCString(c, \"iterators\");\n+    addReplyMultiBulkLen(c, 2);\n+    addReplyBulkLongLong(c, listLength(it->list));\n+    singleObjectIterator *sp = NULL;\n+    if (listLength(it->list) != 0) {\n+        sp = listNodeValue(listFirst(it->list));\n+    }\n+    singleObjectIteratorStatus(c, sp);\n+\n+    setDeferredMultiBulkLength(c, ptr, fields * 2);\n+}\n+\n+/* *\n+ * SLOTSMGRT-ASYNC-STATUS\n+ * */\n+void\n+slotsmgrtAsyncStatusCommand(client *c) {\n+    slotsmgrtAsyncClient *ac = getSlotsmgrtAsyncClient(c->db->id);\n+    if (ac->c == NULL) {\n+        addReply(c, shared.nullmultibulk);\n+        return;\n+    }\n+    void *ptr = addDeferredMultiBulkLength(c);\n+    int fields = 0;\n+\n+    fields ++; addReplyBulkCString(c, \"host\");\n+    addReplyBulkCString(c, ac->host);\n+\n+    fields ++; addReplyBulkCString(c, \"port\");\n+    addReplyBulkLongLong(c, ac->port);\n+\n+    fields ++; addReplyBulkCString(c, \"used\");\n+    addReplyBulkLongLong(c, ac->used);\n+\n+    fields ++; addReplyBulkCString(c, \"timeout\");\n+    addReplyBulkLongLong(c, ac->timeout);\n+\n+    fields ++; addReplyBulkCString(c, \"lastuse\");\n+    addReplyBulkLongLong(c, ac->lastuse);\n+\n+    fields ++; addReplyBulkCString(c, \"since_lastuse\");\n+    addReplyBulkLongLong(c, mstime() - ac->lastuse);\n+\n+    fields ++; addReplyBulkCString(c, \"blocked_clients\");\n+    addReplyBulkLongLong(c, listLength(ac->blocked_list));\n+\n+    fields ++; addReplyBulkCString(c, \"sending_messages\");\n+    addReplyBulkLongLong(c, ac->sending_msgs);\n+\n+    fields ++; addReplyBulkCString(c, \"batched_iterator\");\n+    batchedObjectIteratorStatus(c, ac->batched_iter);\n+\n+    setDeferredMultiBulkLength(c, ptr, fields * 2);\n+}\n+\n /* ============================ SlotsmgrtExecWrapper ======================================= */\n \n /* *\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.8/patch/codis/0005-slots_async3_lazyfree.patch",
    "content": "diff --git a/extern/redis-3.2.8/src/object.c b/extern/redis-3.2.8/src/object.c\nindex db5ec3a..d1093cb 100644\n--- a/extern/redis-3.2.8/src/object.c\n+++ b/extern/redis-3.2.8/src/object.c\n@@ -48,6 +48,23 @@ robj *createObject(int type, void *ptr) {\n     return o;\n }\n \n+/* Set a special refcount in the object to make it \"shared\":\n+ * incrRefCount and decrRefCount() will test for this special refcount\n+ * and will not touch the object. This way it is free to access shared\n+ * objects such as small integers from different threads without any\n+ * mutex.\n+ *\n+ * A common patter to create shared objects:\n+ *\n+ * robj *myobject = makeObjectShared(createObject(...));\n+ *\n+ */\n+robj *makeObjectShared(robj *o) {\n+    serverAssert(o->refcount == 1);\n+    o->refcount = OBJ_SHARED_REFCOUNT;\n+    return o;\n+}\n+\n /* Create a string object with encoding OBJ_ENCODING_RAW, that is a plain\n  * string object where o->ptr points to a proper sds string. */\n robj *createRawStringObject(const char *ptr, size_t len) {\n@@ -293,11 +310,10 @@ void freeHashObject(robj *o) {\n }\n \n void incrRefCount(robj *o) {\n-    o->refcount++;\n+    if (o->refcount != OBJ_SHARED_REFCOUNT) o->refcount++;\n }\n \n void decrRefCount(robj *o) {\n-    if (o->refcount <= 0) serverPanic(\"decrRefCount against refcount <= 0\");\n     if (o->refcount == 1) {\n         switch(o->type) {\n         case OBJ_STRING: freeStringObject(o); break;\n@@ -309,7 +325,8 @@ void decrRefCount(robj *o) {\n         }\n         zfree(o);\n     } else {\n-        o->refcount--;\n+        if (o->refcount <= 0) serverPanic(\"decrRefCount against refcount <= 0\");\n+        if (o->refcount != OBJ_SHARED_REFCOUNT) o->refcount--;\n     }\n }\n \ndiff --git a/extern/redis-3.2.8/src/server.c b/extern/redis-3.2.8/src/server.c\nindex 7a24804..60b2b22 100644\n--- a/extern/redis-3.2.8/src/server.c\n+++ b/extern/redis-3.2.8/src/server.c\n@@ -317,7 +317,6 @@ struct redisCommand redisCommandTable[] = {\n     {\"slotsmgrt-async-cancel\",slotsmgrtAsyncCancelCommand,0,\"F\",0,NULL,0,0,0,0,0},\n     {\"slotsmgrt-async-status\",slotsmgrtAsyncStatusCommand,0,\"F\",0,NULL,0,0,0,0,0},\n     {\"slotsmgrt-exec-wrapper\",slotsmgrtExecWrapperCommand,-3,\"wm\",0,NULL,0,0,0,0,0},\n-    {\"slotsmgrt-lazy-release\",slotsmgrtLazyReleaseCommand,-1,\"r\",0,NULL,0,0,0,0,0},\n     {\"slotsrestore-async\",slotsrestoreAsyncCommand,-2,\"w\",0,NULL,0,0,0,0,0},\n     {\"slotsrestore-async-auth\",slotsrestoreAsyncAuthCommand,2,\"F\",0,NULL,0,0,0,0,0},\n     {\"slotsrestore-async-ack\",slotsrestoreAsyncAckCommand,3,\"w\",0,NULL,0,0,0,0,0},\n@@ -1344,10 +1343,6 @@ int serverCron(struct aeEventLoop *eventLoop, long long id, void *clientData) {\n         slotsmgrtAsyncCleanup();\n     }\n \n-    run_with_period(100) {\n-        slotsmgrtLazyReleaseCleanup();\n-    }\n-\n     /* Cleanup expired MIGRATE cached sockets. */\n     run_with_period(1000) {\n         migrateCloseTimedoutSockets();\n@@ -1496,7 +1491,8 @@ void createSharedObjects(void) {\n     shared.lpop = createStringObject(\"LPOP\",4);\n     shared.lpush = createStringObject(\"LPUSH\",5);\n     for (j = 0; j < OBJ_SHARED_INTEGERS; j++) {\n-        shared.integers[j] = createObject(OBJ_STRING,(void*)(long)j);\n+        shared.integers[j] =\n+            makeObjectShared(createObject(OBJ_STRING,(void*)(long)j));\n         shared.integers[j]->encoding = OBJ_ENCODING_INT;\n     }\n     for (j = 0; j < OBJ_SHARED_BULKHDR_LEN; j++) {\n@@ -1964,7 +1960,7 @@ void initServer(void) {\n         slotsmgrtAsyncClient *ac = &server.slotsmgrt_cached_clients[j];\n         memset(ac, 0, sizeof(*ac));\n     }\n-    server.slotsmgrt_lazy_release = listCreate();\n+    slotsmgrtInitLazyReleaseWorkerThread();\n \n     /* Open the TCP listening socket for the user commands. */\n     if (server.port != 0 &&\n@@ -2602,10 +2598,6 @@ int processCommand(client *c) {\n         return C_OK;\n     }\n \n-    if (c->cmd->proc != slotsrestoreAsyncAckCommand) {\n-        slotsmgrtLazyReleaseIncrementally();\n-    }\n-\n     /* Exec the command */\n     if (c->flags & CLIENT_MULTI &&\n         c->cmd->proc != execCommand && c->cmd->proc != discardCommand &&\ndiff --git a/extern/redis-3.2.8/src/server.h b/extern/redis-3.2.8/src/server.h\nindex 234f569..f7a4d50 100644\n--- a/extern/redis-3.2.8/src/server.h\n+++ b/extern/redis-3.2.8/src/server.h\n@@ -773,7 +773,7 @@ struct redisServer {\n     mstime_t clients_pause_end_time; /* Time when we undo clients_paused */\n     char neterr[ANET_ERR_LEN];   /* Error buffer for anet.c */\n     dict *slotsmgrt_cached_sockfds;\n-    list *slotsmgrt_lazy_release;\n+    void *slotsmgrt_lazy_release;\n     slotsmgrtAsyncClient *slotsmgrt_cached_clients;\n     dict *migrate_cached_sockets;/* MIGRATE cached sockets */\n     uint64_t next_client_id;    /* Next client unique ID. Incremental. */\n@@ -1215,10 +1215,13 @@ void discardTransaction(client *c);\n void flagTransaction(client *c);\n void execCommandPropagateMulti(client *c);\n \n+#define OBJ_SHARED_REFCOUNT INT_MAX\n+\n /* Redis object implementation */\n void decrRefCount(robj *o);\n void decrRefCountVoid(void *o);\n void incrRefCount(robj *o);\n+robj *makeObjectShared(robj *o);\n robj *resetRefCount(robj *obj);\n void freeStringObject(robj *o);\n void freeListObject(robj *o);\n@@ -1702,15 +1705,13 @@ void slotsmgrtAsyncFenceCommand(client *c);\n void slotsmgrtAsyncCancelCommand(client *c);\n void slotsmgrtAsyncStatusCommand(client *c);\n void slotsmgrtExecWrapperCommand(client *c);\n-void slotsmgrtLazyReleaseCommand(client *c);\n void slotsrestoreAsyncCommand(client *c);\n void slotsrestoreAsyncAuthCommand(client *c);\n void slotsrestoreAsyncAckCommand(client *c);\n \n void slotsmgrtAsyncCleanup();\n void slotsmgrtAsyncUnlinkClient(client *c);\n-void slotsmgrtLazyReleaseCleanup();\n-void slotsmgrtLazyReleaseIncrementally();\n+void slotsmgrtInitLazyReleaseWorkerThread();\n \n void slotsmgrt_cleanup();\n int slots_num(const sds s, uint32_t *pcrc, int *phastag);\ndiff --git a/extern/redis-3.2.8/src/slots_async.c b/extern/redis-3.2.8/src/slots_async.c\nindex 852d96b..1708048 100644\n--- a/extern/redis-3.2.8/src/slots_async.c\n+++ b/extern/redis-3.2.8/src/slots_async.c\n@@ -1,228 +1,60 @@\n #include \"server.h\"\n \n-/* ============================ Iterator for Lazy Release ================================== */\n+/* ============================ Worker Thread for Lazy Release ============================= */\n \n typedef struct {\n-    robj *val;\n-    unsigned long cursor;\n-} lazyReleaseIterator;\n-\n-static lazyReleaseIterator *\n-createLazyReleaseIterator(robj *val) {\n-    lazyReleaseIterator *it = zmalloc(sizeof(lazyReleaseIterator));\n-    it->val = val;\n-    incrRefCount(it->val);\n-    it->cursor = 0;\n-    return it;\n-}\n-\n-static void\n-freeLazyReleaseIterator(lazyReleaseIterator *it) {\n-    if (it->val != NULL) {\n-        decrRefCount(it->val);\n-    }\n-    zfree(it);\n-}\n-\n-static int\n-lazyReleaseIteratorHasNext(lazyReleaseIterator *it) {\n-    return it->val != NULL;\n+    pthread_t thread;\n+    pthread_mutex_t mutex;\n+    pthread_cond_t cond;\n+    list *objs;\n+} lazyReleaseWorker;\n+\n+static void *\n+lazyReleaseWorkerMain(void *args) {\n+    lazyReleaseWorker *p = args;\n+    while (1) {\n+        pthread_mutex_lock(&p->mutex);\n+        while (listLength(p->objs) == 0) {\n+            pthread_cond_wait(&p->cond, &p->mutex);\n+        }\n+        listNode *head = listFirst(p->objs);\n+        robj *o = listNodeValue(head);\n+        listDelNode(p->objs, head);\n+        pthread_mutex_unlock(&p->mutex);\n+\n+        decrRefCount(o);\n+    }\n+    return NULL;\n }\n \n static void\n-lazyReleaseIteratorScanCallback(void *data, const dictEntry *de) {\n-    void **pd = (void **)data;\n-    list *l = pd[0];\n-\n-    robj *field = dictGetKey(de);\n-    incrRefCount(field);\n-    listAddNodeTail(l, field);\n-}\n-\n-static void\n-lazyReleaseIteratorNext(lazyReleaseIterator *it, int step) {\n-    robj *val = it->val;\n-    serverAssert(val != NULL);\n-\n-    unsigned int limit = step * 2;\n-    if (limit < 100) {\n-        limit = 100;\n-    }\n-\n-    if (val->type == OBJ_LIST) {\n-        if (listTypeLength(val) <= limit) {\n-            decrRefCount(val);\n-            it->val = NULL;\n-        } else {\n-            for (int i = 0; i < step; i ++) {\n-                robj *value = listTypePop(val, LIST_HEAD);\n-                decrRefCount(value);\n-            }\n-        }\n-        return;\n-    }\n-\n-    if (val->type == OBJ_HASH || val->type == OBJ_SET) {\n-        dict *ht = val->ptr;\n-        if (dictSize(ht) <= limit) {\n-            decrRefCount(val);\n-            it->val = NULL;\n-        } else {\n-            list *ll = listCreate();\n-            listSetFreeMethod(ll, decrRefCountVoid);\n-            int loop = step;\n-            void *pd[] = {ll};\n-            do {\n-                it->cursor = dictScan(ht, it->cursor, lazyReleaseIteratorScanCallback, pd);\n-            } while (it->cursor != 0 && listLength(ll) < (unsigned long)step && (-- loop) >= 0);\n-\n-            while (listLength(ll) != 0) {\n-                listNode *head = listFirst(ll);\n-                robj *field = listNodeValue(head);\n-                dictDelete(ht, field);\n-                listDelNode(ll, head);\n-            }\n-            listRelease(ll);\n-        }\n-        return;\n-    }\n-\n-    if (val->type == OBJ_ZSET) {\n-        zset *zs = val->ptr;\n-        dict *ht = zs->dict;\n-        if (dictSize(ht) <= limit) {\n-            decrRefCount(val);\n-            it->val = NULL;\n-        } else {\n-            zskiplist *zsl = zs->zsl;\n-            for (int i = 0; i < step; i ++) {\n-                zskiplistNode *node = zsl->header->level[0].forward;\n-                robj *field = node->obj;\n-                incrRefCount(field);\n-                zslDelete(zsl, node->score, field);\n-                dictDelete(ht, field);\n-                decrRefCount(field);\n-            }\n-        }\n-        return;\n-    }\n-\n-    serverPanic(\"unknown object type\");\n+lazyReleaseObject(robj *o) {\n+    serverAssert(o->refcount == 1);\n+    lazyReleaseWorker *p = server.slotsmgrt_lazy_release;\n+    pthread_mutex_lock(&p->mutex);\n+    if (listLength(p->objs) == 0) {\n+        pthread_cond_broadcast(&p->cond);\n+    }\n+    listAddNodeTail(p->objs, o);\n+    pthread_mutex_unlock(&p->mutex);\n }\n \n-static int\n-lazyReleaseIteratorRemains(lazyReleaseIterator *it) {\n-    robj *val = it->val;\n-    if (val == NULL) {\n-        return 0;\n-    }\n-    if (val->type == OBJ_LIST) {\n-        return listTypeLength(val);\n-    }\n-    if (val->type == OBJ_HASH) {\n-        return hashTypeLength(val);\n-    }\n-    if (val->type == OBJ_SET) {\n-        return setTypeSize(val);\n-    }\n-    if (val->type == OBJ_ZSET) {\n-        return zsetLength(val);\n-    }\n-    return -1;\n+static lazyReleaseWorker *\n+createLazyReleaseWorkerThread() {\n+    lazyReleaseWorker *p = zmalloc(sizeof(lazyReleaseWorker));\n+    pthread_mutex_init(&p->mutex, NULL);\n+    pthread_cond_init(&p->cond, NULL);\n+    p->objs = listCreate();\n+    if (pthread_create(&p->thread, NULL, lazyReleaseWorkerMain, p) != 0) {\n+        serverLog(LL_WARNING,\"Fatal: Can't initialize Worker Thread for Lazy Release Jobs.\");\n+        exit(1);\n+    }\n+    return p;\n }\n \n-static int\n-slotsmgrtLazyReleaseStep(int step) {\n-    list *ll = server.slotsmgrt_lazy_release;\n-    if (listLength(ll) != 0) {\n-        listNode *head = listFirst(ll);\n-        lazyReleaseIterator *it = listNodeValue(head);\n-        if (lazyReleaseIteratorHasNext(it)) {\n-            lazyReleaseIteratorNext(it, step);\n-        } else {\n-            freeLazyReleaseIterator(it);\n-            listDelNode(ll, head);\n-        }\n-        return 1;\n-    }\n-    return 0;\n-}\n-\n-static void\n-slotsmgrtLazyReleaseMicroseconds(long long usecs) {\n-    long long deadline = ustime() + usecs;\n-    while (slotsmgrtLazyReleaseStep(50)) {\n-        if (ustime() >= deadline) {\n-            return;\n-        }\n-    }\n-}\n-\n-static struct {\n-    long long last_numcommands;\n-    int step;\n-} lazy_release_options = {\n-    .last_numcommands = 0,\n-    .step = 1,\n-};\n-\n void\n-slotsmgrtLazyReleaseCleanup() {\n-    long long ops = server.stat_numcommands - lazy_release_options.last_numcommands;\n-    if (ops < 0) {\n-        ops = 0;\n-    }\n-    if (ops > 30) {\n-        lazy_release_options.step = 1 + (1000 / ops) * 3;\n-    } else {\n-        lazy_release_options.step = 100;\n-    }\n-    lazy_release_options.last_numcommands = server.stat_numcommands;\n-\n-    long long usecs = lazy_release_options.step / 10 * 100;\n-    if (usecs != 0) {\n-        slotsmgrtLazyReleaseMicroseconds(usecs);\n-    }\n-}\n-\n-void\n-slotsmgrtLazyReleaseIncrementally() {\n-    slotsmgrtLazyReleaseStep(lazy_release_options.step);\n-}\n-\n-/* *\n- * SLOTSMGRT-LAZY-RELEASE $microseconds\n- * */\n-void\n-slotsmgrtLazyReleaseCommand(client *c) {\n-    if (c->argc != 1 && c->argc != 2) {\n-        addReplyError(c, \"wrong number of arguments for SLOTSMGRT-LAZY-RELEASE\");\n-        return;\n-    }\n-    long long usecs = 1;\n-    if (c->argc != 1) {\n-        if (getLongLongFromObject(c->argv[1], &usecs) != C_OK ||\n-                !(usecs >= 0 && usecs <= INT_MAX)) {\n-            addReplyErrorFormat(c, \"invalid value of usecs (%s)\",\n-                    (char *)c->argv[1]->ptr);\n-            return;\n-        }\n-    }\n-    if (usecs != 0) {\n-        slotsmgrtLazyReleaseMicroseconds(usecs);\n-    }\n-\n-    list *ll = server.slotsmgrt_lazy_release;\n-\n-    addReplyMultiBulkLen(c, 2);\n-    addReplyLongLong(c, listLength(ll));\n-\n-    if (listLength(ll) != 0) {\n-        lazyReleaseIterator *it = listNodeValue(listFirst(ll));\n-        addReplyLongLong(c, lazyReleaseIteratorRemains(it));\n-    } else {\n-        addReplyLongLong(c, 0);\n-    }\n+slotsmgrtInitLazyReleaseWorkerThread() {\n+    server.slotsmgrt_lazy_release = createLazyReleaseWorkerThread();\n }\n \n /* ============================ Iterator for Data Migration ================================ */\n@@ -1407,12 +1239,12 @@ slotsmgrtAsyncStatusCommand(client *c) {\n     fields ++; addReplyBulkCString(c, \"since_lastuse\");\n     addReplyBulkLongLong(c, mstime() - ac->lastuse);\n \n+    fields ++; addReplyBulkCString(c, \"sending_msgs\");\n+    addReplyBulkLongLong(c, ac->sending_msgs);\n+\n     fields ++; addReplyBulkCString(c, \"blocked_clients\");\n     addReplyBulkLongLong(c, listLength(ac->blocked_list));\n \n-    fields ++; addReplyBulkCString(c, \"sending_messages\");\n-    addReplyBulkLongLong(c, ac->sending_msgs);\n-\n     fields ++; addReplyBulkCString(c, \"batched_iterator\");\n     batchedObjectIteratorStatus(c, ac->batched_iter);\n \n@@ -1891,9 +1723,14 @@ slotsrestoreAsyncAckHandle(client *c) {\n         list *ll = it->chunked_vals;\n         while (listLength(ll) != 0) {\n             listNode *head = listFirst(ll);\n-            robj *val = listNodeValue(head);\n-            listAddNodeTail(server.slotsmgrt_lazy_release, createLazyReleaseIterator(val));\n+            robj *o = listNodeValue(head);\n+            incrRefCount(o);\n             listDelNode(ll, head);\n+            if (o->refcount != 1) {\n+                decrRefCount(o);\n+            } else {\n+                lazyReleaseObject(o);\n+            }\n         }\n     }\n \n"
  },
  {
    "path": "extern/deprecated/redis-3.2.8/patch/codis/0006-slots_async4_bugfix_1184.patch",
    "content": "diff --git a/extern/redis-3.2.8/src/slots_async.c b/extern/redis-3.2.8/src/slots_async.c\nindex 1708048..c506942 100644\n--- a/extern/redis-3.2.8/src/slots_async.c\n+++ b/extern/redis-3.2.8/src/slots_async.c\n@@ -604,25 +604,6 @@ out:\n     return 1 + dictSize(it->keys) - size;\n }\n \n-static void\n-batchedObjectIteratorAddKeyCallback(void *data, const dictEntry *de) {\n-    void **pd = (void **)data;\n-    batchedObjectIterator *it = pd[0];\n-    redisDb *db = pd[1];\n-    long long numkeys = *(long long *)pd[2];\n-\n-    if (it->estimate_msgs >= numkeys) {\n-        return;\n-    }\n-    sds skey = dictGetKey(de);\n-    robj *key = createStringObject(skey, sdslen(skey));\n-    long msgs = estimateNumberOfRestoreCommands(db, key, it->maxbulks);\n-    if (it->estimate_msgs == 0 || it->estimate_msgs + msgs <= numkeys * 2) {\n-        batchedObjectIteratorAddKey(db, it, key);\n-    }\n-    decrRefCount(key);\n-}\n-\n /* ============================ Clients ==================================================== */\n \n static slotsmgrtAsyncClient *\n@@ -917,6 +898,13 @@ slotsmgrtAsyncNextMessagesMicroseconds(slotsmgrtAsyncClient *ac, long atleast, l\n     return msgs;\n }\n \n+static void\n+slotsScanSdsKeyCallback(void *l, const dictEntry *de) {\n+    sds skey = dictGetKey(de);\n+    robj *key = createStringObject(skey, sdslen(skey));\n+    listAddNodeTail((list *)l, key);\n+}\n+\n /* SLOTSMGRTONE-ASYNC     $host $port $timeout $maxbulks $maxbytes $key1 [$key2 ...] */\n /* SLOTSMGRTTAGONE-ASYNC  $host $port $timeout $maxbulks $maxbytes $key1 [$key2 ...] */\n /* SLOTSMGRTSLOT-ASYNC    $host $port $timeout $maxbulks $maxbytes $slot $numkeys    */\n@@ -1009,7 +997,8 @@ slotsmgrtAsyncGenericCommand(client *c, int usetag, int usekey) {\n     batchedObjectIterator *it = createBatchedObjectIterator(hash_slot,\n             usetag ? c->db->tagged_keys : NULL, timeout, maxbulks, maxbytes);\n     if (!usekey) {\n-        void *pd[] = {it, c->db, &numkeys};\n+        list *ll = listCreate();\n+        listSetFreeMethod(ll, decrRefCountVoid);\n         for (int i = 2; i >= 0 && it->estimate_msgs < numkeys; i --) {\n             unsigned long cursor = 0;\n             if (i != 0) {\n@@ -1027,10 +1016,20 @@ slotsmgrtAsyncGenericCommand(client *c, int usetag, int usekey) {\n                 loop = 100;\n             }\n             do {\n-                cursor = dictScan(hash_slot, cursor, batchedObjectIteratorAddKeyCallback, pd);\n+                cursor = dictScan(hash_slot, cursor, slotsScanSdsKeyCallback, ll);\n+                while (listLength(ll) != 0 && it->estimate_msgs < numkeys) {\n+                    listNode *head = listFirst(ll);\n+                    robj *key = listNodeValue(head);\n+                    long msgs = estimateNumberOfRestoreCommands(c->db, key, it->maxbulks);\n+                    if (it->estimate_msgs == 0 || it->estimate_msgs + msgs <= numkeys * 2) {\n+                        batchedObjectIteratorAddKey(c->db, it, key);\n+                    }\n+                    listDelNode(ll, head);\n+                }\n             } while (cursor != 0 && it->estimate_msgs < numkeys &&\n                     dictSize(it->keys) < (unsigned long)numkeys && (-- loop) >= 0);\n         }\n+        listRelease(ll);\n     } else {\n         for (int i = 6; i < c->argc; i ++) {\n             batchedObjectIteratorAddKey(c->db, it, c->argv[i]);\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.8/patch/codis/0007-slots_async5_cleanup.patch",
    "content": "diff --git a/extern/redis-3.2.8/src/help.h b/extern/redis-3.2.8/src/help.h\nindex bf27662..f4ffcb9 100644\n--- a/extern/redis-3.2.8/src/help.h\n+++ b/extern/redis-3.2.8/src/help.h\n@@ -1093,10 +1093,6 @@ struct commandHelp {\n         \"hashkey command [arg ...]\",\n         \"\", 14, \"codis3.2\"\n     },\n-    {\"SLOTSMGRT-LAZY-RELEASE\",\n-        \"[microseconds]\",\n-        \"\", 14, \"codis3.2\"\n-    },\n     {\"SLOTSRESTORE-ASYNC SELECT\",\n         \"db\",\n         \"\", 14, \"codis3.2\"\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.8/patch/codis/0008-slots_async6_select.patch",
    "content": "From 88b32ba356cb52971fd0da00b7d610266913d71f Mon Sep 17 00:00:00 2001\nFrom: spinlock <wnzheng@gmail.com>\nDate: Wed, 10 May 2017 13:29:12 +0800\nSubject: [PATCH] extern: new command SLOTSRESTORE-ASYNC-SELECT\n\n---\n extern/redis-3.2.8/src/help.h        |  4 +--\n extern/redis-3.2.8/src/server.c      | 15 +++++-----\n extern/redis-3.2.8/src/server.h      |  1 +\n extern/redis-3.2.8/src/slots_async.c | 54 ++++++++++++++++++------------------\n 4 files changed, 38 insertions(+), 36 deletions(-)\n\ndiff --git a/extern/redis-3.2.8/src/help.h b/extern/redis-3.2.8/src/help.h\nindex f4ffcb9..32810e1 100644\n--- a/extern/redis-3.2.8/src/help.h\n+++ b/extern/redis-3.2.8/src/help.h\n@@ -1093,11 +1093,11 @@ struct commandHelp {\n         \"hashkey command [arg ...]\",\n         \"\", 14, \"codis3.2\"\n     },\n-    {\"SLOTSRESTORE-ASYNC SELECT\",\n+    {\"SLOTSRESTORE-ASYNC-SELECT\",\n         \"db\",\n         \"\", 14, \"codis3.2\"\n     },\n-    {\"SLOTSRESTORE-ASYNC DEL\",\n+    {\"SLOTSRESTORE-ASYNC DELETE\",\n         \"key\",\n         \"\", 14, \"codis3.2\"\n     },\ndiff --git a/extern/redis-3.2.8/src/server.c b/extern/redis-3.2.8/src/server.c\nindex 4e2abbe..9b7e6a4 100644\n--- a/extern/redis-3.2.8/src/server.c\n+++ b/extern/redis-3.2.8/src/server.c\n@@ -307,18 +307,19 @@ struct redisCommand redisCommandTable[] = {\n     {\"slotshashkey\",slotshashkeyCommand,-1,\"rF\",0,NULL,0,0,0,0,0},\n     {\"slotscheck\",slotscheckCommand,0,\"r\",0,NULL,0,0,0,0,0},\n     {\"slotsrestore\",slotsrestoreCommand,-4,\"wm\",0,NULL,0,0,0,0,0},\n-    {\"slotsmgrtslot-async\",slotsmgrtSlotAsyncCommand,8,\"w\",0,NULL,0,0,0,0,0},\n-    {\"slotsmgrttagslot-async\",slotsmgrtTagSlotAsyncCommand,8,\"w\",0,NULL,0,0,0,0,0},\n-    {\"slotsmgrtone-async\",slotsmgrtOneAsyncCommand,-7,\"w\",0,NULL,0,0,0,0,0},\n-    {\"slotsmgrttagone-async\",slotsmgrtTagOneAsyncCommand,-7,\"w\",0,NULL,0,0,0,0,0},\n+    {\"slotsmgrtslot-async\",slotsmgrtSlotAsyncCommand,8,\"ws\",0,NULL,0,0,0,0,0},\n+    {\"slotsmgrttagslot-async\",slotsmgrtTagSlotAsyncCommand,8,\"ws\",0,NULL,0,0,0,0,0},\n+    {\"slotsmgrtone-async\",slotsmgrtOneAsyncCommand,-7,\"ws\",0,NULL,0,0,0,0,0},\n+    {\"slotsmgrttagone-async\",slotsmgrtTagOneAsyncCommand,-7,\"ws\",0,NULL,0,0,0,0,0},\n     {\"slotsmgrtone-async-dump\",slotsmgrtOneAsyncDumpCommand,-4,\"rm\",0,NULL,0,0,0,0,0},\n     {\"slotsmgrttagone-async-dump\",slotsmgrtTagOneAsyncDumpCommand,-4,\"rm\",0,NULL,0,0,0,0,0},\n-    {\"slotsmgrt-async-fence\",slotsmgrtAsyncFenceCommand,0,\"r\",0,NULL,0,0,0,0,0},\n+    {\"slotsmgrt-async-fence\",slotsmgrtAsyncFenceCommand,0,\"rs\",0,NULL,0,0,0,0,0},\n     {\"slotsmgrt-async-cancel\",slotsmgrtAsyncCancelCommand,0,\"F\",0,NULL,0,0,0,0,0},\n     {\"slotsmgrt-async-status\",slotsmgrtAsyncStatusCommand,0,\"F\",0,NULL,0,0,0,0,0},\n     {\"slotsmgrt-exec-wrapper\",slotsmgrtExecWrapperCommand,-3,\"wm\",0,NULL,0,0,0,0,0},\n-    {\"slotsrestore-async\",slotsrestoreAsyncCommand,-2,\"w\",0,NULL,0,0,0,0,0},\n-    {\"slotsrestore-async-auth\",slotsrestoreAsyncAuthCommand,2,\"F\",0,NULL,0,0,0,0,0},\n+    {\"slotsrestore-async\",slotsrestoreAsyncCommand,-2,\"wm\",0,NULL,0,0,0,0,0},\n+    {\"slotsrestore-async-auth\",slotsrestoreAsyncAuthCommand,2,\"sltF\",0,NULL,0,0,0,0,0},\n+    {\"slotsrestore-async-select\",slotsrestoreAsyncSelectCommand,2,\"lF\",0,NULL,0,0,0,0,0},\n     {\"slotsrestore-async-ack\",slotsrestoreAsyncAckCommand,3,\"w\",0,NULL,0,0,0,0,0},\n };\n \ndiff --git a/extern/redis-3.2.8/src/server.h b/extern/redis-3.2.8/src/server.h\nindex f7a4d50..291aec0 100644\n--- a/extern/redis-3.2.8/src/server.h\n+++ b/extern/redis-3.2.8/src/server.h\n@@ -1707,6 +1707,7 @@ void slotsmgrtAsyncStatusCommand(client *c);\n void slotsmgrtExecWrapperCommand(client *c);\n void slotsrestoreAsyncCommand(client *c);\n void slotsrestoreAsyncAuthCommand(client *c);\n+void slotsrestoreAsyncSelectCommand(client *c);\n void slotsrestoreAsyncAckCommand(client *c);\n \n void slotsmgrtAsyncCleanup();\ndiff --git a/extern/redis-3.2.8/src/slots_async.c b/extern/redis-3.2.8/src/slots_async.c\nindex c506942..71558aa 100644\n--- a/extern/redis-3.2.8/src/slots_async.c\n+++ b/extern/redis-3.2.8/src/slots_async.c\n@@ -260,20 +260,19 @@ singleObjectIteratorNext(client *c, singleObjectIterator *it,\n                     leading_msgs += 1;\n                 }\n                 do {\n-                    /* SLOTSRESTORE-ASYNC select $db */\n-                    addReplyMultiBulkLen(c, 3);\n-                    addReplyBulkCString(c, \"SLOTSRESTORE-ASYNC\");\n-                    addReplyBulkCString(c, \"select\");\n+                    /* SLOTSRESTORE-ASYNC-SELECT $db */\n+                    addReplyMultiBulkLen(c, 2);\n+                    addReplyBulkCString(c, \"SLOTSRESTORE-ASYNC-SELECT\");\n                     addReplyBulkLongLong(c, c->db->id);\n                     leading_msgs += 1;\n                 } while (0);\n             }\n         }\n \n-        /* SLOTSRESTORE-ASYNC del $key */\n+        /* SLOTSRESTORE-ASYNC delete $key */\n         addReplyMultiBulkLen(c, 3);\n         addReplyBulkCString(c, \"SLOTSRESTORE-ASYNC\");\n-        addReplyBulkCString(c, \"del\");\n+        addReplyBulkCString(c, \"delete\");\n         addReplyBulk(c, key);\n \n         long n = numberOfRestoreCommandsFromObject(val, maxbulks);\n@@ -1306,7 +1305,7 @@ slotsmgrtExecWrapperCommand(client *c) {\n /* ============================ SlotsrestoreAsync Commands ================================= */\n \n static void\n-slotsrestoreReplyAck(client *c, int errcode, const char *fmt, ...) {\n+slotsrestoreReplyAck(client *c, int err_code, const char *fmt, ...) {\n     va_list ap;\n     va_start(ap, fmt);\n     sds s = sdscatvprintf(sdsempty(), fmt, ap);\n@@ -1314,8 +1313,12 @@ slotsrestoreReplyAck(client *c, int errcode, const char *fmt, ...) {\n \n     addReplyMultiBulkLen(c, 3);\n     addReplyBulkCString(c, \"SLOTSRESTORE-ASYNC-ACK\");\n-    addReplyBulkLongLong(c, errcode);\n+    addReplyBulkLongLong(c, err_code);\n     addReplyBulkSds(c, s);\n+\n+    if (err_code != 0) {\n+        c->flags |= CLIENT_CLOSE_AFTER_REPLY;\n+    }\n }\n \n extern int verifyDumpPayload(unsigned char *p, size_t len);\n@@ -1333,21 +1336,6 @@ slotsrestoreAsyncHandle(client *c) {\n     }\n     cmd = c->argv[1]->ptr;\n \n-    /* SLOTSRESTORE-ASYNC select $db */\n-    if (!strcasecmp(cmd, \"select\")) {\n-        long long db;\n-        if (c->argc != 3) {\n-            goto bad_arguments_number;\n-        }\n-        if (getLongLongFromObject(c->argv[2], &db) != C_OK ||\n-                !(db >= 0 && db <= INT_MAX) || selectDb(c, db) != C_OK) {\n-            slotsrestoreReplyAck(c, -1, \"invalid DB index (DB=%s)\", c->argv[2]->ptr);\n-            return C_ERR;\n-        }\n-        slotsrestoreReplyAck(c, 0, \"%d\", c->db->id);\n-        return C_OK;\n-    }\n-\n     /* ==================================================== */\n     /* SLOTSRESTORE-ASYNC $cmd $key [$ttl $arg1, $arg2 ...] */\n     /* ==================================================== */\n@@ -1358,8 +1346,8 @@ slotsrestoreAsyncHandle(client *c) {\n \n     robj *key = c->argv[2];\n \n-    /* SLOTSRESTORE-ASYNC del $key */\n-    if (!strcasecmp(cmd, \"del\")) {\n+    /* SLOTSRESTORE-ASYNC delete $key */\n+    if (!strcasecmp(cmd, \"delete\")) {\n         if (c->argc != 3) {\n             goto bad_arguments_number;\n         }\n@@ -1635,8 +1623,7 @@ success_common:\n \n \n /* *\n- * SLOTSRESTORE-ASYNC select $db\n- *                    del    $key\n+ * SLOTSRESTORE-ASYNC delete $key\n  *                    expire $key $ttl\n  *                    object $key $ttl $payload\n  *                    string $key $ttl $payload\n@@ -1768,3 +1755,16 @@ slotsrestoreAsyncAuthCommand(client *c) {\n     }\n }\n \n+/* *\n+ * SLOTSRESTORE-ASYNC-SELECT $db\n+ * */\n+void\n+slotsrestoreAsyncSelectCommand(client *c) {\n+    long long db;\n+    if (getLongLongFromObject(c->argv[1], &db) != C_OK ||\n+            !(db >= 0 && db <= INT_MAX) || selectDb(c, db) != C_OK) {\n+        slotsrestoreReplyAck(c, -1, \"invalid DB index (%s)\", c->argv[1]->ptr);\n+    } else {\n+        slotsrestoreReplyAck(c, 0, \"OK\");\n+    }\n+}\n-- \n2.12.2\n\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.8/patch/redis/0001-Don-t-leak-file-descriptor-on-syncWithMaster.patch",
    "content": "From 10dbb5cd33cdc78edc70c1827e5c7c7f46eb9538 Mon Sep 17 00:00:00 2001\nFrom: antirez <antirez@gmail.com>\nDate: Mon, 20 Feb 2017 10:18:41 +0100\nSubject: [PATCH 01/19] Don't leak file descriptor on syncWithMaster().\n\nClose #3804.\n---\n src/replication.c | 3 ++-\n 1 file changed, 2 insertions(+), 1 deletion(-)\n\ndiff --git a/src/replication.c b/src/replication.c\nindex e7194e59..8d9bcfbf 100644\n--- a/src/replication.c\n+++ b/src/replication.c\n@@ -1385,7 +1385,7 @@ int slaveTryPartialResynchronization(int fd, int read_reply) {\n \n void syncWithMaster(aeEventLoop *el, int fd, void *privdata, int mask) {\n     char tmpfile[256], *err = NULL;\n-    int dfd, maxtries = 5;\n+    int dfd = -1, maxtries = 5;\n     int sockerr = 0, psync_result;\n     socklen_t errlen = sizeof(sockerr);\n     UNUSED(el);\n@@ -1640,6 +1640,7 @@ void syncWithMaster(aeEventLoop *el, int fd, void *privdata, int mask) {\n \n error:\n     aeDeleteFileEvent(server.el,fd,AE_READABLE|AE_WRITABLE);\n+    if (dfd != -1) close(dfd);\n     close(fd);\n     server.repl_transfer_s = -1;\n     server.repl_state = REPL_STATE_CONNECT;\n-- \n2.13.1\n\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.8/patch/redis/0002-fix-2883-2857-pipe-fds-leak-when-fork-failed-on-bg-a.patch",
    "content": "From b83f9fea81411c4809218bd7c51f974e4c4ad7a8 Mon Sep 17 00:00:00 2001\nFrom: \"John.Koepi\" <john.koepi@gmail.com>\nDate: Sat, 23 Jul 2016 16:31:56 +0200\nSubject: [PATCH 02/19] fix #2883, #2857 pipe fds leak when fork() failed on bg\n aof rw\n\n---\n src/aof.c | 1 +\n 1 file changed, 1 insertion(+)\n\ndiff --git a/src/aof.c b/src/aof.c\nindex c6fbbb82..862b5e13 100644\n--- a/src/aof.c\n+++ b/src/aof.c\n@@ -1295,6 +1295,7 @@ int rewriteAppendOnlyFileBackground(void) {\n             serverLog(LL_WARNING,\n                 \"Can't rewrite append only file in background: fork: %s\",\n                 strerror(errno));\n+            aofClosePipes();\n             return C_ERR;\n         }\n         serverLog(LL_NOTICE,\n-- \n2.13.1\n\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.8/patch/redis/0003-Implement-getKeys-procedure-for-georadius-and-georad.patch",
    "content": "From bacb04f89fe22b98881f86523ce8f7b8b6542084 Mon Sep 17 00:00:00 2001\nFrom: Qu Chen <quchen@amazon.com>\nDate: Fri, 7 Apr 2017 22:31:11 +0000\nSubject: [PATCH 03/19] Implement getKeys procedure for georadius and\n georadiusbymember commands.\n\n---\n src/db.c     | 38 ++++++++++++++++++++++++++++++++++++++\n src/server.c |  4 ++--\n src/server.h |  1 +\n 3 files changed, 41 insertions(+), 2 deletions(-)\n\ndiff --git a/src/db.c b/src/db.c\nindex fba731c9..75905e2d 100644\n--- a/src/db.c\n+++ b/src/db.c\n@@ -1234,6 +1234,44 @@ int *migrateGetKeys(struct redisCommand *cmd, robj **argv, int argc, int *numkey\n     return keys;\n }\n \n+/* Helper function to extract keys from following commands:\n+ * GEORADIUS key x y radius unit [WITHDIST] [WITHHASH] [WITHCOORD] [ASC|DESC]\n+ *                             [COUNT count] [STORE key] [STOREDIST key]\n+ * GEORADIUSBYMEMBER key member radius unit ... options ... */\n+int *georadiusGetKeys(struct redisCommand *cmd, robj **argv, int argc, int *numkeys) {\n+    int i, num, *keys;\n+    UNUSED(cmd);\n+\n+    /* Check for the presence of the stored key in the command */\n+    int stored_key = -1;\n+    for (i = 5; i < argc; i++) {\n+        char *arg = argv[i]->ptr;\n+        /* For the case when user specifies both \"store\" and \"storedist\" options, the\n+         * second key specified would override the first key. This behavior is kept \n+         * the same as in georadiusCommand method.\n+         */\n+        if ((!strcasecmp(arg, \"store\") || !strcasecmp(arg, \"storedist\")) && ((i+1) < argc)) {\n+            stored_key = i+1;\n+            i++;\n+        }\n+    }\n+    num = 1 + (stored_key == -1 ? 0 : 1);\n+\n+    /* Keys in the command come from two places:\n+     * argv[1] = key,\n+     * argv[5...n] = stored key if present\n+     */\n+    keys = zmalloc(sizeof(int) * num);\n+\n+    /* Add all key positions to keys[] */\n+    keys[0] = 1;\n+    if(num > 1) {\n+         keys[1] = stored_key;\n+    }\n+    *numkeys = num; \n+    return keys;\n+}\n+\n /* Slot to Key API. This is used by Redis Cluster in order to obtain in\n  * a fast way a key that belongs to a specified hash slot. This is useful\n  * while rehashing the cluster. */\ndiff --git a/src/server.c b/src/server.c\nindex 71bcda7d..cc23c817 100644\n--- a/src/server.c\n+++ b/src/server.c\n@@ -284,8 +284,8 @@ struct redisCommand redisCommandTable[] = {\n     {\"wait\",waitCommand,3,\"s\",0,NULL,0,0,0,0,0},\n     {\"command\",commandCommand,0,\"lt\",0,NULL,0,0,0,0,0},\n     {\"geoadd\",geoaddCommand,-5,\"wm\",0,NULL,1,1,1,0,0},\n-    {\"georadius\",georadiusCommand,-6,\"w\",0,NULL,1,1,1,0,0},\n-    {\"georadiusbymember\",georadiusByMemberCommand,-5,\"w\",0,NULL,1,1,1,0,0},\n+    {\"georadius\",georadiusCommand,-6,\"w\",0,georadiusGetKeys,1,1,1,0,0},\n+    {\"georadiusbymember\",georadiusByMemberCommand,-5,\"w\",0,georadiusGetKeys,1,1,1,0,0},\n     {\"geohash\",geohashCommand,-2,\"r\",0,NULL,1,1,1,0,0},\n     {\"geopos\",geoposCommand,-2,\"r\",0,NULL,1,1,1,0,0},\n     {\"geodist\",geodistCommand,-4,\"r\",0,NULL,1,1,1,0,0},\ndiff --git a/src/server.h b/src/server.h\nindex 3fa7c3ac..4ca73a25 100644\n--- a/src/server.h\n+++ b/src/server.h\n@@ -1435,6 +1435,7 @@ int *zunionInterGetKeys(struct redisCommand *cmd,robj **argv, int argc, int *num\n int *evalGetKeys(struct redisCommand *cmd, robj **argv, int argc, int *numkeys);\n int *sortGetKeys(struct redisCommand *cmd, robj **argv, int argc, int *numkeys);\n int *migrateGetKeys(struct redisCommand *cmd, robj **argv, int argc, int *numkeys);\n+int *georadiusGetKeys(struct redisCommand *cmd, robj **argv, int argc, int *numkeys);\n \n /* Cluster */\n void clusterInit(void);\n-- \n2.13.1\n\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.8/patch/redis/0004-Test-fix-hopefully-false-PSYNC-failure-like-in-issue.patch",
    "content": "From 6a33952b8af18c4c0e778d93a69d97bc2adbc52e Mon Sep 17 00:00:00 2001\nFrom: antirez <antirez@gmail.com>\nDate: Fri, 14 Apr 2017 17:53:11 +0200\nSubject: [PATCH 04/19] Test: fix, hopefully, false PSYNC failure like in issue\n #2715.\n\nAnd many other related Github issues... all reporting the same problem.\nThere was probably just not enough backlog in certain unlucky runs.\nI'll ask people that can reporduce if they see now this as fixed as\nwell.\n---\n tests/integration/replication-psync.tcl | 2 +-\n 1 file changed, 1 insertion(+), 1 deletion(-)\n\ndiff --git a/tests/integration/replication-psync.tcl b/tests/integration/replication-psync.tcl\nindex 3a41ceb2..308d63d0 100644\n--- a/tests/integration/replication-psync.tcl\n+++ b/tests/integration/replication-psync.tcl\n@@ -110,7 +110,7 @@ foreach diskless {no yes} {\n     test_psync {no reconnection, just sync} 6 1000000 3600 0 {\n     } $diskless 0\n \n-    test_psync {ok psync} 6 1000000 3600 0 {\n+    test_psync {ok psync} 6 100000000 3600 0 {\n         assert {[s -1 sync_partial_ok] > 0}\n     } $diskless 1\n \n-- \n2.13.1\n\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.8/patch/redis/0005-update-block-free-after-some-diff-data-are-written-t.patch",
    "content": "From d3b499245015b198fb3bd2814453b5852cad3d3f Mon Sep 17 00:00:00 2001\nFrom: =?UTF-8?q?=E5=BC=A0=E6=96=87=E5=BA=B7?=\n <zhangwenkang@zhangwenkangdeMacBook-Pro.local>\nDate: Tue, 18 Apr 2017 20:10:08 +0800\nSubject: [PATCH 05/19] update block->free after some diff data are written to\n the child process\n\n---\n src/aof.c | 1 +\n 1 file changed, 1 insertion(+)\n\ndiff --git a/src/aof.c b/src/aof.c\nindex 862b5e13..cbd906c9 100644\n--- a/src/aof.c\n+++ b/src/aof.c\n@@ -115,6 +115,7 @@ void aofChildWriteDiffData(aeEventLoop *el, int fd, void *privdata, int mask) {\n             if (nwritten <= 0) return;\n             memmove(block->buf,block->buf+nwritten,block->used-nwritten);\n             block->used -= nwritten;\n+            block->free += nwritten;\n         }\n         if (block->used == 0) listDelNode(server.aof_rewrite_buf_blocks,ln);\n     }\n-- \n2.13.1\n\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.8/patch/redis/0006-Fix-3848-by-closing-the-descriptor-on-error.patch",
    "content": "From c9c04b11b971bb0598307cf2aafe8954e7785641 Mon Sep 17 00:00:00 2001\nFrom: antirez <antirez@gmail.com>\nDate: Tue, 18 Apr 2017 16:24:06 +0200\nSubject: [PATCH 06/19] Fix #3848 by closing the descriptor on error.\n\n---\n src/anet.c | 3 ++-\n 1 file changed, 2 insertions(+), 1 deletion(-)\n\ndiff --git a/src/anet.c b/src/anet.c\nindex ef1711d0..e16ce131 100644\n--- a/src/anet.c\n+++ b/src/anet.c\n@@ -462,7 +462,7 @@ static int anetV6Only(char *err, int s) {\n \n static int _anetTcpServer(char *err, int port, char *bindaddr, int af, int backlog)\n {\n-    int s, rv;\n+    int s = -1, rv;\n     char _port[6];  /* strlen(\"65535\") */\n     struct addrinfo hints, *servinfo, *p;\n \n@@ -491,6 +491,7 @@ static int _anetTcpServer(char *err, int port, char *bindaddr, int af, int backl\n     }\n \n error:\n+    if (s != -1) close(s);\n     s = ANET_ERR;\n end:\n     freeaddrinfo(servinfo);\n-- \n2.13.1\n\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.8/patch/redis/0007-Set-lua-time-limit-default-value-at-safe-place.patch",
    "content": "From 697d3abeff1563936da2653a8fa8db78d5dff671 Mon Sep 17 00:00:00 2001\nFrom: antirez <antirez@gmail.com>\nDate: Tue, 11 Apr 2017 16:56:00 +0200\nSubject: [PATCH 07/19] Set lua-time-limit default value at safe place.\n\nOtherwise, as it was, it will overwrite whatever the user set.\n\nClose #3703.\n---\n src/scripting.c | 1 -\n src/server.c    | 1 +\n 2 files changed, 1 insertion(+), 1 deletion(-)\n\ndiff --git a/src/scripting.c b/src/scripting.c\nindex 0a2ce1f3..216dfbf1 100644\n--- a/src/scripting.c\n+++ b/src/scripting.c\n@@ -900,7 +900,6 @@ void scriptingInit(int setup) {\n         server.lua_caller = NULL;\n         server.lua_timedout = 0;\n         server.lua_always_replicate_commands = 0; /* Only DEBUG can change it.*/\n-        server.lua_time_limit = LUA_SCRIPT_TIME_LIMIT;\n         ldbInit();\n     }\n \ndiff --git a/src/server.c b/src/server.c\nindex 71bcda7d..609f3966 100644\n--- a/src/server.c\n+++ b/src/server.c\n@@ -1533,6 +1533,7 @@ void initServerConfig(void) {\n     server.migrate_cached_sockets = dictCreate(&migrateCacheDictType,NULL);\n     server.next_client_id = 1; /* Client IDs, start from 1 .*/\n     server.loading_process_events_interval_bytes = (1024*1024*2);\n+    server.lua_time_limit = LUA_SCRIPT_TIME_LIMIT;\n \n     server.lruclock = getLRUClock();\n     resetServerSaveParams();\n-- \n2.13.1\n\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.8/patch/redis/0008-Fix-zmalloc_get_memory_size-ifdefs-to-actually-use-t.patch",
    "content": "From dd80fedf6fd10556cac7d8318fa4b34fa67a1c81 Mon Sep 17 00:00:00 2001\nFrom: antirez <antirez@gmail.com>\nDate: Tue, 11 Apr 2017 16:45:08 +0200\nSubject: [PATCH 08/19] Fix zmalloc_get_memory_size() ifdefs to actually use\n the else branch.\n\nClose #3927.\n---\n src/zmalloc.c | 2 --\n 1 file changed, 2 deletions(-)\n\ndiff --git a/src/zmalloc.c b/src/zmalloc.c\nindex 640ee19e..d795f448 100644\n--- a/src/zmalloc.c\n+++ b/src/zmalloc.c\n@@ -413,8 +413,6 @@ size_t zmalloc_get_memory_size(void) {\n     if (sysctl(mib, 2, &size, &len, NULL, 0) == 0)\n         return (size_t)size;\n     return 0L;          /* Failed? */\n-#endif /* sysctl and sysconf variants */\n-\n #else\n     return 0L;          /* Unknown OS. */\n #endif\n-- \n2.13.1\n\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.8/patch/redis/0009-Fix-preprocessor-if-else-chain-broken-in-order-to-fi.patch",
    "content": "From f59b4b93d9211c9888ab044caf2038fa6886424f Mon Sep 17 00:00:00 2001\nFrom: antirez <antirez@gmail.com>\nDate: Tue, 11 Apr 2017 16:54:27 +0200\nSubject: [PATCH 09/19] Fix preprocessor if/else chain broken in order to fix\n #3927.\n\n---\n src/zmalloc.c | 3 +++\n 1 file changed, 3 insertions(+)\n\ndiff --git a/src/zmalloc.c b/src/zmalloc.c\nindex d795f448..edfbd570 100644\n--- a/src/zmalloc.c\n+++ b/src/zmalloc.c\n@@ -414,6 +414,9 @@ size_t zmalloc_get_memory_size(void) {\n         return (size_t)size;\n     return 0L;          /* Failed? */\n #else\n+    return 0L;          /* Unknown method to get the data. */\n+#endif\n+#else\n     return 0L;          /* Unknown OS. */\n #endif\n }\n-- \n2.13.1\n\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.8/patch/redis/0010-redis-cli-bigkeys-show-error-when-TYPE-fails.patch",
    "content": "From 3b46cf97de6c5d7f2602dda924703db4f87efcc3 Mon Sep 17 00:00:00 2001\nFrom: antirez <antirez@gmail.com>\nDate: Mon, 15 May 2017 11:22:28 +0200\nSubject: [PATCH 10/19] redis-cli --bigkeys: show error when TYPE fails.\n\nClose #3993.\n---\n src/redis-cli.c | 9 +++++++--\n 1 file changed, 7 insertions(+), 2 deletions(-)\n\ndiff --git a/src/redis-cli.c b/src/redis-cli.c\nindex 9c1de0a2..40f91762 100644\n--- a/src/redis-cli.c\n+++ b/src/redis-cli.c\n@@ -2022,8 +2022,13 @@ static void getKeyTypes(redisReply *keys, int *types) {\n                 keys->element[i]->str, context->err, context->errstr);\n             exit(1);\n         } else if(reply->type != REDIS_REPLY_STATUS) {\n-            fprintf(stderr, \"Invalid reply type (%d) for TYPE on key '%s'!\\n\",\n-                reply->type, keys->element[i]->str);\n+            if(reply->type == REDIS_REPLY_ERROR) {\n+                fprintf(stderr, \"TYPE returned an error: %s\\n\", reply->str);\n+            } else {\n+                fprintf(stderr,\n+                    \"Invalid reply type (%d) for TYPE on key '%s'!\\n\",\n+                    reply->type, keys->element[i]->str);\n+            }\n             exit(1);\n         }\n \n-- \n2.13.1\n\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.8/patch/redis/0011-Redis-3.2.9.patch",
    "content": "From 5116130d42afdaece3de1816174acc69b6d0ccbf Mon Sep 17 00:00:00 2001\nFrom: antirez <antirez@gmail.com>\nDate: Wed, 17 May 2017 17:39:00 +0200\nSubject: [PATCH 11/19] Redis 3.2.9.\n\n---\n 00-RELEASENOTES | 46 ++++++++++++++++++++++++++++++++++++++++++++++\n src/version.h   |  2 +-\n 2 files changed, 47 insertions(+), 1 deletion(-)\n\ndiff --git a/00-RELEASENOTES b/00-RELEASENOTES\nindex ecc04e83..72cfd624 100644\n--- a/00-RELEASENOTES\n+++ b/00-RELEASENOTES\n@@ -11,6 +11,52 @@ CRITICAL: There is a critical bug affecting MOST USERS. Upgrade ASAP.\n --------------------------------------------------------------------------------\n \n ================================================================================\n+Redis 3.2.9     Released Mon May 17 17:35:38 CEST 2017\n+================================================================================\n+\n+Upgrade urgency LOW: A few rarely harmful bugs were fixed.\n+\n+This release just fixes bugs that are unlikely to cause serious problems\n+so there is no need to update ASAP. Please, see the list of commits\n+for the details on the bugs fixed and credits:\n+\n+antirez in commit 3b46cf97:\n+ redis-cli --bigkeys: show error when TYPE fails.\n+ 1 file changed, 7 insertions(+), 2 deletions(-)\n+\n+antirez in commit f59b4b93:\n+ Fix preprocessor if/else chain broken in order to fix #3927.\n+ 1 file changed, 3 insertions(+)\n+\n+antirez in commit dd80fedf:\n+ Fix zmalloc_get_memory_size() ifdefs to actually use the else branch.\n+ 1 file changed, 2 deletions(-)\n+\n+antirez in commit 697d3abe:\n+ Set lua-time-limit default value at safe place.\n+ 2 files changed, 1 insertion(+), 1 deletion(-)\n+\n+antirez in commit c9c04b11:\n+ Fix #3848 by closing the descriptor on error.\n+ 1 file changed, 2 insertions(+), 1 deletion(-)\n+\n+张文康 in commit d3b49924:\n+ update block->free after some diff data are written to the child process\n+ 1 file changed, 1 insertion(+)\n+\n+antirez in commit 6a33952b:\n+ Test: fix, hopefully, false PSYNC failure like in issue #2715.\n+ 1 file changed, 1 insertion(+), 1 deletion(-)\n+\n+John.Koepi in commit b83f9fea:\n+ fix #2883, #2857 pipe fds leak when fork() failed on bg aof rw\n+ 1 file changed, 1 insertion(+)\n+\n+antirez in commit 10dbb5cd:\n+ Don't leak file descriptor on syncWithMaster().\n+ 1 file changed, 2 insertions(+), 1 deletion(-)\n+\n+================================================================================\n Redis 3.2.8     Released Sun Feb 12 16:11:18 CET 2017\n ================================================================================\n \ndiff --git a/src/version.h b/src/version.h\nindex d4e33a6d..4d7dbc2e 100644\n--- a/src/version.h\n+++ b/src/version.h\n@@ -1 +1 @@\n-#define REDIS_VERSION \"3.2.8\"\n+#define REDIS_VERSION \"3.2.9\"\n-- \n2.13.1\n\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.8/patch/redis/0012-fix-Update-create-cluster-README.patch",
    "content": "From 373facf81c8bc5ab45629b0043b13aca2a5285c4 Mon Sep 17 00:00:00 2001\nFrom: Aric Huang <arichuang@gmail.com>\nDate: Fri, 16 Jun 2017 16:10:00 -0700\nSubject: [PATCH 12/19] (fix) Update create-cluster README\n\nFix a few typos/adjust wording in `create-cluster` README\n---\n utils/create-cluster/README | 8 ++++----\n 1 file changed, 4 insertions(+), 4 deletions(-)\n\ndiff --git a/utils/create-cluster/README b/utils/create-cluster/README\nindex 1f43748e..f2a89839 100644\n--- a/utils/create-cluster/README\n+++ b/utils/create-cluster/README\n@@ -2,7 +2,7 @@ Create-custer is a small script used to easily start a big number of Redis\n instances configured to run in cluster mode. Its main goal is to allow manual\n testing in a condition which is not easy to replicate with the Redis cluster\n unit tests, for example when a lot of instances are needed in order to trigger\n-a give bug.\n+a given bug.\n \n The tool can also be used just to easily create a number of instances in a\n Redis Cluster in order to experiment a bit with the system.\n@@ -10,7 +10,7 @@ Redis Cluster in order to experiment a bit with the system.\n USAGE\n ---\n \n-To create a cluster, follow this steps:\n+To create a cluster, follow these steps:\n \n 1. Edit create-cluster and change the start / end port, depending on the\n number of instances you want to create.\n@@ -21,7 +21,7 @@ an actual Redis cluster will be created.\n \n In order to stop a cluster:\n \n-1. Use \"./craete-cluster stop\" to stop all the instances. After you stopped the instances you can use \"./create-cluster start\" to restart them if you change ideas.\n-2. Use \"./create-cluster clean\" to remove all the AOF / log files to restat with a clean environment.\n+1. Use \"./create-cluster stop\" to stop all the instances. After you stopped the instances you can use \"./create-cluster start\" to restart them if you change your mind.\n+2. Use \"./create-cluster clean\" to remove all the AOF / log files to restart with a clean environment.\n \n Use the command \"./create-cluster help\" to get the full list of features.\n-- \n2.13.1\n\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.8/patch/redis/0013-cli-Only-print-elapsed-time-on-OUTPUT_STANDARD.patch",
    "content": "From 13546adcb9cb83dd021b6f8e068d00f6b0669d20 Mon Sep 17 00:00:00 2001\nFrom: cbgbt <sean.kelly.2992@gmail.com>\nDate: Thu, 1 Dec 2016 02:33:01 -0800\nSubject: [PATCH 13/19] cli: Only print elapsed time on OUTPUT_STANDARD\n\n---\n src/redis-cli.c | 4 +++-\n 1 file changed, 3 insertions(+), 1 deletion(-)\n\ndiff --git a/src/redis-cli.c b/src/redis-cli.c\nindex 40f91762..3c711402 100644\n--- a/src/redis-cli.c\n+++ b/src/redis-cli.c\n@@ -1351,7 +1351,9 @@ static void repl(void) {\n                     }\n \n                     elapsed = mstime()-start_time;\n-                    if (elapsed >= 500) {\n+                    if (elapsed >= 500 &&\n+                        config.output == OUTPUT_STANDARD)\n+                    {\n                         printf(\"(%.2fs)\\n\",(double)elapsed/1000);\n                     }\n                 }\n-- \n2.13.1\n\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.8/patch/redis/0014-Fixed-comments-of-slowlog-duration.patch",
    "content": "From 8da9a167e08c6cb0ec1e789f322f47ff77128295 Mon Sep 17 00:00:00 2001\nFrom: xuchengxuan <xuchengxuan@xiaomi.com>\nDate: Wed, 14 Jun 2017 16:42:21 +0800\nSubject: [PATCH 14/19] Fixed comments of slowlog duration\n\n---\n src/slowlog.h | 2 +-\n 1 file changed, 1 insertion(+), 1 deletion(-)\n\ndiff --git a/src/slowlog.h b/src/slowlog.h\nindex 81df0b05..6b8740e8 100644\n--- a/src/slowlog.h\n+++ b/src/slowlog.h\n@@ -35,7 +35,7 @@ typedef struct slowlogEntry {\n     robj **argv;\n     int argc;\n     long long id;       /* Unique entry identifier. */\n-    long long duration; /* Time spent by the query, in nanoseconds. */\n+    long long duration; /* Time spent by the query, in microseconds. */\n     time_t time;        /* Unix time at which the query was executed. */\n } slowlogEntry;\n \n-- \n2.13.1\n\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.8/patch/redis/0015-fix-server.stat_net_output_bytes-calc-bug.patch",
    "content": "From d70ac1d105ddc72afc32a13a6f1690b47d452335 Mon Sep 17 00:00:00 2001\nFrom: \"minghang.zmh\" <minghang.zmh@alibaba-inc.com>\nDate: Fri, 10 Feb 2017 20:13:01 +0800\nSubject: [PATCH 15/19] fix server.stat_net_output_bytes calc bug\n\n---\n src/networking.c | 2 +-\n 1 file changed, 1 insertion(+), 1 deletion(-)\n\ndiff --git a/src/networking.c b/src/networking.c\nindex fb5341ec..c81a1307 100644\n--- a/src/networking.c\n+++ b/src/networking.c\n@@ -949,11 +949,11 @@ int writeToClient(int fd, client *c, int handler_installed) {\n          *\n          * However if we are over the maxmemory limit we ignore that and\n          * just deliver as much data as it is possible to deliver. */\n-        server.stat_net_output_bytes += totwritten;\n         if (totwritten > NET_MAX_WRITES_PER_EVENT &&\n             (server.maxmemory == 0 ||\n              zmalloc_used_memory() < server.maxmemory)) break;\n     }\n+    server.stat_net_output_bytes += totwritten;\n     if (nwritten == -1) {\n         if (errno == EAGAIN) {\n             nwritten = 0;\n-- \n2.13.1\n\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.8/patch/redis/0016-Fix-set-with-ex-px-option-when-propagated-to-aof.patch",
    "content": "From 351663bd7b01caf50d55c3d9aec18151268c9a9e Mon Sep 17 00:00:00 2001\nFrom: xuzhou <xuzhou1@jd.com>\nDate: Fri, 16 Jun 2017 17:51:38 +0800\nSubject: [PATCH 16/19] Fix set with ex/px option when propagated to aof\n\n---\n src/aof.c             | 17 +++++++++++++++++\n src/server.c          |  2 ++\n src/server.h          |  3 ++-\n tests/unit/expire.tcl | 15 +++++++++++++++\n 4 files changed, 36 insertions(+), 1 deletion(-)\n\ndiff --git a/src/aof.c b/src/aof.c\nindex cbd906c9..4a179bd6 100644\n--- a/src/aof.c\n+++ b/src/aof.c\n@@ -536,6 +536,23 @@ void feedAppendOnlyFile(struct redisCommand *cmd, int dictid, robj **argv, int a\n         buf = catAppendOnlyGenericCommand(buf,3,tmpargv);\n         decrRefCount(tmpargv[0]);\n         buf = catAppendOnlyExpireAtCommand(buf,cmd,argv[1],argv[2]);\n+    } else if (cmd->proc == setCommand) {\n+        int i;\n+        robj *exarg = NULL, *pxarg = NULL;\n+        /* Translate SET [EX seconds][PX milliseconds] to SET and PEXPIREAT */\n+        buf = catAppendOnlyGenericCommand(buf,3,argv);\n+        for (i = 3; i < argc; i ++) {\n+            if (sdsEncodedObject(argv[i]) && !strcasecmp(argv[i]->ptr, \"ex\"))\n+                exarg = argv[i+1];\n+\n+            if (sdsEncodedObject(argv[i]) && !strcasecmp(argv[i]->ptr, \"px\"))\n+                pxarg = argv[i+1];\n+        }\n+        serverAssert(!(exarg && pxarg));\n+        if (exarg)\n+            buf = catAppendOnlyExpireAtCommand(buf,server.expireCommand,argv[1],exarg);\n+        if (pxarg)\n+            buf = catAppendOnlyExpireAtCommand(buf,server.pexpireCommand,argv[1],pxarg);\n     } else {\n         /* All the other commands don't need translation or need the\n          * same translation already operated in the command vector\ndiff --git a/src/server.c b/src/server.c\nindex 308e51fc..4964ff14 100644\n--- a/src/server.c\n+++ b/src/server.c\n@@ -1593,6 +1593,8 @@ void initServerConfig(void) {\n     server.rpopCommand = lookupCommandByCString(\"rpop\");\n     server.sremCommand = lookupCommandByCString(\"srem\");\n     server.execCommand = lookupCommandByCString(\"exec\");\n+    server.expireCommand = lookupCommandByCString(\"expire\");\n+    server.pexpireCommand = lookupCommandByCString(\"pexpire\");\n \n     /* Slow log */\n     server.slowlog_log_slower_than = CONFIG_DEFAULT_SLOWLOG_LOG_SLOWER_THAN;\ndiff --git a/src/server.h b/src/server.h\nindex 4ca73a25..e804ee78 100644\n--- a/src/server.h\n+++ b/src/server.h\n@@ -752,7 +752,8 @@ struct redisServer {\n     off_t loading_process_events_interval_bytes;\n     /* Fast pointers to often looked up command */\n     struct redisCommand *delCommand, *multiCommand, *lpushCommand, *lpopCommand,\n-                        *rpopCommand, *sremCommand, *execCommand;\n+                        *rpopCommand, *sremCommand, *execCommand, *expireCommand,\n+                        *pexpireCommand;\n     /* Fields used only for stats */\n     time_t stat_starttime;          /* Server start time */\n     long long stat_numcommands;     /* Number of processed commands */\ndiff --git a/tests/unit/expire.tcl b/tests/unit/expire.tcl\nindex 0a50dd31..eddc7c30 100644\n--- a/tests/unit/expire.tcl\n+++ b/tests/unit/expire.tcl\n@@ -204,4 +204,19 @@ start_server {tags {\"expire\"}} {\n         catch {r expire foo \"\"} e\n         set e\n     } {*not an integer*}\n+\n+    test {SET - use EX/PX option, TTL should not be reseted after loadaof} {\n+        r config set appendonly yes\n+        r set foo bar EX 100\n+        after 2000\n+        r debug loadaof\n+        set ttl [r ttl foo]\n+        assert {$ttl <= 98 && $ttl > 90}\n+\n+        r set foo bar PX 100000\n+        after 2000\n+        r debug loadaof\n+        set ttl [r ttl foo]\n+        assert {$ttl <= 98 && $ttl > 90}\n+    }\n }\n-- \n2.13.1\n\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.8/patch/redis/0017-redis-benchmark-add-t-hset-target.patch",
    "content": "From ad949f23292eba906ec5d35340b09d92f8068078 Mon Sep 17 00:00:00 2001\nFrom: antirez <antirez@gmail.com>\nDate: Mon, 19 Jun 2017 09:41:11 +0200\nSubject: [PATCH 17/19] redis-benchmark: add -t hset target.\n\n---\n src/redis-benchmark.c | 7 +++++++\n 1 file changed, 7 insertions(+)\n\ndiff --git a/src/redis-benchmark.c b/src/redis-benchmark.c\nindex 50905c87..7f560ce7 100644\n--- a/src/redis-benchmark.c\n+++ b/src/redis-benchmark.c\n@@ -779,6 +779,13 @@ int main(int argc, const char **argv) {\n             free(cmd);\n         }\n \n+        if (test_is_selected(\"hset\")) {\n+            len = redisFormatCommand(&cmd,\n+                \"HSET myset:__rand_int__ element:__rand_int__ %s\",data);\n+            benchmark(\"HSET\",cmd,len);\n+            free(cmd);\n+        }\n+\n         if (test_is_selected(\"spop\")) {\n             len = redisFormatCommand(&cmd,\"SPOP myset\");\n             benchmark(\"SPOP\",cmd,len);\n-- \n2.13.1\n\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.8/patch/redis/0018-Optimize-set-command-with-ex-px-when-updating-aof.patch",
    "content": "From 2b0f03e4f219a25b06c006e3ee3a4c8da0045d19 Mon Sep 17 00:00:00 2001\nFrom: xuzhou <xuzhou1@jd.com>\nDate: Thu, 22 Jun 2017 11:06:40 +0800\nSubject: [PATCH 18/19] Optimize set command with ex/px when updating aof.\n\n---\n src/aof.c | 6 +++---\n 1 file changed, 3 insertions(+), 3 deletions(-)\n\ndiff --git a/src/aof.c b/src/aof.c\nindex 4a179bd6..ea9ac47a 100644\n--- a/src/aof.c\n+++ b/src/aof.c\n@@ -536,16 +536,16 @@ void feedAppendOnlyFile(struct redisCommand *cmd, int dictid, robj **argv, int a\n         buf = catAppendOnlyGenericCommand(buf,3,tmpargv);\n         decrRefCount(tmpargv[0]);\n         buf = catAppendOnlyExpireAtCommand(buf,cmd,argv[1],argv[2]);\n-    } else if (cmd->proc == setCommand) {\n+    } else if (cmd->proc == setCommand && argc > 3) {\n         int i;\n         robj *exarg = NULL, *pxarg = NULL;\n         /* Translate SET [EX seconds][PX milliseconds] to SET and PEXPIREAT */\n         buf = catAppendOnlyGenericCommand(buf,3,argv);\n         for (i = 3; i < argc; i ++) {\n-            if (sdsEncodedObject(argv[i]) && !strcasecmp(argv[i]->ptr, \"ex\"))\n+            if (!strcasecmp(argv[i]->ptr, \"ex\"))\n                 exarg = argv[i+1];\n \n-            if (sdsEncodedObject(argv[i]) && !strcasecmp(argv[i]->ptr, \"px\"))\n+            if (!strcasecmp(argv[i]->ptr, \"px\"))\n                 pxarg = argv[i+1];\n         }\n         serverAssert(!(exarg && pxarg));\n-- \n2.13.1\n\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.8/patch/redis/0019-Aesthetic-changes-to-4068-PR-to-conform-to-Redis-cod.patch",
    "content": "From d067e3342fefe0be14ce5294a53ea2c76a2a0d04 Mon Sep 17 00:00:00 2001\nFrom: antirez <antirez@gmail.com>\nDate: Thu, 22 Jun 2017 11:00:21 +0200\nSubject: [PATCH 19/19] Aesthetic changes to #4068 PR to conform to Redis\n coding standard.\n\n1. Inline if ... statement if short.\n2. No lines over 80 columns.\n---\n src/aof.c | 13 ++++++-------\n 1 file changed, 6 insertions(+), 7 deletions(-)\n\ndiff --git a/src/aof.c b/src/aof.c\nindex ea9ac47a..3b80ca1d 100644\n--- a/src/aof.c\n+++ b/src/aof.c\n@@ -542,17 +542,16 @@ void feedAppendOnlyFile(struct redisCommand *cmd, int dictid, robj **argv, int a\n         /* Translate SET [EX seconds][PX milliseconds] to SET and PEXPIREAT */\n         buf = catAppendOnlyGenericCommand(buf,3,argv);\n         for (i = 3; i < argc; i ++) {\n-            if (!strcasecmp(argv[i]->ptr, \"ex\"))\n-                exarg = argv[i+1];\n-\n-            if (!strcasecmp(argv[i]->ptr, \"px\"))\n-                pxarg = argv[i+1];\n+            if (!strcasecmp(argv[i]->ptr, \"ex\")) exarg = argv[i+1];\n+            if (!strcasecmp(argv[i]->ptr, \"px\")) pxarg = argv[i+1];\n         }\n         serverAssert(!(exarg && pxarg));\n         if (exarg)\n-            buf = catAppendOnlyExpireAtCommand(buf,server.expireCommand,argv[1],exarg);\n+            buf = catAppendOnlyExpireAtCommand(buf,server.expireCommand,argv[1],\n+                                               exarg);\n         if (pxarg)\n-            buf = catAppendOnlyExpireAtCommand(buf,server.pexpireCommand,argv[1],pxarg);\n+            buf = catAppendOnlyExpireAtCommand(buf,server.pexpireCommand,argv[1],\n+                                               pxarg);\n     } else {\n         /* All the other commands don't need translation or need the\n          * same translation already operated in the command vector\n-- \n2.13.1\n\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.8/patch/run.sh",
    "content": "#!/bin/bash\n\nset -e\n\napply_patch() {\n    echo \"  >>\" $@ \"<<\"\n    file=`realpath $1`; shift\n    pushd ../ > /dev/null\n    patch $@ < $file\n    popd > /dev/null\n}\n\npatch_patches() {\n    dir=$1; shift\n    files=`ls -1 $dir/*.patch | sort`\n    for i in $files; do\n        apply_patch $i $@\n    done\n}\n\nrevert_patches() {\n    dir=$1; shift\n    files=`ls -1 $dir/*.patch | sort --reverse`\n    for i in $files; do\n        apply_patch $i $@ -R\n    done\n}\n\ncase \"$1\" in\npatch)\n    patch_patches redis -p1\n    patch_patches codis -p3\n    ;;\n\nrevert)\n    revert_patches redis -p1\n    revert_patches codis -p3\n    ;;\n*)\n    echo \"wrong argument(s)\"\n    ;;\nesac\n\n\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.8/redis.conf",
    "content": "# Redis configuration file example.\n#\n# Note that in order to read the configuration file, Redis must be\n# started with the file path as first argument:\n#\n# ./redis-server /path/to/redis.conf\n\n# Note on units: when memory size is needed, it is possible to specify\n# it in the usual form of 1k 5GB 4M and so forth:\n#\n# 1k => 1000 bytes\n# 1kb => 1024 bytes\n# 1m => 1000000 bytes\n# 1mb => 1024*1024 bytes\n# 1g => 1000000000 bytes\n# 1gb => 1024*1024*1024 bytes\n#\n# units are case insensitive so 1GB 1Gb 1gB are all the same.\n\n################################## INCLUDES ###################################\n\n# Include one or more other config files here.  This is useful if you\n# have a standard template that goes to all Redis servers but also need\n# to customize a few per-server settings.  Include files can include\n# other files, so use this wisely.\n#\n# Notice option \"include\" won't be rewritten by command \"CONFIG REWRITE\"\n# from admin or Redis Sentinel. Since Redis always uses the last processed\n# line as value of a configuration directive, you'd better put includes\n# at the beginning of this file to avoid overwriting config change at runtime.\n#\n# If instead you are interested in using includes to override configuration\n# options, it is better to use include as the last line.\n#\n# include /path/to/local.conf\n# include /path/to/other.conf\n\n################################## NETWORK #####################################\n\n# By default, if no \"bind\" configuration directive is specified, Redis listens\n# for connections from all the network interfaces available on the server.\n# It is possible to listen to just one or multiple selected interfaces using\n# the \"bind\" configuration directive, followed by one or more IP addresses.\n#\n# Examples:\n#\n# bind 192.168.1.100 10.0.0.1\n# bind 127.0.0.1 ::1\n#\n# ~~~ WARNING ~~~ If the computer running Redis is directly exposed to the\n# internet, binding to all the interfaces is dangerous and will expose the\n# instance to everybody on the internet. So by default we uncomment the\n# following bind directive, that will force Redis to listen only into\n# the IPv4 lookback interface address (this means Redis will be able to\n# accept connections only from clients running into the same computer it\n# is running).\n#\n# IF YOU ARE SURE YOU WANT YOUR INSTANCE TO LISTEN TO ALL THE INTERFACES\n# JUST COMMENT THE FOLLOWING LINE.\n# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\nbind 127.0.0.1\n\n# Protected mode is a layer of security protection, in order to avoid that\n# Redis instances left open on the internet are accessed and exploited.\n#\n# When protected mode is on and if:\n#\n# 1) The server is not binding explicitly to a set of addresses using the\n#    \"bind\" directive.\n# 2) No password is configured.\n#\n# The server only accepts connections from clients connecting from the\n# IPv4 and IPv6 loopback addresses 127.0.0.1 and ::1, and from Unix domain\n# sockets.\n#\n# By default protected mode is enabled. You should disable it only if\n# you are sure you want clients from other hosts to connect to Redis\n# even if no authentication is configured, nor a specific set of interfaces\n# are explicitly listed using the \"bind\" directive.\nprotected-mode yes\n\n# Accept connections on the specified port, default is 6379 (IANA #815344).\n# If port 0 is specified Redis will not listen on a TCP socket.\nport 6379\n\n# TCP listen() backlog.\n#\n# In high requests-per-second environments you need an high backlog in order\n# to avoid slow clients connections issues. Note that the Linux kernel\n# will silently truncate it to the value of /proc/sys/net/core/somaxconn so\n# make sure to raise both the value of somaxconn and tcp_max_syn_backlog\n# in order to get the desired effect.\ntcp-backlog 511\n\n# Unix socket.\n#\n# Specify the path for the Unix socket that will be used to listen for\n# incoming connections. There is no default, so Redis will not listen\n# on a unix socket when not specified.\n#\n# unixsocket /tmp/redis.sock\n# unixsocketperm 700\n\n# Close the connection after a client is idle for N seconds (0 to disable)\ntimeout 0\n\n# TCP keepalive.\n#\n# If non-zero, use SO_KEEPALIVE to send TCP ACKs to clients in absence\n# of communication. This is useful for two reasons:\n#\n# 1) Detect dead peers.\n# 2) Take the connection alive from the point of view of network\n#    equipment in the middle.\n#\n# On Linux, the specified value (in seconds) is the period used to send ACKs.\n# Note that to close the connection the double of the time is needed.\n# On other kernels the period depends on the kernel configuration.\n#\n# A reasonable value for this option is 300 seconds, which is the new\n# Redis default starting with Redis 3.2.1.\ntcp-keepalive 300\n\n################################# GENERAL #####################################\n\n# By default Redis does not run as a daemon. Use 'yes' if you need it.\n# Note that Redis will write a pid file in /var/run/redis.pid when daemonized.\ndaemonize yes\n\n# If you run Redis from upstart or systemd, Redis can interact with your\n# supervision tree. Options:\n#   supervised no      - no supervision interaction\n#   supervised upstart - signal upstart by putting Redis into SIGSTOP mode\n#   supervised systemd - signal systemd by writing READY=1 to $NOTIFY_SOCKET\n#   supervised auto    - detect upstart or systemd method based on\n#                        UPSTART_JOB or NOTIFY_SOCKET environment variables\n# Note: these supervision methods only signal \"process is ready.\"\n#       They do not enable continuous liveness pings back to your supervisor.\nsupervised no\n\n# If a pid file is specified, Redis writes it where specified at startup\n# and removes it at exit.\n#\n# When the server runs non daemonized, no pid file is created if none is\n# specified in the configuration. When the server is daemonized, the pid file\n# is used even if not specified, defaulting to \"/var/run/redis.pid\".\n#\n# Creating a pid file is best effort: if Redis is not able to create it\n# nothing bad happens, the server will start and run normally.\npidfile /tmp/redis_6379.pid\n\n# Specify the server verbosity level.\n# This can be one of:\n# debug (a lot of information, useful for development/testing)\n# verbose (many rarely useful info, but not a mess like the debug level)\n# notice (moderately verbose, what you want in production probably)\n# warning (only very important / critical messages are logged)\nloglevel notice\n\n# Specify the log file name. Also the empty string can be used to force\n# Redis to log on the standard output. Note that if you use standard\n# output for logging but daemonize, logs will be sent to /dev/null\nlogfile \"/tmp/redis_6379.log\"\n\n# To enable logging to the system logger, just set 'syslog-enabled' to yes,\n# and optionally update the other syslog parameters to suit your needs.\n# syslog-enabled no\n\n# Specify the syslog identity.\n# syslog-ident redis\n\n# Specify the syslog facility. Must be USER or between LOCAL0-LOCAL7.\n# syslog-facility local0\n\n# Set the number of databases. The default database is DB 0, you can select\n# a different one on a per-connection basis using SELECT <dbid> where\n# dbid is a number between 0 and 'databases'-1\ndatabases 16\n\n################################ SNAPSHOTTING  ################################\n#\n# Save the DB on disk:\n#\n#   save <seconds> <changes>\n#\n#   Will save the DB if both the given number of seconds and the given\n#   number of write operations against the DB occurred.\n#\n#   In the example below the behaviour will be to save:\n#   after 900 sec (15 min) if at least 1 key changed\n#   after 300 sec (5 min) if at least 10 keys changed\n#   after 60 sec if at least 10000 keys changed\n#\n#   Note: you can disable saving completely by commenting out all \"save\" lines.\n#\n#   It is also possible to remove all the previously configured save\n#   points by adding a save directive with a single empty string argument\n#   like in the following example:\n#\n#   save \"\"\n\nsave 900 1\nsave 300 10\nsave 60 10000\n\n# By default Redis will stop accepting writes if RDB snapshots are enabled\n# (at least one save point) and the latest background save failed.\n# This will make the user aware (in a hard way) that data is not persisting\n# on disk properly, otherwise chances are that no one will notice and some\n# disaster will happen.\n#\n# If the background saving process will start working again Redis will\n# automatically allow writes again.\n#\n# However if you have setup your proper monitoring of the Redis server\n# and persistence, you may want to disable this feature so that Redis will\n# continue to work as usual even if there are problems with disk,\n# permissions, and so forth.\nstop-writes-on-bgsave-error yes\n\n# Compress string objects using LZF when dump .rdb databases?\n# For default that's set to 'yes' as it's almost always a win.\n# If you want to save some CPU in the saving child set it to 'no' but\n# the dataset will likely be bigger if you have compressible values or keys.\nrdbcompression yes\n\n# Since version 5 of RDB a CRC64 checksum is placed at the end of the file.\n# This makes the format more resistant to corruption but there is a performance\n# hit to pay (around 10%) when saving and loading RDB files, so you can disable it\n# for maximum performances.\n#\n# RDB files created with checksum disabled have a checksum of zero that will\n# tell the loading code to skip the check.\nrdbchecksum yes\n\n# The filename where to dump the DB\ndbfilename dump.rdb\n\n# The working directory.\n#\n# The DB will be written inside this directory, with the filename specified\n# above using the 'dbfilename' configuration directive.\n#\n# The Append Only File will also be created inside this directory.\n#\n# Note that you must specify a directory here, not a file name.\ndir ./\n\n################################# REPLICATION #################################\n\n# Master-Slave replication. Use slaveof to make a Redis instance a copy of\n# another Redis server. A few things to understand ASAP about Redis replication.\n#\n# 1) Redis replication is asynchronous, but you can configure a master to\n#    stop accepting writes if it appears to be not connected with at least\n#    a given number of slaves.\n# 2) Redis slaves are able to perform a partial resynchronization with the\n#    master if the replication link is lost for a relatively small amount of\n#    time. You may want to configure the replication backlog size (see the next\n#    sections of this file) with a sensible value depending on your needs.\n# 3) Replication is automatic and does not need user intervention. After a\n#    network partition slaves automatically try to reconnect to masters\n#    and resynchronize with them.\n#\n# slaveof <masterip> <masterport>\n\n# If the master is password protected (using the \"requirepass\" configuration\n# directive below) it is possible to tell the slave to authenticate before\n# starting the replication synchronization process, otherwise the master will\n# refuse the slave request.\n#\n# masterauth <master-password>\n\n# When a slave loses its connection with the master, or when the replication\n# is still in progress, the slave can act in two different ways:\n#\n# 1) if slave-serve-stale-data is set to 'yes' (the default) the slave will\n#    still reply to client requests, possibly with out of date data, or the\n#    data set may just be empty if this is the first synchronization.\n#\n# 2) if slave-serve-stale-data is set to 'no' the slave will reply with\n#    an error \"SYNC with master in progress\" to all the kind of commands\n#    but to INFO and SLAVEOF.\n#\nslave-serve-stale-data yes\n\n# You can configure a slave instance to accept writes or not. Writing against\n# a slave instance may be useful to store some ephemeral data (because data\n# written on a slave will be easily deleted after resync with the master) but\n# may also cause problems if clients are writing to it because of a\n# misconfiguration.\n#\n# Since Redis 2.6 by default slaves are read-only.\n#\n# Note: read only slaves are not designed to be exposed to untrusted clients\n# on the internet. It's just a protection layer against misuse of the instance.\n# Still a read only slave exports by default all the administrative commands\n# such as CONFIG, DEBUG, and so forth. To a limited extent you can improve\n# security of read only slaves using 'rename-command' to shadow all the\n# administrative / dangerous commands.\nslave-read-only yes\n\n# Replication SYNC strategy: disk or socket.\n#\n# -------------------------------------------------------\n# WARNING: DISKLESS REPLICATION IS EXPERIMENTAL CURRENTLY\n# -------------------------------------------------------\n#\n# New slaves and reconnecting slaves that are not able to continue the replication\n# process just receiving differences, need to do what is called a \"full\n# synchronization\". An RDB file is transmitted from the master to the slaves.\n# The transmission can happen in two different ways:\n#\n# 1) Disk-backed: The Redis master creates a new process that writes the RDB\n#                 file on disk. Later the file is transferred by the parent\n#                 process to the slaves incrementally.\n# 2) Diskless: The Redis master creates a new process that directly writes the\n#              RDB file to slave sockets, without touching the disk at all.\n#\n# With disk-backed replication, while the RDB file is generated, more slaves\n# can be queued and served with the RDB file as soon as the current child producing\n# the RDB file finishes its work. With diskless replication instead once\n# the transfer starts, new slaves arriving will be queued and a new transfer\n# will start when the current one terminates.\n#\n# When diskless replication is used, the master waits a configurable amount of\n# time (in seconds) before starting the transfer in the hope that multiple slaves\n# will arrive and the transfer can be parallelized.\n#\n# With slow disks and fast (large bandwidth) networks, diskless replication\n# works better.\nrepl-diskless-sync no\n\n# When diskless replication is enabled, it is possible to configure the delay\n# the server waits in order to spawn the child that transfers the RDB via socket\n# to the slaves.\n#\n# This is important since once the transfer starts, it is not possible to serve\n# new slaves arriving, that will be queued for the next RDB transfer, so the server\n# waits a delay in order to let more slaves arrive.\n#\n# The delay is specified in seconds, and by default is 5 seconds. To disable\n# it entirely just set it to 0 seconds and the transfer will start ASAP.\nrepl-diskless-sync-delay 5\n\n# Slaves send PINGs to server in a predefined interval. It's possible to change\n# this interval with the repl_ping_slave_period option. The default value is 10\n# seconds.\n#\n# repl-ping-slave-period 10\n\n# The following option sets the replication timeout for:\n#\n# 1) Bulk transfer I/O during SYNC, from the point of view of slave.\n# 2) Master timeout from the point of view of slaves (data, pings).\n# 3) Slave timeout from the point of view of masters (REPLCONF ACK pings).\n#\n# It is important to make sure that this value is greater than the value\n# specified for repl-ping-slave-period otherwise a timeout will be detected\n# every time there is low traffic between the master and the slave.\n#\n# repl-timeout 60\n\n# Disable TCP_NODELAY on the slave socket after SYNC?\n#\n# If you select \"yes\" Redis will use a smaller number of TCP packets and\n# less bandwidth to send data to slaves. But this can add a delay for\n# the data to appear on the slave side, up to 40 milliseconds with\n# Linux kernels using a default configuration.\n#\n# If you select \"no\" the delay for data to appear on the slave side will\n# be reduced but more bandwidth will be used for replication.\n#\n# By default we optimize for low latency, but in very high traffic conditions\n# or when the master and slaves are many hops away, turning this to \"yes\" may\n# be a good idea.\nrepl-disable-tcp-nodelay no\n\n# Set the replication backlog size. The backlog is a buffer that accumulates\n# slave data when slaves are disconnected for some time, so that when a slave\n# wants to reconnect again, often a full resync is not needed, but a partial\n# resync is enough, just passing the portion of data the slave missed while\n# disconnected.\n#\n# The bigger the replication backlog, the longer the time the slave can be\n# disconnected and later be able to perform a partial resynchronization.\n#\n# The backlog is only allocated once there is at least a slave connected.\n#\n# repl-backlog-size 1mb\n\n# After a master has no longer connected slaves for some time, the backlog\n# will be freed. The following option configures the amount of seconds that\n# need to elapse, starting from the time the last slave disconnected, for\n# the backlog buffer to be freed.\n#\n# A value of 0 means to never release the backlog.\n#\n# repl-backlog-ttl 3600\n\n# The slave priority is an integer number published by Redis in the INFO output.\n# It is used by Redis Sentinel in order to select a slave to promote into a\n# master if the master is no longer working correctly.\n#\n# A slave with a low priority number is considered better for promotion, so\n# for instance if there are three slaves with priority 10, 100, 25 Sentinel will\n# pick the one with priority 10, that is the lowest.\n#\n# However a special priority of 0 marks the slave as not able to perform the\n# role of master, so a slave with priority of 0 will never be selected by\n# Redis Sentinel for promotion.\n#\n# By default the priority is 100.\nslave-priority 100\n\n# It is possible for a master to stop accepting writes if there are less than\n# N slaves connected, having a lag less or equal than M seconds.\n#\n# The N slaves need to be in \"online\" state.\n#\n# The lag in seconds, that must be <= the specified value, is calculated from\n# the last ping received from the slave, that is usually sent every second.\n#\n# This option does not GUARANTEE that N replicas will accept the write, but\n# will limit the window of exposure for lost writes in case not enough slaves\n# are available, to the specified number of seconds.\n#\n# For example to require at least 3 slaves with a lag <= 10 seconds use:\n#\n# min-slaves-to-write 3\n# min-slaves-max-lag 10\n#\n# Setting one or the other to 0 disables the feature.\n#\n# By default min-slaves-to-write is set to 0 (feature disabled) and\n# min-slaves-max-lag is set to 10.\n\n# A Redis master is able to list the address and port of the attached\n# slaves in different ways. For example the \"INFO replication\" section\n# offers this information, which is used, among other tools, by\n# Redis Sentinel in order to discover slave instances.\n# Another place where this info is available is in the output of the\n# \"ROLE\" command of a masteer.\n#\n# The listed IP and address normally reported by a slave is obtained\n# in the following way:\n#\n#   IP: The address is auto detected by checking the peer address\n#   of the socket used by the slave to connect with the master.\n#\n#   Port: The port is communicated by the slave during the replication\n#   handshake, and is normally the port that the slave is using to\n#   list for connections.\n#\n# However when port forwarding or Network Address Translation (NAT) is\n# used, the slave may be actually reachable via different IP and port\n# pairs. The following two options can be used by a slave in order to\n# report to its master a specific set of IP and port, so that both INFO\n# and ROLE will report those values.\n#\n# There is no need to use both the options if you need to override just\n# the port or the IP address.\n#\n# slave-announce-ip 5.5.5.5\n# slave-announce-port 1234\n\n################################## SECURITY ###################################\n\n# Require clients to issue AUTH <PASSWORD> before processing any other\n# commands.  This might be useful in environments in which you do not trust\n# others with access to the host running redis-server.\n#\n# This should stay commented out for backward compatibility and because most\n# people do not need auth (e.g. they run their own servers).\n#\n# Warning: since Redis is pretty fast an outside user can try up to\n# 150k passwords per second against a good box. This means that you should\n# use a very strong password otherwise it will be very easy to break.\n#\n# requirepass foobared\n\n# Command renaming.\n#\n# It is possible to change the name of dangerous commands in a shared\n# environment. For instance the CONFIG command may be renamed into something\n# hard to guess so that it will still be available for internal-use tools\n# but not available for general clients.\n#\n# Example:\n#\n# rename-command CONFIG b840fc02d524045429941cc15f59e41cb7be6c52\n#\n# It is also possible to completely kill a command by renaming it into\n# an empty string:\n#\n# rename-command CONFIG \"\"\n#\n# Please note that changing the name of commands that are logged into the\n# AOF file or transmitted to slaves may cause problems.\n\n################################### LIMITS ####################################\n\n# Set the max number of connected clients at the same time. By default\n# this limit is set to 10000 clients, however if the Redis server is not\n# able to configure the process file limit to allow for the specified limit\n# the max number of allowed clients is set to the current file limit\n# minus 32 (as Redis reserves a few file descriptors for internal uses).\n#\n# Once the limit is reached Redis will close all the new connections sending\n# an error 'max number of clients reached'.\n#\n# maxclients 10000\n\n# Don't use more memory than the specified amount of bytes.\n# When the memory limit is reached Redis will try to remove keys\n# according to the eviction policy selected (see maxmemory-policy).\n#\n# If Redis can't remove keys according to the policy, or if the policy is\n# set to 'noeviction', Redis will start to reply with errors to commands\n# that would use more memory, like SET, LPUSH, and so on, and will continue\n# to reply to read-only commands like GET.\n#\n# This option is usually useful when using Redis as an LRU cache, or to set\n# a hard memory limit for an instance (using the 'noeviction' policy).\n#\n# WARNING: If you have slaves attached to an instance with maxmemory on,\n# the size of the output buffers needed to feed the slaves are subtracted\n# from the used memory count, so that network problems / resyncs will\n# not trigger a loop where keys are evicted, and in turn the output\n# buffer of slaves is full with DELs of keys evicted triggering the deletion\n# of more keys, and so forth until the database is completely emptied.\n#\n# In short... if you have slaves attached it is suggested that you set a lower\n# limit for maxmemory so that there is some free RAM on the system for slave\n# output buffers (but this is not needed if the policy is 'noeviction').\n#\n# maxmemory <bytes>\n\n# MAXMEMORY POLICY: how Redis will select what to remove when maxmemory\n# is reached. You can select among five behaviors:\n#\n# volatile-lru -> remove the key with an expire set using an LRU algorithm\n# allkeys-lru -> remove any key according to the LRU algorithm\n# volatile-random -> remove a random key with an expire set\n# allkeys-random -> remove a random key, any key\n# volatile-ttl -> remove the key with the nearest expire time (minor TTL)\n# noeviction -> don't expire at all, just return an error on write operations\n#\n# Note: with any of the above policies, Redis will return an error on write\n#       operations, when there are no suitable keys for eviction.\n#\n#       At the date of writing these commands are: set setnx setex append\n#       incr decr rpush lpush rpushx lpushx linsert lset rpoplpush sadd\n#       sinter sinterstore sunion sunionstore sdiff sdiffstore zadd zincrby\n#       zunionstore zinterstore hset hsetnx hmset hincrby incrby decrby\n#       getset mset msetnx exec sort\n#\n# The default is:\n#\n# maxmemory-policy noeviction\n\n# LRU and minimal TTL algorithms are not precise algorithms but approximated\n# algorithms (in order to save memory), so you can tune it for speed or\n# accuracy. For default Redis will check five keys and pick the one that was\n# used less recently, you can change the sample size using the following\n# configuration directive.\n#\n# The default of 5 produces good enough results. 10 Approximates very closely\n# true LRU but costs a bit more CPU. 3 is very fast but not very accurate.\n#\n# maxmemory-samples 5\n\n############################## APPEND ONLY MODE ###############################\n\n# By default Redis asynchronously dumps the dataset on disk. This mode is\n# good enough in many applications, but an issue with the Redis process or\n# a power outage may result into a few minutes of writes lost (depending on\n# the configured save points).\n#\n# The Append Only File is an alternative persistence mode that provides\n# much better durability. For instance using the default data fsync policy\n# (see later in the config file) Redis can lose just one second of writes in a\n# dramatic event like a server power outage, or a single write if something\n# wrong with the Redis process itself happens, but the operating system is\n# still running correctly.\n#\n# AOF and RDB persistence can be enabled at the same time without problems.\n# If the AOF is enabled on startup Redis will load the AOF, that is the file\n# with the better durability guarantees.\n#\n# Please check http://redis.io/topics/persistence for more information.\n\nappendonly no\n\n# The name of the append only file (default: \"appendonly.aof\")\n\nappendfilename \"appendonly.aof\"\n\n# The fsync() call tells the Operating System to actually write data on disk\n# instead of waiting for more data in the output buffer. Some OS will really flush\n# data on disk, some other OS will just try to do it ASAP.\n#\n# Redis supports three different modes:\n#\n# no: don't fsync, just let the OS flush the data when it wants. Faster.\n# always: fsync after every write to the append only log. Slow, Safest.\n# everysec: fsync only one time every second. Compromise.\n#\n# The default is \"everysec\", as that's usually the right compromise between\n# speed and data safety. It's up to you to understand if you can relax this to\n# \"no\" that will let the operating system flush the output buffer when\n# it wants, for better performances (but if you can live with the idea of\n# some data loss consider the default persistence mode that's snapshotting),\n# or on the contrary, use \"always\" that's very slow but a bit safer than\n# everysec.\n#\n# More details please check the following article:\n# http://antirez.com/post/redis-persistence-demystified.html\n#\n# If unsure, use \"everysec\".\n\n# appendfsync always\nappendfsync everysec\n# appendfsync no\n\n# When the AOF fsync policy is set to always or everysec, and a background\n# saving process (a background save or AOF log background rewriting) is\n# performing a lot of I/O against the disk, in some Linux configurations\n# Redis may block too long on the fsync() call. Note that there is no fix for\n# this currently, as even performing fsync in a different thread will block\n# our synchronous write(2) call.\n#\n# In order to mitigate this problem it's possible to use the following option\n# that will prevent fsync() from being called in the main process while a\n# BGSAVE or BGREWRITEAOF is in progress.\n#\n# This means that while another child is saving, the durability of Redis is\n# the same as \"appendfsync none\". In practical terms, this means that it is\n# possible to lose up to 30 seconds of log in the worst scenario (with the\n# default Linux settings).\n#\n# If you have latency problems turn this to \"yes\". Otherwise leave it as\n# \"no\" that is the safest pick from the point of view of durability.\n\nno-appendfsync-on-rewrite no\n\n# Automatic rewrite of the append only file.\n# Redis is able to automatically rewrite the log file implicitly calling\n# BGREWRITEAOF when the AOF log size grows by the specified percentage.\n#\n# This is how it works: Redis remembers the size of the AOF file after the\n# latest rewrite (if no rewrite has happened since the restart, the size of\n# the AOF at startup is used).\n#\n# This base size is compared to the current size. If the current size is\n# bigger than the specified percentage, the rewrite is triggered. Also\n# you need to specify a minimal size for the AOF file to be rewritten, this\n# is useful to avoid rewriting the AOF file even if the percentage increase\n# is reached but it is still pretty small.\n#\n# Specify a percentage of zero in order to disable the automatic AOF\n# rewrite feature.\n\nauto-aof-rewrite-percentage 100\nauto-aof-rewrite-min-size 64mb\n\n# An AOF file may be found to be truncated at the end during the Redis\n# startup process, when the AOF data gets loaded back into memory.\n# This may happen when the system where Redis is running\n# crashes, especially when an ext4 filesystem is mounted without the\n# data=ordered option (however this can't happen when Redis itself\n# crashes or aborts but the operating system still works correctly).\n#\n# Redis can either exit with an error when this happens, or load as much\n# data as possible (the default now) and start if the AOF file is found\n# to be truncated at the end. The following option controls this behavior.\n#\n# If aof-load-truncated is set to yes, a truncated AOF file is loaded and\n# the Redis server starts emitting a log to inform the user of the event.\n# Otherwise if the option is set to no, the server aborts with an error\n# and refuses to start. When the option is set to no, the user requires\n# to fix the AOF file using the \"redis-check-aof\" utility before to restart\n# the server.\n#\n# Note that if the AOF file will be found to be corrupted in the middle\n# the server will still exit with an error. This option only applies when\n# Redis will try to read more data from the AOF file but not enough bytes\n# will be found.\naof-load-truncated yes\n\n################################ LUA SCRIPTING  ###############################\n\n# Max execution time of a Lua script in milliseconds.\n#\n# If the maximum execution time is reached Redis will log that a script is\n# still in execution after the maximum allowed time and will start to\n# reply to queries with an error.\n#\n# When a long running script exceeds the maximum execution time only the\n# SCRIPT KILL and SHUTDOWN NOSAVE commands are available. The first can be\n# used to stop a script that did not yet called write commands. The second\n# is the only way to shut down the server in the case a write command was\n# already issued by the script but the user doesn't want to wait for the natural\n# termination of the script.\n#\n# Set it to 0 or a negative value for unlimited execution without warnings.\nlua-time-limit 5000\n\n################################ REDIS CLUSTER  ###############################\n#\n# ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++\n# WARNING EXPERIMENTAL: Redis Cluster is considered to be stable code, however\n# in order to mark it as \"mature\" we need to wait for a non trivial percentage\n# of users to deploy it in production.\n# ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++\n#\n# Normal Redis instances can't be part of a Redis Cluster; only nodes that are\n# started as cluster nodes can. In order to start a Redis instance as a\n# cluster node enable the cluster support uncommenting the following:\n#\n# cluster-enabled yes\n\n# Every cluster node has a cluster configuration file. This file is not\n# intended to be edited by hand. It is created and updated by Redis nodes.\n# Every Redis Cluster node requires a different cluster configuration file.\n# Make sure that instances running in the same system do not have\n# overlapping cluster configuration file names.\n#\n# cluster-config-file nodes-6379.conf\n\n# Cluster node timeout is the amount of milliseconds a node must be unreachable\n# for it to be considered in failure state.\n# Most other internal time limits are multiple of the node timeout.\n#\n# cluster-node-timeout 15000\n\n# A slave of a failing master will avoid to start a failover if its data\n# looks too old.\n#\n# There is no simple way for a slave to actually have a exact measure of\n# its \"data age\", so the following two checks are performed:\n#\n# 1) If there are multiple slaves able to failover, they exchange messages\n#    in order to try to give an advantage to the slave with the best\n#    replication offset (more data from the master processed).\n#    Slaves will try to get their rank by offset, and apply to the start\n#    of the failover a delay proportional to their rank.\n#\n# 2) Every single slave computes the time of the last interaction with\n#    its master. This can be the last ping or command received (if the master\n#    is still in the \"connected\" state), or the time that elapsed since the\n#    disconnection with the master (if the replication link is currently down).\n#    If the last interaction is too old, the slave will not try to failover\n#    at all.\n#\n# The point \"2\" can be tuned by user. Specifically a slave will not perform\n# the failover if, since the last interaction with the master, the time\n# elapsed is greater than:\n#\n#   (node-timeout * slave-validity-factor) + repl-ping-slave-period\n#\n# So for example if node-timeout is 30 seconds, and the slave-validity-factor\n# is 10, and assuming a default repl-ping-slave-period of 10 seconds, the\n# slave will not try to failover if it was not able to talk with the master\n# for longer than 310 seconds.\n#\n# A large slave-validity-factor may allow slaves with too old data to failover\n# a master, while a too small value may prevent the cluster from being able to\n# elect a slave at all.\n#\n# For maximum availability, it is possible to set the slave-validity-factor\n# to a value of 0, which means, that slaves will always try to failover the\n# master regardless of the last time they interacted with the master.\n# (However they'll always try to apply a delay proportional to their\n# offset rank).\n#\n# Zero is the only value able to guarantee that when all the partitions heal\n# the cluster will always be able to continue.\n#\n# cluster-slave-validity-factor 10\n\n# Cluster slaves are able to migrate to orphaned masters, that are masters\n# that are left without working slaves. This improves the cluster ability\n# to resist to failures as otherwise an orphaned master can't be failed over\n# in case of failure if it has no working slaves.\n#\n# Slaves migrate to orphaned masters only if there are still at least a\n# given number of other working slaves for their old master. This number\n# is the \"migration barrier\". A migration barrier of 1 means that a slave\n# will migrate only if there is at least 1 other working slave for its master\n# and so forth. It usually reflects the number of slaves you want for every\n# master in your cluster.\n#\n# Default is 1 (slaves migrate only if their masters remain with at least\n# one slave). To disable migration just set it to a very large value.\n# A value of 0 can be set but is useful only for debugging and dangerous\n# in production.\n#\n# cluster-migration-barrier 1\n\n# By default Redis Cluster nodes stop accepting queries if they detect there\n# is at least an hash slot uncovered (no available node is serving it).\n# This way if the cluster is partially down (for example a range of hash slots\n# are no longer covered) all the cluster becomes, eventually, unavailable.\n# It automatically returns available as soon as all the slots are covered again.\n#\n# However sometimes you want the subset of the cluster which is working,\n# to continue to accept queries for the part of the key space that is still\n# covered. In order to do so, just set the cluster-require-full-coverage\n# option to no.\n#\n# cluster-require-full-coverage yes\n\n# In order to setup your cluster make sure to read the documentation\n# available at http://redis.io web site.\n\n################################## SLOW LOG ###################################\n\n# The Redis Slow Log is a system to log queries that exceeded a specified\n# execution time. The execution time does not include the I/O operations\n# like talking with the client, sending the reply and so forth,\n# but just the time needed to actually execute the command (this is the only\n# stage of command execution where the thread is blocked and can not serve\n# other requests in the meantime).\n#\n# You can configure the slow log with two parameters: one tells Redis\n# what is the execution time, in microseconds, to exceed in order for the\n# command to get logged, and the other parameter is the length of the\n# slow log. When a new command is logged the oldest one is removed from the\n# queue of logged commands.\n\n# The following time is expressed in microseconds, so 1000000 is equivalent\n# to one second. Note that a negative number disables the slow log, while\n# a value of zero forces the logging of every command.\nslowlog-log-slower-than 10000\n\n# There is no limit to this length. Just be aware that it will consume memory.\n# You can reclaim memory used by the slow log with SLOWLOG RESET.\nslowlog-max-len 128\n\n################################ LATENCY MONITOR ##############################\n\n# The Redis latency monitoring subsystem samples different operations\n# at runtime in order to collect data related to possible sources of\n# latency of a Redis instance.\n#\n# Via the LATENCY command this information is available to the user that can\n# print graphs and obtain reports.\n#\n# The system only logs operations that were performed in a time equal or\n# greater than the amount of milliseconds specified via the\n# latency-monitor-threshold configuration directive. When its value is set\n# to zero, the latency monitor is turned off.\n#\n# By default latency monitoring is disabled since it is mostly not needed\n# if you don't have latency issues, and collecting data has a performance\n# impact, that while very small, can be measured under big load. Latency\n# monitoring can easily be enabled at runtime using the command\n# \"CONFIG SET latency-monitor-threshold <milliseconds>\" if needed.\nlatency-monitor-threshold 0\n\n############################# EVENT NOTIFICATION ##############################\n\n# Redis can notify Pub/Sub clients about events happening in the key space.\n# This feature is documented at http://redis.io/topics/notifications\n#\n# For instance if keyspace events notification is enabled, and a client\n# performs a DEL operation on key \"foo\" stored in the Database 0, two\n# messages will be published via Pub/Sub:\n#\n# PUBLISH __keyspace@0__:foo del\n# PUBLISH __keyevent@0__:del foo\n#\n# It is possible to select the events that Redis will notify among a set\n# of classes. Every class is identified by a single character:\n#\n#  K     Keyspace events, published with __keyspace@<db>__ prefix.\n#  E     Keyevent events, published with __keyevent@<db>__ prefix.\n#  g     Generic commands (non-type specific) like DEL, EXPIRE, RENAME, ...\n#  $     String commands\n#  l     List commands\n#  s     Set commands\n#  h     Hash commands\n#  z     Sorted set commands\n#  x     Expired events (events generated every time a key expires)\n#  e     Evicted events (events generated when a key is evicted for maxmemory)\n#  A     Alias for g$lshzxe, so that the \"AKE\" string means all the events.\n#\n#  The \"notify-keyspace-events\" takes as argument a string that is composed\n#  of zero or multiple characters. The empty string means that notifications\n#  are disabled.\n#\n#  Example: to enable list and generic events, from the point of view of the\n#           event name, use:\n#\n#  notify-keyspace-events Elg\n#\n#  Example 2: to get the stream of the expired keys subscribing to channel\n#             name __keyevent@0__:expired use:\n#\n#  notify-keyspace-events Ex\n#\n#  By default all notifications are disabled because most users don't need\n#  this feature and the feature has some overhead. Note that if you don't\n#  specify at least one of K or E, no events will be delivered.\nnotify-keyspace-events \"\"\n\n############################### ADVANCED CONFIG ###############################\n\n# Hashes are encoded using a memory efficient data structure when they have a\n# small number of entries, and the biggest entry does not exceed a given\n# threshold. These thresholds can be configured using the following directives.\nhash-max-ziplist-entries 512\nhash-max-ziplist-value 64\n\n# Lists are also encoded in a special way to save a lot of space.\n# The number of entries allowed per internal list node can be specified\n# as a fixed maximum size or a maximum number of elements.\n# For a fixed maximum size, use -5 through -1, meaning:\n# -5: max size: 64 Kb  <-- not recommended for normal workloads\n# -4: max size: 32 Kb  <-- not recommended\n# -3: max size: 16 Kb  <-- probably not recommended\n# -2: max size: 8 Kb   <-- good\n# -1: max size: 4 Kb   <-- good\n# Positive numbers mean store up to _exactly_ that number of elements\n# per list node.\n# The highest performing option is usually -2 (8 Kb size) or -1 (4 Kb size),\n# but if your use case is unique, adjust the settings as necessary.\nlist-max-ziplist-size -2\n\n# Lists may also be compressed.\n# Compress depth is the number of quicklist ziplist nodes from *each* side of\n# the list to *exclude* from compression.  The head and tail of the list\n# are always uncompressed for fast push/pop operations.  Settings are:\n# 0: disable all list compression\n# 1: depth 1 means \"don't start compressing until after 1 node into the list,\n#    going from either the head or tail\"\n#    So: [head]->node->node->...->node->[tail]\n#    [head], [tail] will always be uncompressed; inner nodes will compress.\n# 2: [head]->[next]->node->node->...->node->[prev]->[tail]\n#    2 here means: don't compress head or head->next or tail->prev or tail,\n#    but compress all nodes between them.\n# 3: [head]->[next]->[next]->node->node->...->node->[prev]->[prev]->[tail]\n# etc.\nlist-compress-depth 0\n\n# Sets have a special encoding in just one case: when a set is composed\n# of just strings that happen to be integers in radix 10 in the range\n# of 64 bit signed integers.\n# The following configuration setting sets the limit in the size of the\n# set in order to use this special memory saving encoding.\nset-max-intset-entries 512\n\n# Similarly to hashes and lists, sorted sets are also specially encoded in\n# order to save a lot of space. This encoding is only used when the length and\n# elements of a sorted set are below the following limits:\nzset-max-ziplist-entries 128\nzset-max-ziplist-value 64\n\n# HyperLogLog sparse representation bytes limit. The limit includes the\n# 16 bytes header. When an HyperLogLog using the sparse representation crosses\n# this limit, it is converted into the dense representation.\n#\n# A value greater than 16000 is totally useless, since at that point the\n# dense representation is more memory efficient.\n#\n# The suggested value is ~ 3000 in order to have the benefits of\n# the space efficient encoding without slowing down too much PFADD,\n# which is O(N) with the sparse encoding. The value can be raised to\n# ~ 10000 when CPU is not a concern, but space is, and the data set is\n# composed of many HyperLogLogs with cardinality in the 0 - 15000 range.\nhll-sparse-max-bytes 3000\n\n# Active rehashing uses 1 millisecond every 100 milliseconds of CPU time in\n# order to help rehashing the main Redis hash table (the one mapping top-level\n# keys to values). The hash table implementation Redis uses (see dict.c)\n# performs a lazy rehashing: the more operation you run into a hash table\n# that is rehashing, the more rehashing \"steps\" are performed, so if the\n# server is idle the rehashing is never complete and some more memory is used\n# by the hash table.\n#\n# The default is to use this millisecond 10 times every second in order to\n# actively rehash the main dictionaries, freeing memory when possible.\n#\n# If unsure:\n# use \"activerehashing no\" if you have hard latency requirements and it is\n# not a good thing in your environment that Redis can reply from time to time\n# to queries with 2 milliseconds delay.\n#\n# use \"activerehashing yes\" if you don't have such hard requirements but\n# want to free memory asap when possible.\nactiverehashing yes\n\n# The client output buffer limits can be used to force disconnection of clients\n# that are not reading data from the server fast enough for some reason (a\n# common reason is that a Pub/Sub client can't consume messages as fast as the\n# publisher can produce them).\n#\n# The limit can be set differently for the three different classes of clients:\n#\n# normal -> normal clients including MONITOR clients\n# slave  -> slave clients\n# pubsub -> clients subscribed to at least one pubsub channel or pattern\n#\n# The syntax of every client-output-buffer-limit directive is the following:\n#\n# client-output-buffer-limit <class> <hard limit> <soft limit> <soft seconds>\n#\n# A client is immediately disconnected once the hard limit is reached, or if\n# the soft limit is reached and remains reached for the specified number of\n# seconds (continuously).\n# So for instance if the hard limit is 32 megabytes and the soft limit is\n# 16 megabytes / 10 seconds, the client will get disconnected immediately\n# if the size of the output buffers reach 32 megabytes, but will also get\n# disconnected if the client reaches 16 megabytes and continuously overcomes\n# the limit for 10 seconds.\n#\n# By default normal clients are not limited because they don't receive data\n# without asking (in a push way), but just after a request, so only\n# asynchronous clients may create a scenario where data is requested faster\n# than it can read.\n#\n# Instead there is a default limit for pubsub and slave clients, since\n# subscribers and slaves receive data in a push fashion.\n#\n# Both the hard or the soft limit can be disabled by setting them to zero.\nclient-output-buffer-limit normal 0 0 0\nclient-output-buffer-limit slave 256mb 64mb 60\nclient-output-buffer-limit pubsub 32mb 8mb 60\n\n# Redis calls an internal function to perform many background tasks, like\n# closing connections of clients in timeout, purging expired keys that are\n# never requested, and so forth.\n#\n# Not all tasks are performed with the same frequency, but Redis checks for\n# tasks to perform according to the specified \"hz\" value.\n#\n# By default \"hz\" is set to 10. Raising the value will use more CPU when\n# Redis is idle, but at the same time will make Redis more responsive when\n# there are many keys expiring at the same time, and timeouts may be\n# handled with more precision.\n#\n# The range is between 1 and 500, however a value over 100 is usually not\n# a good idea. Most users should use the default of 10 and raise this up to\n# 100 only in environments where very low latency is required.\nhz 10\n\n# When a child rewrites the AOF file, if the following option is enabled\n# the file will be fsync-ed every 32 MB of data generated. This is useful\n# in order to commit the file to the disk more incrementally and avoid\n# big latency spikes.\naof-rewrite-incremental-fsync yes\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.8/runtest",
    "content": "#!/bin/sh\nTCL_VERSIONS=\"8.5 8.6\"\nTCLSH=\"\"\n\nfor VERSION in $TCL_VERSIONS; do\n\tTCL=`which tclsh$VERSION 2>/dev/null` && TCLSH=$TCL\ndone\n\nif [ -z $TCLSH ]\nthen\n    echo \"You need tcl 8.5 or newer in order to run the Redis test\"\n    exit 1\nfi\n$TCLSH tests/test_helper.tcl $*\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.8/runtest-cluster",
    "content": "#!/bin/sh\nTCL_VERSIONS=\"8.5 8.6\"\nTCLSH=\"\"\n\nfor VERSION in $TCL_VERSIONS; do\n\tTCL=`which tclsh$VERSION 2>/dev/null` && TCLSH=$TCL\ndone\n\nif [ -z $TCLSH ]\nthen\n    echo \"You need tcl 8.5 or newer in order to run the Redis Sentinel test\"\n    exit 1\nfi\n$TCLSH tests/cluster/run.tcl $*\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.8/runtest-sentinel",
    "content": "#!/bin/sh\nTCL_VERSIONS=\"8.5 8.6\"\nTCLSH=\"\"\n\nfor VERSION in $TCL_VERSIONS; do\n\tTCL=`which tclsh$VERSION 2>/dev/null` && TCLSH=$TCL\ndone\n\nif [ -z $TCLSH ]\nthen\n    echo \"You need tcl 8.5 or newer in order to run the Redis Sentinel test\"\n    exit 1\nfi\n$TCLSH tests/sentinel/run.tcl $*\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.8/sentinel.conf",
    "content": "# Example sentinel.conf\n\n# *** IMPORTANT ***\n#\n# By default Sentinel will not be reachable from interfaces different than\n# localhost, either use the 'bind' directive to bind to a list of network\n# interfaces, or disable protected mode with \"protected-mode no\" by\n# adding it to this configuration file.\n#\n# Before doing that MAKE SURE the instance is protected from the outside\n# world via firewalling or other means.\n#\n# For example you may use one of the following:\n#\n# bind 127.0.0.1 192.168.1.1\n#\n# protected-mode no\n\n# port <sentinel-port>\n# The port that this sentinel instance will run on\nport 26379\n\n# sentinel announce-ip <ip>\n# sentinel announce-port <port>\n#\n# The above two configuration directives are useful in environments where,\n# because of NAT, Sentinel is reachable from outside via a non-local address.\n#\n# When announce-ip is provided, the Sentinel will claim the specified IP address\n# in HELLO messages used to gossip its presence, instead of auto-detecting the\n# local address as it usually does.\n#\n# Similarly when announce-port is provided and is valid and non-zero, Sentinel\n# will announce the specified TCP port.\n#\n# The two options don't need to be used together, if only announce-ip is\n# provided, the Sentinel will announce the specified IP and the server port\n# as specified by the \"port\" option. If only announce-port is provided, the\n# Sentinel will announce the auto-detected local IP and the specified port.\n#\n# Example:\n#\n# sentinel announce-ip 1.2.3.4\n\n# dir <working-directory>\n# Every long running process should have a well-defined working directory.\n# For Redis Sentinel to chdir to /tmp at startup is the simplest thing\n# for the process to don't interfere with administrative tasks such as\n# unmounting filesystems.\ndir /tmp\n\n# sentinel monitor <master-name> <ip> <redis-port> <quorum>\n#\n# Tells Sentinel to monitor this master, and to consider it in O_DOWN\n# (Objectively Down) state only if at least <quorum> sentinels agree.\n#\n# Note that whatever is the ODOWN quorum, a Sentinel will require to\n# be elected by the majority of the known Sentinels in order to\n# start a failover, so no failover can be performed in minority.\n#\n# Slaves are auto-discovered, so you don't need to specify slaves in\n# any way. Sentinel itself will rewrite this configuration file adding\n# the slaves using additional configuration options.\n# Also note that the configuration file is rewritten when a\n# slave is promoted to master.\n#\n# Note: master name should not include special characters or spaces.\n# The valid charset is A-z 0-9 and the three characters \".-_\".\nsentinel monitor mymaster 127.0.0.1 6379 2\n\n# sentinel auth-pass <master-name> <password>\n#\n# Set the password to use to authenticate with the master and slaves.\n# Useful if there is a password set in the Redis instances to monitor.\n#\n# Note that the master password is also used for slaves, so it is not\n# possible to set a different password in masters and slaves instances\n# if you want to be able to monitor these instances with Sentinel.\n#\n# However you can have Redis instances without the authentication enabled\n# mixed with Redis instances requiring the authentication (as long as the\n# password set is the same for all the instances requiring the password) as\n# the AUTH command will have no effect in Redis instances with authentication\n# switched off.\n#\n# Example:\n#\n# sentinel auth-pass mymaster MySUPER--secret-0123passw0rd\n\n# sentinel down-after-milliseconds <master-name> <milliseconds>\n#\n# Number of milliseconds the master (or any attached slave or sentinel) should\n# be unreachable (as in, not acceptable reply to PING, continuously, for the\n# specified period) in order to consider it in S_DOWN state (Subjectively\n# Down).\n#\n# Default is 30 seconds.\nsentinel down-after-milliseconds mymaster 30000\n\n# sentinel parallel-syncs <master-name> <numslaves>\n#\n# How many slaves we can reconfigure to point to the new slave simultaneously\n# during the failover. Use a low number if you use the slaves to serve query\n# to avoid that all the slaves will be unreachable at about the same\n# time while performing the synchronization with the master.\nsentinel parallel-syncs mymaster 1\n\n# sentinel failover-timeout <master-name> <milliseconds>\n#\n# Specifies the failover timeout in milliseconds. It is used in many ways:\n#\n# - The time needed to re-start a failover after a previous failover was\n#   already tried against the same master by a given Sentinel, is two\n#   times the failover timeout.\n#\n# - The time needed for a slave replicating to a wrong master according\n#   to a Sentinel current configuration, to be forced to replicate\n#   with the right master, is exactly the failover timeout (counting since\n#   the moment a Sentinel detected the misconfiguration).\n#\n# - The time needed to cancel a failover that is already in progress but\n#   did not produced any configuration change (SLAVEOF NO ONE yet not\n#   acknowledged by the promoted slave).\n#\n# - The maximum time a failover in progress waits for all the slaves to be\n#   reconfigured as slaves of the new master. However even after this time\n#   the slaves will be reconfigured by the Sentinels anyway, but not with\n#   the exact parallel-syncs progression as specified.\n#\n# Default is 3 minutes.\nsentinel failover-timeout mymaster 180000\n\n# SCRIPTS EXECUTION\n#\n# sentinel notification-script and sentinel reconfig-script are used in order\n# to configure scripts that are called to notify the system administrator\n# or to reconfigure clients after a failover. The scripts are executed\n# with the following rules for error handling:\n#\n# If script exits with \"1\" the execution is retried later (up to a maximum\n# number of times currently set to 10).\n#\n# If script exits with \"2\" (or an higher value) the script execution is\n# not retried.\n#\n# If script terminates because it receives a signal the behavior is the same\n# as exit code 1.\n#\n# A script has a maximum running time of 60 seconds. After this limit is\n# reached the script is terminated with a SIGKILL and the execution retried.\n\n# NOTIFICATION SCRIPT\n#\n# sentinel notification-script <master-name> <script-path>\n# \n# Call the specified notification script for any sentinel event that is\n# generated in the WARNING level (for instance -sdown, -odown, and so forth).\n# This script should notify the system administrator via email, SMS, or any\n# other messaging system, that there is something wrong with the monitored\n# Redis systems.\n#\n# The script is called with just two arguments: the first is the event type\n# and the second the event description.\n#\n# The script must exist and be executable in order for sentinel to start if\n# this option is provided.\n#\n# Example:\n#\n# sentinel notification-script mymaster /var/redis/notify.sh\n\n# CLIENTS RECONFIGURATION SCRIPT\n#\n# sentinel client-reconfig-script <master-name> <script-path>\n#\n# When the master changed because of a failover a script can be called in\n# order to perform application-specific tasks to notify the clients that the\n# configuration has changed and the master is at a different address.\n# \n# The following arguments are passed to the script:\n#\n# <master-name> <role> <state> <from-ip> <from-port> <to-ip> <to-port>\n#\n# <state> is currently always \"failover\"\n# <role> is either \"leader\" or \"observer\"\n# \n# The arguments from-ip, from-port, to-ip, to-port are used to communicate\n# the old address of the master and the new address of the elected slave\n# (now a master).\n#\n# This script should be resistant to multiple invocations.\n#\n# Example:\n#\n# sentinel client-reconfig-script mymaster /var/redis/reconfig.sh\n\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.8/src/.gitignore",
    "content": "*.gcda\n*.gcno\n*.gcov\nredis.info\nlcov-html\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.8/src/Makefile",
    "content": "# Redis Makefile\n# Copyright (C) 2009 Salvatore Sanfilippo <antirez at gmail dot com>\n# This file is released under the BSD license, see the COPYING file\n#\n# The Makefile composes the final FINAL_CFLAGS and FINAL_LDFLAGS using\n# what is needed for Redis plus the standard CFLAGS and LDFLAGS passed.\n# However when building the dependencies (Jemalloc, Lua, Hiredis, ...)\n# CFLAGS and LDFLAGS are propagated to the dependencies, so to pass\n# flags only to be used when compiling / linking Redis itself REDIS_CFLAGS\n# and REDIS_LDFLAGS are used instead (this is the case of 'make gcov').\n#\n# Dependencies are stored in the Makefile.dep file. To rebuild this file\n# Just use 'make dep', but this is only needed by developers.\n\nrelease_hdr := $(shell sh -c './mkreleasehdr.sh')\nuname_S := $(shell sh -c 'uname -s 2>/dev/null || echo not')\nOPTIMIZATION?=-O2\nDEPENDENCY_TARGETS=hiredis linenoise lua geohash-int\n\n# Default settings\nSTD=-std=c99 -pedantic -DREDIS_STATIC=''\nWARN=-Wall -W\nOPT=$(OPTIMIZATION)\n\nPREFIX?=/usr/local\nINSTALL_BIN=$(PREFIX)/bin\nINSTALL=install\n\n# Default allocator\nifeq ($(uname_S),Linux)\n\tMALLOC=jemalloc\nelse\n\tMALLOC=libc\nendif\n\n# Backwards compatibility for selecting an allocator\nifeq ($(USE_TCMALLOC),yes)\n\tMALLOC=tcmalloc\nendif\n\nifeq ($(USE_TCMALLOC_MINIMAL),yes)\n\tMALLOC=tcmalloc_minimal\nendif\n\nifeq ($(USE_JEMALLOC),yes)\n\tMALLOC=jemalloc\nendif\n\nifeq ($(USE_JEMALLOC),no)\n\tMALLOC=libc\nendif\n\n# Override default settings if possible\n-include .make-settings\n\nFINAL_CFLAGS=$(STD) $(WARN) $(OPT) $(DEBUG) $(CFLAGS) $(REDIS_CFLAGS) -I../deps/geohash-int\nFINAL_LDFLAGS=$(LDFLAGS) $(REDIS_LDFLAGS) $(DEBUG)\nFINAL_LIBS=-lm\nDEBUG=-g -ggdb\n\nifeq ($(uname_S),SunOS)\n\t# SunOS\n\tINSTALL=cp -pf\n\tFINAL_CFLAGS+= -D__EXTENSIONS__ -D_XPG6\n\tFINAL_LIBS+= -ldl -lnsl -lsocket -lresolv -lpthread -lrt\nelse\nifeq ($(uname_S),Darwin)\n\t# Darwin\n\tFINAL_LIBS+= -ldl\nelse\nifeq ($(uname_S),AIX)\n        # AIX\n        FINAL_LDFLAGS+= -Wl,-bexpall\n        FINAL_LIBS+=-ldl -pthread -lcrypt -lbsd\nelse\nifeq ($(uname_S),OpenBSD)\n\t# OpenBSD\n\tFINAL_LIBS+= -lpthread\nelse\nifeq ($(uname_S),FreeBSD)\n\t# FreeBSD\n\tFINAL_LIBS+= -lpthread\nelse\n\t# All the other OSes (notably Linux)\n\tFINAL_LDFLAGS+= -rdynamic\n\tFINAL_LIBS+=-ldl -pthread\nendif\nendif\nendif\nendif\nendif\n# Include paths to dependencies\nFINAL_CFLAGS+= -I../deps/hiredis -I../deps/linenoise -I../deps/lua/src\n\nifeq ($(MALLOC),tcmalloc)\n\tFINAL_CFLAGS+= -DUSE_TCMALLOC\n\tFINAL_LIBS+= -ltcmalloc\nendif\n\nifeq ($(MALLOC),tcmalloc_minimal)\n\tFINAL_CFLAGS+= -DUSE_TCMALLOC\n\tFINAL_LIBS+= -ltcmalloc_minimal\nendif\n\nifeq ($(MALLOC),jemalloc)\n\tDEPENDENCY_TARGETS+= jemalloc\n\tFINAL_CFLAGS+= -DUSE_JEMALLOC -I../deps/jemalloc/include\n\tFINAL_LIBS+= ../deps/jemalloc/lib/libjemalloc.a -lrt\nendif\n\nREDIS_CC=$(QUIET_CC)$(CC) $(FINAL_CFLAGS)\nREDIS_LD=$(QUIET_LINK)$(CC) $(FINAL_LDFLAGS)\nREDIS_INSTALL=$(QUIET_INSTALL)$(INSTALL)\n\nCCCOLOR=\"\\033[34m\"\nLINKCOLOR=\"\\033[34;1m\"\nSRCCOLOR=\"\\033[33m\"\nBINCOLOR=\"\\033[37;1m\"\nMAKECOLOR=\"\\033[32;1m\"\nENDCOLOR=\"\\033[0m\"\n\nifndef V\nQUIET_CC = @printf '    %b %b\\n' $(CCCOLOR)CC$(ENDCOLOR) $(SRCCOLOR)$@$(ENDCOLOR) 1>&2;\nQUIET_LINK = @printf '    %b %b\\n' $(LINKCOLOR)LINK$(ENDCOLOR) $(BINCOLOR)$@$(ENDCOLOR) 1>&2;\nQUIET_INSTALL = @printf '    %b %b\\n' $(LINKCOLOR)INSTALL$(ENDCOLOR) $(BINCOLOR)$@$(ENDCOLOR) 1>&2;\nendif\n\nREDIS_SERVER_NAME=redis-server\nREDIS_SENTINEL_NAME=redis-sentinel\nREDIS_SERVER_OBJ=adlist.o quicklist.o ae.o anet.o dict.o server.o sds.o zmalloc.o lzf_c.o lzf_d.o pqsort.o zipmap.o sha1.o ziplist.o release.o networking.o util.o object.o db.o replication.o rdb.o t_string.o t_list.o t_set.o t_zset.o t_hash.o config.o aof.o pubsub.o multi.o debug.o sort.o intset.o syncio.o cluster.o crc16.o endianconv.o slowlog.o scripting.o bio.o rio.o rand.o memtest.o crc64.o bitops.o sentinel.o notify.o setproctitle.o blocked.o hyperloglog.o latency.o sparkline.o redis-check-rdb.o geo.o slots.o slots_async.o crc32.o\nREDIS_GEOHASH_OBJ=../deps/geohash-int/geohash.o ../deps/geohash-int/geohash_helper.o\nREDIS_CLI_NAME=redis-cli\nREDIS_CLI_OBJ=anet.o adlist.o redis-cli.o zmalloc.o release.o anet.o ae.o crc64.o\nREDIS_BENCHMARK_NAME=redis-benchmark\nREDIS_BENCHMARK_OBJ=ae.o anet.o redis-benchmark.o adlist.o zmalloc.o redis-benchmark.o\nREDIS_CHECK_RDB_NAME=redis-check-rdb\nREDIS_CHECK_AOF_NAME=redis-check-aof\nREDIS_CHECK_AOF_OBJ=redis-check-aof.o\n\nall: $(REDIS_SERVER_NAME) $(REDIS_SENTINEL_NAME) $(REDIS_CLI_NAME) $(REDIS_BENCHMARK_NAME) $(REDIS_CHECK_RDB_NAME) $(REDIS_CHECK_AOF_NAME)\n\t@echo \"\"\n\t@echo \"Hint: It's a good idea to run 'make test' ;)\"\n\t@echo \"\"\n\n.PHONY: all\n\n# Deps (use make dep to generate this)\ninclude Makefile.dep\n\ndep:\n\t$(REDIS_CC) -MM *.c > Makefile.dep\n\n.PHONY: dep\n\npersist-settings: distclean\n\techo STD=$(STD) >> .make-settings\n\techo WARN=$(WARN) >> .make-settings\n\techo OPT=$(OPT) >> .make-settings\n\techo MALLOC=$(MALLOC) >> .make-settings\n\techo CFLAGS=$(CFLAGS) >> .make-settings\n\techo LDFLAGS=$(LDFLAGS) >> .make-settings\n\techo REDIS_CFLAGS=$(REDIS_CFLAGS) >> .make-settings\n\techo REDIS_LDFLAGS=$(REDIS_LDFLAGS) >> .make-settings\n\techo PREV_FINAL_CFLAGS=$(FINAL_CFLAGS) >> .make-settings\n\techo PREV_FINAL_LDFLAGS=$(FINAL_LDFLAGS) >> .make-settings\n\t-(cd ../deps && $(MAKE) $(DEPENDENCY_TARGETS))\n\n.PHONY: persist-settings\n\n# Prerequisites target\n.make-prerequisites:\n\t@touch $@\n\n# Clean everything, persist settings and build dependencies if anything changed\nifneq ($(strip $(PREV_FINAL_CFLAGS)), $(strip $(FINAL_CFLAGS)))\n.make-prerequisites: persist-settings\nendif\n\nifneq ($(strip $(PREV_FINAL_LDFLAGS)), $(strip $(FINAL_LDFLAGS)))\n.make-prerequisites: persist-settings\nendif\n\n# redis-server\n$(REDIS_SERVER_NAME): $(REDIS_SERVER_OBJ)\n\t$(REDIS_LD) -o $@ $^ ../deps/hiredis/libhiredis.a ../deps/lua/src/liblua.a $(REDIS_GEOHASH_OBJ) $(FINAL_LIBS)\n\n# redis-sentinel\n$(REDIS_SENTINEL_NAME): $(REDIS_SERVER_NAME)\n\t$(REDIS_INSTALL) $(REDIS_SERVER_NAME) $(REDIS_SENTINEL_NAME)\n\n# redis-check-rdb\n$(REDIS_CHECK_RDB_NAME): $(REDIS_SERVER_NAME)\n\t$(REDIS_INSTALL) $(REDIS_SERVER_NAME) $(REDIS_CHECK_RDB_NAME)\n\n# redis-cli\n$(REDIS_CLI_NAME): $(REDIS_CLI_OBJ)\n\t$(REDIS_LD) -o $@ $^ ../deps/hiredis/libhiredis.a ../deps/linenoise/linenoise.o $(FINAL_LIBS)\n\n# redis-benchmark\n$(REDIS_BENCHMARK_NAME): $(REDIS_BENCHMARK_OBJ)\n\t$(REDIS_LD) -o $@ $^ ../deps/hiredis/libhiredis.a $(FINAL_LIBS)\n\n# redis-check-aof\n$(REDIS_CHECK_AOF_NAME): $(REDIS_CHECK_AOF_OBJ)\n\t$(REDIS_LD) -o $@ $^ $(FINAL_LIBS)\n\n# Because the jemalloc.h header is generated as a part of the jemalloc build,\n# building it should complete before building any other object. Instead of\n# depending on a single artifact, build all dependencies first.\n%.o: %.c .make-prerequisites\n\t$(REDIS_CC) -c $<\n\nclean:\n\trm -rf $(REDIS_SERVER_NAME) $(REDIS_SENTINEL_NAME) $(REDIS_CLI_NAME) $(REDIS_BENCHMARK_NAME) $(REDIS_CHECK_RDB_NAME) $(REDIS_CHECK_AOF_NAME) *.o *.gcda *.gcno *.gcov redis.info lcov-html\n\n.PHONY: clean\n\ndistclean: clean\n\t-(cd ../deps && $(MAKE) distclean)\n\t-(rm -f .make-*)\n\n.PHONY: distclean\n\ntest: $(REDIS_SERVER_NAME) $(REDIS_CHECK_AOF_NAME)\n\t@(cd ..; ./runtest)\n\ntest-sentinel: $(REDIS_SENTINEL_NAME)\n\t@(cd ..; ./runtest-sentinel)\n\ncheck: test\n\nlcov:\n\t$(MAKE) gcov\n\t@(set -e; cd ..; ./runtest --clients 1)\n\t@geninfo -o redis.info .\n\t@genhtml --legend -o lcov-html redis.info\n\ntest-sds: sds.c sds.h\n\t$(REDIS_CC) sds.c zmalloc.c -DSDS_TEST_MAIN -o /tmp/sds_test\n\t/tmp/sds_test\n\n.PHONY: lcov\n\nbench: $(REDIS_BENCHMARK_NAME)\n\t./$(REDIS_BENCHMARK_NAME)\n\n32bit:\n\t@echo \"\"\n\t@echo \"WARNING: if it fails under Linux you probably need to install libc6-dev-i386\"\n\t@echo \"\"\n\t$(MAKE) CFLAGS=\"-m32\" LDFLAGS=\"-m32\"\n\ngcov:\n\t$(MAKE) REDIS_CFLAGS=\"-fprofile-arcs -ftest-coverage -DCOVERAGE_TEST\" REDIS_LDFLAGS=\"-fprofile-arcs -ftest-coverage\"\n\nnoopt:\n\t$(MAKE) OPTIMIZATION=\"-O0\"\n\nvalgrind:\n\t$(MAKE) OPTIMIZATION=\"-O0\" MALLOC=\"libc\"\n\nsrc/help.h:\n\t@../utils/generate-command-help.rb > help.h\n\ninstall: all\n\t@mkdir -p $(INSTALL_BIN)\n\t$(REDIS_INSTALL) $(REDIS_SERVER_NAME) $(INSTALL_BIN)\n\t$(REDIS_INSTALL) $(REDIS_BENCHMARK_NAME) $(INSTALL_BIN)\n\t$(REDIS_INSTALL) $(REDIS_CLI_NAME) $(INSTALL_BIN)\n\t$(REDIS_INSTALL) $(REDIS_CHECK_RDB_NAME) $(INSTALL_BIN)\n\t$(REDIS_INSTALL) $(REDIS_CHECK_AOF_NAME) $(INSTALL_BIN)\n\t@ln -sf $(REDIS_SERVER_NAME) $(INSTALL_BIN)/$(REDIS_SENTINEL_NAME)\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.8/src/Makefile.dep",
    "content": "adlist.o: adlist.c adlist.h zmalloc.h\nae.o: ae.c ae.h zmalloc.h config.h ae_kqueue.c ae_epoll.c ae_select.c ae_evport.c\nae_epoll.o: ae_epoll.c\nae_evport.o: ae_evport.c\nae_kqueue.o: ae_kqueue.c\nae_select.o: ae_select.c\nanet.o: anet.c fmacros.h anet.h\naof.o: aof.c server.h fmacros.h config.h solarisfixes.h \\\n ../deps/lua/src/lua.h ../deps/lua/src/luaconf.h ae.h sds.h dict.h \\\n adlist.h zmalloc.h anet.h ziplist.h intset.h version.h util.h latency.h \\\n sparkline.h quicklist.h zipmap.h sha1.h endianconv.h crc64.h rdb.h rio.h \\\n bio.h\nbio.o: bio.c server.h fmacros.h config.h solarisfixes.h \\\n ../deps/lua/src/lua.h ../deps/lua/src/luaconf.h ae.h sds.h dict.h \\\n adlist.h zmalloc.h anet.h ziplist.h intset.h version.h util.h latency.h \\\n sparkline.h quicklist.h zipmap.h sha1.h endianconv.h crc64.h rdb.h rio.h \\\n bio.h\nbitops.o: bitops.c server.h fmacros.h config.h solarisfixes.h \\\n ../deps/lua/src/lua.h ../deps/lua/src/luaconf.h ae.h sds.h dict.h \\\n adlist.h zmalloc.h anet.h ziplist.h intset.h version.h util.h latency.h \\\n sparkline.h quicklist.h zipmap.h sha1.h endianconv.h crc64.h rdb.h rio.h\nblocked.o: blocked.c server.h fmacros.h config.h solarisfixes.h \\\n ../deps/lua/src/lua.h ../deps/lua/src/luaconf.h ae.h sds.h dict.h \\\n adlist.h zmalloc.h anet.h ziplist.h intset.h version.h util.h latency.h \\\n sparkline.h quicklist.h zipmap.h sha1.h endianconv.h crc64.h rdb.h rio.h\ncluster.o: cluster.c server.h fmacros.h config.h solarisfixes.h \\\n ../deps/lua/src/lua.h ../deps/lua/src/luaconf.h ae.h sds.h dict.h \\\n adlist.h zmalloc.h anet.h ziplist.h intset.h version.h util.h latency.h \\\n sparkline.h quicklist.h zipmap.h sha1.h endianconv.h crc64.h rdb.h rio.h \\\n cluster.h\nconfig.o: config.c server.h fmacros.h config.h solarisfixes.h \\\n ../deps/lua/src/lua.h ../deps/lua/src/luaconf.h ae.h sds.h dict.h \\\n adlist.h zmalloc.h anet.h ziplist.h intset.h version.h util.h latency.h \\\n sparkline.h quicklist.h zipmap.h sha1.h endianconv.h crc64.h rdb.h rio.h \\\n cluster.h\ncrc16.o: crc16.c server.h fmacros.h config.h solarisfixes.h \\\n ../deps/lua/src/lua.h ../deps/lua/src/luaconf.h ae.h sds.h dict.h \\\n adlist.h zmalloc.h anet.h ziplist.h intset.h version.h util.h latency.h \\\n sparkline.h quicklist.h zipmap.h sha1.h endianconv.h crc64.h rdb.h rio.h\ncrc64.o: crc64.c\ndb.o: db.c server.h fmacros.h config.h solarisfixes.h \\\n ../deps/lua/src/lua.h ../deps/lua/src/luaconf.h ae.h sds.h dict.h \\\n adlist.h zmalloc.h anet.h ziplist.h intset.h version.h util.h latency.h \\\n sparkline.h quicklist.h zipmap.h sha1.h endianconv.h crc64.h rdb.h rio.h \\\n cluster.h\ndebug.o: debug.c server.h fmacros.h config.h solarisfixes.h \\\n ../deps/lua/src/lua.h ../deps/lua/src/luaconf.h ae.h sds.h dict.h \\\n adlist.h zmalloc.h anet.h ziplist.h intset.h version.h util.h latency.h \\\n sparkline.h quicklist.h zipmap.h sha1.h endianconv.h crc64.h rdb.h rio.h \\\n bio.h\ndict.o: dict.c fmacros.h dict.h zmalloc.h redisassert.h\nendianconv.o: endianconv.c\ngeo.o: geo.c geo.h server.h fmacros.h config.h solarisfixes.h \\\n ../deps/lua/src/lua.h ../deps/lua/src/luaconf.h ae.h sds.h dict.h \\\n adlist.h zmalloc.h anet.h ziplist.h intset.h version.h util.h latency.h \\\n sparkline.h quicklist.h zipmap.h sha1.h endianconv.h crc64.h rdb.h rio.h \\\n ../deps/geohash-int/geohash_helper.h ../deps/geohash-int/geohash.h\nhyperloglog.o: hyperloglog.c server.h fmacros.h config.h solarisfixes.h \\\n ../deps/lua/src/lua.h ../deps/lua/src/luaconf.h ae.h sds.h dict.h \\\n adlist.h zmalloc.h anet.h ziplist.h intset.h version.h util.h latency.h \\\n sparkline.h quicklist.h zipmap.h sha1.h endianconv.h crc64.h rdb.h rio.h\nintset.o: intset.c intset.h zmalloc.h endianconv.h config.h\nlatency.o: latency.c server.h fmacros.h config.h solarisfixes.h \\\n ../deps/lua/src/lua.h ../deps/lua/src/luaconf.h ae.h sds.h dict.h \\\n adlist.h zmalloc.h anet.h ziplist.h intset.h version.h util.h latency.h \\\n sparkline.h quicklist.h zipmap.h sha1.h endianconv.h crc64.h rdb.h rio.h\nlzf_c.o: lzf_c.c lzfP.h\nlzf_d.o: lzf_d.c lzfP.h\nmemtest.o: memtest.c config.h\ncrc32.o: crc32.c\nslots.o: slots.c server.h\nmulti.o: multi.c server.h fmacros.h config.h solarisfixes.h \\\n ../deps/lua/src/lua.h ../deps/lua/src/luaconf.h ae.h sds.h dict.h \\\n adlist.h zmalloc.h anet.h ziplist.h intset.h version.h util.h latency.h \\\n sparkline.h quicklist.h zipmap.h sha1.h endianconv.h crc64.h rdb.h rio.h\nnetworking.o: networking.c server.h fmacros.h config.h solarisfixes.h \\\n ../deps/lua/src/lua.h ../deps/lua/src/luaconf.h ae.h sds.h dict.h \\\n adlist.h zmalloc.h anet.h ziplist.h intset.h version.h util.h latency.h \\\n sparkline.h quicklist.h zipmap.h sha1.h endianconv.h crc64.h rdb.h rio.h\nnotify.o: notify.c server.h fmacros.h config.h solarisfixes.h \\\n ../deps/lua/src/lua.h ../deps/lua/src/luaconf.h ae.h sds.h dict.h \\\n adlist.h zmalloc.h anet.h ziplist.h intset.h version.h util.h latency.h \\\n sparkline.h quicklist.h zipmap.h sha1.h endianconv.h crc64.h rdb.h rio.h\nobject.o: object.c server.h fmacros.h config.h solarisfixes.h \\\n ../deps/lua/src/lua.h ../deps/lua/src/luaconf.h ae.h sds.h dict.h \\\n adlist.h zmalloc.h anet.h ziplist.h intset.h version.h util.h latency.h \\\n sparkline.h quicklist.h zipmap.h sha1.h endianconv.h crc64.h rdb.h rio.h\npqsort.o: pqsort.c\npubsub.o: pubsub.c server.h fmacros.h config.h solarisfixes.h \\\n ../deps/lua/src/lua.h ../deps/lua/src/luaconf.h ae.h sds.h dict.h \\\n adlist.h zmalloc.h anet.h ziplist.h intset.h version.h util.h latency.h \\\n sparkline.h quicklist.h zipmap.h sha1.h endianconv.h crc64.h rdb.h rio.h\nquicklist.o: quicklist.c quicklist.h zmalloc.h ziplist.h util.h sds.h \\\n lzf.h\nrand.o: rand.c\nrdb.o: rdb.c server.h fmacros.h config.h solarisfixes.h \\\n ../deps/lua/src/lua.h ../deps/lua/src/luaconf.h ae.h sds.h dict.h \\\n adlist.h zmalloc.h anet.h ziplist.h intset.h version.h util.h latency.h \\\n sparkline.h quicklist.h zipmap.h sha1.h endianconv.h crc64.h rdb.h rio.h \\\n lzf.h\nredis-benchmark.o: redis-benchmark.c fmacros.h ../deps/hiredis/sds.h ae.h \\\n ../deps/hiredis/hiredis.h adlist.h zmalloc.h\nredis-check-aof.o: redis-check-aof.c fmacros.h config.h\nredis-check-rdb.o: redis-check-rdb.c server.h fmacros.h config.h \\\n solarisfixes.h ../deps/lua/src/lua.h ../deps/lua/src/luaconf.h ae.h \\\n sds.h dict.h adlist.h zmalloc.h anet.h ziplist.h intset.h version.h \\\n util.h latency.h sparkline.h quicklist.h zipmap.h sha1.h endianconv.h \\\n crc64.h rdb.h rio.h lzf.h\nredis-cli.o: redis-cli.c fmacros.h version.h ../deps/hiredis/hiredis.h \\\n ../deps/hiredis/sds.h zmalloc.h ../deps/linenoise/linenoise.h help.h \\\n anet.h ae.h\nrelease.o: release.c release.h version.h crc64.h\nreplication.o: replication.c server.h fmacros.h config.h solarisfixes.h \\\n ../deps/lua/src/lua.h ../deps/lua/src/luaconf.h ae.h sds.h dict.h \\\n adlist.h zmalloc.h anet.h ziplist.h intset.h version.h util.h latency.h \\\n sparkline.h quicklist.h zipmap.h sha1.h endianconv.h crc64.h rdb.h rio.h\nrio.o: rio.c fmacros.h rio.h sds.h util.h crc64.h config.h server.h \\\n solarisfixes.h ../deps/lua/src/lua.h ../deps/lua/src/luaconf.h ae.h \\\n dict.h adlist.h zmalloc.h anet.h ziplist.h intset.h version.h latency.h \\\n sparkline.h quicklist.h zipmap.h sha1.h endianconv.h rdb.h\nscripting.o: scripting.c server.h fmacros.h config.h solarisfixes.h \\\n ../deps/lua/src/lua.h ../deps/lua/src/luaconf.h ae.h sds.h dict.h \\\n adlist.h zmalloc.h anet.h ziplist.h intset.h version.h util.h latency.h \\\n sparkline.h quicklist.h zipmap.h sha1.h endianconv.h crc64.h rdb.h rio.h \\\n rand.h cluster.h ../deps/lua/src/lauxlib.h ../deps/lua/src/lua.h \\\n ../deps/lua/src/lualib.h\nsds.o: sds.c sds.h sdsalloc.h zmalloc.h\nsentinel.o: sentinel.c server.h fmacros.h config.h solarisfixes.h \\\n ../deps/lua/src/lua.h ../deps/lua/src/luaconf.h ae.h sds.h dict.h \\\n adlist.h zmalloc.h anet.h ziplist.h intset.h version.h util.h latency.h \\\n sparkline.h quicklist.h zipmap.h sha1.h endianconv.h crc64.h rdb.h rio.h \\\n ../deps/hiredis/hiredis.h ../deps/hiredis/async.h \\\n ../deps/hiredis/hiredis.h\nserver.o: server.c server.h fmacros.h config.h solarisfixes.h \\\n ../deps/lua/src/lua.h ../deps/lua/src/luaconf.h ae.h sds.h dict.h \\\n adlist.h zmalloc.h anet.h ziplist.h intset.h version.h util.h latency.h \\\n sparkline.h quicklist.h zipmap.h sha1.h endianconv.h crc64.h rdb.h rio.h \\\n cluster.h slowlog.h bio.h asciilogo.h\nsetproctitle.o: setproctitle.c\nsha1.o: sha1.c solarisfixes.h sha1.h config.h\nslowlog.o: slowlog.c server.h fmacros.h config.h solarisfixes.h \\\n ../deps/lua/src/lua.h ../deps/lua/src/luaconf.h ae.h sds.h dict.h \\\n adlist.h zmalloc.h anet.h ziplist.h intset.h version.h util.h latency.h \\\n sparkline.h quicklist.h zipmap.h sha1.h endianconv.h crc64.h rdb.h rio.h \\\n slowlog.h\nsort.o: sort.c server.h fmacros.h config.h solarisfixes.h \\\n ../deps/lua/src/lua.h ../deps/lua/src/luaconf.h ae.h sds.h dict.h \\\n adlist.h zmalloc.h anet.h ziplist.h intset.h version.h util.h latency.h \\\n sparkline.h quicklist.h zipmap.h sha1.h endianconv.h crc64.h rdb.h rio.h \\\n pqsort.h\nsparkline.o: sparkline.c server.h fmacros.h config.h solarisfixes.h \\\n ../deps/lua/src/lua.h ../deps/lua/src/luaconf.h ae.h sds.h dict.h \\\n adlist.h zmalloc.h anet.h ziplist.h intset.h version.h util.h latency.h \\\n sparkline.h quicklist.h zipmap.h sha1.h endianconv.h crc64.h rdb.h rio.h\nsyncio.o: syncio.c server.h fmacros.h config.h solarisfixes.h \\\n ../deps/lua/src/lua.h ../deps/lua/src/luaconf.h ae.h sds.h dict.h \\\n adlist.h zmalloc.h anet.h ziplist.h intset.h version.h util.h latency.h \\\n sparkline.h quicklist.h zipmap.h sha1.h endianconv.h crc64.h rdb.h rio.h\nt_hash.o: t_hash.c server.h fmacros.h config.h solarisfixes.h \\\n ../deps/lua/src/lua.h ../deps/lua/src/luaconf.h ae.h sds.h dict.h \\\n adlist.h zmalloc.h anet.h ziplist.h intset.h version.h util.h latency.h \\\n sparkline.h quicklist.h zipmap.h sha1.h endianconv.h crc64.h rdb.h rio.h\nt_list.o: t_list.c server.h fmacros.h config.h solarisfixes.h \\\n ../deps/lua/src/lua.h ../deps/lua/src/luaconf.h ae.h sds.h dict.h \\\n adlist.h zmalloc.h anet.h ziplist.h intset.h version.h util.h latency.h \\\n sparkline.h quicklist.h zipmap.h sha1.h endianconv.h crc64.h rdb.h rio.h\nt_set.o: t_set.c server.h fmacros.h config.h solarisfixes.h \\\n ../deps/lua/src/lua.h ../deps/lua/src/luaconf.h ae.h sds.h dict.h \\\n adlist.h zmalloc.h anet.h ziplist.h intset.h version.h util.h latency.h \\\n sparkline.h quicklist.h zipmap.h sha1.h endianconv.h crc64.h rdb.h rio.h\nt_string.o: t_string.c server.h fmacros.h config.h solarisfixes.h \\\n ../deps/lua/src/lua.h ../deps/lua/src/luaconf.h ae.h sds.h dict.h \\\n adlist.h zmalloc.h anet.h ziplist.h intset.h version.h util.h latency.h \\\n sparkline.h quicklist.h zipmap.h sha1.h endianconv.h crc64.h rdb.h rio.h\nt_zset.o: t_zset.c server.h fmacros.h config.h solarisfixes.h \\\n ../deps/lua/src/lua.h ../deps/lua/src/luaconf.h ae.h sds.h dict.h \\\n adlist.h zmalloc.h anet.h ziplist.h intset.h version.h util.h latency.h \\\n sparkline.h quicklist.h zipmap.h sha1.h endianconv.h crc64.h rdb.h rio.h\nutil.o: util.c fmacros.h util.h sds.h sha1.h\nziplist.o: ziplist.c zmalloc.h util.h sds.h ziplist.h endianconv.h \\\n config.h redisassert.h\nzipmap.o: zipmap.c zmalloc.h endianconv.h config.h\nzmalloc.o: zmalloc.c config.h zmalloc.h\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.8/src/adlist.c",
    "content": "/* adlist.c - A generic doubly linked list implementation\n *\n * Copyright (c) 2006-2010, Salvatore Sanfilippo <antirez at gmail dot com>\n * All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions are met:\n *\n *   * Redistributions of source code must retain the above copyright notice,\n *     this list of conditions and the following disclaimer.\n *   * Redistributions in binary form must reproduce the above copyright\n *     notice, this list of conditions and the following disclaimer in the\n *     documentation and/or other materials provided with the distribution.\n *   * Neither the name of Redis nor the names of its contributors may be used\n *     to endorse or promote products derived from this software without\n *     specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\"\n * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\n * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE\n * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR\n * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF\n * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS\n * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN\n * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)\n * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE\n * POSSIBILITY OF SUCH DAMAGE.\n */\n\n\n#include <stdlib.h>\n#include \"adlist.h\"\n#include \"zmalloc.h\"\n\n/* Create a new list. The created list can be freed with\n * AlFreeList(), but private value of every node need to be freed\n * by the user before to call AlFreeList().\n *\n * On error, NULL is returned. Otherwise the pointer to the new list. */\nlist *listCreate(void)\n{\n    struct list *list;\n\n    if ((list = zmalloc(sizeof(*list))) == NULL)\n        return NULL;\n    list->head = list->tail = NULL;\n    list->len = 0;\n    list->dup = NULL;\n    list->free = NULL;\n    list->match = NULL;\n    return list;\n}\n\n/* Free the whole list.\n *\n * This function can't fail. */\nvoid listRelease(list *list)\n{\n    unsigned long len;\n    listNode *current, *next;\n\n    current = list->head;\n    len = list->len;\n    while(len--) {\n        next = current->next;\n        if (list->free) list->free(current->value);\n        zfree(current);\n        current = next;\n    }\n    zfree(list);\n}\n\n/* Add a new node to the list, to head, containing the specified 'value'\n * pointer as value.\n *\n * On error, NULL is returned and no operation is performed (i.e. the\n * list remains unaltered).\n * On success the 'list' pointer you pass to the function is returned. */\nlist *listAddNodeHead(list *list, void *value)\n{\n    listNode *node;\n\n    if ((node = zmalloc(sizeof(*node))) == NULL)\n        return NULL;\n    node->value = value;\n    if (list->len == 0) {\n        list->head = list->tail = node;\n        node->prev = node->next = NULL;\n    } else {\n        node->prev = NULL;\n        node->next = list->head;\n        list->head->prev = node;\n        list->head = node;\n    }\n    list->len++;\n    return list;\n}\n\n/* Add a new node to the list, to tail, containing the specified 'value'\n * pointer as value.\n *\n * On error, NULL is returned and no operation is performed (i.e. the\n * list remains unaltered).\n * On success the 'list' pointer you pass to the function is returned. */\nlist *listAddNodeTail(list *list, void *value)\n{\n    listNode *node;\n\n    if ((node = zmalloc(sizeof(*node))) == NULL)\n        return NULL;\n    node->value = value;\n    if (list->len == 0) {\n        list->head = list->tail = node;\n        node->prev = node->next = NULL;\n    } else {\n        node->prev = list->tail;\n        node->next = NULL;\n        list->tail->next = node;\n        list->tail = node;\n    }\n    list->len++;\n    return list;\n}\n\nlist *listInsertNode(list *list, listNode *old_node, void *value, int after) {\n    listNode *node;\n\n    if ((node = zmalloc(sizeof(*node))) == NULL)\n        return NULL;\n    node->value = value;\n    if (after) {\n        node->prev = old_node;\n        node->next = old_node->next;\n        if (list->tail == old_node) {\n            list->tail = node;\n        }\n    } else {\n        node->next = old_node;\n        node->prev = old_node->prev;\n        if (list->head == old_node) {\n            list->head = node;\n        }\n    }\n    if (node->prev != NULL) {\n        node->prev->next = node;\n    }\n    if (node->next != NULL) {\n        node->next->prev = node;\n    }\n    list->len++;\n    return list;\n}\n\n/* Remove the specified node from the specified list.\n * It's up to the caller to free the private value of the node.\n *\n * This function can't fail. */\nvoid listDelNode(list *list, listNode *node)\n{\n    if (node->prev)\n        node->prev->next = node->next;\n    else\n        list->head = node->next;\n    if (node->next)\n        node->next->prev = node->prev;\n    else\n        list->tail = node->prev;\n    if (list->free) list->free(node->value);\n    zfree(node);\n    list->len--;\n}\n\n/* Returns a list iterator 'iter'. After the initialization every\n * call to listNext() will return the next element of the list.\n *\n * This function can't fail. */\nlistIter *listGetIterator(list *list, int direction)\n{\n    listIter *iter;\n\n    if ((iter = zmalloc(sizeof(*iter))) == NULL) return NULL;\n    if (direction == AL_START_HEAD)\n        iter->next = list->head;\n    else\n        iter->next = list->tail;\n    iter->direction = direction;\n    return iter;\n}\n\n/* Release the iterator memory */\nvoid listReleaseIterator(listIter *iter) {\n    zfree(iter);\n}\n\n/* Create an iterator in the list private iterator structure */\nvoid listRewind(list *list, listIter *li) {\n    li->next = list->head;\n    li->direction = AL_START_HEAD;\n}\n\nvoid listRewindTail(list *list, listIter *li) {\n    li->next = list->tail;\n    li->direction = AL_START_TAIL;\n}\n\n/* Return the next element of an iterator.\n * It's valid to remove the currently returned element using\n * listDelNode(), but not to remove other elements.\n *\n * The function returns a pointer to the next element of the list,\n * or NULL if there are no more elements, so the classical usage patter\n * is:\n *\n * iter = listGetIterator(list,<direction>);\n * while ((node = listNext(iter)) != NULL) {\n *     doSomethingWith(listNodeValue(node));\n * }\n *\n * */\nlistNode *listNext(listIter *iter)\n{\n    listNode *current = iter->next;\n\n    if (current != NULL) {\n        if (iter->direction == AL_START_HEAD)\n            iter->next = current->next;\n        else\n            iter->next = current->prev;\n    }\n    return current;\n}\n\n/* Duplicate the whole list. On out of memory NULL is returned.\n * On success a copy of the original list is returned.\n *\n * The 'Dup' method set with listSetDupMethod() function is used\n * to copy the node value. Otherwise the same pointer value of\n * the original node is used as value of the copied node.\n *\n * The original list both on success or error is never modified. */\nlist *listDup(list *orig)\n{\n    list *copy;\n    listIter iter;\n    listNode *node;\n\n    if ((copy = listCreate()) == NULL)\n        return NULL;\n    copy->dup = orig->dup;\n    copy->free = orig->free;\n    copy->match = orig->match;\n    listRewind(orig, &iter);\n    while((node = listNext(&iter)) != NULL) {\n        void *value;\n\n        if (copy->dup) {\n            value = copy->dup(node->value);\n            if (value == NULL) {\n                listRelease(copy);\n                return NULL;\n            }\n        } else\n            value = node->value;\n        if (listAddNodeTail(copy, value) == NULL) {\n            listRelease(copy);\n            return NULL;\n        }\n    }\n    return copy;\n}\n\n/* Search the list for a node matching a given key.\n * The match is performed using the 'match' method\n * set with listSetMatchMethod(). If no 'match' method\n * is set, the 'value' pointer of every node is directly\n * compared with the 'key' pointer.\n *\n * On success the first matching node pointer is returned\n * (search starts from head). If no matching node exists\n * NULL is returned. */\nlistNode *listSearchKey(list *list, void *key)\n{\n    listIter iter;\n    listNode *node;\n\n    listRewind(list, &iter);\n    while((node = listNext(&iter)) != NULL) {\n        if (list->match) {\n            if (list->match(node->value, key)) {\n                return node;\n            }\n        } else {\n            if (key == node->value) {\n                return node;\n            }\n        }\n    }\n    return NULL;\n}\n\n/* Return the element at the specified zero-based index\n * where 0 is the head, 1 is the element next to head\n * and so on. Negative integers are used in order to count\n * from the tail, -1 is the last element, -2 the penultimate\n * and so on. If the index is out of range NULL is returned. */\nlistNode *listIndex(list *list, long index) {\n    listNode *n;\n\n    if (index < 0) {\n        index = (-index)-1;\n        n = list->tail;\n        while(index-- && n) n = n->prev;\n    } else {\n        n = list->head;\n        while(index-- && n) n = n->next;\n    }\n    return n;\n}\n\n/* Rotate the list removing the tail node and inserting it to the head. */\nvoid listRotate(list *list) {\n    listNode *tail = list->tail;\n\n    if (listLength(list) <= 1) return;\n\n    /* Detach current tail */\n    list->tail = tail->prev;\n    list->tail->next = NULL;\n    /* Move it as head */\n    list->head->prev = tail;\n    tail->prev = NULL;\n    tail->next = list->head;\n    list->head = tail;\n}\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.8/src/adlist.h",
    "content": "/* adlist.h - A generic doubly linked list implementation\n *\n * Copyright (c) 2006-2012, Salvatore Sanfilippo <antirez at gmail dot com>\n * All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions are met:\n *\n *   * Redistributions of source code must retain the above copyright notice,\n *     this list of conditions and the following disclaimer.\n *   * Redistributions in binary form must reproduce the above copyright\n *     notice, this list of conditions and the following disclaimer in the\n *     documentation and/or other materials provided with the distribution.\n *   * Neither the name of Redis nor the names of its contributors may be used\n *     to endorse or promote products derived from this software without\n *     specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\"\n * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\n * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE\n * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR\n * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF\n * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS\n * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN\n * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)\n * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE\n * POSSIBILITY OF SUCH DAMAGE.\n */\n\n#ifndef __ADLIST_H__\n#define __ADLIST_H__\n\n/* Node, List, and Iterator are the only data structures used currently. */\n\ntypedef struct listNode {\n    struct listNode *prev;\n    struct listNode *next;\n    void *value;\n} listNode;\n\ntypedef struct listIter {\n    listNode *next;\n    int direction;\n} listIter;\n\ntypedef struct list {\n    listNode *head;\n    listNode *tail;\n    void *(*dup)(void *ptr);\n    void (*free)(void *ptr);\n    int (*match)(void *ptr, void *key);\n    unsigned long len;\n} list;\n\n/* Functions implemented as macros */\n#define listLength(l) ((l)->len)\n#define listFirst(l) ((l)->head)\n#define listLast(l) ((l)->tail)\n#define listPrevNode(n) ((n)->prev)\n#define listNextNode(n) ((n)->next)\n#define listNodeValue(n) ((n)->value)\n\n#define listSetDupMethod(l,m) ((l)->dup = (m))\n#define listSetFreeMethod(l,m) ((l)->free = (m))\n#define listSetMatchMethod(l,m) ((l)->match = (m))\n\n#define listGetDupMethod(l) ((l)->dup)\n#define listGetFree(l) ((l)->free)\n#define listGetMatchMethod(l) ((l)->match)\n\n/* Prototypes */\nlist *listCreate(void);\nvoid listRelease(list *list);\nlist *listAddNodeHead(list *list, void *value);\nlist *listAddNodeTail(list *list, void *value);\nlist *listInsertNode(list *list, listNode *old_node, void *value, int after);\nvoid listDelNode(list *list, listNode *node);\nlistIter *listGetIterator(list *list, int direction);\nlistNode *listNext(listIter *iter);\nvoid listReleaseIterator(listIter *iter);\nlist *listDup(list *orig);\nlistNode *listSearchKey(list *list, void *key);\nlistNode *listIndex(list *list, long index);\nvoid listRewind(list *list, listIter *li);\nvoid listRewindTail(list *list, listIter *li);\nvoid listRotate(list *list);\n\n/* Directions for iterators */\n#define AL_START_HEAD 0\n#define AL_START_TAIL 1\n\n#endif /* __ADLIST_H__ */\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.8/src/ae.c",
    "content": "/* A simple event-driven programming library. Originally I wrote this code\n * for the Jim's event-loop (Jim is a Tcl interpreter) but later translated\n * it in form of a library for easy reuse.\n *\n * Copyright (c) 2006-2010, Salvatore Sanfilippo <antirez at gmail dot com>\n * All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions are met:\n *\n *   * Redistributions of source code must retain the above copyright notice,\n *     this list of conditions and the following disclaimer.\n *   * Redistributions in binary form must reproduce the above copyright\n *     notice, this list of conditions and the following disclaimer in the\n *     documentation and/or other materials provided with the distribution.\n *   * Neither the name of Redis nor the names of its contributors may be used\n *     to endorse or promote products derived from this software without\n *     specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\"\n * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\n * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE\n * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR\n * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF\n * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS\n * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN\n * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)\n * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE\n * POSSIBILITY OF SUCH DAMAGE.\n */\n\n#include <stdio.h>\n#include <sys/time.h>\n#include <sys/types.h>\n#include <unistd.h>\n#include <stdlib.h>\n#include <poll.h>\n#include <string.h>\n#include <time.h>\n#include <errno.h>\n\n#include \"ae.h\"\n#include \"zmalloc.h\"\n#include \"config.h\"\n\n/* Include the best multiplexing layer supported by this system.\n * The following should be ordered by performances, descending. */\n#ifdef HAVE_EVPORT\n#include \"ae_evport.c\"\n#else\n    #ifdef HAVE_EPOLL\n    #include \"ae_epoll.c\"\n    #else\n        #ifdef HAVE_KQUEUE\n        #include \"ae_kqueue.c\"\n        #else\n        #include \"ae_select.c\"\n        #endif\n    #endif\n#endif\n\naeEventLoop *aeCreateEventLoop(int setsize) {\n    aeEventLoop *eventLoop;\n    int i;\n\n    if ((eventLoop = zmalloc(sizeof(*eventLoop))) == NULL) goto err;\n    eventLoop->events = zmalloc(sizeof(aeFileEvent)*setsize);\n    eventLoop->fired = zmalloc(sizeof(aeFiredEvent)*setsize);\n    if (eventLoop->events == NULL || eventLoop->fired == NULL) goto err;\n    eventLoop->setsize = setsize;\n    eventLoop->lastTime = time(NULL);\n    eventLoop->timeEventHead = NULL;\n    eventLoop->timeEventNextId = 0;\n    eventLoop->stop = 0;\n    eventLoop->maxfd = -1;\n    eventLoop->beforesleep = NULL;\n    if (aeApiCreate(eventLoop) == -1) goto err;\n    /* Events with mask == AE_NONE are not set. So let's initialize the\n     * vector with it. */\n    for (i = 0; i < setsize; i++)\n        eventLoop->events[i].mask = AE_NONE;\n    return eventLoop;\n\nerr:\n    if (eventLoop) {\n        zfree(eventLoop->events);\n        zfree(eventLoop->fired);\n        zfree(eventLoop);\n    }\n    return NULL;\n}\n\n/* Return the current set size. */\nint aeGetSetSize(aeEventLoop *eventLoop) {\n    return eventLoop->setsize;\n}\n\n/* Resize the maximum set size of the event loop.\n * If the requested set size is smaller than the current set size, but\n * there is already a file descriptor in use that is >= the requested\n * set size minus one, AE_ERR is returned and the operation is not\n * performed at all.\n *\n * Otherwise AE_OK is returned and the operation is successful. */\nint aeResizeSetSize(aeEventLoop *eventLoop, int setsize) {\n    int i;\n\n    if (setsize == eventLoop->setsize) return AE_OK;\n    if (eventLoop->maxfd >= setsize) return AE_ERR;\n    if (aeApiResize(eventLoop,setsize) == -1) return AE_ERR;\n\n    eventLoop->events = zrealloc(eventLoop->events,sizeof(aeFileEvent)*setsize);\n    eventLoop->fired = zrealloc(eventLoop->fired,sizeof(aeFiredEvent)*setsize);\n    eventLoop->setsize = setsize;\n\n    /* Make sure that if we created new slots, they are initialized with\n     * an AE_NONE mask. */\n    for (i = eventLoop->maxfd+1; i < setsize; i++)\n        eventLoop->events[i].mask = AE_NONE;\n    return AE_OK;\n}\n\nvoid aeDeleteEventLoop(aeEventLoop *eventLoop) {\n    aeApiFree(eventLoop);\n    zfree(eventLoop->events);\n    zfree(eventLoop->fired);\n    zfree(eventLoop);\n}\n\nvoid aeStop(aeEventLoop *eventLoop) {\n    eventLoop->stop = 1;\n}\n\nint aeCreateFileEvent(aeEventLoop *eventLoop, int fd, int mask,\n        aeFileProc *proc, void *clientData)\n{\n    if (fd >= eventLoop->setsize) {\n        errno = ERANGE;\n        return AE_ERR;\n    }\n    aeFileEvent *fe = &eventLoop->events[fd];\n\n    if (aeApiAddEvent(eventLoop, fd, mask) == -1)\n        return AE_ERR;\n    fe->mask |= mask;\n    if (mask & AE_READABLE) fe->rfileProc = proc;\n    if (mask & AE_WRITABLE) fe->wfileProc = proc;\n    fe->clientData = clientData;\n    if (fd > eventLoop->maxfd)\n        eventLoop->maxfd = fd;\n    return AE_OK;\n}\n\nvoid aeDeleteFileEvent(aeEventLoop *eventLoop, int fd, int mask)\n{\n    if (fd >= eventLoop->setsize) return;\n    aeFileEvent *fe = &eventLoop->events[fd];\n    if (fe->mask == AE_NONE) return;\n\n    aeApiDelEvent(eventLoop, fd, mask);\n    fe->mask = fe->mask & (~mask);\n    if (fd == eventLoop->maxfd && fe->mask == AE_NONE) {\n        /* Update the max fd */\n        int j;\n\n        for (j = eventLoop->maxfd-1; j >= 0; j--)\n            if (eventLoop->events[j].mask != AE_NONE) break;\n        eventLoop->maxfd = j;\n    }\n}\n\nint aeGetFileEvents(aeEventLoop *eventLoop, int fd) {\n    if (fd >= eventLoop->setsize) return 0;\n    aeFileEvent *fe = &eventLoop->events[fd];\n\n    return fe->mask;\n}\n\nstatic void aeGetTime(long *seconds, long *milliseconds)\n{\n    struct timeval tv;\n\n    gettimeofday(&tv, NULL);\n    *seconds = tv.tv_sec;\n    *milliseconds = tv.tv_usec/1000;\n}\n\nstatic void aeAddMillisecondsToNow(long long milliseconds, long *sec, long *ms) {\n    long cur_sec, cur_ms, when_sec, when_ms;\n\n    aeGetTime(&cur_sec, &cur_ms);\n    when_sec = cur_sec + milliseconds/1000;\n    when_ms = cur_ms + milliseconds%1000;\n    if (when_ms >= 1000) {\n        when_sec ++;\n        when_ms -= 1000;\n    }\n    *sec = when_sec;\n    *ms = when_ms;\n}\n\nlong long aeCreateTimeEvent(aeEventLoop *eventLoop, long long milliseconds,\n        aeTimeProc *proc, void *clientData,\n        aeEventFinalizerProc *finalizerProc)\n{\n    long long id = eventLoop->timeEventNextId++;\n    aeTimeEvent *te;\n\n    te = zmalloc(sizeof(*te));\n    if (te == NULL) return AE_ERR;\n    te->id = id;\n    aeAddMillisecondsToNow(milliseconds,&te->when_sec,&te->when_ms);\n    te->timeProc = proc;\n    te->finalizerProc = finalizerProc;\n    te->clientData = clientData;\n    te->next = eventLoop->timeEventHead;\n    eventLoop->timeEventHead = te;\n    return id;\n}\n\nint aeDeleteTimeEvent(aeEventLoop *eventLoop, long long id)\n{\n    aeTimeEvent *te = eventLoop->timeEventHead;\n    while(te) {\n        if (te->id == id) {\n            te->id = AE_DELETED_EVENT_ID;\n            return AE_OK;\n        }\n        te = te->next;\n    }\n    return AE_ERR; /* NO event with the specified ID found */\n}\n\n/* Search the first timer to fire.\n * This operation is useful to know how many time the select can be\n * put in sleep without to delay any event.\n * If there are no timers NULL is returned.\n *\n * Note that's O(N) since time events are unsorted.\n * Possible optimizations (not needed by Redis so far, but...):\n * 1) Insert the event in order, so that the nearest is just the head.\n *    Much better but still insertion or deletion of timers is O(N).\n * 2) Use a skiplist to have this operation as O(1) and insertion as O(log(N)).\n */\nstatic aeTimeEvent *aeSearchNearestTimer(aeEventLoop *eventLoop)\n{\n    aeTimeEvent *te = eventLoop->timeEventHead;\n    aeTimeEvent *nearest = NULL;\n\n    while(te) {\n        if (!nearest || te->when_sec < nearest->when_sec ||\n                (te->when_sec == nearest->when_sec &&\n                 te->when_ms < nearest->when_ms))\n            nearest = te;\n        te = te->next;\n    }\n    return nearest;\n}\n\n/* Process time events */\nstatic int processTimeEvents(aeEventLoop *eventLoop) {\n    int processed = 0;\n    aeTimeEvent *te, *prev;\n    long long maxId;\n    time_t now = time(NULL);\n\n    /* If the system clock is moved to the future, and then set back to the\n     * right value, time events may be delayed in a random way. Often this\n     * means that scheduled operations will not be performed soon enough.\n     *\n     * Here we try to detect system clock skews, and force all the time\n     * events to be processed ASAP when this happens: the idea is that\n     * processing events earlier is less dangerous than delaying them\n     * indefinitely, and practice suggests it is. */\n    if (now < eventLoop->lastTime) {\n        te = eventLoop->timeEventHead;\n        while(te) {\n            te->when_sec = 0;\n            te = te->next;\n        }\n    }\n    eventLoop->lastTime = now;\n\n    prev = NULL;\n    te = eventLoop->timeEventHead;\n    maxId = eventLoop->timeEventNextId-1;\n    while(te) {\n        long now_sec, now_ms;\n        long long id;\n\n        /* Remove events scheduled for deletion. */\n        if (te->id == AE_DELETED_EVENT_ID) {\n            aeTimeEvent *next = te->next;\n            if (prev == NULL)\n                eventLoop->timeEventHead = te->next;\n            else\n                prev->next = te->next;\n            if (te->finalizerProc)\n                te->finalizerProc(eventLoop, te->clientData);\n            zfree(te);\n            te = next;\n            continue;\n        }\n\n        /* Make sure we don't process time events created by time events in\n         * this iteration. Note that this check is currently useless: we always\n         * add new timers on the head, however if we change the implementation\n         * detail, this check may be useful again: we keep it here for future\n         * defense. */\n        if (te->id > maxId) {\n            te = te->next;\n            continue;\n        }\n        aeGetTime(&now_sec, &now_ms);\n        if (now_sec > te->when_sec ||\n            (now_sec == te->when_sec && now_ms >= te->when_ms))\n        {\n            int retval;\n\n            id = te->id;\n            retval = te->timeProc(eventLoop, id, te->clientData);\n            processed++;\n            if (retval != AE_NOMORE) {\n                aeAddMillisecondsToNow(retval,&te->when_sec,&te->when_ms);\n            } else {\n                te->id = AE_DELETED_EVENT_ID;\n            }\n        }\n        prev = te;\n        te = te->next;\n    }\n    return processed;\n}\n\n/* Process every pending time event, then every pending file event\n * (that may be registered by time event callbacks just processed).\n * Without special flags the function sleeps until some file event\n * fires, or when the next time event occurs (if any).\n *\n * If flags is 0, the function does nothing and returns.\n * if flags has AE_ALL_EVENTS set, all the kind of events are processed.\n * if flags has AE_FILE_EVENTS set, file events are processed.\n * if flags has AE_TIME_EVENTS set, time events are processed.\n * if flags has AE_DONT_WAIT set the function returns ASAP until all\n * the events that's possible to process without to wait are processed.\n *\n * The function returns the number of events processed. */\nint aeProcessEvents(aeEventLoop *eventLoop, int flags)\n{\n    int processed = 0, numevents;\n\n    /* Nothing to do? return ASAP */\n    if (!(flags & AE_TIME_EVENTS) && !(flags & AE_FILE_EVENTS)) return 0;\n\n    /* Note that we want call select() even if there are no\n     * file events to process as long as we want to process time\n     * events, in order to sleep until the next time event is ready\n     * to fire. */\n    if (eventLoop->maxfd != -1 ||\n        ((flags & AE_TIME_EVENTS) && !(flags & AE_DONT_WAIT))) {\n        int j;\n        aeTimeEvent *shortest = NULL;\n        struct timeval tv, *tvp;\n\n        if (flags & AE_TIME_EVENTS && !(flags & AE_DONT_WAIT))\n            shortest = aeSearchNearestTimer(eventLoop);\n        if (shortest) {\n            long now_sec, now_ms;\n\n            aeGetTime(&now_sec, &now_ms);\n            tvp = &tv;\n\n            /* How many milliseconds we need to wait for the next\n             * time event to fire? */\n            long long ms =\n                (shortest->when_sec - now_sec)*1000 +\n                shortest->when_ms - now_ms;\n\n            if (ms > 0) {\n                tvp->tv_sec = ms/1000;\n                tvp->tv_usec = (ms % 1000)*1000;\n            } else {\n                tvp->tv_sec = 0;\n                tvp->tv_usec = 0;\n            }\n        } else {\n            /* If we have to check for events but need to return\n             * ASAP because of AE_DONT_WAIT we need to set the timeout\n             * to zero */\n            if (flags & AE_DONT_WAIT) {\n                tv.tv_sec = tv.tv_usec = 0;\n                tvp = &tv;\n            } else {\n                /* Otherwise we can block */\n                tvp = NULL; /* wait forever */\n            }\n        }\n\n        numevents = aeApiPoll(eventLoop, tvp);\n        for (j = 0; j < numevents; j++) {\n            aeFileEvent *fe = &eventLoop->events[eventLoop->fired[j].fd];\n            int mask = eventLoop->fired[j].mask;\n            int fd = eventLoop->fired[j].fd;\n            int rfired = 0;\n\n\t    /* note the fe->mask & mask & ... code: maybe an already processed\n             * event removed an element that fired and we still didn't\n             * processed, so we check if the event is still valid. */\n            if (fe->mask & mask & AE_READABLE) {\n                rfired = 1;\n                fe->rfileProc(eventLoop,fd,fe->clientData,mask);\n            }\n            if (fe->mask & mask & AE_WRITABLE) {\n                if (!rfired || fe->wfileProc != fe->rfileProc)\n                    fe->wfileProc(eventLoop,fd,fe->clientData,mask);\n            }\n            processed++;\n        }\n    }\n    /* Check time events */\n    if (flags & AE_TIME_EVENTS)\n        processed += processTimeEvents(eventLoop);\n\n    return processed; /* return the number of processed file/time events */\n}\n\n/* Wait for milliseconds until the given file descriptor becomes\n * writable/readable/exception */\nint aeWait(int fd, int mask, long long milliseconds) {\n    struct pollfd pfd;\n    int retmask = 0, retval;\n\n    memset(&pfd, 0, sizeof(pfd));\n    pfd.fd = fd;\n    if (mask & AE_READABLE) pfd.events |= POLLIN;\n    if (mask & AE_WRITABLE) pfd.events |= POLLOUT;\n\n    if ((retval = poll(&pfd, 1, milliseconds))== 1) {\n        if (pfd.revents & POLLIN) retmask |= AE_READABLE;\n        if (pfd.revents & POLLOUT) retmask |= AE_WRITABLE;\n\tif (pfd.revents & POLLERR) retmask |= AE_WRITABLE;\n        if (pfd.revents & POLLHUP) retmask |= AE_WRITABLE;\n        return retmask;\n    } else {\n        return retval;\n    }\n}\n\nvoid aeMain(aeEventLoop *eventLoop) {\n    eventLoop->stop = 0;\n    while (!eventLoop->stop) {\n        if (eventLoop->beforesleep != NULL)\n            eventLoop->beforesleep(eventLoop);\n        aeProcessEvents(eventLoop, AE_ALL_EVENTS);\n    }\n}\n\nchar *aeGetApiName(void) {\n    return aeApiName();\n}\n\nvoid aeSetBeforeSleepProc(aeEventLoop *eventLoop, aeBeforeSleepProc *beforesleep) {\n    eventLoop->beforesleep = beforesleep;\n}\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.8/src/ae.h",
    "content": "/* A simple event-driven programming library. Originally I wrote this code\n * for the Jim's event-loop (Jim is a Tcl interpreter) but later translated\n * it in form of a library for easy reuse.\n *\n * Copyright (c) 2006-2012, Salvatore Sanfilippo <antirez at gmail dot com>\n * All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions are met:\n *\n *   * Redistributions of source code must retain the above copyright notice,\n *     this list of conditions and the following disclaimer.\n *   * Redistributions in binary form must reproduce the above copyright\n *     notice, this list of conditions and the following disclaimer in the\n *     documentation and/or other materials provided with the distribution.\n *   * Neither the name of Redis nor the names of its contributors may be used\n *     to endorse or promote products derived from this software without\n *     specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\"\n * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\n * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE\n * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR\n * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF\n * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS\n * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN\n * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)\n * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE\n * POSSIBILITY OF SUCH DAMAGE.\n */\n\n#ifndef __AE_H__\n#define __AE_H__\n\n#include <time.h>\n\n#define AE_OK 0\n#define AE_ERR -1\n\n#define AE_NONE 0\n#define AE_READABLE 1\n#define AE_WRITABLE 2\n\n#define AE_FILE_EVENTS 1\n#define AE_TIME_EVENTS 2\n#define AE_ALL_EVENTS (AE_FILE_EVENTS|AE_TIME_EVENTS)\n#define AE_DONT_WAIT 4\n\n#define AE_NOMORE -1\n#define AE_DELETED_EVENT_ID -1\n\n/* Macros */\n#define AE_NOTUSED(V) ((void) V)\n\nstruct aeEventLoop;\n\n/* Types and data structures */\ntypedef void aeFileProc(struct aeEventLoop *eventLoop, int fd, void *clientData, int mask);\ntypedef int aeTimeProc(struct aeEventLoop *eventLoop, long long id, void *clientData);\ntypedef void aeEventFinalizerProc(struct aeEventLoop *eventLoop, void *clientData);\ntypedef void aeBeforeSleepProc(struct aeEventLoop *eventLoop);\n\n/* File event structure */\ntypedef struct aeFileEvent {\n    int mask; /* one of AE_(READABLE|WRITABLE) */\n    aeFileProc *rfileProc;\n    aeFileProc *wfileProc;\n    void *clientData;\n} aeFileEvent;\n\n/* Time event structure */\ntypedef struct aeTimeEvent {\n    long long id; /* time event identifier. */\n    long when_sec; /* seconds */\n    long when_ms; /* milliseconds */\n    aeTimeProc *timeProc;\n    aeEventFinalizerProc *finalizerProc;\n    void *clientData;\n    struct aeTimeEvent *next;\n} aeTimeEvent;\n\n/* A fired event */\ntypedef struct aeFiredEvent {\n    int fd;\n    int mask;\n} aeFiredEvent;\n\n/* State of an event based program */\ntypedef struct aeEventLoop {\n    int maxfd;   /* highest file descriptor currently registered */\n    int setsize; /* max number of file descriptors tracked */\n    long long timeEventNextId;\n    time_t lastTime;     /* Used to detect system clock skew */\n    aeFileEvent *events; /* Registered events */\n    aeFiredEvent *fired; /* Fired events */\n    aeTimeEvent *timeEventHead;\n    int stop;\n    void *apidata; /* This is used for polling API specific data */\n    aeBeforeSleepProc *beforesleep;\n} aeEventLoop;\n\n/* Prototypes */\naeEventLoop *aeCreateEventLoop(int setsize);\nvoid aeDeleteEventLoop(aeEventLoop *eventLoop);\nvoid aeStop(aeEventLoop *eventLoop);\nint aeCreateFileEvent(aeEventLoop *eventLoop, int fd, int mask,\n        aeFileProc *proc, void *clientData);\nvoid aeDeleteFileEvent(aeEventLoop *eventLoop, int fd, int mask);\nint aeGetFileEvents(aeEventLoop *eventLoop, int fd);\nlong long aeCreateTimeEvent(aeEventLoop *eventLoop, long long milliseconds,\n        aeTimeProc *proc, void *clientData,\n        aeEventFinalizerProc *finalizerProc);\nint aeDeleteTimeEvent(aeEventLoop *eventLoop, long long id);\nint aeProcessEvents(aeEventLoop *eventLoop, int flags);\nint aeWait(int fd, int mask, long long milliseconds);\nvoid aeMain(aeEventLoop *eventLoop);\nchar *aeGetApiName(void);\nvoid aeSetBeforeSleepProc(aeEventLoop *eventLoop, aeBeforeSleepProc *beforesleep);\nint aeGetSetSize(aeEventLoop *eventLoop);\nint aeResizeSetSize(aeEventLoop *eventLoop, int setsize);\n\n#endif\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.8/src/ae_epoll.c",
    "content": "/* Linux epoll(2) based ae.c module\n *\n * Copyright (c) 2009-2012, Salvatore Sanfilippo <antirez at gmail dot com>\n * All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions are met:\n *\n *   * Redistributions of source code must retain the above copyright notice,\n *     this list of conditions and the following disclaimer.\n *   * Redistributions in binary form must reproduce the above copyright\n *     notice, this list of conditions and the following disclaimer in the\n *     documentation and/or other materials provided with the distribution.\n *   * Neither the name of Redis nor the names of its contributors may be used\n *     to endorse or promote products derived from this software without\n *     specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\"\n * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\n * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE\n * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR\n * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF\n * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS\n * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN\n * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)\n * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE\n * POSSIBILITY OF SUCH DAMAGE.\n */\n\n\n#include <sys/epoll.h>\n\ntypedef struct aeApiState {\n    int epfd;\n    struct epoll_event *events;\n} aeApiState;\n\nstatic int aeApiCreate(aeEventLoop *eventLoop) {\n    aeApiState *state = zmalloc(sizeof(aeApiState));\n\n    if (!state) return -1;\n    state->events = zmalloc(sizeof(struct epoll_event)*eventLoop->setsize);\n    if (!state->events) {\n        zfree(state);\n        return -1;\n    }\n    state->epfd = epoll_create(1024); /* 1024 is just a hint for the kernel */\n    if (state->epfd == -1) {\n        zfree(state->events);\n        zfree(state);\n        return -1;\n    }\n    eventLoop->apidata = state;\n    return 0;\n}\n\nstatic int aeApiResize(aeEventLoop *eventLoop, int setsize) {\n    aeApiState *state = eventLoop->apidata;\n\n    state->events = zrealloc(state->events, sizeof(struct epoll_event)*setsize);\n    return 0;\n}\n\nstatic void aeApiFree(aeEventLoop *eventLoop) {\n    aeApiState *state = eventLoop->apidata;\n\n    close(state->epfd);\n    zfree(state->events);\n    zfree(state);\n}\n\nstatic int aeApiAddEvent(aeEventLoop *eventLoop, int fd, int mask) {\n    aeApiState *state = eventLoop->apidata;\n    struct epoll_event ee = {0}; /* avoid valgrind warning */\n    /* If the fd was already monitored for some event, we need a MOD\n     * operation. Otherwise we need an ADD operation. */\n    int op = eventLoop->events[fd].mask == AE_NONE ?\n            EPOLL_CTL_ADD : EPOLL_CTL_MOD;\n\n    ee.events = 0;\n    mask |= eventLoop->events[fd].mask; /* Merge old events */\n    if (mask & AE_READABLE) ee.events |= EPOLLIN;\n    if (mask & AE_WRITABLE) ee.events |= EPOLLOUT;\n    ee.data.fd = fd;\n    if (epoll_ctl(state->epfd,op,fd,&ee) == -1) return -1;\n    return 0;\n}\n\nstatic void aeApiDelEvent(aeEventLoop *eventLoop, int fd, int delmask) {\n    aeApiState *state = eventLoop->apidata;\n    struct epoll_event ee = {0}; /* avoid valgrind warning */\n    int mask = eventLoop->events[fd].mask & (~delmask);\n\n    ee.events = 0;\n    if (mask & AE_READABLE) ee.events |= EPOLLIN;\n    if (mask & AE_WRITABLE) ee.events |= EPOLLOUT;\n    ee.data.fd = fd;\n    if (mask != AE_NONE) {\n        epoll_ctl(state->epfd,EPOLL_CTL_MOD,fd,&ee);\n    } else {\n        /* Note, Kernel < 2.6.9 requires a non null event pointer even for\n         * EPOLL_CTL_DEL. */\n        epoll_ctl(state->epfd,EPOLL_CTL_DEL,fd,&ee);\n    }\n}\n\nstatic int aeApiPoll(aeEventLoop *eventLoop, struct timeval *tvp) {\n    aeApiState *state = eventLoop->apidata;\n    int retval, numevents = 0;\n\n    retval = epoll_wait(state->epfd,state->events,eventLoop->setsize,\n            tvp ? (tvp->tv_sec*1000 + tvp->tv_usec/1000) : -1);\n    if (retval > 0) {\n        int j;\n\n        numevents = retval;\n        for (j = 0; j < numevents; j++) {\n            int mask = 0;\n            struct epoll_event *e = state->events+j;\n\n            if (e->events & EPOLLIN) mask |= AE_READABLE;\n            if (e->events & EPOLLOUT) mask |= AE_WRITABLE;\n            if (e->events & EPOLLERR) mask |= AE_WRITABLE;\n            if (e->events & EPOLLHUP) mask |= AE_WRITABLE;\n            eventLoop->fired[j].fd = e->data.fd;\n            eventLoop->fired[j].mask = mask;\n        }\n    }\n    return numevents;\n}\n\nstatic char *aeApiName(void) {\n    return \"epoll\";\n}\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.8/src/ae_evport.c",
    "content": "/* ae.c module for illumos event ports.\n *\n * Copyright (c) 2012, Joyent, Inc. All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions are met:\n *\n *   * Redistributions of source code must retain the above copyright notice,\n *     this list of conditions and the following disclaimer.\n *   * Redistributions in binary form must reproduce the above copyright\n *     notice, this list of conditions and the following disclaimer in the\n *     documentation and/or other materials provided with the distribution.\n *   * Neither the name of Redis nor the names of its contributors may be used\n *     to endorse or promote products derived from this software without\n *     specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\"\n * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\n * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE\n * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR\n * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF\n * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS\n * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN\n * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)\n * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE\n * POSSIBILITY OF SUCH DAMAGE.\n */\n\n\n#include <assert.h>\n#include <errno.h>\n#include <port.h>\n#include <poll.h>\n\n#include <sys/types.h>\n#include <sys/time.h>\n\n#include <stdio.h>\n\nstatic int evport_debug = 0;\n\n/*\n * This file implements the ae API using event ports, present on Solaris-based\n * systems since Solaris 10.  Using the event port interface, we associate file\n * descriptors with the port.  Each association also includes the set of poll(2)\n * events that the consumer is interested in (e.g., POLLIN and POLLOUT).\n *\n * There's one tricky piece to this implementation: when we return events via\n * aeApiPoll, the corresponding file descriptors become dissociated from the\n * port.  This is necessary because poll events are level-triggered, so if the\n * fd didn't become dissociated, it would immediately fire another event since\n * the underlying state hasn't changed yet.  We must re-associate the file\n * descriptor, but only after we know that our caller has actually read from it.\n * The ae API does not tell us exactly when that happens, but we do know that\n * it must happen by the time aeApiPoll is called again.  Our solution is to\n * keep track of the last fds returned by aeApiPoll and re-associate them next\n * time aeApiPoll is invoked.\n *\n * To summarize, in this module, each fd association is EITHER (a) represented\n * only via the in-kernel association OR (b) represented by pending_fds and\n * pending_masks.  (b) is only true for the last fds we returned from aeApiPoll,\n * and only until we enter aeApiPoll again (at which point we restore the\n * in-kernel association).\n */\n#define MAX_EVENT_BATCHSZ 512\n\ntypedef struct aeApiState {\n    int     portfd;                             /* event port */\n    int     npending;                           /* # of pending fds */\n    int     pending_fds[MAX_EVENT_BATCHSZ];     /* pending fds */\n    int     pending_masks[MAX_EVENT_BATCHSZ];   /* pending fds' masks */\n} aeApiState;\n\nstatic int aeApiCreate(aeEventLoop *eventLoop) {\n    int i;\n    aeApiState *state = zmalloc(sizeof(aeApiState));\n    if (!state) return -1;\n\n    state->portfd = port_create();\n    if (state->portfd == -1) {\n        zfree(state);\n        return -1;\n    }\n\n    state->npending = 0;\n\n    for (i = 0; i < MAX_EVENT_BATCHSZ; i++) {\n        state->pending_fds[i] = -1;\n        state->pending_masks[i] = AE_NONE;\n    }\n\n    eventLoop->apidata = state;\n    return 0;\n}\n\nstatic int aeApiResize(aeEventLoop *eventLoop, int setsize) {\n    /* Nothing to resize here. */\n    return 0;\n}\n\nstatic void aeApiFree(aeEventLoop *eventLoop) {\n    aeApiState *state = eventLoop->apidata;\n\n    close(state->portfd);\n    zfree(state);\n}\n\nstatic int aeApiLookupPending(aeApiState *state, int fd) {\n    int i;\n\n    for (i = 0; i < state->npending; i++) {\n        if (state->pending_fds[i] == fd)\n            return (i);\n    }\n\n    return (-1);\n}\n\n/*\n * Helper function to invoke port_associate for the given fd and mask.\n */\nstatic int aeApiAssociate(const char *where, int portfd, int fd, int mask) {\n    int events = 0;\n    int rv, err;\n\n    if (mask & AE_READABLE)\n        events |= POLLIN;\n    if (mask & AE_WRITABLE)\n        events |= POLLOUT;\n\n    if (evport_debug)\n        fprintf(stderr, \"%s: port_associate(%d, 0x%x) = \", where, fd, events);\n\n    rv = port_associate(portfd, PORT_SOURCE_FD, fd, events,\n        (void *)(uintptr_t)mask);\n    err = errno;\n\n    if (evport_debug)\n        fprintf(stderr, \"%d (%s)\\n\", rv, rv == 0 ? \"no error\" : strerror(err));\n\n    if (rv == -1) {\n        fprintf(stderr, \"%s: port_associate: %s\\n\", where, strerror(err));\n\n        if (err == EAGAIN)\n            fprintf(stderr, \"aeApiAssociate: event port limit exceeded.\");\n    }\n\n    return rv;\n}\n\nstatic int aeApiAddEvent(aeEventLoop *eventLoop, int fd, int mask) {\n    aeApiState *state = eventLoop->apidata;\n    int fullmask, pfd;\n\n    if (evport_debug)\n        fprintf(stderr, \"aeApiAddEvent: fd %d mask 0x%x\\n\", fd, mask);\n\n    /*\n     * Since port_associate's \"events\" argument replaces any existing events, we\n     * must be sure to include whatever events are already associated when\n     * we call port_associate() again.\n     */\n    fullmask = mask | eventLoop->events[fd].mask;\n    pfd = aeApiLookupPending(state, fd);\n\n    if (pfd != -1) {\n        /*\n         * This fd was recently returned from aeApiPoll.  It should be safe to\n         * assume that the consumer has processed that poll event, but we play\n         * it safer by simply updating pending_mask.  The fd will be\n         * re-associated as usual when aeApiPoll is called again.\n         */\n        if (evport_debug)\n            fprintf(stderr, \"aeApiAddEvent: adding to pending fd %d\\n\", fd);\n        state->pending_masks[pfd] |= fullmask;\n        return 0;\n    }\n\n    return (aeApiAssociate(\"aeApiAddEvent\", state->portfd, fd, fullmask));\n}\n\nstatic void aeApiDelEvent(aeEventLoop *eventLoop, int fd, int mask) {\n    aeApiState *state = eventLoop->apidata;\n    int fullmask, pfd;\n\n    if (evport_debug)\n        fprintf(stderr, \"del fd %d mask 0x%x\\n\", fd, mask);\n\n    pfd = aeApiLookupPending(state, fd);\n\n    if (pfd != -1) {\n        if (evport_debug)\n            fprintf(stderr, \"deleting event from pending fd %d\\n\", fd);\n\n        /*\n         * This fd was just returned from aeApiPoll, so it's not currently\n         * associated with the port.  All we need to do is update\n         * pending_mask appropriately.\n         */\n        state->pending_masks[pfd] &= ~mask;\n\n        if (state->pending_masks[pfd] == AE_NONE)\n            state->pending_fds[pfd] = -1;\n\n        return;\n    }\n\n    /*\n     * The fd is currently associated with the port.  Like with the add case\n     * above, we must look at the full mask for the file descriptor before\n     * updating that association.  We don't have a good way of knowing what the\n     * events are without looking into the eventLoop state directly.  We rely on\n     * the fact that our caller has already updated the mask in the eventLoop.\n     */\n\n    fullmask = eventLoop->events[fd].mask;\n    if (fullmask == AE_NONE) {\n        /*\n         * We're removing *all* events, so use port_dissociate to remove the\n         * association completely.  Failure here indicates a bug.\n         */\n        if (evport_debug)\n            fprintf(stderr, \"aeApiDelEvent: port_dissociate(%d)\\n\", fd);\n\n        if (port_dissociate(state->portfd, PORT_SOURCE_FD, fd) != 0) {\n            perror(\"aeApiDelEvent: port_dissociate\");\n            abort(); /* will not return */\n        }\n    } else if (aeApiAssociate(\"aeApiDelEvent\", state->portfd, fd,\n        fullmask) != 0) {\n        /*\n         * ENOMEM is a potentially transient condition, but the kernel won't\n         * generally return it unless things are really bad.  EAGAIN indicates\n         * we've reached an resource limit, for which it doesn't make sense to\n         * retry (counter-intuitively).  All other errors indicate a bug.  In any\n         * of these cases, the best we can do is to abort.\n         */\n        abort(); /* will not return */\n    }\n}\n\nstatic int aeApiPoll(aeEventLoop *eventLoop, struct timeval *tvp) {\n    aeApiState *state = eventLoop->apidata;\n    struct timespec timeout, *tsp;\n    int mask, i;\n    uint_t nevents;\n    port_event_t event[MAX_EVENT_BATCHSZ];\n\n    /*\n     * If we've returned fd events before, we must re-associate them with the\n     * port now, before calling port_get().  See the block comment at the top of\n     * this file for an explanation of why.\n     */\n    for (i = 0; i < state->npending; i++) {\n        if (state->pending_fds[i] == -1)\n            /* This fd has since been deleted. */\n            continue;\n\n        if (aeApiAssociate(\"aeApiPoll\", state->portfd,\n            state->pending_fds[i], state->pending_masks[i]) != 0) {\n            /* See aeApiDelEvent for why this case is fatal. */\n            abort();\n        }\n\n        state->pending_masks[i] = AE_NONE;\n        state->pending_fds[i] = -1;\n    }\n\n    state->npending = 0;\n\n    if (tvp != NULL) {\n        timeout.tv_sec = tvp->tv_sec;\n        timeout.tv_nsec = tvp->tv_usec * 1000;\n        tsp = &timeout;\n    } else {\n        tsp = NULL;\n    }\n\n    /*\n     * port_getn can return with errno == ETIME having returned some events (!).\n     * So if we get ETIME, we check nevents, too.\n     */\n    nevents = 1;\n    if (port_getn(state->portfd, event, MAX_EVENT_BATCHSZ, &nevents,\n        tsp) == -1 && (errno != ETIME || nevents == 0)) {\n        if (errno == ETIME || errno == EINTR)\n            return 0;\n\n        /* Any other error indicates a bug. */\n        perror(\"aeApiPoll: port_get\");\n        abort();\n    }\n\n    state->npending = nevents;\n\n    for (i = 0; i < nevents; i++) {\n            mask = 0;\n            if (event[i].portev_events & POLLIN)\n                mask |= AE_READABLE;\n            if (event[i].portev_events & POLLOUT)\n                mask |= AE_WRITABLE;\n\n            eventLoop->fired[i].fd = event[i].portev_object;\n            eventLoop->fired[i].mask = mask;\n\n            if (evport_debug)\n                fprintf(stderr, \"aeApiPoll: fd %d mask 0x%x\\n\",\n                    (int)event[i].portev_object, mask);\n\n            state->pending_fds[i] = event[i].portev_object;\n            state->pending_masks[i] = (uintptr_t)event[i].portev_user;\n    }\n\n    return nevents;\n}\n\nstatic char *aeApiName(void) {\n    return \"evport\";\n}\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.8/src/ae_kqueue.c",
    "content": "/* Kqueue(2)-based ae.c module\n *\n * Copyright (C) 2009 Harish Mallipeddi - harish.mallipeddi@gmail.com\n * All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions are met:\n *\n *   * Redistributions of source code must retain the above copyright notice,\n *     this list of conditions and the following disclaimer.\n *   * Redistributions in binary form must reproduce the above copyright\n *     notice, this list of conditions and the following disclaimer in the\n *     documentation and/or other materials provided with the distribution.\n *   * Neither the name of Redis nor the names of its contributors may be used\n *     to endorse or promote products derived from this software without\n *     specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\"\n * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\n * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE\n * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR\n * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF\n * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS\n * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN\n * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)\n * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE\n * POSSIBILITY OF SUCH DAMAGE.\n */\n\n\n#include <sys/types.h>\n#include <sys/event.h>\n#include <sys/time.h>\n\ntypedef struct aeApiState {\n    int kqfd;\n    struct kevent *events;\n} aeApiState;\n\nstatic int aeApiCreate(aeEventLoop *eventLoop) {\n    aeApiState *state = zmalloc(sizeof(aeApiState));\n\n    if (!state) return -1;\n    state->events = zmalloc(sizeof(struct kevent)*eventLoop->setsize);\n    if (!state->events) {\n        zfree(state);\n        return -1;\n    }\n    state->kqfd = kqueue();\n    if (state->kqfd == -1) {\n        zfree(state->events);\n        zfree(state);\n        return -1;\n    }\n    eventLoop->apidata = state;\n    return 0;\n}\n\nstatic int aeApiResize(aeEventLoop *eventLoop, int setsize) {\n    aeApiState *state = eventLoop->apidata;\n\n    state->events = zrealloc(state->events, sizeof(struct kevent)*setsize);\n    return 0;\n}\n\nstatic void aeApiFree(aeEventLoop *eventLoop) {\n    aeApiState *state = eventLoop->apidata;\n\n    close(state->kqfd);\n    zfree(state->events);\n    zfree(state);\n}\n\nstatic int aeApiAddEvent(aeEventLoop *eventLoop, int fd, int mask) {\n    aeApiState *state = eventLoop->apidata;\n    struct kevent ke;\n\n    if (mask & AE_READABLE) {\n        EV_SET(&ke, fd, EVFILT_READ, EV_ADD, 0, 0, NULL);\n        if (kevent(state->kqfd, &ke, 1, NULL, 0, NULL) == -1) return -1;\n    }\n    if (mask & AE_WRITABLE) {\n        EV_SET(&ke, fd, EVFILT_WRITE, EV_ADD, 0, 0, NULL);\n        if (kevent(state->kqfd, &ke, 1, NULL, 0, NULL) == -1) return -1;\n    }\n    return 0;\n}\n\nstatic void aeApiDelEvent(aeEventLoop *eventLoop, int fd, int mask) {\n    aeApiState *state = eventLoop->apidata;\n    struct kevent ke;\n\n    if (mask & AE_READABLE) {\n        EV_SET(&ke, fd, EVFILT_READ, EV_DELETE, 0, 0, NULL);\n        kevent(state->kqfd, &ke, 1, NULL, 0, NULL);\n    }\n    if (mask & AE_WRITABLE) {\n        EV_SET(&ke, fd, EVFILT_WRITE, EV_DELETE, 0, 0, NULL);\n        kevent(state->kqfd, &ke, 1, NULL, 0, NULL);\n    }\n}\n\nstatic int aeApiPoll(aeEventLoop *eventLoop, struct timeval *tvp) {\n    aeApiState *state = eventLoop->apidata;\n    int retval, numevents = 0;\n\n    if (tvp != NULL) {\n        struct timespec timeout;\n        timeout.tv_sec = tvp->tv_sec;\n        timeout.tv_nsec = tvp->tv_usec * 1000;\n        retval = kevent(state->kqfd, NULL, 0, state->events, eventLoop->setsize,\n                        &timeout);\n    } else {\n        retval = kevent(state->kqfd, NULL, 0, state->events, eventLoop->setsize,\n                        NULL);\n    }\n\n    if (retval > 0) {\n        int j;\n\n        numevents = retval;\n        for(j = 0; j < numevents; j++) {\n            int mask = 0;\n            struct kevent *e = state->events+j;\n\n            if (e->filter == EVFILT_READ) mask |= AE_READABLE;\n            if (e->filter == EVFILT_WRITE) mask |= AE_WRITABLE;\n            eventLoop->fired[j].fd = e->ident;\n            eventLoop->fired[j].mask = mask;\n        }\n    }\n    return numevents;\n}\n\nstatic char *aeApiName(void) {\n    return \"kqueue\";\n}\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.8/src/ae_select.c",
    "content": "/* Select()-based ae.c module.\n *\n * Copyright (c) 2009-2012, Salvatore Sanfilippo <antirez at gmail dot com>\n * All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions are met:\n *\n *   * Redistributions of source code must retain the above copyright notice,\n *     this list of conditions and the following disclaimer.\n *   * Redistributions in binary form must reproduce the above copyright\n *     notice, this list of conditions and the following disclaimer in the\n *     documentation and/or other materials provided with the distribution.\n *   * Neither the name of Redis nor the names of its contributors may be used\n *     to endorse or promote products derived from this software without\n *     specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\"\n * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\n * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE\n * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR\n * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF\n * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS\n * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN\n * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)\n * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE\n * POSSIBILITY OF SUCH DAMAGE.\n */\n\n\n#include <sys/select.h>\n#include <string.h>\n\ntypedef struct aeApiState {\n    fd_set rfds, wfds;\n    /* We need to have a copy of the fd sets as it's not safe to reuse\n     * FD sets after select(). */\n    fd_set _rfds, _wfds;\n} aeApiState;\n\nstatic int aeApiCreate(aeEventLoop *eventLoop) {\n    aeApiState *state = zmalloc(sizeof(aeApiState));\n\n    if (!state) return -1;\n    FD_ZERO(&state->rfds);\n    FD_ZERO(&state->wfds);\n    eventLoop->apidata = state;\n    return 0;\n}\n\nstatic int aeApiResize(aeEventLoop *eventLoop, int setsize) {\n    /* Just ensure we have enough room in the fd_set type. */\n    if (setsize >= FD_SETSIZE) return -1;\n    return 0;\n}\n\nstatic void aeApiFree(aeEventLoop *eventLoop) {\n    zfree(eventLoop->apidata);\n}\n\nstatic int aeApiAddEvent(aeEventLoop *eventLoop, int fd, int mask) {\n    aeApiState *state = eventLoop->apidata;\n\n    if (mask & AE_READABLE) FD_SET(fd,&state->rfds);\n    if (mask & AE_WRITABLE) FD_SET(fd,&state->wfds);\n    return 0;\n}\n\nstatic void aeApiDelEvent(aeEventLoop *eventLoop, int fd, int mask) {\n    aeApiState *state = eventLoop->apidata;\n\n    if (mask & AE_READABLE) FD_CLR(fd,&state->rfds);\n    if (mask & AE_WRITABLE) FD_CLR(fd,&state->wfds);\n}\n\nstatic int aeApiPoll(aeEventLoop *eventLoop, struct timeval *tvp) {\n    aeApiState *state = eventLoop->apidata;\n    int retval, j, numevents = 0;\n\n    memcpy(&state->_rfds,&state->rfds,sizeof(fd_set));\n    memcpy(&state->_wfds,&state->wfds,sizeof(fd_set));\n\n    retval = select(eventLoop->maxfd+1,\n                &state->_rfds,&state->_wfds,NULL,tvp);\n    if (retval > 0) {\n        for (j = 0; j <= eventLoop->maxfd; j++) {\n            int mask = 0;\n            aeFileEvent *fe = &eventLoop->events[j];\n\n            if (fe->mask == AE_NONE) continue;\n            if (fe->mask & AE_READABLE && FD_ISSET(j,&state->_rfds))\n                mask |= AE_READABLE;\n            if (fe->mask & AE_WRITABLE && FD_ISSET(j,&state->_wfds))\n                mask |= AE_WRITABLE;\n            eventLoop->fired[numevents].fd = j;\n            eventLoop->fired[numevents].mask = mask;\n            numevents++;\n        }\n    }\n    return numevents;\n}\n\nstatic char *aeApiName(void) {\n    return \"select\";\n}\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.8/src/anet.c",
    "content": "/* anet.c -- Basic TCP socket stuff made a bit less boring\n *\n * Copyright (c) 2006-2012, Salvatore Sanfilippo <antirez at gmail dot com>\n * All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions are met:\n *\n *   * Redistributions of source code must retain the above copyright notice,\n *     this list of conditions and the following disclaimer.\n *   * Redistributions in binary form must reproduce the above copyright\n *     notice, this list of conditions and the following disclaimer in the\n *     documentation and/or other materials provided with the distribution.\n *   * Neither the name of Redis nor the names of its contributors may be used\n *     to endorse or promote products derived from this software without\n *     specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\"\n * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\n * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE\n * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR\n * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF\n * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS\n * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN\n * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)\n * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE\n * POSSIBILITY OF SUCH DAMAGE.\n */\n\n#include \"fmacros.h\"\n\n#include <sys/types.h>\n#include <sys/socket.h>\n#include <sys/stat.h>\n#include <sys/un.h>\n#include <sys/time.h>\n#include <netinet/in.h>\n#include <netinet/tcp.h>\n#include <arpa/inet.h>\n#include <unistd.h>\n#include <fcntl.h>\n#include <string.h>\n#include <netdb.h>\n#include <errno.h>\n#include <stdarg.h>\n#include <stdio.h>\n\n#include \"anet.h\"\n\nstatic void anetSetError(char *err, const char *fmt, ...)\n{\n    va_list ap;\n\n    if (!err) return;\n    va_start(ap, fmt);\n    vsnprintf(err, ANET_ERR_LEN, fmt, ap);\n    va_end(ap);\n}\n\nint anetSetBlock(char *err, int fd, int non_block) {\n    int flags;\n\n    /* Set the socket blocking (if non_block is zero) or non-blocking.\n     * Note that fcntl(2) for F_GETFL and F_SETFL can't be\n     * interrupted by a signal. */\n    if ((flags = fcntl(fd, F_GETFL)) == -1) {\n        anetSetError(err, \"fcntl(F_GETFL): %s\", strerror(errno));\n        return ANET_ERR;\n    }\n\n    if (non_block)\n        flags |= O_NONBLOCK;\n    else\n        flags &= ~O_NONBLOCK;\n\n    if (fcntl(fd, F_SETFL, flags) == -1) {\n        anetSetError(err, \"fcntl(F_SETFL,O_NONBLOCK): %s\", strerror(errno));\n        return ANET_ERR;\n    }\n    return ANET_OK;\n}\n\nint anetNonBlock(char *err, int fd) {\n    return anetSetBlock(err,fd,1);\n}\n\nint anetBlock(char *err, int fd) {\n    return anetSetBlock(err,fd,0);\n}\n\n/* Set TCP keep alive option to detect dead peers. The interval option\n * is only used for Linux as we are using Linux-specific APIs to set\n * the probe send time, interval, and count. */\nint anetKeepAlive(char *err, int fd, int interval)\n{\n    int val = 1;\n\n    if (setsockopt(fd, SOL_SOCKET, SO_KEEPALIVE, &val, sizeof(val)) == -1)\n    {\n        anetSetError(err, \"setsockopt SO_KEEPALIVE: %s\", strerror(errno));\n        return ANET_ERR;\n    }\n\n#ifdef __linux__\n    /* Default settings are more or less garbage, with the keepalive time\n     * set to 7200 by default on Linux. Modify settings to make the feature\n     * actually useful. */\n\n    /* Send first probe after interval. */\n    val = interval;\n    if (setsockopt(fd, IPPROTO_TCP, TCP_KEEPIDLE, &val, sizeof(val)) < 0) {\n        anetSetError(err, \"setsockopt TCP_KEEPIDLE: %s\\n\", strerror(errno));\n        return ANET_ERR;\n    }\n\n    /* Send next probes after the specified interval. Note that we set the\n     * delay as interval / 3, as we send three probes before detecting\n     * an error (see the next setsockopt call). */\n    val = interval/3;\n    if (val == 0) val = 1;\n    if (setsockopt(fd, IPPROTO_TCP, TCP_KEEPINTVL, &val, sizeof(val)) < 0) {\n        anetSetError(err, \"setsockopt TCP_KEEPINTVL: %s\\n\", strerror(errno));\n        return ANET_ERR;\n    }\n\n    /* Consider the socket in error state after three we send three ACK\n     * probes without getting a reply. */\n    val = 3;\n    if (setsockopt(fd, IPPROTO_TCP, TCP_KEEPCNT, &val, sizeof(val)) < 0) {\n        anetSetError(err, \"setsockopt TCP_KEEPCNT: %s\\n\", strerror(errno));\n        return ANET_ERR;\n    }\n#else\n    ((void) interval); /* Avoid unused var warning for non Linux systems. */\n#endif\n\n    return ANET_OK;\n}\n\nstatic int anetSetTcpNoDelay(char *err, int fd, int val)\n{\n    if (setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, &val, sizeof(val)) == -1)\n    {\n        anetSetError(err, \"setsockopt TCP_NODELAY: %s\", strerror(errno));\n        return ANET_ERR;\n    }\n    return ANET_OK;\n}\n\nint anetEnableTcpNoDelay(char *err, int fd)\n{\n    return anetSetTcpNoDelay(err, fd, 1);\n}\n\nint anetDisableTcpNoDelay(char *err, int fd)\n{\n    return anetSetTcpNoDelay(err, fd, 0);\n}\n\n\nint anetSetSendBuffer(char *err, int fd, int buffsize)\n{\n    if (setsockopt(fd, SOL_SOCKET, SO_SNDBUF, &buffsize, sizeof(buffsize)) == -1)\n    {\n        anetSetError(err, \"setsockopt SO_SNDBUF: %s\", strerror(errno));\n        return ANET_ERR;\n    }\n    return ANET_OK;\n}\n\nint anetTcpKeepAlive(char *err, int fd)\n{\n    int yes = 1;\n    if (setsockopt(fd, SOL_SOCKET, SO_KEEPALIVE, &yes, sizeof(yes)) == -1) {\n        anetSetError(err, \"setsockopt SO_KEEPALIVE: %s\", strerror(errno));\n        return ANET_ERR;\n    }\n    return ANET_OK;\n}\n\n/* Set the socket send timeout (SO_SNDTIMEO socket option) to the specified\n * number of milliseconds, or disable it if the 'ms' argument is zero. */\nint anetSendTimeout(char *err, int fd, long long ms) {\n    struct timeval tv;\n\n    tv.tv_sec = ms/1000;\n    tv.tv_usec = (ms%1000)*1000;\n    if (setsockopt(fd, SOL_SOCKET, SO_SNDTIMEO, &tv, sizeof(tv)) == -1) {\n        anetSetError(err, \"setsockopt SO_SNDTIMEO: %s\", strerror(errno));\n        return ANET_ERR;\n    }\n    return ANET_OK;\n}\n\n/* anetGenericResolve() is called by anetResolve() and anetResolveIP() to\n * do the actual work. It resolves the hostname \"host\" and set the string\n * representation of the IP address into the buffer pointed by \"ipbuf\".\n *\n * If flags is set to ANET_IP_ONLY the function only resolves hostnames\n * that are actually already IPv4 or IPv6 addresses. This turns the function\n * into a validating / normalizing function. */\nint anetGenericResolve(char *err, char *host, char *ipbuf, size_t ipbuf_len,\n                       int flags)\n{\n    struct addrinfo hints, *info;\n    int rv;\n\n    memset(&hints,0,sizeof(hints));\n    if (flags & ANET_IP_ONLY) hints.ai_flags = AI_NUMERICHOST;\n    hints.ai_family = AF_UNSPEC;\n    hints.ai_socktype = SOCK_STREAM;  /* specify socktype to avoid dups */\n\n    if ((rv = getaddrinfo(host, NULL, &hints, &info)) != 0) {\n        anetSetError(err, \"%s\", gai_strerror(rv));\n        return ANET_ERR;\n    }\n    if (info->ai_family == AF_INET) {\n        struct sockaddr_in *sa = (struct sockaddr_in *)info->ai_addr;\n        inet_ntop(AF_INET, &(sa->sin_addr), ipbuf, ipbuf_len);\n    } else {\n        struct sockaddr_in6 *sa = (struct sockaddr_in6 *)info->ai_addr;\n        inet_ntop(AF_INET6, &(sa->sin6_addr), ipbuf, ipbuf_len);\n    }\n\n    freeaddrinfo(info);\n    return ANET_OK;\n}\n\nint anetResolve(char *err, char *host, char *ipbuf, size_t ipbuf_len) {\n    return anetGenericResolve(err,host,ipbuf,ipbuf_len,ANET_NONE);\n}\n\nint anetResolveIP(char *err, char *host, char *ipbuf, size_t ipbuf_len) {\n    return anetGenericResolve(err,host,ipbuf,ipbuf_len,ANET_IP_ONLY);\n}\n\nstatic int anetSetReuseAddr(char *err, int fd) {\n    int yes = 1;\n    /* Make sure connection-intensive things like the redis benckmark\n     * will be able to close/open sockets a zillion of times */\n    if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(yes)) == -1) {\n        anetSetError(err, \"setsockopt SO_REUSEADDR: %s\", strerror(errno));\n        return ANET_ERR;\n    }\n    return ANET_OK;\n}\n\nstatic int anetCreateSocket(char *err, int domain) {\n    int s;\n    if ((s = socket(domain, SOCK_STREAM, 0)) == -1) {\n        anetSetError(err, \"creating socket: %s\", strerror(errno));\n        return ANET_ERR;\n    }\n\n    /* Make sure connection-intensive things like the redis benchmark\n     * will be able to close/open sockets a zillion of times */\n    if (anetSetReuseAddr(err,s) == ANET_ERR) {\n        close(s);\n        return ANET_ERR;\n    }\n    return s;\n}\n\n#define ANET_CONNECT_NONE 0\n#define ANET_CONNECT_NONBLOCK 1\n#define ANET_CONNECT_BE_BINDING 2 /* Best effort binding. */\nstatic int anetTcpGenericConnect(char *err, char *addr, int port,\n                                 char *source_addr, int flags)\n{\n    int s = ANET_ERR, rv;\n    char portstr[6];  /* strlen(\"65535\") + 1; */\n    struct addrinfo hints, *servinfo, *bservinfo, *p, *b;\n\n    snprintf(portstr,sizeof(portstr),\"%d\",port);\n    memset(&hints,0,sizeof(hints));\n    hints.ai_family = AF_UNSPEC;\n    hints.ai_socktype = SOCK_STREAM;\n\n    if ((rv = getaddrinfo(addr,portstr,&hints,&servinfo)) != 0) {\n        anetSetError(err, \"%s\", gai_strerror(rv));\n        return ANET_ERR;\n    }\n    for (p = servinfo; p != NULL; p = p->ai_next) {\n        /* Try to create the socket and to connect it.\n         * If we fail in the socket() call, or on connect(), we retry with\n         * the next entry in servinfo. */\n        if ((s = socket(p->ai_family,p->ai_socktype,p->ai_protocol)) == -1)\n            continue;\n        if (anetSetReuseAddr(err,s) == ANET_ERR) goto error;\n        if (flags & ANET_CONNECT_NONBLOCK && anetNonBlock(err,s) != ANET_OK)\n            goto error;\n        if (source_addr) {\n            int bound = 0;\n            /* Using getaddrinfo saves us from self-determining IPv4 vs IPv6 */\n            if ((rv = getaddrinfo(source_addr, NULL, &hints, &bservinfo)) != 0)\n            {\n                anetSetError(err, \"%s\", gai_strerror(rv));\n                goto error;\n            }\n            for (b = bservinfo; b != NULL; b = b->ai_next) {\n                if (bind(s,b->ai_addr,b->ai_addrlen) != -1) {\n                    bound = 1;\n                    break;\n                }\n            }\n            freeaddrinfo(bservinfo);\n            if (!bound) {\n                anetSetError(err, \"bind: %s\", strerror(errno));\n                goto error;\n            }\n        }\n        if (connect(s,p->ai_addr,p->ai_addrlen) == -1) {\n            /* If the socket is non-blocking, it is ok for connect() to\n             * return an EINPROGRESS error here. */\n            if (errno == EINPROGRESS && flags & ANET_CONNECT_NONBLOCK)\n                goto end;\n            close(s);\n            s = ANET_ERR;\n            continue;\n        }\n\n        /* If we ended an iteration of the for loop without errors, we\n         * have a connected socket. Let's return to the caller. */\n        goto end;\n    }\n    if (p == NULL)\n        anetSetError(err, \"creating socket: %s\", strerror(errno));\n\nerror:\n    if (s != ANET_ERR) {\n        close(s);\n        s = ANET_ERR;\n    }\n\nend:\n    freeaddrinfo(servinfo);\n\n    /* Handle best effort binding: if a binding address was used, but it is\n     * not possible to create a socket, try again without a binding address. */\n    if (s == ANET_ERR && source_addr && (flags & ANET_CONNECT_BE_BINDING)) {\n        return anetTcpGenericConnect(err,addr,port,NULL,flags);\n    } else {\n        return s;\n    }\n}\n\nint anetTcpConnect(char *err, char *addr, int port)\n{\n    return anetTcpGenericConnect(err,addr,port,NULL,ANET_CONNECT_NONE);\n}\n\nint anetTcpNonBlockConnect(char *err, char *addr, int port)\n{\n    return anetTcpGenericConnect(err,addr,port,NULL,ANET_CONNECT_NONBLOCK);\n}\n\nint anetTcpNonBlockBindConnect(char *err, char *addr, int port,\n                               char *source_addr)\n{\n    return anetTcpGenericConnect(err,addr,port,source_addr,\n            ANET_CONNECT_NONBLOCK);\n}\n\nint anetTcpNonBlockBestEffortBindConnect(char *err, char *addr, int port,\n                                         char *source_addr)\n{\n    return anetTcpGenericConnect(err,addr,port,source_addr,\n            ANET_CONNECT_NONBLOCK|ANET_CONNECT_BE_BINDING);\n}\n\nint anetUnixGenericConnect(char *err, char *path, int flags)\n{\n    int s;\n    struct sockaddr_un sa;\n\n    if ((s = anetCreateSocket(err,AF_LOCAL)) == ANET_ERR)\n        return ANET_ERR;\n\n    sa.sun_family = AF_LOCAL;\n    strncpy(sa.sun_path,path,sizeof(sa.sun_path)-1);\n    if (flags & ANET_CONNECT_NONBLOCK) {\n        if (anetNonBlock(err,s) != ANET_OK)\n            return ANET_ERR;\n    }\n    if (connect(s,(struct sockaddr*)&sa,sizeof(sa)) == -1) {\n        if (errno == EINPROGRESS &&\n            flags & ANET_CONNECT_NONBLOCK)\n            return s;\n\n        anetSetError(err, \"connect: %s\", strerror(errno));\n        close(s);\n        return ANET_ERR;\n    }\n    return s;\n}\n\nint anetUnixConnect(char *err, char *path)\n{\n    return anetUnixGenericConnect(err,path,ANET_CONNECT_NONE);\n}\n\nint anetUnixNonBlockConnect(char *err, char *path)\n{\n    return anetUnixGenericConnect(err,path,ANET_CONNECT_NONBLOCK);\n}\n\n/* Like read(2) but make sure 'count' is read before to return\n * (unless error or EOF condition is encountered) */\nint anetRead(int fd, char *buf, int count)\n{\n    ssize_t nread, totlen = 0;\n    while(totlen != count) {\n        nread = read(fd,buf,count-totlen);\n        if (nread == 0) return totlen;\n        if (nread == -1) return -1;\n        totlen += nread;\n        buf += nread;\n    }\n    return totlen;\n}\n\n/* Like write(2) but make sure 'count' is written before to return\n * (unless error is encountered) */\nint anetWrite(int fd, char *buf, int count)\n{\n    ssize_t nwritten, totlen = 0;\n    while(totlen != count) {\n        nwritten = write(fd,buf,count-totlen);\n        if (nwritten == 0) return totlen;\n        if (nwritten == -1) return -1;\n        totlen += nwritten;\n        buf += nwritten;\n    }\n    return totlen;\n}\n\nstatic int anetListen(char *err, int s, struct sockaddr *sa, socklen_t len, int backlog) {\n    if (bind(s,sa,len) == -1) {\n        anetSetError(err, \"bind: %s\", strerror(errno));\n        close(s);\n        return ANET_ERR;\n    }\n\n    if (listen(s, backlog) == -1) {\n        anetSetError(err, \"listen: %s\", strerror(errno));\n        close(s);\n        return ANET_ERR;\n    }\n    return ANET_OK;\n}\n\nstatic int anetV6Only(char *err, int s) {\n    int yes = 1;\n    if (setsockopt(s,IPPROTO_IPV6,IPV6_V6ONLY,&yes,sizeof(yes)) == -1) {\n        anetSetError(err, \"setsockopt: %s\", strerror(errno));\n        close(s);\n        return ANET_ERR;\n    }\n    return ANET_OK;\n}\n\nstatic int _anetTcpServer(char *err, int port, char *bindaddr, int af, int backlog)\n{\n    int s = -1, rv;\n    char _port[6];  /* strlen(\"65535\") */\n    struct addrinfo hints, *servinfo, *p;\n\n    snprintf(_port,6,\"%d\",port);\n    memset(&hints,0,sizeof(hints));\n    hints.ai_family = af;\n    hints.ai_socktype = SOCK_STREAM;\n    hints.ai_flags = AI_PASSIVE;    /* No effect if bindaddr != NULL */\n\n    if ((rv = getaddrinfo(bindaddr,_port,&hints,&servinfo)) != 0) {\n        anetSetError(err, \"%s\", gai_strerror(rv));\n        return ANET_ERR;\n    }\n    for (p = servinfo; p != NULL; p = p->ai_next) {\n        if ((s = socket(p->ai_family,p->ai_socktype,p->ai_protocol)) == -1)\n            continue;\n\n        if (af == AF_INET6 && anetV6Only(err,s) == ANET_ERR) goto error;\n        if (anetSetReuseAddr(err,s) == ANET_ERR) goto error;\n        if (anetListen(err,s,p->ai_addr,p->ai_addrlen,backlog) == ANET_ERR) goto error;\n        goto end;\n    }\n    if (p == NULL) {\n        anetSetError(err, \"unable to bind socket, errno: %d\", errno);\n        goto error;\n    }\n\nerror:\n    if (s != -1) close(s);\n    s = ANET_ERR;\nend:\n    freeaddrinfo(servinfo);\n    return s;\n}\n\nint anetTcpServer(char *err, int port, char *bindaddr, int backlog)\n{\n    return _anetTcpServer(err, port, bindaddr, AF_INET, backlog);\n}\n\nint anetTcp6Server(char *err, int port, char *bindaddr, int backlog)\n{\n    return _anetTcpServer(err, port, bindaddr, AF_INET6, backlog);\n}\n\nint anetUnixServer(char *err, char *path, mode_t perm, int backlog)\n{\n    int s;\n    struct sockaddr_un sa;\n\n    if ((s = anetCreateSocket(err,AF_LOCAL)) == ANET_ERR)\n        return ANET_ERR;\n\n    memset(&sa,0,sizeof(sa));\n    sa.sun_family = AF_LOCAL;\n    strncpy(sa.sun_path,path,sizeof(sa.sun_path)-1);\n    if (anetListen(err,s,(struct sockaddr*)&sa,sizeof(sa),backlog) == ANET_ERR)\n        return ANET_ERR;\n    if (perm)\n        chmod(sa.sun_path, perm);\n    return s;\n}\n\nstatic int anetGenericAccept(char *err, int s, struct sockaddr *sa, socklen_t *len) {\n    int fd;\n    while(1) {\n        fd = accept(s,sa,len);\n        if (fd == -1) {\n            if (errno == EINTR)\n                continue;\n            else {\n                anetSetError(err, \"accept: %s\", strerror(errno));\n                return ANET_ERR;\n            }\n        }\n        break;\n    }\n    return fd;\n}\n\nint anetTcpAccept(char *err, int s, char *ip, size_t ip_len, int *port) {\n    int fd;\n    struct sockaddr_storage sa;\n    socklen_t salen = sizeof(sa);\n    if ((fd = anetGenericAccept(err,s,(struct sockaddr*)&sa,&salen)) == -1)\n        return ANET_ERR;\n\n    if (sa.ss_family == AF_INET) {\n        struct sockaddr_in *s = (struct sockaddr_in *)&sa;\n        if (ip) inet_ntop(AF_INET,(void*)&(s->sin_addr),ip,ip_len);\n        if (port) *port = ntohs(s->sin_port);\n    } else {\n        struct sockaddr_in6 *s = (struct sockaddr_in6 *)&sa;\n        if (ip) inet_ntop(AF_INET6,(void*)&(s->sin6_addr),ip,ip_len);\n        if (port) *port = ntohs(s->sin6_port);\n    }\n    return fd;\n}\n\nint anetUnixAccept(char *err, int s) {\n    int fd;\n    struct sockaddr_un sa;\n    socklen_t salen = sizeof(sa);\n    if ((fd = anetGenericAccept(err,s,(struct sockaddr*)&sa,&salen)) == -1)\n        return ANET_ERR;\n\n    return fd;\n}\n\nint anetPeerToString(int fd, char *ip, size_t ip_len, int *port) {\n    struct sockaddr_storage sa;\n    socklen_t salen = sizeof(sa);\n\n    if (getpeername(fd,(struct sockaddr*)&sa,&salen) == -1) goto error;\n    if (ip_len == 0) goto error;\n\n    if (sa.ss_family == AF_INET) {\n        struct sockaddr_in *s = (struct sockaddr_in *)&sa;\n        if (ip) inet_ntop(AF_INET,(void*)&(s->sin_addr),ip,ip_len);\n        if (port) *port = ntohs(s->sin_port);\n    } else if (sa.ss_family == AF_INET6) {\n        struct sockaddr_in6 *s = (struct sockaddr_in6 *)&sa;\n        if (ip) inet_ntop(AF_INET6,(void*)&(s->sin6_addr),ip,ip_len);\n        if (port) *port = ntohs(s->sin6_port);\n    } else if (sa.ss_family == AF_UNIX) {\n        if (ip) strncpy(ip,\"/unixsocket\",ip_len);\n        if (port) *port = 0;\n    } else {\n        goto error;\n    }\n    return 0;\n\nerror:\n    if (ip) {\n        if (ip_len >= 2) {\n            ip[0] = '?';\n            ip[1] = '\\0';\n        } else if (ip_len == 1) {\n            ip[0] = '\\0';\n        }\n    }\n    if (port) *port = 0;\n    return -1;\n}\n\n/* Format an IP,port pair into something easy to parse. If IP is IPv6\n * (matches for \":\"), the ip is surrounded by []. IP and port are just\n * separated by colons. This the standard to display addresses within Redis. */\nint anetFormatAddr(char *buf, size_t buf_len, char *ip, int port) {\n    return snprintf(buf,buf_len, strchr(ip,':') ?\n           \"[%s]:%d\" : \"%s:%d\", ip, port);\n}\n\n/* Like anetFormatAddr() but extract ip and port from the socket's peer. */\nint anetFormatPeer(int fd, char *buf, size_t buf_len) {\n    char ip[INET6_ADDRSTRLEN];\n    int port;\n\n    anetPeerToString(fd,ip,sizeof(ip),&port);\n    return anetFormatAddr(buf, buf_len, ip, port);\n}\n\nint anetSockName(int fd, char *ip, size_t ip_len, int *port) {\n    struct sockaddr_storage sa;\n    socklen_t salen = sizeof(sa);\n\n    if (getsockname(fd,(struct sockaddr*)&sa,&salen) == -1) {\n        if (port) *port = 0;\n        ip[0] = '?';\n        ip[1] = '\\0';\n        return -1;\n    }\n    if (sa.ss_family == AF_INET) {\n        struct sockaddr_in *s = (struct sockaddr_in *)&sa;\n        if (ip) inet_ntop(AF_INET,(void*)&(s->sin_addr),ip,ip_len);\n        if (port) *port = ntohs(s->sin_port);\n    } else {\n        struct sockaddr_in6 *s = (struct sockaddr_in6 *)&sa;\n        if (ip) inet_ntop(AF_INET6,(void*)&(s->sin6_addr),ip,ip_len);\n        if (port) *port = ntohs(s->sin6_port);\n    }\n    return 0;\n}\n\nint anetFormatSock(int fd, char *fmt, size_t fmt_len) {\n    char ip[INET6_ADDRSTRLEN];\n    int port;\n\n    anetSockName(fd,ip,sizeof(ip),&port);\n    return anetFormatAddr(fmt, fmt_len, ip, port);\n}\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.8/src/anet.h",
    "content": "/* anet.c -- Basic TCP socket stuff made a bit less boring\n *\n * Copyright (c) 2006-2012, Salvatore Sanfilippo <antirez at gmail dot com>\n * All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions are met:\n *\n *   * Redistributions of source code must retain the above copyright notice,\n *     this list of conditions and the following disclaimer.\n *   * Redistributions in binary form must reproduce the above copyright\n *     notice, this list of conditions and the following disclaimer in the\n *     documentation and/or other materials provided with the distribution.\n *   * Neither the name of Redis nor the names of its contributors may be used\n *     to endorse or promote products derived from this software without\n *     specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\"\n * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\n * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE\n * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR\n * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF\n * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS\n * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN\n * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)\n * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE\n * POSSIBILITY OF SUCH DAMAGE.\n */\n\n#ifndef ANET_H\n#define ANET_H\n\n#include <sys/types.h>\n\n#define ANET_OK 0\n#define ANET_ERR -1\n#define ANET_ERR_LEN 256\n\n/* Flags used with certain functions. */\n#define ANET_NONE 0\n#define ANET_IP_ONLY (1<<0)\n\n#if defined(__sun) || defined(_AIX)\n#define AF_LOCAL AF_UNIX\n#endif\n\n#ifdef _AIX\n#undef ip_len\n#endif\n\nint anetTcpConnect(char *err, char *addr, int port);\nint anetTcpNonBlockConnect(char *err, char *addr, int port);\nint anetTcpNonBlockBindConnect(char *err, char *addr, int port, char *source_addr);\nint anetTcpNonBlockBestEffortBindConnect(char *err, char *addr, int port, char *source_addr);\nint anetUnixConnect(char *err, char *path);\nint anetUnixNonBlockConnect(char *err, char *path);\nint anetRead(int fd, char *buf, int count);\nint anetResolve(char *err, char *host, char *ipbuf, size_t ipbuf_len);\nint anetResolveIP(char *err, char *host, char *ipbuf, size_t ipbuf_len);\nint anetTcpServer(char *err, int port, char *bindaddr, int backlog);\nint anetTcp6Server(char *err, int port, char *bindaddr, int backlog);\nint anetUnixServer(char *err, char *path, mode_t perm, int backlog);\nint anetTcpAccept(char *err, int serversock, char *ip, size_t ip_len, int *port);\nint anetUnixAccept(char *err, int serversock);\nint anetWrite(int fd, char *buf, int count);\nint anetNonBlock(char *err, int fd);\nint anetBlock(char *err, int fd);\nint anetEnableTcpNoDelay(char *err, int fd);\nint anetDisableTcpNoDelay(char *err, int fd);\nint anetTcpKeepAlive(char *err, int fd);\nint anetSendTimeout(char *err, int fd, long long ms);\nint anetPeerToString(int fd, char *ip, size_t ip_len, int *port);\nint anetKeepAlive(char *err, int fd, int interval);\nint anetSockName(int fd, char *ip, size_t ip_len, int *port);\nint anetFormatAddr(char *fmt, size_t fmt_len, char *ip, int port);\nint anetFormatPeer(int fd, char *fmt, size_t fmt_len);\nint anetFormatSock(int fd, char *fmt, size_t fmt_len);\n\n#endif\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.8/src/aof.c",
    "content": "/*\n * Copyright (c) 2009-2012, Salvatore Sanfilippo <antirez at gmail dot com>\n * All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions are met:\n *\n *   * Redistributions of source code must retain the above copyright notice,\n *     this list of conditions and the following disclaimer.\n *   * Redistributions in binary form must reproduce the above copyright\n *     notice, this list of conditions and the following disclaimer in the\n *     documentation and/or other materials provided with the distribution.\n *   * Neither the name of Redis nor the names of its contributors may be used\n *     to endorse or promote products derived from this software without\n *     specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\"\n * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\n * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE\n * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR\n * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF\n * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS\n * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN\n * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)\n * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE\n * POSSIBILITY OF SUCH DAMAGE.\n */\n\n#include \"server.h\"\n#include \"bio.h\"\n#include \"rio.h\"\n\n#include <signal.h>\n#include <fcntl.h>\n#include <sys/stat.h>\n#include <sys/types.h>\n#include <sys/time.h>\n#include <sys/resource.h>\n#include <sys/wait.h>\n#include <sys/param.h>\n\nvoid aofUpdateCurrentSize(void);\nvoid aofClosePipes(void);\n\n/* ----------------------------------------------------------------------------\n * AOF rewrite buffer implementation.\n *\n * The following code implement a simple buffer used in order to accumulate\n * changes while the background process is rewriting the AOF file.\n *\n * We only need to append, but can't just use realloc with a large block\n * because 'huge' reallocs are not always handled as one could expect\n * (via remapping of pages at OS level) but may involve copying data.\n *\n * For this reason we use a list of blocks, every block is\n * AOF_RW_BUF_BLOCK_SIZE bytes.\n * ------------------------------------------------------------------------- */\n\n#define AOF_RW_BUF_BLOCK_SIZE (1024*1024*10)    /* 10 MB per block */\n\ntypedef struct aofrwblock {\n    unsigned long used, free;\n    char buf[AOF_RW_BUF_BLOCK_SIZE];\n} aofrwblock;\n\n/* This function free the old AOF rewrite buffer if needed, and initialize\n * a fresh new one. It tests for server.aof_rewrite_buf_blocks equal to NULL\n * so can be used for the first initialization as well. */\nvoid aofRewriteBufferReset(void) {\n    if (server.aof_rewrite_buf_blocks)\n        listRelease(server.aof_rewrite_buf_blocks);\n\n    server.aof_rewrite_buf_blocks = listCreate();\n    listSetFreeMethod(server.aof_rewrite_buf_blocks,zfree);\n}\n\n/* Return the current size of the AOF rewrite buffer. */\nunsigned long aofRewriteBufferSize(void) {\n    listNode *ln;\n    listIter li;\n    unsigned long size = 0;\n\n    listRewind(server.aof_rewrite_buf_blocks,&li);\n    while((ln = listNext(&li))) {\n        aofrwblock *block = listNodeValue(ln);\n        size += block->used;\n    }\n    return size;\n}\n\n/* Event handler used to send data to the child process doing the AOF\n * rewrite. We send pieces of our AOF differences buffer so that the final\n * write when the child finishes the rewrite will be small. */\nvoid aofChildWriteDiffData(aeEventLoop *el, int fd, void *privdata, int mask) {\n    listNode *ln;\n    aofrwblock *block;\n    ssize_t nwritten;\n    UNUSED(el);\n    UNUSED(fd);\n    UNUSED(privdata);\n    UNUSED(mask);\n\n    while(1) {\n        ln = listFirst(server.aof_rewrite_buf_blocks);\n        block = ln ? ln->value : NULL;\n        if (server.aof_stop_sending_diff || !block) {\n            aeDeleteFileEvent(server.el,server.aof_pipe_write_data_to_child,\n                              AE_WRITABLE);\n            return;\n        }\n        if (block->used > 0) {\n            nwritten = write(server.aof_pipe_write_data_to_child,\n                             block->buf,block->used);\n            if (nwritten <= 0) return;\n            memmove(block->buf,block->buf+nwritten,block->used-nwritten);\n            block->used -= nwritten;\n            block->free += nwritten;\n        }\n        if (block->used == 0) listDelNode(server.aof_rewrite_buf_blocks,ln);\n    }\n}\n\n/* Append data to the AOF rewrite buffer, allocating new blocks if needed. */\nvoid aofRewriteBufferAppend(unsigned char *s, unsigned long len) {\n    listNode *ln = listLast(server.aof_rewrite_buf_blocks);\n    aofrwblock *block = ln ? ln->value : NULL;\n\n    while(len) {\n        /* If we already got at least an allocated block, try appending\n         * at least some piece into it. */\n        if (block) {\n            unsigned long thislen = (block->free < len) ? block->free : len;\n            if (thislen) {  /* The current block is not already full. */\n                memcpy(block->buf+block->used, s, thislen);\n                block->used += thislen;\n                block->free -= thislen;\n                s += thislen;\n                len -= thislen;\n            }\n        }\n\n        if (len) { /* First block to allocate, or need another block. */\n            int numblocks;\n\n            block = zmalloc(sizeof(*block));\n            block->free = AOF_RW_BUF_BLOCK_SIZE;\n            block->used = 0;\n            listAddNodeTail(server.aof_rewrite_buf_blocks,block);\n\n            /* Log every time we cross more 10 or 100 blocks, respectively\n             * as a notice or warning. */\n            numblocks = listLength(server.aof_rewrite_buf_blocks);\n            if (((numblocks+1) % 10) == 0) {\n                int level = ((numblocks+1) % 100) == 0 ? LL_WARNING :\n                                                         LL_NOTICE;\n                serverLog(level,\"Background AOF buffer size: %lu MB\",\n                    aofRewriteBufferSize()/(1024*1024));\n            }\n        }\n    }\n\n    /* Install a file event to send data to the rewrite child if there is\n     * not one already. */\n    if (aeGetFileEvents(server.el,server.aof_pipe_write_data_to_child) == 0) {\n        aeCreateFileEvent(server.el, server.aof_pipe_write_data_to_child,\n            AE_WRITABLE, aofChildWriteDiffData, NULL);\n    }\n}\n\n/* Write the buffer (possibly composed of multiple blocks) into the specified\n * fd. If a short write or any other error happens -1 is returned,\n * otherwise the number of bytes written is returned. */\nssize_t aofRewriteBufferWrite(int fd) {\n    listNode *ln;\n    listIter li;\n    ssize_t count = 0;\n\n    listRewind(server.aof_rewrite_buf_blocks,&li);\n    while((ln = listNext(&li))) {\n        aofrwblock *block = listNodeValue(ln);\n        ssize_t nwritten;\n\n        if (block->used) {\n            nwritten = write(fd,block->buf,block->used);\n            if (nwritten != (ssize_t)block->used) {\n                if (nwritten == 0) errno = EIO;\n                return -1;\n            }\n            count += nwritten;\n        }\n    }\n    return count;\n}\n\n/* ----------------------------------------------------------------------------\n * AOF file implementation\n * ------------------------------------------------------------------------- */\n\n/* Starts a background task that performs fsync() against the specified\n * file descriptor (the one of the AOF file) in another thread. */\nvoid aof_background_fsync(int fd) {\n    bioCreateBackgroundJob(BIO_AOF_FSYNC,(void*)(long)fd,NULL,NULL);\n}\n\n/* Called when the user switches from \"appendonly yes\" to \"appendonly no\"\n * at runtime using the CONFIG command. */\nvoid stopAppendOnly(void) {\n    serverAssert(server.aof_state != AOF_OFF);\n    flushAppendOnlyFile(1);\n    aof_fsync(server.aof_fd);\n    close(server.aof_fd);\n\n    server.aof_fd = -1;\n    server.aof_selected_db = -1;\n    server.aof_state = AOF_OFF;\n    /* rewrite operation in progress? kill it, wait child exit */\n    if (server.aof_child_pid != -1) {\n        int statloc;\n\n        serverLog(LL_NOTICE,\"Killing running AOF rewrite child: %ld\",\n            (long) server.aof_child_pid);\n        if (kill(server.aof_child_pid,SIGUSR1) != -1) {\n            while(wait3(&statloc,0,NULL) != server.aof_child_pid);\n        }\n        /* reset the buffer accumulating changes while the child saves */\n        aofRewriteBufferReset();\n        aofRemoveTempFile(server.aof_child_pid);\n        server.aof_child_pid = -1;\n        server.aof_rewrite_time_start = -1;\n        /* close pipes used for IPC between the two processes. */\n        aofClosePipes();\n    }\n}\n\n/* Called when the user switches from \"appendonly no\" to \"appendonly yes\"\n * at runtime using the CONFIG command. */\nint startAppendOnly(void) {\n    char cwd[MAXPATHLEN]; /* Current working dir path for error messages. */\n\n    server.aof_last_fsync = server.unixtime;\n    server.aof_fd = open(server.aof_filename,O_WRONLY|O_APPEND|O_CREAT,0644);\n    serverAssert(server.aof_state == AOF_OFF);\n    if (server.aof_fd == -1) {\n        char *cwdp = getcwd(cwd,MAXPATHLEN);\n\n        serverLog(LL_WARNING,\n            \"Redis needs to enable the AOF but can't open the \"\n            \"append only file %s (in server root dir %s): %s\",\n            server.aof_filename,\n            cwdp ? cwdp : \"unknown\",\n            strerror(errno));\n        return C_ERR;\n    }\n    if (server.rdb_child_pid != -1) {\n        server.aof_rewrite_scheduled = 1;\n        serverLog(LL_WARNING,\"AOF was enabled but there is already a child process saving an RDB file on disk. An AOF background was scheduled to start when possible.\");\n    } else if (rewriteAppendOnlyFileBackground() == C_ERR) {\n        close(server.aof_fd);\n        serverLog(LL_WARNING,\"Redis needs to enable the AOF but can't trigger a background AOF rewrite operation. Check the above logs for more info about the error.\");\n        return C_ERR;\n    }\n    /* We correctly switched on AOF, now wait for the rewrite to be complete\n     * in order to append data on disk. */\n    server.aof_state = AOF_WAIT_REWRITE;\n    return C_OK;\n}\n\n/* Write the append only file buffer on disk.\n *\n * Since we are required to write the AOF before replying to the client,\n * and the only way the client socket can get a write is entering when the\n * the event loop, we accumulate all the AOF writes in a memory\n * buffer and write it on disk using this function just before entering\n * the event loop again.\n *\n * About the 'force' argument:\n *\n * When the fsync policy is set to 'everysec' we may delay the flush if there\n * is still an fsync() going on in the background thread, since for instance\n * on Linux write(2) will be blocked by the background fsync anyway.\n * When this happens we remember that there is some aof buffer to be\n * flushed ASAP, and will try to do that in the serverCron() function.\n *\n * However if force is set to 1 we'll write regardless of the background\n * fsync. */\n#define AOF_WRITE_LOG_ERROR_RATE 30 /* Seconds between errors logging. */\nvoid flushAppendOnlyFile(int force) {\n    ssize_t nwritten;\n    int sync_in_progress = 0;\n    mstime_t latency;\n\n    if (sdslen(server.aof_buf) == 0) return;\n\n    if (server.aof_fsync == AOF_FSYNC_EVERYSEC)\n        sync_in_progress = bioPendingJobsOfType(BIO_AOF_FSYNC) != 0;\n\n    if (server.aof_fsync == AOF_FSYNC_EVERYSEC && !force) {\n        /* With this append fsync policy we do background fsyncing.\n         * If the fsync is still in progress we can try to delay\n         * the write for a couple of seconds. */\n        if (sync_in_progress) {\n            if (server.aof_flush_postponed_start == 0) {\n                /* No previous write postponing, remember that we are\n                 * postponing the flush and return. */\n                server.aof_flush_postponed_start = server.unixtime;\n                return;\n            } else if (server.unixtime - server.aof_flush_postponed_start < 2) {\n                /* We were already waiting for fsync to finish, but for less\n                 * than two seconds this is still ok. Postpone again. */\n                return;\n            }\n            /* Otherwise fall trough, and go write since we can't wait\n             * over two seconds. */\n            server.aof_delayed_fsync++;\n            serverLog(LL_NOTICE,\"Asynchronous AOF fsync is taking too long (disk is busy?). Writing the AOF buffer without waiting for fsync to complete, this may slow down Redis.\");\n        }\n    }\n    /* We want to perform a single write. This should be guaranteed atomic\n     * at least if the filesystem we are writing is a real physical one.\n     * While this will save us against the server being killed I don't think\n     * there is much to do about the whole server stopping for power problems\n     * or alike */\n\n    latencyStartMonitor(latency);\n    nwritten = write(server.aof_fd,server.aof_buf,sdslen(server.aof_buf));\n    latencyEndMonitor(latency);\n    /* We want to capture different events for delayed writes:\n     * when the delay happens with a pending fsync, or with a saving child\n     * active, and when the above two conditions are missing.\n     * We also use an additional event name to save all samples which is\n     * useful for graphing / monitoring purposes. */\n    if (sync_in_progress) {\n        latencyAddSampleIfNeeded(\"aof-write-pending-fsync\",latency);\n    } else if (server.aof_child_pid != -1 || server.rdb_child_pid != -1) {\n        latencyAddSampleIfNeeded(\"aof-write-active-child\",latency);\n    } else {\n        latencyAddSampleIfNeeded(\"aof-write-alone\",latency);\n    }\n    latencyAddSampleIfNeeded(\"aof-write\",latency);\n\n    /* We performed the write so reset the postponed flush sentinel to zero. */\n    server.aof_flush_postponed_start = 0;\n\n    if (nwritten != (signed)sdslen(server.aof_buf)) {\n        static time_t last_write_error_log = 0;\n        int can_log = 0;\n\n        /* Limit logging rate to 1 line per AOF_WRITE_LOG_ERROR_RATE seconds. */\n        if ((server.unixtime - last_write_error_log) > AOF_WRITE_LOG_ERROR_RATE) {\n            can_log = 1;\n            last_write_error_log = server.unixtime;\n        }\n\n        /* Log the AOF write error and record the error code. */\n        if (nwritten == -1) {\n            if (can_log) {\n                serverLog(LL_WARNING,\"Error writing to the AOF file: %s\",\n                    strerror(errno));\n                server.aof_last_write_errno = errno;\n            }\n        } else {\n            if (can_log) {\n                serverLog(LL_WARNING,\"Short write while writing to \"\n                                       \"the AOF file: (nwritten=%lld, \"\n                                       \"expected=%lld)\",\n                                       (long long)nwritten,\n                                       (long long)sdslen(server.aof_buf));\n            }\n\n            if (ftruncate(server.aof_fd, server.aof_current_size) == -1) {\n                if (can_log) {\n                    serverLog(LL_WARNING, \"Could not remove short write \"\n                             \"from the append-only file.  Redis may refuse \"\n                             \"to load the AOF the next time it starts.  \"\n                             \"ftruncate: %s\", strerror(errno));\n                }\n            } else {\n                /* If the ftruncate() succeeded we can set nwritten to\n                 * -1 since there is no longer partial data into the AOF. */\n                nwritten = -1;\n            }\n            server.aof_last_write_errno = ENOSPC;\n        }\n\n        /* Handle the AOF write error. */\n        if (server.aof_fsync == AOF_FSYNC_ALWAYS) {\n            /* We can't recover when the fsync policy is ALWAYS since the\n             * reply for the client is already in the output buffers, and we\n             * have the contract with the user that on acknowledged write data\n             * is synced on disk. */\n            serverLog(LL_WARNING,\"Can't recover from AOF write error when the AOF fsync policy is 'always'. Exiting...\");\n            exit(1);\n        } else {\n            /* Recover from failed write leaving data into the buffer. However\n             * set an error to stop accepting writes as long as the error\n             * condition is not cleared. */\n            server.aof_last_write_status = C_ERR;\n\n            /* Trim the sds buffer if there was a partial write, and there\n             * was no way to undo it with ftruncate(2). */\n            if (nwritten > 0) {\n                server.aof_current_size += nwritten;\n                sdsrange(server.aof_buf,nwritten,-1);\n            }\n            return; /* We'll try again on the next call... */\n        }\n    } else {\n        /* Successful write(2). If AOF was in error state, restore the\n         * OK state and log the event. */\n        if (server.aof_last_write_status == C_ERR) {\n            serverLog(LL_WARNING,\n                \"AOF write error looks solved, Redis can write again.\");\n            server.aof_last_write_status = C_OK;\n        }\n    }\n    server.aof_current_size += nwritten;\n\n    /* Re-use AOF buffer when it is small enough. The maximum comes from the\n     * arena size of 4k minus some overhead (but is otherwise arbitrary). */\n    if ((sdslen(server.aof_buf)+sdsavail(server.aof_buf)) < 4000) {\n        sdsclear(server.aof_buf);\n    } else {\n        sdsfree(server.aof_buf);\n        server.aof_buf = sdsempty();\n    }\n\n    /* Don't fsync if no-appendfsync-on-rewrite is set to yes and there are\n     * children doing I/O in the background. */\n    if (server.aof_no_fsync_on_rewrite &&\n        (server.aof_child_pid != -1 || server.rdb_child_pid != -1))\n            return;\n\n    /* Perform the fsync if needed. */\n    if (server.aof_fsync == AOF_FSYNC_ALWAYS) {\n        /* aof_fsync is defined as fdatasync() for Linux in order to avoid\n         * flushing metadata. */\n        latencyStartMonitor(latency);\n        aof_fsync(server.aof_fd); /* Let's try to get this data on the disk */\n        latencyEndMonitor(latency);\n        latencyAddSampleIfNeeded(\"aof-fsync-always\",latency);\n        server.aof_last_fsync = server.unixtime;\n    } else if ((server.aof_fsync == AOF_FSYNC_EVERYSEC &&\n                server.unixtime > server.aof_last_fsync)) {\n        if (!sync_in_progress) aof_background_fsync(server.aof_fd);\n        server.aof_last_fsync = server.unixtime;\n    }\n}\n\nsds catAppendOnlyGenericCommand(sds dst, int argc, robj **argv) {\n    char buf[32];\n    int len, j;\n    robj *o;\n\n    buf[0] = '*';\n    len = 1+ll2string(buf+1,sizeof(buf)-1,argc);\n    buf[len++] = '\\r';\n    buf[len++] = '\\n';\n    dst = sdscatlen(dst,buf,len);\n\n    for (j = 0; j < argc; j++) {\n        o = getDecodedObject(argv[j]);\n        buf[0] = '$';\n        len = 1+ll2string(buf+1,sizeof(buf)-1,sdslen(o->ptr));\n        buf[len++] = '\\r';\n        buf[len++] = '\\n';\n        dst = sdscatlen(dst,buf,len);\n        dst = sdscatlen(dst,o->ptr,sdslen(o->ptr));\n        dst = sdscatlen(dst,\"\\r\\n\",2);\n        decrRefCount(o);\n    }\n    return dst;\n}\n\n/* Create the sds representation of an PEXPIREAT command, using\n * 'seconds' as time to live and 'cmd' to understand what command\n * we are translating into a PEXPIREAT.\n *\n * This command is used in order to translate EXPIRE and PEXPIRE commands\n * into PEXPIREAT command so that we retain precision in the append only\n * file, and the time is always absolute and not relative. */\nsds catAppendOnlyExpireAtCommand(sds buf, struct redisCommand *cmd, robj *key, robj *seconds) {\n    long long when;\n    robj *argv[3];\n\n    /* Make sure we can use strtoll */\n    seconds = getDecodedObject(seconds);\n    when = strtoll(seconds->ptr,NULL,10);\n    /* Convert argument into milliseconds for EXPIRE, SETEX, EXPIREAT */\n    if (cmd->proc == expireCommand || cmd->proc == setexCommand ||\n        cmd->proc == expireatCommand)\n    {\n        when *= 1000;\n    }\n    /* Convert into absolute time for EXPIRE, PEXPIRE, SETEX, PSETEX */\n    if (cmd->proc == expireCommand || cmd->proc == pexpireCommand ||\n        cmd->proc == setexCommand || cmd->proc == psetexCommand)\n    {\n        when += mstime();\n    }\n    decrRefCount(seconds);\n\n    argv[0] = createStringObject(\"PEXPIREAT\",9);\n    argv[1] = key;\n    argv[2] = createStringObjectFromLongLong(when);\n    buf = catAppendOnlyGenericCommand(buf, 3, argv);\n    decrRefCount(argv[0]);\n    decrRefCount(argv[2]);\n    return buf;\n}\n\nvoid feedAppendOnlyFile(struct redisCommand *cmd, int dictid, robj **argv, int argc) {\n    sds buf = sdsempty();\n    robj *tmpargv[3];\n\n    /* The DB this command was targeting is not the same as the last command\n     * we appended. To issue a SELECT command is needed. */\n    if (dictid != server.aof_selected_db) {\n        char seldb[64];\n\n        snprintf(seldb,sizeof(seldb),\"%d\",dictid);\n        buf = sdscatprintf(buf,\"*2\\r\\n$6\\r\\nSELECT\\r\\n$%lu\\r\\n%s\\r\\n\",\n            (unsigned long)strlen(seldb),seldb);\n        server.aof_selected_db = dictid;\n    }\n\n    if (cmd->proc == expireCommand || cmd->proc == pexpireCommand ||\n        cmd->proc == expireatCommand) {\n        /* Translate EXPIRE/PEXPIRE/EXPIREAT into PEXPIREAT */\n        buf = catAppendOnlyExpireAtCommand(buf,cmd,argv[1],argv[2]);\n    } else if (cmd->proc == setexCommand || cmd->proc == psetexCommand) {\n        /* Translate SETEX/PSETEX to SET and PEXPIREAT */\n        tmpargv[0] = createStringObject(\"SET\",3);\n        tmpargv[1] = argv[1];\n        tmpargv[2] = argv[3];\n        buf = catAppendOnlyGenericCommand(buf,3,tmpargv);\n        decrRefCount(tmpargv[0]);\n        buf = catAppendOnlyExpireAtCommand(buf,cmd,argv[1],argv[2]);\n    } else if (cmd->proc == setCommand && argc > 3) {\n        int i;\n        robj *exarg = NULL, *pxarg = NULL;\n        /* Translate SET [EX seconds][PX milliseconds] to SET and PEXPIREAT */\n        buf = catAppendOnlyGenericCommand(buf,3,argv);\n        for (i = 3; i < argc; i ++) {\n            if (!strcasecmp(argv[i]->ptr, \"ex\")) exarg = argv[i+1];\n            if (!strcasecmp(argv[i]->ptr, \"px\")) pxarg = argv[i+1];\n        }\n        serverAssert(!(exarg && pxarg));\n        if (exarg)\n            buf = catAppendOnlyExpireAtCommand(buf,server.expireCommand,argv[1],\n                                               exarg);\n        if (pxarg)\n            buf = catAppendOnlyExpireAtCommand(buf,server.pexpireCommand,argv[1],\n                                               pxarg);\n    } else {\n        /* All the other commands don't need translation or need the\n         * same translation already operated in the command vector\n         * for the replication itself. */\n        buf = catAppendOnlyGenericCommand(buf,argc,argv);\n    }\n\n    /* Append to the AOF buffer. This will be flushed on disk just before\n     * of re-entering the event loop, so before the client will get a\n     * positive reply about the operation performed. */\n    if (server.aof_state == AOF_ON)\n        server.aof_buf = sdscatlen(server.aof_buf,buf,sdslen(buf));\n\n    /* If a background append only file rewriting is in progress we want to\n     * accumulate the differences between the child DB and the current one\n     * in a buffer, so that when the child process will do its work we\n     * can append the differences to the new append only file. */\n    if (server.aof_child_pid != -1)\n        aofRewriteBufferAppend((unsigned char*)buf,sdslen(buf));\n\n    sdsfree(buf);\n}\n\n/* ----------------------------------------------------------------------------\n * AOF loading\n * ------------------------------------------------------------------------- */\n\n/* In Redis commands are always executed in the context of a client, so in\n * order to load the append only file we need to create a fake client. */\nstruct client *createFakeClient(void) {\n    struct client *c = zmalloc(sizeof(*c));\n\n    selectDb(c,0);\n    c->fd = -1;\n    c->name = NULL;\n    c->querybuf = sdsempty();\n    c->querybuf_peak = 0;\n    c->argc = 0;\n    c->argv = NULL;\n    c->bufpos = 0;\n    c->flags = 0;\n    c->btype = BLOCKED_NONE;\n    /* We set the fake client as a slave waiting for the synchronization\n     * so that Redis will not try to send replies to this client. */\n    c->replstate = SLAVE_STATE_WAIT_BGSAVE_START;\n    c->reply = listCreate();\n    c->reply_bytes = 0;\n    c->obuf_soft_limit_reached_time = 0;\n    c->watched_keys = listCreate();\n    c->peerid = NULL;\n    listSetFreeMethod(c->reply,decrRefCountVoid);\n    listSetDupMethod(c->reply,dupClientReplyValue);\n    initClientMultiState(c);\n    return c;\n}\n\nvoid freeFakeClientArgv(struct client *c) {\n    int j;\n\n    for (j = 0; j < c->argc; j++)\n        decrRefCount(c->argv[j]);\n    zfree(c->argv);\n}\n\nvoid freeFakeClient(struct client *c) {\n    sdsfree(c->querybuf);\n    listRelease(c->reply);\n    listRelease(c->watched_keys);\n    freeClientMultiState(c);\n    zfree(c);\n}\n\n/* Replay the append log file. On success C_OK is returned. On non fatal\n * error (the append only file is zero-length) C_ERR is returned. On\n * fatal error an error message is logged and the program exists. */\nint loadAppendOnlyFile(char *filename) {\n    struct client *fakeClient;\n    FILE *fp = fopen(filename,\"r\");\n    struct redis_stat sb;\n    int old_aof_state = server.aof_state;\n    long loops = 0;\n    off_t valid_up_to = 0; /* Offset of the latest well-formed command loaded. */\n\n    if (fp && redis_fstat(fileno(fp),&sb) != -1 && sb.st_size == 0) {\n        server.aof_current_size = 0;\n        fclose(fp);\n        return C_ERR;\n    }\n\n    if (fp == NULL) {\n        serverLog(LL_WARNING,\"Fatal error: can't open the append log file for reading: %s\",strerror(errno));\n        exit(1);\n    }\n\n    /* Temporarily disable AOF, to prevent EXEC from feeding a MULTI\n     * to the same file we're about to read. */\n    server.aof_state = AOF_OFF;\n\n    fakeClient = createFakeClient();\n    startLoading(fp);\n\n    while(1) {\n        int argc, j;\n        unsigned long len;\n        robj **argv;\n        char buf[128];\n        sds argsds;\n        struct redisCommand *cmd;\n\n        /* Serve the clients from time to time */\n        if (!(loops++ % 1000)) {\n            loadingProgress(ftello(fp));\n            processEventsWhileBlocked();\n        }\n\n        if (fgets(buf,sizeof(buf),fp) == NULL) {\n            if (feof(fp))\n                break;\n            else\n                goto readerr;\n        }\n        if (buf[0] != '*') goto fmterr;\n        if (buf[1] == '\\0') goto readerr;\n        argc = atoi(buf+1);\n        if (argc < 1) goto fmterr;\n\n        argv = zmalloc(sizeof(robj*)*argc);\n        fakeClient->argc = argc;\n        fakeClient->argv = argv;\n\n        for (j = 0; j < argc; j++) {\n            if (fgets(buf,sizeof(buf),fp) == NULL) {\n                fakeClient->argc = j; /* Free up to j-1. */\n                freeFakeClientArgv(fakeClient);\n                goto readerr;\n            }\n            if (buf[0] != '$') goto fmterr;\n            len = strtol(buf+1,NULL,10);\n            argsds = sdsnewlen(NULL,len);\n            if (len && fread(argsds,len,1,fp) == 0) {\n                sdsfree(argsds);\n                fakeClient->argc = j; /* Free up to j-1. */\n                freeFakeClientArgv(fakeClient);\n                goto readerr;\n            }\n            argv[j] = createObject(OBJ_STRING,argsds);\n            if (fread(buf,2,1,fp) == 0) {\n                fakeClient->argc = j+1; /* Free up to j. */\n                freeFakeClientArgv(fakeClient);\n                goto readerr; /* discard CRLF */\n            }\n        }\n\n        /* Command lookup */\n        cmd = lookupCommand(argv[0]->ptr);\n        if (!cmd) {\n            serverLog(LL_WARNING,\"Unknown command '%s' reading the append only file\", (char*)argv[0]->ptr);\n            exit(1);\n        }\n\n        /* Run the command in the context of a fake client */\n        cmd->proc(fakeClient);\n\n        /* The fake client should not have a reply */\n        serverAssert(fakeClient->bufpos == 0 && listLength(fakeClient->reply) == 0);\n        /* The fake client should never get blocked */\n        serverAssert((fakeClient->flags & CLIENT_BLOCKED) == 0);\n\n        /* Clean up. Command code may have changed argv/argc so we use the\n         * argv/argc of the client instead of the local variables. */\n        freeFakeClientArgv(fakeClient);\n        if (server.aof_load_truncated) valid_up_to = ftello(fp);\n    }\n\n    /* This point can only be reached when EOF is reached without errors.\n     * If the client is in the middle of a MULTI/EXEC, log error and quit. */\n    if (fakeClient->flags & CLIENT_MULTI) goto uxeof;\n\nloaded_ok: /* DB loaded, cleanup and return C_OK to the caller. */\n    fclose(fp);\n    freeFakeClient(fakeClient);\n    server.aof_state = old_aof_state;\n    stopLoading();\n    aofUpdateCurrentSize();\n    server.aof_rewrite_base_size = server.aof_current_size;\n    return C_OK;\n\nreaderr: /* Read error. If feof(fp) is true, fall through to unexpected EOF. */\n    if (!feof(fp)) {\n        if (fakeClient) freeFakeClient(fakeClient); /* avoid valgrind warning */\n        serverLog(LL_WARNING,\"Unrecoverable error reading the append only file: %s\", strerror(errno));\n        exit(1);\n    }\n\nuxeof: /* Unexpected AOF end of file. */\n    if (server.aof_load_truncated) {\n        serverLog(LL_WARNING,\"!!! Warning: short read while loading the AOF file !!!\");\n        serverLog(LL_WARNING,\"!!! Truncating the AOF at offset %llu !!!\",\n            (unsigned long long) valid_up_to);\n        if (valid_up_to == -1 || truncate(filename,valid_up_to) == -1) {\n            if (valid_up_to == -1) {\n                serverLog(LL_WARNING,\"Last valid command offset is invalid\");\n            } else {\n                serverLog(LL_WARNING,\"Error truncating the AOF file: %s\",\n                    strerror(errno));\n            }\n        } else {\n            /* Make sure the AOF file descriptor points to the end of the\n             * file after the truncate call. */\n            if (server.aof_fd != -1 && lseek(server.aof_fd,0,SEEK_END) == -1) {\n                serverLog(LL_WARNING,\"Can't seek the end of the AOF file: %s\",\n                    strerror(errno));\n            } else {\n                serverLog(LL_WARNING,\n                    \"AOF loaded anyway because aof-load-truncated is enabled\");\n                goto loaded_ok;\n            }\n        }\n    }\n    if (fakeClient) freeFakeClient(fakeClient); /* avoid valgrind warning */\n    serverLog(LL_WARNING,\"Unexpected end of file reading the append only file. You can: 1) Make a backup of your AOF file, then use ./redis-check-aof --fix <filename>. 2) Alternatively you can set the 'aof-load-truncated' configuration option to yes and restart the server.\");\n    exit(1);\n\nfmterr: /* Format error. */\n    if (fakeClient) freeFakeClient(fakeClient); /* avoid valgrind warning */\n    serverLog(LL_WARNING,\"Bad file format reading the append only file: make a backup of your AOF file, then use ./redis-check-aof --fix <filename>\");\n    exit(1);\n}\n\n/* ----------------------------------------------------------------------------\n * AOF rewrite\n * ------------------------------------------------------------------------- */\n\n/* Delegate writing an object to writing a bulk string or bulk long long.\n * This is not placed in rio.c since that adds the server.h dependency. */\nint rioWriteBulkObject(rio *r, robj *obj) {\n    /* Avoid using getDecodedObject to help copy-on-write (we are often\n     * in a child process when this function is called). */\n    if (obj->encoding == OBJ_ENCODING_INT) {\n        return rioWriteBulkLongLong(r,(long)obj->ptr);\n    } else if (sdsEncodedObject(obj)) {\n        return rioWriteBulkString(r,obj->ptr,sdslen(obj->ptr));\n    } else {\n        serverPanic(\"Unknown string encoding\");\n    }\n}\n\n/* Emit the commands needed to rebuild a list object.\n * The function returns 0 on error, 1 on success. */\nint rewriteListObject(rio *r, robj *key, robj *o) {\n    long long count = 0, items = listTypeLength(o);\n\n    if (o->encoding == OBJ_ENCODING_QUICKLIST) {\n        quicklist *list = o->ptr;\n        quicklistIter *li = quicklistGetIterator(list, AL_START_HEAD);\n        quicklistEntry entry;\n\n        while (quicklistNext(li,&entry)) {\n            if (count == 0) {\n                int cmd_items = (items > AOF_REWRITE_ITEMS_PER_CMD) ?\n                    AOF_REWRITE_ITEMS_PER_CMD : items;\n                if (rioWriteBulkCount(r,'*',2+cmd_items) == 0) return 0;\n                if (rioWriteBulkString(r,\"RPUSH\",5) == 0) return 0;\n                if (rioWriteBulkObject(r,key) == 0) return 0;\n            }\n\n            if (entry.value) {\n                if (rioWriteBulkString(r,(char*)entry.value,entry.sz) == 0) return 0;\n            } else {\n                if (rioWriteBulkLongLong(r,entry.longval) == 0) return 0;\n            }\n            if (++count == AOF_REWRITE_ITEMS_PER_CMD) count = 0;\n            items--;\n        }\n        quicklistReleaseIterator(li);\n    } else {\n        serverPanic(\"Unknown list encoding\");\n    }\n    return 1;\n}\n\n/* Emit the commands needed to rebuild a set object.\n * The function returns 0 on error, 1 on success. */\nint rewriteSetObject(rio *r, robj *key, robj *o) {\n    long long count = 0, items = setTypeSize(o);\n\n    if (o->encoding == OBJ_ENCODING_INTSET) {\n        int ii = 0;\n        int64_t llval;\n\n        while(intsetGet(o->ptr,ii++,&llval)) {\n            if (count == 0) {\n                int cmd_items = (items > AOF_REWRITE_ITEMS_PER_CMD) ?\n                    AOF_REWRITE_ITEMS_PER_CMD : items;\n\n                if (rioWriteBulkCount(r,'*',2+cmd_items) == 0) return 0;\n                if (rioWriteBulkString(r,\"SADD\",4) == 0) return 0;\n                if (rioWriteBulkObject(r,key) == 0) return 0;\n            }\n            if (rioWriteBulkLongLong(r,llval) == 0) return 0;\n            if (++count == AOF_REWRITE_ITEMS_PER_CMD) count = 0;\n            items--;\n        }\n    } else if (o->encoding == OBJ_ENCODING_HT) {\n        dictIterator *di = dictGetIterator(o->ptr);\n        dictEntry *de;\n\n        while((de = dictNext(di)) != NULL) {\n            robj *eleobj = dictGetKey(de);\n            if (count == 0) {\n                int cmd_items = (items > AOF_REWRITE_ITEMS_PER_CMD) ?\n                    AOF_REWRITE_ITEMS_PER_CMD : items;\n\n                if (rioWriteBulkCount(r,'*',2+cmd_items) == 0) return 0;\n                if (rioWriteBulkString(r,\"SADD\",4) == 0) return 0;\n                if (rioWriteBulkObject(r,key) == 0) return 0;\n            }\n            if (rioWriteBulkObject(r,eleobj) == 0) return 0;\n            if (++count == AOF_REWRITE_ITEMS_PER_CMD) count = 0;\n            items--;\n        }\n        dictReleaseIterator(di);\n    } else {\n        serverPanic(\"Unknown set encoding\");\n    }\n    return 1;\n}\n\n/* Emit the commands needed to rebuild a sorted set object.\n * The function returns 0 on error, 1 on success. */\nint rewriteSortedSetObject(rio *r, robj *key, robj *o) {\n    long long count = 0, items = zsetLength(o);\n\n    if (o->encoding == OBJ_ENCODING_ZIPLIST) {\n        unsigned char *zl = o->ptr;\n        unsigned char *eptr, *sptr;\n        unsigned char *vstr;\n        unsigned int vlen;\n        long long vll;\n        double score;\n\n        eptr = ziplistIndex(zl,0);\n        serverAssert(eptr != NULL);\n        sptr = ziplistNext(zl,eptr);\n        serverAssert(sptr != NULL);\n\n        while (eptr != NULL) {\n            serverAssert(ziplistGet(eptr,&vstr,&vlen,&vll));\n            score = zzlGetScore(sptr);\n\n            if (count == 0) {\n                int cmd_items = (items > AOF_REWRITE_ITEMS_PER_CMD) ?\n                    AOF_REWRITE_ITEMS_PER_CMD : items;\n\n                if (rioWriteBulkCount(r,'*',2+cmd_items*2) == 0) return 0;\n                if (rioWriteBulkString(r,\"ZADD\",4) == 0) return 0;\n                if (rioWriteBulkObject(r,key) == 0) return 0;\n            }\n            if (rioWriteBulkDouble(r,score) == 0) return 0;\n            if (vstr != NULL) {\n                if (rioWriteBulkString(r,(char*)vstr,vlen) == 0) return 0;\n            } else {\n                if (rioWriteBulkLongLong(r,vll) == 0) return 0;\n            }\n            zzlNext(zl,&eptr,&sptr);\n            if (++count == AOF_REWRITE_ITEMS_PER_CMD) count = 0;\n            items--;\n        }\n    } else if (o->encoding == OBJ_ENCODING_SKIPLIST) {\n        zset *zs = o->ptr;\n        dictIterator *di = dictGetIterator(zs->dict);\n        dictEntry *de;\n\n        while((de = dictNext(di)) != NULL) {\n            robj *eleobj = dictGetKey(de);\n            double *score = dictGetVal(de);\n\n            if (count == 0) {\n                int cmd_items = (items > AOF_REWRITE_ITEMS_PER_CMD) ?\n                    AOF_REWRITE_ITEMS_PER_CMD : items;\n\n                if (rioWriteBulkCount(r,'*',2+cmd_items*2) == 0) return 0;\n                if (rioWriteBulkString(r,\"ZADD\",4) == 0) return 0;\n                if (rioWriteBulkObject(r,key) == 0) return 0;\n            }\n            if (rioWriteBulkDouble(r,*score) == 0) return 0;\n            if (rioWriteBulkObject(r,eleobj) == 0) return 0;\n            if (++count == AOF_REWRITE_ITEMS_PER_CMD) count = 0;\n            items--;\n        }\n        dictReleaseIterator(di);\n    } else {\n        serverPanic(\"Unknown sorted zset encoding\");\n    }\n    return 1;\n}\n\n/* Write either the key or the value of the currently selected item of a hash.\n * The 'hi' argument passes a valid Redis hash iterator.\n * The 'what' filed specifies if to write a key or a value and can be\n * either OBJ_HASH_KEY or OBJ_HASH_VALUE.\n *\n * The function returns 0 on error, non-zero on success. */\nstatic int rioWriteHashIteratorCursor(rio *r, hashTypeIterator *hi, int what) {\n    if (hi->encoding == OBJ_ENCODING_ZIPLIST) {\n        unsigned char *vstr = NULL;\n        unsigned int vlen = UINT_MAX;\n        long long vll = LLONG_MAX;\n\n        hashTypeCurrentFromZiplist(hi, what, &vstr, &vlen, &vll);\n        if (vstr) {\n            return rioWriteBulkString(r, (char*)vstr, vlen);\n        } else {\n            return rioWriteBulkLongLong(r, vll);\n        }\n\n    } else if (hi->encoding == OBJ_ENCODING_HT) {\n        robj *value;\n\n        hashTypeCurrentFromHashTable(hi, what, &value);\n        return rioWriteBulkObject(r, value);\n    }\n\n    serverPanic(\"Unknown hash encoding\");\n    return 0;\n}\n\n/* Emit the commands needed to rebuild a hash object.\n * The function returns 0 on error, 1 on success. */\nint rewriteHashObject(rio *r, robj *key, robj *o) {\n    hashTypeIterator *hi;\n    long long count = 0, items = hashTypeLength(o);\n\n    hi = hashTypeInitIterator(o);\n    while (hashTypeNext(hi) != C_ERR) {\n        if (count == 0) {\n            int cmd_items = (items > AOF_REWRITE_ITEMS_PER_CMD) ?\n                AOF_REWRITE_ITEMS_PER_CMD : items;\n\n            if (rioWriteBulkCount(r,'*',2+cmd_items*2) == 0) return 0;\n            if (rioWriteBulkString(r,\"HMSET\",5) == 0) return 0;\n            if (rioWriteBulkObject(r,key) == 0) return 0;\n        }\n\n        if (rioWriteHashIteratorCursor(r, hi, OBJ_HASH_KEY) == 0) return 0;\n        if (rioWriteHashIteratorCursor(r, hi, OBJ_HASH_VALUE) == 0) return 0;\n        if (++count == AOF_REWRITE_ITEMS_PER_CMD) count = 0;\n        items--;\n    }\n\n    hashTypeReleaseIterator(hi);\n\n    return 1;\n}\n\n/* This function is called by the child rewriting the AOF file to read\n * the difference accumulated from the parent into a buffer, that is\n * concatenated at the end of the rewrite. */\nssize_t aofReadDiffFromParent(void) {\n    char buf[65536]; /* Default pipe buffer size on most Linux systems. */\n    ssize_t nread, total = 0;\n\n    while ((nread =\n            read(server.aof_pipe_read_data_from_parent,buf,sizeof(buf))) > 0) {\n        server.aof_child_diff = sdscatlen(server.aof_child_diff,buf,nread);\n        total += nread;\n    }\n    return total;\n}\n\n/* Write a sequence of commands able to fully rebuild the dataset into\n * \"filename\". Used both by REWRITEAOF and BGREWRITEAOF.\n *\n * In order to minimize the number of commands needed in the rewritten\n * log Redis uses variadic commands when possible, such as RPUSH, SADD\n * and ZADD. However at max AOF_REWRITE_ITEMS_PER_CMD items per time\n * are inserted using a single command. */\nint rewriteAppendOnlyFile(char *filename) {\n    dictIterator *di = NULL;\n    dictEntry *de;\n    rio aof;\n    FILE *fp;\n    char tmpfile[256];\n    int j;\n    long long now = mstime();\n    char byte;\n    size_t processed = 0;\n\n    /* Note that we have to use a different temp name here compared to the\n     * one used by rewriteAppendOnlyFileBackground() function. */\n    snprintf(tmpfile,256,\"temp-rewriteaof-%d.aof\", (int) getpid());\n    fp = fopen(tmpfile,\"w\");\n    if (!fp) {\n        serverLog(LL_WARNING, \"Opening the temp file for AOF rewrite in rewriteAppendOnlyFile(): %s\", strerror(errno));\n        return C_ERR;\n    }\n\n    server.aof_child_diff = sdsempty();\n    rioInitWithFile(&aof,fp);\n    if (server.aof_rewrite_incremental_fsync)\n        rioSetAutoSync(&aof,AOF_AUTOSYNC_BYTES);\n    for (j = 0; j < server.dbnum; j++) {\n        char selectcmd[] = \"*2\\r\\n$6\\r\\nSELECT\\r\\n\";\n        redisDb *db = server.db+j;\n        dict *d = db->dict;\n        if (dictSize(d) == 0) continue;\n        di = dictGetSafeIterator(d);\n        if (!di) {\n            fclose(fp);\n            return C_ERR;\n        }\n\n        /* SELECT the new DB */\n        if (rioWrite(&aof,selectcmd,sizeof(selectcmd)-1) == 0) goto werr;\n        if (rioWriteBulkLongLong(&aof,j) == 0) goto werr;\n\n        /* Iterate this DB writing every entry */\n        while((de = dictNext(di)) != NULL) {\n            sds keystr;\n            robj key, *o;\n            long long expiretime;\n\n            keystr = dictGetKey(de);\n            o = dictGetVal(de);\n            initStaticStringObject(key,keystr);\n\n            expiretime = getExpire(db,&key);\n\n            /* If this key is already expired skip it */\n            if (expiretime != -1 && expiretime < now) continue;\n\n            /* Save the key and associated value */\n            if (o->type == OBJ_STRING) {\n                /* Emit a SET command */\n                char cmd[]=\"*3\\r\\n$3\\r\\nSET\\r\\n\";\n                if (rioWrite(&aof,cmd,sizeof(cmd)-1) == 0) goto werr;\n                /* Key and value */\n                if (rioWriteBulkObject(&aof,&key) == 0) goto werr;\n                if (rioWriteBulkObject(&aof,o) == 0) goto werr;\n            } else if (o->type == OBJ_LIST) {\n                if (rewriteListObject(&aof,&key,o) == 0) goto werr;\n            } else if (o->type == OBJ_SET) {\n                if (rewriteSetObject(&aof,&key,o) == 0) goto werr;\n            } else if (o->type == OBJ_ZSET) {\n                if (rewriteSortedSetObject(&aof,&key,o) == 0) goto werr;\n            } else if (o->type == OBJ_HASH) {\n                if (rewriteHashObject(&aof,&key,o) == 0) goto werr;\n            } else {\n                serverPanic(\"Unknown object type\");\n            }\n            /* Save the expire time */\n            if (expiretime != -1) {\n                char cmd[]=\"*3\\r\\n$9\\r\\nPEXPIREAT\\r\\n\";\n                if (rioWrite(&aof,cmd,sizeof(cmd)-1) == 0) goto werr;\n                if (rioWriteBulkObject(&aof,&key) == 0) goto werr;\n                if (rioWriteBulkLongLong(&aof,expiretime) == 0) goto werr;\n            }\n            /* Read some diff from the parent process from time to time. */\n            if (aof.processed_bytes > processed+1024*10) {\n                processed = aof.processed_bytes;\n                aofReadDiffFromParent();\n            }\n        }\n        dictReleaseIterator(di);\n        di = NULL;\n    }\n\n    /* Do an initial slow fsync here while the parent is still sending\n     * data, in order to make the next final fsync faster. */\n    if (fflush(fp) == EOF) goto werr;\n    if (fsync(fileno(fp)) == -1) goto werr;\n\n    /* Read again a few times to get more data from the parent.\n     * We can't read forever (the server may receive data from clients\n     * faster than it is able to send data to the child), so we try to read\n     * some more data in a loop as soon as there is a good chance more data\n     * will come. If it looks like we are wasting time, we abort (this\n     * happens after 20 ms without new data). */\n    int nodata = 0;\n    mstime_t start = mstime();\n    while(mstime()-start < 1000 && nodata < 20) {\n        if (aeWait(server.aof_pipe_read_data_from_parent, AE_READABLE, 1) <= 0)\n        {\n            nodata++;\n            continue;\n        }\n        nodata = 0; /* Start counting from zero, we stop on N *contiguous*\n                       timeouts. */\n        aofReadDiffFromParent();\n    }\n\n    /* Ask the master to stop sending diffs. */\n    if (write(server.aof_pipe_write_ack_to_parent,\"!\",1) != 1) goto werr;\n    if (anetNonBlock(NULL,server.aof_pipe_read_ack_from_parent) != ANET_OK)\n        goto werr;\n    /* We read the ACK from the server using a 10 seconds timeout. Normally\n     * it should reply ASAP, but just in case we lose its reply, we are sure\n     * the child will eventually get terminated. */\n    if (syncRead(server.aof_pipe_read_ack_from_parent,&byte,1,5000) != 1 ||\n        byte != '!') goto werr;\n    serverLog(LL_NOTICE,\"Parent agreed to stop sending diffs. Finalizing AOF...\");\n\n    /* Read the final diff if any. */\n    aofReadDiffFromParent();\n\n    /* Write the received diff to the file. */\n    serverLog(LL_NOTICE,\n        \"Concatenating %.2f MB of AOF diff received from parent.\",\n        (double) sdslen(server.aof_child_diff) / (1024*1024));\n    if (rioWrite(&aof,server.aof_child_diff,sdslen(server.aof_child_diff)) == 0)\n        goto werr;\n\n    /* Make sure data will not remain on the OS's output buffers */\n    if (fflush(fp) == EOF) goto werr;\n    if (fsync(fileno(fp)) == -1) goto werr;\n    if (fclose(fp) == EOF) goto werr;\n\n    /* Use RENAME to make sure the DB file is changed atomically only\n     * if the generate DB file is ok. */\n    if (rename(tmpfile,filename) == -1) {\n        serverLog(LL_WARNING,\"Error moving temp append only file on the final destination: %s\", strerror(errno));\n        unlink(tmpfile);\n        return C_ERR;\n    }\n    serverLog(LL_NOTICE,\"SYNC append only file rewrite performed\");\n    return C_OK;\n\nwerr:\n    serverLog(LL_WARNING,\"Write error writing append only file on disk: %s\", strerror(errno));\n    fclose(fp);\n    unlink(tmpfile);\n    if (di) dictReleaseIterator(di);\n    return C_ERR;\n}\n\n/* ----------------------------------------------------------------------------\n * AOF rewrite pipes for IPC\n * -------------------------------------------------------------------------- */\n\n/* This event handler is called when the AOF rewriting child sends us a\n * single '!' char to signal we should stop sending buffer diffs. The\n * parent sends a '!' as well to acknowledge. */\nvoid aofChildPipeReadable(aeEventLoop *el, int fd, void *privdata, int mask) {\n    char byte;\n    UNUSED(el);\n    UNUSED(privdata);\n    UNUSED(mask);\n\n    if (read(fd,&byte,1) == 1 && byte == '!') {\n        serverLog(LL_NOTICE,\"AOF rewrite child asks to stop sending diffs.\");\n        server.aof_stop_sending_diff = 1;\n        if (write(server.aof_pipe_write_ack_to_child,\"!\",1) != 1) {\n            /* If we can't send the ack, inform the user, but don't try again\n             * since in the other side the children will use a timeout if the\n             * kernel can't buffer our write, or, the children was\n             * terminated. */\n            serverLog(LL_WARNING,\"Can't send ACK to AOF child: %s\",\n                strerror(errno));\n        }\n    }\n    /* Remove the handler since this can be called only one time during a\n     * rewrite. */\n    aeDeleteFileEvent(server.el,server.aof_pipe_read_ack_from_child,AE_READABLE);\n}\n\n/* Create the pipes used for parent - child process IPC during rewrite.\n * We have a data pipe used to send AOF incremental diffs to the child,\n * and two other pipes used by the children to signal it finished with\n * the rewrite so no more data should be written, and another for the\n * parent to acknowledge it understood this new condition. */\nint aofCreatePipes(void) {\n    int fds[6] = {-1, -1, -1, -1, -1, -1};\n    int j;\n\n    if (pipe(fds) == -1) goto error; /* parent -> children data. */\n    if (pipe(fds+2) == -1) goto error; /* children -> parent ack. */\n    if (pipe(fds+4) == -1) goto error; /* children -> parent ack. */\n    /* Parent -> children data is non blocking. */\n    if (anetNonBlock(NULL,fds[0]) != ANET_OK) goto error;\n    if (anetNonBlock(NULL,fds[1]) != ANET_OK) goto error;\n    if (aeCreateFileEvent(server.el, fds[2], AE_READABLE, aofChildPipeReadable, NULL) == AE_ERR) goto error;\n\n    server.aof_pipe_write_data_to_child = fds[1];\n    server.aof_pipe_read_data_from_parent = fds[0];\n    server.aof_pipe_write_ack_to_parent = fds[3];\n    server.aof_pipe_read_ack_from_child = fds[2];\n    server.aof_pipe_write_ack_to_child = fds[5];\n    server.aof_pipe_read_ack_from_parent = fds[4];\n    server.aof_stop_sending_diff = 0;\n    return C_OK;\n\nerror:\n    serverLog(LL_WARNING,\"Error opening /setting AOF rewrite IPC pipes: %s\",\n        strerror(errno));\n    for (j = 0; j < 6; j++) if(fds[j] != -1) close(fds[j]);\n    return C_ERR;\n}\n\nvoid aofClosePipes(void) {\n    aeDeleteFileEvent(server.el,server.aof_pipe_read_ack_from_child,AE_READABLE);\n    aeDeleteFileEvent(server.el,server.aof_pipe_write_data_to_child,AE_WRITABLE);\n    close(server.aof_pipe_write_data_to_child);\n    close(server.aof_pipe_read_data_from_parent);\n    close(server.aof_pipe_write_ack_to_parent);\n    close(server.aof_pipe_read_ack_from_child);\n    close(server.aof_pipe_write_ack_to_child);\n    close(server.aof_pipe_read_ack_from_parent);\n}\n\n/* ----------------------------------------------------------------------------\n * AOF background rewrite\n * ------------------------------------------------------------------------- */\n\n/* This is how rewriting of the append only file in background works:\n *\n * 1) The user calls BGREWRITEAOF\n * 2) Redis calls this function, that forks():\n *    2a) the child rewrite the append only file in a temp file.\n *    2b) the parent accumulates differences in server.aof_rewrite_buf.\n * 3) When the child finished '2a' exists.\n * 4) The parent will trap the exit code, if it's OK, will append the\n *    data accumulated into server.aof_rewrite_buf into the temp file, and\n *    finally will rename(2) the temp file in the actual file name.\n *    The the new file is reopened as the new append only file. Profit!\n */\nint rewriteAppendOnlyFileBackground(void) {\n    pid_t childpid;\n    long long start;\n\n    if (server.aof_child_pid != -1 || server.rdb_child_pid != -1) return C_ERR;\n    if (aofCreatePipes() != C_OK) return C_ERR;\n    start = ustime();\n    if ((childpid = fork()) == 0) {\n        char tmpfile[256];\n\n        /* Child */\n        closeListeningSockets(0);\n        redisSetProcTitle(\"redis-aof-rewrite\");\n        snprintf(tmpfile,256,\"temp-rewriteaof-bg-%d.aof\", (int) getpid());\n        if (rewriteAppendOnlyFile(tmpfile) == C_OK) {\n            size_t private_dirty = zmalloc_get_private_dirty();\n\n            if (private_dirty) {\n                serverLog(LL_NOTICE,\n                    \"AOF rewrite: %zu MB of memory used by copy-on-write\",\n                    private_dirty/(1024*1024));\n            }\n            exitFromChild(0);\n        } else {\n            exitFromChild(1);\n        }\n    } else {\n        /* Parent */\n        server.stat_fork_time = ustime()-start;\n        server.stat_fork_rate = (double) zmalloc_used_memory() * 1000000 / server.stat_fork_time / (1024*1024*1024); /* GB per second. */\n        latencyAddSampleIfNeeded(\"fork\",server.stat_fork_time/1000);\n        if (childpid == -1) {\n            serverLog(LL_WARNING,\n                \"Can't rewrite append only file in background: fork: %s\",\n                strerror(errno));\n            aofClosePipes();\n            return C_ERR;\n        }\n        serverLog(LL_NOTICE,\n            \"Background append only file rewriting started by pid %d\",childpid);\n        server.aof_rewrite_scheduled = 0;\n        server.aof_rewrite_time_start = time(NULL);\n        server.aof_child_pid = childpid;\n        updateDictResizePolicy();\n        /* We set appendseldb to -1 in order to force the next call to the\n         * feedAppendOnlyFile() to issue a SELECT command, so the differences\n         * accumulated by the parent into server.aof_rewrite_buf will start\n         * with a SELECT statement and it will be safe to merge. */\n        server.aof_selected_db = -1;\n        replicationScriptCacheFlush();\n        return C_OK;\n    }\n    return C_OK; /* unreached */\n}\n\nvoid bgrewriteaofCommand(client *c) {\n    if (server.aof_child_pid != -1) {\n        addReplyError(c,\"Background append only file rewriting already in progress\");\n    } else if (server.rdb_child_pid != -1) {\n        server.aof_rewrite_scheduled = 1;\n        addReplyStatus(c,\"Background append only file rewriting scheduled\");\n    } else if (rewriteAppendOnlyFileBackground() == C_OK) {\n        addReplyStatus(c,\"Background append only file rewriting started\");\n    } else {\n        addReply(c,shared.err);\n    }\n}\n\nvoid aofRemoveTempFile(pid_t childpid) {\n    char tmpfile[256];\n\n    snprintf(tmpfile,256,\"temp-rewriteaof-bg-%d.aof\", (int) childpid);\n    unlink(tmpfile);\n}\n\n/* Update the server.aof_current_size field explicitly using stat(2)\n * to check the size of the file. This is useful after a rewrite or after\n * a restart, normally the size is updated just adding the write length\n * to the current length, that is much faster. */\nvoid aofUpdateCurrentSize(void) {\n    struct redis_stat sb;\n    mstime_t latency;\n\n    latencyStartMonitor(latency);\n    if (redis_fstat(server.aof_fd,&sb) == -1) {\n        serverLog(LL_WARNING,\"Unable to obtain the AOF file length. stat: %s\",\n            strerror(errno));\n    } else {\n        server.aof_current_size = sb.st_size;\n    }\n    latencyEndMonitor(latency);\n    latencyAddSampleIfNeeded(\"aof-fstat\",latency);\n}\n\n/* A background append only file rewriting (BGREWRITEAOF) terminated its work.\n * Handle this. */\nvoid backgroundRewriteDoneHandler(int exitcode, int bysignal) {\n    if (!bysignal && exitcode == 0) {\n        int newfd, oldfd;\n        char tmpfile[256];\n        long long now = ustime();\n        mstime_t latency;\n\n        serverLog(LL_NOTICE,\n            \"Background AOF rewrite terminated with success\");\n\n        /* Flush the differences accumulated by the parent to the\n         * rewritten AOF. */\n        latencyStartMonitor(latency);\n        snprintf(tmpfile,256,\"temp-rewriteaof-bg-%d.aof\",\n            (int)server.aof_child_pid);\n        newfd = open(tmpfile,O_WRONLY|O_APPEND);\n        if (newfd == -1) {\n            serverLog(LL_WARNING,\n                \"Unable to open the temporary AOF produced by the child: %s\", strerror(errno));\n            goto cleanup;\n        }\n\n        if (aofRewriteBufferWrite(newfd) == -1) {\n            serverLog(LL_WARNING,\n                \"Error trying to flush the parent diff to the rewritten AOF: %s\", strerror(errno));\n            close(newfd);\n            goto cleanup;\n        }\n        latencyEndMonitor(latency);\n        latencyAddSampleIfNeeded(\"aof-rewrite-diff-write\",latency);\n\n        serverLog(LL_NOTICE,\n            \"Residual parent diff successfully flushed to the rewritten AOF (%.2f MB)\", (double) aofRewriteBufferSize() / (1024*1024));\n\n        /* The only remaining thing to do is to rename the temporary file to\n         * the configured file and switch the file descriptor used to do AOF\n         * writes. We don't want close(2) or rename(2) calls to block the\n         * server on old file deletion.\n         *\n         * There are two possible scenarios:\n         *\n         * 1) AOF is DISABLED and this was a one time rewrite. The temporary\n         * file will be renamed to the configured file. When this file already\n         * exists, it will be unlinked, which may block the server.\n         *\n         * 2) AOF is ENABLED and the rewritten AOF will immediately start\n         * receiving writes. After the temporary file is renamed to the\n         * configured file, the original AOF file descriptor will be closed.\n         * Since this will be the last reference to that file, closing it\n         * causes the underlying file to be unlinked, which may block the\n         * server.\n         *\n         * To mitigate the blocking effect of the unlink operation (either\n         * caused by rename(2) in scenario 1, or by close(2) in scenario 2), we\n         * use a background thread to take care of this. First, we\n         * make scenario 1 identical to scenario 2 by opening the target file\n         * when it exists. The unlink operation after the rename(2) will then\n         * be executed upon calling close(2) for its descriptor. Everything to\n         * guarantee atomicity for this switch has already happened by then, so\n         * we don't care what the outcome or duration of that close operation\n         * is, as long as the file descriptor is released again. */\n        if (server.aof_fd == -1) {\n            /* AOF disabled */\n\n             /* Don't care if this fails: oldfd will be -1 and we handle that.\n              * One notable case of -1 return is if the old file does\n              * not exist. */\n             oldfd = open(server.aof_filename,O_RDONLY|O_NONBLOCK);\n        } else {\n            /* AOF enabled */\n            oldfd = -1; /* We'll set this to the current AOF filedes later. */\n        }\n\n        /* Rename the temporary file. This will not unlink the target file if\n         * it exists, because we reference it with \"oldfd\". */\n        latencyStartMonitor(latency);\n        if (rename(tmpfile,server.aof_filename) == -1) {\n            serverLog(LL_WARNING,\n                \"Error trying to rename the temporary AOF file %s into %s: %s\",\n                tmpfile,\n                server.aof_filename,\n                strerror(errno));\n            close(newfd);\n            if (oldfd != -1) close(oldfd);\n            goto cleanup;\n        }\n        latencyEndMonitor(latency);\n        latencyAddSampleIfNeeded(\"aof-rename\",latency);\n\n        if (server.aof_fd == -1) {\n            /* AOF disabled, we don't need to set the AOF file descriptor\n             * to this new file, so we can close it. */\n            close(newfd);\n        } else {\n            /* AOF enabled, replace the old fd with the new one. */\n            oldfd = server.aof_fd;\n            server.aof_fd = newfd;\n            if (server.aof_fsync == AOF_FSYNC_ALWAYS)\n                aof_fsync(newfd);\n            else if (server.aof_fsync == AOF_FSYNC_EVERYSEC)\n                aof_background_fsync(newfd);\n            server.aof_selected_db = -1; /* Make sure SELECT is re-issued */\n            aofUpdateCurrentSize();\n            server.aof_rewrite_base_size = server.aof_current_size;\n\n            /* Clear regular AOF buffer since its contents was just written to\n             * the new AOF from the background rewrite buffer. */\n            sdsfree(server.aof_buf);\n            server.aof_buf = sdsempty();\n        }\n\n        server.aof_lastbgrewrite_status = C_OK;\n\n        serverLog(LL_NOTICE, \"Background AOF rewrite finished successfully\");\n        /* Change state from WAIT_REWRITE to ON if needed */\n        if (server.aof_state == AOF_WAIT_REWRITE)\n            server.aof_state = AOF_ON;\n\n        /* Asynchronously close the overwritten AOF. */\n        if (oldfd != -1) bioCreateBackgroundJob(BIO_CLOSE_FILE,(void*)(long)oldfd,NULL,NULL);\n\n        serverLog(LL_VERBOSE,\n            \"Background AOF rewrite signal handler took %lldus\", ustime()-now);\n    } else if (!bysignal && exitcode != 0) {\n        /* SIGUSR1 is whitelisted, so we have a way to kill a child without\n         * tirggering an error conditon. */\n        if (bysignal != SIGUSR1)\n            server.aof_lastbgrewrite_status = C_ERR;\n        serverLog(LL_WARNING,\n            \"Background AOF rewrite terminated with error\");\n    } else {\n        server.aof_lastbgrewrite_status = C_ERR;\n\n        serverLog(LL_WARNING,\n            \"Background AOF rewrite terminated by signal %d\", bysignal);\n    }\n\ncleanup:\n    aofClosePipes();\n    aofRewriteBufferReset();\n    aofRemoveTempFile(server.aof_child_pid);\n    server.aof_child_pid = -1;\n    server.aof_rewrite_time_last = time(NULL)-server.aof_rewrite_time_start;\n    server.aof_rewrite_time_start = -1;\n    /* Schedule a new rewrite if we are waiting for it to switch the AOF ON. */\n    if (server.aof_state == AOF_WAIT_REWRITE)\n        server.aof_rewrite_scheduled = 1;\n}\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.8/src/asciilogo.h",
    "content": "/*\n * Copyright (c) 2009-2012, Salvatore Sanfilippo <antirez at gmail dot com>\n * All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions are met:\n *\n *   * Redistributions of source code must retain the above copyright notice,\n *     this list of conditions and the following disclaimer.\n *   * Redistributions in binary form must reproduce the above copyright\n *     notice, this list of conditions and the following disclaimer in the\n *     documentation and/or other materials provided with the distribution.\n *   * Neither the name of Redis nor the names of its contributors may be used\n *     to endorse or promote products derived from this software without\n *     specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\"\n * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\n * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE\n * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR\n * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF\n * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS\n * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN\n * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)\n * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE\n * POSSIBILITY OF SUCH DAMAGE.\n */\n\nchar *ascii_logo =\n\"                _._                                                  \\n\"\n\"           _.-``__ ''-._                                             \\n\"\n\"      _.-``    `.  `_.  ''-._           Redis %s (%s/%d) %s bit\\n\"\n\"  .-`` .-```.  ```\\\\/    _.,_ ''-._                                   \\n\"\n\" (    '      ,       .-`  | `,    )     Running in %s mode\\n\"\n\" |`-._`-...-` __...-.``-._|'` _.-'|     Port: %d\\n\"\n\" |    `-._   `._    /     _.-'    |     PID: %ld\\n\"\n\"  `-._    `-._  `-./  _.-'    _.-'                                   \\n\"\n\" |`-._`-._    `-.__.-'    _.-'_.-'|                                  \\n\"\n\" |    `-._`-._        _.-'_.-'    |           http://redis.io        \\n\"\n\"  `-._    `-._`-.__.-'_.-'    _.-'                                   \\n\"\n\" |`-._`-._    `-.__.-'    _.-'_.-'|                                  \\n\"\n\" |    `-._`-._        _.-'_.-'    |                                  \\n\"\n\"  `-._    `-._`-.__.-'_.-'    _.-'                                   \\n\"\n\"      `-._    `-.__.-'    _.-'                                       \\n\"\n\"          `-._        _.-'                                           \\n\"\n\"              `-.__.-'                                               \\n\\n\";\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.8/src/bio.c",
    "content": "/* Background I/O service for Redis.\n *\n * This file implements operations that we need to perform in the background.\n * Currently there is only a single operation, that is a background close(2)\n * system call. This is needed as when the process is the last owner of a\n * reference to a file closing it means unlinking it, and the deletion of the\n * file is slow, blocking the server.\n *\n * In the future we'll either continue implementing new things we need or\n * we'll switch to libeio. However there are probably long term uses for this\n * file as we may want to put here Redis specific background tasks (for instance\n * it is not impossible that we'll need a non blocking FLUSHDB/FLUSHALL\n * implementation).\n *\n * DESIGN\n * ------\n *\n * The design is trivial, we have a structure representing a job to perform\n * and a different thread and job queue for every job type.\n * Every thread wait for new jobs in its queue, and process every job\n * sequentially.\n *\n * Jobs of the same type are guaranteed to be processed from the least\n * recently inserted to the most recently inserted (older jobs processed\n * first).\n *\n * Currently there is no way for the creator of the job to be notified about\n * the completion of the operation, this will only be added when/if needed.\n *\n * ----------------------------------------------------------------------------\n *\n * Copyright (c) 2009-2012, Salvatore Sanfilippo <antirez at gmail dot com>\n * All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions are met:\n *\n *   * Redistributions of source code must retain the above copyright notice,\n *     this list of conditions and the following disclaimer.\n *   * Redistributions in binary form must reproduce the above copyright\n *     notice, this list of conditions and the following disclaimer in the\n *     documentation and/or other materials provided with the distribution.\n *   * Neither the name of Redis nor the names of its contributors may be used\n *     to endorse or promote products derived from this software without\n *     specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\"\n * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\n * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE\n * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR\n * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF\n * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS\n * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN\n * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)\n * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE\n * POSSIBILITY OF SUCH DAMAGE.\n */\n\n\n#include \"server.h\"\n#include \"bio.h\"\n\nstatic pthread_t bio_threads[BIO_NUM_OPS];\nstatic pthread_mutex_t bio_mutex[BIO_NUM_OPS];\nstatic pthread_cond_t bio_condvar[BIO_NUM_OPS];\nstatic list *bio_jobs[BIO_NUM_OPS];\n/* The following array is used to hold the number of pending jobs for every\n * OP type. This allows us to export the bioPendingJobsOfType() API that is\n * useful when the main thread wants to perform some operation that may involve\n * objects shared with the background thread. The main thread will just wait\n * that there are no longer jobs of this type to be executed before performing\n * the sensible operation. This data is also useful for reporting. */\nstatic unsigned long long bio_pending[BIO_NUM_OPS];\n\n/* This structure represents a background Job. It is only used locally to this\n * file as the API does not expose the internals at all. */\nstruct bio_job {\n    time_t time; /* Time at which the job was created. */\n    /* Job specific arguments pointers. If we need to pass more than three\n     * arguments we can just pass a pointer to a structure or alike. */\n    void *arg1, *arg2, *arg3;\n};\n\nvoid *bioProcessBackgroundJobs(void *arg);\n\n/* Make sure we have enough stack to perform all the things we do in the\n * main thread. */\n#define REDIS_THREAD_STACK_SIZE (1024*1024*4)\n\n/* Initialize the background system, spawning the thread. */\nvoid bioInit(void) {\n    pthread_attr_t attr;\n    pthread_t thread;\n    size_t stacksize;\n    int j;\n\n    /* Initialization of state vars and objects */\n    for (j = 0; j < BIO_NUM_OPS; j++) {\n        pthread_mutex_init(&bio_mutex[j],NULL);\n        pthread_cond_init(&bio_condvar[j],NULL);\n        bio_jobs[j] = listCreate();\n        bio_pending[j] = 0;\n    }\n\n    /* Set the stack size as by default it may be small in some system */\n    pthread_attr_init(&attr);\n    pthread_attr_getstacksize(&attr,&stacksize);\n    if (!stacksize) stacksize = 1; /* The world is full of Solaris Fixes */\n    while (stacksize < REDIS_THREAD_STACK_SIZE) stacksize *= 2;\n    pthread_attr_setstacksize(&attr, stacksize);\n\n    /* Ready to spawn our threads. We use the single argument the thread\n     * function accepts in order to pass the job ID the thread is\n     * responsible of. */\n    for (j = 0; j < BIO_NUM_OPS; j++) {\n        void *arg = (void*)(unsigned long) j;\n        if (pthread_create(&thread,&attr,bioProcessBackgroundJobs,arg) != 0) {\n            serverLog(LL_WARNING,\"Fatal: Can't initialize Background Jobs.\");\n            exit(1);\n        }\n        bio_threads[j] = thread;\n    }\n}\n\nvoid bioCreateBackgroundJob(int type, void *arg1, void *arg2, void *arg3) {\n    struct bio_job *job = zmalloc(sizeof(*job));\n\n    job->time = time(NULL);\n    job->arg1 = arg1;\n    job->arg2 = arg2;\n    job->arg3 = arg3;\n    pthread_mutex_lock(&bio_mutex[type]);\n    listAddNodeTail(bio_jobs[type],job);\n    bio_pending[type]++;\n    pthread_cond_signal(&bio_condvar[type]);\n    pthread_mutex_unlock(&bio_mutex[type]);\n}\n\nvoid *bioProcessBackgroundJobs(void *arg) {\n    struct bio_job *job;\n    unsigned long type = (unsigned long) arg;\n    sigset_t sigset;\n\n    /* Check that the type is within the right interval. */\n    if (type >= BIO_NUM_OPS) {\n        serverLog(LL_WARNING,\n            \"Warning: bio thread started with wrong type %lu\",type);\n        return NULL;\n    }\n\n    /* Make the thread killable at any time, so that bioKillThreads()\n     * can work reliably. */\n    pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);\n    pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL);\n\n    pthread_mutex_lock(&bio_mutex[type]);\n    /* Block SIGALRM so we are sure that only the main thread will\n     * receive the watchdog signal. */\n    sigemptyset(&sigset);\n    sigaddset(&sigset, SIGALRM);\n    if (pthread_sigmask(SIG_BLOCK, &sigset, NULL))\n        serverLog(LL_WARNING,\n            \"Warning: can't mask SIGALRM in bio.c thread: %s\", strerror(errno));\n\n    while(1) {\n        listNode *ln;\n\n        /* The loop always starts with the lock hold. */\n        if (listLength(bio_jobs[type]) == 0) {\n            pthread_cond_wait(&bio_condvar[type],&bio_mutex[type]);\n            continue;\n        }\n        /* Pop the job from the queue. */\n        ln = listFirst(bio_jobs[type]);\n        job = ln->value;\n        /* It is now possible to unlock the background system as we know have\n         * a stand alone job structure to process.*/\n        pthread_mutex_unlock(&bio_mutex[type]);\n\n        /* Process the job accordingly to its type. */\n        if (type == BIO_CLOSE_FILE) {\n            close((long)job->arg1);\n        } else if (type == BIO_AOF_FSYNC) {\n            aof_fsync((long)job->arg1);\n        } else {\n            serverPanic(\"Wrong job type in bioProcessBackgroundJobs().\");\n        }\n        zfree(job);\n\n        /* Lock again before reiterating the loop, if there are no longer\n         * jobs to process we'll block again in pthread_cond_wait(). */\n        pthread_mutex_lock(&bio_mutex[type]);\n        listDelNode(bio_jobs[type],ln);\n        bio_pending[type]--;\n    }\n}\n\n/* Return the number of pending jobs of the specified type. */\nunsigned long long bioPendingJobsOfType(int type) {\n    unsigned long long val;\n    pthread_mutex_lock(&bio_mutex[type]);\n    val = bio_pending[type];\n    pthread_mutex_unlock(&bio_mutex[type]);\n    return val;\n}\n\n/* Kill the running bio threads in an unclean way. This function should be\n * used only when it's critical to stop the threads for some reason.\n * Currently Redis does this only on crash (for instance on SIGSEGV) in order\n * to perform a fast memory check without other threads messing with memory. */\nvoid bioKillThreads(void) {\n    int err, j;\n\n    for (j = 0; j < BIO_NUM_OPS; j++) {\n        if (pthread_cancel(bio_threads[j]) == 0) {\n            if ((err = pthread_join(bio_threads[j],NULL)) != 0) {\n                serverLog(LL_WARNING,\n                    \"Bio thread for job type #%d can be joined: %s\",\n                        j, strerror(err));\n            } else {\n                serverLog(LL_WARNING,\n                    \"Bio thread for job type #%d terminated\",j);\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.8/src/bio.h",
    "content": "/*\n * Copyright (c) 2009-2012, Salvatore Sanfilippo <antirez at gmail dot com>\n * All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions are met:\n *\n *   * Redistributions of source code must retain the above copyright notice,\n *     this list of conditions and the following disclaimer.\n *   * Redistributions in binary form must reproduce the above copyright\n *     notice, this list of conditions and the following disclaimer in the\n *     documentation and/or other materials provided with the distribution.\n *   * Neither the name of Redis nor the names of its contributors may be used\n *     to endorse or promote products derived from this software without\n *     specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\"\n * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\n * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE\n * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR\n * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF\n * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS\n * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN\n * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)\n * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE\n * POSSIBILITY OF SUCH DAMAGE.\n */\n\n/* Exported API */\nvoid bioInit(void);\nvoid bioCreateBackgroundJob(int type, void *arg1, void *arg2, void *arg3);\nunsigned long long bioPendingJobsOfType(int type);\nvoid bioWaitPendingJobsLE(int type, unsigned long long num);\ntime_t bioOlderJobOfType(int type);\nvoid bioKillThreads(void);\n\n/* Background job opcodes */\n#define BIO_CLOSE_FILE    0 /* Deferred close(2) syscall. */\n#define BIO_AOF_FSYNC     1 /* Deferred AOF fsync. */\n#define BIO_NUM_OPS       2\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.8/src/bitops.c",
    "content": "/* Bit operations.\n *\n * Copyright (c) 2009-2012, Salvatore Sanfilippo <antirez at gmail dot com>\n * All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions are met:\n *\n *   * Redistributions of source code must retain the above copyright notice,\n *     this list of conditions and the following disclaimer.\n *   * Redistributions in binary form must reproduce the above copyright\n *     notice, this list of conditions and the following disclaimer in the\n *     documentation and/or other materials provided with the distribution.\n *   * Neither the name of Redis nor the names of its contributors may be used\n *     to endorse or promote products derived from this software without\n *     specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\"\n * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\n * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE\n * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR\n * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF\n * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS\n * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN\n * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)\n * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE\n * POSSIBILITY OF SUCH DAMAGE.\n */\n\n#include \"server.h\"\n\n/* -----------------------------------------------------------------------------\n * Helpers and low level bit functions.\n * -------------------------------------------------------------------------- */\n\n/* Count number of bits set in the binary array pointed by 's' and long\n * 'count' bytes. The implementation of this function is required to\n * work with a input string length up to 512 MB. */\nsize_t redisPopcount(void *s, long count) {\n    size_t bits = 0;\n    unsigned char *p = s;\n    uint32_t *p4;\n    static const unsigned char bitsinbyte[256] = {0,1,1,2,1,2,2,3,1,2,2,3,2,3,3,4,1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5,1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5,2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5,2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5,2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8};\n\n    /* Count initial bytes not aligned to 32 bit. */\n    while((unsigned long)p & 3 && count) {\n        bits += bitsinbyte[*p++];\n        count--;\n    }\n\n    /* Count bits 28 bytes at a time */\n    p4 = (uint32_t*)p;\n    while(count>=28) {\n        uint32_t aux1, aux2, aux3, aux4, aux5, aux6, aux7;\n\n        aux1 = *p4++;\n        aux2 = *p4++;\n        aux3 = *p4++;\n        aux4 = *p4++;\n        aux5 = *p4++;\n        aux6 = *p4++;\n        aux7 = *p4++;\n        count -= 28;\n\n        aux1 = aux1 - ((aux1 >> 1) & 0x55555555);\n        aux1 = (aux1 & 0x33333333) + ((aux1 >> 2) & 0x33333333);\n        aux2 = aux2 - ((aux2 >> 1) & 0x55555555);\n        aux2 = (aux2 & 0x33333333) + ((aux2 >> 2) & 0x33333333);\n        aux3 = aux3 - ((aux3 >> 1) & 0x55555555);\n        aux3 = (aux3 & 0x33333333) + ((aux3 >> 2) & 0x33333333);\n        aux4 = aux4 - ((aux4 >> 1) & 0x55555555);\n        aux4 = (aux4 & 0x33333333) + ((aux4 >> 2) & 0x33333333);\n        aux5 = aux5 - ((aux5 >> 1) & 0x55555555);\n        aux5 = (aux5 & 0x33333333) + ((aux5 >> 2) & 0x33333333);\n        aux6 = aux6 - ((aux6 >> 1) & 0x55555555);\n        aux6 = (aux6 & 0x33333333) + ((aux6 >> 2) & 0x33333333);\n        aux7 = aux7 - ((aux7 >> 1) & 0x55555555);\n        aux7 = (aux7 & 0x33333333) + ((aux7 >> 2) & 0x33333333);\n        bits += ((((aux1 + (aux1 >> 4)) & 0x0F0F0F0F) +\n                    ((aux2 + (aux2 >> 4)) & 0x0F0F0F0F) +\n                    ((aux3 + (aux3 >> 4)) & 0x0F0F0F0F) +\n                    ((aux4 + (aux4 >> 4)) & 0x0F0F0F0F) +\n                    ((aux5 + (aux5 >> 4)) & 0x0F0F0F0F) +\n                    ((aux6 + (aux6 >> 4)) & 0x0F0F0F0F) +\n                    ((aux7 + (aux7 >> 4)) & 0x0F0F0F0F))* 0x01010101) >> 24;\n    }\n    /* Count the remaining bytes. */\n    p = (unsigned char*)p4;\n    while(count--) bits += bitsinbyte[*p++];\n    return bits;\n}\n\n/* Return the position of the first bit set to one (if 'bit' is 1) or\n * zero (if 'bit' is 0) in the bitmap starting at 's' and long 'count' bytes.\n *\n * The function is guaranteed to return a value >= 0 if 'bit' is 0 since if\n * no zero bit is found, it returns count*8 assuming the string is zero\n * padded on the right. However if 'bit' is 1 it is possible that there is\n * not a single set bit in the bitmap. In this special case -1 is returned. */\nlong redisBitpos(void *s, unsigned long count, int bit) {\n    unsigned long *l;\n    unsigned char *c;\n    unsigned long skipval, word = 0, one;\n    long pos = 0; /* Position of bit, to return to the caller. */\n    unsigned long j;\n\n    /* Process whole words first, seeking for first word that is not\n     * all ones or all zeros respectively if we are lookig for zeros\n     * or ones. This is much faster with large strings having contiguous\n     * blocks of 1 or 0 bits compared to the vanilla bit per bit processing.\n     *\n     * Note that if we start from an address that is not aligned\n     * to sizeof(unsigned long) we consume it byte by byte until it is\n     * aligned. */\n\n    /* Skip initial bits not aligned to sizeof(unsigned long) byte by byte. */\n    skipval = bit ? 0 : UCHAR_MAX;\n    c = (unsigned char*) s;\n    while((unsigned long)c & (sizeof(*l)-1) && count) {\n        if (*c != skipval) break;\n        c++;\n        count--;\n        pos += 8;\n    }\n\n    /* Skip bits with full word step. */\n    skipval = bit ? 0 : ULONG_MAX;\n    l = (unsigned long*) c;\n    while (count >= sizeof(*l)) {\n        if (*l != skipval) break;\n        l++;\n        count -= sizeof(*l);\n        pos += sizeof(*l)*8;\n    }\n\n    /* Load bytes into \"word\" considering the first byte as the most significant\n     * (we basically consider it as written in big endian, since we consider the\n     * string as a set of bits from left to right, with the first bit at position\n     * zero.\n     *\n     * Note that the loading is designed to work even when the bytes left\n     * (count) are less than a full word. We pad it with zero on the right. */\n    c = (unsigned char*)l;\n    for (j = 0; j < sizeof(*l); j++) {\n        word <<= 8;\n        if (count) {\n            word |= *c;\n            c++;\n            count--;\n        }\n    }\n\n    /* Special case:\n     * If bits in the string are all zero and we are looking for one,\n     * return -1 to signal that there is not a single \"1\" in the whole\n     * string. This can't happen when we are looking for \"0\" as we assume\n     * that the right of the string is zero padded. */\n    if (bit == 1 && word == 0) return -1;\n\n    /* Last word left, scan bit by bit. The first thing we need is to\n     * have a single \"1\" set in the most significant position in an\n     * unsigned long. We don't know the size of the long so we use a\n     * simple trick. */\n    one = ULONG_MAX; /* All bits set to 1.*/\n    one >>= 1;       /* All bits set to 1 but the MSB. */\n    one = ~one;      /* All bits set to 0 but the MSB. */\n\n    while(one) {\n        if (((one & word) != 0) == bit) return pos;\n        pos++;\n        one >>= 1;\n    }\n\n    /* If we reached this point, there is a bug in the algorithm, since\n     * the case of no match is handled as a special case before. */\n    serverPanic(\"End of redisBitpos() reached.\");\n    return 0; /* Just to avoid warnings. */\n}\n\n/* The following set.*Bitfield and get.*Bitfield functions implement setting\n * and getting arbitrary size (up to 64 bits) signed and unsigned integers\n * at arbitrary positions into a bitmap.\n *\n * The representation considers the bitmap as having the bit number 0 to be\n * the most significant bit of the first byte, and so forth, so for example\n * setting a 5 bits unsigned integer to value 23 at offset 7 into a bitmap\n * previously set to all zeroes, will produce the following representation:\n *\n * +--------+--------+\n * |00000001|01110000|\n * +--------+--------+\n *\n * When offsets and integer sizes are aligned to bytes boundaries, this is the\n * same as big endian, however when such alignment does not exist, its important\n * to also understand how the bits inside a byte are ordered.\n *\n * Note that this format follows the same convention as SETBIT and related\n * commands.\n */\n\nvoid setUnsignedBitfield(unsigned char *p, uint64_t offset, uint64_t bits, uint64_t value) {\n    uint64_t byte, bit, byteval, bitval, j;\n\n    for (j = 0; j < bits; j++) {\n        bitval = (value & ((uint64_t)1<<(bits-1-j))) != 0;\n        byte = offset >> 3;\n        bit = 7 - (offset & 0x7);\n        byteval = p[byte];\n        byteval &= ~(1 << bit);\n        byteval |= bitval << bit;\n        p[byte] = byteval & 0xff;\n        offset++;\n    }\n}\n\nvoid setSignedBitfield(unsigned char *p, uint64_t offset, uint64_t bits, int64_t value) {\n    uint64_t uv = value; /* Casting will add UINT64_MAX + 1 if v is negative. */\n    setUnsignedBitfield(p,offset,bits,uv);\n}\n\nuint64_t getUnsignedBitfield(unsigned char *p, uint64_t offset, uint64_t bits) {\n    uint64_t byte, bit, byteval, bitval, j, value = 0;\n\n    for (j = 0; j < bits; j++) {\n        byte = offset >> 3;\n        bit = 7 - (offset & 0x7);\n        byteval = p[byte];\n        bitval = (byteval >> bit) & 1;\n        value = (value<<1) | bitval;\n        offset++;\n    }\n    return value;\n}\n\nint64_t getSignedBitfield(unsigned char *p, uint64_t offset, uint64_t bits) {\n    int64_t value;\n    union {uint64_t u; int64_t i;} conv;\n\n    /* Converting from unsigned to signed is undefined when the value does\n     * not fit, however here we assume two's complement and the original value\n     * was obtained from signed -> unsigned conversion, so we'll find the\n     * most significant bit set if the original value was negative.\n     *\n     * Note that two's complement is mandatory for exact-width types\n     * according to the C99 standard. */\n    conv.u = getUnsignedBitfield(p,offset,bits);\n    value = conv.i;\n\n    /* If the top significant bit is 1, propagate it to all the\n     * higher bits for two's complement representation of signed\n     * integers. */\n    if (value & ((uint64_t)1 << (bits-1)))\n        value |= ((uint64_t)-1) << bits;\n    return value;\n}\n\n/* The following two functions detect overflow of a value in the context\n * of storing it as an unsigned or signed integer with the specified\n * number of bits. The functions both take the value and a possible increment.\n * If no overflow could happen and the value+increment fit inside the limits,\n * then zero is returned, otherwise in case of overflow, 1 is returned,\n * otherwise in case of underflow, -1 is returned.\n *\n * When non-zero is returned (oferflow or underflow), if not NULL, *limit is\n * set to the value the operation should result when an overflow happens,\n * depending on the specified overflow semantics:\n *\n * For BFOVERFLOW_SAT if 1 is returned, *limit it is set maximum value that\n * you can store in that integer. when -1 is returned, *limit is set to the\n * minimum value that an integer of that size can represent.\n *\n * For BFOVERFLOW_WRAP *limit is set by performing the operation in order to\n * \"wrap\" around towards zero for unsigned integers, or towards the most\n * negative number that is possible to represent for signed integers. */\n\n#define BFOVERFLOW_WRAP 0\n#define BFOVERFLOW_SAT 1\n#define BFOVERFLOW_FAIL 2 /* Used by the BITFIELD command implementation. */\n\nint checkUnsignedBitfieldOverflow(uint64_t value, int64_t incr, uint64_t bits, int owtype, uint64_t *limit) {\n    uint64_t max = (bits == 64) ? UINT64_MAX : (((uint64_t)1<<bits)-1);\n    int64_t maxincr = max-value;\n    int64_t minincr = -value;\n\n    if (value > max || (incr > 0 && incr > maxincr)) {\n        if (limit) {\n            if (owtype == BFOVERFLOW_WRAP) {\n                goto handle_wrap;\n            } else if (owtype == BFOVERFLOW_SAT) {\n                *limit = max;\n            }\n        }\n        return 1;\n    } else if (incr < 0 && incr < minincr) {\n        if (limit) {\n            if (owtype == BFOVERFLOW_WRAP) {\n                goto handle_wrap;\n            } else if (owtype == BFOVERFLOW_SAT) {\n                *limit = 0;\n            }\n        }\n        return -1;\n    }\n    return 0;\n\nhandle_wrap:\n    {\n        uint64_t mask = ((uint64_t)-1) << bits;\n        uint64_t res = value+incr;\n\n        res &= ~mask;\n        *limit = res;\n    }\n    return 1;\n}\n\nint checkSignedBitfieldOverflow(int64_t value, int64_t incr, uint64_t bits, int owtype, int64_t *limit) {\n    int64_t max = (bits == 64) ? INT64_MAX : (((int64_t)1<<(bits-1))-1);\n    int64_t min = (-max)-1;\n\n    /* Note that maxincr and minincr could overflow, but we use the values\n     * only after checking 'value' range, so when we use it no overflow\n     * happens. */\n    int64_t maxincr = max-value;\n    int64_t minincr = min-value;\n\n    if (value > max || (bits != 64 && incr > maxincr) || (value >= 0 && incr > 0 && incr > maxincr))\n    {\n        if (limit) {\n            if (owtype == BFOVERFLOW_WRAP) {\n                goto handle_wrap;\n            } else if (owtype == BFOVERFLOW_SAT) {\n                *limit = max;\n            }\n        }\n        return 1;\n    } else if (value < min || (bits != 64 && incr < minincr) || (value < 0 && incr < 0 && incr < minincr)) {\n        if (limit) {\n            if (owtype == BFOVERFLOW_WRAP) {\n                goto handle_wrap;\n            } else if (owtype == BFOVERFLOW_SAT) {\n                *limit = min;\n            }\n        }\n        return -1;\n    }\n    return 0;\n\nhandle_wrap:\n    {\n        uint64_t mask = ((uint64_t)-1) << bits;\n        uint64_t msb = (uint64_t)1 << (bits-1);\n        uint64_t a = value, b = incr, c;\n        c = a+b; /* Perform addition as unsigned so that's defined. */\n\n        /* If the sign bit is set, propagate to all the higher order\n         * bits, to cap the negative value. If it's clear, mask to\n         * the positive integer limit. */\n        if (c & msb) {\n            c |= mask;\n        } else {\n            c &= ~mask;\n        }\n        *limit = c;\n    }\n    return 1;\n}\n\n/* Debugging function. Just show bits in the specified bitmap. Not used\n * but here for not having to rewrite it when debugging is needed. */\nvoid printBits(unsigned char *p, unsigned long count) {\n    unsigned long j, i, byte;\n\n    for (j = 0; j < count; j++) {\n        byte = p[j];\n        for (i = 0x80; i > 0; i /= 2)\n            printf(\"%c\", (byte & i) ? '1' : '0');\n        printf(\"|\");\n    }\n    printf(\"\\n\");\n}\n\n/* -----------------------------------------------------------------------------\n * Bits related string commands: GETBIT, SETBIT, BITCOUNT, BITOP.\n * -------------------------------------------------------------------------- */\n\n#define BITOP_AND   0\n#define BITOP_OR    1\n#define BITOP_XOR   2\n#define BITOP_NOT   3\n\n#define BITFIELDOP_GET 0\n#define BITFIELDOP_SET 1\n#define BITFIELDOP_INCRBY 2\n\n/* This helper function used by GETBIT / SETBIT parses the bit offset argument\n * making sure an error is returned if it is negative or if it overflows\n * Redis 512 MB limit for the string value.\n *\n * If the 'hash' argument is true, and 'bits is positive, then the command\n * will also parse bit offsets prefixed by \"#\". In such a case the offset\n * is multiplied by 'bits'. This is useful for the BITFIELD command. */\nint getBitOffsetFromArgument(client *c, robj *o, size_t *offset, int hash, int bits) {\n    long long loffset;\n    char *err = \"bit offset is not an integer or out of range\";\n    char *p = o->ptr;\n    size_t plen = sdslen(p);\n    int usehash = 0;\n\n    /* Handle #<offset> form. */\n    if (p[0] == '#' && hash && bits > 0) usehash = 1;\n\n    if (string2ll(p+usehash,plen-usehash,&loffset) == 0) {\n        addReplyError(c,err);\n        return C_ERR;\n    }\n\n    /* Adjust the offset by 'bits' for #<offset> form. */\n    if (usehash) loffset *= bits;\n\n    /* Limit offset to 512MB in bytes */\n    if ((loffset < 0) || ((unsigned long long)loffset >> 3) >= (512*1024*1024))\n    {\n        addReplyError(c,err);\n        return C_ERR;\n    }\n\n    *offset = (size_t)loffset;\n    return C_OK;\n}\n\n/* This helper function for BITFIELD parses a bitfield type in the form\n * <sign><bits> where sign is 'u' or 'i' for unsigned and signed, and\n * the bits is a value between 1 and 64. However 64 bits unsigned integers\n * are reported as an error because of current limitations of Redis protocol\n * to return unsigned integer values greater than INT64_MAX.\n *\n * On error C_ERR is returned and an error is sent to the client. */\nint getBitfieldTypeFromArgument(client *c, robj *o, int *sign, int *bits) {\n    char *p = o->ptr;\n    char *err = \"Invalid bitfield type. Use something like i16 u8. Note that u64 is not supported but i64 is.\";\n    long long llbits;\n\n    if (p[0] == 'i') {\n        *sign = 1;\n    } else if (p[0] == 'u') {\n        *sign = 0;\n    } else {\n        addReplyError(c,err);\n        return C_ERR;\n    }\n\n    if ((string2ll(p+1,strlen(p+1),&llbits)) == 0 ||\n        llbits < 1 ||\n        (*sign == 1 && llbits > 64) ||\n        (*sign == 0 && llbits > 63))\n    {\n        addReplyError(c,err);\n        return C_ERR;\n    }\n    *bits = llbits;\n    return C_OK;\n}\n\n/* This is an helper function for commands implementations that need to write\n * bits to a string object. The command creates or pad with zeroes the string\n * so that the 'maxbit' bit can be addressed. The object is finally\n * returned. Otherwise if the key holds a wrong type NULL is returned and\n * an error is sent to the client. */\nrobj *lookupStringForBitCommand(client *c, size_t maxbit) {\n    size_t byte = maxbit >> 3;\n    robj *o = lookupKeyWrite(c->db,c->argv[1]);\n\n    if (o == NULL) {\n        o = createObject(OBJ_STRING,sdsnewlen(NULL, byte+1));\n        dbAdd(c->db,c->argv[1],o);\n    } else {\n        if (checkType(c,o,OBJ_STRING)) return NULL;\n        o = dbUnshareStringValue(c->db,c->argv[1],o);\n        o->ptr = sdsgrowzero(o->ptr,byte+1);\n    }\n    return o;\n}\n\n/* Return a pointer to the string object content, and stores its length\n * in 'len'. The user is required to pass (likely stack allocated) buffer\n * 'llbuf' of at least LONG_STR_SIZE bytes. Such a buffer is used in the case\n * the object is integer encoded in order to provide the representation\n * without usign heap allocation.\n *\n * The function returns the pointer to the object array of bytes representing\n * the string it contains, that may be a pointer to 'llbuf' or to the\n * internal object representation. As a side effect 'len' is filled with\n * the length of such buffer.\n *\n * If the source object is NULL the function is guaranteed to return NULL\n * and set 'len' to 0. */\nunsigned char *getObjectReadOnlyString(robj *o, long *len, char *llbuf) {\n    serverAssert(o->type == OBJ_STRING);\n    unsigned char *p = NULL;\n\n    /* Set the 'p' pointer to the string, that can be just a stack allocated\n     * array if our string was integer encoded. */\n    if (o && o->encoding == OBJ_ENCODING_INT) {\n        p = (unsigned char*) llbuf;\n        if (len) *len = ll2string(llbuf,LONG_STR_SIZE,(long)o->ptr);\n    } else if (o) {\n        p = (unsigned char*) o->ptr;\n        if (len) *len = sdslen(o->ptr);\n    } else {\n        if (len) *len = 0;\n    }\n    return p;\n}\n\n/* SETBIT key offset bitvalue */\nvoid setbitCommand(client *c) {\n    robj *o;\n    char *err = \"bit is not an integer or out of range\";\n    size_t bitoffset;\n    ssize_t byte, bit;\n    int byteval, bitval;\n    long on;\n\n    if (getBitOffsetFromArgument(c,c->argv[2],&bitoffset,0,0) != C_OK)\n        return;\n\n    if (getLongFromObjectOrReply(c,c->argv[3],&on,err) != C_OK)\n        return;\n\n    /* Bits can only be set or cleared... */\n    if (on & ~1) {\n        addReplyError(c,err);\n        return;\n    }\n\n    if ((o = lookupStringForBitCommand(c,bitoffset)) == NULL) return;\n\n    /* Get current values */\n    byte = bitoffset >> 3;\n    byteval = ((uint8_t*)o->ptr)[byte];\n    bit = 7 - (bitoffset & 0x7);\n    bitval = byteval & (1 << bit);\n\n    /* Update byte with new bit value and return original value */\n    byteval &= ~(1 << bit);\n    byteval |= ((on & 0x1) << bit);\n    ((uint8_t*)o->ptr)[byte] = byteval;\n    signalModifiedKey(c->db,c->argv[1]);\n    notifyKeyspaceEvent(NOTIFY_STRING,\"setbit\",c->argv[1],c->db->id);\n    server.dirty++;\n    addReply(c, bitval ? shared.cone : shared.czero);\n}\n\n/* GETBIT key offset */\nvoid getbitCommand(client *c) {\n    robj *o;\n    char llbuf[32];\n    size_t bitoffset;\n    size_t byte, bit;\n    size_t bitval = 0;\n\n    if (getBitOffsetFromArgument(c,c->argv[2],&bitoffset,0,0) != C_OK)\n        return;\n\n    if ((o = lookupKeyReadOrReply(c,c->argv[1],shared.czero)) == NULL ||\n        checkType(c,o,OBJ_STRING)) return;\n\n    byte = bitoffset >> 3;\n    bit = 7 - (bitoffset & 0x7);\n    if (sdsEncodedObject(o)) {\n        if (byte < sdslen(o->ptr))\n            bitval = ((uint8_t*)o->ptr)[byte] & (1 << bit);\n    } else {\n        if (byte < (size_t)ll2string(llbuf,sizeof(llbuf),(long)o->ptr))\n            bitval = llbuf[byte] & (1 << bit);\n    }\n\n    addReply(c, bitval ? shared.cone : shared.czero);\n}\n\n/* BITOP op_name target_key src_key1 src_key2 src_key3 ... src_keyN */\nvoid bitopCommand(client *c) {\n    char *opname = c->argv[1]->ptr;\n    robj *o, *targetkey = c->argv[2];\n    unsigned long op, j, numkeys;\n    robj **objects;      /* Array of source objects. */\n    unsigned char **src; /* Array of source strings pointers. */\n    unsigned long *len, maxlen = 0; /* Array of length of src strings,\n                                       and max len. */\n    unsigned long minlen = 0;    /* Min len among the input keys. */\n    unsigned char *res = NULL; /* Resulting string. */\n\n    /* Parse the operation name. */\n    if ((opname[0] == 'a' || opname[0] == 'A') && !strcasecmp(opname,\"and\"))\n        op = BITOP_AND;\n    else if((opname[0] == 'o' || opname[0] == 'O') && !strcasecmp(opname,\"or\"))\n        op = BITOP_OR;\n    else if((opname[0] == 'x' || opname[0] == 'X') && !strcasecmp(opname,\"xor\"))\n        op = BITOP_XOR;\n    else if((opname[0] == 'n' || opname[0] == 'N') && !strcasecmp(opname,\"not\"))\n        op = BITOP_NOT;\n    else {\n        addReply(c,shared.syntaxerr);\n        return;\n    }\n\n    /* Sanity check: NOT accepts only a single key argument. */\n    if (op == BITOP_NOT && c->argc != 4) {\n        addReplyError(c,\"BITOP NOT must be called with a single source key.\");\n        return;\n    }\n\n    /* Lookup keys, and store pointers to the string objects into an array. */\n    numkeys = c->argc - 3;\n    src = zmalloc(sizeof(unsigned char*) * numkeys);\n    len = zmalloc(sizeof(long) * numkeys);\n    objects = zmalloc(sizeof(robj*) * numkeys);\n    for (j = 0; j < numkeys; j++) {\n        o = lookupKeyRead(c->db,c->argv[j+3]);\n        /* Handle non-existing keys as empty strings. */\n        if (o == NULL) {\n            objects[j] = NULL;\n            src[j] = NULL;\n            len[j] = 0;\n            minlen = 0;\n            continue;\n        }\n        /* Return an error if one of the keys is not a string. */\n        if (checkType(c,o,OBJ_STRING)) {\n            unsigned long i;\n            for (i = 0; i < j; i++) {\n                if (objects[i])\n                    decrRefCount(objects[i]);\n            }\n            zfree(src);\n            zfree(len);\n            zfree(objects);\n            return;\n        }\n        objects[j] = getDecodedObject(o);\n        src[j] = objects[j]->ptr;\n        len[j] = sdslen(objects[j]->ptr);\n        if (len[j] > maxlen) maxlen = len[j];\n        if (j == 0 || len[j] < minlen) minlen = len[j];\n    }\n\n    /* Compute the bit operation, if at least one string is not empty. */\n    if (maxlen) {\n        res = (unsigned char*) sdsnewlen(NULL,maxlen);\n        unsigned char output, byte;\n        unsigned long i;\n\n        /* Fast path: as far as we have data for all the input bitmaps we\n         * can take a fast path that performs much better than the\n         * vanilla algorithm. */\n        j = 0;\n        if (minlen >= sizeof(unsigned long)*4 && numkeys <= 16) {\n            unsigned long *lp[16];\n            unsigned long *lres = (unsigned long*) res;\n\n            /* Note: sds pointer is always aligned to 8 byte boundary. */\n            memcpy(lp,src,sizeof(unsigned long*)*numkeys);\n            memcpy(res,src[0],minlen);\n\n            /* Different branches per different operations for speed (sorry). */\n            if (op == BITOP_AND) {\n                while(minlen >= sizeof(unsigned long)*4) {\n                    for (i = 1; i < numkeys; i++) {\n                        lres[0] &= lp[i][0];\n                        lres[1] &= lp[i][1];\n                        lres[2] &= lp[i][2];\n                        lres[3] &= lp[i][3];\n                        lp[i]+=4;\n                    }\n                    lres+=4;\n                    j += sizeof(unsigned long)*4;\n                    minlen -= sizeof(unsigned long)*4;\n                }\n            } else if (op == BITOP_OR) {\n                while(minlen >= sizeof(unsigned long)*4) {\n                    for (i = 1; i < numkeys; i++) {\n                        lres[0] |= lp[i][0];\n                        lres[1] |= lp[i][1];\n                        lres[2] |= lp[i][2];\n                        lres[3] |= lp[i][3];\n                        lp[i]+=4;\n                    }\n                    lres+=4;\n                    j += sizeof(unsigned long)*4;\n                    minlen -= sizeof(unsigned long)*4;\n                }\n            } else if (op == BITOP_XOR) {\n                while(minlen >= sizeof(unsigned long)*4) {\n                    for (i = 1; i < numkeys; i++) {\n                        lres[0] ^= lp[i][0];\n                        lres[1] ^= lp[i][1];\n                        lres[2] ^= lp[i][2];\n                        lres[3] ^= lp[i][3];\n                        lp[i]+=4;\n                    }\n                    lres+=4;\n                    j += sizeof(unsigned long)*4;\n                    minlen -= sizeof(unsigned long)*4;\n                }\n            } else if (op == BITOP_NOT) {\n                while(minlen >= sizeof(unsigned long)*4) {\n                    lres[0] = ~lres[0];\n                    lres[1] = ~lres[1];\n                    lres[2] = ~lres[2];\n                    lres[3] = ~lres[3];\n                    lres+=4;\n                    j += sizeof(unsigned long)*4;\n                    minlen -= sizeof(unsigned long)*4;\n                }\n            }\n        }\n\n        /* j is set to the next byte to process by the previous loop. */\n        for (; j < maxlen; j++) {\n            output = (len[0] <= j) ? 0 : src[0][j];\n            if (op == BITOP_NOT) output = ~output;\n            for (i = 1; i < numkeys; i++) {\n                byte = (len[i] <= j) ? 0 : src[i][j];\n                switch(op) {\n                case BITOP_AND: output &= byte; break;\n                case BITOP_OR:  output |= byte; break;\n                case BITOP_XOR: output ^= byte; break;\n                }\n            }\n            res[j] = output;\n        }\n    }\n    for (j = 0; j < numkeys; j++) {\n        if (objects[j])\n            decrRefCount(objects[j]);\n    }\n    zfree(src);\n    zfree(len);\n    zfree(objects);\n\n    /* Store the computed value into the target key */\n    if (maxlen) {\n        o = createObject(OBJ_STRING,res);\n        setKey(c->db,targetkey,o);\n        notifyKeyspaceEvent(NOTIFY_STRING,\"set\",targetkey,c->db->id);\n        decrRefCount(o);\n    } else if (dbDelete(c->db,targetkey)) {\n        signalModifiedKey(c->db,targetkey);\n        notifyKeyspaceEvent(NOTIFY_GENERIC,\"del\",targetkey,c->db->id);\n    }\n    server.dirty++;\n    addReplyLongLong(c,maxlen); /* Return the output string length in bytes. */\n}\n\n/* BITCOUNT key [start end] */\nvoid bitcountCommand(client *c) {\n    robj *o;\n    long start, end, strlen;\n    unsigned char *p;\n    char llbuf[LONG_STR_SIZE];\n\n    /* Lookup, check for type, and return 0 for non existing keys. */\n    if ((o = lookupKeyReadOrReply(c,c->argv[1],shared.czero)) == NULL ||\n        checkType(c,o,OBJ_STRING)) return;\n    p = getObjectReadOnlyString(o,&strlen,llbuf);\n\n    /* Parse start/end range if any. */\n    if (c->argc == 4) {\n        if (getLongFromObjectOrReply(c,c->argv[2],&start,NULL) != C_OK)\n            return;\n        if (getLongFromObjectOrReply(c,c->argv[3],&end,NULL) != C_OK)\n            return;\n        /* Convert negative indexes */\n        if (start < 0 && end < 0 && start > end) {\n            addReply(c,shared.czero);\n            return;\n        }\n        if (start < 0) start = strlen+start;\n        if (end < 0) end = strlen+end;\n        if (start < 0) start = 0;\n        if (end < 0) end = 0;\n        if (end >= strlen) end = strlen-1;\n    } else if (c->argc == 2) {\n        /* The whole string. */\n        start = 0;\n        end = strlen-1;\n    } else {\n        /* Syntax error. */\n        addReply(c,shared.syntaxerr);\n        return;\n    }\n\n    /* Precondition: end >= 0 && end < strlen, so the only condition where\n     * zero can be returned is: start > end. */\n    if (start > end) {\n        addReply(c,shared.czero);\n    } else {\n        long bytes = end-start+1;\n\n        addReplyLongLong(c,redisPopcount(p+start,bytes));\n    }\n}\n\n/* BITPOS key bit [start [end]] */\nvoid bitposCommand(client *c) {\n    robj *o;\n    long bit, start, end, strlen;\n    unsigned char *p;\n    char llbuf[LONG_STR_SIZE];\n    int end_given = 0;\n\n    /* Parse the bit argument to understand what we are looking for, set\n     * or clear bits. */\n    if (getLongFromObjectOrReply(c,c->argv[2],&bit,NULL) != C_OK)\n        return;\n    if (bit != 0 && bit != 1) {\n        addReplyError(c, \"The bit argument must be 1 or 0.\");\n        return;\n    }\n\n    /* If the key does not exist, from our point of view it is an infinite\n     * array of 0 bits. If the user is looking for the fist clear bit return 0,\n     * If the user is looking for the first set bit, return -1. */\n    if ((o = lookupKeyRead(c->db,c->argv[1])) == NULL) {\n        addReplyLongLong(c, bit ? -1 : 0);\n        return;\n    }\n    if (checkType(c,o,OBJ_STRING)) return;\n    p = getObjectReadOnlyString(o,&strlen,llbuf);\n\n    /* Parse start/end range if any. */\n    if (c->argc == 4 || c->argc == 5) {\n        if (getLongFromObjectOrReply(c,c->argv[3],&start,NULL) != C_OK)\n            return;\n        if (c->argc == 5) {\n            if (getLongFromObjectOrReply(c,c->argv[4],&end,NULL) != C_OK)\n                return;\n            end_given = 1;\n        } else {\n            end = strlen-1;\n        }\n        /* Convert negative indexes */\n        if (start < 0) start = strlen+start;\n        if (end < 0) end = strlen+end;\n        if (start < 0) start = 0;\n        if (end < 0) end = 0;\n        if (end >= strlen) end = strlen-1;\n    } else if (c->argc == 3) {\n        /* The whole string. */\n        start = 0;\n        end = strlen-1;\n    } else {\n        /* Syntax error. */\n        addReply(c,shared.syntaxerr);\n        return;\n    }\n\n    /* For empty ranges (start > end) we return -1 as an empty range does\n     * not contain a 0 nor a 1. */\n    if (start > end) {\n        addReplyLongLong(c, -1);\n    } else {\n        long bytes = end-start+1;\n        long pos = redisBitpos(p+start,bytes,bit);\n\n        /* If we are looking for clear bits, and the user specified an exact\n         * range with start-end, we can't consider the right of the range as\n         * zero padded (as we do when no explicit end is given).\n         *\n         * So if redisBitpos() returns the first bit outside the range,\n         * we return -1 to the caller, to mean, in the specified range there\n         * is not a single \"0\" bit. */\n        if (end_given && bit == 0 && pos == bytes*8) {\n            addReplyLongLong(c,-1);\n            return;\n        }\n        if (pos != -1) pos += start*8; /* Adjust for the bytes we skipped. */\n        addReplyLongLong(c,pos);\n    }\n}\n\n/* BITFIELD key subcommmand-1 arg ... subcommand-2 arg ... subcommand-N ...\n *\n * Supported subcommands:\n *\n * GET <type> <offset>\n * SET <type> <offset> <value>\n * INCRBY <type> <offset> <increment>\n * OVERFLOW [WRAP|SAT|FAIL]\n */\n\nstruct bitfieldOp {\n    uint64_t offset;    /* Bitfield offset. */\n    int64_t i64;        /* Increment amount (INCRBY) or SET value */\n    int opcode;         /* Operation id. */\n    int owtype;         /* Overflow type to use. */\n    int bits;           /* Integer bitfield bits width. */\n    int sign;           /* True if signed, otherwise unsigned op. */\n};\n\nvoid bitfieldCommand(client *c) {\n    robj *o;\n    size_t bitoffset;\n    int j, numops = 0, changes = 0;\n    struct bitfieldOp *ops = NULL; /* Array of ops to execute at end. */\n    int owtype = BFOVERFLOW_WRAP; /* Overflow type. */\n    int readonly = 1;\n    size_t higest_write_offset = 0;\n\n    for (j = 2; j < c->argc; j++) {\n        int remargs = c->argc-j-1; /* Remaining args other than current. */\n        char *subcmd = c->argv[j]->ptr; /* Current command name. */\n        int opcode; /* Current operation code. */\n        long long i64 = 0;  /* Signed SET value. */\n        int sign = 0; /* Signed or unsigned type? */\n        int bits = 0; /* Bitfield width in bits. */\n\n        if (!strcasecmp(subcmd,\"get\") && remargs >= 2)\n            opcode = BITFIELDOP_GET;\n        else if (!strcasecmp(subcmd,\"set\") && remargs >= 3)\n            opcode = BITFIELDOP_SET;\n        else if (!strcasecmp(subcmd,\"incrby\") && remargs >= 3)\n            opcode = BITFIELDOP_INCRBY;\n        else if (!strcasecmp(subcmd,\"overflow\") && remargs >= 1) {\n            char *owtypename = c->argv[j+1]->ptr;\n            j++;\n            if (!strcasecmp(owtypename,\"wrap\"))\n                owtype = BFOVERFLOW_WRAP;\n            else if (!strcasecmp(owtypename,\"sat\"))\n                owtype = BFOVERFLOW_SAT;\n            else if (!strcasecmp(owtypename,\"fail\"))\n                owtype = BFOVERFLOW_FAIL;\n            else {\n                addReplyError(c,\"Invalid OVERFLOW type specified\");\n                zfree(ops);\n                return;\n            }\n            continue;\n        } else {\n            addReply(c,shared.syntaxerr);\n            zfree(ops);\n            return;\n        }\n\n        /* Get the type and offset arguments, common to all the ops. */\n        if (getBitfieldTypeFromArgument(c,c->argv[j+1],&sign,&bits) != C_OK) {\n            zfree(ops);\n            return;\n        }\n\n        if (getBitOffsetFromArgument(c,c->argv[j+2],&bitoffset,1,bits) != C_OK){\n            zfree(ops);\n            return;\n        }\n\n        if (opcode != BITFIELDOP_GET) {\n            readonly = 0;\n            if (higest_write_offset < bitoffset + bits - 1)\n                higest_write_offset = bitoffset + bits - 1;\n            /* INCRBY and SET require another argument. */\n            if (getLongLongFromObjectOrReply(c,c->argv[j+3],&i64,NULL) != C_OK){\n                zfree(ops);\n                return;\n            }\n        }\n\n        /* Populate the array of operations we'll process. */\n        ops = zrealloc(ops,sizeof(*ops)*(numops+1));\n        ops[numops].offset = bitoffset;\n        ops[numops].i64 = i64;\n        ops[numops].opcode = opcode;\n        ops[numops].owtype = owtype;\n        ops[numops].bits = bits;\n        ops[numops].sign = sign;\n        numops++;\n\n        j += 3 - (opcode == BITFIELDOP_GET);\n    }\n\n    if (readonly) {\n        /* Lookup for read is ok if key doesn't exit, but errors\n         * if it's not a string. */\n        o = lookupKeyRead(c->db,c->argv[1]);\n        if (o != NULL && checkType(c,o,OBJ_STRING)) return;\n    } else {\n        /* Lookup by making room up to the farest bit reached by\n         * this operation. */\n        if ((o = lookupStringForBitCommand(c,\n            higest_write_offset)) == NULL) return;\n    }\n\n    addReplyMultiBulkLen(c,numops);\n\n    /* Actually process the operations. */\n    for (j = 0; j < numops; j++) {\n        struct bitfieldOp *thisop = ops+j;\n\n        /* Execute the operation. */\n        if (thisop->opcode == BITFIELDOP_SET ||\n            thisop->opcode == BITFIELDOP_INCRBY)\n        {\n            /* SET and INCRBY: We handle both with the same code path\n             * for simplicity. SET return value is the previous value so\n             * we need fetch & store as well. */\n\n            /* We need two different but very similar code paths for signed\n             * and unsigned operations, since the set of functions to get/set\n             * the integers and the used variables types are different. */\n            if (thisop->sign) {\n                int64_t oldval, newval, wrapped, retval;\n                int overflow;\n\n                oldval = getSignedBitfield(o->ptr,thisop->offset,\n                        thisop->bits);\n\n                if (thisop->opcode == BITFIELDOP_INCRBY) {\n                    newval = oldval + thisop->i64;\n                    overflow = checkSignedBitfieldOverflow(oldval,\n                            thisop->i64,thisop->bits,thisop->owtype,&wrapped);\n                    if (overflow) newval = wrapped;\n                    retval = newval;\n                } else {\n                    newval = thisop->i64;\n                    overflow = checkSignedBitfieldOverflow(newval,\n                            0,thisop->bits,thisop->owtype,&wrapped);\n                    if (overflow) newval = wrapped;\n                    retval = oldval;\n                }\n\n                /* On overflow of type is \"FAIL\", don't write and return\n                 * NULL to signal the condition. */\n                if (!(overflow && thisop->owtype == BFOVERFLOW_FAIL)) {\n                    addReplyLongLong(c,retval);\n                    setSignedBitfield(o->ptr,thisop->offset,\n                                      thisop->bits,newval);\n                } else {\n                    addReply(c,shared.nullbulk);\n                }\n            } else {\n                uint64_t oldval, newval, wrapped, retval;\n                int overflow;\n\n                oldval = getUnsignedBitfield(o->ptr,thisop->offset,\n                        thisop->bits);\n\n                if (thisop->opcode == BITFIELDOP_INCRBY) {\n                    newval = oldval + thisop->i64;\n                    overflow = checkUnsignedBitfieldOverflow(oldval,\n                            thisop->i64,thisop->bits,thisop->owtype,&wrapped);\n                    if (overflow) newval = wrapped;\n                    retval = newval;\n                } else {\n                    newval = thisop->i64;\n                    overflow = checkUnsignedBitfieldOverflow(newval,\n                            0,thisop->bits,thisop->owtype,&wrapped);\n                    if (overflow) newval = wrapped;\n                    retval = oldval;\n                }\n                /* On overflow of type is \"FAIL\", don't write and return\n                 * NULL to signal the condition. */\n                if (!(overflow && thisop->owtype == BFOVERFLOW_FAIL)) {\n                    addReplyLongLong(c,retval);\n                    setUnsignedBitfield(o->ptr,thisop->offset,\n                                        thisop->bits,newval);\n                } else {\n                    addReply(c,shared.nullbulk);\n                }\n            }\n            changes++;\n        } else {\n            /* GET */\n            unsigned char buf[9];\n            long strlen = 0;\n            unsigned char *src = NULL;\n            char llbuf[LONG_STR_SIZE];\n\n            if (o != NULL)\n                src = getObjectReadOnlyString(o,&strlen,llbuf);\n\n            /* For GET we use a trick: before executing the operation\n             * copy up to 9 bytes to a local buffer, so that we can easily\n             * execute up to 64 bit operations that are at actual string\n             * object boundaries. */\n            memset(buf,0,9);\n            int i;\n            size_t byte = thisop->offset >> 3;\n            for (i = 0; i < 9; i++) {\n                if (src == NULL || i+byte >= (size_t)strlen) break;\n                buf[i] = src[i+byte];\n            }\n\n            /* Now operate on the copied buffer which is guaranteed\n             * to be zero-padded. */\n            if (thisop->sign) {\n                int64_t val = getSignedBitfield(buf,thisop->offset-(byte*8),\n                                            thisop->bits);\n                addReplyLongLong(c,val);\n            } else {\n                uint64_t val = getUnsignedBitfield(buf,thisop->offset-(byte*8),\n                                            thisop->bits);\n                addReplyLongLong(c,val);\n            }\n        }\n    }\n\n    if (changes) {\n        signalModifiedKey(c->db,c->argv[1]);\n        notifyKeyspaceEvent(NOTIFY_STRING,\"setbit\",c->argv[1],c->db->id);\n        server.dirty += changes;\n    }\n    zfree(ops);\n}\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.8/src/blocked.c",
    "content": "/* blocked.c - generic support for blocking operations like BLPOP & WAIT.\n *\n * Copyright (c) 2009-2012, Salvatore Sanfilippo <antirez at gmail dot com>\n * All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions are met:\n *\n *   * Redistributions of source code must retain the above copyright notice,\n *     this list of conditions and the following disclaimer.\n *   * Redistributions in binary form must reproduce the above copyright\n *     notice, this list of conditions and the following disclaimer in the\n *     documentation and/or other materials provided with the distribution.\n *   * Neither the name of Redis nor the names of its contributors may be used\n *     to endorse or promote products derived from this software without\n *     specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\"\n * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\n * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE\n * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR\n * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF\n * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS\n * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN\n * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)\n * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE\n * POSSIBILITY OF SUCH DAMAGE.\n *\n * ---------------------------------------------------------------------------\n *\n * API:\n *\n * getTimeoutFromObjectOrReply() is just an utility function to parse a\n * timeout argument since blocking operations usually require a timeout.\n *\n * blockClient() set the CLIENT_BLOCKED flag in the client, and set the\n * specified block type 'btype' filed to one of BLOCKED_* macros.\n *\n * unblockClient() unblocks the client doing the following:\n * 1) It calls the btype-specific function to cleanup the state.\n * 2) It unblocks the client by unsetting the CLIENT_BLOCKED flag.\n * 3) It puts the client into a list of just unblocked clients that are\n *    processed ASAP in the beforeSleep() event loop callback, so that\n *    if there is some query buffer to process, we do it. This is also\n *    required because otherwise there is no 'readable' event fired, we\n *    already read the pending commands. We also set the CLIENT_UNBLOCKED\n *    flag to remember the client is in the unblocked_clients list.\n *\n * processUnblockedClients() is called inside the beforeSleep() function\n * to process the query buffer from unblocked clients and remove the clients\n * from the blocked_clients queue.\n *\n * replyToBlockedClientTimedOut() is called by the cron function when\n * a client blocked reaches the specified timeout (if the timeout is set\n * to 0, no timeout is processed).\n * It usually just needs to send a reply to the client.\n *\n * When implementing a new type of blocking opeation, the implementation\n * should modify unblockClient() and replyToBlockedClientTimedOut() in order\n * to handle the btype-specific behavior of this two functions.\n * If the blocking operation waits for certain keys to change state, the\n * clusterRedirectBlockedClientIfNeeded() function should also be updated.\n */\n\n#include \"server.h\"\n\n/* Get a timeout value from an object and store it into 'timeout'.\n * The final timeout is always stored as milliseconds as a time where the\n * timeout will expire, however the parsing is performed according to\n * the 'unit' that can be seconds or milliseconds.\n *\n * Note that if the timeout is zero (usually from the point of view of\n * commands API this means no timeout) the value stored into 'timeout'\n * is zero. */\nint getTimeoutFromObjectOrReply(client *c, robj *object, mstime_t *timeout, int unit) {\n    long long tval;\n\n    if (getLongLongFromObjectOrReply(c,object,&tval,\n        \"timeout is not an integer or out of range\") != C_OK)\n        return C_ERR;\n\n    if (tval < 0) {\n        addReplyError(c,\"timeout is negative\");\n        return C_ERR;\n    }\n\n    if (tval > 0) {\n        if (unit == UNIT_SECONDS) tval *= 1000;\n        tval += mstime();\n    }\n    *timeout = tval;\n\n    return C_OK;\n}\n\n/* Block a client for the specific operation type. Once the CLIENT_BLOCKED\n * flag is set client query buffer is not longer processed, but accumulated,\n * and will be processed when the client is unblocked. */\nvoid blockClient(client *c, int btype) {\n    c->flags |= CLIENT_BLOCKED;\n    c->btype = btype;\n    server.bpop_blocked_clients++;\n}\n\n/* This function is called in the beforeSleep() function of the event loop\n * in order to process the pending input buffer of clients that were\n * unblocked after a blocking operation. */\nvoid processUnblockedClients(void) {\n    listNode *ln;\n    client *c;\n\n    while (listLength(server.unblocked_clients)) {\n        ln = listFirst(server.unblocked_clients);\n        serverAssert(ln != NULL);\n        c = ln->value;\n        listDelNode(server.unblocked_clients,ln);\n        c->flags &= ~CLIENT_UNBLOCKED;\n\n        /* Process remaining data in the input buffer, unless the client\n         * is blocked again. Actually processInputBuffer() checks that the\n         * client is not blocked before to proceed, but things may change and\n         * the code is conceptually more correct this way. */\n        if (!(c->flags & CLIENT_BLOCKED)) {\n            if (c->querybuf && sdslen(c->querybuf) > 0) {\n                processInputBuffer(c);\n            }\n        }\n    }\n}\n\n/* Unblock a client calling the right function depending on the kind\n * of operation the client is blocking for. */\nvoid unblockClient(client *c) {\n    if (c->btype == BLOCKED_LIST) {\n        unblockClientWaitingData(c);\n    } else if (c->btype == BLOCKED_WAIT) {\n        unblockClientWaitingReplicas(c);\n    } else {\n        serverPanic(\"Unknown btype in unblockClient().\");\n    }\n    /* Clear the flags, and put the client in the unblocked list so that\n     * we'll process new commands in its query buffer ASAP. */\n    c->flags &= ~CLIENT_BLOCKED;\n    c->btype = BLOCKED_NONE;\n    server.bpop_blocked_clients--;\n    /* The client may already be into the unblocked list because of a previous\n     * blocking operation, don't add back it into the list multiple times. */\n    if (!(c->flags & CLIENT_UNBLOCKED)) {\n        c->flags |= CLIENT_UNBLOCKED;\n        listAddNodeTail(server.unblocked_clients,c);\n    }\n}\n\n/* This function gets called when a blocked client timed out in order to\n * send it a reply of some kind. */\nvoid replyToBlockedClientTimedOut(client *c) {\n    if (c->btype == BLOCKED_LIST) {\n        addReply(c,shared.nullmultibulk);\n    } else if (c->btype == BLOCKED_WAIT) {\n        addReplyLongLong(c,replicationCountAcksByOffset(c->bpop.reploffset));\n    } else {\n        serverPanic(\"Unknown btype in replyToBlockedClientTimedOut().\");\n    }\n}\n\n/* Mass-unblock clients because something changed in the instance that makes\n * blocking no longer safe. For example clients blocked in list operations\n * in an instance which turns from master to slave is unsafe, so this function\n * is called when a master turns into a slave.\n *\n * The semantics is to send an -UNBLOCKED error to the client, disconnecting\n * it at the same time. */\nvoid disconnectAllBlockedClients(void) {\n    listNode *ln;\n    listIter li;\n\n    listRewind(server.clients,&li);\n    while((ln = listNext(&li))) {\n        client *c = listNodeValue(ln);\n\n        if (c->flags & CLIENT_BLOCKED) {\n            addReplySds(c,sdsnew(\n                \"-UNBLOCKED force unblock from blocking operation, \"\n                \"instance state changed (master -> slave?)\\r\\n\"));\n            unblockClient(c);\n            c->flags |= CLIENT_CLOSE_AFTER_REPLY;\n        }\n    }\n}\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.8/src/cluster.c",
    "content": "/* Redis Cluster implementation.\n *\n * Copyright (c) 2009-2012, Salvatore Sanfilippo <antirez at gmail dot com>\n * All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions are met:\n *\n *   * Redistributions of source code must retain the above copyright notice,\n *     this list of conditions and the following disclaimer.\n *   * Redistributions in binary form must reproduce the above copyright\n *     notice, this list of conditions and the following disclaimer in the\n *     documentation and/or other materials provided with the distribution.\n *   * Neither the name of Redis nor the names of its contributors may be used\n *     to endorse or promote products derived from this software without\n *     specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\"\n * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\n * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE\n * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR\n * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF\n * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS\n * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN\n * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)\n * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE\n * POSSIBILITY OF SUCH DAMAGE.\n */\n\n#include \"server.h\"\n#include \"cluster.h\"\n#include \"endianconv.h\"\n\n#include <sys/types.h>\n#include <sys/socket.h>\n#include <arpa/inet.h>\n#include <fcntl.h>\n#include <unistd.h>\n#include <sys/socket.h>\n#include <sys/stat.h>\n#include <sys/file.h>\n#include <math.h>\n\n/* A global reference to myself is handy to make code more clear.\n * Myself always points to server.cluster->myself, that is, the clusterNode\n * that represents this node. */\nclusterNode *myself = NULL;\n\nclusterNode *createClusterNode(char *nodename, int flags);\nint clusterAddNode(clusterNode *node);\nvoid clusterAcceptHandler(aeEventLoop *el, int fd, void *privdata, int mask);\nvoid clusterReadHandler(aeEventLoop *el, int fd, void *privdata, int mask);\nvoid clusterSendPing(clusterLink *link, int type);\nvoid clusterSendFail(char *nodename);\nvoid clusterSendFailoverAuthIfNeeded(clusterNode *node, clusterMsg *request);\nvoid clusterUpdateState(void);\nint clusterNodeGetSlotBit(clusterNode *n, int slot);\nsds clusterGenNodesDescription(int filter);\nclusterNode *clusterLookupNode(char *name);\nint clusterNodeAddSlave(clusterNode *master, clusterNode *slave);\nint clusterAddSlot(clusterNode *n, int slot);\nint clusterDelSlot(int slot);\nint clusterDelNodeSlots(clusterNode *node);\nint clusterNodeSetSlotBit(clusterNode *n, int slot);\nvoid clusterSetMaster(clusterNode *n);\nvoid clusterHandleSlaveFailover(void);\nvoid clusterHandleSlaveMigration(int max_slaves);\nint bitmapTestBit(unsigned char *bitmap, int pos);\nvoid clusterDoBeforeSleep(int flags);\nvoid clusterSendUpdate(clusterLink *link, clusterNode *node);\nvoid resetManualFailover(void);\nvoid clusterCloseAllSlots(void);\nvoid clusterSetNodeAsMaster(clusterNode *n);\nvoid clusterDelNode(clusterNode *delnode);\nsds representClusterNodeFlags(sds ci, uint16_t flags);\nuint64_t clusterGetMaxEpoch(void);\nint clusterBumpConfigEpochWithoutConsensus(void);\n\n/* -----------------------------------------------------------------------------\n * Initialization\n * -------------------------------------------------------------------------- */\n\n/* Load the cluster config from 'filename'.\n *\n * If the file does not exist or is zero-length (this may happen because\n * when we lock the nodes.conf file, we create a zero-length one for the\n * sake of locking if it does not already exist), C_ERR is returned.\n * If the configuration was loaded from the file, C_OK is returned. */\nint clusterLoadConfig(char *filename) {\n    FILE *fp = fopen(filename,\"r\");\n    struct stat sb;\n    char *line;\n    int maxline, j;\n\n    if (fp == NULL) {\n        if (errno == ENOENT) {\n            return C_ERR;\n        } else {\n            serverLog(LL_WARNING,\n                \"Loading the cluster node config from %s: %s\",\n                filename, strerror(errno));\n            exit(1);\n        }\n    }\n\n    /* Check if the file is zero-length: if so return C_ERR to signal\n     * we have to write the config. */\n    if (fstat(fileno(fp),&sb) != -1 && sb.st_size == 0) {\n        fclose(fp);\n        return C_ERR;\n    }\n\n    /* Parse the file. Note that single lines of the cluster config file can\n     * be really long as they include all the hash slots of the node.\n     * This means in the worst possible case, half of the Redis slots will be\n     * present in a single line, possibly in importing or migrating state, so\n     * together with the node ID of the sender/receiver.\n     *\n     * To simplify we allocate 1024+CLUSTER_SLOTS*128 bytes per line. */\n    maxline = 1024+CLUSTER_SLOTS*128;\n    line = zmalloc(maxline);\n    while(fgets(line,maxline,fp) != NULL) {\n        int argc;\n        sds *argv;\n        clusterNode *n, *master;\n        char *p, *s;\n\n        /* Skip blank lines, they can be created either by users manually\n         * editing nodes.conf or by the config writing process if stopped\n         * before the truncate() call. */\n        if (line[0] == '\\n' || line[0] == '\\0') continue;\n\n        /* Split the line into arguments for processing. */\n        argv = sdssplitargs(line,&argc);\n        if (argv == NULL) goto fmterr;\n\n        /* Handle the special \"vars\" line. Don't pretend it is the last\n         * line even if it actually is when generated by Redis. */\n        if (strcasecmp(argv[0],\"vars\") == 0) {\n            for (j = 1; j < argc; j += 2) {\n                if (strcasecmp(argv[j],\"currentEpoch\") == 0) {\n                    server.cluster->currentEpoch =\n                            strtoull(argv[j+1],NULL,10);\n                } else if (strcasecmp(argv[j],\"lastVoteEpoch\") == 0) {\n                    server.cluster->lastVoteEpoch =\n                            strtoull(argv[j+1],NULL,10);\n                } else {\n                    serverLog(LL_WARNING,\n                        \"Skipping unknown cluster config variable '%s'\",\n                        argv[j]);\n                }\n            }\n            sdsfreesplitres(argv,argc);\n            continue;\n        }\n\n        /* Regular config lines have at least eight fields */\n        if (argc < 8) goto fmterr;\n\n        /* Create this node if it does not exist */\n        n = clusterLookupNode(argv[0]);\n        if (!n) {\n            n = createClusterNode(argv[0],0);\n            clusterAddNode(n);\n        }\n        /* Address and port */\n        if ((p = strrchr(argv[1],':')) == NULL) goto fmterr;\n        *p = '\\0';\n        memcpy(n->ip,argv[1],strlen(argv[1])+1);\n        n->port = atoi(p+1);\n\n        /* Parse flags */\n        p = s = argv[2];\n        while(p) {\n            p = strchr(s,',');\n            if (p) *p = '\\0';\n            if (!strcasecmp(s,\"myself\")) {\n                serverAssert(server.cluster->myself == NULL);\n                myself = server.cluster->myself = n;\n                n->flags |= CLUSTER_NODE_MYSELF;\n            } else if (!strcasecmp(s,\"master\")) {\n                n->flags |= CLUSTER_NODE_MASTER;\n            } else if (!strcasecmp(s,\"slave\")) {\n                n->flags |= CLUSTER_NODE_SLAVE;\n            } else if (!strcasecmp(s,\"fail?\")) {\n                n->flags |= CLUSTER_NODE_PFAIL;\n            } else if (!strcasecmp(s,\"fail\")) {\n                n->flags |= CLUSTER_NODE_FAIL;\n                n->fail_time = mstime();\n            } else if (!strcasecmp(s,\"handshake\")) {\n                n->flags |= CLUSTER_NODE_HANDSHAKE;\n            } else if (!strcasecmp(s,\"noaddr\")) {\n                n->flags |= CLUSTER_NODE_NOADDR;\n            } else if (!strcasecmp(s,\"noflags\")) {\n                /* nothing to do */\n            } else {\n                serverPanic(\"Unknown flag in redis cluster config file\");\n            }\n            if (p) s = p+1;\n        }\n\n        /* Get master if any. Set the master and populate master's\n         * slave list. */\n        if (argv[3][0] != '-') {\n            master = clusterLookupNode(argv[3]);\n            if (!master) {\n                master = createClusterNode(argv[3],0);\n                clusterAddNode(master);\n            }\n            n->slaveof = master;\n            clusterNodeAddSlave(master,n);\n        }\n\n        /* Set ping sent / pong received timestamps */\n        if (atoi(argv[4])) n->ping_sent = mstime();\n        if (atoi(argv[5])) n->pong_received = mstime();\n\n        /* Set configEpoch for this node. */\n        n->configEpoch = strtoull(argv[6],NULL,10);\n\n        /* Populate hash slots served by this instance. */\n        for (j = 8; j < argc; j++) {\n            int start, stop;\n\n            if (argv[j][0] == '[') {\n                /* Here we handle migrating / importing slots */\n                int slot;\n                char direction;\n                clusterNode *cn;\n\n                p = strchr(argv[j],'-');\n                serverAssert(p != NULL);\n                *p = '\\0';\n                direction = p[1]; /* Either '>' or '<' */\n                slot = atoi(argv[j]+1);\n                p += 3;\n                cn = clusterLookupNode(p);\n                if (!cn) {\n                    cn = createClusterNode(p,0);\n                    clusterAddNode(cn);\n                }\n                if (direction == '>') {\n                    server.cluster->migrating_slots_to[slot] = cn;\n                } else {\n                    server.cluster->importing_slots_from[slot] = cn;\n                }\n                continue;\n            } else if ((p = strchr(argv[j],'-')) != NULL) {\n                *p = '\\0';\n                start = atoi(argv[j]);\n                stop = atoi(p+1);\n            } else {\n                start = stop = atoi(argv[j]);\n            }\n            while(start <= stop) clusterAddSlot(n, start++);\n        }\n\n        sdsfreesplitres(argv,argc);\n    }\n    /* Config sanity check */\n    if (server.cluster->myself == NULL) goto fmterr;\n\n    zfree(line);\n    fclose(fp);\n\n    serverLog(LL_NOTICE,\"Node configuration loaded, I'm %.40s\", myself->name);\n\n    /* Something that should never happen: currentEpoch smaller than\n     * the max epoch found in the nodes configuration. However we handle this\n     * as some form of protection against manual editing of critical files. */\n    if (clusterGetMaxEpoch() > server.cluster->currentEpoch) {\n        server.cluster->currentEpoch = clusterGetMaxEpoch();\n    }\n    return C_OK;\n\nfmterr:\n    serverLog(LL_WARNING,\n        \"Unrecoverable error: corrupted cluster config file.\");\n    zfree(line);\n    if (fp) fclose(fp);\n    exit(1);\n}\n\n/* Cluster node configuration is exactly the same as CLUSTER NODES output.\n *\n * This function writes the node config and returns 0, on error -1\n * is returned.\n *\n * Note: we need to write the file in an atomic way from the point of view\n * of the POSIX filesystem semantics, so that if the server is stopped\n * or crashes during the write, we'll end with either the old file or the\n * new one. Since we have the full payload to write available we can use\n * a single write to write the whole file. If the pre-existing file was\n * bigger we pad our payload with newlines that are anyway ignored and truncate\n * the file afterward. */\nint clusterSaveConfig(int do_fsync) {\n    sds ci;\n    size_t content_size;\n    struct stat sb;\n    int fd;\n\n    server.cluster->todo_before_sleep &= ~CLUSTER_TODO_SAVE_CONFIG;\n\n    /* Get the nodes description and concatenate our \"vars\" directive to\n     * save currentEpoch and lastVoteEpoch. */\n    ci = clusterGenNodesDescription(CLUSTER_NODE_HANDSHAKE);\n    ci = sdscatprintf(ci,\"vars currentEpoch %llu lastVoteEpoch %llu\\n\",\n        (unsigned long long) server.cluster->currentEpoch,\n        (unsigned long long) server.cluster->lastVoteEpoch);\n    content_size = sdslen(ci);\n\n    if ((fd = open(server.cluster_configfile,O_WRONLY|O_CREAT,0644))\n        == -1) goto err;\n\n    /* Pad the new payload if the existing file length is greater. */\n    if (fstat(fd,&sb) != -1) {\n        if (sb.st_size > (off_t)content_size) {\n            ci = sdsgrowzero(ci,sb.st_size);\n            memset(ci+content_size,'\\n',sb.st_size-content_size);\n        }\n    }\n    if (write(fd,ci,sdslen(ci)) != (ssize_t)sdslen(ci)) goto err;\n    if (do_fsync) {\n        server.cluster->todo_before_sleep &= ~CLUSTER_TODO_FSYNC_CONFIG;\n        fsync(fd);\n    }\n\n    /* Truncate the file if needed to remove the final \\n padding that\n     * is just garbage. */\n    if (content_size != sdslen(ci) && ftruncate(fd,content_size) == -1) {\n        /* ftruncate() failing is not a critical error. */\n    }\n    close(fd);\n    sdsfree(ci);\n    return 0;\n\nerr:\n    if (fd != -1) close(fd);\n    sdsfree(ci);\n    return -1;\n}\n\nvoid clusterSaveConfigOrDie(int do_fsync) {\n    if (clusterSaveConfig(do_fsync) == -1) {\n        serverLog(LL_WARNING,\"Fatal: can't update cluster config file.\");\n        exit(1);\n    }\n}\n\n/* Lock the cluster config using flock(), and leaks the file descritor used to\n * acquire the lock so that the file will be locked forever.\n *\n * This works because we always update nodes.conf with a new version\n * in-place, reopening the file, and writing to it in place (later adjusting\n * the length with ftruncate()).\n *\n * On success C_OK is returned, otherwise an error is logged and\n * the function returns C_ERR to signal a lock was not acquired. */\nint clusterLockConfig(char *filename) {\n/* flock() does not exist on Solaris\n * and a fcntl-based solution won't help, as we constantly re-open that file,\n * which will release _all_ locks anyway\n */\n#if !defined(__sun)\n    /* To lock it, we need to open the file in a way it is created if\n     * it does not exist, otherwise there is a race condition with other\n     * processes. */\n    int fd = open(filename,O_WRONLY|O_CREAT,0644);\n    if (fd == -1) {\n        serverLog(LL_WARNING,\n            \"Can't open %s in order to acquire a lock: %s\",\n            filename, strerror(errno));\n        return C_ERR;\n    }\n\n    if (flock(fd,LOCK_EX|LOCK_NB) == -1) {\n        if (errno == EWOULDBLOCK) {\n            serverLog(LL_WARNING,\n                 \"Sorry, the cluster configuration file %s is already used \"\n                 \"by a different Redis Cluster node. Please make sure that \"\n                 \"different nodes use different cluster configuration \"\n                 \"files.\", filename);\n        } else {\n            serverLog(LL_WARNING,\n                \"Impossible to lock %s: %s\", filename, strerror(errno));\n        }\n        close(fd);\n        return C_ERR;\n    }\n    /* Lock acquired: leak the 'fd' by not closing it, so that we'll retain the\n     * lock to the file as long as the process exists. */\n#endif /* __sun */\n\n    return C_OK;\n}\n\nvoid clusterInit(void) {\n    int saveconf = 0;\n\n    server.cluster = zmalloc(sizeof(clusterState));\n    server.cluster->myself = NULL;\n    server.cluster->currentEpoch = 0;\n    server.cluster->state = CLUSTER_FAIL;\n    server.cluster->size = 1;\n    server.cluster->todo_before_sleep = 0;\n    server.cluster->nodes = dictCreate(&clusterNodesDictType,NULL);\n    server.cluster->nodes_black_list =\n        dictCreate(&clusterNodesBlackListDictType,NULL);\n    server.cluster->failover_auth_time = 0;\n    server.cluster->failover_auth_count = 0;\n    server.cluster->failover_auth_rank = 0;\n    server.cluster->failover_auth_epoch = 0;\n    server.cluster->cant_failover_reason = CLUSTER_CANT_FAILOVER_NONE;\n    server.cluster->lastVoteEpoch = 0;\n    server.cluster->stats_bus_messages_sent = 0;\n    server.cluster->stats_bus_messages_received = 0;\n    memset(server.cluster->slots,0, sizeof(server.cluster->slots));\n    clusterCloseAllSlots();\n\n    /* Lock the cluster config file to make sure every node uses\n     * its own nodes.conf. */\n    if (clusterLockConfig(server.cluster_configfile) == C_ERR)\n        exit(1);\n\n    /* Load or create a new nodes configuration. */\n    if (clusterLoadConfig(server.cluster_configfile) == C_ERR) {\n        /* No configuration found. We will just use the random name provided\n         * by the createClusterNode() function. */\n        myself = server.cluster->myself =\n            createClusterNode(NULL,CLUSTER_NODE_MYSELF|CLUSTER_NODE_MASTER);\n        serverLog(LL_NOTICE,\"No cluster configuration found, I'm %.40s\",\n            myself->name);\n        clusterAddNode(myself);\n        saveconf = 1;\n    }\n    if (saveconf) clusterSaveConfigOrDie(1);\n\n    /* We need a listening TCP port for our cluster messaging needs. */\n    server.cfd_count = 0;\n\n    /* Port sanity check II\n     * The other handshake port check is triggered too late to stop\n     * us from trying to use a too-high cluster port number. */\n    if (server.port > (65535-CLUSTER_PORT_INCR)) {\n        serverLog(LL_WARNING, \"Redis port number too high. \"\n                   \"Cluster communication port is 10,000 port \"\n                   \"numbers higher than your Redis port. \"\n                   \"Your Redis port number must be \"\n                   \"lower than 55535.\");\n        exit(1);\n    }\n\n    if (listenToPort(server.port+CLUSTER_PORT_INCR,\n        server.cfd,&server.cfd_count) == C_ERR)\n    {\n        exit(1);\n    } else {\n        int j;\n\n        for (j = 0; j < server.cfd_count; j++) {\n            if (aeCreateFileEvent(server.el, server.cfd[j], AE_READABLE,\n                clusterAcceptHandler, NULL) == AE_ERR)\n                    serverPanic(\"Unrecoverable error creating Redis Cluster \"\n                                \"file event.\");\n        }\n    }\n\n    /* The slots -> keys map is a sorted set. Init it. */\n    server.cluster->slots_to_keys = zslCreate();\n\n    /* Set myself->port to my listening port, we'll just need to discover\n     * the IP address via MEET messages. */\n    myself->port = server.port;\n\n    server.cluster->mf_end = 0;\n    resetManualFailover();\n}\n\n/* Reset a node performing a soft or hard reset:\n *\n * 1) All other nodes are forget.\n * 2) All the assigned / open slots are released.\n * 3) If the node is a slave, it turns into a master.\n * 5) Only for hard reset: a new Node ID is generated.\n * 6) Only for hard reset: currentEpoch and configEpoch are set to 0.\n * 7) The new configuration is saved and the cluster state updated.\n * 8) If the node was a slave, the whole data set is flushed away. */\nvoid clusterReset(int hard) {\n    dictIterator *di;\n    dictEntry *de;\n    int j;\n\n    /* Turn into master. */\n    if (nodeIsSlave(myself)) {\n        clusterSetNodeAsMaster(myself);\n        replicationUnsetMaster();\n        emptyDb(NULL);\n    }\n\n    /* Close slots, reset manual failover state. */\n    clusterCloseAllSlots();\n    resetManualFailover();\n\n    /* Unassign all the slots. */\n    for (j = 0; j < CLUSTER_SLOTS; j++) clusterDelSlot(j);\n\n    /* Forget all the nodes, but myself. */\n    di = dictGetSafeIterator(server.cluster->nodes);\n    while((de = dictNext(di)) != NULL) {\n        clusterNode *node = dictGetVal(de);\n\n        if (node == myself) continue;\n        clusterDelNode(node);\n    }\n    dictReleaseIterator(di);\n\n    /* Hard reset only: set epochs to 0, change node ID. */\n    if (hard) {\n        sds oldname;\n\n        server.cluster->currentEpoch = 0;\n        server.cluster->lastVoteEpoch = 0;\n        myself->configEpoch = 0;\n        serverLog(LL_WARNING, \"configEpoch set to 0 via CLUSTER RESET HARD\");\n\n        /* To change the Node ID we need to remove the old name from the\n         * nodes table, change the ID, and re-add back with new name. */\n        oldname = sdsnewlen(myself->name, CLUSTER_NAMELEN);\n        dictDelete(server.cluster->nodes,oldname);\n        sdsfree(oldname);\n        getRandomHexChars(myself->name, CLUSTER_NAMELEN);\n        clusterAddNode(myself);\n        serverLog(LL_NOTICE,\"Node hard reset, now I'm %.40s\", myself->name);\n    }\n\n    /* Make sure to persist the new config and update the state. */\n    clusterDoBeforeSleep(CLUSTER_TODO_SAVE_CONFIG|\n                         CLUSTER_TODO_UPDATE_STATE|\n                         CLUSTER_TODO_FSYNC_CONFIG);\n}\n\n/* -----------------------------------------------------------------------------\n * CLUSTER communication link\n * -------------------------------------------------------------------------- */\n\nclusterLink *createClusterLink(clusterNode *node) {\n    clusterLink *link = zmalloc(sizeof(*link));\n    link->ctime = mstime();\n    link->sndbuf = sdsempty();\n    link->rcvbuf = sdsempty();\n    link->node = node;\n    link->fd = -1;\n    return link;\n}\n\n/* Free a cluster link, but does not free the associated node of course.\n * This function will just make sure that the original node associated\n * with this link will have the 'link' field set to NULL. */\nvoid freeClusterLink(clusterLink *link) {\n    if (link->fd != -1) {\n        aeDeleteFileEvent(server.el, link->fd, AE_WRITABLE);\n        aeDeleteFileEvent(server.el, link->fd, AE_READABLE);\n    }\n    sdsfree(link->sndbuf);\n    sdsfree(link->rcvbuf);\n    if (link->node)\n        link->node->link = NULL;\n    close(link->fd);\n    zfree(link);\n}\n\n#define MAX_CLUSTER_ACCEPTS_PER_CALL 1000\nvoid clusterAcceptHandler(aeEventLoop *el, int fd, void *privdata, int mask) {\n    int cport, cfd;\n    int max = MAX_CLUSTER_ACCEPTS_PER_CALL;\n    char cip[NET_IP_STR_LEN];\n    clusterLink *link;\n    UNUSED(el);\n    UNUSED(mask);\n    UNUSED(privdata);\n\n    /* If the server is starting up, don't accept cluster connections:\n     * UPDATE messages may interact with the database content. */\n    if (server.masterhost == NULL && server.loading) return;\n\n    while(max--) {\n        cfd = anetTcpAccept(server.neterr, fd, cip, sizeof(cip), &cport);\n        if (cfd == ANET_ERR) {\n            if (errno != EWOULDBLOCK)\n                serverLog(LL_VERBOSE,\n                    \"Error accepting cluster node: %s\", server.neterr);\n            return;\n        }\n        anetNonBlock(NULL,cfd);\n        anetEnableTcpNoDelay(NULL,cfd);\n\n        /* Use non-blocking I/O for cluster messages. */\n        serverLog(LL_VERBOSE,\"Accepted cluster node %s:%d\", cip, cport);\n        /* Create a link object we use to handle the connection.\n         * It gets passed to the readable handler when data is available.\n         * Initiallly the link->node pointer is set to NULL as we don't know\n         * which node is, but the right node is references once we know the\n         * node identity. */\n        link = createClusterLink(NULL);\n        link->fd = cfd;\n        aeCreateFileEvent(server.el,cfd,AE_READABLE,clusterReadHandler,link);\n    }\n}\n\n/* -----------------------------------------------------------------------------\n * Key space handling\n * -------------------------------------------------------------------------- */\n\n/* We have 16384 hash slots. The hash slot of a given key is obtained\n * as the least significant 14 bits of the crc16 of the key.\n *\n * However if the key contains the {...} pattern, only the part between\n * { and } is hashed. This may be useful in the future to force certain\n * keys to be in the same node (assuming no resharding is in progress). */\nunsigned int keyHashSlot(char *key, int keylen) {\n    int s, e; /* start-end indexes of { and } */\n\n    for (s = 0; s < keylen; s++)\n        if (key[s] == '{') break;\n\n    /* No '{' ? Hash the whole key. This is the base case. */\n    if (s == keylen) return crc16(key,keylen) & 0x3FFF;\n\n    /* '{' found? Check if we have the corresponding '}'. */\n    for (e = s+1; e < keylen; e++)\n        if (key[e] == '}') break;\n\n    /* No '}' or nothing betweeen {} ? Hash the whole key. */\n    if (e == keylen || e == s+1) return crc16(key,keylen) & 0x3FFF;\n\n    /* If we are here there is both a { and a } on its right. Hash\n     * what is in the middle between { and }. */\n    return crc16(key+s+1,e-s-1) & 0x3FFF;\n}\n\n/* -----------------------------------------------------------------------------\n * CLUSTER node API\n * -------------------------------------------------------------------------- */\n\n/* Create a new cluster node, with the specified flags.\n * If \"nodename\" is NULL this is considered a first handshake and a random\n * node name is assigned to this node (it will be fixed later when we'll\n * receive the first pong).\n *\n * The node is created and returned to the user, but it is not automatically\n * added to the nodes hash table. */\nclusterNode *createClusterNode(char *nodename, int flags) {\n    clusterNode *node = zmalloc(sizeof(*node));\n\n    if (nodename)\n        memcpy(node->name, nodename, CLUSTER_NAMELEN);\n    else\n        getRandomHexChars(node->name, CLUSTER_NAMELEN);\n    node->ctime = mstime();\n    node->configEpoch = 0;\n    node->flags = flags;\n    memset(node->slots,0,sizeof(node->slots));\n    node->numslots = 0;\n    node->numslaves = 0;\n    node->slaves = NULL;\n    node->slaveof = NULL;\n    node->ping_sent = node->pong_received = 0;\n    node->fail_time = 0;\n    node->link = NULL;\n    memset(node->ip,0,sizeof(node->ip));\n    node->port = 0;\n    node->fail_reports = listCreate();\n    node->voted_time = 0;\n    node->orphaned_time = 0;\n    node->repl_offset_time = 0;\n    node->repl_offset = 0;\n    listSetFreeMethod(node->fail_reports,zfree);\n    return node;\n}\n\n/* This function is called every time we get a failure report from a node.\n * The side effect is to populate the fail_reports list (or to update\n * the timestamp of an existing report).\n *\n * 'failing' is the node that is in failure state according to the\n * 'sender' node.\n *\n * The function returns 0 if it just updates a timestamp of an existing\n * failure report from the same sender. 1 is returned if a new failure\n * report is created. */\nint clusterNodeAddFailureReport(clusterNode *failing, clusterNode *sender) {\n    list *l = failing->fail_reports;\n    listNode *ln;\n    listIter li;\n    clusterNodeFailReport *fr;\n\n    /* If a failure report from the same sender already exists, just update\n     * the timestamp. */\n    listRewind(l,&li);\n    while ((ln = listNext(&li)) != NULL) {\n        fr = ln->value;\n        if (fr->node == sender) {\n            fr->time = mstime();\n            return 0;\n        }\n    }\n\n    /* Otherwise create a new report. */\n    fr = zmalloc(sizeof(*fr));\n    fr->node = sender;\n    fr->time = mstime();\n    listAddNodeTail(l,fr);\n    return 1;\n}\n\n/* Remove failure reports that are too old, where too old means reasonably\n * older than the global node timeout. Note that anyway for a node to be\n * flagged as FAIL we need to have a local PFAIL state that is at least\n * older than the global node timeout, so we don't just trust the number\n * of failure reports from other nodes. */\nvoid clusterNodeCleanupFailureReports(clusterNode *node) {\n    list *l = node->fail_reports;\n    listNode *ln;\n    listIter li;\n    clusterNodeFailReport *fr;\n    mstime_t maxtime = server.cluster_node_timeout *\n                     CLUSTER_FAIL_REPORT_VALIDITY_MULT;\n    mstime_t now = mstime();\n\n    listRewind(l,&li);\n    while ((ln = listNext(&li)) != NULL) {\n        fr = ln->value;\n        if (now - fr->time > maxtime) listDelNode(l,ln);\n    }\n}\n\n/* Remove the failing report for 'node' if it was previously considered\n * failing by 'sender'. This function is called when a node informs us via\n * gossip that a node is OK from its point of view (no FAIL or PFAIL flags).\n *\n * Note that this function is called relatively often as it gets called even\n * when there are no nodes failing, and is O(N), however when the cluster is\n * fine the failure reports list is empty so the function runs in constant\n * time.\n *\n * The function returns 1 if the failure report was found and removed.\n * Otherwise 0 is returned. */\nint clusterNodeDelFailureReport(clusterNode *node, clusterNode *sender) {\n    list *l = node->fail_reports;\n    listNode *ln;\n    listIter li;\n    clusterNodeFailReport *fr;\n\n    /* Search for a failure report from this sender. */\n    listRewind(l,&li);\n    while ((ln = listNext(&li)) != NULL) {\n        fr = ln->value;\n        if (fr->node == sender) break;\n    }\n    if (!ln) return 0; /* No failure report from this sender. */\n\n    /* Remove the failure report. */\n    listDelNode(l,ln);\n    clusterNodeCleanupFailureReports(node);\n    return 1;\n}\n\n/* Return the number of external nodes that believe 'node' is failing,\n * not including this node, that may have a PFAIL or FAIL state for this\n * node as well. */\nint clusterNodeFailureReportsCount(clusterNode *node) {\n    clusterNodeCleanupFailureReports(node);\n    return listLength(node->fail_reports);\n}\n\nint clusterNodeRemoveSlave(clusterNode *master, clusterNode *slave) {\n    int j;\n\n    for (j = 0; j < master->numslaves; j++) {\n        if (master->slaves[j] == slave) {\n            if ((j+1) < master->numslaves) {\n                int remaining_slaves = (master->numslaves - j) - 1;\n                memmove(master->slaves+j,master->slaves+(j+1),\n                        (sizeof(*master->slaves) * remaining_slaves));\n            }\n            master->numslaves--;\n            if (master->numslaves == 0)\n                master->flags &= ~CLUSTER_NODE_MIGRATE_TO;\n            return C_OK;\n        }\n    }\n    return C_ERR;\n}\n\nint clusterNodeAddSlave(clusterNode *master, clusterNode *slave) {\n    int j;\n\n    /* If it's already a slave, don't add it again. */\n    for (j = 0; j < master->numslaves; j++)\n        if (master->slaves[j] == slave) return C_ERR;\n    master->slaves = zrealloc(master->slaves,\n        sizeof(clusterNode*)*(master->numslaves+1));\n    master->slaves[master->numslaves] = slave;\n    master->numslaves++;\n    master->flags |= CLUSTER_NODE_MIGRATE_TO;\n    return C_OK;\n}\n\nint clusterCountNonFailingSlaves(clusterNode *n) {\n    int j, okslaves = 0;\n\n    for (j = 0; j < n->numslaves; j++)\n        if (!nodeFailed(n->slaves[j])) okslaves++;\n    return okslaves;\n}\n\n/* Low level cleanup of the node structure. Only called by clusterDelNode(). */\nvoid freeClusterNode(clusterNode *n) {\n    sds nodename;\n    int j;\n\n    /* If the node has associated slaves, we have to set\n     * all the slaves->slaveof fields to NULL (unknown). */\n    for (j = 0; j < n->numslaves; j++)\n        n->slaves[j]->slaveof = NULL;\n\n    /* Remove this node from the list of slaves of its master. */\n    if (nodeIsSlave(n) && n->slaveof) clusterNodeRemoveSlave(n->slaveof,n);\n\n    /* Unlink from the set of nodes. */\n    nodename = sdsnewlen(n->name, CLUSTER_NAMELEN);\n    serverAssert(dictDelete(server.cluster->nodes,nodename) == DICT_OK);\n    sdsfree(nodename);\n\n    /* Release link and associated data structures. */\n    if (n->link) freeClusterLink(n->link);\n    listRelease(n->fail_reports);\n    zfree(n->slaves);\n    zfree(n);\n}\n\n/* Add a node to the nodes hash table */\nint clusterAddNode(clusterNode *node) {\n    int retval;\n\n    retval = dictAdd(server.cluster->nodes,\n            sdsnewlen(node->name,CLUSTER_NAMELEN), node);\n    return (retval == DICT_OK) ? C_OK : C_ERR;\n}\n\n/* Remove a node from the cluster. The functio performs the high level\n * cleanup, calling freeClusterNode() for the low level cleanup.\n * Here we do the following:\n *\n * 1) Mark all the slots handled by it as unassigned.\n * 2) Remove all the failure reports sent by this node and referenced by\n *    other nodes.\n * 3) Free the node with freeClusterNode() that will in turn remove it\n *    from the hash table and from the list of slaves of its master, if\n *    it is a slave node.\n */\nvoid clusterDelNode(clusterNode *delnode) {\n    int j;\n    dictIterator *di;\n    dictEntry *de;\n\n    /* 1) Mark slots as unassigned. */\n    for (j = 0; j < CLUSTER_SLOTS; j++) {\n        if (server.cluster->importing_slots_from[j] == delnode)\n            server.cluster->importing_slots_from[j] = NULL;\n        if (server.cluster->migrating_slots_to[j] == delnode)\n            server.cluster->migrating_slots_to[j] = NULL;\n        if (server.cluster->slots[j] == delnode)\n            clusterDelSlot(j);\n    }\n\n    /* 2) Remove failure reports. */\n    di = dictGetSafeIterator(server.cluster->nodes);\n    while((de = dictNext(di)) != NULL) {\n        clusterNode *node = dictGetVal(de);\n\n        if (node == delnode) continue;\n        clusterNodeDelFailureReport(node,delnode);\n    }\n    dictReleaseIterator(di);\n\n    /* 3) Free the node, unlinking it from the cluster. */\n    freeClusterNode(delnode);\n}\n\n/* Node lookup by name */\nclusterNode *clusterLookupNode(char *name) {\n    sds s = sdsnewlen(name, CLUSTER_NAMELEN);\n    dictEntry *de;\n\n    de = dictFind(server.cluster->nodes,s);\n    sdsfree(s);\n    if (de == NULL) return NULL;\n    return dictGetVal(de);\n}\n\n/* This is only used after the handshake. When we connect a given IP/PORT\n * as a result of CLUSTER MEET we don't have the node name yet, so we\n * pick a random one, and will fix it when we receive the PONG request using\n * this function. */\nvoid clusterRenameNode(clusterNode *node, char *newname) {\n    int retval;\n    sds s = sdsnewlen(node->name, CLUSTER_NAMELEN);\n\n    serverLog(LL_DEBUG,\"Renaming node %.40s into %.40s\",\n        node->name, newname);\n    retval = dictDelete(server.cluster->nodes, s);\n    sdsfree(s);\n    serverAssert(retval == DICT_OK);\n    memcpy(node->name, newname, CLUSTER_NAMELEN);\n    clusterAddNode(node);\n}\n\n/* -----------------------------------------------------------------------------\n * CLUSTER config epoch handling\n * -------------------------------------------------------------------------- */\n\n/* Return the greatest configEpoch found in the cluster, or the current\n * epoch if greater than any node configEpoch. */\nuint64_t clusterGetMaxEpoch(void) {\n    uint64_t max = 0;\n    dictIterator *di;\n    dictEntry *de;\n\n    di = dictGetSafeIterator(server.cluster->nodes);\n    while((de = dictNext(di)) != NULL) {\n        clusterNode *node = dictGetVal(de);\n        if (node->configEpoch > max) max = node->configEpoch;\n    }\n    dictReleaseIterator(di);\n    if (max < server.cluster->currentEpoch) max = server.cluster->currentEpoch;\n    return max;\n}\n\n/* If this node epoch is zero or is not already the greatest across the\n * cluster (from the POV of the local configuration), this function will:\n *\n * 1) Generate a new config epoch, incrementing the current epoch.\n * 2) Assign the new epoch to this node, WITHOUT any consensus.\n * 3) Persist the configuration on disk before sending packets with the\n *    new configuration.\n *\n * If the new config epoch is generated and assigend, C_OK is returned,\n * otherwise C_ERR is returned (since the node has already the greatest\n * configuration around) and no operation is performed.\n *\n * Important note: this function violates the principle that config epochs\n * should be generated with consensus and should be unique across the cluster.\n * However Redis Cluster uses this auto-generated new config epochs in two\n * cases:\n *\n * 1) When slots are closed after importing. Otherwise resharding would be\n *    too expensive.\n * 2) When CLUSTER FAILOVER is called with options that force a slave to\n *    failover its master even if there is not master majority able to\n *    create a new configuration epoch.\n *\n * Redis Cluster will not explode using this function, even in the case of\n * a collision between this node and another node, generating the same\n * configuration epoch unilaterally, because the config epoch conflict\n * resolution algorithm will eventually move colliding nodes to different\n * config epochs. However using this function may violate the \"last failover\n * wins\" rule, so should only be used with care. */\nint clusterBumpConfigEpochWithoutConsensus(void) {\n    uint64_t maxEpoch = clusterGetMaxEpoch();\n\n    if (myself->configEpoch == 0 ||\n        myself->configEpoch != maxEpoch)\n    {\n        server.cluster->currentEpoch++;\n        myself->configEpoch = server.cluster->currentEpoch;\n        clusterDoBeforeSleep(CLUSTER_TODO_SAVE_CONFIG|\n                             CLUSTER_TODO_FSYNC_CONFIG);\n        serverLog(LL_WARNING,\n            \"New configEpoch set to %llu\",\n            (unsigned long long) myself->configEpoch);\n        return C_OK;\n    } else {\n        return C_ERR;\n    }\n}\n\n/* This function is called when this node is a master, and we receive from\n * another master a configuration epoch that is equal to our configuration\n * epoch.\n *\n * BACKGROUND\n *\n * It is not possible that different slaves get the same config\n * epoch during a failover election, because the slaves need to get voted\n * by a majority. However when we perform a manual resharding of the cluster\n * the node will assign a configuration epoch to itself without to ask\n * for agreement. Usually resharding happens when the cluster is working well\n * and is supervised by the sysadmin, however it is possible for a failover\n * to happen exactly while the node we are resharding a slot to assigns itself\n * a new configuration epoch, but before it is able to propagate it.\n *\n * So technically it is possible in this condition that two nodes end with\n * the same configuration epoch.\n *\n * Another possibility is that there are bugs in the implementation causing\n * this to happen.\n *\n * Moreover when a new cluster is created, all the nodes start with the same\n * configEpoch. This collision resolution code allows nodes to automatically\n * end with a different configEpoch at startup automatically.\n *\n * In all the cases, we want a mechanism that resolves this issue automatically\n * as a safeguard. The same configuration epoch for masters serving different\n * set of slots is not harmful, but it is if the nodes end serving the same\n * slots for some reason (manual errors or software bugs) without a proper\n * failover procedure.\n *\n * In general we want a system that eventually always ends with different\n * masters having different configuration epochs whatever happened, since\n * nothign is worse than a split-brain condition in a distributed system.\n *\n * BEHAVIOR\n *\n * When this function gets called, what happens is that if this node\n * has the lexicographically smaller Node ID compared to the other node\n * with the conflicting epoch (the 'sender' node), it will assign itself\n * the greatest configuration epoch currently detected among nodes plus 1.\n *\n * This means that even if there are multiple nodes colliding, the node\n * with the greatest Node ID never moves forward, so eventually all the nodes\n * end with a different configuration epoch.\n */\nvoid clusterHandleConfigEpochCollision(clusterNode *sender) {\n    /* Prerequisites: nodes have the same configEpoch and are both masters. */\n    if (sender->configEpoch != myself->configEpoch ||\n        !nodeIsMaster(sender) || !nodeIsMaster(myself)) return;\n    /* Don't act if the colliding node has a smaller Node ID. */\n    if (memcmp(sender->name,myself->name,CLUSTER_NAMELEN) <= 0) return;\n    /* Get the next ID available at the best of this node knowledge. */\n    server.cluster->currentEpoch++;\n    myself->configEpoch = server.cluster->currentEpoch;\n    clusterSaveConfigOrDie(1);\n    serverLog(LL_VERBOSE,\n        \"WARNING: configEpoch collision with node %.40s.\"\n        \" configEpoch set to %llu\",\n        sender->name,\n        (unsigned long long) myself->configEpoch);\n}\n\n/* -----------------------------------------------------------------------------\n * CLUSTER nodes blacklist\n *\n * The nodes blacklist is just a way to ensure that a given node with a given\n * Node ID is not readded before some time elapsed (this time is specified\n * in seconds in CLUSTER_BLACKLIST_TTL).\n *\n * This is useful when we want to remove a node from the cluster completely:\n * when CLUSTER FORGET is called, it also puts the node into the blacklist so\n * that even if we receive gossip messages from other nodes that still remember\n * about the node we want to remove, we don't re-add it before some time.\n *\n * Currently the CLUSTER_BLACKLIST_TTL is set to 1 minute, this means\n * that redis-trib has 60 seconds to send CLUSTER FORGET messages to nodes\n * in the cluster without dealing with the problem of other nodes re-adding\n * back the node to nodes we already sent the FORGET command to.\n *\n * The data structure used is a hash table with an sds string representing\n * the node ID as key, and the time when it is ok to re-add the node as\n * value.\n * -------------------------------------------------------------------------- */\n\n#define CLUSTER_BLACKLIST_TTL 60      /* 1 minute. */\n\n\n/* Before of the addNode() or Exists() operations we always remove expired\n * entries from the black list. This is an O(N) operation but it is not a\n * problem since add / exists operations are called very infrequently and\n * the hash table is supposed to contain very little elements at max.\n * However without the cleanup during long uptimes and with some automated\n * node add/removal procedures, entries could accumulate. */\nvoid clusterBlacklistCleanup(void) {\n    dictIterator *di;\n    dictEntry *de;\n\n    di = dictGetSafeIterator(server.cluster->nodes_black_list);\n    while((de = dictNext(di)) != NULL) {\n        int64_t expire = dictGetUnsignedIntegerVal(de);\n\n        if (expire < server.unixtime)\n            dictDelete(server.cluster->nodes_black_list,dictGetKey(de));\n    }\n    dictReleaseIterator(di);\n}\n\n/* Cleanup the blacklist and add a new node ID to the black list. */\nvoid clusterBlacklistAddNode(clusterNode *node) {\n    dictEntry *de;\n    sds id = sdsnewlen(node->name,CLUSTER_NAMELEN);\n\n    clusterBlacklistCleanup();\n    if (dictAdd(server.cluster->nodes_black_list,id,NULL) == DICT_OK) {\n        /* If the key was added, duplicate the sds string representation of\n         * the key for the next lookup. We'll free it at the end. */\n        id = sdsdup(id);\n    }\n    de = dictFind(server.cluster->nodes_black_list,id);\n    dictSetUnsignedIntegerVal(de,time(NULL)+CLUSTER_BLACKLIST_TTL);\n    sdsfree(id);\n}\n\n/* Return non-zero if the specified node ID exists in the blacklist.\n * You don't need to pass an sds string here, any pointer to 40 bytes\n * will work. */\nint clusterBlacklistExists(char *nodeid) {\n    sds id = sdsnewlen(nodeid,CLUSTER_NAMELEN);\n    int retval;\n\n    clusterBlacklistCleanup();\n    retval = dictFind(server.cluster->nodes_black_list,id) != NULL;\n    sdsfree(id);\n    return retval;\n}\n\n/* -----------------------------------------------------------------------------\n * CLUSTER messages exchange - PING/PONG and gossip\n * -------------------------------------------------------------------------- */\n\n/* This function checks if a given node should be marked as FAIL.\n * It happens if the following conditions are met:\n *\n * 1) We received enough failure reports from other master nodes via gossip.\n *    Enough means that the majority of the masters signaled the node is\n *    down recently.\n * 2) We believe this node is in PFAIL state.\n *\n * If a failure is detected we also inform the whole cluster about this\n * event trying to force every other node to set the FAIL flag for the node.\n *\n * Note that the form of agreement used here is weak, as we collect the majority\n * of masters state during some time, and even if we force agreement by\n * propagating the FAIL message, because of partitions we may not reach every\n * node. However:\n *\n * 1) Either we reach the majority and eventually the FAIL state will propagate\n *    to all the cluster.\n * 2) Or there is no majority so no slave promotion will be authorized and the\n *    FAIL flag will be cleared after some time.\n */\nvoid markNodeAsFailingIfNeeded(clusterNode *node) {\n    int failures;\n    int needed_quorum = (server.cluster->size / 2) + 1;\n\n    if (!nodeTimedOut(node)) return; /* We can reach it. */\n    if (nodeFailed(node)) return; /* Already FAILing. */\n\n    failures = clusterNodeFailureReportsCount(node);\n    /* Also count myself as a voter if I'm a master. */\n    if (nodeIsMaster(myself)) failures++;\n    if (failures < needed_quorum) return; /* No weak agreement from masters. */\n\n    serverLog(LL_NOTICE,\n        \"Marking node %.40s as failing (quorum reached).\", node->name);\n\n    /* Mark the node as failing. */\n    node->flags &= ~CLUSTER_NODE_PFAIL;\n    node->flags |= CLUSTER_NODE_FAIL;\n    node->fail_time = mstime();\n\n    /* Broadcast the failing node name to everybody, forcing all the other\n     * reachable nodes to flag the node as FAIL. */\n    if (nodeIsMaster(myself)) clusterSendFail(node->name);\n    clusterDoBeforeSleep(CLUSTER_TODO_UPDATE_STATE|CLUSTER_TODO_SAVE_CONFIG);\n}\n\n/* This function is called only if a node is marked as FAIL, but we are able\n * to reach it again. It checks if there are the conditions to undo the FAIL\n * state. */\nvoid clearNodeFailureIfNeeded(clusterNode *node) {\n    mstime_t now = mstime();\n\n    serverAssert(nodeFailed(node));\n\n    /* For slaves we always clear the FAIL flag if we can contact the\n     * node again. */\n    if (nodeIsSlave(node) || node->numslots == 0) {\n        serverLog(LL_NOTICE,\n            \"Clear FAIL state for node %.40s: %s is reachable again.\",\n                node->name,\n                nodeIsSlave(node) ? \"slave\" : \"master without slots\");\n        node->flags &= ~CLUSTER_NODE_FAIL;\n        clusterDoBeforeSleep(CLUSTER_TODO_UPDATE_STATE|CLUSTER_TODO_SAVE_CONFIG);\n    }\n\n    /* If it is a master and...\n     * 1) The FAIL state is old enough.\n     * 2) It is yet serving slots from our point of view (not failed over).\n     * Apparently no one is going to fix these slots, clear the FAIL flag. */\n    if (nodeIsMaster(node) && node->numslots > 0 &&\n        (now - node->fail_time) >\n        (server.cluster_node_timeout * CLUSTER_FAIL_UNDO_TIME_MULT))\n    {\n        serverLog(LL_NOTICE,\n            \"Clear FAIL state for node %.40s: is reachable again and nobody is serving its slots after some time.\",\n                node->name);\n        node->flags &= ~CLUSTER_NODE_FAIL;\n        clusterDoBeforeSleep(CLUSTER_TODO_UPDATE_STATE|CLUSTER_TODO_SAVE_CONFIG);\n    }\n}\n\n/* Return true if we already have a node in HANDSHAKE state matching the\n * specified ip address and port number. This function is used in order to\n * avoid adding a new handshake node for the same address multiple times. */\nint clusterHandshakeInProgress(char *ip, int port) {\n    dictIterator *di;\n    dictEntry *de;\n\n    di = dictGetSafeIterator(server.cluster->nodes);\n    while((de = dictNext(di)) != NULL) {\n        clusterNode *node = dictGetVal(de);\n\n        if (!nodeInHandshake(node)) continue;\n        if (!strcasecmp(node->ip,ip) && node->port == port) break;\n    }\n    dictReleaseIterator(di);\n    return de != NULL;\n}\n\n/* Start an handshake with the specified address if there is not one\n * already in progress. Returns non-zero if the handshake was actually\n * started. On error zero is returned and errno is set to one of the\n * following values:\n *\n * EAGAIN - There is already an handshake in progress for this address.\n * EINVAL - IP or port are not valid. */\nint clusterStartHandshake(char *ip, int port) {\n    clusterNode *n;\n    char norm_ip[NET_IP_STR_LEN];\n    struct sockaddr_storage sa;\n\n    /* IP sanity check */\n    if (inet_pton(AF_INET,ip,\n            &(((struct sockaddr_in *)&sa)->sin_addr)))\n    {\n        sa.ss_family = AF_INET;\n    } else if (inet_pton(AF_INET6,ip,\n            &(((struct sockaddr_in6 *)&sa)->sin6_addr)))\n    {\n        sa.ss_family = AF_INET6;\n    } else {\n        errno = EINVAL;\n        return 0;\n    }\n\n    /* Port sanity check */\n    if (port <= 0 || port > (65535-CLUSTER_PORT_INCR)) {\n        errno = EINVAL;\n        return 0;\n    }\n\n    /* Set norm_ip as the normalized string representation of the node\n     * IP address. */\n    memset(norm_ip,0,NET_IP_STR_LEN);\n    if (sa.ss_family == AF_INET)\n        inet_ntop(AF_INET,\n            (void*)&(((struct sockaddr_in *)&sa)->sin_addr),\n            norm_ip,NET_IP_STR_LEN);\n    else\n        inet_ntop(AF_INET6,\n            (void*)&(((struct sockaddr_in6 *)&sa)->sin6_addr),\n            norm_ip,NET_IP_STR_LEN);\n\n    if (clusterHandshakeInProgress(norm_ip,port)) {\n        errno = EAGAIN;\n        return 0;\n    }\n\n    /* Add the node with a random address (NULL as first argument to\n     * createClusterNode()). Everything will be fixed during the\n     * handshake. */\n    n = createClusterNode(NULL,CLUSTER_NODE_HANDSHAKE|CLUSTER_NODE_MEET);\n    memcpy(n->ip,norm_ip,sizeof(n->ip));\n    n->port = port;\n    clusterAddNode(n);\n    return 1;\n}\n\n/* Process the gossip section of PING or PONG packets.\n * Note that this function assumes that the packet is already sanity-checked\n * by the caller, not in the content of the gossip section, but in the\n * length. */\nvoid clusterProcessGossipSection(clusterMsg *hdr, clusterLink *link) {\n    uint16_t count = ntohs(hdr->count);\n    clusterMsgDataGossip *g = (clusterMsgDataGossip*) hdr->data.ping.gossip;\n    clusterNode *sender = link->node ? link->node : clusterLookupNode(hdr->sender);\n\n    while(count--) {\n        uint16_t flags = ntohs(g->flags);\n        clusterNode *node;\n        sds ci;\n\n        ci = representClusterNodeFlags(sdsempty(), flags);\n        serverLog(LL_DEBUG,\"GOSSIP %.40s %s:%d %s\",\n            g->nodename,\n            g->ip,\n            ntohs(g->port),\n            ci);\n        sdsfree(ci);\n\n        /* Update our state accordingly to the gossip sections */\n        node = clusterLookupNode(g->nodename);\n        if (node) {\n            /* We already know this node.\n               Handle failure reports, only when the sender is a master. */\n            if (sender && nodeIsMaster(sender) && node != myself) {\n                if (flags & (CLUSTER_NODE_FAIL|CLUSTER_NODE_PFAIL)) {\n                    if (clusterNodeAddFailureReport(node,sender)) {\n                        serverLog(LL_VERBOSE,\n                            \"Node %.40s reported node %.40s as not reachable.\",\n                            sender->name, node->name);\n                    }\n                    markNodeAsFailingIfNeeded(node);\n                } else {\n                    if (clusterNodeDelFailureReport(node,sender)) {\n                        serverLog(LL_VERBOSE,\n                            \"Node %.40s reported node %.40s is back online.\",\n                            sender->name, node->name);\n                    }\n                }\n            }\n\n            /* If we already know this node, but it is not reachable, and\n             * we see a different address in the gossip section of a node that\n             * can talk with this other node, update the address, disconnect\n             * the old link if any, so that we'll attempt to connect with the\n             * new address. */\n            if (node->flags & (CLUSTER_NODE_FAIL|CLUSTER_NODE_PFAIL) &&\n                !(flags & CLUSTER_NODE_NOADDR) &&\n                !(flags & (CLUSTER_NODE_FAIL|CLUSTER_NODE_PFAIL)) &&\n                (strcasecmp(node->ip,g->ip) || node->port != ntohs(g->port)))\n            {\n                if (node->link) freeClusterLink(node->link);\n                memcpy(node->ip,g->ip,NET_IP_STR_LEN);\n                node->port = ntohs(g->port);\n                node->flags &= ~CLUSTER_NODE_NOADDR;\n            }\n        } else {\n            /* If it's not in NOADDR state and we don't have it, we\n             * start a handshake process against this IP/PORT pairs.\n             *\n             * Note that we require that the sender of this gossip message\n             * is a well known node in our cluster, otherwise we risk\n             * joining another cluster. */\n            if (sender &&\n                !(flags & CLUSTER_NODE_NOADDR) &&\n                !clusterBlacklistExists(g->nodename))\n            {\n                clusterStartHandshake(g->ip,ntohs(g->port));\n            }\n        }\n\n        /* Next node */\n        g++;\n    }\n}\n\n/* IP -> string conversion. 'buf' is supposed to at least be 46 bytes. */\nvoid nodeIp2String(char *buf, clusterLink *link) {\n    anetPeerToString(link->fd, buf, NET_IP_STR_LEN, NULL);\n}\n\n/* Update the node address to the IP address that can be extracted\n * from link->fd, and at the specified port.\n * Also disconnect the node link so that we'll connect again to the new\n * address.\n *\n * If the ip/port pair are already correct no operation is performed at\n * all.\n *\n * The function returns 0 if the node address is still the same,\n * otherwise 1 is returned. */\nint nodeUpdateAddressIfNeeded(clusterNode *node, clusterLink *link, int port) {\n    char ip[NET_IP_STR_LEN] = {0};\n\n    /* We don't proceed if the link is the same as the sender link, as this\n     * function is designed to see if the node link is consistent with the\n     * symmetric link that is used to receive PINGs from the node.\n     *\n     * As a side effect this function never frees the passed 'link', so\n     * it is safe to call during packet processing. */\n    if (link == node->link) return 0;\n\n    nodeIp2String(ip,link);\n    if (node->port == port && strcmp(ip,node->ip) == 0) return 0;\n\n    /* IP / port is different, update it. */\n    memcpy(node->ip,ip,sizeof(ip));\n    node->port = port;\n    if (node->link) freeClusterLink(node->link);\n    node->flags &= ~CLUSTER_NODE_NOADDR;\n    serverLog(LL_WARNING,\"Address updated for node %.40s, now %s:%d\",\n        node->name, node->ip, node->port);\n\n    /* Check if this is our master and we have to change the\n     * replication target as well. */\n    if (nodeIsSlave(myself) && myself->slaveof == node)\n        replicationSetMaster(node->ip, node->port);\n    return 1;\n}\n\n/* Reconfigure the specified node 'n' as a master. This function is called when\n * a node that we believed to be a slave is now acting as master in order to\n * update the state of the node. */\nvoid clusterSetNodeAsMaster(clusterNode *n) {\n    if (nodeIsMaster(n)) return;\n\n    if (n->slaveof) {\n        clusterNodeRemoveSlave(n->slaveof,n);\n        if (n != myself) n->flags |= CLUSTER_NODE_MIGRATE_TO;\n    }\n    n->flags &= ~CLUSTER_NODE_SLAVE;\n    n->flags |= CLUSTER_NODE_MASTER;\n    n->slaveof = NULL;\n\n    /* Update config and state. */\n    clusterDoBeforeSleep(CLUSTER_TODO_SAVE_CONFIG|\n                         CLUSTER_TODO_UPDATE_STATE);\n}\n\n/* This function is called when we receive a master configuration via a\n * PING, PONG or UPDATE packet. What we receive is a node, a configEpoch of the\n * node, and the set of slots claimed under this configEpoch.\n *\n * What we do is to rebind the slots with newer configuration compared to our\n * local configuration, and if needed, we turn ourself into a replica of the\n * node (see the function comments for more info).\n *\n * The 'sender' is the node for which we received a configuration update.\n * Sometimes it is not actually the \"Sender\" of the information, like in the\n * case we receive the info via an UPDATE packet. */\nvoid clusterUpdateSlotsConfigWith(clusterNode *sender, uint64_t senderConfigEpoch, unsigned char *slots) {\n    int j;\n    clusterNode *curmaster, *newmaster = NULL;\n    /* The dirty slots list is a list of slots for which we lose the ownership\n     * while having still keys inside. This usually happens after a failover\n     * or after a manual cluster reconfiguration operated by the admin.\n     *\n     * If the update message is not able to demote a master to slave (in this\n     * case we'll resync with the master updating the whole key space), we\n     * need to delete all the keys in the slots we lost ownership. */\n    uint16_t dirty_slots[CLUSTER_SLOTS];\n    int dirty_slots_count = 0;\n\n    /* Here we set curmaster to this node or the node this node\n     * replicates to if it's a slave. In the for loop we are\n     * interested to check if slots are taken away from curmaster. */\n    curmaster = nodeIsMaster(myself) ? myself : myself->slaveof;\n\n    if (sender == myself) {\n        serverLog(LL_WARNING,\"Discarding UPDATE message about myself.\");\n        return;\n    }\n\n    for (j = 0; j < CLUSTER_SLOTS; j++) {\n        if (bitmapTestBit(slots,j)) {\n            /* The slot is already bound to the sender of this message. */\n            if (server.cluster->slots[j] == sender) continue;\n\n            /* The slot is in importing state, it should be modified only\n             * manually via redis-trib (example: a resharding is in progress\n             * and the migrating side slot was already closed and is advertising\n             * a new config. We still want the slot to be closed manually). */\n            if (server.cluster->importing_slots_from[j]) continue;\n\n            /* We rebind the slot to the new node claiming it if:\n             * 1) The slot was unassigned or the new node claims it with a\n             *    greater configEpoch.\n             * 2) We are not currently importing the slot. */\n            if (server.cluster->slots[j] == NULL ||\n                server.cluster->slots[j]->configEpoch < senderConfigEpoch)\n            {\n                /* Was this slot mine, and still contains keys? Mark it as\n                 * a dirty slot. */\n                if (server.cluster->slots[j] == myself &&\n                    countKeysInSlot(j) &&\n                    sender != myself)\n                {\n                    dirty_slots[dirty_slots_count] = j;\n                    dirty_slots_count++;\n                }\n\n                if (server.cluster->slots[j] == curmaster)\n                    newmaster = sender;\n                clusterDelSlot(j);\n                clusterAddSlot(sender,j);\n                clusterDoBeforeSleep(CLUSTER_TODO_SAVE_CONFIG|\n                                     CLUSTER_TODO_UPDATE_STATE|\n                                     CLUSTER_TODO_FSYNC_CONFIG);\n            }\n        }\n    }\n\n    /* If at least one slot was reassigned from a node to another node\n     * with a greater configEpoch, it is possible that:\n     * 1) We are a master left without slots. This means that we were\n     *    failed over and we should turn into a replica of the new\n     *    master.\n     * 2) We are a slave and our master is left without slots. We need\n     *    to replicate to the new slots owner. */\n    if (newmaster && curmaster->numslots == 0) {\n        serverLog(LL_WARNING,\n            \"Configuration change detected. Reconfiguring myself \"\n            \"as a replica of %.40s\", sender->name);\n        clusterSetMaster(sender);\n        clusterDoBeforeSleep(CLUSTER_TODO_SAVE_CONFIG|\n                             CLUSTER_TODO_UPDATE_STATE|\n                             CLUSTER_TODO_FSYNC_CONFIG);\n    } else if (dirty_slots_count) {\n        /* If we are here, we received an update message which removed\n         * ownership for certain slots we still have keys about, but still\n         * we are serving some slots, so this master node was not demoted to\n         * a slave.\n         *\n         * In order to maintain a consistent state between keys and slots\n         * we need to remove all the keys from the slots we lost. */\n        for (j = 0; j < dirty_slots_count; j++)\n            delKeysInSlot(dirty_slots[j]);\n    }\n}\n\n/* When this function is called, there is a packet to process starting\n * at node->rcvbuf. Releasing the buffer is up to the caller, so this\n * function should just handle the higher level stuff of processing the\n * packet, modifying the cluster state if needed.\n *\n * The function returns 1 if the link is still valid after the packet\n * was processed, otherwise 0 if the link was freed since the packet\n * processing lead to some inconsistency error (for instance a PONG\n * received from the wrong sender ID). */\nint clusterProcessPacket(clusterLink *link) {\n    clusterMsg *hdr = (clusterMsg*) link->rcvbuf;\n    uint32_t totlen = ntohl(hdr->totlen);\n    uint16_t type = ntohs(hdr->type);\n\n    server.cluster->stats_bus_messages_received++;\n    serverLog(LL_DEBUG,\"--- Processing packet of type %d, %lu bytes\",\n        type, (unsigned long) totlen);\n\n    /* Perform sanity checks */\n    if (totlen < 16) return 1; /* At least signature, version, totlen, count. */\n    if (totlen > sdslen(link->rcvbuf)) return 1;\n\n    if (ntohs(hdr->ver) != CLUSTER_PROTO_VER) {\n        /* Can't handle messages of different versions. */\n        return 1;\n    }\n\n    uint16_t flags = ntohs(hdr->flags);\n    uint64_t senderCurrentEpoch = 0, senderConfigEpoch = 0;\n    clusterNode *sender;\n\n    if (type == CLUSTERMSG_TYPE_PING || type == CLUSTERMSG_TYPE_PONG ||\n        type == CLUSTERMSG_TYPE_MEET)\n    {\n        uint16_t count = ntohs(hdr->count);\n        uint32_t explen; /* expected length of this packet */\n\n        explen = sizeof(clusterMsg)-sizeof(union clusterMsgData);\n        explen += (sizeof(clusterMsgDataGossip)*count);\n        if (totlen != explen) return 1;\n    } else if (type == CLUSTERMSG_TYPE_FAIL) {\n        uint32_t explen = sizeof(clusterMsg)-sizeof(union clusterMsgData);\n\n        explen += sizeof(clusterMsgDataFail);\n        if (totlen != explen) return 1;\n    } else if (type == CLUSTERMSG_TYPE_PUBLISH) {\n        uint32_t explen = sizeof(clusterMsg)-sizeof(union clusterMsgData);\n\n        explen += sizeof(clusterMsgDataPublish) -\n                8 +\n                ntohl(hdr->data.publish.msg.channel_len) +\n                ntohl(hdr->data.publish.msg.message_len);\n        if (totlen != explen) return 1;\n    } else if (type == CLUSTERMSG_TYPE_FAILOVER_AUTH_REQUEST ||\n               type == CLUSTERMSG_TYPE_FAILOVER_AUTH_ACK ||\n               type == CLUSTERMSG_TYPE_MFSTART)\n    {\n        uint32_t explen = sizeof(clusterMsg)-sizeof(union clusterMsgData);\n\n        if (totlen != explen) return 1;\n    } else if (type == CLUSTERMSG_TYPE_UPDATE) {\n        uint32_t explen = sizeof(clusterMsg)-sizeof(union clusterMsgData);\n\n        explen += sizeof(clusterMsgDataUpdate);\n        if (totlen != explen) return 1;\n    }\n\n    /* Check if the sender is a known node. */\n    sender = clusterLookupNode(hdr->sender);\n    if (sender && !nodeInHandshake(sender)) {\n        /* Update our curretEpoch if we see a newer epoch in the cluster. */\n        senderCurrentEpoch = ntohu64(hdr->currentEpoch);\n        senderConfigEpoch = ntohu64(hdr->configEpoch);\n        if (senderCurrentEpoch > server.cluster->currentEpoch)\n            server.cluster->currentEpoch = senderCurrentEpoch;\n        /* Update the sender configEpoch if it is publishing a newer one. */\n        if (senderConfigEpoch > sender->configEpoch) {\n            sender->configEpoch = senderConfigEpoch;\n            clusterDoBeforeSleep(CLUSTER_TODO_SAVE_CONFIG|\n                                 CLUSTER_TODO_FSYNC_CONFIG);\n        }\n        /* Update the replication offset info for this node. */\n        sender->repl_offset = ntohu64(hdr->offset);\n        sender->repl_offset_time = mstime();\n        /* If we are a slave performing a manual failover and our master\n         * sent its offset while already paused, populate the MF state. */\n        if (server.cluster->mf_end &&\n            nodeIsSlave(myself) &&\n            myself->slaveof == sender &&\n            hdr->mflags[0] & CLUSTERMSG_FLAG0_PAUSED &&\n            server.cluster->mf_master_offset == 0)\n        {\n            server.cluster->mf_master_offset = sender->repl_offset;\n            serverLog(LL_WARNING,\n                \"Received replication offset for paused \"\n                \"master manual failover: %lld\",\n                server.cluster->mf_master_offset);\n        }\n    }\n\n    /* Initial processing of PING and MEET requests replying with a PONG. */\n    if (type == CLUSTERMSG_TYPE_PING || type == CLUSTERMSG_TYPE_MEET) {\n        serverLog(LL_DEBUG,\"Ping packet received: %p\", (void*)link->node);\n\n        /* We use incoming MEET messages in order to set the address\n         * for 'myself', since only other cluster nodes will send us\n         * MEET messagses on handshakes, when the cluster joins, or\n         * later if we changed address, and those nodes will use our\n         * official address to connect to us. So by obtaining this address\n         * from the socket is a simple way to discover / update our own\n         * address in the cluster without it being hardcoded in the config.\n         *\n         * However if we don't have an address at all, we update the address\n         * even with a normal PING packet. If it's wrong it will be fixed\n         * by MEET later. */\n        if (type == CLUSTERMSG_TYPE_MEET || myself->ip[0] == '\\0') {\n            char ip[NET_IP_STR_LEN];\n\n            if (anetSockName(link->fd,ip,sizeof(ip),NULL) != -1 &&\n                strcmp(ip,myself->ip))\n            {\n                memcpy(myself->ip,ip,NET_IP_STR_LEN);\n                serverLog(LL_WARNING,\"IP address for this node updated to %s\",\n                    myself->ip);\n                clusterDoBeforeSleep(CLUSTER_TODO_SAVE_CONFIG);\n            }\n        }\n\n        /* Add this node if it is new for us and the msg type is MEET.\n         * In this stage we don't try to add the node with the right\n         * flags, slaveof pointer, and so forth, as this details will be\n         * resolved when we'll receive PONGs from the node. */\n        if (!sender && type == CLUSTERMSG_TYPE_MEET) {\n            clusterNode *node;\n\n            node = createClusterNode(NULL,CLUSTER_NODE_HANDSHAKE);\n            nodeIp2String(node->ip,link);\n            node->port = ntohs(hdr->port);\n            clusterAddNode(node);\n            clusterDoBeforeSleep(CLUSTER_TODO_SAVE_CONFIG);\n        }\n\n        /* If this is a MEET packet from an unknown node, we still process\n         * the gossip section here since we have to trust the sender because\n         * of the message type. */\n        if (!sender && type == CLUSTERMSG_TYPE_MEET)\n            clusterProcessGossipSection(hdr,link);\n\n        /* Anyway reply with a PONG */\n        clusterSendPing(link,CLUSTERMSG_TYPE_PONG);\n    }\n\n    /* PING, PONG, MEET: process config information. */\n    if (type == CLUSTERMSG_TYPE_PING || type == CLUSTERMSG_TYPE_PONG ||\n        type == CLUSTERMSG_TYPE_MEET)\n    {\n        serverLog(LL_DEBUG,\"%s packet received: %p\",\n            type == CLUSTERMSG_TYPE_PING ? \"ping\" : \"pong\",\n            (void*)link->node);\n        if (link->node) {\n            if (nodeInHandshake(link->node)) {\n                /* If we already have this node, try to change the\n                 * IP/port of the node with the new one. */\n                if (sender) {\n                    serverLog(LL_VERBOSE,\n                        \"Handshake: we already know node %.40s, \"\n                        \"updating the address if needed.\", sender->name);\n                    if (nodeUpdateAddressIfNeeded(sender,link,ntohs(hdr->port)))\n                    {\n                        clusterDoBeforeSleep(CLUSTER_TODO_SAVE_CONFIG|\n                                             CLUSTER_TODO_UPDATE_STATE);\n                    }\n                    /* Free this node as we already have it. This will\n                     * cause the link to be freed as well. */\n                    clusterDelNode(link->node);\n                    return 0;\n                }\n\n                /* First thing to do is replacing the random name with the\n                 * right node name if this was a handshake stage. */\n                clusterRenameNode(link->node, hdr->sender);\n                serverLog(LL_DEBUG,\"Handshake with node %.40s completed.\",\n                    link->node->name);\n                link->node->flags &= ~CLUSTER_NODE_HANDSHAKE;\n                link->node->flags |= flags&(CLUSTER_NODE_MASTER|CLUSTER_NODE_SLAVE);\n                clusterDoBeforeSleep(CLUSTER_TODO_SAVE_CONFIG);\n            } else if (memcmp(link->node->name,hdr->sender,\n                        CLUSTER_NAMELEN) != 0)\n            {\n                /* If the reply has a non matching node ID we\n                 * disconnect this node and set it as not having an associated\n                 * address. */\n                serverLog(LL_DEBUG,\"PONG contains mismatching sender ID. About node %.40s added %d ms ago, having flags %d\",\n                    link->node->name,\n                    (int)(mstime()-(link->node->ctime)),\n                    link->node->flags);\n                link->node->flags |= CLUSTER_NODE_NOADDR;\n                link->node->ip[0] = '\\0';\n                link->node->port = 0;\n                freeClusterLink(link);\n                clusterDoBeforeSleep(CLUSTER_TODO_SAVE_CONFIG);\n                return 0;\n            }\n        }\n\n        /* Update the node address if it changed. */\n        if (sender && type == CLUSTERMSG_TYPE_PING &&\n            !nodeInHandshake(sender) &&\n            nodeUpdateAddressIfNeeded(sender,link,ntohs(hdr->port)))\n        {\n            clusterDoBeforeSleep(CLUSTER_TODO_SAVE_CONFIG|\n                                 CLUSTER_TODO_UPDATE_STATE);\n        }\n\n        /* Update our info about the node */\n        if (link->node && type == CLUSTERMSG_TYPE_PONG) {\n            link->node->pong_received = mstime();\n            link->node->ping_sent = 0;\n\n            /* The PFAIL condition can be reversed without external\n             * help if it is momentary (that is, if it does not\n             * turn into a FAIL state).\n             *\n             * The FAIL condition is also reversible under specific\n             * conditions detected by clearNodeFailureIfNeeded(). */\n            if (nodeTimedOut(link->node)) {\n                link->node->flags &= ~CLUSTER_NODE_PFAIL;\n                clusterDoBeforeSleep(CLUSTER_TODO_SAVE_CONFIG|\n                                     CLUSTER_TODO_UPDATE_STATE);\n            } else if (nodeFailed(link->node)) {\n                clearNodeFailureIfNeeded(link->node);\n            }\n        }\n\n        /* Check for role switch: slave -> master or master -> slave. */\n        if (sender) {\n            if (!memcmp(hdr->slaveof,CLUSTER_NODE_NULL_NAME,\n                sizeof(hdr->slaveof)))\n            {\n                /* Node is a master. */\n                clusterSetNodeAsMaster(sender);\n            } else {\n                /* Node is a slave. */\n                clusterNode *master = clusterLookupNode(hdr->slaveof);\n\n                if (nodeIsMaster(sender)) {\n                    /* Master turned into a slave! Reconfigure the node. */\n                    clusterDelNodeSlots(sender);\n                    sender->flags &= ~(CLUSTER_NODE_MASTER|\n                                       CLUSTER_NODE_MIGRATE_TO);\n                    sender->flags |= CLUSTER_NODE_SLAVE;\n\n                    /* Update config and state. */\n                    clusterDoBeforeSleep(CLUSTER_TODO_SAVE_CONFIG|\n                                         CLUSTER_TODO_UPDATE_STATE);\n                }\n\n                /* Master node changed for this slave? */\n                if (master && sender->slaveof != master) {\n                    if (sender->slaveof)\n                        clusterNodeRemoveSlave(sender->slaveof,sender);\n                    clusterNodeAddSlave(master,sender);\n                    sender->slaveof = master;\n\n                    /* Update config. */\n                    clusterDoBeforeSleep(CLUSTER_TODO_SAVE_CONFIG);\n                }\n            }\n        }\n\n        /* Update our info about served slots.\n         *\n         * Note: this MUST happen after we update the master/slave state\n         * so that CLUSTER_NODE_MASTER flag will be set. */\n\n        /* Many checks are only needed if the set of served slots this\n         * instance claims is different compared to the set of slots we have\n         * for it. Check this ASAP to avoid other computational expansive\n         * checks later. */\n        clusterNode *sender_master = NULL; /* Sender or its master if slave. */\n        int dirty_slots = 0; /* Sender claimed slots don't match my view? */\n\n        if (sender) {\n            sender_master = nodeIsMaster(sender) ? sender : sender->slaveof;\n            if (sender_master) {\n                dirty_slots = memcmp(sender_master->slots,\n                        hdr->myslots,sizeof(hdr->myslots)) != 0;\n            }\n        }\n\n        /* 1) If the sender of the message is a master, and we detected that\n         *    the set of slots it claims changed, scan the slots to see if we\n         *    need to update our configuration. */\n        if (sender && nodeIsMaster(sender) && dirty_slots)\n            clusterUpdateSlotsConfigWith(sender,senderConfigEpoch,hdr->myslots);\n\n        /* 2) We also check for the reverse condition, that is, the sender\n         *    claims to serve slots we know are served by a master with a\n         *    greater configEpoch. If this happens we inform the sender.\n         *\n         * This is useful because sometimes after a partition heals, a\n         * reappearing master may be the last one to claim a given set of\n         * hash slots, but with a configuration that other instances know to\n         * be deprecated. Example:\n         *\n         * A and B are master and slave for slots 1,2,3.\n         * A is partitioned away, B gets promoted.\n         * B is partitioned away, and A returns available.\n         *\n         * Usually B would PING A publishing its set of served slots and its\n         * configEpoch, but because of the partition B can't inform A of the\n         * new configuration, so other nodes that have an updated table must\n         * do it. In this way A will stop to act as a master (or can try to\n         * failover if there are the conditions to win the election). */\n        if (sender && dirty_slots) {\n            int j;\n\n            for (j = 0; j < CLUSTER_SLOTS; j++) {\n                if (bitmapTestBit(hdr->myslots,j)) {\n                    if (server.cluster->slots[j] == sender ||\n                        server.cluster->slots[j] == NULL) continue;\n                    if (server.cluster->slots[j]->configEpoch >\n                        senderConfigEpoch)\n                    {\n                        serverLog(LL_VERBOSE,\n                            \"Node %.40s has old slots configuration, sending \"\n                            \"an UPDATE message about %.40s\",\n                                sender->name, server.cluster->slots[j]->name);\n                        clusterSendUpdate(sender->link,\n                            server.cluster->slots[j]);\n\n                        /* TODO: instead of exiting the loop send every other\n                         * UPDATE packet for other nodes that are the new owner\n                         * of sender's slots. */\n                        break;\n                    }\n                }\n            }\n        }\n\n        /* If our config epoch collides with the sender's try to fix\n         * the problem. */\n        if (sender &&\n            nodeIsMaster(myself) && nodeIsMaster(sender) &&\n            senderConfigEpoch == myself->configEpoch)\n        {\n            clusterHandleConfigEpochCollision(sender);\n        }\n\n        /* Get info from the gossip section */\n        if (sender) clusterProcessGossipSection(hdr,link);\n    } else if (type == CLUSTERMSG_TYPE_FAIL) {\n        clusterNode *failing;\n\n        if (sender) {\n            failing = clusterLookupNode(hdr->data.fail.about.nodename);\n            if (failing &&\n                !(failing->flags & (CLUSTER_NODE_FAIL|CLUSTER_NODE_MYSELF)))\n            {\n                serverLog(LL_NOTICE,\n                    \"FAIL message received from %.40s about %.40s\",\n                    hdr->sender, hdr->data.fail.about.nodename);\n                failing->flags |= CLUSTER_NODE_FAIL;\n                failing->fail_time = mstime();\n                failing->flags &= ~CLUSTER_NODE_PFAIL;\n                clusterDoBeforeSleep(CLUSTER_TODO_SAVE_CONFIG|\n                                     CLUSTER_TODO_UPDATE_STATE);\n            }\n        } else {\n            serverLog(LL_NOTICE,\n                \"Ignoring FAIL message from unknown node %.40s about %.40s\",\n                hdr->sender, hdr->data.fail.about.nodename);\n        }\n    } else if (type == CLUSTERMSG_TYPE_PUBLISH) {\n        robj *channel, *message;\n        uint32_t channel_len, message_len;\n\n        /* Don't bother creating useless objects if there are no\n         * Pub/Sub subscribers. */\n        if (dictSize(server.pubsub_channels) ||\n           listLength(server.pubsub_patterns))\n        {\n            channel_len = ntohl(hdr->data.publish.msg.channel_len);\n            message_len = ntohl(hdr->data.publish.msg.message_len);\n            channel = createStringObject(\n                        (char*)hdr->data.publish.msg.bulk_data,channel_len);\n            message = createStringObject(\n                        (char*)hdr->data.publish.msg.bulk_data+channel_len,\n                        message_len);\n            pubsubPublishMessage(channel,message);\n            decrRefCount(channel);\n            decrRefCount(message);\n        }\n    } else if (type == CLUSTERMSG_TYPE_FAILOVER_AUTH_REQUEST) {\n        if (!sender) return 1;  /* We don't know that node. */\n        clusterSendFailoverAuthIfNeeded(sender,hdr);\n    } else if (type == CLUSTERMSG_TYPE_FAILOVER_AUTH_ACK) {\n        if (!sender) return 1;  /* We don't know that node. */\n        /* We consider this vote only if the sender is a master serving\n         * a non zero number of slots, and its currentEpoch is greater or\n         * equal to epoch where this node started the election. */\n        if (nodeIsMaster(sender) && sender->numslots > 0 &&\n            senderCurrentEpoch >= server.cluster->failover_auth_epoch)\n        {\n            server.cluster->failover_auth_count++;\n            /* Maybe we reached a quorum here, set a flag to make sure\n             * we check ASAP. */\n            clusterDoBeforeSleep(CLUSTER_TODO_HANDLE_FAILOVER);\n        }\n    } else if (type == CLUSTERMSG_TYPE_MFSTART) {\n        /* This message is acceptable only if I'm a master and the sender\n         * is one of my slaves. */\n        if (!sender || sender->slaveof != myself) return 1;\n        /* Manual failover requested from slaves. Initialize the state\n         * accordingly. */\n        resetManualFailover();\n        server.cluster->mf_end = mstime() + CLUSTER_MF_TIMEOUT;\n        server.cluster->mf_slave = sender;\n        pauseClients(mstime()+(CLUSTER_MF_TIMEOUT*2));\n        serverLog(LL_WARNING,\"Manual failover requested by slave %.40s.\",\n            sender->name);\n    } else if (type == CLUSTERMSG_TYPE_UPDATE) {\n        clusterNode *n; /* The node the update is about. */\n        uint64_t reportedConfigEpoch =\n                    ntohu64(hdr->data.update.nodecfg.configEpoch);\n\n        if (!sender) return 1;  /* We don't know the sender. */\n        n = clusterLookupNode(hdr->data.update.nodecfg.nodename);\n        if (!n) return 1;   /* We don't know the reported node. */\n        if (n->configEpoch >= reportedConfigEpoch) return 1; /* Nothing new. */\n\n        /* If in our current config the node is a slave, set it as a master. */\n        if (nodeIsSlave(n)) clusterSetNodeAsMaster(n);\n\n        /* Update the node's configEpoch. */\n        n->configEpoch = reportedConfigEpoch;\n        clusterDoBeforeSleep(CLUSTER_TODO_SAVE_CONFIG|\n                             CLUSTER_TODO_FSYNC_CONFIG);\n\n        /* Check the bitmap of served slots and update our\n         * config accordingly. */\n        clusterUpdateSlotsConfigWith(n,reportedConfigEpoch,\n            hdr->data.update.nodecfg.slots);\n    } else {\n        serverLog(LL_WARNING,\"Received unknown packet type: %d\", type);\n    }\n    return 1;\n}\n\n/* This function is called when we detect the link with this node is lost.\n   We set the node as no longer connected. The Cluster Cron will detect\n   this connection and will try to get it connected again.\n\n   Instead if the node is a temporary node used to accept a query, we\n   completely free the node on error. */\nvoid handleLinkIOError(clusterLink *link) {\n    freeClusterLink(link);\n}\n\n/* Send data. This is handled using a trivial send buffer that gets\n * consumed by write(). We don't try to optimize this for speed too much\n * as this is a very low traffic channel. */\nvoid clusterWriteHandler(aeEventLoop *el, int fd, void *privdata, int mask) {\n    clusterLink *link = (clusterLink*) privdata;\n    ssize_t nwritten;\n    UNUSED(el);\n    UNUSED(mask);\n\n    nwritten = write(fd, link->sndbuf, sdslen(link->sndbuf));\n    if (nwritten <= 0) {\n        serverLog(LL_DEBUG,\"I/O error writing to node link: %s\",\n            strerror(errno));\n        handleLinkIOError(link);\n        return;\n    }\n    sdsrange(link->sndbuf,nwritten,-1);\n    if (sdslen(link->sndbuf) == 0)\n        aeDeleteFileEvent(server.el, link->fd, AE_WRITABLE);\n}\n\n/* Read data. Try to read the first field of the header first to check the\n * full length of the packet. When a whole packet is in memory this function\n * will call the function to process the packet. And so forth. */\nvoid clusterReadHandler(aeEventLoop *el, int fd, void *privdata, int mask) {\n    char buf[sizeof(clusterMsg)];\n    ssize_t nread;\n    clusterMsg *hdr;\n    clusterLink *link = (clusterLink*) privdata;\n    unsigned int readlen, rcvbuflen;\n    UNUSED(el);\n    UNUSED(mask);\n\n    while(1) { /* Read as long as there is data to read. */\n        rcvbuflen = sdslen(link->rcvbuf);\n        if (rcvbuflen < 8) {\n            /* First, obtain the first 8 bytes to get the full message\n             * length. */\n            readlen = 8 - rcvbuflen;\n        } else {\n            /* Finally read the full message. */\n            hdr = (clusterMsg*) link->rcvbuf;\n            if (rcvbuflen == 8) {\n                /* Perform some sanity check on the message signature\n                 * and length. */\n                if (memcmp(hdr->sig,\"RCmb\",4) != 0 ||\n                    ntohl(hdr->totlen) < CLUSTERMSG_MIN_LEN)\n                {\n                    serverLog(LL_WARNING,\n                        \"Bad message length or signature received \"\n                        \"from Cluster bus.\");\n                    handleLinkIOError(link);\n                    return;\n                }\n            }\n            readlen = ntohl(hdr->totlen) - rcvbuflen;\n            if (readlen > sizeof(buf)) readlen = sizeof(buf);\n        }\n\n        nread = read(fd,buf,readlen);\n        if (nread == -1 && errno == EAGAIN) return; /* No more data ready. */\n\n        if (nread <= 0) {\n            /* I/O error... */\n            serverLog(LL_DEBUG,\"I/O error reading from node link: %s\",\n                (nread == 0) ? \"connection closed\" : strerror(errno));\n            handleLinkIOError(link);\n            return;\n        } else {\n            /* Read data and recast the pointer to the new buffer. */\n            link->rcvbuf = sdscatlen(link->rcvbuf,buf,nread);\n            hdr = (clusterMsg*) link->rcvbuf;\n            rcvbuflen += nread;\n        }\n\n        /* Total length obtained? Process this packet. */\n        if (rcvbuflen >= 8 && rcvbuflen == ntohl(hdr->totlen)) {\n            if (clusterProcessPacket(link)) {\n                sdsfree(link->rcvbuf);\n                link->rcvbuf = sdsempty();\n            } else {\n                return; /* Link no longer valid. */\n            }\n        }\n    }\n}\n\n/* Put stuff into the send buffer.\n *\n * It is guaranteed that this function will never have as a side effect\n * the link to be invalidated, so it is safe to call this function\n * from event handlers that will do stuff with the same link later. */\nvoid clusterSendMessage(clusterLink *link, unsigned char *msg, size_t msglen) {\n    if (sdslen(link->sndbuf) == 0 && msglen != 0)\n        aeCreateFileEvent(server.el,link->fd,AE_WRITABLE,\n                    clusterWriteHandler,link);\n\n    link->sndbuf = sdscatlen(link->sndbuf, msg, msglen);\n    server.cluster->stats_bus_messages_sent++;\n}\n\n/* Send a message to all the nodes that are part of the cluster having\n * a connected link.\n *\n * It is guaranteed that this function will never have as a side effect\n * some node->link to be invalidated, so it is safe to call this function\n * from event handlers that will do stuff with node links later. */\nvoid clusterBroadcastMessage(void *buf, size_t len) {\n    dictIterator *di;\n    dictEntry *de;\n\n    di = dictGetSafeIterator(server.cluster->nodes);\n    while((de = dictNext(di)) != NULL) {\n        clusterNode *node = dictGetVal(de);\n\n        if (!node->link) continue;\n        if (node->flags & (CLUSTER_NODE_MYSELF|CLUSTER_NODE_HANDSHAKE))\n            continue;\n        clusterSendMessage(node->link,buf,len);\n    }\n    dictReleaseIterator(di);\n}\n\n/* Build the message header. hdr must point to a buffer at least\n * sizeof(clusterMsg) in bytes. */\nvoid clusterBuildMessageHdr(clusterMsg *hdr, int type) {\n    int totlen = 0;\n    uint64_t offset;\n    clusterNode *master;\n\n    /* If this node is a master, we send its slots bitmap and configEpoch.\n     * If this node is a slave we send the master's information instead (the\n     * node is flagged as slave so the receiver knows that it is NOT really\n     * in charge for this slots. */\n    master = (nodeIsSlave(myself) && myself->slaveof) ?\n              myself->slaveof : myself;\n\n    memset(hdr,0,sizeof(*hdr));\n    hdr->ver = htons(CLUSTER_PROTO_VER);\n    hdr->sig[0] = 'R';\n    hdr->sig[1] = 'C';\n    hdr->sig[2] = 'm';\n    hdr->sig[3] = 'b';\n    hdr->type = htons(type);\n    memcpy(hdr->sender,myself->name,CLUSTER_NAMELEN);\n\n    memcpy(hdr->myslots,master->slots,sizeof(hdr->myslots));\n    memset(hdr->slaveof,0,CLUSTER_NAMELEN);\n    if (myself->slaveof != NULL)\n        memcpy(hdr->slaveof,myself->slaveof->name, CLUSTER_NAMELEN);\n    hdr->port = htons(server.port);\n    hdr->flags = htons(myself->flags);\n    hdr->state = server.cluster->state;\n\n    /* Set the currentEpoch and configEpochs. */\n    hdr->currentEpoch = htonu64(server.cluster->currentEpoch);\n    hdr->configEpoch = htonu64(master->configEpoch);\n\n    /* Set the replication offset. */\n    if (nodeIsSlave(myself))\n        offset = replicationGetSlaveOffset();\n    else\n        offset = server.master_repl_offset;\n    hdr->offset = htonu64(offset);\n\n    /* Set the message flags. */\n    if (nodeIsMaster(myself) && server.cluster->mf_end)\n        hdr->mflags[0] |= CLUSTERMSG_FLAG0_PAUSED;\n\n    /* Compute the message length for certain messages. For other messages\n     * this is up to the caller. */\n    if (type == CLUSTERMSG_TYPE_FAIL) {\n        totlen = sizeof(clusterMsg)-sizeof(union clusterMsgData);\n        totlen += sizeof(clusterMsgDataFail);\n    } else if (type == CLUSTERMSG_TYPE_UPDATE) {\n        totlen = sizeof(clusterMsg)-sizeof(union clusterMsgData);\n        totlen += sizeof(clusterMsgDataUpdate);\n    }\n    hdr->totlen = htonl(totlen);\n    /* For PING, PONG, and MEET, fixing the totlen field is up to the caller. */\n}\n\n/* Send a PING or PONG packet to the specified node, making sure to add enough\n * gossip informations. */\nvoid clusterSendPing(clusterLink *link, int type) {\n    unsigned char *buf;\n    clusterMsg *hdr;\n    int gossipcount = 0; /* Number of gossip sections added so far. */\n    int wanted; /* Number of gossip sections we want to append if possible. */\n    int totlen; /* Total packet length. */\n    /* freshnodes is the max number of nodes we can hope to append at all:\n     * nodes available minus two (ourself and the node we are sending the\n     * message to). However practically there may be less valid nodes since\n     * nodes in handshake state, disconnected, are not considered. */\n    int freshnodes = dictSize(server.cluster->nodes)-2;\n\n    /* How many gossip sections we want to add? 1/10 of the number of nodes\n     * and anyway at least 3. Why 1/10?\n     *\n     * If we have N masters, with N/10 entries, and we consider that in\n     * node_timeout we exchange with each other node at least 4 packets\n     * (we ping in the worst case in node_timeout/2 time, and we also\n     * receive two pings from the host), we have a total of 8 packets\n     * in the node_timeout*2 falure reports validity time. So we have\n     * that, for a single PFAIL node, we can expect to receive the following\n     * number of failure reports (in the specified window of time):\n     *\n     * PROB * GOSSIP_ENTRIES_PER_PACKET * TOTAL_PACKETS:\n     *\n     * PROB = probability of being featured in a single gossip entry,\n     *        which is 1 / NUM_OF_NODES.\n     * ENTRIES = 10.\n     * TOTAL_PACKETS = 2 * 4 * NUM_OF_MASTERS.\n     *\n     * If we assume we have just masters (so num of nodes and num of masters\n     * is the same), with 1/10 we always get over the majority, and specifically\n     * 80% of the number of nodes, to account for many masters failing at the\n     * same time.\n     *\n     * Since we have non-voting slaves that lower the probability of an entry\n     * to feature our node, we set the number of entires per packet as\n     * 10% of the total nodes we have. */\n    wanted = floor(dictSize(server.cluster->nodes)/10);\n    if (wanted < 3) wanted = 3;\n    if (wanted > freshnodes) wanted = freshnodes;\n\n    /* Compute the maxium totlen to allocate our buffer. We'll fix the totlen\n     * later according to the number of gossip sections we really were able\n     * to put inside the packet. */\n    totlen = sizeof(clusterMsg)-sizeof(union clusterMsgData);\n    totlen += (sizeof(clusterMsgDataGossip)*wanted);\n    /* Note: clusterBuildMessageHdr() expects the buffer to be always at least\n     * sizeof(clusterMsg) or more. */\n    if (totlen < (int)sizeof(clusterMsg)) totlen = sizeof(clusterMsg);\n    buf = zcalloc(totlen);\n    hdr = (clusterMsg*) buf;\n\n    /* Populate the header. */\n    if (link->node && type == CLUSTERMSG_TYPE_PING)\n        link->node->ping_sent = mstime();\n    clusterBuildMessageHdr(hdr,type);\n\n    /* Populate the gossip fields */\n    int maxiterations = wanted*3;\n    while(freshnodes > 0 && gossipcount < wanted && maxiterations--) {\n        dictEntry *de = dictGetRandomKey(server.cluster->nodes);\n        clusterNode *this = dictGetVal(de);\n        clusterMsgDataGossip *gossip;\n        int j;\n\n        /* Don't include this node: the whole packet header is about us\n         * already, so we just gossip about other nodes. */\n        if (this == myself) continue;\n\n        /* Give a bias to FAIL/PFAIL nodes. */\n        if (maxiterations > wanted*2 &&\n            !(this->flags & (CLUSTER_NODE_PFAIL|CLUSTER_NODE_FAIL)))\n            continue;\n\n        /* In the gossip section don't include:\n         * 1) Nodes in HANDSHAKE state.\n         * 3) Nodes with the NOADDR flag set.\n         * 4) Disconnected nodes if they don't have configured slots.\n         */\n        if (this->flags & (CLUSTER_NODE_HANDSHAKE|CLUSTER_NODE_NOADDR) ||\n            (this->link == NULL && this->numslots == 0))\n        {\n            freshnodes--; /* Tecnically not correct, but saves CPU. */\n            continue;\n        }\n\n        /* Check if we already added this node */\n        for (j = 0; j < gossipcount; j++) {\n            if (memcmp(hdr->data.ping.gossip[j].nodename,this->name,\n                    CLUSTER_NAMELEN) == 0) break;\n        }\n        if (j != gossipcount) continue;\n\n        /* Add it */\n        freshnodes--;\n        gossip = &(hdr->data.ping.gossip[gossipcount]);\n        memcpy(gossip->nodename,this->name,CLUSTER_NAMELEN);\n        gossip->ping_sent = htonl(this->ping_sent);\n        gossip->pong_received = htonl(this->pong_received);\n        memcpy(gossip->ip,this->ip,sizeof(this->ip));\n        gossip->port = htons(this->port);\n        gossip->flags = htons(this->flags);\n        gossip->notused1 = 0;\n        gossip->notused2 = 0;\n        gossipcount++;\n    }\n\n    /* Ready to send... fix the totlen fiend and queue the message in the\n     * output buffer. */\n    totlen = sizeof(clusterMsg)-sizeof(union clusterMsgData);\n    totlen += (sizeof(clusterMsgDataGossip)*gossipcount);\n    hdr->count = htons(gossipcount);\n    hdr->totlen = htonl(totlen);\n    clusterSendMessage(link,buf,totlen);\n    zfree(buf);\n}\n\n/* Send a PONG packet to every connected node that's not in handshake state\n * and for which we have a valid link.\n *\n * In Redis Cluster pongs are not used just for failure detection, but also\n * to carry important configuration information. So broadcasting a pong is\n * useful when something changes in the configuration and we want to make\n * the cluster aware ASAP (for instance after a slave promotion).\n *\n * The 'target' argument specifies the receiving instances using the\n * defines below:\n *\n * CLUSTER_BROADCAST_ALL -> All known instances.\n * CLUSTER_BROADCAST_LOCAL_SLAVES -> All slaves in my master-slaves ring.\n */\n#define CLUSTER_BROADCAST_ALL 0\n#define CLUSTER_BROADCAST_LOCAL_SLAVES 1\nvoid clusterBroadcastPong(int target) {\n    dictIterator *di;\n    dictEntry *de;\n\n    di = dictGetSafeIterator(server.cluster->nodes);\n    while((de = dictNext(di)) != NULL) {\n        clusterNode *node = dictGetVal(de);\n\n        if (!node->link) continue;\n        if (node == myself || nodeInHandshake(node)) continue;\n        if (target == CLUSTER_BROADCAST_LOCAL_SLAVES) {\n            int local_slave =\n                nodeIsSlave(node) && node->slaveof &&\n                (node->slaveof == myself || node->slaveof == myself->slaveof);\n            if (!local_slave) continue;\n        }\n        clusterSendPing(node->link,CLUSTERMSG_TYPE_PONG);\n    }\n    dictReleaseIterator(di);\n}\n\n/* Send a PUBLISH message.\n *\n * If link is NULL, then the message is broadcasted to the whole cluster. */\nvoid clusterSendPublish(clusterLink *link, robj *channel, robj *message) {\n    unsigned char buf[sizeof(clusterMsg)], *payload;\n    clusterMsg *hdr = (clusterMsg*) buf;\n    uint32_t totlen;\n    uint32_t channel_len, message_len;\n\n    channel = getDecodedObject(channel);\n    message = getDecodedObject(message);\n    channel_len = sdslen(channel->ptr);\n    message_len = sdslen(message->ptr);\n\n    clusterBuildMessageHdr(hdr,CLUSTERMSG_TYPE_PUBLISH);\n    totlen = sizeof(clusterMsg)-sizeof(union clusterMsgData);\n    totlen += sizeof(clusterMsgDataPublish) - 8 + channel_len + message_len;\n\n    hdr->data.publish.msg.channel_len = htonl(channel_len);\n    hdr->data.publish.msg.message_len = htonl(message_len);\n    hdr->totlen = htonl(totlen);\n\n    /* Try to use the local buffer if possible */\n    if (totlen < sizeof(buf)) {\n        payload = buf;\n    } else {\n        payload = zmalloc(totlen);\n        memcpy(payload,hdr,sizeof(*hdr));\n        hdr = (clusterMsg*) payload;\n    }\n    memcpy(hdr->data.publish.msg.bulk_data,channel->ptr,sdslen(channel->ptr));\n    memcpy(hdr->data.publish.msg.bulk_data+sdslen(channel->ptr),\n        message->ptr,sdslen(message->ptr));\n\n    if (link)\n        clusterSendMessage(link,payload,totlen);\n    else\n        clusterBroadcastMessage(payload,totlen);\n\n    decrRefCount(channel);\n    decrRefCount(message);\n    if (payload != buf) zfree(payload);\n}\n\n/* Send a FAIL message to all the nodes we are able to contact.\n * The FAIL message is sent when we detect that a node is failing\n * (CLUSTER_NODE_PFAIL) and we also receive a gossip confirmation of this:\n * we switch the node state to CLUSTER_NODE_FAIL and ask all the other\n * nodes to do the same ASAP. */\nvoid clusterSendFail(char *nodename) {\n    unsigned char buf[sizeof(clusterMsg)];\n    clusterMsg *hdr = (clusterMsg*) buf;\n\n    clusterBuildMessageHdr(hdr,CLUSTERMSG_TYPE_FAIL);\n    memcpy(hdr->data.fail.about.nodename,nodename,CLUSTER_NAMELEN);\n    clusterBroadcastMessage(buf,ntohl(hdr->totlen));\n}\n\n/* Send an UPDATE message to the specified link carrying the specified 'node'\n * slots configuration. The node name, slots bitmap, and configEpoch info\n * are included. */\nvoid clusterSendUpdate(clusterLink *link, clusterNode *node) {\n    unsigned char buf[sizeof(clusterMsg)];\n    clusterMsg *hdr = (clusterMsg*) buf;\n\n    if (link == NULL) return;\n    clusterBuildMessageHdr(hdr,CLUSTERMSG_TYPE_UPDATE);\n    memcpy(hdr->data.update.nodecfg.nodename,node->name,CLUSTER_NAMELEN);\n    hdr->data.update.nodecfg.configEpoch = htonu64(node->configEpoch);\n    memcpy(hdr->data.update.nodecfg.slots,node->slots,sizeof(node->slots));\n    clusterSendMessage(link,buf,ntohl(hdr->totlen));\n}\n\n/* -----------------------------------------------------------------------------\n * CLUSTER Pub/Sub support\n *\n * For now we do very little, just propagating PUBLISH messages across the whole\n * cluster. In the future we'll try to get smarter and avoiding propagating those\n * messages to hosts without receives for a given channel.\n * -------------------------------------------------------------------------- */\nvoid clusterPropagatePublish(robj *channel, robj *message) {\n    clusterSendPublish(NULL, channel, message);\n}\n\n/* -----------------------------------------------------------------------------\n * SLAVE node specific functions\n * -------------------------------------------------------------------------- */\n\n/* This function sends a FAILOVE_AUTH_REQUEST message to every node in order to\n * see if there is the quorum for this slave instance to failover its failing\n * master.\n *\n * Note that we send the failover request to everybody, master and slave nodes,\n * but only the masters are supposed to reply to our query. */\nvoid clusterRequestFailoverAuth(void) {\n    unsigned char buf[sizeof(clusterMsg)];\n    clusterMsg *hdr = (clusterMsg*) buf;\n    uint32_t totlen;\n\n    clusterBuildMessageHdr(hdr,CLUSTERMSG_TYPE_FAILOVER_AUTH_REQUEST);\n    /* If this is a manual failover, set the CLUSTERMSG_FLAG0_FORCEACK bit\n     * in the header to communicate the nodes receiving the message that\n     * they should authorized the failover even if the master is working. */\n    if (server.cluster->mf_end) hdr->mflags[0] |= CLUSTERMSG_FLAG0_FORCEACK;\n    totlen = sizeof(clusterMsg)-sizeof(union clusterMsgData);\n    hdr->totlen = htonl(totlen);\n    clusterBroadcastMessage(buf,totlen);\n}\n\n/* Send a FAILOVER_AUTH_ACK message to the specified node. */\nvoid clusterSendFailoverAuth(clusterNode *node) {\n    unsigned char buf[sizeof(clusterMsg)];\n    clusterMsg *hdr = (clusterMsg*) buf;\n    uint32_t totlen;\n\n    if (!node->link) return;\n    clusterBuildMessageHdr(hdr,CLUSTERMSG_TYPE_FAILOVER_AUTH_ACK);\n    totlen = sizeof(clusterMsg)-sizeof(union clusterMsgData);\n    hdr->totlen = htonl(totlen);\n    clusterSendMessage(node->link,buf,totlen);\n}\n\n/* Send a MFSTART message to the specified node. */\nvoid clusterSendMFStart(clusterNode *node) {\n    unsigned char buf[sizeof(clusterMsg)];\n    clusterMsg *hdr = (clusterMsg*) buf;\n    uint32_t totlen;\n\n    if (!node->link) return;\n    clusterBuildMessageHdr(hdr,CLUSTERMSG_TYPE_MFSTART);\n    totlen = sizeof(clusterMsg)-sizeof(union clusterMsgData);\n    hdr->totlen = htonl(totlen);\n    clusterSendMessage(node->link,buf,totlen);\n}\n\n/* Vote for the node asking for our vote if there are the conditions. */\nvoid clusterSendFailoverAuthIfNeeded(clusterNode *node, clusterMsg *request) {\n    clusterNode *master = node->slaveof;\n    uint64_t requestCurrentEpoch = ntohu64(request->currentEpoch);\n    uint64_t requestConfigEpoch = ntohu64(request->configEpoch);\n    unsigned char *claimed_slots = request->myslots;\n    int force_ack = request->mflags[0] & CLUSTERMSG_FLAG0_FORCEACK;\n    int j;\n\n    /* IF we are not a master serving at least 1 slot, we don't have the\n     * right to vote, as the cluster size in Redis Cluster is the number\n     * of masters serving at least one slot, and quorum is the cluster\n     * size + 1 */\n    if (nodeIsSlave(myself) || myself->numslots == 0) return;\n\n    /* Request epoch must be >= our currentEpoch.\n     * Note that it is impossible for it to actually be greater since\n     * our currentEpoch was updated as a side effect of receiving this\n     * request, if the request epoch was greater. */\n    if (requestCurrentEpoch < server.cluster->currentEpoch) {\n        serverLog(LL_WARNING,\n            \"Failover auth denied to %.40s: reqEpoch (%llu) < curEpoch(%llu)\",\n            node->name,\n            (unsigned long long) requestCurrentEpoch,\n            (unsigned long long) server.cluster->currentEpoch);\n        return;\n    }\n\n    /* I already voted for this epoch? Return ASAP. */\n    if (server.cluster->lastVoteEpoch == server.cluster->currentEpoch) {\n        serverLog(LL_WARNING,\n                \"Failover auth denied to %.40s: already voted for epoch %llu\",\n                node->name,\n                (unsigned long long) server.cluster->currentEpoch);\n        return;\n    }\n\n    /* Node must be a slave and its master down.\n     * The master can be non failing if the request is flagged\n     * with CLUSTERMSG_FLAG0_FORCEACK (manual failover). */\n    if (nodeIsMaster(node) || master == NULL ||\n        (!nodeFailed(master) && !force_ack))\n    {\n        if (nodeIsMaster(node)) {\n            serverLog(LL_WARNING,\n                    \"Failover auth denied to %.40s: it is a master node\",\n                    node->name);\n        } else if (master == NULL) {\n            serverLog(LL_WARNING,\n                    \"Failover auth denied to %.40s: I don't know its master\",\n                    node->name);\n        } else if (!nodeFailed(master)) {\n            serverLog(LL_WARNING,\n                    \"Failover auth denied to %.40s: its master is up\",\n                    node->name);\n        }\n        return;\n    }\n\n    /* We did not voted for a slave about this master for two\n     * times the node timeout. This is not strictly needed for correctness\n     * of the algorithm but makes the base case more linear. */\n    if (mstime() - node->slaveof->voted_time < server.cluster_node_timeout * 2)\n    {\n        serverLog(LL_WARNING,\n                \"Failover auth denied to %.40s: \"\n                \"can't vote about this master before %lld milliseconds\",\n                node->name,\n                (long long) ((server.cluster_node_timeout*2)-\n                             (mstime() - node->slaveof->voted_time)));\n        return;\n    }\n\n    /* The slave requesting the vote must have a configEpoch for the claimed\n     * slots that is >= the one of the masters currently serving the same\n     * slots in the current configuration. */\n    for (j = 0; j < CLUSTER_SLOTS; j++) {\n        if (bitmapTestBit(claimed_slots, j) == 0) continue;\n        if (server.cluster->slots[j] == NULL ||\n            server.cluster->slots[j]->configEpoch <= requestConfigEpoch)\n        {\n            continue;\n        }\n        /* If we reached this point we found a slot that in our current slots\n         * is served by a master with a greater configEpoch than the one claimed\n         * by the slave requesting our vote. Refuse to vote for this slave. */\n        serverLog(LL_WARNING,\n                \"Failover auth denied to %.40s: \"\n                \"slot %d epoch (%llu) > reqEpoch (%llu)\",\n                node->name, j,\n                (unsigned long long) server.cluster->slots[j]->configEpoch,\n                (unsigned long long) requestConfigEpoch);\n        return;\n    }\n\n    /* We can vote for this slave. */\n    clusterSendFailoverAuth(node);\n    server.cluster->lastVoteEpoch = server.cluster->currentEpoch;\n    node->slaveof->voted_time = mstime();\n    serverLog(LL_WARNING, \"Failover auth granted to %.40s for epoch %llu\",\n        node->name, (unsigned long long) server.cluster->currentEpoch);\n}\n\n/* This function returns the \"rank\" of this instance, a slave, in the context\n * of its master-slaves ring. The rank of the slave is given by the number of\n * other slaves for the same master that have a better replication offset\n * compared to the local one (better means, greater, so they claim more data).\n *\n * A slave with rank 0 is the one with the greatest (most up to date)\n * replication offset, and so forth. Note that because how the rank is computed\n * multiple slaves may have the same rank, in case they have the same offset.\n *\n * The slave rank is used to add a delay to start an election in order to\n * get voted and replace a failing master. Slaves with better replication\n * offsets are more likely to win. */\nint clusterGetSlaveRank(void) {\n    long long myoffset;\n    int j, rank = 0;\n    clusterNode *master;\n\n    serverAssert(nodeIsSlave(myself));\n    master = myself->slaveof;\n    if (master == NULL) return 0; /* Never called by slaves without master. */\n\n    myoffset = replicationGetSlaveOffset();\n    for (j = 0; j < master->numslaves; j++)\n        if (master->slaves[j] != myself &&\n            master->slaves[j]->repl_offset > myoffset) rank++;\n    return rank;\n}\n\n/* This function is called by clusterHandleSlaveFailover() in order to\n * let the slave log why it is not able to failover. Sometimes there are\n * not the conditions, but since the failover function is called again and\n * again, we can't log the same things continuously.\n *\n * This function works by logging only if a given set of conditions are\n * true:\n *\n * 1) The reason for which the failover can't be initiated changed.\n *    The reasons also include a NONE reason we reset the state to\n *    when the slave finds that its master is fine (no FAIL flag).\n * 2) Also, the log is emitted again if the master is still down and\n *    the reason for not failing over is still the same, but more than\n *    CLUSTER_CANT_FAILOVER_RELOG_PERIOD seconds elapsed.\n * 3) Finally, the function only logs if the slave is down for more than\n *    five seconds + NODE_TIMEOUT. This way nothing is logged when a\n *    failover starts in a reasonable time.\n *\n * The function is called with the reason why the slave can't failover\n * which is one of the integer macros CLUSTER_CANT_FAILOVER_*.\n *\n * The function is guaranteed to be called only if 'myself' is a slave. */\nvoid clusterLogCantFailover(int reason) {\n    char *msg;\n    static time_t lastlog_time = 0;\n    mstime_t nolog_fail_time = server.cluster_node_timeout + 5000;\n\n    /* Don't log if we have the same reason for some time. */\n    if (reason == server.cluster->cant_failover_reason &&\n        time(NULL)-lastlog_time < CLUSTER_CANT_FAILOVER_RELOG_PERIOD)\n        return;\n\n    server.cluster->cant_failover_reason = reason;\n\n    /* We also don't emit any log if the master failed no long ago, the\n     * goal of this function is to log slaves in a stalled condition for\n     * a long time. */\n    if (myself->slaveof &&\n        nodeFailed(myself->slaveof) &&\n        (mstime() - myself->slaveof->fail_time) < nolog_fail_time) return;\n\n    switch(reason) {\n    case CLUSTER_CANT_FAILOVER_DATA_AGE:\n        msg = \"Disconnected from master for longer than allowed. \"\n              \"Please check the 'cluster-slave-validity-factor' configuration \"\n              \"option.\";\n        break;\n    case CLUSTER_CANT_FAILOVER_WAITING_DELAY:\n        msg = \"Waiting the delay before I can start a new failover.\";\n        break;\n    case CLUSTER_CANT_FAILOVER_EXPIRED:\n        msg = \"Failover attempt expired.\";\n        break;\n    case CLUSTER_CANT_FAILOVER_WAITING_VOTES:\n        msg = \"Waiting for votes, but majority still not reached.\";\n        break;\n    default:\n        msg = \"Unknown reason code.\";\n        break;\n    }\n    lastlog_time = time(NULL);\n    serverLog(LL_WARNING,\"Currently unable to failover: %s\", msg);\n}\n\n/* This function implements the final part of automatic and manual failovers,\n * where the slave grabs its master's hash slots, and propagates the new\n * configuration.\n *\n * Note that it's up to the caller to be sure that the node got a new\n * configuration epoch already. */\nvoid clusterFailoverReplaceYourMaster(void) {\n    int j;\n    clusterNode *oldmaster = myself->slaveof;\n\n    if (nodeIsMaster(myself) || oldmaster == NULL) return;\n\n    /* 1) Turn this node into a master. */\n    clusterSetNodeAsMaster(myself);\n    replicationUnsetMaster();\n\n    /* 2) Claim all the slots assigned to our master. */\n    for (j = 0; j < CLUSTER_SLOTS; j++) {\n        if (clusterNodeGetSlotBit(oldmaster,j)) {\n            clusterDelSlot(j);\n            clusterAddSlot(myself,j);\n        }\n    }\n\n    /* 3) Update state and save config. */\n    clusterUpdateState();\n    clusterSaveConfigOrDie(1);\n\n    /* 4) Pong all the other nodes so that they can update the state\n     *    accordingly and detect that we switched to master role. */\n    clusterBroadcastPong(CLUSTER_BROADCAST_ALL);\n\n    /* 5) If there was a manual failover in progress, clear the state. */\n    resetManualFailover();\n}\n\n/* This function is called if we are a slave node and our master serving\n * a non-zero amount of hash slots is in FAIL state.\n *\n * The gaol of this function is:\n * 1) To check if we are able to perform a failover, is our data updated?\n * 2) Try to get elected by masters.\n * 3) Perform the failover informing all the other nodes.\n */\nvoid clusterHandleSlaveFailover(void) {\n    mstime_t data_age;\n    mstime_t auth_age = mstime() - server.cluster->failover_auth_time;\n    int needed_quorum = (server.cluster->size / 2) + 1;\n    int manual_failover = server.cluster->mf_end != 0 &&\n                          server.cluster->mf_can_start;\n    mstime_t auth_timeout, auth_retry_time;\n\n    server.cluster->todo_before_sleep &= ~CLUSTER_TODO_HANDLE_FAILOVER;\n\n    /* Compute the failover timeout (the max time we have to send votes\n     * and wait for replies), and the failover retry time (the time to wait\n     * before trying to get voted again).\n     *\n     * Timeout is MIN(NODE_TIMEOUT*2,2000) milliseconds.\n     * Retry is two times the Timeout.\n     */\n    auth_timeout = server.cluster_node_timeout*2;\n    if (auth_timeout < 2000) auth_timeout = 2000;\n    auth_retry_time = auth_timeout*2;\n\n    /* Pre conditions to run the function, that must be met both in case\n     * of an automatic or manual failover:\n     * 1) We are a slave.\n     * 2) Our master is flagged as FAIL, or this is a manual failover.\n     * 3) It is serving slots. */\n    if (nodeIsMaster(myself) ||\n        myself->slaveof == NULL ||\n        (!nodeFailed(myself->slaveof) && !manual_failover) ||\n        myself->slaveof->numslots == 0)\n    {\n        /* There are no reasons to failover, so we set the reason why we\n         * are returning without failing over to NONE. */\n        server.cluster->cant_failover_reason = CLUSTER_CANT_FAILOVER_NONE;\n        return;\n    }\n\n    /* Set data_age to the number of seconds we are disconnected from\n     * the master. */\n    if (server.repl_state == REPL_STATE_CONNECTED) {\n        data_age = (mstime_t)(server.unixtime - server.master->lastinteraction)\n                   * 1000;\n    } else {\n        data_age = (mstime_t)(server.unixtime - server.repl_down_since) * 1000;\n    }\n\n    /* Remove the node timeout from the data age as it is fine that we are\n     * disconnected from our master at least for the time it was down to be\n     * flagged as FAIL, that's the baseline. */\n    if (data_age > server.cluster_node_timeout)\n        data_age -= server.cluster_node_timeout;\n\n    /* Check if our data is recent enough according to the slave validity\n     * factor configured by the user.\n     *\n     * Check bypassed for manual failovers. */\n    if (server.cluster_slave_validity_factor &&\n        data_age >\n        (((mstime_t)server.repl_ping_slave_period * 1000) +\n         (server.cluster_node_timeout * server.cluster_slave_validity_factor)))\n    {\n        if (!manual_failover) {\n            clusterLogCantFailover(CLUSTER_CANT_FAILOVER_DATA_AGE);\n            return;\n        }\n    }\n\n    /* If the previous failover attempt timedout and the retry time has\n     * elapsed, we can setup a new one. */\n    if (auth_age > auth_retry_time) {\n        server.cluster->failover_auth_time = mstime() +\n            500 + /* Fixed delay of 500 milliseconds, let FAIL msg propagate. */\n            random() % 500; /* Random delay between 0 and 500 milliseconds. */\n        server.cluster->failover_auth_count = 0;\n        server.cluster->failover_auth_sent = 0;\n        server.cluster->failover_auth_rank = clusterGetSlaveRank();\n        /* We add another delay that is proportional to the slave rank.\n         * Specifically 1 second * rank. This way slaves that have a probably\n         * less updated replication offset, are penalized. */\n        server.cluster->failover_auth_time +=\n            server.cluster->failover_auth_rank * 1000;\n        /* However if this is a manual failover, no delay is needed. */\n        if (server.cluster->mf_end) {\n            server.cluster->failover_auth_time = mstime();\n            server.cluster->failover_auth_rank = 0;\n        }\n        serverLog(LL_WARNING,\n            \"Start of election delayed for %lld milliseconds \"\n            \"(rank #%d, offset %lld).\",\n            server.cluster->failover_auth_time - mstime(),\n            server.cluster->failover_auth_rank,\n            replicationGetSlaveOffset());\n        /* Now that we have a scheduled election, broadcast our offset\n         * to all the other slaves so that they'll updated their offsets\n         * if our offset is better. */\n        clusterBroadcastPong(CLUSTER_BROADCAST_LOCAL_SLAVES);\n        return;\n    }\n\n    /* It is possible that we received more updated offsets from other\n     * slaves for the same master since we computed our election delay.\n     * Update the delay if our rank changed.\n     *\n     * Not performed if this is a manual failover. */\n    if (server.cluster->failover_auth_sent == 0 &&\n        server.cluster->mf_end == 0)\n    {\n        int newrank = clusterGetSlaveRank();\n        if (newrank > server.cluster->failover_auth_rank) {\n            long long added_delay =\n                (newrank - server.cluster->failover_auth_rank) * 1000;\n            server.cluster->failover_auth_time += added_delay;\n            server.cluster->failover_auth_rank = newrank;\n            serverLog(LL_WARNING,\n                \"Slave rank updated to #%d, added %lld milliseconds of delay.\",\n                newrank, added_delay);\n        }\n    }\n\n    /* Return ASAP if we can't still start the election. */\n    if (mstime() < server.cluster->failover_auth_time) {\n        clusterLogCantFailover(CLUSTER_CANT_FAILOVER_WAITING_DELAY);\n        return;\n    }\n\n    /* Return ASAP if the election is too old to be valid. */\n    if (auth_age > auth_timeout) {\n        clusterLogCantFailover(CLUSTER_CANT_FAILOVER_EXPIRED);\n        return;\n    }\n\n    /* Ask for votes if needed. */\n    if (server.cluster->failover_auth_sent == 0) {\n        server.cluster->currentEpoch++;\n        server.cluster->failover_auth_epoch = server.cluster->currentEpoch;\n        serverLog(LL_WARNING,\"Starting a failover election for epoch %llu.\",\n            (unsigned long long) server.cluster->currentEpoch);\n        clusterRequestFailoverAuth();\n        server.cluster->failover_auth_sent = 1;\n        clusterDoBeforeSleep(CLUSTER_TODO_SAVE_CONFIG|\n                             CLUSTER_TODO_UPDATE_STATE|\n                             CLUSTER_TODO_FSYNC_CONFIG);\n        return; /* Wait for replies. */\n    }\n\n    /* Check if we reached the quorum. */\n    if (server.cluster->failover_auth_count >= needed_quorum) {\n        /* We have the quorum, we can finally failover the master. */\n\n        serverLog(LL_WARNING,\n            \"Failover election won: I'm the new master.\");\n\n        /* Update my configEpoch to the epoch of the election. */\n        if (myself->configEpoch < server.cluster->failover_auth_epoch) {\n            myself->configEpoch = server.cluster->failover_auth_epoch;\n            serverLog(LL_WARNING,\n                \"configEpoch set to %llu after successful failover\",\n                (unsigned long long) myself->configEpoch);\n        }\n\n        /* Take responsability for the cluster slots. */\n        clusterFailoverReplaceYourMaster();\n    } else {\n        clusterLogCantFailover(CLUSTER_CANT_FAILOVER_WAITING_VOTES);\n    }\n}\n\n/* -----------------------------------------------------------------------------\n * CLUSTER slave migration\n *\n * Slave migration is the process that allows a slave of a master that is\n * already covered by at least another slave, to \"migrate\" to a master that\n * is orpaned, that is, left with no working slaves.\n * ------------------------------------------------------------------------- */\n\n/* This function is responsible to decide if this replica should be migrated\n * to a different (orphaned) master. It is called by the clusterCron() function\n * only if:\n *\n * 1) We are a slave node.\n * 2) It was detected that there is at least one orphaned master in\n *    the cluster.\n * 3) We are a slave of one of the masters with the greatest number of\n *    slaves.\n *\n * This checks are performed by the caller since it requires to iterate\n * the nodes anyway, so we spend time into clusterHandleSlaveMigration()\n * if definitely needed.\n *\n * The fuction is called with a pre-computed max_slaves, that is the max\n * number of working (not in FAIL state) slaves for a single master.\n *\n * Additional conditions for migration are examined inside the function.\n */\nvoid clusterHandleSlaveMigration(int max_slaves) {\n    int j, okslaves = 0;\n    clusterNode *mymaster = myself->slaveof, *target = NULL, *candidate = NULL;\n    dictIterator *di;\n    dictEntry *de;\n\n    /* Step 1: Don't migrate if the cluster state is not ok. */\n    if (server.cluster->state != CLUSTER_OK) return;\n\n    /* Step 2: Don't migrate if my master will not be left with at least\n     *         'migration-barrier' slaves after my migration. */\n    if (mymaster == NULL) return;\n    for (j = 0; j < mymaster->numslaves; j++)\n        if (!nodeFailed(mymaster->slaves[j]) &&\n            !nodeTimedOut(mymaster->slaves[j])) okslaves++;\n    if (okslaves <= server.cluster_migration_barrier) return;\n\n    /* Step 3: Idenitfy a candidate for migration, and check if among the\n     * masters with the greatest number of ok slaves, I'm the one with the\n     * smallest node ID (the \"candidate slave\").\n     *\n     * Note: this means that eventually a replica migration will occurr\n     * since slaves that are reachable again always have their FAIL flag\n     * cleared, so eventually there must be a candidate. At the same time\n     * this does not mean that there are no race conditions possible (two\n     * slaves migrating at the same time), but this is unlikely to\n     * happen, and harmless when happens. */\n    candidate = myself;\n    di = dictGetSafeIterator(server.cluster->nodes);\n    while((de = dictNext(di)) != NULL) {\n        clusterNode *node = dictGetVal(de);\n        int okslaves = 0, is_orphaned = 1;\n\n        /* We want to migrate only if this master is working, orphaned, and\n         * used to have slaves or if failed over a master that had slaves\n         * (MIGRATE_TO flag). This way we only migrate to instances that were\n         * supposed to have replicas. */\n        if (nodeIsSlave(node) || nodeFailed(node)) is_orphaned = 0;\n        if (!(node->flags & CLUSTER_NODE_MIGRATE_TO)) is_orphaned = 0;\n\n        /* Check number of working slaves. */\n        if (nodeIsMaster(node)) okslaves = clusterCountNonFailingSlaves(node);\n        if (okslaves > 0) is_orphaned = 0;\n\n        if (is_orphaned) {\n            if (!target && node->numslots > 0) target = node;\n\n            /* Track the starting time of the orphaned condition for this\n             * master. */\n            if (!node->orphaned_time) node->orphaned_time = mstime();\n        } else {\n            node->orphaned_time = 0;\n        }\n\n        /* Check if I'm the slave candidate for the migration: attached\n         * to a master with the maximum number of slaves and with the smallest\n         * node ID. */\n        if (okslaves == max_slaves) {\n            for (j = 0; j < node->numslaves; j++) {\n                if (memcmp(node->slaves[j]->name,\n                           candidate->name,\n                           CLUSTER_NAMELEN) < 0)\n                {\n                    candidate = node->slaves[j];\n                }\n            }\n        }\n    }\n    dictReleaseIterator(di);\n\n    /* Step 4: perform the migration if there is a target, and if I'm the\n     * candidate, but only if the master is continuously orphaned for a\n     * couple of seconds, so that during failovers, we give some time to\n     * the natural slaves of this instance to advertise their switch from\n     * the old master to the new one. */\n    if (target && candidate == myself &&\n        (mstime()-target->orphaned_time) > CLUSTER_SLAVE_MIGRATION_DELAY)\n    {\n        serverLog(LL_WARNING,\"Migrating to orphaned master %.40s\",\n            target->name);\n        clusterSetMaster(target);\n    }\n}\n\n/* -----------------------------------------------------------------------------\n * CLUSTER manual failover\n *\n * This are the important steps performed by slaves during a manual failover:\n * 1) User send CLUSTER FAILOVER command. The failover state is initialized\n *    setting mf_end to the millisecond unix time at which we'll abort the\n *    attempt.\n * 2) Slave sends a MFSTART message to the master requesting to pause clients\n *    for two times the manual failover timeout CLUSTER_MF_TIMEOUT.\n *    When master is paused for manual failover, it also starts to flag\n *    packets with CLUSTERMSG_FLAG0_PAUSED.\n * 3) Slave waits for master to send its replication offset flagged as PAUSED.\n * 4) If slave received the offset from the master, and its offset matches,\n *    mf_can_start is set to 1, and clusterHandleSlaveFailover() will perform\n *    the failover as usually, with the difference that the vote request\n *    will be modified to force masters to vote for a slave that has a\n *    working master.\n *\n * From the point of view of the master things are simpler: when a\n * PAUSE_CLIENTS packet is received the master sets mf_end as well and\n * the sender in mf_slave. During the time limit for the manual failover\n * the master will just send PINGs more often to this slave, flagged with\n * the PAUSED flag, so that the slave will set mf_master_offset when receiving\n * a packet from the master with this flag set.\n *\n * The gaol of the manual failover is to perform a fast failover without\n * data loss due to the asynchronous master-slave replication.\n * -------------------------------------------------------------------------- */\n\n/* Reset the manual failover state. This works for both masters and slavesa\n * as all the state about manual failover is cleared.\n *\n * The function can be used both to initialize the manual failover state at\n * startup or to abort a manual failover in progress. */\nvoid resetManualFailover(void) {\n    if (server.cluster->mf_end && clientsArePaused()) {\n        server.clients_pause_end_time = 0;\n        clientsArePaused(); /* Just use the side effect of the function. */\n    }\n    server.cluster->mf_end = 0; /* No manual failover in progress. */\n    server.cluster->mf_can_start = 0;\n    server.cluster->mf_slave = NULL;\n    server.cluster->mf_master_offset = 0;\n}\n\n/* If a manual failover timed out, abort it. */\nvoid manualFailoverCheckTimeout(void) {\n    if (server.cluster->mf_end && server.cluster->mf_end < mstime()) {\n        serverLog(LL_WARNING,\"Manual failover timed out.\");\n        resetManualFailover();\n    }\n}\n\n/* This function is called from the cluster cron function in order to go\n * forward with a manual failover state machine. */\nvoid clusterHandleManualFailover(void) {\n    /* Return ASAP if no manual failover is in progress. */\n    if (server.cluster->mf_end == 0) return;\n\n    /* If mf_can_start is non-zero, the failover was already triggered so the\n     * next steps are performed by clusterHandleSlaveFailover(). */\n    if (server.cluster->mf_can_start) return;\n\n    if (server.cluster->mf_master_offset == 0) return; /* Wait for offset... */\n\n    if (server.cluster->mf_master_offset == replicationGetSlaveOffset()) {\n        /* Our replication offset matches the master replication offset\n         * announced after clients were paused. We can start the failover. */\n        server.cluster->mf_can_start = 1;\n        serverLog(LL_WARNING,\n            \"All master replication stream processed, \"\n            \"manual failover can start.\");\n    }\n}\n\n/* -----------------------------------------------------------------------------\n * CLUSTER cron job\n * -------------------------------------------------------------------------- */\n\n/* This is executed 10 times every second */\nvoid clusterCron(void) {\n    dictIterator *di;\n    dictEntry *de;\n    int update_state = 0;\n    int orphaned_masters; /* How many masters there are without ok slaves. */\n    int max_slaves; /* Max number of ok slaves for a single master. */\n    int this_slaves; /* Number of ok slaves for our master (if we are slave). */\n    mstime_t min_pong = 0, now = mstime();\n    clusterNode *min_pong_node = NULL;\n    static unsigned long long iteration = 0;\n    mstime_t handshake_timeout;\n\n    iteration++; /* Number of times this function was called so far. */\n\n    /* The handshake timeout is the time after which a handshake node that was\n     * not turned into a normal node is removed from the nodes. Usually it is\n     * just the NODE_TIMEOUT value, but when NODE_TIMEOUT is too small we use\n     * the value of 1 second. */\n    handshake_timeout = server.cluster_node_timeout;\n    if (handshake_timeout < 1000) handshake_timeout = 1000;\n\n    /* Check if we have disconnected nodes and re-establish the connection. */\n    di = dictGetSafeIterator(server.cluster->nodes);\n    while((de = dictNext(di)) != NULL) {\n        clusterNode *node = dictGetVal(de);\n\n        if (node->flags & (CLUSTER_NODE_MYSELF|CLUSTER_NODE_NOADDR)) continue;\n\n        /* A Node in HANDSHAKE state has a limited lifespan equal to the\n         * configured node timeout. */\n        if (nodeInHandshake(node) && now - node->ctime > handshake_timeout) {\n            clusterDelNode(node);\n            continue;\n        }\n\n        if (node->link == NULL) {\n            int fd;\n            mstime_t old_ping_sent;\n            clusterLink *link;\n\n            fd = anetTcpNonBlockBindConnect(server.neterr, node->ip,\n                node->port+CLUSTER_PORT_INCR, NET_FIRST_BIND_ADDR);\n            if (fd == -1) {\n                /* We got a synchronous error from connect before\n                 * clusterSendPing() had a chance to be called.\n                 * If node->ping_sent is zero, failure detection can't work,\n                 * so we claim we actually sent a ping now (that will\n                 * be really sent as soon as the link is obtained). */\n                if (node->ping_sent == 0) node->ping_sent = mstime();\n                serverLog(LL_DEBUG, \"Unable to connect to \"\n                    \"Cluster Node [%s]:%d -> %s\", node->ip,\n                    node->port+CLUSTER_PORT_INCR,\n                    server.neterr);\n                continue;\n            }\n            link = createClusterLink(node);\n            link->fd = fd;\n            node->link = link;\n            aeCreateFileEvent(server.el,link->fd,AE_READABLE,\n                    clusterReadHandler,link);\n            /* Queue a PING in the new connection ASAP: this is crucial\n             * to avoid false positives in failure detection.\n             *\n             * If the node is flagged as MEET, we send a MEET message instead\n             * of a PING one, to force the receiver to add us in its node\n             * table. */\n            old_ping_sent = node->ping_sent;\n            clusterSendPing(link, node->flags & CLUSTER_NODE_MEET ?\n                    CLUSTERMSG_TYPE_MEET : CLUSTERMSG_TYPE_PING);\n            if (old_ping_sent) {\n                /* If there was an active ping before the link was\n                 * disconnected, we want to restore the ping time, otherwise\n                 * replaced by the clusterSendPing() call. */\n                node->ping_sent = old_ping_sent;\n            }\n            /* We can clear the flag after the first packet is sent.\n             * If we'll never receive a PONG, we'll never send new packets\n             * to this node. Instead after the PONG is received and we\n             * are no longer in meet/handshake status, we want to send\n             * normal PING packets. */\n            node->flags &= ~CLUSTER_NODE_MEET;\n\n            serverLog(LL_DEBUG,\"Connecting with Node %.40s at %s:%d\",\n                    node->name, node->ip, node->port+CLUSTER_PORT_INCR);\n        }\n    }\n    dictReleaseIterator(di);\n\n    /* Ping some random node 1 time every 10 iterations, so that we usually ping\n     * one random node every second. */\n    if (!(iteration % 10)) {\n        int j;\n\n        /* Check a few random nodes and ping the one with the oldest\n         * pong_received time. */\n        for (j = 0; j < 5; j++) {\n            de = dictGetRandomKey(server.cluster->nodes);\n            clusterNode *this = dictGetVal(de);\n\n            /* Don't ping nodes disconnected or with a ping currently active. */\n            if (this->link == NULL || this->ping_sent != 0) continue;\n            if (this->flags & (CLUSTER_NODE_MYSELF|CLUSTER_NODE_HANDSHAKE))\n                continue;\n            if (min_pong_node == NULL || min_pong > this->pong_received) {\n                min_pong_node = this;\n                min_pong = this->pong_received;\n            }\n        }\n        if (min_pong_node) {\n            serverLog(LL_DEBUG,\"Pinging node %.40s\", min_pong_node->name);\n            clusterSendPing(min_pong_node->link, CLUSTERMSG_TYPE_PING);\n        }\n    }\n\n    /* Iterate nodes to check if we need to flag something as failing.\n     * This loop is also responsible to:\n     * 1) Check if there are orphaned masters (masters without non failing\n     *    slaves).\n     * 2) Count the max number of non failing slaves for a single master.\n     * 3) Count the number of slaves for our master, if we are a slave. */\n    orphaned_masters = 0;\n    max_slaves = 0;\n    this_slaves = 0;\n    di = dictGetSafeIterator(server.cluster->nodes);\n    while((de = dictNext(di)) != NULL) {\n        clusterNode *node = dictGetVal(de);\n        now = mstime(); /* Use an updated time at every iteration. */\n        mstime_t delay;\n\n        if (node->flags &\n            (CLUSTER_NODE_MYSELF|CLUSTER_NODE_NOADDR|CLUSTER_NODE_HANDSHAKE))\n                continue;\n\n        /* Orphaned master check, useful only if the current instance\n         * is a slave that may migrate to another master. */\n        if (nodeIsSlave(myself) && nodeIsMaster(node) && !nodeFailed(node)) {\n            int okslaves = clusterCountNonFailingSlaves(node);\n\n            /* A master is orphaned if it is serving a non-zero number of\n             * slots, have no working slaves, but used to have at least one\n             * slave, or failed over a master that used to have slaves. */\n            if (okslaves == 0 && node->numslots > 0 &&\n                node->flags & CLUSTER_NODE_MIGRATE_TO)\n            {\n                orphaned_masters++;\n            }\n            if (okslaves > max_slaves) max_slaves = okslaves;\n            if (nodeIsSlave(myself) && myself->slaveof == node)\n                this_slaves = okslaves;\n        }\n\n        /* If we are waiting for the PONG more than half the cluster\n         * timeout, reconnect the link: maybe there is a connection\n         * issue even if the node is alive. */\n        if (node->link && /* is connected */\n            now - node->link->ctime >\n            server.cluster_node_timeout && /* was not already reconnected */\n            node->ping_sent && /* we already sent a ping */\n            node->pong_received < node->ping_sent && /* still waiting pong */\n            /* and we are waiting for the pong more than timeout/2 */\n            now - node->ping_sent > server.cluster_node_timeout/2)\n        {\n            /* Disconnect the link, it will be reconnected automatically. */\n            freeClusterLink(node->link);\n        }\n\n        /* If we have currently no active ping in this instance, and the\n         * received PONG is older than half the cluster timeout, send\n         * a new ping now, to ensure all the nodes are pinged without\n         * a too big delay. */\n        if (node->link &&\n            node->ping_sent == 0 &&\n            (now - node->pong_received) > server.cluster_node_timeout/2)\n        {\n            clusterSendPing(node->link, CLUSTERMSG_TYPE_PING);\n            continue;\n        }\n\n        /* If we are a master and one of the slaves requested a manual\n         * failover, ping it continuously. */\n        if (server.cluster->mf_end &&\n            nodeIsMaster(myself) &&\n            server.cluster->mf_slave == node &&\n            node->link)\n        {\n            clusterSendPing(node->link, CLUSTERMSG_TYPE_PING);\n            continue;\n        }\n\n        /* Check only if we have an active ping for this instance. */\n        if (node->ping_sent == 0) continue;\n\n        /* Compute the delay of the PONG. Note that if we already received\n         * the PONG, then node->ping_sent is zero, so can't reach this\n         * code at all. */\n        delay = now - node->ping_sent;\n\n        if (delay > server.cluster_node_timeout) {\n            /* Timeout reached. Set the node as possibly failing if it is\n             * not already in this state. */\n            if (!(node->flags & (CLUSTER_NODE_PFAIL|CLUSTER_NODE_FAIL))) {\n                serverLog(LL_DEBUG,\"*** NODE %.40s possibly failing\",\n                    node->name);\n                node->flags |= CLUSTER_NODE_PFAIL;\n                update_state = 1;\n            }\n        }\n    }\n    dictReleaseIterator(di);\n\n    /* If we are a slave node but the replication is still turned off,\n     * enable it if we know the address of our master and it appears to\n     * be up. */\n    if (nodeIsSlave(myself) &&\n        server.masterhost == NULL &&\n        myself->slaveof &&\n        nodeHasAddr(myself->slaveof))\n    {\n        replicationSetMaster(myself->slaveof->ip, myself->slaveof->port);\n    }\n\n    /* Abourt a manual failover if the timeout is reached. */\n    manualFailoverCheckTimeout();\n\n    if (nodeIsSlave(myself)) {\n        clusterHandleManualFailover();\n        clusterHandleSlaveFailover();\n        /* If there are orphaned slaves, and we are a slave among the masters\n         * with the max number of non-failing slaves, consider migrating to\n         * the orphaned masters. Note that it does not make sense to try\n         * a migration if there is no master with at least *two* working\n         * slaves. */\n        if (orphaned_masters && max_slaves >= 2 && this_slaves == max_slaves)\n            clusterHandleSlaveMigration(max_slaves);\n    }\n\n    if (update_state || server.cluster->state == CLUSTER_FAIL)\n        clusterUpdateState();\n}\n\n/* This function is called before the event handler returns to sleep for\n * events. It is useful to perform operations that must be done ASAP in\n * reaction to events fired but that are not safe to perform inside event\n * handlers, or to perform potentially expansive tasks that we need to do\n * a single time before replying to clients. */\nvoid clusterBeforeSleep(void) {\n    /* Handle failover, this is needed when it is likely that there is already\n     * the quorum from masters in order to react fast. */\n    if (server.cluster->todo_before_sleep & CLUSTER_TODO_HANDLE_FAILOVER)\n        clusterHandleSlaveFailover();\n\n    /* Update the cluster state. */\n    if (server.cluster->todo_before_sleep & CLUSTER_TODO_UPDATE_STATE)\n        clusterUpdateState();\n\n    /* Save the config, possibly using fsync. */\n    if (server.cluster->todo_before_sleep & CLUSTER_TODO_SAVE_CONFIG) {\n        int fsync = server.cluster->todo_before_sleep &\n                    CLUSTER_TODO_FSYNC_CONFIG;\n        clusterSaveConfigOrDie(fsync);\n    }\n\n    /* Reset our flags (not strictly needed since every single function\n     * called for flags set should be able to clear its flag). */\n    server.cluster->todo_before_sleep = 0;\n}\n\nvoid clusterDoBeforeSleep(int flags) {\n    server.cluster->todo_before_sleep |= flags;\n}\n\n/* -----------------------------------------------------------------------------\n * Slots management\n * -------------------------------------------------------------------------- */\n\n/* Test bit 'pos' in a generic bitmap. Return 1 if the bit is set,\n * otherwise 0. */\nint bitmapTestBit(unsigned char *bitmap, int pos) {\n    off_t byte = pos/8;\n    int bit = pos&7;\n    return (bitmap[byte] & (1<<bit)) != 0;\n}\n\n/* Set the bit at position 'pos' in a bitmap. */\nvoid bitmapSetBit(unsigned char *bitmap, int pos) {\n    off_t byte = pos/8;\n    int bit = pos&7;\n    bitmap[byte] |= 1<<bit;\n}\n\n/* Clear the bit at position 'pos' in a bitmap. */\nvoid bitmapClearBit(unsigned char *bitmap, int pos) {\n    off_t byte = pos/8;\n    int bit = pos&7;\n    bitmap[byte] &= ~(1<<bit);\n}\n\n/* Return non-zero if there is at least one master with slaves in the cluster.\n * Otherwise zero is returned. Used by clusterNodeSetSlotBit() to set the\n * MIGRATE_TO flag the when a master gets the first slot. */\nint clusterMastersHaveSlaves(void) {\n    dictIterator *di = dictGetSafeIterator(server.cluster->nodes);\n    dictEntry *de;\n    int slaves = 0;\n    while((de = dictNext(di)) != NULL) {\n        clusterNode *node = dictGetVal(de);\n\n        if (nodeIsSlave(node)) continue;\n        slaves += node->numslaves;\n    }\n    dictReleaseIterator(di);\n    return slaves != 0;\n}\n\n/* Set the slot bit and return the old value. */\nint clusterNodeSetSlotBit(clusterNode *n, int slot) {\n    int old = bitmapTestBit(n->slots,slot);\n    bitmapSetBit(n->slots,slot);\n    if (!old) {\n        n->numslots++;\n        /* When a master gets its first slot, even if it has no slaves,\n         * it gets flagged with MIGRATE_TO, that is, the master is a valid\n         * target for replicas migration, if and only if at least one of\n         * the other masters has slaves right now.\n         *\n         * Normally masters are valid targerts of replica migration if:\n         * 1. The used to have slaves (but no longer have).\n         * 2. They are slaves failing over a master that used to have slaves.\n         *\n         * However new masters with slots assigned are considered valid\n         * migration tagets if the rest of the cluster is not a slave-less.\n         *\n         * See https://github.com/antirez/redis/issues/3043 for more info. */\n        if (n->numslots == 1 && clusterMastersHaveSlaves())\n            n->flags |= CLUSTER_NODE_MIGRATE_TO;\n    }\n    return old;\n}\n\n/* Clear the slot bit and return the old value. */\nint clusterNodeClearSlotBit(clusterNode *n, int slot) {\n    int old = bitmapTestBit(n->slots,slot);\n    bitmapClearBit(n->slots,slot);\n    if (old) n->numslots--;\n    return old;\n}\n\n/* Return the slot bit from the cluster node structure. */\nint clusterNodeGetSlotBit(clusterNode *n, int slot) {\n    return bitmapTestBit(n->slots,slot);\n}\n\n/* Add the specified slot to the list of slots that node 'n' will\n * serve. Return C_OK if the operation ended with success.\n * If the slot is already assigned to another instance this is considered\n * an error and C_ERR is returned. */\nint clusterAddSlot(clusterNode *n, int slot) {\n    if (server.cluster->slots[slot]) return C_ERR;\n    clusterNodeSetSlotBit(n,slot);\n    server.cluster->slots[slot] = n;\n    return C_OK;\n}\n\n/* Delete the specified slot marking it as unassigned.\n * Returns C_OK if the slot was assigned, otherwise if the slot was\n * already unassigned C_ERR is returned. */\nint clusterDelSlot(int slot) {\n    clusterNode *n = server.cluster->slots[slot];\n\n    if (!n) return C_ERR;\n    serverAssert(clusterNodeClearSlotBit(n,slot) == 1);\n    server.cluster->slots[slot] = NULL;\n    return C_OK;\n}\n\n/* Delete all the slots associated with the specified node.\n * The number of deleted slots is returned. */\nint clusterDelNodeSlots(clusterNode *node) {\n    int deleted = 0, j;\n\n    for (j = 0; j < CLUSTER_SLOTS; j++) {\n        if (clusterNodeGetSlotBit(node,j)) clusterDelSlot(j);\n        deleted++;\n    }\n    return deleted;\n}\n\n/* Clear the migrating / importing state for all the slots.\n * This is useful at initialization and when turning a master into slave. */\nvoid clusterCloseAllSlots(void) {\n    memset(server.cluster->migrating_slots_to,0,\n        sizeof(server.cluster->migrating_slots_to));\n    memset(server.cluster->importing_slots_from,0,\n        sizeof(server.cluster->importing_slots_from));\n}\n\n/* -----------------------------------------------------------------------------\n * Cluster state evaluation function\n * -------------------------------------------------------------------------- */\n\n/* The following are defines that are only used in the evaluation function\n * and are based on heuristics. Actaully the main point about the rejoin and\n * writable delay is that they should be a few orders of magnitude larger\n * than the network latency. */\n#define CLUSTER_MAX_REJOIN_DELAY 5000\n#define CLUSTER_MIN_REJOIN_DELAY 500\n#define CLUSTER_WRITABLE_DELAY 2000\n\nvoid clusterUpdateState(void) {\n    int j, new_state;\n    int reachable_masters = 0;\n    static mstime_t among_minority_time;\n    static mstime_t first_call_time = 0;\n\n    server.cluster->todo_before_sleep &= ~CLUSTER_TODO_UPDATE_STATE;\n\n    /* If this is a master node, wait some time before turning the state\n     * into OK, since it is not a good idea to rejoin the cluster as a writable\n     * master, after a reboot, without giving the cluster a chance to\n     * reconfigure this node. Note that the delay is calculated starting from\n     * the first call to this function and not since the server start, in order\n     * to don't count the DB loading time. */\n    if (first_call_time == 0) first_call_time = mstime();\n    if (nodeIsMaster(myself) &&\n        server.cluster->state == CLUSTER_FAIL &&\n        mstime() - first_call_time < CLUSTER_WRITABLE_DELAY) return;\n\n    /* Start assuming the state is OK. We'll turn it into FAIL if there\n     * are the right conditions. */\n    new_state = CLUSTER_OK;\n\n    /* Check if all the slots are covered. */\n    if (server.cluster_require_full_coverage) {\n        for (j = 0; j < CLUSTER_SLOTS; j++) {\n            if (server.cluster->slots[j] == NULL ||\n                server.cluster->slots[j]->flags & (CLUSTER_NODE_FAIL))\n            {\n                new_state = CLUSTER_FAIL;\n                break;\n            }\n        }\n    }\n\n    /* Compute the cluster size, that is the number of master nodes\n     * serving at least a single slot.\n     *\n     * At the same time count the number of reachable masters having\n     * at least one slot. */\n    {\n        dictIterator *di;\n        dictEntry *de;\n\n        server.cluster->size = 0;\n        di = dictGetSafeIterator(server.cluster->nodes);\n        while((de = dictNext(di)) != NULL) {\n            clusterNode *node = dictGetVal(de);\n\n            if (nodeIsMaster(node) && node->numslots) {\n                server.cluster->size++;\n                if ((node->flags & (CLUSTER_NODE_FAIL|CLUSTER_NODE_PFAIL)) == 0)\n                    reachable_masters++;\n            }\n        }\n        dictReleaseIterator(di);\n    }\n\n    /* If we are in a minority partition, change the cluster state\n     * to FAIL. */\n    {\n        int needed_quorum = (server.cluster->size / 2) + 1;\n\n        if (reachable_masters < needed_quorum) {\n            new_state = CLUSTER_FAIL;\n            among_minority_time = mstime();\n        }\n    }\n\n    /* Log a state change */\n    if (new_state != server.cluster->state) {\n        mstime_t rejoin_delay = server.cluster_node_timeout;\n\n        /* If the instance is a master and was partitioned away with the\n         * minority, don't let it accept queries for some time after the\n         * partition heals, to make sure there is enough time to receive\n         * a configuration update. */\n        if (rejoin_delay > CLUSTER_MAX_REJOIN_DELAY)\n            rejoin_delay = CLUSTER_MAX_REJOIN_DELAY;\n        if (rejoin_delay < CLUSTER_MIN_REJOIN_DELAY)\n            rejoin_delay = CLUSTER_MIN_REJOIN_DELAY;\n\n        if (new_state == CLUSTER_OK &&\n            nodeIsMaster(myself) &&\n            mstime() - among_minority_time < rejoin_delay)\n        {\n            return;\n        }\n\n        /* Change the state and log the event. */\n        serverLog(LL_WARNING,\"Cluster state changed: %s\",\n            new_state == CLUSTER_OK ? \"ok\" : \"fail\");\n        server.cluster->state = new_state;\n    }\n}\n\n/* This function is called after the node startup in order to verify that data\n * loaded from disk is in agreement with the cluster configuration:\n *\n * 1) If we find keys about hash slots we have no responsibility for, the\n *    following happens:\n *    A) If no other node is in charge according to the current cluster\n *       configuration, we add these slots to our node.\n *    B) If according to our config other nodes are already in charge for\n *       this lots, we set the slots as IMPORTING from our point of view\n *       in order to justify we have those slots, and in order to make\n *       redis-trib aware of the issue, so that it can try to fix it.\n * 2) If we find data in a DB different than DB0 we return C_ERR to\n *    signal the caller it should quit the server with an error message\n *    or take other actions.\n *\n * The function always returns C_OK even if it will try to correct\n * the error described in \"1\". However if data is found in DB different\n * from DB0, C_ERR is returned.\n *\n * The function also uses the logging facility in order to warn the user\n * about desynchronizations between the data we have in memory and the\n * cluster configuration. */\nint verifyClusterConfigWithData(void) {\n    int j;\n    int update_config = 0;\n\n    /* If this node is a slave, don't perform the check at all as we\n     * completely depend on the replication stream. */\n    if (nodeIsSlave(myself)) return C_OK;\n\n    /* Make sure we only have keys in DB0. */\n    for (j = 1; j < server.dbnum; j++) {\n        if (dictSize(server.db[j].dict)) return C_ERR;\n    }\n\n    /* Check that all the slots we see populated memory have a corresponding\n     * entry in the cluster table. Otherwise fix the table. */\n    for (j = 0; j < CLUSTER_SLOTS; j++) {\n        if (!countKeysInSlot(j)) continue; /* No keys in this slot. */\n        /* Check if we are assigned to this slot or if we are importing it.\n         * In both cases check the next slot as the configuration makes\n         * sense. */\n        if (server.cluster->slots[j] == myself ||\n            server.cluster->importing_slots_from[j] != NULL) continue;\n\n        /* If we are here data and cluster config don't agree, and we have\n         * slot 'j' populated even if we are not importing it, nor we are\n         * assigned to this slot. Fix this condition. */\n\n        update_config++;\n        /* Case A: slot is unassigned. Take responsibility for it. */\n        if (server.cluster->slots[j] == NULL) {\n            serverLog(LL_WARNING, \"I have keys for unassigned slot %d. \"\n                                    \"Taking responsibility for it.\",j);\n            clusterAddSlot(myself,j);\n        } else {\n            serverLog(LL_WARNING, \"I have keys for slot %d, but the slot is \"\n                                    \"assigned to another node. \"\n                                    \"Setting it to importing state.\",j);\n            server.cluster->importing_slots_from[j] = server.cluster->slots[j];\n        }\n    }\n    if (update_config) clusterSaveConfigOrDie(1);\n    return C_OK;\n}\n\n/* -----------------------------------------------------------------------------\n * SLAVE nodes handling\n * -------------------------------------------------------------------------- */\n\n/* Set the specified node 'n' as master for this node.\n * If this node is currently a master, it is turned into a slave. */\nvoid clusterSetMaster(clusterNode *n) {\n    serverAssert(n != myself);\n    serverAssert(myself->numslots == 0);\n\n    if (nodeIsMaster(myself)) {\n        myself->flags &= ~(CLUSTER_NODE_MASTER|CLUSTER_NODE_MIGRATE_TO);\n        myself->flags |= CLUSTER_NODE_SLAVE;\n        clusterCloseAllSlots();\n    } else {\n        if (myself->slaveof)\n            clusterNodeRemoveSlave(myself->slaveof,myself);\n    }\n    myself->slaveof = n;\n    clusterNodeAddSlave(n,myself);\n    replicationSetMaster(n->ip, n->port);\n    resetManualFailover();\n}\n\n/* -----------------------------------------------------------------------------\n * Nodes to string representation functions.\n * -------------------------------------------------------------------------- */\n\nstruct redisNodeFlags {\n    uint16_t flag;\n    char *name;\n};\n\nstatic struct redisNodeFlags redisNodeFlagsTable[] = {\n    {CLUSTER_NODE_MYSELF,       \"myself,\"},\n    {CLUSTER_NODE_MASTER,       \"master,\"},\n    {CLUSTER_NODE_SLAVE,        \"slave,\"},\n    {CLUSTER_NODE_PFAIL,        \"fail?,\"},\n    {CLUSTER_NODE_FAIL,         \"fail,\"},\n    {CLUSTER_NODE_HANDSHAKE,    \"handshake,\"},\n    {CLUSTER_NODE_NOADDR,       \"noaddr,\"}\n};\n\n/* Concatenate the comma separated list of node flags to the given SDS\n * string 'ci'. */\nsds representClusterNodeFlags(sds ci, uint16_t flags) {\n    if (flags == 0) {\n        ci = sdscat(ci,\"noflags,\");\n    } else {\n        int i, size = sizeof(redisNodeFlagsTable)/sizeof(struct redisNodeFlags);\n        for (i = 0; i < size; i++) {\n            struct redisNodeFlags *nodeflag = redisNodeFlagsTable + i;\n            if (flags & nodeflag->flag) ci = sdscat(ci, nodeflag->name);\n        }\n    }\n    sdsIncrLen(ci,-1); /* Remove trailing comma. */\n    return ci;\n}\n\n/* Generate a csv-alike representation of the specified cluster node.\n * See clusterGenNodesDescription() top comment for more information.\n *\n * The function returns the string representation as an SDS string. */\nsds clusterGenNodeDescription(clusterNode *node) {\n    int j, start;\n    sds ci;\n\n    /* Node coordinates */\n    ci = sdscatprintf(sdsempty(),\"%.40s %s:%d \",\n        node->name,\n        node->ip,\n        node->port);\n\n    /* Flags */\n    ci = representClusterNodeFlags(ci, node->flags);\n\n    /* Slave of... or just \"-\" */\n    if (node->slaveof)\n        ci = sdscatprintf(ci,\" %.40s \",node->slaveof->name);\n    else\n        ci = sdscatlen(ci,\" - \",3);\n\n    /* Latency from the POV of this node, config epoch, link status */\n    ci = sdscatprintf(ci,\"%lld %lld %llu %s\",\n        (long long) node->ping_sent,\n        (long long) node->pong_received,\n        (unsigned long long) node->configEpoch,\n        (node->link || node->flags & CLUSTER_NODE_MYSELF) ?\n                    \"connected\" : \"disconnected\");\n\n    /* Slots served by this instance */\n    start = -1;\n    for (j = 0; j < CLUSTER_SLOTS; j++) {\n        int bit;\n\n        if ((bit = clusterNodeGetSlotBit(node,j)) != 0) {\n            if (start == -1) start = j;\n        }\n        if (start != -1 && (!bit || j == CLUSTER_SLOTS-1)) {\n            if (bit && j == CLUSTER_SLOTS-1) j++;\n\n            if (start == j-1) {\n                ci = sdscatprintf(ci,\" %d\",start);\n            } else {\n                ci = sdscatprintf(ci,\" %d-%d\",start,j-1);\n            }\n            start = -1;\n        }\n    }\n\n    /* Just for MYSELF node we also dump info about slots that\n     * we are migrating to other instances or importing from other\n     * instances. */\n    if (node->flags & CLUSTER_NODE_MYSELF) {\n        for (j = 0; j < CLUSTER_SLOTS; j++) {\n            if (server.cluster->migrating_slots_to[j]) {\n                ci = sdscatprintf(ci,\" [%d->-%.40s]\",j,\n                    server.cluster->migrating_slots_to[j]->name);\n            } else if (server.cluster->importing_slots_from[j]) {\n                ci = sdscatprintf(ci,\" [%d-<-%.40s]\",j,\n                    server.cluster->importing_slots_from[j]->name);\n            }\n        }\n    }\n    return ci;\n}\n\n/* Generate a csv-alike representation of the nodes we are aware of,\n * including the \"myself\" node, and return an SDS string containing the\n * representation (it is up to the caller to free it).\n *\n * All the nodes matching at least one of the node flags specified in\n * \"filter\" are excluded from the output, so using zero as a filter will\n * include all the known nodes in the representation, including nodes in\n * the HANDSHAKE state.\n *\n * The representation obtained using this function is used for the output\n * of the CLUSTER NODES function, and as format for the cluster\n * configuration file (nodes.conf) for a given node. */\nsds clusterGenNodesDescription(int filter) {\n    sds ci = sdsempty(), ni;\n    dictIterator *di;\n    dictEntry *de;\n\n    di = dictGetSafeIterator(server.cluster->nodes);\n    while((de = dictNext(di)) != NULL) {\n        clusterNode *node = dictGetVal(de);\n\n        if (node->flags & filter) continue;\n        ni = clusterGenNodeDescription(node);\n        ci = sdscatsds(ci,ni);\n        sdsfree(ni);\n        ci = sdscatlen(ci,\"\\n\",1);\n    }\n    dictReleaseIterator(di);\n    return ci;\n}\n\n/* -----------------------------------------------------------------------------\n * CLUSTER command\n * -------------------------------------------------------------------------- */\n\nint getSlotOrReply(client *c, robj *o) {\n    long long slot;\n\n    if (getLongLongFromObject(o,&slot) != C_OK ||\n        slot < 0 || slot >= CLUSTER_SLOTS)\n    {\n        addReplyError(c,\"Invalid or out of range slot\");\n        return -1;\n    }\n    return (int) slot;\n}\n\nvoid clusterReplyMultiBulkSlots(client *c) {\n    /* Format: 1) 1) start slot\n     *            2) end slot\n     *            3) 1) master IP\n     *               2) master port\n     *               3) node ID\n     *            4) 1) replica IP\n     *               2) replica port\n     *               3) node ID\n     *           ... continued until done\n     */\n\n    int num_masters = 0;\n    void *slot_replylen = addDeferredMultiBulkLength(c);\n\n    dictEntry *de;\n    dictIterator *di = dictGetSafeIterator(server.cluster->nodes);\n    while((de = dictNext(di)) != NULL) {\n        clusterNode *node = dictGetVal(de);\n        int j = 0, start = -1;\n\n        /* Skip slaves (that are iterated when producing the output of their\n         * master) and  masters not serving any slot. */\n        if (!nodeIsMaster(node) || node->numslots == 0) continue;\n\n        for (j = 0; j < CLUSTER_SLOTS; j++) {\n            int bit, i;\n\n            if ((bit = clusterNodeGetSlotBit(node,j)) != 0) {\n                if (start == -1) start = j;\n            }\n            if (start != -1 && (!bit || j == CLUSTER_SLOTS-1)) {\n                int nested_elements = 3; /* slots (2) + master addr (1). */\n                void *nested_replylen = addDeferredMultiBulkLength(c);\n\n                if (bit && j == CLUSTER_SLOTS-1) j++;\n\n                /* If slot exists in output map, add to it's list.\n                 * else, create a new output map for this slot */\n                if (start == j-1) {\n                    addReplyLongLong(c, start); /* only one slot; low==high */\n                    addReplyLongLong(c, start);\n                } else {\n                    addReplyLongLong(c, start); /* low */\n                    addReplyLongLong(c, j-1);   /* high */\n                }\n                start = -1;\n\n                /* First node reply position is always the master */\n                addReplyMultiBulkLen(c, 3);\n                addReplyBulkCString(c, node->ip);\n                addReplyLongLong(c, node->port);\n                addReplyBulkCBuffer(c, node->name, CLUSTER_NAMELEN);\n\n                /* Remaining nodes in reply are replicas for slot range */\n                for (i = 0; i < node->numslaves; i++) {\n                    /* This loop is copy/pasted from clusterGenNodeDescription()\n                     * with modifications for per-slot node aggregation */\n                    if (nodeFailed(node->slaves[i])) continue;\n                    addReplyMultiBulkLen(c, 3);\n                    addReplyBulkCString(c, node->slaves[i]->ip);\n                    addReplyLongLong(c, node->slaves[i]->port);\n                    addReplyBulkCBuffer(c, node->slaves[i]->name, CLUSTER_NAMELEN);\n                    nested_elements++;\n                }\n                setDeferredMultiBulkLength(c, nested_replylen, nested_elements);\n                num_masters++;\n            }\n        }\n    }\n    dictReleaseIterator(di);\n    setDeferredMultiBulkLength(c, slot_replylen, num_masters);\n}\n\nvoid clusterCommand(client *c) {\n    if (server.cluster_enabled == 0) {\n        addReplyError(c,\"This instance has cluster support disabled\");\n        return;\n    }\n\n    if (!strcasecmp(c->argv[1]->ptr,\"meet\") && c->argc == 4) {\n        long long port;\n\n        if (getLongLongFromObject(c->argv[3], &port) != C_OK) {\n            addReplyErrorFormat(c,\"Invalid TCP port specified: %s\",\n                                (char*)c->argv[3]->ptr);\n            return;\n        }\n\n        if (clusterStartHandshake(c->argv[2]->ptr,port) == 0 &&\n            errno == EINVAL)\n        {\n            addReplyErrorFormat(c,\"Invalid node address specified: %s:%s\",\n                            (char*)c->argv[2]->ptr, (char*)c->argv[3]->ptr);\n        } else {\n            addReply(c,shared.ok);\n        }\n    } else if (!strcasecmp(c->argv[1]->ptr,\"nodes\") && c->argc == 2) {\n        /* CLUSTER NODES */\n        robj *o;\n        sds ci = clusterGenNodesDescription(0);\n\n        o = createObject(OBJ_STRING,ci);\n        addReplyBulk(c,o);\n        decrRefCount(o);\n    } else if (!strcasecmp(c->argv[1]->ptr,\"myid\") && c->argc == 2) {\n        /* CLUSTER MYID */\n        addReplyBulkCBuffer(c,myself->name, CLUSTER_NAMELEN);\n    } else if (!strcasecmp(c->argv[1]->ptr,\"slots\") && c->argc == 2) {\n        /* CLUSTER SLOTS */\n        clusterReplyMultiBulkSlots(c);\n    } else if (!strcasecmp(c->argv[1]->ptr,\"flushslots\") && c->argc == 2) {\n        /* CLUSTER FLUSHSLOTS */\n        if (dictSize(server.db[0].dict) != 0) {\n            addReplyError(c,\"DB must be empty to perform CLUSTER FLUSHSLOTS.\");\n            return;\n        }\n        clusterDelNodeSlots(myself);\n        clusterDoBeforeSleep(CLUSTER_TODO_UPDATE_STATE|CLUSTER_TODO_SAVE_CONFIG);\n        addReply(c,shared.ok);\n    } else if ((!strcasecmp(c->argv[1]->ptr,\"addslots\") ||\n               !strcasecmp(c->argv[1]->ptr,\"delslots\")) && c->argc >= 3)\n    {\n        /* CLUSTER ADDSLOTS <slot> [slot] ... */\n        /* CLUSTER DELSLOTS <slot> [slot] ... */\n        int j, slot;\n        unsigned char *slots = zmalloc(CLUSTER_SLOTS);\n        int del = !strcasecmp(c->argv[1]->ptr,\"delslots\");\n\n        memset(slots,0,CLUSTER_SLOTS);\n        /* Check that all the arguments are parseable and that all the\n         * slots are not already busy. */\n        for (j = 2; j < c->argc; j++) {\n            if ((slot = getSlotOrReply(c,c->argv[j])) == -1) {\n                zfree(slots);\n                return;\n            }\n            if (del && server.cluster->slots[slot] == NULL) {\n                addReplyErrorFormat(c,\"Slot %d is already unassigned\", slot);\n                zfree(slots);\n                return;\n            } else if (!del && server.cluster->slots[slot]) {\n                addReplyErrorFormat(c,\"Slot %d is already busy\", slot);\n                zfree(slots);\n                return;\n            }\n            if (slots[slot]++ == 1) {\n                addReplyErrorFormat(c,\"Slot %d specified multiple times\",\n                    (int)slot);\n                zfree(slots);\n                return;\n            }\n        }\n        for (j = 0; j < CLUSTER_SLOTS; j++) {\n            if (slots[j]) {\n                int retval;\n\n                /* If this slot was set as importing we can clear this\n                 * state as now we are the real owner of the slot. */\n                if (server.cluster->importing_slots_from[j])\n                    server.cluster->importing_slots_from[j] = NULL;\n\n                retval = del ? clusterDelSlot(j) :\n                               clusterAddSlot(myself,j);\n                serverAssertWithInfo(c,NULL,retval == C_OK);\n            }\n        }\n        zfree(slots);\n        clusterDoBeforeSleep(CLUSTER_TODO_UPDATE_STATE|CLUSTER_TODO_SAVE_CONFIG);\n        addReply(c,shared.ok);\n    } else if (!strcasecmp(c->argv[1]->ptr,\"setslot\") && c->argc >= 4) {\n        /* SETSLOT 10 MIGRATING <node ID> */\n        /* SETSLOT 10 IMPORTING <node ID> */\n        /* SETSLOT 10 STABLE */\n        /* SETSLOT 10 NODE <node ID> */\n        int slot;\n        clusterNode *n;\n\n        if (nodeIsSlave(myself)) {\n            addReplyError(c,\"Please use SETSLOT only with masters.\");\n            return;\n        }\n\n        if ((slot = getSlotOrReply(c,c->argv[2])) == -1) return;\n\n        if (!strcasecmp(c->argv[3]->ptr,\"migrating\") && c->argc == 5) {\n            if (server.cluster->slots[slot] != myself) {\n                addReplyErrorFormat(c,\"I'm not the owner of hash slot %u\",slot);\n                return;\n            }\n            if ((n = clusterLookupNode(c->argv[4]->ptr)) == NULL) {\n                addReplyErrorFormat(c,\"I don't know about node %s\",\n                    (char*)c->argv[4]->ptr);\n                return;\n            }\n            server.cluster->migrating_slots_to[slot] = n;\n        } else if (!strcasecmp(c->argv[3]->ptr,\"importing\") && c->argc == 5) {\n            if (server.cluster->slots[slot] == myself) {\n                addReplyErrorFormat(c,\n                    \"I'm already the owner of hash slot %u\",slot);\n                return;\n            }\n            if ((n = clusterLookupNode(c->argv[4]->ptr)) == NULL) {\n                addReplyErrorFormat(c,\"I don't know about node %s\",\n                    (char*)c->argv[3]->ptr);\n                return;\n            }\n            server.cluster->importing_slots_from[slot] = n;\n        } else if (!strcasecmp(c->argv[3]->ptr,\"stable\") && c->argc == 4) {\n            /* CLUSTER SETSLOT <SLOT> STABLE */\n            server.cluster->importing_slots_from[slot] = NULL;\n            server.cluster->migrating_slots_to[slot] = NULL;\n        } else if (!strcasecmp(c->argv[3]->ptr,\"node\") && c->argc == 5) {\n            /* CLUSTER SETSLOT <SLOT> NODE <NODE ID> */\n            clusterNode *n = clusterLookupNode(c->argv[4]->ptr);\n\n            if (!n) {\n                addReplyErrorFormat(c,\"Unknown node %s\",\n                    (char*)c->argv[4]->ptr);\n                return;\n            }\n            /* If this hash slot was served by 'myself' before to switch\n             * make sure there are no longer local keys for this hash slot. */\n            if (server.cluster->slots[slot] == myself && n != myself) {\n                if (countKeysInSlot(slot) != 0) {\n                    addReplyErrorFormat(c,\n                        \"Can't assign hashslot %d to a different node \"\n                        \"while I still hold keys for this hash slot.\", slot);\n                    return;\n                }\n            }\n            /* If this slot is in migrating status but we have no keys\n             * for it assigning the slot to another node will clear\n             * the migratig status. */\n            if (countKeysInSlot(slot) == 0 &&\n                server.cluster->migrating_slots_to[slot])\n                server.cluster->migrating_slots_to[slot] = NULL;\n\n            /* If this node was importing this slot, assigning the slot to\n             * itself also clears the importing status. */\n            if (n == myself &&\n                server.cluster->importing_slots_from[slot])\n            {\n                /* This slot was manually migrated, set this node configEpoch\n                 * to a new epoch so that the new version can be propagated\n                 * by the cluster.\n                 *\n                 * Note that if this ever results in a collision with another\n                 * node getting the same configEpoch, for example because a\n                 * failover happens at the same time we close the slot, the\n                 * configEpoch collision resolution will fix it assigning\n                 * a different epoch to each node. */\n                if (clusterBumpConfigEpochWithoutConsensus() == C_OK) {\n                    serverLog(LL_WARNING,\n                        \"configEpoch updated after importing slot %d\", slot);\n                }\n                server.cluster->importing_slots_from[slot] = NULL;\n            }\n            clusterDelSlot(slot);\n            clusterAddSlot(n,slot);\n        } else {\n            addReplyError(c,\n                \"Invalid CLUSTER SETSLOT action or number of arguments\");\n            return;\n        }\n        clusterDoBeforeSleep(CLUSTER_TODO_SAVE_CONFIG|CLUSTER_TODO_UPDATE_STATE);\n        addReply(c,shared.ok);\n    } else if (!strcasecmp(c->argv[1]->ptr,\"bumpepoch\") && c->argc == 2) {\n        /* CLUSTER BUMPEPOCH */\n        int retval = clusterBumpConfigEpochWithoutConsensus();\n        sds reply = sdscatprintf(sdsempty(),\"+%s %llu\\r\\n\",\n                (retval == C_OK) ? \"BUMPED\" : \"STILL\",\n                (unsigned long long) myself->configEpoch);\n        addReplySds(c,reply);\n    } else if (!strcasecmp(c->argv[1]->ptr,\"info\") && c->argc == 2) {\n        /* CLUSTER INFO */\n        char *statestr[] = {\"ok\",\"fail\",\"needhelp\"};\n        int slots_assigned = 0, slots_ok = 0, slots_pfail = 0, slots_fail = 0;\n        uint64_t myepoch;\n        int j;\n\n        for (j = 0; j < CLUSTER_SLOTS; j++) {\n            clusterNode *n = server.cluster->slots[j];\n\n            if (n == NULL) continue;\n            slots_assigned++;\n            if (nodeFailed(n)) {\n                slots_fail++;\n            } else if (nodeTimedOut(n)) {\n                slots_pfail++;\n            } else {\n                slots_ok++;\n            }\n        }\n\n        myepoch = (nodeIsSlave(myself) && myself->slaveof) ?\n                  myself->slaveof->configEpoch : myself->configEpoch;\n\n        sds info = sdscatprintf(sdsempty(),\n            \"cluster_state:%s\\r\\n\"\n            \"cluster_slots_assigned:%d\\r\\n\"\n            \"cluster_slots_ok:%d\\r\\n\"\n            \"cluster_slots_pfail:%d\\r\\n\"\n            \"cluster_slots_fail:%d\\r\\n\"\n            \"cluster_known_nodes:%lu\\r\\n\"\n            \"cluster_size:%d\\r\\n\"\n            \"cluster_current_epoch:%llu\\r\\n\"\n            \"cluster_my_epoch:%llu\\r\\n\"\n            \"cluster_stats_messages_sent:%lld\\r\\n\"\n            \"cluster_stats_messages_received:%lld\\r\\n\"\n            , statestr[server.cluster->state],\n            slots_assigned,\n            slots_ok,\n            slots_pfail,\n            slots_fail,\n            dictSize(server.cluster->nodes),\n            server.cluster->size,\n            (unsigned long long) server.cluster->currentEpoch,\n            (unsigned long long) myepoch,\n            server.cluster->stats_bus_messages_sent,\n            server.cluster->stats_bus_messages_received\n        );\n        addReplySds(c,sdscatprintf(sdsempty(),\"$%lu\\r\\n\",\n            (unsigned long)sdslen(info)));\n        addReplySds(c,info);\n        addReply(c,shared.crlf);\n    } else if (!strcasecmp(c->argv[1]->ptr,\"saveconfig\") && c->argc == 2) {\n        int retval = clusterSaveConfig(1);\n\n        if (retval == 0)\n            addReply(c,shared.ok);\n        else\n            addReplyErrorFormat(c,\"error saving the cluster node config: %s\",\n                strerror(errno));\n    } else if (!strcasecmp(c->argv[1]->ptr,\"keyslot\") && c->argc == 3) {\n        /* CLUSTER KEYSLOT <key> */\n        sds key = c->argv[2]->ptr;\n\n        addReplyLongLong(c,keyHashSlot(key,sdslen(key)));\n    } else if (!strcasecmp(c->argv[1]->ptr,\"countkeysinslot\") && c->argc == 3) {\n        /* CLUSTER COUNTKEYSINSLOT <slot> */\n        long long slot;\n\n        if (getLongLongFromObjectOrReply(c,c->argv[2],&slot,NULL) != C_OK)\n            return;\n        if (slot < 0 || slot >= CLUSTER_SLOTS) {\n            addReplyError(c,\"Invalid slot\");\n            return;\n        }\n        addReplyLongLong(c,countKeysInSlot(slot));\n    } else if (!strcasecmp(c->argv[1]->ptr,\"getkeysinslot\") && c->argc == 4) {\n        /* CLUSTER GETKEYSINSLOT <slot> <count> */\n        long long maxkeys, slot;\n        unsigned int numkeys, j;\n        robj **keys;\n\n        if (getLongLongFromObjectOrReply(c,c->argv[2],&slot,NULL) != C_OK)\n            return;\n        if (getLongLongFromObjectOrReply(c,c->argv[3],&maxkeys,NULL)\n            != C_OK)\n            return;\n        if (slot < 0 || slot >= CLUSTER_SLOTS || maxkeys < 0) {\n            addReplyError(c,\"Invalid slot or number of keys\");\n            return;\n        }\n\n        keys = zmalloc(sizeof(robj*)*maxkeys);\n        numkeys = getKeysInSlot(slot, keys, maxkeys);\n        addReplyMultiBulkLen(c,numkeys);\n        for (j = 0; j < numkeys; j++) addReplyBulk(c,keys[j]);\n        zfree(keys);\n    } else if (!strcasecmp(c->argv[1]->ptr,\"forget\") && c->argc == 3) {\n        /* CLUSTER FORGET <NODE ID> */\n        clusterNode *n = clusterLookupNode(c->argv[2]->ptr);\n\n        if (!n) {\n            addReplyErrorFormat(c,\"Unknown node %s\", (char*)c->argv[2]->ptr);\n            return;\n        } else if (n == myself) {\n            addReplyError(c,\"I tried hard but I can't forget myself...\");\n            return;\n        } else if (nodeIsSlave(myself) && myself->slaveof == n) {\n            addReplyError(c,\"Can't forget my master!\");\n            return;\n        }\n        clusterBlacklistAddNode(n);\n        clusterDelNode(n);\n        clusterDoBeforeSleep(CLUSTER_TODO_UPDATE_STATE|\n                             CLUSTER_TODO_SAVE_CONFIG);\n        addReply(c,shared.ok);\n    } else if (!strcasecmp(c->argv[1]->ptr,\"replicate\") && c->argc == 3) {\n        /* CLUSTER REPLICATE <NODE ID> */\n        clusterNode *n = clusterLookupNode(c->argv[2]->ptr);\n\n        /* Lookup the specified node in our table. */\n        if (!n) {\n            addReplyErrorFormat(c,\"Unknown node %s\", (char*)c->argv[2]->ptr);\n            return;\n        }\n\n        /* I can't replicate myself. */\n        if (n == myself) {\n            addReplyError(c,\"Can't replicate myself\");\n            return;\n        }\n\n        /* Can't replicate a slave. */\n        if (nodeIsSlave(n)) {\n            addReplyError(c,\"I can only replicate a master, not a slave.\");\n            return;\n        }\n\n        /* If the instance is currently a master, it should have no assigned\n         * slots nor keys to accept to replicate some other node.\n         * Slaves can switch to another master without issues. */\n        if (nodeIsMaster(myself) &&\n            (myself->numslots != 0 || dictSize(server.db[0].dict) != 0)) {\n            addReplyError(c,\n                \"To set a master the node must be empty and \"\n                \"without assigned slots.\");\n            return;\n        }\n\n        /* Set the master. */\n        clusterSetMaster(n);\n        clusterDoBeforeSleep(CLUSTER_TODO_UPDATE_STATE|CLUSTER_TODO_SAVE_CONFIG);\n        addReply(c,shared.ok);\n    } else if (!strcasecmp(c->argv[1]->ptr,\"slaves\") && c->argc == 3) {\n        /* CLUSTER SLAVES <NODE ID> */\n        clusterNode *n = clusterLookupNode(c->argv[2]->ptr);\n        int j;\n\n        /* Lookup the specified node in our table. */\n        if (!n) {\n            addReplyErrorFormat(c,\"Unknown node %s\", (char*)c->argv[2]->ptr);\n            return;\n        }\n\n        if (nodeIsSlave(n)) {\n            addReplyError(c,\"The specified node is not a master\");\n            return;\n        }\n\n        addReplyMultiBulkLen(c,n->numslaves);\n        for (j = 0; j < n->numslaves; j++) {\n            sds ni = clusterGenNodeDescription(n->slaves[j]);\n            addReplyBulkCString(c,ni);\n            sdsfree(ni);\n        }\n    } else if (!strcasecmp(c->argv[1]->ptr,\"count-failure-reports\") &&\n               c->argc == 3)\n    {\n        /* CLUSTER COUNT-FAILURE-REPORTS <NODE ID> */\n        clusterNode *n = clusterLookupNode(c->argv[2]->ptr);\n\n        if (!n) {\n            addReplyErrorFormat(c,\"Unknown node %s\", (char*)c->argv[2]->ptr);\n            return;\n        } else {\n            addReplyLongLong(c,clusterNodeFailureReportsCount(n));\n        }\n    } else if (!strcasecmp(c->argv[1]->ptr,\"failover\") &&\n               (c->argc == 2 || c->argc == 3))\n    {\n        /* CLUSTER FAILOVER [FORCE|TAKEOVER] */\n        int force = 0, takeover = 0;\n\n        if (c->argc == 3) {\n            if (!strcasecmp(c->argv[2]->ptr,\"force\")) {\n                force = 1;\n            } else if (!strcasecmp(c->argv[2]->ptr,\"takeover\")) {\n                takeover = 1;\n                force = 1; /* Takeover also implies force. */\n            } else {\n                addReply(c,shared.syntaxerr);\n                return;\n            }\n        }\n\n        /* Check preconditions. */\n        if (nodeIsMaster(myself)) {\n            addReplyError(c,\"You should send CLUSTER FAILOVER to a slave\");\n            return;\n        } else if (myself->slaveof == NULL) {\n            addReplyError(c,\"I'm a slave but my master is unknown to me\");\n            return;\n        } else if (!force &&\n                   (nodeFailed(myself->slaveof) ||\n                    myself->slaveof->link == NULL))\n        {\n            addReplyError(c,\"Master is down or failed, \"\n                            \"please use CLUSTER FAILOVER FORCE\");\n            return;\n        }\n        resetManualFailover();\n        server.cluster->mf_end = mstime() + CLUSTER_MF_TIMEOUT;\n\n        if (takeover) {\n            /* A takeover does not perform any initial check. It just\n             * generates a new configuration epoch for this node without\n             * consensus, claims the master's slots, and broadcast the new\n             * configuration. */\n            serverLog(LL_WARNING,\"Taking over the master (user request).\");\n            clusterBumpConfigEpochWithoutConsensus();\n            clusterFailoverReplaceYourMaster();\n        } else if (force) {\n            /* If this is a forced failover, we don't need to talk with our\n             * master to agree about the offset. We just failover taking over\n             * it without coordination. */\n            serverLog(LL_WARNING,\"Forced failover user request accepted.\");\n            server.cluster->mf_can_start = 1;\n        } else {\n            serverLog(LL_WARNING,\"Manual failover user request accepted.\");\n            clusterSendMFStart(myself->slaveof);\n        }\n        addReply(c,shared.ok);\n    } else if (!strcasecmp(c->argv[1]->ptr,\"set-config-epoch\") && c->argc == 3)\n    {\n        /* CLUSTER SET-CONFIG-EPOCH <epoch>\n         *\n         * The user is allowed to set the config epoch only when a node is\n         * totally fresh: no config epoch, no other known node, and so forth.\n         * This happens at cluster creation time to start with a cluster where\n         * every node has a different node ID, without to rely on the conflicts\n         * resolution system which is too slow when a big cluster is created. */\n        long long epoch;\n\n        if (getLongLongFromObjectOrReply(c,c->argv[2],&epoch,NULL) != C_OK)\n            return;\n\n        if (epoch < 0) {\n            addReplyErrorFormat(c,\"Invalid config epoch specified: %lld\",epoch);\n        } else if (dictSize(server.cluster->nodes) > 1) {\n            addReplyError(c,\"The user can assign a config epoch only when the \"\n                            \"node does not know any other node.\");\n        } else if (myself->configEpoch != 0) {\n            addReplyError(c,\"Node config epoch is already non-zero\");\n        } else {\n            myself->configEpoch = epoch;\n            serverLog(LL_WARNING,\n                \"configEpoch set to %llu via CLUSTER SET-CONFIG-EPOCH\",\n                (unsigned long long) myself->configEpoch);\n\n            if (server.cluster->currentEpoch < (uint64_t)epoch)\n                server.cluster->currentEpoch = epoch;\n            /* No need to fsync the config here since in the unlucky event\n             * of a failure to persist the config, the conflict resolution code\n             * will assign an unique config to this node. */\n            clusterDoBeforeSleep(CLUSTER_TODO_UPDATE_STATE|\n                                 CLUSTER_TODO_SAVE_CONFIG);\n            addReply(c,shared.ok);\n        }\n    } else if (!strcasecmp(c->argv[1]->ptr,\"reset\") &&\n               (c->argc == 2 || c->argc == 3))\n    {\n        /* CLUSTER RESET [SOFT|HARD] */\n        int hard = 0;\n\n        /* Parse soft/hard argument. Default is soft. */\n        if (c->argc == 3) {\n            if (!strcasecmp(c->argv[2]->ptr,\"hard\")) {\n                hard = 1;\n            } else if (!strcasecmp(c->argv[2]->ptr,\"soft\")) {\n                hard = 0;\n            } else {\n                addReply(c,shared.syntaxerr);\n                return;\n            }\n        }\n\n        /* Slaves can be reset while containing data, but not master nodes\n         * that must be empty. */\n        if (nodeIsMaster(myself) && dictSize(c->db->dict) != 0) {\n            addReplyError(c,\"CLUSTER RESET can't be called with \"\n                            \"master nodes containing keys\");\n            return;\n        }\n        clusterReset(hard);\n        addReply(c,shared.ok);\n    } else {\n        addReplyError(c,\"Wrong CLUSTER subcommand or number of arguments\");\n    }\n}\n\n/* -----------------------------------------------------------------------------\n * DUMP, RESTORE and MIGRATE commands\n * -------------------------------------------------------------------------- */\n\n/* Generates a DUMP-format representation of the object 'o', adding it to the\n * io stream pointed by 'rio'. This function can't fail. */\nvoid createDumpPayload(rio *payload, robj *o) {\n    unsigned char buf[2];\n    uint64_t crc;\n\n    /* Serialize the object in a RDB-like format. It consist of an object type\n     * byte followed by the serialized object. This is understood by RESTORE. */\n    rioInitWithBuffer(payload,sdsempty());\n    serverAssert(rdbSaveObjectType(payload,o));\n    serverAssert(rdbSaveObject(payload,o));\n\n    /* Write the footer, this is how it looks like:\n     * ----------------+---------------------+---------------+\n     * ... RDB payload | 2 bytes RDB version | 8 bytes CRC64 |\n     * ----------------+---------------------+---------------+\n     * RDB version and CRC are both in little endian.\n     */\n\n    /* RDB version */\n    buf[0] = RDB_VERSION & 0xff;\n    buf[1] = (RDB_VERSION >> 8) & 0xff;\n    payload->io.buffer.ptr = sdscatlen(payload->io.buffer.ptr,buf,2);\n\n    /* CRC64 */\n    crc = crc64(0,(unsigned char*)payload->io.buffer.ptr,\n                sdslen(payload->io.buffer.ptr));\n    memrev64ifbe(&crc);\n    payload->io.buffer.ptr = sdscatlen(payload->io.buffer.ptr,&crc,8);\n}\n\n/* Verify that the RDB version of the dump payload matches the one of this Redis\n * instance and that the checksum is ok.\n * If the DUMP payload looks valid C_OK is returned, otherwise C_ERR\n * is returned. */\nint verifyDumpPayload(unsigned char *p, size_t len) {\n    unsigned char *footer;\n    uint16_t rdbver;\n    uint64_t crc;\n\n    /* At least 2 bytes of RDB version and 8 of CRC64 should be present. */\n    if (len < 10) return C_ERR;\n    footer = p+(len-10);\n\n    /* Verify RDB version */\n    rdbver = (footer[1] << 8) | footer[0];\n    if (rdbver > RDB_VERSION) return C_ERR;\n\n    /* Verify CRC64 */\n    crc = crc64(0,p,len-8);\n    memrev64ifbe(&crc);\n    return (memcmp(&crc,footer+2,8) == 0) ? C_OK : C_ERR;\n}\n\n/* DUMP keyname\n * DUMP is actually not used by Redis Cluster but it is the obvious\n * complement of RESTORE and can be useful for different applications. */\nvoid dumpCommand(client *c) {\n    robj *o, *dumpobj;\n    rio payload;\n\n    /* Check if the key is here. */\n    if ((o = lookupKeyRead(c->db,c->argv[1])) == NULL) {\n        addReply(c,shared.nullbulk);\n        return;\n    }\n\n    /* Create the DUMP encoded representation. */\n    createDumpPayload(&payload,o);\n\n    /* Transfer to the client */\n    dumpobj = createObject(OBJ_STRING,payload.io.buffer.ptr);\n    addReplyBulk(c,dumpobj);\n    decrRefCount(dumpobj);\n    return;\n}\n\n/* RESTORE key ttl serialized-value [REPLACE] */\nvoid restoreCommand(client *c) {\n    long long ttl;\n    rio payload;\n    int j, type, replace = 0;\n    robj *obj;\n\n    /* Parse additional options */\n    for (j = 4; j < c->argc; j++) {\n        if (!strcasecmp(c->argv[j]->ptr,\"replace\")) {\n            replace = 1;\n        } else {\n            addReply(c,shared.syntaxerr);\n            return;\n        }\n    }\n\n    /* Make sure this key does not already exist here... */\n    if (!replace && lookupKeyWrite(c->db,c->argv[1]) != NULL) {\n        addReply(c,shared.busykeyerr);\n        return;\n    }\n\n    /* Check if the TTL value makes sense */\n    if (getLongLongFromObjectOrReply(c,c->argv[2],&ttl,NULL) != C_OK) {\n        return;\n    } else if (ttl < 0) {\n        addReplyError(c,\"Invalid TTL value, must be >= 0\");\n        return;\n    }\n\n    /* Verify RDB version and data checksum. */\n    if (verifyDumpPayload(c->argv[3]->ptr,sdslen(c->argv[3]->ptr)) == C_ERR)\n    {\n        addReplyError(c,\"DUMP payload version or checksum are wrong\");\n        return;\n    }\n\n    rioInitWithBuffer(&payload,c->argv[3]->ptr);\n    if (((type = rdbLoadObjectType(&payload)) == -1) ||\n        ((obj = rdbLoadObject(type,&payload)) == NULL))\n    {\n        addReplyError(c,\"Bad data format\");\n        return;\n    }\n\n    /* Remove the old key if needed. */\n    if (replace) dbDelete(c->db,c->argv[1]);\n\n    /* Create the key and set the TTL if any */\n    dbAdd(c->db,c->argv[1],obj);\n    if (ttl) setExpire(c->db,c->argv[1],mstime()+ttl);\n    signalModifiedKey(c->db,c->argv[1]);\n    addReply(c,shared.ok);\n    server.dirty++;\n}\n\n/* MIGRATE socket cache implementation.\n *\n * We take a map between host:ip and a TCP socket that we used to connect\n * to this instance in recent time.\n * This sockets are closed when the max number we cache is reached, and also\n * in serverCron() when they are around for more than a few seconds. */\n#define MIGRATE_SOCKET_CACHE_ITEMS 64 /* max num of items in the cache. */\n#define MIGRATE_SOCKET_CACHE_TTL 10 /* close cached sockets after 10 sec. */\n\ntypedef struct migrateCachedSocket {\n    int fd;\n    long last_dbid;\n    time_t last_use_time;\n} migrateCachedSocket;\n\n/* Return a migrateCachedSocket containing a TCP socket connected with the\n * target instance, possibly returning a cached one.\n *\n * This function is responsible of sending errors to the client if a\n * connection can't be established. In this case -1 is returned.\n * Otherwise on success the socket is returned, and the caller should not\n * attempt to free it after usage.\n *\n * If the caller detects an error while using the socket, migrateCloseSocket()\n * should be called so that the connection will be created from scratch\n * the next time. */\nmigrateCachedSocket* migrateGetSocket(client *c, robj *host, robj *port, long timeout) {\n    int fd;\n    sds name = sdsempty();\n    migrateCachedSocket *cs;\n\n    /* Check if we have an already cached socket for this ip:port pair. */\n    name = sdscatlen(name,host->ptr,sdslen(host->ptr));\n    name = sdscatlen(name,\":\",1);\n    name = sdscatlen(name,port->ptr,sdslen(port->ptr));\n    cs = dictFetchValue(server.migrate_cached_sockets,name);\n    if (cs) {\n        sdsfree(name);\n        cs->last_use_time = server.unixtime;\n        return cs;\n    }\n\n    /* No cached socket, create one. */\n    if (dictSize(server.migrate_cached_sockets) == MIGRATE_SOCKET_CACHE_ITEMS) {\n        /* Too many items, drop one at random. */\n        dictEntry *de = dictGetRandomKey(server.migrate_cached_sockets);\n        cs = dictGetVal(de);\n        close(cs->fd);\n        zfree(cs);\n        dictDelete(server.migrate_cached_sockets,dictGetKey(de));\n    }\n\n    /* Create the socket */\n    fd = anetTcpNonBlockConnect(server.neterr,c->argv[1]->ptr,\n                                atoi(c->argv[2]->ptr));\n    if (fd == -1) {\n        sdsfree(name);\n        addReplyErrorFormat(c,\"Can't connect to target node: %s\",\n            server.neterr);\n        return NULL;\n    }\n    anetEnableTcpNoDelay(server.neterr,fd);\n\n    /* Check if it connects within the specified timeout. */\n    if ((aeWait(fd,AE_WRITABLE,timeout) & AE_WRITABLE) == 0) {\n        sdsfree(name);\n        addReplySds(c,\n            sdsnew(\"-IOERR error or timeout connecting to the client\\r\\n\"));\n        close(fd);\n        return NULL;\n    }\n\n    /* Add to the cache and return it to the caller. */\n    cs = zmalloc(sizeof(*cs));\n    cs->fd = fd;\n    cs->last_dbid = -1;\n    cs->last_use_time = server.unixtime;\n    dictAdd(server.migrate_cached_sockets,name,cs);\n    return cs;\n}\n\n/* Free a migrate cached connection. */\nvoid migrateCloseSocket(robj *host, robj *port) {\n    sds name = sdsempty();\n    migrateCachedSocket *cs;\n\n    name = sdscatlen(name,host->ptr,sdslen(host->ptr));\n    name = sdscatlen(name,\":\",1);\n    name = sdscatlen(name,port->ptr,sdslen(port->ptr));\n    cs = dictFetchValue(server.migrate_cached_sockets,name);\n    if (!cs) {\n        sdsfree(name);\n        return;\n    }\n\n    close(cs->fd);\n    zfree(cs);\n    dictDelete(server.migrate_cached_sockets,name);\n    sdsfree(name);\n}\n\nvoid migrateCloseTimedoutSockets(void) {\n    dictIterator *di = dictGetSafeIterator(server.migrate_cached_sockets);\n    dictEntry *de;\n\n    while((de = dictNext(di)) != NULL) {\n        migrateCachedSocket *cs = dictGetVal(de);\n\n        if ((server.unixtime - cs->last_use_time) > MIGRATE_SOCKET_CACHE_TTL) {\n            close(cs->fd);\n            zfree(cs);\n            dictDelete(server.migrate_cached_sockets,dictGetKey(de));\n        }\n    }\n    dictReleaseIterator(di);\n}\n\n/* MIGRATE host port key dbid timeout [COPY | REPLACE]\n *\n * On in the multiple keys form:\n *\n * MIGRATE host port \"\" dbid timeout [COPY | REPLACE] KEYS key1 key2 ... keyN */\nvoid migrateCommand(client *c) {\n    migrateCachedSocket *cs;\n    int copy, replace, j;\n    long timeout;\n    long dbid;\n    robj **ov = NULL; /* Objects to migrate. */\n    robj **kv = NULL; /* Key names. */\n    robj **newargv = NULL; /* Used to rewrite the command as DEL ... keys ... */\n    rio cmd, payload;\n    int may_retry = 1;\n    int write_error = 0;\n    int argv_rewritten = 0;\n\n    /* To support the KEYS option we need the following additional state. */\n    int first_key = 3; /* Argument index of the first key. */\n    int num_keys = 1;  /* By default only migrate the 'key' argument. */\n\n    /* Initialization */\n    copy = 0;\n    replace = 0;\n\n    /* Parse additional options */\n    for (j = 6; j < c->argc; j++) {\n        if (!strcasecmp(c->argv[j]->ptr,\"copy\")) {\n            copy = 1;\n        } else if (!strcasecmp(c->argv[j]->ptr,\"replace\")) {\n            replace = 1;\n        } else if (!strcasecmp(c->argv[j]->ptr,\"keys\")) {\n            if (sdslen(c->argv[3]->ptr) != 0) {\n                addReplyError(c,\n                    \"When using MIGRATE KEYS option, the key argument\"\n                    \" must be set to the empty string\");\n                return;\n            }\n            first_key = j+1;\n            num_keys = c->argc - j - 1;\n            break; /* All the remaining args are keys. */\n        } else {\n            addReply(c,shared.syntaxerr);\n            return;\n        }\n    }\n\n    /* Sanity check */\n    if (getLongFromObjectOrReply(c,c->argv[5],&timeout,NULL) != C_OK ||\n        getLongFromObjectOrReply(c,c->argv[4],&dbid,NULL) != C_OK)\n    {\n        return;\n    }\n    if (timeout <= 0) timeout = 1000;\n\n    /* Check if the keys are here. If at least one key is to migrate, do it\n     * otherwise if all the keys are missing reply with \"NOKEY\" to signal\n     * the caller there was nothing to migrate. We don't return an error in\n     * this case, since often this is due to a normal condition like the key\n     * expiring in the meantime. */\n    ov = zrealloc(ov,sizeof(robj*)*num_keys);\n    kv = zrealloc(kv,sizeof(robj*)*num_keys);\n    int oi = 0;\n\n    for (j = 0; j < num_keys; j++) {\n        if ((ov[oi] = lookupKeyRead(c->db,c->argv[first_key+j])) != NULL) {\n            kv[oi] = c->argv[first_key+j];\n            oi++;\n        }\n    }\n    num_keys = oi;\n    if (num_keys == 0) {\n        zfree(ov); zfree(kv);\n        addReplySds(c,sdsnew(\"+NOKEY\\r\\n\"));\n        return;\n    }\n\ntry_again:\n    write_error = 0;\n\n    /* Connect */\n    cs = migrateGetSocket(c,c->argv[1],c->argv[2],timeout);\n    if (cs == NULL) {\n        zfree(ov); zfree(kv);\n        return; /* error sent to the client by migrateGetSocket() */\n    }\n\n    rioInitWithBuffer(&cmd,sdsempty());\n\n    /* Send the SELECT command if the current DB is not already selected. */\n    int select = cs->last_dbid != dbid; /* Should we emit SELECT? */\n    if (select) {\n        serverAssertWithInfo(c,NULL,rioWriteBulkCount(&cmd,'*',2));\n        serverAssertWithInfo(c,NULL,rioWriteBulkString(&cmd,\"SELECT\",6));\n        serverAssertWithInfo(c,NULL,rioWriteBulkLongLong(&cmd,dbid));\n    }\n\n    /* Create RESTORE payload and generate the protocol to call the command. */\n    for (j = 0; j < num_keys; j++) {\n        long long ttl = 0;\n        long long expireat = getExpire(c->db,kv[j]);\n\n        if (expireat != -1) {\n            ttl = expireat-mstime();\n            if (ttl < 1) ttl = 1;\n        }\n        serverAssertWithInfo(c,NULL,rioWriteBulkCount(&cmd,'*',replace ? 5 : 4));\n        if (server.cluster_enabled)\n            serverAssertWithInfo(c,NULL,\n                rioWriteBulkString(&cmd,\"RESTORE-ASKING\",14));\n        else\n            serverAssertWithInfo(c,NULL,rioWriteBulkString(&cmd,\"RESTORE\",7));\n        serverAssertWithInfo(c,NULL,sdsEncodedObject(kv[j]));\n        serverAssertWithInfo(c,NULL,rioWriteBulkString(&cmd,kv[j]->ptr,\n                sdslen(kv[j]->ptr)));\n        serverAssertWithInfo(c,NULL,rioWriteBulkLongLong(&cmd,ttl));\n\n        /* Emit the payload argument, that is the serialized object using\n         * the DUMP format. */\n        createDumpPayload(&payload,ov[j]);\n        serverAssertWithInfo(c,NULL,\n            rioWriteBulkString(&cmd,payload.io.buffer.ptr,\n                               sdslen(payload.io.buffer.ptr)));\n        sdsfree(payload.io.buffer.ptr);\n\n        /* Add the REPLACE option to the RESTORE command if it was specified\n         * as a MIGRATE option. */\n        if (replace)\n            serverAssertWithInfo(c,NULL,rioWriteBulkString(&cmd,\"REPLACE\",7));\n    }\n\n    /* Transfer the query to the other node in 64K chunks. */\n    errno = 0;\n    {\n        sds buf = cmd.io.buffer.ptr;\n        size_t pos = 0, towrite;\n        int nwritten = 0;\n\n        while ((towrite = sdslen(buf)-pos) > 0) {\n            towrite = (towrite > (64*1024) ? (64*1024) : towrite);\n            nwritten = syncWrite(cs->fd,buf+pos,towrite,timeout);\n            if (nwritten != (signed)towrite) {\n                write_error = 1;\n                goto socket_err;\n            }\n            pos += nwritten;\n        }\n    }\n\n    char buf1[1024]; /* Select reply. */\n    char buf2[1024]; /* Restore reply. */\n\n    /* Read the SELECT reply if needed. */\n    if (select && syncReadLine(cs->fd, buf1, sizeof(buf1), timeout) <= 0)\n        goto socket_err;\n\n    /* Read the RESTORE replies. */\n    int error_from_target = 0;\n    int socket_error = 0;\n    int del_idx = 1; /* Index of the key argument for the replicated DEL op. */\n\n    if (!copy) newargv = zmalloc(sizeof(robj*)*(num_keys+1));\n\n    for (j = 0; j < num_keys; j++) {\n        if (syncReadLine(cs->fd, buf2, sizeof(buf2), timeout) <= 0) {\n            socket_error = 1;\n            break;\n        }\n        if ((select && buf1[0] == '-') || buf2[0] == '-') {\n            /* On error assume that last_dbid is no longer valid. */\n            if (!error_from_target) {\n                cs->last_dbid = -1;\n                addReplyErrorFormat(c,\"Target instance replied with error: %s\",\n                    (select && buf1[0] == '-') ? buf1+1 : buf2+1);\n                error_from_target = 1;\n            }\n        } else {\n            if (!copy) {\n                /* No COPY option: remove the local key, signal the change. */\n                dbDelete(c->db,kv[j]);\n                signalModifiedKey(c->db,kv[j]);\n                server.dirty++;\n\n                /* Populate the argument vector to replace the old one. */\n                newargv[del_idx++] = kv[j];\n                incrRefCount(kv[j]);\n            }\n        }\n    }\n\n    /* On socket error, if we want to retry, do it now before rewriting the\n     * command vector. We only retry if we are sure nothing was processed\n     * and we failed to read the first reply (j == 0 test). */\n    if (!error_from_target && socket_error && j == 0 && may_retry &&\n        errno != ETIMEDOUT)\n    {\n        goto socket_err; /* A retry is guaranteed because of tested conditions.*/\n    }\n\n    /* On socket errors, close the migration socket now that we still have\n     * the original host/port in the ARGV. Later the original command may be\n     * rewritten to DEL and will be too later. */\n    if (socket_error) migrateCloseSocket(c->argv[1],c->argv[2]);\n\n    if (!copy) {\n        /* Translate MIGRATE as DEL for replication/AOF. Note that we do\n         * this only for the keys for which we received an acknowledgement\n         * from the receiving Redis server, by using the del_idx index. */\n        if (del_idx > 1) {\n            newargv[0] = createStringObject(\"DEL\",3);\n            /* Note that the following call takes ownership of newargv. */\n            replaceClientCommandVector(c,del_idx,newargv);\n            argv_rewritten = 1;\n        } else {\n            /* No key transfer acknowledged, no need to rewrite as DEL. */\n            zfree(newargv);\n        }\n        newargv = NULL; /* Make it safe to call zfree() on it in the future. */\n    }\n\n    /* If we are here and a socket error happened, we don't want to retry.\n     * Just signal the problem to the client, but only do it if we did not\n     * already queue a different error reported by the destination server. */\n    if (!error_from_target && socket_error) {\n        may_retry = 0;\n        goto socket_err;\n    }\n\n    if (!error_from_target) {\n        /* Success! Update the last_dbid in migrateCachedSocket, so that we can\n         * avoid SELECT the next time if the target DB is the same. Reply +OK.\n         *\n         * Note: If we reached this point, even if socket_error is true\n         * still the SELECT command succeeded (otherwise the code jumps to\n         * socket_err label. */\n        cs->last_dbid = dbid;\n        addReply(c,shared.ok);\n    } else {\n        /* On error we already sent it in the for loop above, and set\n         * the curretly selected socket to -1 to force SELECT the next time. */\n    }\n\n    sdsfree(cmd.io.buffer.ptr);\n    zfree(ov); zfree(kv); zfree(newargv);\n    return;\n\n/* On socket errors we try to close the cached socket and try again.\n * It is very common for the cached socket to get closed, if just reopening\n * it works it's a shame to notify the error to the caller. */\nsocket_err:\n    /* Cleanup we want to perform in both the retry and no retry case.\n     * Note: Closing the migrate socket will also force SELECT next time. */\n    sdsfree(cmd.io.buffer.ptr);\n\n    /* If the command was rewritten as DEL and there was a socket error,\n     * we already closed the socket earlier. While migrateCloseSocket()\n     * is idempotent, the host/port arguments are now gone, so don't do it\n     * again. */\n    if (!argv_rewritten) migrateCloseSocket(c->argv[1],c->argv[2]);\n    zfree(newargv);\n    newargv = NULL; /* This will get reallocated on retry. */\n\n    /* Retry only if it's not a timeout and we never attempted a retry\n     * (or the code jumping here did not set may_retry to zero). */\n    if (errno != ETIMEDOUT && may_retry) {\n        may_retry = 0;\n        goto try_again;\n    }\n\n    /* Cleanup we want to do if no retry is attempted. */\n    zfree(ov); zfree(kv);\n    addReplySds(c,\n        sdscatprintf(sdsempty(),\n            \"-IOERR error or timeout %s to target instance\\r\\n\",\n            write_error ? \"writing\" : \"reading\"));\n    return;\n}\n\n/* -----------------------------------------------------------------------------\n * Cluster functions related to serving / redirecting clients\n * -------------------------------------------------------------------------- */\n\n/* The ASKING command is required after a -ASK redirection.\n * The client should issue ASKING before to actually send the command to\n * the target instance. See the Redis Cluster specification for more\n * information. */\nvoid askingCommand(client *c) {\n    if (server.cluster_enabled == 0) {\n        addReplyError(c,\"This instance has cluster support disabled\");\n        return;\n    }\n    c->flags |= CLIENT_ASKING;\n    addReply(c,shared.ok);\n}\n\n/* The READONLY command is used by clients to enter the read-only mode.\n * In this mode slaves will not redirect clients as long as clients access\n * with read-only commands to keys that are served by the slave's master. */\nvoid readonlyCommand(client *c) {\n    if (server.cluster_enabled == 0) {\n        addReplyError(c,\"This instance has cluster support disabled\");\n        return;\n    }\n    c->flags |= CLIENT_READONLY;\n    addReply(c,shared.ok);\n}\n\n/* The READWRITE command just clears the READONLY command state. */\nvoid readwriteCommand(client *c) {\n    c->flags &= ~CLIENT_READONLY;\n    addReply(c,shared.ok);\n}\n\n/* Return the pointer to the cluster node that is able to serve the command.\n * For the function to succeed the command should only target either:\n *\n * 1) A single key (even multiple times like LPOPRPUSH mylist mylist).\n * 2) Multiple keys in the same hash slot, while the slot is stable (no\n *    resharding in progress).\n *\n * On success the function returns the node that is able to serve the request.\n * If the node is not 'myself' a redirection must be perfomed. The kind of\n * redirection is specified setting the integer passed by reference\n * 'error_code', which will be set to CLUSTER_REDIR_ASK or\n * CLUSTER_REDIR_MOVED.\n *\n * When the node is 'myself' 'error_code' is set to CLUSTER_REDIR_NONE.\n *\n * If the command fails NULL is returned, and the reason of the failure is\n * provided via 'error_code', which will be set to:\n *\n * CLUSTER_REDIR_CROSS_SLOT if the request contains multiple keys that\n * don't belong to the same hash slot.\n *\n * CLUSTER_REDIR_UNSTABLE if the request contains multiple keys\n * belonging to the same slot, but the slot is not stable (in migration or\n * importing state, likely because a resharding is in progress).\n *\n * CLUSTER_REDIR_DOWN_UNBOUND if the request addresses a slot which is\n * not bound to any node. In this case the cluster global state should be\n * already \"down\" but it is fragile to rely on the update of the global state,\n * so we also handle it here.\n *\n * CLUSTER_REDIR_DOWN_STATE if the cluster is down but the user attempts to\n * execute a command that addresses one or more keys. */\nclusterNode *getNodeByQuery(client *c, struct redisCommand *cmd, robj **argv, int argc, int *hashslot, int *error_code) {\n    clusterNode *n = NULL;\n    robj *firstkey = NULL;\n    int multiple_keys = 0;\n    multiState *ms, _ms;\n    multiCmd mc;\n    int i, slot = 0, migrating_slot = 0, importing_slot = 0, missing_keys = 0;\n\n    /* Set error code optimistically for the base case. */\n    if (error_code) *error_code = CLUSTER_REDIR_NONE;\n\n    /* We handle all the cases as if they were EXEC commands, so we have\n     * a common code path for everything */\n    if (cmd->proc == execCommand) {\n        /* If CLIENT_MULTI flag is not set EXEC is just going to return an\n         * error. */\n        if (!(c->flags & CLIENT_MULTI)) return myself;\n        ms = &c->mstate;\n    } else {\n        /* In order to have a single codepath create a fake Multi State\n         * structure if the client is not in MULTI/EXEC state, this way\n         * we have a single codepath below. */\n        ms = &_ms;\n        _ms.commands = &mc;\n        _ms.count = 1;\n        mc.argv = argv;\n        mc.argc = argc;\n        mc.cmd = cmd;\n    }\n\n    /* Check that all the keys are in the same hash slot, and obtain this\n     * slot and the node associated. */\n    for (i = 0; i < ms->count; i++) {\n        struct redisCommand *mcmd;\n        robj **margv;\n        int margc, *keyindex, numkeys, j;\n\n        mcmd = ms->commands[i].cmd;\n        margc = ms->commands[i].argc;\n        margv = ms->commands[i].argv;\n\n        keyindex = getKeysFromCommand(mcmd,margv,margc,&numkeys);\n        for (j = 0; j < numkeys; j++) {\n            robj *thiskey = margv[keyindex[j]];\n            int thisslot = keyHashSlot((char*)thiskey->ptr,\n                                       sdslen(thiskey->ptr));\n\n            if (firstkey == NULL) {\n                /* This is the first key we see. Check what is the slot\n                 * and node. */\n                firstkey = thiskey;\n                slot = thisslot;\n                n = server.cluster->slots[slot];\n\n                /* Error: If a slot is not served, we are in \"cluster down\"\n                 * state. However the state is yet to be updated, so this was\n                 * not trapped earlier in processCommand(). Report the same\n                 * error to the client. */\n                if (n == NULL) {\n                    getKeysFreeResult(keyindex);\n                    if (error_code)\n                        *error_code = CLUSTER_REDIR_DOWN_UNBOUND;\n                    return NULL;\n                }\n\n                /* If we are migrating or importing this slot, we need to check\n                 * if we have all the keys in the request (the only way we\n                 * can safely serve the request, otherwise we return a TRYAGAIN\n                 * error). To do so we set the importing/migrating state and\n                 * increment a counter for every missing key. */\n                if (n == myself &&\n                    server.cluster->migrating_slots_to[slot] != NULL)\n                {\n                    migrating_slot = 1;\n                } else if (server.cluster->importing_slots_from[slot] != NULL) {\n                    importing_slot = 1;\n                }\n            } else {\n                /* If it is not the first key, make sure it is exactly\n                 * the same key as the first we saw. */\n                if (!equalStringObjects(firstkey,thiskey)) {\n                    if (slot != thisslot) {\n                        /* Error: multiple keys from different slots. */\n                        getKeysFreeResult(keyindex);\n                        if (error_code)\n                            *error_code = CLUSTER_REDIR_CROSS_SLOT;\n                        return NULL;\n                    } else {\n                        /* Flag this request as one with multiple different\n                         * keys. */\n                        multiple_keys = 1;\n                    }\n                }\n            }\n\n            /* Migarting / Improrting slot? Count keys we don't have. */\n            if ((migrating_slot || importing_slot) &&\n                lookupKeyRead(&server.db[0],thiskey) == NULL)\n            {\n                missing_keys++;\n            }\n        }\n        getKeysFreeResult(keyindex);\n    }\n\n    /* No key at all in command? then we can serve the request\n     * without redirections or errors in all the cases. */\n    if (n == NULL) return myself;\n\n    /* Cluster is globally down but we got keys? We can't serve the request. */\n    if (server.cluster->state != CLUSTER_OK) {\n        if (error_code) *error_code = CLUSTER_REDIR_DOWN_STATE;\n        return NULL;\n    }\n\n    /* Return the hashslot by reference. */\n    if (hashslot) *hashslot = slot;\n\n    /* MIGRATE always works in the context of the local node if the slot\n     * is open (migrating or importing state). We need to be able to freely\n     * move keys among instances in this case. */\n    if ((migrating_slot || importing_slot) && cmd->proc == migrateCommand)\n        return myself;\n\n    /* If we don't have all the keys and we are migrating the slot, send\n     * an ASK redirection. */\n    if (migrating_slot && missing_keys) {\n        if (error_code) *error_code = CLUSTER_REDIR_ASK;\n        return server.cluster->migrating_slots_to[slot];\n    }\n\n    /* If we are receiving the slot, and the client correctly flagged the\n     * request as \"ASKING\", we can serve the request. However if the request\n     * involves multiple keys and we don't have them all, the only option is\n     * to send a TRYAGAIN error. */\n    if (importing_slot &&\n        (c->flags & CLIENT_ASKING || cmd->flags & CMD_ASKING))\n    {\n        if (multiple_keys && missing_keys) {\n            if (error_code) *error_code = CLUSTER_REDIR_UNSTABLE;\n            return NULL;\n        } else {\n            return myself;\n        }\n    }\n\n    /* Handle the read-only client case reading from a slave: if this\n     * node is a slave and the request is about an hash slot our master\n     * is serving, we can reply without redirection. */\n    if (c->flags & CLIENT_READONLY &&\n        cmd->flags & CMD_READONLY &&\n        nodeIsSlave(myself) &&\n        myself->slaveof == n)\n    {\n        return myself;\n    }\n\n    /* Base case: just return the right node. However if this node is not\n     * myself, set error_code to MOVED since we need to issue a rediretion. */\n    if (n != myself && error_code) *error_code = CLUSTER_REDIR_MOVED;\n    return n;\n}\n\n/* Send the client the right redirection code, according to error_code\n * that should be set to one of CLUSTER_REDIR_* macros.\n *\n * If CLUSTER_REDIR_ASK or CLUSTER_REDIR_MOVED error codes\n * are used, then the node 'n' should not be NULL, but should be the\n * node we want to mention in the redirection. Moreover hashslot should\n * be set to the hash slot that caused the redirection. */\nvoid clusterRedirectClient(client *c, clusterNode *n, int hashslot, int error_code) {\n    if (error_code == CLUSTER_REDIR_CROSS_SLOT) {\n        addReplySds(c,sdsnew(\"-CROSSSLOT Keys in request don't hash to the same slot\\r\\n\"));\n    } else if (error_code == CLUSTER_REDIR_UNSTABLE) {\n        /* The request spawns mutliple keys in the same slot,\n         * but the slot is not \"stable\" currently as there is\n         * a migration or import in progress. */\n        addReplySds(c,sdsnew(\"-TRYAGAIN Multiple keys request during rehashing of slot\\r\\n\"));\n    } else if (error_code == CLUSTER_REDIR_DOWN_STATE) {\n        addReplySds(c,sdsnew(\"-CLUSTERDOWN The cluster is down\\r\\n\"));\n    } else if (error_code == CLUSTER_REDIR_DOWN_UNBOUND) {\n        addReplySds(c,sdsnew(\"-CLUSTERDOWN Hash slot not served\\r\\n\"));\n    } else if (error_code == CLUSTER_REDIR_MOVED ||\n               error_code == CLUSTER_REDIR_ASK)\n    {\n        addReplySds(c,sdscatprintf(sdsempty(),\n            \"-%s %d %s:%d\\r\\n\",\n            (error_code == CLUSTER_REDIR_ASK) ? \"ASK\" : \"MOVED\",\n            hashslot,n->ip,n->port));\n    } else {\n        serverPanic(\"getNodeByQuery() unknown error.\");\n    }\n}\n\n/* This function is called by the function processing clients incrementally\n * to detect timeouts, in order to handle the following case:\n *\n * 1) A client blocks with BLPOP or similar blocking operation.\n * 2) The master migrates the hash slot elsewhere or turns into a slave.\n * 3) The client may remain blocked forever (or up to the max timeout time)\n *    waiting for a key change that will never happen.\n *\n * If the client is found to be blocked into an hash slot this node no\n * longer handles, the client is sent a redirection error, and the function\n * returns 1. Otherwise 0 is returned and no operation is performed. */\nint clusterRedirectBlockedClientIfNeeded(client *c) {\n    if (c->flags & CLIENT_BLOCKED && c->btype == BLOCKED_LIST) {\n        dictEntry *de;\n        dictIterator *di;\n\n        /* If the cluster is down, unblock the client with the right error. */\n        if (server.cluster->state == CLUSTER_FAIL) {\n            clusterRedirectClient(c,NULL,0,CLUSTER_REDIR_DOWN_STATE);\n            return 1;\n        }\n\n        di = dictGetIterator(c->bpop.keys);\n        while((de = dictNext(di)) != NULL) {\n            robj *key = dictGetKey(de);\n            int slot = keyHashSlot((char*)key->ptr, sdslen(key->ptr));\n            clusterNode *node = server.cluster->slots[slot];\n\n            /* We send an error and unblock the client if:\n             * 1) The slot is unassigned, emitting a cluster down error.\n             * 2) The slot is not handled by this node, nor being imported. */\n            if (node != myself &&\n                server.cluster->importing_slots_from[slot] == NULL)\n            {\n                if (node == NULL) {\n                    clusterRedirectClient(c,NULL,0,\n                        CLUSTER_REDIR_DOWN_UNBOUND);\n                } else {\n                    clusterRedirectClient(c,node,slot,\n                        CLUSTER_REDIR_MOVED);\n                }\n                return 1;\n            }\n        }\n        dictReleaseIterator(di);\n    }\n    return 0;\n}\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.8/src/cluster.h",
    "content": "#ifndef __CLUSTER_H\n#define __CLUSTER_H\n\n/*-----------------------------------------------------------------------------\n * Redis cluster data structures, defines, exported API.\n *----------------------------------------------------------------------------*/\n\n#define CLUSTER_SLOTS 16384\n#define CLUSTER_OK 0          /* Everything looks ok */\n#define CLUSTER_FAIL 1        /* The cluster can't work */\n#define CLUSTER_NAMELEN 40    /* sha1 hex length */\n#define CLUSTER_PORT_INCR 10000 /* Cluster port = baseport + PORT_INCR */\n\n/* The following defines are amount of time, sometimes expressed as\n * multiplicators of the node timeout value (when ending with MULT). */\n#define CLUSTER_DEFAULT_NODE_TIMEOUT 15000\n#define CLUSTER_DEFAULT_SLAVE_VALIDITY 10 /* Slave max data age factor. */\n#define CLUSTER_DEFAULT_REQUIRE_FULL_COVERAGE 1\n#define CLUSTER_FAIL_REPORT_VALIDITY_MULT 2 /* Fail report validity. */\n#define CLUSTER_FAIL_UNDO_TIME_MULT 2 /* Undo fail if master is back. */\n#define CLUSTER_FAIL_UNDO_TIME_ADD 10 /* Some additional time. */\n#define CLUSTER_FAILOVER_DELAY 5 /* Seconds */\n#define CLUSTER_DEFAULT_MIGRATION_BARRIER 1\n#define CLUSTER_MF_TIMEOUT 5000 /* Milliseconds to do a manual failover. */\n#define CLUSTER_MF_PAUSE_MULT 2 /* Master pause manual failover mult. */\n#define CLUSTER_SLAVE_MIGRATION_DELAY 5000 /* Delay for slave migration. */\n\n/* Redirection errors returned by getNodeByQuery(). */\n#define CLUSTER_REDIR_NONE 0          /* Node can serve the request. */\n#define CLUSTER_REDIR_CROSS_SLOT 1    /* -CROSSSLOT request. */\n#define CLUSTER_REDIR_UNSTABLE 2      /* -TRYAGAIN redirection required */\n#define CLUSTER_REDIR_ASK 3           /* -ASK redirection required. */\n#define CLUSTER_REDIR_MOVED 4         /* -MOVED redirection required. */\n#define CLUSTER_REDIR_DOWN_STATE 5    /* -CLUSTERDOWN, global state. */\n#define CLUSTER_REDIR_DOWN_UNBOUND 6  /* -CLUSTERDOWN, unbound slot. */\n\nstruct clusterNode;\n\n/* clusterLink encapsulates everything needed to talk with a remote node. */\ntypedef struct clusterLink {\n    mstime_t ctime;             /* Link creation time */\n    int fd;                     /* TCP socket file descriptor */\n    sds sndbuf;                 /* Packet send buffer */\n    sds rcvbuf;                 /* Packet reception buffer */\n    struct clusterNode *node;   /* Node related to this link if any, or NULL */\n} clusterLink;\n\n/* Cluster node flags and macros. */\n#define CLUSTER_NODE_MASTER 1     /* The node is a master */\n#define CLUSTER_NODE_SLAVE 2      /* The node is a slave */\n#define CLUSTER_NODE_PFAIL 4      /* Failure? Need acknowledge */\n#define CLUSTER_NODE_FAIL 8       /* The node is believed to be malfunctioning */\n#define CLUSTER_NODE_MYSELF 16    /* This node is myself */\n#define CLUSTER_NODE_HANDSHAKE 32 /* We have still to exchange the first ping */\n#define CLUSTER_NODE_NOADDR   64  /* We don't know the address of this node */\n#define CLUSTER_NODE_MEET 128     /* Send a MEET message to this node */\n#define CLUSTER_NODE_MIGRATE_TO 256 /* Master elegible for replica migration. */\n#define CLUSTER_NODE_NULL_NAME \"\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\"\n\n#define nodeIsMaster(n) ((n)->flags & CLUSTER_NODE_MASTER)\n#define nodeIsSlave(n) ((n)->flags & CLUSTER_NODE_SLAVE)\n#define nodeInHandshake(n) ((n)->flags & CLUSTER_NODE_HANDSHAKE)\n#define nodeHasAddr(n) (!((n)->flags & CLUSTER_NODE_NOADDR))\n#define nodeWithoutAddr(n) ((n)->flags & CLUSTER_NODE_NOADDR)\n#define nodeTimedOut(n) ((n)->flags & CLUSTER_NODE_PFAIL)\n#define nodeFailed(n) ((n)->flags & CLUSTER_NODE_FAIL)\n\n/* Reasons why a slave is not able to failover. */\n#define CLUSTER_CANT_FAILOVER_NONE 0\n#define CLUSTER_CANT_FAILOVER_DATA_AGE 1\n#define CLUSTER_CANT_FAILOVER_WAITING_DELAY 2\n#define CLUSTER_CANT_FAILOVER_EXPIRED 3\n#define CLUSTER_CANT_FAILOVER_WAITING_VOTES 4\n#define CLUSTER_CANT_FAILOVER_RELOG_PERIOD (60*5) /* seconds. */\n\n/* This structure represent elements of node->fail_reports. */\ntypedef struct clusterNodeFailReport {\n    struct clusterNode *node;  /* Node reporting the failure condition. */\n    mstime_t time;             /* Time of the last report from this node. */\n} clusterNodeFailReport;\n\ntypedef struct clusterNode {\n    mstime_t ctime; /* Node object creation time. */\n    char name[CLUSTER_NAMELEN]; /* Node name, hex string, sha1-size */\n    int flags;      /* CLUSTER_NODE_... */\n    uint64_t configEpoch; /* Last configEpoch observed for this node */\n    unsigned char slots[CLUSTER_SLOTS/8]; /* slots handled by this node */\n    int numslots;   /* Number of slots handled by this node */\n    int numslaves;  /* Number of slave nodes, if this is a master */\n    struct clusterNode **slaves; /* pointers to slave nodes */\n    struct clusterNode *slaveof; /* pointer to the master node. Note that it\n                                    may be NULL even if the node is a slave\n                                    if we don't have the master node in our\n                                    tables. */\n    mstime_t ping_sent;      /* Unix time we sent latest ping */\n    mstime_t pong_received;  /* Unix time we received the pong */\n    mstime_t fail_time;      /* Unix time when FAIL flag was set */\n    mstime_t voted_time;     /* Last time we voted for a slave of this master */\n    mstime_t repl_offset_time;  /* Unix time we received offset for this node */\n    mstime_t orphaned_time;     /* Starting time of orphaned master condition */\n    long long repl_offset;      /* Last known repl offset for this node. */\n    char ip[NET_IP_STR_LEN];  /* Latest known IP address of this node */\n    int port;                   /* Latest known port of this node */\n    clusterLink *link;          /* TCP/IP link with this node */\n    list *fail_reports;         /* List of nodes signaling this as failing */\n} clusterNode;\n\ntypedef struct clusterState {\n    clusterNode *myself;  /* This node */\n    uint64_t currentEpoch;\n    int state;            /* CLUSTER_OK, CLUSTER_FAIL, ... */\n    int size;             /* Num of master nodes with at least one slot */\n    dict *nodes;          /* Hash table of name -> clusterNode structures */\n    dict *nodes_black_list; /* Nodes we don't re-add for a few seconds. */\n    clusterNode *migrating_slots_to[CLUSTER_SLOTS];\n    clusterNode *importing_slots_from[CLUSTER_SLOTS];\n    clusterNode *slots[CLUSTER_SLOTS];\n    zskiplist *slots_to_keys;\n    /* The following fields are used to take the slave state on elections. */\n    mstime_t failover_auth_time; /* Time of previous or next election. */\n    int failover_auth_count;    /* Number of votes received so far. */\n    int failover_auth_sent;     /* True if we already asked for votes. */\n    int failover_auth_rank;     /* This slave rank for current auth request. */\n    uint64_t failover_auth_epoch; /* Epoch of the current election. */\n    int cant_failover_reason;   /* Why a slave is currently not able to\n                                   failover. See the CANT_FAILOVER_* macros. */\n    /* Manual failover state in common. */\n    mstime_t mf_end;            /* Manual failover time limit (ms unixtime).\n                                   It is zero if there is no MF in progress. */\n    /* Manual failover state of master. */\n    clusterNode *mf_slave;      /* Slave performing the manual failover. */\n    /* Manual failover state of slave. */\n    long long mf_master_offset; /* Master offset the slave needs to start MF\n                                   or zero if stil not received. */\n    int mf_can_start;           /* If non-zero signal that the manual failover\n                                   can start requesting masters vote. */\n    /* The followign fields are used by masters to take state on elections. */\n    uint64_t lastVoteEpoch;     /* Epoch of the last vote granted. */\n    int todo_before_sleep; /* Things to do in clusterBeforeSleep(). */\n    long long stats_bus_messages_sent;  /* Num of msg sent via cluster bus. */\n    long long stats_bus_messages_received; /* Num of msg rcvd via cluster bus.*/\n} clusterState;\n\n/* clusterState todo_before_sleep flags. */\n#define CLUSTER_TODO_HANDLE_FAILOVER (1<<0)\n#define CLUSTER_TODO_UPDATE_STATE (1<<1)\n#define CLUSTER_TODO_SAVE_CONFIG (1<<2)\n#define CLUSTER_TODO_FSYNC_CONFIG (1<<3)\n\n/* Redis cluster messages header */\n\n/* Note that the PING, PONG and MEET messages are actually the same exact\n * kind of packet. PONG is the reply to ping, in the exact format as a PING,\n * while MEET is a special PING that forces the receiver to add the sender\n * as a node (if it is not already in the list). */\n#define CLUSTERMSG_TYPE_PING 0          /* Ping */\n#define CLUSTERMSG_TYPE_PONG 1          /* Pong (reply to Ping) */\n#define CLUSTERMSG_TYPE_MEET 2          /* Meet \"let's join\" message */\n#define CLUSTERMSG_TYPE_FAIL 3          /* Mark node xxx as failing */\n#define CLUSTERMSG_TYPE_PUBLISH 4       /* Pub/Sub Publish propagation */\n#define CLUSTERMSG_TYPE_FAILOVER_AUTH_REQUEST 5 /* May I failover? */\n#define CLUSTERMSG_TYPE_FAILOVER_AUTH_ACK 6     /* Yes, you have my vote */\n#define CLUSTERMSG_TYPE_UPDATE 7        /* Another node slots configuration */\n#define CLUSTERMSG_TYPE_MFSTART 8       /* Pause clients for manual failover */\n\n/* Initially we don't know our \"name\", but we'll find it once we connect\n * to the first node, using the getsockname() function. Then we'll use this\n * address for all the next messages. */\ntypedef struct {\n    char nodename[CLUSTER_NAMELEN];\n    uint32_t ping_sent;\n    uint32_t pong_received;\n    char ip[NET_IP_STR_LEN];  /* IP address last time it was seen */\n    uint16_t port;              /* port last time it was seen */\n    uint16_t flags;             /* node->flags copy */\n    uint16_t notused1;          /* Some room for future improvements. */\n    uint32_t notused2;\n} clusterMsgDataGossip;\n\ntypedef struct {\n    char nodename[CLUSTER_NAMELEN];\n} clusterMsgDataFail;\n\ntypedef struct {\n    uint32_t channel_len;\n    uint32_t message_len;\n    /* We can't reclare bulk_data as bulk_data[] since this structure is\n     * nested. The 8 bytes are removed from the count during the message\n     * length computation. */\n    unsigned char bulk_data[8];\n} clusterMsgDataPublish;\n\ntypedef struct {\n    uint64_t configEpoch; /* Config epoch of the specified instance. */\n    char nodename[CLUSTER_NAMELEN]; /* Name of the slots owner. */\n    unsigned char slots[CLUSTER_SLOTS/8]; /* Slots bitmap. */\n} clusterMsgDataUpdate;\n\nunion clusterMsgData {\n    /* PING, MEET and PONG */\n    struct {\n        /* Array of N clusterMsgDataGossip structures */\n        clusterMsgDataGossip gossip[1];\n    } ping;\n\n    /* FAIL */\n    struct {\n        clusterMsgDataFail about;\n    } fail;\n\n    /* PUBLISH */\n    struct {\n        clusterMsgDataPublish msg;\n    } publish;\n\n    /* UPDATE */\n    struct {\n        clusterMsgDataUpdate nodecfg;\n    } update;\n};\n\n#define CLUSTER_PROTO_VER 0 /* Cluster bus protocol version. */\n\ntypedef struct {\n    char sig[4];        /* Siganture \"RCmb\" (Redis Cluster message bus). */\n    uint32_t totlen;    /* Total length of this message */\n    uint16_t ver;       /* Protocol version, currently set to 0. */\n    uint16_t notused0;  /* 2 bytes not used. */\n    uint16_t type;      /* Message type */\n    uint16_t count;     /* Only used for some kind of messages. */\n    uint64_t currentEpoch;  /* The epoch accordingly to the sending node. */\n    uint64_t configEpoch;   /* The config epoch if it's a master, or the last\n                               epoch advertised by its master if it is a\n                               slave. */\n    uint64_t offset;    /* Master replication offset if node is a master or\n                           processed replication offset if node is a slave. */\n    char sender[CLUSTER_NAMELEN]; /* Name of the sender node */\n    unsigned char myslots[CLUSTER_SLOTS/8];\n    char slaveof[CLUSTER_NAMELEN];\n    char notused1[32];  /* 32 bytes reserved for future usage. */\n    uint16_t port;      /* Sender TCP base port */\n    uint16_t flags;     /* Sender node flags */\n    unsigned char state; /* Cluster state from the POV of the sender */\n    unsigned char mflags[3]; /* Message flags: CLUSTERMSG_FLAG[012]_... */\n    union clusterMsgData data;\n} clusterMsg;\n\n#define CLUSTERMSG_MIN_LEN (sizeof(clusterMsg)-sizeof(union clusterMsgData))\n\n/* Message flags better specify the packet content or are used to\n * provide some information about the node state. */\n#define CLUSTERMSG_FLAG0_PAUSED (1<<0) /* Master paused for manual failover. */\n#define CLUSTERMSG_FLAG0_FORCEACK (1<<1) /* Give ACK to AUTH_REQUEST even if\n                                            master is up. */\n\n/* ---------------------- API exported outside cluster.c -------------------- */\nclusterNode *getNodeByQuery(client *c, struct redisCommand *cmd, robj **argv, int argc, int *hashslot, int *ask);\nint clusterRedirectBlockedClientIfNeeded(client *c);\nvoid clusterRedirectClient(client *c, clusterNode *n, int hashslot, int error_code);\n\n#endif /* __CLUSTER_H */\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.8/src/config.c",
    "content": "/* Configuration file parsing and CONFIG GET/SET commands implementation.\n *\n * Copyright (c) 2009-2012, Salvatore Sanfilippo <antirez at gmail dot com>\n * All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions are met:\n *\n *   * Redistributions of source code must retain the above copyright notice,\n *     this list of conditions and the following disclaimer.\n *   * Redistributions in binary form must reproduce the above copyright\n *     notice, this list of conditions and the following disclaimer in the\n *     documentation and/or other materials provided with the distribution.\n *   * Neither the name of Redis nor the names of its contributors may be used\n *     to endorse or promote products derived from this software without\n *     specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\"\n * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\n * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE\n * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR\n * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF\n * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS\n * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN\n * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)\n * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE\n * POSSIBILITY OF SUCH DAMAGE.\n */\n\n#include \"server.h\"\n#include \"cluster.h\"\n\n#include <fcntl.h>\n#include <sys/stat.h>\n\n/*-----------------------------------------------------------------------------\n * Config file name-value maps.\n *----------------------------------------------------------------------------*/\n\ntypedef struct configEnum {\n    const char *name;\n    const int val;\n} configEnum;\n\nconfigEnum maxmemory_policy_enum[] = {\n    {\"volatile-lru\", MAXMEMORY_VOLATILE_LRU},\n    {\"volatile-random\",MAXMEMORY_VOLATILE_RANDOM},\n    {\"volatile-ttl\",MAXMEMORY_VOLATILE_TTL},\n    {\"allkeys-lru\",MAXMEMORY_ALLKEYS_LRU},\n    {\"allkeys-random\",MAXMEMORY_ALLKEYS_RANDOM},\n    {\"noeviction\",MAXMEMORY_NO_EVICTION},\n    {NULL, 0}\n};\n\nconfigEnum syslog_facility_enum[] = {\n    {\"user\",    LOG_USER},\n    {\"local0\",  LOG_LOCAL0},\n    {\"local1\",  LOG_LOCAL1},\n    {\"local2\",  LOG_LOCAL2},\n    {\"local3\",  LOG_LOCAL3},\n    {\"local4\",  LOG_LOCAL4},\n    {\"local5\",  LOG_LOCAL5},\n    {\"local6\",  LOG_LOCAL6},\n    {\"local7\",  LOG_LOCAL7},\n    {NULL, 0}\n};\n\nconfigEnum loglevel_enum[] = {\n    {\"debug\", LL_DEBUG},\n    {\"verbose\", LL_VERBOSE},\n    {\"notice\", LL_NOTICE},\n    {\"warning\", LL_WARNING},\n    {NULL,0}\n};\n\nconfigEnum supervised_mode_enum[] = {\n    {\"upstart\", SUPERVISED_UPSTART},\n    {\"systemd\", SUPERVISED_SYSTEMD},\n    {\"auto\", SUPERVISED_AUTODETECT},\n    {\"no\", SUPERVISED_NONE},\n    {NULL, 0}\n};\n\nconfigEnum aof_fsync_enum[] = {\n    {\"everysec\", AOF_FSYNC_EVERYSEC},\n    {\"always\", AOF_FSYNC_ALWAYS},\n    {\"no\", AOF_FSYNC_NO},\n    {NULL, 0}\n};\n\n/* Output buffer limits presets. */\nclientBufferLimitsConfig clientBufferLimitsDefaults[CLIENT_TYPE_OBUF_COUNT] = {\n    {0, 0, 0}, /* normal */\n    {1024*1024*256, 1024*1024*64, 60}, /* slave */\n    {1024*1024*32, 1024*1024*8, 60}  /* pubsub */\n};\n\n/*-----------------------------------------------------------------------------\n * Enum access functions\n *----------------------------------------------------------------------------*/\n\n/* Get enum value from name. If there is no match INT_MIN is returned. */\nint configEnumGetValue(configEnum *ce, char *name) {\n    while(ce->name != NULL) {\n        if (!strcasecmp(ce->name,name)) return ce->val;\n        ce++;\n    }\n    return INT_MIN;\n}\n\n/* Get enum name from value. If no match is found NULL is returned. */\nconst char *configEnumGetName(configEnum *ce, int val) {\n    while(ce->name != NULL) {\n        if (ce->val == val) return ce->name;\n        ce++;\n    }\n    return NULL;\n}\n\n/* Wrapper for configEnumGetName() returning \"unknown\" insetad of NULL if\n * there is no match. */\nconst char *configEnumGetNameOrUnknown(configEnum *ce, int val) {\n    const char *name = configEnumGetName(ce,val);\n    return name ? name : \"unknown\";\n}\n\n/* Used for INFO generation. */\nconst char *evictPolicyToString(void) {\n    return configEnumGetNameOrUnknown(maxmemory_policy_enum,server.maxmemory_policy);\n}\n\n/*-----------------------------------------------------------------------------\n * Config file parsing\n *----------------------------------------------------------------------------*/\n\nint yesnotoi(char *s) {\n    if (!strcasecmp(s,\"yes\")) return 1;\n    else if (!strcasecmp(s,\"no\")) return 0;\n    else return -1;\n}\n\nvoid appendServerSaveParams(time_t seconds, int changes) {\n    server.saveparams = zrealloc(server.saveparams,sizeof(struct saveparam)*(server.saveparamslen+1));\n    server.saveparams[server.saveparamslen].seconds = seconds;\n    server.saveparams[server.saveparamslen].changes = changes;\n    server.saveparamslen++;\n}\n\nvoid resetServerSaveParams(void) {\n    zfree(server.saveparams);\n    server.saveparams = NULL;\n    server.saveparamslen = 0;\n}\n\nvoid loadServerConfigFromString(char *config) {\n    char *err = NULL;\n    int linenum = 0, totlines, i;\n    int slaveof_linenum = 0;\n    sds *lines;\n\n    lines = sdssplitlen(config,strlen(config),\"\\n\",1,&totlines);\n\n    for (i = 0; i < totlines; i++) {\n        sds *argv;\n        int argc;\n\n        linenum = i+1;\n        lines[i] = sdstrim(lines[i],\" \\t\\r\\n\");\n\n        /* Skip comments and blank lines */\n        if (lines[i][0] == '#' || lines[i][0] == '\\0') continue;\n\n        /* Split into arguments */\n        argv = sdssplitargs(lines[i],&argc);\n        if (argv == NULL) {\n            err = \"Unbalanced quotes in configuration line\";\n            goto loaderr;\n        }\n\n        /* Skip this line if the resulting command vector is empty. */\n        if (argc == 0) {\n            sdsfreesplitres(argv,argc);\n            continue;\n        }\n        sdstolower(argv[0]);\n\n        /* Execute config directives */\n        if (!strcasecmp(argv[0],\"timeout\") && argc == 2) {\n            server.maxidletime = atoi(argv[1]);\n            if (server.maxidletime < 0) {\n                err = \"Invalid timeout value\"; goto loaderr;\n            }\n        } else if (!strcasecmp(argv[0],\"tcp-keepalive\") && argc == 2) {\n            server.tcpkeepalive = atoi(argv[1]);\n            if (server.tcpkeepalive < 0) {\n                err = \"Invalid tcp-keepalive value\"; goto loaderr;\n            }\n        } else if (!strcasecmp(argv[0],\"protected-mode\") && argc == 2) {\n            if ((server.protected_mode = yesnotoi(argv[1])) == -1) {\n                err = \"argument must be 'yes' or 'no'\"; goto loaderr;\n            }\n        } else if (!strcasecmp(argv[0],\"port\") && argc == 2) {\n            server.port = atoi(argv[1]);\n            if (server.port < 0 || server.port > 65535) {\n                err = \"Invalid port\"; goto loaderr;\n            }\n        } else if (!strcasecmp(argv[0],\"tcp-backlog\") && argc == 2) {\n            server.tcp_backlog = atoi(argv[1]);\n            if (server.tcp_backlog < 0) {\n                err = \"Invalid backlog value\"; goto loaderr;\n            }\n        } else if (!strcasecmp(argv[0],\"bind\") && argc >= 2) {\n            int j, addresses = argc-1;\n\n            if (addresses > CONFIG_BINDADDR_MAX) {\n                err = \"Too many bind addresses specified\"; goto loaderr;\n            }\n            for (j = 0; j < addresses; j++)\n                server.bindaddr[j] = zstrdup(argv[j+1]);\n            server.bindaddr_count = addresses;\n        } else if (!strcasecmp(argv[0],\"unixsocket\") && argc == 2) {\n            server.unixsocket = zstrdup(argv[1]);\n        } else if (!strcasecmp(argv[0],\"unixsocketperm\") && argc == 2) {\n            errno = 0;\n            server.unixsocketperm = (mode_t)strtol(argv[1], NULL, 8);\n            if (errno || server.unixsocketperm > 0777) {\n                err = \"Invalid socket file permissions\"; goto loaderr;\n            }\n        } else if (!strcasecmp(argv[0],\"save\")) {\n            if (argc == 3) {\n                int seconds = atoi(argv[1]);\n                int changes = atoi(argv[2]);\n                if (seconds < 1 || changes < 0) {\n                    err = \"Invalid save parameters\"; goto loaderr;\n                }\n                appendServerSaveParams(seconds,changes);\n            } else if (argc == 2 && !strcasecmp(argv[1],\"\")) {\n                resetServerSaveParams();\n            }\n        } else if (!strcasecmp(argv[0],\"dir\") && argc == 2) {\n            if (chdir(argv[1]) == -1) {\n                serverLog(LL_WARNING,\"Can't chdir to '%s': %s\",\n                    argv[1], strerror(errno));\n                exit(1);\n            }\n        } else if (!strcasecmp(argv[0],\"loglevel\") && argc == 2) {\n            server.verbosity = configEnumGetValue(loglevel_enum,argv[1]);\n            if (server.verbosity == INT_MIN) {\n                err = \"Invalid log level. \"\n                      \"Must be one of debug, verbose, notice, warning\";\n                goto loaderr;\n            }\n        } else if (!strcasecmp(argv[0],\"logfile\") && argc == 2) {\n            FILE *logfp;\n\n            zfree(server.logfile);\n            server.logfile = zstrdup(argv[1]);\n            if (server.logfile[0] != '\\0') {\n                /* Test if we are able to open the file. The server will not\n                 * be able to abort just for this problem later... */\n                logfp = fopen(server.logfile,\"a\");\n                if (logfp == NULL) {\n                    err = sdscatprintf(sdsempty(),\n                        \"Can't open the log file: %s\", strerror(errno));\n                    goto loaderr;\n                }\n                fclose(logfp);\n            }\n        } else if (!strcasecmp(argv[0],\"syslog-enabled\") && argc == 2) {\n            if ((server.syslog_enabled = yesnotoi(argv[1])) == -1) {\n                err = \"argument must be 'yes' or 'no'\"; goto loaderr;\n            }\n        } else if (!strcasecmp(argv[0],\"syslog-ident\") && argc == 2) {\n            if (server.syslog_ident) zfree(server.syslog_ident);\n            server.syslog_ident = zstrdup(argv[1]);\n        } else if (!strcasecmp(argv[0],\"syslog-facility\") && argc == 2) {\n            server.syslog_facility =\n                configEnumGetValue(syslog_facility_enum,argv[1]);\n            if (server.syslog_facility == INT_MIN) {\n                err = \"Invalid log facility. Must be one of USER or between LOCAL0-LOCAL7\";\n                goto loaderr;\n            }\n        } else if (!strcasecmp(argv[0],\"databases\") && argc == 2) {\n            server.dbnum = atoi(argv[1]);\n            if (server.dbnum < 1) {\n                err = \"Invalid number of databases\"; goto loaderr;\n            }\n        } else if (!strcasecmp(argv[0],\"include\") && argc == 2) {\n            loadServerConfig(argv[1],NULL);\n        } else if (!strcasecmp(argv[0],\"maxclients\") && argc == 2) {\n            server.maxclients = atoi(argv[1]);\n            if (server.maxclients < 1) {\n                err = \"Invalid max clients limit\"; goto loaderr;\n            }\n        } else if (!strcasecmp(argv[0],\"maxmemory\") && argc == 2) {\n            server.maxmemory = memtoll(argv[1],NULL);\n        } else if (!strcasecmp(argv[0],\"maxmemory-policy\") && argc == 2) {\n            server.maxmemory_policy =\n                configEnumGetValue(maxmemory_policy_enum,argv[1]);\n            if (server.maxmemory_policy == INT_MIN) {\n                err = \"Invalid maxmemory policy\";\n                goto loaderr;\n            }\n        } else if (!strcasecmp(argv[0],\"maxmemory-samples\") && argc == 2) {\n            server.maxmemory_samples = atoi(argv[1]);\n            if (server.maxmemory_samples <= 0) {\n                err = \"maxmemory-samples must be 1 or greater\";\n                goto loaderr;\n            }\n        } else if (!strcasecmp(argv[0],\"slaveof\") && argc == 3) {\n            slaveof_linenum = linenum;\n            server.masterhost = sdsnew(argv[1]);\n            server.masterport = atoi(argv[2]);\n            server.repl_state = REPL_STATE_CONNECT;\n        } else if (!strcasecmp(argv[0],\"repl-ping-slave-period\") && argc == 2) {\n            server.repl_ping_slave_period = atoi(argv[1]);\n            if (server.repl_ping_slave_period <= 0) {\n                err = \"repl-ping-slave-period must be 1 or greater\";\n                goto loaderr;\n            }\n        } else if (!strcasecmp(argv[0],\"repl-timeout\") && argc == 2) {\n            server.repl_timeout = atoi(argv[1]);\n            if (server.repl_timeout <= 0) {\n                err = \"repl-timeout must be 1 or greater\";\n                goto loaderr;\n            }\n        } else if (!strcasecmp(argv[0],\"repl-disable-tcp-nodelay\") && argc==2) {\n            if ((server.repl_disable_tcp_nodelay = yesnotoi(argv[1])) == -1) {\n                err = \"argument must be 'yes' or 'no'\"; goto loaderr;\n            }\n        } else if (!strcasecmp(argv[0],\"repl-diskless-sync\") && argc==2) {\n            if ((server.repl_diskless_sync = yesnotoi(argv[1])) == -1) {\n                err = \"argument must be 'yes' or 'no'\"; goto loaderr;\n            }\n        } else if (!strcasecmp(argv[0],\"repl-diskless-sync-delay\") && argc==2) {\n            server.repl_diskless_sync_delay = atoi(argv[1]);\n            if (server.repl_diskless_sync_delay < 0) {\n                err = \"repl-diskless-sync-delay can't be negative\";\n                goto loaderr;\n            }\n        } else if (!strcasecmp(argv[0],\"repl-backlog-size\") && argc == 2) {\n            long long size = memtoll(argv[1],NULL);\n            if (size <= 0) {\n                err = \"repl-backlog-size must be 1 or greater.\";\n                goto loaderr;\n            }\n            resizeReplicationBacklog(size);\n        } else if (!strcasecmp(argv[0],\"repl-backlog-ttl\") && argc == 2) {\n            server.repl_backlog_time_limit = atoi(argv[1]);\n            if (server.repl_backlog_time_limit < 0) {\n                err = \"repl-backlog-ttl can't be negative \";\n                goto loaderr;\n            }\n        } else if (!strcasecmp(argv[0],\"masterauth\") && argc == 2) {\n            zfree(server.masterauth);\n            server.masterauth = zstrdup(argv[1]);\n        } else if (!strcasecmp(argv[0],\"slave-serve-stale-data\") && argc == 2) {\n            if ((server.repl_serve_stale_data = yesnotoi(argv[1])) == -1) {\n                err = \"argument must be 'yes' or 'no'\"; goto loaderr;\n            }\n        } else if (!strcasecmp(argv[0],\"slave-read-only\") && argc == 2) {\n            if ((server.repl_slave_ro = yesnotoi(argv[1])) == -1) {\n                err = \"argument must be 'yes' or 'no'\"; goto loaderr;\n            }\n        } else if (!strcasecmp(argv[0],\"rdbcompression\") && argc == 2) {\n            if ((server.rdb_compression = yesnotoi(argv[1])) == -1) {\n                err = \"argument must be 'yes' or 'no'\"; goto loaderr;\n            }\n        } else if (!strcasecmp(argv[0],\"rdbchecksum\") && argc == 2) {\n            if ((server.rdb_checksum = yesnotoi(argv[1])) == -1) {\n                err = \"argument must be 'yes' or 'no'\"; goto loaderr;\n            }\n        } else if (!strcasecmp(argv[0],\"activerehashing\") && argc == 2) {\n            if ((server.activerehashing = yesnotoi(argv[1])) == -1) {\n                err = \"argument must be 'yes' or 'no'\"; goto loaderr;\n            }\n        } else if (!strcasecmp(argv[0],\"daemonize\") && argc == 2) {\n            if ((server.daemonize = yesnotoi(argv[1])) == -1) {\n                err = \"argument must be 'yes' or 'no'\"; goto loaderr;\n            }\n        } else if (!strcasecmp(argv[0],\"hz\") && argc == 2) {\n            server.hz = atoi(argv[1]);\n            if (server.hz < CONFIG_MIN_HZ) server.hz = CONFIG_MIN_HZ;\n            if (server.hz > CONFIG_MAX_HZ) server.hz = CONFIG_MAX_HZ;\n        } else if (!strcasecmp(argv[0],\"appendonly\") && argc == 2) {\n            int yes;\n\n            if ((yes = yesnotoi(argv[1])) == -1) {\n                err = \"argument must be 'yes' or 'no'\"; goto loaderr;\n            }\n            server.aof_state = yes ? AOF_ON : AOF_OFF;\n        } else if (!strcasecmp(argv[0],\"appendfilename\") && argc == 2) {\n            if (!pathIsBaseName(argv[1])) {\n                err = \"appendfilename can't be a path, just a filename\";\n                goto loaderr;\n            }\n            zfree(server.aof_filename);\n            server.aof_filename = zstrdup(argv[1]);\n        } else if (!strcasecmp(argv[0],\"no-appendfsync-on-rewrite\")\n                   && argc == 2) {\n            if ((server.aof_no_fsync_on_rewrite= yesnotoi(argv[1])) == -1) {\n                err = \"argument must be 'yes' or 'no'\"; goto loaderr;\n            }\n        } else if (!strcasecmp(argv[0],\"appendfsync\") && argc == 2) {\n            server.aof_fsync = configEnumGetValue(aof_fsync_enum,argv[1]);\n            if (server.aof_fsync == INT_MIN) {\n                err = \"argument must be 'no', 'always' or 'everysec'\";\n                goto loaderr;\n            }\n        } else if (!strcasecmp(argv[0],\"auto-aof-rewrite-percentage\") &&\n                   argc == 2)\n        {\n            server.aof_rewrite_perc = atoi(argv[1]);\n            if (server.aof_rewrite_perc < 0) {\n                err = \"Invalid negative percentage for AOF auto rewrite\";\n                goto loaderr;\n            }\n        } else if (!strcasecmp(argv[0],\"auto-aof-rewrite-min-size\") &&\n                   argc == 2)\n        {\n            server.aof_rewrite_min_size = memtoll(argv[1],NULL);\n        } else if (!strcasecmp(argv[0],\"aof-rewrite-incremental-fsync\") &&\n                   argc == 2)\n        {\n            if ((server.aof_rewrite_incremental_fsync =\n                 yesnotoi(argv[1])) == -1) {\n                err = \"argument must be 'yes' or 'no'\"; goto loaderr;\n            }\n        } else if (!strcasecmp(argv[0],\"aof-load-truncated\") && argc == 2) {\n            if ((server.aof_load_truncated = yesnotoi(argv[1])) == -1) {\n                err = \"argument must be 'yes' or 'no'\"; goto loaderr;\n            }\n        } else if (!strcasecmp(argv[0],\"requirepass\") && argc == 2) {\n            if (strlen(argv[1]) > CONFIG_AUTHPASS_MAX_LEN) {\n                err = \"Password is longer than CONFIG_AUTHPASS_MAX_LEN\";\n                goto loaderr;\n            }\n            server.requirepass = zstrdup(argv[1]);\n        } else if (!strcasecmp(argv[0],\"pidfile\") && argc == 2) {\n            zfree(server.pidfile);\n            server.pidfile = zstrdup(argv[1]);\n        } else if (!strcasecmp(argv[0],\"dbfilename\") && argc == 2) {\n            if (!pathIsBaseName(argv[1])) {\n                err = \"dbfilename can't be a path, just a filename\";\n                goto loaderr;\n            }\n            zfree(server.rdb_filename);\n            server.rdb_filename = zstrdup(argv[1]);\n        } else if (!strcasecmp(argv[0],\"hash-max-ziplist-entries\") && argc == 2) {\n            server.hash_max_ziplist_entries = memtoll(argv[1], NULL);\n        } else if (!strcasecmp(argv[0],\"hash-max-ziplist-value\") && argc == 2) {\n            server.hash_max_ziplist_value = memtoll(argv[1], NULL);\n        } else if (!strcasecmp(argv[0],\"list-max-ziplist-entries\") && argc == 2){\n            /* DEAD OPTION */\n        } else if (!strcasecmp(argv[0],\"list-max-ziplist-value\") && argc == 2) {\n            /* DEAD OPTION */\n        } else if (!strcasecmp(argv[0],\"list-max-ziplist-size\") && argc == 2) {\n            server.list_max_ziplist_size = atoi(argv[1]);\n        } else if (!strcasecmp(argv[0],\"list-compress-depth\") && argc == 2) {\n            server.list_compress_depth = atoi(argv[1]);\n        } else if (!strcasecmp(argv[0],\"set-max-intset-entries\") && argc == 2) {\n            server.set_max_intset_entries = memtoll(argv[1], NULL);\n        } else if (!strcasecmp(argv[0],\"zset-max-ziplist-entries\") && argc == 2) {\n            server.zset_max_ziplist_entries = memtoll(argv[1], NULL);\n        } else if (!strcasecmp(argv[0],\"zset-max-ziplist-value\") && argc == 2) {\n            server.zset_max_ziplist_value = memtoll(argv[1], NULL);\n        } else if (!strcasecmp(argv[0],\"hll-sparse-max-bytes\") && argc == 2) {\n            server.hll_sparse_max_bytes = memtoll(argv[1], NULL);\n        } else if (!strcasecmp(argv[0],\"rename-command\") && argc == 3) {\n            struct redisCommand *cmd = lookupCommand(argv[1]);\n            int retval;\n\n            if (!cmd) {\n                err = \"No such command in rename-command\";\n                goto loaderr;\n            }\n\n            /* If the target command name is the empty string we just\n             * remove it from the command table. */\n            retval = dictDelete(server.commands, argv[1]);\n            serverAssert(retval == DICT_OK);\n\n            /* Otherwise we re-add the command under a different name. */\n            if (sdslen(argv[2]) != 0) {\n                sds copy = sdsdup(argv[2]);\n\n                retval = dictAdd(server.commands, copy, cmd);\n                if (retval != DICT_OK) {\n                    sdsfree(copy);\n                    err = \"Target command name already exists\"; goto loaderr;\n                }\n            }\n        } else if (!strcasecmp(argv[0],\"cluster-enabled\") && argc == 2) {\n            if ((server.cluster_enabled = yesnotoi(argv[1])) == -1) {\n                err = \"argument must be 'yes' or 'no'\"; goto loaderr;\n            }\n        } else if (!strcasecmp(argv[0],\"cluster-config-file\") && argc == 2) {\n            zfree(server.cluster_configfile);\n            server.cluster_configfile = zstrdup(argv[1]);\n        } else if (!strcasecmp(argv[0],\"cluster-require-full-coverage\") &&\n                    argc == 2)\n        {\n            if ((server.cluster_require_full_coverage = yesnotoi(argv[1])) == -1)\n            {\n                err = \"argument must be 'yes' or 'no'\"; goto loaderr;\n            }\n        } else if (!strcasecmp(argv[0],\"cluster-node-timeout\") && argc == 2) {\n            server.cluster_node_timeout = strtoll(argv[1],NULL,10);\n            if (server.cluster_node_timeout <= 0) {\n                err = \"cluster node timeout must be 1 or greater\"; goto loaderr;\n            }\n        } else if (!strcasecmp(argv[0],\"cluster-migration-barrier\")\n                   && argc == 2)\n        {\n            server.cluster_migration_barrier = atoi(argv[1]);\n            if (server.cluster_migration_barrier < 0) {\n                err = \"cluster migration barrier must zero or positive\";\n                goto loaderr;\n            }\n        } else if (!strcasecmp(argv[0],\"cluster-slave-validity-factor\")\n                   && argc == 2)\n        {\n            server.cluster_slave_validity_factor = atoi(argv[1]);\n            if (server.cluster_slave_validity_factor < 0) {\n                err = \"cluster slave validity factor must be zero or positive\";\n                goto loaderr;\n            }\n        } else if (!strcasecmp(argv[0],\"lua-time-limit\") && argc == 2) {\n            server.lua_time_limit = strtoll(argv[1],NULL,10);\n        } else if (!strcasecmp(argv[0],\"slowlog-log-slower-than\") &&\n                   argc == 2)\n        {\n            server.slowlog_log_slower_than = strtoll(argv[1],NULL,10);\n        } else if (!strcasecmp(argv[0],\"latency-monitor-threshold\") &&\n                   argc == 2)\n        {\n            server.latency_monitor_threshold = strtoll(argv[1],NULL,10);\n            if (server.latency_monitor_threshold < 0) {\n                err = \"The latency threshold can't be negative\";\n                goto loaderr;\n            }\n        } else if (!strcasecmp(argv[0],\"slowlog-max-len\") && argc == 2) {\n            server.slowlog_max_len = strtoll(argv[1],NULL,10);\n        } else if (!strcasecmp(argv[0],\"client-output-buffer-limit\") &&\n                   argc == 5)\n        {\n            int class = getClientTypeByName(argv[1]);\n            unsigned long long hard, soft;\n            int soft_seconds;\n\n            if (class == -1 || class == CLIENT_TYPE_MASTER) {\n                err = \"Unrecognized client limit class: the user specified \"\n                \"an invalid one, or 'master' which has no buffer limits.\";\n                goto loaderr;\n            }\n            hard = memtoll(argv[2],NULL);\n            soft = memtoll(argv[3],NULL);\n            soft_seconds = atoi(argv[4]);\n            if (soft_seconds < 0) {\n                err = \"Negative number of seconds in soft limit is invalid\";\n                goto loaderr;\n            }\n            server.client_obuf_limits[class].hard_limit_bytes = hard;\n            server.client_obuf_limits[class].soft_limit_bytes = soft;\n            server.client_obuf_limits[class].soft_limit_seconds = soft_seconds;\n        } else if (!strcasecmp(argv[0],\"stop-writes-on-bgsave-error\") &&\n                   argc == 2) {\n            if ((server.stop_writes_on_bgsave_err = yesnotoi(argv[1])) == -1) {\n                err = \"argument must be 'yes' or 'no'\"; goto loaderr;\n            }\n        } else if (!strcasecmp(argv[0],\"slave-priority\") && argc == 2) {\n            server.slave_priority = atoi(argv[1]);\n        } else if (!strcasecmp(argv[0],\"slave-announce-ip\") && argc == 2) {\n            zfree(server.slave_announce_ip);\n            server.slave_announce_ip = zstrdup(argv[1]);\n        } else if (!strcasecmp(argv[0],\"slave-announce-port\") && argc == 2) {\n            server.slave_announce_port = atoi(argv[1]);\n            if (server.slave_announce_port < 0 ||\n                server.slave_announce_port > 65535)\n            {\n                err = \"Invalid port\"; goto loaderr;\n            }\n        } else if (!strcasecmp(argv[0],\"min-slaves-to-write\") && argc == 2) {\n            server.repl_min_slaves_to_write = atoi(argv[1]);\n            if (server.repl_min_slaves_to_write < 0) {\n                err = \"Invalid value for min-slaves-to-write.\"; goto loaderr;\n            }\n        } else if (!strcasecmp(argv[0],\"min-slaves-max-lag\") && argc == 2) {\n            server.repl_min_slaves_max_lag = atoi(argv[1]);\n            if (server.repl_min_slaves_max_lag < 0) {\n                err = \"Invalid value for min-slaves-max-lag.\"; goto loaderr;\n            }\n        } else if (!strcasecmp(argv[0],\"notify-keyspace-events\") && argc == 2) {\n            int flags = keyspaceEventsStringToFlags(argv[1]);\n\n            if (flags == -1) {\n                err = \"Invalid event class character. Use 'g$lshzxeA'.\";\n                goto loaderr;\n            }\n            server.notify_keyspace_events = flags;\n        } else if (!strcasecmp(argv[0],\"supervised\") && argc == 2) {\n            server.supervised_mode =\n                configEnumGetValue(supervised_mode_enum,argv[1]);\n\n            if (server.supervised_mode == INT_MIN) {\n                err = \"Invalid option for 'supervised'. \"\n                    \"Allowed values: 'upstart', 'systemd', 'auto', or 'no'\";\n                goto loaderr;\n            }\n        } else if (!strcasecmp(argv[0],\"sentinel\")) {\n            /* argc == 1 is handled by main() as we need to enter the sentinel\n             * mode ASAP. */\n            if (argc != 1) {\n                if (!server.sentinel_mode) {\n                    err = \"sentinel directive while not in sentinel mode\";\n                    goto loaderr;\n                }\n                err = sentinelHandleConfiguration(argv+1,argc-1);\n                if (err) goto loaderr;\n            }\n        } else {\n            err = \"Bad directive or wrong number of arguments\"; goto loaderr;\n        }\n        sdsfreesplitres(argv,argc);\n    }\n\n    /* Sanity checks. */\n    if (server.cluster_enabled && server.masterhost) {\n        linenum = slaveof_linenum;\n        i = linenum-1;\n        err = \"slaveof directive not allowed in cluster mode\";\n        goto loaderr;\n    }\n\n    sdsfreesplitres(lines,totlines);\n    return;\n\nloaderr:\n    fprintf(stderr, \"\\n*** FATAL CONFIG FILE ERROR ***\\n\");\n    fprintf(stderr, \"Reading the configuration file, at line %d\\n\", linenum);\n    fprintf(stderr, \">>> '%s'\\n\", lines[i]);\n    fprintf(stderr, \"%s\\n\", err);\n    exit(1);\n}\n\n/* Load the server configuration from the specified filename.\n * The function appends the additional configuration directives stored\n * in the 'options' string to the config file before loading.\n *\n * Both filename and options can be NULL, in such a case are considered\n * empty. This way loadServerConfig can be used to just load a file or\n * just load a string. */\nvoid loadServerConfig(char *filename, char *options) {\n    sds config = sdsempty();\n    char buf[CONFIG_MAX_LINE+1];\n\n    /* Load the file content */\n    if (filename) {\n        FILE *fp;\n\n        if (filename[0] == '-' && filename[1] == '\\0') {\n            fp = stdin;\n        } else {\n            if ((fp = fopen(filename,\"r\")) == NULL) {\n                serverLog(LL_WARNING,\n                    \"Fatal error, can't open config file '%s'\", filename);\n                exit(1);\n            }\n        }\n        while(fgets(buf,CONFIG_MAX_LINE+1,fp) != NULL)\n            config = sdscat(config,buf);\n        if (fp != stdin) fclose(fp);\n    }\n    /* Append the additional options */\n    if (options) {\n        config = sdscat(config,\"\\n\");\n        config = sdscat(config,options);\n    }\n    loadServerConfigFromString(config);\n    sdsfree(config);\n}\n\n/*-----------------------------------------------------------------------------\n * CONFIG SET implementation\n *----------------------------------------------------------------------------*/\n\n#define config_set_bool_field(_name,_var) \\\n    } else if (!strcasecmp(c->argv[2]->ptr,_name)) { \\\n        int yn = yesnotoi(o->ptr); \\\n        if (yn == -1) goto badfmt; \\\n        _var = yn;\n\n#define config_set_numerical_field(_name,_var,min,max) \\\n    } else if (!strcasecmp(c->argv[2]->ptr,_name)) { \\\n        if (getLongLongFromObject(o,&ll) == C_ERR) goto badfmt; \\\n        if (min != LLONG_MIN && ll < min) goto badfmt; \\\n        if (max != LLONG_MAX && ll > max) goto badfmt; \\\n        _var = ll;\n\n#define config_set_memory_field(_name,_var) \\\n    } else if (!strcasecmp(c->argv[2]->ptr,_name)) { \\\n        ll = memtoll(o->ptr,&err); \\\n        if (err || ll < 0) goto badfmt; \\\n        _var = ll;\n\n#define config_set_enum_field(_name,_var,_enumvar) \\\n    } else if (!strcasecmp(c->argv[2]->ptr,_name)) { \\\n        int enumval = configEnumGetValue(_enumvar,o->ptr); \\\n        if (enumval == INT_MIN) goto badfmt; \\\n        _var = enumval;\n\n#define config_set_special_field(_name) \\\n    } else if (!strcasecmp(c->argv[2]->ptr,_name)) {\n\n#define config_set_else } else\n\nvoid configSetCommand(client *c) {\n    robj *o;\n    long long ll;\n    int err;\n    serverAssertWithInfo(c,c->argv[2],sdsEncodedObject(c->argv[2]));\n    serverAssertWithInfo(c,c->argv[3],sdsEncodedObject(c->argv[3]));\n    o = c->argv[3];\n\n    if (0) { /* this starts the config_set macros else-if chain. */\n\n    /* Special fields that can't be handled with general macros. */\n    config_set_special_field(\"dbfilename\") {\n        if (!pathIsBaseName(o->ptr)) {\n            addReplyError(c, \"dbfilename can't be a path, just a filename\");\n            return;\n        }\n        zfree(server.rdb_filename);\n        server.rdb_filename = zstrdup(o->ptr);\n    } config_set_special_field(\"requirepass\") {\n        if (sdslen(o->ptr) > CONFIG_AUTHPASS_MAX_LEN) goto badfmt;\n        zfree(server.requirepass);\n        server.requirepass = ((char*)o->ptr)[0] ? zstrdup(o->ptr) : NULL;\n    } config_set_special_field(\"masterauth\") {\n        zfree(server.masterauth);\n        server.masterauth = ((char*)o->ptr)[0] ? zstrdup(o->ptr) : NULL;\n    } config_set_special_field(\"maxclients\") {\n        int orig_value = server.maxclients;\n\n        if (getLongLongFromObject(o,&ll) == C_ERR || ll < 1) goto badfmt;\n\n        /* Try to check if the OS is capable of supporting so many FDs. */\n        server.maxclients = ll;\n        if (ll > orig_value) {\n            adjustOpenFilesLimit();\n            if (server.maxclients != ll) {\n                addReplyErrorFormat(c,\"The operating system is not able to handle the specified number of clients, try with %d\", server.maxclients);\n                server.maxclients = orig_value;\n                return;\n            }\n            if ((unsigned int) aeGetSetSize(server.el) <\n                server.maxclients + CONFIG_FDSET_INCR)\n            {\n                if (aeResizeSetSize(server.el,\n                    server.maxclients + CONFIG_FDSET_INCR) == AE_ERR)\n                {\n                    addReplyError(c,\"The event loop API used by Redis is not able to handle the specified number of clients\");\n                    server.maxclients = orig_value;\n                    return;\n                }\n            }\n        }\n    } config_set_special_field(\"appendonly\") {\n        int enable = yesnotoi(o->ptr);\n\n        if (enable == -1) goto badfmt;\n        if (enable == 0 && server.aof_state != AOF_OFF) {\n            stopAppendOnly();\n        } else if (enable && server.aof_state == AOF_OFF) {\n            if (startAppendOnly() == C_ERR) {\n                addReplyError(c,\n                    \"Unable to turn on AOF. Check server logs.\");\n                return;\n            }\n        }\n    } config_set_special_field(\"save\") {\n        int vlen, j;\n        sds *v = sdssplitlen(o->ptr,sdslen(o->ptr),\" \",1,&vlen);\n\n        /* Perform sanity check before setting the new config:\n         * - Even number of args\n         * - Seconds >= 1, changes >= 0 */\n        if (vlen & 1) {\n            sdsfreesplitres(v,vlen);\n            goto badfmt;\n        }\n        for (j = 0; j < vlen; j++) {\n            char *eptr;\n            long val;\n\n            val = strtoll(v[j], &eptr, 10);\n            if (eptr[0] != '\\0' ||\n                ((j & 1) == 0 && val < 1) ||\n                ((j & 1) == 1 && val < 0)) {\n                sdsfreesplitres(v,vlen);\n                goto badfmt;\n            }\n        }\n        /* Finally set the new config */\n        resetServerSaveParams();\n        for (j = 0; j < vlen; j += 2) {\n            time_t seconds;\n            int changes;\n\n            seconds = strtoll(v[j],NULL,10);\n            changes = strtoll(v[j+1],NULL,10);\n            appendServerSaveParams(seconds, changes);\n        }\n        sdsfreesplitres(v,vlen);\n    } config_set_special_field(\"dir\") {\n        if (chdir((char*)o->ptr) == -1) {\n            addReplyErrorFormat(c,\"Changing directory: %s\", strerror(errno));\n            return;\n        }\n    } config_set_special_field(\"client-output-buffer-limit\") {\n        int vlen, j;\n        sds *v = sdssplitlen(o->ptr,sdslen(o->ptr),\" \",1,&vlen);\n\n        /* We need a multiple of 4: <class> <hard> <soft> <soft_seconds> */\n        if (vlen % 4) {\n            sdsfreesplitres(v,vlen);\n            goto badfmt;\n        }\n\n        /* Sanity check of single arguments, so that we either refuse the\n         * whole configuration string or accept it all, even if a single\n         * error in a single client class is present. */\n        for (j = 0; j < vlen; j++) {\n            long val;\n\n            if ((j % 4) == 0) {\n                int class = getClientTypeByName(v[j]);\n                if (class == -1 || class == CLIENT_TYPE_MASTER) {\n                    sdsfreesplitres(v,vlen);\n                    goto badfmt;\n                }\n            } else {\n                val = memtoll(v[j], &err);\n                if (err || val < 0) {\n                    sdsfreesplitres(v,vlen);\n                    goto badfmt;\n                }\n            }\n        }\n        /* Finally set the new config */\n        for (j = 0; j < vlen; j += 4) {\n            int class;\n            unsigned long long hard, soft;\n            int soft_seconds;\n\n            class = getClientTypeByName(v[j]);\n            hard = strtoll(v[j+1],NULL,10);\n            soft = strtoll(v[j+2],NULL,10);\n            soft_seconds = strtoll(v[j+3],NULL,10);\n\n            server.client_obuf_limits[class].hard_limit_bytes = hard;\n            server.client_obuf_limits[class].soft_limit_bytes = soft;\n            server.client_obuf_limits[class].soft_limit_seconds = soft_seconds;\n        }\n        sdsfreesplitres(v,vlen);\n    } config_set_special_field(\"notify-keyspace-events\") {\n        int flags = keyspaceEventsStringToFlags(o->ptr);\n\n        if (flags == -1) goto badfmt;\n        server.notify_keyspace_events = flags;\n    } config_set_special_field(\"slave-announce-ip\") {\n        zfree(server.slave_announce_ip);\n        server.slave_announce_ip = ((char*)o->ptr)[0] ? zstrdup(o->ptr) : NULL;\n\n    /* Boolean fields.\n     * config_set_bool_field(name,var). */\n    } config_set_bool_field(\n      \"rdbcompression\", server.rdb_compression) {\n    } config_set_bool_field(\n      \"repl-disable-tcp-nodelay\",server.repl_disable_tcp_nodelay) {\n    } config_set_bool_field(\n      \"repl-diskless-sync\",server.repl_diskless_sync) {\n    } config_set_bool_field(\n      \"cluster-require-full-coverage\",server.cluster_require_full_coverage) {\n    } config_set_bool_field(\n      \"aof-rewrite-incremental-fsync\",server.aof_rewrite_incremental_fsync) {\n    } config_set_bool_field(\n      \"aof-load-truncated\",server.aof_load_truncated) {\n    } config_set_bool_field(\n      \"slave-serve-stale-data\",server.repl_serve_stale_data) {\n    } config_set_bool_field(\n      \"slave-read-only\",server.repl_slave_ro) {\n    } config_set_bool_field(\n      \"activerehashing\",server.activerehashing) {\n    } config_set_bool_field(\n      \"protected-mode\",server.protected_mode) {\n    } config_set_bool_field(\n      \"stop-writes-on-bgsave-error\",server.stop_writes_on_bgsave_err) {\n    } config_set_bool_field(\n      \"no-appendfsync-on-rewrite\",server.aof_no_fsync_on_rewrite) {\n\n    /* Numerical fields.\n     * config_set_numerical_field(name,var,min,max) */\n    } config_set_numerical_field(\n      \"tcp-keepalive\",server.tcpkeepalive,0,LLONG_MAX) {\n    } config_set_numerical_field(\n      \"maxmemory-samples\",server.maxmemory_samples,1,LLONG_MAX) {\n    } config_set_numerical_field(\n      \"timeout\",server.maxidletime,0,LONG_MAX) {\n    } config_set_numerical_field(\n      \"auto-aof-rewrite-percentage\",server.aof_rewrite_perc,0,LLONG_MAX){\n    } config_set_numerical_field(\n      \"auto-aof-rewrite-min-size\",server.aof_rewrite_min_size,0,LLONG_MAX) {\n    } config_set_numerical_field(\n      \"hash-max-ziplist-entries\",server.hash_max_ziplist_entries,0,LLONG_MAX) {\n    } config_set_numerical_field(\n      \"hash-max-ziplist-value\",server.hash_max_ziplist_value,0,LLONG_MAX) {\n    } config_set_numerical_field(\n      \"list-max-ziplist-size\",server.list_max_ziplist_size,INT_MIN,INT_MAX) {\n    } config_set_numerical_field(\n      \"list-compress-depth\",server.list_compress_depth,0,INT_MAX) {\n    } config_set_numerical_field(\n      \"set-max-intset-entries\",server.set_max_intset_entries,0,LLONG_MAX) {\n    } config_set_numerical_field(\n      \"zset-max-ziplist-entries\",server.zset_max_ziplist_entries,0,LLONG_MAX) {\n    } config_set_numerical_field(\n      \"zset-max-ziplist-value\",server.zset_max_ziplist_value,0,LLONG_MAX) {\n    } config_set_numerical_field(\n      \"hll-sparse-max-bytes\",server.hll_sparse_max_bytes,0,LLONG_MAX) {\n    } config_set_numerical_field(\n      \"lua-time-limit\",server.lua_time_limit,0,LLONG_MAX) {\n    } config_set_numerical_field(\n      \"slowlog-log-slower-than\",server.slowlog_log_slower_than,0,LLONG_MAX) {\n    } config_set_numerical_field(\n      \"slowlog-max-len\",ll,0,LLONG_MAX) {\n      /* Cast to unsigned. */\n        server.slowlog_max_len = (unsigned)ll;\n    } config_set_numerical_field(\n      \"latency-monitor-threshold\",server.latency_monitor_threshold,0,LLONG_MAX){\n    } config_set_numerical_field(\n      \"repl-ping-slave-period\",server.repl_ping_slave_period,1,LLONG_MAX) {\n    } config_set_numerical_field(\n      \"repl-timeout\",server.repl_timeout,1,LLONG_MAX) {\n    } config_set_numerical_field(\n      \"repl-backlog-ttl\",server.repl_backlog_time_limit,0,LLONG_MAX) {\n    } config_set_numerical_field(\n      \"repl-diskless-sync-delay\",server.repl_diskless_sync_delay,0,LLONG_MAX) {\n    } config_set_numerical_field(\n      \"slave-priority\",server.slave_priority,0,LLONG_MAX) {\n    } config_set_numerical_field(\n      \"slave-announce-port\",server.slave_announce_port,0,65535) {\n    } config_set_numerical_field(\n      \"min-slaves-to-write\",server.repl_min_slaves_to_write,0,LLONG_MAX) {\n        refreshGoodSlavesCount();\n    } config_set_numerical_field(\n      \"min-slaves-max-lag\",server.repl_min_slaves_max_lag,0,LLONG_MAX) {\n        refreshGoodSlavesCount();\n    } config_set_numerical_field(\n      \"cluster-node-timeout\",server.cluster_node_timeout,0,LLONG_MAX) {\n    } config_set_numerical_field(\n      \"cluster-migration-barrier\",server.cluster_migration_barrier,0,LLONG_MAX){\n    } config_set_numerical_field(\n      \"cluster-slave-validity-factor\",server.cluster_slave_validity_factor,0,LLONG_MAX) {\n    } config_set_numerical_field(\n      \"hz\",server.hz,0,LLONG_MAX) {\n        /* Hz is more an hint from the user, so we accept values out of range\n         * but cap them to reasonable values. */\n        if (server.hz < CONFIG_MIN_HZ) server.hz = CONFIG_MIN_HZ;\n        if (server.hz > CONFIG_MAX_HZ) server.hz = CONFIG_MAX_HZ;\n    } config_set_numerical_field(\n      \"watchdog-period\",ll,0,LLONG_MAX) {\n        if (ll)\n            enableWatchdog(ll);\n        else\n            disableWatchdog();\n\n    /* Memory fields.\n     * config_set_memory_field(name,var) */\n    } config_set_memory_field(\"maxmemory\",server.maxmemory) {\n        if (server.maxmemory) {\n            if (server.maxmemory < zmalloc_used_memory()) {\n                serverLog(LL_WARNING,\"WARNING: the new maxmemory value set via CONFIG SET is smaller than the current memory usage. This will result in keys eviction and/or inability to accept new write commands depending on the maxmemory-policy.\");\n            }\n            freeMemoryIfNeeded();\n        }\n    } config_set_memory_field(\"repl-backlog-size\",ll) {\n        resizeReplicationBacklog(ll);\n\n    /* Enumeration fields.\n     * config_set_enum_field(name,var,enum_var) */\n    } config_set_enum_field(\n      \"loglevel\",server.verbosity,loglevel_enum) {\n    } config_set_enum_field(\n      \"maxmemory-policy\",server.maxmemory_policy,maxmemory_policy_enum) {\n    } config_set_enum_field(\n      \"appendfsync\",server.aof_fsync,aof_fsync_enum) {\n\n    /* Everyhing else is an error... */\n    } config_set_else {\n        addReplyErrorFormat(c,\"Unsupported CONFIG parameter: %s\",\n            (char*)c->argv[2]->ptr);\n        return;\n    }\n\n    /* On success we just return a generic OK for all the options. */\n    addReply(c,shared.ok);\n    return;\n\nbadfmt: /* Bad format errors */\n    addReplyErrorFormat(c,\"Invalid argument '%s' for CONFIG SET '%s'\",\n            (char*)o->ptr,\n            (char*)c->argv[2]->ptr);\n}\n\n/*-----------------------------------------------------------------------------\n * CONFIG GET implementation\n *----------------------------------------------------------------------------*/\n\n#define config_get_string_field(_name,_var) do { \\\n    if (stringmatch(pattern,_name,1)) { \\\n        addReplyBulkCString(c,_name); \\\n        addReplyBulkCString(c,_var ? _var : \"\"); \\\n        matches++; \\\n    } \\\n} while(0);\n\n#define config_get_bool_field(_name,_var) do { \\\n    if (stringmatch(pattern,_name,1)) { \\\n        addReplyBulkCString(c,_name); \\\n        addReplyBulkCString(c,_var ? \"yes\" : \"no\"); \\\n        matches++; \\\n    } \\\n} while(0);\n\n#define config_get_numerical_field(_name,_var) do { \\\n    if (stringmatch(pattern,_name,1)) { \\\n        ll2string(buf,sizeof(buf),_var); \\\n        addReplyBulkCString(c,_name); \\\n        addReplyBulkCString(c,buf); \\\n        matches++; \\\n    } \\\n} while(0);\n\n#define config_get_enum_field(_name,_var,_enumvar) do { \\\n    if (stringmatch(pattern,_name,1)) { \\\n        addReplyBulkCString(c,_name); \\\n        addReplyBulkCString(c,configEnumGetNameOrUnknown(_enumvar,_var)); \\\n        matches++; \\\n    } \\\n} while(0);\n\nvoid configGetCommand(client *c) {\n    robj *o = c->argv[2];\n    void *replylen = addDeferredMultiBulkLength(c);\n    char *pattern = o->ptr;\n    char buf[128];\n    int matches = 0;\n    serverAssertWithInfo(c,o,sdsEncodedObject(o));\n\n    /* String values */\n    config_get_string_field(\"dbfilename\",server.rdb_filename);\n    config_get_string_field(\"requirepass\",server.requirepass);\n    config_get_string_field(\"masterauth\",server.masterauth);\n    config_get_string_field(\"unixsocket\",server.unixsocket);\n    config_get_string_field(\"logfile\",server.logfile);\n    config_get_string_field(\"pidfile\",server.pidfile);\n    config_get_string_field(\"slave-announce-ip\",server.slave_announce_ip);\n\n    /* Numerical values */\n    config_get_numerical_field(\"maxmemory\",server.maxmemory);\n    config_get_numerical_field(\"maxmemory-samples\",server.maxmemory_samples);\n    config_get_numerical_field(\"timeout\",server.maxidletime);\n    config_get_numerical_field(\"auto-aof-rewrite-percentage\",\n            server.aof_rewrite_perc);\n    config_get_numerical_field(\"auto-aof-rewrite-min-size\",\n            server.aof_rewrite_min_size);\n    config_get_numerical_field(\"hash-max-ziplist-entries\",\n            server.hash_max_ziplist_entries);\n    config_get_numerical_field(\"hash-max-ziplist-value\",\n            server.hash_max_ziplist_value);\n    config_get_numerical_field(\"list-max-ziplist-size\",\n            server.list_max_ziplist_size);\n    config_get_numerical_field(\"list-compress-depth\",\n            server.list_compress_depth);\n    config_get_numerical_field(\"set-max-intset-entries\",\n            server.set_max_intset_entries);\n    config_get_numerical_field(\"zset-max-ziplist-entries\",\n            server.zset_max_ziplist_entries);\n    config_get_numerical_field(\"zset-max-ziplist-value\",\n            server.zset_max_ziplist_value);\n    config_get_numerical_field(\"hll-sparse-max-bytes\",\n            server.hll_sparse_max_bytes);\n    config_get_numerical_field(\"lua-time-limit\",server.lua_time_limit);\n    config_get_numerical_field(\"slowlog-log-slower-than\",\n            server.slowlog_log_slower_than);\n    config_get_numerical_field(\"latency-monitor-threshold\",\n            server.latency_monitor_threshold);\n    config_get_numerical_field(\"slowlog-max-len\",\n            server.slowlog_max_len);\n    config_get_numerical_field(\"port\",server.port);\n    config_get_numerical_field(\"tcp-backlog\",server.tcp_backlog);\n    config_get_numerical_field(\"databases\",server.dbnum);\n    config_get_numerical_field(\"repl-ping-slave-period\",server.repl_ping_slave_period);\n    config_get_numerical_field(\"repl-timeout\",server.repl_timeout);\n    config_get_numerical_field(\"repl-backlog-size\",server.repl_backlog_size);\n    config_get_numerical_field(\"repl-backlog-ttl\",server.repl_backlog_time_limit);\n    config_get_numerical_field(\"maxclients\",server.maxclients);\n    config_get_numerical_field(\"watchdog-period\",server.watchdog_period);\n    config_get_numerical_field(\"slave-priority\",server.slave_priority);\n    config_get_numerical_field(\"slave-announce-port\",server.slave_announce_port);\n    config_get_numerical_field(\"min-slaves-to-write\",server.repl_min_slaves_to_write);\n    config_get_numerical_field(\"min-slaves-max-lag\",server.repl_min_slaves_max_lag);\n    config_get_numerical_field(\"hz\",server.hz);\n    config_get_numerical_field(\"cluster-node-timeout\",server.cluster_node_timeout);\n    config_get_numerical_field(\"cluster-migration-barrier\",server.cluster_migration_barrier);\n    config_get_numerical_field(\"cluster-slave-validity-factor\",server.cluster_slave_validity_factor);\n    config_get_numerical_field(\"repl-diskless-sync-delay\",server.repl_diskless_sync_delay);\n    config_get_numerical_field(\"tcp-keepalive\",server.tcpkeepalive);\n\n    /* Bool (yes/no) values */\n    config_get_bool_field(\"cluster-require-full-coverage\",\n            server.cluster_require_full_coverage);\n    config_get_bool_field(\"no-appendfsync-on-rewrite\",\n            server.aof_no_fsync_on_rewrite);\n    config_get_bool_field(\"slave-serve-stale-data\",\n            server.repl_serve_stale_data);\n    config_get_bool_field(\"slave-read-only\",\n            server.repl_slave_ro);\n    config_get_bool_field(\"stop-writes-on-bgsave-error\",\n            server.stop_writes_on_bgsave_err);\n    config_get_bool_field(\"daemonize\", server.daemonize);\n    config_get_bool_field(\"rdbcompression\", server.rdb_compression);\n    config_get_bool_field(\"rdbchecksum\", server.rdb_checksum);\n    config_get_bool_field(\"activerehashing\", server.activerehashing);\n    config_get_bool_field(\"protected-mode\", server.protected_mode);\n    config_get_bool_field(\"repl-disable-tcp-nodelay\",\n            server.repl_disable_tcp_nodelay);\n    config_get_bool_field(\"repl-diskless-sync\",\n            server.repl_diskless_sync);\n    config_get_bool_field(\"aof-rewrite-incremental-fsync\",\n            server.aof_rewrite_incremental_fsync);\n    config_get_bool_field(\"aof-load-truncated\",\n            server.aof_load_truncated);\n\n    /* Enum values */\n    config_get_enum_field(\"maxmemory-policy\",\n            server.maxmemory_policy,maxmemory_policy_enum);\n    config_get_enum_field(\"loglevel\",\n            server.verbosity,loglevel_enum);\n    config_get_enum_field(\"supervised\",\n            server.supervised_mode,supervised_mode_enum);\n    config_get_enum_field(\"appendfsync\",\n            server.aof_fsync,aof_fsync_enum);\n    config_get_enum_field(\"syslog-facility\",\n            server.syslog_facility,syslog_facility_enum);\n\n    /* Everything we can't handle with macros follows. */\n\n    if (stringmatch(pattern,\"appendonly\",1)) {\n        addReplyBulkCString(c,\"appendonly\");\n        addReplyBulkCString(c,server.aof_state == AOF_OFF ? \"no\" : \"yes\");\n        matches++;\n    }\n    if (stringmatch(pattern,\"dir\",1)) {\n        char buf[1024];\n\n        if (getcwd(buf,sizeof(buf)) == NULL)\n            buf[0] = '\\0';\n\n        addReplyBulkCString(c,\"dir\");\n        addReplyBulkCString(c,buf);\n        matches++;\n    }\n    if (stringmatch(pattern,\"save\",1)) {\n        sds buf = sdsempty();\n        int j;\n\n        for (j = 0; j < server.saveparamslen; j++) {\n            buf = sdscatprintf(buf,\"%jd %d\",\n                    (intmax_t)server.saveparams[j].seconds,\n                    server.saveparams[j].changes);\n            if (j != server.saveparamslen-1)\n                buf = sdscatlen(buf,\" \",1);\n        }\n        addReplyBulkCString(c,\"save\");\n        addReplyBulkCString(c,buf);\n        sdsfree(buf);\n        matches++;\n    }\n    if (stringmatch(pattern,\"client-output-buffer-limit\",1)) {\n        sds buf = sdsempty();\n        int j;\n\n        for (j = 0; j < CLIENT_TYPE_OBUF_COUNT; j++) {\n            buf = sdscatprintf(buf,\"%s %llu %llu %ld\",\n                    getClientTypeName(j),\n                    server.client_obuf_limits[j].hard_limit_bytes,\n                    server.client_obuf_limits[j].soft_limit_bytes,\n                    (long) server.client_obuf_limits[j].soft_limit_seconds);\n            if (j != CLIENT_TYPE_OBUF_COUNT-1)\n                buf = sdscatlen(buf,\" \",1);\n        }\n        addReplyBulkCString(c,\"client-output-buffer-limit\");\n        addReplyBulkCString(c,buf);\n        sdsfree(buf);\n        matches++;\n    }\n    if (stringmatch(pattern,\"unixsocketperm\",1)) {\n        char buf[32];\n        snprintf(buf,sizeof(buf),\"%o\",server.unixsocketperm);\n        addReplyBulkCString(c,\"unixsocketperm\");\n        addReplyBulkCString(c,buf);\n        matches++;\n    }\n    if (stringmatch(pattern,\"slaveof\",1)) {\n        char buf[256];\n\n        addReplyBulkCString(c,\"slaveof\");\n        if (server.masterhost)\n            snprintf(buf,sizeof(buf),\"%s %d\",\n                server.masterhost, server.masterport);\n        else\n            buf[0] = '\\0';\n        addReplyBulkCString(c,buf);\n        matches++;\n    }\n    if (stringmatch(pattern,\"notify-keyspace-events\",1)) {\n        robj *flagsobj = createObject(OBJ_STRING,\n            keyspaceEventsFlagsToString(server.notify_keyspace_events));\n\n        addReplyBulkCString(c,\"notify-keyspace-events\");\n        addReplyBulk(c,flagsobj);\n        decrRefCount(flagsobj);\n        matches++;\n    }\n    if (stringmatch(pattern,\"bind\",1)) {\n        sds aux = sdsjoin(server.bindaddr,server.bindaddr_count,\" \");\n\n        addReplyBulkCString(c,\"bind\");\n        addReplyBulkCString(c,aux);\n        sdsfree(aux);\n        matches++;\n    }\n    setDeferredMultiBulkLength(c,replylen,matches*2);\n}\n\n/*-----------------------------------------------------------------------------\n * CONFIG REWRITE implementation\n *----------------------------------------------------------------------------*/\n\n#define REDIS_CONFIG_REWRITE_SIGNATURE \"# Generated by CONFIG REWRITE\"\n\n/* We use the following dictionary type to store where a configuration\n * option is mentioned in the old configuration file, so it's\n * like \"maxmemory\" -> list of line numbers (first line is zero). */\nunsigned int dictSdsCaseHash(const void *key);\nint dictSdsKeyCaseCompare(void *privdata, const void *key1, const void *key2);\nvoid dictSdsDestructor(void *privdata, void *val);\nvoid dictListDestructor(void *privdata, void *val);\n\n/* Sentinel config rewriting is implemented inside sentinel.c by\n * rewriteConfigSentinelOption(). */\nvoid rewriteConfigSentinelOption(struct rewriteConfigState *state);\n\ndictType optionToLineDictType = {\n    dictSdsCaseHash,            /* hash function */\n    NULL,                       /* key dup */\n    NULL,                       /* val dup */\n    dictSdsKeyCaseCompare,      /* key compare */\n    dictSdsDestructor,          /* key destructor */\n    dictListDestructor          /* val destructor */\n};\n\ndictType optionSetDictType = {\n    dictSdsCaseHash,            /* hash function */\n    NULL,                       /* key dup */\n    NULL,                       /* val dup */\n    dictSdsKeyCaseCompare,      /* key compare */\n    dictSdsDestructor,          /* key destructor */\n    NULL                        /* val destructor */\n};\n\n/* The config rewrite state. */\nstruct rewriteConfigState {\n    dict *option_to_line; /* Option -> list of config file lines map */\n    dict *rewritten;      /* Dictionary of already processed options */\n    int numlines;         /* Number of lines in current config */\n    sds *lines;           /* Current lines as an array of sds strings */\n    int has_tail;         /* True if we already added directives that were\n                             not present in the original config file. */\n};\n\n/* Append the new line to the current configuration state. */\nvoid rewriteConfigAppendLine(struct rewriteConfigState *state, sds line) {\n    state->lines = zrealloc(state->lines, sizeof(char*) * (state->numlines+1));\n    state->lines[state->numlines++] = line;\n}\n\n/* Populate the option -> list of line numbers map. */\nvoid rewriteConfigAddLineNumberToOption(struct rewriteConfigState *state, sds option, int linenum) {\n    list *l = dictFetchValue(state->option_to_line,option);\n\n    if (l == NULL) {\n        l = listCreate();\n        dictAdd(state->option_to_line,sdsdup(option),l);\n    }\n    listAddNodeTail(l,(void*)(long)linenum);\n}\n\n/* Add the specified option to the set of processed options.\n * This is useful as only unused lines of processed options will be blanked\n * in the config file, while options the rewrite process does not understand\n * remain untouched. */\nvoid rewriteConfigMarkAsProcessed(struct rewriteConfigState *state, const char *option) {\n    sds opt = sdsnew(option);\n\n    if (dictAdd(state->rewritten,opt,NULL) != DICT_OK) sdsfree(opt);\n}\n\n/* Read the old file, split it into lines to populate a newly created\n * config rewrite state, and return it to the caller.\n *\n * If it is impossible to read the old file, NULL is returned.\n * If the old file does not exist at all, an empty state is returned. */\nstruct rewriteConfigState *rewriteConfigReadOldFile(char *path) {\n    FILE *fp = fopen(path,\"r\");\n    struct rewriteConfigState *state = zmalloc(sizeof(*state));\n    char buf[CONFIG_MAX_LINE+1];\n    int linenum = -1;\n\n    if (fp == NULL && errno != ENOENT) return NULL;\n\n    state->option_to_line = dictCreate(&optionToLineDictType,NULL);\n    state->rewritten = dictCreate(&optionSetDictType,NULL);\n    state->numlines = 0;\n    state->lines = NULL;\n    state->has_tail = 0;\n    if (fp == NULL) return state;\n\n    /* Read the old file line by line, populate the state. */\n    while(fgets(buf,CONFIG_MAX_LINE+1,fp) != NULL) {\n        int argc;\n        sds *argv;\n        sds line = sdstrim(sdsnew(buf),\"\\r\\n\\t \");\n\n        linenum++; /* Zero based, so we init at -1 */\n\n        /* Handle comments and empty lines. */\n        if (line[0] == '#' || line[0] == '\\0') {\n            if (!state->has_tail && !strcmp(line,REDIS_CONFIG_REWRITE_SIGNATURE))\n                state->has_tail = 1;\n            rewriteConfigAppendLine(state,line);\n            continue;\n        }\n\n        /* Not a comment, split into arguments. */\n        argv = sdssplitargs(line,&argc);\n        if (argv == NULL) {\n            /* Apparently the line is unparsable for some reason, for\n             * instance it may have unbalanced quotes. Load it as a\n             * comment. */\n            sds aux = sdsnew(\"# ??? \");\n            aux = sdscatsds(aux,line);\n            sdsfree(line);\n            rewriteConfigAppendLine(state,aux);\n            continue;\n        }\n\n        sdstolower(argv[0]); /* We only want lowercase config directives. */\n\n        /* Now we populate the state according to the content of this line.\n         * Append the line and populate the option -> line numbers map. */\n        rewriteConfigAppendLine(state,line);\n        rewriteConfigAddLineNumberToOption(state,argv[0],linenum);\n\n        sdsfreesplitres(argv,argc);\n    }\n    fclose(fp);\n    return state;\n}\n\n/* Rewrite the specified configuration option with the new \"line\".\n * It progressively uses lines of the file that were already used for the same\n * configuration option in the old version of the file, removing that line from\n * the map of options -> line numbers.\n *\n * If there are lines associated with a given configuration option and\n * \"force\" is non-zero, the line is appended to the configuration file.\n * Usually \"force\" is true when an option has not its default value, so it\n * must be rewritten even if not present previously.\n *\n * The first time a line is appended into a configuration file, a comment\n * is added to show that starting from that point the config file was generated\n * by CONFIG REWRITE.\n *\n * \"line\" is either used, or freed, so the caller does not need to free it\n * in any way. */\nvoid rewriteConfigRewriteLine(struct rewriteConfigState *state, const char *option, sds line, int force) {\n    sds o = sdsnew(option);\n    list *l = dictFetchValue(state->option_to_line,o);\n\n    rewriteConfigMarkAsProcessed(state,option);\n\n    if (!l && !force) {\n        /* Option not used previously, and we are not forced to use it. */\n        sdsfree(line);\n        sdsfree(o);\n        return;\n    }\n\n    if (l) {\n        listNode *ln = listFirst(l);\n        int linenum = (long) ln->value;\n\n        /* There are still lines in the old configuration file we can reuse\n         * for this option. Replace the line with the new one. */\n        listDelNode(l,ln);\n        if (listLength(l) == 0) dictDelete(state->option_to_line,o);\n        sdsfree(state->lines[linenum]);\n        state->lines[linenum] = line;\n    } else {\n        /* Append a new line. */\n        if (!state->has_tail) {\n            rewriteConfigAppendLine(state,\n                sdsnew(REDIS_CONFIG_REWRITE_SIGNATURE));\n            state->has_tail = 1;\n        }\n        rewriteConfigAppendLine(state,line);\n    }\n    sdsfree(o);\n}\n\n/* Write the long long 'bytes' value as a string in a way that is parsable\n * inside redis.conf. If possible uses the GB, MB, KB notation. */\nint rewriteConfigFormatMemory(char *buf, size_t len, long long bytes) {\n    int gb = 1024*1024*1024;\n    int mb = 1024*1024;\n    int kb = 1024;\n\n    if (bytes && (bytes % gb) == 0) {\n        return snprintf(buf,len,\"%lldgb\",bytes/gb);\n    } else if (bytes && (bytes % mb) == 0) {\n        return snprintf(buf,len,\"%lldmb\",bytes/mb);\n    } else if (bytes && (bytes % kb) == 0) {\n        return snprintf(buf,len,\"%lldkb\",bytes/kb);\n    } else {\n        return snprintf(buf,len,\"%lld\",bytes);\n    }\n}\n\n/* Rewrite a simple \"option-name <bytes>\" configuration option. */\nvoid rewriteConfigBytesOption(struct rewriteConfigState *state, char *option, long long value, long long defvalue) {\n    char buf[64];\n    int force = value != defvalue;\n    sds line;\n\n    rewriteConfigFormatMemory(buf,sizeof(buf),value);\n    line = sdscatprintf(sdsempty(),\"%s %s\",option,buf);\n    rewriteConfigRewriteLine(state,option,line,force);\n}\n\n/* Rewrite a yes/no option. */\nvoid rewriteConfigYesNoOption(struct rewriteConfigState *state, char *option, int value, int defvalue) {\n    int force = value != defvalue;\n    sds line = sdscatprintf(sdsempty(),\"%s %s\",option,\n        value ? \"yes\" : \"no\");\n\n    rewriteConfigRewriteLine(state,option,line,force);\n}\n\n/* Rewrite a string option. */\nvoid rewriteConfigStringOption(struct rewriteConfigState *state, char *option, char *value, char *defvalue) {\n    int force = 1;\n    sds line;\n\n    /* String options set to NULL need to be not present at all in the\n     * configuration file to be set to NULL again at the next reboot. */\n    if (value == NULL) {\n        rewriteConfigMarkAsProcessed(state,option);\n        return;\n    }\n\n    /* Set force to zero if the value is set to its default. */\n    if (defvalue && strcmp(value,defvalue) == 0) force = 0;\n\n    line = sdsnew(option);\n    line = sdscatlen(line, \" \", 1);\n    line = sdscatrepr(line, value, strlen(value));\n\n    rewriteConfigRewriteLine(state,option,line,force);\n}\n\n/* Rewrite a numerical (long long range) option. */\nvoid rewriteConfigNumericalOption(struct rewriteConfigState *state, char *option, long long value, long long defvalue) {\n    int force = value != defvalue;\n    sds line = sdscatprintf(sdsempty(),\"%s %lld\",option,value);\n\n    rewriteConfigRewriteLine(state,option,line,force);\n}\n\n/* Rewrite a octal option. */\nvoid rewriteConfigOctalOption(struct rewriteConfigState *state, char *option, int value, int defvalue) {\n    int force = value != defvalue;\n    sds line = sdscatprintf(sdsempty(),\"%s %o\",option,value);\n\n    rewriteConfigRewriteLine(state,option,line,force);\n}\n\n/* Rewrite an enumeration option. It takes as usually state and option name,\n * and in addition the enumeration array and the default value for the\n * option. */\nvoid rewriteConfigEnumOption(struct rewriteConfigState *state, char *option, int value, configEnum *ce, int defval) {\n    sds line;\n    const char *name = configEnumGetNameOrUnknown(ce,value);\n    int force = value != defval;\n\n    line = sdscatprintf(sdsempty(),\"%s %s\",option,name);\n    rewriteConfigRewriteLine(state,option,line,force);\n}\n\n/* Rewrite the syslog-facility option. */\nvoid rewriteConfigSyslogfacilityOption(struct rewriteConfigState *state) {\n    int value = server.syslog_facility;\n    int force = value != LOG_LOCAL0;\n    const char *name = NULL, *option = \"syslog-facility\";\n    sds line;\n\n    name = configEnumGetNameOrUnknown(syslog_facility_enum,value);\n    line = sdscatprintf(sdsempty(),\"%s %s\",option,name);\n    rewriteConfigRewriteLine(state,option,line,force);\n}\n\n/* Rewrite the save option. */\nvoid rewriteConfigSaveOption(struct rewriteConfigState *state) {\n    int j;\n    sds line;\n\n    /* Note that if there are no save parameters at all, all the current\n     * config line with \"save\" will be detected as orphaned and deleted,\n     * resulting into no RDB persistence as expected. */\n    for (j = 0; j < server.saveparamslen; j++) {\n        line = sdscatprintf(sdsempty(),\"save %ld %d\",\n            (long) server.saveparams[j].seconds, server.saveparams[j].changes);\n        rewriteConfigRewriteLine(state,\"save\",line,1);\n    }\n    /* Mark \"save\" as processed in case server.saveparamslen is zero. */\n    rewriteConfigMarkAsProcessed(state,\"save\");\n}\n\n/* Rewrite the dir option, always using absolute paths.*/\nvoid rewriteConfigDirOption(struct rewriteConfigState *state) {\n    char cwd[1024];\n\n    if (getcwd(cwd,sizeof(cwd)) == NULL) {\n        rewriteConfigMarkAsProcessed(state,\"dir\");\n        return; /* no rewrite on error. */\n    }\n    rewriteConfigStringOption(state,\"dir\",cwd,NULL);\n}\n\n/* Rewrite the slaveof option. */\nvoid rewriteConfigSlaveofOption(struct rewriteConfigState *state) {\n    char *option = \"slaveof\";\n    sds line;\n\n    /* If this is a master, we want all the slaveof config options\n     * in the file to be removed. Note that if this is a cluster instance\n     * we don't want a slaveof directive inside redis.conf. */\n    if (server.cluster_enabled || server.masterhost == NULL) {\n        rewriteConfigMarkAsProcessed(state,\"slaveof\");\n        return;\n    }\n    line = sdscatprintf(sdsempty(),\"%s %s %d\", option,\n        server.masterhost, server.masterport);\n    rewriteConfigRewriteLine(state,option,line,1);\n}\n\n/* Rewrite the notify-keyspace-events option. */\nvoid rewriteConfigNotifykeyspaceeventsOption(struct rewriteConfigState *state) {\n    int force = server.notify_keyspace_events != 0;\n    char *option = \"notify-keyspace-events\";\n    sds line, flags;\n\n    flags = keyspaceEventsFlagsToString(server.notify_keyspace_events);\n    line = sdsnew(option);\n    line = sdscatlen(line, \" \", 1);\n    line = sdscatrepr(line, flags, sdslen(flags));\n    sdsfree(flags);\n    rewriteConfigRewriteLine(state,option,line,force);\n}\n\n/* Rewrite the client-output-buffer-limit option. */\nvoid rewriteConfigClientoutputbufferlimitOption(struct rewriteConfigState *state) {\n    int j;\n    char *option = \"client-output-buffer-limit\";\n\n    for (j = 0; j < CLIENT_TYPE_OBUF_COUNT; j++) {\n        int force = (server.client_obuf_limits[j].hard_limit_bytes !=\n                    clientBufferLimitsDefaults[j].hard_limit_bytes) ||\n                    (server.client_obuf_limits[j].soft_limit_bytes !=\n                    clientBufferLimitsDefaults[j].soft_limit_bytes) ||\n                    (server.client_obuf_limits[j].soft_limit_seconds !=\n                    clientBufferLimitsDefaults[j].soft_limit_seconds);\n        sds line;\n        char hard[64], soft[64];\n\n        rewriteConfigFormatMemory(hard,sizeof(hard),\n                server.client_obuf_limits[j].hard_limit_bytes);\n        rewriteConfigFormatMemory(soft,sizeof(soft),\n                server.client_obuf_limits[j].soft_limit_bytes);\n\n        line = sdscatprintf(sdsempty(),\"%s %s %s %s %ld\",\n                option, getClientTypeName(j), hard, soft,\n                (long) server.client_obuf_limits[j].soft_limit_seconds);\n        rewriteConfigRewriteLine(state,option,line,force);\n    }\n}\n\n/* Rewrite the bind option. */\nvoid rewriteConfigBindOption(struct rewriteConfigState *state) {\n    int force = 1;\n    sds line, addresses;\n    char *option = \"bind\";\n\n    /* Nothing to rewrite if we don't have bind addresses. */\n    if (server.bindaddr_count == 0) {\n        rewriteConfigMarkAsProcessed(state,option);\n        return;\n    }\n\n    /* Rewrite as bind <addr1> <addr2> ... <addrN> */\n    addresses = sdsjoin(server.bindaddr,server.bindaddr_count,\" \");\n    line = sdsnew(option);\n    line = sdscatlen(line, \" \", 1);\n    line = sdscatsds(line, addresses);\n    sdsfree(addresses);\n\n    rewriteConfigRewriteLine(state,option,line,force);\n}\n\n/* Glue together the configuration lines in the current configuration\n * rewrite state into a single string, stripping multiple empty lines. */\nsds rewriteConfigGetContentFromState(struct rewriteConfigState *state) {\n    sds content = sdsempty();\n    int j, was_empty = 0;\n\n    for (j = 0; j < state->numlines; j++) {\n        /* Every cluster of empty lines is turned into a single empty line. */\n        if (sdslen(state->lines[j]) == 0) {\n            if (was_empty) continue;\n            was_empty = 1;\n        } else {\n            was_empty = 0;\n        }\n        content = sdscatsds(content,state->lines[j]);\n        content = sdscatlen(content,\"\\n\",1);\n    }\n    return content;\n}\n\n/* Free the configuration rewrite state. */\nvoid rewriteConfigReleaseState(struct rewriteConfigState *state) {\n    sdsfreesplitres(state->lines,state->numlines);\n    dictRelease(state->option_to_line);\n    dictRelease(state->rewritten);\n    zfree(state);\n}\n\n/* At the end of the rewrite process the state contains the remaining\n * map between \"option name\" => \"lines in the original config file\".\n * Lines used by the rewrite process were removed by the function\n * rewriteConfigRewriteLine(), all the other lines are \"orphaned\" and\n * should be replaced by empty lines.\n *\n * This function does just this, iterating all the option names and\n * blanking all the lines still associated. */\nvoid rewriteConfigRemoveOrphaned(struct rewriteConfigState *state) {\n    dictIterator *di = dictGetIterator(state->option_to_line);\n    dictEntry *de;\n\n    while((de = dictNext(di)) != NULL) {\n        list *l = dictGetVal(de);\n        sds option = dictGetKey(de);\n\n        /* Don't blank lines about options the rewrite process\n         * don't understand. */\n        if (dictFind(state->rewritten,option) == NULL) {\n            serverLog(LL_DEBUG,\"Not rewritten option: %s\", option);\n            continue;\n        }\n\n        while(listLength(l)) {\n            listNode *ln = listFirst(l);\n            int linenum = (long) ln->value;\n\n            sdsfree(state->lines[linenum]);\n            state->lines[linenum] = sdsempty();\n            listDelNode(l,ln);\n        }\n    }\n    dictReleaseIterator(di);\n}\n\n/* This function overwrites the old configuration file with the new content.\n *\n * 1) The old file length is obtained.\n * 2) If the new content is smaller, padding is added.\n * 3) A single write(2) call is used to replace the content of the file.\n * 4) Later the file is truncated to the length of the new content.\n *\n * This way we are sure the file is left in a consistent state even if the\n * process is stopped between any of the four operations.\n *\n * The function returns 0 on success, otherwise -1 is returned and errno\n * set accordingly. */\nint rewriteConfigOverwriteFile(char *configfile, sds content) {\n    int retval = 0;\n    int fd = open(configfile,O_RDWR|O_CREAT,0644);\n    int content_size = sdslen(content), padding = 0;\n    struct stat sb;\n    sds content_padded;\n\n    /* 1) Open the old file (or create a new one if it does not\n     *    exist), get the size. */\n    if (fd == -1) return -1; /* errno set by open(). */\n    if (fstat(fd,&sb) == -1) {\n        close(fd);\n        return -1; /* errno set by fstat(). */\n    }\n\n    /* 2) Pad the content at least match the old file size. */\n    content_padded = sdsdup(content);\n    if (content_size < sb.st_size) {\n        /* If the old file was bigger, pad the content with\n         * a newline plus as many \"#\" chars as required. */\n        padding = sb.st_size - content_size;\n        content_padded = sdsgrowzero(content_padded,sb.st_size);\n        content_padded[content_size] = '\\n';\n        memset(content_padded+content_size+1,'#',padding-1);\n    }\n\n    /* 3) Write the new content using a single write(2). */\n    if (write(fd,content_padded,strlen(content_padded)) == -1) {\n        retval = -1;\n        goto cleanup;\n    }\n\n    /* 4) Truncate the file to the right length if we used padding. */\n    if (padding) {\n        if (ftruncate(fd,content_size) == -1) {\n            /* Non critical error... */\n        }\n    }\n\ncleanup:\n    sdsfree(content_padded);\n    close(fd);\n    return retval;\n}\n\n/* Rewrite the configuration file at \"path\".\n * If the configuration file already exists, we try at best to retain comments\n * and overall structure.\n *\n * Configuration parameters that are at their default value, unless already\n * explicitly included in the old configuration file, are not rewritten.\n *\n * On error -1 is returned and errno is set accordingly, otherwise 0. */\nint rewriteConfig(char *path) {\n    struct rewriteConfigState *state;\n    sds newcontent;\n    int retval;\n\n    /* Step 1: read the old config into our rewrite state. */\n    if ((state = rewriteConfigReadOldFile(path)) == NULL) return -1;\n\n    /* Step 2: rewrite every single option, replacing or appending it inside\n     * the rewrite state. */\n\n    rewriteConfigYesNoOption(state,\"daemonize\",server.daemonize,0);\n    rewriteConfigStringOption(state,\"pidfile\",server.pidfile,CONFIG_DEFAULT_PID_FILE);\n    rewriteConfigNumericalOption(state,\"port\",server.port,CONFIG_DEFAULT_SERVER_PORT);\n    rewriteConfigNumericalOption(state,\"tcp-backlog\",server.tcp_backlog,CONFIG_DEFAULT_TCP_BACKLOG);\n    rewriteConfigBindOption(state);\n    rewriteConfigStringOption(state,\"unixsocket\",server.unixsocket,NULL);\n    rewriteConfigOctalOption(state,\"unixsocketperm\",server.unixsocketperm,CONFIG_DEFAULT_UNIX_SOCKET_PERM);\n    rewriteConfigNumericalOption(state,\"timeout\",server.maxidletime,CONFIG_DEFAULT_CLIENT_TIMEOUT);\n    rewriteConfigNumericalOption(state,\"tcp-keepalive\",server.tcpkeepalive,CONFIG_DEFAULT_TCP_KEEPALIVE);\n    rewriteConfigNumericalOption(state,\"slave-announce-port\",server.slave_announce_port,CONFIG_DEFAULT_SLAVE_ANNOUNCE_PORT);\n    rewriteConfigEnumOption(state,\"loglevel\",server.verbosity,loglevel_enum,CONFIG_DEFAULT_VERBOSITY);\n    rewriteConfigStringOption(state,\"logfile\",server.logfile,CONFIG_DEFAULT_LOGFILE);\n    rewriteConfigYesNoOption(state,\"syslog-enabled\",server.syslog_enabled,CONFIG_DEFAULT_SYSLOG_ENABLED);\n    rewriteConfigStringOption(state,\"syslog-ident\",server.syslog_ident,CONFIG_DEFAULT_SYSLOG_IDENT);\n    rewriteConfigSyslogfacilityOption(state);\n    rewriteConfigSaveOption(state);\n    rewriteConfigNumericalOption(state,\"databases\",server.dbnum,CONFIG_DEFAULT_DBNUM);\n    rewriteConfigYesNoOption(state,\"stop-writes-on-bgsave-error\",server.stop_writes_on_bgsave_err,CONFIG_DEFAULT_STOP_WRITES_ON_BGSAVE_ERROR);\n    rewriteConfigYesNoOption(state,\"rdbcompression\",server.rdb_compression,CONFIG_DEFAULT_RDB_COMPRESSION);\n    rewriteConfigYesNoOption(state,\"rdbchecksum\",server.rdb_checksum,CONFIG_DEFAULT_RDB_CHECKSUM);\n    rewriteConfigStringOption(state,\"dbfilename\",server.rdb_filename,CONFIG_DEFAULT_RDB_FILENAME);\n    rewriteConfigDirOption(state);\n    rewriteConfigSlaveofOption(state);\n    rewriteConfigStringOption(state,\"slave-announce-ip\",server.slave_announce_ip,CONFIG_DEFAULT_SLAVE_ANNOUNCE_IP);\n    rewriteConfigStringOption(state,\"masterauth\",server.masterauth,NULL);\n    rewriteConfigYesNoOption(state,\"slave-serve-stale-data\",server.repl_serve_stale_data,CONFIG_DEFAULT_SLAVE_SERVE_STALE_DATA);\n    rewriteConfigYesNoOption(state,\"slave-read-only\",server.repl_slave_ro,CONFIG_DEFAULT_SLAVE_READ_ONLY);\n    rewriteConfigNumericalOption(state,\"repl-ping-slave-period\",server.repl_ping_slave_period,CONFIG_DEFAULT_REPL_PING_SLAVE_PERIOD);\n    rewriteConfigNumericalOption(state,\"repl-timeout\",server.repl_timeout,CONFIG_DEFAULT_REPL_TIMEOUT);\n    rewriteConfigBytesOption(state,\"repl-backlog-size\",server.repl_backlog_size,CONFIG_DEFAULT_REPL_BACKLOG_SIZE);\n    rewriteConfigBytesOption(state,\"repl-backlog-ttl\",server.repl_backlog_time_limit,CONFIG_DEFAULT_REPL_BACKLOG_TIME_LIMIT);\n    rewriteConfigYesNoOption(state,\"repl-disable-tcp-nodelay\",server.repl_disable_tcp_nodelay,CONFIG_DEFAULT_REPL_DISABLE_TCP_NODELAY);\n    rewriteConfigYesNoOption(state,\"repl-diskless-sync\",server.repl_diskless_sync,CONFIG_DEFAULT_REPL_DISKLESS_SYNC);\n    rewriteConfigNumericalOption(state,\"repl-diskless-sync-delay\",server.repl_diskless_sync_delay,CONFIG_DEFAULT_REPL_DISKLESS_SYNC_DELAY);\n    rewriteConfigNumericalOption(state,\"slave-priority\",server.slave_priority,CONFIG_DEFAULT_SLAVE_PRIORITY);\n    rewriteConfigNumericalOption(state,\"min-slaves-to-write\",server.repl_min_slaves_to_write,CONFIG_DEFAULT_MIN_SLAVES_TO_WRITE);\n    rewriteConfigNumericalOption(state,\"min-slaves-max-lag\",server.repl_min_slaves_max_lag,CONFIG_DEFAULT_MIN_SLAVES_MAX_LAG);\n    rewriteConfigStringOption(state,\"requirepass\",server.requirepass,NULL);\n    rewriteConfigNumericalOption(state,\"maxclients\",server.maxclients,CONFIG_DEFAULT_MAX_CLIENTS);\n    rewriteConfigBytesOption(state,\"maxmemory\",server.maxmemory,CONFIG_DEFAULT_MAXMEMORY);\n    rewriteConfigEnumOption(state,\"maxmemory-policy\",server.maxmemory_policy,maxmemory_policy_enum,CONFIG_DEFAULT_MAXMEMORY_POLICY);\n    rewriteConfigNumericalOption(state,\"maxmemory-samples\",server.maxmemory_samples,CONFIG_DEFAULT_MAXMEMORY_SAMPLES);\n    rewriteConfigYesNoOption(state,\"appendonly\",server.aof_state != AOF_OFF,0);\n    rewriteConfigStringOption(state,\"appendfilename\",server.aof_filename,CONFIG_DEFAULT_AOF_FILENAME);\n    rewriteConfigEnumOption(state,\"appendfsync\",server.aof_fsync,aof_fsync_enum,CONFIG_DEFAULT_AOF_FSYNC);\n    rewriteConfigYesNoOption(state,\"no-appendfsync-on-rewrite\",server.aof_no_fsync_on_rewrite,CONFIG_DEFAULT_AOF_NO_FSYNC_ON_REWRITE);\n    rewriteConfigNumericalOption(state,\"auto-aof-rewrite-percentage\",server.aof_rewrite_perc,AOF_REWRITE_PERC);\n    rewriteConfigBytesOption(state,\"auto-aof-rewrite-min-size\",server.aof_rewrite_min_size,AOF_REWRITE_MIN_SIZE);\n    rewriteConfigNumericalOption(state,\"lua-time-limit\",server.lua_time_limit,LUA_SCRIPT_TIME_LIMIT);\n    rewriteConfigYesNoOption(state,\"cluster-enabled\",server.cluster_enabled,0);\n    rewriteConfigStringOption(state,\"cluster-config-file\",server.cluster_configfile,CONFIG_DEFAULT_CLUSTER_CONFIG_FILE);\n    rewriteConfigYesNoOption(state,\"cluster-require-full-coverage\",server.cluster_require_full_coverage,CLUSTER_DEFAULT_REQUIRE_FULL_COVERAGE);\n    rewriteConfigNumericalOption(state,\"cluster-node-timeout\",server.cluster_node_timeout,CLUSTER_DEFAULT_NODE_TIMEOUT);\n    rewriteConfigNumericalOption(state,\"cluster-migration-barrier\",server.cluster_migration_barrier,CLUSTER_DEFAULT_MIGRATION_BARRIER);\n    rewriteConfigNumericalOption(state,\"cluster-slave-validity-factor\",server.cluster_slave_validity_factor,CLUSTER_DEFAULT_SLAVE_VALIDITY);\n    rewriteConfigNumericalOption(state,\"slowlog-log-slower-than\",server.slowlog_log_slower_than,CONFIG_DEFAULT_SLOWLOG_LOG_SLOWER_THAN);\n    rewriteConfigNumericalOption(state,\"latency-monitor-threshold\",server.latency_monitor_threshold,CONFIG_DEFAULT_LATENCY_MONITOR_THRESHOLD);\n    rewriteConfigNumericalOption(state,\"slowlog-max-len\",server.slowlog_max_len,CONFIG_DEFAULT_SLOWLOG_MAX_LEN);\n    rewriteConfigNotifykeyspaceeventsOption(state);\n    rewriteConfigNumericalOption(state,\"hash-max-ziplist-entries\",server.hash_max_ziplist_entries,OBJ_HASH_MAX_ZIPLIST_ENTRIES);\n    rewriteConfigNumericalOption(state,\"hash-max-ziplist-value\",server.hash_max_ziplist_value,OBJ_HASH_MAX_ZIPLIST_VALUE);\n    rewriteConfigNumericalOption(state,\"list-max-ziplist-size\",server.list_max_ziplist_size,OBJ_LIST_MAX_ZIPLIST_SIZE);\n    rewriteConfigNumericalOption(state,\"list-compress-depth\",server.list_compress_depth,OBJ_LIST_COMPRESS_DEPTH);\n    rewriteConfigNumericalOption(state,\"set-max-intset-entries\",server.set_max_intset_entries,OBJ_SET_MAX_INTSET_ENTRIES);\n    rewriteConfigNumericalOption(state,\"zset-max-ziplist-entries\",server.zset_max_ziplist_entries,OBJ_ZSET_MAX_ZIPLIST_ENTRIES);\n    rewriteConfigNumericalOption(state,\"zset-max-ziplist-value\",server.zset_max_ziplist_value,OBJ_ZSET_MAX_ZIPLIST_VALUE);\n    rewriteConfigNumericalOption(state,\"hll-sparse-max-bytes\",server.hll_sparse_max_bytes,CONFIG_DEFAULT_HLL_SPARSE_MAX_BYTES);\n    rewriteConfigYesNoOption(state,\"activerehashing\",server.activerehashing,CONFIG_DEFAULT_ACTIVE_REHASHING);\n    rewriteConfigYesNoOption(state,\"protected-mode\",server.protected_mode,CONFIG_DEFAULT_PROTECTED_MODE);\n    rewriteConfigClientoutputbufferlimitOption(state);\n    rewriteConfigNumericalOption(state,\"hz\",server.hz,CONFIG_DEFAULT_HZ);\n    rewriteConfigYesNoOption(state,\"aof-rewrite-incremental-fsync\",server.aof_rewrite_incremental_fsync,CONFIG_DEFAULT_AOF_REWRITE_INCREMENTAL_FSYNC);\n    rewriteConfigYesNoOption(state,\"aof-load-truncated\",server.aof_load_truncated,CONFIG_DEFAULT_AOF_LOAD_TRUNCATED);\n    rewriteConfigEnumOption(state,\"supervised\",server.supervised_mode,supervised_mode_enum,SUPERVISED_NONE);\n\n    /* Rewrite Sentinel config if in Sentinel mode. */\n    if (server.sentinel_mode) rewriteConfigSentinelOption(state);\n\n    /* Step 3: remove all the orphaned lines in the old file, that is, lines\n     * that were used by a config option and are no longer used, like in case\n     * of multiple \"save\" options or duplicated options. */\n    rewriteConfigRemoveOrphaned(state);\n\n    /* Step 4: generate a new configuration file from the modified state\n     * and write it into the original file. */\n    newcontent = rewriteConfigGetContentFromState(state);\n    retval = rewriteConfigOverwriteFile(server.configfile,newcontent);\n\n    sdsfree(newcontent);\n    rewriteConfigReleaseState(state);\n    return retval;\n}\n\n/*-----------------------------------------------------------------------------\n * CONFIG command entry point\n *----------------------------------------------------------------------------*/\n\nvoid configCommand(client *c) {\n    /* Only allow CONFIG GET while loading. */\n    if (server.loading && strcasecmp(c->argv[1]->ptr,\"get\")) {\n        addReplyError(c,\"Only CONFIG GET is allowed during loading\");\n        return;\n    }\n\n    if (!strcasecmp(c->argv[1]->ptr,\"set\")) {\n        if (c->argc != 4) goto badarity;\n        configSetCommand(c);\n    } else if (!strcasecmp(c->argv[1]->ptr,\"get\")) {\n        if (c->argc != 3) goto badarity;\n        configGetCommand(c);\n    } else if (!strcasecmp(c->argv[1]->ptr,\"resetstat\")) {\n        if (c->argc != 2) goto badarity;\n        resetServerStats();\n        resetCommandTableStats();\n        addReply(c,shared.ok);\n    } else if (!strcasecmp(c->argv[1]->ptr,\"rewrite\")) {\n        if (c->argc != 2) goto badarity;\n        if (server.configfile == NULL) {\n            addReplyError(c,\"The server is running without a config file\");\n            return;\n        }\n        if (rewriteConfig(server.configfile) == -1) {\n            serverLog(LL_WARNING,\"CONFIG REWRITE failed: %s\", strerror(errno));\n            addReplyErrorFormat(c,\"Rewriting config file: %s\", strerror(errno));\n        } else {\n            serverLog(LL_WARNING,\"CONFIG REWRITE executed with success.\");\n            addReply(c,shared.ok);\n        }\n    } else {\n        addReplyError(c,\n            \"CONFIG subcommand must be one of GET, SET, RESETSTAT, REWRITE\");\n    }\n    return;\n\nbadarity:\n    addReplyErrorFormat(c,\"Wrong number of arguments for CONFIG %s\",\n        (char*) c->argv[1]->ptr);\n}\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.8/src/crc16.c",
    "content": "#include \"server.h\"\n\n/*\n * Copyright 2001-2010 Georges Menie (www.menie.org)\n * Copyright 2010-2012 Salvatore Sanfilippo (adapted to Redis coding style)\n * All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions are met:\n *\n *     * Redistributions of source code must retain the above copyright\n *       notice, this list of conditions and the following disclaimer.\n *     * Redistributions in binary form must reproduce the above copyright\n *       notice, this list of conditions and the following disclaimer in the\n *       documentation and/or other materials provided with the distribution.\n *     * Neither the name of the University of California, Berkeley nor the\n *       names of its contributors may be used to endorse or promote products\n *       derived from this software without specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ANY\n * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n * DISCLAIMED. IN NO EVENT SHALL THE REGENTS AND CONTRIBUTORS BE LIABLE FOR ANY\n * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\n * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND\n * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\n * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n\n/* CRC16 implementation according to CCITT standards.\n *\n * Note by @antirez: this is actually the XMODEM CRC 16 algorithm, using the\n * following parameters:\n *\n * Name                       : \"XMODEM\", also known as \"ZMODEM\", \"CRC-16/ACORN\"\n * Width                      : 16 bit\n * Poly                       : 1021 (That is actually x^16 + x^12 + x^5 + 1)\n * Initialization             : 0000\n * Reflect Input byte         : False\n * Reflect Output CRC         : False\n * Xor constant to output CRC : 0000\n * Output for \"123456789\"     : 31C3\n */\n\nstatic const uint16_t crc16tab[256]= {\n    0x0000,0x1021,0x2042,0x3063,0x4084,0x50a5,0x60c6,0x70e7,\n    0x8108,0x9129,0xa14a,0xb16b,0xc18c,0xd1ad,0xe1ce,0xf1ef,\n    0x1231,0x0210,0x3273,0x2252,0x52b5,0x4294,0x72f7,0x62d6,\n    0x9339,0x8318,0xb37b,0xa35a,0xd3bd,0xc39c,0xf3ff,0xe3de,\n    0x2462,0x3443,0x0420,0x1401,0x64e6,0x74c7,0x44a4,0x5485,\n    0xa56a,0xb54b,0x8528,0x9509,0xe5ee,0xf5cf,0xc5ac,0xd58d,\n    0x3653,0x2672,0x1611,0x0630,0x76d7,0x66f6,0x5695,0x46b4,\n    0xb75b,0xa77a,0x9719,0x8738,0xf7df,0xe7fe,0xd79d,0xc7bc,\n    0x48c4,0x58e5,0x6886,0x78a7,0x0840,0x1861,0x2802,0x3823,\n    0xc9cc,0xd9ed,0xe98e,0xf9af,0x8948,0x9969,0xa90a,0xb92b,\n    0x5af5,0x4ad4,0x7ab7,0x6a96,0x1a71,0x0a50,0x3a33,0x2a12,\n    0xdbfd,0xcbdc,0xfbbf,0xeb9e,0x9b79,0x8b58,0xbb3b,0xab1a,\n    0x6ca6,0x7c87,0x4ce4,0x5cc5,0x2c22,0x3c03,0x0c60,0x1c41,\n    0xedae,0xfd8f,0xcdec,0xddcd,0xad2a,0xbd0b,0x8d68,0x9d49,\n    0x7e97,0x6eb6,0x5ed5,0x4ef4,0x3e13,0x2e32,0x1e51,0x0e70,\n    0xff9f,0xefbe,0xdfdd,0xcffc,0xbf1b,0xaf3a,0x9f59,0x8f78,\n    0x9188,0x81a9,0xb1ca,0xa1eb,0xd10c,0xc12d,0xf14e,0xe16f,\n    0x1080,0x00a1,0x30c2,0x20e3,0x5004,0x4025,0x7046,0x6067,\n    0x83b9,0x9398,0xa3fb,0xb3da,0xc33d,0xd31c,0xe37f,0xf35e,\n    0x02b1,0x1290,0x22f3,0x32d2,0x4235,0x5214,0x6277,0x7256,\n    0xb5ea,0xa5cb,0x95a8,0x8589,0xf56e,0xe54f,0xd52c,0xc50d,\n    0x34e2,0x24c3,0x14a0,0x0481,0x7466,0x6447,0x5424,0x4405,\n    0xa7db,0xb7fa,0x8799,0x97b8,0xe75f,0xf77e,0xc71d,0xd73c,\n    0x26d3,0x36f2,0x0691,0x16b0,0x6657,0x7676,0x4615,0x5634,\n    0xd94c,0xc96d,0xf90e,0xe92f,0x99c8,0x89e9,0xb98a,0xa9ab,\n    0x5844,0x4865,0x7806,0x6827,0x18c0,0x08e1,0x3882,0x28a3,\n    0xcb7d,0xdb5c,0xeb3f,0xfb1e,0x8bf9,0x9bd8,0xabbb,0xbb9a,\n    0x4a75,0x5a54,0x6a37,0x7a16,0x0af1,0x1ad0,0x2ab3,0x3a92,\n    0xfd2e,0xed0f,0xdd6c,0xcd4d,0xbdaa,0xad8b,0x9de8,0x8dc9,\n    0x7c26,0x6c07,0x5c64,0x4c45,0x3ca2,0x2c83,0x1ce0,0x0cc1,\n    0xef1f,0xff3e,0xcf5d,0xdf7c,0xaf9b,0xbfba,0x8fd9,0x9ff8,\n    0x6e17,0x7e36,0x4e55,0x5e74,0x2e93,0x3eb2,0x0ed1,0x1ef0\n};\n\nuint16_t crc16(const char *buf, int len) {\n    int counter;\n    uint16_t crc = 0;\n    for (counter = 0; counter < len; counter++)\n            crc = (crc<<8) ^ crc16tab[((crc>>8) ^ *buf++)&0x00FF];\n    return crc;\n}\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.8/src/crc32.c",
    "content": "#include <stdint.h>\n\nstatic const uint32_t IEEE_POLY = 0xedb88320;\n\nstatic uint32_t crc32tab[256];\n\nstatic void\ncrc32_tabinit(uint32_t poly) {\n    int i, j;\n    for (i = 0; i < 256; i ++) {\n        uint32_t crc = i;\n        for (j = 0; j < 8; j ++) {\n            if (crc & 1) {\n                crc = (crc >> 1) ^ poly;\n            } else {\n                crc = (crc >> 1);\n            }\n        }\n        crc32tab[i] = crc;\n    }\n}\n\nvoid\ncrc32_init() {\n    crc32_tabinit(IEEE_POLY);\n}\n\nstatic uint32_t\ncrc32_update(uint32_t crc, const char *buf, int len) {\n    int i;\n    crc = ~crc;\n    for (i = 0; i < len; i ++) {\n        crc = crc32tab[(uint8_t)((char)crc ^ buf[i])] ^ (crc >> 8);\n    }\n    return ~crc;\n}\n\nuint32_t\ncrc32_checksum(const char *buf, int len) {\n    return crc32_update(0, buf, len);\n}\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.8/src/crc64.c",
    "content": "/* Redis uses the CRC64 variant with \"Jones\" coefficients and init value of 0.\n *\n * Specification of this CRC64 variant follows:\n * Name: crc-64-jones\n * Width: 64 bites\n * Poly: 0xad93d23594c935a9\n * Reflected In: True\n * Xor_In: 0xffffffffffffffff\n * Reflected_Out: True\n * Xor_Out: 0x0\n * Check(\"123456789\"): 0xe9c6d914c4b8d9ca\n *\n * Copyright (c) 2012, Salvatore Sanfilippo <antirez at gmail dot com>\n * All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions are met:\n *\n *   * Redistributions of source code must retain the above copyright notice,\n *     this list of conditions and the following disclaimer.\n *   * Redistributions in binary form must reproduce the above copyright\n *     notice, this list of conditions and the following disclaimer in the\n *     documentation and/or other materials provided with the distribution.\n *   * Neither the name of Redis nor the names of its contributors may be used\n *     to endorse or promote products derived from this software without\n *     specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\"\n * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\n * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE\n * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR\n * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF\n * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS\n * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN\n * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)\n * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE\n * POSSIBILITY OF SUCH DAMAGE. */\n\n#include <stdint.h>\n\nstatic const uint64_t crc64_tab[256] = {\n    UINT64_C(0x0000000000000000), UINT64_C(0x7ad870c830358979),\n    UINT64_C(0xf5b0e190606b12f2), UINT64_C(0x8f689158505e9b8b),\n    UINT64_C(0xc038e5739841b68f), UINT64_C(0xbae095bba8743ff6),\n    UINT64_C(0x358804e3f82aa47d), UINT64_C(0x4f50742bc81f2d04),\n    UINT64_C(0xab28ecb46814fe75), UINT64_C(0xd1f09c7c5821770c),\n    UINT64_C(0x5e980d24087fec87), UINT64_C(0x24407dec384a65fe),\n    UINT64_C(0x6b1009c7f05548fa), UINT64_C(0x11c8790fc060c183),\n    UINT64_C(0x9ea0e857903e5a08), UINT64_C(0xe478989fa00bd371),\n    UINT64_C(0x7d08ff3b88be6f81), UINT64_C(0x07d08ff3b88be6f8),\n    UINT64_C(0x88b81eabe8d57d73), UINT64_C(0xf2606e63d8e0f40a),\n    UINT64_C(0xbd301a4810ffd90e), UINT64_C(0xc7e86a8020ca5077),\n    UINT64_C(0x4880fbd87094cbfc), UINT64_C(0x32588b1040a14285),\n    UINT64_C(0xd620138fe0aa91f4), UINT64_C(0xacf86347d09f188d),\n    UINT64_C(0x2390f21f80c18306), UINT64_C(0x594882d7b0f40a7f),\n    UINT64_C(0x1618f6fc78eb277b), UINT64_C(0x6cc0863448deae02),\n    UINT64_C(0xe3a8176c18803589), UINT64_C(0x997067a428b5bcf0),\n    UINT64_C(0xfa11fe77117cdf02), UINT64_C(0x80c98ebf2149567b),\n    UINT64_C(0x0fa11fe77117cdf0), UINT64_C(0x75796f2f41224489),\n    UINT64_C(0x3a291b04893d698d), UINT64_C(0x40f16bccb908e0f4),\n    UINT64_C(0xcf99fa94e9567b7f), UINT64_C(0xb5418a5cd963f206),\n    UINT64_C(0x513912c379682177), UINT64_C(0x2be1620b495da80e),\n    UINT64_C(0xa489f35319033385), UINT64_C(0xde51839b2936bafc),\n    UINT64_C(0x9101f7b0e12997f8), UINT64_C(0xebd98778d11c1e81),\n    UINT64_C(0x64b116208142850a), UINT64_C(0x1e6966e8b1770c73),\n    UINT64_C(0x8719014c99c2b083), UINT64_C(0xfdc17184a9f739fa),\n    UINT64_C(0x72a9e0dcf9a9a271), UINT64_C(0x08719014c99c2b08),\n    UINT64_C(0x4721e43f0183060c), UINT64_C(0x3df994f731b68f75),\n    UINT64_C(0xb29105af61e814fe), UINT64_C(0xc849756751dd9d87),\n    UINT64_C(0x2c31edf8f1d64ef6), UINT64_C(0x56e99d30c1e3c78f),\n    UINT64_C(0xd9810c6891bd5c04), UINT64_C(0xa3597ca0a188d57d),\n    UINT64_C(0xec09088b6997f879), UINT64_C(0x96d1784359a27100),\n    UINT64_C(0x19b9e91b09fcea8b), UINT64_C(0x636199d339c963f2),\n    UINT64_C(0xdf7adabd7a6e2d6f), UINT64_C(0xa5a2aa754a5ba416),\n    UINT64_C(0x2aca3b2d1a053f9d), UINT64_C(0x50124be52a30b6e4),\n    UINT64_C(0x1f423fcee22f9be0), UINT64_C(0x659a4f06d21a1299),\n    UINT64_C(0xeaf2de5e82448912), UINT64_C(0x902aae96b271006b),\n    UINT64_C(0x74523609127ad31a), UINT64_C(0x0e8a46c1224f5a63),\n    UINT64_C(0x81e2d7997211c1e8), UINT64_C(0xfb3aa75142244891),\n    UINT64_C(0xb46ad37a8a3b6595), UINT64_C(0xceb2a3b2ba0eecec),\n    UINT64_C(0x41da32eaea507767), UINT64_C(0x3b024222da65fe1e),\n    UINT64_C(0xa2722586f2d042ee), UINT64_C(0xd8aa554ec2e5cb97),\n    UINT64_C(0x57c2c41692bb501c), UINT64_C(0x2d1ab4dea28ed965),\n    UINT64_C(0x624ac0f56a91f461), UINT64_C(0x1892b03d5aa47d18),\n    UINT64_C(0x97fa21650afae693), UINT64_C(0xed2251ad3acf6fea),\n    UINT64_C(0x095ac9329ac4bc9b), UINT64_C(0x7382b9faaaf135e2),\n    UINT64_C(0xfcea28a2faafae69), UINT64_C(0x8632586aca9a2710),\n    UINT64_C(0xc9622c4102850a14), UINT64_C(0xb3ba5c8932b0836d),\n    UINT64_C(0x3cd2cdd162ee18e6), UINT64_C(0x460abd1952db919f),\n    UINT64_C(0x256b24ca6b12f26d), UINT64_C(0x5fb354025b277b14),\n    UINT64_C(0xd0dbc55a0b79e09f), UINT64_C(0xaa03b5923b4c69e6),\n    UINT64_C(0xe553c1b9f35344e2), UINT64_C(0x9f8bb171c366cd9b),\n    UINT64_C(0x10e3202993385610), UINT64_C(0x6a3b50e1a30ddf69),\n    UINT64_C(0x8e43c87e03060c18), UINT64_C(0xf49bb8b633338561),\n    UINT64_C(0x7bf329ee636d1eea), UINT64_C(0x012b592653589793),\n    UINT64_C(0x4e7b2d0d9b47ba97), UINT64_C(0x34a35dc5ab7233ee),\n    UINT64_C(0xbbcbcc9dfb2ca865), UINT64_C(0xc113bc55cb19211c),\n    UINT64_C(0x5863dbf1e3ac9dec), UINT64_C(0x22bbab39d3991495),\n    UINT64_C(0xadd33a6183c78f1e), UINT64_C(0xd70b4aa9b3f20667),\n    UINT64_C(0x985b3e827bed2b63), UINT64_C(0xe2834e4a4bd8a21a),\n    UINT64_C(0x6debdf121b863991), UINT64_C(0x1733afda2bb3b0e8),\n    UINT64_C(0xf34b37458bb86399), UINT64_C(0x8993478dbb8deae0),\n    UINT64_C(0x06fbd6d5ebd3716b), UINT64_C(0x7c23a61ddbe6f812),\n    UINT64_C(0x3373d23613f9d516), UINT64_C(0x49aba2fe23cc5c6f),\n    UINT64_C(0xc6c333a67392c7e4), UINT64_C(0xbc1b436e43a74e9d),\n    UINT64_C(0x95ac9329ac4bc9b5), UINT64_C(0xef74e3e19c7e40cc),\n    UINT64_C(0x601c72b9cc20db47), UINT64_C(0x1ac40271fc15523e),\n    UINT64_C(0x5594765a340a7f3a), UINT64_C(0x2f4c0692043ff643),\n    UINT64_C(0xa02497ca54616dc8), UINT64_C(0xdafce7026454e4b1),\n    UINT64_C(0x3e847f9dc45f37c0), UINT64_C(0x445c0f55f46abeb9),\n    UINT64_C(0xcb349e0da4342532), UINT64_C(0xb1eceec59401ac4b),\n    UINT64_C(0xfebc9aee5c1e814f), UINT64_C(0x8464ea266c2b0836),\n    UINT64_C(0x0b0c7b7e3c7593bd), UINT64_C(0x71d40bb60c401ac4),\n    UINT64_C(0xe8a46c1224f5a634), UINT64_C(0x927c1cda14c02f4d),\n    UINT64_C(0x1d148d82449eb4c6), UINT64_C(0x67ccfd4a74ab3dbf),\n    UINT64_C(0x289c8961bcb410bb), UINT64_C(0x5244f9a98c8199c2),\n    UINT64_C(0xdd2c68f1dcdf0249), UINT64_C(0xa7f41839ecea8b30),\n    UINT64_C(0x438c80a64ce15841), UINT64_C(0x3954f06e7cd4d138),\n    UINT64_C(0xb63c61362c8a4ab3), UINT64_C(0xcce411fe1cbfc3ca),\n    UINT64_C(0x83b465d5d4a0eece), UINT64_C(0xf96c151de49567b7),\n    UINT64_C(0x76048445b4cbfc3c), UINT64_C(0x0cdcf48d84fe7545),\n    UINT64_C(0x6fbd6d5ebd3716b7), UINT64_C(0x15651d968d029fce),\n    UINT64_C(0x9a0d8ccedd5c0445), UINT64_C(0xe0d5fc06ed698d3c),\n    UINT64_C(0xaf85882d2576a038), UINT64_C(0xd55df8e515432941),\n    UINT64_C(0x5a3569bd451db2ca), UINT64_C(0x20ed197575283bb3),\n    UINT64_C(0xc49581ead523e8c2), UINT64_C(0xbe4df122e51661bb),\n    UINT64_C(0x3125607ab548fa30), UINT64_C(0x4bfd10b2857d7349),\n    UINT64_C(0x04ad64994d625e4d), UINT64_C(0x7e7514517d57d734),\n    UINT64_C(0xf11d85092d094cbf), UINT64_C(0x8bc5f5c11d3cc5c6),\n    UINT64_C(0x12b5926535897936), UINT64_C(0x686de2ad05bcf04f),\n    UINT64_C(0xe70573f555e26bc4), UINT64_C(0x9ddd033d65d7e2bd),\n    UINT64_C(0xd28d7716adc8cfb9), UINT64_C(0xa85507de9dfd46c0),\n    UINT64_C(0x273d9686cda3dd4b), UINT64_C(0x5de5e64efd965432),\n    UINT64_C(0xb99d7ed15d9d8743), UINT64_C(0xc3450e196da80e3a),\n    UINT64_C(0x4c2d9f413df695b1), UINT64_C(0x36f5ef890dc31cc8),\n    UINT64_C(0x79a59ba2c5dc31cc), UINT64_C(0x037deb6af5e9b8b5),\n    UINT64_C(0x8c157a32a5b7233e), UINT64_C(0xf6cd0afa9582aa47),\n    UINT64_C(0x4ad64994d625e4da), UINT64_C(0x300e395ce6106da3),\n    UINT64_C(0xbf66a804b64ef628), UINT64_C(0xc5bed8cc867b7f51),\n    UINT64_C(0x8aeeace74e645255), UINT64_C(0xf036dc2f7e51db2c),\n    UINT64_C(0x7f5e4d772e0f40a7), UINT64_C(0x05863dbf1e3ac9de),\n    UINT64_C(0xe1fea520be311aaf), UINT64_C(0x9b26d5e88e0493d6),\n    UINT64_C(0x144e44b0de5a085d), UINT64_C(0x6e963478ee6f8124),\n    UINT64_C(0x21c640532670ac20), UINT64_C(0x5b1e309b16452559),\n    UINT64_C(0xd476a1c3461bbed2), UINT64_C(0xaeaed10b762e37ab),\n    UINT64_C(0x37deb6af5e9b8b5b), UINT64_C(0x4d06c6676eae0222),\n    UINT64_C(0xc26e573f3ef099a9), UINT64_C(0xb8b627f70ec510d0),\n    UINT64_C(0xf7e653dcc6da3dd4), UINT64_C(0x8d3e2314f6efb4ad),\n    UINT64_C(0x0256b24ca6b12f26), UINT64_C(0x788ec2849684a65f),\n    UINT64_C(0x9cf65a1b368f752e), UINT64_C(0xe62e2ad306bafc57),\n    UINT64_C(0x6946bb8b56e467dc), UINT64_C(0x139ecb4366d1eea5),\n    UINT64_C(0x5ccebf68aecec3a1), UINT64_C(0x2616cfa09efb4ad8),\n    UINT64_C(0xa97e5ef8cea5d153), UINT64_C(0xd3a62e30fe90582a),\n    UINT64_C(0xb0c7b7e3c7593bd8), UINT64_C(0xca1fc72bf76cb2a1),\n    UINT64_C(0x45775673a732292a), UINT64_C(0x3faf26bb9707a053),\n    UINT64_C(0x70ff52905f188d57), UINT64_C(0x0a2722586f2d042e),\n    UINT64_C(0x854fb3003f739fa5), UINT64_C(0xff97c3c80f4616dc),\n    UINT64_C(0x1bef5b57af4dc5ad), UINT64_C(0x61372b9f9f784cd4),\n    UINT64_C(0xee5fbac7cf26d75f), UINT64_C(0x9487ca0fff135e26),\n    UINT64_C(0xdbd7be24370c7322), UINT64_C(0xa10fceec0739fa5b),\n    UINT64_C(0x2e675fb4576761d0), UINT64_C(0x54bf2f7c6752e8a9),\n    UINT64_C(0xcdcf48d84fe75459), UINT64_C(0xb71738107fd2dd20),\n    UINT64_C(0x387fa9482f8c46ab), UINT64_C(0x42a7d9801fb9cfd2),\n    UINT64_C(0x0df7adabd7a6e2d6), UINT64_C(0x772fdd63e7936baf),\n    UINT64_C(0xf8474c3bb7cdf024), UINT64_C(0x829f3cf387f8795d),\n    UINT64_C(0x66e7a46c27f3aa2c), UINT64_C(0x1c3fd4a417c62355),\n    UINT64_C(0x935745fc4798b8de), UINT64_C(0xe98f353477ad31a7),\n    UINT64_C(0xa6df411fbfb21ca3), UINT64_C(0xdc0731d78f8795da),\n    UINT64_C(0x536fa08fdfd90e51), UINT64_C(0x29b7d047efec8728),\n};\n\nuint64_t crc64(uint64_t crc, const unsigned char *s, uint64_t l) {\n    uint64_t j;\n\n    for (j = 0; j < l; j++) {\n        uint8_t byte = s[j];\n        crc = crc64_tab[(uint8_t)crc ^ byte] ^ (crc >> 8);\n    }\n    return crc;\n}\n\n/* Test main */\n#ifdef REDIS_TEST\n#include <stdio.h>\n\n#define UNUSED(x) (void)(x)\nint crc64Test(int argc, char *argv[]) {\n    UNUSED(argc);\n    UNUSED(argv);\n    printf(\"e9c6d914c4b8d9ca == %016llx\\n\",\n        (unsigned long long) crc64(0,(unsigned char*)\"123456789\",9));\n    return 0;\n}\n#endif\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.8/src/crc64.h",
    "content": "#ifndef CRC64_H\n#define CRC64_H\n\n#include <stdint.h>\n\nuint64_t crc64(uint64_t crc, const unsigned char *s, uint64_t l);\n\n#ifdef REDIS_TEST\nint crc64Test(int argc, char *argv[]);\n#endif\n\n#endif\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.8/src/db.c",
    "content": "/*\n * Copyright (c) 2009-2012, Salvatore Sanfilippo <antirez at gmail dot com>\n * All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions are met:\n *\n *   * Redistributions of source code must retain the above copyright notice,\n *     this list of conditions and the following disclaimer.\n *   * Redistributions in binary form must reproduce the above copyright\n *     notice, this list of conditions and the following disclaimer in the\n *     documentation and/or other materials provided with the distribution.\n *   * Neither the name of Redis nor the names of its contributors may be used\n *     to endorse or promote products derived from this software without\n *     specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\"\n * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\n * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE\n * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR\n * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF\n * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS\n * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN\n * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)\n * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE\n * POSSIBILITY OF SUCH DAMAGE.\n */\n\n#include \"server.h\"\n#include \"cluster.h\"\n\n#include <signal.h>\n#include <ctype.h>\n\nvoid slotToKeyAdd(robj *key);\nvoid slotToKeyDel(robj *key);\nvoid slotToKeyFlush(void);\n\n/*-----------------------------------------------------------------------------\n * C-level DB API\n *----------------------------------------------------------------------------*/\n\n/* Low level key lookup API, not actually called directly from commands\n * implementations that should instead rely on lookupKeyRead(),\n * lookupKeyWrite() and lookupKeyReadWithFlags(). */\nrobj *lookupKey(redisDb *db, robj *key, int flags) {\n    dictEntry *de = dictFind(db->dict,key->ptr);\n    if (de) {\n        robj *val = dictGetVal(de);\n\n        /* Update the access time for the ageing algorithm.\n         * Don't do it if we have a saving child, as this will trigger\n         * a copy on write madness. */\n        if (server.rdb_child_pid == -1 &&\n            server.aof_child_pid == -1 &&\n            !(flags & LOOKUP_NOTOUCH))\n        {\n            val->lru = LRU_CLOCK();\n        }\n        return val;\n    } else {\n        return NULL;\n    }\n}\n\n/* Lookup a key for read operations, or return NULL if the key is not found\n * in the specified DB.\n *\n * As a side effect of calling this function:\n * 1. A key gets expired if it reached it's TTL.\n * 2. The key last access time is updated.\n * 3. The global keys hits/misses stats are updated (reported in INFO).\n *\n * This API should not be used when we write to the key after obtaining\n * the object linked to the key, but only for read only operations.\n *\n * Flags change the behavior of this command:\n *\n *  LOOKUP_NONE (or zero): no special flags are passed.\n *  LOOKUP_NOTOUCH: don't alter the last access time of the key.\n *\n * Note: this function also returns NULL is the key is logically expired\n * but still existing, in case this is a slave, since this API is called only\n * for read operations. Even if the key expiry is master-driven, we can\n * correctly report a key is expired on slaves even if the master is lagging\n * expiring our key via DELs in the replication link. */\nrobj *lookupKeyReadWithFlags(redisDb *db, robj *key, int flags) {\n    robj *val;\n\n    if (expireIfNeeded(db,key) == 1) {\n        /* Key expired. If we are in the context of a master, expireIfNeeded()\n         * returns 0 only when the key does not exist at all, so it's save\n         * to return NULL ASAP. */\n        if (server.masterhost == NULL) return NULL;\n\n        /* However if we are in the context of a slave, expireIfNeeded() will\n         * not really try to expire the key, it only returns information\n         * about the \"logical\" status of the key: key expiring is up to the\n         * master in order to have a consistent view of master's data set.\n         *\n         * However, if the command caller is not the master, and as additional\n         * safety measure, the command invoked is a read-only command, we can\n         * safely return NULL here, and provide a more consistent behavior\n         * to clients accessign expired values in a read-only fashion, that\n         * will say the key as non exisitng.\n         *\n         * Notably this covers GETs when slaves are used to scale reads. */\n        if (server.current_client &&\n            server.current_client != server.master &&\n            server.current_client->cmd &&\n            server.current_client->cmd->flags & CMD_READONLY)\n        {\n            return NULL;\n        }\n    }\n    val = lookupKey(db,key,flags);\n    if (val == NULL)\n        server.stat_keyspace_misses++;\n    else\n        server.stat_keyspace_hits++;\n    return val;\n}\n\n/* Like lookupKeyReadWithFlags(), but does not use any flag, which is the\n * common case. */\nrobj *lookupKeyRead(redisDb *db, robj *key) {\n    return lookupKeyReadWithFlags(db,key,LOOKUP_NONE);\n}\n\n/* Lookup a key for write operations, and as a side effect, if needed, expires\n * the key if its TTL is reached.\n *\n * Returns the linked value object if the key exists or NULL if the key\n * does not exist in the specified DB. */\nrobj *lookupKeyWrite(redisDb *db, robj *key) {\n    expireIfNeeded(db,key);\n    return lookupKey(db,key,LOOKUP_NONE);\n}\n\nrobj *lookupKeyReadOrReply(client *c, robj *key, robj *reply) {\n    robj *o = lookupKeyRead(c->db, key);\n    if (!o) addReply(c,reply);\n    return o;\n}\n\nrobj *lookupKeyWriteOrReply(client *c, robj *key, robj *reply) {\n    robj *o = lookupKeyWrite(c->db, key);\n    if (!o) addReply(c,reply);\n    return o;\n}\n\n/* Add the key to the DB. It's up to the caller to increment the reference\n * counter of the value if needed.\n *\n * The program is aborted if the key already exists. */\nvoid dbAdd(redisDb *db, robj *key, robj *val) {\n    sds copy = sdsdup(key->ptr);\n    int retval = dictAdd(db->dict, copy, val);\n\n    do {\n        uint32_t crc;\n        int hastag;\n        int slot = slots_num(key->ptr, &crc, &hastag);\n        dictAdd(db->hash_slots[slot], copy, (void *)(long)crc);\n        if (hastag) {\n            incrRefCount(key);\n            zslInsert(db->tagged_keys, (double)crc, key);\n        }\n    } while (0);\n\n    serverAssertWithInfo(NULL,key,retval == DICT_OK);\n    if (val->type == OBJ_LIST) signalListAsReady(db, key);\n    if (server.cluster_enabled) slotToKeyAdd(key);\n }\n\n/* Overwrite an existing key with a new value. Incrementing the reference\n * count of the new value is up to the caller.\n * This function does not modify the expire time of the existing key.\n *\n * The program is aborted if the key was not already present. */\nvoid dbOverwrite(redisDb *db, robj *key, robj *val) {\n    dictEntry *de = dictFind(db->dict,key->ptr);\n\n    serverAssertWithInfo(NULL,key,de != NULL);\n    dictReplace(db->dict, key->ptr, val);\n}\n\n/* High level Set operation. This function can be used in order to set\n * a key, whatever it was existing or not, to a new object.\n *\n * 1) The ref count of the value object is incremented.\n * 2) clients WATCHing for the destination key notified.\n * 3) The expire time of the key is reset (the key is made persistent). */\nvoid setKey(redisDb *db, robj *key, robj *val) {\n    if (lookupKeyWrite(db,key) == NULL) {\n        dbAdd(db,key,val);\n    } else {\n        dbOverwrite(db,key,val);\n    }\n    incrRefCount(val);\n    removeExpire(db,key);\n    signalModifiedKey(db,key);\n}\n\nint dbExists(redisDb *db, robj *key) {\n    return dictFind(db->dict,key->ptr) != NULL;\n}\n\n/* Return a random key, in form of a Redis object.\n * If there are no keys, NULL is returned.\n *\n * The function makes sure to return keys not already expired. */\nrobj *dbRandomKey(redisDb *db) {\n    dictEntry *de;\n\n    while(1) {\n        sds key;\n        robj *keyobj;\n\n        de = dictGetRandomKey(db->dict);\n        if (de == NULL) return NULL;\n\n        key = dictGetKey(de);\n        keyobj = createStringObject(key,sdslen(key));\n        if (dictFind(db->expires,key)) {\n            if (expireIfNeeded(db,keyobj)) {\n                decrRefCount(keyobj);\n                continue; /* search for another key. This expired. */\n            }\n        }\n        return keyobj;\n    }\n}\n\n/* Delete a key, value, and associated expiration entry if any, from the DB */\nint dbDelete(redisDb *db, robj *key) {\n    /* Deleting an entry from the expires dict will not free the sds of\n     * the key, because it is shared with the main dictionary. */\n    if (dictSize(db->expires) > 0) dictDelete(db->expires,key->ptr);\n\n    do {\n        uint32_t crc;\n        int hastag;\n        int slot = slots_num(key->ptr, &crc, &hastag);\n        if (dictDelete(db->hash_slots[slot], key->ptr) == DICT_OK) {\n            if (hastag) {\n                zslDelete(db->tagged_keys, (double)crc, key);\n            }\n        }\n    } while (0);\n\n    if (dictDelete(db->dict,key->ptr) == DICT_OK) {\n        if (server.cluster_enabled) slotToKeyDel(key);\n        return 1;\n    } else {\n        return 0;\n    }\n}\n\n/* Prepare the string object stored at 'key' to be modified destructively\n * to implement commands like SETBIT or APPEND.\n *\n * An object is usually ready to be modified unless one of the two conditions\n * are true:\n *\n * 1) The object 'o' is shared (refcount > 1), we don't want to affect\n *    other users.\n * 2) The object encoding is not \"RAW\".\n *\n * If the object is found in one of the above conditions (or both) by the\n * function, an unshared / not-encoded copy of the string object is stored\n * at 'key' in the specified 'db'. Otherwise the object 'o' itself is\n * returned.\n *\n * USAGE:\n *\n * The object 'o' is what the caller already obtained by looking up 'key'\n * in 'db', the usage pattern looks like this:\n *\n * o = lookupKeyWrite(db,key);\n * if (checkType(c,o,OBJ_STRING)) return;\n * o = dbUnshareStringValue(db,key,o);\n *\n * At this point the caller is ready to modify the object, for example\n * using an sdscat() call to append some data, or anything else.\n */\nrobj *dbUnshareStringValue(redisDb *db, robj *key, robj *o) {\n    serverAssert(o->type == OBJ_STRING);\n    if (o->refcount != 1 || o->encoding != OBJ_ENCODING_RAW) {\n        robj *decoded = getDecodedObject(o);\n        o = createRawStringObject(decoded->ptr, sdslen(decoded->ptr));\n        decrRefCount(decoded);\n        dbOverwrite(db,key,o);\n    }\n    return o;\n}\n\nlong long emptyDb(void(callback)(void*)) {\n    int i, j;\n    long long removed = 0;\n\n    for (j = 0; j < server.dbnum; j++) {\n        removed += dictSize(server.db[j].dict);\n        for (i = 0; i < HASH_SLOTS_SIZE; i ++) {\n            dictEmpty(server.db[j].hash_slots[i], NULL);\n        }\n        if (server.db[j].tagged_keys->length != 0) {\n            zslFree(server.db[j].tagged_keys);\n            server.db[j].tagged_keys = zslCreate();\n        }\n        dictEmpty(server.db[j].dict,callback);\n        dictEmpty(server.db[j].expires,callback);\n    }\n    if (server.cluster_enabled) slotToKeyFlush();\n    return removed;\n}\n\nint selectDb(client *c, int id) {\n    if (id < 0 || id >= server.dbnum)\n        return C_ERR;\n    c->db = &server.db[id];\n    return C_OK;\n}\n\n/*-----------------------------------------------------------------------------\n * Hooks for key space changes.\n *\n * Every time a key in the database is modified the function\n * signalModifiedKey() is called.\n *\n * Every time a DB is flushed the function signalFlushDb() is called.\n *----------------------------------------------------------------------------*/\n\nvoid signalModifiedKey(redisDb *db, robj *key) {\n    touchWatchedKey(db,key);\n}\n\nvoid signalFlushedDb(int dbid) {\n    touchWatchedKeysOnFlush(dbid);\n}\n\n/*-----------------------------------------------------------------------------\n * Type agnostic commands operating on the key space\n *----------------------------------------------------------------------------*/\n\nvoid flushdbCommand(client *c) {\n    int i;\n    server.dirty += dictSize(c->db->dict);\n    signalFlushedDb(c->db->id);\n    for (i = 0; i < HASH_SLOTS_SIZE; i ++) {\n        dictEmpty(c->db->hash_slots[i], NULL);\n    }\n    if (c->db->tagged_keys->length != 0) {\n        zslFree(c->db->tagged_keys);\n        c->db->tagged_keys = zslCreate();\n    }\n    dictEmpty(c->db->dict,NULL);\n    dictEmpty(c->db->expires,NULL);\n    if (server.cluster_enabled) slotToKeyFlush();\n    addReply(c,shared.ok);\n}\n\nvoid flushallCommand(client *c) {\n    signalFlushedDb(-1);\n    server.dirty += emptyDb(NULL);\n    addReply(c,shared.ok);\n    if (server.rdb_child_pid != -1) {\n        kill(server.rdb_child_pid,SIGUSR1);\n        rdbRemoveTempFile(server.rdb_child_pid);\n    }\n    if (server.saveparamslen > 0) {\n        /* Normally rdbSave() will reset dirty, but we don't want this here\n         * as otherwise FLUSHALL will not be replicated nor put into the AOF. */\n        int saved_dirty = server.dirty;\n        rdbSave(server.rdb_filename);\n        server.dirty = saved_dirty;\n    }\n    server.dirty++;\n}\n\nvoid delCommand(client *c) {\n    int deleted = 0, j;\n\n    for (j = 1; j < c->argc; j++) {\n        expireIfNeeded(c->db,c->argv[j]);\n        if (dbDelete(c->db,c->argv[j])) {\n            signalModifiedKey(c->db,c->argv[j]);\n            notifyKeyspaceEvent(NOTIFY_GENERIC,\n                \"del\",c->argv[j],c->db->id);\n            server.dirty++;\n            deleted++;\n        }\n    }\n    addReplyLongLong(c,deleted);\n}\n\n/* EXISTS key1 key2 ... key_N.\n * Return value is the number of keys existing. */\nvoid existsCommand(client *c) {\n    long long count = 0;\n    int j;\n\n    for (j = 1; j < c->argc; j++) {\n        expireIfNeeded(c->db,c->argv[j]);\n        if (dbExists(c->db,c->argv[j])) count++;\n    }\n    addReplyLongLong(c,count);\n}\n\nvoid selectCommand(client *c) {\n    long id;\n\n    if (getLongFromObjectOrReply(c, c->argv[1], &id,\n        \"invalid DB index\") != C_OK)\n        return;\n\n    if (server.cluster_enabled && id != 0) {\n        addReplyError(c,\"SELECT is not allowed in cluster mode\");\n        return;\n    }\n    if (selectDb(c,id) == C_ERR) {\n        addReplyError(c,\"invalid DB index\");\n    } else {\n        addReply(c,shared.ok);\n    }\n}\n\nvoid randomkeyCommand(client *c) {\n    robj *key;\n\n    if ((key = dbRandomKey(c->db)) == NULL) {\n        addReply(c,shared.nullbulk);\n        return;\n    }\n\n    addReplyBulk(c,key);\n    decrRefCount(key);\n}\n\nvoid keysCommand(client *c) {\n    dictIterator *di;\n    dictEntry *de;\n    sds pattern = c->argv[1]->ptr;\n    int plen = sdslen(pattern), allkeys;\n    unsigned long numkeys = 0;\n    void *replylen = addDeferredMultiBulkLength(c);\n\n    di = dictGetSafeIterator(c->db->dict);\n    allkeys = (pattern[0] == '*' && pattern[1] == '\\0');\n    while((de = dictNext(di)) != NULL) {\n        sds key = dictGetKey(de);\n        robj *keyobj;\n\n        if (allkeys || stringmatchlen(pattern,plen,key,sdslen(key),0)) {\n            keyobj = createStringObject(key,sdslen(key));\n            if (expireIfNeeded(c->db,keyobj) == 0) {\n                addReplyBulk(c,keyobj);\n                numkeys++;\n            }\n            decrRefCount(keyobj);\n        }\n    }\n    dictReleaseIterator(di);\n    setDeferredMultiBulkLength(c,replylen,numkeys);\n}\n\n/* This callback is used by scanGenericCommand in order to collect elements\n * returned by the dictionary iterator into a list. */\nvoid scanCallback(void *privdata, const dictEntry *de) {\n    void **pd = (void**) privdata;\n    list *keys = pd[0];\n    robj *o = pd[1];\n    robj *key, *val = NULL;\n\n    if (o == NULL) {\n        sds sdskey = dictGetKey(de);\n        key = createStringObject(sdskey, sdslen(sdskey));\n    } else if (o->type == OBJ_SET) {\n        key = dictGetKey(de);\n        incrRefCount(key);\n    } else if (o->type == OBJ_HASH) {\n        key = dictGetKey(de);\n        incrRefCount(key);\n        val = dictGetVal(de);\n        incrRefCount(val);\n    } else if (o->type == OBJ_ZSET) {\n        key = dictGetKey(de);\n        incrRefCount(key);\n        val = createStringObjectFromLongDouble(*(double*)dictGetVal(de),0);\n    } else {\n        serverPanic(\"Type not handled in SCAN callback.\");\n    }\n\n    listAddNodeTail(keys, key);\n    if (val) listAddNodeTail(keys, val);\n}\n\n/* Try to parse a SCAN cursor stored at object 'o':\n * if the cursor is valid, store it as unsigned integer into *cursor and\n * returns C_OK. Otherwise return C_ERR and send an error to the\n * client. */\nint parseScanCursorOrReply(client *c, robj *o, unsigned long *cursor) {\n    char *eptr;\n\n    /* Use strtoul() because we need an *unsigned* long, so\n     * getLongLongFromObject() does not cover the whole cursor space. */\n    errno = 0;\n    *cursor = strtoul(o->ptr, &eptr, 10);\n    if (isspace(((char*)o->ptr)[0]) || eptr[0] != '\\0' || errno == ERANGE)\n    {\n        addReplyError(c, \"invalid cursor\");\n        return C_ERR;\n    }\n    return C_OK;\n}\n\n/* This command implements SCAN, HSCAN and SSCAN commands.\n * If object 'o' is passed, then it must be a Hash or Set object, otherwise\n * if 'o' is NULL the command will operate on the dictionary associated with\n * the current database.\n *\n * When 'o' is not NULL the function assumes that the first argument in\n * the client arguments vector is a key so it skips it before iterating\n * in order to parse options.\n *\n * In the case of a Hash object the function returns both the field and value\n * of every element on the Hash. */\nvoid scanGenericCommand(client *c, robj *o, unsigned long cursor) {\n    int i, j;\n    list *keys = listCreate();\n    listNode *node, *nextnode;\n    long count = 10;\n    sds pat = NULL;\n    int patlen = 0, use_pattern = 0;\n    dict *ht;\n\n    /* Object must be NULL (to iterate keys names), or the type of the object\n     * must be Set, Sorted Set, or Hash. */\n    serverAssert(o == NULL || o->type == OBJ_SET || o->type == OBJ_HASH ||\n                o->type == OBJ_ZSET);\n\n    /* Set i to the first option argument. The previous one is the cursor. */\n    i = (o == NULL) ? 2 : 3; /* Skip the key argument if needed. */\n\n    /* Step 1: Parse options. */\n    while (i < c->argc) {\n        j = c->argc - i;\n        if (!strcasecmp(c->argv[i]->ptr, \"count\") && j >= 2) {\n            if (getLongFromObjectOrReply(c, c->argv[i+1], &count, NULL)\n                != C_OK)\n            {\n                goto cleanup;\n            }\n\n            if (count < 1) {\n                addReply(c,shared.syntaxerr);\n                goto cleanup;\n            }\n\n            i += 2;\n        } else if (!strcasecmp(c->argv[i]->ptr, \"match\") && j >= 2) {\n            pat = c->argv[i+1]->ptr;\n            patlen = sdslen(pat);\n\n            /* The pattern always matches if it is exactly \"*\", so it is\n             * equivalent to disabling it. */\n            use_pattern = !(pat[0] == '*' && patlen == 1);\n\n            i += 2;\n        } else {\n            addReply(c,shared.syntaxerr);\n            goto cleanup;\n        }\n    }\n\n    /* Step 2: Iterate the collection.\n     *\n     * Note that if the object is encoded with a ziplist, intset, or any other\n     * representation that is not a hash table, we are sure that it is also\n     * composed of a small number of elements. So to avoid taking state we\n     * just return everything inside the object in a single call, setting the\n     * cursor to zero to signal the end of the iteration. */\n\n    /* Handle the case of a hash table. */\n    ht = NULL;\n    if (o == NULL) {\n        ht = c->db->dict;\n    } else if (o->type == OBJ_SET && o->encoding == OBJ_ENCODING_HT) {\n        ht = o->ptr;\n    } else if (o->type == OBJ_HASH && o->encoding == OBJ_ENCODING_HT) {\n        ht = o->ptr;\n        count *= 2; /* We return key / value for this type. */\n    } else if (o->type == OBJ_ZSET && o->encoding == OBJ_ENCODING_SKIPLIST) {\n        zset *zs = o->ptr;\n        ht = zs->dict;\n        count *= 2; /* We return key / value for this type. */\n    }\n\n    if (ht) {\n        void *privdata[2];\n        /* We set the max number of iterations to ten times the specified\n         * COUNT, so if the hash table is in a pathological state (very\n         * sparsely populated) we avoid to block too much time at the cost\n         * of returning no or very few elements. */\n        long maxiterations = count*10;\n\n        /* We pass two pointers to the callback: the list to which it will\n         * add new elements, and the object containing the dictionary so that\n         * it is possible to fetch more data in a type-dependent way. */\n        privdata[0] = keys;\n        privdata[1] = o;\n        do {\n            cursor = dictScan(ht, cursor, scanCallback, privdata);\n        } while (cursor &&\n              maxiterations-- &&\n              listLength(keys) < (unsigned long)count);\n    } else if (o->type == OBJ_SET) {\n        int pos = 0;\n        int64_t ll;\n\n        while(intsetGet(o->ptr,pos++,&ll))\n            listAddNodeTail(keys,createStringObjectFromLongLong(ll));\n        cursor = 0;\n    } else if (o->type == OBJ_HASH || o->type == OBJ_ZSET) {\n        unsigned char *p = ziplistIndex(o->ptr,0);\n        unsigned char *vstr;\n        unsigned int vlen;\n        long long vll;\n\n        while(p) {\n            ziplistGet(p,&vstr,&vlen,&vll);\n            listAddNodeTail(keys,\n                (vstr != NULL) ? createStringObject((char*)vstr,vlen) :\n                                 createStringObjectFromLongLong(vll));\n            p = ziplistNext(o->ptr,p);\n        }\n        cursor = 0;\n    } else {\n        serverPanic(\"Not handled encoding in SCAN.\");\n    }\n\n    /* Step 3: Filter elements. */\n    node = listFirst(keys);\n    while (node) {\n        robj *kobj = listNodeValue(node);\n        nextnode = listNextNode(node);\n        int filter = 0;\n\n        /* Filter element if it does not match the pattern. */\n        if (!filter && use_pattern) {\n            if (sdsEncodedObject(kobj)) {\n                if (!stringmatchlen(pat, patlen, kobj->ptr, sdslen(kobj->ptr), 0))\n                    filter = 1;\n            } else {\n                char buf[LONG_STR_SIZE];\n                int len;\n\n                serverAssert(kobj->encoding == OBJ_ENCODING_INT);\n                len = ll2string(buf,sizeof(buf),(long)kobj->ptr);\n                if (!stringmatchlen(pat, patlen, buf, len, 0)) filter = 1;\n            }\n        }\n\n        /* Filter element if it is an expired key. */\n        if (!filter && o == NULL && expireIfNeeded(c->db, kobj)) filter = 1;\n\n        /* Remove the element and its associted value if needed. */\n        if (filter) {\n            decrRefCount(kobj);\n            listDelNode(keys, node);\n        }\n\n        /* If this is a hash or a sorted set, we have a flat list of\n         * key-value elements, so if this element was filtered, remove the\n         * value, or skip it if it was not filtered: we only match keys. */\n        if (o && (o->type == OBJ_ZSET || o->type == OBJ_HASH)) {\n            node = nextnode;\n            nextnode = listNextNode(node);\n            if (filter) {\n                kobj = listNodeValue(node);\n                decrRefCount(kobj);\n                listDelNode(keys, node);\n            }\n        }\n        node = nextnode;\n    }\n\n    /* Step 4: Reply to the client. */\n    addReplyMultiBulkLen(c, 2);\n    addReplyBulkLongLong(c,cursor);\n\n    addReplyMultiBulkLen(c, listLength(keys));\n    while ((node = listFirst(keys)) != NULL) {\n        robj *kobj = listNodeValue(node);\n        addReplyBulk(c, kobj);\n        decrRefCount(kobj);\n        listDelNode(keys, node);\n    }\n\ncleanup:\n    listSetFreeMethod(keys,decrRefCountVoid);\n    listRelease(keys);\n}\n\n/* The SCAN command completely relies on scanGenericCommand. */\nvoid scanCommand(client *c) {\n    unsigned long cursor;\n    if (parseScanCursorOrReply(c,c->argv[1],&cursor) == C_ERR) return;\n    scanGenericCommand(c,NULL,cursor);\n}\n\nvoid dbsizeCommand(client *c) {\n    addReplyLongLong(c,dictSize(c->db->dict));\n}\n\nvoid lastsaveCommand(client *c) {\n    addReplyLongLong(c,server.lastsave);\n}\n\nvoid typeCommand(client *c) {\n    robj *o;\n    char *type;\n\n    o = lookupKeyReadWithFlags(c->db,c->argv[1],LOOKUP_NOTOUCH);\n    if (o == NULL) {\n        type = \"none\";\n    } else {\n        switch(o->type) {\n        case OBJ_STRING: type = \"string\"; break;\n        case OBJ_LIST: type = \"list\"; break;\n        case OBJ_SET: type = \"set\"; break;\n        case OBJ_ZSET: type = \"zset\"; break;\n        case OBJ_HASH: type = \"hash\"; break;\n        default: type = \"unknown\"; break;\n        }\n    }\n    addReplyStatus(c,type);\n}\n\nvoid shutdownCommand(client *c) {\n    int flags = 0;\n\n    if (c->argc > 2) {\n        addReply(c,shared.syntaxerr);\n        return;\n    } else if (c->argc == 2) {\n        if (!strcasecmp(c->argv[1]->ptr,\"nosave\")) {\n            flags |= SHUTDOWN_NOSAVE;\n        } else if (!strcasecmp(c->argv[1]->ptr,\"save\")) {\n            flags |= SHUTDOWN_SAVE;\n        } else {\n            addReply(c,shared.syntaxerr);\n            return;\n        }\n    }\n    /* When SHUTDOWN is called while the server is loading a dataset in\n     * memory we need to make sure no attempt is performed to save\n     * the dataset on shutdown (otherwise it could overwrite the current DB\n     * with half-read data).\n     *\n     * Also when in Sentinel mode clear the SAVE flag and force NOSAVE. */\n    if (server.loading || server.sentinel_mode)\n        flags = (flags & ~SHUTDOWN_SAVE) | SHUTDOWN_NOSAVE;\n    if (prepareForShutdown(flags) == C_OK) {\n        for (int j = 0; j < server.dbnum; j ++) {\n            for (int i = 0; i < HASH_SLOTS_SIZE; i ++) {\n                dictRelease(server.db[j].hash_slots[i]);\n            }\n            zslFree(server.db[j].tagged_keys);\n        }\n        exit(0);\n    }\n    addReplyError(c,\"Errors trying to SHUTDOWN. Check logs.\");\n}\n\nvoid renameGenericCommand(client *c, int nx) {\n    robj *o;\n    long long expire;\n    int samekey = 0;\n\n    /* When source and dest key is the same, no operation is performed,\n     * if the key exists, however we still return an error on unexisting key. */\n    if (sdscmp(c->argv[1]->ptr,c->argv[2]->ptr) == 0) samekey = 1;\n\n    if ((o = lookupKeyWriteOrReply(c,c->argv[1],shared.nokeyerr)) == NULL)\n        return;\n\n    if (samekey) {\n        addReply(c,nx ? shared.czero : shared.ok);\n        return;\n    }\n\n    incrRefCount(o);\n    expire = getExpire(c->db,c->argv[1]);\n    if (lookupKeyWrite(c->db,c->argv[2]) != NULL) {\n        if (nx) {\n            decrRefCount(o);\n            addReply(c,shared.czero);\n            return;\n        }\n        /* Overwrite: delete the old key before creating the new one\n         * with the same name. */\n        dbDelete(c->db,c->argv[2]);\n    }\n    dbAdd(c->db,c->argv[2],o);\n    if (expire != -1) setExpire(c->db,c->argv[2],expire);\n    dbDelete(c->db,c->argv[1]);\n    signalModifiedKey(c->db,c->argv[1]);\n    signalModifiedKey(c->db,c->argv[2]);\n    notifyKeyspaceEvent(NOTIFY_GENERIC,\"rename_from\",\n        c->argv[1],c->db->id);\n    notifyKeyspaceEvent(NOTIFY_GENERIC,\"rename_to\",\n        c->argv[2],c->db->id);\n    server.dirty++;\n    addReply(c,nx ? shared.cone : shared.ok);\n}\n\nvoid renameCommand(client *c) {\n    renameGenericCommand(c,0);\n}\n\nvoid renamenxCommand(client *c) {\n    renameGenericCommand(c,1);\n}\n\nvoid moveCommand(client *c) {\n    robj *o;\n    redisDb *src, *dst;\n    int srcid;\n    long long dbid, expire;\n\n    if (server.cluster_enabled) {\n        addReplyError(c,\"MOVE is not allowed in cluster mode\");\n        return;\n    }\n\n    /* Obtain source and target DB pointers */\n    src = c->db;\n    srcid = c->db->id;\n\n    if (getLongLongFromObject(c->argv[2],&dbid) == C_ERR ||\n        dbid < INT_MIN || dbid > INT_MAX ||\n        selectDb(c,dbid) == C_ERR)\n    {\n        addReply(c,shared.outofrangeerr);\n        return;\n    }\n    dst = c->db;\n    selectDb(c,srcid); /* Back to the source DB */\n\n    /* If the user is moving using as target the same\n     * DB as the source DB it is probably an error. */\n    if (src == dst) {\n        addReply(c,shared.sameobjecterr);\n        return;\n    }\n\n    /* Check if the element exists and get a reference */\n    o = lookupKeyWrite(c->db,c->argv[1]);\n    if (!o) {\n        addReply(c,shared.czero);\n        return;\n    }\n    expire = getExpire(c->db,c->argv[1]);\n\n    /* Return zero if the key already exists in the target DB */\n    if (lookupKeyWrite(dst,c->argv[1]) != NULL) {\n        addReply(c,shared.czero);\n        return;\n    }\n    dbAdd(dst,c->argv[1],o);\n    if (expire != -1) setExpire(dst,c->argv[1],expire);\n    incrRefCount(o);\n\n    /* OK! key moved, free the entry in the source DB */\n    dbDelete(src,c->argv[1]);\n    server.dirty++;\n    addReply(c,shared.cone);\n}\n\n/*-----------------------------------------------------------------------------\n * Expires API\n *----------------------------------------------------------------------------*/\n\nint removeExpire(redisDb *db, robj *key) {\n    /* An expire may only be removed if there is a corresponding entry in the\n     * main dict. Otherwise, the key will never be freed. */\n    serverAssertWithInfo(NULL,key,dictFind(db->dict,key->ptr) != NULL);\n    return dictDelete(db->expires,key->ptr) == DICT_OK;\n}\n\nvoid setExpire(redisDb *db, robj *key, long long when) {\n    dictEntry *kde, *de;\n\n    /* Reuse the sds from the main dict in the expire dict */\n    kde = dictFind(db->dict,key->ptr);\n    serverAssertWithInfo(NULL,key,kde != NULL);\n    de = dictReplaceRaw(db->expires,dictGetKey(kde));\n    dictSetSignedIntegerVal(de,when);\n}\n\n/* Return the expire time of the specified key, or -1 if no expire\n * is associated with this key (i.e. the key is non volatile) */\nlong long getExpire(redisDb *db, robj *key) {\n    dictEntry *de;\n\n    /* No expire? return ASAP */\n    if (dictSize(db->expires) == 0 ||\n       (de = dictFind(db->expires,key->ptr)) == NULL) return -1;\n\n    /* The entry was found in the expire dict, this means it should also\n     * be present in the main dict (safety check). */\n    serverAssertWithInfo(NULL,key,dictFind(db->dict,key->ptr) != NULL);\n    return dictGetSignedIntegerVal(de);\n}\n\n/* Propagate expires into slaves and the AOF file.\n * When a key expires in the master, a DEL operation for this key is sent\n * to all the slaves and the AOF file if enabled.\n *\n * This way the key expiry is centralized in one place, and since both\n * AOF and the master->slave link guarantee operation ordering, everything\n * will be consistent even if we allow write operations against expiring\n * keys. */\nvoid propagateExpire(redisDb *db, robj *key) {\n    robj *argv[2];\n\n    argv[0] = shared.del;\n    argv[1] = key;\n    incrRefCount(argv[0]);\n    incrRefCount(argv[1]);\n\n    if (server.aof_state != AOF_OFF)\n        feedAppendOnlyFile(server.delCommand,db->id,argv,2);\n    replicationFeedSlaves(server.slaves,db->id,argv,2);\n\n    decrRefCount(argv[0]);\n    decrRefCount(argv[1]);\n}\n\nint expireIfNeeded(redisDb *db, robj *key) {\n    mstime_t when = getExpire(db,key);\n    mstime_t now;\n\n    if (when < 0) return 0; /* No expire for this key */\n\n    /* Don't expire anything while loading. It will be done later. */\n    if (server.loading) return 0;\n\n    /* If we are in the context of a Lua script, we claim that time is\n     * blocked to when the Lua script started. This way a key can expire\n     * only the first time it is accessed and not in the middle of the\n     * script execution, making propagation to slaves / AOF consistent.\n     * See issue #1525 on Github for more information. */\n    now = server.lua_caller ? server.lua_time_start : mstime();\n\n    /* If we are running in the context of a slave, return ASAP:\n     * the slave key expiration is controlled by the master that will\n     * send us synthesized DEL operations for expired keys.\n     *\n     * Still we try to return the right information to the caller,\n     * that is, 0 if we think the key should be still valid, 1 if\n     * we think the key is expired at this time. */\n    if (server.masterhost != NULL) return now > when;\n\n    /* Return when this key has not expired */\n    if (now <= when) return 0;\n\n    /* Delete the key */\n    server.stat_expiredkeys++;\n    propagateExpire(db,key);\n    notifyKeyspaceEvent(NOTIFY_EXPIRED,\n        \"expired\",key,db->id);\n    return dbDelete(db,key);\n}\n\n/*-----------------------------------------------------------------------------\n * Expires Commands\n *----------------------------------------------------------------------------*/\n\n/* This is the generic command implementation for EXPIRE, PEXPIRE, EXPIREAT\n * and PEXPIREAT. Because the commad second argument may be relative or absolute\n * the \"basetime\" argument is used to signal what the base time is (either 0\n * for *AT variants of the command, or the current time for relative expires).\n *\n * unit is either UNIT_SECONDS or UNIT_MILLISECONDS, and is only used for\n * the argv[2] parameter. The basetime is always specified in milliseconds. */\nvoid expireGenericCommand(client *c, long long basetime, int unit) {\n    robj *key = c->argv[1], *param = c->argv[2];\n    long long when; /* unix time in milliseconds when the key will expire. */\n\n    if (getLongLongFromObjectOrReply(c, param, &when, NULL) != C_OK)\n        return;\n\n    if (unit == UNIT_SECONDS) when *= 1000;\n    when += basetime;\n\n    /* No key, return zero. */\n    if (lookupKeyWrite(c->db,key) == NULL) {\n        addReply(c,shared.czero);\n        return;\n    }\n\n    /* EXPIRE with negative TTL, or EXPIREAT with a timestamp into the past\n     * should never be executed as a DEL when load the AOF or in the context\n     * of a slave instance.\n     *\n     * Instead we take the other branch of the IF statement setting an expire\n     * (possibly in the past) and wait for an explicit DEL from the master. */\n    if (when <= mstime() && !server.loading && !server.masterhost) {\n        robj *aux;\n\n        serverAssertWithInfo(c,key,dbDelete(c->db,key));\n        server.dirty++;\n\n        /* Replicate/AOF this as an explicit DEL. */\n        aux = createStringObject(\"DEL\",3);\n        rewriteClientCommandVector(c,2,aux,key);\n        decrRefCount(aux);\n        signalModifiedKey(c->db,key);\n        notifyKeyspaceEvent(NOTIFY_GENERIC,\"del\",key,c->db->id);\n        addReply(c, shared.cone);\n        return;\n    } else {\n        setExpire(c->db,key,when);\n        addReply(c,shared.cone);\n        signalModifiedKey(c->db,key);\n        notifyKeyspaceEvent(NOTIFY_GENERIC,\"expire\",key,c->db->id);\n        server.dirty++;\n        return;\n    }\n}\n\nvoid expireCommand(client *c) {\n    expireGenericCommand(c,mstime(),UNIT_SECONDS);\n}\n\nvoid expireatCommand(client *c) {\n    expireGenericCommand(c,0,UNIT_SECONDS);\n}\n\nvoid pexpireCommand(client *c) {\n    expireGenericCommand(c,mstime(),UNIT_MILLISECONDS);\n}\n\nvoid pexpireatCommand(client *c) {\n    expireGenericCommand(c,0,UNIT_MILLISECONDS);\n}\n\nvoid ttlGenericCommand(client *c, int output_ms) {\n    long long expire, ttl = -1;\n\n    /* If the key does not exist at all, return -2 */\n    if (lookupKeyReadWithFlags(c->db,c->argv[1],LOOKUP_NOTOUCH) == NULL) {\n        addReplyLongLong(c,-2);\n        return;\n    }\n    /* The key exists. Return -1 if it has no expire, or the actual\n     * TTL value otherwise. */\n    expire = getExpire(c->db,c->argv[1]);\n    if (expire != -1) {\n        ttl = expire-mstime();\n        if (ttl < 0) ttl = 0;\n    }\n    if (ttl == -1) {\n        addReplyLongLong(c,-1);\n    } else {\n        addReplyLongLong(c,output_ms ? ttl : ((ttl+500)/1000));\n    }\n}\n\nvoid ttlCommand(client *c) {\n    ttlGenericCommand(c, 0);\n}\n\nvoid pttlCommand(client *c) {\n    ttlGenericCommand(c, 1);\n}\n\nvoid persistCommand(client *c) {\n    dictEntry *de;\n\n    de = dictFind(c->db->dict,c->argv[1]->ptr);\n    if (de == NULL) {\n        addReply(c,shared.czero);\n    } else {\n        if (removeExpire(c->db,c->argv[1])) {\n            addReply(c,shared.cone);\n            server.dirty++;\n        } else {\n            addReply(c,shared.czero);\n        }\n    }\n}\n\n/* TOUCH key1 [key2 key3 ... keyN] */\nvoid touchCommand(client *c) {\n    int touched = 0;\n    for (int j = 1; j < c->argc; j++)\n        if (lookupKeyRead(c->db,c->argv[j]) != NULL) touched++;\n    addReplyLongLong(c,touched);\n}\n\n/* -----------------------------------------------------------------------------\n * API to get key arguments from commands\n * ---------------------------------------------------------------------------*/\n\n/* The base case is to use the keys position as given in the command table\n * (firstkey, lastkey, step). */\nint *getKeysUsingCommandTable(struct redisCommand *cmd,robj **argv, int argc, int *numkeys) {\n    int j, i = 0, last, *keys;\n    UNUSED(argv);\n\n    if (cmd->firstkey == 0) {\n        *numkeys = 0;\n        return NULL;\n    }\n    last = cmd->lastkey;\n    if (last < 0) last = argc+last;\n    keys = zmalloc(sizeof(int)*((last - cmd->firstkey)+1));\n    for (j = cmd->firstkey; j <= last; j += cmd->keystep) {\n        serverAssert(j < argc);\n        keys[i++] = j;\n    }\n    *numkeys = i;\n    return keys;\n}\n\n/* Return all the arguments that are keys in the command passed via argc / argv.\n *\n * The command returns the positions of all the key arguments inside the array,\n * so the actual return value is an heap allocated array of integers. The\n * length of the array is returned by reference into *numkeys.\n *\n * 'cmd' must be point to the corresponding entry into the redisCommand\n * table, according to the command name in argv[0].\n *\n * This function uses the command table if a command-specific helper function\n * is not required, otherwise it calls the command-specific function. */\nint *getKeysFromCommand(struct redisCommand *cmd, robj **argv, int argc, int *numkeys) {\n    if (cmd->getkeys_proc) {\n        return cmd->getkeys_proc(cmd,argv,argc,numkeys);\n    } else {\n        return getKeysUsingCommandTable(cmd,argv,argc,numkeys);\n    }\n}\n\n/* Free the result of getKeysFromCommand. */\nvoid getKeysFreeResult(int *result) {\n    zfree(result);\n}\n\n/* Helper function to extract keys from following commands:\n * ZUNIONSTORE <destkey> <num-keys> <key> <key> ... <key> <options>\n * ZINTERSTORE <destkey> <num-keys> <key> <key> ... <key> <options> */\nint *zunionInterGetKeys(struct redisCommand *cmd, robj **argv, int argc, int *numkeys) {\n    int i, num, *keys;\n    UNUSED(cmd);\n\n    num = atoi(argv[2]->ptr);\n    /* Sanity check. Don't return any key if the command is going to\n     * reply with syntax error. */\n    if (num > (argc-3)) {\n        *numkeys = 0;\n        return NULL;\n    }\n\n    /* Keys in z{union,inter}store come from two places:\n     * argv[1] = storage key,\n     * argv[3...n] = keys to intersect */\n    keys = zmalloc(sizeof(int)*(num+1));\n\n    /* Add all key positions for argv[3...n] to keys[] */\n    for (i = 0; i < num; i++) keys[i] = 3+i;\n\n    /* Finally add the argv[1] key position (the storage key target). */\n    keys[num] = 1;\n    *numkeys = num+1;  /* Total keys = {union,inter} keys + storage key */\n    return keys;\n}\n\n/* Helper function to extract keys from the following commands:\n * EVAL <script> <num-keys> <key> <key> ... <key> [more stuff]\n * EVALSHA <script> <num-keys> <key> <key> ... <key> [more stuff] */\nint *evalGetKeys(struct redisCommand *cmd, robj **argv, int argc, int *numkeys) {\n    int i, num, *keys;\n    UNUSED(cmd);\n\n    num = atoi(argv[2]->ptr);\n    /* Sanity check. Don't return any key if the command is going to\n     * reply with syntax error. */\n    if (num > (argc-3)) {\n        *numkeys = 0;\n        return NULL;\n    }\n\n    keys = zmalloc(sizeof(int)*num);\n    *numkeys = num;\n\n    /* Add all key positions for argv[3...n] to keys[] */\n    for (i = 0; i < num; i++) keys[i] = 3+i;\n\n    return keys;\n}\n\n/* Helper function to extract keys from the SORT command.\n *\n * SORT <sort-key> ... STORE <store-key> ...\n *\n * The first argument of SORT is always a key, however a list of options\n * follow in SQL-alike style. Here we parse just the minimum in order to\n * correctly identify keys in the \"STORE\" option. */\nint *sortGetKeys(struct redisCommand *cmd, robj **argv, int argc, int *numkeys) {\n    int i, j, num, *keys, found_store = 0;\n    UNUSED(cmd);\n\n    num = 0;\n    keys = zmalloc(sizeof(int)*2); /* Alloc 2 places for the worst case. */\n\n    keys[num++] = 1; /* <sort-key> is always present. */\n\n    /* Search for STORE option. By default we consider options to don't\n     * have arguments, so if we find an unknown option name we scan the\n     * next. However there are options with 1 or 2 arguments, so we\n     * provide a list here in order to skip the right number of args. */\n    struct {\n        char *name;\n        int skip;\n    } skiplist[] = {\n        {\"limit\", 2},\n        {\"get\", 1},\n        {\"by\", 1},\n        {NULL, 0} /* End of elements. */\n    };\n\n    for (i = 2; i < argc; i++) {\n        for (j = 0; skiplist[j].name != NULL; j++) {\n            if (!strcasecmp(argv[i]->ptr,skiplist[j].name)) {\n                i += skiplist[j].skip;\n                break;\n            } else if (!strcasecmp(argv[i]->ptr,\"store\") && i+1 < argc) {\n                /* Note: we don't increment \"num\" here and continue the loop\n                 * to be sure to process the *last* \"STORE\" option if multiple\n                 * ones are provided. This is same behavior as SORT. */\n                found_store = 1;\n                keys[num] = i+1; /* <store-key> */\n                break;\n            }\n        }\n    }\n    *numkeys = num + found_store;\n    return keys;\n}\n\nint *migrateGetKeys(struct redisCommand *cmd, robj **argv, int argc, int *numkeys) {\n    int i, num, first, *keys;\n    UNUSED(cmd);\n\n    /* Assume the obvious form. */\n    first = 3;\n    num = 1;\n\n    /* But check for the extended one with the KEYS option. */\n    if (argc > 6) {\n        for (i = 6; i < argc; i++) {\n            if (!strcasecmp(argv[i]->ptr,\"keys\") &&\n                sdslen(argv[3]->ptr) == 0)\n            {\n                first = i+1;\n                num = argc-first;\n                break;\n            }\n        }\n    }\n\n    keys = zmalloc(sizeof(int)*num);\n    for (i = 0; i < num; i++) keys[i] = first+i;\n    *numkeys = num;\n    return keys;\n}\n\n/* Helper function to extract keys from following commands:\n * GEORADIUS key x y radius unit [WITHDIST] [WITHHASH] [WITHCOORD] [ASC|DESC]\n *                             [COUNT count] [STORE key] [STOREDIST key]\n * GEORADIUSBYMEMBER key member radius unit ... options ... */\nint *georadiusGetKeys(struct redisCommand *cmd, robj **argv, int argc, int *numkeys) {\n    int i, num, *keys;\n    UNUSED(cmd);\n\n    /* Check for the presence of the stored key in the command */\n    int stored_key = -1;\n    for (i = 5; i < argc; i++) {\n        char *arg = argv[i]->ptr;\n        /* For the case when user specifies both \"store\" and \"storedist\" options, the\n         * second key specified would override the first key. This behavior is kept \n         * the same as in georadiusCommand method.\n         */\n        if ((!strcasecmp(arg, \"store\") || !strcasecmp(arg, \"storedist\")) && ((i+1) < argc)) {\n            stored_key = i+1;\n            i++;\n        }\n    }\n    num = 1 + (stored_key == -1 ? 0 : 1);\n\n    /* Keys in the command come from two places:\n     * argv[1] = key,\n     * argv[5...n] = stored key if present\n     */\n    keys = zmalloc(sizeof(int) * num);\n\n    /* Add all key positions to keys[] */\n    keys[0] = 1;\n    if(num > 1) {\n         keys[1] = stored_key;\n    }\n    *numkeys = num; \n    return keys;\n}\n\n/* Slot to Key API. This is used by Redis Cluster in order to obtain in\n * a fast way a key that belongs to a specified hash slot. This is useful\n * while rehashing the cluster. */\nvoid slotToKeyAdd(robj *key) {\n    unsigned int hashslot = keyHashSlot(key->ptr,sdslen(key->ptr));\n\n    zslInsert(server.cluster->slots_to_keys,hashslot,key);\n    incrRefCount(key);\n}\n\nvoid slotToKeyDel(robj *key) {\n    unsigned int hashslot = keyHashSlot(key->ptr,sdslen(key->ptr));\n\n    zslDelete(server.cluster->slots_to_keys,hashslot,key);\n}\n\nvoid slotToKeyFlush(void) {\n    zslFree(server.cluster->slots_to_keys);\n    server.cluster->slots_to_keys = zslCreate();\n}\n\nunsigned int getKeysInSlot(unsigned int hashslot, robj **keys, unsigned int count) {\n    zskiplistNode *n;\n    zrangespec range;\n    int j = 0;\n\n    range.min = range.max = hashslot;\n    range.minex = range.maxex = 0;\n\n    n = zslFirstInRange(server.cluster->slots_to_keys, &range);\n    while(n && n->score == hashslot && count--) {\n        keys[j++] = n->obj;\n        n = n->level[0].forward;\n    }\n    return j;\n}\n\n/* Remove all the keys in the specified hash slot.\n * The number of removed items is returned. */\nunsigned int delKeysInSlot(unsigned int hashslot) {\n    zskiplistNode *n;\n    zrangespec range;\n    int j = 0;\n\n    range.min = range.max = hashslot;\n    range.minex = range.maxex = 0;\n\n    n = zslFirstInRange(server.cluster->slots_to_keys, &range);\n    while(n && n->score == hashslot) {\n        robj *key = n->obj;\n        n = n->level[0].forward; /* Go to the next item before freeing it. */\n        incrRefCount(key); /* Protect the object while freeing it. */\n        dbDelete(&server.db[0],key);\n        decrRefCount(key);\n        j++;\n    }\n    return j;\n}\n\nunsigned int countKeysInSlot(unsigned int hashslot) {\n    zskiplist *zsl = server.cluster->slots_to_keys;\n    zskiplistNode *zn;\n    zrangespec range;\n    int rank, count = 0;\n\n    range.min = range.max = hashslot;\n    range.minex = range.maxex = 0;\n\n    /* Find first element in range */\n    zn = zslFirstInRange(zsl, &range);\n\n    /* Use rank of first element, if any, to determine preliminary count */\n    if (zn != NULL) {\n        rank = zslGetRank(zsl, zn->score, zn->obj);\n        count = (zsl->length - (rank - 1));\n\n        /* Find last element in range */\n        zn = zslLastInRange(zsl, &range);\n\n        /* Use rank of last element, if any, to determine the actual count */\n        if (zn != NULL) {\n            rank = zslGetRank(zsl, zn->score, zn->obj);\n            count -= (zsl->length - rank);\n        }\n    }\n    return count;\n}\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.8/src/debug.c",
    "content": "/*\n * Copyright (c) 2009-2012, Salvatore Sanfilippo <antirez at gmail dot com>\n * All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions are met:\n *\n *   * Redistributions of source code must retain the above copyright notice,\n *     this list of conditions and the following disclaimer.\n *   * Redistributions in binary form must reproduce the above copyright\n *     notice, this list of conditions and the following disclaimer in the\n *     documentation and/or other materials provided with the distribution.\n *   * Neither the name of Redis nor the names of its contributors may be used\n *     to endorse or promote products derived from this software without\n *     specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\"\n * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\n * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE\n * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR\n * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF\n * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS\n * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN\n * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)\n * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE\n * POSSIBILITY OF SUCH DAMAGE.\n */\n\n#include \"server.h\"\n#include \"sha1.h\"   /* SHA1 is used for DEBUG DIGEST */\n#include \"crc64.h\"\n\n#include <arpa/inet.h>\n#include <signal.h>\n\n#ifdef HAVE_BACKTRACE\n#include <execinfo.h>\n#include <ucontext.h>\n#include <fcntl.h>\n#include \"bio.h\"\n#include <unistd.h>\n#include <dlfcn.h>\n#endif /* HAVE_BACKTRACE */\n\n#ifdef __CYGWIN__\n#ifndef SA_ONSTACK\n#define SA_ONSTACK 0x08000000\n#endif\n#endif\n\n/* ================================= Debugging ============================== */\n\n/* Compute the sha1 of string at 's' with 'len' bytes long.\n * The SHA1 is then xored against the string pointed by digest.\n * Since xor is commutative, this operation is used in order to\n * \"add\" digests relative to unordered elements.\n *\n * So digest(a,b,c,d) will be the same of digest(b,a,c,d) */\nvoid xorDigest(unsigned char *digest, void *ptr, size_t len) {\n    SHA1_CTX ctx;\n    unsigned char hash[20], *s = ptr;\n    int j;\n\n    SHA1Init(&ctx);\n    SHA1Update(&ctx,s,len);\n    SHA1Final(hash,&ctx);\n\n    for (j = 0; j < 20; j++)\n        digest[j] ^= hash[j];\n}\n\nvoid xorObjectDigest(unsigned char *digest, robj *o) {\n    o = getDecodedObject(o);\n    xorDigest(digest,o->ptr,sdslen(o->ptr));\n    decrRefCount(o);\n}\n\n/* This function instead of just computing the SHA1 and xoring it\n * against digest, also perform the digest of \"digest\" itself and\n * replace the old value with the new one.\n *\n * So the final digest will be:\n *\n * digest = SHA1(digest xor SHA1(data))\n *\n * This function is used every time we want to preserve the order so\n * that digest(a,b,c,d) will be different than digest(b,c,d,a)\n *\n * Also note that mixdigest(\"foo\") followed by mixdigest(\"bar\")\n * will lead to a different digest compared to \"fo\", \"obar\".\n */\nvoid mixDigest(unsigned char *digest, void *ptr, size_t len) {\n    SHA1_CTX ctx;\n    char *s = ptr;\n\n    xorDigest(digest,s,len);\n    SHA1Init(&ctx);\n    SHA1Update(&ctx,digest,20);\n    SHA1Final(digest,&ctx);\n}\n\nvoid mixObjectDigest(unsigned char *digest, robj *o) {\n    o = getDecodedObject(o);\n    mixDigest(digest,o->ptr,sdslen(o->ptr));\n    decrRefCount(o);\n}\n\n/* Compute the dataset digest. Since keys, sets elements, hashes elements\n * are not ordered, we use a trick: every aggregate digest is the xor\n * of the digests of their elements. This way the order will not change\n * the result. For list instead we use a feedback entering the output digest\n * as input in order to ensure that a different ordered list will result in\n * a different digest. */\nvoid computeDatasetDigest(unsigned char *final) {\n    unsigned char digest[20];\n    char buf[128];\n    dictIterator *di = NULL;\n    dictEntry *de;\n    int j;\n    uint32_t aux;\n\n    memset(final,0,20); /* Start with a clean result */\n\n    for (j = 0; j < server.dbnum; j++) {\n        redisDb *db = server.db+j;\n\n        if (dictSize(db->dict) == 0) continue;\n        di = dictGetSafeIterator(db->dict);\n\n        /* hash the DB id, so the same dataset moved in a different\n         * DB will lead to a different digest */\n        aux = htonl(j);\n        mixDigest(final,&aux,sizeof(aux));\n\n        /* Iterate this DB writing every entry */\n        while((de = dictNext(di)) != NULL) {\n            sds key;\n            robj *keyobj, *o;\n            long long expiretime;\n\n            memset(digest,0,20); /* This key-val digest */\n            key = dictGetKey(de);\n            keyobj = createStringObject(key,sdslen(key));\n\n            mixDigest(digest,key,sdslen(key));\n\n            o = dictGetVal(de);\n\n            aux = htonl(o->type);\n            mixDigest(digest,&aux,sizeof(aux));\n            expiretime = getExpire(db,keyobj);\n\n            /* Save the key and associated value */\n            if (o->type == OBJ_STRING) {\n                mixObjectDigest(digest,o);\n            } else if (o->type == OBJ_LIST) {\n                listTypeIterator *li = listTypeInitIterator(o,0,LIST_TAIL);\n                listTypeEntry entry;\n                while(listTypeNext(li,&entry)) {\n                    robj *eleobj = listTypeGet(&entry);\n                    mixObjectDigest(digest,eleobj);\n                    decrRefCount(eleobj);\n                }\n                listTypeReleaseIterator(li);\n            } else if (o->type == OBJ_SET) {\n                setTypeIterator *si = setTypeInitIterator(o);\n                robj *ele;\n                while((ele = setTypeNextObject(si)) != NULL) {\n                    xorObjectDigest(digest,ele);\n                    decrRefCount(ele);\n                }\n                setTypeReleaseIterator(si);\n            } else if (o->type == OBJ_ZSET) {\n                unsigned char eledigest[20];\n\n                if (o->encoding == OBJ_ENCODING_ZIPLIST) {\n                    unsigned char *zl = o->ptr;\n                    unsigned char *eptr, *sptr;\n                    unsigned char *vstr;\n                    unsigned int vlen;\n                    long long vll;\n                    double score;\n\n                    eptr = ziplistIndex(zl,0);\n                    serverAssert(eptr != NULL);\n                    sptr = ziplistNext(zl,eptr);\n                    serverAssert(sptr != NULL);\n\n                    while (eptr != NULL) {\n                        serverAssert(ziplistGet(eptr,&vstr,&vlen,&vll));\n                        score = zzlGetScore(sptr);\n\n                        memset(eledigest,0,20);\n                        if (vstr != NULL) {\n                            mixDigest(eledigest,vstr,vlen);\n                        } else {\n                            ll2string(buf,sizeof(buf),vll);\n                            mixDigest(eledigest,buf,strlen(buf));\n                        }\n\n                        snprintf(buf,sizeof(buf),\"%.17g\",score);\n                        mixDigest(eledigest,buf,strlen(buf));\n                        xorDigest(digest,eledigest,20);\n                        zzlNext(zl,&eptr,&sptr);\n                    }\n                } else if (o->encoding == OBJ_ENCODING_SKIPLIST) {\n                    zset *zs = o->ptr;\n                    dictIterator *di = dictGetIterator(zs->dict);\n                    dictEntry *de;\n\n                    while((de = dictNext(di)) != NULL) {\n                        robj *eleobj = dictGetKey(de);\n                        double *score = dictGetVal(de);\n\n                        snprintf(buf,sizeof(buf),\"%.17g\",*score);\n                        memset(eledigest,0,20);\n                        mixObjectDigest(eledigest,eleobj);\n                        mixDigest(eledigest,buf,strlen(buf));\n                        xorDigest(digest,eledigest,20);\n                    }\n                    dictReleaseIterator(di);\n                } else {\n                    serverPanic(\"Unknown sorted set encoding\");\n                }\n            } else if (o->type == OBJ_HASH) {\n                hashTypeIterator *hi;\n                robj *obj;\n\n                hi = hashTypeInitIterator(o);\n                while (hashTypeNext(hi) != C_ERR) {\n                    unsigned char eledigest[20];\n\n                    memset(eledigest,0,20);\n                    obj = hashTypeCurrentObject(hi,OBJ_HASH_KEY);\n                    mixObjectDigest(eledigest,obj);\n                    decrRefCount(obj);\n                    obj = hashTypeCurrentObject(hi,OBJ_HASH_VALUE);\n                    mixObjectDigest(eledigest,obj);\n                    decrRefCount(obj);\n                    xorDigest(digest,eledigest,20);\n                }\n                hashTypeReleaseIterator(hi);\n            } else {\n                serverPanic(\"Unknown object type\");\n            }\n            /* If the key has an expire, add it to the mix */\n            if (expiretime != -1) xorDigest(digest,\"!!expire!!\",10);\n            /* We can finally xor the key-val digest to the final digest */\n            xorDigest(final,digest,20);\n            decrRefCount(keyobj);\n        }\n        dictReleaseIterator(di);\n    }\n}\n\n#if defined(USE_JEMALLOC)\nvoid inputCatSds(void *result, const char *str) {\n    /* result is actually a (sds *), so re-cast it here */\n    sds *info = (sds *)result;\n    *info = sdscat(*info, str);\n}\n#endif\n\nvoid debugCommand(client *c) {\n    if (c->argc == 1) {\n        addReplyError(c,\"You must specify a subcommand for DEBUG. Try DEBUG HELP for info.\");\n        return;\n    }\n\n    if (!strcasecmp(c->argv[1]->ptr,\"help\")) {\n        void *blenp = addDeferredMultiBulkLength(c);\n        int blen = 0;\n        blen++; addReplyStatus(c,\n        \"DEBUG <subcommand> arg arg ... arg. Subcommands:\");\n        blen++; addReplyStatus(c,\n        \"segfault -- Crash the server with sigsegv.\");\n        blen++; addReplyStatus(c,\n        \"restart  -- Graceful restart: save config, db, restart.\");\n        blen++; addReplyStatus(c,\n        \"crash-and-recovery <milliseconds> -- Hard crash and restart after <milliseconds> delay.\");\n        blen++; addReplyStatus(c,\n        \"assert   -- Crash by assertion failed.\");\n        blen++; addReplyStatus(c,\n        \"reload   -- Save the RDB on disk and reload it back in memory.\");\n        blen++; addReplyStatus(c,\n        \"loadaof  -- Flush the AOF buffers on disk and reload the AOF in memory.\");\n        blen++; addReplyStatus(c,\n        \"object <key> -- Show low level info about key and associated value.\");\n        blen++; addReplyStatus(c,\n        \"sdslen <key> -- Show low level SDS string info representing key and value.\");\n        blen++; addReplyStatus(c,\n        \"populate <count> [prefix] -- Create <count> string keys named key:<num>. If a prefix is specified is used instead of the 'key' prefix.\");\n        blen++; addReplyStatus(c,\n        \"digest   -- Outputs an hex signature representing the current DB content.\");\n        blen++; addReplyStatus(c,\n        \"sleep <seconds> -- Stop the server for <seconds>. Decimals allowed.\");\n        blen++; addReplyStatus(c,\n        \"set-active-expire (0|1) -- Setting it to 0 disables expiring keys in background when they are not accessed (otherwise the Redis behavior). Setting it to 1 reenables back the default.\");\n        blen++; addReplyStatus(c,\n        \"lua-always-replicate-commands (0|1) -- Setting it to 1 makes Lua replication defaulting to replicating single commands, without the script having to enable effects replication.\");\n        blen++; addReplyStatus(c,\n        \"error <string> -- Return a Redis protocol error with <string> as message. Useful for clients unit tests to simulate Redis errors.\");\n        blen++; addReplyStatus(c,\n        \"structsize -- Return the size of different Redis core C structures.\");\n        blen++; addReplyStatus(c,\n        \"htstats <dbid> -- Return hash table statistics of the specified Redis database.\");\n        blen++; addReplyStatus(c,\n        \"jemalloc info  -- Show internal jemalloc statistics.\");\n        blen++; addReplyStatus(c,\n        \"jemalloc purge -- Force jemalloc to release unused memory.\");\n        setDeferredMultiBulkLength(c,blenp,blen);\n    } else if (!strcasecmp(c->argv[1]->ptr,\"segfault\")) {\n        *((char*)-1) = 'x';\n    } else if (!strcasecmp(c->argv[1]->ptr,\"restart\") ||\n               !strcasecmp(c->argv[1]->ptr,\"crash-and-recover\"))\n    {\n        long long delay = 0;\n        if (c->argc >= 3) {\n            if (getLongLongFromObjectOrReply(c, c->argv[2], &delay, NULL)\n                != C_OK) return;\n            if (delay < 0) delay = 0;\n        }\n        int flags = !strcasecmp(c->argv[1]->ptr,\"restart\") ?\n            (RESTART_SERVER_GRACEFULLY|RESTART_SERVER_CONFIG_REWRITE) :\n             RESTART_SERVER_NONE;\n        restartServer(flags,delay);\n        addReplyError(c,\"failed to restart the server. Check server logs.\");\n    } else if (!strcasecmp(c->argv[1]->ptr,\"oom\")) {\n        void *ptr = zmalloc(ULONG_MAX); /* Should trigger an out of memory. */\n        zfree(ptr);\n        addReply(c,shared.ok);\n    } else if (!strcasecmp(c->argv[1]->ptr,\"assert\")) {\n        if (c->argc >= 3) c->argv[2] = tryObjectEncoding(c->argv[2]);\n        serverAssertWithInfo(c,c->argv[0],1 == 2);\n    } else if (!strcasecmp(c->argv[1]->ptr,\"reload\")) {\n        if (rdbSave(server.rdb_filename) != C_OK) {\n            addReply(c,shared.err);\n            return;\n        }\n        emptyDb(NULL);\n        if (rdbLoad(server.rdb_filename) != C_OK) {\n            addReplyError(c,\"Error trying to load the RDB dump\");\n            return;\n        }\n        serverLog(LL_WARNING,\"DB reloaded by DEBUG RELOAD\");\n        addReply(c,shared.ok);\n    } else if (!strcasecmp(c->argv[1]->ptr,\"loadaof\")) {\n        if (server.aof_state == AOF_ON) flushAppendOnlyFile(1);\n        emptyDb(NULL);\n        if (loadAppendOnlyFile(server.aof_filename) != C_OK) {\n            addReply(c,shared.err);\n            return;\n        }\n        server.dirty = 0; /* Prevent AOF / replication */\n        serverLog(LL_WARNING,\"Append Only File loaded by DEBUG LOADAOF\");\n        addReply(c,shared.ok);\n    } else if (!strcasecmp(c->argv[1]->ptr,\"object\") && c->argc == 3) {\n        dictEntry *de;\n        robj *val;\n        char *strenc;\n\n        if ((de = dictFind(c->db->dict,c->argv[2]->ptr)) == NULL) {\n            addReply(c,shared.nokeyerr);\n            return;\n        }\n        val = dictGetVal(de);\n        strenc = strEncoding(val->encoding);\n\n        char extra[128] = {0};\n        if (val->encoding == OBJ_ENCODING_QUICKLIST) {\n            char *nextra = extra;\n            int remaining = sizeof(extra);\n            quicklist *ql = val->ptr;\n            /* Add number of quicklist nodes */\n            int used = snprintf(nextra, remaining, \" ql_nodes:%u\", ql->len);\n            nextra += used;\n            remaining -= used;\n            /* Add average quicklist fill factor */\n            double avg = (double)ql->count/ql->len;\n            used = snprintf(nextra, remaining, \" ql_avg_node:%.2f\", avg);\n            nextra += used;\n            remaining -= used;\n            /* Add quicklist fill level / max ziplist size */\n            used = snprintf(nextra, remaining, \" ql_ziplist_max:%d\", ql->fill);\n            nextra += used;\n            remaining -= used;\n            /* Add isCompressed? */\n            int compressed = ql->compress != 0;\n            used = snprintf(nextra, remaining, \" ql_compressed:%d\", compressed);\n            nextra += used;\n            remaining -= used;\n            /* Add total uncompressed size */\n            unsigned long sz = 0;\n            for (quicklistNode *node = ql->head; node; node = node->next) {\n                sz += node->sz;\n            }\n            used = snprintf(nextra, remaining, \" ql_uncompressed_size:%lu\", sz);\n            nextra += used;\n            remaining -= used;\n        }\n\n        addReplyStatusFormat(c,\n            \"Value at:%p refcount:%d \"\n            \"encoding:%s serializedlength:%zu \"\n            \"lru:%d lru_seconds_idle:%llu%s\",\n            (void*)val, val->refcount,\n            strenc, rdbSavedObjectLen(val),\n            val->lru, estimateObjectIdleTime(val)/1000, extra);\n    } else if (!strcasecmp(c->argv[1]->ptr,\"sdslen\") && c->argc == 3) {\n        dictEntry *de;\n        robj *val;\n        sds key;\n\n        if ((de = dictFind(c->db->dict,c->argv[2]->ptr)) == NULL) {\n            addReply(c,shared.nokeyerr);\n            return;\n        }\n        val = dictGetVal(de);\n        key = dictGetKey(de);\n\n        if (val->type != OBJ_STRING || !sdsEncodedObject(val)) {\n            addReplyError(c,\"Not an sds encoded string.\");\n        } else {\n            addReplyStatusFormat(c,\n                \"key_sds_len:%lld, key_sds_avail:%lld, \"\n                \"val_sds_len:%lld, val_sds_avail:%lld\",\n                (long long) sdslen(key),\n                (long long) sdsavail(key),\n                (long long) sdslen(val->ptr),\n                (long long) sdsavail(val->ptr));\n        }\n    } else if (!strcasecmp(c->argv[1]->ptr,\"populate\") &&\n               (c->argc == 3 || c->argc == 4)) {\n        long keys, j;\n        robj *key, *val;\n        char buf[128];\n\n        if (getLongFromObjectOrReply(c, c->argv[2], &keys, NULL) != C_OK)\n            return;\n        dictExpand(c->db->dict,keys);\n        for (j = 0; j < keys; j++) {\n            snprintf(buf,sizeof(buf),\"%s:%lu\",\n                (c->argc == 3) ? \"key\" : (char*)c->argv[3]->ptr, j);\n            key = createStringObject(buf,strlen(buf));\n            if (lookupKeyWrite(c->db,key) != NULL) {\n                decrRefCount(key);\n                continue;\n            }\n            snprintf(buf,sizeof(buf),\"value:%lu\",j);\n            val = createStringObject(buf,strlen(buf));\n            dbAdd(c->db,key,val);\n            signalModifiedKey(c->db,key);\n            decrRefCount(key);\n        }\n        addReply(c,shared.ok);\n    } else if (!strcasecmp(c->argv[1]->ptr,\"digest\") && c->argc == 2) {\n        unsigned char digest[20];\n        sds d = sdsempty();\n        int j;\n\n        computeDatasetDigest(digest);\n        for (j = 0; j < 20; j++)\n            d = sdscatprintf(d, \"%02x\",digest[j]);\n        addReplyStatus(c,d);\n        sdsfree(d);\n    } else if (!strcasecmp(c->argv[1]->ptr,\"sleep\") && c->argc == 3) {\n        double dtime = strtod(c->argv[2]->ptr,NULL);\n        long long utime = dtime*1000000;\n        struct timespec tv;\n\n        tv.tv_sec = utime / 1000000;\n        tv.tv_nsec = (utime % 1000000) * 1000;\n        nanosleep(&tv, NULL);\n        addReply(c,shared.ok);\n    } else if (!strcasecmp(c->argv[1]->ptr,\"set-active-expire\") &&\n               c->argc == 3)\n    {\n        server.active_expire_enabled = atoi(c->argv[2]->ptr);\n        addReply(c,shared.ok);\n    } else if (!strcasecmp(c->argv[1]->ptr,\"lua-always-replicate-commands\") &&\n               c->argc == 3)\n    {\n        server.lua_always_replicate_commands = atoi(c->argv[2]->ptr);\n        addReply(c,shared.ok);\n    } else if (!strcasecmp(c->argv[1]->ptr,\"error\") && c->argc == 3) {\n        sds errstr = sdsnewlen(\"-\",1);\n\n        errstr = sdscatsds(errstr,c->argv[2]->ptr);\n        errstr = sdsmapchars(errstr,\"\\n\\r\",\"  \",2); /* no newlines in errors. */\n        errstr = sdscatlen(errstr,\"\\r\\n\",2);\n        addReplySds(c,errstr);\n    } else if (!strcasecmp(c->argv[1]->ptr,\"structsize\") && c->argc == 2) {\n        sds sizes = sdsempty();\n        sizes = sdscatprintf(sizes,\"bits:%d \",(sizeof(void*) == 8)?64:32);\n        sizes = sdscatprintf(sizes,\"robj:%d \",(int)sizeof(robj));\n        sizes = sdscatprintf(sizes,\"dictentry:%d \",(int)sizeof(dictEntry));\n        sizes = sdscatprintf(sizes,\"sdshdr5:%d \",(int)sizeof(struct sdshdr5));\n        sizes = sdscatprintf(sizes,\"sdshdr8:%d \",(int)sizeof(struct sdshdr8));\n        sizes = sdscatprintf(sizes,\"sdshdr16:%d \",(int)sizeof(struct sdshdr16));\n        sizes = sdscatprintf(sizes,\"sdshdr32:%d \",(int)sizeof(struct sdshdr32));\n        sizes = sdscatprintf(sizes,\"sdshdr64:%d \",(int)sizeof(struct sdshdr64));\n        addReplyBulkSds(c,sizes);\n    } else if (!strcasecmp(c->argv[1]->ptr,\"htstats\") && c->argc == 3) {\n        long dbid;\n        sds stats = sdsempty();\n        char buf[4096];\n\n        if (getLongFromObjectOrReply(c, c->argv[2], &dbid, NULL) != C_OK)\n            return;\n        if (dbid < 0 || dbid >= server.dbnum) {\n            addReplyError(c,\"Out of range database\");\n            return;\n        }\n\n        stats = sdscatprintf(stats,\"[Dictionary HT]\\n\");\n        dictGetStats(buf,sizeof(buf),server.db[dbid].dict);\n        stats = sdscat(stats,buf);\n\n        stats = sdscatprintf(stats,\"[Expires HT]\\n\");\n        dictGetStats(buf,sizeof(buf),server.db[dbid].expires);\n        stats = sdscat(stats,buf);\n\n        addReplyBulkSds(c,stats);\n    } else if (!strcasecmp(c->argv[1]->ptr,\"jemalloc\") && c->argc == 3) {\n#if defined(USE_JEMALLOC)\n        if (!strcasecmp(c->argv[2]->ptr, \"info\")) {\n            sds info = sdsempty();\n            je_malloc_stats_print(inputCatSds, &info, NULL);\n            addReplyBulkSds(c, info);\n        } else if (!strcasecmp(c->argv[2]->ptr, \"purge\")) {\n            char tmp[32];\n            unsigned narenas = 0;\n            size_t sz = sizeof(unsigned);\n            if (!je_mallctl(\"arenas.narenas\", &narenas, &sz, NULL, 0)) {\n                sprintf(tmp, \"arena.%d.purge\", narenas);\n                if (!je_mallctl(tmp, NULL, 0, NULL, 0)) {\n                    addReply(c, shared.ok);\n                    return;\n                }\n            }\n            addReplyError(c, \"Error purging dirty pages\");\n        } else {\n            addReplyErrorFormat(c, \"Valid jemalloc debug fields: info, purge\");\n        }\n#else\n        addReplyErrorFormat(c, \"jemalloc support not available\");\n#endif\n    } else {\n        addReplyErrorFormat(c, \"Unknown DEBUG subcommand or wrong number of arguments for '%s'\",\n            (char*)c->argv[1]->ptr);\n    }\n}\n\n/* =========================== Crash handling  ============================== */\n\nvoid _serverAssert(char *estr, char *file, int line) {\n    bugReportStart();\n    serverLog(LL_WARNING,\"=== ASSERTION FAILED ===\");\n    serverLog(LL_WARNING,\"==> %s:%d '%s' is not true\",file,line,estr);\n#ifdef HAVE_BACKTRACE\n    server.assert_failed = estr;\n    server.assert_file = file;\n    server.assert_line = line;\n    serverLog(LL_WARNING,\"(forcing SIGSEGV to print the bug report.)\");\n#endif\n    *((char*)-1) = 'x';\n}\n\nvoid _serverAssertPrintClientInfo(client *c) {\n    int j;\n\n    bugReportStart();\n    serverLog(LL_WARNING,\"=== ASSERTION FAILED CLIENT CONTEXT ===\");\n    serverLog(LL_WARNING,\"client->flags = %d\", c->flags);\n    serverLog(LL_WARNING,\"client->fd = %d\", c->fd);\n    serverLog(LL_WARNING,\"client->argc = %d\", c->argc);\n    for (j=0; j < c->argc; j++) {\n        char buf[128];\n        char *arg;\n\n        if (c->argv[j]->type == OBJ_STRING && sdsEncodedObject(c->argv[j])) {\n            arg = (char*) c->argv[j]->ptr;\n        } else {\n            snprintf(buf,sizeof(buf),\"Object type: %u, encoding: %u\",\n                c->argv[j]->type, c->argv[j]->encoding);\n            arg = buf;\n        }\n        serverLog(LL_WARNING,\"client->argv[%d] = \\\"%s\\\" (refcount: %d)\",\n            j, arg, c->argv[j]->refcount);\n    }\n}\n\nvoid serverLogObjectDebugInfo(robj *o) {\n    serverLog(LL_WARNING,\"Object type: %d\", o->type);\n    serverLog(LL_WARNING,\"Object encoding: %d\", o->encoding);\n    serverLog(LL_WARNING,\"Object refcount: %d\", o->refcount);\n    if (o->type == OBJ_STRING && sdsEncodedObject(o)) {\n        serverLog(LL_WARNING,\"Object raw string len: %zu\", sdslen(o->ptr));\n        if (sdslen(o->ptr) < 4096) {\n            sds repr = sdscatrepr(sdsempty(),o->ptr,sdslen(o->ptr));\n            serverLog(LL_WARNING,\"Object raw string content: %s\", repr);\n            sdsfree(repr);\n        }\n    } else if (o->type == OBJ_LIST) {\n        serverLog(LL_WARNING,\"List length: %d\", (int) listTypeLength(o));\n    } else if (o->type == OBJ_SET) {\n        serverLog(LL_WARNING,\"Set size: %d\", (int) setTypeSize(o));\n    } else if (o->type == OBJ_HASH) {\n        serverLog(LL_WARNING,\"Hash size: %d\", (int) hashTypeLength(o));\n    } else if (o->type == OBJ_ZSET) {\n        serverLog(LL_WARNING,\"Sorted set size: %d\", (int) zsetLength(o));\n        if (o->encoding == OBJ_ENCODING_SKIPLIST)\n            serverLog(LL_WARNING,\"Skiplist level: %d\", (int) ((zset*)o->ptr)->zsl->level);\n    }\n}\n\nvoid _serverAssertPrintObject(robj *o) {\n    bugReportStart();\n    serverLog(LL_WARNING,\"=== ASSERTION FAILED OBJECT CONTEXT ===\");\n    serverLogObjectDebugInfo(o);\n}\n\nvoid _serverAssertWithInfo(client *c, robj *o, char *estr, char *file, int line) {\n    if (c) _serverAssertPrintClientInfo(c);\n    if (o) _serverAssertPrintObject(o);\n    _serverAssert(estr,file,line);\n}\n\nvoid _serverPanic(char *msg, char *file, int line) {\n    bugReportStart();\n    serverLog(LL_WARNING,\"------------------------------------------------\");\n    serverLog(LL_WARNING,\"!!! Software Failure. Press left mouse button to continue\");\n    serverLog(LL_WARNING,\"Guru Meditation: %s #%s:%d\",msg,file,line);\n#ifdef HAVE_BACKTRACE\n    serverLog(LL_WARNING,\"(forcing SIGSEGV in order to print the stack trace)\");\n#endif\n    serverLog(LL_WARNING,\"------------------------------------------------\");\n    *((char*)-1) = 'x';\n}\n\nvoid bugReportStart(void) {\n    if (server.bug_report_start == 0) {\n        serverLogRaw(LL_WARNING|LL_RAW,\n        \"\\n\\n=== REDIS BUG REPORT START: Cut & paste starting from here ===\\n\");\n        server.bug_report_start = 1;\n    }\n}\n\n#ifdef HAVE_BACKTRACE\nstatic void *getMcontextEip(ucontext_t *uc) {\n#if defined(__APPLE__) && !defined(MAC_OS_X_VERSION_10_6)\n    /* OSX < 10.6 */\n    #if defined(__x86_64__)\n    return (void*) uc->uc_mcontext->__ss.__rip;\n    #elif defined(__i386__)\n    return (void*) uc->uc_mcontext->__ss.__eip;\n    #else\n    return (void*) uc->uc_mcontext->__ss.__srr0;\n    #endif\n#elif defined(__APPLE__) && defined(MAC_OS_X_VERSION_10_6)\n    /* OSX >= 10.6 */\n    #if defined(_STRUCT_X86_THREAD_STATE64) && !defined(__i386__)\n    return (void*) uc->uc_mcontext->__ss.__rip;\n    #else\n    return (void*) uc->uc_mcontext->__ss.__eip;\n    #endif\n#elif defined(__linux__)\n    /* Linux */\n    #if defined(__i386__)\n    return (void*) uc->uc_mcontext.gregs[14]; /* Linux 32 */\n    #elif defined(__X86_64__) || defined(__x86_64__)\n    return (void*) uc->uc_mcontext.gregs[16]; /* Linux 64 */\n    #elif defined(__ia64__) /* Linux IA64 */\n    return (void*) uc->uc_mcontext.sc_ip;\n    #elif defined(__arm__) /* Linux ARM */\n    return (void*) uc->uc_mcontext.arm_pc;\n    #endif\n#else\n    return NULL;\n#endif\n}\n\nvoid logStackContent(void **sp) {\n    int i;\n    for (i = 15; i >= 0; i--) {\n        unsigned long addr = (unsigned long) sp+i;\n        unsigned long val = (unsigned long) sp[i];\n\n        if (sizeof(long) == 4)\n            serverLog(LL_WARNING, \"(%08lx) -> %08lx\", addr, val);\n        else\n            serverLog(LL_WARNING, \"(%016lx) -> %016lx\", addr, val);\n    }\n}\n\nvoid logRegisters(ucontext_t *uc) {\n    serverLog(LL_WARNING|LL_RAW, \"\\n------ REGISTERS ------\\n\");\n\n/* OSX */\n#if defined(__APPLE__) && defined(MAC_OS_X_VERSION_10_6)\n  /* OSX AMD64 */\n    #if defined(_STRUCT_X86_THREAD_STATE64) && !defined(__i386__)\n    serverLog(LL_WARNING,\n    \"\\n\"\n    \"RAX:%016lx RBX:%016lx\\nRCX:%016lx RDX:%016lx\\n\"\n    \"RDI:%016lx RSI:%016lx\\nRBP:%016lx RSP:%016lx\\n\"\n    \"R8 :%016lx R9 :%016lx\\nR10:%016lx R11:%016lx\\n\"\n    \"R12:%016lx R13:%016lx\\nR14:%016lx R15:%016lx\\n\"\n    \"RIP:%016lx EFL:%016lx\\nCS :%016lx FS:%016lx  GS:%016lx\",\n        (unsigned long) uc->uc_mcontext->__ss.__rax,\n        (unsigned long) uc->uc_mcontext->__ss.__rbx,\n        (unsigned long) uc->uc_mcontext->__ss.__rcx,\n        (unsigned long) uc->uc_mcontext->__ss.__rdx,\n        (unsigned long) uc->uc_mcontext->__ss.__rdi,\n        (unsigned long) uc->uc_mcontext->__ss.__rsi,\n        (unsigned long) uc->uc_mcontext->__ss.__rbp,\n        (unsigned long) uc->uc_mcontext->__ss.__rsp,\n        (unsigned long) uc->uc_mcontext->__ss.__r8,\n        (unsigned long) uc->uc_mcontext->__ss.__r9,\n        (unsigned long) uc->uc_mcontext->__ss.__r10,\n        (unsigned long) uc->uc_mcontext->__ss.__r11,\n        (unsigned long) uc->uc_mcontext->__ss.__r12,\n        (unsigned long) uc->uc_mcontext->__ss.__r13,\n        (unsigned long) uc->uc_mcontext->__ss.__r14,\n        (unsigned long) uc->uc_mcontext->__ss.__r15,\n        (unsigned long) uc->uc_mcontext->__ss.__rip,\n        (unsigned long) uc->uc_mcontext->__ss.__rflags,\n        (unsigned long) uc->uc_mcontext->__ss.__cs,\n        (unsigned long) uc->uc_mcontext->__ss.__fs,\n        (unsigned long) uc->uc_mcontext->__ss.__gs\n    );\n    logStackContent((void**)uc->uc_mcontext->__ss.__rsp);\n    #else\n    /* OSX x86 */\n    serverLog(LL_WARNING,\n    \"\\n\"\n    \"EAX:%08lx EBX:%08lx ECX:%08lx EDX:%08lx\\n\"\n    \"EDI:%08lx ESI:%08lx EBP:%08lx ESP:%08lx\\n\"\n    \"SS:%08lx  EFL:%08lx EIP:%08lx CS :%08lx\\n\"\n    \"DS:%08lx  ES:%08lx  FS :%08lx GS :%08lx\",\n        (unsigned long) uc->uc_mcontext->__ss.__eax,\n        (unsigned long) uc->uc_mcontext->__ss.__ebx,\n        (unsigned long) uc->uc_mcontext->__ss.__ecx,\n        (unsigned long) uc->uc_mcontext->__ss.__edx,\n        (unsigned long) uc->uc_mcontext->__ss.__edi,\n        (unsigned long) uc->uc_mcontext->__ss.__esi,\n        (unsigned long) uc->uc_mcontext->__ss.__ebp,\n        (unsigned long) uc->uc_mcontext->__ss.__esp,\n        (unsigned long) uc->uc_mcontext->__ss.__ss,\n        (unsigned long) uc->uc_mcontext->__ss.__eflags,\n        (unsigned long) uc->uc_mcontext->__ss.__eip,\n        (unsigned long) uc->uc_mcontext->__ss.__cs,\n        (unsigned long) uc->uc_mcontext->__ss.__ds,\n        (unsigned long) uc->uc_mcontext->__ss.__es,\n        (unsigned long) uc->uc_mcontext->__ss.__fs,\n        (unsigned long) uc->uc_mcontext->__ss.__gs\n    );\n    logStackContent((void**)uc->uc_mcontext->__ss.__esp);\n    #endif\n/* Linux */\n#elif defined(__linux__)\n    /* Linux x86 */\n    #if defined(__i386__)\n    serverLog(LL_WARNING,\n    \"\\n\"\n    \"EAX:%08lx EBX:%08lx ECX:%08lx EDX:%08lx\\n\"\n    \"EDI:%08lx ESI:%08lx EBP:%08lx ESP:%08lx\\n\"\n    \"SS :%08lx EFL:%08lx EIP:%08lx CS:%08lx\\n\"\n    \"DS :%08lx ES :%08lx FS :%08lx GS:%08lx\",\n        (unsigned long) uc->uc_mcontext.gregs[11],\n        (unsigned long) uc->uc_mcontext.gregs[8],\n        (unsigned long) uc->uc_mcontext.gregs[10],\n        (unsigned long) uc->uc_mcontext.gregs[9],\n        (unsigned long) uc->uc_mcontext.gregs[4],\n        (unsigned long) uc->uc_mcontext.gregs[5],\n        (unsigned long) uc->uc_mcontext.gregs[6],\n        (unsigned long) uc->uc_mcontext.gregs[7],\n        (unsigned long) uc->uc_mcontext.gregs[18],\n        (unsigned long) uc->uc_mcontext.gregs[17],\n        (unsigned long) uc->uc_mcontext.gregs[14],\n        (unsigned long) uc->uc_mcontext.gregs[15],\n        (unsigned long) uc->uc_mcontext.gregs[3],\n        (unsigned long) uc->uc_mcontext.gregs[2],\n        (unsigned long) uc->uc_mcontext.gregs[1],\n        (unsigned long) uc->uc_mcontext.gregs[0]\n    );\n    logStackContent((void**)uc->uc_mcontext.gregs[7]);\n    #elif defined(__X86_64__) || defined(__x86_64__)\n    /* Linux AMD64 */\n    serverLog(LL_WARNING,\n    \"\\n\"\n    \"RAX:%016lx RBX:%016lx\\nRCX:%016lx RDX:%016lx\\n\"\n    \"RDI:%016lx RSI:%016lx\\nRBP:%016lx RSP:%016lx\\n\"\n    \"R8 :%016lx R9 :%016lx\\nR10:%016lx R11:%016lx\\n\"\n    \"R12:%016lx R13:%016lx\\nR14:%016lx R15:%016lx\\n\"\n    \"RIP:%016lx EFL:%016lx\\nCSGSFS:%016lx\",\n        (unsigned long) uc->uc_mcontext.gregs[13],\n        (unsigned long) uc->uc_mcontext.gregs[11],\n        (unsigned long) uc->uc_mcontext.gregs[14],\n        (unsigned long) uc->uc_mcontext.gregs[12],\n        (unsigned long) uc->uc_mcontext.gregs[8],\n        (unsigned long) uc->uc_mcontext.gregs[9],\n        (unsigned long) uc->uc_mcontext.gregs[10],\n        (unsigned long) uc->uc_mcontext.gregs[15],\n        (unsigned long) uc->uc_mcontext.gregs[0],\n        (unsigned long) uc->uc_mcontext.gregs[1],\n        (unsigned long) uc->uc_mcontext.gregs[2],\n        (unsigned long) uc->uc_mcontext.gregs[3],\n        (unsigned long) uc->uc_mcontext.gregs[4],\n        (unsigned long) uc->uc_mcontext.gregs[5],\n        (unsigned long) uc->uc_mcontext.gregs[6],\n        (unsigned long) uc->uc_mcontext.gregs[7],\n        (unsigned long) uc->uc_mcontext.gregs[16],\n        (unsigned long) uc->uc_mcontext.gregs[17],\n        (unsigned long) uc->uc_mcontext.gregs[18]\n    );\n    logStackContent((void**)uc->uc_mcontext.gregs[15]);\n    #endif\n#else\n    serverLog(LL_WARNING,\n        \"  Dumping of registers not supported for this OS/arch\");\n#endif\n}\n\n/* Return a file descriptor to write directly to the Redis log with the\n * write(2) syscall, that can be used in critical sections of the code\n * where the rest of Redis can't be trusted (for example during the memory\n * test) or when an API call requires a raw fd.\n *\n * Close it with closeDirectLogFiledes(). */\nint openDirectLogFiledes(void) {\n    int log_to_stdout = server.logfile[0] == '\\0';\n    int fd = log_to_stdout ?\n        STDOUT_FILENO :\n        open(server.logfile, O_APPEND|O_CREAT|O_WRONLY, 0644);\n    return fd;\n}\n\n/* Used to close what closeDirectLogFiledes() returns. */\nvoid closeDirectLogFiledes(int fd) {\n    int log_to_stdout = server.logfile[0] == '\\0';\n    if (!log_to_stdout) close(fd);\n}\n\n/* Logs the stack trace using the backtrace() call. This function is designed\n * to be called from signal handlers safely. */\nvoid logStackTrace(ucontext_t *uc) {\n    void *trace[101];\n    int trace_size = 0, fd = openDirectLogFiledes();\n\n    if (fd == -1) return; /* If we can't log there is anything to do. */\n\n    /* Generate the stack trace */\n    trace_size = backtrace(trace+1, 100);\n\n    if (getMcontextEip(uc) != NULL) {\n        char *msg1 = \"EIP:\\n\";\n        char *msg2 = \"\\nBacktrace:\\n\";\n        if (write(fd,msg1,strlen(msg1)) == -1) {/* Avoid warning. */};\n        trace[0] = getMcontextEip(uc);\n        backtrace_symbols_fd(trace, 1, fd);\n        if (write(fd,msg2,strlen(msg2)) == -1) {/* Avoid warning. */};\n    }\n\n    /* Write symbols to log file */\n    backtrace_symbols_fd(trace+1, trace_size, fd);\n\n    /* Cleanup */\n    closeDirectLogFiledes(fd);\n}\n\n/* Log information about the \"current\" client, that is, the client that is\n * currently being served by Redis. May be NULL if Redis is not serving a\n * client right now. */\nvoid logCurrentClient(void) {\n    if (server.current_client == NULL) return;\n\n    client *cc = server.current_client;\n    sds client;\n    int j;\n\n    serverLogRaw(LL_WARNING|LL_RAW, \"\\n------ CURRENT CLIENT INFO ------\\n\");\n    client = catClientInfoString(sdsempty(),cc);\n    serverLog(LL_WARNING|LL_RAW,\"%s\\n\", client);\n    sdsfree(client);\n    for (j = 0; j < cc->argc; j++) {\n        robj *decoded;\n\n        decoded = getDecodedObject(cc->argv[j]);\n        serverLog(LL_WARNING|LL_RAW,\"argv[%d]: '%s'\\n\", j,\n            (char*)decoded->ptr);\n        decrRefCount(decoded);\n    }\n    /* Check if the first argument, usually a key, is found inside the\n     * selected DB, and if so print info about the associated object. */\n    if (cc->argc >= 1) {\n        robj *val, *key;\n        dictEntry *de;\n\n        key = getDecodedObject(cc->argv[1]);\n        de = dictFind(cc->db->dict, key->ptr);\n        if (de) {\n            val = dictGetVal(de);\n            serverLog(LL_WARNING,\"key '%s' found in DB containing the following object:\", (char*)key->ptr);\n            serverLogObjectDebugInfo(val);\n        }\n        decrRefCount(key);\n    }\n}\n\n#if defined(HAVE_PROC_MAPS)\n\n#define MEMTEST_MAX_REGIONS 128\n\n/* A non destructive memory test executed during segfauls. */\nint memtest_test_linux_anonymous_maps(void) {\n    FILE *fp;\n    char line[1024];\n    char logbuf[1024];\n    size_t start_addr, end_addr, size;\n    size_t start_vect[MEMTEST_MAX_REGIONS];\n    size_t size_vect[MEMTEST_MAX_REGIONS];\n    int regions = 0, j;\n\n    int fd = openDirectLogFiledes();\n    if (!fd) return 0;\n\n    fp = fopen(\"/proc/self/maps\",\"r\");\n    if (!fp) return 0;\n    while(fgets(line,sizeof(line),fp) != NULL) {\n        char *start, *end, *p = line;\n\n        start = p;\n        p = strchr(p,'-');\n        if (!p) continue;\n        *p++ = '\\0';\n        end = p;\n        p = strchr(p,' ');\n        if (!p) continue;\n        *p++ = '\\0';\n        if (strstr(p,\"stack\") ||\n            strstr(p,\"vdso\") ||\n            strstr(p,\"vsyscall\")) continue;\n        if (!strstr(p,\"00:00\")) continue;\n        if (!strstr(p,\"rw\")) continue;\n\n        start_addr = strtoul(start,NULL,16);\n        end_addr = strtoul(end,NULL,16);\n        size = end_addr-start_addr;\n\n        start_vect[regions] = start_addr;\n        size_vect[regions] = size;\n        snprintf(logbuf,sizeof(logbuf),\n            \"*** Preparing to test memory region %lx (%lu bytes)\\n\",\n                (unsigned long) start_vect[regions],\n                (unsigned long) size_vect[regions]);\n        if (write(fd,logbuf,strlen(logbuf)) == -1) { /* Nothing to do. */ }\n        regions++;\n    }\n\n    int errors = 0;\n    for (j = 0; j < regions; j++) {\n        if (write(fd,\".\",1) == -1) { /* Nothing to do. */ }\n        errors += memtest_preserving_test((void*)start_vect[j],size_vect[j],1);\n        if (write(fd, errors ? \"E\" : \"O\",1) == -1) { /* Nothing to do. */ }\n    }\n    if (write(fd,\"\\n\",1) == -1) { /* Nothing to do. */ }\n\n    /* NOTE: It is very important to close the file descriptor only now\n     * because closing it before may result into unmapping of some memory\n     * region that we are testing. */\n    fclose(fp);\n    closeDirectLogFiledes(fd);\n    return errors;\n}\n#endif\n\n/* Scans the (assumed) x86 code starting at addr, for a max of `len`\n * bytes, searching for E8 (callq) opcodes, and dumping the symbols\n * and the call offset if they appear to be valid. */\nvoid dumpX86Calls(void *addr, size_t len) {\n    size_t j;\n    unsigned char *p = addr;\n    Dl_info info;\n    /* Hash table to best-effort avoid printing the same symbol\n     * multiple times. */\n    unsigned long ht[256] = {0};\n\n    if (len < 5) return;\n    for (j = 0; j < len-4; j++) {\n        if (p[j] != 0xE8) continue; /* Not an E8 CALL opcode. */\n        unsigned long target = (unsigned long)addr+j+5;\n        target += *((int32_t*)(p+j+1));\n        if (dladdr((void*)target, &info) != 0 && info.dli_sname != NULL) {\n            if (ht[target&0xff] != target) {\n                printf(\"Function at 0x%lx is %s\\n\",target,info.dli_sname);\n                ht[target&0xff] = target;\n            }\n            j += 4; /* Skip the 32 bit immediate. */\n        }\n    }\n}\n\nvoid sigsegvHandler(int sig, siginfo_t *info, void *secret) {\n    ucontext_t *uc = (ucontext_t*) secret;\n    void *eip = getMcontextEip(uc);\n    sds infostring, clients;\n    struct sigaction act;\n    UNUSED(info);\n\n    bugReportStart();\n    serverLog(LL_WARNING,\n        \"Redis %s crashed by signal: %d\", REDIS_VERSION, sig);\n    if (eip != NULL) {\n        serverLog(LL_WARNING,\n        \"Crashed running the instuction at: %p\", eip);\n    }\n    if (sig == SIGSEGV || sig == SIGBUS) {\n        serverLog(LL_WARNING,\n        \"Accessing address: %p\", (void*)info->si_addr);\n    }\n    serverLog(LL_WARNING,\n        \"Failed assertion: %s (%s:%d)\", server.assert_failed,\n                        server.assert_file, server.assert_line);\n\n    /* Log the stack trace */\n    serverLogRaw(LL_WARNING|LL_RAW, \"\\n------ STACK TRACE ------\\n\");\n    logStackTrace(uc);\n\n    /* Log INFO and CLIENT LIST */\n    serverLogRaw(LL_WARNING|LL_RAW, \"\\n------ INFO OUTPUT ------\\n\");\n    infostring = genRedisInfoString(\"all\");\n    infostring = sdscatprintf(infostring, \"hash_init_value: %u\\n\",\n        dictGetHashFunctionSeed());\n    serverLogRaw(LL_WARNING|LL_RAW, infostring);\n    serverLogRaw(LL_WARNING|LL_RAW, \"\\n------ CLIENT LIST OUTPUT ------\\n\");\n    clients = getAllClientsInfoString();\n    serverLogRaw(LL_WARNING|LL_RAW, clients);\n    sdsfree(infostring);\n    sdsfree(clients);\n\n    /* Log the current client */\n    logCurrentClient();\n\n    /* Log dump of processor registers */\n    logRegisters(uc);\n\n#if defined(HAVE_PROC_MAPS)\n    /* Test memory */\n    serverLogRaw(LL_WARNING|LL_RAW, \"\\n------ FAST MEMORY TEST ------\\n\");\n    bioKillThreads();\n    if (memtest_test_linux_anonymous_maps()) {\n        serverLogRaw(LL_WARNING|LL_RAW,\n            \"!!! MEMORY ERROR DETECTED! Check your memory ASAP !!!\\n\");\n    } else {\n        serverLogRaw(LL_WARNING|LL_RAW,\n            \"Fast memory test PASSED, however your memory can still be broken. Please run a memory test for several hours if possible.\\n\");\n    }\n#endif\n\n    if (eip != NULL) {\n        Dl_info info;\n        if (dladdr(eip, &info) != 0) {\n            serverLog(LL_WARNING|LL_RAW,\n                \"\\n------ DUMPING CODE AROUND EIP ------\\n\"\n                \"Symbol: %s (base: %p)\\n\"\n                \"Module: %s (base %p)\\n\"\n                \"$ xxd -r -p /tmp/dump.hex /tmp/dump.bin\\n\"\n                \"$ objdump --adjust-vma=%p -D -b binary -m i386:x86-64 /tmp/dump.bin\\n\"\n                \"------\\n\",\n                info.dli_sname, info.dli_saddr, info.dli_fname, info.dli_fbase,\n                info.dli_saddr);\n            size_t len = (long)eip - (long)info.dli_saddr;\n            unsigned long sz = sysconf(_SC_PAGESIZE);\n            if (len < 1<<13) { /* we don't have functions over 8k (verified) */\n                /* Find the address of the next page, which is our \"safety\"\n                 * limit when dumping. Then try to dump just 128 bytes more\n                 * than EIP if there is room, or stop sooner. */\n                unsigned long next = ((unsigned long)eip + sz) & ~(sz-1);\n                unsigned long end = (unsigned long)eip + 128;\n                if (end > next) end = next;\n                len = end - (unsigned long)info.dli_saddr;\n                serverLogHexDump(LL_WARNING, \"dump of function\",\n                    info.dli_saddr ,len);\n                dumpX86Calls(info.dli_saddr,len);\n            }\n        }\n    }\n\n    serverLogRaw(LL_WARNING|LL_RAW,\n\"\\n=== REDIS BUG REPORT END. Make sure to include from START to END. ===\\n\\n\"\n\"       Please report the crash by opening an issue on github:\\n\\n\"\n\"           http://github.com/antirez/redis/issues\\n\\n\"\n\"  Suspect RAM error? Use redis-server --test-memory to verify it.\\n\\n\"\n);\n\n    /* free(messages); Don't call free() with possibly corrupted memory. */\n    if (server.daemonize && server.supervised == 0) unlink(server.pidfile);\n\n    /* Make sure we exit with the right signal at the end. So for instance\n     * the core will be dumped if enabled. */\n    sigemptyset (&act.sa_mask);\n    act.sa_flags = SA_NODEFER | SA_ONSTACK | SA_RESETHAND;\n    act.sa_handler = SIG_DFL;\n    sigaction (sig, &act, NULL);\n    kill(getpid(),sig);\n}\n#endif /* HAVE_BACKTRACE */\n\n/* ==================== Logging functions for debugging ===================== */\n\nvoid serverLogHexDump(int level, char *descr, void *value, size_t len) {\n    char buf[65], *b;\n    unsigned char *v = value;\n    char charset[] = \"0123456789abcdef\";\n\n    serverLog(level,\"%s (hexdump of %zu bytes):\", descr, len);\n    b = buf;\n    while(len) {\n        b[0] = charset[(*v)>>4];\n        b[1] = charset[(*v)&0xf];\n        b[2] = '\\0';\n        b += 2;\n        len--;\n        v++;\n        if (b-buf == 64 || len == 0) {\n            serverLogRaw(level|LL_RAW,buf);\n            b = buf;\n        }\n    }\n    serverLogRaw(level|LL_RAW,\"\\n\");\n}\n\n/* =========================== Software Watchdog ============================ */\n#include <sys/time.h>\n\nvoid watchdogSignalHandler(int sig, siginfo_t *info, void *secret) {\n#ifdef HAVE_BACKTRACE\n    ucontext_t *uc = (ucontext_t*) secret;\n#endif\n    UNUSED(info);\n    UNUSED(sig);\n\n    serverLogFromHandler(LL_WARNING,\"\\n--- WATCHDOG TIMER EXPIRED ---\");\n#ifdef HAVE_BACKTRACE\n    logStackTrace(uc);\n#else\n    serverLogFromHandler(LL_WARNING,\"Sorry: no support for backtrace().\");\n#endif\n    serverLogFromHandler(LL_WARNING,\"--------\\n\");\n}\n\n/* Schedule a SIGALRM delivery after the specified period in milliseconds.\n * If a timer is already scheduled, this function will re-schedule it to the\n * specified time. If period is 0 the current timer is disabled. */\nvoid watchdogScheduleSignal(int period) {\n    struct itimerval it;\n\n    /* Will stop the timer if period is 0. */\n    it.it_value.tv_sec = period/1000;\n    it.it_value.tv_usec = (period%1000)*1000;\n    /* Don't automatically restart. */\n    it.it_interval.tv_sec = 0;\n    it.it_interval.tv_usec = 0;\n    setitimer(ITIMER_REAL, &it, NULL);\n}\n\n/* Enable the software watchdog with the specified period in milliseconds. */\nvoid enableWatchdog(int period) {\n    int min_period;\n\n    if (server.watchdog_period == 0) {\n        struct sigaction act;\n\n        /* Watchdog was actually disabled, so we have to setup the signal\n         * handler. */\n        sigemptyset(&act.sa_mask);\n        act.sa_flags = SA_ONSTACK | SA_SIGINFO;\n        act.sa_sigaction = watchdogSignalHandler;\n        sigaction(SIGALRM, &act, NULL);\n    }\n    /* If the configured period is smaller than twice the timer period, it is\n     * too short for the software watchdog to work reliably. Fix it now\n     * if needed. */\n    min_period = (1000/server.hz)*2;\n    if (period < min_period) period = min_period;\n    watchdogScheduleSignal(period); /* Adjust the current timer. */\n    server.watchdog_period = period;\n}\n\n/* Disable the software watchdog. */\nvoid disableWatchdog(void) {\n    struct sigaction act;\n    if (server.watchdog_period == 0) return; /* Already disabled. */\n    watchdogScheduleSignal(0); /* Stop the current timer. */\n\n    /* Set the signal handler to SIG_IGN, this will also remove pending\n     * signals from the queue. */\n    sigemptyset(&act.sa_mask);\n    act.sa_flags = 0;\n    act.sa_handler = SIG_IGN;\n    sigaction(SIGALRM, &act, NULL);\n    server.watchdog_period = 0;\n}\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.8/src/dict.h",
    "content": "/* Hash Tables Implementation.\n *\n * This file implements in-memory hash tables with insert/del/replace/find/\n * get-random-element operations. Hash tables will auto-resize if needed\n * tables of power of two in size are used, collisions are handled by\n * chaining. See the source code for more information... :)\n *\n * Copyright (c) 2006-2012, Salvatore Sanfilippo <antirez at gmail dot com>\n * All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions are met:\n *\n *   * Redistributions of source code must retain the above copyright notice,\n *     this list of conditions and the following disclaimer.\n *   * Redistributions in binary form must reproduce the above copyright\n *     notice, this list of conditions and the following disclaimer in the\n *     documentation and/or other materials provided with the distribution.\n *   * Neither the name of Redis nor the names of its contributors may be used\n *     to endorse or promote products derived from this software without\n *     specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\"\n * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\n * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE\n * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR\n * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF\n * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS\n * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN\n * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)\n * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE\n * POSSIBILITY OF SUCH DAMAGE.\n */\n\n#include <stdint.h>\n\n#ifndef __DICT_H\n#define __DICT_H\n\n#define DICT_OK 0\n#define DICT_ERR 1\n\n/* Unused arguments generate annoying warnings... */\n#define DICT_NOTUSED(V) ((void) V)\n\ntypedef struct dictEntry {\n    void *key;\n    union {\n        void *val;\n        uint64_t u64;\n        int64_t s64;\n        double d;\n    } v;\n    struct dictEntry *next;\n} dictEntry;\n\ntypedef struct dictType {\n    unsigned int (*hashFunction)(const void *key);\n    void *(*keyDup)(void *privdata, const void *key);\n    void *(*valDup)(void *privdata, const void *obj);\n    int (*keyCompare)(void *privdata, const void *key1, const void *key2);\n    void (*keyDestructor)(void *privdata, void *key);\n    void (*valDestructor)(void *privdata, void *obj);\n} dictType;\n\n/* This is our hash table structure. Every dictionary has two of this as we\n * implement incremental rehashing, for the old to the new table. */\ntypedef struct dictht {\n    dictEntry **table;\n    unsigned long size;\n    unsigned long sizemask;\n    unsigned long used;\n} dictht;\n\ntypedef struct dict {\n    dictType *type;\n    void *privdata;\n    dictht ht[2];\n    long rehashidx; /* rehashing not in progress if rehashidx == -1 */\n    int iterators; /* number of iterators currently running */\n} dict;\n\n/* If safe is set to 1 this is a safe iterator, that means, you can call\n * dictAdd, dictFind, and other functions against the dictionary even while\n * iterating. Otherwise it is a non safe iterator, and only dictNext()\n * should be called while iterating. */\ntypedef struct dictIterator {\n    dict *d;\n    long index;\n    int table, safe;\n    dictEntry *entry, *nextEntry;\n    /* unsafe iterator fingerprint for misuse detection. */\n    long long fingerprint;\n} dictIterator;\n\ntypedef void (dictScanFunction)(void *privdata, const dictEntry *de);\n\n/* This is the initial size of every hash table */\n#define DICT_HT_INITIAL_SIZE     4\n\n/* ------------------------------- Macros ------------------------------------*/\n#define dictFreeVal(d, entry) \\\n    if ((d)->type->valDestructor) \\\n        (d)->type->valDestructor((d)->privdata, (entry)->v.val)\n\n#define dictSetVal(d, entry, _val_) do { \\\n    if ((d)->type->valDup) \\\n        entry->v.val = (d)->type->valDup((d)->privdata, _val_); \\\n    else \\\n        entry->v.val = (_val_); \\\n} while(0)\n\n#define dictSetSignedIntegerVal(entry, _val_) \\\n    do { entry->v.s64 = _val_; } while(0)\n\n#define dictSetUnsignedIntegerVal(entry, _val_) \\\n    do { entry->v.u64 = _val_; } while(0)\n\n#define dictSetDoubleVal(entry, _val_) \\\n    do { entry->v.d = _val_; } while(0)\n\n#define dictFreeKey(d, entry) \\\n    if ((d)->type->keyDestructor) \\\n        (d)->type->keyDestructor((d)->privdata, (entry)->key)\n\n#define dictSetKey(d, entry, _key_) do { \\\n    if ((d)->type->keyDup) \\\n        entry->key = (d)->type->keyDup((d)->privdata, _key_); \\\n    else \\\n        entry->key = (_key_); \\\n} while(0)\n\n#define dictCompareKeys(d, key1, key2) \\\n    (((d)->type->keyCompare) ? \\\n        (d)->type->keyCompare((d)->privdata, key1, key2) : \\\n        (key1) == (key2))\n\n#define dictHashKey(d, key) (d)->type->hashFunction(key)\n#define dictGetKey(he) ((he)->key)\n#define dictGetVal(he) ((he)->v.val)\n#define dictGetSignedIntegerVal(he) ((he)->v.s64)\n#define dictGetUnsignedIntegerVal(he) ((he)->v.u64)\n#define dictGetDoubleVal(he) ((he)->v.d)\n#define dictSlots(d) ((d)->ht[0].size+(d)->ht[1].size)\n#define dictSize(d) ((d)->ht[0].used+(d)->ht[1].used)\n#define dictIsRehashing(d) ((d)->rehashidx != -1)\n\n/* API */\ndict *dictCreate(dictType *type, void *privDataPtr);\nint dictExpand(dict *d, unsigned long size);\nint dictAdd(dict *d, void *key, void *val);\ndictEntry *dictAddRaw(dict *d, void *key);\nint dictReplace(dict *d, void *key, void *val);\ndictEntry *dictReplaceRaw(dict *d, void *key);\nint dictDelete(dict *d, const void *key);\nint dictDeleteNoFree(dict *d, const void *key);\nvoid dictRelease(dict *d);\ndictEntry * dictFind(dict *d, const void *key);\nvoid *dictFetchValue(dict *d, const void *key);\nint dictResize(dict *d);\ndictIterator *dictGetIterator(dict *d);\ndictIterator *dictGetSafeIterator(dict *d);\ndictEntry *dictNext(dictIterator *iter);\nvoid dictReleaseIterator(dictIterator *iter);\ndictEntry *dictGetRandomKey(dict *d);\nunsigned int dictGetSomeKeys(dict *d, dictEntry **des, unsigned int count);\nvoid dictGetStats(char *buf, size_t bufsize, dict *d);\nunsigned int dictGenHashFunction(const void *key, int len);\nunsigned int dictGenCaseHashFunction(const unsigned char *buf, int len);\nvoid dictEmpty(dict *d, void(callback)(void*));\nvoid dictEnableResize(void);\nvoid dictDisableResize(void);\nint dictRehash(dict *d, int n);\nint dictRehashMilliseconds(dict *d, int ms);\nvoid dictSetHashFunctionSeed(unsigned int initval);\nunsigned int dictGetHashFunctionSeed(void);\nunsigned long dictScan(dict *d, unsigned long v, dictScanFunction *fn, void *privdata);\n\n/* Hash table types */\nextern dictType dictTypeHeapStringCopyKey;\nextern dictType dictTypeHeapStrings;\nextern dictType dictTypeHeapStringCopyKeyValue;\n\n#endif /* __DICT_H */\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.8/src/endianconv.c",
    "content": "/* endinconv.c -- Endian conversions utilities.\n *\n * This functions are never called directly, but always using the macros\n * defined into endianconv.h, this way we define everything is a non-operation\n * if the arch is already little endian.\n *\n * Redis tries to encode everything as little endian (but a few things that need\n * to be backward compatible are still in big endian) because most of the\n * production environments are little endian, and we have a lot of conversions\n * in a few places because ziplists, intsets, zipmaps, need to be endian-neutral\n * even in memory, since they are serialied on RDB files directly with a single\n * write(2) without other additional steps.\n *\n * ----------------------------------------------------------------------------\n *\n * Copyright (c) 2011-2012, Salvatore Sanfilippo <antirez at gmail dot com>\n * All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions are met:\n *\n *   * Redistributions of source code must retain the above copyright notice,\n *     this list of conditions and the following disclaimer.\n *   * Redistributions in binary form must reproduce the above copyright\n *     notice, this list of conditions and the following disclaimer in the\n *     documentation and/or other materials provided with the distribution.\n *   * Neither the name of Redis nor the names of its contributors may be used\n *     to endorse or promote products derived from this software without\n *     specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\"\n * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\n * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE\n * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR\n * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF\n * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS\n * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN\n * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)\n * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE\n * POSSIBILITY OF SUCH DAMAGE.\n */\n\n\n#include <stdint.h>\n\n/* Toggle the 16 bit unsigned integer pointed by *p from little endian to\n * big endian */\nvoid memrev16(void *p) {\n    unsigned char *x = p, t;\n\n    t = x[0];\n    x[0] = x[1];\n    x[1] = t;\n}\n\n/* Toggle the 32 bit unsigned integer pointed by *p from little endian to\n * big endian */\nvoid memrev32(void *p) {\n    unsigned char *x = p, t;\n\n    t = x[0];\n    x[0] = x[3];\n    x[3] = t;\n    t = x[1];\n    x[1] = x[2];\n    x[2] = t;\n}\n\n/* Toggle the 64 bit unsigned integer pointed by *p from little endian to\n * big endian */\nvoid memrev64(void *p) {\n    unsigned char *x = p, t;\n\n    t = x[0];\n    x[0] = x[7];\n    x[7] = t;\n    t = x[1];\n    x[1] = x[6];\n    x[6] = t;\n    t = x[2];\n    x[2] = x[5];\n    x[5] = t;\n    t = x[3];\n    x[3] = x[4];\n    x[4] = t;\n}\n\nuint16_t intrev16(uint16_t v) {\n    memrev16(&v);\n    return v;\n}\n\nuint32_t intrev32(uint32_t v) {\n    memrev32(&v);\n    return v;\n}\n\nuint64_t intrev64(uint64_t v) {\n    memrev64(&v);\n    return v;\n}\n\n#ifdef REDIS_TEST\n#include <stdio.h>\n\n#define UNUSED(x) (void)(x)\nint endianconvTest(int argc, char *argv[]) {\n    char buf[32];\n\n    UNUSED(argc);\n    UNUSED(argv);\n\n    sprintf(buf,\"ciaoroma\");\n    memrev16(buf);\n    printf(\"%s\\n\", buf);\n\n    sprintf(buf,\"ciaoroma\");\n    memrev32(buf);\n    printf(\"%s\\n\", buf);\n\n    sprintf(buf,\"ciaoroma\");\n    memrev64(buf);\n    printf(\"%s\\n\", buf);\n\n    return 0;\n}\n#endif\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.8/src/fmacros.h",
    "content": "/*\n * Copyright (c) 2009-2012, Salvatore Sanfilippo <antirez at gmail dot com>\n * All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions are met:\n *\n *   * Redistributions of source code must retain the above copyright notice,\n *     this list of conditions and the following disclaimer.\n *   * Redistributions in binary form must reproduce the above copyright\n *     notice, this list of conditions and the following disclaimer in the\n *     documentation and/or other materials provided with the distribution.\n *   * Neither the name of Redis nor the names of its contributors may be used\n *     to endorse or promote products derived from this software without\n *     specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\"\n * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\n * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE\n * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR\n * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF\n * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS\n * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN\n * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)\n * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE\n * POSSIBILITY OF SUCH DAMAGE.\n */\n\n#ifndef _REDIS_FMACRO_H\n#define _REDIS_FMACRO_H\n\n#define _BSD_SOURCE\n\n#if defined(__linux__)\n#define _GNU_SOURCE\n#define _DEFAULT_SOURCE\n#endif\n\n#if defined(_AIX)\n#define _ALL_SOURCE\n#endif\n\n#if defined(__linux__) || defined(__OpenBSD__)\n#define _XOPEN_SOURCE 700\n/*\n * On NetBSD, _XOPEN_SOURCE undefines _NETBSD_SOURCE and\n * thus hides inet_aton etc.\n */\n#elif !defined(__NetBSD__)\n#define _XOPEN_SOURCE\n#endif\n\n#if defined(__sun)\n#define _POSIX_C_SOURCE 199506L\n#endif\n\n#define _LARGEFILE_SOURCE\n#define _FILE_OFFSET_BITS 64\n\n#endif\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.8/src/geo.h",
    "content": "#ifndef __GEO_H__\n#define __GEO_H__\n\n#include \"server.h\"\n\n/* Structures used inside geo.c in order to represent points and array of\n * points on the earth. */\ntypedef struct geoPoint {\n    double longitude;\n    double latitude;\n    double dist;\n    double score;\n    char *member;\n} geoPoint;\n\ntypedef struct geoArray {\n    struct geoPoint *array;\n    size_t buckets;\n    size_t used;\n} geoArray;\n\n#endif\n"
  },
  {
    "path": "extern/deprecated/redis-3.2.8/src/hyperloglog.c",
    "content": "/* hyperloglog.c - Redis HyperLogLog probabilistic cardinality approximation.\n * This file implements the algorithm and the exported Redis commands.\n *\n * Copyright (c) 2014, Salvatore Sanfilippo <antirez at gmail dot com>\n * All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions are met:\n *\n *   * Redistributions of source code must retain the above copyright notice,\n *     this list of conditions and the following disclaimer.\n *   * Redistributions in binary form must reproduce the above copyright\n *     notice, this list of conditions and the following disclaimer in the\n *     documentation and/or other materials provided with the distribution.\n *   * Neither the name of Redis nor the names of its contributors may be used\n *     to endorse or promote products derived from this software without\n *     specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\"\n * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\n * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE\n * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR\n * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF\n * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS\n * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN\n * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)\n * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE\n * POSSIBILITY OF SUCH DAMAGE.\n */\n\n#include \"server.h\"\n\n#include <stdint.h>\n#include <math.h>\n\n/* The Redis HyperLogLog implementation is based on the following ideas:\n *\n * * The use of a 64 bit hash function as proposed in [1], in order to don't\n *   limited to cardinalities up to 10^9, at the cost of just 1 additional\n *   bit per register.\n * * The use of 16384 6-bit registers for a great level of accuracy, using\n *   a total of 12k per key.\n * * The use of the Redis string data type. No new type is introduced.\n * * No attempt is made to compress the data structure as in [1]. Also the\n *   algorithm used is the original HyperLogLog Algorithm as in [2], with\n *   the only difference that a 64 bit hash function is used, so no correction\n *   is performed for values near 2^32 as in [1].\n *\n * [1] Heule, Nunkesser, Hall: HyperLogLog in Practice: Algorithmic\n *     Engineering of a State of The Art Cardinality Estimation Algorithm.\n *\n * [2] P. Flajolet, Éric Fusy, O. Gandouet, and F. Meunier. Hyperloglog: The\n *     analysis of a near-optimal cardinality estimation algorithm.\n *\n * Redis uses two representations:\n *\n * 1) A \"dense\" representation where every entry is represented by\n *    a 6-bit integer.\n * 2) A \"sparse\" representation using run length compression suitable\n *    for representing HyperLogLogs with many registers set to 0 in\n *    a memory efficient way.\n *\n *\n * HLL header\n * ===\n *\n * Both the dense and sparse representation have a 16 byte header as follows:\n *\n * +------+---+-----+----------+\n * | HYLL | E | N/U | Cardin.  |\n * +------+---+-----+----------+\n *\n * The first 4 bytes are a magic string set to the bytes \"HYLL\".\n * \"E\" is one byte encoding, currently set to HLL_DENSE or\n * HLL_SPARSE. N/U are three not used bytes.\n *\n * The \"Cardin.\" field is a 64 bit integer stored in little endian format\n * with the latest cardinality computed that can be reused if the data\n * structure was not modified since the last computation (this is useful\n * because there are high probabilities that HLLADD operations don't\n * modify the actual data structure and hence the approximated cardinality).\n *\n * When the most significant bit in the most significant byte of the cached\n * cardinality is set, it means that the data structure was modified and\n * we can't reuse the cached value that must be recomputed.\n *\n * Dense representation\n * ===\n *\n * The dense representation used by Redis is the following:\n *\n * +--------+--------+--------+------//      //--+\n * |11000000|22221111|33333322|55444444 ....     |\n * +--------+--------+--------+------//      //--+\n *\n * The 6 bits counters are encoded one after the other starting from the\n * LSB to the MSB, and using the next bytes as needed.\n *\n * Sparse representation\n * ===\n *\n * The sparse representation encodes registers using a run length\n * encoding composed of three opcodes, two using one byte, and one using\n * of two bytes. The opcodes are called ZERO, XZERO and VAL.\n *\n * ZERO opcode is represented as 00xxxxxx. The 6-bit integer represented\n * by the six bits 'xxxxxx', plus 1, means that there are N registers set\n * to 0. This opcode can represent from 1 to 64 contiguous registers set\n * to the value of 0.\n *\n * XZERO opcode is represented by two bytes 01xxxxxx yyyyyyyy. The 14-bit\n * integer represented by the bits 'xxxxxx' as most significant bits and\n * 'yyyyyyyy' as least significant bits, plus 1, means that there are N\n * registers set to 0. This opcode can represent from 0 to 16384 contiguous\n * registers set to the value of 0.\n *\n * VAL opcode is represented as 1vvvvvxx. It contains a 5-bit integer\n * representing the value of a register, and a 2-bit integer representing\n * the number of contiguous registers set to that value 'vvvvv'.\n * To obtain the value and run length, the integers vvvvv and xx must be\n * incremented by one. This opcode can represent values from 1 to 32,\n * repeated from 1 to 4 times.\n *\n * The sparse representation can't represent registers with a value greater\n * than 32, however it is very unlikely that we find such a register in an\n * HLL with a cardinality where the sparse representation is still more\n * memory efficient than the dense representation. When this happens the\n * HLL is converted to the dense representation.\n *\n * The sparse representation is purely positional. For example a sparse\n * representation of an empty HLL is just: XZERO:16384.\n *\n * An HLL having only 3 non-zero registers at position 1000, 1020, 1021\n * respectively set to 2, 3, 3, is represented by the following three\n * opcodes:\n *\n * XZERO:1000 (Registers 0-999 are set to 0)\n * VAL:2,1    (1 register set to value 2, that is register 1000)\n * ZERO:19    (Registers 1001-1019 set to 0)\n * VAL:3,2    (2 registers set to value 3, that is registers 1020,1021)\n * XZERO:15362 (Registers 1022-16383 set to 0)\n *\n * In the example the sparse representation used just 7 bytes instead\n * of 12k in order to represent the HLL registers. In general for low\n * cardinality there is a big win in terms of space efficiency, traded\n * with CPU time since the sparse representation is slower to access:\n *\n * The following table shows average cardinality vs bytes used, 100\n * samples per cardinality (when the set was not representable because\n * of registers with too big value, the dense representation size was used\n * as a sample).\n *\n * 100 267\n * 200 485\n * 300 678\n * 400 859\n * 500 1033\n * 600 1205\n * 700 1375\n * 800 1544\n * 900 1713\n * 1000 1882\n * 2000 3480\n * 3000 4879\n * 4000 6089\n * 5000 7138\n * 6000 8042\n * 7000 8823\n * 8000 9500\n * 9000 10088\n * 10000 10591\n *\n * The dense representation uses 12288 bytes, so there is a big win up to\n * a cardinality of ~2000-3000. For bigger cardinalities the constant times\n * involved in updating the sparse representation is not justified by the\n * memory savings. The exact maximum length of the sparse representation\n * when this implementation switches to the dense representation is\n * configured via the define server.hll_sparse_max_bytes.\n */\n\nstruct hllhdr {\n    char magic[4];      /* \"HYLL\" */\n    uint8_t encoding;   /* HLL_DENSE or HLL_SPARSE. */\n    uint8_t notused[3]; /* Reserved for future use, must be zero. */\n    uint8_t card[8];    /* Cached cardinality, little endian. */\n    uint8_t registers[]; /* Data bytes. */\n};\n\n/* The cached cardinality MSB is used to signal validity of the cached value. */\n#define HLL_INVALIDATE_CACHE(hdr) (hdr)->card[7] |= (1<<7)\n#define HLL_VALID_CACHE(hdr) (((hdr)->card[7] & (1<<7)) == 0)\n\n#define HLL_P 14 /* The greater is P, the smaller the error. */\n#define HLL_REGISTERS (1<<HLL_P) /* With P=14, 16384 registers. */\n#define HLL_P_MASK (HLL_REGISTERS-1) /* Mask to index register. */\n#define HLL_BITS 6 /* Enough to count up to 63 leading zeroes. */\n#define HLL_REGISTER_MAX ((1<<HLL_BITS)-1)\n#define HLL_HDR_SIZE sizeof(struct hllhdr)\n#define HLL_DENSE_SIZE (HLL_HDR_SIZE+((HLL_REGISTERS*HLL_BITS+7)/8))\n#define HLL_DENSE 0 /* Dense encoding. */\n#define HLL_SPARSE 1 /* Sparse encoding. */\n#define HLL_RAW 255 /* Only used internally, never exposed. */\n#define HLL_MAX_ENCODING 1\n\nstatic char *invalid_hll_err = \"-INVALIDOBJ Corrupted HLL object detected\\r\\n\";\n\n/* =========================== Low level bit macros ========================= */\n\n/* Macros to access the dense representation.\n *\n * We need to get and set 6 bit counters in an array of 8 bit bytes.\n * We use macros to make sure the code is inlined since speed is critical\n * especially in order to compute the approximated cardinality in\n * HLLCOUNT where we need to access all the registers at once.\n * For the same reason we also want to avoid conditionals in this code path.\n *\n * +--------+--------+--------+------//\n * |11000000|22221111|33333322|55444444\n * +--------+--------+--------+------//\n *\n * Note: in the above representation the most significant bit (MSB)\n * of every byte is on the left. We start using bits from the LSB to MSB,\n * and so forth passing to the next byte.\n *\n * Example, we want to access to counter at pos = 1 (\"111111\" in the\n * illustration above).\n *\n * The index of the first byte b0 containing our data is:\n *\n *  b0 = 6 * pos / 8 = 0\n *\n *   +--------+\n *   |11000000|  <- Our byte at b0\n *   +--------+\n *\n * The position of the first bit (counting from the LSB = 0) in the byte\n * is given by:\n *\n *  fb = 6 * pos % 8 -> 6\n *\n * Right shift b0 of 'fb' bits.\n *\n *   +--------+\n *   |11000000|  <- Initial value of b0\n *   |00000011|  <- After right shift of 6 pos.\n *   +--------+\n *\n * Left shift b1 of bits 8-fb bits (2 bits)\n *\n *   +--------+\n *   |22221111|  <- Initial value of b1\n *   |22111100|  <- After left shift of 2 bits.\n *   +--------+\n *\n * OR the two bits, and finally AND with 111111 (63 in decimal) to\n * clean the higher order bits we are not interested in:\n *\n *   +--------+\n *   |00000011|  <- b0 right shifted\n *   |22111100|  <- b1 left shifted\n *   |22111111|  <- b0 OR b1\n *   |  111111|  <- (b0 OR b1) AND 63, our value.\n *   +--------+\n *\n * We can try with a different example, like pos = 0. In this case\n * the 6-bit counter is actually contained in a single byte.\n *\n *  b0 = 6 * pos / 8 = 0\n *\n *   +--------+\n *   |11000000|  <- Our byte at b0\n *   +--------+\n *\n *  fb = 6 * pos % 8 = 0\n *\n *  So we right shift of 0 bits (no shift in practice) and\n *  left shift the next byte of 8 bits, even if we don't use it,\n *  but this has the effect of clearing the bits so the result\n *  will not be affacted after the OR.\n *\n * -------------------------------------------------------------------------\n *\n * Setting the register is a bit more complex, let's assume that 'val'\n * is the value we want to set, already in the right range.\n *\n * We need two steps, in one we need to clear the bits, and in the other\n * we need to bitwise-OR the new bits.\n *\n * Let's try with 'pos' = 1, so our first byte at 'b' is 0,\n *\n * \"fb\" is 6 in this case.\n *\n *   +--------+\n *   |11000000|  <- Our byte at b0\n *   +--------+\n *\n * To create a AND-mask to clear the bits about this position, we just\n * initialize the mask with the value 63, left shift it of \"fs\" bits,\n * and finally invert the result.\n *\n *   +--------+\n *   |00111111|  <- \"mask\" starts at 63\n *   |11000000|  <- \"mask\" after left shift of \"ls\" bits.\n *   |00111111|  <- \"mask\" after invert.\n *   +--------+\n *\n * Now we can bitwise-AND the byte at \"b\" with the mask, and bitwise-OR\n * it with \"val\" left-shifted of \"ls\" bits to set the new bits.\n *\n * Now let's focus on the next byte b1:\n *\n *   +--------+\n *   |22221111|  <- Initial value of b1\n *   +--------+\n *\n * To build the AND mask we start again with the 63 value, right shift\n * it by 8-fb bits, and invert it.\n *\n *   +--------+\n *   |00111111|  <- \"mask\" set at 2&6-1\n *   |00001111|  <- \"mask\" after the right shift by 8-fb = 2 bits\n *   |11110000|  <- \"mask\" after bitwise not.\n *   +--------+\n *\n * Now we can mask it with b+1 to clear the old bits, and bitwise-OR\n * with \"val\" left-shifted by \"rs\" bits to set the new value.\n */\n\n/* Note: if we access the last counter, we will also access the b+1 byte\n * that is out of the array, but sds strings always have an implicit null\n * term, so the byte exists, and we can skip the conditional (or the need\n * to allocate 1 byte more explicitly). */\n\n/* Store the value of the register at position 'regnum' into variable 'target'.\n * 'p' is an array of unsigned bytes. */\n#define HLL_DENSE_GET_REGISTER(target,p,regnum) do { \\\n    uint8_t *_p = (uint8_t*) p; \\\n    unsigned long _byte = regnum*HLL_BITS/8; \\\n    unsigned long _fb = regnum*HLL_BITS&7; \\\n    unsigned long _fb8 = 8 - _fb; \\\n    unsigned long b0 = _p[_byte]; \\\n    unsigned long b1 = _p[_byte+1]; \\\n    target = ((b0 >> _fb) | (b1 << _fb8)) & HLL_REGISTER_MAX; \\\n} while(0)\n\n/* Set the value of the register at position 'regnum' to 'val'.\n * 'p' is an array of unsigned bytes. */\n#define HLL_DENSE_SET_REGISTER(p,regnum,val) do { \\\n    uint8_t *_p = (uint8_t*) p; \\\n    unsigned long _byte = regnum*HLL_BITS/8; \\\n    unsigned long _fb = regnum*HLL_BITS&7; \\\n    unsigned long _fb8 = 8 - _fb; \\\n    unsigned long _v = val; \\\n    _p[_byte] &= ~(HLL_REGISTER_MAX << _fb); \\\n    _p[_byte] |= _v << _fb; \\\n    _p[_byte+1] &= ~(HLL_REGISTER_MAX >> _fb8); \\\n    _p[_byte+1] |= _v >> _fb8; \\\n} while(0)\n\n/* Macros to access the sparse representation.\n * The macros parameter is expected to be an uint8_t pointer. */\n#define HLL_SPARSE_XZERO_BIT 0x40 /* 01xxxxxx */\n#define HLL_SPARSE_VAL_BIT 0x80 /* 1vvvvvxx */\n#define HLL_SPARSE_IS_ZERO(p) (((*(p)) & 0xc0) == 0) /* 00xxxxxx */\n#define HLL_SPARSE_IS_XZERO(p) (((*(p)) & 0xc0) == HLL_SPARSE_XZERO_BIT)\n#define HLL_SPARSE_IS_VAL(p) ((*(p)) & HLL_SPARSE_VAL_BIT)\n#define HLL_SPARSE_ZERO_LEN(p) (((*(p)) & 0x3f)+1)\n#define HLL_SPARSE_XZERO_LEN(p) (((((*(p)) & 0x3f) << 8) | (*((p)+1)))+1)\n#define HLL_SPARSE_VAL_VALUE(p) ((((*(p)) >> 2) & 0x1f)+1)\n#define HLL_SPARSE_VAL_LEN(p) (((*(p)) & 0x3)+1)\n#define HLL_SPARSE_VAL_MAX_VALUE 32\n#define HLL_SPARSE_VAL_MAX_LEN 4\n#define HLL_SPARSE_ZERO_MAX_LEN 64\n#define HLL_SPARSE_XZERO_MAX_LEN 16384\n#define HLL_SPARSE_VAL_SET(p,val,len) do { \\\n    *(p) = (((val)-1)<<2|((len)-1))|HLL_SPARSE_VAL_BIT; \\\n} while(0)\n#define HLL_SPARSE_ZERO_SET(p,len) do { \\\n    *(p) = (len)-1; \\\n} while(0)\n#define HLL_SPARSE_XZERO_SET(p,len) do { \\\n    int _l = (len)-1; \\\n    *(p) = (_l>>8) | HLL_SPARSE_XZERO_BIT; \\\n    *((p)+1) = (_l&0xff); \\\n} while(0)\n\n/* ========================= HyperLogLog algorithm  ========================= */\n\n/* Our hash function is MurmurHash2, 64 bit version.\n * It was modified for Redis in order to provide the same result in\n * big and little endian archs (endian neutral). */\nuint64_t MurmurHash64A (const void * key, int len, unsigned int seed) {\n    const uint64_t m = 0xc6a4a7935bd1e995;\n    const int r = 47;\n    uint64_t h = seed ^ (len * m);\n    const uint8_t *data = (const uint8_t *)key;\n    const uint8_t *end = data + (len-(len&7));\n\n    while(data != end) {\n        uint64_t k;\n\n#if (BYTE_ORDER == LITTLE_ENDIAN)\n        k = *((uint64_t*)data);\n#else\n        k = (uint64_t) data[0];\n        k |= (uint64_t) data[1] << 8;\n        k |= (uint64_t) data[2] << 16;\n        k |= (uint64_t) data[3] << 24;\n        k |= (uint64_t) data[4] << 32;\n        k |= (uint64_t) data[5] << 40;\n        k |= (uint64_t) data[6] << 48;\n        k |= (uint64_t) data[7] << 56;\n#endif\n\n        k *= m;\n        k ^= k >> r;\n        k *= m;\n        h ^= k;\n        h *= m;\n        data += 8;\n    }\n\n    switch(len & 7) {\n    case 7: h ^= (uint64_t)data[6] << 48;\n    case 6: h ^= (uint64_t)data[5] << 40;\n    case 5: h ^= (uint64_t)data[4] << 32;\n    case 4: h ^= (uint64_t)data[3] << 24;\n    case 3: h ^= (uint64_t)data[2] << 16;\n    case 2: h ^= (uint64_t)data[1] << 8;\n    case 1: h ^= (uint64_t)data[0];\n            h *= m;\n    };\n\n    h ^= h >> r;\n    h *= m;\n    h ^= h >> r;\n    return h;\n}\n\n/* Given a string element to add to the HyperLogLog, returns the length\n * of the pattern 000..1 of the element hash. As a side effect 'regp' is\n * set to the register index this element hashes to. */\nint hllPatLen(unsigned char *ele, size_t elesize, long *regp) {\n    uint64_t hash, bit, index;\n    int count;\n\n    /* Count the number of zeroes starting from bit HLL_REGISTERS\n     * (that is a power of two corresponding to the first bit we don't use\n     * as index). The max run can be 64-P+1 bits.\n     *\n     * Note that the final \"1\" ending the sequence of zeroes must be\n     * included in the count, so if we find \"001\" the count is 3, and\n     * the smallest count possible is no zeroes at all, just a 1 bit\n     * at the first position, that is a count of 1.\n     *\n     * This may sound like inefficient, but actually in the average case\n     * there are high probabilities to find a 1 after a few iterations. */\n    hash = MurmurHash64A(ele,elesize,0xadc83b19ULL);\n    index = hash & HLL_P_MASK; /* Register index. */\n    hash |= ((uint64_t)1<<63); /* Make sure the loop terminates. */\n    bit = HLL_REGISTERS; /* First bit not used to address the register. */\n    count = 1; /* Initialized to 1 since we count the \"00000...1\" pattern. */\n    while((hash & bit) == 0) {\n        count++;\n        bit <<= 1;\n    }\n    *regp = (int) index;\n    return count;\n}\n\n/* ================== Dense representation implementation  ================== */\n\n/* \"Add\" the element in the dense hyperloglog data structure.\n * Actually nothing is added, but the max 0 pattern counter of the subset\n * the element belongs to is incremented if needed.\n *\n * 'registers' is expected to have room for HLL_REGISTERS plus an\n * additional byte on the right. This requirement is met by sds strings\n * automatically since they are implicitly null terminated.\n *\n * The function always succeed, however if as a result of the operation\n * the approximated cardinality changed, 1 is returned. Otherwise 0\n * is returned. */\nint hllDenseAdd(uint8_t *registers, unsigned char *ele, size_t elesize) {\n    uint8_t oldcount, count;\n    long index;\n\n    /* Update the register if this element produced a longer run of zeroes. */\n    count = hllPatLen(ele,elesize,&index);\n    HLL_DENSE_GET_REGISTER(oldcount,registers,index);\n    if (count > oldcount) {\n        HLL_DENSE_SET_REGISTER(registers,index,count);\n        return 1;\n    } else {\n        return 0;\n    }\n}\n\n/* Compute SUM(2^-reg) in the dense representation.\n * PE is an array with a pre-computer table of values 2^-reg indexed by reg.\n * As a side effect the integer pointed by 'ezp' is set to the number\n * of zero registers. */\ndouble hllDenseSum(uint8_t *registers, double *PE, int *ezp) {\n    double E = 0;\n    int j, ez = 0;\n\n    /* Redis default is to use 16384 registers 6 bits each. The code works\n     * with other values by modifying the defines, but for our target value\n     * we take a faster path with unrolled loops. */\n    if (HLL_REGISTERS == 16384 && HLL_BITS == 6) {\n        uint8_t *r = registers;\n        unsigned long r0, r1, r2, r3, r4, r5, r6, r7, r8, r9,\n                      r10, r11, r12, r13, r14, r15;\n        for (j = 0; j < 1024; j++) {\n            /* Handle 16 registers per iteration. */\n            r0 = r[0] & 63; if (r0 == 0) ez++;\n            r1 = (r[0] >> 6 | r[1] << 2) & 63; if (r1 == 0) ez++;\n            r2 = (r[1] >> 4 | r[2] << 4) & 63; if (r2 == 0) ez++;\n            r3 = (r[2] >> 2) & 63; if (r3 == 0) ez++;\n            r4 = r[3] & 63; if (r4 == 0) ez++;\n            r5 = (r[3] >> 6 | r[4] << 2) & 63; if (r5 == 0) ez++;\n            r6 = (r[4] >> 4 | r[5] << 4) & 63; if (r6 == 0) ez++;\n            r7 = (r[5] >> 2) & 63; if (r7 == 0) ez++;\n            r8 = r[6] & 63; if (r8 == 0) ez++;\n            r9 = (r[6] >> 6 | r[7] << 2) & 63; if (r9 == 0) ez++;\n            r10 = (r[7] >> 4 | r[8] << 4) & 63; if (r10 == 0) ez++;\n            r11 = (r[8] >> 2) & 63; if (r11 == 0) ez++;\n            r12 = r[9] & 63; if (r12 == 0) ez++;\n            r13 = (r[9] >> 6 | r[10] << 2) & 63; if (r13 == 0) ez++;\n            r14 = (r[10] >> 4 | r[11] << 4) & 63; if (r14 == 0) ez++;\n            r15 = (r[11] >> 2) & 63; if (r15 == 0) ez++;\n\n            /* Additional parens will allow the compiler to optimize the\n             * code more with a loss of precision that is not very relevant\n             * here (floating point math is not commutative!). */\n            E += (PE[r0] + PE[r1]) + (PE[r2] + PE[r3]) + (PE[r4] + PE[r5]) +\n                 (PE[r6] + PE[r7]) + (PE[r8] + PE[r9]) + (PE[r10] + PE[r11]) +\n                 (PE[r12] + PE[r13]) + (PE[r14] + PE[r15]);\n            r += 12;\n        }\n    } else {\n        for (j = 0; j < HLL_REGISTERS; j++) {\n            unsigned long reg;\n\n            HLL_DENSE_GET_REGISTER(reg,registers,j);\n            if (reg == 0) {\n                ez++;\n                /* Increment E at the end of the loop. */\n            } else {\n                E += PE[reg]; /* Precomputed 2^(-reg[j]). */\n            }\n        }\n        E += ez; /* Add 2^0 'ez' times. */\n    }\n    *ezp = ez;\n    return E;\n}\n\n/* ================== Sparse representation implementation  ================= */\n\n/* Convert the HLL with sparse representation given as input in its dense\n * representation. Both representations are represented by SDS strings, and\n * the input representation is freed as a side effect.\n *\n * The function returns C_OK if the sparse representation was valid,\n * otherwise C_ERR is returned if the representation was corrupted. */\nint hllSparseToDense(robj *o) {\n    sds sparse = o->ptr, dense;\n    struct hllhdr *hdr, *oldhdr = (struct hllhdr*)sparse;\n    int idx = 0, runlen, regval;\n    uint8_t *p = (uint8_t*)sparse, *end = p+sdslen(sparse);\n\n    /* If the representation is already the right one return ASAP. */\n    hdr = (struct hllhdr*) sparse;\n    if (hdr->encoding == HLL_DENSE) return C_OK;\n\n    /* Create a string of the right size filled with zero bytes.\n     * Note that the cached cardinality is set to 0 as a side effect\n     * that is exactly the cardinality of an empty HLL. */\n    dense = sdsnewlen(NULL,HLL_DENSE_SIZE);\n    hdr = (struct hllhdr*) dense;\n    *hdr = *oldhdr; /* This will copy the magic and cached cardinality. */\n    hdr->encoding = HLL_DENSE;\n\n    /* Now read the sparse representation and set non-zero registers\n     * accordingly. */\n    p += HLL_HDR_SIZE;\n    while(p < end) {\n        if (HLL_SPARSE_IS_ZERO(p)) {\n            runlen = HLL_SPARSE_ZERO_LEN(p);\n            idx += runlen;\n            p++;\n        } else if (HLL_SPARSE_IS_XZERO(p)) {\n            runlen = HLL_SPARSE_XZERO_LEN(p);\n            idx += runlen;\n            p += 2;\n        } else {\n            runlen = HLL_SPARSE_VAL_LEN(p);\n            regval = HLL_SPARSE_VAL_VALUE(p);\n            while(runlen--) {\n                HLL_DENSE_SET_REGISTER(hdr->registers,idx,regval);\n                idx++;\n            }\n            p++;\n        }\n    }\n\n    /* If the sparse representation was valid, we expect to find idx\n     * set to HLL_REGISTERS. */\n    if (idx != HLL_REGISTERS) {\n        sdsfree(dense);\n        return C_ERR;\n    }\n\n    /* Free the old representation and set the new one. */\n    sdsfree(o->ptr);\n    o->ptr = dense;\n    return C_OK;\n}\n\n/* \"Add\" the element in the sparse hyperloglog data structure.\n * Actually nothing is added, but the max 0 pattern counter of the subset\n * the element belongs to is incremented if needed.\n *\n * The object 'o' is the String object holding the HLL. The function requires\n * a reference to the object in order to be able to enlarge the string if\n * needed.\n *\n * On success, the function returns 1 if the cardinality changed, or 0\n * if the register for this element was not updated.\n * On error (if the representation is invalid) -1 is returned.\n *\n * As a side effect the function may promote the HLL representation from\n * sparse to dense: this happens when a register requires to be set to a value\n * not representable with the sparse representation, or when the resulting\n * size would be greater than server.hll_sparse_max_bytes. */\nint hllSparseAdd(robj *o, unsigned char *ele, size_t elesize) {\n    struct hllhdr *hdr;\n    uint8_t oldcount, count, *sparse, *end, *p, *prev, *next;\n    long index, first, span;\n    long is_zero = 0, is_xzero = 0, is_val = 0, runlen = 0;\n\n    /* Update the register if this element produced a longer run of zeroes. */\n    count = hllPatLen(ele,elesize,&index);\n\n    /* If the count is too big to be representable by the sparse representation\n     * switch to dense representation. */\n    if (count > HLL_SPARSE_VAL_MAX_VALUE) goto promote;\n\n    /* When updating a sparse representation, sometimes we may need to\n     * enlarge the buffer for up to 3 bytes in the worst case (XZERO split\n     * into XZERO-VAL-XZERO). Make sure there is enough space right now\n     * so that the pointers we take during the execution of the function\n     * will be valid all the time. */\n    o->ptr = sdsMakeRoomFor(o->ptr,3);\n\n    /* Step 1: we need to locate the opcode we need to modify to check\n     * if a value update is actually needed. */\n    sparse = p = ((uint8_t*)o->ptr) + HLL_HDR_SIZE;\n    end = p + sdslen(o->ptr) - HLL_HDR_SIZE;\n\n    first = 0;\n    prev = NULL; /* Points to previos opcode at the end of the loop. */\n    next = NULL; /* Points to the next opcode at the end of the loop. */\n    span = 0;\n    while(p < end) {\n        long oplen;\n\n        /* Set span to the number of registers covered by this opcode.\n         *\n         * This is the most performance critical loop of the sparse\n         * representation. Sorting the conditionals from the most to the\n         * least frequent opcode in many-bytes sparse HLLs is faster. */\n        oplen = 1;\n        if (HLL_SPARSE_IS_ZERO(p)) {\n            span = HLL_SPARSE_ZERO_LEN(p);\n        } else if (HLL_SPARSE_IS_VAL(p)) {\n            span = HLL_SPARSE_VAL_LEN(p);\n        } else { /* XZERO. */\n            span = HLL_SPARSE_XZERO_LEN(p);\n            oplen = 2;\n        }\n        /* Break if this opcode covers the register as 'index'. */\n        if (index <= first+span-1) break;\n        prev = p;\n        p += oplen;\n        first += span;\n    }\n    if (span == 0) return -1; /* Invalid format. */\n\n    next = HLL_SPARSE_IS_XZERO(p) ? p+2 : p+1;\n    if (next >= end) next = NULL;\n\n    /* Cache current opcode type to avoid using the macro again and\n     * again for something that will not change.\n     * Also cache the run-length of the opcode. */\n    if (HLL_SPARSE_IS_ZERO(p)) {\n        is_zero = 1;\n        runlen = HLL_SPARSE_ZERO_LEN(p);\n    } else if (HLL_SPARSE_IS_XZERO(p)) {\n        is_xzero = 1;\n        runlen = HLL_SPARSE_XZERO_LEN(p);\n    } else {\n        is_val = 1;\n        runlen = HLL_SPARSE_VAL_LEN(p);\n    }\n\n    /* Step 2: After the loop:\n     *\n     * 'first' stores to the index of the first register covered\n     *  by the current opcode, which is pointed by 'p'.\n     *\n     * 'next' ad 'prev' store respectively the next and previous opcode,\n     *  or NULL if the opcode at 'p' is respectively the last or first.\n     *\n     * 'span' is set to the number of registers covered by the current\n     *  opcode.\n     *\n     * There are different cases in order to update the data structure\n     * in place without generating it from scratch:\n     *\n     * A) If it is a VAL opcode already set to a value >= our 'count'\n     *    no update is needed, regardless of the VAL run-length field.\n     *    In this case PFADD returns 0 since no changes are performed.\n     *\n     * B) If it is a VAL opcode with len = 1 (representing only our\n     *    register) and the value is less than 'count', we just update it\n     *    since this is a trivial case. */\n    if (is_val) {\n        oldcount = HLL_SPARSE_VAL_VALUE(p);\n        /* Case A. */\n        if (oldcount >= count) return 0;\n\n        /* Case B. */\n        if (runlen == 1) {\n            HLL_SPARSE_VAL_SET(p,count,1);\n            goto updated;\n        }\n    }\n\n    /* C) Another trivial to handle case is a ZERO opcode with a len of 1.\n     * We can just replace it with a VAL opcode with our value and len of 1. */\n    if (is_zero && runlen == 1) {\n        HLL_SPARSE_VAL_SET(p,count,1);\n        goto updated;\n    }\n\n    /* D) General case.\n     *\n     * The other cases are more complex: our register requires to be updated\n     * and is either currently represented by a VAL opcode with len > 1,\n     * by a ZERO opcode with len > 1, or by an XZERO opcode.\n     *\n     * In those cases the original opcode must be split into muliple\n     * opcodes. The worst case is an XZERO split in the middle resuling into\n     * XZERO - VAL - XZERO, so the resulting sequence max length is\n     * 5 bytes.\n     *\n     * We perform the split writing the new sequence into the 'new' buffer\n     * with 'newlen' as length. Later the new sequence is inserted in place\n     * of the old one, possibly moving what is on the right a few bytes\n     * if the new sequence is longer than the older one. */\n    uint8_t seq[5], *n = seq;\n    int last = first+span-1; /* Last register covered by the sequence. */\n    int len;\n\n    if (is_zero || is_xzero) {\n        /* Handle splitting of ZERO / XZERO. */\n        if (index != first) {\n            len = index-first;\n            if (len > HLL_SPARSE_ZERO_MAX_LEN) {\n                HLL_SPARSE_XZERO_SET(n,len);\n                n += 2;\n            } else {\n                HLL_SPARSE_ZERO_SET(n,len);\n                n++;\n            }\n        }\n        HLL_SPARSE_VAL_SET(n,count,1);\n        n++;\n        if (index != last) {\n            len = last-index;\n            if (len > HLL_SPARSE_ZERO_MAX_LEN) {\n                HLL_SPARSE_XZERO_SET(n,len);\n                n += 2;\n            } else {\n                HLL_SPARSE_ZERO_SET(n,len);\n                n++;\n            }\n        }\n    } else {\n        /* Handle splitting of VAL. */\n        int curval = HLL_SPARSE_VAL_VALUE(p);\n\n        if (index != first) {\n            len = index-first;\n            HLL_SPARSE_VAL_SET(n,curval,len);\n            n++;\n        }\n        HLL_SPARSE_VAL_SET(n,count,1);\n        n++;\n        if (index != last) {\n            len = last-index;\n            HLL_SPARSE_VAL_SET(n,curval,len);\n            n++;\n        }\n    }\n\n    /* Step 3: substitute the new sequence with the old one.\n     *\n     * Note that we already allocated space on the sds string\n     * calling sdsMakeRoomFor(). */\n     int seqlen = n-seq;\n     int oldlen = is_xzero ? 2 : 1;\n     int deltalen = seqlen-oldlen;\n\n     if (deltalen > 0 &&\n         sdslen(o->ptr)+deltalen > server.hll_sparse_max_bytes) goto promote;\n     if (deltalen && next) memmove(next+deltalen,next,end-next);\n     sdsIncrLen(o->ptr,deltalen);\n     memcpy(p,seq,seqlen);\n     end += deltalen;\n\nupdated:\n    /* Step 4: Merge adjacent values if possible.\n     *\n     * The representation was updated, however the resulting representation\n     * may not be optimal: adjacent VAL opcodes can sometimes be merged into\n     * a single one. */\n    p = prev ? prev : sparse;\n    int scanlen = 5; /* Scan up to 5 upcodes starting from prev. */\n    while (p < end && scanlen--) {\n        if (HLL_SPARSE_IS_XZERO(p)) {\n            p += 2;\n            continue;\n        } else if (HLL_SPARSE_IS_ZERO(p)) {\n            p++;\n            continue;\n        }\n        /* We need two adjacent VAL opcodes to try a merge, having\n         * the same value, and a len that fits the VAL opcode max len. */\n        if (p+1 < end && HLL_SPARSE_IS_VAL(p+1)) {\n            int v1 = HLL_SPARSE_VAL_VALUE(p);\n            int v2 = HLL_SPARSE_VAL_VALUE(p+1);\n            if (v1 == v2) {\n                int len = HLL_SPARSE_VAL_LEN(p)+HLL_SPARSE_VAL_LEN(p+1);\n                if (len <= HLL_SPARSE_VAL_MAX_LEN) {\n                    HLL_SPARSE_VAL_SET(p+1,v1,len);\n                    memmove(p,p+1,end-p);\n                    sdsIncrLen(o->ptr,-1);\n                    end--;\n                    /* After a merge we reiterate without incrementing 'p'\n                     * in order to try to merge the just merged value with\n                     * a value on its right. */\n                    continue;\n                }\n            }\n        }\n        p++;\n    }\n\n    /* Invalidate the cached cardinality. */\n    hdr = o->ptr;\n    HLL_INVALIDATE_CACHE(hdr);\n    return 1;\n\npromote: /* Promote to dense representation. */\n    if (hllSparseToDense(o) == C_ERR) return -1; /* Corrupted HLL. */\n    hdr = o->ptr;\n\n    /* We need to call hllDenseAdd() to perform the operation after the\n     * conversion. However the result must be 1, since if we need to\n     * convert from sparse to dense a register requires to be updated.\n     *\n     * Note that this in turn means that PFADD will make sure the command\n     * is propagated to slaves / AOF, so if there is a sparse -> dense\n     * convertion, it will be performed in all the slaves as well. */\n    int dense_retval = hllDenseAdd(hdr->registers, ele, elesize);\n    serverAssert(dense_retval == 1);\n    return dense_retval;\n}\n\n/* Compute SUM(2^-reg) in the sparse representation.\n * PE is an array with a pre-computer table of values 2^-reg indexed by reg.\n * As a side effect the integer pointed by 'ezp' is set to the number\n * of zero registers. */\ndouble hllSparseSum(uint8_t *sparse, int sparselen, double *PE, int *ezp, int *invalid) {\n    double E = 0;\n    int ez = 0, idx = 0, runlen, regval;\n    uint8_t *end = sparse+sparselen, *p = sparse;\n\n    while(p < end) {\n        if (HLL_SPARSE_IS_ZERO(p)) {\n            runlen = HLL_SPARSE_ZERO_LEN(p);\n            idx += runlen;\n            ez += runlen;\n            /* Increment E at the end of the loop. */\n            p++;\n        } else if (HLL_SPARSE_IS_XZERO(p)) {\n            runlen = HLL_SPARSE_XZERO_LEN(p);\n            idx += runlen;\n            ez += runlen;\n            /* Increment E at the end of the loop. */\n            p += 2;\n        } else {\n            runlen = HLL_SPARSE_VAL_LEN(p);\n            regval = HLL_SPARSE_VAL_VALUE(p);\n            idx += runlen;\n            E += PE[regval]*runlen;\n            p++;\n        }\n    }\n    if (idx != HLL_REGISTERS && invalid) *invalid = 1;\n    E += ez; /* Add 2^0 'ez' times. */\n    *ezp = ez;\n    return E;\n}\n\n/* ========================= HyperLogLog Count ==============================\n * This is the core of the algorithm where the approximated count is computed.\n * The function uses the lower level hllDenseSum() and hllSparseSum() functions\n * as helpers to compute the SUM(2^-reg) part of the computation, which is\n * representation-specific, while all the rest is common. */\n\n/* Implements the SUM operation for uint8_t data type which is only used\n * internally as speedup for PFCOUNT with multiple keys. */\ndouble hllRawSum(uint8_t *registers, double *PE, int *ezp) {\n    double E = 0;\n    int j, ez = 0;\n    uint64_t *word = (uint64_t*) registers;\n    uint8_t *bytes;\n\n    for (j = 0; j < HLL_REGISTERS/8; j++) {\n        if (*word == 0) {\n            ez += 8;\n        } else {\n            bytes = (uint8_t*) word;\n            if (bytes[0]) E += PE[bytes[0]]; else ez++;\n            if (bytes[1]) E += PE[bytes[1]]; else ez++;\n            if (bytes[2]) E += PE[bytes[2]]; else ez++;\n            if (bytes[3]) E += PE[bytes[3]]; else ez++;\n            if (bytes[4]) E += PE[bytes[4]]; else ez++;\n            if (bytes[5]) E += PE[bytes[5]]; else ez++;\n            if (bytes[6]) E += PE[bytes[6]]; else ez++;\n            if (bytes[7]) E += PE[bytes[7]]; else ez++;\n        }\n        word++;\n    }\n    E += ez; /* 2^(-reg[j]) is 1 when m is 0, add it 'ez' times for every\n                zero register in the HLL. */\n    *ezp = ez;\n    return E;\n}\n\n/* Return the approximated cardinality of the set based on the harmonic\n * mean of the registers values. 'hdr' points to the start of the SDS\n * representing the String object holding the HLL representation.\n *\n * If the sparse representation of the HLL object is not valid, the integer\n * pointed by 'invalid' is set to non-zero, otherwise it is left untouched.\n *\n * hllCount() supports a special internal-only encoding of HLL_RAW, that\n * is, hdr->registers will point to an uint8_t array of HLL_REGISTERS element.\n * This is useful in order to speedup PFCOUNT when called against multiple\n * keys (no need to work with 6-bit integers encoding). */\nuint64_t hllCount(struct hllhdr *hdr, int *invalid) {\n    double m = HLL_REGISTERS;\n    double E, alpha = 0.7213/(1+1.079/m);\n    int j, ez; /* Number of registers equal to 0. */\n\n    /* We precompute 2^(-reg[j]) in a small table in order to\n     * speedup the computation of SUM(2^-register[0..i]). */\n    static int initialized = 0;\n    static double PE[64];\n    if (!initialized) {\n        PE[0] = 1; /* 2^(-reg[j]) is 1 when m is 0. */\n        for (j = 1; j < 64; j++) {\n            /* 2^(-reg[j]) is the same as 1/2^reg[j]. */\n            PE[j] = 1.0/(1ULL << j);\n        }\n        initialized = 1;\n    }\n\n    /* Compute SUM(2^-register[0..i]). */\n    if (hdr->encoding == HLL_DENSE) {\n        E = hllDenseSum(hdr->registers,PE,&ez);\n    } else if (hdr->encoding == HLL_SPARSE) {\n        E = hllSparseSum(hdr->registers,\n                         sdslen((sds)hdr)-HLL_HDR_SIZE,PE,&ez,invalid);\n    } else if (hdr->encoding == HLL_RAW) {\n        E = hllRawSum(hdr->registers,PE,&ez);\n    } else {\n        serverPanic(\"Unknown HyperLogLog encoding in hllCount()\");\n    }\n\n    /* Muliply the inverse of E for alpha_m * m^2 to have the raw estimate. */\n    E = (1/E)*alpha*m*m;\n\n    /* Use the LINEARCOUNTING algorithm for small cardinalities.\n     * For larger values but up to 72000 HyperLogLog raw approximation is\n     * used since linear counting error starts to increase. However HyperLogLog\n     * shows a strong bias in the range 2.5*16384 - 72000, so we try to\n     * compensate for it. */\n    if (E < m*2.5 && ez != 0) {\n        E = m*log(m/ez); /* LINEARCOUNTING() */\n    } else if (m == 16384 && E < 72000) {\n        /* We did polynomial regression of the bias for this range, this\n         * way we can compute the bias for a given cardinality and correct\n         * according to it. Only apply the correction for P=14 that's what\n         * we use and the value the correction was verified with. */\n        double bias = 5.9119*1.0e-18*(E*E*E*E)\n                      -1.4253*1.0e-12*(E*E*E)+\n                      1.2940*1.0e-7*(E*E)\n                      -5.2921*1.0e-3*E+\n                      83.3216;\n        E -= E*(bias/100);\n    }\n    /* We don't apply the correction for E > 1/30 of 2^32 since we use\n     * a 64 bit function and 6 bit counters. To apply the correction for\n     * 1/30 of 2^64 is not needed since it would require a huge set\n     * to approach such a value. */\n    return (uint64_t) E;\n}\n\n/* Call hllDenseAdd() or hllSparseAdd() according to the HLL encoding. */\nint hllAdd(robj *o, unsigned char *ele, size_t elesize) {\n    struct hllhdr *hdr = o->ptr;\n    switch(hdr->encoding) {\n    case HLL_DENSE: return hllDenseAdd(hdr->registers,ele,elesize);\n    case HLL_SPARSE: return hllSparseAdd(o,ele,elesize);\n    default: return -1; /* Invalid representation. */\n    }\n}\n\n/* Merge by computing MAX(registers[i],hll[i]) the HyperLogLog 'hll'\n * with an array of uint8_t HLL_REGISTERS registers pointed by 'max'.\n *\n * The hll object must be already validated via isHLLObjectOrReply()\n * or in some other way.\n *\n * If the HyperLogLog is sparse and is found to be invalid, C_ERR\n * is returned, otherwise the function always succeeds. */\nint hllMerge(uint8_t *max, robj *hll) {\n    struct hllhdr *hdr = hll->ptr;\n    int i;\n\n    if (hdr->encoding == HLL_DENSE) {\n        uint8_t val;\n\n        for (i = 0; i < HLL_REGISTERS; i++) {\n            HLL_DENSE_GET_REGISTER(val,hdr->registers,i);\n            if (val > max[i]) max[i] = val;\n        }\n    } else {\n        uint8_t *p = hll->ptr, *end = p + sdslen(hll->ptr);\n        long runlen, regval;\n\n        p += HLL_HDR_SIZE;\n        i = 0;\n        while(p < end) {\n            if (HLL_SPARSE_IS_ZERO(p)) {\n                runlen = HLL_SPARSE_ZERO_LEN(p);\n                i += runlen;\n                p++;\n            } else if (HLL_SPARSE_IS_XZERO(p)) {\n                runlen = HLL_SPARSE_XZERO_LEN(p);\n                i += runlen;\n                p += 2;\n            } else {\n                runlen = HLL_SPARSE_VAL_LEN(p);\n                regval = HLL_SPARSE_VAL_VALUE(p);\n                while(runlen--) {\n                    if (regval > max[i]) max[i] = regval;\n                    i++;\n                }\n                p++;\n            }\n        }\n        if (i != HLL_REGISTERS) return C_ERR;\n    }\n    return C_OK;\n}\n\n/* ========================== HyperLogLog commands ========================== */\n\n/* Create an HLL object. We always create the HLL using sparse encoding.\n * This will be upgraded to the dense representation as needed. */\nrobj *createHLLObject(void) {\n    robj *o;\n    struct hllhdr *hdr;\n    sds s;\n    uint8_t *p;\n    int sparselen = HLL_HDR_SIZE +\n                    (((HLL_REGISTERS+(HLL_SPARSE_XZERO_MAX_LEN-1)) /\n                     HLL_SPARSE_XZERO_MAX_LEN)*2);\n    int aux;\n\n    /* Populate the sparse representation with as many XZERO opcodes as\n     * needed to represent all the registers. */\n    aux = HLL_REGISTERS;\n    s = sdsnewlen(NULL,sparselen);\n    p = (uint8_t*)s + HLL_HDR_SIZE;\n    while(aux) {\n        int xzero = HLL_SPARSE_XZERO_MAX_LEN;\n        if (xzero > aux) xzero = aux;\n        HLL_SPARSE_XZERO_SET(p,xzero);\n        p += 2;\n        aux -= xzero;\n    }\n    serverAssert((p-(uint8_t*)s) == sparselen);\n\n    /* Create the actual object. */\n    o = createObject(OBJ_STRING,s);\n    hdr = o->ptr;\n    memcpy(hdr->magic,\"HYLL\",4);\n    hdr->encoding = HLL_SPARSE;\n    return o;\n}\n\n/* Check if the object is a String with a valid HLL representation.\n * Return C_OK if this is true, otherwise reply to the client\n * with an error and return C_ERR. */\nint isHLLObjectOrReply(client *c, robj *o) {\n    struct hllhdr *hdr;\n\n    /* Key exists, check type */\n    if (checkType(c,o,OBJ_STRING))\n        return C_ERR; /* Error already sent. */\n\n    if (stringObjectLen(o) < sizeof(*hdr)) goto invalid;\n    hdr = o->ptr;\n\n    /* Magic should be \"HYLL\". */\n    if (hdr->magic[0] != 'H' || hdr->magic[1] != 'Y' ||\n        hdr->magic[2] != 'L' || hdr->magic[3] != 'L') goto invalid;\n\n    if (hdr->encoding > HLL_MAX_ENCODING) goto invalid;\n\n    /* Dense representation string length should match exactly. */\n    if (hdr->encoding == HLL_DENSE &&\n        stringObjectLen(o) != HLL_DENSE_SIZE) goto invalid;\n\n    /* All tests passed. */\n    return C_OK;\n\ninvalid:\n    addReplySds(c,\n        sdsnew(\"-WRONGTYPE Key is not a valid \"\n               \"HyperLogLog string value.\\r\\n\"));\n    return C_ERR;\n}\n\n/* PFADD var ele ele ele ... ele => :0 or :1 */\nvoid pfaddCommand(client *c) {\n    robj *o = lookupKeyWrite(c->db,c->argv[1]);\n    struct hllhdr *hdr;\n    int updated = 0, j;\n\n    if (o == NULL) {\n        /* Create the key with a string value of the exact length to\n         * hold our HLL data structure. sdsnewlen() when NULL is passed\n         * is guaranteed to return bytes initialized to zero. */\n        o = createHLLObject();\n        dbAdd(c->db,c->argv[1],o);\n        updated++;\n    } else {\n        if (isHLLObjectOrReply(c,o) != C_OK) return;\n        o = dbUnshareStringValue(c->db,c->argv[1],o);\n    }\n    /* Perform the low level ADD operation for every element. */\n    for (j = 2; j < c->argc; j++) {\n        int retval = hllAdd(o, (unsigned char*)c->argv[j]->ptr,\n                               sdslen(c->argv[j]->ptr));\n        switch(retval) {\n        case 1:\n            updated++;\n            break;\n        case -1:\n            addReplySds(c,sdsnew(invalid_hll_err));\n            return;\n        }\n    }\n    hdr = o->ptr;\n    if (updated) {\n        signalModifiedKey(c->db,c->argv[1]);\n        notifyKeyspaceEvent(NOTIFY_STRING,\"pfadd\",c->argv[1],c->db->id);\n        server.dirty++;\n        HLL_INVALIDATE_CACHE(hdr);\n    }\n    addReply(c, updated ? shared.cone : shared.czero);\n}\n\n/* PFCOUNT var -> approximated cardinality of set. */\nvoid pfcountCommand(client *c) {\n    robj *o;\n    struct hllhdr *hdr;\n    uint64_t card;\n\n    /* Case 1: multi-key keys, cardinality of the union.\n     *\n     * When multiple keys are specified, PFCOUNT actually computes\n     * the cardinality of the merge of the N HLLs specified. */\n    if (c->argc > 2) {\n        uint8_t max[HLL_HDR_SIZE+HLL_REGISTERS], *registers;\n        int j;\n\n        /* Compute an HLL with M[i] = MAX(M[i]_j). */\n        memset(max,0,sizeof(max));\n        hdr = (struct hllhdr*) max;\n        hdr->encoding = HLL_RAW; /* Special internal-only encoding. */\n        registers = max + HLL_HDR_SIZE;\n        for (j = 1; j < c->argc; j++) {\n            /* Check type and size. */\n            robj *o = lookupKeyRead(c->db,c->argv[j]);\n            if (o == NULL) continue; /* Assume empty HLL for non existing var.*/\n            if (isHLLObjectOrReply(c,o) != C_OK) return;\n\n            /* Merge with this HLL with our 'max' HHL by setting max[i]\n             * to MAX(max[i],hll[i]). */\n            if (hllMerge(registers,o) == C_ERR) {\n                addReplySds(c,sdsnew(invalid_hll_err));\n                return;\n            }\n        }\n\n        /* Compute cardinality of the resulting set. */\n        addReplyLongLong(c,hllCount(hdr,NULL));\n        return;\n    }\n\n    /* Case 2: cardinality of the single HLL.\n     *\n     * The user specified a single key. Either return the cached value\n     * or compute one and update the cache. */\n    o = lookupKeyWrite(c->db,c->argv[1]);\n    if (o == NULL) {\n        /* No key? Cardinality is zero since no element was added, otherwise\n         * we would have a key as HLLADD creates it as a side effect. */\n        addReply(c,shared.czero);\n    } else {\n        if (isHLLObjectOrReply(c,o) != C_OK) return;\n        o = dbUnshareStringValue(c->db,c->argv[1],o);\n\n        /* Check if the cached cardinality is valid. */\n        hdr = o->ptr;\n        if (HLL_VALID_CACHE(hdr)) {\n            /* Just return the cached value. */\n            card = (uint64_t)hdr->card[0];\n            card |= (uint64_t)hdr->card[1] << 8;\n            card |= (uint64_t)hdr->card[2] << 16;\n            card |= (uint64_t)hdr->card[3] << 24;\n            card |= (uint64_t)hdr->card[4] << 32;\n            card |= (uint64_t)hdr->card[5] << 40;\n            card |= (uint64_t)hdr->card[6] << 48;\n            card |= (uint64_t)hdr->card[7] << 56;\n        } else {\n            int invalid = 0;\n            /* Recompute it and update the cached value. */\n            card = hllCount(hdr,&invalid);\n            if (invalid) {\n                addReplySds(c,sdsnew(invalid_hll_err));\n                return;\n            }\n            hdr->card[0] = card & 0xff;\n            hdr->card[1] = (card >> 8) & 0xff;\n            hdr->card[2] = (card >> 16) & 0xff;\n            hdr->card[3] = (card >> 24) & 0xff;\n            hdr->card[4] = (card >> 32) & 0xff;\n            hdr->card[5] = (card >> 40) & 0xff;\n            hdr->card[6] = (card >> 48) & 0xff;\n            hdr->card[7] = (card >> 56) & 0xff;\n            /* This is not considered a read-only command even if the\n             * data structure is not modified, since the cached value\n             * may be modified and given that the HLL is a Redis string\n             * we need to propagate the change. */\n            signalModifiedKey(c->db,c->argv[1]);\n            server.dirty++;\n        }\n        addReplyLongLong(c,card);\n    }\n}\n\n/* PFMERGE dest src1 src2 src3 ... srcN => OK */\nvoid pfmergeCommand(client *c) {\n    uint8_t max[HLL_REGISTERS];\n    struct hllhdr *hdr;\n    int j;\n\n    /* Compute an HLL with M[i] = MAX(M[i]_j).\n     * We we the maximum into the max array of registers. We'll write\n     * it to the target variable later. */\n    memset(max,0,sizeof(max));\n    for (j = 1; j < c->argc; j++) {\n        /* Check type and size. */\n        robj *o = lookupKeyRead(c->db,c->argv[j]);\n        if (o == NULL) continue; /* Assume empty HLL for non existing var. */\n        if (isHLLObjectOrReply(c,o) != C_OK) return;\n\n        /* Merge with this HLL with our 'max' HHL by setting max[i]\n         * to MAX(max[i],hll[i]). */\n        if (hllMerge(max,o) == C_ERR) {\n            addReplySds(c,sdsnew(invalid_hll_err));\n            return;\n        }\n    }\n\n    /* Create / unshare the destination key's value if needed. */\n    robj *o = lookupKeyWrite(c->db,c->argv[1]);\n    if (o == NULL) {\n        /* Create the key with a string value of the exact length to\n         * hold our HLL data structure. sdsnewlen() when NULL is passed\n         * is guaranteed to return bytes initialized to zero. */\n        o = createHLLObject();\n        dbAdd(c->db,c->argv[1],o);\n    } else {\n        /* If key exists we are sure it's of the right type/size\n         * since we checked when merging the different HLLs, so we\n         * don't check again. */\n        o = dbUnshareStringValue(c->db,c->argv[1],o);\n    }\n\n    /* Only support dense objects as destination. */\n    if (hllSparseToDense(o) == C_ERR) {\n        addReplySds(c,sdsnew(invalid_hll_err));\n        return;\n    }\n\n    /* Write the resulting HLL to the destination HLL registers and\n     * invalidate the cached value. */\n    hdr = o->ptr;\n    for (j = 0; j < HLL_REGISTERS; j++) {\n        HLL_DENSE_SET_REGISTER(hdr->registers,j,max[j]);\n    }\n    HLL_INVALIDATE_CACHE(hdr);\n\n    signalModifiedKey(c->db,c->argv[1]);\n    /* We generate an PFADD event for PFMERGE for semantical simplicity\n     * since in theory this is a mass-add of elements. */\n    notifyKeyspaceEvent(NOTIFY_STRING,\"pfadd\",c->argv[1],c->db->id);\n    server.dirty++;\n    addReply(c,shared.ok);\n}\n\n/* ========================== Testing / Debugging  ========================== */\n\n/* PFSELFTEST\n * This command performs a self-test of the HLL registers implementation.\n * Something that is not easy to test from within the outside. */\n#define HLL_TEST_CYCLES 1000\nvoid pfselftestCommand(client *c) {\n    unsigned int j, i;\n    sds bitcounters = sdsnewlen(NULL,HLL_DENSE_SIZE);\n    struct hllhdr *hdr = (struct hllhdr*) bitcounters, *hdr2;\n    robj *o = NULL;\n    uint8_t bytecounters[HLL_REGISTERS];\n\n    /* Test 1: access registers.\n     * The test is conceived to test that the different counters of our data\n     * structure are accessible and that setting their values both result in\n     * the correct value to be retained and not affect adjacent values. */\n    for (j = 0; j < HLL_TEST_CYCLES; j++) {\n        /* Set the HLL counters and an array of unsigned byes of the\n         * same size to the same set of random values. */\n        for (i = 0; i < HLL_REGISTERS; i++) {\n            unsigned int r = rand() & HLL_REGISTER_MAX;\n\n            bytecounters[i] = r;\n            HLL_DENSE_SET_REGISTER(hdr->registers,i,r);\n        }\n        /* Check that we are able to retrieve the same values. */\n        for (i = 0; i < HLL_REGISTERS; i++) {\n            unsigned int val;\n\n            HLL_DENSE_GET_REGISTER(val,hdr->registers,i);\n            if (val != bytecounters[i]) {\n                addReplyErrorFormat(c,\n                    \"TESTFAILED Register %d should be %d but is %d\",\n                    i, (int) bytecounters[i], (int) val);\n                goto cleanup;\n            }\n        }\n    }\n\n    /* Test 2: approximation error.\n     * The test adds unique elements and check that the estimated value\n     * is always reasonable bounds.\n     *\n     * We check that the error is smaller than a few times than the expected\n     * standard error, to make it very unlikely for the test to fail because\n     * of a \"bad\" run.\n     *\n     * The test is performed with both dense and sparse HLLs at the same\n     * time also verifying that the computed cardinality is the same. */\n    memset(hdr->registers,0,HLL_DENSE_SIZE-HLL_HDR_SIZE);\n    o = createHLLObject();\n    double relerr = 1.04/sqrt(HLL_REGISTERS);\n    int64_t checkpoint = 1;\n    uint64_t seed = (uint64_t)rand() | (uint64_t)rand() << 32;\n    uint64_t ele;\n    for (j = 1; j <= 10000000; j++) {\n        ele = j ^ seed;\n        hllDenseAdd(hdr->registers,(unsigned char*)&ele,sizeof(ele));\n        hllAdd(o,(unsigned char*)&ele,sizeof(ele));\n\n        /* Make sure that for small cardinalities we use sparse\n         * encoding. */\n        if (j == checkpoint && j < server.hll_sparse_max_bytes/2) {\n            hdr2 = o->ptr;\n            if (hdr2->encoding != HLL_SPARSE) {\n                addReplyError(c, \"TESTFAILED sparse encoding not used\");\n                goto cleanup;\n            }\n        }\n\n        /* Check that dense and sparse representations agree. */\n        if (j == checkpoint && hllCount(hdr,NULL) != hllCount(o->ptr,NULL)) {\n                addReplyError(c, \"TESTFAILED dense/sparse disagree\");\n                goto cleanup;\n        }\n\n        /* Check error. */\n        if (j == checkpoint) {\n            int64_t abserr = checkpoint - (int64_t)hllCount(hdr,NULL);\n            uint64_t maxerr = ceil(relerr*6*checkpoint);\n\n            /* Adjust the max error we expect for cardinality 10\n             * since from time to time it is statistically likely to get\n             * much higher error due to collision, resulting into a false\n             * positive. */\n            if (j == 10) maxerr = 1;\n\n            if (abserr < 0) abserr = -abserr;\n            if (abserr > (int64_t)maxerr) {\n                addReplyErrorFormat(c,\n                    \"TESTFAILED Too big error. card:%llu abserr:%llu\",\n                    (unsigned long long) checkpoint,\n                    (unsigned long long) abserr);\n                goto cleanup;\n            }\n            checkpoint *= 10;\n        }\n    }\n\n    /* Success! */\n    addReply(c,shared.ok);\n\ncleanup:\n    sdsfree(bitcounters);\n    if (o) decrRefCount(o);\n}\n\n/* PFDEBUG <subcommand> <key> ... args ...\n * Different debugging related operations about the HLL implementation. */\nvoid pfdebugCommand(client *c) {\n    char *cmd = c->argv[1]->ptr;\n    struct hllhdr *hdr;\n    robj *o;\n    int j;\n\n    o = lookupKeyWrite(c->db,c->argv[2]);\n    if (o == NULL) {\n        addReplyError(c,\"The specified key does not exist\");\n        return;\n    }\n    if (isHLLObjectOrReply(c,o) != C_OK) return;\n    o = dbUnshareStringValue(c->db,c->argv[2],o);\n    hdr = o->ptr;\n\n    /* PFDEBUG GETREG <key> */\n    if (!strcasecmp(cmd,\"getreg\")) {\n        if (c->argc != 3) goto arityerr;\n\n        if (hdr->encoding == HLL_SPARSE) {\n            if (hllSparseToDense(o) == C_ERR) {\n                addReplySds(c,sdsnew(invalid_hll_err));\n                return;\n            }\n            server.dirty++; /* Force propagation on encoding change. */\n        }\n\n        hdr = o->ptr;\n        addReplyMultiBulkLen(c,HLL_REGISTERS);\n        for (j = 0; j < HLL_REGISTERS; j++) {\n            uint8_t val;\n\n            HLL_DENSE_GET_REGISTER(val,hdr->registers,j);\n            addReplyLongLong(c,val);\n        }\n    }\n    /* PFDEBUG DECODE <key> */\n    else if (!strcasecmp(cmd,\"decode\")) {\n        if (c->argc != 3) goto arityerr;\n\n        uint8_t *p = o->ptr, *end = p+sdslen(o->ptr);\n        sds decoded = sdsempty();\n\n        if (hdr->encoding != HLL_SPARSE) {\n            addReplyError(c,\"HLL encoding is not sparse\");\n            return;\n        }\n\n        p += HLL_HDR_SIZE;\n        while(p < end) {\n            int runlen, regval;\n\n            if (HLL_SPARSE_IS_ZERO(p)) {\n                runlen = HLL_SPARSE_ZERO_LEN(p);\n                p++;\n                decoded = sdscatprintf(decoded,\"z:%d \",runlen);\n            } else if (HLL_SPARSE_IS_XZERO(p)) {\n                runlen = HLL_SPARSE_XZERO_LEN(p);\n                p += 2;\n                decoded = sdscatprintf(decoded,\"Z:%d \",runlen);\n            } else {\n                runlen = HLL_SPARSE_VAL_LEN(p);\n                regval = HLL_SPARSE_VAL_VALUE(p);\n                p++;\n                decoded = sdscatprintf(decoded,\"v:%d,%d \",regval,runlen);\n            }\n        }\n        decoded = sdstrim(decoded,\" \");\n        addReplyBulkCBuffer(c,decoded,sdslen(decoded));\n        sdsfree(decoded);\n    }\n    /* PFDEBUG ENCODING <key> */\n    else if (!strcasecmp(cmd,\"encoding\")) {\n        char *encodingstr[2] = {\"dense\",\"sparse\"};\n        if (c->argc != 3) goto arityerr;\n\n        addReplyStatus(c,encodingstr[hdr->encoding]);\n    }\n    /* PFDEBUG TODENSE <key> */\n    else if (!strcasecmp(cmd,\"todense\")) {\n        int conv = 0;\n        if (c->argc != 3) goto arityerr;\n\n        if (hdr->encoding == HLL_SPARSE) {\n            if (hllSparseToDense(o) == C_ERR) {\n                addReplySds(c,sdsnew(invalid_hll_err));\n                return;\n            }\n            conv = 1;\n            server.dirty++; /* Force propagation on encoding change. */\n        }\n        addReply(c,conv ? shared.cone : shared.czero);\n    } else {\n        addReplyErrorFormat(c,\"Unknown PFDEBUG subcommand '%s'\", cmd);\n    }\n    return;\n\narityerr:\n    addReplyErrorFormat(c,\n        \"Wrong number of arguments for the '%s' subcommand\",cmd);\n}\n\n"
  },
  {
    "path": "extern/redis-3.2.11/deps/jemalloc/config.stamp.in",
    "content": ""
  },
  {
    "path": "vendor/github.com/spinlock/jemalloc-go/jemalloc-4.4.0/config.stamp.in",
    "content": ""
  }
]